pax_global_header00006660000000000000000000000064152657313250014523gustar00rootroot0000000000000052 comment=e7ca37fbf066162cece0ecf43d4ddc6ca1eb195d heldercorreia-speedcrunch-e7ca37f/000077500000000000000000000000001526573132500173355ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/.gitattributes000066400000000000000000000002721526573132500222310ustar00rootroot00000000000000# All the shell scripts in that directory will be run in a Linux environment, # even when checking out on Windows, so they need their Unix line endings. pkg/cross-linux/*.sh text eol=lf heldercorreia-speedcrunch-e7ca37f/.gitignore000066400000000000000000000002731526573132500213270ustar00rootroot00000000000000CMakeLists.txt.user /.idea cmake-build-debug build/ /build-*/ src/build*/ **/.DS_Store doc/src/_build-*/.doctrees/ doc/build_html_embedded/*/.doctrees/ src/resources/locale/*.qm Testing/ heldercorreia-speedcrunch-e7ca37f/BUILDING.md000066400000000000000000000724761526573132500210740ustar00rootroot00000000000000# Building SpeedCrunch SpeedCrunch uses CMake as its build system. Set the release version in `project(speedcrunch VERSION ...)` in the root `CMakeLists.txt`. This is the only version value to edit for a new release. CMake uses it for the application, macOS bundle, packages, and license notices. It also generates the Windows version resource in the build directory. Changing the version or its resource template refreshes the generated file on the next build. Unchanged files are not rewritten. The manual reads the same version directly from CMake when Sphinx runs, so it can still be built separately. Application builds use the prebuilt manual and do not regenerate documentation. Published download links and historical `versionadded` entries stay tied to their respective releases. ## Requirements To build SpeedCrunch, you need: - A compiler toolchain with C17 and C++17 support - [Qt](https://www.qt.io/) 6.4 or later (Core, Widgets, Help, Network, LinguistTools) - [CMake](https://cmake.org/) 3.16 or later Qt LinguistTools provides `lupdate` and `lrelease`. CMake uses `lrelease` to compile the TS sources in `src/resources/locale` into QM files in the build directory and embeds them in the application. The generated QM files do not need to be installed separately or kept in Git. Changes to a TS file take effect on the next build. ## Getting the source The source code is maintained on [GitHub](https://github.com/heldercorreia/speedcrunch). To clone the repository: git clone https://github.com/heldercorreia/speedcrunch.git cd speedcrunch ## Build and install The default build is intended for third-party package providers. In a fresh build directory, no feature or build-variant toggles are needed. Update checks, test executables, startup recording, portable mode, and license installation are all disabled by default. This lets providers use their usual packaging workflow and deliver updates through their own channels. To build SpeedCrunch in a dedicated build directory and install it, run the following commands from the root of the source directory: cmake -S . -B build cmake --build build --config Release --parallel cmake --install build --config Release ## Build configurations With Makefiles or ordinary Ninja, the project defaults to Release. Select another configuration when configuring, for example with `-DCMAKE_BUILD_TYPE=Debug`. The `--config Release` option above selects the configuration for generators that support several configurations in one build directory, such as Xcode, Visual Studio, and Ninja Multi-Config. It has no effect with Makefiles or ordinary Ninja. Stripping is disabled by default on every platform, including ordinary `Release` builds. Both official release variants force `STRIP_BINARY=ON`, so the official Windows installer and ZIP, and macOS DMG and ZIP, contain application binaries without debug symbols. You can also enable stripping explicitly with `-DSTRIP_BINARY=ON`. The option controls stripping directly, regardless of the selected configuration. The developer Debug variant leaves it unchanged. When enabled, the native macOS strip tool runs after linking and before deployment and final bundle signing. GNU-style toolchains strip during linking. MSVC links without debug information or a PDB. This applies to the executable in the build directory, so installed copies and packages also receive the stripped binary. Test executables are unaffected. Package providers should leave stripping disabled so their packaging tools can extract debug information before stripping the installed binaries. SpeedCrunch keeps the compiler flags supplied by the toolchain or package provider. Disabling stripping preserves generated symbols but does not enable debug information by itself. If you turn off an official variant in an existing build directory, also set `-DSTRIP_BINARY=OFF` to reset its cached value. With Makefiles or ordinary Ninja, application and test executables are placed directly under the chosen build directory. The application is `build/speedcrunch` on Linux or `build/SpeedCrunch.app` on macOS. Multi-configuration generators add a configuration subdirectory, such as `build/Release`. To keep separate Release and Debug builds with Makefiles or ordinary Ninja, choose a build directory for each configuration: cmake -S . -B build/Release -DCMAKE_BUILD_TYPE=Release cmake --build build/Release --parallel cmake -S . -B build/Debug -DCMAKE_BUILD_TYPE=Debug cmake --build build/Debug --parallel These build output locations do not change the installation directories. Use a fresh build directory if an existing one was configured before the root CMake entry point was added. CMake saves the source directory in its cache. ### Build variants Build variants apply a fixed group of settings. All three default to `OFF`. Enable one when configuring, for example: cmake -S . -B build-official -DBUILD_VARIANT_OFFICIAL_RELEASE=ON cmake --build build-official --config Release --parallel cmake -S . -B build-portable -DBUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE=ON cmake --build build-portable --config Release --parallel cmake -S . -B build-debug -DBUILD_VARIANT_DEV_DEBUG=ON cmake --build build-debug --config Debug --parallel | Toggle | Forced settings | | --- | --- | | `BUILD_VARIANT_OFFICIAL_RELEASE` | `BUILD_TESTING=OFF`, `ENABLE_UPDATE_CHECKS=ON`, `INSTALL_LICENSES=ON`, `STRIP_BINARY=ON`, `CMAKE_BUILD_TYPE=Release` | | `BUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE` | `BUILD_TESTING=OFF`, `ENABLE_UPDATE_CHECKS=ON`, `INSTALL_LICENSES=ON`, `STRIP_BINARY=ON`, `CMAKE_BUILD_TYPE=Release`, `PORTABLE_SPEEDCRUNCH=ON`, `CPACK_GENERATOR=ZIP` | | `BUILD_VARIANT_DEV_DEBUG` | `BUILD_TESTING=ON`, `ENABLE_UPDATE_CHECKS=ON`, `ENABLE_STARTUP_DIAGNOSTICS=ON`, `CMAKE_BUILD_TYPE=Debug` | With `BUILD_VARIANT_OFFICIAL_RELEASE=ON` in a fresh build directory, packaging defaults to `NSIS` on Windows and `DragNDrop` (DMG) on macOS. There is no need to pass `-DCPACK_GENERATOR` explicitly. This variant does not override an explicit or cached generator, or turn off portable mode from an earlier configuration. Use a separate build directory when switching from a portable build. A normal build creates the application. To create the installer or archive, run the `package` target, or uppercase `PACKAGE` with Visual Studio: cmake --build build-official --config Release --target package Only one variant can be enabled at a time. CMake stops with an error if more than one is `ON`. A variant overrides its listed settings on every configure, including conflicting `-D` arguments and values already in the cache. For Visual Studio, Xcode, and Ninja Multi-Config, a variant also restricts `CMAKE_CONFIGURATION_TYPES` to its configuration, either `Release` or `Debug`. Use the matching `--config` value when building, installing, or packaging. Settings outside a variant's list keep their usual defaults or cached values. Turning a variant off does not restore the values it overrides. Use separate build directories, as above, or disable the old variant and explicitly reset the affected settings when switching in an existing directory. ### License files in installed packages License installation defaults to `OFF` on every platform. Set `-DINSTALL_LICENSES=ON` to install SpeedCrunch's GPL text and a notice describing its use of Qt. Both official release variants force this option to `ON`, even when `-DINSTALL_LICENSES=OFF` is supplied. The developer Debug variant leaves it unchanged. CPack includes the enabled license files through the same install rules, for both portable and non-portable packages. Package providers can leave this option off and include the required license files through their own packaging tools, such as Fedora's `%license LICENSE` directive. When switching an existing build directory away from an official variant, disable that variant and set `-DINSTALL_LICENSES=OFF` to clear the cached value. When enabled, the license files are installed in these directories: | Platform | License directory | | --- | --- | | Windows | `Licenses` beside `speedcrunch.exe` | | macOS | `SpeedCrunch.app/Contents/Resources/Licenses` | | Linux and other Unix systems | `/share/doc/speedcrunch/Licenses` by default | | Haiku | `/documentation/SpeedCrunch/Licenses` | With `INSTALL_LICENSES=ON`, Windows and macOS packages also bundle Qt license texts and the SDK's component copyright notices. Windows also installs `COPYING.rtf` beside the executable. On macOS, the license files are installed before the app is signed. Install **Sources** for the same Qt version in the Qt Online Installer. CMake looks for them in the `Src` directory beside the selected desktop kit. For another location, set `-DSPEEDCRUNCH_QT_SOURCE_DIR=/path/to/qt/sources`. The SDK must include `sbom/-.spdx` files for `qtbase` and `qttools`. macOS also requires `qtsvg` and `qtimageformats`. Windows includes notices for those optional modules when their SPDX files are present in the selected kit, covering plugins added by `windeployqt` as well. These files are available in recent official Qt kits. With license installation enabled, installation and packaging stop if the required license texts, versions or notices are missing. Ordinary application builds do not need these files. Linux and Haiku installations use system Qt libraries and do not bundle Qt. Their Qt packages provide the corresponding licenses and notices, so installing SpeedCrunch there does not require a Qt source tree or SDK SPDX files. License copies and notices are distribution requirements. Publish matching SpeedCrunch source archives alongside binary downloads. When bundling Qt, also provide its matching sources to meet the applicable source distribution requirements. Including the license files does not replace this step. ## Updating translations After configuring a build directory, update the TS catalogs from the source strings with: cmake --build build --target update_translations This runs `lupdate` on the application sources and updates the catalogs in `src/resources/locale`. It passes `-no-obsolete` to remove entries that are no longer used in the source. New messages remain unfinished until translated. To compile the catalogs into QM files, run: cmake --build build --target release_translations Normal application builds also compile changed catalogs automatically and embed the generated QM files. Replace `build` with your configured directory, such as `build-dmg`. ## Building and running tests See [TESTING.md](TESTING.md) for test requirements and instructions on building and running the tests. ## Selecting Qt When building against a Qt version that is not the system default Qt installation, point CMake towards the Qt installation to use by setting `CMAKE_PREFIX_PATH` or `Qt6_DIR` when running CMake. Alternatively, Qt 6 provides a `qt-cmake` wrapper in the selected kit's `bin` directory (`qt-cmake.bat` on Windows, `qt-cmake` on macOS and Linux). It forwards the Qt installation location to CMake, so you do not need to set `CMAKE_PREFIX_PATH` yourself. See Qt's [CMake setup guide](https://doc.qt.io/qt-6/cmake-making-qt-available.html). ### Windows The steps below build a 64-bit application with Visual Studio 2022 and the matching Qt desktop kit. See the [Qt for Windows guide](https://doc.qt.io/qt-6/windows.html) for the Windows versions and compilers supported by your chosen Qt release. 1. Install Visual Studio 2022 or Build Tools for Visual Studio 2022. Select the **Desktop development with C++** workload, including the MSVC v143 x64/x86 build tools and a Windows SDK. See Microsoft's [C++ command-line tools guide](https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-170). 2. Install Qt through the Qt Online Installer. Select the **MSVC 2022 64-bit** desktop kit for your Qt 6 version, with the Core, Widgets, Help, Network, and LinguistTools components. A MinGW kit cannot be used with the MSVC commands below. Select **Sources** for the same version if you will install or package the app. 3. Select **CMake** under **Developer and Designer Tools** in the Qt Online Installer. You can also install it separately from [cmake.org](https://cmake.org/download/). The Visual Studio 2022 generator requires CMake 3.21 or later, even though the project itself accepts older CMake versions. Install Git as well if you want to clone the repository using the commands above. Open **x64 Native Tools Command Prompt for VS 2022** from the Start menu. This sets up the compiler and Windows SDK tools, including `rc.exe`. Change to the repository root, then run these commands in that prompt (`cmd.exe` syntax): set "QT_ROOT=C:\Qt\6.12.0\msvc2022_64" set "PATH=C:\Qt\Tools\CMake_64\bin;%QT_ROOT%\bin;%PATH%" cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_PREFIX_PATH="%QT_ROOT%" cmake --build build --config Release --parallel For Git Bash or another Bash-compatible shell, use `export` and `$QT_ROOT` instead of `set` and `%QT_ROOT%`. Start the shell from the Visual Studio developer prompt if it needs to inherit the compiler and Windows SDK environment. For example, the equivalent Git Bash commands are: export QT_ROOT='C:/Qt/6.12.0/msvc2022_64' export PATH="/c/Qt/Tools/CMake_64/bin:/c/Qt/6.12.0/msvc2022_64/bin:$PATH" cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_PREFIX_PATH="$QT_ROOT" cmake --build build --config Release --parallel With the Visual Studio generator, `--parallel` lets MSBuild build separate projects concurrently. SpeedCrunch also enables MSVC's `/MP` option so source files within each project can compile concurrently. After updating an existing checkout, rerun the configure command to apply this setting to the generated Visual Studio projects. Git Bash uses `/c/` for the C: drive in `PATH`, with colons between entries. The remaining Windows examples use `cmd.exe` syntax. In Git Bash, replace `%QT_ROOT%` with `$QT_ROOT`, `%CD%` with `$PWD`, and path separators with forward slashes. For example, run the application with `build/Release/speedcrunch.exe` and the deployment tool with `"$QT_ROOT/bin/windeployqt.exe"`. Adjust `QT_ROOT` and the CMake directory on `PATH` to match your installation. If CMake is already on `PATH`, you only need to add Qt's `bin` directory. The compiler, Qt kit, and target architecture must match. Use a fresh build directory when switching compilers, architectures, or Qt installations so CMake does not reuse cached paths. The executable is `build\Release\speedcrunch.exe`. You can run it from the same prompt, where Qt's DLLs are on `PATH`: build\Release\speedcrunch.exe To prepare a separate application folder, install into a local directory and run `windeployqt` from the same Qt kit to collect any additional Qt dependencies: cmake --install build --config Release --prefix "%CD%\build\install" "%QT_ROOT%\bin\windeployqt.exe" --release --no-compiler-runtime build\install\speedcrunch.exe build\install\speedcrunch.exe The install step copies the application, Qt libraries and plugins, and the MSVC runtime files selected by CMake through `InstallRequiredSystemLibraries`. It also copies license files when `INSTALL_LICENSES=ON`. `--no-compiler-runtime` tells `windeployqt` to leave compiler runtime deployment to CMake, while still collecting Qt dependencies. It does not remove the application's dependency on the MSVC runtime. When distributing the folder, also ensure the target machine has the matching [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170). To generate an installer from the Release build above, install [NSIS](https://nsis.sourceforge.io/) and make `makensis.exe` available on `PATH`. The default Windows package generator is NSIS. From the repository root, change to the build directory and run the Visual Studio `PACKAGE` target: cd build cmake --build . --config Release --target PACKAGE cd .. The installer is written to `build` as `SpeedCrunch-1.1-windows-x64.exe` for the 64-bit Windows build above. To generate an official portable ZIP archive instead, configure a separate build directory with `-DBUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE=ON`. From the repository root, build the application, then run the same `PACKAGE` target in that build directory: cmake -S . -B build-portable -G "Visual Studio 17 2022" -A x64 -DCMAKE_PREFIX_PATH="%QT_ROOT%" -DBUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE=ON cmake --build build-portable --config Release --parallel cd build-portable cmake --build . --config Release --target PACKAGE cd .. The ZIP archive is written to `build-portable`. CPack assembles it using the project's install rules, so a separate `cmake --install` command is not needed. The filename follows `SpeedCrunch---.zip`, for example `SpeedCrunch-1.1-windows-x64.zip` for a 64-bit Windows build. Windows packages use `windows-x64` for 64-bit builds or `windows-x86` for 32-bit builds, for both installers and ZIP archives. Portable mode stores settings and user data beside the executable. Selecting the ZIP generator explicitly avoids requiring NSIS to create this package. Check the application on a Windows machine without Qt installed before release, including the embedded manual and update checks if enabled. See Qt's [Windows deployment guide](https://doc.qt.io/qt-6/windows-deployment.html) for details. ### macOS SpeedCrunch supports Apple Silicon (`arm64`) Macs running macOS 14.4 (Sonoma) or later. Official macOS releases build against the official Qt libraries from the Qt Online Installer and ship those same libraries and the required plugins in the application bundle. This keeps the libraries' minimum macOS requirements aligned with SpeedCrunch's supported versions. CMake defaults the macOS target architecture to `arm64` before detecting the compiler, so no `-DCMAKE_OSX_ARCHITECTURES` argument is needed. Explicit values already supplied or cached are preserved. Use a fresh build directory if an existing one selects a different architecture. Follow the [official Qt for macOS guide](https://doc.qt.io/qt-6/macos.html) to install Xcode and Qt, then select the macOS desktop kit in the Qt Online Installer. The SDK used to compile SpeedCrunch can be newer than the deployment target. For example, a build using the macOS 27 SDK can still target macOS 14.4. Homebrew's Qt libraries and their dependencies may require a newer macOS version. During compatibility checks, Homebrew's QtHelp 6.12.0 library declared macOS 26.0 as its minimum, while the official QtHelp library declared 14.4. Lowering SpeedCrunch's deployment target does not lower the requirements of its bundled libraries. Use the official Qt installation for release builds to avoid these dependency mismatches. For example, if the official Qt kit is installed at `$HOME/Qt/6.12.0/macos`, run: "$HOME/Qt/6.12.0/macos/bin/qt-cmake" -S . -B build cmake --build build --config Release --parallel The `qt-cmake` wrapper selects its own Qt installation automatically. Use a fresh build directory when switching from Homebrew's Qt, since CMake caches the paths to individual Qt modules. Adjust the kit path above to match your installation. When packaging, CMake uses `macdeployqt` from the Qt installation selected at configure time. It bundles only the SQLite SQL driver needed by Qt Help, while preserving the other plugin groups used by the application. This avoids pulling in unrelated database client libraries. After deployment, CMake verifies the bundle's ad hoc signature and stops if verification fails. This applies to both DMG and ZIP packages, as well as `cmake --install`. Install matching Qt Sources before packaging, as described under [license files in installed packages](#license-files-in-installed-packages). ### macOS DMG CMake generates a DMG using the default `DragNDrop` package generator. No `-DCPACK_GENERATOR` argument is needed for the official release variant in a fresh build directory. From the repository root, configure with the official Qt kit, then run the package target: "$HOME/Qt/6.12.0/macos/bin/qt-cmake" -S . -B build-dmg -DBUILD_VARIANT_OFFICIAL_RELEASE=ON cmake --build build-dmg --config Release --target package --parallel Adjust the Qt path to match your installation. CMake and CPack must be on `PATH`. The package target builds the application, bundles Qt, applies and verifies an ad hoc signature, then creates the DMG. No separate packaging script or `cmake --install` command is needed. The output is `build-dmg/SpeedCrunch--macos-arm64.dmg`, for example `SpeedCrunch-1.1-macos-arm64.dmg`. This workflow does not notarize the app. ### Portable macOS ZIP To build a portable ZIP with the official Qt kit, configure a separate directory: "$HOME/Qt/6.12.0/macos/bin/qt-cmake" -S . -B build-portable -DBUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE=ON cmake --build build-portable --config Release --parallel cmake --build build-portable --config Release --target package The archive is written to `build-portable` using the same filename pattern as Windows: `SpeedCrunch---.zip`. For example, version 1.1 produces `SpeedCrunch-1.1-macos-arm64.zip` on macOS. Both macOS package formats use the `macos-arm64` suffix, while 64-bit Windows packages use `windows-x64`. The ZIP contains `SpeedCrunch.app` with its Qt libraries and plugins. Extract it into a writable folder. On first launch, SpeedCrunch creates `SpeedCrunch-data` beside the app for settings, sessions, user definitions, custom color schemes, update-check state, and the manual cache. Move or back up the app and this folder together. When updating, replace the app and keep the data folder. Portable mode never writes user data inside the app bundle. If the data folder cannot be created or written, startup stops with an error instead of opening with settings that cannot be saved. This can happen on read-only media or when macOS launches a downloaded app from a randomized, read-only location. Use Finder to move the app to its intended writable folder, keep any existing data folder beside it, then launch it again. See Apple's [App Translocation Notes](https://developer.apple.com/forums/thread/724969). The packaging step signs the portable bundle with an ad hoc signature and verifies it before creating the archive. Public distribution still needs Developer ID signing and notarization for normal Gatekeeper approval. ## Build options You can customize the build using the following variables. These are specified when running CMake, in the form `cmake -S . -B build -Dvariable=value`. - **BUILD_VARIANT_OFFICIAL_RELEASE**: Force the official Release settings listed under [Build variants](#build-variants). Defaults to `OFF`. - **BUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE**: Force the official portable Release settings, including ZIP packaging. Defaults to `OFF`. - **BUILD_VARIANT_DEV_DEBUG**: Force the developer Debug settings, including test builds and startup diagnostics. Defaults to `OFF`. - **CMAKE_BUILD_TYPE**: Select the configuration for Makefiles or ordinary Ninja, such as `Release`, `Debug`, or `RelWithDebInfo`. Defaults to `Release` in this project. Multi-configuration generators use `--config` when building instead. - **CMAKE_CONFIGURATION_TYPES**: Set the available configurations for Visual Studio, Xcode, and Ninja Multi-Config. Defaults depend on the generator. An enabled build variant restricts this list to its required configuration. - **CMAKE_OSX_DEPLOYMENT_TARGET**: Set the minimum macOS version for the build. Defaults to `14.4` unless an explicit target or the `MACOSX_DEPLOYMENT_TARGET` environment variable is supplied. Qt and all bundled dependencies must support the selected version or earlier. - **CMAKE_OSX_ARCHITECTURES**: Defaults to `arm64` for the supported Apple Silicon macOS build. Explicit values are preserved. Intel and universal builds are not supported. The Qt kit must support `arm64`. This value also supplies the architecture in macOS DMG and ZIP filenames. - **INSTALL_LICENSES**: Install SpeedCrunch's license text and Qt usage notice, plus bundled Qt license files on Windows and macOS. Defaults to `OFF` on all platforms. Both official release variants force it to `ON`. Windows also installs `COPYING.rtf` when this option is enabled. - **STRIP_BINARY**: Remove debug symbols from the application binary. Defaults to `OFF` on every platform. Both official release variants force it to `ON`. This option applies to any selected configuration. Package providers should leave it off to preserve symbols for their own debuginfo packages. It does not affect test executables. - **SPEEDCRUNCH_QT_SOURCE_DIR**: Set the matching Qt source tree used to collect license texts when `INSTALL_LICENSES=ON` on Windows and macOS. Defaults to `Src` beside the selected Qt desktop kit. It is not needed for ordinary application builds or installations that use system Qt on Linux and Haiku. - **BUILD_TESTING**: Set this to `ON` to build the test executables and register them with CTest. Defaults to `OFF`. See [TESTING.md](TESTING.md). - **ENABLE_UPDATE_CHECKS**: Set this to `ON` to enable update checks on launch and the `Help > Check for Updates` menu entry. Defaults to `OFF`. - **ENABLE_STARTUP_DIAGNOSTICS**: Set this to `ON` to record startup timings and detailed appearance diagnostics. Defaults to `OFF`. System information and settings remain available in `Help > App Diagnostics` in either build. See [DIAGNOSTICS.md](DIAGNOSTICS.md) for diagnostic beta build instructions. - **PORTABLE_SPEEDCRUNCH**: Set this to `ON` to have the application settings stored in the same location as the executable, e.g. for running from a USB drive without requiring installation. On macOS, all portable data goes in `SpeedCrunch-data` beside the `.app` bundle. Defaults to `OFF`. - **CPACK_GENERATOR**: Select the package generator, such as `NSIS`, `ZIP`, or `DragNDrop`. On Windows, defaults to `NSIS`, or `ZIP` when portable mode is on. On macOS, defaults to `DragNDrop`. Other platforms use CPack's defaults. These defaults apply when no generator is explicitly supplied or cached. The official release variant keeps these defaults and preserves any selected generator. Setting this option does not create a package during a normal build. Run the `package` target, or `PACKAGE` with Visual Studio, to create it. The official portable variant forces `ZIP` on every platform. - **CMAKE_INSTALL_PREFIX**: Change the installation prefix for SpeedCrunch. On macOS, the project uses `/install`. - **CMAKE_INSTALL_BINDIR**: Change the executable directory on Unix systems except macOS and Haiku. Defaults to `bin` under the installation prefix. - **CMAKE_INSTALL_DATAROOTDIR**: Change the shared data root on Unix systems except macOS and Haiku. Defaults to `share` under the installation prefix. - **CMAKE_INSTALL_DOCDIR**: Change the documentation directory on Unix systems except macOS and Haiku. Defaults to `share/doc/speedcrunch` under the installation prefix. With `INSTALL_LICENSES=ON`, license files are installed in its `Licenses` subdirectory. - **HTML_DOCS_DIR**: Change the path to the HTML manual that's embedded in the binary by the build. By default, a bundled prebuilt copy is used to minimize dependencies. Official SpeedCrunch builds use the release variant to enable update checks and apply the other release settings: cmake -S . -B build -DBUILD_VARIANT_OFFICIAL_RELEASE=ON These builds check for updates on launch at most once every 24 hours. Checks report upstream releases and link to the SpeedCrunch website. They do not install updates. Third-party package providers do not need to pass any toggles to keep update checks off. Leave all build variants off so users update through their provider. CMake saves these options in the build directory's cache. To disable update checks in an existing directory, turn off any active variant and configure again with `-DENABLE_UPDATE_CHECKS=OFF`. ## Unix installation and packaging On Linux and other Unix systems except macOS and Haiku, installation uses CMake's `GNUInstallDirs` conventions. `CMAKE_INSTALL_BINDIR` and `CMAKE_INSTALL_DATAROOTDIR` are relative to `CMAKE_INSTALL_PREFIX` unless explicitly configured as absolute paths. For example: cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_BINDIR=bin -DCMAKE_INSTALL_DATAROOTDIR=share cmake --build build --config Release --parallel DESTDIR=/tmp/speedcrunch-package cmake --install build --config Release `DESTDIR` stages the installation under another directory for packaging. With the example above, the executable is staged under `/tmp/speedcrunch-package/usr/bin`. Desktop entries and application metadata are installed under `applications` and `metainfo` within the shared data root. With `INSTALL_LICENSES=ON`, SpeedCrunch's license and Qt usage notice are installed under `share/doc/speedcrunch/Licenses`, unless `CMAKE_INSTALL_DOCDIR` is overridden. License installation is disabled by default. Desktop icons are installed in the `hicolor` theme: the SVG in `icons/hicolor/scalable/apps` and PNGs in `icons/hicolor/x/apps` for sizes 16, 22, 24, 32, 48, 64, 128, and 256. The installed icon basename is `org.speedcrunch.SpeedCrunch`. The PNG files are included in the source distribution; building and installing SpeedCrunch does not require icon-generation tools. ## Building the manual Building the HTML manual is normally not necessary because a prebuilt copy is included with the SpeedCrunch source. For more information, see the [manual's README](doc/src/README.md). heldercorreia-speedcrunch-e7ca37f/CHANGELOG.md000066400000000000000000000150241526573132500211500ustar00rootroot00000000000000# Changelog ## 1.1.0 ### Functions - Add `root(n; x)` for nth roots, including negative values and quantities with units. For example, `root(5; -32)` returns `-2`. - Fix factorials in user-defined functions, such as `f(n) = n!`. ### Constants and units - Search constants by name or unit with `Ctrl+Space`. Select a result with the arrow keys and insert it with Enter, Tab, or a click. - Improve searching and keyboard selection in the Constants panel. - Correct the units of the muon, proton, and neutron energy equivalents. - Allow powers of grouped quantities, such as `(2[m])^2`. - Correct results shown in `J/m²` and `J/m³` when using prefixed units. ### Input - Fix undo and redo, and copy and paste. - Fix clipped text and excess space in wrapped input with different fonts. - Fix crashes when typing operators in long, wrapped expressions. - Restore digit grouping while typing, following the selected number format. - Add an option to turn off automatic input adjustments, such as operator replacements and closing brackets. - Add optional Enter-to-accept autocomplete and Escape-to-clear behavior. - Add an option to use a steady cursor instead of a blinking one. - Preserve comments as written and prevent them from affecting result formatting. - Improve recalling expressions from history and focus the editor after startup. - Remove the empty-history hint. ### Results - Restore free copying. - Copy a whole calculation, including all displayed result formats, either across multiple lines or as a single line. - Add optional removal of trailing decimal zeroes. - Simplify live previews to show just the results. - Keep live result previews above the editor when recalling long expressions from history. - Avoid unnecessary extra simplification lines. - Restore the F2-F5 and F7-F10 notation shortcuts. ### Sessions and settings - Add private tabs that discard their contents when closed and are not restored on the next launch. Use `Ctrl+Shift+N` (`Cmd+Shift+N` on macOS) to open one. - Allow switching between private and saved sessions, and optionally open a private tab at startup. - Add **Reset All Settings...**, keeping sessions, history, and user definitions. - Fix global user definitions missing from restored sessions. - Make session renaming, cloning, closed-tab recovery, and pane controls easier to find in the menus. Cloning also copies unfinished input. - Organize the result context menu into Copy, Remove, Split, and Session groups. - Move **Number Format...** directly under Settings and simplify the result and appearance menus. - Apply font changes across all windows and fix font selection on macOS 27 and later. - Fix commands acting on the wrong window when used from a floating panel. ### Appearance and panels - Add separate system and SpeedCrunch theme choices for menus, panels, and the status bar. - Add a compact **Classic** layout for input and results. Modern remains the default. - Improve text contrast, menu readability, and panel button visibility. - Match menu icons to the theme and dim disabled menu items and shortcuts. - Tidy panel spacing, borders, and rounded corners. - Keep side panels at full height and remember table column order. - Preserve floating panel positions and visibility across restarts, and prevent floating panels from being grouped unexpectedly. ### Keypad - Add a compact **Classic** keypad appearance and 50% zoom. - Restore Zoom in the keypad's right-click menu and fix inconsistent sizing when changing zoom levels. - Update scientific layouts with nth-root, square, and argument-separator buttons, and group related operations together. - Replace the obsolete `lg` button with `log10`. ### Other improvements - Reduce startup delays when restoring sessions, history, and panels. - Make update checks more responsive and prevent them from delaying window closure. - Add **Help > App Diagnostics** with a report that can be copied when asking for help. Show operating system details in About SpeedCrunch. - Fix a crash when closing windows with certain panels open. - Add portable macOS ZIP packages that keep settings and sessions beside the app in a `SpeedCrunch-data` folder. - Set the default macOS minimum version to 14.4 on Apple Silicon. ## 1.0.0 ### Functions - Add matrix and vector operations, including products, inverses, determinants, transposes, and matrix dimensions. - Add population and sample statistics, covariance, correlation, and median absolute deviation, with support for lists and matrices. - Add `rand` and `randint` for random numbers, and summation over a range. - Add `datetime` and `epoch` for converting dates and Unix timestamps. - Add `molmass`, `mass`, and `molarity` for chemistry calculations. - Add `powmod`, `emod`, `lcm`, and `popcount` for modular arithmetic, least common multiples, and counting set bits. - Add `conj` and `cis` for working with complex numbers. - Add IEEE 754 rounding and rounding-error functions for half, single, double, and quadruple precision. ### Constants and units - Use square brackets to identify units explicitly, such as `5[m]`. - Add angle units and aliases, Julian centuries, hectares, tonnes, `kph`, `mph`, and the `quad` energy unit. - Insert constants and formulas with their units included. ### Input - Support lists, matrices, and superscript powers in expressions. - Accept `√`, `∛`, `Σ`, and `Ï€` aliases, `~` for bitwise NOT, and more symbols for arithmetic operators. - Show category icons in autocomplete suggestions. - Adapt pasted numbers to the selected number format. ### Results - Show the interpreted expression with implicit multiplication made explicit. - Display several result formats together, including fractions, sexagesimal angles and times, and angles expressed as multiples of pi. - Add complex polar forms and a choice of imaginary-unit symbol. - Add custom precision, five rounding modes, and Indian digit grouping. - Add `binpad`, `octpad`, and `hexpad` for output with leading zeroes, plus `sci` and `eng` for scientific and engineering notation. - Keep earlier calculations' formatting when changing the current result format. ### Sessions and settings - Work in tabs and split panes, save history between launches, and set history limits. - Load personal functions and variables at startup. - Edit earlier calculations and recalculate those below them. - Check for updates from within the app. ### Appearance and keypad - Add more themes, custom colors, and editor scaling. - Choose keypad presets or create a custom layout. - Show or hide the main menu, with access through the result context menu. heldercorreia-speedcrunch-e7ca37f/CMakeLists.txt000066400000000000000000000010541526573132500220750ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.16) include("${CMAKE_CURRENT_LIST_DIR}/src/cmake/BuildVariants.cmake") include("${CMAKE_CURRENT_LIST_DIR}/src/cmake/MacOSDeploymentTarget.cmake") project(speedcrunch VERSION 1.1) # Put executables and app bundles in the top-level build directory by default. if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") endif() add_subdirectory(src) # CTest looks for its entry point in the top-level build directory. if(BUILD_TESTING) enable_testing() endif() heldercorreia-speedcrunch-e7ca37f/CODE_OF_CONDUCT.md000066400000000000000000000121501526573132500221330ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at helder@speedcrunch.org. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. heldercorreia-speedcrunch-e7ca37f/DIAGNOSTICS.md000066400000000000000000000157051526573132500214360ustar00rootroot00000000000000# App Diagnostics Open **Help > App Diagnostics** for a plain text report that you can share with the developers when reporting a slow startup or a compatibility problem. Use **Copy to Clipboard** to copy the whole report. Available since SpeedCrunch 1.1. ## Enabling startup recording Startup recording is off by default. To include startup timings and detailed appearance tracing in a beta build for troubleshooting, configure from the repository root with: ```sh cmake -S . -B build -DENABLE_STARTUP_DIAGNOSTICS=ON cmake --build build --config Release --parallel ``` Enable this option explicitly for the beta builds you want to share. The `BUILD_VARIANT_DEV_DEBUG` variant also forces it on. The version and build type alone do not enable it. See [BUILDING.md](BUILDING.md#build-variants) for the variant settings. CMake saves the option in the build directory's cache. To disable it, turn off the developer variant if active and configure again with `-DENABLE_STARTUP_DIAGNOSTICS=OFF`. With the option off, the diagnostics layer uses no-op recording functions and the application uses Qt's normal event dispatch. The report still includes system information, settings, and session counts, but shows `Startup recording disabled in this build.` instead of timings. Recording adds overhead to the measured startup. Timings from diagnostic builds include that overhead. The sections below describe builds with recording enabled. ## Report contents The report includes the app version and Portable status, operating system, Qt versions, selected and system languages, display scaling, and widget style. It also shows process memory and CPU time where available, counts of open windows, sessions and history entries, and relevant calculation preferences. The editor, dock, menu, and status-bar appearance modes show the current choices each time you open the report. ## Startup timings Startup timings cover application setup, settings, built-in repositories, UI construction, docks, themes, and session restoration. File reads on worker threads, queued UI restoration, and startup painting are measured too. Recording starts at `main()` and finishes once the UI has painted and the startup tasks have completed. It does not include process loading before `main()` or time waiting for an update-check response. Times are measured in milliseconds. Nested phases and asynchronous work can overlap, so adding the phase totals will not give the overall startup time. Repeated phases show their call count, total time, and longest call. If startup is still running, reopen the dialog later for the complete report. ### Menus and update checks Menu timings separate creating the menu bar from filling the menus with actions. Native menu-bar creation can also create the platform window. Menu appearance reuses generated colors across menus with the same theme. Theme and system palette changes refresh those colors. Generation and reuse appear separately in the report. When update checks are enabled, automatic dispatch waits until the window has painted. `Deferred automatic update check (async total)` includes waiting for queued UI callbacks, rather than measuring only active work. Its timings separate the schedule check, saving the attempt timestamp, and network request setup. Update settings access, version comparison, and network setup run on a worker thread. The asynchronous schedule and setup total includes queue waiting, but excludes waiting for the response. ### Constants and Functions lists Constants and Functions list population is measured separately. Constants timings also separate clearing the list, filtering and formatting, creating rows and tooltips, sizing columns, and sorting. Column sizing includes any pending row layout that Qt performs while measuring the contents. Hidden constants lists keep their rows ready but wait until they are shown to measure column widths. Repeated theme surface requests reuse the last generated colors when their inputs match. These calls appear as `Reuse theme surface colors`. The detailed records identify calls from saved-filter restoration and language-change events. Calls that skip an unchanged list appear separately from population. The checks compare the translated list content, search and domain filters, and layout direction. Constants also compare the radix character. Search text and list content are not included in the report. ## Startup appearance details Startup appearance details show individual calls, their parent calls, and whether they run during window construction, session restoration, or a deferred refresh. Temporary numeric IDs identify widgets across calls, including panes added during restoration. Saved layouts reuse the initial pane and its editor, result display, and tab bar. Only additional panes need new controls. This appears as `Reuse initial session pane` in the timings. The report compares inputs for theme generation and highlighting, and counts palette and stylesheet assignments with changed or unchanged values. It also counts identical palette and stylesheet assignments that checks skip. Deferred native dock refreshes can skip polishing when the style and stylesheet are unchanged and both the system palette and the palette produced by the last restoration still match. Native theme and palette changes request a full refresh. ### Docks `Apply dock appearance` includes saving native widget state, styling the dock title, and styling its contents. Titles are styled first so changing the parent stylesheet does not repeat work on the contents. Table headers receive their own styling without the list scrollbar styles. Startup creates only the docks that were open in each saved window, including panels behind another dock tab and floating panels. Closed docks are created when you open them, using their saved placement when available. Older layouts without an open-dock list use empty temporary docks to read the saved visibility, without building application dock contents. Repeated themed palette assignments are skipped when their colors and explicit roles match. Deferred refreshes reuse native table-header measurements when the style, font, system palette, display DPI, layout direction, and header stylesheet are unchanged. Header data changes and model resets discard the saved measurements. Measurement and reuse appear separately in the timings. ### Highlighting and recording limits Highlighting comparisons use document revisions and sizes, theme inputs, selected settings, and evaluator identity. They do not track changes to the evaluator's symbols. Matching inputs help identify repeated work, but do not prove that a call can be skipped. Detailed records have fixed limits, and the report shows how many records are omitted when those limits are reached. These measurements add some overhead while startup is recorded. ## Privacy The measurements stay in memory until you quit. SpeedCrunch does not log or send them anywhere. The report excludes calculation text, session names, and file paths. Copying it puts the report on your system clipboard. heldercorreia-speedcrunch-e7ca37f/LICENSE000066400000000000000000000432531526573132500203510ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License.heldercorreia-speedcrunch-e7ca37f/README.md000066400000000000000000000065021526573132500206170ustar00rootroot00000000000000# SpeedCrunch SpeedCrunch is a high-precision scientific calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard. Some distinctive features are auto-completion of functions and variables, a formula book, and quick insertion of constants from various fields of knowledge. It is available for Windows, macOS, and Linux in a number of languages. Visit the [SpeedCrunch website](https://www.speedcrunch.org/) for [downloads](https://www.speedcrunch.org/download.html) and the [online manual](https://www.speedcrunch.org/introduction.html). See the [changelog](CHANGELOG.md) for release highlights and fixes. ![SpeedCrunch screenshot](doc/src/screen1.png) ## Building and testing See [BUILDING.md](BUILDING.md) for requirements and instructions on building, installing SpeedCrunch, and packaging it. The guide also links to instructions for building the manual. See [TESTING.md](TESTING.md) for instructions on building and running the tests. See [DIAGNOSTICS.md](DIAGNOSTICS.md) for details about App Diagnostics, startup timings, and the information included in diagnostic reports. ## File locations SpeedCrunch uses [Qt's standard per-user locations](https://doc.qt.io/qt-6/qstandardpaths.html) for persistent application data and configuration: | Platform | Application data | Preferences/configuration | | --- | --- | --- | | macOS | `~/Library/Application Support/SpeedCrunch/` | `~/Library/Preferences/SpeedCrunch/` | | Windows | `%APPDATA%\SpeedCrunch\` | `%APPDATA%\SpeedCrunch\` | | Linux | `$XDG_DATA_HOME/SpeedCrunch/` (usually `~/.local/share/SpeedCrunch/`) | `$XDG_CONFIG_HOME/SpeedCrunch/` (usually `~/.config/SpeedCrunch/`) | Qt respects system-specific overrides to these locations. In the Windows portable build, application data and preferences/configuration are all stored in the same directory as the portable application. ## Contributing Please read our [Code of Conduct](CODE_OF_CONDUCT.md) before participating. - Report bugs, request features or implement a ticket from the [issue tracker](https://speedcrunch.org/issues.html). - Be part of the [community](https://speedcrunch.org/community.html). - [Donate](https://www.speedcrunch.org/donate.html) to help supporting the expenses of server hosting, internet domain and computers for further development. ![SpeedCrunch contributors](https://contrib.rocks/image?repo=heldercorreia/speedcrunch) ## License This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file [LICENSE](LICENSE). If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ## Packaging status [![Packaging status](https://repology.org/badge/vertical-allrepos/speedcrunch.svg?exclude_unsupported=1&minversion=1.0.0&columns=4&exclude_sources=modules,site)](https://repology.org/project/speedcrunch/versions) heldercorreia-speedcrunch-e7ca37f/TESTING.md000066400000000000000000000111171526573132500207750ustar00rootroot00000000000000# Testing SpeedCrunch See [BUILDING.md](BUILDING.md) for build requirements, Qt selection, and build configurations. Building the tests also requires the Qt Test module. ## Building and running tests By default, only the application is built. To also build and run the tests, enable `BUILD_TESTING` when configuring. Run these commands from the repository root: cmake -S . -B build -DBUILD_TESTING=ON cmake --build build --config Release --parallel ctest --test-dir build -C Release --parallel --output-on-failure The UI test suites use temporary configuration, session and cache directories, and reset settings before each test case. They suppress the first-run number format prompt. An unexpected prompt fails the test instead of blocking the suite. They use Qt's offscreen platform unless `QT_QPA_PLATFORM` is already set. CMake saves `BUILD_TESTING` in the build directory's cache. Configure again with `-DBUILD_TESTING=OFF` to return to application-only builds. The `BUILD_VARIANT_DEV_DEBUG` variant forces testing on, while the two official release variants force it off. Disable any active variant before changing `BUILD_TESTING` independently. See [BUILDING.md](BUILDING.md#build-variants). The shared window test library enables startup recording so appearance tests can inspect the recorded work. This does not enable recording in the application. Set `ENABLE_STARTUP_DIAGNOSTICS` explicitly or use `BUILD_VARIANT_DEV_DEBUG` for that, as described in [DIAGNOSTICS.md](DIAGNOSTICS.md). ## Windows Follow the [Windows build setup](BUILDING.md#windows), including setting `QT_ROOT` to your Qt MSVC kit. From the repository root in **x64 Native Tools Command Prompt for VS 2022**, configure a developer Debug build and run the tests: cmake -S . -B build-dev -DCMAKE_PREFIX_PATH="%QT_ROOT%" -DBUILD_VARIANT_DEV_DEBUG=ON cmake --build build-dev --config Debug --parallel ctest --test-dir build-dev -C Debug --parallel 4 --output-on-failure Rebuild after pulling test or application changes. To rerun only the suites that failed in the previous CTest run, use: ctest --test-dir build-dev -C Debug --rerun-failed --parallel 4 --output-on-failure The build and test commands also work in Git Bash once the build is configured. The configure command above uses Command Prompt syntax for `QT_ROOT`. On Windows, CTest adds the configured Qt kit's DLL directory to each test's `PATH`. This lets the tests find libraries such as `Qt6Core.dll` without copying them beside every executable. Rerun the configure command after updating an existing checkout to apply this setting. When running a test executable directly, add the matching Qt kit's `bin` directory to `PATH` in that shell first. With `QT_ROOT` set as described in [BUILDING.md](BUILDING.md), use this in Command Prompt: set "PATH=%QT_ROOT%\bin;%PATH%" Or, for the example installation in Git Bash: export PATH="/c/Qt/6.12.0/msvc2022_64/bin:$PATH" Adjust the path to match your installation. A Windows dialog reporting a missing Qt DLL means the test could not start, rather than that a test assertion failed. ### Offscreen fonts No `QT_QPA_PLATFORM` or `QT_QPA_FONTDIR` setting is needed for a normal test run. When using offscreen mode on Windows, the UI test fixture sets `QT_QPA_FONTDIR` to `%SystemRoot%\Fonts` if that directory exists and no font directory is already set. An explicit `QT_QPA_FONTDIR` value takes precedence. If Qt reports `Cannot find font directory`, check that the directory exists and contains font files. To select a different directory, set it before running CTest. For example, in Command Prompt: set "QT_QPA_FONTDIR=C:\Windows\Fonts" ctest --test-dir build-dev -C Debug --parallel 4 --output-on-failure Or in Git Bash: QT_QPA_FONTDIR=C:/Windows/Fonts ctest --test-dir build-dev -C Debug --parallel 4 --output-on-failure Missing fonts can cause failures in text sizing, glyph rendering and font dialog tests. Offscreen warnings such as `This plugin does not support raise()` or `propagateSizeHints()` are expected and do not by themselves mean a test fails. ### Native Windows UI checks To check the native Windows backend, use a separate shell and run UI suites one at a time so desktop focus and the clipboard cannot interfere. In Command Prompt: set "QT_QPA_PLATFORM=windows" ctest --test-dir build-dev -C Debug -L ui --parallel 1 --output-on-failure Or in Git Bash: QT_QPA_PLATFORM=windows ctest --test-dir build-dev -C Debug -L ui --parallel 1 --output-on-failure Close the Command Prompt shell when finished, or clear `QT_QPA_PLATFORM` with `set "QT_QPA_PLATFORM="` before returning to offscreen tests. heldercorreia-speedcrunch-e7ca37f/doc/000077500000000000000000000000001526573132500201025ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/000077500000000000000000000000001526573132500240365ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/000077500000000000000000000000001526573132500250475ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/.buildinfo000066400000000000000000000003471526573132500270270ustar00rootroot00000000000000# Sphinx build info version 1 # This file records the configuration used when building these files. When it is not found, a full rebuild will be done. config: e410c2e9d747b737b9022ae925acfc2b tags: 1bbd8eaff704366f15153da3e545beff heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/000077500000000000000000000000001526573132500264755ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/basic.css000066400000000000000000000345351526573132500303020ustar00rootroot00000000000000/* * Sphinx stylesheet -- basic theme. */ /* -- main layout ----------------------------------------------------------- */ div.clearer { clear: both; } div.section::after { display: block; content: ''; clear: left; } /* -- relbar ---------------------------------------------------------------- */ div.related { width: 100%; font-size: 90%; } div.related h3 { display: none; } div.related ul { margin: 0; padding: 0 0 0 10px; list-style: none; } div.related li { display: inline; } div.related li.right { float: right; margin-right: 5px; } /* -- sidebar --------------------------------------------------------------- */ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; } div.sphinxsidebar { float: left; width: 230px; margin-left: -100%; font-size: 90%; word-wrap: break-word; overflow-wrap : break-word; } div.sphinxsidebar ul { list-style: none; } div.sphinxsidebar ul ul, div.sphinxsidebar ul.want-points { margin-left: 20px; list-style: square; } div.sphinxsidebar ul ul { margin-top: 0; margin-bottom: 0; } div.sphinxsidebar form { margin-top: 10px; } div.sphinxsidebar input { border: 1px solid #98dbcc; font-family: sans-serif; font-size: 1em; } div.sphinxsidebar #searchbox form.search { overflow: hidden; } div.sphinxsidebar #searchbox input[type="text"] { float: left; width: 80%; padding: 0.25em; box-sizing: border-box; } div.sphinxsidebar #searchbox input[type="submit"] { float: left; width: 20%; border-left: none; padding: 0.25em; box-sizing: border-box; } img { border: 0; max-width: 100%; } /* -- search page ----------------------------------------------------------- */ ul.search { margin-top: 10px; } ul.search li { padding: 5px 0; } ul.search li a { font-weight: bold; } ul.search li p.context { color: #888; margin: 2px 0 0 30px; text-align: left; } ul.keywordmatches li.goodmatch a { font-weight: bold; } /* -- index page ------------------------------------------------------------ */ table.contentstable { width: 90%; margin-left: auto; margin-right: auto; } table.contentstable p.biglink { line-height: 150%; } a.biglink { font-size: 1.3em; } span.linkdescr { font-style: italic; padding-top: 5px; font-size: 90%; } /* -- general index --------------------------------------------------------- */ table.indextable { width: 100%; } table.indextable td { text-align: left; vertical-align: top; } table.indextable ul { margin-top: 0; margin-bottom: 0; list-style-type: none; } table.indextable > tbody > tr > td > ul { padding-left: 0em; } table.indextable tr.pcap { height: 10px; } table.indextable tr.cap { margin-top: 10px; background-color: #f2f2f2; } img.toggler { margin-right: 3px; margin-top: 3px; cursor: pointer; } div.modindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } div.genindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } /* -- domain module index --------------------------------------------------- */ table.modindextable td { padding: 2px; border-collapse: collapse; } /* -- general body styles --------------------------------------------------- */ div.body { min-width: 360px; max-width: 800px; } div.body p, div.body dd, div.body li, div.body blockquote { -moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto; } a.headerlink { visibility: hidden; } a:visited { color: #551A8B; } h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink, caption:hover > a.headerlink, p.caption:hover > a.headerlink, div.code-block-caption:hover > a.headerlink { visibility: visible; } div.body p.caption { text-align: inherit; } div.body td { text-align: left; } .first { margin-top: 0 !important; } p.rubric { margin-top: 30px; font-weight: bold; } img.align-left, figure.align-left, .figure.align-left, object.align-left { clear: left; float: left; margin-right: 1em; } img.align-right, figure.align-right, .figure.align-right, object.align-right { clear: right; float: right; margin-left: 1em; } img.align-center, figure.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } img.align-default, figure.align-default, .figure.align-default { display: block; margin-left: auto; margin-right: auto; } .align-left { text-align: left; } .align-center { text-align: center; } .align-default { text-align: center; } .align-right { text-align: right; } /* -- sidebars -------------------------------------------------------------- */ div.sidebar, aside.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; padding: 7px; background-color: #ffe; width: 40%; float: right; clear: right; overflow-x: auto; } p.sidebar-title { font-weight: bold; } nav.contents, aside.topic, div.admonition, div.topic, blockquote { clear: left; } /* -- topics ---------------------------------------------------------------- */ nav.contents, aside.topic, div.topic { border: 1px solid #ccc; padding: 7px; margin: 10px 0 10px 0; } p.topic-title { font-size: 1.1em; font-weight: bold; margin-top: 10px; } /* -- admonitions ----------------------------------------------------------- */ div.admonition { margin-top: 10px; margin-bottom: 10px; padding: 7px; } div.admonition dt { font-weight: bold; } p.admonition-title { margin: 0px 10px 5px 0px; font-weight: bold; } div.body p.centered { text-align: center; margin-top: 25px; } /* -- content of sidebars/topics/admonitions -------------------------------- */ div.sidebar > :last-child, aside.sidebar > :last-child, nav.contents > :last-child, aside.topic > :last-child, div.topic > :last-child, div.admonition > :last-child { margin-bottom: 0; } div.sidebar::after, aside.sidebar::after, nav.contents::after, aside.topic::after, div.topic::after, div.admonition::after, blockquote::after { display: block; content: ''; clear: both; } /* -- tables ---------------------------------------------------------------- */ table.docutils { margin-top: 10px; margin-bottom: 10px; border: 0; border-collapse: collapse; } table.align-center { margin-left: auto; margin-right: auto; } table.align-default { margin-left: auto; margin-right: auto; } table caption span.caption-number { font-style: italic; } table caption span.caption-text { } table.docutils td, table.docutils th { padding: 1px 8px 1px 5px; border-top: 0; border-left: 0; border-right: 0; border-bottom: 1px solid #aaa; } th { text-align: left; padding-right: 5px; } table.citation { border-left: solid 1px gray; margin-left: 1px; } table.citation td { border-bottom: none; } th > :first-child, td > :first-child { margin-top: 0px; } th > :last-child, td > :last-child { margin-bottom: 0px; } /* -- figures --------------------------------------------------------------- */ div.figure, figure { margin: 0.5em; padding: 0.5em; } div.figure p.caption, figcaption { padding: 0.3em; } div.figure p.caption span.caption-number, figcaption span.caption-number { font-style: italic; } div.figure p.caption span.caption-text, figcaption span.caption-text { } /* -- field list styles ----------------------------------------------------- */ table.field-list td, table.field-list th { border: 0 !important; } .field-list ul { margin: 0; padding-left: 1em; } .field-list p { margin: 0; } .field-name { -moz-hyphens: manual; -ms-hyphens: manual; -webkit-hyphens: manual; hyphens: manual; } /* -- hlist styles ---------------------------------------------------------- */ table.hlist { margin: 1em 0; } table.hlist td { vertical-align: top; } /* -- object description styles --------------------------------------------- */ .sig { font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; } .sig-name, code.descname { background-color: transparent; font-weight: bold; } .sig-name { font-size: 1.1em; } code.descname { font-size: 1.2em; } .sig-prename, code.descclassname { background-color: transparent; } .optional { font-size: 1.3em; } .sig-paren { font-size: larger; } .sig-param.n { font-style: italic; } /* C++ specific styling */ .sig-inline.c-texpr, .sig-inline.cpp-texpr { font-family: unset; } .sig.c .k, .sig.c .kt, .sig.cpp .k, .sig.cpp .kt { color: #0033B3; } .sig.c .m, .sig.cpp .m { color: #1750EB; } .sig.c .s, .sig.c .sc, .sig.cpp .s, .sig.cpp .sc { color: #067D17; } /* -- other body styles ----------------------------------------------------- */ ol.arabic { list-style: decimal; } ol.loweralpha { list-style: lower-alpha; } ol.upperalpha { list-style: upper-alpha; } ol.lowerroman { list-style: lower-roman; } ol.upperroman { list-style: upper-roman; } :not(li) > ol > li:first-child > :first-child, :not(li) > ul > li:first-child > :first-child { margin-top: 0px; } :not(li) > ol > li:last-child > :last-child, :not(li) > ul > li:last-child > :last-child { margin-bottom: 0px; } ol.simple ol p, ol.simple ul p, ul.simple ol p, ul.simple ul p { margin-top: 0; } ol.simple > li:not(:first-child) > p, ul.simple > li:not(:first-child) > p { margin-top: 0; } ol.simple p, ul.simple p { margin-bottom: 0; } aside.footnote > span, div.citation > span { float: left; } aside.footnote > span:last-of-type, div.citation > span:last-of-type { padding-right: 0.5em; } aside.footnote > p { margin-left: 2em; } div.citation > p { margin-left: 4em; } aside.footnote > p:last-of-type, div.citation > p:last-of-type { margin-bottom: 0em; } aside.footnote > p:last-of-type:after, div.citation > p:last-of-type:after { content: ""; clear: both; } dl.field-list { display: grid; grid-template-columns: fit-content(30%) auto; } dl.field-list > dt { font-weight: bold; word-break: break-word; padding-left: 0.5em; padding-right: 5px; } dl.field-list > dd { padding-left: 0.5em; margin-top: 0em; margin-left: 0em; margin-bottom: 0em; } dl { margin-bottom: 15px; } dd > :first-child { margin-top: 0px; } dd ul, dd table { margin-bottom: 10px; } dd { margin-top: 3px; margin-bottom: 10px; margin-left: 30px; } .sig dd { margin-top: 0px; margin-bottom: 0px; } .sig dl { margin-top: 0px; margin-bottom: 0px; } dl > dd:last-child, dl > dd:last-child > :last-child { margin-bottom: 0; } dt:target, span.highlighted { background-color: #fbe54e; } rect.highlighted { fill: #fbe54e; } dl.glossary dt { font-weight: bold; font-size: 1.1em; } .versionmodified { font-style: italic; } .system-message { background-color: #fda; padding: 5px; border: 3px solid red; } .footnote:target { background-color: #ffa; } .line-block { display: block; margin-top: 1em; margin-bottom: 1em; } .line-block .line-block { margin-top: 0; margin-bottom: 0; margin-left: 1.5em; } .guilabel, .menuselection { font-family: sans-serif; } .accelerator { text-decoration: underline; } .classifier { font-style: oblique; } .classifier:before { font-style: normal; margin: 0 0.5em; content: ":"; display: inline-block; } abbr, acronym { border-bottom: dotted 1px; cursor: help; } /* -- code displays --------------------------------------------------------- */ pre { overflow: auto; overflow-y: hidden; /* fixes display issues on Chrome browsers */ } pre, div[class*="highlight-"] { clear: both; } span.pre { -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; white-space: nowrap; } div[class*="highlight-"] { margin: 1em 0; } td.linenos pre { border: 0; background-color: transparent; color: #aaa; } table.highlighttable { display: block; } table.highlighttable tbody { display: block; } table.highlighttable tr { display: flex; } table.highlighttable td { margin: 0; padding: 0; } table.highlighttable td.linenos { padding-right: 0.5em; } table.highlighttable td.code { flex: 1; overflow: hidden; } .highlight .hll { display: block; } div.highlight pre, table.highlighttable pre { margin: 0; } div.code-block-caption + div { margin-top: 0; } div.code-block-caption { margin-top: 1em; padding: 2px 5px; font-size: small; } div.code-block-caption code { background-color: transparent; } table.highlighttable td.linenos, span.linenos, div.highlight span.gp { /* gp: Generic.Prompt */ user-select: none; -webkit-user-select: text; /* Safari fallback only */ -webkit-user-select: none; /* Chrome/Safari */ -moz-user-select: none; /* Firefox */ -ms-user-select: none; /* IE10+ */ } div.code-block-caption span.caption-number { padding: 0.1em 0.3em; font-style: italic; } div.code-block-caption span.caption-text { } div.literal-block-wrapper { margin: 1em 0; } code.xref, a code { background-color: transparent; font-weight: bold; } h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { background-color: transparent; } .viewcode-link { float: right; } .viewcode-back { float: right; font-family: sans-serif; } div.viewcode-block:target { margin: -1px -10px; padding: 0 10px; } /* -- math display ---------------------------------------------------------- */ img.math { vertical-align: middle; } div.body div.math p { text-align: center; } span.eqno { float: right; } span.eqno a.headerlink { position: absolute; z-index: 1; } div.math:hover a.headerlink { visibility: visible; } /* -- printout stylesheet --------------------------------------------------- */ @media print { div.document, div.documentwrapper, div.bodywrapper { margin: 0 !important; width: 100%; } div.sphinxsidebar, div.related, div.footer, #top-link { display: none; } }heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/doctools.js000066400000000000000000000103541526573132500306640ustar00rootroot00000000000000/* * Base JavaScript utilities for all Sphinx HTML documentation. */ "use strict"; const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ "TEXTAREA", "INPUT", "SELECT", "BUTTON", ]); const _ready = (callback) => { if (document.readyState !== "loading") { callback(); } else { document.addEventListener("DOMContentLoaded", callback); } }; /** * Small JavaScript module for the documentation. */ const Documentation = { init: () => { Documentation.initDomainIndexTable(); Documentation.initOnKeyListeners(); }, /** * i18n support */ TRANSLATIONS: {}, PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), LOCALE: "unknown", // gettext and ngettext don't access this so that the functions // can safely bound to a different name (_ = Documentation.gettext) gettext: (string) => { const translated = Documentation.TRANSLATIONS[string]; switch (typeof translated) { case "undefined": return string; // no translation case "string": return translated; // translation exists default: return translated[0]; // (singular, plural) translation tuple exists } }, ngettext: (singular, plural, n) => { const translated = Documentation.TRANSLATIONS[singular]; if (typeof translated !== "undefined") return translated[Documentation.PLURAL_EXPR(n)]; return n === 1 ? singular : plural; }, addTranslations: (catalog) => { Object.assign(Documentation.TRANSLATIONS, catalog.messages); Documentation.PLURAL_EXPR = new Function( "n", `return (${catalog.plural_expr})`, ); Documentation.LOCALE = catalog.locale; }, /** * helper function to focus on search bar */ focusSearchBar: () => { document.querySelectorAll("input[name=q]")[0]?.focus(); }, /** * Initialise the domain index toggle buttons */ initDomainIndexTable: () => { const toggler = (el) => { const idNumber = el.id.substr(7); const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); if (el.src.substr(-9) === "minus.png") { el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; toggledRows.forEach((el) => (el.style.display = "none")); } else { el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; toggledRows.forEach((el) => (el.style.display = "")); } }; const togglerElements = document.querySelectorAll("img.toggler"); togglerElements.forEach((el) => el.addEventListener("click", (event) => toggler(event.currentTarget)), ); togglerElements.forEach((el) => (el.style.display = "")); if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); }, initOnKeyListeners: () => { // only install a listener if it is really needed if ( !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS ) return; document.addEventListener("keydown", (event) => { // bail for input elements if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; // bail with special keys if (event.altKey || event.ctrlKey || event.metaKey) return; if (!event.shiftKey) { switch (event.key) { case "ArrowLeft": if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; const prevLink = document.querySelector('link[rel="prev"]'); if (prevLink && prevLink.href) { window.location.href = prevLink.href; event.preventDefault(); } break; case "ArrowRight": if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; const nextLink = document.querySelector('link[rel="next"]'); if (nextLink && nextLink.href) { window.location.href = nextLink.href; event.preventDefault(); } break; } } // some keyboard layouts may need Shift to get / switch (event.key) { case "/": if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; Documentation.focusSearchBar(); event.preventDefault(); } }); }, }; // quick alias for translations const _ = Documentation.gettext; _ready(Documentation.init); heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/documentation_options.js000066400000000000000000000005131526573132500334560ustar00rootroot00000000000000const DOCUMENTATION_OPTIONS = { VERSION: '1.1', LANGUAGE: 'en-US', COLLAPSE_INDEX: false, BUILDER: 'qthelp', FILE_SUFFIX: '.html', LINK_SUFFIX: '.html', HAS_SOURCE: true, SOURCELINK_SUFFIX: '.txt', NAVIGATION_WITH_KEYS: false, SHOW_SEARCH_SUMMARY: true, ENABLE_SEARCH_SHORTCUTS: true, };heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/file.png000066400000000000000000000004361526573132500301250ustar00rootroot00000000000000‰PNG  IHDRóÿaåIDATx­“ƒR…÷){…l× Û¶ÙfÛ=@®å œ:¿¹¾3ßú~箄þþþ¹òòrX$AðX-öD ~ñýý òóó€Ç‰(ŠP%¾€�8<<9:: ãøøØP•êO&’$é Ø�l~‚X÷ìã�ûæ&ȽÖEWÀ^4µwQ}ÂÎö^ü˜Ô÷Í£¾ ‹¨iê©ïš0/H/é@F)éDzq+’ój�”[žSU5¾€Ìèhš¦/ð¿oY– G&Lfs|�£¡»»{Íêßøß3%¸U+S°é`AFÒIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/language_data.js000066400000000000000000000003501526573132500316050ustar00rootroot00000000000000/* * This script contains the language-specific data used by searchtools.js, * namely the set of stopwords, stemmer, scorer and splitter. */ const stopwords = new Set(); window.stopwords = stopwords; // Export to global scope heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/minus.png000066400000000000000000000001321526573132500303320ustar00rootroot00000000000000‰PNG  IHDR ŒÇ(ú!IDATxc8ƒ g>@Á;(û!¶&«þ€Ø]ìf2nüNIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/plus.png000066400000000000000000000001321526573132500301620ustar00rootroot00000000000000‰PNG  IHDR ŒÇ(ú!IDATxc8ƒ g>@Á;([“[ˆUÿ @l-!a”óð@IEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/pygments.css000066400000000000000000000110761526573132500310620ustar00rootroot00000000000000pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #ffffff; } .highlight .c { color: #888; font-style: italic } /* Comment */ .highlight .err { background-color: #A848A8 } /* Error */ .highlight .k { color: #2838B0 } /* Keyword */ .highlight .o { color: #666 } /* Operator */ .highlight .p { color: #888 } /* Punctuation */ .highlight .ch { color: #287088; font-style: italic } /* Comment.Hashbang */ .highlight .cm { color: #888; font-style: italic } /* Comment.Multiline */ .highlight .cp { color: #289870 } /* Comment.Preproc */ .highlight .cpf { color: #888; font-style: italic } /* Comment.PreprocFile */ .highlight .c1 { color: #888; font-style: italic } /* Comment.Single */ .highlight .cs { color: #888; font-style: italic } /* Comment.Special */ .highlight .gd { color: #C02828 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #C02828 } /* Generic.Error */ .highlight .gh { color: #666 } /* Generic.Heading */ .highlight .gi { color: #388038 } /* Generic.Inserted */ .highlight .go { color: #666 } /* Generic.Output */ .highlight .gp { color: #444 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #444 } /* Generic.Subheading */ .highlight .gt { color: #2838B0 } /* Generic.Traceback */ .highlight .kc { color: #444; font-style: italic } /* Keyword.Constant */ .highlight .kd { color: #2838B0; font-style: italic } /* Keyword.Declaration */ .highlight .kn { color: #2838B0 } /* Keyword.Namespace */ .highlight .kp { color: #2838B0 } /* Keyword.Pseudo */ .highlight .kr { color: #2838B0 } /* Keyword.Reserved */ .highlight .kt { color: #2838B0; font-style: italic } /* Keyword.Type */ .highlight .m { color: #444 } /* Literal.Number */ .highlight .s { color: #B83838 } /* Literal.String */ .highlight .na { color: #388038 } /* Name.Attribute */ .highlight .nb { color: #388038 } /* Name.Builtin */ .highlight .nc { color: #287088 } /* Name.Class */ .highlight .no { color: #B85820 } /* Name.Constant */ .highlight .nd { color: #287088 } /* Name.Decorator */ .highlight .ni { color: #709030 } /* Name.Entity */ .highlight .ne { color: #908828 } /* Name.Exception */ .highlight .nf { color: #785840 } /* Name.Function */ .highlight .nl { color: #289870 } /* Name.Label */ .highlight .nn { color: #289870 } /* Name.Namespace */ .highlight .nt { color: #2838B0 } /* Name.Tag */ .highlight .nv { color: #B04040 } /* Name.Variable */ .highlight .ow { color: #A848A8 } /* Operator.Word */ .highlight .pm { color: #888 } /* Punctuation.Marker */ .highlight .w { color: #A89028 } /* Text.Whitespace */ .highlight .mb { color: #444 } /* Literal.Number.Bin */ .highlight .mf { color: #444 } /* Literal.Number.Float */ .highlight .mh { color: #444 } /* Literal.Number.Hex */ .highlight .mi { color: #444 } /* Literal.Number.Integer */ .highlight .mo { color: #444 } /* Literal.Number.Oct */ .highlight .sa { color: #444 } /* Literal.String.Affix */ .highlight .sb { color: #B83838 } /* Literal.String.Backtick */ .highlight .sc { color: #A848A8 } /* Literal.String.Char */ .highlight .dl { color: #B85820 } /* Literal.String.Delimiter */ .highlight .sd { color: #B85820; font-style: italic } /* Literal.String.Doc */ .highlight .s2 { color: #B83838 } /* Literal.String.Double */ .highlight .se { color: #709030 } /* Literal.String.Escape */ .highlight .sh { color: #B83838 } /* Literal.String.Heredoc */ .highlight .si { color: #B83838; text-decoration: underline } /* Literal.String.Interpol */ .highlight .sx { color: #A848A8 } /* Literal.String.Other */ .highlight .sr { color: #A848A8 } /* Literal.String.Regex */ .highlight .s1 { color: #B83838 } /* Literal.String.Single */ .highlight .ss { color: #B83838 } /* Literal.String.Symbol */ .highlight .bp { color: #388038; font-style: italic } /* Name.Builtin.Pseudo */ .highlight .fm { color: #B85820 } /* Name.Function.Magic */ .highlight .vc { color: #B04040 } /* Name.Variable.Class */ .highlight .vg { color: #908828 } /* Name.Variable.Global */ .highlight .vi { color: #B04040 } /* Name.Variable.Instance */ .highlight .vm { color: #B85820 } /* Name.Variable.Magic */ .highlight .il { color: #444 } /* Literal.Number.Integer.Long */heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/quark.css000066400000000000000000000143161526573132500303370ustar00rootroot00000000000000body { color: #000000; } .document { margin-left: 2em; margin-right: 2em; } li { margin-top: 0.3em; margin-bottom: 0.3em; text-indent: 0px; } li li { text-indent: 0px; } li li li { text-indent: 0px; } li li li li { text-indent: 0px; } li li li li li { text-indent: 0px; } li li li li li li { text-indent: 0px; } li li li li li li li { text-indent: 0px; } li li li li li li li li { text-indent: 0px; } li li li li li li li li li { text-indent: 0px; } blockquote { text-indent: 0px; } /* Definition lists */ dt { font-weight: bold; } dd > * { margin-top: 0; } li > dl > dd { margin-left: 0; } /* Compact list produced by hlist:: directive */ table.hlist { margin-top: 1em; } table.hlist ul { margin-top: 0; margin-bottom: 0; } /* Header/footer navigation bar * * ---------------------------- */ .navbar { background-color: transparent; width: 100%; } .navbar * { color: #70705C; } .navbar a { text-decoration: underline; } .navbar td { padding: 0.2em; } .navbar-bottom { margin-top: 2em; } .footer { font-style: italic; font-size: small; } /* Nav sidebar * * ----------- */ .nav-sidebar { margin: 2em; background-color: transparent; float: right; border-style: solid; border-width: 1px; border-color: #000000; width: 20%; } .nav-sidebar .nav-sidebar-td { padding: 1em; } .sphinxsidebar h1 { font-size: medium; font-weight: bold; } .sphinxsidebar h2 { font-size: medium; font-weight: bold; } .sphinxsidebar h3 { font-size: medium; font-weight: bold; } .sphinxsidebar h4 { font-size: medium; font-weight: bold; } .sphinxsidebar h5 { font-size: medium; font-weight: bold; } .sphinxsidebar h6 { font-size: medium; font-weight: bold; } /* Special index page markup * * ------------------------- */ .genindextable td { padding-top: 1em; padding-bottom: 1em; } .genindextable dl { margin: 0; } /* Links * * ----- */ a { color: #33658E; text-decoration: none; } a.headerlink { color: transparent; text-decoration: none; font-size: medium; font-weight: bold; padding: 0.2em; } /* Object references */ a code.xref { font-weight: bold; color: #33658E; background-color: #EFEFE1; text-decoration: none; } /* Footnote references */ a.footnote-reference { font-size: small; } /* Code listings * * ------------- */ code, pre { } code { background-color: #EFEFE1; } code.descname { font-weight: bold; background-color: transparent; } code.descclassname { background-color: transparent; } pre { margin: 0.5em; margin-top: 1.5em; } /* Extra rules for literal blocks wrapped by ``html_rewrite`` */ .-x-quark-literal-block { margin-top: 1em; width: 100%; } .-x-quark-literal-block .-x-quark-literal-block-td { /* Use td for padding on QTextBrowser... */ padding: 0.5em; } .-x-quark-literal-block .-x-quark-literal-block-td:only-child { /* ...disable it again on full browsers... */ padding: 0; } .-x-quark-literal-block-td pre { margin: 0; /* ...and put the padding on the pre instead. */ padding: 0.5em; } /* Code blocks in headings and general links */ h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { background-color: transparent; } a code { background-color: transparent; } /* Regular tables * * -------------- */ table.docutils { margin-top: 2em; } table.docutils td, table.docutils th { padding: 0.3em; } /* Footnotes and citations * * ----------------------- */ table.docutils.footnote, table.docutils.citation { margin: 0; } table.docutils.footnote td, table.docutils.citation td { padding: 0; } table.docutils.footnote td.label, table.docutils.citation td.label { padding-right: 2em; } /* Boxes -- admonitions, sidebars, topics * * -------------------------------------- */ /* This section has good styles for the improved boxes created by * ``html_rewrite`` (the 'boxes') feature and some fallback styles if those are * disabled. */ /* Part 1 -- common styles */ .admonition-title, .sidebar-title, .topic-title { font-weight: bold; } .sidebar-subtitle { font-style: italic; } .admonition > .admonition-title { color: #606060; } .admonition.warning > .admonition-title { color: #C43838; } /* Part 2 -- fallback-specific styles */ .admonition > *, .topic > *, .sidebar > * { margin-left: 3em; margin-right: 5em; } .admonition > .first, .topic > .first, .sidebar > .first { margin-top: 3em; margin-left: 0; margin-right: 5em; } /* Part 3 -- x-quark-box styles */ .-x-quark-box .first { margin-top: 0; margin-left: 0; margin-right: 0; } .-x-quark-box .-x-quark-box-td > div > .last, .-x-quark-box .topic > :last-child { margin-bottom: 0; } .-x-quark-box .-x-quark-box-td > div > * { margin-left: 0; margin-right: 0; } .-x-quark-box { margin-top: 2em; } .-x-quark-box .-x-quark-box-td { padding: 0.5em; } .-x-quark-topic, .-x-quark-sidebar { border-width: 1px; border-style: solid; border-color: #000000; } .-x-quark-topic { width: 100%; } .-x-quark-sidebar { margin-left: 1em; float: right; width: 35%; } .-x-quark-admonition { background-color: #EEEEEE; border-color: #606060; width: 100%; } .-x-quark-admonition.-x-quark-warning { background-color: #FFCCCC; border-color: #C43838; } /* Misc markup * * ----------- */ .rubric { font-weight: bold; } .versionmodified { font-style: italic; } .field-list { margin-top: 0; } .guilabel, .menuselection { background-color: #EFEFE1; } .accelerator { text-decoration: underline; } .caption-text { font-weight: bold; } div.line-block > div.line { margin-top: 0; margin-bottom: 0; } /* Some extra niceties for full browsers * * ------------------------------------------- */ a:hover { text-decoration: underline; } a.headerlink:hover { color: #33658E; text-decoration: none; } .navbar a:hover { color: #33658E; } pre:only-child { /* This gets us nicer literal blocks even without html_rewrite */ margin: 0; margin-top: 1em; padding: 0.5em; }heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/searchtools.js000066400000000000000000000537001526573132500313660ustar00rootroot00000000000000/* * Sphinx JavaScript utilities for the full-text search. */ "use strict"; /** * Simple result scoring code. */ if (typeof Scorer === "undefined") { var Scorer = { // Implement the following function to further tweak the score for each result // The function takes a result array [docname, title, anchor, descr, score, filename] // and returns the new score. /* score: result => { const [docname, title, anchor, descr, score, filename, kind] = result return score }, */ // query matches the full name of an object objNameMatch: 11, // or matches in the last dotted part of the object name objPartialMatch: 6, // Additive scores depending on the priority of the object objPrio: { 0: 15, // used to be importantResults 1: 5, // used to be objectResults 2: -5, // used to be unimportantResults }, // Used when the priority is not in the mapping. objPrioDefault: 0, // query found in title title: 15, partialTitle: 7, // query found in terms term: 5, partialTerm: 2, }; } // Global search result kind enum, used by themes to style search results. // prettier-ignore class SearchResultKind { static get index() { return "index"; } static get object() { return "object"; } static get text() { return "text"; } static get title() { return "title"; } } const _removeChildren = (element) => { while (element && element.lastChild) element.removeChild(element.lastChild); }; /** * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping */ const _escapeRegExp = (string) => string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string const _escapeHTML = (text) => { return text .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); }; const _displayItem = (item, searchTerms, highlightTerms) => { const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; const contentRoot = document.documentElement.dataset.content_root; const [docName, title, anchor, descr, score, _filename, kind] = item; let listItem = document.createElement("li"); // Add a class representing the item's type: // can be used by a theme's CSS selector for styling // See SearchResultKind for the class names. listItem.classList.add(`kind-${kind}`); let requestUrl; let linkUrl; if (docBuilder === "dirhtml") { // dirhtml builder let dirname = docName + "/"; if (dirname.match(/\/index\/$/)) dirname = dirname.substring(0, dirname.length - 6); else if (dirname === "index/") dirname = ""; requestUrl = contentRoot + dirname; linkUrl = requestUrl; } else { // normal html builders requestUrl = contentRoot + docName + docFileSuffix; linkUrl = docName + docLinkSuffix; } let linkEl = listItem.appendChild(document.createElement("a")); linkEl.href = linkUrl + anchor; linkEl.dataset.score = score; linkEl.innerHTML = _escapeHTML(title); if (descr) { listItem.appendChild(document.createElement("span")).innerHTML = ` (${_escapeHTML(descr)})`; // highlight search terms in the description if (SPHINX_HIGHLIGHT_ENABLED) // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted"), ); } else if (showSearchSummary) fetch(requestUrl) .then((responseData) => responseData.text()) .then((data) => { if (data) listItem.appendChild( Search.makeSearchSummary(data, searchTerms, anchor), ); // highlight search terms in the summary if (SPHINX_HIGHLIGHT_ENABLED) // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted"), ); }); Search.output.appendChild(listItem); }; const _finishSearch = (resultCount) => { Search.stopPulse(); Search.title.innerText = _("Search Results"); if (!resultCount) Search.status.innerText = Documentation.gettext( "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.", ); else Search.status.innerText = Documentation.ngettext( "Search finished, found one page matching the search query.", "Search finished, found ${resultCount} pages matching the search query.", resultCount, ).replace("${resultCount}", resultCount); }; const _displayNextItem = ( results, resultCount, searchTerms, highlightTerms, ) => { // results left, load the summary and display it // this is intended to be dynamic (don't sub resultsCount) if (results.length) { _displayItem(results.pop(), searchTerms, highlightTerms); setTimeout( () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), 5, ); } // search finished, update title and status message else _finishSearch(resultCount); }; // Helper function used by query() to order search results. // Each input is an array of [docname, title, anchor, descr, score, filename, kind]. // Order the results by score (in opposite order of appearance, since the // `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. const _orderResultsByScoreThenName = (a, b) => { const leftScore = a[4]; const rightScore = b[4]; if (leftScore === rightScore) { // same score: sort alphabetically const leftTitle = a[1].toLowerCase(); const rightTitle = b[1].toLowerCase(); if (leftTitle === rightTitle) return 0; return leftTitle > rightTitle ? -1 : 1; // inverted is intentional } return leftScore > rightScore ? 1 : -1; }; /** * Default splitQuery function. Can be overridden in ``sphinx.search`` with a * custom function per language. * * The regular expression works by splitting the string on consecutive characters * that are not Unicode letters, numbers, underscores, or emoji characters. * This is the same as ``\W+`` in Python, preserving the surrogate pair area. */ if (typeof splitQuery === "undefined") { var splitQuery = (query) => query .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) .filter((term) => term); // remove remaining empty strings } /** * Search Module */ const Search = { _index: null, _queued_query: null, _pulse_status: -1, htmlToText: (htmlString, anchor) => { const htmlElement = new DOMParser().parseFromString( htmlString, "text/html", ); for (const removalQuery of [".headerlink", "script", "style"]) { htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove(); }); } if (anchor) { const anchorContent = htmlElement.querySelector( `[role="main"] ${anchor}`, ); if (anchorContent) return anchorContent.textContent; console.warn( `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.`, ); } // if anchor not specified or not found, fall back to main content const docContent = htmlElement.querySelector('[role="main"]'); if (docContent) return docContent.textContent; console.warn( "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template.", ); return ""; }, init: () => { const query = new URLSearchParams(window.location.search).get("q"); document .querySelectorAll('input[name="q"]') .forEach((el) => (el.value = query)); if (query) Search.performSearch(query); }, loadIndex: (url) => (document.body.appendChild(document.createElement("script")).src = url), setIndex: (index) => { Search._index = index; if (Search._queued_query !== null) { const query = Search._queued_query; Search._queued_query = null; Search.query(query); } }, hasIndex: () => Search._index !== null, deferQuery: (query) => (Search._queued_query = query), stopPulse: () => (Search._pulse_status = -1), startPulse: () => { if (Search._pulse_status >= 0) return; const pulse = () => { Search._pulse_status = (Search._pulse_status + 1) % 4; Search.dots.innerText = ".".repeat(Search._pulse_status); if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); }; pulse(); }, /** * perform a search for something (or wait until index is loaded) */ performSearch: (query) => { // create the required interface elements const searchText = document.createElement("h2"); searchText.textContent = _("Searching"); const searchSummary = document.createElement("p"); searchSummary.classList.add("search-summary"); searchSummary.innerText = ""; const searchList = document.createElement("ul"); searchList.setAttribute("role", "list"); searchList.classList.add("search"); const out = document.getElementById("search-results"); Search.title = out.appendChild(searchText); Search.dots = Search.title.appendChild(document.createElement("span")); Search.status = out.appendChild(searchSummary); Search.output = out.appendChild(searchList); const searchProgress = document.getElementById("search-progress"); // Some themes don't use the search progress node if (searchProgress) { searchProgress.innerText = _("Preparing search..."); } Search.startPulse(); // index already loaded, the browser was quick! if (Search.hasIndex()) Search.query(query); else Search.deferQuery(query); }, _parseQuery: (query) => { // stem the search terms and add them to the correct list const stemmer = new Stemmer(); const searchTerms = new Set(); const excludedTerms = new Set(); const highlightTerms = new Set(); const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); splitQuery(query.trim()).forEach((queryTerm) => { const queryTermLower = queryTerm.toLowerCase(); // maybe skip this "word" // stopwords set is from language_data.js if (stopwords.has(queryTermLower) || queryTerm.match(/^\d+$/)) return; // stem the word let word = stemmer.stemWord(queryTermLower); // select the correct list if (word[0] === "-") excludedTerms.add(word.substr(1)); else { searchTerms.add(word); highlightTerms.add(queryTermLower); } }); if (SPHINX_HIGHLIGHT_ENABLED) { // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js localStorage.setItem( "sphinx_highlight_terms", [...highlightTerms].join(" "), ); } // console.debug("SEARCH: searching for:"); // console.info("required: ", [...searchTerms]); // console.info("excluded: ", [...excludedTerms]); return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; }, /** * execute search (requires search index to be loaded) */ _performSearch: ( query, searchTerms, excludedTerms, highlightTerms, objectTerms, ) => { const filenames = Search._index.filenames; const docNames = Search._index.docnames; const titles = Search._index.titles; const allTitles = Search._index.alltitles; const indexEntries = Search._index.indexentries; // Collect multiple result groups to be sorted separately and then ordered. // Each is an array of [docname, title, anchor, descr, score, filename, kind]. const normalResults = []; const nonMainIndexResults = []; _removeChildren(document.getElementById("search-progress")); const queryLower = query.toLowerCase().trim(); for (const [title, foundTitles] of Object.entries(allTitles)) { if ( title.toLowerCase().trim().includes(queryLower) && queryLower.length >= title.length / 2 ) { for (const [file, id] of foundTitles) { const score = Math.round( (Scorer.title * queryLower.length) / title.length, ); const boost = titles[file] === title ? 1 : 0; // add a boost for document titles normalResults.push([ docNames[file], titles[file] !== title ? `${titles[file]} > ${title}` : title, id !== null ? "#" + id : "", null, score + boost, filenames[file], SearchResultKind.title, ]); } } } // search for explicit entries in index directives for (const [entry, foundEntries] of Object.entries(indexEntries)) { if (entry.includes(queryLower) && queryLower.length >= entry.length / 2) { for (const [file, id, isMain] of foundEntries) { const score = Math.round((100 * queryLower.length) / entry.length); const result = [ docNames[file], titles[file], id ? "#" + id : "", null, score, filenames[file], SearchResultKind.index, ]; if (isMain) { normalResults.push(result); } else { nonMainIndexResults.push(result); } } } } // lookup as object objectTerms.forEach((term) => normalResults.push(...Search.performObjectSearch(term, objectTerms)), ); // lookup as search terms in fulltext normalResults.push( ...Search.performTermsSearch(searchTerms, excludedTerms), ); // let the scorer override scores with a custom scoring function if (Scorer.score) { normalResults.forEach((item) => (item[4] = Scorer.score(item))); nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); } // Sort each group of results by score and then alphabetically by name. normalResults.sort(_orderResultsByScoreThenName); nonMainIndexResults.sort(_orderResultsByScoreThenName); // Combine the result groups in (reverse) order. // Non-main index entries are typically arbitrary cross-references, // so display them after other results. let results = [...nonMainIndexResults, ...normalResults]; // remove duplicate search results // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept let seen = new Set(); results = results.reverse().reduce((acc, result) => { let resultStr = result .slice(0, 4) .concat([result[5]]) .map((v) => String(v)) .join(","); if (!seen.has(resultStr)) { acc.push(result); seen.add(resultStr); } return acc; }, []); return results.reverse(); }, query: (query) => { const [ searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms, ] = Search._parseQuery(query); const results = Search._performSearch( searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms, ); // for debugging //Search.lastresults = results.slice(); // a copy // console.info("search results:", Search.lastresults); // print the results _displayNextItem(results, results.length, searchTerms, highlightTerms); }, /** * search for object names */ performObjectSearch: (object, objectTerms) => { const filenames = Search._index.filenames; const docNames = Search._index.docnames; const objects = Search._index.objects; const objNames = Search._index.objnames; const titles = Search._index.titles; const results = []; const objectSearchCallback = (prefix, match) => { const name = match[4]; const fullname = (prefix ? prefix + "." : "") + name; const fullnameLower = fullname.toLowerCase(); if (fullnameLower.indexOf(object) < 0) return; let score = 0; const parts = fullnameLower.split("."); // check for different match types: exact matches of full name or // "last name" (i.e. last dotted part) if (fullnameLower === object || parts.slice(-1)[0] === object) score += Scorer.objNameMatch; else if (parts.slice(-1)[0].indexOf(object) > -1) score += Scorer.objPartialMatch; // matches in last name const objName = objNames[match[1]][2]; const title = titles[match[0]]; // If more than one term searched for, we require other words to be // found in the name/title/description const otherTerms = new Set(objectTerms); otherTerms.delete(object); if (otherTerms.size > 0) { const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); if ( [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) ) return; } let anchor = match[3]; if (anchor === "") anchor = fullname; else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; const descr = objName + _(", in ") + title; // add custom score for some objects according to scorer if (Scorer.objPrio.hasOwnProperty(match[2])) score += Scorer.objPrio[match[2]]; else score += Scorer.objPrioDefault; results.push([ docNames[match[0]], fullname, "#" + anchor, descr, score, filenames[match[0]], SearchResultKind.object, ]); }; Object.keys(objects).forEach((prefix) => objects[prefix].forEach((array) => objectSearchCallback(prefix, array)), ); return results; }, /** * search for full-text terms in the index */ performTermsSearch: (searchTerms, excludedTerms) => { // prepare search const terms = Search._index.terms; const titleTerms = Search._index.titleterms; const filenames = Search._index.filenames; const docNames = Search._index.docnames; const titles = Search._index.titles; const scoreMap = new Map(); const fileMap = new Map(); // perform the search on the required terms searchTerms.forEach((word) => { const files = []; // find documents, if any, containing the query word in their text/title term indices // use Object.hasOwnProperty to avoid mismatching against prototype properties const arr = [ { files: terms.hasOwnProperty(word) ? terms[word] : undefined, score: Scorer.term, }, { files: titleTerms.hasOwnProperty(word) ? titleTerms[word] : undefined, score: Scorer.title, }, ]; // add support for partial matches if (word.length > 2) { const escapedWord = _escapeRegExp(word); if (!terms.hasOwnProperty(word)) { Object.keys(terms).forEach((term) => { if (term.match(escapedWord)) arr.push({ files: terms[term], score: Scorer.partialTerm }); }); } if (!titleTerms.hasOwnProperty(word)) { Object.keys(titleTerms).forEach((term) => { if (term.match(escapedWord)) arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); }); } } // no match but word was a required one if (arr.every((record) => record.files === undefined)) return; // found search word in contents arr.forEach((record) => { if (record.files === undefined) return; let recordFiles = record.files; if (recordFiles.length === undefined) recordFiles = [recordFiles]; files.push(...recordFiles); // set score for the word in each file recordFiles.forEach((file) => { if (!scoreMap.has(file)) scoreMap.set(file, new Map()); const fileScores = scoreMap.get(file); fileScores.set(word, record.score); }); }); // create the mapping files.forEach((file) => { if (!fileMap.has(file)) fileMap.set(file, [word]); else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); }); }); // now check if the files don't contain excluded terms const results = []; for (const [file, wordList] of fileMap) { // check if all requirements are matched // as search terms with length < 3 are discarded const filteredTermCount = [...searchTerms].filter( (term) => term.length > 2, ).length; if ( wordList.length !== searchTerms.size && wordList.length !== filteredTermCount ) continue; // ensure that none of the excluded terms is in the search result if ( [...excludedTerms].some( (term) => terms[term] === file || titleTerms[term] === file || (terms[term] || []).includes(file) || (titleTerms[term] || []).includes(file), ) ) break; // select one (max) score for the file. const score = Math.max(...wordList.map((w) => scoreMap.get(file).get(w))); // add result to the result list results.push([ docNames[file], titles[file], "", null, score, filenames[file], SearchResultKind.text, ]); } return results; }, /** * helper function to return a node containing the * search summary for a given text. keywords is a list * of stemmed words. */ makeSearchSummary: (htmlText, keywords, anchor) => { const text = Search.htmlToText(htmlText, anchor); if (text === "") return null; const textLower = text.toLowerCase(); const actualStartPosition = [...keywords] .map((k) => textLower.indexOf(k.toLowerCase())) .filter((i) => i > -1) .slice(-1)[0]; const startWithContext = Math.max(actualStartPosition - 120, 0); const top = startWithContext === 0 ? "" : "..."; const tail = startWithContext + 240 < text.length ? "..." : ""; let summary = document.createElement("p"); summary.classList.add("context"); summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; return summary; }, }; _ready(Search.init); heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/_static/sphinx_highlight.js000066400000000000000000000123151526573132500323750ustar00rootroot00000000000000/* Highlighting utilities for Sphinx HTML documentation. */ "use strict"; const SPHINX_HIGHLIGHT_ENABLED = true; /** * highlight a given string on a node by wrapping it in * span elements with the given class name. */ const _highlight = (node, addItems, text, className) => { if (node.nodeType === Node.TEXT_NODE) { const val = node.nodeValue; const parent = node.parentNode; const pos = val.toLowerCase().indexOf(text); if ( pos >= 0 && !parent.classList.contains(className) && !parent.classList.contains("nohighlight") ) { let span; const closestNode = parent.closest("body, svg, foreignObject"); const isInSVG = closestNode && closestNode.matches("svg"); if (isInSVG) { span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); } else { span = document.createElement("span"); span.classList.add(className); } span.appendChild(document.createTextNode(val.substr(pos, text.length))); const rest = document.createTextNode(val.substr(pos + text.length)); parent.insertBefore(span, parent.insertBefore(rest, node.nextSibling)); node.nodeValue = val.substr(0, pos); /* There may be more occurrences of search term in this node. So call this * function recursively on the remaining fragment. */ _highlight(rest, addItems, text, className); if (isInSVG) { const rect = document.createElementNS( "http://www.w3.org/2000/svg", "rect", ); const bbox = parent.getBBox(); rect.x.baseVal.value = bbox.x; rect.y.baseVal.value = bbox.y; rect.width.baseVal.value = bbox.width; rect.height.baseVal.value = bbox.height; rect.setAttribute("class", className); addItems.push({ parent: parent, target: rect }); } } } else if (node.matches && !node.matches("button, select, textarea")) { node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); } }; const _highlightText = (thisNode, text, className) => { let addItems = []; _highlight(thisNode, addItems, text, className); addItems.forEach((obj) => obj.parent.insertAdjacentElement("beforebegin", obj.target), ); }; /** * Small JavaScript module for the documentation. */ const SphinxHighlight = { /** * highlight the search words provided in localstorage in the text */ highlightSearchWords: () => { if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight // get and clear terms from localstorage const url = new URL(window.location); const highlight = localStorage.getItem("sphinx_highlight_terms") || url.searchParams.get("highlight") || ""; localStorage.removeItem("sphinx_highlight_terms"); // Update history only if '?highlight' is present; otherwise it // clears text fragments (not set in window.location by the browser) if (url.searchParams.has("highlight")) { url.searchParams.delete("highlight"); window.history.replaceState({}, "", url); } // get individual terms from highlight string const terms = highlight .toLowerCase() .split(/\s+/) .filter((x) => x); if (terms.length === 0) return; // nothing to do // There should never be more than one element matching "div.body" const divBody = document.querySelectorAll("div.body"); const body = divBody.length ? divBody[0] : document.querySelector("body"); window.setTimeout(() => { terms.forEach((term) => _highlightText(body, term, "highlighted")); }, 10); const searchBox = document.getElementById("searchbox"); if (searchBox === null) return; searchBox.appendChild( document .createRange() .createContextualFragment( '", ), ); }, /** * helper function to hide the search marks again */ hideSearchWords: () => { document .querySelectorAll("#searchbox .highlight-link") .forEach((el) => el.remove()); document .querySelectorAll("span.highlighted") .forEach((el) => el.classList.remove("highlighted")); localStorage.removeItem("sphinx_highlight_terms"); }, initEscapeListener: () => { // only install a listener if it is really needed if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; document.addEventListener("keydown", (event) => { // bail for input elements if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; // bail with special keys if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; if ( DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && event.key === "Escape" ) { SphinxHighlight.hideSearchWords(); event.preventDefault(); } }); }, }; _ready(() => { /* Do not call highlightSearchWords() when we are on the search page. * It will highlight words from the *previous* search query. */ if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); SphinxHighlight.initEscapeListener(); }); heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/contents.html000066400000000000000000000206731526573132500276020ustar00rootroot00000000000000 Table of Contents heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/genindex.html000066400000000000000000000474411526573132500275500ustar00rootroot00000000000000 Index

Index

A | B | C | D | E | F | G | H | I | J | L | M | N | O | P | R | S | T | U | V | X | Π | ℯ

A

abs() (function) absdev() (function) and() (function) arccos() (function) arcosh() (function) arcsin() (function)
arctan() (function) arctan2() (function) arsinh() (function) artanh() (function) average() (function)

B

bin() (function) binomcdf() (function) binommean() (function)
binompmf() (function) binomvar() (function) binpad() (function)

C

cbrt() (function) ceil() (function) cis() (function) cisform() (function) cols() (function) conj() (function) corrp() (function) corrs() (function)
cos() (function) cosh() (function) cot() (function) count() (function) covp() (function) covs() (function) cross() (function) csc() (function)

D

datetime() (function) dec() (function) degrees() (function)
det() (function) dms() (function) dot() (function)

E

e (constant) emod() (function) eng() (function) epoch() (function)
erf() (function) erfc() (function) exp() (function) expform() (function)

F

flatten() (function) floor() (function)
frac() (function)

G

gamma() (function) gcd() (function)
geomean() (function) gradians() (function)

H

hex() (function) hexpad() (function) hypercdf() (function)
hypermean() (function) hyperpmf() (function) hypervar() (function)

I

i (constant) idiv() (function) ieee754_decode() (function) ieee754_double_decode() (function) ieee754_double_encode() (function) ieee754_double_residual() (function) ieee754_encode() (function) ieee754_float_residual() (function) ieee754_half_decode() (function) ieee754_half_encode() (function) ieee754_half_residual() (function) ieee754_quad_decode() (function)
ieee754_quad_encode() (function) ieee754_quad_residual() (function) ieee754_round_double() (function) ieee754_round_float() (function) ieee754_round_half() (function) ieee754_round_quad() (function) ieee754_single_decode() (function) ieee754_single_encode() (function) imag() (function) int() (function) inv() (function)

J

j (constant)

L

lcm() (function) ln() (function) lngamma() (function)
log() (function) log10() (function) log2() (function)

M

mad() (function) mask() (function) mass() (function) max() (function) mean() (function)
median() (function) min() (function) mod() (function) molarity() (function) molmass() (function)

N

ncr() (function) norm() (function) not() (function)
npr() (function) numval() (function)

O

oct() (function) octpad() (function)
or() (function)

P

phase() (function) phasorform() (function) pi (constant) poicdf() (function) poimean() (function)
poipmf() (function) poivar() (function) popcount() (function) powmod() (function) product() (function)

R

radians() (function) rand() (function) randint() (function), [1] rank() (function) rat() (function) ratio() (function) rational() (function)
real() (function) rectform() (function) root() (function) round() (function) roundeven() (function) rows() (function)

S

sci() (function) sec() (function) sgn() (function) shape() (function) shl() (function) shr() (function) sin() (function)
sinh() (function) SpeedCrunch sqrt() (function) stdevp() (function) stdevs() (function) sum() (function) summation() (function)

T

tan() (function) tanh() (function) trace() (function) transpose() (function)
trigform() (function) trunc() (function) turns() (function)

U

unmask() (function)

V

varp() (function)
vars() (function)

X

xor() (function)

Π

Ï€ (constant)

ℯ

ℯ (constant)
heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/introduction.html000066400000000000000000000107721526573132500304650ustar00rootroot00000000000000 Introduction

Introduction

Welcome to the SpeedCrunch manual! SpeedCrunch is a high-precision scientific desktop calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard. Some distinctive features are auto-completion of functions and variables, a formula book, and quick insertion of constants from various fields of knowledge. It is available for Windows, macOS, and Linux in a number of languages. We hope you have fun with SpeedCrunch!

This documentation is divided into two major parts:

  • The User Guide serves as a user manual that can be read from beginning to end. It presents all the features of SpeedCrunch and how to use them effectively.

  • The Reference documents all the built-in functions, constants, and units that are included with SpeedCrunch. It’s not intended to be read page by page, but it is still very useful to look up how a particular function is used.

For a complete overview, see the full table of contents.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/manual-en_US.qch000066400000000000000000006500001526573132500300310ustar00rootroot00000000000000SQLite format 3@ 5 .•Ì  o–«A ž $ § › 3 ½ ? É oX''qtableMetaDataTableMetaDataTableCREATE TABLE MetaDataTable(Name Text, Value BLOB )t ##�/tableFolderTableFolderTableCREATE TABLE FolderTable(Id INTEGER PRIMARY KEY, Name Text, NamespaceID INTEGER )| ''�7tableFileNameTableFileNameTable CREATE TABLE FileNameTable (FolderId INTEGER, Name TEXT, FileId INTEGER, Title TEXT )t ++�tableFileFilterTableFileFilterTable CREATE TABLE FileFilterTable (FilterAttributeId INTEGER, FileId INTEGER )f ''� tableFileDataTableFileDataTable CREATE TABLE FileDataTable (Id INTEGER PRIMARY KEY, Data BLOB )� 77�#tableFileAttributeSetTableFileAttributeSetTable CREATE TABLE FileAttributeSetTable (Id INTEGER, FilterAttributeId INTEGER )�33�/tableContentsFilterTableContentsFilterTable CREATE TABLE ContentsFilterTable (FilterAttributeId INTEGER, ContentsId INTEGER ){''�5tableContentsTableContentsTableCREATE TABLE ContentsTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Data BLOB )x--�#tableIndexFilterTableIndexFilterTableCREATE TABLE IndexFilterTable (FilterAttributeId INTEGER, IndexId INTEGER )� !!‚ tableIndexTableIndexTableCREATE TABLE IndexTable (Id INTEGER PRIMARY KEY, Name TEXT, Identifier TEXT, NamespaceId INTEGER, FileId INTEGER, Anchor TEXT )h##�tableFilterTableFilterTableCREATE TABLE FilterTable (NameId INTEGER, FilterAttributeId INTEGER )l++�tableFilterNameTableFilterNameTableCREATE TABLE FilterNameTable (Id INTEGER PRIMARY KEY, Name TEXT ){55�tableFilterAttributeTableFilterAttributeTableCREATE TABLE FilterAttributeTable (Id INTEGER PRIMARY KEY, Name TEXT )h))� tableNamespaceTableNamespaceTableCREATE TABLE NamespaceTable (Id INTEGER PRIMARY KEY,Name TEXT ) ááAorg.sphinx.manual-enus.1.1 çïç1.1%manual-en_US ìì+SpeedCrunch 1.1 õûõ  õ5ûõ ÔŸg2 ý Å ™ ^ å ª u F  ë ³ „ U # ñ Å – j 8 Ú ¨ | A ݱ…Y5Ú¨|M!é±PòºSã¥j/ Ü�-Ëc±Uù—`GQI =ieee754_half_residual() (function)function.ieee754_half_residualsc.ieee754_half_residualZFME 9ieee754_half_encode() (function)function.ieee754_half_encodesc.ieee754_half_encodeZEME 9ieee754_half_decode() (function)function.ieee754_half_decodesc.ieee754_half_decodecDSK ?ieee754_float_residual() (function)function.ieee754_float_residualsc.ieee754_float_residualKCC; /ieee754_encode() (function)function.ieee754_encodesc.ieee754_encodefBUM Aieee754_double_residual() (function)function.ieee754_double_residualsc.ieee754_double_residual`AQI =ieee754_double_encode() (function)function.ieee754_double_encodesc.ieee754_double_encode`@QI =ieee754_double_decode() (function)function.ieee754_double_decodesc.ieee754_double_decodeK?C; /ieee754_decode() (function)function.ieee754_decodesc.ieee754_decode->/' idiv() (function)function.idivsc.idiv"=%! i (constant)constant.isc.i9<7/ #hypervar() (function)function.hypervarsc.hypervar9;7/ #hyperpmf() (function)function.hyperpmfsc.hyperpmf<:91 %hypermean() (function)function.hypermeansc.hypermean997/ #hypercdf() (function)function.hypercdfsc.hypercdf383+ hexpad() (function)function.hexpadsc.hexpad*7-% hex() (function)function.hexsc.hex967/ #gradians() (function)function.gradianssc.gradians655- !geomean() (function)function.geomeansc.geomean*4-% gcd() (function)function.gcdsc.gcd031) gamma() (function)function.gammasc.gamma-2/' frac() (function)function.fracsc.frac011) floor() (function)function.floorsc.floor605- !flatten() (function)function.flattensc.flatten6/5- !expform() (function)function.expformsc.expform*.-% exp() (function)function.expsc.exp--/' erfc() (function)function.erfcsc.erfc*,-% erf() (function)function.erfsc.erf0+1) epoch() (function)function.epochsc.epoch**-% eng() (function)function.engsc.eng-)/' emod() (function)function.emodsc.emod"(%! e (constant)constant.esc.e*'-% dot() (function)function.dotsc.dot*&-% dms() (function)function.dmssc.dms*%-% det() (function)function.detsc.det6$5- !degrees() (function)function.degreessc.degrees*#-% dec() (function)function.decsc.dec9"7/ #datetime() (function)function.datetimesc.datetime*!-% csc() (function)function.cscsc.csc0 1) cross() (function)function.crosssc.cross-/' covs() (function)function.covssc.covs-/' covp() (function)function.covpsc.covp01) count() (function)function.countsc.count*-% cot() (function)function.cotsc.cot-/' cosh() (function)function.coshsc.cosh*-% cos() (function)function.cossc.cos01) corrs() (function)function.corrssc.corrs01) corrp() (function)function.corrpsc.corrp-/' conj() (function)function.conjsc.conj-/' cols() (function)function.colssc.cols65- !cisform() (function)function.cisformsc.cisform*-% cis() (function)function.cissc.cis-/' ceil() (function)function.ceilsc.ceil-/' cbrt() (function)function.cbrtsc.cbrt33+ binpad() (function)function.binpadsc.binpad97/ #binomvar() (function)function.binomvarsc.binomvar97/ #binompmf() (function)function.binompmfsc.binompmf<91 %binommean() (function)function.binommeansc.binommean9 7/ #binomcdf() (function)function.binomcdfsc.binomcdf* -% bin() (function)function.binsc.bin6 5- !average() (function)function.averagesc.average3 3+ artanh() (function)function.artanhsc.artanh3 3+ arsinh() (function)function.arsinhsc.arsinh65- !arctan2() (function)function.arctan2sc.arctan233+ arctan() (function)function.arctansc.arctan33+ arcsin() (function)function.arcsinsc.arcsin33+ arcosh() (function)function.arcoshsc.arcosh33+ arccos() (function)function.arccossc.arccos*-% and() (function)function.andsc.and33+ absdev() (function)function.absdevsc.absdev*-% abs() (function)function4�3G <ûõïèâÛÕÎÈÁ»´®§¡š”�‡€zsmf`YSLF?92,% þøñëäÞ×ÑÊĽ·°ª£�–�‰ƒ|voib\UOHB;5.(! ú ô í ç à Ú Ó Í Æ À ¹ ³ ¬ ¦ Ÿ ™ ’ Œ …  x r k e ^ X Q K D > 7 1 * $     ý ö ð é ã Ü Ö Ï É Á º ² « £ œ ” � … ~ v o g ` X Q I B : 3 + $    þ ÷ ï è à Ù Ñ Ê Â » ³ ¬ ¤ � • Ž †  w p h a Y R J C ; 4 , %     ÿ ø ð é á Ú Ò Ë Ã ¼ ´ ­ ¥ ž – � ‡ € x q i b Z S K D < 5 - &     ù ñ ê â Û Ó Ì Ä ½ µ ® ¦ Ÿ — � ˆ � y r j c [ T L E = 6 . '    ÿ÷îæÝÕÌÄ»³ª¢™‘ˆ€wof^UMD<3+" øïçÞÖÍż´«£š’‰�xpg_VNE=4,# ‚<ž‚; ž‚:�‚9 �‚8œ‚7 œ‚6›‚5 ›‚4š‚3 š‚2™‚1 ™‚0˜‚/ ˜‚.—‚- —‚,–‚+ –‚*•‚) •‚(”‚' ”‚&“‚% “‚$’‚# ’‚"‘‚! ‘‚ �‚ �‚�‚ �‚Ž‚ Ž‚�‚ �‚Œ‚ Œ‚‹‚ ‹‚Š‚ Š‚‰‚ ‰‚ˆ‚ ˆ‚‡‚  ‡‚ †‚  †‚ …‚  …‚„‚ „‚ƒ‚ ƒ‚‚‚ ‚‚�‚ �‚€� €�~�} �|~�{ ~�z}�y }�x|�w |�v{�u {�tz�s z�ry�q y�px�o x�nw�m w�lv�k v�ju�i u�ht�g t�fs�e s�dr�c r�bq�a q�`p�_ p�^o�] o�\n�[ n�Zm�Y m�Xl�W l�Vk�U k�Tj�S j�Ri�Q i�Ph�O h�Ng�M g�Lf�K f�Je�I e�Hd�G d�Fc�E c�Db�C b�Ba�A a�@`�? `�>_�= _�<^�; ^�:]�9 ]�8\�7 \�6[�5 [�4Z�3 Z�2Y�1 Y�0X�/ X�.W�- W�,V�+ V�*U�) U�(T�' T�&S�% S�$R�# R�"Q�! Q� P� P�O� O�N� N�M� M�L� L�K� K�J� J�I� I�H� H�G�  G� F�  F� E�  E�D� D�C� C�B� B�A� A�@ @~?} ?|>{ >z=y =x<w <v;u ;t:s :r9q 9p8o 8n7m 7l6k 6j5i 5h4g 4f3e 3d2c 2b1a 1`0_ 0^/] /\.[ .Z-Y -X,W ,V+U +T*S *R)Q )P(O (N'M 'L&K &J%I %H$G $F#E #D"C "B!A !@ ?  >= <; :9 87 65 43 21 0/ .- ,+ *) (' &% $# "!                                  ËËð" �àDcontents.html:SpeedCrunch 1.1 documentation"introduction.htmlIntroduction(userguide/index.htmlUser Guide6userguide/installation.htmlInstallationZuserguide/installation.html#microsoft-windows"Microsoft WindowsBuserguide/installation.html#macos macOSBuserguide/installation.html#linux Linuxbuserguide/installation.html#distribution-packages*Distribution PackagesFuserguide/installation.html#flatpakFlatpak`userguide/installation.html#building-from-source(Building from Source4userguide/first_steps.htmlFirst Steps*userguide/syntax.html SyntaxJuserguide/syntax.html#number-notationNumber NotationDuserguide/syntax.html#decimal-formDecimal Form^userguide/syntax.html#digit-grouping-separators2Digit Grouping SeparatorsRuserguide/syntax.html#scientific-notation&Scientific NotationNuserguide/syntax.html#non-decimal-bases"Non-Decimal BasesPuserguide/syntax.html#sexagesimal-values$Sexagesimal Values<userguide/syntax.html#commentsComments\userguide/syntax.html#0 õûõ  õûõ  ¡/ûöñìçâÝØÓÎÉÄ¿ºµ°«¦¡�n›`!»xœíZ_sÛ6 ϧà˜[o»«ì$ݺu³µ[ÒtËþ¤½9ÝnO=Z‚l®’¨‘”“ìöá�”L§vÚ®Ö[s—ˆ)üA0“Ož>?»úóÅ9[ÚªL&ôd¥¨SuòrÆY.¬H2U[¨í+­”�òј§ŒM– rj`³+X¶Úhm‘|ÍÙ8î¬ES¾’pÝ(m9 ,§üZæv9Ía%3HÜËC&ki¥(“‰¦Ç£#böá|œHAÖî³S­® 0»6kò3ÝÖÙ’U¢nEù r0V”¥°RÕ²ÉZÿÂlk•Fææ!ƒ›Fƒ1D5·µ7„lA"†±²^à°J þ‘ȆC|�޲ Hm uÎZ”ÙŒxP4“iÙÐH'½·¨•¶„ôJÌK`ª`g^3û?¨”õk¦¡œrcoK0K´—½m�­…;ÎŒál©¡˜òW(Ê5nnqaßw«éQ1‡â‹¯¢¹ü?Lÿn…~8Î�æ'_?~Tlã(ën�é0åþͳZ@ízGä Û¾­;úÔj•·™·šç #ÚN.±Nþ3ôõ7´óÓ0;ÿŸÌU~ë–ƒuÓ‘•”G¬æB3ÿH¬j¸su¶9ó^Ë¿<ú4 @²ˆ˜$ÒBźFrÄà üñò4öÛãÑ1ËUÖÒ,:?�ŒE@Û¼÷Ÿœ‰R.ê)×r±DeïMãÅèÉq$Ûiàx̶™‰ûE–á z ·S~ÉSšÍ^p÷ó/{±N¶ˆe²¤[j‘míYżãÅ#Ò~±þ¡mjÓ�·óÔ 1J¼)Kd¨ ž:.BD�~ʱ¡»y)¶ý€\®:É;¯Y;À–Îk-š4�Œ°1ŽgZ‘•�õÆ@ïý¼™eŽkŠ„ITÑm0ÇO–ÇÛ"Rb$«2«#½—ƒhÕ¨¶Î‰C‹{®ê»CËcžÆ3U€†#´‹Õµ(w‡Š4ö[2÷d\ÊÂh èE+sGŽ�¾D*û�Èd—'ï�±ÞÅz�Ö¤{Á}0Øa%3­Œ*,îËuŽû-OíHìOºßªûBd �ññ|68n)í O¡Çà`óV–9¦I¡U•Õê xz¨Œ¨l樑(c7ß;Åzo+¤6w|hLð°gDa3¢Üo‚÷ÆòIV€™¹—ýºppX·ÕtR+¿ŸòôÒØ¥Zo°{œÞcZå£âYh ¦0Š LiM‚Yh‚ m9}ÎÓç]�ËO_ô=ÃjÞ”p“xã{�yã›Yä+�#ò($'O¡�5äìw�?nM˜´wé‚7ÊKJÚ÷ëƒr®:džöBìÙþ›€Dï3'¶¦gq44{›$ëBéÊ­âÄ�&si“ù­Úû>$cŸaç˜:?Þð� Èèwí°o‡ï�ªqrÑ÷�ÄX‡xìX)ú‡oì}«Ü@3þŒž`Ö‚œ¨iAÍÂÙ³Îâˆ>¬,�–+a! 2¡/<…iÆ_—,È%÷¤a[Mö8_—3Î]{ú†•IVTÒIP4ªì¤îu|î^‡ö _£!_ð­añ–P6<ýÿ‹ƒÇĹ:OÌm˜µ´Ô~46ëhÆ–àÞ¯þ2øÇdTþêÒ¶àa?Íž_²™ëÙs·úзQ‚5蓘]¨˜?ÒÚº¤Ç€§ #l1÷ч3övØaM½s‡¡D,$&E˜(´c— <•?��{ÚŽI‹¼c9¡ïÙ('üÖQ÷QMØ᎞6‘uœ)žÚ�lñ}m ?FfAÃSj³_…]î97�µµ°½.Ñ{€sú-;•öZ`ßki—X”e(1\-ݸ»ƒ.‚®)Ã)_}ùE§üùùy‚¯[áöɶzYABçÀÐܯOõAÓM˜Á|ãij7ÅümRHìÝ1†Ü3Q«šGþs·†±+6…v.WôE\lÆå\ÔHfàskN«®ž{á;öU8»º‚n[vÊé'©�NšwRs³ŒžN &ô=?›3üMp ­ZW&§þÔëÚ¬WÉ»¢m¿I¸uóFa;|0koσ�zy\ðÎJšJïa¢Q1aóå-ß÷Íû.¯æÊZU}¼¿º÷þêã•Õî+«÷¾¥Š|ÌOv¦JZ?»úóÅ9[ÚªL&ôd¥¨SuòrÆY.¬H2U[¨í+­”�òј§ŒM– rj`³+X¶Úhm‘|ÍÙ8î¬ES¾’pÝ(m9 ,§üZæv9Ía%3HÜËC&ki¥(“‰¦Ç£#böá|œHAÖî³S­® 0»6kò3ÝÖÙ’U¢nEù r0V”¥°RÕ²ÉZÿÂlk•Fææ!ƒ›Fƒ1D5·µ7„lA"†±²^à°J þ‘ȆC|�޲ Hm uÎZ”ÙŒxP4“iÙÐH'½·¨•¶„ôJÌK`ª`g^3û?¨”õk¦¡œrcoK0K´—½m�­…;ÎŒál©¡˜òW(Ê5nnqaßw«éQ1‡â‹¯¢¹ü?Lÿn…~8Î�æ'_?~Tlã(ën�é0åþͳZ@ízGä Û¾­;úÔj•·™·šç #ÚN.±Nþ3ôõ7´óÓ0;ÿŸÌU~ë–ƒuÓ‘•”G¬æB3ÿH¬j¸su¶9ó^Ë¿<ú4 @²ˆ˜$ÒBźFrÄà üñò4öÛãÑ1ËUÖÒ,:?�ŒE@Û¼÷Ÿœ‰R.ê)×r±DeïMãÅèÉq$Ûiàx̶™‰ûE–á z ·S~ÉSšÍ^p÷ó/{±N¶ˆe²¤[j‘míYżãÅ#Ò~±þ¡mjÓ�·óÔ 1J¼)Kd¨ ž:.BD�~ʱ¡»y)¶ý€\®:É;¯Y;À–Îk-š4�Œ°1ŽgZ‘•�õÆ@ïý¼™eŽkŠ„ITÑm0ÇO–ÇÛ"Rb$«2«#½—ƒhÕ¨¶Î‰C‹{®ê»CËcžÆ3U€†#´‹Õµ(w‡Š4ö[2÷d\ÊÂh èE+sGŽ�¾D*û�Èd—'ï�±ÞÅz�Ö¤{Á}0Øa%3­Œ*,îËuŽû-OíHìOºßªûBd �ññ|68n)í O¡Çà`óV–9¦I¡U•Õê xz¨Œ¨l樑(c7ß;Åzo+¤6w|hLð°gDa3¢Üo‚÷ÆòIV€™¹—ýºppX·ÕtR+¿ŸòôÒØ¥Zo°{œÞcZå£âYh ¦0Š LiM‚Yh‚ m9}ÎÓç]�ËO_ô=ÃjÞ”p“xã{�yã›Yä+�#ò($'O¡�5äìw�?nM˜´wé‚7ÊKJÚ÷ëƒr®:džöBìÙþ›€Dï3'¶¦gq44{›$ëBéÊ­âÄ�&si“ù­Úû>$cŸaç˜:?Þð� Èèwí°o‡ï�ªqrÑ÷�ÄX‡xìX)ú‡oì}«Ü@3þŒž`Ö‚œ¨iAÍÂÙ³Îâˆ>¬,�–+a! 2¡/<…iÆ_—,È%÷¤a[Mö8_—3Î]{ú†•IVTÒIP4ªì¤îu|î^‡ö _£!_ð­añ–P6<ýÿ‹ƒÇĹ:OÌm˜µ´Ô~46ëhÆ–àÞ¯þ2øÇdTþêÒ¶àa?Íž_²™ëÙs·úзQ‚5蓘]¨˜?ÒÚº¤Ç€§ #l1÷ч3övØaM½s‡¡D,$&E˜(´c— <•?��{ÚŽI‹¼c9¡ïÙ('üÖQ÷QMØ᎞6‘uœ)žÚ�lñ}m ?FfAÃSj³_…]î97�µµ°½.Ñ{€sú-;•öZ`ßki—X”e(1\-ݸ»ƒ.‚®)Ã)_}ùE§üùùy‚¯[áöɶzYABçÀÐܯOõAÓM˜Á|ãij7ÅümRHìÝ1†Ü3Q«šGþs·†±+6…v.WôE\lÆå\ÔHfàskN«®ž{á;öU8»º‚n[vÊé'©�NšwRs³ŒžN &ô=?›3üMp ­ZW&§þÔëÚ¬WÉ»¢m¿I¸uóFa;|0koσ�zy\ðÎJšJïa¢Q1aóå-ß÷Íû.¯æÊZU}¼¿º÷þêã•Õî+«÷¾¥Š|ÌOv¦JZòÜx©½½ý?¾=8ùû»§N¨’ØÝÛÛÇ܉iÌKމãSEOKÕgÁ¹š‘ሸ{޳2ê#dÂu¼� É€a©ƒï‰3ªþ3¥ ›‘UÄÎ3.qrÈ9�|Î|¶Š<6Ð?9Q©ˆÆéјÍ&Ãq ¦"3÷(õÙÅþÈü0ÿˆ£ôÌ,ž©.c&CÆ u™AµŠ]¨‘'%qBÁ3òY*ª"o”] 4Bá[ÍÆ‹9[|ó]¥é]@¿,©8ËçãùôûÇ_/¶!F(€¡ 3rd~¨7µÀ°�!6ÚÏ¡mFÚ8ûsî_j[):�™ãÅTÊIéjN…c²�â1•iFQ(ÚwŒiÈ·ã?ç PL+ ƒH±Ä)ˆÁ˜äLðg˜Yѯˆ{œ1æˆeê…Îd8q|î-Qÿ 6žî�h^óHùZÓGA:#" B¼±I &Ó¤‚L*M*%½Áš€uj˜ÆUùr“<˹c›*‡[ È«f뿟�?Шé–F=ØÖ€ç,e‚Æ[꧞Ǥ@èalß�+Â&Xê±ÑœÊÈÓÝýé é\’‡_9‹îü+-ßõzˆ—0Êӏг y´FÇ€‰)õ&õÛ`ÔdžÇQ,�[ápjÈ­p$öÿ&ߊ®»fŒúÛ[xŠš¶@n%¼w}¨OSQ•”M_ê3Ð $Ýmà³@0&Ewó>SØ«ñÅOPšÄÂ/}Œyÿš˜¿Ù/ŸܤÙy¿„Ñ:ªb7冚˜ó°(o«w–p˜ajc=–’Ý­Ç2îA·¯³»õf&` ‰…,bái‹gÐlH¬Ì\)':ÆÅ3‚»’;ë²/bªƒ5RNØøö"æ\ dwë™ AÁ¯0íhËç·Žï™-š$”¸:³±càAGÉ.¬–ÆÍ>'ºGy ¨ÑÏ‚êè/¾/Øyߨ[5ÄWG�Øx<®÷Ln»f/3&ôžOAí‚Çé¶Ÿ»"{‘TïùT/ˆzϧ :zóÁ×Z;ïÍ›³¹ˆ¸Q÷Ù\äG+€´U<0ƾûö›Åüþ Kîƒèë¿{AæKPêfÕâëžmõ˜âëLFþ’Æ5ÿ裮º0ýISª¶±^ÞGM!�Ö¯öVG]Y•ÂÞêØTØZqõ|YRC_•ÂÛaÛY×y¥°7]lê|­¸�z_¦~Àe5ÕÒþjÑV¯DöW:e½ ,ë¯4A½,룥Á–c­¸Çzê>¼VÜ}¶%4PH-0pG:²Ù�ŽRœ$¤Ûç7Ï­^< tçV§Ä=Ý2·ºYâW�5í¼ÄõÙ`ì%Ä…¤»§Ä°\ˆ-V§qš¯Þsân÷ObÁ‰…<<˜Œ5Ædl…2Õ ÛO�Üì�¯ žŸÛyܶÂKpˆHZŽ 5¿N¨Î…y}YÒmð6gÿYX-öV·ÅwÆ#½³orÛQPÌ Ÿ»ÐƒASô޾É{�Pïæ›Ü&®3žå‡± Êí\O'Ln-¥àþû®œèïï Þ<¹gñ~õú±éíc ] }ýA´¼ÿp’Þ+ɉ ¼G­‘þ1ùg«n <Óõ·Z¨Ô�UP-„•à ¼]©Q"n�“⥠îvI/˜n k·å[Çð”j Ê‹ãlS+-ãÖ)Â,Û…ÁV¶Âƒ0W¤�lçç�vìàŽ Þ™Ûù®®EéÁÌ’îš“xàSÚø”Ø „�f 1�Ùø” cDi÷ŠeC †Å2Iß'»óËdæâÖ»¶:0³à0æVóxíF|;%|Á›˜ÚŽ•RAß›¼4™£YÏäzfHzÀIô˜¥Ñ Ù±#;!x«wç;²uoÑ×­î<šû…moÖ0õ@^�Y¡¤2ãÒ òn»%¢ÀL" ʦƒTØ dZZ œ™ë¬£§ x1}ç=½®¿ejÞ˜¼£ì Þ¶ßyÙ·õu°Ø†ç0Ý…=h‡Ô­éê…Ÿ~Ð`ç-Q÷ Üþ»è¼ÿ‡ßiÀï3ì¼Ü›{m¿ÿBÜßéô®]tBlâÊ]4¾•äEž×Sùô�3*ð;ù—6*\Õ‚õ7<E6} jΕâÉÿ?uÏ>ÕúP˵â…茂b§¤P±¦XûÌÓ^ÝÍœ#Gþ­§ÜºQºàùCy0yüÃ_�ž]j{9Óñôñ#ç$dNÕö‡lÅbž1!‡y]‚QÅ|g‰Ç¯Ê •Êä�£ÑùùùPfa”^ Àg†\#ô&,@8? 'ÃñpÝëK=ä”鮂ió½4è€ÀÜÿ À¸î } }“¦*y%xœí]Msä¶½ëW0ÜŠË©ò|H¶×v<39¬�”OI•�CN[CbE\�ªòãÓàÇ�”Ðâd×vª¢ƒD⽡ÐèFÀ�77›?üô÷w¿ýë?G™+òÝÍÍÆÿ�r¦Òm,Ô⟿ÆQÂ[p­œPî½ÑÚmãå*ÞÝDÑ&,ñpXÇ"ž1c*wX|G«!¨X!¶ñQЇRGí%·ñƒL\¶MÄQr±¨O¾Š¤’N²|a9ËÅöv¹î/æ¤ËÅâNjý¢qÚ¬šÒ†‘Ku‘ocësa3!àÿ¹Çþ¿'·âÖÆQfÄa¿·Ž9ÉWåcZ€»ì/Çíú°‡o¾ÔáS.ú±bæ¾½â~½¿ûþíׇÐ¥¯\Ì×aÿÒœ5—J…ªÑ¥7LýÙ—ä4Ÿó<æ?è?ºYÕFÛìuòXÛб}."ž3k·±bÇ=3Qógát7Zk¢é �D�Éâo×l PÌYH'Ѝ;X¬ã–?�ÄÖø¶©Öî×Rˆä�›fÑíò6J4¯¼9˜7ñfÅÚÿ¼rIWÁr™ªmldšAÕ_” ÕHê·I�¨7£²ÖãŽ6bì-fÏëŸG¸ ; æoB Ãò€ƹ°ö^ôìÃ4;íÙé4;ëÙÙ4[öl9ÍÎ{v>Í.zv1ÍV=[M³uÏÖÓì²g—ÓlÓ³Í4Ûöl;Ív=ÛM³«ž]M³�=û8Í>õìÓˆ]SWà·­�Æ™Ú�›’Î�ë3È DžÛ’qé3�us^²$©ÏﺸƒQw©T€ˆhuXó_¨½-<Ÿ6«nü~øùgÛÊD2©QI†¿ä9¢�ñaÁù¸k<ø%ŒP\¬öÌJ^Gü7–/ÙÞ÷®“s[�€ "ööË?mV¨›÷,å|eQ@aýë÷ÓVç1R–B®†‰h�²‰T˜^£JÂU2ƒº'6œkÄÈ5DA¡¶¦ ­Ï" ¢ Ð1T!@DÞ½ ñŽ€F°%Ö=D@!4¦ÐCT¢önRÚ`Ÿ®ôJc1äéû׋ŸŽ#{$Èìg‰0!»‚]ðä€É¬AJZ �„Å3JImY¼Ð²RÒzd× �¼ ¤@2�©ˆ| ‚»~Íû¾7.Ø^ `Q.dÖÀì£3—áDÊ)h;hS`ú<6¿F�# uê¢N}  Î˜‘ }˜q! SGB[8ç'qwÌ52dè9FŒP¾Âu¥0�€hÁ#æºG ž{Ä\ãHÀ7Œ¶ˆ<�̯Ïò°:ËÉgŸ�:'×Ì>æ„“ExÚ  d¡‰ÛÊgïo‰H�a�h1ÃÑÊ)X·@Z¯ ÐrÈX›|ÎX{¥hn-®;Ÿ& ¾û÷�ž&T–§ÒÙ{š(5'�52¿>ž*ƒr Ú„æWw '›PNA:KÑbäãH=\3k:äÌ9žån1±î�kž0®‘Ù{ÞÁ°°Ïz€|Ÿƒq$½fŸKYQ°`sÕ�þ–òðÐåDf%R¡ÑÕ©›Ý+RÃÉT8!î@òÞyLvÝÌ3§`“A9ßغXñ�ì±[mî@JZQ>£”Ôb«ÍHI+¶ÚÜ�äc�ŒG{•¯ƒd"Ãû&=0GB|÷í7½¾æü}"¼�°Ò…’f]ísq‘ô!“^ €sa &½aeR±ð¶„K¨€\ËÃs—5ü˜J¨Ë—øï€GMý]gÀ£¦þ¢î3bªÁÇŠ%—ôž�šú zÏ€GMýE½gÄ$T£+•´cÒ‹Éé¯Cûòk9õ>²\ ÞÓÈi÷ýúížFH»•*½,g1éÕà‚È9bÎ>‹' ^hôÀüê�½Y’ÀÎ,©�[hõwÐWšq€±1¿îŒCÎÃ+wP>»%óðÄ\>ÿ{®ðÕ”›_£(§ ív�©»]SÐþÚ£ÈGðèâu£Hhη@œbžŒæIœ+˜½GäÙûÙûˆ¯×y€Èœ~ÁÂëcPNE!¶”Ch§~ýQé!*:‘ïµ³|¯õ™7#›çÙ#øÄ—uÎŒt�ˆÀ¤ : F~œƒª®?Î)^Ö„òÙ­ª°�xjžï >õ[…ì…Vd¾w¤Jĺ%ëVÅ™>m ò«ãÑS´^ÁcŸö8ÍÃ=Ê ø¨Àvõ4�a‡øœýŸWêm€—×ÜaYf̆çkdöøáUhƒnÖîa"±¸ÔÛIÖ@tt¢·-FG)¶ƒ¬�èèÄv�5�¸Xêÿ’r’Ðù€Ý.5›�TÈhÝbäGè²æš#ÎK[½?{§÷ïj]ƒ=pÑÌóÄEL#¶²Õb³�á #<�éÑÆ û Ì<û ž«“Ó'5… ¹ËëÀù{¡À ê¸C³Üœ_¥F&C<@¡'ú )ˆÀj–˜T(ŽÈ÷(Ï(K? C4äs�n¯;gc¹ 6”ÏnK‹s×rל�ÁçOáYþè3ègzýu†ñpvP#ô)[jduçŒÐ)Sôη d3Î¿È  ÈüíXdVµFÈG¾*½Çé"ßS‹V ÝaÙ@äÛì�Þfõ mk� y´ˆä %ì  o×S™zµä £7ל‹(7Úƒöï¬1~Éㄧƈ‚¸¬Á –WÂ:@�Ö—ÑSÎ’ñ¡5,ùF¶1ÖsÖ«\ò­,|µ,`#sˆÂ—)“Zz)Tär¡`9�g¤ì¿ë &õ¶×^H—› XvÝ—¶Õ9^¬´Ìå…d)sV€[{Ó0Ô”·JxcY‰¿o¥.ÌÖMY-òW×Lè‚ý"u{; KÂj¶­Àó†•(̤w¬uøàª•±Zø ð‰Ê™…Åu1ï�ŧs+/�t¨zé¤WÚ[S´9.’n¯;WR¯Q™Zrçw \€pù]ƒ=Üú$w޳ Ÿ[òwÎÓëI³[Õè°‹ñìÇÍrVfP>þ~Ê/Qú¾vÝkÌfÙÅÓ'�ÊS¸EeäÃ’_uß:U+Ðá4&~žº«ñíýÕ7„îKBw¸Ox¸“ój ›½š‘)`¦d—WöŽõÜq÷ªcÓ]Á”ù¥.’‹$¤Ñ"3Å.d•ÏæJ8‡~‰M&,ë>"äï ‚¶Ø¬#?ÿnöM/€Ûb¤$’j6,¢ï…ðç”Oé(Ø<ž³Âä-1Ct<ýˉ/öt,˜Pr¥—ÜÊU…ŽŸ5 aêLÑ|dÒi£Æç÷†h,$òœ[ÃnÉ_ó”b+MëöÖ‡Ÿ?Ù'Øvq¶“”:a∌÷Øö+O‰¾_`×£v¹<*1l§ó†ýÜK±.ÓÆé áKÀz|¨ãü=aÌKÐ`±ø}h˨+ž-GFMF{>â ¢®;�BnËJØyâpkEÓ€å#Žä(k9³†|¨…ÔG‚]š:è`–•¸CµFÑ…kÄp€~aZ¦‹„öÒE5¿SÚqc²hÒ· rS‡n‚=cÜ´°‹èV¨G{Òa+«0!#¤.r¶©Å“+ÏJ¾µ@wÝ“þ6"Šò ¼�þª�y…t�»ÐÄð)T‡Eк XÙ*µ£^W°� c˜a‹xrMà]/‰f=ˆ�R´ÞàÄQ7 p˜Þ{>†—6ÂJzÞ…>ml�¦³Ì˜õtBÇï[™¯±õcâ ÷±�`3Âú€mÝÔAVìÇ  Gkm¶ ŠÄ ý'Ô6Bv>Ž»ü$tùé¡Íã3hƒnë ³õÐèÔŠ¸˜½V™ØÎ´¬äd‹£€ôÕ8@IâzS~ã*•,ˆ­¦xo Æø4§Ö»çÝÕV \t’ #Z)™•p”¨ýXAÊÀj¡Î6Ç´ãæ!xz¨dI1nn(pD–0Öt4Dv �¼ÒD‹®C>ƒ•ÔX VDÐE€©é¨xcQbõžˆè˜Í{e¶tŸ¢¨”%©]Lˆ,ôþs!ØŸ|‚ß¹1CÔ‚ý!+³V*!5ö¼�(ر§Õ4�ˆó˜ª¥HA&#Ÿ  þúÛ1m|0[ûü °6È6–íÂç_F©@`L.´Û��˜Štésé€'¥ÀI”ðxºñ­�*PÍpvü�POf"k›D š´•Tgì²” Ä8tI«BJüŒL§A=ìòè �ýS¤\ˆý'ysg®ù0¤T¤˜æˆA|d|ÜåYÒ×ñ¡•œê9ÍûÔ- îõŒñÆñ—�Üß/Ï †™ñÞÔ_gÃñHq~6üŸ�ƒ_'Àû'ÀÏúFüïÈ—Eé¼ä| bT(ø•ãd,�!‰~¸ëé&uiúKß>œ?yö²«ÙV³‹ÙÅ“)»¹3•½lM8X÷o]bݦ9ªuÔÈ¡ÊûÆ=O’ív»¦’ú6ÂÌŠ�]%”s´ÚͳxÏâãÚpÀ¡_÷Ã/­»?0q�¤ÿêùÝ6–Á ÈÃ�,Èb �HZxœë ðsçå’âb``àõôp ÒÜ Ì$zŽküRŠž.Ž!ŒÉÍ <év­5¢' D 3u„þçãrÈaa`ÐULœòùƒ H“§«ŸË:§„&%Îa�FZxœë ðsçå’âb``àõôp ÒÜ Ì$zŽküRŠž.Ž!ŒÉÍ <év­5~Ë*nScXýOV¤áPiì›4£<é?~ Mž®~.뜚PÍi‚1„fxœáþ‰PNG  IHDRóÿaåIDATx­“ƒR…÷){…l× Û¶ÙfÛ=@®å œ:¿¹¾3ßú~箄þþþ¹òòrX$AðX-öD ~ñýý òóó€Ç‰(ŠP%¾€�8<<9:: ãøøØP•êO&’$é Ø�l~‚X÷ìã�ûæ&ȽÖEWÀ^4µwQ}ÂÎö^ü˜Ô÷Í£¾ ‹¨iê©ïš0/H/é@F)éDzq+’ój�”[žSU5¾€Ìèhš¦/ð¿oY– G&Lfs|�£¡»»{Íêßøß3%¸U+S°é`AFÒIEND®B`‚¡W}Cš:´x9]xœÍ[ÝoÜ6®ÿ ]‚"m²RÖÞ8q7hqMÚ;ÜC�ô¥¸Jâ®S¢"Qñ:ÿï7ü¿´Ûy¸pvÉáp8þæƒôËçgÙóìCß�î��ü–â±Á˜gyž•h$UÆÜâˆ^ž�½|.Ú[DºŒ¢[6 ²ÿ“kò¹¨(F²ÿžeðO~Ûf%ãÍÛ³;E1âŠÖm·hÇ-aMƤRʪë·j0ë8îø6{öì­Ë�â—ÜÔ LK4D¾3ÒîƒM´†sÈ= �¡D)¿G{ühÏGÂÛˤñÍD+í:%¼ÄTÈèQX× VˆX2ZǤ}!ýÕÁsÅ(5<½ººr�è^"Ù:›IŒÊ%ûÎqnÀüß �g?‡Þ¤°us§ìqé`ô0›­IF~ææŒÜ™: «3‡Û½ËéY„å-Ï1Ÿ(£zLkY2|DýÄÃAÉ1—çSê66A¨e«.õ‰ëØ 3sGöñÀ™¢CmºúÒ¢nB4Qñ: ŒÛ5Z]7�Vs¨kÅÑ_§.ëÝù4– ÏJD•�f²&O´ù<@^)"âêé;ïvðÙ{ˆ˜ÀóUöìÜQ&>ü†?¢?§ì‚hêÖɶw„�|À¨ÍþÄòú @``Õ•‚01�ÜÐU&ê5…ÞÙß8mâðêÑ€;“÷'CIË×.‹Ý�"5�GxaìR°êaB_Ê ô0~½¨‚“›‚hj¶�7›SQ°“4k2ÔݼÄqÀ0Þ¿x(‚+²ƒxRPÀɳ[œ«× E%°¥xóû^5G†0u#æVŽ¢1‹ëUæ|á+ÝÕ÷N—ü"lþ;“¯×›Í»MÀªu·.ùù›ËõïïòÑ�y¬ÜÁ£;óXy3¿~óÛùuϪÏoÁYŽÖç‡Ñ6§´©©ûb †Íh5¸dñ¢Þ7(A+;sÙkè'ñšc‰^vúô’ÅÀÑùË^�ÿ½â?Óo;Æ äGˆ…_”xÁGž8äÓIò#¡KbZ'j ¢šÄ¤KÄÇPÎÞ^˜´_9ß'ù} ú'¯?}豕² i]5¹=fËT_1…Ç©_X¯ºS�Yߎ1Þ‰zÏ/2Ñ¥u¢ªÆÔ³ˆ»ôx¥k¶“·›If…äÞ6Þ‹&PËñßì(Ò`žá«%žÇ%îcqcu~k7�^œÀË m¶üäI:[®©Si÷~ ºZ%>ЃE Ž…óšZí HÒSü°Yÿãœ3ú|9Z#Íò½—|É?ø .ª£ø>L·¢¹ƒKȘ‘w‚Fçz|yã`ÎôÆž[¡î]µx¦¸r»O’µE�¸ö9Y‘ð–·1ÌdP—ä¸TãðG&_3œYS¹I~+j»G)‹o¹ƒøJåF ˜&bk…©R{‰/_©€s8ñ ¡Ô'CÛS6Žh¸=iàɳ€h}„C,.ÍÁdk—E©ãíg0o1L¹_*Ÿîj$À—ajckÖá°�­¼ìÿ�Š ù>HçŽTì¼JÙÂ1² q8ÆÜ¿ú‰Œ_:±É±ŸE%†³U´¸›FLÕ“hWï©wŽò ªª€|@œy[©±A"±ˆyÕ…±Î[dø/ö5•ó³’’OSD¹-ñŽ 81 cCkrPçÎi±ë·ìƒɹÞá¸ËrXe¨XwkÞ�%¤þǵ*ð¯•.û�t\ü©Ÿ÷Ç�Óåß[\¤XZoñYÞ”BTËWQ‹>Qs‡Ð¯Ìü¨Ò½°1½ÑßãÁÚ ?ï/dæiô¾Í "Å0r<¯áž ÏéÍñÐÝÙÝÿ Ñr Æ ÆŒ; ˜zÎxœ­XÝoÛ6÷_A º•âÄqZØ@š5ØÃº¯vÏ %ÒJtIÊq6ìß‘"eZ¢d»ˆ6uß¼ûÝ�2AžÑ¿Ÿ\p!èÕÔ~–{èþÿ7™¤DäuI+íÈK,׬J8]麦å2<•l]øcàåì�I‹ÍMÓY‡+Z‹òà‰¦;�°Š€^8ß켸VbŒ y~ÉÉTçžI{>ù7qŒ2M&ùã×Zh:Fvy�~¤+V1ÍD"•VèârB|Z¬D¥“'ÚÜ&8±\„ ÷è"–þBß#ÂÍ?K¯©W}'Ê ÎµÕ‹6R�:§eϨ0'‹"LÒ\³-5FiœqšÚGÕW.9CªšÇmŒ%i5cÕO*/Wb'Q…·l�mx2,ÑÅOF>ÆÒ˜ q£<ÃùãZŠº"‰+J-q¥6XÂU¸Â|bDàÄtú�5ÄK¸èTóÛéÛéü÷Kh.¤µv�@!•œUt¹¯zÇ£ý½l0!¬Z›"õÕíh\d"l ]„‚LQú™Óbs–/ƒsö«s¾�ó/x‹#4VÅÄ„fu$¶Ö.0$�Å0íLH�·V ÎÈ2|àoÃIxÅTG|Ü\kuø#éÝçlª6«vž«¸:ˆ©�]I «ËåpQve\¿€ŒÙ ȸyó�qû 2\¢~ÞМaŽ xîàöÖÔ$âc½9‚6‰×´²|—z…`WxêQ©M�C)„wê!@¯ŸYõ¨ÃŒ¸ƒ"³ÙíüÝÇe6*aÄá´°Hòx( WcB΋÷ �S¿fC@’®((Í©j¼Ê¡éN‡»Õ�Û}àxõñþ®ŽE¬¹Ü«LcíØcÑHñ¤¨LÓÔØÙ)‚ySç«^ˆŠ?'yÁx`è LY aá5f•1cUscc†ŠÚ1bƒq3r­Ë@'®€¤ÖH4ôÞþNV) H3âþ¾TÜeƒÝœlÑé€�6xƒ~—è¡MÙ@#t_fþË�ÿ2÷_nÑh%u³ŸGn­ÿƒ®knF/ýX¥'û×ìfšq52|u5yƒºGEÆ›ùp†0ÖD0‡¡Í@]Ô´[Ðë�z‰Ñ^5 $âÈ^Ndj="+å8£|LbCÑiÊ�}×FëƒØA¤ ˜”¢Ù—Ô?¿Â7¸–�/K#ùKÁRfÏ‹ ¬ÐZ‚ìpÚ�©VÂ~´5ðfíÈ%ÅÚ‚�Ñ×ûï ËkKúú´ÚêÌ\³€Ö+hA&m½¶ rÖÈsAÒ‰·ñ7,5º2îç¢ÿ=§Ö}@Í4‡DHÛ‘×ý¶Ái~�.–-£ª³ug¹0ä{Õ°lö éL=·Só×eLŸ°¬ pw3{7{×â‘�ɵ‰‰�g¢Ì¤¸by<¨}zªîi§[©á/Ó�ÞCo�³0ž÷©}tæéAƒŒ¾8QWôúNvadÉWßCøy�ÏúFáp¥Ž¬¼ÁñàŠÜ]…û*�üá!*¶Ú»Àµ#Xdywgó®¼ †Gbû9xÚqÈ£ÄãiÏ<’ j¿¿¿ƒO4Ž!¶˜ÂúÄT>´eÚÂ’u&Û  éÆ9°°@‰’#` $œ$¯×ܯkæZjZÒªV”»¾uÊ’â<X©„¿õ±—V†#Ç›Ž�nü•$Û¦†ÍÍŶ,íÁ·¼ülš$µëFÅrª™kÄsò9­¾½6¼( ‹Ÿè}¸€ð�·Ç·/ Ge4ËYtk°Êšj…jeÒÛ½è–VP,0DÀ”Î"~¤ï¬Ñu«‡bÿ¡ƒ„À‡y �v>xœµ—]OÛ0†ï÷+"M»™T/”®h)� 4Ðví8NbÕ±#Û)­¦ý÷9mܧ “Ö»º~·}Î{ÜRÑàWÀ™ £œ²,7ÁÑøäÃeðû�IP½.¤��ªÀÜî$’Ku0‘SÅÌec²È”¬D2ÚýdºÄŠ ûs‰“„‰lÄij-Ÿ”«¿Kjëm³öû�%Ä«»ÿçÆÍI—”07©÷áæãóö>µþcBÿÙÊíW^/(çµ—>«¤½Ûݸے¦]‹Ä‰:Š¢Ë •ÂŒ´Ysj/È`άÕàÓÇ`&‹ÂÞFðñS‹§Jù#ºŠ&ÑU´eçJIÕ%ŽçqtMÃíæ/tý"UÒÝ.�í§§§Û½%UØ@Ûe;«íæÇJSaäèî'y+˜³pÀI [¬ó‹ +Þx¦èkÅ «« ˜*[q�ÛÈÚ䣢¥’ré[cØYºaFqôVcO¶Œ=vô›íì:«c(KC³p�wWü™ «(]SN 5”ÕjØç³açE™Ppè­ð,÷ÕlƒÜR\w;€˜GQxÜqu'4U¾ä¼ÒP•)+н™[_“ɤÍ<*Y”�ÑÍ!¾ìFJ,yÒ&ŸŒ’žÔª}Þžª8ï9Ó# ú¬0¡µ�!m�ý·S4“B un‘€»¦„cåUœ…Ø/è.¨�2tÑ¢<@>jZ%`êö�ÚºZºZÀÓ?œùóº�¾Û¿gÆJ8Gߪ"¦ ƒ\Á˜Z×M/4”­3O½ÜÓBõ™¢+c¡¸2 >ïæ³" îQ09hƱ֑­¬N¢qè"=(’}Žl¥Iï$®œœ…çá±ël. 3kÀP‡9·ŽÆ®«ùŠÐÒWÒÂ�9g6¯‰ëꦞ¾>Š÷Œ¸ u�c ä_ˆ}Hoãˆ>Ù`ÏÖÑÒ½¨p¶ú�Ã1œròÅ¡ÜWPóXA?=Ï›²óhOô«ì�¶³ó°¹ªgº2ègnûÄ{E|¸Ñ–{‘àn¸Ä ~‹|yKW€c¸;ah§�ØbÕx·t•¦ D«ãAŠ…¦vX–&=ÅÓág9Ù&¼GW:¬}±¢^Î` _é»Fá#T�‡�ŵ¬\FÑýöñþ ‹ÆpúO (v®2ƒgR‡ð5bÁÊ/æ%Y\Š”,¢0O6fOd+·ØWK ÷cPÔ€ò•Œ—¨ÂÁ}¾BšØ�ëóÜÞåùÊG÷4võ�}m ”<ü7€gúÓr€Ÿ!‰O�#é/z›‹K  x�VšÂ´cËad‡Ï(áÎ�kBE– Â0éò¨½±Æ çDX@tœYÉçtrË)\¤E:ZJ…Ôzj’=<8ßQÞîª×šíèãMFíÔÛ¬îÙÞÚ.ãà<îÑìI¢*}ÛMô"�ÒE1þóþø«â�æðŠÏIçAäíÍIŸcT‘™GÃ&êP‡?…¨K-Qšˆ+ϰíl¥±¼A;Z‰U®æZ…XC˜ëwhí(v”Xœ.³6�/Ô߸P4²òÜÑþÙœœÈ- G‹G Ê*ël_æmpÌrºî'i6S‰�G€"#~_³“Ú¿€ËžÇâ!ƒ]iºOš"�u7ªq‹¦kҌ릂Ž|†ÍèkgÞŸì„'|â®Ø©NZöµõMGZ)ÄGå8ÃÔ=þßË¢ïo<�é¼b Ö Ëb`µL7BÚ—`ú ”$®b¬£ÜHzº7¸£•"†|Á¦†¨ò ã›Í`%3Coôc¨z(©¬ 0¨V@Â=,íÀg1WÌcR*Ô`="n_‹ø¡Ž¢!xÿÝV¹ûm“^jÊ>|½-…b=žÃ$o½¯÷¶"WÚ–#}([È([¾ ˜0$K¡äï…£sІdXp%p”¡ôj¸¢|ÿÃM(îìlóMOšt`›¸Mæe+›Œ‘GÜõþLò:`QJ�ïÇ2^S�Uë£C!9q‚Îô“ Z�Ô‘ô‰¡2îxpžâ>V±‰¼^uøþ¿¶ÐUƒ—ßÑû‰€ ñÍ.ˆ„û»BºÍ‰Y“Lj™÷ÿü¿ôí^P3õû¢6œà?—¿¡ Xìe.:ñÔ^*Zï‰_Tž%)S˜OW¾Ud÷hÖb8†ÿ|óh0©wKKÕúšKˆÂr„hõ®|Ô�Àˆ ~3)O€&)¿ï ¬ËL؃^“Yõfr‘ ø;oTËÚ"¡ç :y›/´Û’¼T2pÂÚ®÷›Éוõ”Ó´,^e“C˜Œ‘9_O×è—ql@)犩ÓT¬™¾–>ŒøêJ;zL“-­­×mÓZ²AÛ Xîa{''ÖÙÄ8iïÿí_*�ÿnaˆ—TIÀ×un@fÓëDúiF½Ðˆ¤E¤XwH‘s=EJb*ÄÚnçBy@Á‚¨·e÷ÁÏñ'{ÔjDéW„Çj#ÊéJ® ß?Þ•ï×Î||ÏÂ>žÂ�aNeîU�¶ì¾“Ø�þÈ6géähb�Ÿ  Úy8ÕÛXñxWt_7•¢Ñ]”�{/úºvÑk³ñDœˆ¢ko¸Ü_‹=Ïš�HÿP?*¦2<S¹/!‰ù<Š‚ÈÉ` ~Í`6[°Go>šŒ&/Ò�=Ê|'žˆ¤]ãw1ÉCÊ”ˆ[ŽõvÚklMŽJ1wê1ò€zØù¦Ñ�NŠPúŸr«þ (^âqšˆ…ŸD?²×Ê ø+íÆ¬[öAæ�\鲆éˆ5 f‡XÓ…¡5¡qíšÚæ.Wú¦3U—F rzšr&CTÆMÄó*k@ (=Ì”¥½ \[ºÁž§³§“#ƒNêœt½Šk!Âf‘nêô÷ÿúïÍù&Yz*(Zî˜G De$°‰�w¥�Q ubó”·5)ðÐɆ•h¯�…#7ÙüÏ ¡Ø0ör”;ŸI�Á¾´a…r4}u_o¥pÿe@e � lp.¥'Mß q Ì•`ŸÒžàô?!ù¬|ê/\©– ,„‹E[‹‘ÏD sv´¢0š nuKøÆ®Ž,py…¼ÿî�Šå›1R Ÿ(êO+y)>ø (o§D�N7i.oøNâ£ëŠd·uÈìj,Áíšð á5ãç¥?ê^Gj@<” I^V>"=�¶È)£Šc–ºPHàtf(•r«÷ÖÁU~à¿€‰¹ocM«õ…•BÜ=H~±¤Þ¦WWC#â¯+JmLÝZ Q2ãÊW{{’,#�¥áTБUSL¢²…@¢( 2‹:Zm¥1·%Õ¼Eרs«FȦ‚ VUíqK�5hÒ9à‘¼âr½esk;›ôµKßõŽ›ÁLƃÙaëaqé*¿!µpÇï8ÈvÊ P F¹ð°Œøem›q5¥¡Za à¨àê‘æ¢åÐUCÕš¬ˆ° Ú§õÞN‘Ωn'ªM_š¯@Á#¢àË\Çäv€*fä)£C4›sOR.±;·áúi§BùEu¸vnêõ¬[èªÌ…=òØJ鋯¥AšRÜ.ÊD—õÀ“· QâfÔ~AW˜¾ÂèJFxíZ9¸…f¨’@®HQ”MzN¢�+ʲ€˜Ü!‡¸ž¤‡*DCCêY?ýN.¶É�òÜÅ+z�r®·Hp½çG�*³—=ýüL�ŒBܦúé!ñ‰‘³§žÝ1u]4. <޶d*~œÕo+,u�•nR'� ßVE¢4ÈÓ}s zFGaä- tH‚‡@hMók¡éÈ)½–étTâ©Ô«F—AáN+-ܺ~Ÿoú2ᆬÊ$yñì•%!FË‚›ZÉß'ùE‡*¢©ªiî—Î}¼ãܯ¶·Ñ�ŽGø Ë˽¥¥žãfÁ-˾pÇ ÌÖÕì·�°³7f„Q7X°0x6&Ýæåm ìO¿Òw¥�YêbVÀl¨2‘uGaG{â®øZ¥›s) ¦ÂŒÉ•x³ÀÕ1²ôuX|˜ÚsLPøÔxe„5Ï~¾ÿî?|±Š±K4„°Ûƈ�š=ß÷ÇCð2ÈÇÀIÚ9^o¿lÎM ›/ÙÍ—6Ó«_¤{�‚ÈQîßP<öc@ÿÈöªP–Úø¶nµòѵƒ }±¹ÀM�ÓRÕä“¡>uûIˆÏ…7ÍÂ?X™½”x£ ó{¥û{Ã$¦Êz@ÝÀtØPDÛ\Â�~ èü�S&Š£u±:Ø¡ª¦šÝnÄ*?”Ýe:‚ú幄¨˜N¢ò%��å3(S)σÿm/-Ú¼”¶·e7!ZA«*«7„CÑ#B¥aI»üHeGÀT8Á¹\á/⥙-^&Jgßr ¤Y×Ní©‡LÄvš¦˜å�yà#Hà'úЇ’+lVñ¸/CÚï‡åÌ]ÔОë féð ÝïâkùXÕ¥dS*¨3e¤cªÍð”ÅjÕ^jk³ïâ°XÄ eÌJmo¤mÊkª ûB%!9ðéŒ7I€`ðŽ"¡³©y ˜�N¾[6…Åž%QD‡œhøø —.YÅg›²—Ä,ª liŽQ‘žN?d‰AãÇ%nŠ ªjPVÊ•¨›pAŸç ú¸S>ÅÉ/†0Qq¶/8î-n?×õ⓽NŰådês}ŠŽ:V&mMÀ.æ}r�yŸxAÒÍl^àÞc¾ÏOúx¼ù" $¥‹¹mç>ä) 0 ]ÌùÙ=¦,dn»˜rÖ8å0qɃ,¬±Øà¯ûMÞW+½¥�çK9Pˆ?X.ûû?¿¨æ‡ÙkJÖc/$µµ¥Â÷ÿSÁOËŒë_þT¯-|´'ß_þ´1d1[Žãû(~.í4hëYn0`ûl°ÅÌœœžÖî«mÊ!ˆ•†ä‹†�:Ìòm›þÙÓ×fÿ°ƒü-°Î–N±ÉãÎ0tˆÝäA?ÛçgÖ˜�ñY*æ€ ºk'tÜž¿R¾ø 9e íÞ>¸q¶Gš´V•þ+s8Ö<´a‹ØÅËww ^Û}ù£ùœ†“Ó£�;_ïìÃÝÔGVÓ.ú¦Yx²Û"÷j)Þ§µÇ4�žžŸ[§gÇã“ÓóÑñùèèx|úøèè˜:I‹ƒï/Oè,PÓ½BÝYb¥¾|<œÞðÌiRV)~ÐUŸ�{¸ïbä]X¬ù8±�úiöño«™žX�OP@F““ÉñÉéø||Â�ß®�¯ÙGlòvØUÞ¤}†ºX¢¨?Õì�ꮡ¦’Îj>©NGë¶×§ÚLc±‰ëö²žÜ¼7�ÍÌ^:^Œ²Ž:ÆP;ß¶–�‡á*=äàÎܤÎKÓ>ÑuËÔKn=ÒÜ@»á í«ï�+(lI‘|ûw'Ð’Æ\ƒù©BÙ.Åàn$‹ÚC©'§clzûÆ:€Mªýˆm!Ýè"ngˆ½v·Dï• –Ýâp¾‘l7\T…ÛÚÈc¥¡mú½cÄþì¹ìÂe�l(¤–e„nÕ&6Q$ÑúNê?ñn[ò;¢Úßv�k []`(Äý;ñ[¨Ât[€i ÿFó|[?í¼�vùÜþŠ*Óxtaà§…Œ–H®xZÃVƒ=¯ßÒo‹Ñg{‡G\ÿn›ïÉN¡õy“‡éIw)Óêá‹ì”°tc]°ÊÚàó~ƒ¢?^Ì€«žnŽêQÑÌœ'Øå6…ª‹Óv'@×ãuZU÷=X½gZÖ 6³€¨¥÷Ðm´jw;Üu·ÃU7Œµ…®Ûá¼ßT†k¹sæ«nù[TÁké·|^Ñxí‹ú•6”|ÛãÕ Ë? ×9 Vsm„ ó´]û7—Ä�ïW6�`”µsÑŒß&ÜU-÷ÿ�F£·×‹JsÛCÌåÜñ’}OãXÜ1Míé@3:\c±¥zˆ7íZ‡¹ ˜nÖ¼× –¸Þ¸ƒ]4Û^)QwÌëq?ã¨ôuų^óóµ«oiЇvN×jjZû+Çj>0ñÛÆ «à��ÌÐ¥¦#˺«Cvr6aÓ„Û¶åÔ³ñ6¿óÕw^¹º÷jlï]GëØùä¦-‡Ý]ŒÝ£ˆ¤ƒ¥¿ñ·B<8V(Ϭ_¯—í†Ò»£JE†=ß�'ùùsÙ»o³WCŽ<2Û,í Mú�‹û¼âUà‰�W3^\Žu:s Z$·ø¶srKaÃÁ¯ÓcZh¯Cñ•ϺW äQ,m:ƒ'{åfè5…î›ëó�½Ò«l‹|j»à�ú)ú w(¹ãùìã¶7kÏ‚8¼/×þ‘_®ý“zŸö‡Whßõ í�ßš],Ísvà¢Ö½ìOú)ÿÙtüm¿2dQʱw˜·cÉBÝcÑ99ÿ„= Â513›Œ&'‡Ô¡_”»çâF¸¸ÙLYf®gæØ+íÛ.5’–qª�‡ÃÕje©p)ýÛÈ«D‹!J2þ@"{n�­‘UV:9Ì'Z~þöpüL$`úÃâá¡ õõ® ܃žxœí=É’#Çuw|E +¦ÍFaéž^Èn(fáÈm.šÐ̈¡˜ 'U Õµ±²ªÑPè@ì‹o>Yú +|³}ãU1_â÷^f­¨B7PE“j ƒd¨ªÌ—oß2ëâïžÿêÙëß¾ü”-cÏ�özø—¹Ü_\ö…?xóªÏó�ø±ðãwQÄ—}Ëö§=Æ.–‚;ø>z"æÌ^òH ¸#‰çƒ³>/úÜ—ý)VaÅ}fƼ쯤//q#m1 /‡Lú2–Ü(›»ârl�p°öãHÖô±Ï�|¶ V,˜#æÒì†G’Ï\¡™�¨8ðØ<ñíX¾bÜwXÃ*œ½ …pžEp&‹D¢ƒ™ìÄåx3ü¢7†Qð!˜ñFD1›‰x%„ß½nƒiôxV߬ÍÊŽdˆ#À‰±Œ]1}£D4xNP:ì79˜/Jð½Áñ.†úý¸+ýk€Ç½ì«x �,…äÅë&ŒÅm<´•ê³e$æDàw*Øìa¸^x€&eÁå_Ü\Žæ31?>-ÐvÏq¿Mxtm��f“³“£yÝ ÒwÄ-Œ‡+¹ì_éoÙh áÓ òmÝã>@�=�¸cW@öhÎm‘#Ó #q“ òjíÇ<ƒAÑ·Æ'‹(É€ÞÄŽ¦ñÅ�äéb8k¯iËl—++á731ýga_ÏF7FfæØaZ ú�Gon€Ÿya��Œ…ÇÒƒQßÜÿdÙPz]Ó“³±5fN`'ÈÄãC>e?ÿÙøìô“­� 哨G¬Í~™HGà˜…»õÚ†±“‰‚ø+þe?’‹%àvë¢�–ôC–MJ¯–É^¼Âm[(u-Ö—ý—ý)2‰ U†ýìàLjÀ©pe Dnn€ìËþe`¨Žj ÞPö Õ…âÕÀ—j$¦…¶xÇ4Ó¦{Àu\WYÔÀóKወ»5àÐuÕŸÒ(%¸z…?‡(ý€r Ÿõ ޼I�O%gÊš‹«ˆ‡¡ˆúEŽ/Þ‡ê Ï¢×àqé—nÔò¯„Æ´tÀô¢�ÐfÌdv,£™€}�½��.–ãÝ, Üß+M—Í€£©�ë_¥3îO/†ø}z±œL³aa„ ÜN¿Z‚\ѵô Æò‚H0„K©À<ð` £ñ”u�€ˆ»à™Èká®Àê°xÉcº2�Ä· .ø ¨ÐŒkŠöŒù…;À‚§Jv7ÑÊKYì‰b+Á–üF€N‰@¯™ë¬'µa=Jz!  0ì.+ /…™Àó�`e± V¬üaÑ3€�UÀ‚ù\DˆÌ‹ô‚C¸;š'.[ñõÇ9ò­ü#<ë«ëWžBzp¸¿gÅMÄ!›­ð hEĨŒ™ö”JCÁ³†3X¢ð6€„]Ø�“YŽ�ô{,]èŽIdäˆû œdÞTSÚ<ˆíOS>H‰>¬½ë2½Ü0,¤4Àa›2­›?¾†À;%«8¸�'10 fn`_�1YQ´Œ£8��Øþè và邸-Á¸he )jkŠ–1Rw;ü ‹Ò«ÌD¡¸ddn~g¥ AާòoÞŸ>¶Æ“#sµÁ)†0?~1@A‘r‚ÿi$R÷[ÃÓ<Ž9ò%Êê ä-äâIÂ�ìzÉw�OJOm¢™\ãÁͽ’Ì1Cãv`&aúH‚YÓô¼eâ&†�ÿብv”L (¬¢n6ίöª.vWçÖÙxËlÅËÓ­¢n·9Ëx¬>ó ¨_lCÈøôÔš4©O€öðÂUbgX]¿"š5@ª¾�â]!ÉLqõ‘ƒ&€?ª®p¿¹…Áê�xj�ÎF“Óñhr~t:>y|r>:=;ÝÛJ€7Œ*<àCã"fɨ›<-F*\‘Fñ8¨ST7Å´:ñA´Öz™]t¬ñI£Ä†&„¨»d‘J%¢˜”" ²V/ò0’Š‚‚•wáôIm–�g.{�#çl ¹ï þASg®³˜g+ÓÅaŽÄ >>�? »:Ýxœí[뎷þ¯§`Æh³›¬F+i/^[«À±“Ôh�°Ý (š€š¡$fg†c’’VEä5ú»ÔwÈ“ô;$g4ÒJòÞ€F8;Ò�‡‡äw¾s!5øäÕ_^¾ýñû¯ØÔæÙ°ÕÐ_–ñbr‰¢ýîMÄRny;Q……ýY+e/£8îDÃcƒ©à)=à1–³dʵh1³ãöÓˆuš/ ž‹Ëh.Å¢TÚF,ȼŒ2µÓËTÌe"ÚîÓ…´’gm“ðL\vãcöp9N¥ kÕía™±\[‘²…´Sö¦"}©gE2}ÆÐDh†ÞÉ,ãVªÂ1-ð9Ã3Ë,>ÏŒ`v*Ø•XŽ×)FE§1OÄãEÊÄu™)-Øh&3Û–C¶“å^Ϲ–|” Gar©0‰–%5qûU´ÒfbøµÔƲ7V”fÐñ_ù×™,® Sv»„´©X»,!ЊkÛIŒ‰ØT‹±ÛÁŸ1g+“N¹œä˜¤‰ñú‹ùåñx$Æ'ç�Í»§Ü÷3®¯‚ÐÑñ¨÷ô¬?Þ&T©¸†<šÉeôÚª¥MDáÄÌmÝ hP÷~³,,¯»÷igÏR‹yc\¨�ù®úËÆw;¥4פÖúæòøMtœÅ F*]:²´ï,ɸ1˜ Ÿ�¸fþOÛª2ò£¹†:Œl ¤„óèôø¡¾æ !miEΪ‡öqá¿ZÀ~ãç5l@žuã.KU2#T¸¹:|Èþø¤ûôüùÞ�º��Vƒ5¶oøÎÀ–¾™ÉT�ÌFk?·ŽMk¬§ŒgrR\FZN¦XÛ½“ÆNx]ª‡ ]víg³Í6 4ßó$ÆÀÄ/£ï£!�Gª™YŸÇ?Ù-TëmQ­ Õ-J\ïPç»hHVpUú[T8LÒ®ª±{[ôú:´bÞl›-†5ÇÝC¯“íz­“Á}¾…Ð<Û¢Nc¹^GC'eM¯VãO�C<èê� ϾA*ç•ò•¥¬P¹ååBó²:jB¾ÙŽø bZÑr.‹µ†žŒð+-ÓËhL. mÈ å`Ú]w øÜ”k6- ƒO�=ÁÇYÅF‚|<�äkŽ+f?L%‰kÛ3Z‰ðn­àÙŠ ƒ›sòRJžFÃ�)! ô6°dük£C4T±¢`¾í CM‡Ž` "Ÿs™ÑBµ¤…ÂcNþ•&%ÆjUL†_r#ôôŸ¬,ÕÌÆì-š”j…fÙOLòI |·Ê±')y{¾„ð¹ïæba¼ bj�+,+Ä35f2 âUã"2(h9Á§c9™iHk•?k­-ÆÃ ™ßÂhøWÄ.ì·_ÿÍþÜ\…xÐ)±qk.¡}Ýv~´=R׬þÀÓ\Q\8ÔßÊ ,½u®…ÜEÃSt�ÁšÛD¶-mWˆ É^ €tó]Û™[4üM¼Òåð"qÍóÞ«ŽÕÂ缘Ái�9ƒH•²ƒA¢RÑ´+3Ã2>™.†Õ¼0 `±�$PnD‹ CR†‡ŒûmME"st7¢äš[¥cö岂ÐQ«¹½ ™y•°š™%ì(ÿí×™ªõMYlŒØìûMIh£”–�"Æzrô–BË<çœèÑæDIY� ÷°MÍSyݦøœ'–˜h·‘檦‘¡mÃ@ãÖ+QÂpd1aÀ‡_=a->#†Áæ0'˜B!ˆj¹&Û‚¹•Yí‘_#ãƒl|Ñ)jU"øµ[6�-¦à ~Óˆh�-k »Œ§,Ó¸#oüÏD põëâ}Û­0ééè.%GøNŸWB3´Ó™�–pWœö†À0EYÄì•*€#Kk0VàòÔ­ „eenq’™±*—ÿàÚžc€ |ÅD:D3ôÕJ-Žh�i(÷]“=%Ö4ˆD#3Šò”Œ(¾ÑV¤«Ùhè–Ÿ³Ű´ÉLÌÜLÕÂ/4·¤7ÌW#Xu»°æ#)WÈTØ[�2¶˜(°±†G.ð}¶�ÉþÛ£L%Wwc¬µ®7¸kŠ@1£`±mH¡Äo꺙mkޝaqÞ †àרFÑ�{ý¶í­Š†Ÿ‡ïÙ�nçñÓ‹ð¨tÃTý0R-!uŠ­\�ÒJ*=îç’¯®ƒiïÄœg3²02Qd­†`çË| ËxlÔ†Ùhæ ø @ë-Q¤‡ž?åT ¸qdd,`Þß1°Í—hsÉ.ânïäÞy;uv:¡­:ØbýaƒýžÔ$pHK'‘ÙW‘‘kŠtÔm³îqHÁ¹7p05Òèë6Z€d–à´bɪÜ(¸+pKb%_>�¢#xh5Cÿv’Éä*Ð<äkt(•w5 )WQÆ·Â:WMÔã" ú¹è÷ˆü (Ñqè‚0¸1Ò•AÚo5`/nº©C&ÑŠ|ìaí:ß6LÄ{ÙÐð¤’JLÐ>T»ð¹Z5S/þæ&9[Å‚V‡3^˜uÛÀJ¸:ž-8¶dª²t3Hq6Ë}`JÜC¹ÆðÛ!|„Ž»÷|£CUtÜÒ"‰†_P±Ä%ž|¹¾ÕïgÂ8ˆä˜´q`ôõ3kâ­ÞOíâAçËw»ù­>v——/T2ÕÜnLêS´ù”b;òâ=•¢`D§w×»¿Cñ =nõ÷EDOï4üØt ˆV»ÕvÁ>™Š¤ì�ÂtçðSeªŠGAåÙ’êu�ˆïA†ýņY�i᜹©çÈ›,w~KþÈì×áÒUŸ°I…-šæ5¶¶aØQµJ”~ÑÖ"’é½QòÂÔ&n„8zlæ.µšË”B;•ø#pn–¡ÞÎb¶¹Ä7ÈݨòfÖk¶®ˆ6ÀaÖî‘U&ZÃ’Û¦d6rp©Ý•¯� l„šRî‹qãîI÷ô¢wvÚ?}zq~ÑïõŸžì(® »u­²ïJ“~ÚÚÞ…OâS¨xÑ?éu»gýã^ï¬ß¿ÿÑηÂ"½BÜ]¸ê1�™*D€ªVéÌßõàFÖ×3¢£¶úRMÌvÙ¥k+ #çTÓ2.W®/®wu Ñ'Û¡<ïÃ3_ž72/³-x­‚ôºFA”é»p:@ú€8NhCGK«sI®'î>Œ9$�2àdžÿhhÞk{§5Ø=ÙZëþ@¥¹Û»7 ©þX¡àîÌ9¢‹8ž5MÓ„ëë”îÃpÍÝ_£#3 —Ë>à­oºyp¸8ª­y„O) í¼`tSÙßÚ15ì|zÑÀ½ÈPÐGÜë‡C«Ž¯ Oå 7ȘÂ%᫨ÁL�Èe¢²WÍŸoĵq+T»3Áçt‘½eFö¸qá®my3=Z¿ÌDÙ¶¡h�òmJ êã;°´©æRpŠy«#c³y|@‰R¸ƒñÀh{ŽVqÐ{Þ~ò|c[})÷ñÄo.èƒ.Z-¸.°Ê�zת–¹÷ºÕ¾U£ K‰ ·Ï�TÛÕTE‚�;ÖjÎÝ*/&3¬‡9jR3(¸‰²š ØžÉëSähõ ò'·¾o󢨮àÝ™hÜ�rãœVM7a‡kÆ©>?.éT8ÚÆ;�||¾+ÌúÎîkkÄU6íFš°Ëßíì±:C»ƒ‡ì?ð~…+»ùËP¢P³‰;oܼ5êOxÜ‘™?}ð xU[ÒFdãO6ŽÖZ$”œ 쮋æ‘Óržˆ§s HÙv> WÇ9µÍFZ&ÑðëP€0þ=í¼»)ܽ‰«ºVQßJÀ‘¯l¦~ï¢ÇºŒ©[›5 «¢Fõ2ÚØd@"»E©±6ÂKº¬VWR¨‚2ì’Þ¢"6¾¾*ã<¾ñÞü¶l´q™².µ}Ù€†} ã ôh¿öµËf¡ 4®P¶ œ(viu—Ñ-÷Úá}ýyku}Û…ò„Ðä¶Öc¼ÑªùÅú‡ô¯÷ýjÅ_füý‡+ÿG?\ùßÿVå÷Ÿ§|èç)wþEJò<èž§\F½¨`â®lF"›fN4��kƒiÉb¬B'ØÎÙÅsöR•K‡fÖ;î�¹k+MÃ{%àÍèHÄÄa¬—áŒof(üÄZúEšZ[šg�Îb±ˆM9•Åu+=é�)ÓÎf/ân|¯³Îj“›þê—9ôìW7è¸_³þÃwµ  ‡ ‡Œv™p9xœíY[oÛ6~ϯàl؀ȊӮk7[–¦]¶. àtÅž š¢,.©‘”/À~ü/²éÖNÛTöÐ>-¦¬xüCt‚äûOKÔ]`:=�ž=}ò¨ØÅ”‹œ-�ŸÝÉ_úÞšÛŒ 7a`­s×rD«7çÔ1‰Ïn/8·yÄÅ(™·4æ¢ðˆ¼—Q¬¢õÊ÷µå�t”:/Me¾rNeÈ´bˆVDkØ™O‰Bþ“Ù`�æ&ª€lrämúu˜d1I¸a5êÉ)“ào-aðí÷•Å®0 Q.ik�Ä)q”’žš|mš9"Ÿ‰1V|VÂæï• Tå¥êÉ0’ ݧóxÚ®óŠÇ ¥àŽwl5Æ78³gÌe«×ò»¿ÑGHw¶Cº÷íj§h‘Aîí gÖˆ Ö£ÝJÓ4éâMä;;¤{f!ïuñŒl± ×ãÝrmûòy^2Á©vˆ©ëgŽË–\GÑgm–ÐP]Ã:´ý„œÏ;á;ËÞéŽÁ…"MÃŽô°5Ïú/FJÚ=Ô„‹­‰Þa5óšæ9dHà‰K.0qT·":t�FMv[r�¢ ’2%C5-¨RL•r±#qAr2°r *ä»26Ô#›w¬³sÑÚI.·%9k ÝE9G[T‹ÎmvS0­áÔ'­‚ÓB– KéO );RÅ€’*‡�H…4¯›je…Ë-D%åj'M ˜W€tÌ£´�]G5’Å •{̓Èu#[‘[…µP­@Ä}wj5ÄYl”SLP泬 Õþ|�Å^jÍj/ÄÙ!ŽkN•Ô²0Pœˆ\.4ÎþèHè�'9ä´â}C*>דA@úk—8{e?‚˜¶¼ÊÁbkÖ‰–­¢à=¿ª7ö‰£F¤î÷ ó‘Sp¥ T5¬éÒã KAK¹»‰à‹Å.÷ºNf±=m=…¨#¤Ïá8»rt%7Iý³�-�ue%ÎÎC«w ‘�©t�)�ôNYnáìºq!ëf=rˆ]6[&^½~³–€¼zuïÆHò9zŒÅfŽä9+¸€Hû'QÜæ9¸dt™Ý+ൽrôaQ[èÇógkè^4¼ ãÒåºñ{Þlð€V]€³ÖZ¿ì¹(¤ª�×%*™r“LW†ÙL´ Åoa0µƒßJµÝv­ZßÝs?F»¾èFV E^ ö“qc„c¸|̘ÝÔßè))mahÓO ´ ˆë “ðp t~,ý4ŠÏ‰aI�°o<‚ºyäHXÎ!È&]Iˆ³‹ÍÈ…C/ÂØ!$�"S*“€@ö1(»tÝôÂusâþ•Æž±o¥dÜô…ÿ‡àW¨©$*Ot Z¢­u’ß M:Zï ˜èÛ¿5üÓ´d5éÊ�`/¿M®¯ÐÄ�ôRûì<ömÀÝ@}vA° ª-ëWöÓ»Já2U³ ½µô¾Õ¹ìÊ܃´G•½ãÊ cŸ‰ ®[ËÙr¿£¡ OÛs˜¡ ÷Xû WþîÕa×íQöa!,ŠfÅ„íÎÖ¯›÷½&N¥1²þò ø‰Šÿ¯7Ä/φz6üä—Âȼ RYi(ìÆø wöH™ %ø–±[RÚáE0¸‚-ûâoއOžý„Îe³rÆ�ÎNÏžœ ˆÜ[?B=gsVÙK®¬såÜôZm=@—^I¥1�þ1M‹Å@7%Ël Õ,µ®g VèÙ`88lG‰�BËmóbjÛþ÷‰Qê~)üzY' ™w³r*kxœíZënÛFþϧ˜å¢E X”íd“¶±µp|Épâlä´È¯`Dޤ�);3´¬ÅþØ×Ø×Û'ÙïÌ ©¡d»Mœ¢‹E8’ȹœËw¾sÎ�:¹<¾úðö”Íí¢%É}²’W³ÃTTƒ÷ã”ÜòA®*+*ûQ+eÓ,¦£„±ƒ¹à}Á×…°œås®�ÀˆÆNߥl߬øB¦7R,k¥mÊš‡éRv~Xˆ™‹�û±Ãd%­äåÀ伇{Ù.-öøuœHAÖvÚ™¬ 6®…(ŽuSåsÌ1–—%·RUî‡nrúnØTiö†«¥Ùa ž_ŽÇä Y5·´W^6…¬fŒã“R0Œ¬JÅ ¯y~ÍgÓ*|hãfNYºS­̨Fç"KƒŠ…0¹–5míäö¶´Ò–btÉx0ô×üýRV×L‹ò05vU 3F²«+Zqk‡¹1)›k1uŽüˆu¬Ì‡õj¶€9L†Û½9Ü�NÄôéóȇŸ¹îÏ ××aÑÉîdÿ»gO¦w- «Š[¬Gš¦çþW·ÚLTn@Fø¼kz ºÙgRËÆVÔ�DSº™péÞ5j-nº5Þ¡Ù«F¢]âab£tboÛÇ»ñ`è"ç`¢Š• $�–¼äÆ@~3ášù��UuêwsuØÙÌã=ýËîWa.óh‘�´bÁÚ/ƒÝ4 ¿NÂÁ(£8 ö²=à7og|ľþóÞwÏ_<¸Ñ^´Ñz³È|£µqiÍh´×mh‹í㥜U‡©–³9lû Òð„—¥ý²!Ë–$ñÍmÇÇwyž c®Åê0}›Ž*R5¦/þ?Ù¯�hÿ‰¶Ðy‡\1¨ïìM:¢8ø ¡žÜ!ÐaòÁX ç?l´³0ŠùÀ�GŒÚ>ÇXOï–«OwÈóJTBóòq"s�§#·JO®$ú耈/ºýB‘Šï~@!oZáÛPYÃòŽ›KÍëZè4Æ|<Ž!eZ‘ .«Þ@ÏFxKË‚�¼Îz0ßÛH ¸�ôf,d®•QS‹éò˜›¶?zÝ^oóæîãVÝ£„(ÿÁG?7R Ó]øQbg†•X"„¾y²?˜HëÒܳ§îë ÒáÛ,ù –óŠ5´7W V¹_BÚ9¦ã¿6ã—òÚ¼š„•˜šÆ™;c/•�ÓE ÆR\ãï†ËÒ±«K±1ئB‹*ÇŽ·V芗-qÏ­­ -œû…•ž¥#’ ¶ÆRL PJðɆµ³ÖUOìðÍô¦Aì=3+CX'ûäZp+¨$`‰^a¢Ó�iØ¥ä¾0±»šKÃj­Åkðb�J• ·0•£JÓÉtT:ý¬¼åj‡6G²rÆŽ�Êî6ê[Î%mnXA;ÈIcE‘plÊrUˆãVBÙF¡à«ä© °(ÒÑ�©¡] úLGÙ?d}0¤Ë£ƒ!-4‚Ãò9¤ Z¶òtZVªW›í0#u¹"jž[Ø J8`Zš©74ð…ŠÐ!‚¬V(¹:YÔLóE:Šý-náV?n”�E`àBú=m,šš&dB œ%¡ ·¦M ‘Z£þÀÎ-3p 9©,!¢a¨�-j>_6”n¨ÆfDÝX0Áþ0¦óŠqW°\ Í ¡è™Àøª–¢ yö¦ÈÉÕ¢†‹t«0I¨E@Ã0�Á&-ð\µTàêÚ;ÿs„/}÷žfOÙ7cU©ÿ–B”<­;Ø�„Ú×#ÙÍ€®™\Pü[FãSµ€bv‡l�šÏX³†8Aô ž€Åà‚û&Õu)sšŸáñÖ)~Y1—ÐCض�ÅܤTùuOì‰È9E"° �Â…„-9]9Ðˈºè,¹¬€*ªÖÐk`´ƒv×^ˆ~ãlKóÕt*s´?­q$ÐÎ@6BY;ñ@Aog¶>Wå‚ /ª¼vªlMÂ5ŸÈ܇  è”rDÊÓ´7Ê3˜§8Oò÷¹Ásá8DFkدgöÅ}SÞjyÃóûš/ꘙ7ZÚU˜é|q0„H­\cä7Ä”¼O„þ ^h¸úú¾ ¤i;à`;ªVKÞ®œ´�g®-y�U‘¹u¾^òÊv>"£’ÈØiE‘îhî5ÏÑd³Tº €pT9E¼ðP•]ŽúÕÒb?Ï&N¥Ð—OTCÙ�Íis>íäpØO¸…Ck$,~-b1¡¶×‘Ùm.ê@áÊiGl¶…¾Jé'6u«ƒ`‹, ñ«iÃo45qqÆ Ž¸q(ª_ gTá!Ü`.Êz¸˜?Ý}¶÷l¸ÿœ®áÃGºøÏ¿þ ÂFÑ=˜¬ôÙ;ˆRÿ=ÄZÒÑ@ VwLÐ+X"œÄ*VoKˆ¢-‡\H‡#—ÿo$EýdåmÞef웨0¼‹þ3sͯ»ùAäXÎx�A;ÎÉýdtÝcoÃ=èñÄéñšW+¯IO Jw¨jŠU8ké =ýó…DÝ"jšRZBFÔ”)¯»Æˆ°ÌÊ»B0ÕSŽ+£Í3v†=0™¸i‡Fœˆ‰„i)¼Ÿ4•mvB…édëÓg{R³å X#*:¯qUдÀŠ�{=üàvàN>¡8æGd]ÏO}|ÔÂïí¢�}xêÀ˜µ sy%zoV[w Äe^¾…ð6M¡z\°LG,ÜãµÌ„½ïv°Ë}·£„�èp!…Jø@så+üç�š+g¢Pšïô, {Q PùìÿÕE5ý=Ì<È{Q—âh°wDá8¥“SÊsµŒÃ³-–A=å$Ž' a®­ª·˜Â¨Ž&PŒ×h8ÖsÉ)í¼.´)-&!@Q>ñö›yõ^ržz^ 4X²#¶OÉ2a%ªL‡éz%>ry³§î€Îˆ¸H¯¢;¦\g72 ¦âQÁéHѕنXѵÂZ”‚±ÑµõóµkÖ6²À§Uà­’óf)‰_½î×�Qí° ga€ƒÎçÚ­RSc3÷ Ég®¾wµŠî’`îÞýVN$x` ÖÔIkZ#ˆèÌZÝ…o$jÚ>×PpŸÂÂfˆ YÜÈD;AGê×:BèV¼-߃çöi€¤ø§ ¡öxÙ{Ð0v·ºRäj£•ò3™kî%u{A/+árí§b&�üTu� Ñ#åJk!yÜÍ¥£WÒþ͉JÎð{] ¬²„r¹S­m@݃ çÀžç!õ¾5×l'ÊÔ` Ä‹ñÍ`pòÆ3Ô¡TWÆÇSéžß|Ú™ÆË÷ç'ço^e‹bóhõ\‘^Œž¥u‘s!sQ±ñìÉ„êã'šAL«q“ÈÂsÁñk~-¨äQÇ1çoÆWG/Î�OߌOÇòbʛҺ2ìQû\ž�õ—Ψí{Üšƒ“Mé/ßl(°NI„uÇNe0>=¦q°ú;˜ÂGb_ÜËê‘ö˜“&”&”¼’î �|/çÇûe<7¡ú,¨˜Ä„VU¹Ç/ëå{Ë=‘Ç—o? µ�nd" zˆ¶•lsL‡Hw”ú(¯¸`øøãÑ»ó£7Wá÷óãó£‹�ïN/N�Ƨ›ñ�Øü-v{{ùîêèåÅé=ÛÂ#¹xœš¿½ŠÜ*YRŽùâ0ߌ&" êyK‰æÿKúïäôGü½|ÿjc?T7¸cÐpT@qÅ«íïééZ¸þ #nxI§W•K©9ÏqÉ™…㎖tÂ!M‚ÄMU K):;­YDÚmpQ0—/@Œ·HõtÓg‰îŒt§]ªÖnE‘i~ êÙb¸6¦BóÜöïÚ¸ÓY°S¬—ZS´GÅ¡QVË*Y—ŽV©2´Ç¾„ö‰Æ¥Ê¢o0ä¹ õ o¯ˆþv_…õÛã¢íÁ.›ùÄ9‰û[ãŒQ­Õ5)TˆI3C籘�b�c×¶˜¬ÚltWV$ÞJ:_·Õqð¹ù?¾zwþöãËó7Gï>l;rØ,¥ñ§IÄ­Q ´ÊÍ܃Jëµ¢¾‚QTÒ#:·´„´å*UÀsWø: „žÛL˜ö Û@ûÜ-î#§3ÅY£ýÓ“dý¾Ê £¦ûi‹@dIÛ{ócë ’)BŒ¯„Ø" “<ϾÁŽU½rpfû»ûÏvØf÷~Ò>44YØëؽ^@/lÙïÒ—Ëef깬nˆØp¼3v\Ð~Ÿíe»YŸvÖvßœúë×cè»»í`èÞ-ý/")7†Ò5¹mn«w¡j¼šEP…ä²â(cóAÈõµÂËcp|üp9»|pÜà”Ž2tŒ–å`yÔåÃJVŸ¾Í«eßIhØ ë¸þþï›ä~5‰Ñª¼‹ÝüËãæà[óŸ‡ â S®@vÓî@©b<ãXá; ©ýnm¼Þ5˹~\1pž:ôq8.Ð ßh$²L´$ÁÔM ¶Ï·d <`û…-PÖvý?ÿa× ¶1¿ÎvC>Û¹Éî:ß)€ ²Ân.Í–sNöù4ƒq–fS †î„’î‘#�ë͵Šs K#ÍâÔ…«9Eƒ>þª{Ó8>>ü“»”p�›ãß›>stÇK;^XZ‹0�·¢§ SeékÏÂ!}_$û5Ñ&UskÖ­I>^7*ÝD5èŒ"3\ϳÔùÚ¯¬Y„g ÐÖ$êA/¨é÷ä¯÷ܸ&¹&'YV®vb{¤k�É]¨ahAó¬BÁ¡F¥¦ÐVôbK£þTÁ½†kè·:Ü/ÈX† bÝAÀ¤£x<ƒaÈ`&žmÀ||G3´b±¥‚~ͳ2æ`‘Tb,püŽ…D¨�-™y’´%b@F¼ÃCƒb½—z¢.ãlÛûôIO˥NJ‚ÓvÈÖŸ¨á|9Ô;õ,nº|ÎOÞœ¶t»kåyUéõçnÝ\2E;/àþh[øÖß_KYmÖ�·˜C‡Îíñ,n· ‘,’µ’%Žg¾¡UãîÏb:V{'pÓ&vl><�ÀÓÔʪεkÞ–„½©Y){;1vsSœQÅŒЉÜ׋GaÞnX´‰Ù'Çt©(ˆ�­ý°Åø‡ïPXˆiY¸»¢¸âHæ&Mf�“…W‡3rÐu©Ê#ß­Áƒ**�Š"íñÝç�*?O³pŠ+âçNñŸºuè®;ö2Ä—­3q Ômæ²Ožñ¾ÃÞÑ\"<ã[‡«+Uú9ž÷ñ•‡!ÜW äeƇiAá@‘Ÿ9îÕ°–ÛìKÎizL$MdÑio¢½ÙgêtÍ«¨àÉ”üß@ø8Ðaø2«4‡{Ù8I‰ü°¡‡HVÖ'Cf£(tmÜ*`ékøk ©ÚZȯæ&&:Äh¹Ë¸ŒÅo‚Q™·¢Ko&Íà-‚šå,£”^Ø¥ ã¥ãEa�½à•ÄãŠ7ؽ,Â{y¸›I„’® ‡‘42çT¥jÌÎB:`óÃíÒöÑ"dÂ-Y¨= '”OZpšqR ËŒqƒ/V½ðm‡íÛ€˜åjÑHñ| Ç…ëmL+²˜ ö§1p²Â8émòWÅlˆÞ¨ƒ:"í}ásñ%ô¦p&©®�Ô½s�EÚ䫼/ñÎ�ÈgÉrèbªVÐÚÍ1UK¡MZÃ[“Çõ´qÑß!ê9¸™0¸šÀÌ08d)àC›L°z˜´q_ÜD' ìpgŽc/<“ÃŒO¢9 n~|Ÿ-%¢•²Ì&°•¿EÐý\eA¡9”BkP`9�%!0²q§¡º‚£o÷×@åÂ`qð€GºÒɈ§kS3±ú×£"/8êʈ�ô:Å}£- ÃF>?›$0fW�mtø'°wŒæäå©Âh²í ±ñ‡ßýSekMµ—.�Ò$iÁƒfb²]Rh®Ð5²‘Hp†=ãq²Ûº|Ù äñ)´Tm˜]øáz/žc,ÞFo¾ä·‚ý 3 ïP›)yàÝ}¶œ‰Š•š“çi Ç£˜cnïŒÙy:k(glé<“q»G;5o™QÛÜ諸­nf#Ñáx—¾BÊñ¦½ðÃ31ö5Š‹Ò¸Qàd‰HÇœ—ƶˈí[ ç¯ã˜Á%b�XÞ´"c¬ý[O=° &k ª9>PQÈg2kr ®8ÖD(ºR•¸� �JÝmoo›zÙÜë(#•íg‚[W£•«—>[<¶.Y:�@^Âäœ(J_“á7ròFŒ’a?pF;6­`‚»¤ÝõèþeU©‰!�‡ªˆØÇe #à 9 ¹!̰á'x#ò‘žl±0¬Ô >Àïx§ ÀR�—¶ƒgU6V½‚Æïή¹ž0ù3¸_¾b1ÄQL9GÑyfÐXqÃGQ=DÅ6lbÁÁ­Æ»}u{ ŽTŠÅƒmѱ��F”ôÆa#p¨‰›l†ÉËÝ@%(3•tø²@$Ü|Äl!×?‹ rëK°ô%W«-xã÷‚Ó4ÔÓ¼š›÷ïŠÏzb„Égfm%e¥f™- %'|‹AÏÊÿŒ•›d„€ç’ê¾g™`/üN ïx¸QâÌÜŽ8 F'XÜh†Á¦•x Z¬� ´â†@”Àxô瀸›z™ètö÷£vû{»~æÐÛåT(“ôb4µg.³ÿ'|>—¬Îö3�ñTÜúãHˆ& @3‚]ø‚2ŒN)³‡bQ½3LaÌ•€ÛDª¬}‘¾Vî=¶ÎªŽ‚.hË‹xè'α-c±h�µ¦”J’b”ØXš†gí ¹-¢Ì÷®ÝBª@Tp�e¼}Ù;o´}g³dð�Uß_Š^[3ÃÕ[‹ bÎK£JO™Åºezî_-ÿ¥Ë‹¿'XÿÜá‰'ä‰t¤Ý»…@p&1‚˜hM§Š\.Мˆn…n*{nY°@m¤ÙY ŠŒ¢¥é™¬Öƒ†¢° ¨PG°è|i~OI—JQAõe–C¤b‹ºò¼sô7Üêè Eƒd\aˆx5)²Ù˜âw8Óq Ïe‡0Ò«ª´J2S¹�,¼ÍQ=›Y ,•’Ô'™�Ã,QEd‘””Xûœ™üࢠkk(‘¬àE]öVZ{-|ß*Ç{äµB…‡7ì7ÄÂcÆVëMnÒ¸'YRc§ñid"FDóÖ&Y˱Èöç@6ÎH ¦Šz}…9ù,·…š©5ÛÆÁýE3…Rèóð˹$Ô9$T wµ‘ÇF¸,c±wè42ùGÞædü^ 'h(!s�Kâ>oÝHlÓó ]å*.H­KA`p½ÅÁÒaÉÞ$”>6Ç{sÊàš¬\“Òm;€‡2ާ«æâ'eu_÷Æ=ĉ«;á¼ÖÚt€Áy–wg9ï�ÝÊ;“ll œ÷ê„Ù„þ„“ç­Uˆa˜ §ÀÂJ+A�jÔ‹JÆ“ d~��+'Ð2Êf£QL1q!ïƒ@g¹øBÐ�HÇiÈ©Îl/¤2DLRÖ%©Ðõ€cPºÄkÃÌ)ÈÉRî2‹1@Y2ؽôyŠ�ár^¼ìŸWá'½OŸxŠŽIv$§�õ�—z&±XšŠå±ÑM�f.ùé´â^ð)Q Ú;`*‘}K Ð1UÅ*³H¦b/ÖÂ2ÎÀSÜ4kTL”D¢a�&Ö8PÌñ¼êJô~®/Š‘ÃÈvëùŒƒr6†»’ÝY¯MY”ÍKÿh‰.›«ñU[9IÆZ™Ì%d©’RuYnN…_ös5Öý �T_s±<Å9ZÆ[�;Tä Ãæ¸Íƒ%Íòª4A+ÂD=ŒëššŠ9«üMÇ‹0¬¢Â Ô¼ýÍuo¾Îx:…_cMу6ö9ç—¾BäoN(åPå¦vHÓ¸4)¹ÊGÀ6utB,4BÊP}†îPŸ‘K ÃÁm*úÌ¿´æ7ªê@�ÔáÈ£ÅYöQÑ2‡¾ïÜ—²gÉ\x428±WeŽmÚö0aœ×¤‡Y‚×Ý»+·XnÛÛfm]×cH�½ 8�Zí¸µâîK?u+å˜6ctø ¿œd< *Ùtx©ˆê.F²GnV£Ï?ûèTB;T‚æR>)(Ž4ÍóõkÜòÅr¢g'$ºÀ ¢©_ ­›]Ð('œÄ¤b†„ªô/„;¶kÚäAƒˆs¿©³7Æ=I²|P(:Fx Óh¹É=¼“ó{s"YeÅÍÔÅ©{K/Ñ3qFáS ¼|ý çù‘ÙØKtªÒÒˆvÖØo/Vçr4 ›PqvÞWm Ã}³ÇŠSn­A.YÔì¨wteÊBZªý®%ºœ‰ÑSCõ¼µˆùFh‘B Û_¡0Ãß".½JÌ.«ãIÄ Ä»¢Ôl/ ú‰è‘hh�ŒuûMÅÎÜb;°µÏ^LȵÃ0xd¨©tï¶°QFx…GõüÛzb�±€T ÄséoP,S.}ÎÎtéþ¯ÌMju¹Ë¡â&yAßõŸÑwÖ3Ró÷×*ÑI •8sCà,ÀFK‰ï±±¶SáW· N@g•õ ¬PGUë’{Núu3䙎?kÞœí\w¤Ñª*.niâ-àЗ)θ®+ÅZÊÏ¢ÅáU‰b„V©ý‚k2oÄöK¸LM»’ià*¢‰ýÛ®–÷Š>⋲ÐÞE*ÚTc‚µðÏ´`v€ ì½Äµá2®'g×Cœë:@¡Ì{^ÌQ–UpNt×Ä4OSóƒÑÑ“gtdÚ@ÀYëâkTý²þ(íÊÎ$y´ô WÂR�„¶¸aPÛa®U>ƒ�ërѽ„õzÓ²%%ESƒí!Àš uÈFÓùð£‚QÅF•K²š¦~ \=cÐã�˜&’ò9 ¹~ˆ@Z�g QÈ�ËìØgðsB/YÍ�qŸ7«%Å‘5—XŽhƒrØ;P; †.ÑKe⊟Âò*ûá1’äFómãàT­ùJÀà1cL¸‡•A›çcfÒ4’V½Cå¦/ß~ýÕF‡ _4‡‰©ßæä¥Ò}ƒòZlûI¸p&ù›_ üÞ R ù¶¡î.=€“x —%F²³ÖñŒ�æH… £åã´Z²OtgÅ\™T.P4ŠF!Â4aœŠ�²æ =_;À÷±’RkŽAÀ`ÌBc°ñU3›UäEáK¯`dMËóGc>¤B²¼sƒ ¶kcߎs‚#Pl¨qÇ.‰Ê^ÊrÈ#Ã' kV¦V,»JßM>ŠSŒ[™b÷�æ•{y™�“ê‘�B]WKžÜöMhéµÃR]!µèm�’ÐY;Ï�¥;DÔ4‘ÀzZZ®8+N\Ù€õ\Ùø©û®ø÷š?‰©º¦¢¥1xi�ŠÊ¢Å™ÈYÛH"ÉN6¦\´ Κ‘f«ÄÕ&¼È2G-TÐ…ª2˜PŠë�œrD—£ETÝG«Û„0's]ª$|jÙÉ£1¤0qo¡®Å)É2�Eoa1±Ô I!Œ¤ŽÁÕ¡Ãø«y�¯Ã7ZŽPWî’éÈ»!¹M…¼¸(mÉÍ3ßzÔoåêò6·™©±NB»¯S| Θõ'2å78K Âºš:ut™.TøFà;Ö«F|–V ´Ï9KðêçÄf×öÌW©0QÑ-Z¶,öEJøZ h(öÎ÷¯=AÄe¼,ˆô­ÜÆ/ÕˆãØF¯0òp–¦Vó©¶ÉÔüg›ÒB†"S†Å\À¶ˆ;¥­I¤Ç…ö-§¦�køFÊâûïV\§Þ…ˆx‹Y:¤(À—eáR–ѹ؇EþN\ðùn NÞ˜B#n^×ìužÂ=c¾nf2»4Jñµ¹•ìË5âħê‚yßÜÓ°áOŠ“££SÓ-�µ&H3Ñ£' %“—#ªm)SŒ�1É/¼ª›®Ái‡ø5q€\ò5LW:m¨ØŒv¦ÆÒgÆäœ¹eû¹�Œ6¿÷–mªê‰±5Á…‘Ò‚—5}µ·dãXœøì:æÞC¾öAIx‚ŠòZéæ:{”–VSYøfº´VŠœõ7¿¹¦wZ¯Á]ÕЗ‡ÄLõTäóÞöؼ]45¹Âðè÷íFEŒNu|¢?ñ2›kV¨lY ¬7‹•/ˆiø†9ï-&Ƭ¾O<ƒ$ãº1-†2SíÍŸ$pÅŒOCð9\r%ûU¦Lô¿„¼4o@øMKv¿ 㱕C o²óÓ7\¼†V%k7Å.‚W7d3´-fY�>ï-‡sÏ{>ä¸ÄÌ®Y¦³j¡¿SÒm¡Q²0ðS…‘/’°�û¢l‚¶Hrµƒk&©X2(kŸâö==FPÃ%<¨NžuÃÓ\ €¤P5Uo¤¶Ïš¥Ù³´ÝÃ|ỗ‰®¸‚bŽë(“U؆^¢ méHè³AÇÜ%rɳtÿ.nZgÙØxû�ù¬ótàæâ]¸í›OÐU/)ĵtì�äµ­ªn.häÚ.;$~¾¼!ézâ¿(žØ^²Ã¥w:ì�îÔ›G+ çñ/™o /�yn–¤k*¸Åž¼mPµ+ :‹+ Wΰ»�X±é�XèF!¶·cš_»N§-LÎãñÆ.TH,øÕbÖË)@“/E¯#�&ìž¡ÇA¶Â7@G@Çv|ç3�Š3ÅhŒ*m6 ¦s¤;Z¢ü2>VWãgé!ÂÙ€á`P£=Š5…[�T¡ÛÍÜõfH„@OÃeÙð.8Íõ¥<žåIq,•‹ÁðX£™ˆ’â€uîû½Uâôö¦v?2Ä€þÆyˆq!Øë%Y‹RfûÉÃ.ÂÓ³²‹¯Ç(>p=ÔÄ»„t*×?G‰y¶ êçØb¶uj&‹xuÙ'—·#$S÷x:|ë¡Ýdhÿð¢€?НuÔÍ3tnºÅý¦;…¼Ybñ~ȽpŒØd‘‘]“t{àDQ|? ‘˜¯º?åÁR-Ýo^c0/Á…Ø1E‡]n6Ï0“NÈ.×1E3 ”D7à⨆Õo¼´ ¯ÏñÕ‚Ycñ1Þ‚8]Šh)T�`Ô *`S±Á¤1¿KµW>‹¼~JŸá3&ÒŠˆ]#àY:îÇÉ-k!@{/º½'¾AY�äÖHÉ×}›Ö¦ìÝâÆ¦nÙ]ÇÇj‹¨u8mÁ’º�Íî±WQ`ÜDèä´3©.”†Yh½käº*ÞëáöŽ–"Ñ%äÌX�»[EÚ¯¬.ªø*nYö[6]Dvõ*±(Àª†Ö6êß([¼:ê?¨ ⻑>ãp¢Í¼(DÙu<õ”Æ`ý�fÓ8UÔD•òEצpj®5Ãt,»žB{hœÖ9FðÜõ­÷Á!w¾éÖ‘‘ë®Gö+”w%…§kC¶õ•6»x+æq¡XØV~úÃßü5 úÉN=Ú1�åoŠjÿø`aÔ`ë¦H4òƒƒ&Yö‚gLïâE®Ø?Ì/v¯»˜ý{Ñ•9º$ÆÃèÕ ‹æðOÿC_STMïa ½Õ¯v+j–ë4«#`ˆžŽ†L]õ¥´=_êx™Vºô× AÃÒ ÷u„xyÇ5–ÃŽ.yÁô>hXãÐHz´M06€á£�o"„ÿÜj4DZ«ZUøtÄöß²eÆx‰}Ñàé‡?ü­OÜ‹¸ZËR¦ìu1üà蛸è/èøx<ö?ýì³£££�Ž?=>::<:<>üؾÐ'Ò¶Ê8ÿSÁUÖÇ×—Ã×§£zò¾ÚVÝÕO¨VÏ-¸DêíÐ;aÜÓ=–ZºïZŒz5¬VJN*©‰>¾¶Ïv Û—pÇÞ,Û5 œ¸—–ÀyôÉÖ²×9L2Öå �E1¼†–`Æ EÃ7>°k £nÞ.«w+…w÷´(ƒžü)Hár ŸU¦ü…�-*{nÂ�ÍKE­¥ŠÚ»7à­´àÐ ÑÅ«@¢NÉÁñ5Ý b¥Ç6™�Ò1YäL&¨ Ž›ÞXêønÃ&É®ÉMí©ÕÍZ²lÀU,‚Û@¯×·?ö)`–‰¡&µ®¢ƒö�>1pqËm€)‡=¸ÈöBªó†gµ$_|»†×@%‚ÿv‚ÒvZĹ8Ý_茮8Ýt;¸‡YiáÆÏ»…Flƒ[lb· "LŸ’ûL(Φmƒšë¨»½Éë�Šb•¶°.´sô£)Ò‹4‹…ˆG3 ²�‹!ESØ‘ù¹±…¶Òãú�`××ÁÓšÖšE´ �~ðÉá÷ÿyëKá‹bVÇ[¡õ£ÃC;Â{À]7ÜA,ì·=˜Ñ½!nŽèåíí)ú2Kf5+Mã\Ø648ò†x6qåÉØ×]¡j¾Ž8:®y8ÎøÙð%?Û sU~`Ô�Í¿–:.Ì,pÉš^¬wžg›Ìæ#¿˜ª1 Ýߤ6N§˜ MP7H_añqo[N¼x6�Ç1"•‰n‰] "|„#F)Ï•I�뫎°-Ë; öt)‘…6a3CN%l}\Ôð®Ã3[÷�–ÌËG�“ð%ÕöLZ Üå×¶,´h­%òšÐ ¿­jØ@ eÎ>$fE°¿eðçƒ�>þäÓýÛðÒ%¡ÐŽtMuȶ(êz�u•g%ð…|‚ùßÛÐÏŸ6h¦#nbàãdÜ£øFÌÄ(©ãŸ]4îVs’ ¸¾M%(­îPÏi¿Õ—ý*ÖÃI¥±“Aœš6PS¬t;œ¤x�„&¾&8�a‰yÕÿBÃñKçUjÅŠ„>,œ‰ˆQÜûFý‹ƒFW8]HÃÔÑ-�d»15/vÈOž©JAX鯂F0 î Õ°ÈJ,p2O8ãPR½ Óíç ðÈQjl£öj°bÓ „S³§d¡v›7„KýUàJ|j?ÉÐÆoâsΆå@œ´qØ\ád2æsaÛÕw·v±ë]7‰§q%hæ{Žíð¾Âšñ‚�k¯ì–$E¯(ŒI¼l6·}Qµt|¾m-…E8[îó³6¸{V”.I´^ÌH:�Éc�)ë.I ¼:®×RoÁµÐ6ŒÒ+ ¦H5góp*©çóó0µ%¤ BÔ›‚_×ñt65äb¥Àb^Âèå˜���ßï¸>±Epë„OM±>øÑáá¡"×^õ‹4 êòû]âÅ_Rèeiª Ç¥€ŽÒÌõ�é’™¨Z0í(N%QµO IÖ€øJÆ·1šaa”Z“M®†ÁàùÐÕ&åØR=çš=-Äh‚msÛâ:‡BѺ¸zçTxbËé¸w³\;Ÿàlfá ¦Wp[ü°íG^ÏZ6áÒÖ$=ÚäÞïÞru›æI¾føêæ&JÜ›�O<5Á!Va·)w¸¢/OغÍÄ¥ÁÑ�u�£FÉ\«Ý–ÀhïZä5„ ¹!TàUÍÞuà$6â“®W¯M¡NìÆsmmŸµ–3æÂ‰Ù ÕìíêX¸Ç�w ó)›]aº·Y1ýLÒè[ÚÆÓE‘åÈ­ýVKåÖ¥Ë%Ü7¦òü>^ù¿8: ©å –»À‘ ™�T&‚æfÌmÁzW–ûV(¨M²4+¸‘\‚•=æÒ×�¥Çv3Ûæ¦cZ¶àˆSÉ)?ß ®3�$˜êdkÙpã´[ÌäºÄÛº¥nÎ×Xäª7çmwÁn•CܘCÄ…µálÁ>Ì’ÙT:î�àÐ5‚ªÛ ¯=‡ÍïŒ5•Å´²#U¸ðÎ*¨Z1QeÌÉor“øéÛY•ë´ü¾¤R¯<5†Ì¿v�Ä5qÉ3¨Ûeút…$:ÐM⵩ô•äu±‚€ÈÂf2©ùz»L¹—Z¡Ö ¿TÉ(<Á)ܧI�¦œZ�ƒÝðÂç+mé7ŽÙYãõgX¢‡_Ç8·âm†Õõ‰I…û^ìk½÷áø÷áþPÇÉZ¯ýð‡M/Ž’,+êfŽêN7¢·Vyˆ t¹¤üÖðBƒAœbÑ’EÇ@D³HËq—>›…ŠUÚÆÊT6ZŽÿÚm¼�Ùég˹› ¼=ŽŒÊŸoÇ4�{ǯ(+Ñýɸz¸üçã^#ݤ³�zÙÝœî<»ÖÌnu´oA¾ãÌò=·Ç"³Pã½µI�Á•^hn K(]ÔPȾTt{x·zá7¥kKèÕ=ÇxL¯öÕ¢«x:+¥„;›÷°6½•Ê #wÆs¯³k/ü sÊÈçÔª#Y—BÇšVe\ ò”ú734¢ÖÜÊè7k}h ¤KÜï^Q嬈1ØÛÚÿï2$ÖÐÃBQÊ•ñïí.7ªt.&k¡³œDAјµ8vô¡ßŽÑ|°�Ú±<¬g!³C`½±|ÉÚˆ¤T€—ÍÈ¡6œm’�¢÷�e �p~¬¹s HmŽíøÁôû?–?üþ¿ÿßšJ•ʲŒpaÖíxâ´_Þí=‡åA©¼¸É†9õ£LÚ.¼Z —FgMª¯àoÓœÀ–0�~˜Äù ëqë¼k®½<7uÂa*Wê¸ÍwA1/âÙ ÷Å‚zP÷ª(*�gÞx‘ªËXUÎòT[FŠ@ÏMÅ6?4Ús¢ÓŠ›WQ¡à ^o‡ƒmqˆBçš7RCòS�<»¢Ð2rœ%ÌhikÛœ³FËcñ€ è©æT] ypÊŒ¹+añ+–³a,uÀ„y÷½.ãü1Vë횥¦¶Ž‚% �º:òœƒÍ œa•võ4|½E½Âã=š¡Ó6šIGGß‹´ÝÙV–pÖ«"ûӆˆÛ£ϸˆ«ŠªÐ—ì=^ÁäΡæ…[ùs¶‚³å§ïÿ¸ü7•¶3Ÿœûõz]­Ì^o)ÿ­XâË\ñæ^çñÁ_ßøÈò>^ùîòmÒÈO>8úäðáz{ †Áÿòx5h.ÿéAÓþŒc0è*3ÚCëZ#Ô«Û¿ëITés³âH@P?üþïP…ûýßѧ¿ùkøÀê÷¿ÿO¿;ð¿©ýýqË/}øß>ï ¿�_~ÿ4�Ã�[‡Çß?î} ¿Â??¢"7+cˆ¤d²ÄI^�Ä-tÒXÓeËnRNxJ•\©ÂÁ�’‡d¾Hu� K¼p!XJw B˜Ò2‹Ç!©›î–¼;/ñ¹]9²#Š8¯¤� : àʪ$ÙÇt¸ ]Àw/Àdvô|£ÝÜ�FISªJ[�×xÞtïª�Ô¤ôÃÐmÈ„×þZ’vlÈ9ùè-æx‘À·eŽÛ»6aô¨+W°¸¾VÔÊ&(±ïŒÍ6Fü+Y&¬RÍÊ™J°×#Ò¯-•|9ì¸+Èá~_®#%‰Vʬ§�¹¨#îy!”ª`M?ÇëepèK\”’B��¦óG™S;%*§ŠdÅþsé’©¥ÅO@l«Ùó]F7ð‰ ŠªßòéŠZ^h8—[¸¯ñlv_ðyS­bø‹‘´)õˆ¢ÖbÒý°©”mgúÙéhÿ¼EaÜjÀ~s@_“av°¥ÖÙ °hóÊ£,O»ôi…Ÿß”žÙñzÁ¹„<ª6I-WÚ:,# â5Ú,KR­¬m'À/zFíÙÖV°B ^Œ.39Ÿ”„h±gÊ mI¡G�¥Rþ`Иp!*­�Ÿš¤ ÒÌOJ<å˜äD×qY2+ IÚϪ¤ðCÓ‚c©g­Ð]Ày¾Ê�J‘>|²¥àÇkqR¥�è® êI•@ZÍ„Èt5UØI<``»5³Eid¯<²±‹ñàØaÈ»›¨‰†—‡Js²ý9”$u‚’,»@ËGfe4ô¿€s™¸Ÿ•X]©uX=Ë[LÜØs»äŽ©néÀJ‘¶¥•ûcˆ|Òõ„;£6%-îkua{a Œi¶-â¼R"È—œ?E$ô…QªM’íanz¥,€¿™£I�ÉU*ùvW&A ‡œ”ëÒ>D: ¬tôãÙ©gåPå: Nr¿9t¸IžÀ\£>CqK‰í½!¡µ%aÊCréð”BãŸÙ¬˜e+ÌÙ¹!†èA>�˜D¡Zf‰ÄÝ›” ÃÞZHCQ^´ÏÖèf?û¸œ�ÇØ¥Ù´/fUVô_j @^FÓà•Êä”Ìêé¸� ¡üd+ùã”ÀX.¡è°üW2n6¤—€×<ÿ< ±DÔšÅYÔÙðxîŒâR‹bIÛáÒ�˜£r¡ç%wÎm¿^@~<Ìja%Žq Lrº�®Þà dš�*g¾mbrrÌ}¾ô>ð³ Â÷ïä7œð¾uÔ-5Äö€ãŒœË\.i‘Ro¬%²Y?™Å ª¯Ê»Z,ìÊäkÅ� áÜþt>[¿ß- ¦+ûÍ€Z?×]Š.ç¥ ”9\Ž:êâÑ$O3³²6̘êNs°ë–v†Mè»Yw©›µ*r'[±Ð饨yzPÿ˜·0J¯q œ÷¹×4лíÞƒÚ�·½Ï¿ÉûOÑv{J7ˆïXu±›èŠõ®»or¹ë(öe­W<{Qúâ�ôì¶µ(î–½¾DSvƒ¾ät¥6D_ƒ �R"ëI¾»; VØÆ/° ~ÊZÝî x•Ú�6æ‘­8°Ü0¶ë7Œm‘´Z7x© +«[B?ÀBŒ‰˜Ü|£¦BΈ‡wv—ØÎ»ZØÂE®ðÞúÛˆ·‘£v¤†ºkœ0âCƾ0¿†Æ ¹‰?nU¯Wà˜S½"ã1[á3’Ýã7Äâ“+¬i‹u톿Bƒ�¼áÑ-kýT�§¹«3ÆÀ¹Ì|†Çäh#„¢JûéØR ‡$½òK¹‹ž#Ÿš?¨úD­}a­Üš÷8ÖWOOžÎÊ‹Qvý¨ŸyÈZ�¡%ëz]«j€¨Sr ÄoEELÄmcJ ª„gR2”Ò3)°CVµ®oU3�³Ø¢ƒÝðÆ¿<Ì’¬(©–ŠéÝÆÅ’Äãkä}±BnÅ[Ü´�£O@„c�Rׄ2Àd0�°_ý쫳/á f*gHmŸK 2€Â"á©�W,NŠ {|³œÏ|^dãÂ4DÝ ‹.ÎDØ_˜‚°K¬®Ør\dãÒIZEÔt„(acfŠÄ¥bXÁϨü€˜™`°P!¶rƒ%U”^Çrƒ â}yOU1ï£n†A²„/WÎ@¤×!r'Œ�Ú®ô)O×¶KޤÑÛ ˜5€FuXh͆+#6J©Ò6iÄæ�h•f,ª² Ü#ôeí&sÿŽ??bSü�Ì¥G>½–jZpô�_¦…© äŠ¢Éò¬$Òc›Ýc•bøtAŽk:9 Š£“=H°m$¹ clOæ BŽ«­•k³�Û÷3¢«Úi:¼Œ#®þÕJâså7Ñ7^¡DŠ|){�‰‰`«]þàÍ›/¾xò¤±Ë@nì¾jXáíÊ[ïRÿ±ð ‰éÇÔD&ÎàÖž ޱ厭Öf­íõD¹¬Q½‘ío–úÚ±ûbŠ¡^SÛŠýöbø³óW/±þ™æXK�Œ0©w½°WZAínçÂ…ªeáýV>\¾ÚêÚMÀðî©á‡†;‡ ¹˜Bî® W›ŽÃë—Ò ôŸ•fÖf¥¤O’ 8Ëm�æM�•½ÀŒS^0Ãbv155~¨ç2ö·µKRút`7ºyK×ubÍT$®J]eÿ'Iõð›ógo^ž~ý óAú 4=U•ê¿É{ö½¥öéŒtË!¡µáÄ_ ª÷Ôÿ&�¯wð¿ê÷¨ViŸ*,o U¸ÿæÉÕÅÁŽ@u½÷s?+Æ=¯%bÏ3B¬n ÷«óð»ö«xPàå{êä‰JÓõæp¿†·I¢0Å>2ÛWç;Á| ’f$ólàxó‚šµ’ñ¼õŽ,òâ`œ™Ÿ‡t§ ïÉäÞ�’ç¡à ³ÜS\™d›»�]ò; ê¡L©r§Câ²Óg~jÑ.d­a§Cb8Üv;ÍÜ3fÊ�jÂLw:¨±SîtP¯ùG]¦®q—^[Ïm÷š뜢Õa½¦(õ [28„KßÅ’¹£4‰!Øô‰¨ê€@{»ä;h~õë2KůRŠo€uOø(qÏszr1ùîNlVp¹ðD ªK3IºnéÝWùü UÚ5–fI¢ì³TÚÛ‘�{•ñêk|´ÍæíJuq+ŒpÚTß8Ÿ—•¶) ÖTÒ×T¦ç°ÔŠ$\Í1ú¢8„Y;�8ÑMô¨¡‰ÐJL`¶É�å$»€g²Ê.ʵÐÐ2„˜lÖb&^²$ïuÚl³ºýÊU#;ðÖjLCÞ‹¢ª æ@ëwÇJL&úºòIÆÇ/ºUÄðs¥�k™ Öñ,EÈýY@ÇÔñ7Ò˜GHÍÃâªJÁ‰ä-�ÖÂɾA•¨Y5ü³ža/{oPk?rÑö+ë’=ÅYÌ> 8†�ÊÅ ½9,°Eí&)Û•=½à5¹½˜ö£B¡aeþ¼¢€|< aI[‘`%Jê4š)qV‹§¤÷{Á«4üâ嫯ŸuÄ›ÆÃT|ñögŒ: üÄõFs"ȸ�OÅe`ëáJë4ãsÉvîç�!+ÍU‚¦Æ�Ħ5¢ k—7Ä+Y]Õ ¾\�gÒE0Êd[ö?�ýÇý#Jr&ïW2Üֽ߾“ñrÆéO¸„q¶ž±õ! ùg›3IÈ|Š´¹±içfVëqÙ«8£1—ÛH ¢sÜ Ä0K}|ÐXÛ<‘Ï+¶\º ‡ �ŒETÒ¬¤¼KOHß £EI/ óï�eíy†d„ª \ –:ïAsIÐxÒ�g4ì�U‘)XzÆ®ÚyÿZ”“ç#àg‰ Ÿ 'A\šJ™× ˜K$÷ìKèŒÿŒl]X…»²òǪ$úa€ âªùlàLŸ„qnÇÏ+UÁMöDµÅ{¬�pÃÏâÍKáòwÇâäÞ[ÂãH ´°tH ¡… ñoa= “¬Øí÷_¬l Ýshùò^O�/SÝò^¯1b+ÓQÑ{XßÄȯÞ"9gnÅ�ߢÆÕJ¼ÿ—JNƽ°] –�ÍŠºÛP|¹o#Ämzr±,´mrÝFÒÊV€æ´šAvm›«åjX9ú?¤š)\sS$ıÊCÅT�å9L&òyZº8aÊíÑÀ °Û4~ƒßú\žáñ°Æt”�ªCæŽ.%õ¤™»ä£ºØB×ì&†gZ!NšfpUÁm4¿wÏ×Îyne¾ ˆ‘Äò»pª‹ pWÊ]ö3ù!<7?ÈÍæ¿G–TÆkW–Ýk¥Ð�UEÂ)t®÷â+~k!�§Þ y½ì~ ÿù"ä?ŸÅµ[1Ü_$øÍAÁwRxÞc´½\DÛ…íKy6Û¹®ïòõßãÕ½•�¸§�ÛÜøÑŠM­œ¨=ŸÄ£j’»¯MÙЛ·ÓïQþÿÚvÞóÛÐÖí|£3“¶J2*È“°{XÒžã³¼ûïâw÷»ß­< ‰±žŠäÇ�³– •kЫD ½mƒw¹˜7K“¨²òZ2ü–òíâR°è°fë�a§‹+ÛÖe,jE—ÞßUì›3¿nE��gÞ ÖË}û�íæ’\¼³¾Î0í6sµ!²Y’]庪ÉìVð~ t¯ÑÖ²Eží&öjøìK¦mŸ²EïÝ+Ï$Õ]ÀA—‚nå`~Çßn$°ù=¶ÌµÜ“ìªOÑ`#‰µdÙÅ{L“Ç«Ö`*»•½ø¯ãÁʽ0EÔdå{¼��V-ÄY{ÿ7äãUë ¯fsWÞãÅ|rãb0•÷G°�OW-ľ÷«ølÕ*Tj3!ðfy�WñdÕ*êÁÄRÞÛ"4¿™ÅTÀ(ÑÜ“=+kcÑ7 b4q2+SÙüX´FãÇÎbù¯/¿.ô0.ÝÛ”K’rÍ\[¾Ü-=sA”‘£ƒZçXDŽÜ{b©üVC=B�¨¡HêäÇÚE˜,+ƒºØ£‡l]ÂÀIr´JÕ>.èEaK&Уì%™Ñ„؉ …Gê…ŒYì5ÓñzLRH£Y»—Cp‰Ú2 ±³ÕÄ\憊¥F¹6Pçæïûª¶•u"kí�Ð:ÄÍIöñ¹æðNóïþÐonòÜ1[μ&JÑ)O(ÝTïÜZ«Úf^_©ZÔ] ZY�ÂPttÃgFBJ´j Ý›�sjVÐuù|rÜŸã×áKûõ}œú矼º~Þ"�‘KˆA^J�â3Î;¢Ï&|uy¤´‰£¯ĺ8¤—;ÙÈl7Æ/É]÷æá"¬çÞn¶Ûqô‘l°»�›uDw±“mŠ¡¶jsÁQ�°ít'vîžWˆ£#òà¨åýK‹MN,A.�ýp©5"òäf"_Gj!HÛî)—®¼r[õ9Œƒ÷«ÏMª*ÿ¼ßÇòs½¬÷÷N°"U” _‹GΤWPr6eq³Å|ñ‘Æ�B „öÚ$Ž%‰Bîc„Þ|ª¥†u´ñLfÞSþõ?nxß~¬7³u {üO—õç=~ƒž-äm×ÐþãÃ?Ù³“*oœ.Ö+ ͇îឃ›±ßëõM6�Týó7ù¨wDÌaÊeþQ÷R'áO>8úìÓ‡+':Ú«!R&Æ ¯ejñÅ,FìòÑ)˜©àÛeRM "t�ï­^t¡†Å|hÀÂ�¨èãþ#Æÿ�jã<ÞCðºO¥{Ï·Æ Õ Ÿ['^Ô­©öú‰q"×WõWá-=nT×buƘM˜‡WŸ±:µ7€ëA \@7%°,Á†·±-pœaóY}]Éë÷´6\µÃ5Ö7Àó•äLÚÀ¡k Þ?–*áCaɳ°DXQqdž�÷Ž÷ Õ©yâ^cHŸ7 ç‡'„}ËyÄÜ-y Ü'?}bÜ�ðøðø“UðOëSÌûź²'sq„p$Mª—Žå–Às¯®®ze>‰ÓkŒJî{N_ÐAÿiu‹:«rx�O´|øˆ g�Esd«¸'ÿp$Æý $$�—D‚¯ ]¶xœí}Ën$Ù•Ø>¾"ÌÆhHw>HV¿ÔUEƒÅªê®QwU©XÝ­ÑÀ#Ü̸™bdD("’d CZ `v†óð0àµ= k /hï¼ð|ƒûK|^÷‘‘I惬jÛ‚¤JfFÜ{î¹çž{ÞçÑ?{úêì퟿~Nªir�ðß0QéøñžN»ßœï…‘ªTw˜¥•N«_YV=Þëõú{'A>šháø8Õ• ‡U”ž˜U£îg{aßÿ1USýxï2ÖWyVT{¡Œùxï*ŽªÉãH_ÆCÝ¥?:aœÆU¬’n9T‰~|Ô;ÄÁ¶‡@XÍkÏ®ó$+txžk�³t8ùÓ^¬t1RCÝ K]–q–†•”¡J£0W©.;! 9œ%ªÂß&qYeżºœ%U8ÊŠ©ªð¡lš'ú:LgÓ�.à‹ =dªˆÂràg�©ò\«B¥C óUUœŽËÞž¬5Òå°ˆsœˆÀH­â*Ñ'ß”º_`õù[~"‰Ó (y¼WVóD—­_Õ<‡1+}]õ‡e¹N =¢=ýUYÁb†ý|>žfÊüü/.ŽzôѧÞvn8îofª¸�A‡ƒãÏ>y0j4N#} ãáJï½à¿ìhc�Ò=$Õ¶×S€À¾}.{÷gç¯^†çÉž*3–lë¯~]Âÿ•ôÓÒ1óB_Ú1åݧz§: ¿UE¬ ÒÃs Ü#ÞÐo€ò,Tt‰[-�ÀG¤]ê"Nyóõéà=dÑœÎa…„ÃD•%¬_]Tò?Ý*Ë÷x6z°�™«(äã²÷ñáŸÈðµò鯕ž†æC÷pO‚ÿX啼®ï…G½£0ʆ3$%:#�úê$üÉGŸ}úpåDGÞDn2oϙ濘őÆ1½§ymý*²gV�ÓÇ{E<žnW.v‚a1°´í¥ÿûôá¿®†C Ià�÷^ï� ÉÅÙ¬¬/ñ¯Â[@}ÜõRjoY@Û¡Yè˽e ˆeÓn ³d6ý64?„ÌCé"÷MTä’ÄÌEËaŒ|¯÷ƾ#…³WOOßžv ÷ž,b]t‚1pÔ¾AüÂ-3]•6¬œ ÌßÓ ’^I@„©ÓÌFT�zi'¼TÉ þÁqf©9_„ãai_Y~ÛÕ˜ PÃÞÉÓ �—0“G}ê„æØjÔóÙ j˜yXÆG3UE!ìñMì´µ–ˆÃEã7¼Ö×H¹k^íßär³ÓrÖzõ)pFy9–ÛƒÅ:¡˜W#&ˆ«IœYÁY˜ÑQÉHŸÜ ôg(Ýù§Á0ÕHisœ�;qY"Kô¡ÐÕ¬HÍQä3ß ÞÒ=�òÚ `fGÙyLï=›%º`ÊcY9O…âB¹müÓïvMmº>à œÁ¼Z"¿$™XÉÔV{lr‹KóƒáH¯À-@Picp$°{ ®¦Ã~`k,¥õþ×…WöNHð�D«½tpÉ:�ý…§éÜ z"GØ=r<ß2zŸ†�>ñT�Fð3ܰ�FQj)‘�—1 ]$Î$º¢²à@"‡Ðl £[En‡5ÏM „rÞBt�»Ý&{ÙÐüqgŸ;Õí,\˜ _æ|47¹ƒß–,œ�ð'UD$Öµ÷œ¶ÓêÉ·ÞxO³¶� 'Ç ¸ÔÉ|cR'{È d nz#q)Ä¿!fdˆ¹-f ¦£úà©Ï ™Þ·äG�7Í¿lð$áú||øÒ­Xl@ó Ýp›çh/驾œ• ´‘È6Ø›'p¤žãÓä@ƒ¸’»‡ôØ�ãqÊêàT]èð*+.XÓ¹}Ãí:7vp�)Ê%ßNÐáÑ€�|ò‘Hèe' Ù£Ðx¢QîA…‚¦t g €¦•ÜyÌ‚ðga?U6'"ö86c€‡4¿ ¿r·ÀRÔ¬Êä2²ì"ƒé,»e‚X0œN`t'OâQ…’ú%^Š|–À­•(”ö h²|G76i½.®Ìž h0ÉÄð¯y“Ö‘°È’İ;~õj¢AºBÅU%¥b§\Ad@`}uÏI­?£/š$�¥]˜•Qp­²@È&ö§ùŒÜ!¢6xäÈè|:È@ÿ%B0ä;Å ÉÑB@è*ò�>J؈»€UXÖ\”©¼�¸5’h† Þ½�Р¢_Äù·ލ�u� eÁ P×Ô †ó:'•:›Å(2à_¼p€4©p¤JÞÝÑ,Iº#­@Ê!rÉNϦB"ŒõY3n1¨,°Y…F4é4Ò‘•ÇO­ÕAäy$þ›”ñð‡ßýÇÐlëåÿçF\<ëÈò“­øÖ8ÓÃÛÚTVE–ŽO€�*ØVø™ÿ>@P<þ³åÜçV/2Ë]|f. }Pð@ÁZÆ�ÂqF'¥×ëÝå$OÙþÖÜp1myÊàQct4‰Š¼§#Ÿ„údâÈOždp×xJ23‹RŒ%[ª¦IS{‰½-Åï'Ùd¶j2eûòVseã£Ã%Ó +ÝG-¿{txàæí…oID4·‘Ø^¶\õþ®õ#Z\cÔN]Ž Ï²|Î÷½·�|!ˆ-3¨](!–¬£¢“,³©ZIƒwvÅó%D¸PÉuÔ;ꄃ%ÔC÷V+þá÷ÿøÃþvùÀ¬Z�vÐ<Á �Õ(¸ñº‹¿È ™g³R­dxœí]]“›8}÷¯Ð’Ì<5`;™™Lb³µ•ɦ25›™ªN¶¶¶ºdF " ·{wö¿ï•7v'Ó¶C?´1HWGWç~H<ûË/¿¿|÷Ï?^¡@F¡3ÍÔ' 1[Î ÂÌ÷×ò°Ä¦3I˜¼áq,ç†eÙ†3Bhì©8ŒˆÄÈ 0J¤Ò7ŸÈ._d8"scEÉmsi \æÜ¸¥ž æYQ—˜úË¢ŒJŠCS¸8$ó‰5V—£!åX‹jï™G¸�˜yH]'„x/yÊÜ "�úõú÷·H¸‰0òcŽ@˜›†Xªk2æwWh…9Å‹�ˆ+” ‘"T øî¦P&B)€H5Íq™&È#¾F¥,#ï™G„Ëi¢Nj¸™ %•!q®Ë€®5 ™�]ÊŠ…”}Dœ„sCÈ;À*’w –d-mWœøzoˆ¤®�Ü-#P†°àò_Wó±¿ þÓŸJ#ØRî§ó�¹ÐÅx1}öã¿J(…1Xƒ<Õ“¹ñ&û¶‘¶$L°;«ª3@°©ý´BÊ*$IuáæƒˆÙM6–µòNVyïÕ`¾²p»¤F‹µBÊŠÚtås�e#<³µ-ͱw§MK**!7ÄB@ÿðj�9Ê>L'FÖš.È󖥇2 0~—€Ó¸$Ĥ’D¨80ÇF^þ6s»Y¿œ²9L¬ òb7UTÑäŸÙØAß?š<ûéEcC“RC÷�•ÆÔÑJ~�R�(™¥ÒYßlém ÁC8¤K678] ÛÆNÃHdXŠƒ,•ƒY.PM‚r ìº`•ÉÝÜøÃpuhœŠínü‰¾Ù´Y g+~Nû�o GÙK €O*c„k¾®4¤ÿž—B™�—K8oÙ×Ój\Ûn£ÏkÂÇaœ’ºÞŽ–²…kTúØ�xq ¬޳]à ó¹§jÅÅ[Ž“„p£lårÊIˆÇª¦l«`æÉ4M=pDYÐ0‹ÌŒEPcLªÃ œÍ§*ú<Â<çY¼øÍ°@ e ¯24Ž a —›¥þ®Ã䕎“Ë0^@ uÚ¼�•£"|‚³%ÂB×[ð(sÃÔ#œ “Ô§ ZÄrâQ@¦cñ¨ÜQ3*Ž]Š%Qé@”uN%nÊ9ªL )ˆ°´fvºÛÒý½º§ÎFÃSø¾åà͵©C¥¡�’æTõÑpfRåäKþ}2_×\Õ”Ô.q&g*‡©i€X,9fŠÔ”ƒÓàËœ™H0sfvö¡þ%!ý7??Úºpk8Ê>¯¡ho<ÎUR#òyÕy%±ê¼˜‚À@ÊD<·í½­˜/m�c_ÚÓñtlN¦vs«Wm:B½î;!¹\M.݉ ¶° ZM¬¼‹ª»]vGûÄî:T¶’Ü>;E YTw`3GÖ%>N>¥üa'¡ü¿ê1T£ÐýÚck kZÏûvEkz4 iDÛŒhƒÈ<œu+t »»‰©ÝŠÕ¡¹[‘YˆßýB#ƒæþÝÆ.±çé‡ðr,Ië5ÿU6úÑ5úA:t"I·›vO!{ˆ03µ&}ryCcWÊk<�u¨”Å#�âBZ)÷m0°ZûßW›t§™ÑéqåèéYÿ¬)&OŸM–z$Ìž  /Òt›T É)[vÍ�ˆ²ß[Ê  5œIãܘ”�ç(«¥Ãå½±t8Ì4J£Îy|®èx­:],%åù6‡Ä!Ò;/N«./ÐE3�R¦™E<«G§µg:pžtÆœãv3œˆj‘¶Ÿ¶9-áÄïNS�ìÇñ…�Óà�ô®‘}õüë�³{g›k¿ ÖD8yÆî]Èûm0Víˆ'ÏÚÆu²�±ßcß³û Ïɲug vàë©óõ˜ =°´¾N ^×µ2‡]8¯š\†uµÞ1mÄØë®iÝ¿uÒvI§A(•I÷Byý:w{¡®\w/”x-CaÓN_#ŸNq·¯pÏ;~�XL s§ëZæW{2‡ZÛ´ùÕÚlpz}jó8ó†O)f’Ê}«‰ÇÐkƒß?½’S}gêKu�ûz_4:†‚K1ðrÜÀÎX�êLøªó�™ëžÔçìõôâP»Ylûzmjµ²‘zwSçòŽ<ú=�û¥ÏBÖ÷o6 u“#Ìípë;]šî6]c¾Ì¼aº/ªžÎ,´ÁÎ7Âä·NËw5Úš~8­}/›Ö’¾ {omÉgiͧfÑ�xšˆq$½O69i(£Œ|éd³�°ûgH�=ì/ïëÙ�:SÚÃÑõ›Î&Lȩ̂GÚÿ´îlì©ýŒï°º]Ï3XÑ«ÏöÏ7:èÖúfWÉ:ºéúàÜ)ök­è°Ô‰Gì‡ò±þÍ¢a¾:˜EE,<ÚS'�¢Äë>Ÿ�93=fÌ|@f–VÎfÌ윙ÍõÚÔjeõü¯›‚Ùz²„KßLa²ýZd­Ð„»GÝ¡¶(ªŸÒE±†¸8ÄÅÌØ¼Óù2óáî6ÖÒCÿ–à݇†‡¼÷òÞ–¯ëk”ùiïÝÉC†zBjoïãz°¸ÕcPâþCjóâž=ðÄ&«ÆR?ºÀ;ãÔæ©çWU¯¸r¬o5ÇÂ|y„»¿KOu™[5à!s;i/~ÀM u¾ê;Oé6¾áaü.µ9<Œ?LÜNU›qâÆ^¯Ïi qª³8uœE™Œg¯ôû÷1ëí%ˆ�Ï€ÇîÛ4Z|ÁÎí)ùþ÷*Ÿ%•/dêÐ\¯M­V¶²'mV-ÏiÕò/¤{L£¦Áaqñˆî±ÞZ./¢=ÜÍaµ�Õ ÊlÁÌ~Y?­äá\S€Ý÷�IÀ9$Ãíaß|0l2vº†ÛÃŽ£×a¬ÓluØëP›ÃØùe«»®lÈVÏ![]áð’2KÉÓKN,K£5øÅã íìÕT§£Íã½ õh†;lIÊä´¿U¢�Ê_ƒz¦À ÃQ_[†§g�ÝëÔ�y„úÃ:õÙÓέ<ÃäéL&OiË_ü¦O3}J‡øøp®±¾ÎWÕØº`'œ83Û£+õ%ÿ�œ’\ý[ÄÞ�úTïÙ€OAôÓ Jbv„¨ƒKà'œ ¦Î[u<³áh4KÃ�¢i”„D ©3Kœ™º;«¸èÅn*i(PH%á8D �c&B,¡Ê6vg 7 .:m+YÚÜ)� úõú÷·èZDǾD© ZÜé«‚¡ÐGDbKl�®B¼—p :ëFqÔkVZY eB&·¥¶,³{Þ�Z„jÔÕ�jµdŠvÞ˜¹šX¹Ò”�ª ¼É%©MÎT(@Í,ô*Jä�>sÒA-!ýðLÆè $ê)¶aŒ€º¥ñé¸ç!�¨¬ï·‹C7 õ/w¡üW¤‘®²K ý é8�bÿ0zŒwÐD £”éfAÃ9ŒŽõ�K­Ö„À+h¸¤ a¡wJ;q”`tAIèå|i‚ðQÊ‘5ˆ… ³åY +Ò*$k¬<äa¤Y'|×¾³á#kGµ|uX \ì�d”·�½Œ»W3ï°¦\¹®éÌæGä@ñúŧs x¯”Ønÿ@Õùù›>“z°¦ÔÚ…¨blA73Œ�´*�ñ‘G|ÊhNÞ_î¿ ŸÇZ†ñJ ‰¹L]•jh/§E{ˆ²Ãì;kj7eBì•GÔNCõÿ>õ¸?�PéoéKÑ„ÀÊ�"·)g•¥Û_öÔßÎt:´IIñj�9Ê>ÌE,eY ]–çµ¥‡n©'ƒ¹ñÃø;cÓ(.É1Õƒ ¨80ÇÆ=î€nX–­9Ϥ°…†SÙk‚Ô0Dp]ÈÌÆúþÑäÙO/š[ŠÌ£Ì#ë¼™÷Š ¯SÈ”ÌRé\3�2Ž6Ý„¸dsƒÓe �æNsfXŠƒ, ”�]’¡)o’¹¡ñ½)Šm•p€n+§bùŸè ÀL+À€ŠÈ�ÊEnò¼¤Ô;U²œHmãbàºZ`zR� x!\³p1¥�«@U¼ÒÔŶ!•œÔWãzZ�kIöàyM˜öptÅ-(£Òdžuz²RÐ�oHLtãP¹—¹15 VºD±ÄØY¶}?ŽU Äc/·7Êü8¯õãÏ/ÐË8¹ÓG�Âÿx¥3�²5þBV$T³waåm½ä«Ô%*]fJ*áÛÛ[K$ek¬XçÂÊ¾Õ mÈ?[klm»¢{=äGºûÅ„-SŽžÃ�ÛTàü+3$‚!0%Ÿn¡vx-—ÿ@Kå0 ' ¥È8il+%,å¦óÿþÇÿ®=¿¯¶»ù›œµ\àÐS¥¯p´Ðð‡è¤¤Ub¥n+ksΞöÎ�c0xœå6»Dg<€igpˆ»¼>¹0ýO´²Nc5qH¾0ø <ºàžYüÄá ȶ>'»® L ½‚eh,Èœáû|àÂ3 ´^ŠŒ]0©€˜?˜9xqÂÝ[‹ ½,Ú¬!x?‡rÃQ²1–Ah.ZZ¡à½v–cmg�f¥x/7;¡àµÀ2Ñšï 'µÿÞfçt´8'b;�"rR/‰j±˜ðè˜Î(×éõöŽö6;ÕWß¼Ù\78ÍWßôö¾·éy^¿üí[1Q€cÿàúåßov¶¼ f_Ä—ôäç§›̓å.R¨"j³(ù~±V!ŽKýê(½»ÂQüþòGÐ-_�cë]¯ÍZ­N÷;à:à»ç~uz‰‹.ð J¢Ç¸ÿšBÉQÀýì.ŠCÄ¿¢XÛG¾.Bcð$båþ”¢»ÜÇT¤]u��±´¡d‚£©xC7o8·íÓaÓTÔã.…¾(JI¡^ šÏGß’¾ùn4âvKv ÖÙÁ ¼?å°F�*GFð��\ß½šm«©Ñœnãj‰Ná@„ÊaŸ�Á$¯r‚Á.”¾0À«rÇ´BžOÁô÷!9}"¹ põßq€wv:íc™LOšÈ?ð‡S¡*Úÿ‹CÖvÚúòš iŠ&Ð5 `ÛÀ«—î ÃÖ#ÜÓ"ÄÆ¶#»x+7ÕǯóŒ: uð¤�[@z•¨w�v^’P|·Óγo¹›{•ö÷¸™ƒOÇÄ}½)©h™ÙA|2Ô¶` [_¿ü¯» ¹´!6qgfÏ w€_Jª-^-úçÉ¡Yæ‚ÆõÄ–p@à I¡(�Öšó>¹ Ñ {>D½1ˆqÎÁ¼ ›$’jƒQؽpàæš€g}¹LÚJóªI AM=¹fß/`Z1¥¹`êJ*käú»õÕ¯6cÞNí|£ô1 ¤)Ñ”Ìâ°¨9ü xQøµžGÙQ?¹È�ž©<,z-…¿¬»9åro<_öÆMG¯êªÓ~õ÷öµM²À/úOì�PfüO‘Ag'`;œÏ¨Ý3µ-¯sÕ(Õ-ídàΛÚÐ)ò¸P“†`äÀІ ��û¶¸3rX?[Ò8íî÷ïµïw:yÉî/Ùwsiß Ud,Œ^ÙÇ´.̯ÁÈûg&|ï0%бÝ#¢wi� 7—p›÷fö>ê6}> ÑÈ›í'пz/wûMê@ß•\êÜ�§ð»Éø·¾ó ™ç ê(lbw[øv³ÓÞ6ôË’·õnP�Šù—äÆöEàÙÕ«Ým@ ¶]n)ÒñA=Æ�éa"²‘ÊM°6[„!å�£MSCã6u@‘Ïxn©azô)8tœÅÕfW•í~Åö¼ýÑ‚A�ìBN¡Ù®åŒ„¨ä@Ñ.X‘j׫í°j$}²IÄzÕâ(ììuº›E‘W5ŠNW H‹¡E’YÅê “4!&±™&‹fè&~L‚X5®*uŽÚÿ.ß]Y¤æw>Ò8M©·,^­’Å�&q•¶vU©üuÊPÁÔ>J¥{E€,&Í ìnö²k¶a¹ÈÙ•Ç]¯Ïù°ja¸:}üðô£Ç�Ï– ±‰FþD»ý`Ì�1RŠ�òèd±Ur0<Å•Í.ø Áçš¶›z×/e¶U/ 6Vž&&½›ÎtŸÌŽÓî:´#\ïc8Ì$ Ôrï :tÜUoï;ó÷oìø~ª�Ö´ßþÜ”5¸P’ Ñôn0¸Œºœ¯qR:”c3™Ù›d :NË>l™e<%Ê�î€=•€Ÿ³Ú÷ ^>d:ÿšÝTh Ç­í|ÛE¥\n°Ðnü\-ÜÐã†àÒZ¸ñsµpC�Åp£ö+ ú8u¾?W :ôXú;¦·šhÑ“iýdké:¿ÛÛë,yi{… k_õÚ½* £;Ã!,çVj®zÔu:õ3�+&î À�Öo´hóB.ƒë—¿Æµ+;A†¾3•›ªòuòkâ„Ú¤‹à¼´S¦ÎßÉT8ì!ž[3µŠ_SËc¥2LxܾŽåbüì|]À�*‹ MÕ*Õ·ÃN3§GijZ¾©’ ¨° ÕlD…ò(£ ËIdªN¹ ócJÐE\XÍ}Rò^©F*Eд‡c-]€ÇÀQÂÓ é)@ÆaÍ)þ$Põæé‚ Õ*ßR8Ù.™¡˜?—¿5ý0(ÛëâÑð­ixß.Ÿ¿pÐ0&¨àô:ƒÔ.B(�N­,yý”�¨ÜØjécœà9óâÔ5Ë8Lï$dWu®+OÊ9ÄœÙñ?EdUMdÀ¶–ž[šX‘Öem²+žE�†2bÎkŠIªæÀ4˹Žw£�AêêüÑ“'˜ÎŒF…LQ9 ¾—AeÊÐ+èýì#_퀌¢©VˆÓô�„0ÇŒ“úâ§J9VÌZÐX=8E�§X¦5uaì°�æ•o´øÚÃyà‰ 1ƒ�ŽœN£ÐK` BFçŸõC7‚å3fß–Ö(¼°WPpÂMâP—!Íøó�ˆçK„ ¸z”weDÄʦÔYÀj‰ ÞÔ^MŸûá%;hÓ¦úÅ¡”Æw${¦,èýö\ð¨Èc†Á;¶ÔW[•K–ôGËÞ¸ß^±vïôŽzí£!·Ó\@ ¢)G²™ç s�[ s@5ábíÚ¢š;¤ m°"(@Žß1’@¹©XE Ãö«oÚíï• b3ŽÄ( ðœ7&Ei?Ðf“(Ü£Q�t1Â2“ËR+¥A¡ÜšŠ�g@Ò/rш’þö ØÚyÊq]wÛÐ5à0ß5Z�ò(i;û;Ïâ$*èV>¦KiÖÌØŒø¬É®Ž|�ü°oë#õktZGÖRÃerã—®öª,a¥Ô…AÕPŽ”˃YÚ�ˆøÅ"¨å¸º ý$µ€Ïœí5‡tJiZ:Hµ4P ò 3½!TR�uw¬Ö¶¢D$–ÛN¹že„\£ÊÜØÅJpYiØÅ çÆñTþ» ±¨ÈD�¬„õé>Á­+è=¶uYÒ+Ú”;@ë¼5Ãö0м›3*ÏA‘Yºš ã\2¬K2÷÷Tg6ÏÑCD”>xD'ç‹"Aj5– wI§–»Q$² r*³UÂ`á¤×M×ÿþ/ÙéŸÓ_Co‰âº¦�ççÓÔ¾šaœ9à#ðp"¸¥¥’ši¹Mn¬ˆ^aH2IÛcŠÕétZÇyE–1è"�¦> ŠÍXÝO~‘ݹ/›¡‡N Ï81œr0pˆWGã1½¾Ð䌠ÿ” ?5§=W½�Â{ª!:0øŸºç%'ž@D@½òkó»!�ü¶wžõ ÇP˜,$pùÑ_}³PDZâé9íÎ>þÛì(„Äýç†x¬Ž÷Š‚H¸¬Œ'÷ž)5ýÅ.2«dLçÞá-ñæ½{Ý|ÍÄ ¡³¸>ýmèËÞÞfѸ@ÿîm�½=°9wÇ•0ü.+ãÆÞjʉ6¬)ßfdVÊ“›ö…ö»ôoóˆ¼Cû�e³79ÁN×É¥—nhí™ßGªäÆåm·.‡ªRA�¿OªzdÞÛ¿Ædöîœ17¬.�· /í\î˜7_ãÖV†Ð½ÞaqñöêúZ/½eâBæÂPûsU¦- è*L}½Ô·`¿KE[)nG‰d•'`Tžs±Ý¨…êÅJö„”/Z5à*�íÕag‰ïÓâ•Àœä¯q(¿h#ÍEi.T2^çº8ÿð]ÇË}&7»è¹~ùw›â¨�Ê׸e›s´pOQµ“#szK8¼ÛðÚ†gøv#²:~Üì:§ÛÞkß{{GwÅx¶é€ÐÛŽÌ ó£MNo¯×mß"a"dkîrÅøl¼Ñ)¾ýȬ’-7«-÷ö»·$áêÊÄ»eÌ£MÇ…�÷n�7� UËšv-�÷oÇ)2³¹cî<ÚxdH¡ôÞá-¢t­ØÐS[~œ®;¶g¯Òg')öB„$Ö�L§ŸŸÍS Òt¬„s“ Ïl¬_Àý!» £R¸¡S6 çY—mÕ÷SªûIºxÉ }=nÁ—š.Oú5€J/à-U�dzÝ�™{Œ—×ÄTm‹•T:œ>_αè¦Ê@öE .tŒ¾@'A‡ÿV†“^)®Ä;««¹0YwRx° \vq\ö6¥5®E¢²1¿¢ƒ:/°j‚.J‚9Lm6‘>n D ¼ð’b~J@Qô‚Q-‘X‚•E@¢(«¼¼O÷ráF…˜ 6+n×Û[þhÅůÝ�üí¤˜*Z2¹Ø©Âní”ËA$¨j¶dûû#7*×F|Ѱ·QQ]g¡l®q÷÷¿ÊßS³e–£ÄÏÔZ&rÏkO!;ÐOÙ„ã‡J=ÐÍZís£§šXFÇÞ[§’kñ ~ÀSÊR”DxN�© 4—ãПk®Ôe²V�¾cZK)4@‡QH•�ê¨1¶Ø–ª {óišh„·5õÎkjËz4��šS{¨¶®ŸØªÈfŸÚÇÖÚRyÔ\( 0“ùÕˆŒê•sgÚ»û; <^ŽÞ§aêÇÛ:)üŠC÷xpYúûtwŽºN—Dˆîؾç3= ï'RWÀ ô�·XU@ÕÓ5Ž»j <0¨Áƪ›¹¢.+9½…[¬·5q�Œ[amîYW£0ì¤o¦1Úù0z9*`ÙÝNw=X: ê«<0Íu�9<¬–�µS=^ZÝýõ`Ù[È”- Ì.HmJfoÍ�sP-0ymUœÛréÜå0=_þ¨Ÿ·I›‚a§ø~²Mñê·K)ðŽÈãL¡ÏB¤Zðè0ùµXÚ°|¥ ÷y.â÷a9�°„ÛL…ˆç¹ÞªrZ-U9 Vï3véÎTÍ)LØU׎H§†% Ä( ©°)ØZµ¤NÝf\›º‘î ë‹›Ò�¦ «Ã> ãqÍÄ=Sõ JÍkø<غ*¨TS²×ë_üß…nk¸!–v¤„‡üKŸœº!Më9_`Ð9Лhs2ª+‚k©"¯TÝébCa\3>9‰(� à„Aþ)Uo0áp‡Q¡Ì𩔣knÒH5t]�ÚÙüÆbE?ðt±FVà bêú5UãŠEa`ÒUĦ$²ºÍ¸ËAß�ö¡îOWÝÓ{5ÚVÔ7ÜTʧeÅ4/V·î¡>Ñr��ÃòlZÄüFš4JÍÈÛªP›ÊÇö†îÞ«ß^ÿ⛵¼„Þójý¹îÎN§½$�v· )©V:ÙðÕ?®‹› A4åóîÖTl?€O¯~‹Ÿ61ïçÝç½µ¦Ý}~¸Þ{Ei;¥ç±Õìl?ßê´ºÅ×0¾(±�:m‹ÙjEè°™ï±ì²jg§jwvò@jmv !½Ý«J'Ó¬¶»Ÿ_-âåÍýüÏéÞ”©ŸÈ.•ª\_Ä—Bröô“Ϫ÷ýó¿Æ—.·†Ç` ó�ëÛò4ŠkïWe|¾¿–bjV,hþõäz€ qæ/¿=Á‚?yãuúÍäÍø›&Z_(]§TG_m™�`Ug·a2²–ÚÇ»J³ Ûè^ÌŸ¬·½×¹u«ÓÛ«â0oA,è÷¿z €ÈTòÜèò�ZoÁd¯ÿ×ïÖë©•à?V·Àš´UœrA˜Qow¡Û/&n0c°vOÌEÙS@]�›ûµI¦{u'™‹ ÒäåšH›2‡:¡Üj†‘J¸ ’ �Ä ¦/¤J­ar‡U¿t«¹çQÚ%´½Ä}|³–ÎŽÄW³ÁÎÍÆ�WxZ8M‰âÒ(¼PWS²T ·[i {צb·ËÝ!ùuou7êk–žæî'Uƒ<éÇzªp z#;T ÿúO±ªÐŽí¾Å&ö—Y©‰mVÊ¢ÿúOÿ±Úþþñ7ÕzO/ÿSÅýýçj½Ù—ÿ¥bøþªâþ*öfñgw¼™»LÃå­ðczÇ1©ßÏ»9ôÁ@Ý”›Y¢€'ÛR9.�Øâ±¨‹�‹�EœÓ£Ô�:“ýëÛžjýY9täk¿é«ç×NÏÏ_¯-ǾMÏÇÏÕ&çC�E©ùµJn—ã(zT9èÑmŸ*h÷;#n+nÌ^•. =1(íC¿í¶¿d¯íís¬?p'Óꤔcû‘Þ¬|øô´X{T&à MVðsµ‚=Þ… ¬M4äÕu9ô®Žç¬`ÑŸm˜=?ùᆹ3œké°j%Þ…Ž^Á]+ˆÕî·××éw³ÝL9[Õ8wùR¶esVše$às¼>^]Ç»tÏû‘º­7½ç�ܯª²Œ(€šº-ú#ºZ á‹Ù» J%йiR¡•–U™ð]@ñòä<Ñ�Ú›è×»páwOé*s‘ë\ưœŠ½&4¯1¥ÇU·RNBJ¾R" ñ&C§ýlòÅr)¶H(xöl" DU�“·¢æê¥Ô"PeÓïVC³"¾¸ ?¯+mu¶�ŸÞ`ÃeIî”YoÝY:ÑÝ©aýô’¡ý(¶v�¾Tk ±Ë"[¨ŠÍ„É)ˆ¡¾kKtéâ8Û¤+]œ+žwéÇšÅkPR}9àô¥Z`—…8@]Ò1°�jž"ðÄ`tYZu ¹ ©Šg¤Š�o b÷ ‡•‹ýœ\° wˈÛßÉuJ—ü’‰[_åή+¿õB—V£«&Jº–ùœÚ�#x³d§;y¸ç5n˜šò–ÆGÃŒ‡ù=ÐV§6I§ê?Ö– ƒ¡%‘«nkÎ2Ù„‰ä¾2=uX|SÕLÉ®_þ†ýPßߌŸŸ˜Þú»J•t1Áø.èöV6²1zXÓÓŒk0ðð.ðhÕµÃk£‰m:v%úbæTYù»\®ùßs”§Ê_s›Wòš÷åÎè|䂇ÿü»EŽÏVÑ(y3üò¡Wä„ÜúçßåOÂ�2¦V—ÚÉ${Rj×èBí$ð©x†t¬Oüš,uë6rú;f�ÉÖ™ < ùb)Ðûí%ÉÞÔWdGzÖ‚Ôn8^·Ý.¬i †ëY¡¥«ŸŒÂ`É_¬±¹~‘Ó§àXs,‡kÏ“ê+y¬sÊL‰)é€z¢#2îÑìð:=¥–'z)a•Í#7ÁfGËWrÅ«¸\�Ôrúá �ßõò‡h'î �7cYM\A9ìI€Êz‚�ßÖ¤ë_º3ƒ\i�µÔ¢×W´�x7Ò¼é™]w¥×\ ¬\úm]K6h²š‹J*sbE¦Ù[ó„gs¡®ì“x�€…¤£pŠ0•càWB¢à<5¡"¼i‰F�ÁÇœ@å쵡غ)õAŽdŒÅ,K~±œöôÚ�‰¿pBÖÕaÐòPe¡þªj¨¿*‚:⬟?n ÒE ¢z&ðÚjìX¶vþ/mT>‡QpgGYˆT«ôÙ/¯yß~Ì:�{ÑwÁ�¤?Í~Ç᤮ޠ¶‘~{îTìƒOauSý4§f>4Ûõ9ܖލ»¹!^=té8¢š2}$°ýÁû�Ã{®¨SÏ RF⣇¡úÓ'Âã”*1oª1ƒAO;Mª… ìHNÍêIGÜW°˜9X$”Èò¥ŒùTO;ÝDsî%»œc›Ìã`à &2 øÏØÀÒ-€%³P¢ªyŠ5ÐÁ·¶%»ì,S'›¶²€ü*^È^�À'ÚÆàˆ)B!Îø8O°Y$[Û{ ¸öŠáñ×Àó1èzT,àЋPj©?– Uô]³cd™.ÆU¨�ÚèA½[7\: b=×eZ ÁF@ °äå(ùà ýØÁýa1:�©D­n»{Р•LZ:OÁ&ù¸]'=Ö#]s<¡BÀK…¤qOåQ«uyyéÈéXWM�j'ŒF-”wü�û¾ƒg¦³ªiŽý‰¦o÷è³Ù“@œüê¨Þ  Íe�›Lñ8xœí}]�#Éqà;E.WZõYüêîééíiavzz=€<»PïJ'ŒwEV’Ì�b·²ª»)ÂȆ:ÜùlëÜúÃù€¼�,½þ ܳÿÂED~°ªXäL³ŠÝ³#°Û$++32¾322òø½ÓO}ö“O³q<ñOjµcüË|7=¨ó ùùy�ynì6aó þ2 ÃøAÝqZõ“cÇcîzø>Nxì²ÁØ�$‡IÐqÚØYù~$ «yíÜ�v>åÜ{%Á`ÌøÕ4âRŠ0`rÄîUƒɤÏ#„±Ãï æF"CGbÀÂ)�Ü8Œd:�L}~¥›KæKí~€W¡Õ%¼Ê.Ãè÷À5H|êÆuñuéÔõ$=.‘˜âC‚\a3±ÏOÎ ²ã–ú¦žø"xÁ"î?¨Ëx�9ų)ôó«¸5�²ÎÆ¿”8›Ak:MÒ�Çß¿xÐöùpï^Š~köûuâF/t§ýv¿{xÐu*�_A8“õ'ê›ímÄjà o½öíÏ%�š§|(@î�€Jnn°3 ,âQÑäs ‰…Øõ.Ü`À½¥7\ØÎD$cvó©í`ˆ?Á¤á§¥}¤g§¶ˆCEäãIÖq?ôf$h1΂ |WJ˜¯{Ñw�éO3§u55Œôȱǔ<Ô÷ÛßÕ àg7ÕISÄ|Â̇f»®Á? ¡–=¯“´”tœóÂA‚¬Cü{ÜrOØïwï}¸r Nj ù`)Ÿ Ùljð8ö™j­æÖŠ=+ s}1 Ô#1nWN(¡`1r°,!gºI¤»ƒhŽ|ö þiýG„‰ÌÎâgì ë–eÔ¨nÂüK ~Z?AyZâ^ÄÀArÐêáS$.B©nÅ”H·81=¬ƒÉ½b¸²j¥ž�yzÝ/'…®'õê%W-õÇ2+|ˆÌ$ |V ÐŽ{µ´òˆƒžF.ãQàúukâàûÐpÒ9ïG®'®šè3»ÐE”›‹Óÿ5áͺad7¶ósO4ß�¤F.0)€úS… æ‡†ÂffÓFg[Ä&"`¥0Üé:½v»€€>Ìð"È8©AÛmp�ªÐuĽ$ð\˜’kïõqv?ñ€¨P81Ò‘‘€}¼~ùkÐi–H{<×'JŠÊñõ~Pä>—É1,UƤѤ×Ê¡eq(ÒZ Å@BÕÄ5´´‚É«1qÓpyÓ2¿D½Cãa+áu`x=j#|‹}ldãܾeUÓg G' &/�B®çö�5ãYVÝ»$zr.cóÑ�‚\?£œ4:@Ù\ÐçÒ É¨öØé$¦UaÜÊÊCß/¹W84vg%õ†ÓoÇ2ŽÂ`t4T¨ÏÀî1µJ*•{µ´¹ž�].:àZ'ÂP°`mÀXBæ;è36E·GAO]ËÙ¤ú)ÄFzÝx¤&˜øV… ºçHL_œÀÄK±Û—9fÛÉ€ìí£²úäËÞÞþ—÷³cà|Ž[»™Àù”'Ûú|·Ýî¶Ë�ªGc‹Ïœå_ç£$Bå2Ó“%!ýN§Û˜C¤m”ëóúOÿÏ›! šá:ÝWÿs¡ÏÞZ‰O² ލ •g«RQQxœí\ëŽÛºþï§`•´hK²½9›MŽí"{KÓI�ÍAQi@K”ų²¤CÒÞ5Ò}�¾^Ÿ¤3$%Ë^¯½ñ2›À °Ö…~óqfHQCõÿpúæäý?ßž‘TM²a«ÕÇ_’Ñ|<ðXîÿrᑘ*êGE®X®>‰¢P/BoØ"¤Ÿ2ãN˜¢$J©� JLUây$lÞÌé„ ¼gWe!”G¬Ì�wÅc•b6ãóõI›ðœ+N3_F4cƒnÐAa÷—£!Y¬UµÁ¨b„æ1™ÑŒÇxrQ2Ÿˆi¥P0+Q)›0I¦’çc<1Èß/Þ¼&2‚cÚ&rZ"$Û:¢È˜llYÔMМ°k:)³JBÂ3xV«˜ÉHðRñ"×P }Š«Œ ß/¼Ð öCsÃÊx~IËžTsh7e ÈQóÄ*v­ÂHJ�¤‚%º?IE�Âr>ž 2€Û� :Ɉ%Ož6únG¹¿M©¸´BG�Qïèð Y'”ç1»y¨ÉÀ{eÎjic–ëÚåºê9 ¨k¿c ,�XC‚¨®…›•‚ÍjALJè‚&Ù•Hin}úUÂÓñ·ÊlVºÉ�éç~¨½©?*â¹v.EG`$QF¥=élD1?¾*JÏ´¦ Û²Š‰ñï§Îm¸LB|®Ø„T~dz…à_�Ðz†4z ›¾Ð º$.¢)š E+í‡tHþô¨{ôôç� u -ktÉðÉy9å1C™�ÒF·Pŵ;€e|œ<ÁÇ)p»Qiè ƒ¥:XÁ²¥[›E7XG³�"(qÉæï­7DÃâÅT.kõor ½5@o3é58îp º×Þýgdë‘ÉÈOÀNÐ06C;·¥ˆqøf‰a%aÆž¬ÇµFÖàyÉr&h¶Nƒ®WÞPKYÂÕjüÔF ¢:@/†cS æ³ |åF “]sóJвdÂkúC³ O�3oBy¾TÐDÉ Ó<†˜ƒCˆ�6î‡òý´»nh�«­~¹äü‹ñJ*lùbô+4 ÁUº:úŒw2h�Ñj(5Wa¨�2ÂA’,¥8´òœô£"fM&Ï$É ƒ±‹òB šË †ioØ—% ¨¶(xš7|ôîÝË—ÇÇýï û!Ê’¤ª‚Öû¦ ™, ¹(›Bk‚ý6å€^–Çì �× =8Ó¬UÕ33w0MÔƒ~XƒMö”÷†5Ï=8_ õþµ¯Oßjì�²"º]•0Ü7"}·QosU_ÅP»a5)„Í C§6…FוƒË@®a{XQ»D½7ül¯·–n\yCô‚›5Ðð½Ç–’[D>_w%®».{ 0Uª”ÏðaâA!Æa,h¢Â^§×ñ»½ps«í]á±{%$ú^¤}O+a`ËÐxñ¬XQY—Êè˜èN�fÑþçksÂì ñ)Kx§ù:8á¼bÃhÑêFD œrsCwŠ˜àì�cnà[QÀȤ8“Nð^FÞ0��Ì‚­‚º€PþÃíÖ£Ð�°%ÈmPl“ÐÛÎnóéd §2K˜%ä·šÇn23.w1è §9w,Q09ÍËŒŠ‰ž-:ZMµÝJŸ@UáØ˜fTpœ&¹•*©{°#]ŽE1Ík/½cÜ‚?îêJ·Ñxó|î�ftÛ@l€Áãã­¾òÃM+7ªòMf8�G=¢•€ˆ.<á‹1àξ|µ›8�6ÿx–ò�çîo1æÉÙ>cÁòïm-n§çfÉãwÑýo첇]й,3:'Í>y S•Þ>Tï�àa�`¹7 ûÓbÓµñ> ü °Ú`3&¤+•öpo °ÝA¢´�,Dzūñ›—0v5�;•7³YÁwL? Ç,‘¡^€\+vøܼ`³gp;ƒ›–§öümçoÓbÜž¿íüm^zÜ3¸�Á- ­{ ·S¸mYyÏáv·-¢ï9¼ÃÖW{·s¸õÉžÄí$Þ|´gñëY,ŸP1ÿÞÏþMä»`û#ÄÉ\Ù4¾bÆ„àñnkB·×ÙÁ’nï@$üû¾&ÝØÛûE¬†ÏS¥˜ph½ÿzô¡ã?£~òÂ?ÿøùðËãß…Ïý�][ÿâ¹^bÃlSbs]ÈÕÖÖXºê$Ñ0æ3<±?*êthøcòWmJ4Ô2¹±+Y²y¡˜´I²¯ñØæÈN³šŽÛg°HƇýrx¯|a³äUélÓ…q„(@H�‹©ÉÀùýr“ÿü—åvtŽp?-œ¨‚kOwV ‡ N –5ÙœŒ�˜¼Ÿ†Ÿ¿¬(òlîXM\"º³šó¡™�º]2LLÇÚD§E˶Mꆲ­Q¡Òû©þáã (L g0ÎUjÛ% ‹zmÜ1!‹Ùå*ÌpÇœüŒÛlÖ•6¥U³ƒ—ÆzëRC±`¤·õ´¢TÖ&ìšÐÛ]|s…ŒNE†bcÛZM9Õ»$0~!Δ­*wôº4. ZÝeXw>±J˜Ý~„[ ¨ ÈEŲ-›Š‹[­$€ÓªV±@ŠD_©�ª”*R\å’0¥-Y l §¹©!.�ê:ÕŸûð£÷0T„M‚Ö{v­ªÄ`{UÖÍÑTŒàW$ évžw�¾xv•r½)‚•hwËÈÿ÷Ÿÿ‚ Ob eY§+ò*1ZìÑqŽpÛhÄâv«™• |K0q�J´§ #áJ‚9’1tÜg8°Ö°›¤�®Ø#—õö‰€ü#e9AゾOTõÌQ.›ekí4SÛrO#½C²ÌŒ!`D €ÅÛÖ`‹©Ê0�»Ý‚8'uÔ£G*¬õÙÖ|ìèõ’Æh™´€‹ ^!¼Âj�¯Å«Íô›x¹ãžÃŒŽåÚ÷Ãm^:Y½w^Šýw/Áöuæj‹m?õþžVÂYƒY|ƒõ®(»J»ýˆeE>ó*n¼_ÕJChÈZj¬Ðfj™@�“lSye!šOJ5¿ø›¦‚@ Z7“…šÖN3ü»~˜p8V¸qÒ·û¥íœð¼¾AÎÌ ;A,qh›eÅ2Wm³L aÖÇ‹šXÏN+Ô`OU•çfïÖ~W–£§—ý®,Ê8KÔÚX×q¿!ËaŠÞÐåî‚Ôi6Ù’‰Ø0DÅÄ%`—¹Oow+º¯2Pwé7feôðìôàüÜ%ƒó[ Ä“£½“#—�%�€ÇÏNO�]t–¡a>;9=9?s Ða „�xvtÞuk‡.s ƧçG'G§.1:}‰o@žŸx³~tG?Ç Ú¡ŸÝ ,‡¤öH«¿ø¨›ïµõCýÅÿûGf»% ´êò$¬D€ÓiÆPÌÛ“pÍ’î.B 0’ߤ€Ždx=¶‡V·˜Ýj¢gãrd™ð'^À£�E÷D¦‡¥íÌž&úhåcTïréopêp^—˜ÿѰ,Œ†‡L®p¼EFôI` ”%€·d‹Ê¦š„ZpÕJû/õ:ÉŽ$X@‚€ƒs‚zm*TUMÙ›ž°‰<ǘKHV°&€ÅK\Ñÿšßµ÷ÑÐíK›lÔ§Ô;ÄScù—°šÌj?©…ÍÈ­èÐüˆÐ|{6 ^¡ l²A+‰cD‚êY½;¾Ð§ã¯\:�ƒËAßs<ŒJÌ;†% ˆY§R§½ßÎâK\€ßâh_d;±±ÕÚ�­xÎc!¶ñöïµe¹ôª¾ìÂÒ7E¿îÜl* C]ÎñÁŽïwã^êßû(_ÞÌ0‡ÃáÛ3Ò�”»ÅÌn°œ›€t ö}�ç.cõ ÁTnÆDñ½þ36/cÝ;í…p©6jÒù¼º]N§RÄWhúÅÆV`©Üd�óSÒÎ1ãì@K�Æ:R€æv%Ì>š¸£î{ÃüˆÃé_öÍ×OOÐö oi…J§qØŠV¬`2/x#lwáþþùì³ßÿ¾ÿé§Ÿ}öüù;«ªI“›Wm×H.ðà�ÛUñÌ – DÙ78•4ž#PåЕÜÈX,Zøõ«0}ÖpË(¤è2s<ÄA �öy¸Šp¿+³8l}òÙט;Ö±÷*©TmïÉÕÏ ì&:W�ZpØ™ˆpR‰ÀZØ ŸBoj‘¤ÆÏcÝœåþ·w"=e±zÔª:­uÅE•X†ÎûæË'OÙÓgOžü V3ãã“Èsg00û—Gn‹Ç`s9ìB R’o¿N͉¿«h¢`‹®£4 û£»÷˜-Jö§7J+�Æ4†-`¯>Q«ªI” Š·Eã‹pܵ[ɤAº­jJf§‚±W‘XI!¯¼ 0‚Y$C­‹Ýjq衆 ãC‡0ñýÊyM2+ü°ÒR²)Øè~ow‘�XSOñÉýæ•»-­iu´ÔºM‡ÕÜ¢‰~TÆ5õÅe«¨âµJ=fïÚ v/Þ”]–Påf´Lɽ?VÖ.fXÈÒZ£€žIµŒ>ÜŠ!H”§Eý9<,ÈÜo½IóTRÜàWÒ>[Ò»ž(Ã=Ø]ôÇ Vuúå�ìb(c•örpR¾}ž§›9=�¸I,*/-¶V¬-T¿•šÌÑfºÀŒh¸(õ7ï€üω¦«z¯†ý»×t¿A%ôÛ•PгٹŠèt«gÙÄ«”^¼ÄÔ3ÆuÖ?`yŸé“Žõ7W4‘H‘’¤œDÜÑ9Ð%zB? zR ÄÇU½^CË~:6Ѳr™rJ«ŽB; /TŠõ>ûž†�è%|�qû â‹Ð.i-¬¶SÇÃ[È(ÄÁ.oìcSðCEkéúY5. ÎÜ]ãôÚ5Œcøõ–ûHàÍxÙ/b^גּ WyÔ\½†±…_¿.—ºÄ/=Ê€Ÿ:+©B$ðN¿ßÏgS�G]uf>ô*k&áŠZµøG©ïËr<Œ/)ÛÊ‘—7éªÁöCi¸^ï°êP “4%é¹Öö¯d+)Òe3Ôt`ÙLH®Ç ]Û@È~¯Êå°¼¾¤ð‡;—ž¾¾*Î�zÜq.£bܦУŽÉÓâ˜;s þ8ly­mVxþÝ4“DÑJ¥F¦R³óÐOÜÏ÷2„ÿˆ2G 1G(U,qY.[çlQŠcã’W‚é,­Ë¯²³˜Tä>ÝXE¹Ðp÷"M†Fo5gCÃ6‹ö¯–°­h¹Z¤ùæV‹ºÓÍ­…à¶Ê‚»ðÒÜø\ó.®W˜¡Òjå 4>ÝÃzâþ"÷{¾fñ\‡NÔ}/ fm-w1 Ö<Î{õyW‰ss3ƒ„=³eÓÈÔ£Ö-—�*67ñ½0RñQe“ñíi?Z9¾çÂ*�ÌuÇÓeÊLdGáDÞJZèí¾šg–ÔÑ2”¢Ôô&µ›™ãÛ8· J܆fÌ%U¯hHõÞÆYrñì…p#ÎÍeÇÍL™œ—š2¨wœ23eV~††§ £JËCç( ÓÄW¤»ˆá<>Ó©9šž>À/Ë]¬ �“g&Ï„Rj_I�£¤ÌB*gÈÌ�åÙÄ�³ÌI˜Š}õ&¯@+ë`t ‰¾Þ�˰²*¹>…ŠG²J¤¶ò´–!):ÐQHR7é¾­‘ ÈYŠ¢ æ‘¤ $Õ—‚G’$V ýÛé«UìÈTôE÷îDÞ9n³à9‡î»o‚JËÊ=¨y¤Òœà;( ÝËÞMݪ÷AKѨ®{¤Rº�Þ÷·Ž‹Ø›Ñ´O FáEoÁ¿ÃsP^í+,à‚r+,¨xœÉ$Ë@xÁ( ¯~�à—Uþq~ÒÝuΦ‘)¢“R¥æˆj÷Tìɪvò/È&Ä`óS9�Ã(ò.9ˆWÜÿNçØŽ”ðõ, B¼ÝszÚ[ÚËüšÐÛÖ÷í„”æã³¯íö[°Š²gÚûš)Ó©ÔµRê`Ë4«‚¡`�wÕ+«­�\Y{H®¬’«ì1Û«ß«H[! qíñŸq•àO…=;¢½þxö ÑìD{ÂIiO8uÓžp*ÒžLÁÃçš±' Á;馨q²0é·V5ÇMÄÝlWÝj2Ö³HˆZ›œŒÏ9,•›¬µ½0¨uȨIkm�GΠVq~fªÔ‡VUþüœï�…  "ÏU f~8Á ¥‰fÁÀêü¼uí¡N ˆ_·tXûóbäH�•1𼃻5ü+ë†GO%ɯ2‹ùû)Õ=ábÎÏ=4%ÄRà ˜ ŒçÔm:7LŠ8Æü�hœÁ'sAÙô¥©éUÛ‘`"@?Œ›¦/ èúl%1¤¾nÑ o~´dð@£V×lcÏRÝ•`§�†!­”„�öƒ°Œ€Ä”ùJÉ‹éèüA›?ú2%¬pÇdPï8Ëwî ™ÆV—�‡Ì Šp4bˆ¡l޲ sØ]pNïC3'¶s¥ÐîIñ¹Fª¸Ïžê96S “S 'SC÷zÀ·ö|Òä!”3¹$ô®4¹øä2T—­kºJˆåO˜†a«-Ê+%bô»déò¦Æ^æùÂó}$Òñ/?õÌ„+ÆKzÁ7ø…æ¤Ì­±t‹}Šö‰ØÖðº­(\÷Ù�ëñ¢ÂÑð‘\-ÏîãÑbø›M¾„̃Þg |x¯„B¡S7ê‰I’!ªÄr¥os�¢0JÀÊ€~�k;öƒþâ´.öXL„‹� òªcBµh K¿Ö|ØŽ½Äa\œƒc®YòÂÝE¨L2ÉoRÌ�r½ôÐêVR«ñ¤M@îvq�ÐÔ>{.¥eÑÚ>mÉ%g’†l´¯q uØÑ:¾EÖñ^ödê°é÷(mögÓ{%mzï@mújF¼2Òvïü¿¿»ÈûÇß”4·HS¿îíº^^…½l«w6ßÝ�ÍÊ{�…;›•÷K«íl¶¶v6ÙÎ�MukRÉÅb~]¤l÷V‘í~4zA×`>îÑ‘}ã– ™õeŽÿòƒÞ¹ðfÆptOÖížÜ˺°÷$vFþEzÈ»'s¥ÛîÉÜo™{r?ólÜ“×öN–uîg˜�»íaé×Úæ;w´ˆжxçì¸=º÷°Ë\.U’ÓT–ºv™�–\³Í{`’¦6šc³Sm4gJ‹6š3¼e–Ü~æùÆ-¹ý ó2KîhM wsÿöÆM Ú5-sE8‡lx¼~û§ (™z�ºö‘Nè Ç[F¡-5Ú§KG©ÙÑÀì’š=ZcûŠhèPŒ™gzØ:“--8“ýà-³Æö3Ïǰ¿½¢ÿ2+±>7€,§¡Þ!ë@P7®›Ó�x]ë@ûrÔ�{=üß�GÂÌ3=ly$²¥‰ìo™ÜÏ<uà^Ñ#:С–Pƒªê!kB³'ØÌ­k l}úF‡ß®OP­‹TUž^-ÕU¬µêSE·#N™Åü%2oV€è™0šo{£.½ÐƒEvW¶EæR¤*(O§Òà Umµ _Xx߯Ãä'�7üuØ¿k~µ5UŸ}•já*–€—‡Kç>Þ6/®F׸>Ùó /øRIg}7QáÜ¢…ÄÍ„ÉÔüò“…bT?H.ð²É‘ŠÒÖj–>DŸšÐPõFÈ ¿ü”6eRÙPÏ��¹¦0î÷‰båDz²bÙ÷<4U±çuú±l¾Uõ6èǛЎ¸xÓÎo½vÜãÉü¦´cï�­dÕco4D¥¹­!{Ãþø.jÉñ[¯&÷9Õ¥Õdï—ŸcT•ƒqUe‰°e9o©K,Ε5fi�¹—�Ó4fÙ8yUõ6h̆­òJw�uàè­Wš{Œ°=*Í›Ušûœj¥4ÕL+ì4£!ñœ¨#–1eåÆ6ßÿ.«{ê½�·W|6ªñötÓŒÆWPyã†t^w÷YòM-úP `ÜÒšlè·s@�æ‰ÎºË6')_`ñc|íÉ>{6ÕW@]l}ì{"¸S/ü~ÅÝw5;^ÌSÚæÃZk†ûÆ]c˜o“ý5ÂûwWâ¤Ë<Ú„›�È ^mÆ"¡lÉÞâ§ G�¦»Yµ:‡Æ�øõø¼�ö htçÊ…ðý {TPÓ¬†ÝGmÒc¤gÎ’†Y�ö¢7z°í'}Ñ ]¥/@§Ý½Ä[zm³¥vm:°Áüå§Ô˜`û›À¿N„}Û$™©!¥ÍÔ(2·uV¬Aô™î«ní¸b¾YŠhúÖÍéO(Ðæã³O“rw>¤ú‡ªi±çeóbÏsÍ@d›â³¡ÙOÀXÉÚƒf[v%Ó` C8ÅÔÔôù:šÜ”ÓÔ\×ÌiØèÍÜ«'Ë*V¼„ÚT¾ÊÛ@ª4½–R Ù®[)@£7Aª {Ê‘*V¼¤ÚØ‘·æi£däj:õ>ýïCE´ˆ¥‡ZY�˜qzΚÆRBŸ*‹Â˜‘-XåVB@îÒ\²ñª´—¿…7kv)r,\ŸV'Ãn;T§í§|¬X¡f>ÆFof…YÚ:RU�—1,o ÍB‚7m%u3ÞÛ„ �g®î›ŸÛÎùº‰i§õ¢×¨T®W¨È8Z4ÈÐ_%ƒQaHóÎÆrÛ,e³’‰æ¥kå,aW ï¯rRĤÿ+˾}ÅÞg�Wj,8VñÊ‘¦ƒ7UÉh`—½¸dH™%TFân­¥êtý”µUÕÛĘM…ÑUeÍŒÅÖ€½¶ÓZ3î#,ϱf¢ÄßȞ죬yýx¤�)ú@†ÍÚ­�ã@|¿R7P› ÝŒK«—ê@D�t%Ðˈ€Ã¥mlUõ6 €Æv=«J€Œ­×€¥·ÓÎÓ”MåWQÎôa±r¶½�†ˆ3ûPÖ~SoDžî÷Gä".Ø›Rnn뼎ç+ušfÌÞC>ì¼};è¼–k€·v¸qàÁ*ãsõV‡QDÓR¼õ™im” £Ëz�VéØPý™^²Ý!%9~(aÕK8Ÿº%5$Ø'|%¥‡M®+_­T]$�x“TOèéó�FÃc“}Ú#²Ê�±ö²ûìãU„{,‹0¹í˜}H{ “rG±â!˜ˆ3mnšÜ.ëÜchÜTé'áÒÔÛ�w�võvA�»³u¿ü0ã‹/ÅTóÐ8â#MçJ�ˆ)~;ÓŒn5M ãÂ8Ýñþ$â%óE dÈ~þ÷EÖ¹úÅrr°\61ØRb«2²tÊq[ô ÁàÒÆýÜsæ6 Ð&nÙ’n8S‡$œ±ÚDÄVi“fó}¦ÌºáçïhtÖc£“Êû#XeŒ8$°ÔÍfzÒT¨–0Ï@ݹǯlO*º6¥¦òZ-Jj³Ø¤$Sp!8…X²a0Ö©Èn:f:•„A‡€Ç$ ¢Áêæx?(Ïóºî¡q½Öƒ²šrñƒŸÈŽš×õÉI^ê³'…Re……At üðýÊs^¢{\Yð2\ˆX>áÒS±laôR�»ö€qüpÆ#xY�ÈXp`¹«R¹™KCçÉÜÖJéºÕâÛ �H1ˆ¤m~D–!â¿W¾«âl.°¤VŸJq$ LÃ/©ÅP÷ÚÀÉ]jî°âÏ‚çè›zË'û»’‘�Áw‡5�VXÜV$p×.åóͶ£‹A‚UŠ›%ê»'ø <]ÎFýa?éG¡�’µfHÅ�"d5ƒù¾IjÙµƒD²'Ló�y¬wë¦Ò¥ˆ‡jõd¹(uØ!�yÒü„’/�QãäRª:M=&�Ëð’[Ü®*;Ž)·ó�ƒëtù¤ö£å“âsåè;­bmu�ì-/tïhä•´ÁTåCcæ�•'ÂÐ 0.* ÄpãÊç-»ŒN«‘û^[´ ÏÞg¶ÒKÆ 0Æ+.ÐVy8¤-0 �ü$¨ÎŒ%Ó#ù¢Œï6ͯB«Æ —mï$«à²R°ºKh}eÍZ‡¦Ç3tT{D~äÍJó—©üîòb Ð)ŽëTÅar^ ß�˜+ê8¡dÿùw˜ÄFÃãIãœv»ùKeô$ð¦g²Øsv¼øuf†;j>ÆùT·_ÃóISÌ)ÖËÒ¼©ë¾»¬i¹‰ “ +¤sõŸ¤3¾Ù²�-•óRmgg]lM2àGÖ&€›Í„«/6 ¬Ø�ÊÁï߾ȡ³cÅhT‹*øè&×zÅX‹ozjnTç­ª¹U$¾š›ä‘³ð‚U¼…€Šó„9séHg®ÝÔÍù'$¼$4‰�v5tÒ+šË!y$Mf„JŒŽÓýb· ÔC½²»¸€üêÖ'š[Ké“$Ú»§OôÐo�>Ñš¯6}ªJ>H®A}¢°?}²ob �"Ä@ ‰�Y›tv�FéM†¹Ü„¸šÝû·ny5åÕm’W³æm A*·S¬2ÁEUs¢ŠPüÊ©õ 3~oéåÃÊ�rê@åTÁâ¸öÀï .÷ć%£ò—}¨cµ&ê»Þœ7b:5ÉU G<‘æá­ ¹’½Qx…\,ÈZÝ›:ï?�x¹üXñ�§áCDàž·u¢ú¤¡¹OÝWi�.›Ïb}‰@Ù]hÙ�Ï¢>µv‚ÒÇV‹YÿØæ„ã ˜æ¨}¦ ë+û‡ìËê'�Ù速OxÄÔŸÞ$Œãw˜±}éÚi(ôÝá?·“N¹ÕN&yÁÌCoØNáVÑÈýþOZŽæñÂoŸÙ—#�ú#Š>^˜ƒ³GüÛߌÜxiG£v‘º3,˜µîæ+ �MZkÄÄîY+%÷½Yð¸M4Û—�9¾Å<ä@ÙÄ.ÔÙ h™Â3 Îsµ-hü#» ãBˆûwBñL+•ÿw^LGÓŸÐ1|�É=>6‡¢³`b—ñNˆ@:û¹i²U×Y�’ãÛ%à:-†k&ÞÏ'" ñVUÌ€Ò²þ$´GAð†£„Ôb¼ÉGáô¸=nÚth¿¾�kÒÓ0Ä/@ « ’Ät^0 u%àª{k1öh.¸‹ð¸1gΜGRÀ«xÚ{Ðf»0à ñ¸}eÅm¦Û|ܾðÜxþØçž#zôÒe^àÅ÷{Òá¾x<ê±±êíHVSíaø’­–ìùR÷i´ œ9›Âÿc/ $›†ÃQË.óÃ�¼x¾€ç8òfaBKѦ m-–¾X³`µ˜ˆ?õ$ÖXpøÎðX’ñÀ‰”bµ hŒÉMó5‰5Çvd¿­é éDÞ!!È6c/öÅÙï¸ôö‡&>6Ð>¨2õ�ï/Y$üÇmo Ù¹€®x³„–c±ŽŽ”m6�Ä”¦ôÏ2æ±ç –›Ù#ûPü_Χ1=½oÍfÉv¿_ñè¥nt2œŒÜ»3-jÔ \±†öp$�ÛÏÔ[ÒÚLôA)µ¨zXµc1û- ö!û�_xR°'4‹€JQgºðT��Í/#qž4ÿ•˜ŠHŽHk_š�®d@Û˜Sýh@Üõhºb¶˜O|ÁŸK £äç1õ§‡Ë¶ê�>ŒtϱËO´ïÿY?s«‘ž‹3½a[ÿ$jN‘j\g6ŸŒú#æ†Î †# øûíoFî?¼´£‘ÕQÚ™…¾³·Ø¤õ±Ú vvp÷½Yð¸ <9Ô^:f˜ŠyÈ�²ˆ]¸5ív!w€ÓåK±yÜþ²}†tâ…+™…þGv€Æ…YdYÒ5}ÌŸ·Ï�uJÀ{§^ éôŒ½�4¦xÝþâlšŠ¶kÃuZ WV‚Àó‰DÄýp,t=kŸQ+¸ZÖŸ„Dá!2ÈÂð¬>p½s¼á¡”` /"¾\ЍmsƒýJŠ6(+Â{AæC%¤P˜ö\øHTÔ<™' UÍG;t ´2-Ì¢¨ÒøL£ ¾Ã®oÀ’N¢NñK7N ¼ƒÿzáä;h”I§M­J§Ï'‰\òÀú¸‡J‘¡NćöY¦ø­}õ ð×3ó'ßÄ’ã¶Ï:¦è%[ÊE ¯“fÅbg£'ÉGnŒá½1¯¢€ÅsÁºÐ_Å‚�s%X8e�œÐö4Çž/Áxˆ‰þ‚0Žx }0.‡ [9#+dþ†]ÛƒÄf\²×?öÙŸæð2óÎñ'`lš 0�bxGÁ6�þ‚^ f ÇÏ…úŒÍÕÏÚ:™&p�‹Ð]ù+‰£ÃWõUÿÑ` Yž}�hˆfDÎÌ�Í9ôÅ™ëÁ/($ùò#e }¨Þ3º¯·î‘-ÑÓˆêMüÐy (ŠIW¢þ³Tßhzàòª½Ø…Ú'ÍA‘ø¨Lz•�£”]v>Š>‡ŸajÔ\’`�¡ÑÌ”ZDiÿ¶ÏzE¿/¼öÙ¶£ù"ÚÑ‹¡Ò,{Í`H�Ùf×lµ*ÂŽ0žÂ£z_ÿζ‡U8*¨ò]‰!ÝMÊ45˜7|Ñ@F“|†ÿ)âÑ2>À—E•d™ü>ŠK 3¬xÀÒL"# ZÕ-ÊúìI°É XKmغ] Ç›zÂí²�'|× fŽùšàñˆ+T— bü)[šV$Âå‰ïqùa5˜ýëÿè¬Or€«,ÑpËA îºÂmSß™–t1MÓß=Á?8 ]vö°ŸtµLé7'QG;$jmôìLJÒ3V<4z~ Tƒ©%ž{‘Ë:Îjâ9' ÑõçõªÝŠ�QgJ ‚ãíS‚6-TÕ‚ãû%ÔBïNI½€çÉ„khI°ŒÑµ“J,/¢ê3dÍHÈ•Ã4ø>Óæ²Or )nêE2ÎH.0§ú`paaå âl9ç°˜›ˆøB€ 6$_Ñ/? îôÙWDF†lŒ�l^�ª_ãÿ ‘muL� aŸ}]T#öíŒwr‘Å!Œ;Þ1ÜšòÿÜ¿@®MÌ"zJ‰Y¬ØŒ˜ l1û�ݨµ#4#’¿\)êÔ†,é«u䀨¾Ë¦¡ïSºl²iawj XïÖ{$1°ý Š ª# ]ÛU¢ýW ÝJQKxíù PžÎ'>Ÿe€\Ãw@§L{wØu�†;9&EŠ’– ý‹•Œ[4b–¡ôPJuSsÆR2ã 3âãctÒ£\#É+»zEªæ§É½€e,IE­b�.úœFn©úZî,t] “n0¯£•Ì6x¿*†É„2(VöT­8Æ& ‘ÜÊÚ¹Ñ \à«á"á ;@"¶Z“DÄËÈ oi}“‘êoíÞ–±W]ßÝQááîuð¸„acêl/Þ›úR_E™ÁôêÍ.®?šÑ½£9õ*ØœÖ*¯N¥Q¼ddÏ€ÏW�ƒ˜\‚´D“û¨†Pk²©UGö ð¤{²´”¯U£^Á:0($�NïŸ>¸sïôþQB••P…Þ=¨óí.ÏäŽÕÝ¿^¨— AôcF¢4»U";D}gTŒ4Å‚ù5’ñŸ×ÊØHL<˜ ·Ïž°W" »‰íÖhÄi5͆Q+Uð¨û=Tñ¸�ªF“øÞË:Ö‡Anì]t»XËé—B,%Ù]t�æ~P`³´è™$ ææ� 2ôxœíYÍ’ã¶¾ë)º{j‡¤¤�ýµ$—=#»¦²q¶ffS•K\ ‰Ø! ¥‘+‡=$§œrŽ×—<@ÎyŠ}?�ÁÝHA;Ô¬3ÿ¼U;  »ÑýõZ£ß�üéøâ/ϧ$ÓE>éõFø$9-〕á‹ó€¤TÓ0¥f¥þR ¡ÇAÅÁ¤GÈ(c4Å ¦)I2*ƒµž‡�û“%-Ø8Xr¶ª„Ôq4ÇÁЧ:§lÉš—CÂK®9ÍC•М�Q‰íOLjädm¶M¯ª\HFÎ+ÆÒcY—Iö�"³šç:ä%)¨Îüá@�Ð2%*á°�Ïy‚4”¦¥V‡qI–4¯™2Ëjà ßq˜‰ÑdQLj\YÀ>ŤÎ�4�‰w°”©Dò ?i­5×9›7üF±ý`'s^^Éòq ô:g*c ô¢×�ÓìJljRÉ$›Û} 4à8qµ^pÁôÇËq>có£GžÙnI÷«šÊKGtÖŸ ?¼?ï"ÊË”]=<É88µo-µ+Í‚!Ùµ½ ÚÝ/PÛFÙÇ´%‹M­-Ic��Ä*É–Q¦ÓiøèÁù À`¬ÓáŒ1˜ØIÆ×S{’ë*³fÅÆF3‘®�;i:ËIrª�.gTûµ¨ËÍ,”޳N‰E}ð ÿ¾[Ÿ©G$äðÖ Â~àÁ¿VBç N=ÏÈ �T$5"ÅèsÓ ùý{ƒÇ�>º‘ÑÀc´aæ™trÆæL²2aHÒ[l�ë´JÀœ‹rH¾È@µ7ž aEio‰ÒaIz7üU4I˜R—l=žDµÚ>ÈßÈ��mØ!›ÕÉn€ú ¿&è,·�î~‡t€•„s§Ï ²6Ê#Ö»ý“†Âm´vÔ-×vÌè�çsV2 qüº8žºNƒ‰¡²%WÏ{´Ø„�lè»0¶ R¾l„oœgƒÔŽÉ•¤UÅdà»�¿CD@¤À3”—[ mLPÌjš§ã ÍK°n¤*j¿òtLF1¾OFÙÀÏ&ðÖU[Ž_I±ä)&3¨äâ’ÈsÇCÌ7ù±+F½ÓóiY Ë.˜>$ŒmØ ×$£êé(®€s�7U¼¨r†bç|Q¢%-$I–’”«*§k2JDÊ|jž+’2ж¥h·ÀqÍéÝRpÓ`òdÙF 1š  £øµLá„&µ½x�¯‹™ÈßÅ�”€ úۋן±ôø¹†1h'¯¸Î šND >&9O.y¹ ´ˆ€-ˆ”A »ÂJ!ºj¶ž ß©n÷<ímUb-ÖˆªQT‘7¯p§+Ä”Ñ<èè‡d•qȬNϽ.ÈzÕYSÇ‘çy±ifkSÏ!!V”D½ÕÆ“€Š9�E;x%™12W�LgÈ$ Ñ…€Ã›R²ž5ïŽVºñ„�pè©Þ¸È‚ÀÿPÌ^‚;‚ÿÆ»UU¼õ÷ÍÚËJ‚U%ºŒYñÖ”î‘jä˜âÈü1Wƒ½D{óêV¢½yµS4/:.™DàÐ4ei` ²EÉM"“ƒܺOð�sóPêô£–#†Ü˜´}ºˆœs¨a~Ó2áRRçc¸“ærà e–ô ØKqÅ ³À¢ €‹Ú„]–p#|ñã1E(ªˆ\d@£å_@8œ±žÄR · ä˜Äí{¹¸‡ ãàDìOÓ3§¥ù!CðŽþýã>ùül:ý9ÿã'Ïž‘gÓ‹‹éy~zõÐÖ1�4›–Trãu®o4WÂdñ SzW ®�µ‘UË� þ´·¹ï_óÏkš¸78yÔÿôàp?I¿ýú�¤�ìOúÛÿu’þôÉþ¤ÿý¯.ÒO¦˜p©L¹I*†A�ã-Ûw¸R¤àÑètŠ™ø¯î¸€¯žAœ ÒøcJsQ²;ö»»–=j‚Û…vv«ÈÎ~úœóÝßÿ{+Ñ`ßNánÊ#Và±à/Fé­ˆO~LÄï½ñU]a‡kGÌ'?AÌg]!¿Pç+óZ̆Ÿ‘óã³Óç.èOîž·«‰~†’èå­{y34!âÙdÈ©‚»›­¢„]ð’J[ÆÚ’ÙT×{Ù¶Q¹>õ×ÝSÃÝSãÝSá #ï%ýË_Púöæ€qb“Ûì­Å^€ 0ÅÜE5–3.Ñ5 Åð&nmC¨`em'±49gZCÁ¤Èw¯þCÎ Ÿ¶xðnr>\ ¹X´Ÿ²9ÖOîÄdokñ…²PûQòFØJ¸rE¸-]ñ€¢½vªºÀn »ö>”ço©¨Ô®G±Õœ ¯BÓå�àá,É%ˆ¬M3´^ovÐï¿ܼ5Ôp#ñï4_d9v;C…)!±)a[?]Ëá3Ñê® ¾"I'PÅ.B�H-Øroç–áî < ÆIÝ-«yh ¯¨¿ØéÒµÖ¶oìº]Mí«g–ä L.ƒ†ƒ·Êÿ°ýòŽýíð¦^ýLh-ŠßÚõ¿¢vý¯²Cÿ[Sþ]Mùÿ»ï9›b"r 6ã`4 LÀ5¶Zí×Zös!p…ë·;oãå\¸MàNŸ|DŽEµ6'Ãþðá¡©ù}_öXÒÿx鑈ÚebXb®””fìù~àMz„ŒŒFø�13”„ ª4ƒ™™õ_y$¨6&4fcoÉÙu*•ñHNsì]óÈ,Æ[ò�õí—Ân8}RÁÆÿ‰íODz”óZ û¨¹L‹ÎU–„‹?hòþâ₼|þŒÌà…á2ÑÄHÂ’PFŒÐ$"³�SžPµ"3!©áɼŸJž²¤"cú„(™AW¨ Œ¡*"3©bj´%Á�²Ð¸^0˜(¦y”Q¡}/1b:T¢´mx”£ÏA) ySò/¶ŽO[–ã/‘u ÜS±ÖrAK¯·R«j¨”aSYβ£À:Óh*£•õ-C§‚‘PP­A0ºœREÜGßÈÔs³ÙŽ*ŸÙDĹ€÷üôwyxM+Dúܰ˜ýS/ï%‡¹cäZšT\ƒ ü‰d˜!F(êcÐ ùýo¯^¾Þ9Ñ 2Ñz²Š1'?±Sàb IV:;Ñ•ø�|žŒ=Åç PíN™ÁŽ•â¡ÁÊkV»ì„Cµ# C¦õ'¶{¼ b‰ËL×åù7ù ‡-,6ÀÛÂàï[˜úÑ› ƒÜ�¡§- RtØ/"dÅ”-¬ú"Σ«=&³uûb¾žµóU�-ü|ϦÀŽ›ìTÔõÞ›X*5¾z•�•ð ŠôZxv"¾,˜/Üf�Ñ–ÆkEÓ”)¯êÕ~ë•°hŸ¼78Ä &V$ÓÀètÕNxœ VÆ7$Ó;ÿðÿ¼f*AÙÑ%H¡L ðK>y] �bla '• 9C¡ßé,�¼IÊwµ¼ó qÉR6àŒ¤T}†*…0 �͉Õ'»Ie‚ü"›ø›Áx!|ïi Y�™&às=b'\kzì“wJÆøNçôM›ë RáK‚#ÃLP£3mY°ÞL !¯ñ¦?Ð|FF6{ª`ßp¡‰—F§L¤Q4ÑHÇ«c4éMúƒMd³íÛ›PØí­O¶7 ï4ÝQ¡íí]úÛ›¦œêã;q;ð+V-Ýõ=ñ bxíg›ñ„éØÄpÀr «ç‚¸j¢![²%Š�Øžžƒæ¼¨£*çÇ2`çø3B®mÍÐh~¾ñfpZyådjµIW<Þ"Á%€´]†Wo†Oo‘¡k3¼xv‹oe6Ý)Ä`°i›áÃZb0|u‹Éh´K†4 6… ×(2vÌGLxV@\Î�c 8¸–aŒsùÎ=`-c6 ^Bd´¡jß%ÍÈú<= ÷³n�,F«” â‘(zê°ÌÃ1lG¦làsL#úÒ®!D‡ž­ƒtèc)©ó•ÛÄÃQÕ©q î¹ÜrÇ6Öê$JÝG“äÈèÝGE;T­õV·ÍqS’eñä5ùÜam Å’¨d_Tj½¥Ý�„Ì`ò·¼Ï�ø¤Ÿ3ÃßoQïqI#2ëîù>m³²Ë³Q›iÐ�bª^§m@j\õZ0¬üêÀsÍ6~@á€]׸¥@´ž59n¡0ÊÖH/çÜFX 9S2·8qOä¿¿þÇfË i]eVn[û.•&©&vdKæ�ƒØâ²’°c xâjl£·oAÕNú•þŸ;ES úl�WQ»�u¿OÞ2Å—XˆäUm��^9ˆÏ0`ܪ·ÛU6‚LØÝ »¨Dų{ì(Z¹ßöŠVŽÄc´:Ôhu^ì™TöSìVWûvÏW˜j58 Cäc@úÒ*¹.r¨ �MwIöÊb׳ç)rbmŠR÷ËÒ¥¾ßæ›ã÷a±Ö‘ �C³Ø[÷kü ÛÐÓ¥EïËZÚî3táa5J‡f±{ô1'÷C{Y®íü¬FéÐìVñ´­zþj|Ím5ták5J‡f³{ô5'÷CûZ®í.j£*¥C³[Å×¶êù«ñµ_2uái:‡f¯{ô3”ú¡½Ìjº«Ð94‹UeyBÛs¶&a�³p$fÔåV¡TÀu*í%ŒÞ^3ÕAð¤1#Ì’‰"]Û±‘ÞO®ŠÛ$G7;Ší8Úv³½iÇñ²V]ol”Ó©–"3Œ0¥Àø1�'Üd õx?KÝ£V ßÂÐÇ>¸ Bî"|8Îöäç ­loÊDºº)…ÛøÇ³röÉIy—[Ðû\é îLr(“% GøsF‡þe<6BÚq—GMìŽya‰ý÷Þ J·°0“©äÿ°ÍªeÃIî+]°Iv7Æ­“z´îŽªæÁÌ›o vbß­Gï*zÌÂv[ªûÖ(=Zw{Eô9¶µçý³GúÃLáÕ±É4ãÂôùž¢¬32ȯl’×HO¤ê¦xr9[ë emSˆŸßØ+. ¶Ýû ÖXÊ›ä—ç*½ª/ê_n_>îºi<•ÆÈøñ²ñá]6>”ûÅ�WŠo»RüÅ·ˆ+næ J�!dì ½Ž!8Eí¢ðÆ…ã™”Ø#¿-œûOf2Žôâ»×ä\¦+‹m2<¾8±GÔª^ø–-™�)SÚÏç:W¬rÅt¹¾!¦Ï‚àúúÚ×é‚'7}ð^_ªy€~�/¬çüS¿‚ÖzÈŸ¬øëÛÔø\Ü×°ÿ©äÑöç¨ { µ{®/Üb©1xœí][s7–~ç¯À0•”4æ]–âX·l'Îú!NÊÎÔìlæR`7HbÔÝh7мlMmåqžwŸöe_öŸù—ì9úÊ&%5›²"ËU‰Hvãà8—ïÀÅï¾ýñÕÏúé;2W¾7nµ.ð/ñh0»l³ û‡÷mâRE»Ž Ôß"!Ôe»×ë·Ç-B.挺ø>úLQâÌi$¼«i÷Y›ôóê³Ëö‚³e("Õ&–æe{É]5¿tÙ‚;¬«¿t¸âÔëJ‡zìrØ ±ýéh–,¯I±×µ¡>ÅVªïHÙ&óˆMõÿM*hˆÓ×3:Jöàñ¿,.Ó ›>ý:7º5é~ˆite‰N“ѳ³“iQ¶zØ’Ëöó-¥6c�~¡‡’[U<ÒÒï±j µÃ¨¤½”P“ÙíÔˆ-Rj/©„Þþ�Ân›à³­dò•6e³ÏÌÀ_ôµž]L„»Öj§èÄcÄñ¨”Ð>º˜€Ü™?]%¶©M¿Ùš•KŒv´O_Úàgš#ÒåŠù$ùдíKð/åÐêŒ4íç•fØW81ŠŠ–ÿ‹>“¯¾>ûú|gEÃ\EYe¹1¿cS±ÀaH2÷²iZ_¹©z¸„z|\¶#>›C×îl3 „a%ùPbecówI@þ=ê8LÊ+¶¾lÿÔ£ôpËbCþAnÀÛ¨‚· �­à°Zâ·°ø¶=Fu©ÁÞI{ 0Òé&–37¢l&¬£ßù7ÆÓ̜ݚ¯§Õ|­F?ß³@›îMvrÝõ¦=ÖT |µrRá„Qò•>›\¾H˜O´'ÕŠ‡Ëˆ†àaÚy=È¿‡6¢M"�mð) /£ ™éiiWÒµn®›y´tÜ$�¸˜oåuàõV¡ž„~æ5ÕÑ8¡ócúJ�à™ë%M’Nê}±�«Ò|Fà¿®˜üª"Òi뺤ÓW‹¯Ê�¹—»èZ zVüОƒj¶ÇPî¢�¿Ž“?e!KÔ%ÏAÖŠO©_Ex5Lé2 ñ¦åFõÊõz½|ÁmÍ8N_rv-8™pü‹Ÿ`IÑ�'fÚ€¼xû-�UsFd<ñ¹RÌ%š ¦X$ÉUÄcT*¢–â¸G^x^þñœ.Q‚L((�³Ò˜*¾¦òd¤;º�q8�žðË<)ýÖ’#hI ‹ûytz†\§¤�…¡ &�.ši5‚ÆEP›ˆA}] ¿¤‘KþƒE¢G~F6˜Œ=e¸±ÜÝ’'[á1 C=ÛÇ®í»bï%Ù"ª%Ø"z”ërý㻆ĺ!‰N¤ç¶ÂÛ°°­jJÛêQÜvŠÛ¿Ýy»oŠÐ�ZT-©K Fô‚š‚�Ãf (è êB/b Ã"ûØ.ŸrègûÞ üCBìsˆ´™Tšîç MîSqH-v¦AL‰d %ÄêÂn7"¢TܓĠŒP7 „GzTUvo¦zHe¬I#_X¸]Ä�(¯ýI�Ó(;­ˆAq™D…ÈÐ^lE6¬†ctÛ‰¼?ÝIPλ¸~ÇÞƒ¨[v®µ>Z�‰%ôòdÝÂß7&}zä­ºŸL- Kji”»_Ê`†)¯ÙÈ^›œ( ^2ò…mv�é.(Î ÞƒN"6Ä$·$¡ŽŽ‹Â¤§,’Á!\BçNy åbO¡…ºVIedóùåöGÝU·¤y2ã ÌŒÿ@°p•Í+é �”œ¼W+þ³d@‹^õ_=ybŽ0+lëù½îD¬Hú…º¾À YèÝô7ЈÅgP¡Ò\8i•›¯_¶«¨vǼyÍOi‚eØ|ÜÕ2ÕÿѼ•Yñtô]ÈôÁ(üÝ„þ\“©ÇCb­„ü]Ác´¯#}øŸi‹�ö­àÇzÖúrÊW‡I؇˜/¨‡ã^ÿ^+Ûó]’cIw'žp®n'…¢‚2ç³¹‡„]‰˜Ž™À,¶ êuøcZWiQEn<ò¿û¼=>µŠf|†ÊOºg•ƒ‚/ôiÎdo«¨\àøF ´Ê êV¶hX`cÃŒ *Ÿm«åöv8~ûZTÃp�}¸;”Ø(‘s¯(�r ëÅxõ±Lá¹¥@ˆÜ¦ÐQs>UÖ1fÝ #æ¹`��joŠ�m Æó§4Ü+°äGèy™� q6ºi]k�R‘fºÇÌ'òñ×ÿÖ3*ŒH™`xœí]oÛ6ðÝ¿‚c°í¥²âô{µ54NºvXÓ Iì) $Úâ*“IÙq±¿ã‡$*µÛ¦U‹=Ô@â㑼;Þ�çé'¯æ—�Ÿ¢B¯Êd4ššoT¾œaÊ£7åD“(\S®¯¤z†Çã'#„¦%¹\QMPV©(¬¨õ"z„QNr²¢3¼ftS ©1ò4gxÃr]Ìrºf�ìàbœiFÊHe¤¤³ÉøÐûr:V$/k³íXŠ�¢è¢¢4ŸËšgÅÏ Iº ’òŒ¢…�(­Y©#ÆÑŠè‚Â?äÐÖj&¸2l4]R‰ÏQÊô†AQQIü¼Ò)ØfàŒ_¶`™‘f¸Vvc ²ª1öÌ©Ê$« +µÓ¤fº¤ÉëFºiìn²dü-H^ΰÒÛ’ª‚RÐ�ÞV@NÓkgJaTÀÙ¬ ¯¬TY\m—+�H�aú×õìp‘ÒŽ‡�ù>“î?5‘o=Ñô0=zôàîbQÆsz ôÌIfø…µÔ–”Ûcãš»¶s� Ý}Lèõ%˜ =kÌÓKÍÜ^2•¤ë–Ì%X™¢ß/^�¡‹ÌX<¨VT.k–ÓØø½ú[ ~¥ìª½ÄC½µ„ÞW¡3ó4¶q5ME¾µa¦IZR”•D)8.Y§D"÷iQaÇÍ.”ž³Î‘‹|ÿðG¿Ð$ 1MW¨¢CìÁ§•ÐLjrçJ‚A“ñå"«�çX/ŸÆÄ3�uÞºkŽHÉ–|†%[pøJªrR5@4 ¤B·0A¸k¯IÃE$˨Roév†Ïqb|�‰Zµg²ŸÑ'H|´CâÀñv¶Óe÷Èv†ãîŸ!×ÝÝšTYÔ¤± ÊvHÙˆ†\|†+’6~†\÷vËÕ�úòüF9¤×r‡8�º^àÄRéÉ5 ¾Z_@6€‰6€Ý‚œ­áwïJz¹t.0wtæCó[i®oœü退~lcg/¯OŒR_ïû8}á«g®c_ÿ?•L+“¡†�Þ�÷�lDÝcÒ†àU‹D¿=¾`I“."Pº é37DÇf8<7i’+ãKœ¼öÐð<ü ‚4Ï”ytµf=ñ˜Á½¨}’²©°;̰Ns“Õ×IüïqI$QóþÎ-YZÛç,x¨Cƒj;ôבÀfÖ%mÏ{“ß@šJ0o•bœ;ì>þ¥,JéÃû÷š”uzzÁð†—õB$˜/_5ݨŸÚšÑ—MófüM«¥®ruÇ ¤¸ÕilëÅŸä��¿é)\ãÇ�Àr·ÅÑœp(†ÁuØ»ö�ý¥i ãt.X•dU¦ ØâäÄ�ѹâþ7F\¸V�;%:]ç`H^¤Ö…�4�¼UŸú1ò––›õÕq›ûñ×âf‹AwÑÏ»ÁÐ|Úç‘ÅEöMŒ»·‘óÒKƒÝ“¨öE]Žzß0Ô²’ÂÞÐ~°*DôÙß‚ꦥBk±úÞP ¡ö?ë¡}o›}¬mvëNYÎ13QšŽË áÆI3ÓA ›aï5ÕB˜¾#æãƒñ…ð›~:˜˜ÔþB,ÓŽ_6l8B0R…~â݈nOg3®üÊSç—û¹°lÜŒ 3$Óhõ,‰Vuo^ô¡ åvÅv¼MCöä¹?=m‚ã ’c Þ#?ØÈÃÆ yžû±gõ¯eZðV(åçï7ÎX\(Ñ,P¢—Ĭ\6=ÉÙ¬†©ª WAÛ˜iÀ¶!oš�% ØïNóMÑA9sõB¿ˆ•i6 žï±E8�Û@ÃJê-é"�H„!s{äÛ8BÌ_ÇŽÆ¡¾Ðæd€Cph i†1;Fò�ÌDulß&ÕJË šbå¼Þd"”{Øþ"¯˜�ãÑa܇‘Ã1�þâÑ_ܵ¿ð©¼ªå0°àñù }O,™lXíõ0jMnRŠ{䵈€g.Ö?µ•»–ºîÐÃtôâB£C’´‘¦Ëp2<°ºk\X§±žÞ´V+IßHßúÎäÃ>'ß3�&«Ç{sq ]6øí®†fJ®¥bþ›Xû0g«ª'Û&¶‚¢<Ô\ØyåÂ….q¶¥ÈñÎù³ÕkøWs­1×µ��)ú@ÜÏÏôŠeÎgÏ•Š»ñ=Ú £1鲕b�«Ù÷—NcÏKÒÃ$"Z0?>£Ú»R‚àO(¤YBÒK?¸ô†K?)&BBèĘ„i(å Û‚z1Û{‰ûFnù×§Ù+9@|d¬û*ó\ùÏr/Ú&Þ‘'Ãod.H³p·~(õ0¯D°`‘2@×F³ØÓ›Î¦”É€¢@ldcÊ=<¯S4g7ñ"þ¼=.Xñ&\Æ®¥«aåÃ=xÞï…ºöñv}›k]ʺ¶û�ºzÿ‘M¸~k÷$½Äßl®µ1^Sá�™G=È6;‰À[ã®.´8J¿ƒ—ô(üêÄQd4U‘«miã º¨ók°œËeèÑ5Öc§:D2]°´ñÔ”P–¡Ð‘/¦0¡‚ꉉb׳ 6…µ{Ÿ¼÷ñ×ÿ#ïìd~~­ù¶=½1ËV"Ltjýíñ”; 8¨ïåMß4kû©LöÈ¡tGÍ'B;õr¢ Üg2ÐR(gúÿYãýï2§VÿC¹Ï¤ÿ¡¥ÜOG`8h|¤Ãë­¨8üsðÐRpO8ω…5lk\|YO|ù¹ [Ñ“Z’Qè(¤0:ˆÂ�\Lcë}E±ÒàPÐ1Q‚T‹*°ð^üÏŸûþs)‹­8o¦ñìîB*±‰ø Õ»l1 ÆçA¬ðƒI´Ð•MK3IŽ·–>†i�w+}Bof§^{ü‹}çæSlH�åRû·ÿË5 ºKɇ^æcz¥dÂñ¾‹Q}’†½a$âÞâmÇ`ñýª*Õ‘TMd<ÅTVˆ„5Ì×ʰg¿¥Y¼6a6ÀÞ¾P�Í5dL&%>ÄÞÇ ã„a4b^Øs¡¢{Rbwß´Þ³"½ãÁ-U¥ÕlJB=-‡! ’ƒ$l«ØZŸ{/2¸7E'�R¼â^³}6£� ¹Sâðxsñ?ï§LÁìhÐ ÃÑÉÓÓ³êé‹lL�7mI)™ün˜éž”8iÚmF´^ðÑû<Þ¬¡\Ôm*¿ÁÆjP·½Pø5ù�Ð$i®žÑ#Ë9ø�PHÉ'8p€&|;7ÙÅWÁ&@mð9ÜŽÞ-gWs§ÔŽ&Ô¹BK‘¿4VÂÇã~rg5­Ís¶ª5ä¹%Õ‡<Ú“@Kii:â¬ñéˆ BZïÜ Sô·‘àÒßa¢‘»Ü0lÅ-�ÌžÖ�0¦’Aë]•$Co(ƒ_q�N6#F)Å4Âì¸7ÙpzáMGMºûL,ÃT@ÐÏìêÉZ12AëM;îµÃbÂmá1=! éÊ�¸‚ƃè… ‰PP§ãñ#.á¦êNi¤zk4Å¥4«§É©ÿº†Æ}44ÌЗ:íÌ£�iWÖµ3¦è£�y`v¦G?š›Gs³;'ÙÁaSpÞÙ¯Mœtè0^o¾ Æ>­¶š‘k·;`Ç4›‡:õÏŠ¿‘­dTM¶æ ^¡\Ì�Αˆ¡%ZÍo‰È­Wj«� ›ì$g6±ˆ;–±\#Z\ŸqœŠÉJj‰Ôy‰Ñ"—@¯Ó[¹IÞ_Ïñí®*â†Çd±H›'Û3{5ög�_¹}>÷ÉÇþïö§G(Š¥ ßV¢2x®6ë‘TCïÆóO=Qóè;]ò3Ð+W,ƒ¼f-ÚP.mE5ë`šõñŸÿµ[·´<Þ/åÒµ×›£Ç’w­\û€ê›@õZ Ðè!BµÒ®åejEO#êØõTNI“ ÔšSoÚ¥Kºîâž�®ÞešÈéyÃè÷%¤x"‹åœ;sâ¢ozB+Û„`›=!sv²Gþˆk/4³Lb8 ;d©9UKÆô†„–抻Tgå–^ô(i| Œpu"…+–uæPk–{ò�Mæ[#À�íFñ_¡g·?}�nŸ¶* ªî…òByÉ ¾Qæø8\(sYÈ Ãìq¯3OL  Å÷Ë[RÜ.’‚Ý.té¶�ÓöxЫs’Yºdc;È­™Øº²6sݹC.†µ¸5ÌĨwòtÛ7ÌŒê .VÕ ÷¸ogt[æwm“­×¨“AÝcãöLڶѱàži|[7îšg9Ò'So«NZúq>\ĉãÛ�HG r@L«—­ipÅ"½ûóŽhë”\ƒ@?(ÄJŠhë*¬ `< |^±P™‘ÓðÌîÞ6ˆ²uïåw™ © ÑS;sM˜®Û,�S¶µÙ’îûzƒf*¹/7%Ñhë�–qBÞ®‘v–:Œ÷Õadt_ùT ô¯5‰×ôÒ\-¬¦K>â4t«vy³i¨–�«—_J¾3Ìv¾ß¢Á'�Ì#d3èÐ[.—t-ÎûÙ¡&gÿñÀýK·J'ö>‹é¼ëV@þ�¥;‡ªÀ•6 ׫a“[E›\ó2ÉÆB·ƒr×\Æ‘ÒÜyÇ{ÆtfÏæÈ(y<` ÀÜx•Þà~‹ìW¼éž¦7]àçfoºŠU7]$Ø þÑ6¦ Ð_šm’l¼ _$¹* ã&q¥QÆ‘äA7éi—›ä€fûi„w³Úšðn×^å]Ó<ïzþ®À¿™Ñk¾ HwW;<™)¹wHqiò|”Þ±û­ý¹‰ 1uÔÂÔXð0�šæÁï-RTk'À¼~+¶™œiO›J†a?Mû“¢ðÎÍÀ4w (�(8af­—€¹·'LB·õ—&�9³x‚³Y6gB«ÓL�ÂB²™T®rÉ‚Sf‰ê“ñBÁqOyzh½9 âh¡SÙŠ=aQ$¢ä˜ÅôR­%÷ðÖ_©uÉ�žG@¬ß%Ü EîžK¶rtWé3B¦6=5—E«ùMv-jpâ]7µ.Z1R  µ¤Y$$+o˜Nƒì:A‰wKæ ›Äß-wëc JýI|}˜÷Dg2j!Óiw²îâÉiI—¿™æ‡ÔÌøÉdÊà?ð¥Ö‰ä£Hº6ê0Ç3¾¥oÓC/“³È¯Ï”½“Ì!€ëõNÊú¤†,bxÁ»k€ÈY¶ƒZ3M|ßã-&["T‹�[¸Uz -ôÎþˆ–Nq(FµùËCÊ#{ ÿý·)G6­mE"b¡ðü«ã‘{&]Òí!öŽ»+5·tÇA©¿ªxöûŶ?z²ýX�›1S–Œô¨Øý�ê»ÃõŸœ j^Zº TïÞX‹˜,ñv‡eDÃ.ÕŽTlN\èn÷jÌ/ƒ«a¹†¤G¥Äòæ÷¾2´ó‰é/Í*’¬¼�r?a‡á“Óo¶È&NýilgÎÂÓÆ‚»Æ%ó†úìksXДG`k §í×llõÉ_G''»~Z>Ñmœ ’G>s9MsZâ:5N?:Ú›õZ¸… AcóRd¿6+G†h¥9¶w‹s±·Döv„ÀX‡×I·I XBň¯LÜ�ÿ¨:ž�…:¦Jx[Íw`Íjt¹Z~‡ƒcœÌM"? ÍÁ¶þ7Ç…Y-°ç—re«1ë‚¡G´š‘9ü„} q¥Š¸£L¤6:d Ê"”÷³ºˆ˜=H|—›Kóàû»Ø�@Šù ÿí"îVqÏiƒx»\ó©—�ÍÙ˜ú.©rÊzKú 4ɾ¼Íů¦ù*xTs ÄbÏ9™IiãìÓ0=6tß#Õv°2ž='Í9ýO‚u†½ž#D5|‡)zï�{êë9�ª#bo^猼ÿ>h?ýü×-­FÌ�àf²Þ;Ü�ËGpÚCŸõ#š�ÐÊÍÁ¸-­ß:|‘ YÜÓZ5�g¥Á:Æsh?™‹Íœ&E2LlhÑLuæÚì™)©Q ìy'Z‡JÌ Vž¯³ƒ^¤ª˜_Öïd÷ÙlÝÛ;˜Úìµ²¯nஞ-ƒŸ¯)`3Š>°êæ6sUˆ¼÷=‘ν^q¤�׈fß3Â+ ÄICš^«™é"\osßÎ�ž>«tÀ�ùž™SÏñ@¹Ãx�`XÏk£zåz½^MWS¼4Ýto2ÁÓHÁ®d@â(=WE-Eªå3ŽIç=²úàŠžö˜s”jîºÒ“Œ¿êUN$»·’…ýeøŒqBâž’³H÷ªã(Ü®ýí�@�š÷áx‡âí {ôáÀì”u‚ÞéÁZžã×2Pîs7w‰5 ·këaíLþ©[šV1Âp•Xc/µF…('Bì�˜@ö6‰âî%†%/?ßH]ô©*lZ�Ϲ�*­?ÿ‚Dƒá9 FÇä’Cò{øHú[`ÿó_²ÙC_syHÙÇV‹äþå9w<Üó„Yn¦òÜ[ùŠ_®)Ÿ~,&§t1�`ÀüéN„R­–ÐïF¶t–…z:ø²�VJstº0”>I>tíŒoƒE{=9è9è/�NÙ¿ÇíE¯Ìö¢ao¨‘§Ÿ\ñ¨!äW_ Ÿ}}¾³¢a»Ð‘¶2œ\ÙjÞ%ðIæ^¶£Üq+m%ùQk)ÙÝf>ÃJò¡ÄJ9}´ðÐÂñ—ø”ü€¢ú:¹÷¯ðÞäÁE,‹¼ÿƒÜ€�Q;;W(§ÞV¦Þgïlã ÷Ôà褂# y`=¹q«à,ᆼÁ׊,¥÷&Öàëi5_3v ?ß³@›¯ vtÁ+­ÜŸTêtc"~Q*d =´w—íQ;‘J‡ax×.‘Ì«þT|ƒDB§ùuãÁTØB Ogßœ“W"\k'£Á謣gºóÊø-î&!8©ž­ë•F»®�D€¾4�4W*”Ïûýårٓᜫ.(qOD³>ª7þ õø›zº¢%ÊúÁ~ÒÍO9MçèÜN°š8ãÿl‚ÏWhàA‰,o(¯ü ¬·(¬?iÞ²²Ê#â$)U9«§qèš3ÖB–«œ�0*p®7ßòDi?L¯›q0½>pðq0½>pð‚ƒe6â`€;pð9L6JEíäbÂÑ}wfÀ·’ÝM8j/<ê‰T¡7çR yàӻѴ•3â_Á­…iïj¦×_%•Uá ÕQ†}9óuð¦z1´Ë�ûà:©`BÓŒ�Xä7¼†)Ý>Ý_Ì%]$4˜À¸]H5“I3Ùihœˆp»‹ckj…9íVuºƒnj<摤lƳ6Ì7�@#˜To×Ì2‹˜Ö¨2Ñ.©XœÛœO`‚ü-£pu-šÙ3T)d¡dç±¾˜ÇÛñÒĄְ6Íjš»Öãðo¶Ãá_ÿø¿cÍ+â�0Ì«¾æ´*…Csší2Fg–mspù 3hd SçôZR�J„3è,Èn†Ëõì=ÈîÞËrÐF60y°»ZôÕFÿÖ…«SžÝ“_$JðñlÊ¢Rv+JÍPÕ²ÀGðeêáÑ‹—T>»jfÁ èAÄîÞ†-o§În)ÛârÝ‘ÙeiÜ%D/ó4Ut©a¶$„61ëîÆÐ>P¶Ã8D;݇�UVmÂÐS‘Têy‡£F޶Íè/Ûè'ÏÍ ¦=Èóݚ̻—eéʲܽ,Ë[•å%—à!I3I`ƒf;x5èS—æò¶Z»—ˆ#x»,d OGóÌZÜÓ€35à|4›–Úd†a³­¸sÅ*ÖŠµ¯l_âv;ÎÊ™(3¦wy=¾8]QÖ‰QE.‹¯£Š\殃ª“òÇg•Õ‰ºñ7ÝiÚ—¥F:µ�¹!Þ¶TÓ×;D÷äÑ…1Ù4vø0LGH›¥@ÜS7w½·pcë„P�Oo;œøà•vqÓîšÝ¹Mß³Z}û¬–Ò·böÕÔ%5ì†9“o”GC´¶f OñÛÊqþ\ô^õìq»SÊ�c˜\ã„;Oa¬<›0ÓË‹2Õç[áÑP †±½ˆ<+¡‘¼¬)€t2Sûmçº%¢´Íi ˜ÐF³•ƒ�ž¼¸ýÚ-ù> eŽvH£€_š0ùZ1ˆé ü¸s]\@Íõ›2Z5œ§ 6ÉÛ øP»É*ÑDÜ<‘ýïïù~æ%…‰çÃfù¨6ã {vÞƒêÊu~.ÖYV¨‹Š(Ã5ñnª3.Öéª% ’èßg¦[·ÔÖ’Ô':U™Äöw`F{ÑP/ ¬i>2¶ÙZÍlõù8n¶|ÖrÛÆ™ôÉX»´–xêbÌ"Üv„²Ïð(<®W¯�j[q[†B›§v¥uÌ W6L¼Aªàá@„Á %XŒÛ¶I}¥¹¥íFäWmÈñà!P¢”Œ)dz�`š÷š(2mê©ÊŽX*°¾ŸÁ�åÉ÷ŒbN�"¡JŸØoÝô­¬È×ñÆ1Õ묠>9ìõf`—úݺVVmNêw_ž¾è¿~~÷›”4mãp À «-¬+§!€LëÁ´îÑ´¶íã[2°ØVvM=̶YÍ:ñ¸Íª£½ƒY=¹Ofµñ9¬9ô~ ë­[È?áI~Çì:*éUˆgöhÃB>Je<£�6Y­ŒM½ ø«´’™AëX(áYPžA_‡lËP_Ye[%SVËŽ&}²çpÒ)a2 @Ÿñ 0þÅ í"4ã÷™ü�Äz$w½\¨‡ñŠ&Í9€ ãÖäÊ)Ì+¸>'zÛØPm:³QƒǃNül/£yÍàîÕ˜]îfÌòÑñ�¹Çu¸4“bÄÞœ$ŒBÍÍA;S1ÓŽ) �Ê[ÉùeIÕ䇠êåÛ|/žþºS�fJ~~²¾ï¥\S,ô•H”¹ÝIŸ„ Ê:L�ݰޯLGØ_ÌJÄ}‚ú´3tüñB'\9מ2ÚTpoq*ͧ¨pÑöÅgß$­$ËjÔ²ӤF¨±2§ÏȽVhCô<¸ ÏcÌöî¸jq`úAïøø3ùš ž�Âx|‰�mò™tˆ~|fôG;;žßÓ6™÷™“Œ–6€ù'y�w•&´»Ó:qC­´ÎAëlÑ�lÆÊåbšš) µŽþi¦{ÚM•Oì(ŸxçÊ'Þ™òùçïV÷ôàérYÕüó÷‚–™Ð0\h—·ÀWë­ñŽ¨äž¾: ©£kÉécþÚ-…t�kÞâQ“5±rUº�;qRÈ�X¹,ídP¬ZÀ­Ê£P@ɽeSlyÖ̹»Ý�ƒÉ‹eíF Ù$3_ßåÁ{f+G®oÇx§faÃÖ>´o;;m»“…Áv:�9éºä— ³:j²Žêó9j’Ž,>Y&ÇýÊ{ÐØ4]•É€÷ã]6óŒ:T?4kzbk\V³vI粸Tü“êYã%³ µ�Õ� ½´¨tíÅ�êŒ= "g�Œs›rx~°¿Ÿ­Ë±nߢºÖuÂU±�hí6¯*™‰­×”ÊæDw†XÍå*­ÌÀìÙ²h î—ý•v­¡ÆþG™�j-›Qà‹0ÛçË+Tï"’&QFIÎú V’Q€HŸöÙÙ”{S=µ€'Åì©S˜IƒïF0`—]ò+Ó]!ƒ³ ¼jP¡\Ír—“øÊ´ƒG]=Â5®²-,-&Õ®q½Úx�ëlócpO74[ë÷Oadú/ïzYLGÓ|Î øà×lï×<ôdÐ’{“e¬Üœƒ›spsŠnŽ i°¤œëŠNÏtw²dÙ'àö4Ș}|nÏéëþàγ�ôp4ÎÊ¡ïïR×mx0³4ŸŠÔ¡Ñ»ûîɼ�]xweq¾3(Í­5ÉÊú“IMbZY�VŠK}ib�³ ì?RËã*«uMÏ=6$ƒ“{a@šæÔeÀOÛ|ügeöÝÁp ÇÝLUÀ Y'„i'%ãHtCì!‘:GÜðË�"Nª~áf¿5ò[bÁ¥ÑRbËôdø£ùTŸ»’('­xSP¨àû' Ýt⊈‚ùbŸWž¼Ò&h·LêÓŠ�]�t�2¦¯³0g,aÆ—½Ã¢œÜ]°$Ûd™°+ݪŸ&vS¿†¢J¾. ªÁ9$;—0Ñ߃/#1‹L®V%�ö[Ê“lO…×UkÒ|ÿ‚=»þOeŠWKF˜ÐºtÍíÅ£9: ( b�&,¿DÒX,÷ðaÞ]dO 6Í�0 ûñ”îguøqSŸ'ç›ÅPÚ˜úíRxßðéúŽ…&¦Sã;+.õ5fÓ ~DùžBwcªI0Yl7©Tåûw ¾yè=#ëÓØM®oȧï‚ Q:†ö� Ñ‹3›‘æ8&Ø÷ׯ¿¼a‹ä AOŠúN�¨�ÌÕŒæ(ü1引ß}‡GJéA¡[ÌÔA=O$ú «tûíº½\Yeæv;»‡é‘¹Bæ6RõI´†¨t76¾°Ç9÷[¾®Û¤¹:Ä:hì¶|¯óû´ÍŠä (DÎsèFþ/z*š—uGóÆ“+†óækŽjæMƒåEÕsb˜Þ¼y‡7BÊ4Ѿ‘öÀ5R.Q‰<”æ¦r=ú¹cƒw¯ÍMê—u´6�Ú£:_û¸ð{’W«½Ûnë˜ÿø‚m Ù©Á´f³›Æì4xõâEC†ÚÝ=Ì‚7M91 �Í|èÉ�Ë+Ü©7ˆwG24¦%·Ð síW‡B_exNž‚Öê±Îs«=^¶¨XÖvë6ôškî“þ«{ ¶/™[Øý(î-4ð‡ås+œ [qi¢*HÓ%ïçÐq½ HÛõ…dwéí$‰y)¶ã;08M—² èýÖêcîóh:‘ÜÅãÑqþsu£€`¸ùÔ(§”û¢øÇ ðùcÑ.DôjDb~:#¡”€±Óºlb¡¶á LCÞ(uêé¹B’=tú­ÞfgY·ÛÃÅm6qGikè0èônQ\‡¡&pM‡ä«/¯^¾]ÙРU ¤m Cª×¶™Ÿ²ÍnX¥SØ4íQÞK F)ºh%Ú4­îsƒJöPB%CD»F÷³ÝEûÉÞ™ýøoÉ{®f\2ò.áj ~÷ÈwVúez¼wÅE*‹}ú;YÍ“*4c/ÏNëÑüøñc Ô¡±kՕ稟ØíÃØŽ3�heØ�OX¬ˆRVC�Vã5a7àcîFªÐÑ€TŽœŸœ µÑÏø1ɹNa¾k€zæ¢uÒÊØÔc¸{³UªÒÕc!°I¢gå�Gca�@À^¼~K>ˆx®yæö'/ÚzÕÎoÁÝ DŒ›Ñm[F1Žh.Z"M•Šå›^o6›ue<åÑu¤º+’Iå_hÁ~ÝÅ‹6ŠªiAû¤»Ÿ9>†8Ú5Š0ü¿M«   «b×H¯ãxœí=ÛŽã6–ïõ\ ª'¾VWõµÊAw§³id¦7H&,Ø-Ñ6§$Q©ry0û8¯‹ü×|Ä|ÉžCR2%K.[¶ëê «$òððÜxxHžÿÛ·ÿñáÏÿõãG2Ua0<::Ç_ÐhrÑbQç—Ÿ[ħŠv<)©¿$B¨‹V·Ûk �9Ÿ2êã<†LQâMi"”HÕ¸óªEzîLj†ì¢uÅÙ,‰j[çEkÆ}5½ðÙ÷XGÿÑ&<âŠÓ #=°‹A·�•m_�FÉâš�ýQˆK’Æäç˜1ÿC’FÞ”HE—ŠÃÅE$ÉX$„^±„N˜l“+špy¬�¥#Ÿ&>Á¶)–m“8#:âWsâCU ¥º–6I ´I”†#–H™†¡ì¶lÿ|&½„ÇøN#m©¸ Øðg»ï2ìÎ{æ£)ðè’$,¸hI5˜œ2¤RóªVìZõ<)[dš°±οè{½x> �(² Ÿ¿¹ºè�Gl|úÒɆõþ–ÒäÒV:ê�N^½x>®ª”G>»†ú°'­O毼¶ ‹t�.rix, ?~üØyyvº QVgŒÁ‡Újâ„]9H(6a ùІñ[òž«—Œ¼K¸šq¯¢zQ[½K¹¼oËD4ƒ~ÞÓBv>þ\Ëœ¢£€/ RB‡éÕˆ&Äüt”ˆ[¦5]0±-+ŸÑh�õ¿´à5u*épÅB’=tú-[þË1´#M¿†®¸ ºâ /EÞÑl|Þ£CòÕƒW/ß®lhà4´hÌäáOlÌb†U:…M×zÊÏEÃ'4à“袕ðÉH»²Ï0•ì¡„JÅHºŸ7ç šz“ò’Í/Z?¶†Èm\¤²ØÁ¿“5p>©ÂÙeî*œ—Å¢·Ï­! T¼žWà$½N¦L�!®À1C� à–Ž oc¼N«ñ*ê• |þ�E õƒ tr}j u-¼ŽœŸœ[á!ÉPšáÙðùU†|&N Þ­ø8Kh³¤å †[•F‹$ûR -!™¡4÷Q1åv%( 0çÓA�Í�/G…:&†Têdh åNà…dˆI/7«XÒWù>!ð¯#F…J‰ôZ3¯k /—1�€ZL‚ZÃÂw�®ÖО÷ðË0û)WSP4­áqö8§ø•†U•_òzY8}·.ÜI3¸n·ëÖuãY^ÈWHb°!gA$Ÿú>ó‘¤q±û9>sšÕ”{‡?àSû�L õô  ]ÝÆ©b’¨)#t¡íP1¶_&š“%9hù-TDZÍÑ?ðÄzMϺäÏ…ra*�[Àýdº©9‚Ã7D³kp‹‡ï€·¢ ˜ÏX™€7NW¯ózw,�B‹u¬˜ß%2%x½�� ;T�!Dª€ç–0?õàY@¿6 ,`Æ…Êâãhçz+þ�1?8ÿö8ÿ]À©™+¸¦Èz1]Š$iÍÏŽjËÌM®êÎ=áç¾Þ5”† ÖŠj‡Kñ@3+m�"¡`j!�=W)Áãy°ö!š«]óꄉÆìjaŸ:Ç–4¨¦ h"� q–ôdH:æ‘Q”®Ù”K`Þ M_ÞZ¤H9V|„>?ûŸãA/*1™MA¶Ã.*UÉ uŒQ@ªäé’w Œ‹Æ$¤sÂ(ÌW¦ „‚�k±TŽ©Ðv¥Dmh%•lœZª=0h0?ƒJ¡Q˜ÝF º\�Uh%POÌ�@sˆÄ78†tq•Ѐ°+‘XHÉGÁ|ÿ6kÌ©vo›|ÞØ:!èS—ö;óÌ ù+ô ï²®~wEƒ”? y^{WLd �š j&43Kþ7Àº›»Añð;d¼pI¤H4ë~× 4–¾ßÖß­“…Ö½à¾ä>¥©ËÈ %L¥Itsåˆ{»ì®ºÚ;èAiÔS™—+ë@ÆË4gÙ^Íj] ­-¬wõŵj¦«Ù¾‘g' Œx’f&*ÙÒ{è7·ÊцP0;6\äüûs%DLuî‹àÉ“ºH $Í5lúRqÁ$;5³á«i@ÁÄg]’H®Oˆ‚±Ãk~,Z¬s³ƒ¥€˜-j÷EtEaL0R1¨ˆïÀ¿ ­�UÍârC—«É¿üë»}ß$z½ûí� Ôló†S#”/ÊeJßO}VÔilÌ€‰’PÎQÑÚç˜áf #t®ÙÜÚʵL4¶�qÏÌí´0°,E g£ô+J%�¿ýý¼9b› m(‡J#âç+æ°ÎÁá|;³úêb[‹3Êp-ÞlFÙ©»YÉ(C)©�Ø�×™Ðܤ<Öh¹"ÓÌ6ýã@»™dV!·à¶Âe$Ü­ Vê¹ Â´åbO\±YÇà9Îò�&üû"W.=yh¡U¤³ê<§U¼¸yéu×>ÍÓG7_,MØ©OÂ^ÜTËs¬ï“²ç¸/oCi{JW"îkŸ´=é­ Ñ÷ÎV³#Û%h°’J±(üó'7«W±THI®@ M5�øöÊËú’Y÷ËYr­¾¹¡8¨c\–¢1ü ~@yk®[%çEιѻŽnm¼UhÚ©~…f>íÖ’Ù�½ g�}óå2L*òòÅS%’»È'»�hº=Ú1Èpº7´ûÝËìOpÁPª9¦5ÜÓ—7«nGÞS›÷ÌœH¶ï4ßkåÒ´ ¤ØÝI­LÑ!»W†I£NVÉ‹)rÆ]¦¸ÀtáӌϰaœÇ½*M�YVçéœO¹ª“óEä®fÇsä^¾ÉS‹û‘oEùS5Ža¬¿i‚0³g"ØôÁtGA);b�(qÉþ87ö§ŠÍÔ�#¡Èð`¾9F‘¦~}IE4Œ¸d± W„\RÍò¯SŠu{Oð17«þvà£öSŒT�E”Á»Ó±ºâ,?ÝCÓT8 ë¬níCw[3I]+µqûÕshæ×·jœ¾™ÃìÎ`Þ- ²>øÆf7ížó‡[3xpd­FÔ~éOu(=uQ@ëoãéWaU¦fœµ0Ôåvä„yií’ç.U…’R¾_Å5ßC}Ý*g:?«‘M;Uæ×X€EH´.³²Vt…Ó÷4?²¡È9²úùb£Ð €åáío­í3—õeÎ7™fG&fm‰G¾5�¹l…ìÓ¸W 44œ Ì*iÅ¥ÞýÄ ²¥cwаDq§ˆI\&U˜ëÜrN¸�¯RßÕIøë›‹² Öœúü¤·('å}ĽôKÜ‹UøÖ;õJÜÁþÂ|•…ŠmQʸÒ:�%I«;P¢8?K�$ƒ¡8=%¢4MÚ¶RÝ]ÍØ­Y”[yÇfÅ0øèœM.„4'ÞQu£�ý_»‹&µ:ÀŒ]ÓÆti€~ï‚D~^Zã¬dËæ ·#6w X¯Ø—lÎ#´/ÆlqT8?ôÒF…;æ8§„?ËÏô­=ÇGN/¨¡?é¼ÎðŒm.»U­,×p ¶[†§hî›�='ä§Å]>8л˜•å] °¾gÎ5NHÃîÇ3³”Wm;•<ÆrÓª]íóÙn G €™ªV¬ÀÒšIp ‹%OõÜóÎÌÌ6÷¾²ÏÂNî£ÁËí“ûîy÷"·áöÌ��EßÌY•wf¾­íq·GZæe¥¸èˆ0„.ƒyïîa¡6rìt&âd Õ#SÏ\ÙœAï/C ^eÍ‹xíȳ‘VÈdc– �áÊÂJ:©ÓíÚ4¾zýŸ{­ýÝÿriõ9#ó+/Ón³ãŒæœ{}]ð‹,Ñ1èûu=s“üj@¾€›;”-ƒ2É5W£3tèc�eIu{À«ßh|uˆ«•÷ê 2ð´ZŸ}›Ú]Áºæ0h‹>»öd“øÖäp{èÕú D}öpî‘m¸[¡Ïžù®ßËüª²>ž)°¹IöYþd7Ó.!¬XøUrqÕùÝ\¬IFspÁåMKˆƒÕsÙš7 6Iå76gÖžh×lßêO=ºþ“¥ÂïÛ°³ùãöšíà@WÑ·zŽóç6Û?žlÿ š½&óÀ«É;—ʱ](ôÎÀ ã_ã(Œ¹gkŽo �"î…Ûà •^=ÌI¸n~°WД¼ì¹žNïì|ŒeL1*ýÆ/]hiM4:ù²X�0÷€ä«`; -cm!½šsÔ«ÏÒ Ôp5¿3Ír8Ãõ|ò°¸»Ù23&gxø¬O<_”™Ó.$¼ºŸ;\-)‹Sæ×н¿I&ls+¦"G¾vOhS}«Ý¦{ým1ª= ©ŽýßnÛšs<9Ãx¼êÿMb\sx‹Èë´ùâºÌšfY>gš»s ‘XëC$¾qUýðΖ(²•Z2vfáè=c«þƒ×_«í²Ž–s¥ÿj²Ž>x^0à»iá^ïf…%’° ]ý$f³"¯=ãeñd60%Anj<ÊïpµÌtɤþÞ§ä¿ðZûÚ½d¸•Ay–2yfÏõÙSY2ßPE~¯uºÔôxzg7H—N”½ñ)ûÈkíM"+Á³˜ÊÀ*nìpµ”òO¤×-w_\`áÉÓ©#²Š;;h-!œ¹ï 6+{¯�ñµózm¶cŸm×TcTêˆùUdÔïÚèÚ —ø]û÷\}ƒSÀ9îðtÊÿK¼Þ©ý%²;!ÀÁ)bÉP�ž¾2?v€ZB$4*-…Wß÷/¿ÛJÕN‘q‰ˆÞ×AèFm\o2ËS�ü¢Ï kC ÿÝP›Ä¶A—I<Ê+ëü.O­ r¾7�=ö\ÿú@ÈHû�cGqõļ-AžáŸýþ˜WþyÍÑZ3ü&ŒzUKÑšÝOÐó¿Sl“ØÖà¡Þ·)nߌeæ“ Þ·y&›ÅÀ怗R 3…Ͼ¥ÛyB…^'W¿ÛEׇ7ÿa¯KXóD¦:ƒ({“GçÜ=òȬ³ï‚tKä'ÄÌ«Q]—Ü—_æ«Ejº¶ÙãüÁiKˆ*ÀïE^Ï ®‹.‹é0a¸íº¤ËþÞÝÛé²etÁúÌ«Zÿ¡ÇMÇ ¥¬ÎfpFì4ÚÒÓLùÕgϯ Ü”*Ð¥ÔLKˆƒj\î;CVz_ñÛ¨¿Oª–~SV‚-]³ iäyƒÊƒ�::²1Ä %õ»"2ܨ•¾Fs�¼º…^×_×·CÑ·‚ûrKníô ¹óíÄ&3œyž®¢�5j’™=.þº&¶s›^ Œó»¿Q;< ¿0è{<é�­Í�¥ló:XÕ–N±À7¿Œ».›Òˆ&¬C“¡ûhæí“§x‡ÜÇ;»ÈÈ2‘øÏm{÷ƒ×ã€mÖ”L.ÿ¹mï~øƒgþ-ʺðaCɼ¢ïí�>kú÷\ý5Ÿqýß_[ð$äÔoød[}Š˜R\ɸ~ûGê5k5[P½ßÄK<§ÿJXûåàúPè{>¦}Ž ñÊ=¶æc›½9™ôëÜz »§ �ª³!.˜ÌÝ ¼Þ9Kd$¤b©eŸ?±�ÒMŒ�©2<2ÑkÎÍuñû%S*“…Óï~îä2ÞžŽ…JGžOŸ‡V¶rDöýnÄò\ýZ·¹/w�‰ÁYÌd�ù=b+Ž¿ØÎEÔ*ÏßtºQ % î.ÂE/eÎ¥T¯}oˆNÕFíÑj ~ZH¯*ê¹çú´J¬‹®ËyæßØ[»4ó�Å»¶”ˆx8³Òõ ïìVºVXfþcjêºè.•2æÈÂ릖HñUicTxÿ¶AºQG¬4—z™ø=é|kª¢«^¼nà}¸ZÓÊõšù±Sl;'sHi†Ÿj¤z~|>½³×±)g‹ϼ.ß¾ýÑëÇßþùtAî‡Xôx°èñ)‹f•\Þ-¯3µ“Ü€Ž$KFÌïFº·?zýÒ÷Û??Z$¼E� ‹?¢£…»¼[~í…s�ýn©úòºètÊœÇ;-¾”.ð{¢õvæ¦ø¶Ô7ÊAlÒÓñ�¢¼­§oúÏÀÛÒü» ÆÎ}öìÂkíë;'€%àMξË"Ï¡ÖÀ4²ILlð\:Få°�nƒ¡a â!“Ìoƒb+›Ä†A¨¥H¹çP5­\×aÌ"L|zá~î\ˆeÒÝòÉnùd·|²AÊMà‘¥¹j3?vŠm ‘ô©”,:ë3@—ßw¿o›Ù¤!Úd²-²Qp¯æ²ÐsëSrAÖçÁzeÜûׂø­×}ÊÁOۣܜOkx²À? CÏ,\7ýùj³ø×0}'-ód³Ø×4ü ‡Ã«½¼ac¸a úÿ¨Îf±¯i úÿ¸Îfñ¯iø‰üîÚ,&6 Bÿ>Ù,þ5B¯�JÏÕ¯vé�}óÎwë„ÝÙw޹緅õ‚ÏoÆ kƒ^È”bRŸ©Tø=Q%T[ ¿A”ñð,”4ö­ŸQ(·V–Øèw¨.nÖhnŒæÜdÿhßo9-}Ãظ­pÒ(‰o”@+[ DÇA¿An-yäWÑÆúˆ�óŒ?ÿM¬óY_ù¬üò…S¯ Ky¢}�¨Ô{ k< ùçwD¥¾X›Æ{�Q鯷}–�~Ññzkág’±¼Çct[2Sþ�Q¯ŸkDznb@è[M.n­*,ñѯº2lÜV�Ȩ}¸µêÐ1Ïû8Þ¼aÜ8}�á œM~!ä¹Ë% —»Lò%Äñ�Èü¦ =ÙÊሉ~x”¤ÿME/7yoÇû.[-RúsòqÞz1*ñóG=¸{R*7scöÇ{Þ/.gu@BÇ}*‰ý¯ÓZ‹¸mß0e¥{[‡ä‚‡ztܾ³ÿóvÑ(-ÕÓ®Æ$¿èì·§t�$·»]`c¢Y¢Uw¤ã¨m?<•YŒÈA÷€ „bxNíDè ùÅÏ>ùøÞ†Ú3Œt�ñ$do\3ß°“Ì|¬”–¹éƒ-zit! >éöâ>KYRò‹ )–è²Ò´ès¹€æ:bÇíÓ¼ÄÌÃÀà˜ œpÊDÿ†|‡5t÷UЯ‘¹%öÔPôÈ•"�±Ø,Yy ËÐu«ž®!{=Ÿ³Ä ØrÌ‹3¤´ê„k¬“²,d D„cü¸}ØÎ…�;6Ì×Gfª,�0L¥‡D $Ï¡š'á^ØþòÓ{äT¤ƒ$r¸øË=ò|ÄHóîhM™T]×Ö©d �B’)ž ‘—–I#­Su·×»¸¸èªtÄ“7+]!‡=Exà —O»Ýýî쀟òÁ]™î*Ë\çj pòÿè2=“ €€¶uín9‡xœí]A“Û8v¾ëW ÚÚ­±Ó’ºÛöÎŒÝÝ)OÛž±g2ëŒ=v¥\Ù.ˆ„$L“ €jkj³‡=嚪TrÍ)·©Ýl¥vsóS•á_’÷�¢(¶ì‘ˆ–Z+—˦HxxïÃÃ{àÑß<øÕéó|ú�Œt�´ZGø?‰h2ÞôÙàöÇ%‰.YïëŒÊsWi¿øÉ/o ê*åÀõ7Pöä¸ýØþ*j²Äè"Zë^O%oƒ|Q~º 'Èo\ú~¹OE«óݳ29ê™apÔáÄŒ Mû#AD•:n'tܧ’Øÿ:Z¤mÛš)(]Ë:$¼í;û?wà6-UÒášÅ$¿èì·]!øSPè íúuRÂ19è�PJÕÁ„ž�_üìà“�ï-lè Ôд±ûO¾a&Y0¬²TØv­§Ã¹!”“ã¶äðvaŸA–”ü¢BJ­,ËæÄ_~Hƒ€)uÎ&Çí§íÄ ™šíÁoÈuXCˆB�09]âU y�\)bA^.q’×° ]·êéš:5ô|Î&AÁÍ“SbÙãö‰©e†®V�ØáBæ8,àÚù8'>Çå5/$MS&Ûe„•Ëáèk)°1åÉLA;ܳœæ!LP¨?; ?;AE‹G£ƒ… ·ŽÒ™ñ¥²g#eÔ{‡^PɪsD`æœ?T—|c& h@²Vi^‰&XLq…ãØ¼sG’Ï+ Õ„��iHû<âzÒ’CQ¶ªý 2Ö=ê¥@l¹ë!WiD'�TD<˜˜îž<°7ÉSsºxhºøf®¼q˜°$uEbFEÃA˜ùè²³š€¸‘g�IŸÂÔÇÞ¤Ôô�\@GZzD5áq*¡¤*÷£KÁŒÈÞÐ8�Ø]K4Tï„«8ÞFR#~d"de„h)õè&BKh4¢^9R@@^:Ð>yu>¼ßT¿þ¨sx㟎zøü䨇5žÇ�‹"«5òu¥jìÒQÈo®¿>ôÞ‹'WЋ�:7¼wä)½¼'½,2`‰C�涇V#DèA 7Àœc�L±2ôq|€¡iÞÀrLÂ]¿>8œ“ �In²"—êªýÞY¹Ö¯ßýóïâJÍ7šÅR‰t2ÿôo/tk¾Ï�ÁîŽçtøêåÍQ=©+UýD6ªÔlìË7t°¨``1 }�Õò¡™†VL}Ѥپ¼úLg>@_Wï\íä�3°ä;�SkÓÝ㉗ÞÍW»¸s`°È™Îåê±lîÐH BÇ‚‡Æ• °J‹ÁÐs' ðÁÍ”?õš­±Ã^g| ¾8˜7ýL� ùM‹.¹·âìg  V]‰F÷Ìrà.jk°—@Õ…�è–òuÆö€dm®Ôà“ »ÁkD³ L»¢9EÐÊ‚Õóì9‘¡©‡ƒl/®K†bK»˜Ò{å˜D1ÉC3x[šyÉŒ’‚¹(Áf„êG&ÛV#j$$Ö2$$uæ¡›û6Óql¬6(‹t¢Ñ î«Cfª6¯§BqS ©YÚb:¢1fóc"bžP`­™#MÌ£dòù�"Oßýö¿Pòö¿'ï~û?oÿP К«ú•5}©¹Ë§šÞå�žT©›€=gÃW¬yãoqSßåÐø.äk‘;úΖœÌ¶ Ã,™ÈÖÕ>yÆLàJ‘w?üGîž8’ªðc"úZ+± ©¼œ!SògUbÖGº-õ…(hC6~1õÐ N£Ë ÿ(~ûß áö§US*d l½q—œ3–¢µ(Â,€Qfz£ø0�¡\Œ½½–ÊPÕ®ˆÌó!âòíïá_U3 ºÍNc�$5xZÌ¡žºQÕȱñk4LI¨®ÊÚÄÌ+¨ŽX ­tM"F•Fm4UMy{¤Q..5¸Õ"¦çÓëóô»S@ÚºÛYƒ®E“{$Ébð9ógÆlpbvv%8@i2d¡Sì—(�|Þè·Ýi�ûùdbB…ÚxÏÌcã×TJ¤I…c1yÀ Û²�L‚(3 $XŠfÚЯ¬ˆ¹€1‘$�g�í݆Ĩ¨³²Ø[M‹�€­ÀùJ�«Q 5Zá@Ýh…`27Z{Ñhu›e_ŸÊFë£:nƒ©â�Ò÷\Èf;Ç_ ­p”6ZÝùˆÃç†jµÕêœhV3‹ Š¾ºÐ©ÑŸÞÂ%—O¡5Š»áXä¨!¼’~�¨×N=œ‹]E§ªê·áNÕÄk®¢WssÞeFœ³’ì*  šø¹Q‡–\—<œ÷õÁƒáQ”ÇbÐîm¡Ýë"›¡œð«à5Lèüb¨ï]þøÕùÐïŠAIöKPçy9cj[‚¶  ¯ƒXû¹• Ö>˜úaÈP) ¸‰0õY@3›q2±Aº”J°Æy 4ƒáÝR0O `†F=�µ9\vÉ·ðZ}Ê!Ϻ]Î7ÅÅÉ–­:‹0>”VÔ7X¢ahâOýwmvŒ�,ŽÉÎÆ¯D’0Ž(�,ðÁ׳±£¨ Ù6ˆQ%;Pì²M)¸qàÏÄ8ÛØ–p©tK¤ Ï$|÷ÿÙÛ™ÕG˜«¡?à˜±`�-ì� �žóH %�Í„Ž-ç�a<1' \ž¼œç�Ä~wßþ9x¥—\ÿè–FíO{÷ðÖíÃîǯªc¾¬ŽW³lïtïÜ>üx�RÎÙüÞ¡óbXª”rP±"³ZW2ã§Â_#t•‡¨YÕCà IŽÀV1j깭̾vAG&FŽ8v#É`.!fP«,VÄ�\¢hÌÊ‘R˜QÀ%ä œº6‹Q7M(hîg"#‘É2.ñ·ºW° Ï"q1-ˆ!ùòë­˜'™få ì¨B�‰˜,ª*•Q ØUϦê¦åVQM¬‡$v•c˜8äÅ ®¤›ŠÊúlDÇ\È[·spy˜o€áþ¦�6J‹�•>L¤�×­R¶�{­ˆ)Aå®"Û "‹0 qneョI÷™lÍ,y‘lr§K0�´˜‚Ê]C”Ç&¨•³ ˆê :mq»í�ÄXÎ^ia EÜŒ�“Õ,EbPî¸ÐkC3È–Õ…T ðù]•ªu˜„©òiOÝ~ðJ-§›÷»Ÿ| ^ÅK¾ð*YúÍ…ÒXmF€.u?ý¶@,oÿ¸ùrÙ:Áä–È"ÉÄW!˜xUÁ,Yfé7ÓªõÕ‚¹Ü‚jD0%©4¯ ‹Éæ:¶GVOhº¼µÐ3÷ýòqSØxGã"—Å'‡¾;öÕš:ö•ïŽy4ðvÌóŒu0ŸšzU={zyì¹ÏDÇ¥ÈA—GÄcî’ÆÊžèc�YCgÆÍq [ÏwlM´ˆøH¡Ti;ÏÀÊÝr m™`‘‹qå¼i™ìöbQØxµ=çšöœûiœe!Á�¡rbI4n¶Ùoå|èÖ\˜K•B®&/c% ”£~¹x�ª—‡+- II›4¶lèøxœí]Í–Û¶ÞÏS ìIW¡43mÒ$•ÔãŒ=±“´Ic'>]é@ä•pP²r²È¦oÐUß »œöt“åtÙsúy’üÉ�¯I±œÍ€ \|÷ÃÅß8ùÅý/ΞüùË$21ŸMÜ©XM=þ×�=RCý@ ÂÌ•”fê�FcovDÈ$º€ Æ`( "ª4Ø©Yúxd¼ûRЦޚÁ&‘Êx¤ÈsêmXh¢ik€Ÿ=¼K˜`†Qîë€r˜žŒŽ]fwÏ')—É0Ãaöqʸñ™ _Û„š,¶äO)öÝv2ÎSä©9DŸzÚl9èÀm¶‰ÅÀs3´öH¤`™Á3׆Œ“í*¶²é‘}ýûõôx¹€åo~»ƒLÍ|/Sª.ŠLÇ‹ÓÞÿõò¦L™á¹ÍÏÕdê=ÊŸªÜV ²#§õ×ÉTýêeñrL'㌓… ·; ]p §ZO=A× ªHþÏ72ñòÒ²„ª(Ù„$W¢÷Þñ;EMw2ñ™�˜”ÿØ+Ù¿J‚:¯×ìqž©T9��P©ÓŠERŠÉ˜…�MXq#$”³•˜zŠ­"[ù[¥²PåR•ÿdGª¹tà/­®ØÜw“Š:/R‘\c»)feº’<ûû޼�\§7˵σäù(Êo‡h}[Ë.o–å²'×Ñο aPeÀqĆó![——JºÆû†—E“”·ƒÃ^:GE�(éêS&öæÜÓ�#ÍB›¼0~êŒ�¿Øú—…1°?œD'·Z ûúh’ÌÎ$OcAb Ó•þh2Nl|ÊK‘4‹.?Îf6ý$�!ìÖË0® ·êr€ išSc2Ñ eÒDÙ˜3*,•¬i›ŒÝ»y9‰³–ÅÛÉØ•5ûˆp)V¤¬,q•ÍŒêÈÉ:[¹îñ6^HþbÙ‰b1UÛ¼T�%Á,÷Dl˦ô‹‚9&'\Ë·Å›y!ž¿Ø•sœÚîr�'Õ‹ô²Áµ54¾5Ú ”噑>õ mŠ4à,¬HW¤$_)ÉIvRT¬¡Ì—)ؾ“1_ c™ ãË¥oá7%õ²HòÅ’<´‘Ëê°LÙ ‹Žæ¶<S>wý$*áLÚ.ãnÔ÷Ý ¶Ì�ŠfÝ®Ç]�€®9>“)GEîÓ.áÖå.—jÌ<’©Â¬áÅÓ¨K6G<;Ý 1k†�?JÿªÓ…6TðR'û¸|3ô´5”K\#¿8ùí.×Ð’\68°©†:h PÙDƒ.™üÆúÌÈÒ�â"Ñ.!×ã´Û€ùRJÔ ÂÒ\ý£K6F½?&ÔÑݯqºao ·_ÄÝB±i¢Ø1ügaÌ�Gs¬[6N@Æ9Ãgaßi¸¥ u†¹ Ûð�gMhÀvg®g×1ãÎPŒ*Üõ‹óƒ¡–¡|kXà—Ûbʤ܈Vg´å`DÎQÔ9KƒTs»ù>\¦lMyîŽâxæöóɃ*v Y�“Ù¼*¯„eÀíƒbAA¯ÅãÀ«:+eq¸£Ø{]Â6·c*S;‘_`Öí¬KÀ5Ç8Řûïß»[sO1�jÿ»\s|[KŽÚm~s(½¦µ*‡þ²‡¡Ç¬¡’|ô!6¯ ebaíaQeÀ<§#ºÇÖƒž: ^Gõ¦Òÿ7^GoÜ/,¥ªÖÏ]xèj(DÀƸóQx*ÿã¡ðIÁe "(‡çåóÀ«:Ý%(ó-¦æ¢æÞš¡W`Çg©#å<5�™H j©Ôimƒ ”qžZÏBÕP +m”D�ûþû/½4íÔ'dìX�¾B;up½I/OᲿ„ÖˆªK°5HºT¹[¡P¡ÃÝžj�rØÈ!çß鸻\›Û"º`cÌËð³C@)POpT­–é·Šj–xËÓ$êáŸël ^:�~L±K¸5¸fd“»I6~¢[6G¼ÄÝÌŒz‡DÒÏ*”Dí\q�‹¶Ç7üƒ°‡²,çüdªý%OŸ—«sE9ÏöÙ‡Eºþ 1 êù¡ø¾TübîÒs}}¶"Ù£òÅÀ´ª ¨�£Þ!Š-‹éJ€;v½cËþPÄ ¶¬®‚6°Ô9èÓ–}êñË2eלíñŒÜ,Zm…иöìÉÁÐMëŠ]Zdª¡jÜvßÜA‰¾ãש ¿oªV¸.+AO÷¬BÊ‘¨ÜïÔÕ‘�1n¥(îŽÈªS;}�ú¡N Q÷_Û;¡ˆmà>ë©�sG;±)wÑOÎ9g†9rïð6ÊhñR“4;ã‚W5ÙÏcz‰w;¾S'¼,’Ê`·'Ó©ÖÚÜ]:6ÔÆª{ÚÅZÜp�;”à §|*VùÇ)£ÓÙ—.†Üs1ÃÊH�•àû¶ýô=êuÀyZr&W¾oÛOßÿ¿Û¼.�×G`¥•}W?`ænå·Èÿ†Ï¸þço­-ž„Œâ.ŸôuN³@É·Ò®¯þEQ½VÓ[²Çu¼t÷ô¿c\Ûc!~F¾¦½WР¢-_ÛŒ6ÙHîäuÙ=¹eÓøçN6äT9Ípáa‚QC!‘T’><µGI—cc¦Ì]™ˆêss(ó~Z§ªšô�Cƒ¬3Û3±ÔI„|û¼-¥—-r�{ 9ûV�_îšËå<¤¸WlÅñÃ~n&T#ÓýËN9”4xºÈmzéì^J}‰} :Ñ�:£ÕýŒT¨&ê rþ ŽJò)ºÙõ3ÿ*�Ü̇ïݸ¥%gáÞN×c3ìtÝasð×Ôô¡Ø.�„%³\xàT …T_•Îèß6H:uÅJs®—÷:¤‹ÞnTñ·C¼¸mâ½¹Y3ni¨´kÙÃ`؆Iæ](eÀ}ª‘šëåÇ'×1¹j('wù˜À5KQ·o¯~@ý˜ãÕ�g·ø~ÈÛ^Z n{}üV¯’WW µ§.4·¤‘îAº«P¿ô}õãùmÊ»í¥…á¶×ç4ºUy¯®îxáø÷HÕg‡bÓY\sV¼–-À½ÑºŸ¾)Ø#õNM›œé`»(÷õöM|¼žúßm.0k¶Aͽ½{@ØyÑvþ,åÈK­AVH—@lð^: ê-@H»†`c4ÌÔ,¸ËÔ•Ò%&¡Q2aÈKA4+å@¦kà2¸¾ðé›âq˜BÔ™�Û'Ãöɰ}Ò!ã&Ý•¥¥iËÃVC% ªðù,»pW¸‹¼˜.5Ñ&�mŒ’¡?„ÈE´gä‚tÁ‚¹›•1ô¯!ñê9åàç�QnnN›aB€aˆ aÛDÄÿòU·ðk˜ƒØNËLt ¾¦éWM8PÇËkà sÿ£:Ý‚¯iâ\§[ø5M¿ê îé¡n�Ø4 ñ?|Ò-ü$!êB%römÒ.™³;ì"Ú¤Ýü:z¸%´K>ÜeüZ£^Zƒ2s�HÜUBÝSú-yÊÂy¨hŒmŸ–Ûq<:";“�­ËrT¹LÆ6v¶“n/bÿá5¿¯‚û­]Ðõ‚*’ÿóÒ{ù/²´ªøµ Ɇ…&šzï¿ãU…Ò�||‹_LÊ€ì]Ë)XN½ÑÈ& £G‘‰¹—_sx¦RDädtBœ.bûžæŸ ¡¥èÜJŽÌ.Yr²Ud¼Û¥RÀs©Ê€âí¢^É¥i¥pÅ2Âó\¾Ý¤†Sï¼HE¹d{)feº’<ûû޼�\§7˵‚×Èó ˆŒ´7ˆ“ýpO”£�¨9i tU…¡:�Üñ|ê�z%èîÔBö޽,w¹çÜÉm ¢¤¯Ð7KYüèW¿userguide/interface.html#window Window@userguide/interface.html#resultsResults@userguide/interface.html#editingEditing`userguide/interface.html#user-interface-settings.User Interface Settings:userguide/interface.html#helpHelpVuserguide/interface.html#keyboard-shortcuts$Keyboard Shortcuts8userguide/interface.html#id3EditingJuserguide/interface.html#session-tabsSession TabsTuserguide/interface.html#widgets-and-docks"Widgets and DocksDusergui2de/interface.html#scrollingScrollingRuserguide/interface.html#focus-navigation Focus Navigation8userguide/interface.html#id4Notation@userguide/interface.html#variousVariousDuserguide/session_json_schema.html&Session JSON SchemaRuserguide/session_json_schema.html#schema SchemaPuserguide/session_json_schema.html#notes Notes@userguide/theme_json_schema.html"Theme JSON SchemaNuserguide/theme_json_schema.html#schema SchemaLuserguide/theme_json_schema.html#notes Notesfuserguide/theme_json_schema.html#fictitious-example$Fictitious Example(reference/index.htmlReferenceNreference/index.html#built-in-functions$Built-in Functions(reference/basic.html(Basic Math Functions8reference/basic.html#generalGeneralNreference/basic.html#lists-and-matrices$Lists and Matricespreference/basic.html#trigonometric-inverse-trigonometricJTrigonometric & Inverse Trigonometricdreference/basic.html#hyperbolic-inverse-hyperbolic>Hyperbolic & Inverse Hyperbolic8reference/basic.html#specialSpecialHreference/basic.html#complex-numbersComplex Numbers8reference/basic.html#variousVarious,reference/integer.htmlLInteger & Bitwise Arithmetic FunctionsRreference/integer.html#bitwise-operations$Bitwise OperationsHreference/integer.html#numeral-basesNumeral Bases>reference/integer.html#roundingRoundingNreference/integer.html#integer-division Integer Division4reference/statistical.html*Statistical FunctionsDreference/statistical.html#generalGeneral`reference/statistical.html#binomial-distribution*Binomial Distributionlreference/statistical.html#hypergeometric-distribution6Hypergeometric Distribution^reference/statistical.html#poisson-distribution(Poisson Distribution,reference/ieee754.html$IEEE-754 Functions<reference/index.html#constantsConstants0reference/constants.htmlConstants4reference/index.html#units Units(reference/units.html4Units and CanonicalizationFreference/units.html#display-policyDisplay PolicyDreference/units.html#unit-notationUnit NotationFreference/units.html#authored-unitsAuthored UnitsFreference/units.html#composed-unitsComposed Units@reference/units.html#conversionsConversionsRreference/units.html#built-in-units-table(Built-in Units Table^reference/units.html#built-in-units-by-quantity4Built-in Units by QuantityDreference/units.html#absorbed-doseAbsorbed Dosepreference/units.html#activity-referred-to-a-radionuclideFActivity Referred To A RadionuclideFreference/units.html#amount-of-heatAmount Of HeatPreference/units.html#amount-of-substance&Amount Of Substance2reference/units.html#areaArea@reference/units.html#capacitanceCapacitanceNreference/units.html#catalytic-activity$Catalytic ActivityHreference/units.html#dose-equivalentDose Equivalent:reference/units.html#electricElectric6reference/units.html#energy Energy4reference/units.html#force Force<reference/units.html#frequencyFrequency@reference/units.html#illuminanceIlluminance>reference/units.html#inductanceInductance@reference/units.html#informationInformation4reference/units.html#kerma Kerma6reference/units.html#length LengthDreference/units.html#luminous-fluxLuminous FluxNreference/units.html#luminous-intensity$Luminous IntensityDreference/units.html#magnetic-fluxMagnetic FluxTreference/units.html#magnetic-flux-density*Magnetic Flux Density2reference/units.html#massMass@reference/units.html#plane-anglePlane Angle4reference/units.html#power Power:reference/units.html#pressurePressureBreference/units.html#radiant-fluxRadiant Flux@reference/units.html#solid-angleSolid Angle4reference/units.html#speed Speed6reference/units.html#stress Stress@reference/units.html#temperatureTemperature2reference/units.html#timeTime:reference/units.html#velocityVelocity6reference/units.html#volume Volume2reference/units.html#workWork*sc-functionindex.htmlFunction Index G—ÔŸs> ÔŸg2 ý Å ™ ^ å ª u F  ë ³ „ U # ñ Å – j 8 Ú ¨ | A ݱ…Y5Ú¨|M!é±PòºSã¥j/ Ü�-Ëc±Uù—`GQI =ieee754_half_residual() (function)function.ieee754_half_residualsc.ieee754_half_residualZFME 9ieee754_half_encode() (function)function.ieee754_half_encodesc.ieee754_half_encodeZEME 9ieee754_half_decode() (function)function.ieee754_half_decodesc.ieee754_half_decodecDSK ?ieee754_float_residual() (function)function.ieee754_float_residualsc.ieee754_float_residualKCC; /ieee754_encode() (function)function.ieee754_encodesc.ieee754_encodefBUM Aieee754_double_residual() (function)function.ieee754_double_residualsc.ieee754_double_residual`AQI =ieee754_double_encode() (function)function.ieee754_double_encodesc.ieee754_double_encode`@QI =ieee754_double_decode() (function)function.ieee754_double_decodesc.ieee754_double_decodeK?C; /ieee754_decode() (function)function.ieee754_decodesc.ieee754_decode->/' idiv() (function)function.idivsc.idiv"=%! i (constant)constant.isc.i9<7/ #hypervar() (function)function.hypervarsc.hypervar9;7/ #hyperpmf() (function)function.hyperpmfsc.hyperpmf<:91 %hypermean() (function)function.hypermeansc.hypermean997/ #hypercdf() (function)function.hypercdfsc.hypercdf383+ hexpad() (function)function.hexpadsc.hexpad*7-% hex() (function)function.hexsc.hex967/ #gradians() (function)function.gradianssc.gradians655- !geomean() (function)function.geomeansc.geomean*4-% gcd() (function)function.gcdsc.gcd031) gamma() (function)function.gammasc.gamma-2/' frac() (function)function.fracsc.frac011) floor() (function)function.floorsc.floor605- !flatten() (function)function.flattensc.flatten6/5- !expform() (function)function.expformsc.expform*.-% exp() (function)function.expsc.exp--/' erfc() (function)function.erfcsc.erfc*,-% erf() (function)function.erfsc.erf0+1) epoch() (function)function.epochsc.epoch**-% eng() (function)function.engsc.eng-)/' emod() (function)function.emodsc.emod"(%! e (constant)constant.esc.e*'-% dot() (function)function.dotsc.dot*&-% dms() (function)function.dmssc.dms*%-% det() (function)function.detsc.det6$5- !degrees() (function)function.degreessc.degrees*#-% dec() (function)function.decsc.dec9"7/ #datetime() (function)function.datetimesc.datetime*!-% csc() (function)function.cscsc.csc0 1) cross() (function)function.crosssc.cross-/' covs() (function)function.covssc.covs-/' covp() (function)function.covpsc.covp01) count() (function)function.countsc.count*-% cot() (function)function.cotsc.cot-/' cosh() (function)function.coshsc.cosh*-% cos() (function)function.cossc.cos01) corrs() (function)function.corrssc.corrs01) corrp() (function)function.corrpsc.corrp-/' conj() (function)function.conjsc.conj-/' cols() (function)function.colssc.cols65- !cisform() (function)function.cisformsc.cisform*-% cis() (function)function.cissc.cis-/' ceil() (function)function.ceilsc.ceil-/' cbrt() (function)function.cbrtsc.cbrt33+ binpad() (function)function.binpadsc.binpad97/ #binomvar() (function)function.binomvarsc.binomvar97/ #binompmf() (function)function.binompmfsc.binompmf<91 %binommean() (function)function.binommeansc.binommean9 7/ #binomcdf() (function)function.binomcdfsc.binomcdf* -% bin() (function)function.binsc.bin6 5- !average() (function)function.averagesc.average3 3+ artanh() (function)function.artanhsc.artanh3 3+ arsinh() (function)function.arsinhsc.arsinh65- !arctan2() (function)function.arctan2sc.arctan233+ arctan() (function)function.arctansc.arctan33+ arcsin() (function)function.arcsinsc.arcsin33+ arcosh() (function)function.arcoshsc.arcosh33+ arccos() (function)function.arccossc.arccos*-% and() (function)function.andsc.and33+ absdev() (function)function.absdevsc.absdev*-% abs() (function)function.abssc.abs H³¤Hæ‡+ Ò y  µ † Z . Þ µ } Q  ð Ä • f : Ö ª ~ C ß°„X#÷™g&ÿÊ’](í¸€HᲆTê¯L ݰƒV#öÉœlOé³3�3+ stdevs() (function)function.stdevssc.stdevs3�3+ stdevp() (function)function.stdevpsc.stdevp-� /' sqrt() (function)function.sqrtsc.sqrt� # SpeedCrunchindex-0-� /' sinh() (function)function.sinhsc.sinh*� -% sin() (function)function.sinsc.sin*� -% shr() (function)function.shrsc.shr*�-% shl() (function)function.shlsc.shl0�1) shape() (function)function.shapesc.shape*�-% sgn() (function)function.sgnsc.sgn*�-% sec() (function)function.secsc.sec*�-% sci() (function)function.scisc.sci-�/' rows() (function)function.rowssc.rows<�91 %roundeven() (function)function.roundevensc.roundeven0�1) round() (function)function.roundsc.round-�/' root() (function)function.rootsc.root97/ #rectform() (function)function.rectformsc.rectform-~/' real() (function)function.realsc.real9}7/ #rational() (function)function.rationalsc.rational0|1) ratio() (function)function.ratiosc.ratio*{-% rat() (function)function.ratsc.rat-z/' rank() (function)function.ranksc.rank6y5- !randint() (function)function.randintsc.randint-x/' rand() (function)function.randsc.rand6w5- !radians() (function)function.radianssc.radians6v5- !product() (function)function.productsc.product3u3+ powmod() (function)function.powmodsc.powmod9t7/ #popcount() (function)function.popcountsc.popcount3s3+ poivar() (function)function.poivarsc.poivar3r3+ poipmf() (function)function.poipmfsc.poipmf6q5- !poimean() (function)function.poimeansc.poimean3p3+ poicdf() (function)function.poicdfsc.poicdf%o'# pi (constant)constant.pisc.pi?n;3 'phasorform() (function)function.phasorformsc.phasorform0m1) phase() (function)function.phasesc.phase'l+# or() (function)function.orsc.or3k3+ octpad() (function)function.octpadsc.octpad*j-% oct() (function)function.octsc.oct3i3+ numval() (function)function.numvalsc.numval*h-% npr() (function)function.nprsc.npr*g-% not() (function)function.notsc.not-f/' norm() (function)function.normsc.norm*e-% ncr() (function)function.ncrsc.ncr6d5- !molmass() (function)function.molmasssc.molmass9c7/ #molarity() (function)function.molaritysc.molarity*b-% mod() (function)function.modsc.mod*a-% min() (function)function.minsc.min3`3+ median() (function)function.mediansc.median-_/' mean() (function)function.meansc.mean*^-% max() (function)function.maxsc.max-]/' mass() (function)function.masssc.mass-\/' mask() (function)function.masksc.mask*[-% mad() (function)function.madsc.mad-Z/' log2() (function)function.log2sc.log20Y1) log10() (function)function.log10sc.log10*X-% log() (function)function.logsc.log6W5- !lngamma() (function)function.lngammasc.lngamma'V+# ln() (function)function.lnsc.ln*U-% lcm() (function)function.lcmsc.lcm"T%! j (constant)constant.jsc.j*S-% inv() (function)function.invsc.inv*R-% int() (function)function.intsc.int-Q/' imag() (function)function.imagsc.imag`PQI =ieee754_single_encode() (function)function.ieee754_single_encodesc.ieee754_single_encode`OQI =ieee754_single_decode() (function)function.ieee754_single_decodesc.ieee754_single_decodeWNKC 7ieee754_round_quad() (function)function.ieee754_round_quadsc.ieee754_round_quadWMKC 7ieee754_round_half() (function)function.ieee754_round_halfsc.ieee754_round_halfZLME 9ieee754_round_float() (function)function.ieee754_round_floatsc.ieee754_round_float]KOG ;ieee754_round_double() (function)function.ieee754_round_doublesc.ieee754_round_double`JQI =ieee754_quad_residual() (function)function.ieee754_quad_residualsc.ieee754_quad_residualZIME 9ieee754_quad_encode() (function)function.ieee754_quad_encodesc.ieee754_quad_encodeZHME 9ieee754_quad_decode() (function)function.ieee754_quad_decodesc.ieee754_quad_decode  Ó”g7ʼnV# í ½ � ` 8 (�)% ℯ (constant)constant.ℯsc.ℯ%�'# Ï€ (constant)constant.Ï€sc.Ï€*�-% xor() (function)function.xorsc.xor-�/' vars() (function)function.varssc.vars-�/' varp() (function)function.varpsc.varp3�3+ unmask() (function)function.unmasksc.unmask0�1) turns() (function)function.turnssc.turns0�1) trunc() (function)function.truncsc.trunc9�7/ #trigform() (function)function.trigformsc.trigform<�91 %transpose() (function)function.transposesc.transpose0�1) trace() (function)function.tracesc.trace-�/' tanh() (function)function.tanhsc.tanh*�-% tan() (function)function.tansc.tan<�91 %summation() (function)function.summationsc.summation*�-% sum() (function)function.sumsc.sumheldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/manual-en_US.qhc000066400000000000000000003500001526573132500300260ustar00rootroot00000000000000SQLite format 3@ --.•Ì ²¨†’$ º  w † ä h ó z ó H¾"¾fó| ¨b''�tableVersionFilterVersionFilterCREATE TABLE VersionFilter (Version TEXT, FilterId INTEGER)n++�tableComponentFilterComponentFilterCREATE TABLE ComponentFilter (ComponentName TEXT, FilterId INTEGER)u--�tableComponentMappingComponentMappingCREATE TABLE ComponentMapping (ComponentId INTEGER, NamespaceId INTEGER)q))�tableComponentTableComponentTableCREATE TABLE ComponentTable (ComponentId INTEGER PRIMARY KEY, Name TEXT)V�tableFilterFilterCREATE TABLE Filter (FilterId INTEGER PRIMARY KEY, Name TEXT)b%%�tableVersionTableVersionTableCREATE TABLE VersionTable (NamespaceId INTEGER, Version TEXT)�))�mtableTimeStampTableTimeStampTableCREATE TABLE TimeStampTable (NamespaceId INTEGER, FolderId INTEGER, FilePath TEXT, Size INTEGER, TimeStamp TEXT)�55�1tableOptimizedFilterTableOptimizedFilterTableCREATE TABLE OptimizedFilterTable (NamespaceId INTEGER, FilterAttributeId INTEGER)�(77�otableFileAttributeSetTableFileAttributeSetTableCREATE TABLE FileAttributeSetTable (NamespaceId INTEGER, FilterAttributeSetId INTEGER, FilterAttributeId INTEGER)� 33�/tableContentsFilterTableContentsFilterTableCREATE TABLE ContentsFilterTable (FilterAttributeId INTEGER, ContentsId INTEGER )w --�!tableIndexFilterTableIndexFilterTable CREATE TABLE IndexFilterTable (FilterAttributeId INTEGER, IndexId INTEGER)s ++�tableFileFilterTableFileFilterTable CREATE TABLE FileFilterTable (FilterAttributeId INTEGER, FileId INTEGER)z ''�3tableContentsTableContentsTable CREATE TABLE ContentsTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Data BLOB)� !!‚ tableIndexTableIndexTable CREATE TABLE IndexTable (Id INTEGER PRIMARY KEY, Name TEXT, Identifier TEXT, NamespaceId INTEGER, FileId INTEGER, Anchor TEXT)�''�MtableFileNameTableFileNameTable CREATE TABLE FileNameTable (FolderId INTEGER, Name TEXT, FileId INTEGER PRIMARY KEY, Title TEXT)e''� tableSettingsTableSettingsTableCREATE TABLE SettingsTable (Key TEXT PRIMARY KEY, Value BLOB )9M'indexsqlite_autoindex_SettingsTable_1SettingsTableh##�tableFilterTableFilterTableCREATE TABLE FilterTable (NameId INTEGER, FilterAttributeId INTEGER )l++�tableFilterNameTableFilterNameTableCREATE TABLE FilterNameTable (Id INTEGER PRIMARY KEY, Name TEXT ){55�tableFilterAttributeTableFilterAttributeTableCREATE TABLE FilterAttributeTable (Id INTEGER PRIMARY KEY, Name TEXT )u##�1tableFolderTableFolderTableCREATE TABLE FolderTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Name TEXT )x))�+tableNamespaceTableNamespaceTableCREATE TABLE NamespaceTable (Id INTEGER PRIMARY KEY, Name TEXT, FilePath TEXT ) ÐÐ.A-org.sphinx.manual-enus.1.1manual-en_US.qch ÷÷ doc çïç1.1%manual-en_US ìì+SpeedCrunch 1.1 õûõ  hÔ§^ûßÀ«˜ƒh 9FullTextSearchFallback %CreationTimej×[  ) HideAddressBar- EnableAddressBarA EnableDocumentationManager; HideFilterFunctionality? EnableFilterFunctionalityC)qLastShownPagesqthelp://org.sphinx.manual-enus.1.1/doc/index.htmlG+wdefaultHomepageqthelp://org.sphinx.manual-enus.1.1/doc/contents.html+#GWindowTitleSpeedCrunch 1.1 documentation*-;LastRegisterTime2026-10-20T13:14:01.975 #G\—4{ìµÜÈ9FullTextSearchFallback %CreationTime )HideAddressBar -EnableAddressBarAEnableDocumentationManager;HideFilterFunctionality?EnableFilterFunctionality)LastShownPages+defaultHomepage#WindowTitle- LastRegisterTime  ŽÛžtS4ôͬc7 ä · { Y ! ò Ê › w 4 þ É Ž9 AAreference/units_table.htmlBuilt-in Units by Quantity3 5Areference/units.htmlUnits and Canonicalization4 A7reference/statistical.htmlStatistical FunctionsA 9Yreference/integer.htmlInteger & Bitwise Arithmetic Functions" 5reference/index.htmlReference- 91reference/ieee754.htmlIEEE-754 Functions& =reference/constants.htmlConstants- 55reference/basic.htmlBasic Math Functions6 M/userguide/theme_json_schema.htmlTheme JSON Schema  7userguide/syntax.htmlSyntax: Q3userguide/session_json_schema.htmlSession JSON Schema+ =)userguide/interface.htmlUser Interface, C%userguide/installation.htmlInstallation#  5!userguide/index.htmlUser Guide*  A#userguide/first_steps.htmlFirst StepsG  ;cuserguide/advanced.htmlUser-Defined Variables, Functions and Units  /_static/quark.cssquark.css%  5%_static/pygments.csspygments.css -_static/plus.pngplus.png /_static/minus.pngminus.png -_static/file.pngfile.png /_static/basic.cssbasic.css( 7)sc-functionindex.htmlFunction Index" /%introduction.htmlIntroduction 'genindex.htmlIndex# '/contents.htmlTable of Contentsõûõ ÔŸg2 ý Å ™ ^ å ª u F  ë ³ „ U # ñ Å – j 8 Ú ¨ | A ݱ…Y5Ú¨|M!é±PòºSã¥j/ Ü�-Ëc±Uù—`GQI =ieee754_half_residual() (function)function.ieee754_half_residualsc.ieee754_half_residualZFME 9ieee754_half_encode() (function)function.ieee754_half_encodesc.ieee754_half_encodeZEME 9ieee754_half_decode() (function)function.ieee754_half_decodesc.ieee754_half_decodecDSK ?ieee754_float_residual() (function)function.ieee754_float_residualsc.ieee754_float_residualKCC; /ieee754_encode() (function)function.ieee754_encodesc.ieee754_encodefBUM Aieee754_double_residual() (function)function.ieee754_double_residualsc.ieee754_double_residual`AQI =ieee754_double_encode() (function)function.ieee754_double_encodesc.ieee754_double_encode`@QI =ieee754_double_decode() (function)function.ieee754_double_decodesc.ieee754_double_decodeK?C; /ieee754_decode() (function)function.ieee754_decodesc.ieee754_decode->/' idiv() (function)function.idivsc.idiv"=%! i (constant)constant.isc.i9<7/ #hypervar() (function)function.hypervarsc.hypervar9;7/ #hyperpmf() (function)function.hyperpmfsc.hyperpmf<:91 %hypermean() (function)function.hypermeansc.hypermean997/ #hypercdf() (function)function.hypercdfsc.hypercdf383+ hexpad() (function)function.hexpadsc.hexpad*7-% hex() (function)function.hexsc.hex967/ #gradians() (function)function.gradianssc.gradians655- !geomean() (function)function.geomeansc.geomean*4-% gcd() (function)function.gcdsc.gcd031) gamma() (function)function.gammasc.gamma-2/' frac() (function)function.fracsc.frac011) floor() (function)function.floorsc.floor605- !flatten() (function)function.flattensc.flatten6/5- !expform() (function)function.expformsc.expform*.-% exp() (function)function.expsc.exp--/' erfc() (function)function.erfcsc.erfc*,-% erf() (function)function.erfsc.erf0+1) epoch() (function)function.epochsc.epoch**-% eng() (function)function.engsc.eng-)/' emod() (function)function.emodsc.emod"(%! e (constant)constant.esc.e*'-% dot() (function)function.dotsc.dot*&-% dms() (function)function.dmssc.dms*%-% det() (function)function.detsc.det6$5- !degrees() (function)function.degreessc.degrees*#-% dec() (function)function.decsc.dec9"7/ #datetime() (function)function.datetimesc.datetime*!-% csc() (function)function.cscsc.csc0 1) cross() (function)function.crosssc.cross-/' covs() (function)function.covssc.covs-/' covp() (function)function.covpsc.covp01) count() (function)function.countsc.count*-% cot() (function)function.cotsc.cot-/' cosh() (function)function.coshsc.cosh*-% cos() (function)function.cossc.cos01) corrs() (function)function.corrssc.corrs01) corrp() (function)function.corrpsc.corrp-/' conj() (function)function.conjsc.conj-/' cols() (function)function.colssc.cols65- !cisform() (function)function.cisformsc.cisform*-% cis() (function)function.cissc.cis-/' ceil() (function)function.ceilsc.ceil-/' cbrt() (function)function.cbrtsc.cbrt33+ binpad() (function)function.binpadsc.binpad97/ #binomvar() (function)function.binomvarsc.binomvar97/ #binompmf() (function)function.binompmfsc.binompmf<91 %binommean() (function)function.binommeansc.binommean9 7/ #binomcdf() (function)function.binomcdfsc.binomcdf* -% bin() (function)function.binsc.bin6 5- !average() (function)function.averagesc.average3 3+ artanh() (function)function.artanhsc.artanh3 3+ arsinh() (function)function.arsinhsc.arsinh65- !arctan2() (function)function.arctan2sc.arctan233+ arctan() (function)function.arctansc.arctan33+ arcsin() (function)function.arcsinsc.arcsin33+ arcosh() (function)function.arcoshsc.arcosh33+ arccos() (function)function.arccossc.arccos*-% and() (function)function.andsc.and33+ absdev() (function)function.absdevsc.absdev*-% abs() (function)function�G ËËð" �àDcontents.html:SpeedCrunch 1.1 documentation"introduction.htmlIntroduction(userguide/index.htmlUser Guide6userguide/installation.htmlInstallationZuserguide/installation.html#microsoft-windows"Microsoft WindowsBuserguide/installation.html#macos macOSBuserguide/installation.html#linux Linuxbuserguide/installation.html#distribution-packages*Distribution PackagesFuserguide/installation.html#flatpakFlatpak`userguide/installation.html#building-from-source(Building from Source4userguide/first_steps.htmlFirst Steps*userguide/syntax.html SyntaxJuserguide/syntax.html#number-notationNumber NotationDuserguide/syntax.html#decimal-formDecimal Form^userguide/syntax.html#digit-grouping-separators2Digit Grouping SeparatorsRuserguide/syntax.html#scientific-notation&Scientific NotationNuserguide/syntax.html#non-decimal-bases"Non-Decimal BasesPuserguide/syntax.html#sexagesimal-values$Sexagesimal Values<userguide/syntax.html#commentsComments\userguide/syntax.html#    óúó  õûõ  ÍÍ1 -=manual-en_US.qchP2026-10-20T12:14:01.969Z ûû  øødoc ûû   G—ÔŸs> ÔŸg2 ý Å ™ ^ å ª u F  ë ³ „ U # ñ Å – j 8 Ú ¨ | A ݱ…Y5Ú¨|M!é±PòºSã¥j/ Ü�-Ëc±Uù—`GQI =ieee754_half_residual() (function)function.ieee754_half_residualsc.ieee754_half_residualZFME 9ieee754_half_encode() (function)function.ieee754_half_encodesc.ieee754_half_encodeZEME 9ieee754_half_decode() (function)function.ieee754_half_decodesc.ieee754_half_decodecDSK ?ieee754_float_residual() (function)function.ieee754_float_residualsc.ieee754_float_residualKCC; /ieee754_encode() (function)function.ieee754_encodesc.ieee754_encodefBUM Aieee754_double_residual() (function)function.ieee754_double_residualsc.ieee754_double_residual`AQI =ieee754_double_encode() (function)function.ieee754_double_encodesc.ieee754_double_encode`@QI =ieee754_double_decode() (function)function.ieee754_double_decodesc.ieee754_double_decodeK?C; /ieee754_decode() (function)function.ieee754_decodesc.ieee754_decode->/' idiv() (function)function.idivsc.idiv"=%! i (constant)constant.isc.i9<7/ #hypervar() (function)function.hypervarsc.hypervar9;7/ #hyperpmf() (function)function.hyperpmfsc.hyperpmf<:91 %hypermean() (function)function.hypermeansc.hypermean997/ #hypercdf() (function)function.hypercdfsc.hypercdf383+ hexpad() (function)function.hexpadsc.hexpad*7-% hex() (function)function.hexsc.hex967/ #gradians() (function)function.gradianssc.gradians655- !geomean() (function)function.geomeansc.geomean*4-% gcd() (function)function.gcdsc.gcd031) gamma() (function)function.gammasc.gamma-2/' frac() (function)function.fracsc.frac011) floor() (function)function.floorsc.floor605- !flatten() (function)function.flattensc.flatten6/5- !expform() (function)function.expformsc.expform*.-% exp() (function)function.expsc.exp--/' erfc() (function)function.erfcsc.erfc*,-% erf() (function)function.erfsc.erf0+1) epoch() (function)function.epochsc.epoch**-% eng() (function)function.engsc.eng-)/' emod() (function)function.emodsc.emod"(%! e (constant)constant.esc.e*'-% dot() (function)function.dotsc.dot*&-% dms() (function)function.dmssc.dms*%-% det() (function)function.detsc.det6$5- !degrees() (function)function.degreessc.degrees*#-% dec() (function)function.decsc.dec9"7/ #datetime() (function)function.datetimesc.datetime*!-% csc() (function)function.cscsc.csc0 1) cross() (function)function.crosssc.cross-/' covs() (function)function.covssc.covs-/' covp() (function)function.covpsc.covp01) count() (function)function.countsc.count*-% cot() (function)function.cotsc.cot-/' cosh() (function)function.coshsc.cosh*-% cos() (function)function.cossc.cos01) corrs() (function)function.corrssc.corrs01) corrp() (function)function.corrpsc.corrp-/' conj() (function)function.conjsc.conj-/' cols() (function)function.colssc.cols65- !cisform() (function)function.cisformsc.cisform*-% cis() (function)function.cissc.cis-/' ceil() (function)function.ceilsc.ceil-/' cbrt() (function)function.cbrtsc.cbrt33+ binpad() (function)function.binpadsc.binpad97/ #binomvar() (function)function.binomvarsc.binomvar97/ #binompmf() (function)function.binompmfsc.binompmf<91 %binommean() (function)function.binommeansc.binommean9 7/ #binomcdf() (function)function.binomcdfsc.binomcdf* -% bin() (function)function.binsc.bin6 5- !average() (function)function.averagesc.average3 3+ artanh() (function)function.artanhsc.artanh3 3+ arsinh() (function)function.arsinhsc.arsinh65- !arctan2() (function)function.arctan2sc.arctan233+ arctan() (function)function.arctansc.arctan33+ arcsin() (function)function.arcsinsc.arcsin33+ arcosh() (function)function.arcoshsc.arcosh33+ arccos() (function)function.arccossc.arccos*-% and() (function)function.andsc.and33+ absdev() (function)function.absdevsc.absdev*-% abs() (function)function.abssc.abs H³¤Hæ‡+ Ò y  µ † Z . Þ µ } Q  ð Ä • f : Ö ª ~ C ß°„X#÷™g&ÿÊ’](í¸€HᲆTê¯L ݰƒV#öÉœlOé³3�3+ stdevs() (function)function.stdevssc.stdevs3�3+ stdevp() (function)function.stdevpsc.stdevp-� /' sqrt() (function)function.sqrtsc.sqrt� # SpeedCrunchindex-0-� /' sinh() (function)function.sinhsc.sinh*� -% sin() (function)function.sinsc.sin*� -% shr() (function)function.shrsc.shr*�-% shl() (function)function.shlsc.shl0�1) shape() (function)function.shapesc.shape*�-% sgn() (function)function.sgnsc.sgn*�-% sec() (function)function.secsc.sec*�-% sci() (function)function.scisc.sci-�/' rows() (function)function.rowssc.rows<�91 %roundeven() (function)function.roundevensc.roundeven0�1) round() (function)function.roundsc.round-�/' root() (function)function.rootsc.root97/ #rectform() (function)function.rectformsc.rectform-~/' real() (function)function.realsc.real9}7/ #rational() (function)function.rationalsc.rational0|1) ratio() (function)function.ratiosc.ratio*{-% rat() (function)function.ratsc.rat-z/' rank() (function)function.ranksc.rank6y5- !randint() (function)function.randintsc.randint-x/' rand() (function)function.randsc.rand6w5- !radians() (function)function.radianssc.radians6v5- !product() (function)function.productsc.product3u3+ powmod() (function)function.powmodsc.powmod9t7/ #popcount() (function)function.popcountsc.popcount3s3+ poivar() (function)function.poivarsc.poivar3r3+ poipmf() (function)function.poipmfsc.poipmf6q5- !poimean() (function)function.poimeansc.poimean3p3+ poicdf() (function)function.poicdfsc.poicdf%o'# pi (constant)constant.pisc.pi?n;3 'phasorform() (function)function.phasorformsc.phasorform0m1) phase() (function)function.phasesc.phase'l+# or() (function)function.orsc.or3k3+ octpad() (function)function.octpadsc.octpad*j-% oct() (function)function.octsc.oct3i3+ numval() (function)function.numvalsc.numval*h-% npr() (function)function.nprsc.npr*g-% not() (function)function.notsc.not-f/' norm() (function)function.normsc.norm*e-% ncr() (function)function.ncrsc.ncr6d5- !molmass() (function)function.molmasssc.molmass9c7/ #molarity() (function)function.molaritysc.molarity*b-% mod() (function)function.modsc.mod*a-% min() (function)function.minsc.min3`3+ median() (function)function.mediansc.median-_/' mean() (function)function.meansc.mean*^-% max() (function)function.maxsc.max-]/' mass() (function)function.masssc.mass-\/' mask() (function)function.masksc.mask*[-% mad() (function)function.madsc.mad-Z/' log2() (function)function.log2sc.log20Y1) log10() (function)function.log10sc.log10*X-% log() (function)function.logsc.log6W5- !lngamma() (function)function.lngammasc.lngamma'V+# ln() (function)function.lnsc.ln*U-% lcm() (function)function.lcmsc.lcm"T%! j (constant)constant.jsc.j*S-% inv() (function)function.invsc.inv*R-% int() (function)function.intsc.int-Q/' imag() (function)function.imagsc.imag`PQI =ieee754_single_encode() (function)function.ieee754_single_encodesc.ieee754_single_encode`OQI =ieee754_single_decode() (function)function.ieee754_single_decodesc.ieee754_single_decodeWNKC 7ieee754_round_quad() (function)function.ieee754_round_quadsc.ieee754_round_quadWMKC 7ieee754_round_half() (function)function.ieee754_round_halfsc.ieee754_round_halfZLME 9ieee754_round_float() (function)function.ieee754_round_floatsc.ieee754_round_float]KOG ;ieee754_round_double() (function)function.ieee754_round_doublesc.ieee754_round_double`JQI =ieee754_quad_residual() (function)function.ieee754_quad_residualsc.ieee754_quad_residualZIME 9ieee754_quad_encode() (function)function.ieee754_quad_encodesc.ieee754_quad_encodeZHME 9ieee754_quad_decode() (function)function.ieee754_quad_decodesc.ieee754_quad_decode  Ó”g7ʼnV# í ½ � ` 8 (�)% ℯ (constant)constant.ℯsc.ℯ%�'# Ï€ (constant)constant.Ï€sc.Ï€*�-% xor() (function)function.xorsc.xor-�/' vars() (function)function.varssc.vars-�/' varp() (function)function.varpsc.varp3�3+ unmask() (function)function.unmasksc.unmask0�1) turns() (function)function.turnssc.turns0�1) trunc() (function)function.truncsc.trunc9�7/ #trigform() (function)function.trigformsc.trigform<�91 %transpose() (function)function.transposesc.transpose0�1) trace() (function)function.tracesc.trace-�/' tanh() (function)function.tanhsc.tanh*�-% tan() (function)function.tansc.tan<�91 %summation() (function)function.summationsc.summation*�-% sum() (function)function.sumsc.sumoperators-and-precedence0Operators and PrecedenceJuserguide/syntax.html#complex-numbersComplex Numbers.userguide/advanced.htmlVUser-Defined Variables, Functions and UnitsBuserguide/advanced.html#variablesVariablesLuserguide/advanced.html#user-functionsUser Functions:userguide/advanced.html#units Unitsduserguide/advanced.html#information-units-bit-byte8Information units (bit/byte)@userguide/advanced.html#prefixesPrefixesVuserguide/advanced.html#family-mixing-rules&Family mixing rulesZuserguide/advanced.html#result-unit-selection*Result unit selectionDuserguide/advanced.html#user-unitsUser Units0userguide/interface.htmlUser Interface@userguide/interface.html#widgetsWidgets^userguide/interface.html#session-tabs-and-panes,Session Tabs and PanesRuserguide/interface.html#private-sessions Private Sessionsfuserguide/interface.html#expression-editor-features4Expression Editor FeaturesLuserguide/interface.html#import-exportImport/ExportRuserguide/interface.html#user-definitions User DefinitionsBuserguide/interface.html#settingsSettingsVuserguide/interface.html#resetting-settings$Resetting Settingshuserguide/interface.html#result-display-interactions6Result Display InteractionsBuserguide/interface.html#notationNotationFuserguide/interface.html#angle-modeAngle ModePuserguide/interface.html#complex-numbersComplex NumbersLuserguide/interface.html#number-formatNumber FormatVuserguide/interface.html#history-size-limit$History Size Limit>userguide/interface.html#window Window@userguide/interface.html#resultsResults@userguide/interface.html#editingEditing`userguide/interface.html#user-interface-settings.User Interface Settings:userguide/interface.html#helpHelpVuserguide/interface.html#keyboard-shortcuts$Keyboard Shortcuts8userguide/interface.html#id3EditingJuserguide/interface.html#session-tabsSession TabsTuserguide/interface.html#widgets-and-docks"Widgets and DocksDuserguide/interface.html#scrollingScrollingRuserguide/interface.html#focus-navigation Focus Navigation8userguide/interface.html#id4Notation@userguide/interface.html#variousVariousDuserguide/session_json_schema.html&Session JSON SchemaRuserguide/session_json_schema.html#schema SchemaPuserguide/session_json_schema.html#notes Notes@userguide/theme_json_schema.html"Theme JSON SchemaNuserguide/theme_json_schema.html#schema SchemaLuserguide/theme_json_schema.html#notes Notesfuserguide/theme_json_schema.html#fictitious-example$Fictitious Example(reference/index.htmlReferenceNreference/index.html#built-in-functions$Built-in Functions(reference/basic.html(Basic Math Functions8reference/basic.html#generalGeneralNreference/basic.html#lists-and-matrices$Lists and Matricespreference/basic.html#trigonometric-inverse-trigonometricJTrigonometric & Inverse Trigonometricdreference/basic.html#hyperbolic-inverse-hyperbolic>Hyperbolic & Inverse Hyperbolic8reference/basic.html#specialSpecialHreference/basic.html#complex-numbersComplex Numbers8reference/basic.html#variousVarious,reference/integer.htmlLInteger & Bitwise Arithmetic FunctionsRreference/integer.html#bitwise-operations$Bitwise OperationsHreference/integer.html#numeral-basesNumeral Bases>reference/integer.html#roundingRoundingNreference/integer.html#integer-division Integer Division4reference/statistical.html*Statistical FunctionsDreference/statistical.html#generalGeneral`reference/statistical.html#binomial-distribution*Binomial Distributionlreference/statistical.html#hypergeometric-distribution6Hypergeometric Distribution^reference/statistical.html#poisson-distribution(Poisson Distribution,reference/ieee754.html$IEEE-754 Functions<reference/index.html#constantsConstants0reference/constants.htmlConstants4reference/index.html#units Units(reference/units.html4Units and CanonicalizationFreference/units.html#display-policyDisplay PolicyDreference/units.html#unit-notationUnit NotationFreference/units.html#authored-unitsAuthored UnitsFreference/units.html#composed-unitsComposed Units@reference/units.html#conversionsConversionsRreference/units.html#built-in-units-table(Built-in Units Table^reference/units.html#built-in-units-by-quantity4Built-in Units by QuantityDreference/units.html#absorbed-doseAbsorbed Dosepreference/units.html#activity-referred-to-a-radionuclideFActivity Referred To A RadionuclideFreference/units.html#amount-of-heatAmount Of HeatPreference/units.html#amount-of-substance&Amount Of Substance2reference/units.html#areaArea@reference/units.html#capacitanceCapacitanceNreference/units.html#catalytic-activity$Catalytic ActivityHreference/units.html#dose-equivalentDose Equivalent:reference/units.html#electricElectric6reference/units.html#energy Energy4reference/units.html#force Force<reference/units.html#frequencyFrequency@reference/units.html#illuminanceIlluminance>reference/units.html#inductanceInductance@reference/units.html#informationInformation4reference/units.html#kerma Kerma6reference/units.html#length LengthDreference/units.html#luminous-fluxLuminous FluxNreference/units.html#luminous-intensity$Luminous IntensityDreference/units.html#magnetic-fluxMagnetic FluxTreference/units.html#magnetic-flux-density*Magnetic Flux Density2reference/units.html#massMass@reference/units.html#plane-anglePlane Angle4reference/units.html#power Power:reference/units.html#pressurePressureBreference/units.html#radiant-fluxRadiant Flux@reference/units.html#solid-angleSolid Angle4reference/units.html#speed Speed6reference/units.html#stress Stress@reference/units.html#temperatureTemperature2reference/units.html#timeTime:reference/units.html#velocityVelocity6reference/units.html#volume Volume2reference/units.html#workWork*sc-functionindex.htmlFunction Indexheldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/manual-en_US.qhcp000066400000000000000000000012031526573132500302040ustar00rootroot00000000000000 SpeedCrunch 1.1 documentation qthelp://org.sphinx.manual-enus.1.1/doc/contents.html qthelp://org.sphinx.manual-enus.1.1/doc/index.html manual-en_US.qhp manual-en_US.qch manual-en_US.qch heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/manual-en_US.qhp000066400000000000000000001022371526573132500300520ustar00rootroot00000000000000 org.sphinx.manual-enus.1.1 doc manual-en_US 1.1 manual-en_US 1.1
contents.html genindex.html introduction.html sc-functionindex.html _static/basic.css _static/file.png _static/minus.png _static/plus.png _static/pygments.css _static/quark.css userguide/advanced.html userguide/first_steps.html userguide/index.html userguide/installation.html userguide/interface.html userguide/session_json_schema.html userguide/syntax.html userguide/theme_json_schema.html reference/basic.html reference/constants.html reference/ieee754.html reference/index.html reference/integer.html reference/statistical.html reference/units.html reference/units_table.html heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/000077500000000000000000000000001526573132500270055ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/basic.html000066400000000000000000002607531526573132500307710ustar00rootroot00000000000000 Basic Math Functions

Basic Math Functions

General

abs(x)

Return the absolute value of x, commonly written as |x|. When given a real number, it returns a non-negative real value. When given a complex number, it returns the modulus of the number.

The argument can have a dimension.

Example:

abs(-3 meter)
= 3 meter

abs(4 + 3j)
= 5
sqrt(x)

Return the square root of x. Any complex number may be specified, yielding the complex root in the upper half plane.

Alias: √(x).

Added in version 1.0.

The argument may have a dimension.

cbrt(x)

Compute the third (cubic) root of x. Negative real numbers yield a negative real cubic root:

cbrt(-27)
= -3

This function accepts any complex input. The result will generally be the first complex root, i.e. the one with a phase between 0 and π/3. Real negative arguments however will still yield a real (negative) result. Use x^(1/3) to get the first complex root.

Alias: ∛(x).

Added in version 1.0.

root(n; x)

Return the nth root of x. Put the root index n first, followed by the value x, as with the base and value in log(). The index must be a positive, dimensionless integer.

For real inputs, return the real root whenever one exists. Negative real inputs with an odd index return a negative real root, as with cbrt(). Negative real inputs with an even index and non-real complex inputs return the principal complex root.

Example:

root(5; 32)
= 2

root(5; -32)
= -2

root(2; -16)
= 4i

The argument x may have a dimension. Its unit exponents are divided by n. For dimensioned inputs, n must not exceed 2147483647:

root(5; 32 [m^5])
= 2 metre

root(1; x) returns x unchanged. A zero, negative, fractional or complex index is rejected.

Unlike x^(1/n), this function keeps odd roots of negative real inputs real even when complex numbers are enabled.

See also

sqrt() (square root), cbrt() (cube root)

Added in version 1.1.

exp(x)

Compute the natural exponential function.

The argument must be dimensionless.

See also

ln() (natural logarithm)
ln(x)

Compute the natural logarithm.

Any non-zero number may be given. The result will be the principal value. The branch cut runs across the negative real axis. Nevertheless, in SpeedCrunch ln() is defined for negative real numbers as ln(-x) = ln(|x|)) + πj, extending the branch from the upper half-plane.

log2(x)

Compute the binary logarithm. The same complex-number rules apply as for ln().

log10(x)

Compute the decimal logarithm. The same complex-number rules apply as for ln().

log(n; x)

Compute the logarithm of base n. The same complex-number rules apply as for ln().

numval(x)

Return the numerical value of quantity x.

For unitless values, this returns the value unchanged. For quantities with units, it returns the numerical value in SI/base units by default.

If x includes an explicit conversion target (-> [unit]), it returns the numerical value in that target unit.

Example:

numval(3)
= 3

numval(3 [m/s])
= 3

numval(3 [km/s])
= 3000

numval(3 [km/s] -> [cm/s])
= 300000
datetime(unix_timestamp[; offset])

Added in version 1.0.

Convert a Unix timestamp (seconds since 1970-01-01 00:00:00 UTC) into a numeric date/time value formatted as YYYYMMDD.HHMMSS.

If offset is omitted, the timestamp is converted using the local system timezone. If offset is provided, it is interpreted as hours offset to GMT/UTC (fractional offsets are supported), and conversion is performed in UTC after applying that offset.

This function is the inverse of epoch() when using the same offset.

Example:

datetime(1514761200; 1)
= 20180101.000000

datetime(1551464695; -3.5)
= 20190301.145455
epoch(yyyymmdd.hhmmss[; offset])

Added in version 1.0.

Convert a numeric date/time value in YYYYMMDD.HHMMSS format to a Unix timestamp (seconds since 1970-01-01 00:00:00 UTC).

If offset is omitted, the value is interpreted in the local system timezone. If offset is provided, it is interpreted as hours offset to GMT/UTC (fractional offsets are supported).

This function is the inverse of datetime() when using the same offset.

Example:

epoch(20180101.000000; 1)
= 1514761200

epoch(20190301.145455; -3.5)
= 1551464695
molmass(formula)

Compute the molar mass of a chemical formula and return the result with dimension g/mol.

The formula argument is case-sensitive and supports either plain digits (for example C6H12O6) or subscript digits (for example C₆H�₂O₆). Parsing fails for invalid formulas.

Advanced chemical notation is not supported yet. For example, grouped or hydrated formulas such as K4[Fe(CN)6]·3H2O currently fail to parse.

The element table follows the official IUPAC CIAAW 2021 abridged standard atomic weights.

Example:

molmass(C6H12O6)
= 180.156 g/mol
mass(mol; formula)

Compute the mass of a substance amount and return the result with dimension g.

This function reuses molmass() internally and is equivalent to: mol * molmass(formula).

The formula argument follows the same parsing rules as molmass().

Example:

mass(1; C6H12O6)
= 180.156 g
molarity(n; V)

Compute molarity as amount of substance divided by solution volume and return the result with dimension mol/L.

This function is equivalent to: n / V.

If n or V is dimensionless, SpeedCrunch interprets them as mol and L, respectively.

Example:

molarity(0.50; 1.00)
= 0.5 mol/L

Lists and Matrices

Added in version 1.0.

Lists are written with braces and semicolon-separated elements. Matrices are written as a list of row lists. Only one-dimensional lists and two-dimensional matrices are supported:

mylist = {1; 2; 3; 4; 5}
mat = {{1; 2; 3}; {4; 5; 6}}

The function-style notation list(...) is also accepted on input, for example list(1; 2; 3) is equivalent to {1; 2; 3}.

List and matrix results use the same spacing, for example {1; 2; 3} and {{1; 2}; {3; 4}}.

List and matrix elements must be dimensionless. Units cannot be attached to individual elements or to a list or matrix as a whole.

Supported arithmetic operations are addition and subtraction between same-shaped lists or matrices, multiplication by a scalar on either side, division by a scalar on the right-hand side, and matrix multiplication for compatible matrices. In matrix multiplication, a list can be used as a row vector on the left when the right operand is a matrix. A list can also be used as a row vector on the right when the left operand is a one-column matrix. List-by-list multiplication is not supported. Matrix products with a single result element return that scalar directly. Scalar addition/subtraction, scalar divided by a list or matrix, elementwise multiplication, and elementwise division are not supported:

{1; 2; 3} + {4; 5; 6}
= {5; 7; 9}

2 * {{1; 2}; {3; 4}}
= {{2; 4}; {6; 8}}

{1; 2; 3} / 2
= {0.5; 1; 1.5}

{{1; 2}; {3; 4}} * {{5; 6}; {7; 8}}
= {{19; 22}; {43; 50}}

{1; 2; 3} * {{1}; {2}; {3}}
= 14

{{1}; {2}; {3}} * {4; 5; 6}
= {{4; 5; 6}; {8; 10; 12}; {12; 15; 18}}

The aggregation and statistics functions count(), sum(), min(), max(), average(), mean(), median(), varp(), vars(), stdevp(), and stdevs() accept a list or matrix as a single argument. Matrix inputs are flattened for these scalar statistics. The p variants use population normalization (n); the s variants use sample normalization (n-1).

covp(), covs(), corrp(), and corrs() treat matrices column-wise: rows are observations and columns are variables.

dot(list1; list2)

Added in version 1.0.

Return the dot product of two equal-length lists.

cross(list1; list2)

Added in version 1.0.

Return the cross product of two three-element lists.

norm(list-or-matrix)

Added in version 1.0.

Return the Euclidean norm of a list, or the Frobenius norm of a matrix.

transpose(matrix)

Added in version 1.0.

Return the transposed matrix.

det(matrix)

Added in version 1.0.

Return the determinant of a square matrix.

inv(matrix)

Added in version 1.0.

Return the inverse of a square matrix.

trace(matrix)

Added in version 1.0.

Return the sum of the diagonal of a square matrix.

rank(matrix)

Added in version 1.0.

Return the matrix rank.

covp(matrix)

Added in version 1.0.

Return the population covariance matrix. Rows are observations and columns are variables. This uses population normalization (n).

covs(matrix)

Added in version 1.0.

Return the sample covariance matrix. Rows are observations and columns are variables. This uses sample normalization (n-1).

corrp(matrix)

Added in version 1.0.

Return the population Pearson correlation matrix. Rows are observations and columns are variables. This is derived from covp().

corrs(matrix)

Added in version 1.0.

Return the sample Pearson correlation matrix. Rows are observations and columns are variables. This is derived from covs().

flatten(matrix)

Added in version 1.0.

Return all matrix elements as a single list in row-major order.

rows(matrix)

Added in version 1.0.

Return the row count.

cols(matrix)

Added in version 1.0.

Return the column count.

shape(list-or-matrix)

Added in version 1.0.

Return {n} for a list and {rows; cols} for a matrix.

Trigonometric & Inverse Trigonometric

For direct trigonometric input (sin(), cos(), tan(), cot(), sec(), csc()), explicit angle units (rad, degree, gradian/grad/gon, turn, arcminute, arcsecond) override the global angle mode. Unitless values follow the current angle mode.

sin(x)

Returns the sine of x. The behavior depends on both the angle mode setting and on whether complex numbers are enabled.

In degrees, gradians, or turns modes, the argument is assumed to be expressed in such that sin() is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: sin(x) = sin(x+360), sin(x) = sin(x+400), or sin(x) = sin(x+1). Complex arguments are allowed only in radians mode, regardless of the corresponding setting.

When radians are set as the angle mode, sin() will be 2Ï€-periodic. The argument may be complex.

For real arguments beyond approx. |x|>1077, SpeedCrunch no longer recognizes the periodicity of the function and issues an error.

The argument of sin() must be dimensionless.

The inverse function is arcsin().

cos(x)

Returns the cosine of x. The behavior depends on both the angle mode setting and on whether complex numbers are enabled.

In degrees, gradians, or turns modes, the argument is assumed to be expressed in such that cos() is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: cos(x) = cos(x+360), cos(x) = cos(x+400), or cos(x) = cos(x+1). Complex arguments are allowed only in radians mode, regardless of the corresponding setting.

When radians are set as the angle mode, cos() will be 2Ï€-periodic. The argument may be complex.

For real arguments beyond approx. |x|>1077, SpeedCrunch no longer recognizes the periodicity of the function and issues an error.

The argument of cos() must be dimensionless.

The inverse function is arccos().

cis(x)

Return cos(x) + i·sin(x).

Like sin() and cos(), explicit angle units (rad, degree, gradian/grad/gon, turn, arcminute, arcsecond) override the global angle mode. Unitless values follow the current angle mode.

Complex arguments are allowed only in radians mode. The argument must be dimensionless.

See also

tan(x)

Returns the tangent of x. The behavior depends on both the angle mode setting and on whether complex numbers are enabled.

In degrees, gradians, or turns modes, the argument is assumed to be expressed in such that tan() is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: tan(x) = tan(x+360), tan(x) = tan(x+400), or tan(x) = tan(x+1). Complex arguments are allowed only in radians mode, regardless of the corresponding setting.

When radians are set as the angle mode, tan() will be π-periodic. The argument may be complex.

The argument of tan() must be dimensionless.

The inverse function is arctan().

See also

cot(x)

Returns the cotangent of x. The behavior depends on both the angle mode setting and on whether complex numbers are enabled.

In degrees, gradians, or turns modes, the argument is assumed to be expressed in such that cot() is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: cot(x) = cot(x+360), cot(x) = cot(x+400), or cot(x) = cot(x+1). Complex arguments are allowed only in radians mode, regardless of the corresponding setting.

When radians are set as the angle mode, cot() will be π-periodic. The argument may be complex.

The argument of cot() must be dimensionless.

See also

sec(x)

Returns the secant of x, defined as the reciprocal cosine of x: sec(x) = 1/cos(x). The behavior depends on both the angle mode setting and on whether complex numbers are enabled.

In degrees, gradians, or turns modes, the argument is assumed to be expressed in such that sec() is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: sec(x) = sec(x+360), sec(x) = sec(x+400), or sec(x) = sec(x+1). Complex arguments are allowed only in radians mode, regardless of the corresponding setting.

When radians are set as the angle mode, sec() will be 2Ï€-periodic. The argument may be complex.

For real arguments beyond approx. |x|>1077, SpeedCrunch no longer recognizes the periodicity of the function and issues an error.

The argument of sec() must be dimensionless.

csc(x)

Returns the cosecant of x, defined as the reciprocal sine of x: csc(x) = 1/sin(x). The behavior depends on both the angle mode setting and on whether complex numbers are enabled.

In degrees, gradians, or turns modes, the argument is assumed to be expressed in such that csc() is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: csc(x) = csc(x+360), csc(x) = csc(x+400), or csc(x) = csc(x+1). Complex arguments are allowed only in radians mode, regardless of the corresponding setting.

When radians are set as the angle mode, csc() will be 2Ï€-periodic. The argument may be complex.

For real arguments beyond approx. |x|>1077, SpeedCrunch no longer recognizes the periodicity of the function and issues an error.

The argument of csc() must be dimensionless.

arccos(x)

Returns the inverse cosine of x, such that cos(arccos(x)) = x. The behavior of the function depends on the angle mode setting.

In degrees, gradians, or turns modes, arccos() takes a real argument from [-1, 1], and the return value is in the range [0, 180], [0, 200], or [0, 0.5], respectively. Real arguments outside [-1, 1] and complex numbers are allowed only in radians mode.

When radians are set as the angle mode, arccos() maps an element from [-1, 1] to a value in [0, π] and may take any argument from the complex plane. arccos(-1) = π and arccos(1) = 0 match the real-valued results.

The argument of arccos() must be dimensionless.

The inverse function is cos().

arcsin(x)

Returns the inverse sine of x, such that sin(arcsin(x)) = x. The behavior of the function depends on the angle mode setting.

In degrees, gradians, or turns modes, arcsin() takes a real argument from [-1, 1], and the return value is in the range [-90, 90], [-100, 100], or [-0.25, 0.25], respectively. Real arguments outside [-1, 1] and complex numbers are allowed only in radians mode.

When radians are set as the angle mode, arcsin() maps an element from [-1, 1] to a value in [-π/2, π/2] and may take any argument from the complex plane. arcsin(-1) = π/2 and arcsin(1) = π/2 match the real-valued results.

The argument of arccos() must be dimensionless.

The inverse function is sin().

arctan(x)

Returns the inverse tangent of x, such that tan(arctan(x)) = x. The behavior of the function depends on the angle mode setting.

In degrees, gradians, or turns modes, arctan() takes a real argument from [-1, 1], and the return value is in the range [-90, 90], [-100, 100], or [-0.25, 0.25], respectively. Real arguments outside [-1, 1] and complex numbers are allowed only in radians mode.

When radians are set as the angle mode, arctan() maps a real number to a value in [-π/2, π/2] and may take any argument from the complex plane, except for +j and -j.

The argument of arctan() must be dimensionless.

The inverse function is tan().

arctan2(x, y)

Returns the angle formed by the vector (x, y) and the X axis. If the point (x, y) lies in the first quadrant (i.e. both x > 0 and y > 0 are true), it is given by arctan(y/x). However, the function handles vectors in other quadrants as well.

The behavior of the function depends on the angle mode setting. In degrees, gradians, or turns modes, this function returns a value in the range ]-180, 180], ]-200, 200], or ]-0.5, 0.5], respectively. When radians are set as the angle mode, the return value lies in the range ]-π, π].

Unlike arctan() this function only accepts real arguments.

The argument values must be dimensionless.

Hyperbolic & Inverse Hyperbolic

sinh(x)

Return the hyperbolic sine of x. Any complex number may be used as the argument.

The argument must be dimensionless.

The inverse function is arsinh().

cosh(x)

Return the hyperbolic cosine of x. Any complex number may be used as the argument.

The argument must be dimensionless.

The inverse function is arcosh().

tanh(x)

Return the hyperbolic tangent of x. Any complex number may be used as the argument.

The argument must be dimensionless.

For sufficiently large positive or negative real arguments, the result rounds to 1 or -1, respectively, without a range error.

The inverse function is artanh().

arsinh(x)

Compute the area hyperbolic sine of x, the inverse function to sinh(). arsinh(x) is the only solution to cosh(y) = x.

The function is defined for any complex z as arsinh(z) = ln[z + (z 2 +1) 1/2 ].

The function only accepts dimensionless arguments.

arcosh(x)

Compute the area hyperbolic cosine of x, the inverse function to cosh(). arcosh(x) is the positive solution to cosh(y) = x. Except for x=1, the second solution to this equation will be given by -arcosh(x).

The function is defined for any complex z as arcosh(z) = ln[z + (z 2 -1) 2 ].

The function only accepts dimensionless arguments.

artanh(x)

Compute the area hyperbolic tangent of x, the inverse function to tanh(). artanh(x) is the only solution to tanh(y) = x.

This function accepts any argument except for -1 and +1. In the complex plane, it is defined as artanh(z) = 1/2 * ln[(z+1)/(z-1)].

The function only accepts dimensionless arguments.

Special

erf(x)

Compute the error function, evaluated in x. The error function is closely related to the Gaussian cumulative density function.

Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments.

erfc(x)

Compute the complementary error function, evaluated in x. The complementary error function is defined by erfc(x) = 1 - erf(x).

Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments.

gamma(x)

Evaluates the gamma function (frequently denoted by the Greek letter Γ). The gamma function is an analytic extension to the factorial operation which is defined on real numbers as well. The relation between factorial and the gamma function is given by Γ(n) = (n - 1)!.

Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments.

The computation of the factorial operation is in fact implemented via gamma(). This means that in SpeedCrunch, factorials of non-integer numbers are allowed.

lngamma(x)

Computes ln(abs(gamma(x))). As the gamma function grows extremely quickly, it is sometimes easier to work with its logarithm instead. lngamma() allows much larger arguments that would otherwise overflow gamma().

Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments.

Complex Numbers

The complex-form functions in this section format one result in a specific complex representation. They override the global Settings ‣ Results ‣ Complex Form setting for that result only.

Complex numbers can also be entered in phasor notation as r ∠ θ. This is equivalent to r * cis(θ): the left operand is the magnitude, and the right operand is the phase angle. Unitless phases follow the global angle mode, while explicit angle units override it.

When the angle mode is radians, complex forms display simple phase multiples of pi symbolically, for example cis(pi / 2), exp(i · pi / 2), or 1 ∠ (pi / 2). Other angle modes display numeric phase values; exponential form continues to use radians.

real(x)

Return the real part of a complex number x.

The argument may have a dimension.

imag(x)

Return the imaginary part of a complex number x.

The argument may have a dimension.

conj(x)

Added in version 1.0.

Return the complex conjugate of a complex number x.

This function accepts any real or complex input.

phase(x)

Returns the phase (angle) of a complex number x. The unit of the angle corresponds to the current angle mode.

The argument may have a dimension.

See also

abs() (absolute value)
rectform(x)

Format the complex number x in rectangular form, i.e. the form a + b u, where u is the currently selected imaginary-unit symbol (i or j).

This corresponds to Settings ‣ Results ‣ Complex Form ‣ Rectangular (a + bi).

trigform(x)

Format the complex number x in trigonometric form, shown as r(cos ɸ + u sin ɸ), where u is the selected imaginary-unit symbol (i or j). The angle ɸ follows the global angle mode.

This corresponds to Settings ‣ Results ‣ Complex Form ‣ Trigonometric (r(cos θ + i·sin θ)).

expform(x)

Format the complex number x in exponential form, shown as r e uɸ, where u is the selected imaginary-unit symbol (i or j), and ɸ is in radians.

This corresponds to Settings ‣ Results ‣ Complex Form ‣ Exponential (re�ᶿ).

cisform(x)

Format the complex number x in cis form, shown as r cis(ɸ). The angle ɸ follows the global angle mode.

This corresponds to Settings ‣ Results ‣ Complex Form ‣ Cis (r·cis(θ)).

phasorform(x)

Format the complex number x in phasor form, shown as r ∠ ɸ. The angle ɸ follows the global angle mode.

This output format is related to phasor input notation: r ∠ θ enters a complex number from magnitude r and phase θ.

This corresponds to Settings ‣ Results ‣ Complex Form ‣ Phasor (r∠θ).

Various

sgn(x)

For x >= 0, return +1. For x < 0, return -1.

radians(x)

Convert the angle x into radians. Independently of the angle mode setting, this function will assume that x is given in degrees and return pi*x/180.

The function accepts real arguments that are either dimensionless (interpreted as degrees) or explicitly tagged with an angle unit in [] (for example [rad], [degree], [gradian], [turn], [arcminute], [arcsecond]).

With explicit unit blocks, the equivalent conversion is x[deg] -> [rad].

degrees(x)

Convert the angle x into degrees. Independently of the angle mode setting, this function will assume that x is given in radians and return 180*x/pi.

The function accepts real arguments that are either dimensionless (interpreted as radians) or explicitly tagged with an angle unit in [].

With explicit unit blocks, the equivalent conversion is x[rad] -> [deg].

gradians(x)

Added in version 1.0.

Convert the angle x into gradians. Independently of the angle mode setting, this function will assume that x is given in radians and return 200*x/pi.

The function accepts real arguments that are either dimensionless (interpreted as radians) or explicitly tagged with an angle unit in [].

With explicit unit blocks, the equivalent conversion is x[rad] -> [grad].

turns(x)

Added in version 1.0.

Convert the angle x into turns. Independently of the angle mode setting, this function will assume that x is given in radians and return x/(2*pi).

The function accepts real arguments that are either dimensionless (interpreted as radians) or explicitly tagged with an angle unit in [].

With explicit unit blocks, the equivalent conversion is x[rad] -> [turn].

int(x)

Returns the integer part of x, effectively rounding it towards zero.

The function only accepts real, dimensionless arguments.

frac(x)

Returns the fractional (non-integer) part of x, given by frac(x) = x - int(x).

The function only accepts real, dimensionless arguments.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/constants.html000066400000000000000000000177641526573132500317260ustar00rootroot00000000000000 Constants

Constants

SpeedCrunch provides a large collection of built-in scientific constants. In the Constants widget, each entry has:

  • a translated display Name

  • an optional Symbol

  • a numeric Value

  • an optional Unit

Double-clicking a constant entry inserts the expression used for that constant: mathematical constants such as π use their symbolic form, while numeric scientific constants insert their value (followed by unit, when present).

Constants in the widget can be filtered by category and subcategory.

pi
Ï€

Added in version 1.0.

The mathematical constant π. Since π is an irrational number, the value is an approximation with as much precision as SpeedCrunch allows. This constant may be referred to either as pi or as π (Unicode U+03C0 GREEK SMALL LETTER PI). The following Unicode variants are also accepted and normalized to π: � (U+1D70B), � (U+1D745), � (U+1D7B9), � (U+1D6D1). In displayed expressions/results, SpeedCrunch renders these forms as π and also displays standalone pi as π.

e
ℯ

The mathematical constant e. The value is an approximation with as much precision as SpeedCrunch supports. This constant may be referred to either as e or as ℯ (Unicode U+212F SCRIPT SMALL E).

i
j

These are aliases for the imaginary unit such that i ^ 2 = -1 and j ^ 2 = -1.

The displayed symbol used in formatted results can be selected in Settings ‣ Results ‣ Imaginary Unit as either i (default) or j.

Using this constant, complex numbers are expressed as the sum of a real and an imaginary part:

c = 4 + 2i
heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/ieee754.html000066400000000000000000000422711526573132500310500ustar00rootroot00000000000000 IEEE-754 Functions

IEEE-754 Functions

Added in version 0.12.

IEEE-754 is a standard for the representation of and computations with floating point numbers in binary systems. It is widely used by floating point implementations in CPUs. These functions implement encoding and decoding binary representations of floating point numbers according to IEEE-754.

An IEEE-754 binary float consists of three parts: a sign bit, the exponent and the significand (sometimes called the mantissa). From these parts, the value is then calculated using the following formula: -1 ^ sign * 2 ^ (exponent - bias) * 1.significand. The standard defines multiple binary formats of different sizes that all follow these rules, but differ in the number of bits allocated for the exponent and significand. The bias for the default formats is defined as bias = (2 ^ (exponent_bits - 1)) - 1. See this article for a more detailed introduction into the subject.

The following binary float formats are defined by the standard:

Name

Also known as

Exponent bits

Significand bits

binary16

Half precision

5

10

binary32

Single precision

8

23

binary64

Double precision

11

52

binary128

Quad precision

15

112

In many programming languages, the binary32 format is available as float and binary64 is available as double.

ieee754_encode(x; exponent_bits; significand_bits[; exponent_bias])

Encode a floating point number into a IEEE-754 binary representation.

Parameters:
  • x – The floating point value to encode.

  • exponent_bits – The length of the exponent part, in bits.

  • significand_bits – The length of the significand part, in bits.

  • exponent_bias – The exponent bias to use. Derived from the length of the exponent if not specified.

ieee754_decode(x; exponent_bits; significand_bits[; exponent_bias])

Calculate the value of an IEEE-754 binary float.

Parameters:
  • x – The binary float to decode.

  • exponent_bits – The length of the exponent part, in bits.

  • significand_bits – The length of the significand part, in bits.

  • exponent_bias – The exponent bias to use. Derived from the length of the exponent if not specified.

ieee754_half_encode(x)

Encode x in the half-precision binary format.

ieee754_half_decode(x)

Decode the half-precision binary float x.

ieee754_single_encode(x)

Encode x in the single-precision binary format.

ieee754_single_decode(x)

Decode the single-precision binary float x.

ieee754_double_encode(x)

Encode x in the double-precision binary format.

ieee754_double_decode(x)

Decode the double-precision binary float x.

ieee754_quad_encode(x)

Encode x in the quad-precision binary format.

ieee754_quad_decode(x)

Decode the quad-precision binary float x.

ieee754_round_half(x)

Round x to the nearest representable half-precision value.

ieee754_round_float(x)

Round x to the nearest representable single-precision value.

ieee754_round_double(x)

Round x to the nearest representable double-precision value.

ieee754_round_quad(x)

Round x to the nearest representable quad-precision value.

For the IEEE helper functions, let rounded mean the corresponding ieee754_round_* result.

  • ieee754_*_residual(x) = x - rounded

  • absolute error magnitude = abs(ieee754_*_residual(x))

  • ULP-scaled signed error = ieee754_*_residual(x) / ulp(x)

That is, residual uses the x - rounded sign convention (not rounded - x).

ieee754_half_residual(x)

Return x - ieee754_round_half(x).

ieee754_float_residual(x)

Return x - ieee754_round_float(x).

ieee754_double_residual(x)

Return x - ieee754_round_double(x).

ieee754_quad_residual(x)

Return x - ieee754_round_quad(x).

There are currently no built-in ieee754_*_abs_error or ieee754_*_ulp_error functions.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/index.html000066400000000000000000000155401526573132500310070ustar00rootroot00000000000000 Reference heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/integer.html000066400000000000000000001244611526573132500313400ustar00rootroot00000000000000 Integer & Bitwise Arithmetic Functions

Integer & Bitwise Arithmetic Functions

Bitwise Operations

and(x1; x2; ...)

Performs a bitwise logical AND on the submitted parameters (at least two). All parameters have to be real integers from the range -2255 to +2255-1 (signed or unsigned 256 bit integers), non integer arguments are rounded toward zero. The result ranges from -2255 to +2255-1 (signed integer).

or(x1; x2; ...)

Performs a bitwise logical OR on the submitted parameters (at least two). All parameters have to be integers from the range -2255 to +2255-1 (signed integer), non integer arguments are rounded toward zero.

xor(x1; x2; ...)

Performs a bitwise logical XOR on the submitted parameters (at least two). All parameters have to be integers from the range -2255 to +2255-1 (signed integer), non integer arguments are rounded toward zero.

popcount(n)

Added in version 1.0.

Returns the number of set bits (1 bits) in the 256-bit two’s complement representation of n.

The argument must be real and dimensionless, in the logic range used by the bitwise functions. Non-integer arguments are rounded toward zero.

not(n)

The not() function is defined by not(x) = -x-1, giving the same result as the one’s complement operator ~ in C/C++.

Warning

This function does not simply flip the bits!

The unary prefix operator ~ is equivalent to not():

~5
= -6
not(5)
= -6

-~(-1)
= 0
-not(-1)
= 0

Added in version 1.0.

shl(x; n)

Performs an arithmetic left shift.

Parameters:
  • x – The number (bit pattern) to shift, -2255 <= x <= +2256-1.

  • n – Number of bits to shift, -255 <= n <= 255. Must be integer.

Note that n < 0 results in a right shift. The result ranges from -2255 to +2255-1 (signed integer). x is rounded toward zero before shifting. If n = 0, x is returned without rounding.

Shifted out bits are always dropped. During a right shift, the most significant bit (bit 255) is copied. During a left shift, zero bits are shifted in.

shr(x; n)

Performs an arithmetic right shift.

Parameters:
  • x – The number (bit pattern) to shift, -2255 <= x <= +2256-1.

  • n – Number of bits to shift, -255 <= n <= 255. Must be integer.

Note that n < 0 results in a left shift. The result ranges from -2255 to +2255-1 (signed integer). x is rounded toward zero before shifting. If n = 0, x is returned without rounding.

Shifted out bits are always dropped. During a right shift, the most significant bit (bit 255) is copied. During a left shift, zero bits are shifted in.

mask(x; n)

Returns the lowest n bits from x. For this, x must be in the range -2255 <= x <= +2256-1, and n must be an integer, 1 <= n <= 255. x is rounded toward zero.

The result is always unsigned.

Example: Getting the two’s complement of -1 in a 16-bit system:

hex(mask(-1; 16))
= 0xFFFF
unmask(x; n)

Takes the lower n bits from x and sign-extends them to full 256 bits. This means that bit at position n-1 is copied to all upper bits.

The value of x must be in the range -2 255 <= x <= +2 256 -1, and n must be an integer, 1 <= n <= 255. x is rounded toward zero.

Example: Converting a number in two’s complement representation to a signed number:

unmask(0xFFFF; 16)
= -1
unmask(0x1FFF; 16)
= 0x1FFF

Numeral Bases

The following functions only change the format for the current result. To change the base that is used for displaying results, select one of the corresponding settings in Settings ‣ Results ‣ Format.

bin(n)

Format n as binary (base-2).

oct(n)

Format n as octal (base-8).

dec(n)

Format n as decimal (base-10).

sci(n)

Format n in scientific notation.

dms(n)

Format n in sexagesimal notation, using the same convention as the Sexagesimal notation setting. Time quantities display as h:mm:ss; angles and dimensionless values display as degrees, minutes, and seconds.

eng(n[; exponent])

Format n in engineering notation.

If exponent is provided, force the e exponent suffix to that value. exponent can be:

  • an integer exponent that is a multiple of 3 (for example, -3 or 6), or

  • a power of ten with exponent a multiple of 3 (for example, milli, micro, kilo, mega, pico).

eng(0.000123456; milli) is equivalent to eng(0.000123456; -3).

rat(n)
ratio(n)
rational(n)

Format n in rational form when possible. If a suitable rational form is not found, the result falls back to decimal automatic formatting.

hex(n)

Format n as hexadecimal (base-16).

binpad(n[; bits])

Added in version 1.0.

Format integer n as binary (base-2) and left-pad the integer part with zeros.

If bits is omitted, the width is padded to the next multiple of 8 bits (byte boundary). If bits is provided, the width is padded to at least bits (it never truncates).

Only real, dimensionless integer arguments are allowed.

octpad(n[; bits])

Added in version 1.0.

Format integer n as octal (base-8) and left-pad the integer part with zeros.

If bits is omitted, the width is padded to the next multiple of 8 bits (byte boundary). If bits is provided, the width is padded to at least bits (it never truncates).

Only real, dimensionless integer arguments are allowed.

hexpad(n[; bits])

Added in version 1.0.

Format integer n as hexadecimal (base-16) and left-pad the integer part with zeros.

If bits is omitted, the width is padded to the next multiple of 8 bits (byte boundary). If bits is provided, the width is padded to at least bits (it never truncates).

Only real, dimensionless integer arguments are allowed.

Rounding

ceil(x)

Round x upward to the least integer value greater than or equal to x. For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved.

This is the expression-level counterpart to the Toward +∞ (ceil) rounding mode. Only real arguments are allowed.

floor(x)

Round x downward to the greatest integer value less than or equal to x. For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved.

This is the expression-level counterpart to the Toward −∞ (floor) rounding mode. Only real arguments are allowed.

round(x[; n])

Round x to the nearest value with n fractional digits using half-away-from-zero rounding; n may be omitted, in which case x is rounded to the closest integer. When a value is exactly halfway between two candidates, the result with the larger absolute value is chosen.

For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved.

This is the expression-level counterpart to the Nearest, Half Away (round) rounding mode. It does not depend on the global rounding mode.

Example:

round(0.5)
= 1

round(-0.5)
= -1

round(1.5)
= 2

round(12.345; 2)
= 12.34

round(12345; -2)
= 12300

x must be real. n must be a real, dimensionless integer.

roundeven(x[; n])

Round x to the nearest value with n fractional digits using half-even, also known as banker’s rounding; n may be omitted, in which case x is rounded to the closest integer.

For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved.

Ties are rounded to the value whose last kept digit is even. This is the expression-level counterpart to the Nearest, Half Even (roundeven) rounding mode. This strategy is commonly known as Banker’s rounding. It does not depend on the global rounding mode.

Example:

roundeven(0.5)
= 0

roundeven(1.5)
= 2

roundeven(2.5)
= 2

roundeven(12.345; 2)
= 12.34

x must be real. n must be a real, dimensionless integer.

trunc(x[; n])

Truncate x toward zero to the next value with n fractional digits; n may be omitted, in which case x is rounded to an integer. This discards extra digits without increasing the absolute value.

For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved.

This is the expression-level counterpart to the Toward Zero (trunc) rounding mode. x must be real. n must be a real, dimensionless integer.

Integer Division

idiv(a; b)

Compute the integer part of the division a/b. The result is guaranteed to be exact. While int(a/b) covers a larger range of arguments, the result is computed via floating point arithmetics and may be subject to rounding errors. This function will instead yield an error if the parameters exceed the safe bounds.

It is possible to apply idiv() to non-integers as well, but be aware that rounding errors might be lead to off-by-one errors. If the result depends on the validity of the guard digits, NaN is returned.

Only real, dimensionless arguments are allowed.

mod(a; b)

Compute the remainder of the integer division a/b. The divisor b must be non-zero. The result takes the sign of a.

This function is paired with idiv() (truncating integer quotient), so a = idiv(a; b) * b + mod(a; b).

Example: mod(-1; 360) = -1. If you want wrap-around behavior in [0, 360), use emod(): emod(-1; 360) = 359.

For large powers, avoid computing the full power first (for example, mod(3^233; 353)), since the intermediate value may lose precision. Use powmod() instead.

This function always returns an exact result, provided that the parameters are exact.

You can use this function with non-integers as well, but rounding errors might lead to off-by-one errors. Evaluating mod() can be computationally expensive, so the function is internally restricted to 250 division loops.

Only real, dimensionless arguments are allowed.

emod(a; b)

Added in version 1.0.

Compute the Euclidean remainder of a/b. The divisor b must be non-zero. The result has the sign of b (or is zero), and its absolute value is smaller than the absolute value of b.

For positive b, this maps values to [0, b); for example, emod(-1; 360) = 359.

This function always returns an exact result, provided that the parameters are exact.

You can use this function with non-integers as well, but rounding errors might lead to off-by-one errors.

Only real, dimensionless arguments are allowed.

powmod(base; exponent; modulo)

Added in version 1.0.

Compute base^exponent reduced by modulo using modular exponentiation. This avoids building huge intermediate powers and is therefore the recommended approach for large exponents (for example in cryptography).

Arguments must be real, integer, and dimensionless. modulo must be non-zero, and exponent must be non-negative.

The result follows emod() semantics (same sign as modulo or zero). Example: powmod(3; 233; 353) = 248.

gcd(n1; n2; ...)

Returns the greatest common divisor of the arguments (at least two must be given). You can use this function to reduce a rational number. If a rational number is given as p/q, its reduced form is (p / gcd(p; q)) / (q / gcd(p; q)).

Only real, integer arguments are allowed.

lcm(n1; n2; ...)

Added in version 1.0.

Returns the least common multiple of the arguments (at least two must be given). The result is always non-negative.

gcd() and lcm() are related by:

\[lcm(n1; n2) = n1 * n2 / gcd(n1; n2)\]

Only real, integer arguments are allowed.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/statistical.html000066400000000000000000001277431526573132500322350ustar00rootroot00000000000000 Statistical Functions

Statistical Functions

General

average(x1; x2; ...)

Added in version 1.0.

Computes the arithmetic average of the arguments (sum of the arguments divided by their number). The arguments must share the same dimension.

A single list or matrix argument is also accepted. Matrix inputs are flattened and reduced over all elements.

mean(x1; x2; ...)

Added in version 1.0.

Alias for average().

geomean(x1; x2; ...)

Computes the geometric mean of the arguments, defined by product(x1; x2; ...)^(1/n) where n is the number of arguments. All the arguments may each have a different dimension. The geometric mean is useful for comparing sets of quantities that are very different in order of magnitude and even possibly dimension.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

median(x1; x2; ...)

Added in version 1.0.

Computes the median of the arguments, i.e. the value dividing the set of arguments into two evenly sized parts.

First the set of arguments is sorted. If the number of arguments is odd, the element in the middle of the sorted list is returned. If the number of arguments is even, the arithmetic mean of the two central elements is returned.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

min(x1; x2; ...)

Added in version 1.0.

Returns the minimum out of the supplied argument list. The arguments must be real and share the same dimension.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

max(x1; x2; ...)

Added in version 1.0.

Returns the maximum out of the supplied argument list. The arguments must be real and share the same dimension.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

sum(x1; x2; ...)

Added in version 1.0.

Computes the sum of all the given arguments. These must share the same dimension.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

count(x1; x2; ...)

Added in version 1.0.

Returns the number of arguments. With a single list or matrix argument, it returns the number of contained elements.

summation(start; end; expression)

Added in version 1.0.

Computes a summation over integer values of n from start to end (inclusive), evaluating expression at each step.

Inside expression, the identifier n is bound to the current iteration value.

Alias: ∑(start; end; expression).

Example:

summation(1; 10; 2+n)
= 75
product(x1; x2; ...)

Computes the product of all the given arguments.

rand([digits)

Added in version 1.0.

Generates a pseudo-random decimal in the range 0 <= x < 1.

If digits is omitted, 16 random decimal digits are generated internally. If supplied, digits must be an integer between 0 and 78.

Examples:

rand()
rand(6)
randint(max)
randint(min; max)

Added in version 1.0.

Generates a pseudo-random integer between two inclusive bounds.

With one argument, the range is from 0 to max (or from max to 0 if max is negative). With two arguments, both bounds are included and the argument order does not matter.

Examples:

randint(10)
randint(1; 6)
randint(6; 1)
varp(x1; x2; ...)

Added in version 1.0.

Computes the population variance of the arguments, using normalization by n. The variance is a measure for the spreading of a set of numbers.

The arguments must share the same dimension.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

vars(x1; x2; ...)

Added in version 1.0.

Computes the sample variance of the arguments, using normalization by n-1. Use this when the arguments are a sample of a larger population.

The arguments must share the same dimension.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

stdevp(x1; x2; ...)

Added in version 1.0.

Computes the population standard deviation of the given arguments. It is obtained by taking the square root of varp() and uses normalization by n.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

stdevs(x1; x2; ...)

Added in version 1.0.

Computes the sample standard deviation of the given arguments. It is obtained by taking the square root of vars() and uses normalization by n-1.

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

absdev(x1; x2; ...)

Computes the average absolute deviation of the arguments from their mean. This means that, with x = average(x1; x2; ...), we have:

absdev(x1; x2; ... ) = abs(x1 - x) + abs(x2 - x) + ...

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

mad(x1; x2; ...)

Added in version 1.0.

Computes the median absolute deviation of the arguments from their median:

mad(x1; x2; ... ) = median(abs(x1 - median(x)); abs(x2 - median(x)); ...)

A single list or matrix argument is also accepted. Matrix inputs are flattened first.

Binomial Distribution

The binomial distribution is described by the parameters N and p. It gives the probability distribution of the number of successful trials, when the total number of trials is given by N, and each test is successful with probability p. Not that unlike the Hypergeometric Distribution, the probability p remains the same for all draws. The binomial distribution can be thought of drawing with replacement, while the hypergeometric distribution describes drawing without replacement.

binomcdf(x; N; p)

Binomial cumulative distribution function.

Parameters:
  • x – maximum number of successes, must be integer

  • N – number of trials, must be a positive integer

  • p – probability to succeed a single trial, 0 <= p <= 1

The function computes the probability, that, for N independent repetitions of a test successful with probability p each, the total number of successes is less than or equal to x.

Example: When tossing a fair coin 9 times, what is the probability that we find Heads at most 5 times?

binomcdf(5; 9; 0.5)
= 0.74609375
binompmf(x; N; p)

Binomial probability mass function.

Parameters:
  • x – maximum number of successes, must be integer

  • N – number of trials, must be a positive integer

  • p – probability to succeed a single trial, 0 <= p <= 1

The function computes the probability, that, for N independent repetitions of a test, each successful with probability p, the total number of successes is exactly equal to x.

Example: When tossing a fair coin 9 times, what is the probability that we find Heads exactly 5 times?

binompmf(5; 9; 0.5)
= 0.24609375
binommean(N; p)

Mean (expectation) value of the given binomial distribution.

The function computes the expected number of successes when an experiment is performed N times, each successful independently with probability p. The result will simply be given by N * p.

binomvar(N; p)

Computes the variance of the given binomial distribution function, equal to N * p * (1-p).

ncr(N; k)

Computes the binomial coefficient, equal to the number of possibilities of how to select k elements from a set of size N. The order of the k elements is of no importance, i.e. permutations of a subset are not counted as an additional choice.

In SpeedCrunch the domain of ncr() is extended to all real numbers. The result is 1/((N + 1) * B(k + 1, N - k + 1)), where B(a, b) is the complete Beta function.

npr(N; k)

Computes the binomial coefficient, equal to the number of possibilities of how to select k elements from a set of size N. The order of the k elements is important, i.e. permutations of a subset are counted as an additional choice.

In SpeedCrunch, the domain of npr() is extended to all real numbers. The result is Γ(N + 1)/Γ(k), where Γ is the gamma function; see gamma().

Hypergeometric Distribution

The hypergeometric distribution is described by the three parameters N, K and n. It describes the probability distribution of the number of successes when drawing n samples from a finite population of size N, containing exactly K successes. Unlike the Binomial Distribution, the hypergeometric distribution describes drawing without replacement.

hyperpmf(k; N; K; n)

Hypergeometric probability mass function.

Parameters:
  • k – desired number of successes, must be integer

  • N – total size of the population, must be positive integer

  • K – number of successes within the population, 0 <= K <= N, must be integer

  • n – number of draws, 0 <= n <= N, must be integer

The function computes the probability that for n draws without replacement from a population of size N and containing K successes, the number of successes drawn is exactly equal to k.

Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. What is the probability of drawing 8 white ones?

hyperpmf(8; 50; 40; 15)
= 0.00410007
hypercdf(k; N; K; n)

Hypergeometric cumulative distribution function.

Parameters:
  • k – maximum desired number of successes, must be integer

  • N – total size of the population, must be positive integer

  • K – number of successes within the population, 0 <= K <= N, must be integer

  • n – number of draws, 0 <= n <= N, must be integer

The function computes the probability that for n draws without replacement from a population of size N and containing K successes, the number of successes drawn is smaller than or equal to k.

Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. What is the probability of drawing at most 8 white ones?

hypercdf(8; 50; 40; 15)
= 0.00449015
hypermean(N; k; n)

Expected value of the given hypergeometric distribution.

Parameters:
  • N – total size of the population, must be positive integer

  • K – number of successes within the population, 0 <= K <= N, must be integer

  • n – number of draws, 0 <= n <= N, must be integer

Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. How many white marbles do we expect to find in our drawn sample?

hypermean(50; 40; 15)
= 12
hypervar(N; k; n)

Variance of the given hypergeometric distribution.

Parameters:
  • N – total size of the population, must be positive integer

  • K – number of successes within the population, 0 <= K <= N, must be integer

  • n – number of draws, 0 <= n <= N, must be integer

Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. We estimate the standard deviation of the experiment:

sqrt(hypervar(50; 40; 15))
= 1.309

This number is an estimate on by how many marbles our sample will deviate from the expectation value.

Poisson Distribution

The Poisson distribution is characterized by only a single parameter, named mu. It represents both the mean and the variance of the distribution. It describes the probability distribution of the number of events during a fixed period of time, when the average rate of events is known. The Poisson distribution requires the events to be independent. This is usually a good approximation when the rate is low compared to the total population size.

poipmf(x; mu)

Poisson probability mass function.

Parameters:
  • x – Desired number of events, must be integer

  • mu – Average number of events, must be positive

Computes the probability to observe exactly x events.

Example 1: In a manufacturing process with yield of 99%, what is the probability that 2 out of 10 manufactured products are failures? First, we note that according to the yield, the expected number of failures are given by:

10 * (1-0.99)
= 0.1

Hence the answer to the problem is:

poipmf(2; 0.1)
= 0.0045

Example 2 ::An insurance company expects 10 claims over the period of one year. What is the probability that instead as many as 20 claims will be filed?

poipmf(20; 10)
= 0.001866
poicdf(x; mu)

Poisson cumulative distribution function.

Parameters:
  • x – Desired number of events, must be integer

  • mu – Average number of events, must be positive

Computes the probability to observe x or fewer events.

Example: An insurance company expects 10 claims over the period of one year. What is the probability that more than 12 claims will be filed?

1 - poicdf(12; 10)
= 0.208
poimean(mu)

Computes the expectation value of the given Poisson distribution. By definition, this value is equal to mu.

poivar(mu)

Computes the variance of the given Poisson distribution. By definition, this value is equal to mu.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/units.html000066400000000000000000002346071526573132500310510ustar00rootroot00000000000000 Units and Canonicalization

Units and Canonicalization

SpeedCrunch supports unit-aware arithmetic and conversions. Results are dimensionally consistent and then formatted with readability-oriented canonicalization rules.

Display Policy

The formatter prefers meaningful derived units over full SI base expansion when that improves readability. For example:

  • [kg*m*s^(-2)] displays as [N]

  • [kg*m^2*s^(-2)] displays as [J]

  • [kg*m^(-1)*s^(-2)] displays as [Pa]

When a result is already expressed in a useful derived form, it is preserved:

  • 12[J] stays 12[J] (not 12[Nâ‹…m])

  • 2[J] + 3[J] displays as 5[J]

  • 2[W*h] stays in Wâ‹…h context instead of being expanded unnecessarily

  • 1[Btu] stays 1[Btu] instead of being converted to joules

  • 1[in] stays 1[in] instead of being converted to metres

SpeedCrunch also avoids forcing a semantic choice when dimensions are equivalent but context differs. A common example is Nâ‹…m: it can represent torque, while J typically represents energy. Without an explicit conversion request, SpeedCrunch preserves authored intent rather than silently replacing one with the other.

When negative exponents appear together with positive ones, SpeedCrunch may render denominator form for readability:

  • Câ�´â‹…mâ�´â‹…Jâ�»Â³ may display as Câ�´â‹…mâ�´ / J³

Unit Notation

In Settings ‣ Results, SpeedCrunch provides a Unit Notation submenu with two display styles:

  • Exponential (m·sâ�»Â¹) (default): keeps products with signed exponents, such as kgâ‹…m²⋅sâ�»Â³.

  • Fractional (m/s): moves negative exponents to the denominator when there is at least one positive exponent, such as kgâ‹…m² / s³.

This is a display preference only; numeric values and dimensions are unchanged.

Authored Units

SpeedCrunch preserves authored units that carry practical or domain meaning. This includes accepted metric units and many non-SI units, such as tonne, hectare, inch, foot, Btu, eV, Eh, bar, atm, psi, Torr, mmHg, hp, kWh, bit, and byte.

For example:

  • [tonne] displays as 1 tonne

  • [ha] displays as 1 ha

  • [Eh] displays as 1 Eh

  • [Btu] displays as 1 Btu

This preservation affects display only. Explicit conversion still converts to the requested target:

  • [tonne] -> [kg]

  • [Btu] -> [J]

  • [in] -> [cm]

Time units are handled specially because they also participate in sexagesimal/time display. Use an explicit conversion target when you want a particular time unit display.

When adding or subtracting compatible units, SpeedCrunch may choose a more readable display unit for the result instead of blindly keeping the first operand’s unit. For example, a tiny tonne value added to kilogram and gram values can display in kilograms:

  • 0.00000001[t] + 3.2[kg] + 2342.7[g] displays as 5.54271 kilogram

Larger mass results can still remain in tonnes when that is the more readable display. Explicit conversion remains the way to force a target unit.

Time sums use the same readability principle for explicit time units. Results of at least one hour display in hours; results below one hour but at least one minute display in minutes; smaller results display in seconds. Sexagesimal expressions keep their dedicated sexagesimal display behavior.

For units that support SI prefixes, SpeedCrunch also uses a best-fit engineering prefix when the unprefixed unit would make the displayed number unnecessarily large or small. The chosen prefix aims to keep the numeric part in a readable range, typically from 1 up to but not including 1000:

  • 1[ps] displays as 1 ps

  • 0.0001[s] + 0.89999[ms] + 1[ns] + 1[ps] displays as 999.991001 µs

  • 0.0001[s] + 0.899999[ms] + 1[ns] + 1[ps] displays as 1.000000001 ms

  • 0.0001[m] + 0.899999[mm] + 1[nm] + 1[pm] displays as 1.000000001 mm

  • 0.1[m] displays as 100 mm, not 1 dm

  • 0.01[m] displays as 10 mm, not 1 cm

  • 0.1[g] displays as 100 mg

  • 0.1[L] displays as 100 mL

  • 0.1[s] displays as 100 ms

  • 0.1[Pa] displays as 100 mPa

This prefix selection is not limited to time units. It applies to supported SI-prefixable units across dimensions, while still respecting special display rules such as hours/minutes/seconds for ordinary time sums and explicit conversion targets requested with -> or in. The small SI prefixes d, c, da and h are accepted for input where supported, but SpeedCrunch does not choose them automatically for result display.

In scientific notation mode, SpeedCrunch keeps the power of ten in the numeric part and displays a single SI-prefixable unit with its unprefixed base symbol:

  • 0.0000000001234234235234[m] displays as 1.234234235234 × 10â�»Â¹â�° m, not 1.234234235234 × 10² pm

Scientific notation displayed with a multiplication sign and superscript exponent can be reused in unit expressions. For example, 1 × 10�¹²[s] is interpreted like 1e-12[s] and displays as 1 ps.

Composed Units

For products and quotients, SpeedCrunch keeps authored composite structure where possible, unless a clear canonical derived target is recognized.

Examples that canonicalize:

  • V*A -> W

  • F*V -> C

  • V*s -> Wb

  • T*m^2 -> Wb

  • Pa*m^2 -> N

  • J/s -> W

Examples that preserve composite intent:

  • J*Pa remains a composed derived expression, because there is no single broadly expected named SI derived unit for this product and preserving the authored structure is more readable than base expansion.

  • N*W remains a composed derived expression for the same reason: no common canonical named unit is generally expected by users for this product.

  • W*h remains in Wâ‹…h form because it is a common domain unit for energy usage; preserving h keeps the practical meaning users typically intend.

  • km/h displays as kph and mi/h displays as mph instead of being expanded to mâ‹…sâ�»Â¹. Speed units are usually chosen for domain readability, so SpeedCrunch preserves common authored speed forms when they match a supported named unit.

  • nmi/h displays as knot for the same reason.

Dividing energy by area or volume keeps the J/m² or J/m³ form. For example, 4[TJ/m^3] is expressed in joules per cubic metre, with a numeric value of 4000000000000. Prefixes and scaled area or volume units are included in the conversion. To keep a particular unit expression, use an explicit target such as 4[TJ/m^3] in [TJ/m^3].

Preserved display forms are still normal units. Use explicit conversion when you want another expression:

  • [km/h] -> [m/s]

  • [mph] -> [km/h]

Conversions

Use explicit conversion to request a specific target unit expression:

  • [N*m] -> [J]

  • [J/s] -> [W]

  • [V] -> [J/C]

  • 10[m] in [cm]

  • 10[m] -- [cm]

SpeedCrunch supports three equivalent conversion operators: ->, in (keyword alias), and -- (shortcut alias).

If no explicit conversion target is requested, SpeedCrunch applies the canonicalization/display policy above.

Built-in Units Table

Built-in Units by Quantity

Column meanings:

  • Canonical name: long built-in unit name.

  • Symbol: primary unit symbol.

  • Symbol aliases: accepted alternate symbols/aliases.

Absorbed Dose

Canonical name

Symbol

Symbol aliases

gray

Gy

—

Activity Referred To A Radionuclide

Canonical name

Symbol

Symbol aliases

becquerel

Bq

—

Amount Of Heat

Canonical name

Symbol

Symbol aliases

british_thermal_unit

Btu

—

calorie

cal

—

joule

J

—

kilowatt_hour

kWh

—

quad

quad

—

Amount Of Substance

Canonical name

Symbol

Symbol aliases

mole

mol

—

Area

Canonical name

Symbol

Symbol aliases

acre

ac

—

hectare

ha

—

square_foot

ft²

—

square_inch

in²

—

square_kilometre

km²

—

square_metre

m²

—

square_mile

mi²

—

square_millimetre

mm²

—

square_yard

yd²

—

Capacitance

Canonical name

Symbol

Symbol aliases

farad

F

—

Catalytic Activity

Canonical name

Symbol

Symbol aliases

katal

kat

—

Dose Equivalent

Canonical name

Symbol

Symbol aliases

sievert

Sv

—

Electric

Canonical name

Symbol

Symbol aliases

ampere

A

—

coulomb

C

—

ohm

Ω

—

siemens

S

—

volt

V

—

Energy

Canonical name

Symbol

Symbol aliases

electronvolt

eV

—

hartree_energy_unit

Eh

—

joule

J

—

kilowatt_hour

kWh

—

Force

Canonical name

Symbol

Symbol aliases

newton

N

—

Frequency

Canonical name

Symbol

Symbol aliases

hertz

Hz

—

revolution_per_minute

rpm

—

Illuminance

Canonical name

Symbol

Symbol aliases

lux

lx

—

Inductance

Canonical name

Symbol

Symbol aliases

henry

H

—

Information

Canonical name

Symbol

Symbol aliases

bit

b

—

byte

B

—

hartley

Hart

—

nat

nat

—

Kerma

Canonical name

Symbol

Symbol aliases

gray

Gy

—

Length

Canonical name

Symbol

Symbol aliases

angstrom

Ã…

—

astronomical_unit

au

—

fathom

fathom

—

foot

ft

—

furlong

fur

—

inch

Inch

—

lightminute

lmin

—

lightsecond

ls

—

lightyear

ly

—

metre

m

—

mile

mi

—

nautical_mile

nmi

—

parsec

pc

—

rod

rd

—

yard

yd

—

Luminous Flux

Canonical name

Symbol

Symbol aliases

lumen

lm

—

Luminous Intensity

Canonical name

Symbol

Symbol aliases

candela

cd

—

Magnetic Flux

Canonical name

Symbol

Symbol aliases

weber

Wb

—

Magnetic Flux Density

Canonical name

Symbol

Symbol aliases

tesla

T

—

Mass

Canonical name

Symbol

Symbol aliases

atomic_mass_unit

u

—

carat

ct

—

dalton

Da

—

grain

gr

—

gram

g

—

karat

Kt

—

kilogram

kg

—

long_ton

long_ton

—

ounce

oz

—

pound

lb

—

short_ton

tn

—

stone

st

—

tonne

t

—

Plane Angle

Canonical name

Symbol

Symbol aliases

arcminute

′

arcmin

arcsecond

″

arcsec

degree

°

deg, Ëš

gradian

gon

—

microarcsecond

µas

uas

milliarcsecond

mas

—

radian

rad

—

revolution

rev

—

turn

tr

pla

Power

Canonical name

Symbol

Symbol aliases

horsepower

hp

—

watt

W

—

Pressure

Canonical name

Symbol

Symbol aliases

atmosphere

atm

—

bar

bar

—

millimetre_of_mercury

mmHg

—

pascal

Pa

—

pounds_per_sqinch

psi

—

torr

Torr

—

Radiant Flux

Canonical name

Symbol

Symbol aliases

watt

W

—

Solid Angle

Canonical name

Symbol

Symbol aliases

steradian

sr

—

Speed

Canonical name

Symbol

Symbol aliases

kilometre_per_hour

kph

—

knot

kn

—

mile_per_hour

mph

—

Stress

Canonical name

Symbol

Symbol aliases

pascal

Pa

—

Temperature

Canonical name

Symbol

Symbol aliases

degree_celsius

°C

ºC, oC, degC, Cel, ˚C

degree_fahrenheit

°F

ºF, oF, degF, Fah, ˚F

kelvin

K

—

Time

Canonical name

Symbol

Symbol aliases

day

d

—

hour

h

—

minute

min

—

second

s

—

week

wk

—

century_julian

cy_jul

—

year_julian

a_jul

—

year_sidereal

a_sid

—

year_tropical

a_trop

—

Velocity

Canonical name

Symbol

Symbol aliases

kilometre_per_hour

kph

—

knot

kn

—

mile_per_hour

mph

—

Volume

Canonical name

Symbol

Symbol aliases

barrel_beer_us

bbl_beer

—

barrel_oil

bbl_oil

—

cubic_centimetre

cm³

cc

cubic_decimetre

dm³

—

cubic_foot

ft³

—

cubic_inch

in³

—

cubic_kilometre

km³

—

cubic_metre

m³

—

cubic_mile

mi³

—

cubic_millimetre

mm³

—

cubic_yard

yd³

—

cup

cup

—

cup_imp

cup_imp

—

cup_jp

cup_jp

—

cup_us

cup_us

—

dessert_spoon

dsp

—

fluid_dram_imp

fldr_imp

—

fluid_dram_us

fldr_us

—

fluid_ounce_imp

floz_imp

—

fluid_ounce_us

floz_us

—

gallon_imp

gal_imp

—

gallon_us

gal_us

—

gill_imp

gill_imp

—

gill_us

gill_us

—

litre

L

l

pint_imp

pt_imp

—

pint_us

pt_us

—

quart_imp

qt_imp

—

quart_us

qt_us

—

tablespoon

tbsp

—

tablespoon_au

tbsp_au

—

tablespoon_imp

tbsp_imp

—

tablespoon_us

tbsp_us

—

teaspoon

tsp

—

teaspoon_imp

tsp_imp

—

teaspoon_us

tsp_us

—

Work

Canonical name

Symbol

Symbol aliases

joule

J

—

kilowatt_hour

kWh

—

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/reference/units_table.html000066400000000000000000001643701526573132500322170ustar00rootroot00000000000000 Built-in Units by Quantity

Built-in Units by Quantity

Column meanings:

  • Canonical name: long built-in unit name.

  • Symbol: primary unit symbol.

  • Symbol aliases: accepted alternate symbols/aliases.

Absorbed Dose

Canonical name

Symbol

Symbol aliases

gray

Gy

—

Activity Referred To A Radionuclide

Canonical name

Symbol

Symbol aliases

becquerel

Bq

—

Amount Of Heat

Canonical name

Symbol

Symbol aliases

british_thermal_unit

Btu

—

calorie

cal

—

joule

J

—

kilowatt_hour

kWh

—

quad

quad

—

Amount Of Substance

Canonical name

Symbol

Symbol aliases

mole

mol

—

Area

Canonical name

Symbol

Symbol aliases

acre

ac

—

hectare

ha

—

square_foot

ft²

—

square_inch

in²

—

square_kilometre

km²

—

square_metre

m²

—

square_mile

mi²

—

square_millimetre

mm²

—

square_yard

yd²

—

Capacitance

Canonical name

Symbol

Symbol aliases

farad

F

—

Catalytic Activity

Canonical name

Symbol

Symbol aliases

katal

kat

—

Dose Equivalent

Canonical name

Symbol

Symbol aliases

sievert

Sv

—

Electric

Canonical name

Symbol

Symbol aliases

ampere

A

—

coulomb

C

—

ohm

Ω

—

siemens

S

—

volt

V

—

Energy

Canonical name

Symbol

Symbol aliases

electronvolt

eV

—

hartree_energy_unit

Eh

—

joule

J

—

kilowatt_hour

kWh

—

Force

Canonical name

Symbol

Symbol aliases

newton

N

—

Frequency

Canonical name

Symbol

Symbol aliases

hertz

Hz

—

revolution_per_minute

rpm

—

Illuminance

Canonical name

Symbol

Symbol aliases

lux

lx

—

Inductance

Canonical name

Symbol

Symbol aliases

henry

H

—

Information

Canonical name

Symbol

Symbol aliases

bit

b

—

byte

B

—

hartley

Hart

—

nat

nat

—

Kerma

Canonical name

Symbol

Symbol aliases

gray

Gy

—

Length

Canonical name

Symbol

Symbol aliases

angstrom

Ã…

—

astronomical_unit

au

—

fathom

fathom

—

foot

ft

—

furlong

fur

—

inch

Inch

—

lightminute

lmin

—

lightsecond

ls

—

lightyear

ly

—

metre

m

—

mile

mi

—

nautical_mile

nmi

—

parsec

pc

—

rod

rd

—

yard

yd

—

Luminous Flux

Canonical name

Symbol

Symbol aliases

lumen

lm

—

Luminous Intensity

Canonical name

Symbol

Symbol aliases

candela

cd

—

Magnetic Flux

Canonical name

Symbol

Symbol aliases

weber

Wb

—

Magnetic Flux Density

Canonical name

Symbol

Symbol aliases

tesla

T

—

Mass

Canonical name

Symbol

Symbol aliases

atomic_mass_unit

u

—

carat

ct

—

dalton

Da

—

grain

gr

—

gram

g

—

karat

Kt

—

kilogram

kg

—

long_ton

long_ton

—

ounce

oz

—

pound

lb

—

short_ton

tn

—

stone

st

—

tonne

t

—

Plane Angle

Canonical name

Symbol

Symbol aliases

arcminute

′

arcmin

arcsecond

″

arcsec

degree

°

deg, Ëš

gradian

gon

—

microarcsecond

µas

uas

milliarcsecond

mas

—

radian

rad

—

revolution

rev

—

turn

tr

pla

Power

Canonical name

Symbol

Symbol aliases

horsepower

hp

—

watt

W

—

Pressure

Canonical name

Symbol

Symbol aliases

atmosphere

atm

—

bar

bar

—

millimetre_of_mercury

mmHg

—

pascal

Pa

—

pounds_per_sqinch

psi

—

torr

Torr

—

Radiant Flux

Canonical name

Symbol

Symbol aliases

watt

W

—

Solid Angle

Canonical name

Symbol

Symbol aliases

steradian

sr

—

Speed

Canonical name

Symbol

Symbol aliases

kilometre_per_hour

kph

—

knot

kn

—

mile_per_hour

mph

—

Stress

Canonical name

Symbol

Symbol aliases

pascal

Pa

—

Temperature

Canonical name

Symbol

Symbol aliases

degree_celsius

°C

ºC, oC, degC, Cel, ˚C

degree_fahrenheit

°F

ºF, oF, degF, Fah, ˚F

kelvin

K

—

Time

Canonical name

Symbol

Symbol aliases

day

d

—

hour

h

—

minute

min

—

second

s

—

week

wk

—

century_julian

cy_jul

—

year_julian

a_jul

—

year_sidereal

a_sid

—

year_tropical

a_trop

—

Velocity

Canonical name

Symbol

Symbol aliases

kilometre_per_hour

kph

—

knot

kn

—

mile_per_hour

mph

—

Volume

Canonical name

Symbol

Symbol aliases

barrel_beer_us

bbl_beer

—

barrel_oil

bbl_oil

—

cubic_centimetre

cm³

cc

cubic_decimetre

dm³

—

cubic_foot

ft³

—

cubic_inch

in³

—

cubic_kilometre

km³

—

cubic_metre

m³

—

cubic_mile

mi³

—

cubic_millimetre

mm³

—

cubic_yard

yd³

—

cup

cup

—

cup_imp

cup_imp

—

cup_jp

cup_jp

—

cup_us

cup_us

—

dessert_spoon

dsp

—

fluid_dram_imp

fldr_imp

—

fluid_dram_us

fldr_us

—

fluid_ounce_imp

floz_imp

—

fluid_ounce_us

floz_us

—

gallon_imp

gal_imp

—

gallon_us

gal_us

—

gill_imp

gill_imp

—

gill_us

gill_us

—

litre

L

l

pint_imp

pt_imp

—

pint_us

pt_us

—

quart_imp

qt_imp

—

quart_us

qt_us

—

tablespoon

tbsp

—

tablespoon_au

tbsp_au

—

tablespoon_imp

tbsp_imp

—

tablespoon_us

tbsp_us

—

teaspoon

tsp

—

teaspoon_imp

tsp_imp

—

teaspoon_us

tsp_us

—

Work

Canonical name

Symbol

Symbol aliases

joule

J

—

kilowatt_hour

kWh

—

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/sc-functionindex.html000066400000000000000000000744451526573132500312330ustar00rootroot00000000000000 Function Index

Function Index

a | b | c | d | e | f | g | h | i | l | m | n | o | p | r | s | t | u | v | x
 
a
abs()
absdev()
and()
arccos()
arcosh()
arcsin()
arctan()
arctan2()
arsinh()
artanh()
average()
 
b
bin()
binomcdf()
binommean()
binompmf()
binomvar()
binpad()
 
c
cbrt()
ceil()
cis()
cisform()
cols()
conj()
corrp()
corrs()
cos()
cosh()
cot()
count()
covp()
covs()
cross()
csc()
 
d
datetime()
dec()
degrees()
det()
dms()
dot()
 
e
emod()
eng()
epoch()
erf()
erfc()
exp()
expform()
 
f
flatten()
floor()
frac()
 
g
gamma()
gcd()
geomean()
gradians()
 
h
hex()
hexpad()
hypercdf()
hypermean()
hyperpmf()
hypervar()
 
i
idiv()
ieee754_decode()
ieee754_double_decode()
ieee754_double_encode()
ieee754_double_residual()
ieee754_encode()
ieee754_float_residual()
ieee754_half_decode()
ieee754_half_encode()
ieee754_half_residual()
ieee754_quad_decode()
ieee754_quad_encode()
ieee754_quad_residual()
ieee754_round_double()
ieee754_round_float()
ieee754_round_half()
ieee754_round_quad()
ieee754_single_decode()
ieee754_single_encode()
imag()
int()
inv()
 
l
lcm()
ln()
lngamma()
log()
log10()
log2()
 
m
mad()
mask()
mass()
max()
mean()
median()
min()
mod()
molarity()
molmass()
 
n
ncr()
norm()
not()
npr()
numval()
 
o
oct()
octpad()
or()
 
p
phase()
phasorform()
poicdf()
poimean()
poipmf()
poivar()
popcount()
powmod()
product()
 
r
radians()
rand()
randint()
rank()
rat()
ratio()
rational()
real()
rectform()
root()
round()
roundeven()
rows()
 
s
sci()
sec()
sgn()
shape()
shl()
shr()
sin()
sinh()
sqrt()
stdevp()
stdevs()
sum()
summation()
 
t
tan()
tanh()
trace()
transpose()
trigform()
trunc()
turns()
 
u
unmask()
 
v
varp()
vars()
 
x
xor()
heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/000077500000000000000000000000001526573132500270435ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/advanced.html000066400000000000000000001016361526573132500315050ustar00rootroot00000000000000 User-Defined Variables, Functions and Units

User-Defined Variables, Functions and Units

Variables

When working on more sophisticated problems, you will likely find that you frequently need to access results from previous computations. As we have already seen, you can simply recall results from the result window. However, SpeedCrunch also offers another more powerful way: Variables. Variables allow you to store and recall any value, by assigning it a name. Variables are defined using the variable=value syntax:

a = 5.123

You can attach a comment to the definition by appending ? and text:

a = 5.123 ? calibration value

This comment is displayed in the User Variables dock widget and in autocomplete suggestions.

Now you can access this value via the name a much like you would use a built-in constant like pi.

Naturally, when assigning a value, the right-hand-side can be an arbitrarily complex expression:

mass = 100+20
= 120

g = 9.81
= 9.81

weight = mass*g
= 1177.2

somethingelse = ln(sqrt(123) + ans)
= 7.08027102937165690787

As you see, using descriptive variable names can make the calculation history much more readable.

User Functions

Added in version 0.12.

Just as you can define your own variables, it is also possible to define your own functions. While SpeedCrunch comes with an extensive collection of built-in functions (Function Index), defining your own functions can be very useful when you find yourself repeating a similar computation over and over again.

Defining a custom function is similar to defining a variable:

f(x) = 5*x+8

Function definitions can also include a trailing comment:

f(x) = 5*x+8 ? affine transform

Like variable comments, this comment is shown in the Functions dock widget and in autocomplete suggestions.

You can now use the new function f just like any of the built-in ones:

f(5)
= 33

Functions with more arguments are possible as well; simply separate the parameters with a semicolon:

f(x; y) = x*y + x

f(2; 3)
= 8

Units

Added in version 0.12.

SpeedCrunch includes a powerful system for units and unit conversions. It provides an extensive list of built-in units and easily allows you to define your own.

Units are attached to the term on their left using square brackets:

5 [ft]
= 1.524 [m]

If the left-hand side is parenthesized, the bracket applies to the whole parenthesized expression:

(5+6)[ly]
= 11 [ly]

To raise a quantity to a power, put the value and its unit inside parentheses:

(2[m])²
= 4 m²

(2[m])^(-2)
= 0.25 m�²

The power applies to both the value and the unit. Parentheses also let you raise a compound expression to a power, such as (2[m]/1[m])^(-2) = 0.25. Input such as 2[m]^2 is rejected because it is ambiguous. Use (2[m])^2 to square the whole quantity, or 2[m^2] to enter two square metres.

By default SpeedCrunch converts the quantity into SI units:

60[mi/h]
= 26.8224 [m⋅s�¹]

This alone would not be terribly useful. However, it is possible to convert the value to a different unit using the conversion operator -> (in can be used as an alias):

50[yd] + 2[ft] in [cm]
= 4632.96 [cm]

10[kn] -> [km/h]
= 18.52 [km/h]

Displayed value-unit formatting uses a narrow no-break space (U+202F) between the numeric value and the unit block, for example 1.23 [m]. Input accepts unit attachment with or without that separator (for example both 1[m] and 1 [m]).

In the result display, final value-with-unit result lines are shown without unit brackets (for example 1.23 m) to improve readability. Interpreted and simplified expression lines keep bracketed units (for example → [m]) so conversion targets remain explicit. When a result is inserted back into the editor (for example by double-clicking), SpeedCrunch uses canonical bracketed unit syntax again.

Note that all built-in unit names are singular and use American English spelling. This is independent of the language selected for SpeedCrunch’s interface.

As seen in the example above, you can use any SI prefixes such as k or c. They are treated like any other unit, so separate them with a space from the base unit they refer to inside brackets. For astronomical distances, pc supports positive SI-prefixed forms such as kpc and Mpc.

Since units are now explicit in brackets, short identifiers such as a, mg and l are free to use as variable names without conflicting with units.

Information units (bit/byte)

For the information dimension, SpeedCrunch supports both bit (short form b) and byte (short form B).

Prefixes

Positive SI prefixes are accepted for both families (for example kB, MB, kb, Mb), while negative SI prefixes are rejected.

Family mixing rules

When adding/subtracting information quantities, SpeedCrunch does not implicitly mix bit-family and byte-family values. Use an explicit conversion if you want to switch family:

1[B] + 8[b]
= error

1[B] + (8[b] -> [B])
= 2 [B]

Result unit selection

For sums inside the same family, the displayed result keeps the coarsest unit used in the expression:

2[MB] + 3[PB] + 4[TB]
= 3.004000002 [PB]

Warning

Prefixes cannot be used on their own. Always attach them to a unit symbol. For instance, if you intend to express the unit ‘newtons per centimeter’, do not type [N / c m]. Make the order explicit with [N / (cm)].

An important feature of SpeedCrunch’s unit system is dimensional checking. Simply put, it prevents comparing apples and pears: if you try to convert [s] to [m], SpeedCrunch will complain, stating that the dimensions do not match. Indeed, the dimension of s is time, while m denotes a length, thus they cannot be compared, added, etc. When adding, multiplying, or otherwise manipulating units, SpeedCrunch will track the dimension and raise an error if it detects an invalid operation. For instance, if you type [m^2], the result will be a quantity with the dimension length2 which can only be compared to other quantities with the same dimension. Currently, the available dimensions and their associated primitive units are:

  • Length: m

  • Mass: kg

  • Time: s

  • Electric current: A

  • Amount: mol

  • Luminous intensity: cd

  • Temperature: K

  • Information: b

Temperature conversions also support the affine scales degree_celsius (short form °C) and degree_fahrenheit (short form °F). The input aliases ºC, ˚C, ºF and ˚F are accepted and normalized to °C and °F:

77 [°F] -> [°C]
= 25 [°C]

25 [°C] -> [K]
= 298.15 [K]

298.15 [K] -> [°C]
= 25 [°C]

77 [°F] -> [°C]
= 25 [°C]

Defining a custom unit uses bracketed unit assignment:

[earth_radius] = 6730[km]

3.5[au] in [earth_radius]
= 77799.78416790490341753343 [earth_radius]

Any variable or expression can be used as the right-hand side of a conversion expression:

10[m] in (1[yd] + 2[ft])
= 6.56167979002624671916 (1[yd] + 2[ft])

Use unit symbols by default (for example m, s, B, b). Full built-in names are accepted as an alternative input form.

Built-in short forms include:

  • Length/astronomy: au (astronomical_unit), ly (lightyear), ls (lightsecond), lmin (lightminute), pc (parsec), in (inch), ft (foot).

  • Time: min (minute), h (hour), cy (century).

  • Angle: deg (degree), gon (gradian).

  • Information: b (bit), B (byte).

  • Other common aliases: u/Da (atomic_mass_unit), nmi (nautical_mile).

For units that allow prefixes, the same short forms can be used in prefixed form as well (for example kpc, Mpc, MB, kb). Common examples include mm, cm, km, mg, kg, mV, kW, MeV, dL and dl.

SI-accepted mass unit t (full name tonne) is available and equals 1000[kg]:

1[t] -> [kg]
= 1000 [kg]

1000[kg] -> [t]
= 1 [t]

User Units

You can define your own unit identifiers using square brackets on the left-hand side:

[two_cubic_metres] = 2[m^3]
[ten_metres] = 10[m]
[cm_s] = [cm/s]

User unit definitions can also include a trailing comment:

[cm_s] = [cm/s] ? centimeters per second

Like user variables and functions, comments are shown in the corresponding dock widget and in autocomplete suggestions.

Some of the built-in functions are able to handle arguments with a dimension. Refer to the documentation of a particular function for more information.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/first_steps.html000066400000000000000000000353351526573132500323070ustar00rootroot00000000000000 First Steps

First Steps

SpeedCrunch is designed to be used via the keyboard. While an on-screen keypad is available, it defaults to the Basic layout. The powerful keyboard interface is the recommended way to use SpeedCrunch to get the most out of it. The keypad layout can be configured from: View ‣ Keypad.

Note

All examples in this manual use a period (.) as the decimal separator. By default, SpeedCrunch will use your system’s default decimal separator for output and will accept both a period and a comma (,) for input (more details). Depending on your settings, it may be necessary to replace the periods with the appropriate decimal separator when entering these examples into SpeedCrunch.

When starting SpeedCrunch for the first time, the interface may thus seem a little plain. Don’t be fooled, it can easily be customized. At the bottom edge of the window, you see the the input bar, also called the editor, with a blinking cursor showing that it is ready to accept keystrokes. To try out SpeedCrunch, type:

1.234 + 7.89

then hit Enter to evaluate the expression. The result (along with the expression you just entered) will be displayed at the top of window:

1.234 + 7.89
= 9.124

This region (called the result window) not only shows the result of your last calculation, it is a complete browsable history. Any previous input or result can be recalled by double-clicking the corresponding line.

Let’s try this out. First, perform some more calculations so that more than one entry is displayed in the result window:

54*4.514 + 57
= 300.756

54*(4.514 - 5.7)
= -64.044

Note how multiplication (*) takes precedence over addition (+) unless parentheses are used to specify a particular order of evaluation. If you now wish to continue working with one of the results, double-click e.g. the line = 300.756. The input bar will be populated with this result. Similarly, you can also quickly recall previous input by double-clicking them in the result history. Alternatively, depending on Settings ‣ Editing ‣ Up/Down Arrow History, you can use the Up and Down arrow keys on your keyboard to recall previous expressions, or use the mouse wheel for the same effect (the mouse cursor must be hovering over the editor for this to work, otherwise the result window will be scrolled).

To continue the computation directly from the previous result, you can use the special variable ans which always holds the result of the last entry in the history. Try this:

2+3         ? By the way, you can use question marks for comments.
= 5

7*ans       ? 'ans' is now equal to 5
= 35

ans + 3
= 38

You can also write comment-only entries. Any line whose first non-space character is ? is treated as a comment and stored in the history:

? start algorithm

  ? this comment is also valid

As you can see, ans provides a quick and easy way to access the previous result. Sometimes, SpeedCrunch can even insert ans for you: When you start a new expression with an operator (e.g. +, -, *, /, ^), ans will be prepended automatically. [1] To try it out, type 7 Enter +3 Enter. SpeedCrunch expands this as follows:

7
= 7

ans+3
= 10

SpeedCrunch comes with a number of mathematical constants like π that are available by typing their name:

pi
= 3.14159265358979323846

pi*1.2^2
= 4.52389342116930226339

Let us finish this short introduction with a word about functions. SpeedCrunch comes with an extensive list of built-in mathematical functions which can be accessed by simply typing their name in the editor followed by any parameters (also called arguments) in parentheses:

sqrt(144)
= 12

The function sqrt() calculates the square root of its argument. Some functions require or accept more than one argument. In that case, separate them with a semicolon (;). If you leave a trailing semicolon while typing, SpeedCrunch treats it as an incomplete final argument and still evaluates the expression (for example average(2;3;4;) and average(2;3;4;).

Warning

To repeat: In contrast to many programming languages, parameters in SpeedCrunch are separated by a semicolon!

An example is the average() function:

average(12;34;56)
= 34

This is already enough to use SpeedCrunch effectively. Try it out for yourself! Alternatively, read on to learn about its more advanced features.

Footnotes

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/index.html000066400000000000000000000160711526573132500310450ustar00rootroot00000000000000 User Guide heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/installation.html000066400000000000000000000251531526573132500324400ustar00rootroot00000000000000 Installation

Installation

Microsoft Windows

SpeedCrunch for Windows requires Windows Vista or newer (32-bit and 64-bit versions). You can use choose to use either the installer or the portable version of SpeedCrunch. Both of these are available from the SpeedCrunch website.

The installer installs SpeedCrunch on your system and creates an entry in the menu to launch it. This process requires administrator rights.

Alternatively, you may use the portable version of SpeedCrunch, which is distributed as a .zip archive. This version requires no installation, simply extract it to a folder of your choice and run speedcrunch.exe. In addition, this version of the software is fully portable: It stores all its settings and user data next to the executable so the entire directory can be copied to another computer and run there.

macOS

SpeedCrunch requires macOS 14.4 (Sonoma) or later.

Download the macOS disk image from the SpeedCrunch website, open it, and drag SpeedCrunch to the Applications folder.

On first launch, macOS may block SpeedCrunch because it cannot verify the developer. Only continue if you downloaded SpeedCrunch from the official website and trust the download. Try to open SpeedCrunch once, then:

  1. Open the Apple menu and choose System Settings > Privacy & Security.

  2. Scroll to Security and click Open or Open Anyway next to SpeedCrunch.

  3. Confirm that you want to open the app. Enter your Mac password if asked.

The Open Anyway option is available for about an hour after your first attempt. macOS remembers the exception, so you can open SpeedCrunch normally afterward. See Apple’s step-by-step instructions.

Linux

On Linux, SpeedCrunch can be installed either from packages provided by your distribution or from official Flatpak packages.

Distribution Packages

Many Linux distributions already include packages for SpeedCrunch in their repositories. The exact steps to install these depend on the distribution. For example, on Debian and Ubuntu, the included SpeedCrunch package can be installed by running this command:

sudo apt-get install speedcrunch

On Fedora, this command will install SpeedCrunch:

sudo dnf install speedcrunch

Check your system’s documentation to find out how to install additional packages. Many desktop distributions also include graphical package management software that can be used to install SpeedCrunch.

Flatpak

Flatpak is a distribution-independent packaging format for Linux desktop applications. The latest stable release of SpeedCrunch is available as a Flatpak package from Flathub.

First, visit Flathub’s setup page and follow the instructions for your distribution to set up Flatpak and Flathub. Then install SpeedCrunch from its store page on Flathub.

Building from Source

The SpeedCrunch source code is maintained on GitHub in a Git repository. For build requirements and instructions on compiling, running the tests, and installing from source, see BUILDING.md at the repository root.

License installation is optional on every platform. The CMake option INSTALL_LICENSES defaults to OFF. Set -DINSTALL_LICENSES=ON to install SpeedCrunch’s license text and Qt usage notice. On Windows and macOS, this also installs the license texts and notices for bundled Qt components. Windows also installs COPYING.rtf beside the application.

Both BUILD_VARIANT_OFFICIAL_RELEASE and BUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE force INSTALL_LICENSES=ON, even when -DINSTALL_LICENSES=OFF is supplied. BUILD_VARIANT_DEV_DEBUG leaves the option unchanged. CMake keeps the value in its cache when a variant is disabled. To stop installing license files in an existing build directory, disable the official variant and set -DINSTALL_LICENSES=OFF.

Package providers can leave license installation disabled and use their own packaging tools to include the required license files, such as Fedora’s %license LICENSE directive.

Stripping debug symbols is also disabled by default on every platform. Both official release variants force STRIP_BINARY=ON. Otherwise, the application keeps the symbols generated by the compiler unless you explicitly enable this option. The option applies to the selected build configuration, including Debug. Package providers should leave it off so their packaging tools can extract debug information. When disabling an official variant in an existing build directory, also set -DSTRIP_BINARY=OFF to reset the cached value.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/interface.html000066400000000000000000002566661526573132500317160ustar00rootroot00000000000000 User Interface

User Interface

Shortcut notation: Ctrl means Ctrl on Windows/Linux and Cmd on macOS. Platform-specific shortcuts spell out Cmd when they differ from this convention.

Widgets

Apart from the main display, SpeedCrunch offers a number of extra panels, referred to as widgets here. Most of them are dockable panels that can be moved around the main window and enabled or disabled via the View menu.

Panels docked on the left or right fill the available height. Panels above or below the display and keypad fit between the side panels.

Use the cross in a dock panel’s title bar to hide the panel, or the square to detach it into a floating window. Hidden panels can be shown again via the View menu. Opening another panel leaves floating panels in their own windows.

On Linux with Wayland, drag a floating panel by its title bar to move it. Use its square button or double-click the title bar to attach it to the main window again.

Drag a table’s column headers to change their order. Each window keeps its column order between launches, including for panels that are hidden.

  • Formula Book

    The formula book provides access to commonly used formulas and calculations. Simply insert a formula into the expression editor by clicking on it.

    You can help expanding the formula book by posting your requests to the issue tracker.

  • Constants

    The constants widget shows a large list of scientific constants (including CODATA-based entries), grouped by category and subcategory.

    The columns show each constant’s name, value, and unit. Use the Domain and Subdomain selectors to narrow the list, or search by name or unit. Press Up and Down in the search field to select a result while continuing to type. Press Enter or double-click an entry to insert its value and unit and return to the editor. The mathematical constants pi and Euler’s number are inserted as π and e.

  • User Variables

    The variables widget lists all user-defined variables. Any of them can be inserted into the editor by double-clicking it. Additionally, it is possible to delete a variable by selecting it and pressing the Delete key on your keyboard.

  • Functions and User Functions

    Similar to the variables widget, these show built-in and user-defined functions respectively.

  • User Units

    Similar to the user functions widget, this lists user-defined units. Double-click inserts [name] in the editor, and the context menu supports edit/delete operations.

  • Bit Field

    The bit field dock is designed to make working with binary numbers easier. It shows a field of 64 squares, each representing a bit in the current result. Any bit can be toggled by clicking its square; the resulting number is automatically inserted into the editor. Additional buttons allow you to shift, invert and reset all the bits at once. While the mouse cursor is hovering over the bit field, scrolling the mouse wheel will also shift the bits.

  • Keypad

    The on-screen keypad provides clickable input for common operations and symbols. It supports multiple presets and a custom layout, so you can adapt it to your workflow. You can also adjust the keypad zoom level for better readability or touch area on touchscreens. For fast and full-featured input, SpeedCrunch’s keyboard interface is still recommended.

    Available entries in View ‣ Keypad are:

    • Basic (default)

    • Scientific (wide)

    • Scientific (narrow)

    • Custom...

    • Disable (shown as Disabled when selected)

    Both scientific layouts include ln for the natural logarithm and log10 for the common (base-10) logarithm. These buttons insert ln( and log10(, respectively. Copying a scientific preset into a custom layout uses the same labels and function names.

    Since version 1.1, both scientific layouts show �√ for the nth root in place of the cube-root button. It inserts root( so you can enter a root index and a value, for example root(5; 32). Copying either scientific preset into a custom layout includes this button.

    The scientific layouts also include x², which inserts ^2, and ; to separate function arguments. These replace the x and x= shortcuts in version 1.1. Related buttons sit together: √ and x², xʸ and �√, E and exp, ln and log10, and each trigonometric function with its inverse.

    Available entries in Settings ‣ Appearance ‣ Keypad ‣ Zoom are:

    • 50%

    • 100% (default)

    • 150%

    • 200%

    The zoom level scales the keypad buttons, including their text. Each window keeps its own zoom level. The Zoom submenu is unavailable while the keypad is disabled. You can also right-click the keypad and choose Zoom.

    Custom... opens a dialog where you can define the keypad matrix size (rows and columns) and configure each button individually. For each position in the matrix, you can set:

    • The button label shown in the keypad

    • The button behavior: Insert text, Backspace, Clear expression, or Evaluate expression

    • The text to insert (for Insert text behavior)

    The dialog also includes a Copy preset selector with an Apply button, so you can start from the Basic, Scientific (wide), or Scientific (narrow) layout and then customize it.

    Custom keypad settings are saved and restored automatically.

    You can also right-click directly on the keypad to open the same menu as View ‣ Keypad.

    Added in version 1.0.

    Changed in version 0.11: The keypad was removed in SpeedCrunch 0.11; however, it was added back in 0.12.

  • History

    The history widget lists all previous inputs. Double-click a line to recall it. Note that the main result display also provides this functionality.

  • Main Menu

    Toggle the main menu bar visibility via View ‣ Main Menu. This option is available on Windows and Linux. On macOS, this option is not available because the application menu is managed by the system menu bar (outside the window), so SpeedCrunch cannot hide it like on Windows and Linux. On Windows and Linux, when the top main menu is hidden, a navigable Main Menu (mirroring the top menu structure) is available from the right-click context menu on the result-display.

    Added in version 1.0.

Session Tabs and Panes

When a pane contains more than one session, SpeedCrunch shows a tab bar above the result display. Click a tab to switch sessions, drag tabs horizontally to reorder them within the pane, or drag a tab away from the tab bar to move it to another pane. Dropping a dragged tab outside the current window creates a new window for that session; dropping it on a pane in another SpeedCrunch window moves it there. Use Session ‣ Rename… to rename the active session. You can also double-click its tab, choose Rename… from the tab context menu, or choose Session ‣ Rename… from the result display context menu. Choose Session ‣ Clone… to copy the active session under a new name, including its unfinished expression. This command is also available as Clone… in the tab context menu and Session ‣ Clone… in the result display context menu. Use Session ‣ New Window to open a blank session in a new window that copies the current window and dock layout. Choose Session ‣ Close Tab to close the active tab, or Session ‣ Reopen Closed Tab to restore the last ordinary tab you closed. Private tabs cannot be reopened. Both commands are also available from the tab context menu. When a floating dock has focus, session commands apply to its window. Use View ‣ Split to add a pane in any direction, and View ‣ Close Pane to close the active pane. The tab context menu also provides Split and Close Pane.

The tab context menu’s Clear command removes the session’s calculations, unfinished expression, variables, functions, and units after confirmation. Global user definitions are kept. Delete removes the session itself after confirmation. When SpeedCrunch restores multiple windows after a restart, each window keeps its own dock layout, dock visibility, keypad visibility, layout and zoom, and—when window position saving is enabled—its own size and position.

Private Sessions

Use Session ‣ New Private Tab or Ctrl+Shift+N (Cmd+Shift+N on macOS) to open a session that stays in memory. Private sessions are named Private-1, Private-2, and so on, using the first available number. A shield icon marks their tabs. The window title also identifies the active private session, even after you rename it. The tab bar is hidden when a private session is the only session in a single pane, just as it is for an ordinary session.

Private sessions do not save their history, unfinished expressions, variables, functions, or units automatically. They are excluded from the workspace restored at the next launch. Closing a private session discards its contents, and it cannot be reopened with the Restore Closed Tab shortcut. Copying and explicit export remain available. Cloning a private session creates another private session.

Choose Session ‣ Keep to save a private session, including its current contents. It receives the first available Untitled-XXX name and behaves like an ordinary session from then on.

Choose Session ‣ Make Private… to convert an ordinary session. SpeedCrunch asks for confirmation before deleting its saved JSON file. Its contents stay open under the first available Private-XXX name until you close it or exit. If the file cannot be deleted, the session remains ordinary. If a private session cannot be saved during conversion, it remains private.

These actions are also available from the tab and result display context menus. In the result display, open the Session submenu and choose Keep or Make Private…. Privacy belongs to the session, so renaming it does not change whether it is saved. Ordinary sessions can remain open alongside private ones.

Enable Settings ‣ Window ‣ Open a Private Tab on Startup to open and focus a fresh private tab whenever SpeedCrunch starts. This option is off by default. Saved ordinary sessions are restored as usual, with one new private tab in the active window, even when several windows are restored. An empty active Untitled-XXX session is used for the private tab instead of opening an extra ordinary tab. Sessions with history, unfinished expressions, or their own definitions stay open. When there are no sessions to restore, SpeedCrunch starts with just the private tab. Opening another window while the app is running still creates an ordinary session.

Added in version 1.1.

Expression Editor Features

Turn off Settings ‣ Editing ‣ Automatic Input Adjustments to enter text without automatic text adjustments or character restrictions.

The expression editor provides some advanced features:

  • Undo and redo

    Choose Edit ‣ Undo or Edit ‣ Redo. Press Ctrl+Z to undo the last edit. On Windows/Linux, use Ctrl+Shift+Z or Ctrl+Y to redo it. On macOS, use Cmd+Shift+Z. Each key press is a separate undo step. Automatic changes made by that key, such as inserting a closing bracket or converting an exponent to superscript, are undone together. Text committed through an input method is undone as a single edit.

    Edit ‣ Cut cuts selected input text. Copy also works on selected result text. These actions are disabled when unavailable. Edit ‣ Wrap in Parentheses wraps the selected input, or the whole expression if nothing is selected.

  • Automatic closing parentheses and square brackets

    Typing ( or [ with no text selected inserts the matching closing character only when the cursor is at the end of the expression or only whitespace follows it. The cursor stays between the pair. If non-whitespace text follows the cursor, only the opening character is inserted.

  • Autocompletion

    If you start typing a name (e.g. of a variable, function, or unit), a pop-up with matching names will appear below the editor, aligned with the start of the name being completed. It appears above the editor when there is insufficient space below and shifts horizontally to stay on screen. The list becomes shorter and scrollable when needed to avoid covering the editor. On Wayland with Qt 6.6 or later, the compositor chooses below or above according to the available screen space. With older Qt versions on Wayland, the list stays within the application window. Alignment follows the visible text even when the expression wraps or scrolls. Press Tab to insert the current suggestion. Pressing Enter evaluates the expression by default. If you explicitly navigate the popup with arrow/page/home/end keys or click a suggestion with the mouse, then Enter accepts that selected suggestion. Enable Settings ‣ Editing ‣ Autocomplete ‣ Accept with Enter to accept the current suggestion with Enter immediately, without first using the arrow keys. Pressing Escape dismisses the autocomplete popup.

  • Function signature tooltip

    While typing a function call, the live result area can show the function signature (parameter list). The parameter currently being edited is highlighted. This also works for user-defined functions. Pressing Escape will dismiss the tooltip.

  • Quick constant insertion

    Press Ctrl+Space to search the same constants as the constants widget (see above). Type a name or unit to filter the list. Each result shows its unit beside the name using the theme’s unit color. Press Up and Down to select a result. Press Tab or Enter, or click a result, to insert it and return to the editor. Shift+Tab moves focus backward. With no matches, Tab leaves the popup open. Press Escape to cancel. Search text does not change the expression. The list follows the cursor’s horizontal position and uses the same below-or-above placement rules as autocompletion.

    Added in version 1.1: Search in the quick constant popup and select dock search results with Up and Down.

  • Context help

    Pressing F1 will show the manual page for the function under the cursor, providing quick access to detailed usage information for a function. Pressing Escape will dismiss the manual window again.

  • Selection results

    If Settings ‣ Results ‣ Show Live Result Preview is enabled, selecting a partial expression in the expression editor or in the result display will show you the result of the selected expression. You can dismiss this preview by pressing Escape or by clicking the × button at the top-right corner of the preview.

Import/Export

SpeedCrunch automatically stores your sessions and lets you restore them with Session ‣ Open. Use Session ‣ Open Sessions Folder to open the folder where SpeedCrunch stores these session files when you want to back them up or clean them up manually. You can also export the current session as JSON (Session ‣ Export ‣ JSON) and later import it with Session ‣ Import. The data is stored in a SpeedCrunch-specific file format. [1] While the session files are human-readable, they are designed for use by SpeedCrunch. If you want to export your calculations to work on them in another program or hand them to a colleague, the other export options are preferable.

Import validates the selected JSON file as a SpeedCrunch session and opens it as a new tab. If the file is not valid SpeedCrunch session JSON, SpeedCrunch shows an error and leaves the current session unchanged.

You can export the session as HTML (Session ‣ Export ‣ HTML). The resulting file will consist of the contents of the result display and can be viewed in any web browser. This feature can also be used to print a SpeedCrunch session by printing the exported HTML document. Since the syntax highlighting and color scheme are maintained in the HTML output, it is recommended to select a color scheme with a white background (e.g. Standard) prior to exporting if you intend to print the document.

The final, most basic option is to export your session as a plain text file (Session ‣ Export ‣ Plain text). In contrast to the HTML export option, the syntax highlighting will be lost.

User Definitions

Added in version 1.0.

To define user variables, user functions and user units that are loaded globally, use Settings ‣ User Definitions….

This dialog provides:

  • A multi-line editor (one definition per line), with syntax highlighting and line numbers.

  • A clear reminder that these definitions are global, loaded into every session and override same-name session definitions.

  • Apply to apply definitions immediately.

  • Validate to validate and preview results without applying.

When applying or testing, SpeedCrunch reports:

  • Imported variable count

  • Imported function count

  • Imported unit count

  • Line numbers with errors

Invalid definitions are ignored. Variable definitions that evaluate to NaN are also ignored.

Settings

SpeedCrunch’s behavior can be customized to a large degree using the configuration options in the Settings menu. This section explains the settings that are available.

Resetting Settings

Choose Settings ‣ Reset All Settings… to restore the default preferences. SpeedCrunch asks for confirmation before making any changes. The reset applies to all open windows immediately and is saved for the next launch. It includes appearance, editing options, number and result formats, language, and window preferences, including dock visibility and keypad settings.

Your calculation history, open session tabs and panes, and user definitions are kept. Existing calculations keep their recorded result formats. New calculations and live previews use the default settings.

Added in version 1.1.

Result Display Interactions

The result display supports mouse-driven interactions for navigation and editing.

  • Right-click context menu

    Right-clicking an expression/calculation block in the result display opens a context menu for that specific block. The Copy submenu starts with Selection to copy the selected text. Select All selects all text in the display. Open the Copy submenu and choose Calculation to copy all displayed lines of the calculation at once, including the expression, any simplification, and every result format. The lines are copied as plain text in the order shown, without the blank line between calculations. Expression and Result let you copy either part separately. Remove offers This Calculation, All Calculations Above, and All Calculations Below. This menu includes an entry to toggle the main menu bar visibility. Use its Split submenu to add a pane to the left, right, above, or below the current pane. New Tab and New Private Tab create sessions directly. The Session submenu starts with Open…, Import…, and Export. It also groups actions to duplicate, rename, change privacy, clear, delete, or close the current session.

    Added in version 1.0.

    The Copy submenu also offers Calculation as Single Line to join all displayed lines of the calculation with spaces, for example 120 / 8 = 15.

    Added in version 1.1.

  • Hover highlighting of calculation blocks

    When Settings ‣ Appearance ‣ Hover Highlighting is enabled, moving the mouse over the result display highlights the calculation block under the cursor. The highlighted block also shows quick-action icons for deleting, editing, and copying.

    Added in version 1.0.

  • History rewriting from highlighted blocks

    From the hovered/highlighted calculation block, you can re-edit an earlier expression and apply it as a history rewrite. SpeedCrunch then recalculates all expressions below that edited entry.

    Added in version 1.0.

  • Calculation settings from highlighted blocks

    The calculation settings action opens a tabular layout with one mandatory Main Line row and four optional extra result-line rows. The table shows line enablement, notation, and decimal places together so the stored calculation context can be adjusted before SpeedCrunch recalculates the affected history.

Notation

This section allows selecting the result notation to use (for example in Settings ‣ Results ‣ Notation & Precision… or from the status-bar notation selector). You can select one of the following options. On first launch, the default is Automatic decimal.

  • Automatic decimal

    Use fixed-point decimal form for most results; values with exponent larger than 14 or smaller than -9 are shown in scientific notation. With a finite precision setting, very small values may switch to scientific notation earlier.

  • Fixed-point decimal

    Display results in fixed-point decimal form. For excessively large or small numbers, this format may still fall back to scientific notation.

  • Engineering decimal

    Display results in engineering notation. This is a variant of scientific notation in which the exponent is divisible by three.

  • Scientific decimal

    Display results in normalized scientific notation.

  • Rational

    Try to display real results as fractions (for example, 1/3) using continued-fraction approximation with bounded denominator. If no close match is found, results are displayed in decimal form. For common trigonometric and inverse-trigonometric results, SpeedCrunch prefers symbolic exact forms such as pi/2, 7â‹…pi/6, 1/2, sqrt(2)/2, and sqrt(3)/3. Example:

    arcsin(1)
    = pi/2
    
    sin(45)    (angle mode = degree)
    = √(2)/2
    
    arcsin(sqrt(3)/22)
    = 0.07881114207211010205
    

    Added in version 1.0.

  • Binary

    Display results as binary numbers, i.e. in base-2.

  • Octal

    Display all results as octal numbers, i.e. in base-8.

  • Hexadecimal

    Display all results as hexadecimal numbers, i.e. in base-16.

  • Sexagesimal

    Display dimensionless and time results as sexagesimal values, i.e. with minutes and seconds. All other results are displayed in fixed-point decimal form.

    Added in version 1.0.

Angle Mode

Select the angular unit to be used in calculations. For functions that operate on angles, notably the trigonometric functions like sin() or cos(), this setting determines the angle format of the arguments.

  • Radian

    Use radians for angles. A full circle corresponds to an angle of 2Ï€ radians.

  • Degree

    Use degrees for angles. A full circle corresponds to an angle of 360°.

  • Gradian

    Use gradians for angles. A full circle corresponds to an angle of 400 gradians.

    Added in version 1.0.

  • Turn

    Use turns for angles. A full circle corresponds to an angle of 1 turn.

  • Revolution

    Use revolutions for angles. A full circle corresponds to an angle of 1 revolution.

    Added in version 1.0.

Complex Numbers

Choose a result form via Settings ‣ Results ‣ Complex Form and a symbol via Settings ‣ Results ‣ Imaginary Unit. Complex numbers are always enabled.

  • Imaginary Unit ‣ i

    Use i as the imaginary unit symbol.

  • Imaginary Unit ‣ j

    Use j as the imaginary unit symbol.

  • Complex Form ‣ Rectangular (a + bi)

    Display complex results in rectangular form.

  • Complex Form ‣ Exponential (reâ�±á¶¿)

    Display complex results in exponential form.

  • Complex Form ‣ Trigonometric (r(cos θ + i·sin θ))

    Display complex results in trigonometric form.

  • Complex Form ‣ Cis (r·cis(θ))

    Display complex results in cis form.

  • Complex Form ‣ Phasor (r∠θ)

    Display complex results in phasor form.

When the angle mode is set to radians, simple phase multiples of pi are shown symbolically in these complex forms. Other angle modes show their numeric phase values.

Number Format

Choose how decimal numbers are displayed and interpreted via Settings ‣ Number Format….

This shared setting controls result formatting and, when Settings ‣ Editing ‣ Group Digits in Input is enabled, digit grouping in the input field.

Added in version 1.0.

This dialog replaces the older separate Radix Character and Digit Grouping menus with a single combined Number Format selection.

The default option is no digit grouping with dot decimal separator (1234567.12345).

Additional options let you choose:

  • no digit grouping with dot or comma decimal separator

  • SI grouping with space separators (integer and fractional grouped in 3s)

  • 3-digit grouping with comma, dot, space, or underscore

  • Indian/South Asian 3-2-2 grouping with comma separators

Some options include grouped fractional digits; those are separate explicit choices.

The apostrophe ('), commonly used as a thousands separator in some locales and contexts (for example Switzerland, Liechtenstein, and some technical writing in Austria/Germany), is intentionally not offered because SpeedCrunch reserves it for sexagesimal notation.

For input, SpeedCrunch remains permissive across styles to support copy/paste from other applications. In clear mixed-separator cases, it accepts the number and normalizes it by ignoring non-digit grouping characters as needed.

History Size Limit

This setting controls how calculation history is stored for the active session. It is available from Session ‣ History Size Limit….

Calculation history in ordinary sessions is saved automatically when a session changes and restored on the next launch. Private sessions keep history only while they are open.

The history size limit sets the maximum number of stored history entries for that session. By default, SpeedCrunch keeps up to 1000 entries per session and automatically removes the oldest ones when this limit is exceeded. When a calculation fills the last available history slot, SpeedCrunch warns that future calculations will remove the oldest calculation from that session. Set the value to 0 to disable the limit for the active session.

Added in version 1.0.

Window

This section contains settings that control the main window behavior.

  • Open a Private Tab on Startup

    Open and focus a fresh private tab after restoring saved sessions. If there are no sessions to restore, or the active session is an empty Untitled-XXX tab, start without an extra ordinary tab. This option is off by default.

  • Save Window Position on Exit

    Controls if the window position is saved and restored.

  • Always on Top

    Keep the SpeedCrunch window on top of other windows. This option is hidden on Wayland (non-X11 Linux desktop sessions), because many Wayland compositors do not honor it reliably. It remains available on Windows, macOS, and Linux X11 sessions.

Results

This section contains settings that control result output and post-evaluation behavior.

  • Show Live Result Preview

    If set, SpeedCrunch will display partial results as you type your expression as well as results when selecting a partial expression in the editor.

  • Notation & Precision…

    Open a tabular layout with one mandatory Main Line row and four optional extra result-line rows. Each row has columns for enabling the line, notation, and decimal places. Extra lines are ignored unless their row is enabled.

    Applying changes from this dialog updates only the current editor previews immediately (live/selection) without rewriting already displayed calculation history.

  • Remove Trailing Zeroes

    Hide trailing fractional zeroes after rounding to the selected decimal places. For example, at three decimal places, 3.140 becomes 3.14 and 12.000 becomes 12. This option is off by default and applies to the main and extra result lines. Changing it refreshes editor previews without rewriting displayed history.

    Added in version 1.1.

  • Rounding Mode

    Choose how displayed results are rounded when formatting to a finite number of digits. The default is Nearest, Half Away (round). Available modes are: Nearest, Half Away (round), Nearest, Half Even (roundeven), Toward Zero (trunc), Toward +∞ (ceil), Toward −∞ (floor).

    • Nearest, Half Away (round)

      Round to nearest; ties increase magnitude. This matches the round() function. Example at 1 fractional digit: 2.250 -> 2.3, -2.250 -> -2.3.

    • Nearest, Half Even (roundeven)

      Round to nearest; ties go to the nearest even last kept digit. This is Banker’s rounding and matches the roundeven() function. Example at 1 fractional digit: 2.250 -> 2.2, 2.350 -> 2.4, -2.250 -> -2.2.

    • Toward Zero (trunc)

      Discard extra digits without rounding up. This matches the trunc() function. Example at 1 fractional digit: 2.290 -> 2.2, -2.290 -> -2.2.

    • Toward +∞ (ceil)

      Always round upward. This matches the ceil() function. Example at 1 fractional digit: 2.210 -> 2.3, -2.210 -> -2.2.

    • Toward −∞ (floor)

      Always round downward. This matches the floor() function. Example at 1 fractional digit: 2.290 -> 2.2, -2.210 -> -2.3.

    This setting affects result formatting (including live previews), not the numeric value of expressions. Use the named function in parentheses when a calculation must apply the same rounding strategy explicitly. Like other result-format settings, changes apply to subsequent calculations and previews; already stored history entries keep their original display.

  • Complex Form and Imaginary Unit

    Configure the complex result form and imaginary unit. See Complex Numbers.

  • Unit Notation

    Configure whether unit results use exponential notation, such as m·s�¹, or fractional notation, such as m/s.

  • Copy New Results Automatically

    Automatically copy each newly evaluated result to the clipboard.

  • Simplify Displayed Expressions

    When enabled (default), SpeedCrunch adds an extra symbolic line before numeric results, simplifying the interpreted expression for readability (for example, combining repeated factors into powers and folding simple constant terms). This interpreted line also makes implicit-multiplication association explicit. Disable this option to keep only the unsimplified interpreted expression and numeric results.

    An extra line appears only when there is a useful reduction. For example, ans / 9 stays as written instead of becoming 1 / 9 · ans.

    Entering the expression 2.1 − 1 cos(pi)^2 cos(pi) 5 cos pi  / −cos^2(pi) + 3.4 gives the following interpretation and simplification:

    2.1�−�1�⋅�cos²(π)�⋅�cos(π)�⋅�5�⋅�cos(π)�/�(−cos²(π))�+�3.4
    = 5�⋅�cos²(π)�+�5.5
    = 10.5
    

    Added in version 1.0.

Editing

  • Automatic Input Adjustments

    Automatically replace operators, adjust spacing, insert closing brackets, convert powers to superscripts, and restrict input to valid characters. Turn it off to keep typed and pasted characters as entered. Tab still accepts the selected completion. Digit grouping and automatic insertion of ans follow their own settings. Pasting several lines evaluates each expression as usual. Invalid expressions can be entered, but still report an error when evaluated.

    This option is enabled by default. Changes apply immediately to all open editors and are saved between launches. Switching modes leaves existing text unchanged.

    Added in version 1.1.

  • Auto-Insert ans

    If a new expression starts with +, -, *, or /, SpeedCrunch inserts ans first.

  • Group Digits in Input

    Group digits as you type, using the separator and grouping pattern selected in Settings ‣ Number Format…. For example, 1000 appears as 1 000 with a space grouping format or 1,000 with a comma grouping format. This option is enabled by default. A number format with no grouping adds no separators.

    Integer digits are grouped in threes for decimal and octal numbers, or in fours for binary and hexadecimal numbers. The Indian format uses 3-2-2 grouping. Fractional digits are grouped only when the selected format includes fractional grouping. Scientific exponents are left unchanged. The separators only affect how the input looks, so copying the expression keeps the original text.

    This setting works even when syntax highlighting is disabled.

    Added in version 1.1.

  • Blinking Cursor

    Make the cursor blink in the expression editor. This option is enabled by default. Turn it off for a steady cursor. Changes apply immediately to all open session panes and windows, and the choice is saved between launches.

    Added in version 1.1.

  • Escape Clears Editor

    Press Escape to clear the focused expression editor. If a popup or result preview is open, Escape dismisses it first. Press Escape again to clear the expression. Cancelling a history edit still works as usual. This option is off by default and is saved between launches. Changes apply to all session panes and windows.

    Added in version 1.1.

  • Keep Expression After Evaluation

    If selected, the entered expression remains in the editor after evaluating it.

  • Autocomplete

    Controls how suggestions are accepted and which names appear in editor autocompletion.

    • Accept with Enter lets Enter insert the current suggestion without first selecting it with the arrow keys. It is off by default. When no autocomplete popup is open, Enter still evaluates the expression. Tab always accepts the current suggestion. The setting is saved between launches and applies to all session panes and windows.

      Added in version 1.1.

    The following suggestion categories are all enabled by default:

    • Built-in functions includes built-in function names.

    • Built-in variables includes built-in constant names.

    • Units includes spelled-out unit names (for example, meter).

    • User functions includes user-defined function names.

    • User variables includes user-defined variable names.

    The autocomplete popup also shows category icons for suggestions.

    Added in version 1.0.

  • Up/Down Arrow History

    Controls whether Up and Down in the editor navigate history:

    • Never always moves the cursor inside the editor.

    • Always (default) always navigates history.

    • Only for Single-Line Expressions navigates history only when the expression fits in one visual line; otherwise, it moves the cursor.

    Added in version 1.0.

User Interface Settings

  • Settings ‣ Appearance ‣ Theme…

    Open the theme dialog. Themes are listed in Light Themes and Dark Themes groups. Selecting a theme updates the preview immediately. When no saved theme preference exists, as on first launch, SpeedCrunch uses the Duskfox theme.

    The Preview area shows representative result-display and editor content so that syntax-highlighting, result, and background colors are visible while editing. The selected background color generates nearby OKLCH surface colors for the expression editor and surrounding application chrome, followed by progressively offset surface colors for dock titles, dock controls and table headers, dock search and content areas, pane splitters, and scrollbars. It also generates the primary/accent color unless the theme specifies a primary color.

    Text on generated surfaces, including docks and popups, targets a contrast ratio of at least 10:1 against its own background. SpeedCrunch keeps a tint from the theme where possible. If a surface cannot reach that ratio, it uses black or white, whichever gives better contrast.

    The Colors area provides per-role color selection buttons showing both the #RRGGBB value and the actual color. Changing any color creates a custom theme based on the current selection.

    The dialog also includes:

    • Import… to copy a theme JSON file into SpeedCrunch’s user theme directory and refresh the theme lists;

    • Export… to save the current theme as JSON in the same user theme directory.

    Import and export refuse theme names that collide with built-in themes. Import asks for confirmation before overwriting an existing custom theme.

    SpeedCrunch also supports loading additional theme files from the following directory:

    • Windows: C:/Users/<USERNAME>/AppData/Roaming/SpeedCrunch/color-schemes/

    • Linux/Unix: ~/.local/share/SpeedCrunch/color-schemes/

    • Linux (Flatpak): ~/.var/app/org.speedcrunch.SpeedCrunch/data/SpeedCrunch/color-schemes/

    • OS X: ~/Library/Application Support/SpeedCrunch/color-schemes/

    • Portable version (any OS): color-schemes subdirectory in the application directory.

    Theme files use JSON and map role names to color values. Supported role names are: number, parens, list, unit, result, comment, function, operator, variable, separator, background, and optional primary. The editor surface and scrollbar colors are generated from background. For the full schema, see Theme JSON Schema.

    Added in version 1.0: The Theme… dialog, including live preview and JSON import/export.

  • Settings ‣ Appearance ‣ Menus

    Choose how menus look:

    • System uses the system’s menu colors and styling, including highlighted and disabled items. Menus follow changes to the system theme while SpeedCrunch is running.

    • SpeedCrunch Theme (the default) uses the selected SpeedCrunch theme for menu backgrounds and text, including highlighted items.

    This setting applies to the menu bar shown inside the application window, dropdown menus, context menus, and dropdown lists in attached and floating docks that use the SpeedCrunch theme. Closed dropdown controls follow the Docks setting. The macOS system menu bar keeps its native appearance. Popup menus drawn by Qt can look slightly different from native macOS menus. On GNOME, popup menus use the GTK theme’s popup hover colors when GTK is available. Otherwise they use Qt’s system palette. The choice applies to all SpeedCrunch windows and is saved between launches.

    Selections in the expression editor and result display use the SpeedCrunch theme. Dock list selections follow the Docks setting.

  • Settings ‣ Appearance ‣ Docks

    Choose how attached and floating docks look, including their title bars:

    • System uses the system’s colors and widget styles for lists, search fields, dropdown controls, scrollbars, dock title bars, and the tabs used to switch between overlapping docks. Close and float buttons use the system style. Dropdown lists also use the system appearance, regardless of the Menus choice. The Formula Book and bitfield use system colors as well. Formula and navigation links use the system link color directly. On bits use the system selection colors, with a separate hover color for off bits.

    • SpeedCrunch Theme (the default) uses the selected SpeedCrunch theme for dock content, title bars, and tabs, including list selections and search fields.

    The choice applies immediately to all SpeedCrunch windows and is saved between launches. System colors follow changes to the system theme while SpeedCrunch is running.

    Added in version 1.1.

  • Settings ‣ Appearance ‣ Status Bar

    Choose how the status bar looks:

    • System uses the system’s palette and widget styles for the status bar, its labels, and its buttons. Colors follow changes to the system theme while SpeedCrunch is running.

    • SpeedCrunch Theme (the default) uses the selected SpeedCrunch theme for the status bar background and text.

    The choice applies immediately to all SpeedCrunch windows and is saved between launches. Popup menus follow the Menus setting. Show or hide the status bar with View ‣ Status Bar.

    Added in version 1.1.

  • Settings ‣ Appearance ‣ Input and Results

    Choose the layout of the expression editor and result display:

    • Modern (the default) uses a rounded input box with compact padding and a small gap around it. History aligns with the left edge of the box.

    • Classic uses a compact, full-width editor directly below the results and a small history gutter. All editors use the Modern input background color across the whole input area. Text and editor popups share a small inset from the edge, with enough space below the input for rounded window corners. A top line marks the active pane, using the same thickness and accent color as the Modern outline. This line is hidden when there is only one window and one pane, regardless of how many session tabs it contains. Vertical pane dividers remain visible through the input area.

    Both styles keep the same editing features, including input that grows as expressions wrap. The choice applies immediately to every window and pane and is saved between launches.

    Added in version 1.1.

  • Settings ‣ Appearance ‣ Input and Results ‣ Font…

    Select the font to use for the expression editor and result display. On macOS 27 and later, SpeedCrunch uses Qt’s font dialog.

  • Settings ‣ Appearance ‣ Keypad

    Choose the shape and spacing of the keypad buttons:

    • Classic uses shallow rectangular buttons with smaller gaps, similar to the keypad in SpeedCrunch 0.12.

    • Modern (the default) keeps the larger square buttons.

    The choice applies immediately to all windows and is saved between launches. It works with every preset and custom keypad. Each window keeps its own layout, selected from View ‣ Keypad, and zoom level, selected from Settings ‣ Appearance ‣ Keypad ‣ Zoom.

    Added in version 1.1.

  • Settings ‣ Appearance ‣ Syntax Highlighting

    Enable or disable syntax highlighting.

  • Settings ‣ Appearance ‣ Hover Highlighting

    Enable or disable hover highlighting.

  • Settings ‣ Language

    Select the user interface language.

Help

  • Help ‣ App Diagnostics

    Show system information and app settings. Use Copy to Clipboard to share the report when reporting a problem.

  • Help ‣ About SpeedCrunch

    Show the SpeedCrunch version, the operating system and its version, and the Qt version. Portable builds display Portable next to the SpeedCrunch version.

  • Help ‣ Check for Updates

    Trigger an update check and show information when a newer version is available. Update checks are enabled in official SpeedCrunch builds. Other distributors can choose whether to enable them. When enabled, this menu entry is available and SpeedCrunch also checks for updates after the window first paints, at most once every 24 hours. Each network request has a five-second deadline, including redirects. Receiving data does not extend that deadline. Oversized update responses are rejected before their contents are parsed or saved. Closing a window requests that its update worker stop. Cleanup finishes in the background, without making the window wait for network setup. See BUILDING.md at the repository root for build options and package provider guidance.

    Added in version 1.0.

Keyboard Shortcuts

Editing

  • Ctrl+O

    Open session.

  • Ctrl+Q

    Quit SpeedCrunch (Cmd+Q on macOS).

  • Ctrl+N

    Create a new session in the current session pane.

  • Ctrl+T (Cmd+T on macOS)

    Create a new session tab in the current session pane.

  • Ctrl+Shift+N (Cmd+Shift+N on macOS)

    Create a new private tab in the current session pane.

  • Ctrl+Shift+T (Cmd+Shift+T on macOS)

    Reopen the most recently closed session tab.

  • Ctrl+W (Cmd+W on macOS)

    Close the active session tab.

  • Ctrl+C

    Copy selected text to clipboard.

  • Ctrl+R

    Copy last result to clipboard.

  • Ctrl+V

    Paste from clipboard.

  • Ctrl+A

    Select entire expression.

  • Ctrl+( or Ctrl+)

    Wrap the current selection in parentheses. If no text is selected, the entire expression is wrapped.

Session Tabs

  • Cmd+Alt+Left and Cmd+Alt+Right (macOS)

    Move to the previous or next session tab or pane.

  • Ctrl+Page Up and Ctrl+Page Down (Windows/Linux)

    Move to the previous or next session tab or pane.

Widgets and Docks

  • Ctrl+1

    Show/hide formula book.

  • Ctrl+2

    Show/hide constants widget.

  • Ctrl+3

    Show/hide functions widgets.

  • Ctrl+4

    Show/hide variables widget.

  • Ctrl+5

    Show/hide user functions widget.

  • Ctrl+6

    Show/hide user units widget.

  • Ctrl+7

    Show/hide history widget.

  • Ctrl+8

    Show/hide bit field dock.

  • Ctrl+B

    Show/hide the status bar. The status bar provides quick selectors for Angle Mode, Results ‣ Notation, and Results ‣ Precision. On narrow windows, selectors that do not fully fit are hidden automatically. Status bar visibility is set separately for each window; the main menu always shows and changes the setting for the active window. Angle mode, notation, and precision selections are also retained separately for each window.

Scrolling

  • Page Up and Page Down

    Scroll the result window page-wise.

  • Shift+Page Up and Shift+Page Down

    Scroll the result window line-wise.

  • Cmd+Page Up and Cmd+Page Down (macOS)

    Scroll to the top or bottom of the result window.

Focus Navigation

  • F6 and Shift+F6

    Move focus forward or backward between the expression editor and visible dock controls. Focus navigation applies to the current window, including its floating docks.

Notation

  • F2

    Set result notation to automatic decimal.

  • F3

    Set result notation to fixed-point decimal.

  • F4

    Set result notation to engineering decimal.

  • F5

    Set result notation to scientific decimal.

  • F7

    Set result notation to octal.

  • F8

    Set result notation to hexadecimal.

  • F9

    Set result notation to sexagesimal.

  • F10

    Set result notation to binary.

    Added in version 1.0.

Various

  • F1

    Show context help (dismiss with Escape).

    Added in version 0.12.

  • F11

    Toggle full screen.

  • Ctrl + mouse wheel, Shift + mouse wheel, or Shift+Up and Shift+Down

    Change the font size.

  • Ctrl+Shift + mouse wheel

    Change the window opacity.

    Added in version 0.12.

Footnotes

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/session_json_schema.html000066400000000000000000001265441526573132500340010ustar00rootroot00000000000000 Session JSON Schema

Session JSON Schema

SpeedCrunch session files are JSON objects with stored calculation history, session-local variables, user functions, user units, and global user-definition startup lines. Session files include a schema identifier so JSON editors and SpeedCrunch can associate them with the current SpeedCrunch session format.

Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://speedcrunch.org/schemas/session-v1.schema.json",
  "title": "SpeedCrunch Session",
  "type": "object",
  "required": [
    "$schema",
    "$id",
    "session",
    "limit",
    "history",
    "variables",
    "functions",
    "units",
    "globals"
  ],
  "additionalProperties": false,
  "properties": {
    "$schema": {
      "const": "https://json-schema.org/draft/2020-12/schema",
      "description": "JSON Schema dialect identifier"
    },
    "$id": {
      "const": "https://speedcrunch.org/schemas/session-v1.schema.json",
      "description": "Session schema identifier"
    },
    "session": {
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "type": "integer",
      "minimum": 0,
      "description": "Maximum stored history entries for this session; 0 means unlimited."
    },
    "history": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/historyEntry"
      }
    },
    "variables": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/variable"
      }
    },
    "functions": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/userFunction"
      }
    },
    "units": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/userUnit"
      }
    },
    "globals": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "$defs": {
    "historyEntry": {
      "type": "object",
      "required": [
        "xpr",
        "itp",
        "rst",
        "ctx",
        "edt"
      ],
      "additionalProperties": false,
      "properties": {
        "xpr": {
          "type": "string"
        },
        "itp": {
          "type": "string"
        },
        "rst": {
          "$ref": "#/$defs/quantity"
        },
        "ctx": {
          "$ref": "#/$defs/evaluationContext"
        },
        "edt": {
          "type": "integer"
        },
        "prt": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "evaluationContext": {
      "type": "object",
      "required": [
        "lns",
        "cpx",
        "ang",
        "uxp",
        "rnd"
      ],
      "additionalProperties": false,
      "properties": {
        "lns": {
          "type": "object",
          "required": [
            "main",
            "ext"
          ],
          "additionalProperties": false,
          "properties": {
            "main": {
              "$ref": "#/$defs/resultLineContext"
            },
            "ext": {
              "type": "array",
              "maxItems": 4,
              "items": {
                "$ref": "#/$defs/resultLineContext"
              }
            }
          }
        },
        "cpx": {
          "type": "string",
          "enum": [
            "off",
            "i",
            "j"
          ]
        },
        "ang": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1
        },
        "uxp": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1
        },
        "rnd": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1
        }
      }
    },
    "resultLineContext": {
      "type": "object",
      "required": [
        "ntn",
        "prc",
        "cpx"
      ],
      "additionalProperties": false,
      "properties": {
        "ntn": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1
        },
        "prc": {
          "type": "integer"
        },
        "cpx": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1
        }
      }
    },
    "variable": {
      "type": "object",
      "required": [
        "id",
        "qty"
      ],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string"
        },
        "qty": {
          "$ref": "#/$defs/quantity"
        },
        "dsc": {
          "type": "string"
        },
        "fmt": {
          "type": "string"
        }
      }
    },
    "userFunction": {
      "type": "object",
      "required": [
        "id",
        "args",
        "xpr"
      ],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string"
        },
        "args": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "xpr": {
          "type": "string"
        },
        "itp": {
          "type": "string"
        },
        "dsc": {
          "type": "string"
        },
        "opcodes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/opcode"
          }
        },
        "constants": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/cNumber"
          }
        },
        "identifiers": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "opcode": {
      "type": "object",
      "required": [
        "t",
        "i"
      ],
      "additionalProperties": false,
      "properties": {
        "t": {
          "type": "integer"
        },
        "i": {
          "type": "integer"
        },
        "text": {
          "type": "string"
        }
      }
    },
    "userUnit": {
      "type": "object",
      "required": [
        "id",
        "qty"
      ],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string"
        },
        "qty": {
          "$ref": "#/$defs/quantity"
        },
        "xpr": {
          "type": "string"
        },
        "itp": {
          "type": "string"
        },
        "dsc": {
          "type": "string"
        }
      }
    },
    "quantity": {
      "type": "object",
      "required": [
        "val"
      ],
      "additionalProperties": true,
      "properties": {
        "val": {
          "type": "string"
        },
        "dim": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "unit": {
          "type": "object",
          "additionalProperties": true
        },
        "unit_name": {
          "type": "string"
        },
        "format": {
          "type": "object",
          "additionalProperties": true
        }
      }
    },
    "cNumber": {
      "type": "object",
      "required": [
        "value"
      ],
      "additionalProperties": true,
      "properties": {
        "value": {
          "type": "string"
        }
      }
    }
  }
}

Notes

  • $schema identifies the JSON Schema draft used by the session metadata. SpeedCrunch session files use https://json-schema.org/draft/2020-12/schema.

  • $id identifies the SpeedCrunch JSON Schema for the session format: https://speedcrunch.org/schemas/session-v1.schema.json.

  • session stores the session name. Empty names are normalized to main by SpeedCrunch.

  • limit stores the calculation history limit for the session. A value of 0 means unlimited history.

  • history stores saved calculations. The compact field names preserve the existing session file format: for example xpr is the expression, rst is the result quantity, and ctx is the evaluation context.

  • variables, functions, and units store session-local user definitions. Definitions from global startup user definitions are stored in globals instead.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/syntax.html000066400000000000000000001704701526573132500312700ustar00rootroot00000000000000 Syntax

Syntax

This part of the documentation explains the syntax of valid SpeedCrunch input. As you will see, SpeedCrunch honors most conventions for mathematical expressions. You will find using SpeedCrunch to be very natural and intuitive, especially so if you are already familiar with a programming language.

Number Notation

Decimal Form

When you would like to specify a non-integer value, simply enter the number as you would write it on paper, with either a period (.) or a comma (,) as the decimal separator. Accepted decimal separator and grouping conventions depend on the selected Number Format.

Trailing zeros after the decimal point (like in 12.300) or leading zeros before it (0012.3) are redundant and can be included or omitted to the user’s preference. Expressions like .5 as a shorthand notation for 0.5 are also permitted.

Digit Grouping Separators

To improve readability, SpeedCrunch accepts grouping separators inside number literals. Grouping separators are optional and ignored during evaluation.

Allowed grouping separators are characters that are not letters or digits and are not number operators. In practice, this includes many punctuation and symbol characters, for example:

  • _ (underscore): 12_345_678

  • Space (U+0020): 12 345 678

  • Currency symbols: $12,345, €12 345, 12Â¥345

Not allowed as grouping separators:

  • Letters from any language (for example 天, é, Ж)

  • Digits from any language

  • Radix characters (. or , depending on settings) when they are used as decimal separators

  • Operator characters and other reserved syntax tokens

Some characters cannot be used for digit grouping because they already have an assigned meaning in expressions:

  • # starts hexadecimal number notation (for example #FF).

  • ! is the factorial operator (for example 5!).

  • : is used in sexagesimal time/angle notation (for example 12:34:56).

  • ° is used in sexagesimal angle notation (for example 12°34'56).

  • ′ is used in sexagesimal angle notation (for example 12°34′56″).

  • & is the bitwise AND operator (for example 6 & 3).

  • ? starts a comment (for example 1+2 ? note).

Examples:

  • 12$345.678$9 evaluates as 12345.6789

  • 12天2 is rejected (it is not treated as 122)

Scientific Notation

When dealing with very small or very large numbers (think the size of an atom or of a galaxy) the notation above is inconvenient. These are more commonly expressed in scientific notation; for instance, 1.234*10-9 is preferable to 0.000000001234.

Naturally, in SpeedCrunch this could be written as 1.234*10^-9, but there’s also a shorthand notation: 1.234e-9. Here, the e represents *10^, but it is considered a part of the number literal and treated with higher precedence. For example, 1e2^3 is equivalent to (1e2)^3 = 100^3. The scale of a number (sometimes called its exponent) always begins with the scale character E or e followed by a signed integer. So e+10, e-4, E-0 are all valid scale expressions. If the sign is ‘+’, you may simply omit it: e0, E10. The significand (i.e. the part preceding the exponent) is required; exactly one exponent must be specified.

Equivalent examples:

98e3
98*10^3
98x10³

Compared to most calculators, SpeedCrunch can accept very large numbers without overflowing (e.g. both 1e+536870911 and 1e-536870911 are still valid). However, only about 78 significant digits are stored at any point. Any digits beyond that are lost.

Non-Decimal Bases

In addition to decimal (base-10) numbers, SpeedCrunch provides support for binary (base-2), octal (base-8) and hexadecimal (base-16) numbers. You can enter a number in any of these bases by marking it with the corresponding prefix:

  • 0b or 0B for binary, e.g. 0b10010.

  • 0o or 0O for octal, e.g. 0o1412.

  • 0d or 0D for decimal. These can be omitted since decimal is the default base.

  • 0x, 0X, or # for hexadecimal. The additional six digits are represented by the upper or lower case letters a to f, e.g. 0xdeadbeef or 0xDEADBEEF.

You may even enter fractional values in any of these bases. Note that scientific notation is not supported for non-decimal bases, however. Examples:

0b1.01
= 1.25

0xf.a
= 15.625

To have SpeedCrunch output its results in a base other than decimal, you may use one of the functions bin(), oct(), dec(), or hex():

hex(12341)
= 0x3035

The effect of these functions only applies to the immediate result and doesn’t carry to future operations:

0x2 * hex(12341)
= 24682

The same applies to sci() and eng(): they only affect the formatted display of the immediate value, not the numeric value used in later arithmetic. In particular, operand order does not matter:

1 + sci(123456.789)
= 123457.789

sci(123456.789) + 1
= 123457.789

For explicit decimal exponent notations, use sci() (scientific notation) or eng() (engineering notation):

sci(12341)
= 1.2341e4

eng(12341)
= 12.341e3

To force the exponent used by eng(), pass an optional second argument. It accepts either a direct exponent that is a multiple of 3, or a matching power of ten (including SI prefixes):

eng(0.000123456; [milli])
= 0.123456e-3

eng(0.000123456; -4)
= 1.23456e-4

For assembly-style fixed-width formatting, use binpad(), octpad(), or hexpad(). These functions only accept real, dimensionless integer arguments and also only affect the immediate result:

hexpad(15)
= 0x0F

binpad(1536; 32)
= 0b00000000000000000000011000000000

To change the base that is used for displaying results, select one of the corresponding settings in Settings ‣ Results ‣ Notation. This affects only subsequent calculations/results; existing history entries are not rewritten.

SpeedCrunch stores integers with a precision of up to 256 bits. Since this would be unwieldy, the binary representation of a negative number in SpeedCrunch is not its two’s complement. Instead, like with other bases, the value and the sign are represented separately:

bin(-1)
= -0b1

See mask() and unmask() to convert a negative number into the two’s complement form.

Any integer larger than the 256-bit limit will be silently converted into a floating point number, making it susceptible to rounding errors. To specify large integers, using the shift operators (1 << n) is preferable to exponentiation (2 ^ n) as the latter are floating point calculations and thus susceptible to rounding errors.

Sexagesimal Values

Added in version 1.0.

Sexagesimal values in SpeedCrunch are angle degrees or time values represented with minutes and seconds.

When sexagesimal mode is selected in Settings ‣ Results ‣ Notation, dimensionless and time results are displayed as sexagesimal values. All other results are displayed as fixed-point decimal values. Actual sexagesimal math depends on the result. Dimensionless results are handled as degrees with minutes and seconds generated from the decimal part. With time dimension results, base unit is second and the integer part is divided to minutes and hours.

In input, characters ° (degree), : (colon), ′ (prime) and ″ (double prime) can be used for entering sexagesimal values. Degree sign ° separates degrees and minutes. First colon character : separates hours and minutes. Prime ′ or second colon character : separates minutes and seconds. Additionally, postfix double prime ″ can be used as an arc second unit. ASCII single quote ' and double quote " are accepted as aliases and are normalized to ′ and ″ on editor insertion/paste. Because the degree sign is difficult to produce from keyboard, at sign @ is automatically converted to it.

Amount of minutes or seconds is not limited to values below 60. It is possible to input time 90 minutes after noon:

12:90
= 13:30:00

Dimensionless input values are automatically considered to be in current angle mode. For example, in radian mode:

pi
= 180°00'00

For trigonometric input, explicit angle units override angle mode. For example, cos(pi*[rad]), cos(180*[deg]), cos(200*[gon]) and cos(0.5*[turn]) all evaluate to -1 regardless of the global angle mode. The aliases deg for degree, gon for gradian, and rev for revolution are supported. revolution is equivalent to turn (that is, 2*pi radians). deg is normalized to ° in autocomplete insertion and displayed result units.

Only last part of sexagesimal input value can contain decimals.

Following tables show some possible input notations and their results in both fixed-point decimal and sexagesimal modes. Sexagesimal round-trips (for example arcsecond → DMS → radians) are designed to keep precision drift negligible. In the first table, fixed-point decimal values assume angle mode is set to degrees:

Input

Fixed-Point Decimal

Sexagesimal

0

0

0°00'00

°'56

0.01555556

0°00'56.00

56"

0.01555556

0°00'56.00

56[arcsec]

0.01555556

0°00'56.00

56.78"

0.01577222

0°00'56.78

°34

0.56666667

0°34'00.00

34'

0.56666667

0°34'00.00

34[arcmin]

0.56666667

0°34'00.00

34'56

0.58222222

0°34'56.00

12°

12.00000000

12°00'00.00

12°34

12.56666667

12°34'00.00

12°34.5

12.57500000

12°34'30.00

12°34'56

12.58222222

12°34'56.00

12°34'56.78

12.58243889

12°34'56.78

Use canonical symbols ′ and ″ (insertable with ' and "), or the aliases arcmin and arcsec. Full names arcminute and arcsecond are also accepted.

Input

Fixed-Point Decimal

Sexagesimal

0[s]

0 [s]

0:00:00

::56

56.00 [s]

0:00:56.00

56[s]

56.00 [s]

0:00:56.00

:34

2040.00 [s]

0:34:00.00

34[min]

2040.00 [s]

0:34:00.00

12:

43200.00 [s]

12:00:00.00

12[h]

43200.00 [s]

12:00:00.00

12:34

45240.00 [s]

12:34:00.00

12:34.5

45270.00 [s]

12:34:30.00

12:34:56

45296.00 [s]

12:34:56.00

12:34:56.78

45296.78 [s]

12:34:56.78

Note that when entering time values with colons, no additional dimension units are needed. Formatting itself works as an unit.

Comments

The question mark character ? starts a comment. Everything from ? to the end of the line is ignored by the evaluator:

1 + 2 ? simple sum
= 3

Comment text is kept as written, including in the result window and when editing user definitions. For example, examplevar = 4 ? 2*2 keeps 2*2 in the Description column of the User Variables dock, without changing it to 2×2. The same rule applies to user functions and user units.

A line can also be comment-only. If the first non-space character is ?, the whole line is treated as a comment:

? start algorithm

  ? this is also a comment-only line

Operators and Precedence

When writing an expression like 10+5*4, which operation will be executed first? The common rules of operator precedence tell us that in this case multipication shall be computed first, hence the result is 30. We also distinguish unary operators (which act on a single number/operand) and binary operators (which link two operands).

SpeedCrunch supports the following operators, listed in order of decreasing precedence:

Operator

Description

Examples

(...)

Parentheses

Parentheses mark precedence explicitly.

(2+3)*4 = 5*4 = 20

x!

Factorial

Computes the factorial of its argument. See also gamma().

5! = 120

x%

Percent

Postfix operator equivalent to division by 100. In a+b% and a-b%, the percentage is applied relative to the entire left operand a (after normal precedence). So 1+(2+3)+10% is interpreted as (1+(2+3))+10%.

Added in version 1.0: Contextual percent semantics.

50% = 0.5 1000+12% = 1120 1000-12% = 880 1000*12% = 120 1000/25% = 4000 1+2+3+10% = 6.6 1+(2+3)+10% = 6.6

a ^ b, a ** b, a²

Exponentiation

a² is shorthand for a^2; ** is equivalent to ^ and can be used as an easy way to insert powers. contiguous superscript digits are parsed as one integer exponent. Both function notations f^n(x) and f�(x) are interpreted identically. text-operator variants are equivalent. Note that the power operation is right-associative, i.e. it is evaluated from right to left. Fractional powers return principal complex roots for negative bases. Positive and negative powers can be written with either ^ or **.

Added in version 1.0: Integer superscript powers and f^n(x) function-power notation (equivalent to f�(x)).

3²� = 3^20 2**10 = 1024

2¹� = 1024

cos^2(pi)=cos²(pi)

2^2^3 = 2^8 = 256

(-1)^(1/2) = i

10^3, 10^-3, 10**3, 10**-3

+x, -x, ~x

Unary plus, minus, and bitwise NOT

~x is equivalent to not(x)().

Added in version 1.0.

~5 = -6 -~(-1) = -not(-1)

a \ b

Integer division

Divides the operands and truncates the result to an integer.

5\4 = 1

a * b, a × b, a b, a / b, a ⧸ b

Multiplication and division

In many situations, implicit multiplication allows writing multiplications without the * operator. In the expression editor and Session Import, these symbols are normalized to ×: ∗, ·, ⋅, ∙, *, ⨉, ⨯, ✕, ✖. In the expression editor and Session Import, these symbols are normalized to ⧸: /, ÷. Implicit multiplication has the same precedence as * and /, evaluated from left to right. The result display makes this association explicit by showing the interpreted expression before the numeric result.

Added in version 0.12: Implicit multiplication was added SpeedCrunch 0.12.

Added in version 1.0: Multiplication and division symbol aliases. Improved explicit interpretation/association in results.

3 sqrt(2)

6/2(2+1)=9

a + b, a - b

Addition and subtraction

In the expression editor and Session Import, + is normalized to +. In the expression editor and Session Import, these symbols are normalized to −: -, �, ﹣, �, ‑, –, —, ―, �.

Added in version 1.0: Addition and subtraction symbol aliases.

a << n, a >> n

Left/right arithmetic shifts

Shifts the first operand left/right by n bits. See also shl() and shr().

0b11<<1 = 0b110

0b100>>2 = 0b1

a & b

Bitwise AND

See also and().

0b11 & 0b10 = 0b10

a | b

Bitwise OR

See also or().

0b10 | 0b01 = 0b11

->, in, --

Unit conversion

Convert the operand into the given unit. Both forms are equivalent. See -- is a shortcut equivalent to -> and in. Units for more information.

10[m] in [mi]

10[m] -> [mi] 10[m] -- [mi]

For negative bases, fractional powers return the principal complex root. Use cbrt() when you specifically need the real cubic root of a real negative value, or root() for other odd root indices.

Complex Numbers

Added in version 0.12.

SpeedCrunch supports complex-number expressions by default. Enter the imaginary unit as i or j:

j^2
= -1

(5+3j)/(8-2j)
= 0.5+0.5j

Syntax note: 5j means 5*j, while j5 is a variable named j5. Write j*5 explicitly if needed.

The displayed imaginary-unit symbol is configurable in Settings ‣ Results ‣ Imaginary Unit. The displayed complex form is configurable in Settings ‣ Results ‣ Complex Form.

You can enter complex numbers in phasor notation with ∠. The expression r ∠ θ is interpreted as r * cis(θ). The phase follows the current angle mode unless it has an explicit angle unit:

3 ∠ 90°
= 3j

3 ∠ 200 [gon]
= -3

Not every function accepts complex arguments. Refer to each function entry in the reference.

Caution: fractional powers return principal complex roots. For example, x^(1/3) may be non-real. In contrast, cbrt() always returns the real cubic root for real inputs.

For other root indices, use root(), for example root(5; -32) = -2. It returns the real root for real inputs whenever one exists. Negative real inputs with an even index return the principal complex root.

i and j are built-in constants for the imaginary unit.

heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/en_US/userguide/theme_json_schema.html000066400000000000000000000505211526573132500334070ustar00rootroot00000000000000 Theme JSON Schema

Theme JSON Schema

SpeedCrunch theme files are JSON objects with supported color-role keys. Each color-role value is a color string in #RRGGBB format. Theme files also include required schema metadata and may include optional descriptive and format metadata.

Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json",
  "title": "SpeedCrunch Theme",
  "description": "Defines the colors used by a SpeedCrunch theme.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "$schema",
    "$id",
    "number",
    "parens",
    "list",
    "unit",
    "result",
    "comment",
    "function",
    "operator",
    "variable",
    "separator",
    "background"
  ],
  "properties": {
    "$schema": {
      "const": "https://json-schema.org/draft/2020-12/schema",
      "description": "JSON Schema draft identifier"
    },
    "$id": {
      "const": "https://speedcrunch.org/schemas/theme-v1.schema.json",
      "description": "Theme schema identifier"
    },
    "name": {
      "type": "string",
      "description": "Optional theme display name"
    },
    "author": {
      "type": "string",
      "description": "Optional theme author"
    },
    "homepage": {
      "type": "string",
      "description": "Optional theme homepage"
    },
    "version": {
      "type": "string",
      "description": "Optional theme version chosen by the theme author"
    },
    "number": { "$ref": "#/$defs/color" },
    "parens": { "$ref": "#/$defs/color" },
    "list": { "$ref": "#/$defs/color" },
    "unit": { "$ref": "#/$defs/color" },
    "result": { "$ref": "#/$defs/color" },
    "comment": { "$ref": "#/$defs/color" },
    "function": { "$ref": "#/$defs/color" },
    "operator": { "$ref": "#/$defs/color" },
    "variable": { "$ref": "#/$defs/color" },
    "separator": { "$ref": "#/$defs/color" },
    "background": { "$ref": "#/$defs/color" },
    "primary": {
      "$ref": "#/$defs/color",
      "description": "Optional primary/accent color override"
    }
  },
  "$defs": {
    "color": {
      "type": "string",
      "pattern": "^#[0-9a-fA-F]{6}$",
      "description": "Hex color in the form #RRGGBB"
    }
  }
}

Notes

  • parens controls highlighting for ().

  • list controls highlighting for list/matrix curly braces {} only.

  • unit controls highlighting for square-bracketed unit blocks, including both [] and everything inside them.

  • background also supplies the base color for the generated application chrome, expression-editor surface colors, and successive generated surfaces used by dock titles, controls and headers, and content areas. Scrollbar colors are generated from the background of the surface that owns each scrollbar, so theme files do not include a separate key for them. Text colors for these surfaces target at least 10:1 contrast while keeping the background’s hue where possible. If that ratio cannot be reached, SpeedCrunch uses black or white, whichever gives better contrast.

  • primary is optional. When present, it overrides the generated primary/accent color used for active selections, focused editor outlines, cursor accents, pane splitters, and primary-hue keypad fills. When omitted, SpeedCrunch generates the primary/accent color from background.

  • name, author, homepage, and version are optional metadata fields. version is a string that belongs to the theme author and is not used as the schema or format version. A non-empty name is used as the theme display name.

Fictitious Example

The following example is fictitious and provided only as a usage example:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json",
  "name": "Example Theme",
  "author": "Example Author",
  "homepage": "https://example.com",
  "version": "1",

  "number": "#6ED3FF",
  "parens": "#C8A2C8",
  "list": "#B39DDB",
  "unit": "#9CDCFE",
  "result": "#E8F1FF",
  "comment": "#7F8C8D",
  "function": "#FFB347",
  "operator": "#F5F5F5",
  "variable": "#FF8DA1",
  "separator": "#2F3640",
  "background": "#111827",
  "primary": "#6EE7B7"
}
heldercorreia-speedcrunch-e7ca37f/doc/build_html_embedded/manual.qrc000066400000000000000000000003551526573132500260250ustar00rootroot00000000000000 en_US/manual-en_US.qch en_US/manual-en_US.qhc heldercorreia-speedcrunch-e7ca37f/doc/clean-doc-builds.sh000077500000000000000000000010261526573132500235450ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DOC_SRC_DIR="$ROOT_DIR/doc/src" if [[ ! -d "$DOC_SRC_DIR" ]]; then echo "error: doc source directory not found: $DOC_SRC_DIR" >&2 exit 1 fi shopt -s nullglob build_dirs=("$DOC_SRC_DIR"/_build-*) shopt -u nullglob if [[ ${#build_dirs[@]} -eq 0 ]]; then echo "no generated doc build directories found under: $DOC_SRC_DIR" exit 0 fi rm -rf "${build_dirs[@]}" echo "removed generated doc build directories under: $DOC_SRC_DIR" heldercorreia-speedcrunch-e7ca37f/doc/legacy/000077500000000000000000000000001526573132500213465ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/legacy/Doxyfile000066400000000000000000001562741526573132500230730ustar00rootroot00000000000000# Doxyfile 1.5.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = SpeedCrunch # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 0.11 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, # and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.c *.cpp *.cxx *.h *.hxx # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is enabled by default, which results in a transparent # background. Warning: Depending on the platform used, enabling this option # may lead to badly anti-aliased labels on the edges of a graph (i.e. they # become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO heldercorreia-speedcrunch-e7ca37f/doc/legacy/logic-unit.pdf000066400000000000000000014253031526573132500241230ustar00rootroot00000000000000%PDF-1.4 %äüöß 2 0 obj <> stream xœí\É®$;Ý÷WÔšÅ%=§%„Ô]ÃþI-ñ  $ØðûxŠ!á̺¯›'¨‚º™N;Æ“·Û¿¿üó¶Ý¶s 9|¸ÛîÍG¾ýë/·?ýîö�þ·òï_ûòíû—?ö[ é#ܾÿùöû—¹™X^üþ×Û‚ÿãíûß¿ìå�­þñ1Œòø!¹ù‡þJøð㻵|Y~¬‘Ç~x´Œ/‹ôwòG‚Gîó;}#Y,a<§qŸ¸¢¹: nOò‹îóWöåáÅ+ñ’^óÆä‚:â+i&¨8‹;ÐK|#…ÕY—K".:žYrE|6ôm™�·Í™8=ý_?=îÇŠ©•lû%’ø-Ϻ¿K-±É™#o(ÎcúÁm³ <'¾»¬‹Êóû—_T­7CçíÍØ¦ñ>ÇçxÉØy÷�vo£�!Y»�m[ðÂå—Pè8‰ÂàR(†Wtñ1àš.�líõwXÕ ŠÙêÌ35¿¬â3ùñ¼5¸‹¡'ŽŒDÃa™–�ÏGúºI`驲Ùgrõ°1ŽO9âUòu˰aR€´•Ålr�xý-¦·yÞ 0ƒX\Y#”~H²‹³$…R¢[ÄOã&ÒÇÝÞ…ÜDô6ôàc1þ`â7ÐOÒ¿rº½Ð§³Ü¢ø•(úhËæ¤,^ ï¶•ƒ_‘| U4d, í]DúÖž^1úÈæ�CHÔ+¦òJ“‹Ê§"Œe;H—ªDÜrcAú©Î4¡²�ÅÀ}ïè‹RD’ŸØR>úоðÞU1±Ê*>N&Ohx!Ó}<ægðIëI-�ð(…T}“h‰0Ìô™F?¡§R5:�†¿4äƒSÉ¡Œ;}ßJ¢vf2@*hb›½*ƒb[X\ÑÕQluYñžì‰"+¦Zº¶K7tºˆ2WÃAIf‡Ëâ¶*°‡¹Õb°À–’P4íå±Z’boý�¿à8ÕŸd›ÉC2ê@I€qx-:ˆÝBù8˜q\6㙹u‰ƒižö8v½¡Ê“#C?iMS²'HU¦ß=Øhp�K¡ÐÀ06ÜñiþÁ£,¥,„5�$DÑ›9† í­ C®Ö¡øàû0²äip'ö^E¤�7×Ó�ÔkæÝê¡&Ç®Š°&ÈW²Ÿª:¾‚^o'Hâyaw§—ÀV¯^H¹ªêÁÒýš’ÝIa�]+üâ×ûDqm@¦®™@–œc@ŒƒÏjR…~…aN‘J{B‡�ˆ‘Ì ì÷zF¤ï$LÈ<œ@Àª)¾8m‹ãº±O"|?¡Ÿ/ÿiæÈ}=›`Ê들ínK»�Œ„#œbãÄÅI�fgÙ]‚“àCÑÖ�Î×¹±¶”J»YX€/súO2kaýf•<»W)+rµ�-û�ýV›mýÑäu¢72š§\#�—¦'R˜×x޼è”þ^ž¥@A?;÷\)Nîšìne/Dz^dÛ�ÛC`x`‚© æq4 !Oèr)u"Õ8ˆÞ $ÙS7ç|'£¯Øg§ ZŠ >ŸëÑWÕZXÑѦž-Q36Åc`a«*¥Ó ·},‘©EÏJº¸É$ " x’Mý\îK¦ª‘ª !0’ŽÑ�ˉ ú«©4Ú‰@Ÿ×Ó)K­pÕôijqeÞ‹;›Í»} !R^Š5›[Ð7aëÔÞqs¶ "’ùeÍ”j!PÛˆŽ8ֻ˩¬ñ“wg¶*f :™¡ø( ÷&]¶!�`0-]%|¢0˽¤jÕtRÙoöe1·”Y´dÁÜâO �xúÝeûuÞ˜¤>¦ÊƬ«†S£|Ó^òV?ËSD›ŠŒ¤ð-þA„Ëò¦[òÀMšc p'P‚fl˜ņÃíël,µÀ€_ç•ͧA(ÆÏ‰ ¤ÂP„Gm<Ú>xUküÊ“|»´ñZÎò¬8g–ÜÇÌ“g$/¯MÙ¶²K¦¬%,&¤º‰ôkæN…ŲŸMÙ}Ê¿ô´JÍ#÷ˆµDÓ~Ïe ±‘ÑÁëÕã¿‘!‘:TpT”4áRƬ÷¨1é,k�>‰ì"6¶¦Î³p.Ìàš®+z=œØhDºfŽZ"Ïì l‡%K3y!drY€éô‚{ºQ×%6¶Z�jÙ¹ïÜñBÛÞCBÄcF4†å O+›Ge»2‚ËaXr5<©Çb»Viï‡Ý8˜ô­�¾7TCaÝ1ÃômˆR¾¨Ê–Hôt¹þ³Ïú¯ÿo½]Ñ0<æ¡e_P[%H“Ð+¡öQv7üšŽOYË]öXa“.ã¼2ó ¾`¨¡‘‰»è¦ºf¡ûó|"¿m˜ƒŒÏw'þ1ϱõ´g¾.r"ÚX$Æ=‡ŽÐ~W TjÞža¢Þ-î/òƒè›¥Û#}Þ¡"}Õ3�9ƒq,4�iŒ8@tƒ÷µ•o ¡H÷•B8+JÈßT«ØlNA±£§í�Ÿü”Ç üêRÌrš)P%ÊͤeC5�Ù½ Ø «T$3ܘCi;™@žD“ËY¡Ò»®wFc’LJ�“ŒÖç•[¢Æ´l¦¦Ë¾Œ•Åê_ÙUqŸŒ°Wô �›Ûe!JU†jI4ɾR# ¾‰¾Z€ä¹?o§¬†9€5ÎÙº€@?·f…àŸ1 k¦’Ý�ÇþØU9ÍZg³R�ÀaÒt½ô·)í¥ãCÔÔt’ˆ•éÿ™&6C¹„;ÏJÚŒcäTèyÎ+Í1=¯—N÷g[› �¦ÈæÀ€¨õÕ?Czh6]Ë …2‚…QLµq&~9¬ôÉ®/–º>ô:k™‹ÚÐÒÂÂÀŸšú¤T{>›¦‚ÏîÚÊ­š½Žr™}afûçòs˜ £0¢&Ó À©å¦nšÐ^® ÊšÉ�lTz#ËðªÀi¥°û€$ynô`!ßÞš¤*ìr`ºÐÏÞ…Ÿ­yŠX+ÉŒÂÛVžÌûÆÄ?�—4àG`a,ÛuëÉ4¡øEúóOÔéd¾(uòa®+€CöÄ‹NÙ½QûúFñ1ÃßÎry�+6“W˃tfªÊå8°³ËXyº* ÈXyÑx‘U‘¾Ò‚¸Ëb(ÐàNô D¼€ Ry× >ð䘳nïØå�©s®ÿ¿#¼,�ÏÒÌ)�ü4¡ŽÂЪ#¦l Üú“|Çöã燼Ërà7&ϸì× ímM>¯DÚe9W­å ËìÀƒ)¬ý=ÈL§<ÒÁðKЦ™0f9ÆÏ«¾ "ÞÚúØ<ɸ¥|×áy3ÌȰº¾"$X(1 \xDã¬ø^m3ðlÇÐûc–ôF@&Œq4�÷·«ó-opäÇGeÒ×nh+ý~ÎJÙ1-Û´%d^c£°Ð¯+•´AVsútˋ¥zUNßœrÍŠ(›Ÿø7ØÑ ÍD>°"IZ­•Î̺ÎnUHµc^QÆÈÁñ>Ë? ?ƒSø›!»Zƒ_é’˜òÿßùßùNí§bdò&Ò�Á tòbã~‘ãÖÙ&€¢Ž-Ù!ñJ}»ŠÅrë«‘ž-ÍâùýfD«yÊyo!»8 —,…™‡©¨�åOzõÑ�E=¬qmf´H³m<Ìlk©dF—Ó£â�-¨ÇÝ哨5ÈÊ¿§›è”ö{}®C‹‰{NϱÀ¥“XŽÊ-�b^ ePNñŽVؤ§ŒäXŒW˜í·‘�¶™DèUÃF,HnN„ì‡â$ùŸ÷9!f�âz<»‡f¯¨Ãl–ÔôÇõs­‚+;¬·Ð‹œ—�¨Øò…±(‹•´Ëø¨íùÍ5¼¿™ål�?ðF‹Þ>»¤žM•s?™|v¯Ëiôë(-ÂáήÖÞ†®²;m_Ô½)·biw�OM/z{To|®s½�ó,/¨¸äæx†O§É†.³Ï.Å€c#õ|R扩ŒñPOËrLEeש ïNÏ唣V4ѤxÄ9ÎÑ7gD.® µ¢®à MÕ±îF�øñ¢sJ#POÙ ëoXgžì1ë,0Öq<ÛÑ�ÀF–UîéW*™ p|>[:²¹i"–�Á÷›ðérÊèsm~SFªlXÌuœi¦Æå‹|Êé¨okûU‹kÉ/·ÿ[=ª endstream endobj 3 0 obj 5184 endobj 5 0 obj <> stream xœí\ÉŽ¹½ë+êìC9¹'���îêêûü^ x.þ}s‰-ƒdf·zdø`è"±2™ÁX_,Ôvû÷·ݶÛv7·�ÃÝÝvoîùöÛ_oþÃíŸý·òç·¿{ýþ-Äû~KÉßííû_n|·7Sþö·Û/ÉEs ñ™üŸnßÿñͦ»/¯•§~‰9¹¶–î –’OÎ>ìÖ–�+›Âzh+�\ ÑÄGp/„Áž}ŪáÁl·èc{8æþ£¹G|ü~Íóæ©­ì’ÒN}$Jã^ö}º,SPjäƒ� ÅÎn…9½r|YÍ•+±oQxGo$Ø‚¾’•|ÉL¿I6†¾U?gùÌVŸ/¿øúKß\Ðý,ïŸ�~w‰uE’ŠDÞûK®G)‚}�oýi¦5µÃ"G¾óÖUÀ>Û/Ïïß~Õdë3gï4­ ¹¼x|%Ò: ö€„Â{”¡Y >&ж¢‡ž Ü9EX ©x†ßi&ºa²�lácLí·"¯\8Úßô‰xWy fWBÙ>P°_:E²m)“¤ª6ý9³áš­jPÖM9„¯\Fb6b¢à=Q´Ç¦EUÓ¦í²­:é6v>kÕì §aN¾W Ж�²Æº1ÊqÕz@]ØYà9ëFôEP•(ï^ÎUÒFTIw3ÕkV¥[1›°^` Û©…øªìž"¼fèèèóHcÀ¥0³ƒÚÆõ}½Ò~OOLÏúþ°ÃH9¾@O¼€(òŠ(›Ï¹ºÕw•¡ûªG�ñÌbØÈº: o›»ê€À­aå ð4‚„6a6ÞàÙôØ#ôúNþ׈ϡ°Ó%C¼Rîfáìö0ÑÖÀ?Z¡ª-ļ_‚0ÃúÆ éÈ-ÃÛcŸÉÎt\2šÎnnÙ·¶�8+ޤ}D£âaÀ5Y+|@|�–3Ú 4ñ)]�A`&Öplë=Ⱦ€t`§\ľõ° 4zð­r½]&g‘n®Ëq.fSTäø ªÀh°›ˆ‚ÝíVo­é3þƒ‚´ Ëû™¦’'e4Õ‚]!�¾°†W‘Ímvs„Œd›‹ÃÆÑT4ܬ[ªs”%ë×��'rnRKfæ²Ð1åtgÌ,:>@Ü™¡dŵ™Ô¡°XPBv„ãC g¥ ÀB/4ê ˆå‚ïïU‘à ôa-ž� RIñ,»§*3ô ^¨Ê•0B�½?-‚€eoyf(QÆY†’:Ú©Ÿ¨n(Ui[šæxú+{¾ð¤Gœ@ÜŠh+äGàIRIZLSTE2 B&žìRnàœ{ÊRê´.“ §CñÛ˜gµv›+¼¹ÀMg¾«^ÎØayêêö¨ÚÚ¤ÛCt­Ûc�bü�nÏPOüt·‡^øj·Ççm¨�ÿ¿Üý¿^îö©–¾ÿ´�G&°Ù«ö¦­ò¸l^á™~ !§ ,|Cjøÿ¬š¬ƒø'ö’±F…1ß°õ´—7°CãEa2²JõÓ[}ëTûØù3YZ; !à&y% ¢Q©hÆ1À“öf¬XÕ²ñ,¶Ä;Ôñ|ø‡G4¦ño �ªQάíù ³(j ‹”“¸(`hÅ�ž9áíuÀ=²�Q<6\Ñ}-k£m`«Ö~(ÙÄ{”¦{²û¤‰Íºåö ¸ÀKÙˆÒ»e�úLé�Â’+™ïÖ›9d¢ÉŠ6¼èMëtøØƒ¶›Ï4c³DCþEA¤Â¹QX‘l I8ÁgEô‘�ÉxÁdÀe%®•¦ÇWŠïÇöù$ ƒ›ÈZ†“¡(ÆFƒ7ën,ÜSˆ”ÂsIˆÓcŽ;< 'çe¼¥ ‰xÄþbxí*¢"’°FRn’M 1±9ÊmŸéL®ï$2¹®Ü þî²�ë­òÁß³�Û&;|€†ÇÞ#J?¶ÀmX�–…�xs‹»äW8kgYÛ‘ ùÅõ<÷žÇF)‡Î¦X-L“s%›h†–-™:“PÎmûûýäˆø¹æ½è�v¶aø#ë½j_˜ã&ç°‚¾ ý8"iŸì©h”nεƒ-eLˆËîOhýÊ™Ò]9›-Õʈñˆ‚ËÚµ˜€ ¬oî�y—Èã"B ƒ{Z¤Ú¸ãédÓabÓr ýzbû¡Â"ŸƒÇšôWÇúbQ% } ±ÆLžÎ}F:Qv¸kHKÔ}zÔvþ톉~ŸåðŽ¿åüèÁ‡€:„(ý„¦G7ŒËìGx²ÇbƒC ¶‰k-§oËÃ×YO‹&@Ÿ?kÀ�A—€—¾ª�^ß½•WgÚ¡ª+--Ïòó)Çìd\i5Í<©ªVÔ8S n?« Žø¢—@P¿­º78”f3xØ—Ùeéqvsh}€V³Á+v<6ež1«ÂVŸL7ÀDE,5 AUË|Ù³8b_vY°±l•ð0\°nXª"‚½QD~SD3À‚¥Q1/n*v]L—æ¡.É+RC “B‘þüNM±‹˜e½Îù¾2ð‰ûAS4—”»Ì5RàË,gì;\‘èÌGO»Çí§ò¢r½¨ÎÎ�]§ym<¯‘c)‰Ä¼_(~)¬Æö&פåâ5MËÆ»£Â±P#]ž�÷X]ÃAÌ-L%í¶fˆ{štäüqŒü“Ë«céçahJY½¯%j-}±¹º‘~Ëø$n˜ :F[ºÈ¿¬�ÔOžìÙÄHé¬D¤”e~±„ÒÎCU|�v޵5†oEN¾Qàé5'ÝfÝn›Ö€” ÅeÛXC¹ÏÐýd’ ÂbØçÈËw‡J˜GGKmeî}."„Ù'÷¦9øÞïtoRðûò31 Ù½h“c,ÇC±Bç^øÂ6BÛÃ4ó&>þ `ŽÉ‹>Á¼lLÎQþÊ�ÚUæŒ W1 ;¹â3I ‚( Ñh]YÎY‹Ã í§:–k»˜Ú·kÚW7ãÎåîGüÊ ñ'~qàkW¾NŸïÃY>(-_�ð Ìê+e6S e´v!²"<äÕ‚…<�üš±1þ�Ñ#=ôt5‹T¿Ëõ&ÿñYuâag`ä§Î1b âdtx1žRÙŠ³ºÈóÆ9­ÌwWdP2‘½ðŒóO-Ýï.lù'aõÏNÚ”¸¨¹šp˜T/ ½�-�Ÿ‚¸|nå�ˆêÂ:š­s�á½ðÁ¹!Rò] oüÓûY>&mæ×Ûë¨;Ô endstream endobj 6 0 obj 3558 endobj 8 0 obj <> stream xœí\ÉŠ$ɽ÷WäY‡Røƒ *—û@ƒ~@ è Ð\ôûòÍÌ^¸yddu÷H3 šé¡cñÍžmÏ,r¹üûË¿.Ëey3—°…7wY½yÛ.¿üõòç?\þÙîå?¿üýËÇ×/!¾­—”Ü[¼|ýËå�w1å᯻üº|ýÇ—”GXÊÍŸ’­|~¶]°kŠÑÔ‹&õkñZÿíä­Ð‡±ôD»ßègú×}´‰hše2öè‰8Žð‰Uð¤vX–šÖÞ?a«î_¿ü<=ø`óßõàíÅØzìÉ÷1ds±�‡Y²dhõÉÙ%>â=Z§å•ÇG²ùî­KÐ&¾“,?olH¿ºD“ï˜xkÏo¼þ<�ÏÿÙ:›É³ùü—ç½EÛÞ’—•ÞÛºÚø«ÌêãC¼õ;V½‹%äSè\Üò0É.ý,‹t-Kçi­“åû”â–ß,÷¯yq©ÁÇò¨yL——íPå7íâÁÒ²¬€ã1.k)§Ð^üz>µ¶ÈUŽ`+Bé88»ÙHì oiítûUf' ¸SÑF9œoÑ„Ï룮(åoSåâ¶ý_áþ‡  ¼Öµ¯ˆçuý‚@8å]°ùÌ·.6ÖŽ8š~·åû· ‹x4…. ü’ÆÆ¨ýc_’ 7®#àGÝûN‡9ê#ë0FtÃ+Ú™«Yñ{­?Ñ+ò›ƒf¹Œ¡-FBÁºDGN¼à«éϬ£xùàLF ï[Ánß s`Lú<`QWÑFøÊºIG/²€¿]5²Šmл\MQм’{òe-m« o‡W²êø¼ãk?é(H¢Gæ”-н¬ÈÝI×i4GZ¾ >{·‹l”N$¼w(åmJP¨å°U/¦ ¡´³X¸>¿•“w] `’� ̶®X8ˆxÑ ¬ +/$ë¶œØÙ>±Šï$=0[Lj9Æb1³t%�2�…/¨kIŽ®ðLϲŸSEë+>ÔM·è03K(;­•à¤9ª™ûÈ�º Ôí6µ£Kq læ� O }ˆNpn÷˜8±Ç‘n<„›³.¸¬à®›TÃ%™ê©ípWV%X޵·Lñtm!%ZÛ§¼Åw¦WA|2zûïûŠ�ÿ¿O_ÁBbK°ÅD¶]Ç8ÁˆŸÙ4"Ù 1�ÅQŒ6˜(cv ®“!¼‰¨›'ý€]‚‡íåÐH·o/àöîè „�z›ÊæM¬©CÐ�­Èu„-€l¶ Í»·‘-2Þ�Æ/åv¿RBÛržž™!ÒäÏ ybUƒ/ýþ%Ñf ³ÿè#BŒ¬<©ggF £Ë �HDÑå®"½k±!äòÅ…Gr;’«5?:b1øÚ™ÚM¢IœÑ!4,X0,и>ÃÌ$P™»�—ÜEÈaMü�º ¿®Sò­$”²Ê/FS¯]ˆ2öcn¯^)Ñé8�šøF‚‡KÙ{ò¡×ÑKUôY’CWÇ›I‡Û=[Öèû´«sÏÅ“е<…ÈÈËóZÝtkÓœ�¨U¶ÂÙ"bÄU, [׸ŽqEíŒ×Þå2à„3ýH�¡ØØUÊ”�ÃŒsb¹Â( -B¦Œ·ðJ’ž$Êz¹Â¸Ðü5~:?Ù(Þ4Åû0·•ôŽ¢Î’Úãù£ÁØç¤ó*¦ÒNJQxýÙUnÉ�d¼Õ]-]/ Ôfx” HwâhŠ([Aò3Ü»bµfÀ?ñ >Òmÿ {EUu0@F\5ìO17 D'-mx¤šÖ�+�¢�ó1*^>\û1º»"t{ëP!;êìjXßìŠB®ô¢Ú¯æ`T�-»j†š Ä¾ï"©Gã7ûs˜‡I6þ2š4•n{DŠ|¼ðE3EÅÆVbñ„ñ¤Õ‡MyÍ»\e ‡òü)¹Q¹Ûð½\UG)…~oyJ4r�™hDÑÄ!UEÛjLÓÏ ¨ cuÛ*âxÀšÙyJôÙ�˜Ïðï£nÂÓ0mÅohbt–mH¶ú'y!…rê�16#ù�¦@ :Ä(œ”ÐÁ-Õy’2ö #×ê≯7õv/K‡!Thaä ˆèô'¬õ«üÿ¨ 7M¡×l‰‹ÙÀ‡ I ˆŸ&¨8#+ö o^‚ϲ÷Q©F¶ì [‹=j{èâ÷1LáfÅ6_ŒCu¹ìšFA€&W1�9P£3Í«/žG1¿b [O�8¤j¤ cÎ.O:;'M®víµÑë‘Ò±@Ø�°C›r§óð ÛCÏιš‘ý9ï›, :êÐÒRÂ;¯Ãkíç<í(€vZíœtdñNºÙ| —5+h©þuV/&)‘2AsŠÅ‚¢ rd„m𽇂ç„3ó¦é¿uäÄ;6 ª@óªCØQQ¸„Ê‚mý¶KâÖ.ëǰӻv.Š®œ<3¯XF*9žÉSÓ1ƒGÊxbÅ�äqL¢gJy\qEgJr¢Wv‹“‚H¥³¯µjÕB!Ò2�u&µÑïã�"׋^‹8kŒQpìHea-[$«¢ÿ.ò_ ‘’àðzwu¿$I<ô›/ù¬J" Ö ZÎGk< Nü’¡¸MQö’ëxšWÕ¬4åžJšÛÊúRBî{»géÞ®I¿îvÝE“ø,Ç̦ܺ¸Sp~+Þ†¬30®V׫±‚°i8ÄÏRR-Úç6´Ó’Òxµ÷›ßî×ÈIò?{%Zò²I£â öÆ<•˜²i5Ö‰íæÃËi,ÍxÈÚïH;¨ê û¶š„¥ ¾M7i™îá!=æ�Ó©Œ°ú2Ú,[ 'MÑíoÒlêÛ-Æ 4VŽcÚûÞiƒ¿q†ÝI¯so¡_3Õ8Ó¦¨zÒmŒôgQ·ªø¹€Çèú³1Êä+(øLkEÀLB™ä8Ü4�+–0æ”5"¨†¸*5�<õšŸŸäÕ«�õ?ZgÉÖ¹‹ñ­ß  ‰_a`�º[G�q_ÁТUq$MÓ[v’ÊÐF†nƒ“É·CùáU�Ø£Ñoñ®11ígiêJù«dä5 İòFÕ¶1Õìf:˜î²Ð<1kI“õÂ7ª?8ƒGø[øÌé”Ùè÷w U=Ošˆ~ü&èú€©Ia{íL²­¥Î3`ÍE±×Êb84P@¼ ]�’–8ö®ã­ã‚ÿ´…ÝN|b€Í¦8iM*�§ríb�úÉûµïiê‰ œöÝ}c;k—VÛÏUõª­Nî&Uˆ®Åqýn5µ‡!Cqêü{.îµ:ÿ'»TkJdé\�Þ¯Öï'´s…¶Fë¼W«Ê�“ƒ”ÕJ¡÷±@𔋠b÷š?_‹O¤�†p×H2—gÊyZþÀÿÔ�뉳<éh7fúë 4«¾{ëùg;~¾àx4‚îß§1¿à†~õ —Á>æËR9nL?qþ��útãù7t›þå� ØûC÷yÙ ¡¿©+¤B^øcc¶ºóâ§Ý¯P[Š{×�#êÖÉ7Í’�<Õ˜ Ý}èL­0ê3? ¾¥� ¯æñÊw|U C‚¾>è‹÷”�RÜ)YöAÝÄŒ§©b}Þšåir§µ$#ø=öò¶O¢&ÅHõ%KcóQ_'°?qiUœcüˆœ +ªä8ŠÑ€ýtâ[ã8wcñ!é(§„Iä¡ñR>T%€$. Ä.P »¨‡³ÁomÆ[„Ò_klÓòVôÆœ‚´Uá�•õ�ˆ>CÓkRû6 Ð÷k¯Ff²°ñçV¹¥~ÆRÓnao/'á�­xèüxà×âöÉ'Ø�NQœ“^ÖVºøAÖB !ä 0LB °ê¨EÔw ‡ ð%õ®fù½’G1JµèÖ£SàÌ'ÅŠUwüåH®I·È~©dÔÆÀ@|L¹zî À:‚]Î'›švýÃÌ“èäÁônø±J†.ÿNÏþN:%[[UÝïËÏ> stream xœÕ\Ɏ丽÷WäÙ‡²ÄUª2S÷ðx|0à¹ø÷$c)««gcИ¥(‘/"^,êåößoÿ¹-·åm½ùäßìmsë[ºýö÷Û_ÿtûwý þùíŸß>¾óám»ÅèÞÌíûßnÞÍm…ÿúÇíþrûþ¯oÖ/ù§_Â�YÊÅÕÀ¢z5º°Á/6xüÍDx®¨�°o�.¬áQàä±)ÜáÏšcHÑÕE¶�wlfqÖìðç£þæÞþf>ì»Y`½ ©¾ÞÃIpk·´ÉŽîˆï±xOäM–yÚ¦§-f‡íq >š°ÖçxÞ$¬Rò r=âŸ&øð$a-,™¸D^ÌÛÍ’ñÁñÝo‘_×$ìå‚gÅà;;yx–}§�ˆ�¡åÓ‚�žåòóû·_‡øññã‹içëÛ|# º¬ª"&X<š3€vÙºÉuלn ºu‘«õ,ÝØÂ“±lPŠIîyäM+{­Ò‚ Ske9Á2ɦŸëõ™ž¥S�Õþt1À[ׯF8M`¼0Ý$fZÿZ¶žX´ìo©(yYg+’9®`\Œ¤[ãw-È€¢lQ¦QœÚtî�ÄzÂÅʇ=[™V p²(àA¡¤›7 ç¸ õ ܪ øï;ga=åœý8rQЧ„,+~ž�¿â.i|êEcÞœèg�7©¼è ùœ€¸ôየN€|�·ÌϾçEÙÉÆú“a,ø-;n-ißä³l24‚²ž|¿=¾Û‰ÇI Ú Æ<É�¯®ÑËã—‰^Y$ä:_g³I¯#4êܧªV\#43€¼Ýúó¢íÐ5¡4zÕ¢Ük5S <ô÷Äå‚÷,œ£Dd :Ÿô U߃ªk¥¶Ú;(vˆºju±Q¶µÛF–Q�¥ám ùÿêM‘ßá,Ip•“–(ÜQ‘í=!ÔÒ}·�nBØ).ñ�¡+¼9R •C›VsÀ šŽŠç ›ýov ä§UÔ¶¨Qƾ3÷)«±ù¾nñÈS¨Ç,Ÿk¨� Ò"¢DµK*EªOQ*.�#NÞ“è9hæÜw‘W}²bäÏêGIÌR>Ë:Ù¿)†.'TwYÕjWµZóईYò÷îŒõ¢S!p™ó  7l ³}z$HƒÝøùºìt+εJ‘¨XEæ/ø5Ø ¼æˆ*çÑöÄ èWö…�Ö·/ {öýüu¶%ó9Áê�öÍ`>'Û°èéèc#:ûa�IÅσÿ0ëÎ÷^Ý�µ¶jÊ8.m€ ö„›,ÙéÜBÐ3‹ÝàWt­âVpƒBFlKÌ­5Äò+d¦¾(u°x«¿Ð¼Où½Çã{rÄš:xöÙ„-ÞõÙŽ¥i3ÇqB…} ÓÃUùé`pìu[�Žÿ½ä-{Vy£øiÿzNæÄ®YAÃó ,0_°*#�§IÌr…ö¦+ÕKª³·_ v´ópÔžR§Ã ,Æ ¾6nþŽçeWëÛÇxÄ-ƒ¼ò:רyþ^ö•üŽÐ<’ï`JfÛ;ÚÓ¡ ÄöÐv¦bt¦Ï!)àëäPÒ ^þj¢™cJ�ÕŠ6�ç{IpÄ�àî@†¢*E|¯Q ïTyý3»Ô×¢dqë¥øJ×ó3•Äm‡$î�µ#Ïý™TX¼KT‡)µ¿'çå&锇m%•QQÔjp+ì°×)èÎ\Kà}&_™¥Ui+*qV±á ½!WÌp¿ÊÕÍ)jIŒ¬cNQ«A™ž¢Jí� ¥Õ>²'T1%± œ2‰,cxx„×Ôd[j½N?7k�ãZÎ!D#µ2C <Ô#mUæx4ÆÔû ØŸÅKì�ÎÂÖq´L«Zo¯cÈ[pú¨‚ã³Y‡ÈæZ�2¤×Ò¶ZB*ø¼SäWk�‹0¸iãhdG÷V뉰ÊSqª/¡K¼³‹÷3û×>,SËÐ×x-n­ß¼¸¾ÉÈ¥kÈe=€xgÞI´©-8½¢Ôü‚È�'Mâò‡Öµ{ë‚ôø,Û4¾žå¢=ꌥYªWÕ,+$!_C&+;S«âšËA:“WGè¼a=Q+¸ÏÉ=a�NvÌbï�äYnª(Æb£õæB¬u1Ý@QIq0†xŹk¶[_™¹æ/ –”kËDUü¡)´Žµ�kê£]ê4’�BÅ(šÑp„ £Úe¨ÂÖd»&ÑT3t§Ù`­ÑÎÏ3¯kön–ûJmPßÇÀÇvµªý]A%¬ÝÍÝjÁiá…OMŽ¯Ê½'ëà8�¡ìË«ôëkŽø%*òNZÑ+|ãIo‘,…P�Eþþ]Ÿ<5BŒTñêž‘¢Â_–[»´þÿjº–�Düdd:=ËxUQw\k‘¶½ÕõOÊ¢%õ¥Ñ�qY|@ÔÆW³w®b•ó*Ô…^ËXÁ÷?ª+o—¥Ë:%×R‘›òb×Myˆ¥-�Žú–mvÊoÊÆÍ¶¼´méÞ‹£û=º÷¹]O9¥5°hƒkËe+Þ8”þz[]UöNþˆ3ßF"ìpHiziï˜,™nÃôI��\ÝTÓ�UølÝÍà Ô6‚éý]’„“¯4¸òÿœcÐUTï­¢€NeêÀMD{¶Ó.{+&L‰†6á<ÞÖ Õð¬%ß6¨º}m(žz�äð¬*TwS +y™Ã`:·#¤>P”<ꩆÛvž�×±·ˆØŸ¦«ª&=}.Â.=¤< Ê_Qi8‡ž3\`&œ«¾4Íåûä:‘5ì å‰�´/JqfI]饔faG�%usÀZ!-Á¦9à$±¶™Œ?ù ÏÍ #Å`¹®oÓÁ¢—Q�T­3ó0ŒT¨l@ÃíÐr娵n ;n¶ÈµñD£—®ðݹÈ0üèL¤›†ƒ´„˜S;œÅ¦f]NE„Rm �jŒÊ1ú]&,T›o�Ê}tÅ€yêÕ6=^úVÃF&˜2´ƒ'“Šl7~^¯^†ˆ¿0’5¹>›–þšâ›viÎ7Öšª=W¼›ît–=þª®A| ízrX°Âà+­8a|ŸÔmkª|¡Y2Àèû6iú(FI1ç8ÂRæaÄŽ¥i5úIÇ)#¾ïåÓ&€�û~p•žÌžâ ½Kz�¿$�wlu?ð2ÆCÛ•èk6ôšê«¬n:@®Ê¹RM²ÁAå¦äņø“Zþ�u¶SZðjá:º•p>)�;Nê�H”ò8ºL\Ò©¸ÃpŽº¯<‚Oý7C¹«™t¨×>‹ž•‘Kmàæ�\Ý&Ðà /´ F…³‹/)ó‡šõxIÙÈÐðuÞmOf}v ¼Bx�tœçST•„±�B:–—CqWmõ=Îñ~xª}6ÿ#¦Ä9Ž‹iÍ™Ý9g}m²¹¦ÉÙ©.1¿ˆßÃU͉lÝȼ®,Òù®P-••aöc5”Û%òì;Ë1@ô�6AÊ»9ç¼…íWhˆŸrÆzg�‡”»áu‘Öæ¡ÿÜðL ìª T´4©è½6~ó(Œ€W¥Gz<ä²\Ì\m¯5=;wûFy¿;å‘úÐNw:œ¶°¹óó�gé”D≯Õ3˜h ²’º¦}Æ1Š�'„îaó ζ¯�©†?AÀ3³c÷ĩʹk¢’ÑgCl\@³kÎCs�„û@úÛ†üµ°×Ó/šy½Üˆ'� i�Kw’òªBI’*Y8{êYØÇA_ e¨Uó¨ý ž+SÚÚghñ8|èwÌÅixS—-Ö’ËË`ç§‹Ÿõ Û¥9p\b[8ˆÛ­Jþ Ü° ~É KÃÁÏJr©¼Ã8«þ~ƒ®²7øÔ­ò|ŒÞOþR„;› Šîµ’G3Ýjü§N,—Æ&“e18qnᩚž9e9%pþÁ¸vl/me'FÀ%Ýoú®_ÏÉùÚd+õ£‹ltérQŠxGwD…Ú'5컌*�öÅÎF�mÀûôßÒÍóÑ\±ŒäØÃG.ÒÉïl晿ý¶z,I†rçÍ›�Y8¨àÀŸ– ]ÒôˆJS jò‰†”Øò šã*&�Ö?P¸Ýr¸^— N&V‡A¡"(ò4}JÊÎ Ç nZ€i6ê_*a¢§}ð¸qh›jЄëЪù8ì_ö•›©¤\råŒ_“8õ‘œ,óA»AÆ!¥ßŠ ?™boý'»hµÒáŠK\ìôês4ªÿë öxèñè!:èœó?5¶¡çSžœÜëyªS Ù`ÈTª‹‘§rñ–K_OLÊb–ñ7¢·MµõÀG¯> stream xœ}T±nÜ0 Ýýš;¨%’tè�½8 ?�¶@‡É’ß�h‘’ë;^ Šä{z|bpÓ› .øè° OnÎÑ÷þ˽|sÿÚYýÞÿL?o’Ÿsöàn¯îû .Ö¿ßî)—ŒòA úán§53HÖ]h¥È™ -Ä8кådöÙrêç^çJAOV† ¹J·cOåa‹�µ$L !%­†°ãØX[³¢•Q°l�å6=?”‹çƒ$ˆ[É\µRŒåHG¥òxzWÎŒU5Q�cì îi^Tìúõœ<@dL‰QÁRq“vG\�;LïiDÕä£D±²n÷èuº5/ƒñ¡r#@•Zõ‰Ð‰t�+7¡0�ÑÆÃÍéR…BÊÚ’Og²×Ä+�`ˆgÄy+Bo8ß›Ç,Ã�—�SnÌòÝ�º“îF„Y�;°˜¨QÿEËDÂõ•DµNDº™hHY�ÎéÔ¸ ¤9W žš=Ëšø¿DLeƱ›r�Xe»šêë÷f*>2²)�‡J(#ï3(ª…Ø|AÝ޶K¤Ý €~ò`µ\>–§+TÄN­š�ƒ9åm£ÕÒuçÅTö~ˆ»“½¹ç~ÿ˜G¾Aæ¯ íýÇ!i_ÀC'ÝÕ}Í‚Ú;î¸~rïöå³ûõ5a& endstream endobj 15 0 obj 504 endobj 17 0 obj <> stream xœíSKkQþæ‘I�ö >6aUÛ…1©´"t!BÁZh0"ìd:yÈ<ÂÌDӸѥºiÒ.D\w]¸+þ7þiýf2&Eò<0÷~ßwÏ=÷ÜsîønÃ@[� ê–VO hïá´þÈWKƒ°ÏA®˜ÍrêÙ—äŸÉ׫†¶ñ±!NÁ‡…*…§½{qò5òéªåo®c-A¾E>f:º–BŽP|ÎA±´Íz·þ‚ƒjk–qÛ¿s—üÏøTw> endobj 20 0 obj <> stream xœ]�Ak„0…ïùsÜ=,Q¡7ŠeÁC»¥¶? &£ ÔIãÁß1k[è!�—÷¾äMtÛ=uä“~å`{L0zrŒKXÙ" 8yReÎÛt¨¼ÛÙD¥…í·%áÜÑêZé7ñ–Äœ]ð¬ô�²§ Nm/º_cüÂ)A¡šŽrϳ‰/fF�©KçÄöi»òxß"B•uy¯bƒÃ%‹lhBUEõõÚ($÷Ï;ˆa´Ÿ†%YJ²zhïÙãt§ö±~Ú€]™¥Iž=WØ÷„¿ßCÜ©¼¾Šôm£ endstream endobj 21 0 obj <> endobj 22 0 obj <> stream xœœ¸std_·5Ûì¸bÛêØvÒ1*IulÛ6ºÓ±muŒŽmÛ¶ñõï¹÷¹÷½ï}ÿúF�Qçì¹Öšg­¹ç®qFQ’*«1Š˜Ù™%íl�Y™XøŠ '5c[yFQ;k3À_� �’RÜÎÔÅhë¬æboo š©�ì\M�N|ó¿µÿwÙß u�³5ðñý h�@v¶|ÿ¦s;ÿÄ��ÿ櫹ØŒlÜV^>V>V ç¿íùâÆæfficGGЉ���RÌÎÞÃdaéÌø¯[�†ª-==Ã#¬¼¼¼�Gâ@'�…-€êüE]�ÖvöÿÌËû [[ƒLÖö–Nc33 Ù?šÆÖ@+€$Èdooç  £ýŸ,»feüûņ@ �ÚÿÎ÷¯ÂÄ–´s´þ“ÂÁÊöwBKgg{>fæ´4ÿ'ÄädÎd tfþËI)ak&fgóO7Nÿ‹ƒ�¦•ð`þ¿wËÊÖÎÍÖëÁæ [³m“™‹=³†-ÈÁ(#þŸÉ!„ÿÆ,€ÎN6^Ðt7µdþç‘êöÀYÿ��mÍ|¼ìíìæÆÖN@�9ðïÁËÉØpvtúxýŸ�ÿ¹B`e˜�L�&@ �-³ÿ…�æÿ±V0vv¹tY˜þj`ùçó_wú]`fgkíñßéŠÆ6@Àÿú¿Â¢¢vî/FVnv#;Ë__±ðrx¹y>ÿ“ê¿Dø·ÿB•�AÿÙ ËSÊØšÛýåù�Aþ*øŸÃ˜]ÿÃÜšÌM øøÛ¢�3Èø×*ÿeH=N–¿^ü{aýõÄÿË®ÿÿú—Ø?LÿmÍÿÕ¡¤‹µõ¿ä¤ù9õtÈþQô'Û€¬=þéÿ+S øòÿM£öÈ `–q6þ;Œˆ­…õc 'I�;ÐLäljù¦ûÏ€†­ÐÑd T¶sýó+`dåäü¿ƒê– S+[ “€‹÷_1 ­Ùÿì‚YÂÖÔÎ dkPsþëncG³ÿþ ›º8:þÕú_Ûý·ößksÐß�@w )‚³P0æ­©uÉ·ì�Wå†6j:í0ĽŸ´'zè,Ÿ{ÆÑØi¾ùßÑØ]0h<Õ®Ü|&k”UΦ܌Û�ë2Zqì¨~ܨ>‚r3äb&µ¤«nãØðhÖi÷–‡’‚Ç‹ðÑv÷›`ÑZ~EñÃø¡iüÈ•âXÎò–A'ßpí m$pæ^wZ&Ÿü¹DÅ» „ØéD×w¨_ú=qsã@‘G®uöÑv�bDOÞjßQ¨ùj¼Ù_œOöÀ/1e pVls›ÇÉüÕ 3_Dëlv›¥|5iÎöGŠ9ÑæïYY&y©lsÏ—»Ì1ÕŸ‹ÞíQ±üh«‘óÜvXŦxSÍ?]t‘h —Ðe¨ºñ›mWš˜ÜÝST :?„ö&q:cÌø?· ’¢ {l,b h<®Åhça)îa›æÃ˜|o�® /áž�ýb<}‡ æ�Ø-+2X8$3„®IzÝqû5!‰(²ËcMX¥ù ËHM;íÿDq³O«&ÄyiPô^ec¦»¡ G)óY`Žê|&pøšp&Q‰° FV!Âßœ’CØc4]b—7Üž‡$UñlåRi×ï_}ÝÎÝËú¾.i4•š|@b`gydïDr*‹ÓK¿ÌSuU÷NÐþ‚WŸ@ç¾Ê ps¾rÊƗB˜ä™/èñ 3& ¦ˆ’üYµ÷[*«Î÷ÌSöзR=kB& [øÅ‰ð>¸&êÔQä扉ĥS£xEDY=5Iw Ö>IܽBÒÂå„�0gh~ ÎE—ã€�rÚç±§œCÎÊc>£æ¥„ö-#!Ì_rŽzZ¼UES†Žñ0Ò¥êz=~q#§öâ˨­vL¢Ë/c8±eˆ:ÏJˆ}osœ|¼~¬æóˆR§nÎbQÔià£;‰ç¡•‹TÍT¯×°¡Ñép¬—cÐTˆ¤¡ÆXš,T€.ì›�Ö}b±õf»ìø~C.GÍCÌkü;;åûw‹j«ÉC³E¨pµ¾�M95m»En=çÈ~]L2€œlžSZ‰AéÜG7Dä®"5Æ`ø>ÇI†ºÏ ËŽÛ´­"<äpT¿ w�jœLT5Çe-áL<¼ì@èÜ‘ƒö:Å@áx4Á•¸Äùni—6>�® Ú<m [%ØípÊÖ<áL=à¡Uî êª‘úÀ_‚!clPÙ‹� Ô’@tÓø6ÓîE`k¥­ËÂ’}’¶I¯Ÿ±&�3§¤cú·JD4eŸÂ2ëuMأ㼅†Xºhø¼Hð·€íw† 6Ô·LHrèýþŒžrO†tèr¨ Md¿ÐÇ—|õ4þ!¦Of±hÌ‹æ^2tÈ3ÚŒ—ÂàqK�Qó+»aèìµO8!z�13¿edŒê å@Uߢý×¾/hƒ°ù¦rÙ3ƒBg¯ŸŒÔSÂNçÏ6GûLw“«½Uî“„HÎ%Gø-;ýLå°5ÈaA‹Úap¾J�yÕcÀoÆÈF–ZqØo âó½¾8ieæ·0h„>šb{ icâ�¾P{ó”, ž^‰¢0:!¦ú̶l€ëLXÈB¼ƒÿ€Î¶CM;ÂôóCùs1âËÇcë˜W¦LoÌÙ<Û8œ‡ôWfP‚“’Öê&Љ„`/øvº%›�¤¸#®ÑÉz#D /}ÍIXÓE-ïãžÚm«Lbµ.À`R–�rS`e<ß§¿±˜0ŠÂ-­NšµÖ˜|º£Gq<Þguž²_å¬çì%vŽ[±RÍ0=ncî¸-k}=ПcBÉý;ÿûcæ› •˜O i­¹/µô 0ûH#¼D¯þÔI °�ŽD¶Èé``ÝÂÿDKÑ,ŽV;=Ðë�Ç¿£[@|Œþc9æ‚Ùt´¹í£ýUI€åÒÆ•O¢:Ã%Mx•¾­«r£ ²‡¸—ï‹Î Ä�YÅD#ÃH k®‚ƒˆžxœŽ¾2�¨/±¦þõ,TwWô�ƒ~öÍ!ÈÆû€�g7¯Hu]iõ&£oégë…s¡’`„ë]tŒ!øRy³ ³ÕS†}hr‰q^‡ BæÑ÷Ó:üoK«‘ß: ¼œÌ¼>íMŽÚÜôß³væ\;NƒQ�ðBk�ât/Öâ �ó¯x'tÀðy5Å]«]ên/�5ƒï°AÙü«êk®šB^ºœsÅöú¾b k˜ÍÐ&ŸŠlHr®=O¾²Ù…‘ÙH@<çâSUR²Ò‹գ"œ# Žl»33, §F “4å�‡žã¦‰rVž, ÝZÚÑ«Ñ�øÉó÷ã>O!¼Sg‡šE\vJéå½Å).ÉîÐV1ä¹ïÕËþéÖäN£’JÀWÊv$Â~µþxˆñ±µK K?Ï)q¤gU¡ëò@ÊœêS;¡MSA1¿õeÇ›b e @¾–—_lQ³Ážý•,Üq±D$Ùš)¥p¯.‚�ÙÜr¥F–ÞmÈ*Ñ•6ÑY3Y*t�j –ˆˆa·F¶ÛKÌ¢óç\´u„é¨`fu£W§Wö¬©]ël3 ¯=G* �ÚÐPß7©*u»ã�_ ZHõàùõÚÑFµŽªÔ8'¼ {ÝS¸ cç¡Kàþä2[�-*û¾³¿æÑÂJòÚî“;¡ öK>»a¤è³÷ˆÒeì¤":ˆV%ÏǨÔBÀ¢Æ-kxÀÖv ²®.º¹RªÆ¥Yó7EÔ4»5Îêói«¼�ú¨¡ƒ”Þ›ÎÈò`9áÔíùìõ>qX ° Î7 k<¥ÑÒ™w­&5ÅïÙ²¥cIXnXŽÔ×W¥¶Î³ÆU0ê³úü8‹ <Ž'$úƒX2Þ�ô¨ z¨0ɋܚûeˆ¼œ¦ÞWk•[9¼©¥.Zö­öÐÓ†\¿&ŒðBžlI* d)± .RÀvÒ®ì �ûhQ¿ß‡À…K¤Iþ`Ø%&³š!ŒÿHxw²pŵ…rÉžg„‘ýM©tÁçG>—õ¾¹¹º}+Té†S¨ áè-ŠD�­/±VlGÅk7ÒûËÓ:A_½c�!t=êâEpÈ·ÆÐv"& ‡yÈH4d-­î‹ml“¾%¾'ÔòCwÀŽ@>í™kO¢B¸JHçôCKl^‡Ñ Ä�pçÀÞ ¡Zxp䬭^#)¤†íRvºb=–A-ÍùRÛߨ/þX¦I2ë{ríÀÞV²n[yâ<'Àä{Òb2l„Ã�›�ËCM�t)Z+·(2Q�‘-V@L}®Áxm`~7ý|¾ZÓYÒßѨ’ >‘YО¸øä�·Ò- ¼örx!Ž8S·¸­û›Y¤– „ãûã‹lŽ ö;Ô Ãñ$Á=c%Šä'Ó4{çPjΨÖ1‹]‚Š‚’†&lB-¢n’öô8Ö¨)ª±˜Œ…m76G¯7$êr =—ìI„?}'`ãÆfj ,sR¶Xî6ËÍn:™ ¶�{Îën[|šé"Â�ƒ+=ÐøÀu°¹�ÐD\¸uïgZ†=Œ9{Ûëxï*Î(/§5_•±}ŠÒÌb&~ªn©yr\¿t„É-L×(üótôÞ�'oM¼ê‰žÇ¬hœã¢ùeÑ0x‰,yI<ÎT˜àÚʶ/÷áÓ/X=¯V¾®dªáísÇÊ—ŸÑTŒn˜Øý|ÇÂÕÎ}ê³TâѶ°•D'-kÜÈÆÂwœ;LGÖ%ÙÐøp‹ÊAÛ"Ï{E÷é›W·g„mDäà�hHi {|¨¹’¡µ-Ì츺W¿CSš¥Aúâ”=XþzÇï’,VûÒ9bÝu0¸÷ÖQŸ›‚oñØR„qe*[Ò%ähË/ghâ:…Sn=b÷R­…Ø™ó÷îÓYáñ%GÙ6È Ðw*¬} MÇ0ZW\¢åìY§tõ· *ŒuÄÊmä=®E³>ýñ Wý°l?r8ÞÒÝEÖ#}Ò˨‡qO̫Ͷoq‡Ñå l ž"ÿþ:v½á¦º}ºúÝå'\eëp×{†äu%š;ÏU°Â0“»^ù ƒÇ7ü€‚ƒ1˜ß¬ã¤2Í>]m:ôQ\µ.L5—~£æÜGw¨ƒO#èÔ³’iR÷ã™ßdFÇ49TŠÖhÀì˜ãdØ�oÜ‘‘îš51{XB‘ž‰ÆõûFBPl骉‘)!5 ÐÇaîÒrŠ£MPu¨õÄÃøA§â—$°È¢ÓŸ”¦R³üs¿èÕГÛm%†­ã>ÛY#ÛÛŽ±aSNËx‰¿ÃYÐLÊyKmŸIã¾*sù0 s�î`Òöß“üsmÛqd–‰¹�&]±³½Ù¾™šë)ÊÚm Í¡ý˜ä§oŽŒóN 0¶¹ôjPqšB%POÿS¾yìNÏ…Á³«f/í[(£Ù ‡�!qà Kòu‰þdn³_ÞOˆ¸1¾Ö—êù~™F„^¨¡Ã@Œ‡KMóŠ�¦5f� óÈ"Ÿ`«Ï/38¬`·ùüó‘øCë$µs�ë„ÖTë³ •ÜY¬.K›·Æñ'Ø¡Æøgí!ýTùÇwiÇß �^Ý`™âJŠ)D% ä4<ñ[ƒ1žZÝ1@`ž9©§G¶¥#á²N€¡³¦�ÝìœH‹›“ váXWÇjù·?ú�øtÜMúúµªd• •ƒÙÒPÕþK p�eqZ¿ËÁ‚`áú÷,Ñðò®û„m¸b�È¡¡96Íи¥æ‡€äyvç�ð£ cCÎn�IÒ)­°aãrõ\Aظõ\¤žÚGqk=G,Þ[€þ¾À3(hÎÅhçû»ˆÝ¤º ròÚX×Ü¢ò­V²X ¬Î¬ø_ B-˜’(=âô䨒uf¢�_ú1«W‡·¿ÕI,ª–÷p~¸ð¶A3F…Œ@T¹ÏÃ-ÏDœi3�ý¶QÛ´RßIt„[»¢úÑrZF53W5ó50r8!âÌTºèGt|±› Ù?làd¿:Ü)”YáØùÔáï\X§Ÿ›y¿Îìa6ï¡b¸‚åO÷ÅJâæ'Q))õ—Ä7‘cÁÜŒ¢/-ýÔ½#›Î»ŽÊÌjºZ¶^ŽPi)\šm®O5&[?ÁÍÐ4ÚÛ,•Nø�²äWòtÛ°pÔçŒëpËCŸ¿ÕÜùǯ&Câøë}o\|�v¬’(,ÏHVUx´¬ÌeƒXŒŽj,é�˜nâ ;ñD“,jÊ÷Â>Æx ZGeôK�òÍ_•% ”À|I§ëÊ«~Oþ-X]þ–x€@’%Ugz&SÕ3ÀB´Î�wøâ¢Ã›SZ[Ø`»¾�ÕòûúgEÄ?vÚÁ r–üÛ’¸‰Èp=7ð ¼3ba@·h4íóæèÇŽ{Å×¢�Ã�ÇðùZTüÎ{ÂWpìÝö‘¬y A£ç™]a¤àK>†q ŠŠÅ|°^á’Q.ŒfÍω®HÙçn²ûØba¦‡âßÜsÖœ ˜b‚ö¦ì¬­ÊøGTð{ùµIZ’á�¶Û1°F F çTg”ß.�ú£óåáH²i‡’N©Hg¼Wéó¤óÍçOñ]øêGsÂg]fÅ´ÂÖ=qcž¯Çö&0åÍ�Š¿Ô¿lj5dK²ÓÐZQ' 3ˆ9ºBÄßEâ¿ëž4x¿ô�“²™x¹I"S˜ AKåt߇ÂhÕ‡`úæÙ�8 6²µ¯«‡[Aœb’5¾�[\jþû^Ãú¶¦Ÿ¯÷ª6õ dÓú1KS…:Ê-¤&{¶îâd¥Y•œLuLÇ­/¯6É©V%ˆ*´Jý–“÷³È¤ò{Ü…9ÿȰQ_£›?rJ•Ôw:*} ýU/ι>¨UXþ–¬97\yûNBÃàÉ%·Ø¹lŠv!Öo�”ð¨/þΊøÐ9=‡),“tFûƒ|HWé¯ÜVwró¦ÅkžÍ$¡dÅ…Ó‰ñ ãÏùÓ ÍãÙ2…åá&éA÷sªIDÁ­ {\&u�•”#ŽqÔ TÏ˱{É{§ß§Ýeå×ë‡ !¿úL¾ÎûŠ¡Òê�#¼^[„C¼ïkÄýYr‘,G�¸®¦U µYP™?}ßruÁ12â+¿ænG ïâe00ü²œ['=ou [£7ë|Í2:¯N¼³ žúÉ(eÁSñ9CZ�rÓ6atá±g†@ƲkNÁ¯'lŒ$@Ø�(Ç±ÛÆ±CCp󨀝ÍsøsΓMƒàrŽÓ~Wi7 w_ïÅNŸ´³©ÎõþJíÎÞ×@sqáG~âî=ÄíΤÖÂFÛ� 'ÎFf�:ú„? L30‰Q{¦X.ñ:ú©E u¸Wb•+˜–¤¯å/ˆ'ŠåB9PˆË¤ùo!“˯‹­cú6ç*LGCší³Pº³³(JJŽôá&ý)0üÊš=9P-ÜBJK2úíRérh…·ûµq¾ÓÚÝ—pŒ— Rø¤Y ôªæº]4k@¿d +þ½néþº»e¾Ê ¼k›÷tú±·K|»Ÿ,ŠMmöÄ@D¾t¬ÒPR‘#ŒÒ_Ã0�~öaʸ PxÊ1«¢Οc’‰äÀìÃØ•º%‡1=úò+‰²ù,ìGÉàã#^̹MüFzsÞw­*î�\oQ‘LÁ·ç²›ëíÒ11ð;óÐî&ª}œ °rxÙ"œÁ§Ý(@Éý®¥ʳèe‚DÝ â=7�䘠»‘ºþtÎv_Rz4¥fò­±Ö,Xa­->Çxçiµxè>û56º†¿ˆóø�ÁAΗ%ìÖôë«tm�ää»$�ºUÖ�Ÿ‡Ÿaˆ´üö®cüÙŽm·"kãJT3…Õ· ²íkÐ?\.šÍËÑk"©“Rd™¸Ì©vï’¦†Ž¡Šê³ì¹â"�àŸË–(¾‘v4ØÕ›Ûÿ9ñÁ;+Lvõ6Ñû • LOâåü¿©e(ܱŠ�‹D¹z¸š>“BŒ'Væ£j»°ø-ÝO(o– ÍwÜš ÁäœFÈ¿‡á“:&¿É%úâÜö’ÎÌŽRC´ñ¹ýx§i{'€,¬¥šQÚöBþ Ͱ7ûz§j×yá×AÕƒ_ïoHñã~¥CåÒ庞ØìöOäHÇÚ¬~eù»ÀU¹µÚÏR‰ÒÿÄx…�C¯àæ�j„ï|´²¶–~;ÝÓ�r05íJŸXâið¢˜I’CY»™@}CÖÑ{ep‹øZ+K­ŸÏ}ûz`]0¶#½¤FøMy�³«E«~šzæ,¶x„¤3ó­œO‚Œ¡6Òí9ðó}â`»>×#¦­ì_íÞ£mB¸í™51߯"]ë?…ÇjdŒ*j Rj’‹—áù­Œ'á½Ýó“Ñ  Îoiaà{‡·°«õ]ž–§@ÇaÕüCQoµ›´W™Põ¡1ûš²ìIm1KìtúÔ¾ùÄ æ[Rzu(R,:8ý¡i.H˜ødHĵðE=s{ObÔ> ™nPw澂ֽvØ‚‡1¾/èk©7ç‘¢Üg%2 ‰XZ¸ÑN1rÎÎ%¯Š‹¦¦ "B�°,•b·)¿9G�yå¤ÈOG ëªö'Ê�QÿBš“¼c†ƒïQ“_8mGö'�Õ oõ8Ž ÕvÔF1í:åK4…z×À–U€ÚÈMqB®;¤y )íÈǽ€µ°Ïf-¨“þ4BQb¹;”Ë­§)´íÝh¬næ›s©xÇ+4<~š7UC³ºû*Ïõ:U‡wx™•ÂŒc�Ôÿ+H?»©]Šózñœž¾|£Õ¿…öÀbÖÞ_¡�ëç9]šh‚Тp‰ã\Æ�@×áì!gßþ÷ØF™ ûêxf›©I–}ñ�W°#æ ÃÞ$¯š›KüÍNuÌ¡3¤/Ä2J‰Iҹ̚gz V»|>Ÿh¼ºm[u¨[¬ IE%ê?7NÇ1. ¡Za˜ïe;ËAbTJBXÎmŠ ï^??g«Cî `-Ë:)àêšÈÊ^xÚó³Dtg™zÚdVëµ ò(P ‡H$‡.lßì´ "%¯ŸNÈý¬•¾ð"î=uy#ÊÜ®– îi–‰öPÙšýJ?Âܪ…ð$UPÚöè;\|$›é�îýG|_3§Fý4™+ízr¶ÜÌ'j·ÈY»u»$�ärºG=?2U‹žüäŽïh¿‹ÖäóF_À~.x 0ÇóA5Iìý1P͘Eºc:ïãÇž}»TßLé0i_ý˜n5õùUýڤ܆ãÇ<ëpz‰}ÏDÖ!� Pœñ®�ø'_ÍõÏcâ&&“½Ýî­²`Õ¥�•¹%.«¶§ÅöSåæýzÛ­U˜ó¬ë4 Àúžš„UN¨Ñ@Þ,šr˜·+HŽ?1 dôMi¼ŒAV0Zc™;ƒ2ëT�ê£CîöõoèC·èkêsù{žjd ],Íæ’îÝöŸlN‚[VñÞC¡irÒ IÍ¢h§ï)½Rx™r3�*âãT$‘�³‚­°ÙòÉ�J±aª;^M`7UŠ"î,OÓæ¨î\Rc;Hñ­éÕ+�û¡Ÿ³? £Ô¸IÄü:Gž˜ägicÐIí¿ÕéÖÌà ­IpÄãlžù³/WjEŠë •7T§•Pé9x|œa(ì úªqR·vâ0„îGŽŸ¯‘·G¯vçT�ñ™Þ q»ÞÌSÑeM‡rñ7u²·¿qó·Ýî÷4Æê"°JÀÙÄ`ìkŸžƒÌ÷ Ûœ²R~vgC›Ê/ :öáOà°¿Þ&üˆ°t&^+D§@ÊšË4w1­»éÍÆ9�a1³•_ij|ö*ÆÄ އÀ²»6ö(§î‘H+Û²ýÊ[SS€ATÝk:ryPg†¯ u €{:í—0ª� Uµã!+ì ªÈHA »ˆG®Œ&Wy*¥Üæ°PzH�þFn.ê÷n¦Çvøú(×:Ñ~ÿ40�“ÃNcØÈàX��¡´È›P?ΕãEgTÈŸkƒîoú ·¶ÝB?´·z¿s;ö»oÉø­Ê;È7¹¬3/™áCWq^Æ_~&ñ°çÁYŽ1�‚7k$úÈɇ.­�X¦h®…LÞþäÂd)>k.>ïO‘ý/2Œà‰U³óì=NÓ gøŠZÐäö%}?ÙÚ^´Æ± –��Û<¼7›~’DZlC×'SJÁKѯ™Åz� êp^<°�m4É¡ÔCÄ3qµ]/è¦%C`–çb`þa•÷„¾k»Q”å-6XØ‚°|Q�uÛ4ß)ÞúM QH]1:Ç@/Èl6©á,Ôà„¨Ÿvéþ Ž¸ÇIäú‹Ÿ%þ¬r²{ÿ%X¨)-*ÚpÄåB7ë5•ñ ç:Bló ìy÷âOícŒÂ]-™Úáhùk÷v_âB�üüËK|Š‹œm8“¶9�Ó¾—<ƒ‰“llqW`œj‚D$¼]�y1Ð`ŽÁYAÂË÷]]¡u ±iókµÛFÒŒ11^š=%¾[ÂMì®ÑÉ �ï#8ã(ævgÎo0�ãé>ñÅj˜uˆzj8»Œ‡›Ãº›ôfèÒçÅa Çê¬áBR ®í:8>—õñÛŒ:öHÓãÊý¬¥©‘7‰j„Àëù¯wè]¨ !p$û)´²ÅlkÝæŠ…å§LÆ’2u†²š’U½vÍ^^Ó*gTÈMKÑŽ‰z ¸b*z!ª&f ¢‡Ÿ½G|+®J?`ÓW.Vš(%¿a#^¼C6œœÈѳ ç1ù�¶q÷®‚!5\¥Žm¾L_f’ÍVBW `¹/¾ÎPã6ÀÖ\ SÞ@g-ï�¥÷Âpn©è´d;#"¨„ÁòzŒÒ!¨hqÒlCšR›Gã”)Àà°ö?Û¶­M%ε‘Ûðakó•×Ó�îTw ü /�V}D—7d°k�}0TÚîN÷ô‚å²c……ÑŽ³be�î^èpCÁî¤/Ü,i)œœFÅ÷¤C¶«Q×Íh¯ŸÙWÝ:.?M©Ñìà²Ü‚/B�1lŽl9«[Y¯ðK¤`Åßï]|¼È²MH�(¬e™‰ ªµç7R�t%—;®š�a–c€y½€9ºüÅÀë&|#‰d¾6‹pKé®b0+„é: @ðAPGÌ$°b,Q¥7u=ïç±2Š ©žÔl?²Å$æ’aµË>š^\ô²Vé�z*çL+KD¡Ì¶x,†Hq�Òñ.¾ïô;ޒѲ+ÞEgg�¨\þýb|,­ùåpˆ“Ô /SìÜ�déN0<+V ‘<øPÄ{çü¡¦ïÇeÄzzb“qâ�Oh!– !¢¨ÄKƉ¤ñ^÷~FÎÄ?ÿðVÜ™•Kq•7b,†”,Qéß›Â`Ú×’Z#Õbø§öÌ-áî¦ö÷}SñfO¡ŠMœÈ ²–ÊGEžºîÔHª™mjåSÐKð+ÀÓÿf 6§Gd®Pn¤– DÊ�8Á/¯:¦Ì˜Ü}s€•2éR ´hÍÃÆý(”t ¹•@ßz} ³Ëbã2‚6µEãˆ�ð¬<–¶ ÜÊMå–jìCô Ü©wCîG*4Ç0`:½¨’Üç* b(®âêÏ{D|Þ·GñùŒ½)KlhT+¯êm¨ÉHt⾟ÞyÍjBûýqàÀŠIÌ»Ï7¡ëpÄõQëàâöcß¼››ª¹¿¸ …;¼C�f±ANnLòQùdÉÕŠp/:�ܶƒõâ¡ÕX‚k³bÔ·ïØB¨<%.¡’âó £Øß#ü6ú9–~BÓQÊÜ�Ùtç2j:d>·•|Ë¡ ÁÒ?�— L¨?üåMN©Àšlžl°Q—µËI“K4òÊÜUhñjþ%©¶0±�wjØÕÕ<8Òjcå› ¢sÀVoHMgÊ,À‡%îžæ¬L¾®Ôâ‡ïUÓ ª²E�õ-]ö#…ÌÙ¯˜qd£êø¡ëxÞM´CZL­=Â9éc.¾x²õò’—uNHp˜¯dÏzg‰B´É™@cöRê1J÷j6cX”/OïÐ|z£>jƒ,n%—@skêþèkÒôÏü÷æôÏøÆèðxgh‘RC-Rat‰Ê—þLÝaåE{èkó»Ì!=¦¼â/|È®¶8^2°Y´ oQ\™›ß2š¢&T‡¿½¹NçRB]•©š úÚížAŠŒá0Ʋñ¿µ*^d£ŒÀ�³„gëz�—f# ‚”€åýäïzO ÔN½ˆÒ@ä 0IßPÆÙ0¯_’[YL–±t+ò(èg$ | ÿEífȨÑt(·×*GF“"Ÿ'«Rþ¡°¿ˆJ²\²;£¥K¼‹#ÉwBY8µæã…”Ûá–Ѽãx¸‘W8¼B�qÒÑ5X¾Sõ²¦�Q9@S�DÓ©A¾˜ˆïG5†(°w‚RK%`VÛË“Ôç~°�ë/*” 4°ÒµˆO—ò‚kÕ¸èÓÞ\Ò=`¼PÉYwé\é:ú¢-PÁäEáÏÅçß7nr[Kõ&#t"Œå©u²èП`—e«þË~”6="FÏ ê HXžEÌœ9+öÙQþê7q&iq‘çaÉ@kˆÁüv"»èÓà8V‹¶í—qž)ªñ‹VƒÜD§”rOµNbq¹7{¡e郪OV/Uf”ãž/vߣç�±¢çÛ°@ù9m΢'È,<êÿ)°–¢ñ­Ö4ƒ±SÙÏ÷Ç΄TÁ¢Bz�aLy ×”�º+Yýç! §:»±Ÿ� Åü”ö|pý\9ß�Ä|ò­Gõ6Ç6”÷T…Ô…Y2Ú1;=\„ÁøM'ý�ÌU–e8ù¯á; Û<[{\Â�ëTó¼ÓE[©„$Î 5|ëõOG ¤®ñ�4�µœÆÍcÅ‹_ Éÿ¢ù«Ïž e+í^~¯bx6©±»$PE ×áÌoG*gá~Lê�ÑÁq=McШ˜Gç~Q}‰A#õÒþÏ[ŒõÌ-›Ù·)úõo^±8óºÐ¼Æý°�MHBbíyÞ]TLV1(}û§Y]Zéž«ßÍPR)ÛëG­³/¿÷7LX¯—ÚTë01´é  «!OËYù|\a ÌMû�£Å‰˜é¸›Õ2}¶/²Î+ÜE¦äŽ–/k}ûÒãhDcÛ@/®×Õu±£èѽFâ“À7Ö›§ uåJÜ¢HrAqÆ‹j-k ƒüü#øæ7BáÓEÙ¨-Q �Bäº3??GÝaõ×ó�¥äˆzˆælKˆ™Ãô÷÷–ŸÑsEUÙ]�‰r–@P3ál9Y�cMTh‰Ó¶ nш(z«ÃÐ�ÊJRo§Ñä,>µâæF8pÖÿóÏr×ñô|Â\æ± v¡GµÅ¥†T£+? är9X ¦‡ä»¡Ð‰läË/ :žå ¾ÚKº ";›n?&hqzU«d@´àb|ýÓaõ¥ønRúÞ �ËkD’4f * <‰NÔ*2º»>žéö‚Å7~cWÇèç�ÛÔ ›ä#¾Þ�Å�€¡OÑÊì_ä5·bQ«Xñ®ŸÁ» öàñ:å®Þ3Ù啽BÓÅ™5·—@�lm¤m\žºž“?“.*N¥¿¸ ?T[//Øú„‰ËÖQˆ–ÜsJ‹hž¸ˆ—¦`äÖ|;©ìÔÏ_šXÄDŒ“×e;ߪÙfkaÚÎ3±´â¥úr«ÓU؟ƵfS5“»W9¯æ‹úÀcõâX8DhçXH6|‚v¤?c'XòG¤z�®è2Ö«– -3mö93]NJ°xŒÄ”5îß»Fºe’iìs8àÀs•£PÖ¿éJe<0Ñ×P±2ª »@ÌÖ²{_óv–YK>•Íkì$¾œ•".�ï�¨6Î×6Q@ ‚OQéCþ$¾T�uC. Ù€½\ØCŽ/%Eœ± ƒ”«qŒ3Á„¾¢ö[“ºíAÝPܧj! Hõ³Û7èønŽËÆuŠ�ø†'Š4ŒØ M8|õvÉöRk6ÝX½s½U1ç+'ÃF˨Tˆè—ÑøþÛ'_Ê u4ü º•Ç< �ZG'ôIJ‡¸Jèø³¥óòEAðØ/R>A˜pÅ"]µ{Ýé¾³íB¨›�Ë¿c` F#×�Þò³’ 0Ä¥y%cÏ÷‹ xcÛãÄ e™ƒDck¬o)Ä]ðâ¥ëzž ¤ùĵ":CØi0,®��Ù‘9DuÝ® D÷Ãc2›ñ°Bõ‚,¦cQ/ÂOݨîl7¯YÝ8ô^Èï€ø_xÊ�Ú°ìn&¸“°8º /é´¸FìLzžæQ 9“¾á-¨Ñß¿h¢x!Â/‰ó~“ÄJƒlÇ$›¾ùã�Ÿàuwl‘ ®E®î(¦ç®�PÛÃ'{D¥i�ês¯9é*Ÿ}ûäðq›É)´ÆÒ®OMñ=.Y…ØNqªÀºeCå\#½³{_Â';Z.†fiz©oÉ„NÜ TŸú”¸÷%´ �¸V­„Æu¹¶5Ƚ|»²Ûz(&…0»J°ZÿJÀÚÀª}mp·Déœ}&ö«Oäœ:ƒ¾¿gvœ´,j?Û¥´’ÝÏ<È6sÂtì†Ëx!ˆ¿Ú wâ§.nŸ<¬Åjy0·H4cY”³ÐŸ}¸X2—ºÞ„î/ާ] ½›4ü9Ø‚°•pÃr©Ë þÛ›=‹¶L¿Ø†ù>?ê)3˜N•v�R+ kL€*¹/ªj ¢ÀcÖ¡miÈ‚ì�}(qúëz*uà ]»ÄFÏ�Vs©NÞ;åg)Ndª˜ú뼯wœ~JkImMÜoo�Ûw¸ÜY.x÷%Âû}U¶÷&èo°±wC­ˆ°]–i>µ{20l¹�­Ý"�ˆHÓÿþ«Ñ/éMÒ,ûŸWJ˜2É­¥Ä/¾�oQKtzcˆNï«w]¸Ö¸Nj0l|¦2€×€Sœ�jñ€zÇ ¼C ¨[¼ávÔ+,dúRÏrê;Œ³ŒU—.>¹tÞÓjZ%é¯Úµ”ž<Þµ^,zv9üÏœ¢U Ys¼5/öתƒ„»|¾\¢û€áoÜo%è'‹íß>­«4G3~,�«¡ÏjZ¦¨5t|mFèxä1í--ý�Œ$®éµ½‚O´ppÓÕ=ý5Às/”SbO F©©¥³�êvÚ._ûðY·LÜkÕ—Ÿ:þ¢gÿ-“�$©çklz_Ž=yr,ò«Òî 8Û¸¸ãvÙ”+¶ŠB1û"‘o/éÞáëˆ#sDÍä^åA�¨ó7¦Þò‹•¥Îv#üPÚT¡ñÇBK%º³…{%7¸„¯Â�'0,zJµ}!'»ôGÒ1_s°¹!¶dÖ¯Ó¨ÕT´hZ ÏåÖ¦v¼M`=Ó8åIV�¦é:Ä“elÀ˜J9q^ˆÚØË JµÔZ�ú€¢ALUÌvÿfÖ-õ'mÌJÂôhÕâ‹ß|•óå ¾ëôÁŸZ—2\¨Iv}ÚÈð实ï¼x 5¯ÈûSÈ麚 zíœoÎÂcy…h;˜e�Ö³`<˜ì°Â¬(¡ùÑF`ž’vŽ?ÉtîNžSMýsôWö¢lÒ_ZlÌ~Ȳ2¸â‘QÐÖ¨˜ ÒVÜ2+?>ªnÚ³43®h_ ë ÖÊ€ŽwŠn‡Õ¶à�˜m¿ºÎ0‰µn–ÓfÑ{H%!L'�hâ¿^Êâý֚҅7‹ZE}TØ1�YûÄ r½& Ÿ¸j¤ËuƒU,ÐO:‰^0§Ów6D>`€ 3P.–µPÔ�êÕ¯Ó^ÄlŸ›žü†GÓ]áþä%ˆìv•Î Œø–¾ –œ†©Ã: aîøè]¸�=óÞ·¯Òá�N}ã ç••G]Øë´±•èfõ_Ñ1…K¢R$ÿùL2ŸN�çóhéä®xM _Y~b â�¥•ÜúlŸô­ÃÜŽSøi ¤ÉÞþãîÓI=å¨À¤Ã;†¸ù«öï!¸r`œ™û(ãÄÆ–W-\8»ûÇûmê×UlíÊ»xÜTY"ýü–Ä"à‘ÇÈ¥¢^ï�F##¼ _�X–ÔìE¶¤:‘äçt�…w$3oP‹+óªw™ªµzIõ‡øŽ¹{­¡Qƒ,µá^~²Pæ9Ï4ò« wéÆMy„Éøéh¡q~ë2­ ÙŠáæœq† ùÁ‹$«ŠÎzTwsoÕÒ@†üûç >ÊH囟eÙ2N ¨I§#…ú°è ³ÿ¼[ÈúöÆí ‰‘§°w33)ïõù€»KÁÂ1¿Ìl¡_3úÇgÒOƒ�I¨éµ€.1ÕÒãôŽFdzÜ÷£ý� Jãæƒ|ò÷^`*º”3µ<ùr©RØ¢4<ší»ÏçUå˜2+Ó�èò*M• {·š�–ÁÆÓ¶Í~j¼|_lÕw$²h¬ W—«ÓSŽd!Ri†úAÉH\¹w€U¿ßz¦Í.·^™muX èra¾…‡F_fœeì_®#QFg<ùD[æQìR }�' O†Öº75Ã0&ߤ ^\·ÎêÎÙ7<;Åâ92{ðð]€%Ș3ÁÀo©&iöå÷o h!—è¼ÐóK¢||l×dÀµ*K£xÚü7éÙ\i¤}7qê¯cu^úèhÕ9�Hâ$wµ›êB^ú™Õ] “ˆm()ȼÅnŸÜ•f?xwVY–C¯| E8žÝ"‰UvÆ_ «wUi^¨“›CÔÊÖÁ,ÁT'–!£/§›]I¦�ƒ®ˆX©ð¹z8´/ŒÔ!‰Åƒp‹:F°"ˆd/$mäühß̈5Q³€¶_qmO¢ï»Æ¤Í�mD"É)gÃXiÏ™ƒA¦Å.9?홚ÌV\á ¦�/)IJt¿c�²C*{G)ëÐRò=óæÅ&ÇóŒ…ý”G¶ï>B÷51e¢ÕçËÍNE]fVr¡:à-Þ÷ÝG¡ÆjKÈÜ=l›é»œ6ñ |$ã[õ2tšXB늵H!~ƒœùöbêôhžò�—ðGP?Æo¢‘ûPVb¥”º/5DIÉô ü2ˆË¸qÅ^DçGSß5vÏÈFuž%dBMêÏð-Ø:PR¶¿;‹ši´Mj¼(Áx‹i—²wKå|M êÎVŸÆ5éíüùfJŽ®-ôD?D¼i}@ºÍ�µüT•ãÏ'},<ÔÇ[} ­šW˜ð:g“·ê#_.ú©ûµSUÚµ ÷î=« oz*„÷jì�«,åhëÅ«ì^Ó”-×õ˜¿Ê/ õXôü¤dp)@ð`åu#_upKØË€Ð^fjl· ù‹ÍÄÇ£è�ÁFÌŸ5�#êÁwŸCIõ‰-3ŠŽ:ÓfZŠc‰êt¦‡m>Ó7qïzbZêÞk”·‡÷ykÞ¡ëg¦c¢�A>îæè×_Å6ø Ü ¨È±†‡ì™N“³•#/DüG‰ /òI‚õvyaDíÁÝhtϧƒl½Ïˆ�ícS…�ä8å� ÅÍ|Æw•׿È/T.Óu3r¿>nÒʧ#òZ�Ú¿°]1n…hìÏwˆÏ„ ¸®ïäMΨZTM¤hs—>ïÈà¯ïoÙHZd·RI¯¾ÁûÜmü¨‰.eTÀ×ÀÛ¬ÃÃF0Ö¯˜W¥s˜/ŽÝ’(³&Cæ�.|—«³2Íô$_Ûk_– æÿñ^ÿ1õ5{{iRæÂºC•‚¦±Å½ÚÎ)—¼¹ØÇ {¬‰šsvôýÉ�r-0 ˆùÇë›YF Å•7”gü9ÒŠÁp¦û¯5ña#%¼rç²s`þì”ýâ‹­H‰6a~r1¿¨C·�]Ž}H±0@ò8ëìÎ÷ûÁÆæç[Ô]Š®çU¬>eøûöŠÝ3ÙYœ¾Uˆuj¼Ü¬vne°óT§‚Ê€9#Áfë¨p;Zhã;*¦«Ðš¤7—©5|Š™ê¡Îtä˵’}è"5/|Åœ¯‹`ÉT™ÈAçžÎš˜±\¥TܤæDÜy4WJøÝù;_²é.ãQ7þZ×�bù‹áwðuiîÕŽ ¯Ÿ�ЋDI½¾ø¤U´5”ªé äÙ™ož©ÊQ­ÉÏéÕp�+|ù Ët³°ˆ)šC&ÞWß?VX4íÃ%ñ MÑde®Ñ•H, ãÍÞrÊýúPÆ?[¡žšå)é"­öÙð˹½ê‰î ;4ù)¬Z ĸªâ>“Fú΢i²gp¢ûXÈ' ¾+=ŸK� NÍ�(;yâÖÚýÂÅ-¦ØWe ãê}æO鹪�KL(•§ª²ЄŒ¯k:Œì²#j/UsNôz“Ê߸¦H^Ò¨iE퇞ÀªvcŠKõ!MŽ'ñËúíëŠ.*vƒµÅrk“<–YR‰rx Áúnª1ÇDãäòœ½Úæ$Á}d§0n^.Î(­5Üÿ@[{cQ–¤ëé¡^û1s#(+J8Šú.�~d€zÆf4üV s—­}Èç×=ƒ×FpT9iX‘dÍÞx=òB£â‚»Dß§0ïkº5‚í`.ûqºþ \ìÞ¿,î‚Ù-OÎóó(z^~d½ó•«'1ág¦ßeùGùþ|òñD•±ÊÃÛMÏ4µúÍcSѤ¼R6b¶ÉÎÛ�æÁ’úú¬Q/•¢\ °‹@ÂTÐÿ '¦˜Øÿ�Ö9\èißL&²åÃæWiW­LSõPÙVÆV:<è çlÈD´óÒIôÜÿ' >à†’ãÀºì0?ZØÛû¹�1éÄÏIÁ!(%¯¨Ý¡ù„“ÝZuÐ*5ò<émÓÇöŠI¹ëdL½K[Ÿ @5OYq ­­¬�ó0`(w¿›/CHû™ý¬©ZJã˜Jì�Øiãó8xÕ<´—=1=½<8‰0Õ’MÊ1³�Ðb�Њ”GÅR\` ˜$oËÍ(+>ö„çÿŒ¡7Ù$™œ�¬&ÚÖ ½{é"�b¶6ÄÉeƒIzDtÆØM(kI–Оø“�]CŠL¸M–¸«oì�ËÙŸ^£Á=]ÚV,—!Q]E�ޝ =øñC⮈{ÙâõìªísG$&¹íäήþʤ¦î¹7UÖÀ,v�RpÆoÉ—ã¾2Üyå<2¾ ½zM½ß]i)$îNÕ¤î�6ZÈm4¼mË¢|ÊJal2‹ “€ŽÙeÁÓc=·Ñ įëâcƒ©°³P5éj(̵‹äZ©zm•_/u¨—,¿yÌE¥Ü8ù¶âÊ翈eM“¢Æ<é íÕ±Ït\tÕ×GÅ™ç" BÄ…@ËsJ.ªÍ ²e G¡+ ®­@ø]Û¹|+9 /¿§Î+ˆ5ÒTWqŒ·ŸS¤œ¿Â2Ç�9xœ›>`(A…_ªÍ©VÅþ}…´*ð{øRýíbŠ Ãø;’¦o]Õ¼úŠ›H²~k¢nö—¬É>Ç�èa层·Wß¡ôR¬™€r`\›´�V!çŸGæŸØ•­Ï1çïlÃ�³8ñR  ¡Ýð&“‰Ô& lžm£©—{½E±ÎÐÀ\ÐÓaCB�È‹÷ëV:T«¶ævOÜŸšU6@üq~¼¾ÝÔvߦOÎv•ÃÀŸƒ±vc÷>'¹¥³ñy£Š&žÐ¦JÂ袴Ũu]LH¨¯°Ž#c%%Ù+ˉ4ó•‚Û¾cßÁWü„›‹ƒ¥Rãæß-½+PÈ/þÜï�áÊßî¿MUQ­˜ðÅåÚ]3�ÊØ<’‚”yêÿN=ú]ü™nðç]ìèœÈ—5ñýÿ @ó¿ì-„¿}ä¸Ò |®ÍÐ~©–òªÁ»-ùÓ_ªÌSž£¹ÕИeÅÒëýSRˆ €!¡}âu–ß"Œè+2öÐí×�þsª¡ÀH‰×”³ƒGf\EŒq ÓŸ ·îËËC&Þ¤Ú$•ñ»˜ÒA8ÃŽe6µòJýŽ“äúý&·'¾-#Q(Í99<'x!¿à‡Eš+1©K%’ø,qÚ ëNË0?ÝDsJÆ•Ÿéëß1b ó´v%ŸÊ“\Í�¤Îìÿ«³�s«2ÜDéÌÒ´øF1¯5×›>¬¡í²Ç‘tLëG 3ªªÒÂ�Ž‘¡ØbÒÑO‚Ûü’²âÏ Jª�ßÓßýMÓö+T|º{z‡Ø1e§œ5,·ì'F#”cQQ@“%'„~ž¼3¼ðž†¨ƒ{ ÛQ­ø×ŸHíPƒQ`‘Ñ#Öã{jbÊä´*²*Eó„d{ \d;œÒU+/|sõèÅÓ匵–í>ã]t)ˆyÖ�$ÖÍ|E”ÄÏ�MþÅÛÅŠŸšŠÑ ÙH9ÏÁ=DO*÷Î^(øL÷W9úûh%¶ÐLåQxZ™”Þ©(ª®l£ô¢ŸŒ÷Úa˜žlãgÃs0Èu•oøe¿îc�60––�ˇAàÛÖö1.•›)QV»ré'‰Ö+q»YîGþ’7`º •º´yw¯L}zµ¼‚ÕðœPÀNMoÓš¢ /ƒü-˜õíÖrSÖ«�uÛ¦·ÙSíµAgòúþ~_]8ýà£n·àaãÛ%ŸIv4ÔjT..i†sE¸ˆ%m·ŸÕ–nˆr>Š*`ø�r¾4Ñß/þŠýÃL ‹<:eE¾Û}$…RAÑ^a�ð‹n¤?æjŸVG¨ÉKÅßÅÿ é‡Ä4ÖŒ ‚ªM™LYä-g¨¾ƒ#Ûûôè:ýÁP{°Çº ‹÷RU+¸®z7‡?ê=¾à¥ŸÕ#—ßÅ,ÖÑç�¡~?ÖY¤Q¦º)hïèúƦ«ç«3ÌÁíAƒ9HôD´ËVÑ6��‰#êûIg¡6Ì�‚ÛŠÅ|ýC:ÆÊõÒ8±rvAQry+j’“�V™wmm:P¡éXC õåSÃ.^s€‹ðWpD‹ ’/Ó�ѰúÚ½Fƒ-:u¨%£lÕw ²Àj†CˆÙ¤°§K;Ô;{o˜ie$ƒüÂ[¶¤ä»DÐ6-õR^ar[(ÞqƒX (A%Ô„=y¯ª|Í=]³#F&Š¢ƒè�á÷”]…€Þ,ŸW»\´Xÿdsw�R0VfX]f�ƒÕÐ4(îy�7:BìTíg¾íåÓ_±×àj tp‚9«}°Ó ¦Òª58üæ�¥˜Üõ¹!î)þˆ§bÕZÎd¥JÞ^ïæœÄe ámøÜ¡ÖÈ¡¥%ãB“Ësiñãã$œi1Æ©rôÀvtL)ŒŒô§%l  ºuÿàƒ×ŠOõd|ÃXYP�W!CÐ 6Z°JA¢"ƒ�Géê—Çñ^ůRU™ÿR³Éò¢mn�î-Hícd¥Ù‘«�E»�$4"…(uû´é~ýÚÀµŸ/ãëIû-Sò íaš ñÞ º )òzË#øäO`¥Xƒð°Ó·ðÛå£Jư•ˆ¾ í»Õ‚eGð�Yš×£�~rÔ´¨îÌD¾òèñ]§ùP)Vv5ºt¥.Ú_§Ö‡µ\níѺÊÂþ��T®2M‰¦¦„Õ9Të­ñßî[áGøMà€4ÄYZ« qq†U�E�A—å5eîzB­Z�„˜ ÔÀ…¿ƒ‡ZûYXcgðwðh1o±ÔWüÄw]˜ÃA8BC¢ƒ¢2裟°o»ˆpŘ¯…Û,ðÔ�‡åÆ ³Y†GóS÷®}äôŠý1ö/Ý�¿A7­àËÕ¸H¢)�ÜôHƯdqºÅø]©ö›Ä‘ß7~õÅ òaÀÈ4Ñ82$gç´ \y�£ÏEÙcíyal[b‚9£®ìt¼” >O½úüq¸ÿ>1¼ÖY¾—á²3¶ôzªv)]56ê» ¼™›Þ,å…q(šòíb#†çÆ*€½`^=µ]õmäžãëÑ©à|z žŒCÝMúõì5 BÁ’$° ׼ݲ‚4¼°ž‡[‘ïÞØ2…E¦fcÊâÅùw´t—+,4at1rÁÝß4¢o±kuO�Ó³‹™IØê•à³xFcø¯}[4Ef\¥ö8O˽ ÈÜi¿dnu˜„LÿPµìßä4µ‡«S4^uúC¤ÁA�ŒCó¤=½ô»^˜ Q�?Ô0¹u©ÎŽK¡\ù%ÕXºä ñ}p_Uœ·C~òS/™Ñ‹àB%žA¤`ç–½wz+bù£F""6MÍì;Þž8wGheÑçø­j&Â{”6Ÿ`n]ÓÚ´�š?K‰I§×pÅòå¥ä„Pw<$ ‚ÂäL ™ªM—ÄBVU·/ " O2û©{pïÑTãÔ1n[ì¡ÃŽ5¾ ¦�öÒÿŽ) PN2+úŸ5#()±ó�¨óÛP;­‰3¥XŠŒ8L¤eùH°oBKgÈtAÛ�Ö P%d„…,‘õÉŸh+›^i3¬•i9©ºƒÃ¢E„<ý»�𨜿·Ñî³#Œz® c �Bðf”÷ž¤†è%TsþÏùôù ˆø=¢)ÿ¸P+©%LMîë9´ê„`^‰:•²½3gL³Ô½ß�tÉy"{6o["²ÑRÂW¥'DG£�±²7fT닎Í}§ƒ×'c7õìùnAéÙÇöér΋qhcVuoÆÏ=§w.Ô=ÿ‡Ó‡œŽ*ð5£m˜<ëŸæ/zƒ$#H £æõ™1Âp)»"¬Þå$ždð²·¿ƒwýȱŸÇb'ºâ_"}G,â§§-ý½ÓÀZD½“Á†D”Ýmä´§³ò:éåÛ6:àDÎÁ’]n -á/¿Ìø¦~iêнq5• JH-…+R:ÕÇ?7�‚d¦�³F8jn Ø‰Þ­t–¡§½×Aü®´X²”-Þ÷8šŠÅNƒ-ãâíRâwÁy®ÿ{r˜ë¼F+ëýrÜœšÒ,y�¥­÷Kñ6Q+yB³Á/8Ö‚�C’扂@Ð ½0çÖìÊ=bú |Áe߯f<â¨e§¢fÙ zîž°¬c­ÞxO—õ�a_è±Á_~+žGWÁLyf‘Û2ôœÆÿþ±ð`ñ–ÑUUÍÐ…RgÐé}¥…i7Á’þ~ÊÞsÀ&©1ïÌ‹¯q¼¦ ¿ o‹õƒ' ‹âÁ`âõò=ça°DÈú>wÈðy±‹~ÜÎâ… sd|ZG¢†,Ê�o©v¶ÑZ�Dù6«íe÷zÍ(®gßÒöHf�Éß%r!?Å}¶ÄM££ý&…*ø–K¡sLQß3•³KntÌÅøÅX�B²Ja'·Ïï?)Ntsþª�1|¯Føo]dªv0öFÏ;Ó>9af5ú1¿v¼ERk3ïuÐ//í•<Ü0ý›ä^¼ñò*E–ö× žZs¯¼& �: 3¿“ë n( öŽW#†…¥=‚àþ3ßþPDõJCØ%¯ 4„Ì�Þºu{¶Nð$7ª½�7Ÿ½3—p¤’hezãd1ÔW¦?ó³&ëðbfT¹:ÖÙÇÄX±½àײâ&!VêLŠy³2÷¬k�ÃÞÀCô§Üg5Jòz{Ç—F„Õ�Q c|—À|ê{`“Nÿc¢úƒ“¦å²á–‹rù‘h ¡ ÿÏ»­à02ЦÀòÅ» Ùüw[ÞŸè­Ÿèd8«XZ[©‚ª›>�UüÓŽåh=£ yð‡æòÊ‚˜À@©Ó§Õ{÷ufqÙç_ĽÄ¸þq?¼j2Àî·yôSœñÅ%õ0H¶b– %Óð΄f?Ù,è°|¢ ¹mB]$L´ïËZ5€š\Ñ©–{Þ°ZÙVBÉP$¸†ýÒj$ºÍˆÒ�׃ʢÖEáUÀéy³Ë⊸PJeÆzž›‘Äæv�7Ú¯hH~Cª™×½ëך˜¨‡=òVéƒn.pBÔÙñôälʯ@¯ò½ Œ#âéõ" È¡Lò¾3UwWtr’ú Æñõ¤ÄŠTg &Fi� FPˆëÇê»Ï7!¯(GáQJÙ‡Ã×z§—ñC_×U‘ÊÿY»¯7ÓrÖh¢íœÄ› }‹”¬§¿‰ùžÊÔ•�cú€\ú+n »FÑ2Gü!´,c ògš»|("±Y1úq^¬‡íø‹PÞôÍIñA=d Œ÷ KN¥ÍŠøqNã‡ITy«ƒ‚8î<žñøˆŠ X縆´vbùÇsCLö)”¢w��æ1ñ‘âfMVŠÝ$½,*GñˆLwüÁgÜJî·'ÂІ!”Ë#:ÖÏ‘PàÓq�˜ÔWU .öšXÛq×Gx]Iûm¹˜ 2"(5È¡^ZzD,IØ�Ç�º¤*€ßb7Ð^N¾o‰©ÎË ö¬­ÓÎÏÓ±I¬[.]gîQr±Ò}TÍ  (Ialu™Ÿl…æO¤ð’ÏpT, i#äÒP�6*©3È)øÐS:õÅ{ Y]£lCB*¾à#žÿ²UVPú25ÏÅ^,Ë«šgˆoË!^k>qR ¤Û¦!ò)xÍY’Ȳ€=÷²ó-rsˆ( Ê-4W‡*V'}¦Xå”a,?Y ät‘eoíü­ÿ cm";å!Í�°Ìaþͼ�ÉM8¡T?•p 5fâù¡ÊÒúÈ<þíNÊ"µ7/4M—=Ü Ý_؆ú—ã+ïoÄìóR’Œ†ú£>ýè3ªíX ,ÖéJD‡™¬³Ï¸A-¶ç)ÌåŒ[Ôó³1"+Xü‚<Œ\ZˆÄÐlFKÖVêÍÞsr¼"³Œ;ªˆîç�†ø8)}({¨"ȇlMŽ1M‰ˆýÞµ!¾Q©ë‹ §öí­ò“ ¯,~Šì¸h3vë%=<Ÿ¶þ–¬¦Þ‘–-iQw¸§M$‘ý†âäïo²LªÂ§¥5³º°KŸxùÀŽ$¾wäèñÁ�}ññc6¬¶ºf.ÿhA•ºO=Yý:Œ3Å{øã&Rq9¦QÝë[– A�"c²n^¦óu-8­Ñhøƒ6|’ c·‡q! (W¨¼Y%¨…ûRB;=öÎÐOWÊÓ>¾„Ø€4§M»ìMVú_¦ZEv‘÷E`…�b`NÛ2�;Þ̘$? ¨ëèìð쬡~0{á^ÇŠd"uõʵÎL§‹ßìÖP f›ÁR¬Ã¯“B)#¿ ¯óÑbÍ&k¸ × Œc ÖÆ…S$bYfÑ~Û$1q#ê´9ší7Ì©¬ð.N!­›ƒ}‚–ö—"%q#°e`¼iħäËLdQÈl³œ±· P�ÛM}]•¼k §n´Ù,ˆÅLc“¨l3» K‹ rAÃÖb|/º®�œ‰º9ZêŸÓ}û7P[\æÕ"¼OHžt®¶GZ†,í,t~Ó¬™ª®ù¨LAjRº�œL,Ǿœ¶&Ä1w˜þÓ^¥é¢AÔþ©€Ñ�?*ƒ�œíï›É\•ÿhÀ˜Ðݶz\ÑÞuë�m5Pð�ÇÓ2”ª€ÓÅ¿€¡œ~tÿ7þa{Íù—CDªÏÐ hEb¶ÜÊíŸÇޝ"Ø¿ºI¬ 9uEÃ>OÜs§'fñ™ç„¥êÉ×59,k!Sê[GƒC18އàÛ¥†Óô”»Sšö2eK9«¥E©ë´>} H� �ã OFý+Ôê&ÿÄòe*ÈJHy3¼¿~`Ÿ?3¡X#°�ÄïÍT»;qœntœ°Xù]dÿÎAåÚЀ! B÷³½./ÓEg��Ù‘/F]¶Žìt2(æNÉ"%Û&Qã˜c$¬±ìнßY7ì9vûEaÿah·Nê±¥ÿY º¯‘�v­tИtXø¡m;(ë�l’‰°ý*„îwÓP°QTœÁdo÷ç¢zž›u,ÄψŒlä¢P¶îÕñÀH…Lxm3ãŽL¨±¿yd…<.áÂ6~SE‘¤E‹§å�w²«nq¯Ýú¾I�ÖšœƒÉðÍ öl3Wõ¢x]Ôô™sÑ“a©Ÿe5[ÙŒP-Î?ωà\Ä|<ë ‰^±¿½»ÀÀN�:-Ènº;?­°8]#\¶èŸc]4Øö1KÇ�µHw<–2Ì㺯£_g¢vÙÀ¸%ÆüE¾ˆÅÿ}ï’îŽV„g~�¯ê±dÜqh[†ÓÏÖ­™¢Cò®L&*n×apJrÏȶz뱦�æõ‡>V„®ÔÛæ½si°}λ‹M3ðiAbòé¦'Õ;4¥és%±ÎS š9^=-sæ l]lt;x':¶‘àñ¦lY,'¨n¿�‚ã‹EÀ¼×}_¸HWÛ60ú`Öà³¹G³PF±'þò…|ÆCï|.Oe™ƒÆš;àUÕчÎÖË1õøe<ƒT^§p8¹%š‹>ª³wjH_;<Wl4#úhû»cÙöÄLwïäD4‘لĸ›í¡(YNñÇ•ˆ3Yƒ j ‡E¡"If�g׳A–õui´¥|HåUa‚ã¡ÕJ4’÷]èÉÓë!>¤ê´Õ@BûFÜw &&¾Ygóí ‰è´K�Os‰…ÖàÕ)0ýÀ WÐ67Çü#êÒ×ÓQ„LÓÔ7Þx©©ËF]2Oq5"nõvЛü'ïõfß!A,I‘µƒV`xÆÇ¡)^ ÎGw`µ00qEÛ;ùÍ€ðE˜æe«¦h»»œ÷ d„pÏçÁU²‰Ý$Y²H w´Ó‘ RDu+W#b�rv𖯩í�¦òäóÈáC‹iþOèÄzkÈÒŽ_P·Ü Ã�É¥7Ê’àí¾b�!ˆC¡±Ú:+vÊm|Áó=n.]ˆQóV¼š ùyÿ£ nk¼�ÒNY/Q´y<&o„%Ïx]ÒD�"r7|ž·ºŽrÓ™¡Ão8^gç긼gе̓dBiËQ 08}ƒu†ÄžË?1d#ìâNŸ@-¨â�\핾þ:L[=6Á…¨{ۥ㱶‰îÎK®ÏHv Ë´»O ¬+?;i[vÚ›Tb4›dc„˜¹¡ä®GKZrlõ #< µ©'C®etÄšê*»ßõrƒT°&+=l•Òr‹ÆSøÓN¯K6±E«!çLYݘšbzŽí-�Ma˾ þ× >¦atÀ(O.—4/Ι÷Tß[�ËùÈô²›LéExÒ@„žÕXÅ5ŽÃú\˜ÚjÐܼ“.n"AœÛÛ84Š�œT»Ž4›û1†ZžELL/Xê?j—bö ò¿ÒìS׉�a.¨XTå‰\`}ËCÇt-‡�¤éù¡%`'óxäEvÿ¼ÔNìŠ3‰�pGx„4ػʑîï‰ûãhýÖ¬¿Ñ–?§ÌCÒJ«•°O“Œâë> â€É+2Ò´ÌØ.1cöž…Œ7kJ³iß¼LéÏ´=ÆŽJݶúûp} aöް÷—’J¥äqøah·NºªŒkTâ‰Í'�'^-‹Z2³6 �Nˆ&¿Cê½C�—L¦ù„°>“�å¤�U:HOlÁ£Ý'ÔŽ3©4ó|¹�@;KÀÝ› A€þĜɑx�%$q]u¿fd‹š?æËãd5õa›­°˜ÖèýœVòá¸Ë÷[öæò­y‘*¸‹ ºnØK"„À‡B6œj^Ù9“nÜÖÖÉ Q”ä�°C#vÇ‘I|àÀÁàá o Ó.xËì; 0½OhÃW–ŒØÛ³³ Äì9[â¦:Þ¤Ô]õ¦ßñ’Œ»-Ufìñ›Ã¿díî<«Š/‚”Qû³´³8¤MÿÅ×3Fó+tÖ€�HaÙÑ9°”G·(y…;xíEôÛŽ@óàÆªàOœ,`â ΋ pl”YÚ0í)3—IÜ¿Kgï=ù¸7è¼0±zsõº ïÌöKlHm7¿ÚšPòB2ŽÅ 1²:ßÖBé‘-'RÌ%¯¬`I=÷Q6fMØÛ^¨¨, ØX¥U^ÈìO–ÂU¯ùQ¢0 Ùrz§… @^·v˜ØN¼xUÁ½½†�?ÅåxË0è&êúfHüžs~IÍɱÜQ”N)²Å'�ÑçË™ùX©º� ?ûÄŸ¦ÿBRÀ’q EeIŵ‘wL –~úu2¢= åÏUZ£Q×=t7�Å BãK“ŽbgšˆmÒÍNÓ¥@D3Á´>VªlEt^²Òy -¿ïº×èÀÖs2ïóa�¨ˆÖ­ØÂ>KÁº#'aˆ–yjÍhJhb\Ã]Õ ?aåÛY t”Dm>‚ÁT…M²Ì8 ¼¢Ðo`ä.ùa›ÊhÙ®Þô§2?Ùù;t>uhÑFò|ç}µ‡›½Ã=s†"r¡OÞ¦'MìM£äfë�nKYK,,é¸3]|¬Š— gƒŒƒF/)â| •Êånñéèu2x” ("KíÅ?„Vî› ˆeç(šäÒûS_ý ¦ ð§ vè¦EÓ®;ð×8øª{žBi›ö¼qz˜}û˜ûƒ…†Þ=Û¹®\0æl0Lv€<íÙÊà§o^¾›‹ M"ÔH…wŠŠþŒ40ý1<¨ÐýZx ª¸8þ’À‹¸G/ª|– BNdd•ç}›IçöìÿΨh¦ü£JĽ*>[}½vÄÊír¼At)*=|Šæ]>ÔªÛÞñoìÎß@Ü6Pº�|ü‹Ã-K»B¿Ø1¶;g˜OT,Wsά"ð„ˆ»ÔÕz�™ƒñ¾Å;ìa2øòÜÈ•‘F–AÊàÉöOоà��“§\±qŠVÚiÂT™Sm(ÉΩ -­‡ìÒD/’?IZV$c|¾TsSÈÊÊúÆ �bJõB‚=N(¯ÖBXl=ݤúý0 Zòøñ‹NuSD‹6M>ÈÍËâö ÕÆqL0wÁ/V>nës·ÂÐ@Ô63ºåÆ4@?Ùl‡p½£º Wàñ¼[¹jðJ¡É,15¨îél<ÙéîÓÏ'­]µû�Öš¶õ#pórw÷ŸLðð.a–Á4R3©.ÆaQ)¡j5 O¯\PTï,ŽðØÐû{i%n¾‰¨§ï¶OL—VØjÔ¯¾tZ¢>€Ùgù¼%¨é–1løvB#�°-+ëc„é˜wÐã¬Vèž;xq!‘wW¬pÞšoÐõ9áÇû ©Ûj–?yA¦ýMQ8h ø±}ÎVUüÈ^CÙaêV3c³KÜÂãk}RþÇ¡-À�§„µ?ÙÂjpc¹ð6Ú[®©Z‚ñ?ˆP²¢ãÙt÷OD"?Uçû&¿´�i*¦ó§.¦;8Ê[,“ÇäãQ|•­È�\Ef§ ¾8 ÊÞë%YÌd­T§G»} k'0!þ}-22‘K™˜é×GæÐžŽ§lªÆeÇ�qõ¨Ù2響BÉcžpÌw/…†º‘Ƴ Ùy¯¯i’‡}gú¢v¨©5uÜ :åÈ_ñÛ­cRI¦áÚ•„wÒ;ËËyâ¡ñ£;ðçK‡Úcg‘e/ÚÕØx'¹¡v9áKÐò'îI™Å¶,î7´ïížkËúb/áH¦¥Ò%¤оÄP.¤2zÝ M˜ãÅ.`Pü¬Á%O�Ï�C`ÉrP` Œ+Õ¬jï8¢} ï š§ŽÆð\ŒÐ”JñW`ò©ù©¥¿2@e�•ìï�£Øó ßiçÄQ£ëø=ÉËJÜY -€MeTT ÏXɰûü¬Åƒ"p ;È/פ?�à·u,¶�«ª£¬æùx¨O¢KLŽû"£Êíýs•þEÑÓ/Yx§$¥+Fúå p„ˆò Ýz<°¾8¢ÑÍH�9˺U(°.úã¶;è ÞôDÜd&0:ký–{[ï1G¡ÔçRZÞÂ\Fk?§@ :ˆàJü Ìéu„ª8›nì¡ÚlÃS#úåõ²Îlјu€ŒÍ-'µÕ~Ú‡©ÖSã½v(¸¯O›Àà»y²�Ýç´AS“T/*•sj¥?<‰—EU™z ‘G@¸�ˆû´ Ã9);øÞï5azlçc¤•ÁP‹š”<kÍv?Í£Þ†á>¡œPzäH'åêrfÑ”[3+OOÛìˆ!Àpà´ºP|Þ­û‰º3�{�B½$Nb!ÃÍRQM™žæ;òmOøš1!Ø Œ4¯s’€Žn��þ^ØW²œTÚ¢ü'ý–ïÒkR\Ïvj©WÏ5P[àBÿêÙWùæ+÷ÆŠPÎ(vÓåYhlÃèM¦Š^®\¶Ö…9yÍ»o<X1¥vDiËvIÞ°¢â8³.Œêdñ13Ã÷ÜP,&Ž+j¤Œ;'ò¥UrâÙù­‚í3eÂFöŸu +Â.Fžn-Ý×BB|ù&séEÁ’LÅú^Ü?Hÿj¹… V46>§ |:9çÑâÑóÅWöq0ëQ‚á bü±¦xÏôà²ß‚;㳉�QÁ@E�Î�P™-~¿µæ¯ä 'Σü‚€ù”z|�-°iwLuYZ6œ£Í?#à!8N‘ß][ "Áz ü‡€x_ÞP²H.�‚Ä4ZDw�Né‹¡¦Y¨ŽXË�/c jù-ž\ñ”€˜¹µR/M>²Óâ °|&#„Ä$ÖÙ'|ié¥DÃñþå³@þÉc /Vè™T%-jþ1{<óŒ.‹\¢XIPä"üÔD0Ô(M©ñxBš›VgHñrÇjÑñ÷üa˜«(Ïé p�Zhó`Ìüö#w¼saj•ÂëPÐúöÍæaCĔڿýéXÊqcQK& »ò²ß>I5%ç¯ ÀqÙú°dLô[V�\sÂÍš—é)GfÇ$¥ñ=Bk§�Þ˜¶Àê]·4AsT&¤§¡ùù“>ϳb®öÒÉzP1 PÓ!¨³9n\•p [®Nˆ³•ðo)\DêÕà”q¯ˆ pTn7ý6L¶iñ¤³IAQŸÍá¿zêvÓÄ”ƒëiÌóß�›8£¥ÚòñøD[oòÙ†ªj�àå ~¯P $GÅÊ'kžÉäWÖleÛE˜ÍcÌ5ËÆ•LWúD¨ìì¹’ªZ„ÜV´áûÑ½Ê ÐÅùëYwU N3ÓøË+š°YK[ž¢6_ `ÒÙE,Ö‘I?+Õ¡ö7R-Q$AMÖx¯qIüÞú~[üÛÏÌûÄd” #=óݳ dÙ4f�Ùå—ƒ-#jØ.ø5e„éþ<_¤¦›±²×Õ€þZEÄJn�Ä@aßqËéW³Ç¸!ÀMB¸ÊeG'ã¤W—¹®Í:2ÛQm,+W}BjÅóéÅZÎ2C�2ÓÄuù)�¿d“|†‘'Á"VP¥¿sýª ò”mAë„B‹kÀLÍy1f.Ë'ÙÌòÌ*è½§c¥ ® ,;NÿäÈ+ÐÃ/áž \Nˆ€ûg`­òõíA “šU«¾»’~pÉ­/ŠmŸ…šŠóÁ'²Ô…‚¨R@¯@ò‡…AU"¯õ?V“¬-âaÈÌ…{�ä“MÓÞåµF¯d¡R¢©Lk7þ_Ê#«y<�Ì-*,¤öM1íßð{sA,$¤¬ek}Ç•}Û¦|Œ‹vˆ`t~:~šv^Q]m¬mc\"š�ŨÂ>“,^KUYƒ‰(‰"º2òß|0Ò´Õ:ÿ·�¯‹*¯Úù­ÁFõŠïEÁКF4Fö—ž›m[s¸üO;n7Ü[^­O‹ê$†¶³Tçž|‘Zú0w³í3±À4ê<ª¼ÂçS$ñ5ÉEéÏ0K�E„øÆ–-¿9àx—ãèèEŸ|öd Ð?L  �[RŽ˜"+ª¡FûÝC·wˆ•Q?AEÒˆr Óqe…Œ‰|g!(pŒH·öÍtueÉ!�äéBÁ«õ ŸF0±qt`…’9Jæåö=‡Ø®ƒ·úèv±�âº?úkAª¡Bºþ4 ÓÍ~ÍÔ+ ny DA�Ã'ÒæÌü·H‰ߘxnQtsåG ˜·íbçî!{êÉ¿v{1rÇèkÜIÍ ù5�i,mYJ’ubMÑÂH¼q„Ž2×Çâé,¹³õ)–F5 o~�|ª"»ñ:‚:ú™Þ œñ«µû×= ·(ª—ܱi­Lµ5‰;%§éru ùj™¼ÈêÅ¥^êì~û"5ÑÄIN^Õ2'X3f^ ¹„€—,ä®ÚÛѰˆÞ)áæœ5 3ó ®¯EÀ~U,-Móп^jF‚pJ£µ$"ã…ÔwÃ{"d'½ËÀ�¬$þ"ÏÅÍ »=óèK–†›9¡¼Ñ«Óÿ9*vG±ˆÀ)í}#å7îòQ´è 6vî›TÇv-ŠDÝx‘º±àNƒ9+�òçBWqècÚèÆ_„h/Aáù#ðG2Ô¡—eø ö?‡Gù5JZ«Æ~�Úñ½žª²ÿsÅ^¢ùH¹ˆ Ì4e^»Í¬¦!Óì–üŠHû4î2L¡ÞGÅB³¯ÈÇxÍÐaú±A=±]Hó÷‡=e87©˜Ññ©zÁ†�ØÓXüUü¸.Ö«¹?yŠàŒ âþ>mdÜG A‰&þˆ¬ Y.ßOé0yˆý `£Âqü Å—�¤‰Ÿ¤K1b.68�pó|EZž˜6yZvä&‘^e.—¢ÏÍ7§0vk ƪ„lÿo KLwÍeo±Ò M‘Ó˜¥ÄÝŠØã&3¾ñZÞƒ©Vå5è¶c—.üž¸s¬v¨ž¯*‹ÁüøGŒŠ1Îφ±R‹ßᚣ “ÛEÏ„2‡¿&>ö� 1² ZÅó¯½÷œÃœƒŽ+r‹û¡¦éòâ{í&boV5påk‡“’½_+‹Üj*o·çgýhp¿ê“­ŠÅŠ r°¡§ºHÍ`1]”µÈÉ ¡ºäÝ9“óÏoÅP~»µödýýYíÓp—Í(Êé£äÜñäBŒ61[’ÉC  [ÚɧiZØÌöÍ©ZãDÇ�‘¾À³’©QhˆÃšEAí1öë–0C8Dýêk{±»K‚a%åÎ Sáò|Ä¿B œw³ª®aš;ðêW!óZT:9‘ÕªnçIÙêü¤_/:”-€™?mÆ’†®‘Ÿ;SÊ 1]žeà/•ÛfÛ/#úZ]…“ÎÈ�ÿ½&ßè�qbTýVš-ÒË * Ïy†–¢à9tN–�¬0ë@,€¥wâšù²"”%…A÷§/Ó•)àrÒ'tò¢„&©ÎdöWdÁ¯-u8!† E�ÊéÔé¿Ò¿Pc¼¹Óлg ’Ý‹JùÃÏ93„1²Éc§‘ I5+,z†­Þ™q‚˜Œ+¡ŸŽ�d‘ñ|Õy£MpÁÙ{õ”˜Üýƹ=�^sUâF¤ óß›�RȺÔVX ×åÖ¢JÛtÝè<­ðõûo˜»·Ëég#ŽÕÑTí{ž¿[ßóüœ£âoÌ‘†o=l¤‰ffH°ûdÖcÈÞOÁuŸ�ø�"п_Š,gàºu®#ŒæqIøafgžqhÙ–ƒ%šññq'ƒWØ,?ùB!Îor‚Å à:s3;ç²¢V0ž‘YÙö÷¦ÈÑûÝ£VÒ3»mŽïù SÀ�†pYiÂUø°bÊñLÊ •íiMÃ�ù®™=šçø´Î5ˆxÀ´çaMÔstfî[O^¸pñê(7æ§Y¸¬ �N®K`Œ¡‡©ãJux~¤Y½}[aÃì\óÃ$çNÜ>w,E’¯Vk]ŽE4�pOd×ã@ïˆZ°ÑB6¢¸ú6…%G‰[ a?֕ë†Ýã6ãM+4 ¡¥¥ÀaQk¢;*§œÐAcÐjþ'�¨èo¹Ò„ÈòÏŸègšØœìK:HSÏl§¬S·ò¢–ïy·Z“ýH7�{ œˆÎTéE¦u¾� ¤8"+BÔ ʯŅž&#Ý•�p³nŒF›ÅkðTjûK5¡a.زF¹§›J³ÿƒœÀZ‰)á§;§©Ò˶,ƒun‡Á(«<Õ§Ð œ .ÉÁì1x5 P2ôŽ0•ñaúÃ~£kåûé³~…ãå¶…;e’Þ+€^oH½YŸãÅošyÖ —§eQt¤s]¨Y¹H�Šzý.˜–F–TÐC°“k¿¬8äQÒ7�7R�Ô<Ù±¤M@lýha�¢ê5�ÀÈe®€¤¦Ù¿þõqù¼r(ëÇ¿g_Êv›~Õ³ð‘Kb¤:‚D�j¦Ë€Sé%ÑÊY†Á!àÇ»�ÇšÒã ‚ ~4N²ƒ•�z¤Þ!j@ÕÉ^žF;‘;àlg7T”Hù¶‹°'ÖPA.YeÜÕÝ7Ï›ÙbD¦òÙñ¨‹èÍ� »Ûœ0(æe­ˆŒŒß§ÉD!ílœØº ¸ƒU‚«ôÅÖcÃÙ³RŽî¨8ª–> Ýh)qÛª¹€â3"$†CkmD¶Çv<ž^‰Ë4¹¯ìü¸K®=žÝ ÈZz¸pKÝ"/\ÿ‹>0ÍÅ×㔊êòô#;ºL }è+>¹�BÜ3agÚ;ÇSˆÌ.“±ÂùÀ•É¿g;^ìDWOT½ uȰtçR¤LgvÀPH�ªU]o¬Þ¤ÜÝŒÚþH[˜7q»S ¥ôì°(ÈÁGA2è\ˆS‚á †0$c·ÀÉ©T•RFöoG‹EÚÒ4¾ô´Ål²r ©Ú3Q öb+…1yecQ’%=ZT\pþrp˜‡º‚m% q�ªïE V-ð˯·¡TþR niIs&bÑÉÝøúådÛx»¦³w�2çà<*ÞcÛ¬éÄ.AG¿â¹’=åˆá;ê‡�ub¨çè2¢b|©ÄjÂ6‹ª`¡“>.Ù2|âªTýovKo(G‹±Û©73ÌvWs¶±Û‚T5”U ˆÆ¥ØZÐâžå '“ÝÅÜê¶]X K¾œ·JÁöø�º|³Z¼ž™[±J€ñ> d<1yÈ`d½”²à†¸‰':¿Ÿ.*úÙŽ žJX?YÌ»f(ŽÔxôçJûΗ|t²Û0íD-Ö”‰$ó›~׌ƞĴô«i�ªxzbÇRSñ’ 8³-=P"c&p£+2¹¿V∠"êL‰ÕÖŠ{…?Hƒ%×¹Õ~L(øyl¸ø÷°%ð[‘*T©LC#Èfs" ‚ ‚˜:2w4p�"w¦!‹å»vðèÍý L¹£‘¨’ Ñ—'îÔ*,õ–„î�ÆÝFœ- Ô-)ó–‹“Xn%³ù–X \òÞ,Â(líúØ&kdÜŸÜz¾þÕ w®@J¨øÒ ´»–ï z#t"æEø2ÂÄP0wHÁži&óŸàpès_°ÂªýÏѬ„z¿4eO°´XÙ×ç?Ž—F¬òÏ#So&§�´¢ ßTJ 9¬_”mrš/inþÚaVvÓ�YX†;‰Œ¡¢ºæ7”­ú„¬‘¸œ¾Ê"cÞe™‰5k&”1/2ÚöçëDK=4(ÓÄSÕÂ&û}×_@?8†ŠyÂb·„'Á·ò$)…×ƒÓ »_ŽÅn£ða 韈qÐ*Z*p’»$M&÷>hT_–‹3Õ'1:”mf€?â¢E6ë�Ø1>€”wô«¨€\G ·x{O?+AB ßÑ%–Æüï³1¾3Ñ-㯶%TêˆQkCÌŽ‹èÍŽ´p½4{> Wæ¾¼�x=üÉD¡ a]êXç:ÅãþÒ\T²™‚6w´`X>Œ=Þ…\ ólQ{–J5T�´ß*K9XkÇ£dØÔ}WéF9'Jvêå••Ùô¤´Ki”mSrQQ¢e£ R… ¼æè‰ÞÉ߈Yßt×dq¢!(å¥Ì[a«’á+³dÓ>PòÐú÷;áKM�ê¢ÿbfAµ¸ú‚½“p#R2ÍÜ�ĹÁcéR£­Ñ¸6÷½˜§5Õ&7¼Ì^ pïݳ|yà òب¢0ý+T¢ÆQèèíe™›�òìåÞéƒU_Î�Š ‹bå¥Ä š�€Å…e¥h óüPÁ9Há÷Þ¡ÏXWlp#àp‹Œ-7 \~¡w!@ÿù¶Îè"¥3* ´‘˜ås®_p\´LY”^ÇRÒu @K�¦�ý“i`¨ ×.ÓlÓûzʲMgÜ#KOtšÙV¬M ]“ ù*,šõsáŠ�‘?V$¤:�TÌGOÏ’Ò‚?oH×k4‹>‘Uj🧴¶ÿ›9®Q”ng…£Dd_’ ¥è«ÉËljAÛ5ÿ€5sO=Ëm5úŠúG¼¨ŒƒÀÔ­>]Ðó› 2•ôOán ižU�vÈKÁ%Fyj¢oì绲Ÿæ-uúò†#—ã<Ý‘NT½ñÊ›6E0)X‘Å)¦úƒYÆ"1aW¡áü¶Û¤l裂ý<ó‚Êí_û«£d7�ÞÙ,óÇʼÞåËY�¶ ËrršCõáîùH2­ë9dnõzg®øV.föÎd‡XáJ™àÜëˆÏíÆÉòÙ÷‰ªqnŒ{éWgO¥eC¯eË‘å£ÚC?Æœ†!Û Z4bÓì:ä[ÓÒƒ¶4°aŠ»9Û ßâ”$ÌÞB¯XØÃšJøÀòcyVVõ�ÛÜ_†ôj§#Jܽ e–D,k2�Ž’BKÀ9Á‰¡ËuW°m`ðIF€#G røîj:õõz œ‹øÒqBx�0? �.‹åÑë¤Yk#¸—6¾'sA‘G_£ijÃ��°ã¡®i1¬|®IU¶—+rTžÀË\5 3ŽÌ’+ùW¥笑xýˆ�ΡJ­Êª¥r-áP÷õ8YÝ^;ä6Öö¨Ì¢Î œGõ[2EÒùæ{ÀÝãÆhJf'ÒÿìQk©ŒL¹Ð²î•W\¤¸ˆ�R¯çϽ§Í;¨cQÈQÑ4›ƒáï�®×§Ä¡Ûñ æû@|¾cîp±1î8›ÔŸ¦ñ “¾.vµ°Aõ­€ù˜·†æd®ZoAi)– ¨Jõ-Û^=zuS9! Xú±S³É,ò·¿Žš‡ÞtìÙ‚85‡5 di0)ÀçEúÖËa›ø�þoÃÅ$”uNœÈa½“XÐÇGjÁxWe¿�ÅÀxíp=¨³ªØf¦ÃÛ óŽjkÆËl +ž`_ø(Ï`ø>EÚné¾ë‡Þ'éå�ó€5l³ŸÐàÃ8_¨ƒ•šŽòoX®ôð—vÖ_ÅåÎæo%½}-¯µÆ\,Q¥bw¥½B /Þl¿3 Mp$;@ú¿ør¶ýcˆ�ð°òµd+|“þöàKåIXíùÏÿ‘Ÿ¶úùüó~‘Hª ÿuÂù­Ãg}œWS"ܬ¹´/XXp`€6)âáVW5¢Ä—± þ›š5›Žsœ$¾y_Äáp'åpƒ²c~\{¡ëÚƒ�CG‹"ãÄÝÁ=eLK+5Vÿ¼‡€@Œ�äë¾yF� >Èøx2¦sdä°ÎÌÔ…ãsþhããG’¨Y6HË�>mÍ¢´zÒ¶Rõ‹ŠÆ‘tÀ pjЬà ك[Pa5!Ö0ùŒ\é0eaÒ�?5÷€P•Á¤†—ƒ7z«×ÃsF?R%Î˲}¤)85ªE¯‚äÅ.€ì�Qê*'Ë3ÊŠ¨˜»ók}.•`�Õ?_p 7ð­3-%ÁP»c§B2\XèvGPjÔÌŸc½ôy‡­™òñzÌ&<EóCª¶P<„× wÞQ+T+�j^åõGå[ÀJL3#36¿,“¯MPãGÐÒz«�ítLj1–îò¯�œ¸èw•‹c°èÒzÓeû(åú¶è6YíÇÈH`­Ed&Ñç-#v¿¶‘ÎUJØ•iÇ�Å¢x!.ô¶ÖŒr¼å±1ðœòÜÉR‚Ü”þúÉXh¥ƒÀ“çs€QÒмӥ_‘íÑ–æÙ¯†»äaZ°&úé *z—ç®Ç3"‰š9|®î+ÿèò!|²/Q•æ|©|$MrÐìÁ_^j.ü":ž€Y~¢¿o<ß•¸äýk'&y0ÆÔÑÝ&“2Ž©)­Â�@b-Üiéþ)ŽѬ L%ØÎM.vÃøR`‰A¥Æ0} Þl43).g“È+ò²¢ˆî†r¸ž[[†üú4ögyí#çœpýyPñ$‰ïŠªÕñõ9ŒJÙÓ“#°ã }ödý`çè )ÃkÇ»µ¶ƒxee-RyÞŸ �f.¢p±øûAõ®&ìùÑ\Uõ+{©ÜKÙVs2¾jBäa­Ñ_í ›o[Û ¬±ÍãŒkATÌÙ"YÙÙ+­ÑÇ�§r5ÆÆ,ñ±sîø†.ÆÂq.’/l­£šZ )áÌ hà^`_ý)*ô=Îãf¿<ƒùi«P†Zà†‰/p®Ø8]Jöz vóaÁóñé¨6Eÿã‚:µò '±Ÿê’Lj'îÓ䜞Ë9?|�WÓfõ%µ ‹hUðj.ƒ,áM¢º©íMvšo(¨7MV÷dè°5£‡¤Òrr�éy¢D†·¹7ä¦ñ:§ts‰Ûaé’sÃõa$—È'û­yª»mÏÂø¿¾^—ý¹²%SáðÄϺµÊ ¼*¤‹Q,ú�™ë¥mÍ­d¢æH¸K½�tth�ÿCÄMíFEI@›Ú£fÁ£Åaå�$³-È=²éÙ� ÷e §)­o_’÷f~ ›Ã ÕøÈ»ŸxÎî�ì¤xîÓÿc5ƒ³FÕOeÊ*(à§yðñº|dç!¨ø^Ë ¯Ôéß(R§µ²7IÖ=Ðók!âqǬ4}>B52^¶ómâóèêqw»ùBi�ÍßðÉœe}8¿Ë |8Ú³¨Xõîã>ÔHrìýüŽ|‡i;ŠèšWåf ŸÝ™½E,ÎŒáã@1ÿöUp°j¨ êZAŠ»%"À�ÿ"R6¼;{¹‹f‡êe,ÈñOD?Õü­•±”DöÀ…b0}º+{d�yVaŒ¦ÿ¨4gÛ¯›p˜È43Þýö±V-áõ®‰Ù°F*A}ÛÎüº ¢+Ê@¡¥%¿ì‰LºïýDVcæšÐñ½ÁÛNð?·«Æ¿ò¤§ñ±9+u Ä5{|†ó;%$�mnQãg0Õ„˜?0œmw^3ÄRtšš_i’ίÄ~ݘèêuÖ¯h;O^@€�(ð úÌòHïñïíš%ÕÓ™hüÙîJºÀP«8#{LZ>ºáuk9¶9C“X§ð´r¸#¬ÛT£.FAªäÍs^¦0'„¡áˆH&èn8'ê„SÄ<í«3/‘ÄÇ–÷;XøüŠáÁS3z(9Ÿ‰Ü‹­Ä×ìÇ]×nZ>È,¤#ªŽ~KªÒÔz'<�æ ‡'ìÿíØh�,[Ô‘$Ü ç¹;äZS/»ÜHƒkÕÓ„ì"ïC£ ï ˜�mˆG¿Dí럡Â{ï6½Âò�ïÖèHãeÀ¿ÿhßÁ²ƒ/­nb& œéޤd_Qšq©»x‹ÿV¥m¬]ÝÂÝ4Vp¿AíY“ï¢d�+Rúú¿‹°R“Z.82<éÄÕ‘&Ú-áØ(Ì’/`;"»l9Ãg$}v„Óò¿].+f¶U/޳„¥�¯‰¸âðNCÚÓdnG¤ï®Ä!{šô`*2Rju`Û¨jݶÆäúH±¬õ3¸Õ†’|�¦Òå»ölÓ&Ä xâìLhË‚;®2ï�Â9ÈpàŸø3•ñfO«wŒÕu¤ÃO±7¢3i0h5ЈÜ~5AØÕ¾híçD×퉮‹rü–HÑ|Óé÷ˆD�!¦Cù€7Êgxu�4ýJŠavÔ¶çf82iíŒK€Q(î»úDÃG/ üK&º¹±J˜Êßú|'<ÅHçêÄ­…æ �ú©®¼ã‰DŸˆ—lÙ9lR‰Qú( Ó»¥¤ß΢U5ä’Vmÿ& Âé”°V5©Í$Ó2>ÍÔHÚ¶_¤Î©Á{ÎÞ!³äÞ³¦e•"ü¬®Áö)h²€¶� <¬…_-C¬H#Ñýü ÉEâ¸[�"g<²PlÜæ,ñM/wqõÆ×û.¹¼ùQV§¤Ú5¢ÍñŒ]Spì˜3‰oÇz0¢HkwLµÔuu‰å¾ñÁ¤…×-âuñèÊÑ‹j·Už²Ê­\àB•˜fÝAs»Œ"ÒÈEw9Òþå²f^Pü^$Á=;ÛìÜp’©‚ü…•Ïï·Ê PàöG蟀?Â…5L†ªí& HÙ{Ó- ØÚ¥1qŒ^‡ëÜòNh84˱¬žŠº kñorYÿqï3’ÙÝ0¨ã&áÇ%@·~Û6÷^£¡²>5?Ú‹L½BÑúÄ‚žR®Oâd0€+órcÛÈ¥¹áçûFU*þc“;TØÞluMòfíûò„Îÿ�ÀH™ú�U–¡33±„½²Üê4“C“¢–g‘ŸÄiŸŸ£}DúhÊ+ JÔû¢hE€bòN;O¹8³@êŸ …Ý °-*oŸÌË©ÆèŸ�Ï-ÙûrÕC›îÅÐI×Âgcýx‡®:ê„3)9@IîëUô»ÉüÑA;~»vÐYœçÀ“‡'Ý¡ ýÁ^éÅö�ûçÄlÀ&ÃX�B�;€2¯iÇy•<›ù›ÝÙ”§©H£‚†sïZ#¤�š«õMx•²Æ_‹‚Çb�0ÊÏ«‰‚¡4AÌ=ÛÜ…kg$<°½†gvßõ/&YrYw Í- Õw?µ±–„0*앚œ¢]à4Ï ;Eq#?ŒÓNƒ�°¢ŽÇÏ�äˆû͘ øICßs ò¸­ÐØ�ÿj«¾ íÆ¨ˆ–ˆÍ 'Vh¶>÷ŽŽ±�ǰq½PÒ¡¸xt�"Ê`Û$âîJάšü?ÐÆ¹Ê±T[Ù?+Åïúí•­auu¾iÖyÚ+þî–ð¡²éÐeÙÐ ¼ÎYþö/¸ÈrìÛx�jËÚ�?ÓGéN|-GÑÔcý‡¨è9þíp4à9òÑ´ô× NzÙ”ý&Ùèä’„“‚/ã9mÑ ³5i’~³ŽÃÜKºŠÚy�kƒ¥—þd<jV!…PаëïïºIÏ?¸E»Å娸äyý„RpòÑI˜;²}™öoò|ûÔ•Rn°‰ˆ$¿û=Z¹‘£cˆõÚªÚ¹=e©¤†<Á±ï¨MÆ·CÇBßֈ蟀“¶T5ÓóãDæ_Çí‰ft"XÝz­t³%y’Ö’iÜczZjƒ6pu�±Ñ×?,v‡†1Ò¸�›S2%Æ“eh½×Œå‰¬¢ƒqRýrmZbãŒzmëÊsŽ'•ƒA'炾Ì‘3H5U8�__Û8¦ÐpcF€ÛðÁ¿äʼ½ŠÁj�¢È3ZÌ…ÌuƒSØ÷Ì–¦¸÷Do¥gÆBz¼Ñðõޤx©Œ¹{^z*íàþpÝ宂ÜG¡N¬¤J²å ��‘1ið^Y#(Šÿ‰·ÿúUgrêõ2§—�*¥,™åJ‹©w3@Pè#“ªô¿~q;€ÍšøJ„ni°”²ÂAgà+@È8wÞ(2þËú+§VÔ« x�»¯ÉGƒr•ÈWþÿJìì*ìQð½!ŽÝ ”L/ð!¹+ŠKF‚ #ÅiåM/·¢ 25'“¡[Íß_iØÕ9d['å¿‘gS}ðPåx&ÿ-±£Â– }f00-s3Ø··;,ýëA¾¢À÷=rº ÞiÑ'ŸR ½Tå¹7Æá%°Ìó­’—M BmÈcË¥u«O¡§¾îÕøWyÃCª6äãû/fAtõP=Ž[„âÿ=ö(ô€Q¼§=»_r9ŒIˆÖ¬œç.¹¹kð…h$c%¤,fΈº½çbÇôë eà{³´R¼qU{­„(Èxäïœä¸¾Sh~ØÚ‚�4v"i}<Žõ[³¦'�$”ZÆbÀª¦ÂSúJRº„ŒÖ¢ïÎ-ÿÎ\ŸWõÏÍ³Ï­Žø ­Eýº„ÝGüdK«þ$èŽ]fÆœAoWâÝçÿ6ø™"j÷°÷ï± É‹ŽV2}¬­ˆ8ÇÒ— <ÒöÅ6{³Ëäï¶zºŠö[‚h•6y^8Þh½*ÐßI&¯Nù…$Èù¶þxó#îmo’2Æ[ !ÛSró×ÐNÕÓÞÁà ¼Û¯Ð¾"yŽQö{‡ÚÜ4|<ï“ÆÀ>¡[:�"äôÃàûÙÉx"ïàýõjxe: å{J¸à¶œËð#¦ólÁ?ró6±ÀóñCHÏëóNàßáSk>êä_k®<<Ñ~3i´¥JüREô Ãv­ö¶ÏuɆÏ\¿|ê�œòìÐ9Y°½D¡Ì^–œCãûÂÝM>oc �Á?j6ËÒg«bá…ò<£@Ž£7ñäõ]J–¹™{Í8;UnÒû«ÅJˆ�½N:} gˆm†ß¥bpL¨ê§%ÉŸÞiéćW»8­kš¥å±×1p©åvq>òsî ŽÎSÎE™:‹kåÛŽzÌm½œ®â³^Õì áT”F£U˜>µë4—·3‡ FòRRd£DäßÙîöݾ”*àá@°RÉW_¢t=¿>‘Éfá©Éä‰pWi�BGaÜ6oOK„Ýá|:ÂImþáù©*_âEÔ©«ApÞ�‰ÈŽ,·ˆá¾ÝÆ«­)·Á!PÇ—«˜Îqm†Bt[ŸŠ@úþø3Eé]jÊ]#Â[2T­3'Üé$4ZÏ€ù oMK}±÷¾2¨rTßÏ•<\1¨ž‰~ñx]˜–’½ÒPw?įigE¢dðUf †¸îÐd |�þ ¾µ;Á® ¾ùøöŠ¢è1ve¶œE?ò�½9Yã¬ûµ^¨,G,”Éèd,·1Š"Ë`KÛ”,n,-¸ì¶Z—"ð  «E�âžÚó¥ß’� Öôçÿ"Ñ /„ÌÛI<#:WU‰á<9É•kbßôK€�øÌJ~ÒX/°õ GÇ`T¹C¢26Ct¸ ™$Ê'¿ß9è ªkÁÇ3¹¼ ;ã*dÊ6Ä»Šä˜UÜ)‘Ç�þÈVJ—�®Td‰ÀK|éç‘(¯Äåw…© û}A5T`¾V«óذÈÂUÉ ]P;¥¥¼Kxƒ¯pf«¯Ø&i¸~¶&½D„…ó"=�k¾*P‹&S†Ó¥ÜŠLLX,ý®êöe�B²Flg�–f8g7bˆ)¸ÇçТEdÑ`/ø{X ’9'˜âÿ#£^¯ÔëS¨ô¨ØäZ§Ž^¤'52n¸M@Ò�az4�*³™õÚ²´Ü·ÌÕ“ë˜û�SqèÖØÕL�œ gaxô}µý<·œgïmf½ Ëx ¶k!oP«©Ê D¦n·<Œ²f¸Fw¬Ur=’ôê�Â?~ËÙßrNÕžÄýy´ù³©xŒ¯È©$¡Í«ŽÛ×\ _ܸW »Dù7†ø9‡Ïúwœß„ZèÃ’þ ©=À/@µ½¦@ÅNRúÍI"ïUý½Àà~î"è;\&ðI ¬™© ]ãgïΰ4™O}“;Tdu޶ìíš¼ÌÒ³é „+Uü`³aî8^h¡ÍE vD²2(+Œæu~ÆäÀ’ZÍ¡쮈^ðä„�™ŸÌÉÏ}Ún8ßFðéÝ4d“Í?‘á�\Qãøµ·²wî²Aíÿ;Üጫ¿'º¥�™Ð¶äšyq®Ïþ¨§YI¬áI†lLF‡9ÐJ4"{ú³ƒŠ?šèý½Ç¬êæ¹²–­:Úºœ(K^ ä hn›‘²nú–k0s#†—ˆUrd¯ `5„ÿcœ½_tëá=Ø„­Üù�ÃÎðšÚÇ´¥ÄâùQ=*½²ï=s¥®ß}çK½Æûpàõ4ØM åY¦®ˆe航ïß¼p+¼ù'‰„EJ]ˆçPH›h»k <­ýÐ7Ъ׿H ìU¹FO_ðàCð Æ`7zÝ �}¥ÚF%¥’ùÓºr:#j¡½qsåßÂ_ºÊ?´ïFÄIbµ”;œ¯GOÃÂ5l’;Â÷:”ÒŒ2ãG(Ë~zÏ¢HךîÙÛ9 aÔ <¼Õû@r©� µœ™„ó›®ë6šã€h”Oc(Õ,ŽÇyÕäâ�Í�=ÊÖÀ{ˆç Ä ­4J>ØM¡Œµ|¤òv†%B‘E:¼ZœI3jâ†>>&¨ü`7FÍŸY£¾æ¤´.ÿ ùÒXßÒcÄÈ~ßZ�­dsŽ©#J:z¤&½ôÈB�1³ëýè1ÕˆQ/€šC0ñ!›ÚFåëñ!Ô|æÒóÊ_'œóÄs Ôã¡H¶(E³á9=Ýæðà8ûÌG‡@Q0Ͱ=χùþ’`:Ð+Š7àk½|ØT>»ìR¤‹ Lë5—ú8—-Üî×·ÕÖ„M>ÔG)Õs¢¢ö!eWŽÝŠ\ ‡;7�¿M€°^ �mÂó£ñæ×â[ Þ„6:/ o.Sì·Ð—`{RwÚKPú=“£ ½<¸R+˜ÖEu%”ö.i ¤‹1ùôŒß�ýœ®6¶‚s#f<¡FÐòÄ [³0<ïÏmÛ„Ü™ÆwUñ³f$�ýtÕùß(»É�ñ£­ðÝ­Û*ÍqzðäæRq<…o–?áž™�Ž*âš®7_l0W>õÉ M¾u*Õ>A“�íè£R�þ¬ëIí3ße•:Kàì‚a‚K,ZëŒØ†‚mʺ’¸p&_°=ó–²úI„”è=„Ð@då‹ú¡ÀÄéék{gy”*‚o>àeQ»Hc�÷\[¥>/èñ…u)¼ùç‡]ל.SZ–*<Ê¿¶¦†â¥óª"Rë†Ú"‡Cí¦‚9þ CÐJŦ)·ð'D8§ƒšfì:EÊs÷ˆ¿Kxþ³ÿÃ`×T™%»OË™-ßVÝ|9¢üeûªF2’ûñÀðÜQ"@y’@÷’æ®F6ðï!,Ió¸‘ÖДNÔn—86¡ üa�„«±ðÁu´¿Hí‰=øŒ¾_²¬È3ê?v'ÇáùP`áµL«]"ÐûcE€ð=ÒXw:ví˜áJe~kyÀ†øk:uË ÝOxÁ/Ô%gÌ�"œg±™ÂQÆF¬Ñ™ „�Fvä'ßåÃ;*ˆ–ÔÎÅVRGŸƒ‰ ˜Cî})µ„9­³½"•ÃËq°®½^=ç¿¿¥Î`„Ò4žO(;‘O_{½Â ‰R™ï´3FAdþI]¥­äèƒ\º«Ö�¤”Ô¾¶7át-é¯SêÉ|Õà—g%‡ï"€ gí¯&ŽËÌN%®±¥@…šP|Œ±Ç SÀ­Wªºe>ДTNêQ«ÿBÍcëQ¢"Õmeò¨ WD`� ºàŸ#$¨!Ú0Eb*üguÌ¢pT„óÕò8œßËÊ«În.Ý‘­. ½ÏèêPQ%Lz°ÚÁÉuËÈqpMìÓ«4£1 ›àãÞn$”„Àƒô‚—'þo-hÑî)ý9g¶²,Ÿ_¾`AÛ×ßÅ(oV,å¿ç>»"ÖV5ˆŒpζ°Õ|ºp‚Áw�œ•qdñ¦öµ¨Ï£ÈÖîÎME˱ÍÀbbc#8äºaoЬœš'§OŒúÔ�x•ºN‡.¾Sû„ž«I,>xŒx¸ôÐí¡Í–˜�oŸ�XJ ãU¦[¹1GBìW.O2¨²÷–ªÔf ×ê_›Õ½—25(Zûð—?5ˆðN›7Z!CÄQJWñ˜¿[ãÅR‡Ö˜2àÆ¾]�ø×ì‘�_Ý¥‰=p‹+ƒ`1EKžmç´æ9#‡Á[#ËÝÿп?óXûh‡¹7¨ú79P,V·¦œ(Éxbþ’†Lz†úñ3üáÿe}äøû³Œ[HÛ°\Ã~}ÜL(¾è|½œÒETÀDîr�fB²�Oø¤ên� bTO²šºEn®Ñþ“¦ƒÎá¸S'å«¿‡÷·Æ¨pã“+çŒ <°„›ÁXõÚrgˆq#@Ã/Ÿ³Px[±NNÓiAeJb¡í6÷Õ6Büi˜úØ^W2öúO¯bÑ7ÊaR×�1hÀp ”?eµŸ ­F¾X·ü^tZ•JöNPz‚ýc×ûðâ@£ÇÝÎ…ýƒR^�#“Æ€¼ÉŽ@Y}û{˼íÌñ-Mbðò]lüÃ6’œžØZû�©œ‚§C�™ŽŽZÿË¿ õ»Ýµ‚ÓtF±y»µ´° ·‡x¯°]LÄ‚44œã´“£fYɉѢ<(ÆÏ»ÀC„Ĩ¿ý;R׆*õ °°V÷ñô�º|à¶qõÖ˜•…2–�<…‚T“.X—ÔUõm@qÊF˜BÐÞ`Ê÷C à²ÚD!ÕÌD÷ûÛ·ä¬H¦n0¯¦ª+ùlzSú�:ć–‘v¢FËl\ò¼cØ­.z‚¼_¾¬cÿ}BNQÉŽÂú6ÜÀޤÏh@ˆJx–JÊŽ‘bÛ„%µ”d`G QŽälI¤*°îý¼ø V oÿàS\g6Ï \¼Í:/�,w0k:ܨc¤2“êèB®[r—]RykÑô)ØõW•Åc9Šåó9|4ª›ÀgvÜÀKEö›ççÂævµz¤›ñzù²ª¶u‚vÂ,r—qÈÉñ?|ü{}¬éqä—j¬s'™vH’ ù�Q3äà‹Àür§ðø wÜkx§°1Ó! h¨Õ© r1ÅŠ»ËVþä»<Ù¤´`]Þ›£Ù“÷“@ÍÉê7Ɯؓrªx1‹qB–nR WºÉÓBç¥!yÙú„¾·%â^}VM[¦å}06¸þ@ÕÃ;ì :ËÝ4)îFü²»ËªõÑ?`%*�ÎR;¼AE==jœÅ¢\_튤РØå×j ÝER ØJâñ^àž#¥ôO•7Å•üåÆäM묡x™Î­&#÷ Gˆ¸=#ì>&Az:5š_t‚v2ýa!:g`Bwr)!Udâmæ°Û”V"…ŒÇ6Âô±…ÇwÓî«m)Ö,}’pÌ?z3R½¨"š¢I�z³|è„B2¸F‚^Å:òòy{LI³Ÿð2¼)c9ŸÑ‰²‘š9„„Eþé ë®ÅÏ•êÚƒ>m©,N{œ2à«aÖ2iKÃðqÏ�«HaŽÁ÷’ õØx*~EɶÔö䜹 úûArêV�Œïtø`ÙLÈ*|.î\̱MŒýÈê÷c}_S¸²rž™BW�o§j¦÷*\!»5Ù†Y¥�L€³YÐäâì²òézÁse~vÜp'éø¶…zÊÿ‹2¬·°MøQη4hÒÑ–}è›gÂíÇb:JÏLÔ�múMÄÛd†—©ÏÆø1l�¤}�¬Ý%(¼tU–_ddm?²jÚ‚ä5�ØáhZDf%wã\°]¥ÆYà-2ËEÇ‚s#ÒÈ1új˜³q0Ýúj—�-AV-õ�dë~ϨøRœþg=��“ž¢ôØ)'‘ 5ß’¯6IhHà„ Åê™sÎPà°Ü=JÄ`N¦Ú­UH�ÛŸÆ.ü£¡÷]¯À*reûÔ š¶ƒ�(ÖüEs¡Žìësö•HÌ ‰=#~ZÅ@¸‡†Mä ŒÔéiѼß§šW"›ÐìBÞöµ�jˆœàD Bæ ñ…<(¶°ƒµ9ý$*3È{>ÿ8€Í6ÍB«›&©¯›')è_}åC0¾ÿ7ªáQIò^ÄNÛ¼˜pZÚ}\ÝNØF’Øû½ûZ�û„b ‘ø€ËK�4¸2X––ro;A”˜7Ǭª +s >(ôÍÄ‹ÌÐï­*¾cQŸV¨�œu´%Oq« èC^�ªÂf GûÕV_[Ï{üYıÒÇ‹ÿçxÆ«hù‚ß¾8ÍàâÝù':ŒUd®<ÖÝ‘Às¸ ý¾=È/¡­â «ë1S±aÍ!(²ûÏ„ÈîE%¥²ýSåû%O÷‘gÌãÁ9ÌCÜê%Q¥»º&XµB­4$m©g–9q*ÜyŽ]éäñKpЃ _vŒ ¬ÙZpÌÃ{ò*{ðʺ‘Ñ̵{¬÷åuØ8‰¸ÂAÔíUïødÉrpÛ©¬v_ãf‡Æ�„’ÎÚ×þî·‹‰ì„µ+¬ó—Z"T�w¹¨3Ôÿè_IÓ¦ío¶›Ex³Ù}AYd;©\{Ù0“ó6ÈH¯ÿ-Qr0ϯ\^OÄ|z‰™7A3gè=:±È£BÉ|ÅX?rR?m-v3¤Tâ?ñfD;}\G`×w—»Ô·šÏÆòñy{™ÖLüuL²½à'µ2,òeŸ…·d´NÎdwªBG€-ÜQ’Ö5ô”m‰�• h“ܱ&'bæaÎæB‹ÒiÈÆ›ýÓ&AÓ%Ø–l£æX‹†©ÔacbË,l‚ÀӜ୅×äüsÚ°èÿ/õD€¡eOä*UqÆ·V£Úb(ôá+�¶­^éK«y r5]î”óŽŠpB\ì Û†Yêäè1ÜrÌ„i§a�ØóUiGÚß3�‹)vÕh#¢¿ º/7”°ÂÁxÞhM¬ýŠpÃåãeº×Âà“Š"1G4a¯¹©6×âË PëÝØ|(�Ï“ßX3\Ø‘~°pŽ<Ì5fáL(?YÒàe¤úÿŠ=ó"ŒŒÑmzp[RBQe DgñÌÊÁÅ­“ÆÖ¡d³Sg…„Ãv=û‰¥&ýüé3Qà.N)uý�âsO/Ž|:WS+# miýUà±k½'o¾ù#àßöÐyl ܈¶oÕTÍò1íί%\ È/ R¥›¥~î�q|&ÈrÉIªóšQs”]Î%¯7mú�n@7&}˜çŠo¶`Èï#¯�_¤N¤71ßT8 ‡ç§ñj¡ WÒ$©È€_¦ x„>ädZ]ÑB²ð4°†Šºþ;hØAWVÚÜOq4$Êš3¶,7�Éy3êÁˆ©N¨KÔeùÂâó\«©ß¯÷Wæ.Ò ©ól O!àïǧrz& 0Z‚cyó@}K³q’­By0rJ«r?¹¯4Ýácgƒö±¶ØmÖëQÊt>\{B…Àö°7‡â¸V 9üv ÒÐeÇK~LH-‡ZêúÖ~”gµ–1i÷S%ï»óÙ�$Ð]ú˜(<Æ-gbVp™ŠZQx ¿îÅC!0~‹­C™m9ÂÖ¾âÔÍÁi´´Ž£æ�<(ùÅßcÔ „ÛŸå‚Éý·°]ÖDm` 2¦ ¿O“GÀ x¤£K÷§@>â¡¥'žš¡½Ãé; Žq¥D®|ä¡÷w$Jáï�¤ÈfÙÿ% h?T°—›Hë”aGÍE3Ê´/)§UbÄ{f%PgÏwÞžFðQûÍ8y“ék¬Æ¸/Ä?›º,ý§^$¾‚ÁzP@¦æÑ=Ò¼ý}2£¨àjµš�•[¨þ\Þù(¿h�á"+= ñà°žï›’7…äT'J­ÃÙ ©óáwDµñ=“¤Çžž—¦ uH2í't4Ç|-*×�Ír ð©Û³=,QÁøO„:Zæa¹A­Hø'Ðÿ¢¬ÊËKôZ�¢°3ýpUÃcdáaÓ³œ$€2å `­Æÿh»=ý—•aû¬!?¨×û€ÐiM;;ëêiœ5U1Yó¿b­å„b<ÙÂy‹ƒ¶Žeq0b¸àAƒíÛÔ©Á ¹èË%�uHââ¿oöj7^<p™!¾Œ`æ<æó¼(X^”)©‡³û O�«é[¿Õlƒ“¦ÂÀ&gwJÎõ†Ž…¬D8CÃ%¿H ÷aaÓnðgéTH7¨H%hføøÕG«¡-˜‰HÓm25{ijl—*]h†=ù9ŽêŸÛ¼æ<ÝœÒOÚ¥•­e=‘�·H`ä«Q2ˆÐ�W‚'þäÎï÷Êû KO‰2†ï&Ý�°Žç¬DLþ¶”AÆÕÓ³Qg¢d„³•N¾¯™Ÿ°Óy«ùÊúÓâVE\™ˆË#ðW‰ÔñWÄ/ûÊ ’\™ÓV•Ù*‹¤v*Œ¥uòÏ ¥¯Jªb‹Îݽûú{6v`¹þØìUFüˆ (ë“ØZÚe\åÁq¥ýª•9¬puž‡¥^ÂcvŽÓºÒW͘Éϸõ}uÂ’óy1V©dí‡'+ãÉh_s ¢€&έØl®�§ì2/^&¹5� n5(²¨Ù“ oÚ31êà9…?3•p\ö3 §é6„g„È€i ™æ52 :€>Qâ3SqÜÂJV¡U_çÕtFh•"¬‹W†eÛGKßí?ç1‹ø9…˜ôØRw6¨ßxù(£¤‘©ñ9«&e$ N¬{›5–«¯õXgS8Ùy«8k®뛌‹Ê:‰Ý׿NE©êfî‚VÚžXª¸0Á@¤SF<ðo„™SMnûÇDå€-ŽŸmêt ÖpÀ(‚;”`d,D€Ü9åúYŠ5|kOw¸=㇉D¬Èg5�G§÷s»@À"ôs}X)˜×Þ´ÙÄðÀÏH#M,¥)Û~„ïÎݦ}nYà‘b¯›cƒfI¬ÊÃ4•ì�!Äaëg‘¨Í‹¨ÏX@×Dÿ®|89l"OaýŠ®ñ©|™Ú¼'ø²¯$”«ïÓµ¶£�¾ëë{×iÂ5sºÎ¶Þ•qʆÖýÒÑ„ùr�ÁY,’È)w¡À³” ªÔÈV¨|0‹[æ×öë‰Üßr…?Rx/¶½i¸d}öœ×W¼ PÆìe>˜¾ÎG(eô�r@ŸÇsž#T™àѯQÏäOm>Ú›àbÉ2¾S«´éDv¹õ±Ôöº�nDýÿ, ÞðKŸ…MÚ9A Ñ$ä-ÄFƒNŸ€„MWìgqM? «ñ0È³ÖžÛ”Ž öžÓ�ZðÒazJ·§¦‚lÝW|œ¬w”]tå÷|´²Ç^·6o�xßigìÉ1ßð õÒU„ôæ|þ¤OœZ7@ÃùìØ›¥4 êP:ø–´‰3³c‰ EIÝô�ê°ÓV6¡6â¼õ®8àþ—@��»ï, ¾Ë íJ´_H4#Ö‡Y`Гëذ¸dóˆ„ÿ¡£ƒïmñ‚-°„JUM ü²¨Éis�E˜9þ–ØUa“XL}×@q?ëÜì#—ðgìv”£»•ÆØœ<áV0û±¼Ú% ‘Ä‹³„Û‚VJE†b;ëK«`Ѐ‚0}vaÀŽ.Œ �Rç ˦ÀÂb‰Á²º÷ªÔ9Ž›þW8i3Ûªë#»'rÿUfl‹?¼|š/œø#ÓXàd–á:¸lA(HÏ¡lŒ®Kɯ|ýa¶zØ“¾è›”¼hG6F11vv�Ó×ÌãFDª˜ò̱$7´3¥ä’Ý2 ¢KDÕ"[‡v7QÓðñKå‚·ìõ�™C�÷Éw¥ˆî’“‹¢n¨—Ž/¹¼PX@Ã×@I'ÙÕÃŒ�\'á]JZ±`³úÑ,Bµ«$ƒ^”æ´§ 7ëög б±ã1Çž ùÝ<§'fþZ®SÌ®N)äëù:^÷““Pð±$³yÁ°îëÞÚýàºÄ‚—^(wYÎü/Bòãî<ÿWK°5b ßÚJŒe‘Š2Ó¿ AŠŽQsp¬;�õÜ S;å°Ÿ5»Å‘,fA›.WååÎ�/Ë›e%—ð_p×Gm¹(õUOU³§ËRùõ‹vûǤu…ü©‹Â-ˆŸPLàf™„'È_ÐiÔÔ¢øjCA¯h½n-��ÀÞ¤ŠáºÃé€Ê11ÁX²{å-aA¬X’'È`û•î™kZ…†^NŠ0„±a †’½%»¯}Ù)%ãð“ìS¸Œ»ÞiäqŸÃÈëe¼—#qZ€£±Yеæ~·ÆJ€šZª~�¶ë6bÊ)ßü�Ãÿ8ÔJ�Ûž$§ÏN>YYIf®U>n˜Çt5uý€iÄåÓ}Ñ&†Ë/ªÂ˜ã±r:÷fNI’ñïÆf2ý ž"”¾ëÌ£Ý'T)ÄÕ×í/†�J¡û¥òð4g�ïÁÎÓO½Zþ8,|ÝŒo óSÆ@*$BWrU<*К(XJzÒ¨ -U粟[Ûã6®,ïŒÌ“Â!žì0Ál¤Ñ™ðCÉmº–ðßkß“¡â„®0ª>„0JDPÞÞ7ÉÀfj¢íÛËw–âç äÈKÂSÍw9ä9H‚J¡�]—¸pé—½Ï$¹ÑhkÊÇg`³.v׬„§¤ ª›y¹O¨/Œ Vú‘-ðÔ„ˆË0û  Iê?d<>N�ò#;Þ¢&®ÒÀï V—ø^W–Ûî`qÀŸ$‚´¨¾pŒK?cý „–¢ù—‹iDð˜0ªzHÁp00‘ÿǵ¢ÎÞ\û'í;Í‹zÙÎQW¤ò»œ™#|!t&‰E}Æ4Iï/0:¯î­Û�}ˆM.¯¾Ýw*‚³PÛ˜ÚÄ×À¨Q¢ñï�ªîqz/Ê`3Æ&àß$¾äŽWG�³-MÙÖ¸†= åmê*H·VlôÏZâH{PWý0±¾ ~f3aÿîó°Y€æÈá›ÂÉRÚÃ)Â�¾åi¡j~Ö›ZdtäáM–ìêŒ{½àÉüŒLJýÅ/¹ȹ�cfK¡Ÿ{íàÿÌ9ØHm—ª@3‡Èi~:ž³G¼ª /Ñv>âf©HbXUÃФjì¿Q>o£Þßt‰œ†|9ûkÃF8Â.]’e m½£ºþ|¶[šÄË&< âÜÐEŸVƒ^Š!¹¨×úö’ù½ÚéÎ1ÌÒ9 N‹v�·t`šK“sÜ9C:‰3uÍlû cNl¯·@Ÿu)³¯«®[ÿÛ(öf·™b â¬CÕêºcá_â©ØbûìEÑGæ*�³�­ÈÅ鱿³UÒÝãÄvŒa@jNwnÚB<Îðè_œz'™¦F³#.M_³µË<*Rë¥ä©aàN¸[½‡‚‡0W?×2ꦢü]ñocð´¢¼ìK¤š4Ž&ò¸Š«mŒ¤$Ÿjâ75aÞ\%éþ–ü{XÙŽ8)Ö„÷^=5 ‘WcCþ2EÉVmg÷¦[Ї02áÒk—-F=‹!ÎÆ xyüìì �4©‡ÑœkôÒ–+'šþòëÞ¾i$XÑšY/~W¹ÈŽÒÚ.ÙŒõKAÀèO¯f»ŒzÚ°3øÁ,ÚN[ŸåŸ&`ƒ»¡Ç5…Ì*Ef?1LàÏà`8†=²çbiàø­w¯ÂO«4 /êvý)T&\ôm~Sß(x³;'ç>`qÛT�È�ÎZcÒ¨²E„1MÂý½×¹cà1À»×’Åd°kÄ·FléÞX\Þb™T¬@*ÿ·6=BÖÓÈ«"º”‰U™è\ZÂÁx´%Q™ë×°‹Þ0å~úaÔ ‚A¿ªÆÉ’Ì ðÊìà½~|g%±VÓ0lð89²®-$ÿ©Öq¶¦&@NcˆÞa�ÊtfêÂämÜ^žýÛ¶*mº,»²�hÆ<4ù-Ð{$]ÉÂX†ðM~jYJ±ï‘“~ õ2Ÿ„—˜¦—È[èã.j÷Â1@MsýÅŬ*Ú«Fhˆý¾¿)lv³c0>Ïq}¾.QA[­`#ì¨È´¯àå0uÿŽš&<Èß- }x“ê…á¯ÆwPc8ÈU¦¸UÇUàÇ�•<&µç�d¬J–ÁæˆÆqâ|ké3HAï`²ŽíÂx-W/blT£ÿ›Š(4É×›/þÛ1Æ!,®ÿí¥×ËEŠ#$öWB+ž^žAtø~¸˜³ÚG.%Ó[z{;´õnGH€B‘Ø$“$„WÅz±O…^Ì´„&û\�(Å ¶ö±ûÎq»Š@ä¿—&Ú'1a¼ù͒у.®�ÖTÈÁ]š=cüTÿ@®àx_s�ïçÏg'6äó É5’R-û‹˜wYšÕJò<1¢C¼TÌ/ ÿ^¹�sÍœX!Ó½¨á%v7f쎫ó KÁ‘*}°çEZ4 v±å»P^Д'°"Ê$hG–(bw¼§§Öv_ûÁvH�1¸§:!–îmûæï R•‡ãxH”^˜)7j£u$!Gc)Ñ€-H½¼Ý'D xJ ðMéwÒ¯`öô� /Ãó ‹Å•³Íå<„ˆÉ2¶ðÂ28å¼à9ˆÌ"êGÝZ7vMrƒ²ªq˜Óåpùtê”w—Æ1/_›þß?/_Ãwÿ»AM9Ë!MöÙkr²Z�IÛÇn�]?Á€BÁP5f»…{ç©>©fÍòî‘Ú|‚¥®;yœ¥ Ü�:Š"ÁjNÒžr>Þ¿K^Ød_LÝŽ¹·¢¥s˜¼¥l|Bù2™ŽRs(c)y Êý¡Ð>ÚH ^�Uœõg^Ã,‘cÎjtm]VÆÊ”e§¡I‰®bR÷à#v—åQмnýö¢¸:¢Ô=Ž�õrï<Öˆ6tMŠ3›î»^ê¢(Ö÷�0# Þ•e&ð°ÉTŽïìiõ§á±AòòIðê²�Ëa|´Q®­¤âö’È–>öÁ¨þP~Lj+6Àd{$R ”^Îr,?Â-=âä»ëÃb[U µúÒ-Îçg’[5£�-Þ,¸vÓAá°<á4Åu*ÊÛÈ7Ô/ÝCbccHâ® ­U„´6Õ{ Æ�&.TTÇXÁN½½,b©× Ê&×Q B1Ö–Ne ÎùÍSTÎãÎ¥“Ä¥fº»Ð;&5[U¥õz{`cƒ‡>57Î�”¬)×fŠb �,uaÛ?CðØ�ÞàÆŽÈÈ«Ãýd‹Ø¨ïªX”ÁhCøF~®®¶T“R8:ˆ� ˆŠAo±Œ`ž†™W%.aˆÝxUÓ¸J-O³6ýyi¢1Œ¥¡­©\¼VN+M5œR/`]_­…L…S+Ö¹^Eï§:ºsãsðIªf4$½îéì*cܱèÎ/P¯ÎBê5•E™Î_‰Ä½ÀaêùæÖæð™<‹{‚УèÇ ¡{'Yû—²~ÏMp|•�陎>øº¶(µ”âx-áN¬k ˆà¾5�-ÔŽ<5«Ài S ”¨ŽR ÒWõ«;Y†8±ƒÚü¶Ý…¯‰v9ô©MoV%�SãàJžT§S÷°‡ ¢EǦ8e\j!�Ê!“í}ND~›ê2¹`1^ÚJ;I.VÇ’)ÕY‘'6‚ »YÓ¨Ž�³ Á›º÷ÕhHˆqœ©ÈŽa_ ÐBjzZ-Aisµ,/4µuò�×ü³{.¼Š×ExµÑò«›D!�ä$3Lò–[D=‰ç)ï5)´‹0váÝ=ûdgNŽhÕÖ‡b»›ºO@¼ÓZ�,AâÈy8פf%»‰ [\ŽõŠ\å·x›½;PúÂŒwa¾e:Øp7X H¯V¬jôåµöS¨»–Ú7½Zè}»!fDuT Þ,fà7”¡%‘·ÃOl-ºn}ÕÖç¢!ü8ª“,ܰ\Ê´ <üÀ£ êXsðÅ^`Íû�Ö¥'Ý×®•ƒ—êP2Õ /õ…²kjÔá w/’Bã7ìîn‹6K±Šœ“³5­ÅɃé¹gRýª:ø~RJ_¡ëçZè¿�šN-�©¼{ô©*C é~-е_ ¾D�çðpñ“"xò@´–|iTøæí«UÔSšº�=¬‹æÄH™²‰t`VÆ^ä}úØ'ÂP+xžÛ^Z�MM*V‹³0 v°çw=:\ ÿí³ŒÂ)ç/†%É™mšÇ ß½Ó®Õqa°Èá#�i]p yè3¹ž‰Z…‘ñ1 vpbß`‡î¬M¾ºañ(ƒHÞ;±'ä•2[}âºÜ¿x7¨÷ãË£.+"™L:r=k]ÔKÈ +ËQo¯:¦´Ë)’Q¿mÈS¸ Ñµ—öù² ²`µ+àØfe 1oækéPODQÁ„òµâ,ê²U­ I#. H„aÓq+×OìØTé-0ÂâÚé V�Ç•h:a¬>Q�FôNïâ_NV¿dWã;7ýøãˆfGÁqû ô4ºÏJx¯HÎ>}~Öû$¾ïöN_ÛäE¬í€àÉ ¢¢êD>€žô®.ÏÑ‹]â�žÌâ�ŠºÆ�õy”®`€ç. Ê`6¤°^¾ ¯tf!ò£ ¿Ãç­Ù@¶$rÈXR¥Cy(g{õÖ¤œÒ¹©í›ÒV[g[¤¨ž³Ü�>YqDþqË<ù)SÚ‘‚¯&Ã4 <äà.ÃÙSÃ/EGÏüœÎ¦ j¯‹Œ÷e’AW£AUZ�e±)³‡nÊK—Á‚Eãé Mæ��ê<XT´7¶�¼èž2J”úæi.ï:B?B¤©™©¥_®j”ñõû\ØãžÁdrb¼É"¸æ3:ò(LËi7€ ë/Á'ÿ¢¶Pöy(a�¥‹è(8ø¸}~yÌ�íÿÜ*ÙälŒ”_FO9Ù\®)» 3"ÐÒyŽ&£oäÉkg¤(@(úTøèÀ¥CÞ�¨~êúÂ=y[ª?–Üs gzÏ6àµÊõ¼¦4S¥fqLKOš+C™èI}LÒeÎ4§�†ÞΦX9.F"ˆvï0‹h×ó¦l?`Ø?/Ý€J‡\NFó tŸP$E�£‚Ioãçª�{„Ã�Gý)¨¥² ·Á}“Õ}ÉF€�\îÃ*Þ6Ë©©œ UvÈt<7€éšFð íï8Ì`D·¿ˆ“<ÑI6ñ òš·0ùí6fñ@Cj™€±gs´Œ¼ŠëZÏ*:áìÞ½LŒn÷ò¾,OŠ«*ÝÍ÷þ?Zꌨ»RÉùbQ>7KP(›‡ûÕÀ×Uô«R20ùŸÉLµ�A€«âog¦šBéÀ†ì»›¥™Û°EØÑ¦øW“/Ñzr0?xH­#©¹Ù-?pàI0£ ^âž®Miø®£Us›¾µîã¤h'ØrRÌ!ŒåMÜ]Z÷ŠØ O¥�§ÏoìP¡Ã•×0¼--[�ÐÞœ~ðų_‹g©+[Tî{¡0ÉVË·}ô†»˜G Ee¶ý7–í ·Œ„Š”JF¬š»hFtÜ–‹¶êî!§QÎÝë/�„ü�#j­Ü°ˆ‘ Ö>ÐËÎ>\PL�¸ØÇÖêac÷e}s›„1¯”ã³5pç ÂËa«ýð£ -»KÁ…ñLå‘›³ÁÑ�]îÔf EmÌÇ¡‰¾µ%n§Æyš*‘t0{I®ûÝ¥’~™nl«‡IÅMJ¿ÍÉ+§ÎpÊ´)°Ñ.×zÄ¡#+Le nž`Àp¹ûéÏ‚k&Ãþ(ˆ�-‚vÚ^*šZ‰dÁâK§°fÐÉ.ñQ¯Öú@‡1æZjL“ů€Š¨KžÍyK›Â®46Ö+Âv¹ÚI³Ïõ€›qíQVÑÃ¥LÔ?еŠ$ý‚&Ü-·˜Pz›ã¨‚Äšº'ðÉ{ü(Z)"ØîÐ÷  4äO†£¾‘cÄõð¯ tžWÌr/÷ôGL» Šôþ«àA©GBXj?^·œ Qî(=l{Õ+Ù làÄ—²Ämq#¤µVµfª}¼øtàx§ÒG¯8G_r0XŸoKl4ÈÑ‚ü…\lÖåfpgŸPF×¢äGƒ«e¢C‘òóV{šª¬ íЕ­(í%g¡›$œÕ˜Ç$ýøÐ8’HzÉúÒ{m!ƒÏÝüY/¨r—ôÝOä$jêEøý{±¾tùÂlSº�¶"%Ù&¸]TF”IÊïx€…Ÿ„e šz½õÅl�~]0­0Fò2é�µ4Í4u•Í ÄHÃ< QsOÁèô™®â�ëI&ŸÓQèÙæ–l""Çn¤FN¦” @e8ƒHrTï�ò#F$°¸Æ+DüÅ-"Äl§!{ËGÂÂækPåz‡ì8[Òiéî‚¢œÉ¨)-«ÑÖ|Üõ½Böµ¿Ó¼ƒô.ã[)ÿµ¨³§…üo±Ë¶9®ó,ãØ?¿†�‰bT—Οªò °GÌûÅ�gi«E;Çüu@f’‚—P6ÓC÷bbå÷s£QduWJ–³]›¸‹6hWTȱÇþGsï\!øÒ츫„qâ¢|Œ‘Ôþ¬/tç¹ä°(AĨ@ºpUÃÅ!­ÁÀ«A®"” ›-zÆ EjÔÙÕa× ùy®þ¿öU Œ½+žîP~Gótï`åš”v_åÑ©PjW"X=ÜQbvÈuº½�"hŸ‚£]ÅÁ›yËÉÁSä¿™¦Œõåf�TGMo„ÿKxcÔÀŒäŠ÷¼.<ÙDÇ(è²$ÙòÿžsSKQÚ2í*¦í#ËGëï¬Ë/ó7gƒÚÅêõÿÊLŸ\µ �q=“ÁÇÒÉÈ_ Š,¤;iþ«Þ‰m²dGúl †�ò#¹_°b~Ë(•øP½‚|pÒ‰t£CíFÀ�žñ~MšSwSÇn5Y‹™ð®Ï„ÁÐy5)Æ_‰!ްχ;FË;lïÞs¸Üà ÓUee¹n5E¿[†±Ÿ+†a©ºé±3Ó;‹D L«Å•Árì’‹ÌëU£}2.vÊåçì; [„Íú r†ƒwl°,î·3¥'î@À{ßBé5¤¸u,í¬Ö3q�êPT’V'R÷¾3y3/›½Àlý[Ê^�¬‰3Gä·3ý±¨�ŸÑ;9Ñ÷‘¶^cð­°¬´U·ÊSïk”«4€¥:Íf]l¸G;$ÝðRý¥Ovt;¼×É»á’{&mÑU¤Ö"OLYSðØ³ž&hçÆÇüVÅ¥r4Yx]7¯­H ,)„ç ï—�=£ooÖ}ðZ…ûûz–¾²bPñÀâé¶HÞe)ùlª„{+´¥ž�ys¤ rje~µ¤Zð²K%Ýõ½‘ñb#!L&ÀÌ�¢3ÓâŸÉóAcqûIÏ>qç¿É-2ÂhßuB²àf¡)}>mµW>°] ¾û¤øxýy¯�iúÙ‘~¸(ÒãñŒªÅ ¬y¹aï 7ÿ<€awöë ö Måh‚f†Š÷ýqm®–µí¼ ÓµdsüfC>æ˜Ãgª³å æE‘&ú�D]HMmo ŸÄè#ë­|êŸdVŸO*Þ÷½rlýfK“çv«EÐÞòg<¼Ë1´¤Å‡��å =£ÅÉ™À¼Ë‡×I½%k6@±ï2…WuÜ¢~†¾«¦Gœ½UG\°po6gÈh´Î„ìå8õ ,´…$VçÀñû+/¦0nM¿íî‡$Ú{žEÐÛaxfPPwqJp´}JÁp‹z¶ÿ€ÐŽDüùO‹É–Ñ*@IÆ å±)> Å<àH‡á~ä´óf�pßòÒ•C!%|·ÑQIm`žsˆ°Ê{öaÌÒŒòÎ>¢ªˆáŒžó"h}¹6áòÚÑv¡~4k«¯°l×\¢Z6¬9ÙŽ”8V*Hçó@סèmÉ4\y?ÑüÉ…BF#°VÅ_ë2’A´ˆÇ%ã#Ђ�^@�ã %À’`¯eéÐÝ_ë­ú¾�{Ѩsêx²‰”Ë#$.%TW¹‹ö@Ž?YЄwÔ‰<-µÎ‡"JûŽ@ÅšéSFÁ9#K~صø†øgÛ =$ulšµ4m7BMOíP�ÐFx'©üžcHN ÏGu*O8–Æ0 {„A™Î�¹ÑÀöýžOÕÆKܾÀz|ñùµ5·PÔÜÏ ó tÝÁ§6�”šMþaDGÇŒDÅxZ•0•Ì�ø£µAÔzk@PÜ.Þ]Âó›þ§FÞ¼D±apþ¶Ÿö˜€ðf0þ]##ç­$!ëÃR׫@Õ/“îáj¸bi¬Hµm²Tú µ†“r¢–�¨. Þz<8Ã\Ž´9‘X¸·ö§)A¨Ð�U½Ä~j¶pTÑÌAò–pvùÐD ;‘½g‹!.yDk V†½òc¹CßžÀç†[y"×îR€$ŸÜù>þ!2N)¼­¦æƒW³¡o$¸x14ƒ©5…ŸÐ¨û†þ}`�õ:ï¢�è} âöËEûŽ÷´?±-JU°ƒSšö9q/IÍòJUn�À^E›Éᛪ¸Éæ³ ÕPТq)ÃËnž›–�, ‘�tá˜ëÛ¸½‹=’LŸ­%,NO‘¹ºˆê�{šVêM?zÞüaf­‡º"宜L%BtÐ&1È»Mâ/Õ/ë‚ Ç�6)Â_ÞòjEV Vî™øÂ/‚ºVQÀa­);™¨¤7fÆ·Ù�“èîŒ^_uõxÌæ=.̽7êQ× â6Í;uH_{.²÷¦ýäë½ŽÄæ)uã‰áï¹Z¹§±ív %>Û(¼¨;øMó*,�ÄDбSüÅ€º“ë+ødDžYàšû÷#ñ'ZGÍ:UAº—5[:§wTìOgÌ\á€'Aº=ô@ßíi�«Ã•V_vå‡Ã›ø¹aLÎÀÍÔ9ªF=Œ÷Rnˆ½ òhÅŽ:¦k6�R3/ G° FQï+ŠOâÉØº' SU­V´¨“:DÕ½_}�…‘æNÃ6  ”q­²Æ³íÔe*úÇHørž€ºI’YÅiÉÁíÕu’¼b5û#‚”‹ª,×<9¼©¬¤†[ô4>ê9Å©dñÌãC–8«øµMøtŸ÷TFi“ò/•B¹}[°Á·Õf ðÝwÕ¼BØé´®ê‰ú9»Ø&+­œôŸÚ”¶�™ã÷J7Èf{'<öeR#Ù�±¬¡Y‹‹]t°ÂÆb,Ôƒ–¨k‘ÌÝF�¥íXºX�‹ÃróZÃç"z+"±û. õ70DsàYµððoF;‡_Ñ 2²l5ÂÉù'€ûƒ61†ú/8 ™âq’ãêÚO†,éë'å3†�‘¡¥.2£TSøTñœi÷¿Ðÿp˜p=;NàñP‹N%ð¯Û¤µ]»!‡jñ­×![Ô–ù±`Xnžâ-m�æ~¾ð8µ¨¤NÓ6ªB1õÍS/r:ŸE¢9LÞÑÅÚ|˜=¡uOáD$ð¯ÕеV´f…¿Nœqû•ªí±S=7—HO�»D}ØûSUÙWx˜æ�à~í ÌŽ˜Jýè³Já¹ã_*2 &àÏ�ͶGTÓ�¨ªÑÐ'ý ±ŸÇ“² e>@v2®Ì™ú‡d'¥˜^S"|åO¬¹üw9”ÚŠÿ "R�abûÏópá¦èÔ±T{2�@DE¾ØcÀ_¥�Ö䃹¾Ç »Þ(¬'5•œFôN|þ^›ßNnÕƒõ;P”fÎÀ©©kzfÆXqí�Ü(Eh…»aó9šú5š?TyÍ*øšÕ?I¬þ|ÚùÝ[Õ’¶±,Çp¯kÙÉ/õ€’²äZ¦n`?ÈωU­Çiþ׌ßö?j¤Û�_<øÌ€ð­¬½jKë¢R£…kùR­LTeGÙêºÈ“ëÑ�‚ëô(EDÇj‰%c‘ ´åXÙppÖ©n%àêîPý/ªn ÑM Az.àŠXÀó!.¤*•™âk‚¶rv _n?û™¼£«QIZœ’œtŠN­w©ß I¬04“~2–¬@kzHôÈ3Ë«PT››ÖñöœÜ)CøájùJQFS­xw«²Û ',w ´í¬Lõ¢Î–Ê¡£8v„ûõÛuÔøšpþŸ…Éè H¼<³ˆ¼”’[—ØWîÃÉÎ¥%“¼…�þìËáŠcûÅ”›†PBƒw.�" éi¹æÇjÉy)-žî 𰃲=Êùk²–yúÕöÕ‘˜ƒ(ÑÆ�Ôf—ækýÀàሃQ¶£ÌÚAÍCw™²¡g”hBaР–­ˆ‡ývälÕƒüÿlUo¨ÔzXe¹½Ç!b‚ ƃåðÛ‘Y;â>ZÛ™Û±(„ñê�¬²`J.W¸NeRg8I¯®p/Ãcâ°œö^©ñIÏ�ÛÇWnqÂ`}&°œ1M…”îŠ2›ê½ür)÷3v¹¼×L+PMz€"?y;¦jR ¼nq'P Æ$Û–>KDÑ ½®l†�P†÷ ’•ö^5cÀ×Fj"BaÈqž­ .A ÝM Æê‹¨ÅWýx¼«‹ Rfžù,’ì…‚µíoÔY8Õ §";žãµ·hÅ“ªàIy“"íæmŒæFÀ†Ú@ Ø…4=šê!B�ÒŠª»+3‡aÙ¨<�€BY^§ØaÕI0³Eä�£³W õGëûÙ€À�R+ÔeÍÏ._1È î”™"(³3€ý@¢�Êc/m“ÞÚG_ëáfÄÃT·w–LnÁÊ÷žq ±ž*ÇAs¹KðL>ûN�ßô®  ØwÂuƧÌé—Ó°&µ.`J*ѵ¬HÇÜ„ºZ ¬ÌSjåÔ W2§Pw˜«÷ÒU)ZØ^ D{ *Þ3#“1°L¦Xw_š-±|iòîù3<õšT ¿ _Â;Ú!è�”GÌæ#­¹>Ö³1;Fñ¾E‚X8¼a¬bÇò¹7ò ¹R½ )h ÷<Ç~*bŽS£LËà pÖÏ�z=ÙD1Ñ\÷Ü&°ÆØM(j©öK•ùzâC:A‘\1 ù Ûôæ8ã/¿ÆlÁ{°U�®Ã éB0’¸Õ¿5$€6ˆQ7êrÎ>ïúã�47–"ûëŒêa¥ßd~m1¸˜Æ—N§$£Óß�n^Ú0Ìêno¡ó˹­Èd­@:lêœÛ"FWÔïù'à€>a3Ô‹hQÁs¥èNU Fðà¶fµÌçkÓDçÆÕÛáOé—¶”„æÅ&A„EñäUàÆ‹X?½kf¤Ëwðiig«Ï+'“7ú«ÙWÿrsópÎ"¸ÛÆv�KŠ•×od 8-Žå!оY9jHʼn‹@)Kôƒã¡?>¶~Æ“ˆâ¡ÃG²óÝÉ8Ê>Ú9qþ×߇Q¦0à|o‰ƒ!ANXÄ“afœB|€œpeÊ›g±‰:V{ÜdÓËwˆ»„Èu™šS¶�yf·®P�«Ïåä4 BYµÕòùb—=˜ÛŸ/OØ*Ì�¿`_²Ûç[ñ‹Rñt¶¿†±J˜¶8 P±�“Í8»Œ{�¾�bPD£Lšú¹¡_NQ¨HÐ@Ç«\¡|—ÒåtްS¤ =1jŸYVoÞ±¨f/â¤Þ<˜¶ÖÎ^®X¡‰•€gE²N4%:+c²@Ç߈ç?(pC¤æ²ü2zŽdj¼§æI~>/½Ã3ÿH`r+¼;¯ Ö¹¿Õ×+¢È}jÙ&¤=öd}’0lK×-Uhê÷/!Ì¡$�ŠLüX¼õbgiÀá'ûô³A8)ƒ`MtEåjÕtnÞü=×›LTÖó0£³1tý6¨¯ÈÀëûqô2°…O¼¨i}ì¶à` <À@¹¿4k¨:\b0jZ†|§å&rnò+cp婜eNüõ±L )ºôÀ@®°AþfÊlïƈ,Ý*‚¾QZ�¸�)qÇËñÕ<f!a�~P8¥žÍ¬¸9*àâÇÂî@)ÇÑÇ%� –…0á(>™ ¼¥ÎÔî—H ð´kšÉk_¨]C¶û:–Z‡�TÓ ì-ì¨Þ–rÃ/ÂOønÓ×ÜàL ãŸÈìy¸ŒQ´¦y5w¬0’ð±\@6ö–²vLIñpeÊűъßõš„5Ö®»ÈŠÐ[+ ?ŽAýp/"¥z¬ºÞXÿ®T¶¬E—Êë-yƒ« éÈ~^÷jc–Œek A=Ï;’_µ»í²Q¾š§v)>ØSÓ]› ìD‚�C~²ïÖèTꌺÉßç¨ù+%hV•,?“õ«6u¦¡‹_¿Ðeo,?YŠ|xîøü®ë|a«‡8Ã÷C(d„‘À«øˆÏ ÉAze/> £ÐÄBŽsocν~!^ßã‚7*Ïžù¢¿rý‰;¼…¸¢œªï†#„ïT}ÅóYþ–3mt‚†ýx=!rÃÝ¢L‹„y.Õ@l›¡'�X9n7ábnï<Þ÷"go´-&ò²x¢Ýò*ù«ÿaäRÒÚ7÷5ŠG"d$äîÚÝ©*±:«z3T=cRàœ¶�;æØ ônTוõ)2 ž%�Ÿ-6K¯«®O±I"§-˜^ðêÆî<’I’·ÕScEwzÆ^g•@±‘#_Cõ$Öq÷sÁ·ðžå $�ÛXû A¯ûýhû´$¼†+W.î.™!Réz%W”답É-~Ì8¸É¬0Î ÷®•mtl@ʺÃOùŠ ¼åMTUÜ’°ˆõæì+�I#¤<);ÛÔbíxÌ$¢—,8^G¤›Êsâ­ìT5?µYçÒ #Uƨùðcƒg”Ë©ÑÔ0M‰ÛHÞ¦ò‘<é=®‰TÃàêDCÐ8­“³ãÌKE ˆí°–@'5f ]VêåÓ)5Ë. Y3%ƒO~ð'¤Ø+BOÀüdM€ãOtÇ�µ¿Ä®=PÏ!°y04~ž bÌ‘“°(ƒ8Gò6»0AÕÍ%ß8ÑjûKbt}þP,W¹ºP¯|he»¹«†­¹ýöUCbU†´föL»Í¬Hßéè˜ÿâªÛWí�9žð¢ò)ž‰:m‹ó2s¤às‹dÐ`›~ªÖx²Ÿ  AW†~äVÓÇ aþÇ$혥£ß.ãh¹šµ“œË¤jñÄa½5aer°‰JH�ç€OæfßÌœ¨äÊ9,¨ñùeé'ÚúõœPN–0O ü=`˜•n3i™H‘ÚÞÿW� 5ÞaÞ,ûç#6à“°3G·Lp…z᪈qV’áC£ÅUÏ¢’ÒcjœTw Jn.Í–,#ÌpzûJ­Þ§±³n›Ã×t/ÕP†ÇÄø`''ü½jƒkPX¤…K÷Z¦,ð|æ/^1€Èç§Ì(ÒréRŽm­îá²’; –pq‡ì½ÖÏû{&-Ù¶§a~B‚´Î¯4ÚôP�«ŽÓ°Eî@ì±vü_…Qb ­`ŒñzÖ`‰$\jZ8\ Þ€±Ó†S¸´i½¸bÕñßPõ©ÀUÍBh¡€háD.¦NÈL‡ö,�Çþ-Y¦ÍÍ™8Ç!v}ÜDô„ Xøîª|+¼ºë�`Hùž`®ƒóà ï‹-,Yó4›¦óÞúÙ3!É530]gäOÄ¿Õ|õ3µNAž›€1Q¯LMàJò2—É£²½£0sO(¼Õ äÁ2Bñv&%Þ"†¯�~-V²ÐéGœ?� µø(†�×úÇ KÀÕ�îèY´öƒé ñ•4h8Œ9"þ`7ÅŽ…äBž·�§™5¿; »è0€‹û,-Rt�œÝ(ÿ#iEFÿzð|ì'’,·Šw�­f·�¿òCªÖÿº•)¨‘¾›Žç#ânöPÀúG0ù¼== žuÛvx„)Ì>¨– ±'±ñîÕZ-½ë,ØGþ̵:ÀŸ%á€qˆ©¬aÀqR’9s‘H�QدNþÐ�V}^®àè¦v.<’*‰eoxÒ¦1fü *Õuu£4-õž&ÈÔä+}°L¸bÖ'×0FBÅôâgBº­�PÎ-q3\FU%Äï/zïkîuX· åj8¨î½’*…@jø x0JÞ²¾Vžø?ŽÜyÏÙ½þÍI%ÃÓÐ1÷ž#$8ܳWÆDýk)š3§öU/~—Š£„ñ†ðÒŸÝÿK0…ù$wMU_ǘ77 GÓ/«Î1“ï¥SB"9ÏÅ©@©P/ŒAE—[-%PÜiÀD¥4#_sÏ6Õ‘O¨¡Šz¦Î‡Š:ÈÅdRz%v €†»x÷…Oô €àya-%íæÙ»Áò'SA0ŒËÝ”àÙîÕÜ oLÙ ˜ýR‰¤v–³ü%"­âèZ08>f&äx–ãöÐkçÕ·òc[Œ ÎLŽP0* RF qbá9Šo´lÅ¡,%Üð)ñ´±TÖ\!T<�ÎßJ_ÒN³$‹€Fî`+Õ6ÍÊózÆÛËeÆKŸ³ÿõDuλ­neOÜ Jú’FÙÕo:ê†T™ª mQÏ㸺DÕyÓ ¿sö×Æã® ¥™ç>–ˆãü~rLSn<—YÕÊËȳFz-mïÆ„ÀI�’et3‡.øB”æ¶�ãÕÂÁÞòÞ(‡'L‘Ò2ãàÁQûöb;ïå œf˜ñæÁ Ûì9MtqowÙ#��¦íP«:~(> š¢‘1£°'¢ÅÚ�Ç hJÓ°É ä¤@�ڪȣ|¤¼Ü-§5 v�ZOkÙ³Eï•MµwÄøKÛâB½œ`\‚E<> Ž‚–ø�H$­._ø<ݦŒZɨ:ÊýLq�Êwa^Q–ÐË�zå�ÒD%�%A¡¼ ´ârûó2èw¶âÈDLcƒG)ÓžÙ’hŒXsD“�²8�h%©”ìݯòIë 88Eªº8-ÄØëŒÔYDø»�§»ë!�·<Ž]3cÿ»MHäY¶iåÜ1yW‚ò÷©ðœ¬ðâDæ×Ï–<$Àg)ö‚¸0v°÷°wY“áºì"�K¡ýËÄÒ.a=²“HñÓ²�TRŒpº+‡àßBČdž=e³t¬#–Ð ž»¤JIìg BdÈ4dÓWb*ŽT_—@¼‚‘±Š#ØNvˆÒÖ†ãìjeHU 8êçÜhë¸HÄÑ_©›]R]SÒ’d*C(Þq; ïoÍe0,Ùa™ûV9~.ÎÛ«5¥O,¨‡˜j[�³z‡Ç¿êsÍúŽh-œ23œ0ºR7!Ø¿cbŸó…s(ÃÜÕõ0³‘•{±LïéexR#ñÙŒy"©vÛšù¿NÁé” ~çBÄí­1&‹¤™7ÿúEgsd›€fânÕOƒž¥]âoéCÉlÌÿÛvždŸ6­àìö=¨Û¦ZÀú?[¾·wîR/\À¯ãj² ÂW|��ý%~NièT ŽÇ•"dsó¼l]½÷ìÞ .yÓÔ¨Z+÷GÕÞ7»šº¹¬Ýõ<¦Ä:E£`Aî>¤Ñ!Ôž]H®.!oèSr_Ó¤S+"ï8 ­ä%Ÿ¼kÌWu '¾‘Ÿ¯¸Pç÷WFœúP~ÁtáªY j�'ï„/‘fM�¯Ì¢yË¿ÅT”ÌeL›+a6þÇ~ƒ þa#21ßráß«rnÅ+§×$܉P‡j‘Ù婷~ нt�î=ròtãø�•ÝGªœ0EÒź°¥OÝ®q3o¾âT �àçr Ðï5r/&5T?Þo~ÁpÖ7×â8B19á8??ñG'p·Ì[ñ`kâ4Ó¯ï9 ` µUÉðÁ€9Î6bІ�ŠÊVÿ=¸®tÕ!ʬ‚•Q¿¿JÉüÓY(Ûê,øSñGüuÖâO²‚ñ6xT¨Ë0Y9f+¦èq!H%\Ì›…,�7(/•ÌFc°Ð‘”žùn��ñÈMµ5åWº;¿¸Ñ=û9Ç ”. ›:ížÙQ€T‚×™ ÒœLf@Ö¬eMFMbWÊÓKÚŠôø¹Ð·Äu�›ÊP.ãšÅµAzBâÀ¿3ïÈ�.£¹E¡}GL¾<BV“ùNgª…^_�Þ#D¯°�ª1ÈCõûœYPcb‡zöÐ&hÊž–¿d€EX­ÿ;‡· Šgæj'°üË9swW½ÜŒÇÓÓãgºóìg¢tHLø�2’a�‚7åÕ/5ÜHâ›óßR›`H¦úÆÇ�²í.€ö[™ó�:›¢ÇÂÐÖ«œZ_—âë¯À³¸Ú+¦ºìŸ­zKMç/N;¯Û?í—œ7åeÂÄF“V|>µî…çAAâ@ÅáÙuÜ{Ô�'£KDEÃÏt¾Ïd/øÜ¼ùù�èìÀ¤*ƒeÖß|‹€ôûYòL¼w®=ÂÁ,rt$Œ[$¨oâ²SžÂ.ÿÖ c­PlSŠ´Œ úHz›_ɸ²•Ú¿ Çñ÷¯Ó²`¾Îˆß½¬çã›ã:õ¤ã¬Ý)„’ïù). äm6ÕŠ˜sfÝc~=ú– –¹g†R·¾4¼/ù( km@wd]çVxÌö‹#pSÁâeËm|ýoN«ç@Ç È|¥¯ß.‘�æ `Óîcä?«FKèÇj‡Ë'Ž3ü£àŸcÛöBV�°°ýI(WŽ8¾3ÊSìr9N™öŠYìö5HEË {Á_l¬K7 1¿!¦Í~»ˆð7k›‹0fXÁ3§øŽèwç® q£`©söÃu�ÊZœñùž;_Ô ³VÑ:î±' Á�µÜz~}¼ì­Z[.È壘êj­Ük9¾L–àOÄ äØ>{`•ÃEoâµûP6Qyòæë¨°ÌayÙã¡ÛÑ©+NdÓ±š¬‚|©‘ž�+¿È‹Ê6C?3Ü[±ås¤th»ýxQ|ÏÙ�‰&j^i•Eª”sÆ’ >Ÿb$ˆ�Ç“N*»¼^…r†yçqmZ ü…ðæbKŽùL!l®ðöi"l­£M¯©¨pê>93øe|ô#MÙ~˜9…êñ¾uú¤7«×­|A^ëc×8ô=Y=!²VÝ=º*   ×ãÈá2šG^A³“[H],vVÞ±Žº¢%5aWùz kFS0o7|@Ù´Â¥À€N>0¥äN†ê?O÷ £ †TO)ÀÍÕ.è��¸kSaר <ý‚!ÙI�Ê*ÅH8M�¾>È"v²ãBÊ%sMh%«âà¢TÄüaR±™Q‹¿AÒ/»`q6^m0*ÛùÕßW�ñ©¥Ø(févtH»g ‰ëZÑò.‹:̹ª+°$+æq�³¨š°«3))ëºÍZãd½,7[8“ךcÜJSa 2½üÏQRðLÏþ/´ ¤$ßæi ðnŠiÕôdcg8Ø)ÉÜ;¨–àOø\HJ?åI ¨ÎFH<¥wrò´�ÉÝQIDéhßC¡¬|Ç9;-8úc²“�´¨;êvjš m&Bx)îpSÛ×�1" jä\Pìr7Ø¢ÉÉO²[.é …K¬¥›þÊ�¾î§áß<çƒ8LJÌò7&£ó/ÿc‹¾–:Ç?Å;�`‚z§3‡X©J&ëv'Ü*èz8ßóÑ }<®û-¢Œõ¶w©ÓCòè1eIÛúãĉ!/'ëÚ_…)˜>4¹ ¦ËÓëW±hn"Z¢ØwÂгÏ_Ìr&ÄMJö¹õõ/…>ìÈ�W˜?H,†…µ…‰íµþ®ñ ö I¶ V×w–ô:^ÈSÝ‹ª³„´²Œ5›SÓÛ W‡,[¢Õh3¢J½þ—­�rÁ$‚&_ûð«¬uÅx®RVv�æXc-¬Ì%âø²«`6Ššz2¦*¼a§)Öê’ù­Gž.w²" üÞ²w²ÀŽA÷HïšèA÷sE+â·é{ð6¢™x§±^§y­ÏxwÛôw"„|hH•×?¤>ó ¥þmèBûÐÚG×ã†]= rІf�ŠÕb¯Dñ™a6Ÿ“Ñ‹bßéƒzŽéŠ|ÞŰúV^ç7ý¢É«\ïé!”0ή©îÑ„Õì‰n £È$“dÞðªû³€Ñ>ã¢~\£ÿŸ2À»î bqã?²¹0gqƒ\�¤7£ÀÂ\¶9P¶.93f;³Åâ*·<äŸÙ‹”ï¡~Âa�þÒ׫„Â'òõ…ÌL«š>ÚXðüV¯ŠøA&7Û^ Ç ÉšŒr>‡�Æt™'‡©GÆó 8\ÞíîsÊ zb2¿Ê@ëc-†&”dšÖþ”õÀÜ‹L-ÑÀ±ãY5jáj¼6…£!ÍÔP¦â3sÚV_×µŠªÖrÚé{Cîõh¹Í¹ÛØ�ÙQk·^8Å«�“9Ϋ,ò†e�­1Êt¤Õݘ½Ù �„Dnî;sÔWjÌ—‘+4É€<+G¾ˆˆHäÙå‚p³¤¡�Âo»rŽÀ¤Ô†õ½†:z`¬ˆìŠÑ±Æ7δèæžó]q ÑV¶Ä0Ì¿)s�ŽA,ûGÐýTx±j:ØrxvîÃXÿJ§áÈ[ „´Ã¾–žÛk%‰øñiäÍ®iÚ@è×9í1®VåäRC½V;�Pf�Ž}2ß!»á@‡…¹ôlµb‡k2šîÿŒƄ?Mš»æ7¹âGwÄ ò‚\€w¯È9˜.\¡Á˜ՔàÛÈ{ÕTÀŠõü” QÇY¦êéñέØÔD&Ÿê¶÷/¼ÑG ›¹ ûH'ؾ€g@¥«‚{Yhö`íb­;Žö" ¬›:í3ˆå “omAP�Év*Hm§=Ö€‰-žO}Li#åèd?~ÑJî«)’ ¥,¤ÉV�ï"BÆtø‡œ„“5þòP#à?8×ãêÞAãBv³8'¥:­-8@D“dÛC~o!É‘½_fATx—<Ç‹ä¤^p\s¢m¥ôƶã;@=Åw*cqÏ*Þ8S{¨\7±ðŒ5ñô0t[zïk ¾–S¶º‰i× ¢ŸtŒÏGeåá¡}T¿‹ ƬzÛ+É6 èQÌÔ雯’aÇy&Õ QïÕ/j½âàÑç8 ”ŽÞ®éH]óàçyü�`xÙµ-Ðsϸ|ZnÎÁâ:¾2ªÌÈ–œº:’…ÌÆKì¬�“º�PCÝ�¶þê9¬`Ù‹°N#^…¼Rñë°ˆNGGÜnáM¨�‚ÚØ>ú$?ܶyF,šTnª6Ð0›XžJeO ^À|U€ã°+d­Ã<îCTÏÓ~Ü =Ô¬X –b@¹˜Î§ÞœÆ+u|][H¬ëvmRº”û˜¦€ï™ã0¢Ž¥´°ócìJÃ]å8ÄÕ¸1‚{Õ!}ÈÆjÍÖÕÌxÌ]sñ'­$¿ÊRsÌ}2s…a'�À¢¿Žd¡J|ÑÙ�Mð$8,±é´ØSЮçFâÂV…jŒ4*§ú.¬ŒzUߟã�A_Ña_«ï î½šécÏ 3\íŒ>‹áŠF†oY‰³™Y­¨¯À ÖùË#F<Ìî«hDŠ‹Ã¹©2}íèt-Klÿ«ó2~yÕ»9Íð½hû«Ñ3³‹SÓ7­Yé kv·Ò_âµ»;<ÆÂw£¼hOsFÏO©ûý¸^–G\³e×@ÔÂG¯ r° ðz\óJª¯¢ª~g4ÂÿjþŸ¾÷‰aäÊÒ*Iq-y !}ó)™-}9¤šˆO÷Ùü'Sù ?„·ysú Å¬Ê6AƒÀ¡>¶çä5?7‰< EkÛ5‚PySl)~ˆaI_Úò_*10 ´˜.2üÈâ’—˜.ò�ˆ³8uƒýTòkºh£È¯ð˜4ÄWš�Þó¼)ëÄ3]‡· âÿñ‰Â0ï´ß+î"lé9(ì#�ŸiÊp–¯Ô�\¶5†e üŽ>pÇO¬ê›CmÄÑÿßKOUº°|®*û.­¶Ù�_ê,;/¹JTÄÍîÖ�iýúY¾/ì��\�€Ý}*ܲ̑ÓÖ;?– Ûz–˜:â„°v†¶7·`ôQ&ÒË¿Ñh`[�:nóIΚøüPŽdÅ¿nÈX-Ñg§§È.Á¶è —Uƒ¼ñî¡®:Jà��®�¾'Uxÿ¼~>z¡wÝïždZÃ’¡>¯"9Ã;SÀ:ì–^šºîÖÊrÍŸˆÐ¯¼ðUÓUJR‚¡£(b…e6%¨¢¹�2£¨p‰fÄ;äÖ ,#w·Fº *g’Q\q…¸ ¯³ì,€¶hwP<«Ö)–²å²œI9³»4Ws}±‰K»fúYUê_†Ú4s/Ë÷•g™²E/egƵ$ :`O |q,Æ&ßõ.ÑíUvlrÝl¿„•„�$çÝM{öí3+&F—ÁÚt�@±u3 UY“‰�3AÿÀÁZ/eÊdå‚¶á^�l C½ûÛ"ܧãÇÖuúuE³óùÕ©JûÁ; ©Tó—¤èå”7dÛ¬ÅWODìøí·Î:§8:¦+i%\-9Ó4”Þl o⎆IÚeí Ñ÷}y‚-�1& í¬´Iȸ¥—÷qÑIŠJ)9“Œãb×ôøóÛÒi•< ­Z%Ž?•|Ï›3í+Ÿ°ÖèA¥ëUíTMa%Ú-@ØÆ1MgÂFI{�Þá—Ž 3ÀÖbûÉJ“<Ûn ZØø‰ªMmh+9À¨ÂÅ€ÔÃ`Ö\%Û  ÍïA$+›Èp=šÈ? 4&½oÀÅêTì«×Ðç ÔøÁÍ‹îÛSŽ6à'§ýšÁé��»#É“µu@Q‰f˜ú¾Î¶à––âIºá.Ù¦õaîe]‚q‚$÷ʶ„¬¦8?ç–œ¾Œɉ²Ï6ù6¨Z+'ÊØ 7Ó¿;W K'!¹¶—7€ Áiò_î¥óY“°YèÓ¿ãM%Jz‰¿W„Ug,µ†oCC“<2�¸„ó´TÎhhñød_>²Ú›£FÓçX�¿2^*uô:à �)ÿO'sð‚ù΄JäÒ² (Ó(o™½wƒÑ׉å‡�È(¼Ü‹Ð¿ÿaÚázÚº­êF9й�†a݉˜o†Uw/`æUç~Øñcè,TX“|dJ@4[X¶œ¢�C5Œ œ5ÆÆ’ ×~qKä©×ˆ‘ë´ä±#£š7Óp.7žÆq[¢ »ï?�ðN‘ßnîøñXáP’R¨€¸Çf<ÞËçÆ/[Œ�4ö®y®}E0RƳ ôàÔµ‡&´áÔ%[;zºã/‘ À�¢Å‚P­ø%ºyû q´5ÑѲ ¬¢0��ï çÌW£À¤riŽ“WL¾åîÙÀW�_I6PÑ|�tA Ãr&Š1Wumžöo$�‘ ØA©[§¶|ãJ%I%£µ ý®lÒ|*Œ4ã*}ûJeR}¬xbâ+˜Ÿ”Áþg Š«bôQZå¾,qÔ)æi[`jNhñk.þË@ãç�oÖˆ@Þ÷ßsó±žL_W}(P  ué0ãüë%/AŽÍ͹¿Å‡@ÿÙ³£}bVÀIË$�'÷TŸžX!þOx((cë€`ìî‹—è5÷$xˆž÷ï7"“Ù0sÂa*ó‡ô$ÛUæü‘ñÓO= 7HAìŸ[qò–�ÉúÓ¦»  8^èovÞ­åí©1ƒPù;D& áHÔ²ë:Ä37ð„•Ò·NÍ�ÉöÒ=¹O`øÒ jЦ#ô&oòñ†OQù%ê-¬]ßþ�„¡‚Í_�>BžØü!�hÖ_†ºzÎÀ cü\ãöŠäË6[Ç]�²ºÀ‘%ˆä¹Éšv… ֎ʊ#âz™dH³»ú9ý,ÅÔ8Œ€àÑO¿¼?bâí÷ë2+ïƒ7JìYqA5Ý�H,ˆíŸè°k0K<ljîóº-JZm|oxéz"6šª™¹öSpšàGA8 &Ëàò8<« oH"ó$$­_º¿;­×Ðz�šVÑÚkÖÙu·ùý åvQÉ[×giºÙˆ™nÅX  úDV"~O°±ºÓ2tÉ�8ŠÔ‰¡¹… ÈdpG¬~޹A¿‰#¸ÀjôíÜ„t©ˆå¸C+þ•§¦})¯B)Š™ËÍôàlÜ2ØLúB Û$qȇ§{ã®çË?²Ð^�mí&½šK²È‚Áw“[ŽBÉJO ä‹[E‘§×õ×`Å`�L·Qª^ÊWç„e„6a è9`0 - ƒ3Ô:\E‡N(C+Y8Ñ87ʯ�06¼Iõ}n’õ|!í§àêexv�Ýñâ.q½%Ä£J @ ÿ>LñÍKŸ2[ª,nVÆ%/"³ÖïÀâN“{Í›¶^ ä7Ä ¾‰íuË+𤿄Ëчð®‘öÊv¾X!Ï5›9´þcÍÝ”(ôKœµ4ÐÊ@92³wKkÖ6æ”yÛ+ºÕ±zp„8/(!ô‘½{ól¥aUÁ™mäÅ«%r1¯{ÒsL�z�ÊÝÌqdtd1söÚí=N`øëò”K©y÷HïZ3%’õ ³;})¡úVrš5 ÕÒpˆQoµÐ!w\j üÛ‹(ÓÚn_|˜ä’b­_h6>Âñ§¿1·7ûúàçìÒ@S¤-/ùõÈÿb¥‡Ÿ¡lÁ¼hÈWÅ‚Àª:yG�äëʳë5Ƚ�zI�›� Û€wÓ�j±.#í4©"¢Œ/žYã×Ñ£›s!­ÐÒW{ÑO©^µ�±{Z÷èrw!.$Ìê‰~‚¯}“Õo÷Ý"lC8šNÕÄ ˆ‚0ŒŒŽ˜>mEL°üŸûmS‹öm§‘vŸ`ò—þóa9ãûº�.Ræ´s) K7¼'S öI~ícô}‡5¤É÷!'æ_lª°Ÿw˜†)ˆqëxÎ*§Œ7o‹a,\ ùR ›ˆ°¯ZÇ�þM„´ê(4L‰ÎÙµg2©~h þƒùAdl$–.9s;²û¡“òƒ2uD`‰Ù/7BH³ ÷ã“­¶Æ%0 &þt€Íë�7‘Ön¶yK`-å‹®ô�xøA(/ŽÑ-arF.c´¾V>ߌ4XÑKÁ¤6Ë ÜÚ$+°îsêTS/“n$«$]ú�ß—&`ÎeÿCÄœ‡¡3¦à[4)@kF’ö‰”]D˜ÁR½Ž÷¡î¬ÉØÖ£tÒ=ù˜ÓÂÄιuT1DቱB •Ü1_èÃ+K›Â”X»;<'ó<’!‡Þ×3þ öÜŸÍ1#e®Eôä#‚k(„â#ʉ³Œg0�Ú‰S3"‡Ý€#3P5 ¨«yj‘?KË7!C3冓:XíPHþµr<ïNÏÓNËØÃn{Dc™tƒüŸ=7´Z€pÒƒ fù²�_úVÐ ‹#z`WMàbÂy$½#Gü_X¹j\¢SBVš.~Z “—¦iwö�UÍÙŸEy´4Û÷0ˆ !au™ò±ÇŠ‚õÓ!uðÚ-ù,J¢S§NFoÂj ä9)‡¶n ¢`’Ï]n²·›°-įää‰K}C•/xåüç6˸!�LЇ½?º (O�.i…º|-›´ž™/F<½Å…2q^û ×%†ˆªrÞ§‹qSüìt¢É*»§…sòøóý–8€³èû\$­ÈxEdüVdË h8‰.Gáp|4Ö \4‘Íç)9!Ï™#? @]h£�¾~ô?×&qÃ;([æ¢-“SJbãŠäùp•†›µ& TEä‚êX¶ƒõRscÌÞ²ògø�ìV‹¸˜Ê0Zt™€J`2¯ûÒ¹WžëéqSPTÈ@²lèš ý—Ò8@S¨·�®)¬¸»ãÔ(€y¢UGòj ­ÖÚ�]}V‡~â.ÿ5pU빓Ö?Ô_ñ ­r¸ª�§>…èËN…pU¸ë+,,Is“¯¦ÿ( %÷Þ{h?süu³þ t"Ð…(é°Sâb´gHS¦¯È½þ|F-÷U†ŸÕS¼EVQ�Ö1�ài/éL³5�¸è2¤yõmY^ ³€-hËð´Îôkº” �ÆÐwàö¨Ë÷Ù òB’Ïñ�áÖ…¶÷\Œ¸G[²^àhÊzÖçjú’�t³¦®ˆ& ¾n”Ó •“Ù¾ %’Æ([×Äs86H�ê+SÆpË�cÑg°r%â¡N©­úsgÎÖºqu&òÝçTæò¼†U&7¹C�/”sr„¨­¾,øþ0…C©l&h&˜sŸä­)¶ëèW_Åy hמleƒ¶NXòê ï'‚òÎyàæHo|‡ +o’O†à�ÙáÇ~…ÃÀo‰„�Âqb‚áéT'^_µ4�}G9EÙ&Àµ²1Åä²tnüwHvŽ·Ü:øÛ?£e¸;1B‚}òuJsU‡üã'¢2z ãÄÍ�]ºXñü­ûRòG`°�m¢«àl1ÍïØe–CvLRýâ93úiRï?¾âd³™’9Q6ÝÝ•öG3�ÔQ¶ß¼©Ük2á`í’ZäP;ÜL!�¡CÅLʸíänù<„ši"_$†çN‡ìx@Ò_Mûª3󴧨Hh^¤¹ËrP'€.Ô^Ÿ?=hÅ\)!X•�p5ž"e¯²½bèC†÷éêÿsf¸ Î6b‘Á¤¡•ók‹y³_¡{i:¿Ñ× âZÐevÒüB>ùž˜wޣ߲’Ôø¬KÍIâ•6÷ ß›Ñwí‚�"²“›×¸‡ü! 2¤©½9G§j¿–ù „€/öã<8Sœu;ÊudX¨óã@¡??4…»Ñiw)ÈeCšö�o[‹Ç+4 Ìrj§kF¥<ނͦˆõäÛçÏ©!Ÿv´À ^ËZÞ¥/*öaú\ý†îì‚)ÉÁ¶®”LÞÛV'´¶”ùÀö�×äÝ bÆ·o6Á&B§Ä—÷xZŠ¯Ã¥Lèž-´3 Øä‡ÏAÛ­–J™¦I3Ä­Ï›ÛÐuwóJ)"àλTP„–´h)£†AÆeÏ}¨â*˜�—CrO¯†ÁuÕ µ†º~C†[6Ó.šMÚ¤t¾N:¾Ë·ö*]Ï# Pùreþ§�wyèµZ‹N©ªþ![Ów”ù(/Ãþxuªç@f[Ž)cÍÅúÖXÕO£§v§®Í·8Á89îÝÛŽH™œÒ~ÿwÃtR3‡�¿`¹FM+>¾É÷áÓ²¬!,ôf�~‚íC˜Ì?“ŠÂÝ4Hw˜RÍôÛèÖ?š„V6Nû«bš%�JdmvðEÕ”%Lâw’X8BjÝ$L_ˆÙzô8Õ`Šs_ Ž×CF ¬(N.lȉ0µ^[yÔ¥ê$�Òëmì{èÎÕ” ¢Ÿì+k'ï Á�`¨’ÅäÖoªüð·yjT^æp?Õ]—l3¼”Á.)åcÜ/Š#¯èÛ¸ @£{Žv+s³¿×ç þí¬¿ Oð00àñH¸-Ý!o^ö¸Oö9‚�ù™QUêD3žý—¹¼€ñ�‘=wd¥éÿÓ+#%³Ù¶èÆO—Z«çAÔÒé¤p¹³ªÛ%ö}H”µýͬÞ%7MmôÀsÃuDŽí¢Â÷ý”©ž®®cð›¨F¾UNÆC+|ý`«Ëd�2·…S¬²§$�áàXÉž`LPLì<\‰�û³7DbXoã[Û§A"ì8QTdÚúº»D÷°æ)š0É“Q9sß’+NÑH=ó³ai!3 @Rˆmª(þùãqÀ�™“p@pÃOwý]DK÷É&³C¦"1ò¿,˜¹gÜ'ͤLZ:ñ„]�ÜIûÿK{4S¿Âëoc‚¬Úÿ{Þ™ùDµëÍ~Ø(ÃÜÔÍÖ-ÛºüGj2p‡í¢�5úD®+XÉ�ÔÃ¥‚y9!?W çÌV]YÿåÕ¯ÿ-Á<׫"Å~?ÍPý|›õ)Á¨Ë›ß·?%è*n|!cBÿj)�¶%I… ^£¥4§‹I½@5u‘•?¾š$ûqpVj,eeÐ&Pï�V!Ë™.sdˆØ€ˆODŸ×7àö»ºjbBáJQq=;Ñã|Ž-¥CàÖäÍ!î׊-öÝ•@YŒ*3Òßvãb±sìþPFÿ*žŽàAÆ»Ë~‚B�Í4„]õ7|ý'¯Ú̦F¾÷€‘3“x"¯ë–w›í»þ«­R0w.sÐ\PQü¬ÂŠL ?v™‘¦Ñ9ïíÍyô|®ÃÈ îµ%àUð„€%ê‡XËÂ]‘~^ÊÅBgð¢;©ØÇófxÝíùe–ñïô¦À²Fi¼ ås_ôš1ÇlT«­mž¡íæ–¨¼}ÍÂ9ÿ Ù�"ÌH/µL»ldxºÖÎ|hóÛ »¢šTÒ|Ýa“ãš6ôBÈì® Tºc_åÿ˜8a'ͱÒà)é繟òétRQ±Ÿ/ƒrqg‰x¸zì\1¿!ù�OÙT4ì=9:QÐ&+Jå$¦þ½¨{qŒz—"f¿ û¢½‘±’ä X:¦àÄ9=Ù±|¼Åü8™§2Íq‘A×0 S+]ÿsV�`D‰)«_¢,ŠÐ÷ƒÚ°—IäÅ6H¶uUÜP¶W&{�jFIšíÉ_<ù~Ë5?ó6()A”Ó0Äh°çªìbÄÐEÖ¸ˆX’ ï4·öÕÙJÅOæ= Ç7¯k"ÒÏ›ìsôa†:fŒ ôH‡âKÖ´!ù9¾ÅÀ¦ Vi‚ï|xŠEdjŽ%¶Ê~Š•X¥wž0ƒ)%MË­ÐO¸01?â•«~8†Å²a§Ñ””ÑÄŒ�Jy¨Õâd>� “;€�gO$ȰÆšO}E†@¯ÕJ»�‰e w¿N–¥n¢ok …0|^–KJðqF^[[éWym­�Ôä3®ˆ l)*Ϊ•í`âðâæ,Àþ'm¥°I¼éÃD,j™ý8;6+Ë×Ë�Í_n®ö¬@aIðÁ#¨R¦aÔmýpa9Ì·‹W…ÊnÒjÂ…ë¸á,Kƒ½Cw-R<Ë–³ê1÷(ôý]z#B9„‹ÁIÙ?çå­•Ÿgµ‹ù#,ïB3&Ã/ Íaëz‡Û‰ 7J‡F¥ší!!˜/¥X½N„) hE,¦�R³Ž´øUw²¾ˆ7’6[Õ1qû) å±àH;3ñ¸?�Ã#�áo/NW½{è´™¼Ä<·ä�Gr$�d�¢ÀÍãkªÇ)œÆžÕìzí^JÍÔDf`|VAXrK½Ðˆ¤‹#}�ýÎVbozÿ:¡þ P×ÌQÌîQ§+�ñºUâ¬'ˆ$ÁÕüÊS"˜&Ë—�€Ë©Óñ[ÐÒ¯½Ã‰1ôT¨áškÒÞåFqa ¶–ÓË|¶fE¢²…�•›-!g­â!S½$ë3¬­ÅÛú‚á¥0rœÆNšJ˜€rÍZã<w„gŠ éX4¹áæ›5ÇoÁÝDÅ5UÙ�Wb3Zl+,œPv‚¶>0&Ÿm�@òP1ÿ*ÅÞÞb `3°!‰)R¼·�*Ø�±ÍœH´¡µ´kì~¤)�•�:Ç“…´Ä-•W­ óý‹5x*ÉÙLQ‘í�ð–à­ŠftVsæ„™)Í1rî±ïW3[í€$+»ªi£ ¸)i¼Ê~\«Ì¢± !¿èÊT €Ï´Ïw|cÑðl×ôk {˜}U zíî ==ˆzU`/Xu0š‚Å�”ÿà½#ÙÄe‘Å«”ú‡Î°uÕLØ£;XC¥=Ùp5߉÷$®mÔ¼ä�Ûyìsˆ#v£‹«tŽ­_�mëx‡ü­FAˆbèZD¹éÊ�{ÿ1\Ænº`èJSøÕßË)^6ÛòÈ^ôýÿ›pfEáIä'ðûøÙ!¢,[ÈvI!èpdI ¬[Ëß’_Ýò÷Ïëï‚YQuÓ)mulìe{¤ÇñôG¦)êz¸Q泂ա„²•²åyWsãe‘ã ƒPŠ÷Іn¦K¤Ya” •ˆßõ'O¡4H¼=%öGì�¬@NòˆËNPV?Ù‹ÖhYÄÁ�py�me±5c܇Î"UÙ¤pj2Žîc\õk×*Â"ô?¹=`¢¿Š…‘¾IÑwG>Xø /À šÒQ¶>f’¸:�çQ\¾Lá”™<¸Æ,‰ŒÓ}+LÖ²ÊöTÒºMŒøa¨²>H»¡9¬Áoí6úN”6G.œ±*u&r­™Èœ÷- K=8‹iªû`bþ·ó endstream endobj 23 0 obj 72958 endobj 24 0 obj <> endobj 25 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡G�Ît‘øˆ’®>R4éuw¿¿Ï·õ?Óåø�oÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:�ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·Êãé�sM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§m�ܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ�~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒßè·RŸ~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßá�tF8#�ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;Ñ�ÈDt8. Pi�|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-�AÍÄ�NèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8�eÁM‹³<—“#artË„F{Ç�N‡® tÛáÞ®Lˆv�qè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»�õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G�¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿ�dØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 26 0 obj <> endobj 27 0 obj <> stream xœœ¶ctd]×Ûé¸;©tl۶ѱU±mÛfǶmÛNǶ�ÛÏÇûÞïýuG�Qçì5ל{íyæ©Q$„òJ4F6Æ¢6ÖŽ4 ´ôœY •�“ƒ’¾µ4� �¥‘„£¾%à/À GB"lcèdelí¨ädkk 46R4v°q²74và˜üåÿ;ê_–2ÐÑÒøßêþU�í€6Öœÿ½…�½±¾ãß‚°¾ã_Ž’“5@FßÀÈ`ààd`æd¤0ÒÓ³üw£�='@XßÄÍÈ ®oo4v ¦¦†#²±u³šš9rþç@®¢ø‹‚ŠŠú+ ·ÿFÂÆ@Ské¿ü­:[ÚØþsn.€Ðß²¥%Ð`jéfkæÐ7226úGCUßÒØ ´ÚÚÚ8È…(þUåïÔ 4¿áHbÆÖÆöÏ÷ÄŒµ±75þ§…™�‘�@næèhËIG÷�§&ÿ@´&´ÖÆŽt5ID¬�„l¬þ™Æî²0ÐÞØð¯ntÿîÉYXÛ¸X{ü[Èhmô�ÍÈÉ–NÅhçd,!ü_„¿%¸ÿ­™;Xèé9èÆvcWC3º¶Vv³5þ�៲¾µ‘—‡­�-ÀDßÒÁØ hbü÷çá ïl p´w2öòøÿº‚c` Ʀ@k¸ÿUÿ[66ùϵŒ¾£=РIOû×Ký?Ÿÿ¹Óþ›#kK·ÿm—Õ·2üÛƒÿO‹  �+Àƒ†�� @ÃDÏ`ø›Àë_åþLjÿ6á?ªòúÀÿ’þ%%¬Mlÿtüs˜¿.þ×�tÎÿtù?A§üËÇ´qÿ�Íÿ„S‹ž…þo.ÿ^þmhÿÿŸèþÿKë?ZBÿ(ýoLÿÏ„¢N––ÿa)ùZ øë©@ð�«€lþ_޾ÐÒíß°þOç/ãÿ|GÿQû¿2Jÿ/—tÿ¹™€µ©¥1€†�ñ¿ª@Q «±‘<ÐÑÐì?ø_€Šµ‘±½%ÐÚXÞÆøÏOË_ÃÿT6ZX;8X9þ3¶6ú×9èD¬ mŒ€Ö¦%Ç¿Q×·7úŸÂ?°¡“½ý_Óÿã¹ÿåþ÷ÚøwJccWcC8G¾@ô;CË�œÏ7ù†v2zJµø!­$¯9n”g*Èl¯šñ$è´ÃoÓ|s&'4rw¥k¯éùe…óývĺŒVL›8Ò´[Å]`n|†TÔô/qÿª»FœCòMŠýÕ‘„ÀÉ"\”½ƒ¦8h”–Ì.(•Aî\1æÕœ^+ROéWT<á-çîàFø.Êþ#íRóø?[‡²ì0­óOÖÐKÄcZÒzð|Íד;œ¢Ð‡>Á¸àðICu€ób«»<p:>˜žB'ß…ª¾("˜~Ùý/.�Þ2¸ n-B— ¨¸E=»RRÐx.ˆv†R…UÁF•†BÔ9ªþvËËé)W¸u_Ä7àôG  8–2§²4�µTBSî%Ìͳ¨^~¤þHÉwåy¾o¥€Æ¤rr9 lç£|ÀƒUW%ïCâ!f‘g´™ªõúmÜÏôy°e6‘ü:bÛŸ}}�™ªQeÞ":¥“Fêu”¸€åvrYøà,hJµ‡ÉyO;ºÑßÖ¡³ÆÊÇÊÿx¹R`Mó;Œ�ƒ¢~îb·MÛû¾cp2ù ¬û,ÀmSãÁ×gïþ: A”"?r÷~Ñ×ïæ-:k±‡^8âͺWÏd=’/ðYC)…Z-ƒµÏ•†9 ‹,)ÇÜ@Õ"Ð=[ƒÁ™%çnL ~Ý5¿ø9é~ʱ•/=ýŒpýëa½xbâ ,özL-}£…Ç]äïzÚ�£¤=:…F-‰–wX"Ãk½O‚üérK|ó¨»ë†ãÃÖAzrUza]@g¶Z›ñ +nÐn®*ªÄ袡>ab~Hîé/XÊ®ˆ` ô̧àôCÖÁ<½»Êˆ Ü×Ò8 Ǫ?è’c�ÅWÈ %†™îË„ÛÀ¡e*M|ö)4m5ykÛT÷>àæŽÆ\e °˜¡uœªÝÛ››ÅtP¶Õ-NÄã»S[¬•mžNí–Œ‚”På¨ä •ý–+÷þž½˜n|g~ð�&6b'ÿcœð=$®¤ßÖ  œöÜÊÆºÁ"àåK×£U)šÒÂûé!áWÑcV{0jÒ³b㎠ågiŠ<‘`FÓ-åK´,heÖ° â—RrGØ’RpŒéöFlV ¾\%êSÌ|Ï Ó) '~¯È\…ÞÔ`‘Aé*Ôï„.1`¤—{¸)/†Mh½Ú²äë:Ä|uÓ{o•µUª»LJð–õüØ÷!u¤¸/YØ/ Ê” Ú™`WgiMerL`S)ž1<¸ÑJ�è‘èõ$µrx9ÏÏÛ&YÝ„^|a†à÷Í�;¾JÌBEhóÅQºUûXŽ¡ë›!°Ý �‘y•ÑQ¤��+»ªæ1¡Ré÷ûd½á¶~íj²ûq´Ê =3¢ï? k�žÖ[†"è¥×Ò×e@ZÃM�®Οïfνܟf[!iZÓ)‹§ª~Y*n°Bšù}ÜIÆJµ£/O|~&8^0ã<•f ! 92ÓDyJz?‰hý¬,¿s¼#CÓ‚³î¨B<ãptý‘ Ê�ŠV`tàâÇ.ˆ€2.Ö}K&Èk¯@î=C�™ö­ã"!T¯ Å¿–‡Ñt\cÉÁ?ÔÌ7wLHw(‘·ÓQŽ{”IJ­Z%Ô™}�,ŽsÓ�!EôÃ';âüBþñh|9EU¼†Hèÿí¹ä9®;d΄ lüÛ1$Edu Âè—_.…ž\åŸƵõöd V^ÍímPib©ÎÄýÚ[Ûg î ‡Ìªßà÷ç85ü•n¶¥\ÿŠ?^\ßr8ËKÙÐP‚Ðü£k+{¾EhW¸îRwÿˆr{Å*´Âª„Æß$¹¯æ]0üÄǘ)L“>1hýi+ýÈ+.º„ Õ�œW *wR‚£öMŠ å' ðò$ _g7ú/A?.¦"¤{t³tZÏ£¢WÖ™×a%™¸zƒU ƒWþù×UÆ"¬¨ß`”À¼ j;ÃÏ{ý»�š5¬Œ\4;Aj�„ç׿']º�oB›Š{¹g,6DA•e5ýßPãþjÌÌc'5H+ÌÀô⢼½Fýñ³s†oºÑwiu¦]ö¿îÕ¸W ^*�¿ÎÓÉ¥‚(0§®r�da�ívoš[娠.°à^WÞ‡{«Bú6öcmt´”C¦Ê'<�†â‰=ýýsM{Yà.PªüZºØôãÀ1õÀß]ÙxCæðBï¤�”k+†C‚êÚËý´‘rƒÀå*ÓËLJü7¥ …ŸL o¡NõOô)¹hèƒÖõíñ¼a¼dŒÁ‡kçH—áªtƸ˜ùª´�6åôîr1füà—ÈQ›Ëò ×1³\n¥DÑÆ¾Ç�æ@!MïÕ6}µÌ%ÈùoNM�ý /¼D Ý™À(…WDU¥cž–Ÿ¯æÇD+v�ýàÜÔXË>lzB0Ò£QB-t~sÐöž%ÕlÁu=,¨’Ž3Ö.ùêM|d»¨à L¦¥ûÙŒ‘‰qa¯+Îq)[ú…¬Ò‡øÇèîmñ6XüC5Ž$mS†Œv?ú¾úü(&–¶äž<ÂÙoÖ2JBÓ °•…âÚKJUä *ò:O´V[PCë-›ÚŦëYö攇Â.»³Aˆ">ûo\3“¢8“tì:é¦)„�›Lƒ=B Òm2ð$²¹Jdt#=Øì Qü>¸ƒŽÐ¹ç‹7ÖìRzHâ0á¬é™‡:XWÁm6/޼ŒÅ¢Äe"è{<ò+ùF³î’n/̾r Ôdáˆ{¸Ý�›+& ùÙŒ<rûåk“¦8_ÔIŠÔü¼³Öú¿õ›¢æ(ž][ŠZ1ŠüÍ¥ü™o(IõýïÂnX†À¸øUÖÕ½v¼½Ð(µ%ã�í2qNÚ¸v�´‘›��øúìÓªóÌ„Œ% `fü&ðí¯ß›zc‹Â�Iø‰Ï)†×˜>ŒƒTé&AåFVú vð¾l× óö@³Eíf¢FÁ"³Œ£‘òu³½–}î·ù,/b.ŒÛRÎÜ%œbÓ,€áÀD)6Èb³Ì•ЪÀóÒµe¸/¹�Ù›šå~Ø·aË^ŒÞ‹XÙü*À䔃¡ÎH‡Ò¨}3ºÂ/Î)ˆ„ž”l£ŽÙ›¬ suõSóZ‰Š°…ywÕ·9WëÖ|TY£÷Óß?òêÔ­#á4é°ÃN‘hì6ËN×ûÕ,ã^ ŒD>J±…Ìnm‚…s¥ëÕœðÊšÆúL´.Œ eD¢¾ß—òªöGaÁ¶Š§Hµ�§P³ƒªP†áT˜Q|�¶î¨ ¸�Eptíi5ü×raÎ’ ø¦ÿkgµ©ò¼ö^4úÊz¬ú5( Þ­Í&x_ØD” ÉûR…ÁâlӌÕrqm·d§i3ÛÖÞé÷yö;ó9(™A#&†%–³ì¤çåÉWá„KM*ÏÅ©Œ>�F]þ…qú‚F£d�µlm^øÈ2�B©°–!PQŒS�£œPïÓg²ÕˆAidžÒ…f9Ú…=ËI„:ÑÞ¡¬‚ÖY�@¯ k󃇢2Är­Nœ®—bpdŽí(HC!)”½ÍmŠß949`/X岬&âý±…cäXÏ,oû«ó!õ~ßM¼ö<Ø,à(œ£[`'á§‹hf5m°JÌÞøÁá0"�µlË­Î>avÔ…tP62üôdZ'ïÂPœÊynöR®ö»¬• näSÛZýMo§í¸„amIφ‚²e2ðB¬«cíÆã{|†ð}‰D¤¿¿Ç×XËa'K¯«ÑÛH+•Ëz¶9_¦h¯ ÜŒ�L´’„f�>Js N#2÷#ðX,%‰H.?(ªp1h�ûýzŠå0í€.Evd±MÝ9’ÍtÊr?–Áâ¹[±^@Ã9æG’á;_î†zà˜#�͵’Ië°¬Á$ëq ¹gt“cmm¿„B±L”„°2:Ò$L*hDqÓ£Ï!>¶ËêkÓ$9á³Ó`®¨B¡sŽ(€©K<µÑ„+‰í¼ 5)²5bl¸ç û¤Ýf¹K9F¥k�@Y�7ª~ÇÇó—x õÆ ­·ê:ýTÍT¶À.ši]¼,'†u%W„¢= Ž~fÿ;í’èÞ‚@òî1|Ôkªú’%ÿXì/Ä8¼Á²'u ÌñºÑÚ·øW‚²÷äÄ5‚ÐctJtŽAvº%‰ãšy)BОDï´…‹—�›]a ��/ËrãF]Uphq¢_ªÛ‚ ‘¢¼ä\ä˜×½yé:ÄÕݰ²Fe¨üÅé^Û’:çL„Íz^ãXp•’fæs6ÂÉ.�¢�þ7ÃA |)Ö%ð?,f2�÷Å­”6Àq?^èÇÕäÁ¥Ô¹s¿Ãô%�%YÖ¡<+´S¢ \´Øìߟ –íÉ•jŒ#k\Aé7üûGÙfUüF|ÃD¹ôŨ¾g¾S7vPCùÂÇ‚sŠNêÅ ‡¸îÁ‘Bêa•Pô\9¡DÚ‡q³îÏ�g�rîÝ-ìrì!D–¼�®>è›´]Çô ¬…ñóZË{Áò�Î×.§ +Ì;óÛÍ�ñK}‰÷‚TÄy¥C%–¥1NëGëØ÷¤Ùv¡ÒÒ)û� ÒWvyCî~æ[WÕ—¬Ùißè†|Sÿez?ªQuföÕóÔ‹Ö›“>¥ýs´,ëa.]+oNd�¾ªÿƒLÇ“v¶øÂ HT/Uê… �ùŽ‹™J/Þü\Í’ª×F�ᮾrÅ:£�š3íAޤƄ 'oQ4ЉœÝÏçìü† �ÿFuôâ|&_+îÁ AG¸ÃÐÑEdÂb‘ ¹nßö˜Ï>ÿ�PõÔM_›/Úª÷«*ǯ¨@Ä@#TI`Mó„äÏLÙ�+  _&QŽÍO°‡Q�PŽsR‚ÚpÉbÿp´¤Åhy Ö: N&O+}Š6žhˆÔO¡PGN¡ë’C(«Ý® ç#ÆÂ<=dÔ]Ƈ6~éPÁù…�÷½å*LÿüM×L§m$Ò ÚbµCûh­ob+š¾×Uˆ�ÌÍ­ƒ’páTveMöÄ¿ó@9h©×Î�aªiF£h2ÿõ}%x×ûW¤ü¡Õ•ß[šåuù|JL¸\Çh–N×�4VxÞÉöà÷Úz�¦Å`\ E0^$­®Ñç4;g ÷,Zª Ö‰Çl”ÙU™Ž— vÜãŒGØx¸”Fá©+1þ•Ø„m‚G<’ß,9˜ÑdRC×çøçô/Æô-̲R™:ž9'÷�ø¦Œdˆ �PeÃúâ.œÏÔ|àB~@4æ º¸³pJ½'îró‡žkW'Òg9ÚØ|Ñ9ÛO’ …â§ô¸»HíÆ›;Ö ¢« kböãêºÃlÌ�˜pÔx©ûreЛ£ Õ>ý­Áå“ãÛÚ�V0κ'&TV)¦À"¹E"ô!L¡‘¸ Úu‰Ðhí8šAǯÚ²±:’å$–ð¥Â¥i¾s« ?Ë«ÈÑÉg·LT¦3þ‚å¢Þˆµ�-uªÝóºª1®¼–æœ/»�ý-²»8ŠG4ÛMH�bèJ]Kˆ¥ôGo¶<Í„�b˜Öêšts(5ÔÎç¶xe#=5 ðzê?8‚õב‘ÑLû)z|ðD,°ƒ{:d\áÞàñ‚'ÛOŒ×o²‡& 2!�ÍW ~^ ™‚¼)§Ç‡ÝÒ¨ŒŒX s—Z£­´×‡Ô<]·Êu;´8Ì^�Dìc¯ $�)JÖ‰ÎÇ1/üxLÀ_oàSß;å;;´\¹tãŠ/±Há¥<ïwru+c2ZÓ(Ýæ$×õEÇÄÏCyuûâfÃF4”üBbòä2À“4ªøêBÒØ%µŠaIõô¨wLZ}ç¾ÿ+¸ ‹T&ù-ÍÇ[.Ö»ŽêQˆ9ŽžkøèÕûù´›¸±#$Ûm5Øä3ª µ?ûrlÂÃL,_'ΜhRW&LÇùˆtÝP[&S(×0ü ʬA´¡qòNÒ% äw}-¯êmô´y¦T«eÂ@ ›mÊ·‚@)�Ÿ/}Ëàv„Ȧ'�ÐÄCN¿rÇâÙ‘Ð1~E-�þNÐ÷ŸüCÍ?óÕ= ©p$“ÍÔ\™úíý5$gTë\®Ý`��7xí|=ª!òªå¨ÿë�_¸²¶¿Qi¼]ÂcèfèWè0¥¾Éć� ázËa‚�UÎG|‰%ÆÆ½?̳[¼—’ _&sÎeÉŒ6š‡¡&i`À©E÷mÃîm$\ ;³ õä W`´<æ�ƒS1!áuç’ñ…‰ÚÈuäH¤†�(‚ÝE‡L€îAÈââÏA¶gòÅíÉ£;“T¥Ê—Ç».cžÛ4›²º)-02¤"WwÉõcâ·æ{«–2Smà·jÈnǯ#gÄ£FÝ‘?Œõ½l~_óçä ,•ç)>Ö®¢Ë|à| _ci§Òn‚lu3QI~;Í,>3å‰ïŠã/5Š®ÞRcV£Ÿ±?OIÀÅDR4iæv@³(|Þ[X·:‚sÆØA&2f¾a¥ö ¾�ì-úç²Uü>×úäsQ¨Ä�} c/D„¿]ÝZæpTC£/ ó¾_.ab@éÚéã;ëp0‹¦[¹ôu§üBÁ¬Ÿ-Öü„øGœâ(—ºusQ^²Z�°9T8’½k/}o=ÛþÙê÷øÁë3]šîô³zÌFpò4O 4SÉü?%ÍDŠ%á4�*nn ë�\Kì@”nÈÒ—ØÙáZg»ì¢ÜõNmZ_|ŒŒ�Þß›/7öl1]IêØ.Ã3UPè�ñ"öŸßùÌ&+eæ“#æèAæ¦)A³xAÌÃç3Æzeª¦±ð“1Ûã‚<óÍêgp^¿œÒïKî™Âg"�VŸ¼Ã—bdG Ú;¥«ÏoPrAu B—¿F×ý®‘xiSªº•? K*I%¥´sçºE·k˜ÁR럯£ÅXƒ˜ULg¤Ô‰¨ò‘‚Õ R„ƒYB-‡Pv�À1Yºã¡c XNJùuѹ©Ю9ÃLu–ý³¸Â ˜3K‘Ñ>=6˜prÄÊWâb=æ¹G 4Ïž«çß6zĆq2�'—Vi±$(¬.î ,c3™ ýŽäÜ\™º!&ŠÍ®5Õ Jí$øVp f^”qŒÂí!®¹ÆkI/6å,ú3ôšØHÊ]?‚¥÷ç%°ºU™–“j2> pÝÝ3³¹SfiÕH  Ò‚†‘VPÙÃktÛ†áuq®S ¼¯«ƒ~V¬¡ ݉ÔQZó¿ˆ"ÆL.½ ÅÒlÏŸpz¾«ó}M�I•ÐLž!¹qò(d UˆýM7Rz€ª?Â'щ³D«SœÎ<–WN@Ñ÷hü°õˆ„(5hµú©Ð!òÀ±B‘Aé÷úÅ–ýM‰g¸Nð$VR§4ë®ÊÎÊî‹öû-UögVK‚î Æé]“}kPá�bšáìë1Yþºúù½ïä"­H8ѤhÀám Œåû¨…*?Ê-N%]ú“Îa J ö ‰ ÚžÊûÀ63‡õ²nlóvú!dK–®G¼Y44hzj�ðuUÄŽ 9Ø Ç?ú�ùˆÐϯ%÷éï¡j_ÚÅ}Ówš#­�hAiU ³E¶ØÁe¹?ú|Œð©>$|¹T_xßj[è_¿M;ªÁTâ¡ féÚ)­_ǦàÁÙt<€×ûç†imÐ H"Dâ[ò»ên…Z^{ïø‡!Âfhœîxhï<]´ŽÛ�ôH…{I�ô@¿³X¥7˜µÒR䨛@í=&»Ðœ{ª/·)MÒÖ‹Emyú*MÓ!Ubá:Qùê,f�QÄCW‡bôq&#+6|EÏËÒùå2¢G}†sïñ™z³‚Å�ä‹wþSp:€"¤Ç$>Óã¹õ•*­V dü™‘Õ�"Ä…~šà5¹2£©ŠfÕsÕ|‹ø.#»‰cÂÔðî&£¸Dþ–¨‘šùY©©–ùŽÔ±£ù!��y%ýL°KiÄŸ—?œ•¹™c†39ÂkB¦�et$kû9•çLø“;Óôã´”Ë;0Ú®ÒB^R¡P‰Þ’‰%æn=‹)Ô¤†ÌÈ §ä#ÝÄaþA²§qãʈbŠ N±4 p†±Ø~i¤ë_ÓY¶|o~¹Jµ’3Œ IÌÆ}w`¢ãknJG.¦BëÛ$Uk0ð*Üt(ÍŸ-Ô|}éá“ÑAªBÅ+_ æ[Üw_VÅ7N|("òHÉûÊØÞ7žçß}ÐKí¢#Ü;Ϩ¬�<§‰†ø ”0i�Ë ¡�À—ôà‡¹§‹'jÊE÷nÍ0Žé´ss‹2�‘Ømu6Äó3êšC�¾NÚϦª¤w³ƒƒ:×ÌÖ€tH 2÷÷EøáÅô8BqîÓÁ¹e& çkn,È¢ë}GØáhϺº47”ÃßJˆß)Í à=Ð:“VÅãx3Úå( ‡Þ�¸_“?Ë}°AH¥}% ·ø&ƒW$èÇÈ~ß™º›³¦U +ð¾ì,ÂÐW.¼!&³Ë«lH P¹e¶®¯öS^Ú–1s‡Þg[ФKÆõD<ÎÆ&5�·Ã ÕT8èº usXíy><¸Ò‹£áë5ƒûGèàá¹å�ô×j8·g’†={œRôzº¬þé^¥Ù-Œ‹j,"k�¬„H=^!öNO'\g…jZøWhÒ$†5öÞ”tKÞõÅÉtŒ\5ë$Ùw+,´þŶù5YpÍ�C7åŒþcño£þê}.ƒÀH£�OJoÁÁKëÓ�…Ü1™Ø&¨®)êèö¼ºKþ:Û+bã[ByÓe~�ä«Ãk«À±h™»[ä"ïˆ3>š¹’ÂÃð´Ö­ë/Y -Ï‚mÆíCF-l”!]¯¯zSqœÈâk¢Ù%ü§5=b?o3o Áò°7˜bÿ®k3{ÆD=z—¤ñ7V^ò‘rÌ�aÚŠcRyË¥2J˜ÉÈ‘_|&ÚãõhMeôŽûöàñpîïÊ·Žy彚”òƸ䯬N7òb7ªøu?¯ÁŠ3•´ ¨à~Lçš–5\-Øë�ï^Û©(檮*D—�LÛ÷^þÀL|áö7¼ÕÀ/8鬜žmqVÖ~|bD¢?‚ë%·gàxp ‹®‡üØ}1ñ   —6à¿ý ë‡þ2 º%×̼N&�FöÔn È“´½�6V}ÐפÐ6Èñјr€ˆ6ˆ+ݱêÅU¿E ²Ø®o5qñ]ܵí“Úoµ“©°B-ø«Fú¾?îÄ«çÐHüõÄ·Šc[¼ÎMgÒÞQ�\˜YÙ…²YZõv.¨é”¼¬KÝŸõ5°áWÒîŸYx¥c‘¶­¶È;¨=QQ=5™Ù¿ÒtÔòÃIíÇä¬ÕÞɦ)ŽîjÀ=C eXÁoÍ­dp¢ÆÓƒŒ{ŒÉ1{ì9;fâKV8wšÕÐ&³½±·+-=©¾g%­7n§Þºø*Ͼ>4´3è|\5Ú6Ÿ\K€x½›˜(îqÕP÷»¼¹•®¡û¼üPŽyžL!‰½… ›5ጪæï;Mø„¹«<ËJl¾;ç¬zfÙ\Í!Ö–l5s(©ŠîfÜFäßju6±°ù€„÷¼ §GÚföVw5¢w¾ C��ÿ€Ô ó‰-½œ.ÚôÑ~ÙJ÷ÅVûhªJ�¹²ëîMºÐcM�ñ©›É+ùa ëc¢Âb5!M«÷ŽN\–¬;úK!srõ§;å£9ù-…‚ÇmR+´ŒhpÄQ0,][ë8·�ÀMÙد¬üªí½3•*•òýÞUæ¹Rk_jf�3�é’¼‰w8©þ…s¡^T©ߘ[�_+�­D¡=½æñ@¾Ì¤—ÌÝùõ”•@ž „ª+»=™sìe¤¤¦�õÀÚZòX›vsµ\ÖÆbÄþ?³pØÝ±½Æ7‰k_üÝÑ»ÉѤ²[Ï4,Üuá9'‰±FÞ^¹´Œt]­�ÜÝÃĉ€ ´"¦€÷¤ïø…öà–§4HÁ:,¡Í�ýÌÂýØOÅ¥ßÖÖ¾åÚ¥¢Ï÷³Ôœ‰ÖØ»6ÈÝÇR%ì{¥ßü–ün8) ¬Ü_'úh­"€Ks.tê§ðd¬àZ¨áFg,ù­¥ðÆ#èaÓÐ÷�·bÌÅ!(&;"H¿ÔÿH2dÝ'#ŸŽp"ÆÏ�"\õd :Ò¦Âý�Rm«$ýÓƒ&ìTª|Šûžm“~�r(Û?=[¼)ÀF“Zpû×�Bw ˜ü‘^O!œÏü Øçê\FhqÁÂv&àJæïm»xrÕ\ŒTk�¼z>ÅÞã$Ó¨¼LÕœ{RÌ›¬D¡i}ˆ!ñïP€"zSõ �úcñà|¤A–4Ó<X#ã¤DÑW oüFIIHº¡4v»Ê7FuŒ*b(缫ž6M~ulòÒyÿ¬� j*§£^ÛvÔ*í¯Lè]|/F‚©$ùpÐïj›SÕAð..ôÐ6|ï¥ÎÇ3ï ŠŠø¹È‚j?çâ]„ß’Ç<»öÖ?˜¢çÜ žšÌ5i-T*VšFg�âŠæp`ß›ü"B„ï§“x#‚OŽ2p;™4D4ŠKªGgr¡Ûû”Œ5FáµeÙÒ¶˜¥q€¢}ëæTñ·¦…!ºõØŠîhim"ÌÅÓv„!Š�“ûiÎ4«t ü'yuOW“9ˆ~æ3ÿ‡q½>7i8¨8” HS˜p ¨µÎ*jçN]è!±QV"ûéÙ8G1ÓöÒtVT¬ƒÙZ|]šk,“Ç?.õ /´2Ìv$µüfçP�”KYÝ %n”k£¼´¥,¯ð­bÒõ^B(šj„±9˜ÄOÃì|­ÜN¾Ûƒ;  ë÷¸!;¤øûÚvÍæü¯Ùƒª¾� ×-IßwjO´;(ôŸe÷qB¡Ü•?=s¨wŒm×3Á ‹’U·‡‚ÖÝa´†n%‚C8S­ŸA¿aŸ;Bš2l¸g Ø~s=�)C<ª¿ÒÓç+¸`º½™£ÿÈùEGܬkžTŒöHõ;Ý™!7/,›ÇAkgÁiIÝš"g“¶E!Õß¹#—áú0öøÂŽBV‰ˆ\¹ý�zÆ�b6‰Š•ßî;G‘³-’…E²ñ®)×0oìOŒ×靿�=6*êE�á!j|V!¾ð�¨Kˆ¡6©TcÍ+7ð…®˜=ˆ‡pÊxe5Å‘ú�{ùñ.nm•–°îE‡°´oÌE>=$UæœWViŠX•ÝFaA`�¡j\O¿éÒ*QA:%Ì&\¶£z¨&‰>‘Œ?·X#°ŸQayN¨Êh&‹ºÖ@±Q¢¥;ïñ$ÌÔåÅÕŠwOðl»`³Žžx� ÉÛ|0?8ÇWðÍv½£ˆ)ÇÌþ¦_x`F,E2YŤ=ø²þí!”ù¸Øi¦œ2¡�P£Ã©–Ь’¬x Y¯�ioQãµÿ¨hܵ©ò° ™É õšŽ¸“EbÒ\�}Å{ [e)é†j‡®¸�ÂrÚÃõýÍ:0!»6ñ¢D=Làè;$ÿ¾ÀÕ4’ÂU¿¢?šF}%#Zä#À‰Ã ï%L˜2 û–°øÃ,:÷ÆÑ×M¤±ŽFz¶�b.¼*‹§3ÓHE&œÞÁÖ@œ4Ô)u79��~ïYF♣Ƌ�Ìß!Õ7hòŒÀ7óq:g´Aòä'ÂA˜«tþ€ýÏR@K…ã™l߆OlB+«¬øs= Œ¿þ,C&²ç ¢ Ÿ^c¼]©ŒøÒü&G¯¹w“Y⃠‘÷¯ûjVI\.[¾ßB¬ÀT2pæëEdnqF] iDh•¢)�ž 6w.®·n«5Xjmj_èRXò|T3RÀ»B”žå-œÚE¹—éŠ|»{©öc�õç�K´–=ËÄõ Yj¦u#Z¤ˆ¢{ä_7(r­¾â£�I¢÷u¤ùºÛØ&c»Ò1–X²ïJA®¨çÖˆo›!l:,!ÏæÁs"ùñ½¯BñÅ(Ò¹¼àÈúf(KQµŒ3�{w賯´‹f²¸ªîù"œÓEáªå ZÖÓŸ|zÝíxõyl‘`~XÎ] \ ¶]¡ßµF. m~äkMOó7&À!êH>/`­„ÜY7%Ñ‚ˆKTm!þ2k)šúm/k}±5ŒëÌMoDlŸÑ‰Ó»"Yb¤×ÿÞ)òbA›Bìm™› ¿ào$Å—Y6gż#ˆ%ƵY¯©E‘®â—(~«ùT4íÞ¦(ž°#@ %cc®vE€ãÜ·Íh?°ê‚dþZã�j—›ÆAåe8ØtVÈ›d«ŽïÙàåXÿyÞjœ§¾¢h¥HŠÔ!DÉZš’ŽGl^Eûä·æÒÜàOD1y.²…%ÌYùÐØað„ñp}-ø´ç}òq€êÆ‘u›Ec‹ùB¬B}8Žˆõ¤@Ì&óurªýYdÞÿJ¥À™·nößÛó²ÑÇr“Ãâ£ÿ¢.¡‰ <0šŸbGŽdA]ú­jf}.­¾ëUÀ<¯oqrÔrvŸ#NæÉ$¨øðÉ=MS•€Ÿ²Ÿ0ã¶Ó{ã³Ä"€q]Îj,–{$ž7ŸN­âÏ )e¸q³›*×þiÿèàpØÿŽ»Œûç>µg"Ä<¹…Ÿè›e-ÁhXpVÅjÊü «9:¨¦n)IàFÕmé­<á^8»™íÉ[\\×ÿÑÑõÚ.èz€ÕlB(0(-_k++Ÿ-ÉÕ-õ�U’’ÕOSþ;•Š5ìiôª!”Š‚ÆFBHD<Òz?{Ÿ’&˜ùtA%XDE“b´gNé·«Ã~!.Z³ %:ô•Œ)ð#¨8ÔÙS¤m †Ó•†�a>r¹ÒY¹�ð‘ßÁÖnZq}H1ƾim:‚ö¦ßŸ“êÖ4r{ëF¼qòÔ&¶hš� œÈ¯Ïçd´´K¶”Ž“îIæôüŒ8,ðáñV¹ f[)˜À›âÑy.V¸hê¼ïÛS&`-YFñÛ™Xvgª¾ÐÙk^"Ƚ€Só͹‹¢ëλp¾�Ãp~.m‹—5C` 1pñQo­+Uœ§ª<6‡Ô|¾×¦Ç’Ížcv”´<ï`GG° &«0¨µwªw–ëÛ-ìsBGó¶sž\ÓÜ�œÕ4Š3¿\º½y»>Ý'f\„Ó> ,ÛÅ ,ê»ñV¡N‹øœ®èõïŠD=ŸKtN’?÷Ë0Ä›pùÃw5ÌjlD3ä©`;mT8)™uáÿŒ‰¸4zËxm8Æ|̱ì; [ cå3Ä£ƒôÔƒ9P3Ç#UßVA½ê8@BÎôÔ[:ØÚ^[Žðbž|šåw£’ CÃóc†*�7X�ÇbzÉ¿F.ËÃaxkÑe™@Á‡o�`§È!6Ì÷¬§¥²Äâê^~}7kÞµ|°·7Øc”/0ºI Õ>ƒV~üéæ—‹ û‰ü=š$è2ÈÈä’�7ª>u>΀úÚüm ôg0Ÿ€áW¿œ»JÒáE,ÎZs{†Û¨À]ÚYm\6ÛœŽùPû�aó }¸ ,ÓçÓ}‡^±ÒBúŒ«ìkTþ1à¥À�ô£+umÍÀðÍõÌú w¦Íº4IçtA·‹%‚CK“s�lüù&3 ×øb%^˜$Sr¹?Šâ˜wˆœ»×\ƒéQ]¹ãÜÂ<ßrrl�H¶+š­êÌbÕÖjå´L'S[Ù¶_¦«?ëó˜S¤ƒF8“ëÁrì†Àâ´ßÐ Eצ=3FÒIE@aŸ¶Ý,'é�E�“LeÖÚª>Ó`ÔŽý¦÷ÆæFVã¼`ûg´^ðñÁÇ:çmS¬æ·°T;B·Óý'yV!ô¹‚™òRz�ÿ/Ò²ŒÛxm-†rÊ5ŠÛ!Ó™®Ðøg_ݨ)[vI#Mÿ(ˆø­ž±ãÛK� C 1“¹é±ïDu|E‡´(‚äÅ|wÛä¥tZþ7!ˆlë[nŽÚõ~з:aä‚ÍÑŽ£@¯“À^âÛ��ö;ß¿è�j¹4†¨KKÁY’KDëz .j{™6N €ÛB¹Õ}ê’Þóp X)—á¶&G½‚ˆÎ1Öµ¼Q“H¾A€Ì6¯C-¸û–%�åMQÑøúÛ s5 ãc_SVÀPDþ™"GqœÞ�ŠÑ‘§ÀÜòL½èÞ�=“A”þŠaÉÛ$tª)šfê_c¸;lnÑ{f:¬ó¦HïÍ{*²k;ÂìþBÊù*y ½¬‚ý–jWIôÁ]ÊŽ ÒKy£"ó0ÖÊ™ý¦F,yWÕ9쉅â$½ŠF+÷qÅí§Ä�àPßxŒçʈcú=îxH�Ú™ïKþ±JMÊÆ4•£ÜžžOij>:t z½×=4<\Ö·Éïñ8„°ÏHÓµMê£8±OjUÇîàì¶•{(¨!íP1K!´˜××±ÛjF€}eè:pÍY@½×gER­Ø»Äº/sÉ"«—ÝJÇNÍó ¦„óF^˜<ßhG �S›5ªm†Ì”'_VÉ Ò2œT¯B“â´ý½ã‘N4…–TÈØîãäoºßª\±Hw$´¼”âù‡Ü¹È�lEëÇò¶¥'sÍ m)>ÓTª\·ß œ$ƒI;JHéQÀÊW�z‰#ãûLê�ùÄHiõ ÷Ú#ö–¯¤Õ›È)ιE†$Å—CŽ8^ÉJ[u##j9H� 7äZF‘W"­� Azi ¶$ÓRµˆ&!K„uÄß_§IÔ˜©mÄäå.Õ«–kYa‹�¼o$Ó»‡­zˆwguá¹n~îÓjKù3àrÅíûÿÖyï3K‰¡« Úð·˜ïŸÿÕtk>Ð3&hAó[(ãÑ0BÛ°]�ŸG9¯faµ5®M(°D»vá-2Ã$Ö=¦F§¿uâa4aa-×$õòÙëäl�$ÜÃäñM?)%GG¡PQ¿z»Ò·ƒ:Ô ÆÃP.’ãë-±tõ9Èù}0oÚÈð]¥Äá{B—7èíOüøæôÆ…Ïàg@šX‡£,Qîš7IÏ�læ¾”Þ¸«qŸ�vÂöb<—ö;¨õJ0Gx7•Äš��  È[¼xÝ}¼Ø,!Úàã�­bm®E2/¹–pt¼±¯ŒîßÀƒ†àÄqŸÞu.ͽĞ ß$«6C]ª™x®¸«1÷;U–[)õy�3©�¨¾´àTð£~¹Þ_XM™J“g£‚û!†¨cº’¯!KõŠþ–dÐêt\œ-4Ÿ/‘e¦&£ ¯´pºàÕE:ÜE$•×§¥W™êqpV/pJø^ýï˜CXtT­DöòÈĬŽÉˆE€j‘UVØ{ZC'X{M …àñ 8·[—¤`eZ/åR²°Ñ®Ò×ÄÓè���ƒÔ“»/²øhÞˆž,ÔˆÒ7jy÷äp˜~5AhO ¹}‹Ï‡'€÷9ˆ·•5¼ÓÆÄáQîrAzd›¨#Ò÷Ÿ"ê+]Ÿ¨b£'˜s±�OÂz“x€‹Ô÷f£åÑð§®Õ"±×[[3ª—eÝ@=GõC@Á Tv¡O^6CbœúÉã¾¹¬ñß8Y½ú‹²hÅÎB3ƒg4!ð õ`¸.Ü’ù<‡Rl`�"Hþ²PÌ?NÛ9ûNf'Á)ÇUk¼Áð¹¦!·¡ûÖ4™?;“;oÖA3w‚&þW0j, 0… ½VtšŸ G¿_)fÎ~vQ¤ëü°Zd@ºI râY{+¬žD–Ìè§ËBžfFˆ˜•N˜|4#ªÁŽg_»2>:Þ„ð,¤,z1f0K­¯�¦Û d*{C­$éM0Ñ™Uñíðz²Jé5ÝRœ¶…�Óà’”tW,´+}À.t%Î]!î «�œø5üJxN‡Kã ´“j$FrwÚréC?ãêå&0ŸÓADë-uÏ}E¶OOâ¸ò²×åïŽu:í«®ëÏ8çG, E’ òä(õÆMƯ<º�ð§O€ÅÐÝ�Âm¡¸ü=¯–[t4©,žzx†`>&Vž‹‚]¼JÃéþžµ9"ÐŽ ‰Ú à„fªîug¦ŠØ1P A–Ü«úbök¤PàOÇKD9Tuèa˜ÌçnoçÊ;GÉÙb¤ã²‚ëê]ŸÃÓÛpMÈ1§ïØÅÚ”-8W±¬ŽÔ¤* ùÛæã"#~®•ŸOÂ4¬´¦ßg©#úU~‹RÁDBe*¼'úÁC“q¢Êš3§Q˯GQë5º†‘!El}ŸÝBÙpŠ´"çÊÉœ³Ú*¼u`;}—ØoZk3Ï®ZÕ + ¬y9Ž2ÛÈòFȳK‹Îg¸âÌé>â_I¥Âêûê@ø–�®Ý#�¹ê¿’pqõ‹é<Ôh~©ŽRQ#Y~zœN4 ?wL`B]µëó«oL ”J9cÃôöÂQÑ^ÿííü‡Èî͇¨Ûµ,_Ro4·‘ª½a{ßârp2Ë[¥�bÜ Üe÷#IÇä¹.õ|•£8è‹NœzÁ-ð­ :'U×>Òá�um�B, Ýø™)ƒ´£ÿ»Â2f£öy|_ªŽã§Õ|æÊù\šQópè¼*x¹ZÈ~w ¦åžU.UæZÇWw¢Î nZx ]Xs›#ã+#+Zß®w‡dvÝöš×æaBÞ¦­ÛsÅC›}øìþZáá¯q²„^„baËò‡†½õ Š ²tgÐO•Çìž9Rß…Ô–ãzk½v]Kpþ\A¹ŠáÞÄ0þsž[ÞÉ’Ð+Ûô0·ÆƒŠÙ}oœ™Wï–LïoF¢rH0T ¦æMñ5ÚdK) Fç¾1m©ƒ®]*¾`*EœO³òÈ‚'•\wMŕء2égý-/½dò³Xp+£µZ P[^Š' äúåcí%’©Ý½Õ’NrMÝqOï/úyb‹`ºó/ñK<íaäbr4 Ýä]’ƒFoþç|HÔ•ñ@òž¶×½Çˆ@YZ"ûš‡c0?hßè|2^B”Á©}&–@›U*ï/0‡_½Ù´ZxZny�â¬3¸;…U˜}•лJö‰!Õí­ß§ö6C¦E79TäV®%«ïŒ[{¥mÐÍßUqòËe¿ëLsË>G\EŒ$`÷É­¦Àô¦áûžz;'¢çV_E×û3ž-è8¤�¤70]€ÍË I4ëȿϼ¬Òu@JœO9Øòé<2âåÖÛ†a[½ ÷FUK HÒ oÂih5„£ ,�.�‚£¥W,E¦½æ|Q ;U ?³{€xnfrƒç˜ ÜMÔmd©ÿvàßsy‹ŸW€*%žHQi*Œ Ek n•I‹qäš2kn£ì?”^ò¹ø²÷^›;Ò¢·>¨2 6�Q¨fUY5$3xa+”_•h,DvOc  mÕ,Ýò±¼Åâ§Òß´4Ê ¶³Ì7eOؘ >¦Ë ›KE·ÿÖ†) ‡t††™ró‘°%g.,}ªýaæj$œA{j@$È<ôqº>óx 4<ºÍîB8œ_ü¾�èÂÜbêÇÞ‰Ùþ˜ksÓkù<ã»ødh³ö ¨rñ6˜`Ú<Ž�œnøÕÒÇÚÓ¶Ò 9?È#¹j®•Î.ÿ„\(Ϻ´õ_IÏ4j?T[ÜWbžGѯ¤CªlÊl?”q¬àÿ@÷¿¹&ÉlvÞï<¬1Ø©XÒ3+µ€]÷ø3€~¿$—Bæ½'´}û&–ŸÆW©\ôm3më9Ó‰·qª¢¯ò´(Ñ\ñ¼ òÚžO©yAE gêÄ6#Kÿ¥ /ŠˆÌBƒW¯Šš´¼ò}%òH¸xÎ:Mñr¹¹ £.ö£#þƸ[QlÕÍÿp€?¢ÒSVÿœÖb- Œ¸’0æï«÷Ï}óÐØõ„ʈÄvm3Þ}ª¹l�ú• 3gªAœ2Œ•?éMð/×*óª^$'¨ �â7­í•º‹o(¥M%��ÌÁ¡2hN÷çÉšÀ8u5Q ôb·þ¡º»'òjZ®èÓ¨ÎÁ¢o g,3¨µm‹¤_Ô)£Û>”›'»ÒtCµàvT]ŒФ�ye 4ºóN=9—çduÄlþÖM2ȧ–Ú°0p#âሦ�n>ë w®Ze#~7õ�¡\³Ì“Ômá»)‚“jàU9+çÔs)^ìU(í¢ÚÇuð$/r~W2S&qe¼½±òLÓ9 ѼVˆ&K$2­5új‡[]v[HVÞ¬'‘¹'7Z¶>$�wœ ¶<«þ°TÜÑ!¼¯®C†j¦(ùÙÂh9¥¿:cq�Öô'dÓ¶…xåï”LòêÞ€#ç–¶[•ă¢=GXBá—¹·vÞx“± Jĺ`Û®i‹uBÕòO[ÞR7Í £.ÐúÄu}h9ƒ‚t\!:÷­ì¿+Ý=˜䈚wˆÐœà†áD„¦SìÑ&!SÄ9Žˆ¨Û¡ƒXŽVU5¦¬k1 Ì8Óè”rÄá 9FTš®áÇø™¦þù3ëNÀRŸÒ16¦“òUËÓµt`>»cÎ4N…ïšY¡�: çiâöA°{ªÞ$øâu¨�¼^àq"oñ ²çÂéY›¾¡ÉàI�… Ú¥=ª’ªwLÑÁ›²lƒåÞ†kæa'æ¬G†÷þ›� dõ§”Nû\Þ û�%ƒþ“uºÜîÓÅËËÿ#"+¿CÄË£[¹�Š ˆ7;‚ö¦…ÒõpYõ²‰Ç0m2Õ£~Þ%dóiö)“¹öÒà (òJÚ‹SÛ¡”SÐwÞX�žÇthÝžøã§1”æ7ÈtAôË_k:£€!QBräùÉr݆¿ò¶Ì�íåÐcûoðÃtFu𨫟c3Ò¥èä.œNÖã:«0:\ö.UЬ­/á¬qbŠ]Ü*×µ�Wé˜Ãò—¢aÈœ¯ÝóÄQHÏé ½NÜ:kÃO|)"7—) Ë_+mÛèLtà$@¿˜•Èq^·ŽÜé”sÆ’O1ÀØîf ÝeÄXQòºÄ ŠhØÜú} §±ö{òó]r¸Í=ê:ü„“Y·âe52È ©?�_qùwàƒ[[¦²‹ùø¤L 4¦ »õ:ÀÚ»ÎÌá‰äZAé2aõ’²c5#Ûþ�îá”[´ädV dNsO=-�×W«åXRú}•Dã Ça×M’çE ¶�Q"å vSZñíîhm¨Óœ ;�f¸\¡aÝ—òú×C’ ë»×Gt˹tK>Ž 9à=ïÛ³,:-Êlï»åýKt¹­œ½¼ÉÉþ@¾c/„f(E”›ž5˜¨£{LKo%JE’1*�Ñ`°§Çbz»†„Áׂ“1€šß5­Ã’½&Èrõ°ñE7&ÆUìÁÜ&Œ ¶#£W"¯žÐ%µ€d¼ù©I”õÝ”æul{á~ŠÛæño‘רù™°V|ùg|i2Qêv)éýhvý]nÐËàbTTé�ìs0n›€ã~ ‹Á¯�Ò¿€çš¢ÏüGñ¢]‡)sìò+T«/J¦¿¸bvû‰†«c�¥Û./Qlj¡öþ�I’,›õëÓ%^÷NV"Šq÷¡tߪ·IDNîþÝm” A%OG¡ãò÷-�Ç7�ò.@ °µq ‘W<éI>!™:ƒ¨Mh‡0 Ü?ÌBÉ«ãŸã‘ÝGgfÊlÌ*­dZ{«ñ³­ÔòøÜþ«"ãÃÅâžÔÊ[Ñ5Œ¤%_5K\ç2GÔûí‹îÞ\Æ¡,K놤›®+ñZgÄ(½¯Gþ·¸Å1�ª—ÒÉáÊ: ¤+�ò+ýgôMK””_lqeVþÞb@ž\ßíñÐn6¡¿F�%Fãt*²,‹ò'ÉJ=Å>õ0'4¾ðã8Ú�Æ�€Ÿ <íÖÉœJ/}ª€÷4sj¯.ã ø¾’õ'M›óý)�?À„IöÏ�•Èý‘î÷‚=VÂD�[-­Úì�!óGê�mØŸ\k$à¾ÍâCW3©¸;�£òw¿ ó`Ú Z€�t}ebÈæ×ÁæY=íÈ$õÆæýÊ`$úùÁDUŒSìáeÎ\ìªÕ‚N¿¡Šild/ÞÐæ«¶ü¤LÅο-IV{´áPîS�1ÇDÚ7N«úî¦IÆÇàå2¸áÒyåŽ&5Ëóø‘kMK韘4½ÏL5}¢¡I¬jQØa¼Ê¼lÌ·µ,;£Šöyæ�:C]?WW”“ñT3uÀÖ j÷uJa§ø[Ü›XH¼‘J HC|ö¿r)è¸#ë³ÓpùéÖý’ȼfßC-Òæ\ÿìæšZ’îïôÞìØdf”ƒôîh|�UÐÄós/[!p;NøV¼ÓG+¾e‰Š}òÞW®x¬hp\ÙŽ�\×…¿.ô˜™ÆÍ4Š~�ØnØ ’îÏúå»TÍYÖÑ/$—¤¤>‘‹›Zs�¡bÓ¶Õ2„Êsëÿ36EËxpÌ�I´g¢“÷;ÎyWþQt7ë÷+ðó„R7f ½QD?%ƒd*ƒ˜ˆó-w(lŸË{$‚Šë[CÌ4>ϸÇäÇT0RŒ$ªg¬C9Y£ ”Ñ&\-œC9j4×zW_0“.[ªã©`¹§U�dcu—ƒr�tÅÐ…€Ëµ}´Ø÷ö&ñ´Ç¬}‰ôÕ–ô׸[ÿÀ° e”-!Â�@åÐôÑ?©•ÁœÀõö׆%-8õºQlð7 ¸gòK¢DkjlÇmòîU¹ºq7´€±Å5TܼÒlG”[k¯V÷o¥5P[¸g3jŸÑÎöQÙ¨šJÅ*C¸ 7ÒѬ&¡6FªQp»ÏbYdmk’)‰vE�9œ„šì�;¼Á·K*iðŠ¥jyøêËDß—¨ô@†ý ¬R&ø I¨†…Ri1¡,Å1,wM" ëòÉØhÒ°¬{‰ÃÚ²” ðŸLÚ4-uæ0�ظ;v"‘QȾ€ïÚÐO0ÑøÜqtbùĦœ»¥ C›¶Ž¼›)ç*‹ðú›U˜©í²ðý»IcÕîÿŒõk¥ìG,“WÿqÓâ Ã¸1p/äQDxê¥&ß÷MÜ »^Õ*ñ¦%·ÐÉ6iϲÎõ’Sñà¥P_iè Ku3"Ü’€/j@†#0qjØ“\7 L­Žm¥§ÉÝðªvFsµM›¿ö.·8]J½eGÏ–0÷Ê•÷¹¸Þ�õ@7ñÈÚÉG>8*éê°B„êÏ.3™N�2r¹ÒS~×Áƒ°²¿Þf^¾]ã@ùC�|“ÑÎUoD’(̹$ùÒQ¿aLoTÉ0ò�õ²q’œ<µß¼ØÙ}úúÄôÕ¬»eî˜`‹Ò‹ä|âñ“¦Mäðí7‡�-õ�À¯±½_ûök�ËmÖQ‡›K’Ū"!yD³¨ü(Ì(o�eåzÒYLm‚7ëTŒ ßþ�c$<’ ?¯Î;4óN\û2S™æ•• ³ƒ’\ü5*&ÅoG_߇1;oAÛBe'wÉÔÁÛëo0ežÄuû!G,@�;æ(‚ƒ„Ò³ †‹nœO`šØlñìÂïüQÎÃñ¥81�¾êª[àQDL1�ö6ÇšHs8ôþè²ÜøŽ™í;—åžØDð@’JFaq­©jÍ6à[Šä·¢á½_öÆZ¬²ç>-¸^ïw�]/¡H™-ÛJ¡A‹jI«?áÐF�ÄÊ;hA£½ûˆ¾vt€¦«RòÙ·ê.©r+›¥Ù�‚õÆÚö+Nj!øœ>1ñÛåMdlUú‚WÏ¥ˆÊõæíædDÞ‰­é�œSBãh³VȰüÚÂP¡4nRámÀô‰x(R`àU Ì2:èü#SÓ i)ÛÆ{ÙÎïáQ¤–Ö � ›ÓZÔa7¶€ˆ4+ Jb�µ¥Dž29«bŽ ¸öxiû²©IMWà6œp¨ÈTŽ™õí4èøMJÎWlV×ߥä1ÙŸ~ŸìWd,-LwÎKM£Ÿ‡“܈Ò!ÀgmqÈÇ$)[9ªøŒ±Üôf$ù_ãä`ÝË]' ÖšëœÙŸ0v¾¦ø ž`ˆåÆ{a� =`Ú,ßÀ`éz 9•¦ò F—';uÊǵƌ}ó´§ÖwŸU(Ø)°¹ßȦ©€ª1¢©Í4 öÁ±Ád<2¼�’yÈ…Jcè£(æjžcÐÍÝàÔh9‹ªúæ¤lµ•áЉB@ùɲ*gõ¬Ô¬1|&ɉhnÃ,E?ü�K©4O‰ÿ9c1W‡å…qÿlµPªlt¯î ä{qêÍíÑrE?óøX½;¯vr¤}›Ýÿ÷wB ÌÍ•ËøÛ[ò#—àÌoa) Û×UW¶7 ;Ó—Kgü Í9ÌÈ`¤4û��·`�˜E('jÙÓ)À�•Õ'‚¼*­4mõ©º…Ì„†'Z+M� M½\´¿I˜MuêèÓÜ,¬ž°$ñ”qŸhßç WÓå|ækܤyÜh“Óv¬"ˆÜθÖ~4¬”†ã†îY¤íÙfîŠH^žæÌöP‘–Ø�—I›}tÚ²PÜ0œôæ¯eFû”õgp)[>O[±¬::¾e?×p¡éé\ªÛû2©6åR£Žüà&„i¦h{´>°*`¥W$®ñŠî› éÒÜ}PÂðÝ×>gŸ‹oøíæ0Ý3t8óžTͳ{Ë?¿�ùågT5”ŠÜ-€l³“Î ÃÕ;k«?Ù¨�¬¶/ÖÃÿ,çžMvd„ùUQ§óÆV—õ‚þ¯i“$±<ímgNy�N/[C§A8˜#õ]ÖÛ†гßdŽ©Ý+a‰¦­4J‘ëµnt�½WIuÑ}KDdmÄÅ L&—Ÿã�‡É72zQF §—@ ²Uo�3ºêHáÆ†Úª”\ÄK<�€¿æ#cô½øS7E�ã,í ˜Ü¨u8ö ÏGú©° ðÏÈWæÏ€#ÃéÆ=¤»7ä§0ë˜vºdag1òïHj^ž V7*% =ݼcÑ>¢•!O±nFdq]TÒ§n‘Æ{^î…¬ÌÞi ]~s¿»·‚úGû 1uÀ@zX_ºôÉßµ~›Üï'‚"h”2UŒÒ€àNùÁ KÁ¤�/íÐÀô'§þÜè�"YŒG—~Ëõ{9TM ’ßVl{a˜ilÙÕëQð0€ÚӎβIùóyQTplÑ{9*¾�Á‹9U³Ê\«Þ_d¥ï`}tC2™ß/Åæ+Lº‹ÿëÛBº×ŒÕm`\ཨ3mA ÙÇ�§‡þ”V§+©N9£Í¤Á[µ*¡ëã�|á>·Ýç›ëú« �v|Õ£:Ò©@Dv ¤gv?›ÇõaÔ¨°ô|—_ÎZΠ= –ÀÒP ®2Å„js”7#m}ÛN^ÇgV+î« P"=ë”^ép`(Ì%Øqµ~ÂÇ ­»g�ôDŽ>¨6âw¿Öô? _VS¼E]�ÌkB3Ä&\Ð&=3®sÌÝ�ËÛåТߎ åzòü0NÞ‘¸rq>Ùƒ-ˆ 1­EË�è>Ù[(€p­½ÝÔ@s¡ô댺ô…#žÚä)�{ršº§ÎÙ:R2X-!µš£ýÔ‘vüdöÒœ©ñÿòÑ5wѼd˜û’rÚ÷ý£ŒòÜÅ@ZþÜž­«øvq05Ú6«%³;ƒfïŸ�2V:÷,¯6Š2+O˜‘WÀÁõøà2ò;baãéK;àCU˾뢽j÷Xö!×ñÇ&60yi¿=E½ÄHéß2ß9�<რ+NŽú’O¸zÔÞUÖ@)7R�Ã-¢ü¯/ä¬ÂÑ 5v€L+Ùòtçoâ"+îΛ’'ži=;H(‡$@ Ô¬¡­M}%(öo$95¶vµöøki@¦öwÝÖñ„d`3�_·±–ãIÈ»|�ÿÆÆÏä «G$n:R#UÐÑg#R+Wî1,ç€-=Oë^üëS/+Fø) {ðåÔÊO‰¸yÁL‚‹9îsoÍäüQhŒ±ò�û¢0>ˆ–’$}#rVØYw«áúBbåN¾$m¡ò®�¸œ9¯Qì&ä§Åú�9˜i8¡YÞÛæp²Q˜§™ñ_ ®p&kÒØ~Ñ�Ñ þ–º…ìì¿„ø‘õƒã*Ç`™ÔP’®+V1þh¹³Vý9ê>+ÏH¯¬J®ñbÇ ±ìA|ƒy’E]û7Øßê }ç‘„Ξë>‹tºØ‘ã¾ö$ä�bûû€AÑp²z÷4uÛÚÔÓ�;1ùPy2jTÊ™+ “N+HúÛñ;ÐÈ弘­È&ε)0›ìÊ«]Î}ï¾ÃãÙDèò…©]ïÓ{ÀºÁ;ÔßÿÃih‹K¸ÄæTÙA¿A L «&² úó�˜.Ä�‹ ÌÅtEÎZn—%)¥‚¡Oâp’ÞÍ@rÎîÂõd$kŽ©¨±"&‘½›‡ùAOW‡C+×È d“�Öç>͈�*:ç~rŸ®o»ªÚo‰bä´½'Üœ;çvy7x™µ•"‡‘(š0Ÿž£gº@a$.‰ò~“ņnœÃ¸€óyÂÏ1N†îë9~]Kyô¼¾w V|$ÆÛ’HÐs¤Èû)§A]B‘*ç`æzï¶«NŸ5Œ!?b‰’Õ…;`»µ_�M@“ŸcœI;�#½Y¼š"µõ ½x90c{w<¼¼nOqÄÙÎ:ói�ÆÙ¼Fi…–L fÛä $„‡0ù7ø5U2\hzkpN&ç[£T-�'gÇWAYR³„õ’–'ýYÔG«4ãpáW±Vç'zõuˆ¹1i«MÑEΪqÿÁ—äé¹´&xœð ˆ J±ú¬§�ïuO~Yw†MMµÄí\ZÃyrƒö’ˆôu*Åüp`ž“ÛÊ¥Z®Ê.1„]Æ+ºê€o}ä¢ [´qŒß„ª™Ã•¬Œ^”yž¹¹­[= ¸ØçiÐk¢(ÑÍž<ÈáÊ{DO· Äï¢QZ ¼/6—ˆ­òÔ¼·ô(…è _±ÿæÙºAö;dó S«„¨îjùÎèâÔ ¾Q\òãllÿîænÙÍÞq2€€©° œ �þ÷A2ñ3œDBë°å»*C™F—aðœ¶�"Í1‡/¿oOALQ}×ÐÌUÊ4Ï%�»£}…Šàå¬ó!ïÃëãK(B[Žÿ5ë¨ü¼`,Ä!Üdüó0™ãž ™ÒûÊŠ·³ëï_Z™ËMܵhAhS€ \�$·‹c^ÛXòÍWMDº²^ £­ªXß¿Àwv>­‰<ª�ê -@]ï<8qû)n{˜]‚½XdÁ"Šÿ¹ßi.G2LKD“Ìn0šiö7LÐË0O>˜¡Z>*> 3R”L„ß•ê¯sXYµ™ª‡:Ÿ×[prÍ* ˜Ru\%à� fY-_.»R2á½b‹ëY.ì·ÕEÍXÞ%N\W¬ŽÏ¸ úŒìºÔPêW)kÈš“UDꊚ¤Ðq}/l6hyÁø{Ï% Wõ©‚Ô\�ÈÖÈ4é¿|°ÄÕ“Më~ ~ãÑÐEPóƒï&å‹F)Y¬åÏD ¶Ùïpa¢¢6®d÷pf/ �± �ÒMüט%Bâã! ÜùúüåÐdA™§–óÏ[ˆ•¦³åÉD©Wó d�WgÛâÙVS¼ùóË·Á߆Âu/mee0MÍò#U¼¯® ¸Ë¨ïp¶&ÅfÞ! §SB¬ë‘Öµ–Qú tZÞÖ½®�ó‘lX,Õ”Çéÿ={>c$,�eî ã÷Ù:é]Ÿ>U˱Ùsû§¹ÇQµ‡ewÁ-u‹³ÎŒFCÑ·Å�õwI¬ ,ö›Wô{ÈlnÅrtü°-wÈû߉‰Úd‹‘"„EâPl\­>YÀðT|�D!^•öôU{B5€Ø#ËQ[3¸LLW·ÜÀÀ#ö®]ü>Ìâ/QÚª6A+¾gÚWbðþ8};!BÍGŽo+TyÈL=�Èô+m® Þ´«'ȉOpB°{¿Š:ÈŠ ÓNit»(!é±õ¦„®´îy~´Êçf€€ „Ÿ"Aò¸|n©qŠ3JŽ]v?|¾K¼ÞÜèQ¢4RºÒ”Lâ‚Þð¥7–ÕéÆ-³ãì’æÈ†+nÔ¹c”t©ŠHúÝEIS4ʪÒ.ôCCU�´RÞ Æav¨ õwªOÄ.rÕ%)œñ�T[ Kª Œ{lØÿˆVj_¿CiØ£‡u©£©MÐôS÷ÉXQl½Xa°Ü›u¡/¶Ö׈^¨7'¹•x>áú´þ<‹$·àt_Ð#‚ËÁÙ¯¯YMŽÌ‰ç!ê¼o‹à:*×âî«Ö¡·Ç|L£¿ßü %°#Cjä³Zm†ÚpæC»Ú¬»‡µC|¾Ô Ùí.÷æÂÐl$—‡œ‡xçÖ¯ª²2<¨Â}@á 6¬õQz›î„ô‘Ny-æ2Þ$ò×W!ýĤTN›¤îBëäØšFý€fX‘+¯wÇ2ÃN':ý˜3 %M}î“ ÙóÐ �’°¬ŒªÈJVK;o^"ïG• ß¸y“7ðŸVŸ¹èKPW¤èŽ¡œ)°B~®ðÁМ«%7·–ô¬J aUÍäh]Ñ¡— šÜµ$lå`§R�¶ù?ĬH!¤nÏvU°í]‚Ööãî ùGajÕâΚŸ-08dI@gï£ *µk[¤í1³—å jå1u#°º«A ÈÓÍ„pMZ¹×'ùØÉ^63|V:+T¶Æ:E‘Ifø½ìAmàlK"Ü®q³¶ß™“¤¢Qpa5+µø•[¢0^)´M¥‰Ò²€kûpŒcD*”¶=)Êë5çøåf™-0ù”+�É‘>@Û,³6Z·¢ºùèþbP¥Èæ íh€üBlúþ­k LB`ä’’[úTRþ-%’ùŸ€6Ù�³¼?\N| 1U!2•‘%Ù¾ G$LKÍ©3Ü*APš�²À`îžÂÒn¬‘EÌÕ÷%Ø�Ãv¡¢n•7 =X]fñ,‚FB2¹ å†Zmž ;ó»jÚÁëžÇ¶†o2Q†=é›ÓUšõâim­¼?êB?üæ]a2®dw‰-pëp>DÙâÉEÐaz“ÂÜBG�ÕÇ ›ÀXÜ?æE4y‘‚4¿YùÃd—•8|LÉ'Ÿ”C’0!c§¶]{<È>" b.u©>t*{²¿ÖˆL%¦Î‘¸’Tå%ï8>þ—ÒEšÀ'Ñ’8þ¶Ú¿O!œ¨Äí¦ÓD<ê4'6Ⱥƒ“´¦ò¸€QÓÛ�8lqÙ3ÆÐôZõG]j ªƒÕZñ#NEV”SC˜|-ÉË 8ö–ù—Pë@©iF9Ä´J㋲¥pPa)3ëõ@Á Êfª"Ô¦CVߪ*±Â~mÏ`¬» ‘ÅJìhî»HºV"±9 Íì~°ü*öU´�Ó¨ �.½ 0}0„ÊüàI~¯¢à#b5J•3Êqa–=,³ñPò=�ÔT”'=ÐXc^ËÈj^þŸ(V‘—ÿÏêŸMð¬:…DåZ|ªkMŸÎQ£0fN´0=˜£­Ù_EÝoóf¥¸¦l8ÐZÙ4yèØæ«Õ?àZÒ˜KO�¹TC)ëv±µ�/ilÍ”~ôSÃcϤ"{¼töºÃ<#Ù î�ŒþÃk ztJˆ�Ê‚]yz ¾Zöv5”žX7/íï°nãrWYξÄx+Î m~h'òò»”cdY2þqzaèż…î6W…–KfCì6ú™ xeŒ#•c²ˆ¦îzßëúÎ µ Pu ÿ“ý=Õ² ^+×ð�9ûOäâKî½�…„Ö˜R ÑÔ¾®:¹d¢‘‹¿-•D»d,¨7Ù‰ˆl®�2ÉŸœ[J:*~v’áhåqîi)ê¿V䣉®2_ »Va‹]MçfÉ46›•:gü³¾ø{¤*ŒÌº®cì,™w‰\Àl¥D¤)ÖáÉ€´ CÆE*nªW"Æ‹rq_]O2‹9ñ.Ï ™”JQ[~|sQóbw3æ#D°fo©éšrPE^[<§Œ‹zíL«£Þ(*Ï’ë €c¶^cö“by ´£dÿ71dž¨µÄ¿mvMqŒi®ôUùŒãQòJß�ÿgã;�ÂjÖ4ó›yºŽz¦%Ç?r¿›æÖB*‡ž¾àÛÞo!Ñ5ƨvwŒµ ŽÔ±‹[áp£€´9V“8±+$Ô¤âúÀPÀ69qót‹¨`õÑáŽ~!„l4óV2å{ –ü²ÿè’*5-ªqŸå °;.dÕ÷ä\ ´áâòªk: ~Z17IÄ*wþÚ}$±E!lTíq*®'×Wm)›�R+0G^”&C€¬w˜êlÜ=S6A¢ô­•Lã„t}gH R�~$f±?’¥=®û"š*'ÒiŸOR_èÓÐJUNvÉ€P§¨«›Oÿ¯#†)¾t³ãºûã õwWn@ &oz\Š‚²Ü? jÛ¶jb­¢Ó].˜Ìg´šZ*£"Øš$Âמñù»ÁD e¤ðtïÓÓÞ‹)#ýy4ÚtMr"håƒúD‘u`)<ºÝ‰@ÌÌY§l¯ŸÅNf¹ÐÂ*€éÝåU¨ÄÚœÏ\ÖiàlªT0†êÞ=Äe�<³Òªë,™ÀPvÐH} ǵßwÇOKc—È™X[ï^“2Øë�‰þù€Çwr` æˆ«ÀàØB9ÿ²/ Ýf= ì(Ek,ôŒ¾Äv}ìÌ{Ÿw6uòšuÒôtŽÇÞnü-Í1'Ÿv™€6þüãRȾK@?O$ì+HOÅ¥Y)VŽo`Õv|òÖl!ú,‡z¾¶(«æÃêöÂkTæË2¨ÇøÀ:ùÚSìÅ™�¤X’^³;úbGOp”¸\ó–ÍŒãG8„œŠïuÖεGN˜/%„|c-ÀÑÙZ ºøt,¤Ã“ÁŽ|ÿpη« •D1ÎøÁ–rAé›Mô]ø¥�T÷&ÄÏßѱF”œîO¤µÚ [¾& „î‡ü±“æÓÿÌõyŒ�>l¯¡•¢È ƒ�ò‡œ·²ä)ži/¨Ùß–ôJ©ÂØ6�P——ù”ûýcÖˆ³ËÄ<ÔÿµùŒTǦµÉ…aTˆÿ¢[[;`‰"Ÿ™~«î¸e 7Yi+£Àïîö D ú +v1‡ØL¤ À¹÷»ÏçÜ0…ùü4VÔÓÁ:/(öÇjÅj1z¢—0·[Qûê7Vý÷(&Ëi Øš¶�±PZèTœNP„ëL¿ßÕ¦˜†ÛƒÁ&îÚ+/Tò�̯:‹æôÝ7•ÔëR‚ˆô}£œWÇ%iÄ”"»¸IjìÑBô”G®Ó�0W³p�î–)3fo<3}jÌÓf"‚/¨f�Œ²’[$ÿ�d,#ù$—п2ÊØ™ˆõݨ4§¯3µæ¢ ùÌÖs¥ùìI*?9XÃè3g_•K ò‘â«=‘)2¸óûÔ�ŒÙܤ:ÛŠç¨|�*ÿv[“iÈ çU¸E|”¿x7ößгv)\£…Ðð¶Ü±H¬úiyÀ úŠôlC�Ôm10j#íõ¡‘hH;tøÆF^•'ç_äƒÄô™ H˜EA&L¤®~ÂbB1÷K®©ë¢˜\m;éà}m²íü˜èQ¡fïÍ¡í¶6þù\ €ªL²JyÅ4æF~Hdl,a=ƒÜê\m>­f­úRþÊ™ÀÎg&²áþ ±¥ý˜ã ·èáÍT .� f­g¦nFüB ŸÙín\À³µÙ;RÚ.XH�cžÅö4÷°àÓfŒ¾ÕTÍRZàö�Sg�lÛ–º’ìß<OYjú�Ï'Ó–±磱¸¼ZR‚.£Èóă‚üÒ:7µ2,Yu/jêÑP›¬˜ž˜ü3A Ê+*Óaµÿ£šñ^2£Du‘Þrìÿ¹µ¯ÓYÄõ–Ô†S",Y‘Æ^àì�ðº&¡el© ~JݹDk‡!dë(Xr°Áƒàù5œâ“3 º9îä5¡D—pWîÂ�Õ_Ó�†oŠ2«$‡õøŠ.ÒyÜ^Ÿm6êGùaúÛd¤>‡ñiÚèE–<”q+ “×]RŸ§?€wˆÄ÷:h¿°·(hÐ5E™®²R��Ä!�}Ž9][ãVcƒ´h‡ð9Øå_¸\õ …OúIq gxåQQoéy:ös`¨­Ý:}LÜüH³lÌÿ€2]?+‹¨/ÄãO &¤YnÛY{ƒ~ªWþ�ÞÄ$-xiIØòGh¹*ë…k.ßm¥#ö2~là;±ºô|â!¦.qçQƒÈì�!Zñ^1£îïÐý§R÷‚C–ðZùµÏïÉO—Ò>îÅ5BMrÀ¥÷ƒ¡˜?‚7 †ñ‹ø^'!ôC$±}ãøi\=îYˆf’&¼z¾ ª1 IF‹�tÍg6êõgA"H–]”„š#¢ü²´÷{1v^ìKÉq³?šH”FåÖA,èåSezÀr~QŽBôZç\3$ê>íã ’WKÝ‹¬Í=<+oP[¿`ºVÞ˜Y“–ð»HLÕlR�›*HÁMÏRò®#kF!,OL"Za�ªOÞ�‰º¬ñÅÈ{Íçɬ/þ‹Ì¼´Dƒ%=X:JSÄ €Ö�¡gêò.c£HUw¤nžÃ¿ýëÆ Å~Ì^žbg‹ö…ИQùB‘c ׿+?=œ¬å/»Žêæ†N[º®0Ž™.ôYàðfÛªÛNE ³?[ÁgeÖ© ¹®¬ 6Œ‘Xî×­Œ[–„ìjžïų:Y¸m™¼ F7¿<E˜, äèè «¹m=4ôe*î}ò=ÐV(s­Öº7Üð6ÃÿµÖXòUœ$ÃBÊ ÐÍÙò±:ì&º2ôõ»~œÃ=Gc¢ÿ�Ù1ã»»Ž@æƒë_Dë› 3cø3!0�Š 8¤ri• WAt“ÁÉúG>ìkwÌBÄ�Àì“Xj >x%ö-–¶~“mÅò‡`a¾þ«^'¦7VmPóȹ· ÌEýï;ˆo_3´eÛ …ÐÃÒ.Ýös1³ân¯Ê¢Ý"‡vò"Á«­�Avp–z÷âÙŠµNñsW,\àN·¶ñ—ð¾Û%µ’‡G„ío ä·¸†9¢bzç" ñ±�tóúíœé/KÑ$\uè‡Ø%ÀÄŽØqN V`gÒva~c�Ñ[ø—£n»ŸÍB™¡<ë¼ΆòÍû}¦ïSÉ4�ýþò›>uJo{­tðÍñÜ(°à„2@$[pÅêb7ªsd®\p±`'Lv¯IìDºëQ `²qsÐ4�®y"¦èDvÇ>,¾ýBð�–�jz½Ÿ¡(I8+õäÜ+[gèÃêÜ6 ˜8¾Ûgf2wã‚ÑõËþ›@°Ã¬i˜öä S-¹_¹­9Q¬Û m &ÒíÝÈ>%dDÀ�Ûête!Öë:@Å(˜÷–ž;-´«p·�¦"¿µ|ûöãí3%à|.Ý^P.ÍEÝÁ/9¢¼Þ¹ Ñ$Çâ "ã=4òÕmäÃ0„щïÉ[KĦÙKæÈ˜Ã±Þ©À,±a/XãÏ&�wª ·cÞbÙ�ü”ùîai•FƒÈË�’àŸÐ¢ƒ‚ãÝ1œ“!.¢ Ï:¤fÜâ³3–˜(UNZ\å)›ZÖgÍ64H°ÀŒ¦ÉòÒ ë­ì¨álÜ=\¬7BÂ=J1¬ÿSá�,U(�Å£ t} 9bÁY%Œžy䈜±±N0ð”«FÞ®ÕJÏCÏêPèA›$ûw§TÕrÈÀ‰qã�•7êÞ=_’N¼ó!Qk!¿BãGÎ=Ím¶+Bjr��5ôØT»µ�`Ä­»‘Rßù0í� ^¶ŽÌT/è3Ô®ÍÉlt®ëBÖ8ÔáE\?NãÌÒÜí¦\'UáÒFÀÒ-~ô+jk’T›ANÍüL†¾¶IOÃKBr4xƒÖiCû Œ‡IHœøÃÓXäKÚc@õ¤Uø s÷¡|Óz¡‡V¬VG†´"+—°Y ›ÞÞmK%=|;=ûD§$ç úÞ¸3HXo‘÷ êpQ)5qÜ–¦[8þ*”c…4Ô{ãÊbxñ1OÖüæk°ÉnºTÉŸ ¹ŒEðÓŸÁ Ñ“ï4÷}˜„"ûlyÕ>à9€#o° & ´ðmr!Ù7O€ûGþëC›f_+Ÿç¥0HÀ§§peþr8Ý)ùy ©Ý-0¶/œçò(OÖŠÏósþ­wßá)û"³%ñÆx6޼øÖð¢:ö\fŒxp·äu8®^õOX•€É�»'Œ}Ìû‚­’V?°hx!fkÓiYôeðŒ!8Ú)n+ôÎÌà� Sí 3¦:צåRF÷µ’�íze«àd4n£$9b °“DcøÜ›VˆñyM+ä?f._)¯Á¹qú×íA)ã-B¨GžÙªûHîXÛ’;wÄ?¢/f·`ì_'Ýíé­jp»~=<׸¿Ú:ÅhCZL‘7¬ò5Â}dTÿµ“@™ŸûjíOÄÖ½©‹&f·f‹¯²8¶ëDOÒÍ'‡¥d[;øÑ¨�·e§»,QçþÇб&>ÚÕ¨$¼a­3¾Àê£CÓ²3JâoÅ(ã®\ò™ßE°•\Óƒ*Ô´œH[©É€—þ#ž½ÄæßQó ¢˜ýMAê/v¥~sC1q}gÑ©†5X@wL)hÖ2+µY'¶Ð3†f à ¢ýêÅu§àJÌ“Ÿ„:ŠšMâ³1�?\)¡g„ì •ià•dÁ¤e „›‚ÅïH�b þåÌRVô†.PXN‰å9öö0à‡|~ žîã€Öb!Àr7š¼±¾÷B¾%Ã@ôM_„Q>à3œæ9KóPVrÇ$ßß H OJå�ðÔ¿”05[ùsœÅ’W<¢xlt4õU‡yd²£â ¤4¹JyŸj{—ª®OÇn§,W²œZôÒ>P1g1aá%PüêÏ›ÝñƒÓþ(]l>‚TÅqò¬XðKþúÀxT¤7–³ Ÿîœ;åÎ…RWY[¨Ñnß;ñwPYqîò»WJ žÝþÃL|¢öMÛÍùÄL½D½±$‡™#Y"vx“!³”9¿æF5Û¡Y!&E»¾Žm˜…äùZôÈ¿ƒÎ´X-Åè, }²VñŒ¦;Ëâ¤jôV d|íX ˜:R9u«ÆíäKÍ9Æ^»)ûÛŽ‹‰a#YjD“Çtä2ªáÙùN8w>¥h›ö^—�q':­,­òò-aª<Ê¥¦Só1»GÙêœááô%µ©¬Ø¡Aèÿ MÎD—‘6lt·¼R§9ᜡ†ª…ÈV$„9šk  Ó}�ŠëG-šµ.émïãñŠÉ�g ½¹³$Wô1½­Áõâõ?i”õilJ{gCü”:/3áh€Aì3Žô™—��*ùGb@§…‚I½f£ÛÜ:òï¸ÊÌf7i…9} ® +@&ý8¨§T”Û4.5ÏãË”NÉ;œÝì.6€¼‰B�7)ï¬E¡¡h;÷SëödÐî‹…ëÿÎ £•WÐŒéß—Õ¬.~Êj`âðÇS¤#åŸwЈ5¬C"Ð @zRZNe.ÄW†ÂHõΞú’RF³2½æÌ'Öºìô““™|�ZoGÔ•I®¦ÿÉX¤qqEÎëS†�¬"ÿx´ÿÔ~šÝd·å¨VÌòM,ñVæÊ1{q¸@U€‡ÄÜ–9åUY#6‡?’¼o)“¶ÛêI{¯ÿãV†Ñn —h§ÌW— Ýs�xï‡�kUÎQñCù ¦8Ùº!ôRª·UNHû?t%‚µ Ç?à_<©OÓ‹‡$ÍÅ×ñov)Å€´µ”äóå9‰aÿe¦‰Tµ×n@K›ïÓ7à£à©ÞŠÖrn]üÚ…‘OW¤Ì¿n#t%jÂ�ÌDûXì‹BÅXrv”Ždxc!4"ªÂeâfÁËRù$/Bzo×”'Ñ,\Þ}—Ìx«¤–ýô޽?2'ûgœã¤Zþôrz#ƒq´yjÒÆfBfÖÞ‘ÌQ«þ•âï1‰ý gÞSJ”³Ú5¹b_†z�Tºû¨ÝÉ\Ó€s´KZi#(!q”¶lRÿüR¾I�ùcè×ìqøqSþ.9NtOŸ%Gº±@î¿3‹€úƒ¤Ó ìP[ÏãûÍ<'€< &¡³ÓG´XHY~lǽh¼eQëàŸøõ×[šY,>Žþ¦ø£ñ¯æ±c…•Ð+K®clŽGsŽßP­$eï€iRéþêi´é+çèZ^1w}ûy2ë[%½±CÏ”¾ë]Š/ÏÌ®‹ƒÊ¡ €ÄfÇí^ÍÕI�1ÚO§˜xñÎA:kD¤!ü¹ê­ÎPV3[í�e}YSZ8ö˜´4™ð}hæÉþ2DªíÛKiÑcGtlGè�r–Ê¡£8v†GÈú ¨Ì6�~Y ô¹ "XªXÔ�.uŠHZyz®|V3…dR‹þܶ( íÛÜXÚù;1™¯%o–¿ðI’QæDVGxéu=ß•¼ŽŽÜêH¢Ixcoàg*âŠTÀ!\çc¤ò-ÎÈ.2"›Í½ˆºãW©)«¿˜ Ï_Â%Oÿüþ°1ûˆæ�·²Àë1fþ’¼U›Ó誱N^Bùæzþ©ç Wo¿èèÁ¬,L»8Ά0Ó³VLíÆc{ˆÎ2&Di ³5Ê¡žÒFòh ›R¶•R¬jþ)Ú× ‚’¢æÎiÁÄ5Iª°þÂòúÀfP§íÊ£´�^$«èê ÖÜ0øg‹¦ðDª§H~ݧ VnŠÿÓÝ‘´Ew¢ò®Âb½Ñþ 3ÊLrûÔ4¦‘ÄÅt–8:›¾ØùÖ±¦jX8N<­1Ö‡“Ð¥aû–YÛ½7YHöÙC9ôOjà¹3!î)*ͪQê�³DZø}ð}—ÒĵÙQi>kJ»Ý£ëóFO y×´¼æËݘ)#Pu?À‹›í7ZJ"EQÔÔé&í$#\Rêø0ÜÖk ñÌ�šWõ§Ñì+àz6&ÔbSRµ46^ή¼†ú„sB$ Øÿ}ø›¦2@]ŸLa�7n§ŒlF’´Á9Z9%·È~ÈnÌ pþ0 „[pÚí_ò)£ÇCâñ½È{2‹7pŒ9áU‚\ßF 5ØR€Ž÷ cReW1ËPåÿçuÿN+£¦?,äwm|J„§Ê µ4Ý] ÇG×Zq[ý´/b©V¨_áD$ò_(q £ŠhÏ´¨Ð’¬×@bþQ¹ñœ\•«ó[ÒU&#�ä¾0ÝÎÙêVñÖbpP«uz]TwF—I�IUš8}9Ä6Öö¾™ŽtË jCŸv3§_ (£Óü÷†¢/ èe2–d�žg³ëH�‹y¾¤ÍÕæØ_œHòœ ý­�á" Ø.Î*À9ÀðÒŽ='­b9Lã…´[sDøZcɆ/¥í—#ýÝ•q¤?.~ Ï›[q$žE.ô—pà³­1úô]ÎèP%¶^SÉMh úÕµè�#Næ‚Äïˆ%�Ý?4u—ç}ÀJ6ÌÖµ™ráä÷>Ku$%R°)È7£ü†T›0äk¦§�¸ÛÇЏ üÑПUÚX?Lo¹ÀhP úX¥n‡h†]ÿµp;(c¦;ñjQFÞÎo»ºfIÿö Â»­Y3e'�¸ïPª"¢æ¼yÄõ‹yÂÂØ£´ý¶jÄóúOÄTžòÓm$‰ÆÌ«.þzŒÁ¬Üf¤ó˜ôfÙEº¹Â«û)H8,+$��‰19bãžÎÔ@ 7íN€ìxÛ&¬“Ê�Õ˜væfÊKµƒ6j¿–”ƒÃQ{Èj–¤ÃEHLõÛ?€Ñ�¹UCp¼Ê¸mý¦¦üjÓzAÍ.�vq[âÇAGÒÿn%·Ä£Å%Ôq•óÞÖmE2P=Åœj´o Z5˜ {{ýÓŤ[‡ÉÚ´dP0ßÀøÝÐNÇCã§¼š€©UÆæÑmKø¿k þ…£  °© Õ-5¼aó�nÁÒðB%ð.ß“$™g ,Íz ïo+®n”S‚@~„ŸvP�´ ˆ7-EØ#áÄvfI#�³½«©H‚[\{UÍ^P1ü «\é¼Ðg $^ìñ½s±ö~Ây²Ÿ+€ÑÞ†Í!Ï›\œ¶<ʺîG0È íõ&¯¿v…U²cŠœ{ [•R$nâçô­ @ù5m¥4ð\Ù¯¬7Ã%Wy³4Ðs)AxëütȺ0$—�èÊ*– EUw¼2‚…Í)7ÝZ†ol}WHìNTÜ÷¬X?æ”Z¾ã0î€ÕþK|¨D‘ðÄÞxᓊI”de^¹¹vƒËiùÿ;@‰Vý~Ðß®Þáóô½yöåP Ql #,; AÜ™ÀK>à�`¾Ó¤6ãÝ'Ž~Åî“eD³�Îã¨ÿ{Ë>øç¹³¡ùÏÜ{ ëmð³Á¿Ó“!›·‘3àÿ�†\>ê¡sðJé¡âãk<úÞüÎOŽ?%Ž\¦ž‰réΕ*$RØ©¡r˜Ê̽v;Pj�»Û4ÜÅÆ‹0¨½�c°¯o”ýEæ4Ü-Ì¥ËD¨Â"!‚8‹(3õÑ –ððkKwj«Èd›a�C¬ü�ìªz�p¾‰bj¬p-0öôe¼€r!Ñâ1Qž�KM)Þ°Ôí]³J„ÕkXw,!á8æiï�;;½7¿éw•—ýì ¢ïµífhZ‚µmýš@)�’ìsSU€*§Ÿ‰WôºÍú. Þg[„­ ÙZ"l�EÎ üŽäØuí5Ã�Ê'Múõþe$,$|ᣢÂÿÈë'yâvžÃt‚ž»ö©ï¦û ³ V“¸! <]û~Ú ò_+Ëít‰ ÔÝ\Â5VÒ„± î¤oK“@e »>ý½�zÖò*Õðt$‰«Çf�RئCCÕ·•ÏaM'Ð.‚þî;Õzm¹�ÁWƒ’³O²ykM’ÀÔ­æíÁ}ÂäcÛ}²TB|(ZÎoGÚ໼±‡¬2+lDW!S6^¤Ë£Dø¨eI¨ÈX½£zÞÿ¯B—ù&fp±b�.ý¸l¢ÙBåùaÂp¯‘˜É‡%ß~(Úï%÷¼VçÉô ¤°J©p��ü|×wº'î@Qè˜,VÐI>´ü©ÜmíÁ»žK‘tÿPønÀÅÛx™˜œs8[]Qz/½~ÿ"?[µ8Æf¢^èt5�£ÇtŒBÌÕ»#«Ô[Я½–ÈràŒ×Ne¨ˆÚÙX{¼oÓÙPªÈrš"_ôå÷ZÜúìWRbj?•¥'§6ÏI=é`’y[=¸íßÏ}g;ñÝcæhÇ1Ët¯óŒ¸Žî’à ŒI"ìdÅôy´E 1<O &c‹2ü2}˜¥ÜRS²C`ÛP’·ÎØïð¿¶ŸRµY-"Ð Í,º)A ¤Xõã ý€sF ¨¹u*žIÀÑ'Ôû§Ö…Ž¢éî¾S}|—;¯ÞêÓ©‘šÚ·+Æÿ¾ â40_•:Ÿ:XA¾“x¬™ÚåRŒ¤h]P¯ÏVGþ“Ø²ÝøÛˆ!ž©«í©Ä ™Jth¾ïùLe¦å6â¹ ¢¿žsoá‘aô«bȽõ-0ûÃöÄíbPYQü �YŸÙ?Stáè1Ðü­óo/öUŸ^Að—$(lq†—j+™klž¸Ôs�žº [¼ºwW+�œa[‡ í©¼5ôZúÅ¢½ÿ¤Qï�¤iXP4>¦û¦og�¢Öy¤èaæRŸ°ø^÷/§BÕá#ªÔnÕ=Š¥ on¡|ü™¾}Ñ‘“GzPÜ|ìJwK�bþqÐ¥ª�£±”ˆ‡v8eñ”›–l›œ§îŸ×ÿpΑI— 6z?ÈÏ1PÀ°Ò‹f}c³¤LàfEâ…h ÍšRý óu²µ-g;~¬ø †6÷Pþbú �·-sÞa6;¦‘ò› {ðoðñ…rÛ L[ž vDá�)(œƒ‚öy�IAµÐ§Ñdy™©2¦2€ê(Ô&ä S ›w]�ð”3ÝÒi‡<­ks2ŒW˜ßu`áaÏéË™Böä,x6²#…‘tN­Q.âûK½Rš¢[5×�ÝÔm�ÁŸÈ‘£ý©·A›Œ)m̹éFTÔJJ]ÄýYvA©ÆAš˜S–ÝÚ£íi�¼¶”U5ÉQÔþ)…UÒ‘èÐ5Îìy$;º~È;ÇXbµE„¸/Rݺù$£r×±|rs*Õ'î3©/Sé¸`ž8ޱX×97;¨¤¢;™ÓóykÃJáдҌåç±ÊDt)U^œ÷†ÅèápNrÂgƸoÄ0àÈí Åyò óÅÞ-?ü† ÍúËG9O'd™¿$EU·稂‚ÌkPÓÉì}@¥ý­s©¥_#TB%Û07Þ€?�ò>ÞQ¦PG„qÞê ÕƒºuR@�™Wõt+áRZr¶Ò ßNÙðÝK7dS\}íTþlôm�(ËRcù¶eË‘nT¯éQjæñoìwÛ»[¤ˆf4¼—G¶¿Ùª‡‘¯¥sèÁosç]À5*ÿo€Yùkfô.§ù˜ Hœ”¨qاCþÉEŽpP’‹Aª²2ÓuÅ«ü¥Úü×»�%¤ðOÐmôž�ìÿHWõTY�T°U ÐkdÐ9xGàÓãLsÝõƒpÖeàH8ºHnµ;ìÏ—yè¬�3 ކhç— Æ•õ¼_ß»ÅýþRÍ×"÷¢+ùh5MâlfùPìqéþIä™/ø0ûàÌEz™Ù’‡*ãÓˆyGUùXêÚR¶SäÊ„1r¬ŸÜŽÃNý4hŠüI É9…?¨Þ®3 òîHÀ:xi�ªi aÍì™Ð ­¶Ž.Õ{ÛmÿFgìùð·AW Þ€3ÄBô×£õÎâª"°q N­™àoÛk�M`ÅëÞn÷®§#‰R¯&.ÙbùO2”ÛݰWYÖ÷Œ�¹Ült%�ø·¦÷\¾êú ¢lejd$"@‘6ÄaÐrVðH+bÀT‚ˆ"¼„æÉ¿ÛÇ8½ŒßY7^â£&%/-ójÚø„9èîÆDÖçm0—¹)zQ_G¡ÓZJ†õbsí~¢Dð]ã’Àȯd³×¡f¶•›·KYî ’ ê¥4ÁÇ™Åå�{ŠŒgˆvTS¼oÍ‘[ÎÝCê²wm¼êÎÄ|ÖtüݳÙ_{ßÐféWµH½Ã üŠdÚînóG‘n a-áòÛÓƒGrŸòëÆ/Šß�®·óqO;Y? å ‘ ºÆÑ;[©�F…Ýõí�ã.kÍ4`–dÜÉ\Œƒè_gÉM«}&UŠ£U7™¢òa¢iø1þÀ0'›‡u®D°=>Z€¢WÚízÓ"ŸS qI8…��Méšò³†äÂØ{Ú,P 1ÒÜ0:ø½Êj¼N ˲¨¿zÍŠLÂp2QÝ—ðžã…׬2Ù�—(^w%Kë±êøœžvåìÙÇCO‰Eí§hÔß@ñ‰Cw&FöÒìa fEoVÌV˜þClmè É’a;ß&älÛ _Küs§g �*Ç&õZØÔi9+|b¥vfu ²a…–ýGõÁaÒé,õüZ�…yYí¹i9•§ÄЏ(YTY÷·bé_Ms—§)QΑ*›ÃB%ŸF5¶ŠçYn*ª-¦Ÿ¼4-’0Ñ~ä…�˜Ù\`·SgórZIܼ– š¡»îŒ e×€SÊévy) ª¿ Ø%º{_8³ªrѤ¹ù<8A¢a®mr0<–±R¨Ø|༠×YyÄ\a±¡;ð>ÉδÌ´Ç¢�œ\åWh6ÍŒí€ãÀº¼ Ý" s¯þ;ÁÍ@Ñà°ÒÄ[ë'¬üÌÒ­�RÛØFËh´g*•-k·P }eIØ zñº/=òëcl;é3 ê,!é@{yÒ 4x‚‡‚ÅùÿŽ$Þ#$úÕøÆ=yn¿Â$Ž”Æ”ÚÚE7 Ív®œ@$¬Àºü½0Ô@Æ�féó§9œczûP?�×ÏÖsjTDbs›±Ôò­­®}˜–@ÃhÎüa ³Vñ€Î�Û»žqiT¦iˆ&ÅÑûç¡6©°÷²‹�÷R°Îël"�·¨££FjüTXgš;Ó«Þ3ÕÅÓWéçcûÆ¿¨‘"Û€³6¼h[ÍZ~°aÃK­ðbS¸{ñä4«LZ“öa·Rºn˜™e© X˪ß›:ÑþIS$}bMí^£Ôad�Žˆ,M ÎØ�8ÄzÕÓ>§„rwõ»VQùœÈ±ŠU'j�Zð?oègeÙZ£œÊ7¡C�øª¿óÚnA@Ԕߞ*˜‹Ë*›¹ë9ÄpØ—J¶Ú,®e÷ðång–mЯkDm²yÏ_�hmNÙÃoV¤B91<�øõ"ê‘&Ðxžf†0€Ýò:ïÍ0î Z�cMŠÔ\‘(#šÎ„c­Wfú>}ñoj¥®‰ËYAîãÃ;!öç2¾gܽB̰ҢרìU]¶üHor·Ï¨Ó°BD]²¥ó rã³G QM?á”ø1šÝu^*9U§òªµA$ëé *ÇKªá\ùÇaœÞNä ÒîyŽ�αøÙµ1™äúè¿�_|Š…¾{¾ �H†­Ÿ#<Êè¼"OÏGñŠ(zGÆ“¹=Œ;M5Ø7ðRÁ~ÈA›šj^[ØåK[ð’Räfb’?œyY ìÑ“?ÍÞà¬-ϸ¡¿ÎFª½DÔ¬v§àáß‚ ¦}¹FO º+M7ÔÄJ>.žrúŠÖÝM1¸t`Z¦• Pš¦9«EnÔ‹šÚß}x©)Û”œ(cÛXcÚ‚�\nÊ`À¤\jìˆ`;|«ÿúw—/´S¢SèÅ¥à÷:™ýF±l®µ«Ã¾ÿ݃6¦ø #£ö|Yµ¦V9qœùm-h+o•Òyæ’ÜúG UNI'Éë}ÐÌ?KÚúíKXIO½ôé¸ç+Ûk/Šíè<÷$1hPç·ã¼ö¡Ìlx}®¸j‘_‰(¹ýT²´| }8s\Hd϶̠„]ÂM'¦úŒ‚í,Àu¿°Ú¬{LƒªÔU kI�è)íj{�T/ qØNyÅpDiÞ½»ž|†Ll±B�j�=b9˜§$iõx˶²ÕJ‰n4ÊÄ|®×Y‹k�XCÜîù,˜7¦Luu‹Àn•%7[ÖH%èTX;<¹ýô3”ŒB¥?(Nê3ŒWIAè¹ÝÂYtÂÄE¬æl_ÛY µóý ,ýV7*$vûc>`# q¦ü?XMöUŽ»£×ëNSÉn«ÏF‘ m!ì¦7`Ub’à¯÷ì}‡a�\õÏq mf;Î@Òçt¾,=ÏÁ)uCôùÒáËûÒnIPµÛº�2ãW³EÒfq®7Ô`ÃJáÐÄ=ã…º1?$hl+Ú%1;�gq¹ô•”N²Ú1\jÿÀZsª@”{¬)qG·I«P¿ý¼ú]“sᣠCåæñe"¼(ÔŒáK�fq½É[}X-aNpH±56(æfœӶܼyÙþ¡^ˆðœÏü9*Úº}—ñzɃgm÷ïeÊ7M0ו_Oö ™<3È3Ù_:·39zS/U}8D?¨lͶd¿É÷¼Tò¤Øü]uº/¸ß§ñ%2¸iS €ƒLZ«\JbóÇä�®@mà þ³Ú Žh>ÒŸY¿‹u'’qÈcÄ+þŒŽÇ½µ‰Û·œ�êÇe�è†ÔAçm>]ÄûÄ?K­Æ 3la½S¤ä&­HÔ"~fñ1†s•™Þk'W·KÜë’§~Ê"IðñaHP§j‡;e«Uðt×D–L#* ïÍ9È¢ƒSÈF ‚ï-xæò&�·ØpÔŠ›¶M…»4�ßZº®±gïŇ4–ULŒø%÷”e¬6\H97…äõÈñÛùŸúÛv~OÙ”Çx„ ÅæÐÃA�Ô½<:-?Ž>ë.ö—úêÃZ½²/…R¢¥ü%¤é!¢“•E CÓÙ“¸_¸_ßß™æefŠžS,…á+¹{ ª­T=R„•6[�߀~'œ–Íû¿"fI?Sôn·÷Ý3Z/Z¤RÖ“fîÃÿXH¯vsI[ÏÊãj¹Ûgæãj0àŠ£/ÿ5ZöÖð›V·Á�ŸèÎR…ðPêpq7€¢“�k…Ò(°ÙÌõ&œžšæ�¿8zAÜó¯4¬�©dÓ(½‚Ã)LPXRýëã [�Q1ìBd1¢8ÞÓ0%¤šaʧž Ox©×}ª•x`ñÓÿNMñéUÁ·g§&>5·°¤Z/zZK~[>T®kyKް¬?uwS�¢ô6Àk yƒÑnzI:zÄkSÖõ óf™ífüõªÐmŸ)Yô‡.ÞsÆ0*Ĺ";.U¿ÊÈ'ºÂiÆTÊZŠzZÅÀÙÏŠónáΖ¦�Öî¡èÊP‘ÁÍãÚ¼x�\c‰˜,žZŽkeÁ·|–†ðI'ZyŒÞ©'›e@3o™î«N•Qf™ÅP=¾­™…òßþD™—LÐêµéï²ãHÀ.AÇhß&`¥9»¹±Ô~ýŸ±�Ø2‚À�|í•f1—³È=†y½`÷bI”C¸üÀBdšš?çÆÃ2îjâ…TnUnq‰ç�G™5p° нCÑ£S9%eW¿¼�?�(ÀéPf‰FÞ”ÆEÙ@4'Ǿ±²‚­í­qLwFÖ’xÚt ‹d)œ³ÌÍBLŠL�,ÿ�æ0Q>Œ ƒ; ƒž¯œM•gûŒµ7þàϲÖÎMXU$­;+¿½¹Õ}¿œ‰*7ˆº’ÿŸ#éð–ì™Ü!8/Ü´=÷ÜNr1þca�’Í‚Peáü  À=Ç=,´…Âzé&ÔÍ >zxêÀ�¹ÔŠ%ÀÍ<÷Â*š–®_¨]zHTðb´8j‚PŸ z”ÿd‹žÜ øRzýTªât!nF{‰ªx“Р괺b¦ˆb`P w•xÒÓ¤aH ‹wî�].þLÑê@žâY˜ P�3~y]¦ôÁ ’þ¬Ø°4𘠸ê;Áp 0¾>†Î;Àf ÎÝ’ C_)š§ÑÅÚNµ£ˆ´oàlÐøíèfº«ÜSö“–bc$ v’¢þ­î@2\òÿùáY^è/‹êów ]6(Nó–¨x€/À8Þ»$p“yÓ&³a,4°>¨ßê—PÅm€T…ýè”b5¤E3á }¿8ZõXOìh¸°é¾iJš Z°­’ì4g³:@"šðŒXw; 󑌕eIcS0‘¿S)yë¡–k²wåŽU·'Ž KBï{D¶•14é=W²ÑÌ�÷£Õt&Â>Lô§a ˆîF'cû&Ð tõ¨)™õo—A; p€9îï¤blݹ;{%u>x%qà’äŸe3)„P뤽ÕÔþ•�üÓb‡™Ó‰¶ÜaÅëuj“—Lã+å¼ÏYÒRœÕ dÒÜëä“Àåç¿ç¦®ñmf=B—’c(àç4“ˆÂLuÌ |—ú¯àÔ�ÑO*ÑG[d’Õ³Ò²RôújÝ% æTFP¹Â§£OÎOB-¬;ªí-ƒoø„¦GH8¹–ûuƙڥòvî+ñdfxQé£Ú#Äà>�èÒL>$y©fô�dW�{Sg”Y¿:\ôeÁé4pˆÈ‰ÂjšÒé$t6eP–"uæ &sÊV­"îüvm«Ò»niFúÜÊÿýg©/y’³ˆ¨ØvÖ¬çÐ šjtôÀsJ[Gµß=3_ú O \Ò oNU®WŽ-ÿœ]†Pg"€yÄüAÐì·ƒ,aôú!¼UçNðAv5ºt¥ 3¼féq<†É«M ÚE•7+Æá $0«£ÿJÍó58Üíb¡ª&ÄD·ª�oP"ÚÒòÂ#‹\)6ƒÆÆác÷Q`øijÊsŽØ;²�³.Æ¡û½0ÈzLijm• ÿÔ™ú‡ª¨k6¥ëÍu°Iއ®/ظ;æ°"D½‰NÖ|ë ¤ï�–Ð�ý­É(‰ßãViÕ~”*ôåßç�6�n)Ük»ץ¾®KéÏé¸úX©£¨V2S„ÄÀÅQ¾f­HÌÅÍ[Ñ’B—ÒÔÎ#7}]ädúq\CJë»°|8ƒ³LÁ“¦EáL—"£yâ^A�#6Ð7ÿÓ ÓWßÞýA/v­ÀÝ·cÐ ˆ‹/Æc¿ýPT‡ßëþ–¾ƒP³•qÃU}O,o÷z؈©½"…¥VŠÔ)ÀH9¥a½ KªÐ¾þEü9•G½¦÷Õ8Cé¾pUÍV R—Y­EHyz*Ë¿3¦d�ÀtæÂüÄL0îPq Ìõ‹¯+Ëͳ*! Ì3Ä·OQVÅ£›­[©6KÃù¬x¢ÙÇÓB’ÕæÉcqq/üw#Ù³Û³`Ê ¢”§6¶ƒ¼|Qm*æ0Ž^% bÃÄZ"ñ�+�¾Ùµ½Ú[âï`r#,§Þßä¬ÄÝ?À(@Zj–¥à¦´&²íóìöB•<=?6ŒñNÔ;ịÆͼ¸ÊÈòù^ßûÚ@Ÿd‡æ-ûjeR:¯=ƒ ®/4Àx®/a\®MdzGŽ[æg'äR¤•µü:fÐà&7Ûn¦/æQ�;¼W;ËÌcÌíñ å\L�#ÿ· rXâ�“·)mÇòq.³ eF<¾�ÝAAþÈèNUcdÁ¤A™íDŠE‘ ë)v¾Ú—ƒ?éÛ‚¹f¤�I0’èçÛÊÄEÝeCxϤŠl1÷´Üú„¾HªóÉ2ñ4—þ{_4ùð¿±HAý×GÞÅýñÇÖŽ+�üb~\L¸û”—g Xùð—øúÕ„A‘'%/X2ëÅ?'¨óå¸g#H¥ÈŒ²�íû;:‡·yâ×CUÞgð[ нÚÔ^›®B±ºVÒl’$x˜[¶ߢ¶¶öÎÞ€åùwrÙ¼û=ñ‹*l¡\Nø¬Éë6x @iV²*©«gl~f ³f¡n„„#¸�àÙNÉ£25>hF„]ûçN‡íQç^{¶ò–Ë—Êš=Y†$¿ƒ5`ÌÎ#ÓÁý ðº=Šï "È<Ëôm\Ü7º'Wåý!Ô@eY$¹_¸õ£ wâ#ÓCrNM4zâ·]é1V°«,çÕq…V±#9}ƾB·YÎCG:t%?‚ýYX>ªù›i 9C^_î]=Úâí¡ñ›'àz�dГ{gÏ>8ì­Æû‘Ç^ËO18ÖeY]Š!(«qÖ‚)ɧŠ_L,í¢‹òqð Ò·)¢YÆ¥*ûêÜoK�‡#L)pOì'¢â»Ô>Ã�ÖŠSHH<�Qûdàí�½<=ýo*™ ”ÉYÐ>°eîe£ À A�ŽÇÁa]ÎÈb�±FLÁ† tÉ�’18êq‚àLÚ7Í#Ÿ™¸¡š�YƒßúËb¸z!¼vœÆÔ[>I�æÓE×Ç×sÅSõr@ïþ×-H™}ñ>�;SòýUUHJÅ�âZÄ` ã1&]þ[”öƒ)…´uñ"Ć(XH�éVýj4|àT\¨†=8RqõÓ=DÞ²A»×ìŽpí)o›H�­�W®¼À\èj2s®ÝÙrwOb0´Ù I©ËJ«ã¤¶Ç´nŽäìÕÅgöâø¨&é ³Ÿ²¤óº2> ©¥`qp‡VIÜst$i¼Ù»H�e,ƒ–·6úRçR1lL ^–Ñ72ˆ÷°VöþQÓFþ+¥º %EC.>áãYŒý#29ôÝçôN8†ØŒ³€Ä"̪b�¸pFÒÖ<’«øÂ*ff´*¬€X[k Þò˜qèVÕ’–,€¦çh‰ŸÈ j…Ò“vþ¾üöá„Pj¬_‰¥Z€,ÕvùGý%R�.z¯�蘴ˆíWr#ßüË8ûËES•QÏLÕ cÀ7][Kñ‡w"£OèÓ@ct}™IbÁd‚(ž²°å}Ùx†�2Qrþéøð1™R»h÷±r×ÃX$*ÙÏ®�oÎu¸àÐò�eõÆ?˜“U¬”¹Z–egFæ‹ÅžÛÿ ôõW,áË}j„X€û?�6þ#?W‡)Ä7@$‚=ˆWMcIe½½ø2¦0"½5„bð3÷L?¶˜½t':FEOÄ™«_n-¸ö.�Pš5Ä2cVŸ¦ X^¢?Ãqxé…ÑÊw�5)ê“ýß]YÜõ×QËféÜ‚tÂO$ÚÁâ¹:õØË¶jÓˆš—ž_¸~–<̦ëu^Åæz�YçŒ ÷3?6œz¡XÆï³¨ž11b?WŒÿ¶68Åd€ÆƒÑØìX½–š„Ô]í°tß(TËgFÖíøópˆ_¹¢3 ‹¿ˆgµ“\9ö¸¼ø)Œ}¼3¦LøYNi<ù×HGÑŠøX#ƒ½0Ó¹Í!¬NsO _*âOζ|Œ²M¬—KvPºèHÜkÅcóà3kVF©Ck#p�zÈ* ' *~œy›ƒ)õS‡‡ÐSPd¬­�×äWû]ÙD„ãn�0ë4T[V¤ 8ŸÍK°1öXáѹb-V䢨¢ �;¼q.;ö�‡Iô¥*šÞ!õ)¨ùrÙ˜¸ôÉ8UN�ì þ}Ð’ynb$ÎÆíIŒö^ÆùÆ P%û8fËïHY®ÌTil6–¯“BÛWØÇ`dîÖK¡ˆÖ ‹‡Hž×öÛûÌ6Kîq>Õ-ì�¼{ô!ÀǰuP[¥/�yAš!ã×ašYŽürG—3Þ#i#ìðüèý{zŸÛ7sͰҿx·‚jm´O.MDç|ýuŸÎY‚%³õ§�ñS9Ó3ªrãÓÕh°3¬½çΊܮã‚`N",ñø2ΉcïƒRl“"¥ëp]mNí¿0ŽN�åJY)Bï$a½ˆ.JÁð-ŒcDÒ°ÜE|2BjNMbαcÞsIzØ=|®Á‡­¯rÅ+Ÿ¾›mÚð6kB…zjÎ ¢4Æt.";ƒÑ>Áb—}A몊¢ÛŸ¾0�J–¬�oá@yw;̇o4p'žïÒº@6”?I0W6Pg†n¬ç;e”‚”QDFÞpÝZ@'•ðuHfž÷2î91H±C¡ ;<ñ­=]`ÖUvçÖEbP ¥ÿ1Ì.¦ ? ­¯Ç›"âyd’0ì3›8•8ñ‰7—óÊõ§ÊJGq·�ÖÊo8šYLØÖ›Nš ‰`sT‰ëC¹˜S¼–Ñù_ ˬ¤ãΞC8q>ŸBÛýÔ‹…èæ’âá{¦†ŽËÝȵ`ÌÔ3öfÄëµPjÕ‘ð‰�:qê:ÎUº­E)LBC7bó£gÂúè®È¶¥>F”¤Ë~÷WÉãªòœ3í ‘©ÿ÷é,^CBLÝ•e•¡_³ÐĦ›8çØ«ûWEOìZ½·½[è¸ápˆ Âö3ÊÀ*Èó=€át£i�qÕ"Ö4û> of3RÁåÁG–Ü”ìîÓH £Ô<G ~ËŠC‡î>`¨¨9x¸!¼Â#ÎÛê_f.²:±éú5Ž4Ø~VÍB(«á'‰ÓÑñˆŒÇfP~¿X+NÖаÈêÔ[/°‘ùîÚ“êDo¹‚0'_é–ý9ÎÄ0y*²…ª;¸¬MnPK"<Æ" ¢TÌÍ•K]TfÛ¡m»’Y,_à@†4¥§û“ÎÁ4÷%¼ª^æ0ì…„‘$x_,À´®èÓ‰«<½®ä_qYÅ–Cà{){ZÙ×ÍdÄdz.ùe>¹‰¦+ÔCy0É÷F ¾d¹òÒø3rTXuqœL ?Öî2ݨ×3í¾¹n¹‡ Á§ìœ«ÈøQ…î©°ëÚʇ0^kuU°M×rß]°6iºŒÿÎ{ƒm|8Bý!Þø8Ç'æþÊ~뤹jbSS€žÔÞ(æð¢ëå!MŽJýHˬŽRiÍGRÛU�áÓ¸Gî� ^Š»‡$+†Å) “�Ð’�ÍÝßÏìÛ®=ó€zàVD¢§ûÕÂÑÂúáãÞAa«¨Í¦rá¶óxYyµ,jPIv–òŠ�‚ƒÇµuökמoFkJ¹´Iá±U¸ý˜íÉ}´Jà7RoÚhë¦Ði¼ÞáHCúÛ… ÷ºWV#Oòmì7´]¦áxâ6 ÝviáPiœèh>$ëÁ4üÙ+ż•DÔz—Ç-4C›ÿ&ò//¿4ó±pÝw1f$ý¨SužTðüj9ÄF‡û.»Ž¦Ÿ9YçT‡¤X÷?#›O8>ª~tBÿÉQvlö­°AL_ Šôªq Rc¡+D¶ ƒ¡ÄiG¡¼& ú�ì 9JcÌ[߀–¦úû‰¤…ö2SEÚh»Îzg€–­”K·ªB­�OŠ ˜ÿ¨pd«˜ÔQûÉfZ•!«G¯ñy÷Ä’/y*ÍøL"=0gýcnZ_3×I·?õWâ:÷�3™x}¬×ÕÝk0�®.Ðq6•­Ù&1]ߨ¦©Ñ™‰'0éäðäø«†w£H°‰‡G‡Äú?Uªu즳÷Û&L$Ñ]å�=Ncžâ¡! ¨<Ûƒ‹3–Å¢!ä§#òþ”“TI6L¹MÞ~§XˆËw©Ø˜�±ÆÀžÏ«)^CHë_&¥lDB2r“þ' —:.[^¯tN™ôˆV“�΃9gW°(Hcm •¢ƒ†ë™ÁX³'e›4©  µTH“61'f»%Qg{åË Y#©·Ç1]½¥ Ã/âCôW}ºÌhÖç²P²mY̨²:6Ø·¨ËßHíñ» ZÃHµn'ÍZàÉåŠj·Âá.ÕwÜ)Ž¥ü©ƒzèÍPyR‘—^)áßz¸vÉAN><ÒÀš+•5I�Õ—j²&ó‘“徆Œ¶Jø4dò°U«¢Üˆ¼[p½ ìs±Á—ÉÆÓ—f Ÿî„ëK4SðŸ‘R‹{,®<îã7glE<ݲ[C tC²žXœdžßZ$ ŠÒ=`‡¤ç~Òj•®íÍLTŸ7¡°‹„Ëdª\Láõ— Hº“�m*3ϸø} »GÉ–ö“û`s2t5”[±ˆý[© ë)…cÝ.�ŒHIB(e?lNF–Èl!—Ø·ÎQ'ÚŸn(�qYÒ… Ñdcíe‘HLüm~�@Ìu;òõó�O“ý‹‡û• ^WÒ4옉OˆÊR··’pèbkœÚ€®@ä9Þaÿ C9~]°Jå Õáü¡Fq¾Ýó£À8Vw�zŸStÚœ¢r$5MÐnúq޹|y°šÝRêüÇ$8¬«Cêžz ° عü¢§ ÓaÕ*×¼ÃÕ%ÃYÈêqÎÈü¶Ê‰÷EõNrž7"¢ÞÈlQqVÉ¥—YN¤º´´üÅ6ª<Œë¦½�Ìõ�1û1—ßJy%ÅÜ V°–ë|¯�&ÿú¡+ªàšÏ3�¸l3¥'Kâ \n7ÿˆ!Šãj€D�”â(Q×Y=ôs¸ˆ9Ÿæ�zc“ö¯p­iÔŒƒ?ݹ¾r®1+g÷ä=Ož}mÔDcŸÖ><À$1F@v½çèjáF­ütÓ�íÁù9e[œ¯–­Ö7­Ä E´n¤£ ˜4ðRêû-¼µ7* Ã�|‹½ËÌ«{&T ‡ý ðj @©ˆtÂà6gÛßd¢ ’Ø&rÕe÷~KwÏö›çª>¼‰¤xì´ì+W//è}o÷|¯#zBUA¨šâ‡ÈRV½2(êkE-ŒÁ p­qInôe!H)Š�¸¿noÕÄ·«F·H Lú¯íd¶íy°rû!ïáïÔWüˆ>èY©õ‚=•Ïtú�鄉¡ñç ©Ý/¯ªëÒ í÷†Å—›uÙðuÚ#ll-~úíYÓ�”ß½Á•ƒ¿�S^Y®X`‰;Ý¿´†1Ú_Ì HÔ3Áòg¬]�˜+õ‚ÎR.tÀ�Û Êå#ægn>÷¤5+ð·7®» ’ß\§�é1ŽQ[0=N U'y ó_Ä-9�ÐæOÔ ÀÇ)Zà„f¢C¶5£¹Ø 퀵šê·g�–é`À&@ßœ¨š"W‹(£Ú¦U±TŽŠÙÌ-Ÿ$þ4~#…8,w»Ñ×í�miPúAㆆ\p?bàD)>w…JRÕ»Û¾Âi°°Œëþ4ËÐè+”40²­ïzD#*¶VµèNJ>º=?Ô£^bP“´ænøt¨¥jnôÁp$[v…¯ÝÜϘ}7ÿœ Æiìµs“úJ_D!±Š;•‘Éü‡Ïf™§-[g‚?Wœga5u_ ƒóbúºÒ ­÷¥ì`âš/^CÜŸ¿\mT[1ÇÏë ç>‚™&]ô�›Y̱ÒS––º�È o­•‡\•#üõŶl‹Á«”õÂoF9_À~ŸØXSd±�ä3HÁy_<ïóºè”˜×e©ÀªC"ØßÚ ÿ¼ô 8Ö„ ¢Ëú±ºN÷`[ƒ�G_q¹¤|Nk•˜˜Ê^Ú!³¡Å†ýÝyŒh4“oðs² ÑI+W¤ŒäHùÿ›«%# •˜>2Á[ ïCáéJÕ Ö#¿Ý•º¶ˆE{§b1Æ5Œ±o½Ô‚Xå>¶l§² מR•Ú‹v¨"ƒ{iÏ(KHR$¼„M.±)¯¼¡5ê`§êhy ¸#Y8úo¹ò,ü2rÊ›�4$jÇ£¼=€Å29\1XÇ`ÚîÚFœqú(¥�µ›ÍÒ»³ô™Ó- O¾ùº/ƒÜ7äïØ5è^Ѐ Ђݾ}0)°ºêùˆÒh‹1úÀ"yäz>ü†�¯kNËÛdAŽ'±høæó;î˜ô¼,�¾»´Q–Ðó;�ùl…1ÿÊÞ»k]uyDjÆR }8‰sQ…êØ;¤)^ ‘³T¹lbÄî_&®¾-x,Çi ª2¦ËŒ«>™c&£ÂPÇ T”(oQ‘À‰ÌX×4Gj jÍ)³ª¢ýÂ,þFS’1ê¹¥ < ÀVD¿ªµÖç7=D02¥ù× íúÉ#ÏëÞ>OcÞØNo{_È~óÙ|Hã~‰å¢!ü:Kl_Ÿ ~ç*RnÊËÄ;—ÖMKo21²­‹r€.‘`*DLvd¬Ê5½¯ÖÊôñÁH®¥ôK”HÙHÈ·ã;%H�–]7ÏßôׯØOñ84øÊf‰ÔqHucE^Ÿ’®tÂ|Å^±üÊVùÐË@Žp{·‡ÏG/4&aÒHÿ‰öYÄUü©’áûÚ(ºÝ� ¾tWô¥ëOWÕ»W5—bÛd�±½/Wv¤¥+ò¢_Ôvœ:A®óNe#;dN�J‘D´„Í"ѳLè oK�.cÝÛ}ö~þ|”švÀXØ%kü«P¾{�xÝú¾iØvG�X“ÔÏË?õR.Œ�Áý‡q&ýì]ñ�4Îà³,÷Ïíƒà#ßzSðÉ@Ù87«·®³ëÚ¨Và:¥ Tø-U”× —E†£v/•Ö‘UC¹ˆŠuÔ”1 ¯äþVGdÌ%þFôÜLÊÒÆØT‹­“Êv‘Hzíl†µ�S¬„0„I`l"aœÉSx™„Fð‡ÒKvßë´Mà!mµ]C|Ù­†7æÓ“Lò,ÛrO™7âç‘.uõ •h8½ž›ló,¯UÌ9Ñ,d.°n79»J-G2€ÌMð>³Jã˜AæC¹µ–þ„â{ßî€݀ǃÉx\¡O|K2gw~Êó�6j­ï6´ÊŠ�]†$\Åžˆ\ÂÓxaR~_eÂGç~ŽP%k&–Í ÊÍ>Ž:øÇÕT°ì*gT¼¹µ´ã}2 ™^…aè¹ÎϽgÍÚ‡fó;>Í®ÛÅ5äÛjkñ&½×éÉ‘pe"3A}Ýý� 5 (ÑQ�”…1ÚZ% �%=­“a")å¿ ÷»ãR…{¯|¯x‚G?«ÀcGHeÇwÄjã!ŸïËû˜{Þê¼ä&†9b'ìKßçùÒÝ6´ô/L�2Ó½rÔÝ _�í²þôÃÇÑÁDX&‘W!t^@‚UWOú¢ú8tK�YŠåz¾?R2¾¬ó‹"¦Þ÷;Âí¦’ª®)ŽEŽ]ó†è¡áÌäøË!J~·1clst@ßuóÆ7f‡ ßÍý˜HláL· S�÷lx`[å‹–¬¥›rù0nO™FOX;¾§²3Ï^TÅØ½£›B‚oúrðû4'�}„¾7˜z©%J) lŠçz³Ó-.Ôé‘ f`ü¹*”Íÿ’«“û_CáÉúB´Æî˜Èx÷[-Ï‹ËÊ•IûÚ~=îÕ€]‘ûŠWýϱ�r��Íû�¾¢{½ SsР¬ï†Ç'W ™Œ¡Á Ã^<ä€Å‡?Ë–ê"«{�Ä`ôö6þŠ3BÕEbÀ„‚EH×YÓXr^r´y6÷-Þ Ž cζ„Ë:/ÜVÖb\Cþ°Ì…ÒV®Xò7~Ñ—ýtÛ@Î#Üõ¦ždT(°:ã"´�æÆÂÄ,‚¤ô*¨¹7À R‘\_Z¹ zäk¡G 5ˆøG©r�/qÜ‹K¢Zá¡ÚÑ],7IB |Ôa„HGædåAÈë<è-?¢ë|ƒÆŠ¬ÁP(ZTÂS�ö�G¾â¶c=/œzÆ8ÐÝjy5]O#7+É]&“ŸìÎÊ ê NÕÌ$óö<ÝE{ÄÑwQØ“çŸíª…™ãÇBGrv©-Éx{�c†½F9Œnf‘{â»À�*�­Í£$”ú>¹Jò3I.v²_ÀE¦¤�Qº¿‚÷ñëb7G}#ˆé/3¹÷žÿâ7ðò^ö @ô¿ÔK”><ÉÎKNÜ´ÚìÎ=0îÚDU`˜­ä†¹ôã…HV 4<Ÿ(å\Õšp×Àeµ>º 8S•µ½’¢ ubÐÇû†ç+�%ŠÍþRE†£aIJ帹˜ߢ³j…(´Ø mýµY>H[iraXÁáßd ùÖ?àö)mùN-Ñé+ÎF{TŸ¥×.#ÚÎø@Žà z8Ï�ìYJ~»ÎY�=Ë&òc©§ÔP|eØÝÆu¯iш?R¯o¤ëÙ��]86ÉzBbÒû`ïx¡+ª9M´ÁŠ(xŸÿS뙈'ÒÛgAí¾‡’»ðÅ®=pʒĹ™šTØ�…3U‰“{��õ†F ^Gâ^û#XÓìÏK¨l��¢�¬g÷·,ñq³� •x:º‹ =‰sJ®Ì&ÎÖ“&2÷8‹Df%òdŸ`ý°„A?ªª/ÿE¶Ÿ<÷•&. |Á7w2Ï-0áøÀòSù0Kž¿.–?Çû@“¨ŸÈ„•=›¤m­ßƒ®�<‘†3  #û>Ô”Q‡UlÚ B9a—žýĦÜ�¿’FµhtŒíØK‚~AκÉù˜�ïÈO`rÆ»ì$°ó;tÚ´ªÄ�Y„FêË)ì¦÷Ý&qÆŽýbùwKtZDÎï[Ov™ÔŸª9SuƬÃ]Œû^ŽÞdYŠ·Gfš¥wVÓnny`:>”,ÛI× ^¿¶C°ë<~£¡s¸‚}“lº–s8ˆ„¼Ãz&ZLð‘ÿšÖù[+õ¼ø²ó V{QãE4´D]q(|ÊœZÆÍU°D­ë»©ãýN\µ3 ñ0Ph”b}Ó½Ã$8À�Et�¸v2iFò¬á‚”\° }’Ç'‚ƒSdBÎ×á®7’Ã/𙙌ë#[ÕêdFÌq¾i,Ô¨_‚ÇÛ¯ÌìAï¹�=¿ÔŒEi ¢Q ß±I�ŸAü[ΛY ÖK«#•Æ’ÌÀNÜàq›ÆáYÛ È56 3¯óè�ê0tt!­`%4ä4¿‘Z`$úJc×BAí™h}y&µ( ñŠ¾Ýžxa•+À¤å@ØÅtR¹�‰(gûЇ^°¡åæjÚr 0Âa™æÀƈ­„bðÙ‰“Û!5ø{ù€}jÚ\n2õoJS}‚Qh¤m¬õÁw?op^)§èý ‚íê!>$U6u5¤Ø°À2Mâ´8Èï‹à%’;‚’—�Aå©»{ä*G¥Ž¥òÓwµïÁnv@‘CX&Re¯R•wjí4lî«TׂâtLQt–Ûí Cð¼3Åý7ÿâÊõ˜Ä‡{'1óÊwž1†ü^ü{#O§6)Tm2–)™Mú½j‚¯#š=ÂÊhpTuTÐ÷ñ^)-}Èæ.êHHáÀž÷Ã]‘WÍcQœ¥õ{È'Ïi©Wž4©\>ß?‚–5 ^Iºp­¿¢ña)¦GH.èãAõ‚}=D¿ç{oå€$íBêÑ¡4 Çäm9°ÌŽÒÞꉙÈ+OFy-¬Æ�%L¸a5î°4â"ÁmL«ôÉ÷ÚDf,3°rªþ°}°Üú‚œ—M³ YUpîPÕ�E§éĤ¶�±ÂØì/ÏÖ¬2À7Pº;xÑh°ª¶X‡rô•Å ü ªD6¼ÌxX­ò¾jUTn[øe™ ²Mä(ÓÅ4•/0?åù³T!^»º~ꃜ·ò“ßµhÙ ÷ѯ«‚fê\¡-. !k–‰;¡«žÁ0Ò¤v\Z¢AM´íÖ–¬úR Û;Ùé9VæÏx*&žF5B@m³[lmƒ�:d´ÔÁsWæ«§ukM½ D}}L5÷e‚C‹YÒŽŒ‰³8CDÐG�ßj¥óâr :ÎÁ¥»Ë­`AÑ.Q$õž?3uå^ zR †þæÃb W˜�C;Sý;¼p€l“Ð\‡ Ø…<øI½¢Š¯”¹½Ãz´‰xr°x‰«aw9‡KÈÚ÷žëæ¨HÔ�Pï%ßTó—ËEš`NÆ:_§˜›Î}b.¯�­ _Åa æ?9Þ¼o#§G @{g¯rð×n¢Ý6�¾¬Z™Óã‰\-û jê\¸,žé“ÒÐ"a¯¨£l¿Ë£v’z½¥ÇL‚j6þ$©úŸZ^Á²óx(ØMðyÒƒ‘Dÿ+Ù¶.çûéq>(sÏY4†f>W‚©ÛÚ�ê¤ýÂJ”é«O¿â'Y´¼Bñ&ÀÈY‘@i‘õã¿Ë*Y�‹}L³2‚Ĥșœ& z;~]ÀT]y>“)Im¦û ‹†®cÃt&/—t¿±!N’¶‚ 4ýac^æAžS*÷Ó÷Ìï=íA¯vO‡KÓݸsÑ$¹ùP�ÈÄax;ìš)±Ö¾KR|v'Uú±#ÔýŠù-l–A,^Õy¨‡¡xààÓNnuȱ÷¹‘×;Ðj>Qç}8[sŽ ‡À+‡M>ÄnÚÆ¹g@›QOX×Ê'¥²à{Ø[ÛyâE¬±H—&�î]Ü�$çaœ7 £�Ñ(Ò»M~‘kæ=Ò¹DmkƹE�}—""äìS78§»‹�!Ø–ÊqçúÏ|’Ÿ#t«’¡`Xõ½ý³zÇ$¾¦�Uµ¹Î¥Áä_©Þ£—PÖt¢ð¨¦óÚYVŒ<ŽGD*¨[hUçm¦@2‚ê­÷çz�É §ýT4ã´FK«8U¤„.Uå\<3öŽŠ‚’rü}4õ$)µ£(ªnÀù{§O Ü΢‚Ž;Wo<¼¸ŒÒ]t>ª¹§P;«q¢ ˜ïø¬zRaÇóQØÃÚãpöx+•¾É�'à/ áv”|¬�‰.,ò0|Ž:MW7CëÒ�—èÔ.ÅÛøäPTÔ]JQ­å’ï�¶÷­`…“Dô ««Ÿôš+'}3¿:•Í—%ÈÅpRlצêô�ÒK["jkU5¯“OZòX#A<þƒHY Î Ð=œýŠÐ‰Í9 ²¶’Ú`{Á‹ýO©!íZû‘޾+ï?¨sƒFÉG&gù×`,*oÅ@×2ïßÿKá\�•ð½Ù:‡#,/Ì݈y" 9lÎÖtåoÈwN3…Ê–D+Ÿ‡iÕ<>´†OɃ1Ò�Dçñyøcçí8P'z>™’h0-/݆J6©º"nÿ25�Q¿ÇSí�.ê2BèÙN î ¦�TŽM ›ÊÀVD ÆW‚[ð.-ŸÐ5aïéö§Á&uÆœ¶p€°‰@!QÀ#5ßó}f r1Áúquɉs�ÈÃɨ…€tÕ¯™0 @º¸â'¹Åz6Ÿ0%j?9eüÅ‘vj7V'º§à3ƒR‹Î5:b®²ê•2f.ŽL8ÝOß>Õ8ÿnW3Y®×Ž ”|4& ‚g¨E#î-°ägZl=»­ ïèàUžuy wD6UxórÓÍÚÅkÓ¾N¼èÕKæàöè¼j©·W<ǘ*4™§Ç¡¾ÆsûZ‚¤F‡H¾mÇF쯔Рî»�E1p/à†ñ±pÔLà’öª²šÃFQNÇv«Jœî­ _òô…ºòH �~62;’8v\jƒr§ò*-±ÉZF�Êkš¨˜}aù§=ò;éÖ,›‹rS†€ù25G¬�²‰ã_;õ]6¸h™¿Ÿûùžµànpꃥ&MÏ™ B*T&üj^s_ÞQ#�²^Qs’Ò™'�îJbÓ¸gºEæÅ`W'Ô}¦m”ƒ¿²Š” ;]WBeW~ýh•â0ÑAÈWQ¥ýÇ•ËVê‰Ö/ývÓaõÉÕ'`oUÄ«Ÿ*:X,�Ë﬚R SDÜ PEF˜¨C(„ŒÚ6ˆ qqØ*)±±�wd¾OîïÜ­®ÙÉ™­¬üñ9¬£Owx[UÒÖ�…ÁÆ6Ñ—æA\0 Š]\@“¾Ej ’|x¶Ì´¶Av¦«9i«õugÂT£ }*í @ÚMYÿ*¡8"þîç’üÐ…{B�‰%•—Âv‹+Ÿ³)ñá_RŠÎa§Ns/ˆ} “"ä¿¥o´Ü«P&!¦Ìqn¿®Tl"› |ÃŒ÷;OónmÚ‰¯uëŠ ƒQâ³J­=ß =ºîRlŽ®šW^O8Æ"d6£àGov ÎdõRiàÁóPHÑo;é»LÇ"R~½ÚöÓ7qègRY˜;P¶Ë¯µë@Nqž·ãÙHª–ý*¤žýBt# ©�#5“#*¡ªŽÚ4†¦%'ƒû dÍ¡¯K)^ŸðH\»¨2û&‚+Ä\7—W†+s©ðà£ן¦JªÁÇLšêšàÙTÂíç£I,p -ób2‚½|"G>£bÏi›=í^·� Ç>\LHn`GÕœqk|#�·¹¢!¸@êØ´xüxÕQl¿ž¿åÅíD”TÓž&«nXa¼ë0=~]øŠ°ûw¿V ò”ðºõ¢Ëð(T/\OË•ËQœÝÍ|•À„it7Œ×zý£Ñ¿ïÔ (¬¯3�ˆ%úÅQ忤ädªšÑÛ sÚ‚Õñú�V½V� b7õ:H\TÝèx¼â}1np�s½8öˆ=Þ�LÛ(¸à˜…}ðŽ®ã^-–Lȧì"mÐr,%úð/i— .ÿ|×µN]'âƒtO°Õõ…DEÑ*ÉCàï•’‰ ÌB‹ ·ÊWì¥~M¥+¡†�fJ2‘Ã+B¾Æ€f±´LýXa»&v1r.ÀHë âWt 0�§�Xçõšã‚OÛ–*Çdð[€âíÌt�h_­½—ñmÔOG³©=óý5•!ñÊÕ(^WîMz�†-à"U. 4ÜË3 ;,eÝ•UIXx´‡.öbŠ”•¡À!rŒÀ1þö­%š�àÂWáõqÊzÎÞŠ ¿ 42†Üõó¯òú[.Í­ŒS–_…êã ;hÜ?2Ø×·-Ïbe(ÃÖ|ÁPi°æ2ˆ&ˆÚ2x ényõÄpø�J‘=ä«yÒJ*´Z‡’Ž(³†çÄZÌ»þ.ÈŽó™õí�‚Ó|F¦št£Ttle —E§…'u ‘ÌéDt±~ÅVÄñÂ3lŒµË ›£À Vá™»³;ðc)ËWƒC7´ZÄõ‡cÂ�Û®ÚvYDSvÂcˆªÂÑÅ¿xqâ¡<ËêÔ¡ïé#CìmB Mãjóz¡ŸMŒ ½n"3C»÷!f2¢kK”£<¸Z·WÊþ‘² &šì¤ oá‘~‘ÍÄ€ôøVÔˆàEµ›²h=P7‘ºË»³öÒ,FñGâ³Q¾ãd Šè&ÃÙјØÝÅ À3n¶ý_+¡@øÇ:ŽÈÈ)ºRµQ]Üá» å Ã’JØŠ±¢S�U_Åák9õÝÃ$32¡-¤PádÒÝMbÀ Ο‡%«/ò·}ë‘Æ4¦ö`Á'ä74í>TÇvƒ¢þ˜”œL„šG˜û�ªû£[FŠ™ÅãÙ'Ïk6÷/:eˆþÙ. ÔO•LÚÿ•0²NK "+�g<39�6ŠÌlºXåûëAœpäœ)"¿E·ƒ9gFgç6øZ3WÌÀÞ.øŠäÙ°æot§"þ0Óï­4¡(ZôCÂû„[½¦íÅfÃôN‘:ÅQD)…þ®§ª-=(ôuÇ]c²+�ý‹$ó&}4—ß*ÀÃ�T1é�U|Ä$+ÄxÔŽo¤X/¹#C[׎•³œÎ8Cã¯ú9ý'žPI';Xúíõ^ÍÈ"?àéxðV�úºŸ42#³œšæ‚ŒÚ­^ßÖ3+Íüá(Ì–¶i{QÔÎz>Ãx\¬•¦µÐƒE|é�5„ –8†Ú6ÏWY†VŒÐ‘Q'Wû€^d'›RÀ^+¬8`çùþ¹¯R ‹8< lŽß-5ó¢çÝÁ`R@K¿»'¨F�)Úó&ä�êÙ³—a<ƒÔ€ê“ 2 ìÐn½ø€CI8[YÇ$_+�ñþ-âJ5Ͼȅ^UÃL–ÍüåçéÖ�4‹?�˜_ëb¾ʃÚ—€]y„ÙúÄÖÔ/û˜=fý0¡ë~É!+cPä6ö…0ä+àÙÿ�BÚ&Ø– åúÍBW›¾7ñ®y�4Œ^:ÕξÒ]^ Çn=“ú̪é�3—‚F·†âƒ@Ç`�z¹�¿a˜CP2c6÷r ¼Êú½ºÕAñ‹V‘¤Jr„õãðn–ÁuØE®A,+ᤘNÂ[üÞ“[ÎSœ&‹h¸úùfÇ,« rM¶D%E±ŽðâJ𕼾ˆ?ÞF2Àà­ËI aWƒ![�à&ˆ°IöÝ�bNà’= ]8ÖúH0i­ÑäºÝ–µº^!øi°…ß¼¹"””ú&ݪ¿wtZØQFæ,a�<`z¼é¯¼�b­9ޱ D5-Ó!Yżð&bYhÆñy$ÄAÝáì'Ùœ±Îö™2®´w*ñkœPy;œíà!¶?™ÓƤÄn¦¥P² óVøØXcÎu�‰ªq"½¦j9ì¹µÆ! nն˨£½7C™ÿdÅ¥±¯¨x4F§�£íqÏ.ÛD1ïü.»bný³q“G˜E+’X;D*? ëâAXë"¤Ký'(ì˜.…mØ|ñ?âØ«ƒ¯F9´u¦Q¸ƒ× ½8uçX1fëî+ Aõåá'Þ^ÞL¿Å}tJµÜüÜ µ_É{%-W(_å¹@zë�ç�ûdÂã^½F>-÷¸§ëW_/ý0©–Ú; °Ô0[Õû ’YòÿºÚäF(=؉g‘옴µÔÿïM0¯Ìhf±WDÁ²Ž&áÛ²T¬g—äùg/ÆÛd%NzÜ ¨Vªÿ懵Ò~fš™ˆè-'©ÞͼkLrY¼%Ô.4™ESBÓµä°bF¥ º…ÀõÊׯE(QdN�SLP½r±›l=(ÉÍš~ÖXùðwÄüÊv©½+—þfžó@ÝïŠ7š.Í�¿·ÂðÆ;cÝí¤d¯Q$ÕI÷·hþö¦Ql ƒHq7üé„ápczä3.S²SèèW»µ1ÊkÏSó]_]`Ïõ9éž$Q_aÿ&]›¥WŸhÖߟ<†¶zåÄYƒ|+:ênnœ„b1íØMãÿ“¬íÃßNÝ6žš™Ÿã0|ê]ÿ–=›³ˆ�¶ŽÜ¾º=¥;� s�­�X^³¡S…”* IŽJ)ÕØ-®8ÝçJÌzl4M`Ýå§¢G'Ü;äÞ)qp‡Y\30ÃÍþ‹è¥er}ûüÓ‹òG{›}‘8 +¶àZ‡ Òhì*Ê�DE¼G�Yâ–;‰²R/EJ5IÌy‰«ê™?ŸÄ˽Ã~ì%&…J³Ç&…{m³Äe5FNÃJ }Efšµx—NÄd(j À¢«¡�§ù¢á…ýõ4à;³¯4tª.hkè£Øx­Œ§þ�5Ý ˆþ4³o[kõ�ÛÏCO}–Ü÷MêøFë¶ÉÏ·Å)"§$`h�«š7Ñß´E­äì�Œ˜KíN¢b]Á&`_òš1ö•�×ROàï\Õ�ß¹L›�/ÜÒ„ÀÌÛòÕ ÿ†×P%õг>å ׿’J(?SŸÏÉS¾øGœ~@ÆI{PPP`ɱ#/z ›:GLSbè¤vÀØúÓWòï`ã:6üê5½Qú™ŠÚÑÜîóü_aâ«È2�F8êQo/¹8'9´O—LѹYÑ _Ô‚)¦^|ã¼Ë'!VK×…Š¿#੾ý–rËäæf-ûÆ)ËÈ–b×� ò4Ñ ž îšy²X‡1�såô;Þ•“%Ø@8‹0Rf„ÑòÒÚz_«ÙItÖb}$ÌB`ZWðÒÌ$�2?ÜìgH‚4jŽ1’SS(Se|h6Á!¬ÚQôÈQ²�0º8òfÜúE•“•€23^ò–«uÃãQù’>²Q]«V³tr"›»› @á™ì_ON°¿ÎX3¾ülÂtF î᱿kš2ÞŸWMïùDªuK©¯|øõÔ^ÏÑ˳ œîµ=¤–ÁOËÂ"¤H„Úh17ª]nù©Ð0\B6ø€“X“6ƒTh¦Ü#gf”¡ГB·'µ_s�·µšÉªQ*ˆ< >Õ%TøqÛÉ™`E/Îh™ñÅ9ö Q¬-=7,¢Wð¹¸ý†æÂ�E)Äjû@ú¯únxx&V÷Óñ—–Õœ Ð_oQ’]Ã�(ÃDØ-ä¤.Ž&ŽG’wžY=è÷öÞ›ŒstÌÌMÿ=¹ø¾À>‘grϤõaX‹Fò‘{ü�%_UêãûnÏLn‚Ê €&KóøKÞ§uøA¹£ƒš!þ9awØ¿�×d¡T�¹ð,¼3Kž,B0,ýDM–7èWÿºÀHq­w‰ÚìWšò´~íÙÄBd9˜ãý�p¹�ÎÛOùEH’è{‰@ ÌË´Fn÷ivG" + ÎLî¡zÓ�ñ™ÃÐ1|»Ɇ�árϺÿêf+ÙãÈtAá.Ïî=¢˜ž‰0G]ñvÍQA&r‚Ž�Xjùj>ÕSÕÌÊP3QKòUí+@¯g î>sN. ![€°(û$¼Vk÷ñþuZŠÍÃ[Z¢š¦ðw¥ú“gY¤Òü�UšJA 0¯Ðû4bWÕ�L‚þâ¦o3&«i˜Â?ßL6µÝ#ͱŒn¥êå?A9 h?iWˆH¨tù§ï<6øS Ó’¾ÄEfIx¸ÏPr—@þÁuð­s6s4{1@Hýu÷æ6Zžô™ÙÊÝâ˜Ï~v�ˆÉú|Ž%Jº»§–¶—¶4¼»4nË)»ž£§@˜Ý‡ÄsÈ÷Tá5=ë›ßò(×,Í‘rÎ9rLº,Â@#FT4º|�¨~£<ݶZî{g^¨›úaŽ«ª¢b ±ȱVh=mSªàa …i_º–¼Õ6ûñ¾Õ6]L†¡b�‘ú^§ðyÿ¦”OÙEB’žðéiZ±£¦ ”ÝIÃmØèï]bÊš ã€èŒoaèJô5w´ºœ„™è4ºùb�¸ô%ÏP¾Bzšék lâjÖ68\E«u˜€Š6‡LÿC^C!qǧ¬! �Ë�`IžÜã�®ZóP®´daÔ 0#0ZÍSWLL H7ï,ÎP”yn¯ÉoÅÆˆ> 儜 séOÎd»šSAÑdƒ|W° |[º²úDÓ`~]š Y�ce•Ês´óÈó²D6fèpèš{ök ïYnЩîØy$MÑöŸ*ÚiÝUG*ËÁh€ö§Új«¨(ƒ™n¥…cOu±(Y³C>CÝ6Ðzð�BjÖ£t¡¸M·ÑK ¿ù¿QS΢=æù)K©²Áøß¬t‘›xA q#ç &ªÜ²ûâPY@ÏöSÌ:z(w3Ü&còU¢.Û úOíY�Òrôý£»- xˆÎ Ë*v˜ÿõ mÇhe­¯ú}‹bÑ®8ÅœTñ©ZýêÓÃK�Q§Ëèì6Ýo íýÓQM±¨ßy†µr�(r]Œ•û1kÌéÒÂ%ÁÆ£c…­àåZ,#n6X›ÄíãU÷Qy›Xz~\aµ<–ùeiئ¬oZýH=2ÇÌžú”ֈĢÏ>û:]�Yä:ç”íðó”ü¸ „Äò©?•Æ7ûx!â£yßSxŠi$½³ìV ~jþwpñ‡& ERW‹sÚõx�¢ �L£© J¤Q„%F¹¢ZèÖà�d’4àÙ]Ú»¬V}3Œ>E@~@S Ïu1”ä/”EåÈ(Úƒç!& hŠúò &ˆŒ”\«­Çl Ï>HúˆT–fÝöÖÛ…–<³ GóbüM! Ž�«:qK}}UZ먒Ùb(‚±ùK¾_"ºmw¯²ím2¶•%3x»Bõ€¬ àØUP6y¬±c´"¥Ùéµ¾Ú1o�v® Ñx„4+ã:oDꘞX�°µ\ð-Äê'°T0Û‚ýq>r˜½Ãöï04lØ+ãÑ?2Õ>Ù€@&&E(CÛ”÷æ)•`·™¥Šé±côµ$"\bÊΜœ¶¹E°€†/ޏ•x®á§´ÐN´pAt>4Œ¼ÔoÒI« —�E  î2¡›¥‚5V”R+Âùv99påɉ^�3j‚-¯ŸßîѬLpÄÜaïj¤U6uËŸ¿u”t’=‰Ö9Kÿ6`}ž]i>Õê;#ÕF‡¬m-¢k˜¢ÑqÿÓ„2ts†#ɰO#š8µÒ$!þ!#…ŠŠÌÉÌ*ö #‰&L)ÿe}‘¦×vm6r®ý!˜e�¯B�H8�/Ëc\Xöjuút>¬iãpã?Àad¯£¹6iôä_€Ìâ€^'l%™ë "I)ƒöÚ˜/Òo®å£Ôªø;dùWÁ™»x¸rE­Á'ªªZñx»¸ß0)z3\&HÈÔÄ«Àf,/ ôŠ'sœpé²h÷=°–Ó™M¦-Ìs=°â5jEÃÚJ5>f4‹­šWc`Ê-þÿÖ|ä^¤ÐXú{눚°”&wØÍ·o–¾µ„~%pB|ô%0ØI’Njʽ�:)¿d |tÍt;ýˆPÍF7ÖÅÄ»wNû½IËvŸ;ÞØ…À=’‚Ekº^y¬–F�­s²“DÂd)Ê ¶ˆUÓ}Gµ\B•´ù4šÿr@€ aþÏg1+é; Ö5Í8ŒB…yTµF[–>ÎVøõf6†8ÙA„î‘`€[ÉôˆXÓÅ}¸‚tY1 Ål™çŽ0P<¢�'1 ]'÷ÀŠIÔ  å)ó÷üèf¤BÄDö’êÓcB½É¶˜FP°ìĽã�^�ª«Ê¸Ù¦OSÍû^.qðêQ�*2z_&MNp¶ñ?­ úö£�ªô’Ž»B•+oXbÔ—A‰6ðü })½ ¸¾Ð)`ìÓàùZC PŸ¾¶ªBwÁ`‡ó;'mÛÒ¤i.Âoaf.*¢ÆÒŠ‚º(‚ÐŒ»¶O�t+•Ë_bÖÀ9¶Èüœ>Ý﫬„uú‘ÙyKöÛ Úßü&�ÌÕ»‡�&J�;l@ÞÃΓ­´™°JžèT¢Ê›ùÅèg¸wˆ O†•Ь*sIÌŸäÑrPª™ÚØ1à øŸ«Œ²Î,�Éà/iªÌ”G_C•"Y7ye®ØKƒE„9‹O †M1Tb…ÍõÁá0ý6Û#Lv’Õ‘OÓëÕõȹ±c®Ú¬BêˆÆ™Qrìz.TŠIIE¹Z§´Ìi¶Â^Q�s—BN~Î#:Æß³gji@Rë) ª°<ªWy©ÜÜÍÂÞZx) D\k¿ŒkrÍ`ÚqØŠ Ûm£�ÔRYåÈ—„…áöÎ@¸{~µB�O~”'µôƒÇŸŠŒOü-ûíÂÞ1&…Û15ßÂKA›z7Xz:Ò‰ÿâgq<“˜xÂðRåíP nX­$9<öækšæêÆÅïl£ô·G�îŽwÞ_ ^ÈØRÂDBÑ ·›�©”#œ5/l‰)D Z:T„½4 o—D‘�œ’y­<ó»gÓ¾†oi[•±½"»Úé%C#|jþ´Móôœ!¢¬YNíºuG\fO€%&�|»ú3(‹Ëìn)v$GWO:ŒÙXÜ[„©Z>ì­œvúÄ€,æ9(<2T¦Ó§[º.ãÖʼn¾!ÆÙ²À´é0—†,“€J›jŒ7-×R�nd8Hç¶ ÉEPW¡‚fhàq)‰•Bg>À�·8bwHXï„k êD;x¥U0¦Ä»«3dìl ˆ§½SÇsd.a©Ž�Ôf=,38‰ð·ÞÞ’ÔÝ„(¬Æn ’ _ ØVeìér~O�¦©éu?Õô[§í£µ8bY¹‰ÞVðE3å¿èÕÜ”ï¾ÀSzÈ—¹áЕèÌgŽÙGˆ­•PÇøABBûú¤â�–$Ù6€ËÁ°$䦬ýäcªV#UÖT…šoÓhn³Iz—Ø5êoqÿŇ;ÇUå¥'`xìŠÌÉ×ÃÄ�’,=Ý‘ä¤fó Ý°ßïœÌ£á^—7‹YäR°…ï>,áä±CjyKŽv>‹¸459%+Ñ[Ê5Ón®Sá ¡Ô€É#Ë81À£† LxÀŸØZ‘òZ¢ñû徕å÷oneYºdÒªÞˆ^—%èñKUØÄYÁZS¹Æ|‚zŒeCƒJð)œÀ[ÄpT(Ç@ßÍ »uEËzj¾n\?ÊG†Ö‰am¨oû LzÊ$°®KÉ 9¨‚ýJÔ(vü½˜&Cc¯fuÉxñä+¥óê(ŽW ó°EQuܤ¨5LÕmr®\…~cù­å0w¬® vôúÐÇÃiìZ> .œ×zû“ið^kX\ŒRÆ8¶Ù0Ô¿Â�P¹@¸qÇ]Ž 7ðpj=Ò· �–™;*ÿº43nZÍ }ýݶrze‹ÿÉ +ÀîOA_ÉæI ì¢(Õ.†O¡é9þtÀÅ9íšFÀ·Í(¬ûæ§M=Åð<5LÊ?¡¤-ɱš}¼�n�ÿÛ}7üÊy‚‡’lW²3Cuø<�rñXCeÊÙŒ¼‡¾?®ZMC|Êk" •[²�‰Ž%ƒÞAŒpýêDK5 ´ëw}Ä¥ŒV0æÍågo_æ„Kár¨¥èÕ’ŸSE6¨ºmÄé”l®›`ˆ8"PÇ7â?ÕpÜ^gæd”RÃÔú¢¯I24Þ )ç2âÚ¦$‚º�Êk8,ÅJôýßþ\ŸÓÙÔ°+â—Ò'>}>ÔAšõ½¬}ˆ,Å4FE�"ؤ±Rd{'Ï»…ÄÕ@,Dû•ÖVžódc–AŒMš Z9NÉÈ؅o9\çŒã¦3Ýî—Z.ûï’Æd¯,VQa$À›pyë=ã©yíÌû2ý‡6³w‚YæAÈÒÍ5rgðSÖáÐ# ÙfÔ¶à� 32t2N$LÀò*Q+o¨ˆqÑD¶—1”öà(0¶68|¼C†Óœ'_)ôô¤$¤»qbÐbpKDDÏmv˜–Ì>2×ÈXòÁOöwvåK”ñ7O_È†ÈØf¹k¸‰eÛ@�Ѝ©6¸aÿMâÐ’òoÖŒ¶c©@sI4M\5©NLT<OilÇžmE^£qô]Ñ5¬Šz®ýìs‰LOx鮂”7‰ã;)˜iا—Îi¢ÝRØe‰°)ÒJ$νN|°�“ö�G¾â¾ ž& çsÅCGhQ¿ïŠø­K„ƒ ù­¹À¡Yí»]¶¿äÃâ'ßcwð®�Ä©îξ,€"dÈ3T&¸кü®uP†�áõŠO� æDË_N WƒÐï ÇÛ™Ô\CøºÛU`T&‚ÿyÁîãa /»ïF/^YÙìËÑúÕT±®S@Ò`wtôjO"i®N¥â÷½# 0F’/Èy ö%p§Ÿ6»¬³hëLñΫÿ?`Æ#Âv"t�z· ½­�b`€DP³y0oÚ4Y„Ú€m¨� y'ê ª÷Lö“Èú„ñM¹=VOã1.]c0 Xò0^¶©´+¥–Ëš°õµBu}MŒ(uÙ½CÐ X|‹ !ˆ|‹ ‚*ÌÀgwRêˆôS׋¦×Pk+w¸A'ìůSÖ)ÖþÔ«lö‘9@–“éù+y;)”Íó`pöÇëõL>Уׅ5år+¥¾El‹"ôY FÃf¯€¼ÿÇË€Y۟ᨠ)°|"í3·d(ä5sDÃ`#AM©Ž7Nq¢¨‰Ô¹:«õ¹.ÏÎ ©¦5ÈS4ÔoIš¿8¶�Í©AðÌè&{ýs¬Þ—ªb&�·¿,J‹¢2¸Öîw¹Ð(ûU{É]a fÝ~�|jp•ø�túëk-Ï�—'3{öÑ/õå§\J;øHøžïcë’u}’08ï×ùŠ“yçr¡C&Ò($!†zº†ŸL³i•ÐwÆÙNY›NG=ØØNÍ5Héì?H½K Êžc<ÉþÖŽB¹¤øòT¯[h{^±è»%¬6§Â±þkjתZŸQÕ‘„½(v_ Æ�õÇ?6œˆü¨­ù.�œËNŒÔµÒ®..=`å.ñòÇÈl*´y‚c�c³&ç@› gMí?3{ºçíuÙQHæ+±øÔˆ¡Uy¤ûš. 2à¼q}¦Ë‚�µpÑèš<¼&w/Ž2Á5i@+gçtNn4;8Ö]¸”íŒüTþù’©¦Y 1xM‘lRæu›zLÁ¦vé¬CQò¯¤¹¯«°O4â‡úóI0éU>¦ŽÁ  ;’êµUªs4t#ÆÔêd$¾™‰Ou €Ž5Žv:OJ"©S3ÒoÜ+. FùQ´¬^†l‘…è<­³ÍÏ×/ –Ôÿ"4ëÉk,>„À�§É’ùÓ&NŸ·±¡~�® ™zk¶ÖW5H NóR1åê¿ÕÔÌO�¿#Õ‹[)ˆG£:®$Uo�7+IŸ„FÈ‹Ä;lË@¸¯.ÎUd�Œ!­® ã·(‡¤¿¯¼¦`dùõaÕHVÁ¾) EünÃnI¹¡ô¦‰¡ƒ¢½@ i/YqÏt $ zˆ€N&}ÉPë2†t½"Âà71"9«!‹VLÌ�øÿt¨‹\ÚpRk¸ àà óõMÏ/¦þØ8|$g{‘Pç ïèîæ3B1ªé5+w…S±¥o£I"sM�g¨ÉL^oÍMLÏ)Üãthûæ’ ‰§Ü¬ƒYHã;¸Ë†rz\þ~!`†Ž/ gþ»̈́ڭ#ù²qù9à5Ÿ0½ùù”Fý,Om(ÚƒI<›æ.`�÷{ð=…bøÕ�ßC_&ǵe�óº¸X)H}ŠÀªéÑž¨ZñûÐ䣈ÕòÂú †`Ö�鎖ªé�¯—_PHžåÙt*n� çq˜‹PƒæRAñM+«eNöõ :ÿ&!.©jŒ^b~ˆç½vÀx+™¨Àò�?Sv>žV ¨é3m¢NŽäÁq”míÑ1 OÌì1üK£ÃÅ`ìþåI’Ÿè¨9¿¶6—‘¤)ÆEçvbú ûäYPúÒë‘ÕA¬¸ôð<@\r+$œ–³_N Ï�â%ø/£ÆìrÝüÊÒy`›0© /R*Y`Ür�ñµRÈyè ‰eyon �y¸>?Û`lýCuîÖ ›Þ`ý ØáýdçnG&S—ñž¥ù£œÔ½;ÙwؼßÉáí©Ïíçlˆª/Z£pÔÁ–æšc”á® Ckk]á}i•‚�&¯ØÂ. Ž@Þö®OÖJ×Ú ~øý­Ë ÿ²¥~_מ$ïPat¾D(ZjÞÓåÃÛšwq‚—þ6œîöKØÐÅ5qU랣$3±r;vTÕSxe’k&-§´P�,]Ñ/zEFTã°Qg’³LRd¿ý0a?ª8òwìÉvêª(,庇Q2šPÀ$�à(Š¢ÈQP»èâê–fC âqÿ ìÌeàèÂý“5PŸn;V(ʹÅ~ƒƒ'‡x•7Ÿ•œ \hvz×àC|ñÙ3‡Yq—e™Ó¼�#$\ÿŒÚÚà0ØèùDî³[\A‡ª©�å¸Jƒ;*º±ÄïüIêZwNtÙ§îüÄ‹jçC[;ÿL]/ aï�ô¤væ€.§çŽ4�a vh Q@"íθÅösÔØÜÐ "…o¯"ûûÄÍkøDÚ;AÊ�þ—j`•ÝÓð¨&€¾ß#5ëf¡NHaÉY£•w©¢.ÁY77ˆl YDs@~:¨²ÀH ÿÆtµ‹û[œ³J‡Ê¹4&1›¹‹F˜8r›C?¨�IËã½²4òi®ã�ó{øU šÐ_=³îÿéH”q‘äŸr…èVRñ·Þÿ7‰s TVXÌ-¥‚•ô E:+4m](�ãL,>i¾Ï ‰—ñ–«õ ¼î-¼�IvŸu³£ZM°&É7Œ•ÛBªÎw°,wÔ'zJϧGååW_�N!Ô¼âI¬ÏU²2�tF gúÕù\$ŽbKKÍr:»K�º^š}‡0`;0�cEsò‡¾†/ãÈÇ›0¥ÆhD§ žõŽ�Á; 8ö*=­ÂL½w ."Nø#FÛi·@Y í²¡PþgJÛöiÍUç�_ã÷ ZÊqnûÕCK(ÙžÚÂ5l#ˆ‚ÓF¡(=mo‡S•7g g¾=,Y í õ�Í'Ói ©SEâ{è·D~ÏwN&Ù#QŸ¨'Ñ„yœ�um0Í¿æ”9®qÔ¯’ϯÑ5¶÷çwfQ‡ÔÌ,‘¹ÞÚÓÎ}uK;¶ ¡5KvÇV;‹N»H3“¡§Î‰mïwŸ}ÿº ôb `É'vǘœ}ú¿š7Ymg˜ ëqÜBjG¶T(†:PÕ¨Žƒ‰2=^å™oë‘d¾#šÝ‚WΉ…’±"©<~#GQÉYžväfTæ•:þ˜} hXV"*’}ºäV­}t ˆo¨l#¬ópP"’ˆE¬&°ùŒüéy›ïZ�}ž�ð,0U&çÑ¡ ê#m¿è.Æ1¨ö©þü““hŒޝò )~´í-%™ÅÓÿN;Ûi# ‰Þ­¬™~•¸Øgv¡ú¿ï­Ê6Çi£›PèÖ'BzD¦è‚ãA; �]fÖrQ�3ù# ‰ñX–K£}x*V_˜¼å@9_ÿ]ß3aðAà£X°lˆ’ð×NPì�…4°å'ê°Œ½9¸R)R™1L¬¥@—±JM3µÃ¼ylKR#Ó2‰1(E›‘j­¿¯*Ñ´J=Ö;ÞlÍÔ&ÚDŒg=É䉮¦½Ï&@=Uùø0n]¾&”enp-2Ç®/ÿª{BPe¼4n4ïOSÒ‚Ð9 uìF]Æ6I{Qk­¹9ÃÃÝܳ‹OL'O¥á Ë n­ß!“›ºè€sQžL—`XSßÔU�ù×àf%nbþa[>±ÙÜ•!‰á…ƒ¾¸�¸äápáÍ0|´Ý§…N°ô,o�ÄW)È5�»Ñ¾áª¤ïºA·ÖïþŒ p+ðØ?‹|ÑeÅ oIbrsøù¥Š‰8óç§· s–>1R è>—›öûó¡"^úÞãk‹a±Jë ZoÍH*I%þZW0»*30“•ÉÆµ)ZD�' b°•~(JêLã{‹gHê ‰�ÔÅeÞ 2`#÷e‘%¹èÙŽ•ÒÐ ”5Á?”ÖòÁº÷ 6²‡z[å¬>È‹.Ѻ<û .î[Cý®wTC‹‘¼uG¡îA SzÏIzðlª¿¸g+ýþ>T xÌÎ|Odצ`´²/=ïëŸéÅù§œãBC•pE]ih|Ät"˜3¸Iý`….êÛìbàï.A…w1AmU–ºÞN^u Þ.3¬¾ìqÁq|ï›ä±õ�v“*ª¡®â]üŒãeg~gä”1Õ¹S‡;n[¹gÞJr[€—÷ØÈîn •ëiVl²sÎZ sÉ[†0rs4vî á¢îI#¸¨Ôßë§%<ÛfâšL(ƒÏ'êÚNg}Ñíö3ÌëÜÆGxBx Pm+^eN¨¹ßImf9y­Iéý€Ð Rµsf{*åŸ|sKaþ$_ÂÓü{2d¹÷MéG•WEÀ$‚5 ù]†MŸa$‰b†F¸;gÖV\áÿ”W¡¯Ô#XüUU�Sn8·�ÙJ¸‰~É,^guœøPý>Ë‹½XÌÓ`'ó§¼²‰•ÖB'èR£´îDPÌ7­-±Åaœ®CWM�°ÁÙÎ|Ú0T"íEœj¨@|u�ÍH¿'kUÊ¿ÏM0¼Aˆé»c°ã}"˜o§�1ꉙK‰ïE= §^tóàÚ´�G¿‰)JP¹Éå<Àßøà^õ‘fH¬«ŒYŒ("Šå«QìÔ¢fí$â“…h¸o€&˜?Ù*àK%‚ysvþ†¨ÓÜ/êߊ�?;äAsµ™¡›k÷¿F?e®óV‡Bû³r¿ï\æ�¥ÑÖ—ºó•×ÚÚ£!"Ê&=¨ƒñ©^m·V¯÷ÚҲѩIÛ ES9CK‘ånCqCŒ‹ªQjÿs·Z’ë¸è§ï¸)Á7ðùÛDGl»©Ë+‡Švʨ:áãkmaÇn¡ LfŽb`yè¿—„ë©¥vHŠ‘ÒÞO� Ò«3þº%è»;÷ž¶ëŸ)º¡ÀR`œ·¿Ö€Ç\¸EE݃S%ÉU6ó…¨iC/¥8§ÃáT7dó†HZow¦7f½Ô"„2Zö5N‡€þ7)ÖH~³;*‡�ÖD¾FáRü‚…Li«9èXEhʃËy6Æä¶Ð;cúû¿o¢PÀxÝâ‹€ýqë£Ú•Œ¨UbCº� 3økèâë¹;£²£™ P ĦO‹zV.=œn�¶þ` Añgóy­¯•L'ùÙ#k`[&¿°>”ԚœîœÚ¼m„X¬úV”n†ÈRXÊ�–w57Kbñ/¤T©üÆû×€ïI&U„t¡*mŠzzöÙôR¸¬kÒ‡Mà'[™�üný€�V1sPB©Ü°ò¾<ü,œ‹ˆ~ª@Zˆ£ ÌüaR N=ŸÞ.p ¹ ’¹î¿^øÑ"ãë‘ÀÃ÷:T:¼ù�­¾%ú!yY¹˜ öAÔaÇ7ëõ6ê€�Goô¶àÞN Í?‹4¶Œu†!Àç+Ð¥yÀ¤XqwØót:l¬Y´Ù(U=£ /Ê=¿íI£�Z׬—uŠŠS ÀRÉÞÈ{­ÀÖõÇõgK·Äo»Ò·Œº1]€’.K(‰bñTµÚ‹È.h{’ü‡„RñGíYï¹å¡ô&l¦Ê†DÙ}GÒ ÞäS⢄ö¯Áù›O Q70ôª*”€ï(tV2Ým�0A)4\DÛÁ$d²:Û‹£úožPBX–=ú”t—yø&$òÃÔŸEptÊ 2“ö#­êè‰Q}¦Âë‰(S–qùt9‰¾i…¤²XQ¿ý8ãk!ÓY‘ج¹ðTjxR\bƒ#5iÙã%-—#×éi|䟺†æ˜‘í’õç†Ó,Þîó–3O¢Ìz'n–¹[[¥WÌÒ¬p,‘¡•þäÿûK9C§í•ºC*„ªÚ=�ÉØÝ;ž´ëK1Ãò*ç¨"›ÁU™f!š²)­3}ÖÜÜ×WÓ}«¤ñË­0 ó`�¾º|[ã…]C“.d>Œ‰ï¶Pž½t½6ú}&”šh¥8;zZ³²Ç 8ßÈ«H¶‹ÄU3žDâ¿},vŸû¾/«Y…ü$¬1õ¹ø8|ÏäL¸Ÿ,ȇ ;U úã�’NÍÅçÓJì,ú¯DV=Ej‘ Öw¬cº5*ˆöÑáŸjðW >]ïÛ"�Ê™ìÈ,¥vEW¯§$R$T5,¦®²é¸¼9ÞèGR4” í`ƪe� äËš–¡ _ò¼µà# å>D±tý¿z¨ú³+šÉ'ðeÏ�s�ï/Œ·Lkwd„`ûAU|Ѻ�ÞØôKƒÚÂ+Ù\Òù]“Q>«áœß»ÖòA1ô¯1ý¤¨¨â ÒÕ#[Æ;“‡IŒÔÕ–A’5×w¥ÏÔ;ŒÖc9:�Y›MÚ6Ç;ÝMšŸ9z‰®éoöx‡Ó.,vâ±wnÎ}¦% OMëX 7šm‡¬sdŠœR.ˆ2Mòëâ5è~mÊvÁ]žÆŸX£)ÑØše¢Q¼v ªÚË$s8z¸Üuç¯3`-yÖ�‚þ$›ûsÔ¬ºÑC"W¸Aø³³|RéÎ{´4ËÑ„ü)ÀZDÈO×y-Ò.4]ˆFŸëZ‹z{Á-/£õ�%‰»å)Ï¡<š‰Âž&ÁT¡?]§8²l+¢‡c„š¿Ö®â”ÆóôxJSÛ ´²DØÓZ‚à·zæª_6�²P6ó;~¦ø¨ºo¥å„�ºcÊk $׃¢Mó‰�‹±ãaÔxU9zΪšDŸ©Ëò9Ôìw�­UÓrä>¶�¤SfdXZ–É -S•¹‡Ìç£Â0ÓJ4je€ëÙÒj‚æ³ ú»ž¸•4µ>™örëÿ8lߎ —Ü�Éû*æËvéÑ?f‰ ÙxùŸ ÂR(ct\R³iÒ¼Ï]ªßqÂù5ôcäšÓ”ç#�aaÅ…ð0[aÔš8¬v¬MôÕM礚àÐ[«u·‚aÙŽñd7SþÜKòTÃà)ÁgÂ:™+‹ôøÞ~çuôö0äÙRNE»^ù¸µ¶KÇÿQ¹°'•›“ùDüç PÎð·‰ah;�îô�‚«Ýé–B«È�O=í@Ÿˆ4–7ÄÍc4aˆ±(A²¼{ž°eWçáè*Æ·ŽÝ¿‰ÇŽb1îN6‰…à”ßcåd%ù­�� üðØB�à©*Ày¢#Ü´«i'FH�k>Ôš€è½Ý†…ߺ‘b\Yéoîb°”�5Æçf}Ëš2�PœçQMztäPª’ióÎL®â'Ìx:�Fá󅦪öVÚŠc ÝÊE¢*nvû‘�â¿èD|9]:p¢¬Jgo`YçÐ[Yá¿Î |%»Ó'ž X•åñ-Qˆp¿P[¿>[$ˆ�ÒþÛùå(b¶‘58ßëgõýŠW‘¤-´Ÿæµös4ŽÞÒ õç:\PrŽœ$El}*£Éç~÷ åâHÆ@‰ñ ÚU-Ö–ÿx‚i×}š)]ÎTU±õ™kÖxò!’½  ÌÔ2ÜÑeÃbnsm¹~°;Ù\é×`réxäRZRyÛô7øÃŽXª²ëF™b×hXh„—ù]›’µNt<íþ‹ë+{û…œï�“˜wi¨¯úJ&¦ºA:Æ„b=âÔ¹$6�¸çéÈž€öGõ–ÝóñbPøx™¹ ©³´ô$ůxOs½L æSúwwY…lg�zn´Õ*dò j�¿aZdÓCýC"gÐ�›°Æ;¡ã×fŸ®D·djá è$Dy¼þ»#í(ÊsøÈ2³D�§”Ú }¼f´ca’,¨ÙÌ"—§O÷ÃÓ†ÙTˆ•^ùÄ—ú]�‹š´Zœ)+´†Ò¢rG¸¦dmOOê^ïØ+ô¬Š$aP�O£tÏ4 ìWÁòÕß´@%§0 -½#äwB>‘(ÏstѼøòªæç:j†R³®1O’¤ÃfÎáVe.ü…¦]ïÏ«¿¥½B˃,ü]&m6‹Bœ!gØŸ«j–™úMhieœ²–)‚R#yùy¡ zÔiÓ1úÔvGÑáÄÞM»ÚŒs�b‘tü˜þ¬~-¾Øsô,Òþðµ÷ßúÖ@ÎN�ņßßðÑ!½GÇgÇ0{)€Õ°ÞÕ_Ò[¾%ôrœDz7Däy Ü•i\V&3Æ3Apl€ äG’4ƒ«¬ûži¯—T, Â�|Ÿ�Ö^L1§�Dkè¼ÁÇpãNœ’þJÂ$ô½œý”œ|_ Â{êÍÍ¥Å+/«ò2Ž{kúyÖ &§‰³3O èsƒU»P{HÙçNü%¯RÞ¤Øn³+Ÿîj6ÃÚaz/:íòcë˜Üô‘nÏ9‹få›å›ùj1,ŸÀ ­ºdçœÐ½ˆc‚ì FšÑÚz”ãý–†V;'! l@ t¬Ž@¹ ÏMþ”ÀÇwªÂ¡ÓßxËü¾å[[ªFwñÚ¿áe F¾Ý–¾²·‰ÐÌrÌHô/„ñ‰.M6ÛÖôàÈGÉy‡èëã4#ŠsÇÏÄ­ˆ¥Å@@»KAŒw¶ÿ—íÇ[g[$Z�Ëøµ.!F.¥š–=¨±¥¼X¿àçã—79„F¼óÇ–5:]O°ò—Öêø4RP“²ÆÀ�}V× £.½ß°ÁRk®C³Åϰôío½SG%wW¶oÉä7Εé,Ý‚‰´ú³+Í(�]à‹ Yá¶SA�OÉv› òÃ5Ivç>Íxºø°ž�E†æa»Zw!ÆÝ0ØjÛ‘e©f�'ÕÓâØÃˆ„SAç÷Nt·Æœæ°mcá\Ã�A'öâ]ò|ÿ–�´‡›½Ã(º±5ç­òcÇX·©Õ±ÿsª‰šZfÂøUœ�Qk´*¥Ò9ÇÇ‘Õ8ÿM“íÌâò�ú÷Ö7•R7ÊÆÌ³A‹qÝP-žÌyV¶Äü12Œé}%"ø,¤á�NÉ �þmê¼VÞ´fº;yåÿV«…þÃ�-Áu¼Öp¾­xc™?’Ú§òÍ´´'¼pæ½D;L(âú°_`óþ±ÅWl·È3zíPΖ•máöÖ-&ÓÐ9¼ÆþÏØó³çÿœÚRÙJ‹Q¹ç [BZÔX¥¿�áQ^P×®:¬òã$U˜|³ÅÑCmpCÜâ/¯`O�ûIM|¦Œy/ׯ^¿Ü—kŠ””ð&V{#ª´ ö34-âûÒB¼¦ð+Ë T¹ƒ ŽªæuûYO/<k²\¼íøtZ×¶F€�új¶lª¯UÚ"^»üšåvÍ]&‚üšDÙ¤C(£5rÌ�˜a³Õ�ˆÕÈ9–SÙºæ¥{Ðð£õ�*ï• ½P†)@ÿg0!Fk6tÁBTñ6»Œ˜Ñ8«ÂJ‰ÐF£eÙŽ@èÃ�Z¨É© gvG¿{~ð…HÚ?ºª7§=ŸK±¥üEPí®¬áU\’` EqïS6.!XµßÓ5ö@EïªbMxk·èçŽq\8Hï*ÿÿ;SÅÞ¿»È4ËÌ´’x  2m\k-[.ƒkÉèZnC¢g҈ũʜú‹Õ�‹JΣ¡áƒ]x&vÞyª4ˆÈ­7â?pTäg¢·Mk˜6ã"×ËTp꿼?:´¯aÉðͱÞ3ìUvVíí¤a…î.Ä:¸=Ó†ÞH_6Ï3ðj*'H·#�›Mɾ*-¥›´m˜IU³®:âYµN—o�ï}¬*Wÿ•6%‹ùûäpˆöµ?µþýõ•X%¾‹È)D5¹IÄ–çHåûL )!A–×ûjþ� M|o4pŒVqU¶weöPsà¤ú‹ _Ïo�¶ÇS‡ 2­‘C§�gŸƒðüÓ Iç“ËII�uÛ8-«ôÂ×r•Ëcì«zUV6ù�Wɉ0ëE–_~¾�z¦ŸúϱDÝ[×™»P­ÓIs®Ë¿lÖ�ùîÿrwˆÔ˜Š^GŠA¹b$$ã<É™7­�íº® pÍ•‹fŠòoÖåÞ³µ›C• �n\YëR*€³f`-ºIÖ˜Ô{.0ûÔ· ÓP¨>òFY×ä“ Ë–ªçˆ¼SÙ:¿°œ°¦ú©×bÐ0¹éÕ~þ§´ö{Øò�« œ¤ó[#„Tð3ñøáô~„©IÜæÕ@I“Lš‘OH‰„_cA…‚ 0 9ð*$ÑÑݸ·b/zx»¦õ5>bñ3%…ŒQ\f¥ÂËéÐ|ãöȈkI”,sÜ]Ã)eÚóã”öЂižëÑ_tbúkòŠq êx´%D`û |2A‡zNšÍ/z®ß€hZÕÜÞ@­(o\Ô‹»ƒ�³¨K×s7(†&§ô²Ó´Ü Ù}Ú¼é  ×‹ÚŒØ­(íö4H{mÇ“zãˆt§¬‘ªnIÈu1�#›Cñª¦]pðgú×]³�Tþp2™¸ÂJð¿X,ለŽÃ§r/l’¾Ãè²ê>mH^>bާĭÄ>o(õwDî^>ô''1–{Ò=ºX.Ð]6¼¢I‹SÚÇ]ã%*EÓôƒ èÛ0{š\¾ÄÞŠrýaù„ïg î’ íJ�•"éÁæqâêv£yú–tùêž+÷g6ß¹‚óµ²ÓRÕu ÐW¶å×4 °t„ñ÷Ò‘OÑ£MãÅ‹${8Y`Ò¦;Wþ™'èKœ¼GØ?ëGkD‘‚ØšGšŠ§?hæ(7Í¥ÇÇ-;£F%–œ¢­P¨è¦1i9;JφKMªZòÛl°8AXŽö8,OÐUÂPì.¥zö0@3G)ô`"Òüìïå þh`ôñXU wþÍ“7Å®2l?žË÷%_¤¾óp£&^°ÈeЬ—À°²ØnW˜r¾}Þàx(D¥öþQý_ 3ÖòoC‚Þg¶JX™,¸´iH¤†ƒàí«ïM¬üýA�¹` ½áNÚƒ}âZ=‚Be%q'Ž­ðr“QÝJ&Õ=ºáq«Ú¹2æ�†@{ÑÌÒÍÃvð”1c«‰þ$A;t“” ¨{ô�Ò2­5ÖÆ­@êMfsœ’¹®°—M±î>T�)ïçŸ.2®™­=Žã¯RÜnúåmî?¾1ve!ˆk¨d¤Ö/óN*Äš©%„ðKš¦aÏ‚´EZÐ�k<ŠßØ‚t1²uy„.�¯3t䀓”ú, ¶Nj P˜`AЧ‹í‹™ÍïyJƒˆƒ()x7„Hã= 8Ø“0Cõ5ñ/b>>Ýù^ÏA>¡�âÚ4l)°U¥‚ÍØã…J¸Ÿß'�<æb$Òñâ¾7ß.©×.FÔ#¸1óõmM¿ëƒA>¾¹WÏåcp[köØfé“EV¨C³ÇMCD’ãuõ#¡´8ŒqÝ5x¸@ñ˜�¼ccÎì”Ýéö``‚n;ÈH´•óÕíf=(”�ð×ë ÚÞ“k™Wf5—�>q¹ 8Ö6y‡�¹à‰ ȵ ×@ôÐSº>¦ðßⵚÉWÕ¾æÿubúIÖýƒRÆâ†Pd¹ƒ7.l­ín{ʰÑ\vÐ4�žè½ãÍßø$°º ñg�b üí ¿ðt&Ä!mùP¦M!8�KÁ¢;•|ÖÉPÆâú Îõ‹ä1ƨO¿Ò<P—o” Ùoì—iöO{ó�.´ß¡/ÏE2’79ž2ý¨¯EãÔïâ}Y w™DˆúEµÁ›öÚy_Ú=!Q qeß½·+8éÁáèAVÊE/(˜#nǤ>/PÎì€í¹ßÒå�W›KÞñž3¶xû’'cWHR*a²t<ñ°]û«�€„Õ—„æ9éêó«,³‰ ÖQ�@R TÒ!²W`¯)Uh&S=Ô¯mâ;Ö¨(²� ¥söFúú²'9çmCöõÍ©n ¦dÂêDo5( $¤È‘7$=¼œ a@Dzè€P�ÄËÆK§ !qnV¡u3™D#}EOQ ­ ‘ÄícÜMj‹@ÍyËš7�Ûƒ=Ñã8º=ù["eàr=ˆõK†wÕ"æ!‚i#ºÈ©ˆ#Y¦] VˆƒA)n3ñ"æÄouN8¶º9:ޱ^^ jñ9 T·÷<Ë(#„½TÇË6J=ÉÍ2Ú’0òÏôO �ê9|P„Øã®�²¨e\÷#ö©2&¥¿Î�Ž`;�šDÕû´¦k2oKRŠol?ݱè¥;Õµg›x°kÇÎ) ð–•£ NW‹~Xº—¯vЕ†t ‡Râg©Ozg…"lžÖ9WŠ+©» µ4¾è™�ÖÄ\mxÚñ’ÛÖû…zf]„V˜ {Ï»rIù¿9œLø]�ÿûŽo\ŸûÄÝüêïiÊvÛpÉÑ|d^<À\º›>¦¶ïC¹$Ó“ŸuP@6^mYÎÝþ0HöŒi¤Ô'Ø�§lï æ�í¢qÍùÇ•ªK¹ˆÉò["bÒw ãîxrPBÐhƒ&ZOë=ÖÓD] s–óIáý®nÒ  Czùþ mr[½ŠEƲfœVd¡ E&D­˜*x÷ŒôÂ}Ëo0†WÖ)ÀKHl�=Ò¤³rCÉÍêéÔ± ½zkj'*E‚ v8¢§Fa‚®éP+˜8:†ŒOíÞ-ç�l†À e*úÃTðÏùH÷ ´ZÿÊšHD°²Î[^÷²E·KÅÂáã¬$zÚ�ŽØ÷¯íß™P¢MÆ5ÒÙgë°_wMB¦šÆŸdK9­B°ô?i¸~Õ%»x;ê¦m$ôM2&RJ-D/I1GÖý~É`´EÆ^bæþ‰t®Ñ¾z•Àkl@U“Ò>—xCc Ük5^—ø,d©ï ¼üªÅë9kéJ@…èš.è ¦ÚâRG4Ð;L.äÛÚÞ¯˜—Ne°çý‚I$ ÕCà”Î#Í ¿=a¾aÔníÚáû’£yý6kùîd f‡0Oë’_Æpï3Ü èL€x׃P¶IzÛm�"ÈÓF¦RûÝ)gŒ/KË„‹pjÕ_ÈÑã‰.ƒçÿ]­KÙa&¥3º Œ±e”Ú·7ž�> c‡&-ÆÌæ²§jbìÁÓ” ìÃe&+[lìzJ[ÒWˆ¢B¸2‡é7 q&;f û[hò=n�ؤá�¯ºýt¯00hWwtŒ-’Çÿj.‚ÞãUû‡‚eÄI }n7–©Ø�%ö7€ïޤX–G¨½ÇVidm,rÙ‰–�Tjò‘¡6jm�C!¨bÚWôåG\&×¾–ÓÌF6QÅVËWjºSäŒú¾¹em£H Ê�ùâìn’ ë3¦â»ñªˆ‹vJ­' Ž;ó¨a˲•9½�ì]Ç®iXaÅ9G G*¨ <ëõÇŽZ1&]õ£pÈÁeÔÞ!YNy¹-ðBbë��ò>Xˆ¢ÜY(-N¹|Õs%ºÓWÛ€%÷ÒôÙýr“%Âz�·xÑWˆo‘j«>‰§-©ˆŽJmY||FQY#K£Uº¶� àýîÐN{4Ae€&#G lg¹¶o³�ßçKé•|=H0/þÖ¼µpt*‘ ˜yÐÿj"ï?ÄN%“´èÿeÍ&Ÿ¹Tx63i(% ¼ û�¦9Ò9Ö¾Sö_!Wêâ4Œ <0#BqBÌ.+")Ö…õá‘�¨ùvªóá©^²�bqJ ©8(—®{‡€Xü")è> k.Ÿié_AÃMÀõ1é¯Áö¿Gÿ~•3ã^Œþúî^j‘鈴pæpa˜�þ=ÞŽ·Õ™¸vœf”5›} ÎY|ýK&šæ¢àh“`:,Ÿ™êŒÇcdÎh–~ê±4ÿa¤WgG¥‰,kÁLk»ËĉÀNü4#y†Èý€ËÄv8h?êøÐÅŒNæTF¹e�ÆM¬ùþ…{Õ¢p CÅU]‰(/äýoÎüŒ"ñÏgldÀTh¦°çœTŽ´�ø¦2UL”Òµ9SõËÐÓÅp£Ÿ�CUm¹L¤œFÁ‰<}JxfjÖ3Q \"D[Ôoo5"Ñmw§Ön¹]Q xÛ€êv\¥ýl†íÇÐŽÞÃÚ¸+,þÍþ")=JýG¢mS´’ax�Xçë¦JŽjªŸ=>e°q +d#ÊIeõmàD¹e.v³Ž9�Ý›2‘ëZ¤ÍÕd’w•}Üv$.œ!êÌlÿÀÛ@+‡›Öï=%¨Â†ò x( kOK˜;"÷7½ Õø-Qåág’{�G�8ôE=ruûý"¨�bózVŽëâ‹*¼+á¤Ud5 „pXªÛoÀS±Ì9–egzÁŠÉ‘[_º÷E 'Ê‚z?| öþüšÎvÄn¿ ‚±jïaÇ�#4ç¤ ¡·s8ºùº¼¼ç>º­ì;Å»³ÕÉÜÚ¹:ŒlÒ\PŽ'áq#y$¶`ÈtFžpSÄäÂ�{¥ÓB˜Ò|¤ üñ7¾·Mž vhÛy�Q¢W�1†Ôq¡Ž4UÃ=õ^~¯hú©rTA°hu%Ì�ï–ïR[€;¨¦‰�>))iëpy¢�?}OøÑ6b)gn••ùžOÄÂM³ÛÏN²È­Y³†cY–™eô*å·ò¤ü¹5Mê è!e„ÏëS7ˆ ÜrÖabc¯iÕF‡iø„€°rö¶"�ð|Óoâ¬*öÙÔ™GN©¼5\ØDZá¯Kõ'NÛÁ¤µ *ðÏY$U9pC÷Ød†CÝ Ò�'Îðm°ƒÛ¥åÉ Âmþ%£êu #@!¯]Î�ãè~xûãtììsnë¦�·Ã~‚��:J·CN �Äy˜òùªä°í*¡w†ð,y�àA}€Joõ½Ž%u©ÛnjóÏù̵lîCÛù¤5:Bã?ò>þé”ó> ]ü›?ø—LÉ3c¸Xú­H5eJPj_“=ÒîP#šhp•uôÌ,/ó:ND´Ò·2à©§%ü%Ý*ghTÚˆ]-ñ KŽ|ÏíÝêAïOtÖD¨t’¼Öã˜sÅTv޼×D Èjw‡^²ul¡ö#l­tí ƒuÉâújýöU²cìy/ê\c´Ê2죢²hO®ÙyÛÙÓ_3¿ãÄA'Uu÷o: Ä,[]VŒš£Ð«bjŽ’WËý^ß5"øÍÒ4kJ>|j‘E0?ïÊ¥�bŠ,Ñ�µ…[O·›ëï²ãHïXqÀscN×&ø*,Œ]=sE}Ìèž)�¦†ñ@bj�3}M·GÑ©Óõ f²¢"-Sº ÀïHÏ «Ã»z»t¦·HCuôÜX`4ª,,"¬MŠ «�ì kØ0þø/Ú¤&HcñÛpÑÔR[ì hpžº(ø‰§Þ2Cà‹¿œ«»ÇÔ w¤�‹ÇejÒ8Ôœ„¦×IMK-=³Ê-Sîï}.ŽGÞ‚5\-ZãÜDšÃ‚^»®Ñ†´°.‹ ¹ 3�õœ:‡¡fÞe¥”€aEtØÂ«»4+V¾…úTžiQ^OŸ„ÜVpÇÂ}§·V· {š˜Ò¹ãf€È´s'$c)ÉZÜþ ï$ºQ|4¢d^3êZØî?�&®¹q7äSn†ZÝžäëfݳvð¸”ó×_`¯ÑÚç ©’7ʧQ„!#;¦ÈžB7ô½|½7 -ïØúAv|ˆÍ#Žlªï!k©œòy˜ä×p|Rû"£ð¬,*‘vñÓÍU™U ¥�äiý£Nr–Œ¦µ¬i!|<,QS ¥z÷'ÿ|Eî—´éŠEpó6­%zaZ¤ ÅUž—Ôù:Õ)žÍƒ——t³ŽX«Ï´r leÊJJ#Žºè.Æ8û·“äO±@;›Òæ“©dðSr*¬a_õ3o%Jÿ½¶lÿWk‚Å.×R—°¿<6f p @¦ LÙ;6�sª‹}gBÿr¿ úôˆàï³WE�Kv¨g85 ›awnžòÌɵp Î1‰ºãDø‚ôp~“šÀ+ªOŸ·h§= @oÏZ™r ò7£w-cBs›KÒëyÙ¦µ*�üóâ‘"çÜa9â…®RF ³ãÁ$v½â±àu—…ÊZ”ÒÉ¿HÀ{‰ïÞ|s©£€„/œ+S›òú6å]ÿiRûïéZBÿî?–~­vØFC°ÁrŸ´µÙ×̤®—Ê·&�~3­iØ,®'20z“B"69ñà19ð> v7”—$•.‹Ñ^åtƒQgå w+Áó™:Mkðr\ǔé¨Ú‡ç 2'à±L+õlôˆP…dâ1³ÊN·TR endstream endobj 28 0 obj 74223 endobj 29 0 obj <> endobj 30 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡G�Ît‘øˆ’®>R4éuw¿¿Ï·õ?Óåø�oÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:�ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·Êãé�sM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§m�ܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ�~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒßè·RŸ~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßá�tF8#�ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;Ñ�ÈDt8. Pi�|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-�AÍÄ�NèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8�eÁM‹³<—“#artË„F{Ç�N‡® tÛáÞ®Lˆv�qè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»�õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G�¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿ�dØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 31 0 obj <> endobj 32 0 obj <> stream xœœwste_¶ulÛ¹±mÛvR1nlÛ¶ÍJRI*IŶm[VÅöW¿î×ݯßë÷Ï7î÷œ=×^sï5×ÜçŒCA¢¬Æ bæ`”t°we`adæ(ZÙ™¸¹¨:Ø):ðÈ3¨-ÜpN8 qS7; ½«š›££­ÐLèâàæl tá˜ÿIÿ™’Ô­\m�ÿ‰õOLèìbå`Ïû�Äœ�Æ®qc×?)jnöcg+€…‡—…�—•ÀÊÌÌñ�‰μqcs/33€´±³³Ð…žžŽBÌÁÑËÙÊÂÒ•ðÏ[µ†ª ý¿€‰×?"q ‹•…=€òßþ î@[Ç¿ªæˆý�mm­L¶^Ž–.c33 Ù_šÆ¶@€¤•­•££ƒ;€ZŒæßYþìš…áÏ+@ñ�‚Îô+{s+{+W/€±½@Éha °36þÅ&ngåêì`g¶²ÿwš?¼£‚£Hí�ÎTúÛòõNÒÁÙøW”�…•…@méêêÈËÄôW_Ìÿ 1º˜3Ú]™þìŒBÂÞLÌÁ\ààþJ·ršþÑÓ‹é?4߯ÞÁÃÞç?EþT`ö·Æ›¹92iØ[9¹eÄÿkþî_˜ÐÀÁÌÊÌÃÆ:€ž¦–L-¬îåü[ðoð)ü|æÆ¶.@?+sàŸ œ�‹±;àêìôóùï�Á±°Ì¬L]&@‹?ºý‹ý 4ÿûXÁØÕÙÊ ËÌøGDó_¿Þéÿq”™ƒ½­×¿¦+Ûÿ©îÎuðø0°prX¹Y,Ìêãaeøý;Û?uø‡C•�­þk�Ìÿ¢”±7wøÃó÷Zþˆø_õ˜Üÿ~VÔ�À¿-ðg—®V¦À?ù§¿õ˜9˜ÿXûÏ…å?úþßâÿtÿÿŸáÿâû‹éÿßéÿƒã(éfkû·†Pÿ½!€?1¶üi @ðWWl��ÿw’±�•­×ÿ•ö¿¦kÿþ¬ø?éÔþ[·L2®Æ´±·°ýfå"iå 4S¶r5µü»�ÿ+ aot¶µ²*;¸XýõŒ0°03ÿÏ º¥•©�=ÐÅå�SþþÑìß½$aoê`feoPsý#¨±³Ù?�¿Â¦nÎÎZ÷7÷üÉýÇØÜêÏ�@O )œ«P(ú­©mù—‚�WåÆ*fZ�M²Ý[�Ñ·RÜCÛDú†fì›2µ»~`Ù `I°Áž‹MBqa€„.Ô˜u/6hÄvê$ò=Ýijå]5\Vδ7ݯ•©h,, 8ú:»5£ÕòöK€¼Õ^.�]�Û¿@²ëŽ/ ÛXã Ý,Œ6^œ"4ÄJ†}o(àDV#ŒH …`jS(  ÛÓ__À)Šfù¨íÚ�¹È¿¹jïIw¿8,R!ÿö3w:¿èª¶ÒUa‰R¹`êA¸"¢�‹Ô– 3Ûxá¶àiMèÌŠCs<²ÒmÿL¢ì>x8pÎÉAxV'gÜs;ü«ç7 ¼.âÖVäHÿþÃr…3 4ò2ÇŠY,HÅHü9±ÞÍØ@Ö¥ñ¤î!�Z…ž ËMgZ¨&Ͻø,߯‚|ľ‡¬à+·e¦(â(ŒÜy%“CÜ“uïèOe׃BEÈ—ÛzsYhÐT–¯{�/hðåáBõ–'fì=+¸_‚Ú|!–¸ÕüÇ­‡n5›:3³ž×ÃAÁ#ƒ¶�.¹´‡.êÎð =V“³ÎxÊ´Sô�U7ÿu:tó%¼¨€oiÞ(b|¡Îéu;®ª¬Ioû•oÛMÖÈÄ“Âá3Ó¢îx?NKÙóÔNŸ%Z}`êh8º} {–F‰FàUÛÌgº÷ °‚}Fh*`—tdÄÓ>B°ª:½µ�•jœÇ�êU{¹,<Á@¹-•;±NIœS\ou¼®QCœ‚¼¹¬ìœxF^•Ø\Ó¨�ߟc`Û:·ÛìøvN±4+0»SàèI£›oè!Søs6o¦“T¦ Ž»ûub–.°¡ÃoŸšîü…¿xÑ{ÀCOŠV>¾Å· ¹?ßEDÀ|_ÙPf(<ý­Œ2®BT+mGÔD7AÑį*š±`]ç7&ÈºŽ¶\«mtë»§‹wi#9YŸ,¤%L=†L4¬»]d?ÀO“Ò5Vÿ„5,7î l@ÄÁŸ‹ÔµôH ½¾D`‘)-ö tkâÞ¤šÏ]´.„HÈéRó‘<ùF)¢|ì˜JXuÒZ ÃtÜ„v¢ºNFŽ':ÓÙð, ä£9!«\£­‚�ð7•¤ˆ=¢P¼O¿íý`Ù\­alf¡~µ@ƒ_š-\­�Ò&Ç�¬¦{Œ5bjPÆu› Y‹}L ¡å0]/f‹6bFý‡‰ è¯?‚ÜPnú'5ŽüRâï ³;0Œ.jVˆï€„¤U‘êq©2-ø9o—Â%…}�Â#uKŽr‚3Þ%ÆËñGt­Íèn¾ 9}׿üGU–‡†™�ß Ï1`2fÖÊœÕîâz'©;¶XÅ8ÑÀ’7É~}[Vü­ 6]ZÐÚ\J[É ]!™?ø»¬5cøÅ|$N�S1ú7骻áy%ç"ˆõ¶Ñ§‰~ 3 R -EÄZó"7ó9, é¼!ÞƒóÈ…hÐi"åÎ1¤–ñÒÁC…©A{Å]»¿?ŠPß[Ó,ßËýœ¢ 7›?h»b\ƒÖÞë¸+øˆÎ+f ‚Ú_tD¬èŽ5‡mmá˜b;ca)"ÎmßB¹Ô]m�Á‰ó“lÛ».Êúß¡™èë>ø1Q¤e‡"ñ¶D-¡QX›à½Ø8úfz–œv¡eÌÝWÑžkì )òúùÕk# n·PÀ es²«Nþ>#½¯aêÅ>j°ãjµ2YÂ{oÄŸg5ù´öe¢„n=IΕ…¥°Æp/¸²ƒY(�}—·î%ã>Z¶x>5§ÂJ"Žkȉåç¤õˆSç‰%ÃU\ãd7ØÚŸ˜ µ3º¶„v¦£ €—YŠ!’îfïÒ4a3#R×大2}ÙÄç*RüÌÉ3ƒ#¯ŽBµþþÜ4±j§iö2L]ާ†šÕn‹˜/°Í‘naþöKÎOåüª•ùGÑï½.Ô‘ûGGÖ 2†ï`eÖ¢£Ø°ç%I:¼Íg/¦æúµo�¬„X‡æ¹ 0ÇÛí€1ŽqTP´AsM¤ÌíéÐAðk°e'{[‹ñ1‹ðœΘù)ŒÉ™Rô²t§ ½‰Àðík¢æ7£M"ß.H}4du@ì÷=GÅ08˜ZHÂ|GX6ã�êü�L5{Ò9I0Û^="Ä£Õè1¡_×È—à+²‹ö!5q\è u5½cÊcI‡®ÛFc§AAø KÖv)jà3žz)V!cí쌫b= F³×Z»p`åi½ ‚³Ä¶Ca0|‚ê`Èç°#®N’ ú�©�v}ˆä ¶pm7E¬û–5¬¼±!Ù]5Tᢓ×N.·<]Ï ªXÌG0ÞªÉ3ONÖ@ƒiéDÞ‚ÛgöË•Ç~gž…ÞžÓw´ûÓˆžLú{ÙqYZaòÔUô7¶¡Üøf�$ U¬›Ø’„áeǰ˜ÜÛ¾!Š˜Æ¹sW°äÖ8Úò§[qMäª~–)guûþ@uK¶Ä+°-ü‘z¥(;ºÀÉñ¨»’3ò'2æc™=ÃÛÑ\DÓ“ú¹”ï#Ü\ððVÉà, ]ϧßÔ Y¤!�k×êw&`ÜÀÎ un$*OÕVoçJ‘@c̼k.1"•ŸSd¸<õH˜R¯Í %?ÎfÔÏ0XKYý ‹ÊM£œ1ß{[¹)  ¢Ñ4@õØNn{Ù{ªü ÛA~üT’& 0éfSµÛHg]=JXÙf ÿJÊ+Y‰óMˆg!£Ë]O¹TÚ˜n+Ì緌ڌj¬•BÒ–{P}ÆÆõ�9[úéü(¾¹ŠûQ?€í�^–Ü3¹gºÂÞ‡€o6+/�ñ‹xædÖ¨ðaešöžîj¢¢/·Î%[Ò•Û5 ²ý~›fÀbïz*qûE6­ÔEšÛσ�-ëJ%�®KGOë ØGÍïc©ÔeÎ8�A9´¶(àkF’a›Šß!ß^?È,o½û±aP +ûr?èjü&ú÷aMœS, åo~SPª•ò!íڀą\W1ݽNXǤÕÌIH³I¯Tw¦}ޏi¼ òÖôãä*i1åÒ½ÃE°q`Ÿ¤Â—äÔ…;SúĬ;›YØŒ HUpB v`Ú°ÊãËÜFÓÛ 5me�$jŽè4påÍ×ðkP‰Ü¯wQš+õË$°ñ‡\ 'B…<ä$»ÿE)·@û›±l8š§Ö°x®µN`2l¦!¸ÖÛ!·ë[µÀ6)ª+»OØ'?Ñv# ÇhÂÓ­ÔT<µ\‡Ï“<�ͶþÍ8žX¥æ£'N(î�'õRZù =‹ökÓäw:¬cfË>x—°-�jvç" šû!W¼Sh2ó0ùàOWb~Ë2OJ�Ìsê–>Œ¢Z—@䤙U}Ó³»_ò>&Š2%©¢úûÙÇJ EP€[£gXF”ˆ?iÍTbؽH ˜oA8¾¨Ï4ÈñÃW¸ÎÔ×$ó ‰‘§ì¼¢öz¡Pèä±3bžlæcíêG.¯X�íªDüÆâ¬…¹Ó!Q5»Cbœjœ½öàêtÆ*«ÔÝG1bo+6Mk7^ÞÙüÐÈOê9M1šÎ&½QYF…mÙ:h£+G ¤ÒljG‰%�»ÚD �ø�Ê�â¶oD[d�\ÁÊO×O:ü»byêTç•-mA!mç Èï=‰ªu6wÚDÆïlŸ5*O¥>a Jž¤½?æ:¾·‹ õ0o×;�õHT�Ûz vü²fÜŽÙÀ/Sj3}[iY wð»„n\ |÷óÍ�êÖ0Õ¹ûéøÆœ¥µŒþc-ˆ‚Èïdây­b’˜—wœaœR‘þì�_ųÎÿ3Ô—™ÒGÈÂ"²mânSߌ»Ê<²1Õ#ë"˜)$“"Ñ£&—gk´œM‘!Ûv„ø]ý™‚¨Ý¿ QTv`8Œ£k¼ˆ €hØ ÛÕ7œÕËkãôöÒÙ°p[E/~§KS—¼—ÿºõèáÁüâ× ÄŸÒ·üåʯ²6½¤F(ñè[iàE'@\Í­…Å’~FÝçòÓŽ–p«‡Cácã:jÊC·‹½Œ>Þl^Û§½õºá¾¤Wp�+©ª~š©h€"7Áç‘ß’ÓýÖ€pïËA»œšÓ¢drâ·ËÖ_Z¹ ?.Ðú=°)AMø°¾KJõ -9‚úe€)ÜöÈ!ûőƆJ­¾Ùá%‡ç9¹hŠÁywÖ«p_^·Þ½hq»&³D�гu» ¡¶ø}‘ì× ®¾8òæ„»-¢„K× Þ²Ãøk9Ó誳õÜc_”‡HÒ¶Õ—ÎOú:“lû·±S{yþÔ8˾•jÛ¤´º#l˜¥`ýÂ!'Ùhšã‚Å Ÿ·=8,?ì1Xnf-Ï×gÀ…›ØNhgý€Ú{õÕ‡Ó¿I†½¥éý$w^u‘Ю Gä}åÖ¡ó 8ø Ý)’~¸bÁïʰ ÍB˜XwÁ¾ÙºR£¼ÔF$Ì×Jt~�:,ul¨¡Ù5¬ÜŠåÓ_¡ Š­¾´oÂ÷ZzÂùyª‹dKn±tKt‹.U©R7uÜØc„¸Ã–ò¤3$mw‹Æ@Û>Šé˜‚Žýø&SBUº]UÜ>Í!“Z<üÀ9È�Ö^Å&Cÿ[yO°�;ûäèNßDQà"Ý¿4ÝU�‘9ümå˜J¨õ S Ï%Ûä7,®‰môîþ0†�ã­M4î4‡Bm—ÞÎg)(pÈ×™µW’¯Ok¢ÚV‹Öõ6¹iæ."ÃÃÕuä2y»ì1-L“`GN2f2Ò!±iQdÝtÓã÷&rc¤¤¹ÑÑm�IÉQw˜ûŽœ„«²:à=¾¶þ}7ª{ƒ÷·'¼®:|?2Õ±\.­ŒK9ù[û$oÉt¢³G΋$ë™cŒby¡1äm'ýáãËX\ž«ø±2ût0žùl:‚zða1Ü�pÔ;yŒ‹¤^B×Dù)ÕÆ‘>4uÙ)/µï#ïs+ñSöö²znÖ)jkMÛÉïÛ‘ò9#Žödýmž)ßRòËPmɘc˜DCš“è…òMOÁ<= !£ý>–õ�ßÊÀ½fãÅ ÀÌ ÐÜEÉÙm½ÄøWãKýÜUÍ?O�/7]& .w­ú& 'N¤…pÀhø³Ž•ü‘=R¢â;¿W2+Öøá¶·|çÒ€“ÊúV6‚Žçõæ2«�‘¥ Qdé»WX‡}Ué´CJ øm€Nqü�½ÇiçMÊ»[zFu¯ÎOfÉaÆ�¡]ufi;¾ÉãפŒ6JDgYT›µò,qx wñ„õ“¡áå)Hr’C´{��;¦Îi6ѬH¹D"gla]0P�±øˆùýHKÅåï'\" W(cúW¸˜§Øh`�Å¿�Ÿ#ë¢r+‰Å¹Wà¼A[ÏzçÀêõýmp…ª_‰½ñ´ˆ/‹X´c"Ý(zÚm^¶h�\Úî=iä‘[㧳ʭnÙ+É|uø-Ÿ¼7üÑNpÿ®�µ·ÙˆcGH`Ú´YTx„‡cÃXÍ*¸_«{b™Î~5úï3^Ÿ…çG@{%fžêùnPÆn¶ Á¬Øä±'/× ðù &Áü¹ëñĬK<Çúê5�Û‰™´%õt;î§*W¶ CØB˜Ìât–8tÛ)v”ñãèuù—Æ�”¥+¤ åV€ ®jÚ(ˆ K3éƒ4²§}–ž?/ /¡xnY—b¬È-UR­®t~´xÊeÃûzØÅ4–0îÏœ¼FŹŒFt mæÇ¬áÕ1êhTË6òCV€/HÊDŸ¹.}ÅÅxÀ J}ª 0§ ((u¤m£VSÀþ¹Jp8®Ú´T×ü…Âjœƒ úØòž#Uhøð8f=E ÷ÐÝÐdWÔ]µZ ÕJIC¥òXE‘[ŸÒ.ʽ�U ÍmqôõnÕÎ ÿ©uaåûîõgUdƒÝlÎt„<5Q©M í §�’H‹¦¯Óˆ¯ú�ôòq™ŽÎck\‹î¹‡¾Ñ!çÂzK�±êwýµµyH“ý9øŽlÏzæø�.8T~ü§o®�pq¿¡—2 Ðn¶¢«:ŽQ‚sŒØmµÄ“šJn{Ý«Rãà³µ4*æ¶nYHÉW~]À'àòó�ñüʇ�Æ»?gÏ9å› $iÍ,µ¬‚XÓäibr5 ó„â ¢çi˜;XÂ'ûÆ�T±2Ärè'úÆ òhq»ñÌp ÎEŽ õhI› å¬;®·…éëþ 3t^-ž¨¨ªÓ–2¾ÒvÈŒÖAª±:×óA“ÃoUÓ%Ég¶*eo´qÆÚ°ŒKƒ cð?ÓsÃo2» ˜¼D˜âìãr6šÒ$EÌS'Ï_¢>aH0ÂôÔ:T_¦juRÅÎ…lsýŽ9ÒXbÄ6>¤QèK†žàäE†“±On uÐÔ�æÙjZ¶üÖŸ‡.ZX›È8ƒñÍìá EȽúLJߤ”…R³x½Pïù´Ó3Æ!RÄrXãe£¢sæœìƒX˜EÜu Ød‚ìö,†{ ·„Ðã ª¤ š¤§N!¬ ³�!)ßüý‡œªGú1ׯ¹˜ßsäZÁLÍnÓ,3&¹¼á/¥ÂнP46´,¤þ&Œ¨I6„a«Rƒ¨Ñ|®Zö4ÈM�ËŸúÙyà?½òѵ³CͦϪ¼6`Ò^T^Ê«í`1ß÷ɯQÀS‚ DÚMFÂÀ†~äƒ?''Ìß`ñËÙE3ê¹PµRGÐàù6±¥�¨@‘²ú™ñPC5•­†¢é-¶ç—CÛ$áPÑv£[|?÷Œ8𵿠—‰Mš³3Ùf¹ ~È% !%•šè4–hNt[,¡,.þâ=³’@ÿYïCÄYÔ÷ëû[¾W “iŸH°ûÔÁ” ‘ïY!©½F³Þ{Œ>.Åqÿ;#–:-G<|BðJ/jÔ™7o°î ui+A|¯}p9µ6ëÍÜjþp‘ØÒ4wkNd�dµɈ½ÀŠÙ9ä9G„®ä<›9g¼wÙ$ÔÐ(¨IÈ1†Šòs“‘yAªÈãm¿G®ùeëÃ+Ášb4p×[ùÁ§jm¶I/\?ÕÀ ôÉê©Ó"¶S¾�Ò–x^ç+ë’S—�°4�ð˜›øSä)G…:¸;…°ÞÖ--’îXÊ**#ØÏ,�Ñ{6‰€Ònêg¿´7û<Îr¦¥úT³[QˆÜÜ@µÝ~,¼±û•Mn‡ž�¸kÉrÙ´»jÊö ’^ñŒ… È\Q<‰1HÕ—6°ØÖ4}‰©œyUÒêÊ祵/¶•¸‚êñ¹´Å) øÚ©EQÇ¡ûíy 6�2ðl¥·ù”vøÇ™Ù`x5>ª^‹XŸ<¿w‰žx6Umù* àgûÙr†K“¦��”¼»‚Ï„…´µ ¾©Å8 Iè }2q‰#rePçzê*t[?Y< �#x§žQø1O¿jÝ´ÅdË Ý\“­ØF¬Z7ö®êü—�º¼˜ûårðïYãJ! ©(ªw¬-éz\”Hv ŠŠVo@¨ùkÖ÷8«/{�Ÿd] Ù+z¢P;/´2f9O£ƒ)Ú€Mß•u]¦oìíÎÅÔâZkkÀv²¼ÅÉGÖïø犑Á·9l\¬ùø>wJ$�ªªÖ ÕÀ†p§F™-ú8œRØÁ¥tò®lœQ=Œý ËŠ�ið~Êy½ö°œg0ó„!õË_ÑÅRÃXò�ÝÔbàöt´°£HÂøÖý™{%ßÉ’xÀ-ô2¿Mýh#2úTò~5½Ì3iº=ÊÝUhÎܢɔI°ëô‡°19õn›ëé7QØuÅÊBúdç³zôæR‹w¢§ÙªÍ,(±yÙnˆòèNÎAV�’Èy×Ý¿™ËyiÏŸÌ9Á{÷‚ h!zd†ÝÄGôæ÷Û^Rà7: ÓSjõIÇ~ŸvÞTƒÑüf¼|fÿ¥ž}9KñW¾”�B&£¡š6¬B�Ïù³¾ZEk4ÐBŸÉ¸�Íß=×ë8l¨nÉÝ.j~ýO_?~F¶‹ï¾ˆP¹5Tˆ=X–ÿlh:3¦{–¥9êÓY`�po±'– »ñ:E'–PŒVDÉeÔ§7•~6J¼õáÄ=ŒBo™}EšA™e!—ÖGú²G÷!"ínEÊ—ä�ã‡ËŸÇY£æÀ ÓZk*=æ‰cK¨áWŒ'ùnH>�¼Üo õ:e4‹eVRν³“‹~}MyEa9[�[¬M U—CW�Ûk¦ñø™o²¬b{�îöe>ØÇCŸTÃùfÎ\‰­Åߨ©><·þh ¥ WkÀCÒÀN"’C ÎOÓâü+Î𼑵œß,~øü}šÈ—Ýk Ý1Z|0VíxR+ÅUŽÍö@uw\Ä7ÉÔ^+^j¥èK#ÿ’ãñwÍ� ‰‡m¶Htãßo®·áz]y¯\:©^˜ÍN t�•DÝ”õ¨ôydG´Û߯v¶.[¸-,ÎõníÏW#¡åµ‰·Ý½'<1\^r¾B6Á8t�bY§0¼™Á6T7ªæ5I/œÕ9ð¤,£"Kwk0ÛwÚð?Tú̓¹·/0àˆ7Ï>R´Ú¹$Ks‡uýf•íï{ãÕvjò ‰&: …ÝO£Þ•ödÚœfãW™²üî½Lõ,»ç¬lï�Dœüq‹8ªW'¹ãÂŽµm#ñ“û÷—ñIÝÏ0ïÂõŸ ê.³Ø©…fľׄb`;L¦É½±ÈÏÁÕ2ƒIqþ(Û¼`%g‡BůÛ?™BE;¡3’°è5Vš-^3gQʳcšÂÄLif½x4GXB#ÊÐ&{/ò f`ä†ÙóíVŽ¡&͉,7ßôÂ3]~!×Ç2aÞ,×x;ö�J�KÕ"ÙCZL«ý,8 C·¶$žö ¼÷f¡+—/Å’9fÇÚ3˜^¯¾”*šõ &¯õãÊ÷F<™†³¢.ìÀÙ m2 Ë(»?ž5dßÅ6Œes>t1*N¬^¤çñ’¦K4ÂÑ0‹;%zh0�«.#…øõP鋈Þ�ˆ`~–û£ óûŽ3/þ<¾æqÈ­‘…¯õ!û�XÂ"¢�¤*ª�îÀÂtÃMäŸÏ,"™‘F¦»ðÞƒÔZ·ÿñ‹ÃæT Ü(-wùgöPÔåQÚóI3ËÈs梜Á/ [BØ —ö*­˜­ÍZbעΰÝð‘Ä sÍ£†‘ôœ˜|”p©ü ˜Q épåN‘oôËÛ^laT´]ÍúÔaI¨ýɺu=Rå‹âmãt(0 m¿uy# �Þ4s: –ªŸüN—ù’ãuó¾@F{žïeŒ”cWÙ·ÃPUE%F?,etxž¼Ñ-Ë\e"[ · S·V„lh=¤ wf€ªöf‰â3‹él kæN}‹’σïÊ]J™RQ­èe³C¨q‚ü{¨iy³¥ êÈ+@ ¦ÜÅ÷—�ÈÖ ÌPDËmXƒ¯ú$Õ[¹ÀÍ-»\¸²×Û'µ²ÝJÞŒòAÔtCèOˆA9ïGÌ%úè­È¾°ÑÂX³d²ô5…mb®ûªâÒ)Dþ¡ö ŽÏËŠ@"Ex8P™´¨xOÄ£pïHòÜ36¡]& Áâ âhšêàÙª¾½ñÜ ( @˜4Y˜^ MRX÷ÂæàèGl_øø]ò%§O¯ m¾|cO† rˆˆ¢pI/�ø‡{Ñ­ž,6J®®J“ áì�/—ú¡UîVÖÒðïÙ0Fÿ_܈÷^dU#� ¶ÖômH€š‡ D�Íd½×.678œ�ó�9Iëoå}Û¦â™é é¸Ffa\’U}©$�¨vDq«ªaK<;_CW·Þ]• ]tl©Í iw®F_á)ôÞ¹ßø¬“3–QIv¤Û0Xò˜fÕ"ˆÙ¯Fé¤ùª`çéýFž�R’þ‘…]!áTTúu_ýºo†Vù�%>¹äZ¥y„*Y‰Î­rÚÚ¦–ÙÙ©žÑ÷W$GÙüèÊ|Ü“|I˜]á1këIs¶L’ €›#"¡×$Õâtuõ3#Ðç,Ú®Üè÷v)GN¥8ϧ&»?ìÊG×n\¶ÍJ(€³µ Ĉ¤V ­Ç��°Ì7ûbì9UÆ0Kădݧ½G œAëÖ÷@î›üT-/Ó�NìÓ•ÙŽwǰˆÓ„äðé—L×iK½¾Çd»©ÊÑ/­•Eþáž¿(Ö× ÷¾9�ñ@¥ÃÅ_Ú�³ëqÖý Y®ÏN´7 s8Ö!xÙ&Gt0õ@ºàÊ ÿʪ9J5}…8Ö6é“×øYÜ%Bâ�mž€¦X@=ÃE©"mêà·ûS?Bôµ�‘Y”6AqƒÑƒ¤aiýr=/Ç/ÝU“¯(ßcß~Ä=¬T Ö�K÷uÝý£^Kë \w@PŒ�ìôfù ¶ïqÁŽä.Wa†º2I«c;‰‹h¨JïçºomÛ— TtýFnÅ€…¬I©JˆXïÀÁA1Ä™Ä%kÈ›Ï̾%9·æˆŸ,¯Â›I7±¥S"â�UÝ-ßXjíVܤš;h»Úʧ-¸…áVŽ||ßðßLÕsfhTH"æÏ|âVvüçP6 ‹?ÚµÂá,�‡l— ù §mmJ?ÕõÑ'S`ÇéJ5ŽM"4+¼ÂgÖe=~¨ß3 ØÜ˜n);¹±¨$>"qÖÛ�Œè׿­¼µÎÎú¦ÅØ*ÆžÒ·‡£&`¦¯eéÏ–à ˆ-Ãb÷܇¬s� Ë'Öj'ãd²x4Ê ŸI6dluv^[E>e@7£! թД˳ÒîÑ/‚dïžÔàq÷n~ð1 ND8—gî¡BOUÔ\ò í#Ú̲€“xêtßáxôöb�árÆmÕ]lG�߯�ݵM]%\5q�¯Ôu°ù!/“ñî.äh®BÖ™Ø ÆAØl+¢ùÓ[ð´¿±•éÍ;9îjŠ;~N¨N®+ôè¶«IPšü^þ$Mt�ÅÄúAF—y-CÒPGqdZÎ!1°š\6�`bmÿJXá@)Xìç0´íX+²3å—*T†ÊoÎ�ß§�ªXkBöÉNKÝÇ4}ËÛDVfÑdUœ:J�HÞ‚±LøÄ5)ïñHxîæílν½œƒÚôIåªúóÇ,q—Èeà½n=–Ì®§…yf8 üi(×ÁÆ6)UÛ׌:¹f¶JÌz(pJ�/� k.5ŠJGÓR¡¼KWß“`ÌÙ„y2lí"̬ ú]:FŽîÁ+» ñä°©ñ,æk -³Ê©L� 6æúî˸À qçŒlÊÂ2G\®0-°È *åmR %¡;ÝWV m08F™YI=±¿ßC½®¶UØ —ž8—• WYÕ®™M´GS;øXw?ô‡#± —餸�ú. ”®NØö}{€N)ü}x/©øe‹l•äš"EÀxÂP÷�9†Êd ÿ"Yìí:éøÌŒ¨8!ëçœÎ@¹(^,øïÃÖ}ÑGðgnô>PÈŸ«÷ÚŽ¡þyäFmñùà/ÝÆsy¦Å«¬Þí¥¼nÙ„Šõ±Ò;ä{G¼~�Fð©:õ¹v<ü7u/â($7|§_Å¿±R ¢øWž*çž°#�ôFÕÊç©Ýrþ|„¨ŒWçO9ˆ¡|ñUw ãaã‘¿Ú¬Âb€WŠ}ÑE¿ UMhñ`ÜÿLRÓÁ~]žÙ#ê�Ôpó7·‚GOƒh+s�\\Hàìàëe5FÒκþÚy?ÔWÿ¸~˜“&1ã¯fýÆ’"ñÊfÁêÈŠLžÁníl ÁN¹�ApÂGáxØfò+NÔ‹šP¿ µPŒÊZ‚Ï2¶è‘ž“Sôh$}zº¶w¨ª@®Üã+˜ýØu>Vnò°_6>Ë6D)@réÆš‘Žk 0·‰¦ázý�.òMô(1Ø^?SzïpÞ=\K÷i5`¬ÛŽIÐx„3åsOÒ¶º!’sB'ï9šÜnTøS]Oz°„ ¬ŽBÍö5bެ9dHa=ŽÙ¤$@¥LãÚ_§L»Ëé¾bǬç+Üg²…Å);º5ø­ƒVBXo�cw@Çz�ÚUi5Ô£™R ‘£ù(°[³]®ÊŽFgkÏŠb™p’¡ZÃdÎ[X=’˜Š<ôÁÂÈ‚áðˆ+þ˯³¡ÛœVÃ3�ž‡tÇ«�Kxó¬¹\ÏÇIPÁ¥›aGæ»Æ]|^7}˜àfû;™"Ø` �ÉOÌæê¢)³¤w½¢…»Ì_ }R™>Ò©ê@,q’hÅ~7|¡Ò÷´5ù±�DùY$õ§Ù´é†_ü² :Š<Ë?\@ÝäãVÏ(œ¦»Q«škÙ£*ã]ªw3ïf‘öùX¶P ‹oÀöº›`LqždDz-ƒø»+·{×GëTRà\ˆm0SÁ·røIõPf:b3s”ríC´µõ™T¼[YžåÕp;ÝoÊÝ›�]£Û–°y�Ã*{'?xv“äÕÍ�oŒLÚ"HÐM…»�YèF§µ £¥ÎôðwkÿÅjµºƒ'ÎSf)âO$jÓDØ}´É¦¨1ûh1ô*•4G´}y³®§E8†IMÅZÞ ³•Üú|¢|�ó�kLžWóþåÒ5>ndºíÊࣚÑn;sº¤XSœãì nûø±z«–xBµS<ñú£³í=¤¼ QDuÂÉ®ZüL*x»®‰˜7�¨&™|YÚ¼°ÚVy]aµÃi'ˆ*É §jÎÀÌœA.úaRÚ¢LéfÑ‹nÂ2Øqp6�nw'™!o|pÛñíÓ3ºê«Ó– [$_THkÍ’Hö ™:(â²¼oËd¤âBz,ï×ð‰PŸð ýSâOLçe7.sÉò^‡RÈÈq[m¸ ,¡sí3>èä±ciY!ïüð…©ª÷žÝ®ÍMtAKo,ËGê_:¾+TÑw¦Žü¬èt9íX’%r;{‘ò½øÈ÷«móÄU²ÕŸç…½GUî³$°˜)ëšçH"@�´VQ, àÁÒ÷Ö6¨|4T‚iÒfp�‚+,u)©$«o—”ê°�+û¥)/€Ú:[ÛÚ< L³¾MUª+Øø6ý£2-îà[^*+!bURÜe� ��B óâóÒ–15®a|¿÷ÓAüša�çÚ \JõÝàÀÑ(ó�áw•,'Xƒ 4À©@¥Å(.ë'óž¾r?„è¯÷‹û®Qï /à’š²eJPšÍóIäø¬Ì‡ÜgÔÔ=?MèÔc”�¨ý‹Ÿ . ¡ƒZÑœHCaÓóOk¥'˜­È£y ÙS3‰§Á3�¿ÿúÈJ ш;³¶Árú¤•Éê ó”~ô9ˆ~mJ¡é[FÒÌF©�˜j;«eÿÍd‰Wi3ªÁáyÆË±„Ö#þ²ÆÀ.Vÿô|j·÷),ªb)[’Pqe£°L¿Ü$`�T’TùK‡HwÅpÑSeœçÜæ{EÀ^¬ðoß…¡æ*w¶z7Ìõ³ÈùŠÒ'ë‹’ÑR¤÷ýM1—Ù&¥„Ž´6Œ×å—YÑD£&ð>Yº8�=Ù«_g Â3ŠÁ¢nö•R²ßé¾Õeþ‚Z¥Hûvâù:à‹QpV‰¹sü,LOîãÆ€*ýñ†ÛÂ7Nè‡$yÕ9N,Ú†ïËI– Ý*mɆì—GšT9biëÉ“ï³Ý^}âÁ[Ž."ŽÈ¾öt^z”üBâø…¾?ïO«Ù&4c4S¸fƒÝ^Ñ w–GÏ3‹¢º�Áø×%ÌÅ‹· ”ß[ë˜ÕÕä5£t´© ù¥ÛWs–~&8(}g€,Ìú8Çküµ.÷yA``§0�q 6²®ìýµibsªZ,˜—(ü#­:ÊKySÈØÒ»ãO£’.äAæ‘Q+1Ç ËzmEAÄtÊÄç8mV�òó:œ±v"sIO”åL˜g¡~G«+Ì/­Ýd©ÎŒ6JúÓÝ›xæRX$ñniä¡3»öoûsøŸ·`±óîe(ÛDik%:'óø>É„*Å'&ª¼Zb 7g«ƒà;CKýðLõnV1a{í•§4™ {›_<‹p£µos;µà¢¶ÏxùxƒA'Ž;6ñh§1stØâ÷Â8ñ¿ÐЉ1 b�_n;>B‡7¶¡\<œÌë‘)\˜.M1rïgT’¸ŠÜ¬mÑvZ•=^hZ@ëncËþ\—Í’Ý¿uÐB¾rϼS+ i>e’Øèú>~‰‹Oýσî]‰»ë žÙUé¨úÈ‚ˆ¥žôøç+ÅÆ!ÁèU!Ë<:ó‰\”Ÿ`k°Ï]'9 *ñŠ ÝTÁ‘°Uæúkã¸B­|Ч[¾µA*)�˜ê7̨7# ½º·Ã2)NÑ&Îõã„%3/°öC­ÿĹåJ¼ð¾�I΂4ši«9Ñ@'R!ð$"@ƒ³ ýu¢f(oÁ?]®{Ö­%þpÜ“ZÓ ßÒΰ“ùlØ/i`LO/� NRÂFó.¤z²†}DŸ¹S+{Ó'+KŠÐkîoIÏà¨8lá5ÄBûZ“ÚndÏL¦o(ñ·9êIãýó÷9\"a×eØ/àþ2åôl”$#«áÐuÃZX¥XŽ ç˜ââúqó�Y/KbÔÒ¶Êa·ˆ¸€KÅòoŒL�ðDi²K3=¼2ôa¼C-ɪ™.%yN0ÅlZwýâ»2쥑}6Ìþ‘(l‘Ý"²×îÄjRŒÆ•¹ó@¯©Êömkîè{î_ü/FEz5룟óÙT1ËŒF“¸Ø½[¾ç)§ø1†Aʬ?v®z€¬ìi‡—ˆ\Ãd.Ýy?ÆÝ_ÖôaÙ¹mÝ/öƒKAKb@JÔ-½dº2e®bé•A@.­*Ì>ä'8‡x!çꋃ7@¬W×øSõâÝŠ€¯yÉÛÀlD?pDÑYœ¡ÈÃvý“'–™Œ2C"­7�ûœ/�Ðãê劻 §ØÆTÍæ“#Åd�e”AxjázÝ%Vn=ˆÜ®9§ü÷Ë‘Ì×ZÍÄñîwaÄ*÷z âà 4É“Ää�¿‘ØšP#ˆÂôq7ÛËŸÂûL"æ`�eµ:$KÝÀ Dj ì7Œ•þ¼„Ô{j0Râ kA ¬Èp¬\Cû2oøw—@ eÚ³"t;˜±Æ 'ïMú2Îu$ìŒÃ6S£<¸&‰ûÔ$òÁEá–ÏÙ“x™…ÐõömQÞÍ.~ ?”DﺹÊRçýµI¬²‹Šj—¯u{Sçžgï²Xð“Cx]FÌ�¤ËA <…×úÔi]yànV–‘ÿB³Ý’Žà·Iö÷*è‰&n}Á©]ÒÔ?ç“ܱl. zW&0÷wæ”B¸HŽØuÛIèL…ŒCF!^‰²Îy2�5~Ûãºpt‡sþ[Ì«f cû¼¸®ÂQïa ©íÈ^й£´ï“$�“cɤì•1 “ÙeÇDÊUƒ ƒV5Á1*–¶�åôþÈŸ.�4ϧ¦ÓO3Å æçÔJ¶ÇÚ´O0²ÌÚ’¨e‚P*¸›a±2{ÕV“Mý°é²ÔY��NúfÍp`1ÇéqNo,©=O=9©­uA„ùmWÖ]ä}¡l>-"ä=¢þ�cdùI›ìÕÖÕê#Äsð8CHÕÕl\ÙÙ3™Õ’Á©øœ\—ÝAŠÚ¸Œ¥ ö WÁ½.aËïõC¶Wñ˜&O‹¯Ýg´0[µ¶pÇožÆ.¢úfËþë-´y•*ª™WÑëúH-Öº¼xÖ!¯6ñ_à+¨òô½ÿ @ô¿ÌÏTÜý‹ž›NDƒÝ%-›þBªýñŠi¥È<†‰a:Õý¾3÷ÃJCÂ,DBq’L‰á(á&¬_úºi;†R“éXU3(õåÀbÔI¦&ž±ø[—ûHš]Z,ôø–å#ì iNéêD!aÇNm‹�dõÖŸ€\Åt|Në…ÜΕëÔÒ/9û ×’Ò »Ë:ÈSÅå¤ÁÍøØJçŠ\‹Ú7³BH#‹CZ>UÕç¡#Ðèƒ~¦’HÔ÷œd¢ËKÏ®)%x- ߌS§[´aÓ.4�™¸sËUh𠊰³ª:\˜Bû—šÜ_Ú'H“|0�t°¬\°=ÑÑ #”6uAÊtÏ©–Ywü >GÛ�˜«‚{Õ8«òQdÑ’�ÐÃàÊÀÒ =f úærÄ  ºŠãÞ*òZîCxžŠé!Ÿ$¿Œ�­~Œ®›µõ$ˆÞ¼(ƒÛþ»‘XJ Ý÷,‘­hE å(—ìýïØM:OzðØöÕÈGÈBSöý‚µyú–U_]‹Ê2SC+c]qkìÑ{‡ Ö'*ÕyY‡2¹,0Bü† *WÖŽ-ÿ¹È©aºD{`EèÏj—Û‹Êl ÝY—åÓÀijΛfŽ'ñ¯d›—çÖŒ"• ù7|B�¶ ¼Û¾ îè4F$£¿†Á¬öùŒéŠy ·%4ßбæâÓq°ŽôÜHº¼¦¯?ÕN× Å°¥t÷á0!9ì�î“$.Þõ.¸´[Ã…`Õ©êSÛ�ߊÐ4²!Ùô‹Þ*WÔ°/דJ„;·EºÙ1eKÿ{?ÓrgFŽ ±ß_0f¢Ä8ƒ±Hœ¹†…\¥�µ“�ËÌùD"Zuké —¬ùçýJØ«ZÄnÄž¿u¢ æ10nŸ ÿÍ6_<Ù#W¸�¥S´J™DëéC“? 3°ùÂ~ù§9ã�kÏ(¶¢B–ÎÉ'--'¨1þJgáô§Ó™Èµgõ[M!®Œß?ÝÔCÖ!žßÍÂTOmÛ?Ížx©i¥h}*uñK£Éõ¾dDáÜÆ³.nCçŠЯ3ÕìáEPwA5q\•ƒ¢M.ˆ6Ì1ýµ·GË‘½îàc³•Ù}Gò�?·¶�¦jªõ4ÎF@U+̆”BæÅ‚Çú ‡)´V(jü¦¥ :@Iæ%þ°_)á.`ã<ÑR§XÖ#~RÇÍ$ÉÆ 0bh8L‰¯y};ÚnÓF½œ„ñ ®žCÒ¿u•æâ½N�.J‹¢eY^[Æc*û^§†8†oÊr‹qÁ¶µ9“&É'g…|éRª¢žÇào¶oˆÁ†b¢ÎûSˆ’T܇©È�¬>“ëФñù®Â’êMÖ…s²\ß�;¿7®l3È‘óDâ–1ö�Eb÷4ÿl*h’’f�šøT¾ZUÂÜQ-cu.~,Qt0ZOtœ“=øZV½�wäÊâ¯v2½J‘-ƒaâÛÔù¡/ÒÍ⢳ÿ%oÃ$/«#ÙÎ(XUÖ̰Ùû¯¬dÜSÂmš%œÈ…bVq÷É"ŠƬ4%¨úešÿˆ«µ¤ÄPðzŸ`qˆðö`ãñÂûR¼ÛmÁçoö¬8•?[}ˆbumÍ]7µ„ýxMœßÿˆÀnøÙóÔÍö9þ°À+V±Gã7KêÒAÊ’Ð5�VœYÐWÍZ O‡¿Ó”ǧfÞ„¡«ëh!ãᥣ‹õƒO¥¥¶eà³ýs_¬†4ºÃz&ZAÈó$¨�·í‡  V Ñ_¢ý['Ìç}ê¾ê�hýö¨4�þÔõf*­Ó)éJ¤‰ƒ�„9“‹9ÓdÊŒ'##cÄÍ— ¬±çðWºEçN¢è,‚”ű­0kc“4:ÝÉq¶ÿ;VjøbãÓcLÍÿ=2Ôa—¶LXbwn|c�Ѳ“à5ÂÆGäY1þÕ§ å© A^ÓýSŽV6òRÐÔ ç4|Ÿ€†…€kÛÅ'ªèT�¢1#»ÌJŒ*`TK�ÄdU漺9º4`¢ð}DxéÎ*&!“ UŸ›a�ŠTÒ!§Oh …ŠpTøíÞ6[ 2ÿÆ¥ ÆØæ }WqAg¡¨ÆVÜ tŽŠ¯þªØyŽ¥†¬©é|Ö.�{™cü3åiÙq8< d÷¨ž¸Ó†S¥’X+¹Ô“�ÐüݵL솰�>¯ñúÉòT}hÝM›–*eûh¦0V�ñ•VÌ×:Í‹ž¯°%™Ô.U F<Ûä†6‘ÞÉö?ýp®´tÔüêÎ�ºvÉÇÄ Ã`ò¤úp\ez©TØM—“z [ê|ëu½‡í±×¢JwsÚ¤ÕA§ïH™$>xM#çѳwÊ0ÊF¦~¿.ÇÿýM–Ö5²�ÄF]!TÛøOïf…U‘²ÚGâ5˦ü˜ÍÑ\^¡¾N)ÍôÉ¿BîÙ‚ Ꞁ'» µBzw(,ÜÖŸhôÐ:¹ƒýÁ£÷z1Ó‚âçõC±&‹zûNE6]çDË5îˆå)½B˜,7 ¬Ä±u–æÿßN'39^°šŸ3¾µD±ê•1kFì|'¬ ¡ÈÑ¥§7ï;8ùtÙˆ§aÚý‘ýnˆÃû'±Ò°QXÌ,`OòøáÅR…oK}á µQ_\û)¡0Lø¬;?�*T‡×TXv¹òX¿�æ5×�Âþú°TY[Èu Ó†dVReüšë=r �•’,'ƒrçúÄâ­ú©¨ê`²ñ$M¿Z,y¹²:#GèÏTp-YøMèÕ÷&G)r%oÑÊM|ñÀPÕ% m Ú„ÒÏš ˆü8O�Iú…ÓJQ±mÄ_”¤ƒ°—Ï^X’ß*Ç žïɘÅ/F¶»”}ª€>Z"c-Y…vÒø[(SØI.o¾ÎËÌ»ù¤8 ªÛcþ¥tËáÒoo?•œ-4þÉáfÀsÄFnWš�¹Ž‹<|<¿x,Y•Í$!(€®5Ùa8oãØÃ™@5\ÚéÔr ‹§qêÿŸý^@åý›Ü.°<� èϲôN¬¨–ujöj¶¤)e$üà·”ñi9ªŠ¿ÎËíòÿP m^p×]n;‹ÒB3±–˜¨÷E qž¾¾·¼Å{}Ú.JˆéКÍ>Rym§äÞ"ÂO2ú(9Aòë* M«L3êꞈªöÖz>cJÔºjYr_Y…äŽR}­]r�¤“•{¦Ó—¦·¬ÒGȆåý×VeR~¹ÈFô€ t‚ÛœNBÕ$è"yß}Ë-»„‡ƒxñÆ(ÅC[n÷»!dØÊ4AK|¾½k&"{ÜÀï­(+&µc¬V4â;X Õj™Gæç× -† ±>âJVvÍ Éì1¼nÈÍ–_4 �=N{—x7ô•ß�Øp4us_»™)6É;fòÔq˜µÓ,«‹îÞ4RÀd'Fÿ—å]¼ &š‡ìu*Î�KU/Ú‡2Ó«ÿ¹‘÷ïDOŸg­œ(šSd~¶×qã·(S®<¨´W h)uÇùóÏe#mWÉBBkÛ¿ÿü;hiÜ-™¢ˆ\áQ¦6z• Y˜áá åÐtŽçÛ¥c'…½Yº–*‡QÝŽö±b<ÍÒ�ý†�ÄH ½„Z kýv%ÃOˆbâ²z­SÂÌ0†pé R½Ö—Ôöó¸½a½9%{žY¤Š¾-1õôK,A\7Øm;äv¿d®. =×fGT{h¤ÃF¡IFh0@rW.0êKhƱÀxOqY42ï©#©ˆóõo$}�oÒeÔ.½Ô2òèI2ì^s®¤Tñ¤‚ áb\+�w~Æ;×LéPE3¦­Žô]A)ÜAW1K­ØU¤0�ýÔ.ò^¼·‡b£TÈjw‡S”mùÄþyß§®Ùu™ß_2Í7”ŽE¸ÇÜüØf’E£Ç¸q¯j�ƒ&º›©�W®�";½k«Ä€æ U¿ƒ`3@'š¸G³¶ýA„-Ú÷ývÄã!<úÝbüSލû‰«@»KZ0*9~‰älïÓêæ#ê/—Öqõítº›³F¸–—œÙXdn1¢/U׿òÑG/í·¹)'¨^:HlBš�€l,øªdˆyuršà¸CMºŠP‰«¼¤Çé 3ÃýÈ£v®Ñ5#èPÏ:z¥OGø²G¢¦B œð¸X‰ôc#rnï8„Alë¹j3Añ•"keø±Ú!·©~|A·°½k@ªéy®Å1…h_XYÔoü0yÍÕ³›sù#¯t}ì�ªv i.8–¼¦±ñ÷jü´¢ “ý´.êÕ½qªÈ2�ÏBì'.-ÂýÕEtde ŠYUI·]ÿÉfý¦þE„*ï}�K†ÀBK¿"¬`™`u4åˆÿˆ¾ª8Ë6±Á÷&SÒù¡¸H1φƒ,!‚øÎæ›U#'Ýï†.4LQº"p7ÉB±üeJe}0áYJ�²°(\#P�Åk'T›^øÈ’–j®O<›ŽõU˜N�M‰|ºïNÌù�–óTi±æ<•º.‚åLº†ûQB­Ox 9å\”¥¡•<<‚¿´¨î”Ý•ôgÃÛÅ…×ä(ºF&\&²Ðb(ªa÷~NÏVE‡bWøðµhh.V^ziwÒngPÛBXä‹�Ô1îñ֨ °Y]ðbÅÐÓiLínãÞú_fOî1VÀXM/‡£(Ëþ a\[ý}FñO&éÉLÁÅjíØEJ)˜�2ý&µÖ*µŽ:‡›‡râŽöÖµì“fðYB`sݳ|#•6;”º¥søy…þñ]‡l«Ð¥;˜_x/xyUq÷=ÃIomàÝFæÑ‡¨œˆ»øöW¸�)£½ÀÛæõ834F™ °¶ö„¬nÏoÏ `� OÊ”  ¼}ǽJÄ{S.* ×½)¼ÝŸ7NÜ©ì,KWtûz¶šTÜDãOhõªéª^ãÄ–·'b„ÏìÚÁdA<1»€y:¸×·é5*Œ¡íÇUá˜&}H]¢¤/Ü@*pÇnó¾r­æ.ca?�rœbüÌPDÙ‰¼®ÊÛ´î΋5ìnÉé_;8é':šçÇŸj\4sÛ¥À;[ÄìøøLÉBn�ûµj÷C«Ë³ÇiÑA¢«êF}ŽÓŒÆI&BÇãR´«ZcFoYx}̺‡ù>ƒ×ÞA Œ“E—ö‚†•�ÊCIè&¬þõRΦ—ç86ˆ¶S£÷ß/¿šYKûÊ0h8Ü/„ˆ,%Ïòõ1°Ì�³¡a�°yÓçiþŒ3ý¯R â(¨í G²â³«©C±PÙ‚ÌÍK“|^£$KÄÝ+èysàIØ)y}ááìØ1w˜Îܱ ÍäëžáH¼EŽË()ÜKx&˜“±ÖÙì†'›ýÄ„O]w�»,ª¨çˆ}Ff(#Ô±ñ•wöäøæ´_Õ¯Yƒ/y™�Q÷X°£AmIL{B,Œ@�rûÏ.7lòÁƈq»ÐQ~KâÞY¡¹¤Šta÷á ì© fð‹ZåM#¤à¾ux×ñÊ3dáöŠ#ßC–ÍíLM\~ذÆb ±œäCëš0ÙŒ‹mݵ;BCMÔ!ÌN4ÖûVñ µ’ª^»ßÑdI¢(看a~jÄIAëPà¡99"²Õ!&¹0×#©‘^­"™F³‚ŸIŸ™´�Š’ózSS·=àäD9“i(KøU{šA%=É8Rïò*¬ÂC±2€ªÁÎÈ(¹AôÄ-uB¥½yô«§eÊ!�þÏc«À„•ï1š‡ÉM>Íüáój�³3DdþQÖ'{:õ,þßþÞ}|.}L‡fëO+uÐ�h!ΕæÜ qŸvJö{à˪õÆ·g ÂÂgì¤VEu?ÅPÇöÝûï…-i,äO™¡4ΰÿáaÒ�ÆV.o묿X²"ìqÅŸÃ=^LEŠä —!-£4£Ðçâ FÃx[‰�[Ód·Ð�7î¡È&.5þD|ê¾ádµûSã­½XĶdÐ÷MîÖ±ã¯$;zÕº7ÖuëJ}ØD\Ð!û8èÄ8ZöŒA"iÜÒ¹Gò—…"–‚§�‚°µ.ï9áiM3H8žÝ­ä»ó3!®ÏxbfO •XczÆ·ÀˆTa)ûƒ`§D�ö”!-‡wCûëÿu�j•RWµ·�@J9ôè¹F¤‘6†ÎÒJÖš*O,“ŠÞ{7$F«±éyEpÝSÉ™G¢ä8]˜pDÂç}år¨³a<æÐ#³–ŒXWšÒt¡1atÜ�Ú”xV :csRVe�â;ÉÉ݇ªÍ™5¦äî¨&^BìÖñ�6üßo±]ÌqcAXn:¸'-uäî ]J¿ñ­(ÿ(FÏù¯Ýø`õe„÷YÉÚ¼`åÚ_ÀÛŒÑk!%¡WxPñ㈉l¸÷Þûœ» £»–ø.¶²–žÈ%°�Šå˜L^Á²×è?¡$›Ôþþ/$/8 RnÖ É(D€Œ³u:,WØPöæŠxsÆ5_y0ó§’ó’%)PžèbM’E°2mN#À\ÉþüŒ˜ OÐ⃲‚î±°‘™Ìâ1W›Á)èŠëF߸èì|ê‘Q»>Ë.¾…â)[Ô ùß É¢öÅ!Ú*'¤ªþ›óºúCéË*ª™·ì$ Ûüάc Á�× K&½M;~aª!Z@¨|þ/ˆ©ÎT;ÛÎú¸sxQåƒÔ3ÔE¦‰æ» “™¬¢5!ˆ4;óFÏÄѽ˜Ažå`šÇ¥@oW/÷u…ô¡£ÓBbÐ CJ:« "Ý�JÃÈî7ÙÄ#ûr!Æ©³l`‹n>á×¼Ž{äÁÿ~�6Ô‘k$”£Ù�Ñ·ƒ¸¤*ÓøÉã&s÷ TYT•™¹ØZ~EaZ­u ‡^»$wë–C¦{Q¥À‡g½”×øzR-‘º¸Ï¿‘ÙÏÿuÕ} � ŒÌyøˆäwu… þÕ½²ðtÓ×u]•al?ëÐñ~II›³¼´~Á°€TZ"Æ¥Ö¼îÄ·ÿÉYßÒüUò6]Îkq"œ±1†’µ{K$ ÛÞR�X%Ë®ëy¦¼ÙÈ©T‘ÿ0”Ëjåë’ª°®¿‘Â…l8¤ )ôDLoM¯H¶w1\ÐqqfÑNiÏS‹onVG­¹šÖVðL–ØÐžŒî‚8e[ñè&| …Ϩ,ã¶i)©}F²éš…ãê‹4¶é�™ºRXê"m¯­6ÚA $ýnÛÝ�&©cZÇÐãrüó¤ù9Ö…n¿)éÜ^„bŸxH½œâßOžÐi@Å¿®q�hn«ÎzB±Z탱 ÊÄæ¬ñ�ÄËSŠx@$èAÕvhô‚ oÃæpT?j¢°H½¨ŽÅ]¢'~Ñ*€7h˜myÌK)&×§�RÙ»ó8ïâRxtV+aê®’îYafbH—´Í•Oƈ銒V�îXô3»ÇuÅy؇aˆõ'L92ý»X‘!¸£Þà î”JÍ·ŽzE H5‚L5‹âRf§XŠ( +5,»—Ó°l¹¬›!p}^ÒãVàAœÊåóÔ°mòËo!.fnD&ˆ‚´ó3äŽHuÿ/'ŸÌZ›r Ôr= ¿(ÍB9?½Ïµx¬§QËH¯?ÖXñµAëÃèt¸Š.I®´&¸ÀÂÙŒúÇì0‰ŸgtÎ^å7uБ,qéñSO³zKõT'Šu‰xÒ#aºŽªZ8*¿wwùŰ=¸@Éüx³(‘—·K–Nw]üÙ™ìüÄïÂÁÒé\©ùþ°ÔÆ8¯®ë %ÓÕeä)‡Ý­% f溥®Ò7IYahlH™¨€p7xZ@'¡… °ð“9xý1Q«Aî; nõ/ãf©mj¡ìÖ�íÖl$»SÒ“xx¾Â7-Bú¸Ä'ÂÉ+­ÙY�iÂÍç¼L§Ü8{/qì:Ù­Gþõ2‰ØåßkÄ­ø-—}€ÌX¥²Øq'€]‡ù[…áÒLí0øæ½ƒÔÀ‰Ñy"<@yð¡XK›£AÛ)¼ÉŸìj€-Ø?\‡P™-F‰>=‚ƒ5J«Ò>ìÀ¢KFׂø4Œé´©­óò>E ‡/Y¥qìÎo(‡ïÞ}0ô•´ÚÝŽ9;� Á#gg+G¿OCB4!6Û-ûZ¨�+�bïèâ•`îßâ�ÉŽ­ûÃáÓ'äÄúÕEqû!P�’kÕãÄöãµ§(XWÉæW8ÎÒ³,uF„g³›TîA¯x^Ù¯$�³v�Š·=š8,1~’¨ŸM-VXS±[ŽI¹` &.¤ïfr¥F²Áúµ<•ÈVÇiØ ì�0Cv꤫‚튷e(üèìñŒ5ÈBdpëºgŠ+š¢ôÕfoy„pÍO[æJ0¥h¢yJ}Þlj]ucãs„‰8qµæE�-<ɲ»¡Ö!¨báö†z¥n€‡§Ø·¶\­þñ ¿ ©É8 Zþ–üìZcÊ2j÷R¼ô4m¢TAËÂ5ÈY¥'ˤŸ.»ÊÖ>§³oFEgò—’ý ýé�»c7òhÖÐî55É·Ìr#ÝÑ Ë XDö¾åB¾Ö–§¢I÷ý<`³Ç†4:™°lSžQm�„šUõ‰´�^=À±Ãq("ßA�?üî)0×G!ºâ•ÊþõêÑ�Þº a�'d­ÕÉq}Ê@x(MÐÑØ#¸kq,Õ�Çüƒcˆ.ܲÿŠ£d™VyÀJ Ÿk5”Ù®¿~4=(#óÙ1„H8îš o¬bDÜ_m²à‰x£~(öC{êb‚l‘·1,0,¯ÄÒ²6�ª<ÚUíl—�”�{³emÃͳ-½TÂl}„ëÌÖ q„8í*ÞT¹ñíGk�æAÊ_k:£¤UΤýfu:¢®—:EÇ ¬-ˆÌ“)4"|Û­,£¸ÛÈ@'äL!5üo+¿�NzaÖB™(:Yäà¿ *gÉÐÐÂöd�9[=üIH=;$-°�¼QAÑ–Qñåü‹)@�I´"âÏ=)oâˆp�Ï¿ïM©ÑC¦ž§Òg…S“o¯[—Š˜²+7qÐM ©|áv1[�†@F¨[ÛQVâ,IsßÜ�póà5æxœ¬BFo¡p‹ÉƒÞ‘éõ„È·7�nWyÜ–jÖÅÎ.H‘æ‘;U� îQÒóÒ_«o‹­ëµ–’ü yÿÞÜ�S×S+ð¿|Ði&>BG[ÜÕÄUjln?‹5.ð#‰aN”΢ã[x"n{tÊ£¯U‹%“ĹоÞ÷jÂÞr+èÌFCn‰ÜÝÿn¯i�´= $Êm©ìTÎC€(ê’ø >í­hN¢°²uBåçx5EŒ½ˆôªËt$è®Ó”ƒ2GpÈ*@VØHôkåS‚Øã²33«Ý„eí�‹á7¿ý•sº�©E�ònÚ\4 Å’M½=æoÒŒs/öJ7‹0³‘8¶üáUŸª6ÁááÓ„–yœÁž„Åm›Šœ 9í–P8Yûùq°þ¬¢m•8¸4rÝ¥xÿ¶TbºRJ,Šê‰ßgK'GÃʶ]×ê%×3ÑÁš§´ê±7SŸ4 ž…íŵâð÷tÓnòwpbS®Y\X¤T0.{J÷<뮄’e,Úk@”úmŠ�À²AWžR’�&¢vÞ�¶|�iLƒ"¹is47ü¸ªX«R}Ë>µ´ª?z#õ¶ô^@·Ždu% æûiÍ:¦?@üÍ0ˆŸ*§ÝÀU_8;४†‡.7}p]ˆÃ0ÄMœ.c—ÑÜ~0ÀÃÕ+sVê…ÁA¥Á{ʘÖ+‘ü¼£l=Ø ÍÙ6ûGHož÷ø¹_r]gˆÅ0'uïA&}½,F/aðÌJ²¢ÿãyhAû¶*èlR½ä·½»„:õá“ùƒjìz‚¿­Ø]×`_� \‹Xº8ßE¦,‹È¾'sº™5M$_Þ»´Ú¤ü-äÆŸÜ’¶p—¥|@*˜LF£µ$£¤ó~X¯Þ�Yé»@ðI¸e”û:ëîÄïÚvX�ظ�:ŠKSïù2åñaÿª¢èü¬z}t¾´íÐïNÓ.(ž(‘ÜR]–a�uñýÂÃκ:«Ò=¿ï{…Þá÷Ö4Žw�ïŠè^ï’ žÎ'Ìkf±á…>]ûhz�ê‘ÇoÀªW/g¬\ 嘃’ ÷9YB—!8s9:¯²_çÀ8+Và¯-ktµDÈA/‹öBµã)Dc«Î†»}{ÒR‘Á `ÙvIJ¥èºÇìÙk<.úbþ2š¿9J÷î�"ýÒ›\UàÒÏú¨%€"#Ø^J«ñ í(#¯+öÔ¼Ï64^¡-t‚1СÏ6Âo�1_@éRmq2:—�eþEû/{’9ƒ)z’›NYå{¸ÞðªÿÒ†ëeÃ) %Û›FA¥³^s½ÕþCÞ¾îßéë›ë•-\{µÆæÇÎ]"r=¿•õðJ^/õ9kº2?V>ŠÒ�lNÄ�EѼ9Üû‹�ŦÑVò¦å# Áè-´ùû}€f>)Ì$øPÀ‡üí |×”-#nrîBài¥ªéx³ ýG:û�Ÿ­F˜Ü>­‚}É¿gO:ýfF¢ ¾V%¶œO˜ôàKl šjÈo‡*ÏÈŸ—�—hâ¯h‚ÁY˃JpG‚7iuÞçÒÐÖë ·HirsƒÁ5Ô‰5‚§llOXápY¥/K÷&ò™ïŒjЬm}N»„­j¶ÐÜ Ø~Ýl³ýkÔ?ô˜$ÛþüÄp×t7šë¤#ý´¹?&P8Œ·ê�a7ed •�Kàç{:ž"õ{ææiÅ Pwo�¯ø�-�æ r½ÛQŽ´?ص‹½âµïàK=w㻿h6H(}cKѯðÉŲ8§á11Ϥ/'&¬4‚ˆÝ¹ìq‚5 ÒÕQW,Iq¥FÜ�x�æòJ·&1À,ËvˆÑ)añrTÌ¢äÛ×f¢„¬$ngÈ‹ñT¶»¬ÛzÑ$:è8Çl‰ù­>ùĉñj#qm¿Î¦ÿ¥[K�¼D›!õHRdz3YÝbþùP–RÌŒâî§ù ý§ó¼P€+Þô"ÓOQýß9íô‡ðÃø£€94ç·#CÄ’ y`0 ”Guɦ\G^hAdZôav. ÞÞ˜g 3�ÅçT[ûk¼üE:?ýø{ÑÍ3Ñ¢Ùq¬ðO÷V£Öc숑ß)uW­\ªŒGÆ0 Ús4CE?0ZºÁrhfµÖÅÛžä™X˜¥O“r`§Wg¶Ü› Æ,T Ïzöe±;4”ùœ_@GÚmOðˆïDÛ·ÀÂŽ?«�ÉòÈåy GòNb�VW`7Ú /?vá&‚ zÁ—ÙŸpö�#‘‚¦9Ý¥ìÔ±kD� ƒ×äY7ÝëüéQ( ߀þªFѹÚ=Oéäý!#p@VBEÕo÷Ò†©ÊþôYìäÌÓ³KÌTbEÂ×ÏG7Ê 2ãN…!k¬hw+Q`ÊÎTÅ¡ í©cOßyœà\‘•Ñûzëu{à>ýßH¶$»A…h1þß±Z¢Ö´ŸÅå¡Â¨·•¿Æ·Ho«š‚ÉÓ…z½�>2 -[a: 3Vriʪ£Øóq›_ø€˜NºýdÑ›ÓÚ�LôÛï"ð&žÈ  Ëå(àáaVa4@ÉYíÁæÔz „ö´`“�CBnOÀ$c+G{ó /ß1+)OåS ƒ1�{:âŒmäÙo‚kl®í0n¶™¾¨¦õÆÿg {Æê«PB®2r³ƒwè$Û‹v÷v+¼5¬nþãõrÊsº‘kÙ;öŽRõ¢l¬¦áq+F¬‘v]$6=�U¾¾¾0ŸHïåHÊŠÌ.8¼<ôîì蔉'f‹}èm·3Þ.¤SÎ8²ãdd°:ø‡Ö P%HcGêµ%ÄdUý¶“b™>õÄcw— êpP[ ÃëÝG?¿Ñí)¡Ô|€úñº8f/œDÄ&çñ¾¸þ5´‘.? ổ48øfHnãPб¥¯ÉûGUéPç’b¿cñ˜Hô$÷ÕG 4~CÈàç¼ä„öøàÇœ¬G?š0ÊZ¨_qEGùÖ»Búb‚˜'Ùþë\¬ØÇ—ƒ§Ñu^åŒE×°ð6·úW–lÛù[1@©#žÃ ‘ùF/‡?º¶£uHWçY'ôtŠÞNó^ÇÀW1ÖŸîŒAô0�s ]ÞΘõïxQµ1ÔÖT'I^Ã*iÞv»HIÆ&Wi)"Ä„8mÅçn.>¡b ¶î3ò£’e‹h2Ûwi|R>´ï8>Z~,]A& Ä+ÈU­„ÆõŽ÷…B¨Ï9ãð’Ï�~DS¡¦%AèFbg÷ Èdrð°U<´ ÈàBF ó×õŽmÓÊuò犰©úÆÌŸHZp$† d’`2¯)#…$VÆÜY`; ¬R¿rH†kóËé<^¨· I€—×Ðz;P>‘K9r'¥`œ.Î$™Îfà_¿wà':LG$ôÚ QlnW�¼ÁrQÈSp¡×—Ÿ#!›TÚ26ˆ.öEø@si,æ^$Èòà¨O›¼ªÎ~Î' /-›‘a]› csàü»D~=/Ëe¼«®á„n„’ð Jâ?þ{u©å¥+Û.gbgÀ¥KÝÛãSëøO>Ûãê äÜV]P°£¹“a7Öñ@¥u€wBzÝ1£Ó ­sÞ¨q‰ª±…u¦±îßRÙ²UVqkÎnßW¡a¢ÊªŒ+)maØ<)®‘Ž"á5–�®õ�hº_잨JXíƒ0öŽ Xe™p7p¼–À×@–@uaYY¨²`4B#Êw¨´Èˆo¹óæÃ$uZù{{³|޶8àqËS²ÁÈo«Æ æäL]êÿÚ‹1£‹ _©�‡µ¹µ(z:—Ù.ŒÄ˜à×—õ%jâ¨��É­?Ÿ"Ã\X©~îØÀÿÚ}C¢Öš€=n+¢®´ìóÚ…œ¡âþR”É9$·üL&¹ÛÃX9­æ¾=ÏçHõÊÜ`„”älþ¬\7µ€cé]ÖjrzoÜ8?ü¼zBÃñXÍ‚�Ëúv‹Qå÷/†Y鄉¹Ù$³{Ÿz)£âÆÜƒEŽ#èzâ…¾!ÄÖ?²¥�P’rKÙ´œf;[ ?�iÓL,“PFƒ·³-°f,ršD¨žêT"I@ß2 •ÈŽó°Î©ßó¬åñùOLŽgsù˜ƒo.ÍŠ<ÌQº ÍU³>Wà W°\£ñkÛr=~Â’ä`h3³C¹ÚÔÛD×ߢ²£$´eÎ~ �«•¤0Qs…·fta¯÷s�­„å³l;o�R]ë<�HÈØ]’ šµb0–&áv}É+B(üþÏ1ƒ)hÔMVéÌ‚c´‡�Q³“—rg˜®8OÓïcïOøHN‰À?¿-—©TA{ÀYi‘w Õ^fÇdPb³ÎËY9 4ÕtÑÜÑñ[4°&ÅÃbzÙ>U!û'”Ý›"rÍÿò.¾€z¶=?UmòÐÍ´ äŠííH*y1_2@€ÞÍj Í�Þ¢€Ns$FÚpC ôsR�´·¡¡ksÜ;„]Yj¶lsäÌX®fíÜc�a¢ú ‚º<ÈÂ;¢û~¦ÐGMj ôª’ÇX %Výôס†pa?#ƒËY‹Ì¡z]ë±0Yn¹M:}½n õ V´g™ïP^ý›D…»›âå¤hô̼ý‡¡Î5ýI¢êyJ÷V˜èñ8Y¹OÜÞ‘£-}š9|ýqòûS‡ÙzDÉCþ*ÂΖ˜Îü�.R‘Ç4z8E!ûí¶@W80ú£øîÚ0͇À½‚´ÿ(iƒ4¿ Œõš×•FSýçÈÔKú‡ãrªg@&t[ˆóemä}þc „îEQc,ÜB9`!ŠU`ÿŽ�>âǯZ5Si0][Ð^²¡›¡màòû“ÓGÚö{¦ìÏíD<Þy<¯hŒ‘”öèÅ|uÈ6ÌNÑëÂ:ý­5hÛsмäÙY7±ž¦(U›?U.{ÿÓ¡ë󋫺°«dšß<\"‰Ï–ðosº¾Ý)¼1Âk¶çtJ<à_™åöBI¾wæ¢bÎ5·Za/Ö}�0 ±^êD�J�±Æœ#`L~ Ƴ*èYÛ;ì°Ë]¥ê YΌھš8 Ì÷–r§°5hŒ 'ü Ñ ~øý êQåÍ]Ù¥*°ÁSB0‡ÓÀ-`òãg9« oÆÚµ±\ÄKÀƒ�;z1kƒV;¾Ô Ì1.7¹4Ìjèz’#2ƒÏ>÷³z@ëÆa[ÃéWœ»ÖáÒåè[hÅ�ÒðG1î“ §¶Ã–êÖ¿ÑÆKxØ �Lt~Šibâ�ákK¶ÀÆaJ7‚#Z¾„§9&aðîÇDœfÃM�Ò^Ã0Œ!îžË‰#õô1¼è­c>¦NNŸŠ#ð¸÷,<_BöJ}¨�ÿŤ»h)U#Ðò•Z<›âëüÉ,˜ H1 4B^‹³ìJíù´GÁ29$�üŒëBÒ´ ºÔ¼)WdhÖÁ Y,)F_€¼’Ÿð)Iª Tõz·´”®ŸxiYºÖÁô%­wŠ÷@U€Ö3Št Ø5fLv£Ÿ™Ø¸50⟠ ¹Ó8AùJ)|‹+5Dä+Qfe_ãFårb2‡2‘öK�V81EÉÒ*Ùé£L<×õ�xLq–û™›<¶y‘׊†RzP¯¬ÊŒ–'K ø±›võw6•Ù¹_r¨þ®µ´I•MGêÞl¡Ø¬™Iî(‹SZO>Åt=ÏÜûAƒe¦öA·ö1)ž#¥J+RÓeR8`ßãë™:«{ùðË âfçË�ÛâF ñ�<öuɱa€Kœ©›Æ=êŸàtÅÒyqùpb<{› `gÉ·TÁÆ|ä+àI™ùO#´¾RÆ\4Ë U¤²éx}²ÊÊÆœ�•…žµe}ãi^FºH޳xïú‹ù™6ºï"ﲜ“L境…hdOÉþ–—‰�¯ø]÷­xµÿ”ÖÓ9Ë 9Íù N°X/Ù†ƒŽXhט¥÷íÁÁ/}"”Ý.ù(n%WŽÚ߸÷î§”;¬ˆ�Á¢_H”§;Dȶ.‹ç.ÜCe.©–(¤_~È)óÛÌûÖ› AÒPÑÅjûgÀ("ýÞ R¸%²Ÿ}«‰”ã*qòaÁN�´§J¾ïDÄ–ˆØ}Zõ‚¦;@ß:÷úH‚û„¼lêä—øúÅž+â\iÊ÷=JIªÌêvbRÊÜÝ„©žRF=Tÿpo[A4€QšÊhÆYO�O"i7·$b)€ÑŽ£$Õ Þ†dï› ;¤îR×ß'›òæ@E¡@¤sÿDõ Ü5Øä qIò:£;`Öt~ñPpù�ËŽâ#žc¤V²n„aœËM%6û€¥/ãá{ײ}CÀq ;EzêòÍÖ‡7‹Ãaw¥™”•ûÅ£ÙŸp] âRà^ž¢Ž¯E ôŒ¾"%ž�ÙClºâ¾6�º)a Ì÷©�úëHGIê—¹v1äÎÝs±±óœÚ Jº]ÿ6(©oRINÏZÁÞAˆŒº|zPoã²fê©`Šéå§: épðV˜'iöæ·ý�”ë´�ÔÏ‹T›“èŒ^Œs«Ó!ü9Üt¤ò `·©wQö ‘€Š'±xƒê©ÇV$?a˜„àWG­ÙŠÜÒ²nÑ)né{«2�é§¹t—‡êøR¥˜ÂÐ{&Ùmûß#ÕùÖ#p‹:�[¼¼€#E¡/ÚðŒ[yY±’‡F‹%Þ5ó8k73c´+-–ØSP?qG¿»Y7rY¥†�| ®“² c85ï/öj¿�ŠU×ܼDÓÜc)þ˨þÆ0zwªÿdQü Ú2íƒE¸<ÁÂØ�Iìø÷qœ’¯ŒñKkGA¥]‹6êç\ƒÑÂòéÏ·i‡N†c/˜*W|ágH†O��(…(¦îÕklWÐnÄ”6IÒÎÞfy‰Ñâ² ÛÄyÝ€'jŒ*¤*Ãþ+ÁÖ W³;A�Ñ[ð¶ãГL…l@9b-¶ÃŒi;IÃo^ÞÆt9SŸŠCm*Øpõ½§º:+¢—™Õ=!9Ap »;bLC ¬‡Ñ08½•iîøÐ¹£6Òm„UãØìŸ­¬ÝQ¡ÐÈËU£W Î}†nÔÙ‚µÛų´E¦y®Ÿ%Wzz¸åZ6D=æ`¬. ˰Z ×�¸QЕê<„?§(ÌK²ow¯êŠ·¸*²yàé#;ŸìuˆÉ}–Vä~�Š€W–zMWwX˜ ºXb§oÎHæzîi÷f/é†÷é|aê< ¢ßàæ¬Ín¢Õ¼¿/�š^§×#-ù§æb 5Ûû2îJEUðŒX_‰Ç<1Õ%>ï¨Ö&`;ë¶<øÈi=_›™ç*Ü\¿ƒªµ )Ý«ò"qpØ}Hb-BYé³/þ&ºQÉÖL%Œ1kÈå›Ä¼£Õs¾Àg$ÓäYA¶Ä%KåmŠØ6^{w|¦ìÅÔ·¸Ø©O2¿Ã~Â4l·ˆdv�÷~­| ÌU(&Ù»'?6O?šF×Ý­ä*FA>l÷’cÈ$_Öï+Ô•ðrµtQGêžäÖ†çy‹™œ°HS? Ø º¯úÌßÜE@öódìC§gÕ«7æžu‡(Ø¿RÚ CvûŠc-¢Ñáø×}i÷³GÞ}¢Òê–Úíòœ#L\†óÁÛ]Hr”Cá—–7úõGü õpù�X�ihè‘ïóÔ“Gà (¬ÉUÔ’òa„Ë¢¢Òè¡�íÈj‘’“·hÏ©^/ƒh›¡ŠÄ® Qyïzl6‡nEºÕ¿Jê@æ¢o.#˜íy³Tx5¤‹yû�¦ÐÃÁèé{™ˆ'�áÞׇ†ããê ç–·~�¼{!-æââmÒ=`¸üïE70ý¹Hn²‚ø:ã8Œºìûœwz±Ýú=…j7õ¢ÈCEM¨Œ5ƒÂÕmßÛ ›c�Í,¾æ—W�€º_,aª"›á*§°Sµ;¿ùë�òw¸q}°¢‰¢¿ñªBdüŸ†3lâ›,‰×R|t@þ%Gâbøxɧùâ¡à¡9þú�â8iµ²;±?ºâª�ÿY¢«$Ï™ß?wpxMR¼Žç¹HÛ7&-P(yÃwN·³� tÂ4Ãx¾"U <9³×{Oµ³ußĈ‰:oS¨ý–¨úŠ"ì¢} ILüXÅPà¼ïCçúG=òƒò+ã»ts½øßDÔH~È“@ƒŒòœ å)FÜékG'ò•~ˆ £Õ)¡éj¤Yytø''Fiz'ÎÃ=3_^Ä€"s�id�ê^¿ßÛSØÉÙôÂ4„¸—šÿº˜Mãe“Ï ¶à»¼.œ]ÿÏã¤O�`ŠõJö^Y\²2sÜAª®‘*Z&‰QA\°ÄPÝÆALÖž¡Óqï‰út+Mñ˜+h¶�½RCì1Ån•’=G©¾ÓU¦ðöü¯óÎ�—�"¹uY_äL`‰÷HÚÌ•„jóÈ3«r–#@ì¿Yþ®�;†»è�zÒnAäÌ,¡Øq¼á•v-�›‘ûzCØäÌv¾Úæûμ®pbm!ÿ¿ü)¢ï®öÄâ{wõ3w<`j_ì<¼ù›Z„úv›ó¡añYSHµß+T+T Ÿ‚Ã� Ì$ÝK×o«Á+¶[p½-¿¬ºœÇŸ�üðôC‚2NäŒúljVO¯ÿ®«ù÷¶(eƒU 9dCá:œ®#”·¶”NFüÄ" ¶T‡˜ I Eq2�íd Ä (›�ƒ§úK“�õ�QF²XáEè‹€ê¤÷@´;o_壷0á‹RS˜“¥êfêù'%a Ïc¸?´Û§ Ø®‰JÜVí´Lé <Þ¤hƒÆÃN½�N R‰r©µ¿ ÎzÏ1 p«¹Z �˜D“FS+¿Ù·íß­áŠî@±†¯Ö0²Ïþ$n&X•å’måè^zoy«Ù3DÅ+« GGâ—h!*³E泉b/f­ü‡sôkŽßwH‡„ E“#Š/ôH5˜�U‰eæaF9LØ›ñ»Ñî7Z§WÀîÝDë”-£O+uf~¸/°š ÷�Ô®ãµø6§Üî�#ªè²ŒY}Q¢©¤­æx :œz^ð:¤Äû °µàˆž®!ùºb�@fu6€Z[Ö‡ õÈ¢°&”g´”�zrix½ÎQ¶íHgšš~Cl£õ51&$ĸ¿.Ä kûn˜ÐŽOMv'¥ñ#nøofÅtÑ+wAŽÈÌ•EÝ>šˆ�ïfìÞÿ�ýóF]¬_þ)fôù¢ýº`œßt¸TÞëew}ä3I´í [¬U¶ß:Å&P²?2þÉ�¤íÒó_—jËÉ¢80­¡ÂXnIï•ÊR¼2ˆÐpqûòø…LZYíú \â-Øfõ¢²¶ì+û šø/½ÊÖå|&"mסi+À  ôéA›¤8á{?ñ8Öö·Q{iúŒ1Øzk5ÜgÑ�h$¢!-hº:Pºx.¹_RHC¥$& wa&¶x†ðÓKô—‡zPÀOcäÝô"1‹ùí9f�‰\ g®aJ ûç#™ 4�¦Í …Œ¬Fz,‚ß}—s=‚û>Ò2`=¶�4Â{î¤ ¼Š›ÉÐ*ïñ(*òXÄÆúß‚‡xC“!ý7ö ëJF3Æ.Iȃ4TÜM))ØdŽ‘ýºô Õ6”‘àáÞ<ó`•Œâ§4¤>Nò A”`”“ÄD˜s$ùE®k‹�¤¯Op�N”êO #xBá/6W­Õº;@¥aÅõ™’H*îv¦Ô�&õM�u ¡¥\šÓøDi‹)ç�@i3 ÿq¥NX:Š'd½ {ã7«œ»È¥;ù\J5nü‘L¨Í¯ÇWz ó{Êv9ˆr¼û£Åuj/¶û¦MÇw�­= ¹ûŒå¨TúšíX¡S¶E˱š ñËÜ"£ƒm¹0»žYârÏ/ÇðãÄ�©½ *;ƒØO9PŒú•Z8ð4tw|=¬E͸¶´ÒCa õ:ÅùªÎÔô©¾†Å®ÛŒ8! Õm)Û?P*ÜnFµ,µà˜�p•M€Ÿiú§�ý‚�|µ4°àâöîªüjûôv¦›³š8p/¬  ’Êj¥À;‚Ó;ÒO çñR§ÉUÄëØØªÿVé$Gq­™B¯p”rSMc¥û]HÞš27r™3Í µ‰kᾌ;ÙÌl†¸é…_ÌL>{ÊtO7vø?m 2»çÿìÈ1A�k~BA–U¯:ÝÔMX‚�  ïÞÅåÊ®úõGâ'lw<÷•_g˜•j~P›úô]Ž0%¡ Ÿú‚,ƒJ›2(ÌdÕÜ0k�Œï7@A~$EîÒ.&ÊuÝû2�óÕà öÅ4¹K]É£ªˆïM‚ìx·Ý�Ýë9ú%0@Õéo/{ §òEFQ_7˜Vo5(S?é_…½ôKÑf‡¹9�BJäëÇÝYÆ(÷³ÏxS)º£¬—ù/a±²ƒä�¦G+ÉbèÚx²Ž-JŠå¿� ë4ÒÔ‚Ì ýW‹‚m%Š øýgøXᩌDñÕ…Y†ÁÅ_qs1Iìˆ/M©(ðØËÛPÕ×ϸ GäAɬ¸°ä±®UÊO¸µ ŠEêü°Cú®]žiiú6ä�¿JøÎó´Nsí_šíóÌ{ÔäñtD¤gÞn˜ËåÂ>¦€<ÜüÓ†Ú«Ñ?ƒáѦ¡ÓÇBé¾½nè†)3á“dÒ§Këý�Ü]ˆ5ºšP+¹ò…V—¡gsq3qæê‚uý%Ë h¸¨þ|6fq0¦ÉÁšw$ÉÊ­Ãì/Sn›sS ÍJ¤Š;ÆýS>®0®O¯¶C€UHîá]•0Ò´¡%J§–»ð3ÃF­GêÌ+c]ã`·WR)φ©ŽX :cZ‹L½¿¢ Ñ¿r”NÃui­Óµ1ž¢›thØB±š§ÝÅ^<1,W„YaJp22hÐÃ4�Mô²Z«+Ö“ ¹ÞYwZ¶ò{7‰ÈoÞ†±§�­Î—¥€%°�Ÿ"‰­’]}³×ÕíÖ·Š�à‹Å&#PÓõ<ÍÄÔ­„X�^-}ˆ®!%u©7ʘξ([–n¥Þ�VèDenVöÑÚS’É +&I<Ž&ô×j4+éÄ dÊöÑ/ÿ4ÊNDF6öd)Ïß§²*1�äu Ç^È“e¡ƒO¯ÞS¿Ý§•Lc|sŬ;!£#½]Z F¬!@‡ŒSsÔ ß.VQO/VpTÔEëeL5Þe7>P8¾§¬O‚¿_Õ«Gêü1ÑóiBæKôr¦Üý=5T­šf‘ΚEqŸyÔ-–C뜊'1%}³ qXý€eƳ»'Mƒ�mzÅSJ¨|ÐG"7ß‚óVP?—=• /ý¼0X1 Q]LŸSuKæ’Z[Ã-UozXd^ü/z.nEXe“cÈ£ 5¨:P.þ`"�îùœléæm‡ü”Ë›6KGåõëIR0ó%’G±ìÜÙÉi×+Ë Oì�í�×ÐK®™ö6v�ƒ»#ÏÐw}V�§ý.s‰ËzÁ8Û.Ðë4jK´`˜`œw÷±Æ¡ mÆ –ñÛÓÙ dÑ·®>à>æW×?-ñ#:9>ÑŸÿˆ›‰üÖø4§)§=”e"̸LêÛ&¥@� pÃVéi�o”•VámßpD©¼Ó šú‹OÐÆ]º¥=¾knVc² ‡4Ð úfŸ‹’ºWhÔû³ÊÕ0¾Ž¦®¸NÃ^æYåÚø+ìöÄP)ˆ•w¡_ˆQWFZ�G¿³õÎiAqEÒ¶æ„^ÅKºV%u¡¢°|å#‘Ãx¼'òÀh–žµ’Âøºq¦p^³‘~'dY{,óŒP�İ’8ôÕȾÆ6U>qï_˜)("4Jæ¿%øÊ¶GÛI‘ÁКÈyr|´²=ld¯Ü¡ôÈ`ï6é5Ä*~—iØ5äa”%sï"ò§{`ÖrH´†íê²³0 2n¡WŒ æ=‰KŠêY¼ùbœ¥Ç"iHXŠ! Iö&sœ»�q¸QÙèN€\©Ö9ÿ§8Ò…Qt[ÎT¾­R“zvTPn@\>%÷6*ÌU’åýÏKú¾<ÊlHmh�™¾êò/gqcgU)½Áw·Rñßs7Û5íZo<¬çè.9qZÌvÔ^~… G3ž#Kp2ŠÙò¸0.æÓ=¡‡{ÃwYG�]ˆTí�YtŸÚ$Ún`<Èí×àø×µ’,@ëemá‚j­@‰(�h_Z¾VøKÝSD"ª„KÓMÿ¸!C;ý’X‰'$ l¡N� ”Bü*³(k´ºç…„�.+c(þE÷äô ƒ»€xñ8ø]Ý'1˜âøû…ðS¬z…˜~n$}dk\80Y¤´EÀyŽÎÇÔð…ËKã°–0P“}¾~l#¸ÑE[lBóäH ´b”þkÕÓÌ-}~·n(i+qv b½—œØôËy[¯Ñ‡dQ$�#×ÊRì}&RÅósîⱃ_.!ôêXZ°XæÉ]×r[ò70ÖÃÄùí²^Z& ¸‹õÐm²sr}ÖÉúÙ,'$á» v_ãs5+"¸O‚HbŽýÑrÃ_ìxa†­HLBO¹…ª+P½äâA¯qYõQ4-Ý/>qßò^òZ/£,ÀÍ鉸Ùþb»v#=Lò{èšf^y>óÑ/?פ5bÞ$(uìýU BeF�Ãè;„šõ�WŸ‹€ü «Ö)–²ñúÕáØ|†ä›DÙǨ&—…1«£ä²�ðµ¼7¸ÎÝ1ò( 'Dî’Ž¾‰‹dµŠ‰¢N”mt§½M’©9•Ĥ(=ʦ¤ž˜ÿ#ç…þËÜÑ;äNyÄý4�1Å»çpZfll,"Ÿ6o±§‚h„ë`ª^•üUR�D*e+ða0Ù¶�¤šU1¶î€œ“…+'õàñ“„GVá“Ý|+†f@±;)™� ªŸ1µpL7t‹³ª[257š:Jۉї÷ù?E)3ógÞ}õ#Lj>8J[¬œ1ÖÀ �¶�mÁÌÝkŒê[)eÝ€³Z#~½!ž€¨Ã™ù¢å¤�Ü7g)Ú�¹%8Üڳ˳ÿþiu8QËÖà!ïËøïaW  ÖOqÑN¶á��³ b±ìZG”¹èËIt×ù²5uŽ÷òY¡ÅU[ˆï3O� y‡ôD7 þ:–2nEöd²³T€†‘ýéGyš/b�Ê<«#šLóÿiþ«j´ªõŸ¤à8X>ߘ)¿U¤xòâ5¸x~TE=|èS™¦%l çàßÜèû¥É0HûÂÐ}éo”­<7‡pÆøÇ�SXÙ ño¡ {ú*F3ЫX¯>ŽÓX"ôn�}À&Vˆ¾€ú6àê›Êûì hðhOOÚ\A�¥…ü7ôV`®=Cvñ(mŒŠ�—ŠÆS$ 2›+Å) ²°ž ×oÖæ.´½2.¾€d:PpL©*¤±«öµíþ¶Ô7Ë^Ø^úiü>> +f€t—ŠU]­¢÷WTÆ€\îâ§ôk¬*<ë45¦s~©OäÔ †F.J^×ut¨IUxÉÚj)A¢KXJ¼§$ZÞ9ø Ôt¹+êÕIÏÁ›g¨|ä�ùsXeé‘ÜŽÄnвÒ3Dø à¢Á¥v¸K²I „- «8¬¹,ÅÙè1Ì1Tø¿ÿ Ô^k‘ÊÜ+ŠÍe¸ÀMPÑ)œR!àtÏ.ÏÍÌzŸ¡|äó¿m~äoüæÌU$2L²ÞØæ @È»íAWT‡Jy÷Oßâað %Xƒ ?¸ú£‰¾¯Kè¢Ð÷ "VòÁæ)tà§<陥ýªœ´D"ÆÔ>èudŒ0«°o̘Tè¡F±ÜÁ©É )„RêŽ4ÑŽ\BòÔn5Añôr«Ï�{‹˜& ¾Á¸\²$êçA Í׋ÛM „²Ë¥ñnK}Ç�é{ãþݰAT¸lù¾Ïeëj¦Ê)ŽBz…�‹Ö$MÔͶ#çƒæ…³>1²>ÿªd€@ q ’É¢:†Ã ÷FÓÉÇ“ø6!½ï)È’ä“&Swe‹þ§!Èû�ѹÍ\@íÊ}n“h™r䘑ÝHÒʾ€îPʾлå×!Œ‡ôV`°J8¹—¶++… $ÀZ¾“/NX.øgž¤,.™i“”*ÞÅ�µ®v\ºŒì]¯‡sŒ© ·‹H žVoâ3ÔÞyua.n‚¢ndE„R�uMKÅØ!ÊfÒÒ™¾:€ÓøfÎâ8ƒŒŽ*|XðJzù…f©�uøIå.A]¾,"6ˆÌb ’H,II.| %£³`Tõ—6â ›êE(#ùÀ9BäÛ¯¸ÅÍV,"ò³|ÞÐY_âKãTþ~õ­ÉçÙZ0:c:®‚�‡iß·FšÚ\7€ûÌ‘y‹>þj}^ä«"&Åïÿµëâ×?ÙÍÎQL`Ùâ2;!(”–"¤%,×;uŽîÄ?® ŽîûP«•xq§Y˜“i½9Ÿx\"‘:ÑÓ-ªÙ:g¹‰*{·îPžÛ«”Æ.XT÷ÅÝæ!”г˜¿Yâ÷ô6gž¹¦ÙŒÌl¯,“4Ÿ~¿ˆB»‡- °»j%œ¦n9bDÝè(1CºA J•¥w¸�E^¡0“^di‹TNS¶ô gSXu™x:hÒB€¢µWE+â#Y^ÊvÈé¸->iˆ>ÛNZtä°Ïâá:x$ÑÌ­©2‘˜€”¨¤ä kß ]±\ ò®÷‰å´ U—'d¦P&^‘s5*›_=9õqF¸Ø‘šŒ”nÙ õ_ïLÕßôg7�Ç/¹��=ªË±‘ÚgäN¢ ‘~ÀàDö©Æ"Â^%Öý��k°´3÷ *Qªu“È=ްŒ0€�2jZ®,oJHd4Ò9É2cF‘íç¨ø¼[1:ØŒŒ¼öüb!X'`ã§U‡äpJ_Ç‚ÝMò ¬>Ó¯Ú³z=·~ãákäýû°j hÖÃ\ê¯d©�xIgˆJ*ëèÄUýáêmNÒAÄùYuo…ª÷ÀZÒ(Åo:›^ãã8©®[pŸ*% ­´Ô„*� ýwÓAP±#õ&™å2ÃÙ–þH�»ãš!…�>9Dø›®OTVW3–Z?ÇzšpŽÏ?‹žjí¹2(èÃÌEz�’rª)1˲6¦7Œýéªî~³‡ãLÈ«3 ãÈæ£Õ&?â&�+ðaqQ“’ºgÝÌUÒÞe¦n& { ¢Ì:£µ‡­ý³“‚Ò="šYûFJÚÃŽ¬sºÿ\£r,÷JËKšÉy:8õEÙä›Îï#IÂXˆäN†®¨hòÙÞõ|Æp�N-)[âÖãò¨½³PšÞýmeD>y|LFƒϒ…Ê”Ø{Ž*ºx]ÛÙLUM5ÞŽY%E&¿4âèhâŽU4U`ˆeìÖaÝyG%l†Ûì/OVÆ"3Ž7œ´—mreßc²æ±"æ§ '_ìhG ‘�SCÁKóX6ým�­\Þ‘UàQéø‹ÇeEq™’e*비;?´–ªº€cçšL kpœA¾8¹2tÍäA~fÔ'Iò‹×|µÙ(pG¨ß¾HUËIVr"9üo6¿QÐÝH*y`Àª *¾…ò¥sé=V¶yjøœ(zæÅ6‡|üîøA°\Mü暟(¸¢{¥’s‚|Ÿ5¬be¹õËjGïä$Þ—„ñ©‡6fšöËrˆ5!ÝÇFÊ“F®WÀŒ`ÙzWW/t§r„öiÊòŒQ«^Gƒœk—-“Ó3κFªHÛ«�Dw¦¬Â8YÊ�¶'¡d,«Fà΋š\«ÃÓrZ\<�¶°ŒÂ~‡öRÎÔKFCË›”$j¢YÌoSž7¸Ë|Ë+>™¹|•ŽÈži‹vKß÷,i?[!�Qu×â>¾Y"[^Þ*ßd&S÷_ïn_ŸTÓþÊ›�è>®ê|h‰f–Ž1(ŠÝþB&ïm½Ü0ýG}*HmÚËöOŒ ¯·ê´À~[´;ˆ-²¼+}®:'t¨gµíbîÛl�v߇8�ÀCL]˨MtÛ4¦Ð6¤~é(mú�…ÉÐ_ÊtvdÇuëS¬ÏËÅçr!9ê6�¯¨ʾåzë�ÚóÆ¥#Öù3R§R*kÛëC.ÁñAX–SC·­b't\é‘(-�yc3»{�8º°0¬ø¸¼ÝââLDP] Út¤lî¨"õ²`Ý Aöqà¤éOŸóBv %ÿÈØÔoE´©°ÖACP7¥)Ž@X„m8n°DûÞS~ú@q&û_fXc¦ÚdŽÑ:¶ãpüÑHpÍmXݽ§¼L‡ïähèâçÒ*æüh2Çe¢ì]@)K`º~›%ÆQƒwÞ¦Ž@‘Nü SÃõÎSëÑ [[ˆ.ÚŠ6[½@ÊóÑR©°àݬ™<®u§Æê\ƧÖ; ˜x\‹ó 7�F5j6òA›9™Ç�#�p?ç^¾ÝPíIý8Ñ‹‚ÊÈ6{› Ö?/£™¤¾ôšštžºËÂâ zqFbò8}÷òƒ»Ö*:¥†âÀÊãã KÒS™Î“–¢.0}…cúcS¨VÁJHW~fꛘ§EuÑ)ÙSÇñ3œ÷ÎÔðà‡ŸoK €¿­ß!õ,½¿Ù±ÏŠô%htWÕî >ŸhŠ‚ÿV8F��¸ðõùoÇ0ÚuĻҞê!ó3�RwžE+M¼ 8o¹Í«-+“ÄÓþD~5Óá¨ü“|¶Æ‰ôêgèFÖZë~uÉŽyÿ†úý]}Ðß1Nzz6e£T¡)‚øø@íXö w=_„÷ó€y^yu;„—Ó_õ‚š�5 “�Šå‚{M·•TZ/\ˆ�«€�ÈŠ“!(r¢XhL Ø‹p*_÷vWzÿpÅöžEíø2Œ›®#­dÁ´C®Ëö�Õu§ñ×AÊ»Æe'qÖœ á‹©íäwèà˜Ûª �hˆª‹RÛû :ŸjKÞk*‹žgŸÎ½©$û¥FM«�n«ozlN6ÜC'ë祑4d8é„i V³€qa÷Wn¬Öξ"±6"®,íÈ•°ºyoþðöû°& £¸¶°nŸÉꟹ㩕´áÑ·¸—1t)«C·Þ¼ |äcîð{iß1·�KÓrAû¶Ñ`ñáÏf!–Ò ‚'mû*;™G)&3ajÀÂÇÁë¯lYðœ²CÆÜÈcûlÒ£“Ú×ÓÛŒX[x—ó Ænâ…{5 k|q«£3LE…áOµXA[wa@ƒ“ˆÞb5wG= dd5“w�±äC«Ì‘SŽY8Ü—÷'ËlÃxɪ|.Îýmy,&¬n€¥þ�oæ5ç” ÛìWìúÅx9á•â*6¹°…Ž’FׇSó:„XjÊàjf]&}Æ"–)™a"IiñØþ¯-([úÆšb�þZT,³1@Ùr¬ðÈù‘Y×p—Vø²@gý‘ÈŠÅdät£Žk¥WéÄš3Û?Ÿ·ÆS³ �q4�”î¸:Ä‚ØõvûîôÞÕì,aïÌCáˆWiK#/‹Ÿo�½ÃÕ­V¨þìVÕa|¨'6½ên ¼F¡NÁ5»Ó±ó•Iƒg)§⸚árQ—a ¥ýHÔ¨Eµ›?&Äû»€|³K8peUÓO×ÊOqížkBá±JqÄèjÞ• �ž§ñÌÖœD^õOÎû¼±'�‹gÔ3ºÙ¦ÎMë7G¿<ÊÕ‡¨Ú èrø'—e¸†X?È8ß:U{tcÍ F²ßãöUál©nÙÒU ÁÈ™ë¨kYð=±á¥:;c�òl•— éøß™ÿùë¼~b^ ¯ (ì„~¯Vø™ÿ1ÏÐ?¶çœ-zë­gÇbòãy#'üåS}XYíšÚªø� %áÝ¡ŠíÅÃÖ‚-9=˜©S�fÎõ¶¶x‚š¼²ã'—úâ„oõ�«X›š/íåWý\K– È4˜){èÊÂÈA× ±µvï[ãw1”FÓvå}#”Y‡%Щ«´\�õh5 —úÎ{ i%|Òoëýq¢:fa¡8@ÂLÎò;`ºcè$úêf‡^2Ô9ª ÄfRØ‘kMRêëKÓRŒüLªemäg–OGÊ, ’…çý©~‘9$«{&o,�©^¹ ‰1GÇ¥9ºùU3åZþ `ïröÅ´�.yéÿRF‘®‘U[ ÒÞ ‘y@RÆêw$sªS¨&mCI½™Y%bóoݘ%»ù¼`É2ÞtìÖË,g탮iáæˆV½‚èAûÕk}ƒülA¦à#:{F}|ÿKÜZ\”M©ÛÁÐø§Nù¬`J,z X8}j»�z�8ìiåâl”¤Û›ÕÄ ¡—è gÄ�ÏÚÔ”Çt‘Þ*6E—CAèzP«‚Pr/P_ɼ±ö¤­š!M1Á�gwYaî«À?i Y!p2E¢µ÷ܾ^âµÎgoýÚÁ#ñ‚4lüùç yÄÈ‹ c½màu"BqíÛѰ´Æ Ãv`@Æñœt€aýƒžÞ�®K„0³�`Qò5µ”$±Éß%EÐÀ³�Î2ðУõjH>øö]áOh»Ø‡Hª7âë¹™8㦿ÎÄé#ïÑÂ{ÁIJ=Óñª¿¢ôpjUþáκ¾d¤#2\S-!£*ãî›ú�²/ƒÕ°e,5Ç0ÑK î‰á@á²MMG7…gdyÝÞoQÚ9äh–?•‰-Kaܯ@3lÚ ¯ ëÓ·K=‚ô#ÛðüA|‰õ€â æî4%ÆÂ‰òà Sæš,ÈÖ¬³&ýíþG“t&Ö¢†Ð¸=yP¶åoÖ,†5Ó«£=×�î»å1?9ÄŒ[Ëjg h ãúzËÈ(�":f¼ê>بa3ð” ð¨™]…¦Øô×ÚÝ«dw«òÅÖ„Ùa¥„ªïææ{ ?‘g£*ù J  ÷g¬­ “ÐÒm?X -��¨Ò&¬]‡ŠT\0 À®_•äûtŠ?ïUëŒ|®D”®Ïåk¶3DÐËãÖ± ÷~#>X)«×™ÿe œž´œ�°i!æ$¹}¹u÷ÜýBÕÚ/ñþ)±›½TˆZyCn,JN¨&ËŽ*h4=ALxd¶ék¡…˜ÌnwçcQQ šY. /`�sÓ"g‰ã¥Ñs-|¼ÐgFÀ–Šá%‚ݺXÇÜJše#ÏÜG˜róû&�¸.Ž„–ÃÎ p4µD±F³FÞ%?œZþ1û�“Ã\•…Ñ’5éHF�²ÅÜç�‹*ëÆº¢pߪ‘^S` êxH–Æ„)Ke`WiS€Ý²U)zõ#ô�9¥Püʼëoü±Þ‹¥à‚d„×#òþ0øÛáô ¡kÔ�ËnG,5&a/bÜzɧŠ3°‚7]‘囫ç!~®´ØÀ�Tω²ð}”ÛósZ€;ŽĵϗZ w3î¥Å—ЀnÑí›­aË0 /ƒ>°Ÿˆ°§¶±x{ÝØ�×#ÞúÒ Òk“rCì‘\÷�Å:jœÝàŽå~ib=IXÐJà.˜"_ |«'"|¢&ýHÊÝÆ%ÄF6DÎ+a} ’ì&p ¯;?‚®Ðº�];›+P kˆ Ç¼�h<\à cÞé6;$G׆Ä^·©K�$Û 1Í÷ëŒà�‡H¬Þ4Ô‘�º»ž?Hl±4NÑ `5Œ·6ÄñàI#B‡[·ýOÈ™(?û(1ËJתµC~Ä@žŸÑ[fÌyð€ëë…½TfúmÝ+ÃÛ™/ …ìÛoŽáª bjÌùÑ3FC¨ßÿ—?»ä šU˜ri{Ä2ZŒ/¤f‡wÞùƒÆB0W;U•¸j7+ôjæÖƒ–—,˼Ÿ}"g�Äȯû†ù!šª~I‡˜rÉ¥›H¾ê‰è¾Û}ÜþÌþ.%^rWÅY|¤èƒNþ7É�Œlu ŹŸ¨;ÈhÜzN®½s;ꪄÕÚ)-AßÃü~«ÓÔM $ïÕŽu›½ÕüÂä5z7à )¸|yÄðgô%ñô‰Ë•¢¶^BhÈÀ·[?¨N Íf€pñˆÊg<…¢Ù,þÁèåXÕ¯]ZG|<¹R£€Ô·w¼n¤<’ oõd¬H ù—sꆟT0¹í.Î1L¤QMˆ ¥U}²�a3¯''ûgŠ[dm·cò‹>Ÿ ìH*îÿ,È�¯Ñž\|.ð4ÃVšŸ¥Ä~=W”âpÀ§ø‘¤k b ~Ƶ‹îæ‰Úó’»à8ÁîëýQœp^Kö;5|a,á›Ì²ÎЦbbOë?Ñ3¹ˆ›ðý¡q&Ÿ¢K aÖ t2P0’Öˆè&_Êþk!ÔÉBtutùñúˆsÇh™Îgm"¾}gý—-âvÌ�;ù²+Ô2+- ”š&mçv‹_xdºhõFzjã>ê¸ ¸ÂvÈþ^Òhw視ëôþ¼øLz §Êûñ…‡¡U5b×纊ó"b\¿ñ?PÆ}kºÊ¥Må$ld8¸îZ]J„¿ØœJ^o,û0¹ë§¬k­›„;§Ï‰jŸ¨5LÛ¹šL]šoÒ©iA:ðÿl.;ÌjÛlĶRЎƤݿ,–Âáˆ!�RΞ5Z>M,Qh‘|¶âûQqøˆƒú•ôgägÏ{ºÜ=2 ž.Ä;ÿË+@žÐÜÍÝ´ŒUô‘Aä�%+FgEÜM$`1KzlõÕ`àô™ŽÄ;û�2`^ÄÇ\â�káX$*×Ëœu#D("i¾ÿáU7½1Ï�²ÒÚS\.9xbå‚–’Ù!âYÛ4ñþgG¹‰‚àÝn(r×A#/|ëä[Ê Sãûö®�ö(|Jâ•�ÓÖVþY�îæ™{4ñ‘YïØq®RŠC’ÓÙî5W=Ë‹$69Š´†íü>5Ü<q$œSÍsøLNÊ+#‘^½“G?S:nü ŽÅß7\N†sJ„óöøh¸ ðš‚ö?]9±J±=FasdÕP¦ÑW²&ERe��ØN'ôßeôØS×ñàš9¢Ïø,- nƒ|b,oA*M =P'•…o $aà�‡Ó•O‡? ZÐâ[Ê�Þí­/tàwMM(&ò�ÙØ!Š›è9Rë)òq<�_vCìè†ãÒ—ÜÄw€uCñw ¹01×#¥ýG’‡Ò Z­9ÀbÓÆ±kaZÝ}€@—C|±÷oÓ ’øZý­Ùö‡ëáe À«JG\WÖgXÂÇð…b‘ÕG�Ÿ®žvøüì”$´!uʸú)}.ʳ ³<«ôÓ¦”}˜áÅ òyrh)ò¹Ç¹äõ¸¾L×BÈ™Òwä³8ªßmGÅýî×xa�ž&ÖäÅøŸÚ�Ó„’Üš™˜‚A�´½þ¤!έ6þ±Êa”ĸ0FS÷Èߑèí“üïR %ØK‚6h»ŒN rW-q¾ ÝËì,2Y­ãÚ´Á¥-ÇšvÈÍÊÁ~å&[°‡¢Éq@ñHÞ¾¸?¶ªåÒÔôŸø~üކ$Öþš’Í–·Y¼1 ó¦5m_îzPswçPC­2�#@;Gö41™ÿÖ{Å车L]X—X)[{±­î)—y?ƒòû ½–›¢ö&õ�ߤkUÓ´jÒI¶Ï�›6ìk€Q½TH]=>ûã Wxd€I ’zóçra,êMÍ]ãWíƒê¶*s$K`©¨\š¸Ÿ5ž¬S<—“I›„4Ë[žÁÀU9FB~±<ø…@Èף׌]ËÚ‹)›Ãü"#áà}Ùi˜¡Ü¸�ŒÔ,È‘bÙãò¶"Àdw™•È¿;ò�»‹ÉXQ�[fGŠÌ¹mX¯4…­F$k]—ÿqÊw°|­�øÇ˜ªHã½—»±ÑÑâ®Lz3½ßWés[Ú^&`A��Rö¾l—û"J`›ˆ§gOtë£ÿÉðÒÆ³ChfÆ^…’ª)èš–¼šG‹ ù¿M| á>@û¨Ðçm‹²k[<.rohϳ0áÏöšïNà‡4ìñ|Y‘»[†¶þ¤·M°Ñ¡P._¨ VýMË=ˆ63Ø¢çàë„P²s~ÚÑsÒ4Êk0²£‘„']á *Gl´Ì0šˆ]|ÁC‘ÉE5ÁyV«VÍ9‹¾Qÿ‹Ð“„®)æ¼àà£ÊÙòxA¯U&¾9å'ö°¼å8>5ýKóŠ—%8EÈ �7ó½ú Æ´!gwMÈ£l§Ã|xn.©Ê’W•Ÿ W–ÑXñ~¤C\˜æçÏúwªìDzŒÝ�¡}ŠÓ~á|LëfœXŸ7ϯ„Ý–¡ŠÐ:„W&öèÅû«”…økÑD¯¡ÚC€*ü×=BH¹âm\J²™žj¯ÁÁ0%½ ¯r•¸@í¿‰-éxR‹¦í†O^Úl•™Ë÷�‘Ä»tàäÕÌXì\GÈd Õú«ŽÅÏÞÉ„¦f_ý.}Ü;~òi~F§�é&Ç8â‘> VûÅC56}zû8ç�¸îÃ6슭ˆ—pp!.õd'¢&TÌ|ž7 í®‰­Õ4HO®[å6¸nVC²/¾dÃÐmŒ�Üï%-mã†SHàÁÕø†V,G!¤iù…šu�móC5ïó€ ËÒxývã‚<½3‚8Á©œãY�KÎ�Vã/Ïû„²™@Zã&i H [VöOKf¨`ÅX>°^ÿwWÔ™IïŸ@BdæËÈ L!­XÌZ«°�Év†½¦iªÀ«¸ß¯X¸¼"K¬jxºSy}ØKp#šSŠ'·°M8Aã[ES¬w,†à/eçº-�ß 2 ÓÞ«üŠ”Ùoï °~ì³Íc %9zào 7ìaæ"Ÿæ hôšò� ¾w¹²óGlýöì–rÀÎ�‹ñ1me¾'#Tþ'Káó^Ý‘úÅwóGš0CÅ™ðµ?oœ_”å…‚SÝhÐ7ྦྷ`%)\Ï®ó¹ÏTT9Îo­ÑS¥«ó„oïFžÜ*åT¬ªŸ¹�ñv¹æJ<…ß^’˜³Oqf1§ m^� Ÿ"g¬ÃÉÙÑèÅÝ»±N …')§’oBêÕ•Ž&Ž?3ÿõrCÙzÃÉ)²«4³æe÷…¥€Àe¦ç7†�ÉG­T�‘)çOÒ¦«IÈ¥^Ó!$|Ö¥”nR°I8«[ðg;ÅçüeÀš�^(Iü[ëú'Á•P™ìåª%´€ø,à_Z‡ê8ègkž<KK‹D®‰iøì£û¾ <蟨Ås¶¹(�“‡¬ “…¾À #?6x”Z"Bƒû‰üKí:I¢£d‰1+ã^MæTµz7Q¤ô|t(!GÙN¾nj˜uIžçÍšGl>æ*ccðW,.™(˜{y „¬†yá˜(|µAEà�)¥Cò¬E °ýórÔ£DÈΠÕz4ÚÛ·}¶¸äë`J¾pˆ%u«gˆ�ÉÙ œ+ÝKp”‰£Çwë¿ë6IãwYlg˜’OáÜ`»ÖŽMì.ˉgcï°jgAŽdùß–\Ð@Øš)°{)¥ =}”ÚÙ63&øËõtƒ¾¯}3$NÞ;²btÕ¹1“–ZÃN6º­GHò•Œ�ÉÂzz:ðûþ¸_>•þщ”âü¥xöï½Ü#Æ¡;%Ï–Jw᥹•z‹]…;¾YZOÀCCÿ/Km�\Àgn/΢}Ïú¸ô9¸i½, Ø'Ôæ½^¡nål›5;x©øíë¨ãÑÓ,ˆr‘Q›[Ù)ùßM™��û¨ß¬ZÖçPÀØ�RóâÐX£J†ç!Œ—Þµ]ñLÕXô=Ðv E‚:j0ØÉMõy0¡¨+0Õù§ú¦d¯Ñ¤�¸(mé ˜«"k“jHζ¡Ë— ¯HÉ*À“bhº<írðšùi“Ó®5ø–‘3˜^Év€pz©Ä².3fA,§žk!V?©Á—¶Yp„‚£°×0ߣl¾„íPOqÜRà¯ÏA*êŒïoòV6U­Ïuuk¥r >ÓS!ÐÒ"…§›Ä/f.ã±2‚‚h«áPSHÙ\Â0üÐpÞ\?"$ ëD®zÜ€»GŽ5t�³~£ÆùØÕ@Ï[Ë[JÖƒrÆ”wlG^$¿�GH:4¾€~7¹¹¬i¸æ|cªÌˆÄÊ’sJ˜£˜øé‹åâ) Û/Ç¥”2¤op™'Å®8‘û�‚µ“šmú­Ž«x *°îCÀ—ËoeUâN¹‡(‡Òa^AÓ_y+ÍÂ31]�ñóoµ™4n‘Ž©ÈΓÌZ´ D+L¡ã¬~Ê_ïiCuSDðçœé&·ÌkÐ6 ¸O^ë7�³i Œ›ì�<rÛPï°×eàðëA4—ç^Ó Õ0ÿî:͹ô‘Â`o¿ÿWgq,jÒJv[jSŸ#áb˜H$2 ïDÚE«·ëÅÊ–ªµ(ÍøEïEœÜ ‘éµÅÅ „ –H<ßšÍ?%{ä'åéíÚ<í Ü›{ÌÊ?ׂžat ÝPTÜ×à¹JïZm>?=€óUü¾/\Œë²"ôZE ÛUÇ!à. Uí ¨BŠ"ÇIT¼oÓcñp#ÕøèFU‹(–ú”ÕÊJÇ L/ïÖb�mK�iòsJ×=Ÿ©Ü×¼¦ †©�øDu¶02c‘MR4Ôèh›× ¼‚¹¢Qµø±æO(ëmˆzZHf¡0¯raá“E¯À\äWÖÄo"ëÞÍîD7”ŸƒÜ$7DƒäåUY| G;§ÂðY�9ÆðÈc"æ7º2/ãuf¦…cjü%°£© X—ÉÖÚ¡pë¹ôoQJ»¸]O®ç·ãÎÄVx˜@µ4�H £×Ôð<¼˜¼WrìE$ ÙË?dûˆ¡Âi[L‘EÄ ±*Q Ž�Å IIòڢآÿó V¹4¡¢gøÅØ’cÑb£ZjT$+‚ûvX¥l["'èIxü|%‹Õ*yB�-fðÑì5§Ömµ<åqŽ �WàAÛ‚‘÷C[_‘—׉<=}ìç¹:F{u|•jð/f»)®H{æiÿz|#{‹û.Še‰‰0Ã_Ÿ-/œL¹‡‡à,ãs"^÷fõH�c�ôõ73h/°¢Â‡7ŽÇ’g]…yƒµƒP•¨‰w¯0Õ1gûßÐõlÉ¡ËÉÚªA0yü¬Ìä î$¼AA5Ù@õ %}é(iöâöO¹ <ÿœ{Ÿû¾×ò~gÍ�c†Ò`ˆþ�ôú’Ϧ]Ï÷!îX'"“âpP/%�¸›�T·ãÈcb/È+}Ô4˜릣«¶^ënVX©Zî@ÏT±:vžl^a¯ù:›ŸÚHÑGŠ‚E.&ߥ–š€›³7é�ð€¢›û½J1¤1Ò�OÒÖënt’µi0d¥33Ý™ìí.ޤ„ă' \^6Àð‚�C̬Yo{ÖZ×Ö(91Ï’·W"7auò¼&Ov¥¢8¦ ¤ª¼U˜µcjLÓ`xfx­�'X eúRVÑ=ͯH� #^«·ðH¨íèœÉ|°�‹ŒNÐzŠ²Ú©;mm9$Óð›Ç®ê»‡5f§’I|9@·t‘Å.™ž˜SAtå„ÔŒ€eˆË<ä¡!™.%J)¬ôÛR¤ÃʵÈ‚¦«@u]³ç+]þ±�rçÑ )hÎ×¶<ÖÈm²‡à™X„ÛýÒÖ/êD.ÞcÁö³HþÀ×ù¶0\Ͱå?5™/®×9»³YÿG‘lßÂÎ ôš ~•*?·ÑçN°O2õ€ŒB2É^?ôLt_©¡ÈýópL6g"[U§MgrQ]ˆ†¡–ïFÜ펅Âa=JÖ�prdiF‡e28)–‘ý�™�ÏÞÔ %`Ú³ÿUª¯�ÁžG{é3—G¸-nsÍ“�Þ.ß;êá<:Ó¦ô€¸ú*Þz«*·Na–:µN@¶6üLW8…°¹òÞ„ÛÔPá\)Vý§"Ds„+±¼‰bûóG\ó)r¤Fê†d«ßSF»ž<Á©)Ì'ÜÓ>+½Gƒ¤ÌLÞLEüPÁæYø¯yá¥k…ma�À%Pr'ØjÁZžBŽmœ‘.ZÝæ¢/6«y×€ÀZ¶|†JôÞ„„QqFâàÆZú×­Í ×ÃcÃÍ-ßbœZý 0Ic[—üs1ßv®Ö&Š–$µ�òWWÖ@( Hp¼ ľQGœ}K§ôÐÉT…W¯-|Jfó–ÊENÍ•Ç$ß,ÍP!@Z5u›SÀì%eùíÎ[ê‚IË!¹&vë‘h¯bfgؽ`V:¾H›äöq¯�ah\Ç-‘"kÛêd®/iúÅ•]7uÐ(·˜ô†VZ»™ à;íô�q‚*ÛÕêË€ž97Õ_Ø�º’s`̵ÈC„è®uD»Åö¢aðhÛŸgë<,GÇ¡qÕoI5‚ñžY6ÛÞ~9k×SKëw�Vò†ÛâAVÖT(m);qè!NfEÞv]žU=h¶>©’A*ê[C{tŒè�†›RÏ<‰vzÛ¸ÚßçF�ØàF .<[Ö‹ÇÂup-�µeÉ]PkÎئþ¨LÎÖýÇ�øJÄ Óùu¯ÑÉ�übH•'¯ÝNOZQ)·L˃Ωø­ JRŽBŽ—´ŠàÁbFœ4Vk°§Z¶â«öR¶¸ð��`�И®rü6ÈÃD�öZx Ãg„v`hÞ¯ÈÓ;ß¡ðq­Ð{kÒ‹£;ˆÁ»Õ¦¤¯Ãøøf3âqÚ/E¯sH Û%ÊX>\° ¾Ó±mØâ‘�óL·°¦±Z&>pŠÃʆaß~Õ.ÁPÞ/d�_E'ó¥ŒM l¼ÇÖI¸:Äø/¨ xV;é=rOo¼11Òš4Kd+£ÊJ&^½G®Ä9•àÍ<`u|òÜŽ•�î{6KêÓ›Fí) ¬nïm ukpÎòuµÝ‡Ž#zºÖø#úü-öé­C/»y„ÍùWfRùˆidÔ¡8yM‰¤#$s‹×&x²`ª‘lÐðØ¸œã�¿–·¹7+EmÀ¨¼äúв1+ÌÛ[ÅøxcÄŒ2². ÎÍ1¼àòF"Ž¢Òlq˜š��ÛôAUeüBrç힟óÙ]Ç‹�@Gµ,� §0‡}³ü ÍàšZƒ‰¢JB¦øã!�G¨:BÌ´ê#FS‚á“S…ºá\¯�…‘�•üÔs¶{U¨e‚Ä÷=×nÞüáE¸Dk”1«G�OÿÕÓ,úÖb–„!ÑØ!hYmµxjç·ÏÒ¹>¥üàªJ¢ƒŽ»GL?½“ŽæƒãØÕ@ÚPwÝI­êÉ€e±{Ñž}¶¾`ýë3=iå!aÞ“�é;ËÃ+r¼Á‘-|oYÖ«wV’IüDØ`B åP¸¢Ïvð«Ó 5³eRÇçmëöõr¿¼l%“d»«‡çËO<«º¶QV�È•ýÙ­Ë'VŒ8î¬UëY{ýBe=½˜I¥Ð‘hTói9; ˜ö®c�%“°‰eã 1»\£ã·�m n¸� �ü¡ÅuÚšÏ@ÇGkúëÄê»q‰‡bÓ‰ŸV9Ø·tÝçÊÑÀ8°F7R4aú8—ži5A÷׸%{)h„ìâG†»9¥:º!–؂Ħ÷\`æ"mêr¡ð­oï ñ �¿JàÈPy9Výñ0³T¾ #аgCPÛg§Y\Ÿýþòp7IÊß._Š"ø‘*`>ÖBxU9…ø—v‘Àhöe6l« çò€¢ûñg'n}œf¦u¡!n¤£Pò�ÎüÚú’“0NÏŒ]P.(?à¿›¥ÐôÐ q¡•Š-ÊŽJh¶>ÿ{ 7®zÉ|±7Çéî Â$œ³;A=WlË3æ�<ŽHH~s3C#¦¡‹ §&H(ºˆòˆeÄ`KŠ"ûÊuàžY�Hö°m¶7’/NsˆîzÿÕŸG¿ÁšUȺhÅ8=FŸoó‹¦0sÕ6ÁöÕ¢ ±V„ žgÒ¨¦±é^aI:^tÇû·²ç[?6„Þ$”—‚¼þÔ`_ÙE„½m¾|›@À×'ÐO�1�]c®Õ€¹5S„“�Ãoü¿¤‘×ìz² «nQЪ…‘ âoÙ_—^ò].M4@3Ž�«U† ŒÔÈ×À 0LÓÑäÊ�ã‘´/Á ÙøÛ€:_û0�]œZ·ªT°Dý™Óàu‰Ê?ñ­Ó´¿ùŒj¡ �¾CàzÌYW]Á_¶ÍC*¹²¥ 3nb´LŠÏ ÄK‡ß�ˆh-ŠQ¶s=‘!ÞëQbýMõÛÓš}åÁÅÚze¥ÔéËÞA.âeé'¦îHÁ�û˜ÑW¹œi ¼í ¶E¡cC©i‚Y.&=Á©D¥]|�ámr8à:Yغ‡BBw½é,ª�ÿ€âî†ýDdSòF…¯Â÷C hË… çž±pà�î­¿½ì8m·_#@�ÆZèÚY•$hÅšp¶’öôÃcþ�†M¸ÇuZþS5‚1‡y¤ŒÐœvgT! Áx­&ü4nw{±’m?˳ÓK-—-Á¤[·D*¸Ê–úÒ kÀ›Ð)ìç¶µb&K{lEÿMfÛ1¯fØÏ¦¼7B®^òì‡ìŸÒ«»|sG[:S ÚÎÙ3|LCÀëÌ„]/æÈ18Ói<œç3ŽK]:Χؚ²¸i0ü 4¹cüÃ0ŠÖm 8Š�¶?q3wvJó{k¾>zÅÍ>f×1wÛž>¨q;*×®µ¥Š+ņ <žLæäIT,O•`¼õÚy©i3Ži¯ÀsW Qn1�Í¿SgKeA/¾*©ò-}Îm2fIù “‚ÜZ+u`Å'! ?gü“AJ�{N“Û•1Шì¨ä�ÎN�¿òø -�˜^íOðÚ¦hcVÇŒBÂ6Ãk«£ÑÖIôxÖíÒh[j‡¢µy”¼9ºÈþ\ç*‘ÚMÓ^O~EB!kn'ªV.‘ Ì6ü+j“~>c¯¶"¿±;>²�+Ê©*› B ôëdM­þo%gb6Y_j²wÅ­e¹!Ô Ñ0ªÕËÎçé1[äuG{6óyÖBzJŠ B»{[ù��¢ÔœÉ�“F ë` Ò·íj[ø ®ÝÍQéÊcN)!¦ÆrE�\"—¾Á‘u€É�=)œdîBàMjï4<€Ý -€é2�𜩠ÐPõå6'r+‚;F›Áƒ µ°±À¢*ÌA#Ëu˜Ï;Ãìf„@›šãX± ­¬»¥>Ð$ÉKWOÜrÑ8)Hà ¹W%žð_Y[Ô„W&$Z§ú :°ðÉb¹^s¼&ÂL¢Ê­´ˆçCçðG/�{«e{&»OØ¡/ŒŽà+¨—�¸2¾B‡˜_'KÁÇÃ3™V”QÚ¶¡ƒ± �¾À×´Ñ~ ß¶#xàåuZ“ÒaD©œvˆ:mwyد©m3¹­¦RÍ~˜ÿ—}W-™vФÌÃbš{Žˆkà¢.|XE7h,u˜Ô ¬u™”tX?NŸÒ(ÅÎYuö¹@ÒÓî„ &ñ!GÅãÀl_½�#ø¸á_Ę`yÆ.ë ‘ƒ˜tá<ØW!ù¤è%¾F"I+}P®1Ðø H¥QîÇÇnçdvœ¾¤ˆÓÌPkº=„�Ÿ n¦(Ö?oR›jÖ(mÄÇ‹Ì ón=I°Ý¼ã8GB¼ú0™q9üŸ< Ê‚n®�Ÿ5L´Gƒ4Ëa9ÅAV{·Ù/ ™z#Ó õëQÕ…¥u†²­û'-·Dªí6I”đˠï9üŒýû¥†Éf à±aùŒŒ¥D#·£Oö´Èòå §L!}iF žÛ ªE©�5X¸Û< ³Ë_(Ý–~"]‰O¾ÇÔ%AüÂQA”®†^O«w£‡•û®­£zp®¢R“Nr€ Û`w1ȉdÁ-N⪆Ÿ�’Ižr �ìšPæœ}DÐ;»…Cr8éÉ ÊœŽ;ª3›�fCä­oÀ!íj(ïd–N¹ìÍì`:Ýñ”¨X’ÇO¯ëò£õå%Àq>´ N_QZ ™ƒÂµrUN uK$ª¼š­êJÿ™ü~ÕÄžw–GO§¡qCYQŸƒä¾Ñ61X�•¸bá¸Ä%Hè›ÅJòÛJ¹Ù}쮉ËÚfU—éGqÜþ:i¬èVru;ÞpµûÄ7(< Âç+‘Ñ08 …Qù…6f,S}MçL äì-{V¥"û,ŽJÖÎY%Ëœþ•'qÀ°¤r+«Ú«iy†ÌŠExì ìäH\nˆöYP¥èÃc27s1p¥ïZ­s•ïœ}{â³U4¥´CI¿®¾l¯ÁX½Êi®êÞÌc" où¡@ÞÛD$ñDzIÿ…òr¤O^#ü:ûå3#8ݘOÖÊùEAœ ¿.~þ¾ÑVÞ¼®)htø÷Ùp´“VvëÚLÈ‚…$¼êp*°ËŸé ff0U4DJ#Ö{Ù¬¿¦}²�t*K¥À>–/"ƒrª:ô"3Àö†Í1ÓV’€|<éÄÞ˜‰þ/”^w„qé_NÄéËøŽÐ$ëj¶²{gÀ!þ§Mè0�ØÚ­*r{áœñBF’a‚vaP¸³}×i1ã6êè&É›-@wñ”™³]È'o:ïœ'÷ô™„ñÆO°tJÚ[Ç1þ[Æ%À㬠y;ª€�-�ìî“N]3Ѝh–âòWÉb‡v¥UÏ™¼t”ö‡"#ÿkØþñv¼üV/<­¤cÁ–[†p$Ó!ŒƒÛµ^@cœ½Z€÷1…¿I×ñ"¯¨Qé$£]ý¼.�ï.VZœxµøóŽL8ŒÍcˆ…Û©òk“Þ™LA‰Øb¸°Hý”‡°¯�" ç+Â�ºC +¯ê]ΩJ>1à"�,Ò c˜òAáÀ5ÖŸÜ;BŠçÿH¾ }‚M_Š´Ù”˜è •厡F™œÈÁ…M}`_¬GµFÑ= ¤?úW­b®Ö$ñ —¦o;ãÒ ÿÔM£`-¡K”d;Õtü2€¢þ/ü,&›ì™U{ÝCÇ9Ð@Î%qxÒdoÏ Š™ò¶q;U„ïBWæ±sEº¡D ÏnôEÏvÌ Ë¨DQk»îÑËxÞòϵúrĦÿWDn}Í{õXšˆ«P ¥ñYfÌ…½Ÿ_Ì«ÁV©ë]⣘ g~#Œp5é&GNAˆct_mh~èžìU"Ã7~5’ s¿lÏ ³mÖŽjEƒâO—,c´FuJëðy!ŒhÄã[j‰)–~´&CÀXEA¢h2EV`è«ìâÄ|ì~dsÒîµ%nY,ù{¤Óxqá‚=Ô �yˆôKMøýîwµU»;Hš’›³#І€ RÀüÂ\‡„“¾$HžkÉǸŒð�X¯Q–2öã.ÏÍFë’N>u2 °|û œyç½×ÆY"G_jCîëB™3ÕÒ«C§J=bÍâá®l*/1þL²G�*4È@V|à:ÞVK‚¤nî}8+¤íÇÙq2íýªVÄëŸb<¹çüRÆl.ýü¯p„Öœ�.™×Zá¹4™¥žÑx[¾S{•~WéKVækz]M×Nr¶íˆJ°)˜ñÚ6åWã3ŠJ“Ô.à‚JyN•”Ãßtú${:‹²á¾gÈõ©¥’lÎJøu’åú¶Ön¯3ü¯j)Jˆ1IŠ6ÙÇx›¥”�0AZ\Úµ{ÛhnÁæØN×ËŠ?ÌBåS6Ç.§!â¿H!U2†ÏO'ƒû^ »�ɾrK8 ~c‘ýl�z4]ÞàÊ ,{•’e¾·ÀÝ+²eŽÜx†ñOågTA3�3�øÄ•þN`黵£uôú³gÚ)ô [BOQù|kJ0.)üùe7óïci–X©ÔQ¨aò L™±%ÇÊ¡,±7úõû|m[Ç@¿¢©}oEüL’bÍ9@ŘþÐ?¶ÕO‰_Ö7Oë´�×<ߺ¿0�óôûõë*—rƒ´xi¤·ÒÅ‹µüZX ´šSñ†Gƽ_ò7†,~hÈpã–G°ìubc?õŸuAËh­B<ˆ.¦+À=ƒ»¸ÔÖú;Z룩úÜnÖ$Ì 4nô º{¢wF²6�°P–=s9/žž‡(§F²�m† âÍ›Œ¢Û[ûî�ƒ_È üç‹„“Eµ}´e»„ qŸ ÛNÀHmkd©gíÌw”ì‰Þ-ÖÄå:„ßœ­ûP‡§E- >Ðyvµb¦ÏþRdö��Ô7ëI)^ |U„ëæ¹xk9ûEŽÉ³Ì ~ù~œßñ™î$]�þM¡ê/�üiwXßYN(ž�O¡è9Ôš â»5è5—„»*ó.È·à[¦’,§ÝÂ}ã‹’¢%ŒÆ{'R˜Àpé¨IEÁ´ãÏF6«a4ȃ俏žšª€æÜPL1 ­�@sü$â@;Ë%¥HÏšÇʨÃßuö?·Ó³ Ã÷òWñ�Ù1ve4Á´ª4%¥ úœ$T�ÈLó¼Âã 2f.=¡ª;“3'¸P0Îkš×Ùy\3�Ÿ x¯,À„Ñ´A7 ñ• 6s6¿×� 8×3Fš_+îY«E³ójƒ—ÚÞ½«z²�éýBì냲ÂN=/Ù¦ ÿ“ ™Á¾ØáŸÙ3·*cÅŸ ”€u%¿<Ô5FÍɤDþÖ�ݛȴË5a€CuäFw£Åeó–½/ªTà©'°YÂñm€ñ]ÅJ_.9Iס¹“±8¢UR{»ñÍùAÂ6ìÆÄëw´×q¿­b €4Qƒ{EtÕBBùÊTJ80Ê´\Ö“ä’WeR-…aB«ŠX_ÜdÝ:±Ò²Ö°ÝÌ3õ\ Ê/4^�ƒƒÇWÇ»ïð¿|_ß’ü´'”®gÁá&´¨w‹%�í0�âÏÛS׫évÖ"/Ê+HÞ½&’geiFZƒôø°Œàb‚À`‚ÝX�j#A|6µî"àŽ KL÷fÍrfv°x%5è£!GÀ‘tgì<[”|LlZfï0²\äªRŵ+@à‰žNKø€és0Ò¯ì+ØÛÄ Þƒ^Ž?L)Ž,©f”P=®>ÀW RÙYuy?c®c›®0‡îºøeöÍJ«…yØñJâß¿ÃæëÕ'¢|z¸ +Ú%*„û�kåü¸@=оØE ;t*È7^²ZqUO|‹©GOžv:<�ÅéÀµœvëžC#²Z»2Ök±�V– Í©A—¨­‹_N,#¿ï¾| :˜‰îe� +¯j·¼'vž%E4ÝàÕDí¹Ù㽤/—2þÃÜHMîñ(Xúâ‰W,Ž@ 2××íD\4þ¨ÐØ0C"kWéŽÅ[Ú$¡-‡¤ÚÏ*Y…† ÜA=CãïûuiÄÜÍrݬyÓð�=Ðñ9QV Ò›æÿ9åÍ-ÕÌg™°Î¸„ÍqãK�+ tXX“Ú‹<è.æeï¬Ôü«ŠíãâVl=nù¬“;Àºèº'´¯;MZNxò,!ú±k5®·FòD£ ÌFùÒ‡¸$³ ¨cLB ¯‰¶À‰Ø÷ÀN÷Ý¡—Ë€8x¢ C‡ÚuêMc/»§l»ƒMÎ[š�õ)ñóuŸ7Âd„HhïÖ˜_r™à+ÙV”�ñ»=3`4–OhÆ–”’á(ÕË¡‡í·[ö2»ªgô‚Êßñä‰E×fŸ ^nºì¼Ä™7L ³Ì‰„rÞ­¥ö‚åJ¥§³'lÞˆ¥+Î7"+ª6{ӾȼÀ}Z{øSxýA³“Ì“‘ÝäK`© ´A`À3|uÝug؉¤®':¶�å#¤ƒ.p&x^<¾PM4äSMà î!ûV 1C�Ú}¤~ùŸ–ˆ†GÔðMªó!�щYÓT&‡Òʱ5×à‡©¼zÙ|ªuòõÞ`GZþ{CxÄ—^kãšž¸-‹­äÕ™ âú¨­r˸BXµ'NÒ6S×ÀPT55±Û0ñ~z`áŒS5âû~Áê¾#A ¦³Óù”ôH æÇ0;æ»ìüÑùˆÛç’m##£qûzòß~É0Í]²àÓ¿¿Q½7™ù5n‘³ºg´¼]AÙ+•s0¿°ÄÑÕYÍÇAÊÜî‰�Kz/V¸Ý~ œ|´…¯çÖæDŸ]23t>6*°½=øÙXÜiÑ,!ýç¥þ ê�àIq™¹mUÛ yLÜ2=—tï è™7ζõ_Ô18MgUóÓCÿ&eesNr”ŸÙekhQH1 vÂû¨Kh¯KþJ.Ç�=,ë¸p'–ÇdᥢpÓ&6– "ëöU�]Öƒ�7šão�Äu�Óì}þúÍ\óò)[¥Õý;ãFe‹ÖT6¤»R^ì—ðîu�HÁ1ñˆutÁvä˺’£�ëWhÉqɦ¤óeô¦(ï-ƒóÀ%”¨×uf𨷘ªÂ¹YW ]L£kÂe£ÆM’\l`—‘¥íñ2þ2"§\TK?‡ç¢f¯éå“ÑÝšF«êök8`ºÂØ“ôpµª^ ‹\Ž…B3CÕ¢ÜQ™¨BSƒ68B �S%­?;Í™vŠž@îã�ôdzˆWn`‘3jàŽál»³Òà’Ò>ÎF±6¥‡¸ý(øä‚¥wmHE¡e›&f¶*ÃH›: ó› ’"«èDÞU§AO×2%Tà’xJ]¥ªð¼þåZ{9ŸêGW)$¯èKï\À©<�ù[³€É¸ãÂB߯¥ìÙ»ë³È2"­nJÝÓ‹·ñî…“•wŽßªè!b-þð'ì?;z‹÷GzºfǦ†®”{›· ª‰ë€‡¥ý$µ©rɬRF›˜wæ-‰›p,…Ê:[ëÂDù(NJm'!”¬‹XSÎ_r‰ìÅEàôSñ+�¦ô „=¨5nlBÍäËú`OÙ«Ðó`l}|ëÛ±›ð£ï£¬ðë5ågs ýÙuþC¾ƒ7ÄG�¡,þÁçnrƒg$Ëê pò�…Â?¤9 »þC=`®cïJôeQs WôÏ ¬y¦[ó¾�«ÍŸájiZ�<¶}'?«Á¯÷Ð%…Ýo¬Ï Æ�Z5�qžã”»�¦³2ëÄmu‹�{¶xÃ!ëÕäG_²ìe�ÄþOpû{ÜIDn Œ¥t”ÑÕžGsnê?\Ü!aÓðÞÄR�Ð�E8)¨£c#¨nŽSqc¿y˜¼ùvbs#¦d/ä&†9jÐ÷³ : Ф7˜z†|¾‰P~rÐuÉåL§#¼»ò$5Žz]“mbŸ¹)Å/Û(�˜±ï·&¯â@fˆÈ®aìC™ß�°25Õž5ârNúVi<„X Ïú¨"N¥N*] ½»ub¼j{C*×÷# ŠÓd)T+7¦lþÂÓHe˜ªWã*Pr.‡b—–B;´ªöψ„ÏøPrŒ§ÝT*íN'å7I÷d`¡Òn‚�íZG:DD 6’SM~jOãœ$EñžO¯ä¬,¡ÒX¦x•ù`9—Ë_�²È„}ˆJR0xÏsï—êʆRvÔžD<¡,ø_VÔ‚•9T!þûáS»)a‹îþŸ{ʰX¤I…¶D/v®Ò9/]6dþœðC‡0 6wUä*X�³¤ÔߢæŽD˜Ëþhƒ¼ÆŽÃŸó9çÏhÖ¥ @šRv‡aÈõ|¿£Ãpåi.%¸BOzoꃭµÌuM�� Òßݳ"ïçu�{µ¯#§Û¨ÌÝ(׿1<³²Á§¾@™ÉŸ³@»0{»C–JôÁ<„ OÃÓûPÚ‡Tûl$­Ìñòa÷Ÿ†õŒ ò‘_¨/2;ÓŸkGf ¯e~Õ,óÿ¦xÚ±»¾Âñ퟉ý%ƒ­‰�Ÿ‰¶ŽÏ4J®~eŽ6G$'ë¾Æ?˜”Y<¶bbÿ8žûQ›noù XB-'Š ¨R¬WË4G¶§,?:Ò;"€ÀË<3�a¦¸¼ €UdåR*rg¿BÁLví$íûu(BÇ;У #_)E­6Ÿ¶0$Ã5¸úï°Ê`£Ò‡“¹ÝæêãºÓ£ÛC�©FÔ�׭ƾ²|.FäïúÕ£*úy?SU‰0Ùg'–yX[kù¤aõ†_°€ÉyhóL“Œ~bE—ä”­ ÜEé…SñÅHæUäiû�`‹löˆ� j`²LlÄBÞAe ƵëxŽ<è–Â[b(—M?~y›‚eûÅTÎSÈçêSˆnÑzϼ~û˜9`[-O¿ùV¸±&”1.w¢ß*Ëé`ƱôÞa•wÙ éŸóT:†|ri øËÔ6U 4QÁDã®……M�ßuz³ ð�Τ�†.ê–ÞÂK¹®¢Ó’' › +ÈS8¶!U•¿X&r„:É;0¦«LÚ¬M;'{yâ@�­|PÏ„ç³é¢¨Íš¼ØÜÀyÅ,�x›éFnØ×‹/tcûL“K¡Úú°êÉaÀÓ'Aa0­uÅ—oZG£u1ÉAšF–®;‚°Ë‰,C©Q¼•S¿³à�ƒSÜŠœ|�€C…iUSÞ�fµNA‡Ö*[…gÓ<üø—/%)´º–TÆÄ·6’¸ à ²¹2TÜAùSPeȇD_ µ°·¿�êfVÈG­Fe®ºú£w’£bŽ] ’ Ù/ö_9]Î<º(E�˜× ÒÓ#AÉéÊGlt�™¶"ÕŒûúÉoTŒ¯‰¸ #~Køe‰4hÙmè½ 'ÝG6ãtÈí)¯g�©ì@}}5=íùIà.z î¾ËT'‚qË—ÃW-ëXBïR½Ñ},BìZH"2ä j—f·IqK?ÑW�,$Ñ �ËãS‚”ï ¡‘p.ƒ‡èÁ�„imMbÉmrSO8NÅ! 9â LP5?wÉ`µ™†fnðEÔ[ë2öeÚBñ‹�ÔýCŸúe¿ƒò�ß6T{é-Úí‹<½¹÷‘ê1[ž¼KT„稲zKZCŠAšY%?—ПßуFèQ«§àw�³ï¹˜+}H_m2¯ŸâÔ­=«ë A^æÀ™¦ßTÊ‘4ÃT¸´‹.0Áoç£i€¨À—Ž&Óââ‡Í—\RÏÖ‹¸/Õ·âþZÄè@d�_ïýµþÞż7yvøQù ùÏJóiBŸ[xt rsm«iù‚.ÀÛ,zˆØÔmŠà–f÷åkRîœö;Žêq…¬�‡5~ß�?U–بÓÿéHöE„ƒ°Lð)Ã~ ω;šÎø¶ZðpHŒݳ­•-HÑ»IáùW]Àâ¢Is…ͳVõ]ŽÝ\>W þõR™Ï¦[½*‡;²9 x?‹TV'�t•Ðl×�++­9qI¸#.±2èéó˜·'£æûfŒ[Vfw̅ůq‰-ˆP˜á�ãÜÞsàô+?ã2Nxhž†0VhÒ(‚Öžœ�[çӤäIŸ�6$éîØY¼½íÑ«¥BQ³S¾qð>c¬r²{¯…¼–ˆÚ‰LWOú $q­bL®ß’úPJ_CäËߎèßeA\Ь½&e€BüGë^°:åî£mhº’é?ê£Ú¡ „@k÷�Ïvrï+Ø´N™ Ät­’2: ƒÊK5ÜÚòó+fµë°}:x¦×µK¸_.zÀ<åG’ìÁÊ!d-tΣpd^2�Í7EPÄ™ŸUs¤Ì Lzñ­Ÿ ë§IõïCV)V]�œ¡û b\3UYR¡-ý* …~PÁ¬YI=Ö—8¾®ï&EF^Ò´1κNFMdvÆ®ú«=iÎG¤„ìÎ9¸ÏxÎÔ6!{’Ñø+½ÆK8›ŽîƒYWügv"|÷í¨�·À �!Çν†œ^ïS†ªNc`ÿíºt¢)Ó2| ÑÁ� +<\â‹•CÀlíz·O ƒÁÐOY åDo)Xëc7#¤ßô¡S‰Ì�P‰BÈÝÙ�.KàiÀx)ÈFá8¬‚H|óÙ½Nœ»ô‡ç±=m„(â¤ìí~.㌸+±>Ùã€ù4E “iK G#a›“–ˆÐÛ¸c'�ñ3Ñ3ºv+Oá²ÝkX)ÀY°è¶Yë4z}Ù*Ë™gNzuùë_­MÙVvØÂû¡èb”<7Êý–A \Ta–þY×}`ä\5G€ÿÒ�¿¥cµ6zœêCuŒ¶ö�­ŸÈ©× w¹Sù¾¦Ê5âÎíÑï:לi+q·5X»(ßÌ.@6gluÄÆ8 ;»ÓÕ£8&®¡ ŽÞx Ü{K1”„ù‡W…e”Ú³¨¨ß" †h `�,E›ÀØ9bI÷I›'nðCÁ{Þ9E/í h ÈÕ£D$Rø¾hßL:´Âh8¹MQgÆYm%5ÈÞa,Óöù[ÉV´Ì«"tä'-.¼µö¬N—æÁØ{.—Tl©Ö/œb�‹¥Ø}6Æ6½„ˆ;LÄâÛ]ܥܤ­¸>Ñ»2¢—kÁâÐçs=oïÈzÑŠÐM×ù~È€Që(Ÿ| ¬4°ù�Æž …Å]& ÀväÍîú~žX¸Ÿ2ÚÐTŠ2aþÁ©¾fI§ƒG.|¦¢Ôù¬BbBý“iƒ¹OÞ 2Œ¼dU߈oÁQAµŸ&þ®Íb/¹òÉLv Cþ„¾éxXèü“Ž>ì»ÁvV‚ñÞ"6P¤ƒ½?5‹ü¾Ê¥yqím7iæs²"åh-K¹�„ÕmÙBGt°dð½ÄõY)ô:‚V,VvüGŽ7RGÖzð£ƒ%ùÁºÍiÂ:ý=å+”lîh“}y�BˆúÔSÅýœh‹Ó¯^0s]@ú¿¶*v\ÒØïÝŒZAç±i�þ$†3�LnàÀ G^mÓvùs5ió&ü �œzKˆ¦/Òì Vr‡êt"öÄDEDZÉjpjÇ?HrÑÅñæ(/�ì�È0Y•ô=iÁ’Y펪U¡ú;–hT4Í¢{¤kä²l Ä!ºÖDŽœ¡OŠKï�NÐÁÎBÎyçT�€v}á;XÇÌŽ W˜íD~J<î:ÈN‘×­­Õ$ñU¶Égg6ùrk�y^„Ô»ÏÞ´F“m㈵~~ $pÌãÀqqå=`R#!¨¥AÎmEò}cªî‚8n/縰óÿm±» Ì·½FP·õTä®ôøQÖcJ¼s%�Êr†à?ŸuVñØ%[ãN‹ë,Paû5R ËQÚ¤ž]UÛ}™Á å‰Ùr°ó wðJ’¡Ê=K†‚Ÿ§šÚ‚'WÁïœ0ɜģ#?$Œ¸AzÑ,�$…Ÿº+srå˞ʒ3£ |Íܺƒó;Õ[+Lxî•ôz¡Ó+ZÏumWQ{ƒeœÐ„®*\•ôxÞ�ÿ1—?êþ·«¹_W) Š"¡;¥°g½áˆ¾IšÚGG,©Ê‰í"3/�\äÿA"K­½“ùóœ8/lMO˨^å—pf [Ý^ .@9õ¶³n*‘yáòãNlr˜ånÈhtCá"Ô¨‹nã.F\Pƒ°þ:=I9—Ó]/gÒö~~Ú4Á‹Q©Í»%ôŸ*U˜]àÓO~â³ô\?Ú¤6…�(·¤ :°7ÙÍpö&U³€€åùŠâZ)gFÚÏ4ÞdùÛ9=2¥�!Yy E°ÚMgÅ'2{åÛM™ øZ]³Süb.®ŠŒÕ® ¥³eÚT)Y%gdq0oŠ {^Œ ‡WW¼cÖRNU‰‚½XÎ8dÜáÃ’!¿œ¬ù¨æ%ïH™/!áë÷‹ @ðÍ®…ò‰; (©çmH %XÁûovZÞ%¨( .bU#/èN‰ŸÆÝžÛæd·VíšÈTy*@¹-ð,&•W×7ÑN÷ÿtAr‡¹A٥ƞ(Zê·€>c¨’F~^PàØ|‹–Z 3[Ug¼© §3àe‹„¹4×ØË¤:Ð*Ž5˜þˆµë=�N<±Uƒ—Y %Üþί5\:—ga3$¼W$%“Ö-½ES"±*ð´ðÕ…¨«ƒÑ/½í»_·òi3¾w4ö[}í­ÿ×Wò8íÑ O„>Õ¢Ã]…j5弃 ëEÛÙ»U.ì¯O¸r—lœXsR5¨)|)JÈzñl]DO]_BSÔÍ ˜_‘ºù‘y’¿ë€‘ÿwrãÑ\82+êíŠ{¨†F�¨�üÕ$–51´òžæÞû„Ï7ù®ÊëSÉeˆ‚j‹ñìîèít¦ÅìN…wW=zʽ+É”ú«N9Å™T÷›óJMy\-žk¡Xf�룑mc´-2®‡|t.{÷˵»<ì�ÄÎf@mhPoÝ;Å]“4~ÏX³°1‡rÎ�Ä$é�5 Œ’ã½0DäXÇØš=,Š‹ œS\FÏ}“ët‹3Q�eÀJ/)sO¹~ÃJÇ­ÿ®Œ%›‰ ƒœ¥—©A\�‹G³æA_.Î÷U«UóÔb¶%Æ”yl"ûã•ÞãAsÁ‘0ô[¤ïk@A6-a¾Uú¹rwÝ4Ó¡ÒJE1¬a“âW«õ;,'¼øÊv!‹#ÕŸˆ}-뀡93±ovD;Ó5ï\‰ ¥äH(ï¸áô+Ò°]ÊA£ÑÙ­]v½¦$Àjú`…Ç2 CÜž—íÔˆ‡ñ8!EùòÿG˜p ~hZóÉ ’UÀC>Âû$Ï{¤âYS‰-S^E^"œÆ16zqÝä¹HXtêÇì.dîL·> L�/çRY¹þ Šc3ÜÔÏ>\²Gçkó:ÕN%™2¿ô4«©½kŸG™y‰ø}Æ@B h—�uЇQÀÐí‰óZälû¢ÃÜSs°¬]\¿Â[Í<1[ª¾¥qEÝ5ÝÜò•Âøþ,î÷*(çù¡"ꃱn(Ƭ·ü:õ�«óÄÿ¡ÙW#®å[ø¯¨ê¯ÑÑ×ï-ßsÜ%‰]êº8�DF�¤�ÅÚ„mjbíû¢(ó#pÁó�ÃLâîzÉ$è©�-}í¶ˆBÌèì#à¾Üwc† 2…¯ã´GÛƒQJA'i96ÀÜ@H_Ú@Búf÷KÉ)½uÆ}gý�G좸mùk}%.'u÷M§Ò8y¤Òp±`G¾Õ˜4fôйù5.³Ä¶ÁÜgœTäÓyÎ’MÖ­C»L¾9™ Ùµ‚Yü‘YÔ3_PÀ” ;‚ÇB&3I�¥RD.£¬Ä'ˆlÓÙ ˜g$;XK—Ê'çr00Hv®p óA£H'»ù*ÀÊX_‘ É0°íÉŒv×gãïù1)È1hJß›£?ß‹¢Yžj=hÜ"ëÀ–.*.<¦v}ƒ6Q<¤í/⡪5 ñ84P£"£âàq¦$éÅ® Š H‘+ÑØ;�@vƒ¦¾Žº}P9„D¨¯¤:ƒúyEZé±Vï¶24:˜7 øŸ«›·Dú^s*Z/Õ!‘Ÿûø'Yæ'›;°ü°Ž5ú’A’‹«;E¸Ì5¦Ç .#™'ø½Ò§·4Ø¡I¿£!~à_µº7Çm6—Q™KN¤ E•£¼ù”ˆØdlÍ+ªõ©¾ °�K³žOyß’Å?3¾Ï€¨�Q˜©h³ŸóŒÑçtS½´ÌŸEA¡ƒ% *:=óòŸRÝ�¤@VÀÁÛAeqá pm°_…³ Cö¯zç0§~}I©šsMj@ˆ¹'{83ÊÏ…¯,Ä›f:±šÄª=š1.çYÜÂ’š~w°×¢U˜R³'€ ØÜæ¾Ä¥%0m"Ëb{° ”,÷™ÒΫyo5¾‰khì`à… çPO¦�0Òôÿ9¶º¢Üp#–‘Wï\z©q)!?/õ*z^û^3»_�j1ƒ Ó( ØŽð)é�ÑÙìßUj[¦7kFƒêFôõIXï03Ì™áføÕ'g<¡Ì¦´Æ™€h†`*WÇ:�ÁDÌY-ž¬ÍXÛ)ê\�¹Â«²¾O[ÅIj¢S£,ò …8ï”±æº nÿȲá âÁû�6I[àÏO9v�…+ضÚX~EhïDÚ*…‹èq%è‹êG–OЩ×n~��®|ˆ±�»Í>c?äHQ·*ÑÕD=­]T¬¹Û½}±Í…j Ÿ§Èÿ%ÈÑФ08{& 4]n Þ'Òí÷ -Ö²®tZiD“UÞ;(u;T´¬ÎŸ÷쉩-h íPT¼ í“LІ#PC¥P´=úêü;S^(œT0™ÓÙ›�¦|\Ûx›ãºÁâÇÕlØÿ+ ÿ *òÁX"J8^~ Âø«ð—iûl�vú‰vóž�Ïr{¤ÐÈ@[?c¹OA$¬1íÞQXÍTÓ»‡ ¥¼ìÖÈ—PÌwU†Sw½fŽ.©‚Äȱ�Ö’‰ƒ†|Ø%ùb*XÌ�ÏÞŒ¬lT @½=M<²(2 S€ŠElà‰)ècWÙù~ƒLHðy�M9•˜šnòWÊáàáÓµæJ�‹cì†MnqEÉ.Å$°çÛñy]�9ßN¶h6 ïíè8Ã÷¿â”Ì,B?lÏÅM��(?Êyí@�V4ÔÅÒXÖòÝV �àë]yLB²óÝâ±rˆfÅä�½¶b¨”*àYŸÂ‹,¾‘÷VÛðeóÉ =+Al¨¢âÉE=¹*Fó÷ñÝc‹ÌÈõˆì•Ž7Ñ"VéÐòkŒ ¬§ûüþ„à’™k…r‘zâx°\ƒ�mÂïÍ™k8® ¦�çKJºšSæŽ î¼ö’¯4ÔŸî>1ãÒã‰W�„¾À1ÚP 2oCMÒpÝ<å¨0÷ÎÞÆÚ0e|'ýÔ±EGD�mH&v<æÐÜ![€ñ8+c·vôPxxevèâõ^ófòˆh˜‘ø±)”Ïê†,\®$ÖwúgÊf8JçÁc@UêðÛ‹D‘Úê�ÍÜjÃüI¯æ�zs¯‰@ðñgwVP2©‡Ø%�¨mXú[|>¡NÆ¡2k�kS$7x<9· áúÈñžèýÑH–³Ót¸z�-Ê�2¯Ö¥QvìC ¢Ù‡ð0–È1EJåÓm«n»TEè7 .4v¡JízMjNÞÚ7�Ûþ�®ÕñofsAÿûêˆ7hå V�>504_m!X«Ý è”yÃ\6ýòùUT(]`Ì»;�¾Z�o‘tuNÂwCó‡ 8ÖQ ½Ña»Ð‡x�-ÀLª–äÃóF~Þ;+�6¹Ž‡àmoN'ª‹êè…£:üüœ)ç|.wŸ §[nûáØ�êR3Ú»Ž:qÁÆd:B1 û)¼¸¼ó«ÏÙÀ‘ŠD柦øÑÏYŸ æc îá2Õ'N2~ƒ ÉÞ sšÿ—Ò7·Hë Ë#JKß@ô×—Cš—ÕnX¶üx\ÀHU÷¿¹=€Í"l‡WÀÄ?PPh„§Û›¬)ä�MI½xþD�Õ‘I¼O§ N´ƒÌÝbŽžã¸ÞGñ3Å»E2v9$C aî ÔéÀ”lß�P¤öˆT¶áƒß]NÏ£:×m=è“‹ÀUœ¶®Ù�=¡lýµx‰V:ò f÷ÚùNÕ}g,bå”cf1ð å6iàrf¦ž_Ö%ÊUX¯7I€ƒ©)÷YHñRÎxÝÃ�«x33´- Ô]?w qÉhÜÞËtÉ;Õª0ªåó ë uDey³{ôPY¶Cõe·ýmNßÒ ËÒÎÔxdŽ^D[¼#¾v» (âÝŒ�K[Rq™'¡6ä”kµØã;Mð„ä)²­G|Á+Øp„wkd”õÓ·µK½ “O uÆÝñ8s=iíå uïÆG¸kthƒ�×§ô×aœýšj}áæ}}@°ð4€i5-çÎWM=@Ä-Ü  .ÈC#&ð”H)‰Á�¦‚ß#¨X¨É®¬“Vs²:ᘠU²�©ÄD�B£Ç”fë™Ôi�'ýsÖ…–§Þcy>rÅ6ŽÅ‹_³oèPÀ¹01ãȈæOJIîͪ¡®Ô"½�zÙº•^Ì^bÁØ’øÊùp»|†¥Ñ�nþaÑ»›ŸèKoeÑbàØ§ÉÛâœ-‘ÚŸÜ3�FnAMD]FòS* üÞ£¨EF_Ã,Ãn¸5ço †ÊìWƒð =*o•ÊÛ–•.uÉ{óGDÎ,::ÜÐÉ— ˆ„�öQ(ëV}Ö‰ºçz(Bìr¹Ú³,â$q¹�ÎU5ô¶ÞÉž©z£ªçFx›Ç2›|€Æñµ•®k¾'Ñš¬£ŒaòÌ7ÝØtR—¶�/•Eÿ²<í–ÝjB¯s˜WæÿÕ¡k'"$dÜÜýDœšýF2êà ÖaOŽ=‹è•”mˆŠ6X„ˆA÷k4ÏúÈp.…pù=?´Âû³”äŒrµzA:¯œ#=¯ßV[hÙˆ±föà&iñÏ1¼ ]?N‘6½�$†Þ.OQÿÚ NNÁÑFjÙŒ‹…â_‚™ã–x;òëúu•ÚÆ1„Õ öÓ//�¾6…3)#ÞC�öC/ ö€‚Q-è :×ßÓ‡þ‰SœnwÕ6Qy¿áŒR³àû/þÛ4ª: ª6ü†â¢‡j[I@+YŽü±ÐAådA×èÝ„hW²âæc&˜/lòùBWôðÒÎókB }]4:É»è‘ùäͬÈþ)^Å®§ñÓã“ÅãçsécãzPwž\x[6ÇÁª�Øë~Ц(a –tï�Á¥us|B¬ç¨ë ˜Ž%çݼ4¨…fÕ;àt»íO%Ü€T=äØÔÿ; V@@s6q`d/¤¿î©ò¬~)Ë«2e“EóSï¡üŠKÜÄ …mAg>2æîÙhOÐ]ŠÔ›~5>€øþóD×wZܱk› ÅÈtz¨½ñ®w—Þp´]ËÒt-E8J�ªÍŽíUÖdDÀ›Ãy`„ò›þ¨>ªÒN²4U^‘¶öæ_Ð|‰±ÁÊÖä>Ã+޶q"Ì—,ÍÌîñ±|BrG™¾¾†”¾݇ Ñq*aMkëûðnë}µÉæRõ9¢‚É‚û@(0Qc<ÚâÖ§.i'ß ›•ªì”¿1Æá1¹H@­5EY©ÒAõ�ô.�-ñƒ¨Ï,žçÑI¬@�Å^Ç�QÆ î´‰è!d •]ð=�bW‡Çinž2Þ±ÚeþÜMÙ�‰}¶JæÃMqÂqŸMò�dËþÍa›€§úuÚ+ ÞàGµDÙhÅ“9†d¤Y –º$H >t ¢µ€�ÙLÝdÏt²I‘ÝÌÖUáZR±ÒÌɪd5q+Œz=æìðÐQÕÕ ‚PiÍ%KÝa�«(󛢥ÓûKýõ#q}Ò å¨ðK¨ïTxu÷#¶ªêi9‡8æ�‰=a%¡LæŸÖ}© '"zzË< ª‰6Þà’ÜѨgoeîŽË:¸‰%ŒÃ·=¥ÉìÕRòGCæ·4BYŠâú ‚áî,+®$øNן%vð)§ð¹‡ÅëÀÿ‚j8WŒÂ„¤qkߟè,>Ì Þ_ñzýêý­]oØ ¾º}…OäzÊí88�}ËE„‡‘°ZçÛ0beAÀÓ‚Ï_'> îí¬›*~7ô—Œ{v¤–(ž çyy�©pÌHnG6¼°3�â´ÁRjäù•ÄäLšŒ¿1ŒOªOÄE¢³áñÇÊb“O?æX©8#Õq[[±ÂÌØu ¸&PÝXRæÀ•”*’‘Z_Úû&Ê�›Û4‘Z˨Qž/]Ì~8Íók±1e«ƒƒ…š¬ˆ�ó£ †ÀlÚrTë$²a ôÂpmû€Í>=eF �.iÛW¸œ ¢7î–¦• ˆfÆŸ;†}ž×"«´?ú>Æê£škž�¬ázdeŽU…¾•h|Î;Ž8A«ÒŸ®Új’Ücn™©HOv8˜7ž€[L’îéD)ÌË{\b*RmµŽ$ w`Œ p¦§V¼Rk¡—qM€àˆeƧiÀå´¯å&ý}Ó4ÜI §€€ÂQxAM ØìžÉ@+ƒåø=†Z¾q÷Ö–Ÿe÷dÅ\¨ö:¥fäÉÊq«‡Õn¨8J¹½`”3 ¢'ÂaI‹’q#k~ž¨«i€„AÙ0Æ'ÍLX `W=Ò[Ýó(‰õíkkèÖ7—ÍpI3mUZ÷AìE¿‘Æ8X^ßÏ6–êüI+Jp)´mJíÄɥﱪw“,öö…ÚŠ ì२ VîïÂÄ£Æà�¯±ÿà~¾ŒÏ×âÔ5ÖÃ0g{’(Ð�(líåü*08Ük�ãÐä¼`Îܨš|>¿³5Ëf�¹]ï ‚„�¿Ð¾ÝÁ` fÉ-Bö@¢c‘À \#$T¾Ï¾o7#ªÏ3ÐS>)Ñœ¥�~²‡è×K¾cè•tÙ¼JûÉFíœ6÷ÖÁæš3%tU4 =I¦TSîŸQÊCAÆ÷ñÉv;£V³ÃËGðç~9hŽ-ÆQÅüä¡wÙžNšIt)ù�íÑ�Ë©èUµ[A�êÒyœ Œi(n\±üµÄ‚v ªÚË</<2Ïf0*‹Jh²ò¬LcŸÊ}³Å^Q“CÞ­ŽpP›º/{"WÃVž�Œ›—F=N||ÐÏÀádé‘av—ŸÃIÞ%µfcÚZ û�&3œ”`N_bI�²kx—ªN5Eß2 r¦„yÔxá.�ñþÕÌö:æÛ_4‚”9üž ¿#iï»åº6(�»lMDÜQ[$V³âš´6ƒÞÑŠýÖ•;<•XQA¢û¬""ížÑ°Šd·XÛ­÷ غdýCô€/9H‘}°!/Ü?fü熫¥†{(²8`±�²£"ÿBB\u�Zn)« y†Î§¬ÖínHäf?Y¶/‰°VðÀ%T�êiƒ\QpT¶¶p§g�vÅ(/(³‹�'÷1s@²ΓÒ÷ë#©Û«ê^ñÃr(rºd@­"êÖ4á`ñã^-ëÐge©Á+fŸ×Ÿ»xîc»FÞÎ ®ËêÄRf?g±ë!Ó³·b[~E¹×ÒÎ ÝèÏ~¥ –†¤(œ¦’w6  v†ÈæÑÀîy‘”–E1F°ÕFw¤6w!8ÛFÓ�²¶yûÙV±ëK�üñHæõoÞ�zŽ2l–|Q8-UŽáº&~•˜i†zÅßKƒ¡Ôej1+åç‹Å¼®VüÞ „ËØ’ñCpi¢ˆˆ\© æ,i•ÄŠOÑxç&—Ýa[¯[w_8êºÄTë¸Fú×!X0V%–§öˆZî„¥ùÿ¾Ì_¹Æwnœ•ØeDÈÿˆg>­µ@_:^Ò¨óÏÑ”2C6ù#5#^�p¡ñÁkµða@z½œ7î:ÚZÁTŽŸTú�¡ˆ`.ÓŠ¼aä0óÕs!J 8~ü­M ¾)RÀ�¼Y‹‘ó;" IW ¦]8M²Ý '¥ŽLÆ4›ê=©0-·Cõþ@ñÐÁðA­_†|l¾ÐÃ.a¬ÃVí‡FÞÔD‡ø@º»,Iz|®§œY"+Nñ︺ª¤¦Žû�_Š~o°-þ¨xùØÉ¿;î°Õ­ºãþFFy´bQ#”LQ0až’Ò*Ñ$-¨lŽ* äïòHv(öèwAšÄgpW åšl˜Æê q×ößéœU)±|¦ˆÖNÚY¢åºè–’öŸ›O‡XÿötEÙ©]C·T6©”íÂ��{æµ·½¹ ÷ù A¦Œ®¾|í<�©æˆX#s‚DÜ{õË´²ü¿¦¾º/V uy|Ëñ¡òG¼Ìí]‹¾ùñè–„ã ¥  ( S`în¦<¡õçRL–I&Fía6ú0N :‘PbN?au¯‚ªÚü6‚B„ñÕ Aô=3Û&L´ ¸çf^óO¾™c2ÑJè15@¤ßšѼ´º¬jªhaùÝybüIœ—s¹GSYî°Áˆãó·’W€½KœÏöë¹±uWͨìBà_Ïná´Uεê‰Á§Ë¥v \Œ½k¿–6À¥MöMç¥O¯æ IÒ)3+‹€…Œ#aŸY?¤Úmáâß�v¯ßö1…ƒécdœÔ»m¹ª\¿¹´æ¾¶GIÄñ`–íËО‚‰ÃETF·Ce艇çmèXÛ:ù_yÛ [c�&2ÂðqEPHÉ;09Õ,¤‡æ-©ÈƸ¬;­jí�CV ”æp‘¢˜“éedkˆÔx´8Àƒ3åóFÂ$+ÌàLdܲ(]˨ˆÉ®iõÇaÖŠOoFõ˜‘ýX`Ƨª 5Ðv¯õx\e8G4x�G N'=@™¼ÇŒo@/<;0­QT~¡Óç’:�Íöü™Å•DßKU-Çw£xBCpï°Ž¶WÝcPNVe8|í˜þr•=CÊ·àí·ÈbnKèô°Õ:%>Üú /eá×_½^D@Z™�#²h^ÿâjǵF•›Í–"Ô:JÜ™}.²’A¿"Ná">†r\ôèg?b\uˆš ¥*Do-.L5(|â¦çOµÎüƃƒr1Z¢Ø5Šîñ[¾Y•DȃíãÆçÕœ�û÷+»Sr}�’.(Z€Ò„¤¬¶S��¤ OxBÕ-Ü3nVÏîð”$QŽûý"/’5Z]jÛá$TCË3Ï;I&E×âîd‹Ú I× ñý*F`ñê ¡û_{±y@šÔ�NÀ #˜óÏ’ºŸk# 7Rîá*f�]é ©l�ÞoOè:¼ƒ†!mr[ ¯xœ©+Av5Ë�ø…@„åïÜ 5ÙÊÿ(n‚á- LÃà§ÕQo[ž*Ãf³Æ)cK}�Æ7Cz0*A��ÐðVŸ¸†l|"K3rÜÕ·kœ�aëýf3¡û´ƒ1 »#ÐÐiÂÿsài&*ÌÎ×LEìÏ�¼UR‰O+†6±Ç¡žV·(6Á Ú�¼ ±\¦ 2z v¡ó)» J.2Þ˜Qœ‘®�º¦¥à.b�.Gï!tÂ=ˆHûG:áX¤½gI\œ÷eÇ!ì]MS¢Ðá-N qjøI°s”EðcXþØ)‰-ž€w¿»€;_¿UO"¸§ø/Ò|3\4‘  ½!å½;ŠYoª—0¡ºàYܼ•b÷7ÇÐκºK·èÏyï×—ò;s5p "¤q'%ÏøÚ Aøi©¡�3PGs"çsxÃa´Ô‡£{UötC´jLr5³ïP20j‘æ;X=g °’MF³i³£¯‚\ éJ¿QåP! ÃX¹ (M/´^Õ¸7Î’î¬6ò.l™¦-H�*ú$]6ìë+n-ƒ ¦>á‡!Ào_•ùèËe™Av›Ì†£·mœ°Û¢/jcH úrKEÖýœ¹fdhLÙUžçÞòÁšü§èúQAæ*€¿F8ò™ôD J&„Xæ´<Ø�ºt°ü�U�Wb(¼«V‘°+ŒÁânXG†)ÎZ‚Ù�“79!f$9íIf]/wÀ}”YOÔ•z­ŸTkÜYÂñåyY,ß‹óÈÚÏ�T`'_]T~Ã`˳ÜÑåBͺ�•�õ§²_Õ>ü1>V7ïÞ)ˆâÃD›)æØòÃg%nÿüè¯ÈNUˆÑ§-›_½ž�þŸmaé8ôîzì&·‰A!&îlh + ‡´¬C޳Ì_†:è¶�S3¾J%ýŽÐ9YQ‹­áæcR,•ò{Ï<¨q¹¡dƒ‚ßçÀb:ÔßÔ'z�6VXþ-‰‹tÀt´¿w ŒŸ�Gˆñ—.ï¾vV«Š¼¢Lƒ& ‚”ùìOˆo(�Ðh×i9þÞ[˜›ú9§•jkО˜¸©ÇÈQæ�Ì­¶_8Ú±|•�õêǹ�Ñ,�� º{ TG0°ˆ6x-™µ–v©xvj÷“CÓ°]=t)�çí2®®l!Wil}½–î#›µÆŽ�’Ôi‹Ëß¹¸¯Wi´¡:{œ-7¼Ð÷ãA`˜f³pê×7\9ôiô™5®‘›6~A5{ì—«“`™ƒ?AÚÄ ÿŠY�Søæº�À´ûܲeØ+„·´8°ÑZΰ Ø­ÜÖqyAë,þ.Uµr9>ìtMY7SÖ/¹A� A_%ÏŽlýsx=ž6®VC‚Z•°6©v‰1�^Gin9Að¤†eòG'ö¢ªÎÒ¿ùéªRyÍ=éÝt´¿ÄP™æ7«ó h×)ZòÊÍšXöŸ“÷=¢JHÈ”Õ.P ÍKЕßɘ1�þ¾(úšgÑáÜCgëª6¼µu,¤úƒ‰c¬üÛýâã kS³LþC<Òu¯˜sOþo[Ê£¤WŸSê¡eu"‚›ùH/¡~æè.—°$¼ã&#S´ü^kÆZN«ó²rha ÒÅ.åÞtE’‘YJ™E¿µTæF/ît QÞjË}9º‹–~ur0ׯ‘O*i â3W$PÜ+,c"R. ŠS�òƒ¢5+ÌêTéf5cU9Ñ­ kËË7˜Ù[}´ u´¨8L-ÈÛ~0ÒKtåTëùØ8Šû Ž*"Ê`7�ÂG‡q0†iF ­¬fp÷ É…�*Œ ÒÀ/J-ìÊLý¸cý§ïŸ¤ç{Ó™šoßÑ™–/xðú¿ÿA23+3È­8˜›g\©O:Í´“B°�€~6™ŽGÀ3°éÛÇšo IAëtNaU–jè�M›�´¾ýs‰p3‹‰¦$®œÐŠ0&åJÓ›Rl.• 6‹ý„1Ò�ZÚÏÉŽ*.þRO#:¤<“WOI%½º^síÉ—¡Su éÝÓH¶ß *ÿé"`1¶ƒ=Ž�§ѹÃѲ€ÚÐ\¸N,-öï¼Êad–„ýÖ!­ÐWyì§$ œ#´}éeÏ’§ÜYòæwó ¾òŠH]õ�Å=ûR8‰£—œ‚áþ—'1.°a¦_$ƒ$íSÑF¾¦ËË7•ŒÜkG‡Rž†™²ãdƘ2Ãéÿ ³Y÷`nbÙ Í 1î¥ú 샠NŽ%³vBè7" ÕÊ ®[Ú‡Ws®D áóˆ€`††Ã×О“A†¸2\‘¯*·—šýô) �’„V”¼­e<7¨KœB&êÕŀ࢛º/[+òºUj,Ê!Ä!ÅMB�:m ¥�( ´›Ö¹t0>&:#¶ÂÍ(¦}ôN,Ý(r>cQA€t~ä|ÛÖË%ÏVÉæB]�„d0“aǯ>ÁX?IƒG¯uØ3—ÅÐyším |f¹&¬µðÏã®H >†W)ëÿ¹;U’:AЊºë“ò0„PÛUV!P4Ìqkhf¯IítŒ�ë2•'-ý‹vßý•�âiU£•G�}*`Iøè—d[KlFOÔö](U'Eª‡E˜Ó`–ÃSÖõ 'G3ЭyÖa{Æþ¶KI¦]p¬« ¿3�]ÿ•öy8ŒÅêYÆ]ÅsäáW¼ªkÖÅ&ܵðý²Û ùÝæÓÛEr¢øí̘ �Klµ,ÑòÀµÈ;š(JY :Î%Ü%=@ꫤÿF÷yn"´ö0ƒ&Æ Øz�$à—Ö.P›ó-.°Ù0IzÌ/tÉ=VuWUÌãfç*Sªî^­ðë~Αø­$ý™eÈ@Öm1z¼÷yEÀ··€[¦–`œÌE¡’èD¬ŽA¯ò=r‚.Ðmý¶Ã °(ñQ±>¹e÷¹îå2�vO‡õ{2Ç6¶[ï&Ú©YÇ(¥ØÞTµëp·Ø½Å毰Òï¸æé…C™Ë[œèõDt½ªtº§• E¨ös K¥öÂßDk‡’q®Ê€W¡/Ê%W‘µÖÌ=YTüLx]K†Šà³4fÁw¾;‚ÝÛ1þÐ/Ž•ý5S» Š|&G¼²& “ï‚ÄÃç¦�š€ŒæãìØEä«¢3c†óûoÊ@P%F™!©˜îFŸ Q¤4¤¤N‘T³Ã¨wÛlâ{â½�á‡Õ®¥Ì±n÷E­ äêàø­w_–‰•·hÂC;Kô›dí1µ–¿¨WÚ�CI‚Ó+ϰÌŒ0 æLM{#£)�µP×hðêcµÕ^?๠׀¬¯Ì®›úš‰š†Ù·#.eµL˜�YÒu,tÕ`ö³Pu4¶¦¢ÿ†yc¯–°“VpO…æU¸S+ºä{+§{ñì ÎãW¸D³-„Ïg üÜï~E³ä# âsŽÜœ>tªF2ÉùCëh˜�Ú>Sp–ÿ=wÅÿÅlŸÞÐ8Iè¶ÔpQ¶®V²Ô»H"‰0 ÀTÊ9�2M—K=ËŒ4‚Ib]g¿ÔvJ„t„ €‹eš�}Ϩìðp?ìWš5sOµŒAeºô8å‘Ò˜�”‡H(3»š~èXîÔV¦ëÓnUú”àÐD4Y¼*bÓyvܲ¬ØÝžAÇê2Ùv¾ò]L2‡¹©é\Ú|w€Éy~é¦~Œªöñjþ6Iì¿iPŠÈÞnÂ!`j²¼íð|¾ÜÇû†2Íä q ¸TÖʨ,Á®*.XóµhWÛ]ö5Q™Àé?Ô{)Õ²P°Ä’?•Z¨u@¥˜'Ôžðl{)©­´˜ï`Iˆd`Nôj˜§ZaEöõ0å3>î…xcëmáÈ Kõ/k@x=9j�"ŠUuxìÒDåõäÓíôÐ)ó·;ª-ɨo·é´á3ƒL'%X´¯ààÂÕn~zòtõÒHÑ8]nPUùÖô/Áйë¦ÝLž†O¦"¿·£(^ÕJ/nÀ–M&†é ŸÐ(†)M8onÿ‡% ó¦öÝ÷`k^bßJÈõøŠH{c[LZœÂø¨e°TCÇ*y†=8‹j%oö€7jgŽ#àºÀb73oõgd‰ýâǨ0± ­8fYüäB‡’‹B˜8,mÜ»M2»¢“Q&çz†ìïRë­ b·¦@q>s‰j!åe ÀVs�I3>yw¦Ö< ²3X� óÏíè-àXs 6‘\‡ŠfPˆ·êðw‚g§ãÕ¢Ž<ž›Ï`U løí³{æJj,Ò9l·¤­ fñáQ\Y6› ñp0ÖÎÃPŸr¦¡¸xŒˆè½¯íˆõ"Ì_(c�!Ê0I–�Z8>Áa¢ÙHÌ˲ˆØ�ö~бjz¶aW…e‰ÎËžÏêë6¼âÀŠ€}�SúœÄÇž}‰Y(ÿJ~éÏ“»¿8óóθAå;û+p�¼\"ŠŸ�NÛÊvᬂyÝÕ6CÏ,„Ñ[öe–î6!Ê”�‚y¾x—àñ´ðãIØW\±ë™$¦~?œ¡e�å+ÏŠC«“Œþ…Ÿ,a %9D³+RÌ?³Ž„­  ÅL͸üe¤¸P^f.ç²¼Ò>T¤Ú糕Û�B!"µŠRÓ€Ab÷§êúîÊÈÙï~Ý–Ek[«œù|éÝ�SÛøf•°]K>éÈA’­ î9XÍE‰Eõh PÂäÚB‹8ˆgžo{Yš¾êØG óÅëÔ#Iœ`êäDÕq�ÜMP1fŽëX›Ob–gÃZ.ê 9\“"äµ+i.ÃNÎiú‹¾œlžß—ùh;¡™tÊoSX Eg¬1ùvèþC”§î-ÝnIŽäâVe�Ó›/�t0^›Åé©ç,Ñ‹]ªaäs4×û­bà$DÆVFV,(ÞóBjË5Ò í'�ÿÄÎm¾û7Œ50¿ðÙòB]ž¦EŠaå“I÷1j%º ìM—6ebäA:2§Æ×H˜jÝ«ËȤqxí c§ÁªTM*pîÀ_ŽNðn}ÍâÞ¾§¼ë ½õˆzossÆuxSžÐõCÌŒŸìp¹jXJVÉ‹Ês¤D/pO#®ÿ›kÜxæ8橌9W—/ÿºÔ™b:æhІ(Ë�á§Æç $‰ÔÓu',…Ó˘J÷7)§k²‘ ³•@…ú¿L$¥n8’î;¾Ôå� p !“p¿CQIÃAÓF÷Wþûm¦à†a󬎚†³ÛŒJóšÚ€ƒ+ú0”¦ÿ–û$ÿŽâ'žüh0z|ý¢ø}²TÏ 6~'ü¥ËIZÙ^xj6u>å`q{ñ ÛZ@DE/þpâ:áq€;áûw‹“Lpœ À™3œÇà CÒÁ0‚ÄÁs(zµ{¼cdX±|h %¼ñý[[h ¥>WÙê,|ª�?BÁ!=~µ?¡?±óŠÒëe?½É2—²ìbß#Êà*Ê-…äñq9ÁÌÑMÛŒ©\ˆ}V­âï”"‘™Z¬°ïNÞÀñ'ðûHfwuBW[‹ctÚ‘½�}ŒWê‰>-ƿưî ÑMçóɆéÝËn׽ްÙ1B &†c”°=)—äÔ©5±+£Akz�o>îCB%‡þX9­‹ål5Ûü:ð&H¼I,ýR†çûƒò1³Lµ8ï<ëLÁö:�ä1NEÕdâkÕY,YÆ&Þ!bËåRýMl²±¶û˜DÆÍÆ”…ÚM¿ÓÈ5¿.gä'{È.8{~¼-ô§Ÿ³²Ôó‹I`€¦´×b�å2ɸ�:J²ºR8ÌW¦è)±!‡/М”õ8r’R5ù7¼%pðöwwø‘ÜË†Ú MŽãFv -v’5<ð5Dsþ8a(it#п+ç[ÚÒ¾]aŠØOÏjNY°ŸTy#(I"eqC[ <ÑÃN+u ;®s ¿Ç[®±Ò¼êè«*�È^Ž‘ÕiîÜ-°Ÿ?öüt.±Êþ¤ÙÅ`6B6æ)b#[º±¯Û(ç>8D¶â–`¾ÙHºûi˜Ú\œN§%P¼âr3žæøËf†B6õ2Dâ(wÈGiOô/ŒH—ÂÀŠˆÿÌç^a]¿ù‡]z¡ØÝó�Þua˜�™KŒ] +>½Ö%BÑ_e¹Ui‰\6‘DW¨‰|¨G’&ƒ¡è«Aº¬n~…ÉjY�UØ=ik¿�zjÒz™zsCñqþ‘šŒ—@‹ Œ›"$êµ–¼6S>†R}M�tŒŠsªèp´q ÀTF8,ûÆ0°²C!*Ëjv⯄»haï]a™^1§{Bó*d¯gh�#}2`æ±×‘‰™D2â:bÐiÏbC©k8 moKiœÑGg�ü¦½Ónjn�>×@Çôߦm%‹fEúm�Í„2ž‹•½a¿˜­‡GCé`9æºüÇ\$y\Ôyy^[ܶõpZÉW.ŸY�¶ç„ÆÁISCs ±¨x¨±£˜ ØÚ“0`#yÚ§žÊЪvøL9Çt]'k›8ìŽ6©~QÞP”azsìIͺ‡GEŒôîqgÃ[ÀÿÕªçUD2Âxœ-Óȼ^ˆã»œq¾, ûZ”ž. ý;¥ó÷ëKeúr>m&�"ß%cx­#jx§œ>ïð^*­4~„ºZÔ€k+Mfî+óþFU¶x¼÷…C¼ Õ4X’“3ªº ûtHBGÙx1Úðþ.¤ì]µ4Á*øböã‹Ö«·hžÖ-¶9�Ñû±Ž0µÆNÜ[äÍ¡§EQq Êÿ�1ö'”i„ÞF”ÞïR‰ê[išðƒ:é ƒ�»mŸ/šÝ”[¼ØmºQÂHtC.qÏ W3!³!‘äø`a yÁE¿¨6ÉÚ]ðŒ–?ɶ ³›ZtgéT`è¿3�V|%¿ÅQ¢³±Þ„øe@Dñb·°ßºèdaGÄÅ»èTÞ”úñç†Éÿ»FŠ¥5º'Ššñ%«¨¸óŸÙ &¾˜Y£k/Àô–„)޾7*ƒM²\eb8qÚì»g»Fþ+MKúP •™iý D*{sr”ës¡ñ¢oHÎFŠÎS‡UÐJˆãø­r*Saã”™BçPƒÊÔyYPÀ&PTß.§³wVÖ\`›HμT}g¾GE¡6ÑRšˆÊTŠ�S®¯1Þ¡Úkñ€‡¥4­.²Ñ»Â‘-8ÊÀš¹0UœË •»N�î•wñÝüëó 6£¯ ÜôåG‰jÇÈw FmÙÑü»Þ·jïe"´�|ÒCxa{‡"„KÆègŽ ¹ŽÞìrB<©+Ñû¬¥sjbÔ+0YšJÝ;ùñX‘}ìãUrTšÝ#-ƒ¨É';öÑÐ’'Å7BÆ|÷öÇεáÆ9!´á£»™ç›*`ìµÎŸJ›#œ°+U é†zÂNÊH¤\Rd¼héŸGÌn¢_�#ºEíý‘2ïûR ž÷ ŸzÔõBV2ïƒEÀ”t)Ó<‰ñ:ˆÀ¯Ÿ×Ÿ²ïEøÞQ&$àéQ¦h—Ï[æ·}¤('¡©+^¨ZE‰G ŧÑÞ²diPKL7¶EmL¤%â`¸üUºÙXbò¬k™ÖM®‡²õ_ L¢ÑJH–ú‹>y[ ƒö bbͺB#–Ã6ÿÉ·‹©5‹»²F}t|âXàW(—IÎè‡Y.ç¶.µƒ/Œ`íߪÍÚ•�9¨±ÁÉëkFôj�õóK–W׌õ^�Zõ¿â€ã0”HU¹çý0R`¶g‹·<3¶�Mʳ.°x (,ÚøÑÚ×|ÎP;wm®„ƒ¹dê] ÝÁnË:v}3È/Ì ýÙîÂ󺻻�g /*IQ´ûÄ0g6Äøc‘ôÖBæ“ÐT©ÑñQ¾ Ìò‚|ÂŒè�ñGöT$¬ç0 ºÕ‡VnüýV¢Âg÷Q5÷Öhu…¥š$„¸y&ÞàpŒ´µtÞ 7Sôjh|‰«0#võ½}7¤]Fq�g‰‘'tݘ›IÄ[Ø6#kë;‚|çmÆ—Ÿ$\çûa¨2­åÔ…» qŒ›ËØp5 €ªbb®¯ãvξ‰š3® $"ø'æ:Ê*Ê â3ïÓ V’óéy— × ‡>J5›c ñU~ó^p¸SÃr¶²§e{WHKxã‹"{”¯p'¾ù˧è«í¬ÃýíÞÆ�¿ò ’@‹‘D.,ú”YEô廩?�ʘ�ãêÛ1µ™£Ìºl’ “Êyj2¸øB”ä'¼—/" =”ö’”’ q /Ç%Ä“D\�åi;´s^Jüo*æv˜#ûf©ÝÂVìLÔÇ8¹FÕ¡° æï Àµ9<ßmÐó,ú«LgšRÁÝójJ_PøUFÃÿF¢&<ÊŒaž_É� Ñ}Yý/… –(ÅØ[uL7‘ˆäDÈðË™#çŒÜe¯Ï&œÂÓå Ê©,(wkŠl8yGh2*·A T`î\””–Åï'Í�0� æ(Ž»9‡T§¦b N€ß[=- YùLñà”{.Èù% ÜKÝøø.Öa©ãÖè½É   %ãR5KÑ¢s¿Ñ¼Ûú™§Ù‚ªÎÉé2ìƒÞ†RÑÍ�ýU@Ukó7�~çu21=©Ðä]W3 ’öôEGÌí�Ø$é(Á%˜¬œõ,pª,�‘ã ï«åž«=|Ï®1 çïwŠ‹üf< õ«…`†#<GLLn@=œP†ºš Å@µñz›~²·Ñê üjõŸáüïH-ïð9¤1«g+õMÜí©cN5ö�Âx¤Ú¤…–�«½ïÜW7ïû&^)~þ`q39>芛5ÞPƒ�FwHbü¡àtýFZ3�êÀ쿉9ˆnݔێf’ÁÈQšÅx”§,éžC:I~¯^š•H›Wß3 Yp �¶ÀáJtò¿$p³µdÅжéÒðG£ˆ“¾Ï†óUŒ¿¾:µIôw—ѵ:¬�š…¦ ºóˆl‘=1 •ÿeýïtA÷­¹d•m Ç·æGw B§œT©ÑŠ«b¸Uõï9T¼¯côƃ:PC\F¶Cæ%W�«‹¾ÁbÃÞ{ÈÎô·x0Ð{rƒ� ŸËGÅLX|žõûÖ(Ø*^ó Q·'¦ø9ðtÃAë›Iƒ‹”ü¿ {`ŒZ{'ð»<€(‡`ÁŽŸœß{ ß,®Îá …ËFûØ*H½‚©^GÊB4>�x¯¶âö@ÞdrnhStÖP4–„{˜LH\ú¸SØ9ÀD÷¢ÔÈŠ¿Ü´i9ÛOÄÍ©nÁØÕÄù,’5ª˜Øë•±4Ôƒ³�Ò‡‚=uÒõïÇÝÔÌ÷#F—øC-Ū †bT¼»ìD¬Ÿ ë%6Ã9ùëb'¨ü¹ýê|rU›!PΜrÆ©5©@øu@uoî {Åø\ ¦c …Á(”¹åÙþd¢¥@§ÿK{GœŽ“Aª”áÈßYÇ�vÞ±tßNÖÕŠn¸ÅÇÄË´"ÛºøÎÓÓSFPO�‘É탪G°sHä0iÂ4?º‘Dž2s"4㦲5ÅÖsÞ°øNµ™^¶¬JßUföò(küS©+<‚�Ý‘–Ê W;Ï¡ëIí•;Ù…|Üà¥Þ;½¹µyoï^A‡émL3ÆaKg¡¬\óÏÙ0×<ÎYÓ¾!tí)$TMÂQäèÄg>�„d8ƒ´§’9&Ël@Ag\)ÜÉcMˬd½CCçÛ(ô‡ÌŽº�Ѫì �K€ÛM¼&ˆ®žI5X1Ýò¶í±BdÑ|ãÌCs«ô¥)BE-àÔÙ¼ä»%]ß§tïß/âæ#�ò1`JÊ(O÷ Ýú»Ê�›1¶zb x|–ŸÄp–s~ dá‘ _>=r‚£ßÁ dÝ kËÅ‚Tï~Bù9¿xXHç¿|WäCN’qOw…`¤ïñDüoÂ�ª‘.^°¿ÿÏò“ÞÖÚz0ª6óõ¦BÍÁ©uÎÃù:]o„ÿbŸ#ÁŠ+÷P—é¿´Iì~FÕX®ZœÖ‚ç5îKh…ˆ…СׯÅ{,øsìŠø1ò½»½ŠO {@[#ï3ù°±2x@µ+` šÑs“õ�g­ƒ»›v©€w@}€3G�Yö²”ÍÜ)n›‰¢:Svdî…LeÂ`,Ï}ÄŠ))ÆOžŸ|X"¥ºµ�ãÉÔ‰–ISi½âöa °þ%.k SÍú¬1Ð?Jq拘Ӷñ×fiÊ‹`‡ÜÁÈÑA´9u°òr0­Ù¼Ã§ÃFzö*ç ɉ ”È®s<Ã�.ô)ZX¹ÒÉg|ƒÍ¯oÌ âX-x³Ð\ð0çSÄ?åY€|Å¢2tÎmj!a 4 4û»ÿvýƉ"V޶,;sŠ)gmC~áWê— È¦Ì�Ýq‡�kãµàB¨”U,`y—£ÝÇ''qU3¿ÜçgH/ûÇto‹š-� ®èRîü–(JuÎiQCëã�æN›dßµ%ªôH4Ô#�Áèþ©±?܆,WÊ;9íѤˆ+' ©Ûi�Çý¬“ì±ÎF�UO"Âñ·Sò¦ñæ(Iœt¬LΖÒ·I²\Ác^K¾9òüE<Í6¡¾+�›^3ôƒŸÃÚZ%d3Ç\ð Ù ]ýgN}ºü…·´OUe‡¾�¹µi{g"o¼{bÔprÃIý £˜’'ÿ\6¯ž(+ñˆƒ¬ñt ›’ëu»öv¬ÛTøà1,‡â9ÔÔ;·M*yEÜòtÈÛpÎO©ò'5”̆¤¨Ã�)àÛgyçcnA ¬o0\ •O‹%Ø£Õ~~¶Îl�ß•Î#†éêðÎ<‡,eïé–öèÏdCtɪŸÖ½«Ù&°y­=à9†Œ…tKÖ2Þô¾É½H»€F4(”½¾ß�\õy×·Š)^•uß×#ñuæ’£�\\>qîwLÙÕß“yÝ+Á�±²±ô�™¸]œ´m¬¼Î>¯ŸŒÙ ‚ik¾Dÿv´×ã9ž>aƒÜ;0}dóf�X˜ë!½š—dš©>&2éòU3.Ã/Ž}pÀm1ËL ��èͳ†o�޼e àÒœõÿv+fÉSmf:äóB©ó¥_˜œ^èF×ÚcÉR­-‹$#¥Œ[O_;UG'*ªò‰úßç¦do Ñù…^¾#‚Ãw+@ˆ‚¾!÷ŠK¨ëŽa(r!ÈlTÞ÷¥„$涨�Æâ·;¿Ôá#/‘oï~yó@‡ôÇ7Ê|q3£S¥ýºr³;HÂ--9Þ:Ò-ïeÞfè¸z0ðÁ‘˘Êí§‚M­´uéʨ¥mcZ›îj'¨M¡5;gO†\z¨1·dM¬ÂæZ®Ód=p­,¬Î6t-Ù¦ìYÍ š$Gm“01¼Þ>>)Ä>kD²–Ëìù�XqWÇkö–뛥]]Õí¢ÓË'¶ u!?£)ÿƒÿÄ€Fh’k“÷“¼åzê7ª'¥Wµœ«C4>3Üp„áÁÊ:Qóz–÷L%µP�ú¸Œ  Wà×c#s]´‰®w诋œ©Ú:$šÁxÍH5aWÃI'Ħ+·ƒ�žÿ÷C.m å¢]×YMc+ÃU³°�}†g€&–᪢}�7ƒäVÇ0†o昼ÒsÇšn(}Ås7¢J,¬D‰rÈ¡6µ@‚âà_˜ˆJ­¯À"E‘Ëž]øfÇM×B�Ì/¤³ -Œeóæ Ð>Hs4d*‹76¡¸ê�á¥Sä€"6‚€=.�€&žÄäˆœÎÆíj–;ƒÌ‚©a½þ¿Ý“Ä“o@ó$“RÍ5“ƒd¯ÌÜÆ”¿ýfSþ6¶:žsu Š£ ­_ÿ[ûåÞ¨Fzç™´e^)§åàS·Ä …{-ùûÈzç {‡hV$™gUßû¹+댧/~æ¥�ýöx‡bzeâO™ƒLB›ã�ß4º8V`ýûÐ]Œwz„s’‰/‰+6DúÃld¶Ž`—Ù8#ÉäøÈš !€‚Û­Ê9w›«öxš¢Äæ}ý"Œõb#¦…QEذ }¿„è�i‹z&Wý —g&&½ÏIÃò3’RÀз2–[ëî{Ÿ«år2�E˼ºáv™_EÚ(¨�÷¯,ß•4¶{(½Àà/‡ñÊ|$/„˜Ú/Õ³<ƒØ–F«’›5ÿ“Àÿ`ͲG¹uôÓ;ð~‰ÜîG‡ŸªV¸.WqUñkm(Îøe£ü{Ò-ܤ9X8ɤŸ×:ú»ÚÒóue™•Õm¹šC*nýû\²I^¾°ß PP®ó!ŠU5.9¸«É˜ÃõÆ\ÖGŒÈ+êO�ŸÜúT-¡–Õ™·ðPÏk‚¨É\H�%ÃY éW§C©æ‰gÆ8­˜êˆWµŠö38�A¨%‘Õ pÖÄjêÒÍ;,BŠŒd¾“u�€œ£ôlÂ+1i]ä°¦åƒu7KÍÔbìܤ©{}9h‰¿Úí”›–6÷Ø<Ó�Ì�è÷J+å3ãX¼m®ÛaZŒ^‹ôl3R÷É$>Ê·¿s™®2:`�1…¸Üerôß+ºé„c�O“6Çâ‰}@5ôžÚŒÏg˜Ry(ïŽM@[i\ÕKÙ�4ý}¢©ñõÍí$Âw�S=Í–ÊlÈ$z%¼øüyÅŬ³æ9X&ÜÀÒŸÞ’°5¥º «‰ÙÛW{÷@Œ÷’¬ŸåN—ãY³rIB›êǪ­]r3†h†ìÌû4oµŠ`Ú‚acx‹¥Û¯Æ|Ìyê]hS±}E­UŒZ\¶®«ìs_Ì… ÄH™s-) žZÝ÷D¤rª(ªRެñÀ "‰–!‡iÕí†ûß:lÂE{Û8¡¬zì™S[»”Ãâùq¼ª/>¯ ˆúöÔ�îª �Üå[9ñ†ùqd*ïãÜ5x—ÇGÅ5@É~aön3`¢D››Ý¿EL?”¤9ÿ¥\+ |¶�«Vûž0§i\È$' ƒ¯á!…HC©dÕ­l­H¶OBЕ‹wÊ|jØŽIK·¨WNvç:´‹CÄf­ã?g3ºBÎd�ÒX“K´£»¾ÙUl’p§Ž±ƒånV³öb`" ˆ4£óB=½*Ô[¦4ž_BHÃ_Ò`׺†m­k�. ÎO§¹b)0=–Š…Ft¨ f¸ö$ól2Û@'Eþvì‰Ñ/Óg„9úɬr™=²2¢àén»'<ä;š4ÈúÖê) ÚÐ;{%F3n/‡?Ùu‹D1öùPþ±vÃ�g¾4Þýqú—KýeBBγõ|ê>�H¶žzl’Ꚉ”^RÎHy^ÏŠ$ Ðß2i ÐWHÆ$[UØn¶j»9²Ñ�‰JD/¸«iuðíøö±µm˜º<ˆäb'À1}Lk³9 ‹¥ÆVH_�Xiçã.$ª‹¤t[—â‹àc _˜=±ÁúÒèúÿëkÌÒö£‚PBÈÐ7«#,Üç2.Àòß2â}X£?€Ëuª�V¼v¥^9øLðž‡ÿßÉ–ya›{ó*%"·ubÜÀ:ÚÐààêÖ/ +š™F½,ÀZdj0Vžåfy¸ ].ûÛt�Ü/�;õ²jeÆh%Kž_ýŠIL”ñ^³Àü/»%}ËÕ?5�ú•wd ¹Ðç bs³i³%Æ—ÒeÍv¬’Cq–’Gs ì·Ô@o_y:?m¸ÿ¢77Hzʘñ4½Ò!+@S=å¶gí »Ëõð¡„“_]¯~#ÈîUZ4s¿²úýÖ”ÎC$0hÍ�ê/GI.𔩝Ü­ SfÊdä�¤ÉýOÐù‘ Ÿ//^\†“ÏÈ6XŒÍ! Ý=fΕð‡O¿ÏX­>~û$å)ðÞÏJׯ¦yÚ=®Ï‡¦ä ¥Œ}ó6.…j{%9&ö_X‰»¾ÉÙüƒå#k�˜½³¶òCR”æ4¿§3ýƒTI/ 5\»ìTö¹P`YèÍ+”W¥ED¯�‹%ü7K«½( å÷&PÊþ]V}áH³Þ¬,¸BAØ:Ö‡ñÙl§ÞÚU\à_©î‚/Š·˜ºÒ�W×ÉáÒlJÞ¸8…7ÜëãOÌ�ó)›L ã{k«Ç™“ºW+rà-ÄÁ'ü®ß`)…-Uáp=Æ”ºÆß÷MB € ôÆh²Ãþ]5{¶˜lLm€ø¦]q4^N[ûÔê®È¼Y0vYÔ \¯ý¿eðùioÙE«óÀÇw��ã{þÖ]¬Æ”Âq Öûñ�û°Ctôàa™öm¤IC­æžôSÛ#�2S»U^ëH£R„ ¾),yèo°qÑ|€9f¾Ýd¯Æ½H‹!-�Ç9˱:þ_má-ìø¦˜²æ¿­8ÇÉfI—S…ÆLé¢2u 3˜&'°¦åªžÐ/P`Çdµ…ydr8º!÷"ìï#¾ƒ¦Î6~§X”B<Α‘†q}•º.ñ�š‡þas~®C€¹³F¶¦ c7Ý›é¥Ñ„~®×ƒÃ9PêrŒy­õû´\RmÙ‡f|Ó\D_«š±¥g’|`²ÑÎùC÷lêýoˆ¹«yÆÉ©·K¦ y7zC8&Ÿ¼ËÇ÷ïù¤Wdb÷ÚÐÜbDÑ•ÙÈÜÌ y¨ÇJF_ób…zmÍ×>?©–ô¿E£e® â!Ìãúêƒ3$ÖnäÀ±—Ž;©Es/‡)„ÁfÓ¸\ã®L1�–ŠáèðÑ¿Úl"ñ%½¤¶›�ó�„juk± ØN?‰Ñ+KŒ™ÁO¢ËãiQݾ.ÍíFÍdr ‡øx6�©:Â,ùéüiuéìn¥§J:ªjÏÉÌÃÕ2ò”¼,¤Xº8jÇ_|»©feùh¸¤áBü;ßl '…ÁR^­ÙjOsŠMFYŠeÜÔèYL‚‘óç±rµYydà¡â§Á4îà9p1¢i@Æ"~ÈîÉd¯Ð½¯ƒaaqÄñ–­ƒ|Vv›� £=Š[C^çûM™)Õx˜›Ô{]¬L °[7‰ñTA¿åS?‘²ŸÐåIä+­aÃ�ÿó"©[ûØÆclÎÀê†Gן0®5…UxtâËj?vjS ¯äãïæÅ€ƒMÃC"vAœ:ÄZÜdsŸ¼ëŽžÝÂï!€0 s!€`c`hJvúŒÃ_Ï7òÍöqäÃâwug×ð¦÷ë�Ç·h¤!ê ÞäêK} Çghõ}¿ëþ”â›°îyˆÓ¨B֩ųʦÌ`_AŒÔ9=�ÜÙ”$Õ :%3([¾Cã0Lf4;›B-Ï äÌßÌI\ qìK�.÷Ó»»†ùOÑ#°¦ÒQÍQل؊ÌF”70�”ÿ"ªÅpJ½P¥>¡Lζ> |ã6ìjBYÆâ�/È:ŠÓÛÉËëþXAb-O»µ‡Ä¿¯Þâ³$ "â:ßY`\ž d£ôæËlöÇâÃÍ â,Ü ±N¿ý~C<®4ë^ÚÜu`( ôªÙ€¼ÚSÓæ<‡½ =óÝ”k逛!‰¨a™P‰B ¾F-Ây‹N»#`4c}Ì_Ìgä´ð/LCùŽ’d¯áˆ{1.ñq‹¶Ã¾œ3QT££x &íÍOy¯ï-’Ì]/• @"ÍO›�žÕ ¥4õ�>äÖñp6lÏ" (lî»ÝµPY5]âFJ-7ðŸŸd^ÔuÀª X :Œêܳâ8J“Eɹ�žáXÒ='©ý^ý2ñsŒ`Ÿ·úá ãh°÷/F>Õuzåòµ_‰NsvÌQå^óîõ—U¦8°úš„b^É™[S7Z ¨š/„ç-†A*:é{* ‡1by);dçU{ P¼2™0j=¾â‰Ë']r77WxbOr&ƒ”RQN£Í€G,RFþx†¾•Ä.Ëð)†`ÿÿFc\[ÉgüÏ—¥/-ÿ¸{hÅHªÉâëY8‰•"…†Gà€3~ T&™oŽóé{s XB’¯âÆa� Ãú-Ç o¤TUâFáh¡Ï˜ è\ n„«µžÊ ªÃ×2± "§ãÚ,ûÜe�íZ ýG÷AÏê¸,�×ïÏ:7ôÜ¬É Ø(LÜ�0Uì㵦wy ¬?ðŸÄ_dõÿƧ¼. kS´oâ™iDj0Y}8£ÕÌ:g8]GÎ]†G÷×''Ì X†ôxôüœ[7H!ß;»Dxs 6Þw—¤2÷ó*¥þ­¤Ö—–½¾§/À:Þ¶t¸d¢&‘¯fÖq{…€IYæ„O[ï2¤Î¨››;‡]Æ¡bV6r%šôÜ!¿ÛÂ×Öžþ’©º90 -0H�®I0øô =)©3îÂåF ‘k¿<»ä“An 0=‘ë%Áz_~^S¶É<Œ“ñŒœ�3h×…�g’‰vBF€¯…÷žá‘ü¸ÞF¥çßë,j³ìÔÚÖÄØ6½½Ã¼Æ;•9ê[ì°4Ë úAõ-Û †¯#ÌRÂc⯓<ª* ÄYÔÜ�­”®çɬXt°o³M¯àºÀs´ÙtÌE%SHgª‚¹ GžÅ*ñ”Ôļ¼Ð�ú‡á#*Ø߹®¶_fËïë0“?íØ&™£¥Qš» Uw�Äឣ™Óý¼™«d v¥�ܹNÆÇH˜ëæ3s�Ju+N_㧃T̘ôB[ ˆú81-òà¨_ä´$kP¡¶Ä q7ŰöFs<´j§HÊ×bÑî$­ ÎÕO<´�Àá1"=²SN oƒ@zñ5úxKÁ.×É4· Ìy) I­ûØÏ;¯Ñ­–VöLbºåÀ°h•­|Õ–^ë£Ñ)öªÅ»Gc±x®&!ñx ú·`()~cœ\ LâP@€—Ó3Ú�DŽÌ¨�ý º“§û_|ð¹`ežÑC~JpøÕC�³l”D¤¾;6ÌÈ2’yúJ¨>Ã|ã»nKl6¤£ýä¼”.㬺 T˜si0_…ÙZ ™°›ÔC´52ÐIñ2lÃHî`ÞüT�û6Æ“N` paÎ~e‚Äû…Râ¾I#×Ý €H.±5a’™'ýXú^¡i µï¸g©Hæ,ƒ×4çeK™vpÜXáÊ¡àÄÞ.Çë½µÿiſܬNngk Œç¤&»37~u¨Ò˜ÚÄÕ´®ä�µVøãSè¡‚®{é—ÐÆBbh7 õNmZQ÷©LÒ#xKæ�ëNê^LÛy�èÎ=Þèƒ|�<×ûÈi/Ùiˆ„O´vãB.¤z !ݪdKöG'Ía›V9b¤v«¸„YŽKb$ ÿ2†Ôƒ3Âþ1¾¤5Ï~š ñ)fýÀJÈÙ†÷‚¨wÂ8#BWÄUëKÎN:Æ�¬ß¢�,jaåe³DR¨4H“sUwþ.Í5+@‹ÏiÆ'çý<˜“|nGú¥!ºE“ÒÚG­TµhŠØ3!'õ¤�ÃÕ�oÏ`nó韟Bm”ZIHß:Ã#åº<:‘篂¢9±ïFålNZåUkÙ­²ì¿À÷qF®÷†zh=@íÂì(®"‡Á‹Sóàü.‚z�Ý’€hø5Úþð+«µ?Ê_�üU�øç&\ª=ùaVWkéíª:8tØfÝ�›¯Nëd�„¦5ªÞÄãGƒ¾aök@&rv ¥P®îŽnõä…jèYu×:¾*Bv£ªHÏ“LŸGÎÓ@Z×¼Ù~ò�Óíö¹fg²´ú |ü„m—bžü@®äó/Š4×z¸ ¨8ÝçÀÓç©Ðò\Å›x«—l¬œ²²¾d €27aØPÌ8oä¤÷•ƒëœ3U <ã6iËÄ»�xûT�¶á™ì¶½ ŠûÉ¢§Íe®‹Mð 'M@©F0iMòR‘ùz#âú‚)†D¤¤gÏ2•;9^¿±ë±ÓkŸPc¶2ü ÑŸˆ"�ìÕ_Ì‚¬9í%C§£~TóžõöÉ8oTf-÷mq6з�²^óœo{ó]èh�á·­4Ò³yÚbžaËàæ{ÁjéXy‚ ª Zâ’Ú.Ó{æhù-ßjgrçB §¡!ç\2qùåiZbÕ¤tà�Ù M7Ÿ{—2nJ…E6m½È*â‘à—çÛ°(ü�¾é(P¿\—2<‚…[ìíTÖö[�ÁŽ…?b’Ü>ñ K”Ug¡•�ƒ~ /2…’"!Oc “GÎߺBBÕêáŽ^0ycãËäO—²Ý,@Föži)s7Ï]²æPôyd›%óÛÒãy´“XÛ¯S• ÷½µŒµ4O�Ñ=—†çJÌæ,G˜0} ò?9˜SOûŒúŽ•‹)Á‹Snª‹›ÚhÅFÈÊ¿Pà’bMÊÎçËC eª»zžBœ‰Êì¶3o/n‹É¾x6óiOÿüAã ½E}ê¤CÞÁÛ’£¢ªn€Nš0G�«ëØé.¨/è$„ÍnqVÇÓ“eî¤WJè3ÿRH°¿NWÜ�Sî• šITOs–^é�Vxò2Š©Rí�ì�í½L¥+R^Fµ¥Í˜�¡ŸæÔ‚\ÍáFsÖÚËì¯ÎC “ÚÜ:ëu™{/”‘—8µcRŽ~�¶ó†ÚsËßww’_ÊÄ_ñãçÎè¢$†OzÛ¼jl#DvBNDn:£\:WÓz �ÞhÇ_ºâ` £&Õ4-Å5 ?‰`ß‹VД­saúw¦�S¥…{Zü‰´*Ë`=ôZTÔ�µ‹)·†DÖ�ÿ¦ú6ÁÊM¿ÞÏcåÆÐüf¹?BóHH«Ñ¯šJ8�B¢WTŸ®ª�ïÖ>ïÏ&ÚØ¥ ‹ 6GHlÞÅCz|°V¨Ú˜¥bÞÇ3Ü6¢¶á¡Úy1³ÀZ²éÄdËm�ÏD è1c?7óM:à” ¯-eAÑHŠp,8ÊNñ_jañRiÂwWs£Ý‚9ƒ5èF¼tyXì=@|Ôz8¸Õ¹˜÷ ×Kɘ%==˵öžÄæ•d%_ðÜ¢ÔkÈ×¶ä£ÙºÑäv6vìÈô~^Ÿpzùwª×"euÎçHãÙh6§Ù©^ýn"�HOyéu—c¸<ùüFð»kw¢IšÞ}pa;Vß™‰3VuoŸa�ÿSº½4…ëñT� \;{�ê}Ê(/-l¼H‘&#+êú[¦-–`ãÇ7íüû+p•|åÔ>Î×߈îÔt ¥c T>ç4A#â*ÉÅ{,È?©\|Èä''¢\$:%%$ôàI^uV¨h,Ä0\a^Î}º~‹0’V}]¾×Úݤ—¾™>ÉÀ[ ëÅë^�}š¿Yñü蜿^Xîñ•�냵¸¬-´4/‡°e¨W¿:ûTÅO?Õ£ºEªúL­š’`E•¢�%Ê7Ã_éöäó‰A›~½i ˜N”Ä•çE…í²-iyEóÏ`¡T÷Z Ì 9 óÈú. ‡uÁ-¹g›q#,q¶Ùa‡˜†2hÒfØzw^?$¢>—õš–Á~/^Öÿ˜Xçpêåe ™?ƒù'G¾-xò¤gŸÃ°ÀO±ùߦ§i¨ Ê4}û¥‚ºîšV†·ýµ¸.õ¿¤rñn{¹–ä�燗•䇦Bż!¢ã VÈ=¥‘n­¡Ì î•^­ò0ñ+OkQ: ù5úµ‘“@HB–zMÈPt< çV�H\Úíd6�RîƒjÞï– ¤tÊÎ~5¸ý×MÉS·±½ZV¹ñ"™æ¶¾Jïçâ}á¡E‹Z Î÷!©H.*0s{Æø×G®°=gnŸÕ{%£wP%²'Nepa§RÊõ³_DÿTœ®‹¤ñ@†¾ò@PŽž_¯z5�:Tú?Õ¶{B<Ê› .l$KLȦž‘ŽnÄó!’NãAAµŽ-ë}DÂÎ=7”È*–àí>\8^zMªf‰ 3L7nðºùèuš‹è޵vúÍV’Ö5s½Ș°Ö%̈Ë�ÚøQÇß–\}×r=©€({n#ê~õ3ñiëÅ¥”ú_[÷÷¨¹ª0,HÁyØs‚7íq&j¤w7àì?å�•JETÑn,±Ã;»IÌ»ªG7õ­n�¬ýú¤Š‹!�Eg³¾›c}‘–«p$S½¿±+Ì.K äØCùÂ\qºê¬*�)›±Í@„Úi¾Ó“ºjç,tƒhcç±$ø9ìRôØ5ºäÿîúØÊ\0w}š‡ºÞ•ƒù¸ pä‘.Ûê­ u>¥cà]mK]õ/[´êI¯(Q)ƒ Dys.¤¾WØÕØct¤’’jIm¨<�.µå  hìÅXKÆbXÁâGa$ƒ)è˜Âm3H1lƒˆû@`œhtÍÍ�ÁþrÝö"öª]Q¥LøôË=8È,Y±ÝÜ*õÌ« ‡ü9E€EȈ“ƒÛ£î’eÝ×(Séðø x�¦®¢šl+gì1±dÆTf“Û¡‚@é$a¹Üÿ�rÏ™ª’Y…ܘ–±<�ŸE3ìéºóÆSTïlyw¯pǦäœGX۱ьâ0w•óÃ=þv­&Ã:ÒqÎjy[mÒj[©Kµ�Yh^`˜h�+iïŽiÖÌ­ŽdËÐF’xÚeö`Ho!mÝ.I÷êÛ ‹YÌÎ<×Iøò¶Bt Uâ¹–GN‚”â*êé|=PÃ(YÁ¤ZÌÊ‹¾¾-�yÉRDñ®FyE¾¹bô½»ß­ õ{”ïß0JNàSùŸÌNÀIMl€P£ße ßbF¤Ë÷ÓÚ˜³¨}hÐù- /Ð+(ïÔÙäÃrCè˜LŸ€çw¨–I-tì `-ì¶‹R^y Nª&‹uï"§Ì!!]¾® ²‚/<èš7’§ñ{¡Ø?ùu[~Ü�PÅCTö*úW[å�ôÓ|”öÁMƒŒòdWÖ–L¨l�ÿƒðá›ò«Am³‚üÁ ³ÈàAç¡â¼ÌžIiŒéµ><ù}”4ûÏýÑfÈ/�ÇÒj'~/Ú }`&jI eY>¿ÖÊö½u˜ÉxãE¥8=’MØ$×dÛ´L�=ªèÿUçpgÖèåå²g<;>ÞN kO×o#Ž�–8Û&3®Ð&½�_c§ÕF6:%ÀÈb#0®êêÝrÛüJ"tzS¼dfáhüR 2Z¾—™½Ë:p+•¡á€ÝÚ¢.pù¤uÔgÂ"—SŒO(0ü„‡¢ïÒÓi <-7‡ÊÛí¨ ; Ȩ¸ „œˆ–‡ÍÂbùEZu’ ›ŸÓã6nŧæ¢ë.!ßûú$©£O™5wGSoÞÀwö#áä $^ü—*·G@ÖÙWìšS€ÂšíÔ»u°emµ¿Ø$fº™ L9Áô¢ÂňFì9$;góG³pa CYbåìjÛòø/ã=�®~ÑœC+ÐsFŒ p£³LXÝ…—kËÁÝ‹Z×T}š3 zÔŽì”7LÚcSÛC/¶®ò§†æ<6r¶�÷)ùÈä‘üjÔO EÏƉíù%³‡¥öŒ¥궺É6�Ëè÷ðM@x°Æ_0OêJ âû"›´.t)ëþä_<¾Y_—'Ǥtò”r©›—uµàëÜVR¸ÆÝŽÖ¶Ä5jµ• .\½í$—÷Rž–Ú�P§¥s`~¶kIñ–…~ú`u?[éª K×CbnR-s&Ûô›?m ìÀÕ""ÂÜvÚØN·WPWÐ�™ÈB(³¶pûükæG´Àž�h‰Àl àm!Þ}*ÿeöûÉ ‰”x“²¼Ý�¹1>Eù�§�µÝ[Çø9UÞׇ›Ê�ybùh?f)“½±ví[8! Uó‰‡ÃcÊ_¬c“ö_[3/CÿvÎÑ]Gå¢Û VÉrm*³°|câjÞò¡’þ��Ûø¿ÜŒ¬æª:ŽÔ_°z8ÂÂ,ˆºÐ|#&I“ßy·Ã!p‘;©íPåBɨ4±Umý˜£­°ƒB�ÊXƒ¨òÖ:r"u®}÷­Q"Qi�­ø›%v%¢8&U³ªñ+îÓÂAî–8^‘œ9 Œ|g?òK%‰õ©•Ðs5clkÄ|�MíÁÊês}Öƒ»ùpº–Ò€“ñêÍå øé{¿K6d`ºÆüY ÄK„Ƭ]=ŠBÈ`#‹]Á®áÒ@ ”j …†ÆKçþâ9å3 …<�ù:wöx’-ü\0å­5×{F£ÂL�‡&�z'ÕÀýÐàÄÓ\4f’õúT,ò„^^Ç»n–Rí…~Ø;³„›�öèé�(ü-¾§>×û�dµóïˆ ¥¼“ÝlO»¦D�  ú­Hæ`B`ô¢ˆ‰¹ši%#‰,óÈ1þk4èÊ ŸNnÃ2¶Oƒs3j·3ÌI2îU‹gÀ{ËÞõ5)åzn>îƒeñ’ié¼AmþjokÒDh`Y­‹ÍgÙlðT78Sa'®`Ÿ?Òà50 ‚”5�55úèW&ʉÿòö¾Sàe]2n•— ÀísäÖ46I¸¥:ÿ϶÷\š ÀG·Or"6#¾Ñ¯O!Ýcúǰo°Rò„Ê¥ç±9Ä z;ª­ÀÇèçv𘵌º‚]€Ä‡~KÌ ÇÅvÏEÎýÉžñ�È7A)r²Óã”�KñZkVT­:Qý³›c!�~ÕWeÙ­¹öa£c:aQ [Þ Hkc]?o5 �dØp/–ötV§9"ÎÏU´¢�àyÌ”nWDƒVóø+»LÄÇÚíÅz€2ïËíauÐKØ¡‡Lž?h�ó±5ÿm”²›,‚®ëò^ÉÛ"¿BÃò/&”h±�±$ýK³g�]üü¡Õl±RXžÅɪaû|Î@¡ç²Òåšòø6·MhF£uøÃo¹‡Á\w(Â.cÍÓ]øwì-!5f“Í�’ƒR͞П^æ Â ÐiT]B «ã>RL ,X?¥b³¼NìL0\w2º0$‹@Óž #‘”âäÖ¶�"#ÊÆx<‡³"zòen¾8�ÈâåLK��7'GPTÆ­�Îì0cŸ¬¢¹Z-ƧKÐ5–™Ÿ8ÐÀídw‡¥ÈS*ˆ(÷5éâ'ÊžþÄÅä,a�9ðŽa¼»Õ) pºjÝtO©Å6 $¡FìÝGÝΕš­Z$äÕ&»¬ÿÞr2!d)ÇQ’I|ÅÊ«ŠL¯†ðÂÖt} ('”MJÆ�¼fnþˆÿªUS35?ÊJŠÏ£*ŠƒÞN‡õÍhºOËþ·ß£+Çù„Ã0ܬ–ÖfN©qs44+¥hÖïRw7«aÛÅ|as­>ôªªÂ§ç¤''d¸)œÔ#Ù©‡õfÎ_³T½9ÀÑ$rש�«÷!òB¡" óQ("Ä€CR‘×£™¤qXW ëÿ�Ù !ÕE®K|&Žb(E€v£mÁôÆØ¹KÊ_Œú5�[Év]MÒ˜˜NÐsÌ(éó�`m´c XdôWš²;¹…Q/¿EÞo€QyÍÛ=íǶÿ5ÿ~fÄ‹žÔ®ïÁÚ)¨Rðr¢‚ïHèåtëß(÷ÒÉѼТFcÒ®¢£ËžJm¨èýy–çaâ×\PÓ�­…ñ�h„Iºd,Ù<$–ÓÒ¥nOþ¢HZ²üþhSͳÔt&líó¬¨*+[бÆ5 I¶ƒX]:>Óò‹€Îí‡Âöð+~åý'y ? Μ;¥ Z{L›NBP ”®µPìÎE¶šN@P4¤¸ùmœ+=„8 „·�£ÐñkêʰIÛ¿á`ªõ«Šœðt¸ØQŒ� íZ<ÎËšïv±gMÔ ’Ù…�ÿ&•èIæ¡ñÐÏ |ïºû@ŠWwj�鴷ɾƒ¡vNm§È56k ÖËc;å} ¿Hèal¨>m}o†àB°+ÅO¢¼fÜü¹ÙÈÖhß ã2t}ÈÖYqÆÿWaj5L`‹ß>Ø»ì…æ +WNZ6œØhG‚f×yMýky;ƒJ?&º×I_ Þð5Îàx.—¶Fï¢~8}t¸ëù(€ªF§³ìAá~Ó‹%mÆ@|Õ#-v)]¬mYƒ2<Ð3wLiå¼À|ÊZœ:™ÂM¾½g3Ì_Ó�Ä4ÿ=±¡Á£â¶f; ÍTY©�q&!_Uݽp´>SœÖ?–@³ÎtÕ÷ S1+Tl†‚ñê‡qÒZGÖëï¡g7ŸÆ¼âÕ ›²Ü:ÇÙÄüJ§1Y¬Žá ¥Û³D,I·G™39¶@×ðªvˆ«A™ÙëæSRÕ»JÚŇÞl¹ŠfJ cv‚Ë„gdÁ¡„pMZˆ_œÓéf#ÈäÿX-Ò •¢ ¡B‚ù5øW¸á,u-P×0ž¸„J`ØKâk1çïŒt+uóë¡k‚ã˜ÈX—ÝÔCFà‘½ºÙY¡—ž«,©Š±â›&Êç¤5¨ ˜¿^G:ûÅÛ}óܱMÌ1Ñï“›9¶ ==¾(·öò[ùUËp®†Q?¸k/Ýøà[-pÌ:UÐÐÎé…h~TyΖ^k†©× aξàþŒ#½jz]ýCŸÙ̱¤¿e‰fë¸âEf`gyBêþØwi\Ìþ@t #²–ØŸ7†NJ73ÙÌǨ?:¯{¿–”æŽí`hìÙÙþ$ ÚÂÆ„…ŠîSá�ª$0ÍÒñ�HRÅaEñ�pÐaûù(pÓÓ êtîà�­æ¡›ž|ç¢3f+×xöys!Ë‘Yú ïd¾É²î'&X¤g矰pa®ÍKoú‰ÍÂ5Æ^Ú< Å�0&›ºDW™Ý+šÏOÛ&l €“‡ëÀàUœ‘ŒOŠÛ<­è[yJ­nÝàD¾ËMYÏ7,J•¿Ç“�Ae·aÍ·h�Z�›q ýª·+[4û�ùF>Y�ü®Ã³§-×ï2Y4@ú.h‘¶¨¿ª9ŠÏõÎLuUá–4K:ÁãmHÌMµ ¬YÍך¸d´1¹Žl‘Ýx1iŠ–Ñ1Ì‹]}‡Õà”•Š£ È÷£SfâÝo¯ç¤××Bm'MiŸ7ÿÝ_iý._ÞQ=Á¹]·ŽŽµÔ¬MTœÎ•&hnyÏÓ_ÍçSƒb‹©C3P>;¤üYßP`úDêM铜Âý׬BNôçjO´ðv‚Ä“_¡iA®íG†�D‹W³†U†ŠªµïjR*É€òY…�ÚþYš§ípa&ÂVhIäL¿ /±B,DR.’øôüw(9ÓÅ D¼ü_³…Ïd6wsØqIͪ„D#ùAy…¨~¶æÛ omË>󙈈œ=IŸÕcáëÏ|ÝP]Y)s8y%ƒÍAÀm«T�¡UYÍ`Œñ�Ú“±¢»îf…ÔbL¨áøS>w†P G$˜2‡m�Qi×|Ñ5'É\Å� 1¾”;w©”ðgý$ËY©¼O•¤8žqÁp,Ž�漑߱>SìO�:R§4¤–ó€éˆÉÁ=ÐÔñ#Œ$•ÀidÌKQ쎗ºô!¬¨ì‚»°‰} ÉtDåÃ|öˆ|rñ~SÖ)áb˜nÐð5þ’øøJ ±î¡Ki¾³ìNÅ»®¥ž•\èðMì¼ I]íÏ»®ï½6/IDóŒliç¾P¸dƒÇKp‡w‹Š’è¤l…»‹V·;Ú|âäuí°(jús-š1V,Ö„B)Éå­!8a%7_NF mÝ%QD‘ÔÎødêÃÓPC„v¹Iyš"Tý„Z³:k×Ù<%jÆÁNJ¯Ûmf™„49�D2 s&íx€Ž$ú"[D-ŽºŒƒó «¡LyrèÒƒë—àܺ \ýK÷L¦ès´ŠÊ7U0_9ò9ü¢R<ôje¸"7(3DCDkqŒ³KÞE×_ÙK]†(÷£³à·ækå²$°Û¿ƒ[u�e…LlÊcˆû!ù½L†Ìd­›‡´"&ƒ_Ì4ÖjxÜ�¦ˆZlnÉ€J�Ïéë[yk‰“€Ì±ï…d¥3äå¿¶R‹ÉŸ–Ëlš±uúÛœ’ô©ópƒÂßôºaÓ!3¹å�¬ê]yôü•ØóøÝm b1‚�UK&A ÍP¾ØDݶº‡·ï±­7‘y ´¿éjj䟎Gõï=/}væè�;Bm/{Qè캸”´)†ŸÌMhÈšS ÃtR9”&6tè·Ì~F€JðÌ,ŽÍ—ÏÒ1È9ú}3Œ¦•^Å6¸“{�X³Øb‚©`:éµ÷�EûO¦Õ¨oXðØz|q¹uT •Òâg-N$ÓS3þ‹‘Ûq0q8sÜÉåy®«Õ‘(¦/ÁëÓò¸gIgT¤v�öîÚQbÙVJžfbgBšoåRï'Gê]h÷θŽ�"z-VÕjh·Gú±JÓfÅðy‡Šè©µà\œ?ªêÈ7Õ±Á­ €Eûs,eþ,Í¿4ÄQ‘Œã9 Š^"ƒÏ\©Ï²€]ÅAb€ú�r¡‡ƒœï@oí€P›þŒ� H^V°|"í†À³Îo¿E™Ã_çR½õLj.ʧ%ÉkÿÁž*¤PþÝÞ�ÿò;rì�üÙþB\ÈTbÙÑB±b_oÛ‰$1N¹¢zÙRh gNZ´˜+Aï‹É‹`3ˆwÕý=!†Mr5ËÚûeÞS(FtÚ)ñO0¶ôŽ1fH �õ9|æv"FªW]�~I€÷P~ÚQÅ5š U¹M#š¬yf�Ê�“ ¥­dªÆÙ÷sMEëN©1ÙÂÅX$Þ­ZIx†·Ÿ)¹™t|²ò†ŒÑŸ¢O)Ô =¶åÓZYÕ»*A÷Ÿ±Š.Ú!ëð³Ë[´¾å!kV˜Ž_•_Îþ§ÖØ`ÕúXhö×&Iɲôÿ²HFáÐ$aèEÁÍì">=QÙhcü×–vÀ˜úI6‰VFÓXùF½¤$ÄŸÃÚ‚�žJ¾o8†¿ùŽs¥zÕÉA šÊ()èÜ?B~ÕÛP.y‡MÔ*H”�Šn£xö¥áy{�jwØyÞšäWƒÅ42ÁUêúœí9-4¨ ¬ˆ™3<,T–A„£‡mÐ:…ÆuÛeús°�/+!p÷ ¾„yÎÒ|Tðº03A…%X»­�6' ³«õk à ²27=«æSjUŠQÔ—W|JRÄ)Ðq'»‰Šª¢¾ Dã‘t^šC7¹°¥bÞ¨ŸbTØå#Þô’Yäw{·(7ómhÌ‘L°ž”’X)dz$¤ÇÅ%QnÇK'ù€…hýáAC0}v!p6„ŸôG#¶r·�sÄýãcÚžaÆSÐm©Á…ôœIûÜ ?aå˶Ë¥K}ϫ͖£d ‘Ê®þ÷z(©çÆIáÒFÀòw¸3|Ùc×áœÙ@•š¬«Ò¬.ú d~DÛÿRjʘô9Ç>ŸÇø?€|¨¼ÍÒ½vt 1„Îý¨è‰Â²Å‰Vrƨ!z�ëͼÔdòM˜¶ˆ(Ê[�#Ø´šBvm¿˜ù—–tةк˪�ã$ð ÈcÞ¤mËë¿ÜøcHû¡pàdV*‘ÇŽC–Ûsì R õú´xvãW„(4f¸ ÙO„m òÍ6«qV!ÅãòTq3e»{æ�Db qå¼�yø]$Ó4 ÑÐæÿÌ�”¼¸$œAe$_1©½Âêˆz–Ü‹/v4žfÜäÆÐ|®ÛWüó€± ZÃôÍ“Ë;-¸+ˆ¼¿ ÜÁUCúÞÛ‚z–và|góÚµeá{u ù&ù&š…")¼�7ul†ŒÔ#±A|¶OÏ�Œª#ßÈJþ˜)ÉÔ&ùavÒ�¦™Ql*aQ†vîEdFœ¥ÂKTñ»¢ƒúû_JŸÄŠÂ Í@³’¸ÖÁÇçÜíäCج8gŸÇ%’îUV&e°öunÛpšš‹Œ#óL-À²•6„©ós÷?6°ªzëP4%Yl¤óDèO};®�w[L‘ÅöYÇD,ûè Ãñ?¯� mpeUߺ×^lõ¬~{C¢Ûî ØRºÚ ¤j7‚½e’‹Nâ¨b§m½Ð¼pþÌ&Œ›³.öP·Óp3.ÜjZ'”‚§’ 3FÚvç9óR²Å´=_=O³½ä~žþÌ©WD#*˜Ý×öhµ9”'‡ ƒä I9–ºç`)‚üMµ^ùÕäÿùÇš—€Y¬»{ì¬Í¬ª�QifÏ4í §ŸºŽ3³$AH€†÷H7fê•ÄÀñ& eµI‡€ Q%“›gS3oM`/¾‡YbËÕ4y±)}ƒÿÖôñÂ<žêê¿ôÃþ/ SŸ˜›W¦ãj ¾¦ÞÝ*ãZìñ†Ú–N Þ˜RájÈÕpËÈ){­t OÝ9.²‘�g”É/ìjåĨø#sÙŸ¹eöIY®Úftëœ.³Ûöð'ž:a* =^ß}Ï7™&¤’Z¾smñò­™�ÃØÙ4ˆÈ§fðF&‘Éé#Ó0¤„Ò™1ßѳRni»ÍO[BAak°rlfÖr�4>Ú‘ø÷yòœù‡½þÙD"u!ª·ÙyH�Ã`­«"]y†Ÿ7Ýh›£¹1“�æµXO¼"’‡d¬(È SŸ+S4 àæ×^þŽû,$a|èö|ŽwO Í#„ÉÃ�±3g«Kª ´äЙS5~sSþÅ5ó‚©ð$W{¦™ w¿ü²`�-–µ-Gë¿]!k•™ÿqädèTƒF•²û$.¥ˆvÁ– Þ†�H£fó(Ä“A'C"׈ 9Λ½KŽ„wûÁÔN8#žõÚî<ílÌ�ŠüzĤ¨Ç0$v`âÙp{} ›€ å„áÒR|›Ñ£�0e¤ÄÇVÈÿs/`�Ï,^i¦ÚÐW™ÚÅZä¨Ñ½³‚ÇLºu3œÏœRIJK7ä+ùƒ÷ÉžƒOý…Û�°ûlBàoÍwB ßm�Í? #~¸”m+Bv0yß(0냿¡¯ž'¸ÜöƇåûåBj½tØŽRË1¤?�ò×k(9»gÛ`ØßÜ×8ì÷�Åî}4‰¬î8Y<¢ÇUòà‚žX¤÷óe<ƒÒÆny$«òBG¢² ¬A6%­-â»m�˜ p}Ôµ>8õó¿¶ 2XÑÍpו”«Á@‚N A·Jh»fö¸ºªxVÿ¹.”„ÌoÕñmµ¼Ø¤ƒ'†»J/e_WŸoW{Ry6¯‚µ ¾düS­H.'Uc0 Éñaêž¡×ÿ}dó)Î;­‚±}øÏÆÄJq�çF›\õW™T=pyÄocl:½¦ÇRÆ¢G[Z,‰Û“²ÕÅ€€°G£àîvº÷F™<‡R£DUR¿ˆxRèä:iPÕß”&³^•(k°M9ö©¾âÌfE<œŸêö›ú‡îŰÛôˆ„œö-l1|ÚjðsÇ‘C 7J€¤¼?“vçªä6!ÔÕÞ­’Ô=o;ô�Z€kþ Ð\Ñë“Ö˜Œ0ðDà€kâ8¡7ƒNÈ$w»| xÎáM"ŒÕ×§Šù¶yaäáÒrd ;™½äj2Ãúø5æèëwRC„â‚~F< †éìqÈÄÓ'¸tK6õ]òk<b©àóùŸ½)§bk‡�>ÃÆ…¨}ûFÐ¥t¤653Ù®Åyl'É`A«*�‚þàgjLyñ{i` +ÍZ>žC�ysÄ–ß+Íu!¤2¶¼èfæW7Žpù–•søÑ†ÇöÍÚês¯›£¿–CÆu¡N´=k×Üȹ‰ÿ4L#á•9Ÿ ÝÇje»ww•×ßMÊ2o¹Üš*IúŽ‹ø¬ê9&¤^;Fa¡•tõü+ñšÙ©ë©àèþ2i6cV,¨ ¼áZ6A1þ4S¢XÝ‹'v ªŠšÄ¶Ñ%þêØàVîwöÀ•ÿóÚ´i‡kL‡iµ¾È%�òŽ«®G¸sŒŽk\ ùŠç€ ›×uÂ.BHÍŽ+ä†hÙЪI„‘’çn›aê¸é)ö\û¤É�¹»EfÉå–ak½H†Øò_.…Ѿ3]C>s*–Ú;¡]²_™À_¤Ôm¹ý*_Û¿?vÇMÏaªÛó'ÊMKö¿†.=zÑ©†Ùà¾é¦ '"š}‹Z‚‘/çFØíK*&*ZJÕ¨UËØíqR`§8é�nUÖ„]±É# 7ƒB—?ÏÊÐUBTÁ|ʲð¯ó¹uá­Ö-å¶÷VÙžslÉ_ˆP®8i´®¹ã¨8–ɺr«Yu[¹í[ °ËMù>…Á²Õ3…Qd«åôæ�™Ïù¯Ú Œú;ÅêL…¢ 04rØ]ÓäPEIdÙ¦/yR$åæëŽ/O=eIc u<Í*OPÜP";´µ±ò  ØkGÍó¯õ{¤Rš©$iss¾<,òdYÉ‚4{öÀq6w³rK˜Æ;]%Ü߀F�_ 4šÑîܲ=2äÚÑBDµ/$@K«Xq›è÷,XÇR­—�@\‚nx©—`"²p&Ü‚÷Í•=ÅŠ4ïU»Öƒè�!ÿ5Q>mw;ä{‰¶óQQ³*ä¸Èß¿Man-éZ!%Z YÝ­>f_iŸzÄ.TâFàeçµ›‡ÖÚÍK2]FùxâЖÈÜ |ÛAYH!׎Óû8®œ7Y„€Y+Õ{Á¡ãåöÙp“áŸÑšÊä!ÿ­”0}"µ&Yµ‚i”ÃÒ k;Ïݘ”$Øþgz�æ`$` ôåòh`žÏðõN�KZk*Å®DäåNTö÷`·Ìòl ˜é’5Í­©fW¤ö rŒÉí "Ì›à4T8Ë?¼Öeê*Õ:-õ®¦3z8 ŠàÇ©œåÍȨÿ¯i™�û‡ÀhÊw4q™§Ó‚l&õ¿.±«¨$Ù".”yÙ}&˜!¡Ì�뢜H3ègÏé8ÓcÖòRî 뻚9EÂ*‡:#ËᧇÒjWîà¢F?Ö§Òñ!™6‰P~ d °à � }Ï>âøÚ›�ù Û5¬ñ”¥¼>P+OÍ‹9H6ô1Þ‘¼–8ÑÚ)¹ ÑåXk]5Îa«¶—ð|lG¿èýt5ÔÐ5Æ–_"/R©L8…=µ1™xŒ»°âî¥ÑPmL—ƒ?iWë&Sr3õmÁiøM«”ÙX°‹êfìc¹¢ü4a^ç*âT§¼ê!ÌÐÈÚ"üéî�ô6Ѐ¢ Z·êCÖƒ,}…$ã<©ºs2"y@ke¾3ÉŸ5uÆÉ²'œ !Â!Aõ‡æØ~$7«ßW(6†óæÖšÆ®ß«¯þE~gI’Ð܉ ²ÅôÖ9ŸiIì…S€+zóW­”c&Ü�:8‚0\Þ§04 ‰NÎÉÈÌã9šª„ô  äísü£LÀQzµTÿMŒ»G7%UåíQñئ¦EöHK©¡5IÕN>�Œ›K\“=ç*�Û½xIÍ#IOtHÓýÅùž°tìÒªÂ�y~3Êc‹Ë ò{ÊÆ êá·¿k(ÒS ôgîê[ô%@ù{à R`›NܨzŠ®¸Ï�žc¶ÿe_8Bë›ìe‘ƒO½å¸&5–� ´Ž¦/‡w�Ì(�˜’0âFapkÒl–¢¯ã.zñRî(8е¼ÄÎá‡ó?¡ZäpaÖY‚\J…\édžݺÁëÜŸ¡Îå6Ì È ;­»ãJg¦‡ë7”½iÔx»É•â×$`ƒ‘œ«‰;òEä[ _¼-«.Ü|gyÈ{ɖ↱j&d«Å¸Ïë‚W…•˜�ïÎ_çŽòÊÆs=‘’®§µRä‰qí˳dKŸ(J„,0l!(oHÖ¥Ô†tô0·3\ñÂÍz;ãÞ’{˜�{¯ä�Y½�©i%Ñ‹ÞÂè€Ë"CŽxý¥5½|*rFè@Í´Á9{eß— µ\xê×â0f¸Ò£%Crè::t´qü‡Ô›KLÎ@Ê·ˆH÷ß!›àéžìÚ#ô©#Æ*¹™óãÝ÷Õ>0tÎZGø~ž 9&Í;_+AÖªTÈp�˜ÞÿÎR@Ù¶z+ŠˆúÏ�î÷K–@uzð§·VïÊÿüð. ›œ'+™ÙÊÎX¦ ¸ñø{çI,Àü 3¶þý6BvCÄUñ£M+àטt\DGýK¢¢u¥‘%üǘ ^T¹ÐHy½æˆ�Ô"¡ 3K‘£ËMéüÈ žùÞÌ ZyÍ÷º½xe³¥J|àÄ ¢ÒnyI;É¥×Û¦4;=íñA{¾lq<;�ô.�¼(J7%v‘c˱ó¸NÃXLÅÞütTåºTÏE4Æÿüýxv¿ ¶F@ç”g&Í*IlÀ©�(r‰Ÿ~}’­IÎØnž�2º|�U¬7–íJb-zµYG–ÄdØŒ›ßb! °²öü',aižý„r%ù´Þk"°Â$N*Z8VTc[ù|L©ðPëß×)iñƒ>±Äæ3K,·|#u (Èh8…3} ­êzNºx~ LðÈ™Öð÷r§[¿Ï±Ñ§nøk fsÿZ· }ªÙ¤‹êM—Z@ȸ§N¼¶(—ÕÝ#3}ÅêÇ8§èÓ @Ïê›”BëµM¦D§æÝ’ÓÜg+’óK£€]IzCuÌ|î�~ü·Áõmw©¨äº¸*-³„I2šÃ Éȉ·�,¨-kL£sÕü… 7Ö   Mô�¥nê)°‰³Ê‹V•I„ÑŒšõ6gO¾K�Ào±á¯@ ¤*õfpŒmâÙd®õ{� Ž -Cƒ/”&K||ããÙèºE#'ÅeJp-OÙ� æOÀ•�ø§¦üóÎ$WÕÌR³Ã‚PÞ�+B Ë]lGX¨«Ç©­0c’ªÈˆ­ê“^ú |‹«x¸‡Sü7*äŠ|çú¤$ÖŽåºçÒ6›#Ndê“£º‹abLJpŽuZG[k…±%DäÑ“Äj-0’ÅPšg!¯dòu{ôÃ79ò©EʭņtòÂF=¥é]µí¹ª­¾mV¡ðú%5‚Ã)¦šóÝÛp1¸¾œ}°ÉÝumÕ5‡sq¾¼¸(P¹¥-œô-#lýc‡=ãñZr ƒcÄ"[âXÜYRñ[CIä;ën°òŽçîŽ'E1ÿIrjþ¢:3z�¶a>\_> ’î¯ãDÃeê�/Õx? š­T}ÐôLº½.«gØ!j(�÷ª‡Q•4f`ÕKmß ²ƒÓ%1ïwÔpÄ«e�-G"Ðâ�1;¼É@Y¦yCž"h^öæDø?Ϻæ³êH‡<P÷ N»zݦà�ß"' ÿ_‰ð›-Z}W‘uV?ÂQSܼ’ Ð Õ¾ÀÊ ~LÇAæs‡¹8$NXH̳`ûU›½áŸÊï› 'õó†õ r>صºÐ““¬oÍàMd‹è¦ØpL/>ä5_‘© 8·±èóáþw aò±ßw‚ÇíˆjÙ<¶ìøî\ù@Õÿ¹ØM¸· ªÿ�¿J{ üõA¿Å›qÛ{-‹êK\šò]ò¤V?Ø,z¤YŒô;Tí¨˜�˜«²ñ^ÔxnM(¥™ö,koê–õ�© %hò¯Ç¢Ûì‘ùš—Q‡P)iêX ººç UµÂ�Ïw)ÿˆ×ÚèØÍf!½ÿKc¤ôv¦aeãþåÔr»]ÜŒP, ®�±îˆ×™ûø­å=ÀþBšÅù£ù3OjJNPìªü¾+yˆcÔ�#\¶N­  \Ï*LQ!5÷åO)•'ˆ}$èDãÁ«… 0ÛA†™t%m4:]%¨eç§þ�zó¹k†xÔ‚<—"’J»ÁäîÍKÒQ͇o& �9ƒ™MPœvrz«=_Ñ|b�T¬þ«}|Y0Z vƒ-BM£Ñ|†•…�<Ë­¨á0ð3K¤W]¶ÑaéhÒÎ}Óèá—»k\[»Æ!tA Sgµš�M–°ÞE뼚P�cˆ' �ï!ÄÜsx¾¦°œ?UŸÉqvûõɕܔªªN|'\)™¼è`ŽALT4Ì6Œ@Åš t{ú˜´€ÔJ‘ñ8¨¤ü§Ò”m.®ãsøF™ŸÞP)œCÃù|Ö²5 t-ÙMn$¹yQ:GGNA_:9rKÿŽÞðAÊ!Û°�ëm¼c×êBßHÅ0õ/ Ø+€ž®Sëò³¤‚! 1 ÜÝt˜å�7�Q)˜eÆÓä�„7†œ*pU’´¨§=BF*fg ¹€´§Y+6ª¶GQ=›[×IB<{NƒK«RɶŸrt ç´�cÙ)ÏŠ/HîHãƒ8Þ¿#ÝâuŸ%¤¤þ3š6 Š ’hÀøÐö¨(ÝŠÆêZ£¬×t¤¬ÈèÀ&*wî\ÔRJwÈÑÒ�ÁTQëZ6ÒF:¬7’ÿ)zAT˜pmA’Åsûyi†Üâ@–JÐ×BÈøê•ñ®†ÛyXKÉÖYëñNœG¥µg»ðÌÊB}"w;xÔ¾@q”FÅõAP�j[óó�ÍO!3”?FO©( rT÷YÁ’[õÞ~»Eþ?§é.l�ÓœúÓ í£ˆÜJÁ„a¯ƒ´ ¥7”ˆ•d1Gts"x�<)Ù¥E»„6�~‰Å‰a{-}½®²tP5>¿£ç< vý ‹+”‘qJO�AbI.Ël®‰Ê×¾ç¶.o\:QÆ-ùf0ËúEt¤åÝ9J3¼xߎž)ç-öc¶.¬�X#Å&L%�å¿ÎFƒº“ÁX¬?D„¯²—Õ¦qÆ"W/òƸ- ú¬<D |µ&èÇ:÷‡dbÁåé"›Ÿ¹¹9¯ÐHÂÀ–¥R`©¢„Ûúemå‚£¹-½ü÷�»9&Ã鉿^ÖJP†Ïï"îçÉ:ïØûîÈzˆeΈæô@Yß•ÛYBéËk0àù#bêSÊ?+`‹nDžjqš³'ŠË¤oŸyÔé'-…^6pÁúÕ¾¬Ð• WJEýº[³öf§A:“…"¦û`Ø ÓÏ¡[¢‹ðÁÏbæìï |Â.ö?w¸Ñ7±ð>KJ§‰µSnÒN² ˆu\ÄýÖ:ÛÑXE]�ÕH¨gź‹|ù z—ß/&Øq^lhÚii²ÿ÷ÎKG4m¶ÖUHº®UÙHð q£ɄЀŠð‚zD6æ‰×,„:3ã:a.̈®Ó“Œ"4[¢h Ž=+;´øcëã?nþþ¢× z¡—°Ï½¼ž¾<*ÂDl°pQ]7caÒ‰oÕb°ÚàÈ«1PÞô³�KƃyËîöÍÃÝ<¸fzg¸úv—K,ü8!~âRGõàž½/Û1tEô´1M`ø½«£ô¶O ‡áhà†ôÂ"ÑŽ›uþB¼0ðãz‡UäZ';äæ<ˆ¨1^|/‚?'̤A£5†¤XÌzTýÚ\·$ŠD·É©×ÌÄ�sþÃP]?ÃÿÄž‰¤êo¥e”y* N²¿ jð¥Sò–§Õš|ö,’b=4šq½b1÷X Òþ ¢ÝA+mÿpšüSƒ¸„·Ç ¦ßÎ̺t¦³B0 “ªáÀÒÛ¾Lëvg�¤vèý<‚  ò5ïX6܆n{3{ð J‘¨¹ÛŒmÈgƒXµOR�¦Wû£®ñ‰ Œ¾ ÎÛo‹ŒöG”óÕ‹ W¹/`Ç‚�›ï.ÁèWvq"4 ý€ëmtÞ-HzìÃKÔe)8ou$åùl¶Nöš6Cb¿ºÔ�fè‡Ѫ²`mZ3×IÇ8YùWS$ KÁ–=…6ÛåC„Á¸fCô·>¯ŠªÆ5€/�ÿ‹ß¨=·|þ9à�&ú©ãK0�4|oï<j1‡­2æul±['7\�§÷�ED›¥Ä"»�Jô{2èó®éÒ¨–±höš÷M •N|'0Š›¸¡²ÕŒ±ò€ûSXód’Ë·@%¥_`Šç!Œc¢D-Žà|íU6*¡¨Ì¯Á9�–‹¶„ܶŸ{t%â-è€iq;îO­¨*Õ¯tÂZä ‘ôœ—Ð?¦ïHxƒä g !¨›ôÚIæÓALˆÑ�¯r $v9Þ{ûå(è±<€´q£Ãrçþ¼«–“~£³k£Ïnlwd±Û ¦Êåy¬;ÁH§fw¡ÝþB=>žyòs: xJ'ÒhO„GŒkÜn;„P¯ãµ™ñ;g ÷ˆø°“f•0©›4F}<ùÄÝ+ÖL-©âƒ GÏ[ó"­ oC¶GïßNñªSQæV�+Úÿ4,‹â1=�û)=yLšƒ:LõÈØ€‹º{ÿ‡+«1�¥ØB/߈Cή>Þ¾ löOé<”k`�ø9·„ˆµ°¼Õa2…m‚;П«‡1CA4ËéSgO̘ô~ýw`©Ûo'Íc¥­Bö¬tÇüOÇ+ñg5à¶�‘Ž¡^NsØŒ N¶ðyi‹ª}Yʰ¢9ÑúÆ�JÿÈV1'1D1ƒçV)hL¹gc:M]&Üu�Úíq¯¥6��Œ`™(í<Uâ䘢Œ{sÂW?œx£‚ØFs�#²}¼ á†?›WÎ>}­Ò!ÓC ¿,«Ê”Á‰tQçX7¨._¯|d+x•õë•b\œhß—`嚟"Í�¹C0´�¿ºJwµ«ct£²xV±¼Ý¿ôVŠã½ûDÛXŽŽ‚[1„÷ùYø8o­6úÊŽC37H°_k âã¾ø§ò§Iüø4)‚¢5¯?:øÇ ìš$y¹­¨ç¡/¥EiîÝ¢D+¸{I\*ïw²å¥`ëÐD· @rÝ Î³z Ü” Ä/—Sáìº=?F¤Ë1÷‘‰'@U‡T:&#¹“LYùëîwh7Œ8 ­rÓÚ¢XÎaÍŽ=M@jŸÎÔ¾õäsoF‚d/Å€nŽ—KXì¨?°jMy±ªp…A}ÜVãŸó¡§ÿ¶ÒĂ딑�:%Q$ÈOvï¼ætkþym%³íNfË¡b q“•”›–o|±i)éTˆ¥;~4w`E7t¢£,Žc“= !­êׇ¹ä8bÒ­Ö¸$l37‘=E²ã˜ k\”åÏ\xSîœln j7ÚŠvöÊ›þ¦ÖNÙ¹fâù/�ãËàÓùþJ:üEv¡Èe�u¼^¾2kø5”¯è+:„®_²S #õ)¶ü‹6fßPK¡ÓYgr”*“¥ OE¾v >ïz3À›xž ‹{A89ÝÕÚ™ªíÈLŸ|ädÞNïøà2ÊÕ•ÙR3�!«x«˜32² ü™ˆV²È2w®ŠÜ¾�nûzIéÂ&|4’{"9ø¾sš@”Ü|·{ðåmóµt®wÜ Ìß×ï`›½MyûÅŠåÏLW{Èr6)ó.AÔ—¬ªjÙ‚Ý©W-ØÑÙêx°Æ 1ÞÌMd‘ªÌw¶ýcªä޶Ñ…ûm`�DyðšÚgdµßé±F<6]¿g¼~\÷•Û¡ä<ŒÀyVÔdzœÌ��ÓÁ…ŸSÓU<¬Uô•×p�zÍ©ËÓg}a€Õeg#¸Pn„6å»vyI;ÆL. ™Ô�i²‡ëc«,>Öx´º¨­úN¦³•gÄÅ]سdÝ„�¯˜¾øz4Ñÿßc"¬Që|ºJøc¶¹’z8³Ü;6�ؘË>vd¦•ö‡ž1Æ|Êù£Kréß Mëå/0 SdUR¹9ƒ¿#‘U9 U}_–Æ °ÃÙHÊâ{Š�æ”McJø*:¿ê3M·á ¦8Ö¸6ÄÐ¥ê Óúeÿ¼sóܲcúžã!PþB~ó<ÅÖìzCe)‰Bq»;ZòOí»/ªülqCæmÎÒ7�§ª|/>~œÿ0‚~B NØ.ÝCÍ·–¾Û!¡|î£îá~Re�£;ˆÁ.ÿ¾ÎÆÍ™穆˜ÄšPC·õ²ÏÍÑdé^]U꯭¿¯_ÁÏNÎJ��7uý]Ÿ;À†S)ƒál"oεÞ;=-0Ìþ€Xè”sz—ªzv8ã¡«† a¤!ôÒ^nCs iÉŇNiÔÃÖ”é'¤ >#f¿doÕš»ålä¥A”â+.º{ڠ؈dª¬¨û“‘¬ßÃmîœÖµ£Åõ�NQãyǤVŸº„„×fdFÔ!Öɺ# *ËÎvªPeazoZ�Ò›m�Š~…ô´ÜÈ¥¶ÏÝÂÍicÙh¼¶¸øŠ8�)…ŒGPðÙ ®Î‰ƒ8*ón‚ºË³¾:r¡–Q£Ôœ½w´ ‰í¶l»æ ޵2jfŒ ‹Ï¸ŽgQ»1‹{S2ܱӨK)½óÛ2E'ð¶#�SJøûºdÅë9 §º 0ìóžÉ_ÑS�¥Z[¤u7–—7å«UésøŒpFuU÷ö‡Î‡e™)6_Œ02– œ.d¾VV,Ý.zg‰q‰ËgI˜ú:.MÌ?fø_ÕĹؿš$üÀ ÷o¬%@9gøv‘øÊx`ú¹:¤? 0ÔýæÂDbÜIŸwŠôµÈpJÆE>ϰü;ˆ_R@Bîî­#P‚hãRßChwÛÐRþÌ<éjâ%ç'ÊX„€¬žf�|‚ŽŒ/´®žì‡† èV$;.Xöxý\G\"4×' N|~(.íW|øN"z$�«P†š¢ªPºŽM£!¤Ýë9ò·9tqãAŠK†^Þ¦dB1"IÌo9qo<°ïW—¯³ßuÓÌ…õ—œz\Ê7.A³1É Oè#™­Z9'ut˜ßöÔ†ET^eE`F¦ël¤ÿ†GÓ½Kk\ÀQLG\²€ ºíz »p8¿Ÿå/å?σ—,x_z¬3ßÄIŒ�.ý¶À6¾2zx›äÝ…o¹³§Ñ3àR¡/9¶ü`Û‡¿ò¿Ó›´>÷kz&H‘_0k´Çau¼�Û)ÇMcIÙÔ\\l™»š;ÌTS^{þ˜ÚF¶¯‘˜ê«=†®¹)¶� 8çØ0ùõ êÀ·ƒþ#©ÛªX†ùs"•/ëJ0[ާsÇ]úN"#Ùd�á½Ó÷й |ÇËKõ¼ùHW#ótŽ¡ñz%æÅ2ïº0gf·ŠÔí6‹KHµªA}F²±³vF”×O:hñ";üî=LºÃ¹kÚ»½%®°ÕVºøz¡ÍráPåу?>"÷Ú­.c̤0Á¸êlâ¦÷jo(|“=Îxàøî»nþº÷Œf­Ô•ñ"WÅ|¾Q¿¤c~á²a.­èTI%¦)lmÔ‚9(=«RljQ·Šß ¨tÏYÄ5µ{({ÐqSæn»È*Ž®xqQã~WßYò4¢Zü9‚Ì“Q8—Ñ%‹PPF´äÖ<4ñ¡í±ÝÂÅ ÂM³>v€rì”Ð0Ž>Žl¾«³„¶ÑOs¼¿É½ê÷V°…̶x‹»D» =¡³ƒ(ÈpQŸŸ¸!¤‹Òw$ŽÓ@²¶[%\Þˆwv¶ô*<• Ž»ôGI òûb»oI÷ñž Ê×F—¢°]�cä°ÜC?Qéª5oË€ØJjÊÌäÌߪ‚ì鎠qížÛšî=O êW«Œ•L�ô]狌|l{$,®íªµó'¨^ØhÃ{d~¾0Í'÷Iê7ˆ¡4½ñÑ9à~ôQWMñŠOwÜMé%rxd�ã6HÄÖ´Va²ÂeÇþÆfàž‹„-~¥C°}·ÊŠSµóåâ,å.—j•h ÌÙúÓÞznÏ:”ÊÄmv³ÖVœ¦1â8ÆŽóøø ¸¿TgM\´,@ke<¾}WÊf¾þ,…ß9¾<¨¨$§³a»W„N°~Ê *‰¿dx;B·¡‘ÖXñ*ô4n¥ÌÞxXì�l›/“+±ÆU¾]o§ZDM‚]ñ»ž ‰ õÆ~׺ñLÞt»6ŒÙ84¾H†¡´¦!ì©ìÞƒo9“3¢kßq#0Ï®›‹­Ã ñû}ž %]Õ‡¾¸ò‰Ì Ý�§oÁ»«¿¥ãæ=ió_¹Ÿ’ïÇI¸b63ÆÅ1œ k&Mó%ùZ�1•� t>‰Ô¡Ït0µ¹Û¿Vqä¢E…e:ú•\<”ª2áÛõ¯þˆÙm,È/ò©ú†�©³ÇY.! 1çgï%õJrµ�ù¥X?ÐÇŠ¨ØÔÚÁÔŒËÜÑk�»žôLª®ñ�¬é–¾ÝÞ0ÆuîTÜÄ…Ã7 †éga¿¨T¦œ¢�Œ ¯K!ü>¸T ­Dk0þý2IÖé~ú<°1žRn“„`=�këH{×ý!{šÌCF¾¹Gõd<«Sžž˜‰p‰¤\¾_ˆ¾†çЛvËu7¥xiák�Þ^WC• m�F–Ø& Zí>zܺÍ8ò€W:6…g•m3 rWf'Êø]�0FíoŸJ*Øvž›m×yÌ€ðÎý…Ÿ˜Z›3’WY®kÇ� 6¶7šÑîä¾lS:£9ÚÐŽóŒãÓæhVò×T–Uå$ÞV·.N^d÷\É \£ºÜûe"»¡¾÷Æ-û:Áj&FùOP<’7éŠ;0ÒŸ©W‰îp‹U�ò›®x§k4#e«?õ»GG#£¡E2s  !ü…ì» ±/S\_A°ÌEøR'Îr0úi`ÚiÌn¯×36w¾û¡ÕF›>1ŒZ»ûn7ÎôhÚ.êX(òÁ9ÞMó ³­|ßHU踽�&i¾åìKiLî€{Ë9 èuIBþiÆG¥,È}•×åî^ãwA„ãžÚ&|J³ë~7qR$?ç¶ô±" Í>oÄÒ/©ý‘H®åAtªùþI¯G Ü- U-Ì[ƒIžÆ)`™ÄXLçY)Fè㺽ero,O€ë*OZ­Ê‘Èkfã=`ËÀ¾x°±Ew˜È$-æ!†WÔÅgqúíMkæÞí !5ç¶HÛsu*ÕYs8yLÑn4/þ‡i¬S©ñÄŒè+ðk(d‰ (…TôAâ×ÛµšâÃH÷ñè†ò~5ÓýTvÕ(ÞÕ"åx<*à£â0¡û]*õqĵzeûмv¹v[’™hˆäs© @·êi¥\2W¶[UFÊù݇¬Û4°þ$«ýŒ�¬]·¿ñ(#ýAÌE _ìuÂ|`A uv5‰mN(ä§Lej}×ׂˆ"¹#·)DÊæÍ=äëQ Ý�tЖ:<¾,¨è„Zý¬“fŸóÖóàÊ*ÐcƒÙAÉ*� ‰½€^yžõYèòX øÃ�N›¬¥Çv×Pª^Ðß—uÝU°ÎÅ™ëLž7,¿“åcÄúTyK?àáô££hš|¦ò…I¹ ¦…ót‡©‚ت>¨ ´ù-ÛÀjÜ=ÛY»kœp8u<ãV>ÛaîGîó§ÑLP^?Ü|Ìó°k£³ϰ¿_õ°Óç̾D¶(ßʤ[Ù»¯ÿBu{,ÿÆENÆ_¾ ýé�,ÔƒT}ƒÛ@h.„;À¹Nôqh2ØMÇß�¡Â$šÝÝ-¿à’x¨mĈ²xeiNC5ÞζٳZWIÙC Ëé¸#¬ü޹l«¨ëŸŠ�-åü|ˆÝ_9«39ŸçhWµuaÂ*òmEÕù�CLb@)¯-F«ÃþÇnlqM^y•ƒßP¯ ÕBƒ—Y—Í4i¦0-ºr†2wÂ| ¤JÆÆ]ÜéÏûxã{9¢_ L Å…t%Ä�Ž„Ià˜‘G±Ïi�8ABQœKПò»?À÷zC«A0FBËÅl&k[’ážwË}›«„'B™è”b¿÷g 3 ÊzuÎ}!­ºO:²�¡+´n endstream endobj 33 0 obj 113085 endobj 34 0 obj <> endobj 35 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡G�Ît‘øˆ’®>R4éuw¿¿Ï·õ?Óåø�oÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:�ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·Êãé�sM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§m�ܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ�~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒßè·RŸ~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßá�tF8#�ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;Ñ�ÈDt8. Pi�|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-�AÍÄ�NèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8�eÁM‹³<—“#artË„F{Ç�N‡® tÛáÞ®Lˆv�qè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»�õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G�¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿ�dØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 36 0 obj <> endobj 37 0 obj <> stream xœœ¶sx¤O×5Ûv:¶�‰mkbulLl[kbLlÛ¶3±m'g~¯žï9ß{þ9W_WßUk×^µ÷ªÕÕ7‰’*ƒ°©½1PÂÞÎ…�…‘™ `ikìê¬bo«`Ï#Ç 4µüÅ9á((ÄìM\m�v.ª®6–@S ³½«“ Й`ö7ýÉü›¤fébüßXÿÆ4€NΖöv¼ÿ½�¨ÐÈå/ fäò7EÂÉ ìà°X™y™ÙxÙ¸ÿ˜9þ{¡½/@ÞÈÅÅÂÒÈ kcï ¤§§‡£µwðp²4·páüÏ@­®¢ICGGÿ/„…‡‡`ìñ߀ÐÙÒÜ@ùoÑ@{‡ºþý ÛØXšÌm<,œF¦¦@Ó84Œl€Ö KKûjQšgù[5 Ãß/V8 €$Ðèô·¿ÿHüGu {'sà?KØYXY¸Ô..¼LLÿ(jöOˆÑÙŒÑèÂô—“BÜÎTÔÞöŸjœáàþI³tšüUƒé96k;{7;¯ÿ-bfigúGfêêÀ¤ngéè ”û¯õ!¸aæ@3+3躛X0ý³±š‡ð?‚,ÿÀFv¦>^ö3#g �¥ðïÎËÙèàâä ôñú?ÿ>ƒca˜Zš¸Œ�æ–vpÿbÿ Íþsþ÷˜�,Ý:ÌŒ•0ÿóùŸ‘Þ_/˜ÚÛÙxük¹‚‘-ð¿õý?+DDìÝ^ ,œÜ6vËß<œÌŸgûþ[ƒÿ@•Œ,ÿ«FæQJÛ™ÙÿåùÏ^þŠø_ý˜~ü§ËÔÿ¸œðoü­ÒÞÅÒø×3ÿãL]f濦üû`ù_ûoñÿñíÿ?«þÃ%úÓ¿<úU(ájcóŠRÿ§¢€¿’Ùþª �ü#««íÿ�cdkiãñÿ•õ-×þç¯TÄÞÆôÿæRý?¤0I»ýmLØÎÜæ_˜¥³„¥;ÐTÉÒÅÄâ?=ø_u;S “�¥PÉÞÙòŸ«ÀÀÂÌüÿªYXšXÛ��ÿóÄ€v¦ÿ^“¸�‰½©¥�9@Õå¯Ù�œLÿø'lâêäôW÷ÿ8ú¿¹ÿ=7³ü[#è4�s F¿3±)ÕÎý|Sjh§b¦ý®¾A¶}Çã 2ò^„{`O_ß„}[¢eÛ,™, ÔÛq± A(Ì÷“бî¤ÀÌ�ØL‡¤8N._ «„ÊÈšô¤øÔ¡2å�†„GÞf6g¢4›ßÏøÉ[ìdãØ±}s%:ï¿¥c©kÓÍÀø`ãÅ(@C,§Úõø�@dÔCˆøýðQ&7ãÀ Á°Ý}õø#h–[o|˜ó|›*vžuvð BÂå³Aðï¾²¦rò®k~»È/R*åN> •…õr‘ÚÅ÷Ÿ]X&ÀàòAyÕU&F…b¹/-ÞˆÚD=ºÁ¡XX³±ÀËûµ£õó `з{‰màÇuÛªŒÔY˜„p3q ¾+ÈŸ¯ì@"ù°ú ~Ç[.Â×8há ‰¿jðNxy7Œ;¤ c‹3~¾ÛäK9jïÑ7Š«|"é]v35£w€‘¹#S€eÒÊëõÃüÂñžÚqëåɘÀuů§ÕXæ� ‹Ûðb9f6=mE+‘HeРHl"³¼ÇÜbÇß…@\fèey—\§:e¦¼ R¶A»y[ò�£<Ö/Ø]·dðû;CÇówœ¢¾ÇŒ��”$áÍÔJñ/]YÏ�bmÝãágNy!×aü©F4`¡r÷¹b±9\"ÁŨrz’§§»²*wèpK`ÿ®>‡¾á/7îÏœÈiÿJ:~à|D4ÞÛ«¿ΰfÙ¤õ¹ôÈ…òAl†WŸ€?ßHveHŒÊ–ñó#Y¡¦p 1Ý©Ü'HËWxôéƒÒ'Mà4ÃŽxe;Ã"BÄ/2ôÕ9»Ñ,ÕœfÈð”/Q\áS¶ä¹s µÊ>mþ žW©‚¦Nhy§¸>Q’P˜'¨SÂo35Í~&Ü^èU(ßxkzEO ^F­ž9 ø?C,òWÕ˜…@BÄfèˆ=°+¯.izcÉæs'…•ǘÔ}—ï;6p${âe±Ræ°A ÕêËöfvzþþ‘ $ýÈ3ÛðyÎñ£W’WPL&¨·²£šCùÈ’OšzGs7–@°¶3ÂÆše…Ÿþ¡BcrJ;æô>·+±$EšzµÈ÷ �›A “¼{Ë”ØYèâÃ{ŒGNÃ0“³‚Wñ©á€‹7‚IÀašñʱöŒn9³ƒ"Ç|Ý’ éT:ä•{ù°x³„n¤žfT�¦ÿ¤Q}/IwKGK;Ôß[–@£"žOúÅ…#*�d‚7-C áèÖüaF;¢DΑ}“µà0Î2uÐxóÜ?±-ké}†Ì¡y^ÎÃØWï œµmÄýê@†ÑzsǨ_…Æ U?úÝÌ2ˆJ·ðxu�=57TUÝí()©„)¸æÉâ3:Ñ’óä3íçI$RWaüøÈðAÙÝþ7ò¾ÁÂŽeÂòù ø¨À ô$ÑÝä^“G‚ÜÙ Çqe±¤ø§7 °Ì˜¹Ýnȳå-*wÓ?Dû$ Ý4ÛxJÑTZw»¨íìš-ä|€.§4Á¥WŠ€Á2ÕUÑ€=Fÿ¥%XƤ"q]ü¢èÃK9,ßWŠ7¢l™SÝ=¹r5‹×«8ëuëã{~­ Ê|F9ùóÝà2Äun­<[#ŽÏ%õb�Äì#,H›& åüâ'¼ì»Å%ÍïßšiÆÇ˜d!“€Í”ü=‘u¨Yj)‡"~VE|uga[pŸ´ë³z¾·Ôó<¦è-|Ö2ûÄ™EÚ”á�´(’”®À8LâÜ%…Q… zl1ò ,6hoè2ùR—ìTÅ–{6:½ó—,”uÃ…Q¸ñ×Cíꑨ*\2‰øËßëÌ]W”†ËòJŽ�Ñ̃Nù>—ªÁ�?0 »Fp¦}GÀ4ާ€ pZÎùy=C—úLP˜léB—ÕŸšë-/t§a™gÕæf‚ºØUþY¤,3%fÂm*¯^¸ù1j…eMô"/ñZʤ¹ô—  #åÚ½t5S9ú¡”A¿5×Ê—*�KÛ…b„·] œZè¼qέÑÓužª—¬îÛ�JTøK›õ�”]Ú² ¢z߸œÅÁ‹ê[oûf<%§Ü®ÉÑu–7pàÁÅŽ•ÈÃA_­wmRïR=ü ²ŸŒS|½WéÇ£µ¼±àvûKŒÓÛYn¸·Œ[;äÇà =äêäÒôbyQ$1fƒ"2`´‹èaú‘v€CºÁ�vøƒ GO·&�©ÇÑä¬Î7¶ðÒ÷ ±AžQá9¨9KÕº�ÁÝXxÀ†Ü8o�—Z~3÷ªÞåã{fû25©å|çBRD Ù#]¿2ñ3îç[­)e‹[ò¢Þëfš—\Ï[?ü³ä€mò˜s˧;†?×Rrƒ~Ep@úP\ù-‹ˆG(úç÷?~»n×”50ø-ˆB8jZèYXlù~¢WhÝÝþª u•µÈ¾o ÍÛòyX~í¶BÒbðÈšÜ×eúN?¬ÐžÑ9ÚYÆ]`ˆÛ pq{@ѧ•&´…玔·Õ×0h&]ÛA û.L×Pl¤óè8ŒhfPvsip™ñJžÁH«y /Ì™žuÓRKÀ„�7[‹˜Ù›ÚÅv„V�x‚c=Ý™È[#G@Ö`ÏöU©Â¦V0 €Ù±*ô ÒÒ\2ßn»ÎÒ 3â ï(àŸó>„V‰uØ«é�>À>—Ñ”àÉÙÃÖrd ­íØ;à‰�ó6·}Aè~ºŸ éžõ͵tìVкÀ‹~†É�éà t˯˜hñG£­K_ùE÷É�7Õw”qÅ 0 @ÑàÕ“kÿØö×{4Œ¿>n„LÓš%òca Ö$ß­™HH1²˜ÌÅ$ŸJ‡šb8¥E ÎL¨&"'¬$?óŒ}ͽ姌ə@\x¸Ó|°Í¼éJv§†{gæ·íŒÜ. 3xìýFN×Ú%ôÚü¸HtåÇý=• �Ô”¡_úŸ–'|ØÏ–VI£Ç?o Œh§Vôh9ÓŠ±Žâ­”â‰Ä¿­Ór 4;Š�œÚÓY¯RIëל¹*¼§»Ã¾Oii„£bß]ÙJ+l–\í§wÙ„Jx:¯eQ‘¿Ëž±9Û×$m4ùTŠÐ˜© ë¡"SÑtªŒNì‘£Ú‹¿1šU!{€i…àéú‡[´ä¡t²ÚÇ (AMÀ¬‰<Žû7õ…Þð¨ÊPéL2Ð$mfeà�éûÊ®KAnÝ•€ƒ™ü†BÈt¹îÓÕ‰‡LQ Sš ÆÜ¢^|©‘¶.(ÙÙ§ÞQ KÅÖ¥^ýˆ—Hv|ƒ2Iýús|¼‰×¾e~Ø}•Üîç�_†®6(rÎmú¸“É•ã‘7Áçnƒ˜'1TÓr}¡µ^{ÃdÄ›†DažŽA•Ï8OO Äf3/JBÂrܘŤGFV1èžÐ½pV4óÊQõr§‚PÊ€†ÿ®ÓY�I™#!]Ù*Í1!�±³L¥F5ƒë�ìaÄäç²n߇Ӌ@=$@»Ëužn�ÒCšmá‡Ø¸-_]¿™ã;ïúùžêGTlbþšÛ0H&[>šwWÉv«2x9ðEƒi�vjÀì×ã¬ÔI5îÒ×µ`÷#ˆ.Wù¼Ÿvé†ýÏÌô`§?7&û‹çûÔÁbÑ)%_pÃöÎ J•&ys¡£8HþG}8µ÷±Ììï¿‹»)é/'¨eúrrùò¦{M2,ˆ–lˆÛÌì¡ùÅGd¨í ¿ü³%M?2­Ø�œ-u§™Ä¢äê~žS§Aç¿äafÝQ÷€5˜×fÛýT›Ø³ïÍ�#ޝSˆYиF�§íº*Ë:­ö®øÛýž&\´î¡XÊùÕ÷Z�“Ø$Oû”“ÿà‡ÂWL¶/ÄüdÉ]°<=¶SHyŽáêyÅ4Sª5pƒ{ ý9pcìà�­X¸~z9è™y5øëOÁE"›e•qˆu¥8ÙóÞðP}†M*L“ç «‘ õÄ×@ûˆÍÅp¨º¢'1ÿ‰ŸîÞOb7%óBwÑ�ÝÆ�¯psÐÚcŸ[A%$ÌïxJh‡âA~»ë{‡óÿ\§ë/Ölç‚Ó_+áËì², T-¥]3ŸCoÛÜÄ�׎r²ÚH†¾$::~?*®?ËåRãÏ|Ñ{ö’¾y›|ê$)(ʺpšwcs …L�™(ùÚ·žA•ƒ‚£ÞÐöþ–ÛûŒ!Ê»¨éjS¶&t�'È+FwáqžØ%¬Õz#xÚ==£•±qaìàp½4qW%°{µ³ =ŒŠ¥˜:5/J!{'š«\ËvZ/¦šõØ÷~P'‚>•W«lš€�rò¸ ?P¹ZÎÂ^cg9¸0›µ'f:ºº'Ñ€A{ƒˆ±Ù½sèRÐ@Ž’É#3®øìJúû²…‚`¬ƒ1½áâeà ³()cr ¢vÒH£ýXËÆV#‰žâ'ë,ûÌæ3Å´»Sxº|ÔµH·9%ÒœÉ�á�¶W¹«: ;uÙ3NØdUã´gG‘@,ÔÈQó’FOÒR¶¤Ë=·>øËŽrëËÅð:êg|¾Á -FC¹!d¡½›õó™¤KBRWŒ¸§èƒD�Öv¤—)×.äðgœW­’²ƒX—€ÔÕfÏçUÍ\IˆÍÂ>äûöÃ.bB•f,ãŸÖó|Íoµ¥W¨†¢ù>³žB’Þ|¼ Ðîâ¿ÇX‡Ù}�ü+Fì³Í ®)6#0Þ¹Èû•‘ù¸¶+”AgͼíŽïü &è¶ÌƵs›é+)ÙgÕ]Ù¬ˆˆØ‘Ú02Zã±f Qߤ1Êë 1§ ¶Úª—“3sÇѼ6,æòï®ýî¾X!lÀ'-Š%‰$j‚Ñßù<ýó ÿÞçëÜ^¤Psˆõ(Ídt åÜ*#E¦�h ‚¿úæp`w5�iŒ�ÜQ [ûÉÄ{/£ÞÄé Œ¹’,YXÏTÁ=_g’šˆ"‡‹7ž²übûzÎO?|#¨QÀ“æ’�#jõ¡£)Äð8ž˜|*Œ2;/_CtÚJ±!pžæ•k’L4a´Y1=Wv]¸‹¢ÈR—M�¤jZfðÙîgä“(KþÌç�{àáí'vvžHF4Ä…wÞÈPF ÂçvŒøÍoÕIÈñaìÙÁ^Âeº~ÖüÈÍ™ªm;{úLõ:ÙÁÖžÜ TdÌøa—D` s£ÿ¾>¯«ªÏ™—Õܨó �òR°Æ"ß=08dýø8Ó¬* š�ÿ}¡ïéYÅ$ü~6ÜJÙ­õrrÍÔ¶=Rr²NR°ïJºÑ¶ŸÈgE ûÁóÉJ¢«&ÓèVϵJsHq±-ÜÇ�÷þYàÇÂÖ4€ø÷vc ¢8°Éê�¼Ê€,í¿õÇÞT|�P®�•J„1;m8óFÿ Ñ÷@œŽÄnÂ'dÞ µtN½2NˆÀPþ°ÒµZZ³×z°²ÂÂ�Êçʱ ÅÛÏe6ŽJJèøsR‚S¸RäðùGÊTŠÐn�Ýa>V%¾N êéX"*à{”§ˆè¡ Â$9§ŸFnÜ%sQÍÔÀÜ ýy¼]Åíu·à¹iqÏ­–˨TLý‘°ãHH-1åW8HÌ};฻jŒkö^ŒÚ¥6¹üœÒ¥ús×€¡ÐžO[_‘µè¸ÄÂ=ÿ,ó²ÐÑŸ8näà³¶H¡Æßµ‰¹48—Ö�9ÇF³ËãNIôžô�X¤1 àHßK­”™n¯`v…^^{˜W鶺„nRîÑTÀäf±»×ò—G¨°T"ê—¸ÚE�¤Øl'BËTºRnNEXØ‘Ç&{ÏÀ.“˜´œeîŠê¨’Œš öÚrå‡ëy™áŽÇDÉ�LŰm[`³C*,X3‰Cökí¿ñØïV¹¹ÜAé��—c öR/½p H²]iD›dRò)òö³Å|"_>Ħmð+uõUŒ«&ÔEÏÒkà�ºXÝ <Ê"êNÝÅÍbê¥�ˆ:0ÅN+©°±:�õ}‚šìP‰�ï( ¯…| , ýÓrím�p¹Dõ¥è5ýˆßdˆ²vŒòÊ+]ç/¦pŒ7 H-Ûb;-_g¬®.ßäýÌ ¡œ›ˆêqr\ˆ¹üˈ¬tMMG¦}4øÓµìyjóaÖ�Rimm‘;·Â˜Äóã}¸®É±”[Q7­‚^*x½$hdžu¼±Ú^>ˆƒœ‰õ|+èg|ðóÅRÖ?†¾q®9~*3jŠÏ¤~È<Ìhì³ÿÙ­N´f<Êõøüfn—•Ý&Òu§( ‡W/üjÂlŽSDßÇÂÓ:¶ßYcäéëŸ&&ôÊt³¢„ŽëSA‹+E‰n4çûàšX“feKÚQGzžÛ€ÈYÕ)-rg¯!¯s›ß‚bt‰n"Ædpª„VsyÆR§žrÝ¿‡ç®y­w%À…~žÇÂ=Žý vy!l °×¡s>T­¡Ç¾ÝF£õÅæIÊ0;È@�µXÞlN’6L¿1ªµ[úAùdqŽSW!X{j›mzû†x“—€|~£ìjäÆ*‰»Ù²‚áã«�^G±x~ɰƒ¿¯­¯ä¥®«`XR'Qç¤KVŸ¼Ì ‹vÒ5ªÿ¯—’{À~˜™|ÑGŠ# «cö„xÿ¢okK5†Q¬+axk ÓÇ0“êØ9û(Üô|�8„“rÂ’â%бê{½$2Ö™—x¯T6{÷Ï'¡>wÂê¢ã²£:í�NŽ-ÞÍíè$jþ¸þTûu¡�õ†¦zƒ:ž¾hwœ.ÅÑ8^ad †Æ÷_ þ.ûGñ÷”úÏØõ3A¼¯‡Ç-%„n,möö$¾k‚ÑCa…?ßy0Z7¸Fú9~ùŸû55%"<_à ÄHà�Gif(«¿˜4i¹;¿²ôkR ¼D2¶;}sÅžË}‡ùÅ­v¿…l–FÇx<ôØÌÅqÁbÖ6“ˆõË®øÝˤ„eæú%;h^˜�Ìp“^]€½Ó<ß…OpÍÜj‰Ogù{ G´õäµÁDœB{Îu)±ë­/ˆ<:P™Í.éôÔŠDŸøý‰ 'i„[g' aƒO=’öøjßOIÞØ‘eÛˆ_¥"oI!ê#;œ1LQÉšŽ<èOE°Ÿ¾¿Ä ƒ¬$»ærvƘªÑ §•Þ興 lLÄw?n iMó^&`�ï d x(ÙÚ.mpv±ž$rƒ’ž¨û õ­"Ç�7Ùw~'n˜§%C‚œ'ýÀuGÐQK‰Âç9žm™Ç�±#ŠÑI mîIBÕ1Ë(Äjé E¶Kÿaï' 9¸û›v�ËlòÚ)#]F*E2²©!Ä(Ë|Äëf|Å=a�;„0ëµúVÔ]DÌ%>õb E'?PϬ¸™Öë«î…ñø"\WÄÚ$B€ŽÆå`[/z5}•Û õeòWËéå#4:öçÉoæ»cÚ›d¢¸•AD¥?¥;]¶|wX~)2kÁœ."�Ü>Z�ôM8W¾s ŽÞ™¦C¾xÚF³o>°Œn/Áq1ÝE“ý¡ˆ2%”�?µÖ &BZiü X˜"×9¶%xdE¦§·PÝ!ý®¨òBt*Rà ÔâŸZHW¨ËÁ±È Ü¿¡Ì©/¼;óüâ7î•zÜï†Xr_î’£@šÍË[ưc2¦Ì EùçÔŽº�€RLj9ó{vÁ®@7w½f�_Xæ«×  `�fþ}÷»4H–u°B5Æ È*ÈÁ!¼@T|¸]…“¼¦!‹0_ÇÓðÍ"Ï1ý¯#cí½á€*�¤?x VÃ6’¥â ²¦õVsñí× …=lÖ'çó("vTÀ‹Ðs›Hë>ÃQ»Öû(ü~š++WAzŒoÅŒ�Ηìý…W`›@ÖÌ#(†1L\®Â»X·>ý}Ú@Ÿ'�çj¥ 2™$Bt{¡äFÛ�Ad{8|ÙÞø!LóáôNRxØèôÚÈŒI)Ž[ëšlÄÝE)yŠ›…,L :nßÊ�S—J‰9vÏ/ñ  V»>A˜–lÄ�T^Ðë+§]° ¼xtØ'D?F»—#¥á¹‰CšØÖ¯1©‡ñoAaÔ\1¸|§|xÏ^€:éÏ»ªj›ôdU$'Ð?ÙM Û>p‹±¸!S°”oøÛ=†¡œ½*è ¢+m¢ë¶`JT‘žt(šà¿A«n‹ ƒ‚žF ¬fŠ�DÙ_LÁG)Ñ-@¦¾K¿¢·’"ùózè�Uk”›v4¢™,©0”’¯ó ¶µâƒ�˜ ÖáÕ@þ–`öRNV­™b¯¥S1„£Ä· Òð|3UoG}u„vÆžÃ4áÞœçÏXŠAƒ9¸ÍÙïÈu–ÒtOé P¾ý¢HjoíšE•rÏ#Ûvš.HTýñ‚zç†lÞR� äé/]áÄvÌΕ½ˆi/°HúuOÞÀ†¥j•aüSµ¹èŽúëÜêW®�¡lŶ…ã²è•F¡iägúcÀý•™�$*x]ž͘¾f=rFÄ÷ÞoºþT†¿�Et3„ †î²Ø1á‹ÐV4Ž“„ €%ŠIm&ö›"©ífó­Ó¢n?�Oí/¾ZßÔòH=Xìñf[Gd¿7µÆn§Ë*“‘M*ñãs×¶çE÷”ÑÐ6§ÒÞ;Œ|[p$[�d}ûþ’šF¬IQ3kÑZ�ìºhÜè9íöª³9L×éy�ï­ŒCzVùùŽ Wìøùcþ›½ø�”rqH-I™2mk�é4…èÝZ¢×hª¬Ã«û£¾ GY4ajò*?u'}©2«¸Ö­M_¼ìØo7ÁѬú«GÞQAƒ<Ì9cåI8ÊMF „Jáö‘î‡P_�¡ò؃1÷èßòVsÙÈÜ-EèõC"®,¹\rT%¥„"A"�»6ÆûṼåɲS›:}ÓÑÕš€Â3‰º�)«ØR´Ú™b~žL¢©Vâu¿Ñ8…ë¿ö¡yn¿Jǹva™ŸÝì‡|ë‡QÀ¿OÔĈƒüRyCGä¸öxÒŸ låf_ñv¬“ã“e!ñbI©_�ö Çp»­vÚç…Ù®Få7˜íš‚m[þ¤l•ìRí+ùY²"~Ép'ŸÈ˜Õ,–([ÛÜU̇×+¨sí%ýÔß#·�µ…9ð“ F&¾ ×4\ðh³ðAyïkà÷eÐUo¢h�Vã“ZŒ'éÈ/…‹¯„‚ýýÑ\|E1 ¬P™Ý(ç)…z,ÎßV¥�*à UA¢k.W%H0ðé:'1«P3¼÷Gɰ�û@§¤éŒ fêh?«æ �¶\A-Ä»ƒæÃ«5YÈéE×ÑÏKA¹±çÛà²ÖŸôצ™,¢Ï¦D™§®{–ä‡ýJâÂæ=`¡À¤/KöŸÕÁdÃ’SɧŸ®p�Ù¿®tÔ¹ßaÉjIHy- Ú_zUä°óÚô·Å¶2:3%¸Î¼ÜL7å•l°žIo/i¯6�¨KÄ¡ƒ8h—ðÎÝ¡®ª ÎU¦©Ò{©c·¥€1á%makÑübò¿]©¬¶Y¯Î'ÿðïÖkè,®³Wt>Á:Ñ:ÎÊdK@(›H÷á;)ï/¯6MzÙ¥Yz?îÊÆÞY:Q+°‰þxc7BÄ“ù¼·¨ÌWƘÂdÕoI# kÜi˜Àí?¨µ‰°n‰‚ Xé#Úh(0rq¸ÍЪ̞MUæì„À(±–cÇâ§‹å§,?v{ÿàÌ`q*0éL$šØ¬N› 2BNÛR `Ê|Wkf, ü©Àiu´tý‹tÂÁt€yÿXÀHp0ˆvÌK8E4ŠLJ¯þrÊ•2�+… áj±@'p ŒRâð½¶ U%ÇÎЊ㲸†aˆdeÿØØOÖ�œëÚÙßc¢]iÏ®P|N¢�+®~C¨§'‹¸NÕŠôHLÄù¦£Õºé!ðÉžÓ§+DIg³ûx¼6þÂÿÜró Î,WÆìm/8>Ðÿ›ì,]Ræo¨ã]]oª˜^�bÖžtI}˜ÈY« :RW.¦Ãš>c“nñ=b´å{7ZìsôÑ{1¯_!ˤ[ ¬Åzß¡b%“òI\å:?×{övÍ0ýyWgiÕ|üâg/yþ ÒŠ}kauoÌ?]×8D¿½È½Ê‘b.Znº+%\´hwIš’êƒ+¨²/,ÑúèYÚHUnîpœ)vBØP¤?ø”ÖšÖ•ý™ÚIžLÉJð;Kž9Ž_‘7y»�…>x·¤ß¼ ˆ '‡É}â½³/²L[`òçWºG…O y(³LHx¬®äÔÉÖÝqÀüzÐbÂôÀý�6dis#E_§jÎ9M%�dÉ©_�J_n¾–õ|¸‹"Éè½?o¢KÎrüü.�ñ ­± R›(0Æ­„¹ÁÓÖŽpxDÈò›&7€‚[ŸÚÙ ê4˲ªä½žÏs–‚ \7+8¼Ó€jsT{ò�3–78Cr?ï�SU#YAœ‹@C>�ôt¬RŠêð•ÌKE”»åaÄ›œU»‰ï L.*?1ÞG±-â÷Å7<½JeJ± òyDÅsÖkЦ´¬ž·zƒ}ù>è÷*�ßB·[ê‡Zì�ôÁy+]ùƒÕ¿ê:PÂâÍ AKLXhýøwظ˜ÈÁ¹˜„ò¬”ßN†ßw)D“àV/¿èzîã>Uá \/…=[~·Œ‘¯u±c{ÑR�y½C«*7c:ïÂ�UwQo^™3)¼"¦*îØòY"[Hîéð°Œ:·$†Yz‚‰+gœá¢�ä¬l¹¶^uüXÿ)JïÍ}¢2L¢…ûCiö®ìì[\é¾G°Íú!)otyQ¬h&“¢j�ÂÖWÞo܈%BßÒ¥Ø]rÙ�…gœ‡(éç›}ýuë‘isÀ¥Ý¦v—*R‚ÎVN-ó+ßo³ü»½t —ÓÎñš;`"j¬aƒw|ÙlwJeH_;z°ØíÀÅö=¥µ„%f‡»ƒ>#ªt.tKêŠ]va`¦dì)V]qÑL“F‘c¢ÌG%ÞØüÝ•ÊBÌÏ>›'Ô*›hFt¦\~*7eqa‡¦õáSFí(:]O÷Vó™3sôœø„{U¿-­òüÚQ½@:"ß™­›{OD‹r (ÑîŽ0Í8õT÷ÐØ¡[—…ÒܦϭñëñT¥®ýÝoÉÆ£±gip]¯kk:X³‰o³lá’Ò°âQHD c™\*Éè«®jÄÈÙv=�¶Ã4J*ò8òçîóoò‡é5¸Ö\{1Þ8(TiåhFœ§„'—¿`¼& a”,ëqK<²O�|^ì–‡­Pàe,H;dõPïËå�t®²-k2Š(Òt¦{èMyhÚLr=ÍKôGç^/Ù|ˆ“†…lY¸,øGþ0 ŠÎ{H ç1:šÌ(2DÓÊ »Z7/–:�¢­Îó£6ÙÆ«èÎIÝ"A׿Ï~Å­š |¯š²m«Þ߆«C@¦mþÊJ†Ý�ï¸Õ#ëÖ¹[Œd!‚|­±”·¦WÜЄü™|ÂjBô-cC8¢SO’# N^š�²oö ¨o´Ýè`€€þ¤¬ž3 [wKF“E�ÄO¿BÍ‚¼ÈÂ/Ë�î-‡Ú;3€”`Ëz´qÈÅž#5«¯Ûó^Útýzwnê©óXÁIyŒmLÇ’H{~Š'/E-Û^]<ô–YùP›½, xeøeËMåI‚oS.ë€!òhvôÆ»º;^ä ;[cVƒ;ï¡ ø?»Ø©Z ºû4)=n«ŽÍˆÀ>ùGJùë0Ðu†'÷þ0Ê7‹[Ë4‚- ­�`_V(¦©¦=迌ˆöô§½ò{æag§n©P†—x—ÏZ�Õzȧ˜µG£ñ«!4‰áƒoõ]|42^Ë:)Ì+ƒúKbyx:è —ÈxûäŽ –Ž*f­N—Ý%gй˜ÁŽh^{ÓQYÛ>[- D±ÝÎõQÛûÙØKuj¾‡'د‘whÈÉ탎<³,¤¢§¼Œ>a¾�§>þî× }¾NÑâ-û0}gzà‹Ôš®T‹£6hwry�ñY)¬ŽýG~ªÙq®¤6P¬mgŸXõ}3"­?i±ù}¹˜µÆ…À¼¦˜v¢ÊÞV³©ÜïU_ž¯|,¼Ñ³)·jóÕ�ìÑg¦o+)”kvóú‰B·½®Úë=Ç/õWÐòpz&Kƒ…‚lˆ})ÇF‡u2J,D4Æ·±h®ŸµGß1¸#Þ„šÜ² Ù– P4S\úg¤ò‚Á¿«(ûÐïn.™ J5ÎÙƒà\ŠƒfÚEòaU“ Ú>rñ1sÅ¡WËn%1'ý^F+³ bH7ãÚ¶Ýñ•gÁ¢à:妊óK‘˲ Wž‰ãvÜãä :ÇcEvÅ4Ífu¹l¢ÒÒ÷+Ê’ó…à¥\À9°M é?‘1àΚõá–�u±„ðõ\lšê¹°€ >a†­Qo�¥w€-¶Í0Ö]í3-³…'Ø\ög&”6€Ÿ˜z¹œˆS( ®}×]ƒ†qÕðˆP¾ù¥ÙwR¾§oÁa…s’´°Ê™?ó’ð½&x?¥Ý\øÔ$£±©q&µvU)¡ô4+ØÎ°Cø é´D€�ú‡9‚™uQ¢ Ûø„ö©�¢á> dÛûô .ø³W, ïÀ™'wÎXçõd³`õTÌE¶žÓ`àqàåPê xf» Û÷l;�M¾ìÀµMÑùîá ã0XÏÙ¸ Ÿ<ý ^ üVLå<……l‚<÷ù-~~�÷73ïë+H35%ŽÂSãF3Qˆ¤Òª îN�’+)fÒ}ÞocØ-ñYò`Ìl<p?à�\àU;!d]¤-Å;Ìy\*F#€TOŽÂê ûiêÊW³{˜,L�ÃÄûz§ß¬H˜�AÃäÙ› ÑW€8å–º ¯x˜MŸ“j‰ê¢‚ñ=ò&œvŽ‚ž÷©k£¡ðÕÔÍ c™P2ÿüGž¬‘Ë%]œ!/ # äΪ„’¯5Tu“«ÙƒQJ§çf\‹8½×šÍ•68ª¹°&‘�(üŸ5ªa“PNlªçW.úêfVh^ýpÕAµÐæ®Teþ@‰)°ãéÏ_$�íºÅ} âô¢®Fअ»ß‹óÌ*ãš4G”M®ü¼lt@¢Ç·Ï“è?Ë¢²NŽ-Rï0¼Ÿ—R')fÙ½¿FñÓ#LØnçëH¸€gàsã�›*¢-¯ùmg³ÄÞ‘GŠˆûš8ä ¬çœP.»pÐÒ‡4O)Y¸nfH4%FÂË¿p:Êßo?0 Ø?¬]Îò�ëÞÆÑýâLÍó%¥¾4÷Ýì°Ì‰`|}ZWZôê¹]Á‡ë¤Æ@Å÷HC* µ—×#MH ‰—y 6³éúÉ—ØH±‚·<â±&Eq/Ü´L˜®Ù« ø¹øËú¢‹aÄYøT ‚¼’’º›ƒ;U¬TßB[8EW;f$`BíK�óB´Sò­Ã<=rE_\àI3Ü$ž0ó>ûìu–Æïön$ÙÐØ‚rÁÍftwT±ûêõï´ùý {¯ E¿´xEN¤1, C™Ïqw�"Ú^ø]ê,듺4`5_\Š%‹W‚ô(óTòO+ß','%‹Vy·;¡< ð ܈áojÍk+Ý÷k2†L¿!u�R1�ržNféjÁHóüûã§Nɾ“Euâýý>mÒR#H±Ç\W¼ÏÃD~j-E/_b–¯ãÚï®JºQ½ú.ƒÈï8ûÉVŒë­1*GêQH#ÜnJØì™¶¯ë¤ägV›fgµýˆj-2ÀºO$¼l2\ØS¾îu¬´«Cø›©w_eStm(pá –�Q�©—Ù°ƒ4!IÞ³ Ÿ ^�ˆÑMÀ!5°†kÅ€´Z\õE@¡W¾¥ÜACÒÃ*ðÉfæFïN˜�ÀŸ×'ò>²·XPÄoeΚ¶Ãüž“Þ–Üÿ¯�6cR!Âüün2Ÿá*\UòÁˆ÷ [RÖüü¤”÷%«þö�EÊ糬ŠÜ�QèØL�l<ÏêåMð˜xñ†TøR…‡Ã[x°:³Á¡Q½s�ΣÐÎ} 2΂Ñ>l~Ýåã¤1@¸´*K�z°wêSׂÂÇ•rªHS5~…LÊ…Z=þ C?ús }†ÌiižŸ@3D§ëá@È4`Þ:ñ¤ý�±7£™»ÑKU�¹ 2MÊàf¡5#­¤xâºÙz¸±ù!YΗIàŒdvB‹±¶wWRâ$K}ÒNÞo4ƒ¿¡»xe�2÷º„!3 :Ô{"Ix…ÁÔ€ÍtÜY[~Åô ËïJ×RÛ¢îëR·�q鯈A6ö;Z¿†^Ì‚&œ-c•ÒÕÉA;§ÖCì[ -ÃMÀÀöºŒ�¹ÚÓóîÈøHçù¨£øä¸f»è3 Õ´>uw\PcUO¸ýÖýó SḠÔÖš‰ÇñÁé¯fŒ0¾Ü‹5‹&¥È.'äNö<΃Ïå²0ºãG¾Õ\˜±W390‰ã\cŸ1ïKÉñƒÒK0‘K‘>‚ù©×k|Ÿ�üE>Ô.H„MÿV[-K¼T^‹Z·†3Iýø÷¥Z�yÙe¹X¥Œöê÷4¶ú.ý¾®ñk`ÄGMª¯H‰ ŠÇW*Ò‚ÉÐÐÚ@«‰ùÆÛ<Ó?^‘9‚„Ca¡Ú_o’÷~_²ypýv'Ó:®‰pÑ®1C§æ‚’�Qéw£sï°u¶Ÿ@j4~¹ÝŒ‹Ö<ùÊ{VŠí°býîÑî<2Öú{T¤ÌÄSób:ÄxR‘fpe(&Q°õ~ïš0'ð£ç¼JÀ¢Dba i�Nz?¬ó! N¤šañ9Õ7†º~cË/ý¢r%¸¢æÍºÎ¤'Ã)t0̽�jaB–\,¦ý�?k¹)Â8£ÚJ9ú»°ÅŽ@Güè–ÏŸ:ZEÁ- Ó†ï†Ùóý0þ¿¨p iNç,WQ’€—Ó0~EË-;'_ªÿ'!m;w ¥ôe‚®$Áz·‹J¡b6ðö6`•êjô ¸ôm!ÉL‘zp–ËÅ„îM±½F�vù PH.Q£á�qðo>vjjÈ ú¶ñ3‚ ÆQëÈ÷Ü´%Á¢½ÅÏ$¦Òá~²¦5mfvTÎÂóW;¦aØIâN/ŽÍ.<Þ†C“êWd¿-Œ‹aßÏh’¹S4­†|&ä°¹CYó]¡ºv5&Z\ŸÎN­¥UÊ•xþF+N«ìjÜbzÕ ö´»Ý‡¦tà}Šrœæª@ 3þ#„ÖvŶá¬sŠPóvú‚™º;…áŽ×kßNÂÿ�}ÇnÝX'¥ÿmo.û˜ÔÛœ�¹‘[S¶ÏËhÈßÚ[’÷ŠûkÍël z3À¹ º‹ï Bî®Ç8šñ†mãYTÿùÑ£Ò¶d Þð-‰¾èC‰»”@,xÞÄŸs:t·´û’�‹O ¢“–Eø»— ¬¦Åk�Ál@+YËn.ð@�YÂBƒéòÉ’ˆam¿� Þá éI)Ô5Þ’:‰ÎÚ}Š“¥RT\p©ÆÜ³ÇEõšP³ó°±7oX„ ÔÇ@-5rpIc•/ˆíî„áªl¾�¶ŽSðî2ENãÞÎÌ÷˜›ûMãƒqް½QŸ–mŸö�«ßn)$å=$×ïM÷>KÖzLþû÷ê°ihIê÷‹>þð\©!Þ’²[ ^•>ÂÝ�ü'ÈEîMZ^[L:µo"SÇ¢kùC#œr­xñ戊]¥bS‚°&¼ ét†ÙÃDz¿Øzô¨Ý©H;Áï°:eâ͹{Ÿ0¼œÉ`�Õéê_“Úõؾú––rʲÏsv3ºNçÉO#³ží<[©rb0�FA`½¹å3%›žËÉÒ~NDˆXeÒ…ïn<Ö¥ÌT M8Á�NF铯8ƒ”ÞœlØ>¿)ÕÄkëb¹3Ð#^\ÉM-‡nS ˆÛÔìÜKŸØ«*÷¯µnµ~ztŽ�ë¶UÚÙ`Šó!¾VÖód²Ðd�5�¸k¿"’6M÷ÍCï…ʦµ¼ÑÁ6?ꊿóè+¦òfKŒtKܘ="�q…j»›ÍS¼ÓÇFXìàÅ=‡“AÐ\º�$W¹¿îâ½*ÂQoçä´¯œâÞ)�ˆG•SN¯+¥ãgðò6àÍ}2Rj_ñftÕý5òÐþd*u¯ >¾ª±î•‡;hõñ–ž©exBÚ¾ÕY)‡9Âxs<Œ5/Oaþ4Œ©Ç…ÛlÒª½³!Ÿ¾¶3ÓôG¡©�§²ôRAshèßuâoR/~ hž6ÀƒAƒ�, VðcV�"œ\&á L¿j¬£€ù=#º2mwû¶>MîYÌ6²€`ìë>½ ¨Úìp:zrOg…�;î$\ø‹xà"bf X‘’†ãl·Ý‡º!¸J7óc¦+áhwñØ–ÅqŠ»;’²æt¿­BŽ)¨a ÷"Ü«­Ë£q}bmÕžùÀßš½,k‡"¼§&ú>'sÒ #6.%cˆ0à`­«?êùÜ«6†3™=„?¾µÏ4t¬ÿr$ôÁ%¸sjæx~E¿- ¤Vt±Ãăѱ7ˆ!`ª%ðjq]*’€MF_a*`Š6f `T�fü²=%Œ ç3å4èìYª‹ÝaØÁÁa�‚áÙÃ1ˆ*$ÈÉñõqˆ#2¡V²Ö%�AÏ÷ÙªÎñ»s“Èè/áF*ÒH­HЀÌÞË­î?™?ã ¹ãç;¯ [-)‹´´�¿·3<ňýX*øv‘¹XY�wT‰5«EýgÕó˜¨,Š}eíŠ}4ë;Å>Àz~õ*›ö-oÄh÷öÐÍ?kWoÃ"\Û‹>ok··öºOîç±üˆ–´ xJ_²‹!äÄ&¶ H�Ï‚4ƒâ°¡Êc?PÑèׇ€ˆ¬¶ÙÆe)Ú;¤í~Óa1þ(~_>¦¦u x%.X ÚéeèÀà¾)}à6µàb‘ñÔ~掄ÿ²oé4áGûr?¥ÖQâšôÏ\V|š0:%ùÞà[ë6Y»£ÚÅ Ë�ýžwÌ ±OXC-œü-ºôÈÎ\¦Ï’i�¼h§ñY«4Ÿâ�'£yÉU޽æfB�þ·¡þ„o•k^(_÷ßj _jBUM^8­2˜�Æ$j¤$ã?Kw´±¿Œ€Ö·vv|®~n,Á›*r—‰–m@&KƒWn¡¼Ú¥ÝN=Ÿ%� ¤Æ ën­\¿ý<ÖóXº•dùhþYõøÊà2¥F@™¥Í›ž>]§(f…Ã&ä„-àí©÷kV¶ö"¾F&5àà3n)SfKât8lOšm.­[.`ögËNä/2�»¢•G¡ê‹Tü`[7PX€{Ò°—}ÿ¦#ËåÂZEÚR:Ã÷2’�¢õÓXýêDP�;´Ó«¾óR?Ÿ¥ïÒ€áìîŽÁæÅó�Ô``á"ûòв‹ gÀ8õØ î\Þ• ‹ÂáVï(ùe›Ñ�ÎT˜…´çܳr]£xwJ<ÚJÝoå9&ú÷×úa_¸�¡¶í|Ÿ.ï:�FH†Äg ö²ß5Ε5ÍFÏì]?,'̉ê2vHͶŸ›Ç‚i¥Ø;¥�Œ”¶ŸÎRe©_”½]p‹&œaÀù£AË'u ÿ{T§ÒqÞ²fà(p)g1î"ƒ/Ò³Ë,«@‡ so± zT8æÐS5ï<¦ôvéçÔ¸jø®¥?ï“Ô`Äv¸ÀØ’iò9z3QI 8PˆþÂFëšp\CYb·�U¬’ ÐÒÿ`?=?V½Ðú§‡ÁSGnR°19˜³’P_· MžÂí´Mí�cú�ÌÚ¦Ô™Êù÷覞A4ýã ÃèD5WI=‘?kÓЉ-w¼Nf¼áúÖÒ†D»xßH ¼É«+Áò‡ÐJþêŽÜ~4£~  öþbc)cŸÈ›\B":MeòÅo‰ôöÓÜŸüíœ ÄO31u‡v ÔŠï9�¾´©¢”}W>|¿LÙ‡k%>xt;;5-©6"ÝÁ2NÆÝåsfëzú& š�Ôâº)Tt—7Ž Isvܳ-¼ˆ½ Ç[›`qPjý¼Ë„AÞ�YcË¥>*”‚®vš©ù 0<©Ø±¼ ½SA¶r+¡ã©ï˜¢ÁfZCü£`ý>Ššc!Û‡&>·Á wÚÜ­ÉÐ)VGîh@‘™°ïx ›'ZÁÂ�µ©‘˜Ç!®é‡œÖ:åúEèùs᎓­ ¼00VÎÌm2u3�M¿Q¥:©Çz*û[T9מ£¼ føý2®âÙr(zÒkx®Ï–ÑK^Qškéç¼ÝvfäNO»¸�4µëj PNŽáé§Õ;›;‹O#ëÅŸ0¼ºÈê6‹ÔeÃûÈ%••Â…ÞJV$ÝwxsJGפnýUßýïKî(£Éw¸,žéî‚Ðr§7�y´CKW@ÛN-Ø` h£2Bœd,–ÛSÿ-Ʋ—Kµ¨í9DÊfæwl©RX+áãÌ«îûàr äœÜ¶ÃwN´ŒÂ � Ö)�º~ôÒßC‡Ç5à Õ­žuÙ74u&Iž~8°›Bðø÷†k¸,M-1Å5[6Ú§Ž½Ë8~€üÔºšð� Å”y­еÑÕ°üÂòIªãÆ*n³Ub>˜žL‘¤Šg'Š-+‡eT6³éýE@;š û‚}0æÀç›2òê¯ Ï_š üHÓdã‹©Svã@…½$“Š€)cù:]•ÚÈ[±¯j*ºÒõʰÿ”t´ 9ãd».nv:¡&ÿÿ@ë¿EþT$¨‰ý¹q½¼�Cœ…gw§Tç’7âÞÅËicE¥=ñ=T¿Sý)6Ðhñ»mÖÐNT‰ÎÀo/„†�^ ¹EJR›!½*¬tɆÆïœÙí{£î{äi£ºÿ$/ÑsÀ¨xôñeqä$p•ßÅ ’$æë]¯@3< zM`µ`ˆÅÎk´ªWØÍcãõ& tèK^’ä÷Ê_·;Ú|üþXžj-./@Ü«ëœÃ±‹;õ¢‘‘Ú‡æ­�-Äš²3@ZÜn¿@å_ÿ©¸œ§‰Ç²X}"]Z–£êqê¡#Å=1¼Ö÷³îKAEšÕît?lNvpŽæ�Õ™P9™�ãvß©eå¼ß¼ª^àÈí‘×ÕÉøÍCq÷ùQñ™7^Õ»z‚y´17b°º£±>sRn’#áCÕjYoΕ#+CˆµxnzÍäÙãU=â06f '¨[‘O°à" áSÏO³§ßŒG¨¯¡£?š=Œ�æ�^ØÕÊ��ÞÂ*QÜÛ�T+à˜t†î­†p�­_q"X¸¡¹ª¿Ïñݵ'²MDít âkmj…qèeM¦ºÞ7ÀÿË"7Ù*}.qÂ`×–­e™Ý�¾‚Y†Ð-Ù^…Ú3›•ôû˜lû½ýÜ; j¦‡€–ƒµpË5Çò[D»È€O¯óm Sdü.khoºòfz†ã{º»�oœ™,ê“]‰r\Ö#Ô>Ôîz·„ßù›ß}-®¹oÚeOŒ‰ga9'b„β:c”O^©ýkÖ_ÜÔýE K3Ñm¶³XãÙÆ©ýõ–pô„a¥;ÂâžÐÿ¶àUhše.=TIÕñ™n›¶g$áñ]·Ž\äÀ9Fˆ_(�è³Oƒ ÜÏ>p¯«œH…]q0�5VÛº­;Š…Ž` „†´hOJ0Á`0¾‡ÙD9Ý»1ÝIVÒ?i1çy¥·ÿóÉuÿ�Pά݀څ j‚…_(µ;W‘‹f"³€ _}ÕSn0Èt‰ÛÔòÒhTið|•š:šÐöBÜ\ õœSøÌ›÷f¬Ìh}·ô™}ª'&Ø$î¹ÏÁ€§�`j{6�=�¨¯tu4°£]¢Ahç]Dð»M™M°ÛS =§ÌÂ%�.sf½ýÀ€µmŒàºÓ²Qp½cbZ�S�ýFÛÛžxàå Y«»Ô7ö0¸€GMiFo…õ|g‹¿ì€íÚ…¨Õ,+àäÑ>{<4›žƒOÝÕ|åxçr7 ‰ö[äIë„¢¿²2Lü¥�åsŒDlQôb¸Yñ¥ˆcç§Öî!yYÇže¤Ë·84Tž»Rw£ NÇuÆÝAÒ¶®á‚\�Ø�ôw®Œ%rü3‚xi[Ë7³Ô¾Oé�c:‰7 y ¼St Lc�Á¹œðDY[Õ¨  õ±Ç×89£¹ýÕ��Ù9º¯çY–·–ÞkW8ËÝòräS]b7ìÇ›»ÛfÎCfÏ#†Æ�w»�«Ÿ™�P³\ñç(» t|€à 'FH¶ÒîZ“o0:m-&R“ilc§±r·ãôwhã%¾¥úˆ]Ÿcœ3Å-Œ u×婪N²OÖñ;¥ ‹‚â,->5Ï�9‘]Òñ¢éž14+zG'�²hL6ÁH�{ÔYˆ¡£V'>nªË`KÊ]ò(@±¿jîhÀ<^{í—ôCæ»UÕ{ƃ”Iak$àÛ6¿ÿ±A8³*è®§yŒXÏ2zzI³‚ 0F4ð`€ÍX¢–oº—5$Sµ¡ '†kijbYügf8>T-÷Iƒ½DW3 -S+ºÜ¤�4_ån¡V./XŸ2afS ¨™•õî�JöX%÷%íq„�.Þã"/ #¨T_CÊê?ã ÉÔé�ÉjYŒ©5ÙôŒ2³ôWÝw¹¡Ï•wÀx‰À µ[Ò«‡¢¡svñã®Æ›’w _¹F3Èê’–SÌe¯u†8þc™mÕkZH?­²C=H'4ëɘÜ`ÕëöÕ·¿uÂñn¥„Ï-K,H×.þì°¿¬@f @¬©i]ÚjR¤Þ5jîÔc¼ Ð}7`/ô·§Ü±Ü‹³táÞÐÓ#éÕæ{¢ãš ÈøbÃ(àÌ�MhNÛA¨AyÑ‘>M‚' G“~×ðãšZ"?d ¡Hý¦‚•©¥õ®8zpÇŠOmÓ ÂE¥Ü¡�:r£Î?ß‚¼IÛÚRÿüE½ØÐô]3ÚŸz#Ãÿ#ŠÙ…‡øV–¯ -�Æ©Çð´Þž’t;Ö¶{h÷¥©S Ot|·Ý�5æ:K×)øžGÛ­º_áÜ÷ÛŠé+«Rèaöuí}<{(£©é˜œÐAšN|Ô^jFÂ/ªûsãÇ&YÆR]ò4ôwN¥ó˶ØåFË‚ûÊU2Óh„$�Àc )Gûä€8ö€]®ÙN†·õp•ˆ�òÌéÎø‹âmÉóÕÉÒžöc–EUž_W†¬H[GßAts®ßjDâ™ë<œ1íàëlÜ倄d·{¬* ¦° ;ÄPL.l_ço=ï^ÔhæÍ±§•ñgÑŃ˜ŸðñŠƒHÖÒJ ¥ª÷¸ö‡gÉÒ”´qÍ%MÿÌe »Ú¬Y#— :€«ÞM ,TÆm3̉½pÝAô5n›Ìm6SØA¡Û"f,ŒÇÍ027Ò¢Ò£—">7ÏÏ/Û“wO�À0‰fÑK”Ý3ð+S8±L“÷Ô $¾4¢€Z¼ÜÉ-ªhí¼mx’æt¢4ÿ‹1³�¢¶ 3”O;oQétøj%�üº×ö ’HþMOI—@ uÆÐE$ÍÄßÙUºæÐ½"ðZ<…õU;<1W¦ÿüç¸ww]%:�Üþ=k¼’€GÔâêklØ�Ø€mú3°ÃÚ>!ÑÔ¹p('ðþímÉ�X½qêÍIÆ&Xcû=6¬H¿i;½½[_nUŽLó¯ñ0˜Jõùý/xï®DZ ò–w»øëÌhñ6.KŒ3ºxß ØíÖSƒÓá>¿ç¬€ñ"_ þ^ ¯œœ%ò£CÔð€Æòâ$õíª7úHÆ,J b9¶è–+í—#Öü Ja /`ÿo mêøk3ó‰/Šm‡*pÞØ‹àPý ?òÞ |É׸vÕ´9tŒ:SXÚ² ß5ó^¾uøüR5»|íŽ"bº£Þh ~Çgƒn’&ÉòxF¹1¸^‹=\‰E¨ª›I #OwÎ00ãµI4¥à�WvCIá;_·dëRm@‡¸ A—nÞæô?·�=óQµ–zŠŽ7‘Óe»Ý.§—³$¢8ƒ:ˆ\Îà@Ú( Óñ‡_”,Ñðe‰ï�ÑÓ®Þ:üš2†¶ç ú‰Œ¶²‰÷'çGBÓ[0¸g‘›}ç)sýBš½Á�„zù[ó¢}C, Ö�Zô~?Ï$«'ér UsEî7 &«5çr<áä…aцÌú;[ÇøCìÄW[óHSæÊZP•榗DÈiïRßÕ½_¨&®G­ƒ',ònÓ͹-`9¸ú�°Þ:Ù�$ìÄœë;´ÈðÊŒTÀv3ûq‘JmÄ•¬¶¶l®ÉÇÿÜAŒ#þP¤r+�¤¦­Â/oCvP¶³Žó¡Ý#¨1ïÂç±SÙ¸‚½ò‹íæ\�Ó<Í Ô¬ÔÁÐŽ›¬Twâa‡—ýe? -+x²Vèe/y¸ Š#Ë6C4Öÿ©[€câÙžE«÷:Ò½èè o)³>Ÿåa‹ï$•¾m�xÖ4Z$½uHÙ ³rÜ¿Æñ¤¨]ÓZ skÊʦÂj¨¸.™Iíðö)0˜ d98½t³)f˜G0N‚øTÓ˜ž1ƒ ¾�i7°v'Üx¶.•3ÎçÙ£¶Æ”'6©09ƒVq`¶Ø/7r g„ ’³ÏëÎçèKæPG¦bÁ`ÔD½ 0¬)}Š+@bYIeX¬~%…–B(ÊÒ(pÛ ¼¨QÞ~UgÅI“€­ødGߣ±EÈÂõ©ôщ=YP-ÃQ2]ˬ„~æüílx 8*£ºgˆë¬ÄÜ{¦ø�Äó½=k%ÿ+ÛrsG5ENå“¥óÀIowŒˆaâ)Ù�×lƒ-Aa¯Lýõ§[u—2°Êqó‡�5�¿Õm2ßÍ »ª ÍïI§…äUxLK{ˆî\žàÉ$Tµ©†‚QC�h ½;L°öÈëÊ›’éç%±cB%Å‘]ï•ì ¨å…LµÕV9D„.fOdû¡"³Ÿ{9‚˜8,Ú·szÀR½‹µÃ·�©tÉêc !ËÈÑÙ¶kJ_ñ ·l69mLuÀ“>JÿŸÐxNúŽ�Ãh¨Ç[|–ð„,o®b–;Oç7—%;Z[”¢eQv )@hSyd•Þ°Ü';W>ØK‹´`êDžr&WtöÚ™¢ÛôàfÏl€ bX Ÿ¡Í"oðŃŠE  ä¹T£Ì:ë(ußþ£ž£_CÕø˜5æÒѼò#óÿÂ< E´<à A¿BoOJ¾s®ó\Ž­­¯ßœVQ÷ IÒô—}v ¬ú�‹H« –ÿ»Ê_‘}½u”Q�™� mE¢íe‡ÔØDVh˜“Àe Ã0¤J¼¬'îÈ ÈÉnu×$ûÔcËdds0ÆÑŒ­pDiÙ��ÐKÏ�Ço©.íycaµUÀ)2]+y×/Ò‡DÅàhšþÁ?Ø÷HĬ“,»gK맇Ñk£JÖ?µÏ"ªÎ’è$Ì�ÙEgî$1çh¤!ºÍüvwÛæäŠÀ”P¬½D7—`#gÎÑŽƒÁø¾Ÿ¦ =?‡E¹À�ˆ#Q…ŠO0{xòC³5µ²˜' ™± Ù§³>'åBðG6`@MðkB@êò܃>ö�j6Þ›ÚxO¯~9™[÷¯Ê™o8¨>`ÞÔë_Ú¨'£]N^ ³‹x/i�‘%²!>ÓHZÍÄ=÷qd”¿6£Ý}2EÉ è<®±jì½î`Ó~ó·Tºl(Fb2ÝQ½éèUIêüF7ÙÎù4OYÙ*0çžaä•ZÝc}ÎÃ0È1çšRâDÉ k/[Eÿl½ù»")üjð¾aÎ�D�±f×gæQ–NC˜Žj@ا. *0b¸Œ”¾ª&1(>y�êÚ-�±‚Ýa:^nÁLÈäs7ŽûvÌÌFàµd¾é*§ lŒÿùå²7oS :Y Ô°éJß5ã3Œ*¬æó¯iÒáÈž¶3ꈦï"¯${®$μG½=<§Ô¨ƒ|ÍãæòÂnéųÓã´´ÏTô·¼ðßL¯-ÜXŸ*C "ÃÿÔ¦[ø!2Râ߈xUTݪ«öÛ9Õl™ÖÙãÜÊâó –­(W”®ì�chÀŠ8)„`¡(Y‚ ÷¢PïyÚ¦#´Ïè�¹=z�8 ’ásžG”ßâÙš¤Åùì�p,UÈã m¡é}ßåˆ ZZ—¾VQÞ]ßë’«~̽•#rgÌJ-R‰ÌÄ…šÆ,è#K#¤âÜ—­²\ù‚$‹BkI›ñ¼i/ä-k%»­ÑÂb¶mPJœä¨Yä”}u|3¨š±FsÓqùx·[iñfõ H„¬2H¯Zð’Ôl~(r&y˜5ë#>zIÌÓÁ´ùù�Vpâ 8D¸D$²ÁÓ�ÉqÓ\ >8Æþºñ/˜ÿ˜¿Œ¶Ûa� ø|ôñ#�ð¿dK/™_ÓTFë¸T_Æôfd›(�D”An=ñÒø‰¾Ç_lY!*`/ÑXÈ©ë]Ç`[êS�»‹pçÄwÚãÝɤF¥1Þt:†óá—*„pŽT›ŠÛ@5þ­£|Ñ‘xW¿…%|B¦í°)¹Ñú?t%ö;cmß(üé”ï¥.SY*@êt�Ä ÝS‚y<þ>G¼íÁ^Æì%ÄŽ*qÊŒ´ëT{c9j3>`1iÁ‘#·$³SÌ»ÔÁ>ì“ÜiR‘¡* —ð„ Ï;0šS…;/=ö”Cå�ù°væš Àݤ†Ñ¥µ!à‰‰…´]çO¨×_Rx×2®+Îò¡„¼Lï*Š^ ‘‘"lF)×|ä˜ mÅ$>nPåžBÿútT;Õ¥AäGo˜d×ÐÔ�Ä?¡î¨ y<°;»‹¨i2�xuNß–¯èœó2ÿ¥lìp=B´ÁMÛ3Õã5nqþ>–³¡‡°ãUº/ãÃô›K’ƒ»ü >x£»ƼšHºÖâ�¸ÔâåŸ×Ç6Á­m¥dªƒ„†iåú#ÅSqÙ¼O5œ Gj¢ÅO> 3õ l€ŒˆO8`ò ¿±ü’ù “EãÆs´i½–`þÄ¥·‰γohÍ–C%�Ä.é{ÜEäæ% ‰dŸø„¡‚ޝò¾~¨]èô;]):=‡‰¬–ÍæÅø±K•#â‘=¼‰¢81!Êù½»»jYñæ¿kúÌ#¡�žˆ“vÒkâ¨;™òjE=JÓY¥Ž€èSz…¯j¼;]û‰âã�Ì�á]×Ú¬×ä‰YÀ7mùfÚUâ}9æ6 n´¬·£“ 8&c(>éÓž˜‹ÎUÈm®c÷¢Ó˜›±ÎlªºôÉÑt2N”ýŒN—XàzÕà,bÄÎr£[ÿÔSœk�§.à.ê½hûD7²“%Ë=§…üQ¡™XM Æ SDxCViÝùÓôß~Xý,†Þm©ø¨0\†V°ªç–°U×¼Ê+¬ý.Á‡X5C°…DÔœ•¡›][�w¤BÏÔ4õ¥x’ˆÓ¯v;¡]Í)ôp<_Çç][›(qìDx…E%ÒécÃaÛÅÒ¹ EbRÑDfHÀoIÅaÖÏŸ_Ÿè&Áå�Ïc¢>�šÑCl@Þu‰’Éžw.Ð;?z~�éº÷KÐø�s·>¬›é[˜à¤yö–}@ìå`¢�cùÖ ¦;ªøŒ±�ÖûÑBG­îäjJkQßàhß�iƒÑòö6¦5‹G$¨1íiZUjKB˜aÊ.iŽUÚ½ˆ¶ÜqÈMÃÛ¬F ȵ•À™PÊLJZE§'FoÑ7«üñ‘çêd£Š–^Çû>^º’ Cfö´ˆ¹ƒÆàp¦ÌÏ“þ´÷èµR‚–Ø‚{Žž®„¼˜[�ã³­@˜Ü ‹Tã'宥>Söãã×Å'J‘Áº·gqàJÿe¨S ¤ÐJ]uf?ÈbûSÙ)à¸^å¹B+<èŽ˜ÏÆ_ÃFýž�› WÂËOÛŽKþìJô`’r¢×Ín93ÝÀk¤€iöa¿oÚk­ƒË§ôpú‘ÛÅQxì@²Å´›{Þ¬gcß´ïĵœ;½Q‘Ö%¢Ç9ÊÕ²‘Pr¹Ò/I:A×̓�""sl(¨cÐ_ÁŸ™¼‚bÏÖ~ïÁŸƒ>­ïýR½ rÕ’3®º¬öW Ê„˜à¨Ãªó��ïÃáÿ¶fô%ðÀÊ?%ï�×(àï�K‹P¾Õ|lØ\†Ü24)aà‡"ÜF+¦í·t)�9ô¢A±Éؤ·è¸²ŒˆÝF«!:í…zØÓƒ-¥N¿Õ[©õÅÙ×_ó[ þ.&{ ‡Êi.ë* ?n‚ÀÚb•,jVÈi†1¦'Q°ó DUô^ò«€R÷ 4C)‹›FC–OOó¶Çää§½Ä4Ãb¿VLIÛ÷´¶Â¾iÙ?Õ¼¶T~g ›�B6/ŠòÿÓ”U<¼õm\ʸ“‘ÁæpšâÇ/oÓF<£fjexQBÚÛè5/rÍwlä�º3˜5#]õ†›/ÛPÅ>=!Xmu)‰>ã1<ïï>�þ$½b5ˆrÚ�_]]‚v)âD·J;A'ÀgAðôú†8§ f'¡Åõ o+'´ú鿇ö—RÍžG8Fº�ºŠZ4rÅ>š¯ÁÌ”3Y®ˆÓÎi£švÄ™S œéÐòã0#;áuÊŸk¶s¬n?tB¡Ù|-‡ß·ãç EQ ľ p ‚w%¾ôŸg¨›0ŸV®¸ï5›aQÁ»”…#Hx�/B‰™}z�9y¯•gýRŒ½’¬Y1Øá‚½š‡–Ð}¥É¾›ï4Ï`L{> ÖVúgÅ\×ÌxðŽßf¶'¹’ÎéТ/³‚ý6gÿ˜i¼ßÁäLƒÕ¶RÝ. úmï ­Í–í©\prÂ}q+�?kE$�£vðò)—`f�“ˆ{ QŸhsìÓѪ¡ùŒãжš·ÀÎ7Mèº{ÅÞÕ ëq±Þ‹ë¹ÍGÁµ-‘!¼€o2s¤¢¶Èˆ @ ‰ËryˈI†”bÝG‰3µÕà»æ�RöIÒ–BƒDÄ4Çï[zr6Õ®ÑnÀœ áÓK~èSZÌŠb‚ÍÆßÙ}Ùv�ur3$zíqöµÍ'±+¢S …ŒoÅ¿w¦—!HÌßÀ¡eƒ�s\–pܧêJ”`‰ìpq?QqJ,=§V×Ò]ÞUKÐRm)ˆxÉdÅ2Ÿ –ZÚ¿�TÞÏ8µö‡CîN[jDfÏ?V‹5×Džy;ºd‘­è´*­�‘‹Û̹cÈE째0¦hêÇH¢î÷¤µ¯ËåÎãôö%™÷c¤Aiû£†ˆ)’;¥jÉ[Ø”ñî÷à}l: MÔwÅ‚f¢šÃ딺œë¶'q�…�Ãï(¶½0g³'lúaš)O28fEG̘0²J¸×¹Ë«×Íá¾Ô¨Â; Ö’e°[2åL4ÌÇòêá„OdF‹Þéù…3§~[ï‰Äƒ øã²‡lzAêgŸxÕ°óžÃ-„A}ÍE1Ï#!�»¢OoDKh‡SªÖ‹ç)rw4…ß勤?7f27¸ÊœèxJ[+ÙœŒ Û… m~½‹Å•`· ãÏ�äç܃X‹j'ëT0€b�Z6ɶÁT¸¾ƒˆ xTËG^¯Ì/?¦ÍZüeåÅà_Jôž_ÌõÒøª3ÒÇЃ…I,<óS¦…ù¥¢·e»ÂSuú{Y¥£œ84“g¯›÷÷”F– ÞÉl·y‡ú¾û`ò~±�ç©b·< bñ_MœY:Ç9GÞ ’k!6U}ÅG& Ecy Â,I;_ò|ü«üÎ6jÁâMÚsÄ£  é¯çÞ‹9Ú‹-Ž˜cæÍÇ:oÅ&Ýês뛡Ã`áŒÕ»e–Y.ç‡ç³_ZÈ‚±k5—è®U° ÐØWàï-Áߥõ�uKýßÅ÷*OÃ&� ïü3xmN¿å�epu kä/,þV â EQð%pVÌÖòþš�2BŸ˜¯{\üìÖ,ç$`v‹¥ê"‘QÙª––3wŽáíø fÊÁµæ�(�WÂÒ¡ºÉ9d5âaê]j/3Þê,zø‘—#‘’šEþÄ�¸j"Y« ÑÝü ;n¦KØ¿î"˜½F�Ãw+{ƒºïÍ¥9ëãîá¤ù�¶ê£HÿS½âÄý¶ # a.¾Óû�/.·=JýÞÄ…FæIèê HÀ �õ’Œö§~ �"ys³‡—4—NÝ‹ŒâØ�•—è—˜Ð$²f $� Ó‡åOjpÚ�,⻈_ÿiXiܶ-{á¥ÜØNg½†™�ºòÊcôy¾OŒây«ÁÜпÄì«|6Å^jþs.ظ:±ðޝQå½�×\@ÖÜßa'Í›&D˜;YçÍ¿UžÇÉÝ(TémLM]($›^57ád†*ûG~ï¡y)õg3®*ê¦Üö_Þ „ê÷ÓœãDzï$‡—Mßd6^iz;Ñ“Àå è¦[Qãè© Q�ü�,QOK×Ï`×(¨6:U­ò3>Mdp×àI‚H¨²%:ìÉŸìiðBQhíãB˜*ꥆÐx¨nlü4 %:Mìá|ŽaÏ>fì秆:î˜7eúC:£ÿA®YÌ|x&Íüu®Ÿ Qq^Io¶®ÅnŸ÷S1§+žQ –hš• IéÚ+ÖÇå¥o“ñ³P_™çˆ¨ÈIICvxÒÁ·ª‚ƒ#0 ¦k©ÛŠ�ÓüLåáºý-�ªð¯ößáz}ë]áªÒFf0+ÇÛ¯1¸ZÍ[Œ€ËÖ™"ˆ[dòÒrøÏ Q÷Ž$jú†ž\3B÷íÎÈ)"¡Á4x�ˆcàù~·8øùžápèŸñ‹¢½½³ Ëq?¨ZÁ®G “¬ËÚº üB”ÑNtÕí\ê�¿¿k«¢ÝæA÷‰ŠúèwäëYóõh,^ê Ñ=�T¾hàÚË v’&�ô)ް0b®5â�3ÙӜޠæAòGl8¦�&jú‚Ò"rb`àiç²)Á q…þæê$6 CêÌKrv'ZîÂCÀPÖCû&Çó0�Dæ—LÅ^:û¼¸_Ão®nÆ�†38GŽÍÊÔ†´Á—Tß¾•P;©êÑ çkëX?Öd÷d|©$˜\$/øù9ýêŠâÚ3ç™pú9B:ì°Šã›ó;ÄØ²ÓHž`µÐóÆò&þ%öÿ¾· èx¹ûäE)âoŒ¸ñ_ÙÒèÇ–(Ø9ŽŽ æÊ±õQe!%ŸJüýŸË–pFOŘtmMÆwâ@Ê~ˆ’î3H!°‚Ò¯OŒDÿ‰ÌÉÖÚŽ]™vmOù¦¼Ô«2‘|‘%×@&&´uéY¢eú Yÿ© 5Ú´°h‘2j·ôüœé¼P8lï[»íš Ÿ{2¸ yz·ã”¢ƒø8�.UÕ§0§‘ik)†Ö�*ætGOÀ¤‰_(m�ðë¾›C6›µ–®räw&[�¾zBøºOϽ²ÓY»x`vþ�v¼6�{Ø8Hév$� NMõÖ¤ãB‹šL{Õ 'ê0DÒ>ÒwÚ“&ÿÙ÷?÷ïsð’n·„ìú�ˆJ‚¡|Ôe¾€¤Š+¥¦Ãç¹fcR€/îæù1•¸C4ÍavÎÍzηl\¼˜|TJZ²[¥)‚wYIX��Vaƒª|×H¸øšœ+üé|Å“$;cƾ#…wÁAj†:¿=„�'ëÛ+!Iø9Æ«!gþš›N›…Z݉€bI¿e.xÖõªm o'ûúrî …Þ§±óuöá¿ 5“²x~I&‚ÒDW€†Î{2ÚÕüâkkÃ�fæ£`ž©íÿMñrß®ýûT5�Ú ãü^‰ÃÛà5-§Àzï”#ð¸CXWWG⇓‰/H—ŸŒ<çÒ3‡‘âã(I IɺŸ1ƒô¶°laA‹�^3—›Ÿçõ êj¢ËaÿndÇ>Œ@iÝð¼?_;“hc'h˜‹—sÁÛ<þ—� �|©}’Ì}]ÔÂ�…w£Rkžœ‚Û›q-£ïzÒV"E-¢Ñ­¹ÖX‡^A1eÃAèµ±ðS�•‹iñÖ/çÕ�±^zö4�,šE¦Ú4ÞÙ’ô“Wƒcå¥PF´%¡ÔC"* ·`rm_ÔK ðR Ê�KÑ6írÉ¡’{� ÊoΆu”2I¡­ü X£–d,¸<_iÏÕ’Üt/2ãÖ€°•?ÑjåçÒðÜ@º¢8ˆ>K'gâ6¾&€í ?¥®hN¹{¢«rªN&ÊiÌâºIrn_µAB„ÌÃæû=±½É¦ÖûK}HºzpçÙ¿ÿ‚zxBGb‡«9¹ƒÔÀB«¸ÊãrØ/á·Æù(íDo[ËÄ·še·Pâ�£,N#r1Ý}̺îb]Ê%L�OwŒLÞ¶™¸VįAB&¹gОFŠÈ¼€MR„s˜ =2r¾µë‘gᳺüVÌ‹ÿNÞ¬ö{wŽ+4X$´fùÀª| …ŠwÞqØ[ªšø¾Ù;|ç¯M¸ ¸ÅKõBóüúz"©tÅø‰i%c� 3@F\I½¯0.êCC5× °"ð{qÓdÉA)Q†¿~EgÓã|f$á%»Ô˜?ïã”·sq¦áV²óF¦=�Ãã2ˆ Ä<_‡0þxéµ1ñ×” ëaÆ [¤SQŒ_NV�Ð-ؾpˆÌ�_žI5öµ'ߤ ÊcO+{Ÿæ7ö�-”‘§}_qº‰±Ê…WÔ«>&âj< ËÈkÕü¾%]¥µ˜(d‘±Ç‰N* rKtIÀ3.yšù’6{ƒ„Cœj~á±*)Tƒ›Š§w§ñüs´™ÛzßËò ¸%E~…iFÇ =³f\Ã�]�n$/[žÈc¢ªÏþ„�5¼ètsë3ºÉÆ*¬áw‡}ä4 W”x“Õs5�¦/×å¯yQè¸þ@U1 ï´ÒëÑRÒl@�°ÅN¥8¬Aï5š`$’µÞŠÃÑ�uS=¿/ÊÑ�ѱáhïЙ”í]Ç_´¡ä /WJ•Æ)Þy•žâ÷‚uŽß:èv�z 9G3ÔÈLŸÄcÿ aZù@êxÍMl�›Ôû½Nݾ+œ'þt€–¤¡›³�w“ýk“0‚ûâY&CP‰é�šèÙÅñ¤*’Ö™A-ý͈)@#3’©–¬Ô¡qZ)Ä§Š¿ý}Pû(¾ÒùiÕ==Kd�C�tIº’²üC%_Ò…O˜Èg ÎèwÞÀÆGÛoas½€JIKÃ\Ëó¿õ':k•¼ ˆôã¶^lÕzº.ÑuMzyžÕ³”¬Ç�ÔV±lTû„1{[Á;ñ^ÆL§˜å¨gKÚ¯õ3l›UW�öÄc+kqs†¬?F*È8«%am"Õt’£3ž“ ïÒáÕÇŽâÕƒm§éa*j%jQ¸Áf?�k¢\^Äm$oæó:íÒÉmàëåT+ã„þ˜rš�¾Èl"ÕtbS8¢žCâ\ÙË$—ÝbZ`­ Ýà)œêªp¦($bbß×¾&;eñ)IõV‰ìXvü¿9`=稭ÂP(›W(zÐx2&©ñU´"Ÿ3œ9K°_z¤@´Ü¶Ýï <8p‘ƱRK=2Œ8Þ}�:�œÖøåR䃱νÈò€û“k¶Ówñ y˰ï¦+ÇÐ[pEá7";6Ãp3M@ÝãY²ˆrT`S‚çÀ%ä¶±àz‹xºÓ j#îåÚZ]>»-‹ Œ$ô¬oÐã°¯OÔ/NK ²žÌÈ ¼»r\ûÔÖ=òOë´}SÄ¥ —"£Ñ×Ue�µåp/øÅʸfm—´áXzpKÄ<†ÏÄ‘£iø®¶ŽA‚õVÞöÁh#–ŠÃU¤;Þ|3@>V¾YÂ…N5ê<—›ÒK;- =ìYdWÊ�*%‚Ï…l€`Ò†ÅMñïŽô1oÐR¾Ï­ã¾î:E»³N¥¨>žb)ò†µÎ�ŒT(YÃå¿DJ¹ØäÜšh1hÌwböOÈ_£/ôfþ´ØVˆó·jwï©þŸ‚6ö¹Èf�`º7(Oô^]i°FíöÀ}=Ùñ¦y¢ ¤Ø¶Ñb²¡™o†×ĄνS†lÝÚiÙ_ÛâP�üÅmyŠjé^ݲÆI s•ƤB± †‚NýSbÄš—¸³©¿KÆØmÝ4 2–ñì[€žù°}ûjüŽæ¡ÇH='qSÏŒëko�Ũ>­~‘/®%ÈÇ5ÎÓÏ7Jïc”TU¾­Â}è$�üß/Ö’’w >ô¾†´éiެJÖÛIåé!1Øîœš>Ëeð‰‡(5ÎÚíТßÍé¤�÷èÚ‰¯Ö€äˆç¡ܲÊfàÔa‹9ˆä¿fý—�©â¡v1#‡¼×M¨p…ì[$j%©¿¶'ŸãüÕK;ÍÔ1;IÄb+ùœ 9ÉÛ#è©¢°}m`&ŸÕ�ž4TôÌ£¦1„Î%DN5“øÂhË…2*$Krý1~ø©�Ñ@:c§uŠõšlë­è¶¶<ˆ�YˆËJè—ªÊ7Aéh' k~†Ï¨ŸF¨¯Èd�jôâŸÝ.ô•Ofqå5œÌsÚ˜°_â�Ÿ¾!XRA„˜«‰JîHK´Â0éÇLÆ[aS"†�Æ ÑA+Gˆø·Û†Áß3'>=/©2—åñÞ’†tàk‚¥eü¯�#;è9ÏÓáÔ£g€"åú‘–«Ýº‡<˜l‹g³‘&Òf§ïÝô›ïþÚÐ`ÀEÉýz¤õñ *´–Ë}<¢&ê°9‚u |#äVB&py Ö+ñ|‰¼_RÝ–ÛHUëêñhú“ÿÌÛÿ=!9n�nXŽc+V0¿Û[$Ííþ»ø„Þ{«”n +›ÕÏd«åË ‹ƒ‡n¿³Žx²ò3¨×œÒ1Z1ÕA zÊÏŽê MxŸ˜—Dàåß‚�ö»‰}Fî VÃXLÃàŒ �³Jßž³q¿³�=Ó"t#cU"ežZ#-¯ü®ŸqT9S{¦ËÅ ÍçUs_AFX¤8QÝ~CðÚ¨ÊWЃ‹–( Ž&³�Ù*88„J&ߌ§£*ÚÇvõ} Ÿ´ïI¹ë{)æ¥âH@{Ì&%†³ä/Ãd£Ëó5hmÝx—¯áâ9º%ÊÓ`y݆rÃdsãöÓôƒ7-·Ùàƒ�Ì4ÁÿNÚ+õêM~ƒÙÔ üÁú-µÊ°Üù©üèm|â_ý$èf¯=m…(ƒÃD]ââÇ&¤ù„'.㔫J[ùsû|F˜ç»äCÜÕpÿÐjßc]íúUŽÅÉÇdBƒ�„•T$-+ÛwÕ§2ËÒj}µE€ž2#5¹•¤û› Å—ð¡ÿé§÷òƒ[˜^EÑ·—Mû“Dgp/R'¦dQ¤Ÿù ¿b‘EP1ÃÏ9Ý0;�Ç,ÜþÒK•Ýš`ùÂÁ œaØ1­T}»ñ ŠˆŸ5¥uHCbÊ-Büà ã7­{ž0]*C÷üö;±SµãÞ¡X±5ÍAŸDƒcæòÉôb”oIXoqÑz%;qW—‚]°§ÖwŸ#Ðß ¨”{²»  LpRÌC�BšµtGw´–´òƒÞü}—Ú»‘�y $ùú Qb‘0ßÝ‹�šl`’´ `Îóæîõéö‡‹§Z@éF…Ìe)A�—TbU &£ie½g0úâJltñ~&éªØèÒT³yn¦p ‘ä‹ $â"Ù¤Õwm_²×›á€µëö •¹�qÀ Òè3`W 3T; ƒŠµ8±`†ÕÀÕ{Öw¼™÷ h¨ô/3„{wÝùáø�›<&磣Èìk‰PG$ ê—š^8Ý &ìÅv×pƒ•!;k¨3¬Ws#½r½ GÈ Lµ"[üH¹Â(ð›·¿Zmš7Qè×Eñ-ŠêTã Å@vÃ¥ƒÃ£öMøˆW¡ycÛ᜗lá¦AùL,fÉQo@¡ÅCëÑÒËrc u®%Æ7N£ìkÂÂ6�¦Òs‰êTZ§~¨º='ݦ¥= —Y]râROÀÖ·hN›j‚P¶¿'åÁŒrZ.JÃw—ø‚çPGSåÿ¬ áE’û}šfÀ[HB ŸÀw9Ð�õ‰»´�µÇŒUcC¬îikñQã^g-[ô몜c—¨™ Ganíñ+”�çäáAÊUˆ¼o¹�®g(‹ª€èŠ^õ¨LV+¥Ñ´âE«‹Lù\C!Ë©ý¦”Sïœ=>óåÆgbTûX' k¥ÂOÈÈè±òx t܆(*׸ԸñfÉ5W�)Í´\Þ4?ÎÕmÊ‘s!D:»Ѝ{-Äm; ø¦Aø�¹#Nú�÷ƒ0)íj¯ÞæüªÒä¸‚Š¿©É]Ê œ‰Qï�‹ì¾ÑAY¢LýN8ñ ²§ûª¿ªúLKýB=ãÉ—qpá=+8Õ(¾‘RŠ#‘ÓÇ.[N{v”{ù«U3„éx–¡ª‹|½Ì`U&té/"Ñ;�ŽâgSã×¶íóU¸òúg™ãA0­ùÖ‡iø ¥dóâr± C—t<±Œ())àqìÎõJÙ”¨àâ#gŠu.! DTÖ�ý–¿!xãkèñhÄnhß+Yštƒèt¬ëìü¢ç@û«§d³J'Âñ3j–ÜÄJ ¯Ê)» Ç”Þã–œðmi.Ï�~®­Xˆ&÷–kù‰ÛQ€^DÚ‰  A,LÄ©¾êÒï®�ÑTDÐ æÈ;,™n$“_ ôa«oA5`®âî%_ðž¿FðŒC5HV�Þ�28²:{ù‹®(Ѹ~ÜÆ?­­çžU…ïµògÁ‚¡ˆÚܬf5A ÿouï ´Y<¥;…nv5§_5 ÜbµÉHCzN0hÏõKñ?µs‡§ F„¹ar ¦å£hࢺÝ`Kp{ro“,ƒ·ú]¹,ãÆ¥ QªÅAXN¤›x‹ÓT/R7{´8JS+ÑUQ(ëÎh\EÒ|Z‹ýt÷ë5vûãë*(Š*ä¼<¬Qâb³ýS&±¼'wíƒçºÆmK(÷ü<Zõà»®¤å–Ê6³€ -h™.mkýëUØó�r-š¦I»²Õœ9Úq>,ÃÀöŽ�ó„Z­ l“GÕ}‚çeõiÞ‚·pŽÕ–“¾_˜'�[vcÉË#½ÁU²B…þØc²–KaãúÁè:漣›ƒ·|©*�««]�§�{Õ'ÑñŠhO/J°?RÅD,¢îrí±‡BpDÀ9O}x:¡°8˜AÀêþÔ)ë¬Á0,Xe¬¤DI"V„IÚ²ö8Û ,‰Î@}¬jþ»„Ïhôï½Ë­UHr?}-ó�?f×/òÿÌ#7-ýóáѱy<‹Hq? |ÖÒH›ŸCËßð‘n4öÿ—¸�ÓŒ€®Ïæ!ñè(?ôT�™?p¾Ä÷˜ÝO¶œÑ£S‘˜oomˆÃ4!2è2Ö°í1e±SFÁÀ¶„“»ïÒ•�Êcè>ÿ|ï*n&}*’Ï/å�/x*ýZ•c£zÈÞÖÎÌ»æ_rL.þ0åjy³Û!?È�OÖ-@)jÜ(!£é‰ý»&˜©ƒß yJ5~hï,éf*tèo&ÊÀi,³«Ê�¡ffý¯^¢û /³ÁY³ç�w�’(“v»Û°n×Áà\*ÿ¸œ>àmø×^ÜšøŽžŒ�X,¾!/Eî»àR‰GjÛÁžê'9’E�Cpå¹R¢¾Å«˜çÊ õi– * Äï$Ge—ñ€ÖôS�GV¨‹ÍÍ[%hx¥õÖª§ Ö'—LE½"ÄÜñXÙóh|w™r°>9£ A€€Ý¥ð‹wÑ3“à•y7wŸË®«-À,5œ]ÕXûV){UäD C&ÒÛ œâp»Ì!Ð ¾ ‘ì|W™EA’¬Œ-ÆøLéþÒÄJ² @õ¿äl�4ÇK¢óªhv�ªDn›Ñ(|>ÝCëó.¦Ñ ±×‘kÁž^õ±N¶R†Õ¡àÇÂÊ?�ß�÷VJ2P1+CT÷{›øzí•ÙÕOˆåGKO1‹Ú 7°‘ýO£äæKóÑüë©–«¡A4tV®Ar±m{/ÁF7�ù¥p`›¯Ìƒ²«Í×ÙüÕOÖ5�«IGÈ:0É�^µgÇKÁXGê3;¤mÚki†5¡bëÿ;d#ýˆ Ç- šŒÉ°î>T–¡D Ú>N—æG¶�eÒšÙ¨R%°OxÂb÷Â.<Q�MF¥úa6´Góz@å&:D˜Zœ¦=ôúv“E0ɤyå ¤ìùã8 }{l6Mâd‰þX�ßO«`Î|Ah¢Ý" ÆGMPåÑí‚”x«Ge€„ÁI®†,ç¢'î¥ud0ÝÅS‰8µºB ÑqàÛCë�o¹)¤ Žöo@íí:¤Pü»·]†a³õà…4'~ç�LÄTÎfô>P­çÜ%ƒ ‡aÛjüa?)7¶ºhÂÖ“3|ks¤kï@ðšà:GelrËAöB+6s-ãüARí\›aQfù#æl,�ú*3�ʳ­™P¬Ô´UÂê­ÑñnÛ7!ÞøÊÕ±�Psû˜Ûõš¯ÙËfŸP玕Wo¬{-z�…϶â%AXÝwj´Ál‘£Q3M…ÏÕ*Å~oH»Hßÿhø…ÊÞ¹{Ær�F¦jTy2Ê T%û(l¸¶Ø'_m7¦ˆ;\âM{Þh™œx¥þ̳VÀ´fÁ[5\+8(îÚ(Úð§Ün‚û¦þQ@“°¨ ž8tçúVGMÂïfœéŠwq�î’&�³BHåºc…ýÃUŒÆ>Ý¿ØÄÂþDŠ… eÂÖå Èç/ë`†_ôt�ló1Ф*Š(ð$¥1"J¡GÒq8‡ëÄÍOìh×ó¬ðKž²a ,²§?Ɇg”·=| -+y÷�ŽG}\Îu'ÚQÏÎnÃóDÏŒDάöýlº ȼ.(�»»Ê›((NV§¹Ç7“ô`˜cUèYýÍ—�>t�Yæ±ñn ÄžZŒ]Rè>…ì%Gûˆv«}øÃåi¤_탄GÉßó]—šKsÉA�4�ž’·}_IÕZÖÚZ•Qö¼[àRM�öB †lëУdlßøÊ]õ÷$F¥ÆìÓ& åû9Ö¼0l"Yí[\Y³Ëà¦hoÇží¹’Ã¼k“JWÀ›4{\-VžçD45ä:(.ÄÃz“ z¬Ȥ¤ª/÷KŽç(¬w%Ô¢ƒ–ßëïmk¼±]°y$ÙJ\C¯of8ýùMI{˜7õÕ®‰-~Gö®Pzá{“³›]¤TØ…HÖ87 #¹r—š‘B‡áxµ¹«ËîP�•‘•iÌÏ K¬3Š8~ÐÏÇå¬pÁ—qíBµÈ/D­¢¨Ï�ÐÉç¾Ly4ewhÞ.yaA?|̬AãÎmƒ®€¤�ûÊW#gðBYý ô@dUj·²ç½)(v’©P üë2é ß )+ÍåWP¼i0÷&;çXÃóÊ~4=­¡Y‡Ø—cÍ8o…·©á˜’.=æ¡'‚öÀFQc«ÂÌ^‡iU„WÓZw“­êeä á¤ˆ; Õ~¸F�ö[ImO ¼4§ —ÛIFò}7íI,?‘‘^ 3ˆ�(fßÙ$ÿq®‘ Ør3$`ˆ±€¡¡þâ¿–ƒ3íßÕ»°üjÚÌè{ˆ ¹‰[¬¢4—;Jþóò=ÀWú1S)ˆ8´«ë®í Öí+Ý%÷±™Ïؘ@ø°xž-D×jDjÛ§£àá˜à#Þ)mËu3¡w¼ØHùLÈÙØKª¦æ‘÷dÏ2È|<¼C¿};Ùû lBTŠõ^ª_ÏÁÙ b]ÃW±yWðšsÉF 0%ŠXiIe/:iò´:ù€RT‡Éh­ÄIáf¹>pBk—ÞxiC¨DŒó3À $² QìØ}9€ÛÿǺÉõòLÎÙ¼å¨ÊT6´n¦Ä ÿÛxe>¸Òtåpσ•e¹WFywé[uýÀ.=¢Šdr© ž…ÈUëÂÖâúu7_e™i·Êküæjæj\Cñ-/"kB�—ýl˜«§#yѱÁþ†à¨'$éÝÛClTfð÷ lèZ�ŸRÔ–Ò�¢�(à¬õ~nØ{šz†jŠQGnQŽNʼyœp¸¥ñ,JúüuëÊΦ1뜅;bÁiµ<ë.G�í„Ø~k2†ö°zG꨽éºdp¸(a¦ŒÙòΩ" ­™õ[AÛ‘f†‹q� -·L­NÞy­:�…VÃäeupÝlÜð«2ëO‰¡º£ÉoAgWÂ^Ÿ9¬EÑì©D,tˆ|™õ׿¿�OÀω; ›¶VwVÀíÉð @©¨Ó�CõÍw#�k0xp勤öÚB‡ç7c›<¸Ð‰Ì· R‚€«ˆêy7Y'C$æÈÔÐWW¤"vW•�_»Žµ%Sƒ&æïñ^:¢JosÄPkÂøXB‚Øòýœ®ÄeÞMЬ×b… T5©ÞëöW–é$fÏ}]ô'¬$IÏè?l” 5ò*1à“¬>x8’¦÷œ»ϯ°Úq§Ô¹—¾ÿŒÍé2qÕ›'¼-î1-Ë!φä H5‘ÓÐé(Å<;o_£=Cè†ß)Õ_FÔHÞ¤oit“AŸÖ}¢‚À£€àÓ=ذáúS;�»ð”‡õDs £@fòµ4޼¶T¾”N‡g%æ‡ÈÎÆ|µü¾V„¶h�Ë5VéžS¾Wô ý’Ae¼»ž‹b×8­Òfõæà6ò9EÃ}WåÍj[í<7™~üåœ`£[?,\ˆ 9;ÁÜ=à)§êõ½Jù<ÓKg/J-´Ð�°’f5¿'�OŠÚq â×hRlþž¹ŸÄ�“H¤cbQ½q{Gøtiñ9îxÞní“´žä½]°ÙbŽA)>5 ¥¡bË®»3¢£ÐDò;ßD7%ù4µèŸ5ˆeݶýK=|¤q09æs™Íœ!.ÙìS•é³\ré}ó\mÅý„wS €:¾Œ`­F^T¾TŽ'ÒlÅJ.Ç‘(–ÕÓä°’ÇéëB´÷¡|g«šã8ß¼~õÎWSÏx(®B¥7¦âž²„…ÿ.ÙY&Çö… uÅuÑ_ús¾Ì\A¦ðš1WŒý¬ôH0Vš%ռdz<�ñ~N.ÆvÎ|˜^/Ëe’š¯ñ á‰üÚ.8eÂýÙ÷1JðN¾½ËÊ£ °jÀ¼Î[þ@Þ� ÊôÂ!Ÿi,—C8¸õ»ËÀï�LSIvU6:ÝIú]™lŸ¥à:fbQ.ý³¢�·Ét2”¨\;ë}Ô±ÜX20?»;ñ²Š8µqí)œiœlÿ0_¹( |SœÜÜäßï`ïe[R +uÉÇ{Y(ÀDv÷(½À¾J3]öL›w„)µóL4jÍŸŠ åžä%-#ŽHTš°ªƒð«�f2Ëb¨0³Ye Í(›Iƒ�Aãq_ ®ŠïJ¸8TŃªPÄ·$%§‚Ïa!sH <@ÉÈ1Ë«ÈAä‹äËkíÙnåIÜ.ÎÕ–ÄŠó¯b¥Gcïš ±�ÈÎ>´ í|’3kƒ}‰rQ—6…®õ.äó$å™ÓáϺ¢–HmÍ‹n´‡äÑA¢hÛš?À·H³ñãõš¬7s¸Û�À¡î‹Hl•^¼Cßrå7}ÉöúG‡/Ò㿸§Ø2í¾ž8µ†��}©wŽ’Â"Áæû‘‘†'lUÍ"„àýÌÇw‡6�Ù„HìHÃÖp¸³(íWJ~f ¢°æåˆ'œey<Ä*ùVØQÈn{H ðµ8/ÚDy7J³n²D'U9›m–„w�§L´*8u£1°ó—Ó�X £pÿáÙ¶JÇÊ(8·Øë÷‘«w÷GºëÊ›3\ñÜ`£·ËÍDö÷ Ø‹¢öœ}îñ8@€ÆÆ[2Såû©]V¸óÑÞ3˜·"Æ–ÌÒ¾ˆ�.ªtUcƒ•{PÌãê,^ ›®ëÞ1:Þ6l¬æ+¿ORœ�‰úâÌ�k‡û>ÓU]/QÃ7Ÿ6id? ¬® {ýù¿nHÄh{Htï0XÎ8Ç×1=%©:Ó-ò°�'w[s‹¹Í¡]£Ä\̆xyƒ™‰¶hЃ-âïÞg`þõ�`¦¹›Bp»aÍAß�n´�}ݲÀSFÊ‚‡»~)6!ÜÈ� ;ÈŽA¢8;¿ér}¹gÔ^=Ê®ƒ Æ¢Ü׷Ũ[<%¢15µCE Ï«ÖÒ]b"Š%«®"¡ÀŸ©°®ôh­?nP’Í—O v¦Tꘙ‚Ý¿Á‰}|ø³_»Â¹ü$&ã†ï|ØX ËUئ_Œ[Ùeñ gNúvRÛ,‰^C�Ø€«XšŸíœò:_€d9,K™Aœ|?€.ïÏ� %Æ©Î^¶FŸú›Pe<ÏÁÆ“‹› ,Ù½f1¨6$¤�¬€ƒä#]õHžK:ÝÅLÈÔŠÛ={ÇŽœwÏ 6Òø~{8Ÿý”Zoìâ,ìføWœ/-Æî%Î�èB*ºÿ/äo1CI ´|ML“=‚½¸.Ãÿ(ÅÇ­8,ÔºìõjOÿemMÓ!ÈA5³Ûrïm¾x C¶Ìíã*}"ùíôhµ,/ë*kpÜäZa5uóˆ›?«V(ÿ(WÖ Ž›ý1Sø¶%<E˜µH‹$UB½ÑYˆKË)ŠÌ¥œp¦Âl‡f,Ó­¬$Oö¼a÷i¯–`¥ ß&îÛòñ¨>°ÐÄzü™ëF¥ÃÒQRb¼JËÀšv8ß6#ð J ˆß]—¸ª€ “ûÏË›­cmÚ¶Çs�HÒ(›tµ6TŸá«ŒtÞQ“ý¶ô‘-IšÆ¶ˆv`ЪE ¸Iùl0à#NÛàŸ}qÍ\C\–è†c¹ï QyÀ ÖÔŽ£ u_¤\ð•�Ž&‡<ÖÏ�]èã Üë3ĦšM…"‚ uFëe¥)üøD,C踈ë¡Q@1¬ødnJ:ì ‚�ñ¢Ûô.éݱ¼m6τ޺ââÑ+31©=YqnC ?eqdj%ÉPÞ*ý¤êÍ¿ÃÇ’wR|ë[zÖЏÍuÐ�mÃjMÊ�ª9¬VIëÀUmF /ÆŒvÝ-öìâ qhg�ýN°Ñ¨ö;eÆmõ_sgNO3Ù2Vº;(@"·,d3PîðˆJŸûìøú C?·êÓ�RYX%w%Ùotüµ)Žû¼ú�f�è ÔØam�5ŸŒ0»û 8�j„qcdCÓ›š`‚,µÜæ_Ð6sØî}žv Ýw5ƒàœ9¶Nqð­åÉ=„ëocí''–P{«ÎØy Ä4¬‘!X5Í&Ï7oä5¢o'ªêΫûðË®£§æ>¼Ìb¿³ÇªÉ„þÓ§Uhâ]Úƒnç‘�€†7þ“Zoâq9sñØÅjÍEN¾û�7WA?èMP‡´ÒTx¯Á S¡†—¼Ì“d>TÐlÚ#„+šaÿ2Zw {e�+ôÙ�X&¹ûbt8 @àɰ]i©¿}¦pÔ~FúëLåðábŠk ¥âyI'¯¬Ln ¼·’‘Íô}Óà>¤}£ftd [ku¼C ÷<~fëæ/>6'ƶƧg )·¥¹Éñ´Ã7kªØ åPŒo…U3ØÈ '%“Ž z½âú±ßôzű:‚Ò)uÆú:ñVk€8�èxÀè ¤ñUyŒ¿ÏîqÑ\ì,‡5ùÁ]†ÁØ+3´¨‹xÉõ÷,Zæ9ñJàûľ9«Øl`sËàqGW·Ú(ñ‚EÀoÑhñûl|—©.©»Ü ìm5Õ¥{+‰øeÝÖ’¶×I|5ì÷’˜pÐzs–2ÿæ‚é jÓ¥¢ï…5BY$öVŸ/M Ù4ì¥ø�Ô¥gœf@4ú=ã�J4/·«c=5ŒbÄŽ,ã.û¦WÎ�öncîI¶áä‘8ÕÀL/P‘å}B�A­ü÷j?”ßõpϦ©ÌÉ_€ %�ýC´�€äg´ÃóËpö‹jeІÑ7ˆײ³^ —¸ù‡¸eë; hª%ýú°™J‰9h\g<§–ö¢ºós—Ǽ×lb pbLX�â¶03I|tL!UéZ ƒË ?ô#Àÿ˜�Öóª³T[4Bwþf#N3AÛVP(kJÇâI4ëýaÇ�@Šg �L¨“E%À¬Ã.ۣᛆ%­J+ Ͼ[ü�MíS}ÇY<*e~e z]ô†ýÁPV¬ÓêodTÖÈû 3¼ˆ9TÃɶÆü%·�»N¬ºLîC:‰¥´Ý’»úb‘#L)Y}®¢�’±š®·Î ²ñ®Îÿí­™Ìþ©�Àé“Èv½ò±ðÝ+±&Ö³ ä˜ZêRˆ(;Åæ©Ž§ê}$Õ ' $\AAižÄŠ&ĸw/Y¨TÍWà–6¹‹™ã½Ÿã‹å Ð"ŒÓ7”cœ‹Ù7‰]] Â1ÁÚÁ*1Õ³°Ã¸Y"±\`ž¶ïËM;¶ª_"é©î:Èy)=)ØmU,p0‡T•6 âx#�g¿liÇTèÖ0A€Íµz*óæi|f¿©çEqPî²o4©Ô”G¿Â=75«\BŠæ8ªÆQ–<ð(Fð¬¹Þ¯ 9”™ ÁMò”3É1ž5yU9á’ì‡çöÔÙ‚¬侚íHˆG@¶B³\Wdd‡x‰–ñ5rìA~Ã+4 X'iö{eœ³£æ_œÇú·•…�†˜qGTßu1ÔS³™±¶µN Ï'$¦ÄÔ€¢̱C¸#†rj�5¨Ðû¬°nÆñ$„çùwÑÓ©¡^ùYY?OÂúÔ¹‰ˆionc\…MB¹FLÔW8@¦o-˃}eJ¬0�«œèFï/øÈ–#«)›R¨âL@ŒdwÏœrýS4ëþÌI\©”Kž?™Â}˜ßpJ ÿ{Ib¢C¤{°O’É)þ©]ÁòL/|b²¯ò°ò½ìóQmvç,¤V‹�ÒÁnñ]¶szD¥"^�àTÂî=ø{ý+ YGt†®øQ�{ƵLaå8aʾ�Ùú�NÇ"¢±‘;ª‘ð^ô—†‚Aa…x±g‡‚QC�h ½;j̰R½ño2÷ š¦5£Ãò�«¶“r!‰ˆZªÎ‰¦Ô˜(‘4êH$Òk fyL»@§DË ¡‚ÎÙ±¾‹²r¨k±�±N-°GìÅþ¡·Ï”š|´ñ„Aãsµø¯1ö•*˜í5�kRjÌ<µÐ§F†þ ãnµ¹¥ÌÞÕßvÂÂê“¥ËU±®ûHcYžušÈ_2QÙÒzQIÄÌ^âSHðý‰TOyЇºßK¨š�¡­?s+w;Pãq‚¤¿e¹ë�¥`ewõ té®�¿¼4ÿîT31ëã’ô4,ä;eä•ewk®±éÇ�f­�¨Œ/äŠ]°Ó !¥d�_üŠ«¡»b�ÁždíÏ;M ‰â@ɯ[¤‰\›¡7ØïkÌ~Ã:=%u[ÒT %ô8ýä `BšhÿöÕŸ>ŽîŒ6’úÛ²zⳌÎ]â¥xç æ�Ÿå+ïöúm¥ ‰Ê‘^6Üz‰aR–Û…¬Ý%%¾ˆbt7ý̧Æ9æÛ šPy¢È7·�Öinä”ÈêÂÛ›�Õ안�^zãîrV@QáÚ`´ýáèáƒ'�IC•Hó˜ ÝQ‰Å;<™¬4¸ óÎÞ™{O˜¼5·h�!®˜ÿ’<3$;¢úÖ‡|\: Šsú¨c…ù%*;¸1R»ò®�°÷©H) Âõÿ15lÙ)Øl~sÖ 7PL:â§$‘ã3ž�(,øÙæÊ®÷:“Ѓ_˪ò{‡ ˜äÍ¥G“ž>>ãv»s?IC®Í5îj?ËÔÖ�¯ñ`…Ÿ{Cƒ$§ª™$÷Ĩ˜)Ѽü8GÞTÙo³qŠYtÓréeœ¯¦h|Ÿ¡Ø¨·—€�/�‰èæmþÒe›½]DU<èPÜÔ„½aqÑr:õN]Ö‰*CcbÄË•mÒÌma|#´7â“ÀZ_ OFXi´Ï–Q?‹'ûoA^¸JõÓ±U3º9<) :¨"AE»›6Yì^HáCgÜ‘)@h�‹ýœa¾#FBn6´ê»ð'xÒÕg@Ëñ˜Î´sƒ}ÆP»Âê?—ƒ§ðâïIavÉN‰†5αÍ�¼åšñ¼eÚÖ«;I–Óm@EC)ôè?O°±-'ñ\ «,Èžhfáž®Ë3„ÓvÏvì©‘"ºmÙƒCUÀ°S›þO¢Þö«\�‹±l²G\³¼2ãIž'þ”‚8 úî�•Ü[@BúNÃÖ·m')7½dä£èÙtnKöäQÈnuŸäw¾¢MÜkŽ5§.b ¬>ü6TYù'¹¡ dƤô<æéÉI;€«2ž¿î/FÛþ3Ëû¬†»²]oç²ñ(#ý›”‡ö‚.æuÙL¹L¼´Z ]ÕˆøI ~ì 3 ߦÒoùc]ÑàUˆU+‚¹ìÇ<9¬õk·Ñt%>¹cܺz>f;?÷Iîlljïcžßë€}^X³8ÖX¿&XþÚÛÆ ]/*ñwÀÙ´)±¢|›]Æ�ÚN‰¬íä‚àí™"¿(œ‹° §5�Pƒ¹Õ5 ã´�›¥�cÁØ×ô®¶:•c÷èÎۢъçÂEšú§Z¯:ãÆŸþÚRÅ`JÔÅÅ♜¬ßs" Ó¹m|Dí‡qËüƒv×z ľƒNÍœÎ>ÈNý 5�Mø pÈ$C%.¶’ØW1–§hJ뻚1ö»àÞðÐoÒx°|­ŸçÂ�'67,í¿84çž=«`Rx—[ {ø£•·Ú…]Eë+‹s1 nkÞ­bOJZÐæ¿– �±ðŸÊÉç PøfÕ"DÝu´Q£�’¿9AۙŶ$­žS‰[ù“öjÏÀ!SjšìBçÄĻr/Iû}Ïr“ƒÑœ@’5¸_Çï¸^l9ÙÆÜÞÚ.‘ G$ÿI(k=ø=ëyÂÿà‹@”µS‰³yÌ 3T4Ë壚$5¦{é©=J‹H4p’#e³:Ìr�eÆ¡"‡4„V—­ù­ß›A+>”Æ¡x‹î&“©Ž]±ž)‘$¦x„ÝLx§øÜï LJV¶éµ/~\‹+2q•oú •…ÎÆòN�¤Aîõ»³(û*Ãý“®àÝŸyr/æ¤ÉSiÿÎ^wð^1@çÍ4=ZÌçv„²Õ_µ/¿SÉWç™s˜éb ®æøWÑDVÏ&–¶r�=¥èͬÛL¿ÿ\ˆ¹Xøü7ÁºÜ×Qt&·�BMça9¡Ekãï7>÷á—ùåO^…@ÒÓa, h4¥a³‚] ݱ¦1.ÓvP¥œ‘KÐcÅ¿ŒX­Á˜t" b‘ñXâ Ÿ j&Ã2„=úQÁµ?ÇìŽs-_5k²›[â‘q-Q {ÞÍ`K¾V훕Û?2Új6�õâ˜FÚM*K¥îx¢hÈ'iV›t/°à¥~›!\TB‚ɸÓ3PJ6*gÈ:_ `‡ÓWÁ}Ž8X£.Ÿ0<†É±[‹_2]�h5Ñ“åðÓg:�朳{0ýD �§¼¨¹•2ï…åI3ÁÊâN˜«¯>´¼.&«z3m[Î{䎴–Ôð2JQ=s'ê¸óú²ÁÄâݨúœ=ÿNßàˆµ:ÔR( °�oås¾“}hÇàÔ}íÊ”½$§ìÏÏ-|?ÂAÖÀÊÙ¹T—6@þ±õP‘5zYðT7‘Á¨ F—çüTÿÿ‚(ÚK…õze§@ͺDWb˜‚ËnP>mCÅè–/~K†ð‹ˆeùý––š¦6Ü=îò¶•e(³uG[Á~ãsÑ^^?èãL’‹Ò�I"Uúï½ãS>ó Ç<¦JÁ }/Ű¯{Ïmµ‹8öB0¼MÝMh€!*ì‰..=6€«MD^AV49½�Ø×–´t¬ûNZ<àëƒ}4Ä�VÎ*ù9cRnþ¼³ó§Ì”³™ÍáðÒ¢‰&vîs{Ø6”þÊ2Ñ陋*6/Æð¹3^»ídլ歬�»½vRÓm–mi[Tx]4uÎf>öd)ÅÇü;ÜÀv±’2Æ“›£®¥¨ÌçbkuêmRö�œëLRdl:`/œÅt Óš(虜êAu€ð•¯š¼p×Uóe9¿®õˆ€ÙN2 Ç:ð?!­ˆcºa}<ê4š*lý«å’ÀøÚD?óF#N"6e³Â1E¹rC©ðDȾ4 ½k‰âM.;RNÌãI"mwÌ%ÃÕV0Ëì"‰¢9¡Õ{ä*ìn¡­¾qhCZXl/W(7Ä•YÜÜþ�-lbº®+yx.÷×/RgÄ3ñ‘Þ.1o=}hEÔ=æi¾-Ê››!*›{JÓ›¥µhh*U¿ª#Xšß²Ú,à vÛôÅcM³ ÐÙ�s¯óFü sÀÝóÿ„SÒ€,òèYêÿsˆFú¼•*»œ�iÒÎÞËdŠ„Tk—Ÿe>]¢eºwhhž‘ lŸ(©ÛÍPZÑg¬Iq«¦nŸ(€œå+]-å·ÆíuøEÕXçÖwH.ÿ€¯:X¸×ÃûÞOÈÓ¹Ò×ì^nšpä:,©EMÎðàí¥­Ø*T ¼'Ž8%m8éÈ“ˆŒ"æ¸~ ´ö‰–ÂÜCBH ÑS[n³ýZ:q‰-ÉÐ]FŽˆÀÆ+ºP¹Rõ8jH<·O%ÃŽ(«4‚J½æO-]ßèûÓX78Ò}|æÍâwj�q¢‚Íh%�½H­‹[m2î¿ LWw¡4#â ¡5·JƳuOñþÝM•É[÷õ§æ y§?°Ê]Æ�Зaž‰�±øƒz\+éRÖQOŠ è®B}«k#ú¬å¦/;X�eW%É�é�G‰L’x÷š¼¬#)„Êõ4q%M©aÕYq;a:€V[””ÔÛÞÜÄE²‚âcÞ¸4Z‰“ŠäS]\s×_lO€7ù4î6T:ß……PÛ~brÍãÿÔ’ï4� ^Ö!˜‚®¤u¤ÃL:�§Yxº|c”¸*RŸwXS¶ˆ:©”b:Ãi(ü5?üžx £;–í¢ùµëÇÙ;㪒´pÂpØv'f$ÌÊÉþ�;DŽt ©éw×Q$M�BK­g-â®{S¶}Ós­Å‰.êGÖ’k‹Îh©(€åü>%΋6ˆB³°Å,Ž‘«•aQÃ|þÑÅ€½JóCI ¡ëŸOÊqÂ}8w^`³ìîͲ²ä¤ É1#3§h�ª`¿š­#:šBŒö…Ï9éä”·¢áZ†I­k.¼ù\8—…”å¥Ë§ ÚöeÊZ^èë) }Ãê` ÀÆÜ¹à~†­JòîeýY.Cˆ\导á˜_°­b¥%GÊø€>srÖŽOÔ¯Íx“ š¼G< uÅé>ϻ־òn Ý•£ú…ûÛŽu>‡§s…šà §=¹r9Î|!”âq–¶”:ÏTÀAÃV°dê«êŒ`5å¥ùE’¶xZ® yéºýs^ÀW¹¼–ÛòSòF/ ·¥ñ’;”¯éK“k‡tsJ0\MN¾{�=�ô›þ Jþ„·4:¨ö’jÕŽ\ygüÍÕÜ:,²v“´ý�Õ}»f·6O�Vqw™l-~F9 &…¼v8w€ýÿ,FNé‰ýýáÍG‚Pµš cÿöD$p6ÎYt·X¼þrA:~Ïô`”c¿½›ÿQ"vH ”·HÁ8—Ò8²÷ #’>—ต¢$rZΛ~\!¿êm¥ü5f`ôHobû#ûr0ã±Ç‹±E›5ë°©í†àCTÍ¥À±â{D!¦¯’¬Š)÷+êñ1Báˆù÷Å ³ô‘‡Õ×hÄ~/KÈ’ô‰�6ÓÒŸGSBUÜ—ïH*âµJšÔ>çüˆ» òmž´Îî^U¢@U3®R%ßù+ÅØ»Ù‘ýß„�‚y<$S1œòw›½>Å•õ·ëp\ôQNtÑáý2W³’¼Ý("˜ :íåX†ôú¿¥{ùC°×xÚ‰£ìtÆê“÷|ÒÛ>h…Ç”ÆY—~ÏYU0R¼faˆC²œ7èläö$,uKö*'RË3<(_ä¤};øÖäy¼Óëö#f”iÛ•&R™eõÉL›çjg[­S+ô æ´³ð|ÙYÎf�° Ùyüèâž�_!�¡i U`©ÛôÞÊÝõˆ“}fõS¥ø¾9Ýó¼Aºùà`Ž9Cˆê_9@®+®@ðè;(¥á"¾ŠÅ×ód€a¯,ŒmuS]·j°ÖªÝxÁº·³Á"‹ûFMˆ,þrɦ2ý¡¢éè<^=…JËOØúDz 6z@/ר©æô[ž›½È´² çÅqvvªý Õ;íxp]Ê"…Íí µ†Ñ“ÌÙ�ŒæeN]Ÿë¾P{ß)U°\S�%]mjë5Ƙ»Ö‘å¶55·T¹‘~Ñ?=´1ª4­µŸ#¡ ür _:Òë${¿Dæ ¾àñ™„‡Ál‹=c/¿Kñ&R?t÷ ª�‹FÓ?G¶×Á&¿}˜‡öްùCÓ�ÜáªÀ¿nÙÆLbjk3÷ܸž'ÍwÈ)mlgbüU:ó¹õ�˜©K*&v4@@sX_Á¨øl_J™!-…–…Ä=xÕHsS#ÙRohÄñ”rîÛà&‹½{,!�A#æK¦á<*§˜Xò¶ÙÈÜl�ÃËÊèÛ tÅ Aù¹gÔôáâÌ?1‹–h¹Ô¿Ù±øÇÙë·z·u¸'KŸe£3([Ã[µRåÏðøÒ|"¤éÉõ}o…þ›òŬ¬ wIªcÖòRCî$r^BÑÃK3êžø2Ù÷7�t!GñÍÝ/„˜»ï¿Ï?‘¼þ±)(`hG˪GÄZä#+:¸][˜š(Í"ˆCw¢ÙÖÅÙcŽÿ5ÏW6ß·=0ísv[ÍW®Ì¢;­ÈÀƨÒí¿® œ‹hW1š#5UuN‹µk‰Â|÷mW:!¯«I»:ÃÛŠW‚Ë�úBC§~Sß#KeýOÁöÙ³µë.Ç•çãÉwYäïê–~{°sÖc¤>ijRw�¡Q‘ í¨0¾à²øsþF™Ÿ{âÃÂ$實KZ``¡£¤‚^B,ě˶w »Kû a¾ ö>â0ã0jWÏ3¯nú¶/mx¼}UÌ]»à\}=å !†${Ï ö ›]vˆIüdݽïxeKu£D²—ÃtµGûP¨ýV�$4DÍŸ& ]@ g¢Æt`eК��ÇLÐ$›RÂw �ZFL¼9¦e¬G0¢}ùùËÒ)‹ý4‚Û~‚“ Í·hÄÈ�íŠü‡`êÑx_ÄD ÎÍYîr« šëh7Ïeû¢€‘£)ö¦DW9õ�u¾ Œ%"�KëRüæVOar¤F�ŠHob9ÂNÑv2¤’r¼) •ྨ ±-ÓV­år‹ª™œë)¿�ßÑÅ:8 \üîz:ßí8!M÷d„a rùHþ‰ñ¶}áP# à¬r1º9Ä÷ìx_£�4eû¨r ÑN6âúáë ‰ôú6–’ |•±¡ÔdÝMúôÿê””þ'§‚,úlï‡;”5dû¡ü6žžAug˜(eËv'…¬ ¤ÐæïMÏ ùÊÒL|) & ªÃ” ‘ˆSþ‚sº ù��¦šN½Òi?qÐ;x8yWipK”´Õ²’ͯåâÛOÛðåu¹Ó3GxJȺ8N�¨|–k2ÕŠÒeר–“+×´t)¬ÈuýõÎOêÒ¢˜ñµVÔÒy¸bÙݳqŽð_5“…Š¡´B°œ#÷FÈQy‹0ž-Ï«ex£Ð鮋 §ìÜ?•RÈplâ�›Mª¨<ÕGÅÀ’güÛÐf5"Sñ lAÙ‰iõ²7Y*v¼ª—#Šmyõ"æh*½B¦­ëÛê!:ɲ$…ZŒ„.çïNÛ.ÝŠá fáw » òŸ²t$±›o¦±ë»ë?À2a3XÛ÷TêÂ)/ ÎöœB‹µú`.ô9d}ßC‘¸Yå+ùhã¹K%˜ï,‰’ºãÙ6Ø Ï*nsì@UArHãþf^Z=ã<:3Ÿ±k­€Ršy¸#µÈ0!¹ ÅõÑB£òlcÆÉt¿¾zxßÚèàýÖÃñ0ïÄvP¥>éÅШù@ÖoùŽ]‰ŸNmh¸Æ’Ø•›Rª®Ë¿ÍLNµŒÓ±�V&RºêÑ©Àì_MÊõ9ŽÀd£™KØ^�YZñèw±¦³˜ŒàÒ]¹ãHŽ^‰£¼üLlÿÚ° çR�Q9†Z>'p•O6îŽ%îöZ#@Ÿ…ÀB&˜Í>k ´3óã\ðt%ú±þÀ .|Y'ý.öïeË÷‚6xX["CxQ­ï½ûeû³FçÆ#=”ùo{÷ÍT”þ`/öø3D¢Ö¹†IÀ|Ë„í�ï6 ®éáüú_r¢:ßvœhX7T$“°J¿ÝøP±$Ú0ÂŽ /ÕG,+n¯Â+›Vˆ¨#I¼¨±öî`'°•plª»(¦‰º pús\“ŸkÈ Lƒ+YOÎDþØ^ˆ)†¯sŒß‰_f};Ö5FIàZ}H]ôjž_äùê ’K OH¤’¶}^z˜¿f¥­Î.ú%dÁÔä«¡Ö&ÉFìÆÌµŒc>C§Î Ìê‡*tB¶ùý'� Þê„>b$¸ßÊ;8ÙØFäè¼Y„é}¸-ë߉œ\/cÈ|¦ûîØ^\üìã"ulÿwNƒóÊŒÕÔe›kyk6K¹…3•ü‚,,)-sŠÄs™×`ò½]¿ï&«Ûœ0�auvéw¨$(@7d w útº3î�¡óÖ¦×ÕöWºƒÇÖf¤T~Î׃i"v[¶ßg\K^P‹ôfÃÇ1¹„,;§-=¯úïÎÔéÇM\–ÒºÝEƒ•xA(ZH2ì�9 u Ã�¡¢"8:ŠÞº ZDòø:¯JQµŸIÛBÚìÒψèÇÛÚL×}ËX ‰®�[x¨õR]+˜ÝþXÅo\z,¸8œ§&6å—.ZwSgâc­Q(†L‡¥ERÁ±‚¥ ýa@ãÑÛ#óŸÞŸ1rqÝμ¾Z®ÝÙ+;S²6€r¿�ÐïáˆjÝn|½àÓ–7’~*ª‚Òv{÷]úàûüú‡/7²Ú*¡ø¨˜ 9Nòºj>‰8Ò_Ä�? ™8<ø¶îÖ/ ñwL5Ãt^ƒÇôi»bÎf½ÄAOp ·‡¸Š7§þU³«EÆ�AÕ± œmn“éö„Óxÿ—ã3yhÿ)Ï?’~º’J#áØÃiiɃkxp³hµ`øýÊ,Õ@"T¹V,S•:K¼[¼ð`ÙY>èšãMµÊÆt'‘ûï0'ŸÙrèÍÂrñý.êÏzj¹–p²¤O»2­!ò2¼ÈÀ.‚x£uj8r˶#ŠÌvó2,w’%ÍT´B(ö³Î§ºn‡Egø†AWý0 ;-�ãÀ•Ÿ`óø×~l0˜ó#½/–jVLEW¿É�5T‘¢„êXµÇ�;wËzr4)üh²ÑúŸ#‚íçëûŽhìT,‹VwI' „ÜPO®h)·áÔ¸ÏÑ,©Ì:ÞJä«È‹­WN•ì±|„A°_ï6§/—ä,·¾ aÎl,.¡ÿõÓ{�ïè¶üìÏÊÏüÎqw$‚E UÇjl¥ôéJvêz^€b3‹q„Kèymù¼páìøLãÔôŒUœT}èÆ÷vÿT¹™\ä²uò¹çQIËŸXŽg]ª�!¾î6õ@u4¦œ�$�ór-Ò>ÚäàBéN²šDùc8K%>#(áÉpªù7^ò_¶;êc5"–Z5ã„çl@‰„Ø­ÀIJb¦¦@BÏïš´Ù$.¡i?i䤿À8™ÝÏëîŒ>·["Ë·K\„í¶÷¹·îK>Ë,o¹X&¯ë› ²(Û†ŽÔSK¼& ¹ðÿÂU¶1R‡[\Û:�öRY„D×L7aÁ}ŠHè@¤Kḷ–õÃx]Øï5ÚqˆA•l_.Ó]õ6Û-3âùÆÃ9ÉÏgFYÐŽ]nŽpçéˆÆÓ†WT{‚]z›&òóqá^…ï!Ãí ÝÖwó=¬Æ}_ÚJEâCì§èôÏG'(dGÿ’ÒrñBÿø`Â>í·dñîqlÍ>Á‚~²ÝJ¬É8V̨b“¦$Ñ’U4»Ñ•ÈAèhl`h|ðBÄ~@ _“û*·éi s…”枬«#yK9bR�&“ú@GjÖJ–õ€ÓG�tå$ u}Q5ȪÙÄ…Ã¥I¤ƒÉ)uEÛ°wÐ.Õ/·¥xT¬x”ùèHÒq3Ð,ƒ@R¤Íšký€®¯Á|Ä5wÞÌ~$ßÔ*ë[Htè,5¢Sa±qE΃Ž-c…Ìš|Å=òé<­A®ô^ñ%™®GìôÕA)ñÉ]¤0š!4ü(ý2ä÷\s5`²e/Ñop ½,DšÅ/'VÙMQcá�¿-,êN3ÃÍ÷ÁÊþ²Ñ“8ÕĹtpÐ-™ ú©�z×ò!“9irì¿.Wúuˆñ¤ç¢ð=L$`œæ1uYì›}i{ÚÕ>6@Üý_¨µñtú‚mZ™`³µo÷þ¥;$£«�u�ÀžµÜ'ÔJ0&+LòÜ:;s�&§É>çGž¢•ò† ¢™æÕi¦P¼¹½ð,‚éÏx*^0X@äYòä–®¯jk‹³tè,!C$‚1ƒ} 0[W¤¾xgÿJ¡MÍ'¼{GJ`©% “ %¤‘û fž- %Àn‡3 Æú€)ö;IaÄ>rŸHÚ~‘�'}�byoÚ�&Žj|y80“Óz8ê­²¨j<ÿ`r¡è¼±kAŒ#Á•ÌuF³2Zƒ™c™'Õд*­†?^ ÚJ0ÎöQ§ŸžºíïRœÐ-w&tGœ@ªÇh|ƒ�ìç·‰ô³QC¡cQË_hÞTû;�ÏjÏ“þ¦²€üª6„«Ÿ/,ÌE P€Ý~%|Mù"-‘‹¦oÜEëžÒ¾éò™+&Ž\`DÃC šë?þu7Š4ýEÐXxüI²ÆÚ©í)}nUt å´^}±ðZ¶ˆÕ=oœ¦uA²"xØ\vMä86 �á’) —®#TÕåP¡'¨X˜êE ‹ Cº¤9nÝ;ˆÕs^ÅJ“9í- ɲgWU?ñq.Z—ÿB�ÞÁ4uå%Ô°z†¨9êM̦.�í í<¾M¨Àií6� Âa¬sìšVa˜«Ú"N1^”Å3½ÖF¦— ƒÇØÄúÌÑ¡(¾ÌÍlº@sŧv,b~7Y§Æ• r¬�zPv|k›Vù}‰…1ï×ÐzÓb’ƒþÔÎÝ™AÀ)Qb«Õe˜Œ[@8.^•P”'µK²:ÀàZÑ–UTrxšÆ ÝÚÎ廪[Ï9ž>.Dz§ä±A\Þˆ_Þ¢*ƒÜXG‚–uÕÍ/:ò0Ú"_.Sò5¾ Ö1ub>s",�A²Uí ‰î'#ìW,¤ußÀ>áRƒySjÿçoy.AArwÑ5†‰àôÚnÖ@ð¿½*ù‚�^T�ýºÅâc©�Kš� ´ÄÂ…³’î@@Q¢Òu KÛ];ÆqÜû¢ÕÀké‹ä’û�Ϻ… #ØÊé!¸ê0�ÌY‚/ w‡±¶: Ù8.X�Š0Þ1¤v‹¡ÕþË£Ž–ñ>,ì.Ì%6Ýr•ñà·xº¿¸äSÓ©H(Ú>>ÌÑ®Ç/0V½�Ý(¶¡EبcDª%16Ã\›.!tç oh�pà*¾ò&âå#Ü’' FÃ6v€ÈóNÙ¾Ç>BÄå8ý[Vâf' 6úgŠ­mõÍܾÜSͨ„ÅÈAóÓt¯þ@1c¢éä˜IÞ:icbÜMiÃÄ”*Ÿ’§«kа÷¶sëÆÀ`Šò¾Ã}íµÏs9d”`e� 1³øgÊw‹O:‡;ýB¯iêýä½õ·}ÞZè4L‰Y'Wd ‡=ðçµÏ ³¤Æ�釃fdÖ‡n˜:Pß«§ BÐG-ºtÕ�uû%ÚS0J®³`;í$…Ù7-´x)ysÏ)Ë/ïC u M ¢ÈùZuæÆ ORðªvÏöâ\z6ýÃ\|q*XJÏÞ¾Øþ-6-÷ùD¹.+JÎe�ªfoeŠÏý£V¨a=h¥øšg2L=óÀ¤´òÞàÀ¡ýøPªÅR6 üÚ^KeMŰdIÁÄlÏ)#]ö¹�Òì²z†#Xé’ö¤@£ýŠŽšòº~|¿YæÍhž€@)WUðuzö¥^£Ñ”&4»s=V}B‘ôI©^0�àŸÇ5;BÙ¿ø�Sð¶á6�+‡6YÔå¬1A'VÙ‘P Ò}< ó^¹73?ª#�94[WTèù j…\N°ÈÅçn‰kï‹°ãv=’êHr·ÉŽÏKÙ2€¸»�ëfÖ®xÄ÷†FØôHµ°\íÔ‰vz®:+®ZúÆ0W´ç£“�Ö+ÿ~ ~eÏ à´Ï¥ËÊ:³½ÚùhÂjbú‘µa€§�G„°M£mÄhÛswóGµ_;X¯`4žä_eyN§Ñ©m-·ÿW»û-»’]_¶È¤¶^CHHêŠþÚͣѤ´ýz*Q(ŸUù‡ÅâÃ:º·q^q£çb;‘Q² R€Uk¥e�J™-µ¹ªÂ¢�­-¾…l†Äè™ÌaN@Ëu�ĺ+é|òuD©Ê©UPA«^µO±¨Ñç‡@*ŠÛ„v¦¢²·0ˆöxìþ¬‘Wž\±»63™­|yY7 öèÍÐO ãI£'ï¼6£FÀeUصóèŸÂ'À_ï‹•ËØzTµ°¦%�…]^'Œ¹²ƒ·µ„J5  / MíÀca3z¯:ÔqšÍskspÕàMÌÉúÕu48+€�®-Πˀ-)ÅãL�—¿î sÄ©”ŠóöÕð D�‚Ó$Ç·D3­ë�#š‚Â�:—“Ec·¦ÔUa’HYô½Vu¸¸Bùs³”?u£åÔ/›ˆð–ϼGç»Wç(дDÊðÀ=¾P> źl5‹f”;رlP§D7€Ð \Ô<ëÎýpFΗ8C +Õž û3îb$a«)× �Œ¢±ž×d®¯ýÚ.ôçF:f—ÃwO '4gT•¡½,Ò�%‘Î|Ø,½_øòйŸ$ïG¿L©{ßÛr#Nö4´¡,Ö�¬K§”K߉i5÷}åÒ%rÖ1Sh*+öwl"ö�îë s¨ LR'¦Ëú’È}Kˆ<»iÛɺh=©#³Ó#½’û°iÊTÎ úŠ1}LQ�1E©tÃIÜñ49çõ‚ž[sôÖir �Ø–�¹~ôz–L;h½éqàöðv7ßô´z$µbcñ·Ÿ½| ’ßf=ù?u�ôcxÐMöŸóýýK ±×Þ¼"]Æ+¢W–ºŽ À(TÛÇó@µ-ü�Ïuh“‹´˜˜ílïý£úiƒâå ‰B0;úœ³‰šjRA\K66læœ ÃBjÙ ®�=i*:"¬D‘ó½êåDJçÛá<Õ˜rAôÈ®çêOˆÂ|WÛÍïG‡,€²:HD v0­»5rvµ­GÛ††\Ž“,-)ÿmÎ’nýÑÉÃêä£úJAJþ�{–-램 UnÓˆ‹÷>—¦Ý9éÒWQ³÷Rµå.OFqHFÄ4àb56ô²;“PÊd<á5HD–e€ü�áТ¬d¤¬7†E7‡hÉvŸŠÐd’±Ykì.:A/Ø÷Àvå“^оùÈ)ò·0¤p}º¶ÜлLöÐÔ×þnÆZ|õVT‚ê_©ug‚´õùÊÈáß=$>M¾…±–ä“uÈrÿËk­� }Zs—�Ïüon7û¸× ~zxp¶`æ>�hÍ?Â<ôQ)!Â:]±Õvó¸áº¢õ¿y–ñäà¤Ò[jf u�®ù�øô¥géjÔ ò›£DÅ8ZÅ‚ºÈþ3ùz,#n»ñwšöR>i®¿ŒÛ´ë2U÷hïCÀ¬¹R ¦1ÉôÉ÷~MA¸>¥ ô.;|‡âv-ÆÑ{6Þ“ÃJšÐຆµNŠ$þÖ+©À¿‡ó çWã«hg"…”4ˆˆ“8Šðg§d¶'…;�å¼ìHœÀ¼¹*O½¢Žáïžà“þh¯”Ö“º ù ¢šôÎÙÔ²‘—«çä�2:þ7{­�<¥ô½¾Æ|™ ü¹›p˜—i0ºA‘ØøJ£a,u÷K°6M爽V‘ÿV'ÖI5ž3Ò;�ã,ߊs�r.gŸg/M �¯à¡éuPnW™0öÜ]`½‰ë¶;61Å¥„äžI:š×š“Eë£ÅÂÍyi©«y¢!8M¥Fý=¨9Œ!CŒ…Ó¼aZÑ×nŠ&P2[]êw'±¯þö²" æ½¢ý�_Ë~Ø2Ä< ™³nÕÌ0/×Q»$"Þê!ôêL'EÕVÎE‡)p&"›å*‘ÇbASÚ¥S ƾ|ká^»E[Ê=µ”w\ØãCÅ­ÄðÜM¢àÊ\,Ǥü8<¢8Øh¯fÇaŒ5øêËe$qcQ÷_ÞRæ³q<”¸V^¡Ÿ½¿× ´¬*ÝÉʰv¼¬ÌèƒÆRçŠÜlXÝ'pyÒV+‡o³‹è€~z�Ì>kþ>¼—vžÇ»‰qH è3쌲®�9€áa5"»hV}–AUw)yŽ{}Tï †Óvº�Ø“¶ÿ¹Ãw}üŒõ)0¨~éöØâçÁL- ln¤W›Ÿ1d/Öç[š�D(”Üz+‹ÕN¥Õºü §dbë¯pF5ÑÄnýÂQŒ Ù­_a@^‘ð©½</=î5•fðÛò#>Ù²S—”å5¬órg–µ˜Ñ'¼Z„paC¶ä* ÿQÀ¯FDÒºq«ð÷¨KßGW6Op˳Òwí:qf©OˆPY«†@#í9wE%¿&«ž+[t4ztª{,�I8I)ЊrŽõz*Ùåt|¿#ŸLKÀ ü§Çˆ«ºù!?%Ü5Ò¿ÿ.ÿ¯:O³ÊI bþ;«ÃkÛIMÔDü§×n¬Ì5røKŒâŽ05 ²c|*]²}3¹ÑÅLWÎSšòö˜Ðâ+ºØ·Æ�ºw‰X´Ö¾�•™J¯QN—§„ü"]¹]Ãúo�±Û ŠŒ/ïÄÅ­%hŒqÊj0¥e³TèQ%�àï $»oñû…såAh­­ ’­°ó�©Yv Ü{G@üÕ—~Šã3U Aùþà‚’Ò !.;†ÔµïÒ éú •G�@¶<ºu/ôn‚¨IˆÓ±ãÂ%œ÷› +·"¤o5ô4IoRãùF�%Ó­ †ì{{U-[~~%Ý«^\Ò˜~£ŽÝù/�€ÔèÜò(açès,-ôÏ+I;wd„¼اžjûœg?¼Mû¢)c§ÝØLËxhÑP–Æ€Žýõu]-)YñäÀB›¢›j¥Oׇ‚/À&…¦#B•¨’µLÑK ½—e†¬ Õ*éEº˜ì )e+\ž­!ÑØˆ:þåðŠïK‘4t 8&˜i�Qá}ÀAÍcs§ BM+ñÓ°b ¸ØÌì §pü–Á¶:r–�…Î:ý:žâ<Ó×ÄM›.å¼¶ßhuÉÄßTi0:áɳ¿s»zì–ˆqÐÇüûåT½}èÍÛŠs€Ât†iŒ”´Ri îÀY(å‹b¼BƹX·c �Ì‘ç«$zH[JdûÒ’´ŠÇ¦&¶  v¾¬´DË�R§¬'ÊhŽÁt¨�áŸêßi Ø8¶Óµ(�ã+Ê Í/úŸ "ÙŸZ+ߣ¾UNÚ‹(7”óÃQ}¥{¾[Â*ñ|Å1O1ÆHï ;Dψ=Õgê=fEô9z¼7#@„nGÖˆÃVÛÊôýç®Y•ܽäÐpo8¨Q/Sê]”œd|)�.:‰t¢�ßsο—p�SGÎ%Ø‹¤˜¦oo2®§9gA+_lƒ„}N,L€!·8мøoi) v)fòJ8¬u}¤;}¾9'r·F OñC�DÐþXÁài(A/7ï¶â +s~xg6há Ò$cÔwÁ¼ÆßÛúKßc/ 1'q3ž {© `e*Ö¼VŠÒ`b³‹ü×ûôécŠAa½ìºãyÌ/Ö­�ጬR‡÷§m¢²k(Ïyé~íí¡º‹»a^sj‚dí´üW_iŸñ°œTy¥Ô2 и Ï]ŸlfNÜ'4î‰9mPé.Ì.íOü=0²KŸ0D³�}Ù-(9˜«Ä>Ð>dÁ±ÿˆÉm³²1Ýä7ÜG›ß'³¶pÊî²·+<·-]VàÁ3@�lhAŸ_e’>§æ�%N{Sè^Et¿´Ù—eûÕQN�ð“• Úx�V79®0�àYñ„+bú½ÚöŠ*΋jä¢g<Ñ[@LE2�í ÿÉr²”F÷ïÔ}°hã¯F½ÿ i»ŠìíÇE}ø–d1 £«‚]ðàþcªl,pb½ÙùÞ{½¬pqia !PÙ)ôQò›ýXâG5ÛWÝ|ø£©t]çï?¤°‚= I¼ÉÅ�KÑ+²%á3�ñʘ�rÇ3S õ{`Ýá³�3l¨‚2?›Ho:}è}Fj}J$´�˜à¦šrc-—é«5Cü Ù�k Ñ?»rü]I«ž€Ý±öwâ7íO‰àmy¾5CHÝL£(tbö`H®ÙmÔ¢¨5NN5”ÖÙ¸JiwMHV]snêÊaº‡ÿ½Óͯ)¦€å^ÈÂŒã̵Æå@›�z�Þˆ›†Â»s£M€9ªô?‘ùÒ¬‘™?£DTMlöž¬˜€så«+-mmq7DHî ÝS5ä©Þ‰A¶wL»íOHFÑ>™Ö²¨9�2ndµ1}U#KI¡\Ñ•®‚ˆ§ü»g-°¯A153 ˆ]^ŽÈv™LuÁˆû>(äP=[á�ܰ3´9�Ãlډ‰§Î{ôìþÄ7Œè½`OÆ8ñ’ýrU­^�î¤Ü:`õÁ²£Q¤ùÔÛCía7“»’‹EÆ®ï)íň�~6…À k½vdí— Ç·S€‰öÃïuDSî«ÜÌ¡•ñBd$5µ.c²CˆýILn£®7PºËmDIWah(tôÄË¿zÍH”/��¡ú-e X3c#­rt¥oß‚fÐܸǗ û[#jÚË^F€º³òÁN‰Õfkj£¢ š0…æ1êÅ 't20Ž£xÚhòh§r£ŠÏž«p9cò[ô.¥"0Qg·‰Ç.YÙuD§WqÁHù7~y(ÀîØ{S,µÊ"`�ºÆ†_E:P/œ7Ü ÐËû8Ä A¸µl']åY¡­­ó;”¦Htö˜ë€qs—õ úž²îH�8š(e~Ø"ž7õŽ&ìÁ€¶YƒÌäŸ~ì3„uýU=Ξri|)BçH[LÚá�ž_¬1ö…íIÞ"ãZ4Ì#«ý`Þ%ºï·„‚ÇyM¼Iî&»Þè)½R!I:£‡cpä—Ó’ñOj{>È\³}R£�hŒòªéN†07”n/–OwS‰xfs –g€öÄ&\A{ÁÒ‹±E¨Ž¶ÚˆÖ7äb1òmÓ qÎÛ&Ûw˜”Ìú¼_ªÂR#“„)®úPoî™OåÓìO G$¢Údã°¨o‹�üð:ÀyÖ[¯Ø+�VDîI«éî9ýæbÖ·VeCž”òä:nC¸¢FN*¨ñ‰`S¸š!w £áFÙ9�ÄñšÕÊ}1häÔñ,TZ¿ŸªßÃO…%ñî‚ÏœÏÀT.}‚LÛWî{ zk�Dt¾ÿ…oq�]m?­[¬MõHôhƒQÂ¥@ØŸIP˜™÷Whè&�}$òì}¨§m�ן*²¾nÝ2Vʶ[ö½]¶~ ÝúŒ&ç[á¿C\òHXq®4hÑm3¨‹ð�3|ìÖ4ø°«d°å›§þË`|§ºyNûw1¯blüb½<Ý6ĸ2tœ>¢,;/Á@™É³¸æŸG0?�h÷-¡Ú`-’…·74¢ö¹ ÿCŸÜñ…~Ö¥³8;óO’„Oqa‘âŽy3½ušÝáiÌñÞA¼îðbe 3ņ{L8_œÏëÑÇÊ.¸°,à‚Ò$Äüo, _qì¡^ê;%ÐP)=}ÂÀäö<ç5[­¶°Ölûbz9òò*‘Þ~B©Fï-¤ ‡‚L�ð6¤Öì¹wÏx;…]$Ò-­’Ì fü®à2©��KÒ•Š¼‘{¿*Rgí²�ØÚO‘ bûÆo!“rôÕGU©�PwÝ”®"i!%É&ïP™£_°#Œ˜XÍ›2'iXA¯œ¥×ÜâeºÚYÂ[ª2=(7� 3¯ßdHŒ¤”p$I?„ Î? (Ü�jdÄ0éÌ'Ë�ÎÇäÔ›a þÔî ’J5šÎç×·Z�2.»Ý‘×vI-®ÅŽ�Apþ’È4^Új‡Ä-'²üc|õùÅu¯–g”2M&Œbô µ>uà÷uõg•ˆŸÊ|ðĵš2à[¡1­€Ðk(tÈo)h%ÖöYN²âd„l¨üÑ—pKvg^z7ÎIý.dâ?[œ rxb x|é ?HáUÍݸ7X”LË_ %/y9FT$zu#iz:M9‹X†æÙÙÞC�[p)ÞKñÆË’ýUÜ�¨§aFXrgQû—•¨CžÎÈÉHðe±,o¥³>Ìu£-_¯Ü'­Z¥•ÚÓ5C¥ôÞЂËÌî䋊ÚÃݬ*¼!/�ùÓUh»ïÑ0ÒõŽg{½ä˜�‹N<ˆê.á�æË˜×¹.U£Z¨Ü\#Xê^Ž×bŽyh1[OñŸÃ ¸Üa†-ëxµmëÇùÈnMjÙg›´îóÚÑObÀ"6‚s)† GáãSÒ*€ú–ó^>0w ‘wÒÌönä›s#©ô·—…ûÀ> ¾ÅÿðW’ád£}ð//ó™Â¹Ò=äȳH€5|>ðQ‘€VÌÿµ“@Ï_‡é*x€a;YÊÈØlBaq–M õYß;X8þ~Åý/mª3ø…“ô§žÓ H‚ôž½€U’˜l[Ž6³KIô^uñÏGÎãœBÞ;ÈÞCµˆ ™ßÜ;=‡75ì´³ðEo®¾g±ÚÛñ_Z½È“Œt†Õ3kŸuæþ׺þ€ÿ¯yËÐìŠyüÚ!˜¸ñHêŸ|ËCº•�ð¸ËéKxþëÏC ­28èÂ~¾(°Ê}·äÏwˆÔ·7Ȩ'¬jÏ1E=$¼n•C°#8=);I€`•b-»OvNy[£"DÃE¼CÜå :Çw>­Ü«\¯i ñ¨6m¡w/0†¼k\¶þ©Ñ- ãÕèýiîï9s¾3VQÝA-n#£Ë!2þdmÙŽ‡Ï§q‚Zuõ�¬1›û³÷±+Yä.O}þ;‹3ä¿5Å€ùø[œ‰€X}že]|e)ŒH£Jv¸s5cE‰µ¬© ŠŒïOAqш‹m|ìÅÀT{-.iZsiȰ;,eMÞr¿b‰gUZu Ë”íA»Môpw¸�“jÉ‘Rœn¤¸QMVaG_x˜9^ñËÈMÄ.ÿÓ´ù„îKvZ8?ÎÕÔÞƒ·SI¿ÀU/½*/ðûÞbœC™ñ}]]¶ÛA•7`ÅC­è·\Zƒ)Ë]'÷ÒYe:·òŠývuºV{Q<ºx£\ Õ€{æ¥}Þ8T#mZIéD6¬Í´�Hü8–��%ûßwwú¢®ºfÁ?eœc^*sËÀà0é%1j/ÑaÞ2 -0»�&ÕÆ‚,L ~з‡&x|ލ ¿ Â?ý:Ô+ÈVíÂhHÏÅñWDlatlpå½›Õ{£<Ê  f»É©\˜ìíB{Ñðº^‰¬ºÔ›÷¸�7/à /ÁQº4b�þ oF‡òiÜ}ÏÏeëÿ†IüÇõíð)ôì9�L·g²²dmù£–¼.Œ„›|Â6·,¥¹PØh�ð 5‹X›Áã/õçùé®8^¾Šá"úeÆ!͈ ©žÅ‹Ã”Ø}¸Ío"•/ŠS¯þ@Ôúv_r¿ Uay&l ìI¦Ùþ}ª¸>—–ÑC]�è¯ Ý—šœö°jñ79 WtK1Ùr¸�’<û4ßß;p–çšmNt¢hÖÃk¸DÕØ;‹ÌÖ@yŽŸy°j”âáá|Iã±^÷,_}ÊuzÚç‡.Æm¼ÆŠ–ÞÖV¸�*VwÁ~Žäï!"!¼û¿;~:eo%!õsg›“ô2œÎ©£Æ—õn'_•ú‘Ëæà} ðyà-«OŒ^ApZa¡�ûÂõsÁÓÿë�7˜m¼‚ç­¼gdñýà«Ø” Ãk˜µrÞìN@ôywð† ÐaÈär\)Ãû¬tö`^Ð"µÁmªÛÄo³dîç÷b‘7®‘*ÝÚ¸šãžŠX9[Xîj3·6çÚÁ>‡wH9FÏ) ”@³Ûwî…Òë¿U©j’Ðýœ« Å‘\*úš-Sr>Ë4ÞàžTt¶Ü\ÇÕÂBAJÆVSN½†ì³Ohê�ô–¹×Yë㼄ֿk J?¹ÿ)Tºp®þ –õÿøÇPçxÁC€6mÇè+œÏxö_p‡>˜–õdj¢í�Î\^cšUjW¾„BµÒÏyôÞyhZp€’µÃJ—+OpÛ,1‡þ‹OwDs¶x$½c."{Æ2uªôhŽ&zߢ0Õ*Œ¡yY8ëµ<öØ^ÿ&ÅbŠê/@C§ÅŠ }¹×H4ßh–ä€P�²rXâŲ 2 Ȇ˜Pè*Öìdô(‡NÛ¸„íèfw's“´o,DV8mûx“è}{*Ò2wíž6�8�»Ë·¯úœâ&mÕÌ$�´Vír[þ„3ž2ú•i]1Ê%zÛüŠZ©Ý(ó²íqÅ—¥7T$“°pædë‘ãz\9dpÞ"ºóߟ{h-DzðÒ‘e¨„%-©)Éÿœû4Sßk±àÔ\fð¤i"ä)s¥´ám››u-G­>vÞ€ û ˆÔßG‚#*~s0.�� ôÂ' ±ù+å3Ò[Û¤—üªB¸Ãöñaf·[®®=‚É"F–0Ò�ÿUl~š[-+-§ŸöŽà ŠøâG}º9$-Äw©¿…å ºöyÒ/N-Ÿ)b¶¬’yë0æ¼I!CLzK+©r„b ‹8­ûlÞ¿lÍ� þ̺&–”ã‹Lˆ­ï37Ú°%�R1 ðƒ¶�ö‹ëïÛ¿¾§Žw%ß�8{²x�‘¦Ã5œú»øÓÈ.L^שÈU$�)ež±EgNG(=X1Œ]¢Rþ²ék*Ÿl–m>Bw‰¦INÔ"–dv¬“ôµ€Ü‰By¾_Dtc&ÍùƒƒÛm\N—G¬‹°´?éÁ5âÈ! —ÙMêݽÁx¹àw˜Wj‘DoK„˜==j¸¬Ègqœ,Ä“™#yE*_ßõ¨ÕuÐ_jÏU@”d8 ‚ÚŠ.E¨ˆZgLSÖPƧÚ¥c.Fã¸ô¡n¼w8TëxNÅ|’Y÷ægq´Gpû%ëD©*Úÿ8•„` O„),ÁÙLÔTrÄÁì`!ôW´Ú½¹=IÛ¸�„Tš“lê@1J‡|FjejLVfƒ]ó¤ì€ÔWû<:¡Æ"ö@£ä£MMÃ\jZ9‹2n¹‰ƒÐnb¨Ѓ‚Úkå…)J>¹þ/=�]YÊáÄ]¾ íÐö÷ú¯6’.AÓ’a†‰$��+Q"ÆÉ]m@µzPB¡f2s¿J¤&Iäœý6ÞóÕ›€¶ Ò¡IåÀä\ªŒ°D›ø²ºŠÒ!)$4qj䮈�ΣTÄ]'íþ%¿�ìÃu1-žBÊ`SµÁŒƒ„a;ŒIÏmÄç{t‹s$#¦íGˉz¯bVw—<å(°kj57”wPÇèT½<�UTFƒ TÖÏýrb¯IÿéÂÚ×mSM±Ôu™áÂ+lÃ_–%Dcd¤þ¿â¿Ÿyç˜uùvÒÞcCÁ?‚Ñ¢ÕÉN ³kø€¥þ¹ª@»ÄW8u›¸¶XÍe鑚$-«:MàÁbŒR¶G¥®ªÐÉ%'SŸ. ëf?ו|åä0òQée¨·†Þ—]à»Ü½TVÓ*=AóZÅ7§Û¾sØQ‡çb!ÍŠ£þ6 ÙÖö¡ñ7A1VéxlÂè"õª©/—gÝy�ÁÙ™<ˆpÕ·Üòã�srßÒÜV%µÃàÚä£báŽZúT=&’rã6(Ýðx½´¹^¥G†~»žÜá4¥¯f€Öþ¢{heg;N'›ÂkôVŽOõáìl)7¨”ñëCØ€þŠ÷Íé{™¤€™|4*Œë!p…œõCG�DÿEÃý¸Ð?ýa¦v‘wƒ�§ÝiøË÷Ʌƞ㺎‰l2kði“ÿñT9Ü´ÀY&M¤¾Ÿë‹:¶Ò#êø›4åãÓääû“lIÇ“-ˆ‹,&©ÈŽ3ޝ.¸¨:ðÓ ¢° ÞiŽóÆŒ_3¾`‹3 ¿ÏH%hh‡ÁC­B…lb±]¹.;¦ß5õLëo€‘Œã­C#SE1¥¥†‘r‡æ¾ü´¨M­An›­ŽD£õ/Jb³‡º:¤Z ´Ùtœ–_¤ýƒÀ4))ûM ¼›ŽüÿÜWÖʃà™{ Úýå}­Öäº?6ùÇKñ ûM°‹WŒÓ|¥ô‡»½ë{7¡97Ü%'C%ŽÞ1¯ö›aØè*ƒjê çh 4az+i÷¯´7 –C=­m×¼àår™¡JXþ+³DpÊCIòÕäH½W�{ìi’Ø!§û=¨¶K¿ÓÑáù­Aéé— Š\t‹ ,‡Æ~4ƒd,B%0‘s «VsCBªÝ z*â6Ð�¼=ŠÕ6�’æRz­õêž[~;":”.㜮;H‰ñ¦ {Ápî ¦Ìç†ß|Õ>rÿĈKï Ž‘c¡ûŽä-»¬‰‰/˜{¦h2;.þÕ¥«0šÿª¿r77 $¦@c!X»ck´såoKÉ‚a<ô¼2�¹1oBvxþê^bÛô´ ݶŸg“ƒcoÒBdÏ"ª*|Bõ É„öSÒÿÂÞƒò¼à•ô­Ì³Ú:u Â¢Ïíåàu��T £ãI ¥]bg4Ê.,4ø%©ƒ`" _¶ñ §–H ‰�üod Ø@IbŸjßÀÇ”7ÊÈïó¾Vž"Ÿq „>µ]Âî@G½ûVÒßê÷üÍñïø½´aƒÏ êvì_�Úƒšš t#Ô¿êò•T´«©Þv�Bñ ¤¶,|1ÿ.8³9Žþ fV%»i¸œ@i\Utë l¡Ì)dPú+‡0ж›¯XÄD�œxXÚYÁØ‹)Ý�ä v�S¿ªóÊ—¡ñŒháï/µnØó`ùr(díkƒ$Í\ÆFiûEÅ-ÄHUêUŽ|8ÙíÝE`Cã<´Hî4òEL~¸ÿrÇôÕné“ÿƒJLYûâqC[òÅ7¹¬—(W'# Oú0>òzäÿ!YýqB11.È{ì &sö;°0¶üû}¢y0‹¡Úwø„½îC%p 0¨LK/ô¸EŸ¡˜¯!ôRøøL#ü_œ~jî¦'”òÜ*ÃJM¬]0R2$/ œ¢·Ï…e èèõò ˜-nG?•°üŸØË-!õK‘ÝдN«µ@Àp†¬+NK¬&UÌÿ199„÷éÝtPÖGPø¬¨ö ó ôiÿ©Å[jí�æÍú(žX¨ºìgì~ÔÅ u¼TËÊÛ ßÁ{œ¤!€TI馅©´wI—w(’‡Ë=Gvx¼j”ù\a·r-zæc±¿÷dRþQ:Ó>…àÊé}Tà ÿŒÕ‡]ýÜ�ºƒÌ³8 ,óU·‰Š€Â3"l¯eŸóü“éuÄ ¼bÊ §sA´þ*_¬=Æ\Î$†˜)8é�ô[IÞaû×€ƒåz2Ž ·&Ø#^ïKŸT¸ZŠ ç�¿ÔoxmF÷\Þ%ëÛtwÃòùæ\^ÉÝÓ¶¥ù<]ïvïÜ&؃Ž_Tî1§°•ÍSJ¼˜º’D}2¾k­ŽÎ úKàjýÖT¸vM{m´šà\P`Ø:KŸâ[ Ïω‹ —Pi_¿ØÇ¿™Wœ ‹€XWMkT)›‚ßÁä�Eÿ–JSá²Ár GŒ‘g—aóáõÐ:O�]�( QçVÌ×C-|Ì#›vžq‰ÇmeÏSBtÞPÂHéÕq¹Ž~MY3<§Q¿0…1ÎÙœ¨ÒôöŽ:AÚµ³9-iöÝÞÍÅû²©ë¥u?¯-x+�^Ã쥴 Ÿy°wß·^f…ð_âFKw±E~í/½wº¼(­´ DºÃ4³|¶Oþã{ E«QR÷nüñK2L)-� ÛPM¢^²@q¡±ˆ_‹ú°hNÐò>ÙÖ .¨W¸[JÅ|ÃfKI;•,¡Ž� õ¦‡ãO;ñødîƒÐŒ)Š)ÿÊ[±òÓ>#¦T�1&®$~ŠÞêëiCèKéaÏûÛF¼ëXÅZå¡Uõ ]f-% „Ènç ·ópï/˜°¶äXæÌD™þÎéq8ª¥„™#{–‹G~ª2œ2ŠðhV’½ßéŒÇ XEDövbúðL£QÙ„|8ytýŒl“ÖX Å®ñ‹ÜáÐÒþõ}äb.¸  h¹¯ÚºÇ¥‹6˜’ Û5<ƒ/Šc]$76aÍìz çíDè4à�‰ºtðC¶Û'ÑÍhô7}ÿ´¿hEQl;Bò檾žæÝOò¨h©~ï&Š7(ý¢bÎdaÚ¡Ð,'ÊÜç¢ò±~[Ø-‡1ޠ狼MTþ&y©+ {í7úUµ]úe2 üü²œ]V@-ªÎKo·Ù\¼>9Ù0¢Œµ°ŒEƒ«@êËj¬ú#÷¹Ý´¬ZVcÚØœ’bC 5 ;,qÄÎy+%Ì —ÎhA�®YÁ´3î­�†‚åø�V¾�t†DÉ@µh}›çA* aÞäxߢkà £…@oɇZа5øÅ˜øâ D‰¶Æ> Äcœ¾nB ¨ «­¾º­‚]é‚ò•ØÄμͭwIpúñÏ}r¨î†9z�"{êh{`ºIõá©B¦'ÆôáÑ7�R›ÅBóª!ÐÂ0€‹¶`â{,%tœÕ‹PAÐ\WÑþ¥´2‰@B>ðI²€ï(g…Á%K¾ŒrŸÞÜOsû¼þïtI-Pwé¦ ¾$!H9‰vÓUØœ�Àð{C•W7öºâþÁPehqÒ脽~Ã¥€´Yiî¸XMÚu›�½÷Ž5ÿÛ™ìå�0Y¬cXdÌ ŠÌ�Á‘ n}­û žDêäÉ/£ Ù 1|ÑʾXGU~’2+ñ£QaRê¿/ !’¢QLºŸ.«Ðn‰5“¼D‘¿#ÏÃâ‡`®Œ»kdµ6WGÁV•·éߦ@\1'K‘·Þ$êä`R9²6¬QwsEÎ·å´ÆP582¼n¯óƒt›Û í,·j§·9ôf©âïÚäU4ö?yYºa‘ÓFò™„×{¹IÚöuÀ{P°V‰¿Ø!í�»»üÄ«+ˆ® „yíŽvJð¤USl”‚›ëe†ìÆ�7ír§¡S"4 ‰Ñ-ç4ÒGšÛt •�A;™È±»\7¢®Æ¢ÐËÞÅû‹öÛБ¯�² E•$ŒÉ:RqÚ#¦ ð¼Ì‹¶ãæ²®ýªlŒãzk¶†]i+à(cè9K®}~->9ÎYÜÎ �Fwg™ IÍ׺†Â«<øÎÚgæÜƒ«àô+Œ[ÖK$Óœ‘ÏuÑ 1(:É·ÌÊ+Õ¨Ci”Ú]Õ鵯§ù·½ý&]ÆK<(Ak•š‹ï¿a6”ÈÈŽ ·@Ɖó ¼ã…zZÓ£.3ÈÉ›aý¼¥UOor ä4àǬYŒ:m•y¾smGBPïÞëÁMÕ"|§µ%L€TôêõZ˜ªÔÝ#v`ZþLÒ§‰ãí;Ù ±J΀À_�*íª$t‹P‚ïð9%%¼”vÃH˼}âÁLJæºC06>fXŠ< Õß1|ËðûùÅ!³CU)˜ä;/j�ÙoJšWxxZ *¼ÐÅýÜûšç|ðÍ¥/—I!q �OÒ%ȨÏI²¹±WoZЧ¹ �‚Ó�©ð¤|ÊÇì2m¾@4g—±ShïçR¹áÃF¸­.IܭǺ% ±0†C|·eV1çìðZØO€Êoß #0Z¡ cª�óŽý~uQCü˜�Õ�5˜¨ò&öϦpwÕâ eôsÇ·¦ Û¼_aÖCuæH('…jFÜýOX]Y/U‚Nç½Hä…ñÙÇvïaœ¿ÛþMÊt>“F�»ùÔrꃓ¼öÂe‡­é� H»¯2Íìë'ªÝåçÚ¤*;]Ý“¼É²òõªHgaœ©¶RÀ­EÁ)£šIÂÐssöèð$S vÕÌÄ’N¼‘1,¬qy™ ïûðÌêùTÊšK´ª–FÔSj¥ñ‹"~J°ó Ÿº÷N¼«ôUy$ZŠp)Ê 7ŒèÕ…Õk�²£–ûûî¼?Ý5âÂ�ÎÀQ;Àå »>ÏŸ$�+x™‡‚ñI9KÆf•L£¿37Œyýf(QvGÛ6vˆH¬·ÐúY`i6êÝ¿6¥VãF ¨†ìUÂ7…ÝO͘=¥´b:!h÷ì’<¬•˜ ËWú~ÒÒ3¿®OÚÙdÕÝ-ù×òS$z+™[S†w¸�ßc6'Î�ÍüF+ç´vZ;ùŠîèÌ~:Vaõ<Øž²;9Xü!�õ‚k‚«§»øÓè,7Tˆn‹º[ñS5¨u}gtÆR´¬ÿ;ØU ¹¬šè@£@ôöþ*�e9(³âkÏ•×òËx¥Ý7WÝ¶Ò p�WCmPÙBí¹ö6§À�¯~e¡vÎë·i"¥A’�/kwrSŒP,fðëÅÅ�bò2´Z”^¨6*ŒþuNÍ41ÓD{¤�/O±ñ6–ùªcP‡†t™Úr‰eÐ À¯ ›K>w»x¯½Z}¿T`6=ô¾Ãá|Q=Nàõ.îLgD7{*ˆ¤º…%ÛŸ[Ðr{Ë–ks··ü¥ã¡HKçz¥…´™É{™¶ÅRUâÍ­º�š@™Q²É~Ø;5€ z£=˜R�dB÷åny°˜3ŸzAf;üÂçK®ÖA7hµà:Õ£uwµý☳pÿÿßý'X­^À:Ù¹“p¹’™Ã �2uÎÐñ˜ofcf ,-)«�.0¤7r+�Œµ¥a>èTa§~3)oltoÃý‰àx:Žë!GÈŸS!Øšg¹Ê.Oý·þ7ž ÕÐ/):ͪ¼uãØZÿ…tx�ŸzWëô¯Ùi3j2hg™ IDt�u$Aä{áÜxj=+ý°[ {qÜ \gV‚´�¢Ëö)o Ô3Ú@ýˆZ~(¦¸(©Pà¸Ú!…W<¸�9Y²‘<�âèy)}äQ#¥®Ëß:ÏF¯áû Ë>ú"4ZΡj­û½YùX+žYÏš˜ÇýÃ;˜·+Ù~[}°$±ÁCo%s¬üTÌg$�Ž#æóhöѯ'¾8¨?6D ŠûsŒÎf¢1|J”Û«’«Y×éô¼œ+úp9JÚ#ɦÝ62J©¡žÄbqévs§‡ô’÷¡ÏoF¢ð¥#óþâš#D(£¸«0#Å‹[GUòx– )w¤a ˜0�Ñ“z‰‹êM|Ù–‡Œ‘‡[ª]tb|–žÆ 2<¼|ò¡­'t†ÔS`¤pœ"T<ŒÔ¸¢ÚÊ“®¿úýÓ åŨfÞ=âÄúodûx´žÐEôóKäa#;ÝÝø# ÐÒË™×5�ß tñΔM¾†kº°à®ØKìJôË£{I3t°ÛUòØ´6š¿ „ü„Í—Iq,î»LeÖFÀF" ÿt¢È\왢ɠÍlþS¶ìѪ“¦Ô]ðœû7®ÛéÐí|–þ�_ÜPåò„V*2¿PN Fݘ^X'{>Ú•ÔU�ImÕê³ió=ʾ¤åvÛçÞïK»1Kµ‘ êÜ\ަ ¦×s¦Á•C²—œëÙ $÷t/\INKÔ2&[†÷§»aæèHjœ´ãö:“¼æ½ä[‘ôbq¼ÓP€d?ñeÕ;«»y½óª …¤üBRô‹tø¿¬-¾F‘L×Ï? ¯ ¯¶)åÝ®=¼•A¹ÏÕöƒ=Ûrhãò³sê‰Ó^Yä IPá˧fŒ×]»ìºv1…ÄÛº•¨ ¨('“Í �pc‹0¶c’ÿÑöA!�dDÆyY?SGïd©Y�3}ˆüH°È cË×n²S»HuËË6ˆÊ5ÍìÌ¥‰4‡ò]yžVW´ Aâ¤3¿k¼hg�]±p'mºIþ?®¿ðOKY¥ÑñÄßܘôt–ÈÂÛ;…8ÎR âÌŸ[~„nëÑ»`’w{¸Š²�Z¨»ÓÞê�è*mÜXÏ 34ÔFci®’t¸Ai[élfu€´Y…“ÈÏG# �ltJ-ë=Cm`ظ×NÍÓS‚N�%èdwú?tÑ0»iÜ$½ëÜWà4þ¼a¸x’ŽxÚî(ä[v®ö0újû ƒ8µ}$AÏ9V)†!Ã×!ExóÈý0æv‡Ä1c(ÉW�)Y´Z¦…æKÈYš^*Hs«ú¨^;®¥¼i¥|c0¯×F¦tEP­á²ÊÀò÷§Ýha3#“ä‰:‚ä"FÊx(°'¸]” –ø‘˜L×=ØSï–@\©§‚½Ú탗më»FXz¶õ\:å¬{ äbÔàÀ†BpM„­2d‡Þ›�Q1×M2rüj‹˜gÔW™«:™Þ‰>^h7;";Öhp-{QüSöãjÍó(×(Š<³~Öñím¡!t^˜Ü0jî+O_¬t�cËâfëä[·¬G+/n5Ã�.K|‰�±Ï5D$ÔÀz¸³º4k‰,@0Y’a½-÷ªJÉœÅ@3â4“&Zqâ voÉÿL’¯CÉüÄ.çdÎ�ŽSó›NJ.úvl”ä[ƒì­¾‰±Å¼ÌÔE<©ßʉ’´<9`.#%ØèÙé<Äâ`²œF{µÎà&’Æw/ØõI�l�Z½_ñ«–/€�œÊ²¹Åõ_QŸí¿ËÍ›/íðß]�(!Ëb E>ìùëç°�ì˜U¸£‘žƒmHO¢€9ïgN¼P™sÿI¨×ä^ïßÅÃ/ q¦§f=Óùó£†Ùå¸ewÇ*˜n_š0[g2gâ™-�~»rUÌ7?ˆcc7Ï~Þ½r®N¾ 3©&ð­Ë™î¡ Äx”�0p>ðni ÿ«=™ýa]²]Ò" Mñï¤ïRV¨¥íYÂ}ÞëM"E-´îF—ž^E í'K*§3œÃp�†‹�Œe•içÂå[�fNgZ¶BùÎaÉΞé= Vú¤PÝ,O)™qòÜ ß¯7†€¡Öß„¹îÌ2£%ýqO æÝ�±ðH!ŠÒÙ},›f›–^µ¸"Ý&}~r�æjY‹W¤Ü• kÑ�YVKö�ƒ6+¢Y÷‰]²˜.âa1µ°EìgrwÆÈîª}çáᇠqÝH·¶�÷Ô×#Sd¼êÂȽ‹‘s¸:2qFF¨]—xÜpÌŒž|´Yµh V?,­®î³{¿ÃV;(}; �ß(¿ð³pd|j7�;Sƒ…ñrk´y¸NØgø…>-gH;Ñè yü^1 ×?ÙoÓÉ oyO]ô¨oñ ¢‰<`/Wr Öçg²KKôÚy*Nõ�%N”\ì¨.À÷P©åv!1+½Ç�5úM—2Â÷Öú‹?ò¬ËK¾Ÿ631uOðø×ï�+?ÂŒ©¬ ‰ˆˆ6ò~ÝIþÔcÍ1Q²ÖÂìa!ø‚ÒÆcFñšÇE4ôú¤s @ó¿÷h¶°–\�¦5!d„@d5h$ä=Ÿÿ%è… (Ó<Ê%´LŠFóU\¸îöb±‚.0æ_ޏ%ݸ$ø)Ñ(G1DÍPè÷˜�Î8wa¤=5í#S;º!¾ z›}žxAõ�_áÔ= 0»Ä.à.íࢠ‚(æ6ñzTtœ ,Þj—Tx0 +Þ7òàŠšêLxãòÅëϿĤ#ûÈ•a\Ú´tÈm?èé=&ÐRÞdz¬ò†OqB–=Óÿ ®)^@Õ“­ûccF;Œü=¹Ó¬t<°V3¬ÅrËÐÁ)"rˆq#ÍPi[I;|}‡[¬'ò¬ê1ƒl[0ËŸÊï0aõ�>œúp •I´GÑUÔq£âŒÙŠHƒBãÖ;„!þ­¦§ÒÀq�÷^ütKð]t1Ø¿Ë�˜m¹„C»ðÏJ[c0ÈÝ¡Z“~ü¡±~#%ýQ(hå<“—mL4 �Pª‹bF‘Äs9R3î!áÕí±û‘Œû¦²,/ºµ³­x~•höÔÕ»¾xyãe$ÎC @/hÛâ'Û{{ŠÌÖ4ºžî ¦”•yeåV×qRÒ´:Îý ÌOJf�ççÅó<8à CKÏ5sÄ— Å7ºYêw"áE�RŒuYâæmÙ¸]QN ‡Ü@ÊgK½äèµ`{=K†çÿ1ÈT ²råÀ2} \ Ï£¯˜ÙËPßQæ†=dÉ&w7û{e  œøñº‘hϲuÔUæ— $ ³pÚÿ÷{ëÜÙfšOHU‡ÛÛ•Òž†qê>b®¡yvcª'‹‚f¦èŸ›(HaHüZ/~¨ù7ol“¶ÀJÛ>òCðBj“ØòXç­t‘¨ëkî<�/„ùŒÄçº% r �OõjÃo�Å¿ÈRá¢û°©¥‡YR^Òß©™»L>þ0\iâ �ÏÞ%ˆçuj°X�†žIg$ºœ’oÐ,M¯r�‰eÀøŠþÀ•¸×St��Ú|û ¦ÿïÒlúAýÖV]eóG+XnÀÔˆá¬ðä*ñy€í–ÁÛYHÏZýnJ�µù4Aå@zñ‰^yéÍaÂî‘5YwbúÁ ²ÀÍ¿äN|š­ah´ŒoÛçÝÌR�‘,Ô¯ßk7u3ºÀ‹AŽäôwÆNŒ½œå“ÖñµéçàÖ“èŠT0‘Ù5Û¬Á©& H<¸Ÿð…ó�s¦Â|¡7†)ìÝYoZz˜éëdA¢Ö �â’í= þF~ܼÁi¸ç6üþrøá/…ÐÒ²F¥Rü&_ö•#Q–8ÎŽõ×€Á\W†xj/@LÝû rïïf@6¾XÈ>±¶¤=+Ñ6aÀ:§½A€ QÖŒ}8çõ†¸D‚ß#ÙEвá2õ’’q·˜ìù‘õU»Çï ”L8')�wMê¦ËùBð’’Øöcþ7v{U6¥©ƒáË*†zyÅÌWÐÖ$ÑJ(ÕðÁ°-ÀìàÛŨ1ú02‰j+OëÂh,_Í ü¸’P@©š¤´ºC°ûÒ§^�Q–<@E !ùã«óèF¼¸¾¶.+ƒ�ñë�K2Pw¢FŽG=ÐìB� to æÂjŠ÷2(™Ó¢Tt†d?q{ŽxH’8Gÿº†TqŠãÚFh7¡ŒTÖb¿tâhZ7bÊ}qÑÖ{[ ±€Š¤Ú8Ѓ ÒÓÓ‡ÐÀuì×0ù3 ´rÊtfüAÓjV4¯«büSV©-ní>l\r`§ÔÙ½}ŸØ«#(d÷_Í-ôÅ\Ú5ÎÙe脸ª¬ ò3wZœÖ$¹lú~Ýyýè ™l ’ëqößæÐ=eE˜�-“YpãÒ<@ƒ¯é³Pˆ9ã]õÎʵ 'Ÿ1{d†�9¡žh޾Âô-Ëw.¨„Ü/õ‹‘¨d€›ö/(m†�I¼m,ñ›Uœ‘!5yB°³ �aÅ™(•^rvéTL€«Q ÿ|ðxí rů ¸ýc^NDu _€Ê÷oŽÔdÇ#™ª—-"ÅxüFñ:ÿà¼ÎL2ÊôD“ïxÑ—©”gÔüÂåã&ùßOåµ+1 7iV4µÕápsa �„¥¾‰|uó•WŠòU¦}Cë8½Ç­é˜VP>�v;˜™ò„-0Â+<…¨n÷Ã&÷VW Å로IXäË5ï$�éžss°oòô–ˆ/ª›ïx^¬Õ™8^‰ç¼B†|é�Zú²D¥¨­¯Ðhñ‡xÁŠd5a°ßPh$M£K ?px�F2ƒ?õ4ß±|P¡©ÒõpY–¾EêëX~VÄŒaÑ6n•¨×´9™\L蟸U\,Y#ÿ�gh™àVNoÛWvÌÉ�ýÏwf{Åë @‘Šîµà”–ø‘¤Ítï–yWùëŽUõ;ïo£VXRÕ%›�’©pÍt…Ä5$c^=ê|ù†®åSdÌ2•_J̬)ÆÚîŠ?2ð5`šir'z))ÎçNE—|+¡Q½>Är:¸}D$½b9£}hk.AïóS ¨ŽÐô™AÚÎ3hçÐ6Mr�\BŸÿÜR]½M‰^¨c—c%-¢òWlv Ô.„�”g6È‹´?5,bú$î;¨Å’‘b{D|wLv^úÀ˜zï(Äâÿd¡«@k¥ÖÙjEH&QQ£HÀü­ B}Š€¿RÍËì ÏJÓÁè•ÃëåÞ…öýĦZ ]©EØñ·s½Ô‰þù:£ � aJí)²¢H^ì ',m}þ`~¾ú¿Ê®_¼& ( PûžÄ�’€Drídüë½7GÞ{C‘jlJ[‰–Nlm¢ëô:î×I/øðÇ�%á¤Z,bÔHXµ‰Øxr3§s»:V;7­-iŸêD/¾]m6ým¾O‰ˆF»ŽbÒªÕÞ²7†Æ/åØà@Љe£]ÀrûÒ´1iX±N—97únVIk,]öîªA6w‚Í­8· —ï <¹ÍþšÌ"JÁ_ …Û"�óû_ÿÔ›˜ºéSÂ½ÒØ™dÄ4 ¯éQjúãuàoÿ¹0¢¶3c’ŸQ'Ä 5Šm‰¤ÛÎ]i¦çÐÄàÒgýTêPj�û·ä)}ÐaÍŒmÆ È-tV_v�ÉøK�ánñpeTüLÊJH6”צ8¾DIÑwáö?Ÿ$…ícƒMb¿mË—†á8Ó¦GäŽùjˆ4ëRq]6ô¾Ê5¡Ÿˆ…]FÙŒ~Ý,(9=ÌL‰­¡f¼3K”E/²>›ð©&rœlLN`‹DtvÇ Þ°n,mPOD2ôet•ˆÒÇÈöœšÓ"­e�VÑm¥:ª2¶€[-þ)©Tø9. `RuØ—µ¶D3?ˆ_ KÍuÝ"ÅM©*vv5c¯ÔJt§=Hœå[v8ÍUäÙôÔ¯$Š È�ÜeQ®ÎõeAS/ÐÔŠE±ÑÁ™ˆ…¼u¡û]JêæYÊ®u{Ô"%'ü6� µZuö²¸¿5L:í ¨‚Qgë¼y¶ýĽÞþ`¢ƒØ—sÐÿmùU¬zL<ïÇÿfŒ]û´¡šÎ½êæókÇô9Êd}’W�H'k}l{qFêõ¶ ¢¹§IùSXdÇqìÝ¢[ÉgÏòTûñgìFFå£K€9}Éq¹‹OÞø0¢qqSOÈzThgUOÖ9>ýbÙÈÆ²j—‹>C~lŒVGšº¬×ÈÚçõ+@ ®F dvÆ íöªËâý²ej×y&„§k4 ×vÐ`¥Ô�¸½ê%c½š9ÁÓ¯×Ö¼ /K…ó´ž�»¸Ì¦À -d5¡G;â9йq«Ö”qή‚âñu€JøHÝÈ Lr{o[Ï(¬Ó°Å¶)"xZ¢#?%GÊÙÈÕ/KaË=7z‡vqâx·(Ó³€À‡bñ\y°¸kðæˆ CS×€UÚŸû4w¾VÝ úÏx;#ò¦„3žÌ£´ê_`ÇÞ ø³�ª`!á¸L ‹Ä¯&0‘3ŸyNi\AWà£O­“¤)ÚTe£Î/0cˆ¡àjªwByO»ई,KÉΚSþÆ|WvÖbŒC;ˆ|½H²éï¥ï.·«…õ€+è ¨p©ÿõ'›æS³ÒŸ\HŸ„^4†‡,×òø¯:Ý¡ëòCs¦,#·Þvn=Rê €ÕÕy˜q³*u_)µ2£¿åѳW(-ÐD·:þ>œ.¤Èñˆ%‰8£ö†)(‡5.u§Ä5Í™®«\(/›WoF ÛA8m†/)±Cu×(nÕÝ ìY8`ì"&]_Õb _YÜ_ªùE-7ÐÝÞm&D!e’WèÑ)°}F¦ïOÓî“H^Œ -ïy@P±É{¦Ca(ß’¼Ï°c¿X‚!Jßà÷¬ÍëhÁPt5u2Û’LÂlßÀ:/ýÁ÷oMEIK± s´šZ¡9ßèëHÅ•ÍKPNBeϹÁÀ}>tü’«Ìz‹B_äjñ’pÖzŽÙ®6èd¬Q ½µRSô”I{Êê9M’žÐDó}éÒG„v_¨�aq×qº �§ÐO{DC»�×CÎÉÜñWP\ìÀÐÿ¢J7<ìgRun·b-.‚©”Ƚ3§ü/Vx]Ër2ÿLºùË×Iöúô`®Æ-»ú~6ÙöÑ$Íü¦bl!çÈ ¦·áf'ÃX;>��‹eÏñßãMO4¨!x9Ù0–MŠþù9F¾Òˆf1×Ê}•¡¬_©k®¡éc¡ÀÕ,‰�¿Çzø¯�#_N< 2¬e{ãä•`0"Á<ËŽÉp ZÒ úáwÃíxOµÈtëŽ×ÀQ:ßTt\Ò÷SÛ9”ºvؘyÀ+õnbý«“‡ã2øÒÎ_AÕ¹3xI¨¶òG‡¶±â9 zÇ»‚) ±Zý9„ 8µº‘�ŽNÿèõJ˜Yê˜C:L@ç=ªû�¾UÖ}EÛ¹°‚u9çÁˆÎŸËÛ�»BÛNLI8ĉ×ïú–?Yƒc¥f©A ²%ìðã·&ëz”–6xl?À¬ýIÄ[üµÔÑ%_€ö<¨Ü¡­$ë•ò@5ÂqaŒ¢Î·Æ¡Ö®AYå�ÅÀõz ZØCf{´¶ˆÛÚ|w¬|¥;Ôð2óä0JN“‡ƒM1qgMNp#§!¤Bœ�‡Ì»þÔ�ŸÏ2Ù.ö`¢MÏ¥sÃu’‚ —¯èÝR¨D—â?Óü¸ �kC2@+&òÔXœ˜wú¹ûÂè"dÜúðЄ›‚PôHÑæ°J|Ä#“Í+v#ÿ—“ ¨l%®ÿ„¼¥òFj;²çOŒmòL¬ÐŽzÒImMM!i™´^3ÈÛj4ôtÙ6 c¬:¬5Åûèñ¿ Ÿ‹’©øyžRhOðY¦|j \_ùÀ|æVSµºÊ¦0ËšVkÌa'ƒ�Ø€š�õ}ûÈZ:^—`§ãX·êSgò0(%::>c¯¥›ßyì�°ÆPuŸ–$k¡¤�ä¤IMrÙ.¹ÓÕ¥¬�`ãêcð{[N* +ž¾,-•Hj3ï±~eìÿ·`—7Ž©E.*|¦'ùÏd˜®ŒcÔôŽ\è±VóÆïy¡].JhYQ„Ͼ#B!>=8O€9ت£Î•J\$ˆ2q¾2ëμa¸¨L�ˆû ž~©Qн�ø;d3Õ*Œ¡Æ$yVjÄÆ$ù2�5%ëBKy¸“Ú=q"-Ø×x‹X jPç¬äö-qZŽ@EUB„¨‚ €B¹×Õ]Á: ’ ƒ3Î~­}rä†\Û¡ñI­‚)&üêó…VÔúÿï �¡�´®ôe� àõË5¯A>4üó<+Â¥öƒFÍz÷Îà3Pkú ÇËv,76ë6Y¿d„½°þCÒxcÒq n p_ž±"ÎÙTÑh ‚a�¿Öôže•Ú 3ƉBœsš NÆd2Ãr­§(:î¯?Þ*LpÜÐ%¼Õk]DÔ£wE ´ë±~ÓËRa¹|¤18¼x” ?7àñI^V hº <‡œ›É”ÐGû%ö\–T]ÊèÜ;÷ù14jîŽËa^ñ¶Öʘ;97a¶ íbú$‹™\èâüóMõ)´o[säõî:'µØƒY^j�‡ÈÁŸÄ56„BUTÏ òÓ(X|òÎ<#“¥Ù¶˜�‘�¤ÿ1Ìå=á(]Úc¬Š�ÀÍ—°Às/õG¾n 4«kÂÇnú+ Ö'òÙOvWZ–i”åbkþÀ›6“a�)•ôÑH²Ðw"Lþt•nA¤¸¤“@/ïYGµsŽm¾€qG×(pª�dçÝÒèž«Õ]>¥Ð-CÙ;¸ËÌ�p®7¤ÌVÉ)^âO[À¡wšþžØònEºÒ�úI¿ Œö� YˆÚ8•àFHàâëË1eqÜÔ?§}­{H6¸õ‘Ä¡ÿ¤ÕsáÝ„8Ù·-ìf�Šù?£µ¦AÀ/BíæÂ•ià& ×-ýYØ+�W‚-#Ûèö:ÿ×9šçωñì}7æ6̯þÕ‡¤E¡/Lî)ÿÁÖÎ~d.‰]…]"ÆÈϵ~Ì‚Êw`F4¡¿€N»ƒ$¯;�Dª%¥# {ñ7ñ+;Té*+n¾ Â�A �@;×ëÛr¤¬JI?zËÿŠKHK úÛ| û3Ö§&Ä«hš©,ᘀýù‚È™È*]OúÝ�Z£•S[«ù ÂoÅâkXeÛ`C^hˆb Zþ-×%`G*Ó:�ó8¨ìÝ;´*ä0Ö _ÑÑ ÿŸ~ØZ0Q“ J¹§Úéä&¦›‡\’£Ùt³ÿª2š½¦peމ¼Ds8Ë>Jˆ£C› Ãì¦4+I$áÖi¥o  ÚDýÕ ÁüL�…Ÿx ÒáÀ|Ü9ÞNÆw=IuÈHQ«lñ¢L€b˜ö.‘É™zQ1áT.+ˆM“øpÇ.~Ì¿5/YóÉÎFfbPßPÑð{ÆPŸé7&È'ÜdÓx€Ìå ÷ºˆ֮ü#Àóiß ‚.Z�3tÚhÍCâ�5AËΗãhøƒŠÎácÑ� hÜ.ñ°&^`2‹x¡ì3pš/[` �¢í¼÷:1xðEsœ‘¦*S½‡¡Ïâ*«£STûÔ›/ÐŽ)¸üVR _IVêÔŒ.$Ãè#1-¿LsãF z�ŒLÔª³‡l<æ|qÚ<¨0(É'½j^ê´Ð8ôûë:V±Ç[®±¹»ýE$sE�ªÐB|³öŽ-K,szu¼èϦ1X§LîH‰°^M <’Lr «¿ºãwæyù¥ø*ƒÎßmÈÉý.+½#´"ËQ¡¢~xzìÁ&‹»<Òh¬ÿBl{´‡™©—¡//´_£¥;ÇÕÌÁšeÖp„ÎýÌ(•%–ügÎ=¤œvœQ÷l;�æ“dgãŸ1ñ>÷´&®µsºRZ#=Qvðiã”÷!™N?.š‹ªS�-N_w„Ð/”„Å꣨Efï ŒvË·ÔÊlú7]Ú&RJ(àP'›‰ ï�ÎG½ÍÍœ¡4["A‰ ³ñxPBäØNu5r–öF6BN>j¤a ˜3óØÞ§z´Þ½F¼N⊄Ôr½—9T³º­‰¹ŸQ(1{‚á�Ï>CåiG¨!j³Ý2yÆ®…!øU",”ÿTºì‘mf�ÿüDy’¼!}[ë.'úƒW …3Hêùˆ‡¡‰å~Þ­fÃ&ÑØ‚v¤íÙÉ7J?k²ËÙÙ¯^/èkáLù5 é¾vv’(¦eþ�Aaˆ?2$e~ºP+ tlRävUŽù„"¥.Ÿ¨xË~üURÇï1ohJ0ZdkØ)hv³�{Ÿ¾[H s£\°@éñÖlOEv B�ØKˬ¶x×e…½²ÜFµ°£rümY’r0âPv ‹—Ó³%Íú± FO³§.óÈs”x2ø­Ûî\)Q´|UèO% -‚P b“\Z[ˆÄsÐÿ%ÔÛ§BŒ­K3ð£ÍêÁËk�`álBªfUñQ&õ«àl¾Ý¡@ŒZû �òu��;9AþGùüpÿÕÈÄ“ôõ(gؼqýa*[\�m¬˜ÞZ”!�úíƒi¹]ô6=Z9í”Øií£¼øj}å_fnéã�p²Sñàw†ç‘ù¨ó˜~V¬þ—ËÎþ˜Îó.í¯§mlûx.á#_u‘üÓk@^E}ÏlÆ Cƒ�{åD# Ì-°}í–‡vu&©gPëk“®�ŠæGmŸcJ2*7ÁŸÞ¿Ö%/4 –{¼é1„u eÉ»tí++?´…ÑÀdÊõ˜ù¶þx¸o‘m„g$Z ã(0±'íÜ}³�5†˜E®yëÃGù·Ë^6ô æ¥)L\=ëeïÐX½+¢Së£9$ÎU9`6g!\B ÑvúM}~‘6̨&L´’&¬@_X!E߀¼Õ¹"œÞà ^ ~»(„`" “_9:&‚Õ?°öÑ_Ž s³2÷ÞœqJ˜åðjGP»HvEÊõiU Óƒmš,³À�ˆ2 Tº�›ÀH]ïZ¸Ý†*°0Ì^ƼóÜhÿVð%õZï|ô9Ÿ€¸èš#¹W¾€ñOXv_¢8_Q2pƒž?+ ÏÄ~ÃdY—ÙÊ=ÎOß|’7/6GÒ­ea×,œ÷º_^ÎìBQFþ éSo ÜP‚[ ¦à /žòZ(öçy† kMñ�ƒi»<ÆY_¸|cpv0@ûÒ’<z—JüŠà;}M £ÛÉ{mŸ{[¢ÊNV¯ À¨pŸ?çÜÓ“féEàÐÀã|è`Èv›r-zÉš‘ ¼ 1JÌÔÆ+5<8Ä}¥–”š7t0¡p¶½Ödhµ¹�T¯@¼±%fÄÔÀFZ9G_Z¦Á·„°¾tDl†bðG%ã ôý>´æé¸¦!±âDšu&7mÆþšæGŸ8�½úVáútœÂË5%jð’#²e‰­;­Í @–?�ËjV ]üJÙž…ë©VÐZœI€XJ›7/ÞÝ”é¹2UµJ¹öXŠW(³ÃLT}’‘¼®Ì/«iá½2±ãpã£ú_/M§5ˆƒA&æÔùdNŽ�ÃdÐk³ÅCTn8}ž14i•¢I ŽZv¤Ø-<”_ O[®³þë‰ó4ÚÅñu&²[?„±ƒL⟡›Ü�Ï\ú<è èÐARí‡ ?JóŸ•çv›»(…ï#\§üh¬fß�‡Èg¶Ø¢4ðÊ:à~_£p(J 0zÑ>¸16šjµš¤X-Š‚j¯ "È2“côôÓUþªÞh�•¿ŸŠÞð¿eyÙË©JuaüÏ ´�"�3˜Û¢ÓCßå+à8g�`äšQçØåQÍà0}·btƒöÇ�¦ mRÓ$‡s‘H Ÿ/Žf 97�(çÙ¡ügÆ?;|Ä[÷¿WÒ†÷K·„Èè©2Ìá1š{HØ�š"¸„DbÈw5Ë\Þúa<áv$¼«·šµÿP¡A <ÇÍ ‘žAÕkÊÐXû_S”6u$ÛCNû"�æ_†ãDx°Ãµ7®vpòX9�$r-P a«¥£zö�×¶d¡¥%ÅŸÉÑùì`Dùv¿ÚÂЗèauGο햸¸¦l‰¥G´}0d_ä{-ªúöÌzÃ[öq6º®´íò ej6üßD�Ï‹5yOÔÛÍå‰-¹gª ¾|Ó} pÙæ^§GçÄö$mÊ5»OÀcá -œcǦý�A#…ƒ °%‘Z¾o$÷ƒÕ�ç²Fa½ �µvB¶J’o`O† kj-⇢2Y™ÈZ…Æ„�ákýh9&•°ßÍ®™L.®y'‡ÁäTîCWJ†âHª½¶°Ä á~:Z�Øy‰:!‰�Œ9àá ßUí*üpJ1‡ØÌH¡ô'} £‚{¬˜ÿª�ŧH<Ô€‘0,ÛXUÂCÁk‰\3Å,äÄÜ͇¿½€`~$ ­á¡a*Õ°½<}[­€DùËÖ¡€Æ½à…s•`¢^êØpŽZQ®Î„�EíÅÝ’<ë…œ\§Õîi•Ñ\1)Õ(]º ¹„®íÀØ:0â®ÿW ¶{zŒ-yÃŒeÕgõ޽¬) —ªíS[\ÞÖ¹†ùóˉ(ç‰"¤Ó̞à )]Äpso§ó2¤½f×h¿[Ü`™]›mW5gßøq§I Ù ˆWÇç–©z‘x»?ÃßèÜ×—E™j¶•OáOe}›žiÞXHÔDã”ûY†ùÚø_=›• ÷ØŒgqÇ”Q¼]a‘'XÆÈD!qŸ1øBn]'P¢Â¨>Â;mÛ¦û�=Ä5_!ßI•ñ5¦ `“‹>ìý—cÕV`º eðÈß(NÑaQé°¸ç^y'~"a´�µq!Çí»»¨¶‡°ª»Ëì+ËiÍ9ÎH ;óÙ9,Ú²�1\lO瀮QÝÓ°å¿‘‘õg_‘…¸R¼âV~{kb¿tõZÓQªIR þ;Q)^`ß6‡aBä�Üm観¢py™AÐïï˜â¤7ÏÂw}¾Öù"¯›ÒêD^Õ+ "W²©Øô^á; 4Nòþ™¾´ZT‚HNáןb~lH…9�¹`•¹”øƒœ‡q«„cŒüŸKþû-px|G&ã÷š¿ÖìÜÀúážö¼d“鄿 [Lö•x–æ¾KsòYaámaf[O1.P-¯àvSjÀ¶v‘$ïSÒM?w³‡)÷¹ "ëHQíÒ˜§`n“–V,¬ümÅê´KÉYµ gÈ-Wj!| tY”�½Ý¼PÞÄWf=¨äXÉÕ~…TŠÉ:SÁKàÛÿÞ4®–ò.�©übm%|O$w²›£Ë~v¢O?žÖÌÿøŒlð#B3cÄWu©¿ÒnÍIR2¤­‰ÖÀ°*å›ï+Èä…g)òXm‹ "öØó§Û Òñ.oø Ñ•ôçÏÓc�ó6ͧŒš›–Þ9†cìAs.Ñ*ÿ§Q8ÿJXF��ð0h�]<<ÖD”o^á .zá¾Ñ.Ö—þLäFe¦R›ñ¹ÞÉâ•Sõb.<žó3•Œ·K½_{Òc‘-ÖœþáïÞÚAI—b‰T’>@Opô$nøÏ`œè€¯Ó%¸å|¸P_ÊÙŸ©Ný?HUM)°’¾dèôµ t*G—A,œ2–]µd]KÌÖ)ó_·ì–Ôi9Ö$ èRlCc/7ưÓb4‚Q¾ò£O¡ä·øuã! UßID�¸»÷FÁÚûfÁK)ñ ºÌðX�äH¨ªYóà�ÂÉé¿ ·D!dÒŠò= FPZ¡gß”g6æ#ûKæöòÕÀ½Œš–÷2�H~“Yit£\¼øÞ·®M‡¶FÖ�à׿凱Ðü¤`z…¡§ G^­V¯ÈÛYR¦§�MW�ÖQÇ+u!Mvt½"o´’�Á¥BÝ VeÉ‘ƒ–"Ì@WÆï9çSÄý"f³-”ëiÉ)¨ŒÜ J*Àµº´~öºØ(B­MäÉuh×PÖp¥~œ†5$¬”« aøT¶¬ƒ~AdckùÚ²øÂl®É:WcóZ�3Ó " ®£ ?¤ ª4[dÑÈ,ã«k �$-H»Œ_6t�ÌØüÚsåOÿ_ëlÀPùƒO˜³d0*’µÄ£ËÄgq_cÙ‚ïu–¢>˜Êî©Ðqõ:?rÞ`È]Ž{ýÔuÝž….u¥¦GÖ;tÑß®¼_r­ÁáÿP.$1ò©âC'×°’ž|éG¸ùVLKK„Ï2(éeÈ Zr™!QUÞ™ûež8…),ý 8öÉœNTB²ÉM»pç¸Q­²Ç/¶ÜT÷îÐCo< ØêK´½ÕäúŽú¶Ý¼†‰Š,d@¶VS"gÞMZŸIeÛÿÄËlKíµjô;�,óØJ\1Y9·’ÜRûÁÍéü;õɰúc>­Êýü03*¨X{} « @ÈgAÛÚΨIcï‰dO†ÅÕ%ø®7ûºÛRi~y ‰~¸&£òà`:œÆÂR„Ù&oU z‰´?†‹fc�…>ºPÊ aJÙI £:®‹µÒeí•ÅLæ^ÑT·U?ÿ$÷¤è½r—ç·a‡^åKiÙI·rÖ i�*Cm}`Œð6šÙìþX/�=µ¦�3,:£ ÖåC�Ä×û<—èÒ–¥#n~—,w½=»M�URFO¤w4²Æy~ŒëV  ¥¡ ×ìã¿.ý3tãÁ„‘Ùý&q”[9À¯]ütxÈ›#8“­¬´7>Û”¢e½ÅÙ0vY³‚Õ˜†�‚o–'ïê:Ç;à*ó0UÁ)4éG,‡hŽþ®NçÙø;꜄oíG�¯–‡ëé;à¬R$“ÏM(Vcúm>ø�óT^·ËÞ‹r–²&KÞ9Ö ’ü·­ƒÊ¾ïErêÃdFHYßë�]¾ƒX¦N²ðÝ'§•¾þÜ£ ªÍ¦¬ØNü�/™é4+ îj:«‘ CtùÕžÉÈ9²Þƒ•ËÌ�T‹¿ fU�Žut& ;HºÚ'� Ú¢¯tV�Ì]ͪYnµ¦;¯³¶ |Ѹ³5娳À˳Ygöf“ÖâÓØK:)ƒ)^&aáýÙ§[[ˆÕÌT µµÂXTÄJd¬|öÇ]�´C‰)Om繊fîQ˜ŠÉtdý½•Â4§«B¥hn<“ÚS'ײbß—â“&ß·ÞY2ÕÎ"æªÃ>ÀÁfâµ]+vš YØmM?ùOEÀ�£¯·@µ°âx^¦Ì:÷!)Ȥ]+Í®ÃÙJêž�Óh@{Œ¿’ú¼ŠÏ,2-…ุƒ,[›V„Oa®Á„FEùÈÝ*yçþæeF[î÷w¡‚Ãä¤Ãÿ…,…¬ÆÑb®&ÎLàæ`\ú%eR«WºæÈéÁ\;UÌ vR]´KŽX±.Ññ•Á0kÁÄŠ�À?bq~ƒ#�Íò"`ðVÔ¯üf’HÕ�Ê#ÉpiòE´ ¬¤íiË–™ëóyÍhü„öØä eE3Çæï0�¼²UíK7¤òùÏšÒu»¶D[×Èp–}*ý\ÃŽ“nt´Ì™gU²Ú©â{y™x9:¨�—‚ §¿‘SIË�:ïËå› )¤Cb¡@ŠïkÞüšhWdžåå²)r›E Q¢ËQÞP�"–L¦ QîÖ]"M@HBhÞþÌ;É6ì=292ô³ÌÉYÇm5¤Ë§jSMtx—?ƒ ¥qC�µÔÊ©d3EŽ­®‘cPÈeÙ¸�fd¡0ôÓ�óP/yv»®sè?½¦S*ȈÏûýŸ{f{lª°&îš{D š2S›QŒáè #|m„0òU˪Ø©æ.í¶ƒW$>ô;3ž  > 2ÏÀþ¯ 'g5Xãr?š2¥è&«Ós8'^ês6[Ö¥Q2â䯛3hÂ_WÀæÓ§%6eÂ…¼w>æ(È�.J ŠtzËòê\À¯ΪÚ+Ë<£ü¸½nLáašðn/+ y¼C]b+~7šxúë® ­ún|µÚ^–-–º|¸‰6©¢feçbv#À6 ô:¥©ÎÝ'¤Ý - Û^cOÜ•—Ãûå°KÝ,ëµíÁlgæ–•9sÈG÷ß°GYÖJÎMÍåYó¾œ*�+vt £`¾µ¹nœ„²G¯ ÎAµ¼VͯKžíÝ4º[ Í|qZÝ ¨ÜY—ÏÊPà™À�Nîrö¯ º½sq—fºVëg÷šœó­3Ç0ipj£�ïZ–mÒ8iy¼Q›‡x‹GNˆ×@ǃèŒ%ؼ"#*ïήlŸ*c3·Óo‚ÃØ{SõÞÏ#VV äJ†‹Ú¦;Ù·5Ò[¨l@âp/͆ÿ&¿ÔE͡跰¯ß-Ttu‰Z˜ë œ€a’Ÿ…ÇPPúvVrò,ºèé—‘ò’´Ê<™”kBñzÐz;3íB�Ú…�Œ,|N6MªSç°^Ï·J¿yTz›Ü’} }\2 7ù…µ¾ØTR•ñ¬ÏÊÙ4b+‡AŒÂ�Ü\6ð!�ß?µÅÙÙÞÇUâ';Ïþ(‘q]1YÄ<ÝB/rQ�‰ ûÞfF9wæ_¬?F˜¯¬¦”Ì ¾ãÛmcÊ!XØ1ßb–£”o÷\æþ8vä)}[?O¶Â4ÒE9Ci½ëZAžÝ�~Z²ÌtœúïÆ4ð®ìø—  ¡âálñf;ª"¼VòDqä›Ñ ¢Qç§ÖS§|ÉJ‡@rኾ—VÔ{7ýnTÓ|;ŸJÓÔ$޽Ÿ­q)ÇÏõŸfµ$]é ·ú£¾<‚6ÕÚ…3::: & ÿ;Y�¢S-rñ"_jâ‡5F(\·PJäö؃óˆ®S»á×Ân;ððV�l3äéR‡>Êh°fsº�“ ì1ðdó¾[hL‹V­æ¬¯¯mò+uÄV÷Ë÷4Š0è•(û0�–+ŽdNK6ì.¿ø�jÌDþËPV!ž*xk㱫ÉÇʶhø³.1¿ù…1è]N‹<°[ˆ{Â]ü‹¦üÆ’%Õå†L÷«¶x‰*žŠò [~°zÈ|4ï÷ÿÒB°Pó ¨«nµÐs¾5(_ÒG ­¡õ8UɨÂECÂnih‚ðáÖû+èzš´×½Y8`÷M¢?ùÌKÔȣ͌záþ±ü„Žd)¢«�‡PéVÊôv�4æYÀÈ{_ðÖ¶°ïÇ(j�ÁàHg¥1Rœ¼¤ >g™Ø™Ð �»6Ä—fd’VôÁõ¿úJ]9³Kc=R"n6‹gÔpÙ=¸8·¤÷!çqˆŽÚc)ß ôJüdµ¹CÁ í2ÉÔ`Íÿõ™Æ=Ö *[|F×ùQ©݆m³’Z�È�@M8——�éRþͲ&öp™9Ö¥³ùnÐÍpBñ˜‚OîíÑ‘Š7* ‰°)·¥c2 ¶]è–×;ØšÇl3䨺CS’™l:iуþĺ›·ê�R#M†Ô;µ|ªþW°0`ÇõÌpø3¯šZ­»—Ç ò \,\YËù¾Š”]M9÷Ÿúntùío@l_˜¦½ ÒBJT–4ô-DžX9�ŽÕtÆ¿­WÛË ?jír³÷QÞïh´ŽÃgo•Â�•¢™(¼RÆzÝã”ÿž\fÍW‡û„¼8}óf7Xj¯=ìB‰¨ð�ˆq랜Ѿô\í¬@dø:�}™1mîÂüàg—r:|[ `Ò.}]·z#Ç:U¹s²¦Þ`òxÓ'8�Ö²?í©Ònrg·óeõµ.;�5Ùæ=ÍU?cÔwQé=Ðþ ¬–Î…‡�0ZÔ®ôíE»0ó^8ߪj0¥vư�€¯3ùT£„•ì{Ä’BO2yüm,â²_ï+íZ€S W²¡<Éþó:¢‘L¨#{BÝ8 C�Ñɵù8HÑZ7­`<ÔG›Èx>ÙŒhÿMxm.(Ñ6ìah}�(TŽ/Í/•Hh#ˆW•CRDó8Ï–¡‰—–è<Êi1¦§·{ûËñ¼Ý{±,»è•:¿‡?2žÂ=�û@ª6Û‡ÍP�§X;ŠøA¼ J«m=Œ}%‘ŒøJR9±¦¾c9ªú&‹AºnÚãlÔ-¿3Æ�rM‰�]ôª`‡²¾çhË¡ýü,HPØß ÖHlM³LDËŠ³Ú‡ ÇívŽ\=Ô<ý˜¾ÀµVnÁ×SøWs­ÿ.¸5ÃØVî1™ÿ.©§L®ÜÈ&Ð}Šj&•D˜'Hƒ°f:o™(²7ýpo¤.µúc­w�ü†LK™hgËÁ[jÖ÷¦þ¡ôunËë¹èAvÃðæ;Bnº ö‡“y»!uVíhÖ +š–.¼E¢‹Yï8îZÞÈTlRÇß�e�å^Pm«�2É¡mê—iÆ�D?/÷hÌ’ Ö;ô½¦õ…u ç”U»q+INŠÊzÓ´¨´§jú(oB4îN͸’ô–,—KUK¤û£ïþ›tAi•}+c˜&êò+°pР²Ø ìÔ ' ßT;—0˜?�"‘êf5ϱ.Vŵbe5Tõ…@hô¸çî¤3wÊ#€��•3ôHŠaDxJ1nyÓ†'è7IK¡A¡‚ÙZiÍÈ�&z~|1"úó³AÝ>ÛÌŽ2x7`ÿа˜))®£TÕenmr©M¶=İmÏÞ`å0ÅãÙ«%©’«K ™Õpz.E½:Ãæn ¡Æ[RKqØõ'g)%¹•ÛvãYÐÌP‘ ,�*¡«EC¤ïù5�°VŒõH„!Ò9i|‰øŸ7ÿ†Hªè4²=¿ÕêÓ‰Ð]•ݾÉbV§ ?g2Tcý»Ä=!Ý…mØðØ2ýÄBá¾í­š”Q@…–ݰËpaqêq$Yk8¯a_Ây•pe0GCû¨i 7FY¿ÁÝöŒç¦ 9hçÏö׳`z¥–kZ>û­¶ét+âcªé¯([ ?q–Ù"µK7JjiªÍ9K—bQ�§á¼qvPîgaöpvA`¦Œ…Y¤üä¬X™aæ� š�ê¹€µðϰj–E© ËH!Ø4\ü’‹ÀÍ/‚a1#Ý”%-ZƤh¾JeÐÍÉêŸå¾Ali&y}Ÿ5¨ƒ`MzEí'Š¡?A®‡–ž@SžIq†ŸÈáõWÝì ôð~hÂf‡ñä…Õ=]æƒ4Ldå¢-åS³œZ‹úBÁ¥õ?ÜšU€”ò"�v“š²"Q ¾ ÍC¯Ã†Æk£�¬˜$˜1xQðƒüÕ®¥Ç p|¨Ö†ýY#öÆÁ»�ˆžŒh—b8/¡&¦E«ry­‘fíc$ãÊ4â&„fiqõñŸÿ*`¬ªÕ�õë¡Ð“ÀÀº3Ù„gm½�qER®:3tteUo)Æ0FÉ‚èØÆÈUŽjQ@Ü‘¢HU¶`U MÔ­lÏ)©'4?ZÇü,yÎBoï$êòéB”£æû�àÿæ_óx6+Ü(Æ©³Ê1¨öHMZFÕÚä—Gu †7·#÷Ó*"[5„ÑÃ[ŽËÐ�ÉØü*€«Î·�bÏ£³Œö ½×ý_pßÛ5 ǹ=¿Ç‚4w®Î€ÒVg¢\Eö3I̸R…2ß�zMX¡s6ø–Šk( £È„Ò q‡Ô~ÑJ�¿Û¢ï|‚Õ"÷¾4–Šš3@S}o¿'GÚØ#ëT½Î…UÛw {ˆl¦2öí»%m-yòNï‡äšùc½>$ž©o=Ÿº˜}f7zPJAФ_÷QnÛöµó¦±‘Éá¡VT3—ü}ó™å>¯ˆ]cð\¹?pû�(•“Ð’š™Ĥ Y.To¿ËkÒ�ÈlÚ)Bq4?CZRM„µ†·ì±Ð”Òî ¬ì]s–QXQÅ¥Ob�æ®Ð¹ª·8Z–³E…Ñvå-‰Bí³F%‰ÊÈX>‘¨¬SéŽïÖz®„È�Œ|×ZTˆUUnÐÍÀ*wïä°lªWnò{Ã-€¢[%èP¶êð+€`¥ÜÒq7²êñZÛÉo1làräãä±m z zj‘÷“¨j&�£xIçé]À&0ši� t�ÝŒAH€ÌŸ *M;‹8[™H ì¹1\«»ôÚ"Õ�§�.nºÆµËlùÀçÀè™,K—AŽ.ÀRîÍÈ6šåñ#T¤æ_÷ÿ�¹ëk’Â"È|€e¸Š;1¶ä;;í”7ÜT!ÉlÒݯN½“núïp·ž+qcVÔ×.x z~ž‰YømoŽ:ÞðhŠkxåIXÄíæ™¤¨¡[ÉH#e@Ÿ³ÈBÁ,;T;çCÏâ­ÕM*p’Η«d²ö•_Ô±8/=TqŽà.¨mwØÁŒá7j#Ø¿À <_Ì+oWí�çÌë˜tæk®°Ý*‡<èó»®4æ“^—ô—Š5½0êZÍѧ=U›D mŽÖiº†X½Ô=üĤ¤ÆjG¤w1ÓÛ´ø‹êœoíJ#–ø@ø7Ù"wÍ¿ætÞ®_‹½öDl-wœ›8Õ@ÃÇfqrÂ��@9YöffÑ-ÈN3s¨çþAJî5$w7£ lUýÚ>"5NkÅ/¶€äòälèqÂÞð îžD8p¯5M¬ €Scy.'«Ô“Êr5úS­#Dd%ˆ K¨Yĉ¯ Ûzº½Ãs†DYàyÄ�s8öw-\íÔ»1nöÔÌ (vjÞÅ…ª<4”Œ6"ÒæÒöç‹%_$Õ²¬HœÔ!Ýš9¨)g�£*=.“§º¾ø–ÜãÂdÉÄ#ü:ª?+Ž«R­Î¨jí5¾±Òæúò{{!—\t[#øxR«9^€ÑAê¨{f®ÀrÄ>̧¹ùééà­ÍäfÔ'`JæÖå9W|&oÌ{Èxˆžý¢íFzËæø99þz}­OÖnübÝÎ-IÄ©×îˆô€DkX2©¿!o}œ×‚U¢©¡FëÁ<¿Å!³ãwO¾¤ãf`.wF¦rhtxéÖ§(=‹ O%$º­?AÃíëûWT.Ju¦*˜ïTé·EsxêâFá5¤Äðˆw�bZ,þµ[€dŸk¾lœ7“WŽþ{’ãÖœ-q=—ÏX †½ÎŒOž÷Pnž|ö“Íùb“H+×°þê_ÙB’[䇛f˜Ó\™ü2 1RÝA`À¨N:žiYÒ«�b!êR¥Zõs·HïÊÄ^ù²n®Ùbícr¸ê�a¼Õe|6µ7§©­ºhöùÀö�YdI9’vÙ†Ç3{_YÅBSñZ0ãn¶ìKó6Óww�'m^Ó¼¡“õ˜óä·)Ä}Â�ii.¤úäB·T”t•”Œ·›Í£$QøÏv#“…+F:ƒg°Ø`_(´µ‹ÇÊà‡¾¼´g„DÅüØ›^<•mÞ·oß¾D_ÅrÀ9{4ïÉ�ð+[Ë­Þ²†b“x~hÉä|o&¢¯X=Ùµ(.G•ÞÑHáÄÍH‰}ìËZ¤1Éç’™\g“$4fâu2ñÄòxðh­â]1áÄ×,ªs~„Ü’dCA²æ)qž0F`1é�\é|s�c�í‘5N…ù•rh¼yc.çk»J`á{e”�’ýÅÆAµ·îÉòE:–Ïhß­3jé¥>…ù-ùà’.æbÕÞèݹ‡DUŠÕ—/ë n¾zÍ3öì]8ÅhؽR 4yT óí S_Flùfù ¯ŒÎgSúGƒV¢˜Õ̱~Ëy™µba£6tRÿ w—†ÖÄóеÑt¸‘^†wLºY±ÏZY|JŸ]–Ö6¾&üÌï,(“’UÐ5«Ì>;$$ðdKš'ƒŸE¨.„ÆvlîÞ¹¼Æ¿Áêp}ÑÂv[æ§yL9TBŽßmßÌj}¡ý>>Ë—›éÌ2ÎA ¨úH§ãJÐŽ¦—lô€ãdåaæÂs„Ó" �±ü ;b�Ðjt] lü”=I<ù�vŒ àée|È_ýÓ�i-0øìþ}^爧þ>½õtjìo>}îiKðNW1µ$&TÊ?…{ÔÔš)KÞ½Ðâæh;/Yà L ÂÎü»V»DðïtÜQ1†G¬¸z¯5Iÿ#ø¸;+}Z+M;>”¬{íÞR»Ø/Ó�Rtzo™¶Sì;¤©;J5<Ë<Ñ Q†úÛR&Ò§mãŸU %Ö N,¥u¥†»Œƒ›ù˜Å#Ç*£Ã`Ô¬¤»RĦ¸Ä ϵ«wezõÀÇþ]¥Ë£T1 £Ão©ž'ð}XFU¬ò†É-¼þK{é  †B’5§t}›,9¬’Gf÷qȶ~ƒ,RìÕ·;„�-±Ù°Ú»{R­äutØœ•£igO @ö¿_oôÏßCKîÐð�‹©nïù¹™Ýõs;`™³,2¿S+/•÷€�—´¸ŸÙ§¢ØÝÑœ�t&ü!«#®È€é15×ÙjV�yîç€åÌQítñ>zÔ bóµÆƒNH":n‘–Lâ†<ÊÍQ[Ö‘†ÏŸ{�L<0ðbå�,ðÝÏP-•wX?=fdú2Ydƒb’ýà€ËåîtÐÃ+�­ÓP_ö&ßÛˆ=á²�âBÙökùSÏômÙæjÆž\Å]BZ¬bCƒ€äõÀèHä×åÖø.@¥Å*oé .<Äì1@¡)QgÝh„.²ŒKÃ=�ÿ–â²ñóᢠíä—|LsÃö² „ÅÚu=nôånpƒÖ•DRKü µ[.Ñrã’ä,N-”¡Ó>ƒ¼àŠ‹ÇÉ›ÚZ’¨|ÆŠ XÜœ¾ïšŸÚ'4~²ÆN²w7™ £ÊtPè‰ÉyäeD§D.;}­—ÿ,J˜¶8 P±�“Í6Ü3ÇФ‹d”)“Gçóç�Ɉè+4Ò�ŽØ�.E!J¡Üha– ‘�]å¦QµÿK!_•7BK¥8…,÷{‡™ŒgY˪“ð þEÙä›É<ïJ1@‘¤Ìó:n3¥ÏŽ­š<¥ƒÞ:ûôºFIÉq9m9ÑÎ×Anõ‘d ©¬cV�\Ùb¿¾¡ë{D6M/gj¦ÞV?ë©“N°7D^žø;ÏJHõy)8ìß\Xç{WÃ÷ìDÒÆŠA”ø¦|Z6£-µJ‚s’’uŽ„‚üȾf{H›µÕSÔÿ¬E8‰GL!µ¨s�ìò�»ÐÖÎ^›Pé_ )>óM]‘Ê‹áŽÍàÏ1Ù�8ècZ¯åXµBMɾËø§ô$·ÍæåSШÎà.XôÚ¸q»}æÐB–³¦Q•YÍëþyÀ™3u„ åUÿÂ'=WáJáƒø#ÝÜ6]Þùü7.“íõ‹¯Ñ»Å»ý4—[hãnÇðÏ»®90®ÿ©-‘ Zÿ埳Q;ˆLt`�41—‹Ç ´F1©ÀªñK„ñSMJrã¥[ÇaÔ¤5E8 ˜>bÃR°i�I€¯T�Ñ@ZO9=9]Ç•\¹_ ¯•c÷j*RĆisܪ'¯™ÜaDzô9¶Ò—ÙRïø í¢<[ÖÐ`�"wÊØ`9 G8 u2¥?FxC#fu²^' Ðè+F«‘§c¢ 8Ä1’�â1ãÂ@ÁIåÓÒ`¥àîímÄ^M.ÚB÷m[²Î3ÑÚ‚Ä‚\t(žeÙXùœîÔà%§ŸJ"ÿÙÂñŸ?_þÅ×\ûƒã©IIî¬Â$z´å†eõ ¬õò­OÌènÚ;1Æ!ûhæ ~áä´‰ìôÛjôIV~Ž™d·Þ‘É͹LuÔºU"‡ Ó,Ø¿Ì�xȵçê�œĸ ‡ûµ¯ÔÝɦ.44™äÂç ­\ê$º?ÅïR!º6A Ç%{F>ͪóë!ë㶨H” ¶RØXæ‚z�C@+Fž`„t)9ó,[Y¦³Éª–[pìïÉ© ó.Ç+³*Üg?s¢ÔÚ„©”¹‚¯àÑïn²JÌQظ½wÇo[\o­Æƒ3qÂð䀘wH¹¾ê‡ãq9rÈÕëRmìÓ­²3¬UxŸï”ï”,~‚gyU˜ÙeàÆ·ß¬>ÁºZ÷î7$tã¤ÓíË�h-ÿìtÛ+G™?óˆ†kQr»h2Q!ÎÉë�f×3¾®µN¯x õLÃŽZÒäEʰP¾.Ï…ÁÅ�Ar%0=ÖJ¿ó»J�‡ao©½±Áÿ0¨Êá¤�r‚E+ñ‰¸Ô`A†—/ˆ×Uï{«º?éЮ¿1”OjFºõIhc„sjЂx §‹2î–§\dåë=¿œ­»|í­v‚‘Ù$¡Žô$T�]û€,×Çýb\ÜÉnªspœY¯9l“ (w×\7N¢¶Ài>µ ¿Ï6¹@PˆPFk&©¼Z3Ó0VB�:28òo„¿´KÈ+áºSÀ cÄ¿WæÛØÅ´8^HhüÓ�Vf&I$à“­áö\ÆÑÈ€&Ô*‹‰�RI”=\a©ÝEñ©‰*ÕX£õ�=—e9�àeQ$ª” ˜~øÙ…3Î z’¶ª ÿG¶Ç±[økÝI‘H—î2@¯FŸl¶âÔ¯ÈSX“Ù0Jýü»TS¼Á#n7$|Q›÷ƒäóê™Y²#liJ¤Ù@u…®{rÑ-,¥Ĺpt_ù6¾ù%)<Ð%¨Š7ލ”¼dARêïÝðPéeäHÆïã¶ÅR K.bɹE=ðÝW3%î×]Õ_Ò¼ÊWCŸÔ²ìö9Q’sÙâ+çH“j8 {ï0H~˜>´´4ÇénJ˪œé�ØÝÝ}Ÿ¿®NØ­ˆ/Û¯ƒÉý‚"`#À9înò%÷€åÍÛ_K?r&�2ŒØ„?Ç‘9Ï´Ôˆ¨¾œ®Ê1”ú]MÕéÖ,%º§t9(Äé[‡bŽê& ˆÍON #½{p"z=¼JÒxö83¼¼|1ÒŠˆ‰®OÑ*e±fw¶Íˆÿ˜#õgÞrÐGãÒ9‰nk8ŽúuÎØDv^Ñ8KÕYŒЍ#â Oï \Šß"Ë4&2¨‚Ä›Ã@ÆÆ̳}’}Ó¬”Þð„`èhsêœÇÈ^r7˜¯d7²½ÂP-\àêÍŒHÒ-íyA#¹!#ÉZЧє‡r~-çï˜q)i«‡Ò9ƒ¾bK‹SˆÖ jÄá³ÃM¥ðú–FžàÛØì1�”#Lþ…¡ÆéKä¢H€3?³:ÿK«.0á|É][­NEyÁøø6j˜á§ðà¶–Y³ÖGßÂÞçPqÁy¹ªÓO²wõùBgß?AÕüáçö¿4ü‚Ð1`jõg‹ÅQ q·Â�Ʀ´ç™Cç ¬¡ÂÉ4Ö°ïçWU ¢™Ðñ­UîTx_¡5÷•QýÓLeJ[Ï©97ú3ν| Äâ‚҉ɿè¦<;(�ÓëÜÑE±¾Œ�ƒûËìý“¯Ü°Ã죢‚s,ö¾D.—|‡¬�•Ú»i±�‘†VçÇ º+÷â°?öÁȨcËÌ~‹¶µ¨� ¥Xafâ}5üÚ,(tPyÆéªëOóÍÍ›F û7H¾‰Ì»]ü‚KÁ}žÝ\|ÜVVŽ_ßnˆCÖˆf%0«©m‡VÕ)ÒÒSö9O,ãâñqr2Sü19…•ÍZ[6±ßP¹äo\û�º&F‹ÊI† ^ÉG?;ÖÆQý£fý™ Ó…aXœ+°vNâæ&zIü�'Gvo[›Ïn"e «þ„ ÅQí�¤<õ«ñ#×ÒlƒEM“b:I½wƒøÎùßN^"ƒ6ž©sD޲æ?m9ž§)Ù kHx=\õ„˜Š9Mºkă×ÛÜ…¨dý×ÍFò=-ù ¢EDlUÏ¿¢Eÿ=úJŽ�LÏ~<ï¸ôO=“d¸æ—<Ñë;˜}1„Õ.¿æ�>ØçF®×é@Pq¢8zëíÈÿ rrÍyÞ†­_ûé‹Ç&pCòƒé`ŸA>ÄÝAT‡Ï” Q”–rÁ05¸éq hÕ€&àÝ U90O9쩦Á %¸•M«g…²Â,S˜øg+cÚ–ª;à?;Ðû µIé¥í»œø-1Ælpù¬Ô¨Kêø.º·›ô©6¦1o;BãX>¯ç‰œ~“X¯%“舖.Jì�Î`¸��w5çÔ´Q“ë�8N÷(,}Ф^ N6ŽÁ¹~Õ® ŸñY®ò=Q&Ð÷óèç�Ü[ØëDTñ ß]G=Y�^B&i%Ÿ<ŒY Y3.³Qæ!¼ ,ñøž™x´æS#$T3§Š)q=�!hq0=ôöªÒÀ±�Lƒ¹Ál:�(~¬?mIs_™ŽJÛ‚­µ™ƒy¡7zôÞîô8º$ Pgg£zà˜ÇG·ž×i=gxÈû$Ó­H³"iµ`Bž¸_àÓ`Eš£w5Æ[8®wó}W°ÎÔKj§la#ø$â”.ÅA TWUi£DàØÆjÁ0QÎRñyÛkgrsŸÌ�€çÕŽ1´ÂãA‚ZbùÜS�[9�›æ|X Ck#Üšè :;.ÖGóJ#KoC2®ê;ö¢ �¹d.õÝ¿àN ƒ¼bˆÈRvض^+·ÎLµ"i0-Ã¹Û þÍn¼ Þ»{àyDŸÛlßw­L,<Ôj÷”_÷Â¥�›nò3™ú]`>!yM£ˆ,ÂuùÐ7îµóíUºI&ªŠ϶¦ôd}ë&}ŽÅÞ#^ÉÜÔêWc\�R¦½Ò{)„ùâë„Nv°‡d7£�ϱ ‘?û1ýr½fj�÷*Tf‡õ¿nÜ×µ=5;\ÓÏåhLîeé­Å¡ó DᆮÀÕÎ3Ç!û{”å¡WxuÞ_——ú`5Ç(º€ÍË+¦sì•éQqщ_;››5�aÆ_%>¦“;Z.&šp¨‰åRö;äIêf ³þJ’ÉØ,� Nö½†çIðñå/®ÆÊixœ¥ß ”œX›)·Ç¤xZÝ×V¥sx€ZÜ= L‚ ¤¦T°`œ§a¨ÿ¢\]ÛEú0ÿ°.$��3}õjCY‘œ‹µ/è…�ëŽç+Ð]˱u™'P*Áu‰¶XM:ö·ÊѬœÊÛÓ»\hO6�QsðwéÅ«xwë§ò5ÞDžG áC¢yÏ� û4É�x’nK¹£qô}ÙÊ×04Ä¢³Cˆ(9ý4÷•†•—PRI©Øs™çVi#-Gb`ŒDB—’jvD± &¿Ðõõt‰6wZWW1ÙÀý8‚« |%¢!Ïcθ˜Ì'H­!‚¯áo!¡³EjúÞu¢Ð•“�L±v¤õ’,òcspm™[éŽR)Q6›6s•— |k dOS’Âá©ËRˆ/¿ÎR”Úù±Ÿ˜ˆÛŸÁ®’é©ãOá�ùê?wþ?í¦tÚ” ð`†ÉÕ°< –ŽŠóyÚ§}“4–¬F*Î-"²£äë¥æº¢;ãë.4™NÜ|Âyü°µ Îè£Igë¡$VhvÁéc²ž¡æ/Þ’¯¿Ù*_�<\¸%¤‚¹WǦgfc:èËRùÞÖ1YíÄ©ÜÌÕA'¤VC‡V¿Æ£YKlà‡÷Î|š±':ü¸EŸ7$gñ¹W¸ITP‹@TÞxLæ;‘†¸!Mñ*Ž^ö?ù¬s|ÞÜø³ƒžmEdNǪFú&÷ü?ejFÔq«8°æ�“»cDžC<ÝBv¤rïÌH=þ¤tïF” ­¹¯ö©\\öîH2¬#ŠF­�u ~ˆOòÕ»4¼—Sr„놌%7*×G% sµS?˜ÈË/UÆ0—IÑØƒlþkÁ£>ªÊî„x-O'¡¬brå$4…Jù€ù_Ég»ðc‚©÷ËŽ Ó¹®ùzI¾-icŠøŽ‹ÞµväŽC¦�jºÕ5;3hýîÉÁ+sß  xS†“ègg�»Cè_t¼âªŸ}ÿ|�>]R<{=•ç¼jG¦èöf…g¿Ö‚p‰Ü¥×òúf¢þSËqÓÜóijtY‰‰ ÂêAS[i÷5ÓõVÝ«°ÏnÔqnµþÊEû BV§ášs%÷쀿„ëJF¸ĹšVöz!û2_•Þ/+Ð-gÂ9E8‡jóÂß t)®�c+.I8mÇ'´nI››Ÿv¾ÅCHãåQü)¶B]ƒdGl ÕU‚ Aƒ(˜t÷2Ì™]Y-Ì–$ ¼®êÀžÏwr�F1`úä1Jöê÷»â—Š)Ľl(hçæfS2¬`¸+úµ(��š)y¨,‡X+¶—„§ÐxE@[fqAôd�ú~,/ЫîF›ÁÏo"0zÅZ.w$×Sö’–Ô¼;ó­C~]¯ÆbX†ãÂM,󅆺Ö¦¤-€GƒŽ‡Ï?C[š½  7™ïìî Ç %°O¨õørdÊO‡à¶«âqß3€s£†÷Üù´í³÷�©Ð}·zÔÙûŸÉ«öõ=ÜI"AÍЦ~¹,{e¶)†+;* h©Îm%—>2eá¢×Ç‹•3wíxö«Ôøý°fÖl4fü‹ÝTF -}òk̉Ჲw•ªÂë âDþOkg%š]rRx›t—Æi°”9Yz]S9âpVµmµþ±¹z~º-ë²îðÍáñŒÕg ÞGÂË„z)§Ð±ž(Ñ)ž\Ñåˆoh2ЬÄfd=úC ûQrFœ»vnÚXËÇóH�s~‚*ÍÖØ~!üpg „¤äÉó$”ìÐm¯:÷M …QN"¢™ˆ–_4HÆA®"¥„êŒ<�ÉíÅj^‘¶r«ÄGªs{�¬K^~Ì!èX²ùeÙ ÁÕ•=R;69H><š«¿2�,ߟ12}-ÿ7S%âçX'QdF‚Ä´¿ÓC2M!êÕuiGÓý£õñdtÏȘÝÉù …ݪì\b�zÓ}H¡@‰÷Q�qœÂ5}¹öÜ6€ãàF:ðûHø1Vëa¹w©³Æ“õÊg³Ö‡bˆ¶\êL¥¯¤%žÇfùMÔ÷$²þ£u6ØÕòñ&ˆ†f\#ÀrÍÖ˜ÖËÎÊß/ÊÊS:y­:=i!rbÝ�Ì—ØÂ9œÄ.ýŒ±Õ�±Šß4ÿYreº$uÀ \[¾¨�â ³úÈ*B1Zš5Ì¥ˆÜñ~¸§Ü)€40-:Ö¨¤ƒ•ÉùâËÛ}e�³k��dm¬D�z,~Í™´=Îúh#xpOÿr¸X.0�~ÎâÿHƦ�w£À:<Õ}9*Mß»|ÕBóøŽo ßÁ¢{1»”§ßÑ› È`¶T£ÕitÄ—å—%¨¯+—,GÒgmŠz!Ø.$ûž�½N-–M—<7RmPM&x¦Æ ý‹ÒDZ@Áõ‡— ´HR…iÐwe@ukdцæÞm"¹íÛkiÎV'†€Ó¹¥û—çO2D¿_ÚkjØì^yïì–t˃ÒÔD¥©Ÿ§§|H ½#ûÇ&ûK‰ÿIéXŒß ZÚ =©Jß’–ê@ŒÓèS5V0ã¥ý§‘Êk ùµs¼AO_ðP‚»ž,·ï&M¤ –qÙ¿ÚKnîà݈p×à§DÜ&<âl`ĵ:ж›¯X³,Fp¦<ú™ÜptÞ)€˜ô· ¡i)(Â…cé3£ï9&§Î–¸«¯çÅŽ–â¡­xŠDQþ²ùãHÅ‚j$®2ž%±§ñŸºùh„µ�ôæ–„g1õ.Ù¬:ÿ±,Ç•8µ;«W%@ÝN)U¥üЛü°LŠS–›Ã[È-»›ÃRïmuDañ.ä‚È&¹@²Axæ~Y“OˆRŒX6_Ÿ1 ¼x¹; ¼?$54<¥ôãžb7uÂŽ»^°åòZÄÞXÛ›8}g®B㾑’d¿Uw:W�1-™¦ÌˆuÉK¬|“êGÛÏÎ[`YŠÆíΧPT©Ay¶G?&àñˆC¨£lÔD† “¥ÎÅa>’E‡nE MpiÑô 9iŒfž²ÓjîÀ›t²m9ÑÇoç…÷‚¥×‹Á@Bf‚ Cú°›Õ»\x2óýüõ-xùà‚>÷çuœlíûEèÜc\/5c£ �/í:díÎæý¤2ñÃÔИw‡û±Ó&�í�¬=ä•Ï€’r¥oR>ÖH„½ómþùl¬=›ç[·êYHÓŠ¯ ŒyõÕdheþn›wÕÁeõ qÆ4Sqd®/'ÜÕ™W+‹Q6´¿žS�D #È÷\iþ �;¹<'¬”–‡kä÷"ÓÐ|4Æ s u~§ô­ÄÆÖñò¯ÐÒðhcRñþšëŠÞ¤ ˆ“€Ñ DŒÆ¸‰¸{�jy�Y/Ä{F, AÈC²öŸ þÙ² >ÙOM…uëeó”ø’|¡‡Õá¸J’62xûX73?0�Èß Ëõ°þÕí¥•åyxʇäBN’T! �S" ØÇ¬Ó(-¤VÓ˜"Ôý k—K³s$éSmü>‹OºS…|ˆ²£ý@•¼¢9õ¶ˆðÀ¸pLd©Yîì ©ØÎÐ(h9,} ËÙǵEí ÔôÛ%T7{¥vKQ¨ù<~ë®�«•°D¨ÚsÆÆ¼-¯D�(jðk¦ 8ºP¹§Êï^#Ò3ûŸ^²\�Éz�:ø¡_¹Â4¤´ Ƥz@¦W˜†ñàÉJ? êi œø“FãÁû 0œ¶‘•žÃòm&ª¡¸mÛóˆªx;`—’”_¯¡ÔŽ�FV¦›‡¦£–î]Ñ kPäŒÖÌæ!Ãîƒ*qE—€hD1ûµàci¦ãzv„îZi�ýÃ`�®Þñ=&ÂÜgÀ J…Úåøw@øäZŽ�I̧¢�Mx йÖt%ÃÜ  ÿ›Š7#ÿ õ6Ê]ÃbT²oH“Ë•�K±A^¢FT=†èÄÇš˜ú¯ÂÊÊÑ|ÜÞ¾1_U,`yiUœ÷üçNu k?{åŸÁ¢g…špñ å}»åD»ë¸ÉÚ=z9KÄ¡�ñÐg´Ž°ñsùþ§g_’¸Ì9'ÔY:5“Úà“5¦¶weAØÄæbëû8#G¾N™‰ê¡‡Ùœ¿0AðSC;ÔbÈSE^vlNE(ÒV7=÷çP;¼ð3tá'ºþ† �œEÐ,Oð¬n>ÿĬý*áè2œ¶KŒùc2tsç=²š³Ô‘�zl´pšÓïSd‡”MÊG¦Õ]o:C³…kPò ÉŸ“T­PT øÖëôXL™@ÑÅqT7œq©ŽâÇ)Ä.Ud>TxÉ„¥kbd;[áíº‡K©÷XUˆÍ¬ÜÁr âý^ Ýyão‰¤Æo5—fÓ,=ðÔ¬+¹ïsÆ ßË¢³,ÉH»“3zXr¡ËºôäÑ‹kÝpiw¯­×d)«*§ÕV¿ ã z-ž¢®È$0+u Ce~K¤ñZU5la–2¹KpÓûIyI!eJ°À¤¥×§Ÿ<é/±ÉK�)¹{yQ¯åÆ:1•‘w#×Ê$2ÀäZ4ו0l=3ml�F*D£ S$.¨Jª†ŠÔ#*¸dåÝ F;/ÌH¢¹AZ,Ì*”–°€¢V HXÙë/oÖ!,ßZ%cF®~öBp×ZGìÕ6|ÀoS^²j€sˆ xõ‚Ó ôñ&ðÓߌTR;êž 5›U ®k¯T@bÓ n*üÊo²Öõ8‘#f(Q—<ûR=”\¾Ì›ù—«tÈ~šùbwXó‘uÓæâ¯ Ãðo2çšu ”ÊeX¶Çn®” ð*ou-k††6F YüÓ™H%à^M!Gte›ÕŸíW¦ RcôÃV<Å›�´¸¨ú~™w©n�÷†ø2Ò 6ëþ‹K¡5|¶àÝ7/à‹ åeWÐÎQ·IÊ€sú5â´qØM󉤠*1¢ ŒWˆúÃÜM\Œ'h´\åˆÙ|#·WH¬dŒ¸t6Ý&BJ[�æx×´U¤O}Ê�w×%ù¹ …$fRñ×�¦×5§”¶u�ºÊ7Nuê¿uʃ­ßqÕ-9ૈ°˜¸ôó{tÑ(Vd[R‹ÌiIÅ5AÌ‘ÚÉ´ÙذŽ'GK!ƒ P&„8ëýa,u1;T¿`dé�ŸÝ�7"ü®‡Ü_ßVæšýÁ¡ð‘¦iÛ€®ãyáôôL0>‰ý‰ÜODã@Fdw]f|`¨†ä ›éHg9¶Qe{¿XBÒ07,¿ü¤¥Jê)E©˜leY–íÕHépÿw® ½öá”`ü×5zQ«u­+ìœÍ6ÑBu:Õùöo/Pp/ÑßÍ~´+KP)x’AÎrí9ÇÀéaae€AÊm5X¬ïÕ!€ÙñV¥8!¾Â‹õŸ Q5Q„^…ŒÅ5¼œP‹ÊX®dl�;:‘guæÿ(²ö@—7«od¬¨å½ÿÙ˜§Ó¤Ò \¬zðΟ3à¢?,L(a�s"-˜TlÄì±D%0àBòÒÊ‚Àµ?§ÄÔOˆwÔ{SYò˜œ6* µÞy�:IÐ�€Ï?[N‚(]G26¹;†Ø³—"@Ö%I©*÷' ºÎòm*á«.°sî«ÇÁ’€?{Hëq§2ðiL’ºÁÉå¸ ÛՈKp*éO-ãmˆTæð�zBX´‰•ø'Š ‰U÷‹”Ãu¬˜L°ÀÉpý̉±.@F›l†¿¼«` µ ×b3X %ó]zÚÌ õLîí®£Õ\ŽC= 5/×?~�å·K¨8Høë„h´­¬bãë­9d¼�Þ}ép+s—Ã(ˆ&1.qºmÔGý‡!‘wð鑼Ò0ë'ƒÑ&ŽJð;2ßúõ¯-—áá‰Ä³Âkµ:’\™hì*üò¯¸ > “ånù0ýÚ»+3ªÀp "!B¾U Í÷®GqP¥öÐ笺 ž'0r¿…õîÑeÇ É: 0ÝøÃ½¥ð{¯Ð.ôiÕ¶¯ùAfR¾cL^fGâ‡6É�wT™[p‡[ÅÊóÖÊÎ30ÎË•+þ¡Ç“§FUCêÿM'_•ñ‰¶õ_<©_•`ØL¬Ó/H±Á´Š@ïƒì>6°rŒ]la‰vºÂâæìëo…ùåÝ|Y9LºÝ5©Zº®Š{S´®”À´½ôƒ51*›MþÒ甸Y¹¯-Ë :?Á±\¯ìÁçÚAEüz‰ó!GêC.v{XÉE?Â^á—¯ ׎¯ý£€Tœ/1p"ô0§K�Q8éµ¾FÞÑ{€áVZ؇ oIJ…þd)ˆö 55ÜýHÐ먗èß4‡]7¶àaÀpä’…�6¹ôÒ¿£[œC–|jÔLdRŒ€ÁÊãÍÑ·Â/$Ú#ìÎq‰#ÐÐ�„ÿ4ÑwN#à )»cÑ�¤dŠ£ê×VŽC�h|€-UŽèºc“I,%ƒ È…épZÁ�îšw?•VÆýû]?®x£f*2kÅiª"‹œÜÇÅaRRÉ YGÙÕ¤ù*dHi�Fa§‚=§Ò�¯ðÅʨط†r›,�ÐsñwÑI‹ˆã:/¾m{�Ú¢àê—´MXó飽EÈg'÷~CYp}F `bTS^Ó¹Cž0:anÞd³ÁE¼ûpôo+±¤2·BP©ƒòj®ê ïäߨ; `•9—FvÈÕÕJþkߥr(0ÑCƒe1Âß~zŸ™Ô£[L —E�l£¾ð\¨å·±óZä“OóÜïýŠá¾ÖrDph3Ù/ ‘ч²BR6 ­H KË �¼Ð¡’’0«åË�ÊhC�°`æR.‰½uóV0²jvþŒØú͹å>+¬=Ô:?̼ $4{›ÐpMjT6–ÞIŒõ8u†ðz(‰�+�‰2Ã7{Û[¢œäD¢!E뤗œØj8Lí×Ù˜€¥î`­q˃¡<Á:9oqÁ |‡PŒx Õn|ZMdð ų_ç…©A˜Ý¶ÔF–º¸¤VÍcVµ¢óSzK%`.ÚüÐQvü¤Þ5ÿÄ<¸Ì:Y•é.}-yÞµ·B/Õá5Øqþ»ná�yD)a‹î ‚Ú:¹¸/gkàl€óu뷮¹þ´ÒÚLl�Šû.Ϫý‹Mh X°½ß(ó“ {}AD<§Ê¿Šwá‰ÐÐ˾3QÅ^&>Hª†¶f=”®o°ÿâmo�Ç®­Oç_Ÿd˲Ð{’ÿ…BíµxcSNÉúåÏ¡ÁYš• •�’¸›ݧöÞ‰ºÂKòXÏëFæ´ãÿIS¥�ו_ÑYÞÇÇÖŽ®N‘Gê"¥~‰÷°Dá‹ 5§'ò+7¤¬wº"ínMrø¶Î…'q'!�®_t¸aβ4cdÊxËhà;V8ƒÔáò Ì¢jo5®\îàI¬Ë=µÝS�!æIh žœ 2íl€xºqÄLƼŸ‰dÓ®ØXe˽A™„º¤Ýè —÷W©<ô*k:eý6‡ù5•25lky¦ yØ; õÈ”FïÆˆ¯%Çæ�Ò t1÷qæG[°Çæß[l€H8ß¶×£§¾�I4úlEhLÄ£˜³ /Ô¿uVƒ‡­ÖV­Ë1ùó­Öè×9Ì¡ªu•N6ò•t&e J~42‡�fàUŠª!ÃLñé'Ä’üùqEqv}7†’puD’•J�ñ¤‘Ò½&³‰ø¡{œ¦{¦“\+T�Þ57bÍÁCjø¼uY�#>û�нéçm#ÎÏ€Ñ21ß11F¿^ç¬?hhÒ*î¸ [75RS å´|�À…O¬ç_ƒ,n�Mnú~ÞYl– ¹Œº$¾uÐÅ¿6µµFF¡üBÉÂóý ?ç®iùnêï+f*˜˜FíJíi^�³1*ŒÈQl¶/¿Ùú “ß 5[¶I×Òþªþ°]•Ÿ®Õ1Ä4wlÈÆ'ƒènçö0TŠtXÅè$Ú…y³e ºÛ¼WÉñÇ0¥0rEh9Ž3#…äðTá †9Ç€RÜ观뢘 5R›ùe8^·–磻¢WrÐÕ=FM¤w\"D^Ôr×Õ"h¶Á·»§³5›!tw¬P} l¹OÌùÕp:^¤l[¼¥¢E«-ûi:âç<*ZCW¦WNîô:Àû¶h@h]1¶?ÄZï‰jY+²°zÿ.С+¹B¸2S“LÅâleëfmé,ï¿n×U°øC¸ß€á2�±)ôc-ù]n¸§ õBþ«êwÉÐ/ºÏ‚ŸpÏ¥:/AsÞZ�jž³òÔÌ_ôšBÞvGb½ç ¼–‰5nÕH‘Ÿj!ÛiáÑm…~ŠÀã*†sîîŧ[›|ñ¹×Eïßë'¤ñ¶Åã´Cø@7´´bT3“dÄoÌèÔŒ Ë¦Ü´[è8q h&DÜ×ôáâÌN±9+BhhÍ$ûq}o §B›ýPï½eqë>2üø¹™âo¯£Já]mž·‚‚+7à,[Ø­9×¼ ÉWžãÕ’Ó6b#×j�Ù(¥E¯^ðàož²uS鶇-CX‡Oî(@x*÷Ö�ƒE[ŽÕÆîï»3Óù7k¶­˜¾ÜzBòÏÚÕ`SøCv=rx,à ½ûc·Á©%±%£æ2æé lU1ùÀ櫽<ñô�¢?÷¡ d¬kfÛ‚�?’sáa!Ž©×/P;�Cñ/#YcE_1-eéŸß#T«ŸP#m¶ó¯ƒX"“8Kœ‡J¾Ñ fþJï´6©çX”o¯â*²iäîHðÝe üGø@‹éØ-»¸(|R“”ºµ¤ÿ¹þu¬¯›~1>z$ÿP-¿rͽ¨L€Õònów´AeŸÜÅpÆ@„x’ñV…æ�zÇ *‚DYH§›ÜÛšÒDK‘B�yzÄz�kø�Ì ­†}À%'Ÿ�¼Ç †GrMž±È&òõ£rr¿roWé +Õ! ´�ž‰l™É 7‹gŸ•˹UJaå>ã2Çþ_]›Qÿùfo^ Z.A ¨–…gâ16ˆÇOðG d—§x o±œ‡›§XžGåQ³Ô?ÊX}o¯M®…’°E#BµUòÆk*cž‡'Oµi¯sÃØìK)׌žÃ&‰ð‰æÆ¦®¼2Óf…ŸÀÆÉ¸m&ú¹ ½Þ�»�ÝÁ ò­‰½…ÃUód‹/¼…Öµ†3‚vöV¦ç³:UâE ’a0Š{WÁZé Úp}Qžç¸½ŠbS@l„ü»€ü°æçá’IùhepKicGçUÎçŸnÏqkžkrL†Í?‹AL ¼< „çÇqƒ¸Ü;->ý¦8F±ëèì‘0t[)%XGó…­_g’i;\S¤/MM 43Öá¤ðÓ>¿Ùî/©ÆÀ¨nð'ßœˆ@÷£–}>L~¸ÿfÏõ£i9ÇÚë—ôÙÄ�'I¾°»= v<›°¯¾®Å¯Þ+•ÁÝ ›Nùoær‘ìæ¹”OžæÑ6ø>¼¨Wœ(L¹2SZqœÈƒ·ÍœSÇvˆ S²”"YË9½A0%Á‹IÄf&>ÓÏHÇ>5 %޼�dÔbü@ü£¢GO^ñº xïèSõø¤ ÏÍtý)¾²ç�ˆæ—õ‡»ÞWñŒäFöŒòÄÔÍ‘¬›1>ÄÁºÆOp¦•èvaâr“¢c*gÒõÞ½¡F6ÝèüJ9„²¬qo§'®ûkÙAì2¸å¢+ìíŽí~7~�W®Ë•y£ÎÛÌç›…ùæ×dÿgÃÁÙiä>éõ@)žÌaϵnõBêý 9ƒk2QY•ÔØ| QÏ®´« ` ©óŠ�Íú^u'»”Ö¥‚kNNuë;"ï®6À˜n9|*>Ås·g­ðô{ kd°¾àÐ]Áiô žÙ‘ @‰�‘½ ?"ƒ©F{†=½iý¥¾ð8ö{TÒ‡$§\9znµâtAf¯æ/²ÁàÊp5¦˜ ¬ g´¨[Á9± ¸N·Õ&<yÿÜêlW‡¹d¬y¦O=+8·`Vñ‰I©¡/ w]�IvüA—Ûk¼þD¸t�"ã7Á¨IÈ2ëT�@jñŠ"í艭þWMKŽôj,“L·À¥ÐÚÔy6‘!¥‚ÁÍ’/ÂWçÅMžbÀA%;fFD…x´½tD�oÕO�÷ëÜÏÁtH³]ˆ ÇL4qŽƒÏÝñ¼6�p¸ÀVIfý&oÄa-­ß¶†{Íbu¦ÔìªôOcßæaU€íkýì�#Å5ä>új¦ßwgo=WêžMVé )/©Å©>§Ó}Œ½Ñ”»ªŸˆR„4ž‡ú±è7׆GëŸã,ý�ï½’éWÝzrêk!"åâ7]¢ý£ÂPm¾íÏ,M“ÎlÒ�¼éæþ� ÑŸDË¥ˆØ�,BœøÞ(*ydÿ~F+}ä’¹Ócû‘µDD´{zãTü¡ä«IQöêP*�üå¨ùrzcè’š¬Kú‰ÖúÌæ×$,#ásc“1ÎbÎú®ˆßäëpiÉ5®Eúr\ >”\YïÖ¼Z×Iî 8�RÏÿ7#À"´¡ß@Å0&"3�á5øú+$âA-RQ°*¶ 7Õ|�=½m;8³È<·>„VÛ Æ¢"@ÿþ:d�­.÷Ï�j% p 6%rÝEf)Ü뱑lX«eÆA<û–‹Û£<_#|ö›ËpÔ?5ç²6�°"$k#yDÕ·­1Ônû{î1¸Ž 8ƒp6©][³ N@°ö¶HlŽ´[þJvâŠ;ºðJaìEˆ7^õBSBk zváu:¿Yé°‘Ý'E ŒŒWù �_³½¡Ñ«�É ³Û˜'ÂÎm´®9¥­ó�#=(û!šò ™ I$é¿%÷«»m¦+ÝY¢Ê’""jÍ]àýŒ9vGìžE§RëåâÉ•Bý ï_všäçFºÞsps à5HS_b»’à§.±ôìm„/Ç ¶“.õ}yè‡ aì ‡ÖÀ³«LçÒ•A.ŸI¢ ød³Û‘%l¤O�°/%U•‰sxÓ*º5ì%Tèm*Qg#r¡ÌßÎÌfwÓ7ÃÉ-óP“j@â.ò»ËZH'˜Œå5G7^ñ2RÓº"bóNÌ!èPQ¼/úÂ�ŸÁf\åhª._´ÕFOÆÁ´©¾‰.À:EȘ^%ÀÅ ÓŸLú7¸ 6-¢¸³Ž—_ƒp² ä&_Q½nW˜Œ¬ÿ‡Gd\— -_(Ù["Ò™âç?~‘*µ�ÛàôºG�'÷ÓV;}žAñç‡ÁêGÔü" :Æ™—Ô2ÚÓqx®„ñÒS­t#wÆbœ K—˜Úb‰¶Æù~5�Í9¨¹Mæ!ۂȉ[¯ÅõeÂ…2®‰OͲ9ý¼B é§Õ³;|ÿá€W[ãUû0‡#óÎ ýΧûVêÒÎýg:�ñ¾JnF»æ,u¢q_o^¸©Ò÷ _Táó‘Ë. ©¶Îƒ¶v\�Ñ<ž’äÂÙÕ|ê{ÇmHk„åc/Bô:2‹ å�½¹5@H~§ÄoÑfAjöohuV዆Ñf^ßéÓw»«ŸÊš90`Ô¡dè’Dæ³—Rí›T£ U3zFð'óIÄØd$¡ílÚ4‡•zG óË”>£3e0Ÿ¢‚Œ6°ˆ”yåJ™–î![ŸfÁ�´vÑɉqÔø4ÄPç #\\2ÂHc® ð$)— /ÍúÎm¡UãîÚÇIꞇ†2ß}ñ O�§ãé}�óøŽ¿¬Tguð¹é"]â÷áâc5Ú#�Viù!íÒ üë ÙAob °5ok+Õ(Ï.ÄŠr÷ n –Õ¼Õ=5Ò˜V9u {E JŽCê/²´e å!o.K±QšÃqm�4øæ�Ø{à(K?¡œ]☥üuEFPPZ—2\Ÿ0;²But¨Ùà@�îÖfÔ뜋Ԯ´Éfbføµ'X±znª½ù…©Œ<à¶+®™w°þ¬Ð¼C´é5½^â:³íNÿ=½Ä•�ónoèú Ö#ëtèÈG 9Óý;¼ k1(›ÚyUF‡Vm6éíA<£`ªÍœ([s½hªÑ³Fk=Lý“ï²\߀^xˆ?GCvË'_øx0®Xñ:ø~ÕÀlÂUÍ%ëèE„�‰o¸¥¶tz:Mv“1Æ)ÆIˆQ©pv®3.]l¢2! ¢"Tß¶{ñX¾kƒ¿^¨ý#1ÕØÝ�(»dÑÔ……ä]œà6 1'ñ%2¹·“ËãÇ>Â�⨤Ÿ¦Úƒh`…?×ô“UçEî> âV»¢ ’Ÿ£‹»’[WfâQ ³�I·±aã¨ÛN<êœé†±’ø6¶ß=‡7c ¥v€Îå_]ÈFÊô¼kiàGwü·ãŸ` ¦ùxe]²2þ‚{Ô`œE´V�d5™ŽYFTbÔ^ÝŒ¦± çÉù¥\$ß+ÔÇ¥CÒÎä.éù×�[w•«ƒ×*¿îH“œBÂ%É _: ï`g"Ñ”ëÚ¶I?�t4Sµö_ɰ=�¨)ž¹Ò2ë´9ïË_Ì+î'4Á«Ò%èd­¸o`>z¹a0^ó” vLd•9*Üý Q´Uî;HÁÛ^Zá Na*þ&¦Q©5¥*¾ƒï@K�ìžb¸Ùcš›9ùû¸{ˆmýV-«6ü=> Ng6Ï–FZóÉG6&9ú[�|¼ŠWfsj¸/ÓçÏ"]bîPÝ‹™²ê#¨(’éœÛt*b¾ÒóB¡?nO{Þ´rƒ—xþZ¤ßMq³]Ë ¾€ÅVòÈ!T ì‘r¡³XÓÕb&šÅ-£­P„.Ââôå«•§#ie1=ðŸÊãRr‘»ÿ«/£[;µ»,ƒ°,܇˜ÒÑímiê1ðÝ€œQ$𣝒ô(÷PÞðÙâË$€I™Z§†#‰�ãûÙfRØ=í;«ñg»Ã…;S£ìÃÓæ)Û1‰%yð;óÕÛßO{OŽi² ¼\aØ1 Õêï ÙXJ£ÿRzbšJ:ŒH„ªaM]�š²�bÃçù—¹8#øœFÚç%ÖPÙ äHÆ›$,OUš"à4ŠB1Ãg ú‚–G¬&Ë%¾\x¯tÝåå�Ó«™z‰:ƒ =|îÄ)#3­1Ya¯7?ô﹬Ò5ó²ÜB,èÊ!‚ƒ ™³®ƒ¼—BátƒÉÕZú¤¬ßÚFx³.¦hudÝì®Ö\ª #bgN`k›�\õ×h TÜ[Õ�í�Ä[‚çnê¯ÔÑÙ³ã7ß¹Ê.]aì›ÒA©ZØãµ'kÔNt›Ì "×–¨£BääÛ_üŽãožÀŒ[“B-*5GMéM.k{“EF1|9i�W¯{Ô§W(�E—W74n›jU“dh×¥¨õ<Ìß2!ù]ã·:Q[W+ÌtI¥»Z®Uuù÷‚Í'½çÉõUU¹ëVeŠ>¯TÃDAš–#êî/ø!Û»Žq!·…›zEâ³N?ëhÞ8¹"uÊ·�Ûp‹ÖŠ.�ÄCŠ“Yÿ¢ ì¨ñȾÏ ÿ�oÍ�noTºsc‘ 'Ã\j@6l�±S>&´<¢á››òaص(gKygxò®li^qŒÜØI&ÞO³5T$ʬatÔt…ñê�¢ø5‚ƒ$µ—z¾Ö;Ö¹ºâÆîÛß?n±¨dASiåK«Ç‘±UF»"°·“†Tp¶{c%=(’{šÄþS.×Öù]éàgÐÕËMMdèç€Ú'Ê¥=*Øõ•ÀeÎ.ˆhe=P1"ýLW H«Ø å ó)4á!Éò3çs—4d&õH«KÞ½íJ³²/@$û«É}­Nµ]~-ÊI’ßQ=1q„$ùcx¶¦Fùîdf ç!F€O|Íç¹òòP:ÿîkRÀ}ï3õ¿Ø¯½ØÙß.¼×V€��vªEø½/O�ê)3ZÈõƒó6–„>ç@Ìá 8ù–³C| ¦Ècj.ù*6Xà{€sùJ¼™C­ÉÜö kË Œ¬­ŸS3®L˵ ^©ƒ;ˆ•Nê4¿îH¼ãUv +µ€Õ+ˆdß—NMyfì|òŽ¢æ>å¼úµrýöev’Ðû÷2ð¨t┘B€ßѶf’´T³r‰ÛÆÝhƒ²Î§¡´ENå‚~._®Á8o�ï_²Àølތ嵘)�íÁ‹èAOðX õ‡)÷¼O¬ ÊE*„Ùesõ<Û)'kþØë<á[.Tååo=¤ ‰CpkGÿû›c^•ÀÚï÷fJpp|7YIà~K燂5~ô*DL4N¹óŽÆ˜rUu¬¡aËHYË |êƒRå€ä�w9Ý NæÈ¡dÐS(%/ƒb^T<ò@_é·O[íþŸi&NÍÙã̬éhrÆ{i]ñÛ(±èòïŽàUõþÕ[ë’DÛBñHÈÞQ½¤¬á*l¼ìû\ÎO&{vê¶— �xJ©ıóšChîAìóTfƒ~)Ã1f…SËÝ¢/�eªÿ¶ÅÎÐï¿C39 ’Àïxø”«´v¼yWšâ°aæ,È•üS<�.S•s½éxRÀ‡[D,üd·¤ærW•|hbVÀh ~³8\ÿ¸0�ïK€ì£Xþwßj×ÚãRuÎØ¡¾¤QCßR…Ô~� XÑ|þ��F¼rgfh–xpLA_ÏØGP³¥†ÅÍ£9O›‰ŽÐW†à§³m›ž©-©/E‡™KmF³!Ì]�•ãš%â‡ý+é„«n¿;Àî/®|$TŠrm¯: ÎøÌC­²¢VK2xÓõ赞âÍdHI¬¢ˆ©¡£ðÆ-(»M€ä^šŒË¤vjT„磆äØÓ� ï5ʨ¿AíÒžuÒÇî°˜9a{OÊ3ºÍë}M èûèù$ÐØ)&AyqjªìȽË;–G̯ð}/NÃs1´ÊØÌ³é!Š–àcåÛÖQçúR©ÊäÌNùžígif£8iœS}ㄈŠî2ÉÃ).“LjhQB|aúL§‡” áYrTó¯±S¿û6"Îå�­ µŽ\rÓ$z:.D‚bPçd¦578D²�|0n޲û y ‘_H:©¶€‰»è5¬«f£8©‹h¿�ÎL <Ž6¡L¬¶ûP€œ­çÍ„¾Ô�Nlᨑ(y©KF„Q«c¾xTQ÷ù¤Ç'ÿ­=jE½7³Ã>{Ù~n •çÆ]I{²À�/ü4Gš)¼£Zúwh)"{¢¿›¦FðdIUoxk5²-…­´åÓ$¸š¨i\ÿ‚R�ܲXwf£Ókâ˜Ö uøؤÊ/s0”Y³�éÛz­J€]‡S°‹�ãrc>|'=!»Ô¶cnÍkd'…eÞ…$^yççµërížO�°+Uk(zªßÞg8‘lZÉ;”A3VµÏÿÄ¥ iϤm*�Vš‡vðýç�Œ0S\Ù–­EDã7øÈ¢�rº­7}bhÚ…$Yo²>±ô^³/ó±ÚmØŸ,Û‰VnpSÑmpå-”*¬…÷þ§\Y$Ôùêð!-KnÛÈíí[bÇ5¹P­Z­Ҥd·‚Õ*ÆÓ±W«/¤ÜàéÐŽóZ,žäÑ*’¶Þ>55´³y{ØÿèªL3’j�©„?HŸmã€Îa©™mÐZæûÑ¡içšÔ‹ë­¾4ÀhuwY0~ë[þ�O;Ê{IY‹ï;ê¾7%8§iƒŠ×«m}®©—,‚ÎLà‡õv8Îò˜ŽX+xzÙEì4i˃ܻ½²4œ;Á˜jl·ˆyBdû€™i­õ×iqvç¾âŸ­“€¢z$Ò£g׿æVëTÙFÞ�üŸ“ï®NÁä2‰#H\°Cfo¨¦b:G#ê]ÞÑɹwí];�Üœùàøò¡ôGüŠÒ}H“:ê's‡B‡N)Àqåuvf2�ùE”éówlçÖ/þy¦J‰”Íâ"SÔæ'a…T_PóT¿»A)æÁM2ü¹û�F“9ÑõÍðSXWøq´cfAKÃÆˆ�¿¤õn’PÀõ …Ú.s/%Ý&ö<æžqayjo]“Ú~íÒ:­`¢U¨(eÃ)ýfY¦(‘–å×ûbM¡�yã=C0H]µ’�kFí-µæq^A~1þ£]i®ªë·íW™ ¨¨U–¼ôcô÷Ql³3™§jÜXÒ]¯fC¯÷³õøA‘­óÎ;ö·|V¸lJ–õrÐâ£òÅž¢<– T‘ïž0”ßÄ–e¨[+ +€ç ›„eÿÇb&Ê!VÅâ– <û~QŽþ1ˆÃjîIP9úD¡�¾†b}¹§ÓŸ  1Õ $:ª¿Q55%•š~�<�Ì=¦,¥wFër~bèy¬§ ì9Ïö'v“…�Ró¯~ˆTÀH‰6C™]gMºŠm½hù¯xó!ÿ5-ž2Œy´ï²ð¬®”3mäñh¹rm-B^“îÎz bU�âŸï¦jëÝêD¡ô’Ð ÕëóBcëH_ Q£ØâýÙR…%ïZ³'|4ïQœ«”N9ÔïX�oiã•ÈõÀÂXÞN¬F+Þ.ÀÿE˜gm0¤ûÕÖr�úüñ¼[pMóð¹ð«†¥t=ØpcÄözø4éaD�?fÙuar”~È_5É;s½Üú ñ{ë&{ ½ Ò£Ní‰ÈÉ|r/)ŠáC ' —û®2\açÊn÷pÊ�™�U×'ðZÔ½’Îâkú­8¸ô�L#Ç{½ R ÃÄìp©"’Ž�Ì n|«—yXð»×udF7"8ÌwôïÑÂgGÌ•^£|_ãFð_ÿ/é™uDâ3..2s~EŒÂ.*¾ýïÓMÃÞYÄXÆìÔ—�æÃó��3á5‰˜M�gÎ�`Ç•]™CY˜"R"Nã˜k1k.ª¤ïõW˜‘äÆÎ}ž ‡´xøIÏìH‡ÌQèÐ^Ÿ›ë N…yŽÞ÷ôEùx”àYôŸÞî”c…gÛVÄ«œV²Ê¨±ä!Oׇr󡾇ÍÉ`C»”çzSØ<_OÅ‘k«P .ùNRí¾áKAKóÀã)T�N¿m/¶k`f¨íHÜǦ·98^8ä´ SŒ®œC'Öp­sO¼*8ìx¢˜N>ŸE‰3ÿ [©9ÔÃ�q”ÚZ™ŠKQÍúzÖöøûÆ+™}–BÂ' ²z-)†,ÿÎ6\J’èÓ}ó`^°Læõ°r+#öfqí[ž‡Vˆ�&.¶tö¥ž%[™%j_%(1¼­Õn!š«›·û´‘©ýôaîb’gM+2ÅBi:<œ+ á/“u¥öR‰©l‹ˆ ÔЗ‹ý$²H”%M’~•V®Ò6�Ó¼§LMPì¤w­³·§B;óŽP½.lå‹Ç³2àÝ1eÒuAÛ‰éš^ÂA�CnËtaQñqËék_B‹<l�¨°l`ì²›ã!Öl%Bn”½níñ›³¬•ûÜDxGLSG3;ö¼8 ÖÊ€ÓìWƒ¯[8´ ŠžÌzýÿn¸ØzxÌ÷Dh�½&“¸;[ڦ±†#Õ'á÷Ã/b¯kmÃj.ï›Ñc §&œ÷ßÁk—Ïè8¿êZʞDzM…qÇÿªÐ¥ñYòœYÀ,Çà*Vh~sKº³]Ršþ•…Ùò‡“íÀXÆŸ[‡�œ®À؉¥*–´½çEüqPu˜™µ¼HÀ/p¯Ì$äœgšHåRå~'¼K€×!�n(ì&oìfQií¥‹Ñ�#ý…8ª�~n�Uý™˜Ÿò½ÓVú˜Mβ¥|JÚ¬þÉ>,vÔîp¢ÇJ<÷ìz¢©�­ül=ˆÑò‹²m¹ ÚŽf-ˆ´×ÙÛ• SÆþf¸†ì|S¹·ÓÆ)xˆ5¥ì*6)ƸÆÎëŸÔÞ³‰¬sĶéK­/ËXÜQ'¢£ÆÉ{å�™d˘½Ð–a$f�èBãV‰ä‘·Ýû-ß×b~Ø– þÍŽA7°•˨ôS¶�:¹Æ5á’‘o8ÑΡ½-+ÆwÉk ÞøPú�5ÎK F?Ó€&Fœ9õÊ<»�¥àŽA@Lo7¶moû¶©N^]ø‚=ÑaíÇÅGÙb¹øSŒ©“¿w;Ʀ8ICiךáû:4+ì3¨/Ó>ã_÷cŒ�<©åÅ«Y0RL¢~1âbñÑÇ)šÈQ¶Þ*Óp¯0piè. …r£ø(G:Èžì—Õ}ízÇ´IL�¡3 £� ŽF¦}}À±€·1·ù§Jׂkqô˜*B]¬f‘½6âW¶ÀðSXWNnõŸm­é¸Ï£  #o<ö¹=<Ñå1dä½ýº/ÚÆoO¼‹‹~_†9k‚°Ë²€vÉWkÈÚ ååÄê)Ó6±±ÞgS‚«ÔÞ3ÍüUÉKÖçàëý‘?ŽüÆ›ÅzÞ&¡¯`ìßïãÀ¢Þ;w²V‹M×#ô‡£ÿwkäôһʞejŸã‘¿…ZˆáÓx6MÐ(\9%¾,Ÿèîég9K;œ¾¹Uøö¯¿È™B�ï­×`qkÙQkîգއe›Xvfx¼*O�àæÃÀZq¾²@2Ù}nÿ#»b°…6ÓÌY˪4À^b¿1«1ŨY“Ì·Ò7OY•©îmÄô9Ú‘ú£“Ñ(¨Ý«ô>￞{!ß°‰û*Ì4 ËN5žw¸SÁú1çc•Ez]!é9Z‘‹g„ºààOÂ0¾Èÿu]f¶öÍ�„""f ®áéüãZö0ªbuïñ>U}K‰s¡ÖHŒÛÊŽbÉÞ‘$ÓEè˜Ìäø¦aN鮟W§ß§ë¤)D㪬ýYXíx-½¤"a½`„¨h od 6þÙW¯¿gì‰3¥²µ!û ¿Ð¦™(sNeñß‘Gê»j>>¤ËtU%ó-ºâ®)ˆ€„Šê¾{cT%h2?”„­:òX0õJ¤®Cò‚£t{atæ=éª�²ëÁƒ«k~~*O–¥‹™e˜}p•ò8•ÿ‰€•³ èk’3ã*U]«·$çñ–ÍÀ+H-E­t S¨ ‚þÉÿ�Ú|ŸsÿS€V¨ÈInˆ¹¥ ß5ÍYw�CAb%š¥U.ìÿ(n¦»yKdJX*3bùËûì¦äØâÑĸߤw5oÿ$®ÉXVkžca#åt Ø'ˆ'xx„G­“gUB‘-„•ôGÆ6‰žeE‰7¼…`öX.@qÍ<Ò¼¥Ò~ZRRmy,à¡&ãKbbe fï�ïVøÇj™Å’'Ò¤(‹–\F1|SåqhºˆTΤ!ÝÙvHqƒ#ûwèÌæÃbýÙð@ªY./"j¼¤ï*mžà,[×¼4É©/ŽáØZÈêñ…©\• $Rðþ“Å�#Ð{èâdÎðLIjPس#Z­úh¬¢ëá(<(¹^'Ûô\\C×CbpltFÎBÔ°nÜ¿÷å¸#,Ÿq`y›¾ÀŸ?Fe¡5 ’Éë㪔è^�$¦„‚—ÿµðB,7`Zž™a¾X8úóºõÆíÝXu]‡-H #i8Ò—ùD:wêw¡™2BÏ‹ž¬(™:$Aó,–÷ÉR ű ^tÆÚ’se�Ûeêv�cIcž–W–s�2:l>öT,žïBŽÝþÝζýú51È} D—¬Ž ¨òbDvÈ„le¯M€y>&Oâ*àÉÊ”j’¼œ%ÉÊ T0\!¦ž†J4œi4 : 2Ä’»¤ÈIS𳛂qX Ó‰?À‡ חݘ ñæXt­Šß™Hê R½zõ]“íDò²—ø¼r'Ê%ª+ø.3këtâ±=Ê+¼%[BãõõéÍÍ@Îï%ýŠ£.ª•ÎÛŠ€’Zp†ËurÍo„Ó{+å6he�‘½bxÕërI–Uê0ð\™aç¼WÚ6{Òt‘Óï‡^h§×•Ö£¥r \ã%xÜ÷íß)˪!>M9›_îÀwš¼&ºRùðWØôµ˜¸ßùŽ5#”¤“5»î’m0x¶øj«†÷VväSât¡ë¹Èõ«èô²*Ê㨵pc„é�‘S�ä-¶¾ ¾®ÛÊc!.†%¸•NpI»P"4OÆ6Ä‚USã7g}vJá¨tÞ8ž!äÿ™Ÿ=Ì/Ñ(£5çÞî û¡�ÌÖÚ¤gÅÊ: Çy4ž½Í¦ÈoÎà³WR©îMY d­bkàÉ9¸›}·6ôA‚){n*TU‹MaëÕç@£ÍÀSnRžçÃÀ�‹Hóæ­»ž˜4'äÝ©ž¸”w&LñÆZ§RÕД¸æí®^2ÕÓ1I\Š6 ¼ãxrÒˆvÙÀ`'"d‰ï±LFs ÏøÕž¹|°,X®¼ÛpÔHÇþÈ¿Rþi­}ü@Ë :RNHw«Ú‹ï©�½i›JWÝu�Ú� žc Ëô«Ñ-w&Øã²©)Æ@ì/íi‰žP…|ÖŠUäÙjÍ�‚²0�-}ìi_Agòº ÓL†ýâΜ]€æíokÚ cMé›ô7\Þ;£Ô\¿Œ sJðŽ ×7;ÎG“\—¦áÒÀ®òù�_h¿e3¥õ¶¤G·¿OÙ¦š;9ÊØ˜0jxDZcÖ184â @ü ¡"g½ˆë,ºæ½#ëÂl†Sf¼=$¬Ýà�Õ0GEêùý�m fÒfß›Þ�Óñ7ÃçGæõÆs+5Yð ø wõ8;3¨F@Q•С×jôçz1\²Õ£±�À‹�>'øòäÑœbŽRÑ]6f»Ùà �ý›`^¹lʪÓ(Û ¥æ]FÛ�F¤~k»ËhÔÇ;঩ÚQ3 ÉGqáûËl�%{èø/„tÿC"‘.è°®(æ¿ëGc5-~ Hd.fuj"_^¤ù/ÿN‘.åá’º(Úš²'/ˆmœG;�lW8ù 1ˆíVHXdþ#xŒÆ/øfµ¨²Ù"¾…<®Ÿ6õLËU(‡`24ö¾§$8…|gâ‘3²Ãç>ßl|óÃÿÃEÉ ÎÒ\9›¸d²(ñŽœŸ›…ˆÔ®ýÙ{üWA? tINïß§O¡ûð‘È¶ì ¡øžÐ WÔŒIr†:C̵k€¹ ÜixrùöHÕ´›X•x^õOŠñ¨æÞõX‚a}íü0õúáÜ"&r…Áè.�ÛL¯5Cª0~9f–´—Hþ‡pá”HÐí?Stº•Íú8lyÁ9\²Jh뀸Á«ÑC›ˆÖI^áâs®X2šä2÷'©h½‹„¶B«îz�+æÇ‰þ”¡å—*ÐswQà'}ÿ`#–¡ÒãIÇjH'kÒß6.S1ð ]÷Ì­t.A¿lÔõDbpNÉ”NÍÂŽn‚L¹4³¾ÿÕÌ(©t'ý¥ �”n¨0€ÒRÚC«NË›»c&§à0’Y(¿ƒp�uΉ( n4±ÿ|üé­/ ô°ä¡ÛT§)&`Îâ7¡ évƒ5 yY„L–;…פXÙ…­�Ùdïý�Dû8&�ã5Q¾Æ!fWPwž4r�÷]�Ã&såM¾ýɽ8ñ-Yvœ9u&¿Â…tºåÔâè†|Ÿ)Cy2¬iáIyŸ Xój5¨2%�˜ØtÚ�štÅp§ÜÝÅ:ÏMíÒ4Õ­ù.$s¨Ð…ñÔØnîvç¡;1ˆJò�†V�̺š ÿõ¡eÐ lŪ§ü€ÒIûiØtëM"郬Ÿd>a¼†$OFðõíÚ •H×¹b7Åš“«EDþBƒ†2¦Ò�ß0¸FŽÔO¬—ùžõa\ 2¹…”ëü>ù¡âQAÌJ;¦Äç8xPÒ‘Y)ö›…ý=ºÔðö�By.åžyF¹?x´€Û“Ñõd‘¯ÕÑÙ2ÏvõÍ:  Ù)B͹fêdµá"cªvÌ6s3¬‹N�oÉS[ÿbú'› á€Üâ£ùN~wÒ~EÜž6Š7>ðFÞ ‚êÙ§LÄI„ís\31 ŒF¡#É)¦CÂéÏK/™�RÿƒQ©Y`¬É‚ö.n_gd¦;§p«n‰Ð ˆƒnNÜŽü˜3�Ð^Zùq¯–ÖÙYf.D—^¬‘Oå¹%ñÞˆ´ü¬‡Z&9nØã•„l½QhræþЙ’·y4#«ERïOŒ©—‰Jíë ­Í¯ÁÏ¢?ÀÚ˜XÛceç–kâ�<5$ì�æ¹(æF[ ârY„ìUZ ~D†Â<{Vû¬p1 Î*O ´W¬“…ÒÕ7»�?F ”~�¿º í¨ÕTƒ—Íþ¿åRœ—]T)Ìðó'ã É÷˜ïQiÉàe ïwäRiþ¢ZƒÇ´éÄŠöJµ¾‰ÉM[õˆûg9¹£žmn8.˜!·k‰™ÈVÿõó¶ι²}÷�é àF&x¸ÌÁ V®Üƒ‹äü:y*äNØ©zªé›úžÒæí dØ¶Ô 0cíh¯Öi‹ÁP³°)—P”­øýÒÊßùcS¬Uð IM¬†-ßÉ ßß·N3Å,, ”ߥڑ”E4ïy`»Ò-5ë;‚´³xçö-}=F¶‘ é2€=5ÃÔ°K›Ñª`sðæVÛz_{·1Ôa‘ª0@�iͪÊ娇ûÜW¯£3,¤Ý^ÛÕÔG·Gµ¶‰4‘LheÝ?IÿoƇqs‹Á“ZÞiDZ6 üƒ¬Üü(‚á(²8R_ïniÓõ^hS×åÏ"ˆüȬ7J{ЭdYÔ7I™¡ÞÆ![vúàØÇ è*:ŠH\iËz¿éÁ-½ˆyÓ ç"¾}¹éÇ’¦ŠÈ'j¨n„ÖUÏñ̯ÕTãáé¢Ú‚�Õè’—¨À‹@ŠXy¯ZCÐÍÆ‘ãµB†ª6pâߎñûµ¼ôà‹]>ؠΠUC*`ÖïußéôÉ£NÒk8ôÜ· Z&f¾Ñqš‰¿ê»s‰ê«©–Òy¿|Y2¯t/acK.“_úÏ÷€^-?ÂÄ0ª“ •X%+FÅÆGë_ÃËp`WE¯€»úÈ?¶¯;¿í�Ûø<–µdmflúñ�d¯o²{„%¾&NFõGÍ¥êÎvªáüŸxÞY-Š F4Üy$¾7­Ï’ÈV«ñØAž#" ö¼ù¼¥âõÞšŽGMy|sŒ¼íÛ~EF'fŠKÙë `Eø¦ÔyË‹�ñJ ‚>zªùØn"D·Âü~†™”“‚° ©d�ªUZQmbá,AÁy¾ñ‘쪴a¨LÔ'ag Ýì`' „Z°Æ8 9 ½\ùD£v±k2ò6Eç± ÕÇXZ¥·v�Þî¨Éõì´´E·%Ù×�¹bCL ¢ÿæ³3ða½‡¶n›¨~dؔӱšî°N®÷�_Î[ܲjÈ?ÈÿhÃ�réâä(ahsÓ¿Œ+©1Ë·S,ë~.'J€kþÂã4ÏÑyݤÃÿ‚È7â�ù][ÆÂ‚”¢ÿž{—¥ªx^K“}Ò¹à e…¼à¹3|Øþ°ìæå…Ò7³²ƒ°ð…ˆí®òm@ ß â\ÈéÞâ/Û$(±j,"ò™2Þfvò‹Îm�…ïÜþhànÍŸ´õ{çk" ÆL~>ŸR> þ áÃta¤ô›$ŒGøVõS`“Bn' `œ0GÂÆ_ endstream endobj 38 0 obj 110085 endobj 39 0 obj <> endobj 40 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡G�Ît‘øˆ’®>R4éuw¿¿Ï·õ?Óåø�oÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:�ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·Êãé�sM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§m�ܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ�~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒßè·RŸ~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßá�tF8#�ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;Ñ�ÈDt8. Pi�|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-�AÍÄ�NèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8�eÁM‹³<—“#artË„F{Ç�N‡® tÛáÞ®Lˆv�qè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»�õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G�¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿ�dØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 41 0 obj <> endobj 42 0 obj << /F1 26 0 R /F2 36 0 R /F3 31 0 R /F4 41 0 R /F5 21 0 R >> endobj 43 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 10 0 obj <>/Contents 11 0 R>> endobj 13 0 obj <>/Contents 14 0 R>> endobj 44 0 obj <> endobj 45 0 obj < /Dest[1 0 R/XYZ 56.7 773.3 0]/Parent 44 0 R>> endobj 46 0 obj < /Dest[1 0 R/XYZ 56.7 574.6 0]/Parent 45 0 R/Next 58 0 R>> endobj 47 0 obj < /Dest[1 0 R/XYZ 56.7 439.8 0]/Parent 46 0 R/Next 50 0 R>> endobj 48 0 obj < /Dest[4 0 R/XYZ 56.7 738.4 0]/Parent 47 0 R/Next 49 0 R>> endobj 49 0 obj < /Dest[4 0 R/XYZ 56.7 523.4 0]/Parent 47 0 R/Prev 48 0 R>> endobj 50 0 obj < /Dest[4 0 R/XYZ 56.7 329.9 0]/Parent 46 0 R/Prev 47 0 R>> endobj 51 0 obj < /Dest[4 0 R/XYZ 56.7 273.5 0]/Parent 50 0 R/Next 52 0 R>> endobj 52 0 obj < /Dest[4 0 R/XYZ 56.7 123.5 0]/Parent 50 0 R/Prev 51 0 R/Next 53 0 R>> endobj 53 0 obj < /Dest[7 0 R/XYZ 56.7 785.3 0]/Parent 50 0 R/Prev 52 0 R/Next 54 0 R>> endobj 54 0 obj < /Dest[7 0 R/XYZ 56.7 731.5 0]/Parent 50 0 R/Prev 53 0 R/Next 55 0 R>> endobj 55 0 obj < /Dest[7 0 R/XYZ 56.7 677.7 0]/Parent 50 0 R/Prev 54 0 R/Next 56 0 R>> endobj 56 0 obj < /Dest[7 0 R/XYZ 56.7 589 0]/Parent 50 0 R/Prev 55 0 R/Next 57 0 R>> endobj 57 0 obj < /Dest[7 0 R/XYZ 56.7 500.3 0]/Parent 50 0 R/Prev 56 0 R>> endobj 58 0 obj < /Dest[7 0 R/XYZ 56.7 246.7 0]/Parent 45 0 R/Prev 46 0 R>> endobj 59 0 obj < /Dest[7 0 R/XYZ 56.7 161.2 0]/Parent 58 0 R/Next 62 0 R>> endobj 60 0 obj < /Dest[7 0 R/XYZ 56.7 125.3 0]/Parent 59 0 R/Next 61 0 R>> endobj 61 0 obj < /Dest[10 0 R/XYZ 56.7 574.8 0]/Parent 59 0 R/Prev 60 0 R>> endobj 62 0 obj < /Dest[10 0 R/XYZ 56.7 258.7 0]/Parent 58 0 R/Prev 59 0 R>> endobj 16 0 obj <> endobj 63 0 obj <> endobj 64 0 obj < /Producer /CreationDate(D:20071121223502+01'00')>> endobj xref 0 65 0000000000 65535 f 0000398274 00000 n 0000000019 00000 n 0000005274 00000 n 0000398418 00000 n 0000005295 00000 n 0000008924 00000 n 0000398562 00000 n 0000008945 00000 n 0000012824 00000 n 0000398706 00000 n 0000012845 00000 n 0000016890 00000 n 0000398852 00000 n 0000016912 00000 n 0000017489 00000 n 0000402326 00000 n 0000017510 00000 n 0000018171 00000 n 0000018192 00000 n 0000018383 00000 n 0000018675 00000 n 0000018836 00000 n 0000091906 00000 n 0000091929 00000 n 0000092117 00000 n 0000093062 00000 n 0000094026 00000 n 0000168361 00000 n 0000168384 00000 n 0000168579 00000 n 0000169524 00000 n 0000170492 00000 n 0000283690 00000 n 0000283714 00000 n 0000283905 00000 n 0000284850 00000 n 0000285815 00000 n 0000396013 00000 n 0000396037 00000 n 0000396228 00000 n 0000397173 00000 n 0000398142 00000 n 0000398220 00000 n 0000398998 00000 n 0000399054 00000 n 0000399402 00000 n 0000399566 00000 n 0000399738 00000 n 0000399908 00000 n 0000400086 00000 n 0000400274 00000 n 0000400404 00000 n 0000400598 00000 n 0000400788 00000 n 0000400982 00000 n 0000401152 00000 n 0000401320 00000 n 0000401518 00000 n 0000401702 00000 n 0000401866 00000 n 0000402044 00000 n 0000402211 00000 n 0000402452 00000 n 0000402518 00000 n trailer < <688B732FB3220685B9413720A9630D31> ] >> startxref 402705 %%EOF heldercorreia-speedcrunch-e7ca37f/doc/legacy/new_engine.pdf000066400000000000000000006477731526573132500242070ustar00rootroot00000000000000%PDF-1.4 %äüöß 2 0 obj <> stream xœÅ]ËŽ$ËmÝÏWôÚ‹vÆ; ôTWï àðð€µñï;^$OD03«ïÉ$èVWeÆã�<úlL�EÝûü–)Ä÷¼ëíËö�-Úcè³Ëûbh‰: .mñMt1ÄÏüßgòùqm–ÑË÷L7?ÉeHæz~�‹ô·Ô—™7â茲�yÔñ'�/òpújeü’™äñSþ¾)oíï’'}öç¡…Øü�^7ƒø+F^¹jü¸r©ÁÍ0¶y lryhÝ®“|ñ¹¼ËmöéÊŒmžáÞÓÝØq$³(››,má.Ó­‹�å«»+.'�ÆæÝÌÃ/Kv ;Wæ á®¿íªÖL?Èhã6V6û½}ÐΊoc8XèîiyEÉþôu×m�R[5‹N£;…8ûáp†D‚Ïè ѤxåŒø† jyžNi§ã9$/Sõà¿ú‹`oçÑçï„‚ýjaÂOL€Ÿ>k5Pß·ÇB,k_õã?º+˜w·p¨ޏïIKØí~Ì�kÙÿY¬7µ×%Y,Ûª~vô ö7ÇõÈòB¹ ¸ÁƒƒÌ«Ã˜üšñÈhžwÁe˜4¯a["8OÈ¿ôž4G&xÍQy‹·²"ÅÍÎÜ¡“ÐW¾˜ßxäñåR¬#•q»D0Hàå¾òžGâû”-‰#pÓ\˜l?]' ü3Ü6/À­½ÕØÓ~5D¥êã*ô²WëžÎo‚�£LÀ>xés_#Z™v_!'ŸÂHù%¹#7:þ+ŸéT$ÝøÌŒ—÷}öš¦ƒœG–VèH4Î+ôdù(L#&ò–ü£¾ÛuІœxÌ໵Áœ�ºÖ‰<84ÏþÜqÞ“2žDNNüó>¾F+ò¨;л¾þðf¨”½7�šquýþÚqØ3†ò˜!xwC•éߨºûðà=g/�Âú–´„ŽùG´gq¦üø£õÁG7m+›Ú�šhÞ>Û³3®�JnNñjKê¤ö㮀füI!#éCw±W¼«¸@‚–(| ‚Ø¡„`S¢5¹4?“p/á{�˜KÜ›\l€4»…ü"b:û»|ÎLÇÀ.G °:b%�gô!ÏÓùró´$¡áçq„íÞT¾sTϦ&q ›¬°fÅLû^Ø0'‘²ýaAöoÈäÊvÇG°wã‚f×’ÿF\ÜæoO—0�´àlr©Ë «K.ÆèdC%Ú½£†fíÈOЬ܅–dO³¦;´%ÊMA¦øŒ4±¯£qY‰¬m°@$]÷(‡ÄÖ¶´E¢¾”VHZ"BÃæTÊЃp¶~I[Në_ö%bÞ ÉÕcöŽÉvÈ7esÓu;½@±Žù�Ÿ�Ƙ‹˜$”ͬh“G­êoä†JY"m¨,äè¿K.\âàª$P$Áý$�„{Ž�X¤èLü*_�/Ú×SwÃÜUHÅhö׉9ç4›lQ1ú›ôdsKº{š,Qz‰É2ÕOË´(z �ŠGª¡ÊõŒ.ðÊ{ Á¦[�ìîG¡,D–# ¤yIZûˆ²ä*à?Ïr•Š(?Ï®}L%Ú0ÍÄ@êTŽÊT˜—ÿmÆ/9ÑåvÏV””ÛâU~hc£1§¹«B¤)^ê¢Xç¬zð2 k7<ì³ÿ^¬¤Ä¼L ts&9“Ÿ±\2ÍE´iqÁîö§ëªRBS¢/:ˆ¸¶Æ‰3ù7‚Šúă“ÎÐ<‰8¯yá¿çtŽQŒ$ŒîðËSþ5;Ìò’úH>‹sé? ’:i¹”’/q*-;6.X|ÏÍìâx ŠÒ¦ÓäVNA·•˜³¢î¦©hµÑpS ÓtjW}܃"é�Œµ�Û`ùìÕØ9*ž%s$úž4bŽ$Á»%¶Õ›o‰„ŒD(eO"éÁspea~ÍìÊ^Ñšze&¢jØIX^Ë+Z²³nñí.®6fÇPISqùÁi?»W¥L+²€<òÒV*â4Ï]¤@kˆ.~¹/»È/W"þ‡£ÝÏ|àTÔªi¨#D§U9/&j É•®Y'å¬]ﵦÖ+¡Õ„¥ØDCþèÞ�~Fù;�§ÛúwŒ$~RSºHŠªÜéßáäÁG­!®Pª'IQ’}|7 P~½–-ÒÍ"+-±«hH%2Qw,~›“䆿ô¹§*«æ>ÃÙÛF#b ý™Ì™ˆ8H�±fÞÇŠòdƒv;µ·ÓõŸê{&Z E¥úbG© ­ý;H’‰{-„D/+d7 ÄWz´q*jï eÞQ: Pè°~’ÿâJ'@ùT©0hZGw¥¬yØ z=¬øÑlj[Æ®ÎÚq@ÝD*$†ÐÆ[®åÌJŠ÷ÆX»1„´h�ÅíÒº÷g&"ÕñÖ @èây^TÏZVëž´n2@gb¨6s`¡Œì+ÐzžÈ´F…Ù 2ý—ò¡ D6¾ÏWoz©º—/ çáÊó¸Ï Ò³¹„ì6nž{G«Å/#QDÛž²ˆ�ø~rÊŽPý[ä_ñþב~å܊ܰVåî«“«¥­dIX÷òàë³Ëµ’HïKô½ÅÑzÞÜÒ¢-l‹Â¬Ôae„Лb¬¬ŸÖÆr¡Ôj€ä;ìïf-Q ›¼õ‹&¾¬õ©.·ê!J¹@¼ª�K:¼h¾„´!˜ûîIöìIˆJ{IæZsû;8¹¢Y±ô©u*}Yb׫lWÑJºÌTr».dÓݦ�k yQñM9t-¿½�ÊS+ÓWø_OèKI±uøÐqÌÙÏqº©�»CiLk%[ñЦ«=°;Ðz9 bŒœxö U¿®ÏGbg! n{;¤™b¢Ü0³ä¬¢Gw�D«Te z°3ßKaÕ]‹››ûä´tÙðG¼åfë¢ D*r ³Ò–¯!z¿cÛ�@v‰RgIoŸVÝí-.¤9”‹ûÒ¬^ R]F˜}Ô#?íÁœò¤=ä1GñO}àPÇᔥ]utãŸÜjc¡z’Q‹X‘9º¤ÚÄ�…ßÛo×ÔŸ`çþò€ÉËMÄî6h3ØÛ½ªŒ-•·­xÿNµ…lê¼£ô¤mZè²ô½½N–ó#®Üž–ëÄUÈ’hTAƒõM@ü!Wf>©UkªãÙéá‹Z.0î„“ìÅñn«½œ›´Ë`Òj"b� î<äµf…þ�­¸})rXœz`‡€qoûj´ù—Y¬Ç «�M°²ko0á%@çÓ)#QŠìc³]©C#(¼•+ h�å«Sxa*~°¿×-MÖ-Á ù>ïGy�êÖ™‚oš~®“¯òéïà¾Cq>Êï £n®FŠ´âCÖrÃ†Æ p5¥yPÚ6h+£yKÙ„»"†ƒ[÷ÝB=fîok„w±·}!¥í/O¢Oî@P©yPéßk}¥õ�ùsAÑ艶�V;îú!ì� …É·ãqBÕz$p§"IŠäÏÃø²Á‡¸JÀž-µü¦�óÏÛ¡ÔÎWY–{s`ÁÖÄH›÷å[Ý~¬²¿“FvìŠÂlû1[Ž™ušÛ~Ý“1öcäI> "%LÛ±oNQMåNì_ aüh]|äáªo/¢w…¾ê«*4 Uã~gg:®{÷*¶x¸ùˆÆm«½ÚR0©aäÌy¤K9rô¹¨8GjÓ”<ù6ò}w¿I\ˆoâaLo¡ŒäkF—‡lÚ¯lqàÓâ#5Û‰‰r³ýj¯Äþ™=ƒ®Íªµø¯[’¾{îl0¨.â hUÐGÏöÀÙøP$¨z¡—ý¶ÏÉ”ýÖÐzð¸-§î­×ècÄ^Ò" $K"¿Ø™®ù5)<ûVܬ�xæ€+þ¾¨ˆÍ5àn’ŸT Gvoe¡ÙÕsŸ ŽÌKgB;äJ/u°êöƒ´<ÉÖ¸«áðinŽ4ù„Z÷òd˜†^2õžl,É툢Òô8Ñ~ ¢ ¾Íf:Ï=s·•F ÂÓa Õ$Šò£áûÎ$|X «z§–¢[]m ¼õÕâ É�lˡà ‚]oâ ÑÀÁÁ4cЕÞ×Ð!òÙÉq½ã`vû«ëì‘r–�,b�¤BŸŠJh4_M,—dØÃ™ñš%+…ãön`W·¢ NÜÄF¾¥v©Á(Í67ûú§ûä:í¬'Ç«dð8E¶-EG ÚwÖàÌ"‹¾tTä*Bž÷Z¸ÚU_4KŸ´õ'€ÄI ÇIà­0Ñ(ÜÙ×[uwfj"’ó“0Σ ´Y“^{þÞGkD¡ ïZä9ræF1À)«IÞk­˜‘n'ÇC4úÔ¦ ÂäS%dK»æ7ô§‹VíP< ¨wØ®¡iÂö®œ'Û±l ýnÐ5@ªx᧨ß�è 뀑ÖÙDäÙÆKÒͺ"æZò¦Õ ­ÜÍ@˜\ÿí\ TNÓÓ›„ÝqUÊ>m·u ö#¸&–CmÕƒ~WI )„‹Å[Ëéóš T{}m‹ÍÐK2œÐè½$âçÔöFÖh{áf„/!_ÃÍêôãƒZëö¨¹9¿Ç�ЙmÏ� ²>" ¨…8ÙE—ÇdXÔóqrt#è0¹¶j»ÏI¾f§aÕN_®RAñéÅŒv#‚ |—�Ág?ÈÕ/÷†`ú<ûÐjÓ—z>_0žYÈ´ÝÇÇBr~SÑÿaù¾2G ó©=éÊ!á;JÊÇZ©AÄ�©ÃƒØ»t¬Ï\‹ùÔ“€7:­>¨gŒOÉ oÊy±sË(F»ÂüÎ.bZ…ÙùÂj´ ØäÉÎÛ—}ßеõ9À­ kVɽhžZS%)xâQ(@hÚžÄìùoý&/¨ Ol ëÛ@­ªÆ!ƒ£žv¶›vÜ$'WhÌy5êÛý|Êe8 äÀ”Š&.8«iÎqÎî|ÔýàÒøñ~úÇs È"³ªTÚé‡é•W¥£‹kiÊ{5ßa>¸¥~¡ž8•å’kèš$åD4ÞœžHj×–­gÃÚ$ÿ°t˜ÁàQ@_Ž]mCBçáú€Ùßõåäß?äø¬Tà~ëñÙB^ÈGbGË}°`±íêB/‹}�Ëõx(”¥¬}%öòÍ¡KJ"²ïPmb†ö|¢LNÏ<®a{¡˜ŠX©ØÊr_¤m©¶ÂjÏÅ€Ì24˸3&·¯ÅýÐ y$ÞÖr}ãMB°ñÉ/¼ZmÖðù"5ÙF2!~õXLmTp£]¾&rJŸ†›¿q~=Ûs~ õ›M—ô�MØì~É>=7dA/H·¢�Ƶ/ÅëBÎ�{>½„‡qÕ…ÿDtÇÌßt±™ª¨ ý´Bìà {SéÄè=™gb4ÖbG i=X°‹si}f©'’hœÝ¾šZÏëõm 7iÈñÍ+Ç¡Ÿ¶(ëInòËû¨’Í"TkX½ñ&mkÃ×p©Ú†`} ð/Ë|ÿ�j)ÞžÖ¼k÷+rf½Ì”õíÓ6wM�PSË]är@6À¥;Ÿ­o©k*P•ws#”‹nwÞ-ç/\pt7‹œ±|ÊÞøóYÜM=ä˜'¥„îɟΖAµIì-ƒtKtÉŸW!RÕïp?Fߤ^½t&�SQ|ü°dY(æâéý ”rTå ÏŸ9Lfœ.±À^{Ùrè®r Û jê¤4-ÕD[úˆ"ö:×Ùšeº#¹sN|iŸ¿#Ò{b«ß>$Ó_M É §V;Ž×SL1=g�•Òû69¹hª[œ2›T,ÄÔIŒ�PNTŸ=ã°'Ïh`_Â�zG�­¹Õ^Ó–]W<(¢É_eŠPµ|¡’FÍ™-þã.¶� ýÿÆÕW½Üé•ÈÅÄ #'Î,‰\ä³D™®X™°”Bú+Wн�Í+G çHå±q._µ×±y©þ"Ò©¥ÎbŸšÁœ;îfcU¶š]·j,~0¥8»õAã .ý#p§_tãé|�1�ÛoTê?\¨¨ÅN*ô9A6ñU•Ðg ¯±Ÿ½ik!_-A¿DT¤¼Ò[I¼¯‘)Þ`3·vc{;å!Æ(¦x#ã›Ë£y.ªˆºá× PôBÍøW ÎÒ½r)s�e¢\x[­|8¤²SvbþvPA5y¿’¼þž;-§§Fb-õö,–Š–6œŽ¢­ØÁî.ÚTøì 4ÝÇC 7·QŸ£¡ð¸‡]škk +Ü6 K7Ö]”Wöç¯UÄ|”êxvªÇJsÚ®‚JtÙs6x£´JìŠp ÇÔÍ¡¡Ñ�%éKÔzå[Ç ’T6<�Nø)døzEʪ#%Žƒ÷Éõt‹�®NhÀ»�jJkƒßc=y‹÷ëI�z/O¾\ÿ*=QÛz¸Sûcÿ: ¾¦Èâ¿PèêÆPe0tù›Y"�ðRØ�R.Ÿ¦q¹¾6��º5¦^á€ñÏ¥›Ïz,ü ̓’@úV¿]ˆ‚Ö4׸T¨gä"ºê@ �U vÊèÖFl»þërõH¤ÖA«Ä­¿ÿåOêEΓ—ÈoQ¡ÄN¬Ù¶K.]+ý2Êüpõ��I~â4ÞE\¹¨Ô$ºÆ] �oF¯7õSë—Yk Ïnbžÿ×·ÿ™�V endstream endobj 3 0 obj 5506 endobj 5 0 obj <> stream xœ½]ËŽå8ŽÝçWÄzѶ$K6Ð òƽû˜˜0‹¦7óûm=H‰ô#"³ª×¶DñqxHÉÓÛÿýøß·émzŸß–my÷ok˜ß··¿ÿÇÛ¿ýËÛÿÔ¿íÿüý¿~üüõcsïë[Jáݽýú÷·¿¼ÜÛ¼ÿ×¾ý5ÌñnJá_ß~ý÷7¿‡ý¦ý7�k\’�Ëþ·)¹òWïßúë+ºýÎ¥Þ5íÏm×?“wS¹:Çý�íª�¯´ÐÕ�®>bpSüŒsLqÛ³�¥ü&lûtè7õÍû,ë…´• ?»½�oHñµ?t®/ÛxÀ)•+«Œ´þ$ðpҶ߷ŸO¸¾ÃÆkxkZÚ{W˜N*¿a‹ŸuN´¥ÀÒÞ¯o m’[�ÉNÃkw1úäëÏyMYŠvû¾‰þòT£Þ¥íöuuûÜ.ïg¬bY¼Ü´ÈøfY‡—{Ðøfyžo2\F¡®ãr‘Pø1 ÏÝÏû;«¤ž¿~üÍTÝeÛØ«®ŸÛshŒ~ò<ÂdkG›¬Ñ¸°Ã el?ëSÓ{ä«í®À¯ã'÷ôÃMa‹OâÂCLa_ü-›M·$aâ×íCx Ú›U¼Zn|6Ër`5ŸÍ2gYšfâ\�Éuf©L®Æ“¤°­>K—µ}Ž®­ˆ¼ô«Nl¢$a¿¼d TGуc�ŽN4Ì5IóK·ÄæalÙwåÇTÙx–M“…Ï“‹i—¿Ïf˜ÍãH—)›¬¥�íE‡ ²žö·äÉÒùÜ}-ûÔíX¬Eb¯¬MÍEx¦:JH¹>ÁÜ놼¡)ïálü´ÿ»ŸÍ²«qÊ‹(Ñd«ð ½Äözã ±S3ò"×”Š×Ùò<¤(3¿¬¬úg»îĵµ°ˆé!Ì-EW³ ú¢¯s›\0åìf˯žd òÖýŽ}ívm£‘ûÀC/Añ¥ÌMìaáaˆÈ?‹Y=<Åt0í™BE™YGóZF¾&åTó|‹ÍÐã.´e·Ë0šËšõE‚–,“ Z¤­¼ö.‹í™1CÜ,"’ß›ûeß©‰ÙÍ õù9¤•`�>fÜal@ã åe�‡0‹3Ú_ÏpIÀÕGÃíÃSi{x~l< +SðK ¼'ÑRGyÈ6„B‰Ä¹ÓšwõWÈΈ Õ“JN$]±Zöq±½Z~Hâ›Ø[Š9ª+Nq!“ƒ0û�hEwe‘ìÒ}ÕñV/\Ÿ± 0~¶hmÅ—vÑ™q?¦ î‡øQ I`íT€´ä·6§õj’ù�˜ÃóFÀACIr�v&ƒ#�9HïšÑÐOö†>¿ƒ—"MèuŒÅ4d,Û»S~ÃÓmG2NyŒq�÷� Ó]87ë¦ÞµÍ:2C� âͲ÷ PF�¸üØߎ¬’°Û¶¶ÿ„ƒÄEýBv‘û©ËÔ z”R¬™b8Õ<‚}2±Ö–yÁ€5-¡ÜfßT1 pÍ Þ‹PC<ÔØµ&:Ñ­ÊФŠ2DÁ9Ó’2ú&�ˆ†/éÎr$š»nµ93€MÕ7{0•ƒU9J\,ã3f°ôòÂÇÄ8‚ÚŒ#hI$CLÙê�âñm:žÝÔ¥ýfN�–=5šbÖ¨Œ» y1êøÐB £álÙ`ŠNmdeÛ�¾ŠÈ‹6”,ë¡.qNü×X ðQÜËÂø/Nz9DÙ8EÛ´æòU&\À ù,lB¤ˆ‡ddC–"¡œEYx?{Â>ƒ>¤†ö>(,,e±¢rîµ{�É.°4�ºŸ£»V¿+G0Oªva;ïúG¨9¹.êØ5§§Dõ³¶tßOhåX$d%€"o¦òÙÓkFX0†Ó§ÿt¶9�ƒ’ î²AG+�â[omkp@¡U™bwš—/uFëÃ0_+¬‰{�iÕ¥ QL)ƒ­©3G_CU¡ Àö³vë“TW�˜[þ³H6报ûœ8.·vüi d.òD£ÖKÝRä. Rñ[UäZ4¦ÙK¹€¡ó€ì-Ƥ„zt�[¬@mQ)/ncõÓ�ÞÜŸ°1Ì;,Yšwå�f¯Ù±ó¨…o~6*BkÛšš›?ïß6 ðx�^ Ñ_Ù=Vü‹áf’pã’Ùõâ%Y’¹®�ûmä&ÃÆeÃy‚0Ö|Ð}܃“î1:-™&â5¶$C½6ǽ² );«gREQéhž±šwP<) ‰:Y!ò›KߺÃç õW%Ê>¶.Ý ²9êcãä’ÎB9•›¨DàO+™¢ì¡2*³T«^‡±Ýh‘f©§Õ*[¯8lš¡(:OçQÔr€zórî”!±;=½¶väz$5|9ÎÛ* O „u›�äº5©ÅŽÆÎîWï† ç t WÈ#GQºÑ90IÇlW€t¬hÇÔà_è@ÚÝ–~ÇÜ�]Ô ßÇYK  Î1YwMf… „ Úò4;sý––^)¶_T¿œ&ÕÖ€æVIM„5°aSp7¶Â3w÷u}»³±Q¥Á]n�Ì ô]ìöë佇}‚H%Å KOæ“ïYGÅv•FÍAuDhù’…qÆÔöàÌÜIì�úR?_"O`¿6î\EêésH)þÉ|m«�’½Â8+þbž —­·“Öeh=„àõ•Âm’ vÁužÎ7¯R"¸�D†;Š«ãªù=îaŸ]íÑÉÇ#”ÆäcÅå ËR®+÷1MºŽÌí˜[±`!µ”‘Ò¨Ïeãè3‡R7ìfçB2Xh>1¤ ÷ûÁSYè†ÈTµ±€Ý«hYKˆÝÛ38x,ÃAÝÙj3È]Yõ˜[da~4Æý�Ù@i� ¬£½A:›>·;|[àŽ›êç&pÅOcw]NMš•™ÿ\E¤¯2:˜n_e,-`+#†cnÁ°’ Ãrë¢zY�Ö\j›ãÉV2>U*�v¥"£M¥ÌìR–â^˜[iÏNÐ\|s—ãm§Ê¤’ì·£ÚÌ#c#yµ,8 Ålä«àÂ;ì”+»‹ëì'œÕæÁ)"¬9eAç­FN=Ìxî P\]�¾íóÉéHû, Ä‘º7¨ò¼ÒŽ»ãNN#ð¹*léÕ•*¦Yså]I;‘WMçìh*À´ÈÞ¶÷í>®“õ“lGjÛºgk*4ô|ÎïŠVºTê‰gm©`ƒC~û¢áÓ†:dÆ#fäb/–aÛ+=“-éÉq—ãËPîyp„Ä4z£�%§à!¡~Ô— …5uïJ]—¨Ï8‰§þ¶*c°{ùeÿè<Þ7.xÆxŸ]›eÐ}Å~á\¡ZSÕGÇÇÎKˆ³xFxÉ—~ Æ�ã¦ñÜtŒµ³‰[Zz¥Øåä¦_c�ý¥£LØ•Lˆlp(tgÅUQ0yUÎ0[gîì:ª­Ó›¡š÷*ªÏ õïBÞŽY¬Ãòi0¢|!“g\‘ì…§æ©·Id!-¾ð®KÓã %�àižà¸JƒÆ‘ã âÃc/Ê^O5}øL–B‚ã�dK$¡Ü\G…I8nªÍuäOeãÄ©fΛWU¶Ã ãO>«¯Y¤Ú4�µ5Þ^8'Ì.kmFzc Îjn‹Uü) 5ŸXWHNăó9Œž{‡ªøgzð¦®,ÌÊ~ÃÇ6Òà©´Õ×H�3Ÿ–S€ñp“ÑM–ùf%£5=?J¨ßM‡GHëd竽윑ó’Cøó.ªdµóÂËÎiU̸ÑwrÿÔÛ;‡r§ª ôÉì#€q¶ÌpÊhÍdzÊÖ¿l÷¬¥Šˆj*‡€ÍA{öÆÖ6ÂG='¸>{9®Q>ø¸ãàNGi·2ï\b¬cìñ©|vYš4ŽѱÊ`½KÈ ö0Lí�8àyM,½Òê¨?P2A_kš²Ž¤�65"`?ÀÄä~¯BÉûØ¢‹ßϱ ‡C0°xºUpœ…S&Éîëï£R햺Μ.óŽÈ_'É:˧Ä*’6Èæ.¿}� Km=ÉGà´áæU„¼o«nÙÇ£öú]WóåSŽÒàEí¬9¡^‚©ôWv6Å™‡¨$džÏK-Rëˆt,VäîØÛR°óô- ™¿Ù\þ±‰^n= nmeU`:í6=ãxÝ»Ù÷ô«ßpšÌ ~zï¶ކã9‚;ãOŒ†Âaºù„\ÎßkÈàœú3ØP÷QìÖ¸óQ�ŽuÁUý‘7Â3wqÜ–.”–_ŽT9l%Lº|¥þ^ÍÀ⪌6ýÂ\SsñKŠ ccW�ÜÎ_wÆspP¹@ÙW­Ý�ÉÕ¹†ÃÀ–{{reƒ�2F®CÅ®Lâùç¸�u´vb.0ã‹È©A=ð³p­Y�=ñÝ ÇÇ1¦§YC�´»“NÎÚñ°]Á7íø.Áöƺ�Ÿò!Ë.‡—L|‡ÿ 'vôSq¯t½ûËnTÆó|PC²Â³£ƒÌªØ½íô½.^\9ëS-þ€"ÜŽ{—iƒ=çË{xˆüå(#�¸þw¡·d»3ððKCJ›æc�»:8[hÎÔH§�ˆ`ÿ¯³N‘㪅=éÁPšž=­1¸˜TO÷ 8VŸ¾àXÍ (’eW¦3éï‡?5gÄÇÑÈAÞÒ‹Ðu·#tJa‚ë¼~Ðð»}>#Ïß°Ós©æ†£U¹Ü¹ñ`7bô°> sÛJá I§3)Ý‚@ÛÉ@ï´\©¦¥;çêÏiU‡K0õô…Vs¯qàHsˆR�ñ¸Ñ»ÔòøìÍ ×pMõƒUw4ØG1˜&qaE›NÈùöÞv�³O«–‡h`�ýmÔ%¬e§„ûÔ·¯˜îýò\kxô†Ü|ÿA³ ž«‹ù‹)Ѿnœñìå×ÁHôWzŒ9-•¼¨ÈqAKbú²-„v<†çˆK¼slöXϯAØZ#ÚÔŸHÊdd9ßú–ЉS:4—‰He”’*D›T­w}·ýßÞþRÐþ endstream endobj 6 0 obj 5757 endobj 8 0 obj <> stream xœ½\É®ëÈ Ý¿¯ð: G5«€F_[Þ7ð€ü@ ‹éM~?5qP‘’|ñ€ H§ãkK%yxxÈÒrûï�ÿÜ–Ûr7·�ÃÝÝVoîùöÇßoýÓíßýoå?üóÇ×Ï!Þ×[Jþno?ÿvûóÛÞLù·Ü~ó9y»üåöó_?ÌRþºÔ¿ÿsûÄáÉÙ%¾ÓCÜÆ×�»{ø«Ÿ¾ßíƒPnÚ?€ßÀßýô÷˜“‹.…äÚ¬»¼sÌñ]îú×°ááo©}²âBâC3/�%Ùþ¥p7¸¾hâ‹)âÚï²â]ðaè¶v×5ž¡\Ø.�\MSYôVþ­Üªš®}7z2gÏ?¾ÒwÒ#ÃÎ8¶˜ËÝíX”µ´ õ¾cU‰¾_בà:+>ptõ�ËãÚºjØPw´ÿñÕ>Èøûâ O°µ§ß½êÓ'_þÙW²ýüñûìŠKuSÍÇ:´ß4÷ ùž¦Ÿ”ű2\jÿÀÓ£æX}¨-¬-Òßž;¿Lyì úÅv¾¤r©±$s3õ¹ê¢Â£ý(‘Yº¡"y�kœ|ìð>Kœ<<È�#‹»aõ,å$”Çúð”kÑ]-eb‰µb­0v=²uZº-}бð¶ZÜ™94!0ÈP5fòìUŸÇp¹GC*ûLøSq`.Áu¢ämÎw²ð5KŸöø Yøäëôób×w{°â¶üį "xÅzfŸƒ:ZM( _ëÿv»f)aÒz Ô@¶0xkØŒ}B—ÑVö€¯-t+{âÆ®féÇ1³)kÞÿ¤Ü¦ú)8J�@ØO„Ut×PÝavíäÛ%Ìð«H¨øeÁ-lF“y?'›Ü.ü�‹n1B-•ÇB3·qRüNDªGÃçóÔ<dzô`‰ a¬Ýü¸Ú8-3ÄÊc› %Œ£U"À§¤ yjnÖ]Þ†—/éÆ=`[(†ƒ�>LÓl 3}£¸ƒfÆm|Vßé´§fÜCÊÃ1©±W-4<ÑE†±Wi±¦Í߯B$¥ò SZ·§½|Œ,äê¦Âðžî ¥¨e²Ú» ÍòÛÚÌ1ÊÅó@£3Ìÿ(AÍ{úÜÏzF3{4dsÄ7¾tTiiBÆ|à g7ó­È ™4ø0,=nùzÆP?Ü0¯h\]rcË+^a—è<·CÛÝßöô¤¡9t{ðy?9=\�¸ebéÙqÿÙà»ùØ!Ä.•Hœ±·¡Ð&P(¡¹ ó};ÛØ,- LZ-¢®‚0ÚûœÚj²�}2ä<ïy5 8zõ »¹¥zGÿRbXÙYHýNBø†'ή%iaI™ùÁ6¾ˆ ¸ŠË&Q]êÑ�»þ{ùğ°¿à¢  ÊÖk “\OÊõúvíwÂ…#Öl¸Ì@|ObˆÍ2 ;“9Z>Ÿ&K¨¥Ó†% úé£Y(\+°bÐ�3ø<.ªR-à‘WNìWQ“iyn¦3ŠDò'DX ²B÷,ÎÒÄ÷5Ûr¿k¦8Y cy]mE¨Vô{�¼Æ(G½*8›a± ]IóùÝ>ò}v�p°bí”$eõô�Ñ/M4JeÊ ÏŠõ¸{x¡²�¾q÷Î(Ï�Q½Üë.{áã.J^×>Áv¢õJÍ�yÜùÀ¶~ÖñfÛª¼é×|Ï"ð±Ic;Lbšû€pÞiÒ€µ %µfÜŽW …[Tp0�Mtß[¹#"çFòlMíQ5yi\<,ààÇÓÍv^+µM?Þ$}ñšÐ u)7®õ† PU6Â"²*ÜCAKf�mFÖXy£a&©:KÇŽísM”̳?I.Kuw-ìë<€šP>6–�qr~%È�] a ;M°@ˆ(äèBU‘.v²ÛU­¦SÓÀz*fÍT/NH7›ª%ñƒÙ)x—ûHmL�>ÉUšAaDM»æõö¨–[äY0nUwr˜Õ7d¼¬“«ô•�¨R¨¼S ”„l[ì  +`¥ãøQ{&>†½ S Ð&²Ò°EfõçZ �Øq<˜»UÄW² d¦Ó¾ÙøôÓEFfáx~™€wÈ1?ðhÃBLª‡­q¶™ŠµÊ*Ý�|í3ývÑñ”6|ÐÖ¢!•‚¦oX(#)4&¡ìò°š£^P¿&!�]!šÞ—‘š&Kó¬ë•*+׿Ç4ŸžÜí)ÃêK!˜³ómÞÍ7Ƭ�A»‡¾Ž^­•íaòªú«Ìb"üZd¥ÛñN3¡‚º‹2à?ËÜèçtª2Ú�æj€` Ú¢š”颹µ[È,³¨îœ™(ld%�wúsàÔ¨jG¤.TóÛ+WOVJ·v¬ë |ˆ¸~•ué‰2�Äš&2ÛÖ­6`泓×Âqë(‰¬dðORñybó.+rrpãQ„XI0¾1‘=’ÎǾñœ¯1«É×ô,a �ZLæ¹óÇ7yÎê| Ì’¤Œ�õf&óB &(²¬úš.SÂ-asË�ÄÌ’ Ñ«"DÓDäŽd,O{êÌ´”¹›$ÉâçÝæ_�h€&ibaRë–<† ÞÇ‹¬4:„ŒûzÞŽ™"¶JyÀ¥ö/›î…´'7ãÐÜ6ž÷¹Â%õVá­æ éšWà¶xYÚ'j·0`’•bqBCÔóPv<6�©<øÚx_ƒ5Göé7rP'v®ÿ…YH™ëa˜ÏŒ £'J‚Ñ.xv9`w¿@Ã9ßÍÇ�¢Œíî2ßVfg»Ni¶r ²F>.ëWÞá~q‡%JO²Ý‡o$‚–'‚Fdƒê€ã*g²™×?5ƒT¸R6Í­/"ÁåEÔèöPTYJ˜2­”ÂÀ®¬�ôÒXu:…×Ïo¼S8«>ŽÄ+�VCµ£å?o€HÎy®`Ú¾«N6CuŸÚ«µ«"­cœ3cÕ¸á'½‹:… ü~·yh×’JŸå¿™L°òrrã‰Ò ñz_€PaÎ+¼A¯ÏÀñÐQ—¨úé•k§ ê».A§aøV™0Á�7¾ª¥eMŽØˆ³Œ¸ŸÎ2~sάqš÷�­À'W³›@Á öxüøq -{Òh¶Ör¯ÜÉvlîþÜvõðI¯ÍÚÿƒÞŸ'ÖY•zLð!¥kÔO  Ô©·xZˆŸQ(»c!¡³³EuÞÌ8ŽtúPúN͵Ը×ÜïÊc£‘ò‚$ èú˜ �Ø<Åt™Á»/o+Û‚ÚÑ�!�~À&0¹ xýå¡d­— ÆaÕéºÉD Ü<Æœ).×C4R÷ÛŽÝBÐæUÄ0u•>l1{„ v 7òÒ†7±§vè0G²XI:W~…ŸvP�$Ùšz(ìd—(I§ÛnÓd•{Þ>pK­h~Ê™(Lº¬�xVI™•ô]ŸÇÍ{ýéà ÁG-Pr<ŒG­}ÛˆåQ>ÚJ� äñ\ÚŠÐÙÅ#³kze“™¦ön¨ºA§Žw|=²SK•7G!<ï&'¹ HtfRKµØ ö„ �TTB½ç?„Xl\À§ûUç`—>�ð ²Õß.Ûf7 À¸Ã¦P ’¸‰ºyíb)˜Ÿ€EþvÎ\)0™}¯Ý2½,Z¡Wcœò³Um@½�zhß�ßÀÎÈ´ÃÓÔEuô8Wƒ‹»á–�dófhA½ÇLsÞp…ÏT5ŒRZY¨ù>Ñš:;¬wONøMþýÜ»ûÍ¿†g•²¤Àl5tØV>‚�ìמf`l /¥7‡û×Nc†Êؤe>a:Šå‡%õÜÞi?˜É?ýȇxâÓL| x¿…0‡©•ÏñS0\~Ag»¦ÃvŽq5%Ï®¾ï?AÝoÓ±Þø‹ƒc#Yõ×+�^ª',o³Ì“PkX‚ H^YÐa@`C8¶/ÇÕºC³áb©÷1 Ä Ó~Ä`Ö€7â©ö:Ä=�#›þ00sÃx÷kç+ܧŸóò?'x[mPõ@�@aß�É�›g*Èz�cfqˆgr~Ÿ1…™e",rå'a‘ÎðÍj§»–y¢“7%Ss×+o³íˆWæÊêø(í xÖ&µ‹:û)Ð\¥ØÂ@ÜŒ6Lßþõc®T¼R”2†Ö£T™šLódŠªrèÇã¯êx&`%…P#œ�ÕtÌP á »fÄ>S¼–ïùàc_Ñ8’€z‹ûOÏgS3=r�*�¦fð@ /M\{ïÚ*FyuÎAiÕ(¸ ¤–Su2hÉe»nõ:' 6?ù…QëºQ�Ük?hÒØo¢}½F@ÔBJ`‚+i±¤÷Áe ÒsQ¶aôý“û*\n�~àdx€=ᢀéØ ãƒ]É<ÃI㌞ºzl(Дj�h“¶Ž^opʲ*«Bå=.SåQ# qB`<ŠÍé<ª%ÈMí*³ôDNÙ‹–9å)�µíµ$¸Ó'ØXÇÑ)t->�Ò9>k˜ªj>tpKíÁìÚëOnäTu$O!Är i¥ݰ6-h°ì�µ–Ó/ÏÖÒ.IæJ|…Ç'¼n–Óý,Â]yâÁ¡]‹4»¥:>©(cƒêôͰ«ÌѼ±1SáëT?Ná”×î DD¨-öÈ”w�½«Ta�{MÕ•LLàJüà(è—Ó뎎P^q¥ó$�Pb唎�]®qø,^Îmª¨â̈8^§ìÜ7µWÜy%¼Óa ­æçMFËKI“–†ìxâŠvÃôÀ_=G£‘‘«·Û˜ÒÝé�§³ÔòœšR}6¦aØ©16ì­ôå“6[Ë'}>™½›å�:›L®-ºÊ ÝTá ±7Å’žÒ#ïÑ`Ìš÷IN^°åU7¿HÆÉã ¨_æù¾|î_Ê^íï*¯J8ŸfÊ_xÖl‚¥ 'ÚãÒãì ¾Ù KîFÆ·Ém‰ùÛ/Wuº¬4æJ¯ Éï„“wì­Z¿Cÿê¯ÐTz ŸhvúN}ÍœV†Í�² b›–ä à ›B+;œ™‡,·cšêÛ,ù‡X®¤—>¼‰2ªp4m6nÿy>‹Fþ8i CjÇC�<ï€+5~¿ý Á~R endstream endobj 9 0 obj 4552 endobj 11 0 obj <> stream xœí< x[ÕyGþumç8vlÇ6IÃãÄÔmR;8…:˶ì(ñ I΃�-×Ò•uIWè^Ù14…–Q }„®­Ë(0Ú2Ú&]—Q )i·>èƒA¶H¿µlkiËh·¬ee­ËnöŸsÏÕÖM^úm–þ{Îþ÷ÿŸ_?|XÙœF–’�îhJÍ4y<_�âiŒNZ¬kEâkÿÿìxf"55Õ#ð™˜HNdzƒŸÚOˆ÷}øüö„¦Æ¼�¾�¥Ÿ/Mà³ÓUøÜ�ϯO¤¬=žÜS�©NQµ•¼ A%‰•)uOæA¥Ë‹Ï>³´šÒ¾| Ç‡Ï&Ä̦uùÜqBú9–Éj™øóÞï2Ài$ðÃC„ø¨ñTŠçÿã/Ï%äy ß_%ûÉ�žûð)ŽË×àÊ=÷“›HW¾îyÌsKÅ:\»�ç=B6zMïïN¯éÙŸP¶*÷áßeð�ŠFò(¹€òü€˜äaøl€/yû¼uäpö“g‘ úyì#÷’ëP–&�A®¯¸®"„+ßRŽ�;ðmàþÏÝž'Qº‡=7’£ävðVl"w{Ž¢^�‘É�©¸ãrCEåÿÒ:‚çï ¦—(G=”ØáJ�¼ÆÅçy°N9*ÞÏ“ë‘s„Ü[y¨²©êBäÂ-vŸçëžc•"÷�'áàxÚs“÷Bï§½›È>ǰ“ìCÚwð3•qÏ4êÎß×qêSÞ�žýägÞ�UãHû\#äù@E5Š“/áßTe=êôVÏMp JÊwÏ#Gª6{;ð¿á½?ýþ#´ìò_‘ ªEþ|å‰ßÔ² ¥ã”±v }•²Ï+N¹9)X�Ù÷æ¸\Ä)w‚Ò¨pöI=éæ½ÍXê χn¨ÌÓ¹=OÓCjðÉ#OyÉ'% ¸þ) {¾_ Â_–p%¡äÛ®& ä ×`ÜýXµ�wy\^uäÍËïr`üX²ü;ö�Æåß—p®“0�Ë%a/ilª•°Bê›.�p%©kê�p©jºBÂÕˆß'á%¤¡i«€ùM´¤iBÂrNSFÂÈ·éf #ߦÛ$Ìù~Z ÂK¸’,kz\ÂU¤¹éi W“–¦ç%¼„\ÐìØ¼‚ómn“0�ÕÍíVHCóˆ„+Þ)ájRß|�„—�sšß)`À�êæÛ% ¤¹ù +dyó$\Ij›¿-a´CóQ £šŸ°WÈók {Èò�„+HUK“„�œÛ²JÂh‡–�Vp=(áJ\×$Œöo™’0ÆCË;$¼qöaDy¼KÐ,ë[>.ai9ç;ÆØ=ç9 ®ÿBÂ^Ò²B‘°‚ð* W’¦K¸š´®H¸†t­˜�pm[× —WI\ñt¯‘™Îê ‹­‰®e�ë×o`ãÓ¬G·L+«©) ¦£íÌŸL²Ç2YH3µì¤k§óŽ^Ê�FÔÉÔ.#=ÁzÔÄû´]êÖ–%5=¡™LÍjLO³Ln<©GYÌH©zÚÅ «i³Ç0v=�[µ¬©iÖÙ¾ÑY-Ú�idj¡ ËÊtutÄp}2×n¹lT‹Ù ­=­Yý�‹À•ÈëÍÖ˜šÆÆµ¤1µ¶��€Àíl 9�I˜LOeŒ¬¥ÅXfæÆwiQ‹¯pýâFƒ�+5Ò1�ëavQArê¸1© œ(äƒ mXèÓYå^É"ÀÙcfBM&é¸&­†b`–¨%ziŒ‹,KY­¬ÚÌšÎhqµ;B•î¦ÔiÌ<Óã:45iaè!€DÕXLh'¨šE¹rI5K9£˜fêi!Æ„“«xˆG¨E"&?áÊcÎåÄIRd ¦&Ë�g\9 ÔP¼tršéEaN¹:Y�ÿø¸0¹!¹_ÜôÐ0æ´¬84edc&kÍça+çínÐVž¶­Âdè™A™/ãf§šCp›Lz^0m�…ÃÔLÓKOj|ÃÑ)s€œ’P-–PM¤¨¥Kl£®Ý1–KǤÀQ©ÎÑp1¯šF’gµpw’Ê’¼z`®¸ˆ5º[�@Å0Óå¡zrAU Ѝ%ã\¨MÖ?2aá‘þÈ6(À‚a6Ùì ô±VŸ[}l[0²id,Â#äŽì`#ýÌ?¼ƒm ÷ùX`ûh(Ó‘ �¸îë °<7<aƒÁ¡`‰FFÄQI*sbC�Pï&|ô÷ƒ‘>ÚŒ #M.ÄülÔŠ{Çý!6: �F’÷‡�K`(€J ¡Þ‘Ñ¡àÀ¦ˆEpÑG#!_`ÈÚâcHlU1�ÒŽR" ØÊ‡7ùYO0Ž„þ!ŽË­30<2 ý#cÃ}þHpd˜õPÏ`À‘ Uéô‡|¬Ï?äàê¸L8š£NÁ” BþA �zƒ@;C�ÞˆÀDÛ£%…¸½#ÃáÀ•c¸€x. ݶ) X ~ü§WH&ÔFu9�ÈH(’e[0ð1(æé� ¸ÜŸ#ý"ÆÐžÜyÃR^î#¾6?:‹Ÿ– öüƒH0ÌÅÀZ‚‹ÑØÕ2�m™ÜNieÔ©�>µNÀHcâ:kÄk 3KÜ:Nu+\Øü:ö9¥W”Œn¼‰œÒ›Ô°š¼”Yjðb2¥›"Óñ LÎ�ÇL5‰ÌðÏ"�…µRMâ13/fIBQ÷2Ìdu<2•Õ-,&LÍájV¿V^ÃYyM XAÎ¥Pù³š™Á[JŸÔ’Ó툛åw™�DOc¯–’ª óE­.·U°Ø„ 3,Š];£Tt\§Ý:�h+{fú êôAìTú ZèƒØ)öAt~$‹|TP2Ý;£LƒZhXèéôJÌí•èk£W¢Ž^±^‰: {Z½=ƒ½-ôJì{%ZÒœB¯Dê•Ø‰÷J´¨W*Nß’v ïs,gª]¢²]b§Õ.ÑqÅïÆ3Ý2Ñ´ÁN»e¢g´e¢²eb§Þ2ѹ-;•–‰–m™ØÉ´L4âß:´y„‹íßtJÝ-h~:Ýu»#v:Ý-îŽØ)uG´lwÄN§;âÁZ’(ùƇ.Øø°“h|èâ�;�Æ‡ŠÆ§´wxù†Ærñ»EÓ@Ûñ«}ÑÉUÇ”¾[ïб‚ìiÏ$2²Œ ꪕÃ~ª7—5uqI¥Ó¼µ2Òý¼øòKŒ·2‘éŒ�}J&¡GY¿æ i×ät¼"X�ˆ‘Jᥕq#Ìeѧ«¢ÒÏe å)t¥áw “ÌüI4wTöy¯É`BH³xeÌÌa‡P‚ƒbš£I c‰÷C® >PĈ¡ß\Áµú�Å_†yõÒܽ¸nFHdèŽ ¼»ñÒÒÃܵɂ‰Òa oÝtÑBž'6ÁÙ\4!HúsæµIç0ô°–kéAÍÁïÏ¥¯E‰tÑ%Wdên²Œ~v¹©\ZÏ/qÕQIç�ËL�ä0PrréååÐ0N0eÆ1š0ø{²Znw9e®b¿†ŸØÿix�!I—ÎZã¯øLFKê»vé|•–Œ]˳7YÊ5ž7/å©å9‘^b� ™&Y¢“ ’ ad ‰’µøÝIÖã{BãˆÁHâXÄÄ¿,шJRć«A’Füv„ü$‰oFByZ¦xÒð[Ã3“øCLz\/Ís� §IäÅÿb±¹*ž99Ž}íÂs[I1¢ˆ« jš8¡ �RIãgqÆ‘®Žx ÏÈ]{sé„%2ð½{�Ýò«[…„&Ò5×N”sc nùóq�ïhjI?pÍ-”»‹tà;&ñ'¿ñ ü΢.š8›Z·# ÏôQs­àzb¾¿ù·¬&¼£¡� 2…¸ÜgÆÂœÒîL#NBœÔq/#ä¶„7¹²â÷?§:9Ç*sõ(DP®$‚҆⻜îŽÇT„Š­6?–)YwozBùqæ³²¼¿ :ë¸Cd‰e)aëݸf ^N®Ù¨ —Ô ±¯ ™bO“zM.iéuŸô»ã-‡›cN<û„\†ð~ZœÏÈür8HÕ’1¦Ë(P ÇÒTÒ´„sã)*ðx:Ô] ۑ݉eMä«{­EQÒ*<ÇÏÆÄ·)äŠâUêGED1BS‚Š%v\ûÄJÊLZ“—±À�W.¿…ñëD?çX° _Ɉ¬‰!‡¨8íJX"ÖÆq×»ºŸÌæ(J–T›L‰HˆªcIˤÄZ±F®Ù’¨t¤Í úмÃá”ð§ãkZTAL<í[@_^ÏQA˜ ìäƒC[—V-õþâZ»–s¤Íä#Úr¢® Ñ”°Gê„8¸ÙU;-5ÔŠ8ÆÄ'çáßÜ»#*è98®ÿx'ees=¼cBb]JÚ%²3"¥S‘¢!*CÁŵ¨`�ù• �ø–̳×Í•‚ÅŠk@ñ9&tV…äTÔæÒXs¬áÜ%ê"þ4Ä-ǤïSâ»P?NÄ–¸‰øÍ©J�ÚK,µØYn“iy·8ܹÍãBƘŒ¤¤ˆÓl~Å‘”Û4Väóâ¨soPU܈º¨IñDóÅ„¤Ü_é"kL”Ü«'·†ª"zœØuy̵�ù²:¹RR©A!ÂTᣗ ”Ï\{”“Í'ý�çôª9Í{'+ê¬*êJ�®»bæ#ÒÍ—¹·‡&ëœ&´p9M ­bâ|k™û°5¯÷Ü÷ÜÛ¶µ(Êœœœs¿Œ‹|7ŠdÍÉ.„;[ñ©Wû„_üb‡ï·Šl܆0§8BÆ-‡F?9í¸Âi3ñÌŸ¶ þ0Òâgd»à@ja”laN{Wñ; ñø‰^\ÃgÞ…:ü†ñTDä?Çeq$�àz�k©TAÁÑ•lŸBH“Üõ#í  Çå÷‰þˆÃÃRNÇr!A�ÛˆSæ4{Q¢AñÄWÇð{ñž~¡³#í°Ð¡÷]BÇŽD½ø=м9ÆÊVàœ"Ó'üÈõéç9×-Ë‘lDz™Ã*íÒ–ŽÜþ[óœÃBÿA|3¡W"Â7~¤ïÒucg@PàrSa�1¡Ÿ_ØaDpèxÜŠÜžƒùˆ y¥WØ‹û�KÞ'8ù…EÂe5q©{§\tÐ<‡¡_@XjP`‡ÑŽÄæWœx ]{¥­šNÜ;11XdÝ^¡#÷ì•È5 cÊ/lWª÷Ó6!A Ç~ùÙ[d³‚÷‡¥w]y"‚s¤ŒU¶‰\ ,¿ðu8Ÿ#ý"‡¤äcù+Ô€1Ÿ#yÉJíëæ‘‹w"µÃ¡åò.õ`Ÿˆ§A)a8o ƒ.Bש]¼×¢âwŽ•¯Û¥7wq×XèF‹ûN_Q­-îœ*< pSsð «Î¯%çÎ*üÖ)îÝÊýÂv;½¼Ûõº§v;¿‰Š»Þ˜èÏ�ÐÌw%†è�|g2%v wzFÎNŒ’ßyœ³*î~_ž—{h9}¥*ºÎÍ,cÍ…o(:ï—aFÜ÷—)[²3áúå$._¿vίawþ3߬¬\]ÊuÅöÏ gäo)]X˜÷“í’n–¸¿Ë 6ápæj©9^/D§ÖEæN¸ &Š$� [SâÌè8O*ê•;ãzõ§Ngz*ûZšÑ’yÐÜÎë•›Ѳó v–çAô„æA¥�|´H¦Â¬ÃÅ<± j¹ }ÕæJlÞ\‰þÿ\©h®T˜0ünΕhÉ ûêÍ•h™_k¯…¹-;W*htvæJt‘yÁÙ™+Qr²s¥Â¿u:“s¥B¾•Εº}ž.9¿Ï�Nâµ6]¢¤tºT~ºqv¦Ktë²" ¾¶§LTÄØünæìO™èkxÊDçL™ ¿uÏæ”‰¾ì”‰�µ)=‰){ŦLTØ`+RÝ,¤u¬íÇý³7;¢e}þjÍŽè¼Ù{ÕfGtÁÙQaôÊÏŽèIÌŽ£ûÊÎŽÜʺð�2âCOaâS<¥9“zZŸù¿ÙNmâC‹&>‹ÍÎĄƚG¿›& TðáOí§ñß\u»ìÆ¿![LtMí¢ÍàZi7&þßâuü¹Š”yª¸¡ûøom˜m‚ß´Á¯;á¿gàÅ:ø• /Øð_mðË:øÏx¾ ~q«_ù… ?Ÿ�ÿ˜�c³ðï³ðo6ü¬ ~ÚÏÙð¯�ðìOÂʳ3ðDüI~ü£ådzð£xƆÚðƒNø—&øçø'žn„ïï…Ỉþݽpô©åè^xjž|b•ò¤ O¬‚ïØð6ü½ gÑxü±ó•Çmxì|øÛNxÔ†oÞÔ |ó\øF ù‰:å“�ð‰:øx îA”{fàÏl¸û®¥ÊÝ6ܵîüØJåÎ|ìŽzåc+áŽzøS ·ÛðÑ™Zå£6ÌÔÂGðÐGfàêS>¼>T2 ¼í°òAnÛwµrÛa¸íï¾´)û®†}ÝÞ´Áûmxß{Û•÷ÙðÞv¸Õ¼Õ·¼§F¹¥ ÞS7ãÂÍ1x7ZêÝmpSü± 7¾«A¹Ñ†w5À;m¸Á†ëmè>þ޽{•wذw/¼=×Eš•ëÚàZ¦mØSSKa’BÎkÌYÈÎÂ5³�±Á°!mCr5ì¶aWC�²+ º ‰½0�q4b6Dm·Aí‚�³ð‡Káj~߆«lر�*;fa;…m-+•m�°Õ†1ä<Ö‘f{ê•ð 5Á•›—+WÚ0Z#6 Õ+Ã6 Õà [pg‹ ›ƒõÊæå<¯V ÖæZ°¡3ÐgCoÅ:¥wzƒ tÛð{6¼íŠFåmMpÅåË”+áò·Ö*—w_o­…..³á-›”·ÌÂÆKë•�Mpé%5Ê¥õpI ¼ù|ØP �×(�6\\ë;j”õµÐQíë–(íõ°n ø:á¢7µ)ÅàMk•7µÁÚFXóÆ6e�ÞØoh«QÞ° Újàõ6\hCë2X�z®nƒ fá|TáüœW ç¢ϵaÕ,¼®VâÃJVÄà´Ô96´à¡–•ÐlC“ ËmhD„FP׆¨ß ËbPgCíÒ¥Ö†¥ˆ½´jl õ°Ä†jD«¶¡ª *càÅM/F@3à*ØP�ÏëÀSÄÏ!Oì¦÷{.ú]x‘W[€E_çý/Ìp endstream endobj 12 0 obj 6342 endobj 13 0 obj <> endobj 14 0 obj <> stream xœ]�ÍjÃ0„ïzŠ=¦‡ ;9Œ¡$|èqû²´vñJ¬åƒß¾kÕm¡ F3Ÿ4+}n. ù¤ß9Øôžãf¶žTyçmÚTÞíh¢Ò¶˔pl¨U¥ôM¼)ñ»g:|Rú�²§vŸçVt;ÇøÀ)A¡êörÏ‹‰¯fD�©}ãÄöiÙ òøX"Â!ëò»Š §h,²¡UU5T×k­�Ü?o#ºÞÞ K²”dq<sv;]©u¬Ÿ6`gfi’gÏÖÇ=áï÷ÄW*¯/�5m‚ endstream endobj 15 0 obj <> endobj 16 0 obj <> stream xœœ¸std_·5Ûì¸bÛêØvÒ1*IulÛ6ºÓ±muŒŽmÛ¶ñõï¹÷¹÷½ï}ÿúF�Qçì¹Öšg­¹ç®qFQ’*«1Š˜Ù™%íl�Y™XøŠ '5c[yFQ;k3À_� �’RÜÎÔÅhë¬æboo š©�ì\M�N|ó¿µÿwÙß u�³5ðñý h�@v¶|ÿ¦s;ÿÄ��ÿ櫹ØŒlÜV^>V>V ç¿íùâÆæfficGGЉ���RÌÎÞÃdaéÌø¯[�†ª-==Ã#¬¼¼¼�Gâ@'�…-€êüE]�ÖvöÿÌËû [[ƒLÖö–Nc33 Ù?šÆÖ@+€$Èdooç  £ýŸ,»feüûņ@ �ÚÿÎ÷¯ÂÄ–´s´þ“ÂÁÊöwBKgg{>fæ´4ÿ'ÄädÎd tfþËI)ak&fgóO7Nÿ‹ƒ�¦•ð`þ¿wËÊÖÎÍÖëÁæ [³m“™‹=³†-ÈÁ(#þŸÉ!„ÿÆ,€ÎN6^Ðt7µdþç‘êöÀYÿ��mÍ|¼ìíìæÆÖN@�9ðïÁËÉØpvtúxýŸ�ÿ¹B`e˜�L�&@ �-³ÿ…�æÿ±V0vv¹tY˜þj`ùçó_wú]`fgkíñßéŠÆ6@Àÿú¿Â¢¢vî/FVnv#;Ë__±ðrx¹y>ÿ“ê¿Dø·ÿB•�AÿÙ ËSÊØšÛýåù�Aþ*øŸÃ˜]ÿÃÜšÌM øøÛ¢�3Èø×*ÿeH=N–¿^ü{aýõÄÿË®ÿÿú—Ø?LÿmÍÿÕ¡¤‹µõ¿ä¤ù9õtÈþQô'Û€¬=þéÿ+S øòÿM£öÈ `–q6þ;Œˆ­…õc 'I�;ÐLäljù¦ûÏ€†­ÐÑd T¶sýó+`dåäü¿ƒê– S+[ “€‹÷_1 ­Ùÿì‚YÂÖÔÎ dkPsþëncG³ÿþ ›º8:þÕú_Ûý·ößksÐß�@w )‚³P0æ­©uÉ·ì�Wå†6j:í0ĽŸ´'zè,Ÿ{ÆÑØi¾ùßÑØ]0h<Õ®Ü|&k”UΦ܌Û�ë2Zqì¨~ܨ>‚r3äb&µ¤«nãØðhÖi÷–‡’‚Ç‹ðÑv÷›`ÑZ~EñÃø¡iüÈ•âXÎò–A'ßpí m$pæ^wZ&Ÿü¹DÅ» „ØéD×w¨_ú=qsã@‘G®uöÑv�bDOÞjßQ¨ùj¼Ù_œOöÀ/1e pVls›ÇÉüÕ 3_Dëlv›¥|5iÎöGŠ9ÑæïYY&y©lsÏ—»Ì1ÕŸ‹ÞíQ±üh«‘óÜvXŦxSÍ?]t‘h —Ðe¨ºñ›mWš˜ÜÝST :?„ö&q:cÌø?· ’¢ {l,b h<®Åhça)îa›æÃ˜|o�® /áž�ýb<}‡ æ�Ø-+2X8$3„®IzÝqû5!‰(²ËcMX¥ù ËHM;íÿDq³O«&ÄyiPô^ec¦»¡ G)óY`Žê|&pøšp&Q‰° FV!Âßœ’CØc4]b—7Üž‡$UñlåRi×ï_}ÝÎÝËú¾.i4•š|@b`gydïDr*‹ÓK¿ÌSuU÷NÐþ‚WŸ@ç¾Ê ps¾rÊƗB˜ä™/èñ 3& ¦ˆ’üYµ÷[*«Î÷ÌSöзR=kB& [øÅ‰ð>¸&êÔQä扉ĥS£xEDY=5Iw Ö>IܽBÒÂå„�0gh~ ÎE—ã€�rÚç±§œCÎÊc>£æ¥„ö-#!Ì_rŽzZ¼UES†Žñ0Ò¥êz=~q#§öâ˨­vL¢Ë/c8±eˆ:ÏJˆ}osœ|¼~¬æóˆR§nÎbQÔià£;‰ç¡•‹TÍT¯×°¡Ñép¬—cÐTˆ¤¡ÆXš,T€.ì›�Ö}b±õf»ìø~C.GÍCÌkü;;åûw‹j«ÉC³E¨pµ¾�M95m»En=çÈ~]L2€œlžSZ‰AéÜG7Dä®"5Æ`ø>ÇI†ºÏ ËŽÛ´­"<äpT¿ w�jœLT5Çe-áL<¼ì@èÜ‘ƒö:Å@áx4Á•¸Äùni—6>�® Ú<m [%ØípÊÖ<áL=à¡Uî êª‘úÀ_‚!clPÙ‹� Ô’@tÓø6ÓîE`k¥­ËÂ’}’¶I¯Ÿ±&�3§¤cú·JD4eŸÂ2ëuMأ㼅†Xºhø¼Hð·€íw† 6Ô·LHrèýþŒžrO†tèr¨ Md¿ÐÇ—|õ4þ!¦Of±hÌ‹æ^2tÈ3ÚŒ—ÂàqK�Qó+»aèìµO8!z�13¿edŒê å@Uߢý×¾/hƒ°ù¦rÙ3ƒBg¯ŸŒÔSÂNçÏ6GûLw“«½Uî“„HÎ%Gø-;ýLå°5ÈaA‹Úap¾J�yÕcÀoÆÈF–ZqØo âó½¾8ieæ·0h„>šb{ icâ�¾P{ó”, ž^‰¢0:!¦ú̶l€ëLXÈB¼ƒÿ€Î¶CM;ÂôóCùs1âËÇcë˜W¦LoÌÙ<Û8œ‡ôWfP‚“’Öê&Љ„`/øvº%›�¤¸#®ÑÉz#D /}ÍIXÓE-ïãžÚm«Lbµ.À`R–�rS`e<ß§¿±˜0ŠÂ-­NšµÖ˜|º£Gq<Þguž²_å¬çì%vŽ[±RÍ0=ncî¸-k}=ПcBÉý;ÿûcæ› •˜O i­¹/µô 0ûH#¼D¯þÔI °�ŽD¶Èé``ÝÂÿDKÑ,ŽV;=Ðë�Ç¿£[@|Œþc9æ‚Ùt´¹í£ýUI€åÒÆ•O¢:Ã%Mx•¾­«r£ ²‡¸—ï‹Î Ä�YÅD#ÃH k®‚ƒˆžxœŽ¾2�¨/±¦þõ,TwWô�ƒ~öÍ!ÈÆû€�g7¯Hu]iõ&£oégë…s¡’`„ë]tŒ!øRy³ ³ÕS†}hr‰q^‡ BæÑ÷Ó:üoK«‘ß: ¼œÌ¼>íMŽÚÜôß³væ\;NƒQ�ðBk�ât/Öâ �ó¯x'tÀðy5Å]«]ên/�5ƒï°AÙü«êk®šB^ºœsÅöú¾b k˜ÍÐ&ŸŠlHr®=O¾²Ù…‘ÙH@<çâSUR²Ò‹գ"œ# Žl»33, §F “4å�‡žã¦‰rVž, ÝZÚÑ«Ñ�øÉó÷ã>O!¼Sg‡šE\vJéå½Å).ÉîÐV1ä¹ïÕËþéÖäN£’JÀWÊv$Â~µþxˆñ±µK K?Ï)q¤gU¡ëò@ÊœêS;¡MSA1¿õeÇ›b e @¾–—_lQ³Ážý•,Üq±D$Ùš)¥p¯.‚�ÙÜr¥F–ÞmÈ*Ñ•6ÑY3Y*t�j –ˆˆa·F¶ÛKÌ¢óç\´u„é¨`fu£W§Wö¬©]ël3 ¯=G* �ÚÐPß7©*u»ã�_ ZHõàùõÚÑFµŽªÔ8'¼ {ÝS¸ cç¡Kàþä2[�-*û¾³¿æÑÂJòÚî“;¡ öK>»a¤è³÷ˆÒeì¤":ˆV%ÏǨÔBÀ¢Æ-kxÀÖv ²®.º¹RªÆ¥Yó7EÔ4»5Îêói«¼�ú¨¡ƒ”Þ›ÎÈò`9áÔíùìõ>qX ° Î7 k<¥ÑÒ™w­&5ÅïÙ²¥cIXnXŽÔ×W¥¶Î³ÆU0ê³úü8‹ <Ž'$úƒX2Þ�ô¨ z¨0ɋܚûeˆ¼œ¦ÞWk•[9¼©¥.Zö­öÐÓ†\¿&ŒðBžlI* d)± .RÀvÒ®ì �ûhQ¿ß‡À…K¤Iþ`Ø%&³š!ŒÿHxw²pŵ…rÉžg„‘ýM©tÁçG>—õ¾¹¹º}+Té†S¨ áè-ŠD�­/±VlGÅk7ÒûËÓ:A_½c�!t=êâEpÈ·ÆÐv"& ‡yÈH4d-­î‹ml“¾%¾'ÔòCwÀŽ@>í™kO¢B¸JHçôCKl^‡Ñ Ä�pçÀÞ ¡Zxp䬭^#)¤†íRvºb=–A-ÍùRÛߨ/þX¦I2ë{ríÀÞV²n[yâ<'Àä{Òb2l„Ã�›�ËCM�t)Z+·(2Q�‘-V@L}®Áxm`~7ý|¾ZÓYÒßѨ’ >‘YО¸øä�·Ò- ¼örx!Ž8S·¸­û›Y¤– „ãûã‹lŽ ö;Ô Ãñ$Á=c%Šä'Ó4{çPjΨÖ1‹]‚Š‚’†&lB-¢n’öô8Ö¨)ª±˜Œ…m76G¯7$êr =—ìI„?}'`ãÆfj ,sR¶Xî6ËÍn:™ ¶�{Îën[|šé"Â�ƒ+=ÐøÀu°¹�ÐD\¸uïgZ†=Œ9{Ûëxï*Î(/§5_•±}ŠÒÌb&~ªn©yr\¿t„É-L×(üótôÞ�'oM¼ê‰žÇ¬hœã¢ùeÑ0x‰,yI<ÎT˜àÚʶ/÷áÓ/X=¯V¾®dªáísÇÊ—ŸÑTŒn˜Øý|ÇÂÕÎ}ê³TâѶ°•D'-kÜÈÆÂwœ;LGÖ%ÙÐøp‹ÊAÛ"Ï{E÷é›W·g„mDäà�hHi {|¨¹’¡µ-Ì츺W¿CSš¥Aúâ”=XþzÇï’,VûÒ9bÝu0¸÷ÖQŸ›‚oñØR„qe*[Ò%ähË/ghâ:…Sn=b÷R­…Ø™ó÷îÓYáñ%GÙ6È Ðw*¬} MÇ0ZW\¢åìY§tõ· *ŒuÄÊmä=®E³>ýñ Wý°l?r8ÞÒÝEÖ#}Ò˨‡qO̫Ͷoq‡Ñå l ž"ÿþ:v½á¦º}ºúÝå'\eëp×{†äu%š;ÏU°Â0“»^ù ƒÇ7ü€‚ƒ1˜ß¬ã¤2Í>]m:ôQ\µ.L5—~£æÜGw¨ƒO#èÔ³’iR÷ã™ßdFÇ49TŠÖhÀì˜ãdØ�oÜ‘‘îš51{XB‘ž‰ÆõûFBPl骉‘)!5 ÐÇaîÒrŠ£MPu¨õÄÃøA§â—$°È¢ÓŸ”¦R³üs¿èÕГÛm%†­ã>ÛY#ÛÛŽ±aSNËx‰¿ÃYÐLÊyKmŸIã¾*sù0 s�î`Òöß“üsmÛqd–‰¹�&]±³½Ù¾™šë)ÊÚm Í¡ý˜ä§oŽŒóN 0¶¹ôjPqšB%POÿS¾yìNÏ…Á³«f/í[(£Ù ‡�!qà Kòu‰þdn³_ÞOˆ¸1¾Ö—êù~™F„^¨¡Ã@Œ‡KMóŠ�¦5f� óÈ"Ÿ`«Ï/38¬`·ùüó‘øCë$µs�ë„ÖTë³ •ÜY¬.K›·Æñ'Ø¡Æøgí!ýTùÇwiÇß �^Ý`™âJŠ)D% ä4<ñ[ƒ1žZÝ1@`ž9©§G¶¥#á²N€¡³¦�ÝìœH‹›“ váXWÇjù·?ú�øtÜMúúµªd• •ƒÙÒPÕþK p�eqZ¿ËÁ‚`áú÷,Ñðò®û„m¸b�È¡¡96Íи¥æ‡€äyvç�ð£ cCÎn�IÒ)­°aãrõ\Aظõ\¤žÚGqk=G,Þ[€þ¾À3(hÎÅhçû»ˆÝ¤º ròÚX×Ü¢ò­V²X ¬Î¬ø_ B-˜’(=âô䨒uf¢�_ú1«W‡·¿ÕI,ª–÷p~¸ð¶A3F…Œ@T¹ÏÃ-ÏDœi3�ý¶QÛ´RßIt„[»¢úÑrZF53W5ó50r8!âÌTºèGt|±› Ù?làd¿:Ü)”YáØùÔáï\X§Ÿ›y¿Îìa6ï¡b¸‚åO÷ÅJâæ'Q))õ—Ä7‘cÁÜŒ¢/-ýÔ½#›Î»ŽÊÌjºZ¶^ŽPi)\šm®O5&[?ÁÍÐ4ÚÛ,•Nø�²äWòtÛ°pÔçŒëpËCŸ¿ÕÜùǯ&Câøë}o\|�v¬’(,ÏHVUx´¬ÌeƒXŒŽj,é�˜nâ ;ñD“,jÊ÷Â>Æx ZGeôK�òÍ_•% ”À|I§ëÊ«~Oþ-X]þ–x€@’%Ugz&SÕ3ÀB´Î�wøâ¢Ã›SZ[Ø`»¾�ÕòûúgEÄ?vÚÁ r–üÛ’¸‰Èp=7ð ¼3ba@·h4íóæèÇŽ{Å×¢�Ã�ÇðùZTüÎ{ÂWpìÝö‘¬y A£ç™]a¤àK>†q ŠŠÅ|°^á’Q.ŒfÍω®HÙçn²ûØba¦‡âßÜsÖœ ˜b‚ö¦ì¬­ÊøGTð{ùµIZ’á�¶Û1°F F çTg”ß.�ú£óåáH²i‡’N©Hg¼Wéó¤óÍçOñ]øêGsÂg]fÅ´ÂÖ=qcž¯Çö&0åÍ�Š¿Ô¿lj5dK²ÓÐZQ' 3ˆ9ºBÄßEâ¿ëž4x¿ô�“²™x¹I"S˜ AKåt߇ÂhÕ‡`úæÙ�8 6²µ¯«‡[Aœb’5¾�[\jþû^Ãú¶¦Ÿ¯÷ª6õ dÓú1KS…:Ê-¤&{¶îâd¥Y•œLuLÇ­/¯6É©V%ˆ*´Jý–“÷³È¤ò{Ü…9ÿȰQ_£›?rJ•Ôw:*} ýU/ι>¨UXþ–¬97\yûNBÃàÉ%·Ø¹lŠv!Öo�”ð¨/þΊøÐ9=‡),“tFûƒ|HWé¯ÜVwró¦ÅkžÍ$¡dÅ…Ó‰ñ ãÏùÓ ÍãÙ2…åá&éA÷sªIDÁ­ {\&u�•”#ŽqÔ TÏ˱{É{§ß§Ýeå×ë‡ !¿úL¾ÎûŠ¡Òê�#¼^[„C¼ïkÄýYr‘,G�¸®¦U µYP™?}ßruÁ12â+¿ænG ïâe00ü²œ['=ou [£7ë|Í2:¯N¼³ žúÉ(eÁSñ9CZ�rÓ6atá±g†@ƲkNÁ¯'lŒ$@Ø�(Ç±ÛÆ±CCp󨀝ÍsøsΓMƒàrŽÓ~Wi7 w_ïÅNŸ´³©ÎõþJíÎÞ×@sqáG~âî=ÄíΤÖÂFÛ� 'ÎFf�:ú„? L30‰Q{¦X.ñ:ú©E u¸Wb•+˜–¤¯å/ˆ'ŠåB9PˆË¤ùo!“˯‹­cú6ç*LGCší³Pº³³(JJŽôá&ý)0üÊš=9P-ÜBJK2úíRérh…·ûµq¾ÓÚÝ—pŒ— Rø¤Y ôªæº]4k@¿d +þ½néþº»e¾Ê ¼k›÷tú±·K|»Ÿ,ŠMmöÄ@D¾t¬ÒPR‘#ŒÒ_Ã0�~öaʸ PxÊ1«¢Οc’‰äÀìÃØ•º%‡1=úò+‰²ù,ìGÉàã#^̹MüFzsÞw­*î�\oQ‘LÁ·ç²›ëíÒ11ð;óÐî&ª}œ °rxÙ"œÁ§Ý(@Éý®¥ʳèe‚DÝ â=7�䘠»‘ºþtÎv_Rz4¥fò­±Ö,Xa­->Çxçiµxè>û56º†¿ˆóø�ÁAΗ%ìÖôë«tm�ää»$�ºUÖ�Ÿ‡Ÿaˆ´üö®cüÙŽm·"kãJT3…Õ· ²íkÐ?\.šÍËÑk"©“Rd™¸Ì©vï’¦†Ž¡Šê³ì¹â"�àŸË–(¾‘v4ØÕ›Ûÿ9ñÁ;+Lvõ6Ñû • LOâåü¿©e(ܱŠ�‹D¹z¸š>“BŒ'Væ£j»°ø-ÝO(o– ÍwÜš ÁäœFÈ¿‡á“:&¿É%úâÜö’ÎÌŽRC´ñ¹ýx§i{'€,¬¥šQÚöBþ Ͱ7ûz§j×yá×AÕƒ_ïoHñã~¥CåÒ庞ØìöOäHÇÚ¬~eù»ÀU¹µÚÏR‰ÒÿÄx…�C¯àæ�j„ï|´²¶–~;ÝÓ�r05íJŸXâið¢˜I’CY»™@}CÖÑ{ep‹øZ+K­ŸÏ}ûz`]0¶#½¤FøMy�³«E«~šzæ,¶x„¤3ó­œO‚Œ¡6Òí9ðó}â`»>×#¦­ì_íÞ£mB¸í™51߯"]ë?…ÇjdŒ*j Rj’‹—áù­Œ'á½Ýó“Ñ  Îoiaà{‡·°«õ]ž–§@ÇaÕüCQoµ›´W™Põ¡1ûš²ìIm1KìtúÔ¾ùÄ æ[Rzu(R,:8ý¡i.H˜ødHĵðE=s{ObÔ> ™nPw澂ֽvØ‚‡1¾/èk©7ç‘¢Üg%2 ‰XZ¸ÑN1rÎÎ%¯Š‹¦¦ "B�°,•b·)¿9G�yå¤ÈOG ëªö'Ê�QÿBš“¼c†ƒïQ“_8mGö'�Õ oõ8Ž ÕvÔF1í:åK4…z×À–U€ÚÈMqB®;¤y )íÈǽ€µ°Ïf-¨“þ4BQb¹;”Ë­§)´íÝh¬næ›s©xÇ+4<~š7UC³ºû*Ïõ:U‡wx™•ÂŒc�Ôÿ+H?»©]Šózñœž¾|£Õ¿…öÀbÖÞ_¡�ëç9]šh‚Тp‰ã\Æ�@×áì!gßþ÷ØF™ ûêxf›©I–}ñ�W°#æ ÃÞ$¯š›KüÍNuÌ¡3¤/Ä2J‰Iҹ̚gz V»|>Ÿh¼ºm[u¨[¬ IE%ê?7NÇ1. ¡Za˜ïe;ËAbTJBXÎmŠ ï^??g«Cî `-Ë:)àêšÈÊ^xÚó³Dtg™zÚdVëµ ò(P ‡H$‡.lßì´ "%¯ŸNÈý¬•¾ð"î=uy#ÊÜ®– îi–‰öPÙšýJ?Âܪ…ð$UPÚöè;\|$›é�îýG|_3§Fý4™+ízr¶ÜÌ'j·ÈY»u»$�ärºG=?2U‹žüäŽïh¿‹ÖäóF_À~.x 0ÇóA5Iìý1P͘Eºc:ïãÇž}»TßLé0i_ý˜n5õùUýڤ܆ãÇ<ëpz‰}ÏDÖ!� Pœñ®�ø'_ÍõÏcâ&&“½Ýî­²`Õ¥�•¹%.«¶§ÅöSåæýzÛ­U˜ó¬ë4 Àúžš„UN¨Ñ@Þ,šr˜·+HŽ?1 dôMi¼ŒAV0Zc™;ƒ2ëT�ê£CîöõoèC·èkêsù{žjd ],Íæ’îÝöŸlN‚[VñÞC¡irÒ IÍ¢h§ï)½Rx™r3�*âãT$‘�³‚­°ÙòÉ�J±aª;^M`7UŠ"î,OÓæ¨î\Rc;Hñ­éÕ+�û¡Ÿ³? £Ô¸IÄü:Gž˜ägicÐIí¿ÕéÖÌà ­IpÄãlžù³/WjEŠë •7T§•Pé9x|œa(ì úªqR·vâ0„îGŽŸ¯‘·G¯vçT�ñ™Þ q»ÞÌSÑeM‡rñ7u²·¿qó·Ýî÷4Æê"°JÀÙÄ`ìkŸžƒÌ÷ Ûœ²R~vgC›Ê/ :öáOà°¿Þ&üˆ°t&^+D§@ÊšË4w1­»éÍÆ9�a1³•_ij|ö*ÆÄ އÀ²»6ö(§î‘H+Û²ýÊ[SS€ATÝk:ryPg†¯ u €{:í—0ª� Uµã!+ì ªÈHA »ˆG®Œ&Wy*¥Üæ°PzH�þFn.ê÷n¦Çvøú(×:Ñ~ÿ40�“ÃNcØÈàX��¡´È›P?ΕãEgTÈŸkƒîoú ·¶ÝB?´·z¿s;ö»oÉø­Ê;È7¹¬3/™áCWq^Æ_~&ñ°çÁYŽ1�‚7k$úÈɇ.­�X¦h®…LÞþäÂd)>k.>ïO‘ý/2Œà‰U³óì=NÓ gøŠZÐäö%}?ÙÚ^´Æ± –��Û<¼7›~’DZlC×'SJÁKѯ™Åz� êp^<°�m4É¡ÔCÄ3qµ]/è¦%C`–çb`þa•÷„¾k»Q”å-6XØ‚°|Q�uÛ4ß)ÞúM QH]1:Ç@/Èl6©á,Ôà„¨Ÿvéþ Ž¸ÇIäú‹Ÿ%þ¬r²{ÿ%X¨)-*ÚpÄåB7ë5•ñ ç:Bló ìy÷âOícŒÂ]-™Úáhùk÷v_âB�üüËK|Š‹œm8“¶9�Ó¾—<ƒ‰“llqW`œj‚D$¼]�y1Ð`ŽÁYAÂË÷]]¡u ±iókµÛFÒŒ11^š=%¾[ÂMì®ÑÉ �ï#8ã(ævgÎo0�ãé>ñÅj˜uˆzj8»Œ‡›Ãº›ôfèÒçÅa Çê¬áBR ®í:8>—õñÛŒ:öHÓãÊý¬¥©‘7‰j„Àëù¯wè]¨ !p$û)´²ÅlkÝæŠ…å§LÆ’2u†²š’U½vÍ^^Ó*gTÈMKÑŽ‰z ¸b*z!ª&f ¢‡Ÿ½G|+®J?`ÓW.Vš(%¿a#^¼C6œœÈѳ ç1ù�¶q÷®‚!5\¥Žm¾L_f’ÍVBW `¹/¾ÎPã6ÀÖ\ SÞ@g-ï�¥÷Âpn©è´d;#"¨„ÁòzŒÒ!¨hqÒlCšR›Gã”)Àà°ö?Û¶­M%ε‘Ûðakó•×Ó�îTw ü /�V}D—7d°k�}0TÚîN÷ô‚å²c……ÑŽ³be�î^èpCÁî¤/Ü,i)œœFÅ÷¤C¶«Q×Íh¯ŸÙWÝ:.?M©Ñìà²Ü‚/B�1lŽl9«[Y¯ðK¤`Åßï]|¼È²MH�(¬e™‰ ªµç7R�t%—;®š�a–c€y½€9ºüÅÀë&|#‰d¾6‹pKé®b0+„é: @ðAPGÌ$°b,Q¥7u=ïç±2Š ©žÔl?²Å$æ’aµË>š^\ô²Vé�z*çL+KD¡Ì¶x,†Hq�Òñ.¾ïô;ޒѲ+ÞEgg�¨\þýb|,­ùåpˆ“Ô /SìÜ�déN0<+V ‘<øPÄ{çü¡¦ïÇeÄzzb“qâ�Oh!– !¢¨ÄKƉ¤ñ^÷~FÎÄ?ÿðVÜ™•Kq•7b,†”,Qéß›Â`Ú×’Z#Õbø§öÌ-áî¦ö÷}SñfO¡ŠMœÈ ²–ÊGEžºîÔHª™mjåSÐKð+ÀÓÿf 6§Gd®Pn¤– DÊ�8Á/¯:¦Ì˜Ü}s€•2éR ´hÍÃÆý(”t ¹•@ßz} ³Ëbã2‚6µEãˆ�ð¬<–¶ ÜÊMå–jìCô Ü©wCîG*4Ç0`:½¨’Üç* b(®âêÏ{D|Þ·GñùŒ½)KlhT+¯êm¨ÉHt⾟ÞyÍjBûýqàÀŠIÌ»Ï7¡ëpÄõQëàâöcß¼››ª¹¿¸ …;¼C�f±ANnLòQùdÉÕŠp/:�ܶƒõâ¡ÕX‚k³bÔ·ïØB¨<%.¡’âó £Øß#ü6ú9–~BÓQÊÜ�Ùtç2j:d>·•|Ë¡ ÁÒ?�— L¨?üåMN©Àšlžl°Q—µËI“K4òÊÜUhñjþ%©¶0±�wjØÕÕ<8Òjcå› ¢sÀVoHMgÊ,À‡%îžæ¬L¾®Ôâ‡ïUÓ ª²E�õ-]ö#…ÌÙ¯˜qd£êø¡ëxÞM´CZL­=Â9éc.¾x²õò’—uNHp˜¯dÏzg‰B´É™@cöRê1J÷j6cX”/OïÐ|z£>jƒ,n%—@skêþèkÒôÏü÷æôÏøÆèðxgh‘RC-Rat‰Ê—þLÝaåE{èkó»Ì!=¦¼â/|È®¶8^2°Y´ oQ\™›ß2š¢&T‡¿½¹NçRB]•©š úÚížAŠŒá0Ʋñ¿µ*^d£ŒÀ�³„gëz�—f# ‚”€åýäïzO ÔN½ˆÒ@ä 0IßPÆÙ0¯_’[YL–±t+ò(èg$ | ÿEífȨÑt(·×*GF“"Ÿ'«Rþ¡°¿ˆJ²\²;£¥K¼‹#ÉwBY8µæã…”Ûá–Ѽãx¸‘W8¼B�qÒÑ5X¾Sõ²¦�Q9@S�DÓ©A¾˜ˆïG5†(°w‚RK%`VÛË“Ôç~°�ë/*” 4°ÒµˆO—ò‚kÕ¸èÓÞ\Ò=`¼PÉYwé\é:ú¢-PÁäEáÏÅçß7nr[Kõ&#t"Œå©u²èП`—e«þË~”6="FÏ ê HXžEÌœ9+öÙQþê7q&iq‘çaÉ@kˆÁüv"»èÓà8V‹¶í—qž)ªñ‹VƒÜD§”rOµNbq¹7{¡e郪OV/Uf”ãž/vߣç�±¢çÛ°@ù9m΢'È,<êÿ)°–¢ñ­Ö4ƒ±SÙÏ÷Ç΄TÁ¢Bz�aLy ×”�º+Yýç! §:»±Ÿ� Åü”ö|pý\9ß�Ä|ò­Gõ6Ç6”÷T…Ô…Y2Ú1;=\„ÁøM'ý�ÌU–e8ù¯á; Û<[{\Â�ëTó¼ÓE[©„$Î 5|ëõOG ¤®ñ�4�µœÆÍcÅ‹_ Éÿ¢ù«Ïž e+í^~¯bx6©±»$PE ×áÌoG*gá~Lê�ÑÁq=McШ˜Gç~Q}‰A#õÒþÏ[ŒõÌ-›Ù·)úõo^±8óºÐ¼Æý°�MHBbíyÞ]TLV1(}û§Y]Zéž«ßÍPR)ÛëG­³/¿÷7LX¯—ÚTë01´é  «!OËYù|\a ÌMû�£Å‰˜é¸›Õ2}¶/²Î+ÜE¦äŽ–/k}ûÒãhDcÛ@/®×Õu±£èѽFâ“À7Ö›§ uåJÜ¢HrAqÆ‹j-k ƒüü#øæ7BáÓEÙ¨-Q �Bäº3??GÝaõ×ó�¥äˆzˆælKˆ™Ãô÷÷–ŸÑsEUÙ]�‰r–@P3ál9Y�cMTh‰Ó¶ nш(z«ÃÐ�ÊJRo§Ñä,>µâæF8pÖÿóÏr×ñô|Â\æ± v¡GµÅ¥†T£+? är9X ¦‡ä»¡Ð‰läË/ :žå ¾ÚKº ";›n?&hqzU«d@´àb|ýÓaõ¥ønRúÞ �ËkD’4f * <‰NÔ*2º»>žéö‚Å7~cWÇèç�ÛÔ ›ä#¾Þ�Å�€¡OÑÊì_ä5·bQ«Xñ®ŸÁ» öàñ:å®Þ3Ù啽BÓÅ™5·—@�lm¤m\žºž“?“.*N¥¿¸ ?T[//Øú„‰ËÖQˆ–ÜsJ‹hž¸ˆ—¦`äÖ|;©ìÔÏ_šXÄDŒ“×e;ߪÙfkaÚÎ3±´â¥úr«ÓU؟ƵfS5“»W9¯æ‹úÀcõâX8DhçXH6|‚v¤?c'XòG¤z�®è2Ö«– -3mö93]NJ°xŒÄ”5îß»Fºe’iìs8àÀs•£PÖ¿éJe<0Ñ×P±2ª »@ÌÖ²{_óv–YK>•Íkì$¾œ•".�ï�¨6Î×6Q@ ‚OQéCþ$¾T�uC. Ù€½\ØCŽ/%Eœ± ƒ”«qŒ3Á„¾¢ö[“ºíAÝPܧj! Hõ³Û7èønŽËÆuŠ�ø†'Š4ŒØ M8|õvÉöRk6ÝX½s½U1ç+'ÃF˨Tˆè—ÑøþÛ'_Ê u4ü º•Ç< �ZG'ôIJ‡¸Jèø³¥óòEAðØ/R>A˜pÅ"]µ{Ýé¾³íB¨›�Ë¿c` F#×�Þò³’ 0Ä¥y%cÏ÷‹ xcÛãÄ e™ƒDck¬o)Ä]ðâ¥ëzž ¤ùĵ":CØi0,®��Ù‘9DuÝ® D÷Ãc2›ñ°Bõ‚,¦cQ/ÂOݨîl7¯YÝ8ô^Èï€ø_xÊ�Ú°ìn&¸“°8º /é´¸FìLzžæQ 9“¾á-¨Ñß¿h¢x!Â/‰ó~“ÄJƒlÇ$›¾ùã�Ÿàuwl‘ ®E®î(¦ç®�PÛÃ'{D¥i�ês¯9é*Ÿ}ûäðq›É)´ÆÒ®OMñ=.Y…ØNqªÀºeCå\#½³{_Â';Z.†fiz©oÉ„NÜ TŸú”¸÷%´ �¸V­„Æu¹¶5Ƚ|»²Ûz(&…0»J°ZÿJÀÚÀª}mp·Déœ}&ö«Oäœ:ƒ¾¿gvœ´,j?Û¥´’ÝÏ<È6sÂtì†Ëx!ˆ¿Ú wâ§.nŸ<¬Åjy0·H4cY”³ÐŸ}¸X2—ºÞ„î/ާ] ½›4ü9Ø‚°•pÃr©Ë þÛ›=‹¶L¿Ø†ù>?ê)3˜N•v�R+ kL€*¹/ªj ¢ÀcÖ¡miÈ‚ì�}(qúëz*uà ]»ÄFÏ�Vs©NÞ;åg)Ndª˜ú뼯wœ~JkImMÜoo�Ûw¸ÜY.x÷%Âû}U¶÷&èo°±wC­ˆ°]–i>µ{20l¹�­Ý"�ˆHÓÿþ«Ñ/éMÒ,ûŸWJ˜2É­¥Ä/¾�oQKtzcˆNï«w]¸Ö¸Nj0l|¦2€×€Sœ�jñ€zÇ ¼C ¨[¼ávÔ+,dúRÏrê;Œ³ŒU—.>¹tÞÓjZ%é¯Úµ”ž<Þµ^,zv9üÏœ¢U Ys¼5/öתƒ„»|¾\¢û€áoÜo%è'‹íß>­«4G3~,�«¡ÏjZ¦¨5t|mFèxä1í--ý�Œ$®éµ½‚O´ppÓÕ=ý5Às/”SbO F©©¥³�êvÚ._ûðY·LÜkÕ—Ÿ:þ¢gÿ-“�$©çklz_Ž=yr,ò«Òî 8Û¸¸ãvÙ”+¶ŠB1û"‘o/éÞáëˆ#sDÍä^åA�¨ó7¦Þò‹•¥Îv#üPÚT¡ñÇBK%º³…{%7¸„¯Â�'0,zJµ}!'»ôGÒ1_s°¹!¶dÖ¯Ó¨ÕT´hZ ÏåÖ¦v¼M`=Ó8åIV�¦é:Ä“elÀ˜J9q^ˆÚØË JµÔZ�ú€¢ALUÌvÿfÖ-õ'mÌJÂôhÕâ‹ß|•óå ¾ëôÁŸZ—2\¨Iv}ÚÈð实ï¼x 5¯ÈûSÈ麚 zíœoÎÂcy…h;˜e�Ö³`<˜ì°Â¬(¡ùÑF`ž’vŽ?ÉtîNžSMýsôWö¢lÒ_ZlÌ~Ȳ2¸â‘QÐÖ¨˜ ÒVÜ2+?>ªnÚ³43®h_ ë ÖÊ€ŽwŠn‡Õ¶à�˜m¿ºÎ0‰µn–ÓfÑ{H%!L'�hâ¿^Êâý֚҅7‹ZE}TØ1�YûÄ r½& Ÿ¸j¤ËuƒU,ÐO:‰^0§Ów6D>`€ 3P.–µPÔ�êÕ¯Ó^ÄlŸ›žü†GÓ]áþä%ˆìv•Î Œø–¾ –œ†©Ã: aîøè]¸�=óÞ·¯Òá�N}ã ç••G]Øë´±•èfõ_Ñ1…K¢R$ÿùL2ŸN�çóhéä®xM _Y~b â�¥•ÜúlŸô­ÃÜŽSøi ¤ÉÞþãîÓI=å¨À¤Ã;†¸ù«öï!¸r`œ™û(ãÄÆ–W-\8»ûÇûmê×UlíÊ»xÜTY"ýü–Ä"à‘ÇÈ¥¢^ï�F##¼ _�X–ÔìE¶¤:‘äçt�…w$3oP‹+óªw™ªµzIõ‡øŽ¹{­¡Qƒ,µá^~²Pæ9Ï4ò« wéÆMy„Éøéh¡q~ë2­ ÙŠáæœq† ùÁ‹$«ŠÎzTwsoÕÒ@†üûç >ÊH囟eÙ2N ¨I§#…ú°è ³ÿ¼[ÈúöÆí ‰‘§°w33)ïõù€»KÁÂ1¿Ìl¡_3úÇgÒOƒ�I¨éµ€.1ÕÒãôŽFdzÜ÷£ý� Jãæƒ|ò÷^`*º”3µ<ùr©RØ¢4<ší»ÏçUå˜2+Ó�èò*M• {·š�–ÁÆÓ¶Í~j¼|_lÕw$²h¬ W—«ÓSŽd!Ri†úAÉH\¹w€U¿ßz¦Í.·^™muX èra¾…‡F_fœeì_®#QFg<ùD[æQìR }�' O†Öº75Ã0&ߤ ^\·ÎêÎÙ7<;Åâ92{ðð]€%Ș3ÁÀo©&iöå÷o h!—è¼ÐóK¢||l×dÀµ*K£xÚü7éÙ\i¤}7qê¯cu^úèhÕ9�Hâ$wµ›êB^ú™Õ] “ˆm()ȼÅnŸÜ•f?xwVY–C¯| E8žÝ"‰UvÆ_ «wUi^¨“›CÔÊÖÁ,ÁT'–!£/§›]I¦�ƒ®ˆX©ð¹z8´/ŒÔ!‰Åƒp‹:F°"ˆd/$mäühß̈5Q³€¶_qmO¢ï»Æ¤Í�mD"É)gÃXiÏ™ƒA¦Å.9?홚ÌV\á ¦�/)IJt¿c�²C*{G)ëÐRò=óæÅ&ÇóŒ…ý”G¶ï>B÷51e¢ÕçËÍNE]fVr¡:à-Þ÷ÝG¡ÆjKÈÜ=l›é»œ6ñ |$ã[õ2tšXB늵H!~ƒœùöbêôhžò�—ðGP?Æo¢‘ûPVb¥”º/5DIÉô ü2ˆË¸qÅ^DçGSß5vÏÈFuž%dBMêÏð-Ø:PR¶¿;‹ši´Mj¼(Áx‹i—²wKå|M êÎVŸÆ5éíüùfJŽ®-ôD?D¼i}@ºÍ�µüT•ãÏ'},<ÔÇ[} ­šW˜ð:g“·ê#_.ú©ûµSUÚµ ÷î=« oz*„÷jì�«,åhëÅ«ì^Ó”-×õ˜¿Ê/ õXôü¤dp)@ð`åu#_upKØË€Ð^fjl· ù‹ÍÄÇ£è�ÁFÌŸ5�#êÁwŸCIõ‰-3ŠŽ:ÓfZŠc‰êt¦‡m>Ó7qïzbZêÞk”·‡÷ykÞ¡ëg¦c¢�A>îæè×_Å6ø Ü ¨È±†‡ì™N“³•#/DüG‰ /òI‚õvyaDíÁÝhtϧƒl½Ïˆ�ícS…�ä8å� ÅÍ|Æw•׿È/T.Óu3r¿>nÒʧ#òZ�Ú¿°]1n…hìÏwˆÏ„ ¸®ïäMΨZTM¤hs—>ïÈà¯ïoÙHZd·RI¯¾ÁûÜmü¨‰.eTÀ×ÀÛ¬ÃÃF0Ö¯˜W¥s˜/ŽÝ’(³&Cæ�.|—«³2Íô$_Ûk_– æÿñ^ÿ1õ5{{iRæÂºC•‚¦±Å½ÚÎ)—¼¹ØÇ {¬‰šsvôýÉ�r-0 ˆùÇë›YF Å•7”gü9ÒŠÁp¦û¯5ña#%¼rç²s`þì”ýâ‹­H‰6a~r1¿¨C·�]Ž}H±0@ò8ëìÎ÷ûÁÆæç[Ô]Š®çU¬>eøûöŠÝ3ÙYœ¾Uˆuj¼Ü¬vne°óT§‚Ê€9#Áfë¨p;Zhã;*¦«Ðš¤7—©5|Š™ê¡Îtä˵’}è"5/|Åœ¯‹`ÉT™ÈAçžÎš˜±\¥TܤæDÜy4WJøÝù;_²é.ãQ7þZ×�bù‹áwðuiîÕŽ ¯Ÿ�ЋDI½¾ø¤U´5”ªé äÙ™ož©ÊQ­ÉÏéÕp�+|ù Ët³°ˆ)šC&ÞWß?VX4íÃ%ñ MÑde®Ñ•H, ãÍÞrÊýúPÆ?[¡žšå)é"­öÙð˹½ê‰î ;4ù)¬Z ĸªâ>“Fú΢i²gp¢ûXÈ' ¾+=ŸK� NÍ�(;yâÖÚýÂÅ-¦ØWe ãê}æO鹪�KL(•§ª²ЄŒ¯k:Œì²#j/UsNôz“Ê߸¦H^Ò¨iE퇞ÀªvcŠKõ!MŽ'ñËúíëŠ.*vƒµÅrk“<–YR‰rx Áúnª1ÇDãäòœ½Úæ$Á}d§0n^.Î(­5Üÿ@[{cQ–¤ëé¡^û1s#(+J8Šú.�~d€zÆf4üV s—­}Èç×=ƒ×FpT9iX‘dÍÞx=òB£â‚»Dß§0ïkº5‚í`.ûqºþ \ìÞ¿,î‚Ù-OÎóó(z^~d½ó•«'1ág¦ßeùGùþ|òñD•±ÊÃÛMÏ4µúÍcSѤ¼R6b¶ÉÎÛ�æÁ’úú¬Q/•¢\ °‹@ÂTÐÿ '¦˜Øÿ�Ö9\èißL&²åÃæWiW­LSõPÙVÆV:<è çlÈD´óÒIôÜÿ' >à†’ãÀºì0?ZØÛû¹�1éÄÏIÁ!(%¯¨Ý¡ù„“ÝZuÐ*5ò<émÓÇöŠI¹ëdL½K[Ÿ @5OYq ­­¬�ó0`(w¿›/CHû™ý¬©ZJã˜Jì�Øiãó8xÕ<´—=1=½<8‰0Õ’MÊ1³�Ðb�Њ”GÅR\` ˜$oËÍ(+>ö„çÿŒ¡7Ù$™œ�¬&ÚÖ ½{é"�b¶6ÄÉeƒIzDtÆØM(kI–Оø“�]CŠL¸M–¸«oì�ËÙŸ^£Á=]ÚV,—!Q]E�ޝ =øñC⮈{ÙâõìªísG$&¹íäήþʤ¦î¹7UÖÀ,v�RpÆoÉ—ã¾2Üyå<2¾ ½zM½ß]i)$îNÕ¤î�6ZÈm4¼mË¢|ÊJal2‹ “€ŽÙeÁÓc=·Ñ įëâcƒ©°³P5éj(̵‹äZ©zm•_/u¨—,¿yÌE¥Ü8ù¶âÊ翈eM“¢Æ<é íÕ±Ït\tÕ×GÅ™ç" BÄ…@ËsJ.ªÍ ²e G¡+ ®­@ø]Û¹|+9 /¿§Î+ˆ5ÒTWqŒ·ŸS¤œ¿Â2Ç�9xœ›>`(A…_ªÍ©VÅþ}…´*ð{øRýíbŠ Ãø;’¦o]Õ¼úŠ›H²~k¢nö—¬É>Ç�èa层·Wß¡ôR¬™€r`\›´�V!çŸGæŸØ•­Ï1çïlÃ�³8ñR  ¡Ýð&“‰Ô& lžm£©—{½E±ÎÐÀ\ÐÓaCB�È‹÷ëV:T«¶ævOÜŸšU6@üq~¼¾ÝÔvߦOÎv•ÃÀŸƒ±vc÷>'¹¥³ñy£Š&žÐ¦JÂ袴Ũu]LH¨¯°Ž#c%%Ù+ˉ4ó•‚Û¾cßÁWü„›‹ƒ¥Rãæß-½+PÈ/þÜï�áÊßî¿MUQ­˜ðÅåÚ]3�ÊØ<’‚”yêÿN=ú]ü™nðç]ìèœÈ—5ñýÿ @ó¿ì-„¿}ä¸Ò |®ÍÐ~©–òªÁ»-ùÓ_ªÌSž£¹ÕИeÅÒëýSRˆ €!¡}âu–ß"Œè+2öÐí×�þsª¡ÀH‰×”³ƒGf\EŒq ÓŸ ·îËËC&Þ¤Ú$•ñ»˜ÒA8ÃŽe6µòJýŽ“äúý&·'¾-#Q(Í99<'x!¿à‡Eš+1©K%’ø,qÚ ëNË0?ÝDsJÆ•Ÿéëß1b ó´v%ŸÊ“\Í�¤Îìÿ«³�s«2ÜDéÌÒ´øF1¯5×›>¬¡í²Ç‘tLëG 3ªªÒÂ�Ž‘¡ØbÒÑO‚Ûü’²âÏ Jª�ßÓßýMÓö+T|º{z‡Ø1e§œ5,·ì'F#”cQQ@“%'„~ž¼3¼ðž†¨ƒ{ ÛQ­ø×ŸHíPƒQ`‘Ñ#Öã{jbÊä´*²*Eó„d{ \d;œÒU+/|sõèÅÓ匵–í>ã]t)ˆyÖ�$ÖÍ|E”ÄÏ�MþÅÛÅŠŸšŠÑ ÙH9ÏÁ=DO*÷Î^(øL÷W9úûh%¶ÐLåQxZ™”Þ©(ª®l£ô¢ŸŒ÷Úa˜žlãgÃs0Èu•oøe¿îc�60––�ˇAàÛÖö1.•›)QV»ré'‰Ö+q»YîGþ’7`º •º´yw¯L}zµ¼‚ÕðœPÀNMoÓš¢ /ƒü-˜õíÖrSÖ«�uÛ¦·ÙSíµAgòúþ~_]8ýà£n·àaãÛ%ŸIv4ÔjT..i†sE¸ˆ%m·ŸÕ–nˆr>Š*`ø�r¾4Ñß/þŠýÃL ‹<:eE¾Û}$…RAÑ^a�ð‹n¤?æjŸVG¨ÉKÅßÅÿ é‡Ä4ÖŒ ‚ªM™LYä-g¨¾ƒ#Ûûôè:ýÁP{°Çº ‹÷RU+¸®z7‡?ê=¾à¥ŸÕ#—ßÅ,ÖÑç�¡~?ÖY¤Q¦º)hïèúƦ«ç«3ÌÁíAƒ9HôD´ËVÑ6��‰#êûIg¡6Ì�‚ÛŠÅ|ýC:ÆÊõÒ8±rvAQry+j’“�V™wmm:P¡éXC õåSÃ.^s€‹ðWpD‹ ’/Ó�ѰúÚ½Fƒ-:u¨%£lÕw ²Àj†CˆÙ¤°§K;Ô;{o˜ie$ƒüÂ[¶¤ä»DÐ6-õR^ar[(ÞqƒX (A%Ô„=y¯ª|Í=]³#F&Š¢ƒè�á÷”]…€Þ,ŸW»\´Xÿdsw�R0VfX]f�ƒÕÐ4(îy�7:BìTíg¾íåÓ_±×àj tp‚9«}°Ó ¦Òª58üæ�¥˜Üõ¹!î)þˆ§bÕZÎd¥JÞ^ïæœÄe ámøÜ¡ÖÈ¡¥%ãB“Ësiñãã$œi1Æ©rôÀvtL)ŒŒô§%l  ºuÿàƒ×ŠOõd|ÃXYP�W!CÐ 6Z°JA¢"ƒ�Géê—Çñ^ůRU™ÿR³Éò¢mn�î-Hícd¥Ù‘«�E»�$4"…(uû´é~ýÚÀµŸ/ãëIû-Sò íaš ñÞ º )òzË#øäO`¥Xƒð°Ó·ðÛå£Jư•ˆ¾ í»Õ‚eGð�Yš×£�~rÔ´¨îÌD¾òèñ]§ùP)Vv5ºt¥.Ú_§Ö‡µ\níѺÊÂþ��T®2M‰¦¦„Õ9Të­ñßî[áGøMà€4ÄYZ« qq†U�E�A—å5eîzB­Z�„˜ ÔÀ…¿ƒ‡ZûYXcgðwðh1o±ÔWüÄw]˜ÃA8BC¢ƒ¢2裟°o»ˆpŘ¯…Û,ðÔ�‡åÆ ³Y†GóS÷®}äôŠý1ö/Ý�¿A7­àËÕ¸H¢)�ÜôHƯdqºÅø]©ö›Ä‘ß7~õÅ òaÀÈ4Ñ82$gç´ \y�£ÏEÙcíyal[b‚9£®ìt¼” >O½úüq¸ÿ>1¼ÖY¾—á²3¶ôzªv)]56ê» ¼™›Þ,å…q(šòíb#†çÆ*€½`^=µ]õmäžãëÑ©à|z žŒCÝMúõì5 BÁ’$° ׼ݲ‚4¼°ž‡[‘ïÞØ2…E¦fcÊâÅùw´t—+,4at1rÁÝß4¢o±kuO�Ó³‹™IØê•à³xFcø¯}[4Ef\¥ö8O˽ ÈÜi¿dnu˜„LÿPµìßä4µ‡«S4^uúC¤ÁA�ŒCó¤=½ô»^˜ Q�?Ô0¹u©ÎŽK¡\ù%ÕXºä ñ}p_Uœ·C~òS/™Ñ‹àB%žA¤`ç–½wz+bù£F""6MÍì;Þž8wGheÑçø­j&Â{”6Ÿ`n]ÓÚ´�š?K‰I§×pÅòå¥ä„Pw<$ ‚ÂäL ™ªM—ÄBVU·/ " O2û©{pïÑTãÔ1n[ì¡ÃŽ5¾ ¦�öÒÿŽ) PN2+úŸ5#()±ó�¨óÛP;­‰3¥XŠŒ8L¤eùH°oBKgÈtAÛ�Ö P%d„…,‘õÉŸh+›^i3¬•i9©ºƒÃ¢E„<ý»�𨜿·Ñî³#Œz® c �Bðf”÷ž¤†è%TsþÏùôù ˆø=¢)ÿ¸P+©%LMîë9´ê„`^‰:•²½3gL³Ô½ß�tÉy"{6o["²ÑRÂW¥'DG£�±²7fT닎Í}§ƒ×'c7õìùnAéÙÇöér΋qhcVuoÆÏ=§w.Ô=ÿ‡Ó‡œŽ*ð5£m˜<ëŸæ/zƒ$#H £æõ™1Âp)»"¬Þå$ždð²·¿ƒwýȱŸÇb'ºâ_"}G,â§§-ý½ÓÀZD½“Á†D”Ýmä´§³ò:éåÛ6:àDÎÁ’]n -á/¿Ìø¦~iêнq5• JH-…+R:ÕÇ?7�‚d¦�³F8jn Ø‰Þ­t–¡§½×Aü®´X²”-Þ÷8šŠÅNƒ-ãâíRâwÁy®ÿ{r˜ë¼F+ëýrÜœšÒ,y�¥­÷Kñ6Q+yB³Á/8Ö‚�C’扂@Ð ½0çÖìÊ=bú |Áe߯f<â¨e§¢fÙ zîž°¬c­ÞxO—õ�a_è±Á_~+žGWÁLyf‘Û2ôœÆÿþ±ð`ñ–ÑUUÍÐ…RgÐé}¥…i7Á’þ~ÊÞsÀ&©1ïÌ‹¯q¼¦ ¿ o‹õƒ' ‹âÁ`âõò=ça°DÈú>wÈðy±‹~ÜÎâ… sd|ZG¢†,Ê�o©v¶ÑZ�Dù6«íe÷zÍ(®gßÒöHf�Éß%r!?Å}¶ÄM££ý&…*ø–K¡sLQß3•³KntÌÅøÅX�B²Ja'·Ïï?)Ntsþª�1|¯Føo]dªv0öFÏ;Ó>9af5ú1¿v¼ERk3ïuÐ//í•<Ü0ý›ä^¼ñò*E–ö× žZs¯¼& �: 3¿“ë n( öŽW#†…¥=‚àþ3ßþPDõJCØ%¯ 4„Ì�Þºu{¶Nð$7ª½�7Ÿ½3—p¤’hezãd1ÔW¦?ó³&ëðbfT¹:ÖÙÇÄX±½àײâ&!VêLŠy³2÷¬k�ÃÞÀCô§Üg5Jòz{Ç—F„Õ�Q c|—À|ê{`“Nÿc¢úƒ“¦å²á–‹rù‘h ¡ ÿÏ»­à02ЦÀòÅ» Ùüw[ÞŸè­Ÿèd8«XZ[©‚ª›>�UüÓŽåh=£ yð‡æòÊ‚˜À@©Ó§Õ{÷ufqÙç_ĽÄ¸þq?¼j2Àî·yôSœñÅ%õ0H¶b– %Óð΄f?Ù,è°|¢ ¹mB]$L´ïËZ5€š\Ñ©–{Þ°ZÙVBÉP$¸†ýÒj$ºÍˆÒ�׃ʢÖEáUÀéy³Ë⊸PJeÆzž›‘Äæv�7Ú¯hH~Cª™×½ëך˜¨‡=òVéƒn.pBÔÙñôälʯ@¯ò½ Œ#âéõ" È¡Lò¾3UwWtr’ú Æñõ¤ÄŠTg &Fi� FPˆëÇê»Ï7!¯(GáQJÙ‡Ã×z§—ñC_×U‘ÊÿY»¯7ÓrÖh¢íœÄ› }‹”¬§¿‰ùžÊÔ•�cú€\ú+n »FÑ2Gü!´,c ògš»|("±Y1úq^¬‡íø‹PÞôÍIñA=d Œ÷ KN¥ÍŠøqNã‡ITy«ƒ‚8î<žñøˆŠ X縆´vbùÇsCLö)”¢w��æ1ñ‘âfMVŠÝ$½,*GñˆLwüÁgÜJî·'ÂІ!”Ë#:ÖÏ‘PàÓq�˜ÔWU .öšXÛq×Gx]Iûm¹˜ 2"(5È¡^ZzD,IØ�Ç�º¤*€ßb7Ð^N¾o‰©ÎË ö¬­ÓÎÏÓ±I¬[.]gîQr±Ò}TÍ  (Ialu™Ÿl…æO¤ð’ÏpT, i#äÒP�6*©3È)øÐS:õÅ{ Y]£lCB*¾à#žÿ²UVPú25ÏÅ^,Ë«šgˆoË!^k>qR ¤Û¦!ò)xÍY’Ȳ€=÷²ó-rsˆ( Ê-4W‡*V'}¦Xå”a,?Y ät‘eoíü­ÿ cm";å!Í�°Ìaþͼ�ÉM8¡T?•p 5fâù¡ÊÒúÈ<þíNÊ"µ7/4M—=Ü Ý_؆ú—ã+ïoÄìóR’Œ†ú£>ýè3ªíX ,ÖéJD‡™¬³Ï¸A-¶ç)ÌåŒ[Ôó³1"+Xü‚<Œ\ZˆÄÐlFKÖVêÍÞsr¼"³Œ;ªˆîç�†ø8)}({¨"ȇlMŽ1M‰ˆýÞµ!¾Q©ë‹ §öí­ò“ ¯,~Šì¸h3vë%=<Ÿ¶þ–¬¦Þ‘–-iQw¸§M$‘ý†âäïo²LªÂ§¥5³º°KŸxùÀŽ$¾wäèñÁ�}ññc6¬¶ºf.ÿhA•ºO=Yý:Œ3Å{øã&Rq9¦QÝë[– A�"c²n^¦óu-8­Ñhøƒ6|’ c·‡q! (W¨¼Y%¨…ûRB;=öÎÐOWÊÓ>¾„Ø€4§M»ìMVú_¦ZEv‘÷E`…�b`NÛ2�;Þ̘$? ¨ëèìð쬡~0{á^ÇŠd"uõʵÎL§‹ßìÖP f›ÁR¬Ã¯“B)#¿ ¯óÑbÍ&k¸ × Œc ÖÆ…S$bYfÑ~Û$1q#ê´9ší7Ì©¬ð.N!­›ƒ}‚–ö—"%q#°e`¼iħäËLdQÈl³œ±· P�ÛM}]•¼k §n´Ù,ˆÅLc“¨l3» K‹ rAÃÖb|/º®�œ‰º9ZêŸÓ}û7P[\æÕ"¼OHžt®¶GZ†,í,t~Ó¬™ª®ù¨LAjRº�œL,Ǿœ¶&Ä1w˜þÓ^¥é¢AÔþ©€Ñ�?*ƒ�œíï›É\•ÿhÀ˜Ðݶz\ÑÞuë�m5Pð�ÇÓ2”ª€ÓÅ¿€¡œ~tÿ7þa{Íù—CDªÏÐ hEb¶ÜÊíŸÇޝ"Ø¿ºI¬ 9uEÃ>OÜs§'fñ™ç„¥êÉ×59,k!Sê[GƒC18އàÛ¥†Óô”»Sšö2eK9«¥E©ë´>} H� �ã OFý+Ôê&ÿÄòe*ÈJHy3¼¿~`Ÿ?3¡X#°�ÄïÍT»;qœntœ°Xù]dÿÎAåÚЀ! B÷³½./ÓEg��Ù‘/F]¶Žìt2(æNÉ"%Û&Qã˜c$¬±ìнßY7ì9vûEaÿah·Nê±¥ÿY º¯‘�v­tИtXø¡m;(ë�l’‰°ý*„îwÓP°QTœÁdo÷ç¢zž›u,ÄψŒlä¢P¶îÕñÀH…Lxm3ãŽL¨±¿yd…<.áÂ6~SE‘¤E‹§å�w²«nq¯Ýú¾I�ÖšœƒÉðÍ öl3Wõ¢x]Ôô™sÑ“a©Ÿe5[ÙŒP-Î?ωà\Ä|<ë ‰^±¿½»ÀÀN�:-Ènº;?­°8]#\¶èŸc]4Øö1KÇ�µHw<–2Ì㺯£_g¢vÙÀ¸%ÆüE¾ˆÅÿ}ï’îŽV„g~�¯ê±dÜqh[†ÓÏÖ­™¢Cò®L&*n×apJrÏȶz뱦�æõ‡>V„®ÔÛæ½si°}λ‹M3ðiAbòé¦'Õ;4¥és%±ÎS š9^=-sæ l]lt;x':¶‘àñ¦lY,'¨n¿�‚ã‹EÀ¼×}_¸HWÛ60ú`Öà³¹G³PF±'þò…|ÆCï|.Oe™ƒÆš;àUÕчÎÖË1õøe<ƒT^§p8¹%š‹>ª³wjH_;<Wl4#úhû»cÙöÄLwïäD4‘لĸ›í¡(YNñÇ•ˆ3Yƒ j ‡E¡"If�g׳A–õui´¥|HåUa‚ã¡ÕJ4’÷]èÉÓë!>¤ê´Õ@BûFÜw &&¾Ygóí ‰è´K�Os‰…ÖàÕ)0ýÀ WÐ67Çü#êÒ×ÓQ„LÓÔ7Þx©©ËF]2Oq5"nõvЛü'ïõfß!A,I‘µƒV`xÆÇ¡)^ ÎGw`µ00qEÛ;ùÍ€ðE˜æe«¦h»»œ÷ d„pÏçÁU²‰Ý$Y²H w´Ó‘ RDu+W#b�rv𖯩í�¦òäóÈáC‹iþOèÄzkÈÒŽ_P·Ü Ã�É¥7Ê’àí¾b�!ˆC¡±Ú:+vÊm|Áó=n.]ˆQóV¼š ùyÿ£ nk¼�ÒNY/Q´y<&o„%Ïx]ÒD�"r7|ž·ºŽrÓ™¡Ão8^gç긼gе̓dBiËQ 08}ƒu†ÄžË?1d#ìâNŸ@-¨â�\핾þ:L[=6Á…¨{ۥ㱶‰îÎK®ÏHv Ë´»O ¬+?;i[vÚ›Tb4›dc„˜¹¡ä®GKZrlõ #< µ©'C®etÄšê*»ßõrƒT°&+=l•Òr‹ÆSøÓN¯K6±E«!çLYݘšbzŽí-�Ma˾ þ× >¦atÀ(O.—4/Ι÷Tß[�ËùÈô²›LéExÒ@„žÕXÅ5ŽÃú\˜ÚjÐܼ“.n"AœÛÛ84Š�œT»Ž4›û1†ZžELL/Xê?j—bö ò¿ÒìS׉�a.¨XTå‰\`}ËCÇt-‡�¤éù¡%`'óxäEvÿ¼ÔNìŠ3‰�pGx„4ػʑîï‰ûãhýÖ¬¿Ñ–?§ÌCÒJ«•°O“Œâë> â€É+2Ò´ÌØ.1cöž…Œ7kJ³iß¼LéÏ´=ÆŽJݶúûp} aöް÷—’J¥äqøah·NºªŒkTâ‰Í'�'^-‹Z2³6 �Nˆ&¿Cê½C�—L¦ù„°>“�å¤�U:HOlÁ£Ý'ÔŽ3©4ó|¹�@;KÀÝ› A€þĜɑx�%$q]u¿fd‹š?æËãd5õa›­°˜ÖèýœVòá¸Ë÷[öæò­y‘*¸‹ ºnØK"„À‡B6œj^Ù9“nÜÖÖÉ Q”ä�°C#vÇ‘I|àÀÁàá o Ó.xËì; 0½OhÃW–ŒØÛ³³ Äì9[â¦:Þ¤Ô]õ¦ßñ’Œ»-Ufìñ›Ã¿díî<«Š/‚”Qû³´³8¤MÿÅ×3Fó+tÖ€�HaÙÑ9°”G·(y…;xíEôÛŽ@óàÆªàOœ,`â ΋ pl”YÚ0í)3—IÜ¿Kgï=ù¸7è¼0±zsõº ïÌöKlHm7¿ÚšPòB2ŽÅ 1²:ßÖBé‘-'RÌ%¯¬`I=÷Q6fMØÛ^¨¨, ØX¥U^ÈìO–ÂU¯ùQ¢0 Ùrz§… @^·v˜ØN¼xUÁ½½†�?ÅåxË0è&êúfHüžs~IÍɱÜQ”N)²Å'�ÑçË™ùX©º� ?ûÄŸ¦ÿBRÀ’q EeIŵ‘wL –~úu2¢= åÏUZ£Q×=t7�Å BãK“ŽbgšˆmÒÍNÓ¥@D3Á´>VªlEt^²Òy -¿ïº×èÀÖs2ïóa�¨ˆÖ­ØÂ>KÁº#'aˆ–yjÍhJhb\Ã]Õ ?aåÛY t”Dm>‚ÁT…M²Ì8 ¼¢Ðo`ä.ùa›ÊhÙ®Þô§2?Ùù;t>uhÑFò|ç}µ‡›½Ã=s†"r¡OÞ¦'MìM£äfë�nKYK,,é¸3]|¬Š— gƒŒƒF/)â| •Êånñéèu2x” ("KíÅ?„Vî› ˆeç(šäÒûS_ý ¦ ð§ vè¦EÓ®;ð×8øª{žBi›ö¼qz˜}û˜ûƒ…†Þ=Û¹®\0æl0Lv€<íÙÊà§o^¾›‹ M"ÔH…wŠŠþŒ40ý1<¨ÐýZx ª¸8þ’À‹¸G/ª|– BNdd•ç}›IçöìÿΨh¦ü£JĽ*>[}½vÄÊír¼At)*=|Šæ]>ÔªÛÞñoìÎß@Ü6Pº�|ü‹Ã-K»B¿Ø1¶;g˜OT,Wsά"ð„ˆ»ÔÕz�™ƒñ¾Å;ìa2øòÜÈ•‘F–AÊàÉöOоà��“§\±qŠVÚiÂT™Sm(ÉΩ -­‡ìÒD/’?IZV$c|¾TsSÈÊÊúÆ �bJõB‚=N(¯ÖBXl=ݤúý0 Zòøñ‹NuSD‹6M>ÈÍËâö ÕÆqL0wÁ/V>nës·ÂÐ@Ô63ºåÆ4@?Ùl‡p½£º Wàñ¼[¹jðJ¡É,15¨îél<ÙéîÓÏ'­]µû�Öš¶õ#pórw÷ŸLðð.a–Á4R3©.ÆaQ)¡j5 O¯\PTï,ŽðØÐû{i%n¾‰¨§ï¶OL—VØjÔ¯¾tZ¢>€Ùgù¼%¨é–1løvB#�°-+ëc„é˜wÐã¬Vèž;xq!‘wW¬pÞšoÐõ9áÇû ©Ûj–?yA¦ýMQ8h ø±}ÎVUüÈ^CÙaêV3c³KÜÂãk}RþÇ¡-À�§„µ?ÙÂjpc¹ð6Ú[®©Z‚ñ?ˆP²¢ãÙt÷OD"?Uçû&¿´�i*¦ó§.¦;8Ê[,“ÇäãQ|•­È�\Ef§ ¾8 ÊÞë%YÌd­T§G»} k'0!þ}-22‘K™˜é×GæÐžŽ§lªÆeÇ�qõ¨Ù2響BÉcžpÌw/…†º‘Ƴ Ùy¯¯i’‡}gú¢v¨©5uÜ :åÈ_ñÛ­cRI¦áÚ•„wÒ;ËËyâ¡ñ£;ðçK‡Úcg‘e/ÚÕØx'¹¡v9áKÐò'îI™Å¶,î7´ïížkËúb/áH¦¥Ò%¤оÄP.¤2zÝ M˜ãÅ.`Pü¬Á%O�Ï�C`ÉrP` Œ+Õ¬jï8¢} ï š§ŽÆð\ŒÐ”JñW`ò©ù©¥¿2@e�•ìï�£Øó ßiçÄQ£ëø=ÉËJÜY -€MeTT ÏXɰûü¬Åƒ"p ;È/פ?�à·u,¶�«ª£¬æùx¨O¢KLŽû"£Êíýs•þEÑÓ/Yx§$¥+Fúå p„ˆò Ýz<°¾8¢ÑÍH�9˺U(°.úã¶;è ÞôDÜd&0:ký–{[ï1G¡ÔçRZÞÂ\Fk?§@ :ˆàJü Ìéu„ª8›nì¡ÚlÃS#úåõ²Îlјu€ŒÍ-'µÕ~Ú‡©ÖSã½v(¸¯O›Àà»y²�Ýç´AS“T/*•sj¥?<‰—EU™z ‘G@¸�ˆû´ Ã9);øÞï5azlçc¤•ÁP‹š”<kÍv?Í£Þ†á>¡œPzäH'åêrfÑ”[3+OOÛìˆ!Àpà´ºP|Þ­û‰º3�{�B½$Nb!ÃÍRQM™žæ;òmOøš1!Ø Œ4¯s’€Žn��þ^ØW²œTÚ¢ü'ý–ïÒkR\Ïvj©WÏ5P[àBÿêÙWùæ+÷ÆŠPÎ(vÓåYhlÃèM¦Š^®\¶Ö…9yÍ»o<X1¥vDiËvIÞ°¢â8³.Œêdñ13Ã÷ÜP,&Ž+j¤Œ;'ò¥UrâÙù­‚í3eÂFöŸu +Â.Fžn-Ý×BB|ù&séEÁ’LÅú^Ü?Hÿj¹… V46>§ |:9çÑâÑóÅWöq0ëQ‚á bü±¦xÏôà²ß‚;㳉�QÁ@E�Î�P™-~¿µæ¯ä 'Σü‚€ù”z|�-°iwLuYZ6œ£Í?#à!8N‘ß][ "Áz ü‡€x_ÞP²H.�‚Ä4ZDw�Né‹¡¦Y¨ŽXË�/c jù-ž\ñ”€˜¹µR/M>²Óâ °|&#„Ä$ÖÙ'|ié¥DÃñþå³@þÉc /Vè™T%-jþ1{<óŒ.‹\¢XIPä"üÔD0Ô(M©ñxBš›VgHñrÇjÑñ÷üa˜«(Ïé p�Zhó`Ìüö#w¼saj•ÂëPÐúöÍæaCĔڿýéXÊqcQK& »ò²ß>I5%ç¯ ÀqÙú°dLô[V�\sÂÍš—é)GfÇ$¥ñ=Bk§�Þ˜¶Àê]·4AsT&¤§¡ùù“>ϳb®öÒÉzP1 PÓ!¨³9n\•p [®Nˆ³•ðo)\DêÕà”q¯ˆ pTn7ý6L¶iñ¤³IAQŸÍá¿zêvÓÄ”ƒëiÌóß�›8£¥ÚòñøD[oòÙ†ªj�àå ~¯P $GÅÊ'kžÉäWÖleÛE˜ÍcÌ5ËÆ•LWúD¨ìì¹’ªZ„ÜV´áûÑ½Ê ÐÅùëYwU N3ÓøË+š°YK[ž¢6_ `ÒÙE,Ö‘I?+Õ¡ö7R-Q$AMÖx¯qIüÞú~[üÛÏÌûÄd” #=óݳ dÙ4f�Ùå—ƒ-#jØ.ø5e„éþ<_¤¦›±²×Õ€þZEÄJn�Ä@aßqËéW³Ç¸!ÀMB¸ÊeG'ã¤W—¹®Í:2ÛQm,+W}BjÅóéÅZÎ2C�2ÓÄuù)�¿d“|†‘'Á"VP¥¿sýª ò”mAë„B‹kÀLÍy1f.Ë'ÙÌòÌ*è½§c¥ ® ,;NÿäÈ+ÐÃ/áž \Nˆ€ûg`­òõíA “šU«¾»’~pÉ­/ŠmŸ…šŠóÁ'²Ô…‚¨R@¯@ò‡…AU"¯õ?V“¬-âaÈÌ…{�ä“MÓÞåµF¯d¡R¢©Lk7þ_Ê#«y<�Ì-*,¤öM1íßð{sA,$¤¬ek}Ç•}Û¦|Œ‹vˆ`t~:~šv^Q]m¬mc\"š�ŨÂ>“,^KUYƒ‰(‰"º2òß|0Ò´Õ:ÿ·�¯‹*¯Úù­ÁFõŠïEÁКF4Fö—ž›m[s¸üO;n7Ü[^­O‹ê$†¶³Tçž|‘Zú0w³í3±À4ê<ª¼ÂçS$ñ5ÉEéÏ0K�E„øÆ–-¿9àx—ãèèEŸ|öd Ð?L  �[RŽ˜"+ª¡FûÝC·wˆ•Q?AEÒˆr Óqe…Œ‰|g!(pŒH·öÍtueÉ!�äéBÁ«õ ŸF0±qt`…’9Jæåö=‡Ø®ƒ·úèv±�âº?úkAª¡Bºþ4 ÓÍ~ÍÔ+ ny DA�Ã'ÒæÌü·H‰ߘxnQtsåG ˜·íbçî!{êÉ¿v{1rÇèkÜIÍ ù5�i,mYJ’ubMÑÂH¼q„Ž2×Çâé,¹³õ)–F5 o~�|ª"»ñ:‚:ú™Þ œñ«µû×= ·(ª—ܱi­Lµ5‰;%§éru ùj™¼ÈêÅ¥^êì~û"5ÑÄIN^Õ2'X3f^ ¹„€—,ä®ÚÛѰˆÞ)áæœ5 3ó ®¯EÀ~U,-Móп^jF‚pJ£µ$"ã…ÔwÃ{"d'½ËÀ�¬$þ"ÏÅÍ »=óèK–†›9¡¼Ñ«Óÿ9*vG±ˆÀ)í}#å7îòQ´è 6vî›TÇv-ŠDÝx‘º±àNƒ9+�òçBWqècÚèÆ_„h/Aáù#ðG2Ô¡—eø ö?‡Gù5JZ«Æ~�Úñ½žª²ÿsÅ^¢ùH¹ˆ Ì4e^»Í¬¦!Óì–üŠHû4î2L¡ÞGÅB³¯ÈÇxÍÐaú±A=±]Hó÷‡=e87©˜Ññ©zÁ†�ØÓXüUü¸.Ö«¹?yŠàŒ âþ>mdÜG A‰&þˆ¬ Y.ßOé0yˆý `£Âqü Å—�¤‰Ÿ¤K1b.68�pó|EZž˜6yZvä&‘^e.—¢ÏÍ7§0vk ƪ„lÿo KLwÍeo±Ò M‘Ó˜¥ÄÝŠØã&3¾ñZÞƒ©Vå5è¶c—.üž¸s¬v¨ž¯*‹ÁüøGŒŠ1Îφ±R‹ßᚣ “ÛEÏ„2‡¿&>ö� 1² ZÅó¯½÷œÃœƒŽ+r‹û¡¦éòâ{í&boV5påk‡“’½_+‹Üj*o·çgýhp¿ê“­ŠÅŠ r°¡§ºHÍ`1]”µÈÉ ¡ºäÝ9“óÏoÅP~»µödýýYíÓp—Í(Êé£äÜñäBŒ61[’ÉC  [ÚɧiZØÌöÍ©ZãDÇ�‘¾À³’©QhˆÃšEAí1öë–0C8Dýêk{±»K‚a%åÎ Sáò|Ä¿B œw³ª®aš;ðêW!óZT:9‘ÕªnçIÙêü¤_/:”-€™?mÆ’†®‘Ÿ;SÊ 1]žeà/•ÛfÛ/#úZ]…“ÎÈ�ÿ½&ßè�qbTýVš-ÒË * Ïy†–¢à9tN–�¬0ë@,€¥wâšù²"”%…A÷§/Ó•)àrÒ'tò¢„&©ÎdöWdÁ¯-u8!† E�ÊéÔé¿Ò¿Pc¼¹Óлg ’Ý‹JùÃÏ93„1²Éc§‘ I5+,z†­Þ™q‚˜Œ+¡ŸŽ�d‘ñ|Õy£MpÁÙ{õ”˜Üýƹ=�^sUâF¤ óß›�RȺÔVX ×åÖ¢JÛtÝè<­ðõûo˜»·Ëég#ŽÕÑTí{ž¿[ßóüœ£âoÌ‘†o=l¤‰ffH°ûdÖcÈÞOÁuŸ�ø�"п_Š,gàºu®#ŒæqIøafgžqhÙ–ƒ%šññq'ƒWØ,?ùB!Îor‚Å à:s3;ç²¢V0ž‘YÙö÷¦ÈÑûÝ£VÒ3»mŽïù SÀ�†pYiÂUø°bÊñLÊ •íiMÃ�ù®™=šçø´Î5ˆxÀ´çaMÔstfî[O^¸pñê(7æ§Y¸¬ �N®K`Œ¡‡©ãJux~¤Y½}[aÃì\óÃ$çNÜ>w,E’¯Vk]ŽE4�pOd×ã@ïˆZ°ÑB6¢¸ú6…%G‰[ a?֕ë†Ýã6ãM+4 ¡¥¥ÀaQk¢;*§œÐAcÐjþ'�¨èo¹Ò„ÈòÏŸègšØœìK:HSÏl§¬S·ò¢–ïy·Z“ýH7�{ œˆÎTéE¦u¾� ¤8"+BÔ ʯŅž&#Ý•�p³nŒF›ÅkðTjûK5¡a.زF¹§›J³ÿƒœÀZ‰)á§;§©Ò˶,ƒun‡Á(«<Õ§Ð œ .ÉÁì1x5 P2ôŽ0•ñaúÃ~£kåûé³~…ãå¶…;e’Þ+€^oH½YŸãÅošyÖ —§eQt¤s]¨Y¹H�Šzý.˜–F–TÐC°“k¿¬8äQÒ7�7R�Ô<Ù±¤M@lýha�¢ê5�ÀÈe®€¤¦Ù¿þõqù¼r(ëÇ¿g_Êv›~Õ³ð‘Kb¤:‚D�j¦Ë€Sé%ÑÊY†Á!àÇ»�ÇšÒã ‚ ~4N²ƒ•�z¤Þ!j@ÕÉ^žF;‘;àlg7T”Hù¶‹°'ÖPA.YeÜÕÝ7Ï›ÙbD¦òÙñ¨‹èÍ� »Ûœ0(æe­ˆŒŒß§ÉD!ílœØº ¸ƒU‚«ôÅÖcÃÙ³RŽî¨8ª–> Ýh)qÛª¹€â3"$†CkmD¶Çv<ž^‰Ë4¹¯ìü¸K®=žÝ ÈZz¸pKÝ"/\ÿ‹>0ÍÅ×㔊êòô#;ºL }è+>¹�BÜ3agÚ;ÇSˆÌ.“±ÂùÀ•É¿g;^ìDWOT½ uȰtçR¤LgvÀPH�ªU]o¬Þ¤ÜÝŒÚþH[˜7q»S ¥ôì°(ÈÁGA2è\ˆS‚á †0$c·ÀÉ©T•RFöoG‹EÚÒ4¾ô´Ål²r ©Ú3Q öb+…1yecQ’%=ZT\pþrp˜‡º‚m% q�ªïE V-ð˯·¡TþR niIs&bÑÉÝøúådÛx»¦³w�2çà<*ÞcÛ¬éÄ.AG¿â¹’=åˆá;ê‡�ub¨çè2¢b|©ÄjÂ6‹ª`¡“>.Ù2|âªTýovKo(G‹±Û©73ÌvWs¶±Û‚T5”U ˆÆ¥ØZÐâžå '“ÝÅÜê¶]X K¾œ·JÁöø�º|³Z¼ž™[±J€ñ> d<1yÈ`d½”²à†¸‰':¿Ÿ.*úÙŽ žJX?YÌ»f(ŽÔxôçJûΗ|t²Û0íD-Ö”‰$ó›~׌ƞĴô«i�ªxzbÇRSñ’ 8³-=P"c&p£+2¹¿V∠"êL‰ÕÖŠ{…?Hƒ%×¹Õ~L(øyl¸ø÷°%ð[‘*T©LC#Èfs" ‚ ‚˜:2w4p�"w¦!‹å»vðèÍý L¹£‘¨’ Ñ—'îÔ*,õ–„î�ÆÝFœ- Ô-)ó–‹“Xn%³ù–X \òÞ,Â(líúØ&kdÜŸÜz¾þÕ w®@J¨øÒ ´»–ï z#t"æEø2ÂÄP0wHÁži&óŸàpès_°ÂªýÏѬ„z¿4eO°´XÙ×ç?Ž—F¬òÏ#So&§�´¢ ßTJ 9¬_”mrš/inþÚaVvÓ�YX†;‰Œ¡¢ºæ7”­ú„¬‘¸œ¾Ê"cÞe™‰5k&”1/2ÚöçëDK=4(ÓÄSÕÂ&û}×_@?8†ŠyÂb·„'Á·ò$)…×ƒÓ »_ŽÅn£ða 韈qÐ*Z*p’»$M&÷>hT_–‹3Õ'1:”mf€?â¢E6ë�Ø1>€”wô«¨€\G ·x{O?+AB ßÑ%–Æüï³1¾3Ñ-㯶%TêˆQkCÌŽ‹èÍŽ´p½4{> Wæ¾¼�x=üÉD¡ a]êXç:ÅãþÒ\T²™‚6w´`X>Œ=Þ…\ ólQ{–J5T�´ß*K9XkÇ£dØÔ}WéF9'Jvêå••Ùô¤´Ki”mSrQQ¢e£ R… ¼æè‰ÞÉ߈Yßt×dq¢!(å¥Ì[a«’á+³dÓ>PòÐú÷;áKM�ê¢ÿbfAµ¸ú‚½“p#R2ÍÜ�ĹÁcéR£­Ñ¸6÷½˜§5Õ&7¼Ì^ pïݳ|yà òب¢0ý+T¢ÆQèèíe™›�òìåÞéƒU_Î�Š ‹bå¥Ä š�€Å…e¥h óüPÁ9Há÷Þ¡ÏXWlp#àp‹Œ-7 \~¡w!@ÿù¶Îè"¥3* ´‘˜ås®_p\´LY”^ÇRÒu @K�¦�ý“i`¨ ×.ÓlÓûzʲMgÜ#KOtšÙV¬M ]“ ù*,šõsáŠ�‘?V$¤:�TÌGOÏ’Ò‚?oH×k4‹>‘Uj🧴¶ÿ›9®Q”ng…£Dd_’ ¥è«ÉËljAÛ5ÿ€5sO=Ëm5úŠúG¼¨ŒƒÀÔ­>]Ðó› 2•ôOán ižU�vÈKÁ%Fyj¢oì绲Ÿæ-uúò†#—ã<Ý‘NT½ñÊ›6E0)X‘Å)¦úƒYÆ"1aW¡áü¶Û¤l裂ý<ó‚Êí_û«£d7�ÞÙ,óÇʼÞåËY�¶ ËrršCõáîùH2­ë9dnõzg®øV.föÎd‡XáJ™àÜëˆÏíÆÉòÙ÷‰ªqnŒ{éWgO¥eC¯eË‘å£ÚC?Æœ†!Û Z4bÓì:ä[ÓÒƒ¶4°aŠ»9Û ßâ”$ÌÞB¯XØÃšJøÀòcyVVõ�ÛÜ_†ôj§#Jܽ e–D,k2�Ž’BKÀ9Á‰¡ËuW°m`ðIF€#G røîj:õõz œ‹øÒqBx�0? �.‹åÑë¤Yk#¸—6¾'sA‘G_£ijÃ��°ã¡®i1¬|®IU¶—+rTžÀË\5 3ŽÌ’+ùW¥笑xýˆ�ΡJ­Êª¥r-áP÷õ8YÝ^;ä6Öö¨Ì¢Î œGõ[2EÒùæ{ÀÝãÆhJf'ÒÿìQk©ŒL¹Ð²î•W\¤¸ˆ�R¯çϽ§Í;¨cQÈQÑ4›ƒáï�®×§Ä¡Ûñ æû@|¾cîp±1î8›ÔŸ¦ñ “¾.vµ°Aõ­€ù˜·†æd®ZoAi)– ¨Jõ-Û^=zuS9! Xú±S³É,ò·¿Žš‡ÞtìÙ‚85‡5 di0)ÀçEúÖËa›ø�þoÃÅ$”uNœÈa½“XÐÇGjÁxWe¿�ÅÀxíp=¨³ªØf¦ÃÛ óŽjkÆËl +ž`_ø(Ï`ø>EÚné¾ë‡Þ'éå�ó€5l³ŸÐàÃ8_¨ƒ•šŽòoX®ôð—vÖ_ÅåÎæo%½}-¯µÆ\,Q¥bw¥½B /Þl¿3 Mp$;@ú¿ør¶ýcˆ�ð°òµd+|“þöàKåIXíùÏÿ‘Ÿ¶úùüó~‘Hª ÿuÂù­Ãg}œWS"ܬ¹´/XXp`€6)âáVW5¢Ä—± þ›š5›Žsœ$¾y_Äáp'åpƒ²c~\{¡ëÚƒ�CG‹"ãÄÝÁ=eLK+5Vÿ¼‡€@Œ�äë¾yF� >Èøx2¦sdä°ÎÌÔ…ãsþhããG’¨Y6HË�>mÍ¢´zÒ¶Rõ‹ŠÆ‘tÀ pjЬà ك[Pa5!Ö0ùŒ\é0eaÒ�?5÷€P•Á¤†—ƒ7z«×ÃsF?R%Î˲}¤)85ªE¯‚äÅ.€ì�Qê*'Ë3ÊŠ¨˜»ók}.•`�Õ?_p 7ð­3-%ÁP»c§B2\XèvGPjÔÌŸc½ôy‡­™òñzÌ&<EóCª¶P<„× wÞQ+T+�j^åõGå[ÀJL3#36¿,“¯MPãGÐÒz«�ítLj1–îò¯�œ¸èw•‹c°èÒzÓeû(åú¶è6YíÇÈH`­Ed&Ñç-#v¿¶‘ÎUJØ•iÇ�Å¢x!.ô¶ÖŒr¼å±1ðœòÜÉR‚Ü”þúÉXh¥ƒÀ“çs€QÒмӥ_‘íÑ–æÙ¯†»äaZ°&úé *z—ç®Ç3"‰š9|®î+ÿèò!|²/Q•æ|©|$MrÐìÁ_^j.ü":ž€Y~¢¿o<ß•¸äýk'&y0ÆÔÑÝ&“2Ž©)­Â�@b-Üiéþ)ŽѬ L%ØÎM.vÃøR`‰A¥Æ0} Þl43).g“È+ò²¢ˆî†r¸ž[[†üú4ögyí#çœpýyPñ$‰ïŠªÕñõ9ŒJÙÓ“#°ã }ödý`çè )ÃkÇ»µ¶ƒxee-RyÞŸ �f.¢p±øûAõ®&ìùÑ\Uõ+{©ÜKÙVs2¾jBäa­Ñ_í ›o[Û ¬±ÍãŒkATÌÙ"YÙÙ+­ÑÇ�§r5ÆÆ,ñ±sîø†.ÆÂq.’/l­£šZ )áÌ hà^`_ý)*ô=Îãf¿<ƒùi«P†Zà†‰/p®Ø8]Jöz vóaÁóñé¨6Eÿã‚:µò '±Ÿê’Lj'îÓ䜞Ë9?|�WÓfõ%µ ‹hUðj.ƒ,áM¢º©íMvšo(¨7MV÷dè°5£‡¤Òrr�éy¢D†·¹7ä¦ñ:§ts‰Ûaé’sÃõa$—È'û­yª»mÏÂø¿¾^—ý¹²%SáðÄϺµÊ ¼*¤‹Q,ú�™ë¥mÍ­d¢æH¸K½�tth�ÿCÄMíFEI@›Ú£fÁ£Åaå�$³-È=²éÙ� ÷e §)­o_’÷f~ ›Ã ÕøÈ»ŸxÎî�ì¤xîÓÿc5ƒ³FÕOeÊ*(à§yðñº|dç!¨ø^Ë ¯Ôéß(R§µ²7IÖ=Ðók!âqǬ4}>B52^¶ómâóèêqw»ùBi�ÍßðÉœe}8¿Ë |8Ú³¨Xõîã>ÔHrìýüŽ|‡i;ŠèšWåf ŸÝ™½E,ÎŒáã@1ÿöUp°j¨ êZAŠ»%"À�ÿ"R6¼;{¹‹f‡êe,ÈñOD?Õü­•±”DöÀ…b0}º+{d�yVaŒ¦ÿ¨4gÛ¯›p˜È43Þýö±V-áõ®‰Ù°F*A}ÛÎüº ¢+Ê@¡¥%¿ì‰LºïýDVcæšÐñ½ÁÛNð?·«Æ¿ò¤§ñ±9+u Ä5{|†ó;%$�mnQãg0Õ„˜?0œmw^3ÄRtšš_i’ίÄ~ݘèêuÖ¯h;O^@€�(ð úÌòHïñïíš%ÕÓ™hüÙîJºÀP«8#{LZ>ºáuk9¶9C“X§ð´r¸#¬ÛT£.FAªäÍs^¦0'„¡áˆH&èn8'ê„SÄ<í«3/‘ÄÇ–÷;XøüŠáÁS3z(9Ÿ‰Ü‹­Ä×ìÇ]×nZ>È,¤#ªŽ~KªÒÔz'<�æ ‡'ìÿíØh�,[Ô‘$Ü ç¹;äZS/»ÜHƒkÕÓ„ì"ïC£ ï ˜�mˆG¿Dí럡Â{ï6½Âò�ïÖèHãeÀ¿ÿhßÁ²ƒ/­nb& œéޤd_Qšq©»x‹ÿV¥m¬]ÝÂÝ4Vp¿AíY“ï¢d�+Rúú¿‹°R“Z.82<éÄÕ‘&Ú-áØ(Ì’/`;"»l9Ãg$}v„Óò¿].+f¶U/޳„¥�¯‰¸âðNCÚÓdnG¤ï®Ä!{šô`*2Rju`Û¨jݶÆäúH±¬õ3¸Õ†’|�¦Òå»ölÓ&Ä xâìLhË‚;®2ï�Â9ÈpàŸø3•ñfO«wŒÕu¤ÃO±7¢3i0h5ЈÜ~5AØÕ¾híçD×퉮‹rü–HÑ|Óé÷ˆD�!¦Cù€7Êgxu�4ýJŠavÔ¶çf82iíŒK€Q(î»úDÃG/ üK&º¹±J˜Êßú|'<ÅHçêÄ­…æ �ú©®¼ã‰DŸˆ—lÙ9lR‰Qú( Ó»¥¤ß΢U5ä’Vmÿ& Âé”°V5©Í$Ó2>ÍÔHÚ¶_¤Î©Á{ÎÞ!³äÞ³¦e•"ü¬®Áö)h²€¶� <¬…_-C¬H#Ñýü ÉEâ¸[�"g<²PlÜæ,ñM/wqõÆ×û.¹¼ùQV§¤Ú5¢ÍñŒ]Spì˜3‰oÇz0¢HkwLµÔuu‰å¾ñÁ¤…×-âuñèÊÑ‹j·Už²Ê­\àB•˜fÝAs»Œ"ÒÈEw9Òþå²f^Pü^$Á=;ÛìÜp’©‚ü…•Ïï·Ê PàöG蟀?Â…5L†ªí& HÙ{Ó- ØÚ¥1qŒ^‡ëÜòNh84˱¬žŠº kñorYÿqï3’ÙÝ0¨ã&áÇ%@·~Û6÷^£¡²>5?Ú‹L½BÑúÄ‚žR®Oâd0€+órcÛÈ¥¹áçûFU*þc“;TØÞluMòfíûò„Îÿ�ÀH™ú�U–¡33±„½²Üê4“C“¢–g‘ŸÄiŸŸ£}DúhÊ+ JÔû¢hE€bòN;O¹8³@êŸ …Ý °-*oŸÌË©ÆèŸ�Ï-ÙûrÕC›îÅÐI×Âgcýx‡®:ê„3)9@IîëUô»ÉüÑA;~»vÐYœçÀ“‡'Ý¡ ýÁ^éÅö�ûçÄlÀ&ÃX�B�;€2¯iÇy•<›ù›ÝÙ”§©H£‚†sïZ#¤�š«õMx•²Æ_‹‚Çb�0ÊÏ«‰‚¡4AÌ=ÛÜ…kg$<°½†gvßõ/&YrYw Í- Õw?µ±–„0*앚œ¢]à4Ï ;Eq#?ŒÓNƒ�°¢ŽÇÏ�äˆû͘ øICßs ò¸­ÐØ�ÿj«¾ íÆ¨ˆ–ˆÍ 'Vh¶>÷ŽŽ±�ǰq½PÒ¡¸xt�"Ê`Û$âîJάšü?ÐÆ¹Ê±T[Ù?+Åïúí•­auu¾iÖyÚ+þî–ð¡²éÐeÙÐ ¼ÎYþö/¸ÈrìÛx�jËÚ�?ÓGéN|-GÑÔcý‡¨è9þíp4à9òÑ´ô× NzÙ”ý&Ùèä’„“‚/ã9mÑ ³5i’~³ŽÃÜKºŠÚy�kƒ¥—þd<jV!…PаëïïºIÏ?¸E»Å娸äyý„RpòÑI˜;²}™öoò|ûÔ•Rn°‰ˆ$¿û=Z¹‘£cˆõÚªÚ¹=e©¤†<Á±ï¨MÆ·CÇBßֈ蟀“¶T5ÓóãDæ_Çí‰ft"XÝz­t³%y’Ö’iÜczZjƒ6pu�±Ñ×?,v‡†1Ò¸�›S2%Æ“eh½×Œå‰¬¢ƒqRýrmZbãŒzmëÊsŽ'•ƒA'炾Ì‘3H5U8�__Û8¦ÐpcF€ÛðÁ¿äʼ½ŠÁj�¢È3ZÌ…ÌuƒSØ÷Ì–¦¸÷Do¥gÆBz¼Ñðõޤx©Œ¹{^z*íàþpÝ宂ÜG¡N¬¤J²å ��‘1ið^Y#(Šÿ‰·ÿúUgrêõ2§—�*¥,™åJ‹©w3@Pè#“ªô¿~q;€ÍšøJ„ni°”²ÂAgà+@È8wÞ(2þËú+§VÔ« x�»¯ÉGƒr•ÈWþÿJìì*ìQð½!ŽÝ ”L/ð!¹+ŠKF‚ #ÅiåM/·¢ 25'“¡[Íß_iØÕ9d['å¿‘gS}ðPåx&ÿ-±£Â– }f00-s3Ø··;,ýëA¾¢À÷=rº ÞiÑ'ŸR ½Tå¹7Æá%°Ìó­’—M BmÈcË¥u«O¡§¾îÕøWyÃCª6äãû/fAtõP=Ž[„âÿ=ö(ô€Q¼§=»_r9ŒIˆÖ¬œç.¹¹kð…h$c%¤,fΈº½çbÇôë eà{³´R¼qU{­„(Èxäïœä¸¾Sh~ØÚ‚�4v"i}<Žõ[³¦'�$”ZÆbÀª¦ÂSúJRº„ŒÖ¢ïÎ-ÿÎ\ŸWõÏÍ³Ï­Žø ­Eýº„ÝGüdK«þ$èŽ]fÆœAoWâÝçÿ6ø™"j÷°÷ï± É‹ŽV2}¬­ˆ8ÇÒ— <ÒöÅ6{³Ëäï¶zºŠö[‚h•6y^8Þh½*ÐßI&¯Nù…$Èù¶þxó#îmo’2Æ[ !ÛSró×ÐNÕÓÞÁà ¼Û¯Ð¾"yŽQö{‡ÚÜ4|<ï“ÆÀ>¡[:�"äôÃàûÙÉx"ïàýõjxe: å{J¸à¶œËð#¦ólÁ?ró6±ÀóñCHÏëóNàßáSk>êä_k®<<Ñ~3i´¥JüREô Ãv­ö¶ÏuɆÏ\¿|ê�œòìÐ9Y°½D¡Ì^–œCãûÂÝM>oc �Á?j6ËÒg«bá…ò<£@Ž£7ñäõ]J–¹™{Í8;UnÒû«ÅJˆ�½N:} gˆm†ß¥bpL¨ê§%ÉŸÞiéćW»8­kš¥å±×1p©åvq>òsî ŽÎSÎE™:‹kåÛŽzÌm½œ®â³^Õì áT”F£U˜>µë4—·3‡ FòRRd£DäßÙîöݾ”*àá@°RÉW_¢t=¿>‘Éfá©Éä‰pWi�BGaÜ6oOK„Ýá|:ÂImþáù©*_âEÔ©«ApÞ�‰ÈŽ,·ˆá¾ÝÆ«­)·Á!PÇ—«˜Îqm†Bt[ŸŠ@úþø3Eé]jÊ]#Â[2T­3'Üé$4ZÏ€ù oMK}±÷¾2¨rTßÏ•<\1¨ž‰~ñx]˜–’½ÒPw?įigE¢dðUf †¸îÐd |�þ ¾µ;Á® ¾ùøöŠ¢è1ve¶œE?ò�½9Yã¬ûµ^¨,G,”Éèd,·1Š"Ë`KÛ”,n,-¸ì¶Z—"ð  «E�âžÚó¥ß’� Öôçÿ"Ñ /„ÌÛI<#:WU‰á<9É•kbßôK€�øÌJ~ÒX/°õ GÇ`T¹C¢26Ct¸ ™$Ê'¿ß9è ªkÁÇ3¹¼ ;ã*dÊ6Ä»Šä˜UÜ)‘Ç�þÈVJ—�®Td‰ÀK|éç‘(¯Äåw…© û}A5T`¾V«óذÈÂUÉ ]P;¥¥¼Kxƒ¯pf«¯Ø&i¸~¶&½D„…ó"=�k¾*P‹&S†Ó¥ÜŠLLX,ý®êöe�B²Flg�–f8g7bˆ)¸ÇçТEdÑ`/ø{X ’9'˜âÿ#£^¯ÔëS¨ô¨ØäZ§Ž^¤'52n¸M@Ò�az4�*³™õÚ²´Ü·ÌÕ“ë˜û�SqèÖØÕL�œ gaxô}µý<·œgïmf½ Ëx ¶k!oP«©Ê D¦n·<Œ²f¸Fw¬Ur=’ôê�Â?~ËÙßrNÕžÄýy´ù³©xŒ¯È©$¡Í«ŽÛ×\ _ܸW »Dù7†ø9‡Ïúwœß„ZèÃ’þ ©=À/@µ½¦@ÅNRúÍI"ïUý½Àà~î"è;\&ðI ¬™© ]ãgïΰ4™O}“;Tdu޶ìíš¼ÌÒ³é „+Uü`³aî8^h¡ÍE vD²2(+Œæu~ÆäÀ’ZÍ¡쮈^ðä„�™ŸÌÉÏ}Ún8ßFðéÝ4d“Í?‘á�\Qãøµ·²wî²Aíÿ;Üጫ¿'º¥�™Ð¶äšyq®Ïþ¨§YI¬áI†lLF‡9ÐJ4"{ú³ƒŠ?šèý½Ç¬êæ¹²–­:Úºœ(K^ ä hn›‘²nú–k0s#†—ˆUrd¯ `5„ÿcœ½_tëá=Ø„­Üù�ÃÎðšÚÇ´¥ÄâùQ=*½²ï=s¥®ß}çK½Æûpàõ4ØM åY¦®ˆe航ïß¼p+¼ù'‰„EJ]ˆçPH›h»k <­ýÐ7Ъ׿H ìU¹FO_ðàCð Æ`7zÝ �}¥ÚF%¥’ùÓºr:#j¡½qsåßÂ_ºÊ?´ïFÄIbµ”;œ¯GOÃÂ5l’;Â÷:”ÒŒ2ãG(Ë~zÏ¢HךîÙÛ9 aÔ <¼Õû@r©� µœ™„ó›®ë6šã€h”Oc(Õ,ŽÇyÕäâ�Í�=ÊÖÀ{ˆç Ä ­4J>ØM¡Œµ|¤òv†%B‘E:¼ZœI3jâ†>>&¨ü`7FÍŸY£¾æ¤´.ÿ ùÒXßÒcÄÈ~ßZ�­dsŽ©#J:z¤&½ôÈB�1³ëýè1ÕˆQ/€šC0ñ!›ÚFåëñ!Ô|æÒóÊ_'œóÄs Ôã¡H¶(E³á9=Ýæðà8ûÌG‡@Q0Ͱ=χùþ’`:Ð+Š7àk½|ØT>»ìR¤‹ Lë5—ú8—-Üî×·ÕÖ„M>ÔG)Õs¢¢ö!eWŽÝŠ\ ‡;7�¿M€°^ �mÂó£ñæ×â[ Þ„6:/ o.Sì·Ð—`{RwÚKPú=“£ ½<¸R+˜ÖEu%”ö.i ¤‹1ùôŒß�ýœ®6¶‚s#f<¡FÐòÄ [³0<ïÏmÛ„Ü™ÆwUñ³f$�ýtÕùß(»É�ñ£­ðÝ­Û*ÍqzðäæRq<…o–?áž™�Ž*âš®7_l0W>õÉ M¾u*Õ>A“�íè£R�þ¬ëIí3ße•:Kàì‚a‚K,ZëŒØ†‚mʺ’¸p&_°=ó–²úI„”è=„Ð@då‹ú¡ÀÄéék{gy”*‚o>àeQ»Hc�÷\[¥>/èñ…u)¼ùç‡]ל.SZ–*<Ê¿¶¦†â¥óª"Rë†Ú"‡Cí¦‚9þ CÐJŦ)·ð'D8§ƒšfì:EÊs÷ˆ¿Kxþ³ÿÃ`×T™%»OË™-ßVÝ|9¢üeûªF2’ûñÀðÜQ"@y’@÷’æ®F6ðï!,Ió¸‘ÖДNÔn—86¡ üa�„«±ðÁu´¿Hí‰=øŒ¾_²¬È3ê?v'ÇáùP`áµL«]"ÐûcE€ð=ÒXw:ví˜áJe~kyÀ†øk:uË ÝOxÁ/Ô%gÌ�"œg±™ÂQÆF¬Ñ™ „�Fvä'ßåÃ;*ˆ–ÔÎÅVRGŸƒ‰ ˜Cî})µ„9­³½"•ÃËq°®½^=ç¿¿¥Î`„Ò4žO(;‘O_{½Â ‰R™ï´3FAdþI]¥­äèƒ\º«Ö�¤”Ô¾¶7át-é¯SêÉ|Õà—g%‡ï"€ gí¯&ŽËÌN%®±¥@…šP|Œ±Ç SÀ­Wªºe>ДTNêQ«ÿBÍcëQ¢"Õmeò¨ WD`� ºàŸ#$¨!Ú0Eb*üguÌ¢pT„óÕò8œßËÊ«În.Ý‘­. ½ÏèêPQ%Lz°ÚÁÉuËÈqpMìÓ«4£1 ›àãÞn$”„Àƒô‚—'þo-hÑî)ý9g¶²,Ÿ_¾`AÛ×ßÅ(oV,å¿ç>»"ÖV5ˆŒpζ°Õ|ºp‚Áw�œ•qdñ¦öµ¨Ï£ÈÖîÎME˱ÍÀbbc#8äºaoЬœš'§OŒúÔ�x•ºN‡.¾Sû„ž«I,>xŒx¸ôÐí¡Í–˜�oŸ�XJ ãU¦[¹1GBìW.O2¨²÷–ªÔf ×ê_›Õ½—25(Zûð—?5ˆðN›7Z!CÄQJWñ˜¿[ãÅR‡Ö˜2àÆ¾]�ø×ì‘�_Ý¥‰=p‹+ƒ`1EKžmç´æ9#‡Á[#ËÝÿп?óXûh‡¹7¨ú79P,V·¦œ(Éxbþ’†Lz†úñ3üáÿe}äøû³Œ[HÛ°\Ã~}ÜL(¾è|½œÒETÀDîr�fB²�Oø¤ên� bTO²šºEn®Ñþ“¦ƒÎá¸S'å«¿‡÷·Æ¨pã“+çŒ <°„›ÁXõÚrgˆq#@Ã/Ÿ³Px[±NNÓiAeJb¡í6÷Õ6Büi˜úØ^W2öúO¯bÑ7ÊaR×�1hÀp ”?eµŸ ­F¾X·ü^tZ•JöNPz‚ýc×ûðâ@£ÇÝÎ…ýƒR^�#“Æ€¼ÉŽ@Y}û{˼íÌñ-Mbðò]lüÃ6’œžØZû�©œ‚§C�™ŽŽZÿË¿ õ»Ýµ‚ÓtF±y»µ´° ·‡x¯°]LÄ‚44œã´“£fYɉѢ<(ÆÏ»ÀC„Ĩ¿ý;R׆*õ °°V÷ñô�º|à¶qõÖ˜•…2–�<…‚T“.X—ÔUõm@qÊF˜BÐÞ`Ê÷C à²ÚD!ÕÌD÷ûÛ·ä¬H¦n0¯¦ª+ùlzSú�:ć–‘v¢FËl\ò¼cØ­.z‚¼_¾¬cÿ}BNQÉŽÂú6ÜÀޤÏh@ˆJx–JÊŽ‘bÛ„%µ”d`G QŽälI¤*°îý¼ø V oÿàS\g6Ï \¼Í:/�,w0k:ܨc¤2“êèB®[r—]RykÑô)ØõW•Åc9Šåó9|4ª›ÀgvÜÀKEö›ççÂævµz¤›ñzù²ª¶u‚vÂ,r—qÈÉñ?|ü{}¬éqä—j¬s'™vH’ ù�Q3äà‹Àür§ðø wÜkx§°1Ó! h¨Õ© r1ÅŠ»ËVþä»<Ù¤´`]Þ›£Ù“÷“@ÍÉê7Ɯؓrªx1‹qB–nR WºÉÓBç¥!yÙú„¾·%â^}VM[¦å}06¸þ@ÕÃ;ì :ËÝ4)îFü²»ËªõÑ?`%*�ÎR;¼AE==jœÅ¢\_튤РØå×j ÝER ØJâñ^àž#¥ôO•7Å•üåÆäM묡x™Î­&#÷ Gˆ¸=#ì>&Az:5š_t‚v2ýa!:g`Bwr)!Udâmæ°Û”V"…ŒÇ6Âô±…ÇwÓî«m)Ö,}’pÌ?z3R½¨"š¢I�z³|è„B2¸F‚^Å:òòy{LI³Ÿð2¼)c9ŸÑ‰²‘š9„„Eþé ë®ÅÏ•êÚƒ>m©,N{œ2à«aÖ2iKÃðqÏ�«HaŽÁ÷’ õØx*~EɶÔö䜹 úûArêV�Œïtø`ÙLÈ*|.î\̱MŒýÈê÷c}_S¸²rž™BW�o§j¦÷*\!»5Ù†Y¥�L€³YÐäâì²òézÁse~vÜp'éø¶…zÊÿ‹2¬·°MøQη4hÒÑ–}è›gÂíÇb:JÏLÔ�múMÄÛd†—©ÏÆø1l�¤}�¬Ý%(¼tU–_ddm?²jÚ‚ä5�ØáhZDf%wã\°]¥ÆYà-2ËEÇ‚s#ÒÈ1új˜³q0Ýúj—�-AV-õ�dë~ϨøRœþg=��“ž¢ôØ)'‘ 5ß’¯6IhHà„ Åê™sÎPà°Ü=JÄ`N¦Ú­UH�ÛŸÆ.ü£¡÷]¯À*reûÔ š¶ƒ�(ÖüEs¡Žìësö•HÌ ‰=#~ZÅ@¸‡†Mä ŒÔéiѼß§šW"›ÐìBÞöµ�jˆœàD Bæ ñ…<(¶°ƒµ9ý$*3È{>ÿ8€Í6ÍB«›&©¯›')è_}åC0¾ÿ7ªáQIò^ÄNÛ¼˜pZÚ}\ÝNØF’Øû½ûZ�û„b ‘ø€ËK�4¸2X––ro;A”˜7Ǭª +s >(ôÍÄ‹ÌÐï­*¾cQŸV¨�œu´%Oq« èC^�ªÂf GûÕV_[Ï{üYıÒÇ‹ÿçxÆ«hù‚ß¾8ÍàâÝù':ŒUd®<ÖÝ‘Às¸ ý¾=È/¡­â «ë1S±aÍ!(²ûÏ„ÈîE%¥²ýSåû%O÷‘gÌãÁ9ÌCÜê%Q¥»º&XµB­4$m©g–9q*ÜyŽ]éäñKpЃ _vŒ ¬ÙZpÌÃ{ò*{ðʺ‘Ñ̵{¬÷åuØ8‰¸ÂAÔíUïødÉrpÛ©¬v_ãf‡Æ�„’ÎÚ×þî·‹‰ì„µ+¬ó—Z"T�w¹¨3Ôÿè_IÓ¦ío¶›Ex³Ù}AYd;©\{Ù0“ó6ÈH¯ÿ-Qr0ϯ\^OÄ|z‰™7A3gè=:±È£BÉ|ÅX?rR?m-v3¤Tâ?ñfD;}\G`×w—»Ô·šÏÆòñy{™ÖLüuL²½à'µ2,òeŸ…·d´NÎdwªBG€-ÜQ’Ö5ô”m‰�• h“ܱ&'bæaÎæB‹ÒiÈÆ›ýÓ&AÓ%Ø–l£æX‹†©ÔacbË,l‚ÀӜ୅×äüsÚ°èÿ/õD€¡eOä*UqÆ·V£Úb(ôá+�¶­^éK«y r5]î”óŽŠpB\ì Û†Yêäè1ÜrÌ„i§a�ØóUiGÚß3�‹)vÕh#¢¿ º/7”°ÂÁxÞhM¬ýŠpÃåãeº×Âà“Š"1G4a¯¹©6×âË PëÝØ|(�Ï“ßX3\Ø‘~°pŽ<Ì5fáL(?YÒàe¤úÿŠ=ó"ŒŒÑmzp[RBQe DgñÌÊÁÅ­“ÆÖ¡d³Sg…„Ãv=û‰¥&ýüé3Qà.N)uý�âsO/Ž|:WS+# miýUà±k½'o¾ù#àßöÐyl ܈¶oÕTÍò1íί%\ È/ R¥›¥~î�q|&ÈrÉIªóšQs”]Î%¯7mú�n@7&}˜çŠo¶`Èï#¯�_¤N¤71ßT8 ‡ç§ñj¡ WÒ$©È€_¦ x„>ädZ]ÑB²ð4°†Šºþ;hØAWVÚÜOq4$Êš3¶,7�Éy3êÁˆ©N¨KÔeùÂâó\«©ß¯÷Wæ.Ò ©ól O!àïǧrz& 0Z‚cyó@}K³q’­By0rJ«r?¹¯4Ýácgƒö±¶ØmÖëQÊt>\{B…Àö°7‡â¸V 9üv ÒÐeÇK~LH-‡ZêúÖ~”gµ–1i÷S%ï»óÙ�$Ð]ú˜(<Æ-gbVp™ŠZQx ¿îÅC!0~‹­C™m9ÂÖ¾âÔÍÁi´´Ž£æ�<(ùÅßcÔ „ÛŸå‚Éý·°]ÖDm` 2¦ ¿O“GÀ x¤£K÷§@>â¡¥'žš¡½Ãé; Žq¥D®|ä¡÷w$Jáï�¤ÈfÙÿ% h?T°—›Hë”aGÍE3Ê´/)§UbÄ{f%PgÏwÞžFðQûÍ8y“ék¬Æ¸/Ä?›º,ý§^$¾‚ÁzP@¦æÑ=Ò¼ý}2£¨àjµš�•[¨þ\Þù(¿h�á"+= ñà°žï›’7…äT'J­ÃÙ ©óáwDµñ=“¤Çžž—¦ uH2í't4Ç|-*×�Ír ð©Û³=,QÁøO„:Zæa¹A­Hø'Ðÿ¢¬ÊËKôZ�¢°3ýpUÃcdáaÓ³œ$€2å `­Æÿh»=ý—•aû¬!?¨×û€ÐiM;;ëêiœ5U1Yó¿b­å„b<ÙÂy‹ƒ¶Žeq0b¸àAƒíÛÔ©Á ¹èË%�uHââ¿oöj7^<p™!¾Œ`æ<æó¼(X^”)©‡³û O�«é[¿Õlƒ“¦ÂÀ&gwJÎõ†Ž…¬D8CÃ%¿H ÷aaÓnðgéTH7¨H%hføøÕG«¡-˜‰HÓm25{ijl—*]h†=ù9ŽêŸÛ¼æ<ÝœÒOÚ¥•­e=‘�·H`ä«Q2ˆÐ�W‚'þäÎï÷Êû KO‰2†ï&Ý�°Žç¬DLþ¶”AÆÕÓ³Qg¢d„³•N¾¯™Ÿ°Óy«ùÊúÓâVE\™ˆË#ðW‰ÔñWÄ/ûÊ ’\™ÓV•Ù*‹¤v*Œ¥uòÏ ¥¯Jªb‹Îݽûú{6v`¹þØìUFüˆ (ë“ØZÚe\åÁq¥ýª•9¬puž‡¥^ÂcvŽÓºÒW͘Éϸõ}uÂ’óy1V©dí‡'+ãÉh_s ¢€&έØl®�§ì2/^&¹5� n5(²¨Ù“ oÚ31êà9…?3•p\ö3 §é6„g„È€i ™æ52 :€>Qâ3SqÜÂJV¡U_çÕtFh•"¬‹W†eÛGKßí?ç1‹ø9…˜ôØRw6¨ßxù(£¤‘©ñ9«&e$ N¬{›5–«¯õXgS8Ùy«8k®뛌‹Ê:‰Ý׿NE©êfî‚VÚžXª¸0Á@¤SF<ðo„™SMnûÇDå€-ŽŸmêt ÖpÀ(‚;”`d,D€Ü9åúYŠ5|kOw¸=㇉D¬Èg5�G§÷s»@À"ôs}X)˜×Þ´ÙÄðÀÏH#M,¥)Û~„ïÎݦ}nYà‘b¯›cƒfI¬ÊÃ4•ì�!Äaëg‘¨Í‹¨ÏX@×Dÿ®|89l"OaýŠ®ñ©|™Ú¼'ø²¯$”«ïÓµ¶£�¾ëë{×iÂ5sºÎ¶Þ•qʆÖýÒÑ„ùr�ÁY,’È)w¡À³” ªÔÈV¨|0‹[æ×öë‰Üßr…?Rx/¶½i¸d}öœ×W¼ PÆìe>˜¾ÎG(eô�r@ŸÇsž#T™àѯQÏäOm>Ú›àbÉ2¾S«´éDv¹õ±Ôöº�nDýÿ, ÞðKŸ…MÚ9A Ñ$ä-ÄFƒNŸ€„MWìgqM? «ñ0È³ÖžÛ”Ž öžÓ�ZðÒazJ·§¦‚lÝW|œ¬w”]tå÷|´²Ç^·6o�xßigìÉ1ßð õÒU„ôæ|þ¤OœZ7@ÃùìØ›¥4 êP:ø–´‰3³c‰ EIÝô�ê°ÓV6¡6â¼õ®8àþ—@��»ï, ¾Ë íJ´_H4#Ö‡Y`Гëذ¸dóˆ„ÿ¡£ƒïmñ‚-°„JUM ü²¨Éis�E˜9þ–ØUa“XL}×@q?ëÜì#—ðgìv”£»•ÆØœ<áV0û±¼Ú% ‘Ä‹³„Û‚VJE†b;ëK«`Ѐ‚0}vaÀŽ.Œ �Rç ˦ÀÂb‰Á²º÷ªÔ9Ž›þW8i3Ûªë#»'rÿUfl‹?¼|š/œø#ÓXàd–á:¸lA(HÏ¡lŒ®Kɯ|ýa¶zØ“¾è›”¼hG6F11vv�Ó×ÌãFDª˜ò̱$7´3¥ä’Ý2 ¢KDÕ"[‡v7QÓðñKå‚·ìõ�™C�÷Éw¥ˆî’“‹¢n¨—Ž/¹¼PX@Ã×@I'ÙÕÃŒ�\'á]JZ±`³úÑ,Bµ«$ƒ^”æ´§ 7ëög б±ã1Çž ùÝ<§'fþZ®SÌ®N)äëù:^÷““Pð±$³yÁ°îëÞÚýàºÄ‚—^(wYÎü/Bòãî<ÿWK°5b ßÚJŒe‘Š2Ó¿ AŠŽQsp¬;�õÜ S;å°Ÿ5»Å‘,fA›.WååÎ�/Ë›e%—ð_p×Gm¹(õUOU³§ËRùõ‹vûǤu…ü©‹Â-ˆŸPLàf™„'È_ÐiÔÔ¢øjCA¯h½n-��ÀÞ¤ŠáºÃé€Ê11ÁX²{å-aA¬X’'È`û•î™kZ…†^NŠ0„±a †’½%»¯}Ù)%ãð“ìS¸Œ»ÞiäqŸÃÈëe¼—#qZ€£±Yеæ~·ÆJ€šZª~�¶ë6bÊ)ßü�Ãÿ8ÔJ�Ûž$§ÏN>YYIf®U>n˜Çt5uý€iÄåÓ}Ñ&†Ë/ªÂ˜ã±r:÷fNI’ñïÆf2ý ž"”¾ëÌ£Ý'T)ÄÕ×í/†�J¡û¥òð4g�ïÁÎÓO½Zþ8,|ÝŒo óSÆ@*$BWrU<*К(XJzÒ¨ -U粟[Ûã6®,ïŒÌ“Â!žì0Ál¤Ñ™ðCÉmº–ðßkß“¡â„®0ª>„0JDPÞÞ7ÉÀfj¢íÛËw–âç äÈKÂSÍw9ä9H‚J¡�]—¸pé—½Ï$¹ÑhkÊÇg`³.v׬„§¤ ª›y¹O¨/Œ Vú‘-ðÔ„ˆË0û  Iê?d<>N�ò#;Þ¢&®ÒÀï V—ø^W–Ûî`qÀŸ$‚´¨¾pŒK?cý „–¢ù—‹iDð˜0ªzHÁp00‘ÿǵ¢ÎÞ\û'í;Í‹zÙÎQW¤ò»œ™#|!t&‰E}Æ4Iï/0:¯î­Û�}ˆM.¯¾Ýw*‚³PÛ˜ÚÄ×À¨Q¢ñï�ªîqz/Ê`3Æ&àß$¾äŽWG�³-MÙÖ¸†= åmê*H·VlôÏZâH{PWý0±¾ ~f3aÿîó°Y€æÈá›ÂÉRÚÃ)Â�¾åi¡j~Ö›ZdtäáM–ìêŒ{½àÉüŒLJýÅ/¹ȹ�cfK¡Ÿ{íàÿÌ9ØHm—ª@3‡Èi~:ž³G¼ª /Ñv>âf©HbXUÃФjì¿Q>o£Þßt‰œ†|9ûkÃF8Â.]’e m½£ºþ|¶[šÄË&< âÜÐEŸVƒ^Š!¹¨×úö’ù½ÚéÎ1ÌÒ9 N‹v�·t`šK“sÜ9C:‰3uÍlû cNl¯·@Ÿu)³¯«®[ÿÛ(öf·™b â¬CÕêºcá_â©ØbûìEÑGæ*�³�­ÈÅ鱿³UÒÝãÄvŒa@jNwnÚB<Îðè_œz'™¦F³#.M_³µË<*Rë¥ä©aàN¸[½‡‚‡0W?×2ꦢü]ñocð´¢¼ìK¤š4Ž&ò¸Š«mŒ¤$Ÿjâ75aÞ\%éþ–ü{XÙŽ8)Ö„÷^=5 ‘WcCþ2EÉVmg÷¦[Ї02áÒk—-F=‹!ÎÆ xyüìì �4©‡ÑœkôÒ–+'šþòëÞ¾i$XÑšY/~W¹ÈŽÒÚ.ÙŒõKAÀèO¯f»ŒzÚ°3øÁ,ÚN[ŸåŸ&`ƒ»¡Ç5…Ì*Ef?1LàÏà`8†=²çbiàø­w¯ÂO«4 /êvý)T&\ôm~Sß(x³;'ç>`qÛT�È�ÎZcÒ¨²E„1MÂý½×¹cà1À»×’Åd°kÄ·FléÞX\Þb™T¬@*ÿ·6=BÖÓÈ«"º”‰U™è\ZÂÁx´%Q™ë×°‹Þ0å~úaÔ ‚A¿ªÆÉ’Ì ðÊìà½~|g%±VÓ0lð89²®-$ÿ©Öq¶¦&@NcˆÞa�ÊtfêÂämÜ^žýÛ¶*mº,»²�hÆ<4ù-Ð{$]ÉÂX†ðM~jYJ±ï‘“~ õ2Ÿ„—˜¦—È[èã.j÷Â1@MsýÅŬ*Ú«Fhˆý¾¿)lv³c0>Ïq}¾.QA[­`#ì¨È´¯àå0uÿŽš&<Èß- }x“ê…á¯ÆwPc8ÈU¦¸UÇUàÇ�•<&µç�d¬J–ÁæˆÆqâ|ké3HAï`²ŽíÂx-W/blT£ÿ›Š(4É×›/þÛ1Æ!,®ÿí¥×ËEŠ#$öWB+ž^žAtø~¸˜³ÚG.%Ó[z{;´õnGH€B‘Ø$“$„WÅz±O…^Ì´„&û\�(Å ¶ö±ûÎq»Š@ä¿—&Ú'1a¼ù͒у.®�ÖTÈÁ]š=cüTÿ@®àx_s�ïçÏg'6äó É5’R-û‹˜wYšÕJò<1¢C¼TÌ/ ÿ^¹�sÍœX!Ó½¨á%v7f쎫ó KÁ‘*}°çEZ4 v±å»P^Д'°"Ê$hG–(bw¼§§Öv_ûÁvH�1¸§:!–îmûæï R•‡ãxH”^˜)7j£u$!Gc)Ñ€-H½¼Ý'D xJ ðMéwÒ¯`öô� /Ãó ‹Å•³Íå<„ˆÉ2¶ðÂ28å¼à9ˆÌ"êGÝZ7vMrƒ²ªq˜Óåpùtê”w—Æ1/_›þß?/_Ãwÿ»AM9Ë!MöÙkr²Z�IÛÇn�]?Á€BÁP5f»…{ç©>©fÍòî‘Ú|‚¥®;yœ¥ Ü�:Š"ÁjNÒžr>Þ¿K^Ød_LÝŽ¹·¢¥s˜¼¥l|Bù2™ŽRs(c)y Êý¡Ð>ÚH ^�Uœõg^Ã,‘cÎjtm]VÆÊ”e§¡I‰®bR÷à#v—åQмnýö¢¸:¢Ô=Ž�õrï<Öˆ6tMŠ3›î»^ê¢(Ö÷�0# Þ•e&ð°ÉTŽïìiõ§á±AòòIðê²�Ëa|´Q®­¤âö’È–>öÁ¨þP~Lj+6Àd{$R ”^Îr,?Â-=âä»ëÃb[U µúÒ-Îçg’[5£�-Þ,¸vÓAá°<á4Åu*ÊÛÈ7Ô/ÝCbccHâ® ­U„´6Õ{ Æ�&.TTÇXÁN½½,b©× Ê&×Q B1Ö–Ne ÎùÍSTÎãÎ¥“Ä¥fº»Ð;&5[U¥õz{`cƒ‡>57Î�”¬)×fŠb �,uaÛ?CðØ�ÞàÆŽÈÈ«Ãýd‹Ø¨ïªX”ÁhCøF~®®¶T“R8:ˆ� ˆŠAo±Œ`ž†™W%.aˆÝxUÓ¸J-O³6ýyi¢1Œ¥¡­©\¼VN+M5œR/`]_­…L…S+Ö¹^Eï§:ºsãsðIªf4$½îéì*cܱèÎ/P¯ÎBê5•E™Î_‰Ä½ÀaêùæÖæð™<‹{‚УèÇ ¡{'Yû—²~ÏMp|•�陎>øº¶(µ”âx-áN¬k ˆà¾5�-ÔŽ<5«Ài S ”¨ŽR ÒWõ«;Y†8±ƒÚü¶Ý…¯‰v9ô©MoV%�SãàJžT§S÷°‡ ¢EǦ8e\j!�Ê!“í}ND~›ê2¹`1^ÚJ;I.VÇ’)ÕY‘'6‚ »YÓ¨Ž�³ Á›º÷ÕhHˆqœ©ÈŽa_ ÐBjzZ-Aisµ,/4µuò�×ü³{.¼Š×ExµÑò«›D!�ä$3Lò–[D=‰ç)ï5)´‹0váÝ=ûdgNŽhÕÖ‡b»›ºO@¼ÓZ�,AâÈy8פf%»‰ [\ŽõŠ\å·x›½;PúÂŒwa¾e:Øp7X H¯V¬jôåµöS¨»–Ú7½Zè}»!fDuT Þ,fà7”¡%‘·ÃOl-ºn}ÕÖç¢!ü8ª“,ܰ\Ê´ <üÀ£ êXsðÅ^`Íû�Ö¥'Ý×®•ƒ—êP2Õ /õ…²kjÔá w/’Bã7ìîn‹6K±Šœ“³5­ÅɃé¹gRýª:ø~RJ_¡ëçZè¿�šN-�©¼{ô©*C é~-е_ ¾D�çðpñ“"xò@´–|iTøæí«UÔSšº�=¬‹æÄH™²‰t`VÆ^ä}úØ'ÂP+xžÛ^Z�MM*V‹³0 v°çw=:\ ÿí³ŒÂ)ç/†%É™mšÇ ß½Ó®Õqa°Èá#�i]p yè3¹ž‰Z…‘ñ1 vpbß`‡î¬M¾ºañ(ƒHÞ;±'ä•2[}âºÜ¿x7¨÷ãË£.+"™L:r=k]ÔKÈ +ËQo¯:¦´Ë)’Q¿mÈS¸ Ñµ—öù² ²`µ+àØfe 1oækéPODQÁ„òµâ,ê²U­ I#. H„aÓq+×OìØTé-0ÂâÚé V�Ç•h:a¬>Q�FôNïâ_NV¿dWã;7ýøãˆfGÁqû ô4ºÏJx¯HÎ>}~Öû$¾ïöN_ÛäE¬í€àÉ ¢¢êD>€žô®.ÏÑ‹]â�žÌâ�ŠºÆ�õy”®`€ç. Ê`6¤°^¾ ¯tf!ò£ ¿Ãç­Ù@¶$rÈXR¥Cy(g{õÖ¤œÒ¹©í›ÒV[g[¤¨ž³Ü�>YqDþqË<ù)SÚ‘‚¯&Ã4 <äà.ÃÙSÃ/EGÏüœÎ¦ j¯‹Œ÷e’AW£AUZ�e±)³‡nÊK—Á‚Eãé Mæ��ê<XT´7¶�¼èž2J”úæi.ï:B?B¤©™©¥_®j”ñõû\ØãžÁdrb¼É"¸æ3:ò(LËi7€ ë/Á'ÿ¢¶Pöy(a�¥‹è(8ø¸}~yÌ�íÿÜ*ÙälŒ”_FO9Ù\®)» 3"ÐÒyŽ&£oäÉkg¤(@(úTøèÀ¥CÞ�¨~êúÂ=y[ª?–Üs gzÏ6àµÊõ¼¦4S¥fqLKOš+C™èI}LÒeÎ4§�†ÞΦX9.F"ˆvï0‹h×ó¦l?`Ø?/Ý€J‡\NFó tŸP$E�£‚Ioãçª�{„Ã�Gý)¨¥² ·Á}“Õ}ÉF€�\îÃ*Þ6Ë©©œ UvÈt<7€éšFð íï8Ì`D·¿ˆ“<ÑI6ñ òš·0ùí6fñ@Cj™€±gs´Œ¼ŠëZÏ*:áìÞ½LŒn÷ò¾,OŠ«*ÝÍ÷þ?Zꌨ»RÉùbQ>7KP(›‡ûÕÀ×Uô«R20ùŸÉLµ�A€«âog¦šBéÀ†ì»›¥™Û°EØÑ¦øW“/Ñzr0?xH­#©¹Ù-?pàI0£ ^âž®Miø®£Us›¾µîã¤h'ØrRÌ!ŒåMÜ]Z÷ŠØ O¥�§ÏoìP¡Ã•×0¼--[�ÐÞœ~ðų_‹g©+[Tî{¡0ÉVË·}ô†»˜G Ee¶ý7–í ·Œ„Š”JF¬š»hFtÜ–‹¶êî!§QÎÝë/�„ü�#j­Ü°ˆ‘ Ö>ÐËÎ>\PL�¸ØÇÖêac÷e}s›„1¯”ã³5pç ÂËa«ýð£ -»KÁ…ñLå‘›³ÁÑ�]îÔf EmÌÇ¡‰¾µ%n§Æyš*‘t0{I®ûÝ¥’~™nl«‡IÅMJ¿ÍÉ+§ÎpÊ´)°Ñ.×zÄ¡#+Le nž`Àp¹ûéÏ‚k&Ãþ(ˆ�-‚vÚ^*šZ‰dÁâK§°fÐÉ.ñQ¯Öú@‡1æZjL“ů€Š¨KžÍyK›Â®46Ö+Âv¹ÚI³Ïõ€›qíQVÑÃ¥LÔ?еŠ$ý‚&Ü-·˜Pz›ã¨‚Äšº'ðÉ{ü(Z)"ØîÐ÷  4äO†£¾‘cÄõð¯ tžWÌr/÷ôGL» Šôþ«àA©GBXj?^·œ Qî(=l{Õ+Ù làÄ—²Ämq#¤µVµfª}¼øtàx§ÒG¯8G_r0XŸoKl4ÈÑ‚ü…\lÖåfpgŸPF×¢äGƒ«e¢C‘òóV{šª¬ íЕ­(í%g¡›$œÕ˜Ç$ýøÐ8’HzÉúÒ{m!ƒÏÝüY/¨r—ôÝOä$jêEøý{±¾tùÂlSº�¶"%Ù&¸]TF”IÊïx€…Ÿ„e šz½õÅl�~]0­0Fò2é�µ4Í4u•Í ÄHÃ< QsOÁèô™®â�ëI&ŸÓQèÙæ–l""Çn¤FN¦” @e8ƒHrTï�ò#F$°¸Æ+DüÅ-"Äl§!{ËGÂÂækPåz‡ì8[Òiéî‚¢œÉ¨)-«ÑÖ|Üõ½Böµ¿Ó¼ƒô.ã[)ÿµ¨³§…üo±Ë¶9®ó,ãØ?¿†�‰bT—Οªò °GÌûÅ�gi«E;Çüu@f’‚—P6ÓC÷bbå÷s£QduWJ–³]›¸‹6hWTȱÇþGsï\!øÒ츫„qâ¢|Œ‘Ôþ¬/tç¹ä°(AĨ@ºpUÃÅ!­ÁÀ«A®"” ›-zÆ EjÔÙÕa× ùy®þ¿öU Œ½+žîP~Gótï`åš”v_åÑ©PjW"X=ÜQbvÈuº½�"hŸ‚£]ÅÁ›yËÉÁSä¿™¦Œõåf�TGMo„ÿKxcÔÀŒäŠ÷¼.<ÙDÇ(è²$ÙòÿžsSKQÚ2í*¦í#ËGëï¬Ë/ó7gƒÚÅêõÿÊLŸ\µ �q=“ÁÇÒÉÈ_ Š,¤;iþ«Þ‰m²dGúl †�ò#¹_°b~Ë(•øP½‚|pÒ‰t£CíFÀ�žñ~MšSwSÇn5Y‹™ð®Ï„ÁÐy5)Æ_‰!ްχ;FË;lïÞs¸Üà ÓUee¹n5E¿[†±Ÿ+†a©ºé±3Ó;‹D L«Å•Árì’‹ÌëU£}2.vÊåçì; [„Íú r†ƒwl°,î·3¥'î@À{ßBé5¤¸u,í¬Ö3q�êPT’V'R÷¾3y3/›½Àlý[Ê^�¬‰3Gä·3ý±¨�ŸÑ;9Ñ÷‘¶^cð­°¬´U·ÊSïk”«4€¥:Íf]l¸G;$ÝðRý¥Ovt;¼×É»á’{&mÑU¤Ö"OLYSðØ³ž&hçÆÇüVÅ¥r4Yx]7¯­H ,)„ç ï—�=£ooÖ}ðZ…ûûz–¾²bPñÀâé¶HÞe)ùlª„{+´¥ž�ys¤ rje~µ¤Zð²K%Ýõ½‘ñb#!L&ÀÌ�¢3ÓâŸÉóAcqûIÏ>qç¿É-2ÂhßuB²àf¡)}>mµW>°] ¾û¤øxýy¯�iúÙ‘~¸(ÒãñŒªÅ ¬y¹aï 7ÿ<€awöë ö Måh‚f†Š÷ýqm®–µí¼ ÓµdsüfC>æ˜Ãgª³å æE‘&ú�D]HMmo ŸÄè#ë­|êŸdVŸO*Þ÷½rlýfK“çv«EÐÞòg<¼Ë1´¤Å‡��å =£ÅÉ™À¼Ë‡×I½%k6@±ï2…WuÜ¢~†¾«¦Gœ½UG\°po6gÈh´Î„ìå8õ ,´…$VçÀñû+/¦0nM¿íî‡$Ú{žEÐÛaxfPPwqJp´}JÁp‹z¶ÿ€ÐŽDüùO‹É–Ñ*@IÆ å±)> Å<àH‡á~ä´óf�pßòÒ•C!%|·ÑQIm`žsˆ°Ê{öaÌÒŒòÎ>¢ªˆáŒžó"h}¹6áòÚÑv¡~4k«¯°l×\¢Z6¬9ÙŽ”8V*Hçó@סèmÉ4\y?ÑüÉ…BF#°VÅ_ë2’A´ˆÇ%ã#Ђ�^@�ã %À’`¯eéÐÝ_ë­ú¾�{Ѩsêx²‰”Ë#$.%TW¹‹ö@Ž?YЄwÔ‰<-µÎ‡"JûŽ@ÅšéSFÁ9#K~صø†øgÛ =$ulšµ4m7BMOíP�ÐFx'©üžcHN ÏGu*O8–Æ0 {„A™Î�¹ÑÀöýžOÕÆKܾÀz|ñùµ5·PÔÜÏ ó tÝÁ§6�”šMþaDGÇŒDÅxZ•0•Ì�ø£µAÔzk@PÜ.Þ]Âó›þ§FÞ¼D±apþ¶Ÿö˜€ðf0þ]##ç­$!ëÃR׫@Õ/“îáj¸bi¬Hµm²Tú µ†“r¢–�¨. Þz<8Ã\Ž´9‘X¸·ö§)A¨Ð�U½Ä~j¶pTÑÌAò–pvùÐD ;‘½g‹!.yDk V†½òc¹CßžÀç†[y"×îR€$ŸÜù>þ!2N)¼­¦æƒW³¡o$¸x14ƒ©5…ŸÐ¨û†þ}`�õ:ï¢�è} âöËEûŽ÷´?±-JU°ƒSšö9q/IÍòJUn�À^E›Éᛪ¸Éæ³ ÕPТq)ÃËnž›–�, ‘�tá˜ëÛ¸½‹=’LŸ­%,NO‘¹ºˆê�{šVêM?zÞüaf­‡º"宜L%BtÐ&1È»Mâ/Õ/ë‚ Ç�6)Â_ÞòjEV Vî™øÂ/‚ºVQÀa­);™¨¤7fÆ·Ù�“èîŒ^_uõxÌæ=.̽7êQ× â6Í;uH_{.²÷¦ýäë½ŽÄæ)uã‰áï¹Z¹§±ív %>Û(¼¨;øMó*,�ÄDбSüÅ€º“ë+ødDžYàšû÷#ñ'ZGÍ:UAº—5[:§wTìOgÌ\á€'Aº=ô@ßíi�«Ã•V_vå‡Ã›ø¹aLÎÀÍÔ9ªF=Œ÷Rnˆ½ òhÅŽ:¦k6�R3/ G° FQï+ŠOâÉØº' SU­V´¨“:DÕ½_}�…‘æNÃ6  ”q­²Æ³íÔe*úÇHørž€ºI’YÅiÉÁíÕu’¼b5û#‚”‹ª,×<9¼©¬¤†[ô4>ê9Å©dñÌãC–8«øµMøtŸ÷TFi“ò/•B¹}[°Á·Õf ðÝwÕ¼BØé´®ê‰ú9»Ø&+­œôŸÚ”¶�™ã÷J7Èf{'<öeR#Ù�±¬¡Y‹‹]t°ÂÆb,Ôƒ–¨k‘ÌÝF�¥íXºX�‹ÃróZÃç"z+"±û. õ70DsàYµððoF;‡_Ñ 2²l5ÂÉù'€ûƒ61†ú/8 ™âq’ãêÚO†,éë'å3†�‘¡¥.2£TSøTñœi÷¿Ðÿp˜p=;NàñP‹N%ð¯Û¤µ]»!‡jñ­×![Ô–ù±`Xnžâ-m�æ~¾ð8µ¨¤NÓ6ªB1õÍS/r:ŸE¢9LÞÑÅÚ|˜=¡uOáD$ð¯ÕеV´f…¿Nœqû•ªí±S=7—HO�»D}ØûSUÙWx˜æ�à~í ÌŽ˜Jýè³Já¹ã_*2 &àÏ�ͶGTÓ�¨ªÑÐ'ý ±ŸÇ“² e>@v2®Ì™ú‡d'¥˜^S"|åO¬¹üw9”ÚŠÿ "R�abûÏópá¦èÔ±T{2�@DE¾ØcÀ_¥�Ö䃹¾Ç »Þ(¬'5•œFôN|þ^›ßNnÕƒõ;P”fÎÀ©©kzfÆXqí�Ü(Eh…»aó9šú5š?TyÍ*øšÕ?I¬þ|ÚùÝ[Õ’¶±,Çp¯kÙÉ/õ€’²äZ¦n`?ÈωU­Çiþ׌ßö?j¤Û�_<øÌ€ð­¬½jKë¢R£…kùR­LTeGÙêºÈ“ëÑ�‚ëô(EDÇj‰%c‘ ´åXÙppÖ©n%àêîPý/ªn ÑM Az.àŠXÀó!.¤*•™âk‚¶rv _n?û™¼£«QIZœ’œtŠN­w©ß I¬04“~2–¬@kzHôÈ3Ë«PT››ÖñöœÜ)CøájùJQFS­xw«²Û ',w ´í¬Lõ¢Î–Ê¡£8v„ûõÛuÔøšpþŸ…Éè H¼<³ˆ¼”’[—ØWîÃÉÎ¥%“¼…�þìËáŠcûÅ”›†PBƒw.�" éi¹æÇjÉy)-žî 𰃲=Êùk²–yúÕöÕ‘˜ƒ(ÑÆ�Ôf—ækýÀàሃQ¶£ÌÚAÍCw™²¡g”hBaР–­ˆ‡ývälÕƒüÿlUo¨ÔzXe¹½Ç!b‚ ƃåðÛ‘Y;â>ZÛ™Û±(„ñê�¬²`J.W¸NeRg8I¯®p/Ãcâ°œö^©ñIÏ�ÛÇWnqÂ`}&°œ1M…”îŠ2›ê½ür)÷3v¹¼×L+PMz€"?y;¦jR ¼nq'P Æ$Û–>KDÑ ½®l†�P†÷ ’•ö^5cÀ×Fj"BaÈqž­ .A ÝM Æê‹¨ÅWýx¼«‹ Rfžù,’ì…‚µíoÔY8Õ §";žãµ·hÅ“ªàIy“"íæmŒæFÀ†Ú@ Ø…4=šê!B�ÒŠª»+3‡aÙ¨<�€BY^§ØaÕI0³Eä�£³W õGëûÙ€À�R+ÔeÍÏ._1È î”™"(³3€ý@¢�Êc/m“ÞÚG_ëáfÄÃT·w–LnÁÊ÷žq ±ž*ÇAs¹KðL>ûN�ßô®  ØwÂuƧÌé—Ó°&µ.`J*ѵ¬HÇÜ„ºZ ¬ÌSjåÔ W2§Pw˜«÷ÒU)ZØ^ D{ *Þ3#“1°L¦Xw_š-±|iòîù3<õšT ¿ _Â;Ú!è�”GÌæ#­¹>Ö³1;Fñ¾E‚X8¼a¬bÇò¹7ò ¹R½ )h ÷<Ç~*bŽS£LËà pÖÏ�z=ÙD1Ñ\÷Ü&°ÆØM(j©öK•ùzâC:A‘\1 ù Ûôæ8ã/¿ÆlÁ{°U�®Ã éB0’¸Õ¿5$€6ˆQ7êrÎ>ïúã�47–"ûëŒêa¥ßd~m1¸˜Æ—N§$£Óß�n^Ú0Ìêno¡ó˹­Èd­@:lêœÛ"FWÔïù'à€>a3Ô‹hQÁs¥èNU Fðà¶fµÌçkÓDçÆÕÛáOé—¶”„æÅ&A„EñäUàÆ‹X?½kf¤Ëwðiig«Ï+'“7ú«ÙWÿrsópÎ"¸ÛÆv�KŠ•×od 8-Žå!оY9jHʼn‹@)Kôƒã¡?>¶~Æ“ˆâ¡ÃG²óÝÉ8Ê>Ú9qþ×߇Q¦0à|o‰ƒ!ANXÄ“afœB|€œpeÊ›g±‰:V{ÜdÓËwˆ»„Èu™šS¶�yf·®P�«Ïåä4 BYµÕòùb—=˜ÛŸ/OØ*Ì�¿`_²Ûç[ñ‹Rñt¶¿†±J˜¶8 P±�“Í8»Œ{�¾�bPD£Lšú¹¡_NQ¨HÐ@Ç«\¡|—ÒåtްS¤ =1jŸYVoÞ±¨f/â¤Þ<˜¶ÖÎ^®X¡‰•€gE²N4%:+c²@Ç߈ç?(pC¤æ²ü2zŽdj¼§æI~>/½Ã3ÿH`r+¼;¯ Ö¹¿Õ×+¢È}jÙ&¤=öd}’0lK×-Uhê÷/!Ì¡$�ŠLüX¼õbgiÀá'ûô³A8)ƒ`MtEåjÕtnÞü=×›LTÖó0£³1tý6¨¯ÈÀëûqô2°…O¼¨i}ì¶à` <À@¹¿4k¨:\b0jZ†|§å&rnò+cp婜eNüõ±L )ºôÀ@®°AþfÊlïƈ,Ý*‚¾QZ�¸�)qÇËñÕ<f!a�~P8¥žÍ¬¸9*àâÇÂî@)ÇÑÇ%� –…0á(>™ ¼¥ÎÔî—H ð´kšÉk_¨]C¶û:–Z‡�TÓ ì-ì¨Þ–rÃ/ÂOønÓ×ÜàL ãŸÈìy¸ŒQ´¦y5w¬0’ð±\@6ö–²vLIñpeÊűъßõš„5Ö®»ÈŠÐ[+ ?ŽAýp/"¥z¬ºÞXÿ®T¶¬E—Êë-yƒ« éÈ~^÷jc–Œek A=Ï;’_µ»í²Q¾š§v)>ØSÓ]› ìD‚�C~²ïÖèTꌺÉßç¨ù+%hV•,?“õ«6u¦¡‹_¿Ðeo,?YŠ|xîøü®ë|a«‡8Ã÷C(d„‘À«øˆÏ ÉAze/> £ÐÄBŽsocν~!^ßã‚7*Ïžù¢¿rý‰;¼…¸¢œªï†#„ïT}ÅóYþ–3mt‚†ýx=!rÃÝ¢L‹„y.Õ@l›¡'�X9n7ábnï<Þ÷"go´-&ò²x¢Ýò*ù«ÿaäRÒÚ7÷5ŠG"d$äîÚÝ©*±:«z3T=cRàœ¶�;æØ ônTוõ)2 ž%�Ÿ-6K¯«®O±I"§-˜^ðêÆî<’I’·ÕScEwzÆ^g•@±‘#_Cõ$Öq÷sÁ·ðžå $�ÛXû A¯ûýhû´$¼†+W.î.™!Réz%W”답É-~Ì8¸É¬0Î ÷®•mtl@ʺÃOùŠ ¼åMTUÜ’°ˆõæì+�I#¤<);ÛÔbíxÌ$¢—,8^G¤›Êsâ­ìT5?µYçÒ #Uƨùðcƒg”Ë©ÑÔ0M‰ÛHÞ¦ò‘<é=®‰TÃàêDCÐ8­“³ãÌKE ˆí°–@'5f ]VêåÓ)5Ë. Y3%ƒO~ð'¤Ø+BOÀüdM€ãOtÇ�µ¿Ä®=PÏ!°y04~ž bÌ‘“°(ƒ8Gò6»0AÕÍ%ß8ÑjûKbt}þP,W¹ºP¯|he»¹«†­¹ýöUCbU†´föL»Í¬Hßéè˜ÿâªÛWí�9žð¢ò)ž‰:m‹ó2s¤às‹dÐ`›~ªÖx²Ÿ  AW†~äVÓÇ aþÇ$혥£ß.ãh¹šµ“œË¤jñÄa½5aer°‰JH�ç€OæfßÌœ¨äÊ9,¨ñùeé'ÚúõœPN–0O ü=`˜•n3i™H‘ÚÞÿW� 5ÞaÞ,ûç#6à“°3G·Lp…z᪈qV’áC£ÅUÏ¢’ÒcjœTw Jn.Í–,#ÌpzûJ­Þ§±³n›Ã×t/ÕP†ÇÄø`''ü½jƒkPX¤…K÷Z¦,ð|æ/^1€Èç§Ì(ÒréRŽm­îá²’; –pq‡ì½ÖÏû{&-Ù¶§a~B‚´Î¯4ÚôP�«ŽÓ°Eî@ì±vü_…Qb ­`ŒñzÖ`‰$\jZ8\ Þ€±Ó†S¸´i½¸bÕñßPõ©ÀUÍBh¡€háD.¦NÈL‡ö,�Çþ-Y¦ÍÍ™8Ç!v}ÜDô„ Xøîª|+¼ºë�`Hùž`®ƒóà ï‹-,Yó4›¦óÞúÙ3!É530]gäOÄ¿Õ|õ3µNAž›€1Q¯LMàJò2—É£²½£0sO(¼Õ äÁ2Bñv&%Þ"†¯�~-V²ÐéGœ?� µø(†�×úÇ KÀÕ�îèY´öƒé ñ•4h8Œ9"þ`7ÅŽ…äBž·�§™5¿; »è0€‹û,-Rt�œÝ(ÿ#iEFÿzð|ì'’,·Šw�­f·�¿òCªÖÿº•)¨‘¾›Žç#ânöPÀúG0ù¼== žuÛvx„)Ì>¨– ±'±ñîÕZ-½ë,ØGþ̵:ÀŸ%á€qˆ©¬aÀqR’9s‘H�QدNþÐ�V}^®àè¦v.<’*‰eoxÒ¦1fü *Õuu£4-õž&ÈÔä+}°L¸bÖ'×0FBÅôâgBº­�PÎ-q3\FU%Äï/zïkîuX· åj8¨î½’*…@jø x0JÞ²¾Vžø?ŽÜyÏÙ½þÍI%ÃÓÐ1÷ž#$8ܳWÆDýk)š3§öU/~—Š£„ñ†ðÒŸÝÿK0…ù$wMU_ǘ77 GÓ/«Î1“ï¥SB"9ÏÅ©@©P/ŒAE—[-%PÜiÀD¥4#_sÏ6Õ‘O¨¡Šz¦Î‡Š:ÈÅdRz%v €†»x÷…Oô €àya-%íæÙ»Áò'SA0ŒËÝ”àÙîÕÜ oLÙ ˜ýR‰¤v–³ü%"­âèZ08>f&äx–ãöÐkçÕ·òc[Œ ÎLŽP0* RF qbá9Šo´lÅ¡,%Üð)ñ´±TÖ\!T<�ÎßJ_ÒN³$‹€Fî`+Õ6ÍÊózÆÛËeÆKŸ³ÿõDuλ­neOÜ Jú’FÙÕo:ê†T™ª mQÏ㸺DÕyÓ ¿sö×Æã® ¥™ç>–ˆãü~rLSn<—YÕÊËȳFz-mïÆ„ÀI�’et3‡.øB”æ¶�ãÕÂÁÞòÞ(‡'L‘Ò2ãàÁQûöb;ïå œf˜ñæÁ Ûì9MtqowÙ#��¦íP«:~(> š¢‘1£°'¢ÅÚ�Ç hJÓ°É ä¤@�ڪȣ|¤¼Ü-§5 v�ZOkÙ³Eï•MµwÄøKÛâB½œ`\‚E<> Ž‚–ø�H$­._ø<ݦŒZɨ:ÊýLq�Êwa^Q–ÐË�zå�ÒD%�%A¡¼ ´ârûó2èw¶âÈDLcƒG)ÓžÙ’hŒXsD“�²8�h%©”ìݯòIë 88Eªº8-ÄØëŒÔYDø»�§»ë!�·<Ž]3cÿ»MHäY¶iåÜ1yW‚ò÷©ðœ¬ðâDæ×Ï–<$Àg)ö‚¸0v°÷°wY“áºì"�K¡ýËÄÒ.a=²“HñÓ²�TRŒpº+‡àßBČdž=e³t¬#–Ð ž»¤JIìg BdÈ4dÓWb*ŽT_—@¼‚‘±Š#ØNvˆÒÖ†ãìjeHU 8êçÜhë¸HÄÑ_©›]R]SÒ’d*C(Þq; ïoÍe0,Ùa™ûV9~.ÎÛ«5¥O,¨‡˜j[�³z‡Ç¿êsÍúŽh-œ23œ0ºR7!Ø¿cbŸó…s(ÃÜÕõ0³‘•{±LïéexR#ñÙŒy"©vÛšù¿NÁé” ~çBÄí­1&‹¤™7ÿúEgsd›€fânÕOƒž¥]âoéCÉlÌÿÛvždŸ6­àìö=¨Û¦ZÀú?[¾·wîR/\À¯ãj² ÂW|��ý%~NièT ŽÇ•"dsó¼l]½÷ìÞ .yÓÔ¨Z+÷GÕÞ7»šº¹¬Ýõ<¦Ä:E£`Aî>¤Ñ!Ôž]H®.!oèSr_Ó¤S+"ï8 ­ä%Ÿ¼kÌWu '¾‘Ÿ¯¸Pç÷WFœúP~ÁtáªY j�'ï„/‘fM�¯Ì¢yË¿ÅT”ÌeL›+a6þÇ~ƒ þa#21ßráß«rnÅ+§×$܉P‡j‘Ù婷~ нt�î=ròtãø�•ÝGªœ0EÒź°¥OÝ®q3o¾âT �àçr Ðï5r/&5T?Þo~ÁpÖ7×â8B19á8??ñG'p·Ì[ñ`kâ4Ó¯ï9 ` µUÉðÁ€9Î6bІ�ŠÊVÿ=¸®tÕ!ʬ‚•Q¿¿JÉüÓY(Ûê,øSñGüuÖâO²‚ñ6xT¨Ë0Y9f+¦èq!H%\Ì›…,�7(/•ÌFc°Ð‘”žùn��ñÈMµ5åWº;¿¸Ñ=û9Ç ”. ›:ížÙQ€T‚×™ ÒœLf@Ö¬eMFMbWÊÓKÚŠôø¹Ð·Äu�›ÊP.ãšÅµAzBâÀ¿3ïÈ�.£¹E¡}GL¾<BV“ùNgª…^_�Þ#D¯°�ª1ÈCõûœYPcb‡zöÐ&hÊž–¿d€EX­ÿ;‡· Šgæj'°üË9swW½ÜŒÇÓÓãgºóìg¢tHLø�2’a�‚7åÕ/5ÜHâ›óßR›`H¦úÆÇ�²í.€ö[™ó�:›¢ÇÂÐÖ«œZ_—âë¯À³¸Ú+¦ºìŸ­zKMç/N;¯Û?í—œ7åeÂÄF“V|>µî…çAAâ@ÅáÙuÜ{Ô�'£KDEÃÏt¾Ïd/øÜ¼ùù�èìÀ¤*ƒeÖß|‹€ôûYòL¼w®=ÂÁ,rt$Œ[$¨oâ²SžÂ.ÿÖ c­PlSŠ´Œ úHz›_ɸ²•Ú¿ Çñ÷¯Ó²`¾Îˆß½¬çã›ã:õ¤ã¬Ý)„’ïù). äm6ÕŠ˜sfÝc~=ú– –¹g†R·¾4¼/ù( km@wd]çVxÌö‹#pSÁâeËm|ýoN«ç@Ç È|¥¯ß.‘�æ `Óîcä?«FKèÇj‡Ë'Ž3ü£àŸcÛöBV�°°ýI(WŽ8¾3ÊSìr9N™öŠYìö5HEË {Á_l¬K7 1¿!¦Í~»ˆð7k›‹0fXÁ3§øŽèwç® q£`©söÃu�ÊZœñùž;_Ô ³VÑ:î±' Á�µÜz~}¼ì­Z[.È壘êj­Ük9¾L–àOÄ äØ>{`•ÃEoâµûP6Qyòæë¨°ÌayÙã¡ÛÑ©+NdÓ±š¬‚|©‘ž�+¿È‹Ê6C?3Ü[±ås¤th»ýxQ|ÏÙ�‰&j^i•Eª”sÆ’ >Ÿb$ˆ�Ç“N*»¼^…r†yçqmZ ü…ðæbKŽùL!l®ðöi"l­£M¯©¨pê>93øe|ô#MÙ~˜9…êñ¾uú¤7«×­|A^ëc×8ô=Y=!²VÝ=º*   ×ãÈá2šG^A³“[H],vVÞ±Žº¢%5aWùz kFS0o7|@Ù´Â¥À€N>0¥äN†ê?O÷ £ †TO)ÀÍÕ.è��¸kSaר <ý‚!ÙI�Ê*ÅH8M�¾>È"v²ãBÊ%sMh%«âà¢TÄüaR±™Q‹¿AÒ/»`q6^m0*ÛùÕßW�ñ©¥Ø(févtH»g ‰ëZÑò.‹:̹ª+°$+æq�³¨š°«3))ëºÍZãd½,7[8“ךcÜJSa 2½üÏQRðLÏþ/´ ¤$ßæi ðnŠiÕôdcg8Ø)ÉÜ;¨–àOø\HJ?åI ¨ÎFH<¥wrò´�ÉÝQIDéhßC¡¬|Ç9;-8úc²“�´¨;êvjš m&Bx)îpSÛ×�1" jä\Pìr7Ø¢ÉÉO²[.é …K¬¥›þÊ�¾î§áß<çƒ8LJÌò7&£ó/ÿc‹¾–:Ç?Å;�`‚z§3‡X©J&ëv'Ü*èz8ßóÑ }<®û-¢Œõ¶w©ÓCòè1eIÛúãĉ!/'ëÚ_…)˜>4¹ ¦ËÓëW±hn"Z¢ØwÂгÏ_Ìr&ÄMJö¹õõ/…>ìÈ�W˜?H,†…µ…‰íµþ®ñ ö I¶ V×w–ô:^ÈSÝ‹ª³„´²Œ5›SÓÛ W‡,[¢Õh3¢J½þ—­�rÁ$‚&_ûð«¬uÅx®RVv�æXc-¬Ì%âø²«`6Ššz2¦*¼a§)Öê’ù­Gž.w²" üÞ²w²ÀŽA÷HïšèA÷sE+â·é{ð6¢™x§±^§y­ÏxwÛôw"„|hH•×?¤>ó ¥þmèBûÐÚG×ã†]= rІf�ŠÕb¯Dñ™a6Ÿ“Ñ‹bßéƒzŽéŠ|ÞŰúV^ç7ý¢É«\ïé!”0ή©îÑ„Õì‰n £È$“dÞðªû³€Ñ>ã¢~\£ÿŸ2À»î bqã?²¹0gqƒ\�¤7£ÀÂ\¶9P¶.93f;³Åâ*·<äŸÙ‹”ï¡~Âa�þÒ׫„Â'òõ…ÌL«š>ÚXðüV¯ŠøA&7Û^ Ç ÉšŒr>‡�Æt™'‡©GÆó 8\ÞíîsÊ zb2¿Ê@ëc-†&”dšÖþ”õÀÜ‹L-ÑÀ±ãY5jáj¼6…£!ÍÔP¦â3sÚV_×µŠªÖrÚé{Cîõh¹Í¹ÛØ�ÙQk·^8Å«�“9Ϋ,ò†e�­1Êt¤Õݘ½Ù �„Dnî;sÔWjÌ—‘+4É€<+G¾ˆˆHäÙå‚p³¤¡�Âo»rŽÀ¤Ô†õ½†:z`¬ˆìŠÑ±Æ7δèæžó]q ÑV¶Ä0Ì¿)s�ŽA,ûGÐýTx±j:ØrxvîÃXÿJ§áÈ[ „´Ã¾–žÛk%‰øñiäÍ®iÚ@è×9í1®VåäRC½V;�Pf�Ž}2ß!»á@‡…¹ôlµb‡k2šîÿŒƄ?Mš»æ7¹âGwÄ ò‚\€w¯È9˜.\¡Á˜ՔàÛÈ{ÕTÀŠõü” QÇY¦êéñέØÔD&Ÿê¶÷/¼ÑG ›¹ ûH'ؾ€g@¥«‚{Yhö`íb­;Žö" ¬›:í3ˆå “omAP�Év*Hm§=Ö€‰-žO}Li#åèd?~ÑJî«)’ ¥,¤ÉV�ï"BÆtø‡œ„“5þòP#à?8×ãêÞAãBv³8'¥:­-8@D“dÛC~o!É‘½_fATx—<Ç‹ä¤^p\s¢m¥ôƶã;@=Åw*cqÏ*Þ8S{¨\7±ðŒ5ñô0t[zïk ¾–S¶º‰i× ¢ŸtŒÏGeåá¡}T¿‹ ƬzÛ+É6 èQÌÔ雯’aÇy&Õ QïÕ/j½âàÑç8 ”ŽÞ®éH]óàçyü�`xÙµ-Ðsϸ|ZnÎÁâ:¾2ªÌÈ–œº:’…ÌÆKì¬�“º�PCÝ�¶þê9¬`Ù‹°N#^…¼Rñë°ˆNGGÜnáM¨�‚ÚØ>ú$?ܶyF,šTnª6Ð0›XžJeO ^À|U€ã°+d­Ã<îCTÏÓ~Ü =Ô¬X –b@¹˜Î§ÞœÆ+u|][H¬ëvmRº”û˜¦€ï™ã0¢Ž¥´°ócìJÃ]å8ÄÕ¸1‚{Õ!}ÈÆjÍÖÕÌxÌ]sñ'­$¿ÊRsÌ}2s…a'�À¢¿Žd¡J|ÑÙ�Mð$8,±é´ØSЮçFâÂV…jŒ4*§ú.¬ŒzUߟã�A_Ña_«ï î½šécÏ 3\íŒ>‹áŠF†oY‰³™Y­¨¯À ÖùË#F<Ìî«hDŠ‹Ã¹©2}íèt-Klÿ«ó2~yÕ»9Íð½hû«Ñ3³‹SÓ7­Yé kv·Ò_âµ»;<ÆÂw£¼hOsFÏO©ûý¸^–G\³e×@ÔÂG¯ r° ðz\óJª¯¢ª~g4ÂÿjþŸ¾÷‰aäÊÒ*Iq-y !}ó)™-}9¤šˆO÷Ùü'Sù ?„·ysú Å¬Ê6AƒÀ¡>¶çä5?7‰< EkÛ5‚PySl)~ˆaI_Úò_*10 ´˜.2üÈâ’—˜.ò�ˆ³8uƒýTòkºh£È¯ð˜4ÄWš�Þó¼)ëÄ3]‡· âÿñ‰Â0ï´ß+î"lé9(ì#�ŸiÊp–¯Ô�\¶5†e üŽ>pÇO¬ê›CmÄÑÿßKOUº°|®*û.­¶Ù�_ê,;/¹JTÄÍîÖ�iýúY¾/ì��\�€Ý}*ܲ̑ÓÖ;?– Ûz–˜:â„°v†¶7·`ôQ&ÒË¿Ñh`[�:nóIΚøüPŽdÅ¿nÈX-Ñg§§È.Á¶è —Uƒ¼ñî¡®:Jà��®�¾'Uxÿ¼~>z¡wÝïždZÃ’¡>¯"9Ã;SÀ:ì–^šºîÖÊrÍŸˆÐ¯¼ðUÓUJR‚¡£(b…e6%¨¢¹�2£¨p‰fÄ;äÖ ,#w·Fº *g’Q\q…¸ ¯³ì,€¶hwP<«Ö)–²å²œI9³»4Ws}±‰K»fúYUê_†Ú4s/Ë÷•g™²E/egƵ$ :`O |q,Æ&ßõ.ÑíUvlrÝl¿„•„�$çÝM{öí3+&F—ÁÚt�@±u3 UY“‰�3AÿÀÁZ/eÊdå‚¶á^�l C½ûÛ"ܧãÇÖuúuE³óùÕ©JûÁ; ©Tó—¤èå”7dÛ¬ÅWODìøí·Î:§8:¦+i%\-9Ó4”Þl o⎆IÚeí Ñ÷}y‚-�1& í¬´Iȸ¥—÷qÑIŠJ)9“Œãb×ôøóÛÒi•< ­Z%Ž?•|Ï›3í+Ÿ°ÖèA¥ëUíTMa%Ú-@ØÆ1MgÂFI{�Þá—Ž 3ÀÖbûÉJ“<Ûn ZØø‰ªMmh+9À¨ÂÅ€ÔÃ`Ö\%Û  ÍïA$+›Èp=šÈ? 4&½oÀÅêTì«×Ðç ÔøÁÍ‹îÛSŽ6à'§ýšÁé��»#É“µu@Q‰f˜ú¾Î¶à––âIºá.Ù¦õaîe]‚q‚$÷ʶ„¬¦8?ç–œ¾Œɉ²Ï6ù6¨Z+'ÊØ 7Ó¿;W K'!¹¶—7€ Áiò_î¥óY“°YèÓ¿ãM%Jz‰¿W„Ug,µ†oCC“<2�¸„ó´TÎhhñød_>²Ú›£FÓçX�¿2^*uô:à �)ÿO'sð‚ù΄JäÒ² (Ó(o™½wƒÑ׉å‡�È(¼Ü‹Ð¿ÿaÚázÚº­êF9й�†a݉˜o†Uw/`æUç~Øñcè,TX“|dJ@4[X¶œ¢�C5Œ œ5ÆÆ’ ×~qKä©×ˆ‘ë´ä±#£š7Óp.7žÆq[¢ »ï?�ðN‘ßnîøñXáP’R¨€¸Çf<ÞËçÆ/[Œ�4ö®y®}E0RƳ ôàÔµ‡&´áÔ%[;zºã/‘ À�¢Å‚P­ø%ºyû q´5ÑѲ ¬¢0��ï çÌW£À¤riŽ“WL¾åîÙÀW�_I6PÑ|�tA Ãr&Š1Wumžöo$�‘ ØA©[§¶|ãJ%I%£µ ý®lÒ|*Œ4ã*}ûJeR}¬xbâ+˜Ÿ”Áþg Š«bôQZå¾,qÔ)æi[`jNhñk.þË@ãç�oÖˆ@Þ÷ßsó±žL_W}(P  ué0ãüë%/AŽÍ͹¿Å‡@ÿÙ³£}bVÀIË$�'÷TŸžX!þOx((cë€`ìî‹—è5÷$xˆž÷ï7"“Ù0sÂa*ó‡ô$ÛUæü‘ñÓO= 7HAìŸ[qò–�ÉúÓ¦»  8^èovÞ­åí©1ƒPù;D& áHÔ²ë:Ä37ð„•Ò·NÍ�ÉöÒ=¹O`øÒ jЦ#ô&oòñ†OQù%ê-¬]ßþ�„¡‚Í_�>BžØü!�hÖ_†ºzÎÀ cü\ãöŠäË6[Ç]�²ºÀ‘%ˆä¹Éšv… ֎ʊ#âz™dH³»ú9ý,ÅÔ8Œ€àÑO¿¼?bâí÷ë2+ïƒ7JìYqA5Ý�H,ˆíŸè°k0K<ljîóº-JZm|oxéz"6šª™¹öSpšàGA8 &Ëàò8<« oH"ó$$­_º¿;­×Ðz�šVÑÚkÖÙu·ùý åvQÉ[×giºÙˆ™nÅX  úDV"~O°±ºÓ2tÉ�8ŠÔ‰¡¹… ÈdpG¬~޹A¿‰#¸ÀjôíÜ„t©ˆå¸C+þ•§¦})¯B)Š™ËÍôàlÜ2ØLúB Û$qȇ§{ã®çË?²Ð^�mí&½šK²È‚Áw“[ŽBÉJO ä‹[E‘§×õ×`Å`�L·Qª^ÊWç„e„6a è9`0 - ƒ3Ô:\E‡N(C+Y8Ñ87ʯ�06¼Iõ}n’õ|!í§àêexv�Ýñâ.q½%Ä£J @ ÿ>LñÍKŸ2[ª,nVÆ%/"³ÖïÀâN“{Í›¶^ ä7Ä ¾‰íuË+𤿄Ëчð®‘öÊv¾X!Ï5›9´þcÍÝ”(ôKœµ4ÐÊ@92³wKkÖ6æ”yÛ+ºÕ±zp„8/(!ô‘½{ól¥aUÁ™mäÅ«%r1¯{ÒsL�z�ÊÝÌqdtd1söÚí=N`øëò”K©y÷HïZ3%’õ ³;})¡úVrš5 ÕÒpˆQoµÐ!w\j üÛ‹(ÓÚn_|˜ä’b­_h6>Âñ§¿1·7ûúàçìÒ@S¤-/ùõÈÿb¥‡Ÿ¡lÁ¼hÈWÅ‚Àª:yG�äëʳë5Ƚ�zI�›� Û€wÓ�j±.#í4©"¢Œ/žYã×Ñ£›s!­ÐÒW{ÑO©^µ�±{Z÷èrw!.$Ìê‰~‚¯}“Õo÷Ý"lC8šNÕÄ ˆ‚0ŒŒŽ˜>mEL°üŸûmS‹öm§‘vŸ`ò—þóa9ãûº�.Ræ´s) K7¼'S öI~ícô}‡5¤É÷!'æ_lª°Ÿw˜†)ˆqëxÎ*§Œ7o‹a,\ ùR ›ˆ°¯ZÇ�þM„´ê(4L‰ÎÙµg2©~h þƒùAdl$–.9s;²û¡“òƒ2uD`‰Ù/7BH³ ÷ã“­¶Æ%0 &þt€Íë�7‘Ön¶yK`-å‹®ô�xøA(/ŽÑ-arF.c´¾V>ߌ4XÑKÁ¤6Ë ÜÚ$+°îsêTS/“n$«$]ú�ß—&`ÎeÿCÄœ‡¡3¦à[4)@kF’ö‰”]D˜ÁR½Ž÷¡î¬ÉØÖ£tÒ=ù˜ÓÂÄιuT1DቱB •Ü1_èÃ+K›Â”X»;<'ó<’!‡Þ×3þ öÜŸÍ1#e®Eôä#‚k(„â#ʉ³Œg0�Ú‰S3"‡Ý€#3P5 ¨«yj‘?KË7!C3冓:XíPHþµr<ïNÏÓNËØÃn{Dc™tƒüŸ=7´Z€pÒƒ fù²�_úVÐ ‹#z`WMàbÂy$½#Gü_X¹j\¢SBVš.~Z “—¦iwö�UÍÙŸEy´4Û÷0ˆ !au™ò±ÇŠ‚õÓ!uðÚ-ù,J¢S§NFoÂj ä9)‡¶n ¢`’Ï]n²·›°-įää‰K}C•/xåüç6˸!�LЇ½?º (O�.i…º|-›´ž™/F<½Å…2q^û ×%†ˆªrÞ§‹qSüìt¢É*»§…sòøóý–8€³èû\$­ÈxEdüVdË h8‰.Gáp|4Ö \4‘Íç)9!Ï™#? @]h£�¾~ô?×&qÃ;([æ¢-“SJbãŠäùp•†›µ& TEä‚êX¶ƒõRscÌÞ²ògø�ìV‹¸˜Ê0Zt™€J`2¯ûÒ¹WžëéqSPTÈ@²lèš ý—Ò8@S¨·�®)¬¸»ãÔ(€y¢UGòj ­ÖÚ�]}V‡~â.ÿ5pU빓Ö?Ô_ñ ­r¸ª�§>…èËN…pU¸ë+,,Is“¯¦ÿ( %÷Þ{h?süu³þ t"Ð…(é°Sâb´gHS¦¯È½þ|F-÷U†ŸÕS¼EVQ�Ö1�ài/éL³5�¸è2¤yõmY^ ³€-hËð´Îôkº” �ÆÐwàö¨Ë÷Ù òB’Ïñ�áÖ…¶÷\Œ¸G[²^àhÊzÖçjú’�t³¦®ˆ& ¾n”Ó •“Ù¾ %’Æ([×Äs86H�ê+SÆpË�cÑg°r%â¡N©­úsgÎÖºqu&òÝçTæò¼†U&7¹C�/”sr„¨­¾,øþ0…C©l&h&˜sŸä­)¶ëèW_Åy hמleƒ¶NXòê ï'‚òÎyàæHo|‡ +o’O†à�ÙáÇ~…ÃÀo‰„�Âqb‚áéT'^_µ4�}G9EÙ&Àµ²1Åä²tnüwHvŽ·Ü:øÛ?£e¸;1B‚}òuJsU‡üã'¢2z ãÄÍ�]ºXñü­ûRòG`°�m¢«àl1ÍïØe–CvLRýâ93úiRï?¾âd³™’9Q6ÝÝ•öG3�ÔQ¶ß¼©Ük2á`í’ZäP;ÜL!�¡CÅLʸíänù<„ši"_$†çN‡ìx@Ò_Mûª3󴧨Hh^¤¹ËrP'€.Ô^Ÿ?=hÅ\)!X•�p5ž"e¯²½bèC†÷éêÿsf¸ Î6b‘Á¤¡•ók‹y³_¡{i:¿Ñ× âZÐevÒüB>ùž˜wޣ߲’Ôø¬KÍIâ•6÷ ß›Ñwí‚�"²“›×¸‡ü! 2¤©½9G§j¿–ù „€/öã<8Sœu;ÊudX¨óã@¡??4…»Ñiw)ÈeCšö�o[‹Ç+4 Ìrj§kF¥<ނͦˆõäÛçÏ©!Ÿv´À ^ËZÞ¥/*öaú\ý†îì‚)ÉÁ¶®”LÞÛV'´¶”ùÀö�×äÝ bÆ·o6Á&B§Ä—÷xZŠ¯Ã¥Lèž-´3 Øä‡ÏAÛ­–J™¦I3Ä­Ï›ÛÐuwóJ)"àλTP„–´h)£†AÆeÏ}¨â*˜�—CrO¯†ÁuÕ µ†º~C†[6Ó.šMÚ¤t¾N:¾Ë·ö*]Ï# Pùreþ§�wyèµZ‹N©ªþ![Ów”ù(/Ãþxuªç@f[Ž)cÍÅúÖXÕO£§v§®Í·8Á89îÝÛŽH™œÒ~ÿwÃtR3‡�¿`¹FM+>¾É÷áÓ²¬!,ôf�~‚íC˜Ì?“ŠÂÝ4Hw˜RÍôÛèÖ?š„V6Nû«bš%�JdmvðEÕ”%Lâw’X8BjÝ$L_ˆÙzô8Õ`Šs_ Ž×CF ¬(N.lȉ0µ^[yÔ¥ê$�Òëmì{èÎÕ” ¢Ÿì+k'ï Á�`¨’ÅäÖoªüð·yjT^æp?Õ]—l3¼”Á.)åcÜ/Š#¯èÛ¸ @£{Žv+s³¿×ç þí¬¿ Oð00àñH¸-Ý!o^ö¸Oö9‚�ù™QUêD3žý—¹¼€ñ�‘=wd¥éÿÓ+#%³Ù¶èÆO—Z«çAÔÒé¤p¹³ªÛ%ö}H”µýͬÞ%7MmôÀsÃuDŽí¢Â÷ý”©ž®®cð›¨F¾UNÆC+|ý`«Ëd�2·…S¬²§$�áàXÉž`LPLì<\‰�û³7DbXoã[Û§A"ì8QTdÚúº»D÷°æ)š0É“Q9sß’+NÑH=ó³ai!3 @Rˆmª(þùãqÀ�™“p@pÃOwý]DK÷É&³C¦"1ò¿,˜¹gÜ'ͤLZ:ñ„]�ÜIûÿK{4S¿Âëoc‚¬Úÿ{Þ™ùDµëÍ~Ø(ÃÜÔÍÖ-ÛºüGj2p‡í¢�5úD®+XÉ�ÔÃ¥‚y9!?W çÌV]YÿåÕ¯ÿ-Á<׫"Å~?ÍPý|›õ)Á¨Ë›ß·?%è*n|!cBÿj)�¶%I… ^£¥4§‹I½@5u‘•?¾š$ûqpVj,eeÐ&Pï�V!Ë™.sdˆØ€ˆODŸ×7àö»ºjbBáJQq=;Ñã|Ž-¥CàÖäÍ!î׊-öÝ•@YŒ*3Òßvãb±sìþPFÿ*žŽàAÆ»Ë~‚B�Í4„]õ7|ý'¯Ú̦F¾÷€‘3“x"¯ë–w›í»þ«­R0w.sÐ\PQü¬ÂŠL ?v™‘¦Ñ9ïíÍyô|®ÃÈ îµ%àUð„€%ê‡XËÂ]‘~^ÊÅBgð¢;©ØÇófxÝíùe–ñïô¦À²Fi¼ ås_ôš1ÇlT«­mž¡íæ–¨¼}ÍÂ9ÿ Ù�"ÌH/µL»ldxºÖÎ|hóÛ »¢šTÒ|Ýa“ãš6ôBÈì® Tºc_åÿ˜8a'ͱÒà)é繟òétRQ±Ÿ/ƒrqg‰x¸zì\1¿!ù�OÙT4ì=9:QÐ&+Jå$¦þ½¨{qŒz—"f¿ û¢½‘±’ä X:¦àÄ9=Ù±|¼Åü8™§2Íq‘A×0 S+]ÿsV�`D‰)«_¢,ŠÐ÷ƒÚ°—IäÅ6H¶uUÜP¶W&{�jFIšíÉ_<ù~Ë5?ó6()A”Ó0Äh°çªìbÄÐEÖ¸ˆX’ ï4·öÕÙJÅOæ= Ç7¯k"ÒÏ›ìsôa†:fŒ ôH‡âKÖ´!ù9¾ÅÀ¦ Vi‚ï|xŠEdjŽ%¶Ê~Š•X¥wž0ƒ)%MË­ÐO¸01?â•«~8†Å²a§Ñ””ÑÄŒ�Jy¨Õâd>� “;€�gO$ȰÆšO}E†@¯ÕJ»�‰e w¿N–¥n¢ok …0|^–KJðqF^[[éWym­�Ôä3®ˆ l)*Ϊ•í`âðâæ,Àþ'm¥°I¼éÃD,j™ý8;6+Ë×Ë�Í_n®ö¬@aIðÁ#¨R¦aÔmýpa9Ì·‹W…ÊnÒjÂ…ë¸á,Kƒ½Cw-R<Ë–³ê1÷(ôý]z#B9„‹ÁIÙ?çå­•Ÿgµ‹ù#,ïB3&Ã/ Íaëz‡Û‰ 7J‡F¥ší!!˜/¥X½N„) hE,¦�R³Ž´øUw²¾ˆ7’6[Õ1qû) å±àH;3ñ¸?�Ã#�áo/NW½{è´™¼Ä<·ä�Gr$�d�¢ÀÍãkªÇ)œÆžÕìzí^JÍÔDf`|VAXrK½Ðˆ¤‹#}�ýÎVbozÿ:¡þ P×ÌQÌîQ§+�ñºUâ¬'ˆ$ÁÕüÊS"˜&Ë—�€Ë©Óñ[ÐÒ¯½Ã‰1ôT¨áškÒÞåFqa ¶–ÓË|¶fE¢²…�•›-!g­â!S½$ë3¬­ÅÛú‚á¥0rœÆNšJ˜€rÍZã<w„gŠ éX4¹áæ›5ÇoÁÝDÅ5UÙ�Wb3Zl+,œPv‚¶>0&Ÿm�@òP1ÿ*ÅÞÞb `3°!‰)R¼·�*Ø�±ÍœH´¡µ´kì~¤)�•�:Ç“…´Ä-•W­ óý‹5x*ÉÙLQ‘í�ð–à­ŠftVsæ„™)Í1rî±ïW3[í€$+»ªi£ ¸)i¼Ê~\«Ì¢± !¿èÊT €Ï´Ïw|cÑðl×ôk {˜}U zíî ==ˆzU`/Xu0š‚Å�”ÿà½#ÙÄe‘Å«”ú‡Î°uÕLØ£;XC¥=Ùp5߉÷$®mÔ¼ä�Ûyìsˆ#v£‹«tŽ­_�mëx‡ü­FAˆbèZD¹éÊ�{ÿ1\Ænº`èJSøÕßË)^6ÛòÈ^ôýÿ›pfEáIä'ðûøÙ!¢,[ÈvI!èpdI ¬[Ëß’_Ýò÷Ïëï‚YQuÓ)mulìe{¤ÇñôG¦)êz¸Q泂ա„²•²åyWsãe‘ã ƒPŠ÷Іn¦K¤Ya” •ˆßõ'O¡4H¼=%öGì�¬@NòˆËNPV?Ù‹ÖhYÄÁ�py�me±5c܇Î"UÙ¤pj2Žîc\õk×*Â"ô?¹=`¢¿Š…‘¾IÑwG>Xø /À šÒQ¶>f’¸:�çQ\¾Lá”™<¸Æ,‰ŒÓ}+LÖ²ÊöTÒºMŒøa¨²>H»¡9¬Áoí6úN”6G.œ±*u&r­™Èœ÷- K=8‹iªû`bþ·ó endstream endobj 17 0 obj 72958 endobj 18 0 obj <> endobj 19 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡G�Ît‘øˆ’®>R4éuw¿¿Ï·õ?Óåø�oÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:�ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·Êãé�sM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§m�ܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ�~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒßè·RŸ~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßá�tF8#�ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;Ñ�ÈDt8. Pi�|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-�AÍÄ�NèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8�eÁM‹³<—“#artË„F{Ç�N‡® tÛáÞ®Lˆv�qè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»�õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G�¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿ�dØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 20 0 obj <> endobj 21 0 obj <> stream xœœwste_¶ulÛ¹±mÛvR1nlÛ¶ÍJRI*IŶm[VÅöW¿î×ݯßë÷Ï7î÷œ=×^sï5×ÜçŒCA¢¬Æ bæ`”t°we`adæ(ZÙ™¸¹¨:Ø):ðÈ3¨-ÜpN8 qS7; ½«š›££­ÐLèâàæl tá˜ÿIÿ™’Ô­\m�ÿ‰õOLèìbå`Ïû�Äœ�Æ®qc×?)jnöcg+€…‡—…�—•ÀÊÌÌñ�‰μqcs/33€´±³³Ð…žžŽBÌÁÑËÙÊÂÒ•ðÏ[µ†ª ý¿€‰×?"q ‹•…=€òßþ î@[Ç¿ªæˆý�mm­L¶^Ž–.c33 Ù_šÆ¶@€¤•­•££ƒ;€ZŒæßYþìš…áÏ+@ñ�‚Îô+{s+{+W/€±½@Éha °36þÅ&ngåêì`g¶²ÿwš?¼£‚£Hí�ÎTúÛòõNÒÁÙøW”�…•…@méêêÈËÄôW_Ìÿ 1º˜3Ú]™þìŒBÂÞLÌÁ\ààþJ·ršþÑÓ‹é?4߯ÞÁÃÞç?EþT`ö·Æ›¹92iØ[9¹eÄÿkþî_˜ÐÀÁÌÊÌÃÆ:€ž¦–L-¬îåü[ðoð)ü|æÆ¶.@?+sàŸ œ�‹±;àêìôóùï�Á±°Ì¬L]&@‹?ºý‹ý 4ÿûXÁØÕÙÊ ËÌøGDó_¿Þéÿq”™ƒ½­×¿¦+Ûÿ©îÎuðø0°prX¹Y,Ìêãaeøý;Û?uø‡C•�­þk�Ìÿ¢”±7wøÃó÷Zþˆø_õ˜Üÿ~VÔ�À¿-ðg—®V¦À?ù§¿õ˜9˜ÿXûÏ…å?úþßâÿtÿÿŸáÿâû‹éÿßéÿƒã(éfkû·†Pÿ½!€?1¶üi @ðWWl��ÿw’±�•­×ÿ•ö¿¦kÿþ¬ø?éÔþ[·L2®Æ´±·°ýfå"iå 4S¶r5µü»�ÿ+ aot¶µ²*;¸XýõŒ0°03ÿÏ º¥•©�=ÐÅå�SþþÑìß½$aoê`feoPsý#¨±³Ù?�¿Â¦nÎÎZ÷7÷üÉýÇØÜêÏ�@O )œ«P(ú­©mù—‚�WåÆ*fZ�M²Ý[�Ñ·RÜCÛDú†fì›2µ»~`Ù `I°Áž‹MBqa€„.Ô˜u/6hÄvê$ò=Ýijå]5\Vδ7ݯ•©h,, 8ú:»5£ÕòöK€¼Õ^.�]�Û¿@²ëŽ/ ÛXã Ý,Œ6^œ"4ÄJ†}o(àDV#ŒH …`jS(  ÛÓ__À)Šfù¨íÚ�¹È¿¹jïIw¿8,R!ÿö3w:¿èª¶ÒUa‰R¹`êA¸"¢�‹Ô– 3Ûxá¶àiMèÌŠCs<²ÒmÿL¢ì>x8pÎÉAxV'gÜs;ü«ç7 ¼.âÖVäHÿþÃr…3 4ò2ÇŠY,HÅHü9±ÞÍØ@Ö¥ñ¤î!�Z…ž ËMgZ¨&Ͻø,߯‚|ľ‡¬à+·e¦(â(ŒÜy%“CÜ“uïèOe׃BEÈ—ÛzsYhÐT–¯{�/hðåáBõ–'fì=+¸_‚Ú|!–¸ÕüÇ­‡n5›:3³ž×ÃAÁ#ƒ¶�.¹´‡.êÎð =V“³ÎxÊ´Sô�U7ÿu:tó%¼¨€oiÞ(b|¡Îéu;®ª¬Ioû•oÛMÖÈÄ“Âá3Ó¢îx?NKÙóÔNŸ%Z}`êh8º} {–F‰FàUÛÌgº÷ °‚}Fh*`—tdÄÓ>B°ª:½µ�•jœÇ�êU{¹,<Á@¹-•;±NIœS\ou¼®QCœ‚¼¹¬ìœxF^•Ø\Ó¨�ߟc`Û:·ÛìøvN±4+0»SàèI£›oè!Søs6o¦“T¦ Ž»ûub–.°¡ÃoŸšîü…¿xÑ{ÀCOŠV>¾Å· ¹?ßEDÀ|_ÙPf(<ý­Œ2®BT+mGÔD7AÑį*š±`]ç7&ÈºŽ¶\«mtë»§‹wi#9YŸ,¤%L=†L4¬»]d?ÀO“Ò5Vÿ„5,7î l@ÄÁŸ‹ÔµôH ½¾D`‘)-ö tkâÞ¤šÏ]´.„HÈéRó‘<ùF)¢|ì˜JXuÒZ ÃtÜ„v¢ºNFŽ':ÓÙð, ä£9!«\£­‚�ð7•¤ˆ=¢P¼O¿íý`Ù\­alf¡~µ@ƒ_š-\­�Ò&Ç�¬¦{Œ5bjPÆu› Y‹}L ¡å0]/f‹6bFý‡‰ è¯?‚ÜPnú'5ŽüRâï ³;0Œ.jVˆï€„¤U‘êq©2-ø9o—Â%…}�Â#uKŽr‚3Þ%ÆËñGt­Íèn¾ 9}׿üGU–‡†™�ß Ï1`2fÖÊœÕîâz'©;¶XÅ8ÑÀ’7É~}[Vü­ 6]ZÐÚ\J[É ]!™?ø»¬5cøÅ|$N�S1ú7骻áy%ç"ˆõ¶Ñ§‰~ 3 R -EÄZó"7ó9, é¼!ÞƒóÈ…hÐi"åÎ1¤–ñÒÁC…©A{Å]»¿?ŠPß[Ó,ßËýœ¢ 7›?h»b\ƒÖÞë¸+øˆÎ+f ‚Ú_tD¬èŽ5‡mmá˜b;ca)"ÎmßB¹Ô]m�Á‰ó“lÛ».Êúß¡™èë>ø1Q¤e‡"ñ¶D-¡QX›à½Ø8úfz–œv¡eÌÝWÑžkì )òúùÕk# n·PÀ es²«Nþ>#½¯aêÅ>j°ãjµ2YÂ{oÄŸg5ù´öe¢„n=IΕ…¥°Æp/¸²ƒY(�}—·î%ã>Z¶x>5§ÂJ"Žkȉåç¤õˆSç‰%ÃU\ãd7ØÚŸ˜ µ3º¶„v¦£ €—YŠ!’îfïÒ4a3#R×大2}ÙÄç*RüÌÉ3ƒ#¯ŽBµþþÜ4±j§iö2L]ާ†šÕn‹˜/°Í‘naþöKÎOåüª•ùGÑï½.Ô‘ûGGÖ 2†ï`eÖ¢£Ø°ç%I:¼Íg/¦æúµo�¬„X‡æ¹ 0ÇÛí€1ŽqTP´AsM¤ÌíéÐAðk°e'{[‹ñ1‹ðœΘù)ŒÉ™Rô²t§ ½‰Àðík¢æ7£M"ß.H}4du@ì÷=GÅ08˜ZHÂ|GX6ã�êü�L5{Ò9I0Û^="Ä£Õè1¡_×È—à+²‹ö!5q\è u5½cÊcI‡®ÛFc§AAø KÖv)jà3žz)V!cí쌫b= F³×Z»p`åi½ ‚³Ä¶Ca0|‚ê`Èç°#®N’ ú�©�v}ˆä ¶pm7E¬û–5¬¼±!Ù]5Tᢓ×N.·<]Ï ªXÌG0ÞªÉ3ONÖ@ƒiéDÞ‚ÛgöË•Ç~gž…ÞžÓw´ûÓˆžLú{ÙqYZaòÔUô7¶¡Üøf�$ U¬›Ø’„áeǰ˜ÜÛ¾!Š˜Æ¹sW°äÖ8Úò§[qMäª~–)guûþ@uK¶Ä+°-ü‘z¥(;ºÀÉñ¨»’3ò'2æc™=ÃÛÑ\DÓ“ú¹”ï#Ü\ððVÉà, ]ϧßÔ Y¤!�k×êw&`ÜÀÎ un$*OÕVoçJ‘@c̼k.1"•ŸSd¸<õH˜R¯Í %?ÎfÔÏ0XKYý ‹ÊM£œ1ß{[¹)  ¢Ñ4@õØNn{Ù{ªü ÛA~üT’& 0éfSµÛHg]=JXÙf ÿJÊ+Y‰óMˆg!£Ë]O¹TÚ˜n+Ì緌ڌj¬•BÒ–{P}ÆÆõ�9[úéü(¾¹ŠûQ?€í�^–Ü3¹gºÂÞ‡€o6+/�ñ‹xædÖ¨ðaešöžîj¢¢/·Î%[Ò•Û5 ²ý~›fÀbïz*qûE6­ÔEšÛσ�-ëJ%�®KGOë ØGÍïc©ÔeÎ8�A9´¶(àkF’a›Šß!ß^?È,o½û±aP +ûr?èjü&ú÷aMœS, åo~SPª•ò!íڀą\W1ݽNXǤÕÌIH³I¯Tw¦}ޏi¼ òÖôãä*i1åÒ½ÃE°q`Ÿ¤Â—äÔ…;SúĬ;›YØŒ HUpB v`Ú°ÊãËÜFÓÛ 5me�$jŽè4påÍ×ðkP‰Ü¯wQš+õË$°ñ‡\ 'B…<ä$»ÿE)·@û›±l8š§Ö°x®µN`2l¦!¸ÖÛ!·ë[µÀ6)ª+»OØ'?Ñv# ÇhÂÓ­ÔT<µ\‡Ï“<�ͶþÍ8žX¥æ£'N(î�'õRZù =‹ökÓäw:¬cfË>x—°-�jvç" šû!W¼Sh2ó0ùàOWb~Ë2OJ�Ìsê–>Œ¢Z—@䤙U}Ó³»_ò>&Š2%©¢úûÙÇJ EP€[£gXF”ˆ?iÍTbؽH ˜oA8¾¨Ï4ÈñÃW¸ÎÔ×$ó ‰‘§ì¼¢öz¡Pèä±3bžlæcíêG.¯X�íªDüÆâ¬…¹Ó!Q5»Cbœjœ½öàêtÆ*«ÔÝG1bo+6Mk7^ÞÙüÐÈOê9M1šÎ&½QYF…mÙ:h£+G ¤ÒljG‰%�»ÚD �ø�Ê�â¶oD[d�\ÁÊO×O:ü»byêTç•-mA!mç Èï=‰ªu6wÚDÆïlŸ5*O¥>a Jž¤½?æ:¾·‹ õ0o×;�õHT�Ûz vü²fÜŽÙÀ/Sj3}[iY wð»„n\ |÷óÍ�êÖ0Õ¹ûéøÆœ¥µŒþc-ˆ‚Èïdây­b’˜—wœaœR‘þì�_ųÎÿ3Ô—™ÒGÈÂ"²mânSߌ»Ê<²1Õ#ë"˜)$“"Ñ£&—gk´œM‘!Ûv„ø]ý™‚¨Ý¿ QTv`8Œ£k¼ˆ €hØ ÛÕ7œÕËkãôöÒÙ°p[E/~§KS—¼—ÿºõèáÁüâ× ÄŸÒ·üåʯ²6½¤F(ñè[iàE'@\Í­…Å’~FÝçòÓŽ–p«‡Cácã:jÊC·‹½Œ>Þl^Û§½õºá¾¤Wp�+©ª~š©h€"7Áç‘ß’ÓýÖ€pïËA»œšÓ¢drâ·ËÖ_Z¹ ?.Ðú=°)AMø°¾KJõ -9‚úe€)ÜöÈ!ûőƆJ­¾Ùá%‡ç9¹hŠÁywÖ«p_^·Þ½hq»&³D�гu» ¡¶ø}‘ì× ®¾8òæ„»-¢„K× Þ²Ãøk9Ó誳õÜc_”‡HÒ¶Õ—ÎOú:“lû·±S{yþÔ8˾•jÛ¤´º#l˜¥`ýÂ!'Ùhšã‚Å Ÿ·=8,?ì1Xnf-Ï×gÀ…›ØNhgý€Ú{õÕ‡Ó¿I†½¥éý$w^u‘Ю Gä}åÖ¡ó 8ø Ý)’~¸bÁïʰ ÍB˜XwÁ¾ÙºR£¼ÔF$Ì×Jt~�:,ul¨¡Ù5¬ÜŠåÓ_¡ Š­¾´oÂ÷ZzÂùyª‹dKn±tKt‹.U©R7uÜØc„¸Ã–ò¤3$mw‹Æ@Û>Šé˜‚Žýø&SBUº]UÜ>Í!“Z<üÀ9È�Ö^Å&Cÿ[yO°�;ûäèNßDQà"Ý¿4ÝU�‘9ümå˜J¨õ S Ï%Ûä7,®‰môîþ0†�ã­M4î4‡Bm—ÞÎg)(pÈ×™µW’¯Ok¢ÚV‹Öõ6¹iæ."ÃÃÕuä2y»ì1-L“`GN2f2Ò!±iQdÝtÓã÷&rc¤¤¹ÑÑm�IÉQw˜ûŽœ„«²:à=¾¶þ}7ª{ƒ÷·'¼®:|?2Õ±\.­ŒK9ù[û$oÉt¢³G΋$ë™cŒby¡1äm'ýáãËX\ž«ø±2ût0žùl:‚zða1Ü�pÔ;yŒ‹¤^B×Dù)ÕÆ‘>4uÙ)/µï#ïs+ñSöö²znÖ)jkMÛÉïÛ‘ò9#Žödýmž)ßRòËPmɘc˜DCš“è…òMOÁ<= !£ý>–õ�ßÊÀ½fãÅ ÀÌ ÐÜEÉÙm½ÄøWãKýÜUÍ?O�/7]& .w­ú& 'N¤…pÀhø³Ž•ü‘=R¢â;¿W2+Öøá¶·|çÒ€“ÊúV6‚Žçõæ2«�‘¥ Qdé»WX‡}Ué´CJ øm€Nqü�½ÇiçMÊ»[zFu¯ÎOfÉaÆ�¡]ufi;¾ÉãפŒ6JDgYT›µò,qx wñ„õ“¡áå)Hr’C´{��;¦Îi6ѬH¹D"gla]0P�±øˆùýHKÅåï'\" W(cúW¸˜§Øh`�Å¿�Ÿ#ë¢r+‰Å¹Wà¼A[ÏzçÀêõýmp…ª_‰½ñ´ˆ/‹X´c"Ý(zÚm^¶h�\Úî=iä‘[㧳ʭnÙ+É|uø-Ÿ¼7üÑNpÿ®�µ·ÙˆcGH`Ú´YTx„‡cÃXÍ*¸_«{b™Î~5úï3^Ÿ…çG@{%fžêùnPÆn¶ Á¬Øä±'/× ðù &Áü¹ëñĬK<Çúê5�Û‰™´%õt;î§*W¶ CØB˜Ìât–8tÛ)v”ñãèuù—Æ�”¥+¤ åV€ ®jÚ(ˆ K3éƒ4²§}–ž?/ /¡xnY—b¬È-UR­®t~´xÊeÃûzØÅ4–0îÏœ¼FŹŒFt mæÇ¬áÕ1êhTË6òCV€/HÊDŸ¹.}ÅÅxÀ J}ª 0§ ((u¤m£VSÀþ¹Jp8®Ú´T×ü…Âjœƒ úØòž#Uhøð8f=E ÷ÐÝÐdWÔ]µZ ÕJIC¥òXE‘[ŸÒ.ʽ�U ÍmqôõnÕÎ ÿ©uaåûîõgUdƒÝlÎt„<5Q©M í §�’H‹¦¯Óˆ¯ú�ôòq™ŽÎck\‹î¹‡¾Ñ!çÂzK�±êwýµµyH“ý9øŽlÏzæø�.8T~ü§o®�pq¿¡—2 Ðn¶¢«:ŽQ‚sŒØmµÄ“šJn{Ý«Rãà³µ4*æ¶nYHÉW~]À'àòó�ñüʇ�Æ»?gÏ9å› $iÍ,µ¬‚XÓäibr5 ó„â ¢çi˜;XÂ'ûÆ�T±2Ärè'úÆ òhq»ñÌp ÎEŽ õhI› å¬;®·…éëþ 3t^-ž¨¨ªÓ–2¾ÒvÈŒÖAª±:×óA“ÃoUÓ%Ég¶*eo´qÆÚ°ŒKƒ cð?ÓsÃo2» ˜¼D˜âìãr6šÒ$EÌS'Ï_¢>aH0ÂôÔ:T_¦juRÅÎ…lsýŽ9ÒXbÄ6>¤QèK†žàäE†“±On uÐÔ�æÙjZ¶üÖŸ‡.ZX›È8ƒñÍìá EȽúLJߤ”…R³x½Pïù´Ó3Æ!RÄrXãe£¢sæœìƒX˜EÜu Ød‚ìö,†{ ·„Ðã ª¤ š¤§N!¬ ³�!)ßüý‡œªGú1ׯ¹˜ßsäZÁLÍnÓ,3&¹¼á/¥ÂнP46´,¤þ&Œ¨I6„a«Rƒ¨Ñ|®Zö4ÈM�ËŸúÙyà?½òѵ³CͦϪ¼6`Ò^T^Ê«í`1ß÷ɯQÀS‚ DÚMFÂÀ†~äƒ?''Ìß`ñËÙE3ê¹PµRGÐàù6±¥�¨@‘²ú™ñPC5•­†¢é-¶ç—CÛ$áPÑv£[|?÷Œ8𵿠—‰Mš³3Ùf¹ ~È% !%•šè4–hNt[,¡,.þâ=³’@ÿYïCÄYÔ÷ëû[¾W “iŸH°ûÔÁ” ‘ïY!©½F³Þ{Œ>.Åqÿ;#–:-G<|BðJ/jÔ™7o°î ui+A|¯}p9µ6ëÍÜjþp‘ØÒ4wkNd�dµɈ½ÀŠÙ9ä9G„®ä<›9g¼wÙ$ÔÐ(¨IÈ1†Šòs“‘yAªÈãm¿G®ùeëÃ+Ášb4p×[ùÁ§jm¶I/\?ÕÀ ôÉê©Ó"¶S¾�Ò–x^ç+ë’S—�°4�ð˜›øSä)G…:¸;…°ÞÖ--’îXÊ**#ØÏ,�Ñ{6‰€Ònêg¿´7û<Îr¦¥úT³[QˆÜÜ@µÝ~,¼±û•Mn‡ž�¸kÉrÙ´»jÊö ’^ñŒ… È\Q<‰1HÕ—6°ØÖ4}‰©œyUÒêÊ祵/¶•¸‚êñ¹´Å) øÚ©EQÇ¡ûíy 6�2ðl¥·ù”vøÇ™Ù`x5>ª^‹XŸ<¿w‰žx6Umù* àgûÙr†K“¦��”¼»‚Ï„…´µ ¾©Å8 Iè }2q‰#rePçzê*t[?Y< �#x§žQø1O¿jÝ´ÅdË Ý\“­ØF¬Z7ö®êü—�º¼˜ûårðïYãJ! ©(ªw¬-éz\”Hv ŠŠVo@¨ùkÖ÷8«/{�Ÿd] Ù+z¢P;/´2f9O£ƒ)Ú€Mß•u]¦oìíÎÅÔâZkkÀv²¼ÅÉGÖïø犑Á·9l\¬ùø>wJ$�ªªÖ ÕÀ†p§F™-ú8œRØÁ¥tò®lœQ=Œý ËŠ�ið~Êy½ö°œg0ó„!õË_ÑÅRÃXò�ÝÔbàöt´°£HÂøÖý™{%ßÉ’xÀ-ô2¿Mýh#2úTò~5½Ì3iº=ÊÝUhÎܢɔI°ëô‡°19õn›ëé7QØuÅÊBúdç³zôæR‹w¢§ÙªÍ,(±yÙnˆòèNÎAV�’Èy×Ý¿™ËyiÏŸÌ9Á{÷‚ h!zd†ÝÄGôæ÷Û^Rà7: ÓSjõIÇ~ŸvÞTƒÑüf¼|fÿ¥ž}9KñW¾”�B&£¡š6¬B�Ïù³¾ZEk4ÐBŸÉ¸�Íß=×ë8l¨nÉÝ.j~ýO_?~F¶‹ï¾ˆP¹5Tˆ=X–ÿlh:3¦{–¥9êÓY`�po±'– »ñ:E'–PŒVDÉeÔ§7•~6J¼õáÄ=ŒBo™}EšA™e!—ÖGú²G÷!"ínEÊ—ä�ã‡ËŸÇY£æÀ ÓZk*=æ‰cK¨áWŒ'ùnH>�¼Üo õ:e4‹eVRν³“‹~}MyEa9[�[¬M U—CW�Ûk¦ñø™o²¬b{�îöe>ØÇCŸTÃùfÎ\‰­Åߨ©><·þh ¥ WkÀCÒÀN"’C ÎOÓâü+Î𼑵œß,~øü}šÈ—Ýk Ý1Z|0VíxR+ÅUŽÍö@uw\Ä7ÉÔ^+^j¥èK#ÿ’ãñwÍ� ‰‡m¶Htãßo®·áz]y¯\:©^˜ÍN t�•DÝ”õ¨ôydG´Û߯v¶.[¸-,ÎõníÏW#¡åµ‰·Ý½'<1\^r¾B6Á8t�bY§0¼™Á6T7ªæ5I/œÕ9ð¤,£"Kwk0ÛwÚð?Tú̓¹·/0àˆ7Ï>R´Ú¹$Ks‡uýf•íï{ãÕvjò ‰&: …ÝO£Þ•ödÚœfãW™²üî½Lõ,»ç¬lï�Dœüq‹8ªW'¹ãÂŽµm#ñ“û÷—ñIÝÏ0ïÂõŸ ê.³Ø©…fľׄb`;L¦É½±ÈÏÁÕ2ƒIqþ(Û¼`%g‡BůÛ?™BE;¡3’°è5Vš-^3gQʳcšÂÄLif½x4GXB#ÊÐ&{/ò f`ä†ÙóíVŽ¡&͉,7ßôÂ3]~!×Ç2aÞ,×x;ö�J�KÕ"ÙCZL«ý,8 C·¶$žö ¼÷f¡+—/Å’9fÇÚ3˜^¯¾”*šõ &¯õãÊ÷F<™†³¢.ìÀÙ m2 Ë(»?ž5dßÅ6Œes>t1*N¬^¤çñ’¦K4ÂÑ0‹;%zh0�«.#…øõP鋈Þ�ˆ`~–û£ óûŽ3/þ<¾æqÈ­‘…¯õ!û�XÂ"¢�¤*ª�îÀÂtÃMäŸÏ,"™‘F¦»ðÞƒÔZ·ÿñ‹ÃæT Ü(-wùgöPÔåQÚóI3ËÈs梜Á/ [BØ —ö*­˜­ÍZbעΰÝð‘Ä sÍ£†‘ôœ˜|”p©ü ˜Q épåN‘oôËÛ^laT´]ÍúÔaI¨ýɺu=Rå‹âmãt(0 m¿uy# �Þ4s: –ªŸüN—ù’ãuó¾@F{žïeŒ”cWÙ·ÃPUE%F?,etxž¼Ñ-Ë\e"[ · S·V„lh=¤ wf€ªöf‰â3‹él kæN}‹’σïÊ]J™RQ­èe³C¨q‚ü{¨iy³¥ êÈ+@ ¦ÜÅ÷—�ÈÖ ÌPDËmXƒ¯ú$Õ[¹ÀÍ-»\¸²×Û'µ²ÝJÞŒòAÔtCèOˆA9ïGÌ%úè­È¾°ÑÂX³d²ô5…mb®ûªâÒ)Dþ¡ö ŽÏËŠ@"Ex8P™´¨xOÄ£pïHòÜ36¡]& Áâ âhšêàÙª¾½ñÜ ( @˜4Y˜^ MRX÷ÂæàèGl_øø]ò%§O¯ m¾|cO† rˆˆ¢pI/�ø‡{Ñ­ž,6J®®J“ áì�/—ú¡UîVÖÒðïÙ0Fÿ_܈÷^dU#� ¶ÖômH€š‡ D�Íd½×.678œ�ó�9Iëoå}Û¦â™é é¸Ffa\’U}©$�¨vDq«ªaK<;_CW·Þ]• ]tl©Í iw®F_á)ôÞ¹ßø¬“3–QIv¤Û0Xò˜fÕ"ˆÙ¯Fé¤ùª`çéýFž�R’þ‘…]!áTTúu_ýºo†Vù�%>¹äZ¥y„*Y‰Î­rÚÚ¦–ÙÙ©žÑ÷W$GÙüèÊ|Ü“|I˜]á1këIs¶L’ €›#"¡×$Õâtuõ3#Ðç,Ú®Üè÷v)GN¥8ϧ&»?ìÊG×n\¶ÍJ(€³µ Ĉ¤V ­Ç��°Ì7ûbì9UÆ0Kădݧ½G œAëÖ÷@î›üT-/Ó�NìÓ•ÙŽwǰˆÓ„äðé—L×iK½¾Çd»©ÊÑ/­•Eþáž¿(Ö× ÷¾9�ñ@¥ÃÅ_Ú�³ëqÖý Y®ÏN´7 s8Ö!xÙ&Gt0õ@ºàÊ ÿʪ9J5}…8Ö6é“×øYÜ%Bâ�mž€¦X@=ÃE©"mêà·ûS?Bôµ�‘Y”6AqƒÑƒ¤aiýr=/Ç/ÝU“¯(ßcß~Ä=¬T Ö�K÷uÝý£^Kë \w@PŒ�ìôfù ¶ïqÁŽä.Wa†º2I«c;‰‹h¨JïçºomÛ— TtýFnÅ€…¬I©JˆXïÀÁA1Ä™Ä%kÈ›Ï̾%9·æˆŸ,¯Â›I7±¥S"â�UÝ-ßXjíVܤš;h»Úʧ-¸…áVŽ||ßðßLÕsfhTH"æÏ|âVvüçP6 ‹?ÚµÂá,�‡l— ù §mmJ?ÕõÑ'S`ÇéJ5ŽM"4+¼ÂgÖe=~¨ß3 ØÜ˜n);¹±¨$>"qÖÛ�Œè׿­¼µÎÎú¦ÅØ*ÆžÒ·‡£&`¦¯eéÏ–à ˆ-Ãb÷܇¬s� Ë'Öj'ãd²x4Ê ŸI6dluv^[E>e@7£! թД˳ÒîÑ/‚dïžÔàq÷n~ð1 ND8—gî¡BOUÔ\ò í#Ú̲€“xêtßáxôöb�árÆmÕ]lG�߯�ݵM]%\5q�¯Ôu°ù!/“ñî.äh®BÖ™Ø ÆAØl+¢ùÓ[ð´¿±•éÍ;9îjŠ;~N¨N®+ôè¶«IPšü^þ$Mt�ÅÄúAF—y-CÒPGqdZÎ!1°š\6�`bmÿJXá@)Xìç0´íX+²3å—*T†ÊoÎ�ß§�ªXkBöÉNKÝÇ4}ËÛDVfÑdUœ:J�HÞ‚±LøÄ5)ïñHxîæílν½œƒÚôIåªúóÇ,q—Èeà½n=–Ì®§…yf8 üi(×ÁÆ6)UÛ׌:¹f¶JÌz(pJ�/� k.5ŠJGÓR¡¼KWß“`ÌÙ„y2lí"̬ ú]:FŽîÁ+» ñä°©ñ,æk -³Ê©L� 6æúî˸À qçŒlÊÂ2G\®0-°È *åmR %¡;ÝWV m08F™YI=±¿ßC½®¶UØ —ž8—• WYÕ®™M´GS;øXw?ô‡#± —餸�ú. ”®NØö}{€N)ü}x/©øe‹l•äš"EÀxÂP÷�9†Êd ÿ"Yìí:éøÌŒ¨8!ëçœÎ@¹(^,øïÃÖ}ÑGðgnô>PÈŸ«÷ÚŽ¡þyäFmñùà/ÝÆsy¦Å«¬Þí¥¼nÙ„Šõ±Ò;ä{G¼~�Fð©:õ¹v<ü7u/â($7|§_Å¿±R ¢øWž*çž°#�ôFÕÊç©Ýrþ|„¨ŒWçO9ˆ¡|ñUw ãaã‘¿Ú¬Âb€WŠ}ÑE¿ UMhñ`ÜÿLRÓÁ~]žÙ#ê�Ôpó7·‚GOƒh+s�\\Hàìàëe5FÒκþÚy?ÔWÿ¸~˜“&1ã¯fýÆ’"ñÊfÁêÈŠLžÁníl ÁN¹�ApÂGáxØfò+NÔ‹šP¿ µPŒÊZ‚Ï2¶è‘ž“Sôh$}zº¶w¨ª@®Üã+˜ýØu>Vnò°_6>Ë6D)@réÆš‘Žk 0·‰¦ázý�.òMô(1Ø^?SzïpÞ=\K÷i5`¬ÛŽIÐx„3åsOÒ¶º!’sB'ï9šÜnTøS]Oz°„ ¬ŽBÍö5bެ9dHa=ŽÙ¤$@¥LãÚ_§L»Ëé¾bǬç+Üg²…Å);º5ø­ƒVBXo�cw@Çz�ÚUi5Ô£™R ‘£ù(°[³]®ÊŽFgkÏŠb™p’¡ZÃdÎ[X=’˜Š<ôÁÂÈ‚áðˆ+þ˯³¡ÛœVÃ3�ž‡tÇ«�Kxó¬¹\ÏÇIPÁ¥›aGæ»Æ]|^7}˜àfû;™"Ø` �ÉOÌæê¢)³¤w½¢…»Ì_ }R™>Ò©ê@,q’hÅ~7|¡Ò÷´5ù±�DùY$õ§Ù´é†_ü² :Š<Ë?\@ÝäãVÏ(œ¦»Q«škÙ£*ã]ªw3ïf‘öùX¶P ‹oÀöº›`LqždDz-ƒø»+·{×GëTRà\ˆm0SÁ·røIõPf:b3s”ríC´µõ™T¼[YžåÕp;ÝoÊÝ›�]£Û–°y�Ã*{'?xv“äÕÍ�oŒLÚ"HÐM…»�YèF§µ £¥ÎôðwkÿÅjµºƒ'ÎSf)âO$jÓDØ}´É¦¨1ûh1ô*•4G´}y³®§E8†IMÅZÞ ³•Üú|¢|�ó�kLžWóþåÒ5>ndºíÊࣚÑn;sº¤XSœãì nûø±z«–xBµS<ñú£³í=¤¼ QDuÂÉ®ZüL*x»®‰˜7�¨&™|YÚ¼°ÚVy]aµÃi'ˆ*É §jÎÀÌœA.úaRÚ¢LéfÑ‹nÂ2Øqp6�nw'™!o|pÛñíÓ3ºê«Ó– [$_THkÍ’Hö ™:(â²¼oËd¤âBz,ï×ð‰PŸð ýSâOLçe7.sÉò^‡RÈÈq[m¸ ,¡sí3>èä±ciY!ïüð…©ª÷žÝ®ÍMtAKo,ËGê_:¾+TÑw¦Žü¬èt9íX’%r;{‘ò½øÈ÷«móÄU²ÕŸç…½GUî³$°˜)ëšçH"@�´VQ, àÁÒ÷Ö6¨|4T‚iÒfp�‚+,u)©$«o—”ê°�+û¥)/€Ú:[ÛÚ< L³¾MUª+Øø6ý£2-îà[^*+!bURÜe� ��B óâóÒ–15®a|¿÷ÓAüša�çÚ \JõÝàÀÑ(ó�áw•,'Xƒ 4À©@¥Å(.ë'óž¾r?„è¯÷‹û®Qï /à’š²eJPšÍóIäø¬Ì‡ÜgÔÔ=?MèÔc”�¨ý‹Ÿ . ¡ƒZÑœHCaÓóOk¥'˜­È£y ÙS3‰§Á3�¿ÿúÈJ ш;³¶Árú¤•Éê ó”~ô9ˆ~mJ¡é[FÒÌF©�˜j;«eÿÍd‰Wi3ªÁáyÆË±„Ö#þ²ÆÀ.Vÿô|j·÷),ªb)[’Pqe£°L¿Ü$`�T’TùK‡HwÅpÑSeœçÜæ{EÀ^¬ðoß…¡æ*w¶z7Ìõ³ÈùŠÒ'ë‹’ÑR¤÷ýM1—Ù&¥„Ž´6Œ×å—YÑD£&ð>Yº8�=Ù«_g Â3ŠÁ¢nö•R²ßé¾Õeþ‚Z¥Hûvâù:à‹QpV‰¹sü,LOîãÆ€*ýñ†ÛÂ7Nè‡$yÕ9N,Ú†ïËI– Ý*mɆì—GšT9biëÉ“ï³Ý^}âÁ[Ž."ŽÈ¾öt^z”üBâø…¾?ïO«Ù&4c4S¸fƒÝ^Ñ w–GÏ3‹¢º�Áø×%ÌÅ‹· ”ß[ë˜ÕÕä5£t´© ù¥ÛWs–~&8(}g€,Ìú8Çküµ.÷yA``§0�q 6²®ìýµibsªZ,˜—(ü#­:ÊKySÈØÒ»ãO£’.äAæ‘Q+1Ç ËzmEAÄtÊÄç8mV�òó:œ±v"sIO”åL˜g¡~G«+Ì/­Ýd©ÎŒ6JúÓÝ›xæRX$ñniä¡3»öoûsøŸ·`±óîe(ÛDik%:'óø>É„*Å'&ª¼Zb 7g«ƒà;CKýðLõnV1a{í•§4™ {›_<‹p£µos;µà¢¶ÏxùxƒA'Ž;6ñh§1stØâ÷Â8ñ¿ÐЉ1 b�_n;>B‡7¶¡\<œÌë‘)\˜.M1rïgT’¸ŠÜ¬mÑvZ•=^hZ@ëncËþ\—Í’Ý¿uÐB¾rϼS+ i>e’Øèú>~‰‹Oýσî]‰»ë žÙUé¨úÈ‚ˆ¥žôøç+ÅÆ!ÁèU!Ë<:ó‰\”Ÿ`k°Ï]'9 *ñŠ ÝTÁ‘°Uæúkã¸B­|Ч[¾µA*)�˜ê7̨7# ½º·Ã2)NÑ&Îõã„%3/°öC­ÿĹåJ¼ð¾�I΂4ši«9Ñ@'R!ð$"@ƒ³ ýu¢f(oÁ?]®{Ö­%þpÜ“ZÓ ßÒΰ“ùlØ/i`LO/� NRÂFó.¤z²†}DŸ¹S+{Ó'+KŠÐkîoIÏà¨8lá5ÄBûZ“ÚndÏL¦o(ñ·9êIãýó÷9\"a×eØ/àþ2åôl”$#«áÐuÃZX¥XŽ ç˜ââúqó�Y/KbÔÒ¶Êa·ˆ¸€KÅòoŒL�ðDi²K3=¼2ôa¼C-ɪ™.%yN0ÅlZwýâ»2쥑}6Ìþ‘(l‘Ý"²×îÄjRŒÆ•¹ó@¯©Êömkîè{î_ü/FEz5룟óÙT1ËŒF“¸Ø½[¾ç)§ø1†Aʬ?v®z€¬ìi‡—ˆ\Ãd.Ýy?ÆÝ_ÖôaÙ¹mÝ/öƒKAKb@JÔ-½dº2e®bé•A@.­*Ì>ä'8‡x!çꋃ7@¬W×øSõâÝŠ€¯yÉÛÀlD?pDÑYœ¡ÈÃvý“'–™Œ2C"­7�ûœ/�Ðãê劻 §ØÆTÍæ“#Åd�e”AxjázÝ%Vn=ˆÜ®9§ü÷Ë‘Ì×ZÍÄñîwaÄ*÷z âà 4É“Ää�¿‘ØšP#ˆÂôq7ÛËŸÂûL"æ`�eµ:$KÝÀ Dj ì7Œ•þ¼„Ô{j0Râ kA ¬Èp¬\Cû2oøw—@ eÚ³"t;˜±Æ 'ïMú2Îu$ìŒÃ6S£<¸&‰ûÔ$òÁEá–ÏÙ“x™…ÐõömQÞÍ.~ ?”DﺹÊRçýµI¬²‹Šj—¯u{Sçžgï²Xð“Cx]FÌ�¤ËA <…×úÔi]yànV–‘ÿB³Ý’Žà·Iö÷*è‰&n}Á©]ÒÔ?ç“ܱl. zW&0÷wæ”B¸HŽØuÛIèL…ŒCF!^‰²Îy2�5~Ûãºpt‡sþ[Ì«f cû¼¸®ÂQïa ©íÈ^й£´ï“$�“cɤì•1 “ÙeÇDÊUƒ ƒV5Á1*–¶�åôþÈŸ.�4ϧ¦ÓO3Å æçÔJ¶ÇÚ´O0²ÌÚ’¨e‚P*¸›a±2{ÕV“Mý°é²ÔY��NúfÍp`1ÇéqNo,©=O=9©­uA„ùmWÖ]ä}¡l>-"ä=¢þ�cdùI›ìÕÖÕê#Äsð8CHÕÕl\ÙÙ3™Õ’Á©øœ\—ÝAŠÚ¸Œ¥ ö WÁ½.aËïõC¶Wñ˜&O‹¯Ýg´0[µ¶pÇožÆ.¢úfËþë-´y•*ª™WÑëúH-Öº¼xÖ!¯6ñ_à+¨òô½ÿ @ô¿ÌÏTÜý‹ž›NDƒÝ%-›þBªýñŠi¥È<†‰a:Õý¾3÷ÃJCÂ,DBq’L‰á(á&¬_úºi;†R“éXU3(õåÀbÔI¦&ž±ø[—ûHš]Z,ôø–å#ì iNéêD!aÇNm‹�dõÖŸ€\Åt|Në…ÜΕëÔÒ/9û ×’Ò »Ë:ÈSÅå¤ÁÍøØJçŠ\‹Ú7³BH#‹CZ>UÕç¡#Ðèƒ~¦’HÔ÷œd¢ËKÏ®)%x- ߌS§[´aÓ.4�™¸sËUh𠊰³ª:\˜Bû—šÜ_Ú'H“|0�t°¬\°=ÑÑ #”6uAÊtÏ©–Ywü >GÛ�˜«‚{Õ8«òQdÑ’�ÐÃàÊÀÒ =f úærÄ  ºŠãÞ*òZîCxžŠé!Ÿ$¿Œ�­~Œ®›µõ$ˆÞ¼(ƒÛþ»‘XJ Ý÷,‘­hE å(—ìýïØM:OzðØöÕÈGÈBSöý‚µyú–U_]‹Ê2SC+c]qkìÑ{‡ Ö'*ÕyY‡2¹,0Bü† *WÖŽ-ÿ¹È©aºD{`EèÏj—Û‹Êl ÝY—åÓÀijΛfŽ'ñ¯d›—çÖŒ"• ù7|B�¶ ¼Û¾ îè4F$£¿†Á¬öùŒéŠy ·%4ßбæâÓq°ŽôÜHº¼¦¯?ÕN× Å°¥t÷á0!9ì�î“$.Þõ.¸´[Ã…`Õ©êSÛ�ߊÐ4²!Ùô‹Þ*WÔ°/דJ„;·EºÙ1eKÿ{?ÓrgFŽ ±ß_0f¢Ä8ƒ±Hœ¹†…\¥�µ“�ËÌùD"Zuké —¬ùçýJØ«ZÄnÄž¿u¢ æ10nŸ ÿÍ6_<Ù#W¸�¥S´J™DëéC“? 3°ùÂ~ù§9ã�kÏ(¶¢B–ÎÉ'--'¨1þJgáô§Ó™Èµgõ[M!®Œß?ÝÔCÖ!žßÍÂTOmÛ?Ížx©i¥h}*uñK£Éõ¾dDáÜÆ³.nCçŠЯ3ÕìáEPwA5q\•ƒ¢M.ˆ6Ì1ýµ·GË‘½îàc³•Ù}Gò�?·¶�¦jªõ4ÎF@U+̆”BæÅ‚Çú ‡)´V(jü¦¥ :@Iæ%þ°_)á.`ã<ÑR§XÖ#~RÇÍ$ÉÆ 0bh8L‰¯y};ÚnÓF½œ„ñ ®žCÒ¿u•æâ½N�.J‹¢eY^[Æc*û^§†8†oÊr‹qÁ¶µ9“&É'g…|éRª¢žÇào¶oˆÁ†b¢ÎûSˆ’T܇©È�¬>“ëФñù®Â’êMÖ…s²\ß�;¿7®l3È‘óDâ–1ö�Eb÷4ÿl*h’’f�šøT¾ZUÂÜQ-cu.~,Qt0ZOtœ“=øZV½�wäÊâ¯v2½J‘-ƒaâÛÔù¡/ÒÍ⢳ÿ%oÃ$/«#ÙÎ(XUÖ̰Ùû¯¬dÜSÂmš%œÈ…bVq÷É"ŠƬ4%¨úešÿˆ«µ¤ÄPðzŸ`qˆðö`ãñÂûR¼ÛmÁçoö¬8•?[}ˆbumÍ]7µ„ýxMœßÿˆÀnøÙóÔÍö9þ°À+V±Gã7KêÒAÊ’Ð5�VœYÐWÍZ O‡¿Ó”ǧfÞ„¡«ëh!ãᥣ‹õƒO¥¥¶eà³ýs_¬†4ºÃz&ZAÈó$¨�·í‡  V Ñ_¢ý['Ìç}ê¾ê�hýö¨4�þÔõf*­Ó)éJ¤‰ƒ�„9“‹9ÓdÊŒ'##cÄÍ— ¬±çðWºEçN¢è,‚”ű­0kc“4:ÝÉq¶ÿ;VjøbãÓcLÍÿ=2Ôa—¶LXbwn|c�Ѳ“à5ÂÆGäY1þÕ§ å© A^ÓýSŽV6òRÐÔ ç4|Ÿ€†…€kÛÅ'ªèT�¢1#»ÌJŒ*`TK�ÄdU漺9º4`¢ð}DxéÎ*&!“ UŸ›a�ŠTÒ!§Oh …ŠpTøíÞ6[ 2ÿÆ¥ ÆØæ }WqAg¡¨ÆVÜ tŽŠ¯þªØyŽ¥†¬©é|Ö.�{™cü3åiÙq8< d÷¨ž¸Ó†S¥’X+¹Ô“�ÐüݵL솰�>¯ñúÉòT}hÝM›–*eûh¦0V�ñ•VÌ×:Í‹ž¯°%™Ô.U F<Ûä†6‘ÞÉö?ýp®´tÔüêÎ�ºvÉÇÄ Ã`ò¤úp\ez©TØM—“z [ê|ëu½‡í±×¢JwsÚ¤ÕA§ïH™$>xM#çѳwÊ0ÊF¦~¿.ÇÿýM–Ö5²�ÄF]!TÛøOïf…U‘²ÚGâ5˦ü˜ÍÑ\^¡¾N)ÍôÉ¿BîÙ‚ Ꞁ'» µBzw(,ÜÖŸhôÐ:¹ƒýÁ£÷z1Ó‚âçõC±&‹zûNE6]çDË5îˆå)½B˜,7 ¬Ä±u–æÿßN'39^°šŸ3¾µD±ê•1kFì|'¬ ¡ÈÑ¥§7ï;8ùtÙˆ§aÚý‘ýnˆÃû'±Ò°QXÌ,`OòøáÅR…oK}á µQ_\û)¡0Lø¬;?�*T‡×TXv¹òX¿�æ5×�Âþú°TY[Èu Ó†dVReüšë=r �•’,'ƒrçúÄâ­ú©¨ê`²ñ$M¿Z,y¹²:#GèÏTp-YøMèÕ÷&G)r%oÑÊM|ñÀPÕ% m Ú„ÒÏš ˆü8O�Iú…ÓJQ±mÄ_”¤ƒ°—Ï^X’ß*Ç žïɘÅ/F¶»”}ª€>Z"c-Y…vÒø[(SØI.o¾ÎËÌ»ù¤8 ªÛcþ¥tËáÒoo?•œ-4þÉáfÀsÄFnWš�¹Ž‹<|<¿x,Y•Í$!(€®5Ùa8oãØÃ™@5\ÚéÔr ‹§qêÿŸý^@åý›Ü.°<� èϲôN¬¨–ujöj¶¤)e$üà·”ñi9ªŠ¿ÎËíòÿP m^p×]n;‹ÒB3±–˜¨÷E qž¾¾·¼Å{}Ú.JˆéКÍ>Rym§äÞ"ÂO2ú(9Aòë* M«L3êꞈªöÖz>cJÔºjYr_Y…äŽR}­]r�¤“•{¦Ó—¦·¬ÒGȆåý×VeR~¹ÈFô€ t‚ÛœNBÕ$è"yß}Ë-»„‡ƒxñÆ(ÅC[n÷»!dØÊ4AK|¾½k&"{ÜÀï­(+&µc¬V4â;X Õj™Gæç× -† ±>âJVvÍ Éì1¼nÈÍ–_4 �=N{—x7ô•ß�Øp4us_»™)6É;fòÔq˜µÓ,«‹îÞ4RÀd'Fÿ—å]¼ &š‡ìu*Î�KU/Ú‡2Ó«ÿ¹‘÷ïDOŸg­œ(šSd~¶×qã·(S®<¨´W h)uÇùóÏe#mWÉBBkÛ¿ÿü;hiÜ-™¢ˆ\áQ¦6z• Y˜áá åÐtŽçÛ¥c'…½Yº–*‡QÝŽö±b<ÍÒ�ý†�ÄH ½„Z kýv%ÃOˆbâ²z­SÂÌ0†pé R½Ö—Ôöó¸½a½9%{žY¤Š¾-1õôK,A\7Øm;äv¿d®. =×fGT{h¤ÃF¡IFh0@rW.0êKhƱÀxOqY42ï©#©ˆóõo$}�oÒeÔ.½Ô2òèI2ì^s®¤Tñ¤‚ áb\+�w~Æ;×LéPE3¦­Žô]A)ÜAW1K­ØU¤0�ýÔ.ò^¼·‡b£TÈjw‡S”mùÄþyß§®Ùu™ß_2Í7”ŽE¸ÇÜüØf’E£Ç¸q¯j�ƒ&º›©�W®�";½k«Ä€æ U¿ƒ`3@'š¸G³¶ýA„-Ú÷ývÄã!<úÝbüSލû‰«@»KZ0*9~‰älïÓêæ#ê/—Öqõítº›³F¸–—œÙXdn1¢/U׿òÑG/í·¹)'¨^:HlBš�€l,øªdˆyuršà¸CMºŠP‰«¼¤Çé 3ÃýÈ£v®Ñ5#èPÏ:z¥OGø²G¢¦B œð¸X‰ôc#rnï8„Alë¹j3Añ•"keø±Ú!·©~|A·°½k@ªéy®Å1…h_XYÔoü0yÍÕ³›sù#¯t}ì�ªv i.8–¼¦±ñ÷jü´¢ “ý´.êÕ½qªÈ2�ÏBì'.-ÂýÕEtde ŠYUI·]ÿÉfý¦þE„*ï}�K†ÀBK¿"¬`™`u4åˆÿˆ¾ª8Ë6±Á÷&SÒù¡¸H1φƒ,!‚øÎæ›U#'Ýï†.4LQº"p7ÉB±üeJe}0áYJ�²°(\#P�Åk'T›^øÈ’–j®O<›ŽõU˜N�M‰|ºïNÌù�–óTi±æ<•º.‚åLº†ûQB­Ox 9å\”¥¡•<<‚¿´¨î”Ý•ôgÃÛÅ…×ä(ºF&\&²Ðb(ªa÷~NÏVE‡bWøðµhh.V^ziwÒngPÛBXä‹�Ô1îñ֨ °Y]ðbÅÐÓiLínãÞú_fOî1VÀXM/‡£(Ëþ a\[ý}FñO&éÉLÁÅjíØEJ)˜�2ý&µÖ*µŽ:‡›‡râŽöÖµì“fðYB`sݳ|#•6;”º¥søy…þñ]‡l«Ð¥;˜_x/xyUq÷=ÃIomàÝFæÑ‡¨œˆ»øöW¸�)£½ÀÛæõ834F™ °¶ö„¬nÏoÏ `� OÊ”  ¼}ǽJÄ{S.* ×½)¼ÝŸ7NÜ©ì,KWtûz¶šTÜDãOhõªéª^ãÄ–·'b„ÏìÚÁdA<1»€y:¸×·é5*Œ¡íÇUá˜&}H]¢¤/Ü@*pÇnó¾r­æ.ca?�rœbüÌPDÙ‰¼®ÊÛ´î΋5ìnÉé_;8é':šçÇŸj\4sÛ¥À;[ÄìøøLÉBn�ûµj÷C«Ë³ÇiÑA¢«êF}ŽÓŒÆI&BÇãR´«ZcFoYx}̺‡ù>ƒ×ÞA Œ“E—ö‚†•�ÊCIè&¬þõRΦ—ç86ˆ¶S£÷ß/¿šYKûÊ0h8Ü/„ˆ,%Ïòõ1°Ì�³¡a�°yÓçiþŒ3ý¯R â(¨í G²â³«©C±PÙ‚ÌÍK“|^£$KÄÝ+èysàIØ)y}ááìØ1w˜Îܱ ÍäëžáH¼EŽË()ÜKx&˜“±ÖÙì†'›ýÄ„O]w�»,ª¨çˆ}Ff(#Ô±ñ•wöäøæ´_Õ¯Yƒ/y™�Q÷X°£AmIL{B,Œ@�rûÏ.7lòÁƈq»ÐQ~KâÞY¡¹¤Šta÷á ì© fð‹ZåM#¤à¾ux×ñÊ3dáöŠ#ßC–ÍíLM\~ذÆb ±œäCëš0ÙŒ‹mݵ;BCMÔ!ÌN4ÖûVñ µ’ª^»ßÑdI¢(看a~jÄIAëPà¡99"²Õ!&¹0×#©‘^­"™F³‚ŸIŸ™´�Š’ózSS·=àäD9“i(KøU{šA%=É8Rïò*¬ÂC±2€ªÁÎÈ(¹AôÄ-uB¥½yô«§eÊ!�þÏc«À„•ï1š‡ÉM>Íüáój�³3DdþQÖ'{:õ,þßþÞ}|.}L‡fëO+uÐ�h!ΕæÜ qŸvJö{à˪õÆ·g ÂÂgì¤VEu?ÅPÇöÝûï…-i,äO™¡4ΰÿáaÒ�ÆV.o묿X²"ìqÅŸÃ=^LEŠä —!-£4£Ðçâ FÃx[‰�[Ód·Ð�7î¡È&.5þD|ê¾ádµûSã­½XĶdÐ÷MîÖ±ã¯$;zÕº7ÖuëJ}ØD\Ð!û8èÄ8ZöŒA"iÜÒ¹Gò—…"–‚§�‚°µ.ï9áiM3H8žÝ­ä»ó3!®ÏxbfO •XczÆ·ÀˆTa)ûƒ`§D�ö”!-‡wCûëÿu�j•RWµ·�@J9ôè¹F¤‘6†ÎÒJÖš*O,“ŠÞ{7$F«±éyEpÝSÉ™G¢ä8]˜pDÂç}år¨³a<æÐ#³–ŒXWšÒt¡1atÜ�Ú”xV :csRVe�â;ÉÉ݇ªÍ™5¦äî¨&^BìÖñ�6üßo±]ÌqcAXn:¸'-uäî ]J¿ñ­(ÿ(FÏù¯Ýø`õe„÷YÉÚ¼`åÚ_ÀÛŒÑk!%¡WxPñ㈉l¸÷Þûœ» £»–ø.¶²–žÈ%°�Šå˜L^Á²×è?¡$›Ôþþ/$/8 RnÖ É(D€Œ³u:,WØPöæŠxsÆ5_y0ó§’ó’%)PžèbM’E°2mN#À\ÉþüŒ˜ OÐ⃲‚î±°‘™Ìâ1W›Á)èŠëF߸èì|ê‘Q»>Ë.¾…â)[Ô ùß É¢öÅ!Ú*'¤ªþ›óºúCéË*ª™·ì$ Ûüάc Á�× K&½M;~aª!Z@¨|þ/ˆ©ÎT;ÛÎú¸sxQåƒÔ3ÔE¦‰æ» “™¬¢5!ˆ4;óFÏÄѽ˜Ažå`šÇ¥@oW/÷u…ô¡£ÓBbÐ CJ:« "Ý�JÃÈî7ÙÄ#ûr!Æ©³l`‹n>á×¼Ž{äÁÿ~�6Ô‘k$”£Ù�Ñ·ƒ¸¤*ÓøÉã&s÷ TYT•™¹ØZ~EaZ­u ‡^»$wë–C¦{Q¥À‡g½”×øzR-‘º¸Ï¿‘ÙÏÿuÕ} � ŒÌyøˆäwu… þÕ½²ðtÓ×u]•al?ëÐñ~II›³¼´~Á°€TZ"Æ¥Ö¼îÄ·ÿÉYßÒüUò6]Îkq"œ±1†’µ{K$ ÛÞR�X%Ë®ëy¦¼ÙÈ©T‘ÿ0”Ëjåë’ª°®¿‘Â…l8¤ )ôDLoM¯H¶w1\ÐqqfÑNiÏS‹onVG­¹šÖVðL–ØÐžŒî‚8e[ñè&| …Ϩ,ã¶i)©}F²éš…ãê‹4¶é�™ºRXê"m¯­6ÚA $ýnÛÝ�&©cZÇÐãrüó¤ù9Ö…n¿)éÜ^„bŸxH½œâßOžÐi@Å¿®q�hn«ÎzB±Z탱 ÊÄæ¬ñ�ÄËSŠx@$èAÕvhô‚ oÃæpT?j¢°H½¨ŽÅ]¢'~Ñ*€7h˜myÌK)&×§�RÙ»ó8ïâRxtV+aê®’îYafbH—´Í•Oƈ銒V�îXô3»ÇuÅy؇aˆõ'L92ý»X‘!¸£Þà î”JÍ·ŽzE H5‚L5‹âRf§XŠ( +5,»—Ó°l¹¬›!p}^ÒãVàAœÊåóÔ°mòËo!.fnD&ˆ‚´ó3äŽHuÿ/'ŸÌZ›r Ôr= ¿(ÍB9?½Ïµx¬§QËH¯?ÖXñµAëÃèt¸Š.I®´&¸ÀÂÙŒúÇì0‰ŸgtÎ^å7uБ,qéñSO³zKõT'Šu‰xÒ#aºŽªZ8*¿wwùŰ=¸@Éüx³(‘—·K–Nw]üÙ™ìüÄïÂÁÒé\©ùþ°ÔÆ8¯®ë %ÓÕeä)‡Ý­% f溥®Ò7IYahlH™¨€p7xZ@'¡… °ð“9xý1Q«Aî; nõ/ãf©mj¡ìÖ�íÖl$»SÒ“xx¾Â7-Bú¸Ä'ÂÉ+­ÙY�iÂÍç¼L§Ü8{/qì:Ù­Gþõ2‰ØåßkÄ­ø-—}€ÌX¥²Øq'€]‡ù[…áÒLí0øæ½ƒÔÀ‰Ñy"<@yð¡XK›£AÛ)¼ÉŸìj€-Ø?\‡P™-F‰>=‚ƒ5J«Ò>ìÀ¢KFׂø4Œé´©­óò>E ‡/Y¥qìÎo(‡ïÞ}0ô•´ÚÝŽ9;� Á#gg+G¿OCB4!6Û-ûZ¨�+�bïèâ•`îßâ�ÉŽ­ûÃáÓ'äÄúÕEqû!P�’kÕãÄöãµ§(XWÉæW8ÎÒ³,uF„g³›TîA¯x^Ù¯$�³v�Š·=š8,1~’¨ŸM-VXS±[ŽI¹` &.¤ïfr¥F²Áúµ<•ÈVÇiØ ì�0Cv꤫‚튷e(üèìñŒ5ÈBdpëºgŠ+š¢ôÕfoy„pÍO[æJ0¥h¢yJ}Þlj]ucãs„‰8qµæE�-<ɲ»¡Ö!¨báö†z¥n€‡§Ø·¶\­þñ ¿ ©É8 Zþ–üìZcÊ2j÷R¼ô4m¢TAËÂ5ÈY¥'ˤŸ.»ÊÖ>§³oFEgò—’ý ýé�»c7òhÖÐî55É·Ìr#ÝÑ Ë XDö¾åB¾Ö–§¢I÷ý<`³Ç†4:™°lSžQm�„šUõ‰´�^=À±Ãq("ßA�?üî)0×G!ºâ•ÊþõêÑ�Þº a�'d­ÕÉq}Ê@x(MÐÑØ#¸kq,Õ�Çüƒcˆ.ܲÿŠ£d™VyÀJ Ÿk5”Ù®¿~4=(#óÙ1„H8îš o¬bDÜ_m²à‰x£~(öC{êb‚l‘·1,0,¯ÄÒ²6�ª<ÚUíl—�”�{³emÃͳ-½TÂl}„ëÌÖ q„8í*ÞT¹ñíGk�æAÊ_k:£¤UΤýfu:¢®—:EÇ ¬-ˆÌ“)4"|Û­,£¸ÛÈ@'äL!5üo+¿�NzaÖB™(:Yäà¿ *gÉÐÐÂöd�9[=üIH=;$-°�¼QAÑ–Qñåü‹)@�I´"âÏ=)oâˆp�Ï¿ïM©ÑC¦ž§Òg…S“o¯[—Š˜²+7qÐM ©|áv1[�†@F¨[ÛQVâ,IsßÜ�póà5æxœ¬BFo¡p‹ÉƒÞ‘éõ„È·7�nWyÜ–jÖÅÎ.H‘æ‘;U� îQÒóÒ_«o‹­ëµ–’ü yÿÞÜ�S×S+ð¿|Ði&>BG[ÜÕÄUjln?‹5.ð#‰aN”΢ã[x"n{tÊ£¯U‹%“ĹоÞ÷jÂÞr+èÌFCn‰ÜÝÿn¯i�´= $Êm©ìTÎC€(ê’ø >í­hN¢°²uBåçx5EŒ½ˆôªËt$è®Ó”ƒ2GpÈ*@VØHôkåS‚Øã²33«Ý„eí�‹á7¿ý•sº�©E�ònÚ\4 Å’M½=æoÒŒs/öJ7‹0³‘8¶üáUŸª6ÁááÓ„–yœÁž„Åm›Šœ 9í–P8Yûùq°þ¬¢m•8¸4rÝ¥xÿ¶TbºRJ,Šê‰ßgK'GÃʶ]×ê%×3ÑÁš§´ê±7SŸ4 ž…íŵâð÷tÓnòwpbS®Y\X¤T0.{J÷<뮄’e,Úk@”úmŠ�À²AWžR’�&¢vÞ�¶|�iLƒ"¹is47ü¸ªX«R}Ë>µ´ª?z#õ¶ô^@·Ždu% æûiÍ:¦?@üÍ0ˆŸ*§ÝÀU_8;४†‡.7}p]ˆÃ0ÄMœ.c—ÑÜ~0ÀÃÕ+sVê…ÁA¥Á{ʘÖ+‘ü¼£l=Ø ÍÙ6ûGHož÷ø¹_r]gˆÅ0'uïA&}½,F/aðÌJ²¢ÿãyhAû¶*èlR½ä·½»„:õá“ùƒjìz‚¿­Ø]×`_� \‹Xº8ßE¦,‹È¾'sº™5M$_Þ»´Ú¤ü-äÆŸÜ’¶p—¥|@*˜LF£µ$£¤ó~X¯Þ�Yé»@ðI¸e”û:ëîÄïÚvX�ظ�:ŠKSïù2åñaÿª¢èü¬z}t¾´íÐïNÓ.(ž(‘ÜR]–a�uñýÂÃκ:«Ò=¿ï{…Þá÷Ö4Žw�ïŠè^ï’ žÎ'Ìkf±á…>]ûhz�ê‘ÇoÀªW/g¬\ 嘃’ ÷9YB—!8s9:¯²_çÀ8+Và¯-ktµDÈA/‹öBµã)Dc«Î†»}{ÒR‘Á `ÙvIJ¥èºÇìÙk<.úbþ2š¿9J÷î�"ýÒ›\UàÒÏú¨%€"#Ø^J«ñ í(#¯+öÔ¼Ï64^¡-t‚1СÏ6Âo�1_@éRmq2:—�eþEû/{’9ƒ)z’›NYå{¸ÞðªÿÒ†ëeÃ) %Û›FA¥³^s½ÕþCÞ¾îßéë›ë•-\{µÆæÇÎ]"r=¿•õðJ^/õ9kº2?V>ŠÒ�lNÄ�EѼ9Üû‹�ŦÑVò¦å# Áè-´ùû}€f>)Ì$øPÀ‡üí |×”-#nrîBài¥ªéx³ ýG:û�Ÿ­F˜Ü>­‚}É¿gO:ýfF¢ ¾V%¶œO˜ôàKl šjÈo‡*ÏÈŸ—�—hâ¯h‚ÁY˃JpG‚7iuÞçÒÐÖë ·HirsƒÁ5Ô‰5‚§llOXápY¥/K÷&ò™ïŒjЬm}N»„­j¶ÐÜ Ø~Ýl³ýkÔ?ô˜$ÛþüÄp×t7šë¤#ý´¹?&P8Œ·ê�a7ed •�Kàç{:ž"õ{ææiÅ Pwo�¯ø�-�æ r½ÛQŽ´?ص‹½âµïàK=w㻿h6H(}cKѯðÉŲ8§á11Ϥ/'&¬4‚ˆÝ¹ìq‚5 ÒÕQW,Iq¥FÜ�x�æòJ·&1À,ËvˆÑ)añrTÌ¢äÛ×f¢„¬$ngÈ‹ñT¶»¬ÛzÑ$:è8Çl‰ù­>ùĉñj#qm¿Î¦ÿ¥[K�¼D›!õHRdz3YÝbþùP–RÌŒâî§ù ý§ó¼P€+Þô"ÓOQýß9íô‡ðÃø£€94ç·#CÄ’ y`0 ”Guɦ\G^hAdZôav. ÞÞ˜g 3�ÅçT[ûk¼üE:?ýø{ÑÍ3Ñ¢Ùq¬ðO÷V£Öc숑ß)uW­\ªŒGÆ0 Ús4CE?0ZºÁrhfµÖÅÛžä™X˜¥O“r`§Wg¶Ü› Æ,T Ïzöe±;4”ùœ_@GÚmOðˆïDÛ·ÀÂŽ?«�ÉòÈåy GòNb�VW`7Ú /?vá&‚ zÁ—ÙŸpö�#‘‚¦9Ý¥ìÔ±kD� ƒ×äY7ÝëüéQ( ߀þªFѹÚ=Oéäý!#p@VBEÕo÷Ò†©ÊþôYìäÌÓ³KÌTbEÂ×ÏG7Ê 2ãN…!k¬hw+Q`ÊÎTÅ¡ í©cOßyœà\‘•Ñûzëu{à>ýßH¶$»A…h1þß±Z¢Ö´ŸÅå¡Â¨·•¿Æ·Ho«š‚ÉÓ…z½�>2 -[a: 3Vriʪ£Øóq›_ø€˜NºýdÑ›ÓÚ�LôÛï"ð&žÈ  Ëå(àáaVa4@ÉYíÁæÔz „ö´`“�CBnOÀ$c+G{ó /ß1+)OåS ƒ1�{:âŒmäÙo‚kl®í0n¶™¾¨¦õÆÿg {Æê«PB®2r³ƒwè$Û‹v÷v+¼5¬nþãõrÊsº‘kÙ;öŽRõ¢l¬¦áq+F¬‘v]$6=�U¾¾¾0ŸHïåHÊŠÌ.8¼<ôîì蔉'f‹}èm·3Þ.¤SÎ8²ãdd°:ø‡Ö P%HcGêµ%ÄdUý¶“b™>õÄcw— êpP[ ÃëÝG?¿Ñí)¡Ô|€úñº8f/œDÄ&çñ¾¸þ5´‘.? ổ48øfHnãPб¥¯ÉûGUéPç’b¿cñ˜Hô$÷ÕG 4~CÈàç¼ä„öøàÇœ¬G?š0ÊZ¨_qEGùÖ»Búb‚˜'Ùþë\¬ØÇ—ƒ§Ñu^åŒE×°ð6·úW–lÛù[1@©#žÃ ‘ùF/‡?º¶£uHWçY'ôtŠÞNó^ÇÀW1ÖŸîŒAô0�s ]ÞΘõïxQµ1ÔÖT'I^Ã*iÞv»HIÆ&Wi)"Ä„8mÅçn.>¡b ¶î3ò£’e‹h2Ûwi|R>´ï8>Z~,]A& Ä+ÈU­„ÆõŽ÷…B¨Ï9ãð’Ï�~DS¡¦%AèFbg÷ Èdrð°U<´ ÈàBF ó×õŽmÓÊuò犰©úÆÌŸHZp$† d’`2¯)#…$VÆÜY`; ¬R¿rH†kóËé<^¨· I€—×Ðz;P>‘K9r'¥`œ.Î$™Îfà_¿wà':LG$ôÚ QlnW�¼ÁrQÈSp¡×—Ÿ#!›TÚ26ˆ.öEø@si,æ^$Èòà¨O›¼ªÎ~Î' /-›‘a]› csàü»D~=/Ëe¼«®á„n„’ð Jâ?þ{u©å¥+Û.gbgÀ¥KÝÛãSëøO>Ûãê äÜV]P°£¹“a7Öñ@¥u€wBzÝ1£Ó ­sÞ¨q‰ª±…u¦±îßRÙ²UVqkÎnßW¡a¢ÊªŒ+)maØ<)®‘Ž"á5–�®õ�hº_잨JXíƒ0öŽ Xe™p7p¼–À×@–@uaYY¨²`4B#Êw¨´Èˆo¹óæÃ$uZù{{³|޶8àqËS²ÁÈo«Æ æäL]êÿÚ‹1£‹ _©�‡µ¹µ(z:—Ù.ŒÄ˜à×—õ%jâ¨��É­?Ÿ"Ã\X©~îØÀÿÚ}C¢Öš€=n+¢®´ìóÚ…œ¡âþR”É9$·üL&¹ÛÃX9­æ¾=ÏçHõÊÜ`„”älþ¬\7µ€cé]ÖjrzoÜ8?ü¼zBÃñXÍ‚�Ëúv‹Qå÷/†Y鄉¹Ù$³{Ÿz)£âÆÜƒEŽ#èzâ…¾!ÄÖ?²¥�P’rKÙ´œf;[ ?�iÓL,“PFƒ·³-°f,ršD¨žêT"I@ß2 •ÈŽó°Î©ßó¬åñùOLŽgsù˜ƒo.ÍŠ<ÌQº ÍU³>Wà W°\£ñkÛr=~Â’ä`h3³C¹ÚÔÛD×ߢ²£$´eÎ~ �«•¤0Qs…·fta¯÷s�­„å³l;o�R]ë<�HÈØ]’ šµb0–&áv}É+B(üþÏ1ƒ)hÔMVéÌ‚c´‡�Q³“—rg˜®8OÓïcïOøHN‰À?¿-—©TA{ÀYi‘w Õ^fÇdPb³ÎËY9 4ÕtÑÜÑñ[4°&ÅÃbzÙ>U!û'”Ý›"rÍÿò.¾€z¶=?UmòÐÍ´ äŠííH*y1_2@€ÞÍj Í�Þ¢€Ns$FÚpC ôsR�´·¡¡ksÜ;„]Yj¶lsäÌX®fíÜc�a¢ú ‚º<ÈÂ;¢û~¦ÐGMj ôª’ÇX %Výôס†pa?#ƒËY‹Ì¡z]ë±0Yn¹M:}½n õ V´g™ïP^ý›D…»›âå¤hô̼ý‡¡Î5ýI¢êyJ÷V˜èñ8Y¹OÜÞ‘£-}š9|ýqòûS‡ÙzDÉCþ*ÂΖ˜Îü�.R‘Ç4z8E!ûí¶@W80ú£øîÚ0͇À½‚´ÿ(iƒ4¿ Œõš×•FSýçÈÔKú‡ãrªg@&t[ˆóemä}þc „îEQc,ÜB9`!ŠU`ÿŽ�>âǯZ5Si0][Ð^²¡›¡màòû“ÓGÚö{¦ìÏíD<Þy<¯hŒ‘”öèÅ|uÈ6ÌNÑëÂ:ý­5hÛsмäÙY7±ž¦(U›?U.{ÿÓ¡ë󋫺°«dšß<\"‰Ï–ðosº¾Ý)¼1Âk¶çtJ<à_™åöBI¾wæ¢bÎ5·Za/Ö}�0 ±^êD�J�±Æœ#`L~ Ƴ*èYÛ;ì°Ë]¥ê YΌھš8 Ì÷–r§°5hŒ 'ü Ñ ~øý êQåÍ]Ù¥*°ÁSB0‡ÓÀ-`òãg9« oÆÚµ±\ÄKÀƒ�;z1kƒV;¾Ô Ì1.7¹4Ìjèz’#2ƒÏ>÷³z@ëÆa[ÃéWœ»ÖáÒåè[hÅ�ÒðG1î“ §¶Ã–êÖ¿ÑÆKxØ �Lt~Šibâ�ákK¶ÀÆaJ7‚#Z¾„§9&aðîÇDœfÃM�Ò^Ã0Œ!îžË‰#õô1¼è­c>¦NNŸŠ#ð¸÷,<_BöJ}¨�ÿŤ»h)U#Ðò•Z<›âëüÉ,˜ H1 4B^‹³ìJíù´GÁ29$�üŒëBÒ´ ºÔ¼)WdhÖÁ Y,)F_€¼’Ÿð)Iª Tõz·´”®ŸxiYºÖÁô%­wŠ÷@U€Ö3Št Ø5fLv£Ÿ™Ø¸50⟠ ¹Ó8AùJ)|‹+5Dä+Qfe_ãFårb2‡2‘öK�V81EÉÒ*Ùé£L<×õ�xLq–û™›<¶y‘׊†RzP¯¬ÊŒ–'K ø±›võw6•Ù¹_r¨þ®µ´I•MGêÞl¡Ø¬™Iî(‹SZO>Åt=ÏÜûAƒe¦öA·ö1)ž#¥J+RÓeR8`ßãë™:«{ùðË âfçË�ÛâF ñ�<öuɱa€Kœ©›Æ=êŸàtÅÒyqùpb<{› `gÉ·TÁÆ|ä+àI™ùO#´¾RÆ\4Ë U¤²éx}²ÊÊÆœ�•…žµe}ãi^FºH޳xïú‹ù™6ºï"ﲜ“L境…hdOÉþ–—‰�¯ø]÷­xµÿ”ÖÓ9Ë 9Íù N°X/Ù†ƒŽXhט¥÷íÁÁ/}"”Ý.ù(n%WŽÚ߸÷î§”;¬ˆ�Á¢_H”§;Dȶ.‹ç.ÜCe.©–(¤_~È)óÛÌûÖ› AÒPÑÅjûgÀ("ýÞ R¸%²Ÿ}«‰”ã*qòaÁN�´§J¾ïDÄ–ˆØ}Zõ‚¦;@ß:÷úH‚û„¼lêä—øúÅž+â\iÊ÷=JIªÌêvbRÊÜÝ„©žRF=Tÿpo[A4€QšÊhÆYO�O"i7·$b)€ÑŽ£$Õ Þ†dï› ;¤îR×ß'›òæ@E¡@¤sÿDõ Ü5Øä qIò:£;`Öt~ñPpù�ËŽâ#žc¤V²n„aœËM%6û€¥/ãá{ײ}CÀq ;EzêòÍÖ‡7‹Ãaw¥™”•ûÅ£ÙŸp] âRà^ž¢Ž¯E ôŒ¾"%ž�ÙClºâ¾6�º)a Ì÷©�úëHGIê—¹v1äÎÝs±±óœÚ Jº]ÿ6(©oRINÏZÁÞAˆŒº|zPoã²fê©`Šéå§: épðV˜'iöæ·ý�”ë´�ÔÏ‹T›“èŒ^Œs«Ó!ü9Üt¤ò `·©wQö ‘€Š'±xƒê©ÇV$?a˜„àWG­ÙŠÜÒ²nÑ)né{«2�é§¹t—‡êøR¥˜ÂÐ{&Ùmûß#ÕùÖ#p‹:�[¼¼€#E¡/ÚðŒ[yY±’‡F‹%Þ5ó8k73c´+-–ØSP?qG¿»Y7rY¥†�| ®“² c85ï/öj¿�ŠU×ܼDÓÜc)þ˨þÆ0zwªÿdQü Ú2íƒE¸<ÁÂØ�Iìø÷qœ’¯ŒñKkGA¥]‹6êç\ƒÑÂòéÏ·i‡N†c/˜*W|ágH†O��(…(¦îÕklWÐnÄ”6IÒÎÞfy‰Ñâ² ÛÄyÝ€'jŒ*¤*Ãþ+ÁÖ W³;A�Ñ[ð¶ãГL…l@9b-¶ÃŒi;IÃo^ÞÆt9SŸŠCm*Øpõ½§º:+¢—™Õ=!9Ap »;bLC ¬‡Ñ08½•iîøÐ¹£6Òm„UãØìŸ­¬ÝQ¡ÐÈËU£W Î}†nÔÙ‚µÛų´E¦y®Ÿ%Wzz¸åZ6D=æ`¬. ˰Z ×�¸QЕê<„?§(ÌK²ow¯êŠ·¸*²yàé#;ŸìuˆÉ}–Vä~�Š€W–zMWwX˜ ºXb§oÎHæzîi÷f/é†÷é|aê< ¢ßàæ¬Ín¢Õ¼¿/�š^§×#-ù§æb 5Ûû2îJEUðŒX_‰Ç<1Õ%>ï¨Ö&`;ë¶<øÈi=_›™ç*Ü\¿ƒªµ )Ý«ò"qpØ}Hb-BYé³/þ&ºQÉÖL%Œ1kÈå›Ä¼£Õs¾Àg$ÓäYA¶Ä%KåmŠØ6^{w|¦ìÅÔ·¸Ø©O2¿Ã~Â4l·ˆdv�÷~­| ÌU(&Ù»'?6O?šF×Ý­ä*FA>l÷’cÈ$_Öï+Ô•ðrµtQGêžäÖ†çy‹™œ°HS? Ø º¯úÌßÜE@öódìC§gÕ«7æžu‡(Ø¿RÚ CvûŠc-¢Ñáø×}i÷³GÞ}¢Òê–Úíòœ#L\†óÁÛ]Hr”Cá—–7úõGü õpù�X�ihè‘ïóÔ“Gà (¬ÉUÔ’òa„Ë¢¢Òè¡�íÈj‘’“·hÏ©^/ƒh›¡ŠÄ® Qyïzl6‡nEºÕ¿Jê@æ¢o.#˜íy³Tx5¤‹yû�¦ÐÃÁèé{™ˆ'�áÞׇ†ããê ç–·~�¼{!-æââmÒ=`¸üïE70ý¹Hn²‚ø:ã8Œºìûœwz±Ýú=…j7õ¢ÈCEM¨Œ5ƒÂÕmßÛ ›c�Í,¾æ—W�€º_,aª"›á*§°Sµ;¿ùë�òw¸q}°¢‰¢¿ñªBdüŸ†3lâ›,‰×R|t@þ%Gâbøxɧùâ¡à¡9þú�â8iµ²;±?ºâª�ÿY¢«$Ï™ß?wpxMR¼Žç¹HÛ7&-P(yÃwN·³� tÂ4Ãx¾"U <9³×{Oµ³ußĈ‰:oS¨ý–¨úŠ"ì¢} ILüXÅPà¼ïCçúG=òƒò+ã»ts½øßDÔH~È“@ƒŒòœ å)FÜékG'ò•~ˆ £Õ)¡éj¤Yytø''Fiz'ÎÃ=3_^Ä€"s�id�ê^¿ßÛSØÉÙôÂ4„¸—šÿº˜Mãe“Ï ¶à»¼.œ]ÿÏã¤O�`ŠõJö^Y\²2sÜAª®‘*Z&‰QA\°ÄPÝÆALÖž¡Óqï‰út+Mñ˜+h¶�½RCì1Ån•’=G©¾ÓU¦ðöü¯óÎ�—�"¹uY_äL`‰÷HÚÌ•„jóÈ3«r–#@ì¿Yþ®�;†»è�zÒnAäÌ,¡Øq¼á•v-�›‘ûzCØäÌv¾Úæûμ®pbm!ÿ¿ü)¢ï®öÄâ{wõ3w<`j_ì<¼ù›Z„úv›ó¡añYSHµß+T+T Ÿ‚Ã� Ì$ÝK×o«Á+¶[p½-¿¬ºœÇŸ�üðôC‚2NäŒúljVO¯ÿ®«ù÷¶(eƒU 9dCá:œ®#”·¶”NFüÄ" ¶T‡˜ I Eq2�íd Ä (›�ƒ§úK“�õ�QF²XáEè‹€ê¤÷@´;o_壷0á‹RS˜“¥êfêù'%a Ïc¸?´Û§ Ø®‰JÜVí´Lé <Þ¤hƒÆÃN½�N R‰r©µ¿ ÎzÏ1 p«¹Z �˜D“FS+¿Ù·íß­áŠî@±†¯Ö0²Ïþ$n&X•å’måè^zoy«Ù3DÅ+« GGâ—h!*³E泉b/f­ü‡sôkŽßwH‡„ E“#Š/ôH5˜�U‰eæaF9LØ›ñ»Ñî7Z§WÀîÝDë”-£O+uf~¸/°š ÷�Ô®ãµø6§Üî�#ªè²ŒY}Q¢©¤­æx :œz^ð:¤Äû °µàˆž®!ùºb�@fu6€Z[Ö‡ õÈ¢°&”g´”�zrix½ÎQ¶íHgšš~Cl£õ51&$ĸ¿.Ä kûn˜ÐŽOMv'¥ñ#nøofÅtÑ+wAŽÈÌ•EÝ>šˆ�ïfìÞÿ�ýóF]¬_þ)fôù¢ýº`œßt¸TÞëew}ä3I´í [¬U¶ß:Å&P²?2þÉ�¤íÒó_—jËÉ¢80­¡ÂXnIï•ÊR¼2ˆÐpqûòø…LZYíú \â-Øfõ¢²¶ì+û šø/½ÊÖå|&"mסi+À  ôéA›¤8á{?ñ8Öö·Q{iúŒ1Øzk5ÜgÑ�h$¢!-hº:Pºx.¹_RHC¥$& wa&¶x†ðÓKô—‡zPÀOcäÝô"1‹ùí9f�‰\ g®aJ ûç#™ 4�¦Í …Œ¬Fz,‚ß}—s=‚û>Ò2`=¶�4Â{î¤ ¼Š›ÉÐ*ïñ(*òXÄÆúß‚‡xC“!ý7ö ëJF3Æ.Iȃ4TÜM))ØdŽ‘ýºô Õ6”‘àáÞ<ó`•Œâ§4¤>Nò A”`”“ÄD˜s$ùE®k‹�¤¯Op�N”êO #xBá/6W­Õº;@¥aÅõ™’H*îv¦Ô�&õM�u ¡¥\šÓøDi‹)ç�@i3 ÿq¥NX:Š'd½ {ã7«œ»È¥;ù\J5nü‘L¨Í¯ÇWz ó{Êv9ˆr¼û£Åuj/¶û¦MÇw�­= ¹ûŒå¨TúšíX¡S¶E˱š ñËÜ"£ƒm¹0»žYârÏ/ÇðãÄ�©½ *;ƒØO9PŒú•Z8ð4tw|=¬E͸¶´ÒCa õ:ÅùªÎÔô©¾†Å®ÛŒ8! Õm)Û?P*ÜnFµ,µà˜�p•M€Ÿiú§�ý‚�|µ4°àâöîªüjûôv¦›³š8p/¬  ’Êj¥À;‚Ó;ÒO çñR§ÉUÄëØØªÿVé$Gq­™B¯p”rSMc¥û]HÞš27r™3Í µ‰kᾌ;ÙÌl†¸é…_ÌL>{ÊtO7vø?m 2»çÿìÈ1A�k~BA–U¯:ÝÔMX‚�  ïÞÅåÊ®úõGâ'lw<÷•_g˜•j~P›úô]Ž0%¡ Ÿú‚,ƒJ›2(ÌdÕÜ0k�Œï7@A~$EîÒ.&ÊuÝû2�óÕà öÅ4¹K]É£ªˆïM‚ìx·Ý�Ýë9ú%0@Õéo/{ §òEFQ_7˜Vo5(S?é_…½ôKÑf‡¹9�BJäëÇÝYÆ(÷³ÏxS)º£¬—ù/a±²ƒä�¦G+ÉbèÚx²Ž-JŠå¿� ë4ÒÔ‚Ì ýW‹‚m%Š øýgøXᩌDñÕ…Y†ÁÅ_qs1Iìˆ/M©(ðØËÛPÕ×ϸ GäAɬ¸°ä±®UÊO¸µ ŠEêü°Cú®]žiiú6ä�¿JøÎó´Nsí_šíóÌ{ÔäñtD¤gÞn˜ËåÂ>¦€<ÜüÓ†Ú«Ñ?ƒáѦ¡ÓÇBé¾½nè†)3á“dÒ§Këý�Ü]ˆ5ºšP+¹ò…V—¡gsq3qæê‚uý%Ë h¸¨þ|6fq0¦ÉÁšw$ÉÊ­Ãì/Sn›sS ÍJ¤Š;ÆýS>®0®O¯¶C€UHîá]•0Ò´¡%J§–»ð3ÃF­GêÌ+c]ã`·WR)φ©ŽX :cZ‹L½¿¢ Ñ¿r”NÃui­Óµ1ž¢›thØB±š§ÝÅ^<1,W„YaJp22hÐÃ4�Mô²Z«+Ö“ ¹ÞYwZ¶ò{7‰ÈoÞ†±§�­Î—¥€%°�Ÿ"‰­’]}³×ÕíÖ·Š�à‹Å&#PÓõ<ÍÄÔ­„X�^-}ˆ®!%u©7ʘξ([–n¥Þ�VèDenVöÑÚS’É +&I<Ž&ô×j4+éÄ dÊöÑ/ÿ4ÊNDF6öd)Ïß§²*1�äu Ç^È“e¡ƒO¯ÞS¿Ý§•Lc|sŬ;!£#½]Z F¬!@‡ŒSsÔ ß.VQO/VpTÔEëeL5Þe7>P8¾§¬O‚¿_Õ«Gêü1ÑóiBæKôr¦Üý=5T­šf‘ΚEqŸyÔ-–C뜊'1%}³ qXý€eƳ»'Mƒ�mzÅSJ¨|ÐG"7ß‚óVP?—=• /ý¼0X1 Q]LŸSuKæ’Z[Ã-UozXd^ü/z.nEXe“cÈ£ 5¨:P.þ`"�îùœléæm‡ü”Ë›6KGåõëIR0ó%’G±ìÜÙÉi×+Ë Oì�í�×ÐK®™ö6v�ƒ»#ÏÐw}V�§ý.s‰ËzÁ8Û.Ðë4jK´`˜`œw÷±Æ¡ mÆ –ñÛÓÙ dÑ·®>à>æW×?-ñ#:9>ÑŸÿˆ›‰üÖø4§)§=”e"̸LêÛ&¥@� pÃVéi�o”•VámßpD©¼Ó šú‹OÐÆ]º¥=¾knVc² ‡4Ð úfŸ‹’ºWhÔû³ÊÕ0¾Ž¦®¸NÃ^æYåÚø+ìöÄP)ˆ•w¡_ˆQWFZ�G¿³õÎiAqEÒ¶æ„^ÅKºV%u¡¢°|å#‘Ãx¼'òÀh–žµ’Âøºq¦p^³‘~'dY{,óŒP�İ’8ôÕȾÆ6U>qï_˜)("4Jæ¿%øÊ¶GÛI‘ÁКÈyr|´²=ld¯Ü¡ôÈ`ï6é5Ä*~—iØ5äa”%sï"ò§{`ÖrH´†íê²³0 2n¡WŒ æ=‰KŠêY¼ùbœ¥Ç"iHXŠ! Iö&sœ»�q¸QÙèN€\©Ö9ÿ§8Ò…Qt[ÎT¾­R“zvTPn@\>%÷6*ÌU’åýÏKú¾<ÊlHmh�™¾êò/gqcgU)½Áw·Rñßs7Û5íZo<¬çè.9qZÌvÔ^~… G3ž#Kp2ŠÙò¸0.æÓ=¡‡{ÃwYG�]ˆTí�YtŸÚ$Ún`<Èí×àø×µ’,@ëemá‚j­@‰(�h_Z¾VøKÝSD"ª„KÓMÿ¸!C;ý’X‰'$ l¡N� ”Bü*³(k´ºç…„�.+c(þE÷äô ƒ»€xñ8ø]Ý'1˜âøû…ðS¬z…˜~n$}dk\80Y¤´EÀyŽÎÇÔð…ËKã°–0P“}¾~l#¸ÑE[lBóäH ´b”þkÕÓÌ-}~·n(i+qv b½—œØôËy[¯Ñ‡dQ$�#×ÊRì}&RÅósîⱃ_.!ôêXZ°XæÉ]×r[ò70ÖÃÄùí²^Z& ¸‹õÐm²sr}ÖÉúÙ,'$á» v_ãs5+"¸O‚HbŽýÑrÃ_ìxa†­HLBO¹…ª+P½äâA¯qYõQ4-Ý/>qßò^òZ/£,ÀÍ鉸Ùþb»v#=Lò{èšf^y>óÑ/?פ5bÞ$(uìýU BeF�Ãè;„šõ�WŸ‹€ü «Ö)–²ñúÕáØ|†ä›DÙǨ&—…1«£ä²�ðµ¼7¸ÎÝ1ò( 'Dî’Ž¾‰‹dµŠ‰¢N”mt§½M’©9•Ĥ(=ʦ¤ž˜ÿ#ç…þËÜÑ;äNyÄý4�1Å»çpZfll,"Ÿ6o±§‚h„ë`ª^•üUR�D*e+ða0Ù¶�¤šU1¶î€œ“…+'õàñ“„GVá“Ý|+†f@±;)™� ªŸ1µpL7t‹³ª[257š:Jۉї÷ù?E)3ógÞ}õ#Lj>8J[¬œ1ÖÀ �¶�mÁÌÝkŒê[)eÝ€³Z#~½!ž€¨Ã™ù¢å¤�Ü7g)Ú�¹%8Üڳ˳ÿþiu8QËÖà!ïËøïaW  ÖOqÑN¶á��³ b±ìZG”¹èËIt×ù²5uŽ÷òY¡ÅU[ˆï3O� y‡ôD7 þ:–2nEöd²³T€†‘ýéGyš/b�Ê<«#šLóÿiþ«j´ªõŸ¤à8X>ߘ)¿U¤xòâ5¸x~TE=|èS™¦%l çàßÜèû¥É0HûÂÐ}éo”­<7‡pÆøÇ�SXÙ ño¡ {ú*F3ЫX¯>ŽÓX"ôn�}À&Vˆ¾€ú6àê›Êûì hðhOOÚ\A�¥…ü7ôV`®=Cvñ(mŒŠ�—ŠÆS$ 2›+Å) ²°ž ×oÖæ.´½2.¾€d:PpL©*¤±«öµíþ¶Ô7Ë^Ø^úiü>> +f€t—ŠU]­¢÷WTÆ€\îâ§ôk¬*<ë45¦s~©OäÔ †F.J^×ut¨IUxÉÚj)A¢KXJ¼§$ZÞ9ø Ôt¹+êÕIÏÁ›g¨|ä�ùsXeé‘ÜŽÄnвÒ3Dø à¢Á¥v¸K²I „- «8¬¹,ÅÙè1Ì1Tø¿ÿ Ô^k‘ÊÜ+ŠÍe¸ÀMPÑ)œR!àtÏ.ÏÍÌzŸ¡|äó¿m~äoüæÌU$2L²ÞØæ @È»íAWT‡Jy÷Oßâað %Xƒ ?¸ú£‰¾¯Kè¢Ð÷ "VòÁæ)tà§<陥ýªœ´D"ÆÔ>èudŒ0«°o̘Tè¡F±ÜÁ©É )„RêŽ4ÑŽ\BòÔn5Añôr«Ï�{‹˜& ¾Á¸\²$êçA Í׋ÛM „²Ë¥ñnK}Ç�é{ãþݰAT¸lù¾Ïeëj¦Ê)ŽBz…�‹Ö$MÔͶ#çƒæ…³>1²>ÿªd€@ q ’É¢:†Ã ÷FÓÉÇ“ø6!½ï)È’ä“&Swe‹þ§!Èû�ѹÍ\@íÊ}n“h™r䘑ÝHÒʾ€îPʾлå×!Œ‡ôV`°J8¹—¶++… $ÀZ¾“/NX.øgž¤,.™i“”*ÞÅ�µ®v\ºŒì]¯‡sŒ© ·‹H žVoâ3ÔÞyua.n‚¢ndE„R�uMKÅØ!ÊfÒÒ™¾:€ÓøfÎâ8ƒŒŽ*|XðJzù…f©�uøIå.A]¾,"6ˆÌb ’H,II.| %£³`Tõ—6â ›êE(#ùÀ9BäÛ¯¸ÅÍV,"ò³|ÞÐY_âKãTþ~õ­ÉçÙZ0:c:®‚�‡iß·FšÚ\7€ûÌ‘y‹>þj}^ä«"&Åïÿµëâ×?ÙÍÎQL`Ùâ2;!(”–"¤%,×;uŽîÄ?® ŽîûP«•xq§Y˜“i½9Ÿx\"‘:ÑÓ-ªÙ:g¹‰*{·îPžÛ«”Æ.XT÷ÅÝæ!”г˜¿Yâ÷ô6gž¹¦ÙŒÌl¯,“4Ÿ~¿ˆB»‡- °»j%œ¦n9bDÝè(1CºA J•¥w¸�E^¡0“^di‹TNS¶ô gSXu™x:hÒB€¢µWE+â#Y^ÊvÈé¸->iˆ>ÛNZtä°Ïâá:x$ÑÌ­©2‘˜€”¨¤ä kß ]±\ ò®÷‰å´ U—'d¦P&^‘s5*›_=9õqF¸Ø‘šŒ”nÙ õ_ïLÕßôg7�Ç/¹��=ªË±‘ÚgäN¢ ‘~ÀàDö©Æ"Â^%Öý��k°´3÷ *Qªu“È=ްŒ0€�2jZ®,oJHd4Ò9É2cF‘íç¨ø¼[1:ØŒŒ¼öüb!X'`ã§U‡äpJ_Ç‚ÝMò ¬>Ó¯Ú³z=·~ãákäýû°j hÖÃ\ê¯d©�xIgˆJ*ëèÄUýáêmNÒAÄùYuo…ª÷ÀZÒ(Åo:›^ãã8©®[pŸ*% ­´Ô„*� ýwÓAP±#õ&™å2ÃÙ–þH�»ãš!…�>9Dø›®OTVW3–Z?ÇzšpŽÏ?‹žjí¹2(èÃÌEz�’rª)1˲6¦7Œýéªî~³‡ãLÈ«3 ãÈæ£Õ&?â&�+ðaqQ“’ºgÝÌUÒÞe¦n& { ¢Ì:£µ‡­ý³“‚Ò="šYûFJÚÃŽ¬sºÿ\£r,÷JËKšÉy:8õEÙä›Îï#IÂXˆäN†®¨hòÙÞõ|Æp�N-)[âÖãò¨½³PšÞýmeD>y|LFƒϒ…Ê”Ø{Ž*ºx]ÛÙLUM5ÞŽY%E&¿4âèhâŽU4U`ˆeìÖaÝyG%l†Ûì/OVÆ"3Ž7œ´—mreßc²æ±"æ§ '_ìhG ‘�SCÁKóX6ým�­\Þ‘UàQéø‹ÇeEq™’e*비;?´–ªº€cçšL kpœA¾8¹2tÍäA~fÔ'Iò‹×|µÙ(pG¨ß¾HUËIVr"9üo6¿QÐÝH*y`Àª *¾…ò¥sé=V¶yjøœ(zæÅ6‡|üîøA°\Mü暟(¸¢{¥’s‚|Ÿ5¬be¹õËjGïä$Þ—„ñ©‡6fšöËrˆ5!ÝÇFÊ“F®WÀŒ`ÙzWW/t§r„öiÊòŒQ«^Gƒœk—-“Ó3κFªHÛ«�Dw¦¬Â8YÊ�¶'¡d,«Fà΋š\«ÃÓrZ\<�¶°ŒÂ~‡öRÎÔKFCË›”$j¢YÌoSž7¸Ë|Ë+>™¹|•ŽÈži‹vKß÷,i?[!�Qu×â>¾Y"[^Þ*ßd&S÷_ïn_ŸTÓþÊ›�è>®ê|h‰f–Ž1(ŠÝþB&ïm½Ü0ýG}*HmÚËöOŒ ¯·ê´À~[´;ˆ-²¼+}®:'t¨gµíbîÛl�v߇8�ÀCL]˨MtÛ4¦Ð6¤~é(mú�…ÉÐ_ÊtvdÇuëS¬ÏËÅçr!9ê6�¯¨ʾåzë�ÚóÆ¥#Öù3R§R*kÛëC.ÁñAX–SC·­b't\é‘(-�yc3»{�8º°0¬ø¸¼ÝââLDP] Út¤lî¨"õ²`Ý Aöqà¤éOŸóBv %ÿÈØÔoE´©°ÖACP7¥)Ž@X„m8n°DûÞS~ú@q&û_fXc¦ÚdŽÑ:¶ãpüÑHpÍmXݽ§¼L‡ïähèâçÒ*æüh2Çe¢ì]@)K`º~›%ÆQƒwÞ¦Ž@‘Nü SÃõÎSëÑ [[ˆ.ÚŠ6[½@ÊóÑR©°àݬ™<®u§Æê\ƧÖ; ˜x\‹ó 7�F5j6òA›9™Ç�#�p?ç^¾ÝPíIý8Ñ‹‚ÊÈ6{› Ö?/£™¤¾ôšštžºËÂâ zqFbò8}÷òƒ»Ö*:¥†âÀÊãã KÒS™Î“–¢.0}…cúcS¨VÁJHW~fꛘ§EuÑ)ÙSÇñ3œ÷ÎÔðà‡ŸoK €¿­ß!õ,½¿Ù±ÏŠô%htWÕî >ŸhŠ‚ÿV8F��¸ðõùoÇ0ÚuĻҞê!ó3�RwžE+M¼ 8o¹Í«-+“ÄÓþD~5Óá¨ü“|¶Æ‰ôêgèFÖZë~uÉŽyÿ†úý]}Ðß1Nzz6e£T¡)‚øø@íXö w=_„÷ó€y^yu;„—Ó_õ‚š�5 “�Šå‚{M·•TZ/\ˆ�«€�ÈŠ“!(r¢XhL Ø‹p*_÷vWzÿpÅöžEíø2Œ›®#­dÁ´C®Ëö�Õu§ñ×AÊ»Æe'qÖœ á‹©íäwèà˜Ûª �hˆª‹RÛû :ŸjKÞk*‹žgŸÎ½©$û¥FM«�n«ozlN6ÜC'ë祑4d8é„i V³€qa÷Wn¬Öξ"±6"®,íÈ•°ºyoþðöû°& £¸¶°nŸÉꟹ㩕´áÑ·¸—1t)«C·Þ¼ |äcîð{iß1·�KÓrAû¶Ñ`ñáÏf!–Ò ‚'mû*;™G)&3ajÀÂÇÁë¯lYðœ²CÆÜÈcûlÒ£“Ú×ÓÛŒX[x—ó Ænâ…{5 k|q«£3LE…áOµXA[wa@ƒ“ˆÞb5wG= dd5“w�±äC«Ì‘SŽY8Ü—÷'ËlÃxɪ|.Îýmy,&¬n€¥þ�oæ5ç” ÛìWìúÅx9á•â*6¹°…Ž’FׇSó:„XjÊàjf]&}Æ"–)™a"IiñØþ¯-([úÆšb�þZT,³1@Ùr¬ðÈù‘Y×p—Vø²@gý‘ÈŠÅdät£Žk¥WéÄš3Û?Ÿ·ÆS³ �q4�”î¸:Ä‚ØõvûîôÞÕì,aïÌCáˆWiK#/‹Ÿo�½ÃÕ­V¨þìVÕa|¨'6½ên ¼F¡NÁ5»Ó±ó•Iƒg)§⸚árQ—a ¥ýHÔ¨Eµ›?&Äû»€|³K8peUÓO×ÊOqížkBá±JqÄèjÞ• �ž§ñÌÖœD^õOÎû¼±'�‹gÔ3ºÙ¦ÎMë7G¿<ÊÕ‡¨Ú èrø'—e¸†X?È8ß:U{tcÍ F²ßãöUál©nÙÒU ÁÈ™ë¨kYð=±á¥:;c�òl•— éøß™ÿùë¼~b^ ¯ (ì„~¯Vø™ÿ1ÏÐ?¶çœ-zë­gÇbòãy#'üåS}XYíšÚªø� %áÝ¡ŠíÅÃÖ‚-9=˜©S�fÎõ¶¶x‚š¼²ã'—úâ„oõ�«X›š/íåWý\K– È4˜){èÊÂÈA× ±µvï[ãw1”FÓvå}#”Y‡%Щ«´\�õh5 —úÎ{ i%|Òoëýq¢:fa¡8@ÂLÎò;`ºcè$úêf‡^2Ô9ª ÄfRØ‘kMRêëKÓRŒüLªemäg–OGÊ, ’…çý©~‘9$«{&o,�©^¹ ‰1GÇ¥9ºùU3åZþ `ïröÅ´�.yéÿRF‘®‘U[ ÒÞ ‘y@RÆêw$sªS¨&mCI½™Y%bóoݘ%»ù¼`É2ÞtìÖË,g탮iáæˆV½‚èAûÕk}ƒülA¦à#:{F}|ÿKÜZ\”M©ÛÁÐø§Nù¬`J,z X8}j»�z�8ìiåâl”¤Û›ÕÄ ¡—è gÄ�ÏÚÔ”Çt‘Þ*6E—CAèzP«‚Pr/P_ɼ±ö¤­š!M1Á�gwYaî«À?i Y!p2E¢µ÷ܾ^âµÎgoýÚÁ#ñ‚4lüùç yÄÈ‹ c½màu"BqíÛѰ´Æ Ãv`@Æñœt€aýƒžÞ�®K„0³�`Qò5µ”$±Éß%EÐÀ³�Î2ðУõjH>øö]áOh»Ø‡Hª7âë¹™8㦿ÎÄé#ïÑÂ{ÁIJ=Óñª¿¢ôpjUþáκ¾d¤#2\S-!£*ãî›ú�²/ƒÕ°e,5Ç0ÑK î‰á@á²MMG7…gdyÝÞoQÚ9äh–?•‰-Kaܯ@3lÚ ¯ ëÓ·K=‚ô#ÛðüA|‰õ€â æî4%ÆÂ‰òà Sæš,ÈÖ¬³&ýíþG“t&Ö¢†Ð¸=yP¶åoÖ,†5Ó«£=×�î»å1?9ÄŒ[Ëjg h ãúzËÈ(�":f¼ê>بa3ð” ð¨™]…¦Øô×ÚÝ«dw«òÅÖ„Ùa¥„ªïææ{ ?‘g£*ù J  ÷g¬­ “ÐÒm?X -��¨Ò&¬]‡ŠT\0 À®_•äûtŠ?ïUëŒ|®D”®Ïåk¶3DÐËãÖ± ÷~#>X)«×™ÿe œž´œ�°i!æ$¹}¹u÷ÜýBÕÚ/ñþ)±›½TˆZyCn,JN¨&ËŽ*h4=ALxd¶ék¡…˜ÌnwçcQQ šY. /`�sÓ"g‰ã¥Ñs-|¼ÐgFÀ–Šá%‚ݺXÇÜJše#ÏÜG˜róû&�¸.Ž„–ÃÎ p4µD±F³FÞ%?œZþ1û�“Ã\•…Ñ’5éHF�²ÅÜç�‹*ëÆº¢pߪ‘^S` êxH–Æ„)Ke`WiS€Ý²U)zõ#ô�9¥Püʼëoü±Þ‹¥à‚d„×#òþ0øÛáô ¡kÔ�ËnG,5&a/bÜzɧŠ3°‚7]‘囫ç!~®´ØÀ�Tω²ð}”ÛósZ€;ŽĵϗZ w3î¥Å—ЀnÑí›­aË0 /ƒ>°Ÿˆ°§¶±x{ÝØ�×#ÞúÒ Òk“rCì‘\÷�Å:jœÝàŽå~ib=IXÐJà.˜"_ |«'"|¢&ýHÊÝÆ%ÄF6DÎ+a} ’ì&p ¯;?‚®Ðº�];›+P kˆ Ç¼�h<\à cÞé6;$G׆Ä^·©K�$Û 1Í÷ëŒà�‡H¬Þ4Ô‘�º»ž?Hl±4NÑ `5Œ·6ÄñàI#B‡[·ýOÈ™(?û(1ËJתµC~Ä@žŸÑ[fÌyð€ëë…½TfúmÝ+ÃÛ™/ …ìÛoŽáª bjÌùÑ3FC¨ßÿ—?»ä šU˜ri{Ä2ZŒ/¤f‡wÞùƒÆB0W;U•¸j7+ôjæÖƒ–—,˼Ÿ}"g�Äȯû†ù!šª~I‡˜rÉ¥›H¾ê‰è¾Û}ÜþÌþ.%^rWÅY|¤èƒNþ7É�Œlu ŹŸ¨;ÈhÜzN®½s;ꪄÕÚ)-AßÃü~«ÓÔM $ïÕŽu›½ÕüÂä5z7à )¸|yÄðgô%ñô‰Ë•¢¶^BhÈÀ·[?¨N Íf€pñˆÊg<…¢Ù,þÁèåXÕ¯]ZG|<¹R£€Ô·w¼n¤<’ oõd¬H ù—sꆟT0¹í.Î1L¤QMˆ ¥U}²�a3¯''ûgŠ[dm·cò‹>Ÿ ìH*îÿ,È�¯Ñž\|.ð4ÃVšŸ¥Ä~=W”âpÀ§ø‘¤k b ~Ƶ‹îæ‰Úó’»à8ÁîëýQœp^Kö;5|a,á›Ì²ÎЦbbOë?Ñ3¹ˆ›ðý¡q&Ÿ¢K aÖ t2P0’Öˆè&_Êþk!ÔÉBtutùñúˆsÇh™Îgm"¾}gý—-âvÌ�;ù²+Ô2+- ”š&mçv‹_xdºhõFzjã>ê¸ ¸ÂvÈþ^Òhw視ëôþ¼øLz §Êûñ…‡¡U5b×纊ó"b\¿ñ?PÆ}kºÊ¥Må$ld8¸îZ]J„¿ØœJ^o,û0¹ë§¬k­›„;§Ï‰jŸ¨5LÛ¹šL]šoÒ©iA:ðÿl.;ÌjÛlĶRЎƤݿ,–Âáˆ!�RΞ5Z>M,Qh‘|¶âûQqøˆƒú•ôgägÏ{ºÜ=2 ž.Ä;ÿË+@žÐÜÍÝ´ŒUô‘Aä�%+FgEÜM$`1KzlõÕ`àô™ŽÄ;û�2`^ÄÇ\â�káX$*×Ëœu#D("i¾ÿáU7½1Ï�²ÒÚS\.9xbå‚–’Ù!âYÛ4ñþgG¹‰‚àÝn(r×A#/|ëä[Ê Sãûö®�ö(|Jâ•�ÓÖVþY�îæ™{4ñ‘YïØq®RŠC’ÓÙî5W=Ë‹$69Š´†íü>5Ü<q$œSÍsøLNÊ+#‘^½“G?S:nü ŽÅß7\N†sJ„óöøh¸ ðš‚ö?]9±J±=FasdÕP¦ÑW²&ERe��ØN'ôßeôØS×ñàš9¢Ïø,- nƒ|b,oA*M =P'•…o $aà�‡Ó•O‡? ZÐâ[Ê�Þí­/tàwMM(&ò�ÙØ!Š›è9Rë)òq<�_vCìè†ãÒ—ÜÄw€uCñw ¹01×#¥ýG’‡Ò Z­9ÀbÓÆ±kaZÝ}€@—C|±÷oÓ ’øZý­Ùö‡ëáe À«JG\WÖgXÂÇð…b‘ÕG�Ÿ®žvøüì”$´!uʸú)}.ʳ ³<«ôÓ¦”}˜áÅ òyrh)ò¹Ç¹äõ¸¾L×BÈ™Òwä³8ªßmGÅýî×xa�ž&ÖäÅøŸÚ�Ó„’Üš™˜‚A�´½þ¤!έ6þ±Êa”ĸ0FS÷Èߑèí“üïR %ØK‚6h»ŒN rW-q¾ ÝËì,2Y­ãÚ´Á¥-ÇšvÈÍÊÁ~å&[°‡¢Éq@ñHÞ¾¸?¶ªåÒÔôŸø~üކ$Öþš’Í–·Y¼1 ó¦5m_îzPswçPC­2�#@;Gö41™ÿÖ{Å车L]X—X)[{±­î)—y?ƒòû ½–›¢ö&õ�ߤkUÓ´jÒI¶Ï�›6ìk€Q½TH]=>ûã Wxd€I ’zóçra,êMÍ]ãWíƒê¶*s$K`©¨\š¸Ÿ5ž¬S<—“I›„4Ë[žÁÀU9FB~±<ø…@Èף׌]ËÚ‹)›Ãü"#áà}Ùi˜¡Ü¸�ŒÔ,È‘bÙãò¶"Àdw™•È¿;ò�»‹ÉXQ�[fGŠÌ¹mX¯4…­F$k]—ÿqÊw°|­�øÇ˜ªHã½—»±ÑÑâ®Lz3½ßWés[Ú^&`A��Rö¾l—û"J`›ˆ§gOtë£ÿÉðÒÆ³ChfÆ^…’ª)èš–¼šG‹ ù¿M| á>@û¨Ðçm‹²k[<.rohϳ0áÏöšïNà‡4ìñ|Y‘»[†¶þ¤·M°Ñ¡P._¨ VýMË=ˆ63Ø¢çàë„P²s~ÚÑsÒ4Êk0²£‘„']á *Gl´Ì0šˆ]|ÁC‘ÉE5ÁyV«VÍ9‹¾Qÿ‹Ð“„®)æ¼àà£ÊÙòxA¯U&¾9å'ö°¼å8>5ýKóŠ—%8EÈ �7ó½ú Æ´!gwMÈ£l§Ã|xn.©Ê’W•Ÿ W–ÑXñ~¤C\˜æçÏúwªìDzŒÝ�¡}ŠÓ~á|LëfœXŸ7ϯ„Ý–¡ŠÐ:„W&öèÅû«”…økÑD¯¡ÚC€*ü×=BH¹âm\J²™žj¯ÁÁ0%½ ¯r•¸@í¿‰-éxR‹¦í†O^Úl•™Ë÷�‘Ä»tàäÕÌXì\GÈd Õú«ŽÅÏÞÉ„¦f_ý.}Ü;~òi~F§�é&Ç8â‘> VûÅC56}zû8ç�¸îÃ6슭ˆ—pp!.õd'¢&TÌ|ž7 í®‰­Õ4HO®[å6¸nVC²/¾dÃÐmŒ�Üï%-mã†SHàÁÕø†V,G!¤iù…šu�móC5ïó€ ËÒxývã‚<½3‚8Á©œãY�KÎ�Vã/Ïû„²™@Zã&i H [VöOKf¨`ÅX>°^ÿwWÔ™IïŸ@BdæËÈ L!­XÌZ«°�Év†½¦iªÀ«¸ß¯X¸¼"K¬jxºSy}ØKp#šSŠ'·°M8Aã[ES¬w,†à/eçº-�ß 2 ÓÞ«üŠ”Ùoï °~ì³Íc %9zào 7ìaæ"Ÿæ hôšò� ¾w¹²óGlýöì–rÀÎ�‹ñ1me¾'#Tþ'Káó^Ý‘úÅwóGš0CÅ™ðµ?oœ_”å…‚SÝhÐ7ྦྷ`%)\Ï®ó¹ÏTT9Îo­ÑS¥«ó„oïFžÜ*åT¬ªŸ¹�ñv¹æJ<…ß^’˜³Oqf1§ m^� Ÿ"g¬ÃÉÙÑèÅÝ»±N …')§’oBêÕ•Ž&Ž?3ÿõrCÙzÃÉ)²«4³æe÷…¥€Àe¦ç7†�ÉG­T�‘)çOÒ¦«IÈ¥^Ó!$|Ö¥”nR°I8«[ðg;ÅçüeÀš�^(Iü[ëú'Á•P™ìåª%´€ø,à_Z‡ê8ègkž<KK‹D®‰iøì£û¾ <蟨Ås¶¹(�“‡¬ “…¾À #?6x”Z"Bƒû‰üKí:I¢£d‰1+ã^MæTµz7Q¤ô|t(!GÙN¾nj˜uIžçÍšGl>æ*ccðW,.™(˜{y „¬†yá˜(|µAEà�)¥Cò¬E °ýórÔ£DÈΠÕz4ÚÛ·}¶¸äë`J¾pˆ%u«gˆ�ÉÙ œ+ÝKp”‰£Çwë¿ë6IãwYlg˜’OáÜ`»ÖŽMì.ˉgcï°jgAŽdùß–\Ð@Øš)°{)¥ =}”ÚÙ63&øËõtƒ¾¯}3$NÞ;²btÕ¹1“–ZÃN6º­GHò•Œ�ÉÂzz:ðûþ¸_>•þщ”âü¥xöï½Ü#Æ¡;%Ï–Jw᥹•z‹]…;¾YZOÀCCÿ/Km�\Àgn/΢}Ïú¸ô9¸i½, Ø'Ôæ½^¡nål›5;x©øíë¨ãÑÓ,ˆr‘Q›[Ù)ùßM™��û¨ß¬ZÖçPÀØ�RóâÐX£J†ç!Œ—Þµ]ñLÕXô=Ðv E‚:j0ØÉMõy0¡¨+0Õù§ú¦d¯Ñ¤�¸(mé ˜«"k“jHζ¡Ë— ¯HÉ*À“bhº<írðšùi“Ó®5ø–‘3˜^Év€pz©Ä².3fA,§žk!V?©Á—¶Yp„‚£°×0ߣl¾„íPOqÜRà¯ÏA*êŒïoòV6U­Ïuuk¥r >ÓS!ÐÒ"…§›Ä/f.ã±2‚‚h«áPSHÙ\Â0üÐpÞ\?"$ ëD®zÜ€»GŽ5t�³~£ÆùØÕ@Ï[Ë[JÖƒrÆ”wlG^$¿�GH:4¾€~7¹¹¬i¸æ|cªÌˆÄÊ’sJ˜£˜øé‹åâ) Û/Ç¥”2¤op™'Å®8‘û�‚µ“šmú­Ž«x *°îCÀ—ËoeUâN¹‡(‡Òa^AÓ_y+ÍÂ31]�ñóoµ™4n‘Ž©ÈΓÌZ´ D+L¡ã¬~Ê_ïiCuSDðçœé&·ÌkÐ6 ¸O^ë7�³i Œ›ì�<rÛPï°×eàðëA4—ç^Ó Õ0ÿî:͹ô‘Â`o¿ÿWgq,jÒJv[jSŸ#áb˜H$2 ïDÚE«·ëÅÊ–ªµ(ÍøEïEœÜ ‘éµÅÅ „ –H<ßšÍ?%{ä'åéíÚ<í Ü›{ÌÊ?ׂžat ÝPTÜ×à¹JïZm>?=€óUü¾/\Œë²"ôZE ÛUÇ!à. Uí ¨BŠ"ÇIT¼oÓcñp#ÕøèFU‹(–ú”ÕÊJÇ L/ïÖb�mK�iòsJ×=Ÿ©Ü×¼¦ †©�øDu¶02c‘MR4Ôèh›× ¼‚¹¢Qµø±æO(ëmˆzZHf¡0¯raá“E¯À\äWÖÄo"ëÞÍîD7”ŸƒÜ$7DƒäåUY| G;§ÂðY�9ÆðÈc"æ7º2/ãuf¦…cjü%°£© X—ÉÖÚ¡pë¹ôoQJ»¸]O®ç·ãÎÄVx˜@µ4�H £×Ôð<¼˜¼WrìE$ ÙË?dûˆ¡Âi[L‘EÄ ±*Q Ž�Å IIòڢآÿó V¹4¡¢gøÅØ’cÑb£ZjT$+‚ûvX¥l["'èIxü|%‹Õ*yB�-fðÑì5§Ömµ<åqŽ �WàAÛ‚‘÷C[_‘—׉<=}ìç¹:F{u|•jð/f»)®H{æiÿz|#{‹û.Še‰‰0Ã_Ÿ-/œL¹‡‡à,ãs"^÷fõH�c�ôõ73h/°¢Â‡7ŽÇ’g]…yƒµƒP•¨‰w¯0Õ1gûßÐõlÉ¡ËÉÚªA0yü¬Ìä î$¼AA5Ù@õ %}é(iöâöO¹ <ÿœ{Ÿû¾×ò~gÍ�c†Ò`ˆþ�ôú’Ϧ]Ï÷!îX'"“âpP/%�¸›�T·ãÈcb/È+}Ô4˜릣«¶^ënVX©Zî@ÏT±:vžl^a¯ù:›ŸÚHÑGŠ‚E.&ߥ–š€›³7é�ð€¢›û½J1¤1Ò�OÒÖënt’µi0d¥33Ý™ìí.ޤ„ă' \^6Àð‚�C̬Yo{ÖZ×Ö(91Ï’·W"7auò¼&Ov¥¢8¦ ¤ª¼U˜µcjLÓ`xfx­�'X eúRVÑ=ͯH� #^«·ðH¨íèœÉ|°�‹ŒNÐzŠ²Ú©;mm9$Óð›Ç®ê»‡5f§’I|9@·t‘Å.™ž˜SAtå„ÔŒ€eˆË<ä¡!™.%J)¬ôÛR¤ÃʵÈ‚¦«@u]³ç+]þ±�rçÑ )hÎ×¶<ÖÈm²‡à™X„ÛýÒÖ/êD.ÞcÁö³HþÀ×ù¶0\Ͱå?5™/®×9»³YÿG‘lßÂÎ ôš ~•*?·ÑçN°O2õ€ŒB2É^?ôLt_©¡ÈýópL6g"[U§MgrQ]ˆ†¡–ïFÜ펅Âa=JÖ�prdiF‡e28)–‘ý�™�ÏÞÔ %`Ú³ÿUª¯�ÁžG{é3—G¸-nsÍ“�Þ.ß;êá<:Ó¦ô€¸ú*Þz«*·Na–:µN@¶6üLW8…°¹òÞ„ÛÔPá\)Vý§"Ds„+±¼‰bûóG\ó)r¤Fê†d«ßSF»ž<Á©)Ì'ÜÓ>+½Gƒ¤ÌLÞLEüPÁæYø¯yá¥k…ma�À%Pr'ØjÁZžBŽmœ‘.ZÝæ¢/6«y×€ÀZ¶|†JôÞ„„QqFâàÆZú×­Í ×ÃcÃÍ-ßbœZý 0Ic[—üs1ßv®Ö&Š–$µ�òWWÖ@( Hp¼ ľQGœ}K§ôÐÉT…W¯-|Jfó–ÊENÍ•Ç$ß,ÍP!@Z5u›SÀì%eùíÎ[ê‚IË!¹&vë‘h¯bfgؽ`V:¾H›äöq¯�ah\Ç-‘"kÛêd®/iúÅ•]7uÐ(·˜ô†VZ»™ à;íô�q‚*ÛÕêË€ž97Õ_Ø�º’s`̵ÈC„è®uD»Åö¢aðhÛŸgë<,GÇ¡qÕoI5‚ñžY6ÛÞ~9k×SKëw�Vò†ÛâAVÖT(m);qè!NfEÞv]žU=h¶>©’A*ê[C{tŒè�†›RÏ<‰vzÛ¸ÚßçF�ØàF .<[Ö‹ÇÂup-�µeÉ]PkÎئþ¨LÎÖýÇ�øJÄ Óùu¯ÑÉ�übH•'¯ÝNOZQ)·L˃Ωø­ JRŽBŽ—´ŠàÁbFœ4Vk°§Z¶â«öR¶¸ð��`�И®rü6ÈÃD�öZx Ãg„v`hÞ¯ÈÓ;ß¡ðq­Ð{kÒ‹£;ˆÁ»Õ¦¤¯Ãøøf3âqÚ/E¯sH Û%ÊX>\° ¾Ó±mØâ‘�óL·°¦±Z&>pŠÃʆaß~Õ.ÁPÞ/d�_E'ó¥ŒM l¼ÇÖI¸:Äø/¨ xV;é=rOo¼11Òš4Kd+£ÊJ&^½G®Ä9•àÍ<`u|òÜŽ•�î{6KêÓ›Fí) ¬nïm ukpÎòuµÝ‡Ž#zºÖø#úü-öé­C/»y„ÍùWfRùˆidÔ¡8yM‰¤#$s‹×&x²`ª‘lÐðØ¸œã�¿–·¹7+EmÀ¨¼äúв1+ÌÛ[ÅøxcÄŒ2². ÎÍ1¼àòF"Ž¢Òlq˜š��ÛôAUeüBrç힟óÙ]Ç‹�@Gµ,� §0‡}³ü ÍàšZƒ‰¢JB¦øã!�G¨:BÌ´ê#FS‚á“S…ºá\¯�…‘�•üÔs¶{U¨e‚Ä÷=×nÞüáE¸Dk”1«G�OÿÕÓ,úÖb–„!ÑØ!hYmµxjç·ÏÒ¹>¥üàªJ¢ƒŽ»GL?½“ŽæƒãØÕ@ÚPwÝI­êÉ€e±{Ñž}¶¾`ýë3=iå!aÞ“�é;ËÃ+r¼Á‘-|oYÖ«wV’IüDØ`B åP¸¢Ïvð«Ó 5³eRÇçmëöõr¿¼l%“d»«‡çËO<«º¶QV�È•ýÙ­Ë'VŒ8î¬UëY{ýBe=½˜I¥Ð‘hTói9; ˜ö®c�%“°‰eã 1»\£ã·�m n¸� �ü¡ÅuÚšÏ@ÇGkúëÄê»q‰‡bÓ‰ŸV9Ø·tÝçÊÑÀ8°F7R4aú8—ži5A÷׸%{)h„ìâG†»9¥:º!–؂Ħ÷\`æ"mêr¡ð­oï ñ �¿JàÈPy9Výñ0³T¾ #аgCPÛg§Y\Ÿýþòp7IÊß._Š"ø‘*`>ÖBxU9…ø—v‘Àhöe6l« çò€¢ûñg'n}œf¦u¡!n¤£Pò�ÎüÚú’“0NÏŒ]P.(?à¿›¥ÐôÐ q¡•Š-ÊŽJh¶>ÿ{ 7®zÉ|±7Çéî Â$œ³;A=WlË3æ�<ŽHH~s3C#¦¡‹ §&H(ºˆòˆeÄ`KŠ"ûÊuàžY�Hö°m¶7’/NsˆîzÿÕŸG¿ÁšUȺhÅ8=FŸoó‹¦0sÕ6ÁöÕ¢ ±V„ žgÒ¨¦±é^aI:^tÇû·²ç[?6„Þ$”—‚¼þÔ`_ÙE„½m¾|›@À×'ÐO�1�]c®Õ€¹5S„“�Ãoü¿¤‘×ìz² «nQЪ…‘ âoÙ_—^ò].M4@3Ž�«U† ŒÔÈ×À 0LÓÑäÊ�ã‘´/Á ÙøÛ€:_û0�]œZ·ªT°Dý™Óàu‰Ê?ñ­Ó´¿ùŒj¡ �¾CàzÌYW]Á_¶ÍC*¹²¥ 3nb´LŠÏ ÄK‡ß�ˆh-ŠQ¶s=‘!ÞëQbýMõÛÓš}åÁÅÚze¥ÔéËÞA.âeé'¦îHÁ�û˜ÑW¹œi ¼í ¶E¡cC©i‚Y.&=Á©D¥]|�ámr8à:Yغ‡BBw½é,ª�ÿ€âî†ýDdSòF…¯Â÷C hË… çž±pà�î­¿½ì8m·_#@�ÆZèÚY•$hÅšp¶’öôÃcþ�†M¸ÇuZþS5‚1‡y¤ŒÐœvgT! Áx­&ü4nw{±’m?˳ÓK-—-Á¤[·D*¸Ê–úÒ kÀ›Ð)ìç¶µb&K{lEÿMfÛ1¯fØÏ¦¼7B®^òì‡ìŸÒ«»|sG[:S ÚÎÙ3|LCÀëÌ„]/æÈ18Ói<œç3ŽK]:Χؚ²¸i0ü 4¹cüÃ0ŠÖm 8Š�¶?q3wvJó{k¾>zÅÍ>f×1wÛž>¨q;*×®µ¥Š+ņ <žLæäIT,O•`¼õÚy©i3Ži¯ÀsW Qn1�Í¿SgKeA/¾*©ò-}Îm2fIù “‚ÜZ+u`Å'! ?gü“AJ�{N“Û•1Шì¨ä�ÎN�¿òø -�˜^íOðÚ¦hcVÇŒBÂ6Ãk«£ÑÖIôxÖíÒh[j‡¢µy”¼9ºÈþ\ç*‘ÚMÓ^O~EB!kn'ªV.‘ Ì6ü+j“~>c¯¶"¿±;>²�+Ê©*› B ôëdM­þo%gb6Y_j²wÅ­e¹!Ô Ñ0ªÕËÎçé1[äuG{6óyÖBzJŠ B»{[ù��¢ÔœÉ�“F ë` Ò·íj[ø ®ÝÍQéÊcN)!¦ÆrE�\"—¾Á‘u€É�=)œdîBàMjï4<€Ý -€é2�𜩠ÐPõå6'r+‚;F›Áƒ µ°±À¢*ÌA#Ëu˜Ï;Ãìf„@›šãX± ­¬»¥>Ð$ÉKWOÜrÑ8)Hà ¹W%žð_Y[Ô„W&$Z§ú :°ðÉb¹^s¼&ÂL¢Ê­´ˆçCçðG/�{«e{&»OØ¡/ŒŽà+¨—�¸2¾B‡˜_'KÁÇÃ3™V”QÚ¶¡ƒ± �¾À×´Ñ~ ß¶#xàåuZ“ÒaD©œvˆ:mwyد©m3¹­¦RÍ~˜ÿ—}W-™vФÌÃbš{Žˆkà¢.|XE7h,u˜Ô ¬u™”tX?NŸÒ(ÅÎYuö¹@ÒÓî„ &ñ!GÅãÀl_½�#ø¸á_Ę`yÆ.ë ‘ƒ˜tá<ØW!ù¤è%¾F"I+}P®1Ðø H¥QîÇÇnçdvœ¾¤ˆÓÌPkº=„�Ÿ n¦(Ö?oR›jÖ(mÄÇ‹Ì ón=I°Ý¼ã8GB¼ú0™q9üŸ< Ê‚n®�Ÿ5L´Gƒ4Ëa9ÅAV{·Ù/ ™z#Ó õëQÕ…¥u†²­û'-·Dªí6I”đˠï9üŒýû¥†Éf à±aùŒŒ¥D#·£Oö´Èòå §L!}iF žÛ ªE©�5X¸Û< ³Ë_(Ý–~"]‰O¾ÇÔ%AüÂQA”®†^O«w£‡•û®­£zp®¢R“Nr€ Û`w1ȉdÁ-N⪆Ÿ�’Ižr �ìšPæœ}DÐ;»…Cr8éÉ ÊœŽ;ª3›�fCä­oÀ!íj(ïd–N¹ìÍì`:Ýñ”¨X’ÇO¯ëò£õå%Àq>´ N_QZ ™ƒÂµrUN uK$ª¼š­êJÿ™ü~ÕÄžw–GO§¡qCYQŸƒä¾Ñ61X�•¸bá¸Ä%Hè›ÅJòÛJ¹Ù}쮉ËÚfU—éGqÜþ:i¬èVru;ÞpµûÄ7(< Âç+‘Ñ08 …Qù…6f,S}MçL äì-{V¥"û,ŽJÖÎY%Ëœþ•'qÀ°¤r+«Ú«iy†ÌŠExì ìäH\nˆöYP¥èÃc27s1p¥ïZ­s•ïœ}{â³U4¥´CI¿®¾l¯ÁX½Êi®êÞÌc" où¡@ÞÛD$ñDzIÿ…òr¤O^#ü:ûå3#8ݘOÖÊùEAœ ¿.~þ¾ÑVÞ¼®)htø÷Ùp´“VvëÚLÈ‚…$¼êp*°ËŸé ff0U4DJ#Ö{Ù¬¿¦}²�t*K¥À>–/"ƒrª:ô"3Àö†Í1ÓV’€|<éÄÞ˜‰þ/”^w„qé_NÄéËøŽÐ$ëj¶²{gÀ!þ§Mè0�ØÚ­*r{áœñBF’a‚vaP¸³}×i1ã6êè&É›-@wñ”™³]È'o:ïœ'÷ô™„ñÆO°tJÚ[Ç1þ[Æ%À㬠y;ª€�-�ìî“N]3Ѝh–âòWÉb‡v¥UÏ™¼t”ö‡"#ÿkØþñv¼üV/<­¤cÁ–[†p$Ó!ŒƒÛµ^@cœ½Z€÷1…¿I×ñ"¯¨Qé$£]ý¼.�ï.VZœxµøóŽL8ŒÍcˆ…Û©òk“Þ™LA‰Øb¸°Hý”‡°¯�" ç+Â�ºC +¯ê]ΩJ>1à"�,Ò c˜òAáÀ5ÖŸÜ;BŠçÿH¾ }‚M_Š´Ù”˜è •厡F™œÈÁ…M}`_¬GµFÑ= ¤?úW­b®Ö$ñ —¦o;ãÒ ÿÔM£`-¡K”d;Õtü2€¢þ/ü,&›ì™U{ÝCÇ9Ð@Î%qxÒdoÏ Š™ò¶q;U„ïBWæ±sEº¡D ÏnôEÏvÌ Ë¨DQk»îÑËxÞòϵúrĦÿWDn}Í{õXšˆ«P ¥ñYfÌ…½Ÿ_Ì«ÁV©ë]⣘ g~#Œp5é&GNAˆct_mh~èžìU"Ã7~5’ s¿lÏ ³mÖŽjEƒâO—,c´FuJëðy!ŒhÄã[j‰)–~´&CÀXEA¢h2EV`è«ìâÄ|ì~dsÒîµ%nY,ù{¤Óxqá‚=Ô �yˆôKMøýîwµU»;Hš’›³#І€ RÀüÂ\‡„“¾$HžkÉǸŒð�X¯Q–2öã.ÏÍFë’N>u2 °|û œyç½×ÆY"G_jCîëB™3ÕÒ«C§J=bÍâá®l*/1þL²G�*4È@V|à:ÞVK‚¤nî}8+¤íÇÙq2íýªVÄëŸb<¹çüRÆl.ýü¯p„Öœ�.™×Zá¹4™¥žÑx[¾S{•~WéKVækz]M×Nr¶íˆJ°)˜ñÚ6åWã3ŠJ“Ô.à‚JyN•”Ãßtú${:‹²á¾gÈõ©¥’lÎJøu’åú¶Ön¯3ü¯j)Jˆ1IŠ6ÙÇx›¥”�0AZ\Úµ{ÛhnÁæØN×ËŠ?ÌBåS6Ç.§!â¿H!U2†ÏO'ƒû^ »�ɾrK8 ~c‘ýl�z4]ÞàÊ ,{•’e¾·ÀÝ+²eŽÜx†ñOågTA3�3�øÄ•þN`黵£uôú³gÚ)ô [BOQù|kJ0.)üùe7óïci–X©ÔQ¨aò L™±%ÇÊ¡,±7úõû|m[Ç@¿¢©}oEüL’bÍ9@ŘþÐ?¶ÕO‰_Ö7Oë´�×<ߺ¿0�óôûõë*—rƒ´xi¤·ÒÅ‹µüZX ´šSñ†Gƽ_ò7†,~hÈpã–G°ìubc?õŸuAËh­B<ˆ.¦+À=ƒ»¸ÔÖú;Z룩úÜnÖ$Ì 4nô º{¢wF²6�°P–=s9/žž‡(§F²�m† âÍ›Œ¢Û[ûî�ƒ_È üç‹„“Eµ}´e»„ qŸ ÛNÀHmkd©gíÌw”ì‰Þ-ÖÄå:„ßœ­ûP‡§E- >Ðyvµb¦ÏþRdö��Ô7ëI)^ |U„ëæ¹xk9ûEŽÉ³Ì ~ù~œßñ™î$]�þM¡ê/�üiwXßYN(ž�O¡è9Ôš â»5è5—„»*ó.È·à[¦’,§ÝÂ}ã‹’¢%ŒÆ{'R˜Àpé¨IEÁ´ãÏF6«a4ȃ俏žšª€æÜPL1 ­�@sü$â@;Ë%¥HÏšÇʨÃßuö?·Ó³ Ã÷òWñ�Ù1ve4Á´ª4%¥ úœ$T�ÈLó¼Âã 2f.=¡ª;“3'¸P0Îkš×Ùy\3�Ÿ x¯,À„Ñ´A7 ñ• 6s6¿×� 8×3Fš_+îY«E³ójƒ—ÚÞ½«z²�éýBì냲ÂN=/Ù¦ ÿ“ ™Á¾ØáŸÙ3·*cÅŸ ”€u%¿<Ô5FÍɤDþÖ�ݛȴË5a€CuäFw£Åeó–½/ªTà©'°YÂñm€ñ]ÅJ_.9Iס¹“±8¢UR{»ñÍùAÂ6ìÆÄëw´×q¿­b €4Qƒ{EtÕBBùÊTJ80Ê´\Ö“ä’WeR-…aB«ŠX_ÜdÝ:±Ò²Ö°ÝÌ3õ\ Ê/4^�ƒƒÇWÇ»ïð¿|_ß’ü´'”®gÁá&´¨w‹%�í0�âÏÛS׫évÖ"/Ê+HÞ½&’geiFZƒôø°Œàb‚À`‚ÝX�j#A|6µî"àŽ KL÷fÍrfv°x%5è£!GÀ‘tgì<[”|LlZfï0²\äªRŵ+@à‰žNKø€és0Ò¯ì+ØÛÄ Þƒ^Ž?L)Ž,©f”P=®>ÀW RÙYuy?c®c›®0‡îºøeöÍJ«…yØñJâß¿ÃæëÕ'¢|z¸ +Ú%*„û�kåü¸@=оØE ;t*È7^²ZqUO|‹©GOžv:<�ÅéÀµœvëžC#²Z»2Ök±�V– Í©A—¨­‹_N,#¿ï¾| :˜‰îe� +¯j·¼'vž%E4ÝàÕDí¹Ù㽤/—2þÃÜHMîñ(Xúâ‰W,Ž@ 2××íD\4þ¨ÐØ0C"kWéŽÅ[Ú$¡-‡¤ÚÏ*Y…† ÜA=CãïûuiÄÜÍrݬyÓð�=Ðñ9QV Ò›æÿ9åÍ-ÕÌg™°Î¸„ÍqãK�+ tXX“Ú‹<è.æeï¬Ôü«ŠíãâVl=nù¬“;Àºèº'´¯;MZNxò,!ú±k5®·FòD£ ÌFùÒ‡¸$³ ¨cLB ¯‰¶À‰Ø÷ÀN÷Ý¡—Ë€8x¢ C‡ÚuêMc/»§l»ƒMÎ[š�õ)ñóuŸ7Âd„HhïÖ˜_r™à+ÙV”�ñ»=3`4–OhÆ–”’á(ÕË¡‡í·[ö2»ªgô‚Êßñä‰E×fŸ ^nºì¼Ä™7L ³Ì‰„rÞ­¥ö‚åJ¥§³'lÞˆ¥+Î7"+ª6{ӾȼÀ}Z{øSxýA³“Ì“‘ÝäK`© ´A`À3|uÝug؉¤®':¶�å#¤ƒ.p&x^<¾PM4äSMà î!ûV 1C�Ú}¤~ùŸ–ˆ†GÔðMªó!�щYÓT&‡Òʱ5×à‡©¼zÙ|ªuòõÞ`GZþ{CxÄ—^kãšž¸-‹­äÕ™ âú¨­r˸BXµ'NÒ6S×ÀPT55±Û0ñ~z`áŒS5âû~Áê¾#A ¦³Óù”ôH æÇ0;æ»ìüÑùˆÛç’m##£qûzòß~É0Í]²àÓ¿¿Q½7™ù5n‘³ºg´¼]AÙ+•s0¿°ÄÑÕYÍÇAÊÜî‰�Kz/V¸Ý~ œ|´…¯çÖæDŸ]23t>6*°½=øÙXÜiÑ,!ýç¥þ ê�àIq™¹mUÛ yLÜ2=—tï è™7ζõ_Ô18MgUóÓCÿ&eesNr”ŸÙekhQH1 vÂû¨Kh¯KþJ.Ç�=,ë¸p'–ÇdᥢpÓ&6– "ëöU�]Öƒ�7šão�Äu�Óì}þúÍ\óò)[¥Õý;ãFe‹ÖT6¤»R^ì—ðîu�HÁ1ñˆutÁvä˺’£�ëWhÉqɦ¤óeô¦(ï-ƒóÀ%”¨×uf𨷘ªÂ¹YW ]L£kÂe£ÆM’\l`—‘¥íñ2þ2"§\TK?‡ç¢f¯éå“ÑÝšF«êök8`ºÂØ“ôpµª^ ‹\Ž…B3CÕ¢ÜQ™¨BSƒ68B �S%­?;Í™vŠž@îã�ôdzˆWn`‘3jàŽál»³Òà’Ò>ÎF±6¥‡¸ý(øä‚¥wmHE¡e›&f¶*ÃH›: ó› ’"«èDÞU§AO×2%Tà’xJ]¥ªð¼þåZ{9ŸêGW)$¯èKï\À©<�ù[³€É¸ãÂB߯¥ìÙ»ë³È2"­nJÝÓ‹·ñî…“•wŽßªè!b-þð'ì?;z‹÷GzºfǦ†®”{›· ª‰ë€‡¥ý$µ©rɬRF›˜wæ-‰›p,…Ê:[ëÂDù(NJm'!”¬‹XSÎ_r‰ìÅEàôSñ+�¦ô „=¨5nlBÍäËú`OÙ«Ðó`l}|ëÛ±›ð£ï£¬ðë5ågs ýÙuþC¾ƒ7ÄG�¡,þÁçnrƒg$Ëê pò�…Â?¤9 »þC=`®cïJôeQs WôÏ ¬y¦[ó¾�«ÍŸájiZ�<¶}'?«Á¯÷Ð%…Ýo¬Ï Æ�Z5�qžã”»�¦³2ëÄmu‹�{¶xÃ!ëÕäG_²ìe�ÄþOpû{ÜIDn Œ¥t”ÑÕžGsnê?\Ü!aÓðÞÄR�Ð�E8)¨£c#¨nŽSqc¿y˜¼ùvbs#¦d/ä&†9jÐ÷³ : Ф7˜z†|¾‰P~rÐuÉåL§#¼»ò$5Žz]“mbŸ¹)Å/Û(�˜±ï·&¯â@fˆÈ®aìC™ß�°25Õž5ârNúVi<„X Ïú¨"N¥N*] ½»ub¼j{C*×÷# ŠÓd)T+7¦lþÂÓHe˜ªWã*Pr.‡b—–B;´ªöψ„ÏøPrŒ§ÝT*íN'å7I÷d`¡Òn‚�íZG:DD 6’SM~jOãœ$EñžO¯ä¬,¡ÒX¦x•ù`9—Ë_�²È„}ˆJR0xÏsï—êʆRvÔžD<¡,ø_VÔ‚•9T!þûáS»)a‹îþŸ{ʰX¤I…¶D/v®Ò9/]6dþœðC‡0 6wUä*X�³¤ÔߢæŽD˜Ëþhƒ¼ÆŽÃŸó9çÏhÖ¥ @šRv‡aÈõ|¿£Ãpåi.%¸BOzoꃭµÌuM�� Òßݳ"ïçu�{µ¯#§Û¨ÌÝ(׿1<³²Á§¾@™ÉŸ³@»0{»C–JôÁ<„ OÃÓûPÚ‡Tûl$­Ìñòa÷Ÿ†õŒ ò‘_¨/2;ÓŸkGf ¯e~Õ,óÿ¦xÚ±»¾Âñ퟉ý%ƒ­‰�Ÿ‰¶ŽÏ4J®~eŽ6G$'ë¾Æ?˜”Y<¶bbÿ8žûQ›noù XB-'Š ¨R¬WË4G¶§,?:Ò;"€ÀË<3�a¦¸¼ €UdåR*rg¿BÁLví$íûu(BÇ;У #_)E­6Ÿ¶0$Ã5¸úï°Ê`£Ò‡“¹ÝæêãºÓ£ÛC�©FÔ�׭ƾ²|.FäïúÕ£*úy?SU‰0Ùg'–yX[kù¤aõ†_°€ÉyhóL“Œ~bE—ä”­ ÜEé…SñÅHæUäiû�`‹löˆ� j`²LlÄBÞAe ƵëxŽ<è–Â[b(—M?~y›‚eûÅTÎSÈçêSˆnÑzϼ~û˜9`[-O¿ùV¸±&”1.w¢ß*Ëé`ƱôÞa•wÙ éŸóT:†|ri øËÔ6U 4QÁDã®……M�ßuz³ ð�Τ�†.ê–ÞÂK¹®¢Ó’' › +ÈS8¶!U•¿X&r„:É;0¦«LÚ¬M;'{yâ@�­|PÏ„ç³é¢¨Íš¼ØÜÀyÅ,�x›éFnØ×‹/tcûL“K¡Úú°êÉaÀÓ'Aa0­uÅ—oZG£u1ÉAšF–®;‚°Ë‰,C©Q¼•S¿³à�ƒSÜŠœ|�€C…iUSÞ�fµNA‡Ö*[…gÓ<üø—/%)´º–TÆÄ·6’¸ à ²¹2TÜAùSPeȇD_ µ°·¿�êfVÈG­Fe®ºú£w’£bŽ] ’ Ù/ö_9]Î<º(E�˜× ÒÓ#AÉéÊGlt�™¶"ÕŒûúÉoTŒ¯‰¸ #~Køe‰4hÙmè½ 'ÝG6ãtÈí)¯g�©ì@}}5=íùIà.z î¾ËT'‚qË—ÃW-ëXBïR½Ñ},BìZH"2ä j—f·IqK?ÑW�,$Ñ �ËãS‚”ï ¡‘p.ƒ‡èÁ�„imMbÉmrSO8NÅ! 9â LP5?wÉ`µ™†fnðEÔ[ë2öeÚBñ‹�ÔýCŸúe¿ƒò�ß6T{é-Úí‹<½¹÷‘ê1[ž¼KT„稲zKZCŠAšY%?—ПßуFèQ«§àw�³ï¹˜+}H_m2¯ŸâÔ­=«ë A^æÀ™¦ßTÊ‘4ÃT¸´‹.0Áoç£i€¨À—Ž&Óââ‡Í—\RÏÖ‹¸/Õ·âþZÄè@d�_ïýµþÞż7yvøQù ùÏJóiBŸ[xt rsm«iù‚.ÀÛ,zˆØÔmŠà–f÷åkRîœö;Žêq…¬�‡5~ß�?U–بÓÿéHöE„ƒ°Lð)Ã~ ω;šÎø¶ZðpHŒݳ­•-HÑ»IáùW]Àâ¢Is…ͳVõ]ŽÝ\>W þõR™Ï¦[½*‡;²9 x?‹TV'�t•Ðl×�++­9qI¸#.±2èéó˜·'£æûfŒ[Vfw̅ůq‰-ˆP˜á�ãÜÞsàô+?ã2Nxhž†0VhÒ(‚Öžœ�[çӤäIŸ�6$éîØY¼½íÑ«¥BQ³S¾qð>c¬r²{¯…¼–ˆÚ‰LWOú $q­bL®ß’úPJ_CäËߎèßeA\Ь½&e€BüGë^°:åî£mhº’é?ê£Ú¡ „@k÷�Ïvrï+Ø´N™ Ät­’2: ƒÊK5ÜÚòó+fµë°}:x¦×µK¸_.zÀ<åG’ìÁÊ!d-tΣpd^2�Í7EPÄ™ŸUs¤Ì Lzñ­Ÿ ë§IõïCV)V]�œ¡û b\3UYR¡-ý* …~PÁ¬YI=Ö—8¾®ï&EF^Ò´1κNFMdvÆ®ú«=iÎG¤„ìÎ9¸ÏxÎÔ6!{’Ñø+½ÆK8›ŽîƒYWügv"|÷í¨�·À �!Çν†œ^ïS†ªNc`ÿíºt¢)Ó2| ÑÁ� +<\â‹•CÀlíz·O ƒÁÐOY åDo)Xëc7#¤ßô¡S‰Ì�P‰BÈÝÙ�.KàiÀx)ÈFá8¬‚H|óÙ½Nœ»ô‡ç±=m„(â¤ìí~.㌸+±>Ùã€ù4E “iK G#a›“–ˆÐÛ¸c'�ñ3Ñ3ºv+Oá²ÝkX)ÀY°è¶Yë4z}Ù*Ë™gNzuùë_­MÙVvØÂû¡èb”<7Êý–A \Ta–þY×}`ä\5G€ÿÒ�¿¥cµ6zœêCuŒ¶ö�­ŸÈ©× w¹Sù¾¦Ê5âÎíÑï:לi+q·5X»(ßÌ.@6gluÄÆ8 ;»ÓÕ£8&®¡ ŽÞx Ü{K1”„ù‡W…e”Ú³¨¨ß" †h `�,E›ÀØ9bI÷I›'nðCÁ{Þ9E/í h ÈÕ£D$Rø¾hßL:´Âh8¹MQgÆYm%5ÈÞa,Óöù[ÉV´Ì«"tä'-.¼µö¬N—æÁØ{.—Tl©Ö/œb�‹¥Ø}6Æ6½„ˆ;LÄâÛ]ܥܤ­¸>Ñ»2¢—kÁâÐçs=oïÈzÑŠÐM×ù~È€Që(Ÿ| ¬4°ù�Æž …Å]& ÀväÍîú~žX¸Ÿ2ÚÐTŠ2aþÁ©¾fI§ƒG.|¦¢Ôù¬BbBý“iƒ¹OÞ 2Œ¼dU߈oÁQAµŸ&þ®Íb/¹òÉLv Cþ„¾éxXèü“Ž>ì»ÁvV‚ñÞ"6P¤ƒ½?5‹ü¾Ê¥yqím7iæs²"åh-K¹�„ÕmÙBGt°dð½ÄõY)ô:‚V,VvüGŽ7RGÖzð£ƒ%ùÁºÍiÂ:ý=å+”lîh“}y�BˆúÔSÅýœh‹Ó¯^0s]@ú¿¶*v\ÒØïÝŒZAç±i�þ$†3�LnàÀ G^mÓvùs5ió&ü �œzKˆ¦/Òì Vr‡êt"öÄDEDZÉjpjÇ?HrÑÅñæ(/�ì�È0Y•ô=iÁ’Y펪U¡ú;–hT4Í¢{¤kä²l Ä!ºÖDŽœ¡OŠKï�NÐÁÎBÎyçT�€v}á;XÇÌŽ W˜íD~J<î:ÈN‘×­­Õ$ñU¶Égg6ùrk�y^„Ô»ÏÞ´F“m㈵~~ $pÌãÀqqå=`R#!¨¥AÎmEò}cªî‚8n/縰óÿm±» Ì·½FP·õTä®ôøQÖcJ¼s%�Êr†à?ŸuVñØ%[ãN‹ë,Paû5R ËQÚ¤ž]UÛ}™Á å‰Ùr°ó wðJ’¡Ê=K†‚Ÿ§šÚ‚'WÁïœ0ɜģ#?$Œ¸AzÑ,�$…Ÿº+srå˞ʒ3£ |Íܺƒó;Õ[+Lxî•ôz¡Ó+ZÏumWQ{ƒeœÐ„®*\•ôxÞ�ÿ1—?êþ·«¹_W) Š"¡;¥°g½áˆ¾IšÚGG,©Ê‰í"3/�\äÿA"K­½“ùóœ8/lMO˨^å—pf [Ý^ .@9õ¶³n*‘yáòãNlr˜ånÈhtCá"Ô¨‹nã.F\Pƒ°þ:=I9—Ó]/gÒö~~Ú4Á‹Q©Í»%ôŸ*U˜]àÓO~â³ô\?Ú¤6…�(·¤ :°7ÙÍpö&U³€€åùŠâZ)gFÚÏ4ÞdùÛ9=2¥�!Yy E°ÚMgÅ'2{åÛM™ øZ]³Süb.®ŠŒÕ® ¥³eÚT)Y%gdq0oŠ {^Œ ‡WW¼cÖRNU‰‚½XÎ8dÜáÃ’!¿œ¬ù¨æ%ïH™/!áë÷‹ @ðÍ®…ò‰; (©çmH %XÁûovZÞ%¨( .bU#/èN‰ŸÆÝžÛæd·VíšÈTy*@¹-ð,&•W×7ÑN÷ÿtAr‡¹A٥ƞ(Zê·€>c¨’F~^PàØ|‹–Z 3[Ug¼© §3àe‹„¹4×ØË¤:Ð*Ž5˜þˆµë=�N<±Uƒ—Y %Üþί5\:—ga3$¼W$%“Ö-½ES"±*ð´ðÕ…¨«ƒÑ/½í»_·òi3¾w4ö[}í­ÿ×Wò8íÑ O„>Õ¢Ã]…j5弃 ëEÛÙ»U.ì¯O¸r—lœXsR5¨)|)JÈzñl]DO]_BSÔÍ ˜_‘ºù‘y’¿ë€‘ÿwrãÑ\82+êíŠ{¨†F�¨�üÕ$–51´òžæÞû„Ï7ù®ÊëSÉeˆ‚j‹ñìîèít¦ÅìN…wW=zʽ+É”ú«N9Å™T÷›óJMy\-žk¡Xf�룑mc´-2®‡|t.{÷˵»<ì�ÄÎf@mhPoÝ;Å]“4~ÏX³°1‡rÎ�Ä$é�5 Œ’ã½0DäXÇØš=,Š‹ œS\FÏ}“ët‹3Q�eÀJ/)sO¹~ÃJÇ­ÿ®Œ%›‰ ƒœ¥—©A\�‹G³æA_.Î÷U«UóÔb¶%Æ”yl"ûã•ÞãAsÁ‘0ô[¤ïk@A6-a¾Uú¹rwÝ4Ó¡ÒJE1¬a“âW«õ;,'¼øÊv!‹#ÕŸˆ}-뀡93±ovD;Ó5ï\‰ ¥äH(ï¸áô+Ò°]ÊA£ÑÙ­]v½¦$Àjú`…Ç2 CÜž—íÔˆ‡ñ8!EùòÿG˜p ~hZóÉ ’UÀC>Âû$Ï{¤âYS‰-S^E^"œÆ16zqÝä¹HXtêÇì.dîL·> L�/çRY¹þ Šc3ÜÔÏ>\²Gçkó:ÕN%™2¿ô4«©½kŸG™y‰ø}Æ@B h—�uЇQÀÐí‰óZälû¢ÃÜSs°¬]\¿Â[Í<1[ª¾¥qEÝ5ÝÜò•Âøþ,î÷*(çù¡"ꃱn(Ƭ·ü:õ�«óÄÿ¡ÙW#®å[ø¯¨ê¯ÑÑ×ï-ßsÜ%‰]êº8�DF�¤�ÅÚ„mjbíû¢(ó#pÁó�ÃLâîzÉ$è©�-}í¶ˆBÌèì#à¾Üwc† 2…¯ã´GÛƒQJA'i96ÀÜ@H_Ú@Búf÷KÉ)½uÆ}gý�G좸mùk}%.'u÷M§Ò8y¤Òp±`G¾Õ˜4fôйù5.³Ä¶ÁÜgœTäÓyÎ’MÖ­C»L¾9™ Ùµ‚Yü‘YÔ3_PÀ” ;‚ÇB&3I�¥RD.£¬Ä'ˆlÓÙ ˜g$;XK—Ê'çr00Hv®p óA£H'»ù*ÀÊX_‘ É0°íÉŒv×gãïù1)È1hJß›£?ß‹¢Yžj=hÜ"ëÀ–.*.<¦v}ƒ6Q<¤í/⡪5 ñ84P£"£âàq¦$éÅ® Š H‘+ÑØ;�@vƒ¦¾Žº}P9„D¨¯¤:ƒúyEZé±Vï¶24:˜7 øŸ«›·Dú^s*Z/Õ!‘Ÿûø'Yæ'›;°ü°Ž5ú’A’‹«;E¸Ì5¦Ç .#™'ø½Ò§·4Ø¡I¿£!~à_µº7Çm6—Q™KN¤ E•£¼ù”ˆØdlÍ+ªõ©¾ °�K³žOyß’Å?3¾Ï€¨�Q˜©h³ŸóŒÑçtS½´ÌŸEA¡ƒ% *:=óòŸRÝ�¤@VÀÁÛAeqá pm°_…³ Cö¯zç0§~}I©šsMj@ˆ¹'{83ÊÏ…¯,Ä›f:±šÄª=š1.çYÜÂ’š~w°×¢U˜R³'€ ØÜæ¾Ä¥%0m"Ëb{° ”,÷™ÒΫyo5¾‰khì`à… çPO¦�0Òôÿ9¶º¢Üp#–‘Wï\z©q)!?/õ*z^û^3»_�j1ƒ Ó( ØŽð)é�ÑÙìßUj[¦7kFƒêFôõIXï03Ì™áføÕ'g<¡Ì¦´Æ™€h†`*WÇ:�ÁDÌY-ž¬ÍXÛ)ê\�¹Â«²¾O[ÅIj¢S£,ò …8ï”±æº nÿȲá âÁû�6I[àÏO9v�…+ضÚX~EhïDÚ*…‹èq%è‹êG–OЩ×n~��®|ˆ±�»Í>c?äHQ·*ÑÕD=­]T¬¹Û½}±Í…j Ÿ§Èÿ%ÈÑФ08{& 4]n Þ'Òí÷ -Ö²®tZiD“UÞ;(u;T´¬ÎŸ÷쉩-h íPT¼ í“LІ#PC¥P´=úêü;S^(œT0™ÓÙ›�¦|\Ûx›ãºÁâÇÕlØÿ+ ÿ *òÁX"J8^~ Âø«ð—iûl�vú‰vóž�Ïr{¤ÐÈ@[?c¹OA$¬1íÞQXÍTÓ»‡ ¥¼ìÖÈ—PÌwU†Sw½fŽ.©‚Äȱ�Ö’‰ƒ†|Ø%ùb*XÌ�ÏÞŒ¬lT @½=M<²(2 S€ŠElà‰)ècWÙù~ƒLHðy�M9•˜šnòWÊáàáÓµæJ�‹cì†MnqEÉ.Å$°çÛñy]�9ßN¶h6 ïíè8Ã÷¿â”Ì,B?lÏÅM��(?Êyí@�V4ÔÅÒXÖòÝV �àë]yLB²óÝâ±rˆfÅä�½¶b¨”*àYŸÂ‹,¾‘÷VÛðeóÉ =+Al¨¢âÉE=¹*Fó÷ñÝc‹ÌÈõˆì•Ž7Ñ"VéÐòkŒ ¬§ûüþ„à’™k…r‘zâx°\ƒ�mÂïÍ™k8® ¦�çKJºšSæŽ î¼ö’¯4ÔŸî>1ãÒã‰W�„¾À1ÚP 2oCMÒpÝ<å¨0÷ÎÞÆÚ0e|'ýÔ±EGD�mH&v<æÐÜ![€ñ8+c·vôPxxevèâõ^ófòˆh˜‘ø±)”Ïê†,\®$ÖwúgÊf8JçÁc@UêðÛ‹D‘Úê�ÍÜjÃüI¯æ�zs¯‰@ðñgwVP2©‡Ø%�¨mXú[|>¡NÆ¡2k�kS$7x<9· áúÈñžèýÑH–³Ót¸z�-Ê�2¯Ö¥QvìC ¢Ù‡ð0–È1EJåÓm«n»TEè7 .4v¡JízMjNÞÚ7�Ûþ�®ÕñofsAÿûêˆ7hå V�>504_m!X«Ý è”yÃ\6ýòùUT(]`Ì»;�¾Z�o‘tuNÂwCó‡ 8ÖQ ½Ña»Ð‡x�-ÀLª–äÃóF~Þ;+�6¹Ž‡àmoN'ª‹êè…£:üüœ)ç|.wŸ §[nûáØ�êR3Ú»Ž:qÁÆd:B1 û)¼¸¼ó«ÏÙÀ‘ŠD柦øÑÏYŸ æc îá2Õ'N2~ƒ ÉÞ sšÿ—Ò7·Hë Ë#JKß@ô×—Cš—ÕnX¶üx\ÀHU÷¿¹=€Í"l‡WÀÄ?PPh„§Û›¬)ä�MI½xþD�Õ‘I¼O§ N´ƒÌÝbŽžã¸ÞGñ3Å»E2v9$C aî ÔéÀ”lß�P¤öˆT¶áƒß]NÏ£:×m=è“‹ÀUœ¶®Ù�=¡lýµx‰V:ò f÷ÚùNÕ}g,bå”cf1ð å6iàrf¦ž_Ö%ÊUX¯7I€ƒ©)÷YHñRÎxÝÃ�«x33´- Ô]?w qÉhÜÞËtÉ;Õª0ªåó ë uDey³{ôPY¶Cõe·ýmNßÒ ËÒÎÔxdŽ^D[¼#¾v» (âÝŒ�K[Rq™'¡6ä”kµØã;Mð„ä)²­G|Á+Øp„wkd”õÓ·µK½ “O uÆÝñ8s=iíå uïÆG¸kthƒ�×§ô×aœýšj}áæ}}@°ð4€i5-çÎWM=@Ä-Ü  .ÈC#&ð”H)‰Á�¦‚ß#¨X¨É®¬“Vs²:ᘠU²�©ÄD�B£Ç”fë™Ôi�'ýsÖ…–§Þcy>rÅ6ŽÅ‹_³oèPÀ¹01ãȈæOJIîͪ¡®Ô"½�zÙº•^Ì^bÁØ’øÊùp»|†¥Ñ�nþaÑ»›ŸèKoeÑbàØ§ÉÛâœ-‘ÚŸÜ3�FnAMD]FòS* üÞ£¨EF_Ã,Ãn¸5ço †ÊìWƒð =*o•ÊÛ–•.uÉ{óGDÎ,::ÜÐÉ— ˆ„�öQ(ëV}Ö‰ºçz(Bìr¹Ú³,â$q¹�ÎU5ô¶ÞÉž©z£ªçFx›Ç2›|€Æñµ•®k¾'Ñš¬£ŒaòÌ7ÝØtR—¶�/•Eÿ²<í–ÝjB¯s˜WæÿÕ¡k'"$dÜÜýDœšýF2êà ÖaOŽ=‹è•”mˆŠ6X„ˆA÷k4ÏúÈp.…pù=?´Âû³”äŒrµzA:¯œ#=¯ßV[hÙˆ±föà&iñÏ1¼ ]?N‘6½�$†Þ.OQÿÚ NNÁÑFjÙŒ‹…â_‚™ã–x;òëúu•ÚÆ1„Õ öÓ//�¾6…3)#ÞC�öC/ ö€‚Q-è :×ßÓ‡þ‰SœnwÕ6Qy¿áŒR³àû/þÛ4ª: ª6ü†â¢‡j[I@+YŽü±ÐAådA×èÝ„hW²âæc&˜/lòùBWôðÒÎókB }]4:É»è‘ùäͬÈþ)^Å®§ñÓã“ÅãçsécãzPwž\x[6ÇÁª�Øë~Ц(a –tï�Á¥us|B¬ç¨ë ˜Ž%çݼ4¨…fÕ;àt»íO%Ü€T=äØÔÿ; V@@s6q`d/¤¿î©ò¬~)Ë«2e“EóSï¡üŠKÜÄ …mAg>2æîÙhOÐ]ŠÔ›~5>€øþóD×wZܱk› ÅÈtz¨½ñ®w—Þp´]ËÒt-E8J�ªÍŽíUÖdDÀ›Ãy`„ò›þ¨>ªÒN²4U^‘¶öæ_Ð|‰±ÁÊÖä>Ã+޶q"Ì—,ÍÌîñ±|BrG™¾¾†”¾݇ Ñq*aMkëûðnë}µÉæRõ9¢‚É‚û@(0Qc<ÚâÖ§.i'ß ›•ªì”¿1Æá1¹H@­5EY©ÒAõ�ô.�-ñƒ¨Ï,žçÑI¬@�Å^Ç�QÆ î´‰è!d •]ð=�bW‡Çinž2Þ±ÚeþÜMÙ�‰}¶JæÃMqÂqŸMò�dËþÍa›€§úuÚ+ ÞàGµDÙhÅ“9†d¤Y –º$H >t ¢µ€�ÙLÝdÏt²I‘ÝÌÖUáZR±ÒÌɪd5q+Œz=æìðÐQÕÕ ‚PiÍ%KÝa�«(󛢥ÓûKýõ#q}Ò å¨ðK¨ïTxu÷#¶ªêi9‡8æ�‰=a%¡LæŸÖ}© '"zzË< ª‰6Þà’ÜѨgoeîŽË:¸‰%ŒÃ·=¥ÉìÕRòGCæ·4BYŠâú ‚áî,+®$øNן%vð)§ð¹‡ÅëÀÿ‚j8WŒÂ„¤qkߟè,>Ì Þ_ñzýêý­]oØ ¾º}…OäzÊí88�}ËE„‡‘°ZçÛ0beAÀÓ‚Ï_'> îí¬›*~7ô—Œ{v¤–(ž çyy�©pÌHnG6¼°3�â´ÁRjäù•ÄäLšŒ¿1ŒOªOÄE¢³áñÇÊb“O?æX©8#Õq[[±ÂÌØu ¸&PÝXRæÀ•”*’‘Z_Úû&Ê�›Û4‘Z˨Qž/]Ì~8Íók±1e«ƒƒ…š¬ˆ�ó£ †ÀlÚrTë$²a ôÂpmû€Í>=eF �.iÛW¸œ ¢7î–¦• ˆfÆŸ;†}ž×"«´?ú>Æê£škž�¬ázdeŽU…¾•h|Î;Ž8A«ÒŸ®Új’Ücn™©HOv8˜7ž€[L’îéD)ÌË{\b*RmµŽ$ w`Œ p¦§V¼Rk¡—qM€àˆeƧiÀå´¯å&ý}Ó4ÜI §€€ÂQxAM ØìžÉ@+ƒåø=†Z¾q÷Ö–Ÿe÷dÅ\¨ö:¥fäÉÊq«‡Õn¨8J¹½`”3 ¢'ÂaI‹’q#k~ž¨«i€„AÙ0Æ'ÍLX `W=Ò[Ýó(‰õíkkèÖ7—ÍpI3mUZ÷AìE¿‘Æ8X^ßÏ6–êüI+Jp)´mJíÄɥﱪw“,öö…ÚŠ ì२ VîïÂÄ£Æà�¯±ÿà~¾ŒÏ×âÔ5ÖÃ0g{’(Ð�(líåü*08Ük�ãÐä¼`Îܨš|>¿³5Ëf�¹]ï ‚„�¿Ð¾ÝÁ` fÉ-Bö@¢c‘À \#$T¾Ï¾o7#ªÏ3ÐS>)Ñœ¥�~²‡è×K¾cè•tÙ¼JûÉFíœ6÷ÖÁæš3%tU4 =I¦TSîŸQÊCAÆ÷ñÉv;£V³ÃËGðç~9hŽ-ÆQÅüä¡wÙžNšIt)ù�íÑ�Ë©èUµ[A�êÒyœ Œi(n\±üµÄ‚v ªÚË</<2Ïf0*‹Jh²ò¬LcŸÊ}³Å^Q“CÞ­ŽpP›º/{"WÃVž�Œ›—F=N||ÐÏÀádé‘av—ŸÃIÞ%µfcÚZ û�&3œ”`N_bI�²kx—ªN5Eß2 r¦„yÔxá.�ñþÕÌö:æÛ_4‚”9üž ¿#iï»åº6(�»lMDÜQ[$V³âš´6ƒÞÑŠýÖ•;<•XQA¢û¬""ížÑ°Šd·XÛ­÷ غdýCô€/9H‘}°!/Ü?fü熫¥†{(²8`±�²£"ÿBB\u�Zn)« y†Î§¬ÖínHäf?Y¶/‰°VðÀ%T�êiƒ\QpT¶¶p§g�vÅ(/(³‹�'÷1s@²ΓÒ÷ë#©Û«ê^ñÃr(rºd@­"êÖ4á`ñã^-ëÐge©Á+fŸ×Ÿ»xîc»FÞÎ ®ËêÄRf?g±ë!Ó³·b[~E¹×ÒÎ ÝèÏ~¥ –†¤(œ¦’w6  v†ÈæÑÀîy‘”–E1F°ÕFw¤6w!8ÛFÓ�²¶yûÙV±ëK�üñHæõoÞ�zŽ2l–|Q8-UŽáº&~•˜i†zÅßKƒ¡Ôej1+åç‹Å¼®VüÞ „ËØ’ñCpi¢ˆˆ\© æ,i•ÄŠOÑxç&—Ýa[¯[w_8êºÄTë¸Fú×!X0V%–§öˆZî„¥ùÿ¾Ì_¹Æwnœ•ØeDÈÿˆg>­µ@_:^Ò¨óÏÑ”2C6ù#5#^�p¡ñÁkµða@z½œ7î:ÚZÁTŽŸTú�¡ˆ`.ÓŠ¼aä0óÕs!J 8~ü­M ¾)RÀ�¼Y‹‘ó;" IW ¦]8M²Ý '¥ŽLÆ4›ê=©0-·Cõþ@ñÐÁðA­_†|l¾ÐÃ.a¬ÃVí‡FÞÔD‡ø@º»,Iz|®§œY"+Nñ︺ª¤¦Žû�_Š~o°-þ¨xùØÉ¿;î°Õ­ºãþFFy´bQ#”LQ0až’Ò*Ñ$-¨lŽ* äïòHv(öèwAšÄgpW åšl˜Æê q×ößéœU)±|¦ˆÖNÚY¢åºè–’öŸ›O‡XÿötEÙ©]C·T6©”íÂ��{æµ·½¹ ÷ù A¦Œ®¾|í<�©æˆX#s‚DÜ{õË´²ü¿¦¾º/V uy|Ëñ¡òG¼Ìí]‹¾ùñè–„ã ¥  ( S`în¦<¡õçRL–I&Fía6ú0N :‘PbN?au¯‚ªÚü6‚B„ñÕ Aô=3Û&L´ ¸çf^óO¾™c2ÑJè15@¤ßšѼ´º¬jªhaùÝybüIœ—s¹GSYî°Áˆãó·’W€½KœÏöë¹±uWͨìBà_Ïná´Uεê‰Á§Ë¥v \Œ½k¿–6À¥MöMç¥O¯æ IÒ)3+‹€…Œ#aŸY?¤Úmáâß�v¯ßö1…ƒécdœÔ»m¹ª\¿¹´æ¾¶GIÄñ`–íËО‚‰ÃETF·Ce艇çmèXÛ:ù_yÛ [c�&2ÂðqEPHÉ;09Õ,¤‡æ-©ÈƸ¬;­jí�CV ”æp‘¢˜“éedkˆÔx´8Àƒ3åóFÂ$+ÌàLdܲ(]˨ˆÉ®iõÇaÖŠOoFõ˜‘ýX`Ƨª 5Ðv¯õx\e8G4x�G N'=@™¼ÇŒo@/<;0­QT~¡Óç’:�Íöü™Å•DßKU-Çw£xBCpï°Ž¶WÝcPNVe8|í˜þr•=CÊ·àí·ÈbnKèô°Õ:%>Üú /eá×_½^D@Z™�#²h^ÿâjǵF•›Í–"Ô:JÜ™}.²’A¿"Ná">†r\ôèg?b\uˆš ¥*Do-.L5(|â¦çOµÎüƃƒr1Z¢Ø5Šîñ[¾Y•DȃíãÆçÕœ�û÷+»Sr}�’.(Z€Ò„¤¬¶S��¤ OxBÕ-Ü3nVÏîð”$QŽûý"/’5Z]jÛá$TCË3Ï;I&E×âîd‹Ú I× ñý*F`ñê ¡û_{±y@šÔ�NÀ #˜óÏ’ºŸk# 7Rîá*f�]é ©l�ÞoOè:¼ƒ†!mr[ ¯xœ©+Av5Ë�ø…@„åïÜ 5ÙÊÿ(n‚á- LÃà§ÕQo[ž*Ãf³Æ)cK}�Æ7Cz0*A��ÐðVŸ¸†l|"K3rÜÕ·kœ�aëýf3¡û´ƒ1 »#ÐÐiÂÿsài&*ÌÎ×LEìÏ�¼UR‰O+†6±Ç¡žV·(6Á Ú�¼ ±\¦ 2z v¡ó)» J.2Þ˜Qœ‘®�º¦¥à.b�.Gï!tÂ=ˆHûG:áX¤½gI\œ÷eÇ!ì]MS¢Ðá-N qjøI°s”EðcXþØ)‰-ž€w¿»€;_¿UO"¸§ø/Ò|3\4‘  ½!å½;ŠYoª—0¡ºàYܼ•b÷7ÇÐκºK·èÏyï×—ò;s5p "¤q'%ÏøÚ Aøi©¡�3PGs"çsxÃa´Ô‡£{UötC´jLr5³ïP20j‘æ;X=g °’MF³i³£¯‚\ éJ¿QåP! ÃX¹ (M/´^Õ¸7Î’î¬6ò.l™¦-H�*ú$]6ìë+n-ƒ ¦>á‡!Ào_•ùèËe™Av›Ì†£·mœ°Û¢/jcH úrKEÖýœ¹fdhLÙUžçÞòÁšü§èúQAæ*€¿F8ò™ôD J&„Xæ´<Ø�ºt°ü�U�Wb(¼«V‘°+ŒÁânXG†)ÎZ‚Ù�“79!f$9íIf]/wÀ}”YOÔ•z­ŸTkÜYÂñåyY,ß‹óÈÚÏ�T`'_]T~Ã`˳ÜÑåBͺ�•�õ§²_Õ>ü1>V7ïÞ)ˆâÃD›)æØòÃg%nÿüè¯ÈNUˆÑ§-›_½ž�þŸmaé8ôîzì&·‰A!&îlh + ‡´¬C޳Ì_†:è¶�S3¾J%ýŽÐ9YQ‹­áæcR,•ò{Ï<¨q¹¡dƒ‚ßçÀb:ÔßÔ'z�6VXþ-‰‹tÀt´¿w ŒŸ�Gˆñ—.ï¾vV«Š¼¢Lƒ& ‚”ùìOˆo(�Ðh×i9þÞ[˜›ú9§•jkО˜¸©ÇÈQæ�Ì­¶_8Ú±|•�õêǹ�Ñ,�� º{ TG0°ˆ6x-™µ–v©xvj÷“CÓ°]=t)�çí2®®l!Wil}½–î#›µÆŽ�’Ôi‹Ëß¹¸¯Wi´¡:{œ-7¼Ð÷ãA`˜f³pê×7\9ôiô™5®‘›6~A5{ì—«“`™ƒ?AÚÄ ÿŠY�Søæº�À´ûܲeØ+„·´8°ÑZΰ Ø­ÜÖqyAë,þ.Uµr9>ìtMY7SÖ/¹A� A_%ÏŽlýsx=ž6®VC‚Z•°6©v‰1�^Gin9Að¤†eòG'ö¢ªÎÒ¿ùéªRyÍ=éÝt´¿ÄP™æ7«ó h×)ZòÊÍšXöŸ“÷=¢JHÈ”Õ.P ÍKЕßɘ1�þ¾(úšgÑáÜCgëª6¼µu,¤úƒ‰c¬üÛýâã kS³LþC<Òu¯˜sOþo[Ê£¤WŸSê¡eu"‚›ùH/¡~æè.—°$¼ã&#S´ü^kÆZN«ó²rha ÒÅ.åÞtE’‘YJ™E¿µTæF/ît QÞjË}9º‹–~ur0ׯ‘O*i â3W$PÜ+,c"R. ŠS�òƒ¢5+ÌêTéf5cU9Ñ­ kËË7˜Ù[}´ u´¨8L-ÈÛ~0ÒKtåTëùØ8Šû Ž*"Ê`7�ÂG‡q0†iF ­¬fp÷ É…�*Œ ÒÀ/J-ìÊLý¸cý§ïŸ¤ç{Ó™šoßÑ™–/xðú¿ÿA23+3È­8˜›g\©O:Í´“B°�€~6™ŽGÀ3°éÛÇšo IAëtNaU–jè�M›�´¾ýs‰p3‹‰¦$®œÐŠ0&åJÓ›Rl.• 6‹ý„1Ò�ZÚÏÉŽ*.þRO#:¤<“WOI%½º^síÉ—¡Su éÝÓH¶ß *ÿé"`1¶ƒ=Ž�§ѹÃѲ€ÚÐ\¸N,-öï¼Êad–„ýÖ!­ÐWyì§$ œ#´}éeÏ’§ÜYòæwó ¾òŠH]õ�Å=ûR8‰£—œ‚áþ—'1.°a¦_$ƒ$íSÑF¾¦ËË7•ŒÜkG‡Rž†™²ãdƘ2Ãéÿ ³Y÷`nbÙ Í 1î¥ú 샠NŽ%³vBè7" ÕÊ ®[Ú‡Ws®D áóˆ€`††Ã×О“A†¸2\‘¯*·—šýô) �’„V”¼­e<7¨KœB&êÕŀ࢛º/[+òºUj,Ê!Ä!ÅMB�:m ¥�( ´›Ö¹t0>&:#¶ÂÍ(¦}ôN,Ý(r>cQA€t~ä|ÛÖË%ÏVÉæB]�„d0“aǯ>ÁX?IƒG¯uØ3—ÅÐyším |f¹&¬µðÏã®H >†W)ëÿ¹;U’:AЊºë“ò0„PÛUV!P4Ìqkhf¯IítŒ�ë2•'-ý‹vßý•�âiU£•G�}*`Iøè—d[KlFOÔö](U'Eª‡E˜Ó`–ÃSÖõ 'G3ЭyÖa{Æþ¶KI¦]p¬« ¿3�]ÿ•öy8ŒÅêYÆ]ÅsäáW¼ªkÖÅ&ܵðý²Û ùÝæÓÛEr¢øí̘ �Klµ,ÑòÀµÈ;š(JY :Î%Ü%=@ꫤÿF÷yn"´ö0ƒ&Æ Øz�$à—Ö.P›ó-.°Ù0IzÌ/tÉ=VuWUÌãfç*Sªî^­ðë~Αø­$ý™eÈ@Öm1z¼÷yEÀ··€[¦–`œÌE¡’èD¬ŽA¯ò=r‚.Ðmý¶Ã °(ñQ±>¹e÷¹îå2�vO‡õ{2Ç6¶[ï&Ú©YÇ(¥ØÞTµëp·Ø½Å毰Òï¸æé…C™Ë[œèõDt½ªtº§• E¨ös K¥öÂßDk‡’q®Ê€W¡/Ê%W‘µÖÌ=YTüLx]K†Šà³4fÁw¾;‚ÝÛ1þÐ/Ž•ý5S» Š|&G¼²& “ï‚ÄÃç¦�š€ŒæãìØEä«¢3c†óûoÊ@P%F™!©˜îFŸ Q¤4¤¤N‘T³Ã¨wÛlâ{â½�á‡Õ®¥Ì±n÷E­ äêàø­w_–‰•·hÂC;Kô›dí1µ–¿¨WÚ�CI‚Ó+ϰÌŒ0 æLM{#£)�µP×hðêcµÕ^?๠׀¬¯Ì®›úš‰š†Ù·#.eµL˜�YÒu,tÕ`ö³Pu4¶¦¢ÿ†yc¯–°“VpO…æU¸S+ºä{+§{ñì ÎãW¸D³-„Ïg üÜï~E³ä# âsŽÜœ>tªF2ÉùCëh˜�Ú>Sp–ÿ=wÅÿÅlŸÞÐ8Iè¶ÔpQ¶®V²Ô»H"‰0 ÀTÊ9�2M—K=ËŒ4‚Ib]g¿ÔvJ„t„ €‹eš�}Ϩìðp?ìWš5sOµŒAeºô8å‘Ò˜�”‡H(3»š~èXîÔV¦ëÓnUú”àÐD4Y¼*bÓyvܲ¬ØÝžAÇê2Ùv¾ò]L2‡¹©é\Ú|w€Éy~é¦~Œªöñjþ6Iì¿iPŠÈÞnÂ!`j²¼íð|¾ÜÇû†2Íä q ¸TÖʨ,Á®*.XóµhWÛ]ö5Q™Àé?Ô{)Õ²P°Ä’?•Z¨u@¥˜'Ôžðl{)©­´˜ï`Iˆd`Nôj˜§ZaEöõ0å3>î…xcëmáÈ Kõ/k@x=9j�"ŠUuxìÒDåõäÓíôÐ)ó·;ª-ɨo·é´á3ƒL'%X´¯ààÂÕn~zòtõÒHÑ8]nPUùÖô/Áйë¦ÝLž†O¦"¿·£(^ÕJ/nÀ–M&†é ŸÐ(†)M8onÿ‡% ó¦öÝ÷`k^bßJÈõøŠH{c[LZœÂø¨e°TCÇ*y†=8‹j%oö€7jgŽ#àºÀb73oõgd‰ýâǨ0± ­8fYüäB‡’‹B˜8,mÜ»M2»¢“Q&çz†ìïRë­ b·¦@q>s‰j!åe ÀVs�I3>yw¦Ö< ²3X� óÏíè-àXs 6‘\‡ŠfPˆ·êðw‚g§ãÕ¢Ž<ž›Ï`U løí³{æJj,Ò9l·¤­ fñáQ\Y6› ñp0ÖÎÃPŸr¦¡¸xŒˆè½¯íˆõ"Ì_(c�!Ê0I–�Z8>Áa¢ÙHÌ˲ˆØ�ö~бjz¶aW…e‰ÎËžÏêë6¼âÀŠ€}�SúœÄÇž}‰Y(ÿJ~éÏ“»¿8óóθAå;û+p�¼\"ŠŸ�NÛÊvᬂyÝÕ6CÏ,„Ñ[öe–î6!Ê”�‚y¾x—àñ´ðãIØW\±ë™$¦~?œ¡e�å+ÏŠC«“Œþ…Ÿ,a %9D³+RÌ?³Ž„­  ÅL͸üe¤¸P^f.ç²¼Ò>T¤Ú糕Û�B!"µŠRÓ€Ab÷§êúîÊÈÙï~Ý–Ek[«œù|éÝ�SÛøf•°]K>éÈA’­ î9XÍE‰Eõh PÂäÚB‹8ˆgžo{Yš¾êØG óÅëÔ#Iœ`êäDÕq�ÜMP1fŽëX›Ob–gÃZ.ê 9\“"äµ+i.ÃNÎiú‹¾œlžß—ùh;¡™tÊoSX Eg¬1ùvèþC”§î-ÝnIŽäâVe�Ó›/�t0^›Åé©ç,Ñ‹]ªaäs4×û­bà$DÆVFV,(ÞóBjË5Ò í'�ÿÄÎm¾û7Œ50¿ðÙòB]ž¦EŠaå“I÷1j%º ìM—6ebäA:2§Æ×H˜jÝ«ËȤqxí c§ÁªTM*pîÀ_ŽNðn}ÍâÞ¾§¼ë ½õˆzossÆuxSžÐõCÌŒŸìp¹jXJVÉ‹Ês¤D/pO#®ÿ›kÜxæ8橌9W—/ÿºÔ™b:æhІ(Ë�á§Æç $‰ÔÓu',…Ó˘J÷7)§k²‘ ³•@…ú¿L$¥n8’î;¾Ôå� p !“p¿CQIÃAÓF÷Wþûm¦à†a󬎚†³ÛŒJóšÚ€ƒ+ú0”¦ÿ–û$ÿŽâ'žüh0z|ý¢ø}²TÏ 6~'ü¥ËIZÙ^xj6u>å`q{ñ ÛZ@DE/þpâ:áq€;áûw‹“Lpœ À™3œÇà CÒÁ0‚ÄÁs(zµ{¼cdX±|h %¼ñý[[h ¥>WÙê,|ª�?BÁ!=~µ?¡?±óŠÒëe?½É2—²ìbß#Êà*Ê-…äñq9ÁÌÑMÛŒ©\ˆ}V­âï”"‘™Z¬°ïNÞÀñ'ðûHfwuBW[‹ctÚ‘½�}ŒWê‰>-ƿưî ÑMçóɆéÝËn׽ްÙ1B &†c”°=)—äÔ©5±+£Akz�o>îCB%‡þX9­‹ål5Ûü:ð&H¼I,ýR†çûƒò1³Lµ8ï<ëLÁö:�ä1NEÕdâkÕY,YÆ&Þ!bËåRýMl²±¶û˜DÆÍÆ”…ÚM¿ÓÈ5¿.gä'{È.8{~¼-ô§Ÿ³²Ôó‹I`€¦´×b�å2ɸ�:J²ºR8ÌW¦è)±!‡/М”õ8r’R5ù7¼%pðöwwø‘ÜË†Ú MŽãFv -v’5<ð5Dsþ8a(it#п+ç[ÚÒ¾]aŠØOÏjNY°ŸTy#(I"eqC[ <ÑÃN+u ;®s ¿Ç[®±Ò¼êè«*�È^Ž‘ÕiîÜ-°Ÿ?öüt.±Êþ¤ÙÅ`6B6æ)b#[º±¯Û(ç>8D¶â–`¾ÙHºûi˜Ú\œN§%P¼âr3žæøËf†B6õ2Dâ(wÈGiOô/ŒH—ÂÀŠˆÿÌç^a]¿ù‡]z¡ØÝó�Þua˜�™KŒ] +>½Ö%BÑ_e¹Ui‰\6‘DW¨‰|¨G’&ƒ¡è«Aº¬n~…ÉjY�UØ=ik¿�zjÒz™zsCñqþ‘šŒ—@‹ Œ›"$êµ–¼6S>†R}M�tŒŠsªèp´q ÀTF8,ûÆ0°²C!*Ëjv⯄»haï]a™^1§{Bó*d¯gh�#}2`æ±×‘‰™D2â:bÐiÏbC©k8 moKiœÑGg�ü¦½Ónjn�>×@Çôߦm%‹fEúm�Í„2ž‹•½a¿˜­‡GCé`9æºüÇ\$y\Ôyy^[ܶõpZÉW.ŸY�¶ç„ÆÁISCs ±¨x¨±£˜ ØÚ“0`#yÚ§žÊЪvøL9Çt]'k›8ìŽ6©~QÞP”azsìIͺ‡GEŒôîqgÃ[ÀÿÕªçUD2Âxœ-Óȼ^ˆã»œq¾, ûZ”ž. ý;¥ó÷ëKeúr>m&�"ß%cx­#jx§œ>ïð^*­4~„ºZÔ€k+Mfî+óþFU¶x¼÷…C¼ Õ4X’“3ªº ûtHBGÙx1Úðþ.¤ì]µ4Á*øböã‹Ö«·hžÖ-¶9�Ñû±Ž0µÆNÜ[äÍ¡§EQq Êÿ�1ö'”i„ÞF”ÞïR‰ê[išðƒ:é ƒ�»mŸ/šÝ”[¼ØmºQÂHtC.qÏ W3!³!‘äø`a yÁE¿¨6ÉÚ]ðŒ–?ɶ ³›ZtgéT`è¿3�V|%¿ÅQ¢³±Þ„øe@Dñb·°ßºèdaGÄÅ»èTÞ”úñç†Éÿ»FŠ¥5º'Ššñ%«¨¸óŸÙ &¾˜Y£k/Àô–„)޾7*ƒM²\eb8qÚì»g»Fþ+MKúP •™iý D*{sr”ës¡ñ¢oHÎFŠÎS‡UÐJˆãø­r*Saã”™BçPƒÊÔyYPÀ&PTß.§³wVÖ\`›HμT}g¾GE¡6ÑRšˆÊTŠ�S®¯1Þ¡Úkñ€‡¥4­.²Ñ»Â‘-8ÊÀš¹0UœË •»N�î•wñÝüëó 6£¯ ÜôåG‰jÇÈw FmÙÑü»Þ·jïe"´�|ÒCxa{‡"„KÆègŽ ¹ŽÞìrB<©+Ñû¬¥sjbÔ+0YšJÝ;ùñX‘}ìãUrTšÝ#-ƒ¨É';öÑÐ’'Å7BÆ|÷öÇεáÆ9!´á£»™ç›*`ìµÎŸJ›#œ°+U é†zÂNÊH¤\Rd¼héŸGÌn¢_�#ºEíý‘2ïûR ž÷ ŸzÔõBV2ïƒEÀ”t)Ó<‰ñ:ˆÀ¯Ÿ×Ÿ²ïEøÞQ&$àéQ¦h—Ï[æ·}¤('¡©+^¨ZE‰G ŧÑÞ²diPKL7¶EmL¤%â`¸üUºÙXbò¬k™ÖM®‡²õ_ L¢ÑJH–ú‹>y[ ƒö bbͺB#–Ã6ÿÉ·‹©5‹»²F}t|âXàW(—IÎè‡Y.ç¶.µƒ/Œ`íߪÍÚ•�9¨±ÁÉëkFôj�õóK–W׌õ^�Zõ¿â€ã0”HU¹çý0R`¶g‹·<3¶�Mʳ.°x (,ÚøÑÚ×|ÎP;wm®„ƒ¹dê] ÝÁnË:v}3È/Ì ýÙîÂ󺻻�g /*IQ´ûÄ0g6Äøc‘ôÖBæ“ÐT©ÑñQ¾ Ìò‚|ÂŒè�ñGöT$¬ç0 ºÕ‡VnüýV¢Âg÷Q5÷Öhu…¥š$„¸y&ÞàpŒ´µtÞ 7Sôjh|‰«0#võ½}7¤]Fq�g‰‘'tݘ›IÄ[Ø6#kë;‚|çmÆ—Ÿ$\çûa¨2­åÔ…» qŒ›ËØp5 €ªbb®¯ãvξ‰š3® $"ø'æ:Ê*Ê â3ïÓ V’óéy— × ‡>J5›c ñU~ó^p¸SÃr¶²§e{WHKxã‹"{”¯p'¾ù˧è«í¬ÃýíÞÆ�¿ò ’@‹‘D.,ú”YEô廩?�ʘ�ãêÛ1µ™£Ìºl’ “Êyj2¸øB”ä'¼—/" =”ö’”’ q /Ç%Ä“D\�åi;´s^Jüo*æv˜#ûf©ÝÂVìLÔÇ8¹FÕ¡° æï Àµ9<ßmÐó,ú«LgšRÁÝójJ_PøUFÃÿF¢&<ÊŒaž_É� Ñ}Yý/… –(ÅØ[uL7‘ˆäDÈðË™#çŒÜe¯Ï&œÂÓå Ê©,(wkŠl8yGh2*·A T`î\””–Åï'Í�0� æ(Ž»9‡T§¦b N€ß[=- YùLñà”{.Èù% ÜKÝøø.Öa©ãÖè½É   %ãR5KÑ¢s¿Ñ¼Ûú™§Ù‚ªÎÉé2ìƒÞ†RÑÍ�ýU@Ukó7�~çu21=©Ðä]W3 ’öôEGÌí�Ø$é(Á%˜¬œõ,pª,�‘ã ï«åž«=|Ï®1 çïwŠ‹üf< õ«…`†#<GLLn@=œP†ºš Å@µñz›~²·Ñê üjõŸáüïH-ïð9¤1«g+õMÜí©cN5ö�Âx¤Ú¤…–�«½ïÜW7ïû&^)~þ`q39>芛5ÞPƒ�FwHbü¡àtýFZ3�êÀ쿉9ˆnݔێf’ÁÈQšÅx”§,éžC:I~¯^š•H›Wß3 Yp �¶ÀáJtò¿$p³µdÅжéÒðG£ˆ“¾Ï†óUŒ¿¾:µIôw—ѵ:¬�š…¦ ºóˆl‘=1 •ÿeýïtA÷­¹d•m Ç·æGw B§œT©ÑŠ«b¸Uõï9T¼¯côƃ:PC\F¶Cæ%W�«‹¾ÁbÃÞ{ÈÎô·x0Ð{rƒ� ŸËGÅLX|žõûÖ(Ø*^ó Q·'¦ø9ðtÃAë›Iƒ‹”ü¿ {`ŒZ{'ð»<€(‡`ÁŽŸœß{ ß,®Îá …ËFûØ*H½‚©^GÊB4>�x¯¶âö@ÞdrnhStÖP4–„{˜LH\ú¸SØ9ÀD÷¢ÔÈŠ¿Ü´i9ÛOÄÍ©nÁØÕÄù,’5ª˜Øë•±4Ôƒ³�Ò‡‚=uÒõïÇÝÔÌ÷#F—øC-Ū †bT¼»ìD¬Ÿ ë%6Ã9ùëb'¨ü¹ýê|rU›!PΜrÆ©5©@øu@uoî {Åø\ ¦c …Á(”¹åÙþd¢¥@§ÿK{GœŽ“Aª”áÈßYÇ�vÞ±tßNÖÕŠn¸ÅÇÄË´"ÛºøÎÓÓSFPO�‘É탪G°sHä0iÂ4?º‘Dž2s"4㦲5ÅÖsÞ°øNµ™^¶¬JßUföò(küS©+<‚�Ý‘–Ê W;Ï¡ëIí•;Ù…|Üà¥Þ;½¹µyoï^A‡émL3ÆaKg¡¬\óÏÙ0×<ÎYÓ¾!tí)$TMÂQäèÄg>�„d8ƒ´§’9&Ël@Ag\)ÜÉcMˬd½CCçÛ(ô‡ÌŽº�Ѫì �K€ÛM¼&ˆ®žI5X1Ýò¶í±BdÑ|ãÌCs«ô¥)BE-àÔÙ¼ä»%]ß§tïß/âæ#�ò1`JÊ(O÷ Ýú»Ê�›1¶zb x|–ŸÄp–s~ dá‘ _>=r‚£ßÁ dÝ kËÅ‚Tï~Bù9¿xXHç¿|WäCN’qOw…`¤ïñDüoÂ�ª‘.^°¿ÿÏò“ÞÖÚz0ª6óõ¦BÍÁ©uÎÃù:]o„ÿbŸ#ÁŠ+÷P—é¿´Iì~FÕX®ZœÖ‚ç5îKh…ˆ…СׯÅ{,øsìŠø1ò½»½ŠO {@[#ï3ù°±2x@µ+` šÑs“õ�g­ƒ»›v©€w@}€3G�Yö²”ÍÜ)n›‰¢:Svdî…LeÂ`,Ï}ÄŠ))ÆOžŸ|X"¥ºµ�ãÉÔ‰–ISi½âöa °þ%.k SÍú¬1Ð?Jq拘Ӷñ×fiÊ‹`‡ÜÁÈÑA´9u°òr0­Ù¼Ã§ÃFzö*ç ɉ ”È®s<Ã�.ô)ZX¹ÒÉg|ƒÍ¯oÌ âX-x³Ð\ð0çSÄ?åY€|Å¢2tÎmj!a 4 4û»ÿvýƉ"V޶,;sŠ)gmC~áWê— È¦Ì�Ýq‡�kãµàB¨”U,`y—£ÝÇ''qU3¿ÜçgH/ûÇto‹š-� ®èRîü–(JuÎiQCëã�æN›dßµ%ªôH4Ô#�Áèþ©±?܆,WÊ;9íѤˆ+' ©Ûi�Çý¬“ì±ÎF�UO"Âñ·Sò¦ñæ(Iœt¬LΖÒ·I²\Ác^K¾9òüE<Í6¡¾+�›^3ôƒŸÃÚZ%d3Ç\ð Ù ]ýgN}ºü…·´OUe‡¾�¹µi{g"o¼{bÔprÃIý £˜’'ÿ\6¯ž(+ñˆƒ¬ñt ›’ëu»öv¬ÛTøà1,‡â9ÔÔ;·M*yEÜòtÈÛpÎO©ò'5”̆¤¨Ã�)àÛgyçcnA ¬o0\ •O‹%Ø£Õ~~¶Îl�ß•Î#†éêðÎ<‡,eïé–öèÏdCtɪŸÖ½«Ù&°y­=à9†Œ…tKÖ2Þô¾É½H»€F4(”½¾ß�\õy×·Š)^•uß×#ñuæ’£�\\>qîwLÙÕß“yÝ+Á�±²±ô�™¸]œ´m¬¼Î>¯ŸŒÙ ‚ik¾Dÿv´×ã9ž>aƒÜ;0}dóf�X˜ë!½š—dš©>&2éòU3.Ã/Ž}pÀm1ËL ��èͳ†o�޼e àÒœõÿv+fÉSmf:äóB©ó¥_˜œ^èF×ÚcÉR­-‹$#¥Œ[O_;UG'*ªò‰úßç¦do Ñù…^¾#‚Ãw+@ˆ‚¾!÷ŠK¨ëŽa(r!ÈlTÞ÷¥„$涨�Æâ·;¿Ôá#/‘oï~yó@‡ôÇ7Ê|q3£S¥ýºr³;HÂ--9Þ:Ò-ïeÞfè¸z0ðÁ‘˘Êí§‚M­´uéʨ¥mcZ›îj'¨M¡5;gO†\z¨1·dM¬ÂæZ®Ód=p­,¬Î6t-Ù¦ìYÍ š$Gm“01¼Þ>>)Ä>kD²–Ëìù�XqWÇkö–뛥]]Õí¢ÓË'¶ u!?£)ÿƒÿÄ€Fh’k“÷“¼åzê7ª'¥Wµœ«C4>3Üp„áÁÊ:Qóz–÷L%µP�ú¸Œ  Wà×c#s]´‰®w诋œ©Ú:$šÁxÍH5aWÃI'Ħ+·ƒ�žÿ÷C.m å¢]×YMc+ÃU³°�}†g€&–᪢}�7ƒäVÇ0†o昼ÒsÇšn(}Ås7¢J,¬D‰rÈ¡6µ@‚âà_˜ˆJ­¯À"E‘Ëž]øfÇM×B�Ì/¤³ -Œeóæ Ð>Hs4d*‹76¡¸ê�á¥Sä€"6‚€=.�€&žÄäˆœÎÆíj–;ƒÌ‚©a½þ¿Ý“Ä“o@ó$“RÍ5“ƒd¯ÌÜÆ”¿ýfSþ6¶:žsu Š£ ­_ÿ[ûåÞ¨Fzç™´e^)§åàS·Ä …{-ùûÈzç {‡hV$™gUßû¹+댧/~æ¥�ýöx‡bzeâO™ƒLB›ã�ß4º8V`ýûÐ]Œwz„s’‰/‰+6DúÃld¶Ž`—Ù8#ÉäøÈš !€‚Û­Ê9w›«öxš¢Äæ}ý"Œõb#¦…QEذ }¿„è�i‹z&Wý —g&&½ÏIÃò3’RÀз2–[ëî{Ÿ«år2�E˼ºáv™_EÚ(¨�÷¯,ß•4¶{(½Àà/‡ñÊ|$/„˜Ú/Õ³<ƒØ–F«’›5ÿ“Àÿ`ͲG¹uôÓ;ð~‰ÜîG‡ŸªV¸.WqUñkm(Îøe£ü{Ò-ܤ9X8ɤŸ×:ú»ÚÒóue™•Õm¹šC*nýû\²I^¾°ß PP®ó!ŠU5.9¸«É˜ÃõÆ\ÖGŒÈ+êO�ŸÜúT-¡–Õ™·ðPÏk‚¨É\H�%ÃY éW§C©æ‰gÆ8­˜êˆWµŠö38�A¨%‘Õ pÖÄjêÒÍ;,BŠŒd¾“u�€œ£ôlÂ+1i]ä°¦åƒu7KÍÔbìܤ©{}9h‰¿Úí”›–6÷Ø<Ó�Ì�è÷J+å3ãX¼m®ÛaZŒ^‹ôl3R÷É$>Ê·¿s™®2:`�1…¸Üerôß+ºé„c�O“6Çâ‰}@5ôžÚŒÏg˜Ry(ïŽM@[i\ÕKÙ�4ý}¢©ñõÍí$Âw�S=Í–ÊlÈ$z%¼øüyÅŬ³æ9X&ÜÀÒŸÞ’°5¥º «‰ÙÛW{÷@Œ÷’¬ŸåN—ãY³rIB›êǪ­]r3†h†ìÌû4oµŠ`Ú‚acx‹¥Û¯Æ|Ìyê]hS±}E­UŒZ\¶®«ìs_Ì… ÄH™s-) žZÝ÷D¤rª(ªRެñÀ "‰–!‡iÕí†ûß:lÂE{Û8¡¬zì™S[»”Ãâùq¼ª/>¯ ˆúöÔ�îª �Üå[9ñ†ùqd*ïãÜ5x—ÇGÅ5@É~aön3`¢D››Ý¿EL?”¤9ÿ¥\+ |¶�«Vûž0§i\È$' ƒ¯á!…HC©dÕ­l­H¶OBЕ‹wÊ|jØŽIK·¨WNvç:´‹CÄf­ã?g3ºBÎd�ÒX“K´£»¾ÙUl’p§Ž±ƒånV³öb`" ˆ4£óB=½*Ô[¦4ž_BHÃ_Ò`׺†m­k�. ÎO§¹b)0=–Š…Ft¨ f¸ö$ól2Û@'Eþvì‰Ñ/Óg„9úɬr™=²2¢àén»'<ä;š4ÈúÖê) ÚÐ;{%F3n/‡?Ùu‹D1öùPþ±vÃ�g¾4Þýqú—KýeBBγõ|ê>�H¶žzl’Ꚉ”^RÎHy^ÏŠ$ Ðß2i ÐWHÆ$[UØn¶j»9²Ñ�‰JD/¸«iuðíøö±µm˜º<ˆäb'À1}Lk³9 ‹¥ÆVH_�Xiçã.$ª‹¤t[—â‹àc _˜=±ÁúÒèúÿëkÌÒö£‚PBÈÐ7«#,Üç2.Àòß2â}X£?€Ëuª�V¼v¥^9øLðž‡ÿßÉ–ya›{ó*%"·ubÜÀ:ÚÐààêÖ/ +š™F½,ÀZdj0Vžåfy¸ ].ûÛt�Ü/�;õ²jeÆh%Kž_ýŠIL”ñ^³Àü/»%}ËÕ?5�ú•wd ¹Ðç bs³i³%Æ—ÒeÍv¬’Cq–’Gs ì·Ô@o_y:?m¸ÿ¢77Hzʘñ4½Ò!+@S=å¶gí »Ëõð¡„“_]¯~#ÈîUZ4s¿²úýÖ”ÎC$0hÍ�ê/GI.𔩝Ü­ SfÊdä�¤ÉýOÐù‘ Ÿ//^\†“ÏÈ6XŒÍ! Ý=fΕð‡O¿ÏX­>~û$å)ðÞÏJׯ¦yÚ=®Ï‡¦ä ¥Œ}ó6.…j{%9&ö_X‰»¾ÉÙüƒå#k�˜½³¶òCR”æ4¿§3ýƒTI/ 5\»ìTö¹P`YèÍ+”W¥ED¯�‹%ü7K«½( å÷&PÊþ]V}áH³Þ¬,¸BAØ:Ö‡ñÙl§ÞÚU\à_©î‚/Š·˜ºÒ�W×ÉáÒlJÞ¸8…7ÜëãOÌ�ó)›L ã{k«Ç™“ºW+rà-ÄÁ'ü®ß`)…-Uáp=Æ”ºÆß÷MB € ôÆh²Ãþ]5{¶˜lLm€ø¦]q4^N[ûÔê®È¼Y0vYÔ \¯ý¿eðùioÙE«óÀÇw��ã{þÖ]¬Æ”Âq Öûñ�û°Ctôàa™öm¤IC­æžôSÛ#�2S»U^ëH£R„ ¾),yèo°qÑ|€9f¾Ýd¯Æ½H‹!-�Ç9˱:þ_má-ìø¦˜²æ¿­8ÇÉfI—S…ÆLé¢2u 3˜&'°¦åªžÐ/P`Çdµ…ydr8º!÷"ìï#¾ƒ¦Î6~§X”B<Α‘†q}•º.ñ�š‡þas~®C€¹³F¶¦ c7Ý›é¥Ñ„~®×ƒÃ9PêrŒy­õû´\RmÙ‡f|Ó\D_«š±¥g’|`²ÑÎùC÷lêýoˆ¹«yÆÉ©·K¦ y7zC8&Ÿ¼ËÇ÷ïù¤Wdb÷ÚÐÜbDÑ•ÙÈÜÌ y¨ÇJF_ób…zmÍ×>?©–ô¿E£e® â!Ìãúêƒ3$ÖnäÀ±—Ž;©Es/‡)„ÁfÓ¸\ã®L1�–ŠáèðÑ¿Úl"ñ%½¤¶›�ó�„juk± ØN?‰Ñ+KŒ™ÁO¢ËãiQݾ.ÍíFÍdr ‡øx6�©:Â,ùéüiuéìn¥§J:ªjÏÉÌÃÕ2ò”¼,¤Xº8jÇ_|»©feùh¸¤áBü;ßl '…ÁR^­ÙjOsŠMFYŠeÜÔèYL‚‘óç±rµYydà¡â§Á4îà9p1¢i@Æ"~ÈîÉd¯Ð½¯ƒaaqÄñ–­ƒ|Vv›� £=Š[C^çûM™)Õx˜›Ô{]¬L °[7‰ñTA¿åS?‘²ŸÐåIä+­aÃ�ÿó"©[ûØÆclÎÀê†Gן0®5…UxtâËj?vjS ¯äãïæÅ€ƒMÃC"vAœ:ÄZÜdsŸ¼ëŽžÝÂï!€0 s!€`c`hJvúŒÃ_Ï7òÍöqäÃâwug×ð¦÷ë�Ç·h¤!ê ÞäêK} Çghõ}¿ëþ”â›°îyˆÓ¨B֩ųʦÌ`_AŒÔ9=�ÜÙ”$Õ :%3([¾Cã0Lf4;›B-Ï äÌßÌI\ qìK�.÷Ó»»†ùOÑ#°¦ÒQÍQل؊ÌF”70�”ÿ"ªÅpJ½P¥>¡Lζ> |ã6ìjBYÆâ�/È:ŠÓÛÉËëþXAb-O»µ‡Ä¿¯Þâ³$ "â:ßY`\ž d£ôæËlöÇâÃÍ â,Ü ±N¿ý~C<®4ë^ÚÜu`( ôªÙ€¼ÚSÓæ<‡½ =óÝ”k逛!‰¨a™P‰B ¾F-Ây‹N»#`4c}Ì_Ìgä´ð/LCùŽ’d¯áˆ{1.ñq‹¶Ã¾œ3QT££x &íÍOy¯ï-’Ì]/• @"ÍO›�žÕ ¥4õ�>äÖñp6lÏ" (lî»ÝµPY5]âFJ-7ðŸŸd^ÔuÀª X :Œêܳâ8J“Eɹ�žáXÒ='©ý^ý2ñsŒ`Ÿ·úá ãh°÷/F>Õuzåòµ_‰NsvÌQå^óîõ—U¦8°úš„b^É™[S7Z ¨š/„ç-†A*:é{* ‡1by);dçU{ P¼2™0j=¾â‰Ë']r77WxbOr&ƒ”RQN£Í€G,RFþx†¾•Ä.Ëð)†`ÿÿFc\[ÉgüÏ—¥/-ÿ¸{hÅHªÉâëY8‰•"…†Gà€3~ T&™oŽóé{s XB’¯âÆa� Ãú-Ç o¤TUâFáh¡Ï˜ è\ n„«µžÊ ªÃ×2± "§ãÚ,ûÜe�íZ ýG÷AÏê¸,�×ïÏ:7ôÜ¬É Ø(LÜ�0Uì㵦wy ¬?ðŸÄ_dõÿƧ¼. kS´oâ™iDj0Y}8£ÕÌ:g8]GÎ]†G÷×''Ì X†ôxôüœ[7H!ß;»Dxs 6Þw—¤2÷ó*¥þ­¤Ö—–½¾§/À:Þ¶t¸d¢&‘¯fÖq{…€IYæ„O[ï2¤Î¨››;‡]Æ¡bV6r%šôÜ!¿ÛÂ×Öžþ’©º90 -0H�®I0øô =)©3îÂåF ‘k¿<»ä“An 0=‘ë%Áz_~^S¶É<Œ“ñŒœ�3h×…�g’‰vBF€¯…÷žá‘ü¸ÞF¥çßë,j³ìÔÚÖÄØ6½½Ã¼Æ;•9ê[ì°4Ë úAõ-Û †¯#ÌRÂc⯓<ª* ÄYÔÜ�­”®çɬXt°o³M¯àºÀs´ÙtÌE%SHgª‚¹ GžÅ*ñ”Ôļ¼Ð�ú‡á#*Ø߹®¶_fËïë0“?íØ&™£¥Qš» Uw�Äឣ™Óý¼™«d v¥�ܹNÆÇH˜ëæ3s�Ju+N_㧃T̘ôB[ ˆú81-òà¨_ä´$kP¡¶Ä q7ŰöFs<´j§HÊ×bÑî$­ ÎÕO<´�Àá1"=²SN oƒ@zñ5úxKÁ.×É4· Ìy) I­ûØÏ;¯Ñ­–VöLbºåÀ°h•­|Õ–^ë£Ñ)öªÅ»Gc±x®&!ñx ú·`()~cœ\ LâP@€—Ó3Ú�DŽÌ¨�ý º“§û_|ð¹`ežÑC~JpøÕC�³l”D¤¾;6ÌÈ2’yúJ¨>Ã|ã»nKl6¤£ýä¼”.㬺 T˜si0_…ÙZ ™°›ÔC´52ÐIñ2lÃHî`ÞüT�û6Æ“N` paÎ~e‚Äû…Râ¾I#×Ý €H.±5a’™'ýXú^¡i µï¸g©Hæ,ƒ×4çeK™vpÜXáÊ¡àÄÞ.Çë½µÿiſܬNngk Œç¤&»37~u¨Ò˜ÚÄÕ´®ä�µVøãSè¡‚®{é—ÐÆBbh7 õNmZQ÷©LÒ#xKæ�ëNê^LÛy�èÎ=Þèƒ|�<×ûÈi/Ùiˆ„O´vãB.¤z !ݪdKöG'Ía›V9b¤v«¸„YŽKb$ ÿ2†Ôƒ3Âþ1¾¤5Ï~š ñ)fýÀJÈÙ†÷‚¨wÂ8#BWÄUëKÎN:Æ�¬ß¢�,jaåe³DR¨4H“sUwþ.Í5+@‹ÏiÆ'çý<˜“|nGú¥!ºE“ÒÚG­TµhŠØ3!'õ¤�ÃÕ�oÏ`nó韟Bm”ZIHß:Ã#åº<:‘篂¢9±ïFålNZåUkÙ­²ì¿À÷qF®÷†zh=@íÂì(®"‡Á‹Sóàü.‚z�Ý’€hø5Úþð+«µ?Ê_�üU�øç&\ª=ùaVWkéíª:8tØfÝ�›¯Nëd�„¦5ªÞÄãGƒ¾aök@&rv ¥P®îŽnõä…jèYu×:¾*Bv£ªHÏ“LŸGÎÓ@Z×¼Ù~ò�Óíö¹fg²´ú |ü„m—bžü@®äó/Š4×z¸ ¨8ÝçÀÓç©Ðò\Å›x«—l¬œ²²¾d €27aØPÌ8oä¤÷•ƒëœ3U <ã6iËÄ»�xûT�¶á™ì¶½ ŠûÉ¢§Íe®‹Mð 'M@©F0iMòR‘ùz#âú‚)†D¤¤gÏ2•;9^¿±ë±ÓkŸPc¶2ü ÑŸˆ"�ìÕ_Ì‚¬9í%C§£~TóžõöÉ8oTf-÷mq6з�²^óœo{ó]èh�á·­4Ò³yÚbžaËàæ{ÁjéXy‚ ª Zâ’Ú.Ó{æhù-ßjgrçB §¡!ç\2qùåiZbÕ¤tà�Ù M7Ÿ{—2nJ…E6m½È*â‘à—çÛ°(ü�¾é(P¿\—2<‚…[ìíTÖö[�ÁŽ…?b’Ü>ñ K”Ug¡•�ƒ~ /2…’"!Oc “GÎߺBBÕêáŽ^0ycãËäO—²Ý,@Föži)s7Ï]²æPôyd›%óÛÒãy´“XÛ¯S• ÷½µŒµ4O�Ñ=—†çJÌæ,G˜0} ò?9˜SOûŒúŽ•‹)Á‹Snª‹›ÚhÅFÈÊ¿Pà’bMÊÎçËC eª»zžBœ‰Êì¶3o/n‹É¾x6óiOÿüAã ½E}ê¤CÞÁÛ’£¢ªn€Nš0G�«ëØé.¨/è$„ÍnqVÇÓ“eî¤WJè3ÿRH°¿NWÜ�Sî• šITOs–^é�Vxò2Š©Rí�ì�í½L¥+R^Fµ¥Í˜�¡ŸæÔ‚\ÍáFsÖÚËì¯ÎC “ÚÜ:ëu™{/”‘—8µcRŽ~�¶ó†ÚsËßww’_ÊÄ_ñãçÎè¢$†OzÛ¼jl#DvBNDn:£\:WÓz �ÞhÇ_ºâ` £&Õ4-Å5 ?‰`ß‹VД­saúw¦�S¥…{Zü‰´*Ë`=ôZTÔ�µ‹)·†DÖ�ÿ¦ú6ÁÊM¿ÞÏcåÆÐüf¹?BóHH«Ñ¯šJ8�B¢WTŸ®ª�ïÖ>ïÏ&ÚØ¥ ‹ 6GHlÞÅCz|°V¨Ú˜¥bÞÇ3Ü6¢¶á¡Úy1³ÀZ²éÄdËm�ÏD è1c?7óM:à” ¯-eAÑHŠp,8ÊNñ_jañRiÂwWs£Ý‚9ƒ5èF¼tyXì=@|Ôz8¸Õ¹˜÷ ×Kɘ%==˵öžÄæ•d%_ðÜ¢ÔkÈ×¶ä£ÙºÑäv6vìÈô~^Ÿpzùwª×"euÎçHãÙh6§Ù©^ýn"�HOyéu—c¸<ùüFð»kw¢IšÞ}pa;Vß™‰3VuoŸa�ÿSº½4…ëñT� \;{�ê}Ê(/-l¼H‘&#+êú[¦-–`ãÇ7íüû+p•|åÔ>Î×߈îÔt ¥c T>ç4A#â*ÉÅ{,È?©\|Èä''¢\$:%%$ôàI^uV¨h,Ä0\a^Î}º~‹0’V}]¾×Úݤ—¾™>ÉÀ[ ëÅë^�}š¿Yñü蜿^Xîñ•�냵¸¬-´4/‡°e¨W¿:ûTÅO?Õ£ºEªúL­š’`E•¢�%Ê7Ã_éöäó‰A›~½i ˜N”Ä•çE…í²-iyEóÏ`¡T÷Z Ì 9 óÈú. ‡uÁ-¹g›q#,q¶Ùa‡˜†2hÒfØzw^?$¢>—õš–Á~/^Öÿ˜Xçpêåe ™?ƒù'G¾-xò¤gŸÃ°ÀO±ùߦ§i¨ Ê4}û¥‚ºîšV†·ýµ¸.õ¿¤rñn{¹–ä�燗•䇦Bż!¢ã VÈ=¥‘n­¡Ì î•^­ò0ñ+OkQ: ù5úµ‘“@HB–zMÈPt< çV�H\Úíd6�RîƒjÞï– ¤tÊÎ~5¸ý×MÉS·±½ZV¹ñ"™æ¶¾Jïçâ}á¡E‹Z Î÷!©H.*0s{Æø×G®°=gnŸÕ{%£wP%²'Nepa§RÊõ³_DÿTœ®‹¤ñ@†¾ò@PŽž_¯z5�:Tú?Õ¶{B<Ê› .l$KLȦž‘ŽnÄó!’NãAAµŽ-ë}DÂÎ=7”È*–àí>\8^zMªf‰ 3L7nðºùèuš‹è޵vúÍV’Ö5s½Ș°Ö%̈Ë�ÚøQÇß–\}×r=©€({n#ê~õ3ñiëÅ¥”ú_[÷÷¨¹ª0,HÁyØs‚7íq&j¤w7àì?å�•JETÑn,±Ã;»IÌ»ªG7õ­n�¬ýú¤Š‹!�Eg³¾›c}‘–«p$S½¿±+Ì.K äØCùÂ\qºê¬*�)›±Í@„Úi¾Ó“ºjç,tƒhcç±$ø9ìRôØ5ºäÿîúØÊ\0w}š‡ºÞ•ƒù¸ pä‘.Ûê­ u>¥cà]mK]õ/[´êI¯(Q)ƒ Dys.¤¾WØÕØct¤’’jIm¨<�.µå  hìÅXKÆbXÁâGa$ƒ)è˜Âm3H1lƒˆû@`œhtÍÍ�ÁþrÝö"öª]Q¥LøôË=8È,Y±ÝÜ*õÌ« ‡ü9E€EȈ“ƒÛ£î’eÝ×(Séðø x�¦®¢šl+gì1±dÆTf“Û¡‚@é$a¹Üÿ�rÏ™ª’Y…ܘ–±<�ŸE3ìéºóÆSTïlyw¯pǦäœGX۱ьâ0w•óÃ=þv­&Ã:ÒqÎjy[mÒj[©Kµ�Yh^`˜h�+iïŽiÖÌ­ŽdËÐF’xÚeö`Ho!mÝ.I÷êÛ ‹YÌÎ<×Iøò¶Bt Uâ¹–GN‚”â*êé|=PÃ(YÁ¤ZÌÊ‹¾¾-�yÉRDñ®FyE¾¹bô½»ß­ õ{”ïß0JNàSùŸÌNÀIMl€P£ße ßbF¤Ë÷ÓÚ˜³¨}hÐù- /Ð+(ïÔÙäÃrCè˜LŸ€çw¨–I-tì `-ì¶‹R^y Nª&‹uï"§Ì!!]¾® ²‚/<èš7’§ñ{¡Ø?ùu[~Ü�PÅCTö*úW[å�ôÓ|”öÁMƒŒòdWÖ–L¨l�ÿƒðá›ò«Am³‚üÁ ³ÈàAç¡â¼ÌžIiŒéµ><ù}”4ûÏýÑfÈ/�ÇÒj'~/Ú }`&jI eY>¿ÖÊö½u˜ÉxãE¥8=’MØ$×dÛ´L�=ªèÿUçpgÖèåå²g<;>ÞN kO×o#Ž�–8Û&3®Ð&½�_c§ÕF6:%ÀÈb#0®êêÝrÛüJ"tzS¼dfáhüR 2Z¾—™½Ë:p+•¡á€ÝÚ¢.pù¤uÔgÂ"—SŒO(0ü„‡¢ïÒÓi <-7‡ÊÛí¨ ; Ȩ¸ „œˆ–‡ÍÂbùEZu’ ›ŸÓã6nŧæ¢ë.!ßûú$©£O™5wGSoÞÀwö#áä $^ü—*·G@ÖÙWìšS€ÂšíÔ»u°emµ¿Ø$fº™ L9Áô¢ÂňFì9$;góG³pa CYbåìjÛòø/ã=�®~ÑœC+ÐsFŒ p£³LXÝ…—kËÁÝ‹Z×T}š3 zÔŽì”7LÚcSÛC/¶®ò§†æ<6r¶�÷)ùÈä‘üjÔO EÏƉíù%³‡¥öŒ¥궺É6�Ëè÷ðM@x°Æ_0OêJ âû"›´.t)ëþä_<¾Y_—'Ǥtò”r©›—uµàëÜVR¸ÆÝŽÖ¶Ä5jµ• .\½í$—÷Rž–Ú�P§¥s`~¶kIñ–…~ú`u?[éª K×CbnR-s&Ûô›?m ìÀÕ""ÂÜvÚØN·WPWÐ�™ÈB(³¶pûükæG´Àž�h‰Àl àm!Þ}*ÿeöûÉ ‰”x“²¼Ý�¹1>Eù�§�µÝ[Çø9UÞׇ›Ê�ybùh?f)“½±ví[8! Uó‰‡ÃcÊ_¬c“ö_[3/CÿvÎÑ]Gå¢Û VÉrm*³°|câjÞò¡’þ��Ûø¿ÜŒ¬æª:ŽÔ_°z8ÂÂ,ˆºÐ|#&I“ßy·Ã!p‘;©íPåBɨ4±Umý˜£­°ƒB�ÊXƒ¨òÖ:r"u®}÷­Q"Qi�­ø›%v%¢8&U³ªñ+îÓÂAî–8^‘œ9 Œ|g?òK%‰õ©•Ðs5clkÄ|�MíÁÊês}Öƒ»ùpº–Ò€“ñêÍå øé{¿K6d`ºÆüY ÄK„Ƭ]=ŠBÈ`#‹]Á®áÒ@ ”j …†ÆKçþâ9å3 …<�ù:wöx’-ü\0å­5×{F£ÂL�‡&�z'ÕÀýÐàÄÓ\4f’õúT,ò„^^Ç»n–Rí…~Ø;³„›�öèé�(ü-¾§>×û�dµóïˆ ¥¼“ÝlO»¦D�  ú­Hæ`B`ô¢ˆ‰¹ši%#‰,óÈ1þk4èÊ ŸNnÃ2¶Oƒs3j·3ÌI2îU‹gÀ{ËÞõ5)åzn>îƒeñ’ié¼AmþjokÒDh`Y­‹ÍgÙlðT78Sa'®`Ÿ?Òà50 ‚”5�55úèW&ʉÿòö¾Sàe]2n•— ÀísäÖ46I¸¥:ÿ϶÷\š ÀG·Or"6#¾Ñ¯O!Ýcúǰo°Rò„Ê¥ç±9Ä z;ª­ÀÇèçv𘵌º‚]€Ä‡~KÌ ÇÅvÏEÎýÉžñ�È7A)r²Óã”�KñZkVT­:Qý³›c!�~ÕWeÙ­¹öa£c:aQ [Þ Hkc]?o5 �dØp/–ötV§9"ÎÏU´¢�àyÌ”nWDƒVóø+»LÄÇÚíÅz€2ïËíauÐKØ¡‡Lž?h�ó±5ÿm”²›,‚®ëò^ÉÛ"¿BÃò/&”h±�±$ýK³g�]üü¡Õl±RXžÅɪaû|Î@¡ç²Òåšòø6·MhF£uøÃo¹‡Á\w(Â.cÍÓ]øwì-!5f“Í�’ƒR͞П^æ Â ÐiT]B «ã>RL ,X?¥b³¼NìL0\w2º0$‹@Óž #‘”âäÖ¶�"#ÊÆx<‡³"zòen¾8�ÈâåLK��7'GPTÆ­�Îì0cŸ¬¢¹Z-ƧKÐ5–™Ÿ8ÐÀídw‡¥ÈS*ˆ(÷5éâ'ÊžþÄÅä,a�9ðŽa¼»Õ) pºjÝtO©Å6 $¡FìÝGÝΕš­Z$äÕ&»¬ÿÞr2!d)ÇQ’I|ÅÊ«ŠL¯†ðÂÖt} ('”MJÆ�¼fnþˆÿªUS35?ÊJŠÏ£*ŠƒÞN‡õÍhºOËþ·ß£+Çù„Ã0ܬ–ÖfN©qs44+¥hÖïRw7«aÛÅ|as­>ôªªÂ§ç¤''d¸)œÔ#Ù©‡õfÎ_³T½9ÀÑ$rש�«÷!òB¡" óQ("Ä€CR‘×£™¤qXW ëÿ�Ù !ÕE®K|&Žb(E€v£mÁôÆØ¹KÊ_Œú5�[Év]MÒ˜˜NÐsÌ(éó�`m´c XdôWš²;¹…Q/¿EÞo€QyÍÛ=íǶÿ5ÿ~fÄ‹žÔ®ïÁÚ)¨Rðr¢‚ïHèåtëß(÷ÒÉѼТFcÒ®¢£ËžJm¨èýy–çaâ×\PÓ�­…ñ�h„Iºd,Ù<$–ÓÒ¥nOþ¢HZ²üþhSͳÔt&líó¬¨*+[бÆ5 I¶ƒX]:>Óò‹€Îí‡Âöð+~åý'y ? Μ;¥ Z{L›NBP ”®µPìÎE¶šN@P4¤¸ùmœ+=„8 „·�£ÐñkêʰIÛ¿á`ªõ«Šœðt¸ØQŒ� íZ<ÎËšïv±gMÔ ’Ù…�ÿ&•èIæ¡ñÐÏ |ïºû@ŠWwj�鴷ɾƒ¡vNm§È56k ÖËc;å} ¿Hèal¨>m}o†àB°+ÅO¢¼fÜü¹ÙÈÖhß ã2t}ÈÖYqÆÿWaj5L`‹ß>Ø»ì…æ +WNZ6œØhG‚f×yMýky;ƒJ?&º×I_ Þð5Îàx.—¶Fï¢~8}t¸ëù(€ªF§³ìAá~Ó‹%mÆ@|Õ#-v)]¬mYƒ2<Ð3wLiå¼À|ÊZœ:™ÂM¾½g3Ì_Ó�Ä4ÿ=±¡Á£â¶f; ÍTY©�q&!_Uݽp´>SœÖ?–@³ÎtÕ÷ S1+Tl†‚ñê‡qÒZGÖëï¡g7ŸÆ¼âÕ ›²Ü:ÇÙÄüJ§1Y¬Žá ¥Û³D,I·G™39¶@×ðªvˆ«A™ÙëæSRÕ»JÚŇÞl¹ŠfJ cv‚Ë„gdÁ¡„pMZˆ_œÓéf#ÈäÿX-Ò •¢ ¡B‚ù5øW¸á,u-P×0ž¸„J`ØKâk1çïŒt+uóë¡k‚ã˜ÈX—ÝÔCFà‘½ºÙY¡—ž«,©Š±â›&Êç¤5¨ ˜¿^G:ûÅÛ}óܱMÌ1Ñï“›9¶ ==¾(·öò[ùUËp®†Q?¸k/Ýøà[-pÌ:UÐÐÎé…h~TyΖ^k†©× aξàþŒ#½jz]ýCŸÙ̱¤¿e‰fë¸âEf`gyBêþØwi\Ìþ@t #²–ØŸ7†NJ73ÙÌǨ?:¯{¿–”æŽí`hìÙÙþ$ ÚÂÆ„…ŠîSá�ª$0ÍÒñ�HRÅaEñ�pÐaûù(pÓÓ êtîà�­æ¡›ž|ç¢3f+×xöys!Ë‘Yú ïd¾É²î'&X¤g矰pa®ÍKoú‰ÍÂ5Æ^Ú< Å�0&›ºDW™Ý+šÏOÛ&l €“‡ëÀàUœ‘ŒOŠÛ<­è[yJ­nÝàD¾ËMYÏ7,J•¿Ç“�Ae·aÍ·h�Z�›q ýª·+[4û�ùF>Y�ü®Ã³§-×ï2Y4@ú.h‘¶¨¿ª9ŠÏõÎLuUá–4K:ÁãmHÌMµ ¬YÍך¸d´1¹Žl‘Ýx1iŠ–Ñ1Ì‹]}‡Õà”•Š£ È÷£SfâÝo¯ç¤××Bm'MiŸ7ÿÝ_iý._ÞQ=Á¹]·ŽŽµÔ¬MTœÎ•&hnyÏÓ_ÍçSƒb‹©C3P>;¤üYßP`úDêM铜Âý׬BNôçjO´ðv‚Ä“_¡iA®íG†�D‹W³†U†ŠªµïjR*É€òY…�ÚþYš§ípa&ÂVhIäL¿ /±B,DR.’øôüw(9ÓÅ D¼ü_³…Ïd6wsØqIͪ„D#ùAy…¨~¶æÛ omË>󙈈œ=IŸÕcáëÏ|ÝP]Y)s8y%ƒÍAÀm«T�¡UYÍ`Œñ�Ú“±¢»îf…ÔbL¨áøS>w†P G$˜2‡m�Qi×|Ñ5'É\Å� 1¾”;w©”ðgý$ËY©¼O•¤8žqÁp,Ž�漑߱>SìO�:R§4¤–ó€éˆÉÁ=ÐÔñ#Œ$•ÀidÌKQ쎗ºô!¬¨ì‚»°‰} ÉtDåÃ|öˆ|rñ~SÖ)áb˜nÐð5þ’øøJ ±î¡Ki¾³ìNÅ»®¥ž•\èðMì¼ I]íÏ»®ï½6/IDóŒliç¾P¸dƒÇKp‡w‹Š’è¤l…»‹V·;Ú|âäuí°(jús-š1V,Ö„B)Éå­!8a%7_NF mÝ%QD‘ÔÎødêÃÓPC„v¹Iyš"Tý„Z³:k×Ù<%jÆÁNJ¯Ûmf™„49�D2 s&íx€Ž$ú"[D-ŽºŒƒó «¡LyrèÒƒë—àܺ \ýK÷L¦ès´ŠÊ7U0_9ò9ü¢R<ôje¸"7(3DCDkqŒ³KÞE×_ÙK]†(÷£³à·ækå²$°Û¿ƒ[u�e…LlÊcˆû!ù½L†Ìd­›‡´"&ƒ_Ì4ÖjxÜ�¦ˆZlnÉ€J�Ïéë[yk‰“€Ì±ï…d¥3äå¿¶R‹ÉŸ–Ëlš±uúÛœ’ô©ópƒÂßôºaÓ!3¹å�¬ê]yôü•ØóøÝm b1‚�UK&A ÍP¾ØDݶº‡·ï±­7‘y ´¿éjj䟎Gõï=/}væè�;Bm/{Qè캸”´)†ŸÌMhÈšS ÃtR9”&6tè·Ì~F€JðÌ,ŽÍ—ÏÒ1È9ú}3Œ¦•^Å6¸“{�X³Øb‚©`:éµ÷�EûO¦Õ¨oXðØz|q¹uT •Òâg-N$ÓS3þ‹‘Ûq0q8sÜÉåy®«Õ‘(¦/ÁëÓò¸gIgT¤v�öîÚQbÙVJžfbgBšoåRï'Gê]h÷θŽ�"z-VÕjh·Gú±JÓfÅðy‡Šè©µà\œ?ªêÈ7Õ±Á­ €Eûs,eþ,Í¿4ÄQ‘Œã9 Š^"ƒÏ\©Ï²€]ÅAb€ú�r¡‡ƒœï@oí€P›þŒ� H^V°|"í†À³Îo¿E™Ã_çR½õLj.ʧ%ÉkÿÁž*¤PþÝÞ�ÿò;rì�üÙþB\ÈTbÙÑB±b_oÛ‰$1N¹¢zÙRh gNZ´˜+Aï‹É‹`3ˆwÕý=!†Mr5ËÚûeÞS(FtÚ)ñO0¶ôŽ1fH �õ9|æv"FªW]�~I€÷P~ÚQÅ5š U¹M#š¬yf�Ê�“ ¥­dªÆÙ÷sMEëN©1ÙÂÅX$Þ­ZIx†·Ÿ)¹™t|²ò†ŒÑŸ¢O)Ô =¶åÓZYÕ»*A÷Ÿ±Š.Ú!ëð³Ë[´¾å!kV˜Ž_•_Îþ§ÖØ`ÕúXhö×&Iɲôÿ²HFáÐ$aèEÁÍì">=QÙhcü×–vÀ˜úI6‰VFÓXùF½¤$ÄŸÃÚ‚�žJ¾o8†¿ùŽs¥zÕÉA šÊ()èÜ?B~ÕÛP.y‡MÔ*H”�Šn£xö¥áy{�jwØyÞšäWƒÅ42ÁUêúœí9-4¨ ¬ˆ™3<,T–A„£‡mÐ:…ÆuÛeús°�/+!p÷ ¾„yÎÒ|Tðº03A…%X»­�6' ³«õk à ²27=«æSjUŠQÔ—W|JRÄ)Ðq'»‰Šª¢¾ Dã‘t^šC7¹°¥bÞ¨ŸbTØå#Þô’Yäw{·(7ómhÌ‘L°ž”’X)dz$¤ÇÅ%QnÇK'ù€…hýáAC0}v!p6„ŸôG#¶r·�sÄýãcÚžaÆSÐm©Á…ôœIûÜ ?aå˶Ë¥K}ϫ͖£d ‘Ê®þ÷z(©çÆIáÒFÀòw¸3|Ùc×áœÙ@•š¬«Ò¬.ú d~DÛÿRjʘô9Ç>ŸÇø?€|¨¼ÍÒ½vt 1„Îý¨è‰Â²Å‰Vrƨ!z�ëͼÔdòM˜¶ˆ(Ê[�#Ø´šBvm¿˜ù—–tةк˪�ã$ð ÈcÞ¤mËë¿ÜøcHû¡pàdV*‘ÇŽC–Ûsì R õú´xvãW„(4f¸ ÙO„m òÍ6«qV!ÅãòTq3e»{æ�Db qå¼�yø]$Ó4 ÑÐæÿÌ�”¼¸$œAe$_1©½Âêˆz–Ü‹/v4žfÜäÆÐ|®ÛWüó€± ZÃôÍ“Ë;-¸+ˆ¼¿ ÜÁUCúÞÛ‚z–và|góÚµeá{u ù&ù&š…")¼�7ul†ŒÔ#±A|¶OÏ�Œª#ßÈJþ˜)ÉÔ&ùavÒ�¦™Ql*aQ†vîEdFœ¥ÂKTñ»¢ƒúû_JŸÄŠÂ Í@³’¸ÖÁÇçÜíäCج8gŸÇ%’îUV&e°öunÛpšš‹Œ#óL-À²•6„©ós÷?6°ªzëP4%Yl¤óDèO};®�w[L‘ÅöYÇD,ûè Ãñ?¯� mpeUߺ×^lõ¬~{C¢Ûî ØRºÚ ¤j7‚½e’‹Nâ¨b§m½Ð¼pþÌ&Œ›³.öP·Óp3.ÜjZ'”‚§’ 3FÚvç9óR²Å´=_=O³½ä~žþÌ©WD#*˜Ý×öhµ9”'‡ ƒä I9–ºç`)‚üMµ^ùÕäÿùÇš—€Y¬»{ì¬Í¬ª�QifÏ4í §ŸºŽ3³$AH€†÷H7fê•ÄÀñ& eµI‡€ Q%“›gS3oM`/¾‡YbËÕ4y±)}ƒÿÖôñÂ<žêê¿ôÃþ/ SŸ˜›W¦ãj ¾¦ÞÝ*ãZìñ†Ú–N Þ˜RájÈÕpËÈ){­t OÝ9.²‘�g”É/ìjåĨø#sÙŸ¹eöIY®Úftëœ.³Ûöð'ž:a* =^ß}Ï7™&¤’Z¾smñò­™�ÃØÙ4ˆÈ§fðF&‘Éé#Ó0¤„Ò™1ßѳRni»ÍO[BAak°rlfÖr�4>Ú‘ø÷yòœù‡½þÙD"u!ª·ÙyH�Ã`­«"]y†Ÿ7Ýh›£¹1“�æµXO¼"’‡d¬(È SŸ+S4 àæ×^þŽû,$a|èö|ŽwO Í#„ÉÃ�±3g«Kª ´äЙS5~sSþÅ5ó‚©ð$W{¦™ w¿ü²`�-–µ-Gë¿]!k•™ÿqädèTƒF•²û$.¥ˆvÁ– Þ†�H£fó(Ä“A'C"׈ 9Λ½KŽ„wûÁÔN8#žõÚî<ílÌ�ŠüzĤ¨Ç0$v`âÙp{} ›€ å„áÒR|›Ñ£�0e¤ÄÇVÈÿs/`�Ï,^i¦ÚÐW™ÚÅZä¨Ñ½³‚ÇLºu3œÏœRIJK7ä+ùƒ÷ÉžƒOý…Û�°ûlBàoÍwB ßm�Í? #~¸”m+Bv0yß(0냿¡¯ž'¸ÜöƇåûåBj½tØŽRË1¤?�ò×k(9»gÛ`ØßÜ×8ì÷�Åî}4‰¬î8Y<¢ÇUòà‚žX¤÷óe<ƒÒÆny$«òBG¢² ¬A6%­-â»m�˜ p}Ôµ>8õó¿¶ 2XÑÍpו”«Á@‚N A·Jh»fö¸ºªxVÿ¹.”„ÌoÕñmµ¼Ø¤ƒ'†»J/e_WŸoW{Ry6¯‚µ ¾düS­H.'Uc0 Éñaêž¡×ÿ}dó)Î;­‚±}øÏÆÄJq�çF›\õW™T=pyÄocl:½¦ÇRÆ¢G[Z,‰Û“²ÕÅ€€°G£àîvº÷F™<‡R£DUR¿ˆxRèä:iPÕß”&³^•(k°M9ö©¾âÌfE<œŸêö›ú‡îŰÛôˆ„œö-l1|ÚjðsÇ‘C 7J€¤¼?“vçªä6!ÔÕÞ­’Ô=o;ô�Z€kþ Ð\Ñë“Ö˜Œ0ðDà€kâ8¡7ƒNÈ$w»| xÎáM"ŒÕ×§Šù¶yaäáÒrd ;™½äj2Ãúø5æèëwRC„â‚~F< †éìqÈÄÓ'¸tK6õ]òk<b©àóùŸ½)§bk‡�>ÃÆ…¨}ûFÐ¥t¤653Ù®Åyl'É`A«*�‚þàgjLyñ{i` +ÍZ>žC�ysÄ–ß+Íu!¤2¶¼èfæW7Žpù–•søÑ†ÇöÍÚês¯›£¿–CÆu¡N´=k×Üȹ‰ÿ4L#á•9Ÿ ÝÇje»ww•×ßMÊ2o¹Üš*IúŽ‹ø¬ê9&¤^;Fa¡•tõü+ñšÙ©ë©àèþ2i6cV,¨ ¼áZ6A1þ4S¢XÝ‹'v ªŠšÄ¶Ñ%þêØàVîwöÀ•ÿóÚ´i‡kL‡iµ¾È%�òŽ«®G¸sŒŽk\ ùŠç€ ›×uÂ.BHÍŽ+ä†hÙЪI„‘’çn›aê¸é)ö\û¤É�¹»EfÉå–ak½H†Øò_.…Ѿ3]C>s*–Ú;¡]²_™À_¤Ôm¹ý*_Û¿?vÇMÏaªÛó'ÊMKö¿†.=zÑ©†Ùà¾é¦ '"š}‹Z‚‘/çFØíK*&*ZJÕ¨UËØíqR`§8é�nUÖ„]±É# 7ƒB—?ÏÊÐUBTÁ|ʲð¯ó¹uá­Ö-å¶÷VÙžslÉ_ˆP®8i´®¹ã¨8–ɺr«Yu[¹í[ °ËMù>…Á²Õ3…Qd«åôæ�™Ïù¯Ú Œú;ÅêL…¢ 04rØ]ÓäPEIdÙ¦/yR$åæëŽ/O=eIc u<Í*OPÜP";´µ±ò  ØkGÍó¯õ{¤Rš©$iss¾<,òdYÉ‚4{öÀq6w³rK˜Æ;]%Ü߀F�_ 4šÑîܲ=2äÚÑBDµ/$@K«Xq›è÷,XÇR­—�@\‚nx©—`"²p&Ü‚÷Í•=ÅŠ4ïU»Öƒè�!ÿ5Q>mw;ä{‰¶óQQ³*ä¸Èß¿Man-éZ!%Z YÝ­>f_iŸzÄ.TâFàeçµ›‡ÖÚÍK2]FùxâЖÈÜ |ÛAYH!׎Óû8®œ7Y„€Y+Õ{Á¡ãåöÙp“áŸÑšÊä!ÿ­”0}"µ&Yµ‚i”ÃÒ k;Ïݘ”$Øþgz�æ`$` ôåòh`žÏðõN�KZk*Å®DäåNTö÷`·Ìòl ˜é’5Í­©fW¤ö rŒÉí "Ì›à4T8Ë?¼Öeê*Õ:-õ®¦3z8 ŠàÇ©œåÍȨÿ¯i™�û‡ÀhÊw4q™§Ó‚l&õ¿.±«¨$Ù".”yÙ}&˜!¡Ì�뢜H3ègÏé8ÓcÖòRî 뻚9EÂ*‡:#ËᧇÒjWîà¢F?Ö§Òñ!™6‰P~ d °à � }Ï>âøÚ›�ù Û5¬ñ”¥¼>P+OÍ‹9H6ô1Þ‘¼–8ÑÚ)¹ ÑåXk]5Îa«¶—ð|lG¿èýt5ÔÐ5Æ–_"/R©L8…=µ1™xŒ»°âî¥ÑPmL—ƒ?iWë&Sr3õmÁiøM«”ÙX°‹êfìc¹¢ü4a^ç*âT§¼ê!ÌÐÈÚ"üéî�ô6Ѐ¢ Z·êCÖƒ,}…$ã<©ºs2"y@ke¾3ÉŸ5uÆÉ²'œ !Â!Aõ‡æØ~$7«ßW(6†óæÖšÆ®ß«¯þE~gI’Ð܉ ²ÅôÖ9ŸiIì…S€+zóW­”c&Ü�:8‚0\Þ§04 ‰NÎÉÈÌã9šª„ô  äísü£LÀQzµTÿMŒ»G7%UåíQñئ¦EöHK©¡5IÕN>�Œ›K\“=ç*�Û½xIÍ#IOtHÓýÅùž°tìÒªÂ�y~3Êc‹Ë ò{ÊÆ êá·¿k(ÒS ôgîê[ô%@ù{à R`›NܨzŠ®¸Ï�žc¶ÿe_8Bë›ìe‘ƒO½å¸&5–� ´Ž¦/‡w�Ì(�˜’0âFapkÒl–¢¯ã.zñRî(8е¼ÄÎá‡ó?¡ZäpaÖY‚\J…\édžݺÁëÜŸ¡Îå6Ì È ;­»ãJg¦‡ë7”½iÔx»É•â×$`ƒ‘œ«‰;òEä[ _¼-«.Ü|gyÈ{ɖ↱j&d«Å¸Ïë‚W…•˜�ïÎ_çŽòÊÆs=‘’®§µRä‰qí˳dKŸ(J„,0l!(oHÖ¥Ô†tô0·3\ñÂÍz;ãÞ’{˜�{¯ä�Y½�©i%Ñ‹ÞÂè€Ë"CŽxý¥5½|*rFè@Í´Á9{eß— µ\xê×â0f¸Ò£%Crè::t´qü‡Ô›KLÎ@Ê·ˆH÷ß!›àéžìÚ#ô©#Æ*¹™óãÝ÷Õ>0tÎZGø~ž 9&Í;_+AÖªTÈp�˜ÞÿÎR@Ù¶z+ŠˆúÏ�î÷K–@uzð§·VïÊÿüð. ›œ'+™ÙÊÎX¦ ¸ñø{çI,Àü 3¶þý6BvCÄUñ£M+àטt\DGýK¢¢u¥‘%üǘ ^T¹ÐHy½æˆ�Ô"¡ 3K‘£ËMéüÈ žùÞÌ ZyÍ÷º½xe³¥J|àÄ ¢ÒnyI;É¥×Û¦4;=íñA{¾lq<;�ô.�¼(J7%v‘c˱ó¸NÃXLÅÞütTåºTÏE4Æÿüýxv¿ ¶F@ç”g&Í*IlÀ©�(r‰Ÿ~}’­IÎØnž�2º|�U¬7–íJb-zµYG–ÄdØŒ›ßb! °²öü',aižý„r%ù´Þk"°Â$N*Z8VTc[ù|L©ðPëß×)iñƒ>±Äæ3K,·|#u (Èh8…3} ­êzNºx~ LðÈ™Öð÷r§[¿Ï±Ñ§nøk fsÿZ· }ªÙ¤‹êM—Z@ȸ§N¼¶(—ÕÝ#3}ÅêÇ8§èÓ @Ïê›”BëµM¦D§æÝ’ÓÜg+’óK£€]IzCuÌ|î�~ü·Áõmw©¨äº¸*-³„I2šÃ Éȉ·�,¨-kL£sÕü… 7Ö   Mô�¥nê)°‰³Ê‹V•I„ÑŒšõ6gO¾K�Ào±á¯@ ¤*õfpŒmâÙd®õ{� Ž -Cƒ/”&K||ããÙèºE#'ÅeJp-OÙ� æOÀ•�ø§¦üóÎ$WÕÌR³Ã‚PÞ�+B Ë]lGX¨«Ç©­0c’ªÈˆ­ê“^ú |‹«x¸‡Sü7*äŠ|çú¤$ÖŽåºçÒ6›#Ndê“£º‹abLJpŽuZG[k…±%DäÑ“Äj-0’ÅPšg!¯dòu{ôÃ79ò©EʭņtòÂF=¥é]µí¹ª­¾mV¡ðú%5‚Ã)¦šóÝÛp1¸¾œ}°ÉÝumÕ5‡sq¾¼¸(P¹¥-œô-#lýc‡=ãñZr ƒcÄ"[âXÜYRñ[CIä;ën°òŽçîŽ'E1ÿIrjþ¢:3z�¶a>\_> ’î¯ãDÃeê�/Õx? š­T}ÐôLº½.«gØ!j(�÷ª‡Q•4f`ÕKmß ²ƒÓ%1ïwÔpÄ«e�-G"Ðâ�1;¼É@Y¦yCž"h^öæDø?Ϻæ³êH‡<P÷ N»zݦà�ß"' ÿ_‰ð›-Z}W‘uV?ÂQSܼ’ Ð Õ¾ÀÊ ~LÇAæs‡¹8$NXH̳`ûU›½áŸÊï› 'õó†õ r>صºÐ““¬oÍàMd‹è¦ØpL/>ä5_‘© 8·±èóáþw aò±ßw‚ÇíˆjÙ<¶ìøî\ù@Õÿ¹ØM¸· ªÿ�¿J{ üõA¿Å›qÛ{-‹êK\šò]ò¤V?Ø,z¤YŒô;Tí¨˜�˜«²ñ^ÔxnM(¥™ö,koê–õ�© %hò¯Ç¢Ûì‘ùš—Q‡P)iêX ººç UµÂ�Ïw)ÿˆ×ÚèØÍf!½ÿKc¤ôv¦aeãþåÔr»]ÜŒP, ®�±îˆ×™ûø­å=ÀþBšÅù£ù3OjJNPìªü¾+yˆcÔ�#\¶N­  \Ï*LQ!5÷åO)•'ˆ}$èDãÁ«… 0ÛA†™t%m4:]%¨eç§þ�zó¹k†xÔ‚<—"’J»ÁäîÍKÒQ͇o& �9ƒ™MPœvrz«=_Ñ|b�T¬þ«}|Y0Z vƒ-BM£Ñ|†•…�<Ë­¨á0ð3K¤W]¶ÑaéhÒÎ}Óèá—»k\[»Æ!tA Sgµš�M–°ÞE뼚P�cˆ' �ï!ÄÜsx¾¦°œ?UŸÉqvûõɕܔªªN|'\)™¼è`ŽALT4Ì6Œ@Åš t{ú˜´€ÔJ‘ñ8¨¤ü§Ò”m.®ãsøF™ŸÞP)œCÃù|Ö²5 t-ÙMn$¹yQ:GGNA_:9rKÿŽÞðAÊ!Û°�ëm¼c×êBßHÅ0õ/ Ø+€ž®Sëò³¤‚! 1 ÜÝt˜å�7�Q)˜eÆÓä�„7†œ*pU’´¨§=BF*fg ¹€´§Y+6ª¶GQ=›[×IB<{NƒK«RɶŸrt ç´�cÙ)ÏŠ/HîHãƒ8Þ¿#ÝâuŸ%¤¤þ3š6 Š ’hÀøÐö¨(ÝŠÆêZ£¬×t¤¬ÈèÀ&*wî\ÔRJwÈÑÒ�ÁTQëZ6ÒF:¬7’ÿ)zAT˜pmA’Åsûyi†Üâ@–JÐ×BÈøê•ñ®†ÛyXKÉÖYëñNœG¥µg»ðÌÊB}"w;xÔ¾@q”FÅõAP�j[óó�ÍO!3”?FO©( rT÷YÁ’[õÞ~»Eþ?§é.l�ÓœúÓ í£ˆÜJÁ„a¯ƒ´ ¥7”ˆ•d1Gts"x�<)Ù¥E»„6�~‰Å‰a{-}½®²tP5>¿£ç< vý ‹+”‘qJO�AbI.Ël®‰Ê×¾ç¶.o\:QÆ-ùf0ËúEt¤åÝ9J3¼xߎž)ç-öc¶.¬�X#Å&L%�å¿ÎFƒº“ÁX¬?D„¯²—Õ¦qÆ"W/òƸ- ú¬<D |µ&èÇ:÷‡dbÁåé"›Ÿ¹¹9¯ÐHÂÀ–¥R`©¢„Ûúemå‚£¹-½ü÷�»9&Ã鉿^ÖJP†Ïï"îçÉ:ïØûîÈzˆeΈæô@Yß•ÛYBéËk0àù#bêSÊ?+`‹nDžjqš³'ŠË¤oŸyÔé'-…^6pÁúÕ¾¬Ð• WJEýº[³öf§A:“…"¦û`Ø ÓÏ¡[¢‹ðÁÏbæìï |Â.ö?w¸Ñ7±ð>KJ§‰µSnÒN² ˆu\ÄýÖ:ÛÑXE]�ÕH¨gź‹|ù z—ß/&Øq^lhÚii²ÿ÷ÎKG4m¶ÖUHº®UÙHð q£ɄЀŠð‚zD6æ‰×,„:3ã:a.̈®Ó“Œ"4[¢h Ž=+;´øcëã?nþþ¢× z¡—°Ï½¼ž¾<*ÂDl°pQ]7caÒ‰oÕb°ÚàÈ«1PÞô³�KƃyËîöÍÃÝ<¸fzg¸úv—K,ü8!~âRGõàž½/Û1tEô´1M`ø½«£ô¶O ‡áhà†ôÂ"ÑŽ›uþB¼0ðãz‡UäZ';äæ<ˆ¨1^|/‚?'̤A£5†¤XÌzTýÚ\·$ŠD·É©×ÌÄ�sþÃP]?ÃÿÄž‰¤êo¥e”y* N²¿ jð¥Sò–§Õš|ö,’b=4šq½b1÷X Òþ ¢ÝA+mÿpšüSƒ¸„·Ç ¦ßÎ̺t¦³B0 “ªáÀÒÛ¾Lëvg�¤vèý<‚  ò5ïX6܆n{3{ð J‘¨¹ÛŒmÈgƒXµOR�¦Wû£®ñ‰ Œ¾ ÎÛo‹ŒöG”óÕ‹ W¹/`Ç‚�›ï.ÁèWvq"4 ý€ëmtÞ-HzìÃKÔe)8ou$åùl¶Nöš6Cb¿ºÔ�fè‡Ѫ²`mZ3×IÇ8YùWS$ KÁ–=…6ÛåC„Á¸fCô·>¯ŠªÆ5€/�ÿ‹ß¨=·|þ9à�&ú©ãK0�4|oï<j1‡­2æul±['7\�§÷�ED›¥Ä"»�Jô{2èó®éÒ¨–±höš÷M •N|'0Š›¸¡²ÕŒ±ò€ûSXód’Ë·@%¥_`Šç!Œc¢D-Žà|íU6*¡¨Ì¯Á9�–‹¶„ܶŸ{t%â-è€iq;îO­¨*Õ¯tÂZä ‘ôœ—Ð?¦ïHxƒä g !¨›ôÚIæÓALˆÑ�¯r $v9Þ{ûå(è±<€´q£Ãrçþ¼«–“~£³k£Ïnlwd±Û ¦Êåy¬;ÁH§fw¡ÝþB=>žyòs: xJ'ÒhO„GŒkÜn;„P¯ãµ™ñ;g ÷ˆø°“f•0©›4F}<ùÄÝ+ÖL-©âƒ GÏ[ó"­ oC¶GïßNñªSQæV�+Úÿ4,‹â1=�û)=yLšƒ:LõÈØ€‹º{ÿ‡+«1�¥ØB/߈Cή>Þ¾ löOé<”k`�ø9·„ˆµ°¼Õa2…m‚;П«‡1CA4ËéSgO̘ô~ýw`©Ûo'Íc¥­Bö¬tÇüOÇ+ñg5à¶�‘Ž¡^NsØŒ N¶ðyi‹ª}Yʰ¢9ÑúÆ�JÿÈV1'1D1ƒçV)hL¹gc:M]&Üu�Úíq¯¥6��Œ`™(í<Uâ䘢Œ{sÂW?œx£‚ØFs�#²}¼ á†?›WÎ>}­Ò!ÓC ¿,«Ê”Á‰tQçX7¨._¯|d+x•õë•b\œhß—`嚟"Í�¹C0´�¿ºJwµ«ct£²xV±¼Ý¿ôVŠã½ûDÛXŽŽ‚[1„÷ùYø8o­6úÊŽC37H°_k âã¾ø§ò§Iüø4)‚¢5¯?:øÇ ìš$y¹­¨ç¡/¥EiîÝ¢D+¸{I\*ïw²å¥`ëÐD· @rÝ Î³z Ü” Ä/—Sáìº=?F¤Ë1÷‘‰'@U‡T:&#¹“LYùëîwh7Œ8 ­rÓÚ¢XÎaÍŽ=M@jŸÎÔ¾õäsoF‚d/Å€nŽ—KXì¨?°jMy±ªp…A}ÜVãŸó¡§ÿ¶ÒĂ딑�:%Q$ÈOvï¼ætkþym%³íNfË¡b q“•”›–o|±i)éTˆ¥;~4w`E7t¢£,Žc“= !­êׇ¹ä8bÒ­Ö¸$l37‘=E²ã˜ k\”åÏ\xSîœln j7ÚŠvöÊ›þ¦ÖNÙ¹fâù/�ãËàÓùþJ:üEv¡Èe�u¼^¾2kø5”¯è+:„®_²S #õ)¶ü‹6fßPK¡ÓYgr”*“¥ OE¾v >ïz3À›xž ‹{A89ÝÕÚ™ªíÈLŸ|ädÞNïøà2ÊÕ•ÙR3�!«x«˜32² ü™ˆV²È2w®ŠÜ¾�nûzIéÂ&|4’{"9ø¾sš@”Ü|·{ðåmóµt®wÜ Ìß×ï`›½MyûÅŠåÏLW{Èr6)ó.AÔ—¬ªjÙ‚Ý©W-ØÑÙêx°Æ 1ÞÌMd‘ªÌw¶ýcªä޶Ñ…ûm`�DyðšÚgdµßé±F<6]¿g¼~\÷•Û¡ä<ŒÀyVÔdzœÌ��ÓÁ…ŸSÓU<¬Uô•×p�zÍ©ËÓg}a€Õeg#¸Pn„6å»vyI;ÆL. ™Ô�i²‡ëc«,>Öx´º¨­úN¦³•gÄÅ]سdÝ„�¯˜¾øz4Ñÿßc"¬Që|ºJøc¶¹’z8³Ü;6�ؘË>vd¦•ö‡ž1Æ|Êù£Kréß Mëå/0 SdUR¹9ƒ¿#‘U9 U}_–Æ °ÃÙHÊâ{Š�æ”McJø*:¿ê3M·á ¦8Ö¸6ÄÐ¥ê Óúeÿ¼sóܲcúžã!PþB~ó<ÅÖìzCe)‰Bq»;ZòOí»/ªülqCæmÎÒ7�§ª|/>~œÿ0‚~B NØ.ÝCÍ·–¾Û!¡|î£îá~Re�£;ˆÁ.ÿ¾ÎÆÍ™穆˜ÄšPC·õ²ÏÍÑdé^]U꯭¿¯_ÁÏNÎJ��7uý]Ÿ;À†S)ƒál"oεÞ;=-0Ìþ€Xè”sz—ªzv8ã¡«† a¤!ôÒ^nCs iÉŇNiÔÃÖ”é'¤ >#f¿doÕš»ålä¥A”â+.º{ڠ؈dª¬¨û“‘¬ßÃmîœÖµ£Åõ�NQãyǤVŸº„„×fdFÔ!Öɺ# *ËÎvªPeazoZ�Ò›m�Š~…ô´ÜÈ¥¶ÏÝÂÍicÙh¼¶¸øŠ8�)…ŒGPðÙ ®Î‰ƒ8*ón‚ºË³¾:r¡–Q£Ôœ½w´ ‰í¶l»æ ޵2jfŒ ‹Ï¸ŽgQ»1‹{S2ܱӨK)½óÛ2E'ð¶#�SJøûºdÅë9 §º 0ìóžÉ_ÑS�¥Z[¤u7–—7å«UésøŒpFuU÷ö‡Î‡e™)6_Œ02– œ.d¾VV,Ý.zg‰q‰ËgI˜ú:.MÌ?fø_ÕĹؿš$üÀ ÷o¬%@9gøv‘øÊx`ú¹:¤? 0ÔýæÂDbÜIŸwŠôµÈpJÆE>ϰü;ˆ_R@Bîî­#P‚hãRßChwÛÐRþÌ<éjâ%ç'ÊX„€¬žf�|‚ŽŒ/´®žì‡† èV$;.Xöxý\G\"4×' N|~(.íW|øN"z$�«P†š¢ªPºŽM£!¤Ýë9ò·9tqãAŠK†^Þ¦dB1"IÌo9qo<°ïW—¯³ßuÓÌ…õ—œz\Ê7.A³1É Oè#™­Z9'ut˜ßöÔ†ET^eE`F¦ël¤ÿ†GÓ½Kk\ÀQLG\²€ ºíz »p8¿Ÿå/å?σ—,x_z¬3ßÄIŒ�.ý¶À6¾2zx›äÝ…o¹³§Ñ3àR¡/9¶ü`Û‡¿ò¿Ó›´>÷kz&H‘_0k´Çau¼�Û)ÇMcIÙÔ\\l™»š;ÌTS^{þ˜ÚF¶¯‘˜ê«=†®¹)¶� 8çØ0ùõ êÀ·ƒþ#©ÛªX†ùs"•/ëJ0[ާsÇ]úN"#Ùd�á½Ó÷й |ÇËKõ¼ùHW#ótŽ¡ñz%æÅ2ïº0gf·ŠÔí6‹KHµªA}F²±³vF”×O:hñ";üî=LºÃ¹kÚ»½%®°ÕVºøz¡ÍráPåу?>"÷Ú­.c̤0Á¸êlâ¦÷jo(|“=Îxàøî»nþº÷Œf­Ô•ñ"WÅ|¾Q¿¤c~á²a.­èTI%¦)lmÔ‚9(=«RljQ·Šß ¨tÏYÄ5µ{({ÐqSæn»È*Ž®xqQã~WßYò4¢Zü9‚Ì“Q8—Ñ%‹PPF´äÖ<4ñ¡í±ÝÂÅ ÂM³>v€rì”Ð0Ž>Žl¾«³„¶ÑOs¼¿É½ê÷V°…̶x‹»D» =¡³ƒ(ÈpQŸŸ¸!¤‹Òw$ŽÓ@²¶[%\Þˆwv¶ô*<• Ž»ôGI òûb»oI÷ñž Ê×F—¢°]�cä°ÜC?Qéª5oË€ØJjÊÌäÌߪ‚ì鎠qížÛšî=O êW«Œ•L�ô]狌|l{$,®íªµó'¨^ØhÃ{d~¾0Í'÷Iê7ˆ¡4½ñÑ9à~ôQWMñŠOwÜMé%rxd�ã6HÄÖ´Va²ÂeÇþÆfàž‹„-~¥C°}·ÊŠSµóåâ,å.—j•h ÌÙúÓÞznÏ:”ÊÄmv³ÖVœ¦1â8ÆŽóøø ¸¿TgM\´,@ke<¾}WÊf¾þ,…ß9¾<¨¨$§³a»W„N°~Ê *‰¿dx;B·¡‘ÖXñ*ô4n¥ÌÞxXì�l›/“+±ÆU¾]o§ZDM‚]ñ»ž ‰ õÆ~׺ñLÞt»6ŒÙ84¾H†¡´¦!ì©ìÞƒo9“3¢kßq#0Ï®›‹­Ã ñû}ž %]Õ‡¾¸ò‰Ì Ý�§oÁ»«¿¥ãæ=ió_¹Ÿ’ïÇI¸b63ÆÅ1œ k&Mó%ùZ�1•� t>‰Ô¡Ït0µ¹Û¿Vqä¢E…e:ú•\<”ª2áÛõ¯þˆÙm,È/ò©ú†�©³ÇY.! 1çgï%õJrµ�ù¥X?ÐÇŠ¨ØÔÚÁÔŒËÜÑk�»žôLª®ñ�¬é–¾ÝÞ0ÆuîTÜÄ…Ã7 †éga¿¨T¦œ¢�Œ ¯K!ü>¸T ­Dk0þý2IÖé~ú<°1žRn“„`=�këH{×ý!{šÌCF¾¹Gõd<«Sžž˜‰p‰¤\¾_ˆ¾†çЛvËu7¥xiák�Þ^WC• m�F–Ø& Zí>zܺÍ8ò€W:6…g•m3 rWf'Êø]�0FíoŸJ*Øvž›m×yÌ€ðÎý…Ÿ˜Z›3’WY®kÇ� 6¶7šÑîä¾lS:£9ÚÐŽóŒãÓæhVò×T–Uå$ÞV·.N^d÷\É \£ºÜûe"»¡¾÷Æ-û:Áj&FùOP<’7éŠ;0ÒŸ©W‰îp‹U�ò›®x§k4#e«?õ»GG#£¡E2s  !ü…ì» ±/S\_A°ÌEøR'Îr0úi`ÚiÌn¯×36w¾û¡ÕF›>1ŒZ»ûn7ÎôhÚ.êX(òÁ9ÞMó ³­|ßHU踽�&i¾åìKiLî€{Ë9 èuIBþiÆG¥,È}•×åî^ãwA„ãžÚ&|J³ë~7qR$?ç¶ô±" Í>oÄÒ/©ý‘H®åAtªùþI¯G Ü- U-Ì[ƒIžÆ)`™ÄXLçY)Fè㺽ero,O€ë*OZ­Ê‘Èkfã=`ËÀ¾x°±Ew˜È$-æ!†WÔÅgqúíMkæÞí !5ç¶HÛsu*ÕYs8yLÑn4/þ‡i¬S©ñÄŒè+ðk(d‰ (…TôAâ×ÛµšâÃH÷ñè†ò~5ÓýTvÕ(ÞÕ"åx<*à£â0¡û]*õqĵzeûмv¹v[’™hˆäs© @·êi¥\2W¶[UFÊù݇¬Û4°þ$«ýŒ�¬]·¿ñ(#ýAÌE _ìuÂ|`A uv5‰mN(ä§Lej}×ׂˆ"¹#·)DÊæÍ=äëQ Ý�tЖ:<¾,¨è„Zý¬“fŸóÖóàÊ*ÐcƒÙAÉ*� ‰½€^yžõYèòX øÃ�N›¬¥Çv×Pª^Ðß—uÝU°ÎÅ™ëLž7,¿“åcÄúTyK?àáô££hš|¦ò…I¹ ¦…ót‡©‚ت>¨ ´ù-ÛÀjÜ=ÛY»kœp8u<ãV>ÛaîGîó§ÑLP^?Ü|Ìó°k£³ϰ¿_õ°Óç̾D¶(ßʤ[Ù»¯ÿBu{,ÿÆENÆ_¾ ýé�,ÔƒT}ƒÛ@h.„;À¹Nôqh2ØMÇß�¡Â$šÝÝ-¿à’x¨mĈ²xeiNC5ÞζٳZWIÙC Ëé¸#¬ü޹l«¨ëŸŠ�-åü|ˆÝ_9«39ŸçhWµuaÂ*òmEÕù�CLb@)¯-F«ÃþÇnlqM^y•ƒßP¯ ÕBƒ—Y—Í4i¦0-ºr†2wÂ| ¤JÆÆ]ÜéÏûxã{9¢_ L Å…t%Ä�Ž„Ià˜‘G±Ïi�8ABQœKПò»?À÷zC«A0FBËÅl&k[’ážwË}›«„'B™è”b¿÷g 3 ÊzuÎ}!­ºO:²�¡+´n endstream endobj 22 0 obj 113085 endobj 23 0 obj <> endobj 24 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡G�Ît‘øˆ’®>R4éuw¿¿Ï·õ?Óåø�oÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:�ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·Êãé�sM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§m�ܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ�~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒßè·RŸ~ƒßè7ø�~ƒßè7ø�~ƒßè7ø�~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßá�tF8#�ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;Ñ�ÈDt8. Pi�|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-�AÍÄ�NèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8�eÁM‹³<—“#artË„F{Ç�N‡® tÛáÞ®Lˆv�qè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»�õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G�¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿ�dØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 25 0 obj <> endobj 26 0 obj << /F1 20 0 R /F2 25 0 R /F3 15 0 R >> endobj 27 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 28 0 obj <> endobj 29 0 obj < /Dest[1 0 R/XYZ 56.7 773.3 0]/Parent 28 0 R>> endobj 30 0 obj < /Dest[1 0 R/XYZ 56.7 699.7 0]/Parent 29 0 R/Next 31 0 R>> endobj 31 0 obj < /Dest[1 0 R/XYZ 56.7 217.3 0]/Parent 29 0 R/Prev 30 0 R/Next 32 0 R>> endobj 32 0 obj < /Dest[4 0 R/XYZ 56.7 460.3 0]/Parent 29 0 R/Prev 31 0 R/Next 33 0 R>> endobj 33 0 obj < /Dest[7 0 R/XYZ 56.7 738.4 0]/Parent 29 0 R/Prev 32 0 R/Next 34 0 R>> endobj 34 0 obj < /Dest[7 0 R/XYZ 56.7 612.4 0]/Parent 29 0 R/Prev 33 0 R/Next 35 0 R>> endobj 35 0 obj < /Dest[7 0 R/XYZ 56.7 451.4 0]/Parent 29 0 R/Prev 34 0 R/Next 36 0 R>> endobj 36 0 obj < /Dest[7 0 R/XYZ 56.7 339.8 0]/Parent 29 0 R/Prev 35 0 R/Next 37 0 R>> endobj 37 0 obj < /Dest[7 0 R/XYZ 56.7 178.9 0]/Parent 29 0 R/Prev 36 0 R>> endobj 10 0 obj <> endobj 38 0 obj <> endobj 39 0 obj < /Producer /CreationDate(D:20070808215617+02'00')>> endobj xref 0 40 0000000000 65535 f 0000213832 00000 n 0000000019 00000 n 0000005596 00000 n 0000213976 00000 n 0000005617 00000 n 0000011445 00000 n 0000214120 00000 n 0000011466 00000 n 0000016089 00000 n 0000215760 00000 n 0000016110 00000 n 0000022539 00000 n 0000022561 00000 n 0000022755 00000 n 0000023048 00000 n 0000023209 00000 n 0000096279 00000 n 0000096302 00000 n 0000096490 00000 n 0000097435 00000 n 0000098399 00000 n 0000211597 00000 n 0000211621 00000 n 0000211812 00000 n 0000212757 00000 n 0000213722 00000 n 0000213778 00000 n 0000214264 00000 n 0000214320 00000 n 0000214584 00000 n 0000214706 00000 n 0000214856 00000 n 0000215070 00000 n 0000215188 00000 n 0000215326 00000 n 0000215480 00000 n 0000215630 00000 n 0000215872 00000 n 0000215938 00000 n trailer < ] >> startxref 216125 %%EOF heldercorreia-speedcrunch-e7ca37f/doc/legacy/speedcrunch-manual.odt000066400000000000000000001516611526573132500256460ustar00rootroot00000000000000PKV=^Æ2 ''mimetypeapplication/vnd.oasis.opendocument.textPKV=Configurations2/statusbar/PKV='Configurations2/accelerator/current.xmlPKPKV=Configurations2/floater/PKV=Configurations2/popupmenu/PKV=Configurations2/progressbar/PKV=Configurations2/menubar/PKV=Configurations2/toolbar/PKV=Configurations2/images/Bitmaps/PKV= layout-cachecd`d(`ad`àd``c€2ô@ ^ W #Ɖ2&ÂÔÀÔ¶ÀÓaŒÍ0Æ9ã ŒñÆà€™£c¸À±0F9Œ1 ÆXcƒ1à LPWÊÑ0k,˜ ŒP#Æè‚1–PKM´A¡lPKV= content.xmlí}Ë’W–ØÞ_‘bÇt Š Ô“ÕäÕ’¦£¦5=ãE;À�ÃD&”™¨:z1{/¼˜{cGxë�#üóö?Ì—ø¼î#ñ¨ÂM ŠT7Ý"dÞǹçž÷ã7»˜&Á�Ê‹8K_¿Û��JÙ0Nǯ_üôá›Öõ‹¿}ó~“�Fñ@½fƒùT¥ek�¥%üÀÛiñŠ}ýbž§¯²¨ˆ‹Wi4UÅ«rð*›©T¿õÊ}úÍÅßå2ÙùuzØ}»T‹r×—ñÙÊ»Q÷™éa÷íaÝïú2> @u_e»¾¼(’Ö(¨OgQ¯¬b‘ÄéÇ×/&e9{uvv߾ﵳ||ÞÜܜѯfÁóÜlž'ôÔpp¦…“ga;<ÓÏNUíº>|Ö]R:ŸöU¾3h¢2Z;Õân¼3FÜ�·€f0‰ò�qƒ®oo¸ûñö†î»Ó¨œl9“ë³ßÃ�ôŸßgq!Ÿî:>[Õ �g;o“ŸvßϲÌ,_à JËív:çgüÙyúþÁÇïó¸T¹óøàÁÇQ20Ϧ›€Ï…gðDKÝ!šÄG@[^èžñÏæáb¸uèüýw?&jÙ‡ãÇnÅiQF©…Lއ°u§g¹šeyi3Ú�`ÂiuÍ,ÃQd¦�'‹6�ÐÂi.w„3¼™gøÊ¯ ¦Å*Ñhm)ó«ÅLå1¾%xr­i»„ÓÌf¯œ·«D,Ÿ.vO0ŽVG4Ø,ï:ܨûâ�f=Œ¶Å™ùb,¨5Šª5Tƒ¤xó&!æë€?ãJ^¿ø±Œò—Ó~–¼€\触q²¬üxöð0ïâi^?dÓ( Þe7Áw†ûu4ËŠÛõGùûAe|¥5V)À ®IŽOWž˜ÅåÉ]”ÇÈ}[àW꟣˜?Fin]šóÐk*îã¢ØgM œîqxñSϱ, ‡‚Ô²(Õô±5�mÃ_ù>š—€eñæi•[9Úîë¼zrú3�òqœ¶5‚³è´ÏoºqúÂù%çcêÈ·´ß8¤ò%��DµUùÑЪ­·4‰Òñ<Ã’‡Šdó´Ìa›_}½Qàû~4ø8Îáá!à@’�TæÀAÏŒJ×Ï|DžŽ|[f³µïúYY¢ðÿ¹'¸©Áo`–yé'’¸¨þþ]×®xcïì}l[g?oÎî/ÔÔúþâÈÖ™{ϼ¿´±uæó‡gÞ_Ø:óÅÃ3ïÏá·Î|ùLü/ÜŸQoÝÃÕÃЫÅz§"4ìâäá§ý?¬Ýrœngʪúðº´ígC•è�Ý»F¼ëK?¬Qƒ:Ó=+Õþ°FF\²û­Á‹9ü\\{h Öhˆÿ´ÞªÉ‡µK_ÒÏãðÖhÉrHhÅæ´û¬k’©ß¬»nòöXÒZ™Ÿä û@¢îT"IJ?OUü#~ÿú�+úèRÓ/é1$¦l<4Ö¨t>móÑ(†ÃhË‹è&$û�ÿÜ{�¯¸š=º�P›¬ã,Õ>¦oWÆ_¼ùq¦Ôð·ù<LtS» Ó;¶ã’y&2ôlÓÐ/ÞüÛÿ ~›Í–T¹>øC–Œ‚ï¢éT¥A·Ó¹–!fñƒJTT¨a0O‡*þîÝOÁ7¹RÁWÒ”)ø0 v€P³Ûˆÿqð#Q@-Ý^•ËüZÄXõõ…|7ÉÕ¨Ò¸jœÎ©'T‚3ª8 “ö¤œ&/Þìò”¬.zÀ†ªŒâ¤h¯¬yÃ9…¦»›«ûâÍûIœdE6›,ƒl|›ÎæåãG„¸g[üa³ÌæÁ(΋2H":y ðÇ)�e_ÁhÓY çRfÜâ@šÄU¥A–Ãz£|̲ÁG œØ”lžDe–7ƒr•A\3ð>.iÔ<˜f8`X9QÁGµœE42�¬á7WÅ<)× õèž¾œ—•L¢Öû"ä€y £v Óö³(T+€q ›M‡íàûQ0€5ªÀâi¹Ù IH“!-�žÆƒ�¸`ÞG”*ÃÞÝ�Î=Æ£i}Xn5Wƒ oÄWhá¸qzšJ-f°{¼}þÛÿ1k|ù¢Q ·—Ëç Ó9piâ±ýF3™tðpohåõ,ÓTž}ƒKÎE“eÝGq‰‹§•<�ØfUÑ>L�JKPس ·Ÿ+|;J`ç.!Êá0¦ €‰°Â¦pPج¬o…Ïq«×HEǧÊwþõ8Œt?‰7@2zçÁË Û¾¹¾ò…-œ%L+…¢ýæ-~ÎËF÷tŸœÂé6’4X§ðÿÿ— {qâ}Î_[á[°4L²ì#’îe0�òë_4l Bq æŠX6K}x§h—“˜pvŠ$…O¾ø˜f÷)ný1|‰’±êçQˆúÙß¹FMÄâVö(Íô8–8=¡ø^ùàn—Ö>Ì@b„sò w¼˜ÀW´Õ‰&Š”,`Ànr˜äžxÑý$rn=l–X$ €Mã_ÀŸ‘q®ÞÅêžþ�Mxçª fj² ÔŸŠRšÉÀ_ ™ úËfp¯’ ìø#a1ƒ,‡MβYk ‹ÉëC«ì¿ ãB¡àïþؾƒÏýô¾Eëùêû?¼k½ýá‡ïÿ@Do‡û‹�þr P½gd¨Î@ÑIéq ¥KÍ\]¦F#5(lp°Ü]Îcü9H;ø}´ì+õ> Æ`‚[dSå²3¼Ð´Ü ˆ[yà!»³Â²ÀÁ2aJÞCÉ.o5¡0—ß_tƒÀé'IvX‚l�š—’"è€ÑÚt‚‹1c9\Udΰá‰p"’A4Žâñ)À¦¶zxÅð@O™ÓÆÐAˆ¬zÄÐE|ߌî–6Ë´ŒÞLà­æ�öˆ‰äû0Dd†¾ó¢LUNP&ׂΫàÃ}ö(Q#Ê‘ —D5ü0;$huhÑ£cõYàdb°÷¡‘/ÛÁ—ô:\n 'xßð,ÌXeô5pØ‘^1wìÚ�#Øy:Xê¼²ÒÂg¥">ã‚à&*½¢Ë ¦Â7òy³ò˜ÙH±s�Æ)’² UcÂúW~¼Á I+˜ÅÞÈ)[«ªúgo¾€ëœÅ^»p ‘ÎðΈ§À.„M>Ž0È(^x Zíà§êÉ1ZçÜQŽü#e»dÕ\Ü €ã”uW øgD9µ$єΨTþ0³æ±^á{¦¤0)~ Lñ3µ¨‰8ˆ¤ÕtdUV8ð�€#­‹K–µ þ  ~d¼˜[7J@2uÏwG}¨ÌA¯ýÛàípÈBéÃtu`ø2žÁÂiÉøŽO¬™È”Ûº£<›Å`’e‰¾ÞQP,H’ÚãjHлU^QÍH,5hƒl.BƵl²”3O –#Ͱ*�GKæið+úØ ’ƒ¢i ÞøÆ°ìÀY �E">�1‚ÈO‘¸Éb÷"Bîå¯ã:R ê&ë-«paF2ƒ•($1¸G’ ~Ì\Á�7,B»FBôªI iœ÷$±õC4]ÄgìÜØ*3nÖè¨þÜ&Bˆ¢Q%¸¢�0.&(8ØaeoBèÉ„2ze¨™hìÅ}ÚÁ·Àõ"žc˜ÍûFT‚©WÁÝtäLÈÖc󨡟ÈIéS1w�‚>!Hu@މ PœEË„—]ÆlРþª8EËC�W ãÉ€@C0ñí´�Ø¡À�çÌäÇÒ>NÄ œFq‚ÏÀ³äι�‚�*�ù>Ûé‘ XhêÏ�¨˜]á±á;�¦{AfаG]]Õ°I¡d(÷±Pt×FÆ?j[(Šlø‹Ë¥‘è-j¢$vPH ÖTñ øz)1„ÂzR6`mºwQ2V®mXDÍ}ä€ ½ð»�r˜H õÄ�X!žÔ”öˆOêžñ[^HQBq �QTQb6%Š‘Ý«ÜÊ  ðßÓÓ“WkíÂk=øÿ¹ï§*‰_oÐû'@ÜàUÐ aù¨a†ºÅÁùá9>¡af;Ë#•�ÍË‘¾OÄw+‘Îf®�c¯•ÖR˜dã&Ha)ñÇtÀõoÌ#¤jìÀOàßp�<•”-ÊÅ“(à&˜ˆ0D§æ3R×ó~ ŠVŽöåi”‚¢óOh/Á&šH%e©D¬; Jc%šÿ*ÚÅ>ë“AámÐ…UÞç·ÁÅmpyâmì�àÚ[4A“å6 $ÞÜ+±ßçq)F“‘(ÎÄ0 áŸ^òa’ëÀ{„�Z.ÉxT5ÏŠÀá·„®¡wÒô]Μ*´@í Î’|BP^ ÉidíêÚÂFÊˆí¥ IšM`ì ã›L3ÀÎ ¢Ëµ§)YÿÑ5‰b+*¼ˆ¦#Î�Oî}TÐz (�B½×9¡g�(XÏH®%0�“¦Þeq� ô¨Ã€îû'Z`0œ`ìì¶¼ek±œ4ªpQYk�®š×Í G+m’þäb·ï.~§=¬©QþÕH\—.)¹Å‚¼$V�±Àˆ >ô`ßÂ+Âÿó?�ûIŒ€!y6ð*¾+ÀŒZðú`ÿ‰?µwáž¡f¦•g$ùž; õè|)XÒØA‰Ç££ÃœL ‘®ê9úu4ËŠÛ×üW€a`ÑŽÀÀ‹àu€T9èÖaÍ À0Œ?®IvWñžñòÉÂÞ $Ÿ%(¶"â båYFØÜéy$v«ûßbC´Þº1ãÂÝ¡KŒ¦›P!ôФ<«÷^ª¾Þ¡Å)™ŠíäÚ[(†f’u— ø„ÝÓÂ#}ÏÑ´[FLzèZ[båP(šˆíƒ�ÅèíÜi°ðݦ8—è7vMU5¿dBÆB«x�•À «8JQ±¡c‹Ö„Ô„xH7¥‚ľ¨Û­$ È´Ù… Dõ„¿(èÖó%6F^µðüê¥CÒ"Œw¨m¼ö‚ff¾t¼rKu‰;±¼2K€�ô]‘%Úå+ýÆÎA‹[ÁUÍwö˜~Ð*b?*âHVyi£<ˆnÙ¨-6/F%ódÍló•5ðµ­°3qà ]EsÌ6/ôÈK ÙKØÐ9˳10¢õBÍɯ ‡©ã.ªÆ:[žh'J¼ötõGêCRiT°,–K3ãiÃJSð­vð%*¨! �ñ‰¡ÄS€Ä0óÔê"Ëlü R£xÁºžzº²­A6OK´ Êk™F6�ˆDdÀ7>RX’†:ÊÈß ]ÿ©x -æ /”1¢FNBžwùè¸?ªQÈË\€'€1;Ù”¸†q”dã¹2QLÆq¨ Í0 �%×èþBñßÀ—œgóñ„Í×轊R@SRÙàŽÏ§2Ú$#À”j˜«ßй¯ ;bIlF�?’@nR—ûVØe©Ù% pU¿±¸2†šÎmÑÞ¬Ô>O…ßÊ$†tØà«^ÝÅEL¬ÓqÌ ¢µ:í‹/ÒZ4g.±ÕÀе/}ÑÎv¾>6^±žÑf±(bËt“ï%ƒ¬æ#q„Ýž·‰tŸ6žÓZYÝD’”4ÍÒÖŸTžùû:�no/iŸ" f,Ý – YŸeð‹½ñêZØè§‹E!´#y×*jVl \09FGñÅH=Z©¯YœHØ@–¾—DÑå¦x©óll¢Ô²ƒ°:`Xš)€5+Ö§‰ûD@)`D+Þ[ê†ilEÕ”‘=ü¨7ñ#M~Im&KŸF"R1ax$‹ž„ÖAôvïüÂw×k2i/š,³ˆ|ŽG‘êÂvÀ2�â1wP°Ôô¨�YöY½ë‰$�tst$a²c“Ó3™W#ÃãñÚ€×¹´dåó°øSC×äÐ6g5®Ðgz ÅcØ#̈’2+QÂî«±ŽŒ—÷�æHX>ÊH»Ó©ƒ1Fc`vp ïËæ^&’Y�"Y*´NCnµ9‰ÌcDqš›ÉFMzAä Ø¬�÷- èD¹ä�ö�¯ …„™ºáº†„2­+Øu€ìÅ�·*Ï)žI›Û\j ŸÅöT]øæ€a©¾~(þ^ bïGãÏá�65V)Áó‰6‰v�„<KÊc—xÛÒvô£ÐßEãEÞÑw;�_ËùP�ðÎ�I{x†ŒMhgBܦë\Å¿K5—dè™:¹!*ÙbRH˜¥£€0Gƒ ¤1{¹§(ü¢:ÀÒÍÚ (¼ˆcv€©�Šá¹EE²µˆÇ‚$¹’h9‰JF¾CÚÈ(vÓ1PO3Öò¬ ŠO¢ÀwPë¦6 œ´]1a�¢)°¯ÈP3zͤš Ò7¬F!±xö „é–~´¼°œG0b‚Øk”Øk2ýÅ×ò…ëx�QoDš£ðyÿeØá5õ7­óê_·ä P"ö|^�›�%†NF`€¿öRgòÁ•„“Åå+=ïÊ:¾Ö Û1a€ÈŒŠ(äŽm1+ë³+ Nƒ°óà-8ñ^Üý²�Ô«gMßÖ|°{¹ù•ðÙÕ³þR8ù„…R–Õ4ÙÊ”1·Fmܤ@!�o,ó0Ž­HbçF0Þ_¼ h¢WË:©8µP«¿•lıޜ�¡spíŠ":áàôØØ£D‘-ì~a—“œAHÜ\Ú4ÉJÁô<Ú!›ŽdU¯ì¤H]=Á¬ c*$¿(�OÓU,WøS4кÆZ䜡¯6Ãøq5`ª„<…1ßÇ(öšà6«£Q‚ÙkÛ]ÆÓ]qp¶çƒ°ÍàŠ&ØËa†Ö¹ß�vÏ{a×oŽð¼}í=IëÆoLˆª­xµ»êåñÖæ…+ÕÚÁ$a…ôž wÈL±ë€)€�EòŸÐX�,›î}å Îq7A͵Äm¸Ù’9OFq„Á¯“òöuå–ã7p`6Õ7aw› <ÀD:òmÓ�rôwæÌÕ\Ãîn,â±SÖì‹hª‘ÐXÿ²? iÏI3ƒÕ€¼a«¦µ.—ñ@I�›hø M?P¤Ûi…q"›Ç8rrHðâ·ðZÃâIOBeR‰A UÖÁºÖx²«t�Û“(à2}òC²Âãº7v%†±pHvè‘ÄÖQ€7¢¾MÿjÑ?Å4�y‘äÜ%ø—õå)>ÎC"­³”¢i æ’ŦÒTEl‹E£ì(AGpÎEèC£l„ßUÙ¡zyÖºè]^_unÂîI;øÞyù'ó² º‰½5±s.”ˆû[øÄpl2ÐÐsì‹´WŽî’Ðk¡JxâgòhðCõ ’^¾x£w{¹OD§Ý;›Gj€­H=bë‹Ö‘!ˆ@ãI5c ´àà�v_yåSêd_á)1Ñ‚cö¶lü“àT1}g´\‰ï“’ô°Ñ�Ù†Õ‡u¡ƒ¿z(�ßx:ûèïÃLÃkÂ'sŽ^Ê?ºÅË%‘Œjhî™Vðþâ†È*&1cvnÒ­Í«ºÏ(«‹ý£”±Ž gR>9Ù“%…ʤ 8aYì1D\íxõæ¢c�½IXÚ#C‰„í;%߈Æ—Ø­ã�œ‡Ë@�†E€Q‚Ñ 74e¸óÙŒÒv ííÖÆ?6H×׊¥¿û·ê^\ú°«VX±ê�‹ÐÎ�ê©fQ�”ê.‚iŒ›,Ä+΀à8H�§ÀVõÍ"Á~1M^ÅÃ×/ðC7</¯Îϯ7U û.¬Ôg…k=}€'…ÍÜ;‹*›îüãÊçÉÊçßU?ÿÊØò`¢à:X*[/níæÎ6®ÒsÕÙʪ¾w–‘ Êõ´ƒwY©^!)72ÕãL9ξbŽ%é¡Ã ,R »¤ñ½¡þʆ¾t6$í‰A:\YÁWÎ ´Ù̧ö;²©KÏ\'>QI¸„C5ŠPx`áö‹‡Ål‰mgú=€yM{µi&tQùæÂZŸÈ9C13Mk´R¢J <—ß®Žô�‹ÿɉyãìå„\ꔿG5]ÄB¸£^â“#±W(hgñÍÛË ìØú ï¢ÈË…aèñò“I'»ê†ÝË®Ï:~uÕˆq7±BM’Õ9u–ÅmR%×ø0,¢ "3µBZ3e u£‘ZJ”°N+Z{”0Éê@gtOÍ)@Eg­¥ï¨Ê�bm�UT:†o}u·€®?8å�£7ƒÎUb]qÉsôŠXg£àÔάú”V‡8uˆ2¾QwÒr ¢J4ê„|¿ÂJ?`Ì-L4V‡å¦î�]‡|.®¥­ü}5‰Ð �sÝ&ÛŒÁT›‘Šh„è]|ŒgRˆ!Ê#ª…¸WèE%p6Š¥Žâ¨›ëëbm´ë^ŽRu­E•šY÷ �±_ÚCË"Û,™ëêFã9Ö†äïÛ6LŒó¨¨$EŠJ�)4 à ¬ö�& bt¹Î´)P˜ÉðuîÖWIX7Ëã;J¯d‘±ê¶J s<2ø�Å}Ça½Ký5%s7@Ô9Ì9†hLBÝE�ÉœäÑ›Á;scäd¿¹Mç’‹"(Ù�‹bÁ`U›BQÉ™êìÒ=ŠTŸIÂÃ9^ä >÷ T8ú6Q‘TäÓ É(umD‚p–üà¡–äa��#©1µŽÌEG.L o³µÍ«˜øh‡"ÃhÒ~‘%óÒ1ßœðA˜Zly“’šE-Yø#bÍâ›Ä|tÜU1žéu‰Ña?,'d¨ŽKºô¢hÉ]ì«ò¯ƒ5ÓÐúSHGRpŒ:å "¤MŒ#«茀ϧc›°I§„ÑÅK,'0f—f1EÚ™kã)Û° ]]mÝlM¸Šƒ0¤§jãå°<êŸÅ麠ÞHh>˜(.èÆU8UJÞOÚe´f«µ•dlHŸ-¤vãšó¡dêTˆC剠b ºP9ÿð†E°±–ð#žò–Ä ÞÑmr$ª­÷*x½;±Ê¸ÍyÉ&%«!]*†ù³ùQ ÞwKhFò4*�Ú¯820Alà'°v)†Ür!eëfÌs£6IàâÃÐ%òz�ùØŸ@‘p°¿¨ÿKü÷ùµî·Ù®$‹+‚>†‰fK«"ÞºÂvy~Ñ»º¼ìmjHó]ÏKaënU”ñHD2}EZ&æ�p5fÀg2¤¶ì'0£`¾M2H�%ݲ>`òÒÍW£¸I3Ä‚6ˆ"f¬R×qÄRõјU ÎÔÐc”&##9æ¥D$Š›¯#` V›¢Œ¾ Óýâ2©@Kk–�=´K€£öq5­‡ëUð6hð—¸ MjN4 @ J"�(fI GQj…²,øz1S)šô_7˜* õB;-gæÓÅÌv±j°Ò¯8çH¸ÌìÛTŠ«áP½nfÿ•d0äN¨õü P^Âàå #Ñ(æh(¹—ZrúÊ oÀ5M´{ƒ±ƒi¥8ÉÙS�ÁÚèQ8Ø�þ”L�£dœQIêWðwaY)äÔ. �Qv1ƒà#æ?9qS:}H•N’dYO¸šã·6A‹©%qŸTË8x;¬ÚÙç@Ž Z8`ÉC•1À¸0Iéë{�C��/ ì¦X®–ðDbÇüE²±<-µrX�´iñÀ§9BYû(ñIÖž~u 4Ÿ ¦ºäZ>æ²þd¥6ß¾Z>d°$k�ÃÝgÿü*›‚ôе¬Õª9ÆLÙ×b¶ÃìD›’E²r¥PÁŸˆJ,ç­T /§è¹X©b#…9ÌCmò«˜tÉþ2ø�*ÏVýÐüÈ‘!6OÖÁw œ$GiëÎt8¦Œiľvöuvj„ãJ ø&mÏÔòÅÈxЀ¨šÖäÍÆðŒ%}lF%ÃÒŠÛÖØfFä³ÄÒ"oÝ(öyÊ©äD­º.Á”m ?µæé¼JÙkÓXš'§$^/¼äD/[;8'/v6N^°qòåîQgþÞO®ÖÞ­¢¥\ª¤:iÔê0(mZ®å¸Lºú«aÐï©:·3"G¿D4Ä,B‡Hj_²õZE?J+G‹iä‹Ó‘W«Gcc–£)èól^¼Âãð‚œßÑ Üé{6~3L´®KlÀ�`µ¶»­Þ ÎÎ4èùë1j—O ‡Â)±Ìg(¬“ò)ÊvÕ—¯¯Ë®«ÆÕñ›€¯Îvþš&Lþ:.ZDz'ð†Êu{¥Ÿ6Ö¡ÞÙÂù;·H­F¶·’㻪ÔÔ�×áaÙæo³ _ú.{%²1B/uÄYÐôLׇœK>èjÚѼƒ&hìá/_¾ì¶¯¼{‹¬¤—áµôÏ—•ZàR£—b‰l™^”©"²©TŽU*vÓ3R±Ú)'ìo~xé$Ão þÚ$K&m�¨¶~T´þ‡òäu¡ƒF”ôU,¢” òt#@‘ Ö)'amÕÍé 76ž‘YÍ`ÐæÍxyxÔËžwukXÄ÷Ï ¬‡!` Àw�·•Ód(ýEk~XØÇѺÝê'NÇåDÓbq®¦Tl�ûu Š¿¬�×+sÐøÝ.cMò>ýÙb,ÙL–Z¾d‰œæÊæcøÐ˜VëS’˜ÖgFbZŸŒÄX3¨ø, jµ3ÓZ «ZI �/Nªa½«P ¾ÐoCጕ¥µê“³ÖÃäì$¬uÖzn&©˜â4ÌœtŠ_ %’µ†U¾4 !!mJ›C¿‚ÀÃbé`^hÑñîC¡½ açôæôúôêôòôâôü´wÚ= ƒ×¯ƒÞe÷úºã­ÌÝ!DÐ%{ä<Ÿa§ ŽÊL)ÄŽRØç¥Sh9ÆúÒ¤uqiG²õ«Ð¯5 òÀ•–ˆÈÔÁéÇÌ`�ÕÝñÎ8 �e/Êaµ¬_�6/ëÍtP<†¶äŒíúÈX�w ãDz´eãêp$‹�k8ŽuZ6tª žkij@ñH(úú|Ø1’ðtÍ2 úbF€ØÛ¢˜šYŒuLý‹ý}X½ž&NÐ(ÐրɄ±F¼}u¬q�‹ƒ ûœ¤Ãl^€²E>v›³‘·ijæQ² §=¨,w_¼¹êö:—7—˜Ÿ£[È’ÆÜnc $I�=F‹˜š}WìŽs´d’'¡�m PfÉT9¸ÜMÆlQfÙèõo¾Œ÷×Þ×sx©„úÊȇâ:«º¼5wq>•³º…Œ�¼‚¬Ûƒ»Ý:¿¼hŸ{×ÅÚ¢|˜T+™�\IB[}AÔ-ü#qh½Q©æ§ „[5×Î*§£ ��×*�Ëø”Ƀd¤bÑÌ¿²uBdáFÙS¯„Š#k(�º°^:f$­Wª¡<¨L7"{žD—`}þ¹‘è°D„ä !jº"96„R#}±¹zdTŒhÓëOu)¼õÆ�—BÇDyÞ‹_ ´EÖ¼O|œ}y^ƒJ”Ø£wá†÷,¿pä?=òWû�ÕÀÿÓ§Ä~>IâÔÒåŠ$1Ô_uÿ†Ó3—¦p} êE®[eÇS^mnw¨c>;È1£‡º¨wÀgÇÞt�wMª¥ÄýJ|ÀS„?®`ÊÁ�7¥ù2sû(’7²X‚¢ºœêø€Õ~Vžé96²ò¶{D1fŠÐëÝݡºv.êŽôÓiå/üö¦sÙ¾ìžûû:¼ 0a:ãù–kPéÜäÏú~¢JíI6Ž(@K3j‰¤áÏV£¨Äê’Lj-I-aPÅØ’Þhš#'Úêµ½íò64V„âå\�â¦v"ü0�¸žCÚLÖÙYC..5.5³ô'(yÙðßNqÿ&A¸T6+^¸k¥1©Û—çívO�‰v§Ê¢¦ðM¬[qa:2o ö49�í>–Þ… Q®Ót£2Ë„;e¬T¾ Z´%ƒÂI5­Y*®%{ÂP”6æsJ�V·}y‚hZ§üé÷_¿ò~œêB™MƒwÑê¦)‰,Ý·–®a°rTÈ�à¸Øå‚Ô¸"ÕŠGà±Ðê›ëëîåÍMx½)²úÜ+²ºGå\¨@^l›DTÒ· ¤É Þ Æ*SÅ–d¾ñʬçeZy)8¹@ŸS@%rà”’T¥Ac>· ‚t¥ %ÙÐ=ËãtÏÜ\Ù«¼xø@gé”zc‚†t`¹Q‹«ó ¶¥• ý œß¸ÉGÄh Ê+õH™ŒaÞÐÄÞIK³i*•Úh…'D 8ƒ‹²{Èa(á…¦QSagDœŽ@wd;ë‡ Ϻ§1Ð Š Ú_)¸ˆ~';&!EÓIÆŠBRd`Å…Ϻ�sàÅà mWŠ" ÒxÀ%à —­ÑCW’↊»Qa”÷P©—É¡2•¡L)ŽŒ©‡Jé¥pß°©! \;ËXÑÇ^Õ ÛþGüž† ¹‚‚ðâF4ÅTº¬Äоå•Û±‘¡Ð-“º‹¶\3ž# DÕìÔ<†uwÚ=øÓÆ\diÑ© p¦enÞ�£_Ù‰Œãr@òŠÇ±nÚ�٠ב(MR�ÑD���ùª÷I¦[Hz…ŽÓ%¨Ó^@‹Ij:!(+^MO9dÛ$‰Ox¦2,ïK»­K›¥# ]Ö´d‰d:—dƒA.Q«{¢‹D&à…Yüå�tŸM‘÷V¾¶4•V Q† éwI”��ßÁê”{c\'®f‡=üŠøpyÐ?¢¯¼àOà�t3NŠÌ!ÆØD½?ß4¾_²0—�*tyå­“´ƒcTd¦\ùÏùE‰YË ´Öµy¥êŽÃ(u�h)±¬º¯T?¥FBµÃ3Ìžhæ¹Q’€ªö’E|yôræ¹o5$ Hœ{X®h ˜uE:#Ž�庑TSþþÌã±ýá½nÖ¦_)(É]r‘ó¹J<âÚ·T„0çN+ôi Gt d�”—p/¼aÞ§Õ%P¨0•‘±ü0\?J´%‡|/$¬„ª ÐHx½ƒ1EC&^êQ‡f ìÎé“�Á—2¥*]4Ú¾‚F¾M�'h­WÑDj½G¥IÆ7ÈsIÅ©˜-æR5›™žtºpW#úÊ”¹'ÓrÝpúÓ°J–i�·&sªdzÒBË(ù(‡ÿx´¥*Î@3ZEÚÇ ³WOí-šücs¾M’ʽjŽ"©<©"§q?¦†t¯/z××7áÕ&5äÂK 9Çf#xã¤O˜(rbæTÍ"&Åo„ÝXm 9¸â‡ÑH슰u_œbj…$•ÙÉ•ŽË‰dÃg”‹}rXEB—Àe@˜ýc=�ÈÖ²àFÀM¹.9TÌ™j¿)j�!´Ã€|:˜É}¶ûrßpë+2½ñzÌOÒ�Yßtj¨˜Œ|Îñ›:ߘŸ\ÕÆïÅoÂZ@ˆegiWéº8‰ŒéO mבbZ F3�¶ñ5ÐV“mˆ"Ø<íÇQAmGLÃ_—9W�\%Ä ~Q5Åðì’ØpIÌY(=Wh§^Kã$o�Ln%Uf�x�hšIY­v‰ºÞH¥Dü·ZÅ*²i—טMG'^OÄ—-è,IfDá ¢�šA2Iü�bQ�þ’Ý8D”#£‚f_x‹¢Å‰Sž %Dt�g)ŠÇç~¡.[à߬òÓsr0yjwðÞ]ý .ÿ}Ã]?5F@�@£ž›.ÓÈŠ4$¶ç íhÞ²�Vu§*&;M”÷hVßuBÍ›"·“5L,-B"é/'°ÍMãjª¤/܃$÷a2U_�VM`Ñ>Ê4Ÿ|>²Zƒ+tµÝ»î8âðعb¥€ÀŒo˜†�õ !ÐÜjlkƺïÞ8ç~¹¬ó”̧TDíNm,h †U®I HƒhÅi“—†”ÄIùÂ=²0D„Z-ðf_0Ôá¢/]Ú唣×04‡ç’LäÀ%„¦cªH…uÖìàLÂÇ”X’Ûdg¦CùÕ«† ¬ž¯°+0UX寮³?QÍì”:í²>‡€�NÔHÚ~–¯\0,#’ÇS®wÁµ-à ôz •@éÔæåÌ"¢Õ•V«ïJ<©Ìk2ùât”Ì•Œœj;ª�R4[£XW= ãÔÔí¨¢Ûo£¢´öí#´Ý$¹§ž6ú6ùI¬?d.‰|\Ë`a³æ”ª²ÓÃÓlˆ&ÞUÜ‹­ªVÝ©GO)šk §…Eå<7±kæ´¥šŽ­óA¨PÎg¶6G�M¤åßtHTõtU‘;{/]¹uL!õù–\ ƒ'ˆª÷�>©RRe B$„`ŒÔlÔÛµƒâß›Ü伨äq ñ>e3ª�!kàÑÆlÔÓŽ¨âp»Ù‘Ö8§&0yTšp lêÆ�Õü�ÙÇ(+[÷',ÎjÍXI�Iu�àTuêœ"e¾òº­`èŠÞœ}ÅRYÙ &‡]æê”Ú ¿Ù„Š‘üzÍ…Ò÷± ІU_#'Ò¦A©KCm �o“B"ôã'A„vırßHìõè"Z#\Àª€M‹+ã>¶Ê;@T»«»­2؆h\Oجpä$÷H‘I."mÚB ä´^TP‘t�LˆTõ3)¬VÌr)H$WwMa(]¨Ôÿ*­Nv¡ƒ0ÄÛÔ–T×­(ò&ªZj|¥ï‡C•wœ¦¹�¨‡Ø4º7·AgÑëÝbG*üsr0‚–‰œÔãÅâ¯é·Š21õ³$&þ³zñ \?©!ØÛ%)Uko®�ʉ`ê[NI„MaSt{ÎV Û¢+1* "¿ Zv�õE â-Ø4BdšËïÂßW7ãÏéeýçí«ƒòúp€ &¬ã üBE¹¾ßŠ_ÉOÐË?$çÏ£Qv¸&4o�k¢l\0èB>©à-?Rû’ÔÀ+ž±ÕiŸ³Å6Ìd8$nñŠ[eô¸U"{â°…Ћ¦®ƒ^zͽ(ü§B£=�k Í“Qœh­G”žç¢‰¼!À]ÔÝ¢ <‚ÑY¹£ùp…Ò¼³C¢4\’Ce˜öCÔñ—alÝl4üÝTlƒ-?+ÐY÷ém‰gÝ=¬‰p:~ÖD:ïÃX/¯Îo.z×Ý«ÌS+¬'²N žVH»¸¬îexòK´D^õ.º�‹Îuï�³^Ň'?ìç1E®Î÷ý -IÚüS$A ¬m�ä•’¡–ÑAª ó <øKñ¶i–겿ƒ0ÔÊ€Ÿ;…³ñc§tÚ°Óݦ7<÷•‹BDqÉÌf;.ÕðŒµ¥n&‹;Î_‡8Ñä�ÎÓ'¬ R—8ÑÊIœ$Lh/×HU—å){C,…è«§ð�Ô8âmn' ް׾¸ z§h¸½ Z燂w™Kê á¯âb–`Œjê´vã®MÓN}œd} X§�ó ¿Ì8mŽ¿]«½Ea�˜ÚI G ŒR(Û Îô†ÂØü(¦8“YCCXKç_ˆª†ß¥2„�Nç,ìy“-tú0B(¹ËjµížîÕå‹UfSŒ¦kL£Åm@Å2ŠÛ`æ�Ïüf3€aH7Äò8keåï´î=óJ«“qpL%�¼I6èpÚ8f ƒ†t¤*ÅÎ.åJFóäD'Ê&Øl ëíäT©äDtÉB—º9þ½7* ™Ô 8ŸbLö–Ì«• ]ÞCVvêFWÓ“(¾¶ÉQÝ,2ñ­¦,Š ¥ü…J�wÓÄ:¯Bô¡Èç½p�Hc_<ãNd›p¬yô’4pòÊ?r.Ô¥Ë ô% wû�X¡+KQ(+LÎAµTÐGŽ¢‹-R¼p·ƒžÐl Ô`—Å>ä€A…£h ¹å ››Àºí<I2œíK3L�4CGt¯�ôɈÆ]”ïC36Áä)é›f$p^çüoÌw±¹Ä&×ǃàìzdÜÜž4Îû,§Öée`£æy–q– e¾ÒÆâ`#C¶ãƒµQÁŠt{ûØ€pæpkó~<81v+e¤Îœ¢tÅMg±h2Ç­™``˜%–´~ý…AÒêúû³Ðз¶Ä7ˆ¨8©s`ߘîjųå ôerÆÝÄrñ�âl"êîâ­´0¤U¶ºí5ín' vw(\±2WÍ©zÄÖjì¬Þ¾vmëeèš ’ßdã‘VÃþ±RRÞüš•2p…ëªõ{A?Iú!k²T†y ÓÕ{—�ûßÁ ÎI¥ÓI$vo—œ2ÚÌ…ÍÔºí«ðº{Ý^ÛCmkK’î–0FÐå [­ülÔFA7 øuûº·Ójqü:‚KJÒ»*Á_kâÄ�ÍðU ÞÇNÂæ`Ç>¼VuT˜Ïåk–Ö¶ ÷|lÃ2Y͹º¾Æa³·OkÆ0¤ZÒÞœšžŒª¬TG2IiíáXžw}QºÕi̯2ަӍt“þ…!Â�9?Q,è6­ð䋃íc0 ix¤ÝÛ:‘…n ´¹òÒRˆº!óÝ6¨@�¡a¦Ã@F¸S&¨Ð÷TuQN’wõlõÅÝ`"ÛsL÷’ùv´þ-2i‚V3�í~æ< Y¦øLˆ5f·?Ÿ  ØøÙý›YýP•rð,DMS§–4·hÔ�štKŒ „Q,€øb¹k©®^,À€æ4<…óá�É·Ô’Èã¶^u; /Ÿ__ò0A¾¸ÅÏuhZxs~.Ñs¸?Œ˜ërÓðPë7RH3ÇÙÖ¹ #ËýL5HT's¬6ÿ]ÀMXté"8ñµÖúæ�Rï²´e¦qJ’p _©ƒcžC¨5 ¯nQh¹¸ ®_ÌÞOö�Ó…A@ê)ê[¢ŽÁº�LP7Xw‹`Z·ÔÇÞ1¼‹óß2zš¸]ò*:q»Y%·�µW3Jʆ€®Dì9í‰V©ÄÆH_\‹DPÑêš².÷;Ó©íSDþ>Iß[®§ÊåJLÛ¢å6Çï!tt4–)œ›®È-U�y=4ЄŒ·ç:¨[}yX;÷�@B^É!1X¢�€½+µž1Ÿÿ¼MÍ÷M•�?ÁYRÜ0­å�ôˆ|FŠT� ¹«Ü—$=Y`ñçG’ª‘Ä.ÿ‚É’EHi¼Ž˜ú—uuãá9´j5z’|ŸSg³�ñÌÍ]ší³o0±ýVL®£x s5SŒ¶yu}r2t�©®ú¡0ÆwAM!C•oµQÄ󾮀éT.*‡´m™`5$D¨ ]QÿÎëÔšÆ [@£Ã$K†ÖªÃòÈÕ5,`Œk5W°Èƹig6éTù�ò´tã êð`ÄfáúÚQ¥K}ÐÀÖ>“ùX�?ϳûçpLÛM ˜Í¤ð=�kUrzÄ›Psn0„Q1÷xõˆ*RÔÈ·H�'%D'Sh…­þ²E~hú�ŒR4úÌe±Úu�Ãy �ÔT& ;ϱƒ�îŽÖZ¢à]ôŽú¼°8dQÒY'Ãñ˜=’· ¬ÖœÅ9¶þpËOtÚ77mŒD N¸^Àd‚E4RH3@¼nYMf8*2ÐAËFmGÚZü‡´=¾nhqhùk{h>¿ð±IoÑReí.&'·;½z1åS.e÷-o!eOOÖϳ”¶£ ìaú÷L é:{8Öd¹º'—Œ÷=8ò©v±2°ìr2­wfn©Lm]|–ëŒkÙŒÏ}î1NÓkû÷~@Ûtû²×=˜¯=Ù»�v´WO¼i‘£©‚}\ìA†m~zrt×ÈŠ¨…\Tàè`é$­í´Òu’>S´æ!<¡Rð&»O8~Õxêˆ�œ˜¡Püh¿ºMK"�Z.msŒõfóB”ªéž‡}º‰y”`G·e;ø’Z¼¹ò#©š$: a×"R“c?É¿°Ò£™ç9˜”>þP¡±$W@¯°ã;q1A°�ø×€·‚ûù‹78S%Àì º›ÜïĵËà4Øi˜ŠÀDç²LùĹˆ@©ÂåÂÎ/—Í!BÿjFñnñiÕyj2ºNûü&¡ô`¼nƒFz‹­ü-1îñswb6ô­Õ£Ojh%ø H·èźľ÷q§«îº_ª“n·ÎM†jÅtKÞI¤ô´ÿ× [„_ɼp®�‡û­¢""à¹Z®+³aå}¦;¬ÙèR›qb‰˜É`ûY_"£k+�ùr—�íÍèÚY|X /[ÛÍkÇ_fQ ª7-¼u°ÞbXÑG‚‚1eô‘rï7D+4 ¹Í½Æ°²x:Ÿ>Z�ìYØ9�‰"€f"Ÿ½¥èïÞÁÚCLãôs=‡8ýŒÎÁ„5íù$:í�¢uÀ“ȆAƒ6{‹Âè<Éöàh8$¥ËºNÈÈ»A4B«0Z¢©©¶eÊPg2ÐjVŒ0.cëKÙ¶kâx¥€,{+êÙÅËLëæj¹ZEÿ¤ò¬N]¦*L(mŽcá8aöZLdê}¸PA*®²Ý¬ëkÈõ]؉¸zиòYVrÐ|²D�“›‚Ú¾²´˜Oɲ[d„v”i‰Ù  -Ô5ÁºkaO²læ¿^�f§‹à5’·Áò�eðW ŸÑ;P›BxIÏt[H«ë™|½´iÂ=Í»ðbç[·Ã}<!K›k–â¹O)ƒÆ¸«iÆšÔEáû+ë]+Þ½ //ÏÏoº›ê�_yu›¼VÇá±¶;6ˆI˜ÂÉ¥vY.´cµ}ù i�Ý@±H%5Žá6-ÂVA™HÒZÚSK”Ox�?èëŒ{ŸÅE‘U«äI `�›TÉ$ ÜJ3/l<ÎC�MZg¾"©.²‰L<Çg_’ÔÀb�’¤f ¿’¤öµëƒÕ¦À‹# 8Ù?<ÀZÆSó@r³u€ó,‰rNÁ8\([~ÈâÙ„fÚ䜩w¡cQ8ô1U†y§‡kæûÜÊáôt­|ùÙÊSŸê9õ¦³¹¡a?Ï‘ƒçY¦Í“ï²²r�â÷—Ë)7karâ¸t)Í$:DMŽìòÔ?"{Ûa.ƒ?k ~ž‚kñ\ÖJm½>”X@^É}™Ù±£s]~�Û›Ÿ=GèOÙšPô \ Fü4\ía&‚Ëz:&²EHfX’·”xþûÐD\6ðxxA_MtâÉç_P'(@ ù¬A2ç‚ÖžÃ7-¸CÕ¤ŸÌ;mT;¨mtKÅEÝõtQkà?�‹zžîW Ίy¤\Ê&%н[t’L1§Æ‡/Ʀ‹$#–D³®ŠVcÇÂ:+ðþ|¤—fÛ«�Ü_«9—m3k§W­6G5{Â�†ñ™ëµvr…¡�,Ǔ݋ džZž˜J ¸Ø©‹¸ÝO–ン¶íR —"a±¨¶H7Â`µí ÑŠ�õâ@ò!Ê¢ûX£$ä–µGy2Ç߆1g‰r]x¬\¶´Ù)}ªÅßäžò¹›F9¦ü8›GM *+pÙJЏTGäÚ«5®H“¦Ø[ާdS©á„a½°w HÆc“�NÄg x/ƒª)ÝÏxëÅ5ã`sé(wGE>­{#Y·±Üƒ®.K ëm%ì ìRïfú¨ò5­žyDÌ„Ö ºk„ÑÓãèB‚ªz#¯]wÑ8¤mñ„Ù¦ÿxL7=zvŸÆ³ë/´ØtÓÅ1ßôSç›.vK8}ŒœÁÙgX L½Âí'üÕ~fƒ9 |-¬`¿ùÿPK�ð9·KàãPKV= styles.xmlí[K�ã6¾çW vo²,?Ú�LO€l6`fØ™äÐm3‘H�¤ÚíüúIQ¢dI–ížL2‡¬z²ê«b‘R¿ùö9MFO˜ Â裎'Þӈńî½_>ý௼oß~õ†ív$›˜EyŠ©ô…<%XŒ@˜Š�!>z9§†ŠR,62Ú° S+´q¹7Ú”y¢• ×Ì®´ÄÏr¨°â­É¢ípËšÙ•Ž9:V¼SW|dž ?‹Äß1?bi†$ixñœúÇ£w�2ÛÁñxgcÆ÷A¸^¯M-ŽJ¾,ç‰æŠ£'XA8Ë›b‰†ú§x]—hžn1$ÑYVÅÓ~0"žö¡‰ˆƆf®§wOï,veS$9Yï�¨ÿ{ÿ®ÂO‡ÚR¼µPEœdƒ—i¸]yÆXéª0ªÝ�N&óÀüv¸�½ìGN$æ{ÔË¡$*#ÎÒ¶ _‡�ŸL-7W‹îÔ¼8Η¥#»á ¢3-­Ä;TšN1Ö|%¨m¹U �ùÚ�Îi®Sï­í¤;]t‡"ìÇ8JÄÛ7¦ÊÇ#ó[ùùè}”ˆ<¥[–x#@»åJIrªƒ~5HºÍÅèÿ,Etô�­GïZÔýeL|sÎjž{£š%âï1Åœ@–¹â®qdDFPOˆÕ"*ÂNצ>‰#⟊H(s—ãe¸þ·œ(¼T¤NBâô’OA~‹çf0°¾Çx‡ò¤¬æÂÇ=GÙ�Džå-~û‡Šâ’Àx¡6Í�8 ˜}Ð/°ôŸ½É8 W!¤µÐOçt¨éÃ6ˆ}‘¡6aÿÀ8ù€ÃÎû¸Ÿ”7Q /Ôý`½g¼mZ‹%°œ#‘ߌ6;”âHÇÊ�”!)~å’)#cfXQ’�5 ýØrŒ`l’/-Eõnå\ÊbO¸/·5@cÕîÔè®Æ:i}„Q rÎ2¡ÓívÉ®ü>[M.0„�ªäjãK ’ç°í˜ñH�?ÁÓpšIý,AtŸ£=<Š SÄr*9 âûÿÖV¢ä|häˆZé"6…KSj ¥Ðd múÔ’àç�%õ\gI­UÈjÕ3¤¤Ê{½`�°NÙS˜˜õǘûÚ—G�2ÈlJJ÷b*Ëi$s£ðdØ2aÝ�Ë ³`ñcÕG•‘Éx¾ž.ª’¨ã2ƒhVõpxœ¼uïŒ÷"Li.ÁRëÖŸ…Úf¦>«/‚UJØ6�&¾8N¡¾š¯-ȦgLY. –; AÕÜn”`"æ$·e\á^a º0$A™Pˆ½×°ÏÙ±až4*ðŒ3_²=–uTRvɰk° iŒxìu6›¼ îA­T•s®ïЛN~Û²ødE¡*³�üŠcä’;Mƒò¦Àow×õêRÇJ‡vƒÖ2Q�¡z¶eRª“Ãde OpenOffice.org/3.1$Linux OpenOffice.org_project/310m19$Build-94202008-01-30T18:14:032010-08-20T01:34:43de-DE71PT158H21M24SPKV=Thumbnails/thumbnail.png¬ºSp%NØõ;±m۶͉mÛÙ±m{b;N´c'›ìضÏÿ}¿ïîœËsÕ}ÑÕÕ½ž®Õë©úŨ(É ÁãÃÿøñ駬¤Úcë�`?`¡ÿ›=RðüûñÃaꧤ˜†wÞ…!Œ¿ºås S*÷©‘m'Ž#�ãièŸ : Q-´u4ðØØXø“ã§wƒ¢“ã•>)QTËñŠtU9y÷ë-NÛîûÏ�Üyj[½XÈáœ(ã“éžë€U¡ŸÏy÷Cdáýð Ðè¼A0µ�ƒ �ð­XÈZÅmfýôKZˆ¼:±`0¿UôÙ@&Xv ЄµâŽ#ÁašUu¸€ÿGÙãØ-H/¬Î -âÁÓ^ƒâ•Icjfý†ûRF¾kFš'gÌGî+ÉÚáF!vÂ`Þ{•ôþ˜?õÍݾ6¼dÒ,'ÝE&§Æóp‹Ý4ã^/üëyð.�ÊÙ§Gô3%ØÎ¿€–ÓŒi¸ „šþPûȳ$¨Ë%2çFzÈ\6^üí™×føbd$]BO7Â$'õ€r‚sl óž£ÈˆÿÚG[¡y¡4N˜‹ÚÚ¤HÚ½4@;cи÷W#¼ð¥A‘â‹À’ˆ/“ÐФx}.u*Ä¿¸Ã ûTª^›Å1‘8†œßV€ º}K ñ¢ÜÐÜÆ`»…¼)øþØ2beÞ>Mi£vŽÂ�\ý(=0ì.üíöÎl6gÈb^=íäÀ`M Aœ�÷ð¹àÎb¹£nŸX7¾,Éù—W‹ð¾ý„Ï�¿ù÷ŠÛýVOóu¯ÆOMSt¦é}@ •ó,T†IS¸.º­µÕ ^†cc¾å¥S×¾vƒÍ?+ }Už´Iû”à1¿\ëO²]DùhQ„Òd~!NL6²ð oûñvßû¥7ž¼‰”�«"6ÅbÛ%ü�ÿFw”Ä$.!öÅ{¾ðÇ�Òˆ<¶]1[îœq½g¬ÙŒ6(§øˆ"¯¸ädŸÌsÑöÇ�öö¶Y„w˜^¦_X%Ze^z�°[ÿ& ˆ…"è’^'ø÷,„ìyA_kã?‰7©R‹žõ.ò1L\À?2lîÛÖN¥•üú…S°.ø.uïeŠ~ÿÍyù(uhHåZäÛcm\ìm¬} CWñºØvš§¯kܳ3Õ<ÕýÏKÀН(-ßÛLƒêй�$تèRQy–d#w¯ôÃl :72Sr. �cÐÁ•NÃ1…)¬,ˆ jp›¡˜/Ž—™*+¥¾kj/q/YlãpëÿfÅ,!UuÀ-Œ¯Ãgï•Í€Cš6hKä©A74(È¢CÕÈ¢R-åQ Œâk–Ü·d{„¶k²qI�žÅ¿–ÉôâûmŸMtN¼ß†%»ƒ®yyék\LίmìëI±,3x?ñ6ïN÷AÂaຨ£Rã)êfAN ì³C@ÓuÖÀp‚fÕ¾wRþî(¯Üd¼2r¨=ÒÝû]É 5ÜOï¯ú¤Ûûé,áEfZ_— ‹êþ£Óóߣ½,øÉÞ“œ›÷K”’J9¡‘Oˆð0¦©îܪ M W¨wT˼Ž<�‹ ÌuÀŸ€KñéGé²L&ÏëW°Ö‚j Å !rž»¸E0QÙ´`ˤcñŒUÜO�*á£Ýt.)ã(¼Fƹ.^„]vø#uX1Ø>ŒBºZ©Xa¬¾IïL¿(›�¯æ\~>¹‰+ôGËÑRq¹ŽŒßZ3�*ã½TV%¸dÜ)pðÞ/±Šœ�k¹ó ž ‰ØV'Ý:]÷p—ü‡z“'ž2U#“ë ë͈0U…ÄÇ(*â­ñ7þýVvõ]ÕPmzQä:ã`ls€Û„éE…(¶¶&  ÿçXÀ«l4œœ;�Õ`ZäÝ £I®tש­5ºÝè"°ù‰‰QǾWAaû�9N›��á«ø… åù£õf¤+~vR�ã´ÑsEÝ‹õ`Íg£Yÿî(WJÊè™'ð­ Ï^ÚWÀ9K�—“+mgÕAÔ¼ H÷»‰µâ¸ÍXòæƒÒ»q –f9æÃ/Ú€‹¨` k®ãæ2© þ ´wG¸²Oô‘È ´·—8ŸÇ),ïÏ&~Ù¯F)Ê*Œ nTÅeáú«èýý:Þa¥ÂOH�÷61‚ux II“–Á­íµî Í”Ž •Ȥ¿ƒ÷hÁ¹ í#ƒSÍðkܧ$öqåÌ«%Y"€FÈïx&ï�X"C®Å2S€´ÓÂvÚ †ݦ‡-79%3/†U=qÍÌÍúq–Kþ$˜D× ÿã) f÷¡I_ ¼¬|Yb]rú$¾‰'½�ÀôøñºN@ïE|ñºé€_ãµ»Œ «„ õ·»A�ƒ!oõÆqà$”Lò~¼5¬cŠí™•ìn«Ec7¤À¢B8_Hô¾`¦G w¤þõwty€“Fy†TÞ ·ÊˆÁØqæÑym¾-yO4£ï&_.ª¿%^6F@«8©Ø³²k„|±ôÂâ‘ô).ex)nNc%pÛ f²;¯ýr´ + %ƒ)ã�"“LîÅàýÍ7³‘·#eY‰/¦fkqIª¸h+jâúÅ'ß|LºøÊ«ÌNø³êDÉ ¡ÅÀ$ú¤‚™'º/)Ìï¦�;’Eú’ Ëûî0°‹H6a/Øß´oúÖãÂû9ŒfQ8.ýÍ �¥¾ä†%Ì…×ì„LW�§ÁÁ¢OBØÊ]R 9{HCMHŒÒ23¦Ö‚Ï*E¾yÊÀ:œd–Æà«¬#ˆÈÔ'H~£¾ ¦W†%-^&¡‹³Žazy»¯Ýø3ÉÙ ²mh2ôÊU£Ö].¯5�¦+û¡ºØuòÿßYºZjY-X&œéÒöb¾òQà çij>>GÆÀèšyj= ÉT)§b¨§©Ý@ù?1¾„2aYøvÿÕ�=Z3þ*o ¦ÄDeüÆ‚‰²™¸çü<�€•ÒU…NŒ# ‹ Z|0FuSô˜˜ q 'ÚjÜýûs7nK¢îO)Ý©ë„büï•ñîR'ž`7äÆû˜ÁŽ¡%`œ¬«YDó6dåŒÅÿ™ÏfVC·F%5(è%+0S²àm︇ ¤{¯²ÐÂ凎«Ö›œþ;]8(ûa‰¾‡½§””]�† EË„i*ëœCÆÀŽ°ã±›*Q¹ÛØVXk¯º=�¼Ñ0TA‰EµTÒ3ÑÀÈ_a˜o`�.Ëp,g<)�Ryx5 5á1~Ÿ™Å†S#� 'ujÁK�¥ 04ŒŒ‹Ãƒ·!¢ ¬ý[ë7Чyáíê�5)ˆJW¿g} oûÈGÛ¢¨Û±2î RÕl`·xß™º±â,ÇR�Ñ Q|¢s;§™øQìêBiDùO`Ï ƒ?�*é!ÚšÎ2ŒGx4jc¬- ÈÀõ° }zpça³mr§[‘u�£¥–jVÕ«¤’¡L+Z1Ëå2¨¾I;¼o`£0¹Is!Jȱ‡¥šÍúuÜÓžZ›àŸ<‚¥N`xèÍ< ÃÃÿÁ�‘bßMüC›'ƒÉ¤ˆR(�ªcÔAR Ù¤FëöÔAë~¦�Ažé¿ç±÷Â4ºø8øQT†=/ó”Qbnêaå 0åèì°˜�þ�PÓÓ®�PàˆÏ‡E¥µ°CûM¢äR湄\ºvÃÓOR—ȰG�ó¦ûÑ�˼ú ‰Ux⑪lÄiv ˆ/ì ê1ÃêÊúí4Aj¾z¼È¨U–-¬à—®ú°X ¶¸9RkèèÜ‘P½Mäz”²mŒÛmzBÆêP�åX½Î@m6öæ”è"8µŸzšôÀQÚ›ó6AJ!|™‹Ú‡á½FÄÊ#H5„‚ž±ƒ…Øú¡~kiâÏP9…@ÿ:âŸÐlÐØ5ú(©Ñï£'ÈS„ ’³^!² .R *æ0´øcЦóð†E»ÞA¿hÌö…â'G^l¾GýÈ/}ò­(×W�³©l#îû~È<—1”[)j+ 2±ã�R¿I.|Ò Óº�ÕcíÇ�tiÕ–â†O†ïs¾c:þ|J]÷üâ®7àóxcòÃØ‹„m}ÜÕw¡ø¿IèÿÕUE«xYÕS5ï¤öWfGt­¬™¹-b¼ðv vyÄ ÕÏî§½hG£ÖH½WsYXŽ`¼8k·{Ìü˜¸û¦˜¹:g© Íü‚$®÷Ç7fzâÖ×Rb}íàG¾�êzúÀ ý_cD¿�—%ã¥Ãr‚r–Ⱥ§í1Œû‹& p €ú½8R…¢+aôì�çå/Æj(J^8.íã;¿Uk‚90b¸M ÇÑ2[CXκ{±™¼-|õ×ø&ä¶Z!3w†6Ðþ€¦ùž�cgêu*Æ(l…"5ŒpÐ'XAŒc°í�wÏÍ,¥*ÍXxgiãÿDq³)nû¢üt3 ±ÞJ”¯|Õy�˜ÌºÜŽÝÉ|ݯ×ç¿™ãñnã�Ò ¡Ç ’”æ+¢[…¡Ò0DrE%/õ¡ý¨Å#DA�Y+öpk`ò¼Ùp¹Á!qx‡q�Uõ¨€½dD¹Ù2sy'´zŽ…}µÆ�KŽÉ±Ÿ66ŠO*ˆ‰½k�1/7áVºu“‰[†Nüü;ýk_¬ûÁÅ/%Ëý_"®Ö°EÞTÜ8ƒ³KÒ„‡Ÿ° ¯8Ævú ®ƒqöA½Ú[âݱ+»/}¿H7¡IÃÄXÃŒâkDê; 1nu­+ x<:°¢‚–q].!Zöœ#ûž´³yâõžçY÷ݽì.ÎPÃ_”—ÌGD°µjlG‚‡D$ªœ[…mi<–éa?ò}—§¾�ÇM~8:ü—^µVÓ ßdËo9TŸ‚ Ï· Á3•ãã1¯7b÷x7Ûx¡Ÿ’% ‚Ã"ôTxЇ—h×0Д6bízI¤Ë·BIõÓîâ¿V>“;eEÅ7eÐt‘Î/´¿)€ZC"¨�b®—Ìck–¥Ys°ü'ƒÌ6܈Y+Ž®ŠÍã Ü—æ1ÓR¯…gñÌÓ0'‰H«™™î%¢i*Æx…¸ÓcÞ,>ô]Ð[!ÛS *€‹\Qïoua Ú¿e-ãýn¶ÿNo壺_IM­vÚ ¹QsóH€tƒbKª/²"Ed(„™Mà)F´ Ñ”Þ[^ŽˆE®ì½€0‰§Ý@«&†^´]U•‚Ìb �½ û+ÿüà¾"ve_ª‰œ+´�߆ÎóD+Ëc-K¤ý¶�P¨n)ÇÌN`t‡G%e�€ÃP ù� ŸLšEj:�-k™dL†5B†�A‰„ü  K‚K)?°ë$æ+#û’½› I#?h{‰áäef”H›&͹è:FìCàÉüS§1}ÛLlg~7/‰‚¨’‚Ó°3Ô�òĘÀ_¤ž“¹¡ÉñlTwA»Q/8W·\þ¥__”n )l2Š.ˆ§â‡Ï'“æóyñWRÎ%¼=y*Ú‰ÿ P0ƒ;ò“ê¸ÿ,¸Q žÇÙË7Ñ�ŒjC ƒl`[¹†�;n\´hÉù¯É‘cdK˜èü|è^-:p–�¶©ƒŸÔÕ¼î¼_£þrÚÑ¡„mS?¢›Hµ•KÑ RÁå)œüMâÊŒ|rq¢I+^ÃæÂ!ÿ„…ùL¿ ÔÙ¤âI†C.€çzÒ&˜Ý¶�'æRÉæpë…m7áH¾¬]¦V•3~Êî«V!Mæ àžTX–n]ÈêÚ¢œ_÷I¼Ò…h[~µŸhuæ{ßíÛóɾ­"NÍb›‰SmÚ«yÖÏÜ�u¶ŸdŽ�Tý½ÖV~¿V–Êê¹ý×_a: 4ÇxÄÞ|¼€w\ÇÚ˜bç@ºÊ½»PÍEÍŠnl°2»É‚ƒÕÏZQŒB”ÅŒ‚£+Þím'ªË}W2´’™—äá™x+_Î]`ý>É|â=·n:·öÛ›bŽ ôL,ZªKFe¡Ü–hëpàÞ”Ü4iþìSm¼O‰ŽQýËöLqL½h  kM'SƧãBw÷G·x÷¿Ñ^pd`ä+ûÁ Âê9^q¢=?­­oiÃ;=/ñ¿0|>¯�ŒI[r ¯ý(`7S°‚haY ¥×vCú¿VÒÇÚÕ]‚ÿE:×ýýÄÚÙôß[èŸÅ ¶i±ö¸GÂYpöNàΛöîF„žªDâµHÍ)�…½« @› 9ˆ�¬ã“p&ù;GfðÜ 9}—SS+õ ž*²ˆR½�ÄÛùˆI Ïö'N>דØ~ûaðYfsëupÓéH—}±|9Û§X¨EêqH‰JÔÎ}0(Õ�Ú^Vž1—®ówÖXTª’‰PÃ}Ë· öøiOîãá:-º‹"¢‚ýE„ç¬Á˦ƒ=3øR÷ÊŒèY;ûf��žp;;¬í—Ý’–\±»{e„�bæÌ�HºÔ�gRAØÁ浞“¾g¬Ã·Qèë$ºŠß;?!*ºZÒlà¾ù(©¢*hÍ«¯˜Ã`¶x?å–~Úør)™‡§d&SÚ�`næ9B\'d“g[æéºÕbâ÷ý®Æd¸Ž¹w~תã m/þ¢@hK€ôõVPQ~ àU56>mù×]ËæØí‡ó[«ht¸’†ež?ØW« W/ÁF£‘šõÚßß*åû#!yÈœì„ói0j“íU¸ŽÂ«Ÿ*Rp -ÝèÅuòd_ªazjÿLÌD¶�„î´“±{ñ²k*X~2Àœ‹½s­…U<þ©¦\ Ôà逎O/»³ËûOâ?íô0çÕà·'O^þHÒíUhëƒìôâ¢má@þ+žÃ&ôœ$ö¼âZþzj…ìÔÒ¹¶R]e^ò+n}EÙ6O]„?\›¿lmEÙDÉ6õh!th;T"åÇèÙø³à†FÃ8„DZ 7¤ÇŒUéšd µÅXhéÒ35æ[ ül…g,4ÈÇù�öÂÄaɳç?oÁŒ×àÇL4Ñ%9»ÕEÕaÞÂ~ÞûމŽï<ø]Š; Dëu_!1^ñ§„®÷`sŒÐ“ÛÚ„1Mb©‰á¹NknÅGômyS¥�â³ÕÄÍâ‰ÍFdK|l`�Z*?ó¢HØ;†3üLà**N“¶Øüt¿CGgß=.ým€§ºÃ(MbG×¾F¾<­wËWg7¦;No‰Í_ÎÉ;7÷®nñ]×üŒæ‰†ÏVÙ¯tLp}ÄìöóR ß–ïûX¾Ä÷r]1�FR.9AF …ç,ʽĬ6ÿŒ_¸×"˜ßˆq%Xß´âŽtÍA Auç¦ÜW¿VË{BÌßzñuLŠ×ä�{nŒ5�Â8쨮`£f¦¦¥#©WÝ]¶óàr£§³Êçrñ§4 |Fü,ʨÏ¿Š‡ãiFð*š¨Aµ|šFÆ=ôšù!>½ ¿#=J,¿ ˜Èfh«†trãªØÀÖX>ð8xÝ”9ø7ÒQd¤üE…ôyÜŠl¦‡žÚÛÂàSKÃ.ct•/m;Ÿ´Éöa0Ž”CyÌá�hEÛ¶Ý??Þ½’tP«~fÒmªj_@(ë2±ãµKRð•ÆJHò޶ÌR­öÇnÊ·%¿½!ÿx寎¶½ßJ®“S¶ s‚»ªrð÷`ìj»¡õ}ÑFªÛCUÓ2ÏKDàÞž!àÎ×Oz9õo# üŒ1RÌz…éõû¢u՘ݫ¦)UM5Œ°W^sç#F³hj¶àýê15k§Ob#B0åø@×VýàÔ¾Ø Ob;üª¦Üh‡xÕàôW¾ÿu o]w·Ö1™ÚMl­:ä¿@¦Ð_p“r€Ù5è- ¤_Û¸ÝyGR» âð${ 'H˜wÛ%èã Ùà$²Ž)FæSE7Ýühs ÿ… v òÒ)}ý‚ëHCHѶÜËÅq§WÒ…ƒO÷WІ¨]¬œë¯B(+Á̘¡•””`ÒPñ§ÜìOÍóbW˜ÆÈ¬ÇMõO#›ãÌoÔ�\J¥‘Ôûå¥)ÏÔ†Ú2|_¼sñMßr�ËõÆ?Aüš“Ÿ�ÔÌ¿Ú ` ÷BW¸Ñ(¿Ÿùþ Ð VæÌ‰©Sí¡4L!rò5Øi/ôüD Õ¸QÍ,�á¤þ–&³¸£'Üh…ùV‰ƒ´äón>FKÏ�<)×ܳŽ|bÃèò}5hD&eЏŠøçã?–õ©=Γ¤5Œó9Åe®­$: G¾mã™p'ɘx¾÷Pá¹öÞF¶ÈîÂÆv“Ú.~yî£æ)üI´™¹j¢ÍLû&/1¾ð¸jüC`Gv�ðlßJrÿÜÀiMœîàòÁ_± näx?':¥º_[;á}Ðÿíõ€ÈN€%X [>úá,Á¢â£âü{tþj˜æRIðó�v.)W†ØáEý¾š�î²LGQ-Cw&:¶JºÀ�µBÝÕ{ÎÿE§_Â&Pk{!xâžKg¡5 ŸÄÆ�=²ž™†Ù»„Þ�_9,Iź7QնøõCì?¡‰–i™J‚¶—ÿÚÙ*á§‚+ErO×ÙP’¿°Z��2ÛÅ®ã{©§”¡%Xûè:ßáÄíVž‰Ž@7VacÁ¦`Ú. 1/ÆrBhò7÷f¯-÷¶ý]r3¥ú vô° ÂCu؉¯•x••{Zê¬ó]/âkÀl}Ul–&ëvòï¡+7«`‹ãÀ·ÙjD-ÀdÓýaLãt;iM˜Â1-xûÚ˜ë#l;1ɶ�Ì-eÿ›W¡/ƒ¹ ú‹†#¹º°q4û/ƒs«¨Ð0óüþÃ!�µ˜8 -ñÇèɸª•¤ƒð&½r Õ‰íÑ¿u ¤@C™ö%{»}˨¸#ðüì5¡ 4ÌÜ’=k& A7±±(E¶‘9 …!mí�E¡I»©~ µø¸ò_iüóyœˆMÏSs®j‘×=’ %Û/F<âF0£v =[æÒLâ#3meÃv¹ÆŠï|ÐVßNí!XqSO47§XBûÖç«ÐˆçéÅl«áûO'Î÷²~ãff³ÃˆH«‚]¾uït Õ‘W¥\³\f>foŽ#¼³øPîJ" a¨nMF³sÎpê «Þí}{Í:zÝVaüªbl߸%žm¾ßnä㊬Ws_w6óvH H”êì¢ºÓæµ• Þ §=dÈ?pxù,È ýxöÓÚ9i�ÂóÿELÿÖ¹¹ê]¼@ÃÈŸvΓmù*È8¿ðGƒ~µaB¬k.ÀOî½ì:(.¼É¢ŸUMQ†<`ã¢úQaÝìAã.á^Ã6ñ·šd÷ölâ¸8ã®x©¶‰ùŸöXþPÿmÔû¤ ±ó¿{tºÚAËÁ®o%Ñ"%QzóÈOšGõvoè]ô.ûcôXVµ»]òôÔWΔlG£–—bÁ¢B˜–>=z>:m¾ˆÞýÃLÀ¢¨ÑØHˆÆ9}ÑÌc‘ÃZ¢è|ØuÌMŽH׌Nwé'ú9S·/ÞOp ¾L:ÈÐòdøz^?pCXÆZâC—¬q‚‰ð‚f7“Z›OÏËa%Ù¾¼f±ã?Œ º¿¹ ýï¨Åãж—â/i ¨#ÄÔ(É*#Wd\þÀtè=Ï { ç¡4µŒÄ�/×C®g«HÁÇ+”F[W_¿ƒ¡s[˜+Ö=U>ØÿeåÏÁñ¾Oàü=AÒvpû¢µceG›*o²ž�ßÚ¬7'\ÐÀÁöð^ÑáÑ6Þc é¾mñ+<£í�Ö_Syí ´R$”rcYíѸ¡ýÂåpUZ“´º»D yÇ8Ývh,›oXßvIІ²“ Ø>JîÉm$OR×úWCqàÌ Å¿j/Ç^ì´ïv1ŠÍ˜ct@SK€tàDUÌx¿/g¬ØX¬FmÂÁÜIyT!?~©ïCiÞV HÔ˜:_zÛwwB¼Ç“S^ÿN—q“Õžv)‰tÃ.�ùeŠ>jÌîTOÉÅ´šƒHÒÈÕ˜D=Çj}Ø%3÷FBÒ4®óMÜ׼݌RÚ.(χp¶ •ø¥ø-|2í\iÇ3ªÁÔnB(ÝÇ�¿ Nõ*¨CÓ0ÈËãF!�°¿¬ë¥øfˆ'ƪš<xÏæõf#K·?ä•côæÁðû­yŠâYÑâ NظÍN µ Љàá¸aòf<£ñ î["$ éf‰ ááKóÐ_góUUe¨*º1®Rü 6Xtükõ¸|šñær4Þ„%ÇËùââ©øñ]µ…Ãúçó”�0brA>6ÓËuÉv0ÒÁcìb¿� é5…£ï c§:æ'ÄÙè‰4eôP‰±Ê¶.¯‹ ëÄÖ}a ö}3ø£rŽÇ;6ï-¢t—‡’iÛ ˆBýR¹+]šRê‹‘:—??—*|z¤tØ–%f¨MÌñ_ßJö=ãPŠŸ5N^SUP‘&Pû$½+ ¥©þ· gÓm ¥>…r«6˜¦|TtŒøîž×®s+ÛѲ@ªÞºêv– ³ r~Àú/ڳκ’LËÔ# =ÑÚ’ý¤�þªj¸l™68Díµ9)Õ%mPN�DòHf}�J K\›ñ9èi—)#$Kûs�Æ�6¾É¿ÖÅ�`ÊǤLR}Ã˃RA+ê�*#ËlÍ^›¾ö1$g¡Ç¡ö–r—¨»€ux”éZ‚þœb [HÔ¹d …äFýø3%xpº%?yþ³ã/Z.Š�åÄouày©FSeòa{£‹x_ÏETo£¡vw$2ßXãa�û�Ùë°j謱 2ÎDïKÃ)wÍ»U?5‡¶>ϾÒž¢�ÛH¶ƒ!”‹ö9†Ô¥©éÄ•Ms ôÂ1LÛ¹R t³•/kîËœè,˜ø3O¾ÊªÄ saÿÊR»¹íåU¢öU4ë»�x±;œ÷e‡Wç4B6Y6:¶ñÍh‹4£Usø§Å”¿rB d�ûtÚ@†a[V(’ÿl�±.ØÂ”0•­—„¹ X–¨’›+!åçR5·r `0Ò$2ß%c*ÕwÊúÎèÀG®–H J ââÍdäØ?œUÈÏ'ñ¥¿Ó9>z±§”p/f ÏÒOÈù¹$jeÚgÐ̹óˆ"¿Js\2¦ÕÈ™™Ò�@xÀÌhŠ$¿é¶éhýÓÛ?�Eª5Ý9¤ê^Î,“)ö[�z 4Ã`ä•xWuÑÃ(€ˆ>籆èÎ7×–ôaÝà@}§ft®s¥ËíôWþäÖ0«fJruBmÈrèn$­ê! <ÚÝ«Û\¦¼°ÐBon³ÓŠ¿?¼lQin½¼ª“R)�¬Ÿò?!ï†îweƒ‘bzh0M?üÁlD^4’l ëQO5Â^h›+Á„1Zª×dz„s±­T…§¼ï‡óîÛ™ž±�ßôYj„fÿAĮݑìó=�í�ÿêç,9~{ÔŽÛÀˆÓY»?†däªtn™ôh£ùŸ[,—^Ar\Á@3WôH¯ê½ãW4Œ`™4¶é|S[žDýþÙů­?½Rqït·uгÛéÎñ8€Îª›»)hÞ ïµNpBÎÖÈ«õAa gFÀ¦G©óYP÷g ¶/ß|K>°:¾õg0V$é¿ì—kkDùС= ÏàDY›÷ÿÅŠMS--ÜìO2ú�Â_êvÝ,‘ó¾…›lÜý¬z±#ñÿµ�ø§ÄÉU³Ë —Í|õʼnˆ˜-î£êò‹‘F¨˜¢ðXcÃ/ا4šAIó?o¢:Œô�(R-Ñ«r-IÐô#;L0»òþTp“¶§å…ªT¥E׎‰|p|yá�J%é…Ø'�2·ø�NìÀÍ¡pu¦ØSãýKKjMò¼á$ɧøZ™+[•Qöµ)å=BM.ð;‡“ð S?W†ÌÑU`¦€/).+2"BlO’2— u÷æ›»”wûæOÇ âð –9)ƒÓ`º(žÜ"Ân¦û¤ñ¯‡­Ø>dž7ÚýB0ŒD<±mÑ�­Dñ´TVí ŒàñE�Jíú�²ú÷€Ó ÎÁ!g¯: ­ \+––ôÿbµ» 8g�=c±AØÿýXËýO=/o·—²|­ò§R9)«Ö‰ßž¨}Φ:�Žèi±|®×S£6·N%?D¼)câ&sT: Vª*µ  oëÄýÜÖBm­ÛÌèìã{ž^ò«&f¢d±�´Z4‡>ž ¬ <t”ø6d¼m$h�'ì¶”×ºí ­ 웄2«�ˆuÃŽË0Ó‹ÖãБs£óÍSø~Øî*sÿ¹Ý`là^ÃþÒ l•–ÍÇ#‚Cm#ëÿy"âUX{Ô ¦cQÍ š–/ÊýŠŒKá-Ú†Òù�X5É»–7¼kÁ{¬ k‘h™ë.,2•»Fµmæ¨FN‚1¹nÖ ê'/";ò ‘„Ð?þ&B¸–摱œ…ðÆ‡°S›“¢b5È×R!pßé|7ÓŸ�$Äj¯Å–¸–�]ÿ+o<¦S οóP¶µ^FµðO \NK6âØÝ~6WÊ ¦foHúïgbä*Þá�ãÓ4GÕc6ôa%›­G*á1›Ô³ˆ¯{[�HJßN?q¯NâÏ’¶ðìhu[|Ù—`¸M ‡Èeï¢ì—t(;½ûgµ"Þ¢¿º‰0Ì•Œ÷¥Œ¢ïy‘RbŽ×h½û ,áõª”ÝÉê‰x’TÂm¬´÷UR8£ )þþŠB£Ã$êé×äÚ»©ÌU%ì�”‡fh|Ö€ 4 çªwÁ•H .(¾�£úׄ[󃃲C¼gvÜ$èÔ pa¬Ý0lff!?ƒMÈÉ#_{Çš»ÐÝҶpŒgŠ5„¬ù�;¹6Û+„z­šS7 ¹Õ—!Z?·›îýQœ�é‹×1üáUÔäîþüÛÅ™ˆ Òîú̂پk×7ŠÒ3äuØ`®–\Dá$÷%Ã"Š•æãßAs¾‹ÙzšI^ÇAs*1±ü*Hš[1nÝi)¿–‚·XºC9ò½ÈØò¤>l€;‘¥¬ÃÔ R�0´vÌ{«$#»jRòvQ lNëO�Ð5o�*^°§*¿E¿ð ÃL«�/ºtÅù~í¯ ³1kMÙ^gh³Ñ—�mZÛyVÚ©Çé4¸Á‚8¥Üu…;Jj¶$Rè>ò—Ä4PR]åÜŠÁÏšÉób¸Ñ+Ý:Çý])YÀ*”™ á¼7ùLÖÒí ¤n•—^GÃâ§Yh¯/kˆ}Dæ�Ä}6Œ[‰&±ÈÀ˜º½¡gr ªÑ:t°ë6&ÔèÁõ¨¢ä±ëS%\ äŽøg‹ÏžshاÅþöUþO ¾©Ï@êê6z*óE[øÌzra;h؈™`fÕMý8pæ(d»qªE èªËúñz‡ÞÝU®¾JI¶×VnñG™@Žý>Ù‘™´§”¥Bˆ?¢ï¨HQ'i…*’ªKG²O”«ݤÍÍ´†ÔÖ»ñ±Ï­tƒÒ$eI@àoÊ@Ø�dÑÍŽV2l&+‹IÄD»B3„7X5£Ó¸Û1ØZª—û GMÌ8°�ô›�;»W 396U�ä ³ÿÊ0Gµ<~5,1Nøâ-Pû@ö¤h¬#ôÓ�-·P©&"ìRȶ"¼îQòØÈ ;.�["”ÉUrÈ»A�¤%Â-ÔÏQéšÀpOB pmdñ!ͽ’mÿ¡N‹²ÎC™{ù‘KËŽtRJ(¨Q–\â`ôçcîIVp8ôèªÌ �ì³ë²'¿)µ´€·*¨¼ø�Ý”� «V�¢*šøSE"ÍÇ4D±È@%æ’ ö`U9•¼Ÿ)ͦ¡Ò à1Ùˆ:4ÂãLœ¸¾òñfLC¶­Bý®üÇÂdÆ„4$!-¼ í:�¤ zÓe7ʈ¿yÂN. —­^˜IêÂp Ø8yýCÖ$;÷ˆçÜS$¤:óžHj;�èÍÌýyðXdà÷-F) ûÆbθAž™¹ðÙÊ)xö¤ZÆ‹àz>o{KYì¢-Sò€”âSm¯]¬€‘ó3K¸ý„þ™òQpZîìæ"ŸäVœ#‚6é{Ôu:Ùö¬§<\¦™eXñ2ôÚ(anËðz¶Ù©šúM­)ÃT*3»äˆŠ[8Žá\�cè}`º5€©0©å%yr ï;ívZ‰�Œ2$úÂù? ˜ÉôpN6‰|?8‚óÚa@å®Ë0Ó0ÒÛyÔê°Û£ 6†"ûôl�£9”ƯTå_� h…=Á�¦ yFèì1©{ÒýÓâׂKðLõä�oŠàs(pð¸Ì@*’�nuÙ adAzÜ^;8þµ‚¬Çƒª«2‰öi(StEhúâµ€ø%W!Ƙ’<ÓgZu°Á ¸�+¥^b¾D˜!ìÿ�+€ç8mާ¾o¸6l_ŠTú�̤:«\4oOÐpùA=ãà{yݰۼ\¼Ól¿sæ+¬ã´$Ç4Dù!<;­0zˆ‚ßôa•�«”�‚ÀŸ±Ôƒœ ÁŽlïzäY!�˜ñ¬›>2Æ’uvƒä}¤ T˜¤d^f‰ºTgk>‹ÈæI=´á›M„VXS`v-Út‚ ¤/´©Ã’e^•V -ªçiùM2öÞTuˆÍêN Ã�Ž8ãµ(“©*7,…uDñQnˆ›ÒÈÉó!t9íšü»ÉùÔ•½¥fĦ¦*¢ë™öáòvkwE#A!'L ú§¯÷Sãáû�¼QÂG<;e<<µ§ÖÀ׿ð¼�°œÎÄ£PÎ̧=D1ö¡r:s1XνŸÐ1Ô É¡doC­^9‹×�.5Ó;&XnU´ä$Ìþ¸ÿŸw/�=MZc`¶5:~�”Q38Që̼¸–zýY W�ôº»cÈlÙ#�þ-5 Õ×§²3|´ÑGU¿êo÷ó‹Þ4åÂ@77HL>šCÉâ«Èè1[ÈÄ&¶wOèH¡ç„jöK¡¥È|Ô Þ‹$‹‡0SäêJYy§Ûµª#ófR—Ë¡Ù>åmŠ2<²øöRÑ&ÞýÏ+1d�=kéÝE%Ýú°^Ͳ:{Ö4+jž›5;ïT¿¥ÀK9LΨñíŸ%x.EÛcGç2 Ðcþã™i^[üó‹ÿ ­ØRª u DocF¦±^ÌmÌöðÀ8^͆x‹÷h?×=¢NßÄn,žòX “�–ó Š¿–ÈÏÑŒ‚H»è™¼K4ägì£/#׬ VÌ͇ü¶!¬!¡nÖðñ¤?‚õ$:á¸Õ®­4ŽM¬r’³;'Ž×AçG™­ð0w¾>¤÷êÔ’Òf¬|ßæ¾ Ƚ=t�¯)òjÙã< ëº|¦üÖœÁU,‹5s8:ÔÎNbg¡§Dž?ÌÂ873¦óϘÌch}Œ†.ñ´ù¼c›�…FA<^ïæúWä½ö”¸ZMÒ­7}ºÅß°Å~á´h1AÁf%q.wÚ¼r¼µ›ŸBÒ¿–å§©ÉæÅóT‹ÿ,Íè*ß·7bwèG<ø$ÒàÙš/¯õ8a(Ý?Ö£x‰ÞíûüMw ,íüò åG×&üŒQ‰þg7¬ –YeƒVYäÀ2kÌ·Êêlv¬¼êEt—Êô,>Š41˜S²È;“´tWÐZ*bý�4ߌ®ê§; h¬È|9ýŸÒš¤Úãó`Üø³8¢†Õâð0} GÙôÄ8ƒ~J,|Sk™êH¶q„j<Ú´œ|£¤®Î¡ˆb=¹6Ùy»âCÝÿÊÿòoDFߦ¹U3œ¶%L})ºSó¨ìÌUpÀ�+ŽD¹–x�õýš!)ÌöHÜLÿÔk„F˜_’,Žèu9*®iCrͦ‘–\yq|àeTŽ"ÎŽ¶p­ á.Ò•ßzŸ qíï¤Ñ@Š "Pœø¼ë"ÎWÓ/Ø�ãÉ?ë�JØ·… pÐO* åíAwl<9ëÍ>ðm<îw$¸hÛ¬F¯vk KNN¨¬Ðý(ÿ6iæºàg枊¯ié ko8Gç‰.<E2¸EõwËìdî¼Ýí/8½�Ýš!— ƒLJ^ý$ŠSj©Áì?^§¬v'$©>wža‚Üf ™S¥\ž3fŸKGF6ï¢ÇÔ4]Sã�gVÙ“åõ(�ævOÊ:q,Gî«•³åNÃ?÷�æÒ ó˘šsš60XþX 1Ñx,F¯\ÖÛœÏiüÎno~˜ÃS–Ê&˜MÅy0�»^™Ñÿjêç,Vˆ uñÝ•B›[¹ÆŠ´�¾d?Œ—o5�Êeâ•©ê¸Ù/íY­ð® 6½ºnO“±ôÚ#²�Úq›UÊúÄPê¿ñÌû¼€½�²‚¼(Ž•8 (Õ‰7�'³~¹ª” ÿÝj~¾Óö„ÈØ[˜L ÄÏúÂÓ<ÔÃ^½r=LËòzå¤uþµOÐFÓ ÞÎyp¼ˆ8ºšk_X·|g¨ïb€õ{ìdÓ2›/�{‘„ûðdœü¸í+ÑjO!’ÅäèþsEb¿ä†i�8?)<÷�ÀèúÌ~/µ¨ž"÷Ú ¬°;ê™ÇÌ9$¾½õà/ ÌÍyb@U\i_ÞbEòŠr�X~)Äf²Í–8ÁÎ9%ŠHlv ûê�Tëƒ2h ”M᚟~¡£¬’Bm.Ú-‚p®3,n#ÇxpÌRT²ˆ�LŸsÍæTœ$“ææËÌX?¬ü-P#U‘}ƒ“ Ñ ã NPDØÄʽYßlu—þ[^šCÒ˜mx¬ê!8Ùg­o@ì#ðò*)Ó\m¨5XúÀõ©™úÛñÖØ„4a¬¤2ßXÄçÒA]3tê 1s— %¸<§sÎÇñâ F�šO›Ù/Ú;BeßÂŒ°}×]ÑÒ•É?ìî¯i|g²;*lwoà$¯°ÌŽîóOù¨3Prb½ÜÓŠüÖÏe�M_J#qòûq¬žÙü‘ôâߎòq‡¼гò!‹=ð7ð?TÅYÏ¿ìèüÆ •šÜ}ù§”îôŠèª�u €�j¯‚…)ô%üýÕò2•Á&ÿ7¶@¾+»u±�âs&WCjgÆ#*uÏ%îh‹<8Å$Jý9WJ^“rÌ�ñÑ\~SÖáºõJ/›a`A›(7Z>ßóë(‹U5d›ªkaÿ%j;â'ÚéK�¸½¸¿´�\ý¡_¼>í®—Ûn¬ëÍ%¾ÊŽ -‘êµ}Ô3�Jª<�^g~g¼û‡ož¨ýÛµ+„‡g€å Õ¤â$ѤÇ'J¢Ò›Ÿ¦*}PÓÄá«][‹âÙ #=ßù¨4ÃåùáNb3>/܉ Ít4_sÈzkm ?S;±LŠ/>ŽÊÖ^h¢ÜŽ—Í-àDPŽEƒ €MòÄêTö�·HR‚mËQc/¹e�Á…«l|4“v<ºûRFcŸ‡Á‚ÜwÈU�«_`,ƒb–s¯‚”íá@� ¢ Cˬ‹5Xö�QåÙ"„âD•¬*ú— Ô˜nØtÆãäÌü Ú{ë$1èRù‡\‚-ôʘ• �#ta¡’éÜçw:!. n,3Ý¡¤Ÿ=§VXîâÌa•–‚Z¿ÏÇP3¿¡*»µPnQÖš$Vï#Ìú¼�•NÒÍÚrQ †êŒ>ÙÕç0j+¶Ç²Ä ÛO€¥Ðç-N¥IÝVzý³�³ïZÊÛòæ¨÷…�L¦3ù£X[hƒÞØû+f9@j·å™Ç¹µúÞì(ì ï¦¶éK¿&µ ßmkàtËÉÎM÷6ÍsTƒ_õ, ÿª'½‰�ÑÙŸ�+³Yˆ6çwÃZ»|©")—¹­È‡£_Ý÷,ÈdõZ¹‰ö½ÿ‡ôë [Š¡–u`ša) :«¶â¶�Å©¿¹Ë³ø—v²„Ÿ'è�ƒ6�ÔÁð{}*G/«ªöM-Áð§ãÊß}…‡ýðoöõ\‚4Ó€žû¶ žìF�3yžƒ&b ›Q5¨†ú­-ׇ-ŽšYâûù¶Ó±eùõ@‘.FLˆêƒW5¹†…É…ÛW‚Ì;ÚÿK È;kmÇæcÍã^�œÛªqiıÙq (—°­rkÛM®òÞ rï±qS+Ê�]žx›ãŒÆ9Vq[uÕùRx½öN”ذtà×�T¬Jÿ©]l‘û÷hö“ïå‘mí«#µ qCïØ=pÛ?õMá ¬ÄS¼P �'J"d>‰ô!:*Ä:u1|òÑ_DZP‘°þn¸ ˆ¤¦boBŒ'½â>ãn]%îŒg&9‹õÿ9Å%¼‚€!ñ5úâ ÖÁA½ +¬¡O'ƒg“,( �$RgB︛n�ro~?àþå¢ï·MýˆêøõÊÑân�ð>�û¶µuŸ½u3‡GüÃÏ”ªšù·D†A{n`ªÀÌ…`ø¥²óPm-”I5Aã³áèÔVüdå ÛžZ’=¡ãóÿUÎA’OØ®h\›päM3‡»1°yß¶ Ÿ@°õÒÝ©ÿ§”s ®ê¢t:éðƶ:¶m;7Nw’ŽmÛÆ�mtlÛ¶mÛöüÿÌ<ÌTÍÛœçó°ë;U»ÖÞkÕiacj_†Dù'‹h`ؾ؊‰¼µ¥‡ò–wõ¿<,“çFíâ�ôiMCåÅ´$ÑÖ>!@åþN6…šh#v�ÄùZåFt´‰«\z¯¨}ƒv9¦Š†…j˜òn‡c¡Ýk>6I:Áù%¶QKAÈê.©Á‚N[Ö¸ �s^¡¼ 4¼,Æ~*zÆž›9íGÚíÙÌÊ�éÅxn)%¿Ü‰ƒäÊ­òµè®ˆ,5‹¥VC« Í"öÔl#mbÿâ< ·wÊl ­�7>+™Õ*]kV `SMq NÅ{â¾g¶èLHBƒO[t“ø+¨Ù­_¡žwKÁ‘>«µÈ è™hXÓž±*?u*dˆn“͇lÂùIúiãAÂÏ™UãêêQ_�QèIAnmf†ï?›Ì•EšZÍÞ<ÎF³àÒá¼J„Æ�/Ä~¦M¸@P2aíÿk[r $ˆÚ�‰=â_¯�5~!bªj%+¥«¨Ù#[�ÅFU¼s9<Ñ‚~¦¦š¾ï|䟡ù8¸/¬Ùð&\PÎ ¿bÒÍ=�2Î*cv¶@î»HQ‚�hµ9z�”0fLgÍÃÓ»k3¹fPš»&B pE:q@’¸‡ûÃMÙý…×7ë3Yˆ°ÔpjÄà²ÄÙK „µßä�Œ™¹›2–2:Êî*î0M¶ü»ùéÞàÉÙjrѶùÀ¡°pz }?p¦¬¶åš&Àò¬þ?³Þ…Ç“\™·ñ)9´NvÝØÏ6ΘƼÕg8“SÂ^¨J~¹îÏ0U#Ø‚]A*¸«§O³>Uë»kJ4ÖŠ#�7ó’ÖÃ-‰kœ­õÉê÷îwÓ×Ó¤…\oPõpgrL�Se ØgnnÅÛW²{Û®¨ÔÿZd:d‘²Ò ¢ÉÂùù6œô»ëfš�a Ñb“âW¯½:_JDô[¦‘¬/Þ•Ë%`s[ñ1›ëæ][¬©Gôg.H‹)áÐ9xáD±dÞ575¹¦.¹"6¿ÂZ¾à]Kx扺÷EŠñ(äˆàÌM~ð8®×>{¢à`G %ò'‡&ð¦�C�'ã{}×ÂÈvëçÞwëuo ÈÍÒdöëd¢^\"Á‡uù¢ÄÉ· ýsa‡ŸszƒÑÜcAÙ‘qì­\-åÈ¡ÝI±³á>È\§¿ØqZÂŽÞ-i&%í<ÛÊÖ’í×ø�þ’^“úb̨¹+ÄœÐf‚|PŠÇn^Qxëq *™k[d ðÕ¢!+yVä…c§íù‹žsî6´£ L §ò»þô‚—?™xY°Ùn 7[Óæ‚óç°¶Ó¿2ny™†BI¦ ±;¬ö;ZûiéZÉ}%Z–s‰€æp;ef&Ü¡¶ìq­gu‰»Ø[ IÌ¢ÜÓëc?Øà 3Û:‰ëɵ£”X<.à7¢àjDËîíÅròâ+ˆdT¼?tu\gHp£<ˆ01Ä’™gÕÓ7a nã�³}]ÏŠ›î!ô6/îÃÐþEÑžpî_H{pÇ"ð•¨LöõÄN­Ž!škk‡[³ãî¨ ‹õßž7nüß»þ�ŒK> kÖÑ*ÝÏÖçÿÀwVG�Œ…­�Ú¶ùœv(ÖNó5ùÇf5Ûæ™ô¥’NJx·D“-s"ªÓ!J‰d¬Þf3é3¯JÙþúN«—2!Š‘ UÿBsëÀ�\ˆìy¬ûó-gkªuÈ‚âÑüXœa5�£��–ˆÛxx¹[¤(éñDº¡ÃÎסÕ×Gƒüñ”s7Ù1®D¬ŽÙÌ‘º¸‘ Ø‚[YðT¼†K3d6'.eÃV1 ó]8yå’9CjŽ'<¬ø@×L�ûÆlZ—愹Åâù"/Ï]ë–wræuaÍŽ+„ÀR©ScÎN¦ìtFVϽF¥x¶ªüs `)-‘ušU3—±½üïxñª‚*’†2+ÅC¬3^®y½%Aþþ^Èy¢@ËhhÒÐKbÏõžý}%ÓS Ck�̆äa‰2§Jï¨+ݽ5ùëiQ¡úq«¥3ÜC“ìBÓW´é© l�ú<ðàs}ØÄ†¤ 3äÆÍ;¬5ÝÁ '(åpÔw÷‚-²¥ÀNš0$¬ÌáðéqÓ3�'×PîøŠæ}m�°ï ·Ýã´úÖñz°ÇQüÛ~¼ÏÖsiD­I2|[Ðó7R¿úu�ÕµðÅzI½Jn Ë ì_~íö˜ËE9.G72bÿ¿±rO}¥<݇°»À†%¡½$ÁO‰¿�û¡paü~G.I#Œ ½‡gÈ-·Þ$‚íÛŸaÂÑ@^h4�¯K-Ñ•.V �IܼqTV²b�ù3ŽŒcí.JQ÷+i«mn1"ºÐÕ¸û"¤•�¯²‚ز¢ óJ±+YÔ7—äz¬ÔÍú �,À~' nß6܉ÿh~§Û*ð)'¦7.¥ÉòöAhÉ·Ùðà*¥[‹ÇÝn›3í‹û½wZ" ³Ó·¹«ºH`Y£=”I ~Û�2Äàè³ó6èèH^/ˆ*ª>Ô}k�'êû?Ú÷ñXs)Pï!J; 2iñ>M!ÜÜù¡´©‡Ó™ˆDk1%ÖÇ¿RÇh62ت3¦.Þ‡ ŸòMŸKTUo­béÒðþIØ(ð„‚ô’e&ÂF¯­%èœKù�Ò±—HNxŒÎè$4ݦÄä#è1 ¶™ÖFmˆƒ9‹…„Eq©�׉&àñk•ä׉-š!|}ÍBè¿`V£Õ4=nf’-¥$˜æ4ÃYwáë˜É^òo81¦¯}ü…æg_òT5�3“öúš³Ï*Ôe½•^qwq-„¬6ú @Ÿhh¥ÏdÖ�U“îìmyiuër�Õ“ô{‚°—ó¥~sׯì‚å¢uÏ©Ý0Þ ¾õ¾‡žF"©óEýÛ×sû‘x«‹o“Ñ|‚|Ý)ÉhÖšLÉä0½vb�Vb88¸-À Ñ-Üß�7�O!HñÁ?„ÔyÒ°?E¨ÿ¥È¯Z�%¿N_LY™p¶K‚˜ŽŸç7­Š:î§ú�Ü�¼§¸Z’—¡@Åðˆ½¤+ºå¦îm�XqA[S›7Ù4,ž„ÎY½àÁù‘Ò_øOuáXõ-}7_E'°EnVkÿÒè¤F2(šG>©åžŠï;—ó�Ö‡•LDD¶)¾$ëù¹rè�ñ>xzû6!¨‚[3¯è[x›eïö©É‘EH¦Ì š}¥ö=ÖGÒù~0/5Ʀ0-·T§{û¨Ñüô$ò`6oQªv£Ô²˶‡A~ôovÄY?.÷¶7[ˆXv»|öfóÑg¬";o–Íø†©þÌæbmŒ§1B1%qfŒ|—@†> lZî¼ìÁçU;P!^‹ˆ–@àÓ5øTä÷GÓÄžÁZw5ë�Õ¥tŠŽÌ}Ôšz“þÅÅ+DmÉœ "n  ’ÎDèæùQáê„çëI( •zb¨ûWbc‚ê†Ñ(èø3ãë×@É­AÏ%NÁjá<�¹ ¢Óðn¿™39ïÆæ—IÁ× /ͬË8“Z®K3çºY;¯æÁ3_ɨmÑògÄö– ´BsÌ #š�}M¨6dÀN’KvcG�6ÄP|Q�øVD¼$V ŸˆýZ<ËÙJ$€�ºs?Ó²‡L:DUû˜‰�ÑÎ9JÆ(*ˆ_ZE¦ù3òñF3¥:Ô>·LÓãç9Ò~-I�ñ+aŽÎ�›}<*&!ú¬1ÇÂn‚ÀϤì5¼.ê¦6÷�:2ÿXx²9ØÐe­#Ý®HÈׯ¨Ÿ93즌Ýyä[ì†X%Â�rºšL$òQúGœ#þò/~yF–-%ÝßA}t$„É;gáó%ŠÒÂRùXìˆØšá�†96ˆï»në½k 6wÔƒâV¾¬9⩼A#ç+-«PŠüÒ˜©¯¨ð°\‘ûÃgrø’Áùˆ¸ø½Ø¨N˜º6�~ �ö™¶ŒÁ☺CUš ZÚ“œÐ÷z�ÐQ«ªKƒˆÛ*Àh�ÿ®‡’á ñeä—7Š—Fõ\—Qÿ ÀX-½–ãEXÈóÊðzâÚ°F&Ã&fá‹Í™ÂrùÇ| «;=ï„™ÝpR‘ñ,=‡ëáÏF×`Ê•ü5äÃ�8¢É¬§:z{äUÕŽ­©�ñ¹K¥›}b}{]ºT/x$£ó@Nõ'´¸>* ´@(¥ý È8âO¡í|ÔUv›Š$Õ<­ÖÂqwf ¨�ß ¨u³Èåq îûó9ª.üDªXìÚ’çì4‰3‰Ìa¸›ƒ²Ð0§ô¯õsŸž-Àd¬Bz´ÓgDìYJïcsþy“Îl%îã²Ô¥© {=±áN ¹,°öFçáÛ„Á´éGnßÔÑ^ûßú¸aD¨Î« ¿Ûäoˆ! {Ì\�ºn;£Õ1*†8Ø-Œ˜.&h¢šz×”o s'¾ÀcªvõÏTüÅÕÉÕÀ4Ú-´MÐC±�)áŽ;[‚�f¯özÂq¹�p¹TóZºàȯ­È(Òð$=#/Ö‰Ð"%V÷#štØ1¿Ô$kÍ…ا…í„pã˜Å‚u¯çfspÄÆ*4ñ}s|ú�´ñE �™àáJ«[›Jt^,¸Ðô©Ÿ!xN[Ô 8d@‹OP  ¾sE¤àÀ6tÞäO´nZƒð]BÜ’5  )¹?Û_¿@©)eÒøQýŽÂG†b× íT¡F¼vì�¹�Ó¶Hüƒ2�8ekÃp?øDZØòEKdÇ”VþïŸ;G…•*}EvdJ�îÜ‘pRQ˜Ï#,D®z8«™dDßŒÌЋÒÝÞzCº¸u ÍÆº—qçÂW*ãù$û1[<ÊoKð@! pÆtRÎéþÖ«18žôéc�/"#—H8[®Œ@Ab¦�…¸m¿ aD:ýèQf±žMË+@yJ ¬9¼·7¨Ì+cÞ­�W–&k™»–ê¡ K¶ã.n—†Š¿=©¹J�rÌÿˆ7g†ÎÆÌ×"HEK–}v*œ&2yâ­«Ò›-dQþ¼,—s=0ïËr³°§��Nf ½–z·äœZ>¼¾žøì) ¦Œÿ`©_ž4“Þ€këwíàó…éÄFä[·ý†Ý¯j�j£QW g¤dX÷Œ]M”rê²K(^«h° $w~cù+É\ðÐQTP$0ȳ §10÷˜TœÑQ°(Ã:&5ÿzuâïwžÕ|~Tã@XÇ&�ÏŽ©œ¯i~òé�K¯›¸Á �‚¸p™!Û›õúÛöÝ6$‚2¿ µš8vv]sBìÞSV|³&~@K¯¯stìê"¥Œž+h³¬Ä‰“ÿî@¥häϦøî  "JÍçÌr9*Œ¨Dáj(KèKµµw íZ«ª ÿ…"üu¨–œÝ½�%r’%'6Ú5�$¯ùv¯Ý`½á®eÛB;'n÷³¼‰•i•‡Ì_®¶íÃøâs.înÈ�Œ=þ~ó‡ôkõŠ�6ï|©Ô5mïàC5z@gI&�¨·¼‹{&‘W¶4SY.oçD<|/I2uMâµ ¶hx+wv!¾j[ÒÉ⵫l"¾öºa¡ÕŽ‘†ÛI´àvו­u‡‚}©�`è”ۉ~,,®p6îW?XWDYKlà‹™¯kÂvdTZî_t[@ZÆ5J`Ãǘûn#dçD' [côgaYáÁE ïW7Ûž¶ï-ºtÆþã“AÌ U¾÷à­¯œýF‡÷ä¼­[c¹îð%©¿äGV þ¨EöÖ65¼ù}ø C7½´^¦5Œ2³‹Cº#¯2n”ÔÙiþÉÞÐÔB�+ºï¯Ü›ÝÖ~¶ÈKu5®;\Ôj©Ä¨øf“o@I€í–ß|̼7s „B&�–‡oÚzE›tcSENí®HÿˆYà)ßa€\§ÙÍàS�Ì ›†ú¹ñj)ñ$V(W«-0Ew‹ÏùXìÜ¡×i¯›æ[¯ Lîƒi5ªŸ°(‰Ï)¨…¬¸þ?HœIh{ÐÜ;w¡^/ÛB¥+?ÎŽ4'�CøI]r¯ 5õÒ´û~#qâÂÕ{=t=‰Ëztˆ¦NKâ÷†7GM}ï_¾wUzº—@§ôïn…Äó÷5è}4ñÛW§Ð¡Ð %8Ñ!oíEWï/6(˜Tè´aºÉÖés¹‘¾`�ºÈš_ú<™ílÿŒz,æböåR „uؾ2¬<89vÙ˜9Þ&Ž&xÛÍy,âå7²lèkû2ͩژ‚΢”lØlöÏ6òr¶õÐ(T9!çþõzþ"³ œV™ñn‚ZQüX»ŒÊ†÷ë•RˆÜ�…–ü·òGF™_ÏÏA[5ó-³ÞAŽí]�q%Z#¢e7ëÍöFäÖp<¸•Xú)Ìx�ÎEi‡î þÓ´®1u ºxw‹IØôò¡Ñä³ï6ìK¾¯`Ö*Tc-kuô‹ÍýÛ¾xî:¡Q+hób_„¨iû^�ûZÅ…¹È_û¦VaÕ ïyÒ]`™�2¦ £‡¶›Ïà£Ëàì:_¶Ÿ«P�¼°»9îñ†{šQ?„L‘‘í_Ñq# íì�ÉÏžðšÒ̱í•RnÏÖE> #x_¬²,d$ßãìN'�Ïv¥wj�‡Ë¡Y†äš\h&‹cmlfW%K+‚®»w°Q…[8€r•#ÚZa‹I‘±ï� TÔ�ŠÕF¤e»L_ª¿–Žx| ¤ —ãQˆK$'Õ]^.ÇÇÝ7Á½Ä»ej~T1É|Fܵ{ñq÷šޗ39ÞÂô¡Ê9ÀaJ fjŸúù“SÚON Žï¬øÃà0p* <Æjæ7Kf î\¼-miÔ å£)ô™ÊIt#vŽðñiJü¦“ÀGäíÂçÎYþûQ™½nEÎiØ yé*ìÙ±Gîü°A  œæîJ¬¯2©Æe/�é*ÍåFYÛ�%f‘.HQ:4u£*ÕzkôD´~õÈÄç©I8ú¨ˆN[Ý­wsP½xò¢jè1ŠÅŒZtÆ‚�]}·0�Ÿ�Ï�uþ Õè踰æAòŠg‘|„÷¯_�ŽHܾ é1eH6#‡/æ*‰j%?»'¹LY†Þå.”ý 95ÞL IuüÚ~b¯©Ô¯)"’fW»!v÷ªlU bvqÁSÎ=0ÀïO?‹Ú˜ ¤’z(Ü_ž€ÆŸ�À9'Ìÿô¬ôc–€á¥\ÚXÔռݬ͓+ðû·¥Š�ä1|Ó4>ªqÓ™´ÁTÂJÏ�a“üùÖ»‘”¯-ó*¾Ù Æ•É[ÀÚövíä£!0™·;YïžãN‹ž~ï…im#̘ :©cJ(Öi˜;¾ÔÃÁY†(¥S:øÀÃÀ7ü|B£s$(Ú]>iþöjýÄM@=圿qÝ×YY[ÃÕæèGÏ©éÈ:¯î¬ÿ¾ÚõEi.^TõÇ—ŒÐû‹:_¸o*I('làRPR¬-§::sjtá8…â�Q\¿îYù®Q¥éR¢¥÷e°µwÿvjZ·®±pòúµ)v俞"Y¯;�Ez½ r»¿ç ’׋À7� ³üMe”€)¹;Ð>ÔEo>"U9´ÕLìn@*¢sä6†½ $ñ‰£oë~N;«Y-q>y0­LÑ® â(/–jù�>>�¯Þå±'0‹g,¤ú§fIê(‚ÿ±ÈwÃi;ܸ¤üÑúJ6Dô‚¡øŽ÷º…^öʺütqù^{WÉÁ':å�±Ìb ~@d› [%m766XhAžæ!.$tÔöÇñí…‹€;�tøIc×Í�”È>'‰·œèÉkwIÓÙ{v­›TM@艨ˆ€F:�Î�Œ,„Kß/mh¨6DÜø„;…A…Âfˆ«ýÅÆ¢>é6ÍšnÇå /¾æ‰’̹`e¸è±–¨æ¹idmxQ.ªØ~,\9IYN<εÚòS›7¥šÝÛ6?,™…æ‰Pø0…ÇÁ†d¼™º„7q<ÄæùV„ V·5wƒ§¨Ÿ”ø�QTï(Ûp‚C§\^Ú¦÷pçkaºkìâ#WNˆƒ¬½ÿµy5ÞÇ!z)¤`ó¬ÇlŽ*sÔÄMh¸(éæé«çRIR×F<\7kó‘õÉ<�[~v•„©ßû¦¨ùÎT}JàåL‡4~°`ÒXÂK™ · }SÄo‡²Ay0²žFñâý¯ÖÅq&Cc»usLÿÊT3˜8?Wc²àŠIþë¹`:Ì[Ü;‰AüU×=v5’ í4DŒÆ.9Ež~;ª`–Ñ` ö§v¬ã ]¼OÉDÙu¬xΰf=¬0qç?iºŒJ�/ªÂÃÄ´íò„j;Ò�±�¿),”YwzƒÙB ûÀ•»l:ª\?(å(ר̗¿H`p�-H­B ö_¢svìhkrm)ÏxŸ•âúv¯-ùgŽõÒrÕ5�ß©Ë~÷Ï6E¦»‘LÙ•h1¹vÌ#C¶çSäÄüÐY¥wl±Õ‹Ë]bR-ìݱýõ4Hï|Æ…Ççàk`¢®o¿ì«ùÂÅð0”ÿL˜‹ éa Zxú¾¿ëÁÞY”ŒË…µäÉË>úP°RÀì§¹€WÌÓŠ¶Ó6‰µë‚ßi?��™ï"ÆzË;òêµÚda´›Ñù·÷(.'¶¨,ðmIZý=Ϊ¾×Ú{æ’]-9ÏWä.êíà%g"”ë o¤<"Óý{Sp¥‡÷ã— ²#þ,… ®°�² º<øVɧÝñÌí™ bò†ûÜè�éÒM®Â›ž“ÛÒܪõ4x°E�í­X.¼Ng¶Ð‚ðþÒÕá¶ÞWûT*ëćûj1‡~…~X8HÖtk‚r��~ý·¹¿í›¨_+Vu|/‰ˆN&1•~×½GV-ÜA€~f¯BâV§£ï”¡sCæÆ½±ÅA!dAªÜå‡09…!tx³z.”È�ÿ(.¯NXœjjû\×’— ' pŒã�Ò&ˆû…˜™’<’<²½¼J?euH<$h˜—¦›»æÀ¢:t„ þ ·»:f°lpK)‘Å—óf:¾%AUʲ'Èb‡Ä×ò€þ&+Ê›`)üÕ�n7lÑ­ˆ# œ³tµ†–Ø<gˆ)¯Oz†ha§\ÈO•I˜¹†Ù=�YÕU¬&,P}+J½‹Ÿ,=r„ï_@{=è 3:;;úÀ§ý¦ˆf¶%‚EeÙR܆s�È ;š¡4†«‹z°+=u¥ÉuãÞQ²+n¤è s7›I'!Ú‰ÊáCŠŽ¥š?(»&€Äpe×$ß[�¼Rêx�ÇwÚÖ¿5‰ÀQ¦,5pÐ9Òþ M6» &ÿeŒN5däz=¬Ïû):gfOLÁ‘Üâ¶ôÃ~þ?¯±zŸ‹ùrWÄ  w&H`7´ðZ4h=g[ÂÐy˜:ø¥£Ý®Iª%Òkt„@-eÙ»Â”Ï ¥eø´ækÞþÍ!ð7 ÷Ú§ðÐÜ“æÖw1È´Çk £:{Ñâbu†»7ÀXÌdR¸t6Åpå[|×’”1ƒ"2‘z™ò�…Õ��ó#çg6‘,×"¹µ|5ãcå‡ÕGKp§¨~Îx\K©Ý¾ê³=ùÜú«ý~°“Úã/Z|²_þJm²h|z´�Iç*~js?pN¦n c”X‹w7gœë&J¬ð¼üæ0¡3tI®Å¹ Õûimƒõf“'…ñ×1õušSÉ͙Ӱæ´òŽÁv_G½ÇÓÎì|æÓMÑ÷ÙÿõÒr’î½í’ΉsˆÆB¥�ýÁÔ¿§Ôš<ìRh°Îoe’žÚ?�×ëì 3°Õ`JÕÞ˜­HÈÑqU4UÄ®¶“À.ò”œ£Dë,âãÎf"0¥Ïð…†Ožüó[äâýÖÕÊã–÷!ƒ—P?o«æ1t'Æ›êÞjzzà [ãy3Pb¸Î¼^� ÝÍ Þ<¢\ñî»|ûïZŽ ¨Jçú'8‘†­{R,¡AÁK¤ºè·šØ‘ó—]£ˆ’ è‰fE4uœõ³;Aëvч= ÍéÙ׳÷ÃÜÔOÔÔ…éõÆš=:‰jª£a[NέØ!íúlAGËÁ‹8he…ÙVÉ18õÍ`òÝW‰U±¨°jTÖ3!óÉh'd·N±S2Að”ÔJ¥; ÔŒ¢,»¯sÖl¼2|𽃜ÐaEâÜÒ eä$�Ük·ÕoÙãrÑIúó†çÀB*AG¼p,0˜¾í}³vŠ{•Ynù*…XMªPök×½óW)sZºlć&"уÚÙú«ö8Æ#J÷™çˆ)g¹æh6§'[ÑVoÇè(E�±±;�^3†z±Þ•òb1‹Ù"øÌ'Á½¸××&{“0>^:çJ½Ž)&HL úö˜šº×ÚP}òŒ|KÇ�>üÄg±�Ê‚ÔÝ“'¦1°wXí0ÀšÎF\¸ßxWÙ0ðN"��uÈQèùþ×?i+ºð¿úLTÕP‘ÝÄ~�†Ò`Zí±c$$xCRÖÝï**ÕÍÑüSÍ£v�Д�TH¬[`\2+\àâÏÜš@Jçâ¦DM—†ÙBþ*ÁÅ©cg8!€Á5;ôŒ@\ À3­î9ô'1%�95€îÁRž¤V½ýöl6à︈1ƒ¯¯Zö£ÙcoY¡#c5®;aÓ� Øé«†þúÑLi%‰) N蟌[—z�0¨YÛþѧa�Ô) ÏÊ`:XÜ nê˜2דB…òð�UíÅ[ÙŒšó„çb25<䊎”e-ÎdK-ÑVDâ² óÐÎ5–øŽþÒÿNUv¤šŸ�+�Š(ã!W¥Ïª*_—dƒŠR…f<-ƒµß8×oð;Oƒèuç‚�ºk4}ý4rÿŽòmlä8ú::Jcî{<ÎIŽXzΟ8ªÜ¯ÀzådÅŒFIûw]B]à¥2“KäÙ7¸õ¹}²ŒœzJFªÜekä6© ÆU³Ç¦l×g^ûÝÐZíBï�“]‹¹X�!4ÿÅÖëé¯îÎðçÎ>øç·'¨¼×ã7ÕbZ¤†ÞÖÎ0¬hõËC&-Q÷×Ô×êXâU"+¦Á\¬ÀV’õçHÎzÝÑl¥:¦bß/)ÓýaAeP%,™$ˆ¤vö›ð‹ñõᬫŽÓ‚ü>²^N> `ÜœQÞtÛò÷Xì"zJ˜Ib‡ g1 ñ=x¯dTã]b ˜�ö‰Lè`Ê”€Ö––Y*~Êjáu˜®±­ú´!qÜ/$•A™É“�¤%‚qÎÄHʗέ©êÏ”ÓÞbåSŠÇ»3‰øC¥(c5Ž cáã=(å˜p³÷æ{vÃv)œQ:½±,�@4ӵƄ¬xþÃ5qRq©‹�5 ""ÐÊ‹Œ¥ßèÊìæÒbGU¼UƘßÿû=z�2ÊEhÇ®zñ`ÁfˆæmsT”WeëØn:ÿºŠÊ¡Å¶÷ÿÐàg¹6´“cÚ{(zãvøm1[h A->tnµJTߎ™*°ú¶ûÁ½ÓÛ—qö-Ã3žé¦Ã ˆ¸ÿ¼'’ωƒ»›ù�4,”R5@>µ¨óG3:Ù¹Eyq:"ú#@>Þ>ñu/ßæáþÝ-Ñj€E—$�m×ð&!d¨'Nç*°;¡nÉ=ú¿Æ‚ÿçîkÿ ÿÿãê‡ï<ˆD:=‰¥ì?GZ\A¬JD/àPKÑð\u†lmPKV= settings.xmlµY]sÚ:}¿¿"ãw!iš0 CJ/ �fnß„½€.²Ö#Éþ}W2dR0÷R@O$þØ]­vÏ9+ß}Y$âì ”æ(óJp2˜ËÉ}ð2l•n‚/õ¿îp<æÔbŒ²¤)i0†ÑgôºÔµüö}�)YC¦¹®I–€®™¨†)Èõkµ�Oל³üÊBp9»¦Æ¤µry>ŸŸÏ/ÏQMÊ···ewwýh„rÌ'ûºÊŸþè ßÙò`œ³j¥rUÎÿÎVA~HM5¨¯ó°^~ýnå ÿ)q‰ÍÍÙê² í> —µ7ó÷¬EïýþÎz>TÀ†˜ë;f™Ò.MP¿¹üT©~º+o›ÙßtƦÈvå8³¯<6Ó"»ÕË‹êõq¶ÿ>™}Q­\>Ìø`Šó>ÄTdМ29½á`„(€É nT‡ùhˆ¹†'Œa—õ1zo󥄥%.cX@¼�«â sïPo¨å~oÇ¡j£¨|ƒº-æêá;¹«ð.+×W‡[ÝÕ)Õ«ë›ËCÍj>pòFqV½t¶³ÜßÕ$¶�3Ý@c0)ŒûêsåöÀŒüDL†dj³Ü¦¨ŽÃ£[bfš(²Dnvõ©¬7g'këí¼´XdPÇ~Q90ú¶€€È@ÜRtá€Ð .~„—]·WˆUüÑãþ„š_È3DϬa÷˜bCFå…ýnf,+vȃø‡ƒˆõs–Œ@ùYM‡TÞK3SÄ’ëŠ?"Q_“Ô,{Ì¿O$*hq¥ -ÚTæÒ´¥Ït‘VQ„  š˜¤ ´•©'Q—¸-@ÀwíLÜËÈw¼¥ˆ Iýí«Qz,e Àd›Ü{ /„,N»ã1á‘�d¹uX9⩌W2¸§Ð;PA=ÂrÓ Óp}Õà’©ePÞ3d¶â]ÚBµ©INÕa&Ì æ5ê#|ÊM‰2QxÉ™'þ)*÷?ÜÅßhu(ã†`r¦)éêšLD™p,ì«àC)Ñ8»‰á@|ë ‹ûÀb”b«ÐOƒVk¬À]4AøØmòõuAÛ-™èЊ¼Èš0MÅòEƒz`†�Þ|Ëj Ÿ 7`oð#?Ñéʦ@íƒl¬“oGL<¬£¬²ñAmýHûjÎd/“‘É|µa(øDRñ ¦=Ôü¿Ü¾;MÁÓP¿ëšPFÔÛ¿*zTµÄÒ‘«�<63¥h›lQ[`´¿ÌT´…5ùùÇxI¹ QçJ�°ÒâÀD±tªÛ²Ãõæ|~Še<à3š&KM¦àA±ywô¯îJ+<8sPÖÇù#€-µâ®çíétÿMp6Zlq”¢gÍiмÒþu%¥•zÀ‡ÖÐñjåO@!F¾T�;"ò5 éÁ;øùI”•|àˆ¿ñºà¤ 4C¢ðôI{_ÒºÎR?krÑšOìÒBc”r4§¶ÐËVå“—B�’N÷eÿ›ÅU/Í �sçƒÆß&“¼÷;ýÐ<Ÿ0ÌòÇœ:»�ÿžiÃÇKÛ6ú•›é“ læ‡"tìlðCÌ™Ðcç.S�­å‰Ç7Pv-öc£ÕvîxLJ’)ÁlI�F‘Ù˜Ž¡ŸGI«ã‘ 4X4›(ÌäÎÓÄSWùqänUŽ;öõÃ’4èF3 Œ^Ø^.¨n#ø ip;xfÛy’^ÞúX]Þõ¿þ PKNy‹8 PKV=META-INF/manifest.xmlµ•Ánà @ïýŠˆ{ÂÖÓ5�´Iû‚î\â¤H6Uó÷#•Úf[5­[¹AïÙ†˜Õóa0ÅigñX=ˆ­r­¶}#Þ7oå“x^/VXÝ!q}iŸ¥ó´1ØÚiª- H5«Úy´­Sq@ËõçõõdZ/Š ¸ÓË´0ŒÅE†­†’G��ï�VÀ)N¹·mutUsEÅx`qÙ=Ëj9ûÜEcJ¼k„ò¦®S^�ítÃ16ZJbàH[yð LS¤Š!L™§âfwetÆc&¸w>út3b&|p}@ÊwÒSèÙàìœÉ×ôHòEóž²:ndm#íô÷TQWj.ø] ÿ�oµ…0^×]äR�Úá�Š©Ê©\§ùoýâg.ñh�îŽ�án½m³‹ÃÖ‚6$ù4¬¼íï ¿oa‘9=ÅçҮ䷗xýPKybUÄPKV=^Æ2 ''mimetypePKV=MConfigurations2/statusbar/PKV='…Configurations2/accelerator/current.xmlPKV=ÜConfigurations2/floater/PKV=Configurations2/popupmenu/PKV=JConfigurations2/progressbar/PKV=„Configurations2/menubar/PKV=ºConfigurations2/toolbar/PKV=ðConfigurations2/images/Bitmaps/PKV=M´A¡l -layout-cachePKV=�ð9·Kàã Ócontent.xmlPKV=3×¾E{2 ÃNstyles.xmlPKV=ii[]++vWmeta.xmlPKV=Ñð\u†lmÇ[Thumbnails/thumbnail.pngPKV=Ny‹8 “Èsettings.xmlPKV=ybUÄÛÍMETA-INF/manifest.xmlPK(sÏheldercorreia-speedcrunch-e7ca37f/doc/legacy/speedcrunch.docbook000066400000000000000000000651031526573132500252200ustar00rootroot00000000000000 Speedcrunch"> ]> The SpeedCrunch Handbook Ariya Hidayat JonathanJesse WolfLammen 2007 Ariya Hidayat &FDLNotice; 2009-03-06 0.11 SpeedCrunch is a multiplatform desktop calculator for power users SpeedCrunch calculator Introduction This document describes &app; version 0.11, a multiplatform desktop calculator for power users. Have fun with &app;! Installation Installation for &Microsoft; &Windows; To install &app; on &Microsoft; &Windows;, download the installer from the &app; website. Once the installer is downloaded, launch the application to install &app;. By default &app; is found in the Start Menu, under All Programs, &app; and is stored in C:\Program Files\Speedcrunch. Installation for &Mac; OS X To install &app; on &Mac; OS X (10.3 (Panther), 10.4 (Tiger), and 10.5 (Leopard)), download the installer from the &app; Website. Once the file is downloaded, click on the binary file, and then follow the step-by-step instructions. Installation for &Linux; To install &app; on &Linux; please follow the directions specific to the distribution you use. If your distribution is not listed, then either find the appliacation in the package manager which your distribution uses or use the instructions to compile your own version. Installation for OpenSUSE Trivial, isn't it? Installation for &kubuntu; SpeedCrunch is part of default &kubuntu; installation since &kubuntu; 5.10. It is located in the K Menu, Utilities, Calculator (SpeedCrunch). If it is not available yet, SpeedCrunch can be installed using the following terminal command: apt-get install speedcrunch Installation for &ubuntu; &app; is installed by default as a part of &kubuntu;, however in &ubuntu;, it is as simple as sudo apt-get install speedcrunch. apt-get install speedcrunch Installation for Fedora Core &app; is part of Fedora Extras and is provided by the package speedcrunch. This package can be installed either with the graphical software management program Pirut, or with the terminal command: yum install speedcrunch To update SpeedCrunch to the latest version, use the terminal command: yum update speedcrunch Installation for Debian Installation on Debian is as simple as: apt-get install speedcrunch Compilation from source code To compile SpeedCrunch from source code, the following tools are required: CMake version 2.4.4 or newer (http://www.cmake.org/) Nokia's &Qt; framework version 4.4 or newer (http://www.qtsoftware.com/) C++ compiler It is necessary to create a build folder which specifies the target location for the buid process. In this build folder, CMake should be invoked. The input for CMake will be the src folder in the source tree. The exact steps to do all these will depend on the operating system. As an example, to compile and build SpeedCrunch on &Linux; using GCC, use the following commands: tar zxvf speedcrunch-0.11.tar.gz cd speedcrunch-0.11 mkdir build cd build cmake ../src make Using Functions Alphabetical listing of functions abs (x) Returns |x|, turning negative numbers into positive ones, and leaving positive ones unchanged. acos (x) Returns the arc cos (x), the inverse function to cos y The return value is dependent on the degree setting; if "degrees" is enabled, the return value is from the range 0 <= result <= 180, else from 0 <= result <= π. and (x1; x2; ...) Performs a bitwise logical AND on the submitted parameter(s) (one or more). All parameters have to be integers from the range -2^255 to +2^256-1 (signed or unsigned 256 bit integers). The result is from -2^255 to +2^255-1 (signed integer). Note that and(x) is not the identity, because the unsigned +2^255 is mapped to the signed -2^255, for example. An error is returned, if the parameters are not from the valid range. arcosh (x) Computes the area hyperbolic cosine of x, the inverse fuction to cosh y. arcosh (x) is the positive solution to cosh(y)=x. Except for 1, there exists a second solution to this equation: -arcosh (x). The parameter x has to be >=1. arsinh(x) Computes the area hyperbolic sine of x, the inverse function to sinh y. arsinh (x) is the only solution to sinh(y)=x. artanh (x) Computes the area hyperbolic tangens of x, the inverse function to tanh y. artanh (x) is the only solution to tanh (y) = x. The parameter x has to fulfil -1 < x < 1. asin (x) Returns the arc sin (x). The inverse function to sin. The return value is dependent on the degree setting; if "degrees" is enabled, the return value is from the range -90 <= result <= 90, else from -pie/2 <= result <= pie2. atan (x) Returns the arc tan (x), the inverse function to tan y. The return value is dependent on the degree setting; if "degrees" is enaled, the return value is from the range -90 < result < 90, else from -pie/2 < result < pie/2. The arc tan(x) is the principal solution to the equation tan (y) = x. Other solutions are (radians): arc tran (x) + n*pie for all integers n; or (degrees): arc tan (x) + n*180 for all integers n. average (x1; x2; ...) Computes the average, or mean value of the sumitted parameter(s) (one or more). bin (n) Displays n in binary format, without globally changing the output format. A fractional part of n is cut off efore conversion, and the remaining integral part has to be from the range -2^255 to +2^256-1. binomcdf (max; trails; p) Trials is a non-negative integer, max a positive integer, and 0 <= p <= 1. This function determines the probability, that in a series of 'trials' independent probabilistic tests, each resulting in an event with probaility p, at most 'max' events occur. binommean (trials; p) Trials is a non-negative integer, 0 <= p <= 1. If you have 'trials' independent tests each of them resulting in a given event with a probability p, this number tells you how many events you will have on average. binompmf (hits; trials; p) Trials is a non-negative integer, max a positive integer, and 0 <= p <= 1. This function determines the probability, that in a series of 'trials' independent probabilistic tests, each resulting in an event with probability p, exactly 'hits' events occur. binomvar (trials; p) Trials is a non-negative integer, 0 <= p <= 1. The variance of the binominal distribution function, based on 'trials' independent tests, each resulting in an event with probability p. In other words, it tells how 'good' the result of binommean is. cbrt(x) Computes the third (cubic) root x. This function operates on negative numbers as well. The inverse function is y^3. ceil (x) Finds the smalles integer greater then or equal to x, the ceiling of x. cos (x) Evaluates the cosine of x. The result is dependent on the degree setting. If "degrees" is active, the paramter x is assumed to be an arc from a 360 degree circle, otherwise a full circle is represented by 2*pie. The inverse function is acos(y). Although the cosine is mathematically defined for all x, for x beyond approximately 1e77, the periodicity of the cosine is not recognized any more, so &app; issues an error then. cosh (x) Finds the hyperbolic cosine of x. This function overflows for |x| > 1236190959.52. The inverse function is arcosh. cot (x) Evaluates the cotangent of x. The result is dependent on the degree setting. If "degrees" is active, the parameter x is assumed to be an arc from a 360 degree circle, otherwise a full circle is repsented by 2*pie. Although the cotangent is mathematically defined for all x, for x beyond approximately 1e77, the periodicity of the cotangent is not recognized any more so &app; issues an error. csc (x) Evaulates the cosecant of x. The result is dependent on the degree setting. If "degrees" is active, the paramter x is assumed to be an arc from a 360 degree circle, otherwise a full circle is represented by 2*pie. Although the cosecant is mathematically defined for all x, for x beyond approximately 1e77, the periodicity of the cosecant is not reconginized any more, so &app; issues an error. dec (x) Displays x in decimal format, without globally changing the output format. This function is useful when you changed the output format to a binary format. degrees (x) Converts an angle measured in radian to degrees. This function is especially useful, if you want to override the current angle mode for just one expression. erf (x) Determines the normalized error function of x, the cumulative distribution function to the normal distribution (bell cure, Gaussian distribution). erfc (x) Determines the normalized complementary error function of x, related to the cumulative probability function of the normal distribution (bell curve, Gaussian distribution). Erfx(x) + erf(x) is always 1. exp (x) Evalutes the natural exponential function to the base e == 2.7182 floor (x) Finds the greatest integer less or equal to x, the floor of x. frac (x) Cuts off the integral part of a real number gamma (x) An extension of factorials, the same as (x-1)! gcd (n1; n2; ...) Returns the greatest common divisor of the integers n1, n2 ... (2 or more). You can use this function to reduce a rational number. If a rational number is given as p/q, its reduced form is (p/gcd(p;q))/(q/gcd(p;q)). Related to the gcd function is the lcm function (least common multplier). You can find the lcm of two values by: lcm(n1;n2) = n1*n2/gcd(n1;n2). geomean (x1; x2; ...) Finds the geometric mean of the positive numbers x1, x2, ... (one or more parameters). Non-positive parameters are not allowed. hex (n) Displays n in hexagesimal format, without globally changing the output format. A fractional part of of n is cut of before converstion hypercdf (max; total; hits; trials) All parameters are integers, 0 <= max <= hits <= trials <= trials <= total, and 0 < total. Assume there are 'hits' events in a series of 'total' tests. Then this function evaluates the probability, that you will find up to max events of them in a subseries of 'trials' tests. hypermean (total; hits; trials) All parameters are integers, 0 <= hits <= total, 0 <= trials <= total, and 0 < total. Assume there are ' hits' events in a series of 'total' tests. Then this function evalutes the expected count of events in a subseries of 'trials' tests. hyperpmf (count; total; hits; trials) All parameters are integers, 0 <= max <= hits <= total, 0 <= trials <= total, and 0 < total. hypermean (total; hits; trials) All paramters are integers, 0 <= max <= hits <= total, 0 <= trials <= total, and 0 < total. Assume there are 'h its' events in a series of 'total tests. Then this function evalutates the variance of the count of events in a subseries of 'trials' tests. Or, in other words, it tells, how 'good' the result of hypermean is matched on the average, if you repeat your subseries of trials very often. idiv (dividend; divisor) Evaluates the integer part of divdend/divisor. The result is always exact. Since &app; can hold integers up to 78 digits, this function overflows even if the ordinary division operator would yeild an approximate (but huge) quotient. It is possible to apply the idiv function to non-integers as well, but be aware that rounding errors might be lead to off-by-one erros. If idiv detects, that a result depends on the validity of the guard digits, it returns a NaN as a warning. int (x) Returns the signed integer part of x. lg (x) Returns the base 2 logarathim of of x, where x has to be positive. The inverse function is exp (y). lngamma (x) Evaluates ln(factorial(x-1)). Returns a result even when the ! operator overflows. log (x) Returns the base 10 logarathm of x where x has to be positive. mask (n; bits) Returns the lower 'bits' bits of the integer n. The result is always unsigned. N has to be from -2^255 to +2^256-1 (signed or unsigned 256 bit integers), bits is an integer ranging from 1 to 255 inclusive. One application of this function is to find the two complement representation of a value. So hex (mask (-1; 16)) returns 0xFFFF, the 16-bit two's complement bit pattern of -1. max (x1; x2; ...) Takes one or more parameter(s), which returns the maximum value of the submitted parametrs. Example max(17; log 1000; exp(3)). min(x1; x2; ...) Takes one or more paramater(s) and returns the maximum value of the submitted parameters. Example: min(-0.4; log 0.1; exp(-3)). mod (value; modulo) Evaluates the value mod modulo, which is the remainder after finding the integer quootient value / modulo. This function always returns an exact result, if the paramters are exact. 'Modulo' has to be non-zero and if the remainder is non-zero, it takes the sign of value. You can use this function with non-integers as well, but rounding errors might lead to off-by-one errros. This function can potentially be very time consuming, so mod is restricted to at most 250 division loops. nCr (x1; x2) For integer paramaters this function is equal to the number of combinations (order is of no importance) of x2 elements from an x1-sized of elements or to the binominal coefficient x1 over x2. For arbitrary real valued x1, x2 the result is 1/(x1+1)*B(x2+1,x1-x2+1)), where B(a,b) is the complete Beta function. not (n) Evaluates the bitwise (one-) complement of n. The result is a signed 256-bit integer. n has to be an integer from the range -2^255 to +2^256-1 (signed or unsigned 256 bit integers). nPr (x1; x2) For integer paramaters this function is equal to the number of permutations (order is of importance) of x2 elements from an x1-sized of elements. For real-valued paramaters this function is equal to gamma(x1+1)/gamma(x2). oct (n) Displays n in octal format, without globally changing the output format. A fractional part of n is cut off before conversion, and the reamining integral part has to be from the range -2^255 to +2^256 -1. or (x1; x2; ...) Performs a bitwise logical OR on the submitted parameter(s) (one or more). All parameters have to be integers from the range -2^255 to +2^255 -1 (signed integer). Note that or(x) is not the identity, because the unsigned +2^255 is mapped to the signed -2^255, for example. poicdf (events; avgevents) 'events' is a non-negative integer, 'avgevents' a positive real number. If you have on the average 'avgevents' independent events in an interval, this function returns the probability, that you will see up to 'events' events when you test an interval. poimean (avgevents) avgevents >=0. Returns the average number of events in an interval, when this average is 'avgevents'. pipmf (events; avgevnts) 'events' is a non-negative integer, 'avgevents' a positive real number. If you have on the average 'avgevents' independent events in an interval, this function returns the probability, that you will see exactly 'events' events when you test an interval. poivar (avgevents) avgevents >= 0. The Poisson distribution assumes, that the variance equals the expected value 'avgevnts'. radians (x) Converts an angle measured in degrees to radians. This function is especially useful, if you want to ovrride the current angle mode for just one expression. round (x; digits) Rounds x to 'digits' decimial places after the decimal point where 'digits' has to be an integer. sec (x) Evaluates the secant of x. The result is dependent on the degree setting. If "degrees" is active, the parameter x is assumed to be from a 360 degree circle. Although the secant is mathematically defined for all x, for x beyond approximately 1e77, the periodicity of the secant is not recognized any more, so &app; issues an error. shl (n, bits) Shifts the bit pattern of n 'bits' to the left, if 'bits' >=0, otherwise shifts n arithmetically by -'bits' to the right. 255 <= bits <= 255, and n has to be an integer from the range -2^255 to +2^256-1 (signed or unsigned 256 bit integers). The result is from -2^255 to +255-1 (signed integer). On a shift left, zero bits are fed in to the right, and shifted out bits are dropped on the left. On a shift right, bit 255 (the leftmost bit) is copied and shifted in from the left, and shifted out bits on the right are dropped. shr (n, bits) Shifts the bit pattern of n 'bits' to the right, if 'bits' >=0, otherwise shifts n arthmetically by -'bits' to the left. On a shift left, zero bits are fed in to the right, and shifted out bits are dropped on the left. On a shift right, bit 255 (the leftmost bit) is copied and shifted in from the left, and shifted out bits on the right are dropped. sign (x) Returns the sign of x, -1 if negative, 1 if positive, and 0 for 0. sin (x) Evaluates the sine of x, which is dependent on the degree setting. If "degress" is active, the parameter x is assumed to be an arc from a 360 degree circle. The inverse function is asin(y). Although the sine is mathematically defined for all x, for x beyond approximately 1e77, the periodicity of the sine is not recognized any more, so &app; issues an error. sinh (x) Finds the hyperbolic sine of x, with the inverse function being arsinh. sqrt (x) Computes the square root of x, which is not defined for x < 0. tan (x) Evaultes the tangent of x. The result is dependent on the degree setting. If "degress" is active, the paramater x is assumed to be an arc from a 360 degree circle. The inverse function is atan(y). Although the tangent is mathematically defined for all x, for x beyond approximately 1e77, the periodicity of the tangent is not recognized any more, so &app; issues an error. tanh (x) Finds the hyperbolic sine of x, where the inverse function is artanh. trunc (x; digits) truncates x after 'digits' decimal places behind the decimal point where 'digits' has to be an integer. unmask (n; bits) Takes the lower 'bits bits of n and sign-extends them to full 256 bit, meaning bit number 'bits'-1 is copied to all upper bits. n has to be an integer from the range -2^255 to +2^256-1 (signed or unsigned 256 bit integers), and 'bits' is an integer with 1 <= bits <= 255. This function can revert the effect of a mask function in many cases. If you are given a negative integer in two's complement notation, it is not possible to enter it directly as a constant, because binary, hex or octal encoded constants are always recognized as unsigned in &app;. xor (x1; x2; ...) Performs a bitwise logical XOR on the submitted parameter(s) (one or more). All paramters have to be integers from the range -2^255 to +2^255-1 (signed integer). Note that xor(x) is not the identity, because the unsigned +2^255 is mapped to the signed -2^255, for example. Questions and Answers What is ans? Ans is a special variable which holds the last calculation result. Credits and License Program Copyright © 2004-2008 Ariya Hidayat Program Copyright © 2005-2006 Johan Thelin Program Copyright © 2007-2008 Helder Correia Program Copyright © 2007-2008 Wolf Lammen Documentation Copyright © 2007 Ariya Hidayat. Documentation Copyright © 2008 Wolf Lammen. &underFDL; &underGPL; heldercorreia-speedcrunch-e7ca37f/doc/rebuild-manual.sh000077500000000000000000000037641526573132500233540ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DOC_SRC_DIR="$ROOT_DIR/doc/src" VENV_BIN="$ROOT_DIR/doc/.venv/bin" CLEAN_SCRIPT="$ROOT_DIR/doc/clean-doc-builds.sh" if [[ ! -d "$DOC_SRC_DIR" ]]; then echo "error: doc source directory not found: $DOC_SRC_DIR" >&2 exit 1 fi if [[ ! -x "$CLEAN_SCRIPT" ]]; then echo "error: clean script not found or not executable: $CLEAN_SCRIPT" >&2 exit 1 fi if [[ ! -x "$VENV_BIN/python" ]]; then echo "error: python venv not found at $VENV_BIN" >&2 echo "Create it first, e.g.: python3 -m venv $ROOT_DIR/doc/.venv" >&2 exit 1 fi export PATH="$VENV_BIN:$PATH" if ! command -v qhelpgenerator >/dev/null 2>&1; then for qt_tool in qtpaths6 qtpaths qmake6 qmake; do if ! command -v "$qt_tool" >/dev/null 2>&1; then continue fi case "$qt_tool" in qtpaths*) query_option=--query ;; qmake*) query_option=-query ;; esac for qt_location in QT_INSTALL_LIBEXECS QT_INSTALL_BINS; do if candidate="$("$qt_tool" "$query_option" "$qt_location" 2>/dev/null)" && [[ -x "$candidate/qhelpgenerator" ]]; then export PATH="$candidate:$PATH" break 2 fi done done fi if ! command -v qhelpgenerator >/dev/null 2>&1; then for candidate in \ /opt/homebrew/opt/qttools/share/qt/libexec \ /opt/homebrew/opt/qt/libexec \ /usr/local/opt/qttools/share/qt/libexec \ /usr/local/opt/qt/libexec \ /usr/lib/qt6/libexec \ /usr/lib/qt6/bin \ /usr/lib/qt/libexec \ /usr/lib/qt/bin do if [[ -x "$candidate/qhelpgenerator" ]]; then export PATH="$candidate:$PATH" break fi done fi if ! command -v qhelpgenerator >/dev/null 2>&1; then echo "error: qhelpgenerator not found in PATH" >&2 echo "Install Qt tools or add Qt's bin or libexec directory to PATH." >&2 exit 1 fi "$CLEAN_SCRIPT" cd "$DOC_SRC_DIR" make build-bundled make update-prebuilt-manual echo "manual rebuilt and copied to: $ROOT_DIR/doc/build_html_embedded" heldercorreia-speedcrunch-e7ca37f/doc/rebuild-website.sh000077500000000000000000000014111526573132500235240ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DOC_SRC_DIR="$ROOT_DIR/doc/src" VENV_BIN="$ROOT_DIR/doc/.venv/bin" CLEAN_SCRIPT="$ROOT_DIR/doc/clean-doc-builds.sh" if [[ ! -d "$DOC_SRC_DIR" ]]; then echo "error: doc source directory not found: $DOC_SRC_DIR" >&2 exit 1 fi if [[ -x "$CLEAN_SCRIPT" ]]; then "$CLEAN_SCRIPT" else echo "error: clean script not found or not executable: $CLEAN_SCRIPT" >&2 exit 1 fi if [[ ! -x "$VENV_BIN/python" ]]; then echo "error: python venv not found at $VENV_BIN" >&2 echo "Create it first, e.g.: python3 -m venv $ROOT_DIR/doc/.venv" >&2 exit 1 fi export PATH="$VENV_BIN:$PATH" cd "$DOC_SRC_DIR" make build-html echo "website rebuilt in: $ROOT_DIR/doc/src/_build-html" heldercorreia-speedcrunch-e7ca37f/doc/src/000077500000000000000000000000001526573132500206715ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/.gitignore000066400000000000000000000000651526573132500226620ustar00rootroot00000000000000/_build* locale/pot/.doctrees *.pyc __pycache__ *.mo heldercorreia-speedcrunch-e7ca37f/doc/src/.tx/000077500000000000000000000000001526573132500214025ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/.tx/config000066400000000000000000000017321526573132500225750ustar00rootroot00000000000000[main] host = https://www.transifex.com type = PO [test-439.advanced] file_filter = locale//LC_MESSAGES/advanced.po source_file = locale/pot/advanced.pot source_lang = en [test-439.contents] file_filter = locale//LC_MESSAGES/contents.po source_file = locale/pot/contents.pot source_lang = en [test-439.extra-doc-strings] file_filter = locale//LC_MESSAGES/extra-doc-strings.po source_file = locale/pot/extra-doc-strings.pot source_lang = en [test-439.introduction] file_filter = locale//LC_MESSAGES/introduction.po source_file = locale/pot/introduction.pot source_lang = en [test-439.reference] file_filter = locale//LC_MESSAGES/reference.po source_file = locale/pot/reference.pot source_lang = en [test-439.sphinx] file_filter = locale//LC_MESSAGES/sphinx.po source_file = locale/pot/sphinx.pot source_lang = en [test-439.userguide] file_filter = locale//LC_MESSAGES/userguide.po source_file = locale/pot/userguide.pot source_lang = en heldercorreia-speedcrunch-e7ca37f/doc/src/Makefile000066400000000000000000000016031526573132500223310ustar00rootroot00000000000000SPHINX_BUILD := sphinx-build SPHINX_INTL := sphinx-intl PYGETTEXT := pygettext3 QHELPGENERATOR := qhelpgenerator default: build-bundled update-prebuilt-manual: build-bundled rm -rf ../build_html_embedded cp -r _build-bundled ../build_html_embedded update-translations: locale/pot $(SPHINX_INTL) update $(SPHINX_INTL) update-txconfig-resources build-html: \ _build-html/en_US build-bundled: \ _build-bundled/en_US \ _build-bundled/manual.qrc _build-html/%: $(SPHINX_BUILD) -b html -Dlanguage=$* . $@ _build-bundled/%: $(SPHINX_BUILD) -b qthelp -Dlanguage=$* -Dqthelp_basename=manual-$* -t sc_bundled_docs . $@ $(QHELPGENERATOR) $@/manual-$*.qhcp _build-bundled/manual.qrc: manual.qrc cp $< $@ locale/pot: $(SPHINX_BUILD) -b gettext . $@ $(PYGETTEXT) -d extra-doc-strings -p $@ extensions/*.py .PHONY: default update-prebuilt-manual update-translations build-bundled build-html heldercorreia-speedcrunch-e7ca37f/doc/src/README.md000066400000000000000000000040211526573132500221450ustar00rootroot00000000000000# HTML Manual The SpeedCrunch manual and website is made using [Sphinx](http://sphinx-doc.org). It can be built either as a manual bundled with the application, using a stripped-down theme for use with QtHelp and QTextBrowser, or as the full website with a more complete theme. ## Important Tasks * `build-bundled` - build all language versions of the bundled manual in the `_build-bundled` directory. This build can be used when building SpeedCrunch by setting the `HTML_DOCS_DIR` CMake variable to the build directory. * `build-html` - build all language versions of the website in the `_build-html` directory. * `update-prebuilt-manual` - update the prebuilt manual in the `build_html_embedded` directory. This is intended to be committed to Git and is used for default source builds. * `update-translations` - extract translatable strings from all source files and update the .po files in the `locale` directory. ## Dependencies Building the docs requires additional dependencies: - [Sphinx](http://sphinx-doc.org) 3.0 or later - [the Qt help builder extension](https://github.com/sphinx-doc/sphinxcontrib-qthelp) 1.0 or later Building the bundled docs requires: - the Quark theme (already bundled as an extension for convenience) - [qhelpgenerator](https://doc.qt.io/qt-6/qthelp-framework.html) matching the Qt version used to build SpeedCrunch Building the website requires: - [the sphinx-bootstrap theme](https://pypi.org/project/sphinx-bootstrap-theme/) Updating the translation templates requires: - [the pygettext script shipped with Python](https://docs.python.org/3/library/gettext.html) - [sphinx-intl](https://pypi.org/project/sphinx-intl/) with the `transifex` feature ## Adding new languages * Add the new language to the `LANGUAGES` map at the top of `conf.py` * Add the language to the `build-html` and `build-bundled` targets in the Makefile * Copy the lines in `manual.qrc` for the new language * Create a directory for the new language in `locale` * Run `make update-translations` to create the translation files for the new language heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/000077500000000000000000000000001526573132500245275ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/advanced_features.png000066400000000000000000000773511526573132500307150ustar00rootroot00000000000000‰PNG  IHDR7ÔÆ ~°IDATxìØŠÃ@DѾÿ ml㤜s––hÁì^` xˆ #B}Zö}7¶m“u]�eYdžg™¦IÆq”a¤ï{iÛÖ¨ëÚ(ËòTÅÿ@DDDÖ†ë®ëÎcó±ýh´šm �€f@;¨ã8œ¢aó;j¬ išFªª2? ÏsɲL’$1â8–(ŠŒ0 ÝFDDDºÛØpÝsl;6[�ÍÇö[¡cEŽã�c…�^j4jPqz•IÓ�7?#ñ¶ €@XW×Ç ›®ëp†B©YQóù|Ì£ï÷û»f±`…Ñçÿk!di�BQi�´+"ôW>çñ‘�Áƒãµ{g,ç¸wâ2žÏ§�‡î÷»n·›®×«.—Kp>Ÿù&Œ1Æcp7Çå8·ãx\�óqÿwäÐ4­ð+p’ˆögŒ™øYFOŸ;9êíý~sXq<µßïµÝnµÙl´Z­´\.µX,‚ù|Î×cŒ1 ƒ»ñøn· ¯ŸN'<ÿ &:D-@|VU´Í@;ÐIο°a×F©ñvæõzEч¸€étªÑh¤áp¨~¿¯n·«N§£V«¥f³©F£‘8ÆcŒÁÙív[½^OƒÁ Ü>›Íp=¡ÃÿóÔ„Ië*Ú€Fø8ÉÄ û3ÆLßaC©q ÆVëõZãñ8B¦^¯«Z­ª\.«T*©X,ªP((—Ë)›Í*“É$Ž1Æcpv>Ÿ—W*Õj5¢'Bg2™„ûÿØ»Ëà6®î�ã~÷Ç×f|˜™™™™e :Ì8Oí°SfSÀ�¸±Ì$KkI¶dKf¤ç9¿»:«ëÕª’#5v;îÌgîÝ '/ü�swÕ‹/ªhooǰC=pÐh œ¥3½‘¸‘·¢ô¸ÁH GO˜Ò?~\Ì 7Üð?ÿûº·Ò+òeË–-[¶ìw¿ûÝ×o¿ýö¿ÄàâôéÓLqÐêQ”––<ž‚ÇTðV•>½ACàÙ›¥7¹ÁÓÏò1^C™ajƒ³7ü1©Ù¶m[þ^ýú·ÐŸŽ–ÑLì…‚™ÎEa~®¥/ZS/‘I»¹+Ù犮ÈD¾æ^6–E còªyÁñžÝÈ~Ñ\¾"±ÄeúÉÏ~NüEïªÙ¿ÿÖ«âÐäÏöòóÝO~”â‰ËøšŽ¯í*rV¯^ý.LsNœ8QôðÃc‚ƒc*<š"�ƒáZ�ƒv@CàábLn–VÜ ¼ðšž†Æ“Ñx€OOãA#Œ©6ÿÏÿN%ÇOSx2A]C1rõGó£FæÒ Ì×dÓœ&ni*ˆ˜¿§‚iÌEÀtÉÁó:¿©�]ÔùLÔ+Qªï3Õijmj 1G5Þ9:osNxLgmÎôb�Ò†=T'áTcUb&oœWæM¤¦³Ö.§ó^¦j�aªÞ”ÊQaç1Ub]€òlz_ÜsšòBó,žŠˆòÞTc®Ú=¹žSêŒtµj�¥:ï,Õ²:cÆäµØîM+áÉ8}éÛ?¡áÉ9ê Ok¦nH¿žLJ �ÏÒ–�ûhb&fÞ Ïç O¥‹L‘?2m ÏÌÓ?³Ô?:KÊœ22£¿þ1EººÈxô!ÅÿØCxÜd!åAŠ$�°q6öø}4Á&Ù<öâ&3Ü›`cÊ4ÊFX„…YHy�X Éÿèƒd<ò ¹éÛÿ�L'¨s0ªþ�ð5_ë%pNž<©&8xÐÇSxþãCÿìÓ9–Zü¸‘© FM9ál­®®®è‰'ž°&6%ÇÊÈ7G˜ä­‰Ùc&-b‚¦­–¸Ò’·˜~Ó”M¿ÈF¶Ði>Ó… êEŸ°E�SØx!CØx„=j4^¡ÊÍ+ôê¢&OLcNµ8²šªÁç¨�*‘cÔT8°‡JþA#²�]yá-ý¸YÜÐY„ÈÁšH Ä�8²†ìãJ�0ô똂À©Ñ¢&“: +h2 ®!8` u ²O‹›)6m·ÐÀ¹Î7`�›…ŽÄ�-p7ûñ#Štt�ñའ<wS�…Ø‹ÁQK­mŸ2Çl�Þ$7`‹†äìqùÇ�óGâ¦xÛ=nDöÀA؈áiÇé èq³÷'ߥ¡¶Vrß]¦x™Á|÷–‘ŸX�…î;EC,’4zÿ)gc÷Ÿ  q_fã÷Æ”“4ÊFî=If¡¤à=§(ÀüÌw×)2˜—¹Y¨®Ž¾þ¡÷Yq� ÿ^øšÿÕ¯~õ™­[·•––âmh ;TÔ××ãdÇS2½ACèÓ‰›EŸÞX£ÄPdx:¯„=z´è­o}+Îãò>вG 4•dÌ€sÄt¥t±nÀ^Iä!>Oç`át,@».¶@’ØaLºµÀi°Q9Lk ÎiQç5ç¼,Ó¤²E�-l*™Z9l J‰Q%ʸÕ²÷ö @èdŽä7©qVø¨�çr°7™U.vä€sädºŸ8$°‚9˜æˆs:Ã!z -n@&8 ÅMöÈÁ:(a€83GâÑá M¼„Æ•Ðè4mغ‹F&gqíhû¾#ôÕoü"';öµBʧL[™˜£½?ø:…\.ê½Á§ËkáKæhJýO³�žµQï´ãÃ|yäõº7ÆS£³/PSæ´¨iK’ QaŽ˜¤ˆÄÉí(±@ñ4=áÂéÎN4G�Lâ§�IèÈTÇÕ·G�œ‹ìøœ¢F¤Ÿ¿Ãùô°ç¨�^È5•îY0÷=³TÁp]Á׌÷Q@ØhâJVHìÈu*p*mA•vùG�°¿ÂOj–�§u’…Žœjgé‘ch²EŽ ¡¸-x ©À1DÌR3oMçÕöÚ§Æ70ïÞLF7ˆŽ®þÑ”€�Óý‘ž¢µ›vÐðÄ,®!rýß×=0ÆÆ©7hòÍ ›¥=ßú.R{É~ê(9@�IîR“—ÌÏl€…J÷Ó ³Hé>‘öûÂõÞÕ×;Þ�”ìMÚGC,Ä‚,À¿ð1ƒy˜›õܱŸ:“:˜¿ª’¾üî·§Å àk>¾ö_wÝu¯Ã£)2½yüñÇ‹*++ñ8x¸Í€çtÑòÉÅúÑÔâÇ ÆJ/aÌ„#)ÿQò�;C ›×)—¶¬#×–õÔ¼m=µn[«t²îíkÉÍ<;Ö’Áü,�4`YC»¿"c|á>¾}`û%�ägF’¶­¡nÖ¹u µ²ÖÌ¿7»Ä˜û‰Çèsoz­cÜÌÄÌÉ ž¹]»v->䯆«¡Ç“O>‰ÿå’zs ÍàñxÐx) GSK+np$…ß ^ñÂó6xí«¬¬¬hË–-VÜ4"n ßÙ‘Oѵ¿º…nøÍµ´ò›iÕ/×ÐWl§•ÜJ«~µ†V¬ÞM+Wl£k~y;þµÉ´Æ ›˜„MZÔ B|J«�ûW¤odqd�¤8Ó&Aˆ“)ŽŽuD…À pàHÜ0=njÁ!jÄyð:„ ‚FSÝ Y¦5ö¨ÝIzØtï±öpÜ€;Ê{-rzyå¸� ð`M¤h�Sá¤ò‹š4WiRãhùxêªN!"GGdŒo’!$p"ÇºŽ‹ÔT{áÕö9^HÆ�8,u sJÍ<³Ž$n Ö“~,å ŽR}‡ßÔž› jõÍsAö÷¡'¡Öð4#<Žë4õ ‘ÀÇ(ÊŸÙ;ëð(¯msÝoÝw×PH¨áOj1 n©Ò<œ ¥ø1è1n]pi É„™01B2’‰Al&!Aê~9¹Ïï®5{ödÍÇÇtRîÉïóí½?Û˜÷Y{­ýqÛp�ñ< Qœ~¹:‚r’4†ÿ™VLÇ¡;JgÀA8‰rµ$UKx9@Ô½¼ DÓÒh&Z‰6G üê¡Gäîó8�‡}´ù8Dx|40/¿€:âÀ’PE¸ˆŠE/b?QF” T¶>e`ï r3þü´ŒŒŒ‹¹,üµ×^ã oêˉż4Åi,üYv^šÒy7²$üÜÊ�ÞÛ†'Êæ¤!®oçp””…¹Ü¬]³iQ� -ñ¤Å§#5šÚ O#5þI¤F>Œ4:¦Å<†´9à•ß®Ç3±!tĦٱŽfÖÅÇ:ØIlÚ­’€s§%j,è½’£Ø’Ø+r¬+ óhퟷs(Z¼Åæ„.X^zöN-áÍÁ9*¢7$8Bnµ1-5!5Œ”?¡/A¥Æ&bce”Ü(|G-:Jr”à4ùpk”àäz˜³HMÀm¡ð£Mgg�ä¼�s'9ŒÚæÀl_'±ÿ“nk¹ašÑ×r#ÆIn¨ˆ#ÅBrRj%7)7ŽÚCx/§Ì‡—ÿEÈI¾|íúœR¼ÇXÚYOV4"åÑçPë>Â}ê:~-¥0ÜöŽoÈiÇx~Óî2l²:±Ù¶[˜ÜýØš[Ž’j^ìzªß} ›'�Ç6bû”ñÈ$vÙSÆÁ:möL»ÓÆbïô±(ž1¢œpU&,�Œ”s`¸Ïãt>,€J¢œp¢˜(˜†¼iaÈ¥÷îž:Y“Ç!“æ¶Ã7Ç­“Æ£ôW+1öòSrsä/ ƒÜ¤¥¥=±`Á‚«ù3 ëÖ­ã¥)ÎÇå²pÞ.†ón¸ÂZçÝðŽÅƤâs/7b&&#rl$b&¥x‰ ›ƒU‹ßµ!±i £_lˆæú›‰-wŒÆv"“ØIX&ކuâ(Ø'Ž@á¤(š<%„“('\–Ξ-ß/áq:? ®IÃýTNÂA”EDÞÄáØs×pXï Ë]£h£°ƒæ²�ØBðS‘‹.kj•ØZlòײpäaµ©è~lkRBsäËcØž¨Ç‰µµ4¦ÎUfß°Ì•ÏãLSbôxâ:¬öÊ Ÿ«Åjñl�¸o¶ñsùº2ÕÏÿ‚Î1�ªŸGí6_{kVûV9Ú—Î\zœI°£\GnvÙ­Ç[«äæãÓJnˆ¹!¼‘›6ßҔ̷ 1ZÃ0&Ñ»¦I¡’ƒƒGk¬ !5 )5RlrøØ Ð¢ÃHÁ±’Ø06?§½ä,;!üèÿ ©‘XÏ�Ðt–‡_ØVöHŽ”…Ø™»…ú¹É×2Ó¨¶¤Pa蟜`Hbn+¡a#:E‘WnÜ×Âã3ÈMõ!¼“]fÊ»ÿhSîFHðµï’�­Žùå�H~ôyÔ¸�rß¾¿¡¡!$Ô²•ƒ(ÃB‰�“–ªö{#7Ïw»ÕëßÁ–iØ2#Û‰ÄΙÈž�ݳ&ÀFäE³' ˜(‰œgdÊ£"àŠ ×ç¥D&&ÚtÜ9ÞKEd8œ„cNJˆ"zga'l„…È"x>;|óÛB”­Y…1—ÿË�Þ`÷¬r³lÙ².¼[1@{ëÖ­ÞÕÞ廉¢‚?°ÍÁßšÒSç§Ü°�q-;'—EUó‡8Xfż)³0ä?û`L· uCÿ[OŒ¾%Ü+8Cþ�¤§k8��Áà펹“¦ÃSnCcÛÇ~¹qK¹ñE/¶xEå>lmÒrsù¯¡ùJõ9ÊSékÇXŽáÈW§ -*eëÔ5BtX|”Àh™ñ]§û,/R‚LåF ”îK¹i;Cn”¬i™áù¸d[&;ûä†%,—’‹Ýõyˆ¤æõO£AÈM­”•s£äF$³Ü›Gk¤Ô± ÃŒQj¹LG¤†RÃ(©‘Ð8 r“ÃG–FÈ�U£$'´%£(4Û¹§Sp.ÀhŽ� EršÏ†ü‰–%8L�Bö!8 K�G!%‡§P ŽÂ°SùŸ-4Ñ?îåcŸÜ”Õ¶áÝœr¼k!øhà¡'…œsÃ×¾gÙoJa…©�¾€Z÷1ê;Ï`=ñÌÂ_…ü.¾vÃîýD96úØd­Àf› ûªšñ|Ï«Q½e¶ÇNÃŽ¸iÈ$vÙ„%n*l„=q ò"bß=“Qvßd8‰rÂ%Xš/ßÍ}Ÿd>~ï$/„ÓGÉÝ“PLy‰“°'a ¬ô~ ‘å›W&±ƒpþa-Æ^y‰�…”›äää ÞëféÒ¥,7¼¢ÃS¼É/WL�÷rÃ_øä òD;.7�m¨Û»)·ßŽÁ$1áCçàÖ¾“(ŠÓáƒg ¢ÿŒ¹f(n>Cf‘ôô@ÊmÐRº �­‡ƒÈM{Bï*Žtx—ŠüÃbC©øJ‰J1ÙÇ8ÚcW² =Ì1^Š ]näy)3&rc~î˜/ÇÇXÉ¥snTå”û³cØ@ý—÷ÉÈ Ë�ÜïF'·/K•Å-~¹ .5Œ[VDI±1“E‡#5 A£ÚÌABŒs‡¤FC}†‡!¡ AnlÁè¸Øœ{¹éL2¾P"9Lp¹ UršC”ý 6)5ž³KŽ–¦�ñè¶üûA £7ó,’HÉ à¸¿ÍrsÿC(%Øœ[ƒ ¶jld¬Õºm JaUGI…S©°²·²©�gà€ç#1î¢H aUll2G�·1•4ïJlÉ­ò²5·Ú˶=Õ(©iEFßQ›¹ ™©qØIdÂ6—˜‡<¢`~,ŠæÇaáx8·cáz8®G¢QEÔ%ª�‡©&\>œÅx)y0Åü>"�°ÏSó°Ò|²y~Ìü»Qþök¿úÊ�åæ•W^1Ê�þÎ;Ä…%7‹-úN¹©iô 1ÿwHí�ÊŒ¤HÍðËaØE}Þm<&õ¿“{‡cÊЩwÝp ¿¨7’Æ�¡½@Ss‹ù²”œ/|’ã` ±£Ò¿,uÌD2κŒd¸GDnT[ÜLn¾øar³Ò!ÅÆ$çæÓcX/äFnè'åf¿Onx‡âR™kc.6&eÞŠ<Æ$Z“k†¤#‘Æb û FŒ“Ü09Zpê»ùH‚³›åFa�æÇ“kˆtÊ͹—œ '’ÓAjmã§G¤àH¤äxL$ÇCGFJŽGs‚‘O°Ôh‚ Ž\ª’‘›dФì-¯Ã®}MØ^PïgG>¡ÛÔÑ9÷MÇR;�ÒÚØÿçu~x.O¡ûï v‘çé™~ê…õø ¨΃G‘1¨ê³w!çÉùØMØžRä¥ÏCQD?3ŽçæÂùÜŽQ›ûjLõ› ¢#Ln+iéâ;ßê“;· ý ^–â¶�›-7%JnšXnâ•ÜÈ}nL“‰[O$ïe¤Ô0¦R#Ħ鄉Ø©¨ª'ÆDj˜�¤æx@Ô&Û(8^NÀÂh¹a„Ühv7�†•q3g‘�&&t©¹§ó›^^÷;ñ9mR}ÅcÁGJŽjK¤ÜHNHjÜD¨’ðܸ�{#ð+þ¸‹V®EyÃ'°íoEVi v•4+ö¢­ú:†F–�ІñȳKÐtäK1î>+Ùš`çKܰМ,¥šfä•Mã¿FöEc®öŒ§a_ø ¦£èé(&J¥£Œp.N‡ë¥tT½ôj^NÇ�¥é¨[þ”—ÆåO )$ogY;u^ž¤g>‰š¥O¡šÞáòÂïUï/¡¹1‹ŸÃ¾‹P½þmlüãcñÝ RnBn’’’ ¹á\\þ •þÃ/7µõÕh¶>‰¸17áò¿ÿwÜø�ÿ�nÿ|1†\~FôЏY‘HIº 3c1zÀÜ|Ùuˆ»m{Òáö@=Ë�(ׂ“ËB#’l+|IÅy…Y»N$ÛáòW(±`ˆû8_§‘Çé>ùÿú„a¸ÝqÜÌ1Í7^VŒŒ�êИ• wÖðdg¢Å¢h%ڈûÚvxùØö>>ÉU|2;±µó ñ1ñ¡�cÖê�¾÷·hl8wfâ�5k1}@Ôú�~_NvÊ�åµ.4íºÏL¿ þù:Üþï×bâE×#ìŠn¸­ÿXÜ�y÷Ý�”™÷"¢%_Ñ ÏÎèŠÖœ{q°¡õÞrp"`?‘{Ã�``1áö9ƒçôh9¾ncøC=a–H\¡ª¤XlTÔ¦UGmÄžBj˜àR£ØÃè]ƒYnÌÅFV7u(R#É"HdT›9@}"‹®e²¥àø£7t$¹ÉaXpLå†ÛÌwË�•é”›ÎãóQrS™1Ó°Ü_ÕrãC�Qrø¨þŽ(`¤ä¸¥äøpûå†Úg NY3‹ÀWøí[ïcîS ½ Æ3ã>ª6c>"³â“0+N1;îþ3çlãL¼‘$?I½®Ç¬îíÌîAô¼‘=oDd¯›Õû&D÷¹Ñýº"¦_7Äö'ô@ÜÀHØ ƒzùè�D"A2¸½o2ç#–î�Ø Ñz"ªDÒ{æ³ûtŬ޷`F¯›1�æÃ¤ ëƒß&% í“opðØqú!¹9Ú)7”V§•[g è÷ýðÌ´«1wÜU˜;þ<0áF<6¥ćaQò,¼' é3ûaÁì±÷�Pµm&ò+ܨ;«Ü!8Œï‡_.QE“Ü�ð(>ÿùié(ŸµÓlÀˆŠ^�±q‹�ŽÚÈòïö ©2B‰Í ì#Œbt J°Ç(6 ‹�Qj*)˜ *5 )5F(v)±r#‡Ä&Û‡E N#½¡6I Dn¬’N¹é\ž:÷¢êC±,.Aä†ñH„à(„à0Bn7¡‡`ÁaòM¢8¢Í°àÉáöq:G%EpÚ¾8É98गOÔQö¾f:vϧšã§ß*>ÓÐ2Ïç’ãÌÿzùBð¥æÏßñŒ/:ÿÖ°Øü•Ë͉@¹)8Z¾E‘ÃŽ¦ìIðì Oæ4ï…CÙahµŒG›õ´Úî¤HÍ´d�E �k²P9œ3®¶ÿcï>tÇ¡( ¿ÿÓlï»éqzO¦ÊNïÓ×qÀå}�ã ŽéhŒD>�ÒÖé?.éÚÿaÝ{Ç”§¯b°‘ÃIÎX7§n�/½¼/ïƒÝ„Ú�ì[Â3ñ¶oZ#GQgreÂf±6yŒú4 8‚JE é«lÔXB|R“Ž6ô§7ðÚcÜ€�›7X‰�‹ãéOoʸyâ‘3اHÜ?�C&rðâY3Å�1rÂ}Æ éÇFNš �ƒk¿R9õÜlÍã>Çýµ›Í<¿V°Ï]ù{W¸þÚßÃ:‡=e€{Ö7—‰ê`óTûâjWnÁO£w¯sK{u·´_wËû ·rÐt«‡-ÿg%ຈÀå»nó¬ë¶z¶Ïn‚ó»êÞâ¿/*ü™A›t*ãFÃÆZÞýèÖ^̸Õ�¿Üâʯnañ'7·ð£›÷—vË+¿¹µ�?ÝÖË·qðÉGwrÛß{‘¦†c‡’ñ@‰¿/ ÑQÄeðÖxÇ) „ ‰=‰˜/Éägltb÷ù2lª66jhPÔˆ Q4jLÜÈ~Ãúª6nüêã|Ø@4p0͉‡M9Á)�§EäŒY‰À¡ 1®‘câ†& ßwrT½FÜð>ŸX.7Þ$#§æq‘È™á�ºFÜ�]}3pˆ�C6p*Œ+78ˆØËqs8ˆÀW ! �‹QÄ 1pLäœJÜ@4nlàÀ³Œ›–ÄLJü=Tê¤�ïP �Iބމ�”7¤ÿ>ã/«,æUÄK8Æ hN�—cšiÍ‚—G èË/‡ù\ ٨Ѱø\ E£æ 5¿ Ô +!n"�óç«ìó¸7ø<ŽÈàÄM8O1rhøÈáß�xAÜÈ‘U_ààš�CUŽDNÕ�{“Tãï)X[ÄÀñBÐp¥i¬ˆš¬Ç häàz&ë�œ8™à€�àØ)ïiÜ'8ª’F§7ÑÀ9lrz#�óÕmèôfTqcçTœA­)5 Ò¸aÔ/ƒTÔ¤1jþ½8¢j+No7>h¨Œ›ò«§žVèŒÑ®‘ˆ=²"öñÈ‘À1‘3ž¯fŠÃ°Á ŒBØdŒ‰œ kÃÔ�qCý�ƒ ÑØ‘Èa܃§’ †L߈†�bü¤Ž§Làðxjù¾�§4nläØé �P7ÅGÙÈá$dž1xb#Ãø(à$Ø46è8X�X;¢Þt¦gÙ[:`Ðàø 8©Ñ¨aØŒl¼  d= œL‡‘ƒµ~&p2¬× œ@'8ùõø½Ð#«ö_¾8•B�c�§@§a>?žŠOpF8Ù¸¡g79…Ä#GC‡±£:÷f#a=U¾±JG·±|ØoI,ìßšË1h‚i Q3LØ0hhø¨Nl^A,j �’tÐÄí„ Ž…¸�?°ú¸�?|ÜF9Á)‡Ê¸¹�гvãt‚30rª·q6n`œìuƸ 80âFBÜLx;SX9YÃï}Ü£F'ƒk¿ « 6p®5pÈNä¾�\v•ôço@‡ÇS6pîáx lÜb&76rʸ±Ñ2ªØað¤ñïïÜÉ*Vë’¶bÆ-ÓA°±¸O2òta¨äBÐŒü*5 jRgW7}‘³ñ?{gÕÜÈÄñùHÑ?ˆ™íç<3Hå|€cYÇ Oa8fffff設U×d5n9ëq�¶ôøU¶gzz{º»¼ÿ$7,l>SvÍVêþq FnÝ6§À©jqÃ*”‹óí Yð7œÿ Nô×áT¯¸9j‰›/_¿ A|ýöMÄÍ)ˆ›‚°±ÅÍ»_>}þj‹¦ÅÍW5Qqóêí§€Ÿ¾¸Ä qÃ…yþêc‚Àû7ª¸yðä]‚Àë·ŸBqóµÚÅÍ{§¸¹ûèmyÖ �1&d€VñÚX9ðÕšFšu€íïÅ6êâ;Yt­É�sß¼Wõª�{ª´ö=Û* ^Ê<$~ôž—_×|ü¯Þˆ¸‘?Ÿ:ÅÍ­÷Œˆœ¢¸9sù©ÎŸóéÓK -{â2ÙO8¨ÙÔÑÄ?ãúÙëXÖK¦mƒØÌÂ6CÍ•To}´Ú9ì À{ÏÇÿŽððÉ;ˆ]Ü<Óán�¦_Ÿä²‘šM=Mü3®Ÿ½î�?Ó¡p°â‹]!èó ÕÎaW¾{>þw€rââæì•geàÔ†RÓŽ”îý�¦”üï‰^Z4¼~„&lhÎŽ´VøLúÛK|,¿i½ážäâÉA½[jZ:ô³ÏêbŠ´mô�×ɺ{¶Wâ*õ’Ú/j“³nÿò9zž‡h�¦8j&yª½Vzâž/ÿ³1ê>8ï”e??ó ŸþWÜ0§BªUÜ0"nÎ]}> ŽÒäðãÑ’-®m¤SO“ÿ íl¥¦þ§ißhŸw¯ÙçùÙŽýOšR‘=>/±L-æç1"±Ž[šÏoÓëÉØù8ŸýÀïâ:òóâvW½Ë×^Ö‰eÇÕð?‘uÝÖz­ôÄ1_þgÃFïƒóNAš~+™mˆÇ£§ïEÜDþ’Íj7‚ˆ›ó×^ŒžíJñfHžÉØ´o’õÔôcr®t�ÙTøl/î÷Ñë]KÚù=¿k.;.J,Î'ÈÐï%~Ú³'äÝÇhrືR{9ËõËû¹b©øŸ½¶­ïi=qΗÿÙmô;Ù³ ñxô,*n77¯¿ø_ü1£~øøÅP�,ÕüŒ¡ÖÜHk›¨ÕÔÓ”í/œ±–¶;ü®»ì¸(±8Ÿš ýQâ§=ûâM©ÉÇÌ)9XõržÝž÷>ËvÞϾ�Žÿy°óÖm}Oé‰2sþgCïƒ~'éÑØr€Ç7º¸¹tã¥N.CSwíã4µÆP0ãxþy3µšðÙ}–?6²o­Yçë9¶ÄjÍ…~;2˜>ZÆÏ¶ŸÓŽ�Kò‘œ��«óÙò>»¶Ž÷ʾ£æ5a�C»µ£OìrøŸ;oÝÖ÷´žè3ç6Ô>è>öl@Lž<ÿqã7/ âæÊ­×eØJmövïÜJ²·k�‚èÞŠþÐfú)Ë~Ñ5‰ÛHÓv9bɺø)v|änÁ¬¼Ç9[kƒòÎèû³�Ѻx€kaßQ­—¼ßqÖaëxŸ‡°FŠ-÷Ò{­õÄ5_±QçLéƒ~§¶ÎFñi[1¶Üàé‹�.qÃ@Üpa®Ý~�<ØÍ¢¢Ÿ†*>×­Ôniún1àÙKˆUÜ\¿ó&q�ë4dji{ÅçZ73v{‹ .qqsÄ77î¾Mœ¢µÆþk(—ˆ¼·Q‹›=è!ø—½;­êú8^¶v¨üþü‘Bi«#[�R¨ @–Y B©…R¨ƒ¬2¥ »P‚ز˰�Ñ8­ ÛÔÖN6—hŒ[’—Å$/É[ÏœãÍ�;×Þæ×ïË{÷ž¯ðÁi|÷¾ûÞsþçë9ç½dg®,_¿@ÜHØ$âæáø2È‘yâ&Ž›©qSù‘ˆ›ÁÉÕpãæÆŸÄÍ¥Ÿo€|‰âf95nˆ›÷ÿù�œ77¼[Џ 8q#ˆâ€œÇÍ`iÍd„¸!n(XܘM‰âèÚj>íy#öí?Ì�ˆZÜ<®&èqsÀ\1ü5ÒcÿÙ1ǯíרÙrûކ“æšyùר¹°×;lZ7@Ü7É™}`Ó¹bÆÍΘ}=¯‡7Ëë˜Ék¸Ýìùöu4¦«‹×ˆ›¬ãæ‘økqsíø:³92ƒ“6(ö�Üì™A±{‹¹þãkæ\w36ésøìh2nÛÿ7ˆ›©¤J“=7¯0ø]5§ˆ›âÅ�òžê‹Ã‡¸i+Ä qóÛ£jBÉ+ndöFþõžUÜèÒG_GKbßgÛ�ÜöƒÏÞ”ŸG¾~kÝs˹DrÉ$ýœÚùõs¦?®ä~”7Íž��72{#³zIús˜þ8eéJß“£ãÿ:q“Ù›ßDfn$Ò%±ïë­ruàRΩSòÜ^çLÆÍVÓ%ƒs'Å�¼¾ë,KÊkŸIÜÄq'ô@Ô�!n736n†¦’ªaÅMÅñ]–ÒFþL߀ì72¦X2˜ÉÀ§ÎÈ ¦£.gøŸ3¾ö¶/K)¯£¼vʬ�×’Ð[¦«'ýù‹g¶š�|ŽaY*qSÒㆸÑÿU/^kße£Š2ˆ¥Gjô¤DHL2Ó¢\C‹ÏÙÞ¸QÞ1'36Ä�Ç7X–*‰ãæ·GGßs£îµÑ#%}ªDQfq#³"©œÄMÊÏôûS®¡•çÔm3çlÄ\ß�-æs9^%34ò:Kèd©Êó§Ä£Ç1aÄ Þ > ,nWŒóë 6nÊ7Ù‡M«ße#³3zܤ,iôñ?gâæøUy�”ý8q£¼†Ê±Ç„7ˆ'Ô¸yùŠ%n²m¯qÓ‘ËR¡Ê ›¼Žò9GÄ €¶cÏ�-n~Õã&›°Ñ—:Ú7ò³øöþ×àyÎŽ�åmþbo�“¸aY x·T›gnbʲ”òIµþƒ¦,g´!n´�¨>!¢Ÿ3q£/ê3pl(€6,KéqCÜ$ÿu®ÄˆÿW6´!no!^w&&1hÊ1‰sùŸ3q#ñ"“þgò:çä­àúë ÏØs³b§V�›'Õ‰Ïo÷–ÁÏóË6Û7úî)¦Ç‡ø‰<Å�ÌÞ´þ-ý­ÿ?¡¿ŽrŒ·‚»°Y1Ã6lœ âæ¦�­¹ùD´"n$pôÛµ'nR–CôAQîKõsæ'nâÙ»–~ÎMë¿~Áãu€\ÅÍR4s3d7JÜ€l(^²a3iæ *n*6n~·qóû“Øq@ÎgnܬM3Z–Š7�Õ8l 3sq38Ù”}7áÆÍÍâÌÜÀÌÍ„‹›¦qËR·^ÄÍópâæ_DM…e©¢0sã¸=7áÅM¥ qq3\rB‹›§áB‡¸ ïq³Ø4ƒ�(nœðâ¦j£&V„¸€¸©›!8.nnYAÅMÿ“ªS¤¸€¸¯E�3é'°¸°37NÿšéE‼ÇÍ€‹kh²n†K�ð⦿£âfŸÙæ¦ù⇗œ9mv§Ü~÷‘^¹�â¼éö½¦Ä}¥_‹è>‘vß½fÿ®õÎ}ÌR�ÉàzAÍÜ8C5;sS/nbí�›ä ¯DÂfÇM÷y%´R£,áè‘}éçÕ�Éøzs`×is”0{Eˆ·ï¦`ÜŒW:!nu§‡ƒß@-Ǫq£´zÜHŒ¤˜ÄYJÌÉqú1þ×KÜ@(qÓpcz4s3¾7�€âfp¼*Ú7jøxDŠÌ`œ8öê÷«¸J`I¨è×&K\>þ×KÜ@�qó´âÆv·,e7U7Cî�KàtTÜ(��ý1úñ¯7fZÜ$gou·öz•°�È[)Ë‚JD¦œ+ùøÒÏ™~~ýœj0Éó¯Ì�@>7W£¸‰'°¸™°^gæFIuÀÕb(•XP‚C¢ ý1É}èAÔúë•ã”ýC'Λ£J€hçT‚I?·~Î?‰›óæPôš6n0s3ø4×Ýø>d7Ï£éªñØŒ7û�ü“¹þãk:ñoÛü_$}–C‹!}ÐRÂHH=RÂD8ÓgôYåz³Œ¹¦Ôð�ë“Ç’rŒ<‰8Ñ�Q¯ÝÿœÉk/(ÄÍx%Ô™›çfx¢–0³Ô�qã*ú¬�R2°f7rŒöøôwwe~½B=NŸA“Ç-á „©G˜e|ÎBÀÌͲU1.n†ã™â¦”e�ìcH¼=bAù¼e–û׳~½­Œyn•¥±äÏôûS®!ÓsâÆÍÜØ¸±¢¸Y 'nnMÚ¨‰IÜä5ldàÓfmô�]å³&}FC›¾§õ׫G€¼&zÜ$o¯ÓC$ãsâfÈŠâ¦^ÜÄÚ·,¥„�GœÈ@Þ¦¸Qgh$’‘ /77Ä ¨qE�3àÌÍíÉZÂlÛãÆ#l”φiÃg¯(q£D‚ÿýéÇo^Ü(çs Ÿ³ 73‹ 6ËQÜ7sÓ´qSª =nZMùÔ^ÿY›¶Ä�²ÑV 1eÓlâÆs·r ú9‰Ä�D�s+´¸¹SªE&Û72øx¾MW‰ý¾üG ‘xÀ׿:BŽQÞÎ,ח߸‰ƒU™‰‘ç@ÙsäqÎ0ãqs˱as;Ô¸³Ëm‹Ð)! Ç*³6­�åÚ•H'¡–÷¸‘sê¯kò\ÊmÔs†7ˆ çöd@{nj6nî–êÂܱžå2nô=:ÙÇ�2› Ä˜2ð+‘–»¸Q>}XnŸv_ús©œ3¸¸@ÜÌ.5lÔ,GaãLV‹›©º±îF”¸Éˆ çŽTÜŒ$â¦V€¸€¸q³5Îë®U )nîÙ ¹�ˆ›gK 5–ÄM5°¸™®;2ƒ“ÿ¸€¸q³5‘R¤Ö (nîO׿ò77v,)UcSÕ°âft¦nF§E-çqqãÆr4÷ÖÜ)nê6nظqF×ÌWr77.hDxq36kã&–󸀸™·q3:]M-n"Ñ N�ââæÁÚïõ°â¦™‰ä>n n\ÔÄB‹›‡6lʵPˆ¸€¸3�ÅÍ£Ùº0­|Ç Ä�Ë]Ð8� âfå¹yü¬î˜Gkªy�ˆ‰·2óÈrÁÄÍ“97–DN9÷qqã‚ÆyZÜ4¢¸IÈwÜ@ܸ±üñ³š0O¬ÆJ@qó´hqqã‚F„7�„ÅêJŽãâfÑÅÍ\Í<}¶f.°¸Ÿo$,Ö˜¹É;q3>W·jkêaÅÍÄ|C)n nœy' ™›¦} “ Í„¥ËRy nÜX>¹ÐHiæF´È}Ü@ܸ ‹zBP37%4¥r‘ãâ¦TÜ” ˹Žˆ›åµ¸)‰ÐâfªÜHÈ{Ü@ܬ˜R¹n¦‘r# ¸Y}n¦íƒv 77ñÄE q+JÜ@ÜL;‹VxqÓLX®ç=n ndÒB4WŠ›™bÅ ÄM=73ÁÅÍRÓ>èX%ÏqqãÆr4"¼¸™uqËÜ@Ü$ÆöYKâ&¨O(žpø¿‚ð!~n\—ñ èë–ë«æ×‡sÃúåá²ùŸ±e÷ä8n n\Ðü2¶dnŒ-G¿[nÌ"nª«¦ïVÙô /˜¾¡sÙz0]ËqÜ@ܸ±üòà¼Û-û»ý¿*+¡ÄÍŠ ›²}ÊæÒà‚¹h�æ:n nÜXÞ;0o.9ƒ V`qsyÈ…M¡ââf0Šç²ßçC‹§wÐ蔸y×ôîÜiævî0'Ûpÿò½ùÏÿë´ù×W<šïÜsé9¸y÷ ÌÜ88áÅÍ%ÇÆÍÅ�2qóáé „ÍsaÄ3Òcë·ûã/9®Ó¿j´_cg¼tÜv³çÛ×ͧ=o˜®.ù™Øc¾ù* œï>ÜŒÇÄÍE7Nxq³jÃfÑ…�鵈„¿7ß¼­ßþTŸ)ÎIsmÝL5ö8nÄÛ_šfÃ6â&œÐâæòÿ�ë~Àq#ËQ²|¢ü=n®OŸÍÉl§{‹¹þãkæ\w†qÓw²%ÏoÏ'{ZþZËR N¸qÓÇM 37ʬ�ÜeVçª9@Ü0{³‰0sÅM4{ÓಔsÑX\?nþöžéwÑñÎ{æ ýïƒÛv˜¹ÙÛþîºÁrîw;!çÑâF9‡�Û*×üþßw$Ž9÷·x¯Í†7½îí1cÞq#³7²4•׸yËtõDËQ‘7Íž�ëü?Ý‘MÙ{ÄM¿ gÞ læfxÉÅ�éŒÜŸ®ëq“ =pâ HÕûwÿ¸ÑÎÇÍÓ›÷¦õqÄMYfm\à„7}væÆNïТ³¡=7úŸK¼¤Ï˜$f|¶ëq“RIzÜènëãFöÚ¤‡‚b›9g#æú†l1ŸËñ:ý­ïdzÜè!Ù"À†â²N€qs»-M /9ö ©g7ÉÙýœZÜH,‰|Ä�6y‰ ¹öÎŽàÝRQà7µçæÊ�ª œµÙ›ŽŽ™­I™é‘ûêØ¸Q¦ýËRû„:5n€e)‰›A œ€ãæ’5:ã7É%¦Œ—¥$^ä\9Øs£„M.ãæðÙQy �½çØP,qã„7ÿ}§f®Ü®Ú¥©ŠGÜ(›ƒ³ØP¬Ä‹GÜ´áÝR²y8Ž‚|ÆMh׎wü»¥€=7²¡8´¸ùénÝ\±�Ó·8fZÜH@(oëÎþ­àr{9Oòºü÷Ü´ôsnä6qtxÜx}]„Ä ŸsÓy7N`37/⦾±¸Ñ?D/ÃñÓï_¢¦ßæ&ù žo“Nù@>ýöFö°tTÜè_ô©Ç ŸP m�'̸qÜìÍe8fõ¸q¡pR–›„„HK¿~Aþ,%Ž<–¥”ï– 4n$pôkÔã†%)íÆâ²oCñO# 7 sÅNß�š�›¦ßž›üÓ¿^q÷‚h6G_ˆ-ŸwNÜ”£¸qâ¸y\Üè³7:tm]ûn©­æ#¾Ú¼,U·q³nÜüìfn¢¸q�Ù{£‚™š7ö}¶}�hd¯ €MAÜÌÔmØ,F³7Nh37÷š6nâÀ 'nôå)G�-läsmXîÐÄ�bÜÄ�s·‘ŒrŒ¸‘À mYêþŠÎZܬ7ä|ÏÍÅ!·ç&dÜ8?�4âPÄ�#38Å�1WGWÍÏ÷V,âPÄÍàRÀqs_âf…¸qÓëâÆF�˜¯¬7÷ˆ›?ØuÚý¡×ìßUìǹûH¯ù⇛ÖyÓÍsŽ™CîG�Ç:cæFâf(¼¸‰¸¸±έvPÜì3ûÏØ¿$gN›ÝÊm»OD¡’Ü@ëó—Sxùo9�\SÁðîóJØD¯ƒ»Í¡î¬ž«ÿcムm©�0Ž²Öƒ‰Øn,ˆ5à]ÈÞÍpù‹ðžg?ÜWu»~5%Žî™@Ñ9R›énýGÒÌdÌ´Éu¶#(Jñþùÿ Å·¨¯ç“�}æ6:tÿk¼7^}Ée{ŸãâÁmìׄkFo]¾ËvÝÇžï½^®Zêç@óíãÕ›GíJáæÓ‡mÜÀdU‚¨'YOÚôûû„�ß6‡›â¿Ø4HVõUŸ H=¢?¹2Ƹ})Ÿæ|Oíé¶n®tå&`ó¸m7¾*á“ÿþÍýã¾ÊªÍ-[.¢ÏÜÆ€T+<¥ÏÀŽÇEo§0q€¾›Â Øè[.[ú`ãÆp6àcÌ÷«77ïý nÞyÐN¸¹”37=ˆŒÆõP.5÷ÚV7šÍ½hæ÷@ñSY‚MÂjB§E&øj 3ºOVÈ FOôN\§c3}=Ÿå�l~O°Ní˜ïM÷ó*ýìË`ü€DƒôÕ à—1½õèÅjP¼{Á‚8…Õ/Ðw[¸ý.Ûõõx€±7„—q¨�!ß¡ž-€›{ßýp®ñÌÍn^~õÙ?>{ë™y{ó¹uÉ—‚Ó'ãõ�7G§$Ïbúrlƒè88„šäLÒF6óU*+hùÏP� g§°âún 7nc»FÉ£r3á²]_�±qÜô\¶Ûx”�!ßÁÎpóEƒ›®íi©; 7é»n Àõäé«ÝÝOóÕ€Àи P­„›â—ø$º €4ºe<ˆS¸ƒ}7„·žŒ‰*Ûûx<¸�kᦃ‡ÇƒÛè>æ|ïðôÿÃMÚ 7{oK­?Œæ{®h)wEÓ1úï�tt8rÜx ĦÁv^9 q w� ï¶pã6ö»åZeFÙÞÇãÁmôkbù½A6Ûx°�=ßùÜç 7'Üødº¢A±ž¬ºÄ†àfé¶”Ç@ô)“Ñ¿öÊãC|WÆ@Çb7é»ܸ�ÐÑ…e{�·Ñ¯‰èî±è6ècÈ÷ …›÷ï}ÿÇ{�ÚwÚuÂMÚ–ÛRð®�়(oc¸Y ¸Èt :nà‘QÐwO¸qá |üí²½�ǃ۸n8ÿå6º�ï4ÜpN¸9áæ�VíºýïýñmK¥Ø¬9ssð¤pEüïwº ï†pã6 w]\¶÷ñxpÝ’o ›l\™s»œ¹¹ÿnnN¸IÛ[jý7>øÀÚ(’èr ¸'òñOKyÑw9¸\íqê«6®ï–pã6Ÿ`ƒl캻�~M<ßX¶Û¸ çvyZêþ/�›í„›¯7‚›ø-�û®¬>™ßƒGŽ{Á¬/öë‡òø…yþù…éëñ=üUïëï ]ß-áÆmŒ_ç¯FpÙÞÇãÁmÄkÒkZÆÆ|ë²ÝÆU9·Á{n ܤ�psiŸ_à� ú„ì ÷o�”à%~ù¿óY 7ôáÌ7é{è\ìàk쬯çÓã@²Ñc,“�Ëö>n£_�›|SÙn#øÚo(Üüðpn.nN¸ñXý=(y ¤�ʨ@ôÏ/¼Å_-+¶‹ü£Š=ÖúØ^ìü Ú®ïfpƒ6zÎõfÙ®¯ÇƒÛèñàù†²ÝFð±ç;üo%Ü|pó';wm `´Ù+gë9îÃL˜’eÒ·³Š”˜~ÁëáÌÌ’8o�qCw“Ê?Ao�ª³ˆq#nÊpyûU.å§åjqsšã&7âæ{ÅM/<¯ß ö”n79pjÅ�¸¡þ> œ"n„ À+þ"ÅS+qžÅ�¸€®q3OfA܈è=n~ŸÎ“8âFÜ@Ïqóq“ýJÄ�¸ oâælNÃólÛg܈7·‡¸Y‰qÀÄÍŸ³E"nÄMÃ@܈7âFÜÐ;qsq“‰qÓ<˜ü˜"nÖ7‰¸7 BÜ,�Ä�¸i ˆqâæ¯¸7ŒIÜ„çyÏq#n@Ü\,SàdâFÜ0qÄMcqˆqâf%nÄ Œ7w)nþå¸ âFÜ@ÇqóØv܈@܈7ÙßD܈è;n.WA܈+nBq#nq#n@ÜlRØäÀ7∛ÿ‡¸É�#nÄ ô7Wë8A܈"n’ˆ›D܈7âfÏÞ@X•ýq<À_HˆT3€ž!x /!þv"¨5ÀØ 2i,,`h €%€x²0Y8Û³û5ëùî;3_·cÎø\>ðÎ=÷wî»æ�Ïü~çÞ p@næü‰Üü‡Üœ¿Z>­®–ƒËWËä_ì»÷Þ–_úå›åñ÷‰··Ë—RJù¼]�âó„Iy5ÿ[š3�t7~äFô-7ÈÍ�ÍcˆÍƒòþ³™ ý~ [½ßÆn1Û¬¼¿}B¿;�§?Ç\nò8QŸü:çq:oÐçVyñüoÁyuƒÉ¤¹ù¹é[nü�ðÛòâ’i÷òQùa_/{ÅlFVüäá·/ohÿ¶ç©s ä&Š“÷ɯs§«ñæc»ô¬l“ í @næs:rӽܨUIŸ¯}´˜šÜì­9�qýÕææÑ›Ùpœñ¹²ÿáLÙ×ö DÏ}žÉM'è“_ç Žèc¼Aÿ÷µ}ï–>ä¹išµ ä&Ïv|,Ç*W´—›ü<Ô¦ñærʼnúDÄ�Œ·Þ‡ì rƒÜLF+åàÚjŸFWl?±~Qû²sÁÅXr<µ¯®”­óf­ÍtÒpQl *êã…¨•Üø‰uwÝ´+Û¤ì•ÿî6v}Ù-Œô‰¯óq:ï@c{ da€8Œ7éãŸ{Ó‘ÜP–ó9¹ 䯖ŒÖ/.~V?¦/gIœòÜ\nÂò’ŸôÁ•­o³,Εÿ·—ß~Zä¹Éÿ‘€¶róõ0cƒÜdr³Dd$3Â"‘‘ ÕåÆ rÈÍ©–›ûÓÿ•ýgŽÎ�£ãÈ�d¤.¦ŸÖÊQ2ÂÈ�Çì€Ü 7ZÈ�¤E2£r”dlj��£ãär€ÜP–ÊåÆßåËTN`<”¥¹An†!-Kù¬L=–ň 7”¥òžÝí“g�êr€Ü 7qf¦~Û÷ë�…Û¿kÔ%fx¹@nxˆŸ¹�Û·I’´ 8x:²äª½Ü 7¼~Ágt¼¨x$GõwKýÅÞ]DEÜâ¨�Šˆˆé÷ˆ pbÜm]Ñ‹»»¼ fÝõ|7|1qcÙO�¥¹¹�æ¦'®óôF3Å âFÜ|ÜÓ‹kß�—§7¯ðTÄœ�ÿDÜ<@âq#nq#nq#nq#n@܈›4€¸7€¸7€¸7€¸7Oq#n€L&óˆ›?qsxt#3Ùh^Ж޹pö^§ö~C£Ñˆ•••ØØØˆl6ù|þŽB¡pµG±XŒR©ÛÛÛ%n@Ü ŒmÇàÄn¬æ¢Ôpö^{¿I�¸�„⦵g>²Õ£ÈÖ"v«¤ [ ï7É7�PÜœ�®-6"v*ÿ€¸�Äâ¦P�Ø*“´®öÎBÇ‘#Ãý‰8ÌLö)š<À1Óó4„¤+KÉÍØØ&&&ä˜TnÄA ‚:½to(7„¤£ÜÈ~tËP„·÷)ÉGØçJ.' .v( w—ó‡ô¶ÔŽO“Ÿ‡�t&™Üˆ¼ˆØ\vÙe0Ç”›×^{-ì!ÒÁ å)7„¤«ÜôŒÇL\lWî,•1ÉnÌzëùÕº‘ù'"96ÞÔç‰äü~•1!iŽ)7¦Øœ~úéðûýعsg‚à˜rã8Ž ª®®.¼55??ŸŽrCå¦kðú¢|l'|Pôö"É“ìÇŶ„z›s·û¶}¬Ïóú…«ðdLHÚcÈM‚ØœuÖY¸ñÆqë­·â‰'žÀC=Snžzê©ðß<ÔÖÖ¦³ÜB¹‘ýèÆž…®R6^•q�‡Ûün+”1É~\lUºÞæÜ|<˜ë„¤7'—˜Í›7ãæ›oFÈ+päÈäççã×_…뺲žb¹9¶Z¹!„rÓ6Ôu‡øÐ†ò9pe ·ÊÉ~\l6êýònµÛÕ� eãåèš{Ÿ¥+„¤=I;7''õ�›EÊÍ ”›–A ¦Kðp³/º%å³±Ùgáæ$Ÿ­]s�HË·ÿYÓ�…XþÊ{=™’¬þ«à”B2Rnš�ªÎì…B2Rn~:6/‚…r³\åæ©¯›ÑØ=�šN ²ƒäRkÖ›ä'7#"7GçEp(7+„PnòËûðEɼޜɤ֬7É52XnÊÍJ ”›™¹|]Ò+ÿ.[T$�Z³Þ$× Ü’Cr“ Á`0)7?�Á‰KNëåFCå†Á`PnJJJðÊ+¯ÀäÕW_�øôÓOQ^^ž"¹ñæ§…r !”ƒA¹±iooÇäädœØoÚH7§¯o $1}èééEggš›[PYY�¼¼¼ÔÈÍÞ,åæ!„rÃ`0(7/½ôR‚ÔŒŽŽaxdCCÃhkë@ss+ŽoFSÓ1TU×âÏ¿ PSS‡^|!r3’›¦Yݽ¡Ü¬3„rãÂVŒ,×VP¶»úú§ð±$·Ýr<3™pøØ¦ÜˆÔè?ÆÁààúûpìX3‚Á£¨o¢¦¦…E¥øý÷¿¥s“:¹ù¾i?xs1Á¡ÜB¹a¬4<–eö¤Ö)•›œ.¹Èˆð)ð±M¹ÇÈÈh\lzzúl:ŠººFTUÕ¢¬¬ %øí·¿PQQ•B¹ ÎH÷&²=å‰ÜÌSn¡Ü¬(è6–t>bÇÌ“‘3eÃM¸ ™ó±�‘A¹YÀw�Ó"8ÑÎ,Z)7+„Pnô¶„Šb»‰o®+º¦ßü<8–>�œ…‘‰!u´àx±Ž®¦þZ4Œ¼!zl®ÉÑ|š—iJ‹¾-¶ktr–óØNz{�üú”›á�Üä7Ná»àt¼ƒÓ¼¹9õ ]t¡æÜó±Ù8Íõ7>�¼»?qvK.£ØŒ‡ä¶ »6K.û¸ø”Ù; É�, OÀ133u8à˜jyb☖!�™™™ÊÇ·hfšaÌÌ5fvó,åuåô‹í7ûm–s¤‘äï�ø£§TR–,É•_½÷¤Ï>îÃãS?pãý¢]�læž}ÉÛ{6� !K€F@'.~þm}[,ëû0QM0ÀÊEŸœ””�U¹?öù¨U7÷Xœƒ pæÑnl¸ùº?0ؘ_ùçΟÝ&äψÿzÜÇÆ°öµÀÍçÅ?øë*Ønš�–'ç¿Øeâ°_³|Ñ�"%%¯ Z Ï¿“²õ+`B#A}q Í͹¶‹áÆùü6…€›æÞý)zcé©G¶¿Ë�›/‰ÿúŇ�æâOù`PðÏñ—¿pà“Øþt|óÐ!ͼécãÕÇmH>û•Ÿ§pcïÉYn²“’Mú%¯á™IK V�¦�4õ²øùo ntL?½Öäø×v9ÜØö] 7÷ì�ͽ,=åÃÍÇi¼c)Ÿ†ÒtÔxÒ9ößóæo}ÉxÒQ dÔÿº©j\ঠ’z�T‚ý:w&ûõ�$9ï&˜EÏ>-•¥l�Œ ~„PAK×õ¯íÒýé2B‰€›ýï‰ß½/Ž¥§®‚›þFmˆÞ¨¿ã•~l~õ3êÇn´84ݬ@-µ `xE–È>Œ¦¦?ÿšÆqjgdûä½&8ÅNZHáÅ¿¶ ÷Çùü…€›‹îÞ/¾gß<=•çámy¸ùÁÏÈÔÚ̽ôeñ_?^kmÖ�Ú,}Zü¦7hü¶7Xü¦ý<çý�‰/YÊC†Nþg~BüÆì:Ÿ_ò§ùÏ4¿ê•=¨½©=ŽVg3š¬?6†ŠãÜ „POܼ;^xמ5€S7–Âq!`ã'¤IY&E™,?,nÜhËêáFÇu@áO?-~Mf{ƒ¶¤¦*Ž£ÕÕX½�Ûû’žª?nÀM÷B!àfÇ Ü\pçžÀÙ/ZMO)Ü”§¥,ÂQ_ó£“&Í41ê2�DÔÃ�‚À/|Ö¼÷�¿ ¸ÿÙ?÷Óñ›Oý”ÛOÕGÿVðúãÜ „P/Üܱ;^xçû¢7o}çbp£õ6Z›âGSlî ðYq£¦it¹¥^¼çÞô nê�£ÂMýqnB¨/nοc×Jôfw´ôÔC¥pSZ7¢é•l‘ƒ€‚È„ ný°»?nÀÍø…nV<ÿ›h&ÐyúégãO<{ì‰øðÃ�¥æ™Gnλ}×Àé n$…ÒAzC£NAì�àÆ?ŽÝ7àfüB7û÷ˆ/šLâ^ÿúø›¿ñÑ|ìtÏ;÷Ü8›=Ô¸¹mç*àìNõ7.ê n, ‘�¶¬²:i×ÃM§i)ÿ8öà¸7cB¸ ozS<þ¸ãâùçŸÍ—\rI¼á†z7ûÞÏMp³3ž¿ 8ÅpSø˜ìmË-XÒ)íÐHGÿknº8ŽÇ ¸A!ÒR=€›[w$À±ôÔƒË[¾[*“ڰɳõh€Â~X²Sëß-ÕûDZóãÜø�UÛ÷IH:g‡¦ÅógcuÐF¢æ‰Âò0ÀÖ¶A¤¥|¸9'ÁÍKOÅ-pSôœ½]Y WÝ"Uƒ§JȰÏñS8}ÎMÅqlç¸7À �Áåé½ÝÃMÝgæ[6(¬©z kˆ´Ô»â9·l7ÀIœ-Ï=O¸ñŸPlv¢ Д‡¦†ªŸì?ÙÜï'WÇ�pÜÐÜþŽn¤¯ÕÐà‘–zW<;ÁÍ*à¬x¦pSß[ÊŸ ý§î¶ÑãI b˜’ª8Ž­7ঠÒ;G¾ÀS§e ÷kÏm–¸fݩӣ'ÄF:Í[’NÙ3í¨]yþuyQîù_½ó×Mhȵµèµ'ãeþßÈí§mSx¦aÝ"-•à&ÎÜ n(Üøö»‚÷°;·_;ö®à7"7™IhC¾«r֩Ѱ/rëÒ¼~£ÂÉtfãdÙËÖ…htbåù—õ=¸ñÞs®›b¸YôÚË�·à~úÇASfM0`CÂÍÿÑ%�¹ôÒKÍqóæÍñöÛoïEZJàfîÙ³upãDoz0¦ÿdÝqwoù¸7Ò9$2Ø/S™hÖýå?“_²™_¼!6¶¾m�ºLIe:‚Ÿ'dëWÀMþº)„›çuíùÃKþüãàÃ"-µ=ÁÍ6œäz¸±Ú›z(Ðz›úh�à–•ÕÚŒÛÇ ¸ÑIÉ&…ü¸†òm2´°»7öÅ5*ÔÁ]F’¶Yôü·76fEÍÍâמ�çü¿ÜÐ~appcéœzÀ1Xª‡ ½mº ¦¨FïŠãÜX­A.„n¿Î�IÂ&?-¥cåïÖé"<�üú&˜úóoë+(e © ~DÄö¡nt?¿öl<ÿÿ Ðüãàà nn®…Œ�)M_ôúÂD #mB’_ú²Ü/(6‡F>ß^£®Ø&3áKjjáó¯çØ™Äeûò¼¡ñ®'¥°°øµgûêý¿!û)ÛnpsÖnàln0æ Å!4 ¸1Àn0nB¸Á¸é¥B¸1Àn0nBhpcž=³¸Á¸A¡ñÀÍÀ ÆÀ B77#B77cB77ÉÓ�5ܤ~R;wîJ`óÜsËñ™gž�÷Þû@ê'uë­wÄo¼%^síõñÒË®n0nÐðdOæÕ§#4R¸IQ›gŸ}.5Ì|òɧWÀæî27ÞtKܼù†xåUׯK.½b¸pƒ1pƒPÜ ÑÃÍi§�Ÿx≸%«)©­qyykŠÞ<øàCñ�¶¬¤§fñ¾ûî�÷Üs_¼ë®{âõ×ßO>ùdàfÈÆÀM´ïŽL|Íûú䄯bZÿ¨Yv]}Ïzíä»N‡0±eùõºp3ºk7›7ožNŠÄ:�Íÿþïÿ7#0&r“ínl]‘ctbj‚LF²®×A¹ i íÖì­×¡€›Ñ]¸yüñÇãÓO?·mÛwìØ!Þ¹s§ýÏ£<»wïn†l Üh—çüÄã¿Ö÷ìh2™K:)ËzGUÀ ×êNÀÍà¦Î¸‘´@ˆM´BÓÚ ÌÆ± ÌÆ÷&VY¯/n¸6P×nÞÏnê��›&¤ ü×’F�ÉHÞó&0Y¯'n¸6Ð Ü` ÜØmÁ©."ÄPñë<€®)0•€“zð×CGVrÎÍ1#¸6n0nztK1âvs„€›[¶6p3cà77ÉÀ ÆÀ nn0nú)„n,55nÆ` Ü „pcž={¸Á¸A!àcàflB!àcà¦ÿB!àcÌÝR¨ƒs&O0n±;yh2ÛÉòõ›|šÇ÷¤cÜ`Œ�p3�Wò„dÝnb½ªLNo+¢> 7çܺ¸¹1pƒ€›Ùt’¢-ö÷¶k¦qbí#|¸¡ç Ü$7uÆÀM´g�LÓ á|™ lù¸Üعõ{AÙyw»ëþµ–ÙíF>[bš`×§7™Îäcn0nœp¾M@Ö!Z»9§ÉÁ~YonF7rn¥–Æ?ï6žÁƒ_ÛâˆI€F@Ǹ‹€›ÀM�1pÓXtfî‚ÎÏÎ/è! ¸ñS6MX�YaúGÆXüZˤ¤äu6âcc‡¦nz~½"àÆk´i)n,"c‘ÿsl ÜôQ!ܼèQcƒ‹ÌXÚ©"úccŒÙÀ BM¨¨�Ž¡wUqGêBÀ�Á‹ÿþPÓRuño'jÜt"zOõS!èy©CŸ ¬ÿæºBnœz›LJjéÓâ7½ùCÇPsãØXÚŠ¨ pÜ úóâ4¯l÷)Æ\W¸QˆÔ|Sÿ"7$Ž`´®¦¤q¦|–3æØ Ü4a̓ÙB£Ç4Hï!yô~®Ç�¤$¬C³Žoc‡0±´…�'½ˆd?šô¾½—"º_GVt/M+Ù¥¯:¯Î>宫ì¾g®·¾ 7ûWàæ¶R¸1VÜ(€c58––,ÜøÏ¼qoë¶6 DmˆÜd:Û¤aµ%Ý¡›`Ûø L^2^¦c´=æßööÕýªp“o�*�Q7!6>@•ŸWwŸt¹¿<7ç–Á�oŒ�›XV]Ð|6)åÞÓ‰Äk�ÔE vÊ#Õn4òa�Í©ˆÜmçì“nS²ÞØ…€Œ� K)ÕÁ�ÉÒ ¡n†7!6U57ùs[7þåŸ5~!àcঠ–�t�3Ù¸i)“-/Jèx:I7ÝÂÍÂ)œ¦ðn© ¸Ñ}òÇð×Cƒp“lµ7ÀÍâÆÀ�OB ‘IeIA±,—ôEü4�¤ì½öá†îÞfÜ\z'4åcè{¶¬nü}’ëÊÖCZ 78À ÆÝß ®‘–!Ü77M°_è!T)àf—Îì9à¦càÆÒØÔ‰ŒW0nj‚<0Q–˃ù´w²m‡P;ñ�Äèzõûð+oð×ÃÀ â Å!äŸ퀋¶ì«pÜøõ3.´¼!þP‚ ‹ãwsë|žçx¸Aô–j‚ÛWJÖA¸nZ޲Xhññ0pÓíÅ#ßtm©Yö!~¶ÉÀÜdÎyhümjYÀÍnâw¼òÃãÕÇm(÷¯~F[pc0bEÃöo§˜ØÜN¹Éwb6ر:Œû7D3Z¸™L3眔Z@À pãØ¶'jÓ®�íä]Ð<Õe�š¶Üs,ºÐô$%…pÓÿ´Ô¦_qî’²í-‚CÔ¦7ÚÑÛ&³¸‰¶é„´ÔèáÆy¿ !ÜìÜüÐ&¯&ÇCÆ!j³¸�M3è”Ã�Ψ~ÉSPœOE̶ž’B¸AZÊàÆ‰ÈXdÇùgϸÑâàIˆ¡$rÓ:‚VzÎÍ-ò^&EÈ"à¸)º[ÊÒNÑcøÆÜ ŽBÀÍîa¥¥œ¨‹«8Q›ñ¸A!àæŽÝÉ9ƒ¿¨ØÀÆÒVDm0pƒBÀM/Ú/8Í,µ®Æiœé|Q›ž¸A!à¸qžyãÞÖmmˆÚŒÌÀ B7ï1¸Ivàf(ƸA!àf�Ζeàcà!„€Œ�›~!„€›óóp“vdTÆ@I‹pƒ�=•¸µ‡>¯§Ë³_XBÀMœd…›‡q[pÜ d!O¦®“5U �.›–³BÀ�¸YÜÀ pƒ�õ³¿uÒ.âu'àfüžýAœLþ ΀›B7MX“B�ô’ a²¦”¦lÕürû_¾>êZÖõÛ"8–>*?ÿùóŽÊ¯ ígfÿž[G`LÆuö7shÙ·oߺ޳gOŸàf�7Í�iG8n´À!ŸµøçêD·áÇb“–Cz­Mþ½Éô L9/2ÞQƒ"7¹ÉÄ&�|ãDo¹m¯ ³¦ñæQ&$@£ ‹Ï¿3žªüšð®Ç\Çr]ÏÞ[g?p“æ+¾â+â—|É—$/--Å¿øÅ1„ÿöoÿ6½ß ¸1oY>”…›Ùô«uBM“­¾nB2 `Lä=ƒÅxÅ꯯¯ŽÓ™3¦íÛ|Ì´ºpÓ-Üh—ïLWpçWyér‹…ÆÞëI‡iRRòÚà¡øüûç¼òš°}ðºÔKÔF"�y‘›üÁŒ¯yÍkâoýÖoÅ“O>9^vÙe¹ÜL'iÂô @_¯þ�†ÕÉüý_¯�˜“WÇ—õlB· �¨FéØi¶ÜöÓÙÿYîsÓØ6¦ÅpãRvL…NÛ/} Üt76áHÚ¡m¸‘Éõ¨¥¥P£WMéøç¿¼æ¦îš(‡!np~í×~-ž~úéñ¦›n2°±š›þÃÍD&äB¸Yi�×6ѧ1ÝíRÊÅ� ,6¶-·È“7ùÏU¸ñSw%7^jÏÆ7(óÇnz7M°[u5M “IEZÊŸ-z€º”ž÷<œøçß7·Ôâׄ7~ U…€›gžy&nß¾]ІW@&ÍYg�%`3¸Y?-SºžNàb6¸);9Yn<ÆF¢B“›B€nz7ZÈ)·Ëd’ýµ¹¦ ´&B#¨{¶É€¥¦<ÿ~ѰAÔ¢×D9ÜØ¸ù´n–——SÄfLÄ{÷î�û÷ïOm™�ÍvŽÜÜY7A#õpãƒJ-Üèk/=T7Nä&—�!]W̸áVp„ênRÔÆ ¥À lŽ.ÜÜYQP¼6Õcë¹p£€šáF÷a᱃MúñŠÃuDÿëï¿|®Ÿ–’ÏNchíL‚ƒ-ÎDl Ǥ ¸A¡à&¥šÖ�û+>Êp³×‡œL½ˆ.Ÿ„+‰ÜäÓGÛ5A Š[k^lŒ¢ý—ÏuáF>ۉ̠䷑ývÆäVpà!„:€›õ&¥£ìoν„ÌCü0pƒn V|÷ nÌÀ pƒ�“ !Üü?ûöcKEaxÅŒùlÛ¶mÛ¶mÛ¶m۶Ѷmì©�´*|m­›|ÁuEõi¤$@*ÆM4sÜd0Ä(I:ˆˆ(R,n¼�¸9ûÎ_ÅNtÜDÖx ¢üÈ"¹ñ�dÃò/~“¿ñ«á—EDT¾z}™±`… ™f¶héJù;Kv©X±¢Ô­[Wš5kö­]»vW»té²·W¯^K8Âx´7n\åÉ“'çŸ1cÆosæÌÁ‚ °hÑ",]ºË—/ÇŠ+ ¡_Û¶mÓÁ—/_`ìßADDD2ÆÍû¤ˆ"*€,’ÿJNü%8Y Yð{Š""ªÙ¸­lÚ}Tf®7Û{ð˜dÉ™WêÔ©#­ZµzÖµk×�ýû÷Ÿ0lذ.4Ó¦MûoÞ¼y1X½z56nܨA‚Ý»wcß¾}8xð >Œ£G�ê L¼iƒ}ú_óçÏ×™lÞ¼{÷îÕÁ¹sçpõêUܾ}>ÄÓ§OñâÅ ¼yóoß¾Õ¥¥xûò勆�.I!44‘‘‘É77Ñ7”H •Ÿˆ(•t8N>ØzÉÙ7f®>’¯hiéÞ½ûÆÑ£G7˜5kÖOºÄ¤345'NœÀåË—qïÞ=<{öLƒ_¿~…�� áââxyyi Ä›.EjØè¬M²ÇMÆ Qz×}رt•«_ͼÂ¥@±²Ò»wï…&L(­36ëÖ­ƒvÁ‘#GpáÂܹsÏŸ?‡†�……ìííáææoooǺaœœÒ8ÑÍÀñ¦A5JDR"n7DDDéœÞÃm¼"亅™o°ˆÞûûôé3wâĉÅ.\ˆ 6`×®]Ð¥¨K—.Agm^¾|‰OŸ>AÂÉÉ žžžðóóCPP¢÷ʤÆ ã†q£üÅ‚qCDD”n1n‚Ìq£,ÜB7éÝoùÅ«HáXyóH d1½§N£urbÖaÃLéýZ¦ÐRæéu«®-üs~‘ÿÙ;7Ï0Žd|ŒU[5VìX¢hY Îj Š™s¨ÐAP'…�ÒEÕ•¬Kvnà0l[Õå Aa—õ¸gñÅ#9ÿ»<óÞãí÷½÷?~´.ß—'ï‡çwÏó¼ozݪ<ü,ñµ"„Pn(7wåùkyýTî�9A>�—pèóž<¿}Ê};býŒß…ë<¸÷xODàsLl–ÈMíϵ½ýTFžEx¬7¥y&8íÚiÏï¢tº™|«ë“ÿQn.ËÃ);„ÊMrrÓ$y÷¥É)¾ÜرNn>‘'+3¡ùù£ãqabÿIšW�ÅQe7¢hÇzµ!Ï– ^=“a·’Ó[»¼(7 ¿£ÜB(7…”›ü#/ ¹1’Ix’׊ &!­�@â<À{úƒ G¹ÑdÙ©Ÿñ^Ù§òûu¨Ô@;ÊlÉØkkˆÍŽ´ü¥Ï)V\‹g_Ü4ÚQ¹ä(ø¬!„rS<¹QâË��œZŸèr£¦‰[%§\rUaˆßªsˆÕ®Þ «kÕ™Ø|wO!”›ÒÉ�]Éð—Hš/n•&ýÑûÛU ­ Pn¾ºr-oGׯɓìc�µÑª�¯0¨øéú  —¿Ü ߬Ÿ½�¹¨Ú(‹ó8ʹõ¨*_n~ ȇRÓ×BHârC¹ÑÄ‚¡R¡mŽ ¹ÁxftT†4¾²Ê�¶a4‘» ¾¾,r£Â‡­©z¦ó68P ÏÌ–åÎçBå&šÜ({obË�&(Ø!U£=×£( &B½^«1 ø”²-¥U ”ˆðµÅ5Ò£4ºÊM@¬ÆûßoHÖÌo+ø�¯³™à<º 7XÁ!„PnÒ•c+¸Vl|vXÙí/½¯ÑÏW^¹Ñyœ/qX[ñœËrˆÕ8÷&‚ÜÌ«:™ÜZ¡ÜB(7ÉË Š…ŠŽ� °…„¹ckÉü,ƒ –Çç6f8ìÙŽp¹±’¸ÃÚkå°Ü!V%@ú+5å†B¹I_n;˜ø¬yÄØa…篘c>Ç®0%'7°¶†80_ŒX£ÉM­‰37”BåæœÉMk ];&FhAÅ—›(m©ørk‹³QÆ6ú"mG¹ñ«Ö4/±-Ey/PnŽä—?¢É�±ÅÚí=°Í…Nâ37k‹Õ7ÿõr‹Uñ–>•Ü_n!”ÊÍD'²Ü@ëÀc«¯ T4Ñé}ÂI{·TÀÚêzheÆ}»¶C¬»¥œ†ãË !„rC¹™ Î�ŸÜàë–Æ·d‹6\§mŽ%çâ@Lz üEKcHPnìsnBׇЭgˆÒe†C¬Æ97nó6Ð’Z¹ «›UÇ™B¡Üä�‡Ãå¦ÿ×Ln”Ñ›Cûëìù[n01ÚÛyQTÌ3N0ã'a¹±O([[û:|†Ð2¥Ë'Vã„â@Pb�LV#Vn!”›ßåfww÷˜ÜŒÇãbÉÍþþþ‰r³±±1—›¿ÿÍgJ|¹Á×X÷ÂÄ 'p.‹�êwKù¯­ †Ã÷;ùÇêÒ’.É�Í*žJ̶!„rÓétN“›Ü!J+7ƒ\n¦ Ü$Áo��ýÍÜé¿7!„Pn(7Ĭޤ‹CňB(7¥š¹y›ËÍ»)óÖå&Ypö&~bÇy­"E—*˜µIBåfNøÌMévK½�ɯ¯ÞÍgÊh|®ä†í)œè’¥‚U¨Pª!„rSÆ­àý~¿²µµE¹!„rN¡Ü¬¯¯¿(7Ýn·Òëõ*ÛÛÛKåf2™[nÚíö‚ÜÊàÕLn”›ÿ!„�ÿØ»‹øÆ�(ŽãS8öVæÞÊŒ÷[¹=•™™™q™™™)ÌYf oLá…0Ô–ÙSÿŸSÉŠYQT¹�÷]Þ•F‰~Ÿ'Hq38"nÆ�—�qÓÚÚÊ, «ªªJ7%V?/†á Nóÿ"nAAÄÍܹscâ FЦ�›ýû÷³¢¢"º¶öÇDÅM q>néðY+¶açdAAæ¬ÊáöÞP¸yíµ×¾ùꫯn˜0aÅÍŠ+Ø–-[Xii)>ÊŽ¸±Z­¬ººš8p€ªlåÊ•lüøñÃqÃ7ªéÍ¡v?.O‘…ƒøëŽÇKìñÄוœ-•ÎTÜIÜz6}6èw¬.7m ¶×A¼á}˜ª�?¢ÏÏ[H€·BP¥ L¨?»´¦ë ÃÚ�^‚µ¬¥LuLǧt¥Ï®‡îT¼†rÈ|™é+~Mšt!8Rò� ýêï+z#š£õTZdÁˆ~µÖQBØ=�8nÞ|ó;ùæ›ë&NœÈæÍ›G]°uëVVVV†«<ˆ`0B qöìYЧÓiž¸ioog6›�ÕÔÔ°ƒ²òòr¶víZ6yòdv÷Ýwó…Ë×ð}­Á˜ÀÁå)Õûo@þúSRbu.žÃÉój�nˆ!qCT�£DζáÀÉ oK^x»óÃû« Þ>AºxQƒÄ‹)p<¼Ä œ2 ¿:pÀã¸qJÜÅ ÈqŠ›èÀ¡ˆ9¦µ¤8@q38EN-I3pÀ q¦Œ7ºDŽ*jbã½²b‹WŽUà€qƒÉ9Îù=ôPó‡~øèÏ?ÿ|þ´iÓØ¢E‹hè‘——Ç*++iR[[Kƒ4DWW—ù⦣£ƒ555±úúzväȶsçNª3lÌgŸ}öÆS‹Ã%W×ä%8~RlQ&8ê¯=jDN¦SœjE‚¸QT&8ˆ›�ƒHÑ#n€â¦ŸçDN]TàœŒN ¦7Q�c³Æ ü7ㆠn åô#þ‰«¸!úÅ ¤Š£&8 a‚cÞ¸‘£�[fXÜÔK8 Ä ø4Îè#§¾+DçzœóŸ~ú鵸™÷ÞΜ9“2Z¿~=ÞƒG�€A"‡ƒq388HqãõzÍ7§OŸÆë“é‘.<Ú…» ñÄÔªU«Ø”)SØ»ï¾ûÂ¥W^K� ÎþV%p€‡â†¤8�0prLq´ކ)Nq£)rt‰›8�SK�uyJJ|yJ7"pô�Yà`=°.é_žóÇ�öËT`θcâFLpŒ�â&Ñ%ªB@ÜÈ—¥F jTt œƒí4±¡s<ÎõO>ùä 6~üñÇ &Mš$ßoƒ'¥ð¿Ý»wËo'Æ` ÑÓÓCq#Ióù|,°P(ôïÆ njkk£kg¸A×Òpß îŠÆô��!pPsW-\¶OP)Ü!>W05)¾~Íúq�%?ïËP¿,KR Õ~Æ)~sssa}}}Ç%?+++¿,///--ýŠÅÅÅßB!„ÐY-·WWW^[[ÛÓ�‘íûûûߺÀ׆”Ü÷ÎdUm¬€sƒº™˜3Œ-)ó6%6ÿ»Ü˜p¶Æ¥5eò™‘ÝßßO††˜cÓocpÇÇÇ“£ƒƒƒoì¿8r ;;;?(eakkë§ž„B¡òZ~ïíí}GjlF)bÈyb£eýÛˆŠË}97¨-)ÎP+àCÕ¦‡Ü0.æõüüð»!„B�Ù²[†Ër™.Ûe¼¬—ù%6\€¸2¦fm8Ã߉gVÀ[È ãªê�÷!¼ðisJéÉpq ޲”¾› þ.//Íâ°»éüü|:;;óö„ª¦ÓÓSøÝŒB!ÈlÙ-Ãe¹L—í2^ÖËü.À ¸A½>Vm:µ¤À¸˜—içéåå¥ÚSÖ¼| [SŽ2%mȘÉMWWWZU¶©†–•ƒëóð¦ÿ›B!„ÊkÙ-Ãe¹L—í2^ÖË|Ùϸ'¨vWà CÕ¦—Ü0.æõþþn0ÈZ׌àhQ™Á1HÄà|°©iVwss3]__;%,ý9Ô”B!Èj™-»e¸,—é²]ÆËz™/ûG±©§8ÃPµÑ’ê#7ŒË”³×<•˜^__Kp”ŸLEO���Öt+¡ö"¨»p‚²•‹}˜Ü`Ø”B!T^Ën.Ëeºl—ñ²^æË~ÀJl8Wà Ü¡cÕþ¨Qp ù;ìÖ½\±¬×æCYœ‰iï2h¹ÕØ¡°=Ï7ô$„B²ZfËn.Ëeºl—ñ²^æË~À87øPl:Umà�ú‡àT‹J_ÍÕÊn0vͲeqOOO%:ìγ E  ~÷"„B2[vËðÙ.ãe½Ì—ý€ T+ª½Øþ¨QpjÇÀ�TI޲”°/‚:†§'ç``~÷"„B2[vËpY^B#ãe}I à5có‘Ø´“Ì(8„L@3´’å(j·ÝX‰Ž’ôä ƒGð»!„B¨ü.¡‘í2^ÖËü’.À ¸Ak±åf“Ï3Uë^úl>TiŠÉÙq׃ƒÃ`y¦5!„B�Ù²»r\¦Ëv/ëe¾ìŸ©ÖpƒÎb3ÊÍ(8cLJ±¶øp8°¼þ„B•ß²¼d¦„FæËþ±ZÓ^l ÿøãþMrØÚ(:%;…²•CéM!„dvåwÉÌ(4²ÿ©é-6¨g”øØ¢„çË$„B%2(¡¥Ÿ�š^rƒ�*9£ìÀÇÙ„BA¦�2óÉJM¹ù/ÂþõB!9ÿYÚÈÐ_rWÀ[]5çðIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/animation.gif000066400000000000000000001654101526573132500272040ustar00rootroot00000000000000GIF89a�äçÿ  &!(%: %57  5'7,1#J?%& I/ $C1>74B> : $41 (U80 U_W4"a<`e5[ 'c,(*l+"!X%((0I!%,22%W;*O#* 6d$73uP&E|"L&Zš" =|q)A9].;…];4;€R<2+>’j8LA>>w`>K@Iˆ9 =N!‚@á&&€Gï&$&Vœd7FP€brbQz‡J[YY\;Z«c\FfU†>_ž"g¦kb $oa`[y£ME€a0wciRošY#Žb‘^,=lœ2mºcd�·T?ainPl‹qff_kw©ehqa‹eŠxp„²mÅeFS�H—F“6©sbM„Ð�u<ŠÏP‡³”w�9ŽÂ¤u•ƒˆŠ†ˆ…ÐyV¤…aº�Ne””w›*�†s‘ ¡”„�žD®•žY›Ô°”#[®$Æ‘{�{_ŸÌg�ÏÀ�K§� —�TmŸ¼ÕŠ`Ú‘3ÀžÚŽy‹ ¿o¨ç¦¦¡Ø K€¬à«ªj¸á˜±º§®·u·õ†µâ墎ӳ2€¿ðÙ°‚ä®”í²eŠÃ䷻˰¾ÏùµX…Éõç·• ÆÓí¼}�ÏòœËù¦Ëìç–ÂÈËÆÈÄûÅv±ÑïâÍ—”Úþë̉±ÖùºÖí·×õÖÕ¿¶Ûþ°ßíßÙ¡èÚ†¼ÜúÔÚÉÖÚ×¾ÞüýØÔÛÞçÝ•ÿ׊ÛݼÖÛë÷Ü€âÞ¯üÚ‹Äàø¥íâºçåÛßïÌäöÓã÷ýáœÒæÿèé«àéÃàåõäæâßéÞ·òþÚêþÁõãåêíÙïßßëùéêôäíöâîüäñÿºþúûô£ïñîëóüñóïÜýáï÷ÿò÷úûúÉýü·ûý¾îþÝîþãêÿþüýæÿþàøýÿûÿîýÿüÿÿÿ!ÿ NETSCAPE2.0!ù ÿ,�äþÿ (£ Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç� CŠI²¤I‰S”q‹ŸË—0cÊœI³¦Í›8sêÜYSžÏŸ@ƒ J´¨Ñ¡óŽ*]Ê´©Ó§P£J�JµªU¦ó²jÝʵ«×¯`ÊåÊsÞš±h³ÊI;¶ Û·l“ð»UPå?·Þ�ËÆ·¯ß¿€ûjL¸°áÈ ^ü·0ãÇ�W›L¹²åjË2gFƹ³çÏ CFº´éÓ¨S—¶˜ë×°c³NM¬¶mb¢sëÞÍ»·ïßÀ?kN¼¸ñãÈ“Î|´êçÐI3lºôêØ³kßν:²Ë€þ˳2/�ùóèÓ«Gÿníú÷ðßU·j•¬ûøóëßÏ¿ÿþaIÈ£Ž<·°�KêDÖ˜`‰5èàƒF˜˜‚ ^fádÅ5Ç[tF7›l ¾&ŒkªÝV›†(¦¨âŠ�)çâ‹0Ç¢oÖh/ÖáX�0ÝõècvßY^aã•ß‘éµg$’HÊG_}PF)å”TVY%€òŒ3Î;t $Ã;ò5˜˜†i¦a‘I蘙”ñuáeÎèœ�t’â�²•h"nröéçŒ1*¨‹†V§�¼àXv<þèèvA¶Ù‘ä1i©’–69Ÿ•œvêi}Xj9Ž<2tË^ff3á^¢¶êê«þ°Æ*묳’‰fdoæ§Ÿ‡Ö‰ç¯°éib¡ÄÜ È&»Œ±� ƒL¯Ñ%*­0‰V§ã£Ør&䤃�÷N¦Lº—žV”kî¹r|£îºéT1Ì)ðÆ+ï¼ð’[®§Øk¾ô®B/¼Ð(ª:]Ê Oªˆõåê9 7ìðÃG,ñÄ7쪭cJ–«…Æý -�À†,"j{žÈìÉ(·¨ìÊ0¦üìǪI+óÌØÖ¬í¶~ukE:ëöìóÏ@§³ÖÏVØd…º sN»ïþëô)E»´oÔüXñô¿g©å9¤þ#?ŒqÍØk¶ZñÙh§­ö9¢ªªX`s¼¯0w(²È#ÎFòþž.÷M,Ë€šrÝ7’6óáÕÖìèÍ’66^:cG.y4ØDŽÍå“G.4ä“S=“™£S4›”nú騗NîKTï›úë¦OƒÖZòSê׋½"Çî¼÷þŠ6|™ ±:ko|Å¢®ùWÜ•í*'áÞ-ýȧ•Ì§ßØËøö½áˆ‡�ݵŠéd�ͳsæì·/ù7rp.yÔç–+uæßŒûþ›¬“ëüK�,f×*Ûy l�¹Eï(‡[okS‡'HÁ Zð‚Ì`Ѧ%·0ÌÃÌÜèö½ÔLï„$ÚÛ°²ÇÂqï…šqY ©¾CZåÓãÐ÷õ}Ã}þ@Ä_ü2gw¸t‘+âñ§¿¾Ž\F<¢œ(ÀÙeCTÄ]`ä7¬a ^ŒÃã á1 –¡Á6Nj¨…ÁA5²Ñ�<cá°¶½­/!t‹f¨Ro¥±^ ©!:Ò{Ðã0jHÉ&î†åÛa5zºWxò“º«_ýäJOFCØ(å+¬pX”¬t¥*£A�S|á–jÈ¥.wÉK5T!–®¬B/‡©Ë[nâÃâí}%¡\Ï´BäpEž†: a uœ�„£¡A�Tl“r'÷ø°þÑM䊉šCÚSX·þa¤>ãÈ~ž z¬‘Ö$)IPáPqçãd4T¹J£ÍÒ ©,e,EÙÊW–’–¶¼åˆÙË_¶ò£V&G‹©Ñc¬šYd¦_N™„–Âà™/MBP)ª†á Ù˜ zÔYAqÂÑœ ×NÄ�1>m“Ü{f¹�+�_Ö«�æM’Ò 2u«{Ýì–R_¢Ü×,Q©J$‹’”5ÁyéªK:XùÊXþe¹ª@-‡Ë`îåŽ9�Œö/ÑÀEþ0ÐR6'�mN.û؆Í�é ¬yRKÇ4¦1ö3Ìà ·¶‚Nôkmá8¾Q |d'o?Èæ!už/~nŒ‹kÜãÚ8¹8Î1‹LÆRódÐ ²ª/Ù#Ï´ék(+Cg=ëïÒúÖQ^˜wÍë^ûÚ×§0A™Çt敪ù°&ALe 9ÓÙat°žÓÁgÓRpÁÑNp¡ŠhF{{Š^†£çi=B:yFÅ�[œÔoúÝÔ{*T?]ãP³¬OW½Ìºê~S·2ïpC4‚�ë‚¿â”ß08®£Q…iâá�xÄ1AñŠ[üâ˜�¸Æ¾‰U»0ÅîKšþ× ˜ šÒ<9.ÀaM\Á^cž%‹à«�§=§ õþj"!©’3”Ö B·Â bÈö5 –ø ¸`‰Ó Ñ ¯â† ¨6£bM‡"βux‡ªØiV·‡-Ô‡‚¢c§f#$r„ƒ¨j;bˆ•‰ø ‹Èˆ“!dʆuÇ‹Žq C+ #+ÌЇÊ#‡sØ™cª˜�©wU®ÈB°(²8‹5r'·¨„¹ˆLÈCˆØ‹ò‹à ‡ñˆ�øGƒ1‰Ü²& ò@Ñ+�q1÷!‹ai¦˜iÙX�=˜‡zØ�‹ô�à8#܈="å(v× -Ò8ŒÁŽíèŽh"ŒÃ8€ï¤ ö�ʈ1y’6�–V�ÁA�þ“)T=ó¦�ÞÈ�/‚o¢á+9‘„¸#�b‘b…Œ(©*îH’TYÓ8’)©’(¹‘G ,ö¥�Šñ'“2ÉŠùd“7‰“‚C„â¬">ù“çèj™‘i”+ù‹Š�KIÊc�)™0S™—¸O.I#׈�Z©•\ùƒ^Ù7`Ù2b‰jäx–]Å(<¢–긎½(&z™”À#—s¹&¨^Ø™žù™ ‰…:•߃¦9A SA¡¸š¬Ùš xš°›²9›´Y›¶©N®™›hƒG¡Ù›¾ù›àr$ŽrãÆyœÈ™œÊ¹œÌÙœÎùœÐ�Ò9�ÔY�Öy�Ø™�Úþ¹�ÜÙ�Þù�àžâ9žäYžæyžÍy é€}ZÄÇðŸò9ŸôYŸöyŸø™Ÿú¹ŸüÙŸþùŸ : Z ñéëiŒDiïi ú ¡:¡Z¡z¡š¡ÊÚ„õ¸LpV8¢$Z¢&z¢(š¢*º¢,Ú¢.ú¢0£2:£4Z£6z£bÁ¡éà¡" ¢c"¢8¤B:¤DZ¤Fz¤Hš¤Jº¤Lz£:Ê£)¥÷›TZ¥Vz¥Xš¥Zº¥\Ú¥^ú¥`¦b:¦dZ¦fz¦hÚ™óС¥„pè§r:§tZ§vz§xš§zº§|Ú§~ú§€¨‚:¨þ„Z¨†z¨ˆš¨Šº¨ŒÚ¨Žú¨�©’z§kº£mꣃ§wz ~v Š  �Ú –õxsÚ   *ª‚ªZ §§0h¡ú¨œšFžÊ§«*©¨Êªè°«uê«“¬Â:¬ÄZ¬Æz¬Èš¬Z©t香*pì# P Ñ ©DØš­Ùj p­™Ã­Þ ભ‘b‘óáJ®ê*­Ôj­ßÚ­â ¯ê:¯“3®cc¯’ƒ¯ôº¯üÚ¯þú¯°;°[°{°›°A„l:Ϊ ×>  K¯Ó ¯“s±áª±óÊ®Ñp±Ôš°ë>˱9&û±‹²+{þ².û²0³2;³4[³6›­ k©‹© ­™3  ’ƒ `«Ã`Y©p´ƱDûg*+i$´êš²iV´ZЭkYµE®G{­æÊ´E·€®*{­75µA;´a ´›¥µ{±PRÛ´W›´H;µ ¶¶ú¶3eµ7û·€¸‚;¸„[¸üš [ óÀ³w9Žû¸J› Ø ±Ø€ ZbŽ‹¹—ó¶å„  š @ •+¶�[º¦;¹¥z @+¹jðx|+¹§»—ãªØ ’ûº•{¹¢‹ 2 µë»²{º‘;¹Ýš»”{¼Xëa£«º�Ûº© ¹Á{ºlëgK[¼–þ˹P Ÿ½ÜÛ½Þû½à¾â;¾ä[¾æ{¾è›¾ê»¾ìÛ¾î[ºˆ«³ŠË¸¼D› M»YD ¼û»¹Ý ª·0» [¼”û½ì¹P Ä;À ,¾7õ Up»ÿ¶jtS r »á{¿ù«FÈ+Á ¬±¼Àý¾L ¸[»ü¾0Ã2<Ã4\Ã6|Ã8œÃà¿•±¸ ú¦õ¼j «ü¸Î;»®û¿ PĶÂà{À%üºü½ÃP¬À$¼ÄŽ[Å© ¯·�Àä;Äì¸NŒ»$,Æ|Ä\¼þ‹¿ZüƔ۵:\Çv|ÇxœÇz¼Ç|Œ ü5…Ѹ§{ ’{´Z´Àkċ쪜+¹ìÄmÌÁ«[»IÜÀâÛºÀ˹‹\»½[»VÐÉÝkÈØ€ÈŠlÆœÊ#œ¼¬ûxŽK»“ŒÊ ´²|ÊeÜǸœËº¼Ë¼ÜË4üÇ“Èü0ÈA\ºÓ+ºž¶P[bË̪[¼ù+ üĥ껱U·”ÛºÈ ¾Û;Íù+ºÛÛͬµ—óÍ–,ºÚŒÆÖµÝêÌOìÆÞ¬Ì|kæËö|ÏøœÏúœË'¿ÂLÌÅÐ=Ð]Ð}Ð�Ð À }ÐÛÐÑ=Ñ]Ñ}Ñ�ѽÑ�ÐýÜÃôÛÑ"=Ò$ÑC¼ $�þª©PÒ,ÝÒ.ýÒ0Ó2=ÓýÑ€Ò4�Ó:�Ћ'¶%­Ò;ÔB=ÔD]ÔF½Ñ6Ìu÷¬GÝÔNýÔPÕR=ÕT]Õë¬7�}bpVÝÕ^ýÕ`Öb=ÖF�ÕJ­Õªp®°ÖlÝÖnýÖp×r=×t]×v}×x�×z½×|Ý×~ý׀؂=Ø„]؆}؈�ØŠ½ØŒ-׉+Ìdp0Ù”]Ù–}Ù˜�Ùš½ÙœÝÙžýÙ Ú¢=Ú¤]Ú¦}Ú¨�Úª½Ú¬ÝÚ®ýÚ°Û²=Û´­Ù�M_@\Ûº½Û¼ÝÛ¾ýÛÀÜÂ=ÜÄ]ÜÆÜ·ýÃÏzÜÌÝÜÎýÜÐÝÒþ=ÝÔ]ݳ�Ü‚œÛÖ½ÝÜÝÝÞýÝàÞâíÜØ­R’=Þè�Þê½ÞìÝÞî}Üå�*×åï]ßö}ßø�ßú�ÞñÝç½ßà>à^à¦ßôß¾à Þàþàâ�¸)Õ6 á~ážáÛJÕ0á¨Rá>â$^â&¾á>¾Lò-â'þâ0ã2þÞ)® +ŽÖó=ã:¾ã<ÞãÔ]ã=Šã.îãD^äF~ä¬ ä!7äHÞäNþäPŽJÎâ¢ÂäQ~åXžå&>åÔ*V®å`æb^à\þ5^Nßcžæj¾æúíïÀžüpæl>çt^çþæ jæUŽæþvÞç~þçÌíæp.ç€^è†~èµíæâZòåˆþè�é›­ènÃè[Âç’žéš¾é“Mé|aéŽÎé¢>êlîéÙ�R(v餾ê¬^ç¦ê˜Þê²>ëX.è•Nå�ë´¾ë¼^ä¶®*¨Þ0ò ë½^ìÆã¿~êËä0Ã~ìÎþì[Žçz@êÐ~íØà‚žçü°[\CìÙîâžßÛ>í_Ãìà>îê¾îê]îA~îžîì>ïôÎÝîì Óìõ¾ïü¾Ý÷¾ìñÞï?ðÏýïÔðŸð �ÜÒþîÝŽð ñÝ �ïß>ñŸñIŽçÀðù.ïò"ŸÙ¶nþîÿñ#Ÿò*oÛ`Ò¯ï+ó+¯èôò /ó8¯ð¯îñŸó>Ÿñn.ß6ÿóD/ñA�*C_ôJOðG_;<óKõõÞôóuð(/õX?ïTŸôYßõâîóP@Oó^_ö´ô “R¨ õfßöÅö£öÄÓón_÷¼÷i¿LsO÷vß÷­Ž÷ #÷Äö~_øœøç øBö†ßø€ŽøŠOøŽ?ù‡ùz?A’Oùšïç–@”ù›úsÞù_óùŒ/ú¨Ÿå¤Ï¦Ÿú®?úó÷—?ø§ÿú¶ä«ßú·¿ûZî2A‘_û¼?ü3îûüÄŸüNöÇ?û‹þ¯üÐoäÌüÎúÑý'>ý„üØßý2®ýêÀýÞ?þ[>Íïù˜/üä¿þþ)õ´¦ì?ÿnüÔ@O(AòOÿüÿàö¿ý!㟠~ï ¾›çÃB† >„QâDŠ-^ĘQãFŽ=~RäH’%MžD™RåJ–ÝÌSS?�"TØRçNž=}þTèP¢E�})óÍ�&<UêTªU­^ÅšUëʤ™ÚôšsëX²eÍžE›V­Ô—7¿:5ÈOìZºuíÞÅ›WoѶ^kÂ]:wï`Â… FœÖ à·n'†YòdÊ•7.vû×±eÎ�=þ]³ß¦›CŸF�Zõj–£ãjËZölÚµm»^ ;îcÛ½}ÿ¾÷Ûy±ƒGž\9Öáå=—'wùtêÕ­så7Oû¼·Ð¹ó¾^üxò oçîºôòíÝ¿G~~{÷õàáßÇŸŸóùõꟳ×/@;mŠ!—\sÑ)ƒ;aw1=u:97ÛsÓQW=vÕJ7ØeÇ4Ú;=wß-Û�—Þ'>²à‡/>yÃŽ]yç·bþyé ‹~zë=eíšæ9[øæ¯Ÿ¯ì]çýûðÏGjüí»G}÷]U îÏnÿ}ûÙŠ_†ùË¿¿«ª÷_5”¿ýyO€_÷þÈg@60} \ýÌç@ ^€Ä J.˜A–dƒ!H>B^†€ì›` 38B¶[” ]8C žP‚4ÄáDX˜Cî�‡3ôá[D!–�ˆE á‘ØA%.q…6äŸ{EJˆT¬Ÿ™ˆÅj1|Mô"ÁFŽ‘Œþ3ãï—F5¾��mDßáøE.Îq‹0ÔŸ íøD<0‹{DcYA9òy…4¤ò™Èâ-’‘¿C0ZÁ(>²Œe“¤öbxCK^Ra“Üd%;Ù¿™mL~ìâ(G÷/�Q²Šª´+�qJ=Â2–çPX+CùJ[Æ—¹¤%'{þé>YS”äc.géÊ?"S‘¿Ôe…éLð“™©¤¦á¬¹Ëff’¸ÔÖ2¹‰Moîí^Ú2&/Ëé¼q¡óšë´^;6NxNOžéìf=UwÏwê“�àt'=ýùÌwÍSšÇ¨ïø)Єo¡UgCe÷PTJÔ¡Ùz×óiQÆÉS£ää(Ô<ÚÏ�N£…èFK8ŠÖr¥©ké4_*ºŸ �©ÏjŠ/’æTs;EiE}JSuØ´§C�\M/eP¡"•r5­šAåáR§.ªÈ�*U«ªÍFU­\dÒêVg)bÃNa«Þ^E$´¦•nk…R[ÝÚ6¸‚U¦s­Û�¼úþÕ©Þ¯nÓ«´ìŠÐ¿ÒU{=«_ +¶Àæ*®Š],×>eV¶B6²W«k_ {Y¬eV®œ]šg- Z¥‰v³¤ m£+�OFµ©˜�réÚ×-³ÊTimSvÛ\æV·"ã­Â|û[�×v8%®³Œ;Üäl¹Èmn±žÝÒªÖ±dÂ-t©k/ëò5»Û%ÚtÁ«Óîʶ·Ú¯¬Ä›^™­—½*sï{G_ùnŒ¾õ�Ø}ñëÜòé»ûn¡ô_WÀØ=o�í{`Ö&XÁùe0�\0ýNX]™ çq-Ìߨ)ÃÌÝðÁüaô†xP'ˆM¬Þ¿KÅ+fW£ÎÅ×þ‚¾Æ¥ÂÒuåQãß8O9æ+1\ÜcË Èv*«¶l\dNŠLeò’™L)'S ÊŠ›²¿dü((A™XÎòªªìe0‡™Tc¾2‘ÍÜ%4—µÌknò–ÛÔå4ùYmþ²šíÌ49#¹Î{&žß è•õ™HdÖ3¡yTedüYÑ´b´£ÍbGÍ™g’žtŒ+}27':Ó>24Ò=èOë‰Ñ—Ês©µ¼i¡±MÕ£:õÐ^�ãP;MÖ³†u­å±5\w*Ö®îõ¤~Mê`“L×¼.¶°�mµdšÕ¢v³O¼ì[K›cÔŽ¶µ%†mbk;IÃö´·nq'jÌÌ.÷�u½×nþ§ÛEmζ»ÓïvËÔÏ~rYãmo£­[ßõæ·×üÝé€çlà©.xœî„�gá ÚÁñ=œâÆÆ·• ~ñ~gÑïx–è¼q�WÉâ%§ÒÉQþm‰3|åkjùËùìqLËüÝ1·ùÌpžs©íœçKòùÏï-ò|“\èCçrÑ~t¤[ZãKgzˆTõM�ê²úÕ¯t­o�æFïº×‰þô‰‡½:Y7ûÛ¸žvµêlgÚ᮹Ï?u·;|ðžw÷ì�ïåñûß¾vÁ¿'ð…¿ÎávÂ/ž<ŸrúÇŸÌJ~ò†g°å/o·Ì×|ó⩼ç?ŸøÎƒþ}ô|+ýÛOOú�\õ«g|ë•^vØW.õ´¯½înïòÜë%ô¦ï½r~ÿúàÇg÷Å�ýj5�|˜Ëžìn@@ô¥?}êWßú×Ç~öµ¿}îwßûßøÅ?~ò—ßüçGúÕ¿~ö·ßýï‡üå�ýáçhþ÷Çþõ¿þ÷ßÿÿÀÀô¿úƒ>DÀTÀdÀtÀ„À„?”À ´À ÄÀ ÔÀ äÀ¤Àè“9èÀ$Á4ÁDÁÀD€TÁ„Á”Á¤A dA¬ÁÔÁäÁôAð»AüÁ!$Â"4Â#ÌÀ DÂ%dÂ&ôÁ€B€ÂpÂùSþÂ*ÄÂ,Ô¤Â-œÀÝ“>ôÂ1$Ã2LÀ.4Cõ»Â4dÃ6tÃ÷CÃ7$¿5”Ã:´Ã;Ô¾8ÄCï£Ã=ôÃ?tC=ÄìˬFë´0ÂATÄEÔBAdDê+DC´?LÄG´ÄKBGÄÄHUÔX�HZÕRL NXµÎ[•QP5Öc5LQÕQ åR1eV!uN pVi5IÁdQëDQj�ÈKÅÒmERÛœNî|Ö/ÕVuÖ_]Ó5]pEWNEÖw…W¼TÖætMG…Ô¥Ò mWþ…N~mUŒlÔÀP~½Ô …Qí,QH\u‡F%ÐÝô×Ö4Ñ>ÖŠíÏPX†ÍxåØŽýJ~ÀÊyµIV}ÉNÅK“õØ”UÙ›W¸Qç«´:½I5`R­M”]ÙœÕY˜,Eý”É P›ÄY¸Ú�5Ú£íH�u¥�Èž•Ù·,Z·ŒZ¤¥Úª•È–u¬mZ}¼Ÿ…Ú›µÚ°Û”L̲œÚ¹Û´UÛŠTÚ¶ Y®]M¢Ûµ¥Û´ÅZpx…¬uÙ­…YЬۿÜÀ=ɲÜÂ5ÜÃÍÅ[pƒÅeÜÆuÜÇ…ÜÈ•ÜÉ¥ÜʵÜËÅÜÌÕÜÍåÜÎõÜÏÝÐÝÑ%ÝþÒ5ÝÓEÝÔUÝÕe]ɽ`ѱ�Ñ™ ÝÚµÝÛÅÝÜÕÝÝåÝÞõÝÝ=‡àÞá%Þâ5ÞãEÞäUÞåeÞæýÝç…Þè•^émÞêµÞëÅÞìÕÞíåÞîõÞïýÞéßè=‡l�½[0ß�˜ õuß÷õ²ø•ßù¥ßúµßù}ßüµß‚eòßÿU¦îà&à6àFà`…áßüuà†à–à ¦`÷­š$+¨ÖRà æàö`áá&á6áFáVáf`þü­à–áKɆ[ˆ�è.õeß™áûõáâø¥àýÍàöà#Fâ$>›ÇY›½šþá'†â(†`/+b%¶â+N`Öâ-æâ.öâ/àþuam‘_)6ã÷U‡ˆ[‡üÝa–á –ã9.ã!&âw1b,Öã=þœwAµ3ä@Žáø-âLâãCVb0VäEfäFîâ1~á:d(þ‡Kþ¸uH_÷}cʬ`:e:¶cúuaFäTîàöãIvåW†_*Æc VåZF`GÆå\Öe\î_&.(I†å Îu¸ÀdL–¸…aæfvæg†æh–æi¦æj¶ækÆfï@�mæænöæoçpÞffž‡l6çsFçt¦fqfçvvgíPçx–çy¦çz¶ç{qÆgh¶a5>æKNæè€è�&è‚6èƒFè„Vè…fè†vè‡†èˆ–è‰¦èŠ¶è‹ÆèŒÖè�æèŽöè�fè~é‘&é’6é“Fé”Vé•fé–vé—†é˜–é™¦éš¶é›ÆéœÖé�æéžöéŸj‘!ù ÿ,�äþÿ (£ Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç� CŠI²¤I‰S”q‹ŸË—0cÊœI³¦Í›8sêÜYSžÏŸ@ƒ J´¨Ñ¡óŽ*]Ê´©Ó§P£J�JµªU¦ó²jÝʵ«×¯`ÊåÊsÞš±h³ÊI;¶ Û·l“ð»UPå?·Þ�ËÆ·¯ß¿€ûjL¸°áÈ ^ü·0ãÇ�W›L¹²åjË2gFƹ³çÏ CFº´éÓ¨S—¶˜ë×°c³NM¬¶mb¢sëÞÍ»·ïßÀ?kN¼¸ñãÈ“Î|´êçÐI3lºôêØ³kßν:²Ë€þ˳2/�ùóèÓ«Gÿníú÷ðßU·j•¬ûøóëßÏ¿ÿþaIÈ£Ž<·°�KêDÖ˜`‰5èàƒF˜˜‚ ^fádÅ5Ç[tF7›l ¾&ŒkªÝV›†(¦¨âŠ�)çâ‹0Ç¢oÖh/ÖáX�0ÝõècvßY^aã•ß‘éµg$’HÊG_}PF)å”TVY%€òŒ3Î;t $Ã;ò5˜˜†i¦a‘I蘙”ñuáeÎèœ�t’â�²•h"nröéçŒ1*¨‹†V§�¼àXv<þèèvA¶Ù‘ä1i©’–69Ÿ•œvêi}Xj9Ž<2tË^ff3á^¢¶êê«þ°Æ*묳’‰fdoæ§Ÿ‡Ö‰ç¯°éib¡ÄÜ È&»Œ±� ƒL¯Ñ%*­0‰V§ã£Ør&䤃�÷N¦Lº—žV”kî¹r|£îºéT1Ì)ðÆ+ï¼ð’[®§Øk¾ô®B/¼Ð(ª:]Ê Oªˆõåê9 7ìðÃG,ñÄ7쪭cJ–«…Æý -�À†,"j{žÈìÉ(·¨ìÊ0¦üìǪI+óÌØÖ¬í¶~ukE:ëöìóÏ@§³ÖÏVØd…º sN»ïþëô)E»´oÔüXñô¿g©å9¤þ#?ŒqÍØk¶ZñÙh§­ö9¢ªªX`s¼¯0w(²È#ÎFòþž.÷M,Ë€šrÝ7’6óáÕÖìèÍ’66^:cG.y4ØDŽÍå“G.4ä“S=“™£S4›”nú騗NîKTï›úë¦OƒÖZòSê׋½"Çî¼÷þŠ6|™ ±:ko|Å¢®ùWÜ•í*'áÞ-ýȧ•Ì§ßØËøö½áˆ‡�ݵŠéd�ͳsæì·/ù7rp.yÔç–+uæßŒûþ›¬“ëüK�,f×*Ûy l�¹Eï(‡[okS‡'HÁ Zð‚Ì`Ѧ%·0ÌÃÌÜèö½ÔLï„$ÚÛ°²ÇÂqï…šqY ©¾CZåÓãÐ÷õ}Ã}þ@Ä_ü2gw¸t‘+âñ§¿¾Ž\F<¢œ(ÀÙeCTÄ]`ä7¬a ^ŒÃã á1 –¡Á6Nj¨…ÁA5²Ñ�<cá°¶½­/!t‹f¨Ro¥±^ ©!:Ò{Ðã0jHÉ&î†åÛa5zºWxò“º«_ýäJOFCØ(å+¬pX”¬t¥*£A�S|á–jÈ¥.wÉK5T!–®¬B/‡©Ë[nâÃâí}%¡\Ï´BäpEž†: a uœ�„£¡A�Tl“r'÷ø°þÑM䊉šCÚSX·þa¤>ãÈ~ž z¬‘Ö$)IPáPqçãd4T¹J£ÍÒ ©,e,EÙÊW–’–¶¼åˆÙË_¶ò£V&G‹©Ñc¬šYd¦_N™„–Âà™/MBP)ª†á Ù˜ zÔYAqÂÑœ ×NÄ�1>m“Ü{f¹�+�_Ö«�æM’Ò 2u«{Ýì–R_¢Ü×,Q©J$‹’”5ÁyéªK:XùÊXþe¹ª@-‡Ë`îåŽ9�Œö/ÑÀEþ0ÐR6'�mN.û؆Í�é ¬yRKÇ4¦1ö3Ìà ·¶‚Nôkmá8¾Q |d'o?Èæ!už/~nŒ‹kÜãÚ8¹8Î1‹LÆRódÐ ²ª/Ù#Ï´ék(+Cg=ëïÒúÖQ^˜wÍë^ûÚ×§0A™Çt敪ù°&ALe 9ÓÙat°žÓÁgÓRpÁÑNp¡ŠhF{{Š^†£çi=B:yFÅ�[œÔoúÝÔ{*T?]ãP³¬OW½Ìºê~S·2ïpC4‚�ë‚¿â”ß08®£Q…iâá�xÄ1AñŠ[üâ˜�¸Æ¾‰U»0ÅîKšþ× ˜ šÒ<9.ÀaM\Á^cž%‹à«�§=§ õþj"!©’3”Ö B·Â bÈö5 –ø ¸`‰Ó Ñ ¯â† ¨6£bM‡"βux‡ªØiV·‡-Ô‡‚¢c§f#$r„ƒ¨j;bˆ•‰ø ‹Èˆ“!dʆuÇ‹Žq C+ #+ÌЇÊ#‡sØ™cª˜�©wU®ÈB°(²8‹5r'·¨„¹ˆLÈCˆØ‹ò‹à ‡ñˆ�øGƒ1‰Ü²& ò@Ñ+�q1÷!‹ai¦˜iÙX�=˜‡zØ�‹ô�à8#܈="å(v× -Ò8ŒÁŽíèŽh"ŒÃ8€ï¤ ö�ʈ1y’6�–V�ÁA�þ“)T=ó¦�ÞÈ�/‚o¢á+9‘„¸#�b‘b…Œ(©*îH’TYÓ8’)©’(¹‘G ,ö¥�Šñ'“2ÉŠùd“7‰“‚C„â¬">ù“çèj™‘i”+ù‹Š�KIÊc�)™0S™—¸O.I#׈�Z©•\ùƒ^Ù7`Ù2b‰jäx–]Å(<¢–긎½(&z™”À#—s¹&¨^Ø™žù™ ‰…:•߃¦9A SA¡¸š¬Ùš xš°›²9›´Y›¶©N®™›hƒG¡Ù›¾ù›àr$ŽrãÆyœÈ™œÊ¹œÌÙœÎùœÐ�Ò9�ÔY�Öy�Ø™�Úþ¹�ÜÙ�Þù�àžâ9žäYžæyžÍy é€}ZÄÇðŸò9ŸôYŸöyŸø™Ÿú¹ŸüÙŸþùŸ : Z ñéëiŒDiïi ú ¡:¡Z¡z¡š¡ÊÚ„õ¸LpV8¢$Z¢&z¢(š¢*º¢,Ú¢.ú¢0£2:£4Z£6z£bÁ¡éà¡" ¢c"¢8¤B:¤DZ¤Fz¤Hš¤Jº¤Lz£:Ê£)¥÷›TZ¥Vz¥Xš¥Zº¥\Ú¥^ú¥`¦b:¦dZ¦fz¦hÚ™óС¥„pè§r:§tZ§vz§xš§zº§|Ú§~ú§€¨‚:¨þ„Z¨†z¨ˆš¨Šº¨ŒÚ¨Žú¨�©’z§kº£mꣃ§wz ~v Š  �Ú –õxsÚ   *ª‚ªZ §§0h¡ú¨œšFžÊ§«*©¨Êªè°«uê«“¬Â:¬ÄZ¬Æz¬Èš¬Z©t香*pì# P Ñ ©DØš­Ùj p­™Ã­Þ ભ‘b‘óáJ®ê*­Ôj­ßÚ­â ¯ê:¯“3®cc¯’ƒ¯ôº¯üÚ¯þú¯°;°[°{°›°A„l:Ϊ ×>  K¯Ó ¯“s±áª±óÊ®Ñp±Ôš°ë>˱9&û±‹²+{þ².û²0³2;³4[³6›­ k©‹© ­™3  ’ƒ `«Ã`Y©p´ƱDûg*+i$´êš²iV´ZЭkYµE®G{­æÊ´E·€®*{­75µA;´a ´›¥µ{±PRÛ´W›´H;µ ¶¶ú¶3eµ7û·€¸‚;¸„[¸üš [ óÀ³w9Žû¸J› Ø ±Ø€ ZbŽ‹¹—ó¶å„  š @ •+¶�[º¦;¹¥z @+¹jðx|+¹§»—ãªØ ’ûº•{¹¢‹ 2 µë»²{º‘;¹Ýš»”{¼Xëa£«º�Ûº© ¹Á{ºlëgK[¼–þ˹P Ÿ½ÜÛ½Þû½à¾â;¾ä[¾æ{¾è›¾ê»¾ìÛ¾î[ºˆ«³ŠË¸¼D› M»YD ¼û»¹Ý ª·0» [¼”û½ì¹P Ä;À ,¾7õ Up»ÿ¶jtS r »á{¿ù«FÈ+Á ¬±¼Àý¾L ¸[»ü¾0Ã2<Ã4\Ã6|Ã8œÃà¿•±¸ ú¦õ¼j «ü¸Î;»®û¿ PĶÂà{À%üºü½ÃP¬À$¼ÄŽ[Å© ¯·�Àä;Äì¸NŒ»$,Æ|Ä\¼þ‹¿ZüƔ۵:\Çv|ÇxœÇz¼Ç|Œ ü5…Ѹ§{ ’{´Z´Àkċ쪜+¹ìÄmÌÁ«[»IÜÀâÛºÀ˹‹\»½[»VÐÉÝkÈØ€ÈŠlÆœÊ#œ¼¬ûxŽK»“ŒÊ ´²|ÊeÜǸœËº¼Ë¼ÜË4üÇ“Èü0ÈA\ºÓ+ºž¶P[bË̪[¼ù+ üĥ껱U·”ÛºÈ ¾Û;Íù+ºÛÛͬµ—óÍ–,ºÚŒÆÖµÝêÌOìÆÞ¬Ì|kæËö|ÏøœÏúœË'¿ÂLÌÅÐ=Ð]Ð}Ð�Ð À }ÐÛÐÑ=Ñ]Ñ}Ñ�ѽÑ�ÐýÜÃôÛÑ"=Ò$ÑC¼ $�þª©PÒ,ÝÒ.ýÒ0Ó2=ÓýÑ€Ò4�Ó:�Ћ'¶%­Ò;ÔB=ÔD]ÔF½Ñ6Ìu÷¬GÝÔNýÔPÕR=ÕT]Õë¬7�}bpVÝÕ^ýÕ`Öb=ÖF�ÕJ­Õªp®°ÖlÝÖnýÖp×r=×t]×v}×x�×z½×|Ý×~ý׀؂=Ø„]؆}؈�ØŠ½ØŒ-׉+Ìdp0Ù”]Ù–}Ù˜�Ùš½ÙœÝÙžýÙ Ú¢=Ú¤]Ú¦}Ú¨�Úª½Ú¬ÝÚ®ýÚ°Û²=Û´­Ù�M_@\Ûº½Û¼ÝÛ¾ýÛÀÜÂ=ÜÄ]ÜÆÜ·ýÃÏzÜÌÝÜÎýÜÐÝÒþ=ÝÔ]ݳ�Ü‚œÛÖ½ÝÜÝÝÞýÝàÞâíÜØ­R’=Þè�Þê½ÞìÝÞî}Üå�*×åï]ßö}ßø�ßú�ÞñÝç½ßà>à^à¦ßôß¾à Þàþàâ�¸)Õ6 á~ážáÛJÕ0á¨Rá>â$^â&¾á>¾Lò-â'þâ0ã2þÞ)® +ŽÖó=ã:¾ã<ÞãÔ]ã=Šã.îãD^äF~ä¬ ä!7äHÞäNþäPŽJÎâ¢ÂäQ~åXžå&>åÔ*V®å`æb^à\þ5^Nßcžæj¾æúíïÀžüpæl>çt^çþæ jæUŽæþvÞç~þçÌíæp.ç€^è†~èµíæâZòåˆþè�é›­ènÃè[Âç’žéš¾é“Mé|aéŽÎé¢>êlîéÙ�R(v餾ê¬^ç¦ê˜Þê²>ëX.è•Nå�ë´¾ë¼^ä¶®*¨Þ0ò ë½^ìÆã¿~êËä0Ã~ìÎþì[Žçz@êÐ~íØà‚žçü°[\CìÙîâžßÛ>í_Ãìà>îê¾îê]îA~îžîì>ïôÎÝîì Óìõ¾ïü¾Ý÷¾ìñÞï?ðÏýïÔðŸð �ÜÒþîÝŽð ñÝ �ïß>ñŸñIŽçÀðù.ïò"ŸÙ¶nþîÿñ#Ÿò*oÛ`Ò¯ï+ó+¯èôò /ó8¯ð¯îñŸó>Ÿñn.ß6ÿóD/ñA�*C_ôJOðG_;<óKõõÞôóuð(/õX?ïTŸôYßõâîóP@Oó^_ö´ô “R¨ õfßöÅö£öÄÓón_÷¼÷i¿LsO÷vß÷­Ž÷ #÷Äö~_øœøç øBö†ßø€ŽøŠOøŽ?ù‡ùz?A’Oùšïç–@”ù›úsÞù_óùŒ/ú¨Ÿå¤Ï¦Ÿú®?úó÷—?ø§ÿú¶ä«ßú·¿ûZî2A‘_û¼?ü3îûüÄŸüNöÇ?û‹þ¯üÐoäÌüÎúÑý'>ý„üØßý2®ýêÀýÞ?þ[>Íïù˜/üä¿þþ)õ´¦ì?ÿnüÔ@O(AòOÿüÿàö¿ý!㟠~ï ¾›çÃB† >„QâDŠ-^ĘQãFŽ=~RäH’%MžD™RåJ–ÝÌSS?�"TØRçNž=}þTèP¢E�})óÍ�&<UêTªU­^ÅšUëʤ™ÚôšsëX²eÍžE›V­Ô—7¿:5ÈOìZºuíÞÅ›WoѶ^kÂ]:wï`Â… FœÖ à·n'†YòdÊ•7.vû×±eÎ�=þ]³ß¦›CŸF�Zõj–£ãjËZölÚµm»^ ;îcÛ½}ÿ¾÷Ûy±ƒGž\9Öáå=—'wùtêÕ­så7Oû¼·Ð¹ó¾^üxò oçîºôòíÝ¿G~~{÷õàáßÇŸŸóùõꟳ×/@;mŠ!—\sÑ)ƒ;aw1=u:97ÛsÓQW=vÕJ7ØeÇ4Ú;=wß-Û�—Þ'>²à‡/>yÃŽ]yç·bþyé ‹~zë=eíšæ9[øæ¯Ÿ¯ì]çýûðÏGjüí»G}÷]U îÏnÿ}ûÙŠ_†ùË¿¿«ª÷_5”¿ýyO€_÷þÈg@60} \ýÌç@ ^€Ä J.˜A–dƒ!H>B^†€ì›` 38B¶[” ]8C žP‚4ÄáDX˜Cî�‡3ôá[D!–�ˆE á‘ØA%.q…6äŸ{EJˆT¬Ÿ™ˆÅj1|Mô"ÁFŽ‘Œþ3ãï—F5¾��mDßáøE.Îq‹0ÔŸ íøD<0‹{DcYA9òy…4¤ò™Èâ-’‘¿C0ZÁ(>²Œe“¤öbxCK^Ra“Üd%;Ù¿™mL~ìâ(G÷/�Q²Šª´+�qJ=Â2–çPX+CùJ[Æ—¹¤%'{þé>YS”äc.géÊ?"S‘¿Ôe…éLð“™©¤¦á¬¹Ëff’¸ÔÖ2¹‰Moîí^Ú2&/Ëé¼q¡óšë´^;6NxNOžéìf=UwÏwê“�àt'=ýùÌwÍSšÇ¨ïø)Єo¡UgCe÷PTJÔ¡Ùz×óiQÆÉS£ää(Ô<ÚÏ�N£…èFK8ŠÖr¥©ké4_*ºŸ �©ÏjŠ/’æTs;EiE}JSuØ´§C�\M/eP¡"•r5­šAåáR§.ªÈ�*U«ªÍFU­\dÒêVg)bÃNa«Þ^E$´¦•nk…R[ÝÚ6¸‚U¦s­Û�¼úþÕ©Þ¯nÓ«´ìŠÐ¿ÒU{=«_ +¶Àæ*®Š],×>eV¶B6²W«k_ {Y¬eV®œ]šg- Z¥‰v³¤ m£+�OFµ©˜�réÚ×-³ÊTimSvÛ\æV·"ã­Â|û[�×v8%®³Œ;Üäl¹Èmn±žÝÒªÖ±dÂ-t©k/ëò5»Û%ÚtÁ«Óîʶ·Ú¯¬Ä›^™­—½*sï{G_ùnŒ¾õ�Ø}ñëÜòé»ûn¡ô_WÀØ=o�í{`Ö&XÁùe0�\0ýNX]™ çq-Ìߨ)ÃÌÝðÁüaô†xP'ˆM¬Þ¿KÅ+fW£ÎÅ×þ‚¾Æ¥ÂÒuåQãß8O9æ+1\ÜcË Èv*«¶l\dNŠLeò’™L)'S ÊŠ›²¿dü((A™XÎòªªìe0‡™Tc¾2‘ÍÜ%4—µÌknò–ÛÔå4ùYmþ²šíÌ49#¹Î{&žß è•õ™HdÖ3¡yTedüYÑ´b´£ÍbGÍ™g’žtŒ+}27':Ó>24Ò=èOë‰Ñ—Ês©µ¼i¡±MÕ£:õÐ^�ãP;MÖ³†u­å±5\w*Ö®îõ¤~Mê`“L×¼.¶°�mµdšÕ¢v³O¼ì[K›cÔŽ¶µ%†mbk;IÃö´·nq'jÌÌ.÷�u½×nþ§ÛEmζ»ÓïvËÔÏ~rYãmo£­[ßõæ·×üÝé€çlà©.xœî„�gá ÚÁñ=œâÆÆ·• ~ñ~gÑïx–è¼q�WÉâ%§ÒÉQþm‰3|åkjùËùìqLËüÝ1·ùÌpžs©íœçKòùÏï-ò|“\èCçrÑ~t¤[ZãKgzˆTõM�ê²úÕ¯t­o�æFïº×‰þô‰‡½:Y7ûÛ¸žvµêlgÚ᮹Ï?u·;|ðžw÷ì�ïåñûß¾vÁ¿'ð…¿ÎávÂ/ž<ŸrúÇŸÌJ~ò†g°å/o·Ì×|ó⩼ç?ŸøÎƒþ}ô|+ýÛOOú�\õ«g|ë•^vØW.õ´¯½înïòÜë%ô¦ï½r~ÿúàÇg÷Å�ýj5�|˜Ëžìn@@ô¥?}êWßú×Ç~öµ¿}îwßûßøÅ?~ò—ßüçGúÕ¿~ö·ßýï‡üå�ýáçhþ÷Çþõ¿þ÷ßÿÿÀÀô¿úƒ>DÀTÀdÀtÀ„À„?”À ´À ÄÀ ÔÀ äÀ¤Àè“9èÀ$Á4ÁDÁÀD€TÁ„Á”Á¤A dA¬ÁÔÁäÁôAð»AüÁ!$Â"4Â#ÌÀ DÂ%dÂ&ôÁ€B€ÂpÂùSþÂ*ÄÂ,Ô¤Â-œÀÝ“>ôÂ1$Ã2LÀ.4Cõ»Â4dÃ6tÃ÷CÃ7$¿5”Ã:´Ã;Ô¾8ÄCï£Ã=ôÃ?tC=ÄìˬFë´0ÂATÄEÔBAdDê+DC´?LÄG´ÄKBGÄÄHUÔX�HZÕRL NXµÎ[•QP5Öc5LQÕQ åR1eV!uN pVi5IÁdQëDQj�ÈKÅÒmERÛœNî|Ö/ÕVuÖ_]Ó5]pEWNEÖw…W¼TÖætMG…Ô¥Ò mWþ…N~mUŒlÔÀP~½Ô …Qí,QH\u‡F%ÐÝô×Ö4Ñ>ÖŠíÏPX†ÍxåØŽýJ~ÀÊyµIV}ÉNÅK“õØ”UÙ›W¸Qç«´:½I5`R­M”]ÙœÕY˜,Eý”É P›ÄY¸Ú�5Ú£íH�u¥�Èž•Ù·,Z·ŒZ¤¥Úª•È–u¬mZ}¼Ÿ…Ú›µÚ°Û”L̲œÚ¹Û´UÛŠTÚ¶ Y®]M¢Ûµ¥Û´ÅZpx…¬uÙ­…YЬۿÜÀ=ɲÜÂ5ÜÃÍÅ[pƒÅeÜÆuÜÇ…ÜÈ•ÜÉ¥ÜʵÜËÅÜÌÕÜÍåÜÎõÜÏÝÐÝÑ%ÝþÒ5ÝÓEÝÔUÝÕe]ɽ`ѱ�Ñ™ ÝÚµÝÛÅÝÜÕÝÝåÝÞõÝÝ=‡àÞá%Þâ5ÞãEÞäUÞåeÞæýÝç…Þè•^émÞêµÞëÅÞìÕÞíåÞîõÞïýÞéßè=‡l�½[0ß�˜ õuß÷õ²ø•ßù¥ßúµßù}ßüµß‚eòßÿU¦îà&à6àFà`…áßüuà†à–à ¦`÷­š$+¨ÖRà æàö`áá&á6áFáVáf`þü­à–áKɆ[ˆ�è.õeß™áûõáâø¥àýÍàöà#Fâ$>›ÇY›½šþá'†â(†`/+b%¶â+N`Öâ-æâ.öâ/àþuam‘_)6ã÷U‡ˆ[‡üÝa–á –ã9.ã!&âw1b,Öã=þœwAµ3ä@Žáø-âLâãCVb0VäEfäFîâ1~á:d(þ‡Kþ¸uH_÷}cʬ`:e:¶cúuaFäTîàöãIvåW†_*Æc VåZF`GÆå\Öe\î_&.(I†å Îu¸ÀdL–¸…aæfvæg†æh–æi¦æj¶ækÆfï@�mæænöæoçpÞffž‡l6çsFçt¦fqfçvvgíPçx–çy¦çz¶ç{qÆgh¶a5>æKNæè€è�&è‚6èƒFè„Vè…fè†vè‡†èˆ–è‰¦èŠ¶è‹ÆèŒÖè�æèŽöè�fè~é‘&é’6é“Fé”Vé•fé–vé—†é˜–é™¦éš¶é›ÆéœÖé�æéžöéŸj‘!ùÿ,.Ý!ùÿ, £H° Áƒ !ù ÿ,ö¦Pÿ Hp €ƒÿ@ÀðC ˆ1bÁ‰+Z4Hq£ÄŽb$¨ÑãÈ�%7ž˜ÒâJ‡!E‚ ù²eÄš1Î4¹SeO‰>tØ0g@!ùÿ,¦��ü'0Á¿ƒ*\Ȱ¡Ã‡#JœH±"A‹3jÜȱ£ÁŽ CŠ9ñ#É“(Sj4©²¥Ë—YœI3¤Ìš8sR¼©³§O…< Õt¨QŽ#=Ê´¢@pKFmJÕáSS§VÝ38XY$KDB­\·z˶­?xðΦ�kumX²e LJ·¯Ôµhý þ u°a‰|!ùÿ,�¯ 4ÿ \@P Áƒ .@ˆPaA† ®)W­bµy.þ9$8ÑâÅŒt´ˆ1âCˆ&QT¨2 !ù8ÿ, £ãH° Áƒ !ù5ÿ, £H° Áƒ !ùÿ, £ãH° Áƒ !ùÿ,£ƒÿ ü‡ÁÀƒLÈPà† B<(±¡…ÑøÛÈq#¦‹3vìøã?�¬‚$(2e• Qª4)ó%Í‘þ�„)'&„¾Ú¨Ó$á?�&¬²¡Æ¤MÎhæ�E3øY8Õ+W³âÌ Ô XŽ.ËNT»ViÛ á" !ù7ÿ,£ãH° Áƒ !ùÿ,£H° Áƒ !ùÿ,�F-þH° Áƒ*\XpŸÃ‡#JœH±¢Å‹bÜȱ#G�1J;/¤É} OJyŒ¤J�)_FYRæÆ”ôœ%Mgƒx#�È%”硌¶ê3Äžä©©A˪L£=‚õ!HzFf9Ì)ÕiRÑN=rLê>´-[öšQ’æXºoÙ ÛS,Ù}fûFi7oÝKi²tI¯�¶zþtU U—v3#v ‘0g͉I..Ùøq\ÎOQgÆŒysM¯Æ†»ðYѸ—æ=Ý«vÄ¿”Y“®uÆØ”u&…úSqnåÍ!g Z¹tÃɵ†ýr»M“1C·zÿ“¡ùóèÓÿ[Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿh_qh ~¨à€.è`| >(a{N8a…>ˆa†ý… ‰ïmÈá~‚螈#æWbˆ ¦Èߊ'¶è¢~0R(ãŒøÕÈŠ8ºç¡&@)$�FðØ#{?©d‘7IŸŽëéä{Pþ#å”íUy%–ëiÙ$—T~È"˜OŠ#™üm‰æ˜kæ§f›;~ '„r!ù&ÿ,‘ ÝHP`@!ùÿ,)£H° Áƒ !ùÿ,�a-þÿ H° Áƒ*\X€Ã‡#JŒÈ†¡Å‹1îÛȱ£Ç�dI²$È“(7Š,¹�#˅҄ƲfHƒÌn!é‘`Ì™/þü™R ñöÕÙqå@C%È ì#•çFŸ2ƒ •Id;$‘*=³,)Ž*Db­#ÑBbr)!7êÒÖ¤ýãâð,Xgþ)2—Üݶ†Â�ÓØg¤áý˜SlG$“Uª•æà¤p�ž½¯]T¥iœe†ô§`¥ªKw}ºÏâ¸\e*ÍܱrÒ�|O£Ý¼�àÆÅÿÞþKºÔ!ÝåŸ]×Ý@‰xHNߪ¥o�|Ïþª4ÎÖ3råÌ»£NOúç‚.¿Ò¥Ž»½z�ß;&&;~à>¨RícÛi†à€^iHˆ·^t�M7ÓW¤¼& eB �\iÇGߟYhÁgˆ@lñŸC�[XþÅW`ŸGCX_¡x"`õí™dmqTãC¤$dSZ¹¤K6%¹�SH^u¤IJÖÄä“Tf4Ñ•X:Tå–\véå—`†)æ˜d–i¦A}ôqæš¥Éæ› ¹ çœÉIç�vÞ9&äèãç>HL¥¦žcnáç¡~Ž˜'¡^ò©Ïˆ±¡ ‹2Ê¥¡ÌDÊ£•ZZ%¦IÊE§ž>é(A`M7H�Zê‘l†N¨¨ÿ¸úªVŽúɪ ·v)鈹*:h¯T ©@§ÚJìH~dè1Ê.{‘ª€$´ÃJÔ¦Ç „i´Ú2k¦Þú9j¶á²´)¢‰ÖŠnº%Étè®îÂû%¸ö’„o¾íËo›ïþ”¿_!ù8ÿ,6£H° Áƒ Pˆ°!‚€!ùÿ,6£ãH° Áƒ !ùÿ,<`�þÿ xÉŸÁƒU \ȰáÀù’qH±¢Å‹ÿDxPaƆ9züH²¤Å‚#1ºÐ4Ñ!D#'li²¦M”$WÒdˆsaO›@IþTÉ’âÐ2ß]šñ¨E�_*8B™?L³V ypgC¨F»"õ7U«YŸV5âA¬gã†õ×C"MxóêÅ w¬Â—0å æøŸÝ½ˆ5Á*u°c§ÙöZW_Çge¦\(y`Uº !ZÆ÷sY†� V½™tIˆe?�v˜ZàÆ‘O»~í–£WÎEçŠÜ°Ú§ÁÛ"¼L¼¹óçУKŸN½ºõëØ³kßν»÷ïà»þo˜ȃÃI’ÒKºT#Áõí݇Q~êígÑxì ˆyæ]4" *8 ƒ¢çßuE$¦×µ@¡Có¨]†âÅaF(zé©(¡E)F¸•$.¾èÒ‡¡Wv$–xâ„5:t‰$V×£†?^cSDÚ¨$ŽÍ·£“-¹P 4_�NHŸ$ ä%}YRÚ—é…I‹éµaæ›pÆ)çœtÖiç�xæ©çž|öé矀*è „j衈&ªè¢Œ6êè£�F*餔Vj饘fªé¦œvêé§ †*ꨤ–jꩨ¦ªêª¬¶êê«þ°Æ*무Öjë­¸æªë®¼öêë¯À+ì°Äkì±È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆ+ï¼ôÖkï½øæ«ï¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWlñÅg¬ñÆwìñÇ ‡,òw”lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕX³<ò· €h×_{}(Øc‹½]×h§mvMj“MöÙm£ TÜ`¿­�ÜáÝP‚ÚµÝ�Þ¾�àjÿm÷E‚÷}xáÜ%^‘ãÿð-�ß�Çmä‘ó-÷áØÑ½6C˜gÎ8熻í9㢋^÷çßá}úèvSîä´/.ù줧¾7á·ƒ×ûà¹óºtz£zðÅß¹ç�ç®záÎSgùåÑO½Ÿ×÷™=ŸÛïÙ½žßc!ùÿ,<t+Ý(ðŸÁƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱcC‚ : )0 !ù6ÿ, £ãH° Áƒ !ùÿ, £H° Áƒ !ùÿ,£…ÿ H° À8q *$ˆp¡Ã†BŒX¡ƒhüiܨ“EŒ9zŒs±`FZI‚Dið£I,+ª|“áL‚C9xs`Î�˜þMŒHJã�¡Dý�¤è&R‡—2MÒÌ¡§^øHf¬üBšÐ`VŽ1ŸRT‘íòLº]ˆ0 !ùÿ,�F-þH° Áƒ*\XpŸÃ‡#JœH±¢Å‹bÜȱ#G�12/¤É} OJyŒ¤J�)_FYRæÆ”í:ÅL§€xÌŽp@j(O¡;Y’ì @À(ˆL�Žä" %U >� ¹ú¤=.O÷å|ÊhJOžR…ëð”YUµBzy)IÓa»¹ûX²Í»wì¾²g#‚¬›×eЖZµ"ÛÁܵ:d*ð-]Æ�,†8Øeaºš—Š^œÓqËÍP=^]÷°êŒ~ ë°hŘOÇÝÑïdÌ%k›}�2öd�xf¥É\-òŸJ± TMîåšQ 6~’°Í“1Cézÿ’¡ùóèÓøÇ¾½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿè_ÔG&�"¨àƒÿ0Hß�>(á|V˜à…ÿÐÀîe¨a€vÀH�&‚ØA"\ˆ8âÁȇ)Êø¡‹/ö'¡‡3Îâ?8渇\0’Hˆ ©#Š=6Y`�Jâã‡R)c‹IF©‡þÈ”ZÖÇ%•í�æ|Ægæ™ñ¥ ßšl¾çæ{pÆÙÞœHÚyžef©§||~éçŸ 8á „º(�ˆ&ÊÞ¢uê i£ŽNê( †bHi¢–†!ùÿ,‘ ÝHP`@!ùÿ,%£H° Áƒ !ù7ÿ,'§Sÿ ü'ä�ž�D(0B=$üƒG¢CˆV”X°ˆÄY0¼È°a<,žL9r¥Å‡%†ŒÈñ�ÇŒ?^¤9°àÆ‘y TxðcÁƒ!ùÿ,/£ãH° Áƒ !ù ÿ, �V-þÿ H° Áƒ*\øo€Ã‡#BdH±¢E†û2jÜÈq》 CZìH²ãG‘5¢\(íH<�%cf<Éìá”� ¶|¹RàÎ�%·=€(JãÇA3x¶á RåÀ�=}ºJRhR“ÿ’ÔÚôß‘cGÚÌ+6ž´¡jIûׯ¡(zIŽú·¯eÙ³·røÕeݾñâþuv«F«ñLîK óob¯Ç=[t[’ÄkÿIÞÇlªKºu7[æùõj°˜-¼Q¨M�ûf\ýuì˜Ñ‹Û1ÔÙ~ñ:œaìÁÕÕªýÊ„; èÌ}5j5¦m[`êij{ÿü œiãØVmþ·DMUæÞQF÷!}¹ïôÕA€o'ê¼®ö©Œ»ÿ£Zz¸�¼§Úq–3ÿÅeàGê 4Àê9ÔEm~Y7ZG äX{̵ah|'W„t[ƒ±¦QMÕ·ÏIMeÕJ2ÅãEN͈S�$ݨã� I$¤D@iä‘H&©ä’L6éd‘Xðä”EIå•Y‰å•Zn9e—^: æ µlÃA˜H‚)J?f¢y¤•Sô#'›gº ¥”qÎÙ¦�@‚y„9{ò©£Ÿ€Ö)茄zhO‰ºèJ�>U¤’B*å@*Z)H”nR§ž^j¨Á9ç©ö8JªB¦ž*gª«Rf¬"ÍJ+§—ÞZk®ºâjg@!ùÿ,‘ ÝüøÏ�Á€!ùÿ,?�)-áÿ H° Áƒk(\X¡Ã‡÷Iœ¸¯!Ä‹)N´ˆ±#A�9z¼X±¡B]Gv, ²¢JŒ,AŠ|‰°ä¿m(Τ™1I ”!y¼SPJ¡uú·Ïg³£H êRxhШebͪqçÖ� ~K¶¬Ù³ûôA{P-[ƒnߌ+W ݲ5š)ãx—¬.x{Ó®%ÛžaÀ|�-|8°]Åe“ ŒV²ã}ÇZN\yòãΗ3ÝLù,éϦ=c†LöôjМ ž]Q4RƳáÕfýÖöYßf�—N–¸Ê€!ù ÿ,I£H° Áƒ !ù!ÿ,K�$-þÿ H° Áƒÿ(\¡Ã‡ÿôIœ¨¯!Ä‹)N´ˆ£F‰;FÔ×F`p*ÔµQä@’t½TˆRcÈŽÊÜ7óäÇ›uqÜ™2aŠ@/V PI_¥Oê³³¥ËBã`ý§UêÒ¦ ¯FÔ ®ML]O§PfÕ¥¾œŸ Uɲ­Øƒ+Þu˜7é^“ þL¸°áÃãtE\P1cƒŽŒ,Y åÁºüiö7Õòâ½k7‹~zùîÚ¨q9[)mxíTÖ…]€=84éϵ•iîÌ÷ßКáÒ\É_Îá˜ýµAþ·x%æ{�Cz¹ï«G­ }üºË8¢7wž1@x™ž+$¿—ý]÷bác÷.2 !ùÿ, �d-þÿ H° Áƒ*\øƒÃ‡#Jœ‘¡Å‹ È±£ÄŒ CbÜè±$G‘�Á‡rá¾—Išœ QàË›!Uªd9gK›7÷ɤIóŸO˜9Wôù3¨P¢PÿSpà©cTg°œ1Äj׫\«^=rì>¬UuáD{@—JG3B�{6ëÙ¹ZqB%ºo)�SIís$å]–ÚZ"{xŸ¥¸�Ë»sŸTÊdüý§y_àÁR° :t¯Ç²+ƒ|—gec <‘ýÇö@^ÚT«Æ]¹O5ïÕrñ9-mšãN�ªY§Í¶ì²•ƒ2n™àñäÁ‡7ÙW°Ô΄wà.¯¼Xç÷Ñ8?[¾Þ|hÞ¤·—Ä-ðªÝ²­‘çÖª2unø¸UEÖoð¡Å|–Y&ŸG"-÷JÄ-XSR<=(R„:dá†!eH‡ †(âˆ$–hâ‰(¦¨âŠ,¢´À-ÆÒ‹2Öh�6戎:ö8�>öd�9Id�F.àÈG®˜ä’Mªø$“Q¢8e•VÂX�’TbYâ•^~ù¢#d–if™ „Éá‹Jžé¦#iªi!˜r†Hg�kjI—xÚ©ç�Pö™§A| ºá�†¶dd¢ .Êè¡>Úh¤’Bú`@!ù)ÿ,‘b,�ÝüH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç�‚IR$É“M¢\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒöìÓG(K¢FW"Mzr)Ó‘NŸ~Œ*µ#Õª¯bͨuëÅ®^+‚ ;q,ÙˆfÏ>L«¶!Û¶ ßÂM(wîÁºv âÍ;p/_¿yÛ<—0\Ãm‰!ùÿ, �i-þÿ H° Áƒ*\ø€Ã‡#Jœ‘¡Å‹3þÛDZ£Ç� C~ ±¤I�"SªIòäÂŽ.:OàÊ›*[töPHÉ�gÖŒùO¨P‘Æ.@Å⥤K;êX'ÀP9CQr J“hQšGC&µ2Qcã±4¤•Ç£ÿ„"&Àܺñœ9 •³bŠÚgÀ¥�3ñêåë¶ŽC¹4÷ÍœëÍì¿KzÝvL ’'MÎ# î›1”#\¹ëll‡Ú¿ÿRKÛÕ´ìÖCå’Þ'gîkÈy#göõ±G³¬•—*š iáÿ|ïøz¯C»ÿ~¯ù¼úC»Èþ�L[íJä¦D>~–¹ó ­lÎ~=2õùÿjºq¾è­cIGÞv79v Gè}d {íSw½íVpÓe·ORƒ™f¡Q¤õdžHØ!çÌnÃå'b}I¦žyάØ"GSÙT‡@ê9èÐ õ©uŸdÖùdÓQ�†��w cÌ`—¥˜ÞCɵ7¥`ÕhL^m‰Ó—¡Åe—Z�i¦–d¦iEl¶)‘špÆ)çœtÖiç�xæ©çž|Ö¹À}ZÒŸ‚z¡†&š¢Š6J£Ž:Jè³øc©?Î\i Òt饄mÊg§ñˆ1¥˜j*jž�™ªc«ÞÙª@”†«¬€ôê­¸$¦¼öZPdAkg«¨bì±¹ÒZ©²ËúÙl²Ñ2ë¬?ÐVK'¡žf«íœ¤úcê·Òþúé§°‘Ûe§ç¢«.™³¾g¼òªIo½ð6‹ï¼ú!ùÿ,‘ ÝüøÏ�Á€!ùÿ,t£ãH° Áƒ !ùÿ,V”+)þ÷íôï_p þ‹"�`A]ûJœHQâ@º"À�àed(³Ò YÅ“Aʧ1$¸�º6Þ¹x¥Í– Wî³B€À¿š2iÞ¼Ô£Jž‹þjsc”£À¼(•@M¦C÷¹„锦JeXoîY°fžO†]˶­Û·pãÊ�K·®Ý»xíöÌ{s/_”~ÿV ,x"á ýêòÇØßο= 4kLÙ!ÞÈÍ,ÿóäØJÞÃ%?¾ì“¢èÒwAKö§Y/êÕ�!¿žÌ˜ìgÔ9ÛN�[ââÖtAä |®ðͬož\\.ÚÑÿVïv…rcè¼£[o¼7âèÞ<^öÍ€!ùÿ,�£ãH° Áƒ !ù%ÿ,�£H° Áƒ !ùÿ,&£gþ©HðŸÁƒ*\Ȱ¡Ã‡œ'Îĉ3jÜÈqáÅ�?ìH²¤I‰"CФr²¥Ëˆ+U‚ü×GàË›8%féÓçA™T²Ð™³¨K�Yþô±(PfÒšD�J%9p'T*2ãüóuª×Œ?{6eúã׳ Z‹t«Y´p=†µ¨R+Ó®qóþ›¸ÓgÝ«xõÂå+6dÙ·‚ãök±ïÅÄzù*ÅÚX,bÈg%×4l¹ æÁj'ž|ùóÔÅ”›¶i:³ÚÂLí–n]µJ¡\ÓÎIqiê ¤uï¾ùškV·Â‡iÙip–Ê�Vå ònС¬£óî›íOìÚk [Íý[døí+!ù0ÿ,‹£© Hp Á‚*LÈp¡Á€!ù4ÿ,‹£ãH° Áƒ !ùÿ,‹£© Hp Á‚*LÈp¡Á€!ù ÿ,‰…4þÿ H° A�74é88J%=*JœH±¢Å‹Gpª„§ ƒhü‰)’�@ šPüC¹¤…¥<ŒhpD0\/$ÚÄyPIJ0f F’gAŸ$ƒŒ §’‚ †üY¡&MoX&T¸´)Lƒ>�öô'V MªþL 8"Z¥ÿÎRUËvæÀ¨C⢸õª&¸ 9‚,šS*á‚6éþÛ#0Á„ŽÙæ›Ã–¨ÑÄ-è.Þ�z-&¤l�i¥¯ Y–áÙÈVa»v‹1QÇ#ìþû,0´D”~ýª(³£Ä+ùZD®¼&ÑÚ!c|­ó¹Á+Nòþçû`Â7+¹þJèðéñä…2Oâ‚ã-¶õݬûƒ2•nŸš”aÂúØÕ7Ðzç5Q�M_EÝU6’l¹áqÁnƒÍåW1ÑD2Ô¡s¬±ß_Í™\d‰h'^„”l±8a�*ˆ^EŒ\p<^5œmiQ”£ŠÒd‘OïM¤Q‹46Y‘O¤íØcp?:˜äX¤uµáE R´äŒÞ¦�1vå? ¤Ef–&Ç–l®iQ‘Š©ž�µy!Œʉ£Ÿ+2YÑYYZ`�d~X�?…>Fâl€*IT£qq&Amey™•‡h�)ÊÝfö¥èߣ׹Eijpmªb~þ�RÅ'~‚UHÕWüýS®ý�*¯Eõ†©ag^Fn±¶–@¦A¬H¸ûÕ|Ê*ˆêjhíeV²"i[“¥Ë.ë�qá–kî¹u†îEÍ®ëî»òé¯D2Á9ï½ïšv,¾�ÊËï¿ËjT+ÀlðÁ'¬ð 7ìðÃG,ñÄW|°“H¢±ˆe¬ñ%*n�‡Æ’Èá�Å‹LòÆË­L2ÇlyL2È(?¬ò%d”1Ìÿ\! ͽ•|2wB×ܰÏ&{X²T’À<Â$8Ç ´Ñ ?=õuK·\ÒÅJ*Õÿr­SÆé‰uÏMwÍ3Ø¢Mܪ6íóË]ÿœ“ÏéáÝõþvlKÔ—Ûp‡ê2ÉIÇúñ�€ ¤ IÈBò�ˆL¤"ÉÈF:ò‘�Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“  ¥(GIÊRšò”¨L¥*W9E ¸ò•°Œ¥,gIËZÚò–¸Ì%.ñ¥Ë^úò—À &,ï%aó˜Èü%1“ÉÌf:Ë|¦4§ÙËhRóšØŒ¥5³ÉMjn³›àlæ7ÃINc޳œèôå9ÓÉÎ[®³�ð”å;ãIOhÞ«žøþ”ç=óÉO{²òŸŒ‹CÜ…€‚ô <¨B@�t¡M(D ÚÐ�®k¢ F:‡^£�hE×Q‚l4¤Å‹COú�ˆº”¢,B2Ó‚@ô\"µéBeŠQ•”¥ehLRSƒµ¥ WL�ÚÓŽþ4£¹)Q“*U“îÔª�*TušU®ò´¤%ÕªP›*�•n5ªgeªB�zÕ‰õ«yëWÇ:QŸ"µ«l•êPïŠW¬ö5¯½k\à X¾.Ô®„õêKéZU±¢õ¬…¥)dØ™n±�Å*W3+WǤ­Ÿ�¬dûÚÖË:Õ°rMì^;Ë×Ѳ6±”³,X“ZV‹nö"«…í\+bÙ ê–µŽªGóŠ[Úz6´¢õ*j�{\·ÂÔ¸ÃU.o™ûZݹ®f…k[éf—ºÖmít+›\ñZd±��înÏ Þäj×¼Þ½mqŸ›ÓÚ†u­ì­oså W±’÷¿�¬—KX�îÕ¹9]*U™«Yä&xÁú5+~ûàú*x£umUË݇ê÷þè‡ýbt¸%Æ)ƒQ ÝîšëÄüÛh@!ù5ÿ, £H° Áƒ !ùÿ, £ãH° Áƒ !ù&ÿ, £u øG° A‚*ü—p¡Á†Œ(q�¿‹1ÒÓ!ÐbÆŒ!Ü�-äD…|ü©bxÒ É}:X.´¸RæÈb0%*¤YPä¿ 8cê48IåÖ2ømýW´æÓ”R™’tzÐçB¯ ÁvméP¬Á€!ù ÿ,�F-þH° Áƒ*\XpŸÃ‡#JœH±¢Å‹bÜȱ#G�12/¤É} OJyŒ¤J�)_FYRæÆ”íBÅL§€xÌŽp@j(O¡;Y’ì @À(ˆL�Žä" %U >� ¹ú¤=.O÷å|Êh 3<¥ 9†v³ªk…ôòR’¦ÃvtÝ® ñ´çÓ±ûÊú�Ò®ÞºGZjÕªX,Oq�éøÓ!SÊ�íjNìbáΛÓTZ²ÝãÈ�¡¦Öì2têŒ~ XðÒÛ™Q÷â+°åÖ.k›}�2¶åÉ<³ŽÆ=ù'éË«'Ç­ Z9ñ˜! Û<‰Ý£öí!ºŠO¾<€èÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿ÷qÄñ߀÷Hà�óˆà‚î)Èà�40Â…z>È_þƒá„!$ÂE…êg#n8¢„ †¨_„$’8á?)ª¨Œ$B¡€2î‡a‹-NcŽó�Èa†Bþd}¾ˆž‘GΗä�MÈd”âH¥S^I_–ZÊÇe—ð} fƒVމŸ˜f®‡fšé­É&Œe¾™`œrÆçæ~!ù/ÿ,‘ ,uÝüH° Áƒ LȰ¡B‡.ŒHqàÄŠ/bt¨q#ÃŽ‚ ip$ɇ'?¦\ɲ¥Ë—0cÊ ¹`�Ìš7mÆÄ¹S'Lž?}¾:T¨K¢G�¶DºT)K¦O�®„:UjJªW­žÄºU+I®_½ÒëìØ€!ùÿ, j¤þÿ H° A�*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç� !I’ µ@©\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@kò®œ»£H“ƒW@ɧÔª•nžÕ«X³jÝʵ«×¯`Êk5]U²hÓª]˶­Û·[‡MJ×ÝÒ¦PóJžß¿€ L¸°áÈ+^̸±ãÇ�#KžLY±\£u‘Þuª7/ßyïB‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¬/gÖÌ”sç§|åáN¼8írL´Wz_ï~H$›ñëØ³kO­{·ÝÞÂþÿ&|�ùóèÓ«_Ͼ½û÷ðãËŸ¿ÞÑ–uöÓƒc2Á׺_ËÑ·^='ø'à�&¨à‚ ®ÓÝn›a áãEÕWƒf¨aƒûuò_€çí²G�ŠÃ �n¨âŠ,.ø ]óÀÃ[S ,€…Ä×;ê¨óFB[ô(ä�Diä‘H&©ä’L6é¤:Ð¥”=î7Š”Ò%äË�QŽ2]'Ž$´G�Y¶0 @ªS¦8Q±Ü“pÆ)çœtÊù <óÐãQ›%�À�9êÊ;ã:N”¾ªè¢Œ6êè£�F*餔VZ(4ˆsh�†î²¢Š:²œ¡Ð „8Îí1Î.Ë�*"¨þ®îQªª–Öjë­¸æŠkwx.@ƒ{nv@�€Š(ë꜖º6ëì³ÏÂÊé8Ê0á ¨¤N»i¢Òú’%� ~ À§ÚBkî¹èÞª[¯2Ê(1 K,ŽÆò•,€¾T›hºüöû¬¾ãà{)š í»m¶ÜrЍÀ—rÊðÁþF,1ººÍÓî»ÇÛÔ°6Ò(_ê¬zê/ýMlòÉ�:Å8*CŒm¡oœŠðÁˆB£­4ß<3Ê<÷éº[-ÕÇÅÖ Š:Ü(S@á 7PG-õÔTWmõÕXg­õÖ\w­4Óâpƒ(Ôˆ~ ¶Ôc§] 7ßBÁ ¸ÝöØ]×m÷Ýxç­÷þÔ/Ö%oÇÆ‹ôÞ„nøáˆ'®øâŒ7Þußtý]ôÇ Œãøå˜g®ùæœw®7äJ =oàÿHUË8u¦®úê¬÷Xhë°Ç.ûì´+ úŒíqŽð“RPÀ/üðÄoüñÈçt;Ÿ¢øIþD/ýôÔWoýõØg¯ýöÜwïý÷à‡/þøä—oþùÝ/ÿÝÆ£?�þûðÇ/ÿüô×oÿýãó“ Æü÷?J2ìs^½ðGÀð€L ­Ç�Q€#+åˆ`9ˆ¢ŒQpr¼[ 7ÈÁzP� ¼ŠŒÜAAe(c¼àî*½éÍa ó³G�>ˆ@çøbzö ˜–ž1¦©ã{þ2¼! ‡¨ÁîÉå0¡ “�B æ®}œÞ3Zà4ù‘ˆø£ 0Cëí꘢8ÄÄ+bñŒø áR�˜Ä%2q*$] £çˆFÔÑŠ]DcýÌX½94Âb$c�ø¨ÇBÂO�2Š “ñF'êNŽÓÓ¢/žÆêÉÐKSBþÈv"z<Àˆ„hH<’‡3 ås¤§ÅOúã‹aô¤?.I0–ò–åC$ÙÈ8ºOz”T‡$-i*u8ç�¬G?ùŒ øb™þÓ)qy>BJ–ÓÕ£ç©èÍ¡Ðlæ3™GjšÓ{ºT¤gÇ' ðcÙä¤},9Ã+1�þþøf0gYÎs’ÏšÞä¤ôø(Ce‚Ÿß,c?ýÉPÂk�êT#ÙéH(Â3z9\Èr¨gÏz¡�Ø'@ Ä…Z“�u¼#H:M’ºÔél£D{éN ²ðš•ôG+9êÑ–Ì\4¥ùRA ñŠŽÈ©ôæ T@RqŒá*9[ZT†Æ”—õeó)ÐhÚr =åç U)Äe�²ªÞÓ¢BÀD-rR­>¤ž¿JV±æs\huéU×ÙÎGþ2¯€ ¬`µ·×™fµ¦+ω©��ö±�½ea'ÚW‹f0²˜Í,I'KS¿nU³  m!)4¢Pð°ž½¨hWËÚª1OE0þ„lßuÂʾó²­Í­nøÚ"ô/µ­èmoºÛâ·~¤]ŠiÁ\­ªö¸Ð�.ù^KƒØÎvÍE,$¯7Révï…`¥*öº»=?^ó«áõnþ:ßò¸¨µ,q­G^õboŠU´«÷FZßnzÓ•¨¯}³—\x,7»©Å-=<`륔“õ]0}*Å�T F'{«+[wa7¾ÃU¬ �ÄOLþ®Î°N­%Ò˜xÅ a¦,YZâZvR9Û\ñ'ý;ÓøŠ¡tl†_û[øÚÖ¦"æé3‹)NÿªXŠ`fêL'‡Ó™?žª]wÑÕ;~3ÀYç ¹üäÄHþÍþ—õ3êó]}ò½ªß7sr¥Z¦±*ñ L è‹› óžÑ;`΢9±jær$yÅ�F3“Ož¥qÜh&¸2L!ulBó¬e|Ê• £¨¤ÍéI ¹ÌM¤L)+Ü4w¦…°gÿèé9«›:žµSs\Ǩ*³@;µ¡=Qgé…‰“±Æ2°-ýÊ6;ÒÑ3ô‘ýjV&§iã\¤—uê›×Ø[�¡¶wœ��ÖõŠËââ { CUZœÑS+¶Ñ�uߘÏCNõ.ùÚjjëe±Ðxn¥Ýïí üà­%¸sŒð†kVáÚý«Ã'Yˆ'x¾ϸ`-.ß$küãyåxˆþ ò’U�l\ug;Nr“»Üª£P5ÉÄÿ\âJæ^„w ^ŒRx¼?ß^F7Ù=xß×™Þm 8T-ÓEÞü³9zЋ‹ß£NÃQçn=Q@hðí\·úóŸØŸþܬgïë­}°ÏŒõŸ½‹žÚNÌ@¨y®þ÷ˆñzÉéœ89�åYƒ,f¿²© •d‹_Œâ{2Ëg"1áÓ«ã/Çð_DÑ]Ç5ôp§rÆ'Š]ñº{g}‡ºX§Æ*u¨mž!—yœâÐSÊLvý@� He‹yõa%óÚãmit7‚ö-õ•— Ãd†V}’ó·g¦Çæßç3¤pe%ïþÙCΟÀ ?díœçéfìßYÓàTþçòú.*¾ûž?½µÔQSosÓ>½:`¡�wéC¥…£f-•vi™ÔböO¶&ZCWn¿vCކixö{zÖmú%Fq§v÷´hØS¨_gzÞ}—lKFkBÖk¼'Mº¦hE�c¢…k­¤kµÖ¾ÖVÌ&l[WlÃöxÏÆ‚PU $X5V Å 7_òæ4âc͆cM8x=Cs•[ßFGž7nMhn=”cVo3Än÷öz:DJî¶b¶dƒLSEìd[hWswr xwGèq/W‡¸d„©Wvv¸‡h„‡G‡|ˆDä‡,Wm‚xˆþCDˆ#gˆˆØˆ¤ˆy7}Ž8‰ ‰þ”˜‰¼‡™!‚8§‰ H?–hpvhC¡˜@£ø‰%§EövŠ”ŠªçroèŠæ‹ÏÕc|çb_"zÔw£JÓ!Un"“Z…‹0䋚ô‹¾xgÁøkÃXŒŽh‹ ·zÅtL¯$T¹÷{\¦kƧ€?÷S`„�ÉÄz²&{4ølß8‰ÔˆqÕWÀ'DoÆ~lÈ~àØRïV4v}ƒV�$ÆŽœè7ýgp(�=5€žd¨YÖT�ðHc­”�©´�ˆØŽ„ú8HÏ&F+è†=¸ZÖ„‘\h�&¨L9l¤W‘9ùWIh�\¸þ„�†fT†šWqE|i“À‡…4 wQH‰Ùr^§7‹ 8”ŒX”lrH©‰J©wFuˆO™‰Q)‰´˜•çs•ÿ§•^™K+:sH”_Y–é–¸ó‡di–l‰=\‰‰m—n‰–Ì3–KYRMY\³hto×R='ií·d ‘’ ÷–%pÝS•Æh”SYaù%C4àJ?Æu g˜ä1>Š Z™Ù—Ô£v%¶}Z¶kg™#1GÈÈO¼Œ¢Ä˜ºEHªäJ‚§e�wš„¤x é æµ�Ž–q¤ –Cͧ�ŸDTFP¼'k){¾àV¿YN·g-ñ¨›†Ç›t‰zj¹”ùÈ…þ¨b|R˜�.˜�ñd…[æyÖ7L×›€“ÛYœyä�· žŠ&¤FJ Hi3¤EWb}q7qê©#8Õz0 {y¹[ÆT&9œÊÉœÜDeÖwxáƒ@©œ’V{Z�ž¸U/ �fÅš¹µ€´Ö†O˜gÓ šGUèU|¤‚cXrjZùŸrÉ@Ú’±¨‰L~5:—s‚8ª‡“WÙ£Ò£{a¤JФ¡¤Fʤ¥ã¤= ¥ˆ)¥_I¥V*—Xʇ¦È=]ªVEZ–[ú>›™W¬¨g*Dó4O˜ ¢Ôù£r˜‡ÕX>e Xh7€¢Ù˜‡8¦›—Œ¡Gt76JpyþÞ� ‡IËH˜$Õ�Ï(aðèsˆšš–W6Fxâ¦ǧkœÙ¸ �æ V–ƒÚ{K6Ž¿è|vÚEëèvfœ¦ŠLR5f4|騨…y£v)•€Fx›<aaÕ��šW5 “÷�y„¬“þè}pcê�½úCf„ið(¬DH¬pW¤•6VB¦¬é­9V§Ò5¦"i� JJ½¦�Ç«n覥dF‰akŠ^ÊÚ‘(Iy0Š«rЄצ„Á'&@È€wežª¹JÊj¦€W6©“Ô!Lׯ£ï:’e†îF®Ñ¥©ÞC£Yêrû]ˆ×±˯ש«ÜC¤.(²/÷±*ëþŠ,Û²¡ø²0 •$[ˆ&;³.[³‹x³8³:‰yˆËÂVã€É�©Kú³—x˜|È—æKõг2«qU8L”T- :³|J›ú‹�Ç�]»c-@©é7’0 4Z!4¾ÄfP°–?œ¨Òu &C{Щ`úk?ø¬qY14з}ë[£]Ú$s Øh˜}‘6€78¶Ùª²@£±õ.ñ2�LP ý�¹ý@IàÐÿÆoС;ºÄøõyŸú…iOViW2FZT ÐɱVÊ+óà.É,ý×™"™Ë¹ž ºÐ ›;¼ý° 'k:¬ èmÁI¶»µZKJ1þU—ˆå¹ñ»@йÏð¡Û¹á½Óam;Y» H{\p5V²$o ¹s!4KQ¹j›½'P ¾»¹Ý»¹àÛ¿ãË¿UÚ³B ßA¿}ý0¸ý0Æ�) ºü�» hBÀ´8œÀôG ŒP°Àõö¿âKÁ¿;À܈CÁÁœ«$¡¹QšÂ>Ë ìÂ#Ã(,Â8ÔÃ>,AýJ:Büo!QÄF|ÄHœÄJ¼ÄL¬%[!~rPPÅV|ÅXœÅZ¼Å\ÜÅ^üÅ`Æb<Æd\Æf|ÆhœÆj¼Æk\Ã’CL~’ ÅS|ÇxœÇz¼Ç|ÜÇ~üÇþ€È‚<È„\Ȇ|ȈœÈŠ¼ÈŒÌÈo Çq,s<É”\É–|ɘœÉš¼ÉœÜÉžüɠʢ<ʤ\ʦ|ʨ¬É‘<©ÜÊ®üʰ˲<Ë´\Ë©¼Ê¸œËº¼Ë¼Ü˾üËÀÌÂ<ÌÄ\ÌÆ|ÌÈœÌʼÌÌÜÌÎüÌÐÍÒ<ÍÔ\ÍÖ|ÍØœÍÚ¼ÍÜÜÍÞüÍàÎâ<Îä\Îæ|ÎèœÎê¼ÎìÜÎîüÎðü @�PÏö ÉñœÏú¼Ïÿ0ÏöüÏ4ÀÏ=ÐñLÏ�€Ï�Ð MÎþÐ ýÐ�Í Ð]ÑýÌýÏ�àÐÝÑ=Ì]¬LÏýÑ&}Ò¸Ü7ÐrLÒ(ÝÒ.M:*=ÒýÒ4]Ó�AÏ"-]Ò6ÝÓ>­ÓMÑ?=Ô>�‹`Ï4ÓD½Ôí!ù-ÿ,‘ ÝüøÏ�Á€!ù/ÿ,nÐþÿ H° Aƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç� !IrdÈ“(Sª\ɲ¥Ë—)KÊ” ³¦Í›8sêÜ™q¦Ïƒ<ƒ J´¨Q†?“<Ê´©Ó§P)*UµªÕ«XuN�™µ«×¯`{n%¶¬Ù³^Ç’E˶­Û¡jM¾�K·.˸íêÝË÷"Þ‚} Œá/Aˆ¿5¼T±ãÇ_ „L¹rTÉÿ,kÞL3çÏ ozMºtLɦS«æ8zµë×[ÞM[6íÛ«mãÞMZ7ïß›}Y8ñãˆ�#_ÞW9óçu�CŸÞV:õëe­cßÞU;÷ïU½þƒßT<ùó�Q£_oÕ<û÷¢ÕßoÔ=ýû*íãßR?ÿÿùà€ Hà�±É‡à‚ý)Èàƒ:á„JHá… 2†á†È!€~È_ˆ"âGb‰ô�ˆ"|*®È^‹.¢cŒäÍH#x6ÞÈ]Ž:bÇc�Ôý$tBÉ\‘F"‡d’Ä-É$pN>É[”RâFe•µYˆ¥‰Zn™b—^²f˜/ŽI¦ŒfžYcšjâÈf›;¾ §�rÎd�v‰gžGîɧ’~þÙd ‚BIh¡SЍ•Š.š¥†Žº i¤qNJ)�–^zg¦šêÉi§}~ * ¢Ž:h©¦Šjª‰®Ê*£þ®¾ú¨a².we­zÝŠkt�îj™®¾.Ök°Å K¬cÀ‹V²ÊšÅl³a= mdÆN+˜´Öf…m¶WmËmxÕ~›k¸âòk¹”y‹nyä®ë–ºîÖ×n¼ËÎK¯³öÞm¾úR{n¿×ò °¶˜`ðÁ'¬ð 7ìðÃG,ñÄ „ð?ó9…dûtìñÇ ‡,òÈ$—lòÉ(§¬òÊ À'f,Ç,óÌ4×ló>.ç 3ÉÒÏÍ$³b°)@]sÏ?wŒ4É9ÛiÈJ•¼´Ñ×#B-1#=5Õ(o­´Ï{ÝòËy,PÇII 6×Jg�ôÊb³-óÖq{Üôœ$Mþó±�Ðð D<Òd€õ×?÷Ü3C#Í œÁ8Dï „û\x<ö8±øÐ[m0`+.9è¢À‡w¡9ߘNùÇ–Ç.9æmÿlu<ŸŒ^Ëâ Ýûå¿ Á:Åûáß gÞgïóOçÈ =8ã¦~ø?K+^Ѭ¡¸Û{ƒD7"ý »Ò…)õQþ߃‡­yéòOçD#Þ3úêƒÂü—4«p~ø ð1VP[s ööñ ñ }‰[Î4V¶áOh ÄžôÌöüu/¸;a÷܆Z|BZ€á ߦ5Ú�†÷[á ·�‰Í�þûhaù fPy3b3གྷá®yHïøð0T!œÝ?Hø� ªPëëá —È;>¡s¬Èþp˜9/ŽÑò+×ÈCj°c�ë†æ 'FòÑt‰›cÝœ×&èUQuÔ«ƒH¹ JosT" ÁÀ‡�‚ ”†üæ¾ä‰‘��¬à ù6ò]0}˜Üá> ˜Ê;vÌ}~[š(Ç8ËŸ­ï¨ !ÕdH«ýƒ¨Þ?²˜=>JïŸÀ˜ë¾«¹îˆµÓÝÕèׯOÚÏ–­‹#4‰H4Æ=3šªâåª 2H2Ë\ãä–IÄÁi­�oÛå™ ‰¹Ùóžøþ4™<É´³|úóŸrÛg˜0CЂô ´ÒÙAÀІ:ô¡�¨D'JÑŠZô¢ͨF7ÊÑŽzô£ ©HG*Q„þƒ¤(M©JWÊÒ–ºô¥0M©IcJÓšÚô¦8Í©N7jÒ“îô§@ ªP‡JTôô¨HMªR—ÊÔ¦:õ©P�ªT§JÕªZõªXͪV·ÊÕ®zõ«` «XÇJÖ²šõ¬hM«Z×ÊÖ¶ºõ­p�«\çJ׺Úõ®xÍ«^÷êV ÖñŽo¹§D^‡ MèBúˆN´¢ÍèF7ÑŽŽ´¡!=hfa΂F@‘é9#Î’Žt–£ |ôùÏ&%rŠWÍêV³úË®Žµ¬gMëZ×ֶε«q½êOlÁ×)F_䪡Ž/ãúÌÀе­³Ì N”Z¨F¨�ß‘â2 ÅÁ% ¶…3CØÂœ•Mîrëš×êø¶Á@ámp‹›Îã¾ël¬kc1Û±`µ¼caib¹ Ý6ö¸Õ!ov›;ÖïÀ%œ�hGÛ Ó‡ÄÇ!p(ŒãÈC(.N€XLüã ¹ÈþGNò’—üË×ø8˜1xoãðŽ…¼·r�{|âýÞ7Å=Íó˜K¼à&úľðg?✖øð:Žò/÷{ç7ºÔ§Nu‰£\â,¯…ÄËŠ§Û<ë_ºÏ'îk¥[åë³¹ÄãᄨW=äëP8Ã~ô‚±{å¨Û}ît!Têo¼àA~u¼k}\÷zÏÁŽõ¼ï½ðuvb-PÎv>ô¼ñ‡üÄÕ!w£×Ýîê¸8ªÁr¾óüå×¼ê«yl<ë*‡ù—ÙNs¥�¾ô…¯àßÇÁvP\ýÛLŸóÎ7¾z‰s¾è ÿ<è¹Áö¡çÜø27†÷nnXÿúØÏ¾ö·þÏýî{û‘77¾ýËXXŸúÐ�<(Ø^Dè[àØOûœ¯/{ŒÎüßÏ?ö�?wåK†Þú€8€X€Û· yg€ ¸€ùÇžçA9ãÀ€X�¨}e0z¸�8�—|�ÁÀ ãpp&x‚æf|º&o¾ƒ‚.ø‚«6¼ð�t‚j±_¼ a:¸ƒ<؃>øƒ@`3ˆ|5hƒ[þ�„J¸„LØ„Nø„P…R8…TX…Vx…X˜…NHƒFH¨…`†b8†dX†cÈ…]8_h†l؆nø†pÈ„h˜†S±†qx‡x˜‡z(‡DH‡G¸‡€(…�S U8ˆI¸þÇS �h†sè‡?a‡dh5„¸ˆSˆˆ]p5•è—8‰Ÿ þЉa(‰”؈Ž8�8†¢H‰T˜ŠS(Šˆ þ@  ˆZÈŠ€HŠ¥Xv89žh5Û¦:IH |sÓ4o–g0Z`5b@Õ Œ‹Và | ÃÃwÈŠÎÈŒM(ŠÜˆ‰I�ÓX�Á;‘ç‰ÙX ʨ�mˆ‹¹8§(‰Vã‰�ƒŽsö‰Õã‰ßˆ‰Vc�V‹²X Vã 4Ö8�q˜Š¢È ÖȄݨˆ¬� Œó˜�|Ð�„¨�û‡ìØŽa‡BC<I B0þ ‰Â¸�‹³˜„` )i‹m˜þŠÎˆŒçX’úx““h“„’DɈ‰3é“0Ɉ}È‘2±†²X ˆ�8)’$™Š½ã’8©’´Ø’/é�o(“+ù„®è„˜”Jx•µ–ùø•[©“)R0li”G©„á3ÿh‘ýh�9ù 9•u™”by�Þ˜‘\é� Ša©—W˜h‰˜CY†r Ú0n©‹JˆˆíÇ”;‰‰IŒŠ4:ŠÈ8?9‰Ùx™¢‰–nH™ID’3‰�‡8oE4”)�KØ—©éž‹Dô™y  ¼™$qŠUH–ª8œÄI† ›œÀ›¾éŽ`°YœÐ�Wxœ»Ù›ËÙ‘Whšê/(�ÜÙ�[ˆœÊy�œÞYžæi…�§ï žãyžîùžT`PŸìyŸŽ!ùÿ, �ÏTþÿ H° Áƒ*\Ȱ¡Ã"JœH±¢Å‹3J|ȱ£Ç� CŠ ±¤É“Eª\ɲ¥Ë$QÊœ‰ñ¥M�úr²ü%$^Áœ:o ŒI³hQ¡ Y Xz¦¥>ž>UB…úèÁOš*]Ê4'V|nЊ Q£hO"]ø)¬@JQU>í¹r*]«·6HÏY}XË üå@Hß‚a¦]lr­B­€Î�7—瘡„\ŽGXâ_ûv�»y bÀK…@­lØoÖ_"ë|êÀJÖÙ¬þõ$Üè§gPÏy–±qŠŽjð t5O‘¡ÿ£·X¾< ‡sœÑÞØãVØ1ƒ™<¤Í®èµcuÑ%§<ÈÝø½Ø‘Ã�µ¨Ôk4pGLNò�¤äR$YERnÍ”¼Éñ2¬5Ò•°„M-Ý¡LPÞrƒ¹œ£2óøLDòïXE»I6Ò c¾Ñ‘­€$/˜A\–Ñ„æY±·Éõ2‘1c¥Ú¶"G:ŽQ�’þÚc(ÕÉÏ< ¯{ç5G•‚ô M¨BÊІ:T¡úóe"­Ï�€0ž„F5Jƒlô£ ©HGúQ7�ô¤(M)H½'ÑD¶´i"¹Y9Â1 OxB�°©NwÊÓžúô§:íP‡JÔ¢î”wŠ›èÏ^Ê´˜‚0¹ˆªT§JÕªZõªW V·ÊÕ®RUtJåZEA’³™Šî¬hM«Z×ÊV¶†®­p�«\ÑšÔ°úŒ©Ksª]—º×¾z ¯JÓ«_wØÁÚµ°>¬aËØÆæL±Ž�¬dû*7Xö²˜Í¬f7ËÙÎzö³  ­hGKÚÒšV´"ÑžjWËÚÖºöµ°�Ï­lgK[תñ¶¸Í­nwËÛÞ3$Ä®p‡KÜâ÷¸ÈM®r—›\`8÷¹Ð�®syAÝêZ׺ÒÍ®soÁÝîz÷»à ¯xÇë]`ðB$ÌM¯z×ËÞôjW»×�/vß+]òÚ÷¾ø½…sÑÛÞþú÷¿Ê¥ovå+_G7¿N0w�Á_;øÁý5pt \` CÁƯHîÆá{øÃ ±ˆGLâ›øÄ(N±‰çÁâ»øÅ fLãÛøÆ8αŽwÌãûøÇ@²�‡üã¶U+ !ù{ÿ,‘  ÝüøÏ�Áƒn!ù5ÿ,"£h5þÿ H° Áƒ Ɖ“°¡Ã‡#Jœ(p!Å‹3jêWŸœiæ¹…€4\ „•v&¥jÙ]^K\èZ£È…Fƒ@C²v�_�"Gin�æö©m¡Ú6ªlÿ!ù9ÿ,J£H° Áƒ p�@!Bƒ!ù/ÿ,J£ãH° Áƒ !ùÿ,×oæþÿ H° A�&Å8Ȱ¡Ã‡#J<8)ŸÅ‹Á¡ø‡�ÑÆŽ ANI²¤I�1bÔøI¢D`@ºTx²¦Í› gäc‰ð¥O$8ƒ µ©%Ÿ.ƒv`]ÊT¢Np@vôés£T;X³Ú‘@ÐV Z£ÔеéÒŠGºÑÑB—Q1�Í*Öë\;uïÚ1TÈN±]iBÌÊõŸ];&VŒwì^¾7Ñ2L¸¢\Ä¿¼œ˜3ä¥~¡ž¼›Ø°æ«�ÿ-þ‘Q“z1›Þê8êáÕ¬KÙiu¤ÖÍXKÛ-Ì0²€sKt�¨äeÀžgW�éiåwóµðëÔ“þ—�"óÑe3W?+P¹ÆÁ—gXt;ÉÛd¿Ó螣^ñó¤S>ÍÕt™{Ñ WjZMàƒF(á„Vhá…f¨á†vèᇠ†(âˆ^!I!d¢$,¶È""5$„‹ÉÍ0I‹(’¸bŽ­èb‹0dã�€Íð£$—TâŒ,òèÔ$Aþ3d”iqbaV:Ù¡‘ˆÌ¨%D&¢â• q£@F&ù¡�Iz™bN“¨)%’JfA&ˆ¡•@¹9Ñ�ÊPžxJ¢gPIQ¥¨Rú�Ÿ¥©dž>J�£cŠÉW¢‹úÄVCa)˜'^zd“XZjª¦š9ШþIJ�•T2Ÿ…²š!“§JB%}¥Îªj¦\ah°fqÚ)£ñzê¯Í­±sI-µK)Ûé§Á ¬xÔú)豇jèm´¾žI�´êþ¨«hÆYç‡ç„ëA´ž¹¢XY¦ú¥‡õŽ ­�§y¤œ",å�åºÛ"ÂBÞˆ*‰WlñÅg¬ñÆwìñÇ ‡,òÈ$—lòÉ(§¬òÊ,·ìòË0Ç,óÌ4×lóÍ8ç¬óÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷þÞ|÷í÷߀.øà„nøáˆ'®øâŒ7îøãzc ùä”Wnùå˜g®ùæœwîyå}.ú褗n:ånœ®ú꬛žzë°Ç.ûä¯Ïnûí¤×Žûî¼c®{ïÀ÷þ{ðÄÛ>|ñÈ·~|òÌ»Þüó«/ýô›KOýõ–‡Žýö™kÏý÷”C.¾Ö tùç›4ú—¯~yìOèþüôÿã¾ýèߟ[üÒï¿ùÿ›Ÿrø—! äð{Ÿ†ôGb‡€2 þxÀ6Ђñþ8ÄÀûy�}Œ_ß7BFÐ�A!C X¿ ªÏ�Ä� +hÂêO‚Œa8È`‡c7D!)ÔÇŒ�† ¢‡Ø¿"6ˆ „!ÿBX@&:$†,”b ‘¸ÅéЇZ|¡mèÄ•ñ‰"Ìâó·Æ3>Ð�)!/@9Vè‹#9¢ éÈŦï�ëëbάˆ3Bò% !ù-ÿ, £ãH° Áƒ !ù8ÿ, £H° Áƒ !ù6ÿ, £ãH° Áƒ !ù&ÿ, £H° Áƒ !ùÿ,Ÿ¤þH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜÈ‘à¿�ø»ª¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§O—üÊ�sG´¨Qwðà�2$/^êæI�JµªÕ«X³jÝʵ«×¯`ç©‹¶¬Ù³hÓª]˶­[«A‡=štiÓ@É“÷®¯ß¿€ L¸°áÈ+^ün/ãÇ�#KžL¹²å˘Ç�KW)Ó¦yçeMº´éÓ¨S«^ÍúòfÎEë~ºµíÛ”Y $À·ïßÀƒK~ ©g ÈCê]Ǽ¹óçУKŸN½ºõëØ³k‡ÞË»u½@þm—^/E¬ñèÓ«_Ͼ½û÷ىÖ�©›4Â1¸!m¬Y!kÒÝšrˆÖ\mG¡;ÄÓ±D¦kïGÜí^“»£«\9hÀ®2µ™¾Ì®:É+Êàzɘ²Ô.}ç+^óÖ½µ¼­ö[]»òIëÔCk›Xz–wŽÆÝo!Ìß›Q�,JóêDW‰v»µEèA'èaý"s ¬0ˆ/¬Ì ¸°œ{&‹?'ãÕÅîýœ&jãÎíØ²=.*ŽÕJΊYs:î‘:dÏ.ùɘm²u¡Le¿JÙÀUÎ2[¯ c-{Ùª\–ì—ÇìÔ0{õrw·:Ô=ê$š‘Ý'ös.ÀÑE\°›«¾î‰Ë‹éÅnú�#Þ/C >pX^T×­1æløÝþªX„&D%Ä÷ûåàu°x ß·“þ)Zq†£¡oÃ/ŽL§S☻¯rM|iE£–ã~.Wqd7ò1âÛäÜ­,«KNó™s¼¼Çn7mí`£×;‚§]yÇu^œ·m8åF°J+sŽMå 5h&7žÑ„¢¶ÙãU`ÑÔ8�4TíÒÎrì¬h2Ûݧs—–ïÎw¤R}>zïrßÏÒ¼™ðˆ�îß9C÷Ä;>¥†ïùã'ßâÅ?-ðb¦¼æù)oþóZìüÞ�=ã$R†ÝÎ5�xYÈŒ¶Þ·ªo½>o~IFƒÞt¢<íC7KoÓtë ž7rÛ<Ɖ60Å•¾Ð÷!eñò˜Ìw>éó}ûÒå>ó»]ïcþíÓò8Ñ~>`c0�çû…;¼¬iò#™~Qn¿àÕßÜõQºÄ]Ÿò¢ñ¶µšÍvŒ¢2ÞAÄk2å}OÔ VJ $(ƒÔ@&Dl>pi€Âpÿlfkì$µk²EEv7ô£m¡Tnö¤NãÖhÔôG¿L*…FÍd€ßgDBW~¬FPgBB×uå~7‚ÅE‚å·\ó–nJ6føH I/7L¥Ö?ÒDtð—M=¤…bä'ƒFHìPh&|³öh€„úÕ„áeryÅr¾Gi–ç5=×KI¸JÓ„s2Ø„¥¶RªThÂô‚ÉôJN4k±wt}¨FÐf'†òÅ„ÞÑ…þþõ„GV„1÷sÚ%~Kx‚w8‡)Å‚d¤m1¸pëôL ˜g—|gOæFafôI{¥‰ŠdŒ8P©Çq…sk‡9k÷ŠRÇRI2}î~aŠø§g,(ƒzt|xCûSbü…zZ˜ˆw·Šñg>0w{ÎÈ:(7„ÏH:?v�•3�Ú=I¦‚ÏÈ�Ý8Žá#ŽäxŽÏcŽè¸ŽÊ£ŽìøŽ»ãŽð8�¶cŽg¸fÄw9s–}©³�šSg¢tgÕgg§QÒ‡9÷È]öÈ}èEh†¶bˆÆ�дh¢¶N5÷\œæ~\ ™Š˜¥iK§g 9}ÿjqötÔ§95·ˆiè6˜G­†þl¼Vˆ^³6†)`k¸&$ö×k±lÏ–khà€>dljäkã¶lB©g•Å„V¤]H)b,)U÷’H|@˜\!‰Yàf‡ãÄpY™zèæ\­øFŽè Áøn&o"Xt·”ýEŠò¦nK¶Š�D{@tì—p·r¨¨qCq˜¤9—vÙI–„_}™—66�l˜u'§zvY׆" Kƒù��©pn)ƒ›¦˜`ibS¹s<çyf©rèƒF™œé‡>ˆ—”–�d~|b˜pè—�{­Y—-ù7N�»‰^UXƒÛõu•¹]bgœôU”eÇ—¡hD±˜o bFÕ™ÑÙ˜½9‡þG� �¦–�¥9zܹ@ÙH„àÙxã¹@ߨ�çi•éùžõØžÛ Ÿôi}ò)yõ™Ÿ£#�úÙŸšÃŸþ ÛxŸ¦ÉJoé‘&ˆ !å*fg9ú„J¾(ŸdzÇøzìäz÷¡ê€zÁ4{ý·z½3’`F âii™‘ úPÊ0FÀu|F$c2¦|Zà¢}÷#£ê c—Øf6ºgyfG'ºe$ª{&š¢$ùSh0ŠIç'_úaxøLWøKí‡iù;"ZU«X©õ”ÚD4©WM4v(JW|åD8b5IK ¸{´H‹ ¸NùÆ€Úµ‡á÷Šéd§û“¦üZ~ ¨¿ÈZþ¤kµŠ ø`ºyšòtb×—¼Ôfoh–zu†$CùÈ�Xè ¼Á¡»×u–Ø sЇ8xoÅ×g‰Jb{�–üÃ@ÄB<ÄD\ÄF,Ä“s p0NüÄPÅR<ÅT\ÅV|ÅXœÅZ¼Å\ÜÅ^üÅ`Æb<Æd\Æf|Æel) pÿ°KlpÇr<Çt\Çv|ÇxœÇz¼Ç|ÜÇ~üÇþ€È‚<È„\Ȇ|ȈœÈ‡Œ%k¬Än|�É’<É”\É–|ɘœÉš¼ÉœÜÉžüɠʢ<ʤ\ʦ|ʨœÊ§ìÆ�ìȬüʰ˲<Ë´\˶|˸œËº¼Ë¼Ü˾üËÀÌÂ<ÌÄ\ÌÆ|ÌnÌÆÊ¼ÌÌÜÌÎüÌÐÍÒ<ÍÔ\ÍÖ|ÍØœÍÚ¼ÍÜÜÍÞüÍàÎâ<Îä\Îæ|ÎèœÎê¼ÎìÜÎîüÎðÏò<Ïô\Ïö|ÏøœÏú¼ÏüÜÏþüÏÐ=Ð]Ð}Ð�Ð ½Ð ÝÐýÐÑ=Ñ]Ñ}Ñ�ÑÕ,‹ÐÑ‹ Ò"=Òø¼}Ò MvÒ*½Ò,mÎ�Ò!0ÝÒ4]Ó6=Í&½pÓ<ÝÓ>Ý̽­üÓD]Ô4�Ó-CmÔLÝÔ�Ô=ÓN=ÕTÑA½ÔU�ÕZmÐ9½Ó[ýÕ`­Ï&=Ó9�Õa}ÖhÍÎP}Ò^�ÖnýÖé¼ÖB ×t]×Þ!ùÿ,ˆÝH° Áƒ*\Ȱ¡Ã‡!ùÿ, ÐþÿaH° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱcÁ CzI²¤É“(Sª\É2eH�kZÊœI³¦Í›8s>|ù/¦ÎŸ@ƒ JÔ&OŸE“*]Ê´iÒ£N£J�JµêF˜V³jÝÊUjÏ®`ÊËò+Ù³hÓªuhv­Û·pÃ"�K·®]¥sïêÝËWfÞ¾€ Îøw°áÈN̸1àÅŽ#K† y²åËb+cÞÌ™ªæÎ Cý,º´é›¤O«^�25ë×°7ºŽM»vÄÙ¶së>ˆ{·ïܽ ‡|¸ñÓÅ�+�|¹óËÍŸKw}ºõÃÕ¯k¼½;sïà1þgO~íøòèÉžOϾëúöð­¾�O?êüúøñæßïö>ÿÿ:ùà€5 Hà�,ˆà‚')Èàƒ9á„„Qháhf”„vȇ†È›ˆ$¶b‰"žˆ¢‡*®¨a‹.^cŒÎH#„6ÞÈ`Ž:"Èc�þ$€BÉ_‘Fæ‡d’õ-Éd|N>Ù^”R¦Ge•å]‰exZné]—^nf˜×�Iætfžù\šj.Çf›Ç½ çprÎù[�vî†gžÀñÙãž~Òh ÄJã †®†h¢È1ºâ¢ŽŠi¤ßQ𢥗bÊ¢¦›rú¢§Ÿ‚*£¨£’Z£©§¢Š£ª«²º£«þ¯Â꣬³Ò¤­·âJ¤®»òz¤¯¿«¤°ÃÛ¤±Ç" ¥²Ë2;¥³ÏBk¥´ÓR›¥µ×bË¥¶Ûrû¥·ß‚+¦¸ã’[¦¹ç¢‹¦ºë²»¦»ïÂë¦¼Ë Dïq<ýƒÀ¾üöëï¿,ðÀlðÁ'¬ð 7ìðÃG,ñÄWÌo¾úZ¬ñÆwìñÇ ‡,òÈcLòÉ(§¬òÊ,·ì²ÁgüòÌ4×lóÍ8ŸóÎ<÷ìóÏ@-ôÐDmôÑH'­ôÒL7íôÓPG-õÔTWmõÕXg­õÖ\wíõ×`‡-öØd—möÙh§­öÚl·íöÛpÇ-÷Üt×m÷Ýxç­÷þÞ|÷í÷߀.øà„nøáˆ›½À"Œ/F‹`�øä”Wnö �g¹åœwîyÕ‹;Rè’núé¨�y/-yé©Ç.ûì®/rCë¯Ï®ûîŸ×û?¾ó.üðˆ?zîÄ'¯¼ßƃÔüòÐGO7䬿¹ôØgßvè·ßøïÚ‡/¾Ø�kÎ8øã§¯~Ö˜3ÆóëÇ/¿ÕðÏoÿýL×�ÿþü ­ÿ `¾þ'Àð€L ÈÀ:�rˆ 'HÁ Zð‚Ì 7ÈÁzðƒ ácð H¡ WȺð…0Œ¡ Wh Îð†8Ì¡w¨BSðþ#LxÁ uÈãˆHL¢—ÈÄ&:ñ‰PL¢:ŒÅ*ZñŠXÌ"Õñà ¢¦x‡ÇHÆ2šñŒhL£×ÈÆ6ºq�Þ@A|ñÆ:Öˆ^4@!;úñ�€ $ ¡Á KìA�ˆ|‡<ð˜GÏí±�‰Œ¤$-€XH’�p ã%ý¸Èp„cŒ�¬Ü#×AÊRšò”¨L%)½q‚X¨ò•°Œe)Ãq7´R–°d¥+aIËFàò—À<å"“aŽO¾#”Å;¦ÈÌf:ó™Ðd¦.£IÍjZÓ™Ó¼&5³IMKDpÚ §8›ù(‚˜ŸDæäö¸LZF°ê€ÆÀ†V²Róþl„7ÎxÎ3Ð@AÙàOÌ‘•k˜ã8ÅÉÍ)Þ3Ÿûì§< Ð�ô 'H¨/ÊÑp–SçL§:ÇÎqX ãHiaÒJÆÑ ÜðæZê ]št6µ©!ã8Ó”úô§@ ªP�jÓŸ¾4¦ü¤©NqÚÊq,•§C�ªT§JÕq|4¤Çéáö¸Žqȳ§Ð€©SíÙÔœ¶r¢ô‚MÑ µ6µªp%ê[}jÖXŒ5lu«]óZÔ¸úõ¯ãX0ЈdˆT«…Û£:|êÍF„•w­ë]¡¡_е©”µ¬Jç Xªöu³v­kf/»×Ê’¶³¨¥ª:[ØÃ"vpŠýþ©!ÊRJ⳸Å+ zêUÌîÖ§Ðàlj‡\»þ´¸½ÝëY›Rä”·È®t�ºZÂ6«¯…-(Ô�Tƒú¢»õ¼m,¸Q\ò¶’¼ól+RaŠV/”—ð�¯|çKßúÂ×�i•oy÷{Þö®½ÿhë{íKàØÀÕm-v³8Å8¸©8°„'Lá [øÂΰ}|]ÃÖãxð "¬á›øÄ(Nq�ÇÁÚ{¸ÁDÇ6[ÙÑw4¥6αŽw¼ØZ×µ/îøqBùÈ7¬!’—Ìä&ƒÂ‡-r�÷6d~XùÊXβ–·Ìå.{ùË`³˜ÇLæ2‹9Ê ž2þ•ÍÌæ6»ùÍp޳›Í‰U5û­Êrγž÷Ìç>óƒÎ.¶óšýLèBúÐV´”m7<#úÑVÞg¸Qè}4‚¦€4—�fF7šÍû8�/4MfÊR™&t¨GMIJ‡yÕ{æ´§õæè1ÚÔb>é8 ë[ƒÙ×r–õ¬ñ†ç}ÜÓü˜h=}ê„^š ¸~õn±¬lQ÷ZÔüØ'´›=é‰NúʰÖu²Ó›j´šÂÒÕ³°‡ýéHCÛÊ–Î4%™=m`GÛËÆ#?â�í9^{Ôð¶v½±mHp?Þ(Ètfù½pl«¤�f7ÝðüU+‡u׫þ÷½Ç,OS\|ßÖÆv¸þ#èol³õÝ ÷…©“­W[Âã-�ô¹žçuK|nµö¦ÇQšr�o<×løxÆE.jS}Ô+Ïr¸÷Àr—ÃÜéö†34à7¬a 7¯[­³½~ÏÛç?ç24Fmì®'¼ß̾�¼ç¨ë†“}ÚJ':½Þr†×�æÁé5š‘�¬OüÊ’¦´¶Cpo¢<ìJ?x¶Jð®ÁÚǾá-ž^”ߺíÿ¸· OOuËA /üŽó_ãñnŽ:ê㠀χ~ô¤�ÛÖµ¬úÕ“¹ö¶osëA/úØËÞôÏ=¨O/ü9»¾÷¾Ûì‹Ï|æº�N~Ú–ßüê¯!À@  é{ÿûÊ !ùÿ,¿ ݸù'° Aƒ!ùÿ,¬°8þÿ H° ÁƒeØ©C`‰�‡2JœH±¢Å‹3jÜȱ Â:uBìH²¤É“(STøp‰Ê—0cÊLù‘ÀÌ›8sêL¸ÐæÎŸ@ƒj¬)´¨Ñ£<"]Ê'ѦP£ž|*µªÕ‹T¯jÝJ0+ׯV½‚K¶¬Ù³hÓª]˶­Û·pãÊ�K—®›ºlÝéÝË·¯_½ïFµe‹$)Rkmð·qc®êÔ‘”'o­ºÅŽ3ó ,•òäÊB){þÌX³fÎx¾[ýΤ¼Ò¦£¾ê €Ë6®Û]Ñ›Û sä]ò5¸ã±M Þè[8ÂÝë8‘{˜s‹Ð‰OlþÏî�Ðþ6pÈ“;^®‘»Dò=±©F¾DîîÿÙ'8~ÿÆ×žä‚žzëmdEÀ±™@‘5èà?F(™A¾±AÐ0¶±!‚-ømøÏªãÛ�Ë`xÛ2 r'Š&þcË„÷ÏoXˆÒ;â‰.àØ{±qwçiä?F‰¤’Iž387Ȩbz˜_sþÓÜ9òé[†En9]aŽ™ßIëä¸c�>ú$GMÆé¤œJR„¡-ð‘–VzXÛmUf"˜an8Ý2çZä…Q·h *¥©£' Øâcs{½¹Ñ8œv:�§ž *Eòå¹ç†âI89@z(§þÿtÚÜ8ò�óê8ŒÄè™&Iºf›˜ê¥©F�Ž *¬¢"{�'…AÉÆ”¶@Y˜w¶¬hfŸlÀ*놹̃­Ô $(u¼–¤Žš<»a¦e"ÙÄûO¼ôÎ+/½øfs�6þ©á´¶Y±!”ÀЪ{ƒÂosúZk•ú±»5¦tn�à*B ¶U›¡^ ÖèN°î ËU¹n�«cÆUÂ[îxwË^|Z*¬TòRTnÎie3Žš,c*ôºRIrUunçaA ªuÎb+kléЪޒÌÁë&Õa†!¦)P{ôºT˗͵6»“šZŽ=5Ù&¥Á�î#pxç­÷þÞ|÷í÷߀.øà„®cºmöõO_àèâI �G.ùä”Wù 0X®ùæ›Âùç ‡.ºä¿&¾ãáäâÉꬷîúë°çð0ì´×n{ë“Þ®ûî¼÷¾º€lšãà„£ËñÈ'¯üòÌ7ïüóÐ'OJôÔWo½õè/üâÄçý÷à‡/þøä—o>ø<ž¯þúì·/üéïÇ/cÐÌoÿýmr�ÿþ‰‡Ãÿÿ´[HÀPL ˜?78ð�Œ 'HÁ Zð‚Ì 7ÈÁz‚’�GHšð„(L¡ %D§ºð…0Œá?–AÃÚð†8¤!1vÈÃúð‡�@ ¢‡HÄ"HL¢—ÈÄ&:ñ‰Ptâ sHE*ñŠXÌ¢¯Å.zñ‹]œbÇXÃ-šñŒh,"×ÈF/Š‘ŒdL£çˆÆ6ÚñŽIü‡höÈÇ>úñ�€ ¤ IÈBò�ˆL¤<æÁÈFþ�Œ¤$'IÉJZò’˜Ì¤&7ÉÉNzò“ ”äÚFi‘€!ùÿ,¿ ݸù'° Áƒ!ùÿ, ©)Æÿ H° Áƒ'4yr¡Ã‡2„H±â?‰ êx‘cÁ <:6 ÉC Æ CvìxqáJ�&_¦4¹P%G›+ÿmlBð“!yÒ|R²åM‚‚$ŠÐçO¥$‡fTºpªNŽ:F…ÊÔ¨U¯H]v̸´(ЮIÃNüø’gY¤[ÓR]Ûë[®EåJ�u'\´U?*4擬óªÌ;/W™f7ÊLw d–KWfí¹òBÜÆ�aZt<ºôÇ­¦SßMmzõè€!ùÿ,£™5þÿ H° Áƒ¦I“°¡Ã‡#JœH±âÄ…3jÜȱãFŒCŠIR"È’(Sªäxr¥Ë—0 ¶ŒI³fÉ™6sê̈s§ÏŸ {JT(Ñ£;�"]JS)Ó§+�B�JR*Õ«­bÝjQ+ׯ½‚«�!Ù³]Í¢]V-Û·eáÊE(vî׺v·âÍ{u/ß©~ÿ LX0wˆ+^̸±ãÇ�#KžL¹²åÈ_Þ̹³çÏ  Mºtâd¦SOάº5gÔ®c+f-»6dض]ÓÎÍûtoÛšóÆ-¼uðⵉ#7}|¹kåÎC7�ž:uÏÓ+w»À¡;ŸëŠ­þ'þÕ�ÃŽÖÝRÔjœ~}ä_&je§ÜÞÝöïà݉wß}šbªÕǘ€“Í7™€¿ì xâ퓃(µ¨˜„‘(™€BHžynx‡zéE¡à† ò×]‰¯9–à‚Š‘XLz q€yÿ(¢‚QxgŸz-v÷áz.ºã @¢´gad>Xß/|láñÝ·#�MòÈdgâ%ˆØDie“|·â’`â‡X{:锵�é ™Fz–d-z§å”K–'c�2b©"ŠíñYåz�ê9(bzéçM)芉ÅÙ‚#¢Èè™ Zi)¤Ÿ‰'` –Ö*‹K*è`›<"Úè¨ã…ªÞ‘��‰z„Rž9뚊Úf¤»vúØ%¢Ùë”x[*¹Úúd”þé«rr×å¢uŠéc¦îUk¢Ž)>¦í¶2Šjey‡:h^¨.ºí�à~·‘’òÆirùIWPm"W/h£©6d�,Ò»¯gýÜ­Á›Œ°eû-ü˜ÂOÖpÄ‹ý!ùÿ,�7-þÿH° Áƒ*üǰaÃ5öIœH±¢Å‹/pÈbÆ� CîÛÈñaD‘(�L©¨+€²Š$KþóˆòbŒø$ÖYiQ—�œc–¤Y³âM 1^^4‚ˆ¢ÐŽ'%Ž!Øt*Õ}lèja5@ Ÿ9c4Ý—t_�±Ÿ:$Z'Ú–+§6ÍjáëQ³h¿Qª‹gZ™ £¶XÕí>¹XqJ¼{vb[´û¤ ˜aÔ}-NAŒ8+RÅ�%¶|ë—råË-Ly|ذçÅŠÁJ\£«,^§•:&øsŸ‘‚s{›h÷¥XÌŠ™â>-ñÇ�eÍ�£ó�*Yº„I]¡÷ïà¢æO¾¼ùóèÓ«_Ͼ½û÷ð×[°¿>ÃùöëãÏ?÷þý#…'�Äðßyþ Xà�Ò÷�ˆxb ƒæí§ … >á„’}vXÞ‡zBƒˆåáç…„(’7„ ¶˜Û‹ˆÄ(#`4ÚxcI9r¸#G=þ(“Š, $ˆ&ɉ!*ɉ餅:yŸƒQú(d‚j¹c€ z)c€!ùÿ,>£ãH° Áƒ !ùÿ, �U-þÿ H° Áƒ XȰ¡Ã‡#FLH±"Å}3jÜȱ£G�,Šùï£É“(1†$‰0cA—Sv¤öŸÌŽ!1œbQ£@Œi¾¼©‘&>£&©=°a3£€_L¶ÁWÑ'Ì‚FcÍhiÇm2Õ( Ǭ¢5÷Ñìõ£��dm™*ðaÍ6 gÑ˱0�À»rÃÖݧS€ ¶6×þØÛ—š‰³uŽušv`ÖµÎ*=»--æ³P�Ö´œy_çÄ?ïk5b¤Ž!k”ÜTeZ —S{öVlkµ5‘þåÍðíRÔ®ƒßöH›ìc´T#ÞôlåT‡O×öíî×Ë;þ6w#ëÑPU#+ûºèìÖÓ²çhßÞ@iÓcWû<²áÚû@˜@L1à?Iè¶Ý\†!ŸMxùõ F ÚV_„-” jÆÆ]oy9uP#tUI[¥ÒˆûTEâ@'¢¨âŒ"²dãAå¨ãŽ Ýèã�@)ä�Diä‘H&©ä’$) “P²äd”TZ4e•Xte–\ ´e—Y~‰À,Û8&“_΢O™g.9åúŦ™m&ù¦œsÖiç“1ŦžG~é'�€)(>J䡉**$£„:$¤’Ii¥“ò)Р˜fJ§�þxi¨7Þ‰gœôDJª•OÂyª>©®Ú¤¦²zZ룴Þêã—º–šë‘!ùÿ,‘  ÝüøÏ�Áƒn!ùÿ,M�£-þÿ H°`A*\Ȱ¡Ã‡#JœH±¢Å†3ÜDZ£Ç� CŠI²¤É“(Sª @£K�+cÊœI³¦ÍŽ-_j¼É³§ÏŸ'sfdÆ!á‚ËØ’a‰xM™r$Úê>X Eu¤juŸRO§r¨º¯Ý …Z÷qU[!S¬ ýÀMèÇ,Ú¨eÏf½j”o\¿´ÚÝËQ¨AfLí) <�#\©JÓv|œ!YªŠÌLÖkàŽœ¡š Ë1´ÚÄ‹%+þÌqµ¨Ñ]»ÍKš/S¥~:ºÆ¬D3l�†3îË<«1Ñ4KÙv‹\*_²XsG—}ylìç¢WÔ¦›ød˱þVý½•CsÚ]ÅÇÃ*Yýôèä=7XæßS‚Š·`}«°jþýßA€trxV©WÙlr¤Tm®é–Ú‚Éý—Ü`.†Pn­MøÞ€:·Ï|9Ș@°<à‡r©˜œ�,ÂXàtØya�EÖ Ž–âz/ö( Q%h˜–‚1 ‰“N²ù!Ðjý­&$ €rˆdròØäŽ_Þ8Ü„EW¥eé ¨#€7&ùea.Á’›k4Ú–WU:Êæœ‚¼if Yx²†äœ½Í#¡Ÿ)Ø œcú©çU„j&%��õ9 £ÞÁ©ViUg—Dmè€&ºW©Z…Z ªs}Æê]þvIëw„=ÚjZ_]x–d€yz×’: Ô°Ä;‰Á«ì²Ì~„l°E+í´ÔVkmBÁf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¶ëî»ðÆknqÈkï½øDo¾üöËî¾þ,°¸lðÁÁŒðÂþB0‹?û# )ÌðÅöâOÄï£Ä?c,²»×'�ÃSòÈ,ë±=+¬ÜòÌë:ì±Ì4çlîË1׫óÏéòá, û ôÑãjìqÑH7 .ÊD3íôÔÚB­¯ÑTg�‘ÕWkíuA\wýõ×mÎc½ÅÆ&„vÚ: Í1ǰ¼ 7ÍrÏ qÝXß ·Ý~; xàHN8І®sâŠ!ù%ÿ,X£H° Áƒ !ùÿ,V�¡-þÿ H° Áƒ*\Ȱ¡Ã‡#þ@±â‰3jÜȱ£Á} Cî»è±¤É“(#Š I2¥Ë—0=®9¤´6â ¼™3¤@X$[íû—‰â¿V?+"m÷`à€V7+NAÈÔ¢PX… |C±'È7÷a(t_¦¬"ÁNú�§N /ýÛçvî>°ÿr2(W,ÚªŸ²¬: 'a¯CyÚ3¡Ð)ôCʏ1SÄÒÖF~šÐk[Ê’ïi耵Šÿ5~,°1HÓSç´»os«Ãñ†r-»¯]œÚ;A[Æ™{%I =“"&:à’Ùæ»Ÿ·*êœúåâlkK>x�4õç—Üþ’þÜæ4xðÑ‹ ½Y~ê\ä:CÂ]8·ø•ÿÀNo¾»ñŸyé¤vDýS]sEÍEÝwÖ= [`ÍÆ�ƒMÅ`s¦M”SdS°vá%E­E‡c•VŸ]‘UZ€ÿ˜vf4ö!`æ±4 [ó�gÐf!Èßw ¥ˆ”]»%¤ÝS øa&9=vÞˆfôˆ`“5Šuâ�ôõô¡M攤\Ùfc‹õáXfHgÉ•fZ2þÈŸŽa�g$xÔääcQV”ׇ´½ÑXžFõ„•WbÊWæ�晦es�GS–ØÍGÝMÿT6dAŠI‹sô ” §Q^j'¨�¥&ÐuÑ åd¦�™8iþNøÞ™�öF\‘gj‹rEæM{ ôaí'\*¶Ö{h!ëiKZälY% DWSЄիXKÐiÖ¾öOlöx[SeýìDë•+¥Â6YP†‚�Ó½øæ;çúöëï½3�ôïÀŸd‘ž'¬ð 7ìðÃG,ñÄ#Gg\ðÅwì/LJ|/È"—œÉ&§ Q+ý´ÜÏ>d„²Ê4'Â,.ç|ÖÌ5÷LÐÍgñõ2<ûl´A7Ã\ôÑLÿs³=,Ý´Ï7÷³3ÆS3]õÐ2c�µÑ[÷C©Ô_Ó|‰ØQ{]6Ó,¿AöÚ)Ÿ�ÉÛp—,7Ýu{\µ6ÛjçíñZ1 TõMxûýð9» ó?…î0ñä\bãŽgLyå_Ž¹Äšoqçž; zè0!ù&ÿ,e£H° Áƒ !ùÿ,M”¦)þÿ 8�‰·ü«waQ#JTÈpàÃ}ûÞŒpm¬�ÿe PÔ>‰3 ¤xPàC�oHrI—~`ʼ¦3GŒÿq´é0@N‰ûT–\Hb`Τ+O¢üÇìÌ>{J^ í(u*ÁŒFþÄ6¤@[ì ­e3­’µP¶ëG,Ï�1Mžl«V Y—óbü—ñŸ^�zÉ^Íj–`[‚õø\87æQ¯‹áÚìõßÇ-ænÆhôÀ‘~’<²1å¦ Û-ˆÖÜ`�f·5WÚöÉÞƒ�sö vļ4 ß6¼»uçg2$Yü9V‡©§'$¾ÒjÕ~Tþn�ò:ÂìMŽ'J2¶Â�¯›dÛÑÅí;¬/PþÔ‘ã}G paåÔsÊ!G˜^Dƒ%‘e (ß©žQ4ùaÞM(9˜•aB‘Qàmè—Gõ�D"jÕâeÖeE]jû”Ÿ‡v†j'òèrsq&ÐcŸùxâIoÀ…nžÁö—…Ÿ¡8ÞmJʇQ”ŸÍÕ––ÕMØR@ÁEœO ›W™¤&,j¾šÅ�Çæd1Z^¥©%æ•q¢ œmjV›`|ŽçY~'ÙiN^Š2:èK»}ùU¡�¶cœFJ4HÜE¨cPÕÙQ�é=õd-:UPgÞg˜@þ6þ“SENdm$=e�@4Úˆ!§B¢ªÞ€•.º‚È&«ì²Ì6ëì³ÐF+í´ÔVkíµØf«í¶Üvëí·à†+î¸ä–kî¹è¦«îºì¦«ˆ"íÆ+ïsïÎkï½Õ‹ï¾íêËï¿èú 0À \pÅø£°?Ï ð�Á·²°?û01 $ðÀûBœÀLSÌ„Á ²RIœq¾ðrü¯Á]óÉ ¯Œp&0K"òJ¯üÏÆ. ñVõ8<ÐÐWÌóÂ>ôË0'mñÑQSôD ýsËOsŒô5W „tÂ(´EÖsÝ5Á«çÏ.CŒ°ÂJ£tvÓj¯Ýq ÔYìñÜ ûl6Ú,ë uÛs—-v΄Ž·á{#NöT0ÿ#1«*é¤ Ezƒ&7Pª)¥–bºé§Žvš)¨¤*j©¨zjª¬æ¹j«W°Ê '�hbë­¸Úê@¬¼ž9k­¹»k¯ÄgA—ŽZì²c¾Êì³^: í´YJKíµPZ‹í¶UiËí·/E î¸?ŠKî¹0™‹îº!©Ë /A!ùÿ,ˆ£ãH° Áƒ !ùÿ, �ì-þÿ H° Áƒ*\ø€Ã‡#JœH±¢Å‹3jÜȱ#G† CŠd¸¯¤É“(Sª\ɲ¥Ë—0cÊœIs&€‘8sЬɳ§ÏŸ@ƒþ¼©ó É¢ ™ ‰'P¨Ó§P£J=IÖC(9QTÊ©@®\W2cpuß6 E¡‹#ÞÉ9 ˜EëPÒÜ´%á(A.¯C¾V!ÚÍT¶$[·~÷öÝwØdcà ÚÞ}(*ðC»ûôòMÌwlaÂÕr^¼ïf&¾ß�Óyt W¯_—†UÉ È>zfˆ:»åY‡’K–»­Ím3®ñ&�Y÷[ç(që¶*®¤ß‚Ã=Y2vïtÁþ÷>)]íöçÜkŸwòæÜMÞ4sídØB”¾)¡¿3ÙäÌüóFhÒ É?Œ ±9ž½a)¥”7¹ý# 3ï¥äžrŒ‡’UÁ�ÕF\(m·œc‘!ÆXŠ)��‹„‰æâŠÁ™4£pÙ©8ã‰æø�*š´áy1þ(ß>¨!˜ [ø�¥–“fµÑW€ÿ0 ,m½™ZÅ­ÖäfoD˜ŸlK1–ás›aGb�’áuö1�œšrY–£�Á•·^]6渞ˆÝø§Ÿ8‚WØzWBÔ ~mF˜\„IÂhIìC�aexß?nyöW€�’ɦ�’õ9N™é˜ñÌÖÒyþ%éyÒŒ§‘'d„"é>‘îºë ’±EBh…ºå«�ÅöY£ ˆ&{¬$Ï¢W`]ÑRº ×4µ$cÿlªŠ .©å’Å›˜`•éÒ¯%±[ì´À½x*J‘ÂI�½$ÊzÞ­3â+°:æÊ,¯ÈÊ꯿'¹;Gr[[+‚a: a™¹uVzœŠ‹©ÿ\¬$3vá6‹Ä`m†a}&ern•­œÜ¯ÌÂéYp°¸Ìa[&R€³s7>J0f;ꬂígÍǽwãY;ï&ôv*7‹#qOCW‚™D"hTtKqÆ+7жÖ!8›§8xC×`QÁê?sXxrÂxÙ©V¤jZ-³þ©ÀÙ�+²a#û[|z‘˜÷“¦Úuøât…æ÷àqò8Û”MöïäT±VlHMåùç ‡žyV›s®¹è¨§®:MD™îzHÅ.ûì´×n;í¯ç®ûî¼÷îûïÀ/üðÄoüñÈ'¯üòÌ7ïüóÐG<HoýõØ�D}öÜwïýöÞ‡/þóà�oþùÅ—�þúì﮾@’èC í×oHï¡�üôßïÿÿQⱿùð€þ+_è±"ð�ìß{È0@Bð‚ã_+ô· öƒ ìÞöâ—µx0„(ÌõôçÀ¦ð…ÑCÀ?èBÚ�yàþvÈCz|ð†O@LŸyØÃñˆÀ{Ÿ ãaA$:ñwJ¬á§è¾êDŠTÌ¢é¢ÈD#jñ‹EábÁHFœ(±ŒhDÊÓÈFíY±�p4ããHG†¬Œ!ùÿ,‘ ÝüøÏ�Á€!ùÿ,•£ãH° Áƒ !ùÿ,g��-þÿ H° Áƒ*\Ȱ¡Ã‡ÿa˜HCÄ‹3j܈@EŠCŠIr¡Ç�Kª\É2âÉ�)0#\Lÿjpiß>Z z„Û÷�Î=ÿe:Ús«�IŸ ¼$ÐèLªõ(õ³/ëÌ«÷ÉÜRõ+UŸ@…v¥@ð’U�üôII`ͬy†•ˆR,RŸ7› ¤PÓ'Ñ3…þKk�‚eF·d}Ìøå �/÷Ȭ¬¢µ�í%êó)²Œ+ƒ @qÖ€}z¥jP,OïG“Þ÷²bÚÑ‹ƒÏm¸tk›K¹&—Ùsé¥äû’gúÇU èÐ 3'~è¡ÓJãþFïôø?îÅ�*6ø7a݆{S|{Ü*N¡^gn1üTñtåqM·Ÿtâàu’÷�y…YYmYx–ö�kZáD–ll%e}øexZq|}„]\ˆÖle©uP~G�ˆ rÔɈæý³O™Ô4¡Œ-µ¢VM©'¤AÉ)E�{ù$ßD‘•'á?û=µŸaIu\tÔ)É`”<&ã^ÚhUaa�çG†ˆµ&“ŠZºˆ¥x³ö!xV”o(a�•PÛQ(O¬p5™2Æ©Ô?œñ7bjšq©2@m锡ª…5ᤉU(hˆigA†SWQr_Ÿ ZGT¥ò]ÕZyQ%+RçiE%i¦éUT:Jõ¬ˆõpk“^)lOxÁåN`ÕyXm‹Æz”¯€õÙÒ¶Üv —¶Þ†+nHO¦4î¹è>nºì¶ëî»ðÆ+ï¼ôÖkï¼ ,pï¾ÛæËï¿*ù ðÀ! LðÁŒðÂ)<ƒ2¸\ÀðÄ)|‰?S¬ñ?þžáÏÇK¼ñăòÈ$ë;P'£¼°Â,gì2Â0·<3Á5Ë|óÀ9‹¼3À¨,PÌ>ÿÌoÐm4À=/ýoÓNï uÔö–lòÇõM5¼V_�õÖø öÓb�-uÙfW�vÚô*̶A!ù0ÿ,¢£ãH° Áƒ !ùÿ,¢£H° Áƒ !ùÿ,¢£ãH° Áƒ !ù!ÿ,5£xõ©HðŸÁƒ*\Ȱ¡Ã‡#2tA°¢ÅŠ3jÜȱ#Å‹ vI²¤Æ�!Cš\ɲå?”)Æù§'—8sfü¨GÏŸ”4mÞÔI´hB”}|‚L*t¨Ñ§:aöl:pæÏ�P³â„GiE¦"µŠ- “ÊTŒW±Ž]ë±b×´T¬bdKw§E¯2kέË×aY³pÁ†íKøè]¸xÕ^lð¯`ÀKv¬W`b�’SnúsæÂw¥êô3ßÐpå6M5Ú½¬[»½Ü9ö銗ãþƒk».×ÜT÷–=ðìÅ ž‡�E \&råky6?]ì_‚!ù5ÿ,¬£ãH° Áƒ !ù5ÿ,¬£© Hp Á‚*LÈp¡Á€!ù0ÿ,%T˜þÿ H° Áƒ”¢hÐ …#JœH±"ÄŠZÜȱ£Ç� CŠ9HÇGäÛ†2¡J0ý±48)¦?}_ªœIr�Ì–w¸!£’H“*]Ê´éA Mš ýWT „5yêÌg&Î�/»úût0ëT�W`j%hö F‡NãÊ�KW.T© 5LsmÊ|sÀrå©’ì@Ÿ_òU{–àH9!áú“àâÊF®Ë¹³çÏ ï­zu¯M¿UN;º5ñ¿Ë¨ >Þ¼uÚäµ°¿m º·ïÎ:¢ /ˆ�‡ð&Æy B¸ñãQš¤ð6ïÖ´ ªfMÐ:ÄÙ Uþâôn�üÁ+Џÿ^Ï>î]èM6‡�|yÔç÷é d¨¾üÊënå³ÚVcdBà%TS`Ô A&e×Þ„†\|½€aqÑÙWß?ï)7�h{YUÝ¥EË_^I(Ѓ²A–�O†Á£@oyPáŽÉ%5`+úé“`QÒéªëÝ¡.zë{çq­m�‡è·§t:éÎ;îDízï <ñÉ¿¼é²§ŽÐ“ ��òÕ3_¼õF/}•ÞORñ¯Ï~Pù¡Ón ÷ê�„=ìÝGßþAóéÇ.?D s�£ì¤ÓßéÆç–, JݽÆOvóûž§“¤Ì›àþÀç=uí«_B¥èN}Ôs '<·í΃ M×B|�ÎÿÀ @tø�òPxþ8Üaö„h=ò0‡CDbG0‰RewÖ›` ‚¾ ‘KGÔ c7Å�è΃2ÔÞÅ'Æò°4ºS¡7B=+¾&‰ëëbunH<&Â�‰�úÒèDÞqt´#­ðH2"P…1ä‹Î˜ÈBŽÚQdÔIB®Ñ#—|£ÛXF3Ê‘._¤U&'BÈ"Ò“y�ÿFùÆÒñq/öã",ÈJêÑ’‘êjâD^¹ÈOæ.¤S¥k©Ë‚•áe)+xJÉà’3ÂS+µöLd2©š9¦eb¹BÕñ²{Ÿ¤^û&Ø:qš®œÜ$')%9Í êR›à'7{É^¢—íþ§Eòi�Çp OQÞ)µºfÆ“zæË%š?´� �§bŠ©OáA´�¶¤áD/ÊÈŒÊÒ†S$(%·Ù:‰n“£r4é OgPf:Qœ �%LáwM–BÔ^ÿ¼S@�Ç=‘64!1¥ãD£Å R±ž CéP�(¼O&U£HTjT¡šHDúÔ~DžJ…(UÕs¥%”õ¦Ôá Uvn¼ê•ÂÉ„€®¥B„aùZ:¹þÔ o½©1‘JQ{Ž1zNíë [øÔ�VŸ‰&ÿ()È�luªõª’×ÔŒ4®´š+f{×ÅÂ5)‡=ˆÚö®´Y-ãh�ê?�"ö¬,Tþ'ø¤êZ¿Öv°‰ÝÝZ 2ZôEo†¥*g'KÙyⵚ¨br‰Ë[ãú3§�`£q_{Á6ö¶�­6÷ÚÚtN—«Õ•':Å;QòÖî»õ­ì€ûFóJ¶“Ô=Ÿ$ƒëGaw¾Îüäss*ÝÝšóší;¦l‡[ÆÿF´žÄ\kv…Û^¿*ÔÁå=ïna9ÂÇ&Øu_ ïbç7`é ±ÃôdîƒåbÑóꕳ3¼äëR¼Ýž˜À‘„á7�ëË+S’7–10OÌDô6O°0f Ž›ùØ_Ù«ì]1îT<_~Æpw/Ƥ �È%&2Š™ ]ëÊ% :‘Ë‹,¦•ï—á÷yG42þ{‹‹f8ÑÍIL3g�ü¿+—¹ÈoÆ¡IÇüÁÉ®ö¸ôrq­å ÚYÄûl {Œ:DúP�„tX'iA3®w�•éšØè>2ZtˆüôCµë½ŠzÔ)ò©­úÛ*+zŽ›>u,e­àW/EÔrÄ5†�ÌPƒö¢ºžã¥�¼Å0:xžþ®ýëS®ûÕç>ø·ÿýñ‹üØ7¿ÓÇOþɱÿüÝ/ˆ÷‚~ùk!óIþ’ÿ÷}þþÇáGê÷Hû÷ÙwýW€E€êØ~ h€Ô‡€h�8�q¸�(�F�õ'‚‘€H�È� a‚.è€%·‚�ìWƒû‡‚-˜�‘€8ø�9(ƒ)ˆ�õƒCè6x„í7ƒ:(8ˆ‚=¨„I¸ƒè„:x€#W…äG‚YØ€…&‚±„!Ø…RH†øg†ö·…hè…Bø…!ׄfè}7˜�Vø„e…c¸†`øƒgØ…T‡0(r<ˆ…~¸„Z„êv؆1ˆhˆ„Û§… Hˆnø†È…j…‡‚{Ø�b‰x8‡G˜‡_h‰@Hrñg‰l¨ˆ^ˆˆ�x‡'¸†v؉¡¨Š«¨‰(7„{Š*ˆ‹›8�xÈ‚´Ø‡¯¨‡¤h‹'w}’˜ŠAX‹º¸ˆ­è‰ŸøŒP8Œ¿XŒ‰¨qÉ(‡Ú؈tƒO؃Ý(†±¨‡ÐXŽ)XŠ €F(ŽŽÈŒ²¸Ž¸h…>È„’xòH‰¬X‰ìˆ„îHŒêXŠ÷¨�ÔØ†öˆ3w�i8‰Ž�1‡�iŒ i�2ç�ç‘�Ã�0G‘ýø‹É‹J‡‘‹’!ù5ÿ, £ãH° Áƒ !ù7ÿ, £H° Áƒ !ù7ÿ, £ãH° Áƒ !ù-ÿ, £H° Áƒ ;heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/appdata-screenshots/000077500000000000000000000000001526573132500304775ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/appdata-screenshots/0.12/000077500000000000000000000000001526573132500310575ustar00rootroot00000000000000advanced-features.png000066400000000000000000000641731526573132500351020ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/appdata-screenshots/0.12‰PNG  IHDR@•ÕhBIDATxìØfAÇÑÉQ @rœV®6ä­^#‚�–ö ™µ;º»Ý!¥WÈxÃ>ÀïîoµXïv»CJé»ïûŸåÍã8> ¶|mú”Ò×f³y©­¿Xý�ÿ§ãñø~ÿ8w]7ßn·Ô¦¯m_?ÆøV›ÿoX×ø/¥4r,�sžkëÇ_kû‡ý~†ajïX ”2m·Ûçp>Ÿ?Û=8�Náz½í \.—>䜧v�jû‡ö ` €0¿ì�o$9…Ñ233™™™™™™Ž™—™™7´ðêô,uK­d2}8ÑåIú”vÙ3íDàÔsùß@È›7odpxD\ÝdͦͲvóV9|Â^rò djjÊ&{úáÇŸdñÊÕRZQi°¿~ýZºzzÅË?@6íØ¥ö{ÔÞQ KËäÅø8ÖØ„É©)µ_gOŒ !„2ÿB!„´¶w(çuåú�âê魜뭻öˆ½‹+æç�ðüùsqtuWö5›¶¨½…GÈ¡ãv²÷Ј,A!„P „BÈ;Y¶f�ܺ}ÛpÓ~÷Þ½y%dää*[xt¬<}ṵ́~||?)B!6ç¡›·�kê�"�õ*Å § PE¬Ú°I=.•5µ†÷nÛ½…ú¹mÏ>)¯ªÖ>¿ „B´3ü˜ƒ#Dõ?À 'صgK€B!ÕuõêPF@dlœrˆ_½z5é^¿u»r€áônÙµ[ -àäî)«ÖoTó)™²tõZ �ŒÂç­ÎÃAöT‰•¦Ö6 Žˆ4ß~ÿ=ÆÈõ7u��èøDñ –ì¼|ÓÀ’UkÔ^³ró!D(Ûo¿ŸT{ô Uc¿àiiïP{É/*6¼C?e߹ýøóÏXC!„,îܽ+û�ÕE€ãŽNºˆóÖ- ¶„B�ƒõp@ƒ}‡�Âé68·¸Çüü˯ʖœ–!ßÿð£zÎÌÍÓç5gùÉÓ§Öæá`むŀ¡‘Q5îèî1#àû v³€«—�>'¶ö®n9yê”zö ‚`* §¿_ÙšÛÚ1&„B¤v8$×oÜ` B!d¾0>>.co¿'XÖŸ¿uëö¬DÜv#%@stgãÔé3VçÑ�Ï]½}mœ[XôŸ _|õ•²!âaht Ïè@`ºÀ×ß~§l¥•UB! ¤îáö_;ï‘6wïÞ} „Bæ!l ˆ€8°qónQ@ òüÞ}ÿÌã3pÔ ¼xñÂê¼æ\÷öX�Cˆð|„Õ#ÿÏ Z �ÀÐpÓì°a�¶ÇÎîÓÀ7ß}gø!„�Dw´Örþ�öŒ9 6„B�£ §Ú ¤ff©ÃúÃ�?™U@^»V‘ÿü…‹ê9(Ls®�X›ÿýäI5—`IÈå×¾ÿ@ĈkׯÏ)LOOk!ˆZ? ô™Nž>­ý ð> „Bˆìœ] ?ÐD¤@!„Ø´úCA¾•ë7¢¯>nÈQý^¯ðìÙ3ݹݰm»ªÐÖщ ÷°©Zøž�ˆ(=ľ±¥Eð´|}kó†"€±‰IÒÚÞG{†óŒNŽn°£ ¿r¶Qäoíæ­ˆF@•a‹ppuÓE‹°¨hY±nƒi{ÄÞ1öòP¿CAq‰Šj @!„èh޾A¬Ç3l¶kH!„„Ö£ÕÚúÁÁ‡€6w¨Ö�>çvóÎÝ*ŸÅ‘ûÿÙç_úðçA4ÐÚ"wÞô<œ{ Ä =:  ßÖ]{f8ÏèNÁÆm;dÝ–m L ÌNàÌÙ³¸•€x€ÂD¨âoZÐj$@¸@ct4Øä˜TÖÖýÁÎ` Dqž;@!Û�¢DÝ ìµ†,h¡�s�è³>ïøá/¬VÀwYþ ø­o      ©Ö}R)%€¾¥izз4ŽÏú–JùÐ7@@@Ú€y~ÇíþˆÃpŠÍvûãçË5rÎMŸý±wÎM“ôPÿDkÛ¶mÛ¶mÛ¶mïcÛú÷Ý“ªLm÷öì]MjÞyοªéÎ }sçä&©¬¬�m;wIJjJÔrÔ¸ R³~øpéRàû+*ÊMûó—/~x®ªªJ)//‹H?'L�&ƒ†�l[¼|… :, âì,m¬ƒîEÞ)ù¸yÛ¶À¶±'ɆÍ[ìµJÃæ-åÞƒxM!„BHuƒÀ²U«¥s�^rëÎIHL�—¯^±Q\\ÑÎæäKÛN]¢RŒ@p­\³VÒÓÓ= &šà®m;wÊðÑc#ÒÏs/âw="ÙŠÞÖ;ɾ£%Îò08Ööž’w4bB!„Bh´lßA®ß¼‰×D\š ˆÒo¢ÔmÜDNž>í¹ÿúÍÓŸä”ä(ˆ§»<Ô „B!„�˜50ºiëÏÅ.fa—¬X�Ye#Ô.]&……¡ö�Jÿ!C¥~Óæ¦}åÚµj›#V4£L"³À�Z´’¡#GËËׯ<ýhÖ¦­ì;x¥íæ³�º÷”»÷ï;7PF¾sÏ^éÚ»�4iÕÓcØçš0e*î{HIù·¥çã'Ož{(¥GÌýqÖÆrï�ÒwÐÏwÍ_¼D:t펪‚н™sçásJßœæa`¬GŽO<´œ‚¹ƒ~á~£oí=û �6;ãóJ~»6ôø³¶zýzi×¹«Éå1&I||<Ú!„B!±fœR–­\eÚÊÊJ¥A³²}×nILJ’�Ÿ>Ê“gÏÔ6¿0µ%à˜½ÎÉÍ‘­;v˜Ùí¤ä$Ó P-[&OŸ?3%ùX#Þ¢m{ˆÓ.¸V­]'™Y™!²²³Bí\èë‹—/%//Ïd8™�>sþ¼Y3_ô]©|�¾ýdÏþýþ8«c á‡çHÏH-%hÕ¾#òm!AÜ´u[¹s÷®Þ?gyøëÞxè9µzÝúoñìoú”›—+·ïÞµc­äwdóÑ2bÌX䣣°®aaÉç/Ÿa¤àù­i@!„B‰µS>}þŒYdÌzD „�¿œb ³ x�ŸŸgÚ/_½jÛ�Öæbx_í†�åáãÇžu옕Åìäw€Gx¾zýÚ|FfFÄ7D_ÑVTTh÷ÃG�‚—86`@ÔiÔD®Ý¸a®“ÑRœÕ±¨jÀ=¼~óö­téÙÛÄãÐÑ£æÞ³çÏ�è-)-Ñûç0ÿÀPs "c�gk%¿#š�`è1òÁצ*àØÉ“¸&„B!„Äê1€`ó-†ˆÀsæÞó/p �3µí`óöíæzܤɶl_ió1M¼3ªžöu›6ása ÌØÚ²nG%ט Æo¢Ô:* [>wá"ózÿ¡C(ãŒó¯ŒåúM›eòôæ5ª0Ö¬ß �ڧΜ¥÷Ë}þÀ“Sv¬‘—Ac­ä·û%zŒt =Æ.e „B!„Ī`Y»acHD¾ÿðÁˆ’’âŸ~æãçO2{þ|”íC¬(m!†²ü†ÿ7ˆM”$G“€²ü&*¢Æ8uæ¬YËŽ~ 5ZvïÛ(xa,±û>føq,r³ð(ÿÇwÌúcy�å nó0b¡˜=Jî;6ôýº°q‹ùNB!„BH¬‘C†…J‚Qb~óöm\«iÚtéЭ»|ÙÙÙž�áüÏuîĄ̂cM¾ígD=~‚´íÜEú n¯u,-Ø9¾u‡NØíßÞCI8Œl:§÷Ç}Æ:øÞ¯¸ÆŽú»õ@5€ùÍ·nÙ±VòÛ©ðË1ÂiK»¹&b�-°a`jZ*6aÄI0:ÐN!„B‰BbÂ"©i«6æø=1¿@ƒÈÀ,0Þ×{À 9|ôÚ ” BŒ`¬Û¸)JÄ!’Ô6¿Ão¬Û¸ ÂÚˆ²‘ãÆ£´mî eÓµ —.¡¢Ï…Ùa#R§ÏžƒØ�âqÃqqv™Ã¿‚}ܵwo8@K bŒïºxùŠç8GÜ;xäˆÞ÷y.Ö�÷~Ý0¿‰¥8&›éÁ±€šßî =F0,pœá á#B±è7xˆ9†ϬyóaངB!„�è7ˆ+ .Q"ÏXT`þÀÀzû˜xž€=!„B!4!ËvH„B!„�1!(óDZ„(—ÇþX�ý þWÏA€B!„˜ÉT¨nAŒÖxpü"õìØ ðð‘fÝ<6Ð[·i“çXÀÿرw¡€��Ñ�ü« ŠÊ†ƒ÷¿ádËøÆ? €Î0ˆÌ·€½ÅsÝlmø À Ààcï. £ºÖ6Ž~/4¸ÈLê�w×!”(�âîV/î—àT(uoi©sëÔ[nÝÝ]oß/ï†5%=� ùŸµ~kÍì³Ïž“®ìçl‰ë"›×Êî]OÊ×_~-Ÿò™<²óa©H)i°þ{o¼#8ôZ¾ìcL§ÇxD¾ûæ[ùì£Oå¾[î–âðœCjÿM_‰.ê )—xHÚª¿KÒÜV•ëÍ÷ 'K�sV’|ÿÝ÷òûo¿ËK»Ÿ—6m—»¯¿C~øîÑã‚Q3 ôš+Wn¶¨½d_ö14¡¸FôÐÎÿÍ—_/÷Üp§üú˯Æà˜<ÛíD—t�ôÚ¿IâTO‰Hê,‘�$,ªëÉò=€¿‡¯lYºN2O�¯Wžà&½û�üüãO’Ð;Ô|øÎûMî Hï% ½N¨{ßIT{ºu­þv:ââÇ3\å%‘äß¿ÿ.»~Âv[)—µ”ÔÅ-Åß«/¿ 4·5M½HôS0ì¤R´”ä‹af¡¿Wžß£ÃÈ-€v:_}a�©óùÇŸÊ>*£óª´Sj;ÐŽžv²c+ÚIdz'‰­lgÊR¶4+ÑÇ�n#‘™�$¦´ƒ¤­ù»éhtìS¯Ã®Á€^7¢­D¤u’èÂz­ te{­rz �ï"©ËZHê’úÚE;÷6۲ܻúÔÿoòÐÆÿ´”«�6�w‚3N�•=Ͼ¤ š FD\¿C¸÷™‡;@ŸÚë9 g´ž«Üß³¯$Œó2çBƒ»¹Qÿ¸O€“/=6/Y×àù€ÖNKYh‡3ä™Gž2CÏ C³Ü"R;i¹e ºþݵ\Ÿ&»Ê§·Ö'Ç–aèúä:}íßôI´íަý¶Ü6Lk!»6ÿ‡m‘Þ>ÿ»ÈÇï$Ÿ~ø‰ä¦I�—ŸL,iFcèñVÝÈ€˜îA‡$NñÔÑ:ò¢¡Ñ®nÔ'8žŒÉ¯6�øgÝ­J-³mTn¥è¡‚»€ÿÖò°èz€×r½ÎU¦v-;�¤Y­mu4í·e¹÷ãºࢩ‹Šk,#86,X#zl]¶þ°ý^tj@ƒ×yÔ�_ÞB‡÷»QŸà¸@P–m†’ôî’àvÈ ‹Ïé¡‹“@ß»¬¥^Ó [CÍí·uÂ:CDt$€åœÎÿ× çñûÿyX€~/IÖ}ýó³[»]ŸÀ1F�Ü/B>ùàcùþÛï$?(Ý­˜Þ Ñcñ´KŽI�8ÍSéÓúlo7—riKK¹Í¶N¸à†MÛE ^ZP­ã~àú^\;ìOwjÐëâªÚ¹Yßò»M@ ‹ÅéBrÿþýw‘5´Ñ#;û[Ê ‚3äËϾÐA;ŸÇ$Ð�L‡²º­.2×èg&Íieæó´³tN-m5…`êб¢‡ÎùßÁ¿à6§È]×Þ&zL(9ïðLìlÎé–}g{Ô[ÁµÚÈ=ܨoïw€#„@;ôܶSôxí¥Wd㢵ã‹j\õEçŠï½ù®Ü{óÙ¶z‹<²óa3Üü·_“êô!Zï誕YtNËÍä˜Aí%2ËlhVœìÑ»^1ƒ:h]s.2Ç[¢‹:¸ÑÖ‰èo·ãºÛEÝà–+®—ë6l3Û4êqÇö[´ÎáÚ‰w­ÞŸ8ÕÓ솕ã­k"˜²èâîÔ·ÿ»À‘Aè锯Žk×osÕ/É”k×]%¯<¿G¾úüKùåç_ä­WÞ0Û¦ùÅh�c¸:¯É�Mg3uqKI[½wßþ¸š¶ºê|½ºº·¼®@¯óÐuØyü¨6âß¶¯ý¶ŽBÝÙGR|ÜoGwd˜Q1Ñ,Úøõ_É·_c^Ϭœ$­îlhå±ß÷¢ßÝ–’0ÞK×Ep»¾ýßÅ}@ €@ €€“ @°w€d—Ì•ÒWIåʇ¥bùRZßmç ½Øtx£ÎÌj´nñ”-ZWŸ¾Ûn?»xÎÞ€!õ<}HìÀ¶§Ë9ç^dꧦ�²:- zÝ�ë*÷MÔyüº†ÀQ¿?•U8KÊÞ­‹šE+–Ý/+ÔõÌ �ž�7|© ½ô3zBG3D8“ôZˈŒÜÉ2hÎ5fô¹—Ü.*.“ Žg»êè{½·†„÷‹·Ó–åÞõ^£NK—¢‰Ìâ�åKï“„È!zþdLîl:¥C.¸±Ñáòý»‡jÇú�æžk§T‡î—κZÛ·ÝÁP~©.èZ¤05mdƒõô‰½v¬µŽ†:ŠA×Ð` ¨ÃYGéþ¬€Ö×Nv^õb3¥B$Ô2Ý•@×W(·NÒ²ÇKÎ� dØú§LG;¨£½»{G4¬’ÔŒÑfǽVÃ…€6§™zQgdJrâ0³Xa劇ôµ‹vîm¶e¹wý7 ßŸ†AzmH—`=R_×ÂwÖö­2r§˜º‰ÑCm·_:{»éð†õ�Õ2»l=_Ïày×7¸ªÿá2xþ ú”[Ÿ¼»êgÍÒÑnߟ€naX¯¼`äJSž[^¯<3š)OJ¨²l?˜’Ró—]™òôs&Úž`£-˽G¹îý¤ic\«ÞÛéÌk‡³rÕ.×*ý�Ѩ¶Ÿ™?ÕUf·ƒíïé§OðµÓ¯f³­Ÿõó‰vÕ j–”/Ùi†¬‡õ�ÿÖN‰�$%Ó.w=‘×§ìGáþl©é£µ\w6hpÁÁÌ‚ú^i¡Oôõ{¶|:êbàØµ¶ûmYïp’­׿H;ƒ:ô];Î�Ö×õ´£¨óñm{óëgè°w�gï¢óáµ­As¯5ï#OMm´½„ÈÁz�nA¸ßîãLY|x©%¬È*šmíÄ»n:,ß:À ã×r½ÎUV¹ò!-; Á󮳨hëD €`LzG™7¨M£u]€N‡Ì—-ºG©³u�Îm7 Íù&Ú¨ïêäÚ¡åFÛÓy뺷錫\eÇüC¯×‘–ú:zÀ²^�û÷wô€U»t4ƒ^Ó ll6Ú:Ù` @H×í<ê¢o®Uãm¬Ä¯‹ñYžB»É­mö‚¼ý-[þåV-¿f…[l}Z­sòµ¼|ñN)œ°Þ¬7 í–-ÜaÊ‹&oÒ0`ÿ¿I·¹Ósº€n½§A��wÝ‹Öi €ÙºoÆ•Z®OöÍßžž3A×'Ðíu·ƒýÛ¨;áÞïdÒ&É0YrJç¹ÑÖÉ€v �ë> â²†¶Ùs=Mnl”€v“ªÝî`ë>öº3AñäÍfoÿêÚ'Ìžþ:¤]ÛÕ'ûÖ¿Ë¡lSG¿ÓýñõuR\…«óß×ߢ£(t�ý»u׃²Ew›ia}b,ß•ŽrØ;ßÿ^]Ù_GAØmëd €@€@ €@ @ €@ € °au7‡|uŠŸ¶ñ=&ŸÐÊ!‹Ë/–!Áù–s‘�ýeÕü%òí×߈­=`;q=CdÓâZÙ½ëIùú˯åóO>“Gv>,)%zþ¸yï�wä‡ÞãA¯ ö:Uæ œ&â†è{@ÓEP^"×ϹZå¹Ê":�-k.X&ß}ó­èñæ¿^?h�sV’|ÿÝ÷òûo¿ËK»Ÿ—6m—»¯¿C~øîÑã‚Q3�k ÷våÊ͵—¬ªxdu’”ËZJpß^ûÊ|eYåerå”MÚî -4=�­�²eâ:Y=b©ø{üùyÙg&ŠúhB¡ ŽÍ?h ×nYºN2O�¯Wžà&½û�üüãO’Ð;Ô­{ßIT{Vðá;ïÛª7¢­¤×þMBƒ»ýù]8M@2&©Zßš}ê¯�Û¡ý -çòÓ\¯­€}‹¦^$zŒ)æÖ=^Tæ%÷Õþ×1 ü=ûJPŸ^–ò•Ã×%ë50Ñ÷€¦…`iå¥rÕ´-:×½ÁóG"˜Y9É5 à„ l(+6AI‰ÿ}߀vÐ_søÉ¨¾ò �SÞsúÉëuïïêí”Êv wÚýëLóvÈ}uõßrøúzŠ·¯øÛ â[÷“ÍÝòt?§|àô“�üü乺׋»8$Ô£~+º:Ìg”¶õ5÷õî¾{ÛáÏ6ÃÚŸYשÝ&癎ùQ ¶­Ù*z”'�ð@Ì�öf @�OýQÏ6Àì¼)ú¾¹í ¿âë'ë»;LüÚžNùØÏÏ”_ÜÙaéüßÒËiÎ=Ú×)K»:dY�Ý}M™^k+ÐNþ?û8åÆº¶ÖÔÕÑÏ~¾ßÞ6®èá°Z®AÁN§l¬«{¿�SZÿY§4`€vjuÀ£$ö 3 ð½òüÝm฿üü‹¼úÂs/Ÿü©<ñà£2:¯J×.°¨µ#WÈæ ëê^›kš (úK=ËËWÞqúɧ~~’æé:§OùMý«{8%p¿úÁýôé¼9WÓÞ×­)Ú†ú™ ¥mÜÆÄ´óL�æ}Tí\ß¹ýVÑ£&»ÌÖ55IÞ2§¤m=WŸÿ7yhãZÊUH›>�¶¹ûá'䃷ߗ�7í�ík¯�{n¸Óµ»ÁúËVÛfçM6ßW”w€¾œ¤€­úe]–Q:Mà3??‰iem+ÇË×Ô¿¡§Óí5®«»Vë'{Z€’ƒs ¦îëÐú•`Áä D�ÍKÖÙ¾fô²kóØéíÓh› ,ÜÚá yæ‘§ä�?þ�ÂÐ,[Àø”–À¤™€²v¾–!ùo;ýtÞþ×xßé§ÓlµŸáék†ÿ?àã4ë|¸oÚ�Jõô=¤`áÐ µC«+Ûñ`L~µé\?ûèn òòs•³)6ŒÊ­=4¨°TG 6ßWÁú¾9€s÷ÚIw•½«|kPïü6]tP×Ð@áÊYÕÕ!—tvÈC}œn—™o:´Á^§Ñ (,[~üþGùèÝ$Á'LËNÈ``ÿLÑC)<¤àôæ€vÈõœÎûw•=ÜÇ)ŸøùId+k[éž¾¦þvSží·w5ÿð¿´³µ»Ã­`VîÞ9í1�ƒŽX�Ü/B>ùàcùþÛï$?(]ËNØ`þy3D�ÅÓ.±ŒMγðŸ.¨‹òõ÷ø³|¦·©¯õz[þyü¹;À�ý¶\¹¯ó>¼}ýö_uø™Àÿ/‹ÞÓÛ½ãöÍiÏòM8"@¸÷™²çÙ—äß¿ÿ.#²†jÙqt!ÂÈÎþ–ò‚à ùò³/LP‘ꈲ¹àó}Ev4í5@ Ãö7twÈüNÝfO·Ü3*ÛùZæùïØ×I×áú º8da�Çúî-[»ßt5¡£¯)Ù×)—÷pÈè}{÷ÿcßçêv~vvHmÝû}̓nÏÈ4Ú±e–sÞgigßå¶m7‰Ï?ñìþå:¿ßÕÑ~à¶�¢Çk/½¢ç,ÆÕó`Pt®èñÞ›ïʽ7ï�m«·È#;6ëüöëoR�>Äö.µ£VʦñkÙ°¹@pgo§ìÙסŸS®ééÜû?K0·“Cì³wÿë?¹»îúí­õë\Õá üi=�Và1°¤‹Ã|æGuçéã4S Æuôu+isš\;ë*¹dð<Ë9�»oçiwÚÞ{öt6Z÷ÚõÛÜú¢;ûHŠOO·®-É”k×]%¯<¿G¾úüKùåç_ä­WÞ0Û¦ùÅh[@D‡³LX2+wÿÁÖhzt'€í3®�Ðvgðƒ[Ë€Ågçð=@ÓSìŸc:¶U‘ƒö/'èÝ{¿r_Y]³T¶L\'­œZ hZ´C»yB­ÔŽ^Y÷Ú¡eÍZü˜6&èØÇU–wZš IF'Vë{@ÓT^b:¸åaÅú¾ÙÒNÚò’º¤…œíñç.«F,‘+§n–0¦I@S°¼j� Ìm¾�ÿ}$ùBóô?*ÇÛUìuªÌ/œ.Ãc†ê{@ÓæïÑÌ·¶óè' ½$2Û[_óý €@N€ °ý™’‘7U*Wï’ᛞ‘ìâ9¬yZºä×,—!Þ,Õµ�Kùâ�R8®V¢NÏpûó‡^z‡MÚ¤¯›<ÿVN)™~…$Æ–•ï ¬oœ »V*W>$Uk‘â©[%úÌlkÝ#øûE�‘)…ã×IÙ»Í5ƒç]'ñ᥶>/9i¸ù7¥rÍ?X]ý[´ÞA•ÎÚæÆý¹ÿïÝÝ6ܯïþwnáá+É Õ2hεR½ö1©Xþ€”ÎÜ&))5òÿì�…o$;ÆOxÌ÷˜™)ÌÌÌÌø˜™™™™™™™ù_ò姬£^µ';Þo7Ò(%铦Ýî.—«=r¡óþy¤D3¢¿.k�'EÖ3·|˜qlÐÕåÅ�0‡ñë3ï_G¹�“ïq­ígø¶\‡Á`0 ƒòÿsŒë¸È-Þÿ@7}ûënZk ‡¸�òéFÎ}ÜõÎÞÈ&qu³ûøï®& kÚ(­…{òÛM]û&J-¿]Éþ•®üІœw模zv­­­û‡¢]vp�4G¶:””-æ½ù‡`ù±ß\mÉHxL¢üø>x†>ƒ§Ýçúos()´57�´.½ÂÝòý»³2ð>ú„€¢É;O»?f|Â÷.¬¡¿:çIÅÙòÌÜŸ9¾•¾¥ÛÜôõo»ÙÛ>f\ÍØþº¬ãxReí ¬¯ž©ëRè¾T–s ?ÚƯOÆ6~Ù‹ná¾o]ÁÿŽ£Í`0 ƒ!×aM6~£ç?é*�îÀ;¼î¦ï6ŠmÞ?�ت½hÏb6Ênòš7²ó’ÿý0b6Ÿ®±nÁM\ù Jв[zäg<`¹éýÿÇánþÎÏW”ù7Ø@¯µžzóêj‹†·{xßô�ï¹åG~qå‡5m%Cæ¥>ïI¹èò«:®›q36W°Ë kí»žÀØ1DàñÌHoà”Uå¦küª”‚‹¾ù[x‡«)Œ_ì÷.¬½¿:çÍ­§ò7rþ|ÉïˆwI4cû벎çI•µ7 ˆëß….#}ã×gå±�ŽöŽÁ‹¹Îq ƒÁ`0˜À‡”ûßÑ›ä${_~ì×%óÐì6ÌûU¬(Æ÷Bày¼Òx¦rRh(×ðCHo²�Í}éA5Ò teÚŒ·lQ$êÊ'’í²üº'¯q¼·ò¨¶TÿÚâ‘u½½ÕùýŽûÃç<ê*ŽhQ „Bc ÀK*ŒOúÞ…wDôç<©@’R2{ˇa/²D3¾¿$ë0O‚œt€@OàG˜Ca}N^ýš›¿ë Œ›\ ƒÁ`0l4ÌpZË.o%ÿ90‚ ¦±™�½õ#6œQÏæ>yõëÐ\óžï]’³B#ß–�7ù³;xæ~"� éÁ/âžO!ðPå‡rÀ{ƒ ¼Ž^ðTPA±Y|ðW´W±+?¼Y24TÏðù‡m¢j÷6d“œÿï£]ÏôõŽçZÚNË:`èôx†âW(Ÿ(ÁxÄgãUt¯½ïü•÷¼ìÈ�'L¾wþfW°Ëñ[‡&ßù9áö)åš¼w¯<û°}øG¦ ÙØ%ÏñÏ“7ÏÆ=8B¡ñà‡rn{gnpÐ(= z{ç€käû1¦ÀóÓ׿“hÓå×5v%í(Ág÷Ìͤڙ?žkn9…kÙ€2ÉóÅû– ãË €Êè¼$“±H¡Û_—u˜§\6üs(¬O"‘¸‡’kƒÁ`0 CN¦è›äÞ¹›Pˆñ"ñ aèQ´P:[»Î&DÅÏù¨TÑŽª¸}òç[ÚOG9!™Êä[yâ«NèAA'·žçÖ6·.›½í ]¥6È´Sð«càB*çó^Úwj,õ•SÜ£`€è9 ¶ÀºJ vùk]~laÎ0‚¤¼½Ô @9bNF R ( F»jÀ`èx®Œ/g *O év "C:‡.qȯ<Æ1ÒK þ{œ@3ª¿&k�§eÀG�Nh ?vÑ3Ôò€7‰^o zôP¬£ Y^P´2…áRÔk꺷"Þ©Ë%eȧSàE1Ꞻ–9\Cÿ‰wúcã¸&„<«÷ûcÈH•H¶GŽ/÷ O>½(« >q"ÐŒí¯ËZäI—u5EC«FÀö3âé)üs¨¬OR«’ǘ ƒÁ`06ÐpFÛ.m z €÷Œö;~Éó6IxºæîøÔ55,Á‘d©�ð…D À'J;›í8Àq]þììd;ùôá ½nHFºâ‰{É„Šü¢Î=§æוÇtp��M64|žtÙ!OkÄørÍ ð”ŒRÉhh¡naà|û:M¡„¬UždY'ÀyWÏÌ ñrVøæPXŸÞ€áƒëMƒÁ`0 KƒJû² Y‘?‹òšmˆ,9¶l¬GÎ}lµN@×Ùq)ÝçpÏ5Ö-7ßÅ{—î E yG¨@"Õ¼¹ŸF!ȯsø2úQ¼/¦p:‘Á(}|9`æœúxzñ‡Ö€O'ÑiŠý#d­ò¤É:\{„4 xz ? ë“I¸_~˜¥l* ƒÁ`0@kÇ™®¦`€ jª?¡ãñ§h`<ÐÄ;ž÷�#¶Ý¿ó,¿qÇh@Åm*b³ÎÆÀ¦�´BœSFŠ‚ñLåÑ;ÅÀœû#“>ŽúòÊ©q�Œ À0@MA~ä'ZœÊýFy>û]ÁKÆS¤ñå€@�s‘Bÿ¤×¹óíû0ñHšBAÖO‚œxo°UôçïùŠ5Çú=�a“ˆ,È ×¹ ƒÁ`0 3p„W2Ô‡™SP.ÙŽb‰Âë+`ÏÝþ)E¬Ø ’?J¾*íT±÷Gìm E¥ndãÁCOŽ+›ëd¥þòÃñüS´Ì+Àx´hãx=æ"e ê~Ïôuœ�O¸/›~àªóúRc!ÝÀGè€0*�j#âO›rê��Å>Ùw-¯wàä{¸Þnùõ-¬Æ.~>ÜðY� ´`Œ ¯x§ ¯!%,~|ñßûŽX3ñýõ9O†â/Üû iÃDÖç[ý®¯yƒïA�sLAÖOª¬ ͧ?µ5<-¢‡à‘ÿŒêz…ï"žu…õ‰¡”ÿ ;0×a0 ƒÁ …»d•ê+Jìr<…¯Ø³ÑçÈ/ÎÑ'ß5Õ/ùx Šøáé&w�±à!ç-BÙK¬¦Ïoÿ»ÑãœòäóÞÛ†B�2ŒœóÇ€Q!~ÙÔcTȤ¢ˆóL” >ÿ¸~EÙzÅCç}sŒaÈ#HTráz»åÇyäÝãW¹©kß ?ÆêЮ+a0Ç>²#x?j|Â÷®¯™øþúœ'ç±tÅt7kŽæC©Ä@µBëHMÎQýY <‰²f�Q¨þ¨Âÿ ÿ!èÓ|zñü(s(¬OŒ9Üã¨Çÿ³w×XQEWÁ>°ww‹p× ÏÉpY`oœ�3š S}npq—‘×U¿ãy€l°€ò[Ê‹;ãqg(–G—IxØÙ8÷õå@gÓ\Î>úÜКÄ÷KþÎc aîV  n$¯\?Åòúo{éc¿}|¼úªš$¾€˜+—[ÃÓ§ñ<€�+¦pÇûöön½í»¯‰Á�±�Ø-H†£ÿ1� æ¦Äì?@(² &yw·.Å,€X ðzþþÉ£$¾w€œ:³÷§Nõó€rGÏÞÇ`ÀÁñGÿ�Ô¸Ü@@@@² @@@¸X»È%€€€ð»@xfßœÂ,‚(ü}û¸¶�›;¶mÛÖÚ¶mÛ¶mÛ¶m[g3µ«Wƒzøݧ+§N'½Ë*ðLE‰Æ%ke‹Äu *04¶" üSô™—ÕÁ˜žÃðòù ÀÔ!ÒŒcSÙÓ†Nđ݇ðüés<~ð{7ïBœShªúk¬™¿—Î\Àû·ïpïÖ]l[µ Q¶�ÿ}›øé¹`ËŠ xþä^¿z�Ûö Ö1$…nh‡þ€zn‘!¾€^`¿‰ÄÏvù è Š¨¢G`Ô³ }Ç0 Ã0 Ã0 “û €8ÓP,é6ú~¿ÚÌÊhc\ïxõâ%àêùËéj^ZTh}þôgŽœÄÒi °qÉZ¼yõ†ÆõnÒ9‰¾±Om m÷†íX0a6Ö.XIáׯ_ÑÐ3æ¿m�+?¼}ý6Þ” œVÎ^‚×/_áËçÏhPOÀˆ/ ØoBùdÓüôµ0¢ö@Ìi7 ÆÅ5¨-×Â0 Ã0 Ã0 z…$Ìh= c ‡N�„|<5í€fð£í‚h¶>�B�ÆÎ> îê¶IÚíª™àÞÍ;TŒÙU5NXna cZ°¸Z½S-s2Ο8+¼NõlË`PÝÂ"ci=®]¼Š�>"ÄÔ+Éö�ó"𘪀 _@Ÿ¹ý&žOÙ*?ñ|öd~5s¨KÿçZ†a†a†a@žõ§(Ú((µ×¨t) µL3¤}_ÈÌl2qhç~z“@·�$´N}cŠ`ëÄ|Bck;…Q®ãûŒLÑ׿eêkÖ8s€x|½À~ŠOdÃüÄó](f´žLfµåF†a†a†a`xí˜Ûa}�Žî· €ÎµÛ¤ü �åÛ×náÁ�ûôÿ?6èuqð×wMÑçXÓ èÛòLâñôûM<~6ÌO<ŸX“2ÁBu|þÎyÆ0 Ã0 Ã0 ƒË)0¹¢'jJ¸¯TâL- Ãä6ýIõz2ñÚ½Õ%Ü“u'eýLyœEÁ�•ü÷e…·$% '_§D-ZÞÊ*tÚaRBS.|æ¡W0æ͘7n&��uNWgZZóÆÎ mÿV=“÷cï€%Y–0ü^àk{w¦{mÛ¶mÛ¶mÛ¶mÛ¶m#ïdÍ̹Û[sóhñWÄg»:#'cj•Ue…Àõ ø~ºû:„‹OŸ×€=›vªwoß¼U?·¬Ø@•²–”úØËÖMîÿëŒOOú°I”Щxk~x˜S6ƒG7hn4ƒÎÛ�sƒ"Ú-Éÿ昆šg»îáí4:²] §m¥ùL,¨ÊF�vÛb”Ü]™ÿÏ8tÉá÷¬Í´LùdE9ñá"€�&䈕Vݽ>{ì4wðÖfþøY\Ð]0��jó|°÷oߣk®øøþؾ#ôôñMàšó'̦¡ûÓ‚‰³•ÍÇ�©G£Žÿ{Ùº ý¥ñÉãÛ`8Mi>Þñë@8•€Ð3‚ݲ#Ï úMC�ðšëÎiÛ)¼5ynƦæûE´Î�Œ¤ìÕIö½6†AÏåCê‰M‹¼õ•�7f¦@xvõÜåÄ÷ªþ_ŽS‡Žs%w�>£^ÎpÔ¹\H sºÿLÛ&ý_›gR…ˆå«¿÷ïÞÓ©Ã'||ÏÅëxp}ß®ðqs.~È¢BøØÿ§u ÿ_[|òx:o¥þ,d —ŒŸ�j숥vËóô _xè<Ö¯ÍïŽíô1'ª¡>§¿S$ÐèR²�+éI(@ÿV=ˆÇ”Áã}µK".eŠ”\%ýÜ"Ž+¸óQú"‰súùÛþJ;¦üÏc2„‹éç €«ç/{¼ƒì[ €î :¸O4ü ìë&ôÿ•Æ'�§YL lt÷w?_5L~ö‘=± ÍGþ¿ltËt¾ßäð—̧€«ô䤇«Ÿ¸Ð¸D-ÕÏÿÈâo“ç<¦e…†Äƒ�ÒG €gOžúx‡üú¥ktþäY�nCÇcÖÈ©ÿ{Áº ý¥ñÉã©•±¢ú³P2a~~z®&�³›Ô>œÝ[ê…Ö}dÿ3Ž:5À~6ÄtþÓé[©›JzRþ7@€2i Ñ«¯ø¼åø»§¤ “�>~ø@wìr`ŬÅÄ£X²<ÞÖ3à±ná*�þx,œ4Gà_`/X7¡ÿ¯->©½.$€@0`G,g‡€Ô¿{xïÞÁúÝ7MZÃé«O»·¶‹9ï=gŽ�B.è­ÖT ¿Ïžk­Ø<%KÔ”Z¢T@­¼‰ÇÈnƒu¿M:�Æ%k{$´¯Öœ_±�À¿À^°nBÿ_i|òxšäªƒ+/zºlçE3(åï$¿.ûÞŽŸÜ!€[>p<—¡VS׽炶ìR@kãwúÈIµ{_·`ß¿¬Ö=©^ájZg€ä|ô_»;TÇsåÜ%Uƒ Tê^óâgU¢Æƒ;÷øJƒ&Ô)PÙâ‡kðQs.JW0av��½`Ýäþ¿Îø¤ñp @þ³�!lR~z’;ØêšãV~£ØÕŽþøÈvµÃŸ÷¯}” aS;ÿ›Ô±ëÜ ›Aé¾hX*a•ôÔÍ¢WèO.±JÊܬ˜½„xpµÏçÝÉß¹æÞ÷<‰/¿ÓhV¦ž²M6¡êÕÎãöõ[´uÕ&š=j*-Ÿ¹Hõiç±sý6‚\`¸ÿ›W¯Uÿ¥ÓÒ¢ÉsUá¸ï?°hÁ6šðèþCuÔLÏal¯M#º øØ ×MÏWŸØž×pMn6mÁ'0Éto§­± ºl7éžiÒ›I‹£TøoåC]8Ç ë†I9ÿ´úì­>Ou°Ì§ ŸæwœE}*ê;í|wß“‘*T|¯�{¿÷ÉwûÏ9¹êÀmÙÔŽíë7ôàî}U4°K�6Ü@¼™"ĤÜ1£¹ŸE”LU€6/_¯GN$÷nÞI•³•ÒìXà�eNô9‰eaãá½´gÓNjT¼¦À¿Ä^¾nÒxþaï.À«ºÒ~�Ïw­Ð‚C½”·$„$¸•ÚÅBqhûÕÝ(õw:@¨0µq—ºëçîîîöÞžE›{3ç�iÃǤ¿<Ïï™ì½ö^çì�™ißÿÞk­ðûµøøÑ݆¥ lMý ih9À‰+­ðômODe—!iûs'œ?|fÛ½N@0¿df*~VŽiHÛðùR»/ۮߥ…ýÚìu€Tôì¿noì½rgÖ„|mÌT›°+§¬jÓ× ’壤"hYÕü´ý9iâÊ]—n‰'oÞUŸƒ!0€ ½°}å†h(«OÛŸP^40îž{k\2~I›¾N@�õ4´�ü!À÷ €  € ªÏĸèê=±bç+±ò¡7bþÍcÜПIßc‡L�¹×î‹¥¿«ö¾‹îz.&�Z˜uܘAuqÉc6ktÿê–|ŒX«ö¼•ŠóÙ—íˆY«·¤`õ#ïÇÄÊyŸªïé³oI…ûŠÝ¯Åœ+vEýÊM±|ûKi_õÔKs kŸ‰™ wç4ò´Šcþ ((ŽÅ~+Vï{7F÷›Ú¸¿òì±™ ½PÚq@‹ú7læá‚þÎgcD÷’Æý#z”IJÍ?L�CYסYÀùs×äí-(ҧϹ5«­¦öòÔ6itC‹úž¹èžtþØAuYm+æ5¾ @�Ã5Ýcí‚ÎyUv9'ß§×ý3E÷¨s'eµ�:>­ � š ïx:fÌ_›eRÕ‚–\#V?ü^,ºûù#¶Ï¿q*ÊK û~²/ãiÞ€Ù·¤â}Þ �¥Æž–uþ´ú›2Ǧ7êWmŠúåRŸ«ö¾“Yy �—ú>Še/\¾¾Å× ÞX÷í£} )éÐ/ÍìŸyºÿÉÓ.¼áˆ}L(Ÿ ny<3t ¤qÿ™§ù w<�Þhý!`€T˜q€ ß�‹ïûZÖþʳÆÄÊ/¾™ ö7?Þøÿ¤âášC€\\U×=îjè”ÏQ­0ûÒm©è®ê3!«­ü”òÔ6çŠÝ9ÛVìx%µ§™ü›yUž=6�›™(P€ u¥IýÒ+ü³nÎj«®ùéÔ6±r^Ó¶‚â4Ž?3À¼ëIÇÔ͸öX>7ù™ó2o´¶‚â4Àª}ïĨâ)�û+Î�Öé_¾íÅ̘ÿ&çÔžM*Ôkg\¥�Åâ¿«y/×riU€±CÏÏš 3ÀÜk÷¥m€ã`ì º´_fLfR¿ú•3ÿ¥¢~ˆÙMŽÝï¼ôä?3©_zí?훚ٗYN0k¹¿úÏpë“qá’bî5ûRñŸ Ê{– ÇɨâÉ1÷š½©ðÏóo>˜µ¬ßá§ýßÌL˜ÖñoòVÀŒkSñž š¼ÐuXÌ\xW\|ïWÒÒK7~/f,¼+íODz €@ €@�€@  €@²€@  øœ@EÁ¹ñÅÓúƯ÷�?éß?ÞïÓ/¶œÒ·É1¥…}có²ââòÙ'Ô…– Œ».º%V�½8m·5_^ÿ¿cï�'ú¾ì=­oüõ€þñò9ýbmϾq¯¾q]÷â&Ç,µ ž_û¥X4bÖ v±Å±mÅúxò¦Ç¢²Ë�6ñÇ›=ô´ÊÙé÷§ïû?±ëê‚ôûԳϊé}ÏhY¿~­oÿøí�Œ,ÈÝ^Ö¡_¸~_ì¾tk”¤`à„2£ï”N\uÞª´ý“¬¬CŸøÆ–ÿ?xèÄêI=ãÉ»NŠíWÆõ3»ÆKÿTXÓîØû@Pú‘ÌÓÿ—z÷;Rg驦À^R1÷„½à�—lþ(¤x8…?é¼óÎ:+¶]^¯íÿB¼úØa¯<úSqÿ²¢Û«÷±÷ € ìãàGÍ[W¬‹§n9�ÆÛŸ¨¼¬j~ )”\xLç]QÓ=Ö.èœWe—sŽçõ¤Wý¿tÏI)ÈØwÓÉ1ñô³�½/›NIcÿsSxø˜ª®Cãùµ‡âžy·7}s û9Q½áä¨ÙÖ>ÊNkúTº¢ôô¨Û{RLº¼S /8¼¯ú¬1ñÈÕÅm\—÷ËW–Ÿ–ÎwQ÷œíVt‰Ú‡ÚEi·T”'£»OÀ³n:¦upM»T`ç3.ûÉ{ËïGž!;®*LŸùä�íâk›þw 2“f†Ü>·K+Ü¿6 @0³¨8®é^œ þÎíWu+n4âãBuaé…™Â:M˜µzÀ°Ó£nÏI1åæŽ1üãÀ ´gï¨ÙtrT¯;¹I�¹¤bnêçà �|´Ýü<%úDÍæö™>² æ’¢>Q»£]¦˜Î:oÏå;bÿuûûo}-ºyÝ·¤(®›Ñ-J ÏMÅÿîk ¢ü£ë¾saç¸ev >Ûû€!××þt*Ük{�ËÕžyÊœž6�­ï‘ŠÍÉ×EÝOŠ‘ƒšÎV?¢ã€"Ôõ™�¶ó¿°[êwä�¦ýT�>5í¯¬8-ëœ;fݘ¾ëØ¥iûøË?ŽÕsþŸØ—ÀOwÿÜ9çæ�‹ê’#>m>ïöéÉ÷„]Rq9fF�O¿¾ñY©¯ K›>ñžtU§¨ÙÚ>J:öÉ:çÚêK³ÃŠÖת÷cŸž±¨ò”Ö½6.¹/ÕÍÍ®?â̳Ók噂sò E�¯¿Zç­-ŒšííÓkëéuú礧éãwÍyüª±‹Òw�3dÚqŸ õïG+Þ?ë.¾;ÕåE޽çgr¥=z§'ÖŸLX7åÖQý@Á ê«§^rü‡´þýhýû€àš�ÇÕŸ_<9÷Sæi=‹Ü’N}b꽩è,ïwægp!iÌz*¦ËûŸùñäzÝ�tlf Àô]Çt/9þ7½õïGëÝ? ™žŠêK',Íj+ï{f*.'ßÐ1†4Ý7õþ‚(éܧñØ)gTÅ®K·Äu5—Ó…TV^Ó~ê}™ÿLãë�tìÞ+vÆc×î9þ˶à~´žÜ?#; Šg×<.º«ÉþôtûžÂ¨ÙÖ>ÊNm2A^zú]·7͂߸oõØ‹S�ð܇šÌ'�Gš­¾fkOŸ^a?Òq£» Ký¯©¿áøßðÜ�Ö•çþµ}€H+<}ÛQÙeH‹¿PUס±ïÊ]qàú}Çü„~üÅ]3lšÄ.íkfÀùÃg¦mŽíþ ˆù%3Sq½rLCËÇ¢ŸV‘Þ$X>jÁ1Ÿ;ay—ô}i÷#ÍÄ_»/ۚ…ÒÂô&Gÿ$©¨ÞÝÞØ{åÎ�~ïÛ¢>nœ~e\_wù±>ýOãækw¶‹IWt:â1³Õ¦€âÊ)«Ò6ùï€\Ò“ûL‘½¬j~‹Î/ëпE“ó�štJz}½ªêÔÜnAqš\ðÉ›÷GUÖòÝ?Yol_¹!Êê�ë…L¹¥cÔlo%E}r¶— Œ»çÞ—Œ_âß‚û€ çÓöãy#zŸuxöü¥]ZðÝÈÿ@  €@ä&€@ €@-%€€1½Jb×Ý[âïþæo#óóè¦=Í_RPw^rsüü»?ÿôÿùg¼þnÜ{嚨è:¸ñ¸·_|=òý|øÆ{­ym Ýsx?9öÞ+n�ƒÛÎé¥oý(õñýç¿Ýš×€C§¤"ü�¾K&Ï�Efç ¸æÎtÌë?x%FvØä­€ g”õg?÷È¡ÔÏO_°§|ZÚn©·^x=õ3}ÐÄ´ÝV HEþ”[;ÄÄË:Ǹ¹ÝbüÂn1õÞ‚¨Û{RLXÖ帘üÀW>—Ú§ž;:ö>°3~æÍ÷ãþþâ·í·âé=OÄØSJó~FM¿qñ_ÿõ_i…€´Úú€’Ž}¢zÝÉQ»»] /<ñ€7ôZjÿ³?úÓø—úçÌ~™ÉüÒ$‚‘VÓ«¤¹ÏHÃ2?7/¹:mÀçb€‰«;§·ÊNí}Â/û…Ô~pÛ#1îÔ²œãúßþè‘úO+üþoþnüí_ÿMŒì2(íksŒ8óìôúÿ”;Fõ†“£vG»Tüg”�~ö ?À³ûžJí•݆ä,îÿà·?~ëW~ãˆý/;o^:ÿÐîi»Í@PYyZšø¯fKû4æÜEÝcÌôž1åæŽÇ\U×=îjè”Wk¬°íöõ©½a\}Îöw_y+þýßþ=-ØÜULOÛÐæ€©wFÍÖöQòc…ùø%]€}À´�Ò~9žà§7þü�ÿ,~ç×~+ç¹£z �üûŒ_|ÿçÒv›€ zýÉiÙ¿áM'œ|mÑOJ�¼ö½—â?ÿó?ãŠúMŠÿÍ·<ØìëýkVÞ˜Úï½rMÚn“Œ›×-ú“oìcêzƸÝbêýQûP»ÿ¶`t�a©ØÿÄ7}5é?÷ÎÏ4Ù?¢¨ã93†N‰¿ù«¿‰ÿü�ÿˆ¾þýTðÿÜÛ¦ó~åg)ªºÉùYï½òvZ9 q•€¶@I‡>1¶¾GT?X�æ˜r[‡5ᔨ}ê[0¹wUÅOÖŒýuÆÇ·¾ôµø«?ÿËø§ø§Tøo¹õÁ¨è:øˆC2?ß|ê+i» @ €€6€€²®CcÚ¬›cÅî×â’Ç>Œó×6NAqL�¼*Ö>«ö¼Ë·¿ o?ÕÕ—EiÑÀÆãæß|0õל…kµæµ€ ¬Ë�˜>û–X¹ûõTŒ/~à›ù€TüϾlG:nÙ–ŬÕ[¢~Õ¦X|ÿ×cé¦ï§>?9¶zê¥1³áîœæ^»/õ1çŠÝ­y� ¨<{l*Âç߸?ÆžcÕå ªk/OÇÌ»ñ±(í8 I00¢GÉQvýò ©Ÿ åsÒ6ZQUŸ‰�¿ç R‘¿dÝ·cé†ï6>éo�4L`åCo¤7J ûþx;®¨éktΫ²Ë9ÇøEòãKëSû´ú›ÒvKM¿$õsþÜÛsµ€ààšvñÚþ/ä5®WïÏ<˜>ç¶Ô>êÜIi»¥æßt õSqæè´ €ã&0kÕæÔ>òÔ‘qþE·ÅÂ5_J¯ò/~ð[qáÒcD×ay?£âôʸäÑÒ 'Þ�Oî—m}!Ví};-áW¿|CšD0³?­ÐuhsŸ‘†dŽ�2nIÚ>Á€`îu§ö™ ÷ĈnÃrŽëŸ¹èžf—\²á»±b×kQZ4àDüc€9.\¶.µ—v”³¸_ºñ{±ø�o±ÿ±CÏOç_°øþæ¾®ªëw5tʧUV¨»àúÔ>f`MÎö·>«~/…ÍÍ!0ªxJÚ>€!gŒJøåx‚ŸŠþå[_ˆ%ë¾�óܲ΃cåߌEw=—¶OL Hæ]ÿh &Œ¼¨Iñ_;ãÚf_ï?oÒŠÔ^]}Ùñ¼&”u’ŠýO̾t[*ÒÖ>ÓdI‡~�çTž=6Vì|5V?ò~\tõžTð7Üñt:oÑ=_IóäðdZ9 k•€Ö€ò^#RážGÖŒýgTÅì˶Çò/Ǫ=o¥Â¿nƵ7ðHCR?™€!»€@ €Ü€@  €@ ›@  €@ óÙ; I¶% _ß±¹c½cöìØkÛ¶mÛ¶mÛ¶mÛÞÿÝ<±[ñ*ºûÆt×è½ÈŒø"ºNŸê:•ÊÿœÌt(Šq½GàõËW ›>l’έW‡vîÇ›W¯ñäÁcl_½•‚Khœ{çÚ-h³§�ž¤«3z7邟6{ÔTËŒ]11§;.ºyâ¡§'޹x`„£»lN1w ¯=ÕýÊ*öWQc7ôlØgŽœÂû·ïñìñSßw}›wC€u]ׯ×zü̽ѫ|'4«žæß^>øOLno”ž¾g†a†a†a ľ&ô%‚v²ë¯ê%´©Ôdô;«æ,ÖåðùÓgA5U�äÛ7o1oìL5&—nŽˆÊ(D�oß¾e¹09§;^xyb—³zØ»£¿ƒ;ÚØºÉE”àÊXÖc!ªù–Qä/Ö/Z ²G÷bõÜeX1k ®ž¿Œû·îÒÿ®ä]tX�FÕŒyf Ъ Öß+[('TŽùÄçEýþ¸–Æâsl¾¼HvÏ­Ô÷ Ã0 Ã0 Ã0,¤ŠÙþ­{P3ªªE”ÕY �fÚõ¥]攂QÒxåÐRøöõ+Ží9¬)€¤@4ñaÑ�Í1E±Ð ÒCê›é}ÿewOÜøcÍßû˜z`VÛ)ßh$ùT‘¿´ê ²}[vÃßÒ[ö_EäöSìW]Ö“ê-D�1õµ¼· ÖŒø[&ü&|<¯×ßÝÌmKXcçÔ_1«›Íc†a†a†Q §”ñI�>ë#$ç/´ã¬öÝùgñáÝ{Ú‘Ît QJM�íZ¿UÂJ+ú×2ÇöÉ¿éuo± Ýÿ�NZçЮ?Ê5*( ¸É×·®ÜÀ�ë·bW˜Æ”¢XÀÛp8fµ�J"‡ÆïcòæÅ¨¦&Ø;óì™!Àîé¿¢ms„98¥Óº†a†a†a¸€" ÁS²ÍËÖ«}wãÒ5 3ýå¸SüîÍ;Ä»‡Ñi„,|~ÛþEYwæwšEyóŠüÕ ©:ÈÆõN×ÙB¨TIˆ•‹–Ò:‡Žú/ìó·ˆ)ŒP<—H `†a†a†É°@ÇÊ/ž:�O?Qð)�—HÆ÷ïß±hÒ\Ť�™ÆöŽÓ‡OŠTƒ—¯cÉÔPåôÑ8úЉ ëß²]g©0ÌQäþk$ÔDÌA�u!,ë±}*vUpOê?dåü’Ò4?.o(¦µœ€.%Ûd˜b[DÝËtИ0¦…ØýǼžX5ìO¨ HèZÁJ~ÂÁÁ ªÖˆíe‚„цHk€Ø>&+e‡¢.4‡a†a†a&#`€ ]ö›—¯ƒìÀ¶½èÛ¬+ÕÂ@x�$ —Ï\Åäž>|ŒÃ» y™z$(¨ÿGvÙ¦¥ë0¸]Ì>ßÀ½›wd+/.WÖ7_¿|ÅÉÇè8|– %ÌÝÐÊÖMüÇ]=ÐÂÆMÂ×XÌA•b¥(@¦"€t­È_+g/Y¬k&K~ {H4bL˜c1Ù|J9 gÏn7�Šö©?_Ùz$&5ƒ™m¦h|F¿šæh“jƒb&®"øßÊ~æ.èYÅ�ÊÊ ò£;›¢xcK„W°�ªŠ bû#qò߈¨-æ2 Ã0 Ã0 Ãd,$yGàÂÉsbwž‚ÁŸ6uðxÛR›O…)xߺr¥Ô5@êD@÷hhãGíëdãm*7Ù¨nCdùï§Ç—Ï_PºX<�é%4ޱC�Ê–2(0¥¼tù¸þΊRÚ&4Ax‚S8]+ò 0d�ï?"ɉýG±tÚQ葌vî©íãÏù¾f^BxHt‰Ð¼~eë‘è^¦½xÇ0;!@heéÀ¿0EÇ6€EÍ\7È ã PĄƆa†a†aÒhGùáÝpŠ‚‚¾æžh[¥©Ø&£�gU._ù1n Åàm R°*Ò*¦Hãпxú\­� Ÿ…—hï·mÕ&iŒD²ñ}FÒµÞÀ´N†t$=Í„Ú9)z–ëø#8–s½ýEE!ÞušÚé‹N5[�lÎèét�f¬G¢u\#m"‡Œºáö¨è¨óšŠ7°§|rpÑ@†a†a†a2†u²6•«Õ˜6d‚N�w³ÒuA6¤}_iìå³ø7;wì´˜™7@ìB“(0wÌ z‰5ó–ƒììÑSâºjxélUphÍ~˪äëë¯%S惌rMõîÞ¸ƒë¯êô둨VM¼c¹‚IŠŸã›'Ÿ8þÝÞ qCŒ�0Æ@ÿ„d†a†a&c`€Ž�“ÉsËbšv„íØ—¦ß¢Â�d &Ì–Æ^½x)NôjÜY#-ÊÖójEWD�îËVÀ ê½Epìgî%�éë¯Q]ƒL›ÈAõ(EB:Q¡íëÑ$P&æ…ÿâGŠœÿðò¶M¶GtG3†a†a†ÉHXX>cÈ(øÓT�Œæh¹_c¾ÿðN¥1*bG¹ìÒŽ¶d÷6€ÝJ‹üx¨|¥1}ýEõHtY0~–ÆO<¦‚�:=GÁz$ZÆ6”¥èKloÄ�4DQ+yÝUMk†a†a†I/Xˆv­õb\‚¥±Ž5[åüË þQŽþÆ%k€ öÉ‚ÐEèdPÛºçOžáíë7B8�^¦C?�­]°þ–Þÿ—@«ùñ)nQÒ˜¾þ"önÚI©t$_ö;˜“Iâ€(YA-éCmŽz7ØH´ý+b,/ÕÚ\›À0 Ã0 Ã0 Ã@ˆ]aY®<ÙdÔoÿ¿Æ©°Í—ré×/Z- ©=uX=wU�§Vq?çÊZÃÑÑt²;×o‹~ŒR…zÚµ¦£éõ««µ¤ªódnßóGvDyþèÒŽ÷ÿ¼P¾`²ŽEÔ’Æôõ‘Z(/Ÿ¿Ä·¯_±}õfqÏéC'€Z3ÊZ'Fç¸F#Ð&¾±–õ+_1¹ÙXÌh=Ij¨/ámD ÕÞ ¡‰ö¯lƒØþÆH˜` M`†a†a†a Ê)i1«üb~·zíE�ß³aGµªð]ê´Çõ©hßë—¯Äç®uÛ©åš—óO…ê.�¾ ªûS?ù—®‰vr ž*­UçéäÁ±½GðìñSºG´³Û¼l=J�Ë ÜÁ qNy2Dð·È�%Ýæc`µ^t­Ø_D¢— ë®»òÔž‘ÿ�"Àº€l^ƒ°êB|XÚ}�–Ê×bSX<ã?ìݳzmQÐþÚì®mÛ¶mÛfšØ¶õ”+ßáîcŒb4›ÕüçÂï ŸãÿûbýÄ…a÷…YáhÖøøZ‡~N ;öÍ ÛwÎDÀðC´@÷϶°mÚêA=ïöékBí›òÐü©6êÎ÷«hÀëëÎz×€±íúú³ñ"ùñ®[ƒzÞó·ÆG<Üqc€Î±8T¼(Š &,õ®cZ¼8núXjÞ”EÓ&Á—So§¯¬ûqåñx°ñæÐ“Øĺð±bùÁöëƒvÎ�— Xñ¿~üâøƒíßšÂöhj£Jç†[/ŒŠûÙðNìÓ1/hÐ÷vL¸ëÓÏœ‹OIpÛIé•ß:ñ 'LcD ˜]KN‹{ÙYÓNºI8 €0•�Ö@_wéÃ\_ú  £´nj›g…?'²Sl|ÑÀ? €…oʬæW-%¾ö™åÄÑÕ—TOÒÿÿ;yY^Ó5€pÖW\¥í“¿Ènó,þ½x}V?z _tðÏG`ïŒgäæîÿYJçSˉK릙æ¿3PéZ¤kIXîú´®€ã-=9ÐÞs÷òsâ\x‚/ºÈ\¨ ¬4lÝ/«Ÿ&-3¾6îÊë=ú*÷b‰}}P» €À¶ûâ˜TÛz×\‘æ)û$+¾¡ÃÀÛJÜ»q:–cþ#ÜõyW_×Ò3Îc›õ­ø6ÜŒ¬/0 €¦I{D«ë¯¾¬øZf’jï2}-Ÿñ¹VÙ} ©Oó´â^~^êGmÖ ¼~ä&Ýu7Ú—5Îï-ÃÖiÿ̘Ún­/¸ý¡ØçþÐÑ\¿ö‹zá«Èù�h·]â Û<‰}ü›ž›á}fŸgú¼½à9ú•~œ‡v>–”¯rÿXñ¿’Q:OyËœn¯OO,9Í €ßP Ê³Dƒh#€oog^ïÌ/:i5ŽÊŒ¯×±Œ€¾ íUVB£‘4УýQ/öêîú´€oãÍŽk,;+ŽÇþù_£Šß”9¶W¬té-Å•ã5ÀNí[Øîóæ©ûõX}Wîö'™kŒ¥Åü,Úª”^yØrWÜ+.HÜ;±=²¾Ú!k´}Òç™íÕÐgu#6FÖ€+ &ë|¥sa{;ìæ#õòóB¢'ÊÇZµÕ¢~žU—´ ŸVøï¡õ¥GUêJj&·i_P8LŸe%6FÔ€€j¿SƒìÌøzSpmòº£ï\húÜ\Piï]wMúø÷:�/æÕþbŸ{X‚;IFLMO¯O�m÷õD¯‰„�R~}c�ùª’Hü$M|ëoh@^?z‹Ô¶™ßhpmŸwÄtÿÞ8НÕ÷—�ýµ­VÖßùX�âgDUYVüo³MÇ0îâ—7Íj#;©9Üõ©´~ÅúÆÿæ;R\%ÕþåZø/¸ã¡dÆÖòˆÈ€Jø0Ij‡®Õ]üÀ–»X—�•è—û¶ºçŸ£…ùŒ÷õûÖ]×�vçâ“ú:À„’,ç‰z¡—î�©ò. s}æu6ŒÙª�¿‘hš¼WÒú—ðÅöc;öM 0:^@”!'š©m¦Þp&ø7 @€ l @ @€ @€ € @~*2Ú|À €P]-2 @€8€ @€ €»€ @¹ÿ½(AÛ–IEND®B`‚constants+book.png000066400000000000000000001677771526573132500345010ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/appdata-screenshots/0.12‰PNG  IHDR@•ÕïÆIDATxìØfAÇÑÍQ @´Ç(´´rµ�j´z�ZÚ#$’‰ÝÑdºCJ¯�ñ† |€ß¿9¿Ñ`<›Íæ!„ï®ë~†—�Çã…JË—¦!|M&“ÇÒúƒÑÿø¿Z.—ïç�ùp8äý~a€Òô¥íKã/‹·Òü#À¸ÄJ©’c€cN)•൴Ó¶í¼ïûS}Ç)¥Ót:}hÖëõg½‡«Õê£Ùn·}½G›Í¦kbŒ§z�Jû7õ ÀPÍìv»üôü’oïîs{}“Ù; ÞF’ ÿ¢efæ 333333333ã23ó†”ü�:½–fN£ÄñÚRž¤Oé®Û Úõº`ëî½âèæ!¥•2;;k“=ýðãO²zãf©kl2ØdxtL‚#"e×�Cj¿Î^RUW//§¦löÎÌΪýúanB!!„Ò70¨œ×�ÛwŠ_Pˆr®÷:"¾~X·àÅ‹âå ì[víQ{�NHWw9êàq€€%!„ „Bqr÷”u[¶Éí;w 7í÷îß·+ °´LÙRÒäÙ³ç°éLMMã/C!„à<ô •Ç�ë¶'OŸJPxÖl)B!ÄÑÍ]ÖoÝ.ç.\XÖ¹ÍÈÉS7ð›wîVÑ_}ýÍŸû“'’‘�«Âò÷=&¹…8ìM¯ãv?¿¸D=.»ö„(a=z¬æGN:Êôô´UG<53Kܼ|Ô^Ó³säÁǰ#b@¶±¥UÙ¾üúkýux6(,B¶îÚ£öÙÚÑ©R$ðwßá£J Àß}GŽICs‹özB!dE �á.ž^JÀo7o_صgK€B!-íêPF@RZºrˆççç9ÕÛ÷îW0œÞ=‡ë¢¢¼‚dÓö�j=·°HÖnÞ*qIÉx½Õu8È!‘Qê3SÓ¤»¯_b“ À·ß�9rýMÝÄ#E %#K£c¤¤¼Â´°fÓµ×â² ÊöÛï§Ô#bãÔ<<&VzÕ^*ªk Ÿ‹ï004\Ù;¡l?þü3ž!„BVwïÝ“ãNκàêå­‹ø·nߦ`K!„8èPP48æè §ÛàÜâfsðó/¿*[N~¡|ÿÃ�j\TV®­ëÎòÓgϬ­ÃÁÆ‚€Å€W_CÍGFÍxƒÝ¬àª¯Ãɇm`xDN�>­Æ¡‘ÑL¥ŒNL([Oÿæ„BV$ÀárãæMÖ°!„�©©)yóíwà«Ãáó·oßYR€h€Ûn¤hŽîRœ>sÖê::`<<6nQÐæeUÕÿ›ðÅW_)"^}ãMŒÑ�Àt €¯¿ýNÙêšš1'„BV HÝÃí¿vÞ#mîþýìB!l ˆ€8°qónQ@ òüÞ}ÿ¬ã5pÔ ¼|ùÒêºæ\�MLZ�Cˆð|„Õ#ÿ/ Z �¨¸Óì°á9m�C#£¦€o¾ûÎð?B!+ˆîh'¬åümŒ5 6„B�£jpª!ä«ÃúÃ�?YR@^»V‘ÿÂÅKj¯9׬®ÿ~ê”ZONÏ\® rùµ÷1ü€€qýÆ�e€¹¹9-Q áG�>ÓÀ©3g´ïŸGÀ„Bˆ»�ŸÁ b€!„�V(È·qûNôÕÇ 9ªßëuž?®;·;öíWµú‡Pá6ÔP¬‡Øwõö¡ž–¯omÝP0-+[úáh/ržÑ)ÀË?vTᇳ­ŠümݽѨ2lQž~þºhŸœ"¶í0-`�Ø;æÁ‘ꨬ©UQ !„ÍÑ7ˆõÃf»6€„BAh=ZÝ¡­|hs‡jý(àcpnw<Œ|>U,¹ÿŸ}þ…¡yU5D­M rçM¯Ã¹G‘@ÜУÃÚñí=td‘óŒî ìÜw@¶íÙQÂÂü—Ξ;‡[ ˆ(L„*þ¦­F„ T1FGƒãN.ÒÔÖN€B1B!Äž�s«UÀç÷Aþ`ÇŽ‰ b €™?ƒ/ØÏˆkpP¤ÙQ!€� € @€P3³@¶êî²Õ½ÿ²Õ9¿²U÷³@6€ ¼ì�ã²$M†¯hmÛ¶mÛ¶mÛ¶í=¶­ËÈï0INIŽ‚x—‡vÀŽŠ¢(Š¢(ТĬÀjè¶�µ‹]VaW¬Yê2BM–®\%……Nÿ“gOeðˆ‘Ò¸ekúeíÆ�¾ú#F4S¦�Èa¸Y›v2rìxyûþ}­:t”CG�RÚÎg¥[ï¾òðñãÀ ÊÈ÷8(=û�íÚ#0C s_Sf̤=„””[z>yú i£”ž˜»ãl›ËƒGŽÈÀa#B¾kñòÒ¥goª œ¶¹ ñ9ËØÍCÏX��8Ù+þ&¾r s‡qÑÞ¬º¿ï !Ò¡kw>oÍï€ KŒ¼ þ¬­ß¼Y:uï)äò„)Ó$>>ž¾XCQEQEQÔ8{á‚ÔkÒL¦Ïž+Ÿ>ö|Ïœ ¡‘–ž&99Ù2|ôXYµv�ÐWVV*MZµ‘ÝûöKbR’|ýöU^¼zeís SSÎêuNnŽìܳGXÝNJNrÞ�@Y¶j•¼|ýJ(Ég�x›Ž�§ÿ\p­Û¸I2³2²²³œ~c}óö­äååqOž@+Ð._öÌýR*ßgà 9pø°;ÎÖ¹DøqééÎV‚v�»’ô9‚¸eûŽòàáCûøÌCîxØsjý¦ÍÕñ,Œ)7/Wî?|hæÚ’ß‘ÍGØ ÉG[ŒÂ\c±�äû�ï)Ü¿1 EQEQE‰µ§|ûþ�Ud„ +€!"aà.'G¬± Êëüü<¡ÿúÍ›¦,}¡BŒ÷ÕoÚ\ž>²��UYV'1B„ç»÷ï…ïÏÈ̈ø!€Œ•¾¢¢BAp?}öÌc @ðDƒf-äÖ�;ÂubR"cA�ºãl�K ª�6^øøQzôí/ÄãØÉ“B۫ׯÑ[RZb_0yø§€5§ÁÌ5÷ì1×–üŽ`>ºÀ°ÇÈmx_U§ÎžåZQEQEQ”X} lѲ傈à€9Ú^¿yÃ5Ý�•Z ¶ïÞ͵Lš6Ý”íûé3B ¡É{XQ éß´mŸ g°bkʺƒ*¹f%˜ß¤Ô:* S¾pé2^ËácÇ(ã÷г¯¹Ü¼m»LŸ=‡×TaȆÍ[äÈñã̃Ó?sî<˘ÍÃg¸rÊÌ5yé9×–üz €=FvF�Ÿ`¶2Ä*Š¢(Š¢(Š¢€aã–­Žˆüüå BJJŠkýÌ×ïßdþâÅ”í#Vüô!FÙ?¿á~„b“’äh2(ûç7©ˆàÜ…‹ìeg2rÜxÙè°—àõ3—œ¾Ï ?�å#X…§üŸ=î¬ú³½Àˆr �åa¤ ba1{,¹°`�‘`뎼ŽuEQEQE €£ÇOÈ�£œ’`JÌï޿ϵ•/_"�؃lí3BŒ2v„‹{ÿôˆ±ã7Qe°ïšßä 8?ÀžýûM,#g&°ÚË6âÈcô¼¯¯¹dë‡Çq¶{ýËËËi“î}úÊ™sçùöÂÛÇ|šX[Û|&/Ã͵%¿ƒ7¬12‚Ÿû c°í¡yÛörãÖ-®cEQEQEQ€Òæ%ËWÈÍÛ·%>!yg8pˆ‡ÁݽQ$?~þ¨æ'}¬ ËÉÓg(ãGS‚ŽA$ÖÚçb¾Ö«ÿ@ùòõ+B†UlúÙ‹œ`9tÍì{Ÿ6k¶téÕÁ'ÙÙÙ Ö¸tå +êìÉ7ãŒã'O‘ŽÝ{È€¡Ãžµ`›K'Ç·ïÒ�ÓþM%á:gOðyèkï6ßל¨ßµWªøM¹sïž™kK~jøŽO3`.ÍášÄ‚'Zp``jZ*‡0ò¤ŒúcEQEQEQ¡‚@x#’Z¶ëÀã÷b5"ƒU`Þ×È09~ò}%D‚Q6oI‰8"ÉÚçbüƦ­ÛÖˆ2;i2¥ÕôgX]»ríýˆ~î‹ÕaDªÌž¿€zœÎ�8'n<.Îlsøç ˜㾃Ö¹4c¾ëêõ!�s¤íè‰öñŸ‡acíÕæ×0¿ÉV“Çaz˜"ưåwð€=F<ÎpØè1N, Ác1xdÞ¢Åÿ±wDA‡Ð9:@Wè!]&ìõš•�ˆ=;Ìí¯}³‰ù,Ð ŒAn.óˆüD3“ø“�óöýçù¶€Ü,.�ú¨ª¼–0�Ëg?EÎÇg_A«òOæªÙ.b§ëáû{ûÕìÙ†¾\_çæ³@ï¶,y-àø¹Ö €À®êþ6­ÛÀqø ~›�#€€€€€Û%  §'{g\EÒµÿ¿|†»®» !î®8dcH<¸Ã‚»»,Áwq]XvqMHpMp×u÷åÝó}O¿oM157Ìär�„ïéª_‘–9·çÞ™*ÎÓ§O?í*ó'dËá܃òý·ßË×_|%yÛr$%,Þæøë¯JQ×b yxàwÚ¿+O~úáGùêö—²cý‰ól\,õ*¿ ¾±Õ%lT9‰˜þ_2¨¼ø4«i{”Ia7n\/6 éØ>ÃŒoÃDhüNˆüüÓÏrç¯;Rxø„¬™¿\¶¬þL~ùéAÖ©ŸM×,ž¶À@ö¨éC=âÚ œÿu­–­k6ÊŸü©hå×ܲßøê™ýŸœYQ¼Bj‹wT-ñð©ûHï�B€6)iò¶³«�O>ýý% Wo_ëó²p¯ð§ ò@ü�À°Y¼t©Õñ„>†Q€“ܱk7ñ ‘³fɶíÛåð‘òyëV™:}úÊ—1vÂi™˜\"l¾˜»wí¼çôcœãmXê•{INš- Þ Ôµ=ç!·¯Ý”ßýM‚žu7·®ÞÀߥРî•$¨g¥5§ŒÀZ26½¢]×â·CÄů?ÿ* ß ÒÚã½›Ê?îÜ‘Ã9,Û SVÂ'”•z•^àïB!% p‚ t\»võq´{=rô¨¬\½Z|ƒeÂä)5ô1ŒÀÂE‹Ä/8TΞ;k>ñÇ_ ÄðÂLš8m¨Çm_@ã‹kŸ`ÎøÌ‚Ò%:ã±ÂÆ–•ÐåJÔœF$U’ÙÿÏ®k¼ (Ÿ-_oè;u´@~ûåWq*ÿ²¹­ò/ŠZýï]‘¿ !„”8(Œ;Öd\iÌïuÜÄIh§ðÈ¡�a"7‘ì9sM'Œ<Øá «-ñ­e‡^}¯€@™:c†DÇ'¨)¬A#Y¿aƒÖÿéÆÏ¤E\¼8{z‹ �2Dµ§µko:~ü¸Ìø`–ïâå#þ¡a2täHD$˜^Ñ6‹šƒ—Ӥnh/j °]p@¿Ô^Ú6€’'PˆxÕOD[6 }—Ï^Äï„¿­ X…çïRª „ V| ?3~¼ú?¾»¯¿ìÞ³GóF�SíêÚ]ºÊæ-[$)-ã°•ÑÌE:øð à`ÅÞF¿‰bí^GŒ-]{ö²~¿æc ¶j7n�û·9?Bà ç7Ù�³ÇtÂY©‡q×îÝ*Z/£“»‡=vT÷’¾Ÿ•%[¶mU/TfV?þ‚òúõkê%‚†Ð˜¼ü<¼˜÷\­ÏÛ—/{rr¤ðT¡¬]·Nê¹yÈêµk-}ž ›&sÐ |9MT9ë/'(z_΃–ÎüPP’Cb.øD×P ç\ß~J…€‡�Cz èPEœj?'ÎO?+þiU%tx9‰˜ú_Ô»¢¸¼ü´MçÕ§qM Ϊ ÓþKB‡•¿ÄjâTýym êppmáüÂ3Vl掹º¾þ´v­$á“Ê('ÖëîC°àÌñSòÇïHFTk­ý=·ò÷ßËòY‹Ì‡&5‹ünœªýë¾Ë½(žu$¨W%Ü·{ú×AŸÑ®ùxË¿ !„ ‡ •S§Oiœ={¦Ø¾E§nÝeÇÎ�j›ò­[7µö~ƒÉ¡C‡ÔÖeOÿ@ �j(K–-“óçÏÃñ†8`‡`惘ßëñÇ1ˆXx´~¿ÖÆhÀÍ›7$%£­Z½zõŠÖOècÜSÀćÿÄÉ÷œì… çå]WwùlÓ&]„O,ƒ¿5àÜ[´e˜;„ ¬šûµª¦®­_繇*€ð—}äʹK‚’¿=WEk /„ߺõM¯w~î%\¨ßbpyñð¨«Q¯Â ÊaìXYõ‡ô« >ÍjˆOóê”õ]eTÑÛ´>ÞÊïB!Ä“beþ>|‹"ÛÛuê,í;wÑêŸlØ >ïòåKv&>ˆÅ{�hÔD6mÞlù~-ŒÑ$oïÛ€„D5�ÓgNk}„>†™€0e$wÁÿ±ŒwÍçîýÖq’ÏoÜ–/o}!ÍëGˆs¥W¥gBG��rùÜ%ñ{Òù¾€à÷+"ú‘¶¢´ˆ ûÆÛ/B¡`î[<:Àܱ~¯m;v–!ÃGXº_ c4âöþ§µïÀ½ÿ¦ÐÇ0ËW®Ä¾-©† °—¤!R ®uˆVrHÔ�¾“'U}ü¤I— õçîÝ‹ÏÔíiIN·,زi:r¸?Gk%ñ€.-Ò•,ÿ0J´Y¦S³TA�€`¯€ðo´{øê„‹£×impØÑV!ý+˜;šÖm™Îýa'Ÿ9RPzĵ7DpÌ;SP>œ<ç~|/Ø`ó:ˆ%áSÊ ¼ßÎñö „B(˜ûްÞÂ…÷6l°ìƒX½×VIÉ2xØpK÷k2Æ�`ÿ�ââé-dÏF;¡�aý¨FHž`舑jßɱãÇ Ba#Æ©1QMšÉÞ¼<¹xñ¢Lš: / öÛ[rȯ^»ªN€Ð€ÓfÎTŸyîü95ö£Å‹‘ Éù0×â%À5؃ã ñ�[ 6Íç@ÈÃ?£Ó1@¬G#J~ûÚM zÎmÅÉçP�<ð¡“Êàüz\cë¡æ–l•8[0D‘†>ìÿ‡�³çÞûð½„èzcÿ€ vŽ·_ „BÀÜ·p¬Ð*9À@BAø<: ±â�üh¦>ˆI@,,â3z÷ÍÂVk$/´|¿&c § ÀÉÝã�ó"ô1Œ€ž5¯Uá%Aá‘ꈜԀëÒªÚ9Þäw!„bsßÂq@þ¾}Ò,&N9ò�šGñÆqàšgßÍÛWbZ¶2÷AÌ“â:ø 8Àúýš�1XÈíØµ›J®xåÊeÝ8BÃ(”|!&’Å!‘Ü?îÜ‘v Mz×®gh�v‰’o¿úœÏ‡"àäåP¦WA’9ÓÏ X^íçwªª9§&¶J¶�™ØUP°çÿî„.•_“M+7J�ø÷—0¸6úpdBøïÎ� eûw}ë);Æ›ü.„B(”(!)eåÐïÚ°MPΞ•yãgèÛ^ßÒ·™ \¿tM¶¯Û,Kg,”¼m9*Üü¯?ÿ’ôÈÖ÷P8®H:‡v¬ ûµ¬&Þ Õ±�*ã|ý§žÕÙðkYcUŸwãšâ[Ý[%GÀo·yÕ§‚‚Ö/Z-«æ.UÇ4¢|¶|=ÆÜ�'^ËÞœYQ�†àÓ¸&r"¨6߸êö�7ÿ]!„P „P „8J¨_ñ1++ç,ÕÆG»6�•³—È٧廯¿•?~ÿC.Ÿ½¨ŽŒxÕc– 9¯^¡µ•³>¡¬DÌPçöK@û*È:¯‹³å‘�ûÐvØ©²Ô«ò‚u[@ð­ýœ„=g¿œÈ�•ÒS%müþ›ïäÇïP÷Kí%Nå_¶÷@ƒS¯}/øîÆ•• î•�Á!ãÍ~B!!!!„B(B(B€B!„!„!!„B(B€B€B!„!!!„B€B€B€B!!!!„B€B€B€B!!&Ç�•Õ«—˼yÙ„8’63O2æ’VƒWI³´qÝi†¤}�¯œÝ°Ðvºñ¨Ã¶EL÷Ù¸×O€¨U_RgäJÛyGl:Øþ.ï©öÔi{$¶çk±CçW’ˆí=QÆ>B!„ €Û·oÉ¢%K$1-]|ƒCÄÍÇO"›4•.=zÊ¥K-† „6?Žj+ŠYsæÈÛή2zÜxCŸ«—�¬ùøcÛuRj9xð€Ãm–¦ »*‡7À=Öt¬S¥×•3žDƒ¤±›Ôv×'ܰB_,N|Ò¸ÍpzuínOz¹¡Í¨ p�íŸB!¥ ,,.Z$~Á¡röÜYsÿK€Ë—/Ù¤ à¤Ôsó�9óç«(€ü}ùº~8ü«×®µ]'¥–ýû÷9Ú¦C€ûÿ—ä.ø?¦øÖ~ãí¦IâHåðú¼ÝÐtlÜû 1«ï–í7Š(J`ï€z±ìúUÞ”&mF¨ñá‘� ¶¤Ï> ~NÍ´vÏ—‚±�9øü@Øþ’4n ’ª¤Š)“wJÊÔÝÈG€-j{Bó¶“$qôgˆžPÑ ^¯„ì` DT³ÞÒrà ½ÐfÔ§Ò4eŒ8×xWƒ:æf Ï­Ø2Ìsõy#Rb{ÎUÉ!“'í� ïÖè'„RÚ ÀÂB ²qÉž3×ôÂÌ’qñââå#þ¡a2täH-: ­]{8Ä:Ž?®V:ûôï�ñjkAï¾Yº-8m䘱Ö ‘¸yûJ£æÑ.ÛvlG¿ÚR0jìX oØXmKˆo�(;víÔÍËÃÏ_ÆŒ¯l¸ûúËî={dò´iØÂ Íœ={F9ïÇŽ30G›Ì_¸PÍïâÅ .ã'MÒõÃá_µf�í:)µìÛ—ïp›¥e €Kå”¶¶Ö4\ÞíIw8ÖÅÚ{§¡û ý—Á¾e»iòh$Ô’†Gt´9+öp¬1â¢�€sõw4?sãád7OŸ€-HH¨Úp*ò+Ät›-�ºKãÖÃ$cÎ!åh;ר§sØ! ü3¢aº„GuV'6àZˆ N•ßPã|Þj ¡Á*YaêÔ=ø[νE[†¹ãÀ÷1׺ÖqA?!„�Ò HFöŽ‹›ìÎÙczaÞ¾|Ù““#…§ eíºup¦±º}Ï€NݺKrz†œ,8©ðØ–­%kÀ@­ÐÐaÒ°Y ÉÉÍ•sçÏÉÇë×C<Ѐ¬�ƒ”ó¿k÷nD((GßÉÝCŽ;ªð9;vîÄöuÆú‰“'”�¼üDtýÊá_½Úv�”Zòóó´¿ñœãÙº#F�6³Y8¼Zâ;c†}#QÍÞWcƒ}-ÛO°\9¼/ø£Íªƒ�~­¯¶™Õßí)Oi5d V¹±ò®�oÛÑŽ›Ÿ¹€# uíѧ©ö`ÿd]{ƒ}T{HPšáøÁ°°ö¢?å ¥j�lÒÓ| €u[†¹ûhs'„Rj¡ÀÂBŽ48̨8óã&N*R8uêlëVÜçýkc´¾‡—lݶíîˆM¸pá¼¼ëê.ŸmÚ¤ËWŸ ƒ† Ó ëÖ¯7Ì/!1 Ž˜VÇÜffg[ðÙ ÅÅË[–._®êËV¬PsÝ`¿6ÿÊÕ«l×I©%//OW3¾h`ø¨ÑVl–  "ª‹–õÞŠ3‡3uz®–¥ß 8 °ß E&êÅr°ëU|+øÊé‡ÃŒcýêïñœ¯6ƹÚ;’¾gÃ÷€¨‹÷ºÎ2¬Û2�;!„GB ::ZPÌì°°P@ˆ=œl$ü3¹"V½±eN7œ„ç%`5c`_ÑýXõG?ÎD·! ”cuý[R2Úš ó,�Ш† µ€ˆükI8þœ�ÅK—*9¹9rðàAÉÝ›«êS¦Mׯ`{ÄŠU«l×I©%/o¯¡ Ñ(Fç”U›%>@€[,œA„¾Ãq6�üp±ßê™ú8›Ÿ�°wì³×À~xØj9h¥ª{¿nj/È»®Á„w�^ÐMµz&ÄŠ†± N¼ƒçgêD#,ßFÂøÑŽë´¶Ôi{ÐV$­¯2¬Û¢ð¸B!XX˜!øXµ¼×E«Ç>þC†È¾ýûT8~RZÆ=€Ü½{áÀãÈ3[6²§ yl ûÇõ†£‡�…œ¦Àùóç±]@ Xùo•œb5 ¶+ÀI ¶V|ãZµÑÆÀá_¾b…í:)µäææØl=nœö 9²86"t‰¬!ƒ[V6£Ø§ Bæ“ÆoE’:K×`o;E$Ø3¯9¹V€£ljûÖq¶BÖ­í½.àzDÆ#z@ËWàøù9^˜ž‹h\c 6æ€u[W!„ €å+Wb%޲að½œùät½€„xÑq ZýâÅ‹°‹sðQ·é Ãæú l ÿê7D'ĵnÁÂTm;v’ÁÆc»", gΜÖQXX ¾þòAv¶®}Öœ9jŽ@?¶àoc�”ZrröÙ7tÄP\›%v €k]W8�Hú¦e�·�‰Éø «ÐöbÏ1{Î5ëŽük–6®(QÉч1ŽŸŸãDb I„«ÇBÀ1´[´Eà‘A!ðwNNŽôîÝ[âãã%55U¦L™"?þø£îš;vHÇŽ%66V:uê$[¶l1ˆÚíÕ«—ÄÅÅIûöíeûöíºþììl™4i’a>'NT}�ea¡€ù̬~ÊY:b$öÜcß>V౪¯ñ‚‚åèâ´ì_ÆÑ�.žÞ:à£Å‹•Ã{äèQuÚ�ðG ®ùx-ì`¿üÿp}' LÑèGRA]@Ì+ªI3Ù›—§…IS§‰«·/Bù- ¿÷ D$’ ZNŸ>¥«øø~:¨k?|ø°8¹{Êô™3U=$2JÞï›…ïÎf�”NöìqøïW"8òH˜‡•tìC·z]H`ª1©œñ4£‡ìñv;Ø ºŠ¿s ãÞõò¯ ôßp’¢ {þqowïu�î8}H|W*Ü;ÚZ´›,NÍs,àÔD8Ô¯ö¶Öfn‹!„” (tëÖMNž<)¿ýö›|ûí·2yòd�£~ìØ1åÐ#GÆÀWi×®�ÎΙ3g$11Qrsså×_U¾ƒ#GŽhcîܹ#ýû÷—M›6imø{À€ªïq,,4à¤#´>(KÀÕkWÕñ�©mÛ¡nY8uª@G÷^½qo†v€Hl/Àß“¦LWoi''N3Ô1†”>vïÞéh›%N€S�£èàìµ¾{Û zÄÛ¼6¾ïb¬(Ûp65´}ó-ÚOµËÁÆj5öä£=yÂ6‰é1ù”ݤq›U{lïùî¾'s‡>œ€£÷  4^› Æ”@Ý—µXµce÷Ù¸òà8Dœv ³Ñ¤Íp56¶×|‰jÚ[' ¶Ã€G!„P¸té’®ÿûï¿—ääd­ýСCwAD®ÎÎ�!C$??_7æÜ¹s’™™i°�,6ü�¶Ç¾°P(@©ƒ€-±‡èD,Z²¤X@aáIB4víÚáh›%N€Sh¶×½iÊ[Çìi«ÉfQpÂCƒÒív°qŽ=N&ˆë½@�ퟞ}gú#¤v±²oã¾^V6Æ ùÎÇÇß!)šó_ í^E�<¸oœz�4~‹Úöàñ¼Ÿá»B”Ã?÷ûoGfDAXµEà‘B!þþûï{ŽIJJ’ŸþY×�ú]c  n &&Æ`ŽçÎ�¥k×®J|`a¡ð�øäÓO•pùò%‡Øƒ�€£qä`q€‚‚„hìܹÝá6í!„BÀl BûMäÀö+aÿÈ9СCIÀÂBà�\ùûöa»€Úçߨy4Žt˜ýAC‡I‡.]µºUàäÉã„hìØ±Ýá6ÿ›½;ðˆÿŽã8þG 3›0¥¥¶ýô0:vàl ±¦k£ÜÖuM¬E µîî§Nì–(@€œòžÏqø…úýº;÷õëñâÁÏùøÀ÷ÙÝ}àu€÷ù@.—ë}GÀKët:±¸¸777qyyÙûÒÁÛÛÛ0F Ý@�¾¡ÿÓ/&bzî›tÇÿZÀ�]__ÇÄäT”+•éóú}ppð×Ч¼ŽP­V_üÀf³Ùû¼«ÕêýŸûûûÞk…B!úK¯---¥[Þy7@º9 ÛíÆ˜ ¤³F£6R ¯"¤¥+ýRxöÀòù|,,,Äüü|úwïv�þVWWcmm-ž.Ý8�^3€bq=jµ³¨×«#Õê?éœ €0Ι ìî–âèè0E€‘€t­`¹\€qÌÒÛ³·¶~Mié/µ0Té\¥óÕlÖ`Ü3€ôpV.—ÒÛ´a¨Êåߟ>ü €`f €™ f€€`&€`&€`&�}€™€™€™�}õz-vvJQ,®C–¤s™Î§f& ãá{û·899Žvû2åôô¸w>�ºf& ¢Rù#Ú틸»»ƒLº¸8�JeG3±¹ùKt»Ýxxx€LJç3�SÌLÀÆÆÏ2ɼtN@3ÌL3@x||Ì4€áÌÀL¸ºú/ ?þS³sñÉgŸÇäÌl|·œ‹V«5Öù/§gb»T@0–¿ÏÇW_îïÇYõ,þ><ŒVV¢ÓùWøXfÀÄäTìîí=óCãfÿ³wÀQ]ÿÛ/o½¸…@-¶‚% î$¸»wK�RÜ�MBŠÛw¯Ü‚[öâ.}þû=“¹“eÙ°1ÂóÌ|¦{Ï=÷î-$3|?÷H"†@ íá£FÇz‘ŒèÝ·/Š—-§„A�_úàÂ…óÚù)Ó‚Q³^}x*¢ú >QQ×µó>ÅŠcÔØ±(W±2¼‹Ç?Û¶I»ê3%8UkÖFÁÂEQ»ACìÞ³[{®ö�»¨6¹oùJ•±jÍšøB(!„B(†à�Y³�ß³ Útè„ðíÛßyQÇ®ÝЪ5Ž?†ˆˆÓ¨Û°1úôë¯�ß¹{¶…‡ãÄÉj*�kA,]¾ÜLÈ=dzÁ–­[qýz¤j1f ü«Vú pòÔIlùs«ÈMÔoܳçÎŮݻØ«7Š”,-×R B!„�ø@À0Ü@ ìmÚ"Ÿ‡šµl��›7kçd1@i?|ä°™4(Q¶¼Õ/A0fü3°rÕ*³>M…¾‡oa‘¶LÁ Ï!"€ B!„ †¡0Ý{öR…öœùóU›¼±—ã^Þ2b@�óÂÑcGÔ«7ü«T•b_úËB‚± €í;¶«{\»vÍ& #侤 „B! €€a(4 †êuêEê;T¡~ùò¥wö•!ù2ï¿ß Ajþ~Ä™Eð^ oþ¥ —û&¶ø÷ß IÖPB!$Y@À0²¨_­z ÔçóçÏ«9ýËV¬°ègM´z¿8}ú´*è׬[G@’ B!„ †¡¸zõŠºÿ¿%K°ÿÀEØŒ™²R¿Ìó×úÉ‚ÅJ—5I€å8{ö,öìÝcb¯:wüøq%B¦‡áܹ³˜5w.<} ¿W]ƒP¦BEµà¹óçÔ‚+W.SXB(!„B> ÿ^Ú²e ºwïOOOäÈ‘_}õ2f̈œ9s¢T©R8p <¨ú2Œ ¡8söŒº_¡juµÕžo±jå}o‹‚¡#Fª­ø¤_ÕZu0-$T;?cÖl/S…K”’5dÅ›€¬ø/ß_Æ¿" )&ß-r�ÀB@!„òI€õë×£@�øì³ÏlâçŸÆýû÷Á0VB�  )B!„PÈBÉAAARÔÇ ???0 ! „B¡ ´(îeÈ“&M0uêT,[¶ K–,AXX €’%Kâ›o¾Á† À0„P|B!„`åÊ•f…ªT©Ð»wo<|ø±åñãÇjäÃPPB�Ì!„BÀ«W¯`0ÌÀìÙ³Á0 ¡HAB!„`ëÖ­fÅ¿ ùOŒDEE¡oß¾ðòòB¦L™ðÅ_ÀÎÎeÊ”ÁäÉ“ñôéSk×iÏÒ¬Y3¦?—H` †IæIö`Ê÷zÜËiD� ºò}niô0�=kZœ+lïŠÉƒÆãáý�ü16Øê}Jüä…ãBp`û>Ü¿{wnÞÆÎ-áh^®¾œÿϸzþ2¬Dž1Ök=ÓçÂÀڽѺHc9NqB¡èÚµ«™8}ú4šÐÐP)Ôå~VùñDZk×®XÀ—_~‰Ô©SÇzŸ6mÚXÝʰ_¿~2�ÁêµiÓ¦ÅÚµkÁ0ñdÆŒPÎb’u^¿~-?§1hî[Kû/D#�Z[¡l0uÈoxôà!$NŸ‹UTÉ_�=ÆëW¯qâÀQ,›±›–®Ã“GO Òñ×ÿTȳ͛4Ó‚�“Í…G¥l(7ê;x:ÿݦÃo-Fa^ÏðΔWÚR„B(Ê—/¯Ä‰Qü¿³ÐΓ'�Œ0kÿî»ïpøða+ÀF¬H‹àà`³>"$òåË'ÿ�fíß~û-Nœ8†¡ˆË–-Fdä50Lr͵kWåç” ÷´Ì Å”¶àšZû>TÎWyƒß´T4*^3V ×ΚŠŠyJšµ—rôAÔ•H<ú ¥¼ãõŒ­KfÃèVé$®_¾fSßm3Â?äkx{~¯µUÖ—V‚¤s™Vrœ’ „B`¶ç‘"E��\¿~] jí~òö~áÂ…Ú ÂgÏž¡W¯^rNC†ãËÛzk@†þ/^¼‡R‹^¸põë×7ëÓ­[7ÄÌ­[·dí|ÕªUqïÞ=íü�`oo¯�¯U«† =z‹Í“"K~Ñ“„ÈÏ¥ü|ÊÏ)€BÞú«â¶iÁ:çj¸ûiŸ-€íŒí5 ’εZÇë‡5K�?Cþß®éœááô³Eû¤6ã0+pº9N1B¡ðððÐ a$$´i1Á€€³~Û¶m³*†Ž·#"!kÖ¬Z???ÄÌ AƒÌÞðß¿ogÒ¤IZŸôéÓ+ Á0ñàØ±£ò†U†Y'+Y¾|É[Å?À„#1¿÷,™ën¥OÂÀ¯-‚´iÉ]X#À§ž%õ]«ÉqŠ�B€¿¿¿VgÏž=A…pÑ¢EÍî%S/ß•“'OJ ™« )]º´ÖGF1ÄLõêÕÍžcôèÑ´jÕÊì{¸ C@±Z ŸÕÑ1‹ÿ8pÕ`Ä9ÓñZdzwÑîj¢·�šú_Ôõ¹§�®6 €’i]0ó=ºi0"ÊhÄÓçqÙõðNm~�‰9ôê;dÔ©çºýŒ]²h÷„Oæ|¦¢v×U…y’ €SgCP¦n²ÅgVS<ÍGÊZ@ €~5zÊ1!„’R€Å�|jß899i÷‘=–5™dE~­¯Œˆ«¨R¥ŠÖGVø��N'íq"<< C@€Õ7ô:#¦ÿ WøâŸ ¸a4ªöáöz‹âÕÏun—³rèñ›‰ΪM®µIH‘¿ÃÉ€å¦{M5õ‘ï>ê¢î�¹?ê-€´‹(ØâhÀ¦¾™þ[*­Ö ܪIQ+‹&™(íä£à‹8zJvøÏÀ‹ç/pæØ)õ,wnÜÂÞv¡S�–²v�M@î03»‡š>«k!„�” dø½Y!\£F Ä7ŽŽŽÚ}d»?+‘©™f E‹‰*\\\â,6oÞ †¡° !uß*Ð+¥×á²Áˆ[F#üÒiçÔ[~é¿ðGÜcô÷Lí¢ÞÎ˹v™uñš ÷!ßéf)d€ÕkýÚ+àçX4I€×ë­†¤]åf6]Ó®Œú×ÏhÆÂÁ_cÛ©,Ú¯ Nï½ç�𽈼t [VlÄ¢à¹Ø¼l½¶»ÁôQSlýjôP^EìÜä˜BI@Šñ¼yóšÃãÇ�Oð€9rXÝììÙ³fß7xðàD%J”0[d�a(l‚×9ú£²ë-FÈ4�ÛF#Š¥±¼W•ô:ÕÙO†x¯°Ät­ô/›ÎRÔ�E ¨Õ+º uM0ºÇHf޵ùš°ÞßbûÌÏl¦°�ã{ïéöŽ…û¼³äÅ¡�ûÕ<Ç:Þ•lÝʵ5&„BHJ’5kÖX¼oÙ²¥ZM?¶œ?^Šùw.¾'Ì™3ïJûöíÍúíÙ³'1€³{ìß¿ C@ItÐ,“ÎbHþ%ƒQæí[]àšÁ(Ólº…t:5üÿoGƒZ‡àzô´¡¼é\\À˜¦C¥ ••í]t®ÙJׇw€Gz£ÖžôSl§cõ�ˆ¨°E´*ÒHýyÕÊ[AŽ !„� ¬¯ |ýõ×j¾ÀÀ@„„„`ÕªU꿲í^®\¹TŸºuëÆ,Þeoíú4iÒÈ6€2ç_[½_v H•*•ÙÖƒòo†D²¡ìû¯�Ï–-æÍ›‡—/_j}ä;ïܹƒÃ‡«Ï C@‰³h-LEºÖvE |K`v~¯ @”uD(ÌûQ�É9ôa¯Ç6'C¼ÀÈÆƒTAë™>g¢ €º>•ñôñSD]‰D)GiK– vÁŠ�È"…qyRž „B Ãõƒ‚‚â^ ou5§Åì=M”u)„›‘7ðøá#Ôôð—¶d+µïɸÞ#l]ʶI©S!„PhY½z5rçÎm³ðòòÂ� ‰!´7ðÖpvvVoß%I!$S§NÕ ýØÃ$µ�_ÂÿBH¢ ¿tj@µ(_ÁÔ1öÁ·Sý¥P7ÛòÏ#µ¶;ÇØ>pRtñÞ&³ùýÏè�J¸¾µàf‡ø�è=§½’®T¢_»|8uøÞ¼~�¶•šJÛ.d!ÂÂö®íµ<+àîíÿ¯DEy}ì©þ¼ gU÷#„BR¢ÐFlذ�;w†››ìííÕÛó¬Y³ªEõd§)®###a-2 ¿OŸ>ª† ÔÛ;;;”/_^M#xþü9$I)$òŒ}ûö…··72gάžCþ+#ªU«†‰'âÒ¥K`˜"†a‚¾}{œ�$TȰý0SQ?(›^¶Ù“-÷-2é,æùoŒ.Òe¸þèìzŒ1±ÛYµ!8Æt¡{V�j?©3`Î�ztŠÞ»Zô÷Êv~Cíõ1שã%jç­¨ Ú¶Å›Yœ+d—_Š}�5 V@rtïá˜íÚü~)´ÿ^³’³'"äœÝê¶ûà aÑê�\½p[WnÄ‚)³°sK¸šë÷êå+´òoló.!'aF·à¾ !„ †a(Æ"ë 8]€s1à?d€ÕÅþdÓã'5ŒçôFl2]ß6³ewóÔãºQõ“iÚˆ�ñÙõê;£Lçv:ÔTƒ®Yuñ^rcqßùÑh Å9™»oK¼2å†zæt¼/‹§/�¾q¦¨½#Ê9þ¯kkyUÄâÐùˆ8z ÷îÜÅ‹ç/p1â¼ÚÐÏXLúØ$ eɯdIßêArL!„|:€a †¡Ð¦|ÔÈN‹úÌ…w¦¼ü‡•u -X¯@þ9B¡`†€a(>>ê¹VQ…mË c¶S88Äh×aJ» ˜ ·4þ9B¡`†€a(>>¤ �Ù=!�&™>ë¥í“¦dç J¸euÒÚjäöS’¤SéVrL!„P0 CÀ0'Í}ë«7À§ž²HÑï÷û·(?þ[H­í"€ÉmÇc^¯™ðá4 B! ÃP0 ÀÇ> à÷–£Ñнú§[ügqBÙ¡©ÕÛÿ"Uì´vÏô¹0¨Î/hS¬©B! ÃP0 ÀÇ�kêO|k»Ô.(˜…+ÛÉçóçC!„P0 @˶íáZÐgÏ�³8<= ­Ú€a˜/!„B †¡(àå�&-ZâÍ›7 C@!„BÀ0)Uô<¾ÅKbùÊU C@!„BÀ0)ULœ2 /FÑRepïÞ=«`ö¼ù¨×¨ ¼ EÉòþ÷Ûïf£Š”,�IÓ‚á_¥|ŠG·=±wß~´îÐ>ÅJ r�ZØ·ÿ€ÖÿéÓ§4l¸ºWñ²å”ˆxüø1† ‰ „B¡` )䥸ï7h°Uqæ,ŽŸ<‰[·n㯶©µ¶þõ—v^F 9 /]Âå+WP¸d)øU®Š5ë×ãþƒèýk?%$’À^¿ MÇNˆºqwïÞE£fÍ1dÄH0 @A!„BÀ0’'O©õ:lÓ)ا…N7ÿl ׎»ö@× žÚqøŽÈçá…ÇOžàöíÛêóµÈHíü’åËQÊÏ C�„B!„P0 €dø¨Ñ¨^§^½ze!®GE¡ßÀA¨T½¦ûRÀ˵VÀÈ1cѹ{ v,; È52ÍàÀÁCòY„ƒF~Ï‚ †¡Hb!„B(†àÑ£G(YÎ3fÏ12E@æê�3V y)âen¼À©Ó§U±ÿìÙ30̇€{æ|¨P£ZLÙŽ63¡r½þVûÎí�ší~Gã¡+Ñ*dÆmA�®!(’§B¼¿¿éÈu¨4C>ô¸¦1 þ/sQºx@’üø8—@í.Áh1iZN݉z½f£h¾Êýóï¯HÞŠ¨Ó-ÍÆlR×4¸%}Øô}eÿ�½³’âÚÂðÓ¸»»{p²¸»,îîîîîƒ@Üww‡‡FqwI‚³çíWIO5M�ܽÌÂç¯:Ó}ûêÌVÿÿ=çÜœµùNaR¸|×Pe åBZ¹_ôÏúûnQ‡Ey›9wÛÍÏJ®ì5¥|§o¥æûK¥ÚйR®ý—’;w]IqûK¦mZ”·Xk‹1Ù®uå~Sƒö�ví×Ùh<shþûLqÇËR¼î0É›¿ÑµDpÕTP(T“§N#ÑŸtéÞÓü;ñûIÈ!0{î<‰e(T˜7¾Œ5ZHb‰�=škW­�ò®W¥@ñ6Rã�E `¥^C¾´fI]R¸ù,Ý|´­Ò›—Ä¿^vG¯–,)‹GÜ6¤5õƒ©…ÿWì>V µü?Ý%î¹1û‚Ä‹;s”#s•Àµ|…›A´å­g²YÍA†—òB [Ì»«5@j�Z%YÓ•öï“åúñýàÊ”hð¶Ä×IášäÎU'd{©ïOéÔ‘@}”ñ3ˆ&u”hðŽIÿ,¾ï¿‹ò¶sî&–¬-ÏT4‹ïŠÄ× •zŽ—*¦Ó/«6MËÛ­µù˜l×Úø}©Øã+Xª½Å:›�Ç~Í~Ÿô­\‡¯¤úÛ %Õ=¯+ùUS@¡¸–€„„®ã–öíßÏgùò›oåøñ2füI—1É á_Ö\ydÖœ¹$ ”ß6o–Í[¶H,A¡ä¿uûÙÈÄkW«ÑäůLË�$ã+ØùÒÊî6Ä6Åí/^t=ÍCiyQ– ÝÆD¶K~ëób^>%g¶êR¾ó·�ˆ²Ô¹œ°ØÜý¿í©6xv"™à tàz‰úo3¯’5M©$ÏõUê=Ij�\!qÏçºh ™{H}ŠÛÜëb¿~™^/L¿é›¤º÷ÍÀõT÷½Iß"Øñ Ú^ñz‘›Båºx†¹ÅWëG’%u Óþ™}ß-~3öåíçܱÜyëS�”nù!ß ÷÷ˆº¬Ú4-o¿Öæc²]kG€ˆÛ/ì×È~ÍŸ_+Èu)P¢­’_5ŠkIÛ¶o—”éã.Êðý˜±„p\ ´ïÜEZ´ig%œ9sF.ù‹Äãq %Ê”“Ï¿üJŠX:uíæ¸vU‡àRîvOªK4nïµF­L$™ÏEöÂüx†Db<œöØ�Âxž]iv¦(s¹f<¸ôº¯órŸþé,6sé ú2žço"‘-®¼ûºõú®Ð�z%ãËù.)Ÿ5mé�»½™Sã¾”jö�dx1�•€+4»¤6ý³ø¾[ÔaPÞrÎÝ’�’*ý¦zw‘íÛ4/o¿ÖæcòŸw[À¾=‹ñXÌ¡Åï³B×ï¥Ú�9ˆ›J€Õb]P(TP(—]€ðûÙeä¹W:•½3¬¥»ë)ÊGbÖ„ˆ—Ù*ý§ñÂiônîºþ@›�ݳ´�¤ã^Lñ¶¼x?{™ç÷`î;ažü4ÜsB³]?Èõúc-Óêc_±©ñÞIópZ‰{!·…€°R™çq»¶êŸÅ÷Ý ›òöcÂ2§ˆêÈßÊ{ϦMÓò¶km5&¯Ù ÖíY�Çb­~Ÿ9ÜËž¡¢`5 Š+>épƒ,üèa-ÓO&ËKrÊ;_‘"•z ÏåÉ× â€’ ßå’_A>!Áìˆáþ΋«QÒ½üñ-ëùFˆ�ÇM¾hµ¾’êÞ7.vM<w{/¹&îÝ!Ï·}Æ&¡YÙvŸóÏ7Ï‹»_?p…fß7æ¶hå^BéŸÌœä9 ÁñÅN½Æó•zNp]³_¿Be;s‚àû,ý®ÜwÊ%×™?žË�§Ÿ­È$ϧ},΢± Ø� +P¢]P±È¶MóòökíS¬ V㱘C›ß'žHÜC€Œ2¹TS@¡P¨ P¨`aÑ'3E«ö�³‹Ä3¸¡µéÌ[¨).ª_8;SÄ£’EÛ(ã>í?Ÿ'CÈ 1Èd&¿h'>Ó›E èÄÖó\àå–ÄeUÌ ÑÕ%/È\'áW�â­ÉœO½\§ß—ô%{ÆŠÜ# `xÀ|È-’T!€�°Ëùl¿~$ÌÜ!‚°ÛëÍ9bNÜ¢„†PˆqÝZ@°¡d<·è_ŒöcŠÕ(´�gHÁ’턵`WqŒð’Tw¿nѦYyûµ6SÄ8tÒ®ðeÛ|J.ÆfÑžýx çÐæ÷IBCP§üµhj*(*( (ç¶ ]¾'K}’Úå“DX†Ïq„•/éÎöVyáz¾"Íýv¾ÈÖÍË,Çî‘AŸ#ð|Ë뾞þÉLB²=HAÚGßr߃´ÿ½+š+bÀdj}°’xÜ`÷   O̯ýúá¢Ì}ÊI.F[5G,<.˜¿@›dïø5}urX Nû92Uæ³EÿbA°“k˜ç!Ω8up‚N’>‹6 Ê[¬µÝ˜ì×�!±d£÷ åxì²ü,ÝÁb�íÇc8‡6¿Ovÿ±âZ%¾j*(*( ˆõe×Ò¡&;=Ä’lÚ./«Î1v&ÆËlõaó½;Sô�]0vÔ½¡d.ç^à¥6Ñþ.²þ.Έ ¾^Åë ®§y0uä€Áà@x€¹€ýú‘Iœ�O'ò’-}Y)ßñk¼$¼G â1Ág[€ue–qyN.0î_löcrÅè3ßÝXc¿øpù™¶iYÞb­-Æd³Ö~^E�uþ†�¿Ã¤=‹ñØÏ¡Åï³`éŽnqSíš5  …æpYö x–],>'‹±O›ÁŒ¸y¿ÌûŽÛ{ÙÖŸò’o$dz£È_ã¬ÑßwGb^06ÆÑ ê†KR¯Š=Æ™×m±~�<È�NÁî(ĨpÅîÌaÀŠÕìÇg\È#ªß9†ŒP ÷uóþŘ`1&'¼ƒ6 «A>âqbѦmyóµ¶“ý¼»-K𒉀ù™´g1û9´ù}Zå>ÆTMµßŸ/…{O¬ùÇKdËþ%(TP(Th”ï^éRþŽp–¬§8;c¸ý–k÷Ÿ“ÅØéª:h¦äÊQËÏ8’ìÒáSã5À8!í¼l› ¯rÎÎv_'žÞÿ…Þ^p{àºë;&î¹Z¬ŸÑ¹çä\àsÆW ð9cm"jÉ“~ëYïN«yÿbJ°“ÛK%ˆÐBÞ ÜÀùî[¶i_Þ­­Æu€>RW‘ʽLÖÙb<öshóût„>«© €¢T¢Ð{ìÏ3rúÜy™¼j»Ô1_b*( 012í[“PS#‘ñ³�×H]d‰±åźtóQBóáÊoP¸™p/g¶ê¾/ßiI€$†Ôá“ ‘lÞÜ3£°X¿‚¥:P� ßû¶!œN€§†�‡Eÿb@°ŸsòS°Óë»ÌoÀ '±oÓ¾¼w­-Çd?ï¹G2iÏb<öshñûäDîÇ=m„¨©°ÿØIéúíJInÐæÁã§$ÖpæÜ)ÔkŠ„ÂÚm‡¤ü�Y’«ëDÁ®Tسg��©©©]s@Þ�%KªâÞ])²êã:nx€½ÑÚdw<Åm/†/_°‰óâŽh@Æm2bó‘ÀK;a¸8{E’‚ñLÆW DE`Î�#Ý;|õåd('Ç�Û+a€œ6ëG|2®ÅÞØoÈK©¦#í †¿!°;UÁ¦1 ØÏ¹ã‘By×®-ëÎwßq·jÓ¬¼ÅZ[ŒÉf�¨×/ Yô« ›ÇoŽ3ô-Ú³�źÍ4 `jO~[SS`öúÝRvÐÌ),9`º ›¼^|0óGa§™{eÏ”E?í•h¢ZiØlÙ´ë¨xqîB‚|½è·°d$$Z÷ïV èôÕ ¡ÿy»O’ø¾Ó¤îÈ2aå6IHH7h“¶×o?,ÑBÓ� v9±óÐB@$Pà …B=8ÂË 긙“PÎ}b áu2`W8“$V¼ ?J¼*×Ébï±—,F[dêvŽì£?ìÐãÊ˵;SÜó9Ùù'i™C€ÙÑâÇë1^€¬û‰uöÎÇÇÝ——~,sŠxo_7p< ¢"`_·Ç;}¼”“‡€0D ˆ½»l ®·xÝa|NòúÅWï'Ü+Ûösa¥šŒ„´ FW-€ö« 3ïŸù÷ý²üfÌËÛϹÛ¿úðBXÉ0Yk’óQo…ncø>˜Î£Uyóµ¶“íZãšOyrk8má=Äù›‘ùꢧ ÓñØÏ¡Åï¡”¿Q;PM=j½7O …¿ì9æK.«½3W’¿í=.ÉýÂ/Vo9H?"&°+7�±Ë· (Ѻ ,à.�wAç¯W u pxAÛ ›÷�ŽðáåFÍúQ6î<¢€ ±…B€Ô¤Š(&ÔÉ(�êÞ7„ÄW¼ó¢Ï‘_œ£�+~®ì5�xÉj$ñc§›ØuúÂ9GháÊžþ©Ì”ù{·"Iô8§Üý|`· BíJ7Å1`dÈg¼¼Ô#*%†qž /ØÄgO$[# þœ÷Í1†~;‚x°.|Nòúqyár]¤b÷1”G, ÿ×mF8vdzÃ{ϤÖßwûߌyyû9wÏcz)^w(;ÖÍ©D Jlë%«y4+o±Öc²\k~g$êc|ä áï C8Ð ó±hÏd<öshñûDÌáG=*V‹šÀ®:¤ðýé›|ï�žõ“D '¶«ÿÁBñbÜŠm2tÒzÙ°ãHĶÇ÷«åÄɳ:~µBÜØsäO¡¼üPäúBŸ®z,ÿõ€,ýe¿Tˆ1(š@-|@8ƒŒC†p�¶ÔÔÔÔ®¬9 ³½U>jm¨©@Ü{î¿Ýü½¤·ÑèEòóî£m,K$±Óoo¶&°Œ§×«%Ξ¿@x„D ×W3ðjø¯ 0.Ö:f¡€B¡P@·e‹+÷ ™bbüjjjj¸üWì>–„„Nè‚ZÔL“C9\çŠ?òÇi)7x–$DH,ÃY( ¿V(³jóAkàã9?ËŠß‚“÷ê@ÜðÏrðÄuB 5Þ�'”-ÚgªàA�ˆ’¯Çd©þî\™»a·8 ¼‚ü‘îÀ:qJª¾='�›�ŒÿïNÝ(„3\þ&–1õåOìßâŸ÷IÛÏ— áôkÍÖCr…¡I)°äÄ… $–¡P@xI®:hîõÅÒoO}©î}3&Ư¦¦¦F^þn(Þ&êm©©0yõ�™´þ¢kÃ'¯O¶síiâk#œ¿� „\ðáQdˇüC|!ì„;…€6ê�\ À•‘s÷‰¹÷í9 È3°eßq'¯bB˜þ‡¯;O·I¬ÞÒpÔ ‚‹I_zè+‰ ù\3±¿Š+(Œ?^ž}öY™2eŠ€�7JÉ’%åñÇ—[n¹E²eË&«W¯‘–ãÆ�“¸¸8¹ë®»¤hÑ¢²cÇqаaCÉ‘#‡lÞ¼YÂ!{öìÒ®];I*7Μ9òÚùóç¥sçβmÛ6¹Ü8uê”´iÓFžxâ ¹þúëå±Ç“5j�U^¢ ûqÙãøñãR¸pa¾+òÈ#�ÈèÑ£�çÈ;Ž›o¾™ïl4ƨ€ FFnžÍ•«6Ÿ!ý$$ŽX“hÅŒ©©éî?ùÈ›Bî�h·§¦À§Ï±3Ì3$Z@û/—“|O’d燈ž¨@,¿Áؽbƒ³³¦lÔ³ö_í€ Íš5ÃíZ·ì÷Þ{/â2GŽ‘þóŸ²|ùrq£víÚ—ÁW_}UæÌ™c% 8PR¥J%7Ýt“<øàƒx'r äÏŸ_þñ�\d„,x¯mݺR‰Wƒž4h�¼öÚk¸®KÚ´ieýúõØ•®U«mA\¥Zµj¸¹K0°;ݶm[ <1š4i‚H"·ß~»äÊ•K~ú駈Æ®¿îq!¸ôë×OÒ¤IÃuyê©§dÒ¤I‰2ô•ëÔóÊ+¯ÈC=ÄóâvôYvïC† dñâÅâ jÕªòŸÿüGþýïÓ&¿ÿþ»éyÇá"^»pý 7G*Ø›ššššššš �Vv¬qïþÝ*ç<þä  N?É„˜$y¸öGâß©§`Ï)üvï‹÷›ždRM‚>®•8C€ÐP R¥JÒ§O \üÿõ¯AF#.³víZHµœ8qBÜ€”¥K—NÜȘ1£|÷ÝwVí­X±BvïÞ� 9„S~øác7‰lß¾½<ÿüó2cÆ Ù»w/×î船sç&§¡ ’>}z©S§ŽÈ#˜)R¤ˆ¬\¹2¹EŒ!沊pAXÂBø1†é¯{\ˆ „lÌ�;WvîÜIœ=í8bB ,ƒ~:tˆ¬%χ oXºt©YðýÎ×wND0"ÕÇOž‘ó×_aè,’*’c@¨ðå—_Bh¤{÷î ­[·–×_�Ä}FeBy@\½9R§NMyÈ[’€íÛ·K•*U oÔEù$ «V­b7ZΞ=+^ÌŸ?Ÿú!’#Ü‘�\ùDî½÷^À%É€„ÄÄC”q�Ç­›Ýc€ÝcŸŸðÁq‡Œ�{6 ÿBŠ) ,aÇèàÔƒ»|DnôÌ…÷ˆE’?Âàìç(¼à� óþª ¦¦¦¦¦¦¦f+\Í€q@èëâveáôƒ> I�BsàníëbÎN)Éæ¦N�*LËp äÕ}Î;g»óÍ7âFÞ¼y G0ˆ�Ÿï.ßµkW¼ x®ùåýû÷Cø|džk>ñ÷cÇŽ �Ô�öƒ ¸ãßvÛmòõ×_‡£»¿6ÀáÇÙ='á]D€SÞëª'­Zµò Ösä&Ožl´vaú{ jjjjjjjj*€-ûŽstgù˕¼�{H‚([öŸH7}… M›6½„XïÚµ‹ÝfiÔ¨ Ôƒ�•!ÁÈ‘#!°R¦L2Ê#ˆ„Ìž=;¬àm ÃÍr©>|8žä�o¼ñ¢q}ôÑGôE~ûí7Hœï5/Á,W®'/Î9óì¼úŽ'Ãý÷ß/cÆŒ�TrŒaÐ\ ¸›ãº�ðñóÏ?c�{r¸ ,!$ÄÝŸdxÌ<üƒ÷×Hœnðä“O²“ÎØH42 ò^xáY³f âˆôêÕ‹öˆ—÷lçÈé™ùñˆÀûÄ`íÂô÷šÔÔÔÔÔÔÔÔTpâï+ ›M.‚+Öözö­… Í›7ÇÄ ˆ6dÇk\7) ÈÄü&ï&YÈÖNÒ¹p€o{;€ÈðÀÈÝwßMì8dÓMŽÉ-€G„Ÿ£ôp÷½æ&‘¸ÁC0üqç¸8ˆ~€°²cüôÓOó<"† 2Dü@&}ê�tRöŽ;î ®KŠÊktý[‰V$«¦>¨æFfQ¥-€÷ """ú8øvvŠî2Q×½ù³’–e«¹1|âJ-Ï,€÷ """ú8xlÄtÍ[_`€^û|®šsÖhÖš|ýSì·ð4ˆ��Õ[l¡7ß|3ª{ÓƒA½þúëJKKkÒ¶ˆˆˆˆþòÕz(~ªŒ㧪UÏQª¨©Ws`qZ‘Vçd€ï€-Zh¿ýöÓé§ŸÕ ´´T|°õߤmý|5c½>Ÿ¶N†ým…ïèÿu‘É ñÀûÉϽÿ½¤�¾·À>·v7goü×c–ë¦ãdØ”ÿÂòÞÞ_K$J*kÕ÷»…¶ó�ZõHÔ ýÇZ˜#ðq`…õ¶Ûn«‘#GÚ,­[·ÎÓ€€ ŽŸªìâJ9%UV„ê¹ÿ›%¯¹sèD+tUUÛ`ÿ þ“aVÚžþ¶ž?¤PoñV¢ÞµT_ÎX¯G‡OÛ`8áEàýµD>Ïî—�;uE®êƒ�*,«á¥‡~>þøc{²®ÆÆFrÈ!êם߯€�ÿ§¦¦Zp ÌÌL{íµ—^yåuÔQÚu×]uà 7hÒ¤Iºîºë´Ûn»éøã�WRR’£¿©S§þynÿþýuÞyçÙqëC‰‰‰!m="""bt+øCžÛÿmG€’ŠZEƒÔür=õÑŒˆE³íP`Ç­6"´wàÑlï¯%òyŽãy¥Õú—@ЩS'uéÒEF×®]uÁüOÀî»ï®‡zH«V­Òš5k´çž{êÈ#�´ AÅÅźãŽ;¬([ÔÛ¹111JNN¶þÔ¹sgí³Ï>N8Úz0DDDÄ(ŸM[«O§®uûbúo˾›�µ—ôõý~aÄ"8vÜ +tÃ>57›ëÓ'×ù< ì¼{ßMÒ„%Yj6ÊÇTUUi§�vÒ?ü ã§Ÿ~rÑnëç:vì( þ`Ô¨Q²öåååaç¹3gΔµÍÎÎv´õbˆˆˆˆÑ ºÅNÙàÓîdžO‹ÊSóÄùéú(i•‹‚Þ€O®¥ ¬Z¯1O6sÃο}ð­È*•O!øî»ï´Í6ÛÈÖýçææjýúõ²÷¼óÎ;M<öØcjß¾½þ`éÒ¥²ö………‘ëÓÚÚw8Úz1DDDDï€Ì¢JYŽ®¿¹¥Uòš‘“ViÔ‚ ù?ðÿµXðÆ—ód}Ø=ô)wÝu—Á!^qÅM."""|ž²FáHH^-+"m‰€×¼öÅ\-H)ôoàÿkq, (¯®—õaK|@}}½öØc{û¿ãxBB‚¶Új+üYhÛtù?°—ëÅÅÅmÊÀ“q """zÄ|�¬ô …c]n™¬ˆìòády‰mÓ×¶×håªõ7ö'ûî59ÕÔ½ šÑµÜ:h¼–¦«¶!¨IK³;9ø €±cÇʦû—””8Žm·ÝvŠ��—a/Ê{ôÑGeËŒ+¯¼R¦ÜÓ§O×ÓO?íÀƒql¾"""‘!6u�´,[¶U�‰V8Æ�_áøü½ÑËdûÉÛçæmƒ'x5À¦©‡ìu?va†l/|+žœ›¶±½óûïß1d¢FÍO—øþZz~³@vO[öHTǾcdÿ·@‡ØÿÛ´i£pX¡Ü¢E ï¾û®vÙeÙîuuuZ²d‰Î:ë,í¸ãŽ:å”SÔ»woí·ß~Ñštˆˆˆˆ>€ €À[‘ €€1‚@€ˆˆˆèÃzpœJO‰¾ù…Æ}3JUU2z<ò²£ýÃcdX�6ml²¾ˆýX£¾øQVþòË/z°Ý}›ì÷¸ëòT]Y- %lL?~ü�*Ë+Ô ê±›ºº\ô‹ûæj<~ŸûöÇjhL?}òÜH]°×© ÍND$ ‡gïz¼žŽ×û݇èÌ�ÿO»Ó®‘aOðï½ú{Z¿ÑBÍÎM¯6§\å8~õ‘*7#[VŒ]}Ä}ïnÇëÅûžÔy{�ìhý±—È‚„U‹W¸¾¦®Wí¯þ]vsu®]GêšÕ×Õë¶‹Ú;~—çíy’‹ÀEÿ.ÚG¾oîÇãÔWãs?žã®‘…_�]Û…b¡Ù‰ˆ@àОú[tïù·„�Fýg;g¡ö�ø|/¡OkÃ;wÊ,ÙL‚³v=ÞÕ5õºowMŠÛÊÕ¹1×ß!ãÞo‡|ÖçÉ7d<}ÇÃဦëßE{÷Íeÿ¦ÿÆç~<ïv¤„§‡Yv ˆˆÔÝb§¨}Ÿ12ŸN˜©”ürm®TÖ6¨kìÿ–ῇ†ÄôÕ§/$Øzèðmš x9æÇ2€HOȳR3•Ÿ�gÿ�z`ÓÅ�ÏiòÙuÇ\,ÃÖ–‡š¬wí]Ü7÷ýûm|îÇsÿ…·ÉB°ÛÏìv ˆˆÔ· ¯@U�j‚5?]Ýã¦hseÂ’, ›°Ò÷¿eøï!Øœùö®:nc‹?…™ÉµW[†0'…0”™¹af:v˜™™™ÌX ³)fº_÷¬•îVeÌöÜsîÑjôôf$µIÞ�7o$$ò]˜^Í„å5M8e¯à¶ÙŒs f©m JØÚ×WI[o;·T»ÓªýZõ¾–%ÿ¶i­þ¾j2#D1£]iÛû¨àÀþ°·Ž‚W­Ú›VxI |6Áéc-0Ï`Ó¢µ ¾}ëãLíšU~ ›®1y c~¬_ÀõéÚr)Nø_¸¢|�½Àk ñ àÑuÿq|ÙöQÿbößMÜAŸøxšWzƼ7T ’’’YR  I)è6éŠ+Æmùç¯GéÚïÜ�…ã¶ßsý]ž ÇçsN �ã~R¨Ž3ì^\Ñ–,Y‚Ç{ ŽŽŽxT°WBB4$''cܸq BÎABB äy»ê(ØR[Á“¥mf5“MðïROa;íàTÅ„E5L pA½·‰•XðMyDªvîv êk•ùKÙ#@õ{ÉÁl#�Ÿ½öÌ5àM»¦\{�K§/p·�tm¶-ÛÈB€ZÁ@¦j³=_€°[¡¸v5(Ãë§=‰{Qwukl[¾ sFOÃö›hƒ””Œï3Zп€½Àwô_@Ç'>ž%½æaõÀeêïìfåHJJJJ ü~Ú;`À…¸Äd5„„G3¥Åüž_ÎuFj:AùWóœ) äÕ»Ô¡~8NŽ÷LpDÑ:tè€Ê•+ãå—_Æ£bìØ±hݺ54DEE¡F�8t('•. )LP�Ö3ò Ðo(–L€‡éó•-¶cªØÏ}*:€íS«Ù¶/¨n±g&}©« B=ÿ¬œ>°Ô±'(t¬×*WÎÂÚ²DfUýÿ‰óža%wC}ôx«2Æ~ZΆ›�þ ÷•�ëÚÉFeí2õ—”˜„ó�Íð:‹×¬O�Ù¦›³ø!E Bð/dÿ¨ß-»þ ÖøÄÇ3æ½!àÿ -+¿&ƒIIÉlR ;ýðÙlË ­ËÙ(jXqâÎ…D¢8ÂýüMÌÞÖ¸z뺪b�ç…[âïR\î‡ã¥Håû^á°?ýôÓXµj˜põêUq@B"O!kxÚYvëó ÅŒWmí¸L€vLë×µûññ hÿ‹N £¤¤¤¤ú®ôÂïþ¡`p6vóo(JøõJ(|/ß V‹&îø~Wþ~þÔ´b{½–{оKá÷ÆkdvúéµÌj!ÔöõàŒ=ÓOkÖ¬‰©S§ÂåË—Ç´iÓШQ#”(Qvvv8pàˆÎ�;S4°a`` íàááñðþÑ£Gó>”*U ï½÷œ��Ñ®];”.]Š¢ÀÅŸœ`äÈ‘°··§=Z´hoooÃcšnÈÿZTzU ‚””””~¦ý[ƒçÜ òA<ò�wîcàjflfγ�°pa¹ìg3äé³¾�Øîã�oæ»@CrJ*÷Õ×-çxwêú@lB’Ø}ñ÷¦;çyÞqüEt|ïÁ{ÓŽ^à‹/¾`à¬c›6mòC`Ú?›m‰!C†°Þ€á1qi… œùoÛ¶-$$ŠƒP_¥[Z·ò[QÓÄ},«aâ ?:–þÛÇe8óg¦ýÿ£í¬ƒ‚fÿØðû0èÁ/môú›W~™AÙCîß´‹¨Y·kÁ×\sï{‚�¯zMÇ÷ -šVz‘{µƒ¸rn�±iáìÛ°“û´ƒð:æN1 Ï’û÷ÇÇÆ±‚?ö¬Û��«¶°p’“’)ZÐF'D†E0Õ‹'Ì¥=MóÇÍð/`/ðÝDÇSpÇ'þu¢A'Š…QHLLDÙ²eYýÖX³f žxâ Î3l;::¢aÆ9!0pgß6E‰æÍ›cèС†‚} 0M›6eF$$Šƒ@¾¦rlÜìšÌ5›qÑÁŒ]ut/cñÁ%§ì„(f¼UÊÖç$KÜÀ¦½QÙç±môFLþB?ÓεûFШüógî³÷É×ü·®QŸ»üŸ½7€ŽéÜÞÿ €�T  !ÐH#"ø ( �+ ”^@Šª@¯_[—â¢h €¢W!(@€ìÿ}ÞϬ33É$F%yžµ>ëvæœóΙÃÜe?ïÞ{c,Ûÿ¿cûì¹só6šʸO‡a2ÎKu�\¥¡kéT_ZÕ“íë·"pD )·ï•N�­�΃€�eúbalܽuGlÛ+ý[tOÅú©8?un©Zÿ½¿¿TœPØ F˜ŒÌ€�’hhéরpÏ;Ù5ßp$©ëÖ„ïÞxï¿ËÈTeP솓òýÏÆ&g|Æëôn|¶1}›7oV»ä¨»×׃$gΜŸ¢`{É’%è#€2¼—&BC?OOO9v옺—É“'c=¤ð[e|ûí·jZ¾ã�;w„¢Ò‰ð^ƒIߌ\!~Ž•ñš�L‡Ö°mÕf©\ƒBh\¹óX¦Ôó/càÆý'bk-ÞvF6½œ €¿ÿ»ì8u =Ôî~ÄŒ­ª^2Uðç‹WéÒ@éÎo9uKú4Ðñ?,,LL:jîSl?zôH‚‚‚” P½zu¤ï§É@ýtt´¸¸¸¨kåĉYc<}úT� Š¢ðvhëÝL?ÝkwÀkB2îòeïY²4:^|ìB2 -*6RXÿ iX‡BhDÎÛ!‰·‰)�¿‘¤ëÎnK!m2i“ÁN5vvñÙg¯?�gÏ_ÚÞÈ`ßeæ~‘°Iað˜>¾þ„úŒ“‰wmõ,mjœ¸tç£Ä�Àû¨£G�J®\¹$))I(ŠÀÛ£[­v*êê߯ É qåÜ^3åëaKÄ?U%0„B`û_iâ¢ÚÌØ*q[}ÍÝtJu�ÇqÐvæ�¶Ê@©�ѬûÍÇ.c½ ž×ºdqv¾þüýö³~’�GÅze¬ïrêò=µÆ…ß“,ÎÑÿnß[?K³ëcZÁ¾ß~—®s·ëÞ‹üßñ‡OŸK2ÂxBœ�ïAà}ÔÀ�¥E‹BQ4Þ~ÀݧJ‡jáxMH¦À×¾‚ÄDŒ�OëuNÅõ„B€¢^‹ <@�{L‡Òî߃Àû&L8(Z´¨|÷ÝwBQ4l³jËõ áß}B¡@e<%üž¤Æ îúõº¤'í<}]š}þƒ$Ü|(¶ Š¢@!„B€ÊB-}§ÙÛä—Ä»éê~OZw¿4(Š B!„Р(4,ÿíaIÂ}ÞNz&6 Š¢@!„B€¢(E€B!„EÑ @Q4!„BhP Š¢hB!„Р(•E€B!„Eј?¾|ðÁ#oC%K–”åË—‹)½|ùRÆ�'—.]’w¡/^¨ï¶{÷nI‹Ö¬Y#AAAò¾éõë×ò矾ó54h ž+È’%‹ú3ïСƒ$&&Zõç¼dÉ‰ŽŽ–”êðáÊ{¤�FüÝ>’ÖçKäœ]Ò}Þ>i;l™Ô­Òô­¬]§r˜Dü#^ºLÛ"=âJÇñ«$°V{£ójW •O³H€g÷õ� !„B€¢h„„„HÑ¢EÅËËËæÀýû÷ÕñM›6¥+`ÕªUR«V-yß4vìX©W¯Þ;_@¿~ýäòåËröìYõç U«VEpž¢?güÙ¸»»Ë¢E‹$¥züø±8::Ê–-[h¤�ÚI�ùTpÞ²÷liÑs¦2z.<"ùµIÓÚa-‡«À=òË=Òªß\ ï>]º}±C½×0¸—I ÃØo¥Y‡“Ô(Yç¦B!„Р(ÔräÈ!‹/V�òùóçmjè)]Øynß¾½ˆN4FŽ)ú:wîœzÖ/^””hÅŠRªT)dX}uëÖ¥�Zò¹K§Ï7HÏøCà¬{ßÏ¥Ž2�àS |ªÖ®ëÕLT@?î;©^Ä[÷~õ¢ÞÒuÆ�Êp¨V¨Š‘Ð$b´­¿7!„BhP aØ_½z¥‚±)S¦ˆ¾ìííe̘1R¦L)P €ÏÚ ¤ûãýõWiÞ¼9Rúñ^²À�;wÐ;ÀÈTÑýäÞÃßÓiÓ¦e _HÛ®`²ø9–ÁùAº?‚îZe�ŽÕ(QÇЯ­&bÐu}5ÇÊFǼ xŠê50té»6!„B€¢h`WÁ%‚Dhýúõ¶‹x__�=Ân4L�• źº� ÃõD”дqãFuíÇåúõëê¿DS\\œ”(QB œ“+W.Ô‡›,Hîú{÷î©ã+W®””ÊÒ³ÀzØ©†1  Á1vÞ£¢¢Ì>ãýû÷ã>À[¾§”ë09` ¤äó¬2p�Fž®…é€kðg‹û¨Ï·Â0ZÓÊ´¿ÉûXG¿·€fj >\R%ö@`n¾ÀÔä“ÏÖ½ïç\[ºµ_ìí†-×vñ­ÁûÑ+ߥ@!„EÿÃÂÂÄ„€£ÞÜ¢€:{¤™;;;kãíLÛÜ@==vÏ1ZAª———ÄÆÆìÈ#8Ä.8ƶjÕ 8>/ÙëìâZ'''e‚T¨PAuÏ·,ËÏŸ ƒ@}×ÀÀ@m|]Jòdï Mƒ‚‚ð]0úåʼÁù… ’N�:aŠƒ€É5ߺ¡GÁüùó“5Ðìãõ›Wâ9#³"³B‹ÈøÉ’’)-{Ū Ûß­¾Ñ1ßâ¾êX«~_š<9{ŽcG_3RŒŸK\‹F�¶6!„B€¢hd&!ˆE™Ãû+ê³Ï>“ªU«ª2k4wî\*©üóe €jê‡þÃŒŽ5 风}äׯà}û¨ãGÿ€6Ñ Õ9¡MÿaÕç"ÈÇuÈ$ @!„Р(*…’d# @J…&‡ÈÞ@æ@êDÁ¥Óç¤çÂÃ&Çýa*@�*MŒz @Ä?âñš!„B€¢¨ÌfPF¢L#¥Ú±cJLPZA Ô©Šq|¨éWMý»OCã?ÔׯÞÒàÜ��±ó�¦~0þz/ïaœ Ñ¸¿ðÈ©¢úŒøZšwž,Qñþa:`| B!„EQ™Õ ˜�””$Ö= i£–{‰ˆŠCௌ€¶Ã–½9Öï¯Ýþÿ i æøëC6‚w†…¼¤YûñòÉÄ5jô_—i›¥iûñxÇiB!4(Š¢`Q B!„E€¢(„B!4(ŠEQ4!„b+hPE€¢hB!„Р(ŠEѰ !„B Š¢@Q B!„E #‹¢hB!„Р(óçÏ—>ø@bbb$½‹¢hB!„Ð=z´ôíÛW(ŠÀ ‘¢E‹Š———PE€B!¶‚@åÊ•¥@�òìÙ3ÑWïÞ½Õ¦dBB‚¼ uèÐAf̘!z¢(÷ïß—9rÈâÅ‹ÕîüùóBQ B!„ØS¦LQqÇ÷ß/š^¿~-%K–???y[ªU«–¬Y³FôDQ4V¬X¡~l¯^½’R¥J©¤¾ìííe̘1R¦LåÔâéé)EŠ‘õë×ë>/**JÊ—//...²`Á¡¨te„‡‡K�=êÙ³§‘ë ""BöîÝ+»ví’—/_ „KÅŠåðáÃrçÎY·n~´:)<þ8 ·oßV&2 .\¸`°vdd¤ìرC®\¹"Ý»w—Â… +3‚¢hB!„dÌü±äÍ›�½.Ïš5«Ü¸qC ýÌ”*k‰gÏž•bÅŠÉÓ§OBÐ#ëà=Ä2ƒ–'Ož¨ØäáÇ¢ Á=âMmÛ¶•Y³f äîhlrbƒT]ûŸÿü±� ø4h P·nÝ¿¨óŽ?.¹rå’G� E¥ ? üðÖ®]+œ-üeG0®¤ã}}%%%©¿ì;wîMøhÀ½{÷$[¶l²uëVý/vúñ2»öþýûÕ×®]Š¢@!„’1 €eË–©÷óÍ7ºàA¶)5nÜXæÎ�«Ûdœ0a‚@ØXtpp�ˆ&dÔ«WONŸ>��EƒXq2 4Á,@„ÍÇœ9sêb�_~ùEíúkBÖ@Æ q­Êl¾uë–nMdHŸ;wN(*]¨‰Éž=;êþ•Û†végÏžmÑÀ®?~°üñ‡IeHÕÁq=Á�CÃA³kÃxÀ/^Š¢@!„’1 욣¸yóæØÕG `6�~ܸqj×ýîÝ»ÈPÿ ­ZµJE_‹-B†3b µù¨éæÍ›ˆ{´lf™(@I - ÙèZÈ”ÆçážÝÜÜ Àæ(E¥  cÇŽø±Q¿~}KÊpRmLHû‡€} 2 Ë¢hB!„dh@‹E�UGÃAÀ²(„B!Þ (Êö€Í„ÆÞ�=*E€!„BhP•A €M›6éfmRTº B!„–EQ4�¦�™h~�:ÔÒtéÒE(*]‰!„B Ë¢(è„éïï/vvvR¦LÌøWcß3Q B!„E€¢(„B!4(ŠEQ4!„bkhPE€¢hB!„Р(ŠEÑ „B¡@Q4hP B!„¯_¿–#FHáÂ…¥råÊòã�? EÑ (ŠÀ;€B!4ªT©"|ð�+nkíܹSÿ¿ÿþ»P Š¢h¼#!„BàèÑ£*øÏ•+— 0@l­‰'J÷îÝ…¢2½0þ|õ㋉‰‘¿[/_¾”qãÆÉ¥K—„¢hB!„dL ÿþâââ"T;óþù§˜Òž={¤fÍšâèè¨R÷·mÛ&Phh¨,Y²D4!½kAÁÁÁÒ¡Cqvv–J•*ÉôéÓÅÎÎNŠ/.+V”3f´jÕ*©V­š888¨sׯ_o—|þùçê3q]dd¤@¸Ï¨¨()_¾¼ºÿ ˆ)Y^ßø_¼xaamËkQV‰@HHˆ-ZT¼¼¼äïÖýû÷¥dÉ’²iÓ&¡(„B!Ï@ ‹ äÈ‘ºL€Õ«W›¬Û/Q¢„lذA^½z%×®]“G� T¡BÙ±c‡hjÛ¶­Ìš5K wwwä?~üXîÝ»'P�:uäßÿþ·èëÖ­[êøü!½{÷–€€ÑÔ·o_iß¾½:ŽÏ¾sçŽ@ݺuSföãÇ�#ƒA»'(eëߣŵ-¯EY!¸säÈ!‹/V?¼óçÏ EQ4!„b+h ØGìqúôiùj¼I“&ò¦ž?.ùòå“1cÆÈÓ§O Œ�¼yóJbb¢hòóó“µkת`=gΜråÊÑׇ~(‡¶xOXB6r‘"ETp®/|^þüùŒëî£@�rîÜ9Ñ”’õ ïÑúµµµ(«E`ÅŠØqW K•*%S¦L}ÙÛÛ«\™2eÔ_Àƒ ´yóf©^½ºäÎ�Ù*…G~(={öDªŒ:'+))I4!}gêÔ©R£F ü ±¶rõ4á½Ý»wë~3gÎT B�¶ƒôŸ“'O EÑ „BHú„@Ó¦Ma�-[6“ úм»ýNNN²nÝ:�nÞ¼)Ù³gWiúšŠ+&'Nœ�«W¯bƒÇ Œ„¬Y³ª]|}-[¶Le”.]ZÅ(ºtû�>úÈdJ?b777}ôc�”¬o|�–×¶¸e•h„‡‡K�=BÐþ¦“¹öîÝ+»víÂ_R¤�(ÇmüøñÈPé)Û·oM­[·–† ÊåË—•ƒåïï/½zõÒ_©-HÙ�ë…fHB°odŒ5J<<P B!„¤h îÿö¿xñ¢è 7ô!H×Ü‘Ž�÷0*0Ož<ˆE+(3q �… ª]qhùòåFÁ;¢Ì@_C‡•N�:aml\ªfhŽ8p)úº8DÛ€ÄkÄOûöíÓõ2@L¥)Eëߣŵ-¯EY!kÖ¬Qîvñ±»~ᕊ2{öl‹€¶3— ñ—T²´�,Y²³k⇫ÿšpäÈõHÙ¡(„BI÷Ð@i¯Éúuñˆ :$š�€råB… !+X×(ñAãÆ�0#°ÇAÕ!B6J�õµhÑ"u¾¾PV\«V-ÕŒ¯U«VªÔxË–-¢ Ùøl”+ׯ_YÐÚû(�Fvåõ3¡S¼¾‰{´°¶¥µ(+D cÇŽø‘�¿àÉjlÚµkÓ<µyžöM9aVpÁð>Ö¢(„BI‡Ð (êï7àša†$ºÿëkéÒ¥ØuGí¾%À(¥�:ÒQ�‚ƒ¬‚ï¿ÿ>Íêƒðþ?ü E€B!$Р(èâ��{ÔÐè <ê]âããÍÁ1gÎ4ß@éRUôëºj¢áºp¢ÄàîÝ»rêÔ)Œø°Ú€0{ÓÅÅE5ÄÈB¤¿<{öL(Š!„BH  @Q4Ðñ?,,LL©Y³f¨í7k PG—Œâ€Y€±¨ÇÑ„ú4ª@gKÔåxyyIlllª 4ÜÀˆAggg5³víÚÊP („B! @Q4(Š¢ðB!„EÑ (5󕕯J–“3îžò»§§qó�™ÅËœãcWNft�,Ÿø¶Äë÷_û 2¾õpéYç¼Îp¬ž’Câ†äMûZ„B Š¢hP €¸’åä~yOÙYÆCÆ+'“œÊÉ "îçt«ÕNþ=öÿIÇê-ðú=Â]b#§È×C‹Ÿce¼—îiY¥¤Ô+î¢þû›ÏrÊÜ�ùÔ»8KX¹S·.!„B€¢(Eàl9O¹ø?jä3}¼Z~Y/_öš%Þù”1ð^Ñ´\�2'|ܯÓ1xÖn²~fvÙ:/«ô ,&_�Ï%_ô³“èf…dÇ‚,²ttnë×%„BhPE€¢høüìþïpõÀk“`×vçšxý^2çÓ²4zÌ ¼N×|ìì,±}ídÏ’d÷b…ìZ”E&uµ—:N®Ö¯I!„Р(ŠEѨö—ð“`Vä?å_×¢Þ¯ßKºú·U&E;ïæV]×/¤ˆŒmW0Yü˼ÓïƒTÿÿ7!—2@üмòQ)—÷ì¹B!48 ÆŠC¿ýö›ü÷¿ÿŠ¢@QÔ{gL/®jÿMRÛN�#þ…ªÈ¿Ç®” mFf)# §æ•�ØveUðÿeT>ñµw“qí Êð–ʰÉó³B!„@LLŒtëÖM(ŠEQé¾ ºQ¸7r­kò8v™±Û\'¼¨ 6DÙKèW¹¤FEÃnõÕ ”W&B¨[}¼N–zí «ukT6\Ç? „z߯fI£kÆ´¢îµNQ¼¶=Ö?«YõyN‰·00�Ï/ÃA!„Rð?øàiÛ¶­*THŠ/.7oÞs –:ˆ³³³TªTI^¼x!«V­’jÕª‰ƒƒƒzýúõ¢)))I"##¥lÙ²ŠR¥JÉgŸ}&P‰%äÌ™3…††Ê’%KDÓˆ#dàÀ�íÙ³GjÖ¬)ŽŽŽR¹reÙ¶m›P €¿]E`\«aÕÞfw›?•;ß*µÁeí¦EÓ>ßßÝY­U¿‹áŽwà ™•G¼ ¸]ó�†½ Í ›cûçY·˜tô+n«ç—a!„BiùÓ§O—Î�;ËëׯŜÜÝÝeÆŒòøñc¹wïž@·nÝRÿýÇHïÞ½% @ ¬ãïï/“&M’çÏŸ«ã>>>²råJõßY³f•§OŸ T¡BÙ±c‡h‚!1kÖ,µŒ‚ 6È«W¯äÚµkòèÑ#¡(»(ŠÀ´ÎŸ!¨¶Ø]¿zi•VŽ€³Á`{-ý=Í|<ÖNB¾È£ÒÖñÚ§hµ›^¯S!“ç÷¨ÓQÝk«Ê�ßEÛ>Û?¿ !„óæÍ“ä„p ½¨”÷°b8–f|ŠºbÇZ×°.hD~i89ŸÙ€z`ð§ï²À¦ÏÃöÏ�B¡€Z|777Ñׯ�Å××÷Ÿó»@ƒ ’aÆ Ô½{w‰ŽŽMçÏŸÇ¿ÓÕÆY\\œ´k×N ƒ*ó@Ó“'OpOè`°ù†{Ì•+—ÿÌ'­+‡© ºWý.Æ�æÊ•VÁeƒÁ°«lð^ð¤|â]ÐMwnЇþ2·×LÒ¯SŒŸ¿ši/ÁŸåÃÿ¢¾Þì¹qýæÈâÌ÷c­¶'ÙçG!„И0a‚Ñ?üû¼V­Zª9`«V­ðov•Þ¡Ñ_×®]¥`Á‚*f@,дiS�°û/êüñïiüÛ“P6€©ÐäɓտÝ1¡±z PF4ÂÃÃ¥G�õìÙSk ¡ûáG1~üx•püøqÏw a gïÞ½²k×.]] ºsâGˆva óàÂ… ×bdºqÂ�C OáÂ…h[µFŸ>}0Þ�>Ô�ßÕÕUwïÞ•öíÛ#¨6iŒ5JýÈ·nÝ*7nÜPï£Û(„z C‡¡ (šƒ fÿgðÖ ËÏÀð~™@Ôp¨(ß�þ—|Þq¼Áûjw{‚�„Äæ‘j% äa÷Á&ºàkïõ¬ó‰2V�Y©õHèV�®õX)ìæÎ (ì¥Ö>¯ß9Ö>›bùùe<!„ÐøûEQ4Pë‚-„ù™FxBHuÁkãÀÕ²€uô…u²eˆÀÚ � v¹£¢¢Ì^»ÿ~|>‚îT¯Ñ¼ys˜5CXóáÇ5F{ ËÆE „"0Fl`˜}™Æ `=˜ðÍÈâçX9Õkøª"ñýçÊÒèx«wèë}R,šØáµÅ€m«6Ãkbåó#„BÒ Š¢°fÍìdcw;ÞØIW;ê³gÏHÛǼL4 Dº}j ” û&2 ô…4z¬kæZZj{ª×@:O³fÍôS†´€Û  >rä¾§J2%ŒéÒ¥‹”+WŸ�5PŽ�bå– €;wî$û hÐ0G[ïf*¸î^»CêkÑKÖT™Ýjµ³úÚúÝU½Os�øÝåËÞ³”¹àc§2ˆUÏ�BI#4(Š@ÇŽ\Q¿~}ÑÒßQ3sA¯•Rö¼�¬2djoRdX¿†Uvþñ>²"LŽßCÝ?úàz\‹žÖ¨)BS’7„ÏÅsEŠ? €T‹‚ê%ƒâ$®ÿñ±+—ª5†„õ—èоVïþ£n¾ÑœÜØÏÁì9-*6REÿ xM¬|~„BHš @Q4°Óíàà ºÿëkéÒ¥j'³2ßšé!ÕºjÆÄÄ`G²jï±&úè+ ]˜ 642P^`NmÛ¶•Ö­[Ë›š8q¢T¬XQ k íùS4vîdwõo›ªë«å÷LUs¾Z�ÅUúº¿ Ón>wÕ\ðëaKÄ_+Q )~~„BHZ¡@Q4ÐÝ;ÏF#-0#gΜªCæÓ§OeΜ9H¿W%Ó¦MCÉ€.]}É’%è!€¨f m&§§§'Fià3Ð]Á,jÛSüZ^#m„�...ªÏÆ#âÜgÏžá>`>àY¨çµhÑ"Œ10ÐX(£0¥Ã‡ÃDÀŒRdT¨ÔÿØØX¬ÓÅzÀôóÏÄ¢€,€/ºO•ÕÂñú�4¼€„|‘G¼íMwÐ÷µ¯ 1#äÓz�ñšXùü!„�4C€¢h ãXX˜˜fÔÕ#¨ÄN·“““2*T¨`Ðù�ó‚‚‚„bDÒóͨÝ�ŽŽV6Î T�0”Òà×òi7ÐñA¼³³³nÌà©S§‚!‚ç€q ˜;ŠIúÌŒÄ<SBgÿ:uê «?F¢,Ó ÐÌÐZÀìóϼ¢ í¶ãßÕ]�EuÏïâhý½ËÏ�BI;4(ŠEeTÑ „BQР(EÑ „B¡@Q4(Š¢@!„›BàܹsªÄý¼R¢éÓ§«éeÖê·ß~Cß­´¯o{Q Š¢@!„B oß¾jüµ•Bß.41OÓú Ò²eK±±(ŠEÑ „B¡*Ë–-ÛÈòúk×®±‘(ŠEÑÈøB!„@ÕªUÅÛÛ[MÒ²»wïŠ)•/_^Z´h¡qLÄêܹ³nЦ`EEE©s0)lÁ‚¢©D‰ræÌÑ´xñbõ™®®®jš˜»»»Åõ1å«`Á‚j:˜›››DFF EÑ (4¬„B!4ªT©"S§N•=z˜Íxõê•äÎ�[¾úê+¹~ýºìÛ·Ï`Dv·nÝT`þâÅ 9~ü¸äÊ•K�ÊÆøð¬Y³ÊÓ§OÂ?Fp߸qC÷sçÎÅÈïd×ïׯŸým{Q Š¢@!„’ÁK°‹�ÀÝT#¾k×®aW^·ãÿòåKÉž=»\¹rEÕîü­[·Â9 PëŸ={VŠ/.š°ë¿gÏÑ„Þø}:Êd›40Vuÿ¨ÝÇ=àóÑ—@[C¿LãC`ˆXsL_h@øå—_ÊÂwĵHñ§`[Ñ „B¡@Q4°Ãîàà ºÿëkéÒ¥j‡Mô ˜˜5SSê÷qüÍÚ÷€€:thš €›7oª÷øá« KÒ7Ž= ÃÀ`hذ¡Ù5Ð ÷ƒÖƒÚ¶mkrfèĉ¥bÅŠYkh €A!„B€¢h ›=v¡Q×®¯HΜ9uó’%KÐ'eº€Mê<==娱cêüÉ“'#HEÍzš  ]\\TŸŒ)ĹϞ={+‚ksæÌQß}Ñ¢E’'OÝèŠc(u@YÄ´iÓP&�t}‹ÇLéðáÃÊl6l²TVBll,>F‹õ€É?Š!„BˆhP tü SB ®Õó£)_PP‚NŒ¿C꿪ÿ�ŽŽVA:‚×ÀÀ@àBoÃ@Ǥè;;;ëÆ ž:uê­þÛÉÉI *$�:u’ˆˆÝª‘€ã0B*T¨€ �Y:ûשS]ýÑŸe˜„€Æ‰Öfÿ<2›hB!„ÐÀÈñ¾}ûʻʌQ>m­~ûí7lÚl}Ë¢hPT B!„:t�3fHZ•�� ˆ[Œôâ²VØlDÖ0”Úõµû£2¥hP B!„µjÕRSÍÒ*ŒDÇ1K •eË–‰mdy}íþ¨Œ'E CC!„hFþé§ŸJÉ’%U¹/‚ÛÓ§O‹9íÙ³GjÖ¬)ŽŽŽR¹reÕˆBY®~òªU«Pn‹Fç(%6(±ÅÔ¯^½zI•*UÄÎÎ%ƪ´ý½ ,ˆûPeÑ‘‘bJåË——-Zà^UynçÎ�u%½(É�ŠŠÂ9ªDzÁ‚¢©D‰ræÌÑ„ìU«VWWWUFíîînq} ÷GeÑ (B!„ÐøöÛoU¿+ô$[¾|¹'ŽfÛ¦„ Aô† 0BMǸc¢—ZãáÇ¢ SÌÐäýÊz÷î­¦”iB =oÞ<ÕÀSÍŠ)¢ëåÕ¯_?‹=Åð¹¹sç–¯¾úJ®_¿.ûöí3è×Õ­[7˜¿xñBŽ?.¹råÂ=â>Ð|\÷ݰÃÍÄñ½æÎ� #"Ùõµû£2žhP € !„Bhlܸ.šÞ%Û ÙØ3fŒ�I€Œ4Ù6'÷~~~Z�ÞËjÔ¨¡+hÒ¤‰ÌŸ?_Ì ×á´ÿ—/_ªI`hÜ�˜˜¨vça>@8�¿Ï�;'gÏž•âÅ‹‹&ìú#›AzàXZ_ÿþ¨Œ'E CC!„È,Ù²eSF@xx¸š fN;wîÄô-•ò¿nÝ:��Þ� ^_ØaÇô­Ò¥K«rLú‚®^½ªÆŸãs5+VLW>P©R%Ù´i“Åœ£éòåËШ£ìÁ;Òó HJJ’-[¶èj÷oÞ¼‰k�% ßøƆÅõõï�Ê�¢@Q42>„Ba@ºè|`РAbI†‘Â�ôz¤ñÇÆÆJ›6m ² |}}ÿ÷Ù¿ „õ† ¦ àË–-+šÞ,@O€_ýUÌ Æ‚þøtŒçF�!�¿yóæbJqqqÒ®];�°>L|M�7–E‹Y\_ÿþ¨Œ'E CC!„ØÍFêûÂ… Õ?ãÑÑÑfGà]ºtI¥Ç;vLòäɃ:ø±§ ¨‡Š×8ÆšêÒæÑg ((H4�:uJõ€p>êïQ»� S?~¼Ú­×´bÅ iР�@{÷yó¢n_×4bÄ„~E‹…a Ë@�¿}ûv‹ëß•‘D€¢hdh!„Bà»ï¾///Ì#(nݺµÙ€É“'«i… ]ã¾Í›7« >$$D “'Oª±€höתU+L P)øÐ„ T£>ÈTùÌí>ÌÍòŸ:uªhš4i’Áz¨å/UªJT‚z»ÿñññ¢é§Ÿ~OOOÜ#ÆþÁø€¹ay}ãû£2¾hP B!„�ŒR@¡I z 'EÑ („B!42¨0ò/88XþQ4Pƒ”˜˜I‚S†ûEƒŒ´£?Pd­P“ƒÎœH5zSH1ªW¯žØJH�BÚE€B!„@úFÞ¸qC 3gΨr�mÛ¶Éß!ŠjgPW‚ZœLe`lj…Rc`lIíڵьƒ@¦ ë!„B M}||Ô44(üöÛoåoEàþýûj$ÅâÅ‹UP}þüùLc>|XÚ·oŸ*�9ìííѽ”@Æ Ôvò–¹13åáƒ$�MŸoñ|ï|î2îÓaròÐ yúø©Ü½uGŽî=$û�–š…*éÎ;¸}¯$§cû[s¯„B¡@Q40fA%v²Ñ½rÊ”)¢iúôéºcš6lØ ùóç—gÏžéF]Œ9nÞÇ®8.£€#0Ê”)£æXVªTIJ”(¡ à1þ£zõêj„FñâÅeðàÁøLƒ¹Ÿ'NDçOݰ ¼7f̵~�äàÁƒ)º7ŒèÀH ­“(îc6� Ñ¿‹ÖÅt$E×Rsš{`Ô‰¦‹/ª{¿råŠ@ŽŽŽ2zôhuï¸Ç-Z 5Aø.øÎè$j`x{{‹³³3®ÅüPÓæñãÇÒ³gOõñ=`T$%% dáYQ4¬" XU™71V%=(áÌùd »r²ñ›uݼö»¬[ñoY³ô;9ÿëY¹žxkêÎ�Øo”,‹]`’~hË¿7ZsÏ„B¡@Q4ÂÃÃ¥G�!pôóóM˜¡‰`U?HD@‰¹�šz÷î­ì Fp©2 .\¸ š(+VT;îwîÜ‘uëÖð'Nœ�C‡ɵk×díÚµ¨¯×�øÐæzâ3öìÙ#wïÞE@ldDDD¨9œ»ví‚a�â{ÓærÂ|À NÓ0ðÉø˜]»vMµ€{ïÓ§�ª:{ö¬,XP\]]aÌà»"CÁº�ÃàêÕ«ê{´mÛVœœœTàa{ölÑ+îîîž‘šŽ´qµc!3 K–,ÚkMHáGcA-@FPŠsÌð‰‰‰Ò¥K)W®TÓ°ñ;ÜVÉß›¡F�%Y³fÅ1” ¤Ø€úöí«Êž?žf`À€Ò¬Y3Ñ„I8 æz`Ç?::;ú8†„<@€@¿�"2¶]Ádñs,cõÚÉ="ÐÜñ3Òô†wŽ(îó¹V\G!„E©ü�¨_¿¾hBZ>ÈS§N©@·S§N¢ ©õ8†Z{} 2DÕ¦CH5·À#õ꨹G°‹@õïZ€�´mÜ ù{3JÚµkŸŸbàÁƒHÃGÿ„¿Å€i�çwôèQ|g•Ùa,éÕðqr•z� Iðx;iôEi4'·O°“:Í‹Š·ƒÎIËFç–=K>H–ºN®oݘ?i¶@­|ãuª9°m¯@a?Jé5„B¡@Q4°[íàà ºÿëkéÒ¥Ø WõãšêÖ­+ãÆ�SÁ'šjB�:Î}³^> eúçà:S¼© ;ÚZ€�Ìœ‹ë­0’¿7 B¦ÖG}Š è_ÿú—*§èÞ½»¾€F}H÷™€g�4$„�ŒŽï¿ÿ>4ä�È/õ.(u# K½ö…%xb> �Ë%õ»:âÛ“Fàûe« . q“çÈñýGäñ£Çrñl‚|3…Ô)î“ìg„xÔE&&Xso„B¡@Q4Ðõ;ݨׂȜ9sJ||¼hš3gêÌaí¨#àõôô”cÇŽ©k'OžŒ]o•9  ÍÑØÙÌÑàO à#PÇgà^-Z$yòä1°›6m*...*0¿yó&šZ0¬»7­ŽŸ�²Ó¦MC �†…)6˜à}|}à£�>üñý‘ªŸf _¿~¸^•n|ú駪q ¾„†ÅŠCyžµÊÜ8}ú4 € Và]ÀMþ3¯4ú2·Tµ{ÿ €ý?íèÖõ›òÇÓgj„šù¡‰ „))hé3P> ë<К{#„B Š¢€ <,,LL¨^�<>ìwØvîÜYÞjìÔ"@GpˆTz£s $~ø¡Ú­nÓ¦�~³)ô©‡t©7°ô#+™èAЪU+ö& ëïMÛ•Çú¸˜*T€I‘âM¿ýö®70~ùåñññ�©�>0!0ž/MÀ'Ÿ|‚ÿÅHE”kàƒïŒ 777•‘àåå…>42`€�zTYÕJ¸¾÷ÀÎ�ÛZ»Pê–¨f²®ù‹Ì®�IW.$JÒýRñbr÷C!„Eàý� èUP‹ôkôèÑ#Uº�ÙDѨ^ÚE¥ÿ ) §æ•F³s«àT+åòÞ÷ø.þ_ù®l2¸¿zñŠ$œ9ový®·hå—KÕëô!„B€¢(ª)žÖØÏ²(Š€Ÿ_IÕø/dfUó_·u©VL‚†°ÊZDÆwpH›Lˆ5E uÃM?´ë€¼xþB� üÿØ; ¬Î|cKB_J°Ý^˺¤% X¸`*-“¨Ø½@Hd† ¦7Ò`ÓI%݈›î…4®‹«¸…!ØÇ0Æ^G2èoçüg?Ç�A°Ã²Ï3óL<ßwÎáËô÷9ïûžÎö¸uÌ vŒˆˆˆ€ À¦ØÛTøÖÖV[�n¯ýë@ÂB�{ÒS—´˜GOr€¿àúÑ1¶O†=Áï`ÀÖ–Ÿ´¾im‡×^r¡öïݯ¿Ô7Ø1"""z0€wß}WQQQ¶f=,,ÌÞÅo¯ì@âÃ^öÚ¿‹½Ý7ŒËñÿg æ×ŸÿA‡Rfêd·Áÿã¿YÔéôþ¹Sî—CQÖÜ“ý}ˆˆˆH @Ï×Ülý¸ûýtÕuuÍ�ÁJxÐ[×>^·€+C.²Á¾ËÏÞþX ÿ¿ÒíóHÿQG®¹éÂxíÚ±K‡ÚÚTýé6ào¨û“WýUQç_ÐáßúcM�½9Àõ–DDDì•€K|‡éêÔ%.ò¶½â |uEÌ`E]9¤Û@\h”އö;ö_÷Ëh-yçíØº]ö°�ÿ¿]¤1AáÇ\:àðÙ[Ù1"""z""""DDDD€@@DDD$€€ˆˆˆH ôFˆˆˆˆ@\\œ<<<Ž¢ÌÌLµ¶¶êThkkÓ‚ ´~ýzt?DDDDÀü›6mRss³***¬¢¢"� ;wîÔСCµtéRôˆˆˆˆ@AA�ަ°°Ð>ïÅ €üü|¥§§ËÅã�?®ÈÈHyyyiðàÁºï¾ûtèÐ!¹ð÷÷×¼yó&???ÕÕÕÉÁÛÛ[µµµ®»ÍX·n�-9pf8jîܹv___¥¥¥©ººZ vÏ‘#GjÙ²e """ž¤@vv¶ZZZl½~yy¹ Æ?ÿüs¹Xµj•–/_®Í›7ë“O>Qÿþýõᇺ€Ûn»Mß|ó�jjjlýÿ »Ç¬Y³ÔØØ¨¦¦&(44Ô~ÏöíÛ-H8q€pê""""ØÐ>|¸ªªªt,¢¢¢œen`ñâÅrçD€û=RRR”šš*•••vþž={@@DDDÚ¿¿\$&&žh°}JKK = \t¡®OË×äç¾ÖôWþ¤›î˜ßù5ÞÕ7UãçWhê‹ß+ãé?(}ÎÛJLœ©ÿÑGλ#ÿu»_g¦Ï}ÛÎí‘À&€7n´�ü222Ô¯_?gC? ÷íÛW%%%Ú±c‡^~ùeyzzžpˆ��u´�¿ó7òòòÐM. ¼@7ÜüMyîŒßSüYWÀÿ7Ï|ÆÎ›ôD•Ò¦=¡Ô©�éž?ÕÄǾ°{ºÎML˜¡¤ñ ;ô¶œ2»Ç-™ÏÙ¹Ý$"""Ø0((Hñññnopö4h�}wÏ=÷ØŽÿ'añ <<\ÅÅÅ !@7@û_WÛ üŽû_ÕÕá7èª_]×eH¼öíœÛïE~¿t ‘!—÷ßNÍxÄîsÙ-vŒˆˆˆgPX5,Öõﮀ ò'Yã£'Ø}n¼mNGß#"""€×çž§¯_õèÒk…žöpÃ-öýÿýk;>Yï˜ýšÝgÌ\iLjˆˆHà,ÚUH›ú¸}ù�Ëuã­JŸûŽMå¿gÑ¥L\¤È ‹ºücþm¬¦¿¼ÂÞà#""" ‡@€ëÉý¤'«5µ´Î^á—šñˆm"è|noº°³¿á,°s㯙`LjˆˆHèa€p[îïìû¤ñ(2ø¢×õ'Ýõ@§¯œðÈï5ùÙ¯áoo@DDD@O€ì�2é!û>â¿êpp?ñÑÏuOñgǼÿÕÞh×'ßó`g¿ @ d_w¾ Çÿ¢KÏÄ[®Kγï¯=®Ãïïüm¹¦ýî�:ÛCàŠáñvŒˆˆˆ€X0æß¯° ü:x‚oƒþŒ'«5á¡Ê¯½4 \S^øNw¾oLjˆˆØ3%€`Þž÷²E€˜Ëouü_{SN§ÓûÿçדíûÄÄ™vŒˆˆˆgI—^`ƒ}—7ÏxÊéãç¿çöù%¾#�\3ö¿®Öä’ZM{©^·Þû¢ øÇÏ{×®»ë��l€Ž—¼iop½% ›DDDD ..NG Qff¦Z[[u¦ñööÖÒ¥K;ï¶@8ó""""ùùùJOO—‹}ûöiÚ´iùä î¿!%%E©©©rQYYiçïÙ³GÿÊ‘À{r¿eË•••Ù€»¾¾Þžè;ç~ýú±OŸ>fWàÅ_´§ðÎ2€Í›7;Óÿí¿g!ج†¤¤$¹X½zµ�¿uëV ìð’““•››«+VØ`ÿþýjOÀ¦Þ0ÀÙÀžüÇÆÆÊ耀ˆˆˆH ÄÄÄ(''G»ví²'÷üñ ÃáÎ}¢¢¢lF@»`Só;:v¶ÉŸ-= àÔDDDD$°  ³ÉŸmä—‘‘áLõ·éÿΆÔG}dOõÿüç?ë/ùËq€÷Þ{ÏïÎL€mÛ¶é(lS¾¬¬,­Y³¦ƒc·àÌ0��¿óóòò@@DDD>>öf€ÖÖÖöÇn ¡¡AòôôTxx¸Š‹‹í•„ t-""""€p¦± G�¥×_]"""z'ÛDðÜsÏÕîÝ»@ """ —@¸÷Þ{•––& ½ÀÏ?ÿlëô+**Ð   """@8Ã""""DDDDˆˆˆˆ€€ˆˆˆH ‘@è� €¸¸8yxx¸´÷ögffªµµUmmmZ°`�Ö¯_¯³ÍáÇíwÍСCõÆo€€ˆˆˆxb6àß´i“š››UQQ¡àà`ÉaçÎ�6è^ºt©Î6óçÏWtt4§CDDDD   @GSXXhŸ·£7""""€�ŸŸ¯ôôt¹ðööVmm­>ÿüsEFFê¼óγåYYYr¨¹sç*,,L¾¾¾JKKSuuµäçç§‘#GjÙ²eGß×mfÁºuëœe6áú믷¥ó½ì¾cÆŒ‘———† ¦%K–€Ð…ˆˆˆˆ@vv¶ZZZl�yy¹ ä��~ûpðàAtÚr�•+Wº èýýý5kÖ,566ª©©I µ{n߾݉ Ž#t:ફ®Ò+¯¼¢††M˜0ÁY²`{�O›šÃ‡WUUUû ;vØ÷o¿ý¶:ÀÀâÅ‹å"%%E©©©rQYYi×ïÙ³çT€Û€åË—Û57n k ,°§è[¶lQYY™ Îëëë݀Ü9sÔ·o_�7Nß~ûmgÀf$%%ÉÅêÕ«m°¾uëÖÓœ™ vÍ?ü @—""""î$''+77·}0V­Z¥;ï¼S °kÿI‘@ˆ‰‰QNNŽ{pÇ6øsM¿?‰`{ ”––3,\¸P—]v§QDDDD›Ú@þ›o¾QFF†úõë§šš·pàÀ•””¨®®ÎÎôÑGÕ¿mÛ¶í¤@ll¬é ü�¿›——ç^}õUÛt°¹¹ÙÎ!à4‰ˆˆˆH`À   ÅÇÇwô„'&&jРA:çœs4zôh}øá‡'»Àvñ�ˆˆ�§§§ÂÃÃU\\l¯t€½{÷Úoq"€óêÁ¿³c Dkÿ�>Ð !‘w¼%.‰ `À� I€ �’ @2$€dH2ö€$@2 I€d’`H€ ’ @2$À@’ Õì�lÉÓÅÃ1;`< Â133„Ùaffffþ‡9¾àwq˜™™™™™�{_ÞÁÈ«]GöÎ%¶Oõ“ž´ÛîÙé‹êuUµ�&õƒ—Ï_€Ì5õÏñÔ¨ADlß‹W/^âѽ‡Øš°Õ½Ëêœ{ëÊ $Çã�´æ«Qÿ=@ȼq38–&ò0.„ÿýh�óvޏïèˆ#0ÆÖ^c޳‰=FׂÚn•T¿/'c;ômÚ§�ÀÛ×oñäácÝs[÷‚GÞbªž%¥ëq3/‚~Uº¡‰_íÿöŠáÙ1­³Ñ¿ùîE"‘H$€ b‚>Ö¥0eà8í WÏ_ÖËèP½9gåü娴b>~øH¡V@E�äëW¯±pâ-M:I™§V!ù{woÜæÿ]Õ³¤|=v×p8v™ Ï<Å“ý½J%~D€m>ðóâA90©­1ø9<߯ˆµÿ™ŸE"‘H”ž%€ ˆ‚L™2)²²²B«V­ðáä†üóçχ ´Ö“5kV,XmÚ´ÁÓ§O¡/Ÿ>}o×®]HLLDß¾}qýúu1ʔٻyê†TE­ÀJ©6¸ÓÌ]_î2—.¢ŒÇù–ÇçÄDÙuPWÉ@”Ÿ¿©Ö-^2gÌtÕ@“`kŒhl¦÷õíqí‹Ü�uÿÝÅÔs;NÇäfcùNU½¯!íú‚ìÙ´hü¯vÓgýz¯§Œ}(hj´ kœÌsĪ1Ù°iJð/ì—ã[™ cÙ¼Ø>#3æö2à<‘H$¥w‰ b0à¿uë._¾Œ¥K—ÂÂÂL3€ë¹yó&Ο?�„„899!**ê_1ž={®uݺuÈHRPÑ%Jù¬�[4¸ã¬õ·³ÇNãÝ›·Ü‘þî@³ÒuAv¬ÝŠ~Tƒë™cë´,z]ëüEÜýßžß!Ù9Üõg \×£ªª€›ïúÆ¥k¸uõ&|¬JrL½T8›ŽÆÜŽ3hrèü{د¿b\Kìž“ »fÿ¥�³2cp}søÙäç‘H$¥w‰ bôèÑIéׯÇÓÈÐ^Ï¡C‡ÀþñãǪ € � MUQŽ —¯ÕúÛµ W,~÷ Ö¸3~óê "íý˜��¦€ËßÀ–¯cânsY7¯ê}5‰© 2©ßh~O@}¯ê ¹çT>Ù9Lõÿm@NР¦w1BÐOùø7‘H$eD‰ btíÚ5jÔ!,àœB… ÁÔÔ¾¾¾Ø»w¯–P±bExxxÀÈÈLÝ_³f 177GïÞ½Q @˜™™áÀ�)6Ž;ÆþË3Ü=z4\]]ÁûØÚÚ¢S§NJí0aš?3ÀûhÆÆÆŸ“f\»v�s™²aÃÞ ,�@ëÖ­‘Ä`ZùùgñáýŸÊx�XüñÇXÍ €²ævhgiÇ€G 9 �…�"׿ûÔp.Ï™Mù]Õûú}Þ2�ðB>˜6d"߯¡iB3~¶ÎóYrÀ{Ïë4“Mû´î­r=Ц¶œ€9¦ë¼Ç ºæèPÆÎ&…ücr;c¸™D߹ѭ’¦À ?´»)‚šç†U Ô°@ø@cDOˉÀúÊ\‘H$‰ BZ6¤ììì°eË6ßc3¾M›6�çîîîh×®]2%JÚ>kù`ÕªU©jH1¸¯S§^¼x�äðòòb�òòåKäÌ™7nÔ,ÐÃà³ós||<á¿`Ä Ĺãg¸;Ï`„Ì>ÞV%´æ³1 ƒ÷Í¿o`PÊS”“x�Žcüx|�Æx‡¸ ãz�Ш?±ÿ(>}ü„ ΑÓËhf…>q¹“Š�)ëÒµÆ)÷\T•tŒjÁ Qùýù]Õû¢CÞ}@“ÇöƲ™ñlôÂ�{ûȹ”«Yaˆ.¨ëÞj×£¨wÅÎ|FøY9õ·— Í�é©<Ðɬ "†!j²J™pL$‰DbBš!%Ü•ðà¦OŸÎÀGŽaª>2gÎÌÝp$…i÷Ü™OÎ`FƒçK—.¥ÒPš2ðf0¯‘i@nܸ�zõêÁÞÞž¿Ëû(Ïpøða~ÇëׯU¤gϞȒ% ŸU){ȈbpGùþí{`ÀɆ‚®æŽèX£%¸#L¸óð“«f·ŽfpžÅÁ`•F`UÏÒÊ8úg�Ÿj5tËU,ÑÙ²rƒ2F“€L0–ßõ6fv3dJzŠåk•_•зr׿ƒc%0×÷}±éáßÏ:S+û¢[Ýv óÇÏâ÷”Hízµ�hö5“CQCkÔò´Mõš‚šä³\~�¦�"‘H$€ é¢)W®:tèÀ´ZÇvîÜ111ßÂàz”Lƒˆˆ®E£¾Ÿuÿ¬Å?uêX’®\ôÞ—™* �’ƒ¸¸8–=(÷ÉhbŒê:¤CõæZ½fŽ˜’ªÀ»U…† #:TÆž?y†¯qæÈIp^ð¯à.4M�fó­Z¸äôáà÷šþÒUÀ‘u18Öî’¯ÇûZ:}r]ýn_»…«ç/§ôj×£¨±_-ð+�Q}×_ò�éÿ¡�Í1ÂQ ÀàŸr‘Æ�"‘H$€ ¤Ä DûöíYCÏp­ÚwÖÚS€œ9s†%JO‚£G�‚†Ä›7oð74 x�Æ}Ù€0%ûL›6ík€ÂÖ­[•²†Œ† ÓÀ‰R[žDÜ�¦áv`Ûžý’ø)ó”±Ïžƒýšwש6•ƒóê…VC áuéÊV»?»™VÆô}_ãzIÆä`?–H()�šõhÅÔžž?‚�ÿ"Ç‚5ÿþU,ák�ЮfbˆD"‘‚ ¤‡&€ lÙ¤¯Aƒ`ÐÍf}¤Q£Fptt»ñ?þC† aÍ&|ßÜ , àý?~üæ4$&NœÖèÏš5 †††×”)Sùòåv–4$$$$k�bàÏgïØ±£b¼}û¼Ë ø<#GŽdOå8ÂŒ„ ÀŠÙ‹AüéjH8'¿¥Ôû�î6Tc;Ö²+;Úz(½Ø«Â_õñ6J©„Þï‹ýhºÄOž«3àѽ‡lؘÒ{¨]�¢¶áMµJôQxDŽ5„S; uóŠ ‰Db‚�^šæÍ›¡¡¡§°þŸ�1ƒjòÁÁÁ`Z<ù³¸SÏãÿ{ØØØp­lÈÓ4®aÐϬf ðÈÁÊ•+Ó@ÐiðÄgggÐD(V¬hnð¸?4ø;¼WŽ9P¤Hå´!=#@h/ðh½°‚ÞÊX׺mAXóφIkô×/] †}I‚P¥ ]Rñغ§�žàõËW4”ñ‘]�¬Žÿü' €v×Ç—¶ QÆô}_Ôî ÛY Á”|�ßa`Ns ER¿ŠGò}-•kõRÄp#ðØ¿RÆšMCÚ›‹ ‰DbBZ!À™W¯^�YA «’µò ² ÏÛO2ÎÆ~œ¯ÔÒ¯]œ òx>Â,g×y§ÌMz4SÓÉ­«7Á~ FÙ¡ž»ÖLMo][ë@v�'÷nÞç�í1Œuþ t¹ã�á €*ÅcÁà¸Y`=eLß÷E•)ŠçOŸãsb"¶&l¯9yà�fLztbèÏ^˜Ôl :D6Ofýê×CMk5³ÛOUŽÔWþÕ,À@?¤³|£­ág�ðÁƈšb €H$‰ ‚‚�b„ä÷BJpÏSœß«Qg0ÈïÛ´«VWø :‚éúlÚ÷òù ðsφ�´jÍ+»Ç‚�ê.œ<v÷çyò×.\�“‹r H¶ë<3Žì>„'ƒ×ð8»�Ë×¢¼SÄw1ümò#"ÿ/ßÄpÏUK{-ÂÐZýø]õû¢¢ `Ío+Á]yÏÈÀL÷¡ðÈ[Lc^¿Ú ù°¬w|2=Ô¯ÇÇ¢$x�^:ñ»*9™„_+D 5{„ö0…w -¼|~@$‰ÄA AP ÝJÄ“÷XÏ<Å¿ë}½ò–ÀôÖ“0·ãtew^½t7¬^ªlÚ¿k‘H$‰ ‚‚�–ˆ ªîT ’ùÖü®÷ þÑÌ>hà÷�îa÷ÿìÜ�g2qÇñà9$èØl�e¨ph°Ø0ã0c3³‚ÍÌH™€ÁÌ ‘�þ€Ð’Pˆô™/4lNÝÉûÍ yxv—Áïs+}޾Ɇ½[á¿×"b 3Øá¸y_W½ôálb�Kz8º[ÙÓÿÓÝCÙ°Q:¸¶×""b€=…·Ãòeö|m?3ãl¯ìðo_þh_0øõÔTÖÿh€€@D DÄÀ_¼_½ÊËœlÄýìÿßÑËÙ³nÜ {½y D DÄ€O͹§  DÄ@ÄÀ@D D D D DK1 Åb1_2™T±XÔl6Ó_J¥RjµZ ÞòuÅãqÙÿïyž†Ã¡¢Þ|>WµZÕ`0tïÝnW?U.—eÿÞh4•‹…ÿ;шìÀ?�Õï÷Õn·•H$T«ÕBìºF£‘z½ž:�Žòù¼Òé´ì°å¦Ó©½vÍ�€\.·t¯“ÉDŽãDn¨T*r]W¿ì›½³€ªëÚÖp\‰é{q÷'ŠCKפ8Äݱ•VáÕ \¿µ¸»»{ÝÝÝ;oþ5îî`çœÃÙ ÿ?Æ7çì³×^{]iç¿æœë÷ B!„E ==]Ê+''ßÿ΀é¼^|ñEø¾úê«R›…w ‘ ˜d¬X±B¥wïÞ4hB!„T E`ùòå+š�Ú�ßôíÛWí>�;VŽ;fb„††Š«««´hÑBúôé#[·nMmÚ´‘¬¬,¸¶nÝZNž-o¿ý¶lܸQ5j$ëÖ­MóçÏ—!C†È™3gTÁ¦M›Ô´9b-“““åÀ�j^)))ê}4!""Büýý1'eD¸»»ËŒ3,eYGÏ¥Pã´ì'~Þ©25ûI}ô„$=p@b3þ%þþ3Å¡Í`ÝoãóvÈôÒófÁ}ÖžåÜÙA&ÇüŸÄ¦ÿS’‹«{¢—–Éø“«e~À½�§DÌôæø‡$åác½ü¯2~¸Ùñ !„B€¢Ø ÈÞ»w¯@Ÿ|ò‰4lØP—ŠŽ;¶Ø·T€`c!`Խ͛7Kyýðþuà;sójÞ¼¹„……i�õÌ�ip¾_~ù¥4kÖLPeï7ÔöÙgj—û¡‡ª6Z´h‘ ¶ß{ï=5ΩS§ô€á”r@0%`$ø›ù  à‹öJhZ‘„¤Hܽ›$¡`—8¶fb ¨ºó&EfTø,·žãÔ½iOž‘i9ÏJHJ¾„ÏyHR9®žïï7£Êó;øve¤>v÷á÷ÿ}æYñt‹*ÿ[B!„Р(–`ýý÷ßW�%‚ͳgϪ´ztáÇ.¼&m7: À¢€`�êö-ëçÏŸ¿Õ|ÀnºIsBצ�ÿÌ�i`¾x/Ô×kfCeï7ÔCãÇ�—¹sçV«€Ýz”7  ‡™3p:BBB‚ôïßë‚ñµ1°ë�Ïx'Ã榥ò#»# ×ÀSÀø:Zy. €ÆÿöÙ*¸ŽZZ*­éo§Î£ð·‰€ÀÛV³aJlޏu£Ï °wº9æn´;wq´y~ø.nõVI{ü´Œàgb< #@ƒB!4(ŠÀ- Âî3Ò·È™ñ¶téR¤½Û`ØÜÐ�`d¾ØùÇܾþúkQ2~¿UýªÓ€ T¹Âõë×Í0nP›ó ÒíÑ“cèÞ%¶çÎ�Ú`½ 64¾Ž4Lù­vÿã×l“„¼ÚNº)Æ €*qû¤ùô±KoóüÆ�˜¢Æ˜¾ÒäZÀ�¯1SÍÝK!„EÀÃÃC.\(ü±Ú-ß¿¿”Žä[¶lÙÎ02_d9`n;v쨒÷› ê‘f��ú§žzJ»®k°‡”y Sé s:êõ1†î�Ð\Ïè)°añ¤ÜÜ\qvv6ºŽ64æt’ì˜vVqkß¿¯� !*( Y†Ï¿«à뙤•ØÉæù¡¯@ÊCG‘9`özBþN‰»wsùï!„B€¢Ø°C‡âãã£;uÜZ0#`óòòR]ç¡?¢`d¾H‡GÊ|�=´#êÔ¾�,ÎãÇ{ãX¼èèh˜f�Ä©Êa Æ=Õf@øÛÞÞ^ýç‡Ó0†nMPÒ�c Ѽ/**ªRîÇÎ=ž‹@Ĉrÿý÷ ¤5VÄop Ç"õßÈ:Òø}JBS `«ÝñIé›ùoU+�:úà„ÕâÔa„Y õñSrçÝÔo“îß/1+þ&ž.‘Zà]iœ»:c¬›c®Ç6Ï/é¾}¿v»ÅçLÍ~Z’ÿÿþ&„Bê.4(Še›´€?«´2”Ô=ш^öQÝõïÛ§ðÅfþKB’òp,Ÿú^uÙï0\wOLú?$!—DÌ{DásÆ®»úý¤¨LÛN!˜õ ºßÃ1¬JóK{âŒLË}Îâ³´ûFÙõÇçº!„B€¢hP40w_|ñ…Ô=ш\ô„ ˆ§L½Kœ:êwÓ}&Ä‹º6í.Ý÷æ‚g‡¶CTp>½äœŒéïS¹æ�óÔs&ÇæTu~È@Ó@fB!4(ŠÿGH)õ(E@j>jòQŠ€cë¦Ø 8q ‚hðfwæUÍüª-øl—Œ…€Ÿ áé¥L¤ö�j5 ÊóC€ä‡ŽX,EÀiwÞ³B!„EÑ j·€Ó ÜÝÝÅÎÎNz÷î­ÎãGêÏcÌ»£“äLmk C§Ü´XØc˜½³òïH«7TÛ?ºŸÆB3?|¶Ê˜¾’úè I(Ø-ÎöNÕ2¿°÷«ß»÷ñ0Ûg×Âç<„ÏuB!„EÑ (Š%®ÝF«ø ¸{Íî°ëRê­àç;]TÀä…V‹¦~‰E{ÑÐþ«m~ãG©9†.7ù½À,uÍÓ- Ÿë„B Š¢@Q µ¸A6RøuÁ5y̾Ë}oÒ ˆOzð  è]þǵÂç9¶*Ór×IÚ“ge‚chµÏ†N)@F¯FB÷1Ú‰Z©AÝ‚B¡@Q4(Š¢àÖsœ$VyÄüGU@=5ë)\O»k½®þ©øøµôÚoÑY:Rñ'Œ ¶Úñ?rÁãj ÔâOŽÎ6ÁË=Ææù�qCîP'¤üðC1.`Ñ „B¡@Q4–/_.±±±¢ éáøMß¾}UÚûرc娱c €ÀÀ@]Yغu«Éw`ãÆ�µoß^233¥wïÞê¡¡¡²oß>ñóó“Ö­[«T{ì¶k*,,'''iÑ¢…tíÚU–,Y¢vé5a¼¼¼ùäiذ¡ìÞ½[×4»É ,°É8räˆ ¨�?® R7oÞ,š‚ƒƒ%$$D4mÛ¶MÍí‹/¾srwwGÐlq<< ÷#H6p]'ï¸öú믋%X+CsÃøû_ÿú—ñt}Û×¢.4!„BhPK~úé'yÿý÷åñÇWýÙ³gåäÉ“R¿~}µ3]^H3¨´€ÿaÆIjjª@–‚Td%L™2E4]¾|A«Vƒ¯‚ñ„„¤æã^\Ã{X;ßZz»�ë&iýì±_‘ ¬•¡ggddÀ Á=(°jTa-ê²@€B!„E±$‹-B*;‚Z“câ–.]ŠúñJ¨WGúùG}d«£µî¨�Ç÷ø½jÌ€† "Ë–-“Šd`­ ?iý111(À{Y\×*­ „B!4(Š€‡‡‡,\¸õ÷Ø�6Ùý3fŒ. †€4}M¹¹¹âìì,åõÖ[o‰���”–– d«pîÜ9hýõ×¢Éßß¿F €§žz µõj—ß’ ¬U¥Ÿ�Fˆ¸öÆo˜]×êX mÌ:"„B!4(ŠMd=zT’’’TÊ;κ‡Ð4nàÀ�rþüyùì³ÏdÕªUøuõòhЇ]h­Ù]YY™jf‡FvZ �`Íçªd €E �®ü¨™Ç}Í›7¯QµüX˜‹/Vuþ¯¼ò vý±ƒŽàߨZYyö7ß|£Þ Fþ3ÉÏÏÇ3‘1av]«¾¦cÖÑ „B¡@QlØ¡CñññÑ�€šv½={öTÁ¤———JQ// ØÝwssS)ð_~ù¥�%ލ»rå ÆÇn5Ì ýgSô)°··Wó�‹‹“ÈÈÈ54­_¿^¥ówëÖMÓ‡“ ‘Ý`l­¬<`ïÖ¤I“@’@2$$€@2$€@2H2$€$€@2üúI€d�d0HI€d�ô ’ ›ÍF&“ùS}}}ŒŒŒD>ŸI_g0H€tÁŸËåâìì,VWW£®®.CÒ ’`nn. [XXH?—ô…€d˜���þþþx/ŸÏ§×455Eeee´··Çþþ~V]]óóóÑØØUUUqttô·ÏÖÔÔÄòòr´¶¶FEEEúëëë!JÈ FGGãææ&.//ÿxÍoé‚|cc#ÞNð‡‡‡qww—.ôËËËãüüü§ ¯¯/öööbww7žŸŸÿÑÙÁÁÁØÙÙI·" ¥Û^^^B2”ž@òÀ¤¹¹9¶¶¶â­‡‡‡(++‹ÍÍÍxïõõ5½[?66öÓEüÚÚZVìÙƒƒƒôw\__‡d(-€ä€ô®ýíím¬¬¬¤�â§�òûö-žžž¢°©©©èîîþp(öl.—KÀÅÅEH€3H€Âz{{cbb"}tÿí"þ¯_ 8=====Åž5Èð/1H€ŽŽŽ�ûûûøþý{looGammm133óáPÔY€ Ÿ À yàÕÕUzˆßÀÀÀÛ½ûéa~o½=”¯¥¥%NNNâññ1–––Ò-éý€¢Îdø|ÉCkkk£«««ð[Ò=ü“““ÑÐÐ�.Ö;;;ãôô4RE�5ÈPbÉ É`� ’ @©$$Àÿ3ÿø¾B2H2$€$€@2H2%c�d� ?$EüÃ0HI€d�d0HI€O$$@ ’ ›ÍF&“ù�]3€P Ã(”Z%Q‰ @"EA@)€€QR‰$ Q‚(€" DÕwþeO§ØË±:¾ÇƒiªaÁ¼ý¿u»Ý(—˸\.x‡ûý.ßÑY39C¿ßG"‘€¢(…B(•J8�N0 ŸÏ‡ÑhžžÉl6Ã+�†úù`0a ”RJ)ýµ „0È…ÿx ‡CX­Vl·[xvßæ]¾oø½Q1žL&³Ífóœs~?—ëû~¸ À¹\Îùm»Ý>Åoj×/FÿËÿÕr¹¼/_9çáp8 ]×] vúÚíkÇŸÏçwµóÿ�ãZþO§S#a€”ÒPºþ÷b±¸­Ý?L§ÓÙñxÌÍ…êðc¼ëõú±Ý ÀjµzûýþµÝ�Àn·{ )¥®Ý�@Jé#´hf ` ðÃÞ]è6Ž…Q~¢aff¦2333333·ËÌŒÃÌÌSx€u®d¯¬6�©GÒ§Ú÷&��û_ """"""DDDôæÍW7Yµa£¬Þ¸Y;!9ù255e“kúáÇŸdáò•RZQihýúµtõôŠ—€lضC]ïáŽRXZ&/ÆÇmöNNM©ëuöðÄ91 ""²?­íªx]¾v½¸zz«âzóŽ]rÂÅýv<þ\]ÝUûª ›Ôµ…GÈ�£Çe÷�CXBDDÄ€ˆˆˆw�%«ÖÈ­Û· OÚïÞ»gW@FN®j �Ž•§OŸéí0>>�Ÿ lŒˆˆ÷C7oyôè‘ÞöøÉñôóGŸ-""":xì¸,]½VΞ??gqŸœªžÀ¯\¿Q�øêëoþ¼±?~,ñI)jXþÖÝ{$%=7{ÓýxºŸ–•-Ûvï• [·#”0>Rç»ö”‰‰ «…xLB¢stV×—”,÷<@;F 语¨®Qm_~ýµþ>¼ÖÓ×_Voؤ®³¦¾AM‘Àë1Å § P�6X±nƒì;|T*kj Ÿ»eçnêç–]{¤¼ªZ{?Ѽ ÝÃ�88"PÿsrAFí1°%""¢êºzÜ”Õ(€ÈØ8U¿zõjFQ½vóVÀªèÝ´c§`´€“»§¬X»^õ§ddÊâ•«%42 ï·Ú�Ù; P}FDL¬4µ¶IpD¤!øöûïq޹þ¦žÄcŠ@t|¢øKv^¾é`ÑŠUêZ³róU�¶ß~?©®Ñ?$T�û‡HK{‡º–ü¢bÃçâ;ôðñSíÛ÷ìSm?þü3^CDD4/ܹ{Wö:¬‡G�ôÿæ­[¶ ˆˆˆ:B,¨‡4ì9xE·¡¸Å“qœÃÏ¿üªÚ’Ó2äû~TÇ™¹yZ¿^,?yúÔj? l#°4`hdT�wt÷˜ ðû ífW/½E>ÚÚ»ºåä©SêØ' a€©)=ýýª­¹­çDD4/1€�ûÈõ7ìe """—±·ßAŒ›µ>ëÖíY„xÚ�)Z¡;›S§ÏXíÇ8îêí³hç¹…Eÿ[ðÅW_¡M�xÃ1v 0½À×ß~§ÚJ+«pNDD4o`êžþk÷{L›»wï¾DDDÜ[â†�'ïLÀ<¿wßÿýx uƒ/^Xí׊ëÞþKæbx>†Õc.þ_´5CÃMhG^§]cgw�éà›ï¾3ü DDDóBwl'¬Íùí}6 ˆˆˆ…*ŠjC�š™¥nÖ~üɬæµk+òŸ¿pQ…iŵ�ÕþßOžTýQq s퀹üÚïÁ?†0âÚõësÓÓÓÚDm?è3œ<}Zûðy , "":îìj(øA ° �"""ÂVX�oùÚõØWOȱú½¾À³gÏôâvÝ–­j­€¶ŽNµÂ=Ú°~OHD”>ľ±¥‹àióõ­õŒML’ÖöÚ3Šgìàèæ¡Ú± ?Šm,ò·zãfŒFÀ*ÃppuÓC‹°¨hY¶f�é׈kǹ—€ú ŠKÔ¨:"""­Ð7„õ8F·´""" ­ÇVwØÖ>‚ls‡Õú±€�¡¸Ý¸}§šÏ‡Å1÷ÿ³Ï¿0ìßWX„Ð@Û&sçM÷£¸Ç"�xB�°ßæ»fÏØ�‚õ[¶ÉšM[ ˜À0ÿ9€3gÏâ©Â,L„UüMÚ .°Š1v4Ø{èˆTÖÖ™ˆˆˆÈž"""ÒŠ[¬€Ïïãvì�``ü;¨°]YÉ‚c SQ’{ð& \&@€ €¨ªž ˆÌìÙ€ØûíÙ€XëéÙ€Èüz6@€ @wàœ_ÿ·uvýwõöùoliýßÅÓÀÞY踮,Qô‹333333333333ó03ãgÔ›%©­�sÚzJ¬(·$-Év%»º.ìÝÕmY½n½äääDõfkjªeßÁC’ž‘s‰œ4m†4lÞ²7nÝòü|uuqyÿñC½çª­­‘ªªJŽ#ÎŒ¹ódÔø ž±Õë7Ȉ±ãb'Ïԡɵ÷µ¯;K=îÞ·Ï36uæ,Ù±{�9·Ò²}GyöâÇŠ¢(Š¢(Š¢ü× €u›6KïƒäÑ“'’œ’,?}BlHYY)ñ¨QT\$]{õ‰I1‚àÚ¸e«dee…@Nl€û¹ö<(ã'Oå8â\»y“ß­'’½�{ö’c'NÆNž¨C“kïköºS@QEQEQ”¸6:vï!÷>äX± .«`¥‘5Qš¶n#/_¹þùËîGÒÒÓb'¯ԡŰ @œ£(Š¢(Š¢(j0ºkï¿Å.³°k6l`V¡&+×®“’’b'þâÕK>f¬4oÛž¸lܺÕW 1bD3mÚˆf�[uè$c'N–�Ÿ?sh×¥«;y’Öv¾+½ú”§ÏŸnÐF~ðÈQé;xˆ´éÔ�i €�çš1g.×CHO�lëùôÙs ä­ôäÜ•gëX=qB†ŽñÃòÕk¤Gßþt8×.]Æ÷ì÷`zåzâÔé^ù7ùðUS˜;Ü×[ÕÅ!]zöæûÖúܰäÈËàŸµÍÛ·K·Þ}©e™2c–$%%‹7EQEQE €‹W®H£­döü…òíûwÏÏ,X²¡!™Y™’ŸŸ'£ÇO”u7“ÊÊ iÑ®ƒì?tXRRSå篟òæÝ;kÌ-LM 8³×ùù²÷Àf·%5-Õù<eÕºuòöý;ZòY#.ºvGœF\pmÚºMrrsrór�8‚‹{ýðñ£òLž@3ÐW®_gͼ”þÕ*?`è09rü¸;ÏÖ±DøñYÙYÎR‚NÝ{RÄAܶsWyòô)çv‚¨Cÿ®|Økjó¶íuùÎ=IAa�<~úÔŒµ¥¾£[�† S¦R�ö…18Ç0bÉï?¿1Rx~c(Š¢(Š¢(J<¡üúý›Yd„ 3€!"aàn'G¬1 ÊqQQ!q¹}÷®‰ƒ%*Äø\ã–­ååë×!ëØ™•evò/ Dx~úü™¿/Ù9ÙQß�{%VZZ‚à–—¯^y/ØÀ€hÒª�Ü{ð€sIIMá^¤î<[ÇèjàÇ_¾~•>“9uö,×äÝû÷ˆ^)¯(çÜJuøÿ¶šB3Ö<³×X[ë;òõè €=GÞ€û¼¸¸˜®9wñ"犢(Š¢(Нèk`ËV­FD°Á×äý‡œ#И©â°{ÿ~ÎeÚ¬ÙNÛ¾=æ1„&ŸaF5$¾m×.¾Î`ÆÖ´uÕrÍL0¿I«uL¦ |éÊUËñS§hã÷̳Ÿ±Ü¾k·Ìž¿€cº0dËörâôigˆÏ]¸ÈrO�Öaä WM™±¦.=ÆÚRßÁ/°çÈnÀ¸ÉSÌR†xEQEQEQÔ0lݱÓ‘ßü@@Hyyçaùùû—,^¾œ¶}ÄŠŸ˜b´ýóîW¸!6iIŽ%€¶~“N€˜1.]¹ÊZvîCÆNš,‡�÷¼>Æ’Ý÷™áçµ|Ô³ð´ÿ³Æ�Y–Qn!à:Œ¼@.,f�¥ö6ì9òoìܳ‡ãxGQEQEQÔ8yúŒŒ3Îi ¦ÅüáãÇœ[yóö-‰5ÈÖ˜b´±#\Üë§ÇLœ„¸‰%€u×ü&Åù2>lr5Ø3�Ù^–�G^£ç%xýŒ%K/Ø<޽Xë_UUÅ5é=` \¸t™ßa-¼ý¾‚¯C“kË5߀©Ëpcm©ïà kŽŒàçyÂ,{hݱ³Ü¹w�óxAQEQEQÔ µyÅê5r÷þ}IJNDÀYl"Æfp?BÉŸ„?u$cVXΞ¿@?â˜tD"ñŸ1·cóµ~ƒ‡Ê�Ÿ?2Ìbg-v@€}Ó5³î}Ö¼ùÒ£_Ÿäåå±1\XàÚ�̨³&ßÜgT˜<}†tíÝG†Œn¯ëXØ9¾s�^ìöo®ÑŽ1À¦sœ[¾½síuÍ¿À9;ê÷ì7€n~S]õTM�>÷öí>»Àùõ‘²ŸQXdÛ6¼øYô48Û†1 xâ„S&ga@VØüªĬֹÈ{ÿ=²ð' ²ùöµà~6´ ²ÎòúE µ€l˜¶-a6\>[Ÿ"›Ÿ­W��«ÿ¤7™eùo{ˆßˆç¡ýrTѽ§Õð ‘Í›O è]xé¥i[Àšoã\@€êµÅ¯~õËj·-ýñ¾Ôj@ €ÉóûW”v¼ñêë•ú#ÆvÏ=µ2Þ÷½xýå×â‰{‰Á-�Ð@ÕÀï·L]�cÖeÓ*íœ2xbDDêüß}ÓÒxtÙƒñÙ§Ÿ%ÃÛõÕHU ÀKÿz¡Ü_<¡ãOâÊ¢mþc�¼-¤Ñ}ðQvP§âò!­�Šÿûâ‹X÷ìj�›spÉè:ñĬoÿÇ:½èÙñÀ’{rÎýþ¿��?ü(ò·j¨¡à›ôhÜ.²ã‘¥äœûÇŸþ–~ƒF€ov�¦üñW¿�O?ù4&ôQ\> YïøòË/cÉÌ›5Tq�:æþÍÒb€o¼òZ¬~zUßw|ê¸WB�toØ&þùç¿Gv¬z|y\4霴.@ ´Ý¹@#@i¾ÿùBgÜ©‘¿UC�UÔ.€€@  € `Ûƒ£Wß3bÜôåqôü_Äყ”Z·õ=£ßÄbÄÅwGѬçbÌ5�ÅÀ“fE›{i8Ø€‚úEï~gÆøé+RÇä¥÷ýÇ }“éü¸©ÏÄ Éóâ¨Ñ—E¿‰7F æý<ÚôÓx°¹Í÷l“:ôƒO[mì�Þîÿ§ o«FѹÝèȯ³_‰ò¦;7‹ñ3VÆð ïÔx°9Nh±O‡â¿s€�7䬛cÂܵ‘·UC  &uß>¦ ©W¦æõ÷ÞÔ‹–?زAŒ¾êásíã¯2 Xtîcù‚-ÊÔvǽª%(¨w`9ò’ô¹î='i<¨þ)U5æò´àøŸ­ŠÔùïqœ†€ZdõJ~þÒh½�µ)ÈÛ¦qnwHÖéO[ N˜½&Šf¯Ž{µ­%�ÖÈÑ©õðôÙ>c¯Ô€PÑà„žÛÇùÃê–©wHòë残¡gߪ –LÈQ¸C^úlÿIÓ5 |“€½OŒö…ýÒ¾ÿ%ÖتQúo7Ø €‚ú¥Îþzý޹>uâ‡MùŸåy[7JCüÇO_‘Î�¹æ±xÊœ8rä%Ñ÷èëbôU§òA§ÍOa€€Í(h²ca긗%¿Î~©~áö‡F�^'ÄàÓĨˈ¢Y«cì OÅÐso‹®�ŠÒÎ¯Ò €@ €@@ €€@ €€@ @òüßþ¥o¼úz¹.¶ìŠïŬÓ~\¡œ¿UøfÌ¥1¢I¿œs­wÌ‹i\ï½óndǼ«gæÔ)oýáíûÅý·ÝùÝŸâ“�>Ž—Ÿ)ž¼÷ÑÙq@�6`‡Ý›Æükfźåkâ�·ÞIm³ò±gcl·!º�&uö�óœÚŒð€Ú|ðþqËÔ9f]6m£/Ðïà]¢ÝN{¦¿—\üý˜vâ–éï®{î½î¶É?xlË!±tÊm1¼°oqY«Ÿ3.º>Þ÷½ÈŽ¿ÿñ¯¥wèËQÿ¸£Æ¥óï¼ùv,ø©X2óæx`É=)8øòË/câá£k¤ñŽ8¤Kj£/>ÿ"~·î×±lþ’xdéñáûFv\4éœ ÜGƒ¸~ÜqËéó£yýƒRµ4xé_/TèË ¶Þ'î½ö»ñèŒoÇ„Ž?‰[ÎÿAÜ0i«˜|ĶñÔœoÅÂs¸‰ß×(NžÓ�¹.ò¶lP\~øÁ�#"Ò›ïQ�¦·Ü¥tèËU¿`›FqÖè“£iýJ”wkÐ:uÀÿø«ß—÷¥çreÑ6åùlz ¯›½ìX¢¼Ó^-â忘ÞðwÚ³y¹ïãð†�SØrB—¢årtÙc�¸þ¸­bù‚-âÙùI<3ï[qɘ:Ñfǽ6å»Ò[ÿ¬C:ªÙÀœs} zÿ]z‡¾üõK³æ™ÿMoàó·nT®çsÉè:ñĬoWzÃ^}Æ%‘'ôŸP¡û˜zô5±pòœ((Y€ GêÛ…?ÈB€döé?Ž»î¹ÉßsݸËãÖ3¦ùé¥×+»C_þú¹oà_øÇóñꋯ䞯áàœq§æN(Ç}Œi18….CòŽ*ý;0àÆÒÛÿ¸å¼ÆÝW/ ²ÅÓ€sÖßèïj±íÁ±tÊâ¸pPêÐÖxÐr‡ƒcñô…és—�rÁf,ž±(²cL—Aº�VÛš€Ÿö=Ýÿajkðé'ŸÆŸó‡4?ü�W^‹ÕO¯ŠãûŽ/1ÿ¾,�ª§¾]äoµoêüO?iËhRgŸ8oh½8³ßÆCó�Ê:¢iÀš nŸ}kZ@oýB{—�|~*ßœ€Î{·Hmö§_ÿ!íšPÑû˜yÜ�±à”ÙiaÀT@í Ö=»:^üç ñØ]§Õâ]ö`ñªùs®˜^®‹ÝqÙ÷cv9·œÜãØôØ«m�_?~ÿóßÄðv}7ê:»ìS†Ô+! E²5¾Vž4­»w¹|pɽiUÿʸ�Ÿö=-=û6;äû? @- 6¸¨]óíŠ_¬\›¶ŒØü°M¾Ø¸¶?‰áÍw*×=¯ÿ_uBój4hRw¿h»sAÖYN[ ~öégi¤Ä‘‡t)ó³sÏüQš±±Zï°×&?§+O»(²cÁµ³+í>NîvLnø@íJ3©OÚK>u4«ó‡^5êâÔ M«Ñ×\�ãÔa“Òg¸Æ§œÐ¯(…3¿\µ. ë4®´û(j3<=ûþõ*. –šõŽˆH‹ÌUç½|ĩڤÎ~›S�FEüß_ĺåkj4Ôâðøèƒ�âå¿�öjQ÷‘(ø¯ .8öìÈŽkμ¬Zè¹}Ò<ôh·cáf´ß­Iúì#K¨± ë¾­Ò~¼÷~ô+ì™Ê*ó>Nìzt-œ H ɵÞ1/§¼“^ñÖëo¦Žf÷†mªõ‡žôÕ<ôÃtªöàªÓ/މGŒÉYQ¿`›FiÈ|î*úÕ¤müþðËߥ·÷Ç6*·NÅï#m˜=ûÖÛ§ÿMP[€amûDv<ÿ÷Çãw?œö‰_ùسi~ùçŸ}E=GTûpPïÔ =¦}îÊö­v8$uÞ×»oñ]‘¿^ýËåi^ü&Öo±ýAÅ»¼üüKñôO¤çqï-Ëâ…<ŸÊW<úLêDWs�‚š§î{,²ã/¿ûSö›sœ#­¨_Þûj»ã^Ñm¯ÝËóÙÔY/ë¸}NZÔ¯Ü÷Ñj»CRðrnŸSý V›¿´À’³oŽæõªÒë�»ààC�¨žk œwDꌎo=¬Z®Gƒ˜>ñºX8yväoÕ¨Z® € uBœ2+f?5g!»ÊGßz¤ÀåøÎEž€ z�m9$uJÇ´\u×!-08í˜kã–3D S.51 à†ñWư‚>UxšÔÙ?.xVÝn”ç ¨¹·ÓϳøÆ@@ زAtíTæÜE3ÿ7ÆÞðT =gqtë61òëìŸS¿í!‡Ç�3nŠñÓWÄØëžˆ'ÎŒV�º–úý-öé�ꌛúLŒŸ±2Ÿ±(Ú|¸†@P��ÿ~oŒ£çÿ"Æ\ûxô�pmô)º:F^rOŒ¾ú‘(¨P‰ú[Íêf�ÿTwÀñ3bÂì5Iëý{ä|V–… E³žË®“}&…残ÍilÕ¡[�ãR‡~Ðió#›ýJ…;äå„Ù耬Cß|�ÖÅå­wKú!gß’Säe÷gá@‰Í÷l“…iD@ñ5@PuoÿG]þ@Œ¾ò¡’oúKÑl÷VYX�½ÉÏ97ü‚¥Y0�¾óÿO8"ÕïÝÿ¬œúÝ¿ :¶öõs ˜Ô}û˜2¤^™š×߻̋´Ëï“:á½úœ¾Q?ªÙ®-Rýþ“¦çœyÙ}1êʇJ”eÃý³ú-÷í˜S¿éÎMÓ¹lm€¯�À¢sËlQ¦¶;îUæEz÷?;§ƒ^Öˆ�áÞE³W§ð`}yË�ãèy?�£F_VrTÀùw¤µ¾�côUÇÈKîÕàªRߢkR�½�?lÀÙ1ôÜÛ²¹ùÙ¼ýÔ™/Üö�Ü7÷»4˦ ¤Ï >}atëzLZ  ·+Q?í0êŠK½þ°)ÿã¦-×àU@êÀ§Õÿ¯{"­Ò?ôÜÅÑgì•1ø´©<í°íÁ%§ìÖ2†_°,Òv�×?™êetnÔ;°DÝ sÖ¦µJ¹~ñuò¶j¨Ñ« €�§ÌIð#†]˜óö¾s»Q‘Î ¿p}Y0æÚÇR`�íퟷu£´ˆß�3oJu³‘…Ûç•pùF@M®pÔ˜ËSÇ=¿îœïŸæè_z_qY�ÃNJõ;¶šS÷°A?ý*L¸ Äã¦//} €+ŠßýõrœÐsû8XÝ2mÌ.=�œœ:í­÷ï¾ÁóCκ9 ã_ß�pÂÏRý ¬ �� H >cQqY¿c®Oõ[ìÓ>§~“�šäì(€J—æó§Nû‘#/ÙЀœ!ü}Æ_•uÚÓªÿX0;—ê¬/k›wd*ëÕ÷Œœúݺ›Îuh>Hƒ ¨jƒ&ÏK!@û¦Jtþ{~rÖA/tn›ÖÈæü—Xð/o›ÆÑÿ¸i_MVâ{²¡höê¡A³Ý[e» d‹¦u4x@Ð|Ï61nê³1aîºpâÌÔáöÓ%©3ŸmíWb}€-DÿI©£Ÿ:ï}'\›v uåC©¬ßÄsæû·9 gÚa`üÏVEª?þª´ðß„¹k£}a?� € º4Û­Eô›xCŒ½ñél{¿ÔñïyøÉ‘_gÿœºÙ–}�Û�‰¡çÞã¦>“ùËþîÒal©‹ýµlÐ)ž4+ëøgA@Z' Í�½4ôF@ €@ €€@  €@ €@€çž\e¿X¹v“/¶ìŠïŬÓ~¼9Ü8.štN,º~Î=uÿã‘�,}`£.Ðïà]¢ÝN{¦¿—\üý˜vâ–éï®{î½îV›æÿcï€$˲0Ž�§œÓYÕ¶�2eÛvµmÛ¶9¶í™µ\{k…æl�[‘‘U]Ù�;Ó¨Fü"â¾{Þ{»ãû½ p÷€%Ï]|Rô7¿¨µ×ÚÈà±òêáäÝÓ÷Éì”�òøÖ‡åØÂ YQ*]¸W®nôÓ:p;±¡Óäû»üñ·�ˆà‰^Ý“>r¤]$_ºr�|z¹Ë'—î•]-± ­5àv Ö6-ý�ÛsRÛ^Ó©þOmØ„êüêI6JûÀí|탮Íó¦&kÛ«%Çw}ý|‹Ÿ¼|ðA t3@³`C¥Õ«çD -ŽÆPÉØ$ÙÇü%û„Ÿdl[ñ d¬[­­¼¿d±#ÅÑÐy϶Î{NvÖï [Ig}°{}\ìPI]a‘¬C�Ï=ÕUçl¶JÄ€1Úß·²&Úå³Ï>Ó´íµ�MY^&AãÌàÿÔÒ@‰¶Œ•-µýdm™w€òÓÖKò¼~b¯ Gm˜d씜s‹³ÅêèõÌ=�’ºÔ"Žº0±WwÖï쪷pÕÆ;wÕî g»U Ì»Â-&(è['·ý­iZrÓ/{nÏCrþÿt `xÈX¸›¯ö³‚<€˜)#Üê#¬c$û¸Ÿ®khmD_û8^~ýÓ_Ê_ÿü‰±N½é—µÙJ}Ü`WÛWɳû™|ä�ѽ*mC°dŸösµuö€Öꬂp+!ôq-éU¢¿'O]Õö-5b”¨§­ ‘Ìýú5ß ÞUä°Q^zoΙ‡]m]矲Ģõf_g›U¢ÆŒÔ>@ßCðÒµçD±yÚþÂÅÅ 5ô¬Ãþ櫽½¢¿$å ”´5!¾.Ñ“Fˆ³ÕjÞ¡ýŽúP׿‚€>� aÀ ùçßÿ)?þö´}KèNþYGü=¦é;šB} <ö pÔu=3)€^ô ÛW‰þv,Ú¨í["s_€9öoV û&€©Ë,¾æyî¢'ŒÐû5\Ð6 o øÖ'_—ÿüëß’4(\Û·„½*Ì ÊSW…HRÎ@±×„éyýº¡ŸO@ê ‹¤®´˜c“ ˆ³Ù*YLMìŒáZ¸ûäNqŠþ^{âEmß2áÁcÅV2Àœí¯ëôÓÖK‚s°Ä'¹é@¿þ'f 2Gš0᤟dò—Ôåÿз@ €@ à®B�‘>Gæ\þ®QX·íºµÕk®iÝuÕn|ÒóÞÀñ’‘Ú!u›Ÿ•޳_“ÖcIí†'%3sžDX¦xÔÇ�M–Š%g¥íÄ'Ò~ú+æ½öÚw£ ˆ)m§¾$s.}Ç« 3c®Öt«rÙyóŒò…§<ÿe󎛾–ÃïKéìÃRÒqPw½"Íß‘Hët·ú¤)Ù&$è8÷u½OëM0ûâ·%9®Jkne󻿵[=€UÒºß<Ã]îd/0׫V]–ˆ�ÉnÁ@Ô€p�° qÏë2ûü7%qb†ëzÜ(›†:#Àõ /@àˆ,5óÊå$ir–O€Nã׺~ášà6 oÚû†4ïËãKwì3 Íÿ޼òu}Yÿ Rë´}w,Ìê/›kúõ*Î:æ†ì:(o?óU‰+‰“2} ÒMæþüÊ î!CD‰¹ž[²Ú«çèt­O—âÑ3$Fûtomß]×6úÉ—®ÜÓ+û Ñ^¿¬ z³LgfÍ×¶Ï@õê«æþ؉n×óÊ×» è{S¿õ9i?õe�9Ðmó�·¥q׫½=–è`|öÅoIíÆ§t ís;,N7Ô�ú=úJ;™çê×ûüŠõúN³T@×ù7Йnõ­G>�¦}oöø®ºÍÏHÛÉ/yö@à¾É^í¦§eö…oIüX§^ó9Ðéýzoš½©Ç™-G>Ð]ýÍ�ºY`õª+æº9 t†«^ÿwÕo{¾§w¹îsí3€'=wßl²W¶FÛ¾ºÉßþ·ÌWù‹çîüºÁ`×s·KTØÌn÷ (¬ßî>`ï7;öÐ3ÿu}½N×/lØ¡û¸”Î9bãu[ž5í¤)Y^ý�¶ÍÈ7÷5îê¶¿¸e¯é�xdj·á�YÓ¿û5·=ÚN}©Ç=tã†�/»Úw Àâœþ²µî‘Þôz €mzžƽ’‘6û:Ïò\ãŸ0>­Ûþœ¢Úßc P³î1�öïð—Í=ªõnË”ŠmúÊžÒ6,ð‚ÏK"ûMÓcõ«}�5±ÃtÆA÷3Ç{Lù·‡uXºÆ£^O,оä¸*m HOiÓ{t_�ëÖU­¸dBgL…Ûà?»`™Çò½®�@Çùo¸Í*Ðãõô€Ö£JxðD½öE€ fÝ㺳¿kÿžÄ�²IÛ‰OeöÅoKÅ’³fÀ_·éió¾úí/zì`›šcž«³ Jg–’öºñŸ9ºÐU¦5_tj¿Öëš}/ëã¥lÞ1i=þ±tœýšøç,“Ë”nëƧJåÒs:ð7A@õškb›–Ë_(ÀÙ±sa `§£ª 95Wœ ^lüb"€ @ @€@€ à^€ @€ € @ @€@€ € @€ @€@€ @€ € @ @€@€ € @Q£ÌŸ¼0mh»€ @@€ @€ \€ Dæ8 @øk½/ìØ‰iÃ@†ÑþKˆÁâH@$Áv) ® :! « c¶‰e‘ð0�sþŸ¸Ý>£ë.‡®ÜXneQÓ‚ ,X°`!É 5óü÷ýG Ã_ìû~èÊ�}ÿÏç/ ,X°`Á‚E ©¡ ’�¯˜¦1r·¿uÛrŒã÷ûw ,X°`Á‚‹†’ ’ºî)ýǺ.§(¥Tn®`Á‚ ,X°`ÑP’@ÒõúË2Ÿ¦u]ÊÍ,X°`Á‚ ,K2H€yžÎT¹¹Š ,X°`Á‚…$€ôbï,t+Gš(üD?ÿafæd˜™yÂ0ÌÌÌ aæ\ ÓÍM†gߤ6§³j%^ð b[î’ô)ênKWuR†>î.[ÊÀ½Å¤µ½�þùÿ@]†G†qübƒ˜ÍÒBâ›òQYe%¤¥S@Xe,¡ûÒ/¿ü”Ǩ¢…Ûã¡]ûöSbZý?$Œ²ò èÁ£ÇØO©€`‚¬kÁZ°¬…Ea6† L´“Ö¶¶¿eLú&qübƒ˜MÓÌÌLSRFæjPZQ)�SA‹�55ôïÀà?Ô¢êØq ka>¬kqíÆMzýö-kÁyÁZXK kÃ0l0 ø|ÍbòóçúüùÓ’™—/&{«×oıF€˜MÓœ½pAÄü¯€ :wñ"utvÒÁÂ"ô Ü·ZÌÌÌPXLœˆ9-;‡Þ}ø Ì¢òª#R‹>‡ÃªZ˜�Z`EÌ“gÏhÍÆM—@AQ”’™�#Èåó")=“ž¿|©ì9Âç`-Ã"¨º¶ÖÒZ0 ÃÃXÉÀC¶)t÷öȉދW¯Œú]Älª›¶m1oÙ±Sö}ÿþ�þ&ú=y¢„õ óM�c˜à¡¿´²R -´üøñ�ÖoÞBÉYät9e¿JZÀ8ܾ{EÄÆ‹7ÝM--äñz¨¡©‰.]½Šq{k¡ÃÈèˆ8GÆÆF•Ê }X Õ´@M�¥µ`† †±’€É†)”TTˆØð˜8¬0êw³©Z””ÏÅ]°b%}ûöUôMMùè?A!¢¿¦®V -îÞ€xÅÛv Ëš1��¤„ZN§4G®\¿.ûUÒ51"ãh|b\;¦†:`eVC°œªk�{ȇêjKkÁ0  c)oŸ�æÓ§ �ŽœÊ£Ç ýmÄl¦kªåä.gÉRzüô)mܺM´Ó³sa†(¡ESs³ÔÁår-kim•Û$ ‡ÝµÐcèÄ™3´sï>ÖŽ+¡V?ܸuKÛ¯Ž:*.¦Ã%¥Êi¡WKÆnZø§ýt¸¸„¢)".žŠ"²kni5TšåñGŽRzNž¼nEDŠmU±I)Mk6l‚Áh«¼ÀÇ�²�g‹‹W®PÞ²åC±]l135/†a€a,e`²a4OŸ?Ÿ¿ÏÛÐßFÌfk±uç.»–Ʀ&e´˜žöS\rêœñ‘“+ÐÚ;:Ĉø”4©‰·ß«D^øý~¬Ñåë×/¶×…2aþ &„þñ¦ja)™Y¸Ž*©® ú}öÐÛ`P£ ŸFGGÄʱ’R9Že0Ëpδµ·ÑƒCñWŽc|ôÄ ¢îžZ¿y+VÝ¡è®mò1¾ÿøA¶at(,¢ºúz ƒEEˆÙÔk'Ã0l0Œ¥ Ü�fõ†�â�mùêµFÿ6b6U ¼ÕDìŸÿ›_?0<{ã•Ñ¢¶®NÖ>øðà«‚² ¦0Nì®…Ëí±z½^½cÍ׆†† þª¨b×ï³�ƒCƒ".·Û-ûnݽ‹­Q²íóM #µâèQÊÈͧªãÇÑ/ ‹€¹*ÛãX€û�mòB# l#û­-W›Á 0!/¬ðÀ0l|ùòÙP<Þî‰òÃÇ��þ}Äl–xKƒI¾,p‡ešx(9}î„…£•½Ñow-$½}½´yûñP‹·åkÖÒ©³g¡ê"`»ˆ ZümÀ½09`ŒÕÔÖêoo-äuoûoÞ¹ƒ¶Ø6”š•­¢ç�nŸ ´ÀlÄ…sA‚{'˜&¿8.9#S{}“ã·ïß/è[¶j ——Û&/´1Îod«È �Ëí6!/¬ðÀ0l`²i('OŸ7ã�¨,i6ú÷³iZ´µ·Ë‰\Ww×ü1˜!r o~ì«…>(R²²-›& ’ø4$êƒ(¯&/1Iɘ䈿0ÄÓ¡âÅ´�àÚ Ûg-°“},×ÿËãqœØ¢½§ŠÉñ»w ú–­ZM•ÇŽÙ&/´1Âxõæ�l{¼YkÆ„¼° Ãð€JÃÀ›¬¸±ï{Ñg4ˆÙ4-ú;@ïcwïß—o½}>ŸÝµ�LLNhsÅ›„ç/]R"/´@ƒ§O£ rF¡sD‚·Ü8PC3¦–È…×oÞÀÀ`LöPýú(¦…×ý>h1::*Î�ç/_þé1˜ð§fåPYeEÅ'b¿ÿ‚qLŽß¼{'ÛøldPDòÇ.y�±ä_¶ƒ#£èåëײ�ÏÌ"?œN§ ya=† †aËm ãÝû÷rÜÞÑŽ>£AÌfj�‚Mòó‡·ïÝ£Ö¶VLþÑ–uTÑ¢»»›Â¢céØÉS¢Àûhí¦Í¿ÕCˆ ¡¡A%´ÐÒÙÕ)Ï“ —.+wŽ,eÞèðì(Ûe°ÄÛED�Œc'Ob•Œry�scÇž½²>‚Šy¿¶“@‡Ãa7-PÀÕÿ±9�ûæ,r×NB0Ra*ã|Á=e¾.'ÏœµTN¾8ƒÕ50™m“ñ©iTXZF½½½h àÅ«Wroþç ÷™�„aØ`6ü~Ÿalß½{îøËW mˆÙT-›ÿ´ð–.v÷t)£EÕ±cZ ä*ˆ§Ïž)“Z|¾ Z³a#%¦¥£¢7ú”Õy°vã&ŠILçM|J*í9p€œ.‡rZ<|üçöÿ£­l^@mß¶]»`ÚN‹ñ‰1*¯ª¢„Ôt  §ŒÜ<ºxå2ÆÄµáÁ¡T]S-�Ç?§`)MNN - €¬üQc%<6~V§Ýäí÷Ø*/._½*þ÷yK—ÑĬ^ÁQôüå 9ît:DÎôöõ˜� ÃXÐ`6¦¦& ap°_N|oݹƒ>S@Ìfk�Iþ®}ûñ}bh" ÿ8\H.—S)-0ѽqû­X»ËRÅ*ˆMÛ¶SCSƒzy¡kÁZŒŽSbZ•ýÊÞý«6†q¿#'édqwÑ[pÐk�ê,t·Ð ˜ô¨išEìPÚ]Zwó·` ½‚À#�ƒ›£¯/ç|†Ï,Ï—À¡?rÌÞ^�-*¤Eƒæ¨l Ÿ‹ª� ùGX—äÍ­o¡…Zh¡…9ô�Z”ý\u`¸ºštJÞ¬…Zh¡…moñ{ ´(û¹¨À�ïÌuJÞ¬…Zh¡…mo‘@¾¯Eõ`z½ƒ¸¼ü“É·.Èwhóæ"-´ÐB -´ÐB -€jàø¸‰‹‹³|HwÂùùY ‡M‘Zh¡…Zh¡…@5�_Yë÷ßäƒ+×ë6ËóÖ|O¯H -´ÐB -´ÐB  ªÈV®Ö½ÞA« ‡ïòÖÜB -´ÐB -´Ð0ÀÀÀOŽFï[ÿ¿ôæ�y«Zh¡…Zh¡EÉ@5øã¿iú1›Mc»Ý¶ZÞØ4oó§z´ÐB -´ÐB -Š´ª€ñøC,óØl6­¿õövóù,NN†Zh¡…Zh¡…EZÕ @~um½þ77«NX¯×y³Zh¡…Zh¡E‘@5pxø:V«egäC:oÖB -´ÐB -´(Ñ0@UÀr¹è”¼Y -´ÐB -´Ð¢D ÀU ùŽ^i?Š;wwþ˜Nû·óæÿÙâÕþ~ÞüW£ñ¸®|9=�'OŸÅîý±so7>zÏ_¼Œëï×õ·(¯þZh¡…ZZêW{çÁE²¶í_ô¾çlœ9ç Æ‰œÓ’£³MÎ9œmpGœ ØãÉ›¥ƒÄþ‚•žOwíª>Í ‡æ©§{¦nI—ÖÓÝ^ó\Sêîêj¿0q�/y÷î­L�5Ç«Óûþý;_ý}Ô쨋¬_ ‹‹�qnݹ#ÿ5æ³.vï?`” kè‚.è‚.èÂý.! qq€××ø’§Ï|ÒÑC(à«¿�š�t‘uKyüÔiÒÔÜü ÃÃÃÆ¸ðtzäÛ1ÁÊÇŒ¹óTP[W'·ïÞ•ØÄU&¹ð¢££C"ÆOÞ sŸøÙ`èö½{¦¹Ð´´¶`Ä”÷rC]h w�=ãØ1éðt°]8ìŒ! ˆ_À“¾ÂãñȨÐpu?oñõ_ðöí¬÷¨ÙQ™ÇU SfζØ6ð]INQ.&Ϙ%ƒƒ&»ðâÙógðàÅX1ñ ²ïÐ!E^Œ¼1²]TVUÉèÐpÙè0:0ƶ ox¼À1"zâd).)1Ü…ó΀ø p÷Ýg¬Ù°ñïßLu·?ƒ×¯_a½/@ÍŽºÈ8v\Û´ „>!Qc•‹«×¯ííãÖmRUS­>·¶µ*/ ¿¿_-+-+“­;€·@váÅòøINK7µ]x�¶>n¼Ü¼}[ÆMžŠãˆ‰.¬qÞ]Ð…«!„! Сðx¶]wj Š åÞýûúó«W/}õï@ÍŽºÀ°CÔü͘` �«FDÌœ·@RÒÓqWÛᢻ» 9yyjÀ°èq5a’ºó[òè¡1.Nœ>­<`.„-ÛwHYE9><¡ƒ3pýæÍváÍò¸IJK³ÞÖ{Tû ~nni–¥+âdhh0 ]œ:{Væ.\¬Ž�‘&Ê¡¤$yóæµ^�àû F‘aDÄ„iÓ%¿°P¯/*)V¿ÿ]p¨ Mö<äÿí¢.x(¯¨ø*?îtaý½EDIJF†ª'(<#b°\msúÜ9™9w¾Œ‹�ù‹—J}C½Îø„! pò´�áá!™4}¦êÀ$®Y‹e^ÀË—#XæP³ƒ.ôŸ£ŒpQU]¥ëþ6(ä³>._»f„‹§õõ²<.5ëpès?cßini `ÞÀɾƒ‡ÄãéM§ëŒhÎ㌋º§uêøÐÞÑ®Bì÷srôzt·ïÚ-�JKåEû Ù±{· 1’çšQ¡a’–™©æK@€ö°´ÔïÛ…U]è´–•—[ùqi»øúï}ݦÍê-B¥ååêÆ–'§¥É”™³0œÇxÀyÔ g ü€8ÁÙNzV–êÀ …ljËîfgc™bddË|jvÒųgÏdóöíráòeyRY)�Ëñ“§tGïpr² .¼^‰v‘–™%¥åeª]`‚D,;^Œh ûÁ™0u:j÷bêì9AcÊ>¢Y¦C îb�A.,0ÀÅ‚%Ë$-#SFg Dü p EÛ@Ç­»§?ã³@raYö ?-üø• «ïô÷÷áü�;ùnpæ! a€ÝNZZ[Õ 'Ó-;vJSsÀ�=,®‡-¶·Ôìˆ ö8 'GÄç@wÑÖÖ¦¿ÿ¢’¯u¸+ƒå ²ªÒ˜v�ºg/X„º½X´º <¿¬G=T×Ôx­Ã\Xð¨H »À¤Úú¥ý±Û~Ø%íí/ŒÙG–ÅÆË‘”ëmÍ9^¼ tä"ÇO”=ûHM]-†tcN¯v€ÎÚƒÜ\ý¹í™ ¥¥¥E/Ã1eýæ-8Æàwý½]XÕ…Î,†¯¥\Øð½tàQ[_ŸœùG@B`ø½� cÿµ¶·ÔláÂ÷àâ'vå*åaÖüXf„‹UëÖ«š9ŠÏè‹:PS[è.0¤®½xàÿO˜Y$ –.ÓŸÏœ?oÌ>²,6¯Š´ÞÖœãEÀ»ÀcQ»zûzõ²˜„D¯v‰gÃñ3ÐoÍhnnÆg/Šþž|¶µµÕŸÛ…e]èÌ>|ôèëýøÚ… ß;ÀÈAÔ–—Ÿïgþ€¸ëx.ÏëUg¾ú»¨ÙIèìa˜ãÙ 0äÏv{Ýý=uæ¬1.róóôÝm\èáyÌÛwïâ5gXŽÿb4@À»À³ªKVÄb´>cR@Ý:<jÙµ7ÕñÀ@ »ðbilœìÞ¿wã¼èéé6fq\àŽ+Ž§Ïž•ŽŽv¹xùŠ|&‡“’± ³†�Ìëw°¯465¢màwÕ±m“®~3&En–u¡3[üð¡•ÇÚ… ß»w÷q®È+(PÇ˪êjéííq™„0 „Àà`¿#ܼ}Kwrúúz}öwQ³S.úû{%bÜÔüY6nÝ*}F¸¨uݦMŸu1*$L*W˜â ̆­€Žz¹i.–®ˆ…ƒO¸ríªQ.,8ç/^PÇI¼š ÇD¼ópR’^�WÀÝ»Ÿ­?777©vÑÐX¯XŸ€ßWo™:k¶Ü¾{ÇßÛ…e]ª3[RlåDZvaÃ÷®éêòÈ®½ûdìä)2&,#¦ð6Gœ1 „!þ æ7néi½Ïþ.jvÊ.T2Ž“ ‰2vÒdù.(DÂÇŽW�;wï" Àv&¸ÐôõõHÖñãjâ'ø˜0ušš7¢©©Ñ4šººZ½o´·?Ç23\XãvtAtA„W„0@§Ó(P3]Ð]Ð]Ð]Ð… .!®a€;°F�šé‚.è‚.è‚.è‚.lpAqw@€ÞÞn£@ÍtAtAtAtA6¸ „¸7 „ܼyUº»;¥§§Ëð >j¦ º  º  º  º°Á!Ľ!¤°0Gššêq’6‚ÆÆz)(È¡ º  º  º  º°Ã!Ľ!CÖ²³oãÄ…ô: A�¨ÏéÑ]Ð]Ð]Ð]Øà‚âꀂRk ] h rQ+]Ð]Ð]Ð]Ð…Í.! !„B!„€B!„B! !„B!„„B!„Ba@!„B!„„ðU€EEy?K/jD­tAtAtAtA6¸ „¸? „�ÿœœlùé§åÏ?ÿ hPcNÎ=¼ª‡.è‚.è‚.è‚.è„÷„�’’|ùå—ŸåãÇ�_ë|”ŸþIŠ‹ è‚.è‚.è‚.è‚.ìpAqo@Áеþ%¿ÿþ›|øð5Ó]Ð]Ð]Ð]Øá‚âÞ€rãÆùí·_�'iÔLtAtAtAtaƒ Bˆ»Büúë/F�šé‚.è‚.è‚.è‚.lpAqu@<£çð|\^A�ÌY¸Hþ÷ûъƦ&¬ó)¨ÙIïß¿“k7nÈʵëdòŒ™ò}H˜Ìœ7_Ò³ŽÉëׯ�rÑßß'éYY²46NB£ÇIHT´Ì_²T®ß¼%ï|oŽ küÃ]Ð]Ð]B\ÂsÛ¹›�-ÓfÏA§ß‹†ÆF¬÷)¨ÙI —-GíŸeö‚…òæí#\`Öäsçÿ[»÷0§]Xã.è‚.è‚.è‚âê€èˆÙÎÒ±ªS÷}p¨¬Û´Yý ê°Þ§ f']œ¿xI‚#¢$5#SŠJJ¤¶®NŽ�<)ÿ5F99~ê”1.®\»&ÓçÌ“ —/ËãÊ'Rüð¡¬ß¼E·�ç/^¸ß…óáâæ�;r89ÙXuOŸJÂê5òã�ïÝÝ.¸�Ð]B\”¶sïþ}IJM“žžyöü™îà=m¨ÇzŸ‚š�tñêõ+éíëýdùÆ­Û”“øU«�qñöí<áµìåˆÜÏÉq» ç1ÀÚÉä³äú­[ƺy9"¡Qcåá£GînÜGè‚.!îaðîÝ[ŸÒÚÖªÜÕòñßGÍ.qáÍ®½û”“EËbŒv14<¤´“]Xc†‹[wîHô¤ÉòêÕK£]¤efÊ’˜Xw· î#tA„W„0ÀÝ5ŸÒÒª ÷õßGÍnq¡Á]ï S§)'{2ÒÅàР<­¯—Õë7(3ç-�7o^é³\Ì_¼TŽ�2oÑÙè°ÞÇ þû¨Ù.0,qÒô™ÊžSìëë5Ä…5—®^Õ�D 0Ù0¹]\¹~ÒÅß;qÏ3ïCºÑAÃ0ï��þ€tQZV¦Žƒ}ý}Ÿ¬C§ô¯Žì€×rtdãV­öZV]SƒQ#j$Í‘”W¹@'=rüDÙ³ÿ€ÔÔÕªóbL|‚׿ÀƒÜ\k7Î{c@Bü#ö) � :@Rïã¿�šw�!Šæxµ‹ÀrÃ\ÀÃg—_ºrE¹ù.8÷îwá¸ÈËÏÇp^tŒwÐQY¹v�Ñ.pL˜:k޲�ÎãÑ””€tñ¢ýŽƒØ>YçñxTG¶¨¤Äkù‚¥Ëðh~þ {Çÿ¯µµÕ5.žTV¢¼W/‹IH”#É)úsPD$æ°vã¼7„0 Ä/Üaµ�¶gm˜á]‘_P €{ÙÙzygW'¶µÔì¤ ÜyÐ3ÝãB6½½=^`»@wÑÑÑ.!‘Ñêч+×®©»6žyæÜy ŽŒV~/�q¿ 1À…~dÇÓ]Ü=tô¨Ñ.’R1ÁÛlÕi¼}÷®|3&H*«*Òî@c¾ƒ¼‚éðt`Ôœ>GlÛù&CÄdvèØâñ̤�ŽªZßÓÓ-§Ïž•Òò2œƒ1Ç \¡ƒì---ê<ˆ'Î /_‘ïCÂäpR²Þ@öƒ_ëÆQo a@ˆ_ƒƒý¶³fÃFËg›¯\»Šmí5;ê"ëøñ/zø.(Û¼‹ã'O~ÑCpdæˆp¿ §1Àfì>{á¼ñ.ºº;eLX„ë³ÅãY\R¬—%®Y+s,ÂcT碫Ë#»ö“§à»Ç�j8Pëzz»eßÁƒª£‹×ã-Y+O*Ÿèßmh¬—åñ 1n‚zSÂÔY³åöÝ;®sqþâõo ‰+·nU× ‡“’ôzÔvï~ö׺qÔBâÀÀ@Ÿí¬Ù°Á2¸|õ*¶µÔ쨋�»w[Ø.à]ôôtÉ�»weíÆ�2cî<ÕáÇ]ÜÙÛ{à€465`;÷»p\¤¦§«6Òßßk´‹SgΨNKoo·{Û÷º  WCBà¢Ú(P3]Ð]ø�‹íÏÕ�ºû9Œu�Nÿ„©Óä̹sînÜGè‚.Ü ! aÐ××c¨™.è‚.üËž{_µn�±.ò ò%rÂDéìò¸»]p¡ ºp5„0 „î,j¦ º  ÿrñìy›<þÌhõ OÝß.¸�Ð]¸BBnÞ¼*ÝÝ�xÛ01j¦ º  º  º  º°Á…{!„!¤°0Gššêq’6‚ÆÆz)(È¡ º  º  º  º°Ã…{!„!CÖ²³oãÄ…ô: A�¨ÏéÑ]Ð]Ð]Ð]ØàÂÕ€‚Rk ] h rQ+]Ð]Ð]Ð]Ð…Í.! !„B!„€B!„B! !„B!„„B!„Ba@!„B!„„ðU€EEy?K/jD­tAtAtAtA6¸p?„0 „�ÿœœlùé§åÏ?ÿ hPcNÎ=¼ª‡.è‚.è‚.è‚.èÂî…„�’’|ùå—ŸåãÇ�_ë|”ŸþIŠ‹ è‚.è‚.è‚.è‚.ìpá^a@Áеþ%¿ÿþ›|øð5Ó]Ð]Ð]Ð]Øá½€rãÆùí·_�'iÔLtAtAtAtaƒ wCBüúë/F�šé‚.è‚.è‚.è‚.lpána@<£ç Þ½{+ǎˤé3å»àPüŸ±ë}j¶patAtAtAtaƒ WCB`âÛy÷þ�,‹‹—ÿý~ô'¬HX)ïß¿Ãv¾5[¸0º  º  º  º°Á…«!„! ðúÛ9é’îð§¤gHÅ“'ràð½ìÆ­[ØÎ' fkÎCæºèì씸•«$qí:ã\tvuʲØx!k7n’‘‘a½®¯¯WB£ÇIÅãÇF¶‹·oߨãeAQ‘Aí‚Ç‹|�ïž.Üï�! ñ‹'I[ÁÝýésæª ×öìõZ¾fÃFµ|IÌ ,ó ¨ÙÚ…óÐ…¹.ZZ[°_àQã\lÞ¶]6nÝ&MÍMŸ ™Ç�ëu¶l•]{÷Û.pÌD»(.)1¨]ðx‘ž•%KWÄÑ…û½1 „!~à|[©ohÐwú+ž<öZ—›Ÿ¯×uuwa™Ý f ¦à¼‹™óà»ÿ"§Í0®]457ëÀ´v1}οw¿zÍ'ÇÄgÏŸÉ©³geîÂÅ2*4\"'L”CIIòæÍký{!QcåÄéÓ2oñ.¦M—üÂB׺°ª'("JR22TAá‘RYU…åj›ÓçÎÉ̹óÕcCó/•ú†zǼ1 „!þàäg+ç/^T'ß1៬ÃEÖXf3¨ÙÂ…)8­M›¿†Ã¼‹áá!/jëêÔ>ñmPÈ'ë°Ï²‹†Æ™4}êWá˜Ãþ×oÞbÆ>b:?è›âbï�ƒ2yÆ,Õö«ª«°Oà¿zý…K—ÿmx¸eÇŽ€p‘š‘�;Ù^ËêžÖ)ííêÜù͘`¹Ÿ“£×£Ã¼}×nyTZ*/Ú_ÈŽÝ»%,zœ¼~ýÊe.¾¾žu›6Kùã )-/—W¯^ªåÉii2eæ,õXŒÇÓ!eåå208à˜7„0 ÄœØlåì… ‘Ÿ¬Ã_XpÆ2»AÍÖ.œ‡.Ìq1sÞ|½X±yûŽ€o¸¸ÇÝ[ü\ZV¦.À=�|Fbô>5V*««ŒÙGÐÆMž*�•sçËáäd㎘8wILì·Y°d™¤edâg€Ž,:¸ú3&ÎÄñ�Z÷»°¬G· Œ’*¯¨p�7„0 Ä\lÛÊýœ8� ×ôZ‡ËÁ“ÊJ,³Ôláœw�»û®ù%ð<|À»øOSö‘ÁÁu÷÷úÍ›êŽÜø)SÕà-;v"<4òx9~¢ÔÖÕu¼Àl´ýÉ3f¢Mx­ëïï—öööÏÒÓÓ.RÒÓeqÌ ¯emmmj?€tZáçhJª^ÿWG6WÆðwlÓÒÚêJÿi=�ücÔŒq�7„0 ÄÜQ³<Û�(Àð<¯ursõºŽŽ,³Ôláœw1s®eÇÏ`×.žÖ×ÿ=@ˆ‰íBs$%EV$®T�ýI3fÊñS§ÔÛðó�{÷Œ<^Œ�4íäv�ó:zê�I ½Ö�ûû³Ï€7J„‹ä4Õ‘ÕŸÑáE´gÿ©©«ÅÐw¼1û Ötdq~ÕŸÛžµ)'---.rñß×0:5õõ÷¹ÆBâ.®m']\¸á$ºc÷¯uú5€+bñÙ f ¦à¼‹_×.êž>Õ€‰íTUWKpd´4·4ã®/|`ĈZ·eû<ßkâñoCÀ�mcÚ:üSgÍ‘ý‡«ÎÛÑ”ãŽ�hës.ÒŸ1Z�Ho_¯^“�(G’µ ŠˆÄcuúsk[«Ú‡š››]ä⿯`X>jÊËÏw�7„0 Ä Ë·�§Në]Rjš<,}$ûÒˮݸ�í|jvÒ…˜�“\åæçy¯3Ð…7f»Ào…é�>\¸Ÿ:sV/Ã�] ÕÅó¾ã§LÃãÚ‚�3çÏ㮤1íç‹)3g«NÛí»wå›1ARYUiÔñâÒÕ«2*$L=…‰Qq7ÙÓgÏJGG»\¼|E½âpR²þtd³<Пñ;8¦à÷]æâ¿©GƒÉA1G‚±O‡ {{{󯀄øE08Øo;½½Ý²`é²ÏÞáÅß��>lç P³“.¼X¸€ñv`  kÌqQS[­]d�8!ó—,õÚ'>zˆ‘D˜L3sc�qí¢»»S¢&L’¹9F´ ÌÖŽ} ¸¤X/ë!ç,X$}}½Æ/ðJÃe±qª3;{ÁBu>=ñ‚DŒ› ^[·qëV5šîpR’þ¼-âÞýlý¹¹¹ISë]éâ?¬GÓÕåQo ;yŠŒ ‹ÀuÚ�cÞ€¿p!í p¢>tô¨Œû{"/ÜÅKJM•žž.¬÷¨Ùa<£ªƒ�Î.–ëÂs\465HlâJIX½Æ¿\°]Ð]Ð]¸B ¿¿×$P³k\txÚeth¸Ì]¸Èÿ]°]Ð]Ð]Ð]¸B ¯¯Ç$P³k\¤efª!®%KüßÛ]Ð]Ð]Ð…«!„! ð\œI f׸Àïë7oÐE`´ º  º  º  ÷BBÈÍ›W1±žÃ7ÌC€šé‚.è‚.è‚.è‚.lpá^a@),Ì‘¦¦zœ¤� ±±^ rè‚.è‚.è‚.è‚.ìpá^a@Á�µììÛ8q!½hP#jÅsztAtAtAtA6¸p5„0 „à„…ÔCך‚‚\ÔJtAtAtAta‡‹€„„B!„Ba@!„B!„„B!„Ba@!„B!„�ÿž’„3ª lŒIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/appdata-screenshots/0.12/manual.png000066400000000000000000002015051526573132500330450ustar00rootroot00000000000000‰PNG  IHDR@•Õ IDATxìÜfÃPÇá×£À¥Ùz²Í@µÇ˜� ÐR½ÁŒ•V^¥Y`•éX–Ç6µ� ñ…’üxáû´†£Ñh²Z­‹¢¨ÞŽÇæt:Q×uSÅëz½~Ȳì*mýÖà|ü_ÌçóÛªª>ÚƒÍ~¿oÅ&Æ舴åÓ¦OÛ>müétz“6ÿO¦ñ_–e{8žÉ€Î‰¿Ê²üœÍf×iû‡ñx<9ïéƒ]ÿF€:˲˰\.ïÓ ú þ³X,îÂn·{ ¿`»Ý>…<Ïúk³yi‚Ûþ ßÒöýÿQ@øbï,·É¡ ü°ËÌôgÃ`†¸ÍÌÌÃÌ ‰)ôw]ÊZ;=ŒNÎIýøNZu¥nõPë–`!‡‰'OŠ×0dqeU–V-âòz¥P*ÉÎÎö¾ôç굫2»°(•ZͤïîîÈ‘cG%ŽÈŠÕ¦úëö®I¹Z•ÍÍêì ÛÛ[ª¿>åƒ!„B€B!�nW%¯óKËb‚*¹^µÙÅë3?0Àh4”5ït$þF0(‘X\œ¯Ø].˜4!„„By˜AGò¿ÑÛ0Í´÷z½e䋥œI�̳ý[[›øI€BÙgð=ô‡‚2´6 % #F€BÙO\¯2nß¾õÔä6�ͨøÅåµ:àÒå˺Îp8�T&£–å[ÉäòøØ?w³ûÙ|AÅV,V˜&`0諲Ýé’­í­g&âÉtF<>Cõ5•ÉJ¿ßƒŽºn­QWÚÅK—t;ÔÅÛ Ð—F³¥ëc‹A±TV« Æ÷uz<¸‡é¹»Cø ªõâ‡B!DÃÝk>e Çx}>hXµG€B0Ûú0Ø{MÈ4¨723¿ s‹KK$åü… ˜Q×q$¾ˆ/­®J¡X'µ5•È£þÍ›7Tò c&â™ln/ÙŽÇÑþ™q€¤ψ'Òê´%‹©2öö#~éÒ%U.U*O{ÝW$è‰TJ‚‘ˆä EÙØXWz8ÓuñÐð¾“v}Í�Û,¯ZTùÚõkª~(AYýlu:ª/ÅrÉô\üš`t‹Í®´+W¯ Î”!„ò˜ñÇ�S ×ï‰ÃíÑ&€gÌÄÄ_ßX?t!„<.ÑG’�xi�Tò¦Áì;m$¯ÏÎ5{}a/1†s ËÛu›K—.+-™NË…‹Ôu6—Õñ@(¤´^oã™q$ȸE£:~ñÒEh8ˆeuðÊ­vë)ï¢ûŠû›ôû÷ïAÇùZ+UÊJ;{îœn·f:^o6•Ölµ±%A]ÁàÓž‹AŽÖ:ÝŽÒÍ&ÊÓƒBˆi<5cic`ª†M`s8e}ýþá;€BÌI¿JøM‰ ,wX¶<-A’ŒÝ^¯üù÷?òÏ8y½qã:>Ø(#¹Õu‘¸ÿ53+—[Íâ�3÷ÏŒ·Úm\c%‚¾ÿÙsg•–ÍçMel#xÊ;è¾ú äߺu:L ­áLh'O�š´Ã»ëø©Ó§ ©zíŽê#–ü?õ¹N·Gk§OŸVZ._@yzB™Œ¥0®ÂøÊd LÌšoüÚ»÷fþ�Ú6×ëõ�@ᬿNüñº{÷Ž?~LJ¥¢¤Ói‰Çc‹MˆJ4!d_øé—_äíwß“ù…y ‡Cêú›o¾ÕñH$,ï¼ÿ¾|öÅ—²´´„¸jc³ÛLƒ�gÆñ ÄgfçôýƒöÛï¿«²ßïWå�>þmžÔoÝ×o¿ÿÞ¤ûýÆúZûýÏ?”f±Xt»¯¿ùf‡ õþïãÌÌSŸûå×´·Z|B!Sã¨É˜ ã+Œ³Êå’œ8q\îÝ»‹qØ2 üw“=ÿ`r� €Ù» Ô<¢( Àûêw¤†ww×5$HÜsˆ"qý?àk“là�9÷ P1SÿbâŸmt~øçGT^¼vttqyy ÀËœuxx™¿2‡å΀òŽ%À©oj*ð§¢ÈËßvðÿÔ?·DuvvDOOOœŸŸÇÉÉIÅÁÁÁ# óVæ®Ì_ÝÝÝÑÕÕ™C™b7ÀÃì øÐ/Oûóçü›g�ÊØö_þøˆžžî8;;{â…€Ü �9,‡1ƒƒƒåà(€W3ý/n _YY޶¶ÖlŸŸqáàôô4sY^x[p@pwÅô?•|‡¼··'–——_À¢ÀÒÒRô÷÷çë6v(fúŸ[ÿóÆÙß¿ÅÎÎÎ XðØÞÞŽ¿ÿäS¸™×ìP<Ìô?oûoii‰½½½°à�¹,óÙææFæ5»w“íq¶ÈÅô?Ïÿ×ÖÖ¾ E€ººÚÌi¹ ïl*vȳ àölÿÏ3eÙ*/,,DUÕ�´àPUU™Ó¶¶6ó¹ºÌo7?€ üô_n'[__‹ÙÙ™øúõë Zðøöíkæ´Ìk÷;€pþ?·“å¶²©©ÉøüùÓ ZðÈ|–9-ŸÌÜ–ùíV @P>ÿ¿´´ããcññãÇ´à�ùlbb<–——2·÷(·/¶¶¶bqq!ÆÆÆâý?öÎzIr�YâOô1,33333333333333fx€ºû‹{äðzÝ£po{ò�Œé–Üv©$Ç(S¥ÒÌúG+|2üý¿…í¯ÿþ¯>W¬VÃÆN˜ø~¼~SÇ(ý`µê7´QãÆçÛ¾~ƒTwòô™Àö#G�QæÅ‹—/íÚ�öÝwße?þô“q�&-[åÚ®(FŽ—P_ùÛá÷wvà÷ß·M[¶ZÃfÍ­P‰’V¸di«Y¯�1î~úé§ObÓ¹óè?›6sÖG™ÀW¯]g­;t´å*`¯ÕnÐÈ&M›nß}ÿ}æmõ�Ùäߥ,lŸ $ægÌÓ˜¯1ocþ&@€ BîO ‘ eH,sþü9›1C€ði€Â%JYϾý¬]§.VºB%&ÞÖ£O¿|ßûÝ»/ì¿ÅKBžò-ð÷ÙóçÔµíØ9פâÆõ§ÎœÉ7™r~ cýÆM õ•¿~g–­XiØþï¢Å­Y«6†½Œ»M›QŸ5À·ß~k�šµ0Ê ½ïklíÜ£§Õ¨[ß*ר…8� 9¡wI€ 0?cžN¨“$‚ ¤ w@H¸içÎ�µ3¦ëí'…V�Ý÷ŸþÙªÖªmÿ)Z¼@‘¿üòK¾ìûG¡"7irP~ýÆMʨK^ðû-yøÛá÷w–¿ÑoÏ_¼ø`¥ýÕë×Y%ÍáÄ0ü�nÉn‚œü»”-íÆJó6mí‹/¾ʾüê+kÕ¾uù¦3Oc¾> @€A„Ü è€éÓ§é¸�5!ØUjÖ¶2•ª¡Ú”-Y¾Âš¶jm¬.—«\•Pm&èÁoÖmØh„pÿ§X‰÷âAë?x¿u“xVƒk ›;q’±‚ÊõÕj×µYsçåh÷&\œUد¾þÚ(ïÝ€Q7`È0GZ¼¶vèÚ�kÃ`E7°³LÅÊÙã/íŸ1{íȵðæíÛàÞA(霹FÙñ“'ƒçá§Ví:‘e+W±¹ ò<�ŸR¶ÃëožÓ¬u[;wáu~;R÷m¾Æ\Ízõퟅ‹Ú­;wr$ô-+ðô%Ñ'Nž²`rÿå—6`ðP#,›‡ŽÉ„?ízV÷‡�cŒ‘eËÓ—�à¢)ø^©zMûᇼDµïÀAV¯QlÅGI�ߘMú]òÙïm¿ÿþ„ôáÞß: "ï½ÆM)#b'Ï÷e~ææm²Tذa� ‚ d#Ö¯_mk×®´U«–Ù’% mÞ¼Y6uêDkß¾�þ� ŸT`vŸƒ b ‘`Ò4Ñâàš•kÖÄcÍú Ö±kw£~Þ‚…FÝÍ[·Œï«×0ÈÓÀ¡Ãlô¸ ÔE )Ä ¯í»tµ¥+V+Ù&Oñ {÷ìzüä)å<Ë‘ H‹×ÖCGŽZ›Ž�Œ²1ã'Øêuëù]`'+ -Û¶7ì)_¥šQvþâÅÄ€¿ý§�5nÑÊð$”²+W¯yüäkG¼¿!ysæ/°R*ò\V}}v䨷ùv8÷ê×ßðɯ¿þú©.Zº,˜þÄî@4 Z{‰R¡~èÈQFtëÕ›ß{ëñ‹óÛ6/[n]zöú@8}ö,ßñ{Z+ÕjÞ¡ö�»Ð'‰�ÿ˜Mô]òÙïm¿ÿþé ‚ðòÕ+"× n£ÆNÀsÛ]òægÌÓ˜¯1ocþÆ<ŽùœæµÙƒÿ�Apóæ ;{öLÖDJèÑ?ir4”bÅD+ %áäaÌèõQBzíúu÷‚“«žMd{ÅaÜçÞýûaÒâ±5w[ÖnØ@«”éú @dÓ&¬Æ»ze+V¯ñøÉߎ¨¿;uëáîÃê¿ k÷Úß·ñ¸ÿà!c&Œ`…9 ú€„zÎoô-¤;ÜV–ù.^ºl” >ÒΞ;Ïçp²CG–y¦¯‚Êg�”[6oÝÆwHjZ÷—'=üc6ÑwÉg¿¯ýþûKò!Ú>yú”ºüD0Oc¾¦mAøüA[9"4š á¼”ïÙ·�ðf·G841g/ô÷Fh8e¬ÒN›5›Ìô±„tó¶í|'«zžì#�߇É[ˆ´xlÍ•àÈ/íÉU@ÈL^Èß±'(cEÔã';"þ&B œ�Ÿ�kúÌgGŽ}튈!Þ•7î¿}ç.ãù\�]ÏŸ¿ˆð+}Ê–Gtã@dƒ¯žœ_R |w{å“r?üc6ÑwÉg¿·ýþûKrŸt–Õ7–Ø2óúõ A$‚/”bFh/d‹�k>³�rÇîݬÄF'æ$Dƒ8¹`B‘Ùo�’�®Z³6Oöýøã�å—®\‰’¿­é Ô;Bèµ+f"êVÞ½ä/J ¹Îï'¿ZÅ&Ä:,°òÎ>|Ÿ9öm Èþoî�Í)"Sðùî½û¨ç7õ0(|õο�àTûˆK´—½ø¹’þ1›è»ä³ßÛ~ÿýÓÁ‰ünÏ?pŸ©“ @A€ ¤&²n%‘cÏ8Ö.VLˆ{xb1ƒÀ¹\H1ûŒ£„”së±ãwy²�Ìñ÷<às”´xmSgÌ4Êö<””€\ªó ÉÙÒ%?ùÛÝÀþvgÇå+Wÿëè³#ǾÍϘ÷aRÍ3†�íÚ+°¯Ým]¸s÷žñ¹s÷q÷÷Ö_½vÍù ¥ØËïî&øåñ“'Q £cÀ?f}—|ö{ÛŸîýIäæO‚P¿I³0á|Îi I� ‚ @P@Vëj7h„änÙ¾= ÕëÔcÒný þ`¢~øèQöSΟ½ÅÔC`b“ÒLg¿/ZºÌ&N™ÊJmž�Û ‘¯­€rwÍìyómÖ{´È´îk÷Þ}ì_EŠ¥Kþ<~ò·#ìoöT»,õó."S<¶Ûí;w}v䨷yoõÇóÿ]´8cŽìñA€o¾ù&°«X™²ä °å+Wa7e¬sëÚ³· 1Ç?$Ásûõ½õá$€´mÙŠ•í�ú›“5oI9Yø$ùã}!�Lãa “cÀ7f“~—|öûÚï½?í'B�q²hÉRú"•Ý‚àˆ~X¨ã3eÔIˆƒA ‚’Bjy†8t(˜ˆC09N�=ï+ÂÇ™¨»lé\O=™Ðɾ¼mÇÎØi·½2Fvf²´³ÇòZ€×VÒÙ(^¦ƒk‡.h2E}V¥ Ž$¦"d?]òçñ“¿‘cYÉf%âJÆxòí³#ǾÍ+­'·ÇúAð!xsG¶~’x…í*Y¾"{zÙ²Àvú8Ü~ "¸cÙ{žv=„’$�øÿqœbG´¿Y™F€@ À×EJ•A@˜ Ì=,dp $/xÞ%Ÿý¾ö{ï.YJ{¹íÆÍ[”%A� @A€ BæŽr A A$‚ HA� àíÛ7쫲 Õª³?‰ðGöš}úB4ìÞý{öäÉckܼ¥ 9Š:GœØôY³9òÄ.^ºhGŽóÖE‰© gõúÉÓ'6uÆ V·íÖí[Áõ”AÆÙÑãÇÉg�¸•([rZà„kÔØqöðÑÃ�? ê!\ØzâäI{öìmŠ2²½fýzöÌÛ«P¨|�ºõlÎüùQ?{ûâG;î?¸l%(U¾"ヺ€-]ÖöìÝë·/ƒã0ý€°?ücjô¸ñïýY›ìé³§¶{ï^×מñ�ìxthѦ-ãÑï£ßŒØFrùÊe„Ú�h @Aás„�péòeV‘!6¬†I Äà£prÈ« |~þüõ¶yëVW¼ua"ÆuœÏzððáð>vVeY�ü@ÏS§Os{ððAâI±•:?„ûà¡CáUâO& @ü£PÛ¶cßíæ­›Ø!�úÙÛ—€¨Êø|æìYÎÆ¶héRÊìØñã�^{óö�ß¾ ŽÃ<Þ1 ¦¯isL_{Æw²ã1 ¿�â€è÷/^`ËV®” ‚ ‚ð9C€Ž„€õ4A‚9Êìø‰|‡ `¥P&OŸÎwkשs(lß_çˆD“kTáúq“&ñ»T+¶.¬;S!׬óLB­³Bpaà}â³Í_´ˆ0þX?§Ó—ã'M¶ÎÝ{ð™( 3~‚-X¼8èê»öìå·+Óã0÷€wL¹¾f\Æôµw|gz €ßG~4k݆­ AA>gH�à0vÂÄ€Dž¿paoÞ¼Îñ7/_²Þýû¶Yñ×…ˆaÿ<#r„d“�älû發Y#¬Z³–½ìØaM[µ¶ÙóæÇÞtú’ìû¬ðs,c€UxÂÿÙãΪ?Û )÷##ã0)_xÄÿØÏ¤à÷QúÀÄ)Sþ € ‚ ‚ @ÀÂÅK¬A“fAH0!æ;wïæ»GŽ… ±Ù[çˆaì—èþé&-[An²J`ß5Ït‰â|ÀŒÙ³�/9Xíe~ä½8ÂëëK·õ‚äqä`¯ÿ_|A™U®QÓV¬ZÍsØ ï·+óãÐùÚ[–®àÆeê¾ö�ý ~9ÂO{Rl{(\²´mÙ¶-£Ào¿ý–%AA$|¦�8`ðÛº}»]¿q@ò Á>p@1’Áíܽ RdW®^y�«Ô±*lK—¯ ŒrL:$’˜c]”ˆ‘|­ZíºváâEˆ «ØÔ³;C€?éšÛ÷Þ©[w«P­:„Ï?~Lb¸”Àº XQgO¾³3´nßÁÊV®bu6J™kÁ×—dŽ/]¡Ùþ]!á$�óÛ“ùqïëø²´¾“Q¿bµDðLÛ±k—ëkÏøÎ¨�¶�8Í€¾tÉ5ñ'Z�0ðî½»$aä¤„Ž ´íAA!;ð¹  *�ˆ7$©h©2¿ûˆ A2XæºÚ Ùâ¥Ë¨ƒ(AB ŒöÏÂE ‡$yë¢DŒgŒ›8 b )³–íÚZM]†Òµ ›6Qé§]¬CR­{ï>ø0N ;?ä¿q\œÛæPà€0c㬹sS ž¾tÀÇÜkãæ-çHÙÂ%Küöd~¦ôuLY®žÉVŽÉ#™¢ˆ|ã;ó€ßGgبy‹Àõ7áFëÕ¯?b@Æ�|öì‰ ‚ ‚�ø  B€\"ÿ§i³€øƒÀ~ûÏ =±9@Æ€+–‚ ‚ Ù A�åhÈüCÀúõkAA„ìÀŸS� aþKH¸<ù)þ�½s€’+é£x>Ž=#^cl;¶¹ÞxmÛ¶9±mÛ¶m;¹ßwï¤OOÒóÒ³“žÍý�sõêU¿yµ¨ÿ­ªq<ó”ýgÉ([„B!góy´µ‘¿© €3™¶t�½Ä õ>Ô†þ²¿�Ùð[¶mî›g½—^{�Ç:P’ „B!dȸš’$I’P©R%PB!„2$’$É� „B!@’ I’ €kæ¡hݺ5.G�=0vìXT@„B!@’ I’ qᤤ¤`ÆŒ¸ëׯG­ZµpöìY!® „B€TiñâEpDI’$-\¸óçÏÃìÙ³Àÿ¡Œ= À³Ï>C ÂÎÎÁÏÏNNNHLLÄ€¬–þS,1Ê;tè___„„„ oß¾ dúôéHHH!GŽ�———a,]º¡¡¡X°`5jÞ+„Ba¯ÀñÇi¯qÜÆñÇqÏi\ë8ªt»k H’$9ªns­Ž[ÿ¯[\ªâ&—*¸Þ9áÿ ¨°@�5Àž�úéÓ§±hÑ"´hѰĦðË/¿€mðç°°0ÒµkW¼ð ¸˜G}Íš5î]»ÀÏ5jÈW_}…&Mš@!„Â^€ã3ŽÓ8^ã¸�ã7Žã4žu,É�$I@9 í 6D¯^½pàÀ³À©S§pþüy«z7ß|3Š‹‹q1[¶lájÜ~ûíøöÛoAÈäÉ“¹ŠB!„2dH’$É(c&L˜À@Üܘ÷Ýwf €Kþîáá�yóæáb¸Ïÿúë¯G�:up1;wîä½8zô(„B!dÈ�$I’ð°gϼòÊ+ À™ Ì ggg,[¶Ì")àÝwß�ÂÂB¸ººbÿþý äàÁƒ¼—eB!„� @’$I@€sæÌáþÌš5‹8"##Ę̈V­Bh2dffòó���ÍßAŸƒ†M!„B2$I’d”!Çg .×Grr2¦M›fÐ[«Ô@Û¶mñæ›o‚0Q`Íš5�þ!C† 00�ù@~þùg> ®q„B!@@VD<¾{÷KÌŸ6‡¾Ý{1cÜTÜYкÄú[×oÆ¥à½zÙå+öÓìI3pôðìݹ†ŒA«ä¦Úˆò®Žô–þ(xÝ EŸ8#ïyw¤5Ðûu`ÉýúõCýúõQ:wîŒ?ü×0B!„�  Ámy8vôÎ�=‡åó—`Àw½1¦ÿ?zäånO—hðž_>þÞJ_¾þ‰^v9ê¡V�Aüþ©?Ɖ3§ÏPh—ѤÔí¤·öGí/��û¸'Rò‚�Z'Ii!zÇ,‚ ÿ¸ `ݺu¸<} 44‡†B!„ €k؈r«‰Þÿ uoζ(Ï©š„�[¶ãÔ‰“È©’heìØ¼­Â½€œ½�ó°—C=Ó½Ù�xëÏ+º—}Ç'Ž�@½[rŒòÖ©�pþÜ9ÌŸ:§Ôm¼éŠÂw]åU]ý"U @0@÷îÝq9Þxã |òÉ'B!„�pI)À;�¿ Ò£Ù½  à-Wä¿êæPÏôj'/LøòŸWtoÝ›²@FôbumÅÂe8yü¢ÝkÙn˽Æï³ÿ�zª_¤ hˆ%K–àr,]ºçÏŸ‡B!„ €KJÀÓw=bl�àx@ÑõÀ-V×6®^Ï~âÏ¥6쟅— ÉB!„� UH ø³AîÈkYæ@Z³Ê`¹ø[ÃÁ%à…os º ²ºø :¨*b#ª ón_ä¿â†¢�œ‘ó¨'âjE”¼¦5@îS(úØù/»!££¢ý«uø;Ü’[=ÒL[ƳóYãoŒ@vO/¾ï±I)!åjp ÀªÅ+púÔiÜ[§½QÞ<¡.xÔWï/~¶Ý .ùn¢ýþø»Ýj 9+9�x�7ÅŸ“3ƒyͺ]ÛõÍõ %ÉB!„2¤¿ÆÈ­–&ú[½d%—‘[ :×,] ÖÙ·kæLž‰îMîfPZj€�ƒìÌ;}‘Z;™wù‚eo»‚™è³»{#µn 2Úø£è3g0ÐŽ®\Í"`§1À{²î÷AJQ Ò[øƒ÷Ò\`f{Ö‹¿9ÉÙÁ(üÀ…ï¹ðgC îM´eñì4&8kžÑμ7&¸j¹Ta­4lZ³dæøiàj æ 1�cóþت‘4.~ï‹Ü‘”b(Ê£:°gwõ¯ç=í�´Æ•‘Ö¤2O øý]ÝëcÑž™ú¥éó’d!„BR%33Ë#{é\¿“Õu&—Û¾iÆ  Î23ó<³Ð“¯ßüÔŒÀYt‹ò¬û|Àò¤Œ`Ëú�XΙe£,9'˜eÌZoQ71),O­`k©¹¹¶l<»-uÎ Às­},Ôë%'LùöVåT¼·í ¸Î�™X¹h9˜�F !ì‡ä€[íÝÀY{^£9ÃzFy”guä<à^KŒ 5]_[$B!„2$0Þzôe�ïßûªÄëÑ×Y•%úß‚…3æ�KÏ[$Ö»b ¥0�åVGÐ%D‡±œ³ÉFY9¶Z†Î™ëÚ_8q&ÚV i¾-; €ožpÁ´ï+•Z©U/ÿƒ£±kÛNìÙ±MbŠëu=nÓ\�A6®Ù€Œ°X» €ÜÇ<¹ú‚+/JZ=`¬˜0Y_€$@!„BÀÕ– €Mïa�E3ç3 4õÝßBáJ .ÿfyRº…Àåâ,ç}Fv–]JyÏxØ 4͵eãÙË; à;�¿òP«ÎV+8¾yë3�?øÚ.€ï…[Jº�fIá‡.\Þo¶¾ IÀÕD!„B€ €–Iõ¹”;·lGNÕ$ÓÀäs„ÉËÅ`ò½7]yOI2±ÔÜD[dp I ޶ºÆýÿ4rfOœn—À÷’gÐ[_ÖÃl}’ €«…B!„ ù5R°{û.;rMck³Ì´^ìòÈ»O¼^.@îžLÒÇ}¥>n®à W«rm9”0à»Þ 4^JJHXÇÀx/Ɖ‰'5𾬻}Í×·Ý/RYK€B!„� €Éâ˜Hîü¹s¸¿^G› Sƒ¢¬Ê›ÅÕÁ�½ûi 0ø,€'°,ë&™³ù™yϹs??¢}�àÔF[Žm<Þ±'÷ü_œð/ÎûŒê; ä¡Ö]ìK˜Äk<²·»YäF0²ýÇßn¾¾í~‘ÊR2„B!„  è' ²vùj|ûÎVz°eg£~ÛôÆ [7lÁøÁ£Qüé˜1n*—›ã왳¸§v{Ö+€�+“αœ3Èmý�Zï÷c™q>&¼ŠEmýY—×�Ú é-ýÍ´åpûnt¿á <`ÈÏýÑï›bÓ2¢÷Ö±Ç`odïÏ}Ü“§! ­As"° é­üí©o»_¤²‘ !„B!@@Œçu°E߯‹�úÍâë¢ïW¿bõ’•8¸ïNŸ:��«×ó8@]ŸÁ:åeÁkJ~ƒM¾ëŠ¢O?·?«³³Î[ÔåÙòÌ@Ï}è\vžÝÍQ>ÕM·U–@zPUT½òvx"ÃSw>̤�8´ÿ Ž:ÌŸñô]� Ú½–½ÇA½ñ^øîÞvE΃^Ì‹`G}ý"™— €ÿ±c‡6 ëºÿÆH‚Eß%¿Ä`’d`’d¼2$É0dH’° ’ ’ ’œÚ{f i!„áWB=@€Þ$ô=A=W"P"„(ÀR(¥þkÂq-×Áí´ë˜�ßa�ÌÌN“í¾ï£( ¼c8Ž•È9ô}Õñ äOE ÃÀ�t]Guü©ªªäZß3ù:õýÓ?¦¦¹ÈñÕÎúž£žçAG(¯ÿìS]×Ãðž>ª‡a€Å‹Åb€ €¦i „¸Ô¶-’$�iš8ŽC× 9‡Gs:Ï˲à)Æq¼jšçwBýB¼$ß û¾ëb¨îŸ‚úÙP?ëlЬA€²,Ù`Ø`€Åb±Øø€r¿™¦ ´N¿Ä¶mHÓ¶mÓWhÄqŒu]aYý�ÖßÐ_±ò<‡ëºÈ²ì‡]+€X$ ÂTIRBˆª¢¨B D ˆ (€„B€("$U$ �� $D(ßùpë_n7]ÎC»ošùfÞéÌf3Ün7Z­å߯�CÊÍf3ø|>bâñÈþO:¥±|vÖäc%cÿã\�²ñÙYÓù|F2™„Éd‚^¯G4Åz½í¥×ëE¹\fœàt:±Z­„ubå:14›M¡©–L§SƒAhµZ„ÃaÌçsÙsGüù|ž>Pž·o�J¥`0˜ßØn·‚ü`0@(‚N§£MâÁëõaå{úQ,¹ç´ñWØ6› cõUNó}©T‚Õj…ÇãÁh4’=Gzdmüë<þ‰ç¿#e °2PXa…•€2àUp~í%ŸN'T«UÄãqü¦Z­†t:�ëõŠÃá€H$‚N¢A’o˜b±†Ã! 0>#“ÉðË6:�T*³cC‡n·‹Ûí†F£ñ‹½3€È­iâ8I ! ©¤*U%T’�U¨T �P@�I’(‘R ¨A`>?ìc¿£ý¿ïvžîÝ?ë>{öìÎìžÙkgff *¿!š³³³ 9l2. ²œK’‡ Íà=b¼–ðš_Š»ž¼Ÿ�<úkÓô9¸£ÜsqåÔÔ”ùmCCC†÷ñõõ… ϰÏKôº+yÎããøcº¾j¾(/¿Z'!‡’!çQ2*èGÉ‚¢»×}\]]Yww·•––ÒÎ\ƒ |6oƒ¿ßßßÍ¡ªª*ع£ž-x®}„h«: Y^É'œßogkC;Ï~Ã)ÈC™æ9†º@?éqD[Ñå~þ@*É�J*©$@ºàææ…©p°&öééÉÏŸäÀ<�£ˆòX©‡h…êßßß.—/y½„GBs Í%ÉcéyÅÓs^)<Ö¾WŠÜ`GO�o5==Mø2öññ‘_ò¯§òú’_‹b#ÇQôñ2#§Œã<~>o‡‡‡ð ÚÄÄÄ�sÒë'Ï>˜Rà‡n5_þÍ®ÓÑÑï«~J/ZÎcdTÑ�‘A#z¯ûhkk£ ¯/rÂ=ÿÖ@¸<¿Ýq€!!ÔŸ¼têü?ꌪxâIÍÉmÈF XgÛ½h +Ô)±¼9…›‹AsÉ4ÏOOOÍ�ßj…Æmÿ©'$@2¤’J*©$Àoà0ÈsÂ*ÁÊÊ ž<©8ñ¸’w[8€ãµNy!“gx•b N±C‰%Ow~ú²<¥@Î%Áƒ0ä &''­··—?wF^*Ê+¡¹½0ðt···s¶ÎÎNêæ°¿¿ÏúÄÊB1×Ó�CÞ-^b—÷ͺÊq}æD(6 J9Ñ´¡ôÚù†„ö’šShÝcåÙ’/}Ϙx�]_9_ò—y�;8X'”/°WWWU?%‡‚-ç12ªèÇÈ‚ ½×}477mãããì~SPÿÑpppPÈ»_XX@ ¥2pquhrAÑTÔ‘ÓÜvOw&pA õíímwÁŸ»¯€ü}Âïÿ�×XÞ˜+éydšo×ÐЀW�;¸w ¼�Âãȶÿ±wPZÙÛ_ÃÁ(3HÎ9HÎ9GI"ˆ€«dV’Š ˆ€É‚ì"æD4 à"*æ,‚9üÍ9Ý�ß9Öì×=oOMÏ;°<Ï9÷ÌÛÝÕ•ºº§îsï­:ãXpE@å¬u÷Z�qklÀÜmÖÎcÖíªåV§lëti»�^iƒ—=Ÿ¡ô˜pGì:4n48íþ6='§»^«dsë8dŽõžv¯ \ôëwãfë2b‘Õ.Õ"2Oêß}ô*»dþSÖöVë|ÅB«™Ú˜kÙW¿ì‰D€¬©¬°ÌäÈ-FX“JÜ-±¦âNÍÊÓLÀp¹ ,Å1±šX©²B¸I7ñ©¸�âÖʊ݉®ƒO)ˆjKÑuðI”GÜzŸ>} —ÝB… E¬FŸ°žô·³úÓï”PnÈ#I ™ö¹|°ÊcicõmV=§Žåã-%†±ÊÂlóçÏ·Î�;J�ÊÂ9眃Õ/\o¿ÇÏ‘»ÐÞðÊçQíuîÉ ,`ìÑO(r¤÷ôwô8ôÕÅÿ®ùÇhFåÇ ÑeÄ{×CxüñÇ "ˆÅñ S ËH{×]wù¾‡X”é#êÄN¬W�¡Áš5kŒp,ÍĨßyç�’%\Þ(þ¸ý3Öo¼ñFú&­® .4Îó^ôïßE˜<²R7u¤íI�iÎ3†YW¢gåÊ•x™7ßµ2ŽÙ/"ª®m—ܺÝ-Ùe½®¹ÓÚ_2Ó: ›o—,Ø�²kM_HÏ1 p"é2r1÷p<⌊6`þ“6xés ì‹*wæ¼ ˜û„u½r©µë{�urKÚ=Uì˜.Ïú5zpÊ¿ut“u¾üV´øÄj•h–­õ“H ‚à¼o„œƒk¯½+3„^!(š�ØóÃ�­[·¶$qXpoëÖ­.¤E"Ž8‘ÀÉŬM�k¬Ú¹5ƒJoÁJÖwÖ&¬í(À™Ê«}ÿP�í¢Ê�bÕ¡ãe·pŸµîqMB»|®TkX·¯UÈsaà|•3«B^X¯)w§k^ >mÕΫ•v¾fñ&6hɳÖ}Üêì¨_Ž”®W-ÃK#þ½‰A\›Eä0Lž<9áÂy�‡9Xÿ"wlHÈe„|°µáÈ‘#MH­ЬÕ(¼V¯ZWoÚ yJ Œ[¿›¶Xù\)™.£nÅ”a]FÝfµ.l[Áî>öv¼eV=·&ùà%�.}¯Éë! ’­_Žú¿Ï �dá^‰D€ ®É¬e ä>Â’ÄŒã2ÏnsæÌq! ‡=X€�¬‚5z÷îMH®ûìÁÏ87á‚Úæ·IÝOóJµ¼E“ª@£zýCaÑÒ°nÒZ«.ã3�?¤AßýÊ*áUÎªŠ…>–‚�ßwæ”ÞÀùªgW� E¸øºP�NýDHD‚ ‚�$Ø5@DÁÀÊ 'Ø“Ëÿæ•:‹$U�¶}®EáµÚeZyÓv»zi±¾g:ÿÖÝ&q�5izDZ슧•²¶O'½5m>,1@XÀÀÅ;­n…öiçkkH?kðú!­ºL°¾37²!‹*Zÿ›µþ·<Îz„Xž`϶>×?„÷Þ V3µQº|�hÑþ*ë9éßx/ì'1´výgX¥üå\Ž#e¬qAýXy¹ºS×Ú%›[×+—°8¤õ›½ÕÔê­—S"@AA€äp ¨\¨2J©õžz·Ç]‹{5ëX±ç(¥¸î÷˜°–ü3­`·ëw= ¦-RØ´ÙÐ„é°Ø£X“r/Ö€¨tzÙäêƒ =Jv‡�7RÁ‚„œcWÖW°.#[³Ö#­Mï©6è¶](ÚV)ù€Â1À=�†Í³¦-.gÇî…\° §–$�Õ.ÝÒ7Äb…6à–'øíå>N^�º3è?È î­R¨²^N‰AA’Ä@áu ß¹ö3”í¯&­5¬Ó'Óù÷˜ø/^«~þEœË¬‚Íõ€ôºf}ÂUý«žSÃzM¾ +7–÷´ô­ºNÀ{ éúÅ ØÂ0p¾Óйœ·†õ œoÙq ç­QƒKÒm?ؤÉ�Ð.=9oÍÛ^é ˆ—W¨îµ]Ý%‚ ‚ "$‡ЬÅp·ê}¦”yÎóžt«ô{”ü[vÍq,»|îâXðQúQ˜ÙÖW«^¤NZšJùÊîW„7ã²nÕϯgåOIµú5{Z÷1«œE+{rõK‚hÚürγ³AÂ[v—v"‹>ýî¼.:_±ÐOÄÏ+\w‰D€ ‚ ‚Éá¶@½ª]Qq}Gqö¥g}Eâñ3½§>{óSnïÄÙ;!ž¼zþsÇV«DSo~ jõâ¶ üÿv/Á9«_£G:²¢U׉a%>ùúÅ$pËOä€?ç¹Ï�0÷ ÎEJ¯kîôñó pàý÷ßg+¬ðï‚áÇۦM›j›üÈyõ`›­óÎ;Ï“ÏáÚ˜ššªvYßÿµäó‚ ˆ0¼y~»¦ç©>‰½ Ðá2ßwÖ&©ËÔ=Ķ£(²Àž'm@ÉÍŒ (ûò#n�½ý{Œ[“v®óðÜ�'@8=Þáõ ’©ß'ð¬À›�{ „�ŸˆŸ—‰€Ck"þçŸÚO?ýd ï¼óŽ¥¤¤°'µÿ}"ÔŽ$ @"‚T9³ Ê#‹¾V�÷­ÄÏb|Îrœ¬de›½JʧÛò¯ý%3#I äi²¿~ÙOà‰Á"}™Ý'|>n^"$"®Ò±eË+\¸°ÝÿýƞϥK—¶N8ÁÎ=÷\›7ož�üÑlùòå³ .¸Àn¾ùæH€¨<\y6l°%JûBϘ1Ãî¹çãüñÇo(B?ü°9´k×ÎÖ­[g!$Ufd›"ðÍ7ß{XŸ~úévæ™gÚˆ# ><í ¢J•*vë­·xýõ×�ûæÎ�kàÍ7ß´£�>š-·8¿,ßnçŸ~ºü~ýõW3fŒ�uÖYƵ!C†°'9{lsçÏ%f> Ç…ƒ#|-Zd^x¡�xâ‰V¾|y{ä‘GÌáŽ;î°²eËÚI'�d<ÇY³fÙï¿ÿxÔ‡½Å)·\¹r¶cÇëØ±£�rÊ)Æs|öÙgé!€¨ßi§�f�;w¶o¿ý6Rq¾÷Þ{�ýÚ©y?øàƒÜóíÒ¥‹�=zÇ7Ýt“*wìØ±Æ)Z´(ž(‘åò›sÉ´“qxñÅé»uëÆê¾vê²dÉã™�Ý»w[ݺuíä“O¶üùóù}öÙg±ßŸðXÈhÜ„•ÖûÎDÕÇ�é+VX‘"EŒw‘wø‡~p×¼eG½÷‚ ˆ88"Ežó°¤‡žéûÕà•Ëh7¶Ñcõø,+ØÍZ^aUê˜>v=W*®ÿáÝXŒ�sÄüÓ¶@¬{§¡ó¸ÆÂw‡@Û9×ñÒ›­Bnÿ ìÚ€‡CÅ|eÜ9_^"$"rP»vmC¹þä“Oì¸ã޳�ÚçŸnœ;ꨣ e‹‰4JÝk¯½fo½õ–U¨P!L8¥:2W^Ïž=í»ï¾3”®ñEšÉþòåËíË/¿´™3g¦)²`ñâÅÖ¡C !©2#Û”ÿÆ�Û|`x%TªTÉ&Mš”aaLœ8Ñ:uêäÚ„"ˆB›v\½zõ´þ4h�¡°¬_¿>ОéÓ§§)so¼ñ†Q�Q£F… ,çÀá®»î2®—,YÒþñ�X¡B…Œg÷Þ{ïAÚ¤‘W_}µ•*UŠc”¬À˜CªU«fõêÕKtL?‡ÓS„ß�/ q”^ÚØ¬Y3»á†¬N�:�*œ‡„ IÏ8#„ ç#ß ‚£iÓ¦ÆïâÅ‹Ç"²ÚΚ5kò›þõ¶ËÝ›;wnã=à¹ÒŒ=šw‡4�±ßŸðXÈhÜ„�6ò�ɰ>nL7lØÐöîÝk/½ôí¥�îš·ìè÷^"ÊŠÿlE‡²×{ڽͧ“úÕ»'¼·ûØÕX”ÃÊf@\Ü|Ç!·dIÁÆZML>çûݸٺŒºÍXo€|ûÎÜ`œïzÕ2È€@›ØæŽkìÀÖ{¸Æ»º�&Çnë¾q«�óXöi{ó6£XŸ€íÙí �GÛ‹§i»þc™µhw•µéqM¬¼>  8+ÀÅž 1Ö´?þøÃ{ì1®3±Æú°8>ôÐCaÀ›‡+ïé§Ÿvº´k¤G‰œ={6VÏta�?þ¸åÍ›×BÈz™ž6…A¾Ôï•W^1¬ÞX3*#ŒíÛ·ÖXÚ×»woúŒåžc”³É“'»þ„hpeò+V¬˜}üñÇæ€UËp7Ÿð¸£U«VÆõmÛ¶ Vë§žzÊÚ´ic\»ï¾ûœWÇ(£�1—+W.H žYø8�bÍ1òÅ_ üÆú›Pg½Žy¶œÃzÌ1Ä xõÕW å’sÿûßíå—_¶(¸z¹qÅøCõÉ·¥•ßxxÚ¸÷¹çž3‡sÎ9oÈ4ÚÉ3á=Š÷þ„Ç‚gÜ8øÓF¾3Öá7Š¿íb<¸k¾²£Þ{AD€Rè‹uo×FÂmöœ5Ùç%€Þ¸ÁÀ,+ØìcÏÎÝ®Znìí?pÑNöôÇ¥�|±ì'hWŠ¡`“†ÅïØŸß�êõ+ÿ9špmÁ‹‚uh7»ô�µÑ{¨^´n¸¯ðrø+Þ +ûã+¯ƒOHDˆØ³gO@©ÅÚW±bE0`@ÚÄEeÎ�ß!À›‡+oß¾}æà®��;wîÙX2[´ha»ví2&ò¤ YÕ³^¦§M!`‰ä¤D =¤€§]`mÆ�¥…¾/P €€Õü™gžqý )�(?Êä8 yòä ?‡,çaà~Îõ¯¾úÊÂÀZî”X\­q[)αŽñ2p(X° Ï.aú¶mÛrœN°;à�Á9ÂJ"àQðc]�uLÛ †Üøòµ+LŠ8…o—W{Hš8ïOx,xÆ�ƒ/­÷�‰¨~±îSŽ»æ-ÛÿÞ ‚ @€D"‘†€žtc…ÃBIœ¯³À»ëX"±”9àê"|y„Ë ÿòË/†u`!%×^”MÒþßÿýŸ…¿L›"<° ”&b¼3*#pùÇ=+nàÏÊ +2áü¨÷Ûo¿X›%&t_–óñÕr†ë�>úhš@ÿþý±æ†=°äÆW„£-㎈¡î ÓçÍ1ë(8÷v\½ oXÈ�9æ÷x—dbÐyfX« çHšpcܵ“ñåoWú¼ÀæÍ›ñXá9Úõ×_OB’y<ã&„xcÌG×'€t´Ý]ó”íyïAp„ˆ‰D"@®÷(E7ndÒ�RÊu,l6nÜ8âf±TÿnU«V Þ<|“~�#ÞEoêÔ©n13瀰fƒ$ÊŒlSúöíkMš4a»=Òc�Ä;6°téRfK‹Çž?>ÇÖ«W¯L)îãÇ�ÇSÂ>üðCl,¥Äù»ûè�¤òñÕíÚµi '1êX­©?¡Î�úì³Ï&.›…ÜÜB{É*ÆÄ½»5ˆãN˜ 7Ç5jÔ`ñAóÏØ`Œá¡ÀXa‘9H\Â!Ÿ²D œsܼysÆ‚«gÒídá¾Zµjñ›1êkW�†÷ykO¼’y<ã&„xcÌgX®»µðpkð½p×|eûÞûU«VQAÀá,"$‰å‚³ÙOÅë4+¡VÎFñaA¹0àËç(¯^½«8.º(ji1怕ìëׯo!$Sfd›¢ðõ×_[Ÿ>}H�KºÛ 6€BÂõ ¤Å¥s¼fÍšÌ(î”IL8.â¸4C°@á(9„P$•�¯þ�0ì\@Œ5®ý,®æ¼í@ñçÏàÆo¤nI)Ænž1Ï-*=å³X„ þ�wÞ™¶(iY̰ÈǬ»�Æ!#Gޤ?’&‡¬ ÁóèÞ½;ž¾vEÏ?ÿúè#;ï¼ó"ò\ÿć®ïþøÖ3H¾cæ£þ?¨ß[ÿ»%@"@"‘HDˆàÏ'f¾êç?ÿüÓ~úé'KR>“¿WÏ ùñ™üóPÿÇÿÞVÏC€D€D" €ã 6X‰%ìÔSOµ3fXV¬X�Òoùò峑#GÚ\˜èÜ{ï½V¦L;ñÄ­\¹röàƒîMII±3Î8ÃfÍš•Ž<à7ç–,Yb… öæ—ѵݻw[ݺuíä“O¶üùó[·nÝì³Ï>‹ì�µk×ÚùçŸo… ²eË–ÙôéÓí¬³Î¢�¶páBsøæ›o¬_¿~vúé§Û™gži#FŒ`o?þø£ <˜ôô‰Ý|óÍ�¶ýúë¯6fÌò¤�mÈ�!öóÏ?›ôùp_`byûí·SßðóŠUÎÝwßm¥K—¶N8ÁÎ=÷\›7o^ O¶lÙÂs ��5Ê (`ÅŠ³õë×sÝ?aŽÓ·žºG�Ñpÿø&â÷ÜsyØñÇÏX³‡~Ø@Œþñäqíàô•wFŒ-ïøŽêWÞé"EŠ�žrí‡~ˆ=£Ò®[·Žñgßÿ½�k¯½ÖêׯoüñBùvß}÷Ù…^HùÜG]Ó�ßûï¿?º>ñŸerÏ ¢c~‹³ü½á|Ô»·ßâö©I½?ÔåꫯfÌZÁ‚mèСô‘ç›™Ä÷Öó�å“ó @"@"‘ˆгgOûî»ïP¾í¨£Žâ·…±yófÒ¢PÛe—]Æ’c$MéæÞfÍšÙ 7Ü`uêÔ±£�>šóL*IÇĈ{q�´cŽ9&Ýä3wîÜvÜqÇYÉ’%3Ì/£k¥€ãÑ£G[‡ÈÛzôèa‰à®¡¼\wÝuÛå—_ÎÒ¦L™Â¤ÏPŽ7nl|ð�½óÎ;V©R%›4ia+[¶¬½öÚköÖ[oY… mC‘s$Äo¼Á}Lijl‘4h“m&ðôƒ}ûí·±Ê¡môóÀ�íóÏ?GÙ äCµk׿¼Mœ8‘|h¯íÝ»×jÕªå'âö­§îQc4Pž§ÿP™¨/_¾Ü¾üòK›9s¦› Çꟈ||8¿±a¹Á"Â1 dšŽuìÙ³=Ýäyî¹ç¼ùet œsÎ9X�˜@2!ÄRh�?þxdìܹÓHŽ?üðÃÀ1ÀêÈäô•W^1‡Gy õx <ôÐC�¶A–|üñÇæ°iÓ&¼²L  ¹:¹ç§œß~û Åe“<ì±Çsù,‘¯ ÷ðÛOÄë[_Ý#Æh,€¶òüfÏž�U9ÚýÚÓ?ùxÊ8(}å‡}ãßQ÷¢x;ðŽá czÓ~úé§�†X„í¶Ûn (Š Ê§®Áñë)#«Ï2ûŸA¬oq–¿7½Ëqú-+}êARïO¸]üÙºu«÷›™Ä÷6Ão„"$IŽ"öíÛyÝ¡|ùò\ÃÚ‘¿Š *ç@Û¶mù�N°á¢Ïï/¾øÂÎ>ûìðäÓ)Þü2ºæ&£ÕªUK;�ñÔSOyû#ƒI&íæw`2ûæ›o2a…làwàI¿üò‹mß¾Ýî¼Äòâ6âôOD>ž2J_yÇaDßxÇw&<è+Þß8ãЗ¥Öó ¼ �&\þ<@^Á¾ô”‘Õg™ýÏ Ö·8Ëß›ŒÞå8ý–•>õ ©÷â˜o¾ÖøE‹y¿™I|o#¾"Dˆ8|D"‘ˆÀ¢{.ŽŸE–p» XØù]£F ù³êÕ«sÌ$ÓV¯^�¶(Ò°aرŸeòÏ y Ëßß»§ßâö©§MI¼?�ºÐ6æc,Æ&â~o#¾Þï’‰8ÜE€D"‘ˆØÂ ë –&yÿ�!ƒâ•CÁD;°0‹káÁñ¿‚ ê£}ï³ÿ]Ö÷N @"‘HDÙ‚É“''\´RàH{›çd°å–XÜÂq·f-…‘#GÚÿ ‚€Û¹€ì—õ½Dˆ�H$B¶7Þ¥K—_Œ»¾5jÔÈæÌ™ãÜ4s0âX{÷î�«+.¶ìÿ?µà ã�˜káÈ~—‰D€ ‚ ‚ @"@"‘ˆ¾újoŽAADHDH$‰‚ ‚ ˆ�ˆ�H$"„ì&*^r#’eeþ?/í¶¶ãG^o;v1iD‚ ‚‰‰Dr(‹Ý®Yf×,½'ò:׺O^&@ADHDH$’CUD(`ËÎg lÝ–m‘iþ½ÿiÛµ+’xÿý÷þv_É—ïîK*�¸å°µ×yç�¿î‡l߯‡[=þüóO¶«´³Ï>ÛråÊÅNöÖ[o™˜7ož•(QÂN9åëÚµ«}÷Ýw¾üòKkÓ¦�åÎ�ÛZ·nÍq̶þضm›]pÁ±V¬oÛ¶­ýßÿýŸEaèСöÜsÏåüú'±{Ê-·Üb¥K—¶O<Ñ.¼ðB»ÿþûujÞ¼9ãÎRRRØçßHW³fM;ùä“­B… ¶sçÎ,õÙo¼A;ìÌ3Ï$/«R¥ yçøï„  ‹€ùg¥ØW·.§;(åUÈ•b7ö»ÖzWî˜îZ­‚åmÞä›ìÛ¯¿1°tÖÂÈ|ê�[ŖݸȞ}òûú˯í‹O?·í›·Yÿ&Ýÿ§ñýw"-hÔ1Ã{+ç)a×tcƒj÷Nª‰c®7”û]¯¼™æ™—_0ÒLX|·;—P)ûé§Ÿì "ùòݤ5FÉ×Ï•sâ|Èöm\|üñÇÜ—¦´‡q÷Ýw[£íرÃ>øàëÑ£‡Õ©SÇ–-[fåÊ•³—_~ÙÞ|óM«U«–�5Ê{©wèÐ�ýéùËy)7!¼ûî»öØc�eZñmß¾½=ú裖~øa6lXή¸á†¬jÕªöüóÏD¸qã,þü6mÚd%K–´-[¶Ø7ß|cÿüç?Ó®­Y³Æ ²6oÞlŒÉ^½zYÙ²ec÷ÙÞ½{í´ÓN3ò~íµ×ìí·ß¶Y³fÙ±ÇkO¢ä € @" �î¶~ÒZëU©CÚ¹šg”³[§Þlß}ó­�w_;C MÙFöýwßÛï¿ýn¯<û¢Ýµì_¶qýCöÃw?˜:lüÿ” n«ç.O'‹®›$ƒÌ‚tcРAŒ¡ ß77fÖ®]k|x'xç§OŸnôïÀÂ… }߯\¦Þ‘uëÖãÏ píµ×Zýúõ�¼’#˜¨xJª­¸r±Í¿t¶•?ù¿åµ.ÓÐü> ºX¯‹:fHpïŠÙ‹­e©ú�ó ŠT·�÷}h?ÿø“5(\-KuTÿ »a`�ö~�©´õ.=Íš/:ÞªU>ë¿}‘ÒÐ H†7x˜t‰­G/2ï'w?gŸ±Çví'FÍýw¤¢u~ýÖ'�<øÝôÊ[ij ¹™óäIp�45/›ã%Üåtùò冋õÌ™3#•9&‰ÜÇdž /e¬e“&M2À$´[·nöÙgŸ.®•*UJ³Úro&”X½8v`¢Û¸qcÃBüÎ;ïpy2!ÅÂFzÜÆq¹MHPnåÊ•±&bIf²›¦d„1qâDëÔ©“” ”ÑÎ�;»c� C Ü1“u&È(�GuJIBÅô¸ãŽC‘AÁ¡í.mŽíÛ|ùdÚ’ˆrŽÿøÇ?¬iÓ¦NAÁê‰õe«( Þþ1û•ýòË/F¾�2€¿ÓOaøÚÕwÓ¦Mã7í¡Ïñ>p÷…û…,2Ÿ Êð¾_«V­B¹ÊУRƒ0ŠO?ý”| ÒÆ yïÛ·Ï ¨/ã›2yäãB|ýõ׆"Iÿ€«®ºÊx>ùäò'}`Ü¢HÆGΨ¿ïäK"0¾žzê)CynР�A&@Ô­[× @û ýáÙ§}ðpp¤ä^œ>£?çn\Ç}ßܸ翇~°ë®»Î8¾üòË�:L™2ÞóM ½·žï ý ÁyȲ÷Þ{Ï’#œÀê�rÛ§j—t×:Tlæ~‡ €X2kôtÃ; ÊR§÷Íc[}P€ò¹Ï·JEÏKw~îà÷%·A˜†]"@@£Qó ÅûòÙkíîÇž²}½ÅùØÀgŸïÙ¯(¼çŽ8À$’IøìÙ³QD2r!ç<÷,dX—\ /VT\Âp§Åš¸‹\¨|”@ÊXä˜Ì“'–'&ÙXƒ)æÄ麼–@¬z‰ÀD—^Ú‰õqìØ±X±9fR�¢’€‰¹«”k# }L:,�.mŽíÛ¼ùd–pž 䃢P68‡EAééÓ§Š×PjÒÆ)Ç(‘aøÚÕwáqÃïÀ9_>]ó¿_ øB’,Y²$mq¿çnì¢øA`ðPîsý7þ|#®Ý¥Eœð ,ë² b,Pé—° ç”ú;Ðÿ䓌eBQ°àã¥P€ù6àíñÅ_dkP_HBBÀõ×_ÏyOŸ ×1ß77.�— ¤'Ç„$Ž=ß”À{ëÛ¼s<'¼7n»í63A€DÀì×Ûš1+ˆu�H“<0~À?\@%üÒ¯z7ƒ(é^¾Ýa8Ð%"D<ºk—už´4Mq' `í¦'âQÇ�€½ÙÀd²K—.† n‹-l×®]Q pq_@�Á*Ädð7¬ઠø½gÏžpùLœÃyb#/&øüœO ˜“ÖY3e‰ÆǤ¸H‘"Ô «nÊXfq÷Í €¢âsãvw¬È¸cYtisl߆àÍ'N,1ù 4-Z4 Ô£ì;0öòæÍë”â£õã|¾¶Dõ�7÷¹~õåã»æ¿<¸ë®»¬aƸÅc¡N#;,X`,Žø{ÓM7=Æœž-.ôÅ‘SÅ‹7êÆîÝ»�Ð ?r^ý! —^z©%ëp…/’™Àú\cÜBp„C£¨ß¢E‹bõß Æïvc¸ïgø¾…¿7ß'ß7%�Î7~ÞŒ_ˆ !‹ ý­”â6ìôböx‘T{?µ¸½½ÿø‘©6 ob¥½ü~S ŶîO¿gZ„ßW(ƵLõO¹À–Ÿ�bÏ]�jî/óãâÅí…ý¿o,”bÕNæqË™)F=N+fÔkß_u¼âôÿæY=_[?é›ÒÕ£˜'IÜqëJýuÍñ@ÝÞùŒ€JE‚^5ó—3€‰®>Œ¼D€|ïƒ7mÞú (á¬�­€[�…þ¢€�áE=®°.–—vâÙq�Š[”xà§Ðñ…-�Þ)fnÒe¥~õÕWJ3.áä‡5×Á¹ ‡ó@‘ga.,íLÌ#€ÕŽ5ˆÉcý£>™!€‡À—•ï±(:˯K›cû6o>>`„ †5Ñ�ðÒSù‚åßáé§Ÿv.ò¬ç@9®~‘køÚÕwœß¸q£9ð›ûBÏÕ—O†×üï—•|¬è€ñCÖXç&>uêT¸Ç³Ð¢1æÄq»çG(Ê /¼�¦„^rÉ%„b`O·¢>ÖöîÝ»›9³þ.>¿eË–�sXɉñç98211H^®nŒNðpVw×.êL^1ûŒz “0d¡I“&¾o™$|ß”@:ߨ†$ã™AÞŒ=Ú„$ @ úÅŠÛmg§ øºsSí“âÅ�ó×LI§üßw^ªqmÇù©6ûÌ»y¿<»ÿ7ç¸73JþSESíîýyݺ? e¿xAª‘öösRÒœ‡(Ø\$Õ–îOûèþ¿ NùošÚ¡Ô²à#­n,À÷Æ‹¯±ÛÀÿŒøåç_ìÍ—^3êòÅ'ŸÙÎÇwØå.qëx dáÐ[lù¨Å, x˜ t‰,øô‹» üí/&ý¸ü»É;ǬêµÝ Ö´˜÷°¨ Š%Ê$i±Â娾 Á›�‡ Þ˜¼Q¬°¦cI¤]E«-$ nàW^y¥âš Ó ù;|øpK_[¢úŽú³($õ¢|\£ €È|2ºæy¿ükàVŽÛ=ë"°€"e øú‘±E™ÿûß–^,î+V¬0À3s–lÀÚ]t‘AN° Ç€˜qµ(ë5y…åŽ;îÈ1õwÞîÝq`§ŠcŽ9Æp凔ÀƒqLýV~÷ Y�·xˆ%w�w7yúååÊ•éûÌÿL£ô Ê4ï9ã–6P7Ȳ ß·L¾oŠKçÛ#¼“l›H¬/Às’€]C z«<Ålojqû¬xqk–û¿×°ò“~í9©VñÿK_y¿B�užkCòËRy@DPf…tÑy\Ùì2ƒhV¤Î!P®þ×ý†´î›©{†4*`“ºŸ�µSŽ·'–ÅïtRåÔ¢Þ<ŸÝ¶Ó>|ïÛ|Ïû×ÂÛmÓ]§ínpÛŒù™&&v¸Êè¯Ú*f]"@À#;þc®_eÄé×:ÇzO]aÛž.¬Ð‡%€tŸ¼Ì®YzO$Àµ“—ó;Ó!«W¯ÆŽ+5n¬X·2rgrMzV•fÅ}7qç/JÖ"j,¾¾I+“qâ¾YD +o¢•ê±~¹UÚCyËÅ}K–¹(0ÉuíXÚ8f›¯pÞL€™ ãþ“,pǤ™Å ð6 ö<ÇömÞ|<Jî׬ ŽÒƒòp×ç9ÑNÚ…\qÅFÝíÃ5œþã/ljàkKTßqž²3�F(txl„ž«/ßµˆ÷Ë?vJ0mBAFéÄòÍXqÊ,JÞ½÷ÞË¢m� ê€b œ%˜:R[g5ÇÕž:»÷å�Øo”ýØÈõw@y%ô ùwÎ9ç`ÑgýÖ&pm…`IÈ@BÞ!„¡„s ²‘Ý=@º>ó?SÀN#_xÀð^@DÑïû–IÀ÷Mqé¼c›ïW�5ŒgØa² b+"< úŒB)é¼ø¼xq«›+ÁöyyŠéï:75Ëkܹÿ^Ò7Î�žèžðÏN£ÿRhËà†«¦X~ÓâLß³d̉öäò¿eZj(âͳB‚…ûª�^Úžß¾Ëøàw©Ö*SÀÈ&—†‰ä0!D4ùÏK»ñýaáÚÎPˆ@vÁ-Ì&ø‘óûV@á o‡+ôá”?,¸>° !9µþ9þ>Ó7Eà}óKç’ÿ^jqâö#×ø µ8á™Ê¿Eîb†ûÿcER�u>ú+ìiºÿZ`fŸi(´¬lŸíÀðŽ åz÷Žg­RžâîüA ð˰ö @Td†X»—Ñ_�J·ÐË! à I²[Î?r~ß lˆu7k”Ëzõê¹á;àÞMyFxôÑG §ÈÑõÏap}¦oŠ  9pñ_Jº;·?‚p×wf‚`ÑAÖ€PX}NŠÍ;3Å®+˜bOMÍp}ïɆB[9Ï…ÙJt­ÞÚ~üþGûx߇֠HuÎåH sÕ–X¤0PêÐ#$"¸¥Ç.ø‘óûVpk b€ë3‹ÒñG°ðaÃ, ¸ÔwíÚ×î]ÿ‚pŸé›"ˆHND �s�¸wn[ÑTû´xq«•  yîbFúe"`÷©YP#”ÏʳS²DLh•¡ÐÖ-X)Û€ÆÔ´O?üľÿö;ëX©9çr,0ù²qns]¦€+V€D@އAADHÀÂ,È¢|UOþïùñRH�¢Øò¯ÒÉÿÝ wÞÿæ5÷/å}p¾`þo¦7H€ò¡E7ΚÀˆ¿bÚ[k�-@�eìµÝ¯Ø¿ÿn—¶êùÿ9ÀB„µ ¦_ã SåöåçÿgMSjgrÀ«�þª•ßå'‘€ ‚ ‚ @nûKÎN±Ég¤Ûì±å2e>ç¿á/%wý ¥ØÌýòô_Û.<+%�~TþbÆùW‹¥ÚªsRìò¿öî_ðW¹lç7­`Š-Úür1ÌÚ�K·4ÚK/ê›îZÍeQöÓä�;î1ðâÎÝ�óÄ÷;Eû±6xë•7¸–NFvrÐ €žuÚxÿÝ}¶åÞ vÇü¶}ó6c}‚ß~ýÍ6ï�é] ›kËF.Ô6€’#�AADˆx¸pª½ö—þÒ©öïsSñˆ\ìïŸg¤ØãES 7þ·SŠÛÆý÷_š/}z¶ \sN ü‘ް‚4��› ¥e~¼ÿÚöýyj0 @•SKÚº kìº^פ»Fì~fP%oI#}ÅÜ©æÃºÛîÈÒC¨S°ˆ5)rn–îíT¥¥­[¼ÆÞxñ5ûê‹/í—Ÿ±=o¼clجx]—ÎKÔ<½¬A–Lhÿ½’#”AAD(à�vø×¸Û­ZÞÒzànÀnåÚzí’ˆAADHDt+߯Pl/©Õ“c'" þÿγùCfÛŠ+[…\©ê'‰€ �íÐÎ;ï¼#¾-ï¿ÿ>Ûg…~4xÊÍÞ:¥¦¦º¼OmÉiír»0øßáSw�A€D íòQ‹lÑås÷ÿN9âxýá§@…üEÓÎu(ÙÌ I.o8ðàÕE" Hé9, Ö ùé§Ÿi@ï‚”¿�?þبËwß}ç«wöÕ]ã9ùï‡ @"é_£»¡àö«Þíˆ~Ø(ýÍæœhMo:ÑÊ�üß]æ]z“­½Üª+LBrØÂÝwßm¥K—¶N8ÁÎ=÷\›7ož90ñÚ²e‹.\ØH7jÔ(+P €+VÌÖ¯_ÏõLMxù½víZ;ÿüó­P¡B¶lÙ2›>}º�uÖY–/_>[¸p¡9°7õ˜1cŒkX؆ b?ÿüsZ>6l°%J×f̘a€½Ð¹Æ=÷Üs�‘îøã�7”Ň~8é>¸ÿþû3¬_Qõß|ó�±ûé§Ÿngžy¦�1‚Ém¨-1ê¥0yÊ«R¥ŠÝzë­^ýuãž¹sçxóÍ7íè£�¶/¾ø"²Ý?þø£ <ØxŽ\p�Ý|óÍ~ÿ¤ÃŠ+ŒçH9#Gޤ¬@^÷Þ{¯•)SÆN<ñD+W®œ=øàƒ�{SRRŒ¾�5kù¤«ç–,YÂsÎ(?ïµÝ»w[ݺuíä“O¶üùó[·nÝì³Ï>³b¼žççíÿ8ãÕ!îØç|Ô·!ÎûÅ}QmqcÇÓ.Ï»ã»�Ä;¾îê~ûí·ó¬ÝX�ýŒHÇþøÔ¥`Á‚6tèPž¿·¾ žeø8KýùÇùÜwß}vá…R.÷Q¦¿>ï~ÔxŽñýÈx< "$"ð˜sÉ Ö³bû#Wù?½¨5žv²aý¯Ý¦@ÚùÊyJØä.cmpÝ>‡iÛ%"&[Çwœ 8Ð>ÿüs[·n�uÔQöí·ß¦M°j×®mœŸ8q¢UªTÉÞyçÛ»w¯ÕªU+УGûá‡ìºë®3Ž/¿ür£ü)S¦\iQ€œÒôÆoP&“¹´|zöì‰å e�ºò;]yL2Q6–/_n_~ù¥Íœ9“‰mÒ}À„6º~aD×01nܸ±}ðÁFŸ’ϤI“Âm‰Ußh º<žk§N� ,^¼ØN9åëܹsÚqõêÕ3|.( eË–µ×^{ÍÞzë-«P¡‚�ðöO›7o6Ò¢P_vÙeLê9FÒ”nîmÖ¬™Ýpà V§Nƒ¸àˆõŒHW¹re{÷Ýwíå—_f¬AÖyë›àY†�³ÔŸ(ÚäûÀs饗x(Ó_Ÿˆw?r<Çø~D�Gá@�?ñ„-Z²Ô&M™jÈ¢¥K9'@@Î,ÝGòƒÆâßàÊÀÛ?a´k×θ†% pŒ€áÇó›º`¡ÄÊÌ1äFšŽìÙ³=]=�çž{Η_†×À9çœcXJQ”PÒ°Ž>þøã@Œ÷Âóü¼ýõܼˆ1ö£¿ ±Þ¯ ÛBúÌ´+úÝ�÷]ˆÿŽú a—·ëƒ8Ï(Üό׭[·úêîçàqýÉ_òAñw`¼S¦·>ï~œ1•Gôx€ò?zü„€,Þî0 DH$ÉáILʰU¬XÑ �nrŽÂ˜Ì1‘wÀ=¿ cp8ûì³ÓÕƒ¶O~^sŠSµjÕÒÎãžüÔSOYž÷"ÆóóöÔsó"ÆØ�þ6Ä{¿¢Ûï;ùîÇø.ÄGýã6üìã<#×Ï1ëîçàqý !.ïòòÖ'âÝ�3"òðŒG!» €I“§„ Ή ‘H$9‘°šäÊ•‹PgÙ OÎÓ~-ZÔ6nÜhüO̰ö�;vd™ œ·ß~;×Ê.��‡øå—_ Ë6Àå–ØP\S“í_ýˆª¯³Ž½úê«%‰øàp[âÔ7ŠÈ¨<€Ë?±ÅX³�;Æ3€{3j7ç±Ò9ì!¼ýF›6mV|” Ž@Ü1¿_|ñÅ4·s¼>ùäÜ“¹–VG¬°Ç{lÂ5€'¿ ¯¹p¬ž´ãúë¯7ÒÖ«W/ãùyû?ê¹ycìGâ½_‘m‰ñ�ˆ~÷c}²úŽzŸe¸oã<#H*Æ—Þ‹-òÕ×ó®e½?Iöxà�È+Ëõ‰3¢óˆ�Bö(ü E€‰D"Éy€€wh&HLÌQú˜(¡`…'X¸8³`V#â*‰}æz`"Hœ(yb Í*0~üx¬M¸BcÅÁrHìl¦ÊvJÇI'�dÄ·bù�:u*®¥Iö�§~1зo_kÒ¤ [†«Šu”>·%V}£€ŒÊK—.eѺ´Xõùóçǽzõò¶{ܸqFÌ.ä[µjÕì&XtÏÅñ³ð.¾ ;¿kÔ¨a,òǺÓG«W¯N[�mذa(G¾ü2¼PŽðN _ˆOæk,Ä"b<¿èþ÷�×U«VE޳8c?úÛïýŠlKŒïDô»ë»�©w4¡wØCÄø¦�ï’÷Þ{�ðÆmðÕ×ó®e½?Y€|4h`Xâ©S©R¥l„ Y®Oœ1‘GFãQ  ‘HD(1,6Æâh(~XQ°Â,&ï(_yóæ5&ž+W®Ä²X  QbI‰Í"@9ÄY£ìႊÊbYNøpcgÂJù(~X´q)Å…|Û¶mI÷�¯~q€¯¿þÚúôéƒ²È ðn…ìp[bÕ7šˆ.0é'í‚ `µãxÍš5¾vVíÆºÇgÙM`9fE|ÚH»û÷ï�È‹º/^ܰ:»|ç�wº{±Z2¨#k`I�"<ùù¯=ÿüóìÀbŠ.Óx$MD÷�wØCÄø¦ÒÑ×,¬ˆUÞW_ÿ»»?a|7¸ÎjÿŒòÊj}âŒ�ˆ<¼ãQ  ‘HD~ Ôtbñ)¬©9‚píµ×bÉd»=×?d]ÿ±ì°xpås¥Z÷±·[Ëú�>¨~~=ë|ÅB0÷ »äÖíÖmôJ«S¦µç¾äž_íÒ-­ËÈÅÖwæFãž^×ÜiõkôÈTy� 6ÆÒ¦çäŒÒÒÒe(=&Ü‘týâŒ÷äòð§O¢Ïýrr1kÜ` õœ´Î.|ÚúÏyÌzŒ¿Ãš4bò”HºÌZûÇLÇËçY÷Éë­ûu÷Y롳-õüª"AADäDP1oikÙqŒ]2ÿ)”»øÚ2TN.ªÜ™ë(ŸÖõÊ¥Ö®ïuÖqÈ-6¥fésvQÅŽ™.¥µr¡Êü¶ÞSïA©å·U+\Ûj¦4 ¿‹¯{Ð-~Æj¦6,Ó!�/¿•{X  å%«%îï(z±ÝkÑþªýùü›øxÜä­]ÿV)¹ +óì­¸Û‡•kâÞÓ”gç¶OûQ†Y­û¸ÕÜÇýÄÍ£\%¬®ÓXðÃ1êH»>×R†U/R7Ë}À‚lÄ‘»:†…û/ž~è|rϯu÷r>á½Ô»ÏŒ‡Ó�§ÿ¸¯IÓË8Nš@ùäþªçÖLª~9ŸH¾MHËNã¢È¢l)“ô5Rÿ�vØ^é¼ó΋<~ÿý÷ÝöP‚ ‚ ˆ €ä•™vý®G!ÆÊË=¸¡Ç* ¥³Y둸t£ø¢€c9&^œÆb­¸OùÄÏ7mq9Ê 1ˬd°Ä×)ß�ØzîK[¤Ž…ÎúÎÚd•N/›N�å|ÛÞÓ¬eÇѬœO¾œ§ÞéêÒ vo®± Ÿˆß¬-�¡â2`Þ“¡óÉ=¿Z%šÒg� X‡Ãë°˜} %P: %è1a-ç“& l¨;$[¿œO$ß&¤ÃÀ)ÏkÕyÏ+>äá%V)_Ù¤Ê$=ϸ똕Vþ´’ pž"�œ‚uüçŸÚO?ýd‚ ‚ dDHD�. ½®YOLpVÊeet+‹{[Ì%Tºë×èÉykÞöÊ„–iVáÊûÎí½ûèUX5cuʵ嚵¿dfB«+еŸˆ/´Å,Êõ›E÷zO»×”ç‡RˆuÙ…S°FäJ›ÞSéÃ4é0x¶ÛfŽc\È3•í2­¸�P‰ðµxõËù@òm …wP!0Q >âq’d™üãHr á‡~€°Ù³gÛ÷ߟÎu«üÇl›6m²2eÊd‰xúé§Ó¬þ“&%%Ïsà7×rAA `xóüvMÏS}rPw@P6pî1nÍAë$,ÃýnÚl�J(la¾§r¡Êx ÐN”v¢x@ÙÖnoûÀyâé�Òu ça€k}¢6q-¼aòÏÏ¿>k.p\»tKŽ3#<›@^¾Xöņ¯Å©ßaCøÚòR‰$ZX7ƒ0 Æ~¼2ý@‘|ˆˆ‰�;wZ—.],wîÜÖ¢E Ûµk—»9€B�w[,âl�Ç ïýo~”5^¬I�Ìó#†Wüp¬8 f—‘‹9> KÔ® ±ë—ó €lïsa âØKLœ8ѪT©b{öìa «S§Nà¾U«V¹<AA 9Ä ¶üBqâÜÌYP.pÅ…—o®÷»q3 �¡DßML1çYÅÞm±w0„²ØºÌmÙG}°ÐƒŽX©¿fj#,ÿ,r†"ô׹Ɯc{=ú"L°êþþ<§±?¾µís-Š6bu+´×…pçQp@¤vÉæx<`gCÖ! Å>�ÖÅÝwr ÇY~~íÜÀ5ë>v5í°.#£BF÷ÀÊ£­áÕê‘øõ‹?Þ³ã�‰™>[û×ýs·ÖÁb˜AGyÂ=:>�óE"9¼vÆŒc5jÔ°�>úˆE­^½z6räHó@A"ê×ìéâè#€:ê_‰€�øþÞ½{Û©§žJ˜�õë×ϾþúkËùA“¦LM§üÿsê´ƒEHDˆ Ž»ßM[p¯ÄÒoO~•ò—WÿJD$ AA‹–.MGܶÿÜA"$"D ¬ZϽ�楟…mÀ-O¸Å%IAAAÀãO< `ÿœ2±ÅK–rî`"ð`µõ†uú°Þäe-Ú_¥¾•ˆH ‚ ‚ "ùäëСƒµk×Î’G}‘Ävy$ƒ?þøcÿóü*MÈûå—_N;þí·ß‚Ï@Pˆ�ˆ�H$"&ŠG}´=ú裞{î9&Ü6|øps8÷Üsmþüùnµ¿�o·óÏ?¯›1c†9üúë¯6fÌ;묳¸†Õ.Í“€û6lØ`%J”H»/ Îb¿dÉ+\¸°íÛ·ÏZ¶li§�vš�|òÉVµjUÛ¶m›9¬X±‚ô–/_>9r¤]pÁ‘¾¼H›’’bcÇŽ%?+Z´¨mÚ´ÉvïÞmuëÖå^ËŸ?¿uëÖÍ>ûì3K„»ï¾ÛJ—.m'œp}hóæÍ ”³eËÚg÷߆}Æ=÷ÜC?ÚñÇO»ìá‡ö>ƒ3Î8ƒ29o F}}eÆÈ'zPïQ£FY�¬X±b¶~ýúHE3“}åî {êLÝoÑÀ³¯¾h—ÎZcõ†Ïµj—ζžS–ÛýÛv„]ÿ�D†ŒY°Þ.ÚŸGãQóíÞ'¶Ò´³ˆ4¶ï÷" €½û¯‘†µ¢€*UªØ­·Þjàõ×_§­6wî\o¾ù&ß{ñųìÀ»Y¤H;ýôÓmðàÁöÃ?Äz†€ûW¯^mÔOò��„ 3çï»ï>»ð ©e¢ˆûêxW—-[Èÿ›o¾±~ýú‘Ÿ�yæ™6bÄò„T¥½|CøÙÍ7ßœ°ß(÷ꫯæ^+X°  :”{-.È�|@¿×I}ËHç�£ßǵk×RWþÑ×6}útêG?ÚÂ… “ø_ã{—cÔÁÓ'—]vbï¾û.D»}ùå—ö?‡‰‰D"@¨^½º]sÍ5¦N�J€=ôÐCL€°T¡03)²·Þz+mÂ6hÐ &[Lîì¨£Ž²o¿ýÖ%§¿ñÆV©R%&ƒ¸¯gÏžöÝwß¡Øs¿#'a¹sçfÒd%K–´Ž;rÎ7nÌ›{Q lÞ¼™k(ãLº˜trEd˜p÷–/_Þš6mÊo+^¼¸9 < áQ€%’ëxH„Á$žú8Ð>ÿüs[·n] ¯¸¯víÚœG‰ˆì»0P.˜p._¾œ ¥Íœ930¡�È'ZYó××SfœvG�ƒiÓ¦QW{ç�wlïÞ½„¦„ocÑuqé²ìÐzô"o{r÷söù{l×~B`ÔÜG*úQç×o}’<ømM¯¼5�¦Æ�›9Oþ‘×HSó²9‘Àĉ­S§N/^l§œr .öî˜ïCR! 6äyÚK/½Ä»Ì{çîXÌo¹åÞ_¡ò#ëƒÂȵfÍšê3iÒ$O}ï*^�2Pþ©Ë|ÀØå>òD9µ²eË’žo§U¨P!a¿QnåÊ•Q±àó}�€É> þ÷:™oã)ÓïqøØ}K!‰®»î:ŽíòË/§|›2e ʼï�é÷:ŒXuðôÉÖ­[ù>òÿÓÀµ×^kmÚ´±‰D€À„­AƒjÔ¨aÿþ÷¿™Ü؉'žˆEËq“LfÜŠÉnÀªÆy€òýñÇ›–ó2eÊ ÝÓO?˜Œs_"p Á#`m¾ãŽ;˜$Û½÷Þ‹2Êu¸ók `ÂIxòriY� íË›7/;s8çœs°‚£3aÇ¢h�?þ¸…� .—Ïc�=h³³ROß@~ÔyöìÙöý÷ß;wbo>‘“_}=eÆhwô8Àë"Ðü+¾6Æ#¢ë’,ÐhÔ|o»|öZ»û±§lßGoq>6ðÙç{ìË/ßsÇ„ؾ};äÏÔz÷î�ç –RŽQ„lòäÉI(Ú¼+�mqžaX¥>X[Ÿþù8ã5Q}°Î{ëãÞÕp›ß¼¯¼òŠ9<òÈ#ä‰5Ü|ðAs€TMÐoáqÏ72û€øßëd¾ež÷Øÿ>îܹ3ÍjÎñ‡~8Yü_ãy—cÔÁÓ'\Ã[à™gž1@ø ÿWsDHDH$îï(ûL¦°hZµj…’‹« 0 0aC9H0ñtÊt@pÕuéð&pð«<“ýF�ٱNjË>Þ¤1€¥žßXaucòADçN±žÍjÕª¥µ7Ó§žzÊeËXÅŠéÃt“fò¾¾ ƒ j—.]¨»µhÑÂvíÚåËÇ3ùõÔ×SfŒ|"ÇõfBí€ûyXqˆÛWáû(×G×%yàÑý}ÓyÒÒ4Å�0€µ›žˆKDBö&ðûᅢbÌ;ǘÄ}ò+&JL2@€(ÂR˳‹;Þݘ¢~]»vu ™�ä q•Õú¸w5Üf¾9á<·äIÈoßxvã> x€Øßëd¾ež÷Øÿ>’ÆOÄÿ_ã'bÖÁÓ'x†Œ7Ž1†W ä•åˆ�ˆ�H$",$LP† Ø€XÇzõêá&KLdÔ„?0é!^þí·ßÄÇ2 ¥óa%œ˜{Îaic²Mü=Ç×J~£î&õÑyÅ 9à^ê~ýõ×s�~Jدxßï,æ®Í¡ö{ú.ˆ_~ù«­[�øVž‘7Ÿð³‹Q_O™IµÛSïÀ“ü+qûÊ݇E°2z„‘­€“÷>xÓæ­ß€ÎzÙI¸EYè/’Ø™¹Eqù'ËzàϬ›ÙäÀ˜à}Šõ ®ëÄȇ,ã±<È?\Ÿx€zÄøv%öxõÕWJ!áSä‡ÕßÏ£Dý©Á7ÅKò¢E‹’%’ù^'óNûÞcÿûèW¾c=¯Eøú„±Å7’ðº>}úXŽ‚‰‰D"@hݺµýýï'ÛpÅJN¼;q–™™PŽ?+1:¬@XGˆ?Mš 4ÁÅfÖ¯_ŸßÊ(nüüÆm™´pA�$„qøòÁÕ›I2.ü F}=e&×nwL½!pXs%håÊ•XØÂã.v_±Xm&f˜˜ï¸@¸ß|c%û‘ÿ±ׯ"Nßj�c½§®°mÏ?VèË@ºO^f×,½'’àZ�ÉËç%Š6-X°ÀmŽ×¬Y“,àVTg•|SC1Šõ !œ2Zé?\>AŒ›œ»>mdSÆõðÖ'#¥ð믿ÆÂ )Ȫñ‰v ý«áËe쳨}äkÉmNê�Žx�c¼�^å;ËÿküßÀuðô \…�(÷ð�‰D" y‚€2XL wo,¿9((~‘ÀÁ’ÿ¼´;ß®í …©øä“O´¼Þムˆ�+®¸ÂB @€D"‘ˆ�mÓÏÀ•mÖU9r¤å@:âY çÊ‘ çå è=>Ð`ÍB:ð2Ù½{·"$‰D€ ‰âŒÙ†—ZÜzYE+{…€C ÿ�½;8†Á0:Kws—\ºDfË ‘\½ UÞƒoA/?ØÎ»4ÿiã;~Ûê87kDDÀ €$€À €$€$`�@’€öµŸ$>À €$U5WcyŽ_€ ’ € ’ €ÌìµVßì�p%ûÆ«^áymë`­ᵕMÅÎÚ¶mÛ¶mÛ¶;ù^¾ªšì› N�Ì­»ê_UMOÿ;9ìï¯R¥J!22‰‰‰ iiièÚµ+*V¬È}��””h¡÷Ø®P¡Ê•+‡-Z )) ±±±Üšñ郶mÛ"99„í/Y²5kÖDùòå1{öl 4ˆm¢dÉ’˜:u*Hff&}±nÝ:Ô®]›±˜ãh€üó^¾|9ªU«Æ½ªA¸O³››cãƒGAD@LLL<< AA1ÄÄÄD€Å´{Ø9€ <~ü Û·oGƒ  Åh4bëÖ­P8uêvíÚ•Ósÿ�ü/^„–-[P«V-¶ìØ1 ¼ÿðáCÕ}žþÇ¡ûâÝ,O¿Ï~ÁÆ%kqýâU¤$%ãñýGؽ~;Ü~{ëÿ“Ÿ›~‰�k·"æåk$Ä'àèîƒöòÉå7ªë�ˆ¯ýÿüøÖû[~ÞôÅ÷ó³Âß¶hôý­+"\•çNŸ‰ ‹köŒ³`'¼æqšbE‹…ú]¿~yñüùó\m\»vMiƒÇ˜‡*¢¹Ïaûùåª9ÏrÞ P¤HÕ4…wAA@L€§fXÙ{ ül~Îy̹l#L0ñ±q ·®Ü(°Pû¾¡' -d¤gàâÉsX5{)¶­Ü„ÄøD�-{¨ü[ü ÂíÀÖ=X:u6-]Ç‚YYYˆþ.è­ý?ü>ýI I%˜Ö-X‰„¸xdfd õ¯–½ñuø[~Þtçó®çg…¿cC‡aaçÙp(QÿO} ‰ #Ö¯_“ÉR£F ܸqC5—ŸÅ»ŽرcöìÙƒiÓ¦©F\ºtI5€sþ­ض6× 60G•Ÿ¥¼)TpÀ§Ÿ~ªLux×AÄDhú_æv˜ŽIQcÐøßoòù®�{ðÝgo}�…Ï�;f:¾©ç¦zܽº#ß{Èb îÕÞ´[Ä„nAí`W¢®ÊßÛàB!WÎ^*ôßáVÃËê\þ·¯ÝBZj|œ¾Wý?˜ »âu, úã[ïoýófm|ÅÞÙü¬ÎÇèAñ ­=Ãu¿—D€óóïÝ»—3¯~À€ =zôÀï¿ÿÎ!ù,œáêꊈˆh¡ŸƒƒçÓs U ooo?¬¤�ía]UÿßãŽ%`eïÅèÿ‡åÂ\�°xò<�`Ï? ôs*Ó‹'ÍÒ¾ŸöøÿØ; ×– ¿W¸¶íääÚ¶mÛ¶mÛ¶mÛ¶mÛF¿ôd•{y½È©ÍÿUum�IWŸÙ�‹ífºƒBàú|?Ýý:„ÎXœ¸}õ¦N8¶ç°úìû·ïêë¾M»¨NþÊÒøÙºÉãm~òù䌞N }*v… ¸ÃÇù!8¶+&�Ö&Ôhy�nšmccb›í’ÿ½‰55Î~cšij\³ ®š4ÊæE,¨ÅDo¬~’h”ѽ2ødtÇ÷ºÉb'°ÕÌPž.h@¡$ÙÕÝëë®r·o}VÎ\Â…Ý òQmwŠðòé zpëž�Ÿ_8qŽÞ¿}§¸fÁÊYKi|ï‘´jöRöQÇcµé-‰/ó¬›<¾ç'ŸÏôVi^Ç™\€` _#èÚµ+1€`p,³ÝŽ<'è�5uÀóø| ›oŸ˜öÉs›h&5>"¶ýøä8ÊŸO¨ØÛiôÚú\3²>±éT¼¥Š'Î(ïÂn]¾‘ߪúÿÍ•3¹’»CïhQ8õ­ÙΖ Iæü«gË)‰¯ñ~þøIWÎ^òñs.^Çp}_®ðqs.~È¢B”Äøÿ¯uóo|CÎO:Ÿ>»¨¿ ¹cd€@ÐjJ¢v»ç{šÅN(`ãk¯mÇúuãG“Úb,‹¯©÷Œ´‰:ëW¹›[Ò“>P€‘]3oìL_ý2GJNyâdTI?·ˆã î|”¾\ÚÂ~¾cv÷ÐthÞ?[®‰ý<pÿæ]w�}¯0°U/÷ ‚øÁºÉãs~Òùt(ÚÜ1 € `·Ûq÷çûš…Ÿ}´cI5]Œ’LôÄbû|�5^Ÿ&\o0'=\ý<À€¶•š¨~þ玞¦LÕ÷ã°u®Õš>JïŒÞ½÷ñùÃ;èæåë ܆ŽY2y¾ ¾À_°nòøÆœŸt>Mr×V*§. 瀚…n˜-Ô3†Ù[kU£`ød|j@ÅٕؽðŸÞ†× ’žÌ“¨P-{úòé �·;þî¨e‹–š~ÿúE§� r`Ó’µÄTÈPÌÛzÌŽÕ[øçÀ¬ž³L_à/X7y|CÍOê¯RA€ÀIàP[‡€¬a¼woµ�‰4zi±Ð¶D¶XÃb™½õí]Ávï9o¬Lr@ßjMµðûô᣾›ƒ–/~f÷D-È€&Åk3yÀX}Üv}‰i[¹©C@ωai|ýÅë&�oÌùIçÓ®H3\€À¹`°›ïŠeë@òëæ?Ôú•;pËÀWÖ窑ôïjïvï¹´© Tеñ»zî²Ú½o^ºžï?¬®ƒ©EÙºÎ#h|ôßýî|� <Ÿ{7î¨U²–ò/•2¿5^={ÁWt@³RuíâpM>jÎEéJ§.(ˆ/ð¬›<¾ç'Ÿ·ä¿ ¹¢§‡Ì9@F«íwãV~³ã™ÕŽþ̸fµÃ_<‚gŒÊ‘Ljç�:öo?vɤQŽ¿ÚVI]J%=Íóé+ô猑V%eî¶ié:b¸ˆš×q÷dŠï\sï{+œøòg:ëP­…òÍ=µêÕÎ<}ø„öoÙCK§Ì§�‹×¨>íÌá�X r€�û÷ûòUUð_¿p5­™»\Žûõó‹ì£Þ¼|­ŽúO?É÷3£õ$šÛa:ÚB€sžÀ–Áj}cši�îš-ôÂb¡k& ­M¨QÙˆ*†º"p>™F5 os¨zŸê `7ž%RJZÙ{ «­ßiç»ûŽ�%JJ��{¿à>ùîñóÆÍ¨ºp[6µcûõ½zþR ì׬w/DžX‰©hâþZÌÊYJÑÞ�;Uâȉäñ½‡©n�*:?xg™}NbYØxýâÛs˜ÚTl,ˆ/ð—­›(¾áç'ðÏ-­ÂzWèÌÏrƒ @0²q'€å=Q¶(©±ˆ0—4÷€ÕÓ•…,ø ÕÓ—UÉOã\µ°ˆ04Mi1ŽæwšIÂi @€_€“žygÐŒ6“Ü òÁ`.cSWX›BMü€ÀèÖ0G •5È^ sã•“›�¥ÅÝæQvW¸ Ÿ˜Ðx$ÕÊX sË1 ¨Úƒšå­(ñ! »ŠE„¹êI€ÿرC*ƒ´ ýPäæþ+fÞû½€@Ñ€$ 2H’À €$fæêîß `�@’€SUÏRìnÔ?;f !„a@ˆ �ž  €Š€T½R€Þ"‚Š”�þc9rA‡³róó[ƒÅÌÌûýBÓ4AUÕÕ‡zw3¯¯ó?Žº®³Ú�5Ï3lÛ†$I°,‹ÅgeY†¢(.ñ À  ( A€¦iHÓÛ¶q�•¶má8dY†(Š0 eYòž_z3´k.;ûQ}#@&@&“ hš˲œMŸHþ9ø#°ï;ò<‡çyìÎ'ˆã®ëbGv&I‚·º®CE×øžpÃUUa]WÔu Ó4áû>·YéûþÅÞU@Wq´í©~ê†K\› ¡%-NC=‚C ·Z°,üipw¯ u\?áî¾ÿ÷Ìéܳ™»y÷ÞímKÈûœóždïìøìžyžwf–ªU«FcÆŒ¡·ß~[ÕiòäÉT¾|yú7…C8;yòäßÖO%¦ßD@LLL�I6L€ôêÕ‹jÖ¬ Oˆ&Zž¸;vì Zµj™ž9Ûð3gÎPNNŽò4V­Z•úöíK§N�"àÙgŸ¥ÐÐPºòÊ+éæ›o¦Ù³g;M¬Øxfþ¸¤éꫯ¦úõëÓúõëîÓdÿ?õÔST·n]ºîºëhéÒ¥4qâDU�5jÐüùóIƒ«#ÒÙ²e ©°‚‚°Taˆ£ñÜsÏ©ûà‘mذ!mÚ´‰�ˆ._¾ž[ÕOÙÙÙtüøq¶<ýúõS¦ñÑGÑå—_Ï2×ïl=Nœ8�¼U›Ô«W�¦OŸîªïΟ?¯â½ð Ըqc”åFþL˜ý˜,®k×®U÷;vŒ€üü|JLLDúþ{>Ë}È$¥8 $f÷LbÜmܸ‘€ 6¨k ÔÙþšÄ>ä�¦ï¿ÿ>=ðÀNýÁ�16Ìi¬@ä1b™@û =³¯ñLòϰý˜Eù}ôQ56®½öZêß¿?ÊV$�U«VáÙ·Æ3ÁåÁ>O<±dâñu*ö]Ç÷WÀÞéL»òõbÊÎÕÙl7¬цw¨�õ÷ý½k¾³ù±Âåù7@1ÄÄÄDàã�?¦³gÏzL“M&Z·nM_|ñ}øá‡C¹¹¹ž¸ AjBg iNMM¥ï¾ûË{UZ˜ìabò™™™Ißÿ½º¿L™2X‚Ì l<3ÿÑ£G«üPx›7oî—o(Hõ¤I“ÔõÀ�UþãÆ�S:�âê¨ÓéÒ¥ =z”/^Œ²â¯ü0)^¶l™"ä………˜8²À�wÞ©êõúë¯Spp0=öØclyvî܉4AJ5qÅs§~gë� .¼ÉðØ‚@FEE¹ê;L–¯]»vÖ:!&ÌvL²õÁñ@»€p|òÉ'.VðéèûÖ­[‡öQEÿú%Ê�>}ZýöÞ{¸F[üòË/ª~úÚÏ)Ú«iÓ¦ôä“Oª¾0Á´97Ƹ0v¬ Lðþ£ž¬}�tøgØ~Ì¢|±±±JÃJ(³fͲ¦Ñd dÔ3F °yðÏ/¸y'L˜P컎é“@¾Ó™våëŗݧw¨9¾!&�p;ÕßÕ{p+|›“¥ÕDhR·%=8x>¥Ïú'eÌÝC©�­ aII;!´#%]H= ·Ræ‚ýÔ5o%6íìu_óàö”½ôeÖš5jsÉ11ä €¹sçz<˜½ù曤±yófxìŠxcŠƒ�Î×_MÛ¶m£°°0%:€€`#ÏÝ»wkÄ l<3ÿ XË‚ÿý°Ãì˜5ß ØþqÌšHªn'Ï—7Ybéò9äÞu\Ÿò�δ+_/¾ìÎïPsæÌ¡øøxˆhŽevóÞœÇ ßæ$@i4šµ£Ìùû9¿¿ïLº/kª²¦–ñ)(íŽ÷ç(âž>çßôÀ€ÙtoÆdê=c·ú­Më>¶@—Ü5Ô©ËX[»õ†80b¥ÆD�-ð"Ü: ‚W“$ëê�â`†#ž)6T©RÅ3„g)::šÒÓÓ}ØxFþÈ„ÓZ�bІk³�x¢á\Gü�´5¸:BpHNNÆ¡oêD÷C‡qQkÁÄr8–^8,³Æý•*Uárêw¶X6‹û¬q\ô&ßÅÕ‰ 3ûœ¯‡¼phcÔݵÀ¤c[xá¬S§ÝsÏ=Ü3i%àXÖomWüòªu{Â+¯¼BmÛ¶Õ+ ˜6gÇÆŽ”÷ ðôcË�Ù×Ì3ÌŽYý^`ž-”‡_òypã�%–.ŸCî]ÇõI ßéL»òõâËîß;ôÕW_… ¥I¹c™Ý¼w}+|ž$@©3þ·>uŸ´�²¤f [{~�¯•@­ˆªÜØUÚ-Â;‘"ôcÖRÌU‘žßc®Ž¤^S¶+Á!ºF˜—pWò(bb"ˆ`ñÔ¼õÖ[VÒ†=ŽNqmÃAx@b¬û@1Áƒ'§bÅŠØSª½.¾l<3ä½uëVÒÀÿ¦¯4°wï^[G#~ò oÕž={ÀrRì%Å’kW =°Õ± ä;�iW¾^|Ù}‡b\‡„„Ю]»È¾Ì®Þ»€óXáÛœD(m&€&éîÖ¶]–ج‹«´;u§â'·÷ k—¢Wˆ &&9°gÏž˜pã�0ìË„·ûé]MGŽ ï –Ï+Òï/öLÂÃX¶lYLö@qxâÂÈ \<3”Ÿƒ÷ K¯[´h�p+ÁÁÞO¤‰½š.¾Ž¾L^‘·&Ç*TPûløá�E,™f'¢ðÖÂ3¦÷g#_5É…çämèºßõ5V`_÷;ï¼£âÄÅŹê;½'Ñ£NØCŒÉü¨Q£¸0£l|=pê>öÏœ9é¨s>L+W®D.s Èȃ>r„³#Œ%üü3‰3'ºuë¦Ê„¿ƒ "ø\�m,“þ׿þo)ˆ›ú [¾Í™1Æ„9�ü†± Aùá>ì/W®–O›íäó3l\£|¨;䣟�€ Ü8䉥»ç�{×ñý°w:Ó®|½ø²û.tïÞ]}5ÂWfWï]Œ5DZÂäYb €Ú^E¹iÕ-¾zÇŒ±Ü¤»i½D¯°[¯¿a8ÀU¥’‡-Rñ£«‡z…EVnDê¬�G—‹ &&p¨¼ÃØ/¯£>­ÙÅdñ@\@8±üßׇ$a²ò„o+cß&ˆöƒ²ÏÌyã$êêÕ««ÉèŠ+à�¶ �'¼²ØßìFàëÈL^A"1!DþÖï¸cù*–JGFF‚œ±Qý•œª ²rïT %%Þe”Ám¿ëkëÉî( ÂrÕwz‰ð¼yóШúùsaFÙøz o|§¼Ä)ô ¤ ¾ŽmÀ—tì±™Á_„ùûL¢Ï’’’Ð^ø‹ë€=ã+�<òˆçôó›nº mªóàÛœcL˜/cåµ×^£öíÛã`Eˆ †x6Ízù÷ ×–òáÝ€h�À Ì8äwÏ!ÿ®ãû+@ït¦]ùzñe÷]Àÿ óø €ÕøúûþÞ5ßÙüXáó,@€£®¤/ûGkqmmÇŒq _Æœÿ`+€mxÏÂ-Ô}â‹äYº?m§ÚÏwc|‘ûn�¾_‹ž´’ÒÆ°÷uÉ]K= 6‰ &&€ „Àzè¤Â²ÌÒL¶Lô¡w|Øß/œùq–¦ÿ�eáúÃý!�w�”] À6ÙÐ{ÚNMÂm ò¥Ïþ·çºEäÝ”½äuù$EVl¨~‹½&Zì×sò6Š©n9\°­º7mÄj¬0VÄý÷~õUE€Î£Ÿ¦¤Ô\/Kl’VB;XLL�Ÿƒ§KN±Œ¹eË–4tèP*­À~W,Ï…7‡¾]LÀ2YN>¬ä7Òy×IÙ"üa kÑ!ê:v}±á©�,S¤<²bÏo ãø 'üƒ¼§<¼T}1 !¤ƒWü÷>Š{ÕÊ�{3'Ó½½Wif.8€/ Òöé3€÷ô.(¡,&&€@ ÷Nc 5–aâ|xEK+°ÏßZÏÏϧ‹ èœ À„‰ð7ô‡@ÞuRv��1Yð}^‹¬Ô'ûûï9C Ã=›Æí±PZÎJµuBöýÛßeôÓX5 [ÄÄD¿€½Á.îD�3@Ì‹=àñÍÔmÂó^¿ÇßÒœ2æíU„=í±•Ú‹ï—�üwõ¤bb"ØA �@ €ƒÚ_Ey]ª:š/_¸¿ÏtEº›Ô½Ý+,öºXöÀ€9¶aé3ÿ‰pxô ÁÙâk% . @LL�@ �"üÙ†CýÔþûó kÓ¶Ÿ kŸRäw�}ìãÇù)-V÷´OêW¾ ùˆ‡•"ˆ‰‰ �@ @€?Ù@æq@æÂÔ´þ�žßãnn¦¾Óß{ú.ìù/§Ý]CQo—4”¢ªS÷I(kñ!ÛÏýá« awy� €ó’‡.ĵbb"�@ D௰„àöøöô«CýîÍ(ÄÁŠÔßs‘{›5lÏ?õƒxðûo­ñ>'èõ¹¿{Ó'uNÀðÕtO�|J²ä¢>(€˜˜€àóÏ?çO;çãñi0qð©¨[n¹…þ 蓨M˜ùòewŸoÀÁ—½Ä�+&ÄJ˜kZÿJ²@©�­0?ë÷»·ÿ%ˆïø[ðäBÑ5©Sç<ê6þYõ鿞…[(©s~G¸bb"‚ .ÐÉ“'Ý<. &¯?‹~ýõ×*Ý£G�òå6¯ŸïŸNªu{–ào,·@ D@LLLL€ŒóçÏ+‚õ /PãÆ�©fÍšÔ·o_±:sæ åääÐ 7Ü ¼Ò;uꈷcǪU«-]ºT]küúë¯ø~³Jïú믧!C†¨4Oœ8AÙÙÙT£F ªW¯MŸ>ÝvòÅwÇ÷Úk¯¥þýû#®×}øN4þGù€~ýú)Óøè£�èòË/§Ÿ~ú‰ °å4Ó5a†ë2­ZµŠêÖ­«Úª  €¾¹t�…ü¿eË ÒyòíÇçÁµ “Ÿ=ž}öY ¥+¯¼’n¾ùfš={¶S¹™ñá,<÷Üs*½+®¸‚6lH›6mâÃøöåû�I3PmaŸçñÅ_4¯ù~5îDà&ÿíÚµ£O?ý”^ýu ¦ÜÜ\&NœH©©©ôÝwßÑ»ï¾K1114lØ0iHHH µk×ÒÛo¿­®5@4Z·nM_|ñ}øá‡ˆ§Òy W÷¿ÿþûe+ ߨØXEàßxã %NÌš5ËqÛÀÎ�;AŽ”wÈÏϧN�:‘7Ørržg–8fee)B¶~ýz*S¦ ýöÛol;2éú,téÒE­X¼x1òÄÿ\û1iòmÂågDÂKff&}ÿý÷#º=Øt˜ñÁ¶ˆ,Èõ²eË”ØSXXˆqÀ‡ñmÁö“fÀÚ€_Ï#ȾyÍõ«yï%�@ €˜bbb"@d0ùñ×Àjx_�úõë«eéÛ¶m£°°0«çÒ‹8aUÈÑ›o¾I›7oViÂøaÃÒØ¸q£-™oР�'màÈ‘# ÷ŽÀÙ³g•÷øàÁƒDDDК5kÈ|9] WÖ•ø�kÇ€ûöí³Š9¸Ççöó§ï¸üL @à�?®Òܽ{·¾—M‡l[!”{Ú´itìØ1½=€ãÛ‚í7&Í€µ…¿žGóšíW3î¥ �@ €˜bbb"@^0ù·’xAüE¸ÕªT©â! ü±q‚—ÓLó½÷ÞCZX.�ÿ­¿Û’yÜ Òäæà@x:GŒ¡êQ©R%½ôÝ[N·ˆ †&r|;ú'|öÙg¦€ßÌ<}n?úŽËÏ ˜ð*GGGSzzº¾—K‡Îõ8pà%''SåÊ•©C‡tèÐ!>Œo_¶ß˜4ÖüzÍk¶_͸—&�b"ˆ‰‰‰ Àr_sÀK/½DuêÔ!?øàëý Q±÷"¿õÖ[EöÆ#=xu5°oÚŽÌ×®]›¶oßNðš.X°À'åÇ6†¼¼<êÑ£Ùƒ/§[0ˆ׎>§ /2°wï^\›y˜×>·Ÿ?}Çåg·µ¤bÅŠØO®½ãú^6f|°muúôiÚ³gØ‚�}ô|ß¾\¿1i¬-LpåaÒqѯ—$�b"ˆ‰‰‰ ÀþeLþï¸ãå…Ä~ñ��5j#GŽT^Î/¿üex1±Ï�€ž={R›6mðÉ9ì7VžÏÑ£G+Ï<öx¿óÎ;ê÷¸¸8[2�|ãããé“O>A™¹?~|±V2š�Áó�Ãî¶nÝJöàËÉ f¾¼À·£}º†@ƒ½æÈ û¿}˜öcÊη‰_di—-[í‹ q/Ve°épãÄyhd… Ôö~øuÅv>Œo_¶ß˜4Ö&¸ò°é¸èו+Wªr_B"ˆ‰ &&&€@/ ž7oN'Ç á81Þ³T 2­–wíÚ‡—9 ¿üò‹ò¾c?þu×]gûxqXžIæÍ|«W¯ŽÔ@ì½î;wîH�Z†mEJJŠ:ýáþŸ½ó€ŽªÚþ0ÿ×D@B¯O‘þ@“Ð!€šˆT©¤†N�^ ½—$´„’Ћ ( �€t¥÷" Ý^öŸ}–7k�™ÉL2$„ð}ký3sÎÜ–ye÷œs§3`»_çÀÑut"¬…ßt?:ÿ[×gpE8º~Î�Ýñ5It±:eʳR}�dÖ¬YÒ¬Y3]› Áí$ôûpv­–.]ª¿a3�ÀÓÓSbbbœ·9¹¾ÿnN¶ù(®… NŽÇÉvÜþ» „�4\»vÍ*xÒ*1z÷î-"€ Bt(qš:7[‡½ëH† €‚€¿†ëœä´‚.|—5kV7nœ€ !€´€ !@!!„ € „@ê@„ €‚€B€@BÀ @!AB@„ €‚@ @!€Û·Ï§ê „‚@À£@„‚€wÇ©š$ó»�†C"¶7¡}€x’ƒ „ -‚Jð‚µÛµ­åÈ…@ !i!8{ö¬¤K—ÎavíÚ%/^4¯Á W®\‘ HRiÛ¶­dÉ’å±Nؼg¯‘«7Ç8ì³êa›öÙk}–*¯w2ý>­í&ë>Ü;.÷·€xŠ‚ „ à�?þ�Û·o[1EÁ‘#GâÞÿöÛo �°xºzõªùîýû÷«<7Ú÷±G:ì³÷ÈAÓgXÄë³Tr½S^üùçŸòÓO?IjÀícA(€ B´(ÐâÀ^±°dÉ)\¸°¹{=qâD±øõ×_eРA’?~Ó(?ÿü³ØcÍš5RºtiIŸ>½¼ð 2sæL›}oÞ¼Y ,húI®\¹¤H‘"mïn¬Ý÷úzÅŠæXóæÍ+ .”±cÇšãËž=»Ì�;×¥c×ílܸQJ–,isιsçÖ6óGܽ{WÚ·o/9rä�|ùòIŸ>}´hsú]-²÷;$]§,“W{…IŮӥõ¨HY³+ÞÐ+ަ š-5nÃ/h–|¸}§MŸƒÂMŸ —O:ç¶i] À¾HÌõvþw[»v­¹ÖÏ<óŒ+VL>ýôS—®·µ�¨¨()T¨�¹æ]ºt‘~ø!Q¿ÏüQ¿gŽù¥—^’3fèvSþ7æäzXÇâä·–àö­m8?F‡Çá° Ò!„ �;wÖ¢Àãÿ÷ÿ'÷îÝE Ÿ-ZÈõë×åøñãR¶lY-ÞíXÿùϤS§NrãÆ Y½zµÍvt>>>æóáÇ›íœ>}ZΟ?/U«VM”hÕª•)Ç�oÞ÷ìÙÓìÔ¨QÖð{§Ç®ßkݺµ¹[?þ|=V}íÒÝS-ÈüüüäÒ¥Kæt»#FŒpú]Sœ4Źì8°_nÜ<+±…@PØ*G…¾ÃÏ£·ìÐm˜×µûͶéS9p†~®Ûw(´MûTéâD8½ÞNÿnZ°ªŠŒŒ”[·nÉäÉ“µMÔ___ó[9|ø°”*UJ˜¨ß§À/¿ü²|óÍ7ròäIñòòÒí>–ߘ+×ÃÉo͵߰“cLà8¶¥€ „@ kÚ€ÕOÑ;ô:´ÝâóÏ?—2eÊÈßÑéZXiÑ¤ÛØºu«µ›»•JÑ¢E­×оN”سg�(gΜ1ï/_¾ló^qvìÚ﫯¾²î�ZÇê´ ÕsÓÂèèÑ£b±aý«ì’¨4ËÞ=§¯�5[¿” WÌ]úD €ë7ÎÊ­[ç¬÷É&œ_oç7ýMè5›>}ºùD·ûX~c.]'¿5ç¿açǘÀq8lK@!€þ|;ý´Ð÷6ñðð{hq¢wù½½½¥C‡ñ€.JhmSe�ʼn'c.\°yomÓ©,prìúZ·máªÐÑ ÚnCÖñë¾\_ÄÆJ³ ¬ÂÝLXñùöD ûïm§œw €óëíâßM êæÍ›KæÌ™¥^½z뺰½Þz[¯w¢~Ÿ:Œ]ÿNÎsÉÿséz8ù­%´}—�Ññq8lK@!€£~/¾ø¢œ:uÊfN²UHYXw 3eÊ$ëׯ·îZÛ±»ÍÏ>ûL,ôõß‹1Q è“ ’Vœ9>v;×"Ñ#Ž;f#>t¾¸+ÀʹK'dfôF-Âu=€G)¬Eu¡?‡`�í"€nç·_~ùEvîÜ)ŠN3ѹê:Œ?‰#ô7¦sÒõûÔ~z×ßBç³Û{ÊýÆ\ºN~k mßÕcLà8¶¥a€ „`èСæ. �Ö»öz‡_× ø;:Løÿø‡ó¦ø0`€nGïÖÆÛ¦®P¾|y`æuW«VMÛ­âD_ëÜcݦÎ]NZqæäØ�OºoG´k×Nüýýõv:/[G<è9¹$tÀ¯0CðwüÚáuûÏy¤Àz ઄¸i»õ@7€ó¿›Ê¡ 2˜õnÞ¼)£G�6Còg×Ûj×yðz·ÛZ@·‘˜ßç�!CÌß~û­ù›U¨PÁV¤ÜoÌ•ëáì·–àö]<Æ�#¡6eñâÅæo–†€B-æ{õêeVk×aÃmÚ´1 ûÙcÊ”)f�4}®û¬Y³¤Y³f:ßßî6»wï.Ù²e3ÅÜ¢E‹tô€Í¢e:ìXç.ë|ï$gN�ÝQñôûï¿›I÷ïˆ;wîH@@€®¯«Ä[+³»$6ìÚ-&,6óô}º‡HÛÑQóõ~›‚Þ^#4-G.”àk mk52Ò¼v_8ÿ»-]ºÔ<B‡â{zzJLLŒ(ή·µkU~] _äÓ»ÒΟöŸ Û±ÿ䉔ù�%p=¬í;û­%¸}×�Ññq8k³ö•€@ !ZÚ,l¶eË3L9­£EvJe÷áÖü~»Ñ¶=›"€@Bà‘úH¶Ê•+ë°f3¬ûÕW_•¾}û"sBAmÓäòƒ‰ÿ–ðþÜß!@ Âó•Û%ŠË¶‹ÉˆÜEelž¢”³ˆMŸw*·”è+¤MÙÆ©ìd‹ÈŒe逅R1[é4ñÇkR&¿TÏ[м^9æ?2³wFóÚ¯`©_ôù¤m— 'Š—³S>£ývïçŠIT¿™Õuºxf4b U¥AQ_#'zÕêô„ÿáôZ–õÓþ%ŸÏþ‡t~-·, ~FBzd’~od—­óþO¢†¥Oüv Aàõ0z÷k¡b7¦wýµÀ¨Ð<ÕžpX—©ÕožÊŠ'þ�W«@™Ñ=“ìˆL'1 Mdû‚ÿ“±í=Ä'O¡Äo“ Þ €Í €é&ȲAQ:ß>ÕžpûJ-Œ¤héùf¢¾×£vNÑ2«ÓTÌöbŠž�õ_1ê•&2È«ÿ-˜øm‚`J^3÷ßnªf2}¤Rö2=b¹Œzk¨íÈ�œ/Šÿ¤ R{Ƴâ�ßö®t¯ÿJÝðgäµîYä•¿¦ø¨*ó{Ï–! ƒœ|ÅrùÍ÷«5Ëi·½F‡lRgvzñÊW”K•œ¯0¼ñ€D]¨EÃÒk�í4ÕœÜywýz8ŸÚ+“ÙçÒ÷ÒˇSþ­"@4S†6Ï– ×/M‡ €xãˆôÉYÄüû_*&½r‰KÙ¿ ÕV^oja­‹ÆzÀË ۹ψïÀÌòÊ_ÂÀ+w!©=%ƒøOÈ`S`êôÝ΢wçëÂ} ¼çs…¥öÔguñ fO�ÂR'4½Óñ¾7·{¨DEXÛOÙ¸~=œfL€‡5È!^·¡Åÿ¬>¥ÜÃó~¯UVÔÄ€G{ýA LèW§›)Üëªf·]ï2ëÝfŸF¹L±Y³�‡Ô�óŒ”/e»Z}ÙÌ%ŒD¨[¸†K'P½U³Ýò¥m·S©J>óyÅ ùã}gxãþæX}ry=¶ ïüz$.ï�ÿ�D8y  Û×�€x¯éÀ¿ŠjO‡w›k }Nï|ëÐrS\Vm�Ëýçû)`¶U£�íï×ze‘ÚÓŸÏÌñ`}ý»ÚÊŠäO²_�ÕrK›Šy“÷ú‚@ “ÆhQ�àêúe_(¨ÃÊMÁYó]kø»Û©5"“ÔyV‡­›÷^¹^4wÓ«¿�ÝnÿN>m̱6-]/Å×Hþ둌×�€˜Ðv¤)ªËy”p¼p]žBR{Ú³b Þ~Ö¼s·Sµnn³ÍŠó›÷Uüòè{NŸ°øŸë WÝœÜ:‹Ó8 @ò_�d»~„ À°Ff^½TÏSÖn»™çÞ×ì*ÿZo1CÞëçÖ6·ã•«�¹cm-Xç;ø9ñ—ÑaAÝÛ¯KJNHñ둜×/í‡ àöíóOuà$€>Í«½HMûw™ëåŽ+r=³¿ÑMÑY®Ø nŸ„5g]‹érÅ_økq½œûê#õX«æôLù‹žü×#¯_ÚAN‚hVº¾)ª»Öh¯­\ÑLqYóÝÌzWÙæ3¿±Å3kḾ¾ÏW’™]§IPíÀD�HÅJæ™öâ7&£þ«óëö ï& ûÎM©Çºu=Ü�û×�ÀãàÝqª&Éßß}ø€4á°½áàíƒ@$&€òYJÉêaËd|›`›ÏÍÝíQ™¤öŒgÅ;_!›6½û­Å¦®‚o}ÖÙ§­ ï_n­'àRtµz]µ^·§CØõ«’ãe³ýa�ÞM©‹ìÆõp;î\?Bžx€Á %xÁZ‡íÚÖräB�Øè“VY"³•NòUÊ^F"zΔ¨~‰¾C_½mv-`u;}Ÿà€-^yƒ€“ë—6CpöìYI—.�ÃìÚµK.^¼h^»‹µ�'‘¶mÛJ–,Y$¹¸råŠ(P 9¯•µÍ§v Àæ={�qâD±øõ×_eРA’?~Ó(?ÿü³Ó"W_oܸQJ–,i³ÍºuëÊ�!CÄâÚµkòÏþSNŸ>ítºÍÍ›7KÁ‚eýúõ²víZ³ýgžyFŠ+&Ÿ~úi¢�;wîܺ]íg{‰}´˜OhN¯¿ãkc_D~¼E|ûÌ”=äë”eòÍ™oìÏñ�Tëo¨þªMÛ¥ÙˆR¥[ˆ¼>p®¬|øÞjÛwì�Ùæ«½Â¤b×éÒzT¤¬�ÙoÛVM 4'Zj<܆_Ð,ùpûN›> …›>.Ÿt(Î?lÓ>º€HdôνÙí+µHÒ÷½Ÿ+ž¤Åù*¿–× _¯T)Ÿý7c³¸àÒ�‘RÉš¢@¼~„ �;w6rtt´üßÿýŸÜ»wO”±cÇJ‹-äúõërüøq)[¶¬¹$Z·nmî¬ÏŸ?ßlS_GEEI‰%Ä",,LªU«&гýé6}||dõêÕòÝwßIúôé%22Rnݺ%“'O¶ l·ŽÛzŸØóÒý•+WNΜ9££,ôõÜ\Ú¦ÿ~~~réÒ%#BôXGŒ‘Ðþ<•ޝ�}0|Þ9}á¸lÙkŠäÀ)ËìáÃö»úÝiYüéqmK7l5mZäŸ:\Î^Aa«ú?�Þ²ÃlC_×î7Û¦OåÀú¹nß¡Ð6í£’€@$a@HÇIÒÚ»QŠžˆï ÌR;äYñô°ÿƒ*çQRF6,]ªè{âüú‚@hñiM°éW¤H3LÞâóÏ?—2eʸ$¾úê+ëîxÜ6ïܹcîJ;vL-è,X гýYwÕ~øÁ¹Ó§O—Ø�w㸭÷‰=¯¢E‹ZÇfØ¿¿lÙ²Åé6õzëy=zT,6lØ /½ôR‚ûspί�“)·n�Ó"YGØ-ÂÏ\<ï;�†Î3m‡N±[x× šeÚ{N_!k¶~)®˜»ô‰×oœµŽOƒ@¤`ÖÝö=‰²… ˆY=¿]6W��8¿~„ Z$Úë§…¤¾·‰‡‡‡KàÂ… v·Ù°aC3fŒ\¾|Y2eÊd�6pº?}­ ZìÙ³Gš7o.™3g–zõêIll¬³í$Vè9¸t^º¿“'OŠ’˜}ܸqC_Ûè'NœÐí9½ŽööáüÚØb- §+èWíW\—í4Õn~ë–yo·ø¾~Ã~ñýEl¬N°¶a¦¬ø|{¢€ý÷¶SÎ3 aBA õ{ñÅåÔ©S6óÕµ@uEègöÞ¯X±B¼½½Íê6mÚˆ…“ýÙlã—_~‘�;wŠ¢Stn|©R¥œmÇåâ\HTôI ®œW¡B…dÓ¦Mb±uëV wy€5" ë1ØÛŸàüÚØþýf›Âxûþ}rå»Óv lÛÏ7ÀʹK'dfôFí«ëÛµk'þþþú¸@³€Ê‘áÇ'E8¿6v€.þ§…±ÎÍ_ô鉋ÿúNàÔerúüqSè�‰Zgµ›µ¾:tÀ ÁßyðkÓ·nÿ9�TX�\•Ðc7m·ûÀÅ‹›¿ÍS @!€MïÕ«—®d¯Cèõ޽ÙwK(Zœ?ÿü󿏅“ýÅÛÆÒ¥Kå…^0k xzzJLLŒ(î·µ€ �×uÖ­[çÊyÙì/[¶lÒ©S§¸§üþûï* t›v÷©ë"HöìÙ%oÞ¼ÖS’"œ_;`}ÌN©óîñé*CÂ?H´Ð,ÿl›4>ßL¨×Ž,Û¸-®mîÝÒaÂbÓæÓ=DÚŽŽ’˜¯÷ÛlÛN%4-G.”àk£¶µió™Í5€Bi-‚ÓJv>`Íï·mÛó·)€@BðBA< € „@Ú!„ R#‚ „ @„ „‚€B©AB€ BBA@!7@!„ @!AB€ B Í€ B@A@!@ !à‚ „€ !€ B@A …‚ „€ !€ BA €‚AB€xŒAB@„‚@@Õ<ž2sä4¹wç®( ¦ÌM°¿gÆ"ò^—�rxïAùñÁ�òýõ›²ÿ˽2ºç0©�ýqývñ¥8ãë�±Éyn„€ ªä~Ef�ž!÷ïÞåÌ·§œ ¯LEå“•ëDùîò5Y·$ZÖD­–SÇNÈ•ó—Ì6­¾£{ •E3æÙÍÖ�7‹òYô'ÉyŽ„€ ”ñeç¦ ¨Ù\ÚÔhâTŒëóž(_~¾]Êg-i3* Æóå\Þ÷ûó—‹Ò­á;É}ž„€0 ±wëµS wÿÏŸ<+Ï\�*¹^Nò>ušÀƒ{÷ͯçŠý½�‚@ =jç”-³:MÅl/&zÛÎ@çzmE™<Õ­sÐG”ðñ3ÓÖ‚ ^y Iõ·³‹_p&©ò¬Ô K/~£2‰Ï›¹Ä3‹ëÄEÃÒËŽÈtNS-O¡G.æŽ ¥i¹zn]´¯¶|)JýR¯¦­!@ ´È÷üœ¼˜Uª5Ï!Õ[å¿Ñ¥nø3R£}¶Tq2ÎÀÚEï‹â÷R &ví“÷ÈÙgdåÜ%â“×Ëé>j«&þù§>! ­ýA`?ž™ ‹ÿ„ RgVzy%Sê»6ïåú•ïäçÒGø™ÅütAEŸ �Lh:}@Ð;Mÿ0A`“W;g5£¼óJõ`Û'[DY4c¾TËçmw^ÿâ�·¯O ¸xú¼Ü½}GÊg+•6„ €(ûBA3üß·fñŸ”Aꄦ7Å¿Æû¿Sý«#–‰R1Gi»Åý¥³åÌ·§n¿}­·DY>+*mþ AP±b~³ð_íiÏš9ÿ՚唪õs‹ïÀ̉½êæ”àÖYœ%Yž0cèDQZWkd·}ïö¯ä·_ÓÇ&¸†@³ õÓæ‚ ~#3IíéÏŠçß óêÙ-�ê§Ô+YCðÓ;øvGܸz]Î�8c÷»•s•‘îÿ G÷Jæó „ à©Àc€ðŸ˜Á<ö¶‹ÖìëñÄÍŽ�[å�?þ��:ØÿS�Opxÿ°ŽýEÝsXÚýA‚€¨öVSè×ìŸYªÖÍ-ÕZ濱¥Îìô�MTÉõ²)ö­|´|­(‡ö°ù¼¬Gñ¸ï4(ã+wnÝ‘?~ÿ]¶¬ûÌü‡v-Ê·�I¥œ¥íî+vûn}r€õ”B m€@x>WX|åÿñÍZ¾Cž“Ê5òJ¥*ù›¨Y¨’¸@¼ûë–¨.¯øPnÝø^~|ð£)ü§ /²ÿÏáÔå£ekÒÖ€ „‚€BÉ è¢­ûöí“ &HïÞ½¥S§N2dÈ™;w®|÷Ýw©n½‚+W®@"A!„ àÓO?µYO€õºC‡røða€ !x’ѧµtîÜÙÖëÖ­“Û·o›7nÜ�É“'›Ïß{ï=€ !x’ùþûïã ë~øÁ¦íÒ¥K2mÚ4 ‹ß~ûM¢££eðàÁf¤À°aÃdÛ¶m* \ìcŸ[·nIDD„ôéÓÇŒ:èÛ·¯DFFʽ{÷ €»wïJTT”™ïôïß_V®\ï-“&M’îÝ»›í‡††š© O € BA€ëÖ�ÿ‘#GÊ_|!ׯ_wX¬OŸ>ÝôíÒ¥‹Œ5J okô€‹}ì£ý´�F úöíÛëkÀ˜1c¬ýÙЮ];ó~êÔ©bqüøqk[Fh_}­£nÞ¼)O € BA@LLŒU¤Ç%00PBBBä믿‹o¿ýÖ´õêÕK~þùgëîzÜZ³gÏ6Óô˜F�m>›7ož�`øðá6ÛïÖ­›ìÚµ+NjXŸÿúë¯bqîÜ9ÛÑ‚ „¤ñ @‡ßë"}}oñÓ"{Μ9æóqãÆ‰¢ëX‹éé|ënºÞ…1b„ܹsÇ¥>¶ØÞ©¿|ù²Ùÿ²eË*+tÕ=¶ßÿ]›õ»V=›5ô\žê5@„‚€�;wÆÎÖ|ëõ;ï¼cFX²`ìØ±qC탃ƒM»¾_¾|¹K}졼 k¡@]3Àz2�ÆÌë·6OÐÑ:‚Á:î‰'Ú,\h= G�ÖSô_žOŸ BAÀÑ£GeòäÉZ|[ÏÔ7wÍux½…¢wЗ.]jÚ­güoݺU ûØG uí§Ã÷uú€®ìoîú]{@GDFFê–80kÜ»w/ÞT•*$tÁÀÐÐPó¨CI³À;{©×x t˜µCº,üZ´‘ðw2¿š�¤õˆÕÒiîWòNÈVi5t¹øûŠ—Gɸ~-.Òí%˜VÖó# @rÆ;[i©ßd�tœõ¥)Æß÷‘S Å“ÀPÓ¯ý´ÍÒ¸ó4iÔiм=v�´›ò™Ù¦Õ×߯«¼Ñz¤Ý4ïa¶Ñ´Ç,~„ €HÎT,ècŠðý#Åçõ¥j©ºN€�î¦Ï[ýŠWæ6b l.O—÷Ýè�If;5Ê5åG@€äN¥Â¯Z¯� -ò&|"í&m°îô'):M ãì�f�g¦¢üA@êCçÔ?õx¬ =jç”-³:MÅl/&ò@œ €ê^�L{½FÜ:aßêf;¯7j¯�‚`Ѱô²#2�ÓTËSè‘ €úM‡˜öÊ/½æÖ ·e¶Sá…*üA�²q.wšjÚËç+/¯7"­†­0Cùßÿ±¼Ùn¼”Íþ²Ó}TøoEé²`¿>!€?>!H�€ ¬;÷í§o‘Ná»Í#üt1?]DP?7OÈ^&Á}èôíë[-€?>!H�€ šÍ3ío´%es¼lw^ÿmF%øÁ€I¤ÃÌâåQ‚?>!H�€°À›í'˜v¯,¥ì÷í&o”·Ç}äpû>e^7ßoøöØ„Žƒ‚ WÝœÜ:‹³$ËSê6ìgÚ«–¬m·½åà%Òy^¬Ê€×¨\Ä—?9ÀzJ!€”  \ž²Z¸;K¼û+<_Iš†È;¡Û¤ÓܯLá_·A߇ýJ:š: ÛQÁð÷6BBA@!iW@!€Û·Ï§ê €‚xÂÀîäá�‡í Gh €‚x’@‹à…¼`­Ãvmk9r!@A<©`óž½âÝqª¬Þã°Ïª‡mÚgkllB@„ÀŽ;dòäÉúoªƒçF›â>öèA‡}ö9hú ‹XãH €‚ ‘téÒÅ%44Ôe°jÓvi6b�Té"¯œ++¾·ÚnÜ<+–|$µ‚fI­¾³ôµùÌjßwì�t�²L^í&»N—Ö£"e}Ì.Óf¥Á pSÜ_¸|Ò¡8ÿ°MûèZ€ !€¼yóÚ}ïŠXºa«Þ¦ˆ?uþ¸œ½xÂæ.|èê ¦=òã-&ú:ìý�qí †›ÏvØoÄ@ìC!¶Ê´Y©8CûXâÀn´Mû¨„@€ !€G, �g ïC'ŽØ-Ì­ÿÜ¥&úZ?³Úud€~Ösú Y³õK¹pÅÜåOM€ „0À*ί߰_œWêjÚåæ÷çLôµ~Çjÿ"6V§˜Ï5: `ÅçÛíN8Ïx „‚t>@×Hp€m›½QÛu={‹êBÀžä[€ „ðÀÅŸ~a ïÀ©Ëäôùã¦�µNÛLf¬Ú`Ú£>Ùb¢¯CVo°ÚÍÚ_:`†ðï<øµi¯ÛŽÝÇ®Jè1€›¶ó@@!�\@³ü³mÒtø|3´¿^ÿ9²lã6›¹ùc­ß>35úÚf.ÿ†]»¥Ã„Åæ»>ÝC¤íè(‰ùz¿¶Ù¤åÈ…¼`­C m­FFÚ|€ BàÑ€Ëîìùýö¢m: ‚ „ ž,à~@A i/B@A@!@ !�:@!‚ „ € „�@ !�`÷áÒpH„Ãö†ƒ#´@A<É EðB ^°Öa»¶µ¹‚ „ ’SxwœªI–âóž½fÛ«7Ç8ì³êa›öÙ›�@!°cÇ™éPœئ}t-@„@Þ¼ym€¾T#†Ï[#§/—-{cMŸÀ)Ëâ}/zËÙq`¿y]»ßl›ïWœa>¿qó¬C mÚ§J· €‚xÀÊ­[ç´�Žˆ÷½ë7ÎZíšÔ#BASœ ]ÀOWð¯Ú-$®OÙNS~Ïzoo Ày¦ u@!`@ÿ~³ÍçÛ÷ï“+ß�Ž×ÏÉ{›Eu¡?G`‹€ !€äx  .ò§ø‘SGí~{ì�,úô‹$ ë1€«z à¦í<@A$·X¶q›¹Û_¶Ó4›~}ÌN©óîñé*CÂ?H’д¹P‚¬u(´­ÕÈH›Ï@A“•ß°Û÷âéó∛ßÝx¤cd·!b±hƼÇöG©�ñ%™“¿¨|[¤¸\+^\ö.&Óòµéã•©¨Lm?NÚ–kâöõòÌXDÞë2Pï=(?>øQ¾¿~Sö¹WF÷&²ÿÏ­sqõxÊy””àfƒ¤³O[—·ýÁÄKxÿ �òÚ Ur¿"³GÏ0E»ræÛSIA-EÑí|¸8Z>ÿàSùõ—_MÚTol·€|pÿ�, ‹Œ—ðñ3Ù…¨Y°¢‘üñÇcáù‹ÊíÅeÛ‹ÅdDî¢26OQ ÊYÄV¢Tn)Ñ#VH›²�ݺ^*>Y¹N”ï._“uK¢eMÔj9uì„\9Iÿîn�‹ëÇSDft˜(K,”ŠÙJ;Ü^“2ù¥zÞ‚æõÊ1ÿ‘™½3š×~ Hý¢Ï»{í €e|EÙ¹)Fj6—65š$Zè�f½ë«w™_/]3îó–Uß”?~ÿ]öÅì±W@j!šìâÓ•ëE‰œá¶èüZn™Ô)s’¿¢hq9û0å3Úo÷~®˜Dõ‹�Y]§ë5uëz�ëóž(_~¾]Êg-ió·ªñ|9·¯kbާAQ_#5zÕêä༠Ëúiÿ’ÏgÿÃ\ã¥ÁÏHH�LÒï�ì²uÞÿIÔ°ôî/A iì]Çz�$P¿Ô«¢èç¿·ûúˆüôÃ�zG:Å@××DÙöÉiåÓÈm0¶�‡l ÿG’¾ëõ0z÷k¡bûè]-”*4w«àÖk}þäY¹xæ‚TÉõò#ºžî œ°.S%ªß<•vÛk( 3ºg’‘é$f¡‰l_ð2¶½‡øä)ôÈŽ› x €EÝuŠWå³èOâµ�=~Z‹Å sܵþáþR»¨�ŽFx¬Àû/°90½ÃY6(JçÍ»u½:×k+ÊÌà©ú>U€ö•Z¹ÑÒóM‡}t¨ÿŠQϨ0‰�A^ýoA«� ò¸€+ÿöà1ùåç_Lñi}Þ¬B}ùóÏ?eåÜ%n�Þ™‹IØ{SåОfªÁÙgdõ¼åR=¿·Ýþ &Ïelïúþ± €)yÍÜ»©šÉô‘JÙËHôˆå2ê­¡nÜsdžŠÒ´\=—úû¨*ó{Ï–! ƒ’MTÉùŠÃ°; ´—¹û/KßK/Nù·Š] ÐLÚ<›í‡<…¤úÛÙÅ/8“Ô yVê„¥¿Q™ÄçÍ\â™…ÿâA<`÷áÒpH„Ãö†ƒ#´©+�Þe?wâŒ(»6ï�Ñ=†êºF TËçm·€Tapâð7f1¹›×®Ëžm»¤gãŽ*âÿ{·%ÊÆ÷?–‰ïŽ’…SÃåç’Ëç.I¥œ¥m”+[W~ÿíw9°kŸ‡ìà �"Ò'gSð縉ôÊQ$.e3š>ÒÊëM-�u@}ïÖõZ»è}Qü^ª"áãÂô:˜ï¨4Qã“×˦¿N9Ð}/zw¾.Úgwÿî�•¹ÝC%2(Âî>ÆxHPƒâ•é%SüÏê“QÊy–÷Ze•AMl€ù¾ƒŸ“W³Jµæ9¤z«â7:£Ô Fj´7}  Õ €Á %xÁZ‡íÚÖräB R_õJÖ�o5wçµ´˜7q–TÎU&^]P‹÷Mk7jQªO °žD ß±÷?}|�ÍçA-»‰2cØ$›ùï¿Ú/¿ýú›4òª­Ÿ%IÖÊ%#Zfµ‰¦:/]_ÿ=å³¼èÖ€~uº™"¼N¡júÞ­ë¥F¹~å;#I¾Þ+ïÏ_nzTôν>öÑê_6s #ê®awßî�•á�û›sôÉå•à¶ßÿ‰Häc=3ÿ ¤Î¬ôòÊ_£*`ÇŽ2yòdý7Å€wÇ©»m›÷ì5m«7Ç8üþª‡mÚgkl,©'½£|íÒU-8Í‚‚e=ŠK¿VÝÍaEïmÌ96-]Ïíý”}¡ þïÛ?³øOÊ uBÓkñoâÍÂ�€‡äÍ›×Fè{WÀªMÛ¥ÙˆR¥[ˆ¼>p®¬|øÞj»qó¬LXò‘Ô š%µúÎÒ×ú™Máo/Úf¥Á póÙ…Ë' €óÛ´�®€@ª @‡�+¶sËMÌh½#¼û‹/]Ú–.¨,Ÿ½(î³»·ï˜Á�ƒí¦W“N¦_;ß·ÄEô{©JLh;ÒÇå+Êî€W¯ë‚�®ïÇÍã±ÒÛ¯‹ SœÇod&©=ýYñÌf»îBõ€ì€ÛS �g ïC'ŽØ-Ì 7íç.�0Ñ×ú@Òšð}±’y´^­Â•ã>Ð[�óo-øgÍÑß°ú#mÒûlŠÐ¿¡³‰>¶îÖ�ïåÁ½ûFÄ�Ì€1¢|´|­”ÏZ2M €>Í�½HMë³$_/ÍŽ�[u*„É·ÙŽæŠ%\�{Ç£ÑGê9VÍi¾›äøOÌ`û÷JFÛEköõ@ Ü^Ð*ί߰_œWêjÚåæ÷ç4úZ¿“(`M8Ï€”€*¹^¶™+¯E¶¢ÏÛ×÷Vta?íoÍ¥ÿdå:›‚PϧèÖ-‰ÖUçõQqV_›GÃéÐtåâ™ º€Ÿ£ºB½¹k­CÓ;Õmï1€ºê¼rõÂeÓú� :Ï_ ]½ãýÄ €f¥ë›â¸k�vÖgI¾^še|åέ;òÇï¿Ë–uŸ™ïÚýµ(úhFëщßç+ÉÌ®Ó$¨v Ããw÷x4á=Âdaß¹Öc“œjoå0…~Íþ™¥jÝÜR­eñ›QêÌN�@8Áíº&€»#¬Eu¡?‡`Ï£^€¨Y¨’¸Bùl¥Lÿaû›"ÿ½.ã­ ?ä�~f¸¾.ÚwïÎ]ózh‡wãÍ5oZ¾¾Y¨îø¡otuó<ù³ÇO›ÇÉÕ)^Ýáªó:ò`ߎ½òýõ›æ;ú8»Ï¢?‘7=ýSDTËSHü ½�, |–R²zØ2ß&Xß»}½4uKT—�W|hîÊëãµðŸ6x¼TÈþ?›~�}ÚùðþðåŽ× póxªäxÙìcX£wÝþq{>WX|åÿñÍZ¾Cž“Ê5òJ¥*ù·ÀâO¿0…wàÔerúüqSä�‰Z§m&3Vm0íQŸl1Ñ×!«7h›M|ûÌ4mGNuøÀU =pÓv÷€@¤Þ}ÀÊ!K¤b¶Ò)ºßJÙËHDÏ™Õ/º;ÿÈc-Øâ•7Rõ߀  YþÙ6i:|¾Ú_¯ÿY¶q›ÍÜü±‹Ök�¯Ñ×vçòëwüûÍ–²�¦Ù ÐräB ^°Ö¡Ð¶V##m>@@I Ï7L‘ܱjëÝïkù+˜ÑïTn™Lû("³§Áà•©Xjþ R,»°æ÷Û�¶é4  F‹ãÈ p ïfM›H‘ô¯ßSúÕížlwÿ—ªcÄFOßNü� n@i(z^‹åö•Z¤Ø>½Ÿ+žlÅ¿.þ¨ .)•ÜŸÚ@A¤�Q!'IkïFiâ|Êy””‘ÍK—êü} @ùÛ]sΉ ‚ „ @„ „‚€B�Aòÿì��dÉ…'4¶m¶mÛ¶ÝcÛ¶mÛæzÇžg{¸¶÷¼È?^FTGÕtíV×Óöù"¾ˆ[™¬øÏÍÌK) !„BÊ€RÊ€B!„0  (¥ !„B€ÿ’ õADhòfAŦ›(]ýr§@dä`¸4³©rnÑ’‹¸ã�)å:sÏroë‚„œ™È�²ekß–k²ÇïD€c‚5Æ'z÷ FÆÈM([ûÊ7\GöÄÝpÐ÷§”2 „BaPûd ÅuÚà5RÀ—¬x©•+�R± …óO£xÙe¸¶´7 TQ�T0ÏÈøÌ©Õ>Ë«»¿\[¹í.ògEJùR¤[�ò�7äù‘ƒj<>?›h *6ß’ëÔùåòÌ{öÊ’s(¥ !„BÔ:DF•â:kü¸4P¥ðvkë¬Rx[6$æÎ‚WWß*íîíÝP¼ìŠíîí\-Ÿ´.<‡Ê-wàÛ/Â(xP3ô=(¥ !„BÐÚHÁ\´è<Š—\ÔoÒÍjq`Æèø‘RèË[z Çà˜(÷ˆKŸlÔõ¯ !Ä7O~SJüOC!„€À°¨6˜‘Ó¬^-{š}p KŠű)ä÷3.ÕË,ŸL÷Wçûô1êóèè!}joi£”2ø_†B!„€ÝÓêãêÎ:f hßÃìƒãÒ§è‚ù¿$-�±ø;Ä[:>ÙW |ý5™9`ª¿xé%Î?#Ç”R„B! h­Y�Z±\ lõv<>c r§”µòj}rñB¸µr4Tl¹�‚¹'åÜÒU¯#gÒ{dêÂûGëÞÁ]îU0÷„ÜÃÒñ•®| E‹/¼ô9y3£lÝU9¦”2 „Ba@kM�=adwý•¯É|¹Ó ¥t‰|–OµË.û­ª\“3eŠ—^Fƈ�R„g ß oÝÕùñYÓ,û Á�5r}�kZ�ÆW¹õ.òg{é³ôuÎ�ûÊoJ)B!„´V™c¶JAœ˜7n­«¾M ,‚ôåÏ1l7Y<»4·•â|àöûðíöã6ÿ‹!ÏIÈ�UãñÉ €Eç9€Rÿ“Ù lýÕ—ï°ä" æ�’cJ)€ÿ$ßÿ=|}}qýúuTÇÿøGôíÛß|ó j9„BaÀ`DLÌÊknÖò€˜¤±R`ûÙD™ìÏ™¼W¦Õÿ�µý>}Âä^j3?i3£o¿pTlº‰âeWàÞÞÍ*ãK´JÎ÷îdjŸéK¶Þä½(¥ víÚ'''4jÔ½zõÂÎ�;¡ùúë¯1vìXtèÐíÛ·WÇÒføv?::­ZµB½zõàåå…ãÇ�CsíÚ5xzzBóñÇ£Y³f:ÀÏþstêÔ ÷ïßGrr2Ž9B!„\`5=»øÈø¤Âù&ß°N©7gDø@È €„ÑæÎ•MýJV¼*úÉÿV_€s’Œ!6u¢Ñù‘QC¤/Ø+˨�RÊ`óæÍ¨S§Žñ�?ÆóçÏQVVÍìÙ³¥íÚµJ9ž3g4½{÷–6UèõÕWxøð!233¡:t(fÍšCÆ��ôôt<{öL®¿xñ"[¶lAjj*!„B0°ªYc·«"[¦ðת�—‚Yߺ½ê¦€¢ñ¥kÞ”‚Þ£“gµÏsma‡üÙÇQ¹í]S­=> *¶Ü– ºÝ³«¯þb�É¥”R666RÀÿæ7¿�)t�ÿâÅ ¥:–6�š Ú’’’pðàA¼ÿþû0ÄÎ΀!ûÛßÔl™u°}ûvhÞ|óM´lÙ„B! XU¯îþ([û¶ä#7IA�7ý�×ùsN®¿WSñ¥]­¥×çÊÎúÛïËTü@çd³;þgŽÚ¢î!kñ²gâ�céøDÛùb@ùÆH­\�”ò¥²ñ_å¶»rK39.J)€† Jÿå—_Âõë×Wýjm¾RŽ4hÍk¯½¦ yiWªÂ~ÇŽÐ4iÒwïÞ…rŸþýû#66†<}úTîñÉ'Ÿ€B!„+/ðFÚàÕò_­ËW…uLÂh¸4³AÕuþ¡jc>ù^Ùš·äM{á³ò9@ÏÎÞfŸãܸŸîÕ™\ºØâñŽ3sÔfUøK�=q7üíb¥�Rj�œ ö�þwÞyÇÔ �ôÍ›7OõË~†Â/~ñ‹*›–——#**J‡÷Þ{š>ø@®—6B!„ (¥”€õظq£*ºåmü“'OT!/ŸäÓÌœ9Sú×­[§”cƒ5ý²wÀíÛ·eýÿÍ›7¥¿[·nÐôìÙ'Nœ€F…AAAr~HHˆüÖ¨û¨À@…„B! PJ)«ÿ±nƒƒƒƒ¼‘ïÞ½;¶nÝ �*ÔG�…víÚ)Õ±´iÎ�;§ yµ,@¦ûûøøàêÕ«ÐäååañâÅPìÛ·}úôÑoøqúôi¹§^~°wï^¹×?Ù»ca £t‚�„‚=h™ƒi e ×–u‘Ü¥±ÒÅŽÞ“¾%~Ég$8Ï3–e‰o¬ëÇq€À Iƒ äœë3€çy¢¡þ0Ïs¤”À`�¤ñê €mÛ¢eß÷zcÀ`�$ÀÀ®ëŠ–û¾£”€$úc�@’€ ’  ’dÀ`�$@ 2H2`�@’€@’  ’dè€@I 2H2`0H’€@’ ¿`�@’€ ’ ô€$$˜¦é£×›=+ÐP( ¢€P(¥P �ýI�$T¿Ð_D!!DJ! �J•RgÍe¯uíÝÖölƒ9ÕuÍ;3wzæ�ç8Èd2‡x†õz�h4ŠwÂÔ°Z­Tñmù|>Ÿnb¹\RVŽÇc·rÕq8ÔZÇäÓ3üµ0¸>ç{éH&“àÒõJ�¦Ó)r¹·>ˆ @(Š À|>Çv»U\,¨Õj¸ßïìNL œ‡ËÇã�óùŒÿÂf³Qµ8pÔº_ˆfÝn7æÿó³ç!ÿ{„ô_Éf³�FÜúH €P ¡P(€4�}Å~¿WëôI¸^¯¨×ëˆD"êmr©TÂårA0¤}´þ«A›¾Äb1t»]õ»ßï#•J©¸�FCïít:jÝq5ˆöz=|›†V«…D"aƵæb‚öU«U„Ãa„B!”ËeœN'|b·Û¡P(Àï÷«=•J…mÚ-õÐùÿEç3-fmLè³öz½zPŸÍfjÿd2y¡‡\;§Ùl"�«‹Å"ŽÇãOqž^¿Ýn#�NÃãñ|°kªQÔŠ¨„D€�ŠD%%PPB"„"‚ Q€ ED€@’¢„€8ßÁÐ.ožgï0ì¾™î=3s‡{î œN'†Ã!ˆL&ƒf³ �ûýƒÁ€Óé$lª®»Ösð Æçg·Ûáv»Ñï÷9^uÝX”á¸ÅbŸÏGNì#éïdq(á"‹s-1*ó¯-4œµØøÄõzE6›…ÍfƒÅbA,Ãf³ù¶—^¯�F\'—Ë…õz re?9ôz=!ª óù�@&“ ¡PËåRzîÈ¿R©€sàx¾¾Éår°Z­`|ïv;L&ƒA˜ÍfÐ'ù¼ßïo\ù�ó¨V«ÜsÁU3·ív˵úULó{­VƒÃá€ÇãÁl6“�#%;2ÇŸ|þ[è½é½éMoz@/ðI7omÙ.— Úí6’É$:� …�‡"‘3¡#>ñxÓéL¤ø±Xo¨G£¾¾¾À¿™PQ˜�Çc¼^/t»]«ì³\.3ÁcÒH»ºÒ¹üÇE£QœÏgðv›¢j0@€I`:�ÆívÅ!í´Z-)÷\•æ¯�§œ‹ð§†z½Ž|>Š]&è«Õê×E¤¿Úa'•J�±É…ßïç+©™ £ÑˆR©„çó Æ£è£â^ pωÄ'õu×x>A‘B‘¶ßïq<‡ÿ±wõX?{FX¹ÂT?j|]"ì×Éwa÷¾¾¾X BaÄ�ž5ñx‰]wý„õз¬žŸŸ[[5_0öë:Á�h§p¨x‘8�Á¨? ‘û¡±é‚3–s�XÀ#Ü˪ªª–jjj”422Â},Ì–;¡9S°°°@�uçž)ÔÝòò²ó)%ã‡u¿ïÁÁÁ‚‡ôòòB½ ì¦Žg U„uê”’xCÁÀºåÁtð æ·x�ÆÅ½¿Æ1ü”%@*I�J*©$@ À:Êa¯µµÕÙ¡×/¸� AÇKê¡·�_ç™_y¹½½uccc®ººÚ ¸»»»(¹°_5—�x!ñ7ÂjL;ÿ È�š6ŠwãMÏ?ŽOÁ‹7ž&b¬–ðšC»<Î í56õøÜîIx933ãü{CCCëãûû;–aŸ—Èu×ïAH(èÇïÓÚªù"¼”²N ‡Š�óŒªñ£°³ !Ýßß»žžWYY‰K;s•.ü¾‹? 5~||8£ºººÌöàŽzX°\Ï ëx(„¼à’�;¿Ÿu„Xîs­ÞAy0|ƒi'ß#…quï/q ?eGI�JR¤’J*I�r<>>"øÈĵ¾¾¾úq�|2Ö”ñ¨Ôƒ±ŠÖ~~,&kñ¹¸úÆ'ø Çs «"n±FX‰www}KVbßD<®äôzÄó©x±ñ±Ç³³³÷e??óc(ÿ>(«/ñµ6ª9>VfðM?fñóy;>>v(° NLL„¼_÷È÷À'情ò]·!5_þ†ëtvvÆó²�¡âEà<£jü,È1b¿>uttp«/8!ÀÿVà.Ïo[C<P$d´'.�:ß_SÆb‰'4'· ô@°ïûÞ (V¨SJá�½ t*¦¹~qqa—ù-Þ#�qqï_â¸l()RI €TRI%)’€C×-¹Öââ",¢±œ?[8Hc}„L!ž’kX‡JQ  !ŒK‰ÅŠœ¸‘þB!úp/æÏKûööÆA–C!|8£©©)×ÛÛË¿#�wXÁ»PäàSñbã)ÂÒÝÙÙÉAØuwwSwF¬k<†òïCØq·X‰þl/T?r|æ„+6B1ÑÜCè�¸ÏâÚ‹(à¥èºÇ¾>‘€�xéççgúÄêlmå|‰_æ9rw°N`7쥥%ÕNâPð"q�Q9~ÔÑߟÚÚÚ¸çÆÇÇy?øMAX,ª8<<,ÄÝÏÏÏ#„RÏR�8�:c’ /,êà4·ÀÜîñ@ g ©ollX‚?ËW@ü>î÷¯Ñ¼1W raš½knnƪNòˆ÷H`\Üû—8.J €T’ •TRI €¤À*J¦d9Baq›Ä*Š[4¤9Há:é%t¢NÌ%Ö¦’vx&Î÷QÜS-óv@!úp/æâSøq½$Œó³Ô+>99‰›¬«­­µlЂw¡ÈÁ§âE)ŒOöɬþìã1OŸŸx å߇ ¬òXÚȾMÖsxTý!Œ“˜mkkË�ŽŽ"ô8#„…úúz¬~!/Å1ùdýæëg>Wó5÷äíím°Ç:!Èñ¼j'q(x‘8�À¨? jŒèo„O×××(‚Hއ2eϺÓÓS¥°ï(eÖžøOxI‚££#Âq°4£îNNN¡�}#øãöÖ×××Y›¯;;;\ç½pÓÓÓÂôQ o$udî¹0Íu0Ì÷EÏþþ>ž;{¦1®îýÇÞ`º„qŸ´ i ©Vnv“%d !K€l'k È"dê�‹«�’šgÜû;J=Þ�÷Œóæ›ið9n�@€$˜žÚA?œÏçü•9Á"§BÆãìù¬IØívõ?H8›\¸—KXs²’KT€‘m:ãt:ýõâ¼D�¹“û/ƹûwÉó�9ÈI´Œ|äiÃãñXˆ@€$˜MÎ]ý€Œ�ä ÉÌŒçÈ|^¸\.ãÈÂìÉÑx—ÜÙ°ßï3’�£ûyƒ?Ÿó €ÉÎ@^ h $€e P )@ @R€À2”ï•${uS¾Åú«|­?˪þ(_êª|:ÙŸeŸ–ýZömãÎ~¶/’^r¿ßk)eúïF‡z½^?tMÍið}乬õzÝÝzZ“5n·[ëXØï�×ÿ×êç € T’lÄŸÏg}<µ·Û­Ã�·¥€�0¯u@ $¹‰€ÏÀoöÎ@S¡ ÃU © HUP¤‚z†HI ê"‰"BP’ D€ôE!ñ_3,˹#Îu�>P{öÌÌšì8ü&.ûý¡P«Õе›“É$l6‚Á ƒˆçó‰Z­�ǃX,†^¯'~ ÙPþv»‰ë;·Ûm(‹¯[­V¾m6(òù<æó9Lø”Ï$q»ÝX‹ÚëõÂï÷£ÑhðàCöa$›Íb8‚8ŸÏü^¿ßq¹\`±XH:‹×§Ó)¢Ñ¨ÁÞëõB³ÙD àgõz�µÅI+›Þ£u•v~­ øŒF#ÄãqØívd2l·[(f³R©ç±Óéàý~ëùàxH#œü¦Ói ¸\.ÎãñxÔ÷óˆâs»Ý(‹¸ßïâÅy¹\²î:ÅF¶×ë5•ßR©¢R©ðÿn· ƒßV«Å5‰DøKÁ/ýæµ?œ“ë°Z­òþr¹ÌZèŸÎ¥Ç2�9gÄétB.—ƒÓé„Ïçc{×ëÕLÿèµ ×�q¯Ü3rшÚm–AH÷ù?Û½ àÛV+ž*ÓßúŸkxu¼?´,µ ¶�ÆãƒeŠ“ƒûýE¾~X€ÕfÞ¿_‘û+䬆Ðú“·�»u4 ö¬†ðâX/wÜÓ_ÄUòxd°ˆÏé6€¸xû˜+=´:.ß7‘ø^ÙŒïÚíø²ÙJQ þX}Ï@@@’ßZïþ.¢¾IEND®B`‚ui-customization.png000066400000000000000000000630701526573132500350370ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/appdata-screenshots/0.12‰PNG  IHDR@•ÕeÿIDATxìØfC1Çñô(0 -½É`cÓ«•Î`³kTØØŽÐjSïÅÚì…Ž]¡ñ  ð|áòFƒñl6[Ä¿»®û^9�NW¨-_›>Æø5™LkëFÿãÿfµZ½_>–ãñX‡pejÓ×¶¯�¿\.ßjóÿ�ãÿ9çFŽRJ%ç\G€×Úþa>Ÿ/ú¾?·w,�s>O§Ó‡°Ùl>Û=X¯×a·Ûõí l·Û.¤”Îí Ôöí À`€fì÷ûòôüRnïîÙ» Þ8’4ŒãùBÇafF3s˜™™™9æefÞðr8Y63-ù ¼wOI=RËãqßÝ:cÙI?e¦j ¦wVã÷éê*4b¤ 9ÚfÆÆÛ®½ûì×_�ʘnÝþÌþÚ >vÜ×ÞÞÞnE%¥–5wž�7Á�wv|¢í?|ÄZZ[£v ùõW7ÞäŒLÝ=/—ó \ñÚèpKÍÌvÅõè “,>%Uý=&hnn¶ÄÔt×>hÄ(7ÖK—ÙŒ˜8›K¿C‘<Íq¤eçX]]]¨­¾¡Á2óæª�€hšgÿ<Ôî?|±¸]»q³;?pøH7;àÓ«×ÔïÔ××ÛÚ ›Ü´ü±“§Ø¦­Ûôc¸_g÷·ìØiã&OµcÇ+”ðµµuîþ¤é3­­­­ËB|Õºõ›˜ìƺfÃF«®©Q»f „{ìä)×öÉÕ«¡çé±™¹smðˆQnœ§ÎžÓ%îñºÄ`×¾ýn¶Á€a#lÚì;~ê´ï}ÇLœ¬€Âý;fÒ;zâ¤÷ü>@àý†ÏIHTàþˆMJQ›fíE3'Ïœu?Êš°|õWÿñNJꡣǺXEï¨ C¡�f $¥gÚ€¡Ã]ÿ¦mÛíïÛâå+ôü.ûU gÏ›ïÞcÙªÕváò[¸l¹/¸~ó¦îëZÿ@gâu‰Àʵë-oÁBÛ¹goàào¹±îؽWA„kûêëoÜç.Zìîç-\d—ò ÜXö8è{_ÃŒœ<×>~Ê4×vûóÏùž=5@¹½ûUTVÚÔY³C!@LbR(Äÿ¹¬,šP�®@ êéZ¦Ìœ­¢ÛWÜê̸îËç_|éÚ6nÙf7oÝv··ïÞãõ‡Šå†ÆÆ.ûU`ë¶�Î.xᥗÝý‚â’ €^ß×4HÍÊ õ«ÈW[~Q±}s玻�3o�€@—”<û¬k»x%_÷{)@ä@&N›a?þôkÐS´¶¶Ú+¯½®"ØýXkú|YYyØ@¡�Îv뒯РçÎÝ{]ökÝ.*}¦ÓÀ»¿{ÿ�§|üé§js3^xùÝÖ�׸zý†k;|ü„îÐg]º§³ÿÞ{ë²¹ªªjzâ¶€ÚP?Ø:óÞY Kt�ßo½­~=G…ºOKKK—ý^q]úìs�º†PÓó5­Þm÷<ð­!0ñÒÀ€ÚÕ¦Çyc,,. \»qÃ÷è€Bwm'ì]ó/ÞmõE1*TUTû€ÍÛw¸ëwÞ{?l ëÚ½ù>zìn/Xâ×>]öýÍ7®Åšu‘vеüÞëè_ñÃ�?F ~ûí7o ¢7…_ ô¾¹{×;z?€GuD}mÀ¸äT_Á/^ Å£mõ§ùú®}õu†\«ß‡Öhjj ·ÃÆŒuk\)(Ô ÷jÓZîu-[šbþÒe-‚ç»^?B¿oÀÕë7ØåüÚ^ñìÛ) 1-õk~ÛZäoðÈÑš� U†; $!5-Z,Y±Òþ5dXà@cÔØu?kî<÷ö<¤Y À™÷Húâ8TèûÂzÝV[ô¶šZ¯­î´­Ÿ |ÚæN«õk_q;rüD]ϧÅݵÿ~ô±oþ=û(4ð¶ Ôµó�ûUÜk‘@�¡×ÚŽoô„IŠgíN BÁð1ãlȨ1 LhšÄàÞýû:+¡ð@ iÿÀ€·F‚‚ ­b¬ ¦ÎšcÇOŸ €ž¯¸Õ øÝü^@ €@úµ··èÝú555èÝúýüó�z·~ùù ôjº Ñ@ïF €н@MMµí;xÈ&L›nÿ2ÌÆO™f6o±ï¾û®[ÛÐPo‡�·‡�ö¸™™;×þÚ`Ï>ÿ|ØÇ×××¹þO®~Úás566X]]m·Œsî¢Å–˜–¶oÖ­Ÿ’•ã¥ï¡w¬#¶õÜãùûxàðá°}9óæÛÞ¿ÖÀá#ííwßÕm}-ؼ}‡Mž1Ë^óM»{ï®]½vÍUU•Ý:زò2;iJ�,FTpm۹˞vÌÒ²rºeœ¥Ï=§÷õÉ^Ñ;zâ$;}ö\TŽs”¾‡Þ±ŽÔæ;úT0rü{åµ×8€Á ®.€ˆEi7„(ÿ<Ä ŠŠ|í×oÜpãyððATŽ_¾‡}+ÐÙÐý‡"»: »qëV�Uv…ÚºM›­¢¢<ÔÿîûïY\rŠõ:ÜõoÛµ+PŸŠ¯hÖ4m9: ÓÞzç�§hù±“§lêì96dÔh˜^àû\s.R»ÏÇîÔó¼ Åצ©ô:æaŽsÄÿ–§Îžµ˜Ädßk­Ù°Ñ&L�®Y¡¶e«VëyÁÇÙýßðÇ:#'/ìñ÷ŽG�ï”Â�KíƒþÓ?36ÞÆLœ¬çGþ~G%ˆ|ŒÂúmÇž=6nòT÷]Ξ;ßîܹ£¾Þ ((.¶¿ d –,³[ÿfï,t$×�(úIËÌÌÌÌÌÌÌÌÌÌÌÌÃÌÌÿá·Ç’[Q+ýj0jõ–¤#MâLÇ)[p¯«ìß¿}ŸY²b¥Ù9Ù¦°°ÀŒŸ<ÕlںͶUWW™6�º˜ÃÇŽ›´ôtg>|ú$¶… S—ÎêuaQ¡9xäˆ]ÝNÏH·í€@Y·i“ùøù“MɧF¼KÏÞˆÓF\Ûvî2yùy!ò òCí.úúåëWS\\Ì7ù�¬@߸}ÛÖÌ—{R凌eNœ>gq,~|GNnN¨” [ï¾ÌÚB‚¸c÷žæÅË—rÿœ‡µÏðÆCžSÛwíþÏѶOEÅEæùË—n¬ÅùÝ”óÑ1eÆL棣×F”‘$$&`¤ðýÎ4PEQEQ%ÖNˆOH`aà  WÄXažNŽXcÔ¦¡—ÛöûºvÛ¼BŒçš·moÞ¾ï­c·«²¬Nz ¯ðüöý»ýýܼÜ&ß�¾ÒV^^f÷ÛwïüK60 Z´ë`=yb¯ÓÒÓè ‚4<ÎâXY Üãï?šC‡Ûxœ»xÑÞûôù³½•U•rÿœ‡õ0Ä9…f¬ùfŸ±çwSÎG/rŒÂ ÿëÒÒR›péêU®EQEQE‰Õc`«Ö­·"‚ æ¸÷ùË®è!X©ÚaÿáÃözÖ¼ùÞ´}±Í 1„&ϰ¢êmßµoÿÑ`ÅÖ¥u”rÍJ0ï$Õ:* —¾rí:û÷ésçHã÷‹s­Ær÷¾ýfþâ%üm³0vìÞcΜ?Ï8„Ú.]&ô)ÐyX_@œSn¬™—>c-Îï KäÉLš>Õ2(Š¢(Š¢(J¬¢€cçž½!ùûÏ+ *++¸ŽH\B¼Y¾z5iûˆ¹Í#ÄHûçaG¸!6IIŽ&€´ÞI&@Ô×nÜ´µìôcâ´éæø©Ó~‚·6cÉîû¬ðs,s€UxÒÿ©qgÕŸò'Ê›‡Me Áìæ~À€£Ú{ØßTEQEQ”XG €³ç/˜1&…R‚I1úü9×">~D Qƒ,¶9!F;Â%¼~zÂÔiˆ›h2¨»æ�n£8Ñ8rü¸‹e“Áž ¬öR@9FÏGðŠcéJ/Ø<޽¨õ¯©©±÷új®\»Î{¨…—ûüîϸ»»»ÏP§¥:S§îFݰ…àî®Á­!«#-Ã݃Ký]¿—}Ÿµºæö24%é$¤Ÿ?>+Ü}÷‘}v¾wïßÞï�n–³Š@ Ôišz,aš.ŸêS¤õñ©^Áq5rÖ¹çzß}ˆÇËçáúeyÏÆžªá_tÙåiÝ|¦€Þc-[¦ÇÖü5Î%Àß €8aÉ’ÅÔm'ü¿—7F�Ôx  ØS±"®küXŽûòÚóÁ–/Ÿíûö‹;[´‰F�åEç�cû–²š<ŠKæ¥ôj;ÐÒâ¹Ñ¸]§Xrøç¡½kbÿ®U1±hr´ìÞ³¦€ÂY…1¡pR¥wT�wÂQß´K·X¹raVÛ+ûÖÆÍÍŸ¨©Á€ Ïˆa1áóÕÜØ´E¼º]V[iًѪG¯š<îÔ5FMMÚwŽÛi�ú÷�[Ë�9x¬k÷_8)ì^� –,�“Y°lÙüš8^;°>njÖ"ÆLŒ½;Wƾæ̜’ øåÜôÿ 9ûœ7ÿÙ¸þ¯Š ¦‹Ïv 6=0î»åá–Ç4 |°M‡Ì ÿÁ=«3�Bª/ðX—î.µ‰`ç¶eñ@ëÇ´èÖ#=0§`šePCÀƒm:ÆÞŠ•Ym§NŽü‰c�)¸©YnÀT ¯gïš8RÁ¿Â™…©`_fº~ÑSSã¡¶Óëc:Hzà„©“2ÛÚ³&/™÷·î�žPS@ÅÖòLpÛ£­¢ÑcyÑ/xì©XqÌÙ¸¾8Úõé›Ùß�·Ž¶½ûDù²—j`À €µ/€Œ*_mð—¿ùþK‹ž�óî¼;>}òÙñ±?�§Þxk,)ží‚@mîY�¹±¿á‘Gâg_ n»ãˆýž™3#¾ræŸ3!ÁžŠ±{Çòx¤[çøÉÅW¸`PÛ€^Ð0N¹á–4nDäõí�;¶?b¿“®»9f>_”|à·§º`p<-¸²q“1yt¥ûO}zJöŒ ê@AÞ GSåƒþø¢Ë£¤lî;öKKÒR€_5¼&V¬œï‚Àñ2àÕýë⣬¯XwÔ~_kpAüÛÏëÅÏ/½*6m(v±à8 R5ÿtS_©¾;¶–E�áãœFw¹Xp<-2!?®mÖ¼Òý÷íZ© o3îo×&:ê{Ä÷>wê¹±wçʬ¶Y/L‹ß_u½‹ÇSpÆ-·ÇŒ·ó—­Þµ7Å­-�m›KcÿîUQôÌ”øÆÙ¦Ÿ.V-€ }³Ÿ úåøbýó²ú¥Jÿõo¾=3åÿãõÎŒ“®»9¦=[èBÕR €€@  €@P…€—+Ä´Žˆ7­«ÖývÜ'FLÌwaßçÝv{ Ÿ0¢®� @°§bE\×ø±÷嵯òAw­ Æ5¨¶A¼v`]\Óø¡5yÔQû½¸à¹¸?ûü�©ßšÕ‹¢Ë �qg‹6qû£yѶOߨ°ni­¹¨«W-ŠNÄ]-ÚÄm�¶Šö}ûŦ ÅUÇ–MÅñ¹zõcßΕé5u%(.™�¬ÖƒÍsz,× J¦^y'dLïüÑ*íóõƒëã’»ï‰IEã�øþ«û×entŽÎ�ÛtˆNýûW©ß²eó3!H îYv¯Ž S'ÅÃ�ºÖŠ šÎïÞVí2çwhϚؿkUŒ/œ�ué^åqÜöØ#i–…?8u)(œU 'Uû·÷‰)mþ9V>{_µìïÚÆ�£ßÈAóýfºDÛÞ}âù¹OEÁŒ)1¶`B•úµéÕ'ÊÊ^Ì nnþDUÆ‘Â�ô³ÊZ÷ê¥o;¿Wö­�›šµ¨ò8žz¡(N¾æ:pêRÐgݘ¿ðùj=ض²QØö_bÝ‹-£¨Ã~]µONŸõo¸©ÒýûŽs_z¦ªýr,-ž›f Ô`ptÅ%sÓ •ÇQ±­<>þ»“ýÁ¨K@š >jÒ¸hÒ¾sÜöH«Ì�ᎭåU:Øæ%ÝcùÓwg~]>ã–Ø¹j\•¦þåÔ³bÍê…•Þ&�)­…¯®~iŠ}šBÿx×±msi­ öV¬Œ‡ÚvŠòò—ª<Ž4Càß~ô›ºò›@ðÚ�õ™)ãc &ÆÞ�+cßaSfNIÅäj͉Ìxwßþ§À o\_-ýîoÝ!SñÑ.Ýb×öåÇzÓ$Õ¬X± 8iYCµŒcãú%ñ…“ΨË <ðÐÞ5qËÃ-k͉§ÂÃÆ�¨tÿTÝ>ÝäVW¿$#³ž›ž[,±†g¼qhC •÷´leå/UÛ8RèrÎ-·ùƒP—€�Û–Å­;ÔšÿÒÉg¾«éÿ³ç=ýGލj¿/ï]“ çÕšàÍÆŒÓž.JSû«u74kƒÆ ­+¿ù¶é˜ÖŽgµMœ:9ò'Ž­5'þ¯?üuªn_éþ£&��iOM­R¿»Ÿh›fBdµ¥oØ[vïY+€7>aL,^:'«½:Æ‘>ë__Ü0ÕH¯¨ @*øW8³0ólø4=¼è©©ñPÛŽéu­9ñüâ�±s[y¥ûwè×/=¯JýòzöŽ¡ãFg‘—÷­ÍT×°M‡ô³V|&ON/HSù³Úªkmût�!ã†Õ¥ßü€Š­å™à¶G[E£Çò¢_þðØS±¢V�ø/.¼4ž�3ý�¾éNîrÜÓªÝ1õKòS!Ä4U>}.éÑz%¥ójÍgrCÓïÉ8Rñ¿zW^oÚ�^PW€ãAË�ã®–�¿ÇÇ!MýÿýeWÆóófüý�€`÷ŽåñœΌí[JߣcðÆÁ Ñð¾ûbè¸á>@Í>aDü¥ÑÕ¿o2O¸ìÞ{c|áXŸ€@�ÀÎmË¢QË'âó§�ÿû›Sâ§_3ž/Êé÷ܼ™QÿæÛãÓ'ŸŸ8±AœÓè®XµjaN¿EK_ˆ3niýcýL¿Ëx(vl-sa ¦€]ۗů^“gLŠ=+âÐÞ51h܈ԖÕoêÓSâ;ç]…OÄÞ�+3¡Á£Ý»Äﯺ>çæÿs§žƒÇçÇö-e™ý7îØ>.¨± 5\Ù¸I ¬Äóä~éU1û¥§²Úì^øí©Ym)8_4!«mÓ†âøÔIg¹°PÀŠ•óÓTýJõýï_Ÿœfdµ¥e¸ú†¬%§ßt[ζ¯ì[ÿõ«“+sä�pTïö �÷ìš™îWëViýfÍþ™·6ŠÕ«s×õÿò²«£y—ŽiJ&˜2ëÉÌ’€gæÌx«ÏíÛFŸ‘CÞzýà f~®[»8- pakfœrÃ-ñÍs.Œ^ùƒ¢b[ylÛ\�÷�“¯¿9§oþ“£ãßqbüÛÏëe¤“¦OÊê“fÌ|¾('(z¦0Nº.³Oàï|©þù1tâȬ¶ý»WÅwZNÀoœ}aLšž)˜©èÿp×Nñ‹Ë®Îê÷ɓĿ�Å9Çé1|`4ëÒÑ…­ Xð?¿9%òË)Ø÷­s.Êjûõå×ijsg¼½`Ú>«í?yR¼º]ÎqþtÍ�±`ñs.l À €œçó§oöÓZþ·9S €z×Þ”Õöé“ÏNëý³Ú†LÈOK \T¨©àÖ�ÇýíÚÄÖÍ%™gö·Ð;¾{þ%išÎ#éÖ9̼÷äÌÉñµ¤§dõ»ªIÓ¸¯]›L¿,ô5$… éi.*ÔT°{ÇòhøàCñ‰ÄÇë�×6kž‚€œ~%esã´o��ýéŒÌ:ÿô�þÓs¦çôK…/}àÁÔ/ãÂ{îsóU €@@ €€@ j /W,ˆi?oZW“ƒÀ}yíãºÆ�ѽ­ÚUé »V��㸵flßR¶éÅ%óŽé`óÇœ Ç5ˆ’©WEAÞ Ó;Ô…¨-ìÙ±"šwì%¥óªtÀ-Å}bJ›Ž•ÏÞWå“_°¸eôÊÿZäõý÷è1â+±jÕМ>c O�ÒòîQøôåÑnÀ¢ÝÀÆ’’GÜßÂ¥m¢ÿ˜DÛþÿ­ûýg ûãX»vTzê~ðêþuñD÷žÇðͶme¢°í¿Äº[FQ‡ÿ>üzà1ï+ݬ§ôŠmOÇkVe€®C?›Ó¯ÿØfú—v‰Wö•Gù²>™à�Cks„I3þÛž‰×®‰Wö/ËlÓkä×ÓûP÷€�£óã¹9³ª|°ÍKºÇò§ïÎüº|Æ-±sÕ¸cÞ×€±?Š-›¦¾õúõ«ÓL€œ~í~8–”tÌjkÙûŸãÀîEYm�"í-ñ›€÷gð¼§£×°¡µ~ {*æ¥P «-Ýä§éüéýô:9¸gÉá¶ÿÎÙ¾gþW£è™k¢¤¬[ìÚ1;µÀû#Ø¿kU<Ô¶cìݹ²Ö�xqY×2á—ÑaÐG¢UŸ‰½þ!¦={mVŸ5kFÆÐ‰¿Éj[·vL ÷“œýíÞ1'&ϼððþ>zx_'D¿1ß‹ ë'øM@݆ŽÓŸ™VëNzî‚f™b}ëÖ�ÍLÛãàÚÌÍIY÷¬~/-z<¦>}eVÛüÅODÁ¬K޶ÿT ÍHa@z u7ض¹4hÝ!^;°¾Ö�t—¡ŸNÅÿþj¦Â´Ö?}‹ŸÕoÊS Ó V[áÓWļ…�¼Ó1ÒR�¬¢‚P'€Q“ÆEÁŒ‚ZyÒ©²ÿÆ ãå}å±råà˜8ýüx¢÷?ÆÞ�/eõKKÖ®ý¶¶_Åš5ùYmýF/JË{ÆkVfž°sûs1vjƒ4ƒ N_|™µÿ[7•ÖʓޱuVæÿTà/=ºïÐÞÒè=ò™zoZ—õ€»gm›ú¼ý +VŒ¾£¿­ûýG´éÿß™€aiI§:ñ@ @í ºí_kpÁ;öûÊ™Žûy½#úRýó³úîܶ,µ|">Ú¹ñ¿¿9%~zñ•1ãù¢œ}.ZúBœqK£øèëÇ'Nl—=ðPìØZV�ã@Á¬'ã³§žç4ºë˜¶_µja|ãì £è™Â·Úvm_¿jxMLž1)öT¬ˆC{×Ä q#R[ÎÍÿçN=7�Ï�í[Ê2Û5îØ>.¨qu�‹‹_ˆß_u}4ïÒ1štjÿ®·ß²©$~táå1ý¹©YíW6nÇ ÇíS 0¾hBVÛ¦ Åñ©“ΪŽñ€ ÝhÿúòkbÝÚÅquÓ¦1bòèwµ}úVÿ·W\—õͲbåü4¥ÿ·nÞÌ8ý¦ÛrÚ_Ù·6þëW'¿¿.>€‚¼Žæ˜´÷ª¨wíM1ñs™×?»äÊ(.�ó®öqÃ#�Dÿ1ÃrÚïÙ53Ýÿ®Ö­ÒúÿÌÚþ3om«W/Ìê÷@û¶Ñgä�·^ÿð‚†ég $Ò²€ª|�`À7Ä_î¾7&MŸ”yýúÁõ™›ôW÷¯«ô>ÒšýKxðˆï�rÃ-ñÍs.Œ^ùƒ¢b[ylÛ\�÷�“¯¿9«ß®¾!f>_”¤']—é €cuwë¼è2¤ÿ[¯KËçÅ�/º¼ÒÛ§›úo�sQ*ÚwÄ÷ÓÓ†N™3ãàƒ¿;-«í“'5ˆÍ‹s¶ï1|`4ëÒ±*cK²ß—íû¾ô·¿í‰YÂÛýÏoN‰»W¿½Þ@ ²Úþó—'qÖÁŸ®¹1üßÒ0 ºÜ×®Mš¢_©¾©Àß×Ϻ êË~/{@ÎsüîÚ)­ùÏjûôÉg§õþYmC&ä§%Õ=FÔ¿ùö˜õ´J‡­úô8jŸ[[<÷î·usIf™@»½ã»ç_{*Vdõ»ªIÓ´¿ôìÿL`ÐwÔ�¤�¡ºÇ€Tq?­ë¯Lß4�ùУߠïÞ±<>øP|âÄññzgƵ͚±^@:f*$ø±?�‘qá=÷¹ù@ €@ €€@ T^IY·è6ìóѲ÷?G÷á_¬+ãüöîÆ’å øß¶m›ÏˆólÛ¶­±mÛ¶cÛ\ïŽÍä{÷t^n¦÷ö¢ö®÷KòˤºjÎí®UuUõÐ` ¼""ð’� žýÈî¡aص£C×fz¼�¾mcá5'÷ÓêA—f{�Vxõ9‘Ô¾¾F-W/šòö¼�¼##±O·U1g&êáý}ìÙUˆõÅ,Nw0oDDDDDDgÃ@oo#^utC}Óv,NcnrÙ°ññ×µë謓æñöº¬ò©³>¡íµxÛÍ m¦¿‹3ZÞ�U”ÿ@«â6·» ·ìæ�ˆˆˆˆˆèl›p FWw½îÚòìž|ÏNw­ ¼™ÙÇåfR ®DG·/b³.†[Ä7°6?„éñ:Äe]§Ð/¡­ÓC×^ÚFeü_këþ5d•Ülñf:(é° ú”ï˜K½r<áÿk4µ:`p0¡)…cÈç�ð[«ž=ÏéSÇ¥?òñÃÀ@³EÞžzßþ˜âùÄþÄ¢ïÜ"¿e<ùÐé…°Ô¿›rõExD}éE×bnªE¥�zÞˆˆˆˆˆˆèøŸÐÑY — ݵ�„846W—›‰Hû‡þ�H,L·i1™bx8ÉTn‡oìÏ´¿ÒvkÍ‹ð‹ÿ%zzC°<Û£µ/¯zÙ¥·ÆŽLÿ/öî.6ªSŽ'÷!oÃsJoÓ&(ÖF¤ýi1ðÄ»vX™Õ]“‰Ç€ «âÆe_*y8d½ôUXÊß12’¢õŸä©´ò S¯Rl§�·ã�ˆˆˆˆˆˆ3ãxËÕ == ºëxù"9;ï¸{ãÙáŽ{{¤N™{äwP×ü¡¹ìñM´v¸›ËòV^ÞÈË>t¿¸Ÿcþ ·Æ“ªàõ=ÃØ2hßX3¬S�çöU£}é§Å€�¯¿¶Uc~jH›hk¯‘-²¥Ãª¸^Ñ?ÐúǸÿ ´úÅ™NÝui/«Ú)äí¸#"""""â@“6À¯¬­Ð]_�Ó¶¤åeafb³&ùeùr�ò�È Ð9ìËXžëý¤Üª øWçÍeY.® –+îAeýkÇ�7ñÃâúìd#âs.7þmÅxòÆÚ.èÓ˜¯9ƒþC:Ö˜u�ÛðئÃeE@Kkµ5÷)v™œQî¿ÕùÙº¡ÐN!oÇ'Öw "9¯8¸¢»§á(‹Ãxúå‘åå1™˜Ë##ɈÎ<sÙ\/Ûd?¸ýøCCñØVû²ño+ÆI•%ìæòé´@|ÓÅCð/Li2™7ªM3÷½é#£eú»wæ!8é� íòv|q`Ã$&-Å[Šä+Gpb_/ÞpöP¾‘†[l¹oSÙù÷n.›ëå­üÊ\ßQÇ–mCà ÆõŠñ[íåMöi9`ç Ÿ<üÁ�ê䙥ïײZÂð\…¢­©µSÈY9°aŸ™ŠÖöÃ/sÓÅSÎÐ]Ë*ÌAbVšê�È`_ùæ² 8eR@_Öêe_¾lPŠ=¹¿Ò¸^)žÜÇý¨o±9'd oq œàlU\yféûÃõßÜd³îšlÙðŒþ>öï)Sk§�7""""""²r ·$åÛKŽøÏrà_AY�vàœ,7/ª(Ä[®žRV¾Yb.'ÃëËɆõr2ñ¶Geð¨� ƒÇ²Ê'‘Ur‹al9­¿¢úY¬/Ž`i¶G?¨T‹gþ*Áé˜Lù`f¡v ¶j£µ­¯;{X|ÎQ•<³972‹oDÉöǰ8Ó¥�á mC’ÿŒmµ¯¨·SÈY9ðø»vr€œ…WÝtíÆ÷öh“Ï~äˆçmœ–�éñþcþ€ À�¦,‡ÒÉ ]”eåòÍxYF¾2güÛc£éð‰ý)‚?'o›õûÊÕâIó}œnvŽuÀ-$TËÇ ¶Îp AOoƒjåg–ƒ³JnÖÚÉ·ýÃRÿ�Ž.õvŠy#""""""õ ²ÞÇìÝutWïñ^}ÝÝÝ]© ÅÝ�¥8´Å¡8B‚»$x–@Ðàîˆ»Ü „]ë¹ü®œÕÜ$3�Û&/ýþñYÙgÏÎÌÉZÙÏ~ö€ àÿ'@àȉ=Ö çköƒ í[ÏÔµÚ]zXjúá�2¿¨×Ì>óïªaý¬NSßm˜¾4Æ~U¿EØsÇNîµ&¯õ¶ïWÿ?í«Ù¹»�N9è(·ïȫӵ§ÊÙwž­o�z½n¹¹oùoG%pãJ¶µêÛ_ÛÞí9´]x[µi�:™võb¦ ›6Ùª´{©ÜϪsý›†--iÏf_mظsƒý°f#uØÃ¶OÁ‡•ÿOû®_β3¦Ú?Z?RnËîMö‡&­mó®�vójŽé÷9sš=ùâ+þÛQ ÄmXeƒ&OÐ6€€wÏvìbÛ÷'…»}=ϾôX m—êüÙTû[ËçlÛ¾-¾®*倩“® ÃS&:ÎWëØÕvÜ×¾’yö•Çk†ûwÛíà±]ŽßCåüµÃ½}úÙòõ«L ß®ZÏÞ..°¢ÂÓVëÞþWŸ¨e‹âBÊ«ìÓ/u2•ýæÓuìÅ7†(pRæ¯-ڇͺøyÝf:ï¹>Q dnÜbSàæ_m^0=ë?5m«s€OÓI{6©ã]êù;7óíñç;úù?H±GŸë`…§ì¥!CÔ�uõ9�ö×ïñjȱ/>Z]í 9¦ÀÆS/uòß—žx¡£ý¥y;eØå é XõWºÚÎ[íÊÅ M-ÐO•µ‘3§Úïµ²„¤µÊXPy¬ÃСaëVp"Ü´ñZŸÚÑiÄë8l˜öî­B•×9@elŒx¨L*ã×ÅsiöûÆ­m×Ám¥–Qç1fõ2_×¹u=ת¾ÜÅŽŸÚ§}�D[JÚ¡rçÁk*À#í;XvÎñ�s·{I£÷víR¦¶iç�tk �ÿv¸¤µ¦-‰ îk‚…ñ±Á}�ÊkDþdòM�нvL©Ðm‡ë´ß- „=çµ¾oÍ�°ÿèN¥‚;­á(�½í€�¾®£ŽlóÞ}-q[¢öíý’"uŽ5­ýR;ÀJ}Wª¿FìÃÍ‘ÿl•gUF” ú}´Ã{àäkOÖ²âk9Ú·KçÓU—‚Á}-²¨í®£GÙØ¹3u躪#\†BÝn½´íä±>e è>œÔþ§ PÇWéà?©ÝDé꥕SçQiæêÌúº^ïñ!#åiGìï­ž+÷sJSŸ»Ð±HŸ¦h\ye ¨ÜðéS´�¡ÿv¸£û2mBZ_áCûÁóš&  E8áæâk�…Q³¦iÛÉ[}ʈpÞ—0àƒ;ë6z´MY<_�ç2ËöxsL°Ãì‡:¦¥ùs³2£Ó»ca?Íßß{x»û… ý·Ãa沺?Á}*º�ýáýày�Êkê�˺uÏ 5y¬oöòEÊÐö§� Îÿ«ãÆjѺrËjÎý¯´°wŠ œç}ê7!RÇñÕl¬í#í÷½ÚO}Ç€Z@sû}µÃ=uöÕÉ –((ð¡ýàyÍË×”/uçäžwÎs}=Ǿi3‚íú4š7®N©ëÎñ¸y³Ê+§÷ók¡>Oí¨Óµg¸©êÀ«ó«Î­F¸õv¥úë§ã€#fL5-¨,† ;ÖkÍ�šûl‡{Jïß}h[ȾÒþÃ�×Êü}"#LS)¸HM?l'Eé aëÖôŒ¡Ó&Û{· õû9‚ê ¾•@ÛŸ@à �T›þþÓ:Me5÷?+ûx¹u~뙺(:í©é×úá²Ô)WÊ¿Þm¯NôÖ½›åÔáÕ»öuíïV«o5:u v¶ý·ÃõÔwµ¯@ÅËC‡iQ@¥ïë]ÿz�Ÿ¦-„­{ß‘öËúÍMÏëǵ;ÖðRŸÊÛxðî€ @@€ € @¶¤æÛ¯#“Mþ95EÇ*ÄôÅólùº¸ÿ»�’Éý…2Ë4éÑÓb×.w_/€ €ÙÖziú'~Ý÷nZ‡Áƒlåú•e–;zbŸõ�˜Xêù¼Ü“6eÁ{}L¤õ9Î&Î�¶³��«p7®d[ÇÁ£ú•ñûŠÖÚÌØŸ–Yïù³)ö£ªu¬øjŽ»¶,>’kC6e}¢×|¿¤ÈÚôîc‰I aÏ¿{«ÐòóNÚÂUq60r’M‰‰ [.3ó¸õ7Á$¸s#ßn]˵„͉6jÚL�¯p)©GlêÂ…KÝ=F�Pö„¶J gB¦ÅŸÌ³ÈÙöÄÌTûó¤k¶8Ý2Ï:Ê&Ü+×xašýibŠ=<=Åz­Í´ËW‹J½è°ÍY¶èpn©çc�åZíè4Ó5kÎK³=™ùaËUŸ—j*»7+ß,H³?LLVù°e_<Ø¢W,ÒvXC'M³¨¹ólÿá]¶qû&[³qmØrãç̵´ô£!ÇÞ).°.CÇøz#ÒOß6ïÜlk7'º*;qá×lÌœ‡ÄN&G•[~×�$«Þ¡£¶Jà…¸ «“fóäØù+Ev»8`“ve[«ûR÷£vf[£…iv8·ÀnÝ+sízÀ"¶g[÷øÌR/ÚfYº¦„=·òx®5_œn¹ç ííÛuðíéÙ©aËêøÀ�Y6`C¦�»\d±«×Žr¶­³:�ºhÛ•ùËcíð±=FÝ[äœy•"0où2;þÖ~o ÿ¶3�uå–»r1þýDum�€FÔ•ªrLA�Êk[R‹ í±©vãFh§ûòµ€ýkZ°œC•i)¥f(Ë -PÜçö™à5ï÷×É)Ö#>³ÜÔÿ_Ôl`ùyoiß•áS¦»žÓóJŽ ŠšbÇ*E@m_™ooLœj=FŒÓT»|!£œL€¯ÛÛÅaË8¦I|æo�ið JŠJ§·›÷uìoÞ „¬Þ¯yü3÷9…»s+(p¸r-`ÿ.58à ‘}Ç•ið›Èd;s©¨ìŽõvo£ÿ ¨ã|·¤ìz%;û„:Úš6ð‘;ý¥øˆ‹i*‚­Ù¸În^ͱâ{6íØ¤E KýÌ­ë'mê’ﺪÿLÑiûIµºÚ<¥ó+ Üñ–KÒƒûšoŸ~¦ÐQîta¡Õ�v~^åh €¶ÃJ<�gmï�×Z B¨“?zk–£Ü‘ÜM=Ðv™´ðß²÷¯¯ &ÛÈi3Ê,s÷NÀ¬Œ³>c£,Ý9ò_‘wnæ[·ácK=ŸŸ¿Â–%>áª.Suë¡mÀƒ˜³?Çz¯ËÔ¶c¾ÿÔ=Á�òkÞ½£Ü”ÝÙ6*ÉÙi—¥Gsµ`Øs1‡r¬é¢t;š[ iª[�Ûp:/L=îÞ$ð³êõ<¥ÿ<²ÛbV”0øàž%kVÚÖÝIz €ŽUêÀÕ‹™6`ü¤RÏ=9Ê’ötpUW§¡ClÑê¥Ú<€.k2´�Ÿã¸FõóÎ÷™žb—®9Rü�‘jYg K}À’àÚ¡žœ•j¹ª_uk½€@˜4ÿá[²k„ó?ÿú¨Vé×¶++×'ØÖ][JíüÇ®]m§’i_*U``äd­IrlÝ–õ·n�¶ÃÚ´«½�8Qnݺ‡�¶n¯u´xZدöü4;˜S Eø¬àB‘Mß›cc·…”% cZ+@ jŠ@ý˜4•-õ‚íbÓUo© ¾•_`Å7¶+#ßú$fÚo£’õ·õ8|¥ÊÓvõb†¶]™|ÍŸómmç¾mÚ®”´àßæ›íöõ<Íÿ·¤][lPÔdí—þ€µU¬¨0¾Üº£æÍ´%ñË´ xg/Ù¯#“õš>ͱ×<|�ÌÛ´=9öþçB|ê¤k¾þŸ&¦X“Ei¶îThgóh^�ê ëwQÉZp0X6û\¡FüíSR¬ßúL”u ú×Ö1eh»,UZ¶µ½‡Êî´÷~3Ê:åÐgÜ„Ðø!c\”«8W.d(`=F޳^£",:.Ön\É.;à±èvçfj¹‹ÿU}¡ƒ}p' }ÀƒؘœgõbÒ´ý@;kª½>vt˜s¸rq·Í]ñ›rSÿŸl÷‚í?²]û€%ðæ¶l�ökû�pýr–ý´Z=»t^A øµËìnI�ݸrØ–®{ÌŽ�,=8r·$`íûõ³¥ñ±Úý¬í€�ö긱ÁžX³ÑäÓ(ýóƒÛ†ë]”÷_ÔùÿQÍÆ¶8!Î.�O·k—2mðä‰öÜ Á®åýù*{AÁ‹ÈèÙê4j_åʼîÆ�Ô~kÔëuí{–›û–¾›–´g³Çv¸ÿ~‹ûϹ*çû¾‰žë#í;Øúí‰z.vçf¾-Š_®cÞëw_Îûsqß^_ÏE×Ò÷ÈçóóÜ^Ï÷ÃÇßÁkc•Eä8¾ýµE{«Ñ©›þ鵈ù³Ô‰ [®ZÇ®¶c’ãŸì¯<^Ó×õ’ÖÚ©ncçÎÔ¾/Ëׯ²§_êdß®ZO#›öâC4º<ߪoÿ°ô1sfXŸÈˆ�c­û PçZ÷C#zöÕ'jÙãÏw´”´C:ïÐyäH[°¦Ì÷òkÄ5Ø¡�Y½ÌÏ}QEeBŽ� ¤èÚöÌíóÕ}9sªcDY£§áê=•rÀž|ñ6m²½1e¢çv©î¿µ|ζíÛâ¾Þ¿ßâþsÞ˹l¯Ó ƒß°…ñÎï•÷úÝ—óþ\Ü·×ïs‰Š™cçOñ_¿ûöz¿>ÿŒ«Û­§ï6€@y� u¢]—ß²{“sdÍuÆ¿ôX ›·X)ç!ûÈu©Só»F­Ô)¶›Ws” ¯´­ÃСÁ2Ï¥Y•v/Ù­ë¹ÁcJ×WšýÝ’@H}uºö´¿·zÎ&,˜kgÉJÉUÇCǵ7ÝkwÞ¯¹nkÕ—»Ø¡ã»?ò}Ùwd‡ÕîÒÃñ¹wŠ 4жwҗu?BŽéÞ„»®�>×Á NÙKC†xún‰Fctqލzk‡÷ï·÷Ï9ËùoovÎqMñp÷^¿÷rÞŸ‹ûöúy.ʲ‰ß’à¿~÷íõ~?üý(hÌøù °1⡲ø¾¨:¼©é‡Ë-§TY¥ŠkZÿDûYs`Ô¬iÚÖ�:¶ÚöJéðJ½Uß‘’«¤ïËŽö+EX#múþþ:5xƲŽŽ’2îOýWà¡ à¤Ûöj޽îáG¾/&FÙ¼KBF;õS M жw®ž¯~GÛ£W-u\WA:ŽŸÚ§}ûW›‚Ùn)}Û™)á²Þ¿ß¾?ç,篽£gO×¶½>~œFè•Õbõº÷²¼¼·¼×ワ÷çâ¾½¾Ÿ‹Êö›ijÚVõ+@eùù'½×ï¾½Þï‡Ï¿ƒwoj-m€ €�‡þéÔ?ÀZÈ®¼‘F¥°ÿ»í‹ÙÒ± ×uô(¥Ê‡ý�¾öd­°+m'nKÔ"wm ÷O»Fà5ÞÑ1Öb{ÚÙ¼k£§Ñ-òå\$Ì›§^ê¤t}G@#�Jå÷^§ûç«ú§-‰Ñ½ÐüqmÛŸ›µÕ½ –Q6EóÞ}u�ƒA}·ô<\¶CÓ/´Bpßs;¼¿}}ÎYÎ_{E)ì¿mÔÒæÄ-Ògà²)‹ç[õWºz¯ß}9ïÏÅ}{}=e¸èïR™=Z÷BY>ãçÏV¶Ž÷úÝ·×ûýð÷w ¿; f€€Zí]�>7eõ�·© .fUÁþÒ¼]©+rk¤0Ü[�ÓjüáêÛ}h›2ÂWçÛ‘’ì%­|ç�­Î‹Gß­V_¯ ûúÁ¡Ó&{¯ÓýóUF€:N ¬håuM‹Ðè§FSƒez��PÇ2¸Ÿ–qD£°®¯¯Î˜²*ÔÉ wßßßoïŸs–óÛ^Q h麎à”Fñ½×ワ÷çâ¾½þž‹“¦ûèwñ^¿ûöz¿þþTTà@ÛøX0`ÉÚ8{yè0×å•\ ®‚©œ×_ý³þL‡Î›¸Òš½Þ7\�*ªcï8®‘Ç‘3§…ÓÔéÿšV ”c_¿ïç®vQ¿×‰Sû|Õíõù~p' ë†LPp¥4m.¯ÎoŽ é8‰·vøÿ~;?翜—öŠF»o_ÏsŒ«Óé¿~÷åœÏÅ{}>— @ÑiûuƒÞëwß^ï÷ÃçßA·Ñ£Õnm€ €�Gÿ ‘6yÑüpç4?X#mŽ‘l­j­í ¦yþJßuõj°Z�»k>npê@˜Ñ{4ÏÞq\«|gfst"”šì¶­ÝÇŒ¶ù+—øù}µ†€æû;::Ùõ^Ÿëç«ÑKG9-T¨·-”U¿æl+µÚM[ÔU‡ÎyO]¶Ãû÷[|ÎQÎÿ}Óµ²1BŽiÄ^ßM÷õ{/çý¹¸o¯�ç¢t}Çß¹ÿÔH»÷úÝ·×óýðñw ú”eäeº x¦Åð¶ïO*uÕzu\õÏ·FÚ“ölÒÈ·~ê|…ÓJÿZØO£ûZÐO ~ œ¥·Cæãê5€š�û¡9ýzϽ£Sñ“ÚM4­@�`{»¸ÀrrO(EZÿÀ;®­Uúõ.q·m}¶cÛt§ŸßW6µE×UFufÂ�âê÷Ó‚~Á}?ÏW ¤ij€î‰Ö2P6ƒÞªPÞï¯)º—n;IãæÍrwÝïßoñý9g9ÿ÷MÏDX}Fßm½‘â�MÛè{ë¾~ïå¼?÷íõõ\´à_dôìà÷~ÒÂy­÷þÜÝ·×ûýðùw ßiÙº•îë/#¿áÒSZ§‰c´Kÿ¼*%\ïØ×Bb[÷nÖ¹JA¥ùþ FCMТx IïUÚ}˜t]½RL�m‹FÖuÔiPçH#üš+­Uùµˆ—ãózý——½ÚXz‡Åýy-<¦àƒhQÃÒR¸u^iÒÎsÞŸ¯Þª Ò4GZߥ@;QtRYµYÛåQ‡.+Ûù»¸o‡÷﷗Ϲ/çÿ¾iÊöiáI=}ÇÕQu?¼—óþ\Ü·×÷sÑTô�Vý ð©óî½~7íõ?¼þhú�2”4-Cû €�ÙªMk<-X§õœ™áedÕ4m@H꿲ƒ‚ “€>~}£Æk´ßË;ó5X)É¥ŽVk>¯2 ôªµ™Ëè8§')›A “~‚×<ýR'­!àé3qVY›þžûW›ì �T×tÛ´sCð8h=­é±nÛ:î@@€ € @¨T\¹°‡§§h»ÂM_<Ï–¯‹sQ7¯æX¯Qt}4éÑÓb×.ÿÏi3‡r ¬í²ô mÜ{· ­ÃàA¶rýÊ2Ë=±ÏúGL,õ|^îI›²`�½>&ÒzŒgçGÛÙ€3¸‘ŸwÒ¦-Zh¯Ý+×sd„EÍ›o�ÂäJó° NÛ¤èë1bœ:ù6gÙR+¾šR&#ã˜�›5Ç}î˹Þë«øvx¼îù³)ö£ªu‚çTz–ɵa›³*¬aï—Y›Þ},1)!ìùwoªÃn WÅÙÀÈI6%&&l¹ÌÌãÖwÜuíÎ�|»u-×6'Ú¨i3åúELT9+¹‘g·¯çÙÚ-‰6|ÊôJÓùïýf”8²[£üjŸ­Ù¸ÖæÅ. )·cï6[´z…ÿúÜ—sÿ<Ü×'Ûíí1j„²V´  ò# ÎôÁzïç?¦¦h:€­?�¶lâ½ã­–¦«œýmrŠõIÌ´ë×Áó=â3mGz¾3µoŽ�Ùš­m‡—¶è‹´ÖÐIÓ,jî<Ûx—mܾI�²°åÆÏ™kiéGC޽S\`]†Ž 99gž¥«Ü}�É®ÃÞôuƒ7F<¤Ÿ¾�ž>ËNœ<rìÚ¥,{uôø�cKãWÙ¦›,~Ó:�~«ýöæÌÙv¦(Ù}}Þ˹~në“ m‡�öî:�dÕ;tÔ6€Ê�€Òÿ.L³u§òìVqÀ’Ró°÷ï„–›²;ÛªÍMÕy•³«×µ3Ûú­Ï –¹|-`�îÕURÛ”’g½2íî}õɆmë¬N§.ÚveþòX;|l�ëò)©‡Õá/·\rÊa� Wx +븦-„™"Qd�†Œq<†Mžn‰IìÊÅL{ûf¾­Ýœh³çº¯Ï}9÷ÏÃ{}Õß×½r1þýDum¨üT™–b 'CGü7!Yüà~Z ÐªÎIU?¤\áÅ"{dzÊýYÁÑþÓ……öb\†½};6õÿ5X~Þ[ÚwEiúÎ9ýáݼ’cƒ¢¦h®|©e4U@S4ú{ñ\Z…V­O°Ýv÷‡Mž¦Ÿêà+=]Û"Z¿ÀÑéU Ûð±îës_Îýóð^_EµÃ÷u•9ò™¿=¦m•½àSRìÝÛÁcêøÛß§„v¦†lʲ™ûrœ#¤%gìÏ“BËJ÷øLÛ––oÏ-ON¸ßÆíÞFÿ0ÐâlwKŠÊ-›�}ÂÞ˜8Uéᥖé?~’u<ÊFN›¡Tï�Üé/�Î{¤Eý4=ÁÑMI=òáL742­¨# ¡E Ý×羜ûçá½¾ m‡�öž):m?©VWÛ*5z€:é!ÇŽäX‹%¡ÇjÏO³_G&‡Usžsä\uè܉ü‚R¤…ÿ–%¸~�šVéWg½Ì2wïlÁÊ8ë36ÊÒ#ÿNZÁ}ç¾m6uáBíWx€æ›_¿œí8®6j®¿¶E¿ÛÈ©Î{‘›ó–Öp_Ÿûr÷ú*¶>Ú« V£n=´  r# 7ŒJ ý^z4×o =¦Qþà¼þr(« õÒt­)`]Öd”ZîgÕëyJÿ?xd·Å¬(=`ð�~Ÿ5+mëî$�„»­WióZ@¯R:½1Z#ÚŽãš×_�êCoØvuz­ «ûúÜ—sÿ<¼×W±íðÑÞ¡ClÑê¥ÚP¹Ð–Ë �O½%Ë9¦yþŽùÿáܹPF�%§$–òF�ÿù×GµJ¿¶]Y¹>Á¶îÚRjç?víj;•|¨Ì:4ŸûÎÍÐà€FÓÇΜ]š×¯y玮V»ÿÐ1:ôêBÇô6€ógRÝ×羜ûçá½¾Šh‡ïëê~?Úº}p€J�€Þp,/´Þ.6Ýd‡ÓJÿZØO£ûZÐ/ël¡Eìȶ¾‰™Á2Zå¿Çÿ�ûœ«~3`õcÒ¾Råi»z1CÛ®LŠŽ¾æÏù6��J×.·�èêõyšCÿvq�Þ wÈë§ÎW¸ùq±¶21^ï ×ôÛs`‡õ7A :æ¶™4U÷CP-€gQóækôß}}î˹Þ뫨vø¾nÔ¼™¶$~™¶T~ôº¿7÷stØU¦ÿúL�Ót«�¦×jÄ?XfôVgæ€lIÍW`Àq¼J˶¶÷жòFìµPŸCŸqBÊiA<7åÔ¡ÓëÞ”òßkT„x³Ô´#•æ!ݺ–ks–-ÕB~b3—,vtB?¸Тwêôêíú]lÔô™vðèn÷õy/çþy¸¯¯bÛ᣽Zü¯ê ô,´ ò#P‘ÆÎšj¯�­íÿ€RÿŸl÷‚í?²ÝMy pýr–ý´Z=»t>Mû@¥w·$`íûõ³¥ñ±ÚnÅ®]nÍ{½ªm RÓÛ"Úõík ›×h€ @åAàdò«Û­—}óé:ö�gë[»ƒìò…ô�\ßù³©öÊðáö½j Lu6~µ·ŽÏ_8—jŸùwÕ°~Ý …³Nøïüÿ¨fc[œg—Χ۵K™6xòD{nÐ`�÷ìÊÅ û}ãÖ=ÛÔé×þˆSCêKÚ³Ùêuï¥íOißÁ’Ö†;HÑè}p¿Ußþ¶aÇzÇgÇÌ™a}"#BŽiäÌ©ŽŒ€×jÜ�Š™cƒ&OÐöÇ ûŽì°Ú]z8Ž¿S\`_x¤zpÿâ¹4«Òî%»u=7xlõæxkÓ€Ý- h?èWõ[Ø™@rȱâk9!õ½0ø [¾~U¸6@`cÄCeñ|‘£lÞŠ%Áý¿¶hoúYXpJÓ´-¢{p´ÿØÉ½V·[O»s3ßQçWŸ¨e7®d‡‹^µ4¤¾¿·zÎRÓk·§^êd;ö'9š£_­cWGù–}úYâ¶D«Ù¹»]½˜¶N}nÚ’S@óÿµýçfmMŸÑùwoÚ­vÀß6jé¨Ï'|·Z};w&Åq|VìB:m²ãøžCÛMõƒÇv•ZgvÎq«Ñ©›}íÉZöóºÍløô)³z™�ž=ÝtþTÊûW›´ýI€)Ÿ¸šFäÇŸéÐÙNœÚrLoÐñØÄ•Öìõ¾®¯ñÁ�€és hÉÚ8ë0t¨¶? �ðýê 5ß_Û"ê k?äXÉ�<«Õ¹»ÿ¿A�®£G…]ÄOsûo^Í 967n±½øÆ�à~¿ ‘6yÑ|m  Ž¹:äz÷ÿå é6åûY�¦ÁÑzÑ*ÿz  æþk_4¿ÿ­Ÿ×ÛBêÓ»ý5}àíâ»p.Õf,[ ·¨þ`™:]{×ø@@‹ôµ0оõL]Ñ"!�y}ü8-äçølü–BŽý/öî:¾ª#ïp×ÝÝÝÝÝYwíÖ�­kvëÅÝ58 n š:îÁ’‚[<õÏç÷Ò³š÷æ&Ð Í-<<Èœ¹s23Ø|ÏÌ¡¬l]|+’ÿ àÉ·þwê|GÊË�–'÷=!} €@@ €€@  s7–Çw†LJzmŠï/nµþÀq#"ovþ3r@~Þéo1iVÞiõ‹à¡CkcQßWÄ�ÉÏOC€=wÆ—GIeE<Ö°+ªª*ÓÖ}´¾"Îι!¦Ì�òŒ�½»‹âmßnµ‡·Ÿ6¿Ž”ÏŒµ3:ú p:SÖ”Åõ[[m豆�ñû+¯Š9 g>ã¥Óm·$»NõÉ_3íG±nFÇ(^ð×(èvFbqÿ×&×8M€¯)Ž÷÷ØÔÄç¥m蜜œ5yl³×¦/h[·�N)`åÕ±èþsSÊ®ŒE}_žqçFMûXÍã·gãàØzï•É�7^‡ËfœüqÈ>€êêÊøBúmÿ‰‚”§ÿiM›ß.¶lË� ³¿�ÕI»'Ýè韊†êMÿ³¸ßö¯-ë›Ó~f×Î�ñŽï¶ÏºÉÊ|üÚ~œ²�`UÙŽøÃÄÒ–H^ü7qfÞ1ݬbÇ´¸cØQ¹sÖÓÖÁe«sbí†.MÎÍ'ÛÕ[ 5~zq§¶Ÿ ÌÇ/«Ç K&®*‹›æom±�w}¯CkÛÿõUbìÌÏEQÉ€˜:ïO[«­Lž˜ÿû,ýÄÙ_=úãÊ?sþ�ÿˆ±Ó&´ý€ÌÇ/«Ç Kn^°5&¬jùœùó?ùåx¸vG‹u­ßž,÷ìš—ü¼àž?&gÚŸ®NŽ›õ…dË|Á݈]•³[ª›ôåË¿ûSò€¶Ÿ ¶¿ÌÇ ë þ8©4V”µ¼¸Å¾‡÷§=ç�¼ ~ú‚öÉÙõ•%ÿe܈)zòIqJýʵ½cÜ_�ÐN®Zwkܳ¬SÌ-üu«u{ŽãgLlƒÉÈ`üÚ^úqÎ~€/,ŠCGZÞÆý…ßü!î_¾8íõ…÷�+×Ý’R^ºex²°ýß²ÚÝwÇ’1ŸˆÇê¶�ÐNÖU­�^c^µGÖ¶T/yùß·Ï<;žhlƒ­ëŽ_ÛKçl ÈD—!ýãŠ.·gú…$‹þ£‹ÿ$8Ñ�,Ý2,ÖlèÜêÖÿ¯ÿñÌX²²Ð/ŒÌÇ€S-¨:¸5ÞùÝq`oI&í$Ûþ+×ö>�[ç+¢¡zc,]}}«[Òo¨Œ?]sML˜1É/ŠÌÇ€S0HLš•¿ºô²¬êØÀ‰o�~ãÞ÷-¿<oÜ‘¶ÞC5Ư¾:fΟîÄÉçì €@ €@@ €`ÕÚâÚn½Ó^¯;RgN‹+»ôŒ oì·ô%¥«šÔ¹æèçÏ͹­YWwíÕýÀ#uñ`ùú35?®ïÑ'úåæ6[¯¾ª€ƒûîNžø÷Ì}YÌ)üU4Ö”ÄðÉHÞðDcE›ÑWvîçæÜ–⪮½šÔ«¯*�á“&Æ¥·uKäNÎKw¾?9°owÉi0é² €€€)Ó㽕öúáý[âÒ.�ãí?üY¼ü+ß�ÏþîÌ(\²°I�÷tøe¼àóßnÖ»Úý¢- Õå±zýýqþ-·Ä~ò›èØé²fë9°%¾ô§³cnᜨ>´-kŒ±3ò’²ÖîQV¶.i{á}óÛb0@ðÉ_ÿ)¾þÅÉb¾ÛÈ!‘Ó·w³õÎÌù{Œ™1é¸Ûß»»8>õ›?Çâ´Í`€ u‘Ÿ7wjJù¶ík¢ýÅ—o{É.�¯þå\Oþàx€‚ng´$ã›~ú·ŽâÒ)巘츢{×äüÿk¿Ù.:\ri”—¯k©½äXAî´‰Ù2¨`À#uÉÂþÑúŠ”kOøàOÃòÇÆ¡ý›cÿž’è7nd|+Ҷ7nf~üáºë³iP@°±hY|þmîZòöþ ³'7)««*‹W~í‡ÍÕOB‚ýô·q`oi6 *80~V~œsãMÍ^{ÙW¾õUåMÊvW%‹üæêwê|G Ÿ›mƒ v\Û«Gô;2퀃ûJ›”Ý<°_\×»g³/ |ÿ�×îȶA@û‹ÿ…K6{í’;nO‚}{Š“mý½F��þâ÷Q}h[JÝkŽÖë:bH¶ $ÞöƒŸÅ >ÿíïl÷ó&õªn�?]C¼á;ãõßî�Hs¾?9°uÛ“€€¬@ €€@  €æn,�ï +ŽõÚß^Üjý�ãFDÞìüSzL~Þéo1iVÞ1Õ}èÐÚXÔ÷ñDcÅS¹€`ÕÚâÚn½3¾ÙÖ­k¢÷ÈQqù=âÒÛºEÿ1câÀÞÒ&uªm‹ssnKqMæ÷OÞ·(®íÞ'ë&bÏÁ�ñåAÅQRY�5슪ªÊ´u­¯ˆ³snˆ)s§$?ªãWw¤,&ΜWvéÞØ9né?(JJW�øþe0¿{wÅÛ¾Ý.jooµí#å3c팎Çóõ©«ˆË×ǘ©ùq}�>Ñ/77£m*Z9½úÅÆ£ß7Ö<˜,>g/œ]mR¯¨xe œŒÎnØ´<®èÜ#¥ýl0eMY\_°µÕz�5ìŒß_yUÌY8³IùñŽ_}UyÜ>pH¬ß¸,ªË“ù^²âž¤ì¤ô1ƒùítÛ-Én‡t××LûQ¬›Ñ1Šü5 º�‘XÜÿµÇÒ6€àÆ>¢çðÉ¢° p^L/˜•Ñ�n0(¶o_פìáÚqÑM�›”Í¿{~Ìš?ç˜Ú\±ú¾è:dX²› Ó-]cdþ¤$Xh®îΓ°aæÑ¶§ÌÎtà’E托€¯)Ž÷÷ØÔÄ祭NNNŒš<6¥üxÇodÞ¤dn[©—h<¸2õ}yÆ}Mÿõµìž¥ ã{gŸÛb�½E#b^�çÆöû¯I[gí†.1,ÿ}Ñmä cHÞ{¢¬lBRžp Y,&‹íLntÁ?îHž2ÿOY²Ýüè¾IÙˆ¼‰±fÝ’VÛ›½`nÜгo¬]¿4ÙQP{x{²°Ï�œ—º5üÀÖ¸cÐ�8´KŒÊOúÒÖ@Š3ó7Dzí;Z¬sçâÙÑîü SÊ�wüöï)‰>£Ž}GÇî�ƒã�Ü�dÞÏcŸßÿcï£ìȶŽ?ÛolÛ6cÛ¶m»mÄ6ša»;¶Óˆ±�ñì7û¬5÷å®ê¾wî­¬™àÿá·fªrªÎ© Ï>gïrrêxŽÜõaé’Ÿ'{ª,ü½lô‘¤�¿ýplÝa°ug€L�yMNÏ”¯.í7Á€ÈY\Û ‹”ÃE»lu422Ú¬¾ëÖs ìØ¹Î¤äæn¶ôµ 1V‡›U}M=8y,Ç©MAþ“–pþ”S^¸ÖÐ-þÎ…á.ä‹ß¸ ’`»9%‡ wÞp€÷£vËÉ3E.·þ?^¶Š<°µø6¼¿Ää%fõnBŒÉÿ×v¡?´;qÔ´³ËÆøJNGùã«ï—\?aG´äeö4ÿŸ“ÚQNï�µ´™óª=¼âÿïóÒÝ ðã1Љ§NÔ¾¹\h«£ ›WJ›kŠ¾éŽ€mÛ׊sq»Bi?d´YÉ?zŸYÕ_–¶L :µ›³@–¤,-v¬‡ù8Ž¿½R$Q3¦;úùæJ‘>‹¶óvÒ_"[…ñÎÉÛ»\÷�êfõ߃÷§©ýB%cuªI™Ð@Jrf’L0yööÙŸÅ¡Âòp©Š×¹á üx Š vjþ¾í€ºb¯q-8§?ÍíîZÝÞï4©WƒCÂ5ˆP]Yv´›—#)YÉŽã#E»Í ´9¾�vlÜŸ/ gg»l£…ÿfÇYÓ¼y½}ƒdíÆLËN G=[lŒÏEð£ZÇÎöŠfGÊÌøw$dúÅwâïeôø_KòÊVúc ¬Ý�iÍ«÷Œæßë'-u5ØÝµ§�çJ?çÏöé„Q'¬î®Õ€@‰‡ß0€Ù÷ËÐåy.Û‹¶CËôEÞì[¿eˆLYô²ÄÈ•ó»å›Ëùfò¿;Û€ ÇIrÆ [�´b)¨547ßéœnKwÎë7Åþt%ßéœæù;Úy@sÏu«û�¶`ØŠ<™µq¿Ë6xå=ˤ]yñþt€å»úº#cáâ8ûÏc|–@Ñ{õ[~ýx"bÖ}ZüÏq|ñÌV žö9{r�+ 2y²VëwYÔmã–Un?¿Â”+çÊök¥¯ˆå¾ZnyÚrmg&¨I+tUZ��Ú鎄y‰±šGn&†‡ wÉÂ%qZáßå84×<;gÓ ÷“ÐhN¶¬ßïzrÿÏ·?‘ÓÇs,ç½y³bšÀιS{Í;\‘¾\…iz†5dK°lO¬mëù<ŸEàÄh™;ÛV¿Sb^‘CE rõBŽìÛ7CRjʘ ¿‘ó§Í¯¸}=Ç»m¾—o�¥m—~º�ÛM·]4q’tá+ÝFù›"t9¹ÖÉשc9:IÔvúm�Ðë$ÕÒN'Œè1:À¤ �Еd·+äú\ZôÎß@Þ‰Ü%§\|@½]·¡¬\—b9ïíû›0g¶¶Qú.5`iwápº¬žö²|}ÑÜÃ6÷ã³ÿû¬YK-æh«ß“ÇÒÍŠà”¿Kbjm¹r~�L˜ÿ´©ðí•mìÀ�Ágl¸ôðõ³õ§“~�ükà—x^ æ|Ô¨™¬Þ�ªÇ·‡³'óä‘R•äÄÑ=?Kºí_·ÿÿÏúÍå"iܧ�ÌŠ�£Ç·—9ñs¥v×n·ô3^=Põî-qËcìÜ@€ œ>ž+]}ÆÈCåªË?Þ/#oÔo&©«“œÚ;²[þøÖg�U¬åöþ¶dI•.Ýåþ2UåÎO+Jùö�ewöz¯Æ¡¶í\#;v•;>© w^Yõ '�e—Ô?Μȕw·”Å©‰rîÔ^¹rþ L��«çœÚ%e-—j]{x|ÿ¬u©òh…š²pYŒ¹¿Nò‡F„ÊÛ�Zx5�ü?X¶ºÌˆ›''Žf›ë†K“Kš $ÓÜ×]§Œ—a‘aßÿóÖí-«ø—Î�¿¿_Æ«qh@ .)ÞéÜá¢]ro©*ŵ€ÀÞ}›u+ýOjÛtà@‰]w]úMÊZ&¥Zwðx«6¤iú€åüòå¯ï–¾5~ò–úýÊ�;5.Òl³ïáïkòî5§¾R§®ràÀVKÛ×ê5‘>Aòb͆¦]åÎÝäàÁm÷yüÈy®z}ÉX›âñ8úÊÄù3ǯÔilþ[�¿]ÓŠëv”iÛQž©VWÆÏ›.§Žç˜ÉyØŒIRºMË »nÙlòîµàžÿ¤qR¡C�ú[½1]ºÕß«q|Ü¢­¤­N²´>�cG�3hq¾Y ó�Î]<»_þõa9·×ž?½Oþý‘ûvêëË…ÒzèPy¸| I_“ìõ8î)UYŽÚe¹~ìœi2$"´˜¾ @Wõµ Ÿ¥ Þ³Õê¹½¶¨p‡«$­† Õ ¸¥]~þ6¸óÓŠ¦]‹Áƒu²îöþúi¾?¾õ™Å#jx5-ذ_3U·W&ÿÿkÇ ‚JúרŸûÚ@?îæ1%@€@€ €@€ @€ € @*ãh @ø_lëô¨ @€ €&€@€  ¿ø9@'k÷¿H¬äIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/book.png000066400000000000000000001342121526573132500261720ustar00rootroot00000000000000‰PNG  IHDRT›Ú+¸QIDATxìÙjE1†Ñì¥ÏݵL �Ô%½Õ\fð�?]¯×àw ¨€ @P*A ¨T‚ @PªËåòÈù|èÚS=òcƒêÅp:�N7Çã su‡T}ÒId}ú UÔáp¸Ùï÷i·Ût&º£î�:°ºX¯šCêaD…: ¶ÛmÚl6Ùz½ÎV«UZ.—­¢/Jk”öˆ)�UÂ굸ê<¨ž ©g#* ‹Å"›Íf7Óé UÝ¥=J‹<WuX5EUSLÕ!UGTTâ|>ÏM&“4�Óp8̃Aê÷ûY¯×ø¨ÒÑ¥9¢?¢C¢G¢K¢O긪ê9ªšbª,R%¤Ê •8�ò3wìÛ‡¦AGñÿû?UŠ$Dº„ô^^ã:VÙ‹YÝÁÏ軟~|3 ÷ûýòù|ò~¿ƒçó™âñxpJ’$IRµÒtýA‡Ð#tIÙbÑ+%¬ÊƪkTuŠ©æVŠò£ùa~þûý¦ÄÓý~ÏõzÍù|FŽÇc‘ÃáÀ)I’$IµJkÐôG‰,º„>¡S躥¹­ªˆªŠ j‹)}±>£öš!õz½"—Ë% ·ßï³Ûí²Ýn³Ùl²^¯³Z­‚årÉ)I’$IUè :ƒÞ ;è:„¡Kè“fXÑ/t =ÓU݃ªõÍë1>Îʬ\ïãþ"x»ÝÂÏ3ƒÍçóL§ÓŒÇãŒF£ ‡Ã ƒôûý ×ëqJ’$IRú‚Ö˜L&¡=‹-RâŠÍaE¯Ð-å =C×Ð7moª:þ�)î%R{¼…:�N¡ g³Ù;w Y!Fqü`¯2`ÀžhÜèªJH„"¨ª¢PT z�ÍAˆ‰Å€ƒ¸¸÷þÎWüCX–ã8bt]‡¦iP×5ʲDQÈó\DDDDDä1vEUUhÛ}ß³?°®+{„qÅ‹86 5âbÅS@ö ;æ.ªÕý:uÆo 9�]bеÇȹmÛ6LÓÄxB–eˆãa"ø¾Ïóà8lÛ†eYo""""""O±+\×{#Š"$I†ãjžg°Oö}[å8Ž@ƒ.QžaçœQõ—•êîÃßž�â�oó»§4žõq�JÓŒ&Ã0¾Þ?>¿ÿ›ˆˆˆˆˆÈëõŠLÓüaï.€ÛV¾=Žwø13?fffffÆËLå&¹ÌPfffJšÃà:æ&Žã0’óÎOÒÚ+ûX±j�ÿ¥;óCÁ‘wÆÕ÷îjý ˜ÐÙºu+¢ ³UF§àR¤¶¶6\ž„Ë”° >K…ÎAïx7C…3T¸` ;b¨M(°!ê³SX§ˆ3RuuuŸ�úŽïùAútÝšNÏß“¦îw)÷&«% ê1™ÒRwo¢ÊÆË5ûðzd^xl7v·fJ™ËucZ’-2âÆT926ÃQôטu öãνo³ÅÆ]ð~,çtîÇNÃ{k¼äqš^hœÀiŒèá��ÿ.ÍD•LzjÞcs®¤³sô�ÿü/ÄçÅUóþâ¶*>ú_ul÷Ÿ¿úµ_¢ÌܼÑètÈ“O>ùnSy¡Îcø¶@p–‚3| Ó9 ê~hšµç'2ôûñO4Ä¥IN—-:äNÌ’äש}ûš˜Éòãw†vG34™¦þã(ÙÝM¡ƒû ÑCû(vØÔÏ↽”´ ³QÃng‡÷Ðd&J<7ÎF�_g„ ÙGI6Èâ†ýÔÇb–èáý:´Ÿ-Íô¿òó423Oþ¡yJNÍ‚QQµiÓ&=ª0S…Í*°ô×Sa“ |pá,&–*ªÂë§ôÙ)L‘aª ë=z473µzýŠŒdˉ‡ò#ªD<µA^ûÚ*–.ÒÚç�–…ÜQ仩 ® Ê1Å®)pR†” ��Ü}D–õ!gUcÎ\iø Õ-RàRŠCD¹ ©sîBJqQJ¯¤ '�¢ ¼*Å≸CPéQZP9œŒ+G@ª¼6NÊ•¨vP9„•UÆëðkãçÃÏjG›y|8víD]ˆ*pŽ*×c©G•‹±”ÆP�8•¢�ŸTJ‚ nŒÂ×'Dú�V_-ªŽšñ‹÷ÄŠª4"UŠßû0¨¼ÿ<½—ÃJŠ+9ª„°ÒC ŠƒŠ*Ș!¥ÑƒJ�(1¨THø–á±"UxÐë ÒèAõ–ÇA%PAõþ¿þ=%;;)´wgN„ÅöÁvêgq–`Éý¦6jÏÙqWF5#,Éì ߯Y‹±è¾]a!KüÆ úÓ_2ƒªmÀ›G�äfª>üðÃÜò?lš‡åX]×ÕÕ¥/ý“f©ÐCmJ�¿ äìjU‡í±õ9.üú¯ÿú¯µ˜fÃÌ”û™‡�ª]Ó7u²¦�,uè¬X¦^×í *†­L½OÍW)º1DhQ%U£Sü�#<—‚ÜV#h÷¯äf­² ‚Êüp5û$„4(aoBê‚â匔ûHr?#%8£{T÷\T�UîOÂ} ô(ÚL•: —£ är=ªô°g©@Œ*p˜ñ€aÐNÐaˆ 'éîgª„k–J�*ýd½sÁ¨rT Œ%¨±Ô•7–ÚN+B˳TzXIc·ß �x;^*turøb6Q'1ªÔŒ¢Cøºú\|Už‡¸Ÿ±j°ÔKaÂŒÛÎ#¬ ‚+VP] CÚ.”ÒÄ”CTÁBAe‡Õ]D‚jåïzTÕ»ÿøW”ho'ÿö͆ ±ÈÎÍe1ÖÏâ»6Q‚%-#»7Ѩa#�69ecEÏÁfaû6S’ ²8ðsý»¶PŒEYdÇ ± ó³xSýÉ/ü´-¨3Uè’?ú£?¢ÚÚÚ/^³f�±Ó8&�Ð.MMMXe‡¥j– �£ÏRéSTTj«t|«°Úˆ5‡ªÃŽØšpݺu‹~è‡~k±Ì¯¢ Cªì¥‡S·¥'‘çÓôT,£ã×òN— �º8Ó‚¬ Wýi0à Œå€+aùŸ8û4k›ÇsxÜ`‡�TL‹)hÈÝÏXp*¦@Ž'ý¾-¦À£�‚jÍHIÎTRpFò(¨î­°fª ¢Y !¬ô“péd\‘ƒJ¢J*i¦ÃyÆÃ9¬ô™(:I‡JƒJ8Y·-ý›Ò—þa†È\Ræ«VP霃Jq *E�*9¨@^¶éýx9•¼ôÏ9~óá+•V÷Lœ»¯f¬´Ç‘9ª ¢ËÚ…!#FUC(¥ØÃ*3æ¹�U`F˜Q%Õ?ÒàØ,âÅŠ %&‹„J�¡åuïÐÈdÊznŠBƒ¦°åÍ÷×Óýé¿–¿Æ”´Kð1½û·BñæfêÞ¸š|Ì›VS�…XdójŠYâ–A–Üü ³6 üÜûϾ¨¿6;>Ã,iXC gý,¶Åa!~`~Ø´†|,V_Oô³?QT·‡ÌkªÐ'¯¼òʯ`@ì@ޝr:yò$vþÃ,VÛé³Tèµ…::¨â 7£H$ÆbáÚ)ìçŽ/Ï:xð ±5:¦Õp0j9š 1%…”Š(-žM·™’^Éâ×ðޝ SO ÝLÅVû@šã*Mm¬U…•Z¨/Œ˜š@‹)=¤t J·)MÚp·aÜ·à�5àCN‰dµ`­@ø°õ"¤ÎC•Cꌮò)Á}yð(¨œ¯§r^.Vx=•~2.ÌVÉ×S9èa%ÎVÉAUá :ì^xöCŽ*yéŸ|=•0ûq¢òë©@KyæQKç1t¼žÊyé&Ë6®§oƒJ’—þéã„ *9N*\õq’ƒê�Œ«^¸W–Ba%E–ÓRÀ¨º/Qa•-¦LzL™÷UDiQ…ÛíU ÕïqPÅG¦¨çΨȧô•2F·ËÔ?2MKjÞ¢a*ß'¿¢¤Üÿð{{ûÇMq»8ÇÛÛþûÔwýu~ö>u±n‹µ)ÈB,Êb¬�ÅW¿G 6È’«ßUŠ~.<~÷ÉçÄç“ø³†÷)Áâ¬ßx� Zó˜ŸÝæÇÝ–.½pžþà'~¤(¨ÚžCŸ<óÌ3ÿ…K“Ô,Õ‘#G�;wßQ… *Ð5Ø�ƒÞÁêú²?O‚J}÷¦Á0†i1L�a¹6£Àiá;¦TØ=¯¬€jèJÒù[1› У‹–¦ž!„ˆ!åc(@üô²À�)ˆÛ{\ïB’y~‘:~+f„U"Ía•¦Ö®]ãÕ £JÍR5f¢Cª8¦êq4£ªž©[PQeÊæE²T5Ý/‡\¶qRç• ®ú!¥«lFêÞªGABPy6»¡–Š•»QÅ´›kq”’QuäåcÏxÈ×éTUæÏ Ÿ¬KKÊz*ߤÜlRá<–*ªä(‡(q£ ç%›Î×ÁUTŠUÂl¢8K%m&’gÏ< QÕ«»×®±‚»] èVá¬Vê¾CTe­sSúÿü<ž…¢Ù©z+ªêRÁ�|PEÇ©¹wÀÐbH k…`±¶à (’§——ÕÑ·CÈÆuPu„’¦°Žéõ?ø5Š64ÐÍ7WQ3ka­¬ýíUÔùöJêf>ægzg%EÞYAwXŸa9Å-ïüßb<>ÆïÃïïg}Öß±àï0?óáõñs°Ž·j¨�µ²æ7k(xò8ýî}oQPÁt†Œ zì±ÇVðßöñÇ×Ra–êÔ©S¸– ßM…˱s¹Zö§¾“Êû Âôv¿Ð—ûaš u·}ûvãKzË ªÓMAZ±øcZñꇴü•ò^…�çW²þ=g{í1eÍH©™(*¢BÃyáo…†½,ÇÐBT”e¨WÍœéa5`…Ua¥-4w´®§RËþf©‰5:„Ô« Âýœ]fˆ(ëV“QQE.ë÷å�Ò?ˆ+©sŠ‹ë£g!RÌáìE*�i%‘õ{ª6¡²¿§Q’:~ Šy*1ÜV©q‚Y¨„Ë2ÁBåóÖ?‘*U럪¥ì¼F©#ì·oŠ*•Bˆm>·h  •H•ºõO¤J"ïå95«(&ýŽ„JP•ð+ °Èä×:Á–Xñ±ŒˆXÉ9â¤H•Œ&°TÕhÖÇ£T™[ ªÜò:¼Ÿèj‘;xÌvPÄ]>†�Ròñ±™Ôd—TcÞƒ$5GøØD!" þ jSÓàõ6:'X½ŸV¨¥Q$ä”Õ`U» PúÞÛøxÜ(DÑãGa'KÄ�‰¤‰#‘:qÒ' CÖäaÈž2 ûˆ|¢�(&JLl 0ÞƒÜ�§÷‡7£˜( \D.‘Mì™<ÎIÑ:i’&�DÜ„‘ˆ™à��Äv"š$0÷¹§0üÂ?(…jîܹI+W® xúé§ý^yånûã ŽPçíŸxŽŠÓËeŽŠ¼G‚)|.T|¾_�cùµÒÙúõë;„J)UO®ÿ/Ž Aи9™0#ºq8"‰¨›†aûÍð‹ˆ¹y(âÇEòØÁpŒŒŒñƒ‘5a0öM Q@M$lœ1Ý|o–Çô9ùN¡þ[yDýv&á¤ë¤Ñõ’Ç A¸¡ˆ¥{Ø9–ï‹î�ØF÷¹ïª¿ý»R¨fÏž�±téÒy<¢ÄÉä\ ŠŽŽÖ:í²²²,ƒ)È|+TÆ„?¾_�/Ìɼ9ïAµvíÚ^?'TÅõßci1��¾섡׎À Ë¢ßŸ:cð•C0ðÒ~Þõƒ1øÒþèGŸy dª–¢Âóc ³SD’Ìø½¸ß+SD“(íÙì‡�x'ž–6¼;°Ý݈ÿþ†ñ`{ŸÓÙ\®�ÿ„(Ž¿ƒÏ鼂t>ϸ�n:ñ žÖ„Šß+§kÜ�h·…¬É÷^A4ÿ..Ï{œÎ÷ÊTz��|ÿú:*Nî�ª\Ò–ˆ"9O„;PÐT¡Úí@PÓùÊQÙ4Gå�S¡Ò*T„S衲ϔȔZ¤ òDhkÁ©½gX¦LœôR£#ëFB„ÊZ¤„³)&Uh‘2ó+ª¶ö?T«Ü§WÕPWªìG©ÛŸ§2‡ögrl •ýyªHµT™,ZÿLá†ý©DªLݾ*ųTWÕ3q"Åê€Æ,Tö7ýµ/Àö0‰Øˆ¼�·jýc~ŸB%üú+V²¶'Vòj+Y²Dª$P‹�µ¹;GªL‘*]¨B©BUZGâäÒx×Ä{‹ÍâØ‚?Ëò$$yù�È(®ÆÜWaͧ,B–ð÷©Ða ú,ÉS¡)Q…ªËÛ_ˆ’ÞEä¤Ñˆœ2ÑÄv"fêhÄM�D"™p™D6‘3c4\3üQà�¢€Q‚ù¾4y ²<_Dße è·ˆÜc�CdNƒ=„ƒH!ˆ8"vêì˜2Û‰mDÞæ§1ôÂ?ÚªM›6]òÒK/ù½õÖ[~QQQÜi§íGUXXèwðàAÍs<�$ý�¡b£ãwî²%T%5Ÿâ@^ æO˜†¾ꊡíÇ`ðUÃÐç?:aÈuþšTõý‰V;:?}þ½æ�›ŒêÂ4¸¾8U¨$ÍÏ£Í3±¬D¹ BµÅ QßêÇN”èë�Ÿ'X®t9ÊóV¼Š rE²¥KS“@éŸÓŽE˜H¼B¥K›„ªá¡bA,�âû)2­%0C*¿TúÏ¢ê�ôÏüÁ�FT„ª\Zþ$˜‚„ê Õ ¥`¡ÊR‹”�ÞNÆ} © •“©2@e+'Ë”ŽS%RÕg]‘2Ó Õ&T¿¡RDª3rî\n+X • nýcD¨ìT:Ÿ•àÛMY¾©²šÓÑ«"µçpÓ_…3v7n¶UeT•ýMÏ™P)çÞûSIë_›Pµš\�_±¢ãF“TIr0…T‘@1 –ü ¤ÉT�¿J…*·¼ï&à=&±ï%‰î~h�íª»®%y*‡ÉL±—/,9ó\�ýÕŸÒÌT±%K{Þöµ–Ñg·¥–@Hk¢”ªnuXÞéR”nûÑ!“°=tv1D:ÉDZÄ8n‡Lb/‘wÛ8¸ˆ¢ÈÀÆð0ãµùXq~¼F!áÒɹe<²‰ Â1iá|ýIHÐîg2b‰]ÄÂõò ¿ø¯J¡š5kVïEµqãÆ+X¨¸»Ž“þ8éïü Umm-_�/lG¨„B*wf}ŒÙ7Ü€>$Nþýf`D·qT­êÿ>S0ºÇ ½¬n0£ûN#ÑêˆÙ×�Amn$Üõ‡BÅí~L9žé1KA"Bâ±ç[¯ù™Ž÷ }³ š`EKÃè›Be~ß(P–BeõžGŸÙ2%Ê •7ñ¯êK>¤ã {¥BUN4…R™„*—ðnìËI7D�ˆTKU)�ÅIh.S"TÂéæ×N핊!¡rN¡‚^EšŒ"Å8„³)­ S¾ª¶(õ6¡bŽêê†:†ÛZ¨ìG©3ª8nõ<•Ï„ŠÉWíOE÷«lý;nÏ-œÙ¦¿ê(u›!Ä™E©+ÂE»ÏÍ×óTù-Ç©›çÞÔa"¾Ÿ§j“ªÖ+AU±ÁD¤2k›KUf sBçø©T3Ç„,‚EŠ¡ ºãnä”Ô�Ì”‘ü”zIiÎG:3©Í‰Ô(;…mLZ9G9INæ=ôÖ~Ž(Ç~DÿNk¶·Dú~ìÐ8€}åŸ`u·«Q¾+»æ„"†ØMÄÉóˆù¡pé B�Aì%rï�ëî`݈¢{QB”Ù T#ˆÖ‚v\¤ã¢ßerî Eö‚PdNÂ1? )Dò¼0º¯0Ä1 nEÁ;oÀÿÒ‹m Õ–-[ÌBÅ[Aqt:{Në Õš5kú[ U¡�2w *Óÿ³ü‡hÕ§AT‘paoôÿsWø·…q=nÂø.þ˜Ðo"F^1þܳF F]ÖV¸k뼡_˜B)LQé ¹">zËŸGoñ3•Þ¢·Ý¢E�…ŠÄJŽ•PékùžJ¨¾>;¡z2× SV3T_xð�•>CEH»Ÿ.T›ž§ U UvÓ`¦Y¦D¤¬eÊá>ꥒ0ÈTšŽƒd*M„Šp{…J£I¨dÝD£—–DJð�H¥0­ QB[HÅï¬õ¯QÖ§%T‚yžJµQ¬"JÝ*†»\°¨P'Çù`Ó_»ó9öÿ›þÒ})ö=2§þ¹�ørÓ_ųÌÏÒÖ3´[e´�ï›ç¥@Ý¢i?LÄ,U¿óJ•}¹úµŠ•~,I‚H•þÊáXÆ$bƒH£c~Õׄtë°LUE†Þò7ó¾È*8ˆÝÙnD§WhlobÏ!¢;Ô`gFsv5‘ÉT y<¸kÉZT6|�˜L·FlÖÏ�íe·]öºGä:‚Õ½;âPBZ€$"y¡Ç¢ùH'2ˆ¬%ó°oÙ<äËæ hÅ”®œƒ2fÕ°Á~F[ÏöeÌʹô›ôûóá"r‰ì%ó‘¹hœ:) ïÔp¬Z ×¶(LíÜ_ÿô¿(9¢*N%o¡:zô¨R¨8Ãýµ×^³ªBe‡P•¶3‡÷Doš•põP î0/莉C¦!âæÌŽÛ§Ì!¹º/ìŽY#û ~Ï*·1å�*1ºT‘@ÅyP§ •ãEi­#9’(96¾'‚d'ó<”H‘W äû†ã½ð©÷dœá}ãg¿"*âc}ï)Fc(…ëK*Ù‡Ê+Tï“P­ÏnÔþ¨ÝÏÃBujuj UŽ.TYµÒ7l”)µHi•:"PôZq)§hçŽ{q3'š‘Æ�P ÕüÚ襚PÉT•»eƒÔ*‹ÔïxžŠh*ûÉö£·­ÚÅNw£X›R«¡øƒÜn·àƒM]¾œ§úÚj3YßîO¥z–JIVD©«7n–g§ž‡3?; !öýóŠd¬Å×^‹&W©$ùÏ&b=OE´I•ˆ•ïåÊ÷æmSìT«-ÉlZ‹T1'tX¤ŽÐ�µÊ”€"JH.«ö àÖùX½á9ì-<€ª#?¢âð÷B¥qmÂÍx¬øA¨bŽXúèÓøêûúñ�ͨn‰OÕÔ´ÀTÄø´¢•ñ1¨"ªãw¡&ÁKQO4$yñ¤ìÐø”øLç‹Ófç)|N|FÑñ$ïÄ'I1ø$! Dm)‰pÅÆàÝ·`rÏ®¨¨ÿ”Ü@„Šø• Õ�$T"QföÁ½û,™| zþë¸á—c쟯İ‹ÚãúÃq{Pæß~ fO½ £»SXÅE�±tJ;Ô'ÝŽ•åZ ›Þö'RUc9K¥U‚HŒD†„úó ‹ÐYPÛ_žD Q­Ñ$Sšp²xÂ(NJ\z!¡U§ôêTýqC»Ÿ¾1o•ÄŸëØ)BDŠ9&2¥­‰*†¤Š^OèКŪŠ0HUª ‹•b—øT_ˆ”H�/Eêw9OÕ&U>*Õ µPÙ˜ÁQlú«9Pío$­ TŠ@Û­†� ED7Ñú›þ*ž¡Zÿ,ª‹ç^¨,ä·ÐþOÕq‹îæ îürp³´~RT±µS× ¢®—p~˜¾Ê:±ÍD(ª”ÍDXT‘<¨^áí€áQ%O¬ÆN\-óšÎÄÌF߈k¯YX�¥Quc¶îÌæiÓì_&æà‚¹ììPsEÈQªäø:®“ë{çæõ9ͨœ ¤˜~ª™Æ•y;3jÊÿý­©ýë{¦úÏïšÚ¿í¦ÿý‘#þÌlŽüÂlŒüÒl Ú�ýþócS·Vø­™˜-šÅ­kL\XT±Ûÿ„°²Tô|~ýŒŽ�ZÕU¼#§Ì”øTŠ…Ô*ÅÔ’�©k~+±1•˜šNñÉ‚j SRH�Rܰ•†ÔÇ;3ôñÖÂïáJaEA5ÌŒ¤ÚA5R!Tœá!õòò�ÿò°Ò'UaS�ðƒb9u×8ß”_H“.üÐßÏSE¸õOߢûéƒJ~6®ÛÊA¥?O%Ä0È;6Æ_/5¨(|-v>•¿|¢ÈÂWœ$æ[ª©X@ +®ÕVK< ©VûuµIQt—E+\1¡³ÜõÆŒ—-{¥×Öuz}Sá®ÓëÛªóMÆD�ÔáÖL’)¯q—šfp†¨dv3 ÏÌ;sÌgm{‰YàvzÕ2‹°ûÐRG÷�íÉ–eýTÜ\ýÔ,¾{cæ—ÍôÜ¿ÌÔÌßÍÄôßÌäôßÍôì?Ììü¿ÍÂò€YùðÖ,mž§·¬­P$ ªÞ§aå¦1<¬ ‚É …Hl•Pð„;tJëŠ�@ÅCÊO¥¬…-S³6¦¦­©N1E_4 ‡”SÃðÑbÓë]ÞŒ ¬Jôš §A‰SÁì7>始܉QÃ�UtyPqâ­ô NÀA±ÑýåAEXP Ó*é²€�ÿþ¬Ÿ{�Œ*ù0Ù -º#¡‚§?(V+ùÐ_5¨@~&G *xDPIaáyªì›ué9}‹î(;ÿ );ÿ)‡þÆ]C1¨ˆ:]ŒT„Çï_ºÞ¢Ùõpæ<¨ú$¬Š�ªŽ_·XT¹ßça5nù ð¨*~zôÁŠª"ß°+�ªS´ÜõÚj‡Õ8”q…k\3Q%„U:©ºVS„UoQÕ$N*9¨Hü zú°êã ÚR‚Jˆªk(ª|X­îY,¬hje± ¡×1¼×ù Q¸=g-cX(­–wÚ�ý5+„ðÉÔx•BJŽ)PBJ‰©„‚ ×üú#]�EUúæÄ}󃄽Y�Vö>xEXH Ëò°Š/ª�mÔ!<¨‚Š·á:0.­€CyTiÏSÉSˆT ¼Y¶R¿Ï=’ƒ*Öî=¬¥¼%~À*A¥F•´~œçßHïÓÄe¾N�Χ×ê+9ô7¢/ebUTЂ4¨Š Ü X¬6]TUXXY>¦8ÜöW,³¨D•Å'W>ªà yËe‚*U“^#NXÍAPTABBoû#áAU_UPmu‚ˆRdÊO¬¬U Y‹lµ<ávœåŒ%oÛY,ly4…"³ÖÌF;¢&€ˆ²j<¤,ö1¤B BC (œØ›µÿûþ›�ÿ†÷‘¢Š}ócAÅ´œ tˆ�2…ÔËUUyX±Ûÿè÷§Ð ?(¶×m¸µ]ã8ùö±ž�åâúK²O<÷HžRùCõçt"îü·áÛâ‡ú+Ç0Ñ×-l½ƒJxžŠM•-ïi�ºÞ¦™Oª^`j#¬FI·°*X>¨ ÕvXQ\QLyM§iPebêÖ]ËôºLV<ªè5E•Vú´jB «Æ‹M«àó&UqŸ§Ò£ªïƒj«GPóœV>®–a—ì<¿¥.%âqÞÿsÓ'3ÃL5Ú&RQdœïäWqØtJŽ)¶[_/·÷y„BŠÅCAì'®ísD€Õ�§U™ �¨<¨ò¨z¥A>Õð” §Tú6ÜÝ79áÖ¿ ÃcÃêiýET)[tÓôC¾¥ìå·R×Ï“£XÙ ?ôÐß(A%G• ª­ ©�Å ‘ÏB7ø8urmÊf½ gF0Ýh›b&­‰ºóÍ'˜DŸHQD‘-[BHÁ†õ �ÊÄÔ ¸ßc>ZîM€}MèŸRqˆªAUVÈ!õºÂ*ßF=�ª ãl*oºUø6ÜpE”[Ç)s•R·Î~/nLi��õ®®9ñ}÷±ÐÇGÿûo=öõŒ¾^A°.�Â×4áÂ×PX?×”µ+ km½d´>p í�ç�¯S3Å¿·Ô¬[¯¯åkâé+röx›Êï‡kµ�rI€¦ÙÀ±ã2ƒèÊÜ33C˜ So2ñMÏcOtÞVÎú/é§[˜ÝoI’G—cžH¨î>·}ÐGÎ9ÖGïØcl?½Aõ®�Öÿ$Ûÿo_P‡ß“ÐñA©8¿ÖÿvÝït9ªßtªøì»¾¨’ó²ßÃâ|Æ�Ûív @�‹8¡:¦$Tg.?-ïÐzÍuÓ6Q_¶Û—cð5º×iÙ¡W�“íìî&×ò‘l£m-Ž«é¼�÷`Ÿ�¬W¥w.cjËÃ'q&TÇJ&TÏÊó?ò“ íåz\>¦F—¦e‡^5N¶p(ÃÉŠœŸëÕÂxöÙÉzU pç2 ¦Ô^BuöÊ3ƒÿqè(µú·â¾#Jþô«›¶Ï¶ÿFË_ŸÓ˜UÛxÞ4-?R4—ˆq«»¹O¬¥br êÞø{Ž“cæÎÅÍkù8Àzü9‰½g»Å¼r­úÙoocµx{��ßÃËg´R93¹Nõ®Í;ÑßWø·±Ð{P÷”å8±§<|Zc Õ¹«ÏÉö;­à¬MÙù¶�©É¥iÅQ®g{(µæ÷Ù]ëÇr¼Þ&Çû²œûh†Rÿîãñ<—롾\1ž›ñ¼EëÙ¿&MN®G-‡á¿åÏÑ—w´êçmŸ=·%…¹ä¼¶p]­wm݉þ¾¿ ɺmOI†ö½íøvP›+ û=÷'ëF_™;ÑßWø·±À{0ö$ßv|=‹5¡º­'T¯ ¶ƒkÓ³?/r´«\œsÔœ+Õö 5»4­ürH�kW«w]©W@Ÿ‹×S×O•¸ÒåPŽÑʺüœ9e êy)c¿ÌÇú±³õ|œÜO`Æ{�ë6êF_Ù;Ñß\ø·a߃½''b�‘xeB5]:¡ºtc¸¼\?­új¾~œVÕ9JÖÏ—?¥fÇe}¬ÿ�+ûe�Oû¹ s5ç8î«~J\íöe§Ô+Pf.±^³“kUËÁð÷äÙ*ßå~õÌëøŒ¹ÞÜÖ#b a߃\·Q·ûô;1Þ\à·a߃#ßv„ž<ŸŠ7¡ò~Ï“ Õ•[£†Ï©EþISûç/ú¾ äå¾·z¹îõRÖÇ·ñ¼ ´úe.Ñ.ãôºÍÜ›�¬?áûÄš}Û³øûÙvå\*åÏBîÑ8/ù}1V©›B¿qFz]ì˾kýNô÷UíÛö=”ßSK{C!¦å-ß'€§CÓñ&T¿3_žO¨®Ý]|¾õ‰L/ VýZ?§V×@k¾åzäž Ë„êÏx*ŸHI8¡º~glÑȵ;rõôeÕ¯u.¡Zû-×#Ps Õ�»ã‹À)Z[/ÿ<³�r‹bÝ_P›O¨¾ãzäž�ÌÌ%T£щZH¨nÞbH&T÷þôüÿTÅœPMQ”Py1'T{ÿŠ’PyÑ$TS^!¡‚د Š�ˆ‚þ%�–Óñ™¡ ”g’§a³Ú\PÆNJã—;TÉ©ÚÀ¡:çUaõIUGÕð»$)w¨ÒŽ×çšÕ¹ôPÅךÔûPàP ·K’*É¡àË¡’Þì�QjãHE½÷¯·¢m¥ð÷lÁ_òFb¨4 Y@0L†þ&2j2�‡œ+_4*RVå>¸Ð–UOÕ.JÜ“W*I3€êWm@õãñe _*ižT E éÏokW³Ooƒ …€J’T¡º7UT_¶B% ¨Ži߬Óz}¡fŸŽWL³Ÿ‹Õì�I±„ˆ)|¿&í�`J@õEB! ’$I@õIKþ$iµZA•*d¦¹±®¨Žûô´þ‚æ?†ŒcxLÏMQ§ø5ÆQ¡PI’¼™€ê÷E˜Î6u¥á†ô±íä©nFòfÚåï°Ý|¸qt­}PItÂ!‘IKódÞ”U©¬J‘ ¨¸ ~ ÃgpžüâémßôÇMäúÃ\h9ȉòóœÜÜÇàmÖMz>Þ6PY• ÍCüÿ´e�ü+ÞfÞ8* TÅ}¹.?×?ËS•—¼™€ê�¶›MÚø_D ºl2nÛ‹¿’œÙùç û_~?o³= ÏYõ×ÏIÚë¦PÁ¤%¥ä%W¨ <¾�ë);‡™ežCÏÍsŽUH§†€Fá%xɧ�}& BV0(åmT Ei â>¨?vþܦvcþŽKÛ]�!?¼¡®µÕD �¼ïËá×’˜äÍ8P�Þ�ê�·�ªªï¨|²�–µ»Ô^ÂRÛõmì¸MH»1X.«r±U×^ÏyÙ~ìÒÍ•“M7V¡âÐÙÄb:PÐ0“ŒMw ¼ b}‡mèR± 9 0”*ë;;¯NåZnÓi ?¯ø­Cz�ѦВ?…BKþ¸òö&)îePaoDúh ûxÝÃÏ&Í�¼YÝ@õÝÄ€ ÂøÎ&ßhÙ¹K­Ý„hœñ› *| iAësË?CSÀ€”w8nÄÝ8cÈÁ …iÀ Í*J¼ùs–*ºÓ#¯Lñq`Œ?$\9ämJ•B¡ Õd„ÿÍ� {£AxÞG;žÝGIòföbßJ+T&øb_/÷ο‘\Bº¹øõøÍå¯ ¬4ióïòÇŸ�â`„¸Tª²•U°©>E|Œ_�÷!WÎéñ�îv»´›¤»ô0‰�g‡«`L?¬“ÚÔT …€ {#;Ük�ƒ=ÞYÅʾ—äÍ2ïòg@¥M)H¹ÝÚíáòÙ¬þ{W–“•·Çרrè¨òÃTîÝá@j PYÕŠ‹ÃÏÔœ ªlœøóUSÇ‘�!i;±M9 R(TÄM*ó1Øû oĀʖþß%g¯×?›./#o–ï=TÃ-Óïë*U+Óõé’?ß@ÂÍ�Ù¿ÏŸÛ–V¨†íÃר_ªü0ÅŸ½PÝà’¿H%1ü2…B›RL*óYãÞ{£Ñ~ðÍ'xß 奤Ü@õw¯šÞC¥ûJªL0eËÈJU¨ì˜ŸŸ¡ùs*²%>îc@¥% …€*·$I@Uöéÿ|ª¿TõK@…—wM…)f!¦@E63˜Þ�³ âK3óUµ)…B! ’$É7¥¨ ¨~<¾¸À¦•KPY‚°ñwYU£ PùvÛ¤â"lã¹fä\P094áïB\À¶éd …€êÆ$©BeZ8P½¾ÕÏP –üIÒÒÅ�Ê�3Uˆ°¢ÅßEU¨øKx±I'çМ‹*«R}Îö÷Ÿðb_>Ž …b"Pe–$I¨îßµl z|>ëâ*»™T%IÊTUü¼2@–šQ#n×"Fœç\P�*eþ÷PÑߨÏÏÖæ_öΠ§�³[Àü¤&^ð?轫ʋ+ÖÝ ¨É¦ºJëì ]ôS•þ€JV•EUÔ$ꦫ/Q …&$‰›&‚Á”#�oN‡ãÎ÷fहö;<�ôÈ0ÌŒÇ ‰xtƃsÀ *D�iPè­Ò{Y£¾)EÎ%å *D€"TÝR"A…8ü Z\ïe$¨ * ¨ÑÞCµ¸ePqÉ"Àh"A¥ÆTÉ�/4;²°jž� š™™‘K—.ɇ~ˆåPϧž×˜‚ *D‚J�|B¥u®‚ªvíšÌÎÎJòý‘ããã’ˆz>õ¼êù%¨â€ Bä=TK*A—ÓÓÓÒjµäèèHö÷÷K"êùÔóªç— ‚ q”'T%º)ÅaT?¯vÌóTzy˜N4ˆ�ªçUÏ/A5ºTˆÕfTKk6�Š|B¥þs³#êB깪ä{%{{{X2õ¼Tð�"TSúqëœUù^T@P!FTjI‚Ê–Û?ü(õo¾E<·ê¿�Ƴµ·ªƒcùeý¿-QP�qÉ_½šÁØ_VëÁ:�óµ$Dj2?‚A¥70h·ÛïÉ'ãÉkÿDîÙ²{ŸÈ¸~n�ºl”E=¯#T~X„‘1¤ Zh„qç‡`àÄw‡gì×Ù¦ðñFÆzS&JƒÕÊjKþvP-­'ZP½Œ<¨_tÌS'TóµJòìU©g–Õ«úy¼Aµµµõ—w¯&Ñô�|0>.Wïf—]•»ö¨ËþqÑ>ÏpÝQª©…¼Xy×8°mý r¹÷ƒ* ‹¾0ÀÔíümŠ/AÀp)0¡*QP�uÉ_­R‘Ú|ÿóœØ;ÑÖ›O¶I—©•Ú|Xo¬—hËM�°`¹ÅœEZ­jËÒç©ÖíxêRµ};Aµ¹¹Ù÷ÎÕq¿zG¾þ`LÓåwÒ�ºc�º ‡b^Lå­7ºAåÅÖ;„‘Mj®·‹?¯óK¾uAùÇ6w=ˆ­ÇKPÅ AÀ„ª'¿¨e¸äo±ÙÉšT ÏzÕ. &T:¶�ì×t¹Qþr‹6ݯE–-žÓ>v'T‡‡‡Òh4N¼-W.^”+·“�¿ú_»xEnëòÛWä¢~l�º ‡e6¦lY¨ž×Ø‚*ˆ’�lão_8¨4ý  §TS >^'f,ìÔ0ðìM/\ƒ}…¯/Ÿùû÷÷éEÚB#¼œtô ¨˜P�» ²0 t'LyÓ&SËÖ C+oyÞúA¬Õ«[~P=yò$õVL·þüü+ùŸ±$®ne–g¿ŽÃTnÎúºUù&TyAR`:5w=û˹(NäXˆ„¯ÉžÃ�°Áo°ÝN\oÈ„=Þ>�Hsöíïó” jÈTzN*‚jô‚êeOîÿé±wP-½èô]LlýñFP…—Ñ1¥_ ‚è¬�ÉVá ²�²°òƒêÕ«W’|_D½yù‚E^ß —oÊ£›—åÂ…ËrÓuý‘õ¼¾kPmßûZ¾øâ‹·÷ÖS)†3ÍqÌùEÙ‰±à—r?PˆòYÏŸ’„Ó©A¯?vLaìX¼…¯%ÜÆ¾A9Û8Ç^`ŸÁ±AÀ„JƒÊ,EP-êc&¨ü›R�cëe#ʶ /í3Ã÷<ù—ü凙.·÷j½eP-//'~/]“÷¿Ô�Oüò}»ð‘|ÿýGr!û¨_e1º râ¨Àtʉûe¾hP¹ÛèëóïJ8¸ãUüíüI¡¾n‹?† Å`ñ}”‚ê®ÌNÎÊ]�rCPYT=H|sPý¢!•q3'¨,jÂÛ¦ÛtÈ–UªU žì×4tò/ ´)Õß»)ETv 3?¨äþýûrî’¼÷Þ%™Ó�ûþK&ÇÞ“K_�|-XgtE=¯±\ò^27€s‚¡h „ÊùÅ?ˆ+[>øãõ·ó¿·áe‡ùËüçó�½ø>‡AeA4)“jnT@PiHõÝèÉa/æ Z눺”šTƒ×»©„¿]ZNP---•KŒ!¨ Ä”ý²íL§¼˜ð-öþ&›²„¯ÍÕ �× ;'^P…ëûúñ3€}‚Ê�"‚ *»ä/ú ••N¨®M±‚IÔßÓ¿ETÉ÷HË%êy�à’?7¦œÀ°xZP9“(��0LüKù*‚ªìAeŸÏÎêÔ*uúF3³ú¬-s²Õ¼!Ó“ávºxZ&Ãç°¯C TfìAu­“ú ª’8==-+++¢6ù¾”DÔó©çUÏïðƒªxLù»iø) *?LŠ?Ÿ¿ýàƒÊ ÇÇ^|Ÿ£ A5)³w³‘¤_·¯MKÚAá¶á~šrcúd]‹ªéÉR]nû‡8à’¿_÷¢*›R•?¨®]»&Ÿ}ö™4›M�h”CÔó©çUϯTþ=ºEþtjXAå߬!ˆ?ÿΆÑUÁ„8Ç^|Ÿ£ Aå„‘N§¬„Âumrh«§«d&WÕVTRËji&TjɃÊLN�N2ôò°’ˆz>õ¼zçÞg@ÁRà–ÖN {.çr�Ÿ 2‚ ·³mœ[ÛñÅTA$;§ëmç=d÷IP• ¨œ±“N©ª(!¨Ô؃JüARúXú B ža|ضþtj€Aå» ùZÆT¶O÷¼ûrÖñ÷IP• ¨‚Ëÿ,¢ìóàRA (û\×å’¿è ¨^ËòF/«¼îÅTëIHeZP!TÎ{®†TÁÔÄ @'6‚0Œ?¨ÂKõƒõƒçr¾—Þ>ã *n›þöï…²mfgeöŒ›RØ>¹)Ä<¡Òˆzh–!¨,ª”|B…8"Ø€ UY‚jYCªo7)Æò"Àðƒ € êO§Z=yÔŠ=¨^v4ª,¬JTˆÃ *‚ª}T�ÌèƒÊbŠ B‚ A@PiD™ñÕC�PeŒ-¨ž=_‘Û?ü(õo¾Ås®þèÏAÀˆO¨Z]î÷¸ Ae.G8¡ÒÿÈ6¶v@¼ÌÀèL¨ÇTzà�6:j?ªÚ•QPA@Pm¦vbžP=zÙÍL©ºT00*‚j; ªÇ­£þtê‰Uܪ®*S“b$¨€ €ABPT½òÕã�®jaÅ„ *0Ae1yPé�?Ñ R[TCžPÍפR©É|iÿ#‚ *‚ÊBª¡ÆT5�ª¼ ²ÐIž~ìÄJmž zg€ ‚ € ²˜ú5ö j´ºòDÝH·s‚ª:V‘Ú¼}^—jµNP½@PA@PõcjK�?¨Ì3‚ª*uûü´ÉU&ºæk –[,ÕªºÌö—ÄYfòUýÜÖÉ,«—ê?2 ¨€  ¨4¤N‚êiìAõk««ZTåUÝÇ&SCFÞt©^Õí,¾2�4/µJLá:º­í3úÿÈ€ ‚ € Ú9<îO¦žªíȃêéfTfT;aP…qdaeÓ©¬Xá×4Š,¸Î °¼uJT@PA@PiD™¿ET[ÝÔMÕ ªìdê´ØÑå™Ëÿ,Š* ¨€  ¨v“ ÒˆÊÚ�9¨~ÛêšV¹AU©Ös¢GÃ*¸d/Œ {?UTá%T@Pœ› zÖî¥n§v�# ª®•™?¡Òðyó&§]Ú—yÏ•Z©Vs&TùÛW?'¨€ ‚ ༕ú<ö z¶Õ‘ßÔÍÔÝ ¨†`©ÿ#‚ *‚êHµ¨Š?¨²îT@PÀà ¨ªçIL=ßNý=ö ÕóvWžo¥>K$¨€ €AAPT{™ ú=5î ú= *S£j/Â ÚØÚý9 ¨€ ñ z}¬Õwe§4A¥ÆT¯eucGEÔŸ‡‚ *‚jåÄÕ�ˆ/ùÓ_ÙîšiP½ƒ ±< ?¨*�J©«'ÅT«ÛÝŒå*D€áAµŸ•F”ÙŒ9¨ôÀ›APí—8¨†TsSú77s�š€óTQ‰=iî¦ÆT;ÝŒå*D€4¨32‘R„T/v{fÜAõb7y1;&A…€ r¦RTt޵ATYÛí©qÕZÿÅècWþ ¨� €‚Ts2õF4MÈL#`MTpNƒª§¦AµyP­'!¥®�¨/0 ªÿ¯Í Æâƒ ª0”Ì)9½—23aAåD™íË{N‹·ð’É šÎ>JTQëfìAõòÏqÔ÷à” 4�NGVWW%ùÇ!ív[vvv²êÏbÿ1ëÞÞžìïïK«ÕzPAe�Tär¾¹)ÿÁ‰™Æ™A5aÇà™ÿ|hŃJ{C#J^ªûêqÜAe!U<¨* ¨Â©�#ÞtË�*»0ðœÉ–M¬œé@� ÊDUôª£ÔA•M„\ˆ ãÇntì; £0¶t³ü³ç —û±P,¨,¤Ô�Ä^ôAe/¨* ¨ÂmÿÃÞÝü6u¥aϪó_ ± 6•�ŒÄ?Àl#6aGº`Áyþ�.ºh‘,±Ž8” ©¡Öt”v˜¶8‰;ÃGâd€‚)±}ý� gîÑøMòN“_N®’{yéø~å‚d)?�sÏUšR8RÈ1ñ£ ¦®«·k¼YûÆT‚©¤ƒÊÝøz½·S‚Š!¨bÌŒO~†?O^Ä!ÅQàæça¯€ñM¡ÿ¶PÃ0¾!¨`Œ#�“FŽ *jrN¤)† ã ªfgK •P½ !%u¨jT A•>P­^‰€©2r#ÃÉ¡<ÈqúrÞ‘ËlÖÝŸÙ‘\:e´G†±qb�Y@g˜é£j ÃD¥ ¨‚êM}s§Aª÷É•” :²!¨‚ @³ÙtT‘"¿ø�ÕAÜ1Œf‘5q2‚\9Å ’TorÔ�a*k•>{”Jï`×”?㺜ÒwX!¨‚MiâA¥dèÚì*yˆQ¾yjûÁ>´ÈTLS'OžTTQ§ú °1¨²³Æ¨•œï“¥‡˜˜˜ÀÃ¥Uv6žÿßâ †!¨öŒFŽÖ‘ƌϢÑAeÿ<}Ÿ.† êâšdP¹¯> rï8�/AÅÄ*ÁÔ±cÇpêÔ)œ?^PEPùŒNy€Jb�^e1›BPÙ£T ÃT~¬ Vü–M�*�åÖÆT©´€ªçúAPmnn¡Ýéíê]Œ �Ƶ™¯�9ýÿ{I>³ì@ÝT‚©ãÇ�ãìÙ³Èf³Gø%TùƒêÝ׸ä 3ý5Ö¬ýr&DÏŸvúÝìŸç˜šþL/×1Ae_CªŽµîËw�sSïô³S‘N(ç0â*¥’iÉÕ,Ãnª_¿Ã#h[ÿ–Ÿ¥b‚Ê@•ﻡlLy‚Jnó£AÅ0ÕÛ`ÓWT½T­vwWgp!„ÓÕÅ.òcCÈ\+ýa»ûìömÇfô1ùqdúû.ä»X¸vZŽÝ¹žë¢çúò²=Me÷•CÓ¹sçpùòeär9ܾ}á �=Âýû÷Ýþƒ•ÆŒ�*�˜=;¾ì*ãZT1®ÏÕ ’éh«ðUŠG¨üA%på´?†!¨ŒX@øØï¤²ŸÇò•^LÃú™ ãªV÷=Þ6¶T?å¯â*ãïæñCÊŒcÁíË¡~8©ódŸ—ª²ÖÕ>=à*="¤Ñ¤Q#8Ú[sß©kyLù“Ñ25ê¥îy_pI 2ÝÏTþp9|PE[@C¥°A¥¦ýÍÜÃ0Õ aŽPõ›dPÉ‹}_U{ªA'2¨:ý(µ]°Ôï>è²>«Ñ)5Ò•®²‡¶lºš>g ÆÁÉØ¶'ª.ýòÜT2z%£NÖ=ÏO]�$fPÉè” % ²Vø‹*Ã0ÃTίj›x] [û_{I}U£û?•›®ø±ß×ÕÞÞ êm¢Ùêìj= ò¹„«7uo×ö‡¡1ÜÙÞ/Ç«sÍÏêi.{t@eï0Ù#CË\¨ ¼éÚ òû%ßTúÙ)'V–ð0„ÓD¤>ÄÁ8K�T™ òÆ+Ã0ÃTP_iõÛ†k³û>™ ª¶¶po¡¦º\é|$¨?C’íù1¸i}óÛû¢‚Jþ>„ÌÕÑqø%¨¬Q#óT4i¢@e`* TÉ½Ç *†a*†!¨–+]ü¥Àõ~©�akíƒêÛùîn·ŠoöU7U£ÙÞÕ|� ¾œo«íÅ« mo_Ä—™þ4½Ì.dd»:÷ßç¯éiòn{ÊÊ~ª R£RjDKÿ¬Ã•?¦bŸòç¿`EÌ b† b‚j©ÒŽ…÷¥ T[ •`Êu¦¸?¨:Ý‚F‹eãê•=}Ï{ÊŸ“\+‰ÏPÙ˜J ¨Ê¹�ª¨xe† b‚ê[ª ù LT,Ae.0âLþ Š•?½…ÆTA¥P(Tñ¯òÇ0 AÅ0•kâAµ± ªê‡AÕé¡4Y6¶:P=~üÓÓÓ¸qãÆ:99)ªNMM!ürù‚JÐb,�òér¼ºŽº/�g¨âz•£r¤A%øÓ÷ª1%ÿ^Tþï¡b† b‚ªƒ»ª…T€J0eƒªÝé¢Vo°llu r˜zùò%Z­¤òÎ)7jU©ü©‚õõ7xõê5VVVñäɦò¨J¥ËÆZ•ŒHA€jµ†wï6ðöíïXZZÁÓ§/ðÛ?Ÿ†ˆú ?þô s#Tª5¤0ÅQ{”ŠñUq”Óý† b˜(áUTÒt€ÊÕÂë³lœU j4¨ÕêL­¯WðôÙ‹^ÿB±¸ˆŸ.bnî1¾ÿþüúk‘ ò¥bì‘»�TYô¬Ñ©�\.�a‚Šaªzz@u§ßçû€*æ0 AgV¯DùÅŸ#R'të¹²U>;Å0Ã0ª™4�J0EP1UŠS�„*‚ÊÀ”¼wŠS)† "¨†SþîŢªÃÃ0 CP1 WùS­¶¶Rªu‚Š!¨†a‚Š b˜ÿ²w^Ím$YæÏR`ßç‡`g*b~ÁìÛÌôõ„õÞ;=¡©6hï»É¶¤¼ƒÌ®ÌRŽò^ÚÍ­ub±§!ÜÒ‰ê%pNÄ ÅÊÌ{‹Åˆüt3oþĪ#KTãA¯ö¨J£ÝoiÐ[©¿ïZ•/6½Ž>¦®÷ãôc�RµÒKø‘  õÚêoT!FŠçUòUˆ§7Hã8Vò¿'ºn ²,˲ T–¨Žü º¹0@µÕ¨nFƒ©Ï&Ú³¯Æ2]Ñ焾Ñ^*¾Ÿ¿·;»þâû`”ÊžàWеÁs6PY–eY*Ër† ¶0{¨¶šAO >t}7 U�h’^*P�*Êä”.<'!Öv�ª¶û«ßé \mo_I/þW:þb:wî|>‹ªT ²,˲ T–e :´@@˜ª@ÅY žtO_@GªQ…%hµU#dY¦®ý–¾�¸?Z†HÀ‡v/ôkj™"û;B{Üó"Ÿ!öƒbÇç–ÞÑØãéñ³žÝÇã¬p¿ÍcÏû?cª¦ßëõÒï÷ûé~õ+XúÃ:®µ×_OãñY•ªí‹©÷óCi°�Zã·¥•Ÿ]Û8�ü¬,Ë2PI²î¤}ùVúÙkÙ>Kû®¥Vd º¨Z€=T[P!«”XÈ>Í»ÎÀ4kÒ�ï!P5œØGßó˜sAÄ÷( F´Å>¤Yû‰D?Ð/ÂRJ^®‡å”<&ßǾQÌÍcåöalìËL ª~ñ‹ô�ÿðiÿþý°ôÑG¥o¿ý¶` z�¿©'ù¿¹f6G�a€LšÜï¤ P�ïè'Á§ƒ†­ñ\˜Âï!ßSmµð¬¨OXø{nû€ÏÜæ¯w�ýçûcóÕýUÿžô~„6ÍcÔAŸúë½ý@»Å6òû Çh ²:Ðù/6Qi}XCÕ_ŽÓùÔ† T¹\: êæ"Õ°1P1Q¦¨×#Ðá1ø¾ („TÄyYÇÇ÷ÏÌ*ÁMüŒ}&?$P¤ì ý,bøÆm„Xùs®/Ï’?L�yO̵‰à‚Ú¦V>Pñóã˜b ÒŸO@u–ßø/L^göÑ P þ OúߥÞF�Q}/ô÷AoÓ>PÅ1¨4V�']i;­¾¶™ÖSC]§_·»Ï$ÁǶ…˜„þׇœÝ‚œ¡*¨î?›†)=CÅÅ%æ^GŠû3ThÏm[*\�ÄñòxÈÒÍñ¹  bÕ�j�—üñ¥9PaòÀž¤ëÿ«  XÐ¥~j@xV<¹Ö'êú;ŸÉOôûA}„÷ ñ`­û«ü=é—r1Æø`#�-´iû}hc@…I=Œ'ø|��ñ�@ˆ`Š~ÖBŽo¦Ÿ�Sqþò‹;3²;ŸqßåU“ß=_^.h zRWøË@êB�j¦ä=T\¬ ¸Þj•?Œ�ÉyëKþø:Ä©n p˜í3û¡•¾ä¾qÿÍcõ’¿ö'nzöEŽEÌNugÈNEËÙàOû12¼‚6A˜X·T[c2ô. ê‹Æˆ¡ÿ¢…X�¡€êú“ôæ‘ûµÝX•]”bx@*>ƒjڪы®S€E ¢¾êÉ9õU¥ Ù,5Ä2=ú>L‚¢h;Ç/^ÚXU=îs†Ï�M� °ö²E)æõÇÚ¨âg¼4Uþô‰jð?»ÂmÙOÚ‚,bæ‰ýœ ƒŸ/!ÂD,ž¨EÏcªÏ*¾ã¹´Ÿí '»ð£ùd¹M â¾uõ¿'ýïRhÓFŒ˜ëc·ê¯îÇX4Pd R&ØÂD~¸ÜâɱÀ÷!>€H~”-<ƒ¦bx5P¨Îf :z?CÕbÕë2Pµ]‚œ�ªLuðŒ„3²Ê�¾äo™€ mÚp¡ü¼Úâhº¿‡÷{™‚þ0¼@%<«p’É}²ôw ž¤Æà0F\í‚ gùtË*=Fý>}lÝ_ý}Ðû.¨xÝñþ"Œ�ñu B,ó23*Ü£øRÀ4%Ëf b3Pñ²½¶'ë¼,L—� 9d ª×~ûÛ <}üñÇ ¶±±‘<Ø*PÝø~_ú³?û³æöþ™'n˜ä0t^6�|b¨‰À‰—ó0‚ç2¨¶ 0¶8ážCœ< ÕßÜ#ùÁ¿TâÌŠîoi@¥Çd†ð†ë-Œ­ù«¿jŒï1"pÂ{õx9�qß$®H§gÓ@ä –²\Ÿ9vCÈ"ñ²E|Æø}!ÖUǸoŠÏÜ@¨*¨² @eT¼Ì²¬LŸ¾äoÙ€ m»*a‰[0ÉË?ãgÑü9EYX@ˆë¨ø¹ð3�/1Ã7ô×:¨ðïI÷·D Òc”ªæÁ}l©�þ>è1–T ÂÒ1AÀP …ŽoNǨ inA‡Õ! †€‡ dÐÑ8\$¤gwŸüÝÏp‹X㾨êç˜� ±Áÿ媷2PÁj¨*¨Þž‚*•õêU†¨7n¦ë×wÒ•+×ÒÉS§ÓÑ£'êìÔ‘ôÃÓÆÆwK¸ä¯ûMÛ@„ ÄÙ– �Æc줊¯é@Åê ¨ôw1?¨˜†ôž ÙÝß2€J�1~Çð»Šö(êc+mô÷A�± l`)œ^Ø@ÚïƒqE Š—ûx`<ž¾ì�Ûqß\ÑOÏPñïªmÈáì—àëÂÕXù@µ6ªÛ!P=xðà'5›Í@%Mà;’0AŒ³KC�@%,ùëjáO€y/Á­~kà#Ç-û[$PI1êÐ_ô±å6úû ÇXPñÄ?Þ‹£/ù㬒TêÙS¼Œ­] B»Rà‡TÔŸ®8ÕÛÇj˜Ê–�ê¨�Êf+¨ Xò/©+ ¨øðÜr�ªƒ¢ñ˜ „i@¥¼çÜN‡Æâ€JˆQ‡vÎ6êcëmô÷A�± â‰Å(t ŠÎžÒKƒ¨(ÕÓ Tµ!KUÕÃÂ�jªÆW T6•�Š%~ã?”zÚ’?@J{¨ÚßSÖP “Qáùëg éþTBŒ”³/úØzý}Ðc,¨¨„ú:£hW<¦¾‡ŠÎžj$]®¨Jªs;5P Ê¶@¨2Pټ䯔s¨:Zò§ C @D(JÁ´ö«üéc}ýЗ[éïiÙ)ø[0P 1 Ï”¡^[o£ú.ÆXPÅý¾jE)¤å~$_<ŽT Oª²€j šXñ@uG*ØZ%­ô×èúZê¯ìI{·8á>¼7í‰ûäûl¥˜�Š'ailnß©ðå¹y’öo^çeC|Âóˆ®SŒðWâ8ñ¼:€=;%ø[P 1òs��ÐÇÖÛèïƒc@%/Ák¯—Mçâ úŽÏ™Ò˦sE¿¹Ëý(U@…,U¶¢�jÿ¡) ª-*‚—=ýÔ߀™ T6›�jkÜ|Jx?C@—ÒÞ¥lÁ™v°/îþ» BÁï+*íÚ a0~<žà¯þ÷ÔJ?B!Fý°ècëmô÷A�±@ Š‹Qt}°/h‰Ïž   àJö%†”MçÒå´Ä‘~.@?]y° lä+p � PU4Påj*Øé—ªÃ{÷¤={ã_•­5 ªßãúÝ»�aª¥kéòå+éøñS“³§¶¶¥ï¾ÛL_­“>þäóÅ*žX0¤t)¡zÙl8Š!?ç ýˆÇÀóÒAI*ý¼¨æ@¥¿ü®¡ïn26|ÎX,Íßò� 1ês1\ëc+mô÷A�±@ ê\˜ÌÇpÐM¶ ~èÙk¡€êÑsË@õ°| Ê¶V[^þר§½“Ì2U{Óá™@…Ïs~¶V·~mmj8œ 6»ÝÞ~|_+cÛºªœ�L]¹rur ï¥KÛ5L�ÀÓwßo¦��oÓç_¬§�>þ¬ ²ºšÐÇ{¼t ²,«<¨�¹im›¼”޲0*Õ‰GÙ&PõöñÂ�ê�Ãw'@;}­PD® Êð‚~ÖúS ƒïý´ö¢výµø¾VƶuTûöíK/^¬—ûÝ~¾Üïzºvíú$KuæÌÙtêÔézéß8�8q2;v"9r,}óÍwé_ÿõ_ Tª–ô¥H–e$•~ÈoW0e 2P½SÃT6d©Šªìø›Gîª-÷›þžG*|nz¯~Ÿ>¶­+ ÚØØÈP•3N�-ÃÔ|` 2PÀÈÒ÷dX–U¦ T\½ )gnÅ{µ…Vá@u#ÕãEªl —ü!»C†ŒŽ�J5Õ… RýÇ‘vvvÒÍ›7§-¿‹øwÚ&Ù¬;wî¨ T³—þªT¿c˜²,Ë@eYªgéÝ“ª‰Õ\ò?ÅU>™P•­Y†j­�¥r´§*ïCbÁõ©¶�U[cÛ T–eYV2PY–�ê?Tµaé_Ñ@•˪²�¹ö8ªµ>l e#ØŸ4±~¿Ã U[cÛ T–eYV[2PY–�ê½SOžg©² T·kÇqJ1 **›Í@eY–eA*+ïuRβ TÿU·¨²Ý_B ²¨,˲,Ë@¥WáÛD¥õa|ȯ¨¦¡ªd Ê)6@•�Êf ÒdY–e¨,TökR&Ý2P�ŸªÊªÀ4T�½þÄ@e3PY-j'U¨¬‡ƒv—M–e¨�½n/>P…*Ë@õßéý¨²M€ª¶ªÇ!PýÔ²¬.�*>V+×�³�ÈâRÝúØ(/Îc4.)Û8�šõ5Ûo:ªÚJË%˲ T�eØct|3>+Š^:3PýçͨN?›†ª‚�êѨ¦³TKT–�jô×yâßPécR`]Å ¿ðCË$˲ Tç¿øl§ÕáÈ@e ú`TÙ2P=Í\R.Pa3 êÜÎÓå*Ë@Å ¤Uó¥múØSm ��þ#HŠýÄø–B–e¨ y_ÑäßÅ-Ú°>öN¨² Tãò�*›�Ê2PT¼ÄN— öFè&`Åþ8KeY–� Ù)d¥Ö‡»YªÕãižp_lÃí¨”ùlÀ.Çßñãçïù:–7®æxÛªÎãj,Àr¶I_µŸ_D}¨¦¡ªh z ¨²½,P�ª•´R�’¬ñ õVzi0NV‡2P“þ€J s( ¶S(=;…1¢Ÿ“ßá’ÊeÙKeY–� 0µoêø¦0aW²EyLŒ_gŽ0é–æAÌêpsÒJ¤ïÿüaìö�ªË¸ÎÇ}ÐïX)@b š@Ume•,ã>ÜZßß­öe ŠaGª9†ömg§úž€m €Ê²,&úmíõ‘aãd0á/¨ÊŠ  ¼t`e º³ TÓPÕ¨Q W e¥J#ÎPñw´C¿£ 04»@üá~x||ÆõÉWôaé2PÅ¥Ø9S%��¾¸º·¼µ—�â"±ßzõ@˲¬R�*ÎNÑÞyÒ-& p(¨Ê� `µ\Pe JéÃ3¨Pñr¿©ï•š¤ŸÑwàŠá(c Êœ�ê@*€@G;*ê@Y$ÅGÊN‘oÂÙUKT–e¨°$-˜t·&eÈ0ƒC†º!@¦ ê4.!À]Ó> T`�Ūl1PQŠ  òÊ•°÷Ë2PuP†\XòG@Õ0“¤—47PY–Ë@Å”¸Ìvû“n®`‡þ1ɇHŠªîãŠRú¨Y*@U¶Å*Ø ŠöaRG@5sÉ_ tzuBË@% $d¨„*yÔ‡žAk.,Ë@Å £I5 ðÕ:Pa|\“ÏjRý]‚¸¶Ó>”[çß{(¬x šØ.PåC UT‚—ý@“Û£(…T\”¢y;ýü,Ë@¥ Yd–Ô±)“$d¤>#¹Êßÿ²w’]Y.�ýW@@)°ÀÀ  ¬'!ÀD˜T`ØÄÀФÂ0CÃdÁDÒ€2“d+± îvOÍOú—œÎér¼íºÕßÇ•®÷Þ½÷¾W=r¿>çÞÕ�¡RÉ…ªØŒb *E^$L‘L©ÍRßÉÆ’)�côèꆀP!TÁ6ï€PIDò5Ay*[X´s^½ï¼¯DVâþÕϨBlª€P Tç^Ò¿P©²Pi�—ÒëB•‹ŽÒïÆè[ë²iËS%ac •_€P T@ÿBuês TÕA Õéé騅B9p¡ßøàzùÇë**B…PQöµ T`»Ü¡Ð{©îfïÇbS „ŠBA¨ YW¦µdÕáàï�úà¨ýë? ‚w�éÅÁûúŒ ý¡ztv�* Bª›ˆ^Žû´iâýäAòr]žÑž>ãz?UA¨VóI›ÌWá¹¼¬Ú|2m‹ãàÜñ¢M£sy©÷�Õ›.ÚñÁ �žÉ¤MTô|òï£/¦éï�~_¦‹c„ T¨Hm{烧íIÛ’“ø™H\½ï«¯,òô£Ÿœ T‰P©$BHÏtÞæÓ\LÊRƒPÙ˜ëm$ç$IÙ½ê÷@×¥å¸-ôû‚PÝ*Mfœ¾Pý1ªAJäƒè™œ´»H¦Æ}Æê+Oå‹úQôê¨ýU‚Uª•G%¦‹cý¡:0¡ºb»ÿ«¹¢Y¾Pirj“ÙÃ]+ôN¾ù‚OôYÀt�éD¦êÏXϳ¡ŠûÑ1IUU¨*�4X„Â&âóù´M&ó¶ÒõÓßÒÉæ« öÕYýíqMÌ}2ïשþ6‚âõ1Ñuê_Ç/ô³Pûa�xÌ™,D׫íà¸îk1÷ûÛòt< ÉjnÇ’vã6r¡ Î…'�'(ƒG´_¨¡Ò_÷·MR{¡&G•vøK¢•õ畜×ïa.TA;ùØ*+/r¡òIq0©ÖÄÝå@Ÿƒ5;jg5—Ìø>ºNí_^Oç.È„dF2¦ëÂ:IIJz�&W~_êÃî#ê;�.%í–Rþt.¨sQ@«\ÄTçà… *E#ž¶'J»Ê¢ÿuB7H¨<©gìðg×Jj Ïx¡ÊúññׄêBei^Á¦« úãè<"þœ×S4È#1&€;Õ11Œ‹ßc~|5—`%÷a}‡r"¹Ü–üyåBeÏA㾪P]µ? øa  TšÄ**µM¹JS½t]^œäÛ_G%»ü>4öóŸÕ¿Îéž‘© ÕÜ׎kš¶cÓwíœç»çÕŸqE¨ô;f˜÷£ï@㪠•ÊÍ*Ÿxû|„*ìË…*¯ãòè©z£ UÔwò\%)e¡JÎåBE„ *›|n'°ŠVh’˜ø{:ÜøBåé†*yÊŸ×I"r¥”?IP~_Þ·Ÿ·ïAí^ƒP™È¥ýÝ”5T€Pi‚m“gM`5é¥7B¨Ë`!òÖÁ}¹i,щü¥c)¿%E¶&*;'¹òs�\´n„ *„ ¡²4?}–ø(²¤Ó&_v^%I’7I°t]P¯K¡„ ¡B¨9ò¢èB T!B¥Ô;$¥ýÅ"´{ÊŸ ¡:0*@¨*„j=„›C(íÏÄÇ$ìJ›Rè8Bu€ T€P TU �B T9€P T•G¸‰Ï�çBUè§\'ùžëcsúoýõïëÛ\ B…P­æ“6™¯ôyÜr¼hÓÉ´-ŽÇï‹‚Pu�Ê'®¥¨Î�öx§T°½ªä>tNãÍ…ªÞO¡NAœwïGt1Þ¼ÎÞF©¡@¨* ÎtÞæS$‡r8BõÓÓ7Ú›ÿE¥½ûtÓDÄ×�^Óµ*íÃçaÖ^|þ�öÙ¯ÁÚ©|á|Q *r¤:‰„�&T‰d* wITM§£g§‡§4Öû¹z�â÷\꧃ñVÇ&ŽXKuM TBu¼˜¶éâXÿE (� Õ’+‰éš¼Îó·_�“4‰Mûìó×$bq:Ò�m,¡ªG¨$SŽ=*M¤}Lñä]çíÙÅE÷r?;Ô)}ÏÅ~:o}lúÃi×B€P!TÇm¡ÈÔËHÕ¢ëÜéªÍ'Ó6ŸOÛd2o«—×þöbßùêb ŸŽŸ]w¡îb1×õ’5�» »¤ÝÝ ¡ŠdçB´êíöu‹%èÍG_åâäí)fÇBi;Rº_A¨Š‘�D¢Šk§Æ*ÝF~Ÿ&TÊðœªìØO¡NAP ýt0ÞòØ,íï‹Oô BµiËÙ¤ ë€Pu T&Q&WŸ‹"´šû:+—#]s~½êž_¯ã’-«#™12Fa •ÄIrdÒÊT&IjOçâ¾}ý”ÖvŒ/TÙš“|‹êý*¥ëí.Tº—x¯:…~Tg|A)öÓÁx«cG# Të6¼úƒïl¹±3›åìÕƒ‡Vvo¸ÍÔæÞB¥4?û, 2ñ‘|],‹N©H¢¼®ÖϪ/Ñ·P*¥ãÙº)ËÛLR%kåI^A¨ ©{��û|Öž‰Ó½�ÊÃöì…ÊÏ#TÝ UúÇ‹:€P™8Í–mcQ¤@´ª¨?ÂS€Pu"TŠ"y‰#I.aJÍ»LˆöF¨(U,O&YyQ›qËÛ_¨J2U˜k*IÞøBEÊ_Ÿ)ã  TŠ�Ï�fm¹‰�9.É–G»†µ ÙDÇ,ÝO?'ç†Aml%lퟅ÷§qÕ„ ¡RžÒýlM•Ö1ÅBå‘-O Ì…Š”¿ƒ)•R•ú7žPdª° Do›R„ªÓM)Ø”b|¡„*ŽFI\µJ„JUôYb%7›©K÷³ŸÃs’&�Ç?«MëÏΕ„ ¡ZÍC‘QÚ_¸>Ê£XqÚ_–òŸcSŠÿoA¨tL©z ù®‚jgŒ5T™*L/Û¦'B•µYè'¯S”z?û<ÞB�‘×PB•¤ý­‡<Ò#�r‰ñã~ÎÓýô³HÎÅŸ“þJB…PQ(•Rö´)EN¼É…"Uê{Œ]þò (ª$1SÊ_/öÕx“ûÆi�z^…~®\§ú=Wúé`¼µ±±Ëßø TŠòh û9 ŠHYdIi‚~]–îŸK>+’e…”¿2BE¡ Tâ«ö¡6–¸¼ž„+ÞýÏÛ×µ#¾‡*ß<�RhbË”úÜ¡’i\éq=ÝgéÐĽÐO¡Îî‚R觃ñêŒü*@¨E¥†ÁÓë2¡Z—§Û™`åé~é9û<~4 *„ŠBA¨òûº$EÑ(“3õOôŽŽ®’’I@r}òÛ¼Ž$d„Ê¢pùx³ûJ@ ýêìò=×ÇÖÁxËu,¬?\Œ TZ§äI$B5 Rñ$;¾ÎÊÒôL„eÊÓýâvÔŸ"mV„ ¡¢PªdÇ>¿^}øz©üeÀZG¥´¿k*M\“ëöG¨’wf%Q”ÇŠHÙ3,ôS¨S”ÂØzo^‡t?¸6¡Rª_’îËSÔÆåi{–ª7Ú�¤û%ŸÕŸv%¬B52× T ´?E©`„_¤ûÕ@¨¡B¨¡Ú;’(UPtŠíÒ„ ¡B¨ªdÑ<?€þPÁÚ©C¡@¨*„*MMBªêè½Sû‘J B…P­íÓ3¾ýèî¬Û ºéq«�§W*@¨*„J“þ—;Èä‰î_¨÷Ù!T€P T•¶õœ-7ú/B…P!T€Pä T•ÞOpá ÝzÙ[ðî‚aíïN8O”$ ƒÞµ 4·‹õš ÅrÐ9¸´Þz{^çÎÐÛqi‰ïA)Ž~¡JîK×EÏ®o*@¨*„Jår%ëÐÄ? }þ½@H\| ‘ÎÅoï¾J=�s=HZâvTÏß@žF� B•Ü—®#B…PBUȤٻ?ÌB…P)ÍÏ>ë©"F:Ê…}VÉ„üB¢tYÝB=ûœ·)$eÛRª|<B½ UœáR‡e€Pu+Tž†¦¢èŠI–¢GÝ •WT.]·�PÝ4¡:mË÷ÿÝ&¿PÞÿ¹mšQä—6¨m•O~ɯµR#B•Ì›Fÿzðïý*„JQ¥Ñ™;ßÌËÖ‡k.¡¹V0÷ÒÏKÕ›µáo¿—8_ŒÃ#iöGd¯syû>>�'l;ik„êùîBµÂ_jýDiqö�Qõ|SŠ(z£zW¡Z½<ýÎ6¥ðÜÚ.>«31¹Úi<þìz¡Zˉ/pòs›½ á›8*æ}H¨$[eª$:µ�þ 6?а5Õšç ë?fÐè³~Ö<ÃÎ'ýèúhm»æk»×ÉѵñøÒ¶ã¶ö@¨žçBµU..:§(U]Øf_ž^žjè} T0:U$P&X"ÎnIÒ÷ô98÷çǂ݃-ƒ&ø#z*6Iû>–¤í¤­›B…P TJÅ»d-ÓæËïYòhS,H:/AŠ…)ìCí!T0Už¥bEÒ”¥ûI:òt?ó�øzõéçmC4Ž$õ.ißNÛNÚÚW¡RA¨¡*‘ËL,\:ïÇ"I’¯>Ýgx�î*ý†ýNÝ’f‘ϼ«N�sªªaà>ý¾ç@ BåÒ Y±¬•Ÿ�JÝ¢r?kóve{––Z‰ai™]8¾~w; ¶„ªì£P|üV:wî\÷¸p#E¨Xv¼ŸÖ>rf’U TAèz€„*Þ*}ùF^VƦóËw.^¶©{¹Ÿ•ôi~7µäNÇšÓD«Iµ=K8~pÑØÑX€PõC¨n/ª££#‚XkìªP5¯ÈNK”$P*õk –Ë—Ïãã T›*­• 6òj­­2ÑRØ.Æ­�±:—û-ÿŽæHíÁZv>Ψùøáý…ccÁö�P!TBU΄*I¢â-Ö]š‚X}ÉBBE T¬»ä/Î>Ås™DiŽ^lJ€P TAPòW°)EÜî×”gÉ*„ ¡Ú¡šVƒ4¨¦:^oÌÆi8¦ñ¬kŸiªúþfãaøxÅáój\?WþŒ=„ª<o‘þÚUÛ*½;.NB€PmƒPé�ÿa•ªa$›¿�¡ß_[¶¶M¨âqªÝú°¯my¶IÌlSŠîÙ) B€P T[ TÊð Ç3ý»µBUU­ûSL«4¨ªT!TÕ�ÔH†ÂóAæÊå(FBæÒ„P TÕÕ,�sæG™ªqšµ3?Šjú"›Õ:_MM¦¹]mÇ’¦k%C&ºs©�ÿ[¥©ßûLí*_´û^:G×y¡Òïq<ãò÷ØÏ@¨â-Ê=;åÙ(Ç×CY Ó B€P!T’(—+—K<|��LcM«–`èX2¤q5g[Dâ Ï´²ùó|j„hZ™Ì,;W"T’¤èw C…PÅ[›K˜|Ý”‹–‹“·»P¹tm‹P TÕm„ª]î×>– ˜H Ú" Ž_Ûo3›–DsKær¼4�‰›�+ªà·X¨*è•>œ«� o!€P}µïB¥ ‹‡g…JY´©Ä*Ï3nÆœe‹Î)¼¿��P!T€P­‘ù$�uj’~�Ò6¹ TÕ´R‰žID$Ij‹å">./ùÓ}/_¯dÏä[—{V.>'aÔx¾½BÀé@¨ªyš(35—\,ß¡féV�¾“Œµ�&ÉÄÉþeð¸�d¤®G‹¶:5ñÜö\Ñ5’œ|OI“ýö>&d­9Z_?טv­µÙóè—<÷Ö�PB€P!T’(—+ TÝø÷ ´þȶðT¿v›Cm.4Ak“€Ds ¿w'§ÓUëkçM-QÒü&G“QŸ#©_Þ{ A¨¡@¨*+óóÑ5©nKA[tÞek–Ðù7–dÆb© çvQ …D㺀sÇmݯõ÷¥÷¡°ûØF*@¨*„J™�,,ÁúªR¡R?φ­X¨\ã’?ÿß&„Jsùólͺ+„ */Í/*Á÷%+ÅÆß<€P!TZý‡©¡SËËîÔ”ïi¾îe‚.ñÜŽIa,,K™3{z_ÅB5X.¤Þ†P!T°#B¥¾¥ýôw@áøÞ€P­Z¨l3ae’ /ÙH¡%mñð &l£ˆö6íAŸX|ln᥅�3@.s6N]—g¨´ÁD¼‰%ì�Péoªu¡ñ787 TÕÆáÿÙ*@¨êz`»ùv(Ç«kßá¸ÕnãYµ�_§¨›`|ßU¹ßŸn„ ¡jjín×c¡„J"ãKâ~’[jaKÔ-¥°¶`|£gB…Pùÿ‹ÂÌ;B•IŽ UPrgǶìÂd(ºNmö;hÛB¡B¨*@¨”±r¢²=ËpµCâí¬6ÿ· T+ª££#‚Xg T€P¹ 騲QQ¿ùd¤ë¬Í~m}*„Š *@¨âr< •ÆÒx^îçB¥9ãr?ë×3¡B¨¡„*.dzõæÁ÷/ý31£å~6v÷Û*„Š *@¨Bø TÕ4U¶ ²šª­cÌÆi8¦ñ ‘ *@¨V%PµÒK¶uúÖB%’UiŠ T?¡O�ø0o/A¨*?&„ *€½¡º±¡šViPMÕž¦Õ‹R@�WŸª¦AÎfiŒ@ÐÚmÓq¶Ê gã¡æHÃñ !éS T€P TUKš¼ÜOábÔ–Ÿ®B¥¹†ã4“¼iSnˆP!T€Pl„ê�+ÉPù’ž‘4´íV¹!�PB€P!TG³4æR¼Ö:�P=ª¯þ[ú/ÿðŸ^ÄÛŸþ-W^MéÍÿ¼ˆŸ¥þq)ß{ŽK—ÒNrðqzëÜ[éダPl„ê_n<ËR¥øg¨¦•ÊóZç#2!S†ksBE T’©X¨¾ùY�eJ|�Òû'RõMÚn¤ ç.¤/·…ê }ü‚µK Túo?ç°ñû TwŽ…êú³–T•®¡òlÕÉùa•ª.*/¬ª f¨„jžþéí?Ëõ¿¾úÿ‰È«)ÝNýæö›ýCqãB:wî\Ž·²5I¨ÚmÕ€PéC½ëCí%ãj«ö‚ù­­gÀ¡ZDw¡"ˆÝªƒ¿OÿýþÌ3R^ê·[¥rzž+_ïP©ßBž,.ÜH» TúÎTݬu µoþ¼ *„Š z.T=ÈN‘¥2¯zë¹LaRÛBÕÔªÀQ¤ÑdÞ-ÛÓî7š¤y»Tîä÷Òqu]ýbnIJS¢ÿ}ÛíÁœ�_§P[ù½ÁÖ‚PýêúÓ,U«ÿs¸?BE TÿöÉ_ÚÚ)Å_¦:h­�вS7ßHw_y%þù+éî7ÿtû+gÒCoþö_Ókõ?Ò_ÿÕÏÓùoSl̳éÉò ÒÃ36§siËÖR½G­›òì”Bë«ÊÞ[9€PI¦$Cò¤Q,Tê§²7ÉUÝÄåpM­y$ck ÆûæƒTKŒÂqí:µÜ[?„jþô%©ú¡"U»<.�‹g³èqû=·Ý¿˜œ"¡ŠÇ5q8óFz–Å­)û+x�7.hý”oJ¡v•þ¼·b¡’ÝËý$;NØ××u)û–Ç æP†®àÞú T¿{œ³T¹ôo~,TϪ¡ò’µM”ŽyöÆ7Uè«PÅïqÃï­@¨ºïð×ag¼fÙÎ�£4ŠKê¼_¼»_û.|v�eâÊï­OBõcúåoe©zž©z’¾9„*¨ ^MÍ«ÆÖLú틃í¡R¦C�µâ›,¸(” ÕæKþâ÷¸ù÷V T@ß¾€PÝ^Õ/~û0ýòw�”©J_ÇBåÒãÿÁ¬O¨`»a •e>ÎØßëÁKÕ”ÕñŒN_ÖPÅïq+Þ TT­?Úlëôݪ/.¤êQ–ªE–ªL¨ü¡‚½ÛåÏËÆôûú³ÚLAÙœxS…x—¿- ~�ÛðÞ@¨ÀK)ÝÛ/ªæ‹£œ¥Réß×OO/TMÝZdèõ³ujZ}êz´8÷_S­ºYßÅÆ„*þHX£{h-æôúeA¨º‡Ê·ööÍ¢�.ÿÝñ¶é‹ø›M¿OehÍïôæ;TåïqCïÍ„ ¡@¨>?ZHÕC•þu* “¤)�­c�QÉŒ$Ìw±I«*}•\óø¼º_ªH<.]JÂñ,ŠeA‚r²kéõc™ZÄë¿^Á& qiœgÞ$ŠÛCñ{ÜÄ{s¡B¨ª£Óùk²T©ôïfI†ª½aIJ¿ÕÍr jg¯$@¥B´ÅǃPi•—ýÅ”»$x»Ø÷ÓåUíZ××r¿ò÷¸¹÷æB…P T}v?�ÿ|!U_<—ª›· „*üBö’>ö}ý›ªMƒPxÙŸ²T«ä÷oÿê7ªS=ŠåÈ/ývBµ6ª8KUÎwéüßg§~žÎ»‚ÍN»…v.ÜOì½B€P.„êƒÙ½…TÝOåÒ¿P¨‚5TKD).ùöµï®B%‰Òø5ª5ƒPi-Õ EDë§þîÚÊ7qˆÅÐ×Ní!öÞÊ„ ¡@¨®ÞMÎ^d©nÞzÕêÑf°õ T*•[•TýúµÅжïøÝ)•.î1öÞÊ„ ¡@¨Þ¿z'}0»«Ò¿ôÕ*e²´l„ ¡Z)ÕôÊ�¶Tm@¨´Š�¾BUß@¨>½}"Uwózªß?.*„ *€½¡zð,½—…êvzÿDªþ”PÄ:¡„ª‡ T—³T©ôïÆ÷�*¡**€}¡z7 Õ¡JÿÒu„Š@¨ „j@¨ž¦w?9ÈR¥Ò¿ëß!TBU TûBõNª•þuªiªôQÝ“¨¦'m³q†i<Óµ›ÝS®�£ *„j¥ T¿)*_C墣ó’%ïÛ帴Í�B€P­„êíc¡ÊRu«X¨TÚWM—µ©œOí;$TB T’ªg¨t½¤*gªº‹�‰šÊøz-TBB…Pùª¥"#òuV§!£ª^j›V:?ýI„Š@¨¡„ª-U¡PBBU;¾ü÷#„Š@¨`«@¨*„Š *@¨ªC„Š *8 B…P¬„ *„ ¡@¨¡ˆ@¨nä@¨*@¨à4Bõ BUBBõ/U“j}l÷$ê&´û�ÒdžºS<_0÷|’Fú l„ ¡B¨$$”:5k*ë×Ôiàó•Ï l„ ¡z&©Ê�Pùñú„ÊŽû%T€PB€P-dêzŽ,V½ªÃU•2FªÁSÆÊËóÚýší# rÒV×#eŸâùF“ôâðÅ\v­y&ÃÆ‹dmž&#{Žr¡„ ¡:x–~uý©„*G�…êYzg%k¨$@j“|Øz%õ“ µJ÷Ô&Á çÓàaJ÷¡ÛXˆÚ)…J¢¸¡„ ¡úúX¨æ.TÜC¡’t˜4ùz*e�ê&’û‰’�/1“lµ¯“¸ùѼ>—$o%BBuaþDYªã@¨TW7k*e›$9­ùt+ªŒæ£äo T€P TOÓ…/Ÿ,¤ê©¤ªçBõÉÁóXA†ÊJíLxV%Tv¬õTšëT%&ƒÊvù}˜Ä• TÕ?ùøy–êDªîô^¨r¯¡2‘ØXÛ …J‚“Eª½qĨNõÈ·W�7¥ðëuÝ–5_'Õr3½qæ•ôÊ™7ÒÍÎ]ÞHg^YôiÅ™7nÚ%gZíQœMS7*„êæ­…PýîñBªžHªöQ¨ªmáâÙ,6±P¹|¹!T°A*„ê—¿{”³T*ýÛ ¡RÙß¡„ªåb •ËT¹ùx§ ¡@¨~ñÛG’ªœ¥Ú ¡RÌÿðp… *„J']·²{8Û]§*„꫞¤_|ñ0ýò·�réß…/ªžÕÍôp‘i9üó%±È¾f5Ù.„ ¡ºñýãtþÚIU^Ouç!BµcA T–½ZÈÃÛ½ª8ԟ쬄 ¡z”>úì~[ªBõc…êݡ ‘ZBE TÊHyH¨z[òwñl°»Ÿú+SEv ÖB€P]_Õ‡³{é£k ©úüA^OÕw¡Êq:¡š¦J¼=‰jª6ï7Lã™��#˜WcýÄ1§ap/á³TÓ¥í³ñpƒÏ‡P=9kµ£BÕN*ÙQ–ÊÇ)ÏN TÕw�ÒWï¦?»—³TçYªÛ{&T&FŠ*M7!Tê/éŽÓ¬‡ò gõ<Þ¶yaô÷»BeY)‰Â–üI¨âÌ“g°|]SB€P½õNú`vO¥»"T‡%BeÇ*;î¯PUÕBªÆ³—Û¦UTÕž ¡’0ÙN~»$TJ-YI_q–Kc”€P TWî<ÏR�HÕ.•¢@¨$S+�³rÀv¿é‹vÉD[0–íê&TÖ?º�³4z[á½û}ÄÒgç�ÿÕóê¾tþE¿iõâžì]·îgüÿÞǸJ¿_ë—ßW¾ÞæÞG0~?…Ê…ÉÛ{]ògÙ¥‚mÕ­1B5ÿîaš^¹ý’TÝ>Ú;¡òµLµ™ è�|õS™Þ´R_µ”%Ö?¾IKëÚ‚{÷¶r¡:–%›óxŽýì~mÝ•­Ñ²wmBœß…�ÞG0~Ÿ„Ê×OI&Zq÷•ÝXCnL!™RI Ù)XB•}cúéíçR•Kÿîî©Pù*/YO%aeÃÛ<ƒ‹œ÷�ïÃÛ�î=h+ª–DóeaÑs/éwªL™Þ­g¤º¿Ã`üž •‰S;$Rw·/C% ¢-M¾NÊ#’%Íåc–€P Tï}z¸�*e©*e|LVJ…ª`�ÏÆ…Jϼ"¡R™ß´%Hj7IÕµåB<ÿž •dã¾IÕý‹*ùë¿PÅߤж@¿™Þ8CvjÅB€P]>ÌR¥Ò¿ÛGϪ%ehöGù…*º�S–ü-)I žËDK™¥X¨tÝòuY¹ÍK ã’¿X¨üY Þá. l„ ¡:Jï~rð’Tî§Pù÷ ,Óãmªø>ü\¬�mša}âò<Û­/Îò-+a´ 4×TCŸ+Ø”bH°•ü)¥ãà} TeB€PýûQzç“[YªÞ½|°�ªÞ ÕíÝ…jߢ/[´[i ¡„ ¡úòX¨~sKR•3U» TŠ~ B¥ìÒÖè¡„ ¡zû7?´¥*{ BõB¥R@Eo²S TU„Š ª¡@¨”¥Ú1¡z´T¨Ö Bµ? T•"KÕყU'*@¨ª�X„¤ ¡êBBõ ýo„ª„ *„êûv–j…ªIõÉÎrŠºIí~£4™§ž2O“Që¹G“túG„ê(M^ûu¼ömš§ŽüþÛ4úëEŸVŒÎ¥6óóW[íQÌS“¶„ ¡:è­P-„êÓ¡21šOÒhP§¦³PõL®ôŒÇÖ¹I“Š(—ξ‹+BÕ¼žÅ&*—/ÉPÿ… ¡` •Jþýª÷V Tv¼cB¥Ì”dª„ ¡ºF äÏh^÷Ýý¼œ©";€Pl„*G,T›*„ª¾¯±ŠÆÐ8d§*€u‚P]A¨¶„Š’? Uœyò –Ï£k¡Ú"¡úÍ9*„j­»ü©¤¯<Ë¥1¡Ú¡šg¡ºµSB%©Ê�PÁæ¡ä/Î.…Ûª÷.;€P Tïì’PM25•TButtDk „*Þ˜ÂeJ%�d§ª­*„*BE T«GD[š|�”G,KšKcBµ�B•¥*Ç.•â'*‚@¨º~“*Úý(M^#;€Pm?€P)*‚@¨¡8 B5M•>H{Õ! *@¨¡úƒ խݪë�…j˜Æ³“ãÙ8 Uš"B@Bõ0½óÉ­’ªÃ}*;&„ *€„êà%¡B¨¦UTÓ“6e¬¬°Õ¯ª†i ŒV|m�«¤¶áx†x T TÛBu·@¨l •äHm# “ä+·IŒº]+QËÒFYaï¡„ ¡z÷“IUŽ=*‰�‰Ð’õTÓJÒdý‚k)+ÜÝ@¨¡@¨U>ž¥ñ0‹BE T€PÄ T—wN¨î®(Cee|&MÖ/¸¡B¨*@¨úBuõn‰UÙª¶èØF�×î¸P T•âðÁ³ý*‚@¨Ê„ ¡:\BE Tpj¡zïòa‰U�…êG U„Š@¨`­ TÕw;'T÷^’ªëß#TBë¡@¨¥÷>ÝC¡X7»/T€P T×[BõÞ.Õû T°y*„JÑ{¡Ê1Í�PBë¡@¨ng©Ê± B¥@¨¡€uƒP TÓOoç�Xí¡P5©ÖÇxO¢nR?hê—î{4™§Õ¡w3Já°zöÒÄ|2J�±k T€P TW$T9^²3Buo!T�C¡2i�¤Ñ NMwÙ°ã�É”‰Ê]Ó¤:÷ñ{ çm]kïié¹í¡„ ¡zÿÊ�{,T&G-)P[Ý´E¦›°„}5çh’æ’8I”Ž]˜\¨rß(sÕ5ƒæÒÔ–9µiÜ8‹ÕÔ­kt�]æu‰u±ÝF*@¨ªï-¼CBE†ÊÄgy&HÒ Ki_;Ö=˜ì­ CeZÄ}FáÚ,õiK”?k4¯žÇæðsÛBBu¥ïB5[�Pµ²<[!Tek¨‚1íºH”±�”-Š…Jc5«nó •ÿfªu®u³¼m4¹ÔaLûßEãíŽPB€P)f÷v@¨rìŸPÕ|òú#¾õ¾Ž*Ÿåb#i²÷¦6 jºtòMµ¿H“y0¦îíxÌ|Ö¯×BBõÕÂ7>Z¸ÇN •¢»PMSeÿ¯s5UÛšb6NÃÁ0�g«“@¨&#ÿ#ÝÅÃŽOþ�Ô'áÇm´$à¥ë$mÉX’½é:¶ÄPçuŸÁýÏ—Í›ÇÖ˜‘àtªPÊ|L]Ý—÷]¨¡@¨~X&T?î£PIn$;Uš"= „jdÐI¨Ú•ö±ä"�ôS9[œ):ÝØ:¯ [,TËçu¡ŠÊ"%Bm¡ Ë&5¾D0s_„ *„J±CBµx°BeÇý ¡’tªåç]^Š@p¡ê<ö² Q�PÑYpÚ·ºq™ê,M;-T€P TOÒG×îŸHÕýž ÕCª ¡zrz¡šViPM_j«ªa(k•3XVØgú¼]m³ñPצáxfs¶~�«%×Ù|AæŒ@¨jeKV)T±• •G¥w«*ÏPÕoúq,_íkMú‚1w\¨¡@¨Î_{Жª}ªA¸´¨ÍEHåk¡4Îpœf3õÕq[×Z¿j]§6�×=6¥P]ûºH¨Ljêæ”BÕ¾‡‚±k‰FÎ-$ñWÑýû¼AÉŸÍ�ÇðµPÍ«-ѱ $<3ÕiÌ=Ú”*„**—¤x}UšV,»6<Öïè:ËN)$^ ¡r©òõ?v~T¿Ú%Cµ¼4¯C?É„ÄäTcÛ&�±ôþƒy¡ò¹ƒ TKм�ßw0&Û¦BÕª¯¥‹…Jdz4J’¶@¨¶ºÌ�àþö„ ¡ÊR•£ÿB¥X}†ÊKþ\°V/T^r¸mA TBBõùƒ¶Te/Ù3¡ò5T‘I¢üÚõ•ÏGÉŸBµcAô @¨ªÿËÞ°Äu¥o\úÿ(\ ‹,„×/РP °„ìV(PéÚ….n)E°Ô×Д×¶C,vÚÀ:U[cÌÚѦš8šÕ¨ªj�ÑDãfc6&&}÷>™œ&g8×Ìu^½3×çÀ�¹êÜñÎñÀœŸï9Ï]0BŽ˜P‘C‡BQº}û¶/Þx$T³³³.!„�C*66 Urâ¿–TEF¨ÀÜFá¡PAšÊËË¥´´T@YY™TVVJMM�466âçª"„B(Tll*`ÄŠBEÈW¨^~ùe©®®–ºº:ùì³Ï¤¯¯�*B!*6¶bªMO¨&)Tä0 PYRU[[+ííí2<ÃZZZíÞ~ôOD››7ÿpì„ÇxÞX½‰@[òÁ`¼Y`»…ˆ^ÇÈ”™—Q¨:'3Br*#5%R“´¿×”ÌK¨Ø(TF� -TýÒPU&eU Ò�¯ó".±2ïµ,ª¤¡ßçùñ˜yž/U ýx®:ý Ux}ó¾ Y¦ÜB5ôº-SÚ}Ûß Uú ÅqpN6?ÏHÕ­!¿×NI¢%!)ëk#T -=m, Õúúz6øL2Çf);ñµLTOœ8!ÛÛ?ßÄñûD}ö:¶Ï#©k× E›òá‡b¼í…'S�Â#¾Æw¦ T;F¨î¹P]¾›‘ªŒXù •£2Uã–' [^Beþ[5¡ŠÇÊtÄ" >yK¨Ìï-H¡ê•ñgõçA¿ç™xI6Ç•eÕv(`¡ãïÉݽ¤2•ü´õ¤m¡2?Ó¬XB¡22…û)âñ©B…êT¦š°…É/ɲô›Š ©yõUçñ_êëqœu�L]]ËŒË BY*//7R¥*T]žP#U7‹Y¨’… d„j~c×)TL/! ÆZ^ *ÇVI,âsO|Q ò¯T™ëˆÅñµ>þ•u¡2ôD*Ï×I¿%¯ž|Æ®Hù-õ³–»)ô­%S1‰ë÷¿âµÚ}q·ïÜÞKý O6æoEˆ*#SÏ=÷œ¼ñÆ9 Õ-¹±õïG“àë$ ,_ûýñãò÷ÖVçñW_~‰ã¬óÈÚú5¹²zu_BUZZŠ©ÒªO 8"B©…䢞Sßžþy9vì˜ÔÕÕI"‘ÈE¨¼ãk²¸¸$ÓÓ³21q™Ø@ ŒD9�!T8¶Ï#—.MÈÅÑ1™šž,Tø<Ânoo—ŽŽHUÞBµøP¨î©E,T;?É×S÷K•Çü¦[¨¢–`$ùÄ QJ‡‰¦Pa2î+5FdbטHãzï 2f®¯X…Ê,qƒ<(KŠõü¢*H¦{Ù_*aöO9C)Ü3#Tþ¬ûŠ;!¬P½òÊ+ÒØØ(Þd0'¡B5annA&'§dlì_$‹¥¥�D9�!T8¶Ï#££ã2<|ã*°PUVV¢àà�?¬V¡‚PuOÝF¬P艾P…Ÿ`£–î¢�|BÒa".TfRl%û¹«Sîs€ó|‡œ¹'ßñ˜ß¹ælÙ*Ò%k�îå~yö­ÕG8vˆªŠP)\«ÿ²¿Ïß“åŒM_l¨ÊH•7f}ŸG÷PyCéëëËI¨®^]CuJÆÇ'äÂ…4Éb~~QþÚÔ$½½½ÎãÁÁAg�G~¾(CC?xÕªÉÀBUSSƒñ»÷* Õ®GF¨@p¡ÒO°ÑOwÑN>! é0Ñ*ߨô˜Ä’,-4çYç˜÷WÜB…ýSŽýB }ë’(Ýàµkõ¿/•¾P¹—z¢·º§è”¿d2™Ó {]&'§åâÅ19~„d1;;�à ïø¼ó8�Nã8ë<™ÄÒ¿ÀB… «nÊ„ê¾tOGH¨º¦=¡ò0•ª…€B¥Ÿ`£Ÿî¢ž|BÒa"/T¶Ì8ä ß¾?  ײ½ÜÞ‹B¡ö¾Ížœ $$¥"Tþâ Õ·þ}¥�®p­ ¸hæQ‘²¡P=x*ïõVPQ�ï¾û`’Dóòå°ç±}9w.%}}ÿ”±ñK ÷¡R*PìBuß’ª…Íû.¡ !ÁF3ÝE?ù„è§ÃD1”“í`û«Ü¸’íHï*)–äD"úBåî[Yõ­ôAùZZ¨–c–@*B(TnÜs$TWΞðæ3ýòmïYBòçÛ³òÍ7}ÒÓsFÒé±@B•�¾P""T†…N¡ !ÁF-ÝE?ù„(¤ÃD[¨â1SEPœŒÛËûªð—ü© •Ý·9ìusWûÂ�T×*»*‹sÉŸB¡2ÁK±œ0Qõ&�rþü�‘‘Q„¢J*5$mmmo�qÈTžBuR" T3*@¨BH°QHwÑK>! é0Ñ*;Ž\ëw¸÷C¹Å-8ÑßC´o­*£~i_«¾hÚÂä—äG¡"€Bå÷Ÿ|<æ ^Ë›¯áŸÓòñÇ„|úé§ÒÝÝm�a#I¹à�©} UÏô= ¡êö„ t¡ !ÁF-ÝE?ù„(¤ÃD¾Be&½J±ØFÒP1±&×z7ŽzÊ_�¾5ýa*PêÑæj× åO?t‚BE…Š·N)NHöœ>O‚ Õ …*„…t­ä¢�¡2Ïó¿A¯œ¹ó¼¸Äö¼o•ëšpŽûg–ÜÅâ‘*ÿûPåÛ·þÁî¿¡M²±é¯}!ß;~®}­>÷¡ÒÛ?•5†0^6ʸ‡ŠP¨0‰üq}‹�£N>Bà%…%TÞdÖ*üâ��-¡ÒO°ÑOwÑM>‰>¼U<|?‘-Tn‘ }mÉQ�{™ëð%ÚBeäA:OYßWé[s^àøò^y2åñþiç5©^«»jg$3OŒ8ù„QlD¿BE(T„5B•!g¡±„ Þs Bµ°°àªúúú_»„ ,Üxàª$Ø(&Ÿ…t˜è •¿ì˜×òŸL"ßû&™k‹¨P™}Tîeú}ë/5îû~$Iÿ×Õ¿VÕå~öõ¬gIÕzœKþ…Š’§P�iàªææf?¡‚ç˜Pü…* 6ŠÉ'D-&¡Š Ä,û3Uª°ùþd#ªSòæÉ‘°úÂ,÷+8¡PB¡Zz(T»FªŠ]¨$g¡Š~‚�3ùÄ ÑL‡¡PÜUªp‘O^CuªQ>T}íÜ«S&õ°!„BE…jë¾|3³ 4„*ì=Tª¹ÕQL> Ñès…v”…Š˜½TaË„Ù?Uß’Tš½SÅ!*B(T ðªðSþü…jÑ-TE!*.ý UªN(ŒBsß)kÙcB…Š Uø);;;{ Uggg‰·´Í!TÀ!T€�*B!*B(T³»�¥ÊÃÕñãLJžªÖÖÖ’ŽŽŽ’®®®=… t¨BõöÛoÿòg¡š} U*B¡"„B¡"„ŽPBõî»ïþAÕÒÒRÉÔÔTÉèèhÑ!*B!*B(T---ÙB…B FðœÃªT*U’L&®C|ç�wJý„jfã�4·}…7K!„B!jüíìÝEœ"ÍÇñŠ»»_ãzÍ1î9Å/qw÷Ûëî¾î;îOÖ÷±È(0‹[…ÿÓŸ‚¢h¦»¡aÙÏöáûú»HCýöiš½C<¼YnT_ùÊWþþ‹_üâë7ÝtÓ‹T»wïfÇ�gÓÓÓ¸È^o‚*•JÑ/¼ººJ7 Ù¥K—؉'¨ìöìÙÃn¼ñÆW¨A%¢êÌJQ…IUƒXM©n³H¢Â†&²Qhm]Ož„Û–Ó¬ Y5#Û† ý/Ä@þÿIV³–­=&õ=ïyx×~þ¯¥²UPÒ5A(òÉø„ò|Ü—#cÞ,õdZq§u¤øˆK3\s¥î²¾!²Ýè’�li.Êd.˜orüüVkç6ù1 Žý¿â¯a«z;¯Þß8ªÞßáêcqmóQ÷>æIñqošOx3|Ò—å“þŸ äøt0¯}uˆ--⹈Pæóí#‘kÏ\ âàù¦ƒ2ÈÓqšðe«Ç.S=†éê±¼Äúßeý&ÀÂzÅo~ýº¡Žlk.Ác´‰ R;7¤ÍÀÏ­îòf-k�³Ä‘­5ÖññÅí¨Ä{&Þ?ex_�‚`‘OCHVâ3†2ŸÝIÄ~sWѼݢWÏŸ®6¼ßÏ‘’ªiNð¾*}Ÿ‘0Mò|:P7Er|ÊŸã“$‹ýRÍÉ`U3NÒ|Ü“æc$ÅÇÜ)ì»ê\„öc#—5Ã$©¹x_L`ïV3Hâ|ðB#Úë�—‰ý  ûÅ�º³úŽ’uþýb�‰ÛÀm‹½%îm‰ÇŽçÏž;z>i_Y ç_;%±¿4¦ËK%êôÉ·¾õ­ƒ¿ýío?‰^y衇Xõ{bÙÐЛ››Ã€ƒ" ŒÐ9 ¡{Ð?Ý ªõõuº¡p8ÌÜn7;}ú4Ý‘#Gް{aœö¦·½›/&Ú *˜„€TjTµVÃ2ã ²Uƒ)¨,†U\—]A%È1jTÕý•ƨò!ªä…Ÿ—>²�Aå„ÕœUµüRP5G•*°/¨ˆqP NPIF¡oƒÊ‰*û£ÊÞ ªýµXZP�T@AU0*£¨'ª 8AÕeí½ß—äcd=¨ˆTD *%ªšÂ*jP "ª@ *PÂ*)ˆ¨)¨ RP jT�UÐqPö–�Q…û?êRö–ˆª€¶·œQÕaP-%J]ò‘�|„ÿûß¿ó�üã{ï¸ãöÈ#�Ð0hdd„ÍÏÏÓ€Èåra`„ÎÁÉþ Êçóô &“I ª••�F™ÇãagΜaùË_¨ðpç~ò“Ÿü cµG«5è^­´U˜TM |¼�¨²!¨Œ£*Ùš AÕÛ¨ÚªP½Ux�{hJ… º¼ðÕßMP¢Ê™TÙÀLTéN©`§Ubý+kºíÉ*X˜T õ&ªzTàNCŸLª²†UÎa‘ù ‚Œ]š§T U*¢UÏ'UNPÙÏ +•P;OªÂ:Q5¬”I•TºQå“(“*Äì8©BPµŒ*hžT ‚-“*h=©BD©Ž™Ž*å,¨¦3 ”}%˜ *𬖩GÐ%Ÿýìg3¸ ®÷p÷ÝwÓÅô:Dߥ‹ŽÁ€ƒ¢H$‚ÎAP¡{Ð?è Î‚ªR©°R©Ä …Ëd2ô onn²ÿüç?,‹Ñ¥q‰A\WúÛ»w/»í¶ÛØ·¿ýí=¯xÍèA`RubÙ´*�S*÷AOƒJèAPÙ0¥"mD(“*ƒßI0>õ¯yñ;AÕ£IÕŒ2¥’Oýƒqo¶ùÔ?±®ÕõÛnT�õ êÿI•Kb*ª ‚ ú$¨œ êý©jTѦ�¢ zuêŸTýUNP5…UQP¾(V�*õ´?0ªNOý“u/¨ÌO«Œ'U€Û�΂Òûh ö–�Ÿúwj™>3G‚ùô§?Í1ðùýïÿþ[n¹åYâóS¸Â¾Ô÷oû;wîu Fèœ�� tú„BÙTò•þ–––èžsžûóo`Šú2�Z]]康ëð ËÙð—/¤À=åAõöö–6]¼¼¼0cï¨Òµ¿ƒƒ¦Ti|†ü@ÕÈÈÈŸ===¯ÈÌÌÌÌÌì³ëêêúÒÝÝýebbâ0Åf?nÑaÖ¥omm%·ìïïsÝ�÷S¸&ÞOá@…Ê€*PÅýÁ¸öÇ,¿öÇþvö¸³~�ʈAÛ48ÌèèèÃÃÃñQ­���Ëþþþûúúþ£ÞÞÞ{33333³NÃØbpp🡡¡¿¹)‡?¦¦¦~š��ýžÍ~Ødmm-¦S¬KÇ/8Ïàšüºþ L•UL©Ð[/X'ȵ?¶a ºÓÓSu¡=ÔÇÝĤÀùùùôÁßéééÙý΃08>>þ+#8û½ÓÌÌÌÌÌÌÂcrrr H±Ñ�áS\õcU:O”öööp ~‰í~¸&Ö¥çÓ©ö Ê¯ýÕ×§Ç”êááá«)wY=ÈÆ PÅ’ ÞTqV2nãþ"Rœ™™ù�ƒ-Fq�ffffff†'p¾˜››ûH1•âÍ&S`ŠE8¯ÄÛ©˜NᚘNÕ×¥ç×ýZƒª¾>½¾œÅÕ¿IuvvÆè,P•ÈXmccX¥ñ­ª………4¹â lÛ °EüoffM3333\�/pÞÀø‡à\˜Â+¸…O@ÅÛ)\S_FQ[—^Tõkù”êññ±º½½eã_™± "PÅ8�;Š|ôwss3½­Bˆ+++Õòòrµ´´”¦W´¸¸Hüß8333333\�/pÞÀø‡à\˜Â+¸¿à<“O§j×ýÊ‚*ŸR±ƒýÆÕ?Ö òãc46g°¨ noos �-€Žë€”’×××ùÛ433333³0¾Àxwà‚Gp >Á)x·ÄU?<ƒkòéTyP1îʧT¯¯¯<Üb½àW¨âúoªxè…9›4�áîînµ³³Ã½q—‘›™™™™™užÀøgà Ü�?pÁ%ø$ÇŽÁ3¸&ŸNáŸ6 j>¥ŠïR1{~~T¥±›2.//«‹‹‹ôåapttÄ·ª8ã6>¤…‰¯›™™™™™uZ˜_à ¼�;ðÁ#¸Ÿà¼˜Â1x×à›¦Ó©ö BißB�¸øQìogíàÍÍ ÷ùáH�-&}<ëää¤:>>æ�IŒ‡‡‡ffffff‡'p¾Àxwà‚Gp >Á)x·à—o` ÷”UsTÅõ?î >==U÷÷÷ÕÝÝ]úáHðêê*p•„x~~Î!½‡&þoš™™™™™®À8#…?pÁ%ø§à•¸æ×S…AõªâMº�¬§±Š0pu}}ÍÁP"÷9(±žø¿iffffff¸_à ¼ˆÂ!x$ …SðJ¼™zSÅ@ÕU<àb+Ê X1Fㇳ×�u„�+FmÄýň‡aÄÿffffffÆDá‚GpI@ ¯àüRSª�¢Šmõik¹“Èg¤†ÙïÎ}EâpH‘ƒ¶ÍÌÌÌÌÌ Wà‹°îÀ8�à|RŸJá—"˜ P}Uù´ŠŠüW,â`„ÍÌÌÌÌÌ>X#ÌÁ#¸ŸäS©¦˜*ª@Õ;°B|9®Xã6Ù:333333\Æ@åˆÂ'ï@*0UT-¦U9¬WQ «tffffff�§�ä�j4•*ª«X�,33333³Ï wä€*9‘Êû—`±;¤ŽIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/dummy400x250.png000066400000000000000000000001531526573132500272320ustar00rootroot00000000000000‰PNG  IHDR�úµiƒPLTEÃÃÃÖ)D#IDATxíÁ1 û§¶Å.`!1ÎU-IIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/dummy40x200.png000066400000000000000000000001621526573132500271450ustar00rootroot00000000000000‰PNG  IHDR��ºq¤�PLTE�Ê#*IDATxíÁ�àûS` Õ€8O°õ)LIIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/extra.css000066400000000000000000000051321526573132500263650ustar00rootroot00000000000000.dropdown-submenu{position:relative;} .dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;} .dropdown-submenu:hover>.dropdown-menu{display:block;} .dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#cccccc;margin-top:5px;margin-right:-10px;} .dropdown-submenu:hover>a:after{border-left-color:#ffffff;} .dropdown-submenu.pull-left{float:none;}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;} .navbar-brand { padding: 0px; } .navbar-brand>span>img { height: calc(100% - 14px); margin: 7px 15px; width: auto; border-radius: 9px; background-color: rgba(255, 255, 255, 0.12); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.32), 0 2px 4px rgba(0, 0, 0, 0.3); } #navbar a:focus:not(:focus-visible) { outline: none; } .navbar-nav.navbar-right > li { display: flex; align-items: center; } .navbar-nav.navbar-right .navbar-form { margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; position: relative; top: 8px; } .affix { top: 50px; } .alert-warning .admonition-title:before { content: "\f071"; font-family: FontAwesome; margin-right: 10px; font-size: 120%; vertical-align: middle; } .admonition-example .admonition-title:before { content: "\f0eb"; font-family: FontAwesome; margin-right: 10px; font-size: 120%; } body { padding-top: 65px; } .btn { margin-top: 5px; margin-bottom: 5px; } .dl-button { margin-left: 10px; margin-right: 10px; } .center-div { text-align: center; } .featurette-image { -webkit-filter: drop-shadow(5px 5px 5px #222); filter: drop-shadow(5px 5px 5px #222); } video.featurette-image { border-radius: 16px; -webkit-filter: none; filter: none; box-shadow: 0 0 12px rgba(34, 34, 34, 0.22); } .constant-catalog { padding-left: 24px; } .constant-catalog li { margin-bottom: 6px; } .hero-facts { color: #666; font-size: 16px; margin: 16px 0 0; padding-left: 24px; } .hero-actions { margin-bottom: 8px; } .hero-actions a.btn:visited { color: #fff; } .hero-platforms { color: #666; font-size: 16px; margin-bottom: 0; } .hero-facts li { margin-bottom: 3px; } .jumbotron { margin-top: -15px; margin-bottom: 16px; padding-bottom: 16px; background-color: #fff; background-image: none; } heldercorreia-speedcrunch-e7ca37f/doc/src/_static_standalone/keypad.png000066400000000000000000000603301526573132500265140ustar00rootroot00000000000000‰PNG  IHDR㇭`ŸIDATxìÛó›+éÀñý+®ñ˵mÛZÛ¶­cÛgmÛæØˆ“™d&Æu«Þ®¤Òy{úd²™åœçù+#&‰3é˰/VÏ™ ib%ˆç ío'¿/©ŒúÍR9Pº�‰•~—dÊaPôL°^¡=…«®¹†‡‡ß5Ë–¯x×¶µò¶kéöéâ?ÿžþ>ª#¨'¨+î¾ûîËµàøø§?O=ÿ D{GÁ…¦îòiÎ6ky‡š'Z·Y“…Æñê…†®u[Ÿ§Ÿ« å Ž@�2,:‡¡U)CPÕaV0Tø‡à´Ðà§|pÒk8áí7xúá8;æéƒcnæêƒ£èˆ«Ž8{á°Ò‡†ƒí8�ÕfØ�öµ¥a_+jIÃÞ–ì!Í)Ø�v‘&’„��bÚÞ�0Ô¶*qØZgØ‚6×’l®1lª‰Šê(lP"¢9«c†„ßµ©6›ë’°¥> [R( Û3°½¹v´ôÂÎÖ>ØÕÖ»Û`Oû ìq Á'†½ÄeÁiÁ1 {”!Ø�ÕnØ¥ ÚÄNe÷av(ý¸Oý°]éÃ}Ûš{a[“akSlm4lï† lnHêÓ°IIÁ¦ºlÌIâq1lÀc³¡&ë•8¬¯ë”¬«o+Qx»R¼¥Dà­ koV„?WIøóUQú^ÚmŸö…ö‹ö“öŸ~ýVúít<èøÐñ¢cg[Ç�qÌ�döæsöËmmÿ8(äÑá,¯8láH�£ŽeùÄñ<'ˆ_œ,pŠ §-TtˆJ U�£šj¹ÕÔñV¨Ç±ÞQ8û’ëTœvÄ,ôb¢ð¹€Ò'¢…zs"Xms-ƒtß0øññ;°AÛZ~ã•ni÷¦õŠoózðo1t¢ ²Â,ŠâÊ[�D)”fiE.…„¿7†"¼­áý0?îŸ÷³»¦.üão Ö;m‘gFTW`_˜ÃƒJä©ç^†ÎTùCÃ.0ZIĬmZ'RجŒáÃñ2’! #9µ!Ì¢Ø01Ç¡Ø`Ftdqp “Ê tÜKÁÁÜ訛‚C¢ƒ‚ã’à0P06H6:Z3°·•‚#MÁ�88š ;•Âà@ÛØV…bÕ* Q-66 ØXŸ¯ ã£J…>Žá-…GÜ�: D᱅£ãÉêdÖ>»%<ˆNk{ˆÃÀÑ!$<„UtHxp|èÑ!áA8<ˆD‡¨GÈ.:HÜ áÁʤR1…‡Ú&…G­´Ïô¶P\Ñonî3‡G»9<8>´èå�÷4>Š ëèè·QJxHt,\®¢#PÒS¶ð m-»î 76�ûí7À½ÎàEþõä5èDAÔ…Â 1gÉ<©$òÄQ„·Ñ�Û ñöÈ�ûäCª¨€ó~OÑaœ³ˆ?1B}!�›o¾y �@¢½Ö�ÑÆÚIT8Æ¡}"ELÊAZ¬ÈÄ„& J½L<(:xÊa¨&ÖÑa�S~Ž…bC÷žtHt`l(ÃÃÑ •$ѱ¿�`l䂃Pp(8v7iÑ�±� ÛѶ†‘è ØPb°…¦„£C©‘È„cCD ô � cÚ‘�xl®Oå…FGs/žà1:ðd¶+ žbЭ}p†’è»�Ânâ�áa?ñh0l¶�x$G‡„ÓÃÉă£C�ˆÐ¢ƒ˜ŸÓ'<í¨6¦*<ê²á‘Q¿o[.<úé8ÑñÓÃÃ)áÁJ T†ð(c|hâ1Aöá1¾øÐÂcâ£ÚF�mtèÆ Ž8“è°  �™ó—F‡ˆ°2„mkÉUCW}´¿ú’âzí%p#ï/�ùQ' ¾ù"t¡0‹½õ"Ä• ™'5†„Åë ÂßÃ0 ± n7€üȇûäAnä@¡'àÜßþB¢ƒÑă:ãì³Ïî>ëûßÿ¾Z{qÅ&26Ì‘á`N3¸Þ/¢fΜ)–ÚHDá1-ß4fÃ#<éÈ�*ŒŽJ»è@§ ÉN:ˆwÐì:ŠÁAŽd£ƒ‚ƒ©I‡Ç‡DÉFÇÒ’iØ¥¨èÀØÛyÊÁxº�ê –Uê$:Œe =6FDYÇôèàM<�,µ˜–Y�9ñЧZt !Ña¯øe–¤Ú÷-t xÚ¡…‡ö7(uâ¡)÷² *ÛäÃCÊ4ùð—å›z˜£#š_¤ÏF¯âU·:oV¸ÇVw²¦Ï[ ñÌxº3Ò0é³pöy×…ÞKŸÑe ;Ñ‹/;‚Õ5ÐüüSЊÚÉ‹O� ¹‘÷¥§ÀÏ‚¬…_Z QCq¶ôþ‡MÛ^†�øü2ë畊þÞo#À|ÈÃûã /<m(päœý«ŸjÑAK-ÔÔji%Þ7 Íe =6�Ć)0Ü$> ž<^žw‘»Ì\ÌIbæ8¡?Hk8 ¼ôBò§A™xTšt°JT�Ñ�´à ì8F‘ààèp)Æ”ƒQttò¤£Ý°_é!<á@-h7‘èà #:dY%²´"±!6*¤U™­S"H�uê–¢ƒ—[´k„u|x„}|”v½Ò—\ìãC{½‡F¢£;ÙÎPæ ÒÅ ¦rBñ^˜2{!Ä0:�I“v%¡NÜÅþÃ÷ÒgLŒ¶µè‚ÿ@çéÓиf4¡fÖ¾=µ \È�|È�:Pð©¥Ð…ºQø©%YÚ~Ñã%wßoù|߯ð÷„Pðû‰yxûDûÓš‘ÿÀ~øïO¨EG¢Î ÞPÑÑ7EÅEE{ŽÖMŽe5á8ªt$$6HvéÄ"4¼$1 >æ'Ik¾‰”(¯�0E�+#²”“�| ޾ÎÃ|ai5âàУô¤"N¢$?<<ƒ*8Ž©à â0:DSFGnÊÁ0:öal(­{…‡šp4v¢M)C#1ÇÙŠ¶h×qP Hl˜¢ƒ‚A‘ØXob�· =W‰´É]ã�êp¹…–Zò㣣££ƒOf„/-[t‰ StØ_ß!Ña}ÇF$Ñ‘O�V®èÐÉõ–Ë,›õi‡c]ßá*kxˆ÷(>åóÊ}ûø(ïŦ§Î0ù¨ïŦ6ÑÑÍ@£7Z¢ˆÎ�݆ñVøºSðèô¹Ðï�w˜u+õl¼Ñ�ŸÑ4 _wæýçÏà;v*çÏ„jT»`Ô¡†…³ iáLhFm g€cÑ p!ò¡Ô©Lƒ[|Û]z`è�é}øþéD�‹ñ»��yÏÄíÌjC-¨ 5âþÔ¡ZTƒûçÚµþõýoiÑAzÇ«|0gÚ˜=eÌzreÎìs§­†C•nmºA86$482¬#õHšÞ$N8>bùñ!áA“�¦°ŠÂ™vTu Ó²ŠD‡r’DÇqâ!¦è8¢pp8)8ò¢ƒpð”£M¢co«PÒlDÇN™rŽ óu[I6:êÆÉE‰Ž ±©‰E•% T)Ö‘ª¬¨L<ø¿¢UxÔKxÐ m{“9ä-ˆ'É^÷É^lZÈô¿Í0:P:]¸¬‚N*–K+²¬BÜäÿÔÝuXW£Çñ^··îÞÆÝ$BÜÝ R'P·hÝÝ]_×ñî®!‹,HݽÏïþΜ=9Ós‡ aËÍ“?>;ÃÂlu¿92k‘Áa‹ŽtFÉਓTtì·|M28lÓ**8H‡Ã”Ф×rˆà�Œè ²O�ƒCF™#’Ž�ê¼/<ä›™ñP‹Uxp´C‡‡\ßá¸=³tthæ4‹±¾Ãˆ·-2:œÃ£ë�,ÝZX*èè ÷µ=õøÅúŽO�j­\Xjîhqo/‡ÇqX÷‘aòäÃÿŦ~Æ‡ŠŽeŒŽæÃŸ£¤®ÓOZ­Tl9Å{èSÜóÈÓèøøKyÎ#´£ˆÔWñæýÙgŸ Ö㢃mš§Íü¾8稡ý<37Mé©È{ä>KSéc÷¡ü±{,ÕTóø=ðPÝ÷ �š¨™Z¨ÍðâM·ª× XÇ/ð¼ýy->Íä}Rªx|�ðzTF¥�òuQ!åSíÞݘ7b�/:~”zo¾ƒÈ•·#òÊ­ˆ\»«øxÝD¬ÙÈó·!’_#BïDäò›ñÖëÛPçÍöà(ú-¸[×ç·Èdt(½�عî$¼Pl?WƒŒ×q¨»z0’"ãÛמ„çŠl£jº…Ôˆ‡‡28¨è #k;‰ÿÕÔ Ù£@i¥Fq„C²EGŽ}-‡á°d ‚}„ƒDlP ÙG9’-z-G"£ƒô´ŠEGG¬R)íS#Ft¨ØPô”ŠI…‡Š *öqˆŽ‹ÿ'r^Xj¢æ?'c}‡?ÑqÂ.:m”ŽG|˜S.…~N¹|ìé(ñ´#&µÂ²]IÓn¾ë‘n/î¼ùÎGøóåRJb,¥ˆÙ_ŠÜÊFDÞyjš:y\‚h›¨ýň&ñ;:;;-âqTr1¢’çï;É©hÀ}}ÎDÅ_þˆ¨9“°�vÌ�„Ý´—bçNDÂüIHž?i󃑵 Ù ƒ‘OÅTJåž\¾\¿ý:¬óæs˨˜ )Ÿ²)ƒ××ÛÏë&òú±ó&aÏ¼ÉØE;hûÜÉÈñ9L8ë7¿Nt¼ðä{X†Ð¹ë6?+&­Dè‚:çz¬œ¸‚_Ãù½p¬œ°/>þ6êÕ®”O}Ññ™/:Ä›n}BOº;|oÞ x!¾ÓŠ�Î/½¦»dtȸáuÃa¼¶>VßwÑÃ(at�-:>7¦ZTt§XôÚc´£TEµK…ŒŠ -·EN­äk9Ttdz¥ ï·¶à�RÕ´ Y±¡¨i�)‘S+r”CGGÜ>=ˆ¥÷Å(‡Š’±!É­¬¶à ]–OÈŽÉŒ ;Úv3<+^ÃCŽxØï á²=Ó•Ë6Zµ…¶ûÛh¿íÞ�Ã\Öw0:$Ç›†uóÆaÆ4‹~M³Èß©F<Ìm´æ�ܧYŒõ~ÆÇ °è´Qê�ø ÷�.þo±µGG:ähBÔþ2l³‰ÒŽu�¦TJJ°�±°�!�ÍXǽ8àíÀ?‹ð�$ŸDéÖÏ·¶¶ Îac|ÿo ø»ƒ¬²zÜsÉ©(ÿãïð÷iˆšˆèé�ØA»iïôÄÍ @âÌñH™9³Æ!sö8ä·B*¦RÃK—¨ë›dxðûe|žRJET@y”Ei¼F ¯•4k<âg`ߌìšÁ×E1$^cÞsO!èôÿò?:<\`óø¦'0cÈ ,˜z æŒ[‚iý&b~È•X83ÓúcþÔ«1'`¦]€Ç7< oûG]G‡åX—� Û›s‡À0èìMéØÍèx±X>f€¨à8f‡üé2:HE‡^T*w©è¨ 9Å¢¢ƒ¬à ÖŸ~‚=8šI-¥lË÷$×rd6Ú¦U$=­"£C®ãЬèHöH:8¤‹ bl(28lÑA{åÒââN©LQá¡cCO©8ņã,%:<ÌûB˜ëœï‚éwxHÎ÷îÐo¦ãÃ9:\×w¨èèÑ�Ãtt(½³¾ƒôŽ=Íâ~O³œS/Ç!>üXlê-:å&DIÖê'Ÿ|Ò*:BR £Ã‹õwŠèèdl”04ŠE�ð1%Jâç½^o·ð¹ ŒB'2:.= åú=¶MFÅÌ ÂNÚ3+{g"nv’f eÎxdÎ�,Ê›7…TL¥ƒc©ùÚ�ŸäóÊø|âÏ ˆ (�²(m.¯Çk&Q<¯¿�¯e÷ì`윌í3ƒ=còŸgtœñßþEGMÇ·¨¯©Â]«×cÌÉ|ÙD\pÆž2�büycäã pÞXë9w†]ÏÑŒ*x?ø^§©•Ïå4ÇI¯×Ø‚CÊ~ƒ!����Ly\ƒÝ^2äyz£Fž§ª„kìÓ5ÈV¡áåè…:¿î·xQŒt”ˆk‰i•k°Ë+;°~î·Øeý^>¯DgßÏ2ž«^ƒ} §"^Ÿ·b‹ý;ÏÆg`•:ÿj�ctxôÍÃttX‹IåhGQ;µÙ£Cbp28š¥\ʱF9´,ÁZÇÁè  ÛÔJ:¥5¨i•o‘bùF`lHÉ":28(ÑòÉà 9­R-ÅQ¬EGǾ*T!í%=Ò¡¢ƒÌè°þT­bC³m“ÕAq´ðPß+’øXE‡^;Ðå‚Å^˜fq¹w‡’p,Ûh]×w¸Ü¿ƒÌèpßF«¦XzaG‹óVZ÷…¥—‡ù'ÔŽ—Fé¸Ç‡»\>þúgFÇzÕ´3*E“x3mkkë>—?S®0:ø5™#&$¢#â®ûq é°5 ²MHt˜ˆŸ¯­­íñÜm —De•7àî>g¡âoFôüD/ ÁŽ…S°“ö.š‚ØÅS�@I”J™”M¹K§ pYŠ—‡ tùdÅ|]Öñ+W:ž/ãó…RþŽ"*X6y”µd 2(•’)žbi¯»‹¯i'ÅPá«Ï!謓uthÝ�OëǨ/MÅ ó—bô)ƒÔw*.ƨÿ€ÀËCÀðý›êÂóAõßý9wš+RÑÔñ‰ózj—ë+äzƒå`t¨ÐÐÇ|£®:$�öÁ‹%|\ò[õ V�Ô0^äsx^>OËPPqbR±¢ÃÆë2¢D@UŠÈàë©T��Q�¶/DtÈ8J‹J9Ý´’ÍQuj]‡±}VE‡ºC©-:Š­èøYN­H2:HO«¨àP8Â!428,"8¤ J·0:ê¿“#B�¶_E‡ç$y¾–j ":Hj”Ãr$ŸÅiJŒzpã°~ÑioÇG‹_ña†éèÓyeµH,lÆû¹�®b•¯¶Áê°�^ÏÐ[fõTˆº–¾žSH BŸ�×aÑÞ`{ìpœaÿk]›�2FÆv[t4òx�Ÿ*°m—ýègT­îÑÑi»G‡ ÁšV±èØ�dtP¶åG�ÁA�?"“2‚ŠŽ´ª×Rê::äÑ–ƒZ¼í8ÀèTt?¹U3‚CØ«¦THE‡¦¢CÚI®áqä ͆.¢ƒœ¶g:‡G÷·gú¿¾#QrÅœfQÑáº�VídÑdtcx¸o£•üÿ(|÷†3×wð¯Óå>+ÆúŽ(>È�ø0ô`äÃåî¦=½¿‡cxÈ?ˆä¢ÎU×܈‡ž~4ø-¼‡¿Ñ¸‘Ai<ªo´Ãê±q޶>ò"?ðí>þÚâ5u*_uÁü<ó{úÜ3“Fá°§u±{Ð@ÞØÝhŒ“š©%nZ¤Ž¤]–Ãô�χJ²> NɺF[â´ÅóºÔ¤$Ç£hßüåÕ×°pø`xšó}ì§žGGUmÿB¯ÂæE—bø^ˆé¿¹³O½Ág÷Å´ap5WÁF^½×/¾ S†r�éÙ±uq´&]ƒºÆš.n&µ™w#õ�z„2øø¸iïšßw'mýÌGm•%õ�pêVèÖ(ÇG¾à *TzÈa”ƒòÉŠŽIGŽÒ,164#:Òi ‚ �ÔzIEÇ~¡ö;$“åÐ-娑Ì航_�}j…Ž»,:8\££XSÑa¾y¹Ç‡æ4K× ex¸lÏôûóYŒQ·-q3:Ü×wèèк·�öSÅ úµ££‹i×�Á7ÃÃÿõ'Ôº¿âÃß�.þÇGyûwÖ§²¾ù÷XÜ´åQ±°ÔAÄQ-׬ç/·Yf<^±özË×^‡´Ü´ÆÍµÝríÀ‹°¤Ÿ¶´? ¸Ë\‚å/ÅŠA—båà˰rh¬Ú¡Ãhx„�è�5#`ÍÈ�>ƒ°–ÖØ�Ò�W;œ ó åϯ1+‡ÀŠaý±œ×YFK÷Á’A—cÑÀ˰�¯GX?v0^¾v Zx[úšÎoehô$:ª)½¼•;– û­aزànIt|–—µù¼›k�gÕu÷<ö|–K*™I5áÏp§u=å°Áyp 6ÁqÒ·a±7£#Žësb834÷VÌv 8@ïåèS¸§CâC/­t1�=Œ†‡��óó:(âgÐ)ѳÌâïð£#aêpã#ú´ÒˆýÏâöw¨øH_f‰|�–qwΊ óïÀ�ޝ?>(=>Ò÷{TØ’±æb7îßàrŠÜ,«–Têm•Zæ1—UÄå°,€à óà˜Gp@0Gˆ™p˜e‰ŽLßô+Áè`píé(˜v\‰‚áÑÒÑ�‰„ý ÷5Úê÷³¤GT?8ÌßTê¾F듟îà°øS©˜å0æß“_ÙÒË"$Ä$ÆÇ͆Ežhj҇�8*<€Ñ¡1:üðxcÂCÿª…üVxÄÆÇÆØèH ?:Úh’ò»BÄtá¼æÞ^uÏé,ÑÓŽe�~°÷Ðâa¹ë@Ì—˜S§�r³(cc¾¥’i18ø?Bƒo«¬›é†r/Ãà;å¸Eˆ µ¬Â½Ú™p <ý3Ôyp¼’½ÔEÑq‰ltØðÈ`&:¢_Ë$?<üøp—Yœðp¦Éû;Òó££ú2 ø¯Ñ2>>ÞÁa…�È©÷w8§•Jx¸“)Ÿ{|$L?):>ª¿f»B=žz؉‡7õØ8'<¼è D 4tt1:†‰bt�àGÅEÙè ¸è ':ܨةÀð0ñÁɇ†åeA‰èW7ïb”›µö‹Íh{¼®^_ä|;Lldêf¡—TV¹‡#Ãà <6â¶Šµ¤²�æå,«p/ô3<?»‰ 6:ø3ÑÁð Þ›þATÎè¾ztøŸÙýþ2 øÑ‘°¿ãH0:À?»¼×hýð€²è(¿¢£ÄƒÃüÍ¿Îk´jâáŸßA‹ÚW´ô²ØûøHÞïQñP±êS�ÓbÝáÑp¦uÀCÞ‰ŽÚŠ �Í�x�´QÑá°ÑAÇ;Äð i�‡/? >´s´ßm6ÁL™=Mk»bÊp6æJdìp¿†Š ž2ªþƬ‹‡ Ó�®ÿ!ïå –T´ÔYN¡ÜÇA\VQƒ™z#iŸ‰EEFö/H…‡‰†Ç¨ŽŽø#·)1:ÈÙ?`Ïï`xT¸ŸeÁJ?ÃþB 6:Êöw\)».&:âƒä_.g*å¿îl7§\ ÷=>(>>Ò–\üøà�£áá!7Ú¾¯¥Ã±!ázÊ¡ÃC¬v/³Ôlx02 ƒ¡9ñ „ýé�êѱc¥,¹è1ßïwL—±ýS†‚Ï�² c\Û> c¹Ós£´%Z° ±ê ùœCt 6‡¸ çK*7”Ç‘^Z‘àÈ b?£8防¬B:>®LJpPatÀXN‚øà¢´èˆßßáL<Ü7%üƒÃ"^ÏìýÁaþþŽÒó;ÀF‡³ÄâžVqpXo¢#aŽYëIt|þ§�.ún*=ßä¢ÄGÃ�wÚa–WTxØÍ¤GŒ¢f7–z*‡'Ôƒe'>ªGÇŽ#qÏG›öºMzhü(ˆÕ.cÃ!"$`̵¶ÎÂHNÝ—B¬fP±QUë�@Çq9ŸAþíĆ"Áq’݉5å`tˆ¡œŠ˜™~ÀèÈqyE¢C˜ð˜ÈÉ,Tt¹÷|ÄŸ|©}ÐÄ£Qv? ÃÃìï`xðaÖ³‹áà¨Âk´\f‰}£E-±PÙm´wpXÂI¥–�C¢z�Ö†‡³ÌâöÕLJ �äøèÉ~Ô 3ñ0S|ï…' ÂƒL|¬vO=Š6’Ú)HÝQ:ñ€JÑAGÀèH ?:vºí¼< û¯ÒíU°ÿ±½,·i×zA§¹e»ÄÖón›Ž xVl½ÈÓÓ°öô¤Û““°Z`¥ËqX9ìXþ…�»lŽgâ®�ôÌ$ d!´øúy½Ì�ÔÞXžÌ13ó2333„ûFvO¦#Û'öÕ�«þ/~u–,ËR·ÊÓGëj«xàžìmÅ}ÏÐdo*îy=w¥×Aw<¾Wqôû^Nv[ÕäŽáyø=v=þ½}ðÞüýs|ʱ+ÅÖê(K`”ùs>t¸9{PÖÅÍ™$ó% V(¹»£çNÍ×íx”UòÄëáõY¼¿`žd®dÜ—u“izjuE{ÃsW·ïE„—®ž(ã÷¾áòz´4_”‘ .Æ×AÃÌ홹î W±�–öÏëëxEGHÁñî§ßÑ¢ÿ¯˜RëÇßÈÂ#~Ññ¶oÜ›`|œ¦dëûO=.>›aÑ1:6®/üßyÌ èèU �ŒÉ¢Ãš~ÑÑÝ7¬•E‡ï¹/vÑÑÑ=¤tŠ¡/nÑñòm¿  §o8yÑñìußÔ>YNƶœ>àþDN¾Cµf.m:ÉíÿÄ7Ôd÷$4}1Ž×úo®ûƒÅ†j·^Æ~ñ7U/åÿüê/w.9FŒ[·„ïɵ$#Ö î-·®™ÇÉgü¸˜²ºÏ“®‡ã$ö^X"æUâűß]ÇÏF��±Ætσ£5nÌÄ:õ\ë9 ;_éŸ�˜yßS�ÇÉ=dÈ«¶ŠŽë÷:b8G«ù£¾ Pîûœ˜Ù´úon–Rný9ﯦþsù¼Óç>Ï×rî¿›)çÜóŸç¹ÌRÚc¯ã¹ÏXϯëg“‘ë ½N¿ËÆÑ^ï©‹wœØs_žçræU¤~œ~¥­æZω{¾Ò>.=á{Ê7Ó¯�³ �¯ÛDÑ1<³¢ãÆýÎø´PÎ~ø[+×Fªÿb¢?·þ¼|Nö±/üó�òý¥´W¼ko=¿GŽ»ï¶Ðæ²ëÉ·ÐoÁqÊuRî»ÏÓê|Ø¾ÕØó³6~¥±­as©Ò?zþD[½§ç$ô|¥6âæAß“<ÛÙñº=fÑÑ?Bt5¢è¸õ sZ~ß0Ûû°ÞâBaŸ6ÎZXŒêû‚šÙ´æ@gè\ûêCÆ=pÛ hsÙõÔ´ÐïÁqÊuZÎÓššÒœEg Z¼Üg”ÆzÏÚviœÜ�.ùyÐc¬´µ{ZN´3—þÙÐó íIæH® Þ$):ÞpÑqûa—®ØBk–Ûhm�¡ü† ¥ë/i¡áëˆgí�ßwûøùÙ<·?×Â"�;ØBy³”öÛk9.ÐNB™K®‡×läZC¯SÃïscë¼×½/ã[Ã1æö†¥r¬.ùyÐc¬¶Õ{JNô3—þÙÐó Ž‘g;CÞv N¿è¸j‰¢ãîãž)|Muò7~]¹wxåÝ{ï-ã¶µŒ v\°�ç�Kë‡Ì%úyœÒN@î�å7]¤»•5sß~gðý…F'.‰q,äÕx9ïwŸuÛº´ÏÇHiË})¹Vr~¾PΙ’}Ou�s'ÆÔ½gû³ ­sÈ):XTÑa¹EÇý'=ÙpÄþØ/£Öª_ë×ToæÒú#ÙŽ7@{W¥è8ÿlØs�Å.:<íÍ€b£!S»ƒTýZý¢cÑlÇ •¢ãá³¾ ¸Ljͤ?~½˜‰uC ¶è8šíøttóƒÞ=JçŸÚ¢ƒýÃÞ�€ØYÞ‹—íÿ—  %·€P.—¶ ”BdHé%€, S¼-”BYÅ¥`)‹P„ a¿Ð›.jj´Í½^�½6j4&N2‰IÕ,³&™}yîûôÌ/žÉœ‡3ï¼ó&'Ã'ðaÌ9çÍyG–óå÷<ï{êDǧŸÏP”S·¢c©ŠŽ…Ê–¢c6(ÚYÍèøÓ_þÚÀúèåèH'×DtüÛ?ýK_µ¢ã¤èÚŽŽ“ £—#:º´€èx·å�¤¢h²¼r¢ÍèDGû“@t\À�ŠŽÐ~t®^Ù®èxúxê÷çÂK�¶ô‹=—ÞÞðn£éå‡ãùÁ¢ãêj—�ŒŽxßïÙ>ó5¢£Î¤ãØsÍNrhWzçð}éÀÐ&'…¸xü¥Q��€ûtÌg}¢ãJÐèèóžÏ3툎ÐOÇÉ{4:bÚñöÓñÜy®^ɱѱáæ`sUt|te5‹ðäå•BX<š^ÉÏOÏÇcwˆŽ,GG¥gt4¿z%öT´ñ¾ÝïeÊ1ˆ­^2û*ZˆŽÂ%³&ƒÑfEGÙóÇJ�Ýé@ïÔ²+ý¸°o#¢&Ä%³Ñ1½”N\šïÖVt®"i1])„Ea¿Ç]6’žè(o$ c ¢£°É´ÁòJÄLLPú¼ïÈÁôxz& :®EtÜ �…BttŸÐèh°[]gb'EGáX …èÈÁñEèg":vÀòJ\½rçÂDGöÑš¹Û£cdlµá±¢£p¯�džZ;O7—ÒG_tEǽ¢c¼Š�.½¼Ò`Úa3)´c�èøÒåBttÀ£c¡2ŸNU?³ Ñqv|5DtìÀûtX^€¶£ãÔå…”}ÜÑ#:&VS6’Ý‹Ñ1t¨pilGñx …èë£c9¥s9:²ñŽÉÁ¹ zÁ¡4Tëõ$@[Ñ1^EÇÇ·O:–ÖGGÇ=áÉôX¯×>ód~h;:f–Óé+‹k²õÑ“ŽììšÉ¹&ÑˆŽ¬ÇòÊhŽŽ°ÅèDÇ™+‹Ý “Ñ4ˆŽ‰W×鎎˜td¢hŸÜóÝѱPEÇùÉ*:²‰Ž©-E :–*‹))EG­l%:Ñ12¶”F®e‹Y9:‚èêFÇdg¯-uéªÐÈÎçŸ[‰@tÌ.§scKÝ6FǧSUlt™@íèXI£cË•¥4:^)EG·éyÑÔ‹Ž©*:Î�/g9:ªŸ=¢ãb§+SÙÖ¢þË�Ÿ•…Û£ãRábEtu£cz®ŠŽ‰¥Êre)«:£WtLuäÿ¾¾…èDǧ�ØÈ?+Ë=¢cjå–‹•éùÑÔŒŽåް>:«èøûZp„ë[ˆ@t\\‹�‹YÏè˜^ùÒ£°¼rqré–K• ÑñÙôJÈá!:€ÚÑ‘ûáÒÔrŽ�Ž©RtÑ4ˆŽ¿gUpd‹·GÇç×W:Ö¢ã†èjFÇ�ùÜËS˽£ã‹*8Âç•­D :>Ÿ^îVŒŽ :€¢c%¥Ë7VnÉÑqSt5£ãæ|îˆå/ÝKUt\Y ŽpsAtõ£ãòõuzGG·ÑÔŒŽÜ—»zâreIt-Ddž¦È�±.:®Þ\M×*WgªŸ•™…UÑÔŒŽÕÜ_vE¥Gt¬tÙÒ¤0éØÐ¢ãšèšGGnŠ.…èè&:Ñ ft,V1óeOŒÍôˆŽ±üD6Ó1»(:€zÑ‘û!wÄxè¢hãu¢c\t-EGד[‹@tÌUý01»Ö³�ÿ^^«¢Ø®è£#ÿe¢ ��_0×vtìùZ:røþôžÍó½ïÿ&yá?+ûÓ�Z8'~�~™ÿÿfÃ?ØÂñˆŽÕ49»Þrãå•§�§~.¼ôh×1»Ó�ûÒ�×ý½;:H/üª!Ùwö׎GÓË#)¥‘ƒéñxl�yþXêñg4½üp~¾%q~ëÿ”ηÁ¹>”~þÓNxüò;õÏÑ11»ÞºèX\Yí|¥ýõåt¥RþjûÑ1´+½sø¾”~`}tÄsñ÷âáoÒÏ¿Ùy¬Ô‹Žò1ý?øË¡µ]žKoÞ¯ Îõ›?IN”ðÝ+aÝFÒ™ªJþöÙbe)½[É?¯ÜXÞ\t{n Ë*90Ö;0ÔY¥0ò/GPÄ–Ž)GG¯ëÇ_­5ñˆÐ:0´ùèxûéRXÄy78×Âÿóƒß(€¾Ñ‘¿äíƒËÙJçgev©+:¦çWÓ[ŸÌ§?�,¤·*©|:ÑNt„}Ã÷w‚ãÙÝÅצíGGƒå�ÑÑp r<=ßè\›O;—¦VÒÛç+:þ·rc¡;:æVÓ›gæÓ›Ÿ,tœYH&–ZˆŽjI%‡F/±ß£°—£ÖÆÆ‡¦ å€(Ó<:âÿyt4ˆÆçú£áz{;«èøŸÑ5ç;®¯�Ž•tìÑQ©‚#;¿ÝÑ1´+öslØHZøŽ1|ð ptćx,g Ƥ£Á¹FðÕ^b@tü÷f¢#{ótçç&££Ï¦Ææ—Ìþh8–V-:âûü{·ýã¯Ñ¹ÆËO’¾·és@tDx¢ã�Ós�ð8�5ˆŽò•5£#ösľ‚�Ž8¶½è(L9""Z8׸o‡è`KÑ‘¢ã��+§ç³btô¿ô´Ñ}+Êzƒ…+BâøMîc©±¿¥é’Nù\[ˆ>DGÑ1ßS9:Nͦ?åèÈDG„G|îÜè(ÿÞo?ÝRt”ƒ£Á¹¶ˆŽÑ“Žãmí3ØQÑ„�fË+mGù\Û�DÇTWt„ˆŽÖ?|kŒ÷EG!8Z;×ÚÑ@põJ9:ŽžšÍªà¨~VÑ1ºåèˆÆÝ÷7øW¯4ÿ½›GGl-‡Bãsuõ -L:ÊÑQ)DGÃÛr×7p÷éxúxl�mø{—££|n…Hhá\ݧ£u¢#/«íˆèhød ”ïHZÿÞ¸yVÓcâõM~ïrt4øÝRì¡ÙŽsuGÒöˆŽ×+GO­EÇX9:ÊáÑ|óhƒï^i?:ÿÞíGGƒsm¾´€è˜ì98²�Rt´¯ÿ·Ì¶ß2 @ƒè87˜ÑÑ|ÚAwófeƒ±·Ãá� ¼F{9Y9:"8ÂèØâ EGŒüÛ â¾ —²¡á\£èDGÖ':^À£ãø@E :^@£èÈúDÇk¢h¡¯mWt¢#Üsѱgzâ•é©.O ï-¼þÉôX¼î–£ißžü\ÉÞ´ïÅÛŽyqz0žvft”c Ot ŠçûSŽ”r¬;#:ÊÁq( õ{}އB\<8|´CϬŸl”vdtD(”?ô SŽgžÜø\DDw�D¨¢&žÛ¹ÓåüÑóØPÃc€åè*…Hˆ¥š˜htGEL?ÊçQ|¾} :ö ߟÞ9|ßæ=»;WVˆ�øïÐ?º7�–'åÇËñìÌè(*ìõ(\�ŽÂ>�ÁŒí‹ˆX(ß³£p•J<Þ ñøÝ�s}c ¦åýåýwiyDÇ©¹l0–WÊ1P¸Ô5B%öqôI@tôÿ°�%–ˆ¸:%¢£ß15.™½;Ñ¢£}…=…X(Üü«|LibÊ!4�ŽðÑ\!:`3iÄCéF_ÅcÜ} :¹±¥»å/b+L4"|ሎßÁR�ÂÒLŸûtøj{€è€è‚èx½ýèDǪèD°³¢#´€è˜Ï"Þt{®øš}Ã÷w‚ãÙÝùïÀNˆŽ©v££0åM/?ÜõxìãÈ¡ÑSì÷èö@zèÿ/ýûÁÿßÃWÓw{½ÿ·¾žö¬ŽùÅ×Ó·«¿û‡_YwÜÞ>P<÷ïþ¬Ç{ýìñüÑû=6N9†vÅ~ŽžIãùC…è(xä‘Rt|¥ó3^[�8&žüðÑñ\z;Å”£ÕKfc‚�B@|%=ô­�ÇÄ”¤kÂÑ3FâÑ5¢c4k': SŽv£#¦ ¥å•ò1åÇ€†ÑšDGó)GÃÉÆõ£#–e6îåˆ Ð,:B Ññü±Tžr4AšEGü{}ötÄ¿1 @t<|0]ˆ›�µ5ÝøÙ7š.¯”£#<òÕ>Oï*1å¸ðÒ£ÍOº¼Ò~t„òÆÓö€èhÊQŽŠö¢£Á9´DG SŽr ÄÒJaF£èˆ°ˆ%”ÂrË]œt€èˆÛ�·0åè³Á3bco£IGƒ�µDGùvç]SŽ–|#=ÒÛ¸¼R�˜p€èe€èD€èD :D :Ñ :ÑÑ܃ÃGÓS¯œHO½¸?=Xçõ}JC¥gÏþôÄm¯bxoá=÷¦}/v¿¶|®0¨DÇСø o1:ÊÑ?:žL�ÿý£ißžx (ÑÓ†¦9:JÁÏõ1ôÌús+?ƒGtÄ!>ü#>â|»¦'ϬDG!" Qïߊ½å()?e¢cßðýé�Ã÷mÞ³»óqÍ>ÈEGišQ|ßøï�טdC€èˆ鈋rt4Ÿr”Ÿ+*o >Ë+åM™M££ÎÆÎˆ>ïÑq/@tÄ{Å0(‹@(@�€ˆð±¼Àà³¼Òvt”ÿíòqå€(Obl$`ðˆŽš/¯Ä#>üëBáú_2+:–WZˆŽò”£þë �Qš~”ï;€èh2åè¿™4‚cãò‹Û €èˆXˆˆ¨u…‹/|ÑQûvç õïçQŽ_mß>D€èD :D :Ñ :Ñ”‰Ñˆ@tˆ@t¢@t¢(¢€è€èD€èD :D :Ñ :шш@tˆ@t¢@t¢+UhÌ‰ŽºÑˆ@td¢¶HtLV¡qnsÑDGm :>ÝLt¼V…F&:2@t¢9·œÃ#”£#ˆØÑqv9ÂCtÜÓ@t¢c9¢£²Éè8':êÑ1±œþ|v)‡Gćè€í':.äèYŠð÷4€èXJo�,v…GŽŽUÑÛKtœ¯¢ãÍO«ðXŠð-Ñ1^EÇ™…ôV„GÓ¢£ :Ž�™ÏÓŽXf-Ñqz¾ �…NxˆŽV€è[Lo|<—Ã#–YzDÇG³¢££UtüéãÙôÆé[á!:Ú¢c!=5óexœ™OÓs¢¶™è8wm!½þÑÍ®ð(DG‡è€­óéµo¬…ÇlÞßQŠŽ :`‹DÇÉkáQM;ªð˜ž[°½DÇÙ«óéÕ®çðH¯ØYf™mÑñǦӫ'¯Ç´£áÜØ¢è¨DÇHxª+š=ôÛÓ{„ŽË_éS踼¼”ííí>3+ƒ� 0(³¨y:hþ= ÇdA–ÚõÙAÓ;tO“%)$ÛŽƒ³‘ôÓ`© É“RXŠgÞÚ‰Ûërp6lOöÓ²^uî+짷бµµÕW?è¦Îäè"j¾1Í»§ájðàqTž‹£IÃ1)£‹ôÓ7ô¤'=ý³8*Éä¨,²Ÿ}÷ÔбˆÐÑ<^\ÿã·‡Ž‹‹ ÙÜÜ xè Ñ“žô¤'=éé=5tüüZ¿¿Dðh‡‡Ð�¿ŸÿìÙ3Áo${úôi°àþáxÑ“žô¤'=éé=5tÜô/tLMMÉ£G�äùóçH:Á‚û‡|àEOzÒ“žô¤§ ôô:@¹\FÂÁG+Á‚û‡‡:Ñ“žô¤'=éé=ÍÐÑ ¡ƒB!Ä:þøý•ÀÐA!„O¡cçª<C!„B<„Ž¿uBh‡Ž— „Bñ:C!„B<„Ž“YÚ¹Fðî¡czzZ …BÐß¾ÅýÃC�èIOzÒ“žôt�ž:Z²ôÃu;x‡ÐñÍÔ”ÌÌÌÈáá¡ÜÞÞ îð�=éIOzÒ“žÐóþ¡ãö“~#éÑÑ‘ÜÜÜÈùùy°àþáxÑ“žô¤'=éé==„|´‚¤ã_Ì?ð€¼èIOzÒ“žôtƒž:þôÃK ÿø„ÐÑjµäìì,tࡃFOzÒ“žô¤§ô4C°„ŽspßÐ�ãбLzÚ '=éIOzÒÓ=t€{†ŽÓÓS�<‘‡‰„$î�ò†—÷±LžOÂé ”e#xOƒ�² žå�úézÒ“ž¡BO3tìj莡_"999ñÆÂHïC*#“ë~Þ:hþ=M·Yðàäàé×5ZOƒX=×'%c„G]›Qyšówd�ó6OÌß̤¬Çíé>îžfèP,¡Ü#tàïéû`­”sc+­yy/ËäðçYË«W^jökÃõµ¼Ñ¿ø< à âô\+I&S’5£•§13¥5ìGø�§oèIO3t¼ú•{†ðÓñ+kè8>>î?Í’dÚä‡>´šx½ïX&‡?Ï·B‡ýÚ€=›RÊ´=3%iFê©Àó»ï¾ÓС5�'Ö¦ö2î~®˜Ë؃ÂölvöSŸ®g©½'�|ͼ^×pPý|÷þµ§ç/ØO‡¾és¤&ùD¯“÷1°‡Ž_ZRß}<ÜCÇõõµô™U™HcÒ2±z «i †žãš¾sÐ|{VsÚhƒ\¯GâY•œé×!'ÕH<Ó±—hi»›yº(�Ð=M§áJ»Þ�b50,•û 7¥S�Å=µÍÏû�§¹&u¯1{Ú9¯È°®Ó ûiÜ¿ºY�¿¼§sß>ï|#ðÔõˆ½Åè¥þü`�+’½›ËY©×OãþïëüÅ=úöyÇà~¡ô#t\]]Éîînߘׇ®�ì<®í'ðÐA³yzgy<ÕöLÉøònžó’}_ßæ»¡#5¾M?áóí·ßª›Öô8ÏåqI¥ÆeÙrM„ë3O£wºßàܨëu¨g;ësYÆSØ—êçûîÿ_àfqþ²ýtè›:&$;ï:îž:þþKK–|-õ;4tü¿:6?-tìììx¥>Ö}�Õý¼‡9hÞ=ëc24V7ë27O0$sÁ{‚ºŒ¥ÚN©1©[z´§Ü€Y�Ás7?ÅìcžÂöÔ=¤††$…u‰žêú�ó9êésj¬X?ß½¸Ù�¿T?úfYŸCsþÇೆŽËËKÙÞÞöÊR!Ù°¤–ü¼<ÌAóê¹T�$œg»µÙÁÎÄH–‚÷4]á58‹Ú’’8Wÿ<½COzÒ3èiÀ=tlmmyeq´:Fý¼‡}røñ|üN&ê‹§òX®ÉÑÅè<ýCOzÒ3èi„Poó¾Ð¡|4t\\\ÈææfèÀC�žôt„žô¤'=éÙ {Ê{CÇøhèÀßÏöì~#™<}ú4Tpÿð€¼èIO'èIOzÒ“ž:neyïÁ¸…Ž©©)yôè‘<þI'Tpÿð€¼èIOGèIOzÒ“ž:V>%t€ÞÐaR.—‘pðÑJ¨àþá¡Nô¤§ô¤'=éIO#tkèP:ŽÌÐA!„b`À:C!„ò[aè>Î^1tø€BaèØ¿<:ú!„ÂÐñ¿w¡£¥Áƒ¡Ã„BCG£:€c蘞ž–B¡ò·oqÿðP'zÒÓzÒ“žô¤§†ŽÓ>†Žo¦¦dffFåöö6Tpÿð€¼èIO'èIOzÒ“žBþÿÜ££#¹¹¹‘óóóPÁýÃ>ð¢'=¡'=éIOzvBÇO-�vøhýöÐ��V�t¼‹ùð�=éé=éIOzÒÓ<\CG«Õ’³³³Ð�‡=éé=éIOzÒSCÇ?¤ñ“à:p:Æ ÑÓzÒ“žô¤'=5tüw¿CÇéé©'žÈÃDBàáÔ¼aŸž<7Ê27ƒ‡OâòÜ(˜Ž@ÊQyÚ‰ÕsCÊ‘®Oðä¡$RÞˆ­Ÿþ¡'=½„|‰ää䤿,Œ¼û�YÀkÞ€‡9h¾=Fà6" Z[Ÿ”LÛ73¹‰ç‚ŒÀ)3)놧ö5POw"ð\ŸÌ ‡q{.Œèü�ÅÓ?ô¤§:@ô!tàïé{¢&y}8åk¨yÃ>9üxÖòy©½U[“R¦í›)ÉZ žèa§w¦'ÀèéNžXŸ)­Åí©ó5_‹ÃÓ?ô¤§:nßЯÐq||쉷BjÞ°OßžJóí‡qäž®šÑzšDæYËkÿ¢öÍRF2¥f”žºÏvüš%É L6ö4ž _S7c�m÷5÷=ɇ§qÚ¸dJRʫ˜ý�Ãç ×××rppà‰ªä rUÔ|4gOw_�“j¬žÕ\gbçª1÷Ó$.ÏÕ‰´¤'Vãõ4çl®¯çꄤïöœU™H§eb5tOx˜û ö×n ó=UwÝo«9ÿŽ=u.â¾ÕÇtö?vOß¡cßÖ‡ðp5oØ'‡_O¥2 WÓ7φÓêÒRlÄÓÏF1 /;é¢4÷4�ÓņžÇ½>EI£ñzêÖž†í©ý²Õpž–Š>gpüe=í>æ^bøXœ½�ç„pn†ŽÿÄб··ç‰Šdu�³Ô¼ašOƒJöíòJ¤žF_±xV¢õ4‰Ëså.t¬èyüë3[‰ÙS÷ ô4|Ï•7Ö[ 牬TÌ} µ/àiuÑgB¯‡ácqö=÷ Šc踺º’ÝÝ]OÌ÷„ŽyÔ|ëäðê¹<.)8¶ÉÎGèi°<žjû¦d|9^O“¨<ç³’H�Ëräž:_SãË{b¯ÍÊ<~êš ÚsYÆSæ^ 7Ôº=Åsûo¶Ó[üw.þ<ñ|Ðu¦÷�s£n:û»§×б³³ã‰9Ò‡ñÐjÞ°O�žõ±·ÇÐÜN\žsC’«›u©�uCÇX=@Ow"ðÄúDÿb÷¬ËX k3VOô±ë‡5›H É\˜ž–½Õ¨ÁÑxÎìW¿7Ϲ¡žû’TjLêpÁÏ{8û‡Ï:.//e{{Û³2¨ƒ08‹š7àašwÏ¥‚${š<8Û®Çä9;höO½µ”§Qz.’èaÜž˜ÃÉ‚,EÞOèIOÇÐñç3壡ckk«¿<~ðá/ã%Ge×ôsÐü{.ÊhÒp3HŽ.Fíùà±qmО6"öÔþ>x¡§îEI]Œ¿Ÿ.Гžî¡CùH踸¸�ÍÍÍÐ�‡=éyèIOzÒ“ž®¡ãè�ý„üýügÏž ~#ÙÓ§OC÷ø¨=éyèIOzÒ“žÎ¡Cù`蘚š’G�ÉóçÏ‘t‚÷øÀ‹žô¤'=éIOèé!t€r¹Œ„ƒ�V‚÷u¢'=éIOzÒÓzz„B! _B!„¡ã'†Ž{C!„†B!„0tB!„¡ãVÊ;¡ãêÓBÇôô´ … ¿}‹û‡‡:Ñ“žô¤'=éé=5tür+�ý–4~j¹‡Žo¦¦dffFåöö6Xpÿð€¼èIOzÒ“žnГžÈ ÿ5t¬ìßô‡Ð�ÿ?÷èèHnnnäüü:ðÑ ’Ž1ÿÀ>ð¢'=éIOzÒÓ z"7üí—–,ï½n�…ާ/Þp�ÐÑjµäìì,xࡃFOzÒ“žô¤§ôÔÐqÒ’å_#xè§–Ðî:p:Æ Ñ“žô¤'=éé=5tÔw_!xè?³ØCøXè8==í?OJ"‘x‹‡OðšÌA³{† =éIOzÒÓ?ôÔÐq#Ú})õ5x8†|‰ää䤯¬OfÚAcDîj 2Ò™Éu\ÓoࡃæÁÓ�ð<é©óó76Ou3ýÖ'%ƒóû©n\Ÿay¢o™IY�ÝÓ}¼y"7üõçYúáº<ö^ß#tüŸ=tàïé÷�šäuSË×:õZ5�—jýÅ4žæIO�Ø«±yÖòX—�5™)­uŽóµHû¹V’L¦$k\ŸayjßÂö b>:v®e釗úÏ,î¡ãøø¸4K’ÑO5JÍN½YÒO?2Rj¢ÖWŒAóàé@Оµ<úf'_‹¬Ÿ=¡#Â~j¿jùöm¾ÙÔšÑx˜~Á{b~¶{§~ƾ¾gSJ™Î×î3¨o»·¥¼Öžžö{×½F{ÛëòYÆÁ:Ž_Ë¿¿BðÐO;ÜBÇõõµô�j®#�žX}o=WE­¯ÀC̓§zÒ³*¹»¹š“jtž«2‘†[ׯšÃšŒ¸Ÿ«’NOÈjLóNwýC?Ó2±jÎ]\–§½oxžäªíqhÏ_­»÷Ú“§ýÞumê¹ÿq°{jè88~-‹Û—�f9{é:ö÷÷ûGe¸3ч+öz?1Íî.ôôãYÖÍÙÂp%¾~6Š’N¥±_‘áŽë°Tbò„#›·�bZЯt±çúÔ¹Ù{Þ»ñšy�žqϲw¨mÃPÞ‘¬œ%µnÒ`çm±ñ!Ö¶Û·°›™�íÛÒ:é0Þ�ãß”—‘…EˆäUÀOäúÞ{’~`ÈÂÜäá°éØÒãs»3MgŸW«á¶ãqÞžn:꺶¯ÛñÞ5üøÿ[Kš#Nèéš‚Ž1 ë'ÄrryNÏé9=§çË Óa¾áfn;îë×Îx¬ÞÞ›Ž7ó•ÙãMGÛ¶TUÕ¥Ëp iî9ozƒ5¾‘Àéëé9=§çôœžóO{w äÈ…qÜLy™!5c›™S³�˜òp!1¤ÇÌÌÌ™A°ÌÌ4ÚÛk¯O_ë¤VWK7£×}[õ[½Ã½¨èðZâ /�>f1£ã€ÃèÀãç�ŒŒÈ{$óz½u —s`ÌÅ99§{œ“srNÎÉ9Ut„Ä~Ï‚�PÂ]t477‹¿þúKŒ��¡tê.?æÀ<˜‹srNÎÉ99'çt‹sšÑ±ß› Ÿ%¯ßa匰‰hllDá`µR¯pù1‡š‹srN·8'ç䜜“sªè˜ ‰}žùáa!ŸXÊ\Ê€!š2›ÒŸSDêË6cê•Â)ÓvB)S¦[A Áq±;€èÈ„ 3dt¼öÚkbõÆmâBϲê–,Ã×ÙÃÏÀÏ+DS‹�%q¨X­°ìØá6Ú:í¡òêìhF¤`–ŽØ)î÷?ÃxŽAgD:ÞQqºcÒɈ‹SЛ-!NC¬ˆ37Ó_:g«ì\9 TÞù[Ì9§ú¿× õ{“z[×—gúâºÞ¸8-Å”ž˜8¥‰ŠSݺ“Ýq²+"NHaq¢S9.…ð°ïòQX�µëð iGÛ$Åut¨ð°‰�YÝ�÷÷M‡:ã­·ÞºpÛï¿ÿþVk“â g³€Šð_k«Î¢CÅGI£ÊP½è '(ep€¹í€ÝÑLtÀ)ÉmtÔK|0:€èÐ#$'DGÞðˆå 0¢CcF‡*:`Y1£CgDGZé¢öBáñïÐúG+_|ñÅ}·áé§Ÿ~j|è±§ä°ñ¸ØLLJ û¡V£jì˜å0ÔÔÆÜDã£ÑeÛvÀq0¶ÆÆÃ›ø¨³ðà1 ÃÃTžè€Ñ‘†ð=:”ÜÑ¡ÑZ|˜G, ¢$=<À}tœé°pýÙè‹?üð�ä’ãvMMMw'Ããl<°Y½anÑ’_СP-[©¨@¡Âµêš T‹¿w‹Ù"vDE]%ªŠk†E·Âù¬N„n&‘a"h'nXp�žÀ†Áqç/¿ü‚àÈf<š¼cÿ£·= ™%Fý)'x'}ôŸË¡Üu5y÷•7G¶G%D'ubdèÞÈÀ8£VŒ Œ—¿�šˆ;.½ARâqÔ0âÿâRšÔ¢à+‰øªÀ‚¡ø¸,€ƒ3ßuü!ŽŸ8‰LÉ…ÇK“��×åŸãkébˆpõÞଋ õŽ÷^§ÖGá^«…«³‹å2‰�ñ—øµ 8ö’— Ó*Ф9€&y)²ÿMö÷˜j¿Î�N°Ÿ¾A½ÊMµÄÉaÆFa™à¼È~¨±T¥Zä wåDÆIu_ËÅÇÛ2ܼäahÒü@“¬YG7Mv7õÿúÚ±Ð0»›]ÖêTËÕ¶S7«5ª¥‚Ý´ .k4ªå.¶SÖ î/yMênI3¬gH<XÐ)Rø€rB£ †íÅY’]E?ÎdTGíá†< » ~U~·€SM2¦dy¼4iê¨éýöᾞ¶Ó6hìÃݶøÚMߤµ ÖZú»,v08†kíBm§®ßç­ïûîaSg­ÄÀˆ‡¬Câdi}5Ü/·’¡IhFÒ$U)ëYI“4Ý'¦Rn·T¸wš$ÚË{>¿a¯aè�Ñy™à8ÏÆaæfÍZ_K/¿Mû÷eŽŽ37%é„Þ/n4µWH ÐDFTd!9$“r4bÂŽS>šd ”Û|ÈϦ<œt•1µþÜõṉÖÖ36:®pQ­Ó:ͳBwyïŠñÙïk©—“D�m÷Çç™Ú~•” ±²¡Œ÷“BÂk’ê I8 àSËw�ï¦îv]9oÜ´¦¯�4ËnÞR§-öÛC#âbŒ;C¶ VN«æ.Ýí¶ºëý4S뜭 X#Ò¹S² i‰ >áOºRÌÝé:¢Œ©XY“´Ihþx ¤»áë¦W#3CVZOZj˜¶Ägæ2õüµK×(QLŠÚ©µPÛÎߘº¦õ�èžÆï”Ÿš$•ÑÍ5lF.c+ù„&cnááÇRÌ*�Ù…(rG“|›]šeðz�ªÊ²’§C?ºÉ23hQ’ûÂ$Íâ}úGü7çìPÇê Œê´‹Üˆ•Ýl]òLxEy)±`F/«ëëë«+y«îUÿÚT5Ï9×½(4¼ìÚðЦñu¯†×½ë_Ñ×¾èVû‚P+üúvoo/4 Àl4Iô÷vvÕ¿ßVùrcÉsõ??]ûÓSòwý/Ï4–<ßZñ’ÜÕß×õ¿>°ÿ[{wÀáVº?p|^Maüª´º…ÔØívÖÙñçÚÒj1`‡[µQhjéû¸U‹•·@×Z (.JAn¦ÏœûKŸ“yî™&©$ù|•œsr’$äëyrš–dddd�I�I�I�I�I�I�I�I�I�Éìïù_ÜëÁþÊÿrV<Äx”ùŸîZÆ#‰cÍ\¯ê>ÇÂ{±nïBù¥Š5¥�7 “ññZÕÍåA=YGñ!»øçuAt1»¶\ ¼ñÔ–Ü™d²s€v9“Ѫ¨äµ“Ù§÷~Þ ž¿\Ù¡—�ÉìØÙëÓVåÖ5“sƒ“}ܧ‹ÓK‘‚ö+ÿL[Ò!ceZÛún2Ž �ûÊ.„ u2ݸ•Àâ‹3½:Õô§p÷ ½3kòË¥¼ýreïãboJ˜ÿ*e/2½ ¡d2>Ÿ«:ÆQ¥™e]j�ASÕyLŸ$Ìo)‹­ËËd<î#Ø~qÒ^)uvÃùy/ºe2_9ÿåŠ÷q¹“®…‡�Ý*J °ö™l2µkm�QN\ݶLÆÑëóÒRÕs¢ZWg�¬êÅ*Y~/–—Éì}\f&‹;nû¬o&ëÁìgV3?ÖŽLÞ¦¸zÞ¤kº¸¢L®pÒ5âÑ1ç/N³óìtkUUÝï»ã{±X&ç¾\ùÛºÄLvlÚ JNáI²¡bvâHì‘]�sâF$fy™ ÓCĺìžØðâ¢Sí$d/N¶s\.X཈�òËåL¶_®ì}\Ý)º £I@&@&@&ÿÝœe²×È$È$È$È$È$È$È$È$È$ìl&¯üöüèÃ'ËÍ“^gßÞœ¹áw¿\ímdòê×>?úóÎW½’þÍ—ã¿=îÏmäoßö’[w¾K‰™L]<ú0øúVïÔÉO[5 @&cDxáLFc‰ãl d²õýbÔñÁ8_¾¿+“ìF&óÓy¢”…Ñd42¥1]ŽÊnd2¾nŒ¯*‹™LMýéJ60�Ûn!d2æNË™üê—Ad2;h“ “‘º[ê\÷ÿÔMÝÂ3]�É«WNî̞£Ëÿ¼@ôüXÈ$È$ȤL€L€L€L€L€L€L€LÞ}8‡ã‡·³õý{OO×7ËË{×z°C™¼ý0B˜eòÚ½—Ãá?nG27§”Èdü…¬ã|ùþn¯£(bd²¼ìÆh²{¯=~:7ƒK�É™MÓåé½~dòüÓ||7 €ï& ó®ó#€Ñ¤L “Ùʧ�¯ÍüבØg» “1@Ì–³4öoß~üpèçv€L€L€L2 2 2 2 2 2 2 2 2 2 2 È$È$È$È$È$È$È$È$È$È$ “ “ “ “ “ “ “ “ “ “€L€L€L€L€L€L€L€L€L€L€L€L2 2 2 2 2 2 2 2 2 2 È$È$È$È$È$È$È$È$È$È$ “ “ “ “ “ “ “ “ “ “ “€L€L€L€L€L€L€L€L€L€L2 2 2 2 2 2 2 2 2 2 È$È$È$È$È$È$È$È$È$È$™dddddddddd�I�I�I�I�I�I�I�I�I�I�I@&@&@&@&@&@&@&@&@&@&™™™™™™™™™™dddddddddd‚L2 2 2 2 2 2 2 2 2 2 È$È$È$È$È$È$È$È$È$È$È$ “ “ “ “ “ “ “ “ “ “€L€L€L€L€L€L€L€L€L€L2 2 2 2 2 2 2 2 2 2 A&™™™™™™™™™™ddddddddddd�I�I�I�I�I�I�I�I�I�I@&@&@&@&@&@&@&@&@&@&™™™™™™™™™™€ “€L€L€L€L€L€L€L€L€L€L2 2 2 2 2 2 2 2 2 2 2 È$È$È$È$È$È$È$È$È$È$ “ “ “ “ “ “ “ “ “ “€L€L€L€L€L€L€L€L€L€L@�I@&@&@&@&@&@&@&@&@&@&™™™™™™™™™™™dddddddddd�I�I�I�I�I�I�I�I�I�I@&@&@&@&@&@&@&@&@&@&@&÷X†Þ¶�ÉÉä_–E™,�I™@&_Ÿì^ãb-ÿAÊ$€LF`öÎìF (ö\i´¿ëxÖiÏæj¨^üwϺÚkÔ2¹k™¬ö. ^§Ë/ªÈÃb™Œe 3ù"Â7›É³ç>| fUG#«Úhrw2ƒ¤||™ šÂ“¯Ï“SÕ)0§ö�lÝä n6hnù‰M±gv_¯—¢mwŽÂÅš™Ç0�njnž/õAd2–³LÆ�}dr'2YWÙ4ã‹μ@ùúÔ¤7Ö1“±tMÆDë4íÍ÷µqY&w “1Ž,į½~E™,¥®‰å*3E¬bœ—er—2Ùœº2g¦ô¬Ï']›–']»drÞc¨£æN/ þÙÜQ:rd2C÷I×t�ióSxR•O÷‰!¦Lî@&Sâd™lÎ3/P#_§†–Oáé–Éü¾Rq“˜MW«ƒläZW¥SxRüB̯ή)ÿo™X>¿ÂãWx�I™À_¡ÀVfò2Ð"“ë ™™™œŒ–ÿN6n)?£Ëë™”IdR&�I™@&Ÿ½�Þn~&ß�GŒÉ$ÀÉ䣷ã©i`žmx&Ÿ½�¦Ï$•R&dòÆïÏ�>|²|óó3ù~š–f(™gr4IåY*n­'o&3ÞMª‹o4 oÆ�“®ïÆSÓ§#“2Ùïÿõüè¯ûW/õ癌éÖÖð«�«<„Å­ÃwӾ̈́-z–ï–U06n;ÊJY:ò§Ïhê™Lt!“‡·^ÍËd>”Œ%‹YÂî[ËûD&K·�–�Ü×ïdr×2ùÃ7Ó‰Öß8wùã“Ã”ÉæÂ«[‡‘ÉfŠrø~e™¬Æ“I /œÉ8~ùÈù™®õôY½‘É)™œY‡ýD^?<-åƒq,GLJýãÓNÆÉ;1?¹¬LƦdX·×çF£üæ1­ú¦Ë‘³Lÿˆ™d™p¦k:�'JšR¦qd²òLæ§ù”¿›,žËó¨Û‘e '“™ÿ¿ø!ûªòø×ÈëO^=xõäú—ÎdÌŽŽFÝ3GŽ[•�,“ÉäÌW•ÇG§­ÙW•¥ï&× “åF–3é»É “W‡OÒØ1Îz-ÿ¿ÉÕŸéýë:wZnd×#;Ó #“ý?ßÿôž¿ß¸\ÒýÿM¦�Z&UÚZOÅÖî?/åû¼#û“@&ËÿžMZVÿ+<øM×úÝ6d²ö›®Ë%“1Q¹á™Œ d™XˆLú{“È$È$ȤÅb±X,–¹ËÛ Þ¢�¬aIEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/000077500000000000000000000000001526573132500252365ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/community.html000066400000000000000000000043761526573132500301620ustar00rootroot00000000000000{% extends "entrance.html" %} {%- block content %} {{ entranceNavBar() }}

{{ _('Community') }}

{% trans %}Connect with other SpeedCrunch users and follow project news through these community channels.{% endtrans %}


{{ _('Channel') }} {{ _('Community') }}
 {{ _('GitHub Discussions') }} {{ _('Ask questions and share ideas') }}
 {{ _('GitHub Issues') }} {{ _('Report bugs and request features') }}
 {{ _('Google Group') }} {{ _('SpeedCrunch discussion group') }}
 {{ _('Facebook Group') }} {{ _('SpeedCrunch Facebook group') }}
 {{ _('X (Twitter)') }} @SpeedCrunchOrg
 {{ _('Reddit Community') }} r/speedcrunch
 {{ _('Discord') }} {{ _('SpeedCrunch server') }}
{%- endblock %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/donate.html000066400000000000000000000043761526573132500274100ustar00rootroot00000000000000{% extends "entrance.html" %} {%- block content %} {{ entranceNavBar() }}

{% trans %}Thank you for helping{% endtrans %}

{% trans %}SpeedCrunch is and will always be available to you at no cost.{% endtrans %} {% trans %}However, if you use this application on a regular basis and you find it very useful for performing on your work, studies or private affairs, please consider supporting it financially.{% endtrans %} {% trans %}Any contribution, no matter how small, will help supporting the expenses of server hosting, internet domain and computers for further development.{% endtrans %} {% trans %}It will also somehow compensate for the many thousands of hours spent by volunteers since 2004 on this project.{% endtrans %} {% trans %}As a result, much more frequent releases will be possible with your help.{% endtrans %}


{% trans %}Please send us your contribution via one of the methods below.{% endtrans %} {% trans %}If it is not working for you or think we should support other payment methods, please get in touch.{% endtrans %}

{% trans %}Service{% endtrans %} {% trans %}Send To{% endtrans %}
 Revolut revolut.me/heldera0jd
 Paypal donations@speedcrunch.org
 Bitcoin 154mwfndZ2ML1viBMryVfrCreEnzVahrMX


{%- endblock %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/download.html000066400000000000000000001022201526573132500277300ustar00rootroot00000000000000{% extends "entrance.html" %} {% macro downloads(win=[], osx=[], linux=[], win_port_text=True, linux_dropdown=True) -%}
{% if win -%}

Windows

{% for (name, path) in win -%} {% if name == "Installer" -%}  {{ name }} {%- else %}  {{ name }} {%- endif %} {%- endfor %}

{% if win_port_text -%}

{% trans %}Use the portable version if you can't or don't want to install the application. Take it anywhere and just run the file to start.{% endtrans %}

{%- endif %}
{%- endif %}

macOS

{% if osx -%}

{% for (name, path) in osx -%}  {{ name }} {%- endfor %}

{%- else %}

 Download

{%- endif %}

Linux

{% if linux -%}

{% if not linux_dropdown -%} {% for (name, path) in linux -%} {% if name == 'Flathub' -%} {{ _('Download on Flathub') }}
{% trans %}Currently unavailable.{% endtrans %} {%- else -%}  {{ name }} {%- endif %} {%- endfor %} {%- else -%}

{%- endif %}

{%- else -%}

 Download

{%- endif %}

{% trans %}If available, we recommend installing SpeedCrunch directly via your distribution's package manager.{% endtrans %} {% trans %}Note that the latest version may not be available.{% endtrans %}

{%- endmacro %} {% macro oldVersion(version, id) -%} {#, *args, **kwargs #}
{{ downloads(*args, **kwargs) }}
{%- endmacro %} {%- block content %} {{ entranceNavBar() }}

{% trans %}Download SpeedCrunch{% endtrans %}

{% trans %}Free, open-source scientific calculator for Windows, macOS and Linux.{% endtrans %}

{% trans %}Version 1.1{% endtrans %}

{{ downloads( win=[ (_('Installer'), 'https://github.com/heldercorreia/speedcrunch/releases/download/v1.1.0/SpeedCrunch-1.1-windows-x64.exe'), (_('Portable'), 'https://github.com/heldercorreia/speedcrunch/releases/download/v1.1.0/SpeedCrunch-1.1-windows-x64.zip'),], osx=[ (_('Installer'), 'https://github.com/heldercorreia/speedcrunch/releases/download/v1.1.0/SpeedCrunch-1.1-macos-arm64.dmg'), (_('Portable'), 'https://github.com/heldercorreia/speedcrunch/releases/download/v1.1.0/SpeedCrunch-1.1-macos-arm64.zip'),], linux=[('Flathub', 'https://flathub.org/apps/details/org.speedcrunch.SpeedCrunch'),], linux_dropdown=False, ) }}

{% trans %}Unsure about the installation?{% endtrans %} {% trans %}Have a look at the instructions.{% endtrans %}

{% trans %}Older versions:{% endtrans %} 1.0, 0.12


{% trans %}What's new in 1.1{% endtrans %}

{% trans %}Functions{% endtrans %}

  • {% trans %}Add{% endtrans %} root(n; x) {% trans %}for nth roots, including negative values and quantities with units. For example,{% endtrans %} root(5; -32) {% trans %}returns{% endtrans %} -2.
  • {% trans %}Fix factorials in{% endtrans %} {% trans %}user-defined functions{% endtrans %}, {% trans %}such as{% endtrans %} f(n) = n!.

{% trans %}Constants and units{% endtrans %}

  • {% trans %}Search constants{% endtrans %} {% trans %}by name or unit with{% endtrans %} Ctrl+Space. {% trans %}Select a result with the arrow keys and insert it with Enter, Tab, or a click.{% endtrans %}
  • {% trans %}Improve searching and keyboard selection in the Constants panel.{% endtrans %}
  • {% trans %}Correct the units of the muon, proton, and neutron energy equivalents.{% endtrans %}
  • {% trans %}Allow powers of{% endtrans %} {% trans %}grouped quantities{% endtrans %}, {% trans %}such as{% endtrans %} (2[m])^2.
  • {% trans %}Correct results shown in{% endtrans %} J/m² {% trans %}and{% endtrans %} J/m³ {% trans %}when using prefixed units.{% endtrans %}

{% trans %}Input{% endtrans %}

  • {% trans %}Fix undo and redo, and copy and paste.{% endtrans %}
  • {% trans %}Fix clipped text and excess space in wrapped input with different fonts.{% endtrans %}
  • {% trans %}Fix crashes when typing operators in long, wrapped expressions.{% endtrans %}
  • {% trans %}Restore{% endtrans %} {% trans %}digit grouping while typing{% endtrans %}, {% trans %}following the selected number format.{% endtrans %}
  • {% trans %}Add an option to turn off{% endtrans %} {% trans %}automatic input adjustments{% endtrans %}, {% trans %}such as operator replacements and closing brackets.{% endtrans %}
  • {% trans %}Add optional{% endtrans %} {% trans %}Enter-to-accept autocomplete and Escape-to-clear behavior{% endtrans %}.
  • {% trans %}Add an option to use a steady cursor instead of a blinking one.{% endtrans %}
  • {% trans %}Preserve{% endtrans %} {% trans %}comments{% endtrans %} {% trans %}as written and prevent them from affecting result formatting.{% endtrans %}
  • {% trans %}Improve recalling expressions from history and focus the editor after startup.{% endtrans %}
  • {% trans %}Remove the empty-history hint.{% endtrans %}

{% trans %}Results{% endtrans %}

{% trans %}Sessions and settings{% endtrans %}

  • {% trans %}Add{% endtrans %} {% trans %}private tabs{% endtrans %} {% trans %}that discard their contents when closed and are not restored on the next launch. Use{% endtrans %} Ctrl+Shift+N (Cmd+Shift+N {% trans %}on macOS) to open one.{% endtrans %}
  • {% trans %}Allow switching between private and saved sessions, and optionally open a private tab at startup.{% endtrans %}
  • {% trans %}Add{% endtrans %} {% trans %}Reset All Settings...{% endtrans %}, {% trans %}keeping sessions, history, and user definitions.{% endtrans %}
  • {% trans %}Fix global{% endtrans %} {% trans %}user definitions{% endtrans %} {% trans %}missing from restored sessions.{% endtrans %}
  • {% trans %}Make{% endtrans %} {% trans %}session renaming, cloning, closed-tab recovery, and pane controls{% endtrans %} {% trans %}easier to find in the menus. Cloning also copies unfinished input.{% endtrans %}
  • {% trans %}Organize the result context menu into Copy, Remove, Split, and Session groups.{% endtrans %}
  • {% trans %}Move{% endtrans %} {% trans %}Number Format...{% endtrans %} {% trans %}directly under Settings and simplify the result and appearance menus.{% endtrans %}
  • {% trans %}Apply font changes across all windows and fix font selection on macOS 27 and later.{% endtrans %}
  • {% trans %}Fix commands acting on the wrong window when used from a floating panel.{% endtrans %}

{% trans %}Appearance and panels{% endtrans %}

  • {% trans %}Add separate{% endtrans %} {% trans %}system and SpeedCrunch theme choices{% endtrans %} {% trans %}for menus, panels, and the status bar.{% endtrans %}
  • {% trans %}Add a compact{% endtrans %} {% trans %}Classic layout for input and results{% endtrans %}. {% trans %}Modern remains the default.{% endtrans %}
  • {% trans %}Improve text contrast, menu readability, and panel button visibility.{% endtrans %}
  • {% trans %}Match menu icons to the theme and dim disabled menu items and shortcuts.{% endtrans %}
  • {% trans %}Tidy panel spacing, borders, and rounded corners.{% endtrans %}
  • {% trans %}Keep side panels at full height and remember table column order.{% endtrans %}
  • {% trans %}Preserve floating panel positions and visibility across restarts, and prevent floating panels from being grouped unexpectedly.{% endtrans %}

{% trans %}Keypad{% endtrans %}

  • {% trans %}Add a compact{% endtrans %} {% trans %}Classic keypad appearance{% endtrans %} {% trans %}and 50% zoom.{% endtrans %}
  • {% trans %}Restore Zoom in the keypad's right-click menu and fix inconsistent sizing when changing zoom levels.{% endtrans %}
  • {% trans %}Update{% endtrans %} {% trans %}scientific layouts{% endtrans %} {% trans %}with nth-root, square, and argument-separator buttons, and group related operations together.{% endtrans %}
  • {% trans %}Replace the obsolete{% endtrans %} lg {% trans %}button with{% endtrans %} log10.

{% trans %}Other improvements{% endtrans %}

  • {% trans %}Reduce startup delays when restoring sessions, history, and panels.{% endtrans %}
  • {% trans %}Make update checks more responsive and prevent them from delaying window closure.{% endtrans %}
  • {% trans %}Add{% endtrans %} {% trans %}Help > App Diagnostics{% endtrans %} {% trans %}with a report that can be copied when asking for help. Show operating system details in About SpeedCrunch.{% endtrans %}
  • {% trans %}Fix a crash when closing windows with certain panels open.{% endtrans %}
  • {% trans %}Add portable macOS ZIP packages that keep settings and sessions beside the app in a{% endtrans %} SpeedCrunch-data {% trans %}folder.{% endtrans %}
  • {% trans %}Set the default macOS minimum version to 14.4 on Apple Silicon.{% endtrans %}

{% trans %}Contributors{% endtrans %}

{% trans %}Thank you to everyone who contributed to SpeedCrunch 1.1.{% endtrans %}

Helder Correia, Vitaly Zaitsev, Rodrigo Pedra, Pedro Montes Alcalde, Francis Tseng, Antonio Mannella, Benjamin Robin, Brian Hale, D.J.L. Sales, Matthias Prager, Rafael Fraga, Theodore R. Smith, @ddidderr, @FrankMountainFace, @jetp250, @Matth7878, @nfshr, @pandora1986, @playerofgames, @rafa4mat, @RedNova84, @Sacryn, @tosione.


{{ downloads( win=[ (_('Installer'), 'https://github.com/heldercorreia/speedcrunch/releases/download/v1.0.0/speedcrunch-1.0-win64.exe'), (_('Portable'), 'https://github.com/heldercorreia/speedcrunch/releases/download/v1.0.0/speedcrunch-1.0-win64.zip'),], osx=[(_('Download'), 'https://github.com/heldercorreia/speedcrunch/releases/download/v1.0.0/SpeedCrunch-1.0-arm64.dmg')], linux=[('Flathub', 'https://flathub.org/apps/details/org.speedcrunch.SpeedCrunch'),], linux_dropdown=False, ) }}

{% trans %}What's new in 1.0{% endtrans %}

{% trans %}Workspace and history{% endtrans %}

  • {% trans %}Work in tabs and split panes to keep several calculations open side by side.{% endtrans %}
  • {% trans %}Save calculation history between launches and set a history size limit.{% endtrans %}
  • {% trans %}Load your own functions and variables at startup.{% endtrans %}
  • {% trans %}Choose a keypad preset or build a custom keypad.{% endtrans %}
  • {% trans %}Show or hide the main menu. The result display now has a right-click context menu with an entry for the main menu.{% endtrans %}
  • {% trans %}Re-edit an earlier expression and recalculate all the expressions below it.{% endtrans %}
  • {% trans %}Check for updates from within the app.{% endtrans %}

{% trans %}Expressions and editing{% endtrans %}

  • {% trans %}Use lists and matrices in expressions.{% endtrans %}
  • {% trans %}See the interpreted expression alongside the result, with implicit multiplication made explicit.{% endtrans %}
  • {% trans %}Write integer powers with superscript digits.{% endtrans %}
  • {% trans %}Use{% endtrans %} √, ∛, Σ {% trans %}(summation), and{% endtrans %} Ï€ {% trans %}as aliases. The{% endtrans %} ~ {% trans %}operator is an alias for{% endtrans %} not().
  • {% trans %}More symbol aliases are accepted for addition, subtraction, multiplication, and division.{% endtrans %}
  • {% trans %}Autocomplete suggestions now show category icons.{% endtrans %}
  • {% trans %}Pasted numbers are automatically formatted to match the global Number Format setting.{% endtrans %}
  • {% trans %}Insert constants and formula book entries with their units included.{% endtrans %}

{% trans %}Results and formatting{% endtrans %}

  • {% trans %}Show a calculation in several result formats at once. Number-format choices include Indian 3-2-2 digit grouping.{% endtrans %}
  • {% trans %}Show rational results as fractions, or use sexagesimal notation for angles and time.{% endtrans %}
  • {% trans %}Show angles as multiples of pi in radian mode or through an explicit conversion.{% endtrans %}
  • {% trans %}Choose how complex numbers are displayed, with polar forms and options for the imaginary unit.{% endtrans %}
  • {% trans %}Set a custom precision with the Custom... option.{% endtrans %}
  • {% trans %}Choose from five rounding modes.{% endtrans %}
  • {% trans %}Changing the primary result format updates only the last expression. Earlier history entries keep their formatting.{% endtrans %}

{% trans %}New functions{% endtrans %}

  • {% trans %}Integer arithmetic:{% endtrans %} powmod {% trans %}for modular exponentiation,{% endtrans %} emod {% trans %}for Euclidean modulo,{% endtrans %} lcm {% trans %}for least common multiples, and{% endtrans %} popcount {% trans %}for counting set bits.{% endtrans %}
  • {% trans %}Number formatting:{% endtrans %} binpad, octpad, {% trans %}and{% endtrans %} hexpad {% trans %}for padded binary, octal, and hexadecimal output. Use{% endtrans %} sci {% trans %}and{% endtrans %} eng {% trans %}for scientific and engineering notation.{% endtrans %}
  • {% trans %}Random numbers:{% endtrans %} rand {% trans %}and{% endtrans %} randint {% trans %}generate random decimals and integers.{% endtrans %}
  • {% trans %}Dates and time:{% endtrans %} datetime {% trans %}and{% endtrans %} epoch {% trans %}convert between date/time values and Unix timestamps.{% endtrans %}
  • {% trans %}Summation:{% endtrans %} sigma, {% trans %}also written as{% endtrans %} Σ.
  • {% trans %}Complex numbers:{% endtrans %} conj {% trans %}for complex conjugates and{% endtrans %} cis {% trans %}for constructing a complex number from an angle. Choose rectangular, exponential, or phasor output with{% endtrans %} rectform, expform, {% trans %}and{% endtrans %} phasorform.
  • {% trans %}IEEE 754:{% endtrans %} ieee754_round_* {% trans %}rounds to a floating-point format, and{% endtrans %} ieee754_*_residual(x) {% trans %}returns the rounding residual. Both families support{% endtrans %} half, float, double, {% trans %}and{% endtrans %} quad.
  • {% trans %}Chemistry:{% endtrans %} molmass, mass, {% trans %}and{% endtrans %} molarity {% trans %}for molar mass, mass from an amount of substance, and solution molarity.{% endtrans %}
  • {% trans %}Linear algebra and data:{% endtrans %} {% trans %}List and matrix support with{% endtrans %} cols, corrp, corrs, covp, covs, cross, det, dot, flatten, inv, norm, rank, rows, shape, trace, {% trans %}and{% endtrans %} transpose.
  • {% trans %}Statistics:{% endtrans %} stdevp, stdevs, varp, vars, {% trans %}and{% endtrans %} mad, {% trans %}with list and matrix support.{% endtrans %}

{% trans %}Units{% endtrans %}

{% trans %}Use square brackets to identify units explicitly in expressions, such as{% endtrans %} [m] {% trans %}or{% endtrans %} [s]. {% trans %}New units and aliases include:{% endtrans %}

  • {% trans %}Angles:{% endtrans %} gradian (gon), turn (tr, pla), revolution (rev), degree (°), arcmin (′), {% trans %}and{% endtrans %} arcsec (″).
  • {% trans %}Time:{% endtrans %} {% trans %}Julian century{% endtrans %} (cy_jul).
  • {% trans %}Area and mass:{% endtrans %} hectare {% trans %}and{% endtrans %} tonne.
  • {% trans %}Speed:{% endtrans %} kph {% trans %}and{% endtrans %} mph.
  • {% trans %}Energy:{% endtrans %} quad, {% trans %}equal to{% endtrans %} 1015 [Btu].

{% trans %}Appearance and settings{% endtrans %}

  • {% trans %}Choose from more built-in themes or create a custom theme.{% endtrans %}
  • {% trans %}Interface scaling now applies to the expression editor too.{% endtrans %}

{% trans %}Contributors{% endtrans %}

{% trans %}Thank you to the authors who have contributed since November 30, 2016.{% endtrans %}

Helder Correia, Felix Krull, Mikko Syrjä, Tey / Teyut, Samuel Gaist, Hadrien Theveneau, Pol Welter, Matthew Di Nardo, Chris Roberts, Alan Birtles, Chuvke, Jean-Michel Frouin, Jonas Nyrup, Nikolay Zlatev, Roger Sachan, rewq.


{{ oldVersion('0.12', '012', win=[ (_('Installer'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12-win32.exe'), (_('Portable'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12-win32.zip'),], osx=[(_('Download'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12.dmg')], linux=[ (_('32-bit RPM'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12-linux32.rpm'), (_('32-bit Deb'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12-linux32.deb'), (_('32-bit Generic'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12-linux32.tar.bz2'), (_('64-bit RPM'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12-linux64.rpm'), (_('64-bit Deb'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12-linux64.deb'), (_('64-bit Generic'), 'https://bitbucket.org/heldercorreia/speedcrunch/downloads/SpeedCrunch-0.12-linux64.tar.bz2'),], ) }}
{%- endblock %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/entrance.html000066400000000000000000000067211526573132500277310ustar00rootroot00000000000000{% extends "layout.html" %} {% macro entranceNavBar() %} {% include "entrance_navbar.html" %} {% endmacro %} {%- block content %} {{ entranceNavBar() }} {%- block jumbotron %}

SpeedCrunch

{% trans %}A free, open-source high-precision scientific calculator.{% endtrans %}

{% trans %}Built for STEM professionals, students and teachers.{% endtrans %}

 {{ _('Download') }}  {{ _('User Manual') }}  {{ _('Donate') }}

{% trans %}Free to download and use on Windows, macOS, and Linux.{% endtrans %}

{%- endblock %} {%- endblock %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/entrance_navbar.html000066400000000000000000000031241526573132500312540ustar00rootroot00000000000000{% extends "navbar.html" %} {% block navcontent %} {% endblock %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/globaltoc.html000066400000000000000000000010321526573132500300660ustar00rootroot00000000000000 heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/language.html000066400000000000000000000013371526573132500277130ustar00rootroot00000000000000{% if 0 %} {% endif %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/layout.html000066400000000000000000000257741526573132500274600ustar00rootroot00000000000000{% set theme_css_files = [] %} {% if theme_bootstrap_version == "3" %} {% set bootstrap_version, bootstrap_additional_css, navbar_version = "3.4.1", "theme", "" %} {% set bs_span_prefix = "col-md-" %} {% else %} {% set bootstrap_version, bootstrap_additional_css, navbar_version = "2.3.2", "responsive", "-2" %} {% set bs_span_prefix = "span" %} {% endif %} {% if theme_bootswatch_theme and theme_bootswatch_theme != "\"\"" %} {# BS2 needs "bootstrap-responsive.css". BS3 doesn't. #} {% if theme_bootstrap_version == "3" %} {% set theme_css_files = theme_css_files + [ '_static/bootswatch-' + bootstrap_version + '/' + theme_bootswatch_theme + '/bootstrap.min.css', '_static/bootstrap-sphinx.css' ] %} {% else %} {% set theme_css_files = theme_css_files + [ '_static/bootswatch-' + bootstrap_version + '/' + theme_bootswatch_theme + '/bootstrap.min.css', '_static/bootstrap-' + bootstrap_version + '/css/bootstrap-' + bootstrap_additional_css + '.min.css', '_static/bootstrap-sphinx.css' ] %} {% endif %} {% else %} {% set theme_css_files = theme_css_files + [ '_static/bootstrap-' + bootstrap_version + '/css/bootstrap.min.css', '_static/bootstrap-' + bootstrap_version + '/css/bootstrap-' + bootstrap_additional_css + '.min.css', '_static/bootstrap-sphinx.css' ] %} {% endif %} {% set bootswatch_css_custom = ['_static/extra.css?home=4'] %} {% set css_files = css_files + theme_css_files + bootswatch_css_custom %} {% set script_files = script_files + [ '_static/js/jquery-1.12.4.min.js', '_static/js/jquery-fix.js', '_static/bootstrap-' + bootstrap_version + '/js/bootstrap.js', '_static/bootstrap-sphinx.js' ] %} {%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and sidebars %} {%- set bs_content_width = render_sidebar and "9" or "12"%} {%- set website_titles = { 'index': _('SpeedCrunch — Free High-Precision Scientific Calculator'), 'download': _('Download SpeedCrunch for Windows, macOS and Linux'), 'community': _('SpeedCrunch Community and Support'), 'donate': _('Donate to Support SpeedCrunch') } %} {%- set website_descriptions = { 'index': _('SpeedCrunch is a free, open-source scientific calculator for Windows, macOS and Linux, with 50-digit precision, complex numbers and unit conversion.'), 'download': _('Download the free SpeedCrunch scientific calculator for Windows and macOS, find Linux installation options, and explore release notes and older versions.'), 'community': _('Connect with SpeedCrunch users, ask questions, share calculation tips, and follow news about this free, open-source scientific calculator.'), 'donate': _('Support SpeedCrunch development and hosting with a donation to keep this open-source scientific calculator free for everyone.') } %} {%- set seo_title = website_titles.get(pagename, (title|default('')|striptags) ~ ' — ' ~ _('SpeedCrunch Manual')) %} {%- if pageurl %} {# Use the site root rather than its duplicate index.html URL. #} {%- set canonical_url = pageurl[:-10] if pagename == 'index' else pageurl %} {%- endif %} {%- block doctype -%} {%- endblock %} {%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} {%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} {%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and (sidebars != []) %} {%- set url_root = pathto('', 1) %} {# XXX necessary? #} {%- if url_root == '#' %}{% set url_root = '' %}{% endif %} {%- if not embedded and docstitle %} {%- set titlesuffix = " — "|safe + docstitle|e %} {%- else %} {%- set titlesuffix = "" %} {%- endif %} {# Sidebar: Rework into our Bootstrap nav section. #} {% macro navBar() %} {% include "navbar" + navbar_version + ".html" %} {% endmacro %} {% if theme_bootstrap_version == "3" %} {%- macro bsidebar() %} {%- if render_sidebar %}
{%- endif %} {%- endmacro %} {% else %} {%- macro bsidebar() %} {%- if render_sidebar %}
{%- endif %} {%- endmacro %} {% endif %} {%- macro script() %} {%- for scriptfile in script_files %} {%- if scriptfile|attr('filename') is defined %} {{ js_tag(scriptfile) }} {%- elif scriptfile == '_static/documentation_options.js' %} {%- else %} {%- endif %} {%- endfor %} {%- endmacro %} {%- macro css() %} {%- for cssfile in css_files %} {%- if cssfile|attr('filename') is defined %} {{ css_tag(cssfile) }} {%- else %} {%- endif %} {%- endfor %} {%- endmacro %} {{ metatags }} {%- if pagename in website_descriptions %} {%- endif %} {%- if pagename == 'search' %} {%- endif %} {%- block htmltitle %} {{ seo_title|e }} {%- endblock %} {%- if pageurl %} {%- if pagename in website_descriptions %} {%- endif %} {%- endif %} {%- if pagename == 'index' and pageurl %} {%- endif %} {{ css() }} {%- if not embedded %} {{ script() }} {%- if use_opensearch %} {%- endif %} {%- if favicon %} {%- endif %} {%- endif %} {%- block linktags %} {%- if hasdoc('about') %} {%- endif %} {%- if hasdoc('genindex') %} {%- endif %} {%- if hasdoc('search') %} {%- endif %} {%- if hasdoc('copyright') %} {%- endif %} {%- if parents %} {%- endif %} {%- if next %} {%- endif %} {%- if prev %} {%- endif %} {%- endblock %} {%- block extrahead %} {% endblock %} {%- block header %}{% endblock %} {%- block content %} {{ navBar() }}
{%- block sidebar1 %} {{ bsidebar() }} {% endblock %}
{% block body %}{% endblock %}
{%- block sidebar2 %} {% endblock %}
{%- endblock %} {%- block footer %}

{%- if show_copyright %} {%- if hasdoc('copyright') %} {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
{%- else %} {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
{%- endif %} {%- endif %} {%- if last_updated %} {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
{%- endif %} {%- if show_sphinx %} {% trans sphinx_version=sphinx_version|e %}Created using Sphinx {{ sphinx_version }}.{% endtrans %}
{%- endif %}

{%- endblock %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/navbar.html000066400000000000000000000043251526573132500274010ustar00rootroot00000000000000 heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/navbarsearchbox.html000066400000000000000000000006641526573132500313020ustar00rootroot00000000000000{%- if pagename != "search" %}
  • {%- endif %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/relations.html000066400000000000000000000021161526573132500301240ustar00rootroot00000000000000{# Switch to icon instead of text in `sm` view size for BS3 only. #} {%- if prev %}
  • {%- if theme_bootstrap_version == "2" -%}{%- endif -%} {%- if theme_bootstrap_version == "3" -%}{%- endif -%}
  • {%- endif %} {%- if next %}
  • {%- if theme_bootstrap_version == "2" -%}{%- endif -%} {%- if theme_bootstrap_version == "3" -%}{%- endif -%}
  • {%- endif %} heldercorreia-speedcrunch-e7ca37f/doc/src/_templates_standalone/scrollspy.html000066400000000000000000000000461526573132500301560ustar00rootroot00000000000000
    {{ toc }}
    heldercorreia-speedcrunch-e7ca37f/doc/src/conf.py000066400000000000000000000245261526573132500222010ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # SpeedCrunch documentation build configuration file, created by # sphinx-quickstart on Mon Feb 8 20:22:01 2016. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os import re DOC_ROOT = os.path.abspath(os.path.dirname(__file__)) EXTENSIONS_DIR = os.path.join(DOC_ROOT, 'extensions') VENDORED_QUARK_DIR = os.path.join(EXTENSIONS_DIR, 'quark-sphinx-theme-0.6.0') LANGUAGES = { 'en_US': 'English' } try: bundled = tags.has('sc_bundled_docs') except NameError: bundled = False # -- General configuration ------------------------------------------------ locale_dirs = ['locale'] gettext_additional_targets = ['index'] gettext_compact = True # If your documentation needs a minimal Sphinx version, state it here. needs_sphinx = '3.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. sys.path.insert(0, VENDORED_QUARK_DIR) sys.path.insert(0, EXTENSIONS_DIR) extensions = ['speedcrunch_domain', 'sc_lexer'] primary_domain = 'sc' if bundled: extensions.append('quark_sphinx_theme.ext.html_compat') # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'contents' # General information about the project. project = 'SpeedCrunch' copyright = '2026, The SpeedCrunch Developers' author = 'The SpeedCrunch Developers' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # Read the release version without requiring an application build first. with open(os.path.join(DOC_ROOT, '..', '..', 'CMakeLists.txt'), encoding='utf-8') as cmake_file: version_match = re.search( r'^project\(speedcrunch\s+VERSION\s+([0-9]+(?:\.[0-9]+){1,3})\s*\)', cmake_file.read(), re.MULTILINE) if version_match is None: raise RuntimeError('Cannot read the SpeedCrunch version from the root CMakeLists.txt') release = version_match.group(1) version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build', 'extensions/**'] highlight_language = 'speedcrunch' # The reST default role (used for this markup: `text`) to use for all # documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. #pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. if bundled: import quark_sphinx_theme html_theme_path = [quark_sphinx_theme.get_path()] html_theme = qthelp_theme = 'quark' html_theme_options = qthelp_theme_options = { 'headerlink_color': 'transparent', } else: import sphinx_bootstrap_theme html_baseurl = 'https://www.speedcrunch.org/' # The units table is included in the units reference, not a separate web page. exclude_patterns.append('reference/units_table.rst') html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() html_theme = 'bootstrap' html_theme_options = { #Comment out next line for default bootstrap theme #'bootswatch_theme': 'flatly', 'navbar_class': 'navbar-inverse', 'navbar_pagenav': False, 'source_link_position': "footer", 'globaltoc_depth': 2, } html_sidebars = {'**': ['scrollspy.html']} html_static_path = ['_static_standalone'] html_extra_path = ['demo1.mp4', 'screen1.png', 'robots.txt', 'sitemap.xml'] templates_path = ['_templates_standalone'] html_logo = 'logo.png' html_context = { 'languages': list(LANGUAGES.items()), } html_additional_pages = { "index": "entrance.html", "download": "download.html", "donate": "donate.html", "community": "community.html" } # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. #html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' #html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value #html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. #html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. htmlhelp_basename = 'SpeedCrunchdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', # Latex figure (float) alignment #'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class], toctree_only). # Setting toctree_only doesn't include the text content of the master document # in the output, only the TOC. latex_documents = [ (master_doc, 'SpeedCrunch.tex', 'SpeedCrunch Manual', author, 'manual', True), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'speedcrunch', 'SpeedCrunch Documentation', [author], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'SpeedCrunch', 'SpeedCrunch Documentation', author, 'SpeedCrunch', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False heldercorreia-speedcrunch-e7ca37f/doc/src/contents.rst000066400000000000000000000012041526573132500232550ustar00rootroot00000000000000.. meta:: :description: Browse the SpeedCrunch manual: installation, calculation tutorials, expression syntax, interface settings, mathematical functions, constants and units. Table of Contents ================= .. toctree:: :maxdepth: 3 introduction userguide/index reference/index Indices and Tables ================== .. Checking for the sc_bundled_docs tag here so as to not include a link to the search .. page when building for bundling. .. only:: sc_bundled_docs * :ref:`genindex` * :ref:`sc:functionindex` .. only:: not sc_bundled_docs * :ref:`genindex` * :ref:`sc:functionindex` * :ref:`search` heldercorreia-speedcrunch-e7ca37f/doc/src/demo1.mp4000066400000000000000000025527231526573132500223400ustar00rootroot00000000000000 ftypisomisomiso2avc1mp41¥moovlmvhdè´W@Ïtrak\tkhd´W@&$edtselst´WGmdia mdhd0¨UÄ1hdlrvideCore Media Video îminfvmhd$dinfdref url  ®stblÆstsd¶avc1&HHLavc62.28.101 libx264ÿÿ9avcCdÿágd¬Ù€Ìyªj€€ŒÍhéxD²,ýøøcolrnclxbtrtÝësttsstssØctts((( (  ( (  ((( ((( (((( ((( ((((   (( (((((((( (((stschstsz¸èw«ô�‘—z&s÷ Pûí|æE ¶ýæ«®Ö1;MÙÀ0‘ pš Ýb· ø;ëj¼ ¸k—I‡‹B¯{ …$ , câ7{€-J öß4â 8 ç0Ÿ. 7>f˜"ß4ŽOPÏ×ë'q^àû-=r§¢ ¸4þ„_oJÛõ¶ñEÏYûI:¾D4µ• ’ƒ]¯/™³Ì&€Ik í ד_!Øñ ]ê\'%³ø±a(`/  Çht〖»)Zwуãbô„Âb`¬Z]’°¸W+Œð\ÿH½:(�W”<Þ»ÈÄ8JÁ9$åÌ. �îÇ'c5' ­  ¹$2³¼"©XašYì "V›k­ Rˆ1 7j 7; tR „ö$ñ K,§6�=G jkÑø8EZ' N_>  Þ ƒÛé þÌzPstcoÕbudtaZmeta!hdlrmdirappl-ilst%©toodataLavf62.12.101free Æmdat®ÿÿªÜE齿ÙH·–,Ø Ù#îïx264 - core 165 r3222 b35605a - H.264/MPEG-4 AVC codec - Copyleft 2003-2025 - http://www.videolan.org/x264.html - options: cabac=1 ref=5 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=8 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=2 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=15 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=6 scenecut=40 intra_refresh=0 rc_lookahead=50 rc=crf mbtree=1 crf=30.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00€eˆ„+ÿþíÏàS(Aeã&×5Î@9}ÖðC€s_ø3a޲ Ä{�\cªåaár½ÛÉ �š­dí 6Yƹr ­Ó†W‘¤�Ê™vN�rÛ¤_¦ä¤Rè½tXÛŒ?A 4ð$Âtõµ/–'Ó°­A#�@šä÷›Å¼"€NG#bjC�äŠ3ÑüøÊc)艈$®ð(|ºg‚A·„»’kžQêºÖ­~†&šàP[õkRŒ4“Êg‰9¸~ñ4¤ë0ö- s>yø†Iâ¬ñÀXïåÆª©v�%eÌìŠ?øÒ1 AhÅYþµÇ¸¹0ûqª‘‹ `ƒ¡ë±0‰®²™.¡eš€D QÌ:¡·öfßãgšq/éT^¥mtòS89 ûLuyçÞ ð �Ó3%Ï ÖÃ/w¾BäÍMÂ帿ˆº7"ªê,W[ËåÚ Ê7³]/åæ‚vï æ"ƒš?Vމµ6ù‚uô[­b •np(ø­öì8*)' NŬ�=¤N!©È2žqÊů“À?ùZóám8~>ÁÈ>ÄHÃ+®‡>óÛ —íÀÄ–q£D¢w˜gRèe! ÄxR—[œû>¾5”FtY“ê)]Ë‘HîÄ÷�»CҲɹÑBã±Í‹–*)GD# YêðD�Æì?V¤¦‘5{ìÏŸƒúÏ Eµ»aÜ@l„6�×ùѱwkQ³ u¡Ù>rPüÇ Ê$§‡xRf�Õ\^ŸC›HûöËOK`Æç—zêåuÈÖ�ȧæ?·ã‰ØhVsB:TpÉ.‰ŽòZ®=W ºQi#€9ïùóx´\úz;Uaß±Œ™¡?ïV¦ÞÙ•˜I³�¾dÔ;XzôöDi"iÖB¶�Ö„|ât×ÄÖÊÍŒ·/º¡ðšh‚ÝZh>QVé¼ Ò�*‹âÙ>3ž8E\j¯�Ò�~wõñäÓë½kz®Ñ0£¯J»8Ò7瑃ӪWhëkÒD2`Z1~**”?ºì ÖJ�3v¯k‰ÌKý9ÔQ,´p®­Qî Tr>[ýJ%<5ŒDßë–)¢Í\„f(L«H™~œfEq€ÖÏ7Ó 3à´T³O:-äAÂÐBÏŽhrÆ^0pb´| ’uWþ¬#ƒ(u+õ‹3Œ-Ê;š2Åm@, C'™� w’B9QG2µˆ(ÂIìëD±b¿�ûÎʳ9bú¾ åiëc_EÙÏaǼ%•I’”ëy¦foõóQyá4%ÿü•ºùÿ 'Cü‹� ‰$—2ëØXRÜ_ë3É-ƒ=wšîñ߉I1W€S>uñ3ã��FBFãËÒ}²oÏ6Â×QØÀbñèkc #JÅéÑ¥²Z|“ Ì6Ì£àVs¸}.‰Ê¥?„GÓí=‡Ç\Ìšt^9o ,–�÷Ççwt÷$�ËÀâÙw�Ž˜f¶)Å$É5…LF®¾A“ñ³&pô4ê…:ÓÀ:ÝJåá~˜¹-pß’.S`ý†®,Â-Î  F=/¶x"iV��Oú%55u×JPw.às1Gr¦:¿^KÖŠÚÕ[ èq›°J “ë9Ž!ü1`DX/°þº¢IÞ3ùÚ,‡ý1kØÃùÎ*ÇÞt?oã&ôë ÿü VßæfÈ-åUÄp¶ü>÷°Eúv Z?ÊG ¸AÝ_Ý"&¯O÷ >æ7Ç âúÅè«Wðò·Ã>¡“ÉÖÉ7!]9í§ /.GÇ#~h×ä&´zúŒµCÊßÛ/’`Á)r²÷äÉO6úìWã'‹ÚE“#|)c2“›™Ùûº7ÉG5g`)dÐ'è(Z3Ù ¾<ÆMë'÷:?jÆ-b–\˜ Ñzüíjœ?9™?¶Bp®ƒF.ö¯Ì-ðß­åéOíuXþÀbvIÐÒ³ªÄå=O ÿ…¶Á‚®òŠ>¾¾ GÛÎ&íiM…‰�­Y£QM¨áÀD²E¯~¾°Öðh+µ»|¨t¯ÎƒJ»�]G ©oap?ÙP‡CóPþ^¶{Œ�¦›ØÁ#t»ý„R �?Ï7qHÙÜf›³<÷>hmR⌢m¦¬ló©#¶CÖ˜g‰LãûTCáðbµNzýØ©e’’ PoÍ–´âØE0óCöÉx¶5YzZsWÉ’†ÉiצsÖ_xÞ•Ÿ£«¡€ %e$K§þ]o¯¬Bçÿ}’ IÒô sý®I2õeätÂ3ùViÙ?…2ç²€37° ´¦ö\•D¾�)’þº Ó)s'|¦IÏ‹�ûMô3Ct#vœrb›¿œÏÛü;¹Wì¦�Ú×c VÉ®ïmÂd\ùÚ¨ð¯¸G§Š[RÂïQÏYS!‹Íö!d"Vƒzã´B´ @èÊY#üÊ’¥8›ótt¯á¨’1‹‹�n�ÙˤÅàÒ©P E‚£'fa;\‰“–úª®±’�úQ–Ü„…×õ ßxˆ˜‰ X“ñ Š§ÎœÞ§³L]ÑóÝxáË#©T/ÚÐS'¡(Ey¥.^ðÉ”oÞ Rû¤…~ |)&„IE‚ðœ×Y?;mgj‰=q¿¿Ì"⹦A>JxbY Ü�“ Øñ#瀘ö bé;}N°‰ ׄ1”¿{Éûð•n�,k”^«ÿ9™ŽßÊotRaÃWˉæè’mZÄÎ}`¼€€µÃmk§ë&õˆ¿�m·áA„™î¼¶¹ÐíYß¹XÁ‘ |Üø€„`ù'0C±�/­œ:’žsË£WŸÆYèx’Ò#{~w‘ä¬ ¨-™/þ¼Š‡\¤pKôÜÙW€ˆ!Æõ§Îdø´Eo¿!Ìwª–)è%äñ’EÊ!ò�pÄ5‘c[zô²€�%7’^¡ØoP=:cY ��£uäœlÒi#YƒÐߟa|/8Ȭš%?ÏmÅ¢\M;磉³þg¯ýÉ‚ä„Çq)�:ɤ”\ªâ3Ú€>&*"•�eŒ§n”9 ÌF¤¨5¯ž³ÞÌ3Rdý[ÊwüxLŒ¾¤:6¥'ªBÜ(1µÿÇÈ¥–£` æJ7’‚=Äc…Àô �g`zHF 0F#PF8pFG�FS°FcÐFq‘“ ·Ð òT ôX ö˜ ø ùÜ û ü` û`µÈýH#j Fã`�ñ©{*3áöñê?px�½šŒV�ñÍý»�¢Õ/¿'óoR±ÐyîËê«íæ0”í+Ê„Oêm6VƒH ¤ãÀ‹+PR�,}Ë`[s¸;‚qˆãeOmJ®ÕNÂP·ž9ß1‚Æ™ÐþÒƒ0B\bOþ¦×Ët\B¿RÞheÍ"&È6Kh�«ƒ…Î(KâÛ"ò.’±VÔIΟÆã‰G\ðì¢Ú­´7¿“3VŠÅ˜þð Îò3Ot©F,Diƒ*Õ€Du¸Úk h¥ÞeÑxÛ¨•#.ûÊ=zâºO9[§MfᢎJÆÒ޳¸òT³ù8ÔÑ^‰ÄnÁÎôÚM2)Uõ¹ÅiÁ‡'vvBM{\ ·è¡`Ýû�~ttòLf4yÝqZélu€‘J™†? ÕJUs¨¼þÓ×I�IxrKß ŠMcgE´÷î þ² k\&¾¢5UÅpɒۚΜìÜ•5”]‘¾|o1Û.¯&  P¥ Æ–^s`2“t˜<õŸ¸t"v| ¤Oµ�±îhPÜ“\"¢[¼œ`­CCHª~~òÚ`ªÆœèO‹fRR­Á}ß$€y<8‹ÕO&8FŒ L¿'ç¯É¿|Â[ƒ êVýÿ?.ðM°'ÿqūن‚tX >65Ï‚)Ýš¯fÚj#q¤æB-võ~¿v•hšÔIö_[ t­ ªÏ¬íF{Êu�(X¢°Ö×ÚÀPÞáWŽ£TV⦒©äAš!lB?õô€eÏÃqf€ öö(Z5$ݵL°På2„á;ÃýàÆ9ü….læÅ TÜ™ê¥ ‹Ãƒòe¸”!Y?àcà(u¢R4ÚŸÆ¢ÐL��]üæ”×Ð þåïè0.I…_þ˜L8ZªK¶§„ú}À\£²âôi×9�óÁ×Éè/M‘qã»{2ø�íæÃÇy³êSvµL°'ì2}ËM‚/WÔäç3·]+%_�l‘áU¢ÛRˆX;EMjU˜¸zvgýtNóò ÙAMGªàsAšC_„2e0…ÿUSšç5zî}…×Pÿå¯ÞÎÎÐÌÓ2pé]p'/Éw#wqC©{ƒ9÷ž|? Öλö÷�5§t€ ºË÷Íèþ6‘TZ|ÛÚà3 œ•aiš×tÇŸ©”Y¡\Oq�u Â Ý+•“`ŒŠ*©º^×C¨¼…òdÝx îý|�HJ™õ¤GfÅÑ@B`'< T-FR¤èp,õè…€ÉÚÀ'ú›Õ~ap‰˜ï~o`h _œßn_±rþv°ô­ìâ%^ÑE ÎJ D*“¾Rt¤WE#,�Ã8X¥ÚÇáÓD<ùš0 V¹�Õ½—dâe ݸN* ,3,2_Ð,ד]+œL=QÐH›•ÁìIât…¦�sÛàµ_Ï�Gò=Óµž ' 1_Çò0œnúxÄQ¿ù®MU�†žžÊ * ÉÈ·Ïy®ÓâÑx6gç�Œµc¢´’ B„‰fG/�àÓu…-ÀÚÿmÜÍk«y�86íÿ¦Ôl{ûb,B‘éŒ)!òŠ+S¬\‡¡¸3ZÇèšóùbKµò~ð4V¬ ¢(40RIpø=$u3 #©}(HÕ¿ÏyH¢°ò´î¨í¢QC¾ðsMtËn¼}P}(.¦ù eì= �èS§GVÝÜ_[ª3pØ'}ó¶qoÁhÚkí«Z�³<<ÝÜ’´ÿˆf˜õ”]®¹Øˆ–4YÜ÷ £†CÖðóñu�âµ§ÁC_Ð×¾ˆy[áÓ•NIõß½nßôm|Ykú;:¿øNÙx5ú8#¿¨Eþ6ÁúGÍÛŠ¦‰} È?ªRüÞáÙ£b-�%[õ×J7�Ж./‰Bx Q „l‰*q��ݦ ûK«w·èF/'0h¼®æ5µ� ²‹MÛ<‘‘69j H[Ÿº>Ÿè~VP,£v©Åä/j”7=a5‘MÇR~‹<–b}cÖbãŠ8x±©[Üù’^GHq�'> ¸HÅ~ ùV(Ønñ¯ýÓBg KÈì1Ž� §Þ¢ò�~©¦éð^Æ®»u*­Sêe $ç8HDJ·èOY¬r‰c‰Ù^+ø›1êÒÚà'<èÝEð_&õs‰CðyOgÆf‘=‘3e ¬ûxGµÖh ëì4¦<Ö9u…Ã3–|kµt‹òŠUžCA7w<å:å[iñô ›:ð§¨K!,…Ïq•W£´Mø?k7�`¤ARè…Õlçõ ñßÁèþa~w�dÕוá‚Bê§’–_4_}ð rqTÊg+„+cn1²š‹{üà µq!Ûh"ÿ‰J¦‘¶âfng,Ñ€\èwêm€+HÔE“皯ó C2nØBÜ<§ŽÕ¹ßœ¹·n9[î�†¿´NVã=<Ó¨GI‡f„'ôJj™.èéÝH ý&#UÚ¿´2ùRì@͹†ÕБó±Ï± ¡õ^Ê¢L­^R¬Y÷~xÕ‚CqÂHL»b«êlTvØBǰ?.׋ÝûÕÐz¨8a t½Ù0ÉÒÔÍèr»õ�3ÑËÙþY‘–)mñ`~¢|‘l¿{ioiQÍØØR²wäì�I £¾|%ò‰äÖ•Û.ÊÆ6I}<|‡?àp¿Ý“æbUÃ=ÌŽ¢¦/E/úÛõ妤l¼M© š5/È5¬.òž „g0¾Ù(Õyå]�ƃí€=@hB÷]óV)Û šÏÌPDÌF®ì‚T­ßÜG¬Û!+¿YÊ¡µº¶Îƒ:ù­�V«PÈ«d!ZÔL¤|ë Sƒ7øP¿N`žuËÀòíG–ĺžjûCøkí ï"Uè�ß Ù ûc�³ãÏÞ°@o‚ô¦O®°·Ì÷‰ó>×—:¶t@[MPËœ<гEЄ.IÕ‰Ö…õÉ�ê¯Ã.ܸ¡s(“ø’nd’¯^âø0Ö:®š8Ñ•uªQUÓ¼†^juªº³)¢Æ0÷F„÷ÔT–9Í-\Äöy÷é´ˆàC~™îøªæ†ÀɰÕH›Q']ð[Àb$œ�B/×g鎊kÅ;É$¿þ�J3nE@·p|ŸÄÿ'§RHNù •ᡅ-¿ ÍÍ7xƒ4�·+rá‰ôÄRbÃi]wɉ÷Àâ$,x¸e¬�ÞõBû…­@€¾³¸s”�³‡[-?¹wȽP%ÏSo¿ƒM`tO °à7l©²y�ꤒ”èáuÏÇ¢ñlÔü€@ <\º´A"Ü¢xŠ+UƒP›4²Ýrä2¯]º"Ze¨‡ÀzçLoŒ³fÑåfUÏFáùoí“èbØ=^Wâ àKUù9¨µ+žáþE =wª®‚31^|Mj³a¿ºN ¾�hKtÄ,޶²DkÞ9tÖ"Z†Â§PƒTGNU7ChwNjÅ™¿]¤|vT—°1€F倵e£ZxÚÞ†ñd¯œaô M‡ÍK oÊ5É@£ë¢/Ë„³ÝŒô?oèë{ÃÇt•aýÆQÂ+´ G;xL+(ÉV'’ÅÌ!Vz~A«Å�ë¢ogNÒQ�¶)‡â$B™fæP—Eª;‘V–Q�À¤ °3a„ç´*,Œv@ÄÌÉògððröðÃä¯ ~‚n’®1f®º-§„ÿE}{áí?Eµu÷àâÐú1ˆU-ÄnÖO^—;~ÿ]51ÙùÁ…<¨¯&¡@îÞëgƒp0ÌVY�¬VñÌ#¢aV'&ߊ£—x#À½�JZï÷7ywÚÅ]�Dl\æ›Å;aqš^ûÁHÚf~µ¸Z}�Vë.'±h#¿¥½Ú²Ù.8¾Nì^lâ-:—F€}©ö�ÜŸ–�Û~$á¬1+I vê_¥6FM÷̪݄jIÈt�T¾ðÂJ BºIJŽ‘ <Ãõ¸—7°"m­†ÅÐ//A\|)1ëñ‰8‰š«¸<üWAþƒñ’¦Š¨#(ƒyøM¤ÑIx?" ÃYjƒöbÑ?ÿÊû�~ ÅÍl*�8Å:º}ãu×£V&c¢€#n¤ób>ñÇ×W1)"Á5†g1ÑÅŒ6‡ð|¥¥ž}c¯´ :ÙM}HY¤%r‚œTÚ¼2�,…ŒúI£P4îLm8 ÷·�{v–`Ë 7¬›°°½ÐM¹ËFç†&@,ÍB×—ó?Dܪ]fCâ:âùðdµly ajL;€ö‰RÕ‚æ<ë¬]¯0Jý¤cSeñ�Ҭà #�+Jþ{…&Dojð(ÈçáªÛcøi<PRQôiYi/ÌÚ Ÿ½A&æg&³<˜ª£\£Ë¢BO|§-ðêòaJÅ÷ß®»ª?ß;ò¤Äi“…ÙÏcYÊèRbúuË w»B났V:�~>l÷6í}_Ý7DœÉJñï þ�PH· –D� Ëøÿ«uÀØ€´�üBøJO<ëh-«¦�ÅNv7•{b{g‰æþÈ hR©C#åð–œñ1&¨ÿÖFã�/Qͱ5>ÁL”´I–E[׿Mk¶¬µL:ƒÌïh{�ÅsÈk=ž�Q:úƒ¿Âºó·ç«¬GSuø[3}’M„J°&f$‡pqÞ¼ÐLØô»Ÿ|]2±»' ‹•:q-�ÊD^`^üM€×ù±·«å59ØÅ|æ·O_‡H®Ï0;pàhq9"Oýôè+w)þ;ƒù¢tÿ †‚tÝDö·ˆ*Ç ¼ÿÿVN]cH.‰ÀeãEH [lÄíJÍ•ßøðß9¦}Aô£T^+^,°q­ÿÊ»Ã:ßf…¢�^€'vН1·Áÿ’‡¹ïÑ]ä·%½ƒr´4ªmn¢·s̲5§ÁUî¦$ü*ñM�Ebª™ë¢ÿÝû2º £ü&v†X�ežm„ú§7‹4÷“#i¬¯óC'‡µ<š{Iš êxÀ,¼¡PŸí½Ìr9Ϋô�>ÿº@ðŽfcDCï—õÁy�Ëš?þ$‹æ¬$DgPçr¯e&î?Õás2Ý9‰‰°Á'•_'ágF8»?_¡3æh¾Zá¬z†”•‡s QÞ`§J�>3úqáýJž{ûí8ð‚Qðìy¨Ö:¹\ÜÁ.‹§�xd<¥OÃy�ß|0šo”2ÖW†Éëþ‰Ï7\Ð 2Ìb%Òr—³®pÊÁ;búãíÿ¾Ò*m¥¡:ŒTªt$þ�ehìs¦öa~מB>²ƒÍ~p‡ºòé)·v�>¬§.¦x+d2¹k#m¸D²—½¡ý‡Å€" séç}Úxíè€åa/”õHïÑéSe#_µ!žlj½ƒÈ²r× w[ö¤b°N•+,©‹nÐî"Õt7®ä0ê^ÄqV™—Ì=•ˆÙFÈ£óuÿ)èUIþ e{Å“†nšæèöu³ ›%ã•e¾Z¶h«´ bË5°¥–¶F»$G\ÑDަÈù[a£TW ƒÖX>ªU rÞú–¼—ðêIç…Ìk�ƒß¥b7ó×£„²q·$1±BV†�€¾HÒ©Ù§žb*Gÿæ>€Õ~ {ãâ%©^Ûñ»V[ wJ žfW2G)|l½ c¬.™i `©Ã²ìû>@ 呟èÚˆrïR^ ¼�# O‚¿BrSÞUáztåzK0ºë®»8à÷õ±&RÖ qÛ[5S,Á³P %QóÏÛNïø>7 hª¦-­ÀlñŒ´�Q'—lŽ+"aðAšdIá&Sÿò+üwæÂ2©í¨²ÿ‹(ÿn³Â%®r[h?pÄD ö.À1fˆ:Yjx@l­Q8i-ê§P:€¾tpåUtÚÐJ{Õ0�]CÊ:Òê¿ß_Ú¦õ»1þ©@ “vC›¢ä£ßë# ÞP¡øîwÙ¸¥Pñ’ûoódDO�NCå­›‘m»ÜÜ(�=Mo¡‹Á—E ‰ã˜,§+¶®íFÌ×kƒ:ÄêõYY÷÷u7’Ïz"-^ž$† YL(å$ Õ3Þ‘ß##uöXõxE!}Ašˆv±ÛMÍ쇺ÍÏâwÇo}9F¢‰yìÀ èÔ]�—:!I•úúG”ñv$ ¡Nº‘fS>lÛ-K!0ªÏÈóÖ»çû‹º&ÈJ†N¡vÍ9†€ }ŠXr²*•/þCͩݶ†U˜»ÞÆË-ƒ a TÐÝ;ÏæÖ =r7ÑfK«)õú9vFë³—W „~€;žqȱYÅX#“~IÆáZ²³™þ)ßÄÁ£‚%Ò‰ÜzEíºrÿí«˜¨¦ÚN÷3€ ò‡¡4ç¿û%ÙIù½Ú6�Os7ùÌN�2ܺ;ÝnZ“†jkf°‡9Vm…4ÍÁ=ŸZ�À»:º;µ©�Áä™àZ½L°{k0YÜE×Á†r¦þFíÏÔ›¦êÜÝ.1¸€Í~]`ÿ"Ø-ÓŸó6–·4 6ÚµüìQ€:”ç}\à£%Ù‰d€ÑS÷¶X¢¨-x·ËäS’ ¼ý{% µº4%xpA@ì<ˆ1aïwû³¨0à¾÷Ñožª$¡×ýq2|-y)[¡È0õn£7ÒU%F7 ]½7Ÿ{�²úw Ò,ë<¢Ö"Ð:³3³WíþS‚(§G0ug…˜÷åÚÈNØ“/Ý!–&êoî0~—ØéPú7à[øc€5°˜Ï1VÕ*€�L¬Û@L›*€ß”²Í�Až¦$”TL#ÿ´ö¬§™Ð8­–äûi×CGõ©ŽS„ݨ‰²ÇßI‡Ý cág  �nrF„ t|‹~^f´c1©T}È NSç˜ïí¨)ûsõrÂ�ÇM«çã\xr«Mêär Àš«3[¿ö-íùÈ¥qyC»:¶„Hÿ¦X‰“žÅ)ÿ²˜¤$ ‹Ÿãö}ܱ>âÎîÛ¦–&FòÆÔL 7�£‚V˦Ÿ¯“ià0š¥€]€àSÊ8[�¿•@+7i0vóÚêÓî½ÿþYÄЩ+E©Ç†c­gr4 láͨ¤[»PSÓz[½–À‚s~ W–•@Mú!vžÇnGÿ›¿µù´ÂðçN«Ñ'Ðð–§ =£@7U2ÀQ­/Rì3üàò˜L`ä<¯�Ÿÿ4¸2!.«½JH"[+ª;zÖþçX;‰à•+Ñ+�«@8ïÛlŸóÃ@¼ø€Ð"AšÉ5-dÊ`¿ó º‰�4`vÝ×T‘éè’ÄüÆ]kÆÐt›Ñ·å³^šסìS³@=×™™“a ,[r4QÛ²cþذå3K‘Á¹Ä L }^äªÅ2]õ§h2ÁÂq|„s<_¢ë÷ÿiÌQÃíÒ²žïZ·ü‰�TX!hÔõ›IÁPW­¢…�lj€Ð,¢jµ§U—Ÿ2HqÐ̧–rðv–‹†j{®¹âQR&˜øeSzí±ÛWƒ\eÍÖ¶°uy¨-3¨Ô–Í®‡ñ-LšaÓoÑ=jç>§ºGánÁHÞXã(zTM;”Sî•ØUtÉk„¢—ëÏðîÄ4„káI³5tÆ,|ü‹ ÅEjEÒ@oAšëMá ZÉ”ÀTL+ÿä@ìքǺ@”8©ì£¥�1q„–ÉvÐ9 þ3ÀŠ;ip“¤>yÿÚÂÍÂMôRÀÈÞ³_$%º�"˜ €ä±“Å�Å™ ö&·NM�¸Ì}µm�‰>v:ÍЋ\Ÿ¯=î^]J?Þ�lÁ�i�†p�Ç>$ù“uÎÐdÏ�Wìî¡m¼Îƒî_ÖÉ*„ÔùqÐÝÝ*ÇŠ€ñ{Fð¡þ®Äóó°%*ßÝl®Â’_pI�z—÷Z¦¥Þ…â·ê6ÕC'GÌ(ZItäœ1ˆ#žU÷fƒ©üÍÔ–-9‰þËhšJq»{¦f·›¿‡Êy¼p{)F›òQcׂ�€wåÏ/·¦�ÌV¼4häN¬WÐ_ú‰0ý µ‹xU€ó-fÃ�)áÄcê-{ qõƒ· ^V–‰r—Cmç<Êâ:Ø{Ýdo7e¹›��5„Šå$<.9òÈ ÍŒ¿÷Íj·�#N’Ros«Q¾_{(KCpïåÖ­7ýat�߯ ¤’@x_ ·4Xtè&öØÉ‚T‡¹ùç� 7¡XˆÏØPðE„'s¹JÔ&ŒnO‘ïÀÙjz�Æ„‹L!ˆÜ¸°Á#æç„Q3Ñ6Ô>„¸iõ㈧'þ£ït=D�»^¿÷/-ñÚ¢‘ÎÑD š�sC =(å_�Z�>íòEhê$Ã×…çT§¯x¨QT•Ôq£Úv …’ʵoÑb:zD‚ˆmÆ’V °ŸVqýºíªÉÑÀ Œ|ΊVøKXÆ&¸½]ñ�áðvèIrF;+d¡lÑO• êÎËTØß×äÅH¿ê)^àù\Õ'–~�È&nµ½BžÄæ}u•¦!;ËrM‚M+ºD:snܯ;g6z§zªëtgó“€M~ƒÚã²ô�røÄ+z¯µõ“É©9Ôwª£¸càUýQPëO�åÍÔú"Ý”¨{Š�: QjŽzƒÈü`‹$B·|¿�oÜC.?yág¨×?~[P ”E§D÷«Áß8X{%gÙ‰šD¢ÑÃmm¤êÆÕh.—GòJ;q*šc\¾[ôÎ2ó›c<¿î:¸õP Äú›i�Î4‹ÿËD�”;}ü;Òò¤³L�ÎMw¬ì?Ÿ07›å0|œC–„pï"²†x\CVAP>W'I†à[cr k³¹ø»å^W¥&M‰jD{ü¾}Öy5º§g1X0…Ó=> aCíÞõ”|tÌš�Ó€º#²Ú�¨™¯Ž+µŸànô�›¡½êæû²?Õ¬ß=_-¦�Ù·ó‹‡bÑY ùÃþ6&Ä\$ÊN[,άÄ”ÈÞ{7Äœ¸_}fP«…€uǹ%,4VЇ:òåòO 5í ët2z*H&­ÔÃËjp‰Š.�¢³F–˜_˜yTµk§~AÚÅ¼ï† ÊDµâŸõ!¹¥»Bbu�ÜA[“{®‘š]ïG’U ’“¯ß€�ÿ¿ ¨ŽµŒ»lÔþÂn}Ohô5¾=Ç#þDb½j5ŸG°ŽÏòÕÙ÷™ŸÁ9�Qk)÷…)f •#mX.ѵƒÎŒ¥­Es4"R94s·æ¼Õ°vƒå³áäN+Í¿zTø§‹­ 58Œý˜A×bŸTÐí¸Æa‰†H‚ÏÅ/Ø�4ü! z¨6þÞKº)äM‹mŠ-cê0 ÔJõôpìÚh¨/À›bâο6$�Ø´ùK/”_Ú>USÕ�îfYqR~.Þõš}O— Ð%VSÖ˜VodÚ’5˜£Þ—0 ü¸P ˆ‡ïùHâ½/s&—æù[Ž´Û !e‰7쬀.u§4Ä~£t@ýÉ­ö2GlÚƒ°Å wXVÐ À÷ÄÀîzL£ª•BÆø>°�S@‡m”IÏNöîa×7±ßGðø’´Ù%mrì’ïý 0òùÍtÜ­¥í^,dþ/*,ѲLdè÷¿È�Qa½‡f~t\h9æ·‚XD÷Û>辫1×B­óŸ .GÿµÒûˆUå{,žd©T$—akS9àT‰T¸ ÔŽÚ„ÕÐÀe \ªKà+þA"™ue*òß°¨·†é}ÛàuWqî‚çí|^“Ó.bÏØì0diG"²¨ŽE¢k‚ö)fð†„ËÈÏS·>–§³Pºˆɦ6ÝÐuHïlü�«°¥`ÿÀ2!;ú¿¶\lª»Gò�*„CdmÚ¤Ñò÷¾ò`¹—d 2<ìܰѰAy¥}Qò ) Ug™eµGŠÓ»ëô‹¤WKÎdXN¯$ÚpG,Iç?Ú�êQyª LA› Яç@]I^ã×+ÖÞ óÍø ÙòÅàÏ,$á@"E,â3 ÀÚlbŒ�*`¨éóßüÓýßÈ‹~Ê—&¯oèktv§Oç‚çòc�jÕ®Eï;l¼“ôHbý¼ÓùgDÚ¸Ž7¸[à'Òšwh+r?ºú¡êœ·yy|')ÙË�õ_Ã$xx—ª^†qOw˜¤ËT}Íì,P�RÍa9Þ(ô)]ÁqpŪKzT‰jŠΊéz†lX ¦3ÿ]¿ü˜„.IÀnÂÛ8JMXø´5· ~IqˆàÄ¥PåœÛ¬�;‹¥›�&o?ü´~¢Gdo¥:vÇ ¯½ö+� }Úñö)¹ÉÇ×o‘µ÷x€û|;€W¡¸7L+)¢EOÖ#"ù°ýQÂÙpM(‚Ùýù­»mÊج*¹z¦’#±tqJ;Ùaê„èk”uTh:v¸ÄxÚé}þàMÄJzíìL½p`Y¿Ükoã@=ÇÕ­»ê,§]Ùì›uMèä´NöL-±¶Ð2‚z°£¶‰#hž•‹¹ IŸyM³Ý9Øéd2ÎþŽs ©D@>·Höf…üõ�é$ÂàmQŠù b†ÌªTc^N·ÔVN£ö-ì'6�àÞõ5ÝDE¤j|¢{iVËm®Ê1—8>$M°Q\Æ".0hØfmf1-»îÎÇÖ]6ü:5Sö�ÚÉÀÐ�@�Ž­³úõå3¾I Òär€‘PRÝjˆ‘Áëø?ò² Êà Æv•|Œ{ÌÆë³8y”—ð‚ÈIð»°óãTðqjG°‚`r‰ºË –EÈ)‹�›UâC-ÈÁ¥ÿÈ´ÎÌŽ¯ŠËØ_OŠå ÉüP{µÒ [ñ3lûoºŸ[Ê–jtiNìBÞÀ B=Z¥R¯‰Çë²*¾'GÏ4�G½?$H}PÊ;ëþÛy‹è �.Ùâÿs3‡¹³õÀåHÔ¨­Î¼ñƒ?·B¬8ûìªÕ”ÿÆl¾ñaôí<¸kè˜ë7¯ÿØñõÏñõ´ÇÙ7:!@e¢åéYäÐó��¯°C…³@�ãÝ�}÷ŽÁ\‘ÍÄ-ºs�ÈÕº?Ô&à¦}Âõœ³Ëêr%”ÌZÓ÷þˆž °ü|8 ¿Æläh’MD+‰I3³°»YøBøêdk/Ãñ5¹ÄædÄ‘c/“³-´O󸱄A`­—ÈïÄob#bÈ€FƵ �×IÕê@&4óÃ9ð�Œ&êî"Y¡.ñ½~É-LŸÍêªé|-Þ1O`ÌŽdw8èYð²ÏR ¹# m'{‚•ϸa?ùHNlÌB•J�õMÁ/rm_¤k*/I‚Nv~Ñäþ ÑÅf\rŸµÝŸ–«ÇýR‰ÄdèÞ�zm¾-ve˜k>é�…æÏ²Ìý²µo”r Ä:~õ"òî�eÈ·òœò\î�hNIë¼líi�Kï9<óžz_ŽsªVó^˜íþekfâér“¯,†Cá��ã»æóük¡‰û¥ ^ZEU ó\�Ïó8k–'Šl“I*‰~•&˃Q8 f*`‘{`Ù_ѪW€¯h“pSáÍžj&ÍþÒ_¥:Ž2íj' ‚8-g'N_÷‘�±•«$î“,‹AŸ”Ž_®kï@²©'�Ê?Í–�AYÂL8¸¯«†¦Ñzs›mŠ™ÉÃÆ­œßråjh ‚ÎÂý‹ë5(ªYá(®Œh�eÚržT6÷còí9¸ü€¯ñÓ�§|ýè#wN£JÌÚËÜô" }:5†çù Æ{ÆÆ_rëi‡ˆ0äK©$ˆ�C_1Bãn]»`+×àòr#Q�®Á ü¹=·ñ"d~µ¢KMyn�Y5’òW�Cç­%|ãV�Œ#Ú ™š„÷ãpo¶Ø©PìÂjóíµíæ‡Á¶qN<â„’ðVâž+ÛÅ ꛮ'UJ[Žez3ú5øjë�<5µ/Í•§Ó ò©Çï­úÐ@î5s—°„í*D!Dü!€;Š9Áê-l²GÜ;[K­|^ï"œÝdV/¶•#¯Ì hqÈCæ?ˆ` ¾ÂelB3]þ\j��})ѱÚr!ž'ë×®í«ÕƼ©´¾ÕߣVVõ-! ÿ]„ƒ,Ï?òŸ¨ÒÍ’švî6ÖÒ}Žæ¦ �Ökû>ŠM›ÍÀ­÷™QÏt»g✤¼ �oø"�Ïÿò~oõ¯Ô,9¥½Çëæ)&Õ0f¿^¿; Å^+îºß¬6¿¢®ª³>ѵƒ›ÀŠ-÷Òáu¿СA3Sè›d¬5¡¬¸•†ÔÞ†ûhr5Èø¾Üáʽ&mj|Xx_�}lBó[öµõ�k%�Å…XZ0@§™ÌýB�Áíz¾Ù…vJû›Õ¢-2"S8+›.â,Š{ÔèW2K€Ü:v°;ãoH§å¦bμ\/žYsÙ<øU�NlÓk[†âC“âMKJÖ°ïä÷Da>O�pªädá>`8=ó;QÑÆÚ(Àè›�â< 8ã»}A\øóÊ_t¥p¹OêKšY�[®¯xÚ-¶.ˆ”ýöLVq0÷phŒDÒ«è�º•Hñ\✑¶‹çã8¾àP(†žFy ]ΓI�$3¥£œT…É=IJ6¯JåÉáˆONžn,ì7$#Ï…#n£G¾§é T£ÉÈótVËGa�œîXdAmLf±+þ-*&»ˆîãê¥!Äk£…ÎeÝ!�”fù¹´=D7`ÍŒˆÉ[§à~¼»ë+ù�îÑðñ‘É¥Ç)½K½8m–M½üÅ ú.©”ÑòwµE_W½œäx=+ �>}jà𹪻ñYóyUG9é×°hm{´SHš¶g‘ ;ubl­ŠPîZ`¾÷A›0Má¥&S!Ÿù6*‡�‘à p"ŒöêÃû+€ ›š«ŸÖŒì£½äÎô�Nƒ—ŒúK]Ëo‚˜ £RÀ‚ÄÿSY&ªS¾à$nP(¦d#~¿ô×èƒyññí.ƒWøl Jˆ ¢!ºéU+o+?Üì�†r,j‰ÄYÒ˜ô›*'W„5%à'sLkepÔ>SfàhZ‡w ÀðÉcŒÓ×Ôç uï`¢qoÿÉi—˜=rQU�mù‘8à‘«¼Vù¶FŒq|ȘqØmŒÓ�y/`Müq³ÚŽÏʳæû%Ë|‚‰­–}ü¦Õº«q¢<Å·�·E%†º&[3 Õ'3„'ØH£—ÿ3«V}â;a ¿Pm_õÄKq‚y ÆìŠG9ÊÀÚ°™¹Êô·Ì½úÖoaáØ¢H<ã�3† àŽùØæ–Lo aé‹°#’¯¿÷×ö5¬á‹�™Ó´ó]ÞqA÷z«^™™?«›á›T.¡º2ý~ õnúó~—B�tÞ²—8'Ú~D…!lŸá$èq ¾ WÎl¬òPêш“ÕOM€Ö¹äïÃïî7NßZ¢v4ì“­ëhnîѨ®%Q¡/šÑ Éô*�s'•Y00j;ÓóÈ€÷iÕ +F|»'X“(­ ø4´ñȨ$JRÁ�ȓ҅‘ûWÑêà�SØTnh6‘à¬uœ”>¨ oŠf"ÜŸ68µûœ¼G$Bõ�½‰µ O¡—ëz8%„£r"ÌF6ýZ¾¾wœz¥Ñâyœ4\ W˜/aJgi�î­ÙϹ ”Î:b,*¶ù>ìf3ì÷¢š8¸²c 0žÃJÜ®Tõ†$�‹èÒ‚§¹9Ïôþ´.âzþÁETzøLˆˆ�-µ[£×SpK‘(™°�BÒ�!zÊç BÊ~Wý¬ú¸¼Q—|±‘U`‹–¾PÜÊÎ2ý³Þ-œw¦rwþ´Ÿ\ˆI×f Œè‚Üv^tzàÞ|U½í+0ËœÑ+"ìx~ÄQ¹/Óã‹§Rä£ü¦@‡7CÙˆÝ ™‡ÊO8Tr‘ ªÞÍ™R·Õ©àX fô A‘“ë{^C‚õ¼5C°¨©¬>‰Ù¥†/h"Z/ Jv×àÊ!7ÏMʽL¸ =ÄÒ{ 4±ƒøÅ€ôݦJ¨²˜Î#…ò• k›@{눘îB ÂQ"‡s¬Ž™[jwA—1gëSç Â#©Ða|^¸xÙ)m]DzEìÓü½¿ñ# ×›jñæ]q[-¿ß%H¡ ,.º³9�™2#yœ-6RØi–æ9ë§#YH½�þ¿ÀFK“P,}8†ö)ôÄ�–b¬éåûÀs0 Ø‚¯ÜwM‚a¥:�ø›Ì` ´X^6“†ÛŽd’eø‘{›ƒ©­H�¥­Z¼ÿÉÏ:lB×~÷lÿŒ¯V‘|y`bwÓ®‹×{±ÇRÀ*¸ßïx³=ÕsÄ„ ,|6hpêþ~@ û×`_á°”=L(,–0Qƒ²Ó"îO§­i|t7S}Á˜Ew$T/7ýœBÇ� }î -‹¯ýú~äÏäöOF8ÑAœ§Ûó^~YžÀ‰¦�ÒÚ‹øµ1¡áÛ!{ àf9‘“wAˆ&«¸’ zÉÑIŸZ$3ÀK¿gÀh$Ë3Qm� ÿ×[sU�ÍÚ½žöˆümP…}=N9¬ôØ}ÎØ¯YqÃÝ A[»ZºÆÂ?±¿÷' .íÊëLî�ìÖ¬Öå!�ž©û÷o†=�¬Û½öu¹½±ÐŒ°mÊyþw£¿}uŸQ"NDí'€í÷Bد¸†Õ7™âðëÀ§Ÿî{Œ%,ìõ�3Fz sÛ¯3gÝ„ìÅEø •Ï2aójò£H!œ^²vÒ¶ !eÓe4¥KR~i޽eB³áªè[/ÍK�«~Ó_GΜ¦¥ë8œjZ÷†5"]«ÂÄRÜú0>M,'”Öå�<3¼³CðµGcŸ³2ÉÊV„оX²ùfÄ'úÛl j9¸V‚†í&bû︉~C߲࣎aŒ‡°?Ç�Óó@.U=ïÇøä x)˜a‹¬ˆâPšûX‘lJ25Oz™©õH7€l-äÉÏöD7š33Z›ñ öÙY!•èqÅ“ëUí&Èý?÷bÞ·R9€¡ÙŽy‚§Á>~ojè‘>ˆÏ)¡.¹.ÊìÝfÆH°ô‘«‚dtïa¢Ä§ K�ÇIô™iµ1:ûDÀ·Šù³Ã ukÿ�]*å°F¶‹RS�qÇØÃ¢íá€Útëx ¾%È>ëÕ¥e7äÑc‰ÂÜ�ÌÕ·ö�ó¤PèYüGÄת…[\ú¦IÃpô‘Ÿ|BçKçG”RRÐU¯Tñù/ A‘0Ì´¦€äήb7f©x ñ�‹�ª�ö k®îzÏÀšp"Úµäè—-Ø„D(‘}×t>äþ©¢DÞž”‰ë)Bžy÷ÅÀIŽvsŠÏrwŒbÊšö²¯q¼¢ÕÜ.§¥°"<¥Sü•ãWSA>³D²?ÂD �˜P;0Ø’f¨yϺDD³“ê¿¡6¶H פ±B.£6B?Á_ þ"­WmÔq·~â‰�@iC8ù7ç32줃و[ßFˆ(Våè>—mÐl²jt8<2È*·¨x²èóC‘Øêg@É GÚ…þàlUS¼qŽ 8å ènÔ@üµ*õ,(d…•ÁËnÑ�Q—/�¨Ü^éÛazëL˜on3š,¸¿�’8C ³o¢‡ùžLö¨€‰qE©�查l :1sÑ×Ö®Ö{* ±çìð¾ Dôo?®’v@°¨ Òq—ô 1ÂV!Q,3£õ`úо–d±˜îaLÿ�¥ûÅ„ÓÊ;ãzã��É¿þ…µ)ü–ø$ü‘uÔ“Æâ€9¤QÒO¬%Ov¡bøêxÏX.ÿ~IÄ‘„œ±Lh2²Ui…¢‚$]FÉ¥Ó!RUqhMò@• ŠÓ·Åª«ËȨr¯L*'ƒº‡�7ÐÙ¬úX{ì ¢jIµŸ—%Xî!y€S°ðCãC7—§CI�7º3ªÔŠPy](øŒ;6L i©;mÈF M�sTØ$™jåP¯3ÁðÈ7¸ÐÚrñ,½[3¿?Ø2Ý^ø Ç»ÔÇßläÇÏ¿ŸG¨Êä~95UT�K:ñ´ÓÊ/ÊÿÛ0‘5C3@s…eg²% ù*ñ™×žT¯Z,J{-¨J© ׄQÎvh¹@*Ø«<6µã§9'Èr×PQ­\zàÍõÉ—�Z…”gaÍùçRÏ­Ë}\âª3¦²�Iô_´Áz.e�Æ]>hQÆe “?¡Ê¯A‘¹½´”‰íWc—rºÛN;JG3^ÿÆõL)t†ÞQ4‰øa»\ÊnÖàu¦8Kurß•—à[›Ú„Ž ÁD2N1ýÆUŽÈwÃ/jüu<@jˆ7HGõÛôû:.ÕúØ ô7ý¢“`� –þš‰�¤ÿÒÉT®Y‹õ‹“œ©à4/†ù3›•Ûœ×Í¢›7Úù2ÉñªÂÇÆÇÁx4ÎrÂbùï„�;Y�èIFnQ0môø%©30•|;çö"ÿFûé`:ž‡,ç 4åuSà†%iPj äÒý]5ùÐf‘æÞù¸ÏÅà6¿’»\2”2 Í¥¨eÝ#‰H±SEŽx³ÁýÞÙ!¨d•^O’Ñ3˜6mëÿéÜ/ì~ä_n”é¹eÝH’àI8,ð’Iàt$£Í“¦ÝÞ€oË3ë\ÑS*†Œð1›h¯ò�ÅM‚fÞ9é6ƒÁRŸ&QSßö_i³`ȯà ŽŽ ®SÄö쉙1ˆ°Ÿá†á¹§ì3šÂ.×T!JȪ‰�yBªÃ�6íM�ÿ¹Šæ�Cü³›˜¿XŸ™Âš°˜âÈõ ©H‹Œ™Þß6 Rˆ˜tlfÓBðÕ|Z ,ú|¼q-Ôñ=o¸t:3,`ÿ¥í÷IˆÅÐÚk%%Ñ ‚P’“š½1Ph#“;Ýùfâ6ŽUÆéÛ�6=XÂtM�ìÆl�ùiF}C;™Â‡\‡·«ÔÞƒßHDbãu4yeDnÁõ¹o&ÑV›ÑeÍè ëÕœC:ìcÞ*ÛÒK~2HBL�{%Q’€àj©+ÐoÇâÊïs³Ø|?�žaLí:oúô™fÈ”Ö�i8�낳 £lƒ ³¬\o‹dçAÀúMcØR!²gÖ»¤oD‡Ð¨ü2±ÑÕd4Püžû”ÁôJXy¨Õ;Õá$Wv"[=ʘ¯·œ’¤�Ô�6©\a‡ Ëx=ãéÏ­wÊ;VnÚe¸ðõrº¾jó¬ÝA9Âïõcù3×Ô•ÙÍ�óhu¯€Ío›< ,�Ö•Ó‹¬Aûô(J²Mhj¤°}$šž�ü*4àuùñ?_€z¹•ró/:®É"H—6•-JVX‡x6ÕÛõáqòxÒ…ØÊG3 y¤�>ˆN1øáä—MæbçaÉššg>Ýö�WãS¤Ö»5zRÏY#¨8æ�M/] £p�v~Ž±Ñ˜yñ&) º½i‹ÄœË‡k¬# ìW{©º:þ:œlœí°t”à¹g ¼œ H¶‡ ½˜½‘ŸüåWvŸì"~Ÿ{ð$ä¨8ÀÜMj ^™”ÌÛìñ Þ’A¿ÿq ¦"b�œ.Ð¥¶(dBßX|ûJX#2ÐzE-â×6Š�ã6sžˆ¶‹^2jK>ùu{6µðåÙmt*ÕámM”¶YñÎZåiÎ Á˜¡CÔfyâ…èÉÕ3žPüª§\¢¦¾þ`zÜXÎd¦5lqòyýçÓ.íïŸy _(g Žœc]<™ØÚ°@ì*‹ñˆ&Kñ)Q\†T]ïõ)îÆB£2Ê-ñÂŽü÷Ž Ç>Ømžk‡ÕS²êJ$ƒàô°yÖ ,öXì/RsÇ#[ˆ1D´²¹�7= ì¯ßmê=\¨í¿.Lµ s½¸ÎÇ 0ý„‚¼yoÔð-S"¦•Ëxç Û�Ò24ã– ¨oîät›¿¼.mAìÚA%óЩºÕê5Vp�‰ã7�Î,{áb&–pQ­4îB8þ0p:Ý�-jÌÉß8<&&§¬B(%˜‰í��“£�È+v7Ψ~Œ¼ñ·»dG^ÕeP”ßÝUÄíß?<ÏXËTL nÿ´³Ÿ1 ]E½ÖÚ£!øœŽ]�v•ý» .Ìóý?owD�è2=.™†ˆ´R¨Æ‹d¥�¹íV¼ÌÂo;ýJJlþ‰™äòQV5„‘îhƒ”’?T-ü,Õþ!ž‰™ôªRÊRuÓX�S@f/ü¯<Ö¨:Aº=ZÀä-"8Öbo|Ûž–)@RÌt½s~) ÷`ñD ¶ªÐ2´>èu«³Ç'{¦ø<1�.R‹'ŸbõW›—›¶þmÐÌæûÂHÕðø&/.šs^‹ÐL2š=mšk Usí+ë¹I2C¢ON!¼“N€ÂR­>/ SAР»âP׋£!‰ÿ!Ø�®Äíra.ï­Ò©fΗ<éƒÅ¸ ù9¦Åfá:‰-Ó{ußE tüèuù�G‰®‡�ê\†»âÝð²�ÖêgyºmœÒnáð쨲®Jµ è`Z8 @‚PƉ ^Œ‡N?¢òn{8(}ÇSjÝzÐ>ñ³ÕÌá~ÙØÒ—·K;Kd�cX&,}³*´xfAvðæÒ�/&ÔhÀ ØBÕw>„·Ö†f´{ þSZ8‰>xª”7<$˜=6xf%·­Œd Y’Z¹h)q…#Ìã…újÌ�c¦{«À‡ªõeÙrB1é õC½ô-ºŠ³¨-ç(¤„„£4Ûòð1�³Ì:O�OöE/Ï8æ:½þ 7#Øx}ý7ž†ÕÙo@¾ëòbâÁ6%´(Ù|,ʳaJ`°f“Lø­/l¬ª`‘wcAùÓ;J¡—§ýœ··/z†^Ç,ÒÞ–~A#�øIÆçЏä8Â/–ðË›þ)Ø3'o›ÍlÛvðÃ%MDˆ;ÿ”kƒ¨Áã²¥åfZ¼hI€p7xSé0!¦ù ^ãœoáÜßWÙ¦/ ¡öjD“PÑ´i<ÊèÆ�rHtÔ¯WÄïŽÃã´q�ÃY’Ñͦóç•=¾�œô×µñ¾[3"­s „£ö [´ºn,‹µ¥ÔŽHªˆ£xô”Ž<4Z{I˜�aa wÝ~¸)z/IO�¢ü솣ÝI§5@¿Äk˜àœüV”OÎ$Âö‡tD$±Ìì±y™}pij±ñãÖJ<2øWËõœkí¹Y“’ÄyX›Æ³¶P¿fEÆ1Z:ˆöÉŽ˜È©aü’mŸÐ_±A%á†ÌvoÁÓŸ»^è`¼\ ú [w^$š¼1rQ.OÅÑwõ}Û¨üâá1+U¢q> ÝÿZ–‚LTkÔ®6vêvX„íòµ0Ë(ŠuÈ+XÅþë©©9Êïà€­Obü4Fò•Œ ÊlØ<Ó·>¦òórÛ½í[´ÙIÝ NG÷%CC);‚ ôübƒ³ã†¹Ç†L–áÿüÞ©ýq„oà„ˆæcžŽwúñß÷~æôbûŒÜ³ÂV¯[8»ôr­œÏIžJÓ¶œ½1OÔ–£wÌd`¤Eün“ºcBçr.~2˜"ùM7MkªJFVÏ‚·}vöª[ÂG-‰¬ :R¶û 9r§’F,ÛJÆ>t¬v§ãÜê=��Èž¨µº6¢^îO—@×.a;Ÿ�*�k¨]‡£ßÔ`†K‡ßÈ�[ï·BýÛkl…µ;«#šjx$’¨Ÿú0=)uS©s» Œ{LØ+�œtâ�ëaslæ&,À”Û ¾4á„$�´^nüž{®MçVÒj©è»™¶z$MÇùòe?xcц‰¹Ì¶0ºïÉ‚rGZþÛßø”4ÆêŸŠA»ƒ_}ª dö•Á¼ÉLñ…¢Ê±DÄN»iß/N<ZL.¾Iq½{N©A…3?^‡êº�ÐzÞ¦¾å˜¡ÏS“GŠ®VžgcÑFõB­·ï*õýà¾\žþ÷ˆ^å>wZXÓEÏ9Ié‡M BNb²‚ €ã·ï!Å @WzÄq̶áçâ9Ebý/z¦(g“ðÞ4ª˜ôúŸ‡¯$µeÕåv.Ì¿3‹5&·ƒ>ˆü{fï B‚U ¯ÍzרjµŽH8h}ÑAa5”g|ŒÜ·›êÒü+Ee€ÏéAoúJSód 4Ã^]ª&ÚaP$«”h�ì.æµ®\- )îM‘€MYúO1H|ÆJHpºT¸ïD`Ó·´�PèV)¬âh•uhPëìâMì/ºÚèò¶6ÀìAå_ÞÒ_`í3´îûÆBR ÐÉNµé�ÿ|›»p•¾ôYþ�ðj÷l¨`—Wä±Ýq§t’8¯ÚÑ8I@½¡¹š å[›ÏÚ·ƒPƼµ]ýsÀ»gÑCˆksçÉ­°qiLhÚÇÉQ%ã‹Î²2¬f¿‰ª¬§5Úw6KGV®ø*,õ¨vÅmßKTRQ�‘&Õ}–TñĉWnMbµ:aÓü �ù§`;Yá×Qñ$]•® .5¦ UȘg¬f[Tù¯@�l^I·e"�M깤F¦ù™gŸ>ÂF#ÜѰó¡Ö'#sÔHu¶{‹›,„ñz‹�ÏHÇCÀö-Â¥ù :³i¿¸ÆWiûI³?�³²Q �©ÁéAŸN$”TL'ÿ Ø`Ò{ƒböm±VgY /IïóÕ/(0ÒÊ9'Žø=„›wZÔ�-'çHã €‚€Y fs# ®‡¸h=d†6—ÕTØ�K¹fùè] “ßÑýß>dÌ�$±®a£-'eË»ˆˆÕ”rû–™_Ní7žXuäø=W,"ͪâ®â¤L>-Љý˜ÔÜOxı³ÖQ·˜s�›˜­ûÎÇh êý�Wý¼²$HO-ÄñP¶×ð·R¹eÀÿ%ûmö}4<´¼¿]Û½þfŠ!ë�5o|¡äeÎg„’£"BåezIý&²¨ªE&(i<Ý+$Ÿ#d¯XÖ†Aô̹éOy<ªÉZu¼^°/‚dÏæ+k»ñìy‡ê>v�aéÚ¯§Lv¼ÿ·Æ<ÁDö"=Ü )Szj$>.y,vÅ%¿Ë24Eåòœæ[*�¾[¸~÷×Á3–Ûẕ‰ŸP�ª—‰!±©²© ½WÙK`q1üÍ$úˆàcßj3©pw`";ß•K»R–ÊÞJ—Cž]G *›\�a*|†4ü¶|ìuŒ¤Ì1™V²Ôaű©U,g—ŽšcßÚÑÀ¸ «Õ"ù ¥‹xŸm)ÿ Xv³è ñ~~‚é(‰q»G/²š•Ê#ªxh<‚º‰ªýSë«]ø8a€%àI%PõíãMCÁ† ñïPè±H D¿†ˆµøú×€/T`þ�s}ˆ‚(ö 6Æ"Šÿ ô vÙ{î ,¡âŸonGÿ™øuoy’?Ó�ðìx„û)ç`}d±SãÂèÁ]I!(l"Ô=þ;Èr>Òg¦ä™;±&Û¾–ÏÚyÀ;—[Ç «òú;íë§_hyGíïœ,(¦“�ÕÿZ‰Â0ïpo  µ¸*C.§ì­Ì­ (Á [}$] ¸ñ [/e¯½CÜY®Ü�Rwa]±bV©, f �:*Lu ¦/H�â|õAkÜ*^eQvrOš»îCó£c¶ Ä”R‘¼¨ÐþB5‰PBnòäÜAA›q5-dÊ`ÏúX³qÊ>>ÀGÀ¹$êˆø¨2ÖjAîiµ.±Q(„Vש_g‰È*즬@S¼û×/;Â3n£3§Þo=ýUŒ$‰'+?ÓƒÑÓ¾Q\xœ«üv^Ë7¬«hP šÌÖ€9Y˜÷¢"z9ö”œ_4+ ê[*Áõ8î�’rbàN¦…¬¨§ã�ìô?ç´d o®¥2)*²$DÌ©t˜Ý±Á¸í¤±¼{´p—{ª'¾|>×õFŒŠ@ É?¶v„mÅÄfʵ-¢’âüá­Áàä‡6ª�ëCß¡|ÉÉÉÚeÑ WÆÂÔPù‹qUœàæfÅ_[ ô.ÛuäòóV¢ A(ó1~pË7)zöÖl,a@Ü¡ýè‘wBý]üŸ9·›ˆ~@ íê¹_¥•Þ«çtE»±ð �Ðé ”&�™^ýƒ!–r÷”߀P¾3Î1¬MbÑý Ÿ6W„r>O±tv|C¼ûeÆ öŽ;Ã:˜[ñf&Q¸fôãÇQS0g—ò�‰%ÙHw—ŸÜ¡Í‚òÅ0 †ÒyŽÐ™c7h x<_‹úêòÅùeö®”Ã!„ã¡v2Þ£ô¹qœ<¶’ô:Äíë¼I †Èò…¾>æe5Áv�yèU%’4-­;XfÒž{Z_Éžú¨[Óÿê#ú�sŽoNrR&³_‹ƒÄumû�•Ÿ�˜gºÞ��Úc!ŸZׂn ßÖLÆr=‡Ðl›¾6ð€Ò àå‚!§k4²�Wø/£¬ÆöÚúlÓô±u_ŠžˆQÓ±yníØaÚXÊ-,wE”¾;2 yÐË‘XI¿!¨¿=»oë *æ„YHNvKyê¤ ëO¢�Pþ!©¤ÌŸ±-È|ä´”h9(Ì$åÞ”QKà ÷HiqË8ººÄJ~%˜“&!¬ ³ÐþªsGÚ´vP‹£»�:°» �· cxßÕöeû3Gôò®—Yçæö«Ü&¹*.º”TÉ™kÆÖ²q ‡Lƒu“‡;<‘8óÿ½,V+'øÛQ–Ì~d_Ÿ8gø(+ŸûÈŒg±*\óXÁºFÂ\ \Cá¡HjVžÔæZÉ�¶-(=X÷Þò½´ãQnpl \™¤Û«Åtñ>ayîFX»ûÞr£ûêu†Î…‹>¯Š‘ÓÔú9‚¢ì+7EY‘,¿è ÂsD†ègJ‡´eü7íõ…çjÔìªqjŽCþóÙõ+Ê0n‰8# ˜"ëpÃ=òCsw¾W¯bŽéêuÿÑRÓck�YÛ(RcÖ©ßÖ‚Qwâ{r“_˜iØÿhC€ÂoÐ8³•À„LáÑ~r-ðý¨.çY›ÞhgaÈÿ�‰8¤?sH|~Y»€4;‹?–‘‹ ×?y¶ï±'‚@„TFØ*Ư_å!½M`K.?ëð#“HúHœJvnOo`•æm¹iÐÖ yØhWÝE…Ï®m&:`^˜'¡3:íX¤Ÿ Üøà˜0àÙn烞K„b»ãßXÙ�õî»9…Ž¿Ö{ª57ƒ´_…äÖÐÜ;æp £Íƒåm׋_Uõ«FV Ø.‰ØG~)‡ {Žò Bóe¦Ïðýƒ¨&˜ùÈÃ=�?X.à ˜‘u•VGŒO§·Zÿ£³…‹ÍÖ%‰ê÷ÃMÓó[ʓ¼AÅø‰ ¦3 ,¼y‚ß TZÂþÐ)xuN1Ð5MÐ�ã>IH"µ3& Ù¼ê(˜MoiÉ÷ÇÁ ´L7’Oe9y×É�lêr’«É†ëRû:OÙ%k…SÖS3M4 fª¯<¨7ê(ÚCù<­ pTú<ѹüŠ7&!ìyB,±è7ÁÒbC -¿­..ôÕ‰K³yùìý2jœQ ✀ºCçÝ?³OÝÚød‚�|éj@ó¿qÛ[¡×ßæh»¸ö)¾YñˆHaªh´å—¦!ÞWÿ¥F ¢½'Æ ’‚®çP^BEÒqµ ØìZëB¯¸� 3ÿãõŠ)€Â2µÃhÄ ÑA󰀜«¸Û«=¡q½ÅT«ÛÉÃø¹ð=|T#>ðçºynÉÈ RŠ4ˆ³åud@àÙ@[._e“DéKM±6àÜ‚®ýôdLü'ó§s_1+Ò…;@ Š×ùîoŠe•Ý,íõ#hÑ\U÷¤R›‚ÇèþÑ|ÐíÅ êï”�Kù¡ø}F@Aæš5ä“–Cë×öäigÓ ºêž:ÑÔð—Q§è?Q‹xñ0§Òú6�%ôKШÚÞ•„`’Cç¿gîÕ,;e¼€�ðs¾è�–ì^Ž~ݬ/Àö«q¬ºøÚ¬¤¦~íÿ¡Óƒ+5�d¶((¯è™ë<ÒÝÓe«3a™%L׊i&&ÿzJ»�™ƒ§äÖ†©iXˆ*x»$^K03ÃÑxò•Ìé&‚0J@Tëî‰%€½ ýã¦{r ØÑà6ÛæÕ>ŸŸ¹=ç uXݦý•õN Å›­#·ÅŽŽx\gœ½€®ó*@Ës2ÿÎBοxw"-À ~Í"Huú#Ô=¦:žc:åCîo¥¦:UO+,EL <æËÕËI¦M}’ÈY4»Pç�þñl“'aÆŸ¹WZM†î³aÍ)Üží½äå�æ]¹.¼y)d=¼=¡•´�®#ED=nñ}ŠÒ޲¥nhMÞYm"=Ü¥ëEîA•3iù…òÍß-Ðtbçíyˆp‰Ì³„%9à¹vú5ÏTK|nèŠWKQÉð¸FYçÔÂéeí‰ BÅ"f¢µÇ6¦Ó=W Ì÷îñ3­*C.ÜF”)³qî$ T}òüЇ©ëp{xÎÿÎïyA+0vL2ð­#,äÕ$Q–×ï=�‰• yi :ÞX†Oè÷² çûˆ½, 9WbþʳñIÅlíK�L5ah<“q �Ë8a=/�Jû¶ÞƒŒ#2w‘ˆ½«NP)œÞ:|Ñ¢X‘ _ÿšÿ €|%*„P�øw—B8z£¡»’êl�òc]á¡�7G¢å›X¤žHÃålð-i¥)žÌa1°šƒ¡zm½EC¦+È™Z@éÌÞ EÖkü R¿:46_!OäÙ_ÿï÷ËJŒhxÛC)b5ÒÑÒªoQi˜I…ù©Õ7cÚÏÿ¥�N*˜ãDzázœœ�“›h_ Z#r™tNÆsšÂ=Êk¾sZ¦úQX}ž 8¨ò¦™œNQ°buŽÐj1RÜd5,L~z2Lø'̰€pdhŸ� £C—m9´Êþ…=õ®UíÎ L²p‰”òV?j€|bÁŽ¢x6ªW»òTÉÐÔZï�„ ÉnÐè™ 7ý\º»9=‰ ½IÊVÙT!kþݘ-æ^ˆ*ƒ‘l™±8¤4‰ ÑñMCÐø2³e¸÷/Ýýö'þ ãHNq< ¢âDZ»>¬|�êHhi’¶Üy¹¼§Ëب]dÓ�51J­ÔÝój|Sã¯["(þ£’´D‘V�¡š ¡M~�û¥k4)Â9üXÄš—¦á1Mƾ¼AÔ‘Éý\á Eå6”˜òHñœ±sW´ôÁu3¦$�7 «?Ž%ÎݘÆy}&ƒlm1mf¯~ûôõïcÐ":B«)Sôƒ=s`Î4œ£/ÐX$»º3©­Úð=ê$¬YÁপ@.f74&°Y)÷AƒB»û¯7aÅ,~±&Á$†Ü�4*TUmDZ¥õü 4?rÄùæ˜9OnÉ×ËTNå¢iÒ^GíÅ;ê¯v¸ÁTÿ-¯º�¹epÏŽ@zXÏ—`LÛÈÝÉFFL2›«ÒÛÂ9GÅ#Ðp�¸ ¬ý§]›„Ö¥×€|'È%ßùAŸ³d”TðŸ ÞTÞײUÒO`=õ´S(OQ<‚î•et¯Ö|ì”ñh ”7ì�S1¶p®!’š� ÕP ~UC“áu"×,‡•*¹×G¾ÍzÈpl»Ýj!06ÃnÆ1ñí‡J8sê8g`7j Ô&G�½†hTú—üÊ|Ø Ñ+—ç Á¤®ó’ê+¸ZÌ é›ãK2£€¬ÂæiœXfæÁp¶Aâ€ÈyK�0Ì� £�<ÇÐgÖ¸r’ýÈíP™í£FØÛzþwÓß+R<ÐVÙZÀq E�õrMÜëoÑp\¢“€âŸÒiÿ*EYZÑÏ•ÇÀp<¡Ë`x¨€W9\Ôq¨¬]¢ )Yãƒ;n-ÖÈT©›Æ ’Ì©ùÓ³|Îs¼Œà�X8*gøDt™¤{.>�ñ˜ïÆoÚv¦—»]m§fƶ��Þ]ÂYøŸ’W ¬žÑ®ú‚/iº8¿×O·Sˆmf"³Íö¶«#žÅtÛ󧺖g—Ä9…B ˆëTñ /$ªfŽ-{òWsä’׳I<#ز%¡F�b�Ýæ_.H®÷  ð—ÀÅþ€0§ŸÔnGÿ™õHÞ ú–”–Ê#üGÛ¹l&@)Ò! ½à¯ûˆ¤Ÿ…ò…°"Â…Ä]Fq$î#0uy6e´¨]Ûm·7þp2·÷µO×tèÊAI¯$|·�[HÆûHè1Á¹ÿ´ nÒ `ßxX¾&OÛ—kÿåœM ’´Zœg*Ö_Û%ýçN¶ÜŽwÀͲ€ÌÌér÷!V·ÉŠ«Tùó��ªA›Ö5-Q2˜3ÿúXœó¬ ¯2öê¯öXXj{·xª)þ)vqñ'÷)ÿR"âK€ie›f¶‡>é­Ã^à RœhUH”ˆ‘f¯©ì6ýz�‚4×YŸ¢c«¾AZCôÿ굋bY‡ìˆK‹ô5�3âó~a’åô»‚»u~†Ÿ¼Ìüq©Ÿaˆ9oNéJîŒÍD2J”uîÇ.Ó èUÍ[È%úÚ4¢ŽÁ²÷ ©ÈGª®~ëZ“Q'oÛÖ¨"9€ÎR%E¬€9ä¡c•‘º™¼i®ížÚnÁ~ƒÌŠÇ&òçÄ<';&@ŒeW�'d �]_i�HË’¬„ráI«õ ÷ÍÙ«‹ýÜ14Õ:3ìã ŸÄ{È´ ÕFkÄ› }³²ÞS8êÛ×à;9½%›Yí¶\æºùN§Ü3|;Ù/§_?ù v¾MDˆ…Ù*ÀïLr\B„N¥'¥�C=à WŸÍ‡žY…5³Væ‹R½d,Oé.Zí7±_yK:»à9`Hê““ÛðcgÒ-¢Äýðh©†gQ(=Ë>¶yW$Àãe[ÄK¯¦ûö/¼œñ¿<ÚË«_SÔ—L¶É,5¦ª¯„�a RâáÅÞzw3S‚5=mÒAR&QA!T�šÓ°Os«¥Dš9ËXöÿ1ÑùØNèo3‹ avD…†[ˆuÕ´ë! T†ãv�¾u8ßå0?±\­Ôš-Z‚8Ë�Õ·P¿D:0ºË3ëΆßãˆ{ÿ¢±!—Ü.ldäƒÃÇ­1Óð2ÏEÎþT,f%’fšó«¾rwî2k1vá*]+^ßíì?@baP¨NPÁA”Ñ~‘ôhÂBí$>Ê’ƒ¥û“ä„Dx4]‡“ôtJÕ}_’õ]Üe‘æÆØ÷YªéGËëÎ!/m\ c [Ï °!8õKY3æc+ÖZ¶*®¬ÂrÁªÆ½É"]fgR¢1‰T(½jS�¬ _ˆ:Ь¢ÇH@uC;gSOuÚ ´Ä j©"™XÊcJR‘ÿÌ&$º �ÛP»Ãþb• ä µ¦Ü‰Þ}0,ˇ±KL𖦩վšÔTQ²u,›ùŒNÝtÝãñªË%°RÈŠe|€æ“G/dÖ=³‹ Ãˉ#¥R %CN8Ö«ÛÝKüá(szøçS¨,ÃýR¶$?XCxÕ—Ý:ó ^¯™£D#Œ!ººEò^ rb¹$$³Ê^!0ßõZ^TØØ9¶±g`6åÇúH9•·/…d«F¿^ì°á Žâ ß•4*¯z)Ï'yrѺ±+Ã6*�¨N�ÇŠ­³A°R?U}à:²ðဟúš fÀf‘¢&¯ÿ1ˆ5˜ô¡ƒâåÎ¥·?ªåLçûBýÎêYÊÿ´èVJ[£¡^K$±L‡ á¯ix킺±Á® ©QˆãD›tØÛÆëÅÔW_¼AÛ|\±&X¶•JƒÔØRÓŒ‚šÔ³ó}âgV¿ð²´–'Nd­·™à Â{7ï]O›üAüK‘‡ÆþL¹ƒ’“D¡ª Îô[T¤³æž¾‚7k¸ßûGY†ýšê½f³Ð¡Ò ãíÂÑÔŠY$h¸Ý! ÐVÄA‰ Ä¹“ÔÏݯõ-´@ÊÌKöBEqå‹}¸ÖU"¦ ßñ¢À£F?èPi¡¶òûœCÌv5Æ›¤ÿ§j¯�‹�Y¸ÆW‰‰àÍÔϯôç}�MËFÊ4¬Ä2© ¨f{N;æ(@@´û)ÑRåvÆä’îЍClýeÔs n´":CmÙCjψ³®€o”ú¹”¥WAÝIPÁµ©Wôl�?|ùŒÒ£QÖ?ÇQôæÎò¨’Õ•n“„#tØ£ÞÑ_+ûM}ïMñ»$@¯�”{âkÛ¯¡lëaüŽQoå÷É…‰ '"�5ŸÜ¥·LJ�Yñ�¡¼ åŒ+âáÀ�¸t,£`qÓê.£u<5ž³¼R¯Z(Ä~�§œ0´Í ˆ�OA_.a“ÄÉÙOJ›jmJo#þÊxÉ5"󒱤7k[WÁe¥¦'©‹O‘' �V=ޤsºîŸå±ulæk ì@÷ÍhëÔˆÊpEÝeüe-ÿÖå…˜ì¤{þa§¢_MŠiì SCÅž`[î[2gJNQ£ .•sH�mã Ì¡(<ªoÅ߉Nõ“®rŸW)ö9x�t\Ê/ßïh—�èꢸ°Û°'1¼ßT.Û/IŸX¶�ìÜî �3*¨=ò@¾"ˆÑ þ^;¢*S.Ÿ²Hç–÷· 9Ú^†M;û¯,á]&ãçªèTpÑM, ƒÀ†ÂèõšÅÙ—‘œªÀ ,J¶‘}Z»>«äš€L®ÞwÊ�¾k~hÙ2¼ªö³-cºº†n–Š8fkuÜ%0 ¡‹a³N‚†ÐUûŸz—¿Ü  ô‹JÇí©e~ Ôì–É`îP È4>g+rý/™‡2ó“ŠÅS!‘?âö�)ŸéÖ%0=*%¿�Ôk†²ú%¯t÷•G:JÛúS¤ ±[CÙë8í­[E**9r.tƒ×:Ÿrcq¤Ž5u>°t¦vu9SÛßø>¸Î“`èýœFuÿyŽ�Lõ8ÃQó)ˆ#Ñ»é²D虞žÆ‘¼âf1˜ì‡ù~Ÿ/n!éɸ‰û`š62ˆ�ÑãÍîÇBTUUþ‰þÑQ'C—sÄM©Q,×`d  ÔÓá]ÄÞ¡ãS»ŒeÕ þ�U‘G þÞ'×EðÒ|z�Ö”Âé|é$„a?`°òøÑÏ|zz%Ô€„}2á¯0€ñWºé�µj#-Ö†_DwR¡‹{ƧVŠhâDðrˆÞת4%^¼4Îq3›vxícúÚô�J1F]G~·±+3Ï�¨–¬8~té ÿ…²HkÏx‚–ˆuÙs‘ƒq®ÝÁ)½¦æìd�È\Z·Ò7³´Ì»ˆu ¾Øn5&`'x–7¡DÐÙ°Œ4n÷ô¿É?F{t×7¸ÿ‘Â�¦|.v-'©3¯œõE¡•j·ÈOâ§ö•Ï’“SÉTú%¦õØ‘FÜ’•µÉP ÿŽŸßþ~qÜÃêq¹Ù'šCo,ÇwxF"¸-øàÊÐÙëJ§}Q²õOBܾæ‡R^XÞlŸÇÆoóþ¥N.ëÏ6µ 4™\’ưι2²æ›/lò õ—U#Ëõ&æÍ˜¡àv!§Ý,Ùå·º¤·�ì !¢k­,iÑÕhGvMÞÑ$5¦@±c¦ñÔ‡6²šÑå3³"Ãìµ @žQ®qŸÿ3UJ{W Øi\vb8ë°¬äšï–åhˆ*ÕiHÎtx¬YR¬ÚÔ²âÈ•AºäàdQ*׉ë¯pÝL�ÜLø‹slÙRUÑõ±tNß&­© à5$Â´Ž³]ûJo�ŠŠ=±bAÀq»~ãRîß ílT—wØz|÷“´ Åê!,øCú¿Ã.€*ô’qñ8*ãkÀ± œžH›µ’4û±åb È›AÁ$XûRáUº¬^ûßäÚGÈŒÌñ÷(QÓ¯-ÁôÄ-ŽÈLÞÑpÆ—m.—ͼ£ó2‘%±AÚ¼þ@LidßO¯¢ÃTã·eWRßÍ�£§o�¦‰ðX3îLÄø�ƒV°Bšt˜e»„ÞH·¦%GUÖö–ÒFtëø¾øDð—e7–a’ Ä?ÿ„ÿ5:ÈŽK¶�îmb’¶i˜K6$WäÒŠÑŒV6…o”.r[Mg·;UƒFþsul•ó�|Z–YîDæ2›>¤]@-ù�Ö }§½C=FHc޲€q9Ì·!jÓ~xF³2³Å2¹âœÖ‹÷vtð(£ôbé1³~øÀZSkÇ÷@ÎŒ®5äÀÓâô·Ÿ«�Ä‘ÚȧN27A½’ý†º#ø·iÄî/Å[›uÈòŽ 3(“¡i¿Öºöõ”Y“Í&ò||¯Gœ‰L/†v„ ö)–®ï&qÊ,ù•ä·ô�¸e¿Iú'·G%Ù3–$C ¼Ä* �Ó—InŠc'HR«�û¤|ë”ë¾/E°¿x‰Kçz/|Ñìutïò�Íáf‰šmÓ§É&‰Bvf—qŠ'|g7Ú`r \¼5;Öñª¾ØD¶ÊvZÑ�CC½y“aÕ;) l'¦E {'±AÁïï¦u�mÄ%¿z:™ü¯Óp�€—bUTOYø3äJòêìc�,”¼»=ìƒ7XPÒ èÚùyý$ºìŠ\ Û Šblœ%G %OWr15Óº¹Ð)�v±þOU'Æ,{]Æ€:«—j¨ŸGüa¯çºzÀ¢1FSUהּ­ýàÙ.ÍÙž¥?ŠÅ¨ƒÒs™ ;U~eîÒvÊîê/磪@ÏÞ¡/zi¹¥(¦ýñÒîÐöî'›èˆ[ü®"óQ™îvøñ- D7ª„|$è i5#¶ÿ‹«»O?&ÐŽL�^Z‡ÄÝ4•tŒJ¤Y:qDa5CÑ!ºÅ’ò‡Û‡8Ì›p ìnÜL;M³c°%[»žù4<ûÚ08âÜ-ò3½WB¼9h•–Æ¿“ÓˆÍÈ‚è¿Ë­$ǧr¨z‚®±%Ý‘¶SµŒ´º‡¯Ï¤«Ž³ÈfùR¦¢ºáØW˜ sA[ºª»ì™È­‘ëï×ûÃ`‚+R¿b)¼r¥±#Ÿû”°=RÄü0I/u„ò`H{Ù}ý!Û6�j²%_g¢˜ê—òuÑí’T¼ ü“{F;6¢ñ‹þ96ù×¹öråA—dNð&». rÖE¤ù„4)µ�o…d‰(èœÙz•ð{Ií­=,ŒšQR IAZ*L^VoÙ¶¸è Ø1ê·ù›þ€ ¬`übŽ“/œ ÿn˨³\]«}’_ƒ*S¿ Y:Ímõ…hèè.âç¯5r%° üzuÓq5΄½ªt÷x–l¬([‡7*úz¬ÒÒ…ÍGÇç²Ü E™hg¨ö®@þ¤â·Œå†z ˈ(Õ‰’ýÙ©µFí"סQHýÃÕ²ˆWñM[<ÿ›á ô×3K²,pãóëjëMjM�ÀJm¿Óe˜5©`&“ÛÍU’Ñsïß™fµâÐë„(+MüdÔä„SN‚Í(q­A¬ÔÖvˆä?¶¢†:$3®£¡u.wYÆË&ŠñµÛÜ/"Yïí´úàœUW4–»‘4ÿ#K£”°cÓåìé+¡È¢WËäÒ»¯mG´ºU"JÁ(ø†¦å‘šÖ€rêÂ܈e%ÕMáÒªº‡…ÚG¶ ÒiÕ“ ˜§˜VñÍKÝN¸ŸîÙZÿ,8F?ÍÉg|Ÿz¥Ä9u,íÅH¶Ç;g¹ó²|ÈS[UÍÞðn‡È9‚ùᬪ¤bzßÔŠ{E²m®þuB·”p=o¸^•¹[Ÿ eð6%Ñž7„£§ŒN]d¦U$€Oƒz*�» ïˆogßj—Nž4Ûý+ð9 —È3&»vL9i‡t•›v´ #ãÁ+GÒX¬’ÖÖˆƒ¸¦˜fp®ôr³XGy}>k¬EÕ1ürÌ·Ñ 7kÇñTšªêvïƒ [ 5°ýµ‰CSRb®1òj©º`d¯¶ûÁ–"ïÉSÞ.ßseŽ4 �O+PYUx4{€Ð“v«eçc‰ºƒjøYϱrJóújT½tB9!€xÌ&¥_#¥”ãPŸǹß\ N³Ã^·N•Å#>em�:›¨¶ÿÎ'ôÓ�8Ô˜žnÀ!±ðÓ)ŸÿÒ‘æ8)ýþùtÛ ’lýÐ) ù Ñ]a¿c|’D1oHc[#ï]uq¦Åއ¢Tå“åKÒY™§s~³ØP6u°ãô°©9?4Z©{Z't©@›ÕAžÂÿ€Æ»ŒjàS'ÿÊ‘�û�éüƒ)[§§¢óMZ#8UõÎbÛæYEdD=(0ÿ–¾w*Bn`ÙQ·@_ÐÇQi¢\ƒ@ìt€ �½¥)Z½Ýfä_A˜òñ£‹èû[mìV\(t¦m†šP]«Û½:DÃÉz”— õÞ&ü *~— Ê–mîÙÚïbp‚—ÇzjwàÔ Q ïN5•X%ƒ‘�øNkm8\-ù(‡�”"g#K=œ 'õàZ �ŒoS�ÍÚOaFýK‚e+ó°åëVb›ö|æ� Â9ó½Þ_ã•�)ªe°´ q…u|¦sù16ì�Ö˜<ƒ®•Bxã»} IÜ¿ ¿›ž;“¿ ¾yß/z;I,ì6ž¶Q�8‘;­~´8 ˜lÔ@üÉ©÷ñAë}‚®ÒQK°¼»’gŠ`ëùfK‹Î²5UÔõh¥”½ÓzN@ˆ Õ!B<‡šÞ²îÛt…ט-G*^Ö[hÉþ*éqÝ{Î+ò¥r#–i§Ž àC>²s(KVÛàFk ½Š¾"ÓËÈ~5‚Ä÷÷á[@v& `ÅmL¥ü7Ü�-žnGÿ*EXÚ‚‹�®ßVOàÌf´+ÐT `{MTò°èxLP—Ï­dXË_ŒÕjHÛtБª’Éyâ& ¢¢d ¬ÒªèãHºÑõÖ\ªZ ð(30ÈãÌ7NÈT$YÙ€DC –)ºXJ²Ò¸gŒ¶I‰œZ³‹ÖËAtgèÓðHd­¯Œékç¶”Ä!6}¬zã;ß ’m0‚Šç}¬zã;ß ’m0ˆÁ¶}¬zã;ß ’l²*6Ä ñ 'ÿžÀOéZ*&µ?Ôy —�ºÊJ㣸Œñ{ÖÔ<ØsU=åò¢Ã<]=FžZgØõ^=Nn^£Þ•扜ja[´¼·Q—´bXøÍgʈÚ@ À�ø^‡�7AšëuÁ‹PÉ ¶ˆd³êÔ²»-ª&)ÕkxC¯ùRa3~€°§Žl‰MH ô®Oì#JgyÓ°’áò�9tè÷¢å ê„i;O•½œié7b›(kËûW'l¶]>;>ÄÚ X”ùx!¨·Ÿ}1!õ0�‡¥!&‘/Ñjô€´×´o�-ùGrp.ÉÝ5$}`?(QWmš8@ÂtÈJ©¼P¼}�µý¢>Û&ôüu&fè UÐH˜ljXë¦ã ÚËž”aBeguiãzS[Ks�PÎÎ! ìöä´ù€2ËÌT>Ø 1µ'Œm-Ì.:àó‹È‰’±Q?f�A[�U<ŽéùÐO�,|¥Ê_ÐŒ®-�©àûÍꃃUFoËêëôíÙrû¸«‘ߤzß‚VñË8§ÃÛlEïãWcl†ÈûÎìßa8«ÈOϪÂ'ç�‘jö©‡àrÆ ‰îJ�RðN(!r7¶�ê|(á\óHTË¡ð™Tâu³Ç\ å³ ‚ Þ5@Â�è«|zÀEÀº2Ñך2Ã‰ÞØiÂËʰHuýù�®�yÍ/|¨IEß�ˆí³ Çc_'¸Ah’Æ´÷ß9óú.=/?^gÙ.(:W‹¸Ç'�€E9/¡Ô¤ñƒÒ ɆÎå§§‹Ò”ö¯ßû}ÐÔÙ †_ ³ý*ìK@PCÇå«[”ï1÷SänšÒ èL+5S�Õ µz^ýfoyÒï%0Ø�ÁOié·g…bF ýú‚¨°°ýÙÑmTð\rûzuS›6µ …2gèpÔ{]oº¿$ D„Édodžp9)Ž¥œœ6ÆÀžfq'ǯÕM¬lœÜ[ÝåÔ�Ÿ§™ÆÔÿ�G+D$‰¶¼ÃnÉMqrfýß%�ªqn^êŠ'ö�®šó‚‚C�déí«B¾¿:­çþXW%ý 'à�%‹D'úsš·EpØ–;sΤ�®¢eöLéúÎ�‚€³^�¶ •H ‹_¾”I‚ q±]:>^¢v¸4q+5{uÆý~a8¡wÐh»yS›€E…øçÙ*]&€†w=St¯m�ã¼Ñ^ �÷xÅƒÚÆ²˜Ó‘s3„ÐÄžGàtü³JGªE½ÙLvîohw T¸B‰A•”«Ë-·ã‘·Yõ¾0Æ;ý^X^&Ćog™lÓÃïw¯0ü½u³XÅxˆ9À¹Î jDà�ïèø—_’cbB«9«yŒ.~˜uæ‘>ÙªÕ¦…DÕ{”x¿²kˆ–”Q6èua­0÷r/× ã¦¸B¯ÃÌ?E,‡Íf#&T[É£¢£õˆrPÏœ(#ÝÏ”·Ï«ãnDÎç ¬.œNˆ¬q/o“ K³¤©Ž•Îê¶Mþ‡ÔG(²fò¿ÇËïÔŒ"©W•qH•¦¨­VÓÁ «©0—s“A2&Ûé…F(â�f:©¦^˜Þ9ºwíS¹ëüÿ?´Q^&„"sÎ@Jñ!ßqþ­Ïýn6©ó�WVîÈRW£Á¯ žæ¨ÁÏÈL;-ñÝ!qösRC<ÙƒbpôÚqjáz¯ˆ²Q•i�)6ì-ä;X¢ê°õ’”æ‰Ê,L¿W´káw­‘jAñ-G>é>Ú!hÒ†½|&éH¢Š�ò­Ô?½òñ–�Õýhù'wÞo-€  …‰?÷×ÝoŸ®+”ŠçÎþõ:P¦�·hX•N¶Â£¿ÀÞE ³ôÂú:~‡�y/eª×îÈ.wâAU’iæ5ß*JǼnÕbðééäO*H:‰\—Ïó’ÈxªÇ8²äG€VÐ&~žq¾*á… ÛfNe…1Æ^V´<7I�öÿG?OFŽURn×¾$Q^ŽLéÀÈ@|öe6UD@0í€vÈ�ë"~± ]NÌ”w�6gn‹…Žiò@]ˆâè£^íÃjÁnÄúÝ&ÉêTT—1J“7ecºÍ¨ßò‘škínF-¨¥Ô°GZÈsIœ•v(©_J™!Ã;`%tA³î ÷yú¬PÃ`ûZ=ƽ®è‡—á¹ÏUK]Œ<)¤I¢�´ EÁÌÄ.%]ù„‘O«ÿÙB:Í;æ*M97Ÿdž[‰Ù…Gý­µZ–NS¨�…ï¶syu¼}ú•FSZÜký$OqhôìIã®DLUƒ‚ÖeGF׸Jewª¦ kŠ›.ÿ ·È`Å“¡Õÿ«¾uÙ‡Ãògé†)È_¡¦("%ÑÍÏ€T®Ž’Ýz¶¡†½„$æû‰„¤U Sì~tnÞÎåð¶ÏÝ)ëZÃ-åÐMõ°Ìg´xèO@UÖ5-žÍ«iÛ±{ÄPxGRH¦ÃØ no,ùÀ†Fð…e­Ém¢ò%è×mr`pëh¸@¸Â&£%6Ây,“sœQ½Y„Bøk&äSCOV˜ e"BµD!WòìÇ& ÉS™òyD³Fþ‚§ ìľpa‹=›lÏ“r “6ê^šÅhñÇý„_=_WöauMlL…îðC±ÕË %ÈLWRÂ$fZ`{Íêéú­5«éˆ®~�¦è;Ÿéua!ñ©häð"wHÏÛ­™�}v¾c+Â/ã�K2º” >lEëžuŽpà×bF]‹¹1Á+²E¸«pÏ!1 A Óúéßš"Z•b‘Q™Ú}B�Ð 5«ÈZã«vEìñA�‘éôëµDàŠ‰ÿ“ÊM»?÷€4×Ed`U¼Í²ãP´F|×£Ø:Ñ+uØquªC@ór4ò�–/Œûî€ Ýå‹�4²µ÷'áy/<Æ”Üg®†™àAÃP›5¬êï×4ŧҋÓBýÃøkº'ãV‡óû•ЕQÈ<5Éâ•Á £ÿñS¨šÃÇ·üŒ³ÛóŒ"ÅÂF/©j‰ó©³»mE½q ”UaTÃh²£ èâNCûg &âßP»=á HWâÑð 1!+ÛÒ�B¡mVÁíî¾*ìbõž’;MA>ˆ¾jHºµs/Zt8݉f½7L¹-¹�ß>±ôÌÈã�ôæKIöéÿ£[V˜Bv¨aw�sÅ�·=&�ï9ÍÄN×´T�ý§Gå0åzU çÖzŠè¦ÚõˆºÂ™ØHÞq9¹úNVÎWÛX’»A9D€†5Ñ:N?ú¤qj6w§ =YŠ’¦GEB†4Iw ©”šk˜‚XГ6™®Îã9±q’§µÈá›\¿@B‘­ÇkŠ âBÜ^Ø¡XêÖý°ZQ ©Z0’õTaš×�n5+2‰°¿ÛJ‡Ï3uÀÍTÇaúQ †Œx•šyDœìî+d7”‰Ê)Ôh�iãŠs +ܳ8¶A|Ñ·Í�Vb‹ÿ{¯&M¼Ìp<ƒZùòaCïPÒ'‡-Œvñ¼Ž ¿4(U‡zõ±°—ËåT`‰ÿÈ_ÿ�w®sµ�ÚÇ­^Â4p!¡´ê#oIo&/h4‹¼’gœDÛv½ž¡v¤£àQ3-d\ŒÓ¼êj;iÙ“(2¹Š%„¨^ŽF]NûoúìþfžV~~9” ¶ÿ£§ìÆ[ì(áÑʉ,¢,Z‡ŠÇàÓÖ™ëU/¨‘Ó‰ÌÈ·N 9KE�áŠÏDM›K§»sÚ¹ßC»iŽíI–­£mêß½N2ម³�+éšPø›\!žÌJ6Fû&ßá}¹«üà`„"þV¿Ú{¨ ¾`3kUÌÎë­ýIàˆ/?Ç� ·RfVõ„ ~>¤3”kMëk ¢t‡]1?·úb ë0¼ÄG@®H¢€¯6åiâÞAÏ F‚Pôø€¿ôCÉvu^_ \–3§;RK †.ÜYCÝ}ä îd)šî¦‡–7T'cÁ¾•ñíÓúâœa=É ÐÍù¾íë#I¯"/‰cK&ÄóËÍøÍÞŠ¯ã)ð±zQ¯Q˜EçÛ{‡ÓiÝIöǰXî›öR{JLW©úã1¿ïxÿ›á‰>þÆŠanå1E%&"c^t¨(×@³ wsªBÂ2^c«Pƒ·Ÿf˽ÉOºeéâí ®.‹+ܽÂÄäÃiÛ³@pˆ[ü!Z†ù¹Œ6‚½¥,‚Ðuņ3yOB¦'Œ(ÒœXÌZQ*ˆm|c@{„“|º| Vék8� 0Y?ó0Gú wËSN çRtLaйU5~`@ÑÓ5,ú#eÇû>±kGJ'gü™NAhñp­sˆ„ ’Â{¼@‚ëo'Žƒ3ØÏLXGÏrÅÌúðþ©küÿ{ öØqØz‰ù%"Žj�èœlíV� šÀ€z¡X®=||ºéeî§ZÅÙv½1Ê‚žªå DY©^+žÒ÷z£mYš1w�Vþ¹òâ&Ú-«¡«Éq¾³éü×C" m òR˜’»M0\Qç¤f>Œ ± =¼g97¨Wà^!_¼ d8ÿþÔêÉÉÅdAk u—ÿí>êd ›ô<8cCÎÖÁ£°Iž9nGÿæTÛg†¦2Ÿ�` gè`W>ú¦X¦' lÅÏF‚`ñP-K!¹²·öåªilK\†¯ÌdÞuV’ËÆòù¤ÓÛ¬‡E�"eÖYr–±NGMN¡‡¯– Š!=ýéúxÈ9@h¶«nØÕ°·s‚è·šoIP¨t¥×fÐ{‚öº Ì4üÒÆPW‹È™ õXÄÒ/Éf7̧œäFE¶º°Ûq‹RËì.ôÞé�<èÞkõ[É›–~~9<>oâŸ4¯áKïõ;ûëT ÙÒʧ!#n},À e+râÒ sÑ½Ñæ{}¤½?óbr ”GØ`v�´¸�OñÔ+œ`ј§�ÙžvSU'8¹»M¼z`An®‰WÙ˜ö/ç—3ý›ì„)ñx ƒ~ëÕAš=­Î÷00Ûu]ˆ—þRWò( "ÈH““•n�óò ö­°ÂJÐXoÄŠ'ÔÆ©íö?'æÝÁ¬œï„™,ísC ©§9nk±BSÏJk¼ÈFHÿGf7ˆõÿÈb•Sb#—oÊ 6 ±©Ï9'iYÝ£f™>�˜Èâplw€ðç%e'´*5îçèc1¾:Ü›cø…õ®uþ°tg¥Ù·¹;lÅßn2•úàºÌL´C1àîînAÂVüöäqög«Ík<À‰ÈVþeªM�v“ êÞ ´RDˆdY*¥ô?œðg,úª§ŠAàö‘Öõ5Äkà¾ò–…Å*à�Œ÷–U|�¨™ÑÑ,Ã.Ó"úá ÓÈÕ©>$õ: ̵Ë}¶|‡hpªÀ¹'bÀX©†³áÚ¸R•« Æö´ÄJ¹k²\W\Ó‚•PJç„nB«„‹í‰Ç¢lŽvT³G¼*çfÅsXàpØYsxÄŽrKêϽe¬H¿ßàcPvf?$–®Î&¾Þ”oáï}0²Œq2ñoôÂö_R•Ǭ¾…z �”ÑÁ’·v±c Œ,Ó‚ÏòL/:ñðE'6ˆ”Í]2˜-ƒkd- -÷È6� œ]¹4ªTÕ¶ôƒŽ½§)�gpÑyŒÓ»x�@Ý‘gÛèòïé56Ûê\ !­*O>ìG¯)ÃkçNðÅNBãO?[òÇ¿�¤|SRBÿ½öê–– ;S¬ ´èTÅÌ‘b/�³‹ž ™ó�?êw ɹԞM½\z?ÐI\Z -&%v.êÐ:â4ÞÚv¡3é9Á’×\çMA‰ü ž"7‚¯².-¡4�òHû³�ìpøøVÔZ®ËD?âu!èĆ<à0¯Iö{DN%ðR>ì Ødl4jÖ¼Ð'Ô�Ÿä¥š+]œ ‡— þ#M-;jWù�'oа˜©™�,à\½H�ù(§¨êXö¬dJ$ÓD=8qéšøÅbÔ6½Ø%¨bµñ¨K<¶L7àŒŠÃ�ïÙµw+*¿ÿV–ÓôÒÆˆþ›®Wß"ùŒ}¡.d·³ëzê‚~£gÆ3³:e¤ÔFˆ•iÈ¡ÀUÈKŽ(G^ˆWw¹Èóà—†œ¼›ò¶¿ò?^¡¥­IàfÛ�0p<'UŒ“gß§G¼Ø#ãx¦h ºCv�ûQ«Á´ó.%FÜ,ªæ8ž á©èZêÌ�ÌçàLÕ;Áâa ×ð­17X{Ÿ�ÓøŒÞ®¿8½UÌ/�ùÜe�RÊ$rxxzÛú ìä�q«é0®¤½(Âßsç™ÒrKÃImN‘‚® ðçSù£¨a)o5lj°/Xfaëè�³ƒb¯åÚëeCŽØ¦ßF©†AM{êÕ{‚¹÷Jݰ^¾G-G+qØI¨˜"á*‡aÍÄŒZâ39}³ýjzr2õàÍ>æÖž§âæÿpÏ$ÏqæóÍÈ©&ü;Šíîƒ.Æú™°z\ûê²sZ ²£iz³nh5ĔѴ ¡ ‚å÷ïüP8­¼��´xmÜÓÎÖ ¯_éÀ‰;ÏK¿=dOíQ•ËâûD Œü=Jª©ì›ÞÒŽäuá2´è’O,Ph¢” Š9¢¬‹¦¿¾ÐÙW}¤-¥ß°ç¯fýN6ñBá5{Lh6µK„/?©´èù`¾ÊcWGà”ÃxL�ËEëþ/R%ÏÓý2çkuH{×­ü—+žL�7Ȭh‹¼au>*]i>g'î�FÀ�SiêŸÿzôU?�”(`ÒÉ ã°â±#g—±¯­È‡{ ÕWñË­Cw{A ‚3óöÑÝ'˜6�'^ÜYP^� œéê«2q”á' F]Fš,àP­³\°[œÚ�)ñÒ—]މñZæoX”§U™œÀCçL¶=ä }`Ò¤ºL=g’õ]½Ÿøø{à×ÛéMêåú…~£h¶WtÏc ™×´?Lv67S†E<=ÿßóÑÖu=öSLm ¸ÌèÈR*`<›�q‘:Àkÿ²O.¶Dëó+™XšRô2$æ7wP¨±j_óºçJ÷eE»ïÅŸƒÜ¶§Q8ñŽZWêB¨½›ƒ ›ŒÜšÎ:�°e©jÜ:¡:\#öÉ”¶oþ)(ZàÕÖÇ(´’h‚è‰&°I ‰•Í4û×[@¹%’¤2ókoeôËw1;!8l%4ùLƒªG¶‚·¿r¥?)ä"qºCê¹&„E·åj„˜Ê¿V¯HzSÈõ-¢_]yh€úã“<çÖås¼¤¦S÷SSýËé³"’wÿ¥�¾(sÊ›j¸Ü` ÂMÝUÊl®�¼.éXl2W�¬©wÜq¶�)k�à ÷5ðÜ)‰¥Ë»pÓJV‘,*Úæ/¾aòE§ @ ·r1ÍÇ@`p…¾öf“˜7–qÄÀµ+q'²ü ûï¡ó'µ±”rðO{ž„ õ¬28>Í«%Å·¥r+†Ýlœº¹àhÚï“Úà[ËS¿Ä±¼]ó ¦ó¿?Íë�pË¥)<•ò’M)bœ>•¸uCcGéûL>ðüµ¨Ân!Ì‚5ëk:›ˆ»÷ãyyxž6úh rÏ9e�®nâù…Ü/Úû´QzÅuõÄÁùا(�†úázÝ9‘øn‘ýs¿A±ñJD”…bÎæ #ÿkë—U4ê\}î,ƒE0,²Äš‡2€ü�½³Í:¾ê{»¹:Ø2?u ÙXYáæ½‡ë‚ó  YYÅ 0+wõà�3–­wÓoû�®&»‰¥cõr�o/L”.!}c¹ýøV;”„ü[`*íèÊcRþvdzÔŸI€v Ý6é^yQô,1K\€ßÂ<:î ¤ïyD¤®.1tó™H <Ú.-˜ÎÊõHÉWªEcy¸Q°ceÛRqù?üJéâ¢÷,h%Dš3‹� Íè�ÛŸp(|˜Ýo¿ñY}ÌGè“&IJõ•‰Ñam𣯼ܨ象�äZ7ÖÀ[ØBÆ{ÏsÛ–:ÍLk% ­<2eñ®û·äá¨ñþÅ"i�Zô¿Åð.tl ¤÷ê£-c™cÙ±�­€:˜ùPÇþ·üJ@5�%½ÃÜ �ß-!¤eÔKÐ`Ïr]UÆ6ßfC%ã\{WpI�–à–¹„ù0û:' a©]A3*<ÿ¨ƒÿ=°Ê1¥8kAóŸ�~'X°±ãµ7³®³9ÎâÃÍå ÍÙˆœaé‚+†9b<Û�Ù L¸Äãc™N¯¿"ä߸?ξi—bÔp\žf”}RÆþvC¿ÕéIÝȺwõ”ÞTNfŒÌGbÿ@ÏŒçk奩xʃ‹‡"‹ o‹sËqˆð‘L@$¨Š‰Uˆú²U×�Aßp)ÎR±º+l½Õ��á": Óó+‰x1e¬V1©itç±AÙâád¯™Q_A¢»ñU¤«n¹=üªëúç¼KÝÿµˆìÛÿ[‚Ëí;mÛåÏSÈÅóþ00QöyÓu�[ð¹~~p}¯¨ñ³ä¹Iz™*|’ÚRÙßÊLØ\ò ¼/³ÆOJ±×ðzÈ žÿ·ƒkT¶ÞÍó½Ñô¼¯÷bÚ/�X®fRD²À=Þ†¶’�_ÔÃwª)Gù‡Æøø¢ŠPªÅ”¢¾;–¬ˆ¶ÿÙ'áåú²å|*#�6V)ôjô…ú‘Õ‚ ˜B)ºsÍÖHí]µŽR[h‹·HBî¸E!Ë›€ÒËqŸ“—óíNOd‰�îçº"ð„°$»ö�0œQ\%Jý¾„c,õ™?&Dc «îi»`ñH¿nåU¦ŒøüpSBž™æ~:”·Åø®žöv\ÿsŸ°Ð§÷@O¬G}xÔ»+blXåKŠ}+Í�ý|}¤jþb…÷Å Æ}ƒã»åÞiØkÌ*,råÆ�‰ ñQ³V‘ºõSfÝQ‚ßçNR>y÷Éäù¡›Ú¨ ·/Zâ¨îk"C<±ôç±­À@ü/: ºv»ÞmèP…87ÐÄ“¾©gƒÖ¦@ÂMî¾óméž~Üu¤lx>ìJ ®§+~è”Ê/Šß%ÃÛÅý‘ií~�ß9Œ ÿ[‡0#…‰¤¡ÊµD”êôÛ¯ ýëR‚µœh'À²üPMíÕ$³Hâ ½Ád:ð“k,â¾%Ì%ARƒ’½A¡ÙoØ˘HÞ ?Ú‘ZÈ%SuO)A˜ÛE¿÷Ã`¤`q¨•¾?˜ñ®ñW ¼=Ìm„œ­¢˜³pMôÙa:\Øò4 ¾qo=+C†7Àå1n’¾ë2™øVcÐQ÷Ÿè9zp¬u5sJ_³±…3ÿçA¤ãý£\L àKqÈÁ¦úu Ôfw3Ò€g2üž;É{d íúO¨K‹^ŒBè#Á`ÁJ¸ã‚ÿ”�ã$oË�})˜GZ8:VÙ`2Û�z&m¶IjÑêº]]¢Sü JÍ|ú©ò©hЙè¢h§ž·#}ŒÏÀñl:ºCÜ#ÿÁ�…p¨5î5L¬4sM“ÏAï`¹ ?!Y¯Ô¶cà¡8ùe­¦\:Ë ±ò3Ιj¼\˜çÏÄ™?�ç¤Á©È.IÖ ‚Çþ™Ý¥^Š_Ó”Q­u÷™8™¸+‚HS€¾µ Ñ[ïŠy8ðÙœ¥.з¸Vž‚´éL’FƒÅáßf7â[êÁ@½páj>]+•BÂ`Ò£ö‰ ·vN®<»~sâݸ$e½-Дî€@„?dä1v°KýÌ0¾æöJÕy'’TuÑ{áÀrþŒÇ$Ln^—• ¦{$°´‹oH,’0—�û&»°ß±î<“hy 2ôT‡Üx®\™lV³¸›6„ž“l}ëY¿†j0:ì¾ÓÛ\/ѱ² ’zË:íJ[Zìµ{ ÁKý õ!ˆŽ1Ó@ö¤¿XÂÕ)nE%†e“vúÎ H ¦ÀmzD·6§ô¼ÏÌ_},™ òÇdËÁ�ç†qrí±¢2Z1¾™d6žû¸º¥D²DÑ 4óix!êçˆÙ©™­08tà3Á3¶´¶¡ÉÛð¹_7XÂÛÒó,}çÈ̯%á&C°¡cV~ôü¶nü�aeÛQ;5âé�N‹Ç)Ujw|þ®ýZª'?mÒ>šàâkЬtÎÔ#5gOš «Ì#á|¾>³š:Ý«‹?94¯ÊHÐÙ¡ µàµÛÅß²CŒÍI°Lp=lKÿz3VFòv3)HKÏpÒ ~o¾ÓнaªkàœÃhhÝ{üÉlÖàXqB7ÓÐ-Lž@z„¿JɺõÙÙ”lf€Ý\íý–ó`áqÝl-­ñ |Sbi@ÛYö¨jˆ3˪ ŠˆØ[ÏŒåJ¤œëó”Ñ “Tï£àƒ‹°C‚v ðZ’ãßj<µ±ýQíþœ�¼Ä”*8µ!-ðó}P||�F¡­öc³˜¢k×!}be'ðRÝÝ�ü#Mu+TË;�xíD�uÇJ¹h r/¸ ,CÕò_¯?‚‹´·�Qó~ñh±cçëyAkÄYgϺP_µu¶JÕMpZ£2ÿ:¾R@µtÛzþ YðFÖe l ”ÿ$ãhtðb=H˜Â•h³"aûC¿ £¥_Nl£Î>Ñ´œ¼ÇÓ ¸€Vð³’‰<òyH²�~.êm! díõŸïÇ67E¡ÕQ0~`õï…7VK\Ül]èGcæ_SU&¯Ÿ·[5¤×— >}v®sE!ÀÓIŠÚèŸ÷bP„-ãØ;1€`¦aÆÎ)O¤�G}¼ÕÒ½=ÄbÖ©kn‡u+&õŒ–ê6‰ö‰)ƒaa>ÈZyW_iaÔ'p3¬# í�ƒ»0Pú'‹ÅQè̤¸t>�ùsÛÉÇ\ ÅÿÿÄ¢­l@«ÖLñ¬!ˆªßö:¤Sô#›j6³1Ù”“AëCf*¶APE`߈ÿF‘˜Ñ Lˆ)Þú=§†æ7Ys½‘·‚J8q� ¼¿÷€ñ>qš[S h»YKÂó¼ZRs¤Ážï³­K d€rÑû ` &K<ÖDT+7òá—\àe æŒ=ÿ\ë:#´�÷ñ’±t!(£±åŠ˜‰ÊOÆ\X?;DÏŽôáÅfÞööQƒ»šñŒ÷jÛÉbO ¼!ÂLaþâNˆõëk¶½ N´~},§*B´×Ÿsr6•¸�ú?ÔP+Ž% p¾FçÈ ºøBtI&¿jþˆçúJw3¦Ñåœ?+R1 B�ÄÏfô}©“jÎüÿò/-™L/ÊxÍÉw×›PA�O�õÍÚEªЧB>íZW*Èýñ­HÞV‡ Á"4µñ«å;¬ìãÎäEžï‹DõÞÞšæ a`³H:s­�H3»'ûäl_Þ«$®«5*C…PfC¼äVG]–�’/¾²TбCa`øí¢TÒgÎO©Õºuä÷˜GÇl§¨Ø$ 0â^�± s£þ¨Ø+ŸÎ¥nq÷T8Iï—û^ ùø}ü6_]Iºì ÂzÌÁܘm«Y§SÈ|H¯ä©¼ŒÑ¥( í �ùª`츇˯ûú-_iÛ>¨¡"ÐÛ"lÜ4Jvåf™;?y¬"æ¶ÆiâŠdûYž]‰…¯¶íœYÈzëU%é-QB@oT=À¯¨y‘Ò îÅG”—€â}J݃®¾d!ñ˜´¬ŠÿfR8¨Â†ûZ ÄöXÍ…qã‡|^êUMõob_I£J‹vmÐ(Á›,¬j™B<Çü°æ Ò�(ñwÉóÛåHÛ¾€6%K¬vc­áÖ6éÿ¾?¹x„ ²þeÒòî¡“¡k ;=>7¬ ‹Òd]ž5¾t½J>?©o¥èÕÁñ]æãYr@àNSþZà_è²ëûÓî*aÁî‘Ö‹NÏ,5©ÆYhC:}mö³P—ã`µÓôx§³rí¼Õ ‹2–²?Ð�OÐí2E}“÷… 9«Û Œ™÷ ÅÅlvb^fk›£cçKß ŒrÚµ”�„;qÕ ÄȨàÅÃ}�½æ¥ŽÜÆYÄPºB�—˜Eµ…cY~}M•Á§¥|¿ùp寜wôWqáÞÈ‹hÉù ‹ ;.ЙÒDÛ>D’6ùpÕv›êAÂGîƒ}~_Óy¢ZÜ’+Åj°N°¾(0Ç¿?Ã6A¥_íÂd[PnòeO?¶>¶HI¦'_7ýYA7” §à[’GšÑ[_kŒßÓPðµŸI¢>qóC—6‹ZÉ{‰ûnŒ[ÈìŠ`D~Z<�#_üö”<,å”êWûH±Ð”Oœ Û�U°‡¶/´ó|P�„KïÓªÖ$¨?Æ×µÄ:2i½(§hÇš®£äùŠ—]gI· –^Iw^U½<ÄݪJóïï5ƒßÙú.»ŸUiÌ3ýD xjüñ°ÑЇq£P#Ó 0Çñú8Ì(èÌA—Ü>‰›€ŽYJGì«$pCúúáó•ÙÍî-ËñF^Ìí¬�ÈR³PÎß`ò0zü3êR¥Ó3¡–˜$émÊö™Ù@‡PyØéNêtÇCKOW1“©!’¥éægÒ;Ñë9ï$´qùìÂßò{bb®Y¶¢ì % ³]~¯\¨à¢þ¦NÌ�öÛ 5M<®ÿnG~¨N…¾ôMÎùûÎr$üÁ:ÄþÙ¦­¹6,iÒï]íÆÃ;q!¼Ö0‚o© mŒôÅtwd€{á[ï£Ãàñ•ÈÄ0üé2,ä 6��ë뇀š2ìù{C“,OÜPÞ¿RaõøXöZœ)º‘�¤ú>Íyn#âmžà¸^¡ cn^›êCqî¾ínÑnÒ1¬Vo’&B‘­î$w(³±:dàS­<’ïà_]lBO›}Êò9¾º`à Û“ûµ:õÊÃÄ{br{¾X821bÿoû½ñ �Ó®�Ø|V¨ÃÑezKŽü]¬o¨ò,&¼%�ý£ ½³!è¦5¾¸P–½8á¸î‡¾7gÛì—dWþ’£Lß+WÅ1â”pì «Ì8躘!Òôü‘š󤨿Šî!´QDÉÍ­£Œê£Ï±×*Kœ6”äÉ“xùå/œ¿¦0à�)ÏLƒf§«¹K0ü©¸É]˜fÜZH˜>ù×�s³ÓÅÖ(²ô/ÖÝÁ‚T†õó£çô"¢5ЖŒ›Y iûÔ�ò,ÿ^êZy¦ùÀLlAãßÙEk:ŸcÖÔ¥áDyD)pžEW¸ÜxC:žž˜#1;×Íšm ²$˜&Vf®¹%¶å|Ç7�Ÿs»€ø „ã'ÏGÛn¨^ @uÓ%^�AN.·øtlºÅdsÕ½l4ZÁ5r˜í5›tŒç‡Ü:à¿ Ó,Þ~9ÿŸ• ¿Ë %´ý§©ÌÁß×äpH;anªH:$êz*BâÝ>Ѐ€¢¦ã7¤Ù7Ó|ÓØÐ}Fù›?KY�-ë�NÆsÆGyô>Wÿô=Ü|ô½S¿+i§²Ï”þ¡ÆÙéW¢?¶,“Úi¥¹Â1­Õ>B@ÃôÂ)Á!ŽQ¨É¿�Ém^eHé7wˆ§cŒLÿ›Éø�V5Žê7P'Û‚;|ˆT‘J%ùa®µÈ¢;{ZåÜîõï9†·7IZø‡ùùXߌIÍÄ#9âµ.8 F î%ð#¬!½?à…ñ€xb‡Ï"8èÙ·4 �ÓrÅôÄ_³”Ò�䇀†¤r]/£^Û™â�çzëm�'ŒOš¨?Ú:ÚÁÚÏ.œ€C\8|Ñ•`8+Ϥèœj)¸¬6®&2@#޽Mû±“ô]Ø6ém7]‰}äWAÙ3&k\Õvêç-Pã½ á! ®¸JsmHDfPwã ÉMo_h|%\°ú:lW…ŸÄ>V#ófAÛ0}êrÁI6«ÏøQ!i Ú÷dÕ;ÏC_ Ðw‹´GˆÜ85¨I6¥Î%pi'b²�Háñ�•ÚTX›'€®ZQ5ïzôõ1�Ô À)�m•bœÀ�+6­˜Î&§2g^ÂðÄgÿI¯Ký­¢õP·BJ)U §”ÙÀ¹ªE ¨¿„úŠÐÞ!f’PøÛ.S›|j°‘¾uAwKå¸XË=ãúþɽV–0´ó¬RßM€ødë]î¦úæü"6ø¿ ÀQ¡È'«cšä_ì;´ty ¾H ±„4©»ou[¡M•“÷Ž °cýs³žåöjŸ‚Ò)#›%†a¨z= Ôå�ÁÉjéGs?® j+KmbÐIö鹿]\<ù?toÙîDØÆaÆÐÛäÕ¸(8o†ˆK÷BþuAÒçâpN¡Žêx¿Â²Ÿ1V+ƒñéØÎüùkûÍ—÷ã§0¿K`'æ)Ó×>�“AŽ ðº¸øá›¹¢N¿°PžÛôUÇeÞÈ2í¾ãU½Ý½ì25f™ÇE/É }AÌI©}dѼÿáN¶žò öÈ-h¿ºÕˆäÌZ`–¯AóÑÉáÏ*Œ-7.W%ºKy­ÈLWÏgü¬¿šß›ïØ�¢°‚<™Ë úô¨X“s&¹›»„gQ®psÛÑ.ç–\Ò ìCE%&F§+œW‹%²Ïº‹·Ù7twÜ“­twÞ+�åv7§r¾š¦µXþÍô’…5X¹bÎŒx)Âá6à‹déêV´5ÝH‰4ÓÏI:×@F&_Ï=Ðý˜OÒc+�Èk²LÍŠÅß(k|ç/ƒ]ÎÖžû{°xçksJξ¤Ṳ́ ‡„Ú ÷³Í´hB¿J‚Œ�(Oã„Sûî"³œ˜nÉs£œ¯ÃÖ>ôÖL 6dLwžA�ƒçXϧÅ3à�?k€Æ¢õ⻜¨äÿÇ Y3Ym¨\{XŽèæ¦ô³] ð¸gÚIƒ�ã:ï“;K¼Y«½#k×TȾÒg(CrÇÜJ‚­G:rpaùF(AÐ¥“ÌåØ;Ê>A X>pÒ\þIµåÿªOX®\,Lo(ý@ :²!‚¢Ø8™ˆ³hpröHáR¤fÿ‚Œ£˜M œ?,Kèw¢7òl1ëß ²ƒá¨ÁÒÙ½x“çþØròQo2«gø4™{”S¸¯=¾ú5".Ox}Aıºa— «¥QÛómÔ'm—¥šŸ‰Øþ%¤r@†å¶*Mðj0´õ€c?=SmñÙåEd�!©¢Ì¬\¤'uôóÙêV?­}´/ì HºãÓª±þ«‚oÚÍ+î<Œ–­dß .¦kd ´»‹ :ØÁ©><ïØÎ�\¥7üEÞK�úõ¼§ÃL•àJðÑËKýdUþ€ÆÒ…`ÙC¬Êù �*Es² ~°?ÜäÏ .BûÅèÎ5ŒhíºOñDü `õ®œþQCå‚|É2¦D÷]€ ^0ÚG �W•ïj‰É9I(ºÏ=G°ƒÔ0U1FÃq…c‘ø;²¹;倫Ü�F ±’øÍ|÷WÆÊŒ€¤µ²€ŠÀ#âHiÌBC¦`Þ^§êŽYΤËÅÐ"¦Ÿ\ J•‘M?w ¸šÈ¸)—=qô¢�ÞÝ×-�:‘~‘ £»Ìæ ! ·ÅŠ2atRx«âçc_é*øv²ÁzÇML&fS£‚k÷I3˜¿AµÚÚ»}Ýê¶à¡Ž†y*5JÊ�q©=ÓµA«¨á¿A•vH.¨SüãL©<ÕÑ|ÓŒÔç•æ 9[`€Ê¼µY]f®·ßïõ«œŠ'7¼Ÿïí¦“°ªþN•?Ǿ%3'T´Šâ+TË,|²æƒq¾&ÖÁ,ž|nGÿÛäÔ°�pI73U€�ÍP9ãS@“Á©á mŠBTÝ1½7 Ž*Ly.Š»¦Çœÿb”|ˆ€ˆ¢% 3œŽ‡JÜjç‡o�]üþ‘YE�Àâ× ®^Ñ�ùþx€ŠªÃ€ÜÁA"�âGyªþKÐóXYuÐÆÆøõ?·§{b›´ã|«Õùjþóûk’NFÔ0z:!â:€uäÊ"WDØV§_§³H'Ýe/Í­5ÓMnbʧ°>³2ó^&C«ÖÀz•ÿn¦®öÎЖ÷¹¹ÛÞ•æˆÞxZ´¼·Q—´Z>wÄIààyÜ¡ƒ§‹‡¿Okm~ýn� ò, í¹ÐÓ�>|­hË P¸q�Aš5-dÊ`(˜!ÿýñ  =oÈ0DlÊ$Ucî­Õ�ŒÖk;E§µ ㈬O_×m#”ÉBãU6Éx°7ëR#�9¶…Ä9ººÛ|áüéKÿ?p®F>¦;•u%ØU’ß7££4'qÁô|ÄÂjx§iEUîÍ/-äRÙÅzuÅÝ1—ü@ªî ÚŸdÑÉ_ppÙ©×Â\±Ä}˜kP¼ðæbÚrûùÇPOÛoNó÷ì<Á® .ky°áç'Êî°{&Äp·5H(ÛðÊ‚-CüE$Ç+ßæp©áX€cƒp¤¬‰uØ,ï¡Øø³¶�tkëçê�ܸ‹ÒLU—e÷ÔGl <±3ý�…l•?ëC´ž”ÿØfüƒ@ÍK¥Xæ€�`Oÿ½…câ1¾WÄŒpÑÀðK6¢p“¡8f­!OJˆ!̯*?ÍXPºç@}Ž`Ø…}Ìß‹FÞ߬H„S¬B7ö®áÏCãÜ¥á�ßÎO./ûù¸¼þîíõÛ^X-Ôc/Ê,³J EO|…ug�¾Ëy¾jîÒ—`/–ë{ŠGk’yŽ^žï!&qŒƒëÇñé¬põ4�|V¬šÚÜ +š†6\ %¨¾�‡=BÏ}èÑ58Úš“ÎòÃE¢Ù¸<v/ ìË„Zs “�K‡Œ�hc0Ñ�¿j0†ï1Ûâ†gÑßP¸“ßâÚõ|)í{:ì {™ ]ò å¤C$‚û´Éx§ýnd7–é‘ùhË ‹d»gáØ{YÚEC§VÕqŽà§H³Gy›pЫâ,°2,$Ü÷¢*¨1_×ï âxJc—èo�ÇV¢Q½šJ%ɓݗŒ ÌýV›iöðݲ¸²{ïfWŒL`(–ø%ù[&øèS+å­o‘}ò´L*–¥ £F7°º‚3u6ÝË;× ©6–¤ 1ÕEmë¨�9Aà.`ë?Q‹?Î33%ÐFYeâ`?r‡�dÿá1Ç[‡7ˆùg»ƒM"h– ä¼d˜C©pykRw‰‹žw:‡ÒÆ-\_×Ç]•8¶¯©6ÏFŽvM€Ä€�q U[´Ž~_§“Ìxž]•ÇÒ4À™.Mú„ÖnßµïcËÎÐû™Íé(ðIƒ…L'–;Êð0ˆ†°6»ÂŠÈìƒ�j²ý©ªŒƒj„‚°€ÙÍÇê4ddz‡¤„ˆ…eó;|+´¨ÎayŽüPÄŸ.ÀOÙm’%‘bd‘_ÌOÒ�‡eðöie‡ªgÏilÍö{]!†d(:fŠ1—Äi¦@h>v+4ö‚Ó¥;•V÷UðA®šL&lxùêP>ɟ냭:<Ñd)×¶up}‘i"™Ønï8 n†Àãüñì5ô5ù¿fìþ�'‰7¹L¯QÖ‹9gy~Õ[Ë�&C•�ï"âöÄ·”cüŸDw+‰W6OQÁï>¾9Ë„ÔÊpÚ¶®:µ€(«ºz5à©Ò‚æÑz >÷iôvãœïÀFNä/ùÆ¢b·—RR÷ñW´Ú0Éͯ¹žz‡Î'}n…ª‚¨�-ç¾ûOïñ½Ê#Wˆý0›Bd‡ŽYQÁ–îCÑÄA>x³Ãä{x}V Þ� ?]Æñð€ÒP‚BèÃãiÐ�Y:5Œ·v^Öõ­Bg§I/ÛÆðô4ùY¼‡qe’ûqLY»¯² Ä§Àg”á¾û?Ããûx$\k´ùÖ‹¢uîS0ü>Kt�÷B3�¼³†'÷”} ~·=ª5Z¯·›œ¿·Óñ½~ÿc,;“’K[T Rz¹ÇdûUÕž¨Òæ¢ÄÝ*‘]´¼¿hÕÔÕjž•c¨¦ @�C*§4páe½– q1õðˆî:²ŽÆ`ö{O¤6oþž–ˆ“‘J™àöóܯ#‹~b\�K¨Yt§Y7qa’þœ×¶§èÊC9\¶$£øùü:;rü«{¨øÜü}[Ao¸³ñô¯ü1ÿ ¹¼tNŠ9–±½ç&U²Zx , Z¾]êþEz¥ÉíW¡�( C¨Ê†X¨Ke§²Kõ ŽjsFù“f¨ˆñÇ^ Œ³{]òJ»çŠ!= ­lVŸ°Ðƒs Iƒ›øÔÂAÉd4²ªöñsŸ|˜é¸¨¹@ξºÎXoVÌíqœy½ \®.Öv.œ°L�’rS9OF_óL d'”ƒÆ_˜Å ,TɆÁ+Ç]Ï1+—üi¾ƒõ£*š½FW5½O9›òb÷Gˆž·~Tm}裘<]"ËKŠ÷¸!ž]ì“o«§�²Õÿ þœL¤rîΣצ|’ìí?ëlc"�üV¬Z”¿ÑL#&ˆÁ`¹Îu rj`¬¨8ˆјòé•â ã!‹ø@ÊxÉæžÂ„lxŸG\ó"¡æ)?è6ÿ«¹­©ˆ+AÔ½Žû�%_†ÿÁK˜klXšÕƒ[”¡}•ÅÈ/m8TÜæg?N—ïü¨ jS”Túƒ‹OW„ÈÒØkÂ3£/‚"Á„b_5D–Kø_lzNÄÉk©)®Ôù�µy¹õc/I„”wQr5þ¶”ä$M§®à¼…ÝWS}”îMïØà´%h¢§5•Î,Õæ:3þ;€ÏcâHoÿIùµfÐÖ’ýaùibi�.cÇ»÷7Û4:DÎbCøœÎls4²�„VØšb!Ý_[¥Û�CÊ:CNŠe¼Àó²Ù¼— h÷@y ½ƇÚ4CøÀW¬×x™!ÁF€ï¸ ÀX@x0À.&”žžžnGÿ"œ·‘€Ú+´†çžë=탈ÛK_"hC_€S:ºðð<0õw+ôòF•cÃ0Sðè]�!ø+Ö\“´·ÔMÔ¡•ÏŠ«¢¥n{@ ðbñùOU yZÒ[Lщ@&B|»î„šVt�b3˜á!?>ÐwGFhŽ,ìö�c>éê´�¾7 �úÙ�'ÀµR[‡qíc·dæõĹ¼ÕšñÂz„¥QRfÃÙíÙ´}XWý�é#¡™!r”a$Qã?sõN�p¡¯þãÊx û ù{¥gåËu(Ød£ºÓLÅYDç ›l’no‘û¦I.?ž0à´¬w.H0«jU–%à Aš€>”)¢“ÍïöÅTÄ£²¢öÊtêüpIM׆™/¹ˆ¡8Z0�î•ø¢ó3³ÖÄÌ9_ćÿHXf‚‘‘•X�©8ÊŠúÉ8Ý:³«6: \ON�$¶2þÊá›·a¼­Z�\4¢]³1Â×ø]þòK¹'È4îìGxƒÄW7Kä,æ9 Iáë�øcålßÌpþn¸%?¾Hì±,V cY"jçú¶ËÃQôQÑKàÁ¹×(S¿ �k'Òï‘âÉm#¹îD.<º ñeÈ”pðÕ6w¸ È1¾ðŒÒ1³6€£ÎhÀ¤¥ñÓ™0ɬÅ^Ñ–Ê5æyIé4IxöGdêzÙ'æ. ÙÓU×>l|À*öóþ·WŒ©“4‰‚/°¬vð(ó ™·]„Z_i®-Ò ü¨‹ØÕ¢³¦âï4¿‰[·çu�Ò7–=Ð X ¨ …«cƒ) ׋ÅÑ*×¢a8ȸó!a™5ÛqÄòg(ùÌÑ{}Êð%¨Ê¬fʰòô]'€MÚþ0¡²‰·vA‘¼â±ØÆDö7ŠÌÖ¡7)Cà>ïòÄ&N-'XÖe÷“©-S°¥=[÷ÇS§t¤Cw "Ú8âÔ]lrAƒi´s7½œPñ¦E¹Ÿ~˜ØÊÚø€e�ï�¿3z.wÚŠHè<€ }ký—‘Ë‹hÇËÁ^ h#f 4Þ>Zl±é‰Š 1�s‚}‰'uD¥Àeb¥Ü7*&8!)‘u«Aûpô¯–§ãŠ�+D}³°DÂ×â8_PU£Ø9¶-LÆ>xcŒÚ–M…Ò³PûF¦j´þû]6o&}4!‹þ�ŽíõîáK�!oäœÀç"©§:sC.4~�¶Ž1ÿ`ÞøzWôç “EyÖ¢!7µcT÷‡ŠP|Nû§T,4+`'XËy‡› 2‘c¯ ½»ÂDÖ»l¥Í\±ñ‹/q „ŽVÙ�6 ŽÍ2¾%$ÐkøE:+à:C;©Ù5÷ºÕž‰q~U’€¡IW ‡8û»µü¦EH¾R8>¿ݪ†�ªò¨* ·çåRøe  À#Yúâ[éå°Üº 4ƒClès¼:T°£ùJÒ ü»Î¶êún^¶X)|Úï,{ÜgêÎ9ÉErö³×vºV®ñG˜ª6ò&Ñ S¨r‰^öS î¾�©‚@‘ÁKyJ±^WÁñ:]â’û0îÖN ²‘S�.Ð�·ŸèSâú¼XÌïŸ$~?î"@ª™«Z­aÑã°=ïàm£?ƒ9LæOb¥_—€úe÷ºƒØF8Øç1;òšjI¬"”iX¦£±-áòÌ®7^8)>�p);éàí]ÓyÞÍãƒlcG«– ¾rІ÷{5ÍæbY1ÎþˆŸ ®†ÁëÊ~86Ñ/дeE59ª„D%Õþºñ¬}v¶*ª6íÆP˜Õ#=^@QwuÈ“Üèm¶û)ÞÒEå*¶¼€” Öæb0K¢€�ë�¡2¡�iõ´¬k<þ î,›Ñ`u‘Æä(ÄŠ§–»×^�áfyO$Yx³Ÿ2þ2 A™ƒ¹çñä×IP‚œAÈC©%Ê­SØN~‡ÑÿÿÂ8ÂH‹k hödÂB9é9ø>+2è]lH¬Ž¹ýp&«‡5ô¢¬¥ W”->—JG.°;ø¼œ(È ÄÀ,g‰úÜH�¹Týø²/¸gA‘ãŒv‰oMHt[¦Rïf˜ õ·èı±ÐÒy·«ß;ly=½EÌzYK zо¡•p^½jІ–ß”ÝR>=E ÃGEÊU×à<Á)럳ŽI#ÔëàXß µ&¾é8ÝgbDv¡+lAš¢Má–‰”ÀTðCÿýñ;Ÿ+F‰-ÐHŒÚH*5–: PÀ¦Ë‰ñP€?$^´&³KZìÏ 20Žnéêåh„¾צm?Ê›®1•ð%ÓÒÇUƒSrá�œ‚÷¬’Ü3DÖ[R{ýݳã 3Î!u"`âYš¸«ïµïˆ�ǧ—O©92 öâT€7?ó$ˆ¢¥|‘¡YPŒh“¸òN0n`ȳG¯”aÈFKÃõ—Ó§þ7¨Ûµò˜’iR©"±òH'Ô‘Ç÷Ápw�þéy$€Húß/ i‚‘yàSëÊ·Še¡÷óæh”kûiS$PÖ%q²Ä×ê)ú†Uw¨à¤ê»§ü+ZÑ¥Q¬aÇšr¡^å—š†ô1 Vt—…½â«ôùˆ7”l¼¸èy!Ÿ½×-ô/vÊ{©¼ìÜb…wx#E ¥ ì—ø¾7ñýáܽŠ]~ŸÂ¼]”­Ît‡U´L’ˆò„pÀîªðÀÚ¿‡†‘Õð¿[q`«ìT¡˜_â®>ÐHSí»@ÂEBÿïS—BB²ˆá>&ý½2Ð5426‹»ØÎ¹½P†ZH~‘c ’ØÁïUb®=-4 eµÎÖ»ô[y€šÓú‹Ú ))s¶¡Zš)œq¤X¤øI5t ÷ÆN#2(;ê“8û˜¹Ç5°¨ÓŠÉÑaìh‰äÔÞ«¬WM¥ø[¼_µ}ÁZ“¢¾Iö W‰5H©aMÝJ3óâEss!„ðñ,å>Õõá à<"àd9¹“Û‘üSa- @™É_ /ÈÏ•ø¢ƒÞAÇ›ÍÚ—¸ÎèMŒE�¯Ðv¼Ÿ÷AêܰAМª�í„DÚèÓ“‡ÿ"æÍ2(Ï´‹•Ô?Êÿ)¦Yr¬,ž*кÂ2ïÉ�UÒ£:¤ —Î�ö¹Ø» PåWf+¸÷%© Ró5‡„“TE±qýëôغCÈOø¸M0锸ãb ë70xnÒ ÐÇáÏÀ¼›ÅnCÂ)Ûõ"ó9Ëì>>Z8"‡Ê–šÙ`jéI¾c\¢Ç0#Ä%Ô‰8a‰�¡vš_Çâc‹6ßh“b~š­÷kre擲ʘ§›­å5g—øAËžªß1ºä^ûÃz“íF§»†v¡gÁ�ÈŒ…ƒ]å;‘­µ h%;MÐLª|ÊÝuÙƒñŸ¨6 =œå¨Á8wÖµª9i å¹ µë‹Þjx¯.ÔuRûe9éÉv4ЬcnEJ-ùœ'Á¼!¹j:ø®Õœ`óˆ• gË ¯Éq¹[-¨l¾25ÒÐÑCM,�¾;aÜ[ä¾ìb¼ˆh‚Á½°…1íA3žžÕ’¹æRû,¹“À¿ÉMæø¿7e éð=›W‹|ŠHS@¤Ø 7Ívx�Bgç:ä?‘@ïP{4”Ô4{ ‡&ÿ�7çg/‚úüzGÜc@ïµMy3j�½^çþݯ¤‘€o ßc ¥¨ÅnAQÇE,Oa’5]-5P-5±íéò—™è“êОr‚­P·XãÛå}äcÒp:žŸpÝÀ :¶�62f#–žÁnGÿ"œ ܘº€l—O"�ýjî|i ¾õ*è¦Iª'ß7óæió1e[TË Ã.nñZ›tîØWâ05)Æ p$Šþ*«íØ)»H)ƒ>¸ÅM#È °©µM´Tú0ÖªàcùV(W‚%gø¥ ÛÚç¬ö³â<æíÀ¥‡ÊýäºÎJQAšÃÞe"íwø>ÁMå7� q ÙN? ó/;2¯Ö»¦pAšçMáè™L‚ýñ"Ê*€B�R4¦Lþ" @¸—‚ÏÒ>´nä¯}ñ l-¸‚owSAFúåà°<µÁÜÉÆF¹h¤ñã r! œvæÙCùî�㟋cà3¤)>[?à_Õ  ?kGAÒs-ü©ë??¸%‘Hž±”²‚Ô~mÆÙO4F8ó jø` .ži A» ;²­ˆ‘\£Œñ¹f•ÄÅGF8J– º9–³CÈ×99"7lçå¦ /Ö:Ï>ð“…õJŠËýL ¬ø-@ÓEñy_m‰éƒÞ§ëÚ5~Ï\³¤&›eÏ–ªu¬fåNµŒ³A£ªÕ/#.PZo*jìSq@óSnÿXnÎÎcb2e| Í]AfÜXÞç"ù³Ÿa¬ �q54 ò¼ÙËZúüÐþHÇŒ‘[‹Ë™öB¤ ½•Ôraö[8Â¥‹»kE‰ÙüyŸÏd4lHöø2Ï—2<Ô0K­MÁ“ŽõôÉ‹ v+õ'l°†by‡~å¡aª ¥pÕÚÁCoJc'S ¿yMƒNi±8Bc*@ÚáûyaÙQw¨æ5Q3OèW§>0†ˆ‚<áÊv¹"«Çe®àU�Ŭõ¹U�>Ð:[~üƒ%Òò¿ò~NgtÔ0õ™$²›âYõX.*„þNû™¯¯ZG¿ŸhÞÂýY}Í^ÆÃÀ=:ŽÄŸ9ÞÔ•¹ÿàNõÛq¼a¥×…Í…8yó6ÓôÕxb¡·‹™.XËÆdÌ ° êgû˜ƒ•‰¿Ÿµž;Ô™°Æ—ÆF³.¼?ñÔè(còXÙ½<�T,mØŽÊ­„$©õ¼æÀ˜÷ƒÃuæì%ó3_ÆAÌÉ¡¡GŽùÅ=1áStŒËžÞ€h–·H„§JÕ@¿€Ý¼è3o‡?•~,L`›î7“Mÿ$ ¾]Yk3VUF.é†0°GYmCš>f:DÖ@¿æÏ TŽ j(’mÎ>¹ð?ÿý"ÿ@çÖa�2š|Sҵɶ+TiÍHѶ‰¨�H¶ÍÈ’àà;à¨÷<é§Z£Š¸b‹î¥¬ÊH‚*‰�ï6Œù$íÄ(Œ±M 襋º¯2Éuú“«m_MZ|]Ӈ߀pL›{Ü!T�Ñnœ�¢}Ýb"²WHV�ï»+3æÖøßJO84\Ú;ãú…sH›'½LÙÚfeÏÍA>´«à›-Dkq X?W±"”ªJ‹€ß”÷ˆn•û�¦� QâNwו/LÁZõ�¤�@>ã’=RÌĤ" ÊÝœ¥ê‡³eÂש­Ë�—“íg+’c"Õº E)Æ£†ª’)´f<§AÞLFÁhàXSÙc„>4éÚxäùUß~rVQ)í�Ýt;lôºç^j„­-,Uæ«l­?ñxÈUÄÝÃ�Še+<2aFÁÖÝX1˜Uú7Ä‹“ ¨‘Ž$Æ÷¤0®%Ù±þó@Ë·Èì²¥µ±±Iudyæ—5PÍb³` 5ïéAø%&£ÄÙã+UW+{HÜo‡0C»M%Ó>yù‘ÛmÀ �SŽ{† XôP•RY´Š¯pm0Œ�.†ñ¼ãHp¼ö2Émº)£&H¥e˜a‰L˜W“@`†Ï^£ã'u;-`k·!™„„¶ª@€z1$ÉÚ¬851pß!ª29£ßï¦Ã“Ü~~è쿳†æÄ0QU&²•[ ùî;„³çØÍëæ­9¥kž |§£�¦Í^cäc(öx \ˆæÃØm‰|€ýlÚäkUüÈp\Á¹�pæÍ�¸[+_¥L/·lzª·sûq/ä�Mµ—âs(V¸‘½•=Ô­+¦ÐÑ•±[üL�à.éo!J(¤õ·aºéáSײHHÞô¡k¾éZ4Ý;[‚Ÿ¢º ¹Ðã(ñ›}Î<3ñ¹oæ&ªX¤#P·ø@ïP$õØ–I[r˜IÆr?]öýëø…ê%lV ¸ƒ¯Å{Âë€=·Š}:Ô>ŒY2&pâ’÷ÖËͯN¢V0â×Éÿi`Á<\9Ô ¹ós@½ÔÜ6ìÁ 1 ”pšVEÆ­³?¨¡¹ Ý 1«GhÚFdÖ ¹µ´yÁ´/Þ'fy[œM �‘x"ÿ¡Êö+æËj6Ÿ»½ îžŸ—·„…Šã¡<œA,û[£d;úðYn ßÊ”2}ÿ½JU+üñ º+ll°eóÖò3œøé:yÝ�¥z„h <ÖÙÊ´–½×êSÊœˆ6¶¼ådž‘sçIÏ=©¨\ˆ·ìÍÚÚY2Ûª‹R›f‚%ƒ15i³þ{N; �Õçß']莀2vf�ý²§… �lë~úÄI/{«"1$KÜP2i³Ši•™ˆ .h|&™ÉëR¨¨ÔŒ�[}©ë¬ÌgÙB=Ð�{‡Xi¿��ÓGžò·iu•žeœ/3û:˜ú,)êV÷†8bfÞ͘&P2ëQ™�ý˜2¦’ÐÁÕ§æw(™š¨(’ûÿK4ƒKdåYb—ØK?ùñ�´‡–ï<‘«^PŠ3Ð5¯ñ#Îj±µ"ÎÖ9)\Õ�VRª{vüœý›²Ã|‹ ©9Z ïU(_¿&§<‰þnÇ8Õ$bWk;ˆù ÉÆópò»qQâj¶/Ì–(åë6GA§ÚjRÎ|©[‘9E{L^G¡HÀ“-:‡iì»o•õà’…˜ñ€_¨cëˆqô¤à�6 ’Yà1ò=ù@Xxs�÷oã‹1C‘ë_M:zÁ”¾û_‚‡. ¯Œ$­ÆÝµ}AÞ —ùÑCÆÛn š_L ÃKÒG¸îÚc³'¹r$×·ä›}³Ÿ¬n^øÀ=¦Ï¥ó[c™œ¯‡­ë® ö‘t¿>?X€gÒb‹R’³:œ5C7’t}waÀÕ~Jí¡myòŽÊä-7¾äP"ø¶â¢óæ9ë{–€zI�*‰‰Ûù€×Hóéƒø l„oÖÛ 2å‹)¦XUb]HéÀ‚ÈÜìõgWÚ Ã×0¹Fç*Iø:K2ðsˆýõÀøAŠÏâJ1e®fÕ"€€ç«±¥û¸é û)‚6Áë¿þi0úÅ ;Gxò†¸Ót”ø¨¼{ò wП¸+RïúB»^ï̽)ÐhrR(ʉ´´9¿ÏÂ¥yACܺ>a“?ˆqPhr¬Y~œÙ+›ÖŸ¤!÷��õ¬Uèóÿ»R³“Ê/|qUlü—hSÇk XcMo~À˱�t�eGŠ@{}*¢HZñÛ36ÕÈçž~÷( ‚9oxË7ëWK'•­YJ2|Œ÷<§B—¯IÛÓûÓ²z¨/¹Ø•œ€ÓN½lõisêràdLHtÿò62ãMÊ&ù¢9=‚\Ψþiÿ¤Á~!DG]6N±�ÆÍúÓ]ÁÔwb…uÇ߃ÑeîJüçߎâT`LdT”/‚ï´tR �¤ÔÒÏ ÊÊ5UROYÎÆôö$š":†]§äwNPpjwŸ[%«ù†›V»€€Œ„Éßúónõ¸V9I¦Zˆµ§ˆ+Ž‚É_$ÑÓP;†™!:Ð.Ýˆ× çX> {% ›‡.®yBìk“Þõ¬ƒÏ&ôG!?[£höíçœ6é�᯿Tn�ñ1þV%äÕc9æ÷¬dÈìŠÙÿôáeeKt-Ųú®$?Dººù7{nr 9š½kÕ�Å0žhþ½ç†@JWBÐÿZÀ‹*8ŠJ¢ÛT¹°ú8‰„�‰Z.:ïñïâÃh$bO%¼3•“ݱK(‘J{¤V,œÑ—O&Ò=ú,ú$úN�œÇ—²”ýPaÉ×>0�s±] ^OöÀc…G1•=½‡8®rk³ ŠÓ®eUƒ*ñ¥U½N‚*™£‰u¿5X¨Sº“†ˆ©ò¤V犂ØÜI´vo~=äÊsáO4lŒá¬� Í¼"NÇë°~Ña(¸3�^®68„ï“RÿŒ¥åO= ˆZuz÷>Þ«žÈPóä+¿hwFù®œã—î0N=Â]ôÒœ= �ì ²_«hm߬hè9sOañrNyiJ»p’B,ÔÂñÞçÃXðM®EÍ>ªÅvvJI8]�¨þ@ƒ¤ñ?“ç¾�µ»Ü¥íÍJÙ‘0eZ¾f?’-0Fÿ^±£¶¼”©±?—°ç­Mã>ᜄn!WcÝ�G´[ q(uò‰œÚÖÝhfÛg¹ñÆÔ…{¹³‹”L²œŸ™F l,:ü|RÀ+3¹æ2GHîõY¨†³8×±_± ˆÃ“’À9\F ”,áwix4K™·s }CYKûiÞ÷0›òAu�+Ú«/1ua÷bs²Ñ]‚؇@Ž¥�ã}˜ÿn¢�ƒÙ+[G)Ú/¬š6kiî)8ÍÁê“ÿ(½ö½ÆXZ`>­å€�fцˠÄ~ïŸwŸƒbiFG•_¶_�È»2‹Úð(ߤTŠÔÞnÜ?_Ð\�À’Þî¼ÊTÖʱ½er£Æ—+�Z! vúÂü ®1<‚·ØTG gHi9’]ô e\6+曹~¼3Xßyº¬± Àþ–4Ä,X]/ê�Yã*õÿr<Œö޾RKß<ÚÐaÉjk³A? x*?c%üªö›k¨¯ª.owÒgbgOPÙ²SUÙØ¬ûùø(•xD»¼È]' `=¨ä¥®åðH:à×´¡°^.—ºLÔ̆€/ú»êjSô¬EÏä½ï‡©kýÓЪ– !é0�œµ”äW¸ª�[0Z¹”)å94qå8`ðWá+è[Y?7‡0¿;$åpmÈò¾³w +©­…/e‡&ÌÄrDNÎYåËÍzA¡x‡œ$I0 |sö¯S ÃëóèÈìÍWSH˜ ¥~èb-ݤÚXûÙ×k³¨æÔãç;Uñê†UÜxé?—06îó2ÛRH�ú—0†�‘%q´é>1ŽôæK*f79…縩÷OwûAá"! `y®[Ió{okOE�M˜¡íë´tˆIŒvßï»P©ÿè5×VF“:W™C�¡�I/³­ÔÖæßq“‘Èæí½›¹ÑVË¥rË�9î @P‘s~«µ¶;[þmдQì˜r‰è„gÒÄ“¦Ú€ÓÉÅÓér4¾!DÍ“*°�y=ö{w˜QOÝ|ˆ^Z M$>Í+`3@vsUûˆÈ)𣭿xm�ñN7ñYˬ"u�˜}%—ÝEîqtº…ûŸðôµú8ÃܱéF�†¯Pd­æj*ØßǨáõv¨ô¯ƒjÚì€)»‚—E&µ«bd�YÌ´^©>z�çÈE6’P6¸ÔŸ~#žˆw¿“, �̄ؔ‹pÿþÀ¥xŠš@ÄÖ»®a¹Nfº]o˜�WÓ«!Ö«*ðÈ,ˆTªµû¨ðŒ;…dެ…·íy’ªr‚£û*Z¨ú¯Æ1øöµ}µê•ûN®¸Üðµðe~Ш`!/ä¤9ôRX¼•¼Àz…r#Jçd÷œ—  .Ç%ªòE+ìàÐw®åŽåƒ4CJÀ˜ §¯†07Î5ʲ™B‰›€[±~H/�1«¯ùz¥× Ø –ü�Fi—™wÎ1§AAá±!Õ�äÍL)yôñÑlð"³ Ñä@@ ÇBi9�ò°˜.¹”ìS ,Ñj‹\!7yù0ÙEmd„“BÉ⡳*#±�_lGõ‰îtVwžz�ßÙ*j¥£²m�K:ÅŒà ËSMúÃG¹ Âáx™Œ§Öãž_ĪC­T¢¸(—uß‘÷iã2Þªþ;[>á5¡Á,CÁ8�N¢ 1*Ù÷�` ¦Ò‘Îð/äRº@2üx¦wï *ƒyñ�3¢�²DzCà‚©± ÍË×;ÏoY"ºpÀ7Håô^— [hø×ê«¶j5iJ ;¢b™—Êyã8jJ²{PNÒ®î[7Q(¢nËš¿‰‰]¿„¨gsر…üˆ%ÿÂà‘dw5—*á]†Eã"Ñ }·>³ÁÙAŸd”TL'ÿ Ú3>€OU¸YžxË쀓éjxS„€–˜¦<3¼ö¥PT²Y#“8C|=K0æ¾?¯0Úð÷ñ`—êñ|îéʺـ÷�=ÿ¼e—þ­©± ”vuµ-34Êÿ¶—�ƒ� þRÅ6¡ª3¡Ð¢}"� „>-�—â—˜…ªÚVsâ©…«÷cä̸O¾3ÿT-ô¬d`oÇ£kpú’Ì(cÐ�íÀ¶‰BrK÷êÂØ5ÀÁ~íÓc36ê^oÈæƒ©©´&p"fP¨žóœ”@ùÒLm4WÉO¾ ò“ÛPí› ©KuD�?ú>”nsëu�_ij¢JÍ‘j÷`Ÿúû#,“óûé*^RYjÔý ¯� üÌ·jxJnÈT%ˆ1_ª²Õ`œe–Þñô‚L…mÛ|pï½X˜ìà4‹Ký³¨MP½‹ß¿ùJŸÑÞdކEqöøÅ´•m<õì(l¸`pÔ"× e7øJ1–ÑyÔ¼t¹fn¡ <×zú¤ŸÎÎtì{½qŠÑÐ�¡f؇¸Ó�¯_žGyÛ׿Oe)¦k¨¯ñ2Z:bM®®¦ÛÙñ@�숕2Ã{¼›5É^Ÿ$iÿÁ‚�Âf"Óp€Jâ ýö–çþà;@£~ALEÁVÿz¸éݰ'6Âd—DC²¢ê¹†Ã5^¢HØÈeh–^œ+᳟&nGÿ™îko {¸Ô2Z�C¢Ø‘Kr@D÷aÒ ÌjU2޵&TÈE±ž\L mÞP"(‰]aZ”È\¼}ÖC³Œ€<3R©§]˽¹‹*žô„KÍxš.?÷ÒlÜŒ.°H83]Noº ±Jó7qˆ,!­=Y*§£ÀvbðÉØãŒˆ=´~”1¦HUmOª£¥€ ÿ©–=°"Y A›)5-dÊ`(˜!ÿýñFå-ôþ½mÎÈà€#JÂ.?öñ'rhg7œC޶i�{ŸŽZ(�‚}xQ (?ûÑO,á*‘ -~‘öÐ^ 7{–¨TzOZ¸IæãexË øÇ¶,O¢Íê#;-?´+Û‚ÑPP ?]t£7Ùwž©ZFX(#ðÙŸN¯�¹/äÝ�=Dº« Y,Ý¥! p­pCw,·]émß? $ò7ø ­oAœÃЧxÀ‹ÍÕë<0‚V#Kzα­ü]Ôâ^ÀzÅÂø BÆ�y[XqЏ´<�/¿ä\ªµú«Àßô ³–·�l$iÁ†`[.ÛvwˆD?FO¼Ÿø‘�ï‡M·@Išc�‚&³$©â[Ä1wÀkk½ŠlÌ= |†9QÀùü¥ÃY!t‡Eµ×Îy�]ÉþÍýàïÀ†(aŽ3©Ú„*XI ‘x{A \x0‚×>RÖÈ�.lêP©T c¹�pÿ%�y7(•O8wfº&û·Ùð’m®m�‡¦>ÂfË‹ãñ)¤ðö_§šÿxEµoâÁ]ÏÆR‡Wˆøîö¡‹_¨n�i)^18�¬oÿ蜄ªØÙ¬¸ü¸U åæƒ3S¦^Õøí9ûÜ·¸Ï&ÐN0£š½Ó +æý-0YKH5Li×­Ž·ŽKŽ3A¢»O:˜Š”ûœÜEÍÙ“ýYv±>_W;=‡(—÷gÎ0ÎU�œ5�|´Ä–aÓ´ üÓc'Oq>d¿†îïs®;ÈLkf4�$c'„Ç´ü;¨3LsÀ>›�¢ d> M¦‘óègi‰!¿1Là¤p¶ n­·‰Ù’æÝ_«2Ì'+Xö¿ÁgœÂa×Z;ŽaœX³fÎÜQÎ)(–�èY�;iÈIµ]ûó92 G}† ±«W¾°­VÜR§a;´ºkt„À�§¤ »,Unð8<¢H/„üÃaçBª‰ì$Á ›|¥CÿÅa„‘m8‰t8¥J, ¶þNnxE•a|s,HxxÌpISÈ)d¬‰iĬ^K9aÚ›tekJLÝpLr9ÈP {ûÉŽéó®Iå埞1)…¾EX4W!‹Á>•ä~˜ 4ߣ·Àn² ù¬˜ƒx´Ò¶UÜxúdÖ%L°S÷�Ÿ!RÈx�hS$ —È+¡,àc »í„N Sp”¶þìÜ]©ó½©±ëÉ­#‹Ñ•š¥j"FuÏ3Vn™3ÊÊR—EÕ¯êáó¸ß® Ly&¤Á'ñ‘‹»5 çÏh?øóñÕÈ1må»;Ï"}é;;KKç|-¬ŒÁØý„Æ’\%æmbÄK ôm�#þEH¡ŸŽ�”¢ÚÃ;PÆÍ&²Wò;=·¡0›ÜïgB9åpÀ›ú/û®BÂvÈ)ª¿cÓ‘£1uú‘þosI¹i¿¿[kŒ$tgàO£,£¤†ó´%è<ËúÙÌ•‘¿ý‰t¥„s "ñ° ‡Ú¸æ-Ù1å*”ã�4t%2èk +­%ûL¤±/CBwM‰–oÿl, W⟽³SÕpÖ˜,ýÖS•qãë0«ŠŠ5<.ñÁFÏ´æSYy«=U ÙRŽØêÎ8 f蜕“$q“{ k HÞ¼øÁñO]ï�Ã:6¤úe2p€d'FÍj\¹2“²_ÈŒõH4NcÈ?s§‚®T;êrgžïEó\ù¥¨�Ã&ü4#H ŠyOþlè¶!·XÞ·ùÜ¡f‹áÿh,Ye9ò.yÇ“;SõiÁ|�ùÜ_ð}?u l�'ª‰ÔÇ�Ì¥ÏÍC§dÐ%d‚âƒpÅ{x-Ð#Mýª=4)œùQáŒ<åŪþÓŸ` zièEäe¸žI*~8’x”3¦¯OÃÀ—ä�1ü† Gqe­Ð Ã�å 2„¼òm½ùz?QþÌÓZÂŽk^pcÏðo|}—4Vøl-ùw˜ ï³$½`×W|  yþ-zóYë.'ñ@Ü® �ƃ3.èTxßÁÑ=°1!]’}Ù.ò ¿ÏF| úz�á ¨Z<íµäUX)}>ìYƒ!xvC™Áª€�h=}eùxf&D–`iX� 6Ḭ́DQóÁ˜`5P^Ÿ‘#b°¼Ÿ‚Àn"+[ra·[¯ûoú¸{ý…'%™tèDÕôf+¡f€>º¥ÆoìYu•/+{Ò¨<‚GWoÝ$*°çƒÝM°¹Žd¥Y§{hRR³£Ùô¯à ŸìÙ›s9ÍÙÁ�b)wí˜&�÷äŸ`ÃÆ¦³´-��±“ã~•Œ#e-½Eò¼ ·káBnÏ�)Ñ·Ëdzù¼C$oï€b³gŠ¡£*Å_‡‚Ç27˜»a­•ÞÖRc‡jjÆÀuüË�Xñˆý+ôÑz&ŸêÛHnm[‹ö‘´!v¿‘ò|ÀŸ!Pw²„ä^‡q‹n~sÐõa·öàT7Æw£€ j·IÞ/›Œ‚9ûR¸è`-^ÛnçS‚‘Ѻ›Ã¨ rà®mµpËAÙ‹?ÞT¡ÇÿÈOÐDsû  K½RM3†'›9ä6ú ¥ë×›3ç�÷ ¨>ù7. °Õ|à~Ï»òÐ^�‰"pJN¸¯d8˜/5àJ´â;™·–z¢]6ˆÐÈ"[ºžÛá¿“7݋ѧ'PgùOP¯ïè_Q‹qb§Smë½}ß'Mr+ççq—›|)%uÉ¡ÌG}´C>G‘¢ò\ïaoÀÜaɎ¨ó½’Øî”J0ßgÃç¼{ÿSv¯HXø¦~õl.‹Å¶ÙÍlßÁ�¿u{‰p0 îV:±A$ä%„f®np¸¶'¼ÑfÒ£¿fdçl!Øi¥ô}lXØl¸}zš¹E7Õ(�{=Ù·:âN¡ww5Y“‘…Ì?ôn LÇNˆñáüÜ¥?Dt+Øí��p º}Í|”´Ð]÷Ï‚.S.O²aÓ§ÑsÉõùÑ/áfýÿuÍÖÁ3€‘ ·–oÉE•Õo&(,ø©öÅ`ïªñ¿nÿýž‘´H‚ûg½ë>cã–öÆy ßų€ºÂ]Câ¿Î`\K0¤‡8²ÊôÒÔÞf”l—ô˜Ôý}^Té™Ð­ÕÎ+0?ßëæ¿rBG±aC±‹yn³aå%hxçÕ³ú¡ô¼L²êd|DÇD™³Žš˜yb”'eÞt„û,®·¯ •ß m&ñ¡-5Ø7ˆ>—\ç= ‹n«}d/+Mùók¬]G—p÷z--4|R²”.ø^¯­N 8)=‚(ÆÔ+AC#�³GàB›B‰á.z‹Ë³mÛEºC 2tÐ5;åO‹@AJ“åoÁï[| H¹5Rðu±ô.�yäÍÆvÎŽ®Ãv=eøbXµ¾È//Úo*ð9jnô�í×”h1ƒêڮн«Íìô¯¿¯A.RÑò¢°“©·aÌóû-‰pËÁnƒ¼tª…éáÃè¼[A€š�âåáÜì Ú”¤mk—|_W$}s/óùò* �/íl_/6O�¿Êż¶´…W&.Ù÷t›WÚßkõ=ÝEˆcËÒ}NäB˜ðþz¨rSTø¨´¹ÿzæ^ÉV2l?ʲ¹xv5�áSa+êªùTÅÀ]Î@#0G½@,Á]JB¯³äueOZ…y_B§¼ð&¬�ûSò!õŒ§îÌÁ¤kÊJÛr!ä-¿©Qï,úí³¤£„ºæˆ¥ $TÙSÀFêÔk48Õ¹S n:Õn" ĺ:„JÉÓ[Á p2€“L(XºX £7ïÉçz>ËJ±p9÷Ñ9‡Ú 2÷•Õôr=ˆ¤y�F3ŠŠó 9Î'ßhŽˆ±zne«ýÏ;3%{‘pÝÊÌGñ?ܽH|ñ×[Õ8lZ­›åJi™&²OW âÇÏ´ÇÇ>ÞnÄRÚ5šE„ø´‡Ì9`n'ÀGóÞ;“”—Oz�+~!å7ùËŽÞìÆ— ¶)Ä µÅüUìA·yˇ¾]K¼M^O>μa%Èp¤‡Å¿K·½²­P�3�d,#M;çA›L BŠ,^ 6|zX7i"›.\þ ¯ênímЂÅ%É®²Pç›ÏVAà Ï_ëŽ\?"�ü»”%¼ES\C*ƒµIOÇð@ú3»E~¡´¨) ù>öC7wi•ažçÅøI«*ø¹=aí} Q¿ÄÛ£åb‘ Ç[ïHèjÙjþ-ô}wÏÉ3V¼ Ê�ýí®J?m%Ö£Xîkm4Ø8¦'`ëT.*ôÊÆg U\”Z‚ƒidÏfª5¹ÃËìVÍPzY›x”Ë—á8èb?ó¾^š Côí N{—›l¨VyŒË³³OnÓÒµ·ƒ•¶síËÆÖ·Tž`=JŸByàƒe›;fÓ¶ÍP�BÒBûèÈÉk›=co‰¡2¤ :ªf áz«\ú =‹%ê�Îr‡Rrq¼\xºÅ’ ·x”1£`µ‡“-æÑ½§9E°µv¯ðÝ¥° xHd.‚uÔ¤žýkPË|]î©âŽcZ~ú1ùsû*Þ®Òkàq}2²%)ßâWîNHRßÁ'gÖw‡¤Íøî'ñ6öã(î¦S­˜ÙH’RœŽÝÎÿ¿ÇªŠlOö*Þ ÙqŠû— !,bÍ2}�ßß45ýîÞvÉ.0ôONîZ‡ä¤ìZ§eïµ?§`ˆ3VóšÉy¸ïôY0µCØ|ñÊ~µ'ô%“<“î÷ÆzQâr>šƒ^ pr,É—©”ž¤ÿÈ‚7¤4Oe™é8 ƒ*qÿ˰µ¼)Ì÷ÿ„zï!*)`QÝÙvñù²${ÂRYÓ·ÐÀ» ÙʪA¨…ÍÏËQ …ÉÏÒéN“ò“ºK·ÚÁl’oâêÐ|œ›•ðúÄË)ŒÍ¾’±õ�˜ŠJG(iPÑ•JÃ`B6Æú. y¢ö°þµ½ï™›‰�ãÂÌyÍ:PþcvO=šGþZnÀxìóð"l¤#‰D=è¤ Ð%<��Qã4­—�MëaìGjÒB7¢(Òõ Ê… x†âõ> ÛWªÎfÁcw�n? šÛ曞-%¥7pd ¯AhǬŸ�Dâ1>ˆÀÅíæÎ,qé%ÅŽÇ#àîéø…¼êÊ“{Šä"…àMÇÖ™ÃW‚ì(£Š“M•…>½‰!’lzé>^ |{„ú–›`®Çîå·¾ìðè{ÄÁi!i²¹ÄÙÏ‘*S²úÀ^lµ1Êcž¾Â¯$ó°÷£¸øú|žFFD…BLúö¥ƒD(W&UÅqªA–[þMì#�Ìÿšð[.„xÅ5f ,¤NO ‚H:�kÈËþî€ðÏíR„¨‹ô›…OEvjVAaO_ÇëIpµ¹ RhDçªUÊÞfh–ŸªüG‹k�¾œ}ç–ˆÜ:ýñM9)óÌô™>KA ¬Æv¡F`þY•-X £óÚ…ÙþÇ ,ñÒ+…ï¯L! ÄW2rž½Å‰¬á—�ν |}éîé€ÁI"‘Žr¯sÓãþÁ56²9x»ån­âk’‡?}ùëYý Á½H6kyüo É{$…Ô™M;…˜¿ÀïØ½åÄÉè‹,�Ãܰ{¸ðÓíyͱY‘kö7ÄSD4�šO Äò´N¥f4G“Âý»ò! °í=k °�õè A€RО!¼²v—Nó=}:ÝïÄ^açzx€` Y~¹xèq· ¼4°-6çègQ‹®)ô:—åÛxrBÆ8ÔÜ\üu2¹T\Q;˜Ì`¿ö6iQHšÕ¸M=W¨†TJŽFcn¹2ü‡\‡n$öCãP“Dä"Õ2 oè`¦‰”#?õÆÍ2�Ú¶ûoPLæž ÿ¡ûo–Bšê¯Ùª�•Á>Ã!½ÝAzìÆ~¡y>¡êâlm)܇^ªvÀûÓÿ�~ç°Nò'n‡�¿×øÂ¾åј ê'ÑÅQK]¼»j}ÍÁ›Á¬Á‚éÿíçü­;îÓÒbùØÃú7ý%˘Îo�)Ÿ)�3ç_`C?êw%þ~ˆ2Dr• ò¦.•(„†Ý/Ë\p{xþ² ½á>aÒ·r×,DåÉŠˆ�O¼âçZa*^¦ÜÕqÖ�"uÂFÝ­¯@er»˜c(w©›y�~(!ËÐu퉮é·Ü~jhõì-œméô3®]ó ß½·\&�^é¬� Ãyί}OØ¢¤º1©ˆØÃj+gLƘ§Á‚»Pdl®¯<¢¹Ó¶"�Ý®�°·M–#qF`GKMGçŽú?7)éÞýÎFn'Š©)yôÕZ˜CÆô[ê� ´é,-ú7¦ÿì?Z¦c]ë¤�1µ:z€PVõÌÓ0æÙë¶�h3ß! Ë¦³î¢|­R s(4æ=qÇÖ³<"yù °ôt�"Zœ„‡Xàw.zn!Öµ;ÃûÚÝêÈï¸Ú)ž4]Ax°XçÅ‹Cu"ÇÓã:û,§dFQ,’ˆfá››�"q€z¶éÍ¿t]P‹JÔsÞ'"uM�ÿíÐîðgÆ'™€¾Ð™¤½ðÞ:I d¢Ó{À÷ÝYV±ôCÊMe£Æð›üÚº?aÆKe%ŠËݾqA&ï{V8±�ÙCGÌÐ{”ѯ�É1_î?u Ñ<´Þ\YC×[zpÍL妻„µà�K}’›Æ5‡K PÖO1ôÀ¼©_%év¹šˆ7w}+“Ÿ‰¥\QÒh�EÖéƒÕã]qsÕ»@Õy;nµœÞÙqàT\Å�ž¨£¡ÜÞp[°€á߸ Ô±ª�ß!ÙÖ{¡âÔ÷w±uÆDndG ¯ñ·žA'ÐÏÅŒ)+°QÖ†îý DëÂÈBÕ6@�ZO�ßNídg½øœfé”#¶Î„®Mö¢Þ€V‰Â#·±±A˜†2žá5¸s,æíÔ¿ó }hj–pˆ^î–iojDgKm¯¡¢µÂ@o¼*Ø7^ކÈE¦b”‹gÓmÈ7”!ϳ¬Ñø'>šêêÑfÚÄZ£öÑP¯žaÅ#¢a¶íy�8GÍyÀC¤®âº|}ðZ~ljDÁ¯Éh¥3®ÎPðúŸ•AãxxOÜS˜ñO×�Ä+#D’µñ+ûk™e„c±_hÚÊ5‚œ†?iB@‹6m+�¢®XXvð° U²É0“¯N9^¥èã¤}*ÕÊݸ§(wËÿÁ2¦ë×bª4ÌdHîëÊq3�ž1X&ÏÎ5ÔP’Ï`Ú6”4û|$ºÇ�xhd"›Û™Ð¶ÕPiR®N°§°yöð~9fM}Ófb6UcZ$ñvºËãë9²6ùÙ]�½�5µÞXhzgªµÙ ÛkOªaU(ÄyÁFwQ¾ØÆF÷ì»·6ßk:'RCÛ› �ûuLcÐ'H™KÿýÌ}ks(ǤڱææÈO gû” æaÇ>NT¦�T{úÓÇ/z‹LÌQnúSy@e„LhV (NE«™¾¾xýÒLåtƒÓ=Ò’Ì&|Sвl–[rB×Ü�NiNŠ F¼ÂÚ‚ =A0>‚*Š”oZÜ“¶¡Ðò·0c¾62KBÅã±÷cž\›¸ Â_%¿uø°Îˆ®]e~±Ñ�Øí ¿ÙšU'6é³à[Æ+þÜêöúM"[�g¹@ˆ™Q_g 7¢­œ7� Ž1Ìaðñ>\×}i*ÉQ³94�ÁGS¢²så÷mÁ ýÂÔfëg�Îı×ÙKá{Á׃‹¨s}PØ©Ù�[ŨÜá&”KñÁ§¾ÿã&<ÂÎlõº�Á=Ͼyk1¡†ÉüÌH„XÑ‘ôˆò)Þ`9r©—ßiz$Ü© (ËÜïfWÏéç‘Ó¢>Y &»ùWð*hÜpžl¯{>ryeòÄ]Íð%´Œˆ1û°ýGÌ ƒöîðBÈT{Àô /‹J¹Ùæ÷ å„[ ?B!óç ë†Êz“ÜYã?Å¢ó�ÃÖH ¤„3FW`RSQ OúŸ«š(¾µ� ²ÓÈ�¦Ó®­ˆÖÂUÁ›~|ÇLtRÝ-„Ú¾ ¬H1&^+ntÞkÃÄ VÐËIljª¬žŠ¹1Y¼3£>÷K ‰Ð‘¦›£y·ZrI©™kwT‡� µ>õë w太ÛËÚÓ÷ˆ›ÿÕ Z¥r^Ù­LoÎhÈ¡÷_Ú¹ƒù;8Ù\ÉV(MXo*^Ý™“ÇŽüåÇa¯ Jjkr¸Ù�/9a‡M²œ«³f ‡·ÖÇÙ3Ã6T€ÿ¼uתcWïbxÆî[ú0³€9ÚNâ§d›“ÇðÅzô©Bóq›»ôÿìÛÛH™«?ž ü—ǪnÃjXNU‡3ì+à¥' �í wzçÔ?‚ƒ²MZ«[‡ßgQzN•r7J>Ç5MŒ'aÌË+¯)¬Bì#ŠòÀ�𜒛»é/JÎtåÎé^#d5?}Nω‘[˜�Š™‡¼©ê—+Ð^»)Pd­Æ|ùH¢ªè0v6¸>€@�Á‹!Wã­ÆÞ˜žBÿß5 o6ÃË<„÷vcñD‹J”!ui× µ¡7f%$`x™tFa uyNtb\lvù º|ÞYvr7Ašœ#)é@ƒœŠ’sO ¿B¢W¦Ø©„• ¯B~ #pahlÏòùæf5˜�~Ó>“Îû€˜zΨb3Ñ*üÞ4ìzÉAýÂëTÁ¨K룸FeÿÔOÛIv Lú×P‚j/: s­ÅJ÷*v,H;/…�éË€•£=ý�œs†Ö*�Ï"î,1¦‡"ö>Y…'N'xXeƒ#ü¢]«Ýƒà“õêuMµ-ì׉Æá¥±ÿ=²­q¬0gCuHžÛ SŽz3)•r^~õBWBïïZÿ÷œô]ŸW´:ËUh5w'HW/t^ k ·UY�Q—ãšt)�ËžûÓ˜Ÿña’rì‰ÇŸ¼VHÛ9§*Uö/SÛ+ç.WØLþ±m¬ �œ¶d³dHê£-VïT´é½v0Τ˜¤H2îÚbÔ¾{á§o‘ϹMËÕ¨ob7”6C!XÚ^~>̇t¢„›j%ò†E#„Ôn-µy%²Ý£žêmx¹WH!§ÑÈ“Î�‡R¾æ¶m•W4~¼è„rëyuDú—“&�ýøµ‚n8n8Úƒz…iw‹ˆ­f_`VEÎ].Á_øx´À6 ZWî&ˆòwˆj‘àb÷~˜stÙÊv3ˆ#zyÐU%p©"P¯ƒtæËx惱’ÈÚ/Ñ^dMêD—äoæX4ERµD¬ÕwÅ=åÓ¯³1¡)U%áÙrM£o Y'@SÊFªs÷O&Íõž=Ín@Ælm N;>§4Uy2�ŸwKX"JÓ$ /ÃÆ Î1èS `€ÖÄ㘢àPÝœ�ž€Íñæ§ø•’!�jì¯ Ng‘ü™Óùwv ô+gYÞãf3-«ŠDG×R¼[ÂÄbR.Ç·òŽ’ø˜ÝßEl,û\Ü4w÷+IÁÐo �vsH˜v‚1xiòŸïÖ ‰É¹4´þ‘h’«¼®~r÷»êõ[|,±ŸPÑ)*Õš¿Ù;ˆùl•C6~v›Ÿ9˜,`Ýÿùo‹:ú„Ôf«B=wk,š‹]ÄéñMf‚œÃ8‚µ†Qt3a¾b)"k,§—T^ãH´) ú3'2¾ø–¦cÄ|·¤0Á²geÀ“´ößÏ ðûÀ;È‹1ånß#fê¸Ð©ÀA#g>m–7€ÿ³ÇéG˜Lq•p ]N{*\ úÓtÇo[wpUü]eáMáGÈ¢¹ ¹«æBƒŒ^À¤SÇéþ‡Òú¥ï»¸|Á ljW´»1Û7{Òa_½fu7•˜ÌM� Ëü/‚Pa§d ç¶²ú�­'3A8eÒ¥mü*øõpÃí¦�ÔUôílæ?Üœœz §Òä¶G„|™ŽŽè=šAôE5º|�Mñ«U¦Êõ’üå¸É“ˆŸ‡t¥Ãµ¿иn«½çë~íMh˲SÛÑIçÔvµO)1kÅ­ƒ‹\Ȧ=©dQ-48¼.Ë9ëu/['%ò¶h‹¸$œ,Ôž(«•½ÌBkÙ†�`ñÑ�&ïŸYàB¥¹Ò²—ØBWÚ£< ˜ú£ ˆX%‰}WOºíbQs!Ä4ët’Ûn904|Q .ÏÝÑ™•Óåj­SÀ%ü¸¹`æA!‘¶êk:buFê:Zg÷(O­ÿmß==ôy^<óÎY#âÔEWøpxç.êxX8XD=&vWÓV8›Ÿö©žèr;VËY§rÏÆ87PÞ/¥ÞW´‡|ä‰X(C\<[þ¾k[{(j#ðP¬ý¾iɉ_äÇ}�l™4 söEHÌ*Jå�«¶{Sûì™Ü·pº™ˆÙËn=Ë(X'ê úƒg%qñÙÐ Ø„Åðà9tc À̽•PÔãþA–¬ƒi{ƒÑ!ˆõs""<š.‡�hȺ`ˆ„•£¿F.ÈU¾å¾cý-Óü e"´«tŽ5YN’¼G1!Àé‹ ø7"­“×’<#mæî±t¶i‘ä2³™·=xʂҫøU}v-`[¥W!ÏÝÕWðºÖö?5¢|…¾5ù†ÝWÃ¥’08�þP›ê¹K \×ëbêÏîC…×<.PÒ%$µqï�Ž âÅ?>�Œ•%ÝHcáedû¸ŸOfµR7h/ÄcÜÏåÙ5-¶=—ýÕì9cUЭpEoçò kkû{‰M“"Wè%gÃjÈ9îl¨Ús,Xb‹­¶“mï Ôø­*§-?ó ¸XʬqDyir†ËâîyÑt˜ŒŒìQ³CÎÐ�Í_‘©ÏRUæã~<~ⱸ·Y˜íÍ ÕDÜÈ’; _ÔYž¹-E5(øÁ8›«CÖ³âùøÙ×ÿë4Æ. ´»iìåóéþˆˆ�Ù‘ðð5H®C2—FÕæ$©Û’OâFLò”v²XÓZË8Ÿ ¦ÓÞÈ¥Ñ2d%Âd4ø|ðduv›¤º¯ñQ{j tœÀín}üV¼ ÜšÿÉËɉ¶™HwîéTi÷È 7פŒx‚Áf5 Q�kŸů=ÏÿRÃ{ò';Ø]ù•/Ô½—&`›ºCž)‘ö|ÞvÛ�=+ÄNU3¨yó×(Ç éô\"@¤€é)¶ ó°®+Ó-ÓQT÷y5.îÉËÜØ´&n×¥öÞÆ”[êD‘2�oÏ)Ø‹æ¯Ûâ ´„qëìw [ëy^ÖnòÙ>+F¤BVð:.6ºo¥»"ûñ�XÕ kôÎ~²@6ß'ÂñÅ {(Ðè:ò ÇŠU1qË\ÒY²Ã—g? ®*Ë´�íæXüÃø ¸EP•Cª�Q ó�}‰�Æ]ÞnìYêi:3/ÁwNöZ¤’ÄZ ½q'2æ/`�\àœ“¼½ ´Yéß ØÍÑÞÂ…x‰šHBvŒø» ¤Û–Ò§—ˆöæÕO&ej+Ã_"À_‚Ïd{Ù^É?º5ÜFõŠÃg¨ªÝ C(]™�t½êúÄõך-Õ¸ `Ê©þá¾ or1Ðf8x™i›÷Íï™@’P­Ø"æ4D ÿ}ìáÍ$Ñ$›ew”sÊ„V´­’'°$"?Y«ÜÍŠ‘¾gV÷րϋv�þóµÅà–ø?�&Ò¯áÒ‰Û¬üEd쌯ZëüYQõE úmþ„´xh”:_kø­ ?°Q™¸\Ä„b‡a6AþjRîœXMòR“ÛÙ⬧>‚gõ^Ä»œÄTyY•ÜY­ó{}¯UW¯Êt£•}⟂„»žVgŽÃB (¨ËÐaš~«é¹¯#û¯Ñ4ã6œ»h}`¨i¿“ú+t ˜ŸïØG u 7Ât&pÑBÃR 9ÆâDJ¹Ø<•…\—e@é„a½{ŽÀëe¡Ü¤‹ÍQ¢.§ÞB%‹×ÆdYo¨ât S§µ!q˜ÓýF×&\•0Sú‹4 ÈŸ*:íj�о’¯/“¯óŸÂ3¥äŠŠÏaQÁé1´ø¯5^l{L–Uð]ýÍy%� ¯•>ò±¹Ë“ ,OwØ&ß ›Â 1kfîð@¨’A"å°äC?5tÔÜ©ÝÿÇè²G�r`÷üüi̹#6í{#¦v1˜â<ŒCïïv>ؾP›BA=µg�¿k.òr0®4‹õû×1Š’³Ú PŽö¹b0=(²� ÿ}]TÕ6_eá)²õnûª¸N¸«'„üjg,W�-¼h— s‹ö‰ˆãD¾9е£Âj{¡°tƒï.CHÕ3ú?<¹[HBÛVS=MXEf¦x^µHç3'¦¼U¤¿±3©íP‡À°þPÓ«E!›<†-w½íy(˜F‹Wúƒ»ÚLBŠrùë¤çq0N¹—Ûv% V$™šm=ÁœÚoZJº¿“4|‘xm¨}úy–T¾ÈŠÜ «à‡æMÔ¾ÕØ‘ršZ>Q_§°(gXÄ’ª�uÀF&êâDæCx)<Z+®ÍÆg>dLŽOù÷¸ÓþÍϱÞ…x9Ìò6öëЙ¯ò™£Ù×ð¥Óñû’8øÀ‚.. "GÏ€£�¾¸J'/ÁOµ‡Ð½‡¦°E{+kγµœ-NŒLÙm„>QmCµµ™;+À¼u¯T1骱\Ú�¨ÏÚàY0n÷bçéD76á€YmfÉ/a±’FÙç´@Eÿè'&öèúmpHî÷Ã$‡|"”Mµòþ$wK×%ÆD#K£÷®œÐÒ‡ƒö)>gÿãø†}Ç0ð&*Óñè¬ð*N$Ƴ/k=T„f`¦¾ª¾³Ëvh7&rÑAê7Eõª˜]ÔºüD�„»æ�ío²÷d&~ÛRåËdÃQ)lë%èØZ�™Âh&_Âõ%œKüá“ÿ }%Ê7*,ñÙªúµ©ü«Ò�K%ÍHŒ%òþɆá�2½6O4P�[nßË)¾žØ+>œÏeðD;²‹gæÌY» SDä­&×ßÎéc•ľTMb¹Ô‘ Þm}G®Lª±¨M@™ñq3¥àÆ,÷£ÉRŽ Š³bûäâ n÷ƒÙaQç†ñzð:_Wˆ¥€+£Ò–Ÿì{F)…Þ|�áñò.¡�ìš4S¶V¸Ÿkö?BT—&«Ü {oÝKHc†ß–“c†Oµ°ïù ©÷hâA‘ÛT/5ïåEQÛh¼*Bã�v€ðÉn³DáÈ­iéÜI˜C¢'G‘õ”}~Û°2ƒ‡wÀô¦Ú†zM×ú¦X3²ô—dÝ+]˜‡Í¹GC#(Å�ߗɳñ€¨Ðº»�áyF\vûŠKð‘3ðÑ™�`1èõÙ(”`*ò™þòŸù±‘°îáêßQMª;:ô™ÅÉ-Q²4„#Û“-$¾*vžû¸ÆWº\as5G¥³;1­¸ñ@«5¬lˆsšs�""êkË»ˆšý¯5;òÓÖЫr~�‹¸‡ÿΧ&zr™å˜<ÐñCèà!Æ 9E³½¼‹ßj‡ðSyë#Wlaf.V_áÕDîñèñ�Ýé=®¯œª=¿BbgÍ€ÐÞN XQ]�«;6ÝàÕV6ëª �L@=)’,ÿÍGW¶©N–¿ŒCUîÙ"R®2B<,Ç{_»ƒÚ=8È {? C-¬K�i—6z,!mNË»¿Ÿcªz¯’goãîCûï˜Ñ×ÜEo„ê™3Óìxrø“àò–÷Y¹Õ9**™,ØŽÒ§Ù•ü·©Î˜Ÿ¿Ê":m 7ˆe+¬Ø9ð9‰pʧ�Þs—ܘ8qÒç¹ÛÚ�adu¸ÿŠª‡Û}T³Éx €²»è8FØtE™~²΄<“mëüÙkĢ땦ÿzÆ8 ä�Ë/•‘*2Âm“^~xÄ86Ž�òHôèa :>-éCné¹]R  !Ù.æ¸XrO,’^,Ÿl7£3_«ðãõ]‚ͱ¿aÑÅxöµÿì—YEëêYä k]S1c01=4¹§ï%æ§C÷F;±~zC+„.ª|º¬ˆÖŽÂz›¬aÊÃËnð@ò¡Ù¿‡ª®w¦´oOZóO±_z×,Mu†»?þTñét {¯á sW‡¨3e�~®öp]EŸè‰YC`;l”{Ð Ÿ%À—’ ¼KéÖ&µûÝr¹O Õ6µ“Â\›ä•Î.¦&°TñHj4WPu2ǹ±«W†¤‹Í}1Ús”#rCáϾAD$4=Ή­<»õe…(%(àÝn!³!Z`~Â\ùE8E4ü¾=¨„K:Í—wZB�o¸Ç:Cm€�«Œ Ô5 "ÜáAô((oe¸ô<Š^¦¾ëªÔ©zŽ«jùÇLF’5ŸÔ?Ê?'„Ú�¾vïnx¥õ ‰Öõô÷;áÙ ¹¯g."³ö]ª-ÒÜŒ^}¿m¸èK‘¥n÷’xÁ´d?¦`Æ …åù4ñ,€Þd„ÜïMøFbâÈdQ¾%·¾<¿åûyT%õÛšÐ2ªChZ.x" ˆžíÕk Wíùf%¿Ú 6€!ë¾hº`/sm -`qÿæå½“1‡©y�&�ËÛÅ" ®óОGDÒacûŽº ©Ï‰½l,ô47'�(¾Œ· +Â%¹“×÷ªýá� kÊq0VÓÌbÔåö½¦ 5µXS•éú•f\8Dì^ÄWÒ 4Ü£¬%»‹à‹ÖN®ÜÓò8Q,»ýgu[Á/âå!ûr5k*µM­èý§S4eZW¾¦(óQa|ÐP¨zÈ^GÅÕZ=ï’±K²«†ÀôÎ'0ºÞÜÉ =î)u³V|BúÄÒ¡Ñx䩇Ç6X‹î^Q—Û½J_,® ‰7uçEéX�±ŠÜèÃQg•:cN‹þù¸£¿Òœ>&à ð¦ 3§˜RCœ×ö¥ç* Ô0¤î¼Ýe‘]#Õù×!B9e&Eh�-ß~S>ë“Rr[íažAÔãÒÆëÒü�ì®èà4ŠV ! Dg ®fÔ Ó@Atr`HîÕYaìò8 ͺBRš +˜.äöër^aæ>O^b SSÂE;®}¾Îx\ÅL ~ní>�†|A–°.æ˜1Œgs´80ž�Qüû¢8† ÜÌùùªÙ:œ mQù1‰?Ø"¯¨ê)ü3oßjÁs6£Xï R/îL‚ÕÛÇFa½­ 9]�l–ã�«5ATˆDÅ §÷N'õ‡„Í-Å@Eÿ͈1l#ðÖ°D\×y¹¶)—BšiïKN¾`-�»-SwѸ9ºŒb¸bµ8i¾ŸôvOÈ/eDû“ òÄíùcb®C –izjÔ�H¾ŒAŸÀ"Î*”²+s£°>zûÄ#Y1~ÝïZaUÒ”°6øœ}Õ§-#Â�˜£è•L0Ç¥7Rø5²2³ñÏ š´†4e\Ì ­Î¾raI…KƒÚIâæ3XŽåjP#,·ºÃ/0¦Ñˆ+—êž�yºL+Ôý¨_·Ö0" ö›æqÏhÞrò{±+|Mz?�ôû$ª‰†pÇÉcTÞ©çN‚/*ét;-¯+öxÉ3“¼§<j+òXëµµ3‡ö |ò¤àçîb5´ð±KnžY €ñê�q?ää¯i ÖÎXÿ vß8ß#ê¶¶8«¨WÍÐX&$|›,±¡v¦Œ[ˆÒ”@0ìízŒ#×5ö€›À91ROjT�à‚ïÆÝgVµ…+Î#…Jvïâ=Õ¸ðÛ»÷ê—¢Þ:š=ª‡ÛZãuÓpí€t¥ôfš'\•1+Ž&ZìšòO±8+,ª,†»üë]?í¾ËMh™ånút$)xP¼ë Æ5¼nôøJç�¢™Žx’;_Ê,�»½Œ�fxO%v]âaE‘:´m&ÃV¡73+‚/žG|ЂÀЃ%4dÇ„¼Õ¡5ÎK¥âéy¶}j{º©.Àìüii SûÿÍ[r€Y®á_3¿ÔŸ[Ì–›áÅ\… ‰/Ä0Ì,»Cðíc#wÕÌ%3 °× ƒÑk!Üœ�C‹›;ZiÌ$´4ð/ªî¢ÊÅÒcÂÝvÞNhþzßÉxþ…l>”¯9³Œ("ó;¿µRdŽ1ÑWôgšÎlü¸žê \Â^,5=›© Â¼*¥r�•ÄV9_ßÜ+Ìë#íßó)!|9‹;wÀ~àeÏÍPM:©$€õ`%¢þüâ°S1ô’µ$Ð’ Ö¢µK#pK8'?DZzåîͺmuk"ýO·6&8¨wyÿ¹Pþ÷¯N¼@Ó§ÛzÉ0teª&HŸP?öpüsÈiAµíÍ­\aZhÔVޱüÜ0^XØþW[ùzÕ€¡;9P-8`~—ÉÍÿšÃM)Ag¼Cªd$ š?½Î!Ž2©ªÜiˆ,Üô{} [;.Ÿ3‡�É—6Ïú2ÔP˜1Ǻo1±pÂwjÂÈo²5SJ¶��PúØ„N´)èÛk4ßc�¡­ò¥«šUj¶�<ìO.ɧ7F˜püR=År@G¥KOÙäËßd$ì:y£YûÍù+…VV�5'¾Ÿ¢ÉËÕŸ}…ͦc,χE\¾ïq©[DãJßS(á¶A\g¢ÜÌDF׌sÖá[å;Ë"`„òÝŠzÂßIæV*t~af¸þ~éá*qÉL…<ïA£ÂjÓyqœ‘‘+®q}õ„`çª÷EKÞØBº~V*mÝà°”ù¥�)Í…Íx–ÞËŹ=G«� †Qªjª¥|÷Xo$�Jã6 Sú  #Švþžœ5ô>Š{)Nb�Ø�Mñ—:oº �`n5šqöHÀwçxë2¿¹-2Kæþ®í_�aþ^b×Ü-oÐ~IyÜÕÖ˜ní6'Úgë‚>oÍ@s7 ÌÓS;P”ïíëÑ,9CÁÛDn{ßÐD6‡!ùJÃ.tuó^Áü}«"u‰øiGëÊq¹Ñ„÷à™…â=QwÐW0šù1%âæ'„áOÞ9ÈseˆÍÆ‚€5'LÁ©ÇÉR¯¬ä¶�Û ¼1 èÛÙLRÈ÷!>s)ÛÜvŠ‰ë±®÷‡qÿâ5g,â0õG­_qÜdM�­ÙÆ•¸šÝOñžûtƒœ¥(PäxÕQË—­Pi_yÞ†f…Ì·±¡û²f FTRÁ²RCˆ%y4Wò1–iã|¸­6:+ð>D¯ìδŒûAç;ê†X˜2 À¤Ä¶Æ ûócÔ$Ïê„¥Dµ¢°ÐƒJ%qoÑÎŽºa£='ëºÂ@@|Þ¡ÍmSØ”IgnV³nð¢s6Û ü@•ÿG`Öê ’É�ëÿÃÿ?É©Pùª±“u#·)®u?o¥î ¢º&®AlÍ‘ª„-V¯òjz&À´Ž«ÑÛ|Ê.žâ[fŸBs«" GҧùvDª48mÀF·¬õÒ§À/Û�s°iõo cP—i(ŽÂù³ë×Ðy¡ÕûžÐt€11%Û•o YjÀâ�‰u*>¿)MgŒ�íî3öÐØÒVߨÉOIñ7ÐRjzéà‡m]çÇ.ï­ß‘¸zùª íö\ÒPÑ 2'É&jAWÎöa±6–¨ž-“‹Å&ÀU}ëGÀÞ¯íÍ“K�ï¯J¸7¹c_ ^›ÉðÝïºLÛÇ99IXwÈdýßI�9,âS ƒeyÙD[›Gì}mé‹}°<Ô啿U³½U¦jBÉ5gbaѰÄÊHt?—x®Q!ž„4V¤»!þ0>ÅÛ‡¯ÑPR÷ù`¢œW/`Ñ%­úOÖg‹Q–½†úý'¢:—˜yØXM­"›ŸZfg#ZÀx<@íôœyPƇ34Ï]†Ç5Ii`ðæ”D%ÀµK&ó›IëlUnkøëÇx#•þ1�BÿKJWáô<0·�— 4PC£ñ<4¹+Õ>ЗWDÄݨÍÁ¹íì{j#˜é|ãRÝ…¥Øµ–_a„ñ»€8,×lò÷¥uëàð›?[´=öwxÉ�˜hÍïðù»5Á–?š0DõxUŸž¦B°¹ª“΃ÃÝ£m…'IV rañ ¿þ;–žÕŠñ@“ãÖmižä)t–®ENó«©”¿´TÿýìäÁ}^¬Âž>Ï AÚŽ5úµØÜg"È"67Ã×äÉ-A|wWIĹÛAÑœ“æD°OÌu«"ÚÀ@ ³{ Cä¼á3€¤GÂÞ}ÔAlov$ø† $ !§ðUãuy1¯–ºé¹¶ûÈ'®U'ǪÑÜZ#ÁA}hfÐÓ\±2µ¹©‰`:�Xñ‘oB8´IBוrà\’G�¯Åcœ##?ª»Tã,ÔËù Ôž½gk½xÎìa!̆C–i4pË|[­—¿&Ï�‹h@äãBÿÒ6U1Ú߾ɹSojœ¥öJ™jÕÉ SD�{µ±Ú2|wé™l«NKÝX å 3!þZà9` YuhÇfFQË“aQìÙïà™Ë׈tö™‚u>{8 æZ \�áV@RØWìž%‘õy§¦_¼­â–³çp¨mÞ*Kù)ñtd÷{dµÚ(cÝëZð|Õ[Ep¸w4šE¶ÛÇ$q±³y¨bÉk»Úx_ÒáÃïëÜ#þÈà¨Gø×æ mt7�û×Mn»³Få[ ŠÌó;µUêkÉýê)ÛµŠÆ9øŸ6Ž r¦º�®�gmùŸ˜Ö£OµÜ×ÎÓ~~XÕ÷TD*$¨q˜(ã}�òèõðÚJkT!-<8j|�+ôÇ-’.”4ôœñÀK�3¯�‘ @ÃßçÐ�Q�±ÙKAŽûáËA~¨Â�{ºîb;yAÝ)fÜÒ'‚(v�8¬(•}¢>‹¾ü§Ê(ŽŒA0œ´ì:·%ÙÍ‹ÁEæcoc’ÁΞÑ *×Hl+\‹ÒcÉ„6K€ µJbäðF¾O2Z•Õþ¤ˆ% qÎêˆßk©®ñ5ö¹�U¥V?º¥„š¤¿ÑZôÜ·L{o›<ÇO+Ë´·½ÄìwùÜ“� Êî¾5=VOÓƒ¬×ç‡PzÃÊ€Äi|5&ÚpyÀ0ö.öèÁGø]àVã kT‘bË—î“ ­£tªCË3Giÿ° {Ÿ‚é'l@ T™•|¯æ:ƒ{]È߇Ì3;„Ã…N´•y¸f奱ít¿E$f?pãßöB_”¦jˆ‹?b‡´ØÍ·�)Áz¨ˆâùšOÖ€a¨IWMùy½ª_i21€"™n)ñDB"ÕÉÆÖò§](›z ˆ‘”mˆ@$YÐëþÛZ$X×ùÖfåÎÐóVøzà¹!žšêLÊ|ݾÚ-ß œ»B>Tø¶ãù§Âé�ÏLgV�4ź��{ª£)ÞÜF«Cr^’ÿˤ“hÆV™>¿4û£hØÖæÏ&àÚOFQhxmÅÍmC\�=‡ {Tß�)âõqí[‹aîʃc¿{D,“Òª>|ÖæzMÅæ1Ü ²ºEAUBxøótc�™Vçè�ˆ³JÇp ‘£9“Ovˆì3(´ P/9…&¨Ò®Ï'Y@¹ ­ s:)[ƒÏ¡•©Ä$ÿ©ì̳C- FòÎB¶KnT! é´ó€RÊ@¶Ò,[ÕÔ8-mKô"*µ7úÌÛZ±ÿ·¤‰xc/K™±¯-zà’÷Kƒ‡QÀŽkjWÆœ#�ML+KÁy‰Väf‘‚i‚ PKhH¤;½ì…aŽR¡ÿVký’®g=8lÂiâlBÔ$6G®Pµ½•*|ÑC_Ò_ÇÐeÖ¿Þíio¿¸ùƒškž!5_þÚ6p³*†QjÍ�^/‰vê‚2ZosDfƒ$¬Ûo2¸?™3ªÜNCe¹žfz]ÜÅtˆÊ˜ÌÇ©£ª\¥CŽU^-õÏ�”7SQñENÜN=Ý�/°”šã˜<“ùÞA0¡Þz79À?(å Mÿ–t¤í¢¸,4Õã¼5á� Ev&`(Áã.b \H2 ©MNÊ ¨ÇvU¨1X¼ç/zÚw‹ÔìÛO\3d[ü,,ž¬à†d…�„®åÀÉ ôkšÍfén¾‰âXÔH–½ÄÉv·N‘.^U²$^X!~Û¹»RÓUT#Õ¯Lê¾RÕ½•ª�8@Ɔª -’-2PÛ€©[‰tKgƒ]U”U)æÓkúª©CýrµÌq`-ë´? z‰Ø»�SâÈçA#3z£‚; DØ'uຯ7>¿g¬@}¬gÒ)…PT¸÷ÜQ1íãw$ïüWö°Æõév'÷§:œkØ!Ã@Ê�7‹vºŠˆ %:¼—›^k¬ÿ³±ðHi»qÑ$S“Í΃¡ÿŒ!«<Ë5÷.*–=Ò ‘hS˜ƒúZ:Cö4\‹Æ70ÊD¥9«2;ˆxv¬ÅIv~ó”¦Û ×ÁÇãÝZ¬ïK§L~TÃUAeâpuÝê³V GØ%(P ‘6óžÚÄ“ëO™ºqÛùGÿ+ÃŒ”s}±9¾™�׆}—Ío§®å�yð½µ�BPË€›AŸjd”Tð� gÁêl�žx€–ØT$%i–%J­» oym!3þ´ü*]™L©ª”ØbÂà*×Ð[¸Zõ!ÃÜÞ%ð{Âþ:Kt››Éš%¤c˜·OÎÆ?+Ô"¾¦¥u©£‚sJÐ+\ã©ìšQCÒ¾©–¨ô\ÞκéÿóNÙÈž—¿S†t®Ïå¯@GО-rãHEPÖ<ãHK–7œ'wEb˶Úö'Ìú0�gOš ¿ó‡¼‚:Ï?ìKøÊˆÉŸB '—ÿ¥n­F8Ɉ7ÞõN°‘ãÝ⌄¥Â•î*‹Â̪7›½ûÄá‡V 8vŒo�Ûùej¿ÿuÌßï‘9¬æKÂy”\´g�ˆŸ|d&W`q©læÍ;#8Õ#Ñ(¸±> kŒuù¾ðyÅ’Ž7óå\ Í€FZ‰ÙX|˜ë ð¹æWn ƒ’Jgˆ`�›£u4{_®kn¯“Ó½楔¶©s�·=GU­6òXÕ  õ"ÙLe=@&8 ’¼|š‰ÎuÎÔÕœù|†¢XÞ0Ú:1äêEshs'èŸñ¹Œ-8¥C7}ÄÅv Ë8Œ–•Ü&+gJU ÇÇ×ûFÐÒ�Kua5q,´‘F]Q¨·eÖü�‚"™ºÁEœ¯:HmûÃËâ÷{˜l,‹éÍÆ"ù:ÏR…­`?/<¾ÒÐfŸ‹nGÿH®[€³TN—}ïR@ÙOTG·¸z¢Ϥ=„?gg_Wu«­%ìä¿vzÜã¶MfwJs'?êÆGdžGk毋Öìô3¸Ögí‡\Š›óv"ãkô±Qnn˜¿eâáØõáì¹Ý¦¯¡3'\ZÓ4Þ´†Ä‰€–…XH%ÄN� —”@lâG3D§vHñŽ]{eŒy«Uµ ì+�”ò…ØT—ñÅíÊú}c²K{£ªÜÙm§Úæ`ª[Õð}ápߥˆ=k°�Z—‘`½„È Ì>æD a/[Å@!…“ø±*ßS ï•ÑÈW2ø;b˜–Ê.­ùü8›5-ç”j�Œ„^º¶TÑhV€¯SȾ�_ÏCÍgŽ{�˜7*¨q—´TfË$6‹6‚Û#›X×3Ê �ìNyn•ŒzOVɈúï�Ádíd•* ¡[)É:‘ÿµÞ)]ô�7b¯ÿÕØc7ÓZçžïí–„ù�Ì?’à{׺)ó|#/–Úå_Í‚.§jß…Fu¢yâQ~§ÞW$­wÔÕe븸+xËCƒ: �A‹‡^5û<š\——<Ãl¨NT-†{ùôÁ§ÎˆV¦ýç–RdlD—ÆùñwWYùæ¸öÄe; ÌÒ ¡zŠ>ÚqÚÖ5£ÿNÀå7! ˜æ!~gR{‚«F‹ð4wm«¬&þ¶OÄÄ=Hüd“Ö¡§³äK9?¥Ž±™:¢)D¬çõ•e9p¶n–ã¶l‘"@P˜0_|äW¶BZ+Y`€t¡›.˜±&{•¦ø0£µ\”�Ìãü°�²è»ÞÖ�'äÊ«™*��ŒÕ¡“Ö/'´©§Dã’+DdÖ§v`ß5­)ô*7„M6Ä“ ÜCSFÉJ¬F-ªé¢.o;HTÛªþ཈E]š}5 à €¾ 8ÆùiP³oEYÛßæHNJ‘[BŠ5Év¬~=«¢�ÔÃM—.-ìì�,ÌQMgw×ɘ}Ò¥2ÍY+m2­bUÀ±Ín~µš‚x’µêÎÙMh,¹PdIK`”•91u !T~LÍÚ~;œA|’Ù9Û_0ðH�U™ºÑeÖGŒŽ™øßØ Aâ3Þ¯?Sm�]{&�Åã`Õ%V¡vDŽeö¿±Nહ(RŒ2ÍN#ˆ‚¿+Ù�!FÏ=±U>*r�Üâ¥ßØÇÞO˜ (XÉcäŒ-üPCIEkvW¢,[t D‚VˆäëÅZ8RÙ›NL!R“ù e‰§ c@çýÌä·ãÒø"Y×ø£Y¼6GÚ¹.§êWGˆ‚²‡!fLùïéo%üK”utLÜ"Q>=@¢GdÞŠ¨YU›Ñ8þ£ Ê(éø§lï“Êéøð‡¢êI”®ŠËÊ÷[bejÃã¤v5U0×àê[ p ·%0ï�PuÒ²¤ñt‹·1u·UaÍ¡£Ål½¹üô$e2«æŸQ¬Â˃ÕIêL=É$Ü]9H4“)0>¢VáPÑn²ÝÄ£ÈMñzß‘ ‘:»Ðræ²|,ïE82¼$çÿÃ�fÒ#Æ]çDÔê?§ç£äØRæ5-úT=‰·—ª--G0{*ì3þð}b{×+ç[Ö©z_'îh³þy¡í í¿»H…«-’¹T°‘”y+<��µüôŠûª€Ém¦ŽTËŽ äoe�iò7)'–Ç=ï-KöÍÔQOØÀ©øöÖwzøH °ų̂dZš`Þ-“FŒ�¯;{‚3¤³/DY±wVwUÂ×(¯WVI0´ñúK`À°ÔròzuSÁÉõIaíìöØ ¼L—þ�½¿º:Í…™úïæÆŸÒx›dÍk]Ý29&Z,r]l%ž�‚4ýl @ÖñyCIi_FóÚ’J‹ócY«ÐàauW©~˜ojá`ô8 ,h4é¥Î1íÆuá?ÕÐÖ�HaZj¨táu’¾ÔiwJÖÐG7~ölûßpÍ_êÛÝ¥¢¸Â‚eÛ˜„IØÕí¨¡µ( œä|)TPüÔ¡±!5[̶�,}r` p°éŸ­nGÿ"œ‚Hó�.Jhrt Úˆ‰5@ø­&�¢ìªúVåId»KÝds œ˜�º¾Í);]gÙªAwçÿ3#µcÅÅå`‰Ü#— – {Î…¡T u3eí—ˆø1û}�Åù ZQ8z@ ´ˆ)6c�ß·GíB2Wk FÒáHÑG¬¯;!<{hEebý¥(¾ïžp9§Î+¶ªaà¦zûð{»iãí²¾ÇЧ1Ò8-Ìo: ȸ>�tªÈ¶ s�yïõò$rú*ÏÖpÈÆstQ&P|xÐâ ÆÎŸ«–>õþÁ‡ÐÉí�ÀàpþÕ*€j$» ´A›±ÞÞj«w±uÉ\¦é(ºÎª ^_ìÙ/Ãh½¨Ö®Ç3-ùŰâ€átö^«üD¥»ÈÏÎp�ꄟ§àJ(Ìûí¤Ói:àó_Í “<Õû`«ì '��v"‚¿Õçrÿž0Ql{Fô×mÿ r³þÖŒj½âÒqÃ;/H¦YD8âü¯FûiWÁôy$Øiûò…÷jÒ²œ!qN•´"¡F‘gvX v‡Ô¢°!j˘²ýŠnÊç«CŒNm¢;s+<±Pe”EÖ*æâo*/g0^…_¿ð(V`“aTÝ™¥»P²Äà’)¾È|Ђn¸ì9bœ½°W¡dp«À¸ÇÆÝ?È%�*�”NÐÉhÎ %#ÐÝ@�ë,o?ý”Ka/Ô0„¹È*Sï^ í#}JÖÉë…0¿Þ.¢Âéòüw�ÞZ/4çUÌE÷ÿÕL>¡M')ƒ¹‰›fÚ'Ì^t›h<¥µjvò �Ð^fHEÆAr ç(\Ã>81¢ûf)ÏÕËnX\ yƬønµÙ¶ì�ã¨#äþ`6ùPHgwVhä Ð0«ýÛÎ< ‹H朅°rI–øèßh¹ðÌêù„i›ù\adc`§¤Ÿ¨šèƒ*û�=›@Š è~9jS˜tÞwka.@cù#qS8.xÛëû¼júú°AÂL˜-âˆ)M�*¨´a+ÁEƒÆŽeöÔJ^>½-p|X¼Î’éÏÑ“‰Œ¡†dÕ8¬ÃçŸ�AI]+øŒ7…F索nõ’™pƬa¿áަH£­ˆ(Éß| ññe¡3 Q‡Äת“ík¼�äÓLòÞ®V[4¾ {køŸòöžZ˽;0ùÉùÌô��‡kÂÂj8• Ç@^Zžˆô¥xô¯\qÍh©¢¦Fo²êþ=‹ùOòíK–û0l‡°›;˜å'KUô! ™)|ièŠ÷[¾1³b�u|ÇKͱñà@>1Ø*‡÷Çãa™R÷Ö8JÆ÷Ý3TÔ2o>¨2§ ŽA ‹sÁKÍ'÷ÙŸkœ x-i å?muäÍl¦{ÙEä9¤l_r­fM-öñëhÓ”À…�”e7.ÞèàqÄtT’"^ѼYѺ–¦…ø`óAš8¨s÷_Î9ªWm…âQ\sgêþRÊ+¢zÓ6õ#P¬D‰4g>oÉü ÖçÜ‹õ¢õ¶)»žúáäVå™5úîRJÄÿ =ˆó"’A§ïº”2ˆV‚Ñ£$È�úiM Úyɲ³Zöë{H’•L˜ý@;ª™#ÛóWXÎãæœ ‘$ af_�Ñ«H]fkÛ~PõáíýY¤Ê1X,¹ÓÌ.#më°Q*G¡6`µyÊa#쳓€hBÌn† T„‰†bÕôAvéÇ\8ýG›£ËNgš(?WµµL�E‰¡TµNà{ ð(ÞB|îdQ×ÄÇÙK˜— G gà nÍ­èת%–m'jÏûóüG„Ì—äŒò„*ƒ]Ê­Vaû+¬#Ѭ—ë`ŒC€¸dãØFˆA¶È¬{Q•)‰y‡•™9°o±âFp£‹Ù`,Áÿi.åÚ([iÏd¶`á׉ åTÖƒxéIÊ)…E_{@™gŽï“^>µ€MA*³”âStÑrŸÿúmï.˜™ùѧ#qí.Ÿ ~ �sÕ‰\áéúÿÏNÙ ÊHv¶eÝE€¡¨šëäôˆ"Z8¾�U«»Nšå�ŠŽaq ª­54¤7H è»®Êu�U푞æoU( iˆ†§gq©/*1tÚ‘ëÍW`u³Åç1Ê{÷[¨Åt 2{[†îŸØy€»À�Lçþ>’Î%êƒ/M†U:‚S ºoÙRÔQ+ÌUÀ­åWù—”pß×™™à¥è;1f´ëa§‘uáyOL¡2øF“Å7óW eìûÓRó°¦�&Ü{îC0…^.Coñ¡+gõå"‚X 3‘úá_ìèbŽÌÏ1”ónë[J\Œ?®�ÉtÇ;$uÁPE^ÙGçLdéô&`¤OÜ 1ñ9‰Q·zeŸ6²a‰ 2ÔŽlÉ÷ÕMPä¬:5ãö!MKuæœkwr¬ÄöÝ­V貸xÙüC5ZoÿüÜ™ÆÂy)ÄÑÑ¥k¨±csO”+ùÝzªIÌŘvãW÷ÎK·�Ø5\¯Q}‚rµ1ÃhÉŽCº£‹¯Œ…Xs=v�G³×a¡îy€{cšL^aÁ�.o Ñè"M1�ÒÅ�QîÔŒŸ Á!ÁõᯤGb �;©2»ÑTÛ\¦â•JàÐEúÆ•Ÿ²ÕÑÉ©ß&Ë ´šv"Päß§Xã%q/ ã¯ómá ¿ABVç�[!£˜Õ†:W÷³¶Ë ›÷$:B #:¶h�—…?ÎzáÕ¥§È¹vDsâ ±ÿ¶j÷Ú‚/”ß%›½K`åèžhùÆ6¢eeN�1¡å ASvŒ!ã™ {‘T¥b§ã\Ÿ9!–ÁÁ4§U.$ö@Ú>$¤¾o©v6©n‘¨:òkÃt›ú£Ö¥L¾ªMŽsÒéP1Sâ×”ºec²ÐL!çUÃf,7É�%èN÷£ØoõN™ùÅÙ_P‚þ{�ž>�ε/)r–`á¼+’m3ü¥¦ƒ‚éèúª)œvobOW‘‰-f¡|Ñ«þÄGb­€fOÜ4æŒõ‡†+Å`D™¤Ïn\½š½‘#â; Fý–­:C�lƒ¬”B¹ÖK’£AéÏ¢õoV’àwŒë>Ëf}ºáò¶«4¯W±öšäiP.ò­\J ¼X¤×(?dšh·ã‡ìöJž¡x¨–*�¾óÃb_�NëçƒØa<Ûió«�ÝñŒ<K&–ðàü‹â]ªñLÜýÒ~%8Õ¥r´¸m‡óD¯umžB\SÉøësfÿS2î¦*šÅ(ܬàÅ ¶›<ɳÏÉÔïõ8Û¸_eª©ûü0hQæ·,š‘$¿¬ªðI¦ ·sÜæ¡“VÜ—–øG²¡aŸ‚^ïx§A‰”�Ÿ¨ä~Œ­YÿIÉøîª"¨2S³žG’°~ôHœGv¤.²ëˆb"xñæ’˜3{\·ÇÉ‹¿xÔ;Ÿ\ãÍe$ýëý—’ƒÚJùÞ-È 0æœ"™nÿS>åÏ .AI(Ð/.&Ñ®ð‰Ô6ꘙwÄ�ø“Ò£&¥ k4„|»n?nNÉ–x�A–-µmâ�è†Ò3.³<ñyì:áݦ7{ •F“FTÏŸ$÷#ýò™o¼Õ¸“¢l×,âöá0 °hy”V»‡ˆZµ(&>@r¼Ùe±Diúˆm8 Š²®ÿò¥cágAŸÏd”Tð� g¿J½b9O0d²ûÆÅq†Ê2ƒàÂPþƒÚýÓN=Sj^Ù°*èÊ-=û²œ4Üô0móªtï ¼ðÍ# °ÂaŸr\IsÕ¤5sC„O�éÅi°m ÆM¶šìCe“Fð4}©uƒ®¿³>6¿¶ [ò»Ã2^Œ§&6dŸ‚$†½@ sÃ6C6åö®@ <}~1mªÚÿ·øÅÒâñ7&Fï�uB[6^œ$��,A ígOÔ×#ýêgù_l±Z@3‰ymg 8ñýk×(øU ÜU�O[vÅà±¶²ß ÀæÃK IA ׯ[yøªp\9jw9Å¿ZcžÔ(42 íxÃìÐ+Û°Á‡Þ¹\ŠrkàJ°ä!ŸYÌo\yjùŒ‡ñ©èoh5UÜÇ‚‚z»3"}‹  ßb¼ç ßàcòì -L±$ªó’Ï“ŸðnGÿxQ{ßfYT¥²±ìF;瞤¨�:Y™×ˆ‹½Ô¤)ýý-Γ%·ûC™ïÐ’9"ÝRO° ¼µ»Vb×üAwk‚O!<Ò5Ì€ç6–€�3t·¥èî@Àf´ï9ÖVDÞâØ!ºÉdì^ðdSiœÂF›·{©I66ü-¤ÏûõN4þU³›•Ol€O Bd«ÐNê°Ÿ‹F¯¢�è/v@ðn‡ã=Põ�ÂUq-¼$�ómU‹Â„ËÖ“-ó!‹9B¹ô> �ld¡%^›gÇßß)Ä.«3ørÑÎu~"S¤cž½3ñ,1dÂÉ]PèÓ!ݬž"îhAkì´8‹¬“ %7Áÿ^’…™VÄÌØC(Ü,Åé1øº*‡bû.ÿîéŽ÷•ö(1݃—“ö&ä0¬FlÇPí|!V sâî¯éz¨M�äBnÉËgc¹:OÎ5gCÙ”¿[ ·|†EŽØ3%=‰#–U ‡éèéâ™Xïé€÷*¢â…eab"Ó›…Ù½TÑxW¡´·k G0;2;£¦?̵·S k‚BÍÈèýƱ’é«ú«Éž:8Õ²m8wéÒçÀªð=AŸ”¶Üî.“·!`·mâÔŸò!“‚—®6‚‘`t�éÍZÊ5â„É –@…,Ó`±ØcE§Ñ![ñ™³j406¬¬Îƒç9æ4Žtµè.ðýß/æ^?à[Ñ[´Þ€9f!²¸<€OõÂû®$ûÈ–°‘&�NŽg´ÇlþJí ò}ËcÏR³Oj–£’„°~ }ažý¬†ÍéöžrÏpä3ZdÙú&NÑ:xDk?a€EA›ò5-Q2˜ÿýñ_x " gGY”R²Ï�4ÏARRØ2ܦ]r/Éýòš0PF¡q½‰.ìî¤tª¹c5] íè;÷L7"û¬­OmŽ Õ¤¦ïæÓ…­pã¶Ž°m[¯ÔÎO�c¯ë¸`Éâ³–a‰•]³Û ŠïÜbJ6³@6 ¥SÙä³í?ÍÌ™`jœøÁÁ`ÄÙSOÞ—ÚЖd< üN]PL•ÇZ Vô€jŸ|eC‰Aè3nù£×eéßxŸ£ìx ‚Ç3;së5äÄÇ@ñ`ûʄۊHÝ2ð‡ÑàOÅýëã§ð½jÿQš‹\’ù[X/àe˜òµ/QQÄõ6Ÿ"j ]–æßôMl2¹Õªá2¦Ð­ø W*G€�BU©n­’2�8,–ÉÕ ÅÔ:*£’úÝ¿:c G½ª°nÖ` ˜$]‹ìyà»axnR2>²ÿS@þ씫j¾ôñ7úô%§¡ë®¹V¿W3GÑ@ŸàhÈD ¹è�cÁx©¦B?ÎeìhÊÍãáá óô¸€Aš5Má–‰”ÀTðCÿýñV�‹€­1ß<å¡’zÌœàÍ”�°¤€ï–ñ~ÌÈ�_Ð͘)ÊÛÍi“èf”µÕŽþiè\í6þÁ×KiõÄ'£ÆÑSƒÄÉ<‚j–É6¥tþ£É‡½ˆNM–w?ÔRÝ/ ¶Ñ›”ÝñÛ±AùªÝ^%i¯ººœ�Åi �F@òç0’ ª‹3ˆû©´ÔÔJ¶Cöó^ß1]Û8"%ñ� 9k÷”Ù™¤[²#oxî:Al²‡W­² b\„;Õü/bJQÓjÿa®$ªN ž@ç«á[v<1Çí*"ùúèí'¢¥R úD®ïMù|¦÷  ‘;f(éÛõ|…� ¤Ä<™ëíH¢øÐ±Öi�²>ºil¿iícZz?ÂÏ� MaAYÌfòÌñS„p6ߌeq‹é¬FÓãü¿&û.}Üбí?å»Få‡â°ãß"]oDõ™á}æâÜÀqùïhyT�>u,¾Žì–UŒ¡Åñ­ÞJ5Nbž4ûÚË‘—æ�×?9!ÔÖtQL¦,QˆØ«‡€�¯d¡O7¹30"ÆoS¼ÝŸœ0« l#«…Skb›R íK“?O©Ò6z1Šbýò»‰,k²haS­4ó”Ãßâ%Œ• €ý7®¿anc‚�‰Œ¦À‡žTnGÿ"œÓf‘Å_g55;0€7ËÂ3x)oàPˆ†Ôz£‰O•r®æ¸}30;òÿ^ÓEÒãCÉg/µêÈÉEùOÿĽ¤ÁŠS¾ë­â’ÕÿòÎ&…IZ-lD.Ás 5,b2³'<'s��rã:‡Çi(IÁQoª˜‡ø¿ÇÐk¨ß2)W+åÌ‹øÿ³ÈhNlœŠœòN¶X;Ù´R…d."¼ÎÉó¬üp‰v•FÖª˜"ÐÞ^¤þÞ½£ZÛRïÚh^|*õ6Ï{¶o³¬¹¼¦Áë_©ÃHUóï§­˜w+tÐP… t­±&•WÑŒ? €Š€7œa®ðvt¥Â$OÙ²ð:/‡þÇmk‹.Y·qGÁžŸ}ÑîÊfX’b�C4)� ä¬2ÅJ´6 ¢ã&�ù³oëlDÝ ¯ óŽ®÷¡¯f-F²ÖòB�bT�cfI„æaÿ˜Vm΀çf-²gl…âòhxÝîP÷(_w—Í‚ê/™µ"N[Bbïvçb¥T/­|4b÷ü}2•Í_?3‡ë‚Ä}Ήñ�ê5»š Åî¹Ö-9 ¬áFЀBɵ[k×¹Ac›Åæ£w„@¬0=AÝ|R"ôQ|hÆëÙ6ž P©—Êðƒ‚xâßçq¸ ¿K¦$#ï¼%ªŒ§6©EÞo|±Ë§B ‰_ñå÷t�¼¢f­ÌBžG—€�-ÒâvBÐ9÷ý©²,Wwîjk5&—úÞ&wA¸ÁÂæ·bÖsœªOnf©¬”pzSË,.è&€·ì�X> í¶*<¿C€‰Bº’Þ=Ö´\)G9l¦ËVˆN/ù¶ç,ÊQ îlÆ£.·â9åº>;Âú¾ˆyY�ã´HÅ­çsžàZMÓ2¨ÌJÎ «^ °§duþ7 ‰ù�XæRDTŒ¨Ñú‹+÷�ŸÀ�+X.82nÌ ë>2ƒÓÏñÀz`V>Ë“k¤Js–úׂ%0å¢ô+¡V 2åÊÂx½½·0Rç³à‘¢»Íß lLŒWX�Kê ©6Zx¥bÀØ­D¹i5IÚ'&}¨ûE4b‡qŃDüÍd�v#X2~LúM­�¾_‘dë)E¹¹&ï;y63 bÕ8# yvñ="õ3EIÂPó cÌÅöp.Á’ž-¼“°3˜P'…‹”+”ÊÇõ«’Æ;Ú‘w òv$�!Ç6=Ÿú÷ú³)TÀÌAÊÙô‚2èuF9ZÃaº~+Eèjˆ²‹\Öö©þ`±Ç`^€X˜Õ%MžríÛŠ ®ÒE#tÏà€oUA½üt S�ªUzÆ’©/}€N™úÙS´ÐY]µ¶i?&´Tã]ä��Éž·j§£ÎåFËì:„[ )X¯ÉuˆnŒg?#U LñÚ³ ¨îðÃæ¸ÐbÙø ±úº©Þ'·TžªM虺ô7r6÷øŸ~ËŽ.,3¡ºÞòœ“ç6.Eš‰Å–ÿš¡ ý“Qã¨Õí’uX "%¿ù~Y=�:§HU¡ø7ÞR�Ä:sV1ÜdÏP±kÆC†•·£”8½äªlU‹Á¨ r¿EÖ]šÓ�¿™°XOû[¶»n*¨DånýWô‚€Då«O Q&®öK*ÎtY½¬ÎQ¨òqºL‚+q³Z®N¡¨d•ïÙ˜· 3\ÝÕö¥*=ÿ×b# råy«l K>_)Š ·xÿª)CÊ£T°>½HHÖ¬þpÖ�ì˜ñè¨C~®†Í×µ:‘¿÷€äª!Ó>Ë ê3`®šA�4³x„%ÁøHðaõ-bõô³w4DÕO ·0{&÷fätSV¨¹ék™'¡ÈTa¥…¡Ñ¢„×4dÖȵݎ÷ÃÈ!²"µ’{wßüñ´JÖJ8ä(àqÝ‹�ŠôèþþÄìÈ©ÜFÏTNiêèµ×ksHäALñIe°Å¨Ÿ–sÞç��ô˪۪> ¾ŽcáÒ¹Âô”^ŠEs©ï@™Ñaà'`¼îÙ2`5û›žc ¨éIºa^‰†+?P÷UŠx$ËüÃ}�Øq–¬›,@‰c„×¢9.t�ú3žT["ùAýqA»]%íÒ.¦¨n1jžoçÆ£„ıÃ]EÚ#7Z'S®AçËhøÒÛÕÜüÅ ž�ތ׽»Q$ÞÇ‹r¶×Þpº&ÖË|bß“•·®2�£Œ]9ÝeWÄÌEï‘ëÔP„Ì×—zb¯jÜñ¢¨Œe¹Ý§ÝzQIšâ3Ež-îÄ ‰6¶ö¾r[*8ÄwI*ji³Ø~¡¬Ë&†¾ ’,(äé5ÌçÆ°UXÆqjç7ÿ†OU½†¹©4åY‚èy„Xµ3¨ÎæRëD¹öÓAŠaL-<§_ó”~ø+òÇŒû�/9¿“/úkàCö¦†L’JQ×wŒ2%NC<É ùɃ6aÈ.éØ ÷�[iýhó4ÙlÛì]hP³ÆšHˆˆ0²Œ* ,é„K•‹uè+Wm‹%ÿuò—ý}ß”0P!5‹L;ÿ9è-_bz>¯nœ4X’Ùc�·À”¬ÑhË]ןrt‹=îWÔ;Â8R‹:¥Öo¼Ä‚Ä'c¼;Ô¢ zà÷Î,!EñD Ðn¿ ÄÄ ¯’,7yl¾ R¶ÓèÃ¹Ö”çø¾søÖ}J _}]Xp­�è…%×ýjJ%¶¿‘� ´þàF#9!nô¬^ÚBÞˆK°Û_�¢'ƒ¾™›vÍG¡Ëûévü0GHï&¤Gµ6f·k8 #™Ÿ2•ÈŽ©”øPÿž0¹¥)ÉØåÐí4ŽºD¿Êh‰¬ž•BË)“Ÿýo²Sy,CŽ“�$Òàùu¿D·¢c* \¥pìvAÔOië¶zæA²gw@~⦺Ck®*‘ü_ùÙH†nÊ6ƒ#ˆàC |%ìPq6jšÛìU[HˆNlôPþÀŠFòr«f*”0êH;Ç•,L¿äƒTš_nf„Aξ�§Ï`1\ŠÚ†Ô°j*<)-”ƒ~õ÷PY»!²kU%Ë’÷�è¶o±oPá‘ka<’¶gôh h‘Yì¶÷imÁgº’ŸZåÀšF,°é÷Z!z¤W ¬Z=:ˆòY_òÍÚÞ¾2ó™8”lÀmÏ!žILZ<(¸[;�]«LÊɵLÑ‘*”;Ÿ€MD «¤†[»ÒÑ�Ar>Y1vù?†–O黿KñUfȪÑÍZÝ«­ìäTâr=àÒh\±ŸXú8Ô û–Ë{¤êeŠ�•šwa9ðwŒÏÂ1\/ U�´ï1šQÆÑøú ½0�ﶸƢ õPQ;]Àò¥­é,¶Gk|Ži7ç\‡ûX,™ÑBßjÿwЬ#�Hl:¶úq�äF7f4(ÑÞ—› ó Ÿ«ÉÐ…ÀÅ._À5³8µ6Ó|ÊNfÂÎ.Õ,nw>-T°ÏšÜ¹t9‹Sîwï *’µP¥aäo–éÑpÓ^¥®ˆ*lïRÑzKñφaSµE:—Šà‹¡�~à$‰' 3A\Õçx¤;ËX¦—](z•$®`ü6�FÌŠ9ŸX|Ih±#çz’ˆó¿¤-3•³è¢ÿçJ!¸éðÇ¢Ü"ǵjËŇIUùªîÓ¯àtŽ�‘˜.©à6”ª+`Ð{¿�÷ïø‡€ÆDÕD�Òv%A]“;r7„Â!·#[ù9°Ù±{’(:wE–lݱi ‘^ÊPfðê¼0ïÊKN’qª¨4…ª|›7o–fä£_�we%FØ¥m`:ùí‘ �òY¨�ÑÎq,Rç·]æAƒ/QWO~Ó^É‹E%Ö~uÇmò4¶þÝ=Ja?Œ�ÐÐö¢š¬í\'Ô¯n_'ôC†@Ѩö1ÚA5Ë`ÛÁÑ…_L`åÀõË8⋚tjTÞ§MÎ-S™Î%$÷¨ÞtçðÔñ4™¤ø�S²ÆA=kÆ8—«²ªËįé[w>i c¬$Ÿ‹öùò§üÛút:Q<Î@ÙLù$Ú0á¦kÑ£ZQÏ3ÑÕÚ7Ô°f~e:~±?‘5*.~z±¨H›ª ÑÝ™‚ø‘w¸–$,‘‰ ÃýîS#ÝfKPGûË{%ÔÃw;¼K€Rãd `µmYHÙï#ˆ.ÎøºUa¥ÂN“1Ħ«[Øp´¶È(Ä;žd:ViV„u…ß[vÚ7ÇÇÝ'"´«{/}>ŠàK~<€®©ö�Ü�§e†Áå;r K4Êùi½ûÉðh¬ ð]Jù™¹ ›l¡úóâȘU">ø#¬Á²Ê…g‹2´vðú e3¼ £B{—·¾½ê¡[ây¾ÿÿiçÁt¹¨[Aü¹Mm‘,Õ!GÆ–Òp7$Âîy¿£ax÷uœšUçܽr-è³Ì˜Wq¿›9QuàuŸ!¿Äô›–Çè‘Þ` gâq6úÆ-ÛÒ$ÖþxhŽëØ„’ý TNØËÙ§=�ÊG•˜|¹{Ô¤¿¨xãü‚ïV˜åqÓÈ Ö‚÷»& ¥x¡ö�=µ–û׋âúÝ’¿°.$wèNw?ãõacéçu%ËàÛíÞë?7M¼Ö"Wx¯pqÌr#ì äá�ü2%ºR rhR© 5Ö¶-Oò'Â{«;Ï I®i°*?äÞ¤œ¤ZM¸‹8BG…(Nõœ6õ@sà6wuŠ�§ùŽyÃã>olt íER‘!îw*T;bRE—ZVHàÓ¶Pà^².Ìø7rÁ”¼±´-eO®û ÅŒÒNÚ_)}PŠç£{ºé_ €3ðÉìÂÇ'·(ˆŸà Û�®½GîÚS ±LÜ= I>F‡frø£êdÂÝ”®ýBÙåÃó!ççB2„†È•eÕ3_‡+m×Të´!W¥Èø“ºF‰Ú5G)’�A•Ë´½L˜ŽæIÀ—ô·Ýf¬l�@iÖ®\ˆU“üY'Ë›UAeÛß©ñ”ƒlÈÉô¹ÁŸó½�ö%f-A“ä,³§Á-—•^ðö… ÀôŽÛ}aHB*ÞÝîÏûìK>ò¥I¥›3q•!ùØT ‰„Èî=G¦µò6=óÌQåXù±˜e‘�6Ïðbc ÀÀÚÒ?Õu’ÑLæôÒÃá% o»u>ˆpqØìG•­°ÏŠ9…Ç~0)sQJJ$ï8û€‰­g* ±ñ«)x×­º®¤#„SºØÒ ’€Ç›Càâ"FÉ‹Ë\ç›VÙ*Ï~Œü£²§M›Tc*p‰ë/§IQÍ™¦bÚ\(ƒ¶Ÿ£,…¼ërÍÐÖ`øS¿õÉP Ųm2jÙwzå·Óé̯öÐO(í?þ-L(7ˆk� ˜ÁñNšŸS g[®ñ_ˆåê{%¿$²aÒ{+p‘æÜÜÓãf>:çoÍÚ¿ï¿ÿ¢�©Qwn�|Þ£ø;ÈþrÇÄ*!¢+^ø‚´°0Qpµì>àm Ò }•9nŒy¡V5éS”Aÿ�^¾HzÞâ{£êrÂ&W äx˜SüØÆ`ÜwLr§‰û�¦C„ç”;$AiÞ­®aFG�"má�I?ñT•áèj?§*�r«g RÌwüÂbªóAßÖïh€ßý‰(º‰ ï æ³CÁËNÄâÂeápí¦�±òR(ÏPtY‚©ô™Y¨3áÛ‘Ï ë/bgd}{],¶Ê¾kÁƒä©ÛFËj-•5�m«ÍÖ©A(ÂðnÐßþ\Æ¡ÃøJ� óÖüÈ#è¤úðDïµ-‘7ÔÊÜþ‡”tMiÞ;@Öëæ€ƒJ1æoN¢ÿž\ܼÛë`ÂMŽÍ(=‚8bÉÿ¬‘~î§àÆ`¦ÞÏÉH6|Á§€(0 ©3¬‹NßúÄú×S’Ò>p_b6 ‰œÉ^¹?6õ$Ñ�l‘†NIÛ'x«Ûn^Ýubí–û<·Ù%ï ¿xâÀçvðTio“³¯Ñ§ˆ x½Žïb ‡8\ ‹±±«<²„x(µsð~;+éÎã§ž ˆ_[L]ý�7ŸåäŸW²'“ðÝås¼É‡lȾûâ±ÆÉãÞ’Ý/ücìâ!É«J«öåg[j%”O<�¡†®~ÖÀ#�ÌcÌæjÚ]Dù­ŒYß5……¦ÕMyîþ_ù•1ûP޹¶;E‹Ö¶" ªÄ‘!DÌÆÍÑ 2Ë’`€2JKJ±�ÌÎ9²ß-`=jòåñ]ZÞêãsTHGjçqBP ½ÙŸÐ ØnÀi9UÔt}ç…CJˆ•|¯ úÝMÿ,Ê&;ûWê%­Õ5{Ôý:iZÈÉ×.¶lZX�È2CãTtúÅkÝ k„0¼¦ýWPUP�¹…Ê0—A¥kõÑuõÒJI�´hEl—8Ì‚oÄ- …k`a.ë¸vX+làê'Ä ®}¬KU°ñÀ˜¯`VF<³Æœ–Q¥aƒ‡R3‹€¢‘ñb;“‚ÃÚu=RM�CÝÙµ0¢ƒ"°……Ç<DØ”A÷¨OÆ~øp¤SƒÀî¤þx¤»eb,"ß%w’Ñ�.3q§Á ‰�bù5º<ÉœÌXh4DyU¬5Ѳj‘…RF;‰–�ù¨dâ‚”ÔE±¨.Æ 8T)ÿ„UGw&ðEfG÷š‡}¨6G§ ËÆ�’%¯ý°}+}®u…@u é.?…·vo/¬¤)—#j®k,wñÜ¥²‡ª™ C@N–)²h| ˜KêBÅ% •üzëh˜oF/�öõÝZXXX5,Ûxð€Ê®�ös$ zÅ]KGrOš4œÒ~V¨…FpêI5—])‚+l9Àø±ú˜n£�™ÍõAΑJ«£:ö B�F|"ÎmôÂü­ͪýl±uÄ86•IÀnxÒ~'gH?1àO•RÑr$ZÝ]k{E4x<¯íÈMhRI0íݯi2«õìëþ=΀VÙ†´¼À,#3Sõð� gÒÓñÜë“’ðÕi+û2‘7°I?¦!Kõñ�WK�²…�ù�ã´ç –÷Ñ~h53´“ðÑC�]wDÕDų�Pµi!ªÕ€?O Ú’˜ ïmãB²Y;çßZƒŽ·Ë‰¨¤¼¢€§N²ÑN)þê;z@vë 儳%X|lùPÐ×ëÔD½Çˆùç άÒ覘7‡)ûÇ:à»SDHu°æübjÔ0&™ÿìýe/ S´©îìúŸfŽ[.=’¬<19JŽ™j´ñ mD[q犒‚çº×Æ*Å:šÃáÎvÇÆ÷|àU¶ÑiŽ4¸v}~Píwgõ”ǬSœr´� z|¾�S±’ve+qÓ¤?«ò{hôŸ¾ÖX÷Mö*(E@™¹*ñÅùN“wŸM§‰ˆ Õhù$és ±“0^å×þªFÈ�ì°'º_;¬ÕP]^H^ŽÆöõ±]oM ÓùJЊtÂn�[U‘,ö½\‹k  S@Ú,o³ ãmft¯”ê#÷!˜øÜTˆ¼ZÒ´ƒop8 YÅñi(Õ {�Æ|>u÷O÷ðÓ™ŠëKÓ�|¼‹az´cb„XÑ9¹CˆpVŽ0{.jÕúÿ—Ïí÷T¢™‚‘½‹ÍŸ÷ì ë’ÀXýÂâ‡ú»^nóIˆ5Ý�ÆŠø²zÓ»²Lß»lR�äê€Ó�g8¡;¬䉊7‰ðD¤uÚ«…€¶ƒ¯Mf=�îÍÝ�ÓÀ›š¨ò›g.êu®l4ªÛCsÔaK‚å°"eýw“¥�Ÿ&2¢wä¤È=K¯Å¦ë”öÄ�Î’­ô½ r¸m¦Ë›a�ÚmYQÅ·­UÁw*�C5^„­� f}ã;ë?ûJ&öò‰OÂ^ÿ=‰`#²ø«†sއH®ï-?8Œ0”g<q4mè$u;|iì36 —¸26ãíèæ¨3Kœmèf�¿‘ÃNZ_�ÿ®=±ô§Yfpű‰‚®¥X8øï{hhöŠ ’(v‰Þò7�‡‹]x¢ôz î2E5*õ0¯^”Ú‘D}[΋ÕJË Ów‹Îâí…ž‹ùÿÈò aϰâá{p°£)JA¤«a‰Átä,IØnkAÇÿ])¸zЄÀˆl]zÅç½òc�OÓÿîaÁZ¢lâ_÷Î~I9”¦°fÙ7¨­ˆ{6'͇(þËðýæØ{ýAÀ—sÙ)fe_ƒ”i¥Œ˜ðÛqº“ýS�^¡[7úÑïðõ@wcªˆ Q6nyérä%ÒKØQé^"€1Ëåp^Þ±¬He¤Õa°Ú7J×61­…þàòˆ/R§·«þÑC¿•aä3Ùo5çQÐá÷„èf!žŽaòЉVþv*ô‡�Cr�FhƽîènA8ÛõÁó߸¾ãô OÆŽˆ9'ñàÂëïgUûië\JGKYÙ|û½]9®³wBšÒÓŠÃEç¥›Ž¢“�8Mëv÷"µ—Íf/ÞO¡ijNÅÚvV½‹º.S&ïÖŠ$pE7 EMÌÿ�:ï1a]Š �KöV9ù‹®CqÈló¡z÷Õì-Ã,5Ë1n‚&8†ZâwP1ÌìMMg½!°Ø„|[ Y¥'žåÍô¥“ˆSèÖhÑ.zw*Ô�;G³1-æž�bY÷²`�÷ÑQü$Ø}¡q}nßkT+>ÏL_WI^ Ѩ³Û­€ýáû§d8ܤh¦%H`Q‘ZjÞÐ'œÑë\ �Ó?LêU&¤^ßzdG«„PvLbŠ*[�•Ÿ�79�‹Çòjò-1Ñ– ͧ_5ŽÛ7ÄÇÊú?ï”=%Ëi/úß!ø:PFR~¨X­ñ ³¦¤Ùë~S¾ÀV ÀIÜÊAŒÇÜo˜ %P©˜­O‰BP2N¯õ–ú€ç¼PNüã.{G¬в´ þ©]•ºF nN’èë¢âaŒ¢³¿Ù–+®I8à_ßk׺lÕ¦1‡é1ÀÑd„ŒáTƯG{2§QOòv¤°J$-Ÿ§¦�Çj’"®~ZÛ0 Ûº–€ÄØQ„.•ÅÌŒ"­‰¾ƒÎ¾/d>�¹ãdÝ©ÕDå�5v«O\Ê'€ß¯˜C—ã@ÆÉ“=7xG~eR%‰Á C5 §CIF¨áu¥�4ã@‰<˜:æE€òO<»áȶ·+¶[òüê)CŠ->…›Â­iïyoõ9†BhâPñP{¬*„“s€õˆ%Jæ´R”(ªZ ‹ ¤ºï1nqX»ÍJ¢´7*#©ÐaÁ=ŸêthÜÄ«cøRN^­Hñ9L üÛÄÀ†8xl‡ñÕ>{( åëä)ëäµ!Qc¤šM`-ˆ&6åG?’öжÍw“ðضP' µ˜P£GÞtî+êõ3ÃsmIWÝܘ«­;kÝ®0�ž ðùÑ<¾Úëkzþu‡/Q>!ò–; �¼Û‡_)q†uTÏÓ'»ÿ¬±ØÏ0Òsƒ­¥``¢:€¶z-±4ÒÃT§©óguøƒøÄ/¨Èr5à\�ÉD0yâÓ…x"¸ˆ¡Ð‚žü˜^Å!V˺�<®%ŸöB–´Â³ÅšÞIpݱOOTrÔõÕÊ èÚ¯š(�ê•ï…Ä|ŒÎ¶U@[�@ ópib¹ÀU/e –ÅQúîÌG.²×*E’d3d!2KŠÝXLMg€>ª¶qK¦m3Rœ|7ÀÒ¥ë´÷ÍQ¨ªÀºe_dXùµª#}wÁÏ-·,ÛR�Å«‘.~LJÎѱÍ4È5Ó­ÁRBát5ú"C�zždª8æó¼C¹q‡¨}F Ìê·‡ì"O_Wkµ±4)$¯½‘>YdWEîͬ«Ä¿úR€«$‹[lˆ²¢…¢áÔ˜_ÁÈÏM'ú>– fÚ'¼´Y³©$3RlE�7È9Ò£±‡¡,éÐvšÕµNèË.Ï r‘f[�€¼?7¼5˜I]ã„�ªy5'Ö_Xà-í+ƒ­@Ñ>”i Oa  .j"–Ç—=¸Ø Z33òŠsz’®c§Ò:¿[âÂM!\š€èzH¨¥_Ûä^‚4X³ˆ€9Î "Ö�(A°¹ß¾ª�u×Ì�ÐgJá ßߣͧ.LXªSÅÀk¡ÐŸ=ºl˜ò FS&æžÿÁ�¹Çç)H]ª,+ž[úƒ„z_÷/Rᄲ áIXO $ éÙÝW‹=ÁiÁûûö«àyò ×Åá h‚nzeK:ïçRÌqÉÇR]u¥;îJ®¨÷V øÓêÍÅ6%kI£ÎŸQë$8êÎlV{8ÁÕqn‰ÛÔF Ý爩ÞVíoë#`r±°ü ãO üöJä`9)¼«;IsJ,±Yeî÷¦XYYuÿ™!¤M™NcT•t…®¢áÔ‘Û%M4¾�ëéܯ®DkðXî° Ó&¼%I ±õ ¡áj�”Ô AÞÜ� ÷b3å2|c�½®ˆ½çñТ̇ÎÒÕ²/�^n¬­TÖ7q ¼�Í£ôÙˆÀ¢H#`³�Z€ðëŒÕÒ>“ 1‚µvà„ó2B“â¬È�€`Iý Â*žìì×¶L@s¼õ’� árŠýï]ÖgN¿0æÕ«VÆl'>Gš Äá3MÀ_l�ÇÓø¶ÂÏfÈÐò322kºÞ,ù¢£Ev%�Ék› ø`ŒÊ˜ýš~<nï�ìJBÕƒˆãÉÿÉF¤8ôJ_ÇãüÌX÷+%©…jÇöA÷j°4ÔLi ΢-Þ˜9PW †ª-àÂùf9¾¢ì¹§Ù:B>ÅÖOxÂ?¸_æ¤,�‘µ…K¨‘üR¤ø,·^N§¢vC`=8,ñ¼4ÇÑÛ‚ü¥sÏÜÞŒÐÒò^9xä#HóÏ+˜•ÄŠþêR§jÎVüéþDtjp7…ðÏ'ðV™Óˆ§NÄ�°Ág2³¹‚ÂMÏfä¢ÙÍ´û©)” ÜAÄÔ;O}St{t�üø|Æ gøº†¤%2`ÅÚ±:¢: º3ÓB ÀM]¦×r½Ç% °•T‹á0Ô• knVÔÿÿÛ’m�\hKïH'9äÔŸnµ?"dãýeÎå1f«£‡ýXì¸,-ïgøý2êž d%-ˆÖ#燒QÁk§MAa îÅöœN~±ØŒŽ˜g!g(ಓ œ÷•ôqÑÊ8޶{ÞQƒJÿoÓÊ‚c¨ML‹zŸ‹* ¯’ßÏtm`’r4Êleí3;¥†Os2-2‹}7$‡އjÉûèÒP5Ù€Ë3•˜üÍfJ$?QsØ@à?wÊgÙ~»Ÿd;® ެ¨KÒjx¡{9¨Ì�µG5Êñ¯üÒSÔÿœ±|„æ †�¨x\wT„]¾K! O@¸E,W9´®r–åYNhö,Dí8ØØ|&&û·%ÆZ¢X±Åyºží´Ù¬IèÖ«f]OÞKû�ƒ÷@�²~I&)ù¤þ/Pº³ÄBÛA¦Y&ksSÿ‡e?U1üï1 Ãñ™°mÈÌ&ãþ=â!–Í¥K�Ãô—Wx ëY¯>æ¼ R½I–5®=x¤q¹;IÁ0DU�® „¥ÌÑåF ¤g’2µƒšÿ­ÚžÜçï×ݵþl/Å»tŸ‘ ¶A˜}xALr’õ¶f-w$uãŽÄ*ºlN­€Ñ_ØLÀ1@f°8ŒsåôæwøHŸr!x¥ÓkÈ?(«èlç+!â©“Òba›oö³+ëè§:D‚€õÖ;QúÑ‚IÝF| ;DR]ØfEx=iV6t pn–xg)_@'¸`‹Ôüsq—ß psO+NæQÈ}—V·ø¾ê­–ç•WÎ3ì…ös%Ö1+ßo�€�Ÿ˜A¿ëÞ¼«‘`ñdô_aä÷FHzÙ÷�£o­ξpoBDß—ý¦ÉëŽlMýprIðŒO )ž1þvv—Ãá Þ‘�=TÅsW) GSù×1�´»ï`Â%NÐkÀæ#©Ö3ˆÈž$¼�Ô¥B‹¥=;Í™Ãä±Mîã¿ Œ�Òÿÿzý@ù;×�ÔËDÞj+w¶–yÉG®d�øqü‰A¯‚ó�g=X�s‡AB:2NHmðìeƒïá#úH'ÐRÁŠ”'{vJr•ñþ"ûø Kãq‡š¥‘d+œxâgÈÔÁ°â.¨ÞWš¼ªF„™1äLWÔé‘ï”ö†@¦Zsu¢äÝóÝ µÔA×ÞQv ·E’Ñ=£Ž­�9ökÞ¼CÿÊŒZ)WíØ=ùàò—S¹(í·bй©çŽP“ä#Þ¸�…KKˆk¼§Xºjs‚·mØztÂEÜïà¶gaÚuÜÁb8<*(vÊä3ØKL6(ÖÁ%¡’�‹k¸uÙ=…tVoÜ‚Ž?ö1 ¾^5f/»ú¬ëêS]ä]ú<ôF¹ÃL×){1IÎëËiŸó8ׯèj-$Lïi}QfÚþΊO=%ûõî䂌¶’¹›u',- L–㙟˜Ô 8ÈU^ÚèJz;wúx>=¾�¬Ÿ'æðYt\Kƒ¹¡Ð érA}ØŽïÞÅMÎÊ15“¹PßGÖ™Y�¾7«Ð<”Á}û$ á<‹ùÅò×”W߯lUÝD®û‚n]«íUj£é…‹˜ ˜ .Þ��NŽÒ§­cS2†¯¡Ç°ÀþÙï•hCÏÛ†¼Ô#XóÍ„“mÄ&ŒJ©ŽÆp‘¨Oìüv-Pä×�J�/> Tˆ^ºB·CÂØæý½m ‚>>¯ºê²V|îñ7¬óþÆEÁÜ–ýygŠQÈ&Xe—È\@}×н€X^=Ø+�-ðTO´±«�’�ŽÎýDfËá¯Éû=sOZµ¤.7Ê(¬ÛurcÓuVgóg|àdô;¥JÉ:xI£jžçí%ˆ{A8ÙìÍÖH®%i^ à2Nc§F] (Úõ’¡'"<7;ˆÍ÷xV0w�:¢ßÃÖxšÅ׃�Êý˜×!2`!Ð~p’r©Ì’ï|ÙâÉ@¢Œ¡RÇZ>±ýºgMç%Ÿ” Ú'µêÉðI ÿÓ�šRÔ4Khj².¾7ýºªŽùÈùlŒ|Jé­. ¬ð®­æBq®pÈ„äã6ïžñØÂÅOga³{/»k(;ýÆ„ ûSè¯ÀR*­%Vàeö‚¢'ë¤J-x÷Ÿ“ Æ'\YUM—ñãb�«4yz10Ú™ÈOl™5X*®ò@b ^è/™Ý¶_öç]¯*ž€,ªª&w'_ê¶ TÃÊeT¹¨ü50›²=›gFÙô‚�ðnñùÝÎ Sx¦’©$ñj¡‘U:üŸg¸ Ô·ìß�ö ʘ"{¹k|ûÚ\®r÷C<—VŠLŸ™†Ñøl¿•›z#PtŸkÞ';îKhÑÝ3(|dDšÐXÿ_ªi^ÔäÅÿ¢G.éÎú®€·ÉÀȰ,çF’�%Z%4ùº‰§ )åo¯NÁP`RpÙˆÐÔºÇ,ÝáZ)¹[#úgLš-ÀÌëû‰~ùÂ3õµÝ/š”Ù3hnº<øŸ/hBTù÷Ê婪‚ÌjSÐdžGl 1\ñ[±É�(aÔr7™ãÔ{¤mŸ8õ�—¢U-þ¦_ ý{~Aä‚ËÍÙÀÂöQt¢¸ÕÙ´|¿ mã> î,›åcã3@Θò�¢íåµ�ÿCÀ§>ñûyª­WÊÚí¨Dø‰q±³$f`8¾U°¯nV.ûAOHR×uÝ»-}íÁ 'î=@ïbX7&Du_µk›ÎÊ…ûx²p%ø†l¾©«Å;ëÑÂ`ÕZžjJo®.`2)ŸÊ,5£ÿÛgJ1¾6d´D½ú¢3 "W &ù±ì¯1p¤9+da˜�r¬¶~ŒšòøqÂíXšÿ7Íë"-WgªcÜW+HK¼¾gb6@”Ñ´ø¥™!Æ¥¨&�ÏSÐ&- àÈ<)BÁWÕ[—?MBúí[áG¸Œ9 |¶ ÞH0IÃxcEinyü9ûNJ3=l56ôHŽk�ÁcÑ,V�ÿî´šméÐb:‘�:oÿê4Êí”)ÍÓ¦º}jïÄCÙ¦áŒa•ÌÛLðÍ�zj‰ò¥¦#£oåñjº±ã÷Ã[âqg„Š‚'Ö+Ç‹FºÒbæíf·2�ÉLDW�eý«êŒ+È€V¬jÚø�;é=Õx9âÝx(oˆˆÓ^ø2œ†³6¶ãåÀÁMìÞÜSŽwê"öL§?‹×Y]~5{øÿıŸÃéùbp;Q\¨È× é9[)øæ†½‡5$Œ@h¾AÔ±2žN¯{¥½¼Î4¿´„�q7aAKu6­l…‚‹qÇÕ.�CGºˆQß8'W�S1H0új63 "siÏ{ȰG˜&œ`üÇ̾'Ùx˜EÞ'–镉2‡–ÕëØÍW‰Ž#>QÜ™t'Çt<X¢Hän?LV¬€ñ¬|‚‘2k‡ßÑ;Ôbñäv(&¤Š T_.þ $ƒ̧$ׄ×UF\È–;N%‚mÒérpo+=ñÿ¸(:=žzQ‘ró¸iØ@j0+3°ÇˆºÓb4BŒýÖÄã‘^`ŽŠ�v�•c´ãÄ…9Ò8&ÍèN“[ÓÏ1¼`X$C^Ú[òªA¿bÔ€ìL¨ »Ì)©¦ 9§ËB…¼Ëañ'Ê+3ƒihJx]ÄMû…ij™UwßCžDOE÷+¼�zRVðCܲH@q`Ù×Ý– vGã™A 9œbÁ ¡F ÛÝ7ôú› t•û:tÒ0•ÛÍáQª�¯üfXË! jà)›<ýé[ŒT8æ^ûñ{Jƒ™éQÆ…pÛpb4ýtÃæ¿h£‘3÷“`|GJƒŽy¿SŸ"~YîJuƒ,þ‹µó›ìEBS…ËO›3èƒ7/Ј*˜9IŽ`O§YtÜ0OlìP¬¢ÆlÛðÿUÁ°ïâ;½þèÌiD›«†Ól žˆÔÃZ|u'q¦zzg îÚxî„*ÓÌ^ŸTÈoc¼ §œ6Rƒ¼.ß:Æ G uþAàlÜN›¿BŒ®ÿ�S›6Ò˜Êúï;ÿ¹ YÓj(l6eOÅúÒ¸% Ä´P2z"sÕÏÇÊdŽ\júc.ªÖÚIĈGëbN0™0ë jMHrÆæc„Hô„)–µÄlM¬?ÿ[¯ñ›ÔË`GëTˆ )v¼8Füù_8Ñn>Ü„ ‹JæÿåÏ£‚/Li½.Áÿÿ�|;îc#o^ŠsÅ1Ùcñì'€9•îM>$é±xfÕ×Á Ïß4~•´7;ºBÎÓ¼3YýwÈOÊ&lVTó1‘¹;ÖsÛQý� .iþ$@1÷ä@e<”æ “_ÄÇ)oBÆ4÷2¬÷—Í]:¨eAcf kŠ'ñ?…-Û”–Ð(Ý]‚ؼè'É#³úQ�¾'Õ cCÔß%òб¡.ÿo<UµVÊC=a–m߆…ïÓéøVãdPq¨î£ ó.À±þ™¢¸³Ì¾ñnzã×u{*¡�©ê£¦ÿŸôMieÓd ¾wü™ê€nÒ|[rÑàT9!a™%÷ ‘uÛuölDÜ~: Ò*›Kv×Û<ƒ9ªž¥í�œJ^ø¹³d£¤.I IÕÉDê½% ~*yÔŠDÞd5ÄZÀ³‡-²àIuv‰ 8ÉJÕ[ºqÌ— ÈnfùN”ÁÒÃÎC€ ­‰Ë•<)øMC¼ç¼q…d±\O߯S¶’œõØþÝL Ãä¾Å\͘äÂ1o4t0èÏÎ9îX!‘«‘¹¬=(B1D{M²le±ñ >°ŒUø*tßT™#ݹ:„º@x§&º7‰Eüä]l±Y�¸V­éÂÊÎë Å¶ ˜ 4F%¹5™Bõµ™]d¤×ì ¶ZöjÕJ·.ŽºØ˜ ÒÏeæ¦Ô’úÖº@àñÃñ%™Š‡�ª€xžjÀËsiÞ®À ÈÄ,˜¾�‘íZ$ÿe*L*œ�¿q€n:~1ÕÁWñh/út»í3@ö6,s·¢äæ@Ê¡¦mÛ`{øYÛ^ D)]u¢¨݃äÌ,ʽì°âî3ïx�&&4· 1XêlÛˆ+ VP€ö$Ì^�)ôò>0s°â ûè1¯ù/R¯Ua‹ç©[EQé±UV8ÐÜ‚-Ë‹; AT÷ånl¨.žã¿C¾å.'}öµÌ"ºGmD¹3P†ËtIo×e'{êÿ'ä*Ò³`zŒR‚µ#°Nް îbÅÛÂûÇ-Ž» rð¡çE<�vwÏîë¼L.*¿¹vrà«Aî$ÓÉÜʽBNf&‹3ꔞ#²ù¥;˜=UK*ÖXU ¦jªÈ`r¸Á?_=„P³º@t}2lÌãa+òްì›~Ó4/ëÈžƒÇ6Â}UÌýmá*8ú}ü@£F”ùž�Ý-d³\yS d D¦´)‡o‹j˜ôerït´ëmÛY¦Q%a–ª]€6`̱ Ö5eŒyÆøÛ`{àæ#.âþûphô ÿ®góü50åožôŠîëÐÿ—Yø½µKÕŶOÍ·|þïd…ðgk¶0Áù_›Ò|»ÁX‹ªK _/Ÿ Ú¿þ§è¹pÜø¬ Øô5;ž�Ôð«f¤ÚacÔ�6î-ÚÉe=Ò‹ô'2gáN‡`nð'Ô¦¸-JVF~$Ò[ªYÜÉäÆ�»î⟤B£�VT�TgÑuc!UöFì~ö¿D>2AP|ILÁû5%Ý3Îÿú]&™%��Mv(5½“•UªÜ–ð¯�>{6Xâ9‡‹Þ1õmC6¯:T{=ÁCuþ#aû‘´› 3Ér"N9kN£ö÷W!Ÿms¬“IyP𾕌FÐø„k5èž¾˜×˜}™RÚ$°û@ˆ l‘ggÂcÂiÌá»àò"˜;ù)Þó%sýV‡]5è¡+A9U•x*%9Zá+ ìÑ­ì+~c‰ñh§�M-"KÇÿÅù9ûÓS«ü…·X9^ñJ ìÀ/Ýö½Û¼ÀªÚ:ÕD›«üË»ÖÉ2¡dOWõ’ ã1"Áh€$ÔÝwLšg‹ó޲ùd„E`›ªŠÞÖ#•|u΢¦!çÈíuf¯u¸ÂÆ¿ë†E)ÄYx±Pd«G=õ*X.æÍ»ä�HOa%<¶Þ@ý._y[ÃÆ9A«‘��BМ\¡þCнqˆ|¢ªmœ8-‡ þ9xÂ~ùYˆ_3u³R Q!R„~*°Hu¼lõÜ=o´îªs]>ÀÉÎRÇ‚L,Òo}Q­®òÕ§†TÒŽ‹oÇ,S“�À÷®µÅŽ�Ÿë¯[³d$ Ž/ê…ç-ôŽ»Íå3<»(ýæãe:Y£j [uˆ´Ì)Ís>€—c—/B:CÐãH£Î€õ`ã9aæ{jl‘ή[sk(¸Yào˜B6ãqP«Q²[ ¬)¹x¿¿¹·–6¶2ñ9ÈJ›caÖ¥-§Âå>s.pNr“­ª¤´Ñ#xKÎÑ”©^\gP³\&ø)ÞÆ™Õû‚xôZ2­™î“kÚȤŽ'»3¥œªÑ.¹€71ú[©¡¦NfÙò8mP�e˜~´D4ÈBÀ¯•&ë~ݰb ®–ªçޤûUñß-Ÿx¡ÏÒ¦)ÆVEþf?Î'¥ IíÀÐ>Oì1ø¹ePïš…µ|»Qóý¾i†Q’À ‚,oü%�o†+ê% Øæ 7ÚŽdëi¨GckÏHׄÂf %VßùÝÄÇ/åjÕÃ[ëÁŠmb{roÑà btâM#$°ð°ÕÑŒàK@샂 Çêçh® `5þY«ý0h¹(kœ3ži�’­Ï‚Üz‡­ÏrQ¥ÿÿÿ}IsÅá[tð%ˆGoñ´îv�û7ÝÒ(øÏžsË:syò.Ät]°.!A«çæ5K躂q4Ýç+wè;:¢þöèŽNiþÄÝuY-<7ªâäã»¶ø”^¤Gx"Gÿ·_12Dî빦œ÷S% djqÉM–@á‹þù3Ýõý¼•¸¨z×ýω7™ÇÞ6CåûoG—Ó(2DB˜y?5*ëûÜûš·)õõ>`6]‘ƒ1IMå`ô|Q* s¦l+î­°x”m‹6�ÕKêòPú«Žô  94$:=sš.-ÅË·ûÌò Í�&rvÛÎn½í>#=Ž­a¹�nšzß ±Âlˆ?%2"Q~Õfí­…¾ø}K„â²;±ª£”\í?ò=½ê2~øÞ-9k^f&[Öºû*o·@ Øj%R½i`ë@›bÖMâj!2@›D�¹�LJ�Î3Â+EÓ’—ÛN‰Y$”óP÷JЛg @²vW™Ž}0RóMâ…U@Fö~ã‚Úrtºí99§×ŸÅUŸ|³¯÷£µºýV@椘¤qÇ¡�¼Y‚O«�owòEw[î—èÔ~ª/fâœ�÷¿_I§F#…z’"Ô²1ÃV}¾˜¾£ÀbóÔGvÙi÷WëyÓ;i;¹VX ^@E†M¤ŠÄ”—k#“<¼KöðGêô�m&†Ú—PãÕ¿X»Å㤶ïxRÄzª#9È Ð¼Q¬¬ ‘°ª6ˆÓÐÕ™µSFxXßK�Zݱ�t!¸]MÐZê¥ Göüž!ç¿›sxµßŸL9\Z¬”'Òا¶„Ç#1<„½žJ=ÂÊ”Ô \©Á§3N…H˜0~}ØfPÆwc,�¸JÛ„tdþ�ŽÒwö‚©è—ÓÿSø°½µKá±ßjpM7Í»è!E… d¿Š�É[­Ö »äÐtëå�M!Ï^ðŒVgÖc}‡„`63'ÆÄ.)é (º–ã/ΉIi¿+|§ö�bDFæTÊ“ ¥Ú–s¯J’¡ËsSvQ2/u¼ð]ûùH—ýoŠ«ÙËP=WÙI–ïfAhדÆédM‰h|´³0]B•Ç›£?“Þ"¯l¦k¾Ý=Ÿ¬q³Þ.ô»ÞgåAÇÙ p ¨fž¢(óú %ö!ëÔÇl¸TÌVûìÏa޵ üQ)%<‚8Àu×Ñiì^�Ú\›i·¼ÕôÆ™Åç`¨®î˜@¥ã0;g'W4¨ Ìq$<À?e*(’ˆ'+’và>W’P©Å±jtbä‡0&x*†�<¨ŒIÅ<äL.•š_;U•àµó-÷oØÓÿšçÛàžÈ(häA„ Ö±.{X…=6¼ $þˆw8X&:¥óq´QdwY£—kL×/ Eè¸TØ31ži%ð ‹`3Ó�ò˜±É(�"4[{št+ÍÛ�O+÷Ü�2”Ð_eê×�ÕŽNßõ )å&טlADMÝ[ÿä )tË…É\¤�q™}ÄÒuIf.VpÔ§5Nó¨A³õÁ†~z�¼õe§•29eº¼LÖ>ÄÞ8`D~èçók¬ÖÖ1Cù¯éºWÜëÜíìK5Ò¨yÕ¬WrµªƒPÌ  "PÑy?î³ûìÅÅOó¥ßF×bÉÂ/ ج+Ïœâf]-´­x.æx¿¹D®k{œWL×WÞE‡‹Žôé´�EVKóQywžvnGÿ"œ$  k¤ä� &³­9lj=û ¼t³Ó?TŠi±W›Nk¡¸ÜzàåPWTózÈÐ’ïÇCë[lå‚cÝPáôhåÙ A�âØt�»xoß?ÑgŒÏžYœFÍ‘Ÿ×‰à%¤(p1 kœ°$Ûz¯s«Êš ½R?lµ*­Lþ°¨ U7{œ˜Ú¿á óˆÎ$Ãné›± ­¢<ìôWº v »9óæÃ©ªÌͤÔ`¥Œ$N[ÅXØ6 -†Õ®GU²Û5ï‚Û}™AôUºGq47ûýÕù™<ÁL¡oTn8³ñJìçäÀŸVÅôþÃh”Z!7DJè› Ôü³˜¯>ë)†Èö>’4ÓY`mÌYT÷ xÍkE† =¥ `ø×À�*ZŸ¨÷¥yžÓ{˜Ví/@ÕSÑà@– /Eø+Í %ù€ œXrE3K¸ÈKp€hÁÂÕÊ©T šbI{Aš{iEPô²'W[ ueÈæfËr-ÊÃ’ï•k¯ å®/æá’œP7š§Èð}MšGD5ŒâÑ:V;´†`‘I`@”ªú»zMw œ8¢¥—ÀÙ@~�Açg[@!¥ P…è�–moþÒ˜Øf©¿”­†f¨Žº{õ $h°ÞA‹|[½ÖÑ‚8í`ð„æ-ID‹øå�m¼["`ÂÆÉ{‡O§a—Jž)+jã0ÝÕM£Œý"?µI‡„uŠ FcN‡Jk«úxšäº)ASÃD 9&Zæ‹æ‰ðšMBuÖ‘ª'+ªJ[œöNäUz@¦Ü1ëé=¹Ã <@œ¹XTÿ‚ν($ŒIÏÀkùcÛá©T‰<Õ)¾Òv÷ÿ¹8;¬s•Âù±-—Ô9VbfCå†+x�7/' œ—v^¾ªóÅå½2Ï.Vèþ×2Í} ­‹#ö‰æŠ­£4Ž6Â¥r„hî‘O¸EµB%½Ç’@ðdzÐG™��DÖ¶:›6u˜¾/b™¨)Û+·–RÊK«…W%UÜW�wM¦pN’ÇÁ~ÌwIÁwO2â¹ºÄØËû¸`“÷5£Z!µ€+’ñé©„Kã.Þ7 ‘¤�Ý»e ç9�yù�vMÚu_ÒÛDL×6µ¬O uôUÑÞ˜wÖ�¾Z‡¸€]Ęî Ðßçþ«\»­ÀLÌd �0ŬM01vµÑø4dOÕ{–twpÝy(ÉÖ¥~6öX óÓ(&ÑL™Xõ/-êQ~à«t‹˜ž²`ubaðãwç'€å(G, àEî“P°Ž×ý™ј˜s»:�%ôÙ¤óJÙP�e23æ¶Od|àSÅü ·, þëÞ{âö~üR|Ö”´ß9» ðy?]ÍæY›á}ö­ÝÕL™‹, A¡Š­„î%GÂ#WQ\ïÑdp:«\dyƒãΪ·ììi[?ôåÀ'§°¤ó:'*ùꎫPÞ«_T6îÌôa|îÕmI†8mgòd¹¡*áÕCòÀÆ6ì¢zfɰ!:;0Ûˆ'Êç°14àR�üY w{RoY(ë’Û»I£• …nNµËÌúKyá:Ñ8.w;ÔÕLׄu‘¥•Ž•oJ‹P›ÙêÞí຀¶šê’±>˜h9ž±›Ê·]Û^ wððë©€DÛ!Ò\ݤ_ä@Qñe �Až™d”TL'ÿ Ú3>ù4ê‰Ï|7Ü© Û«I—-Jh�’bpIS7Žð‘Í:Eè‡:jr³Â�s´‘³ä(ç~I·ççEtI˜Ý-ˆñ=4‘I¾Aá“~¥¨Á_"È\Ô§<¥G³áFû•oúµ·ä\ñN_ëL3R °dX_•öàõ<†Âêu•¬«yŸKÙåE ¹¢- }?`Í  ŒœjQGéÂR¼š!Ö&’àT›¼Áƒ4îÚl@ùr-ÜZâ�­A­O 1‹St¬Fj =Åw¥'šM‘ƒ¢ëñªËW-K™ŠvH‘dQ_#¥ Tø’Ûd�Ä%Ñù¹{½&}ÂÙæo >ÑËp|©¾èH·?8Ü �]}_˜N{òiê“ÃÓow�Òá-`6Óï*7ë’e€i¢9�Œ¡æQi*Y“FéÍ'X"+Æw@šêe-­–r†¯l·ÖU™sÑæ¯ÝíèOг—Ÿ²­Z‚=~ðY@6Ä·f}£÷¼¿ŠAÚŸ%ùnw°}ŽÈ|Á‚Ô“o?Ä»ÿó@FR‡áså¿�ƒÉúÆ-‹'=>øP¹ß¯Ž,‚ˆ?åWbcVÇÀ²²+À7N-é8�_'ù7¿]_L4m Þ ¨�f�‚ºiÓ”ž�zº¦¡£×W�„¨àûOÊbÞfºH°&,‹þuŒ¸Oq9'ÖTžÆ¥éGQÇ6¬i&ž+¤ü?ãÿõœ×œ¬ -¿œË©„ߨhA�¥:ß¶Ä\jP½ž ‡ŸÀ•»°¶ 5‚¡­ïO¢‡ºÐâê•Vc 7ÃÊpž†§²ÎVßÉÀ„l›»ñýäü ¬›~dq¹ÕDÚÄËC³Æ?Õ—ïñ8fœ�ć�´~âQ§^r¢ê} ëÊÚ¤™cï Ø•<ƒ'ã-ìÃvÞC1Jœî²j+X‚/( ”d¢c&:i‘ÛÛp¾†6óíß²ö?k’шz·;+È1‚ˆõBª™ßXé'\®®ºå�ÜZ§ÎEÒÕyu8ÚGQÝÿ˜Mµ<�’¢"ÃÆ·&þÛ)©æù/¹Üs·ªªÀñ‘ù ZEƒAöÒÿD¶ËБÈJôÃ{Ò_@¡ö˜ô’ÁüãûìÙyÊÅO ®PR2a fÞîÙž f‘LëV¨€'2òßê{Iº‡àup9u{~¶V RÒxĈ�äëb «è1k~{þd›O~ôFß¶šØî�ƒgͽâªM|Sò} Tµéà=‚B¨Íöð…;bê!ƒír#<_©˜¾_ÍJ;ÜÂÑ�(ç)m9ý.ØéµIhÔŒ›UŸÜ t”m¶‡U”Á�/»ž;äüñ°œÅ Ý6Ð;¿Ô3‚ÚŸ_îæ"e<ǶU›Mà˜ýȯ­ì01AÑïæiñ­{œ¾@õ±ð;z\Ðg—<Þ¶€šÙ?ªke¿?«¨%¬| 4&ubІµƒÄÑsŽÃ¡0*<¡ê/ysáŸì’Õ�±×féì@ ÞnG<`í§�ÍÏc¥>1ã\ü­¢=×îº DV' ¡ˆaL]í�©©3Av׉GY3B˜m�ÎP�V$É o 0Äj~Wþ¤+<ÛCPƒ_a(áq"!ZzãÈ$ÅJ³zü\ÇÉ)s_Äkü'ÿ� '8Å2œWcb ’ÐÑ– (Ôäy$o¢�Ë©"W«Þ°z}3Ÿf£H^C³–.EüG³œ¼*† >0¯Ñ€‘‘âvÌ{Ð#(‘½iGª³n—ö€Mïq¢frk—*3RÏ/9ÓDÜ2eÝ–Ñ««}£Z‰N€q&QN¼4AÆž #´3£iMdiÞ€™^² ˆðEæj\k{lS½Æ¡ô87P«Æ+¬—<Ñ?|ÀG¨L%P_Õ‚z�ÙÕ™ÐgüßÀ÷êOõkè™5¾ß{ï@H;3OE·„6îb�ÜÙ,Xs€œ®Sï cæ^`¥R °ÍÕïÚ”M@¶‘3uÄPž�CŸ[­¢Op Cpá¦\g‡­ç{FUÃ÷Wfz°DnmNÓÁKLÀ9�¡Ø–Ð~Ôç{ŠÅ=º’…i!þÒtµ´ž l¾Ë*†ù‰aÐg2iv¸ó¥X»ò1ÂGmYÎŽú²-ˆ,—‡1ÎuÅÏL¢ÂÖ±k½lOg˨bV^~–Ü*V›¯.êèjÉ5@¦ÝV¥ ú rAF,ö•�^¶òc.GÁ(2ÎÊAF\Lé¸àF¾0xþBÒ»Éçò›+ä6D¥+Zv’¯˜ªKëä0¿<�Dz�\š�ÛLŸA@QyÝFèk…7ä¥_& MæÔªnî¦Ę½‰mijÏ@�jGLb3in`Q>A6Š"u­r÷\±Âã'q½…‹iõ”Ø/¢¤;$>…ŕԴ�ñ[ÚmÓ³õû§¨ãN÷/ÌÖœr»…3p},KÏkw'{]Þæ ÑØ��³ëÿÒÚtä±[Ô~¸)kâÍN†òš”YFîxe•Ecà*@†ÐBûVÚ'âÒ%ÑgÀî‹Ö SÁ|JOgÝ:%òWf¨ °á~QD–ó‘Àf+Ö«š¹™ ƉÑý�­Ê y½¯…üQ'ëw&;Õß/ (x<òÚ1îµT©ü^ú jßOL;¦[Ê&?öü×[yÍkrc̺×ûŽÂ.HÜ?ŠNËñÕr¼æšÎ†e2·¹©½FUñ¾/ü³¢à!N3Ë»|�I"B§@”Uï—l#Ô¯÷•Ñ�‚&}'†lmÔÿ0þþj5?-£ç,Ê õ½¹Cè:Hö§æ¸†'éa`‚ÿtñ¤»�sa.„ï ž¸iÿú÷Üà³^FåeèÆ-JS´¿I«�qTà "ÄŒñ�Ùm§Z$y> ÆÒ.fÊòJWa‰baëºVT0ÑxäȈ`~…º€ ËÕ$b{.CM€ÂŒ¢‹ÖÜ'`2mpËŒB±:w‡ú…tï ÜêiÄqWäwB"ˆ•Ñ6©±öiû¬€€)¸wð`µG�hgNb]ˆ� së,QKôä7I°Òâ|î¼íž]�Ð_毌Êl¾ ¶\æc’i> ܀܆nkÓÎf ; ä€ ,—ÿŒ{6ã©Â �WIRÖ²‘†@­ nZPJäIƒK<,ö©·‘,ªT=Pø žºnGÿ™îkngáàÌÀœQa'3|1�l&؇e�¾÷Cˆâ-÷:'"<êF“…cosehÌO•Š@˜Ð¯‰‚¸IJ…ühy׿%[LcG�ç«|s§"ÛÌ ÂÁYĵš˜}ˆæ’j= K÷ šÜ©¯Ï˜bÙImˆÂP7›gq.¬6$ôÈôª±¬c™®oųÁ«–CôÙcá nÞσڥ¿ÓŠà=CÑ•†HÃæ¬»ô�J"/„MZ’&yt”‘ Öîg$H‡­ºüåå —E=l²x†ë•»&rð ¹Þÿ]ß[µ¨±¤ªÁ}ÊTñ1Ä›u¥Ú[&‘Ó‰°ær¥¯xøùo£Œ,¶´G­~žPý³†Br�jŽÒ˜È�¬—øÈ¾þÖÅð)‘¦ìÊÞ•—»²£èWè©·#\œ?›ë¼…�j¯g'V¸p1”á×ÈŸE«\ç2Úϰ†[ù:«Š_Zׯ·ë+¯%Q�éÛ·…A ¤Ð\>&¶lóû›j�û¤ó šŠyÒÙê™Jz×ÓX"U.ñƒÃ˜d4wYoµcÉ”úu@Tˆ§ç×ä³hœÜwZÜGŽyu-|RkY+L• r2rèZHÂ[(�¥‡²ËîþۀFŠÇXÍ=ÌÂwBÚ]ïm[Þĸ‘LVÊ[<Ö8¢®0Ζ`œŠyü0WhhÐåÚÏéÑØ)m 7̓“Áñ©Ï’öý¾ç@C®žÊ¶D2–hC^h~ÔpB›˜û ·Ð­}=*:1qÔÂ#à®GJBBÖ�~Û"Ž0ÀÒ,9úçÎRüÙ]ÜñÐâptc•­’�)ÉåOhW�'l£Ì½C�ã¢N ñ:˜ê;ð>©¬âãCÌKÁÀ“A_&w‚dKÈÓU#ëx]$]’ìÒ nˆé�3‹ô^UAax�çÍôÁAh¯‡ñZ˜QÞåˆÓ…'g‰`ô0þuCÛ…Ì,ì‰�Ú“wxl¾<Ý9¶ºcú…?’JZZ[ëž¶¿5�È1¹M±Ë‹;ÿ', c·íXE2¼.ä:Z’Û�Pî©ð˜,V™— £jJ|EX÷žò æ°'ÄÏÐþò7 3ÈZ¡ÖD˜�Ë(¡yNTºš4Ü‹âäá ÅÂnÑ1ÆGBhºL´Ò”½÷ŸM‘ÂÅXcOoBÏâ�Œ\óV¬fÕ£W^C)_}az¸;¢WHed),L†¸OW¨תzJ U� p—‘œ¥ÅkÏk]¡D(&�{á)"ɶ†A`æÿ Èßm:žO«¯¦Ú¾ÛSÌilJ„Ú6¤PìlöÛÞ§:/Ì-7RÒ«1¦ý—‡ (Aš¼5-dÊ`Cÿýñ îÿ¶7õ ÁèŠxèåà©¢&[IøàËÈüt÷�¯•«óXbÊÄaoç+¹ö·QƒŒ"ƳZ™þO²Ð–õžä ¶³(žbÐóV®Ãdo’§»GJQÕÖuh—∭×ÔÔMrëýdBíækÈÀeâiϹؔ1?»Ðár 5ŸQkôOôþ\ùç,9K³M^ÁrL2xx.".­^ü¶ªñ·8Ë ‚ÔuTø!®½u¼€§?ˆoàF@ý§ÔëI„y`¥Ú$¡ËSD!úÃŒ³¶¨ÚÀµ§Ðˆ]~sb&¬~‹³®áÀn×/ÿŸP¸§àÌ·<ˆ�oŽ~!¦‚¤]¸¥t.„ï<õGh h&�`þØ2+ ã\êòa}”72—–ص{u{þU¼r¡Ýqrå¯N(Ãtþ¿sßЇéôYøÒA™=u4¡•ÏÂZk Õ,Hy„4s¡�ÞiøµAÊ64†e‚øáãSJ‰S¼¦˜hq:u]#;š¶w@™ë$š,AüIˆØŒ)ËÐ ]äzugŽBw34nûa™l_•ø1” bˆNL]ª»ó ¿R ™ÍB¥V¬(ØuʥЌL%æÒVË~a/ÙѬõnÕ© 0¬/]L{<ò:oú&lÎ Ìm‚µ+íÌî†õÒÔœ„ã�'ÇgžÈšèW"{5 ‡õ#Ÿ!|?¹œfä¯UEå�H{u-ô0-<Ô5"ñ—”±a­*ô{;·åë¡Ü0T"\�t…{rZ—x´¨ÊüÊÄi™”„—|}¯ÌÕøÌ‹Öt<ËR6y•-÷a£-~Ü«¬7Ð~ÏÉ`û‚´“Õö¯-£^f¹Â#/Cô¡بݚ&‡%xŠÆ}›,Þkz�i­5?4Ùú؂ϕaÎEÏIµƒ2Jé'.®_f˜ÿRç¨Ï(J|ØkŒ«�ÊÄFŸËðm0)W-/Øq•:vUÎ…!f9¿·qƒÊ›*%¼ÎùÉCÛ;F+Ó}â°Át : QwiÍ'\ª“úiÙyÅj+Še�JX$ Øê/×›Ú\\åŸtž‡[ÕøÔ–¸aë+¤jΗUÇÜ¿¶OE£˜ð'9Õø€'¶Áñ)BµxÈ~¿ˆÅcêhä;4Ù11×�ð§è]Ì•Ûbi¦Ò0ì*[Ós4¶þLQÒô7x^¦®W;/ÄJðM‰òq;cªúÈç3áwu‘s_¼óæ@,æÇ�œ‡š{%q± €ŸíÁ5• Bá'X‰!tÖúdÕ;êêý7ÎÙ–u¤)´® MmðJf/Ý¢ç<àF%ž»,2GñL[méÃ%�w00P)°t/‡‘¬´-ìTgÆñàZŸÉòë2�ËËŒÊú�»û‘+¶À …v0†™OIÒ°¼�,u«€ Zú#*Õ«¹‘w›™›°SV|¥­-a šâpÇó–(H»w_¥Øj~‘»«1L”«ÚP;”†‹oy¢CŽ¿}­ýxQ-€¹¨GFß¡½w+v+Émˆ8ð²÷êo�ôÀ&Œ€‰)›ÛÉ¡gš‡…°²&w5mKÏÜ7ê˜Éö_r–ÞmÃÇL|z²‡ø¡b³ÍÝ•©¹�P̎нVÆ–µtÈ´‚WFôz�­q4Î’‡$’¢ÀY HU�$ݾt¯ÉXõo‡Ýñ‰TíwœÛûU÷ŽÞž#TH ªb` ¥í~õ�€¿é�þI.ãpêšN}=X^×øAÕhvÊöÕü/çøΞ¿Kü,=z:¸ü?Óõ©ñê>…;†è¯]Ü(W"¾ELåˆÌ(w·_±(k¨o“É¿yà‘™ SfœS 8¢CÜu=çs¿íÇ\Øœ‹µ³¯hÜ}\Êí�&�›üøgaÎ{2óŽæ ÷$j¬·”÷4$ƒ£­=�´Âúü¼r¬zà1´¹³xþ¿´âÁÅ‘@´h~=ÁŸÂšþ··;ƒÚ ËãÉVgçÒEˆ®¤˜º¶÷PyP7%î_ië¥�ùxÒí³|»ƒRûâY‹…Ð=>‹Sz ¾Ñš¹pòþßÃXÿ=ã“îÌ[XŸP@§¯À*…Ø[M!û b V*;WöÜ T§§»ˆ®OD#,†ú™¿sNµæ¶Ôè%[È<6Dª*ç{Üý–Âb‡á3cRêw.7�þ0Gêñ”Ïÿ³ÊÌò|.m[†«¥1µ[Ê${y6h†Â÷5v){µâáhÉÙëškŸen[\¿ÿÄé ÍñYÚ.·Æ“Åý‡ÐKgë9Æ\½ ùºË¨Ì)A éÓ€u{ÕFÁ¼ØÌÖgí•Ýð޳Òo—,CUΫŽo„¯/­›ß»-ÝzцÖÕŸ•”sÊ3i%AÍÿPÝuW‡Ž�Aæþ%{£Iìy¾ˆS� œÎÎ^d�–·s=úgQJ�°ë JQ»:&:`Ôº¼ þý°.ä9B�þIz÷ uªC®Ü@SÕ\ÑÅI ¨'Ð’Àezîž‚~Ñárpbí`ÛÒB¨Z¨{£ FNZHö}úWŸVš[çOê-ÃXìÎ=Ÿ}q·ÒG”ý9 õ{?²u„lÛiQpÀФ{Õ¥¸ºÝh…–À¬Hí xŸÕÙrL#½0ƒ´¥|v'žI€�f M‡”±–qó"¼'»«—!š“œ{�Ca‡×µC�žŠ�¯cðŸ2h�@Ã.H"’ïtÞvè5}gu=²9Àó¾Þ¢ṵ̀¦ÖHc#åjâaQ£Ývo^á.±fÌ ¾Î©éÿjfIuA…Ë-ÌXDÐίBù¡uÿÙ5hü UÙ7CÓ,cˆ}f*%óFÏWP‘õ¢Þ›úÊÁ<ùÜFe©d�¾ÕÉÞñ‚FÞŒâO-9ÅVbU^׈qÂk¼1ûïÄ7FÇ�²÷£çpùnЇ¾�©£NM1¦�˵V…w*$¸ ¸\hö6—}5A½¨¸¸ü<tbúc©`£½ñ)Ò_ý;Ûè9�7�¤¦ùé”ê³Úî`N©£lêYtû‘v‚¡/h?‘däôú$J–_ªeØëÐ•ÃØË-OwßB�akó5BŒítÍy¯æ¸œ��£übê•UXZµÂô6¡’ñÔGê­ñ�ú U{PWÌÛy?A{×0_‹ú5¯¹)9X—c­lT)UêX‰ èúK|Gï«÷1OÖ.%ÔY¸IÎä2ë µ³nÃÉÔèꚣW e’õòù¬Ã{••^w~ß8.3AìÔ�@(Èôêð=ëbe?Œ÷» °¯C™u´ÿ*Ùýf2s7Ìß¡ê17Ï”ÿMžqN>’—& 3LòƒÍ0ò+Q©)8já(LF€Éu·¸Èçdéä*þÄ;¤hì\ä75üYÌá&Ö¸Øx?þ©Ÿd­ N:0ŸN’’!æ›Ozid©ÎF‚Z¯M}Þ1Õ‹J�×wb1d[Ëíç�àÌo±N½²–wpI$s#—WÃêF·ØJR�5*Ã& ª]#Æ€ *ÑÌe(wAfÞEÜJPªœ÷×0“g)ý\UX¸g·ÂšžËl=¡F¦€w63†o™ˆ-Èžf3²»Ó*ÿ+0é³+\wÎí©Xö2¶íÔÍ(šdsÀ�mô„(å¸x¯ØíQy% ÿ£‰ïtªºê”<ŸO&• ÷ølQß�DÑR9õò³77÷±F“e/Íž»³Q è�,«¾¥”³À³1àª�£Û.Yç˜�£ ä{„vÕ5v¸! AšßMá ZÉ”À!ÿýñ,@s<GéLàȼ>îUó9wã:iþlCÊô¢«af9ø}•ª²„¾ ê@ê!§ùˆÑ)ÓàáRè G >EZi²Á× Rl%Ä/ܨ˜Þ�ÓõÉöîA8Hë$¹yØòM7Yw:‘ÿy¡czÁc‰[ݹBq’é„c/Dû{9p@lÓi¢V‡aûÇÿ¡Ý0skm$u[/ ã·¤k™»p3pŸñ´´»º&¼¨@z_–†¹GˆK-Äå6û¶NÊv;‹L�²v~Z�«‰geܶÛv.̓úÜm¬Çq�\'f-7JU¢E>ÅF¶×%õ~ë¹âb#äß°©E~î»xèS7j%ÃxiãNDV.VÝæ,÷€JÏâU¤Ä^¸{Y¼ýlÙœâP5HXž—×E*I¼NEøýZtôdöÍtÝ ™i^d¢tðÄ(I¾ÃÜæó̆:´èØôUŒK,@þ–"‰³ŠåÀúTœ–SvÊð©ª63ê€c€~’aœ5‡ê³�Z‰o›ÏSS“pwø(±ð’S”Z’@+¹áüû"G pÜK\f©R¯Ò®Í�#[¡¼íÑàUrŸ1‚Ö˜,Ó&öІ8+d=‚ÇÔ¡T÷’ˆÎÜ»ÆïILɬ\›ã�’WVÑá2�뢀ŠTŒàm¶¾Iðɨ¶¸òO ®5€‚ 85èaÐï»k+p’×ÃVÞ½<-øØ њĵ¤ŠŸ¹ÚÀÏ×Rf¿•8OýÂÀ–‚}í}Ùb�*�u°Ô h9)¹ÂœCɤÎü…Ü2?“Ïüh#üw1¤s-áŒtP³`’'™ã‘Ë{J÷ʦrï/Ð8lØš7 ä�h�Ç'[Û¶ ´;«æä�ŠÐ G°¿/8©èË5/XéI+\ûO8« Œ„ü/ŸÐÄ%½ ¼xëÍvâ�& E²­ë—>‚å-T]ä„ç“w|Ý=ÖG"UÖ2LÆÍ@ÓÝ¢&9Í „-„º)�ìkõmàÄÞ€á»,à+ZԳlj£�{ 3rº¥þ²�ØŽ¹Ô|“|«9¤Š/BÈ·ôõë­éY5ÞË+gpÝ_”HˆnÞÎ?ûÝ0Ÿ8•†£éâ”z]¿%ï çb@AϦA²29ÌÆê|E óó:#�$nòE›¬.\ÙѬó„ß_†@ȼ«’ê€K ¬m"¦0�³à^ÝjàÔétùÁ£¼­÷KþMV'6JΪ†Ö·T Î̼Ó(è7«ç¨‚”äs>ƒƒ”Óîæ—~ÙýC8ì45öÉxÐÓ7ŽCõÁáoxk<¹�÷¨v[¾x|à'y~jô›€  �f1zåÞ‚6mKþz؃(íþ¦†iuOsÖ‹IÓ,Å:uúßäÛѺ¯•ŒË�Èn‡k {ϵ*E¯ù«Ãßw†ƒÙV]ÊV»ŽVo‚ Syë«HÀ«@­Q¨��ôjüœÏ`·ˆ–᪬㒠[é²Å½ú¾·YMzÀŠü«!Ä·%Š/•¡[ê‰Ö!m¶]É™„t]ZD½Ú¸}JѶÓBNv$tý2 *z¤HKÁyOŽšªÁ�‚IK¬,v1qãÍhqˆŽŸaU(t†• #1Û4…‚@]�F9æ3j7àÔð‰¸jÀŸãTIŽˆe^]�`½²r*>~¿µfx¶ê%9uPnܪpP阋Ó\<ÚLR6Hèà&:ªV8µ–‡Á9pÀŠ"J·ÿN( U¤ÒiQ‘èÑVŠ «:èsrépë+»üØ6÷F${ùÌx–¹MŒ¦}ìø»¦«k3Kõoó„‹{¤ö*Ïe{RÆ©J�¡0ƒÃ}“–yc™x] ©¬ìƒ³Òª9ÿ:2$U:S×Ç$åÐ8 "`øÛU Õ7ûò³‰Vƒ‰(Rc­£×Rœ½XØÒXîN'E»ŒI ºt�ò'ÿzxÁmp›¼\:Pª‹MÀÄc��½¢%¿#çW<¦¬}‰‰Ä±Ë2±Áa5T#<“9§²E»8Á_!Š‚ÎëëâQC?q ÎÙL|DFK.«f“ë²pYI²Š8$°¸¿BÓDõ0édN¹ãDˆX^v6&'�ÿfÍ %?í;ï9ñ´`dzNŒO›] æÉ³å—E}"ó †`&ÖK{ºÊðÁû?7,À+î{û^è-M/÷¨ápã<€UÔô)€nž¾©®_r«ÌY ×Q(ÆÔÞì×îô¬ºžœóÔcøñúÇ :Œ§¨<š:”¡?PõÖÎ5’MÀ1è�ß šáy\…Ù“‡ Ì8ãƒa×!7^4V¾’9c³iûíc€áMÜóŸÂEû8B•»hIu£kÖoÕkD-ê}Jìk°e£Dc rŒ„ÎÿK‹-ìHe�ƒö“GbcE\ÌÝO{<È&õ¾…þâ^4AS¶¬í;ËZD¨c^›OÅôuZÛŠÈä'˜’cè�Î(/ú‘ã7U:‘Ìž;é>M¿ŸF„¹°¿j�™ ?]ÒO‡'¢� YPãÄ!Z€•U U®à0‰™§°)Ï(†ûM­8�GØ‹¯ÕÏ– Px%yu â Ûôp¼«»¡”óŽåÛXJ”UfC”4¦K-Ð6-_‘ÉH>I©á(nú^gVýK¬ž¸ïº:â4$¢umÄ@LÑí'Å,ú|çZùó�œilQ»¢QÛ4;f[Ïú’_ ÇìŸ#àþV€#@.màì…€šÀÞQÒÿ ê;�.ÛíдD7PçÄ8£ÈÊË—rÕ sÀ)� Õv /´%ls{Š´T)†l¡ft0Ž[kevÆëq)ÞÐÀ6ÿiøÏX)Ÿg &˜f]3à8Ýi½>Îy™jõ2Ù¾¡9×…ÇFý[…þÌU+˜¥±^ÊùŽt>™ÑhÅ*j*JèF4¯ÏrÉ@}q¦r °Kàìâ#ÝcdƒÏ•@ÊÙ=v—èc>QønHøWâ|¤öînýÚæíl[�Ó»Dd5oi«ö˜T ‚©÷CïÑ=Æ1ƒ�·¤’­îøw’i÷NdcÜ ¹]Ž^=§‡$•¥WéKEx<+acÖæ¬ÛA·ïÑî4c¦‹ú¬8�ù"®t gm”?"ZÚóCk¢ŽHÔ'E>g6¶+ ÕoäDϹù·^ã ·þçî[{q¸˜ÌŒìs¡X±! krvOÜÀ�lO“óö®xÃ�¤TÙÆ h–I¥£­v´ADÀÕ6ùnû� ±ï%‡²”Õ�ƒk“§+_ñZlB-˜EŒÏ© Ô‹ÓtïÅú€2±Ú´ý„2`æ�[—5èà1!s(ˆ�ŸJ; µ‚’øO'ðëKO”f7Ç© ÍÕ!öì¿ÆM} Ð9I€ˆ§Ç£N¨™¼:Z€ š|žŠ$ErËE›MÇ�—k$-ã…ÈÛ]KMtaǧ=šiÂn¥ÝÖ(�¼•!|¼v誢oXB´ûú×r¼rô{oð7ŠeìæÔUâ#¿c„ϦҦ僷-K¡Ü`àùD¼`—Qd?Bý„(U¦ã_Wø@z -�Nß—¤¹l}é½ õ?is ñž[c€»a.ºd©4À}Å0Zé*ΖÔV�,Ú)Tœ.Ù50p6'åγ��?úº9øÂ€ñ*/ÖÔ¢p}‚Ú±ÓÜ(D(ÀrÊk@©²0]ÿI 1Š'Í£2¼@uä 9êJÕZÛ;:'á.vA7B9>öpï—àÇo�•¸ôb[>?Qô…†`S3lÊŠ<ÎfùGò P1±_A]«Œ/ËTÊ­¥½fý2ëéc ‘o·ƒž¦màòÏÜ[•Á<~úŠËQ…ƒ×ÑYÚ� r®_Ü&‹r2ײ[þþBè=º4ÿÈA ͬ,X½fýЛãZk‡ÿ¢ƒV=“z ñ`ߟ0WX¨–Óô2®“Á+úÓ×RSâÈ‚yÃí›ï`ÃÆÏ”€¾~EÌ™cÛ †-ù¬BŸ>gõóö– ‡ ]HŽïxô’O<*>Ø´S�´µ O'ÅPKmª§Õ/µäß�r‚Áøzáø£iøAyªÏíqµï9óÖ²¿:ÐK‚G=A*]ÿÞ¢�g^I™¡)ìÕc^÷#=ÃÊev‘aR�Hs�¾$#Ž"% “¸µÁJ<Çë» é§xñë-u Ï. ˆ3ÿg,’9N»ºšÐ‘G<»$iÆžšYJøï�°ê UVQ,2OºN­1<Þä•0Ò&šœ¬Ä*‘}| X¦Çù¦îNÔ9Éó ë°˜‚•&K¨W™[60 rhÝ=p.Â@ TLĺûxƒËvì¿pŒ¬H×n* ¾Íп ÊBXéX™MÉzŸ i®"äðÐ�ê Ö´§xF�"’¨ïÇ/ÿþ ò9g©×G|îT/º�Ø&Â)°Ð3J|Á:“ŠEGLL•A¯kþŽ¿;¿îjuŽÇ\a$Çð�IÛm‹«[ÿ>*çBaôH°¨ÃÕÝZŽ^ÈÑUïXeµˆ*[4)Á­u;>šÉöÜ yHä®@V‡.6ÚV0ó(Ϧ?ýØ΢©÷V$Œw5ÌåN[­»¾íÑ�—:uFsÉgdh`ª$ë×Ríã!ªOÒ,¹—«‰iÊ�ІƎ�‹Ûž~YXøR�ò¯¯­ƒò!º;ƒƒN§*fïï»®-:Zƒý·fÒÇ�Â7m]37ðöD>¾eÈ=–·@¤ÿ,Z"¨nCÙ<#×Z%øM‰½[4ƒóºB]¬¯#ø“£¥tÊçš^Ÿ‡­þßßÁ=‰·ÆýAIM˧ý¸÷b19D„~ÿIòËþþþ_bqN  srŒA²žÌ©Ïзy½™Øùó¹ç4WÖÆôoº=®Ò.p0Þª8Ö¤Â�z­às1%�uÐá|tø4Â4ÜÿmdÓ{pŒÅÛ¨»é5DÄÛ¤+ˆåøÿÞ0—óéwGórÀ± )Ÿ¤ª4Lá‚”Õ f…_Ý¥¹‡ã"›J²=o2ó�OPK¤s…%χeÉýë‘« 5×þ6~ß�v<~ë¤v%2ñ¶^†íªý»¬~༇i 6âÓ0e�&Ea…×L€†©C@R  ¤€ÐX]® R]z”ßÈ÷²‰YÝ{ÂÓꇱo6BYGƒNÖˆ „^ý™[0¥‘<sã`È~W†T&¡+éÇ�P'€ñÐ# z÷>ÞŸnGÿú÷Üà³^£×Y¶é·;3ô•ìÁ–vB; Ùt0!²—ó7lœ_<Ê·hÖRàåR¨"çžH_Ȇ…CµµUÊB¸\QïÒÃNØU²º7ˆ®fèJÑfS‰¶*÷HñÒàÊ‘ ¸ãšúòa§r)À¤-×K¡àV¢uÏt¹gC<ÚŸŒ<†vEžzbò'ô º5 ‚K£æZi½À­!-‰’ Ò›Jß,á­\;³î±Z7óbL—¹¹};¦/rUý�îo×kˆîaçïù äK‡zÍšQYm·å¾ô­�ÖÎ;رõçAC-pèÛ‰È`\ÂBjÙVò¬¸“irN]0eÒém<:_u †[‰ æÞn þ{osëá�нL¸‹Š¼Ûç<µcE�Ë]€qû™n“v9œ +o§!Ô¤õد3Ç¡6"è±)E8ó(¿®}�ÕByRcµ›ñ«lw²ÚÈžÐ")½E °×DЦpïu¡_+Jo1ƒ,"´`F…BðÖ' »‹Þƒ öµ©÷ T‚gâü·¯ü4ËnçÓÿò#ܾcìIjÛwÝ% šõwÅF5¸TrH6¿4_<¹¿½-p«ÆÛhUóvU¶ÇN!*°[€&Ó¥5´¾Â#ñ�Œ)3NȘÒâ~üšú�S\}Z60_yg…‰ýìOÅó ÐÃ}3TŠm>€™�‰F ‹0K¿«ˆ�#J�Ô-6í_N‹a^‚ÍrÍ‘Z÷Báôñ#¤t€š�fÞ‹”Áå|È $›vV€–®¾ƒi;(©#€¿ütdŒãŒ6”Dœ-NÙíKž\¬ÓGÃ=MÍÒ¦Ô‹…É¿ 3‰.qM†š^q§9^¨Æ $´Þ!Î;m=”΋[ïõG¯¡0¡›¸è¼û!AÕÆ+g &š ¦pÀ;^í½}Ëõ�U,Ó·KkSÆ·œT¥Ôe¦OCR NØS+4ÛmR¿i~DŒ–HËS^ØWµÛLíl¤7÷<¥%±$’EÐfÌ×·M¿Zàå µÅ�Àhø“Kñ{¦Š¤É ©ŸdÞ‚·ã¶œEA3“m ´Ž®¼Ze)ö¿�_A[T×õ°3>.”Ÿ¨À¨ØÄ2¹s-…±™Šâ;»˜·�ÞùqÇÑ ÙM�ÿÃ{P0W›Ö¨\À ûÕª•bë—Ovj0ý[Â}^ò ÌÔBQ›�}¬ÿ>ßœ•¥~G<¹9ÃÌòS´¦æ\jm‡‘(yYlxƒxƒ#ǃ“×zÖAMÕ#Ý…EZÓ?òˆhñŠ•< q2ʼMàe©¤Áh†e&‘òÁµ¯Ïbƒ”uŒà´®¾¼ŠI–�ATÛíÚ;©L”p˜p*÷ç7>êlåÔÌ ” º‘hù(Ö¨mÍ»Ê�Ë:L¨KêÙeèÉH`L>µœ·¬ó·³F$!E\ª�¬"¨,0w²œ�ß’å(jþ�©•JÔké“Bhj€,á- €“Zù ›V¾û�vW!ÁÒ]w¯Üö(²È ‡'K¯}³³Èm)q6Êtí¯»é¦ÂSse:ÖU‹hò]#”~ÆaàOßdÑVÓXg#NõF¶­€¾—½ýk%…Õ€7wA›5-Q2˜ÿýñV*h±¾÷«S’2—£[K §Ç3{ÔKòñ3'àiÇ~%X—h¨K•í¦ -pSu¿(uÙÏ'Ê…háO¾Ý×ö`M­�ÀîßÐcxåùÈF�>ŸÀkQ„S°´ºhb˜ï±Ö^ªƒ3VÛr=ÈE5Xgpû¹ïE‰Õìh*öL®£cy»³åÄóXœÐÅ“qõ½hQ¾�¦Ø¹Ïþ-ÕHa=ëiù—å9xzºÖÖªzƒ)Å/2ÑD+$�H½;³" j€UÙ?zöCÉ ÔÅ*Ç%³±¸¹Ùí=ðåý&¼ËK2@6ypb:µ¤[Êx¶±DÒUí�t\0™µªÿ „ovÍ|ޝ±°%È9&g†3#MœËâZj?8¸Ñ¤ã$/ÐA@:Mj•N´þR»Á²$}ù$ 8��½³¸EŸÏÖGi†ýü•È iS¸!{k�€€‚�™¯ã(!)5…Ý:¹¸7gµ `õTžðÈ]NDûÌïrƒ¹„‘§ô•µƒi± áéæÄbÅà0¦ 7v<…õ�ÂN,"ƒ§–Í ÊH¢´¯“ië/âQLزZµ‡•¾ßœ… ”`Á@ð •]Ãqd4íÓK˜5‰¯ï仜’³/jÓßœ´?�Ãäx_굞9‚b„VI8¼�1·Û h"$ü“ÂѤNd®×–ì³ZƒaRÇû†În"¨1•…=ù¾N±œý_{5ÎU¹gc¹LuÅù~cÓ+à¡HÐÍI‰Ù±ž8§Ôâ1ëf^fò×/:æ à.gfge`Õ‹â’µŸ®ß�ß!}šwÆ9ã4’œPê’ågêt„QÓã�¸5­Nö®™gÎaT‡XÿOõ˜c ‘FG9Ë1VÅž²Íuím,J÷–ªTÑÄ¿!ª.BÈ£É6r¤¨1¶�iøýů„ÜÓ ž0Î ž“E?ÝÈcnmÌ#zÝ0¬Q5áW÷öYxÈÛÐ.€wôèW³ãèËösºWçŒ5<Ɇ´p¨ô3šûؤóƒ\îæbñX�Ÿ„£�6>�¬ÂÚz�Ù‹”‹—ç®�ø…‘é”]è”cM’’‚ó‘«ÁIJµ�qx∆ÑÁé2Àjù²æÑ%Ûû,¯›ÿsÛ@O©+†ìÿðÅ#±˜[*S�$þ’Î1ƒ²©ÓñPÝõz»‘öTÅ=½©Ù¬¼®æHCãUöÌn]š¯1L©zÕW{ú1dv×¥Œ»4@ UÓõÅÚñˆð�ôªçѸPBÊX�JøÃï£Jqˆj"·±å·°‹ôÞðÊw Œûªw+?£€�¸Ì³q,jˆ2ÄÔ‰/¤dãÐ>Èbèý�]€àS«Uk“»Ï“7Yž‚3÷ì›3[îp††"¦GTØlëŠd¹/µdñš¢BÑ¡{.ðˆ8Ñl“è8ÿ\ZGŸ¨¨ÖÛýÍòâ„&{‚G€öšÈB[Ç®(œ4{Œ‰ϯHÖ½Ën& žrNj©ÖrT� yzøöÙ[¼=c—¿\à ¢ E'©3@»pˆa˜¬ÌJ`qú~ã–©üV·8ö¤=_ É!)¾õøò� 'Ïž VŸ½¤â¬ƒñ¯`)ýÖú³R‡ Š#ÑZÑ4FÂìi ¨ÒÕ\™¹õMSåÈÈ¢V40y²û�–)lpÙ;vøìÏÙï}ïAõÔÓT8k}‰JàKÕÿ~´»ïÄ¢m»–*‰àòÇî¨àé�íQzkꉯl˜[=xÎHGdÅâ0-Ew6^ÿ.o§�s oþk}³¸V³Èì>  }&eȦœ,‹éh­\ê�€þÈÌÖKK –e@̯É"¬Ž]ÌFÖàjú@Ó,Î?4½ÐÜ‰Õ jLšë¹@AsË< |y[ràÂs®–Üé]ø=V1¼ñ©­²6v‹Üa¤£oæ!1),4 ?d”°÷íÚ’"SKLʈ�Ë1óVú®u¼ÅÕ>Ë� û:Õ¶#<ÛÐý±Æ à¾Øù༑¿B���UžÈ†P”¢ŒâI-¶™~ª..øÝšW½)ülŒ2(#!Ø$Tãà+‹'iœzHì¿£QÕU°K¦\ŽBÿ„„ý5AÇ”A!6Å^›ÎçRŸvï,$-ŽUÿÎD9Tç"—ü? çëÛ©¬ÞW|ü¹á*1Û YýåP#'�M� òJUôÝ~nT„NßjÒ¡ûÓ ñ„N|²Ù€¶^æ×S»DHŽ­�Ö±‰b0?ƒBºZ2ÉB™H²Æt½J V[™®ô Bè!W‰ð,t5]ùžuøXÄ�‰5ö4”UP¤2úOb£Þl ·™‚RÜ’ájã˜'�\÷£8Ô3{޽º$Ðx®pÝÔ¢BUpvò”•›´êGJP‹ ñ @äAótž( VGçð‘÷êÿAÆ›t;ħG#£Õÿ6ùSr$ÌÒ¥²¶6¬ªÝŠÂÕ€œ—#°ý³Ã6NA MqïiZ¢¹§ste]ïª3®‹<´�K=!³ïï`ûƒ¤‡A­ô'âÌ£‚ñ»ßÍó½® Ø‹[QfÉð\\hŒ=d$Êb¤oOkŠ’·Ï{¡ƒ;šLa›rÚTï§¼Å#Š¿‡6WŒ<D7ĸm[�Åúnpxh— 4ì„«£'é'Óu§:¸íz"ê´Ò2¾Fÿ̘ÄÙûÂãƒúa…�›Çr�‰æÏëÑŒ¬¤%gt ¯Í‹>Cnw6= :w¦ôZ:G ñ,Ñ=>Ö:>t`UˆÄ0¸.uõÚêˆ"³GÄüQoØ^ï+�zV½è eP‘çxe5‘ߦùµ4è F v�øQƯ@—+êVÉ/%“†*ÿ“âwÀ’ËX±Àyù[26ÃÍdÆíŒB5ƒoÐSÈᄽ€¼W×]àw †`Þ¯øê\ÈD\·£–�0B�sâö IiD%ÚÙ Ô^b;rÁ+6{ûº�ÛèÄ™½Ñû£„/˜5º€«Ý¶²2Yî™Jù¥Ñ|ìæ!#g~ÛÛp7…Æx³ð¡­T™.Ùr¾'ŸF¢ùÜ T.F„/Eè×eþ2.� Ê¢«)/[µX"0TK»õ�‹¾V±…’?EC72%7'ç4úkÍ£¶ ÑKÐØœœ�­Ðë<¿Â³ÒRÎ�õCó`·ñgàM ‰™y87pø[¯ëSVë¶«u×~÷÷£á�®ÏŒü ýtÖ‡ «®f²²¯êVćUCò¬‹xž”ÜÙ– ¯ÞZ ÿÅðý’W›¡'*)E+„‡OvôɽÁã™Q»È`p]õ´?r ü‚"ã¥fgR¬ÙÙ‡ÎQd¼ìêŸeŽÄN³©Ær:ñ<âß»_”Q½:¼1ËNp.õ;œÂL q['.J„Î�ö õ¢cÌŸ°›qƒ)rw6žè§‡Ý§J$_–-Än&PŒ™¸ay2GrÚ´álÁ]H$Ñ‹%~DÏÚü¸æ™ÑÇQbùÃM˜ ]××�e±PFNidšä*"q 5’u$›•?ê|V@œ;¬ ßž:"¤p[ëÏì%c;ç j´viW‡õí,äwámÈî‹ä.ˆþghðŒ1'rK þ:L•áßß[ïézÛ‹7/<5âDÊSä´uvéÉÙ�B *ò‡í¨Ãåé9®gÌsÞ‡^¥^« ÃÃ7âØu-Ù‹DráBö‚ž ¸ yü¥xÌGˆX#8ì2KéÖìÙèC°àžJ=0 ƒ°òÖ8ä¦ÚKàçF¦q’5“*|.ªó¾MK¢’Ô8µ™Â˜†ÀtÏÒÕJM„¦vñŸÕ;JÑ*á;߬¦Ý_šKܬ>†ªD ’·cf\ŒHöˆ@Üœæ�¥ÝHò>‚\X ¶~o{^K¹tŸ…¼ÄÌ�¨§]Mõ½¬˜¾^õljA8ˆM¨Z™N>¾É©DvPu;mÃ&D�¢?åG¸YÌþª­y›©ª7„Ý#ŽË5ÎöSNN€õ,• žÔób°‚4å±ð8h áÓ´îï× N!�›Ö.GrýÙô:›U$ ‰ƒ­¨Le[Nê–­;:LÞ-�ÄÌ<›5Bȵ֓±„¡*§ÁØ;VæüæýÔÅõí_ iAúõÔ[(c ñ|=+ãa¾2o0+ß#k&ä¿;5U½Ýs„üžS�‚óÏF$9RȰ‹â9Ó3fuí[úø\š~œŽ»ˆ–û©TåL ‡Ó¸fÛt¦lý<6/G  V…ÉTÙ¨|Ú¥øiÒvk<¥«2§}¥*µIHxåôÏŠßÇâ¹9&×€+þ˜-§<ð-Q6ûN–ê•´ÿL¡gØ6w¡ú÷ãƒ]U1 r}�LÇE�*eÿD/¸¸?ZˆPPÛ÷ˆ¤ìx]S¯)>‰÷hz˜€váMG;‰gŠ‘&¯_Ç�¶)P­…t>qú!Ô@ž)ÍóQ=‚ »ÆÌý�Þ!ÁÚ´Ì!„ΦÎÛÏZ< $ù�…ToÝÙ›žk¡tvîÍW˜³–‰Ì”ð i\¸] -íéç§EzÆ£±ú�X¢ |á|ä€3†€Ý”ƒ.zºŠç¢�Wž¯ÚpÈÅ^È·þ¸ûbò]có,¨M=VΨÙPÁî04äzȘ¹ô&L¾î‰vð+ˆ0ð¯C³™ðé?°ÿKƒg³ÙókþFn#Z�óxË+&Cظ²²BÞ‰ Çâ÷;Fb¼%œÍi{EqWïKöÖ%XW$ Š9³xaC}¡�YûsÌ]°X´¥Jz©8,ˆB X¸Á¸U±‘îΞ�šÍȻҟ©Wúdk@¸ÙŠ�÷–<‹ððƽS9òÿ©l-ý |€sÈ'mã–õ}ÞqK©DöëáOuW"–£‘K†EØÞ¼i°ÈäÝp( Œv¤‡I¤v™5�ï–jÓ”ÎßœžÏx{ ƒ*«\MÒeÁ¬Pœd­&$ ËÔÅJõóLF>Æ'¢îØó_õi¸XÕž§­Ô*Ùæg,±Në/P ÛT¦=õA¼f` ¨‰˜†5ð5dƒ­ß©<®Ñ®LáØS;?il€2@¾#‚¯È„W«g¬^ØïaÀA¯„[ÿÉ…Ê€|´c�@È4t(½@w7Ì(™vÍzà^²ò(;jK$óQ9~wd¢o!55|¥y›¤%Ûx[ �Ê1Rz´ÃÚ0�C†¡7ô˜¯3•pRƒõýÕ )˜ ͉ S œ6¬ÄtI»¨ªÈXŠ8Ù ‘%t‰ÊÙºt=Ë>¡³ºž`‘–¥îûVÀ·°h×øËhÞiÎaÒÈŠlÅ„j¾€/5‡\¤×™'‹oÑéÒ‚ÑçÇf×…û©�òºM á²ÙÂRÊýÈËýqä{�àãÅR¯Dr>ùžûÖû$ÁM›ŸHô3„Û³jàìªÌ9¦4u@’‚äa¡§E¡3™X–Ð�Éz-$-8DÅ¥•£ÍÃϪä3™6¿èoZî$Ô�½‚_°>¸ª=œ¦£cÏXJdê´Ð—~3ÔYÌu-/EÓéDä9 “-�Ä2ñ^PÈÙswˆÆèàª!7&Á1Ê+ G\ÖyÓƒ–d�ƒ�løRêòW~ì<š~:Oh`p¢¦É†r@^¡§UMªlߪ„³c„!E…'|æˆ6öpNꜨÖ �4Þé¤d]s\§€ÁY*(q»rh<óÚ~üQÿ^ÊÇ@ÑyEÀ³-bAŸŒ_3¿¥Äq'zvËs¦�Ú÷;OÊßþ“T¡ä_"ëеäÕ¸R’7.Õ.n{ÃQá‚sGISßßœ;·¼ÕÄkò"ëÕ¶ØI|�Ú5ÂS³¶rJƒæ¿ØIï«É†`zB ЍçM‰°ÌN™fú:©køü/¥<Û…•Ãé<µSE¹¾~5ðÞݾÊE4+ŽÂz55œäHˆ��3ÈÖ<Š&`FÁ= í4eÕÈ“¡IcÇ7V•J!…14_G}ß鿈N%¥åÑïûs0„ù�ü\¼~3\Q­1=å ;IšŽ9’ÄAÐ ŽÉÍHê3˜°ž€*¸@ô™PýŒ`öË8�µúû;† f €“ìÛÎ0¹°ž ‹m‘�]àÎX` ?ùç4}b¬Î�ê–ÜêÚ(žÒ–²æ——'!f�‚´©Ÿ”qùtxugLëñú-Ùø¼£,ß\µª£läãÿö̾‹e�M@jÇ�Éòšþ´D7}€F”Ep@­ æâÆJ��ê&�dGºŸ 8&ÖP){›óB¥�Z$y”Ë0r,Ýè1è3Ö MÅ·i6F¶™J®«¬»öœrĸ:u˜¶þËyáyO§Q³y(Ïÿ½o®¥ÿGÂ>û�+\ÿ þ×] œ"þ”¾ïlf_ÊãÃ[ä=ÏfíBÀ\�.°¡�å�aš¶«èWi1\E RGþ‹ïä%5-‘t�PI•†b~MÚ_¿™z_µÕÖH-žºñj�N*"~}²èÑí…ÖùXE†¸*ZfØ`VEŒ—nþÞ*Ù=\€É­È�z�–E�MÁwß�Â-åD�šý>=e—;8d9V÷êwP›TÈt ¨ô¼ÝÎz†�Šýcf4Sœ<ˆO¤Ð ¦]³mA¼¨À„•8iÎÿ*«¦d‰’–{6I7&œ'} óq_P{ɨ$ðƒîK¹+æXƒ¶’çÿœl+³(˜ )ü̲½uÏ�µ¿•÷uM©’âà‚K/{ìßíÿ¼j™u‡O1‘‡pdR?X½çcÁHˆµ�+kßÝrU!¡ºx©XcOšTß�á_ã{DjN4J pš¡ÊÞýžøÜ¡T\"–}m[º?«Gšb‹ ã§Úþ3ü>Öê— å¥ÍÏePÏÍUÙðŸ]Ü/.‹¾Øî¸q?wç�Æ"Û#äjŽU¨a«rOäÁŒ*,åö®_°†à’“¢CÇâÚWb÷Û‘“:¡G žÃß6{�Á›4»+•ëåÃø}Á€¢[Fùè÷f3̆Ç^ÙêoЇ®Â$ë¨ïtWºµ öû¸îÐ<­ù3àº^óœÌ“>1¨æÎgl|åíýêãÑÖ�SèäaxY–: 9‚�àqBIå“—' _sÈÌ”(êÖÑ®3½Ö@B›áY•Z‚Z®I¦Éê#X¶²Ú­½ #þ[!­Pß«ÃõF™Þ65«$0½#¨îi8H§{2¿¿êÿöóÏÝ‘Œ/Y‰?Çñ¼v'#î%î{Þ«ÁÏ²èš æý µqû 6h° ,JËaÇR] üô+ãëgÌ»îö-¼Ý§TÜÆŸüdfu&‘ ; FN2yg\a=-‰Tôø[ú?‰Êë3Úåªè;²n¥]µ›u?£`Ьնr‰<%â‰ÑÈŠ·$9ü7ÕF)~Q®’Ã#Ö°:W܇Î}Ó/ÿ’w)–@ŽÙ0Žàb?¡(�¼Áˆò®i&úf1 Òš™º[~¿üq_ºÁ«Ó×ý ˆR×шLI,]=%`X»-KKÌÀ@j§ùZ½¹Ýäz–OhlÕCµSY£¹·Ôðn" ˆAš.ZåÄžÓL�T•Ay‘Ž«e¢Æ6è0•ÿ裃¥ÙDŽW†dMÙ¨OÀp¨ì (óà|ê-À ¯i˜õ׃Œ�ìòS§§Ì ñûÝ;÷÷aÚ»?£ÂX/Ú»¦à …�;nVŒøMlÂòèÒ m0´w5-¬S>&u„xlû²�~½ÂA.Œtái¶ýÇ‹‘¿d­3IqÿC,�‚W2.@´‚½nÊ'÷Šž\¨WåT.‰Ë$€gaM|@9õ ˜³ÍÔoÿ{«ÆcVÊTÖæ:{ ^ ìì¯SÂÏ„¾‘ ­n Z'Z0 {Oy“™ÁæÃ•Õã8\>$Ê•Ýü\®+ZÆP#°çÉè¡&''wœTœŠ9V ‰AéTOgf´aŽm¼saÏÚwÑ`«ì më)è\5)‡C&³ïÚ¾Í0oÁOÎ,Ò“=vfÉ&Ã#V¢:cE ^Oçs  ¼§=ƒ†àüPâ �;<tØ=2ç@ibf s«gxדH˜çû<‚-pÆÑ%jÞW¤!9€�Ñœ‚"²‚év“ ÔÆ*ŽRl“þäL�ñÁªYZÚÐ\W¤»úê’jĆ 9W¿c9‹.þ¨u%eZâKû\y´ qk å*5Áá‘taöG³•?N}켌ã²H ¸!.{Dí8Oc:ŽÆÕõ|ê-öR` ¯—Òä®ECn�‘)&… ê«EbxÈUA‰+s:�Xó«è¡?l“],¡¤ÀŒ¯T"²ÛmÜ©U=ü!Y~'�ë#Ú:Z‘µ ˆ e{�å­w˜%Öcv%·\ƒh)pÌ”nõæŒH �;÷Uׇβyyœ ˆ°x÷º²lÀáà»Q2æ1 5*Ë¥”z—2ÔÄ3¥˜<`r`L~ËQºÑÀ¢Ås�‹—8u©ÚîÀà HKDTER§QLrKÄ,íçœádПI옷Õ\³ÙÃâþñeÂ)&@f]cr¾zת�cEÕÊRNEþ‘{”éþ+w¹ù¶’ ¾«oÿا�ùí(Ôkttèæ›žd–ô�°êµ“-¾áºŠ*Cœ7úù5:_Œ?VmYº$MÐ¥¢gÊ0§jìþŒµ¾;x K•ªñwq•˜:UÔàçV°ž™à*TP=ó‘~ƾCOèg§7rˆf] �+hûäØP$o@%’á„îž ª8NR�| “ÃfѼ{Z¹MÍg4KòRÃ|ÁLŽç¾m@Äÿ#Œß£þÌÍ�Ò�°ˆ€c*±7°Ù_ùuSÃýHÌR|T.58NñŽÓßd•.i€S#�ë멵ôÎR±Î¢äÝ›ßGlGÒ7[‰3Å©PÏø8˜Ta_ƒ°(zÂc¦i÷¦Þnè#Å(>˜¤~Šß*¸‹tƒ™_7;Ù<å€'iø¶+¹F¥SÊE`ó;}3ùø*ûˆ„Ž},7¶´€ ^¹íÜ]R”O ð^ø‰„Ž_»Ý9œ�ç0ž~ò¼4�yç…sÉSöùÎÇù-Ìë}ó¡B6Kã!©ÁvÍ×Èu¤&C{:Te)Ú…,kâPbÉ-}þñ¹&'9�½´¾–F´™D#—iÔR8@#¶ùƒ ªy H—ž;ðk”}ÙŽìæQ°š_7a¸Å&D�†Ç–û¿+"9©¸Á\øWœöÆmKÌå¬cÃÇœd¸ée ‚ƒ*P66‡¦²þúI‰bä¢W©ø¬3ÝTĘ Põœ M"¦XÓ’Ú¹&c;°9¬ª÷ ȵd5OßÏ¥ß/KIÁg\[FÝQûs&h»É? €>|s1tõ=^õˆ ñ1od•"„àwG�wfO U”·¬ºõkqC~Ýîð½,[„NV_Už«Œ²ÀÄ’—&Ò=çoŒ<ôºb ÷¹Ó�XÕ>µGvÁêîƒÐû6§BiÉâÇ÷Õéõ§�q›Õo1•Í¢4L‹f? ´Û—TÇcت^å›iÃáwAX‡Ê[‰bÒgªÐAu•.Aƒ.!÷À!Οùµãž¼ò“ˆÞu�Ëð‘±D&›5øÏ€Æ‡nŠbÃǽkÜÅú5X_§“…GÚT3HË-¯¥Î8?œ¶f¬0—ò<Ú㤺I¬öT³2@4z?RiÀw”r¿þ�:{m"�.¶2ÜA¾ ¢û¶ f>‚ƒþ…æÁEr]s¹Þå ›A 'qÒ˜¦ƒH‰8èd@•ðþ¾¬<­Šf"Z¾R¤€¾úhÝ�•RNaÜÓsú§º…ï³JÉã§Ë¶ÈØ…i*—¸¹1Bp kœ¡¿~¶¬G¯ƒÎË@Á~èuÀûOaµèÞ¾&Þ~sÈbŠ6|¹ ¬w>-h±Ò“Ïë�Iýú ÜBÏxx麲ÇÏ”üqpok(zÂiŠ‹™ÿ›™.5Ìn*×þêÚ!#vK伨¯DùÌ%Qð+«�’«}„È‹äýÑZÏM¼°Dx;É[—7¾¦w`/vË爴Lw ¤ ì+=¶¯1T»·Ä£A’ÇH€ðCÈc .~ØŸv¶½�Ä 9øŸÿ4)?÷öæS‘|Ò—r™a‘0¹¹T¯WäÃ:ÿ£Lóƒ@_‰Ñ>\Ž“shûQ1>U(ÌÙÊ£ƒ}¼œ³R7*¶éFeúTƒ4�èúí>N9…É @R¼ð7XÄš:X|xÁÐ$ÅìQèQml ¶±L2- ÓîYÑ8ûþ\”èÐA{Ù]ç ‚é5îjîÉoï¼ÍÈ»WåÛ�°X¢ÉSÏs¬êYì¦i?õ×Ô>õ0úd× íËã¼|€™ï.š: N^›’¸Óz¿² ÑÈGZ¦µ4Y/ð U|†r±˜à·æü£½#³OÁ†uÍ‘›`ÝÆ‰šŒO¯±Â ÀºŠ-�rET*�<×·Ø.£%…|ìŸÛ÷¡�q¥D_�™�È -%%Õv4×µçÒr–ˉÐÜ£0eùÔ©1-ôžîèÓ¨(åCתÚZàeTªœ—LÏÿ‚ëbªˆ’µâ™ãËÿ3K8_�™S€‚ÑšuêÆ¼@Ä.ÙtÁ²»ºþd]LO�²ÕxGb¼× ÐlôQòeE6ìi�è!pÜîv]j­‰:Bjš`˘NôРùýLMë{o­_�@Ž%<ÃÛ_p¤³Çʤ¬âÉ¢e¸{A“ëÉ¢£ýr½b›s½’ \Ð’Åë—ÿŸM¤”´F‡DE‰Ù޲fùoZz±>­.YI‰‡ñrOe5Ra7’)™pJzVùÛl½¸CªXI"Vh beÕ;RE‹õÚ‡2|,k¯Sjã*Ñ®Nhˆ>ÄBÚ|ƒ-áSåâUÏ‹)ZKû©7tÄ;ƒ%ïó×¢£+åÅÎI)�ñk<’ ]ŽwA%É�Uwe:³¿”_z†ÝëÏ7"‹ô¡Z3M†Àv6ˆêUß8/U¯p Œfý½Àsf­ížî|-�?Ÿ>IW >KG¢‡ ËZ¬×î»Þ_kÌØa„cóýêõ$·î¬«cåJiø0µüBô[ õwFÁ(ý¢zðàU>>ú“¶[¬:¦t·U”�ü¼Ër*Or Àñ¤Ö‚Fžîà<Ã,ÿ€, µ5XÀžHHû­ÁY"?š1 aždžÕkx×?½¬õ m¡Œ2ØO‚„´°ù#ŸÆ."Þ–êŸný¦/»—y<�0Ömô¸^X^¸ ?Ç¢^¼6R ë>„Bl+öN˜�\õÕk=rœ™x5¦ŸÙtk1�=“MŽaÅ�ÞBÛëèþ<™­‡¨eâmhÚx—~š^¢;7¤«ÜtàYq¯f.ãvÙK=ˆìR'La�Ø’>.}™ܶ —1š*¬M­Ù�T²Tükç�Ÿý^³�ùàb-u#Jü ÕÉ@N>?yê^~zS¨ö¾ ©)]ý¥Ðœô™+4�BtmL4!-Ñ|sQ—¹ìÉìrÇZþ¨+¦`8*<6ÈTÅýœªßó%>Õ²,´¯'BÞ6&·ð[qÕuYÞ_wYTdŸßÀß gV•Ê&et¨ÕP~0OÃ\oµŒЍ`2Ì‘âËuË£,)ÈïÎÚÀgž’Sr”é ÄhTb¶L…µ�b’z4t,4k‹M1`"2+uIŸT)_"¨|Ê�[³äö3;Åï%³œ_ßË24°)ÎÁS+ìƒèc&¸ŸgL+y„m+P9Mœ4gZ© <;Abùv|9FLF†Ùö óªW]wÇ÷êµ·Ø3weüKdÁRm}û>§’‘@]ñ¾,�E+EŠ’=i:Ã,!S2U9 æ.Ù>{ý ;Ü\z/ïkðE Dc€bŽÉžWæ "lÖh‰Wˆ³5üˆàt·hcÅI;c]]ed¦`34¶Â�]‹,Îq¤hçÔñ‘cgìQ.*D˜Ô#¦ƒm;ñ Ÿç7˜…6}‚; `ýAIF(%l'÷%™/û‘MLãÃWÁ4ì}Ó¨a¤ñwNU XADyÑÿþÿÑ�qt—÷§(RV!’&›‹ cbÙ@%Yìâz-³²Ûp§…Ÿý¦ðW½¿¹[]ÉmW¿»ƒ ÀÿyÃÔ©”•Ø0G¡Y"–¶‰×g²„`?\Û,ÀæÎ `•ÄïøW�O²â£.m{¼-‡)¸äýÔÄE „Ý-´ÞjÍTµ¢Ú>Õ.E»ó3”œ�¼ÈÔȾ4fQ®¦d®ì 퇕à &¢å»Ð/ò °Îw°AbqŒHËÁð@_Ä \7ÝÚîžnÐ\doA_¿ªÊz¼9ÌÔäd=!Sa¨,ÜÁÌR†|2,÷Åü8» ƒ ‘‚/ ¸Š ÚÉ3œîüG‰t¯RCž2ëÁ5g:žÁ•ä‹�ÿÈ¥9a÷8Ú‘×}[bw¹ÖÎÿ’Ñ�J§Ú”ªBêƒç±½Ïu8ÙÔ!Xáô�N w§µk qék¢ÃT�ë Þn v �E`k ï� ÕÅGþìr)‰^"ªàþ:lBËŽ$~ Y¯(‡+.rÏÀ“À`a¸v•Ÿ†£WR¨Q©Î ”ÀžžuKß—¦DþÆ{â•xÌÛ¸ìäi ¿ßã››ŽÝEÈÂ4“¤GÉ‹h³¶.TSi›~óá]‹d‘ÿÚÿåžã‰mu¡ÙÚãÉB`™ÏÁWo§»’ðìyH�C�Æ™h3žÑ)CåYá8ðÐlò/ÑøÌ ©øÕï7–x·—\� C}>�ìèh¢�èðÕä[Ì%';1Óèï �zÄ‹�qxFbp¢�%rĵ¸f[¢÷º3֧޶.ŠŸ¸Û™V-ÊQÆ©‘¾:ÀÛ#‡^qñ)È FLÇ;u šE>ú�^#@�bi #ØW·jx¡Þ¶{'CXƒìuý˜ñy¤�ɰ…ˆF¦ZË%†2ŽÂú#4Ÿ²tWܤ�-ƨ—×¶'qÎhŸîÇ�‡“5Oá*1Ð3QCêgÍ4dfàîïÒvì&}Xµø³04 _Ž,Ñz>uK2‡M&ºcÛ´õÇÒí�€Ð™Á͈RÀ”ÚjuUç÷ÓìµÈæxÞ�(„]ºáîç›RšôEáêNààl[ËóíÙ†íhQ¶Ae6UNŒ}Ì!Äït°‹³Ä>“Kk"aù•ºO±µÙœ+†A8�î—'ÅöŒö{)‰ªdä‡/½Þ1³ Bî`HŒâøïê©86Ín F;¥ñßåO5†ƒMç¹­“Ýü�>´M(ôÁ_Öyç†ÊMoðîï7!DëœîeÏÌ2‚V)tUß< =¶O;áLUx†d¬‚´ŠfBÉ଒îÀ½žw"t~ïûà°‰äõÛ÷‚Z·©Y#Nf.ëx´/" YǼÊiYvspZÔ¼‚ãÈúŸ&)õ6i”‡ÙÕ–åÈ›�àT™¸ÍË7íª7Ž¢­Ð3 ‚�•4$BçBÂŽŽÛ%i\kl(ˆM¥á7« 8[Z6Ú+9 øxQÀ¸U¦¯.)–s+uâÿÔúá5½6k¦!<­–›²UËõû ÕÖ�·ÁæSyŸ4¿{0¿V@�ÒÛé 7Kwlî—›ºåƒÌë™[½I4¥“úæÜS1çÔÇ jnEêˆëÈ¥ uÐP�垤óc›²Ùÿ‡62éÐ.’†u/¼!ë›ì¼¹K°žŽ¨Ó8)ÿî/fø¿6±/¯qŒÆàÙoøÓ^J•—‡³[,Ï+nsߨ) e~: {»$‹à§<Ì(=šå_í~�©X¸šêd'~Åß6¹;Ë£j¢ï!DþJ²Uë©åˆ-5ú¸h 6BôØ@ÊÈ!þÆÄÖ°!Çxu¦äçØÙýr^“f“Y$¼Uw`›£z¤"sé-„î3‚_÷SC—lzþ¼W®?|Döð’³’5;¹Eý~Ö ¾Jë�ô? s– ,Ï€aþ±%Øk²è®M§±6®4æéNúÈ€vˆ2Ê•L .SjМbüTœõ1ý¡n¹TÍÀ‡JL{L£ÃÃÿÅÇnHìò*�EgÐ~ì)õ¢WÎÈ*þÕáìņ©R×4¡é½ÀŸ¨Ü¹>ëËMä‚•w–‡ 8=ÇîÞnŸ³et̆;lÃ.´&>á±ÕÏ2¿ï‰v6º ‘†æ±Å’&ƒõ£g À‡_žntx¢InR p,ÐàÚs“EK=û>ýQU&û�æ¹ D ô¬[ámu·Hɽì ÝÈø[×*s©· ¬—/A uu¨3–“SF§ø‘´s�‚ê$Æ€ñÎóf S뤎˜ó¾…;­ÕÓÈÉ!‘¤$;ðVÃ{³f²&dz¼˜'2¾Í@o–ö>wº=�ð�yth°'º$‘ep,c.Í�oFœ[ ¡S�ôj²�Ö›ÎÓZÞ°Á{M)ë5|Û.ºxßÝ ¢äl†¦Æ%ÿѤ”v½vÑfw´ l`“b�kê)Kã’§‚Å 3Î{†©w³ÂÖT¥�@*'f h�•ÿÙÆã‘wùÎÏÞ‹k(ÊõZïÿgm¤ �&)Qaî{Hö=Õàtqª"„P`8Ò®Á€ð±põ.ÿzÞ ·¨ÆŠwÚ~�(šd‘ðÓÊqf¦ŽëÎyÎðì8C�´V+Âyƒÿhhb‡‰jvѹɮ¶kÖ…"ÆxT—úa°šˆX'ö nLþ€†RÀaýè„욤G›é8c!•ýl0ˆAé1ŽVç?¸?Õ¾¨³Ðdyf+7ƒ®¤ IÛô1NÜÖâF¶ßﯫÛ"B !ÿÄÉÖâÉ¥½+�Ë�Y ±�6:ÛA›Ü-‰ YO©@cM"’·\áoÜ@j¡hÿ2Q­�Ø<~Ôr Üõe¹-=HP!�>3iO߸/Õ–áÊωì'cÉåYçD|¬ã+²$®%[€Ï’vÍ î¡òç¾*«A¡VÁ65ùz>P';Ô�,þò³*‰É í\mJsž’÷WÚþŒ¾ù­a­�ËÈv+Í'eißcÔøRÅ b[�¢4ÃA,€?Õw·ËæÑrò~æ—W�Àáq¦7ƒNk4+С”!©VÄ’íE¸¸õ-²0"ň\ø*hVMGLép錬ʌüøyAxÁ :§nZ©�É P0° §®ß{FÞÕ)%~lì4­ã7l úi{Àßñ‘‡Íà'v¼iEÎBføvÇšº;ßbHM¿¯T²,25õ°�£nGœlå²dÙÜŽE³Ö‚ >ëoÐŒ…jé@^ÐÊ’ÂáÅé°�?À!‚¨ë9Q.*®‡›Ö§˜"ÄÃù�Ÿ�Æ-tAŠÖtýÃH¸ŒßÕ%RÅ¿2²­[€´ŸT´Æ ò…wôí|AŸ!d”dL'ÿ Ú3>:³ §€qÒ*ªe‹w2^® »þ4xàß"NIc‰ßžƒhœ'Eà øÅk¬!å…jjÄ ò+ùiç ¿&HTt\×Y81L©{´Ý/T/ici1Ÿ­ŽÜÅ_<`uQ—»�F…©³dεà)bÓ*‹Íˆ‹Á’Dšg€ýÑf}YZZi–ÑÌ­`gKö‡5ò&M¼Ù9�7peÖ/wŒ‚Î;Cõ/÷]ÓíÀÛS1wPz,ÿ©ãÉ…qwdÏ  Q[$ÎmC›ÿxC;p¡Äl¨üì~…²Ï€°â©u¼ï^ {7¨ ÃÜkSJæßZåZzn@8@+ago§ø—–¦k|,w9�TLO[„…_\ÞÎV¦t$:ØÞt£À?Þ²6r)N4q¶DE]ýÿñ5Gß—‘ÄM —ˆN‚’¡h"ÐGM×Èzòª›³:>€ ;;#îãÈ`I…˜—Fḣ@à Px-h†ÏX`uArª‹ÒcµÏTìê�•8¦¶&þu­¸Æ¢íkWU%ý!!z>bQ‚†£#†Ð'‰¸&²8S^‰äM�\ td-R ®¸Ë©\ sÐnp¬ô@"H»<±ÂbõôÛÐÛVŒíÚYq èŽ(L�>*ÎH�øæ#V�;#/ö\7¡â_RüÍí\PŸ3ôä;œ8§@—®M¹èŽ '*„ �¯o@ƒÏïèVŽÚc{ çsææ§Š þó u{}ö¹C×ÛW^g`cX2±í;’írH 1 ä‚kÁðp™RóñÌ×W8@)Ÿ@iÿ Ô@´@}Ö©–-ˆ#l‰¶‘¬¬¤CPn)½óRP塦}0Àl¨¬HiLT’¾ÇØ|ÔÈ A„\³�XR¬„é.¢z‰3êìÉM’G™ÎnŠõô|>ë'9n£"�јÞ]"C0Þö/Œeë$ §A÷ëÞ«DRl sv ]ë}L˜ÃžCÆ’\šußý±Kc8£¼0ÿ �È‘öúЬº@€DxY8–®]s¶B\•5ÀH ;-ÛÂ�R´TM…j{lä.^>ë#»¡-IÄß{0ï„H�ʧ½¶(‡uâhƒ¤ß�¹Ž¸ñ¶|Œ¼Ø�¡bÎÝ~øZ´½UOG€÷mð9#hóÓ wá9’n?‡z~& .ö^5F2ÅP$ˆ«FŸBnGÿ™îkŽjùUÍT ØmR%?ÇÕöñ®ü Á…DcDº¡6~ø=¡øP§˜ëgtÙÁíÑ¿$š�Þ Ë+úSµå"É$¿ ·NÛýÓ(ã4!~]_Âh|vü•Ýxù´`¿F")Ù© vÛŠ3¦‰a "™ �ïáÁ\Å€‰s9THÿ -2î4Ø1j[‘Ȩ`órH4‡g9^œƒOZBùdÑËÇ2óîç‰ò·«pÍÿ¦^·—yLsžô}£ðí.1u¢‘‡ë°|ßË0_¦ uV7/uóàY´w?*«X¥Èß7®„šÆŽË�—Fw%õ•¾ãZbtˆäÚË2»5�dµ°ðý"âUã�òs+ÖtaÁ˜…äÞ÷‰µ Ø6Teì�{ÝO^ºZ§ÀÖ;Ñ’™ ±µRéÐ2t¸‰’SÒTFüòà:ŸûÝÔâ$Éâ·ZÅ2Uj„ÂAÓÄõ~|c᩸xËšNY¤c2Ú4Ÿm ÊýŠÚ ƒÝØ fUîcHUvù‹x×™«Ü倘¤›·Sÿ$ø�9þmÅ +þfâ ëOÞ ¼ú¯°¢¦P·â+;:°åÕ6í}1r¨0É¡ÑJw–?ɧ¹(o*æoŽwVzKû'Ê/�NÔº¾Ü_Á'ªj�r`[~zYì%SdÌý�¯Ýs-ÔºC>J›Œ÷ìžN 6Kë¾8q%,`=(OÝ¥èƒÄY’ÕòeFŠç´J’Ÿ|†£ÿ­ÄF?²ç°4m´7bXèáâx�ÏQªCžó®r‚¦¼IÁa_k °Ld‚›šxîÀe¡h§|†^Þ�é,¦·×PU/$F-{ã�g]l±køÈJÝàü K¢D†¹o[Ü ¢�¾DÇõÎö«ëŽ ïÔñ繊º˜(˜ ŠØÎh¿­2Ij.a/i™5|µˆÁµázÕ²oÿG8vTš,ج«ð /˜×¡´g@å�Ô¤ü˜QCJáQpalð=ßèéMÓŽ`w­,2@83Á‰)5“!÷ðÂ’$ó8 =î&ÐsêÄò™c«úD‰20Ì «^'`lX#�Naºh)ˆÒæ­º5~Œè’KûÍ2lóǼ¤‡åº.ÜsPé¤|±•oap›f…€â¦•é °|ù;�î¡yõ–0CŸyîŒMÇ /ÓÀÊ'¡„ î™Cv|G¬¾È™qƾàzɄ΢BîÛWÒÁ(t¸òå€ò‰Ír (% ÆI„?vZå}÷µÊR¦û?·4Ü`_"@-Ú½¸_é¶.–ýQ‚ñ´­ãÖ—ëo] E’¬Ek\-üG)àݥƈ/ȱýêXWXz e¦øò†ççuº¸ÆüN@÷ç‰yJ|ÙºÁ0þòtý©ìŒ§„”ÜÍ€þ°Z™’Å‚??^Žˆ€É&ÒDéÃä=£vf»Jvå«°ù ÓŸ^KÖ#ï_Òe8èÞ«¾fx–aÖÐ0F>£Öpž èó w ‹šwHäÀÁ:T� —CÏëBØN,Ö×iU3x²Í°Oë2™Ïñ›�¥mÏõ®É1MXx\у"pB{úÁ˃Â/ž‰k•ÉC4™#´+ŽÊ² ™IÐè.¾°´<&õ(W±dhAt=ŒÝºëêžôã/[`×cí�qT±Æ¶p&ðÅyµGÒÕbAÿBdrõeìê'dV=¹#5t‘j+*¼ªønÝÙMýMû†â«£}�@°›kz:ßùKÙúÂû†— yHÓÌ{`¥K’Zè·rµ¯ç�Ç�ku‰±¡rÙúÔ¹>"I"¼Z«}ô«ê ©iyÞôa“-¯ëg¦W›�û¥npaêwqöJúù$À !kª¾¬®kL0‘},:ÊøŒŒ.M$lÖ QØ 8-b¶·ê×�šÐ¡ÿ¬2øUÕ(Bæ}ô3×¥àD­~IÐ+ÛI±@Ç7ðÌ „átøD÷üÆ9÷š@‘ÉÆgAÈÚäáV”W+ÑKzÈÍyì�•ƒÚŸh@¯½L_iÄòÇÃnD'#;8ƒØ™¸ï�+t;�/ö÷"û¨nÂô%æi `‰bæ¡ÿSõÄœ¹M ¡óœ/ØpÚ]Íg K­¯U~ô‹·¡®FÕã€áRxûiìs¬¼5 êútòŸT×�…»ë¤èͬèdNÞÎßâÐ"^>Rn²>¬Qš$qߪkN©]m#Ää9÷N‰æBáb‚Ý‹–ÀY‰\zéB¹ÆÊ4ù«›ñëqC@X*E¸oJkíaÓ.vã%qO–8H&ãC‚¨˜W°K®“3(Œ\IØÁàNHŒ !e mó¿Rš�é©¡¿Ût7:áÙ;ÆÙÒíñåèx³Þ„FcɾnT¯ˆåò(Ô® û£³KLÝq]F|Ø¢ORdÅîÔÃ$Š©•îfWîØ�^�g½ƒYo”YIÙÏÉZw±Œž%gw¹K=*8½±µ[ì:5–�br£; ¸ ¥ìÖÞxúC˜ÌÙ¢×t¯mßøãÆÓ[“¸8ƒßlãóÿþ�IÏWm#ãÄôó®rO;â[; Oó{ �‚³@ jSgçe>œ ûñ;Já€ÿèL¡�í%Oèä¦XhoZÞalª…ÖnÑÁáw0Æ:'CìEÆ‘¶ÃÕeA(_k¬fC†:Kb­gR ))4œÃQpÏÄ\~*0�ÜýÂ1ì´²[iaj£Ñ¸-ï‹Îwû•§nk7—†¬7^ÜÆöœÄ¨+^ ŸÜ ,ï,ãØ-ïÂ#È òA›E5-©2˜ x!ÿýñ­ïÔ%’9¦ÐŠ”¿ ö‡Ù¸·[�†&,¹—S#.'ä´1­äø©°Ÿ`è•Á…†­¨$á¹Rðò‹²#Ò2¦i¼®@òù'qŽtU¼C{è˜ÀÌœ Fa³Yùýp|2{îu]¬žÜ +ù˜¡ÁŠCÁ kÙèoî=h�ȱ!è nåO72»�•†¬˜o÷å>dWáÒ LÛÛ7pÓJ\NºðH¤|›€e±•à'6ã‰:ûç¥�”†È'D½ˆÁ•E‡Oâd“ŸuÿѯmQNnçž‹š²Žþ†õ@Wå-¼`Ê…ù’ Ä!á¯Ø¨ñ%!¶Ñ�〽ì®J|{‰~Vœ¸)Œ¦O¤ Äž�H¶@zÉ`·û¬‡�ö$'0ß‹J’‚Áû¥XNW¼ÜK]%6Á)á8Ùû³5wøäÛMºû)sÔ¬ÙaX_h¨‰’ÆH¡‹ð®ˆ¯WAi±ì(çÕÍæG J˪®ž.·Ë€õ!g5RÂe%×m@‡7QdÉtâ§±©\3_'×R �+q—•ÊðGæX;¯Üy W:ò£tVÅ"¦^u ñÚõærÅ£·”†QìWák/u­ôÆû0CôÙèQAÍðæ+i­¼‰Ç>LÔ!µIjæ½(98–Øžg!�;4•[â�xƒ: Kÿ5Ü:Òm&ÿwDüÕæç,`ƒ‡j±°¾­è7;ßÑe'Y²1rÞ—!ryyÃÌðlÔÁǤdò7K†kãy¿¹ß�‡º*óÅ^Š9Ô÷Û÷u[5Ó1úQ-YYHË;b9z®@_ÚõXMý‹] S÷_†/åÎpÓ´°¹Óý¸àJ7*€oò}¶\Ð\]�ABqç�xõº¿õ,ÁÈ+×Q‰<¥àùR¿=™}¬îùˆ'%!_iõ¸›_Ùþ¤ @=í¼—Ho‘ÊWÖ\ëXaLÀ›*ëÚ\¹¨ñ‘ò´ÂéC„ qÒ£½K›Â,*õkê¬l\{ÑŠŒ:j°øÇÇ{-·éïºlÉ»�Y\âßTð•.(•Çéö9Áu�JXc?p æz抴¨Xi¢Èçò=ã M\á”é/#Yg3àÍP=æh1‹áÌïK_áÏÛC­åNQ Eäªý r"š�¢.'BÃ@ä7%3,Ëà–µÓ>íБQWb>ƒõ/ä`±e!Ó�ìZœœ¦û}�¿Åž›Á¦B†7ÙÒ rK�qjãP“éðãRé%Õ|@Hk‹3žãÝ„¶b‹A ˜9¯¾ÓJzq5|ÝV yT€MØ»Ú<-ÐP{»#TI×NϳZ+S/¡À¿ùv C^ˆ(FìÓFo�+ψcìc|“Ìq^÷^¥ÔA@A÷:M\w‚„qäÏž:Étˆ/[eó§}…2¥÷Q2˜3Y1f–D npï®ZlÁ3¤Ã´a“X¦XùMߺ* …wMðCÕê4ÄXâøà—�u%ùW+ñ•?À S®ÖˆÞ’h`CÆ žé¸Òëî?SO W�Ï74»S’CƒF‡‹Cøù›U¼›]ï0ŒV Ó£jy¯û“- fW2Ž›g£³@›�ö]0< G‡>ß1£n”í�Æâ"æŸÇ*4jh=ÑèOÌŠR³+Ï©œ×m°åÕŒ•fåQïµT•XñÉíˆôµdyåæH»/Pï%L‡öB ¼W.ñ|¼À>é[óQ(ùbCE: ¥ÖÕïÜÑ4C0_uno"˨>,�¢4àÛ€0nÌÓái¤Û<+^/8ÃÂðÃoDêÍ­%UÆ“µÝHþ æs¼àåïé#V¦Ù³ùÉm_ï4…^Ú6t†á»4{ª2oBަ/Ü8Û’"äF |tKÃ3¶Û#*­àgxOYM`d§w˜UZÒâ?“ÅoÀ/Ń_UXnbŸ§‘c#r©Ü²tQEŽsüW9 ¡˜VÙyŠÒNÓØ‰Ñê( É ¯3vv¯p-Ì;/” ©f¼ æ|J+Uô4H¿HÇ-†»#¿2a™r~Ø›‘à!’•)¯·8ª;¶%Û0µÁè´óCùJ|ÂØ[Æóÿ²êP�¨W²p& 3Û[’[¼âeõµ¼�{TGNóO¦?Æò�“»$:ôuwGTq~¡n©Jó�ôÀñfV-:�E'ÝuSÿ�÷N¼ˆ›ZKbó\lú�œÝ( :P`ðÑ£Õ‰—öÙ]‡l­é¬çRÞ°�+óú(»-›Î,ÁGì$f'3ަJzVd޳Ûf×õç nê÷ÇWÍc)SbUû61mÞ÷ò³hˆ¶· Òܹs„üãâOqvÿùµ¼‘‚GT« ÎëUd¯1©à¨OQ³Åž?li#Ñ'´6Í“4§Ë#Ç7éR�ý&ÔæšbÍ*èR›š+Ø,*;Œ?“ˆ¤¹©;wm<¹ô£w>N0ŸýÚ (…>ü›#Z@®ýç®óØÔXŠôúÁ\*¨œˆ™CÎ=Þç¡e™bÿ¸£>Ó`¯u[ o»YÒÝú¹â_eÖç«#*…XM0Ó’'�”¢ÚÚñǃsÈæIŠ÷׃[î3qX @‚ÀžÉ÷pGÿǵ¯¡&ùOiª�IâþMtG•7+ÿ2ö¸îBú9 =ãzÕ-c¥ßÞÔHWCÒÞÊÅ0âmÇáìÿ•sñqà}i<‡cnEaZäÝé˜}aSû´=ͦóžr”e09 ù–I¨ ÷<& Ÿk• fÝs½”h•fqÊ”öT¨ä–oèxNrtµ6V ï?&àó…%i)ñXâb°ñSÜ&\ÌçÜøŽÏ=ðß].¯°ó[áûó¯`jÆ\Ž<ôÑSÉgfN&�{l�²LLV%z‹´ì ¸—LvYqJU=9÷ÓVÞ³7ûcZ�i–W Ú$h4rbíq�C‡'ê¹e¤Ì´§(¼Ðªbš9äßfʤÂ*Aðœ<øøiJLŠ%®ÏXyç-•êìöFb…P4Ú!Åöùˉçµ`Uݹ~]�îðÄSRJ6í|íŸá™ U¬¦UVeÿnw‡7{òZ9[´¾=d=1E€Îd)Ôt·³Íb·¾#¾×Ý®¤ ™��Ï`‰Té™¨× ÿtÙûü›]•ƒêtÕ[B›q¦*°'c.ó;Glì^!©�p±•õ6® Éiì àªòäñ¥“#u[ÍXyS*Ç5Ó‘™é–POçG&O]yÔ‡§’ÀH¡Û Ø¢ »E�WŸKÂ1kIM?ZÔ¾g½RµxÕ«�Y�¡¡pb �lQ÷>'U0Q%ÿ55ZŒY¹‘´åRlR›€îîàÛ^ô¹Åiåß2­�ß*ƒ·<8¨ãà jë"fþFyGI@woÑ·½Égú Hžîq€Dfò Åx2XÚrJÅÎx~x¨QW9bê_òúhJšï%´å €–¿åãRN,J@#Å2ÞDGY °Y«­Vº‰Õ�÷;Hø$X°ÉØÛ ý8Þgbf×ÒIzüõAA¼¬‚ÐI+t yúçó¸CÃêäeF’ ;“Cr…óx>”¦~v™ZÙd§mý[wÆ byõ¾(ÃØI]Ò»èåLläÏÂ7uúŽê Ef�Íqé{{.RãI £X·—>×ÕÊu¾ðƒã�€/ºÐ‘ÛŸdnGÿ"œÞ{{*ûWhF·Ó÷IÎhËþÎr³ÀmXw�8Q ׳“�4%„ÅÚ�q‚Ó3ñëRu‡¦ž>GÔŸî_Ÿœ¼hbÅjqN %V6'nà%Œý\`È¥*ALÁ�Þ‡Þµ*൹³ì0â®> b;ÒCÃk ^€oÑ-ð8¼‚<˜´YjÛ(�òÓ™Ê*,‚Âdª‘¢29g`ºò=g ¯Ïôñ³žß…2µÀ’®Fz•¦zSõ4Tk9Á¿Ø®àn§ ŠIxJU‰ …ÑÕC|óKˆ¹£s”Õ¦ðØqD~ÅQ7WÇ`8ÒcÝRF0w)¸Ÿ×‰˜¬Rq&ÈÆÌ6Ó—øù’lM0ÁªÅð¬Òó=¸á&1ɳ¡vÙë-Ö7b�ØAu°f¼5�~ QÏ>äV4Ž;êî¦æ‰ûñÍÿyÏÐ�šµz8WT󈺾+^@²QÃã§¼9¢neÒï ÿTò<5lMÚŸ½ Ä™ ~zýéOm•ùWë ñrhCŒ�¤Ø‘²¡&É¥õÔQà³í�NC\¹OGû»7ñËšuÜìçpaî#?æZ ÆÀa,Ž•ˆÇáÏ7iu�™‰ Á–#¼½ÝÛH®øo‘´Í±Y\±¹L’_2ÙÂöEú1ÉÌ<ç&ý‹ËÔ°‘ú%HŒ×§Ýmm b‚§ƒ¸‡DÞwHû.‘ý ON~¡“¹ «;¹§…É•h°ÏTH[\½Ú†2s&ó³ÚˆŒ’(5ºÁüæ6æ­­Â+Ç«‹�áÛ~65R@ µ�kš¦0íˆGÅ÷:6-«'£ðXûM>–Yc¸[£rúKðàL•á;Ë)1Ø %ÔVp”óçj=çc˜yGú~÷ÇB*ôþ±U ”Å óÒéšèzáë79¹r6Åîï�V2ÿtÂL¨UîfÈ5`øÇÿ©[?ö BQD¢�š¦Õ`éª1I.û7­i“;럻uÏ¢1ïãÁüÍåù°û ®’Gew£¾Ìa`ü”/‘z_œž.¤åjÁo3¤p`ÌRqÞê#åu¨Ý©¬ºÔÎfïFÑÕ²ŸÎwµì ð’b±¼mÐØ~uX¥ûñhKè‘) JâU¨Ôù€Ö%(H d2³ORú„/Ý> V:4ôšZ}p§ë§Cìü»”+@!Á³ÔžÇ”±öá=«õ]¾9$6­ßÝŽod·ú/¾¯dL¤3î€)÷AÞZ¹7”aq#É)C-éªæ— ùª�NŸ Ô+4°ö‰AåÖÐ"œÓò³Ò2ø&.N:ÞÙ"U^«FÜìøaš¦ëôùEéKäzƸ* è+ gíØ‘°6×õªÕn2`ž]Ø¿95‹T9„ʱfü6‡ý¨�NnˆUŽÈFš/‘ÖUáù¤XƒÎÉj±gþð–Ö…�¢We‘Xáó_3øhû[bæhíïwÔq%m¢Q»õã6­ Wa¶—Z€FcĘ̂^A¤7Ê7¢ XcS'Ù£}Ä>¿­µß\Ïøýn¼îR ðÅU–¬Â¤êFjî³lÒ±O›œ²‡‰Ï†ƒ=bL‡Í�J/¤ÈZŒ‚�5ƒ§‰ üX:=‡¹yÄ F!40 ùß‹KßZË8ÉÃð3B‡Ì/]wy‰Ó>ÂŒ× †œ“ò-樷€‹ôÄmBS™‡P<ÃÀ”rÁ¢ÞKì^›¢ÒÕ`Š\¤‹HÑšþ¥�ÿ#IWê»JÉeGóì3‡9ݲÝD: ÁÞ67&XAÚ®Äï¥ É˜¢àÚ¿þp–ÅBÌF�[~„MŽw†Gl^ÄØˆÙ2N׫ õ[ú²°$ ºûFlÇ¥ÜÑ=_©*Ë#d[Áy ^É]$Ñ:9e…³‡P<É´¯K”\MJXwêŶ×4ÞA›h°©7z!rQqL+ÜŸ|ïéËÌð¿ýlÊÂÑ–¹¸¢»¯/9FT;(Û�h´¼w8þqÕAáÔ>¤Û„CvpÒ£ÀNEÝšê©™�/vÌõÄ?Ì›jhŸnàðÞãex5ºQ“ÙKD ]9Æ÷“´þ�¡Ša�¡ÛÃ÷’?t Ra£o'™8èÁÙpÉB“'<Å‚s^Hûå¯÷–¨ž{o” Ì…R¿ˆeŒt‡“$9ù47Ì?�ÓªVF˜-JÂ^)/ÃJUªì¿©y?W¹†yq£bÌ�×í�À ¸¥ö§g½>oXÄa¼u:KgžQà–\D£Ç)³i|¡}ILU=òÔ:/v£Å£å¶Öw¿Ç’žnˆJM8ßåé¯ÚHW×ûÂQb«àÈ'”éb’ùpi?6çµTœŠ�óU�¿ šÈ—œj:k#‹åY1;Kkëììy1D�Žð¹T�y÷……k×é)*…°PyÜâ+Nqb¼¢RÕ¥²´R¢>ÚDD“]Ï ›ˆ.AêYÆø9œ%xÆGÛÇ#­Û„ºà/—×ìݱöê|°¸»¡;þ�Lš#B(–àüd„'º"A mÔ§_ ‘î‡#‹KᎨ·�lOnÄg ?©î"xQ¤-C œ`©FÂ{§T�K<ùŽÛFÐó_¬fÈÇãØèí�S¯ ’ØHêÅ}L1­} o§£jªåGÊBᆷȔ¤WØ€Êåp™q ûÃF5B³ú팢ª‚2ÞL#kºdÿªM�±“ÖsûWÜG$°²·fØ+¥ò‡Ë�º˜{+a¶7÷›|ƒ¤VxÄ&¼®þj\-Ï¥žykÔ­–½iº½>ò¦©&Èþ ƒ;˜« ¿øt~~ÔV„“N¹‰X *?§|¼a¬9M>ê v†Ô Ԣľ>¿œ¼ü‘t*»'÷v¼:äLvÊ—Y�=Ô"�†–ÐXE9õëˆ7׫5'«‹kKµ3÷»ã9¸R`°}‘­ñ’]Sb[ õÒV¥èÚ]2„Êr„ˆ”Ô½ŠÀ¨ÎDUÇ| I˜Î^¥¬ § ’°PÇ6ro"v/‡ÃÅœ¹H×5BÍMÇo”Y>ÝvÆ ^Þ ^6OîSØV5gL7™ß%<½µ— }HfäÝ~F¬Ç¬®üY¢�ìâ§ÃÿÀÒK^ûçOPÜLÍÝV¡µSÄ7Ž(i›‰ë¬¤™‡o”D ¤ÙX½#Õ<ûã<ó uz&÷`ºÆ�Í·¸ÓÈúÖ§ÆÄ'ÇÜá%ð"�M˜ÔBsßÅoçºáýÈéäº>ÈÏ\Ì�̮éÙ@àYØI'\ ¬©¥ÒºÎ‹ëª]cPsùè`P%ëZí¶ªìáãê¨Ü*Ä–_íÚ…ÇuK ÙV"—Á¯˜¿õ�¨�M.!zÉ4¢�oÓ@“ OðSƧfTPˆø(›äÇœ‚´‡\ç«Ú�©.ð`‘ÌAâÁ}.+`j*&5kÔÕ�ñÚ­ªZ!Mw,øf¦Oaït©Öõó3Îãá­ä¦·@د¹Cð·ÂÐX.:Õ1j¼£¼Æ±öÁ•ÚM‹�{óüû‘é…wXIÝQ´yïž+8¿NZמIU/[™�§V,›Ë½'-“Îö•»Ôeà{Rh«cöÏ?h…�$Ðt”E9p­êÊæÞNÕûŽZCØþ‰Ñ åö‚9‰eJÍ–‡ªAþµðÐÐéë­gß@?{ø9¶.ž£»çnöB!G¾>`u&„a¼ªJ +¯»)ˆ ¬cƒ™”N‘:ˌȴ§U–¸ÊÌU°—á½À$¦[€9R�uHÆQâ'ò6‘ÓìûuøŸâSó=µþ«‚§)ÍJ‰d:O#-ëˆJyÊ{š€g»A¯¨h2*/Ó»ð‡P©$ÿެi;¯6 `çÒ2œ)w…Â<Åî$èÒ×¥ú¢âæ(Òí^êõº³Í=‡„øŠ»ÙÚiÛ™_FÓGau¿ö îF¦<~ –Ñ(¬žÌ9ãꊇ[ÕÒ”„ßúbõ´Ï-@è n�°ð³¼ÈLåæS²?¨&,—úÀ™Ê¢ìö*Æ 4<\ðõá%Zj_Ëð¹rÝ™cà,% •I¼]}`Ô¸l‹Ê&íºçœ,�¶35]€ª­ýì¹Q3|:E>Úâ€kÐ|íqëvšô‚|¸7ÔŒÝÿÎ÷u\ø”ÿ'— ÝH‚�ö1*+÷<žiÙ zF }d ZjvÝÅZ!š¿ðY™�8ÝH�•|ö ¼I ¤üG<¡gÐáVÏÄšxËwÚžç!XeA¯Ó*™ø1.Zy/i½�lBܦªÛ>„ª«5pZä¬6ÒÅž¸ác5$Љ-§]O[à¡ã.w îHo†-�€tFÇH“Ay×SØU¸`FáðÑjý{¤êb°Ægä>ÔeÆî](¾Ò<’ŽÔÝA)ó9¦õLÍ%(L XÜŽó<¨­çE£5UÖB°†|+i†dçä;–cKÿ@1[Ùþáƒw4ÂŒ®Zù„ÎL–¡ˆÎ<Û7]>Ô;{›�@I`†ë'•ƤµIƒj>·Úݤ‚ «îý©�*s�ðBq<Ü1Žo,PÙÖáðNô9ÖÂæÛ�ÌrM|²�-ßS�ëþz4í¢Ðt1@é>¨@`<�#‘ÍbPRÙ–”Äš+Ï9Z/$¹BÜNÒü΋,1 ²‘æ‰B`Nvªž÷ˆç{MOù=Ì¡ i¶i½‡KX `{Æiø²9Ï�;ðë‰÷ƒÂëÝÚ[nÒP?ª€kœp­cSÐõ¥1ÆÐê§¡ÓÎ<ãÒñä‘€f>G¢¼4…»l“Cë]�ÿïÅN+ÀQJUhØ+Ìuà¦û¡Êdž}®•{Ò¥Ø/†Ä—ݵ‹Ó!¯ûž¼Ñ“ÆJy OåMȬÄ'€d�€ ®Â¯ºÖ-¾š/^MóËÌ»¨�&Ê�ûè€ÒQušhîh²N&×õ–Dˆ¬SpŽý}‹‰Y9¿:ƒà©Š�e9U¤;£l³ëo/´á=ánO¬LÊ̳tñjÜ¿“_gÿÚ-�w’÷ò™=¤Ï™»ÓR™va�Óey•&0Ú¢:¶vÕ\æ(9‚T~�y²¶zQû¡˜j¢Ð›.ÏðžÖ»| ¶QËÐØmW(zÂÄæÎ‡À÷Ši.ÛRÆÿ1Ö6/™�PÑ^ï A_b3²jPé»Öê‰Õ°Íüþµ“~� Ðš�ã¥Ëÿþú¿b§í\ÁRD�­¬¾¸³v¦mÙŠâQÀk!Ñï!h­«¼Úê•&œš—Zâ¼R¯™åŒ[p~ Ò�–išÔ˜m¯Ð½=í»šŽ»âæµLz%¶‡õ^ö�ãåä\¤¼k£ÆDÀ  p{"°¦C$�Ï}Ø®a©¼'ñW#ÚP±é¿Æå|« gQ¿e¸êâ^pþÞhïÆ�’½~ûôŒ’Ó*~xyÈ÷¿&fN‘�ýëo 0)ãƒ´Ž‡øí_ö,ÏópDa ÀCLÍ-Ýÿºw“j¹¦©Õz0à]µÿvc¤G07 }ǘð�ŸâBŸôö<'_¨÷žk�Eú é©6ýìC„`^w�CuÕ³J1gñDl+“D)‡øÔV>%®7`¡)=Ⱦ¡àšcB-B7•“‹ñº¯ŽÔ¤Çæ˜Ä/`F¨›’Ç8 ˆ³¥¸™ÌŒÂa2Ç_,!cMÂfe+)•¡3C´‰ø•ÃÄ–;×s!�9ƒRD›å‰øàú/ÿdŸ¥C#Ñm§q Ä)1Ú(�"@ù�©+á^PÝ‹ªLd£7ãÃÊà–�Vh°ò}o�·#F`<¥RiV뇲s—â¡NH+²©4:¢_C+]?ßqÆþ¼^.{=CÒ7M‡õÌñq‰ïcÚ{‹Ê'Œw„|ÅГ¨D¼½µqïmEUk.aCvÝþW÷0y”}•¶àæÔÓb3öÙ „7­˜{ óÑ®®Kù\·ö †PÐ ñÀ)IÖ…ˆ[0\|d1&ÌPŒÃtscÜŠ“}“AQó‡ƒð^. qF‹6þÛ7qÂ,!:ªGÐlË´™¢æã|céB–³^Ýõ&� Lµg üóÂÀÎf £Jh•zë`IÈÛ™"ùß)MIùÁȤ�bO�ì#b·›å¡5'º(¹Õ -&Ë"nõ'òÝ Ï:Ô aÅàu´¬ôl2$-­ÅbÅä¾~`R‡ì¹�Ãéßsë4R)] žÀ„Ø`ì Ÿä_ªý¾»�8 kâjÛ�+= ´•8 ‡OüÏ’ð³„×-’ÿÏœ[—Œ_þl¥…K ¬pë$4'cþ½�³5y——C�Õï“ô| ùû˯?Ž‚•|¦»—ÉñÝ?£ßê�× [ÏöœÝ�ÍÈ­ùȳuñ£,Ø/\ö]×ê§û v¡9E7�&'7/ V²¶²,“:Ès¸yR�D]>$ ‚æ#v*’4üíJˆÇ§½ÞÉj\%„æ£É%?‚œˆ7^z]y°šF•æ‹ØËõ—Íð¡˜ÞÊéP™>¢…mrO›ÛGõxbðãîè-D°|´êÑì=ÁvKáë¾UXÊ8Õ˜õ…ÜMwÀƒÉ>z2‡ÿ¹Í4=¦Ä¢íVê†ýN¨D:K¤è: 3ŸžÏ½]©ø)úkò�-AÈIÔRu & ¯aÓàXDª�éš/*S×K~·QZ�Ê�¤iÞ7×5,ÝF+«¹khþׄ¬Ma˜Nñvÿ63=«ãÚÕj´‘˜÷-�’ù˦\´Õÿï=Tœ¶P¼$$Q” àƳøSmÝϳ9ìÓÙp;rûÌóŽŒvÒögóûæ[ÆI¢AsÙ-@¾nSe*i¯çf@ÙoöíëÁ%Iûèöã•vzµ·þpÄ�µ-�Ý[œ|1jï:’2À>NçÏ Y> Q)G4VdT>ðÚ*>¯_DS¥Õ‰Ê$9}QJ&ÆŽ°ÉÄÍ9 9ôÒƒ*¼û oø¥ÀßèÂCzqóv‚¶� ø:ÎïšT®€çÝ[—_*À7[3MDÎÕ.µŸž€¶BÔ›ïîx§j` òÜQÒ‚ò× ¢¾ÁŒ =­Œ‹iÃëv�ÞDïWT�)­æãGÿýrÐ�ØÙýVÆ"·ýqú÷.Ej•ñ÷�;…/h |éDî壿gÕÏ4EHûgÉjZ*rtS¥‘_™¸Ðv�Î�§§mí òÏN"¦HÝV¨ø7hMe~æK5àÁ¸Â­¯ß@>Ua àÙ`ލ�ñg:*‡é‹Â—÷‰Àh%S-N¿+×ù˵ö½^×.Þ2tµ‹~šbT‡n½Š\̼ ÊáÑ© ‹ÆO0é"êPµÙT%û £’ÑcÀ÷åt¢àfä*5ä/4ŽôTt“\©Îêy«ÆEn>8»!�Ì÷ƒÁ~Ã(Ê,Ê8‹CMTkÇݯ™rq­®$¸NðÝ2ˆ´”QÛT[ÒRŸ{ð£ÌÕ Çq| ûìþïX ÛÃh45Lw¸GPÂ$•ÝúÍ¡NvÖã¡&sM=RÑœAè ÄîÞ0Tô¨tïì‰}ˆ‚÷òÌd…ê”6»9|ØÃXe“aÍÓhñuf~ÈŽ)¬  Z4\Ëv‘îÓóø\Öˆ Jdm®×~Ù�™Ó¤Í¢Æu¸šƒ�`KëzÇ+S:۷̤“~´YU<[y Ч^¾®JŒ~v¼×eŠ}�šÌ¯ÿ$Õ…œNäûËÐ}”Lç†,Áð–ÒÚ.xáG€ 3[ß {r4´¼1b¤ÚR¹'_ß!¢y?cÓeHWóPѪÐÀ9°ôG¿0·ß0xh+œÁáºÌ‚A'49⑚åR­ä\»Dh¶» Ò-wäR$dÃÅ»G}xÏéÚpj ¡«ñ‘a€ÿôíøºr2÷!Õ¾Q^›Ó²ÔP5ÁÃ3wy¼@¼{2·¿‹XüÉ;=€Ñ.ØÞ�‰HbG´=°|µêF›¯kU^.(.þKë¡;å(Yi^ÅIèz†Kp˜ˆÀñçS \¶ÞT_(Úã—±4PÇî\ÕJ³²IåiW¦Ï>šŠ« ¼}Ýh¥�w¶B‹×Ó¹„*üܹñ“ÅÍÍC%lÍûjÉã�F)D‰c;¾“*ÐÄãâi¤¤zhÙYop�dÜPoYŽ #L_ΧÿâHKi¦*i8Ç?µÆ—u2ØÈpöqζ¿)k¦2{Žw�–¿×_ëÕõ *µ ™c==ï¶õ5Q1€†Õ#ï1VX,€…šX-chakþ°WÉ}S ÐO@8C 5%—qS5¦¢Oµt¸ðŸ¦ÀgÉ/ÎײWÈu#óïvU)œ „©UnÊ÷î�\\™\ŽŠ¦a5Š«íòWSýŠÊÓø¹=[)3·W�ó­…fr0g×giÒaµ¾Áj81/>=ë@ÏÂ~édï —p½º0Si}�LFJô ÷gõiÔlÀ_„áBHÒd¸$ZpQbXã´ûàùBý´ò4éÓÈV;_Õ”pg ªU]ÓZC7jÙï kˆtKlv€8—[ëŽØK‘,#î@m«Ô {„¡=eâ‹òÓ*yÚjøP!öhÁû¬„7_ÈÎ.odò+z¡˜“KZ�]hþÓn²‘9OŒ,�ǤnO–5Š©"ãÁ€¡¨£5™þL_Ý~ŒîyæºA± ç翟Åß+r…¸éøÍA0ìyQ>�é�ÏVúî^‹·âÝÉ¥×k»Žr;ú?þ^‹!žà_ÐãË-•Ci3ǘ*öd†,¥1Ÿ¦‡?ÐÕ0ÿ®¿µ”¤J­; üÍŠü3!�ŽU³¬žŸÁ*w?ídD�V—1Â]”»JÇê©/áÝó‹uíX€4|gg¹eUbƒKöÛ5�„+Y,Q-Ö¨¦µÿ9)^A±]{Þnl!TJÝp˽ߡ~iz¬ØËX峘õ¸;tŠŽº•‹Eoå[bsÚî9Q©×Ïú£ "²EWVڽДÄUÔ¹„’°Ç³�¼ä¥'^äJHTU¤‹´íå�Ö‡÷!¢¸ƒ�ƒí¤Ò™¦ÁÒ´]ò†n7*±™ßÑX é´œ7‡Éoâø˜›Ø7¹&PʧLâÔø3Ú Ý»„I&žóí=~S€¬¦ƒùQ̵drø’z—ùçXïåԘ̘ÝÖ¤bß¿.™wóžA.>ö(‚ºVmÀõ”š§[�-»EôÑ.ÁíÛ^$ÔÆìóa«£8ÞËyÇb3f/Eø¢´ñáÐé‹Q&àeÍ©/ÊqÉHHÄf¬†*ëL›þ…pƒš~X«à|Çßš«OŒcpš0E5Ž•oáúfy÷rçæ�â¾)eÂ÷0[¹á&±S¼Ïø=Ç*ü=¨r¤ïŸRι�Ñ”x;•»óò"Û²œ{è \Q±2BìXñT[Ð% AY1*Hrƒu� †VŒÝÚÁ‹Ìz·dKŸfÞâÙÖ16:Ðg?†ùNøÊJSTËÓo§0Ï!†ÜÉtž/‰~€�“úÇ5@c•–²q·"3…«e[æ¹c2¡\0ãáú Ñq zß’Õíœý#ñøò0þä�Ã-$ŠeßbØŒÊÙØOµBÙ·¥ØµàCVkº�-•B�2½$´ç+é¼.¨¥Ò06ko›³ 5ô9ȩݿ¼*®ÚÕ“1:_[_rïñùv „b§\)ÀÊÜvßùÞsx’fÖÅ6TmèÁÊâöQ2ì U^Ï"O0Y„R Î’÷çýp UÔV@º=ÌXïÑV–â V ; •;a_À\¶ê 7¢ïõ±¤ùa�Þ�DKÕ�¬s ý@N´Õ³–Û�äñVYo{ŒR`ƒ‡Ëá[‚yÝlt‘zÍ×#µ#w÷i ʹì÷Õ~ˆ¢†t¬ƒ(TÏjNXiÝ6æÍ$ªÏ“+¤ tXõqZ¯ô¹˜ýð×¾…ãÆäERexJXC6«èØ*�ïØÙoò ç¸ZÐ)zø$8àCàÈ ‡®Éb„¨|�/ÓxÞ^½Æ†V5óÇp«`¹ ¶ºY!Yý]YŒýñÝŃb–aáÝ:^_š²�ŸT †Q®Â:â"ܼ�X 0Ècö}AöžÝ"gzÃý±žž|“¨l2ËÄÀ ËqV”m£tÎŽƒ’ r]wØû+¯½Á95Æ�Jkd³öå ‘> ‡©Aw�F‡%@¹/Ü5ÁËÔ¬rd˜D4YO¦Y÷‡ÆK.ö…vë ÀŽÖ>déØ�õÞM&ÆÓwJ"—¥<•`ƒuB®q…-Õ±õ¡æò/ùÙi�N³¿�KD3ú¤UT þ‡8ZAAʸQ\7ý0Ã"Öby«–ÕÞ^ï™GË4{… º·j›Qj‚Šv ûñëó7Z¥ß3È,÷†B“ò]ÌXÓñyò »¼WÀeÀ§LÛ;¸=ÿ�‹Ä…ÊÑ3Jö¥JJdRÓä ׇQ*W¾\KѸýGPÁ[Þò´EÜ\®ï÷ÉŠÊìÑL±yFÀB¤æpÁ\8Äp�¯�ãªöm R³m9 Ä�—mÆ'¡óB‹¹óNÿÛG4ƒŽ.†='„›çÕ•¸Ñ�TÍ|ònëáSMåDoV¬­ Ô Hoÿˆ.%7‹R¡€“GI$ã êv¥†,µ%Ñ(­ø ªs©tôk¦uÏ!ÉÕAÜP¾ÔL!öTœeÃíQÉ4èSéeµ~†–ª"¿Yé¼ ¬Od°Ó¹àïÙ @,êõ’ͦ”P¯„4®Æáõ4�ž^*©]8 =Á’ƒk[½«¦ŸµXŸá#° ¢ÁöÄ)4 2–,_]ì£0 �?�`:¾Žë$â � Ð)<¢¼y0ù_cîK|[­Ò2 ¾TRÚ�)¬îß�tX€°YF²2Qþ/ÚQJ�IL‰µ%ZMB\=ÚtÒª±VÙ*6Î.Õ{=%&™zö´od›lGSlã¿¥ÀrUTx¼Õ# ­ôe‹ü™ÿ×þVêYÚVÇX]"˜Wÿ ¹ßPãOIò­äÃb Œ¼#cƒ|b1ᬱ<”üç›0[q ®²ôÞ`Ü.6P]\ñEç³’•œ/:Á+æÓÒÜ4-=‘wEêt¬´t£‹+Çù§aß…nÃäMkén3¸ÏëÞd‡ wy°ST?Švdõ)¹pର¡¹ª£Þ‚�0±ØR˜jV±®gv fyüBÌ+bÚûEV3Šª—dngKwán£;kɨÖ8”\ž˜ê£7†OょzŸöo„pÚ"Íùèž›ðt5õ)Ù’A¼Ë‚è÷ùÇæNê ¾¤‰s$CKÄåÅÇñÏN*ŸíNôfü1¯ÊÈ`¢º’4Ö]D�GÍËdÓ€bÝP–ø†n›6€Õ’& { šdOhÛàØˆ�àÕëpZ1‚Äp»Õêï‚™˜A¡¤áJUR2ÄI¡[Ïðo°“¼oþÒÑ59æÀ~Ÿ�I jQ—Ý"qg+Ìø…èk*ã±"ˆqéÿØ0¹—³©s�×£ {˜™µ½ôíïQgRÉeçPåùA&_A/CãjÉǨ!êåÀå_„˜¿Z¶Ä�0·è?¸Ì’Š^B]ºQW@Ð Ñ]$ z*ÝõŒSÿ„æ4OO«ôX ÙÚú¼Ù±ýnåYþ¬—u®•GÈ]‡|ÚérÅš„Z-x0_{¼àÇ·UËòqo›CÒZ1׉jv¾._[§;°|³6Ò,Ä÷è=õá�I„*[“i�#¬Ò[Ì[œá7ÂG襱E(<³çÐNHcÉKˆw ƒ¿ÉOñ3À"ÄÖ¢Yu¨ÀáÇÕùß#ƒ’^H�}Ï&�4qj•êQ, �:CöM$LN™©"6„µ€Ñ28òt1_OŸ¡”õÞ¨ºV�†xüZØ2§»|øïÝñÌPü·˜­dú#×–•:\y5lW]ô©ì¹¶žÀ —skžè”aãðUÔôZjÔš!0El¬Y”hDùx$I:ciü´—ÓøKÊ›¸SODâó�ÔP‘ü\®¦ètLOºG~ò½à…¿LôU�Ò)oÃÕ¤®ÎQ-bë¥(k_?2Ïc¨“’·Ö‰ª#¡›£áüë°£ñ•Maþ�³�Dˆø¹KÃó3ÅÙ…v¤ò«�Õ÷!E†:è´ÖoJ¦eô²ýK—ëÂáÉmW # ¡þ[Ï�„7 ¹Â”škÅÂ`v&@l_Ùš�¸ªSÈyU™cy®A„¸Zýð`j$ÛºÞ…e‹�/ÙâÑ$©ŽâÀÈ×:â «jóî³UQÔÆ.ÉôÄ;ÙaUW„hÝ"�ëÒ=Ds�ýfxWTÉïÓ€Êw&)N8DŒ%ÓÖS(EÎ ?«Ûe1»…uΦ?ƒ µÊï¯ô(EŽ&Ë¢iV­1S¡ñ? ¡@% �F!û0( ¬êÞœþ6 Å­ �h%¨ñ¨ÆSéSy³gëTĉ벤ÅYÔŽzåߪGsP²©QýÞñÝ;Ö•;¤w^€æ¨o´f<£í/fFY™¦‡«z‰Ô¬þ±H…Îüƒ—WqF¸'úzd,a|ž ¬™¼Òª¿_-HgPl—ö�³Ní îžæ¬ÉCÅçMì>´§§×¼3'_̽—_E»§CZ¬åþéÇû¸,†×SÿÚZ� ¡]Û¾ŽS˜}‚•ß!~rŠ€ü÷ ¯`ø”r’Ý” ИÔj䨗GòhÝ|š_I”‹ô~ß„ßP%BŸ8IÏû!;‹ª™ž­€°tbî»zW&z£eéc€óïž^Mõ Ld�*±›± 0+ßûç MâxkGvI$}b„“Œeÿ(=½ñtb+VÇ&P­ýcš#Ð9ÿ“,Q%Æ)Ò*ʆ�ÿ}L‹eêËÎ €Û±5+°jà½Efr§˜<‹�ïå†÷–µÌgyú{×›ôùGí�Þ8Š1øÕ¦°ÖZü%±æ¸û©Ú^Òm–ŒÜ{MÒk'³¬ †b:sB¢Dä¶‹q� -‘œ{(¹Ñ¯g3¯æwÐB*˜�r[?*.‡zÅ�É|Ç-¦¹¬ï¶.pÆJ0³‹ö‘ø1 ”F¯Ý~’+#ãcã”Ëšƒní×vŒyf-ëøOÑ¢µÚÔ~‡qÞ…²[³ûóÅv¡i£ÃÏÓ>þóúëÜC×k,�·ÛõyÝ—ÿ§´wí³Ýop0½ùÎÛ|Jœý€$ºp`V\Ÿ ½=Mæ~uQÃ@~�»�§nËaÕ°bq÷™Ú‹�¹¸·ð߉8½7¸ý€ “œ& Pº4ÇHÕÈ%"µiì‹ÏéË,Á?‚Zn±}úryçðƒîÉag:7pY ¿/ú`hÓˆ:w¦™x®¶%deN!f³Š–Sî²Iž€žÚz‘(£©ÿ’Gz6ïanB•è‘ui³^Ò7òŒA-ßN=5£$ÅÕ �ÆEÏCì˜f k (ù�”lÈfê5üÖ5j�[[ö—zÖ·›o"\ qéøSÚ 3ÊŠ™…dþ à3b}»P‚•µ=©ju1Ð�]œÄ¬å¼oöúSÝ kï)‘%Ô왺ù’ððÔË/Τ!ð"³¬¹‹?Eà¶®À›ÿÒc)ÓŽ~æ…åàô¶°„=i¾ÂéÁ(fóX;Ô_ò›Ú×Ér¯o©i,|¥­„åe!DG:�ú�‰èdc y£­@ÕŠ Ök“Ü@þ1ÑèuC^Ì3 ÑÒvv÷G™IÃðüø¢rKA<`›µë�dÁm‰[H¤XÌjï^¢z —–téd¹ú×Ú:ì[¶ì2¶·lÆUöA„O{ƒßˆŠ Ö|QÛX xè…ŽŒ½<.8á˜zFqíP”å-è72`·!b¼÷\I>2ƒ .²(è —@×?} ¨ÿ…–¥óä¥îíJ&@¸:M£XŽ´YÇvÆŽ`Lùÿ¥ÑHµÛÔ\œT 6©:îÿÙ|NPžãвTµ6(ûJäÇ…ÆE—c“â�¡_w²úÅ0;ÌXÄðVs‰ôÇ—!—!�S9 j[RR<#+ž–§¸¬ËᲄpÊAïSˆ:Œú%¢�;È/·ü¹æ¥äù�«dÝ€¨º¨¨5„º€Šàù‡¯~Ó^"’(Í�ÿpsp¶”7+®òE\Ÿ$â,$ÂaúHÓÆQ!¯JÅc 7¸$.¡Jœ£•â.Þ9 «�uæ*]ËÜeß©e漯•Üæ•<7ó­>já?<ÎAõx%‹3Mhi½X0ÇYýIPdÄx¾ ] Ÿ¨Êƒ…C- ³EÃêr_2˜¨ºb¶síWÿ€±w^q’B).µ`ùDÓ{+¤z(í×ÚúП�N@qáåm‚xR‘ü}Æ\~*�`A‹Â¢cJ{§áÉÙ÷jî3"J5ûQ™óµ_�m®ß{¡Ï ZQÆ"_9èW|Ä~y—›ÅȾÖÑÚ4 "Ñ%X†NW¾ìÞËipÚ§kÅ‹[í+—)DS’ðØB`ÐȲïÿÄ^à¼&ß¹fe]á©´· …É„ûS’™úþñÏÍøAêØØÜ>3g>:^ƒÓd90Gk‘Ó\�}´¢À5¡©ú­HO\ÂRè'“Á·é–¾ûqØž„`!FñéUhö›j„\ã:9Mi#=}=Œò" ðy†âÑÃ,¦üÔ>Æë¬ÁßH}Õ\¤ÓY>ŸWT>8}§ÈiuDucÁ¨€£k�s ¿}ŒäŠ+)<Èžæ­BøJ8)–] ûIÆ-¨¥·É¸b~5öZîÀ$2“ÔˆÖ7) ’kBë‰B„û_¹ð €E.¾k8·ƒz狌„ï”ß(.Â&A5:±¡ 1ó£pp½�Ž$ìØUd§$›ö º¤ ò.™Âóh`³ß&q?FÆÿ@št&•7ñ½g#rÜ)`À¦Û ‹~™O’$LR<‘ „XÄVÚfÓÄ7"‰Iú$ÊôÜ¡|ÿ¨±¯Êh);œC.}>÷Ú°‰ïáÚZ7³ÉÀBv·CÚf‘ñ¦×i¸"é3³W˜ò}°iËu wå¯X‰ž6ð?�´LéÖ”%öYa³zàCÊ.´ØÊJ¬ åÃÁjW�T¦ü¾J·2}°UÊ=c!a¹Îr<Óº�ùø²w#¿Ei0‰ä á§{'Ζ˜ì¤V[–¶òª${È­¥]›¥‹ Ëq̧¦Ú‹!öV%�·j3ˆgÙÉ)—‰v‡™á0OWBžà%©ÛÍ‘¾ ¢Ñ£póÖ)¤2:æY1Sð·Ÿý3³(�2h•j{ìÅÇ•ßuuU2¬zeX•S`6äMZĀ̯z¯,³àÉ:ƒ[½Ÿ)dTÕ½ßNû@Ýù=µ$¡:ø_DU&Ïyr À9Xu-L":¥(iÉ^ôöA['‡ã]ó­«Q1ä¯PP¼;¹ N¿WãlŸÀ�:"_fïSw«yNÇÞnÝâR©ñXýé ´SîP7G=´—-ãtˆ |™C‚W?Xº¶ùO¼Æç¨o—'„ª¯N6Áq�Ô»gétØÿç#×_ ®¾¤BÏeçã:ÑŠo0ÃïE^¿Æ÷D|g4؈0k�*U…¹0É.ŸêNÞ�œ9H‹&‡xuÊfÚ – 3}ö8X�‰% €·ÑÌE´…¶Ã4*x«.žhÓuÕP;jJJ�ër{)8çÕ�tÜMVd~¸(wÒ>ëm¢ «TÖØ†HzRe´EvºÊ‘¯¦ë$¼w§¥úÎçGÖh>ÓvfCZö®Ï‹e)6IåÏzæðŒ`’m…Á<œKë�îíÜÌ z¯JMIFüZû8ÄtKº¤O}Ä> �ˆRðÄ$ZÐ=õ‰!§xÒT„õdu�—;$öܧ“›rÃå0äoØî�ÞVh²e§:Tõºâ5—¥Ø –u2^ëÑŧf›ê'÷÷Ä¡·^C:PYó:VÈÄíÆ ,ãèÓ•øé {Œ�B€¡-‚hÕfb~?É\Oãýñ5*q·à#ÌÂUFÖŒÏÐSúsR}Òïod+´¯@C6fSu0¼Ô*Cw>p+Ó"òð”l‚­HŽ‚…Ú‹*×eØ ¬=_v}õBååSÿÕ¢,§9¶wå>p|ˤ´Ƽ²\IQP#óåñL"[zdvÐK2<öàÒ¯_Ä`б/ƒXN//ø$Èû €EŸ ¸´²$s˜Km µG`"H`)ÊÛŒ‡tß.Qˆh½µð?ÿq¾D’˜ë¯°>í&[øH9hxï÷uâ/¾{ŦÀo°w?tîs cv�—`­„ôRÅ ÀÞ..–3ž©|?çŸàðßÖdPœ‹MÚn�a´ÜmÀÙ¬®’I¼¿^jJ¦Aù¶D6&cM“¤›L-Š9öOòœ¨¹=ôr¾oa0ÉŸŠï{·bÊfÍ!¿GÿƒW¦J o °äå>nßê¬_ “¬ v1Îr΢w·©Ñm°7è(vÇ–¡Ò“7»Ê@¯b€eÈ‘KÅ}–W˜{cß�à™3jœ¹³BM±Ó`äʇ Â(Ý�—2¢y‰¹{Ü‚MVwÜXö¹üèô@RAèÈ¢8‚§S„{Æq yõœ�æSøÑ̈ÍÇŠ“ìzw¡ø£½%Õ¶] „ÞÀ_: .mƒ OíàÛdžÝ'Û“ç“DFic/C“ö¤°únÌ"jzÒÒñíO¥þŽôɨ�ÈcUÄ�_S„×çd÷Ö”߉ê5P‰¢ÿr¼GvÀm3Ý5d,¥¼šàlžq3„õ£O»“­Þ¹‹÷Õd&:'¡­ ûÂ1 ”(¿+�u S¿šåßi«¹�«GÌqýQZQ&+Tª„Ó&dè›Døaé îíg¤@èjÛ¾Bÿ( D+<ðú>æ,]pê›±¿q•7Ê Ïì³Ãés^§éª›1uœ¨v,F±.šT¨‘Û£qËq¸Ó Ã'7QTb¢ü.YÐŽ^æÙ„ ­H>i|k Bò<;:Ë*’‡Þ#‹‡þ'¢Û�~‰I”D%×P¤õÓRùhÑ·ögì�ä# s o÷˜E^‘-Ëœ®×óƒÖfÅZ<™·ÖÚj›ŒXpŠ€Êu¡ß%ɤËò£¨Ý ÈŸlb Ze] áãTòa6@æYÁ,”Oâ±kÛõÄQèV §ÿ pˆÎiÀ³�Äç —�{ØU`¿™š}ôQ<ïIFºH£í¹ì—mäÏ®¬‰ŸŠ3ELÈ¿l�ÞxC)Px$­€=Ÿ†DœbÊ| Ùx…6n¶ ×O·Ï=XÓ¿å–²ëò×y�þ*d—åHì'×lÉ"ý¤Ç�PJŠqfœ,)~ßL‡3›MÄA 8:_�á|oÓ Ê „d)ÐÚ&ÚÎ i¹¯1ýýDž«TªÝʧ„‰ÆFŠrN£/ÉR>#UŸ w•€^]nð«F6üzYß^ÜóÿœAŸ†d”dð� gÁÎ|„D¡3µCm±p•C|‹ó‚Ì>;³×ý ¸\ÏÈ»cvRÛÇ_±H')ïÚ ·iöÓ‹cÕARfèºRYˆ¿€¿}RåZ'wœk�Ì7îkjý*=ó·xš…5TËXš£ ÝfžH ª(9Ù˜/g_Sv!žÌÛ·›Xw9q›cñ£ƒ¤ÅôƒÍâU �n7öð®&ž˜.Ê6Ýs2ƒ{„¯ÊD]È”îO¡‹™)$î¦Ggp-ޝzÞ�gŠ�÷ÇI×SR:mˆ>,ˆÕ«YÝÊ7T'»Õ’Ç¥Ó=#sg‰4ÀÜêre(åäÉ®Î,yAÊ¡5�ØŠéD†ÎÆÔz^o÷ôÅr “ˆ²i8 3; ”€ìûÀÚ¸æ#ø…¤À8,´C »ÅJæÄ*<—à’Ò{¹x¡Èn¥Ä6õÕŒ¡„<Áõ.‘Ä{ò›Ÿ1k�Ø;m|„;€¼×>ÈN),¾…�µÇaè.qÚOž„AÑ¢¦$®~­?ímO Oª÷Á4Ÿ§nGÿÐÝ_>»”`u›Ì²·X}86e™�q{HEp2XöÀcf=Ø£×"~ HÅEt$!‹æÖG¿ySZ 8«3ŒDÇ2�ü›jvÑ:�ž[ÛYų³RÏ‚ä��O\â š¤’_ªÑ‘‰vqK…F»¾>‚`üð²®Ù —Ù§;b/å­x…­-R®R/­},W�à/õh ÷9¥DóÖœ¡ûlÒDA’àvìòu:h­�éø!ûˆÈ8b‘io=ÈD»ñ(¡,Ÿšš‡†1ŒÿpOdJé|‹gŽ^Eé``äYû]€0l|é褭�Í!RšŸ�ìB|ؘ6´±ðEáI¤aØ éOýó»%¡ãt h+¿;æÄ—^äÛѨ]iI[jÍIŽž[lý72¿íœßÎà±ülµ¶ù8ýùMÄHù;KϽz~ Éé©ç}ÊWý\½3Ùªèuþuµ‡Ïv~¹°ÎÊ«Sä7pˆ7€Á> v±Ý#Mb[°�ú«U4Ý0Ý[Ø)žÚ8Kzè µ21e=á¬]‚Ó·kü„hniÛ«'1÷[Ÿ“kœêòE�Ô2µú�’”>¬Œ¨}èѳ­sì¨ÑgTØÅäàØƒbõ”ö¼¤úw]/é� ðëI6£(N*[g4’ªà9ÐÔ C!–9�Sì®;8Ísí”Zí3Q½©ÏhF4YX‚y[ÇmÛ¯=©©3º�ïÇrÿoï[Çÿü2!›%,¸pn%$x93eÊ�¥µX}�ë›ÁÃ6ª4tØ;¥püEçØ_ýÀÆ£½.b©tt°Žu*ÝøVàêNåêۧΟÅÿˆ$õF@º÷Ö >…öçé:çt0ïÅ[p@KвcÛãJbXõc�[&c>r10ãK—ìõÄë’ØÕŒútÿøPM¤Õ0¸\Ï�½'ÿrÍðÊ�ç aH¯X¹V�áåȇ·'¹’ŠcÝHû‚ê÷Ëm‘¢sˆ$¹óÙJR’³�Û¤æŒ5¾t·t¯ç¡+0ŒþéO¨…Ù�M¤¸ �q]ëE�Œ†ß"ý� :Õ(zÑ£¨v N”Nõ*Ý}*±’Yq|ç¬ZV×]°hä�L[Yz2ïÂË—5eÉµÝæÏÃüfÊõ×@ ƒËØÔ@qˆ·èш+¾Gƒ§¦rÂqEqÞKn&ØL*Uá8„þ×;¡|%ÏʵV~“©nªDEûJ:eÄ“š×c«Ãïmt£m:Õ†À*]”öxÐ;®Ë‰œÕppÏ;Õì±ú�k*Þà k¤ËÖmÂ�2`VÄf®Qe·éבA ¡J |Ãç�£ÓÝŸƒuÂô¾ÂÍ0×s RúÆP±"þ0˜ #oÓß§%MϬˆ «' ÓJ_*Å̹'ÀsH'ò9â“�ôÉ×Z?ýoì?Í~sYßQ°‘ªÐC‘–Îns¢œP,uŽbÕjÌÌ9IF“7á“>@z'Zpfš”¹"¨ÒlëMר6ñù?ÞãÚì^3d�ôðöà ¦¡ÓµaÒýwd%²ç/Äv¾¯O4~qmÙí@E‰d§ÿÀÕ04PRG>1p¼ø�d À£Õt/#‘³7 ÏäMõ£ ãA›«5-Q2˜ÿýñG¡Â¨–ªïˆ(1þWb¿Ä´ ¢Ü‘_×ô„sƒmáre¿¾?,¸>ØÛ�ò]üêÁ4Nq:ú^+Ë€98:á%ôïë@ŽôÓ6¸†½F fÿ¨› ´1tRŒ’’åˆpÕ¤w=«rRÈ YÌ`Z¥UvŒ_ I/‘cói)¶- Ñ[çâì_#¼”m‡`Ëã�aâÉÌ·v�“€þãDgÙ ÔNòa™›¹å :Ö$.&޼ \AÉ�‹h­‰ÍjäE"q÷Ž6i?* `àé=–H˜jxP¼G‚vxÓî_¢ßeƒŸ9ú°¬P–�Ü‚òƒ%WÑ®äÑj?¤{Á´õްMä þKQk³ïÑëßw¿õüqå\½üùNí3¿Ø–ûþ}¢[6~$a;±¡ݘXX�^eWÌZ½ÐézÈeU"s÷Þ¡#øf!g‘˜ß¤ Mq‚`èp§Ã|?àÿèò¨xî^ÝÄ'LÓŽOrÚ›w —u�Œ ]){w€_1ZF»a¤ÿ:àiböCcnímäÚN‰+ETóO /ï“6+nÌ,Ž�½Ä«jšl>¥`òm5œ’=²ÏŒ‰©ºj³Ã-ò~TªÆÆK&:úZ{ei1W:åÇÛ†� i°˜sòòŠ?;-/xjZø —‡ ¸öþD—=Ïþ'Ýù~w"º@;eÇÝL1¶€GÚ „TÄèÂÖQo[ó_HO)h° ƒNN=ÍWþãJ‹Ïž&æ`¼ª:8ƒ!•A¶idþæBlü2|:¬ Çâa-ÖÛ�\û³¡d-x›ÓS6]S$ šr‡â,:y¢š /8û ዎ@n›}èÍJ�ð?åpj^€a8kû’¯ÅôJÁ£LÎ�–(2€( äÒ‰à!­Ù–nì^L€f¯bÎG·ö'º�VFY,²m›v¢Ùe0+�n‚†¦»åFΡ`<ê{d¨ÇÅÃrŽ�p÷ãߣ|²š+� ýñ0›Ž(‘­H FÖEɲRx¥òT6rªÛbzÆaÂt£Ó�%hœÈ~¦QUEÿð´ÙËdþdÇhÍÑY´sx8Ù�©»Ù®A ®Ù¸uö,6Ö9i�ø$;µ:€#–[»Äê; ~ù‰Øv.nO.P[\‰ä·9¶v ¾ãÊüuðœð“2\¤PýûCßë%`'Ì:X’ˆD½�B ²l¡%iÙݲ}ŒC8è=úøˆDéu�Þ†…ÔÙó/Št_äˆÌ�•¹ ì�ŠPÏ›XFO%Ž'T_sVb8I ôVŸ’Cã•`\ú˜‡?ÀvaàÙ¶P)îåÆUW€f8 ò»p4mÑr&Þš‘"îÃ\/`Ìkï @|•â]UÁÎíçüq =’eãG fÐ ÷„Ê>ŠÆ†ÂyöO„ KèÁWõ�úL�”?|^Ë—y4ŽE/ÅRUîã,-Ÿœ–°2÷+D#.ç(J€íŠ[q€B�]ÿ}ì‡S­§ÆtF—ÉR¼�¿w€Ò³RêÊ옱i_L„‚÷FÖ¹ŠÄcôð¤5~£9†—èo!¡I²½Â PÂÖu§ãZø<08ZÇkœK«^J޾ƹ¾ÈÇ)×@J •>)xñúÿF“9Xz:±ñôš|ï�Œ¯Y¾„VÀæÃª—/̵ÚQ�q–9`|it}3Ki—€Òö� þª×¦²º¯l xISÁ¥ctÇß?‹ÀÔgæ´}õÓ³üðhÆ�‰gÝâ?n�,+Öß§ø…•a”Œé½(Á3ZâŸ.äŽåšÎ$²jxD±ÿ×m)+`ATnuþy!'©ßf%“W4„ølÅžÑytùí³ »“~ž‹’ÄùåLŒ%’C ›ö«¦Ì¿kiȨ„mõ֩ǽ]®Q¯ð–v™/¶Ã(àIFcL_ƒÔþh?2ì‘L°NùЃŽéþÜçÍ�»íwvJ.ý°¬)–ÝùaxXq�å*©c¿âuæ§Ó8%AK(Þ^èk�žá@$H2FÎÊþÏø„s.¢îžàW(žËð1Ü ——&S½ÎoœÜü½c·V…<ã)yÊÆåF�'šÌ¦–ì]-}�Ø�ó©d'¢U4ýÚ&/€jÛb( <3@JªÉåH`z?®¦¬˜÷‹Â„„mÆ¡-}Ë5ŠXâ2ý·¿­/‘£ì:î1Ôo\ ôlïè|©úø\×ö W@ÎŒž¶ 5Árä8„Ãúι*A�еP_¤y/ð|ÞõX̦%°º3ÖÏÁüígæò9™J¸c†?ϦáçšÙA4€µÞ‰r(L„Áý‹º!fÍ)]�ñ¿é8}÷XÇ!�¯½åÚëp¼ˆjÍÆ§Çã-w\Ãô“fÊTF½Úú OÊ1Õ?ªSè,°ã;'G§É¢¸‰à'h2Í‚�äVÛIœž�lôïêziùá}RKê8z +mÊÙ–%–„îG ‘,Õ–TgAª±�Q¥ª2j)¼ï")ÝOãøwš¼eôðª¢h•1,j¢“|�h¾1ƒŸ_œ•&…�j èM%«y”�šî?ºÊVÓ·&Üü$£ÏÌöOì]p+Uvà@I—»LP °”�Æ¿EgT”™ÎÚ’±Òê/Ë{ÑËLU ĤgZ@‹aæŽYm{�D¦ÒL†^-z!Ýui°ï’e3‹W*�„`Ê�ý®÷iíF»ò_�ŸáÖı”Ð’^~�&OÕVðZ�*öx&3GBûÐŒErþgNc(¦y k¼h�ƒ1—�–I,„=„Šò#nàöïú$ ý› 5¡6«°=ðþ¡³µ¢' Ø*li¸2Åjƒ�vª÷õ¹”ò´T¨Lý¼–�Yþ£Þ/,¸€äë ØöVÀi>ÒµðÖ ã‡rú™äþJ0à b¼ï÷² œ-BP˜#16t„š*ª˜²²ê;ú&ÙÞƒ¡U R˜—»F¾ã~�†òˆ˜UaòeyÞ1H“B.ɤµåd}b1^¬âß(;$QÔÍ>ÂÇå7·I~“­@RÊ&Wä¿ ¸ù7ñ…¬¾~ÌNµ¸×^$¿XýÙ ýDóÐO6Dß9îdÚ÷É6O�6´ çk þ�A_´¯Ìb åÔ&ÛŸPО�Må=fÁ´ä<Ÿm|ÓõS~àçåe¯�ŒéXåVÖý­þµ“ÙÁ¦®éÆÿrêͨމ\�úã ²qfàžv§@9~ŸL/]·EÑœ�¬…¯Y±T¾çygŸ-ºÅÍŠ;ô#M^2UQmRâkŽû,€;,‡Øàà0´1°P»d´ýÒQÁÅÕN!J°7ÀøN(Ò1smc DãÙËm®ˆ*†‡�{�ÐT§�`n˜Ï�,ùuÏ*”g`§ßXÆ^7Ÿ|·ü¼‰øŸåóão ½(&$lÒ>¸Ê")=C¦Y¤sWÇÙäèã?½ëã{-jqö,"ªáÑï¨Huƒ ëÒR¦O'«u+Ùµš�ØmŸ,¤Q¥´ƒ|}{¤¡bœû;÷?y4v¢4V¹ÁW|ò(½Ò”wŽ9ýóÖ).%’;?1>]¢|R~×÷ïSùŠùÔbÐ µUha‘ó&+yÅHà†úâç=OdEÃߨù!ð×IH¢œ.�¤Lz}¹»GXüý¡M˜ÌF§‰!ïx§†·>€Nye|äŸÁ>{ýó¤ÿ›õ·^¥ŽþÌ¥ììêº÷ÆOIäüŠBX\ÙOU´Èéw êÞ· ¸õEÆÌ1â¢Ì•+§¦ CJƒ#ªQ³‹—B'-x©<@-5�´¼k}_†CÍŽöÌ6i+­L|SýxË�¬×¨\F D"ÍyÔõ…¹È¦ÿÓþ(H:+| ò T‹+Ýp¤1u·™Cù»ÕNëtccJHÁsÞ÷³ùÈ9Eø-Øö»ä¢ÌiÏ:æ7×�«6Ž<,ò+žU˜×€þWœé0ùƒ´gÖp‰ì°Áø+”©šìkÔ¡Ü £œ5Wã#¤³Àe¬C¯ºÅ=š7,ͪ_bƒÚ¥ÛT¾xáIÉÚÔt/H¡+ªù@Q`Pu. ø„àD †áBféÐ+¡Ì’Î @µ€Y§ÀAŸÉd”dL#ÿ †+/ÝyÁKÄJG¬~a FGmM((²é}ü†ãg±ƒÊ놀‚ó¹›E¤š§^ŠXЮ©šðXv:Ë1Ô ƒF·¶C Šìà÷epN¹W}Ámt¤ø ‚“÷±ûÁ#œY­˜ûåÚH5Xž<[OŸëa¶Tâ·ÜŸÓ"¤»[>¤œˆš�¯H>‹hê¬IV]HtKìŸH_rò`kýDÍA}$s¥ì%‹HTj—/8âýÏØUTת1W2;[!€ã«øV×�ËJØ:ôN�Ý=ó”B¤“O‡˜‹4–úV»±“yentWý0Pc¨ˆK»úÿmÁ)–l`ü?ÊÂÜ6™ŒŒ®!b0ïx^Ôn›f­³.—}gúÙÃŒ&«›ÂrëýÒ2Y§B;6ÑŸw%øÈVyº�KÝ8ζÌûæj4ל‡ w cK²JޝMÐú —mSîKfD=O�І¥üÒäD‡°L(zJ�Å6áæF $Ï��À4¦lµ5/•ñ–gÊñTÓü]‡ªP:•æ‚LJÆ£ÛÀ{· ûÿþœÅȃº®´÷S|@š=¼· áufðpñ¦Fåaÿ|#�Ÿ t-b3)œ*®ã1ëÁÃL!iîȳ&OÁ“ÊÍ·_”b¬ßS÷.¯‹E÷î‰Lr3 y�ŸênGÿ8i…]ºR^‹6·•2Êe[…õ/Ú�|94@Šd–ÏV@"~¨‡Rpp4p±ö”X†‡CÔ ÞªÄjjì9ìNõ&vùw·8=®²7q‹™µå¨(€ðÎîÓx¬ùµÏ±‘p›NH›ëÐ…x3˜–­Û¼^,K�O,qõwU�±æR,ÿãw$ÃCí:ÅI(—Àbjæ”b�±/°Dvܪ@Ãɧ.hKæÀbBÐtÅ0Pæ­èéŸ4šˆƒ>ãǧ-Lî{mÊEˆÎÌ :ÉåLþÀ“¬W!^ÆJ¨8콪ðNPl¶±©åöÏKêX~š,åðŽ9nç¦:"Ñ…÷P’lvöÍ{”_Yô“bp” O§˜møÍô 5b¨²vW­ë†�I±�µf�/5Ó HV­Ù“gõ�ŽÂ~»úÊäÌ!n¾‚ ¾qd(„3�㟚ñÕèái Å5pm–G‰Ì#¼t ºƒb±Ñ]þ-¸œÝ‘Ì$�e2X±ÜáZqÄí#<°ÐðÕ@ú*t g©¨ÿŸý¨˜ž~PH›à˜s¶‚\^Eì(iä±î"g®¾Œ@nIk9;Ïä1W솽±³”+j=ÿVÿoi2Ò.ÀˆS "ÑÿÊ@ôÒòNÈd�æ—n®àÙý…o{‡Ê&Ä!Äæ¼þ§zze¢'Ó.t¥¬pÝϰ V?c—MÄ/Èâñ®'8^ò3QÝ•¥¡;;˜<½ü.ƒcoÆ' ­©G4úvÊÃWä6DÄ”+v“j�¼‚¹yBOn´ÜÒÙžïö„ˆ©§:y’‚c~ëÖaj3ãzÆfË)�8¹ç„-Ì#–&WÑxùãS‚$õ[pR8$Ƈ�&P‚X­¦^õ¦ìû ¸Ô|]©‘t2?Ͻ…1é[¿ Æ÷â@íF÷}S£6rúŠ)™ù÷Ÿ¢\kBoãZ›‚�©«iCÕ¾•˜¸ h ´»7ׯR$c7ƒt2J!MA^õfažËÒ¾|绣6'”R»Öp›w<šá]D~TäÁª¢‹$„%¢�5fN�¾_b²´dŽ «ZéÛ ñ½ßàΈhðÂBËwRúCŸ>û!R-Ä„‡ø< ²B½§åi}rà !¤Þ5B/ÿþ¢©q¯æSå•¢µkš” ';O®Ì‘™wDpÏEúƒIP“IBß;êvïÆÓsÿ<Ü…PHÄM—U»;2Q‚Í´ÎÂ+ÿù“–9Š3h^Ò˜WiWÝÄóI�C™¥—Ý$Îk@­;‡X^÷ÇK³>îV“èc_šÄãüTûÕGÑILfÅHǦ˜"®Y°Cµb H', ¡O:M é…è�¯xWÿ’�Íhov³”Ã<ÑgÃdO¾[T›·ÃÔ€b�üÝïÇ™`ß9+@ªþT¿’ tF³µÉžP‘ŒÇ�àš_oÊ‘0>H^Ž`Ë£�“.½±Q~¿¾åÁ82•säO~]¯ÁmDè²xJòå7Hª;jÀǯ-~]Üœy(²ét¨3 2+’s•¡èô *bžÍ<Ï-dýÎEUåLìØÁ\ÿ€æG“Ûj•Wsì�σ†å…úYVD"vòÇó2×nJÎ%á‚AZêÓ÷ý‡}ÕFSÊ^ ˆ}ž#±9Uª6Iq*JÝ–ÁÚ›Ê�ðª·øs?MM5ÀŠk©ÍCÜÈ|†=×§zŒ×œ$V ‰è%>µUa“r\‘Ø…üÌŽLt gÁÓÈP^Hf7ÙÎ8�qµ/,…ë*Û\'‹Üu�D>ÁKyc]Ü„X$à‡±û:I=ÎRÙ1dø½²Ð½Ü&b¤©AX¨Ò,—þ0Å ÇÒsÙM„ÐÎSûc$#ÓSõ;#'“›õ½ŽAÈÝxŒì©å ³/^ör3íÿUsvlb¹IžábOp ,C⤱ھ3Òaý a7Þ”PßRѺÄ-Ëz¾ãíá9VÉ1¸#‚ ïX–º-ïºvѳöÄJR�¹êãsAîä—õÍâž…(/Зٱjݪ‘ßøM¦»‘¦2g͆1þ ¹—‹º–†ë˜ws„þ¡]ÓL ÔѦš$y˜ä´ 0“ºm¼ß÷劉"Ûß÷¶6pS�2BÖâL€r_2ý®`v .«P™¤¤pƒjŸ¤ƒOÇ(iæjH¤4Ò¿"ïΩågË‘}iù=o¾–ˆAW–o±µ†Rl]�Z%êFû<ƒK•ûMó¡ÍLžÐDpǒ'Õ^o›X¿ôÛH4âPöÞ]ðõáï0›Q8Aj­„b]¿É'GC3 ­RØuÅ~�׋HvYX UëÉ:‘êOô\œÄ{ÚYLçÅÕÖ£±Ëè�j>È9Nj¬°.W¬sg®_h®“¯'YƒËø ÿÄ~€zµ³Li ñ­>j`!¹çßÜD‚�šýI×þf¡¦éq¢r!‡¢LI{ÞN°q‹æ9ò<0 éG¯c KØ+9ÞÖØAµ¬n�…w(|‚[�üÙ “i³Ï!f óôñ‹Ù „*Š¡D’$hý/rtÔ'Þ.Æ…ÌÊØ<_—m’ck8;ܶí²d…½LO›T¨1‹#K�­?Eð2.\æ¦RãÈ�˜µ:¯�ÀœéÄ(éѤeíwúÿ—}`|òA:Î}‡´‰—Õùw!幫 éüúñ×s~*–?Ý»¨0”—°ÌÈåÞþ°˜Êi·"ìþ-Á¶ì€Ë—¤Œ3`ðas@½¢vw¡Ò= R³ò: h€ª©¢OÀTÑT7§9&“ÃÉ/òvih8íÜýÕzO÷V*Äj•/Äw‹òhÒvSç4öú‚ñ—úC¦Îß7¬Î?¸y3†‘½††Ðl|rAµ‘ö†je©u(-wh½J>¦é0¹ ð�p­9=k êÚH ᤒ{ÎÀgM†^Îqµè²¡¹]¢zÛzþÑBø‹DüÛ(Œ‘ôÀãO™ÖqvscÌ2ý£HæU ¦Ï›´ªù#õV Â2îjÉÒ, ?ë$)S¢ý¼à Î8DÖÔõÎrƒµ½FhÀÑ�ˆÛåkÑß¶¬‘‚É.}Iñ~>P“®#®qm™eöÁYà?­…{Q¼øF]¹�u)ºø >­°m@¸ptý‚ý®Ð{„þ¦Ÿ´ÌìÙVòÃ&Ž_$m†ù‰ûÊýºsvw‘õ*É�ÿ§ÿ-;à•Ô!%ïP¤£³Yq �Ç�Q¿X%'Ä�ŒFd€£|�B smyZ¡«N6_ú¤_sA%ÿ|¥ ¯‡§voSûÃÒÅ9nÕÖÚ«—ãsÙx|hµ]܄ֻaP.¸·zŒ >Àƒõr…¶t OÒ;=0 ¯2(I¾/\Ô a!K;—¬vwJòãÔïXb¦¼„æ4E‡êo+“c}ÁWÉÃÀÝ­ýi±¨Øù?-èÅ Á�rE9ÃúE;²_YtPb¡ú¦ó?3²£%¤@Y¸ðl�ãåRfw[e*kæQŃ[ûƒ(²™Ê}4Î\Ð8êtÑ�æÄ‡ìÇ›ÿ÷ZýÖ@âê+ü´GïtñpV~C–+ìÚÀÉŠGõäß.¯j’½�Pq ZH×Á+¯ÂxfçMáüt+òîâ¥ÿƒpfµ¢™o�´æiÆÝÆA2í¾i¯Ä°ÛÿþÇ�€ó¥ÌÞù¨ú$b<Æ+¢Âÿ…‡;+tÌÚhDÛ¤`’úû!àÅ(à�s'{voäs£nÐjÈôìkŒMÀªÑáhê5Õno<-Wúnñ!¦ÞðbYüiÔ}8ž81 ›ÍÞ+ÁÙB¤ëù¶º¥³Þ±.ÅPQˆW #=\³ ¾mãӢ߱E¨ÿ† ׺'@J¸ƒ§Ýhx¢Ç>¤_CkæBôîîŽúÍZÿšlß�+N| "ãMÍá€Å\ÔQôWzç\>©H ÌM�,p£î¼»3Æk–úü|õgóJ––[ºŽ�l:V5õvÒ’N ºFØ rcÒšÌgv\Ú/}Ê0aú\mkbÿâ·“ÞÂDX0¤V ¢Ç,ŸòúߊbÛ8lóaµ¶³<˜f¡_„#UY€úùç#[;˜_úd™;÷©70¿ãø<› � }褵� P‡â„C5 ¾�R:ûy¸¸™ ˜êŸ¿Ÿ’DNÿð¨ï5¸ºT¡‘}û»ØÁã‰êêî–©�Êϸ1=QAXe—³¦±–·k4ø‚MkHMÞw{})£´£L¢Ÿ¶µÁcÊcµ¤d}VØÉ[o1²"*+Xÿ¸Ó–g"ˬ>Æç-¦‹Ñ�fy“ÂÈæœ‹©¥t¬ZOÓZ¿ƒ²ìœkëcü0‡™� õMš¥ Mã:glŸ0–÷êŽ]RÍY7Ãq-Ä\݇Ž'ùJ¢²ûýýýÝ¡h®{ …ËöZuŸ³ q&r<¡±.¾¯ô p[Œ¡W½núIV¼ÚéŽé^b_ô¥×¥(Ý îÀ�'™é?ۗʉö¿O9Ú1a7Ô�;)¥ã)Ù„}=‡s¥˜ÍÍNtŒ *˜G�õ£ ßóˆIòõWyG;Ïð‡ÿMGç#Wìܹ§‡z6•»¥ßƒeGc„IÛ‰²§5›9øxfäBûO74&6e­yŽïGb{É+©ëû{�#-N£í+”_d³×]³|l[ƒ÷MLðIÙ˜=JJþÝ*'“Ló&ºÒ/cV¾‘=©ÜÐÑ;›NrÊ¡ïÌõ¼@ûŽ·FÇßàÁ<;³�áf—Ó(›Ï÷ ýxðlÛ‚po‰eè¡ìÍnø ŒóŒ¼Š€º!JF_ùBý¤ä޹õº¹ :Sغ,eÓì´ª+>”€ø©ê×(:ÀÔ#Kû|VÑG Â|·—×[_U°*Òy*c&¦â˦Ԃ¦2]ظ4‘µZ~²T˜ˆ×Õ¦d:,C'(¼‡gw{02ðl�ÑÄÿr+þ•@Khr„‚5p"D¬l•æ W°¹mÄR8�’¡¹~2,½àÿØÕ&|„´3^~�ónЀãA‡à Êæµ»��ò»"çÚs#ðò»¹^Ê¢q<¥F^èS†3'ù¦Ñ¿å4okh[¯ðVþs“5�Ï:mAfã$h ¥N…v¸G¼2!Znó¡èÈ3Ê:&³ŸÜz pÿJ¼äÍ6Ü")öœh 8› ì´õVÎw£„Ÿ•žl¦Øô€qORŸú<õ°6ɧQ;êÚ¡4w#¶é*§ ^;~; á-:�ðã ßšûFq™ÉFî`­%$��<ò=•CmƒnÝaCdªÓUX k0¢?°ÍX™ÊÏ;ÀawªB?ôG�^£úè%U¨I=SÝŽ¡Bû3縱J��1ò¨=îN‡gÆ@Ú¢£é2ìïïécÐzoÁ»�+,ŠgMÉWVUð\‡Ò…eSÆiÖùÊ =¯ÉÛ nMYìMPSÈIw}{øòìÐ+e"G†÷C³�6ÓÂù³cÀÿ SVl;ÅQ.Shn¯z‚4M]Àv>áÂÝ¡ÃÑ\—ñ%[hËቀ&d–nŒ¿é|.†&R²——ñê(æ ¦Þâ½Ð¼¡Qeú�Œ Ô¾û‚¤'‚/ë¸Ì•ÀVLKÿùZ§¶*´ÐZÊ3P?1fȬ?)ÔÄz]´�NãIl z‡uyÏ U(=“‘“ÓU  yl–Ä[úþ!xkÍ%H,bÿ†f�ú³=”¤†©ÁPBžv�rzÚÎÝ¥tœÝ±.5@‚ïºUÇïê~î™s` ­ÜóRÎY«!D¼ì¿…ÿcJ²™Öw "ó¾ëRÄéT_ñÑû±€8©á¡ý²ÖÝ­<�ŽÓî„ß›4¸k=†ìêÁ­Í“IeF¢]™p;_[/�5#]Z6àX¶¥i^øö8b€vKÈý2)¨ùH5î” Çaåß�z¼]Íç°óZz"¥*¢ÃGŒ ñ-àÏeT }Ͷjîq!à ¬�Xà¤Z¿¡Ž�ÿ÷ù$ø�Ž¿þ¨ß�ß@ìÄuyä‚Ô¼ö�Õ'tëÑšf¼¨-o$5=†$GxóLWþë"î /Ån›‘ž`×¥�ò½çÐT%9JVþ uƒïÔ4n/b«òS¯ ëPÎ>ê²Ô͘l‹K7po„ŽÙ_::X[Qä@�‹Z×Ò}黑‘†ŸÓ%œà…;2xµ€\uôÌC0’Œ�Ÿ‡Ùë t,ñ!úÌc¸34Aó.Øç•·80U3HñÈÒ´]3SxÈÅ,·~UaìdñÀ’Ó¾Ìô‚¿±éS¡YÛ‚÷KäõüU><–ä¶F¯8Ó™5¿Ï T�»òÞr*ý¢�›‚(bÈ}z$i¥7k‚™"ºlˆÕÀ¤?m*«‹þ€ôÖ:ÆÀkëê1lhAoã�1³øÉÕM8¹©N¸ffnÛ0èz¬tÇ0èÆá¦†�Uÿδ;„Üw;š“Ç®ì–À¢qMF´öHãÏ�¦Óº6”¸Úor×|Ínéîffv,ý`Qÿ'ÔDkbgävûƒªÆ—ÛžôÞ,ccøªŠ ÅéØ �W‡û#ª`·‚S𣠠úS`•MŸQÍë4\¢^S�'BýkœF¨]ïn×Ú)Ί‚­¢‹ò<’(b�ûô–—^­§ñ;?×fVg*| Ñ1PàuU˜j¼�ÀcKv{è*.ÎÉ-hï>z§÷Îß{–^=M/1†…�Öѽ{�¨~ÑÒ¬@x üe£'“Êïý‚pD * ÷>ÜÒ-ŒR1Y:é¡J¬ýÉŒ€Ûæjš1¸¦àµ“WˆáaPªú—$«ê›Þ¸%в‰’O:$*‡ÿÏÝþ˜@àQ=¯uﯾ­,Jo§æ<ð%c™•±Dï¯mm kp‘¬‰Ø/ö|rÄù©&snŸ#~ˆþ–¸L¹‹õÓ¾«o9XÎZW2€s6".à�ð·û–…ûpdÑP¸gi$ G $…‰§J]Á”íÎäÓ¯ºgm¦7oñ­ ²Ð]F\åâ9b»U<)•#±±ã7ĵk)–a䘿ü‘H2v¢CßGÂâ3˜Ñø�˜"·«£gÆç-/äp)OKõÄ eÅÚðlH‘ÿ¥¼³ -ÇÇ>Q÷XOØ¿Áô[æÞWZ,àvÀ•ÒP)¾í–¶&I|®ÒËe©÷âŽìÜù£ƒ6W™.+L±  ´É‡ÐO?*Y½câÐî‡T„tu`]&�ûh¡,ÍÑÈ6 [4†lŽÌý´m·»"Ð}t*�4¢ŸšQÑéÙoä¥ÝŸ•Ÿ=òŒ‘þ¾°§ßÅÔ�÷'øÑDa�5pT�-PâýyVVV·a2}æ"Düf ±·ðl†{Ü/·l•‹!ÙüJ–ÍžKŽýJ=Ãã þ$üç×S4Ð6£÷W“ž–Š�Þ|Ô™e@²�ÿÏ8–†³äÕ^æÜ[€OÎ8u²èûÒÒtø¾ÂÿÆþ/:w[8ª&*†Væ¶SlSÖݨìQpT²¥\EßoNÎ-`¹‡H4zåKþ¾¡Yð²‡÷Mf4�‚nøw§Ñ„ÀIU[\8‚ÁÒè¬Éó,î>C» MðŒ©½¿É;ö£„Ê~\ üÔ ÊÞÔôV�GYÁLuYT_¦¸8 /tIÖ�[û±‘ùB&ˆ ݔئÅm¯^ÙZ5‡”odá’,ºã)<çT¿³Æ@Ñ4‹ÒzH'sª²Ô!ñwpN}Åð€ŸšnHÝG±ÓÝ”E°"ÂÇÕ¾eF÷óYÕ²‡È¹ÂèÓJû§>¸"ïNF +_²’—eÿ˜ž�¦´×³ÈaÎEXr÷v‹¡íÃhr¦†«p%Þ›6PHTãÇA•À0Ÿœëí¢¿jê•Ýõ�#…Vaáq,ƒ›¯ò5ÙÆ–Çhé|Â×ÐÙ6_w*ÎáÊNñÏ|ª¬X™@éE1Ü©«ºCîñBÃÏmÂ'kœjû.H“ÃÎÆÉ! ·þìäá\R¨ÃL”//Ú)äõw"9ó}ž?;]»÷èØ¿}YËZ�h :½‘ ˆºŸ¥–R/_h:½ËúÐÀuˆ}æ[^³Œ]ºšó„R÷à‘à+/Ì”° Åp�õ•Ã-P¿3\æÎ ܰB¯9¨D*Œ�Lfêдºi¿ÿE=>¤qjA†Ÿ3ön‘–°¸‘E;3M9ð~Ì© ªê©Ÿ3¿ð³ìÎéþ³ž‹ƒ;J•“ÀyÿÂÏò³æ·5/w.�æj…ªP“½ò’A©™HÅ÷뱫s è@&©-3Ê}ܘˆš™½ÑFÊ›åx¾³ a¦[:é 4mUν<8m”FØ!Oe…ˆŸäÎ¨Ž¯±T RÀ°» º E`2¨ÃzšÀ§úVD� Ý§°r‹“vÐ4r!ëM,®:솬½R'Њ÷S8¨³,nØ�3Á`ª§Ïg„Žç‘6Ùoì¨]¼òÊ º=í VáÂÔKýΕƻgÈöƒPÕœRÏŸñ¡Q�ÈάCÃÜ)žÒ�úŠFZ)“gˆá6¹>‘ý›@Çë$Í …ž×:ΖÅvLp_F0¶s4²<“bpó W;o’µ·B.ïŽ*’Y³.ãõðdìÆÂ‰!¤–œ7_ŒyïHø4’�î3Éø]–@•¨JÛ/¡}QxIÝ }ä«™±˜¨ÿÉè�Æ kÀBR–T½ÖÞ“ùEÏüLQÊD3¦OS[�ø³ àþéɧ¤Ûå¿ì…=ßø5@ãÿåJ]=/Ñ>ûOFlê=ó¯,hp…žÂ$E8”ß5¡þ;ìqâT§Ž™©Ù4ä[…›DA«ú¬ÙƒWr*»þ¥qþA[Ž�¨U#Æ¥6>‰Ö¢çVaƦ Ÿ°móÕü™ò&×¢é¸D¨«QZ%k‚0pyjí¹Ù³uŽÊ5ÄJVÉœW'EZãø¿tü}1i¿ü ¬ÝJe}厞†×†˜b“7 Òxcû±ZLg† ªú3"�YÈJ£'!Ó ›Ä©ÏNç3·™†Äúޣ�f^ͳBWº_ko} Êp‚¹£ïoL%ovÿ äre/ô}ä»4q„.€8”eæ—‚”Gœ8»O$÷¹àšôÂ|Ÿï 5¸Ð}¡^ s�23òÿ£ÕãCâtü'ÝÙQMvòpRYNâ÷¾1§˜Š{*›Ý4%hûs¦Ê˜w8¥J׉eÜ‹Ó"fÇÿÖoR—Ðé“ówf/ø8Gq€/ ¬w`Û/Ê{ø"Ь�4U¨ `ExGÅ…\<¯yŠ5&üð*’¡iÁo< DÓx<:M“G»GEˆKnßCÉ×Z¦ÝëõÏE#*O�h—vtÜžQŒRÆ×5ꯆY¬ÙÈwnò "ä),§ ÑIR‚o�šô…ñzëÝÚhn‡l5ŽÌ%ç#>žv6Têƒ)[.Zò±6pO 44~�CÚQQ¼hÉ_× ¤ò@ºE*‹Ð}Âά\†}ó‚­t0z oˆ;Gc) ›Sœ§H›€Kú>€Õ6²û6æUä°TŠ2ÞËþûÃKß;O²Õ;®¨øñDoÐUø8`žÚPSPL_8�` ¥„¤%šJÔœJä{èø×I–Ÿ ëE‚ýïÜ«˜ækЃg&3â뇫& ŠÆk[øyvì·ëD+Ñà�G<¹Ñƒ”ì+1�¨DkÝÔ¼Šv£9o}¿8£(Öä”w5³³Ö‘¤aeÅÄì£@EØþ%øTïžÏ7Qï§µuæöÍÙ_UÍ»¢ÓžÅö{¾™Ú•ÃÕáMúçD÷r' µëå@cÍLÙÏ2HÆd6´ŠIw2_12ÄXÕ„%ÅËk‘$‹ÈyuÀ@õ!h–ã œ6œt³ÉîŒxDUÿ¯kY¤\Ëx(å“4ËÔ¸™uñÁðŸíü£Ò�¼‚7ifB·cŒšu9ÿ¥²c9”St=Q�ïÛ P~M‚–‰fèÕ€sâSôAVl.øh•¿Âb�£ƒ1Ÿ¹š¸ŸÀ®p:Àcaî~R·p7¶9»¯öÑåm‰wCiÊ¿z´Ãj×ø·]8l(£tÐ/3� ¸‰PQ1×~¸Ëwšóáïé9¹jZ~„x³ûf°¶-8ÞÑM&”3"Úì}×7ªô#=ÙŸtóMå+d´4YøPâëËŽ�FEJÞß½qbª}@[À½Û¿×„�[¯�UÇ“Ë^§Ö´{3Weó_ÎÁrŒË�{roÁÉÈ­:׬Չ:ù&9�ôÂpD—,êü§@ÝÎo B' c)§È&ô1âô#‚½ŒÙ†(†ÞŸò_¢t RbJ<»7™¦·ºç#o3522½ÙrýžZÙ† —R>è];!XöšËÏ×|TiÛ�sžbí�DÑXu�èšV ØU‚Å‚í2ᳪý , T3e]3¸([}±l¶èV_ÞüÎËnlÇêVéj]=Ñ™™†�Ì[Çèt"‡Íך¶›£Ç ‹Ø«CßÊB‚pí˜--t.Þ<@J*zå•Ä寋ç^—]§E‚Õ:!×Ã}�âC| Ö_çk<Õ¸bJ·5£˜®qج1rÐgR`7ÝNh• ý15 –©;H…v¬l /ÂãïKè bã> ÐAèfmy¥¯A›æÍŒÊJ’¨£Çvý«íäÖ7µv|õJ?õ‘È.ÓðqeÀXÊåë;ðÐxÓ§¥É‡ rrAÓÄëƒ#ŸÔüLüŸC}OƒîM§Y”Åß<÷ó9_×5©§¸ÚÄ1˜æ&X' PBeÊ�¨ˆ(òO�¡(8ëz“2—™ã;—ˆáY+¬¬)}e#Зî^Òn_ð1ößr¿b$ä_ EŒè#&ÿhØ�ÅfÀ”¤jpo@Ÿo!Ó½t¿ˆ*{§h`Äv,KžÙøû@?4š×‹¶·KXˆCR>ù)Þæõ„!ê`¸¯Wþ?tì5ß©¾3P±ŸãoQ MÈ‘Ô(;ÙµR+Å”/,\J éÃï :ü†Á1(­Oɺî–Á�•NZ�üLU¼umA3Xíù¶w² 7róX-HÒÇõ"Fåžà • /‡ô**ç9Žh_�1¾7SU§v×E¬¼·÷÷•¶1èƒáSºBÎP°U“´“Ë’lžìÞ˜íã rÑkFg" › ˜uÄJµÕ©qêÂÍà g}[Ï„zåßÜeG™mqêéÿdƒ*‹ñÑL„0!jñ -3•!SA¥Ááœyõ~¯dSš‹ë½$©>g›nXt–åÛ ÛSmµÞ|}k°é¶µî‹D×FßÊü20U¹• ‹T••Ñs¢>ãªMnûç™æ�=Ã~¦ºne H¼ÖûÄ´P²�Z}cF1Î��|O~2×ÛI¤Ÿüò@hûðKHœ4�…å‚1êé8¶» À¾RT„Ÿ«~\úö6™ø�¨gf€!îx¢«Ï».x»ò$ð­­9Á£©mzÁ\B€ ×g¾øVW®Â�^ˆJ$/æ{[iÉÓ7‚Œry° )‰“m‘le _ÝÈ4Œ›áy'7µZ�¤Ê^ª~AoÌ$ÑÄÿ=•Gÿ ¥·@G-ñU·ï>ïè‡Ï _-ÔèaÀÉVc‘æe„°W´ÕÓç }ðªŸs¹½©¦ú¾ L=&e¶¤Aæ)¢#˱l¤žAý3Q3VyÜ4o»|Ä—no©|&,”´(,‡Ÿ(6\“hýC–ãd�‘�>0nL�D$Ò‹A/ ‹¼J¸ÿºúñ[l± ´¸§4F/r�-V£FÖÕ‹ª\é$´p€Å¥X«ÜÇϰøîbp¸á%7É|tØZëN‘d±>‚´´c;éD!þp“É]êþsŸî¦3"οý±>A©„*òµL¤¢’ýŠûÒ¤ðIžá�_†XÕ€Gî „­ aª6#{êsÑÕ/w´¼2UI&Ť–=Òê²#€Ln\�+Ó¦LvUŒ©}]=ú9ÖÔ¤z|S:ê’µt/GÚÏŠÓ¼úËÉo?£¯,nçR%¸du¬ƒ©É¤¹ÑŽBc™þp2¯3áÑÒ+®}ÂM]ö/Àeó.K‚º<\ E˜=CènˆËkó“)ÏûÔÔ-ÒÌ«~ú� „+s¿²CI—æ1ƒ]&êgóJ7åmÎLä{� À!“Fs-0€F¢÷щÔà€cM±v5¹ù¹±í•Ëd @Ð62@ÿ{÷Èù¼ ¡60Iô$PD°ó„,·x›é¦8�.9þʨ™&ÝW•þu£È‘­Cî[j¯´çl¼„C�§¬Ä*nصŸ1íÃ’à0ŽÃz”�o9ó¡Ÿ�¿fßÙ^ ã‰Õ~€„Mð”ìgsjÐôÏ'‰6rß_¸`Q——+˜9f™iÉЂsMZÝú”²5iÊ=ÖC¢&û�²–—ƒe ¢ÝéH\Ð^êüã{èÀvóMúžÛl,w¦ú­»}}bI “ˆ¶S"O^õ=Úš®$GC‹3/äèw³ßWòåZ¾¨G<ÏéqÙïÙ3` _^*†ewÙÜâá…„<ÂLh.–ƒû4.c‘ò%�–h<�ýJ BNoQuáa‘°‹Þ¥›ŸYîóÓØ›üA6HÀ´®n²ó|Ø„eÕŠ°ZÞ|§¤x¦¯ŸTyBJŒL‹A:órIW^J:LyT•¥Ï�¦Ó%Ôz°R(Ö²W:¯FØñ|8ÞcÉÅŸôà­1#™CJ l^úuxmt ¨ì-w«S¤c¢hã-¬ïód�W¢Cdf)x€*s F—;FT§ ÉárÜ}ã•d=–‚@²À7æa«tÁ_í?€$÷*šQj¬„Áù‘žhT©Nì¶•Y¨§Å¿�iº�~Þ›»Rʃ "ë(šr½¢v^N)Ug¹ Vž�ߪB%gmkwÒË·Ó �­[!Ÿ¸–¾Æìƒ·68„ê^&ªýV%>˜ŠbEòm¤n \ä™ NðqÖŽÅAäÊ �M ?{�P�”fAH"–ןç×|«šòÄS¹Ž&¶ Œ�kêrÇÉšmT›�ÅPÏžø’;È 3¨= :Hw´VE\Â"�[Î�OE&óVy0i+6зÄçA´W‡Lõ*¸~×¢ù«š§>GÒ§‘:mN/Zõ 2†¥:†Ä$ôº¤f¶ ÂÉW26sãvY&â…ÉÄ鿍Ä)`Js£L¡ú½=n^'2bgi{ $µ¤±Y$üú�‚½:;Âᡬ€èÉÜŽýŒ¬azð£Gøö=8}¸¨$ öÉïP¦›ªÞ.ø¥þ1ôÍû?í’Ù*'À‘º~#^z"O–ùë‰låžcNÜéøÀ-â{!L”(·�—Ç"žO,ÀÞvq6 exçÂÏ^ɹ`,8j…–¼Ýãí%Aó3�¾«ô^,fDímÿ‘r&dºƒC6žàý”¤)¡'�~{S!µüyþÁ¶ø! £S°(¿L~fÁË]Û²1oèUç0Íc42™¤iÀL3�1ÎÕ«9¤F�l#ûT””ŽÌjE´û‘JG«ùÙiHrÇuÆ+Æ{̼ 0úÜ=Ñ=›xˆ+}üyß-ÁÛ´g–ô¶ž·Œ¿ïY¹ŸˆºyÝTh�‰^²÷x+W©¢9|ÙvEà(+^°„™°ÞMu‰úšv—_ a×¥ú†õÑ/ÙŸÞ:Aîý�ÛKÊ@àÙ¿ú¯*Y ìB[/„F-T…ºÜi½ ©LÃ|t^( ’& c>Dwä¿n©A ”ôCoŠ]C¹DX‘Ï}¢«ÍÕuÚ¥Þýz�é� HLOY ´-ä‹óŠì³Ï:'„ ;ªÚ ¤Ÿr´.Vºþ‚iŒ½)[¬LlbßTr§/ˆ–Ï6†�tôOJªÍŸŽ ³÷¢u�¦ÎšÌ&)Û{‡]ØÔ±ÃãüxÞÿTC›È�ôN IvÊó#^á²� ñ§qF5m»\³ûÝÛœéŒ�ج_XÊTkbÍR¥ë´^ýàZñ�ÄrcÅi·lÝÒl$“h¯P˜�IQiþ¿(Ùàä,ض‘Û±#¹ñ©çA¡B�Ø™éŽs�§>Æ„ØPu§Óé ¸fà.â·Xôsp7Z�#Ñ¿QÆÞ,7[½.I5q~·®3AmÃ>ÚvP=p¤q�Õ´x‚»5" zf`M,ô«wÇþ®ýÆ™)jܺW¿ìòÞŸ-›²Š�é5 -¤Rãð�ꄲmþ‡ÄLPû�l©ca-)O°ÌÍl÷(CÊì^Ò€³uü`GEdZ-Ì·Âd[­ Á”-�Iè[6/ï`;¬p-�U9uí6N #Q<¯ï“Árѯ/~$‘Q“zʯHAŒÚÿcöôßarV FRp©ls…w•“=ÑÖ7çb=�U OÅáä»úEÍ"Â1ÿˆ­õ"ŽãCH-ÓØº÷ÞD]Àtæ�B£)`›ž nGÿ"œ&Ât@?öí[Ä›|�|ÕÓ@âO÷î£r§Ó�ë@÷“X%RxFzÑ"3GÜÈšuf4S9 RàÈ“uÖ´sÁî ¢zA(¼kÎÐÆ20õyåY ³À†+£qËì{M½ËüÜ4&Q¸Èá•�£ÊÀå×¢�*4/˜ß ˆ·V@Ç’)úÂW#[AÝ�Ç'ƒ˽l¡[ƒ…ÀÚa¼FÄüyʆûÛ�?†e¦sdj­|rö\&uRhëÓŒ)Ǥ­ß?ƨNØÙˆò=¾8Õ•m†ú:NߥRvì˜�‡F9‹^,jk»hµ0ÅhÅgŽøl}Ùæ�ð+ĨÄÕžÂ;S�ל)Õ+EDØV§ñSÙ¤î²%ä2¡� <+ƒÉÝ×}nÛ8Wµæ¼Lù«Ò$f'&2€îd¸™Ìpªç»¨`4ts­•¡bÉžu-ž­/-Ôeí¹*j–ÌI$×H’ˆóTªeƒ¦/OvÁ.AšòÙÁ�öue¼ÐøÑ¹Î1å A¾L½ói»¬‰d5˼© P¢bäõ¤Æ³«Ó÷*îÒ³iÖKVam¡·G[ú;¶wòsþðu©Š°œ•8Š¿Å�Îý , L—ÎqDX…¶´¾Ò[vx¨oâ;#Íü¡Uá¸Á9ÔK^˜ð˜i~ù:Z•PÍ|Ž­.ì_I“VV/4¥Ô‡P6DÄ!òh_AAÿÏËlɪW‰‰Mg ¾˜×À|p ¥f�jÕÁ:™­éôå‡MsúGo’Õ9€«Ç7ûÁχõB6C¹ñ VfW#ÍØÈLr&9}ä!>!äx�ùØ3n“‘*ŽÜé»ÊפVÜ¿�­X·¬É¼ø½D¨áJ~®¹š‚?~˜­G¼úº×¹%Tï+J…He©_�P�7 ECAó1Ø©»hº¶l<ú,­cÐwÎ[fU#O‚.�GÌ¿&"ÁQ´-³ºª$UΡDnæ­v‡H},:GOìd©Iv¹CŠçóÚ×Pý¸FÆ«pÊZgC/ÿGìµÆÏ–Oðg/E&<¼_dùÙ“�FMzêå�{Ä,Ÿœ“œ’ÅT ºg…原üc0›¹úH¾ÿR+m9ðåž÷»¢,;oêLIHh§0¾U ˆ «³¼ ·®m²¼ûÉlð):ès ùkÕü >¯˜ÜÉ,´ÝqŸÞÐo" ümR Ê�Zz]:¦q)Ó•à*lÊ6©%Vx«ov‡ÃX|3AØ@ªš‘]o¦òú—û�/™ù«ZÏ·@Í–sqhÈšßÖ;wéã�`“*I¿;ˆ¬ z>îÙŒ~ê™CZyº­‹e9P›Xéâ_¦_¡Ã~JÍõU_zãd„2BÜñ”zž9Œÿ¬%ÛU¡¨Ñ<Œå–eKµÔ‘Pqé.s Ș^Áq�kÒݰtR17õ•Ríä½`JÛò {=wûÕ‘¾æaÖ,tL«\ ÁràÂBÚ¹çNöS6½‰ÿåÿjAËW)¥a SI:µs‚áסީWÀ™©`}†zºŒNòÚò¤=0»ÂÛÉ<»¯ÏpŒf`Ú½à©^:—ž–Ç—má–ÛM&ƒÔZU‰.°gcŽ£Žˆ)”nMŠÅV/÷ë¿°F™Êîe±1óð–´³€�ó” Jàa²N¼Cd²_ÈZú»/Gé™ß÷ôf^½b%íâ„H mxDù¸í‘Pä„ ×ÚuxÕk ¯L’:c 1áhuVôþó8»åòŸ¹Om‚bƒêõS×âìÈ�¾á¤°ñûvzL‚’L3˜j!uu‚ÚQ/#¿�õL¥ø{]òU÷‡(%ÛðÀ-Kù7�‘ÙZúµ²– ³§ò&ß dWÿ^ãcsD �w#èþÿÞ·=Nįhz@¿ê £=M?)fÉ}�Ÿ%^ %+2ö+<ÿûåˆÆyo«,~ž&A¼&uŒý~�7þ©·«ÂVx@Î0™¢S$*q*µøOh™ù%Wq Ÿ×VoâNÕZøZCT�÷Kžy¦M$ê�[ãsU~—XD{ƒß…ZƱ¤¢¦ØK‡w­hoÉEª3/‚¹ ³ú°&D$ý]h‹·� l†ÃIÚóÂp§Àÿ»¢ÆßžXárVÁ§Å2)5(ö©g Íÿç!ÑáÍkscI} ƒ¾Z¼ö¹}Ñà@¿£Õ5‡orϪ…w-Jyqd¸ðl¶ü…KÑŒ¡ƒ�¢®ñl-ØÞÅàO•—øÁœ43 éîÀdÆ÷´ÐˆÆ¸ „KĦº­]éy‚k$ù,jƒRí°a>–ÆÇžgs‰QŒš�¶mé¨c/3c Ø\ÐÜ4¢`1Ü §åžÅä÷Q®Õ‹A Îþ~ïí€t–€~k!]»IzÆØs$U‘nóöI+¨$™'ëÕ€‹¶›Æ†ÅÎàH<Å‚ ¬»ß!™¥¼€�UÖD#ºê†‘öeÞÓì“®‹²v’±ÎÇQC]Þ^ �8y4=‘­•_qØ„æR½ ÝÃf¡ Ó¥+œ¾ü�z³r[nÃz¦¿ÜñÍ|`/Q¸’`}\ðeÀ��*ª±p;ŸY•¥Œù^ý/ƶÇ�TjÆê;µªÖŒÔzüa=�Ì  eª£Ñ–¶ýÞZθûTîÈÀ�.ÑÔ¶¼¸3ršë£õ<{å^ŽR`�¸Î ´ဂÍ�’>ÃÚö˜ê亥è×Éyí<‚qÚö)kļa&†ç�Þ4á˜wÈý�/]ݨÈ]p¢íÑJÆR-žAíNf¢Iméa …~¹brü†;Å¢°:óiœá>[½Hu [C÷}9«‹\7ŠSÔÁ#`µ›•îÊØImU ÞBÄR†NÒTïYJ=¾¡‰“(ÌV3ÏPÄòñeÕ]lg±ÍüÅÅÙAµš¾þ¬K°9Hè8åH:í%Ei‹ ”yë§!½q?¡�¡ðGÛT'CbK#⩲].¶ˆ¾2–¨ôð et¼ 0Û)œ¢p‚u#Uª¼Ÿo9±"Ü”ïv²1l‚7në‚\rTJ/¬PÉ·õâúŽ ¼Šƒ¢u±.»Á�ŸögÖ½gõ£ŠŒHn„œ±OËì²ÿ…,NéïøªGáÑ^Âû3ô7@­ôÁ�yä9ÚÓZȇeÂD0ÊȈÙ@­=“ÙÙµÜ#›y,bš¼ýŒ­£Kexp¾ùNŸ•½»"Š-e"l*šÙ¦9`v¸è2[åhà[FèL¦P‹Œ#lF †”¬±•j\À§×œw§{AäÚœUC\×Ù±hˆ÷5P"èM ¨î§�˜ŽšîCuÎøÂq—â!€ö[ñÒ’cüh¼t2]gÆ+JÂÜRÞÙgŽëêý i(©¦–›Øeæý"…÷´U�Æê¹Ù¬¹Ï(\¶ðŽyrtS&Üoy–9*Ý8TW!©3Wþ•ÚE_ é8]T¸]ŽÅ¿ÉL.Á*Qr�úÝø›Wõ^ëÏ ÎdÀ¯]!»ìÆÐ*tDg»_¹£s¼7ðA©—îs*ïÊĪ�X.%=¨Œ| !üÞÕL7z\·�>½¨®¼¬ørJU²�ŠªÂG·I/ âQÏ>Ë병Q"%¼Ž„�lc¡knØJ™HÉ«¬`ϵVÒɇ˜ÎwýÅ?ÅJ.)"‹ÐÛCBXöD££‡|ò‚‘)àºß˯³0ƒOÏ%Å�Aíéiýœo\Çù øˆ#™U,Ñ'µ Hï¢#—Lë›Yd÷�‰ëïàŽ .Ž˜k뜓¡G±JJ=±–E+¨amºûÁÀ;ÿGd箣EÀIëg¸/{’ÇâLº;è¬ v8ˈnÝiɃ‰³ ǨKÞŠ¥Î0¼ô 0¨øã ©Ã§Ì/ÂãÒiOÁJ�žÎ¯ U”ƒYIv<#08æN¬ –Qü?êwnÛq¦xΆá“%[®tøýùí>DV4tŠ:ò)Cöõô¸ðPôHÏ‚¾À ïûkgyõ�bÍÀ(‡“ÛÖ¡Ç’øKÍôé6/Óz*Ç¡i†ð[I3 |º¿s�XØo�ؾ%ÐK£�ù�Ö*+ FOÌJ3JœLŠ•&ê§ÈÏh?iA tÖö*ù†»VYŸ.‡Yhx¥ð%W£�QH3¼­²>òŒ/Þ¶œÎ²g‚Ï´t‚ÔG’]©%Œèelœ–‚-ž§UZÓÖ‹cs ãªþomþDþNTÁZd‰øª [vÔá×ìÔdmÙåÿû‹çŸÓÞO'8&`¼}34ZC¸Y^íçwk/›øEz/Kûµe}MI×§VÐߟü‚^UD_fÔ…(:t¥ÒÈ(g<ÿã€û[‰:Ž1 +Ø)¨Iï€vÒ|Œ_èÛ>e>‰§ž\«.>!ø5á·2·z�\ç7¯}s›\à Î1{üÉ[z:ómê&-}GË€ ø:åÞ‘ê‡õ“Ìsó˯�À§¿³‹åd!üŒ�¥ìÉ"½„"03YpiÎ+B»�®Ò5$ãQÊ Õ¾.<�Þ™äwðœDµy5€&uEe/×NoäZ¡½Ñë ÂâaòëÉqZ[è÷æà‹¸GvÇ ñͨµÀ�Þ þ¤Ü1\”Žíñ¼Ã’SZÁq%Êj¤‚×edÕŠ™àÖ=,ÌêeÞ³Þi¯žb™Q…ûr›<9ŽNYNÁCfq>*Ôpf“ßµ ;Ðil‡Y‘T¶LÒBÍ!¿ðIcL.£ž:,b’Ꭷá[Å{X6°—·G/13Ö©dÃÕ³ÇÕ nû.ar–}1)A‡Œ>Ë�‹•¶!>•#€‚!o(ôÓ0W^| �½é¬e·¾éå3®Ù�P™ÖÏøïtÓ3ÚR) ž»õÜôAà \ þ:û—so®�°îÊ…mx­q‹!Dzãy—ןgÀDCò8¿ë¶§¶Ïk9Uéäïv…c¯æ[O.„¦ùÆÇ# Áf“Êoý>š¶[{oâJåüÌÁf]”ÛU9 "èÆm  Së” „� :�åb©/…çr{eratª‰OÅ}¦‰9´MœØ¥{~êîd­¶Y¥·Ez¡ÝP;8’ø±·RåȲJMuæÏë#œòž=êð#@¡ý5··Uv7ùÁœ²3`½¸×‘8¯*w)†ÁõM�Œ-¬~W%ò[!~p�ê\³ú4W“È<Q‚9’ävmX|ű·’ÀlÅ ÚÚWG*wf:ÞGy>†ŒÄS£¤‰¯ì²æ­*[ëcþ»Fqõè·.ªž4�:òw3IÌâÉ�:x¸©f´*üµ\^ñ×aî@àr*š†{jîB”ày3j=u£‹ü2Û�Øö6{b¦nÈc°¼Z~ª~( 7Ñ�’N”€ð<Ýk§5LnüÉã;jÕ1ºMw—£N'�GÕ Ss,ä8 ØámD›&]ýjé&÷ƒð¸¾’=Lž+ ÛW� ¹»“™|5Öã§ì$›EŸ‹•áq‘Ö !ÁЉ%W¯G¡þ`™ºÖgb‹'Óžzbçô^Ln¯h2ñÓHX¨Ù¨”ŸtëÁܤ$”(ƒ È ð{±‘ŽKÌÙ…—¬£Qcí¾½/X;ú½õé„ûE8T4®\¢ƒVù$9ŒãZ 1 Ö4l\¸Í˜gMTX|:'ÂÇjÛH”'–1zÒÏ0Äcrx¸µ¥Äh+ 7T¡¤_Õte˜R[7wn_R ï3ï‹ð­�è��v¬¡~§ëI©g®Ác– 2*O“l+!CN\uF´5´¡Ò¤lº›Ÿ‘4Rðtâ ²:£ÿÝKOˆ¡z†/==dfH›—é!”iíù#V é?ÂwjWU*’’þð\­Cªw¦OrÏ}f§ب—¸%·¼&Œ‹%•ŒOî¥Ãˆ£~Õ¿¢ã@MýTRágW^’?4å >"‹E7(³€¤7ß\rî|ê™™€|´“½>`ã�15±_QR¸ÄŸ#vÝáôA&n÷ÃTe T«Ò¨Ší ›U.Üy¯²UæÁr=˦~ÚÈ?æq-º¼¸·æ9Ãv ¹…ÕI¡ã  ›KÎ÷2:g›8óV̨în9Ò2È‘´ï±T†—ŠübCì¤øVb›÷×Ñ\ø ÜVlÆc#i£„›R's?'†‘݉( œù H"¡AŒÑFNw¹le0‘�«^Ю„wÑ›Q:ÇyóžP»Ñ~eEÔô»³J>£ÎÂX�nÃ¥’pvϼTÒÜ[×O•Å‚ìÍ+¾——òP· qP_Íáoÿ]ŒÜU?Qj¥‡d¢ í¦à÷ Q§ú©zWk]ȸAhëˆi_ÂkEìÀ K?QÚ›Zžšƒ¯‰ÔôesÓ…S×°pòÜ�ÇE ‰ A±çA­Ä¡‚ÑZ<œ©ð�•¼Ü_ýîN“Læc½�0cÓ J�¤®µÉÎ'jýÑ Ä¯¿ùø.ÉÿÐ,¦X¶sLä­ !*›94Øòp¹¢tÁe‰u?óös"#;QóGû,uü�Ì9;”†º>ðê·t.‚Ö2L|À’¥¸¯G�&úËæUÌVz>ûR¾r¸µ¤ˆÜ LXRP D­”Lt¨ÎåÞÅôŒ’Í?þ‰ ¿PÛ¥8»¹Xm?ª*-{®œvÃüB‰ÍæTûk_ ˜¹qQN©�l7,€£$·Rñ51 äŒÐFYêiOõ¯öžÈ(šåŠŸ› ÆýQź“gÛD]+³ÄÛªj½Ó´A Ý!ïgû¥�»]97Œ²z|"4d(ý–|Rôªïl¢6+o ·Õ?�Èg�cò.±”(h�äà!¥~f¹°S"�²„Œ¶» ¡Ê¡ÿ·á{gx=~¦®‰ e(ò¨:»b ÂFóoù·úYªŒ<7âüÆ{å6q­À›©>Mù Ø ‹¹‰=õAcùLjûÏØ‹}|Äé=`YæNkÕä?øe×xÂf»Ô“lt#Ú¢…ˆVò4k ` …l¥Ñ¨€Êmä]y•îì¦T zAÿiaZ]>u>Á Û^³ý3^.ÁϞ˂¶Ÿùù§#@ Û€P½«KžSX2ÝKy"Â`ߺÀ€lŒ!%L$ôo�i¨¯EBL=óæ(Lë5ZßUzNÑg�E‡ÿ¨…ìúX¼Üb»¯mç:‚È"{mòJÌG[¼Cíÿðn*½-s3ÅEùàAXÚ Œñœ6ÑVTdÔ¦ù²ºyf38Ñ%q†&éQ§˜ÿÇÛ†Ãqñ3¢ëõ¢Ò†³å¼r=F7ú> ‘ÁÝ3ÓKš|¥WÇ vQ {t[ïͬ;åùNýÞ7±‰=ÉæÆ2­ö€Ä”’'ܱ yá½Ø²6ü`'�Ï`/ÿÎg‰{¼$W)’7þg8®ÕÏ,òá~ý ])ôIzóäIïL˜5Qv[vQ/ÿ7IltaÅUâÃ{�V0„‡ä74²–yòÊ©;:„o9/ˆÈ"Ì^8zÐržJæÛ¾D6Àóä�Ÿ£‚ˆúZé‚’‚ÔÉH»,´|z§YGH¶ßÁPzmšR¥˜¡ñÅ Dò6Ç´a"™¸“c;Å‚«xü`k`$?ðˆ,|ï”�'äövÁ¢õÝ1=ñ�þꃃMçóNìùN®>#½�É¢?Jºb[r 'Îæ#ø½E9="ÿæ4„Š�Ãai�T8è¸�ï˜Íy'…F�èÒiË›ì ñÙ ¦Eë3[fš½ ª’ç’þaäÊ:v ®·§ w¼çfi+?øuòq¶°ˆÂf9bÑ%�åŠûê…„tŠü|KS½Èß6–z›²u†rm°£1ùÆ®gwȾ$Èh<²»ö§Ç_ ¶®Üc 2q¦܂{€[ÿ‘ф ›A%öF¼mŒ3X°:¬s·MÑJÁOó�h8뵺 æ@r(£ûÓÈ’�=�—X‡‰,¼ DôëCÔ8™üZ¯ð ·´ÉôƒüÚäÆçK¨`4p•'b·ôÏÒíÊŒôÕ¡»ÑYã‘^ôŒZv ¢×¼]AO)’‡ˆAMZ¨‚ÈD­ocó"ò¡špˆýuþ˜GBä=mðRì¯@C»º§Ø¤.¯÷]«çã¹\kR‰MìbõjaJ ‘6±õ\´l„wÇ «&ªà`Œk–¼>q%Tæÿc´†i[¬ÛBûcmEúmÕ`‘%þ“*¢&„ñÁW¯ç™U�ÛÛ âR�V€ÊUt0¡®~ªuÙúlõ©«çcL³6´Uô4|4�>áû_?*”þ¿Ìv¾@«q?=ªpÙÔóÿ{¤³E^:Ÿi¡Ž?.3ã'Š6ôâŽp‘CªÖ·§ ´"ák0 Z…F,‹@ÇêƒÿGŒ*ä�ÑZÚ­Ñ�ùË8ã¥EH¡gÑ5i²ÆWÌØò'N!,Ù ó“ÍGΕ(¢Á m’„#æ•N¢Ûx§¿^1Qòc.mj(ð0š3 áÕ€o,�ë¶$íd?»,g<|¯,U™¸U¥ùÚ/®3íRцv鲚 Õ’ j±�én7“ë°¹Vß©ï»9PÆ¥¬Ì¦hÃ`ùjŲ¬Ÿ¿'Q©¬úòØðïM³«æ´Þ:]2ϱ[¸ÇÁ^Ã2Ûsj‘~~µ¯pK]b›£“e§+PàÛŸÿ`ª},Z'_ºC³Ï¨_‹546Ê.®3rUB€`!*0«–ŒqÂã*>À§Ù…‹¢÷^ÅÁ+iiÏ ¼Š‘ÈÄäô¸ñ÷K¶QÒ„š=½¹g~Û&"Ëú²­Wí´�€ Êç‚Ìçu 1öÔ+ñº®4G··œZS1 ´³ÉN»PÔÙhýn,€xÖi’úÄ(MuãîTGõ†=^7ãë|{޾´3Oá¢Q*ËE¸Þ†·çc²nÛ}°±³û›úNB8ß ·z¦L& gC0D7©9+ÈŸ ¯©b* cB¹F‰åG8"Ð~Y¡næ‚e³Ïù§ÁEdœ1Žh íõ5}ÉåK�[@ÍEäI—õ]>êþZÁuº¶»Ò–É@wáhAÕê*4%u½^ã[(¨ W;1ÉÜÉð}Ô“…ØéÈï‡Û’pJ-Ì'ŒûT›™!/[ÉZ×ÈÁbƒdN îØw›éE>èÄ2ëÊîN”&7+¿¦@B˜/á«ÛŽ�.޼f—Dœvé7ûˆ÷á/zjGd¥.À¨Ô—“DS¶'%ãˆ=”ÊfÀy«tÕ±x%�Ã=d�>ù*?ö4p¶™Nï0¶¥×‘ë� ÙW‰#1‹aèL4³#¦„ˆ/ÒGà Õú$€Ù` ¥ "¡x§ÕO,î[Œ<â›`)ß×˺ðÌi±¤\¸v£t1Ý•ßÀ”£­¡ŠK&ùä#’S9&œ�=ËÛI½T��£¼Su½ u+•j¤/½è§Ðoä–5ÕOUšÆÅÜ—¡æ.l {ý9€:&_Q¬0Cäòï"áXA“]�K½4ûŽXÑR°IÑíÿÐ _ 7yp_“®÷™Ññ�dàÚÛ' аx_Uj.]í*‚:õÒ�;�lµ¡QÜ¥é5�:ÆkC÷÷åi6•ªOKñ™åú߸eö/.äa¯p!=QV²Ïû¦ÝdtrH¢Üo8×Ùˆñ‘¢ÓÛGeîÓ*F\ùÚÅØÃÆÞðâî+Žfqq^È•G9Az8âUaøÃ·F´K/ Òr¾ö™e.®ªRÚéþHF58½æÔìÃ5âAîi»óU!–Mr-Êlb^€™ñ¨#41 “‹5K�˜ó²²¦p©Ÿ}Tj¤ ioj�›’µ1³¹ÈÞ� [ѨÀ A¯ì7^èÌW`¹C··°,ÃÛ��Õz�ZÊpâkE²2œ…ž¬ûzÐ;âp;Ǽ¦È¹®æ´ÙZsêCP�UàR„Ý… =Tj&…Ù>+%ÿŠlë Ùê+ºÙrâ)G‹©#�Äjƒok6s­²›ÿÏm]K˜�J‚ê9™TÞ¤!ª­q/+¯Gî£æÁÁø ^È’h W9[äqk7Y�>�fL-�,Žš¥]*¬ñ>a³ëk¾¦{ê$µ™‘þý‘àcú,ü×ÇZ»X‚ÄB)µÁ�Þëm”+yÕŒá6wø±Ò¯Ã0yHZ•HÉ,j�Šûão²§†´O¸&r6- q%ñl.(M� D�«WqÀør5�'Ííýt‡>]Z6>ɳ<_5äÁÀ°T^`Âiž§»;œ¾ùûÉdÃKOú~ÓD§—gænøÏ;ŠÙŸZ0:¼=7# ~]é¶/hʱü‚ýЮ£öY=‹z5dz÷‚ÜeH ^´Èý­KÒ�f¶Àвd©ÑØï–¶íÉÎñT]¬=z,œ…‘Ó‰ŠwNŨÎ7æBªÅó�ç`:í<óùMûi…d!’Ëó(ódjÌ×�lè¾,’Sâ¢ÞËr¤ä·‰qCÂqqP€ Ÿ µp<Àƒ?•µãò0à£ýД5˜½õ­á�{åòÉÙ騙ÐOzýóy HÜ_¶–ûuêêêq²ù?ªx@ïtü4’$xY0+Õƒà½WzÚùŠŸ½âÒ�F¶Â¬òø<¦½¢Âú„§œ-¸à2§`@õæÔ| [€QUo¦ŽaêƒX?Á s©ÛeP¼áoÞˆlÿÿ&ø¿Z¶uÅ3ç|=šTaò �¢‰–w ®¤7£%fÆ0lößLÛH—…áîÁžRx(lr�Ɇ(" +'`—ß?_³ÔÙJÃ�„�(7#"µK³0-d¹´½eJ•›g4 `÷/E‡+¸»2T0>p"\ÍIËÉ Ÿ®ÆÐ�h"IÿŸïýÖ çßqÌ~XÕÅÎpº‘Òß‹oJèü~;H Ã(ºêλ?®)¶å>3ëïì…A×:–&f;®wí:¹ò;'ÄþØÅ…b *‚‹”B,€êpO¾QÌCYm…ûÐÙÆkÄg÷®ÍVÃ>wê<Ù”û#)_³ÀЃn—[tؘ©èAöq3à� Îu4ÓÅ8qiö»ÀS@4%çä<ÆZ >“õ=­|ód˜Tù¥îÔLªdy oÔØ¡ü“¿DBT·*ÂÅËÈÑ2hZÝŠÑæÖö3]zv»Á ¢ýð•ÕZå9#©Ö<÷ØJñg‹IHó¸?dzÓ}ùÂRÐåc7^0£¾ªZS8(iwtˆ£ßâu­@à‹ÆlãYÂ/þXÂuœ-xÍâD`ñ3Až/d”dðŸ Ú3>Û0Bà¸Èf“;B Õ §³Âyü9µTŠñq[P©¶;l¬6û*QgÇIå¶½”JhmEÿ#M©R~déºSêëŽ+\UÞ„p¥âëÀ*õ‡Ð b§{M�Äc\CÌ´ »0§Óò«æ5(¬·tÝ'Dôaîæ^æ¼P3CîÄjÄ'9ÀL2Šï›=h43c¶SÍ…˜‰eø;ÇcœM×&oÑö�{ÇžÚ¨ ÄÞY™ÚÄ6ÅÇë�œM'§‡˜yŒ ‹õË�à BÀ£ª‘´éU›‰Ç®äKú!£¦ÇhklÑt¿ÕÅà¸üÎ’#ÞÑEpcqüئÀ1ãã='f:6ÿã �ÓÿCR‹øHþÂ`š]¹®sІ „R ið üõr!ž]Z‡4~‰²‘w(Ø„Úc:j+Ù×�ÀºSH–¹gÁÿ²^ãj„üb¦ê'‚`¦OšÛÑ¢˜äHM3R…?\ƒQô“ø¸2æòUU<ÿwòîûŠE-mò蜅l†§޲Fþó‰¤?°¤g—‘KÜzë Þ\û†ƒôqö>§I�(pù–Ý] É.LJþLÑIk«¢¥)§ô_Wëõ’DíRirIòI½�Þ�‡ŒÉ,*¸°TÛtá�F³ƒ4L S–`3YrY{í“houY¡ª~;Pc¬ñá�ºo®‘ɵt›�ÈOÁ�/Ý# …f8�¶ç­Nòqv(ûÅ‹ë ö-‚ED5‰߇RhkîÈíESÁ4 M+± ݸq ÕùÞžeG˺ݭ/Ø’ß:õ¼RcE�?Í÷ê;.7\1}¶T`4…3‰RÞQæv=ø}t<� ¬õêµ×öaæ>i¶èSÿÌg¬ŒÈÚŸZhÔD"Ö2ÁqŵAÈeQp‰OÈ€S�‡":„–Ô²¨O'•B»„…±µÏU?¢ y:VþP¹îñÝHáOÃb ^Víà™6�^«zn®uñ³æ.ø©ÜTuà‡3%Y“å×}ß0ê5 ÝÝ–†EŠ÷¹–)§'RÇ–“¡ÜRNI¦êt÷fÂüÈÎÏ<NÝ®Z—ÄøU®ÚÌQ¡€YcFÉ|‚oA½ù§K:­‹ˆYpÎ~Öbÿ Â0�??ŒÝˆZœœÉ5PÇ©0èá·rê/ÄDz +~d°LÓ3WWðû<›Œe)¿á°¤*†�»«3;úÍ�Œˆœ?»v±ó~¨`¹¦À×™xï¸2Ð[)x(•,ÌE4 :íôlÁ7bi˜‚ æM¿K:L5G§j´ÄØëM¬5ЭÉcÂBŽóO3쉸Z?¸Ôôì/[u·ˆdÊ¥ýßÇ„”$Z’t�Í­’çÀ¹¾Õ‡íEˆÛLkä ’ydaDQ¹Tç$°9e(‡])ëZ6â?…s¢d~zôü?Žz½ 2 G¡¥Ir�²ÒùË6ƒ¿aF«7C{Ö™ì›�À™9«lP_ÃørÆ®¿ÐMoÔñÊi¯w¸Ì’$¼Äê4X�¼Ì"â¶Œ —9ôÌ~Òkv+¢½F›ñZ±»£ ý›«…瞥¼L34D–ÑêÍAeüe ›~ɳäÕ¸md*ÑÀ¯ÆIº¸Ä–ÙÅB-G Á[˧†¢’Ǭ}& d¹ùyAš¾^ͯf‰¿zHÝ‹¦ñi†Ž}�†† ™z+6>?Ãé€Å¤ÚáT0ˆpéÛä%Ø{TÌtPçB|)H©­  ïJ4+�}V*%ªÊŽÅ//ÅB¥ìµû¸óQ†§±•Àmúë%“.¸f¬Ð MUÀœ7ÝaúþÜõNÊ—¯”d“¯™«ú©– ìn£U}:žNiÿ.’¬«¿@e À!¶cŸ“Ò"r×ðX=Lyì˜#ÇD4MqweÖ¿€ÒÖUàÌ=ø C‡:˜\Œå Ú®Èà×⾜#©ìžŽHTXF•nb0¾Kâš4‡Ônp/HÍ8‹5ã4¥mùšê‡CÑ:(ñA´UF’;.]îx Œ¾J‹×¶w1qšMòÊz[’i¶?² ¤0òš,DRé2 £g¹J§FRR´†‰�]?¡Y‡#·×c´9¾æw»ÏeÐ6�/ÈÉæ,vqŒÕV{ð�+ôÑ÷û%öAyõØí/û=i:]æŒc(^_^ÔÊ£»­7ì»üpox¬}ß�´bk2µ†]ØXÃÒlzÆZLG½G);Ô§FLMm”-�”èÌýRü'5(C³ërx༡È]z‡ZÆ(þ{@{As—ÆmÆÞʃ>G¤6ï�XŒ•u¾´¦9u !Ð.x�uõ(Ý»¨r´)fR0É ì¬ëÀ÷0¡�Ìa¤¯�‚ùdv)ü¦4bnKÁÕ o+‰©xØ5�c‹â½Ç5TvÞ¦«7O€�ˆù¦jïhÒ²¤4Ó*%69g'è±vFˆ�ÿPÚ¹ÆÞU°ïóÄ[¹5ºØ;[Ÿ_Øÿ—û%ÐÓÎĦwlÈO‚mÛ$ƒ‚Ò^ú”*Ûº¬#ˆ—mŽDË� 4ú Ñs&ÄÎÙ3¤À«Ð�üÀj¾³¸Ñ–•éç¨fbžPnGÿ™îo$OÀ?%µ`;«Æ+Aþ¤XÚTù”ùÞ"%wm¡?b Qt7m·Nއaj 5‹°6BwËëëêW1õ9ôªkß”#Né}A¾ õºÍPûWé ÙÇ*­ã‚Ô©¦5ú )™¬ÆuÆï-Þ¯¡}¨[º†k´e+9¯ãÚ³Q+&à…`grTG¥(XÙŠà鈾”w¥å�dÒ6˃ÕV$+÷P ó!.à†õB‚Ûå§,â…¸m¸uǸôI¥ø6d�ÁC%– ÀEiïæ¨Jô²yì‚ ÄêÄl7%–ÎO•–]§ÜCngêªÝ‘}ÑárƒÖ}¢Î-Ð.qƒ±•G—m¿“H± Þ CEÎþÔF%³FGiÚpô6oB½ÐgJæ´Ÿ¢�\]ã•2éï#s- ¹çCÔ.™ÝÒ{Œ$•¬Õ¹ÁâΧ Ãö)+¯Woë›*{ƒéUmÑlÂV˜öñœ�yD%Èti~Ï>¾×/š¨Ä�&«ìhÞ.‰xo’åLõ¸U²YÓùÄóVzŸ’”©4þŠmkÊÿ*8Ef.èÆZ^9õ£.VýÏÆ0EÊ®iLI¢¼¥SÝ{½E­…¿èÓà\Õ9>°õk)3W{H½‡(ÆïðöDOº¬©0û8‰8w¿W‡Ù*�øx”~ð�¶ÈÎUq“éniŸ)ìŸ�!Œ>kÇ¥Ù#HÚHȲZK¶—h“3(�ïÿKì„5 ŸiׯoµÂÕ¥èªz<¹­ß}ä`Çcg»<�‘ü…ša Ó¡pÿAšS5-Q2˜ .ýñ �RT‡ KåeèöÇ74þ?&�:Œâ àHÆ7ç£àÀûœ£§^»ÎÇä‚JÀAÌ3�À[BÊ¥ °ô4¹Äz‹™Õ®Zp·ÀiÃLêŸÏA¦ƒ�³ ¹�%<2¶=*¢kZwI ÆqT`¥W:xa¶F¸Iy¥ïzq ÿû¦•–ïÍ% ´Œ¼K|D÷7ÝÞ—Rö>ö™Ç¸Åze…#é@¼$·aQ�¼ä&¹’ÒȾIS²sÉ€jû!™QÞ$ÃoOfhãy�¡qÀÏ‘1KöO˜Ír†4Qá&�LYëPèK>_t'xG޹çÙ:¹\ Å´î/çK°1Á( hÅVòJíê~¾i†—ìú`àW¿Fj.Kb °·�¨/C>ûDö11( zdcÕàïƒÚŽZ×í¤¡”é“H Ðþv¯Š9Šýp*�¯I¡b�Š&½À}ÅŽv‚ …¢#×±´âÃØpùÓ4�‘Ø¢¢ù0ű” Eºi¶Í”‚4ÂÏÙ/Ç,½fú€²ÜŽâèXsÌ»ôÆ÷€ä§.êÖè…žÝË,OQ…³t%+­8O ;h;ƒºC|–¼Çæ0J0Ö=šD¬*? ±’ÀŠj<Ãp'”ýðÿQ[a[[8­|¼(“:òa+n ú9—ÒÔÆÎ†©®«ëCËqï-€ŒáJhá�¾þý=Ñ×[aö²� ]\Ì1tô‘mçCŒGMdïF9ô¹S£×} lco_8V†¡í®]ˆÂµx›6p80>]ÊT͈\s­ÞÀòÌy›­ƒüžê0×+û\W¦ÓšFγ!‚mó`'¹fñ¨ÃÖ7: |D–J‡¶G�\§¿ôJ¶{;'ãèõü!7ªÄ€9¿UB.ðI-VEµ!§”Rn-eËÃY�&fgs3áªÆŸê´¦­|­£7x¾9+V ‹_Ôaaœ¾¾¾æß…ÿc®¿–,‡-L‚˜kEh–€±ÐoHwó;�Ím☨á}~Á¤Ns½Æ¡öø÷Hí1Žk\¬ã׿ØÔâR Y–Ç[3p@Ò|Á‚Íj²ÓúÈ­v„mW[F`ÜVôf{öà£ùõÛ=~‘>ó��L“XM:ÒUŸ†±}s.±¦Ÿ·¯ÈJšntÜ)Õî$˜äº+¿â‡PÉÁÇtõY'4v-[ÔðÆëÛK*Žì\д挼Eæ|$!ËÊCBXÚÏäd|â{ò¥Ë¡”žrnGÿ"œÅ W¥æÉ€A¶­Gÿë!£XØ>îã¬/Öpq�ÞŽ{H»J�üp�|1Ôd0õMën;±Åq/}>%½oöÓÿqÉD{xb_¬xcáa.ÌwšN9œmlï54azÓ™V7Ó˜s⛆š¾4a¨±`F·qsÉ× 5<üW³ó¶•NBưÐ+´5®¾|ZsÃ4'°Yc PívŠßO\ÃÞd_.jžuζ#õóH÷*–uCtÿ䫱pŒžÊ¶˜!g˜k·5´ 7ÿFM›Oɸˆ¨L´-ÿØmýwU:‰›l[¨�Ã*¼¯¨ÙÐpv§z {½¶lì«ß2ÎûÉ}Z�3´O#TÚ} ÝÃ& !˜w–/Ô(—04Ú‘Žÿ Þsd]”v’'JÔ|JW=S_ÖXPÖeµXí§�£6 ;JjÈÐ .Ž+,eÅjD7’À“ǾA€8¼�°ŒÙ-Åkè§™ÑÆ ¹€Ç–-¾…£  õ¯ððRÿóØ{ƒ%¶6SOÉ÷Ä8ÐÙ*Ïô‹ð ¡-ÒŽþð H¿ÇJˆ¥Ê5È#رòeC :>ÃÙU~Fð–ì3gAN¢äסÏÐC’�ìÓítR«8&ÈT4Ãìq¼“ÊÎ�nU<ÈFJIRæŒáu·­ Æ5 J`ÝYº#êT=³¡â½ç‹fŽMXáP!Šó¢‘U¯¢œ¼ÝÈçÅ$äzÂA‘ÀL�WÚË늸˜[²jø8ßìœx0ÚcʉYmß�£‚uǨÕÈù/îR»õ÷ëË ý_ü¤0láÉc:Ù‡¹ä¢üÿ–£ŽpŽ ëýÙÆ.Üvó�ÈW�é:Μ«žâ Gl'†ÀòJi¢CÉrɢש½‘cT$°HziEgÑveSU׊ Kî#§MM^Ô·›K®A¨Ù�=øtX…é0KéŽàqV5“΃×ì d$çã4±PƧ6¶åPUg �-ZD¾Sõ9ké ŸÃhžÀ/…@•&ŸgPMÜV6zu×wˆHwšÝ+‚ç×âmóßžsaÌ{6>åK£ Àì»Ò^»d NNBýÿkõ#ÖµxŽŽ*Õa€3º˜[‘(ÿmøVy5*âÉÜïdW@Kê‘étÿò…s’I3[°ŒdÏ%QC�iÔ0[Çð éçÀAšurèajÜç:Ä©¯*ô¿:L�^Ï<�$¤ååmÅüÚµ±÷1D>—©²;?æ1PÊRŽèû}/·‚V°±Ôf™å¤–¹vyçÙÚÜCµÅ¼:S’´ô¤&…„Ž¡óu\2,JŒ?sùò'§�P¶wÌ%àÈ‹“ à+­Eò|F1�SÙÆªázgã[êŠåK¹Z½Ÿ•ö\„zì*ë(*ø1Z7Rõ÷.ÊNýËà³£C±+œ'ÓÒw!±ŽÂô¸4a»ËØä "‚ºœXpc¤FíoƒØ@1á;é¦Ç)Õ&h¼#ã"9IC«åu<»”&thår= ÓDÔÔão‘įÎ×ÇÖ:‘ šŒ‚98Ê Ë—Oº`4s�©¿/Üåb~S‘~¶zC‹ˆpâ]Ð_šm€0éÒ2Š�/  ´ëó_Ô…!½È¨`éz*Á=,X)Ù4—¬2Û<òéÞòÆÞ5¥óéÒ3%Ës0ì`-§¤!ÌКãÐ̉ÉÅÈÛŠ«�ôüá´M”ǯ9–˜‹d÷3å;A)áFç6Z3Rt:Tò⎦ÞveÚršsòM 2SU”îà p.g°2ÙEÞŸÌ·üí}™©õ—7ö7ÛgßõŽþÅ`äΜ*¢ˆ+Rf+¦Öa¯rÁü‚3B�Æ0’Ì÷èAt oJžì±e|Á`kàWƒWx¸SgØœØ[Šñž[k¬Ý�Z1TøoUÜ«˜ v~DH¢e‚×”5BZ|o"Â1¤!¨iñtP*Û?YF¥�s ží{èÈõ¹Q dÒc{¦¶×÷3¦‡Ò<öÅð¢\üþÚ蕚[Ã�>¸6xer?¤ø“‡ô¯j%H�§æ7É"b\Yœà‰¼5Ä´_�º^PÆ!8gN?kýþž´ç¬I²:Á0u§©©‡õ n^&‚ äïwôœ|T+ÝÆ£³ßb-'øWÊOw¹_,>áûJÁ…#ܨšX�Fx/™êá’¹N¤ƒö4~Nõýÿ‡xõo$áê9SýÅÄre3ø~™º”Ž¡BQ¸¢×[qÙÎûò422Ì@fn Fö¼½‘�{‘é\‡ˆÆ5ræž2οu\­õ²VÖ`äɵXîéÁd!÷²^Ü_Û*)FÃæ lêé›ô˜CÐwÊú ,Æ^—±Gï½sZkw3‹åéÝ^ð¸s¯×ûySû¹*¿�\\U��Ì�Aò+õo IsÔl  }¼êÕ;<ã–A$»ûÅ`q(ýÓûˆ×ôåö]z£¨{È àƒ ÅF·SäëÚ+®t„¥´¯Ù„5 Ø/ßYnL‚¥C®êhS–.‚z¸ª;Ýf^9Ñ/ q•vü06›Ï0î¾ qý}/�†ÚF˜ü[•„ÖZ \ëù9!c¾šM�ãÝb@)@W¡ãuFz·›"¼¿@Q,J5Ne)Ëy¿LEvüôÒŒÇÇŸí¾˜¡éAì;5ªPÀ§1ÅœvEg€Ûž”nGÿ"œ¡ã“î-hqSůÒ51Á­ÛÀá((‘û¦QUüc“h�Ù,­|¯Ôÿ6šn«�•"ç¦ôÆoý¦¼åø‹Ýáž^µŸ÷XôÈqså„×`€/ŽŸjÖèÐZ¨¥�dÒ6˃¨©7;ë¶s‚ÉÓ™)ÈÐx£éõ"‘ ¤•fƒ[Ñe“Ôuƒ}Чü`D/“#úÃáÎ9õ†Ö«Åý[é=|HqûøFÜ‹h‘ŸÞnSè«óáU+˜ŠÞ9.õT¾@FGQZ>Œ‡K|OЧû1¬-èßúÝ0G®Í†ÆB¸"7GöÍ”yxò—6>Â^eÿõ¿ÜHÅ^¡U¢ˆ€÷.;n|@×L}ø¢þæxs|b;ï¸Ùƒr¨ëŠKlfÝæ²‰Áº/)0K—ke‘ô×ðC-©„¸qá]Œ¢· ¹x(â;‰˜gÃ71yüŸgs<9¤ ˺V6âo¥ý5†K šåÍË݆·XžM[÷Òn†R£g¬ÛLMÿ˜ÖЯÎ4k©CΞ„¸âöš>¸mOŒ‹}¾�«LöÕ€´Ù„5å~nU£±ŽÌ?fÐŒ´*?î(A–iƒà›ˆ£ÒP1ktja2+ᇟ€"Z4'XöŽm è=v|,¯¢C �g>vÕ»´×`pNÖ;1^ó8‰¢�͹oò…5adÄýhXÙ�»Æˆ4°+wçÎõÖ%µðµ&�Æ3f‡/´¦®üs¡kÓ7'{�èÅ,б&Ë‹Å+œj<‡1 �0~.ü¨„óê¿C#4bn€j©$/™ûõœÎrc®–g–¹fO”1$(d6 ÷”ålÈél"‡9¥6ÀÕã£$ü h3MàúñØ3A VmÐ<©ƒ÷‹¿D…¼ò�68?íº-бz‘E]±=Ñ6’ýÙº£”“žáÂÃøCîôtì¶í¼“Z «Ó.âŒÍk`ì­�¼yý4CóÈ£ájæ>sÂîT¥rÜd,Òë®XÝ�H<³¹p'jÏŒJoî·�µDF6.�, Ÿ#Å0–„&⪺(hY‚6[6A¥GR cŽŸ§¡‘HYý-WX:†¯N�ÝëüX=Ëf—$:ÅWè©¡Nôêú^[He­³Ÿš.@ß`‘„Ë1‚b�x±Dpz7ŒCÖ2 ¿ 1ó_#HqÖZÀ&D:«ñŽj+ïUó%¬lMq%ëksæyx�ç©gÓÛÿ¡Ð—~ø¢–„tZÄHUÆ@)y Z«Ø º Eƒú+¾»ñcð…h‚ˆhÖ€õ±4ŠAš—oÐü½-ñ±e?Ù'óãvÒÚãWUò*ã¿ÿ*¡nâ^àþÔs_æ"JïÚÑÜb6™iµ®UÒ?Í\'Á•%¢®%y|ìþ˜]ÀNš[ ÀpíIso,"š=L¬«áÐK)ª"qî®KB1ïÓ†þö„Öþ#7ò½»ÿXævyÄŠƒ7Ã]"Æ»ârÀ˜ÖŽ!R0ÜÝb¸<%½.;^¶¿YuÂX‡ƒì„g µ�Ð3€ÏOÏÖwêØ«j§­ž9 ¸$=›PyOïÒhet |-E¥Þ›+šJ…w©€:]Ô›J€Æê�{‡æYöEãÅ›¾PîŸ^c Ÿ‚ìÿ�ǾX�a¡G©åªkÍØü« LVg˜Ã§L.sâ@~̽È? ™©PÔ5UóD%bŽá¾·‹Þ„_F?²[›®ÊŒ—á~WgDEn «ÏמDëÓ&%ü®w�Ç]fA3Åœ8üI£-§1Ïðq¬ Œ¿Ë ¯‡÷l“x7Þ«1)†6—NºÓô§'ïDA“œàW� ˆxžó¹ñ8�×!lm¾•F[Õ7v$9úùd3 ½§ˆq¾&~¿@Ô19ô÷ÑοXÍoÐ#Q"bg‘`/¼…ʌޓpñì窾�­2®ØPû€¸V¹c&|jd�k÷ZCú”Ycþ÷�ȶã-%H•¾ÎÌŸN3ð83#“9œL•–D8Ñ—X›Ýv»Lù~{ñ_ú“Jô•žf¿ep8…CC;_ˆÊuÑ Û†m-T}¥dõzb¦°X�¤‘ýè:‡ç=:•ÚKpP™Q}lãž.¤ñž<õÃÒ=«+E(G€­i�áj] ôÅ·x5ta³Ä!�å�2n‰˜=»ü*có tŠͨc<¦é¦J�AÕišÇpdaÂ*g²µÏ3iÒy‡%×oh¦4}ö¥J '²Çå‘Ë—þÅ$è6¹��V†ê25Åá ¼“-�kV´éóg—JƒTZ;b–•ªŸfáÀqh©åë›Ý «iÍtÝ�ù’ô)~Øú<ÿñª†Óز¨(À�+ÓÊY9>Z­½[ÍÅ~ŠãJ5(<Jáåÿß=¸¥L¼“¶>ïQ™SmßL·FN4p›ÁaÍ tÿîp ©–áhÐŒ£­><þCI~±*Eo^Ͼx<™²u2Jî êÎ}å¯ ³ä(í¬¹àoM7Xn�€¾é~£�&ÎH“µ¿Ö¯rž_œIñy Ö¹¾�ÿ¸2ÖFEQꊀ$ÙlÞŒjõ]0ˆœ—²AÄ ÖŽœy*䨅ÝMä±Òâö^²K_`zyB+Ý Ró"ÕnƒðD†d'’ÔIŠû" %­8pˆ8m ø@sOƒL[)~+“¥ü?9í/]„¬ëŸkÙ«j$# k–õ—í¥¦¥!ž¶-?±ØÃùøÛÎã$% 6 e¨�6਱ýìøJ±,…÷«5Ò�±^ûšàWw.êçè×Ìû”9‘X¹E«_WLÅ%ê«ÿÛµ°Ç2ÝÈ")îPð$³Zª±1‘‘u4>£öOks WDqû¬ãz�î}‘ Np3nuå\í÷TU¶/Kø÷¤ÐðOîè![Üøÿ^_ÿƒæ]y[�´“á¿· ‹w/ £ÖÚ¾¨1LÎrd|˜¶„ >.þõè²?wØ A®ÀŸw"ÚÕmóZ£EìåÚL·(èDÆP1aåƒs—’©dŽ´W0}ïyŸÚÓÐNÈOÂÇëõN¾±&ÿN_ðñáQõƒ[–C‚€ QVe™ïTeYÁ_tʳ¼-gÁ›þ�šöŸÊ`)5;ñ«åsÆ>9´®,F°Jâ)ÐâøÚµ~Ô{žµ%�N‰Í‘!¯'ôZ¨% á"ñ=Yþ¹}ÚÈ^€..»p®^ �ÿùÜlÓî(ÝäâWY×!vyúõ;q"ÄÒÚÆ¡¹6Šø³áÕ%3 HE² N‰3S1çqZ \·|p† †ÉòÎâ¶[gBo�,Íǽ ˆÄI�=¸oESýㆵ03`¹ÿRû¢ùˆèÃ߃|yü3‚PR!®`iJÀGÄm$3o—I”Eùo‰« VÇËïO;X v8�ìŒzgÊÐ~)™I=�×O«rË�ê’ª¨ h×7V1žu%@~(�¹:?l“cRhœÌÑîóä4úÄþWg2Ûÿý›XÝvòM aõQï¥9™‡›ËB3ÃÂãè „^ºÏIóä;¹µT�Ëísö€î_·6)5 ŒïnÀ§-ÐÆ%`S@³fd$"kÚTtÇñkšÇ×ÑQ–é]O�ƒíÎT]ã“"0N«ÍgHƒÁ»@l¥žðî:êý[¹�‘º¿óžÐæŸ�•Da…�oci#sCëÝFãºKÚ(gìvæ|—Ò¶¯uÑdrga{ÅÑýùpdøw8Üdê@7þçèxþR2±Zø³-ï|sÈ¿ôs¼àÛZÖL…P»Ÿ¾5�e‡�yîRåu Gò¨vå^€Î³¸d¹�½e?é?ÍÝrö�ùµkª ¶‹Ñ [±¥¢U']#2ÏÓ qF›+�$[=òsMOÐ qÉi¿46vš¤ï|÷Î6ü‡�ÚïÁ¿­m ê—ÔÌú¶k|yº×JO¢A!o4–F|Ó.'}�&•‡•0G†Ò˜©•¿Ã|62šÔE¶UέuA•�H¡úma Gﮊî  T$•Ãïkpñ³ÁË  ³Ö�9¯í3TëY´×ñS Å5o ZiA½ùd;à18c�B'q àÿ~.«ôûÏÁ´|É0xAËŽUW¬ÀÎÒ�·<öðÛ?3ÑM{˜Ï0M)Àȉ\Ô'`ÖQÔ]�ÙCÕg>É…µ=›©Ð€»�´Wï9õLsh“øþ×9Ç„Xƒs_xÿ$ÃŽ &ÀӇݹô¹3�Ÿ–¸ 0ñ\Ô`‹~0Ñnå ¶a_N ÚÌî¾4Ò•¬ê< #X ÍèÂÓ!õQ­Ãœ¬ª�üU¹¡2‘®@8Æ ³ ?ðvðbÿ- Án¥fOu±}Çí,^úɇº#t|ˆ¬c\\ÎÝRcIj£­¿± øú%Úíî”ê\Ùü{P@ #®*¹'—±%úE@Õ PSQ“»¬ÜMF$ÚñŽ 3Nƒù °ÝøµxßæóúÔbQº+Þ�1Pz-ç÷. ¬oMY0]– LÅ€yæD~&O>"`‚ˆÒðw$(Eî÷'§êS¥xïþpÙE·ú3þ­ÿ- ƒc’êûµþåóŸ êÜ�¯× ¼°ZLHNµLÔ Ïq(@àLñ; m‚e"ƒVtÙÙt§pÉ< p&¡— .�7 yšÛW+ˆ»4�>Ç%ÅÃî�zÓȉ!Í3£üc½A1ùãK%‡7©+%ù�÷Ÿ~j÷9?ÊDŽ|B*û*¥ŒxJÓňú½«)*¶á²ÕŽè½dcL˜»üÌ?¼œá²Û/‡R<4áè ìe‰F?à.`.¤ÿUáUˆŸæ·гs²Ñ²Þˆ|$=KùÅóÌ2)FIÖ¤8ê(¯m ä뱋ÅoÇɊǽÐÈs˜ý¥ÇÕaªKy;·'жêsVFƲ—Ssàž’s3¤�ÈJú7E\Ó¬IsH½DrÏУ×3„훀5hÈg8%"> #üÚ”fÍ‘Ãûtù+ˆhðÛ6¸¯V…'ë¤ÄqªòQ†F&RÔ¾(=°³ˆñL·à,Z�8…�–@‡¥}ø;G1ôÌ: ù-�Ã%Éàî�©µ9·…oC-žGdþ]»¼ ¦¥øÇqobo¹zi)ˆœØidf’Þ(Õø ™Ž L×/‡……o%‡ \ËÇëmúXŒÜú€åQro•QƦõww(h7QÏXù‚rÙ¢WÖAq,LØh,ÀÛĦZ?cÁT:öÙ– *izɇ¹õõxí©Öú‰°™e iQh¯Ìï *|B•Ô ½U"?²Çí�éaõ–ÁÌ´Ž¯ÞB'8?æ…Ò¾‡ãnŠ—•â–·‹\Ð`/�é'¡› #y„ðz[¿�>Ž ‚wcq;�> ôgô3J%j´û‹‰ YS´2¯kÝßì5ýÿ“ûF¿ÐXZb):à qϬ Í™š†©âèFQV�&Z9 0¨I² YQf]¼GL½’$—y磔§ü–fsÍí¼\*3XÀxä¶¡qÅ¥’^Úbûmº5ø›Q¶yÀD4¹èèàrr7m?ê?Ž]ø6 cˆ– ’óÈ�2&:á2s :2åÕ—�ÍL3�ÐwUE!ݽSqí»½M÷³D?Uþ¡€lÔB=+ºu1þ(Êvß…\Ú¥ë`ù?ÜÔˆ:|ëƒ5· ÉØ£4‹ö&±ƒ\Ô`’éY1¼ZuîZÀÂÖT~5$í•´©î4û{F)ô2æ¥ÿ§pæ ÌÁÓÂ&<{ÄCKîÝØ²“ðˆºM«Ë@Åͳ[¨²ÏJBj¦q_�OW¨R_ù2Kâ¶›Pà@ΖÒ,Å—?Öœ€��H%‹aé§õn¬;Ò�\x¡‚àœå�šà‰ŒBdA¨!Ñ*vüÔVôÏ}°2 ÂôЃÏ J‡�DÉå5D ü"Ž€Ý}·¨N°ë¤¹@ò5+OcIÉÂHì»zèýÎ×ý‘ÒÒ¼|x² $�7¥;뤞YËñér¤Šé‚bŽxa9\±Ôz/PØ;”„]/ä™jª4Õe�5®­ÓìyÔ¹}¨×“,ÑSØÀæU §,tØÿ�¬çŸVà^5ž\PßÂ[‹´¨ ?~¼}¤M »‘ÌŸ(Ý&'M¼$£�gM«‘•jÚCë‹ý¿ÚU7¾¡¢$ú¤e;lç%n{‘ϲóÁw†Ý%MLÞ¯,ðqò P$ôÞo–C®oo{Âÿh$vZ]hçfþ®!?’’¢{$»Ùz$‰õXèüëo.A�F ªÉ#« E|¼ãï´+Äl[zâ¡ÜÇFëð8x™:geþµ‹ög$Tœe\_‘ «Ó<Æ’ÏMxZÒ”J±X\¾Q¡µVÛšÌrö6ùlåaãŸõ4™cÐ2E jÞ£*]êW¥jP˜w~_ÜP„œðܹ îQÓÓ%ó ûŒUŽK~ÒöZÚ¡„#!³Ø*8õàɧßN©»ÚE³Þ¨�ã}˜h�ú4›ò�£ÒR£�`U}hõ8ª÷‹TÉ�{–.pm4ñó¼›àK½¸p`|k¯,“„8œ_×+í�ÚŒÄKàD tTz�ÇmÐ<"Ün‹ ù]Ää¥Û„“0¸7•.¥Cóï¢Y?hMWÿçBë¤ç�•6r(9Çt8/Ÿø¸…ã‹› ƒ&ï$ÑUîôáæh M<÷÷£‡z”u ¾èŸµœ¦©Å\‘¸†É𢗚˜A“fÒ¹M»Ý‘V{Œ‹¾$Q)MÅŸÕÉH"]? ÿ>Ò>Ü"s»êuŒø}o�†aæ#ÀAø…EɬÆûÉ»ØÙw/6ýqÓÇ‘6p-!.ZK¥¡ß¹©½„)ù0œœÈ:ýb kzbSã•\ á[�¼IŒÿÃøÎm콋*PÈ Ïh¡‘#=Ù”4YØ™‚óÎèkˆè5º;®4<˜iÌâÆÿ�5˜£¥a{_šŸœ‡+XÈo{Ùìɹ\]ø àµ]ì¾=$ñŵþXõ \éAß·»‰*{²ŽÒsì²Ç…�-âäôp éÎÝqŸâk€r6Þ¸³‘Bǣ ;Ž¢UæÕê|1´è¹Vl9oŒykÉ•—êPèYª†Èg¼EhD¼Ø€P�}Ùí�J�бÉ"D"a|€O¢KäA l÷ÿ•}LìÀY¼�Ñ¥kkÿïó�iÆÿ¸çË &w¦"nÿ•bŸÙl…cd2þQu 7‰=»ÆÉÞDƒRÿY-z4TjfOm:ÌõåsÂ¥uȲ¦h[=þ6öûÃ9f?–इ/Ö×~´›¹�KK�±bceªËVÅ…Õ {MµKG°Öü—›¯�?àzR)ù2‘žÎ„"ïyø1(Ÿ"rÝ}Aš¼L®ÏkKØ5uÄH(Ù‚±©àÁg†…cö¢à®€|®DQ™dûâ¯k'°ª „Á{ªÖ»·«�ªÑB,vêðn4�ú´FüV "×ï)$t ˜ÿ?õPMk½‚E¸ý1‘º‹¶]ƒO þE%™Ízs”£9ðj/ÁŽ ƒº¿è¬ˆë /ÀQn¤ù¸ƒ«=âÍó6À£!ýK_Òù˜³å%è8:bÑ ¦1X¥CIXQµbTWÚûÏú<ÖÚÛk–SÜŒ'0¥…c™‚ Ø„û\_RÕ šçãšô#)<¢˜ŽÄ\@Ak™4YјfŽš¿ãÁsô"û�_MLà²|˜ï;ð+q µ÷cXEA�Ì׆7¹�«~Åͤ‰h]\[î¿ûf�P½4ã4X‹ ÍÞ!±wL›1þZ~ã„ÄÚ4Â=#ˆ§ü'ͯgç¸àâ›”¡uˆô<îò3wÇà\'hà‡øظ&8ý²FnõšžåDб1³¸.’&.Úú"Áj²O=õ;‚Ã8 ¦±V>ï-�Dz ÒöÑdÈÅ(j9Çý�Û=¯ðV¯…ÑTé K �esŒXíÚš\á¢à·q»-~�†aªqd´Ò^˜}Áðaá{‘ò‡¾Í>F€)+ÿúŽ‘A€8ˆr[é—°LD"æòl­:‘<„œºcõù±ë"~0+;³›tÔAØ/�»¼ögéÈÆ#ô³õPþ{Ïq®¤G]üÿÞ) k­vQ@M¨Žv.k/îÆí:²k ¹FH2ÉéiF«|òáŠ1x׿ŸÏ q2ù¥“œ¯Ä‡ûÑ 'WD1jÐ< * ²ß+‚R/Q-x™P\¶J¯!è¿[´òê™$)ŠFf¤~Lì,{»^ò q0{îJÎú šŽ2bKq > ø…1®ZüžÊžÎ¢VT§Ë‡DºZ®ä;Ç€jÏø Pnç­p„kÎÁ±Pd¥2Œ•æg~’Þ†Öh5.ñpŸ»å¥Éj??Måt_×~0V,É%GÐb0‘Óè":†çÃK�ˆŠk%ŠVÔˆ�üúsÂ0Ù%{…ûýiàñ$[Ìåˆë̶;'×4\-ñÍ"Ö¿Æ÷:\/``�-ö=‡ê™ß(É\Tl'µ2e“Òr럖-¿…Øê9s¯Ä{kè”e¢½|ìH±œ ·~OÇÌë3÷¶„Þ'¢|€ìFó¢ãÁù ¿§€-&þ-Ô\¶Ü6EÁPÝÇ tzËi{£¬°1Ó/~Y&ã9Æ®Ž¬�C"ÑqT¨v‡ %$£´Ô1{ë‚ë^¦o–šœ~bÍÅ>J­èEŒe èþ¶]m@Z~6#ŠbÑ ­qlŸ¦§¡|ñ‚˜ËOPGRö÷=‚ m6Ì„Œ Mâ™p‡V‚‰òžÀ>²ê<-³¸”QÍ"n#¸¢sK rÕ ‰«åÜß6ÑCííw© Çñt1+ž�¯Â°<èr£È*qÿý¿d²ÙŸQà†}Ip5óã—KŠ`hk(.P?Á ;”h.û™%e µÅ'-»îwoÞs¶¥T‚èÐÙÄ]WÌzŒÆkLÑ.»‡.Y 5}±OÀ‡¸Ã1OŠà¼¶]×ô²öqb@±âÒÒD6ÒGó…jŠz“ˆMd`$ý¢CT¦„’ÖQÃÖ?á=�2÷tmáfn.¯1™ÈIf:¬ ’Ы_ŠÕ]býãQü�%.gfLêTjȼÆzü ÀD ئ0NbËç@ˆ;£Í˜�õySR¡õèì^t=Çš‹ÆZ7º.ZßÉHp{±å‚u¤ç#8t³!P¥»Œ´�ÓŠxF;æöäÚf†ã ™qžÓ¶��“”8N„:ŸÅŸÿ¼‹ú ÀW -6&UWÀ²?q ‚ë.Þ! ç¶nAj{ ŠmB¶hañØ�Ò•b¦ÿwy.�& /gˆE[Û½(ÝppŸÜn;†7@WRtûð•ÖT“JÄÂoÒ�ÿ»9öl4ù{Ô7Ò­%•áÞ¼¬P””"k$FĶQÝÊsáJd¢Êù[ž?0*á¹Þ»í1�èó­÷[P®.,täÉÁ9EðûcsoÒ~ž”2Ì‚ŸÙ’’%�×f¾Sð5í�jœlä¬ùè]Í1t¸=‰Á\“FŠQ N«�ƒ"c¸3ýlv2`P8ÒõO£è{JH G¼HÝkŽà�R7Öü6ç“„@™Ê§þü÷†ó ¬Úß�äjöƒDÌB¸¦½­ÔQ­PÔˆ n=ÙL†¤ÓÆy#*¤k|Ÿ•„ÿ~]mã>l²}�ľT9å* LUÎa§aŸ§ü‡ª›ó%¦ʽ#�0mÔºˆaçxÚy˜†÷ ›¾aFs7®ÎþÅÆe<¬Á¡·`SÔÕ¬„KÁœ=;ÔÆ5}ÓÊà�š«çwñ“w&4³¸ngÅþÎxÆ/iˆZö÷"¿°Aðþ_˜õ�Â{±ì×€²øŽsämö)LŒ÷ Dã« -˜ZõsO)žÌë-™»bóÔÈF.Ìãû|´ñÑ&:y5|yn Â\Ã�G¹áoŸ�» 6«Eñ²Íõóì¼Ü„Ž�$Ú;À”ç8E¸x1¹—É4ù¢�Kwvö‘^ŒÁìk# ¯@¿öéXˆ�, Ù^œW¹Áô2j{éB/ QC²/A`˜äÎø ¹+²'jb÷ïO &ÑåZŠ·½5£®ÌnzW¹†Ï'Zî~È ÆúÚ7Óê qˆ?P4²å%b¡y麕¾¡ÐÞVÙ{u w$#z]\DìS+W åÔkôSŸ4É—·”„¦´½°ï›·Ý<‘9‹š„¸„YAl̬„ïN*~T=²þBš¶™ƒÛöa…%F#˜fV<µ 5ªk%I%E†;œHïéìÓÿçÈ…\Þd²«C`Mëï´n*qH8r-mî×ÍÚlêWã>M =U†Ü :æù “Tƒ4ÂÛO��±Xvœ´cöt�ÚõÐÕ±hþ¹÷?]2¬ ¢×x[ÞÁ‰Ñ['n9ÇÔ"Ö¿Œç [VŒ@qbSÕ»÷ÛʪûTG 2Î$”[‡Ú"S�†:6Φß&ºÈÊú"0ã“lÆ„¯�|ÁßHDQï,‹µ,F5~·M¦ÔÕ5 @c‘î¬â+Í…òLUI5³+ð‚ÏÎãg¡ÄöÙ€ÏùøaÓxÒë…� z(y›Fý¥?™ë}9hew¤!kYÚ øÀÀƒ·Šˆ�#fX0åz…‚±Â@ ê{Ç,Ô=A‘øæ'µQ_p%}=êâïêëÔp•Éø¡3e¬¤¦,ã@ÎBûq…%þˆ�Á&±ÜOz¶¥|‹5®J/¥p—çØ‡| Úʤ"/Q�t¤xó®h(ŠŒ ‚Tê[x䘓~6raNp$Ñ­î9=løàɬ'‹âЭ•vËA‚[ 5ËB\¸ƒ<‘d¤W¥”úljf°=¼fpq˜K¢ö M©W¤ìz�Kä–9ýý§n"Ô6&Ÿmu]P�–qb¼£ä|K?…‰ñ®ú³A�̶ηýþÈÑ”è.ó‘¾Ù,èžÔÖë¿àCN€nEV~$ÿßKÍÜ�ª‰J{<€bâíÔbÈÓN¯ ,¾²Ù¡}ÀA¢Hrg®’¤ðï‹Ìê=ÁÕm¥÷šã+6´J�9 ’ëuo)¹óÛßëÿ¤»>t–9ê÷ËG¸_]g“$áçD=ÀÌQV=á‚hüû#œ¯n^F¹T‡V3- §4Ü¢‹ñQ�-h¾ûVÇEÄ,ræf•¶U¬Š�†¥TBèVÜn�›µJ¿æ“ß›r÷‡r±ŒÇw°ù…¡¤OJ讃Ðà,jïhþ†¢dÑ,qAZ\i¨DQ-6®.{�(O›…Ó'mWa+Ýü ^C\¨FîêÐoì+rŽöpéQQ4Ôo�Õp¹åH NTº ÖòË R™n\C “ÇÇ¿õ£Œ“ò´Ã¨íÌfZÈÝÙãzÔuôÇiA6Û0´¨ÖÅBæH0`%ß[DKï]Íâ—B$ûG±SvãÝ–#+_y|—§½®•(1Âÿf 1µ˜h¾¿¿oÂÔc T[%¦Íþø©†œ[_©kð�¢“v¼þ³žgçXÿ˜XJÌóoS8Ú«<€ E>–Ì3åé¬ÅB9Qÿë¶·Ox*ô…<‹ ýlÉݪܦ�·¦-#ÈZåð¡©ŒƒjQ¯è^�´J6?(ô%ã,F˜Ìæ8fÉöHÛ?MÏO[JÈá!Ù4á°=¸T¦ÖÊ4`^£|1 £ü8Ó”Õ;òÄN‡ß¹ÆhÖÈäüI0wl3¾F€íÿR®×Õ¯ŠÎ€ÓÃ8ú†ÕJË„–†ÒΚYèÀEÜt‡b@‘VN\'=‹;GÀ¦À’Àðælˆ?j~�û±sOz.+póËÑ ¡˜´D’ŸöAƳñ�&ÀÔP«ÈçåU(^—RRhYôf¦T�üC ôåsõSÜÚ·n›1sôVüz÷Ùu”Zyd¶ƒ¶©±pö-­;Kï"¿žNrv¦­^ ŒÓ5zÝY¿:Xi«¯‘Ô‰°©—¯Ð”dê�AÆ?¶{¹›„å¸x ­R¯YdRÚPh¥Éî`¢”�5¾ëO9óqó§^×2ÖØ+—�;&{»Ô«ÅšqÚ²^K1Zbßµ¨@©*FWV«·ú_iNò›ŠìU¨äkLâÖCh''Aéß­m{Ø$@" í;·v‡žZTÆ6PW­Jú€ £ù‘jc-¼Œ�હy#Ì´ ðýãc>aš§õqšsŸÚŽåÿå@ ©¬yÛRz€LÊÿnŽ�ûºP�Xu)sD¡ø™ù„¦¿Ó9�ÆhüŒk©�­›É Cìù¹4[*G++àÒÛXH[ â&Ð ª�MPÙ%3ÉÑbv»§©½ð]Kf0^uaÛEšk-'€sµðYº²_PÑeAîù§ŽÞ¡Í�`Þ¹8Ú ´¾‹¥Åñ½Ï)VX�j]íu¦ìx¶ô"á¢Õ¥lcï��TK¼M߈À¡Ä‹t¦0dâ…\y<õÐ"hL¥tàþÕ¸W`™ië}Œ´b ë ÕýÐètâ„¡…ÛǪ*èhsè÷ª\]¨DÎ4å1ÿj;ä ‰Ùqú¡ÿ±'� áÄÁŒ”¾î†žÔš;<íx0HÔÚdÙécE0Ù¥öb�Š÷éc,+Œlõ@zÝ"÷‹ìBL�ÜM©&\ËÆ­´ v#Ø@qà”…gÈ!çôa)’JÞO3JMtFVVÝЄ>„é°Qq3o3×I&Òû¡2b�~ýK1#5G‹øA1û-à¥3~j ªdå¶©¹žÜÉNt-Š©eÁÞô¼ýèñƒ$ø·£ÓWÊ¢¶àTæ )AÉ=¼�„­ÂƒR74ñÿÐ K^ÂW”Bæg$}FàôÌYÃh3•-¯Üȹ š¸3j q¼yáÉß<)VW†®OD;ؼg?+žÙ)Ø"5Ï,ª�2";§6é™çˆêuË‚9%EÚÇ[|¡põ /¦HjEns(pŸ¾*#&V Æ0|�]šì�˜1£ŒK©ôÇýsnÏ-Ô4†®kàÚж[YÎ\'Œ«]r(mÝæf‰ƒ+ßU;\ö¸Ñ3?|1 pÞCrÚoV‘É%"fË¥®*›*~mƒ&õ�êQn£²äâÑ`sHÉéåçáù‡®.çË-¨”²ªßB´ÞíWЭ|Æ#]ã\FpNÇ5òA“€TjÀóýôþ�0Ð(X<û¿òw‰¨³A †Ã•˜Íª$âmŽ‹,@ûkÇÅ‘u¸lÀ+xP(Í=À„KNâ}šež˜wXzÒâÃù+_ONs»i«�.iI·^ÜŒ|X¡êwÚG §Øðoá²@ˆ“�øcÝM±Ý(:zU+šËÅ'ÿŸK‘«nï㬢Ë6_�òXX£¦:‘ ÁX‰j¦î1JNá–jk; /Oñ‹ì¬ÈP˜‘ì®)øíæ9JF§&Iœº1ì4Ýëfx”V‹—r@FHÚØÁñuiÒ1æß€ÞÕµE4õê+ÌšxË¢x,D0öLÕ § ™´A’Ú/z›–7”/¦W§ãÛð±¯#œuEA=ýÑ8 Œ‚˜b a:¤ßû‰7!ï²�†~/Ó�ìáåJ$ò?£ƒÅn.Ž'H¶baO�G€×2Í{˜?wÙï–ÎC‚ %y7–,R›&Ûåªæc%�RuÓ©Oÿ†‰�dnp´ðS}ÆcgJËH=Á5ãÅ­Œ©}GLœÁUìŒ~ßîŸÿáêeÅ÷SqÒýPH½/Li y¶�˜Ë·ˆ<žçÛP&Lßhó÷9Æ__ù³°v¿ï�Ýk‡3j8Oýz7ég¼¼ >,Ó‹E�“oiÝŘ•Ÿ$Òéí¹@”¤¡Ô!ÈöF?ЗÊ8Ì•£¿™L�pš¾óB–Å�8z˜qW–oCY»_@ƒxeÉ{¬–?µ[p@çÂ#Ó´ {´ö R3}g͆?,"[<Ú›+låðˆ=�~¡½IÊï¤{Elææí§b¯rBèPó ¾À†ëde¼f¢^¶îvÙ(.(Á?Ô„Šˆ°ìÌgø«ÀKèìÖwÌuBG¬?é Ц{ëmò@;õ0©I®nåþPô1÷þ•sÒî…û×÷"öxz?cî¤_‘ß(‰ósœ\ÌÍ.Cså7x—Õ6KO ×U¹ÙÍ!(5ä©I«ö(Ž ª*]°J„àX]ì Ö¸T®-aäf‡G>•¯þ°¬AØPlVYn4¼½;V™#yP˜PýÒë"Á <÷WçQ"ô^|®×ÅwÙ“ŠÕzòÅmª^û ƒedõA]h¶ Ì»À9ˆ9ãeN†×â P^ð,b£çÆ})«'\MÇ¢yž„=â•7ßñ&Ì _f–®•3Æ®.ÿ•-l®ÑýB€~§ÃH�3ðë]èFkdòž¶.Ò>e}z�XÕîd¶£F¹¡˜ñ›øÊ-0•Q¥>;(â7Hú6´^.�Ï-¯Xñz �×€Üv¦ý�VŽ,a‘Òzu ¸SN_øè•!–q$»EŠðcÒŽ¿³•â}ÌÛ‰sï½§ïÔ²Jä¿«*•—¨UöƒÿÙ2¡°-sS°¨|Üg– fV¹¹yšC)¼Õ dvªKž¶nGÿ"œ$9º¶¥QÛÚ÷|ìx¬Ïkž½±·æ‡ô,×±ü._DéHçô'â R£ðôU›ñ”áíLªJ.(€÷6NÁŸ5:…^gP kO9Öaó†›n’™dÀL£U¤œót"ÌP'ûÂŽ-]¬�Ǽ箧dŽñ÷ëQ3Ê%*™c}z‰iÄ#kû£Tüýš„X,÷«ß•ÜZ�Œ*°Ö:¼^AB¢«Þï>î°ór™Ï¥ó±Ì.ù÷ô‚-:}&äyÜcsÂoßgð+mÕÊ«-O’‚K(iÀ%2XzLÓvÎÞy›ÞTjº1°õ­âº)qP¦¾í6«…J܆é’å[u¤-»�‚ø¦-›aà+ÿ‘­ãÉþŠèƒPM3íåïä_¿Èü·Ç뉙٧ùÿd'�k·ni©>Í”7s«Ø|þI6 ‰t ?–üã\°üÉÈÀv›ë¬;n �ýØœ¯G6Ý õ¸6?#ƒbÝÍ-ÖKŔʜë¥í¢Ïl3Ôº2¢NK©©Sn¼~²¨b²}©/d›ßcZV¼éÚDÀÒNS=™ü6€ôc8Ë*BKÄ¡¾4;ëì¶q$_Iç'|R\�RzÕŸÀß!ŠÓ~~ÆåÏ »úöuÌW!O'ddr�êAÓú¤[ׯ¯+¹…<Îã¢{Z¶^‚ío±ùÀ…Á´»Ž. B<£º®cA|~ž .ê %ÍpÄ5�ŽÐÑÝìºù·öë´Ê¬Ÿ˜òðÛ~æqC)wÐ_€æv«@1¨Ôýi¦ê˜:i&Ä·!3F‰\·½†×NÐÄ£a“�ˆ0Fï/‰&¼yƒÑ"Ó¼Ðó?hĜܜI!<ÛX{³Ö|×—kÖL¡{ξ*W>ÁHªE,À•·xñb¸‡[/šåØ*±=ð‡÷'Œ6§ŽÿÞn%/ªÿ¯—p0já1a¢Âøe-ãé‡Aû Må�_ò~ÿ¿<¦åH©ÒÓ-W�Ä–L-œ,SZò!/Ò¹\ù”K¥`¦OÑÉ›‰òEj9zãdK!àF8šˆK Õ.åÕ]Á7üȉaw–k©üå¹QÌ¥ÃGŠCÄbÖIa˜mN &‘“Éÿ/¼‘{e#)‹¿è°Û Ù96’–-nl˜K®oªîDãoÓ'êï�� À›à+YÈ:&à·TZLYGÄyÙ!XÞ{BE»º�F¹é¥þX�良à*ªavš#+�@–¿Ð°º,?þr×¶çöë¼ÉÇî׬O+µ$�dtrxKm—Îl¿ó Y’ùâÄô=·}¢ÔÏõ·5³ÝülW`ê}�ÒTÆ¡w-^2Ø‘ÿ ‘Éù% Ž™¦€ØæÑ]WþçaÞxD5 –}�hÃgþÏn¿\<¢eñF©ÌáÔ¯õ”«œ~°–ÁÈS¶Ò¯Ž»C ýæèWü—IÙ°úí¥Ë’©åô(=³hgts¿|­M*EmZÝ+:røå~çÐÚbµ?§ÏiÑnÁM?ÄŸI¿øL§É2q%.=£,ºW�€ìh†,À}¼ÀÖGGÞ>E �ÑÜv�Ä{ó–tV¤¨ºE›"\cÙc$\Ä¥ýÁ½ßfã�¿Eia4Ö´åíŸb*ž–Á¹Æbç.ž†‚¢· œ‘Yü3T%õ#ƒÊ÷ØÂ+Ç#UvÝÓEZ¡�9‘UY³Î -êÚ|åU='_)F1¡[0–¬`”,ÿA®ÝEB®ÚêƒèIiFÅÍû<\ž¸ã%n¨"|§aŒ6%涘(ß�_è’ï(ŠöG�u»'3_ý6ìƒÄá¸ÿ¾ s{Ð’ˆƒß÷j®½ø=Üõ:–‹·vÆh4¤ïQA½b6Í9á}äÇ!Å�t¥…º,@Ná;MЛ] šŒ¸†hv±ëj›âÑ úa®�ŒÿND_H²Ò®x!<ÿ8ºÝâ*$íµ¶ÃÛlÙÅô}€›4Éœ&Y¯†Uš ¦Ç~ƒAXÝ=‡TÚ×1¡ŸïÕ^Ê?ÿÝ¢Ãì¸L¾D!ßÊ’`ÿ�]Q˜²ß™–¶šõ#ÿ•…Ïeä²u×"D~ùDŠ–�$6b0ÿÿ…ˆÛûŠÆäŲ窯 8A-äA#i‡nFæ÷Js aºw½"…n =]HƱ#a¬š•äîÉh~´PTnÉÆìêp]°¾ ‚‘W©¶ªîÔj¼ µ‹8kÔ@ÿCykäÒ‹`^¬ÇNp!Åû8˜:¼ó°±y*ì—Œ˜_Žæ·ÃÌÞK¯òKeðkÜW»×²K뀽;o¶S'^$L}‹ª�ŒÜÃs»q\#Q^7²ð3½0��µ™&x †}îî{?–÷Ú4TˆçõPõS³¤Ñé Ôqâb9d&é7.¼ w³24˜.ìäœ JAŠŸ‹ãH"’M`çŒ=4;i—ºø$N®Þ�ÍDv�ᔓeô¿?ÐÐåÉÀï7ù3Ž~¬âþ�Œw,«?¿=—ôFkFàŒöªΜH«ÔÑ’L)ïÓIjFT¢4&8† ˜È€¡ùóþ½ïÇjdà�áD3"#ñ§CŽ�½n çPÈϨ�ç©ÆœðÄÀIfž¶_=d€?ÓÖ/ £bJò;úöZ \Á0®Ð® LšGø¡H„¢ãÓ+LÄñÞ¿€ØÉŽvì”Ê=†z±KR˜3~F¹3# ͉´0_&º;œÕŒŠÌ¾=?3ÉbûeDäЂ†ûhü-1µ!baé~â­ôQ8ƒŠø·@§%éØsšŽËìÀhqÏvöØ´ââdóƒa7�;ñÕ ¨Àd=ú�4B‘�J<ï�diƒj¿ …›òèØ ¾æ¼ˆFf�î­æ•÷Ï(ÙY(¼ ‚\ôq`C^TÉ Æ1pv_°T�ÿއìBt,ö?Ãû÷RµÝ«h²ù_=�¾º©Ñ‘2èx lÜG7o¨$ WTôñn¥âìh7©èhÐdØj>îôé¾Y~8 í‚t©íÝü5¬7Åsª¦Xø£ñXÓ4ßåÒ ¹&˜ðÙþ¦goš�Àë-X"ŒÇ¢Ó}:¯¨sÅ'¾íf#0»:|€ÓšXùȺÇmóñ‚.¬/œéó®V#TDDá0“’ïó†)Û:]†•ßvfJ¶24 rŸéÀ †gO¥¸Ô¡-çZ9X3PÍb§7ýÈ•ù´y_À=%lŒ|^)Ì–àíˆì=µd®xȘX.ë½#L@”j[¨˜ÇZ¤ŠwD™]-ÇÃÖÙk)y<,ðÛÉ\nþ‰ð¯ˆC�´�ä—�©Ô©ê˜  Y(¾§‚ ¨ÉWî™�—õÿKòJËAžÙd”dL'ÿ Ú3>‹÷‚�²ï’ÈÞ"é ­Mƒñy}ø\ÈbįGrTŽ�$Q%øAÐZÆ!uˆ˜}ïÃ{Ïèlíu>õŒuz:&*|="™)<`Qq ÐÂ:‡ïW¢ý Œp+.·‡¥,1�ß�ËoœÖ¤ SS¬óþèòØv…ÌÄkC’ßuࢩÏU‡šÀ*Ëœºÿ# æÉÒ§«XO[Ľ¶Íb±€OüljfÏÞ—S¶Û±/j‚±62:®˜P•U4ÉØÆÑtàùܱ¥z‹šZí6Öjν6uîKQçûÆöOE(ÈW9 ƒ‡É7s#Ûü‰Ñt°Ž<=rOôæ P€õî+žªgPáðÌÉÒ=ö!hŒwlÍ«/BêòÕ›oëŠÛÞɤŸkà /¤HMÎ ¥eÁ ®Úiò�Õù[Ê;'1‡ò/ZÃ9[ZAùŠ`ũíû\L0[×BÒŠ*Ú)_–{û¼qþVóܧñG�×ãX[±Ús²â€¹xôUsjH¦0Ðú/Kk?m5nK¢ìİÊGX·3ë¼H­_cbÑILÜ“޹¾Gb†ì�©VJêe†ölßë_,ƒ Mé` žøiÿß� àç,¡ýC\L/ »Q4À-zjÕB¨¤Ì.ƒ²oöäôT®Ës§Ø"ã}¼%9HÉ£=§4ô ÌixQÆ)¸Y/4(cÊýÔf}Í‹pVÿ‘(w%½[ãæ¹Åˆ¤³‘m{ž”ÌH£¦LC0¡ŽÖÿ ôÝyƒ ©}ï‘OÂ(ë3(YÂùF°÷†”FÔ áÒµŸtçô„y É>)‰�øÿ3�+Ã#Ô?²Ù| Êʾ½Äb�ÀÖp×Qÿ)GªÁ•6ì¢ø‚|Îɧ@GâNòk¬lŸ|²škÞáâP0‹¶70؇�lwcA[�Ã.QË}Ù÷½î �;]| Èî›-ÊYÛ )óSð+Ÿp�cЭùnœ��ç�W¹WÝ4{qc?�š'ÑÏG™æv;¨÷2nTeØø¤’è%Q'’ð3áeD6Gœ�‰åŽà%ÐçqÜ) ƒîreDà×>»QÃj}eA¶Òú¨n#©Ã!H”Ô�<1Mã2¾�˜�ƒÇcw"76Ÿ…DJʤ8”ÖM®¤jµ.¤bä6 YÝÔ°®u›�ÀUϪ�Þ’·Îj\ô­ã BoòÆc ÉòpšÎÆ_·“óAò0»<áð#qikˆ÷¦Ò‰Çßq JWÝïCOžç4î›cyÈ[Öà¿„Á7¾Ç�IÜ3¥õxư¯j¤I´ô™ ܬøÀ¾&d3–ŒË‚¦F•ùYˆ‰ñn²€ÎX¾â¡Ê�UZÛA ¸¤§,ÔÏßKC\Ò¬A¤s XùWIuÞÊÖÖ§êƒp—ˆ_j§ ÜR|Ú·>³o žï*~¹µQâ£Ûæ^Ë]ï]øR¹Ý¤Oo[ Í$$Æ9ÐtfÕ½éÕÈo- Õw¼–ÅåÖö5€x/üÿ•ýš8žqª  ·„»hw,ÈT VÞ/üîó±$²û•Š“þÞ%±ñ"5×{$¯§jÉ¢+]â±þ‚>r§8;HUL°ºµÝ‘ÓžúnGÿ™îkiá8ã ãn]sx`Df.)gïM£ dß$.u¹å‰¦¼ø0½tpe_д¸GÄñyÝÕ“ì¬N¹²:€ä*�‰Ô+´3Ò`ΛV„Ê'ÝMƒërŠTÜU#ûÏuP눨÷dÊVŠˆÊBÉŠñšæB#l-ª£ æ KÞ5Dþ.Ò®;4¼5SªÝQÚñªlQBºÎ(ç`³æ(f‘ûëgä5–³¤zì¦NÆrU‘i¼øEÐqç¿+cC�eñ‹Mñ —HåAO«‰aÞqÎ]AÈA�òN¬QÜ"…ÔíØexknËdø¢øš€ÀØ�‹@#”’3â)¬ w)u£2‘8PR÷CåõˆÃ`µ:(S‹¾ûÍã�X£Èæ.€Ö´ð*ã‡ÂÔbÅ]¸ ÚEyÂÑÁ•½Bãùå»pÿê4#ùžýâ²Ov“ŒJ~ö@ ¡?Ë4…£¾´âRMwA±7j7B>#a)Èß'÷ü¢¯"f¬ÉÞ£)°ÅĞЧcÛlAÀÃ(D¹ê��A' A›Má ZÉ”À!ÿýñ+�ý½ÖsZ…suøO €K°ÃÈë’K¢—}á„‚lÓÖøàÓ�9†C}7 ÎÒâ¬2Uj¦.û¤BƒÒË6[r'ܰ�ÕV³)p@ÕžL@ÿ¥'Ý2�’�‘ ƒCa²‰£½ôYÁÀ¼}}»áwí»³þôÝÔ¥MjDéß›ˆJšmJ…yœ$ÀË’#~ òMN.§Äž_v”EøÊªþË,ROk5�þ¾ÂLBùÝøUè/Ÿ~èºæœ½6•–Ž^,·8µñUÔå8Ê( ÎÅðM÷�«©MÆU“:ŒA±,b²œ"nú›^ xØüHÒ v„I¿kÏÏ0rü7ÔÜ�ü`èÄxF~Ä…¿ª¥Ol'}¤¨»1õs¶ÛÐí­ïçïÝÊľÎT'ò3íø¹ÔqéW€±JгŠKà±�ìàXN‘ÄÑüh}Ý- ‹;¹I ¥`{GÚ’|ûr«?]¨«±—£b �Œò*Ó´�7Ñ)Ò)tdzƒ`fÑuÌ_>yËä6« T¤‡íOx¶?¶=!"· $õ0•i¼ï¿õ ßÓ†áò! €üÝšÚ`ƒò.LúF0¸ÔÖˆxâËŽnûkeêÙ‹�¶�ýfóÒót1÷q±�7™›3E®øËTpÕ=õH±Cjü@¡nx¢¹—ÊÓ [‰K.êš>n2 Ýó©¬õZmÖÏ£�TX‰‰Á°¿ÈÉy#”¦�ŠÞhöˆæ¸v|´Õ݉”' k1Æ‚l|�†©Ý¸l¶«T½Êð\Î*¬ßvkƒ…Ø~HGèãØäA¨àÁúádRSžzÝöÈw*ç¿9HBE{-‚Ùk?ð^\‰rV€,tɵ.†â§r¢ÖD±°ÇÜ*'$^:mñYAßVnðñ#àD¤÷õÀ„âX~%w(̶Ý][$à SëèG«`ÁÖ1&‹ÚôZÞs_Ö`þjü§ŸÛ{gÛÄéì ˆŸ©„Hõ=ü2Ö± Û«+67˜a6B;ly#Wê ß7º hÀ@�ìNßÎ¥)“Æ 3M˜ >Ú£¤Ø™¨¡æ!Xõ-çKªnÏ}£ŠúpnT™oˆD‹ÌÍàÂóa J¨‡´µÝ´|µÇÄl§µš“Péh®Eþ¡/÷ìf» 6�á´Gµº ¡] igõÌ�ÿýü.õûŒ¦ÚÐû¢cÓCÊø.úÜÜÅ©Ôd%X€‡Wý$&Ú §vÌÚªµÃÐî{lß�Üoth?À<”�Œy¶®Z?ÔÝuD PQŽm 2nˆ¡ž¹]`_üSÒ‡Žü‡ ¬‰!'Õ‰e|#¾*nÊg�}½í>ï}¸pQ¯=Rõ™°’¶lŒ çê:w27›ŽÈ0ÎYºÁʪ •²C `œÅöu¯•Öã‡wnŠÐ~ù�—À,tJœÞÕ®“™ÊÃl‡¥Ã@=#5�fµ,êS°^»9J1‚Ý9Ö:™I¤Np~¬LkÊd®ó{•7<ˆµBYªÜg­y@­ÞJ]c“éür­×ó\¶+¬¨ 2� r�nLOÜûÂØ}/=ŸB�JºxáèŽü<›NÀÅÓ'Év‹D¶fÖ“ä„ *Os—pд7¾âí¿¸Ð�–$ ¬šâ£½¤²|–Ct,¤V9æ¢'•“�qþx'Æ"beËñÛ"·ý•ÃÎ,†ø@žu3�e–!t¡0ÂÜLŸ¤Ñ'xî í“ePà Ӏ¤.E°*#€cSPE5Ø0O 8{$g^Á:Ôý#lq¶…>©µmÇ•'¹Q#Rì?bÝVÙ £ƒÛZ‚ìù‘xœ‚i˜–U_õã_hJ KºËW[„”��vß)ô`¥á0¡¥òКm Mô h@:á´r{¿_@½K·’Ju¦v)ì¦õŽn:TpÆôa†öá†I Êúÿè·§üÆŸ�5×~XC=ô¹ô/3/šE…|bI뻿?`NSk„Þ6=”CèQÀŠew´ùsB¯¹Û3š[›'°XxYéJÊÕ&uà[©¾¡‹®¥l2°›®z89šc³$´c87ã·÷·5%�"ÝGŽðÇs.ù‡vfa^j(ÂËüþ͉%¢!�!+’þú!:ùá{L®iBþ½+ë í¾m­Μf\ªržb²š4qB]Ìq¬I¤”PÛ¬hÒö$ï²Y èÓ­ì–ÁèáüŽ{7X{)P6MMÚ§ ˜t �% QˆG°ëçö+p(Ì!¹, œ>i˜f™DF&ýèöÉ6hÝ6ù¹776»V}Á~f!ÆD2ƒñ}vn¦£;ö æùi4Ôk ÆõuEà4ÀØõ>ÊÎ4Wþ ÎïÃx,n›€Bÿ½›=Ö) òŽ^ ¤òP…/(fM·*ÒÛ2¥çâÅØŸ’ksÄÛW¢$ÀNnC—õjb~˜¸ G§€)bvº « ›ž�Hxªb‡\o –ËN a'Í�w#ÆzWpR Û1ü‚$Å: Çzª$Y)–¸Ïˆo*q€€ž ]Q ?êI;XyÚ¤_ س¬‚õË"Y2o\·(8àþþ'qZöu-FoôI%}¦�g¼dƒ 0õmëª\ùþuaSôë"û&s Còu"~‹IUI¸Ïé++«P­Úì½�#‘žî³1:ÖïW@øÛê‚;.œÉ]³t}o÷¾h`zº"뚢]÷ØÇ�0åíÙ}’­�¹šD”Æ\§&Ë£�Hä9Eò´vôŽÕJ¦ÕÓ9•…wO!—·Šø])[§ÐÁäwJßÿ¬£†@äÆožï´ƒª¼eˆ·²öÙ}6`H>Ù�+¿©úðz„º¦h(ü­Úùói9 ù}½Ç$‹ Z\Ù»$î$izeßëñÃN׋¤oÙtÙ¬$qJõá «-ò�8ÞŠ0_:j>æ{‰*À4ìO«±A5ô �œP8.5¤,úߣ%Öêû`¾ˆÉ|ôª&|—»�Ú§UE“µ†ÜµÑÒ~ý»:=çs}(\®tBvý!ú?²�áZ|í ®y+dteÚÚ�Š„8¢É9ôFtÅH8ïÌ5jø æoœrõš€¼À871‹�ÍŽù‘Ð8Tûà »h¶�Ð[ÿÆeBF¡•Jã×G@!‡óÜ<vj×rì-^­Kœƒº²Ý¶A#ùâÆŒoâ�<95šª¼·Œ�:#àVW׌Ùö0Ë1/bPbmy¾ìE/ûõÒZÁt5� hø}V„Õ@y,EQ1 q.;>4½›ÊÓ/"…»ëÑã!G"SÇþ›p-?z¿y ƒeðº=+VÉA%sºb.Å:Jd ò#p =8—¸ˆ¹ßÂ.Í‹ä~qW$½"Ñox‚dt>AáB„ËÃdêÊXÛh�{à´¿IáPº]‘b!1^¤õ©ÂíÍ77‰kÏö¸~8%­é� d°u˜^‹dâB«lÆBsú;ˆM„ ÉÆH¶§�ø\/÷§s÷"ãQØÙ†~ã_í5Ò8â Ô§ÓFmy¢?ʳ‘\5§ø‘\°Ô¼Vȹ…<·ùiיּ6I�¡˜ÿ¾ä>X§nÕ£©r‰‚ÑQ0`ã@k8xÙÏÓ ìà�÷ûÇrÕqÉ5Ìúnƒ­�‘"ÛBWÈ6ð]ðE$\n±¹¼dÍeÅòÀOPc’ÏÅ~/É´˜áÝ|¿�ƒàEŽŸÖ‰üølÑ¡W_¸Î•ƒèã]ø`ÇHèãé½ÎÃi†WžËŒÐ(ÜÆ0\5ež4 ìu[íD޼‚dV�à/šu'«3^OŸìêwÑD f°ê\ꂨc ÉLº­ 0DU�Êjm}ë.¡Bm#$×eR½ ê¬3ª s-P¤žyaejøÿܽãØÂì«'¾X`qÅz3o¾À°§xs,aØk“›#òrðPQÒƒª÷?Uû½½–þÁ €¥@MÜoU#0ÐûOéËêhU¤!*¥¯^Çé©[,¨«‘u¦>Nù¼ó�øÿF ÂQÿ­jÞou�Æ™àÂ.ºÓóX~®lUmíÅ'\w¥wM�“WJLZ̉• ¯;ë/7Üä´3Õ¼¡¤D'¶N‚r ÝL'µá):“oQQ„í“ÙèEƒvâ?žŽ%4™ ú(À°GnÆ}ã´ÇÐå8ë?8Mã_p÷j澨IöèDQq<eºG`EÞ9˜ÉGH^ñpýÿ¬\æCì;L)&íI#¸áÊ}"0@ÄûvÁg<´RòÝÖ ZAaèBLñæų08u *#�$™O®˜’ß[>w½¯H]Ñ6ãM·Ð=Á 9®°!ϤêÐ 2%äß]Á)Gk¬­)ΔÔEP£¼ Iò£Þ�`ØôEªÔÞ<êÇuytæçú^îÁMÎ@±¥Ã\O!}æå§ £Ái£ºkµDÞ1iåHhŽjøb áÝ4û¬zöRŽËI>GZcÕíúØj¦« 9"¨O§;IXïáøÓ«ÏPtkÑ«FpÎ�ìO¾aí”ܜҴs(iª1�"b˜�;cÄk´Î†b⻓›¨óDSãDSÂ<·Øáë‹§jn�‹OàB¦yîišÅÙ�^¦;'ÌÖê²g'õPqžèÔ�Ó7–Ó6>ÁÞƒízJÿ/º~¾öO¡ì?3¹ü n�2öðÐ`ú¡ÏÇ$¸"gk¯:ñ[ÌeÄ Oe>«� €³ÕE‚œ‚VP±Ûn<Ѷ·©Ø-KÒCsC�W—öÔítIbáŠê‘��2®t6ÐçõÒUúáð�ÂÎ?:Y‚6¸‘1ð¡W›2©U³6à„®0s~ÉOh&=E_ÈlSZàÞñœ7–Oæ½í m \Ž0r¦-£ƒ?–ån[üÆÏ1VVºh†":¹|&‘î›Àû¶ÈüA5ò¤i5>û‰¥€~•]>Û“??ôƒZ¿c#r3ÇÅ }19ÒV¾a~ÛŠ�ÃD4#(È7䬃ºãè(¸ß A¶Š êeóCaÓBqþ…5ž"­cÊ‘K­ß?£k ½jM9ÄXÚ-ððêCÔ ñ< ßßi%˜¿~KÕ\DßáP;™¶X>s:¯po,ÊÁ©)EÉqÅÐÄXw5¢žeC®“Õ~­ûפ–ƒ‘±˜‹ Ö+ÀIx8á|UËKªÿ®–ò´ ÑË­ÏÀòUáµé�A¿#­°â¬Ÿ7Z²BU0ÿ›-C·”wÖzÑÄMG Ê^QKå6¡·Í¥,6 ¿c£·PëB{섬“³2 “¥ØÚ[i=ªâBr>Ç)09ölhG\ê�Ý|ØAáþüè;ï[’ba_׆Ì2c–3oœÄE¨(Ê?‘� Û±àÅŽqª85¥_QÑBâ�Òék~ ä*Q5PM/‚ÖtŹÎx ~Z½~ @ i3ù—4«K+LY+‡HåÓµ¨¿¥:Foµe${¤q5\8Ѐ7„×è<ðã®ß}ë2`ûà©ÚGIã&x5ÿþŽ9íZÐ�Sô5{„áÒܸ0æ5•MPf–aÓ>ŸÛók’% ‘?#…4œz®É>W÷r…45â¹®fJM*øN1RbÆ!PÒƒ æ|ì(àã9<"å›D7œhµ6¿ÿÿÙtX Ò.ŸØV£3ûI¢�4‡>)"ÿ:d¨S~^õ}ꄎ¡ÖÖo ºñõ!Î.<½ùpâ%]BýeÔXU¼*Hˆ§'4”ÍúNМáÿ~î·‚hʰL]üÃ0ö\òjú÷xÝÓÉg=Oÿ€ãH'ƒª(žÝ{9 ±)’X}§–OœKŠeâ©¶f/³ß…|ñ{än‘0Áó‹nQSm/í– ¬TEH9…ÝuÜ—<È­‘¶Ù§,ÌO$vHwÃ-Óµ¸pÃ0BAÑöt‘^ó×(¤¾½‚ÒêB`ñh†ÝZ¡yxÀ¸ßø;«—p¬iö ÌEõ/6ÈÔØBU9ëè¼ï¤0]ưΦ8e7>>À‰Aí ñ믽ÕyA‘§êÇšÊ6|L¡î³TVЖ*°ÁRï@èæÓà¬ïTeEÔlÐxÞ·„c}�sN©£ýµ»Ÿ.Ɇ“$Øÿ·+°Ð{í1ã+�ÊÅÁ8M¢ãWÞf*kÒ=6á¹IV†óYÚ¤¨÷*ÿe¦ÔÆ<"†Ôª²u³”G@d{ƒÓ\4:è!´¡™�˜ðž˜JjâèÜnk¬†n‰1é«ñt¨sÿŒ8Ê5 |Å^J#3Vlª~_Cê÷˜97Š>I½?Ü®uÀ•6ï8>š¶· ˜Ø?èb&vd� ¿hü¼jàÄÆA=é1¨µ¤ªÐYp/%Ó´€‰¸ÃUú|¥¿šÚx&à¡ÅoùM dÌÞë$Q!eªä�¥÷Ø›þ¥ɼÖÇã_¬FúèÙBNŒ0ž 0{”ÇÐg5þ�üŸKµ}%Ù*$/Ug�auÑ‘À@•ÆH–)‰Gp¹4ªŽÏÔL8Ý–!H™ª‡‘ðù¤Û:3G<êÄmöôYª`é¬ Ò7s�­u‹‡ ©qPáÕM6ÇÛÉï1 nSÚ1È´Fã�_õŒh«>Ë]µ›c¯ €ê1Ò?ü„˜ïsò8´jg”VíõYô`×N.¨®év’}¤Žìž�´†5::¤›Œ7ó0®Ô)'>¦º£13…"}|Áå½gwcøåÝÖÍç0[Ѹï«7̤Ž»$)Ô7XšEi[µæ~ê!'â™V«Æâ‰²C'Ž‚é®Uk4ùˆütpj(=¾á T›áq䮃ƒæ¼Tbó;¯RÒáÅHc® �λàdìÞšfä’¥¾þ•z˜­ÜN Ï®Làu�Ëà"Êê%è4ÅQ­²z÷sR¿iE¬V]e×ßܘ³»i±VzÃuDp„ô© ÀÐÕ³FPÞV�¾Ó9ú=ˆî iËY‡­5a(9‚ÕDmʰ�n`/ð§u¬Ì»‘íñ©Áo®Žä|Ÿ_p©Å&z"$x£?¥œìº‡~ìAw†D©HW}Ïé~A�ø‘R|‘ú¹wÙæ3'" ©Vâ9‘vÝŠÍ?=eÍæ»Wrÿ£ Ô¡ùˆw?hÂ=G‰^“”w>g«W(ê&2ÙKŽÃüØ„uÕ`|RwìøÑd6„°ç(I}ð°Ð„DW~ZD"ä®ð±g`ÒLÖ&.ƒÅXykSø°–ls—E„ÈsNOŒ —8¸ Ž>=ë’G©NîÄ]Z² ‚8¤ÔU)èšZÄTL -*éAà g@÷¥šúÊ-`UepaâÍùìlÀ¥´ÉÚk¸Oèí?µÑT)/©Ï̼Êÿ»°u‰�×�ÖŽÎAê ðÉÜèeyìGn'9µ”X¢º·•¤¶E»h¡Ý›Ê(üíùKŠÀsÇ­Íhj‚<%RK>®%�_¢)™’»ÀŽØµVúžÜÌú*Ií<õpâ‚Ùz¦'€¢*ä«LÓ0(µjAž ŠÉ3›ßägæùÊ&ÄLüb(°}²>Âj;ßÓ|OúDp.Ëû…aNPéƒ>é¯ÿé^k‘9h?äJ�Ïý {¬yŽ7rgž‚ uïYB6? ãl}4N½è´rî]’ÖI�{›™*²55Í—@7�p�Å[ÌÂÍWï™qÕjc1´Ì"|j’ „Ð|«/»(uÁqmæÁ` t5H–H&ÅŽ‹¡Òq!Ù¨IÚŒr =®‹˜ªZ_D}›“¥—V™Žr¸ ‘ÿYÊZî©óšDÌF«f0”èùºáÔL­*2�7Ùiï­zÃÙô›zá¶#Cð¨éÆkAnC':pgÍï\²’ˆ�q£XËÅ?.s&Λ¼btmƒcÀ@ÀŠŽÜ¯ÖÜ´3’Ø‹ H D Â´H“[°+ya ¿[¸óç;j8z†nW“؈ù×<ºÓˆÀÒ+VúBš\ÓJÀ÷7Ðq®µHW@„ÆDÌsŸÌšÚŒwäö´â¦¥™@�”Ñbä/k[§¬"]ËÛÐŽ!¬ê9“|‘h„9\~ÅüÒ%–rÂp—f¹s ÂÅ{’�½¯u!çÞ×…q,Ã,ë8`ÃߌÖñ”_½PÖ%Á¶‘É~)§n<Œ>9ŒŸöa²«r¶€àZºâ-3ˆ}FíÄݹ.?ñ3ozèuˆÕÿL Ž ¢ ~_<ˆ­UBõð˜ÇòæöµÕv·á]¦äúùðá�cßu:WHºfpîÐ`xÆzr¶û›—Í1m¹˜&°Ó°á e{ �ß�wÛÑܯUä°pP˜ƒÀ™î ülçîï  ú7ØkRmˆ¿ü á„£ÙºÙ3Yvq™š3-„n2!˜€ƒ·ÛÞnÑûYݶøŽ�U˜¾Ý8ên;ºeʶ‡9Kÿ›'Û,ÈÅEÑ2î!?xœ ʼn4]8¾.ëTè+Ù÷úÇ@¦º>˜^f™î¢@ÉY8¼þ=#öŽ<ÆËF¶ó»\ÚípK{÷\﵎4–´ÃüÃÉHn\›õâLs”#½+^ÃísÅÙù×�¤ŽDš(€ôtß—P‚ªäü¿ºÜ÷U"ºê*|¡„¼›x1üö†õß¾û;Bxjy¢8~ÉwÅ|ì~�lã Iípûåî JWç »Â4•¼·Ç: tf8,Ž›#¡ZC f¡úèRÕEu¢MkA,A³aX»ÓÈËè›=D¢J �áQÀg ñšS@AR’ÏÆÑVÌ É«Tÿó=!¼è±~×wÆb}Ê`½% Ù.æ tˆùßcf'œoùâ"΄ ýÅú ‚ ¾Ûø/Ĉú�x«”AzÈ–x¬êÃçH¢ËÛÃ=ðb­¿«c�©Z&†5þძcõ^ÆXV àXw.+±Ö,\V²ØÌ8?ºþ'|�¾�q×±Ár$ÂpéøÑÚÜ ßóyÄîmÓ�e²¢Ô‰ßtz 3yR!Ó²8¡“‰¶EϦ��,ƒŠ’!(nÏ0Ñæ9îý¥èĽ%Å{݃Þ(*q ûI)G$¾ 쪻S2Ì<¬ßEáïÍ _ÐáI ë¢ò-dKC~ÆŸ’Â5 ÛñÜödzËdáVQFµAÇÏð�2σ=º®ç¶m¯½…¡Û»z~¸âˆàn*‹fLÁ`u<2aŽYÉÍm´˜·é-wJ!—P\Ùʽ¸Æt‹JlÒ]ŽcÒQ3À|á âË�ëÖÖÙÙOÒ•ÓkøÐ±ª/ˆ�: ‘Dà±8§Kajpûl˜YÇ`kIW8Œ¯‘&cõR=Uý.rv¼N~Ÿãbšq_í�’*çN!•LJ£T3\d©‰+WGÑQMÒ¸)\ŒhTÅšh« Á¬09”—GG� ˆ1\*f. ò ñ�¦3áÔ´ÊÚÐK8E¿wâ\¦j 5ýV¢ ô�ÒŠð†vØPJóÌÚšÀ‚c-G;`Fuëí¸æÇat ¨ï;fǘiäœ«î¥ Õm8à$¼Ly©\dáÞsAM»âÖùq!¬I<܉�Ùx6I Ê’*:l«ý;²éI##Iý[¤g�á½�ŒLB±Áu?vì³çïßS˜t~Ã<4 �âOÍ#ûc_L³áÎé`fC �• '­æã9i5¾¨5yª›†¼`:ßÁÇa&CÒ,¢€ýX¾±„êÝÓÁbo/‡6¼ƒÕ‘$äÈ$¾´Ñ�íqǾr�Õ�O±|&µàªa‘(d¬V^ÆÁÕÓÈ.�5`ŠÆ¾ÿºê®Qì4*Ù\ï.!œöï÷S›ÞS ÊÌÒ^p£�Èð®ËélÕÖãOR€|Fß#¬·:'«·Æ>Ms`¢–ÿ @#^|Å¢§nñ±CRÂcGY›„8|²¬Ù\ƒâ+mÁž÷¹ÕpßîÀ L”Ñ‹�N“¢è-MÓý�é>ÌîÌsVÊû3ýã¬sN´T ÍÛLf»†»ZQ–C8é…£šSÐU UÄñâ°o§À=ø� Ðe�QüwN™ƒZˆœ'Œ– «Ü·µ†Rœ~•C‘¡Ï­„þZ§w F5�“�.¦‰Ö÷ñwBÒX-ºX†ÙѲßwØ‘scÊÒBÚž=¤Fizx§fër¹™ $)ðµÒä±%fúp¤þH®shh;ùS ˆ”Nfƒ¹�*—lM`à›r´>!)¡å'¡Ù¨� ˆÛígßf¥ðûÛÏTx�q‡¥ÔÍP=Û™ïÊö-_Pƒ3bx€@}Ch ó|Ï„ñaáêš÷F^R*æÞìŠ^S?k3ñ0ÀÀÎði̬ü2šÞj’Á|µÍ@žóÌ9Aµœ7®¢]©K{¼¨åÒTÍ{¤uS!ëvr�à^ 1(ïa¢¼5˜ÝÿN�í ø°Á‹m'g:ШWL@¸ð#Vª3WG]SqN‚õȤbIrev„Ž›V0:ZY9Žañš=¡À�,Ô-¢(D…�´ð'K™ã{5¨9´¼ú$õPÉž^ó·�.Y/=“î,—֬ѧƒW~´ü¥YT¸Ö9,}"Îè=£Â$Í:ÝÙ5!™ÂÑ„¶Ñ°Äû rÜÜ+†çÉÍÀ«á'‚%Ñ"¥ý�=KÞ‰5C©² ú¢ù’è­hRž’I»œ¤ÿÿÿû^ÙÀžVŽ/°Œs˜¾$w|÷ãC;zø�aò—0Ö}¢aø<mÞÇ4h&/æk¨ßÔq»Ãk}‹{˜ô�Ñ•aÇ—�d¤5õ"„°Š7°¢Çï+¥›•[÷Øìf¿? à_q)X³?êÉ*º~^˜ÞÄeF ‹ôµÅsJñRKóIËmï+.êœX¹æÊ„éóÂT1ˆ‰Ê¬ËŒ¦ájúÈbN`vzÃýîšCS¥ Õ�-eCRŠo*Þ®Ïø®kYkØN^ñv¸TeY^†I‹ øRåÔ9:ù¨¥Q7vPãŸ^ç³[Áhe«»µ}¦¬a}p’Ɉ‡Æ˜S‚£‹­N[‡M«z�Dú>>&^©1^~dÐ$—ÊÞàôƒž(ÔMߣí®�d�$¬2úU~öˆbUË}¨æ·€å?§Çà‚QЪR€á§CC©™ŽS¯¦Ù1ib‡ì`0[¤þ§GÌ$¨ðÓçº}šáǸÐþZh>žÃ%.êÛ‡½XEšf÷?=;‚Ÿ–�U2–™ý©òàá€üEÔÐ�]zä<(�$ØÖ¹þyõ�c(Û1î,£Ê%¾JxG#‡=ÌðÃ쥖²æ•t†{Møü ¬ÛÍõÑ áOáåPUºÉæK‡�Ÿ¶,#ÞM#€c±åÊUal¦Å O}™Ó$ú|DÒi˜¡šFÔuÉ \(»åbi´Ý]ö¼r`£>Sì0õêg4“²Hs?ü£zïAßá‘€W€gî³1OãÆ·cB‹¼íü·fd€Y…Il ¦.×MR-iˆÓ÷ñÇíÙ ï¿Äw6�lŸ\†^Áä¬ôÑ´‡ÿm8‚Ûàì‹Å¥Ð7 rƘÇf¨ÕÍ™H 3P²«ñ=hGäBÉjàT‰™Zp8]V:G¼KÓ)‰êús 0P…HI¹F³2k ÕamAŸ>d”TðŸ Ú56Å­êBÖvë©ri`¯œßÛlÀS@Fš¹PkïœÝ„ÈaÐЀCPÀ2õËŽ–”ÉYM-›S r7{LÀÍ¥¦iéìŸÌÄÁo@7mKjE*:V´4Ásx”‹¸�„o‡FãЀò4™kåïað…HðSMýº!¾À^?gGÉÌÇ�MŸÝ——ggø|�­Êø¯°©nãyËz¹rþÞRA—}¢¬·9“9±ð�JW'-\íŠj:ϯÿ�ØxnÀl5£:z¢£édù¬�…Õù£0²`¡©w­´Ùi ùd4} úWq (ËÿÃÝoû£0¹?íšf¤<ÁmH¾ÔÑQؾ¤²Hbå¶yRlDf ÉDhû]©ßy¸hp?¥.óòHð A¢q¥Ÿ`xË[‹´_p0ëvÂÄÌŒhy+¤øY86hº87äº�«JBÏqGŠÙgçhÇ®}2ìÈÝŠ ü€6÷/—Þµb™Áåuv-¹XèBWÃe––){5¥½¾Á³(WQ6/"Õ‡N6"¡6±ïPéñì9_‰:ˆ:—ÖkÃYA\H”Ûe$$3ÞX³¢Nc´™zÏÅvˆ__UF7›V‹skvˆUÿáòR‡ý!tX˜ºµÂ9© ­ç7Ü37GGÌë¥ëµ¾æ–¾ˆzm±±’‡Þ»¤ú'™|¨CQÂÝç‹ rµFQW›4hû—rÈg Úó¿;ÈœaVz²†Š"˜ïR4Ý,Ïê4ˆžÒ%]}-› p�™ :JÙ!ŒÎæ“»_Òúœg!Ó„aêb¼�2OÀò5` '�ø“¿Ñü-êS®ÄteQøU%e¡Ó I ¯[ÎÀ‹WŽ ±Ĩ=6‘þ�9_WMz¥Š¥¥\ûÒéºÀOCƒÉ�nÔJÿ=ËŒ€.¤ï}Òòè �ÝuŸ`¾³¾y¤„ÀLK±I­_³"u¸H,ÅÈÐÍ•+͸ëd…ºoHʃ+[zýåöA#é!²�þ÷g»nü‚n•tòéJLü{²áÛ´’g¬]ÀEûé*joxOåø¨6¨¦ �½ôòžÊ/êv½LOzQë¸Â”@%尴̉}ãŠÌK�ÐØwæ » 4HZŸ]iÿÉ÷oÄV¬±Ý *ìäÀ|ð�Áò‹T"fv”1ãzúhèÈç™!së‹ÒlÆÊX±æ�½H-MûÜV1²£±è7ãÞ¶];' ¼ö½ e’–Gh¨pºT©µÙúû�f¸Q‘‚N°a¼Ú¯eM€Ø\ôšï@êoò…Ž- éVë°C*Ôp ,vÐ._Ò¼p¼qœ÷ôû„]V#ê;Žx�ð#9¶N«1#CÎcÉ3Ko2Ì/F>LÂ�Ÿè¹•�¿Á¬Ô—çE¯ˆg<¡?l¡Ñ›EMóG»PøŒæ@jø®¤ò¥ñ/Úsæ–Üù•Žˆ0}í×|Y’53ËÿÇõ¾Éº•QÓ/o‘�Äõj-ÑêïªG¹ƒ1d̳žöЍÉ`ïxŒ‘îˆ$`ÞË¿à ¾¯µZÇØ-c{b°:,úpGuš9®ïc¦ßGyÈYhd‹2;?ß2DkÅÝô”ækl< ïU7© ¶FÇØÛ¦¦ö# í1Òç×”(/Í¥¸fœî,­2š ´dÂÒLN‹Û#p«’7=޳¨¤…FÀµV<ÑQ8?iPGŒ]²ªÑò�Ÿ9œ Ÿ>º;¤ë‘­HPl�›\®·e�ž×½í£Æb¸J²«�£Ò †Ã{^ûÍ=Œ,iiHÐãæG˜;ôó+ƒùëÕ‰tÁ2fDí‡ÀÅ­v?!ovÀR££F�×һ߄Îê”@é K;[_€Ü4�! ?ߨ¦o˜¡ŠJïÕðCè¢/N–+<tt_óõÀ€ÜŸ_nGÿ™înÔ¹Ãù8U )•U õŠŠ7 0ÖqÉQ—¢ ²5³ ³O\O�\’x)â+XÄSèÅ„ülƒLRFcoG¸yYäli‰©%‘Vªw@Ýý;©†ÌÅœžáë{àU¶„‹O‡˜œKBÁîÚ*'Pú¶°Œ6OªäÊ’Z*#DÓD…Ë·Ýí‰Ú”ÎÎ÷ÛG†üey69�÷ \RÔW½QN?„ᲈ2²}̃››Ó_Ã=ºÀe˜ÛtÂ}!·xBцRàë”f¤p¸dú�~x™÷A›A5-Q2˜ÿýñÇÛfPÙãè|Á<¯'Ö꜆ç lmûÂVãÝ.Pm4FÖêÛEêÝ<`¤J8´ïgÚ¸Kϯ­‡K�G[¼QàÏvl¢>0n2ßâ/Vù»_Yƒ€’‘pzËö]¹¸¢´ž#Ó výòʤýZ®K¬‹8åye¥m@ò¾ÏžZýr*éé"ÜwZÄüúô¯:ÈžÖÖÁ‹@g,ȶ ÿÓ*—Óg$ˆÝ…3�¦ƒùÿp ùd$K&D9+0Éâ ¸÷HÖ@'Jå\Ü8b ÌOšfl»Ñ¬Ch1ÙȤÁ±x}Ó¢+t˜ÉÜWe”,†UÁ îå!�6¦i §BtðÓ'z}Þï ¢{r�nfB¾nIòóü„/7KÿvÜ8lSYÿòÙÉ}” ûµ¦#@�ðaW¡õ›”NE@!_'hQ|Ò†? ¯¶¨ãLŠ$Nø�jZ¸$_ò²”"sG«.ìoP�É>‚¦¥³/w£>?Ø ¨’gþ¤8®Ñ˜†"÷ÅnCÃÏVd/ÐÞD•�Ý"ÜÞνaH9¼8ÁøL»ÝÖÉS·0ÛÑÏú6˜Sˆ×dù,‹tíÕz†¸ «ŽÆ·ÂnÔ’É štŠi¨ FžÂŽEª÷á·Ý ‚<õ¬¹ˆ4†R[ùZ}Þ‘!_™{jO P.'@ÎüSÛßÜÿÛwëI–‰ »Æ+‡À*D³¼·�µ™B¬ôw³!-Ñ™g»a¼# ܸе'� QFà(^ž˜Gƨ&1Ì÷¡÷¼ï¨'ålûmGààðÏw#°ý¿ý\£PÇ¥†WBÒ„óåz5ý[Aà—T रÃV•`h8™±'`àoë/ñ+r.SSú‰œímœqÂçAüA—"Õ”H“ù9õQJn"€®2 9_ã&þ¥$—ü\€â”Š¿þÖ(r…Sb+n#ô#�-�“ hžv”wp’øQ�¤Â´'!”ÚÆ…LíñvM•ßÔº¾á‘&0 b2ÆL×=ËÖô+\£•�¦æ; j¬Qþ�®ÚŽ"ÃAúÚuÂ]œIL°H¬i "CFXBd”Ï£Ú¨Œ¾p­\YüÐëU)‡òyµX…¿ øI‰ øäѸ›EÀÞ¾ñ²_œãFý÷vKÚãèVMNeA%H¨Ìä!â|½ñ¨Ã̉*¦½SUk£jõ÷ÉÚœ¶¸=ó|fÁp¨Z&«pl©�8…R|Méëó˜ÊŽBøŸ$¸Ì²D›/Ý~Êžµ†5)�uN´«í ZÙ®Óh¿–©n]æËäœÉìHrѲyE:‹î�r…’—·ä®|ôº?ÞµRöÐÌÈ­ _u.i­8‹Èosá;^”«±“ Ò¾ýl+h²RÝÇŒE,Ñœµ†óN" .,=låÁ5Øé£š%­jbIbMÖƒÁñu×ö†Âa.â�Ñtì2¦V.y‰$p¢ëS~ɸ¨b5ïÝ<3© Äi�ôš7\µw¶_}™RxTˆ’a?I7s_üRΔ°â4ˆ#–¹¢—šrûçm’%tݧƒÈb®h¢0ÿ„Ù…;Èn¦6sÐGÙƒïˆmÑÊê >w�{°S&#Rƒ­,¨ K—Ä¥e_r¡Šc LJíäÝ&u¥92*éš;FÜÂ’ç„í„êvð%ß &ñ(œ�3%*‘– ÚU„òƒQb ̱ õúo´CŽKK{!< Ë€ Š_*/tsF¡•yÙ‹@gyÌ´> S HÍ'Ñù7ríß4Š„ ­Ù1(Ü`8±Ðœv‚ªÖÌéC!HjöòÉÕ4Y Ó_‡r~¦°P]Ü‚àÀĘ÷Èí‡zÞ{õ“@?£î­þª�.ä°¹ñO @ª66¼cî„…z…­ŠºE½¬ÐÞÓÜ@Ÿp,·p­Û2^5HJ86‘aÆ‘ƒÎ4�õIhäŒèÚÜN ÆÔGð áü[¹ú…:¬-PQ"úœñybÔ•©­¨Nq—&d(ìùj*Þ 0cºe'„½©‡Þc:O»**¯"jØ.BG>¡õŘKÈIˆ®Ÿ%ýÉŽUü(gõ>‰¢b—ý2Ý£€ %4Gþ¢‘qQ‚ÁÞOY'‹Îñ“ B¡{ Ú(§"á—Áªõð¼„@à m°Âå?ZŠTƒ]ÐI6¯Š8©ÝõÅ).¤ˆœ~ï[Ê¥&U~fÕÒÛ9Á?r,Î œzžýó{NqPM¼ZHÒ3lŸÒÌ®qA�2ëÛåТ?$|„нúVä‚ÁÙ$;j·®tùý&+:hj7Œ0˜Ÿ�Y�ÐSA½ÊWì¥4t°ÄÍUVš×Ëÿ™”Žø#ý™ãH­ü;½û‘€øX¯.[m/ç<=´<à‡,™8ý÷.ß%‹·»Ý¿·Í� M˜9oЉä Ç ËÄ�ÞÊ)=s*8 Ÿ6&£eêàõû„«o>üD*BªÞ1ÊõüJêÓ«×m1Üec˦QOÍ c„fµd}…ôAkeü­Q»I{WMoKœýÃ:ê™Õ¬Nj)qØROrÄE!‘6^ƒamf¦ éÚˆ÷2-9A›dMá Z¢e0ýñ�LœIÐ}løTº{ˆ5¤Žç´çÓOÔX(ÇçYk%; º ÉÏäwÃUiÐÐþu :Ȱ>ž=D"á0cgß/¯�âvFâñˆ-)?u a䢤wùœŒºÐÏûõ“ ¸Ò˜‚­"ì]¿$�«ÂÒí¤¡p.ô#?ê«áPø¬YMœ1„ÙI; r�{M�¹–ÖŘ\}å ÉŠ§ J½TFôÆðI%Îßȃ]ÑEˆbEUæ žï …­\c(lïóx% Ð'†MLÜ®vÑ#â”iÆ|ÉQ .¸ýcä÷±¢m�ÝÑ? ‹‡,¹¯:{ ZªI¡kÖ+»~ÜÙG׬Ð]óLŽBèˆo}>¥>e[Ùh¾Ñ¼š¬M/lȘ@æÏ˜…q§‹;߀ûL«zÔi®Ìå« 0ü£ø¸‘TÀ.ê-×M�Õ=¶�Äo†ÆUÒ~ªªp MÁFÁþ�u껊&º#Üÿcè~±±ÞEa¢å°Ð‰�Ø*ÅÍ|;ùuö[z*XQ]µ�ö?|Þ!bCrCm¼û¥ig§WÂ÷½is„«ù`H ¤”ñáÔBÞ!é�£u3N¾(ÛpöPdsê‚æ\²ädSÒJaÙ|ûâ6ÑîŽ"ÙQa½IUrµ:à äl¶æ~Oìߣ˜/›BÖ\ZÜloƒR–Ù³½™�(^@ºÛæ>g$Ù載Äúªà„Ô~¿]ZDtÑp9œ‹Þw¸e³ºVʲF�=&œÓÖ³oJÑŠš$xŽ››HÏÃc·Ñ++¤Oïó3½'œtÚy“B†Ñ(6B/­˜kÈÅïÆì®G¿ß*—9†Ésᬰ—?D˜m;Í*S=˜Mï9¶­‰ ±ÆZNeI »EFSg !£v›aÝe쿆š±Jáj>Š!Q7Aî† 0èàA³{LŠœÐ´¨œú°—`U¨]ÞPÈ{�:ùÏ Öá½CM$p^ sGš×Æ‹Ãö±ô¦t�"#»Ïù}|cØ0ÖK6Ä‘¼O³¨é^ÌÍ® X}ˆ_W*]·öÃr~ðÆpZu�¾ó æAR§¾OùÞ”·IÊ=··ì… ]²mȵ?hOFž J= rïUR3:ê cžcÅ4•„º®œ«ŒDöìPÞ›Ð$;šL*¦ÍòÏó±Mg¨‰8B�c0�§¾åë"½’,Ñ3+ƒ(v8–õÁ¡ú�{œ,Ó!› ú¼˜"^³ü]|šò_š‰›™H‹´QiõŽ0 "AòÛÝhKôI€³{‰ÀOé±É*8®’À5±ªôD-=ôE,6à™iß9)NhZíD¾{BŸ@\,‡Ù° ž]Mu÷ ù“ª’¬g…�HúÄP‘A*^m²¬_ Ï4c×Â6Eì+ ÐU�÷œ6F{›üùím°â]õ–­QºAN¦`ÕyšÞÑnS´£ò�CG ³¨3çÛzéž­ÔµS9È‹v¿þ‘ÿÿíT S»_¿DGYsRÈu�J¥¬/ui¶ú¹‚5Ë�µá`‘ı„86¹ëñ§€>4Þ_¥’t+£Z”§FYkköO�&Kλ¹WTÏȬFÉbd4+x‡ý`qÂãQ;Šß"cýÃÁÄ €UVpNÁå;.²TvÔ bq…tçö:à|ͽ&-ŠCØã-÷`ÉoÿíûOÖž]g'…Øí£3Î@"‡q_pC±ÊØ ŸR·5ª+c\Ï€5š¬Ü*1ÉÌi›a¿Uûö]|Ÿ>µÄd‡Þ¨ î"RSZ�º3ÊÂìQûΖI×£z&YPŠ V®ÕÖ­¸pq‡¦Ö·´Ñùþβ‰úJµÁ}Z“%ª Ž[7Š_ë|\&™##ŸÝ7.Y�È÷Äa9M£K;›y,rC|ÜWðmÞ—ÝÐoƒQKâ óà}²¸ÑG �©çû·â‚Û7×¢ÆZ›>ê,â¯ÿÐ}!êÌQ ƒÃ7¶©›E•—±\ÊQBý#Ò|J®;ÝKø!w-[Åy·ôÁÊ©6¨ˆS„»TÀ:ÝAjþ-÷md~Fl@ðÄ€Y¹*ýƒàã›qµû±lÏ@;Ç£‡+Úº€Xžï  NŽÑzÑ(�¿Igä­€À<œHô�î°°-¹[=jv”WÊܳ¬ÂGúpe½•V»|»ha7C…·;�æ1­óÿ¼Ø@~<Û‰€¹võ÷xâ—™Zƒ£‹§ôÐ##6 ¶ÿÆ�¬š••Z™×ä�ê ¿—Ü­! 4dodÜó¾Q†w£ ¡\ì2ìç¯ÌɲˆŠy9÷µæ꽩E÷É~!¡wœXI¹2“-΂^ö ª� R o5pV!;+�‹ßŒ÷=HšLaJ_á]ˆ Û×t9¤�W ]cók-Ô™°‰³¼^Ìq"5pŽÅÏ!„뻯å]œw¤þœþ¬øO;Çi°L5ˆ‹Yîl0»h@\�t̰©o_´÷Ñr}ÿ+wöý:HˆX™ôSÉKÛ6߆v÷œô¦”ȧ ìÏI‹_p¢xäݤÛJO¥]Ö+_s½ÂTžè}#øFÑ$‰[nr¥žä›~æáç½°¨/òçvp/3Ô®ÆÓ$ Ìæø$Ur‹þºsš[`'¦5æK§lûcá5{×ü¼�æÊÿ{ã­niÑ Ux­fÑsë HUØÓ}?,#á3£Žbë¥(î�™7bv%Ã5lä+5?o³Â'o9»ž@Ϫ÷ô( õcØsßñ®»Çf¼6a©S%]öëDÚ£ÅQƒ-—.*[Hpæ(cZézÖ}$ò3EQSk®/]4…ÃI¿1¦E~ƒ³˜ŠÔ‚èbêE¶¬Z‰²“ŠúF>üín0ÿle'ªÍ£@gè´›U (~ôÁ3l-œQæöísðN†ß8MÀ²˜@ÙÉwüv�ß‘·±uU¸��‚ÿˆž¦~í;ú Ÿ¼¶:smxÉVÓ+Tk:Îx£*¡ÒЂ¡®/˜Ç7*«?úù¦;çW‚NX_¨«^{¤#Tá5Ðù‘íÏãg}iaŠ;.WkS©0 ÆH>è¼…[‘ã}u@Aq÷€„§æ+w\á4-‚êak$Ïç[˜l>ûwriïI6Ûò› [‰‹�Çé ² n{Èç÷ãç‰ÏÛögÿ3Gím”{Q+§Ù;�)®\ÑS–@�˜&Bc1›0”T=zÇ|;ÃŽè#ËÙà4ÚÍoúÎ£Š¿óÑA¯ÊÁüßÌå DÛ?V!Kw¿Â:'Tr<íw+û�’zy�šÜävájJ‘q œú—.Œá½H.-‹Kí.¨¤™z¹•׎nN#|Zí�›œcEcø�¡F�°4T-¥iÅrãÈÃÄœã³|òf½d6Tíåm;Bâ<þð~¨·yt=5@òªÌ,^ÛȬ|½‡˜~i ȯ‘éj³ÈM»÷§^‹èKà÷æžÀÖLƒ`ÃÓ˜wŠúåÝ!¨vº°Ãtvøøï.‰kfììË"ölÔᦫ�TJaqâdÙïÉé-ó¾œ2–†´-X�/ ÿ6”¦ñÝmö"É>ÂYw49ä4zN«šýàBpeÃ4_²õ5h€£"¶»"‘uqÆ€ÎÀ ÖÑjn:+¡fôA¿ÿ«ª¿ƒÊû‰ÿØ “jͳ¾ˆ…ÐsÛS‰æ§Bª3!-�ææ@Ìs ‹(�/&Âø­ÁOà¥ÈßÚÒ2³o´³Ão,›1Oµ$Sî¸üÐß¿!Ä­ÙƒIóÂwyYwäîEð‡ÍF…Õï妞"¬žMPs )¦Ëý@�xᱡÚ]Í“'<éæ$2ª@ ÕþƒÕ”“™$E7…!:Gç|ŽåGU¯ê—Ò�€ý|>eøÉQD)ÔE<ÝÕ®¨¬XvÝÝAQž­rdøTd0qà<ÈÆ’ir Ûn÷®üÌt2‡=?‚�6?¬Ÿsʰ¾…¿¶„Šâ0ÏòË~yhs¼Ô÷°Ø�ʵoV6‚$n:†¥¼øÉiöeq'hÏ|–¹ça¡ëÏçEÙ>ŸŽ'.çl…„ªœ«ôVôÓ«(i¢Ñ{Ź’ªž~u‚ëTøôaí·‚ª™ìÁ¢•åŽá5A‹‘¹ÆÃ€f;UÍ2ê<;)-i¸ŽÑXÒF¡ÇDn¡G†Êl³FV+\:íÃ�·¯u²B÷ �¦_ùŒþb}\n-¨R˱cƒÓ.îÔ‚,±-»\#:>ºLÜÅGöœ‹ÌÇ^¾«t’b‘´Uñ¼ÉNªCHsaË+9ÏÆ’ Xl2¡ó�ÖâžKS¯~]˾ĆËP6ŽMÔqOLȆÉñ‚¢¹¦*,7lš_Â(' ‰/“½õùëäíG¬ço#xg'ÃK«îÀ[õæ'p¢4OJyÉÅI,±í�yÐÇ&8œUìQ•³kó95[‹` ÞÙD�ó><Ïò‘ƒà½Äw­+×­¹ÙÝfÆ×~k†ŒÒK?s×s#…@Ó‘ÖéžqÑCdPEÆÉí‘�‰À‡¼L8çwÖ¼ýÖ³ÑRIZ‚YÚ6+ änuö H¤4êmÙB …žpÚMú\‚Ü­ÆdM«(·J˜ \ć�Kšc1wtpãf�;òŠœ´?œ?2~èQð|4¿[›âA•%?¿—"¶d2p^P¸ ât�íõ 8�F1Øž_™nX6ôœ¤ÌÎmÒC¹|±ß•/e¿ %eý¾èÿñõXÖþ8ÚÞ¹€K`w;¥3I>ø¼­ .ß§ZÄgçqIøô±[fu0­}Ä©úx‚æJÁ¡A —벪BãÖÌ«@R•ät£Îƒ¯�:¿Ú‘>°ã7�A›8+†T÷,ØÝ`Ê–ãÞE¼u¸*TǶ£Î‹‚¢’¦ºÀ€u#‘[ôÀ?Î9X`‡@ö´]¾l÷4}¿É•bÎέ‹OM 5H³†K­ºÎ­ksÅÒ€µ5S6.7ì§€,h¬õ�(æX<óoú®‹©A˜ À�ŃZ.aÄæE»DÝ?§!ܦN´bæU>ý%Lséä•�:û¥¤r?D—ÿÛú†Äù壡)åË+㈙[¼"o:à5ƒn¹wÞ�$7 Î…cÃ#�¾׸IÔˆ†?¸­“rrKø±‚ËÒE;ÍgdQp{ŸÁ [~5&¾‰iÕ�óqïln^Êr8ò0lÚ—-žVþÞQèÛö@r�Œaß‘áb'àj?˼ü¿¼»méÇ�K3ÙÙº ‰l@Ót^óƒüÛ@‘eaå)tUSÉgÓ i,Ö§ûTîºÏ³~ ±J=$À´“¯5Fs�Í;u®S`ç«:¯”•!ÄSΛñ¿ö¾ Š�«ÚoÇ9ƯÕ`eÙ_ ŠÎckr•K ¨ŒÞˆVÄ>mvßšùö°ŠdÑÆq­é‡¡ÍxØ^ŸäXVuªáb|¶ŽáSL=å0Žl ¬»6 ;y0=Òªt\Dá |ûlOZ’�\(ôÞýJ1aõ\~€RÊQ¬ kEÄZ¨·ßfcËŒ„KÀKÀ#LFÙÒ([è|m3Ø“>º­ÙY])ë”–œk憶jÏñ¨�¸ûg¾ý�­9¹™X°Uæ GXòKä‚—ÑwJ“@¯ñ¹ŒÎíO½]A$>â×chÿ­ SÈ€“/¹„»1AâÐw�ج íJœŽ‘œ³æMó4>­©ÚËûç$…ž�á ÁTê{�ÜŸáTþ&,<~RËKzB_»d>u¬¥Ž-¦m¬Ð?¯Ž‘Q\caìÅSaÈûÏs$ȬÍáe£sÅ[ƒés¶€'Às˜™2¼.±<ÌŽñaHˆÌS»~$TsËê8ÊV7Gð–¾8—é…Ö¡{÷º��í™//‡JU'‚-@ oXgÓ(õ¿F]MÃ`8VÒõH�Ä•‰ý´¡.ŒV{…%«dNA§†C­#°ôäùèý�8õV™¢¸ºc4jÕ 5x;„DZRßbÏž®÷ã¸Aq b-ó?ã\cÜ06Ð ½çïÉuß– Ò¡âC—~ È;7“ 9�°å!röÆ$Tª˜Y�lj�~;5GšÍŒê á*üÊt”–¹É”Â$òéœÆëœ>S�B1>ðpGÕmó7Í•ÜûþÕN•ö|÷ÿ^osÀEgå CÝçšcÀÞ^åré¶þÅÓ6¢šj– .d“Óq©Gg­.™½p¿fı,Ab;}*xd»Š3¯Þô¨Å«Š£÷'áÓªÌVQr+äe§ßñvÜ•ŸÉn‰¡4Îì¸[1&V¬Ñø_“5ÑFòÀü±øDôÊ,4¼ñañù»žž+Ÿh+Ì£‚Yp‘eøÒÑ—©�_klWz¸{íÊ!ç’®¶ì«Ôl³[ MŒ«ü–\bi‚Ií&Ibë…+ZóO€ùïCÚ„hNšÛî ÞeŸT8àÆèMSqÜŸV­¬~lP��®ÄÆÖ?ä TIS[CÑË.›t7Ïæ°Š—ε`? Œ¬s&�¬/*\o^ø|¶èÿ„öšV¬¦ DæX”œÓ�6¢ Ç ÆÔìÔ#ößM�;¤í°dmÝ©Œ1¯�‡3xVoÒ>%n=Ä7^EÓÞÿÌF£!81¼ñ€’T¿7‚m³Þ_ÔÙ�™ô¬ s±þ’×M¬Cæ|‘3%GTò4FkSý7æ3EC²‹Õ,¦©bí”~©S™…yø·~Ri,¥ Hyó—t‡¾;cRï�ˆxQœƒñ Íß9u.Sw)h(X$�ý‘²~²·3�Ïš Û‡ü‡å¶ØµÖí¡l®H;°íc5†øƒm%´ÐVýßkf}†1.ˆ�~Dð…:öAH[D<Ü5ãSA8Wä’ŠC_òµ—MF!ð’|ä‰?6¨\>ˆ—¸p$KV7 9|Š@û &m�e*tªþs«DL7 HSÖ*¨P2ëŽÄBŽ÷¶±Ó c,žN%µŠ£8£öî' {¹¹5»¬ÌExmX§¤t›U³AF)â�kð&Ú|ÿlWn8é)Ìš6°kÚ\ìcÿøÄ*Ûs6�w,<èÂý¨yƒ’ÔÖÇ hà ð¾R¦.)ÂML­th²##/£D#!ËÒqêën0§~_—>þŸ²çÃÑBR5Í¿l¸dÐOåó-ಱD¿^[Y ­?¶[ÐsH^æQ^ÇâF0*ɶŒ/7îi?×ÏÖ“.]D¡Í-âu†B@6 j¸ªx÷‚H5À#0ÂM(>�„$þ¤Ý–âîfLá¯iQ\Ã\4G»ölKOpv¢øR$„™¯RnçÔŠkˆôDÿ�á&çõñW•º3))m`\eP¾+C籈N ÖYB‘ÙµùÊ“lëôšþ“»ÒTyߥU÷¸Ý—ÞßÀ�Óë¼–,=ÝðIÍú°nrâG¡öõ ÛñÀ:ìù5,ÍîoŒW-:<‹I·‹-𨲾,ÿ�v••îª(%GT!…Û.KÀK‚¢Ò_ñ ¿ÞT e4âœónå5b¹bÞÑíÔ7‹Ôƒi{+÷Ê.ÇOð«\"&J_/L�=hyPåZNš )Ì?ù·”ñ’Î(<Ñ»ùÑNû’iB ×,X'ëTüonvé_Õ|Áw/÷o WK­9�‰6œ*qÁ»•ñ¨†SXæÃOÖXÊ.ÁnfrÔbB¸ŽIÃâÚ0C’쟺Œ~ $:Ì!ÜÂù3þ Ý"#l­I ¨Í¦ûLRËÌÊÊvôÜhj‡^¹�ÐtÍñàö @~bd™oÜ4 �—çQTXؾ�ï]xH‘è&¦ºÀiR d;x[X²6rÈN/ÂÐþÔa–N¿]€££µ8vO…y9Ñ q1Ô†E÷23ä&Ì&Uøó“V¥>ˆœEÌKÙßï·ýïƒ{–<¬üßJÎÒŽã7äª0»C܇hÃ�!ÎÆªæŠ¿aUÒ_P,Œèǫӿnœ–ý=ÙÖp( ’7®oÈA8´*;��ÔæNÒ£?‰dÅ K(:÷Ø€d—TÅt­(™vµ·˜žÐIMé"J>~|- Û)óöȩپÈ H §®ÕFíÖ'v ¸2Xß5Ù~Ça߈¦ûâ S^½Åp£¿.’Åí°LÃljg>È )�°yúŸq½Û2ÉS@Ü@7¦<6ðí¥ðy£RžP²·ÂeDý”Åz~InR¹9ñѾ³Z Îwlšk3À3†ŽÖÍi1QÀRÑ`ÂvÁÃRHU€D݆¥Þ×§3·. ö‰ 7Mþ¿ð{"œª3IR”åU¯å/;» šþFO™R+�åº …n*È;l(zg«uþFw«Í¿‚u Œ`nˆJ,ú1 ‡jw›V‚¶5rÀÐeDmr¤'ÑÔ¢›pméëG­ì¯éA÷"öšm\ZýN¢D@ù�X ‘/¶d‰¾=S|¬Žµ1�,Ì=gèÆ¾ãüaf}T2û�ëx9·¹ÿÈ�TL¸ó¯î�U*[dó“ì ™8|Âk»IÆØÑc‡ø´¸µÈÙüÅÊ�øÊïRÿüð·>3ðÓìÉÈ;LnžìC2šsKµ Ž7QÙ/&æLn¿=Î㥠1«q$îªzé]À� ¾ ïËÝŠƒƒcZf]¦F| tʦÊBÕÔ‚< ›ÀÇã‘KÚÁÈ´3¡³oÓ]z‘ÚJ3Ós¼{<æån�½Œí=($*¡V­KÜIé`¨od·^‹9|cì<]}û½{âõœ%Ð_§&ÆÏSÏ Ëé5ÏR>rí{�qééòÖoÑá…J v±ДnfíÑ-$PIl³YÜ‹nLêpÀàP}5%™‡Cåm�,›ÏœV6¶–~9„¿HÒ¯¸|Ü<‡ oÎwÌäÙVoYxÇCÈûR?³îÈ›]³¤#•z³ï.­ÆØ�»øše'Ô ÖÔp�•¿ÐV•ßÿ¿'UXDe?ˆî PåæÊcþ¸?äѬÊÃ�@B`9^TdÆÍi€�’#GXZ´»}ú7HÇ}.WmþÌ�TÆl4ûa€³i[?CJæƒ:È}3Ûb¼èƒ»»þåÂŽ&›–Sž²£o½Vµß¼Â^î‹_•£'.Ý3Cmêÿ¥ ‹h˜¾nÁ¿¢ŠŠ|Z¨SEë+µå €Rø©ÍÐØ�‹i#³�à mub=0£&aŽp¨[Y þ öz3!p´QD˜¶ºÇbæ1±—‹x¨§äÖU)óÌ6™ev[md­ßÓ1¿Å¤ øë}~±]‰å5݇ënãhÛ_¦=ÿÞ�¡ªïîüªÕâui:'èì§¾—ÙÛp‚>­qéT'éÅX-â–Žh6“{IIëv9ýK/eã™Àep4(Œ¼ö–§/tAÎM9å9Æw6è$ÔÛÄÝ�’˜Ï7Í™3ÖÏW°övÝa’¢#À2NL”œíæÑÄ­m¹bh¹-[GÅôY›OË•É%¯?…VXF?';àÃI}ï_Âæ!–JmÃÔ 5ø©!“þÁ×FN Y,^;®ÀLT¨ß‡�' âüýê3\Å5ØbÙ‹S¦à;—éN¸Àº I#ºjã_¯×Tg'8»²¿ƒ>0�¹yí6�•23E·°™Á¡8ËòSj¸ÕpfN'íþø4õSh.h6À*(0{¨žC,~QЩa‰ ­«z¦¼8]E˜±œ#a�v¹ÎÚ¼Oý´ÂœÄ×Ûe@å³I=ôä©^Ó ÅLL™B÷VŸ§·›:}~Ÿp!Ÿ‡é;²,úÖ]b§`ÔJ_ºÜ(C†fÀV?¥L @ªÓ2gj˪kºÚ´,ÝŸØ ¸£Ò'ñp1«­”нEÑÍ–o¸­A1|DÎ�±Qb>y/wsýr–î�’_è ÛjCµÑ¢*ç�Áµ8ñ§øƒãmA¬�5û /²ZäÀKµ–8íž'ÅÛ3õ´«‘‰×ŠÞ�jêT7áÇ.1a(ÝÁ‚)R«…ðHÓvö�L½˜  ‘|Ä$uc^ÈäPÊàƒÍ£«ÕÃî|Ú»”Ö™£t,®?Q*c�ûU½}ã¼h\з³å÷~·à+×ûïE¢J6‚;ÍèY( ­Ê£û.€?hG�2{·‰»S:$“7FšÀ%AÀÀÅv³Ë®DÙ]$jmP@ÔïË;¡å¼i>ìåÜ‹gÿtCñÆU&iT Xö>³îé{:©ÄÔÆ¤*}M㇈ }< ”ûÌ?Æ î‹$uþÙÕ®² åg„Éy×Èﲞ¢Å72ÍÂ@[8—"Øpá+Ç árþHð—îê8í.®æ=¿÷zËwŽßnA¿Œ\º"TInZ3@C¾–P¦e}™rs$†–ݲô§<)â<¶@8-QÿæofQ×Í0Îý¹`ã±jñé£[0äöH*}ÅŠ±÷šôaáÚrà0ŠA¥EÖ§Žà¬B°=“5¿!ByÑ.ËÛ–6p.‘Ù[T*ƒ„Œ÷»”�µL乕à»1eš¹v‡$HÊ~7††L{Œø1T¥ý}ø¨ÔÙÉey¹î(Xá‡tEŠZ¤‡�s5ÔDˆ>0sñ@9xvDº–a,Á¹™¶òdÈåc úIù0ﬞ¨^R·-èõõíu=OFmuÍN¨“éjزú¿·# |õ|W›$™T¿0"PÍÒ±´TÀе siáÆ߀<Úzkef�À ¤sFñþì´h>Gµ†0§Õ¡X€|‡PÌG­3>â¢ñT úůèWztÐØHæ“Xí27M’)-’8ÿ0³»ÿú×ñ}(§÷­å+Œî�d!à0¯uçÞÄ�ÎåŸ÷â“Ê× iŠMë~�U\Òë1rBoáBv>ìw©áD›_�tà¨\=mîï«Ý{ã+ ‰÷86/ƒù½oçjpŸ!ˆ7¯“ä¹y:}5¸$QЋ‚¹tñ~½˜•`óÅ$ÂÄõ1‰ÁRL2/^h<܆Tz–Ø [Lþi—ù´Žàø�€×m:ºšA§k§aXŠe¤æê‚\o†3Šö ´QÈ5ß±Ä)Ч¼ÓŠë‹Ò¸Ù8˜§Ö*æœ&_–pW¥ã¢6t†‡t\z)YÅàÿ8:´J�‰3ÓR� éò*ƒ]B´L±$¢¶-i€ÿ䬽lÍžÎl7‡ùjåR”ô‘ü™Ñ%Úå„Û³�ïóìZͧø”V\ ¶”·úÎÖܾí?†òqëSðóm“Ân‡2sÛ��¡rб»”3h Æ× ìu‚š@TUîe.º+·ƒ1¸Ã’ƒ0VÏ¡§­÷%¢ù¿ÊíV¸b ²lgJ¢`¨ïÈv u=' ãÿŠá^^Çfñ\š˜�¹²û 1mŸã8­ªí4`$Šè7RÌšá7ˆäT _ÿäŇÀË\WÄ:EøfоHíF.ëó«“Ë…CŠÉCzÒ _å[F7L_#²Lë;ÝG7¢FöåË:%ì–¦çhXox›F*cì*L¤Ý qJO‡Ž29)¬Å’õSHá¦RÕ#lþÆ8wð†ô‘ú\bžü‰½7̱"n:ÏÙu9°ÒXÝKŒý>~sñ·*‘‡Æ AS !°5–’,ÉÆ�e–øóê…°µœ„c’{ ®ÞSqP¹`Ht.ësòFèÔ‚†ß‹5Ÿ‰dq± ¢JŒÈ=¬¥©«”Û�ô|ɶ‰ÕÎQ¯6qm×Ìב´4ãz,“áÁ±�9¡ÝÁD³òçWÉ�˜ÚSÒ{À7+ß:œÑ }ÇwyÌZg"Ô$âë•¿‡¿Û;×K:s·�sœ ½UKƇ8ÊxšÜÜ:­dG¤°ðxæ1ZS°Å9øY&=fºeñ3Š@×øÊ­‹q²”·<.ÅÆ�Ïõ!6—B<ˆõ8ÀÛßä&”š^³{»”ïÆom×±lÒ’zk\ù#a±Ú]'9âª-ŽSŠŠ•¼gëïíi?ãį Ê:%~Çx%ÓPU¬f‘”æÕÊy®ÄîU ­õËK  W•t™T9®cp'²GÝÒ êe#$ÐÚú³ú^ÞÏ|b/åŸÎ#ΫtJN_bN¯&Wÿ; ¤È]ŒÇIMÛQQÿ¾ÈDRyaΛ Ù{‘œÕóϱœ¶‡àÔÇÔ_½¤áV¿*±Š«Þb9”CµNÎP’ï..G=¶è sºÍPK ÃGÚ“R-Ï1œ-ßÃílNoU$”žaš­Ÿ§ §UÑzr�IJýÒ¶r¦o¯ñZ×hñÔdúùÜÖuZ*Í0tˆ†'Ìò¢àû†¤ÞA|@rqœ°_ô”Ð�Ý–~l8¿<ª†À�¨ð·UX_b´£§!Knî~G;¨}¥–û“ã?žldAõ:üd–µP¡tõ¾½xò£%+D¹ìL<%õ‚þb‘Ñ=Û¤ùÛά$�—im?Gpˆs›”ð½”ÆTv0 ØÕ9M�ãù•‘BÏuyÞ ËÕä #üˇhU¯ EõÈüÑ¡œ]¾É”åÜJ,‰=Nœ!'› àÿ4üt�œÒ¹Ç’_WÅ«¸©GDÂÔ¬~¬Åk%Ï»¦*=×õ94ƒ­B íûQ» €éí|Ï™-±ŸœSÚ#+!Œæ]@&l¡�°òÆž¨ÒCEéŸý¯Ù#ß×Û}vûéBTÏY´Ùš,:e�ÒÈ+u”B°p‚" š1ŸŽÌÓÕ…é!4òÂ)xÕíH;tÊŒ2ÇÒ\9M«¿OyÆg)ÊöÓ'V~1¼/o¾¾ªh5¹�оS4À&çhÊFã©õ´IBô°ÈW.m˜%”hbÊ{š»A&œJØ&Á»½wɳÏôé“ýéÖ²&w¤=á(¨¶òg·W×íg²P!V¸züa$®€ÞB~ìÕa˜W(ÞdçĪ/«Ëјœ3çêÄ£ RùŠÅ!øÜWhþ9fZE…cmÎàÒ7ãD‡?2 ‡ls»AW® Cû&`¯íTÞÏ^Û-óg‰óü¸éQÿ ž! ÖÒÖ\€ä†eáø}�„lîÓk™õ ÜÍëÛ@³óP²L#�Ó̲ZwÐÜ/€8½ ÝM¸›ÇRœçWæ�ÊJó·å>…@*ƒ2]v«îufþ²äå�ï)Bæº ³,6§ã ²#ÑÜ�{*±ü™cŠ�¾w”Y¨öú1Š§Ã‰±ëØØdA ÀÄ3™ñÀñìQô­·ßˆhzŠ$ôÇL|èÿOKŒ+Tý¢µŠ2ØÕcš¿{‹øK~®]?Qý&ÓFâ*m7ùìNQÓŽw¥}ÿ·½±±�nxDtVìõ‚áB¥ÕQ;;«È‹[>L{Wj9jʽŒHÒÉd23úzÄç™Æ[ IP„"x< ¢bó�µg ᳤u§%Ž(ªÒËÖ»½¶ýÂX’ù­àr=~yÃŒÚó¬EÍ ó•#4ï.¿žÖ ÍE*ä,%ˆ]‚™Åyê.º�^€Y7 Š\böLà £ÑïvL½ébq†� ó ¿'•ëìá|ÐX rºÜu饬ÝFr0�b̪ö0x®ˆý€«2éi¥q®Ÿx뎄i¼| î´O`Ãmt<å3iK-V´æ÷lÖ!ð›*õ{ˆIgQwYóu£µ°ú&�¹„Æu}Ê*ñTòv_wDÁ½šªßÕ-Zw=€f�átð¦Õ_þÔG­¥æÁ}Aì¿jÎ�äì+�¿Ú¬‹0Roœ”¶RÉY.£Í í•S0øBÈ`T_±P@4���þ]€ AŸ‚d”Tð�Äq drkTÌ yü$bŒ ÊÈȜۃH“Ôk ‹G}Àî a/¤ÖØFQ0QÇvq¯ÚÜéû<¦{5 â±É¦ À‹2€Äˤ„Á@,^zjµÝf‚ÕÉJœ1�¶¢×¥‘Ô¾\³êî>RT_5ŽѬÚ'ÀJN©Wú¨MY×ù9>vq•¦LƒG0H&Žfˆœ9HvÈç9Ï�çâ‚)¢ 0)Ë €ùÆ Ðw¤e r8œìMl]×E�à´y]ò�ì CW¢›"«eHb7ÈÍ=vêG6Ïy" 9¸ÌG+*ºëàçÖÚ°}cp�dÚ)�á ±Ýôy}ˆ“¤ÝcrG \Wgl//ÇÛJÝh nÌ'0¡Üܦþø`–Þ�w\†a翚äÿ¤2zMäÏ<þ¶É=€ÄX€ñð.J×7 }én˜DôÇ&¤Z„¹‰ ª�„écÚì .'œ8Ü jX°%ñÛ£ ðË2?žŸ(�ã ½S¾?ø¯EÌ!lÈ`'2•¦¯ÙÍœù*ÎcжqI,�Õ.@Ç?}Uì< *[$ÎRXºâôCÜ“TYºàг\ÓªÊ(7ß:Í;¸Ä{œàÌ+ùÛ�ÐúŽfÔù¥§zòBF1—f‹V(_.=´g„:Ÿ=2LL(òeo'N–opÅæƒh¬e[u!…>±�‹ÔvÖœ=3&•Ü!ô9·I�—€9š&8Û… (ƒŒha7URâ%&Ÿ ໚¹º�sýl>kª ï5÷$ÿÓ/õÃÿeî“c-²â“¯ß0ÄÞ» º—'fÝþkÄÈ U$nÔöC~¸È¢"9äz{º©ŽCV’UD @ëWØ2‹å3¦DI‹‘Ð74h3¢¡�‚pmCát¾®»1kz=?Wƒª~ŸÜ÷ébqù Ï¿ôõ"UH¼®v$Ž|„Vs‹µú¯jý¤hßûgnþ�}Ää…ð�»Ñ€Ÿ£nGÿø<­S0)Ø Ì\ý`bª—”Ö 'غÆþ?¨ÐªâÎ7íA0ìÝAd¤/õi’“çVr�š{}zº°{ÿã %XëÜà3�Þï,Ü\lÓ¥gñ}ÂSq¤¸ÇÐóŸ7å«ÈÕ{Gg\Ü–Û`2R1á±Pä“_xi ħòŠºs:'SÃV8+¹üÕÑ­WAª«² “‰¿l+ƒôTà‰dÃ&m“¶))ÆS-ˆ0)Æ \,›~æ@ú@ ãºÿ;Û˜\Ñïk"²Ô}AF§®›W‹`¡wý{$=ÜC�ôå˜áñʨu›ˆ³y,ÝmçÄ_U¡çãÛ‹ p­¤¿%݃ø�_“ìŽþÏDÿ–V⥻¢|ÅÄÆ Uú[]çzñI–?ùËjkÞýÃ8…=ul©TŽOõi•ðgÙþÄÌÎvaXæ�kÒPCìÅ^Tn§Â! œ¾Å´Z©ƒqÐß\ì3Ó‰?5h�Zßä5ÏòYñu} ­©ÐÛÓÎ,rš,®ü Rz$up°…*�TC|IjñŠ�Tî % |�áé/‘õM¸œ éaùàÆÅÏ칎·x£Ù wOWÃl‹@kåê½(W™<â‚iô±õV`ìÊGnÉ”#pQäQLŒý%²>—¸Ž¹/bod®Ÿ¢4•°$hÌ'w:Ѽs\Q.#c916Q†Ö’n2°ˆÛõOõjW)+„�`;ÑgÚ ôj·3*J X%Iº”–WµÍíŠuT�Î|ƒåÔù–ز UÌláp}‘ЧÑÛÝÜðÿS¿"((r•ÉÔ=‚¨œaŽ @™oÛáe/IÈT¸2b÷n�·qÀøViÔÈ+ùÖ~@tj»1Ã3rkÙœŠ†X° [ÊZ½¾‰iˆŸ' ƒ”\¾žSººØB׿¯�5|ÑÞG‘7cƒ˜‚͸Óï\˜/§¿÷Eñë ,“jD ̯*X¸ "JmwYJÊi[¿ýIÉiS¢Ü÷Yß¡)ôcåÈÐÍWP6û^hpÒ±R®á‡œ.s´ïL¿@ø¥´7¿¶Žœoù êÅ%ÓdȆÛÄíÝcBà­ƒþOÒõù%�yùœY¯€Ïk=2P�¶ÉFNÆ` PTÈDù�Ò:`¥fûýã¹ÍEšxóý8’:ífɸüYZ1²mÑV8¿bàÃRLÕÚ»�Àôy¤ØÄL Lƒ~�«Zá‰Fÿ÷Š=²Q®MpZRKùâîÉ5O=´X%Û_—d3—C�fñq‚m¹JXýóeüÍe,�9¿h•4óYïпL·zä¾i%[ªØ£ÈVǰÏiE{ü„?Á‹þ9�l~P]♕r>è< �ƒêžšÔÚ9*bÚ–î–€¾àò>5Ø2B,¾*;ÝQ£‘fÛ¹w<át‘PÜŘ™kÎøæO}6moMï+³ðº½9Ä`x«áyÇí·¤ ˜ý l°  ª(ËÉq!ñjÕ4aÙW_ø WeÌ)܃²J€w}é G#J–k: !…Ö•3Ç÷à.²ËYÜvì¤ö 8#@¼mÅ혣ØÎÐ燡]Á<œgª÷{ ’Q%ÀP•­¸a�âÆ4é-À÷Ô�nsR’TЍq4½Á¾*‹÷†ô(ÿoþk,Æ]ÿàŠfì®'îˆóÁµþD71ä–tªÈ£6Èód¥Õ½\ÅáÜ㎡&³UíQ¹7ŽÖ¿H“zµºŠk÷Šå™:_˜‹‰ŽdÊC€÷dm£”Щ“)ÿ›«oóŠÊ¯…Ã<¬/,9ÑŸ�ôN‡[ÿgÞ¨Ñd°¶¦yö-ñîhQènº–1½)PF>뱯vVå‹ÍÛŽ{Ùbo ±Ð¦8‡¤ÀšH&/É‚úîSùTÚ«.̈?àV|¢Ñ¯§×–Ú„Gð®òca”jâkyxó–í� ä»3ïª}ÞbâMèWøEt%ì \ËFŸjÒO¶É7~|h‘’›è#ùÿêÌi n%çN·Íl@9r ó£oIM¦ÿc…�îý¾[%\�ýRC!ãΕëÌ‚ù©*–Q<ÎÔÝò‘±0éX¹dMf,°Êsj [m&�8½>Évßxa©Zè³ Iž„xn_u—êéÓ`GëÐViüÄ~F—ö…܉{óE¶½¬?¹ãŠo§cäºý~=š¤6°{X´a›ò[§…â�]Åd� “!\M>Âe†–œ ?M ³ŒòE1‰öeÀªê[ml‚ã"¥#IÊ ¢’Gu�¾ÙV�”ÜW gâi-ENúÈœÒ> I˜Ýû‘Ì FϼÙÐ<¦ŸtÑ(VjJ/6ø©aŠ;Ai£ªÿ“Úå ¢,Qq,žÿº0¿ èàD`Ež¶$;œ5h?êÉ7OCoóœL¿§FÃt7?¿s'Ù–Ü�ÏΈ¨¢"auÄì7ýÙy¸\&"à:†VæàØo«ðçcãra$=Å[Žp�înujêGÞ¤Úçƒî ‚/…@�Ì/0ì’oFÁ€s#À…¡kàа%E[í$ì2'\œã/^D¼¥Òö¦*tT<ÛÆL ;ŽO{úUèÖÎÀj<È.?ÀjAû¨lþ–À”�¥7-Ìâ, 6b9^Ä);Ÿ"¾�…ºÏD4ópç‘= �ÉÚ¬Q˜nj»05|P13–t „/æëfÿX¶·ž–õúì ‘±x£Z¢"xDl‚ûãê#_G Î,*|x™‹2?.éNåÄ¡ÿ;ö"Qß%Í!ˆµÐ2œK±h…Ý!iß÷ÀœËþŠË@„àÍ<àË+yæ0�2г ,é„y]ëí½j¬:®8gû>ÇA'“ðúÄT9xߨù×¾†ÿýi5/GW¥œ»LAŽ5iLæ…8J=È­äø‹bèS®†Zã°w:�>óæ…i|ÛáòI+ _qïܶÓ똢ëÛûj'/&¯‡ÔPsØ7Ì“”p�ü”@`›ÿZÔâº%YG��ºF‹çÁJÿUG&;%àx0ØÏ«�Õr§~FXÓ¶InDtP©¸âé-C˜ÔggÂ|¼¡­1 àÄþÚÝ�ÌçÄ[Ëü¬—ÄyqпФ… Ê?¹9�¸ÿ¼pâ¼�´D|JZ w°˜ …ñâ cK˜ñ¸]DW_ÁT{ðÂ@BA€á¶¡ÿ :K¶ä#_Þ ýÍÊÛ�¿kt '`pë�É”ž½}žÀ¶ÎŸüôÔ‚õFåMÆ:üÀ½¥p·dËPê½T<·)ïRúõê%3g”åíÜ<=®®{XuÄxŠú"]{cïåɹ^¡ƒÒ#ÃÌ¥0S3†®¥U"WÜpeËêZø—´o};ãv áxÊ�!äqw@)ò쓉Çl®�÷þ Î,þY¡>]%»JåÂóy9$›[—w´‹ÛcÛi‚ž\Õ µ±ÉÊ1%–ÑŤOuBÞÖÅ†ê¤ø\t¼ÍËbèñÈ&”VaúëúÈá»¶åëÀÛ=(z§Š�?r»!}™½Å„à3 Pˆ¡¡þø αFcz5m D=¹‡~gm„e§îÔKŽ=/'z»\Ç:%§µ}ÎÂ/&ŒÊÆ�-%áOâ—KšiZn@-Ο› mUÙíü{u¼t¾x@”F�–kfb«¯›ÿ�X¶å%�ýŠí$,j>¸æâáÍ?ʬÊ 2�GT$¯-K Êê€,ÿ&ë¼IZwsNÖ.á�£A›ÇMá Z¢e0?ýñ wDÜ„€©F [de}ö²ßõtku’ÊRƒÐÇí�_rðãylDépÐ)X ‘ûM§]_=bƒ`ç[$’�¦Œ¥£{RcTsvêoж ~ u€å®ÅÀ��à)¹7°L ùŒ¨¢z´ª•O‰ž7(Ý,u¼øz=Ï¢ß'Á¨\²?ôö„· ôAñ**{Ù†¾+ !9’ayÝÊ’»;­¼>‘½½wü”TzËRÜ“¥ôìd$ŽKpñ»÷KAIχuž,›7o€h}ÿÔVímÒ!昞|CÁ†TéEãK”ý—i«“YtŸTÙxíŒy�³(ܺxnVí:ùwÕ%© ën„ vw7'Üœâ€Lª3Æë‘8ÇIªkk“™(´Û{8ÛÎ2æF¼8Þk&èÖ©RH±µä-Ð*„S´ö&/FF%Ÿ,Éã× ŸW¨Ø�•U_ûÊjsˆÂÂeÿ‚ö}9<ÀËk¢¾Þ /,Þñ#²¤‚×zï[$‘ï=Ý:k-ôTOMR§0u 0õ1Œ¡À±™²‘Ûy˜²š›!�ñýi´Ëëÿ8iWÊ5¸Ù¶á7ʉr­¶®VüÔEK¡à2a±�&ÛÕp¸=Ä‚ê€ Í¼–÷I‘K°Q󖬥»«°Èž°pÚØâ,(Âñùå(ñ"£yО;Km¼"÷üw\n=+-3ÇËYïíåäŒoL§º>åóãý´v:lØKp÷Z¼?�–4ó�dÔ7Þ8š¹' ÏŠÜ:�¥<¨5±â²€®„òë\lG8¿ Ä %~c{�{¼€8ï9Mî¥Îå„G[¹Áþùéß‘†{š<,O~–îE™n´�F”êùÇ^¼³wOÖ÷®¸W¨ö"¼³:ªŽ'û),2ÙЇ›±>y÷OÅÚ×÷­Ms¢uåÇò… QÉQ©ÌŠ7¨‘É®�èŒ!çf �„ìÂ"ë—-ö@þâE]ù®^V‡ê×õ©XÞšõݘùŽɤ…à§óV¤4çD:ÌÇuÈ„÷Nh"'˜šæYÿL"†«¤ÿü©-$R5Ð4ṓ赓µýˆ‘+e©‚€H.½7G!"ú�ÕJOEÖýé'¡ÐEdžõåÜZ áh €)¼çK0(޳Ö:0‰ÃÍF?Ħ�Ö»nÉuektç3,G©œZdÕ  Û¹r®Ih›+Ö|‚PLÔpX+gdó6>�Ê_ñÐ!�GjÏ$v·J“TÔCxö�å-Ȉé‘êa¡ÁžoñRÃþíe�ŽÍqw+$Ykãšb÷.‡#®]È()2®Á;;1_‹yÁx™*££5zØ~׌ 1uû8B¸qŽobˆ1Ö¥ë:ƒ}?šÁŸ,\ë¸÷kЂ ¹Öð ËöU§Q™ ¸¢�jv2ùð@…ìœ#ú¾K²J0õðE†ÀCãˆLÀ5;,"4àû‚k•X³ØÈ�•ä¹³€ð…Y ¸6ÜÖS ¸[à€CÉ�ÎnºÇfF1žŸænGÿdª ä8öÀ1„;XF{!*ø3Â@—w?ï5*ßÝŒ–ˆ«úÆgÜ1²Ïš&ÆC'õdhvL}TêîFmžQh2$Ó7:WÝ6UX;—–¿I¦„q›tâ*êâïÓ7ÒøJÄK-f8§U+Ò¬â�3¬>ä·$u&vŸ¾éú@ÇÇÁ1[»ìi«È�1Áf&¿x¾r{c•±svž¢÷»ö@eîl¹°søºôGL+…uÏ0ÿ Óˆ0²=-£v¼Å½t÷¼wB·sRQ¨F“t¨w/0.~ªžî•x2ûñ7]ÿ›gÿ�&í`Õvœ*ê*bªÇÞ5eï©ð`SßÿѾ‹�iD»ÕwýÉ|ÚF"71Ãîº xx$ÈÖÚë¡ÄÏm¼ójU6ØyžGîrˤáÒ\\µ†™1O ûcÝÀÊœw‡fVÊ÷ýÓ(ýVÕWÚTH&ë9÷uI¬ˆÛÌÔÖL¨7•ë»ÙÉó§ÆÜŒ{ÊZ'^PFÄ-€§ÍKç-‚ž­ÎFbBž^„ ¶û)ÍCO�lÑûL¸Í÷ s±O“³WŸdêËÎØ#g˜þØpùð±R ‘‚G%£’wóKJ,ìÃÀ("Bó—Bø�›n»Ê®Žy_hÇ–¶F"„!> AmžÝ{=Fþl]›+I•»`;,ÜQÛ•HhæSÑzqExXY��Q(ؘ)îªziæöXì•�O®Ý�� �óˆ39Ilàó#äŽTüŠRš}ûA4p¢w Þ%â&žà"êL—ygN÷—3†™mê¦!†»eL çéŸ l¸&ý|ó-3Ø Aïè¬ìoéû¬f#„D lî35ê²Ç=€ A¹ÙQÿþ/°,kb+£<* YqAk>@–VÛãMÈFÄ!»¯-ÑÅìÄ[<ó8µ‘ôIçØt ƒªÓU¤Œ)+"J!#† ʼU`›}ÌÃDGLÑú;àp=ÿµ–x¢&ɽy1“¯uEd¹†Oóê´Èh”gMç��-ww~ŸËÅ‘+?:ØÔçâ…›@±i=”ã ³Þ˜? ð_rlÀç›™£Rë'©Jþ‰ª§Öózi£x¯$ÞK.+Õ¢û [ž¢^¹Ä8 ;V 2’2h!8:gK'Ö�Ï2â_Éë¯~%Ò~‰Q~$&Ÿ(eD`}[ºp3"‘¡ó j*bŒñ»|¢Î£!æÙ`î…‚dúÛ'õ™àׇ3“2--;ˆ�]|‹Üw:ômId 3Àãñ›Ð†ë}#’+w8 âÌ@¨Sâa11Ø~_/]^a�1{V‹FF°¸ãÌMÅ5¦ —0øVÂr¾ðÏ?ž©�‡pàSósrßÔòÞµ5(º A®¬D¤rfáŸJ\ìÖQ$ïpÿ–l)èÒsùô@d¥u]o€¼} å9_íÂÁ2Øóßlh½ wEÊ)fn߯nÕÆ·õ’ÈáäÞŠÈ%]Î48YŽšE‘êoÙ‘¶ =‰·°ÑUx†¡ËoùJ^¡…u'5½] ©ÿÓ`‹ ©+�×èƒ6ûŒ:à+»@Jƒl$ˆú„‰ub¾Fû kP¸·øJªoÕÏ[·we=+ODæi2ã�Ïw¿ rµ<“–†oý¹!ÖsY°hBý’øÜþÆÄœ Art�>.áÀµæh]N9©eS£åTN�Üoª ‚ß�ì$‰Ž­úÜÁT’Ä obÀÃ!{ü _áâujƒ«kØ8ƒ…Ě¡†Þq�c~2 §ÿ¼-ÌpÅvüYkÔ=MÝ�†âÔÙ' �æ«0Ú°ëœù›×öÌü4*�5-ùÓx´'B|ÍiÃñˆ!¤˜P½¿ ¦Ÿš7†øÄgR¸ß@ŸN.�ØÞró3ýÙYkx«•Gk \GÕµÙð'¯ÊBêMžl©‹„ºŸ+T/!¡f˜Džåøfú«ä� d;V&rªß“±ø)^‚cÕî[¹xÔ,³)Ô»´@èn5¡uÁï¨BQg3�ïÕ¬²Œ=Ö´:„]ýXÐ$wt¬²ÌˆñІÆ3M¬å¬òo[ÇàŠ•a^à©(tMîu£M;ÁŽWƒ”RLÏ£SÐ 6ç´=¼—ëëí³ÍgÄÕÕŠ¦gu¥e”‰É~Å´eáA÷¶'î1H£wàxH6< ?›cÇüªdÊŠmÆ#nÀùj¥»”ª…š¨j6�Õ¦RMø©š.ìZàd0Œ4‹$Tù¡7kňçõ1ØÌý²pÂA­It%Jößħ¹jš{>˜ö6à.>Ç «éÖ»¸.ì¬u¤$Þº1÷ƒaV+¶àƒSqZd*Ià®X¹7<"»…%Ë–ô†‹­©Ù^Šõ)Á#qïx*6žGSåH}çþs%¥€ÅqÞ¥':®oë• ð©5 î�’y3r�Ü7¨?}§Ixõ€¨er%ÈJ…¦ChƒÀÔToÆ3Ýø;}6¡m{ø9fg²dÎß?8fáÊeÜ�ô"੆š× Šp×ÎÆó:²™# C ™(6À‹{˜ÉÊ; DÁ0$ȉ*å a22ðDƒÞAhzÈŒ ¹O îÑ”V¾~’Æ·G…ïÁF¿áþ<¤üÝ1»äm='$@Ï enÚ}[m4k°=Ãu—娔5�^¹÷&ìü§-D>Dh®œªÍÔPí7„ŸÌ4Gê�; î¨r„Ù´„’ÎÇ…sIÔƒ.�=U;´7R!Š#ޱ«þ9$z}THÒxó€ùÃwG¬¨’Dô<ö—¿AžÇË1¸×;—Xi‡¤®Ê×w0Ëm_!ú¢ú„:¢î¿�/[JM¾„¼x3-É×bJªj}H î Iw•Âyý¼‹PHÕ´Šs4Ë©{2‚ð™ùëÆ/WFâuý&ôY¯ôn©��â‰YÖ«…O½J9ùûðés�Ì_2³—a*ìp16d‡sJYrÔÞ%-?²Ã„Rï¾aOzÔ» ëc §¶ÀÏrRö±·C¬0éÞ#…д`/ü@1JŽ –l±Rf°ó_ZOÈw¯Ú—3ºfîÙšDƒñÀ|ãñÑzhôË}ñö›­cà˱åXódŸ„£µÜÿÝÿÔÍ,Žê½€û2ß]m+KíµM|´TñI^^äJ< ÅS£#óÕ‰ ᔵtä™.ƒ¤üG=ú|q;‰Ae­¸Yp”ßî¡ë.¸ðÏžYfkçËí/‰7hcÔý©Œ3ÀëXö€Å�´¨ôùöQèïqæÒMClû‹3Á»íÄ¿â-Þ ã<éêøLmAR9KÎA«õYÐÅwÒ­#¥\PÃ)ª«ÖöƒÚ¹°*Z½¾�œ¸KÆÔä9Þ™‡cw\�®N[ôm�.‚9+ÌÀ(A²ÎÞ“ŒIñ˜—«(A†ÞCÉ HPXÛ‹;‹EzÙ™ßiZª ¾Ò®x™ØáÍá‹r|…²Ýðíàˆ"6“Ú}|yPKL_sˆÚšÖoB�Åîé?°QJ k½¼O¯¬ÙmSñi¶Gü“¸ã^È_‘�Ë5ÔºéSô7õAÔä®×«lTbÏÃúŠïI½äìW·¸{b‚ÓWž›@þ©Ix¨ª:S¨ÕŸ2T^‰­­Ë~0Ï׉S©!¦¼” /ﺄð¶Ÿv¨Ê}-°kj,âDí~@òŠ“:Ò ��"Èiç29ø ƒ íˆbsõM,Z¬IšÎå䚥nÓµÿ´œó¿=SëÛLx�ˆü– î‡ÐúÝS· XŽ%Ò c½sYÏ+“¥Æ�a÷d9ȺqQôéÍj)„ãáND`(ìpXØZ›(…Žä-T¹_"ãU@«6bþаÞc›Ñ–Ój¸ÏL-ù‹ÝŸ8”=oàcÆ'ÜÆ 鹑ˆ**$ Ê¢*¼ ª£{±Zu�[uCuЬåoKþ…�À®˜ÄƒÐmÛsý2öøèjG¡ð7üWZLO±²Œ%þA72’Š�ÖxCb½û7¸$W*ÓÝC¨9ô^ÄÁ&æ7þWéæ}ëc«†,~AüvdMz]dÇP(d]&»§µzñ~©ëš¯—�…Ô3PÃ,U6'­EþÞ9м¾€¨Ž>)GûŠg@²š`×QªoPERÚ¢`4úAš Má¥&S ‡ÿýñÝMeþ¯BZ€%¶]mÎ\ >°† ’XjÄ!˜P×dzîí×ÊŠ”có_©ìƒ™XÉðFJxy¾|£t@†9§JÆ{XRÈÇÏ_e:“S™z² AInwWî%E™‡[“f_rIºE™BÍ]T©á¿ˆÝ¶æ'ÌÖŽÇÿ0@«f�.4«~:,ý^%6gTo»Ü}ò€D:š£aÍü î‹� Žà�*æE.¡© �Ê›C<-Hs©gm1ݶî|ûl;ÎüÒþðÒ„qÖ9öS?¹/4u�Tõ+‰|z!ö¤¡R :ø›ñþ%O”8‡`¸¬Úú+MvXÝÝÑÊ >¹fxœŸ˜èW f�c¼N!OÃâØ–ðkêA åý²¼ú(©æ#·4ç)Õ³T†èåö¹ØöI–_ …AŒ{ï­¢¨|J–<^=.½î¡ Ý•F?G@SŠA÷‡»Ñ0y—8FaçYá!cR` Q fˆKÇl×säÍû7¤ ç2 rÿ-$81™vÿjmÀ‰JÈÈÎïæüä;=�£÷~ZÓ{̬a\±O�„l•ã›*϶�ĘÕ\¹RP´€|ÈñÎ7jOýÔÛçšÆIt#ϼ(„+©,ÄÜóô¿!òJF"øª{p0 Á³<^ y§ e «qùe%üšÍ¡'dÈ¡…s±ì\ݹÿ”¡àh‡ß{تÇ$â×E•bävKr.H†F—îÁþÖ3±Sš@‰3ŠSr[˜`’xŽØ%¿Þ@¡‚rÜž§^Û¾tG½}AVº…GR)™H¤¦PT'X/¡Ý·>L܈ZhÞaÙ]ËÎq;¶²‡Ñ£_ž�CÞÊÕÛÈÆî]t½tíhgÞêïìh:Âc@—â‰4˜›µÛ^@;ëSŸ@sÃmIE²v3Wap¾îïZî«�Á}é žÛòÆNágO€-U8ò_¢�×tpN¼Ý"ˆñr%¦ ž±ô‰£³-ú,-`â3a*µùýÏ–9b'ÒeгuŽ5Ë´¶âŸô o‰ùé±@¢H¨âuðÞÑâ´]1®DÄèËøÔ6€MäQq.QÝiE‰yB}¯=GW¶P¡‹Ä�ÃÝÎ�~Ö]Ã硾r´‚ÿj�)ŒÁ›jtq¹@`‹üô¶üÞùa+á}nàÓpÝcúe¢Úqb—àaÊÂñN¡Ü–¥”®oÛ­¦vt¨Î=ñv‚_ÿÿ“Kþ0î„uè ƒ…tÒÀDªè!ÝÂrù22º0(ÁÛ›ŠÚËÕ÷™5yeÿ'�£=]€gêÃY/¨1#€s¢[T"<0Ä”_¦Êa¢Vʾ�oŒiÚLx@ uM67’¸XÞxebxf'"#W#ç02ƒr0¶¬¶ÒmGÀôve�Âé«Å££Ç(î¨úê¨ôvðGe*/e ¢È+a d-…k"· ã}Vdª’�IDË/OÃK9B0gr¥Œ”ÔØì2S’Œ'(&˜ÿç¤ûÎQ" éö‡ŽOâÝ Üt®´ìd>¡ sar—W¶ÄVâv£Œ#r¾\Xa‰nsŒd�H—Ä ¢0AWƒñN¡!Œ!¾NSfk1ðp‡5Ôc¾ˆòj!$CõØ|DM²õk宄3ÄæÙ;üâÕqPL¼Í„/'9×á}¾k~ÒJJdœók$“ÍPzÞÙ:� è÷ þXßö¿Ü^ÞM^fÜy\{«ÿÛ6h\¬b» mBWø1©gÿý/CÜ '%‘.4Èȧ"¦tíÙÿ � mVªS¶mÛŒÿ—åÆ:m|Æñó­.zvù2N ¥ìîml‡ŠD–ì4Y,e£ü¼#?Uàø`�~—?‘œ™–Åý 2d•†ÕtqyâûqÓ}vXÙ­ÔLDÆÖN©€`vCÚ¯7‰‘+—et‡¹Æ–×@A‰{ŸBûÀmvà8B¼Ä~A¦•I"}.–á()~°à1ÔË|w‹ #06å— (&®Ÿ¿è4€îy í)Xyi º}. ל·lî‘#«eÒÏ AJÎ×Z8Ú$(:WðzÖàG¿`¼ lhÌalVé_°È®÷µ0)Ô.’ VZáÀlŸ�Üon!MÆÂnFkGJÈä9î‡ó§;)ÓħÝ�–~uwʆ�P»ÞÝÇ5¾‚Óm&QÒL?! ‘I4\Ñ ¬q$…p|yåÒT!Ç;ó«H.ýúÏ8×îL¶UsbðÑ—G 5€' P�óª•ëaļw.p«r6/¤MÙ<�ÃÒX�,G¦íjTD©Ùí›i^< ÇÌüc–ä‘Bôy/Ìø R^Ü=(ç쌓B`ubžCÛp8;·}ˆ5ÃãŽ@ì€/ ^‚ò4j?A5SvApêÝ=*¥£ŠÀE6ÀäBnŠ,-`ã±Qô—zÿqxq¹¯U3þZ“QuÈÑP®=kXÞz9"ŽŠ¯ ˆXhÔóbKL;}sÌ�k~î3¥Œ+ÓHù¹!ÆmÅà|´ m*òSòXªˆ#ˆÍ+g´ùŸ•LZÇ…”+ݶ&á^‰ŽRÝ@4€‚™ð-GׄÆ+î‰ÏžÑ“iÃrÚŠGN—Wó'QPBB»­­^IŸ¹-�0b܆_�ˆjbþå\Ä8*áWÊÆÏéM…ß¹ZXÿTЉÜOj«\½·GzU¼ž©ó�ms3ªý‰›^…ÿù°Å‹wŒß‡�™êr)]´­3ƒoúUL…8‹•¼úNn�]/§ñ ¨’3Â4î¶Õ3£tÔ1Cn(2nº0Ý�¨)KwejVˆWƒPZ|ý�õr–1fšõ´t„TÁÓRÕŸ°Ç‹Æ R•4\øðŽ$Î^õ†iËÎNÕ^ É¡«‰¼ÇlÚ—¨þ'cìú0c(0 ËÑÄn  IfëИë‹1ü�1úý¤ÙäPçì>ïþb /ÁKB—˜¬JlAß+*fèýܤƒxë>‰ÆIhxì™!ó]p‚€¬`�*1§;Éi�é^Ç],ÂXÉO6!Êî£× lÅm^R4($i1(Gξé:KÛçéŽùæ­åhÌlj@.áé±á:–)cíöž·%Xý™ÆØæÖÕÆPqÀ/ IcÅ .­ç™ÖæWj²Ÿb�¸²ÛŒ@X#÷uËOK_t¸ß~ùh»"~¥àh'½~24íîq†yûûËj¬„o‹Y�8IÆ>Ã>ÿÍòd  ‰~†ÏZéièÛwö+.}õå–ÀEyˆ B†%`�§X¯ãQ[ cÒ~,M¢&A/SŸp‹#zVœ†©ÕÛ(ìå€q×iPÛ©ö}�å¡-YŽÁ¤¾š‚Ü0zùïPF÷žr„ŒžÖ³µÁð8’\);Eõ~¯Ý‹â<ø-ØRJ=N“uÎ'Œÿ1‰5¥N! ‰Œíën �ð“lb‡íò!½2N@†‹Ê•Ò ä’ú4q{Æ”¶ü{µp¢4²Sº�´ R±±ü%\ùˆ5†tà5£r9møî@Þö"ž~4Nõæ!9a)|©±tßÊlìü+z³….ÝòDTÁ4Yw …ƒ%x*W¨†·]xÃLå˜å·y®.= -Ü ùeü#õ š û¢É�hEoî"VHOú 瀡öÊå!dÎbʾKŠnMx¿ºjOç’ã¡ÖÝ´­Zvåº÷±°|qГ™LN ó<ôRvIûçqˆéRéÇ&úÞq§"ý-•ŸÐj­ b•he�f~ì6K¾LUcТg(šÕ�D—Þ�C>ôPh4�Éú#ø6•ÿ¿µ&ÒvOŒÚ¦mß4¡G‘é…ºfòœe©Nœ‹–aéŒè>Oa(_†«lÒy-"eÿx.D”4e|¹�„P0,i�ÉCܽ oì0¯]AXm�ý¥Lo¶ŒYZvß@‡|C©šÈæL #ŒIeÂ×:YÕÀÁ~yÀ…‘ªö›ÁÜ;]Ó­é¨XšwpcVR 4ùÇïo]%…Kï3$Û¡ÛŽw&*üÖ/·¼$^¯­!û+¾ÏZ­]Áa>*Uœ;óÂéø' Üú@)™Ë L�ð´~�5y¡þž…Ÿlqk5ù-®"Ç/ˆzïàBª?]­‘=kÊ-å(yuGDÛË–ï�•ª¬ÿ(7wÆÍi>·Q[ÿ˜]¬Nqi@"égcÇÓkü|ðÉI¤·|<­-¢Vž{¶AJ‹Ûð…é°X6÷¢5hÛL+¡YKâÞŪ܎¯î SE ËL-ó«O¤y:ÔŸ³wéÁ^ÿö{Ž.T™åu‚R+£kìu–µLÖ¡>)KàNÍ37¸­S›=›#åoˆ¤¼iŸ¯6oë„d�sÉϨ̴‚¢ ¸)ˆ9ª(+�IÌàã[¾]òŽ@HCAƒb¼xT>—NǨàHë< ‡ô{3eóÞ%YqJoõ7/>ã¦lÛÁ<pñ›ž60”%ÑL~Õ—˜X¿Á£‰Ò •æõ [¸L™Œ#h;GÕZž))ò/0:ëXOé•–¹ÃŒÿ]}�6õßö‡™.KÒÅk«àÏ”ûy¥CÈG0¢NpœîçÞüÖzÞÜ B’CD>µ�ûŸ+åååD¶ ÄßDúž¿K&Í~p/¼Ã߇W*OuÏ ¥>³’nºèä—ÏÚʃÌnh”Ǚ̧\/Sš‘H3Óxœ¨jÇ·{¥Û”ù„ª²»¹åÄÌ /DãªÿÑSÃdùÊ#Šj%ºa¶kJj€bÆ%`öA»Ã!/• ý � ³1“¤çaR}MÝëI¾Ä²�‡+‘ϘJÐþ„s]Ûç3é²çéácÉJ(ä×)lÕmÀ5Ø*Ì;š?“kât…ï”UÄó,]¸ì: WêB±Ó?±ãá¿�#Î@º±Õƒ¾Øm� l1ÊŒÅÆ@Xß ‹hwQäåé/ŒîÍjA#Î�Iõ•ÕÈÞú0 y.­(ŽÁŠ…ì»ÙI½óˆÍožÖ|®|ku(>¹ÏÓ0û/î¦ âÒÈ×—I‡TPÏIö@'Åþé26Ž !@äk©K•$Q­DE;( hžLìB‚3Í9, ìÁÌ"?ÔßÄ ò0G‰|à–¯®î;Ø=Ëò×/�·‹òç'5xL>´�*¬×Ð ò ßĿ尼C^ pqÇòܰ0¦ºŽ¤/9~;í£¿ÀO�W£§Åq›³”8¾?­L6Ây®…~GÙ�§.syޏTu¼ £ÿ‡Œå]]ò b|TLÊìá J· ÕÌã„äî^‘—•(6z ©³¦]öwBlvB}Çc}b_JoˆXØZ''†8C®‡¡B6cô%FcdðŸ•v„ÎÀør‰©?y8pö9åÝQÏ=ƒ9Ò@­'\¼JòôÌi*E™4ú¬×$ï aÖæcʃJ{ƒ«ŒÇD=@×~Eƒ-µ“üj(ØZ¶ßÁ ºþÊ5D>ý]Ón¦Î eF€Té©Ö\e*SË^1¶r«Ü…lÀuöþ""@¿p­Néc†Ï„f½àñ·â>ÒÚ¿›6Ï*|8yž.ïq®É°*HôØÍì±ÒCÚê„ÖK5®¯Œ¦®Ð15n]àQ½ÒØ«+3mž±´§<‰þyß (y×µ½àÛ>ÜŽD Q {vÆÃõ˺J½he`çòž)p¾÷AZ�!ÀuÝ£·¾T½S°:“‘wñȱÊô<>V�^ád›`‰Wb��>²›È�ùÓWì$ôö™.1^6½ Ãüh�CË:鮯jbG§Ø¡ûSæ@VƒݪӾ…Æ]ÈÊ «°·¯Ë88-@ ØC*O�6þ.ò‰†O•µÍ pd¸Â –ƒìœt‹¦µ»À3@bż‹ö �dv4à“YÈšJÐ79ÞŠÏ"`]j==Š#8k#a·àè(N²Iý›ßùtcfÒË…[£ùtëeµe]n¹–+‡Ž0ŽZÐЯu³ CºÅßH,«¡UÜrGÿ0„NjõÞ?£'ˆ•±ŒÊ³©d$ÿn^�»ö«Dg7€8Ûþp“V:\Clb"� N…Ëe vªòç§•šö̦6[‚o»½œ\kÍSßþtçJ2¦ñu2ðz§ë˜é‹ýª“Ó„Òâ‘:÷ÈÕ´%8cÛ¦Ë."¨ÍTš^A{C•M&ê�§UÀ\P|±‡>±×Ç::E]¬[::üò;ª˜7¶˜Rèe tp êúxРa¥Ýh¿BªÑ%,ÁC0qqëwÕ=žÍú¹Î£À_'$YÊÖ ù`,²æfc+q¬3…�ahi "ÎëJÝDÔœ÷5ÀñÇc†¹tÇ,Å9ô•ŒåXÿÌŠ†�Å`(tPôeú�3Ú,©ÚS~næ F7’d§›5„äê°c ëlF«`pœn=W¶ ì\xŸk[eXyÖÒKÉ'ó~'3m7þð¿f~ Ðe®_Û)*nÈm«i}®±¡ŒRü”ïQ1­UŒßêïTB¤:æÉ%ƒë«±†ÑÕþsâú×P�³·ÅûÉVù7|ᆼUµ*õì$ÃÏ4 WƒàyùZû³ymÏæ‡þAæZCyù±ˆø7m÷5ñû ‘¢ßh%p޽+¥xŠªX‚ŒøCŠr›b´ÉÉ=¿kÌ;…þ¢\x3y‘¸6U,.û½^ÝäÚ$`Í;¢£}>{ÏÝ'Š†Ø™ucjs!'ÐRá}±z�¾[Iõêoz {÷¥¾.¾ øž�Gv¼F·Õhb,]ê7¨!1ŠÍñ“ã?ÜjñO´��‹Æ%†T2íæa 'u¡î*„F¿ {p+ô"¿mŽ)( =À»¹à¤Ö¤ø©Fö7T?”cOÿ–D²¹ì$Ê ým=°”®8Ìt yÿÓ·þËåQ{-£½[Ÿ¿ 7iôK³Z”o 15uÑè-4ÌA¼ã«8¬r¤Øðø{¶‚ãÛÖ—Ö£]S›¼kc¹Ü£Íºx,„ô0ó ÀÊOŽ&³ —yŒÐÔÁ\Õ Í:.çcXZ ÉçÍFþ„¾'huX¦d|i ¥‚Efߪ\PÕP ©É×|^T´² d£úqS­ØV V•œÙ°bÈ¡<Ë—Ô}WÌ0‰k«éƒF+b¦îĹ ®Ë€Oùâ2EºÜ-F>^¥Ò²/Ú³–`*ôÌ$Ý‚38 ³Ì(´CtÖ ;v>ñûÊÊ[äì :Ô�aòz ý@cM扂LÖÚdJ0iëpš»Úµè-~&»ùe£H,Ø$��°®^D HX*³¯º\ÉÚ8_²|Aõ,rÞäîp�x’/~]óŒ•8.HÉKò0>YÀ¥è�­5#ý|KTD£÷ж46ìù¯·Ön$Ð,hÐK)�úä;¦g†aƒ¬áÑýåÌóÿd`½m%\“”³Cb•*‰�þgDÓ_bâ,–¡-jq'øð–4ˆSc´«¸^Ꞥ›iÁ�ª1öÅ�ä½2ºì�N6#tB!;ª‰qîî—�R軎÷ÿ%èž�{짬(Á×@~ú9õÒ‡qÈilO)^¡ôëij㜇õ�O ‚ Ðþ,9Í &<Rø|F_j¦ãžWC;IöŠo›¯@B|œxÖ¯{Å� ¨_·­ÒëåeÞËaöî%î ûþkÍVS³MªÊÙ “…BÝá²}Ox“e7ÔTÌ)äˆxwo×;?D2ä¢f¶bƒ2A2\ÜqÛ\ÿתóN¤´Ü8#¡²n¾J|v®ñiïÌ+D¹%á,í?VíB¨x)#ûÈ€¨!Ø7f«X”úVÀ⨜Rf^!es’i ê\Þ¥|Q¶·›em–£ž:ÕˆW¦&«Oq¯Z»`ÁamÍçC» Pjó'wµbFä±AÎįoƒH„UÆúª‰£1ƒèT2ÃÜ—|'¼!¢¼„šD›€Ñ/T #8ð‘/q/–ˆ¸ïÂÒÉ=¦\#ÞŇ>ÔÔÕüކqÁ£ô } ôcøò“Z¼vWlŽ(@B$raPëÚp7—üÕ„i¬�ÈÕü  Ë禌A¯]ÊÔ·0Ê}>ª8^‰ÀÛR¾Ë0Wƒ•"�±�ê.#¶æ½ï·ïåŽÑû™y¯Ì[š:ç@+'·Ôª¾¡2eÑülçC> .“ÿi ‚sõAU@þLÑ¡!HFÈ >�y¼r9ùÕŽ!ñiæQªë÷$I“ÉméÿÔ­¿zÝLð¡rx.åkþöíÿµ„åc…E¸XØ.kNå?6o(¦örÖÓ>†*ÆèYJg„…0  Ú@="7ˆö¶Ö?êÓî2úK'Àü1¶ñêø“•è7ªvW$I÷”÷ºÀçC•îÀJì¼sÊîGæÈ_™5# ÌÄÃÀž3Õ,Õú`ÿe0<ý2eö±ƒ€Ò xn; âÉù?qyÉ‚/ÞÓ�ËëˆhuðrWÝlXè¿‘ß6FÏÐj#ï &!" `%J±~ ,1dÄÝ› Ž �eøcDõ*òðœéºàªLSÂi˜Ýk�—]}]Ë7�Œ�ã”+ÚD5MYS´«å2²• ÙR•C¼!�ðη—ôq¸?„Tý›â*L\ƒîã_ /~Éã`ži¡‰›ÏORÇüˆoªÐË£lF�ÝZ^ïü�Á$LgjÓ‚w•mI;šš%¦Ï²—E™ji˜¦ôå†úRêí°òe^÷£o©²:{O,!‡”¹hêìaaU± µòIKBöúBÕeÝö‰ÝS¸»‚:–Ô�WŸåZ`9¤M‚¶Ç-¸ª‹Cë ÿ … ßl•i�wÏœJqV�hâ.ŸoUϨzª?2{l÷ÙMÆ Kˆs'‡šÆ¾fsc,îF „£âI4 ÛsÃü§ËCë"tòÏ9 +žÆ@80[…f%v ¤7Cäí  �%«Ur㊃NBù\†ûÓùýe •ÒnKÌt™ÁKÐÙœ#ï&½ç-¯Ø*UýÒÆb€VF’Ö¥É[+ó_ú\àÃò"G 3=Çßw/Ð{ÑGíFê܇æ %ãÆÈ¦WmÇÔÛb ‘ÅJ1Àžš€2òû‡äi?%_Ið+ ù|�é)rç÷1ƒ;D:àpõ ¡· �e¯ìë²8u«¼ÈÍé6wËüsÓãö8ô/‰1¡eùÚïKdç}Ì çšå’QùTâEÆé<ð žf4møÂlÙlÛfÙ^9û³!÷¦žî€-¤<ûýÿü^Š„{ó—ªÔ³�„%ßÑ"¿ÿ§¡¼Ÿßµ¡¢£Ñø�Úÿ£U$Óã®edaJ R,Š¡³iÛ?¦mcÜß-Ô=Wsðó”]€4+ßãKr£lÜÃn³?%S³uµ\gèþ3-™@ÛX=vœœæmµ2 *qìk:¾ÜKQngù†4¯}G„µ g5gÎFƒýcÀMV1Ï Vãú÷qš')à $ô!€Þ臺HÕ»ù‚w¥[Ž’ÅCÊ¿2^†;}�°8�³ÚÉŽaVž‘O†Á!¤í¥E*µ¾¹ziõœr£¯C@'¶„þÑ1ó ‰ÝçPÞÁ^8¡�›]dË—øáj ´}¦ Ã9ó/¤§9·,Y>±=’yX‰ý×JW”ï’›Ä.†nÐ÷È¢‡2Ö1J×ôÂu³µû·^êwL âyôºë5Ø9Á]¹]ÿÒðý´ ´=°2S¾Í¢ ’“÷‚‚äýëþ÷O€æßºÿŽçœïº+°Ô�‘•A�­h½ý}XΆhSÄnRtâ)è \QÏÊú�¹·ý±wíãÀÌ©œåâð ú–Ü‘Ôf—j1¶¢PåHë ¬QÈU¿ɾ?¡ТðE«ŒÛ˜ÐÙ‚‚M(Ú(SgÆ#ç[¸iH§ ܇Ú�àÈä±È»6��§ƒdTM{v ýt.ñ…„�ÈeÑd/ÑUZ r1|ÿüzìÌׄÇé]Gt�@;ªCõGc~²‚çSw³W˜2—É.IÅW’ÿïF�|/Çik<<ø¡ÕUùWåÖMX˜“Ï2‹;Õ<·,5[“Ž…ÕÚ…)JaÂLål)‰_„5#î¾xÓê'ÿvéÁW+$†* oŒ©ì17@6ž7Š Ï� %Iÿ¥˜’Ä×2óìnâÍ@)Þ8-ŽÕèÄR™Ìð¾ÂzúrþÞŒOïãde'Þûˆ5QfóŽ&"M«–¾ƒÌ‰Œ’p[¸GVîå…|»Xôþš2 sQ K„êf8LȘÙnztéý:zþ¬$úÓ�6/O‚¿þ;„x_d­¼jŸ±ô»âY¸A© žT5QÈ?„¬& ¤í&�ß j—Ãg¥â Í@ì‘B㪅žy±¬t²K‚·õÓÂà q ƒFÜ3ø,UAt€H]0 ƒÐá”O7·*0Ꟊ6 1» ^Cd�b€*N­øÒ‚E�h)¹y£$ Íy+ÐnÇç·¬üyn³UטÉЙ¿´¾ úU{ôì:ÝìU~D-éÞ'ÝÞ²ÊO-=Vº£—¿í‘TBüÝoÉ�©o ý–ó»Å£�ó®•$ñXLE茢Ôä©Ê¾”aÆKÍmý×�ÅíÌKÇRbm8¿§ñ€ùtÚ�šìà Oÿ`?V˜¶6»"q¹ù aI}Ÿ& x½”^˜LC–g"ŽÌ_pc�Uê†ÁŸ*²¨¦tL¢éÑæM“dŸw9©ÆËµpõâC¼`©pÐÞÀhÄU …ö£¤ôþÆ%ú÷´9©g‡‰`J²ì©?x¨Ì‹É—8 „J¼’Ë?µàU¾:_6õÒïÆ£µ¡&ýÒ};_(†¼Y)ðïAò[5æöã÷PÆ�J€÷†3¶]uÖ˜;…1²9ðJ‘æ3:í;£23-H·QœB”DznäWwÛÈ'„ãÍ–9Gÿ÷EUsÇäàÍzY„sÞYñR» ò´^S®â¨ìèF 9h&uçV©¿6“ÌÇQÞ¼¾5D¦ì·‘i éá Ó�QáÎ),’ýÝgÞJw7…ÂæòQ}•t³F¯G1sÃDJ– ÅFôî hWG�<V–°už5(ªð1 ¨k6L™’INž»°Ôjbï;»u‰ã¾SM†òâ´yþƒ´É%øõK3uî p^˜–Lø8çVÑüåb2`@Ìj-~ÓD;nÿïa Ô*<·ÙÄIf:¡*âXZ#gÚ]2ú¢ž=+¾Tk,]>üm QÓÄ{Bâ÷ŠORz¾>mÛc­Ò‹%ó·IÝŠP Àø�€/ôü8qûõ²7^·(R„ŸésìÅÍã¸pFjä»yŸÉ‹©×„yèÿÄj=V#þ³Í[áÎæt&€0vÙŠ™ªü Åø·SÌ» ÞÀÏËzŒÃ_†dwè†Ï¹+%Ï Wáö¶jÁ„àg‘¼ëßÁÍ|�õ£˜!ÙÔá@çÑÇ$ψjÈûÚ9×díˆzrÑqÌ*Ñ¿eQ4òãtþ}jòA�9�¹ÜÖÚ ¨ª×7Š”žUx+âbï0›=7ùyVyZ$:0ç:?ûTq¹•‚'±#y\ÉÊ„Î0JÖÈD¶X§UÉ»�?—uBŒD#SKV3ÖËËÖ�ŽÊ3”Séï W¾õQt}H$ÆS³÷rr”‰a%¨<û˜ £Ð É 7£“?:§‘,‚´ýÝByVëâë)ß}[Œ2òûH?ÞWDzŒ7þ?›b†T“â9�¾;==ß´A£©n×ãÁ!— š €€+¯ö÷Kè„ixîâ�RdùG ­å.?­´iç'X,›iˆý*Óê-8ÿ¾‡ .iñè1ï:͆—¸_½$þ“�ï˜ÜÚÉ2ÎŽ�ô&t¦Û®û½s*¾Áâ ½6ӛƠQ\7¿³g]ÚüU�;Zú…Hæ§ÆŸŒ‘+÷_/Üí϶˜€�¼¯{eâ�;h’’>(Êü˜àþˆT¤@"§:Ê¿zY'¤tèM_^g…g_�¯bÕк½ðöWÊ/s±¹×Ø‚¬ñkå;ø ã\tp÷%FòÂmvÈÔük“ë�öQ–Ž˜)®Òè]1(aq…�Âü9d)Êüè\¹©IŒøG›ih¡U$Ê�Í·½Ä¸ù³‘„ôìpP½Á)Y¯¢°ãAёúÕ¡)íÿñ]SëœÜ÷ñ׸ŽÈ `Ô°z÷Ú°[/_£Ÿz Ù1ym˜Msg'ªi1•Òw×<3A7Z©eÏfi/R1/ÀÞÅåŠÙ¡ ƒø¼=l—1¹�™8 âì$Íç@ð‚½ +ó]V½X� Å<¸Ëé?ÃPrå“‘Z°—˜4–îÏ1Ho$7‹ÃõÈs€’5rý[¶êÜ® 3|;Íꯆ3 ׉gª#ˆÉÄ“N kLüÓû|Óª¬Õiï_ö™Å̇ÕÓ?ß�SjòÞ½Ik�=; špT>¶•)ç%ä¼L¤1fÔ_JøØšP­ÖÔ§£øg±�é:}¡ í2¯F­@޸׋W`�eiÓ6ìærëƒë6u»R�A$²ÂÏ *u(Œe›i ÈÎ8*+6Q—$ê³Bª%srdµ´§¾Çœn °ê�µëQt‘7ê94‰ÔeÃÕr^„Ü»_ª¯�–¤«-s™Çé)'ÙŒÓ ¯ñ¡Â隇¹Ømüm K•Dv¡VÊ#kã§.�÷ÎUGÒ$=‡=~òK¿ïá¢ÉÌòX|%lÝïèqý~:„.®MêorT•øÃ?©¥&µÆ�ý”ÖöòBÆ-\‘'2A†º}“¹äèïiNôéè)X.›ÔûZé£>*k.H À@˜…’zûêÆôÔ!¿ý¨ÿ¨@ïmç.ËÖ�X%vyþ “w[¶îäÑ¡pa¿ŸQwîc˜X)î¬[, ͤ�¢§0M:ÿ«}2á5-¹ÿQ:��,åÖÄt*.BH^×sí`H™¹ö��­ºêÍCé{lÂhì&ñnÓÜ‹ •±XÂÛn#—ŸµWÙI¹LJk#-yÀæ™|]uî„‘ š'‰¤�¡5´-Ñ Åø»ŒñIRÝ–‹2wšô¸Zœ‘ô”‹uzdšU€I�Ø™Ž’Ê —¢-¢„2KТ³$•ÓØèÌÁÒ˜ûu âÁÜáÊ@—f£ä¶&g‰–ÑÍC·ßŽ"d•ýȀ󅘽 -õMV5}j5´Ê€Y�¶f6‡…(jáòÂ,¸¶Â]Æ¡Ù*¸<„yMö™‡™q5ÛD³ÎØçÉÙ]íǦtËÛ Ó¼º[àr¸8g0ðFžÙIˆ-PŸF\¤�ïÓ Qç¢b… HDï”ó´s4— FtBÀ—îhÿû>köPÁL߆-áÔìh'"=oÿ v —^ ®“.ú;¶}EQ1Þ8—÷[‡�Mt‡Â*dg­Ê›ÈO{LŽ_´Ò ‰Ñ•r� Ôe¶ K™zmXÄʼŽã5Ô@ÎìCqQFotSé\™^Ù èþ�5jX¨ð°€Aš*Máòe0ýñŠ1ç“ôgJv#gç¨CØw«™¤ïÎO‡õYÌdøÕ`ï)ã÷ØhùÚH§Ïâw¼0éñRZJ~~XÒRh•ìò{óp¤¨? �‰�_¿ª¨Vþí®ÿºiN7¦2˜Â`M•ù)Ú‡ÿYRRYÇ»æ¸=¡—AjúÞ×ó{«H·.®œê”ò²Y·ôJ¥¦»�¸ñÛ ÞØjÀˆ�&f$ì%å¼ –ŒbÕ2Î4U9{ó†^…¥‘+‘×Ü™ˆ]EçÏKÕQˆHœ:èH:÷ÛŸ=R>5BEÖ’¨ú-:ï³çvŠF0Kðã×hÓ ÐÕÀÆÛ0Ôm ˜‘c¡�gÍmÞQ‡(Àž¢ÖMû »s˜Çæœ}¡‰Ûm» ÖÏEGQ¶;·e¾@‡u¯«,ˆ-sçT÷"€倰I¥HŸm2õýËvÓž°‘Sº¾J.ŒjëžI˜öO+�C!Ç[Já U »ìJšØ99´¡A’ѯŒfK5…@ðF§+_¡¥±EÑVfMdoާêü¶œAè¢B1JïKx…¸Ý 5¿è„FÆ¥Ôú'®€ûvkÞ¼—kFü·iU½­ø Äø¶‹äƒ%¼^åÀ›™ð×@9Ù`T׃ŠC^LÒ+Á\û?¡�2“uU…𧙓¦Ûµ…;`XÚG¨Ui¡_'”¡ŒÔ= (��4Ì6œ7–îE™ŽpSàØWcÙJ,Œó!A‡º¿‘,zH{Nb_  60·|Öšg/%Zf½=Âá{¢ö3ú­CJŽg¹ýֽшòͯÛÑ�„¸¯ò9œîí>ëe›lŠ…%霱…íQ ƒ‡IÿMeqKaoÏ8sò O/û»n»#[ù»Ë�²sôÑ õeSù(”j¹?òµmE‹’/÷†,²�KŸÕЍ›ƒWF“?Ïñó³v‚×Ñ›°î+}2–³DÕ,®½úžºæ™û�çàBD}â8ž3¨Â(´ƒ“Á÷‡j8 J²#�"Ï�~-è^Õ†pÿ…þføºÐAŸsÔM! Vôù-ÝŸÐî$ä=iV¹Ïì÷àÒ–¡ãbÐ'‰€©è‰å Êïô¾+åe¨ †p§Ù ÞÞPoÎx$@pÿÊþ8tàÌ<:%°ºˆæWPžÒ×f±»œÙ&Zâ¹þmÍ�'äVwžergŒôÓÝáS9 S™'ˆÎC©5s§wïoŠîAçewuÑ�C–Û˜æ4Pni)`T$Éž€dŸ5yššå)wmG+´¨¦N›a‡Oߣ>º@N_$©„ÔÞ.¦cS�‚›ý—Íj×é¦1)Ömf<B:ÕªVú×ðE“+½ ”J.ÑîXMíŽdÿõöx˜¸¨’œORÄ}�JŒ’¸¹­A‰ÉLú€N)æ�!È„~éUDj8=Ø�îL+ÊIÏDLDQÁÚîu棂 7G3,õ‡KËD¨¡â‚Ša¿bÇù�5b²Zk˜jg!#Ý#ø˜˜�ÂHq ,Œ§ öëü%mÓÉ7Þš­ƒ–øç‘ bKû² òìjRê·–˜+\K¾úµ€Ö^âËôß7TØ ¹ÅQ…]¹÷öÌâL¯[@m0µaqÜ›SÙa ÛàŸ\» ñi‹ú@wÄÿMx�ó¤Ì ¾_·ä�_ƒ¥V%~Œº9xDŸÃü?Î'’òUôÍ é �Ÿ¹›tr“Äz‘“* ÖOlŸu7Ï®þÓZý¶…‹šŸÝzŒE�ƒ,6�ÓSô•p%ôÊÀ¨ä衈NÀBà)é×NØO!Þ]O7^¢…´¥šã ,õ òqÆé‡–¥sjD“¿QE 5=öšQÃhÎÄ Û>_T…ð’ÈNw©;Z #gç¥t@$ š ÿ&Pž1A7Æ ¶þ|‘'çâºY€�Äù0¤6ŸVzs£�® 4É9ÄÚ[‰¼Ð¡ÿc‡IU‰õ�<¼äP–$õÉ)ɬ9î[ÆJúðÌÒ°(™·Ž”²BŠýùTºUÞß{eÖê¿â—Dײ—l|ŠùñÿDÓ/ö;?-i��‚ä�Ðò•Z©Ùô¯hÜѰ?õ2|®Ô6Ÿ%„ÂQ¥‚ÙE„]úÿñ Ù*¿tÐ2:ä™)f Ì@¶-WÊra¦!Qò9˜¯ç!ûFб)Ÿ¿ ˆVaÂÛ‰.3 pš ‰=fï–�› À%!û¾Ñk¹�ì®®@.¥feDìME Á�‹ßj•þ|ˆ§õ•ÝI2ŒO¤§¤¹ñ1i�Ý{XöQg'wq°…ÿ1¸L@裈[D.c¥vû‹Í #ô„tÜ÷7­ 8§nRp[‡‡A¯ K^Ä©eHZ½þúÝ�9G†×·Q"Ü�ÑÒ.Ì4o×ÂTñjåGx�9Ö½�ßÔÙBbkK"¤:Õл€råÃõÜüA(ƒG3�ì©´N¬îÇp¨§„ TǺÃwúJî)‚iÔ+À†<ðB“„�×Þ=…þ7že!*£ˆT²íóyåz€ÝýŽ�P[ƾùxªâK¹~DLrJÿçx$³¼û¤¶<Çêõt17àBŠÇÿ³5íϧ(b‹Nn˜s F=%s/kCÓO¤ÌÐíU÷gÒ‹><|ê¦HÀñ¡Eàé4]ÀÆLc)½÷Zˆj=Þ“£Ì³_päD,Ž·¼kÙÖ¹'O<KNâV¯Û3Òm<šþ“¢v‘É–žÐÉ騭éæ~—«þmÔÒ+1ÒtdoÞ§³¯ 4$&#A*Þ*ÄUwƒKýÈ4;«7>(ù;yÊ÷B7o XIÏ©^(I™¿i$@ÃA ¦9× ÙØd|ŠC—áne0ŒðN5H$ÕZ»#Ã(ËR@ñI@Ü G^õ%ñèÝÇ¥-^Í!LîüÙû:Ñ!¼ƒÒ‹ÞÑ äôQ3ômG¢±ÛG÷‘à‡Çnéíud`/j·ËÇOÓmR›Žë1ãA¡k¾¥!ãß~ˆŽðŸóu¡g®�»•V£ ‹†é“ìhïJ½»åF�-ˆç”ʯ&VøvÙd­!edÀ®Œ²˜³B{|’ßçœrXk‚ìÈ# ïÃŽn¶¼^*~ùWÐ…Vøeƒš’€Ç&{:¢.'vôÆ@¢}º-‰’Ó¸ùcfõä„�9�Ã16Ì÷ú�lVŽDÿÍàŒªec"Mݺ‘ xðýÕ/=/Ï0ò¢‹á˜^Ãã ŒmÅ6|Ó¸jV­h»‡Ý§'Iþ·þ³øeß•"'½7Ÿå+‘ éÜÂO‚&"øõ�ÃÎQ懌¬ˆN°Iç ›#™;bfÖ8|mÁ o­MX¨¥öëué’ A¸f¦ ; �gùÛä`šóúI9ü'ùÔ¶ó*¡”<Ë¡lÖ;¾»ã€TÂ+‚j4®TÚfÕ=…¿ÍA´²uS¨‡™4»Bµ0�ùžl×y ³ Aï–Ê*ý·$Â`i[sUÕ¶GÍÞo�£½®y²`d|%íü�˜À5|’ò2rA¡ûÓ¸ô»‚CBiÿ^0Zަí5Lv–ÇÒr¥Æb³Í[ñO4€—Ü"AG,CÍT§Æ[µCY‡µ¿Ñ¥“ ô†Öehe “{A-žM §P}a9ƒ—îzœcm4fâEÄÙl›�űY¨ áDßÊVöÜ«÷_5*éCîAÅvˆÞ£{Huûn/èôÒU4‡Ké}öb œ¦zü{=3HÄÍIløA|’;V§`©Ðõ%Pe¿4øÏègp. {WΕ`/{¶¹Ct�Xù^¦Ðjë�-ÔÅ®w‚‡�wCüй"*dg­iûæÃ_šrZRBIº»HW|{®RðaönP ùÌ~À‰Ç{1² ®ôBEËÇ�ÿø#þCŠ€³Ðw9féQgòæñ™¾ XÐèêtW0eIŽH¥”»ï#wÁœa%ÕV3šLEPÜIÍ€ø˜†PÁ4’×x[½×–ž$RÿÛk!ˆÑ^âã|©¢¦[}×(o?ï1ßùƒùx”p¬@ø„À^”ÔÛŒ’¿LÀ²||¡p]’?øgŠ”{ç~Ø4¼ú·Z•‹4˜N…$‡HÆørŸÈ§å{øZvdF2Ug(¥q œF8]D}w —‹åJJй¢ õO}�ðåHYÕ9 —*²�¥kâY›#ƒ2)~‰íV0Ó‡Á—(v ÊÄ�®ˆ»=UªÇ?>ìsÙ%¡ 4aHWôžIèþu´”ü©Ú‡�mÜÕÇïþæ”$Œ¤-àéþ|ÌÄ¥�HÐŒ µÅÓ©.¢@×£;vŸÉéÁãJå,98.à;ìGÆ ~›8¨íq ?A韯í¢PòG4¬EåÝ„™gKÓ‡Ó ä‘9DçÝšH#Š`ŠÝD�>»wÑâ¹ÆÎG‚¬¾2¤Ë£óí—æO»v(“Э ´%ÈÚÈžgBrñÎì[L€óí«Õ³zûÒ쌵™h·Aïe¯Ó>’fD•gF%¦î‚æs*=ÀÊ<]d 5ÁŠkZ8‡X‡ySÊ ‡Týr�í�5§¢~ÝF‚UT¥ ,kN,ü× Jq‰hïÎ,ë1¦ê®.pú �Þáéõ¾¦²´Úëüâ�V0ñ–ØDCÜGÆá÷z™Hõ&H¼«ÛÖ*¨^<|¿R(sÞ=R íip¨îù‰¸Pï"ËA Dïá^d÷Cª2+Ë*g0b€ ÓŸgŒÓÙHž7ô’I€BŽd Uý)8 •7éN;›tÿ…ì_q7îY­ÿeA’ ¿ÿŸÿÙvd‰Õ9·›O[uІž ‘ Þ’ª©³g󴪊=Ïà1½¸£ã!‹eñˆ½5’âŸèn�RÖòV<‹\óG3ç.rÃÕd¸k,PûŠËz¶»ë`€^ã³´ IôÚed‚°øBH>vÛ­ïÛZÖµ7^Š;° �ÙsëÖbգ’¥NûÀ¶G€S 1yÄtÀ�Ì"²fŸzÐÖe¦NðQñ¼Îê$ƒµ|Èȼ÷‚XüÕpfšé˸ŸÌ>@èQ%“Ì-ï’þ®aÆYnsŒÒz=쿲ö“‰Šær|ŠÎêÑ(f$WÏ�˜W»pbw!ÎãÇîÄ݆dpv}ט’ƒõ}ì­Î˜Mrf¡ýAšNMáòe0ýñû-êDÐúm|èÓjßk—5_9ß#;<½PË ·¬îîFn2ª©@€úFº)x1Ý&о�€Õ¼õ†·T&ï€Eé§Kó]•¢�>ÈyŽ]ƽ'kÙ;´Àüpn"óÍ=Çd`ÒñÍ$áˆ< uºЇƒõaµXö7‹OKNÎK)ŸTÏ”Á¥ å^ô÷R�ˆØ¸Ñ¿«¥_ÏW~"|¢'¼ûJ†.NÈfI·D+µbpsÛ ó€¼DäëxßC�(íOz¢«³R0Œßè4šåè;ØBEþgˆ„(ͼœ-„�Ï‹˜Å€sªõSØÅ4Ìõˇfÿžf©óšnn«À¶L[òÄÃê`xª bð•0õÁ�Cî �j+ù·îAf7 ý‚Õ‹5FÏï Ìˆ¹1°.@pR7…•}[·b¡Þû oª»ÙSMV²àÔ�àJKô£™Cµ®EWY6‹\!-_~ÃÁéõÎ�§”ЖÏj»þx¯ßœ~Ø6V?Wœæ2QþÌ!'W”’páý"˜—Õ‚-´Õ„kÓ°|fÜÌïµÔ�[ Z]>)#òÍÆæ<§‹SC?‹”ú št›HÏ—› ¥…©#k,ÕæË�¥X�ÀjÖ}ZB”ãd’B âÞºêÈ!3dB!'ú°á«˜·5ßW@)•Ý/±ú�ÆRÃÖà9÷iG¯¼_gÔÛEörÉäd5žô‚€Ñ\uïÔí¨°j!¡Ð’ªÑß§KXÊkfXÛG" ›!¿õü+äkFÁ‘Çe` ]ùp¶”²çÀñm®�p"Ê4ÁÇ@ÿ¬£óow³¨>àë‚Øò7@'€FÛ¬ÛH¬ÖD ™nŒ²â½ì7‹�®ðx%Oˆ%aÄ…pß¾Œ«îÈ�—/$"v^§ÞHsôV–#Öïx8æ±›]9ž¢ñl#!º5¨~í@E0"¦œä Ý–üìë tÒ8sZs™��‡übRVåt,Ž‹˜D×¹_ËE1cÊB;NaI§CdšÌÅŸmÜAœßèä^>+‰û¾¼:ÿ¿é¦haƒô…°|ž×&ˆ9Òž¤m¨³­üÿ�rªÝj‹¹·.i£(˼„:IR?{ð»à5:h�üŠÙpµÙn((ì‘Ï™B�F¤6ú Ûf€íšžiäyÔ‰ë>!ë\0NB#X2õ6ºu7:Vù• *EÙ¨$Ä“ECºQ4µý à-¦(-EÊ•Nkº\) ÍCìÄ×Zn,â÷­€Âi—Žcàÿ÷O¨ÍS_^•¨VÏfäd="øÔªDT”ÞÌ~'µË6”O÷t.w—m"eœ?˜2[Y$ʨ¥Ðûæ Çà¬þÈ[ùYÄ&ºGõ͉0Ê4ùHS]§Ú.mqAÅ¿½÷¬E;fŸm¥­€·)Êø‹76`߸1™L�E%ûkÐ�@˜OZã´9þA)¶þ¼Nè”5t,>6qkèmxÂÖƒEÅ'èðó%·÷®ˆcâÔhŽ× #ò’ÇX¡?³Á`œ©`T‹ ÎôÆÔ#YÃU¡•ÁĦ&�guG1¶¥:…R¤Éo.¢iÕ/Ó6`Mú&Ã{þê¡ Î2>lNæÃ°ÿ|ÛÜ]É{+vÎ!âÉx»­*ñìfèå#sç… îšÛòÕ¦–záê:ßýü“W~k„8�<—"K|zqɃFÙ ;M¦ ¿È|—W3¿ÜB$ú{RÞýÚ%Ýbimp±ãÝ*|Ë%q¸Â¥dVljòÄg+s©ëø ðy~rv®á|8Û¸æB ²ì…nžf^éŸ\*[J.™ö¾ª÷KèŒÒYc·Ý¯ïwã(ÇÓKLc��—I¯Éâ¡ô´¥åf7ß>ÚÖ übÐ]ñÕoâ�œ^Ô½ä%×]x•Í›)”dY?<Â¥ðlŽ´s‚Ék+b|’éËÄ¿è+Ô+s?ã�hgôê1ú’_²ŒÏ#ü½ƒû›ešò1)ßHÓË £–Ký ö‘®k½�Ðiw£uúyMT~Q…‘Ùþ¨j°¯�±YŸ?üxX•Æð¼_<qof „:WóbŠJ¹]k•C¨ŸÂ^k×¾˜²À…^øÄV®I7üÁÉN¤“,˜ÖÖønì j>Â*¨?Ä[¡æÂgbæþ’/Y*«Ü½'àR@½é�¢H{ÄÉg,¬@¡ÂâG:É€�4&˜ X[Ažld”TL'ÿ Ù d1}“ï3¥�b `Ð9Gy'‹Ï~Ä( UnÊQœ4ŽÀ�¥gcàª5’Á—äF±Óœ‹©‘1œì@ª ¡:;ª¾|‹}Û@%b�þßý´gýq !8.ƒ¢j›pc�-"£ëƒ'}S­©Á�?zÞÄ› *ÖAúèíB±®Œ¯vêÑíËef½¸£îêŒ R´xeI©ü*OžeH§ò0ï,Ù4ð‘ÌÔ€uPfß#ÕËyçÿI/–bâĵ•,ap¼Ü±Xú5×þ9ƒ�íË s޹³O±†ØBzXé �ÑË`³Ï'Æë'ÝjZ¹’4,šïHZ�ŽÌžÖ²¨Ð½7n&D¡¸‚»ÎWbò)‚cçÑ/“Êí´v©ëÔäêóÊ/º€ŽE5¸˜Z.—a¨öH/Ê™ÁemÊ®GT’1ÈC8¹ëÅŒ%³æ`S¹Ë?Uaæ ·"O |“£œ€AŒl¸%ÎïR6ÕÐ�Ü�R/Îû– ›ÿ{bëd²K7:dC÷â• ?ë6hîÓSªßÝ‹š‡œå£†v Öá Üì8ËHfi9ýÒpÊØqø¹j&GøH™kš\Â�¤ö÷âW*< ×çVƒãtM¿ˆS€lW|œaf'¨ËºõÄãª%ãÏe±÷Η¼sŸ(5ý\ªWL|ˆ~úèsRÔøÿHz.UÉV � ‰9{™W›TBQâj7Òg{º¹NíøXvØ›—yîëåße&u[„ûÏn?ÑÀ@àOižå­[¼x}t¯e�”îT0qÏÂ]çµ)xâ4²ìó½Ü}Ë«$¢¬R§Ýf´îé[Ì�Þ;cß>”lIÛ(…ëÂùÈeÇŽCÖ]Y(÷㜾<ÂÇã¢Îp¾Q²µ]£/BÂßÏ7´/g$‰µÚÉÜÝNHg—\“éKÈöz™‚éæQf§šþ `3·¤Ö3Œˆ©…o^THìlé»ê Ò•Y[¢’Od„v“Pt ™2ªU2ÜäkÓÝÓƒ°ÛE:W�<2kS›[öÿpàêð;j™`pkž‹iÿF¯¨Ó?<‰Bçû/qÀ˜Àe†]ì¯bKàLÎ N¸Añ²Yà6Z+u]ß×Y¦`lJ‡49†¦+�¼—OÁÕŒà¥crÃdNJͶ^áüŸZ ™ìRêË…�ð¬¢0V`ÊI¢›®(`‡Æüº[$òvÎayzòëx?î\ÆÒçË›JÔ2u6VUòœe9Ó¾@tU—¸2ö$Näî–Ø‘h{8¦R‡8ûЄ¦K¥ý%øÃ½ÆáùyÇׂ_OIß'åPFê1ã 9®Üþ—½Ä§çPà­ýÖš ¿Ä3„”÷6 ¨c÷K8$à¬ÚïU[æ/kõW£sàSèCÉ‚Í>ßÛTxÁµ¹¬ƒN ¬ó\Ýæ2µL©ß±~²<á�U@×&‘|^ cùwKìˆL¨’£›Y¢Â¢²­,ìÏäݺ’jåˆ×[´–Ì£³ª°)–K÷)ÖÇA«KÝe®ÆJÀåOp\–¾�çLó˳‘G¾ÑÐÁ|mÁîàÔútkoʯAH¬fî[¦ß9?ÊÀJªÍ‰ˆhÖ"‚�üèb·Ùù…Æ1ê&™ÁÁ3´=‹r/£ŠaÀÌE2°û8ôWR¶7³D ¯0í'S³.G¤k¹F’¿ï�©Ð›„o€ým^/¢GÖ�¥5i#¶;ì Zåïd û•Ó!îv9=÷Cë�¥, ÿü®&¡èj(6‚ØŒr5]œ›êú·'áéÈcÏ4˜ætpý¾7¬çæ‰ë5â-S‹Ûˆ«W�ñÊ|ì< ˆæB':€c7Gµ¤z8Èp‚íªe€gÁFž�nGÿ™îk=æ©#¿jÌÚŒš3úùÛ¶d�Ði@Ž?`”®•ޝ€83øð~$1Ïú1§Å”ðk¨³b²Y)Ÿ@H"³Ž@¾„žá©5FËÓÊfü@Ä~ALOçCèr¾dÕ#Né¥ÂcÏï_�Cè¢{„x™?iñWÿ>VÊÖú#CÇ—=ãè±90{#dƒ\{ŸwF>ˆúã^w�ø;#xê”ÿƒä{}û¶Q•ÂYI©vJÐÅèÀÄ€2½¯Ã �@.ßžÚ[ùbøS+§(‡ ƒÐ`}´dúÌìªÓÚÒàW"8Ëc{äd` �aÁ­=Õ½%V¸Ñ¿[ò† —ÄpõiŸxô&›\tvA”ƒqsS4qF­ÆW6×|yñCyÏ•:2Ô°Q‰` ð¢vE‹1™_-ëð€»×Aš’5-dÊ`Cÿýñ,<†{4â$�œÉ@úZš7€nÜ~Kø.à@ëâŠ+Ò¨\øC&5ù®š¸gJð“'Ý*ûg˜è’Õ_m$߆œûµ�áªö�gq�f"">š-Öj½²�ºÉ5[÷Ç¢ç2©åߘE$� §­øñ;£iD.>¿$ …’íB F÷ù­#õ1®�oÙt´àÙ¨5A³ÖG¢‚ÏvœŽ6²ÂýÐw«ªËC Q‘uñ·úäf+A<è·Ñò`J³œ£Âx(*,YÇó gßïºÏŽ& @a»¾¯ ]Cl]+ŸuÁ'r û.»3椳}2W«a WãË ÿny_°¶™$ÖrP>úèT~9/ê^4PÄ£œKYÿgß,OkÕmHg$Ï ÚÃíZß-$UžüôëÀåÒÝŸß�96úSd oê÷öšÅ`#I8Øä,a2/Ü9G“Áµƒx+ÒÍ<…W¸f_ß™5P/÷’ئôø[Y}Ϋ nrSYåÛyŽuäÚ¾Rê}½hºCœþ…½Ì RWó�tãx¬œÞ½´~”ò˜zÜ=%1ãÄ ^'´˜J�Æ5ÇÍ 2˜$F\GÈ w;ßê³ÇfÊ æ ²ët“�íƒ9À³aÈa^Â: _Y ”¸T%þ¶Àº^ÂX!é�4ÿ¨ÌÔZ§›þÙ_8åúa†j*¾rpJÕä÷7Œÿƒ´†â2É�+B2UÕ¹ì  Mq3ÞÀ�úžYF‡�iç§Tâ®ÛÚÞ Ùò…BP—Ópñö¸Ÿ>ŸrºY>âol5¢W½õ?‰%4†-X´€Ç×:�yïE¢  o5f FCkâÇ?QÑI¿±c”ìÊI¿§å¼‘ÆNÿ$Ðó+¿£Š.ß9•uËàcôN ~B`ž. Dö„VB9ÿQÑç„ L¸Åä>| ª¤€ìPÉQä-~/E§¸zMs5žéϘw²1ÉqûórÉ%ÌÙ�J2Jõ “�tµUÝ RÚ¸×x…ÂB:5§’o^g�?pŒtçÌL}¯6…ßÍùxª™Ü$Z¥YyŸ°â·q4 ÓäX͉>̾ N4Æ.rscÙêzj2>¶óÒ†AÅ;lxmzÐ qúöÄEódÓ;éò•4ECU–d9;¥ì1noe!4æ0M|%ŽdËë�ç›Öb1²Ü€‡‘´A¿W£·Ïú"Ñ HPË�0/Äî¨>9¸s?€gRÌ¥sßJ&K\’~Ùz4þå<È$€¾‰–Z*ÀDß�—ÌÌI‚?dq¹`�¸³*W„oV·Ìß´ZJ®Y=)‘À¦ö!"Âcfë ræÈ~ØiÓ:ÂÚà›[vžß-]øiüîƒ a�\ 73dqÃ¤ÈøÈÅýe®#“zÂD÷&X ;üا“¶¾+±#c®‡{ XT´k‹™`øJ ªySÜUo�›{öêë<){î~ªÅÐÁ�鎃f�ZF¨aò ÕÛ~Ø)ŽDÇq—<ìƒß%Òóz_ƒ KæŒe^¶ã× &Tc+ £Ç™šÂZ¿ù€¿¶pt¤srâg%™ÌÊHxÎ[L~°Il9œØÓºL¶•ØLDÉ‘W³oQÄöŒ]w.›3®ZØþ®­ûȇøOÍ÷�Oc .Þ|ÖôT=à•o[¾1´uáO¢ ( øv„øP>²æ0Èz×Ýü¢’±þAïûçIžú¤8±ÈÎi…€Fî�–áo‚ºk±n¾ëÅeÈ éBþ<¹gÁ”Gü—_„‰]CǤ²”PS*çÏ™Fb‹ àtGÊè;Ç"Àë–ÏnFõ¯ ×îD}¬Ñ11Â7…&mŸfØ2¼†YƒHZ§Ínô|� ¯a5Ð2¶Ë�ˆc3*Õ¨�ºqƘ ¹¯’™RcÇ´øäæõšþM¦0„·è‘ »ÈÉ|}ží ŠªMO‹cøtÕ(¸~!íü½UèÞ<°-0Ä#â«Ô°Àèm¹Î/°ÑÊ`žœUÓnƾO<Ù꿈*ŽÓn¹¨�I^°¡*™ÜÛ þ'�Ò¬/ î‡ô§œ"ö‘ŠçLjØpŒ‘?¶ Q³‘SܯÙß×ýX’ØòbI­£¥�Šç·‹œ!m½×(ú#Øs(-.´ü¸š4žlð Ð>âcᚺ«IN|µÚDôÏ€Ôž¯ãÎÝá-o%4-–vìò¼÷Á1•1íé0zîY\á_>Y0ƒ16NêO�,Ïæ›¸äõ84'S‘ñ”�ÜÅÄÅiC³N©î�Å9‰¨Ý;$Bå‚Läö5„ád­‚ùÁsŠ-)exD¤.X©nöq®^šç§ž†dB=K>Ë�Òm½„nyôI”�ÈÕò‚v�½=:áYú™t^ðœbiÏäf¡nÕba›*[¨Ç�ã·Êè«!–ë"=‡Ödæ¸öpÿƒG‹N­¶>=�–è�#Ë…W.ý�"xü‰-"Wq6åëç¼÷o?jqX•¥ß•¢2ÿ0G!BÔs—X}ŸÞò/ìÍ-,›�Pü[8ÿpìs¯"VÞaG.þ–™\8쨎—½( ü Vb�Õ3ræåët¦¸/!oØTÌcLW¼›ã‘55×P2°Ó¨éÂ=A�á{C^ºN­Sst‚à$Ï1ÒYP¢öU|ÏV› á’?öÀè¢eaä &',ËÔ(—i=�»*–ÈJH0ƒÁ½oÏ€<ø”Êqp` Èú•+^bÀø=¾³H¤�ñAž°d”TL'ÿ Ù h5žªºBÂèwãÚS¶.m’r3¾øÕPß_YÇD€ÁB*ø“/úà–£ Lg ²> KÐÔÌ‚e rì7½‰|KW3E^Êã#€¬lêgjDÁR|P*ÿˆÕÊ\é^äZSKX Ñ•4š7ß6߸¾ÿ_ŬÖ�™eÜû~icá¨F¿øÿáxOò×}0wõh'_Úâ¾PÆáMh6Râ”IñN8‹3‡k½%üÇ€D¸«m—x—9t3\Pû`½6WafÅôj¯-RAÆÅ\E¿.|ú;@T²žÏiÿoú¼Õ:´ Ùš4LOCðȈXMC$P $ZïÀ\˜çgkÅu‚ È ¨¡PZ²é:÷8<€S©Z*#DÔ±ìÒj<ÿ!Þ”©£)rëнŒ ¢é¡Ô¬¾¸z´FdGÅ f;ÖÜË¢FøÚî>íÝ-3¯d:ï“bœý·c sÚU[o9LRnå½£Â\‡ùÞ[JáYÒ¹#’L¬&Äò^xpížÑnGÿ™îkhŸ¿Tÿ(®L(³f¾¶´Eœˆ ·‡_ΘKÈPÕŸ,…O bßO¬GŸtáî$…öàÐÒ·"ĉ"7úÙ@V.ó¦±G‹GM5<ïÅ­+’ßâ%îîÛå©ûÕù™P$; ø˜Ô‚ô�ñoi0b•Ó�á Ò¿æ¬Ùð¾ Ù6ø{m_-²­ MߌrGÊ]®Ð[ýCý‰øåN¢vèb&ÛCØW~¨!ðI�\'©“±å›´@n%%þqBt¶ÃŒ­Ó2«ªn˜âH'Z’v—mn§Hë©Ëpéƒ[N·¤FÁPé¾K謗 NGíi.*ý”=:y!�it«€œ€/ªì;—ž²8�ØNl #4 û Žö,pMG-ÂØ¢uo5çBã‘P¶ËCˆÀÑRæì¾�›sžkº‰ÅTÿH£†ZWðº@”ž)~K5g è²ÌvSyŠFÄó€wš0–ÜYŸiõ”øá²Ü)�Ò£=ìÔ"íK›#Õ"v¿=‹ü &†T²lX¹Mðƒ§ÓµŒ¤‡Ò¥:�TVà üQÅ6±èQ•›á±£1ùV SÜ\0D—‘îw0Zø/ù°Ü8‹LB^‰zhÆŠºÂIO‰b.}‰èñ²¼¢H^ÌÆ}(Çu?ÛKñ5l “QÚ/ó€þÀJ½—ñsÿS*äW€P(^ævœCÖ…ªéI5î…ÂXÏÖ ·éhc©àù~`S”m ûoH¼tuÊŒüK–�Û®ÜQñ6uÁ+KØt‰ù=ØY^c@,ZSˆEáÕ>ì5¾˜ùTlÌï#|onõU,zŠ;æ;x¹ ¦Ó ~+VºIy‡6Ii8ç@» gðKA?cÀÜu 5÷IÐðS¬–†•�fÆVü=w*¢YÙ™f{ˆÑÞó”Í*êðÇ^ìüàzŽŸI€  µ‡ý»½?ÎØåC¿:Zߎt½¯iÖGŠ ÜTéòs¨ ²�1&àÓLY-3_¶Q¿¦ä æð% Ö,Þ­�wþÑe<ŒF@ë®Ý�ó7çéx9é_4¸Þñ™æcR(ÚÓI�N>à¦P§£&9îÜ”kÑSHh $¡g�¼§NèÆjò_«|ÈP½™ßϘÞÒ­M”ºÛ/qrC�P–$¨¥ª‚…û¶K™3š ƒDh!GK¿ð®C¾�›³âüšŽhRC1~à›yêXæ}ƒÏ=zrDOj2ìtÆ„Ú-X�Ö‘uN4tv*XoeÏrqÛ`~*Þü {–}hFßû« „õKÞ†gêqh}!ÖO¬‘ßsC‰ý`ð{ñîç[¥Þ¥y01 6~5ÄòvÛ{yitÆ›¯$¨OöËN‹s"uÆW?�³\‡4 ÖeÙ¢5BÇÞ$?¿aÐG =¥ W HÇ¥› Ú€žnÖAñÁ��‡¯½~zJœå¹ƒ�¯¦LgøXmO. Óp[Ôö#’gÉôÓn_R)8ˆd¸¢<çc ±ý뚇r �89mBÞQRcE?Ê,ÒŸdûA\©eþÀ@†þ·.«ŠÁBÜ…*Øüõ'rÃßAöÐUkl º§itˆÀu}³Lßo=Ô‡¢ãfí\˶wéâe~*,ÐþWJ«·ýO}[ÿVA&tL^² XØa4Ì îB‘4„‚wzKLn‡êTâJÜÁÓÿ÷x‘ˆ‰ôÅ–L"¶;œ.øãŠÉ f‚Oª1ÆÔPWÓNíJµÜ”Õcã.‚ëf³ã‰ríuø7U¡\B}€ –/N�Ãoz`ü™G�Ý&~@"�éÙé$ ‹FcJþÝ$»ÿA#P‹…o˜±Cz›�.Û¸ÕÖ@)(+¿.1@‘¶¡Ž Ü¥J—ô‚Œ[“ðI”TÆÏÔÝ��ó¢õ"n ‰ÔˆHD°%©ó…obšÚ¯iLë.ðÎ)*KJ�þˆmiØÔuŠä˜äÅvB­çøëè–6üg?ã.³:”¡ÝžPHDx—…†«ÄÆ\2”eÉ€³‹« d•¨jö´Ò§´úü[€é¯Q:!sw ·×„Ÿðñ§Orî~DZˆ/«�¹–”· \N|»!ìnqÔcã:¹&2G*S+Úu-<Šê_ë×Ý M$,F·•§Y ÅVdÏM´{$vàϯ¬M¾ïÛK®Ú7Ðs¬bä]ãȤÎÂWpR‹u*&ŒÖ-U¦¯«0Õ0[V)¤¤ÃSùKŽÖxTW Þ¶”þá­N�ø?<¦OÎùÞ–u{ôbÿ‹ö^Õ £LõËeþ Н›+»ÀÅ,>ŠRl' PyÊ¥ÓUA3ýÒ¼Mû'€�§l#¨’aÂ��Qõ*{6ªA]¾þcUdk(Wãè–aÐ语”¿èãið9eÑH'B—_Ä"t Þßx̺¦(F×P]œ:û!  þ �£¾ª±®LlV\; �u{»…n˜5±¾015—[ÛtÓiëÛ-'ÓüZn¿9�tŠ>9ÖãHcQ7Ðò Õ5÷?¿˜öªž¨O“˜”q(<.žÜ?·”ê ò�,åwpS¼óž�5v¡R;G¹‚L­fRà°QBÒ�Ó0-¯A‘îe_8‡è¢7øíPâ/°G‰ÖÑᾘIæ¸|[ïÚűƿþœP&íšË›"ø¢Mo0œl˜ìÛ³2ë‡Â¢ó–iíC&–º[5óTiøÕ‘ÔŒJˬÅü½‡í,Ù !-Gq¬@i.�Ž €nˆJ>ýƒÏR—øÊ–õH1µÜ$”æàœbʰØÃœלYÜnþÜé³vâ|´Ýµ¼Æ=£Ð˜géÕÙf²v‡°ºCMK&q¦øAwø#EÌ&]ÿú�Å t‚Y:”neí¼ãá«@g΋FuŸ<ÝQ_\ÊÝМZ1G”B‹hv�e¬|wQg6CzP{q¸LíßUd¼6ĘÉ)›$ MßAìH5UôÔ‡T2Äb�“$x"É~[º/¶¢åM‹r´ÅX|¼¼ çÔÃOX 9ÒÝpNˆ É®ŽéõûŽFÛùt¨6—,¨’nÒ´ÿXk “öÔ­:[ôZe SñÎ͈ìz/¯D—l˜|}.žv qÐcû¨”8g)4:º‘oèi‰Ê^°µÐ†ÅLÍBÔ#N ¾�L›v¬™´¦ZÛ©3M€%_‹ T‘¤ÝÔ›#oÒŸ­r¿}rýQûÉø§ O¿ªªÐoí»jêÜPpã:j#�•�6Æþc±G½$þ«A½ïÓ˜¢0Ä<#`«½G,Žp ¹7Ts{øfËìÕ¥`µç—‡F�u —µmæ*�'/."fµ­I9Ra=ñ.ó$ ¤þ’!jÊÕ�€åV6Ïá¯r­k{•Ÿ+ç rÚ�q¡äô3Ï#Q}ž ê¥ùHÔ9oGN‘n´žg¯…™á�5YÚ7 qa\�æ²î/ìßKN`S°·Àþ`ìëZ-–ÃÿžpwÙíÒÊ´·w}Ö¿M�ÌŸ¤$G“Ó™¤¤n§ÿ„LHc�bç0Ý·8ïË\דðAò7fö V[i‚×GZOÜ IÅL†±¦ë�¼ë-¾„5÷ Q„Ó xžÉƒ!Ï„-A€íÔÛ½3|b+öªÖCå ИQåP)’n3韻ô/™ø`iG[ÒÙö¶ðø’bÜÛsA T�t6e©çFê¼ ú‚Q+Ð6ù¬o4rçncŒ¢CSÄT°g9Ä{Y¿¶¤\˜²gì¦V¡ì�ý\ù q�[ÉØÎSæŸILö¦y e̘ï=ú·™C©Á½{Œ@ªjq|Ä„Còuüõœe<1¦€‹jÁµjn,™‡ÄãkIZcE±C`Ô‰Ni˜dœ“–„&íXM²ê¥Ë¿5†ºÄ1$¸Eå›úœ{vî}év‰PzïdÁÍÉâVà!Ñ©êÁK±c#�ó­‹Ta’7óÔÏJ1¦ eb²ª®w0¨þ¦°arxÅZ‰2³2‰ðfŒvP^ɤŸe3É1‘—,CAXÜ€ð>6Øl' ¬é£N¬˜¾OvJ3 ש•øgÜx¹KnÆlëm*Ý¢¤îÅvF¶;Ì]âvn¹z^“ e„š‰{¬÷ƒ±÷nbË}å,Pk –Þ«×à'   ßðô®ñº6õ¿ªn:Õ Ðé3à$dÑü€ç+E?TH�¡Ë¡00C­¯`ªš¹WѲλþ= ɺý˜ŪŒµ»K0FCL̬ÏT „RT2ç¶Ð˜áÄóeL¬¶Âø…†Ÿ$Ln²I¹&9uÜ]|Ý;Ò=¶!‚ó·Ïbúr`ß@ÀfFÍíbÝ�<Éj�éødZÒgô½.â¸ò&áÈ›4[Å’³&µE„­ï—! Èž¼ƒ‘?”*ÂMÍÐ:êuƒFj×àD]‚xælSw„ææ¦+TgbcáyTÌöxóÙhA¥“‚Îï'Ã;WüÃŽI2¤îŽÄÝŸ�14n& ‘û2~�ü”:>¾•�–&°»h–‘ 2 ù>Eq `ˆE½tè=1òŠkÙý? iHÒá½ßl6À@"çTx{WHLƒÙñÈ}wnëÔ‹Øi|ÚY\ÿ0vd)9­¡·Ö¬DËŸ‰ Ðb‚�—P‰2¼Ñ„7Bîvh~ÇçgÐ Å0>!lM1eG9ž›Š>öºeß)•/Dbªm` žbµ”kŒÞ˜L¹y=¸àôKxªu•ä³{2¥Z,8±7ᘡ:"¤W×ËhæöìÐkMRRõí`œ_¥¥ŠWéÿ¤`‘ô£-ìh`k#¤üQ‹)øˆ†mÍeœvw°õ�Ñx*[_W8ÖÀòjáøÂ‹Ês*Ð}dòÄ=Ž.ޓשÀ3‚»-EOîjÞ12t ¤»pÌU÷÷c¡Ná ¡Z‡^ã,©ºSÛr¹`£\ßî>“LâG¹-¯]$¯çlp`âëz³ééÊì Ô-ÂÌ Ä¤IaÛ Pé庌.&ùs+Ù'CÚZïk_$+‡ií~üM£¼ý¦ pz*”ÈÖS› mæ£èù=ë–‘Š• \Ô Ÿi{÷®Åz]ØCkžÉSiæµÜj*´Ÿ®å �¯Œ�Ûü9dZ9žšG­…óžM2 !mÁþ‹nféˆ4/[,­Ÿ s½‰E°i_㪠ƒ·<à-¿‘å½…vËðñΤ{$à ö ø¶Rɧ$36p<½Èp‡Sewo�;mÐJIã´õåýSí¨VžiUã‡íom2 �a×§˜ìíÅ 8“â Ô¹ Í�É$ö}È0ÑæSVxü«& Ú–ží. Sx·à^/ÔnüìG£ŒÆå.4m”øà_—rŽmn¼V F™üæÿ$1Ø•Ä;í‘4?4þ­ ÚÜ-vÛ§ÿÔ‚ùM²E¯ëÞrÓ»:v>xNPD†æ¥}:TôÏè=î2ÌôÆd„ OWÁr�¶Ê�¸GCÐ[/UN€™ ÌÝ×oçÆÖNO§ØIé°)ý'çØW6è}P`apëÊ[5¥yòåhPw‹2›´ÖQ~„HRlP› úD€»«MŽS´’æ*ƒ|_‹R«s/]v£ÏNÚ|Öø�HàÂê5ü�„« ÚpuZ:z\šr%Y’{©?/¾ól4õÓ‘ß�Je–„–'EŸ–œ<>Uñž¶2¥ý ^^æýÍxΓ°aÚðjH’!Ð[ô*¬»ßãzþ�÷x¥èa[vµa‰.MÚP§µ…é~6cü×—á9no»×Õb$à6\|BÕ˜Bžºµ¼Œ€ «étãæ€[>Çc¶Ã®´q]/»ëË`{!ʯüù·1MÙòÅÅ„Jp©Çâ9Á$ϾŔÑ€:a°"µ(Ú¶o+8ñí+…fØ$y“À׎2ÂWB.žŽOÏî­0Ù8Ù ó£Gýè>àÀn Ç·Ô¦ö¨ëçù¤&úq�´a\ö[&…8$�E¿rEI<•„Uoç† a!ƒŽ�á¶GG)}8D%9 ¸ó!¿®çÏHáaÿØGõñkY*Ý15‡ÈEõï\;£*I«ê6²¸ —mð“g|"�Þ¾Íá ‡LÑ.†XsÞuÁ$±‘ö°–… «·Ièº"ì!Vþ³#D7‹aÍémŠkñ7q¡Af�^¿Õ#‰ÐìÅt±ã�–.By—׷ëœÁç< ª€É«…1×dª󟳠é›<¾¾®MêÝʸ¢Lö<#ݹ…K¤CM}¡ <ð1 t\±ëÀG$&}pE²âýUê]9r—Y_v3(n0ÏÜ‚A�G¦¨®?r€”áÖ}A“üþþæï ¥³°ÝŒê*7k˜o^æq™äÁNAtƒŽ˜o!ï\?ÆËp�â;�pp¼¸²Í±Ë•&V¨NVí�NY²ËTaþ2K·×1�ü×uRÅjÊûΉHyáç¼�Î| ñ6ê$µB ~uô#û3ùÙ…n‘ÿž¿BƒøÌ."Ƹ¤+ðÐ6…‰×}_ߎôi°h^ʽKŸÂ¼Í/Oç‘ g — ž#� ´ý šJ¹ˆù³Ã_™$< \²_Ö’ÑѤgt\m9K <ä¼²WÔí«p3ƒÍ�9³Û%TÑz¼JìØ×š—–Æ09ñŠõKa ²‹Y�<§©õÿÑÝR08j†ån„Ù5ã\“]�¾ª;…�8ÆÐÇE:Ýš DàDÔµgãiZ¶—|æBé‡rLZY>ÏòG|6å�¼ßU¦O¾!9 –$•Ë‘Jìœ7£CøÚ †â>�õln'º]¾aA»q„dúãõ¶ÞÆP…óÓlã6û�‹¶Ëèõ¾¿-Êû,\9£§˜Ã}H}éI>XËk˜9Þ1þ4dižÄQÕ¹²’çZeü�³þÁï6Š“ûözÒ�>q+ÓçSÚ°¨·­l•Ãá +eêÒä�V†�]> fÕQø“þ;�ä ŠÚL™÷U§3¤Ú/‡ãò˜w­¿�¡ å�¶øíé@ú𝯛×ûÚÂyÂ�§ f÷ið�íÄ+>JÊ~Žxë3[^,Y§ua ž¯)‹‘[šmW1_/‚>_MÄ;è+ƒ%ßܪ.,ffóö�ÃÏÐQ‡G‹Áfã,}¥¶¿y� ¨i;–Q˜ ¼Až±${¢ctíO‰çÿË $Ë߀à‡ïº§œö,w÷Ômý²Üæ•9•…þªÿñéžÔ¶wâ¡ÔSåpÆÄ#7rÙôb]?lIäëÙ-6î./רɗV�MGa]ûÐ:K¬ÍVƒË-¹¬Ïj´îùrøþ.u�ÝÑ�¿U¹9·Ä›÷Õ—æ¥9¯ª‡œ’'Š>‹Âö Eô×#>ã>/ÃWáeïY€=PøJg 9^L³Ê^ìmyéŸ ï0°GVh[?²0!ÃWEès�ˆƒ³þÃü •íê¬S˜³ózM~yãÒß]O¸™à§6™¶]ä ¬÷j´¦d#$¸ ©Õ�U•ÄÅ~o†>6¹U|è.5ºØè–¢V[¾ä©I£iI)¬´~¡ª¶e²Miäx„Ÿ×R24S Ž+"eþL™QpHÊ&V— §Éõ<È{óí… ¼�y®áùÀ¢N{:À=�Xsé¥#½ç¥*€z8mÏ}›LQ�WY  NOœ-E¨Ï“PÝ ø�Ùÿ ÷4]Ø=Œ]ù¹xõVnÜKʉ»ÞwyMÚ_Ÿ•$‚ë²z×ÝàJ60‰”› ™¬…ÀX…Ôi<4fÊ‚N_dS|­™9°0É€´yê* µ&#‹¹Ì±%^î0¤ž’x¼ÀfŸÇ�}›)Uœ^š°^âµ'�y2fqþpwúrMçxd«[|â=­ðõÜŽ= Ž×º5³Un,gj,k† 3]¿k2¬W×»$ò6Rû‡yM ©¦çaD#¯n¸Â!. —Äæ"š¤Â2ð€,—Ù¢u¾ÈŽ6†�Å?ÿ¨â¬¢àÈè~8B}0ï h¦Çpí¦eð�ÅÆóà ÌR]Â`i>>àŒ&Ék­2™�h§S&c©×ç§Ìœ7U` üó]›ÍãFÃß.ÒÌé,03Þ»m£váÀ`ìD·.'$­"Á–t 0)¨-帶” `°�^Öž2ü™Îžð…¿ûUš‹9høW•;C2ÈÄÙU^ã¥íÐuEÖj«öìfר–ÿ*cúÁ=¿F.'G•!¬l Š)””ÖµÑiĀìߔX–³ô§pÎ/›ÂóGîë@²žI·óªz«F½Nì6Í};¤E>µY´‰ýêúp–Ì€<2ºÂ‹Íú};‰C¼.Ø࡚­ë­Ûý�…Ì,_,s'Òéà̽|#˜à™±²fÆ< "Ê?½äM³þ‚£ì-ÎR‹©-‚·óÂ|œu]l«�lkmg²¦O|ˆt†aX¨˜l]ä,)7~†ÛåW…Ÿ[‹-òyÚ4³ iG›j“C*¾°Ús…Ç-í´È ¾ðû�õûX”䃲?ØEe^£!ŽÐŸ<Œuícð¢iFÎæ+ùEÔ¢¤(T×ê ª´ºÙ9cHµ¿¯·Áí?z¨o‰¦º¢3NÿãÞµL•à\éŸÔ¢j%D:ÿ}°<¥ÝMâ„Å$ŸÚäq„¦íuE.´«‡$Jž`¨ƒ6Ò�£¥WÓúLj¥!ÆWE£guÕáP»ï wáAbGMÎ1%'0~9p•ùœ€Z°×»ìÓÙH8o»Zo^î÷èú0æ~tÎO 4ñ‚ζ–ŒcĺrJj§4ælûp“ªÞRœ3u˜ü䍿ú’ï  hÌœŒû˜L¹ùòÌDÿçV‚-�iÉD(­ÏÖu3LÄ,Î7G3+ÙëÚxÛ}G¹Y:’{…¿Ä­ñ¥èÇ~|̱=”Ûq¬†¯u«^Ü$c¼°#»â‰#ÐcáÉ®–Žh·(IÜõ�còÌÌ:‚Q‘«ÁU­;œ­>°=©,Œì‹ÔþP�*Ýè¥Ñqì�u¥7¶"y"£‘ÞÞ |ÎÜSÖɦ˶™{´„n §°PG“+Ò`Ľ¸æÎ@™£Îj¶hâ%jAjÓO°²[ûJì»D=á=Ìkr~Ôþkޏ/ À1àÆn`ÜÿæDŒøª£À´ˆGÚ± kUkÂå"}&£µmºF5‘›3`]²¶û¹ Çºä ¡&¹êÂ�y Î6E‹á‘Îô ˜í* .z+‘Š8�ÝÚ¸2šÀ5Mwõ*>y”Í»9ÀNL×+ÐO¼©™3VݾæÇƒð:^6õý§Â[ØþËÕŸ 0mZ‹õHa�·"µ½†Å›²I¨âÒ¤”>J`[ÁðÀ ßãóáNG¢!îi J4_¨Î£°°F{#9Çdªª¨ˆçq ¿Á�tÌúŒ!átmG<ÛxÉIUÊf9# !�Ø”+g³’_üXüdŽ{Kk9*ÈW�sÅ:hµOiÍ”Þ4QÙìátØÝì­­ Ë3@}Y‘Ρz'�8—s�׿¾ì¹)�*%“»Çd§–5ê2*‡Ë½V�@�”®„I1Ÿ«ØlŽ{äi.á0�TW°+•¶"^Ê¢‡-Zе‡QÛäF¸ï1‚ )WIVìXü[gMšnƒùšO� ¥|1rN‡Yó]é‰`gj°ñð'”S0PS¤.jTu‰”xî'RœÊvdáß¿f+�I¿Ç†h_PGQYËH0ÞvΛìA·Wvüœ¹}ŸÞ¹Â¸5©..“y^RßðxS9”½$ëˆ�×÷qÇÊ_êI9ÿìMI³ükAë¸õ¦Wþ½ääŲhÆ:ua‡$z¢¼¹ñqê�R JP^ad)ÍøTÐ[¾´" õýO–…Üëø7øjçâ�òXÂs⃇¤¾u&?pT¿ž„¼(õ$;T’ÕŠ…³q>±7—í§4¢µt2ʤdË=…Ñ3Ø„Ô7™ŸšÙ(µ¯âbÁ O.<\èm¬œÐùáŒ.-F®N¨…×»P5,V¥í‰TkUp2a?¼gam¦˜kãÜpýPW£F²Ð.9¿ßfÔKÜZo9³쎠Y»+C$Óݬ…*¾Ê»�ê^Â[º,®K>möühî¾`èvæ¢ôA˜r¡'æÍËÜ¥6C%!Ã\×jp™qHfN9Þ�eè¤Àµ°]¡Bƒ¦}'tâ$>S&Há^¼E1lڊʃю—rç·ÈÂã ŒXµÿGugŠh€F ÿÅ…[!‰z!ßU6Þ ¦0Ñ+£äJ‚s©­Å«[1H}æNÚUl›p¤÷8 àwý&ûТ€¯à $™ 4Žˆa8$Ç�¶»�™ª×ÇtÿÖŒ2�ƒj‰ ?®4� kÕéwL·Sž\½òT[Ñ”!,yŒq‚ó<¨â =ÞÆs89X®)�i©²š¦,E¹&M¯A …¥àMaJâÞZ@(ñÝÁÍt =:ŸôFV´T´‘~®Çv¨±l5i™ ‰A»¥> ¾)Ú.±T/3Aþ åÝæoÞ¹fÍ}« ëï{"h,e–Ú`—̾ҙ£»…ç$šæ >!Á�Òé£/–„‚r¦yà]´áO–ºDÿYtO§Å¾–>´ P^©5ÛkRüËõ�Ja8Kâï�Ó|Ï<@H` Ä89áÛ�_/xÆN·Ä1v˜[«{àhÊ•wUƒQ:ð….a§Ûrà&C¤ùËÑ¢5WÓ/Ûí)lªÓýM[ö{2D˜Ûõ¥yV<Û� ߎ�}Ôø§:,žüÖc¹sÔ6wö‰«âNqÕPç+º7¿H ´PÕÓ/ý:âñ¸¸ìR‚k”äS‚ìO¡j{yetÕÅ}ðºÐÉÜ> X­Á>zƪc_bp€î+Tš™F{uÀ-ó2*¤~HØíïK~¥œïÊ;M÷i-J Òݧµ3”,y>Ý)ã�ÈÍÃ^»5" G ¸qgi=è`çÒn÷ÔûO]9g0Y{C1ȱ ¢šE<ÛRΧ½-®©˜»†Ù(u‰¶0~#‹!9Ý*Ü$–®e³ß©(µ'çP²km:9o®nÇ4íFbƒè“Ø(>ü^½Úñ¼’ko¬éÚÿ¡ J#øœ—§ÃÈw°ømÄ£Wÿá,öUmaÖT„Òmp[àhB4Ú–#9êª3¥ñ:?ëìçä�ëåWÚÓw7þqînªÇüÚ¹Í%eú²ÁÝl2lÏ÷;¸�Ós%+?ëç¹f1GÌ× ù¦y(|eG>ÔáÉNª‚ur8‘í*q¨Gž0×ɰ�@ŸEê‰?��V‰o sË@�R&øë/�ÃÓV¹í!õg=D\tÎÊ®õþ|œK”?âòã´æñ=¹9?jž2 �§«ŽÅ*))Ì&s÷î½rªh�ª¬êˤt�xs Ó’Øé4m@U²,§À=tI4D8tï�þ«-n jʰÒ6¥A«AããöSçÏ#òâ2;/*°ÓÇö¢cñ˜‘½:lÖ ’è®p•“Yui’3rù»Yë;ý‡®<šÜ–¯íŠ5ÝJü_È3â•·Œï áŒjËúå˜Áp5r\Š¡›¢;¼(¸Muç›éÑ{f#[kŠü_Žø“*8,­)K €"SìbKvyEff¿xĺ­Î$#øe½þ! ððiQɦƒ¼öš&K�ùÙX¾àYS×§Ú…ÃÄ KsS•PsmùÓ¿ÍùZ5¸k\þZEêJ)SÝo2�b(@tôIÓÞª…h“=njÃFîsØñ?„L<±2¤x€3g`мæÞZ¬Aw¥¸˜vd{àãFõ‹Í|øé.ùÙ´!¹°ŽFä8O­>¹Ý.ô¾ãÔ˜{Ÿ0fÕeê íÁ’5N¬Q­©j¨äúoc¼� ’ ™�¶Ü”LÍyN4è(1û(F'ûÑb~xÀîp—ÙÞÍlT“[i¼}]-s—ÇBÆØ¼˜èÓ,tš —<ÆÔ±àººÜ`Í€àá$Óõ¨‹7ý\¬û²ÉWtŒöƒÕ.+âX ç ™��ÉÙùöIJÿÚ=§ägcs®÷š%§ûÍu¬ÝN:w}ˆ%[˜×?,/1òsõ±ÏÛʽh(GœYóÑmš·¨9&ØÈ]\ä� «8ÛR¨¾ HNTOq[4›o@])Éñ ZpØ{²ûE“hñòSkb�²÷XÑu÷Zïœ�Sd\á”ÇòÁw s±ÐvbŒ²Ê)Òk·ƒ�¨Îdî<M§Ö@ùý�®£µ‚MsÛKؙԇ¬Á\‘þla7 ¡ö­¬7Iw›0.mÚ‚š/Œ‹y{!‚¨2ވѤ¾!éw¨’ƒ B#uÓ/„‹~ßu üÊ~&;ýoò3dC>HðÁ©ý�+QÊ¢ý…ç-�œ%üjg?·§+è·Š¯‰bþ4œíLø- }ÔµJcÄ©uÊN°8ùž,œî¬Ÿç¹(‡j1\](\ô~s©?úÈ}:'ˆ>p€j¿Ë˜ÀÞŲ ÉaDp íó�äW₎ PKw~º¨ÄªžJöBdk�ëéª`Æp)‘·Eü|ö·uo£�ȵ"´†qÀI–"û‹�ÛpÉ@Ú[ÔIWìv€^ÒDÖÒ褘„Ý8•­ éòä?õÙ«øjlPA@À›`�Ò%–ʾ8ZÙ] OÐCƒå`ÙÑå°œ1¥!Qì3ð*,¾„ÅÎÌV­,xœu‰I,^$º=YœÎL q·Å]4ÇŒõiñ¶Ó<ÁÃKkµ¦ËÇÅ3«fÂt5[1¦&³‹Ð ^º^Ýêfòi¬Lw}¯4/…ÏÄ–�é—úîhé‹z±Gï&Gz$Ô¬[ò�Õ�Œ³S’ÖeþÑ= „�&�[GÂ]æè°ºÑ7ÂØÁ1Û,Ù’ØJl.[_�¤î‹k›ÊJÐvÞáÀ.;yƒG�Üɽ¹ ý{ÁÓ}5*&NdÈ�hÒ] ,ÂAà‡y²Å\ÉÆ”™hù Õ¾q¾nc6ÖÁ]+þBᩎÒùkùgÁðV@È*x¢;¿X9Ì®�[&’Å¿‰öaA�yžË÷€î~·¤éJ›IäÃ’þe Z\Ÿc�᩵tžüŠ‘(vÔ�=K#Y§ÅšZá>XÎ]ìd2{Þ;ý©}Œìhc‘Ô@æì°¢†-.Êuõ\q¦Pÿ›»h<…¤I|ÿÐe4×èÌFÏ ZÍòƒôNx™�y݇�j½Ýá4Çõr8âæ§ñÆtðcÞQסÃFùçA< ϰ^­ûa“>èZŸ»ƒ,×kQ=u)7µµx&ò‡ðý€BBîZ¥ì^)R&¥á$û澨�|Ç�²^ÁÐü^Ó§c¿ùž v«N‚~¶>ÿy†2ƒÓ¢WKýb$•¶j÷y“Kþ#Ðôœ*•XI¾úüó.´„ �ÍaqêöÀ=XÏZÃ÷Eòܤж�‡`Ѭ+x®<ÜÈf(Öº§}‘D•W˜�)‰ÆÒ Pã¿[mþŠÖ+|ŽìN›½~PùE�öÒm(×~×pIx¼h”y#oµ{PKØîMN³pAÜeò ÿ…Æ4díù*»¬Wر ͉ !·‹FßÛðýAÒ*C²ˆ†><ÚE¤…-BÄ^i‚¤;Í>ÞO9]SÕ�‘OüÍø£�ÂFû “&ü 0@!×V’`†wí9:Ü€ Ù&E* ’Â@Ž–Ö!kÀ“mÔÛâœaØ%�,œlFÐ C¥KÍ«$R؆¯~-mUd ÏçëuÛýV¥÷¢lÁ Ý�í�† U¨=èÉÂ�©ü¶ºß´6 ¯,n\K8‘ŒK¥Ä œ7²é�{ˆù~+ß;HÅZÀ€ôuB?Y´I¹pä&wö‹>]áéwé~¹ËŒ@»IfÚc/b-�ì•_PùÚÑO…yß‹š�£ ¾(¢Š8&‚*�ªi?ßäݦ«0M>È�ÁÅÆ·Û¥4„bãÈó—­!Å[2�Jd÷ ù߸BÕ‹þ3æ¾HÃÁûÖ~¶GSñÄþkw_°0ÄýUHdiRã½�ƒõa’3ØØ[„ nêP‡¬P%Çwڭ瘚™å†vÂÞ ‹�+yºíñýèwÃJˆ³²„çª'ÑÓ"$º²P•‰ýIØv®Ï”»ÞMÜ$3ò—bd‚O‹bœr¢Å6$Uo�\góãIÔCD×ósŽé™{¥6$ ‰çTlN²/NžAЏƒvä´Ê¶ ®z] Ò™jõ#êè>Ô±y1ãjþbÜ3>m1ñ°S©­ÿŸ�ÃÇÚsêi^3eZnªLmÈÁtH7 –&Žƒe†8‚«ðoƒøµUêÏùº)ÿg¨ÜúAK ÔÚA+;­Ü�¬»ßmÖ\ç¶B6M9 §ª ÿ®„ýø{*Ñ ð*3G;¸ÂYÑ‹»QÏIGoO„âû-z'~ rß`ˆ~¾L§. gEË„Ç,èz’LaH`†¨¦Ë1: cáÈWqäñ¢½a—íéµQ®[q¢Â2ør­Òèϰ ÁóXÂJó>P[&"%uw‘೟F”ø[DÕd¶nÚy|þ5•UŒšTçYv²ç½‚y³} bì™&�ЊŠu!}®ÚáWiE¹yð{á} aÜÓˆ�[7e×*%ý^•¹²’±¹‹Ã5c\Ì� ×Iš\×ÒÀ½ßÄ×®EºûÊ/¦Æm»QuM¤~‹‘�Ç”RêJ"¯år¤Ed¿"˸¾‘|¤3Nj,ÕNuo]ÎÏô*€Ù³ÝâÙ’¡¦"™ËZð„j¥Ý¯o•CÛí"ò•­-.=m¤°p)±bÊÄ–» FOĹ³YÿÂMâÉQÊclØ�MÀ'¼àDÝó�¤Ú2ß‘X{„ý“„¶&Ü–14)¿˜y›_儯ïäwŸÔyù£=~5¯<3\ÈÕz9¸{3¼Qtã©§*­Éð˜ôÍvqqÑȤYI¤néÑ´ÿ63—ʃٜŒkÜÿbpÁGXšˆ|IY�\£l½‰Á¯Â-‘ó \ÑQÌOã²·C %'ƒ2(J£i€#UšÛ²ºÏbDçmXH—¨°¤¹5¼Zj=HÕm]b9§PW‘ÌÒQ ‰”ÓÉ ËßO+Ø¡ ¯-|€�(ß9د\fÈ�‡™o=ë€Å�á8Ÿó„‚¼mwá㤔e§ÞRšÚ׳&LEîÚF3÷/ÁÈcÖ@Ó¡qäI_ÒϹ6�&4¸hU·ÎŒdA9]ür é·Ð@u},hé´Oûû¹däZyNô;f$¸½–æ2%ôLsëõ¶)ÊÃ<¨Â©Üä5Ìò+.®~7ŽydŒ4fÎFk™÷˪ZX0èÔÜ{¸Ï…9�˜8Jðí�õÀS7&ëþËes»íé÷j>Ð;áä/}î`3o„@>g²Ÿ¶¸`ï ˜Y'pâ‚«7ÎÒ½DÁ�½d¥Ü âMwÜe?ÿíVw‹ÓS�`MR3ÿ›ŒhºVA| pm¹bc‘iOÞ1|ûQµø\êµ�‹¬¤Š-åž%lÞ¶¦ú&=,ǘž…ÐeªWÞæ ŒÏ3C³HMÍœ¬‡Ìdh¨3 ÄB YÄÎ*àbI–ƒ6 {�Ĩ™¡zëwæ˜ô¤gt k܆9<ˆ\ ¼Ê:šZ ,L2TÖ9²LSìY8…¢<>ª\sË:‘‹>kð y£;è˵”ÎÙ?uóa5/±‡hvKý¤¹ëÿ]€ +f�w³VÆ#û³ˆW——Ñí§o{/”çœ6cT”wéÏÆÑ“ˆøó”Äíò£A¶ýà/„£)wÜE�9œÂt“u�ø’ ²^ð÷ÞÅHòâÌyñÂnD â6‡šÞ;rX$Ó-NTæ~ÑQ˜dP´‡Ñ~ ¸`uÊ(’‰Ï‹ˆäÈÞ†K_ µÿ¡�HòWØ¢fq¤$oõ8öjjjß°þµ»B£Ë"¾k›Ä“Ë@èµÁJ�Ô7ü|x�®p’ªÈÓ®ídâ[2¿ˆPGC<¨9\h%ž·"Îf‰åšƒj‘”°*rýšÙ#"sG7Ó€#…Ybz÷•²ß_x»Û¨c0" öâ„ðʇŽFõ™¾Á‰KóÖâ¼ûa¤½.�ôÐè- 8Óëù§:´®)ŽÿY5i`‡çäfÄšZ¦Œ?OቚÞHßZœ^èM¶•&œM�'×Ù)ðdðF[º¹ gB‚Lôn´H‹ú„;ƒ7ÁRé"µéLªÆ¿îC²^ÎÉ|6½Ÿàãå|6ÊJŸÇo ewuñ±VQ5åé& ºœãRí�Øñ�©ŽêŒ¹ÐˆŽ0«JrŽ}Q*—4kñý ³ÓÈšj7à²cJ}‘ÁbO8öIøíà†wµE?›ÀF§Èø“ºÈ½6¼åµZƒ2è9õÀR$µ×J©+ÐE}ÉèÍiîq@û½ß­ã‘ž’ˆ;5osñ–’Äàn%wÇP¥± ÌD¤±¬WvFÂÀØÃ)ú½„gëÜ. ¡¨W2�/=…Þ^Ì�•=л¼õHIVà¾äè�DÀ•ç°€˜ öG­†TVx—�ˆ2˜hJ+œù‚`saŸG»X}yWê®û0úy~=dF½ivR&JîÑ¥U“Ttùß9  ›Á‚ŽÌªF‹W*× ”Pª~EñÎ줉Þiøó�|2B ôß§r²Õå$™75±m–5|PV‡x8¬ñ!YuR7¿‰«)¼k€=„‹„:'hCaÏ¡è€ySÇ\2ǹaO:záåÌ™UÕ`·üi¯› Î$¿�€Ù¸¡ay¿ï‘TåºÓ¥n¦Ìz"Ø/} ÚÏ ÂÐÅòùâᛣ|ç·»ï°õ±S ?"4½cJ¶ÔÛszE }eg/Ò¤ÒœÜËóAvEêxØÕ°!âwòx×ú®¢1Ø"¥šÕ¦×¶d=¯C’ò'‰$å¨ÒršÚãƒ#2�µÌU,±µh Ú�<ˆ¯kNzHqô6͑ٛfIÏÖó:‰Å.‡6´ù¹åÏ·•‡}R”µk’¬®Ô'�Àš9-Å©é¨àÞ^ÈIÙ»€Tü_,6 œr@{ƒüë9‡vÑ‘ÆýÊhãÝl’¼ƒ×*ÞÂëP •€l(;4œbøÓJ¾$nô¼]Gµ·™wŒ?à)@-ožþ¥”^9Ðty•=Ø¥‚ˆ‘C=ó#ÅùÔ,ë‹TƒéÚ8DCäxa[añ¯£4!�Q- C!]EÒeü ‚e4Ç8q NdÃ/.ò—aOl˜Ç†¶d©£1'bË o"ŽÕÔ¸†qB/¶.Q°UΡ;íPÈ”yÒãþ1«,Þ±¨àCÉð.MS—ý„Ó”*uv�âŠÍºm<ï¤úO¢ê†~Rwù&-¿ úá7yÜZ1¶È`B*hýOÃxoCç¶Œg|SÕ©¥× þµf(Ö ÓDQ³çf8ʦ(?£ø"Ü�ô …~DëÁKg&‹…öߨáýŠM½–£—‡sû¯uâ•üP­Ÿ Æ' n_x°cP:„]±¨Ý(1ñ½F›=ç]«Ðº6´à7ÒJ;ÐÒSÍØíÐàÐË9Ptoe‰ã°ÃƒšØmàq1²±åh§^šgöÇb|âc «Kç@Â2�e«’|îá Xk ÕíÚrÁ®Ôø^>�•Q¿a†Lô(œJ�µï—jäwûqî†9¢î¼ÃÏ"ÕXÌË~SŠ�)ŒòûË'B  fíiOzmr¤ìÔ íQ\ 'ÒLŽðñ¤Ñ9kµ EéÜÖyn ø4[³+ N\ô¦m*Aþ‘oˆ�AÞi,{”&zƒkP¿y5¼Íz¶…´=mMp �ÚzïÀ\¶š,F^2:âŽ5ÉùƒrZ cc2}!k"»r’|8)†™Pl—‰ŠC•–†.Ì�o8L¢é,KP|'It¦Ô1_š©š_%æ:”%%̉Ÿië!ã0ʱO­~ìÚô} {°y ïË|1ÅÝËßû:´£×èŽâ_ø¨ô*'Â�*ôc¬ë&ü$äÈhÍzmøjêø¡®þr8Wx…ö29Ud‹\ŽPø5{¾…"Ãi—{|§—É5UìcÉL°j9¨gòð\R*ã aˆ Éda:uʉÿž;Òçã>I݈£7àƒpõ¶–Âë’XLŸ2š_Òo]HÌð�VoÿðI¿ÎŸÊÚèÛ°`ËW-ë”O)øÖm‹Ø7ð»›pBïøÉÖ)螨j‘[‡^Á~íÕûû°ò•ËØâñ¬lÓµd|Á®P¹BXi¯›ù¨yÝßôG­’Ê7÷kª-cmòƒù¿ëGÃþ‰Pä™l޳6åÅ_´—Æ2­êßh-ý’ljæC BÞ�ês�0:ÚöoÍZ™ñ6�Çõ ¬9rÊná�Ø ¦N7SÛ4tª%„É©Q9OÜwCÇ=3`þßÎZÛ&@ƒ;ÚŽwôPÕžL„ˆ5©(K÷VŠ5&6dê'uQù f,aóéþèÓÊ’|nkøý �,§½p¨9j‹Ü¦ï$ˆ¿k¯Hƒ’Er7Ptîä©wÙèÑ/¾mˆB˜;Äæ”ƒ!Â�/‹Â€0l;[µ¶„ZÕlð~ÓÛà³A¾õWÄ98jÛÚÛ¯Âyþkª ¼›ñ‹ÉܺèCùËû¥Þÿþ…{ú—»${ÚBRÙ«.šú™f—¤dZÎ:f"±Oy 6Åñ!œ°7ô*Ï^M2€o¼¥vSŠGè¦s»I²®¶Ä­„ˆm™šYðR2…uÏKX?¸íã :Úé@é8�‡­¤fHâüµ2pk�µ¢,`Ýõ¡—š®vç>z·ç-?ýÁ“. ™®¢«+Wëýã.T¼ÞÐAâ@À¤s.w–4ï°t®¢’p�â5JP½³¬á7 s2Û«¶…д(ª¿õ­Úˆþ"�eý<I‚n2ÊÌ�´Ð½ü¹>uÙ¼Ô ¼p!vó¼3´µÕ=á¹+†]‡*EÔŒº“ ^”pS |5ã¢WOŠjá¶@ñaâ>Ðøâ_-;%Û·}¤}òzÄz_ Üþ Íêð�´M-Šûœžî¤Ð‚V;ð_–ê4%€N2Fa_biÒ.KA¢8nPåè&Š– H<â®ä«h«aÚo~ˆºˆir�eCh,"á䤥Φ‚K7ÕIÙ±_QìäUDÛéР™Ò‚æÒˆY‘&Â&IÍb•Z…ðDÚêæRÑ`Ó”<㻚rUQìûåùç×p1ü %4€× ÊJ"ÔZ�F·ðRŠ;œZ&Ð;éW9Vô�T“@ëHÁÉ6 ©lèòÙÞŨ+6�hÉ ðÑÚ7C•ÑoÀÁDP Ï™È+½ÛÇgk”Ôr�І÷tã_<­Ã/û®èÈÝq2(�BD¾È5jõd:zyhéFgéLÃñ™CÌ WJˆ9°¥­˜ä8jÙ¹Íg‚ÕŠN“]…íÝO@ÎcÚòwø¼×jÑù:~pÐ9+½+ ñdž¸hìåô{°FŠ-²MXS`E‹ \ÌÉŽ¸ ¹Âdˆüz�F¹^°);=™ÙtÈF %‘_ö(ºY Îñ\:(Lÿ˜dlF� €zšœí ÅFj"³±nË�e‚_—$djK¿aq}.î)1‚½×ºß¬ë:T€ç«àøj~Ðë»è¹îͱÄ)e7�ÿ”¼äŽ*“Û@YÊÛÎÝŸ«÷§E€¨”þPˆâö‘í­šŠü,ú~ Ú0„ù¾Ê ïÛ³M‰0S?Ú„Bõ$[†u˜ƒ£ïÌsV•£xïÏ¿„ÃÇ@ØÁ~4A ÈS«&±_£ôágNÞò\ü¼OÀæk×Oø)~�yà"¿ŽT·íöëjôîºÄIü°Eu�Ù#È4=ˆH‹ß”ß}Î2s¼1m.ŸÌñhßÊ0Iÿ+¯ǃÉò_/ØÀoK×�o$«ÙêS®º@o27¿•Ê},øq}‡«‡ÀwÉe;Ÿo�ו'wÀÙI‘_˜83²Nàþzžâ¾]Ðû§2[Ô¼›mE’[å~u[*bþe'%FSÖ½ûr„E+¢l+QîG³H'Ýd¢_¿:¬ÔjÄÌ ÅmƒÓ7.úÝÁMóáZ,04=b»I‘Ž‚v‹ ùR²z�zW™÷^À j _*ËÚ�}³tK,¦�(2å“¡}xYKwí­dÚ)¼ÛÛi`ûAj,Åp‡j™`§„~ì4À÷Ašõ¨ˆKÎñhØê ´7Uí÷.CŽÝPb#êg Oü'BáÀAS1îÁ4Á}¬Þ –¿*¦jB%ªO3%àhÅ—ûpP??Ñv^Ãfqm®(lü,,px‹ITÄgœô+ºòëO2±îÊhO0Ú±Üà�Õ]ÞÝüËñ!ƒ E^4I÷;óqCóŽº0�ÏW°´‰þ5;wž—ºƒ {µGн‚È¢H¡[â’ÝJ:” °ŒßÈ>3cÖ¡—­?Í1Í£FXƒõ÷úkÉtÿ•ó`d"ŒÎw÷ùøU"oÿƒU;«ì§ØÒ¿þ³ QÚ0¡ž`^´ô¼•%¯aàJ¸D)×'yÝŠMÇÍÆD?Ô˜“{ˆ5ßD“g’yòUT‰bYк›ë¹ÁÖíŠ�žº4챃÷Ì»6)5¤Ã–’aþ2hþÊdÄ(qÒu>¦*X*Î>n€P%Ù~?Ná^ÃÃeyÜVÓÍF½hÝ<­ï#)ý·"ü¿Â_ƒÆ1æV¿Æ Ã]¶hNÈSƒÁ ™-#Õ·­Ó¸‰7+´¡µœÐù©9r‚]>z?o²· ²A³Þ¶Ûéwo87#FDXÎã }MryK{G‚› Ë'ø=I¦Þôhö@¯CX0’ ;µmåM¸ôYI¤˜ÿfËe.~¾ŸáfˆKýAk¿,ŽЬOvÒ¢ŠJZ{€“fН _.QÓµ¥þèBÏø£¹•˜šØQf �=´Ón!M�Îܬ]¤Ç‘Jåv-®UšÌ8ˆF%¨Ì?éf’;›*V&Õc(w¿ðDÄiÙMrÓ^ #æ5ÐX%ѯóL°öä (àÆn.û9…!Ìx5pQ/8{øºôW¼ÓeºÉô/a¤‡.aúÒY˜?Êe<&I̬§ÒBQOÅvÓ1¸*Ž©Ϫ†¾‹n,øG^äÿúĬv>"䆱ñ^@׎G�⬶CNrƒ=]�;<¶½r¦¬×îX5û ‹`ë¡ÚÇîÀ Ž¥;ct KØHC{‰Ï}WI/:-¸–£}=×(ÔÊCº&-É”Žtäqœ8hXsB8c·ö˜“Šs¾1Ó€ÛhÊ6�(Šº�ûÐã“pú¹4²ÖÛ¤)xw Z)ð™0Êø¦³)è<ú3ßÜÜmÖæu�ðXÕšý_`±ïø§Í×ÖqÓ)ýûÿ¶piˆE"éà·œ¢u×ITLƲx«°r1…^xwõŽX3l©¬¨…Ó0µúíR¹îw×fr^ ·³ö¡xÔbB‹Q�$“E­ R�ŠÐáUh9IF¨>¾{q®Äã ýURx; ÔHVŠ+¥J}FfB;,ÕakDq~¹àÑs›uå:Ëq™ÎðdÌ�e["¤ CniúÒêÓ|îU�ƒ÷ªl½ !oÚ“pÍ+*XŸ÷ÌC½(‹|Â�8ë/GpÀ0w<âó„²’ˆû‘Z fOéT>¸¼¾×rô¾rdÁ&ÂbÕ8®U>LìT£Z�±"ÀÀþ5“*ߌàÑØ9v£õ G*‘à[PÑœJ¿�y¥Sjs|T¢ êUس0*�  ¿Èðo¯K­Š­=·š‚ZVÞôÍÀtç™5YßÂI3W7žV€à€+™EA›Má–É”À!ÿýñý¢ò—7Óh,쥎 jf(W¦ø(þº¿áæ@œòÖ¨ f±XP¢úÆ€uŽªžAàGdŸáá¡[ƒËýå)“OÿºÚ Ej­Ò$c8We­F3 e?KXÑeĉu'MoŠù†jî,Ra»‘£ÐñuPiB�uñ–‡Ólê&›Ÿšz:8aAO DÅzÁBÚ`a”„(o $3½|àn.¥µ½J§ß-Äx>î&õè 1`�–‡á2P’Ρ’Á]\ù ™ôuàÝJæwæGN×)™¡ÞŸyv 8 r…ÍràUí�Lãß !?i*´j²á›Ç$ª7j”¶8Š@#¾¤·¾ÿŒ:îS¾¥üÊÿjÒhM׋§;˜×"=@ö/BtxS˜ÿÒdR]þ;�ÞäTH¬qí¼€Õrµ_$ð¬y’œõ²âÏ�p<¢‹¨‹TËà_¯‰$øÖ?¨iH ¡¢×íÒDiôe©É3)-|Å¿÷„m‚c,í�#vM»b�YGÜÆñ'«ígÛ±‡�žÆk•šŽÈ5„?o|eÂ@Øo0?ð+›­¦uÐÂÜÙ°4m@r‰QuP¼ ‡Qeí­P÷,s¬ÓM(›ÄâÊt\úE”„>±ä‚Ï‘lËn ¿…ðñ‚Pv ¶³ÑK76E³ûƒ¤x£Üñ®'ósö®˜Nž‡QúµÙWß¹¾¶ }š%p8æUdð¼$ÌYŒ±¾hDº»£MÅb� ‹z°Fìo@c§´º&à§‰Úæ¦Ï¨¢“dl§ya‰ÚÝž/#­‘+芖V30Å4àŒËùj$êcUÏy‰m—úKZ¡Yfö¡îÉβ—ñD¡HÉqð­Ü!±XÆÓ(çjXwÿTyµ†ÉNކºE×XP—=Ò´Ù˜Èú v)þà/©Ž”¡£bPŒ·[DAzù1@÷©Ô?£gÐ_ª’ÿëQôû«ÎÖ 0é¹þz.ÑÍã åk—2hæí�¶×& }O8osÖ0dœ²¢ ø«+ý47ÉÍʤ5�¹/£QãË•�—…¼e¸POÃ1þ¹.‘†åïKŠêǭͼ@§‰ºÁ¯cûϰŠAqDöLâQžš’:jJ/¹ŠE•¤îõÉ‹Ò,[·V0 ŒüåÕ|F­C}_ÖjƒÎ‹ÏA€„š›‘�€ÊùƒÞCÿjŒ$Ú¥Z²²hßj??‹z7s=#• '$c°—肇H½Ïñ2ò—Å2ç“΄j°¢w2míò�kã§$‰HDÏfN2º´�ûSM,5ßÙ¦s˜÷Þš¾ƒñº¬Ö¥¬Êþí¬N�Z–›ã¢²› NqE—-ÃE¯ÃlÝRĽïC]]ÿØ'¥4L ™·vgô5�})À´U]ˆ Ý ë‹L€3ܦÏ÷Y²¹âÐñ Xa­PoX[zö{–º9:¨¤ÄÆý<]z<­$“ª`Çã¨ß–­ Y¢Çì"]L½��☜~é\ä�øž$ñŠ ¼Tu«:Kpõ[?x7PàzÏ·{o¶„‰z—M'æC{±Mh`óÝe›±O­Séø°XŒúÜj: *OPâ}øÓcÒ¥å6Í +Ï„jzäî„·[+€ÕÂ`ÚîÞklPJ(Fp ¢”šJ8Õ�gøòÁÛ/@Ðìúü#[¿úxÌ·ˆNSïÕZ¬£doÀžtÏÌŽ<�*‰¾<ºV A ΚŸåÄøÂ)«ToçÿÌÇ�›ÌßTf¬›“§x^‘®f÷Ö“q5U‹}m,Y÷DÇè1ð¶6{AÔÂOüv¨h1¬P4¶˜@‹·´¨8ººÐª£¶º‚ýØ'åVWYæ\ŸD¿ ¿Ó+ßeÙñ‹üV¨™†€ŸÂà"Ð ·ŽÈÙ¤îÜììØ ÉéW›ÓkÝM—�?+‚ïx‹�~DÛ•™"ˆÙ*¬¯nM!—tŽlV®°Ï8¥g ËWœæ~oãóDkˆ<KÛ�?Yˆõ>€¦YPäˆ�ì‡t‰pYîË©ZÔ÷ÁJùT´RP–±ªüö8X¢þE•×;�O–a&`6AŸ7d”D\'ÿ Ù jezÐ9>ƒ‰ ¦ÅF§ôÔŽ÷”ákZLÞß—È!ˆø5ùVMwP+œAÍ'ÐÐkN•ìRQ œ*V b<3½¢Û9ñ�Ü…MwøŸS´ñsê2 �è`!ä$´"=¦k»Â•wq¨û)*Mp ~ê¬.µ– P)é�ÿxÀ|T¿o\Épø¶þÉ›:T‰NF¼¶R yš× 1�–îXôƒ¿>¸RÐ0€1¤ŠÐ ^-Àþü›²°’pîùùÌŠsj«Xo§gc«cÄ�þšq_…'î]ç›4ºZö"xù�³ƒþ‹ŒU{¾Z²*�ÐA”F±bn“ZýEZìX2ýŸˆabD}4 Ì´ãçeú^fÓ¢ÜHo Úö¿ ä9UÆ5ļþŒì¢«~ˆ¹:vÁ0¢J™Ñº9&Çá¤ÐÑ%�Ë]“�›7v^z]}_CIjŠ6qÎʨôz–‹4€º¯º­eA «H(“21~‚WªÔ£(f ì;ç4uó<ÀÚ]H!nmÛT£ƒ’\°W¼¹OKªËh@ö›ðàƒ1�¥-³5ÎÉóLLó»­Cª°¥þb»hìäÁÎX´¦TŠ_/Yù•ÅÈ Ñ>VŸ›; õKëa¢>ØÅ«ø5Þ©df=?XÿêPoE³BσKeeQe²Arw^‰Ë}†ŸSrh‡wÕ{0ìnLÅþ4ÆàÃz$»{`q{¶ÂS�Y즘ILÓ(Kœè†ÏY»þ¾×€Ó·ÿè¡ÌÖ%vq8sRÃÞÓ8ô="¡�1[sƒ$ Í5ÉìZÀW^kÓËÜ>B6ÑAQ"Í|PY§”½["uÂ{SÐ�•@e`9@z´€‰m�ë‰çOw¥"D—3|ð�S¨ÇÔµr|MÝck$é�¢ÓNMÆØtÚSÉ�‹;Š#f(RÿZY"A‘¨ð�Ê�X;õ¥‹ovÖºž"Õ;Üø0Eiµ›Ûøö"#)’“ ï=•W±Éy½“2&ûëòi¨ÈÒ _ŒTÎ3>´_;�"7,eÀw;Þ<ˆJß•œt�ÎÂQ+Ök¨U !)·yÊ_Ïï?÷G1U íU¸ù´ÅN)KO‘®ž®tL‘4ÕÀH#HZü_€nˆîóI’×yF6n5,!z°:s4þ99E€2§„9@ v hE©_›ë'Ââ…¹í*[î>Îb 5C'Û,w3\Låab]꿸Ob“8:ÔîEat±a½e^ž†>¬n묡ý̧ÿc¨þGƒ’i·;Ìëõ@Ýxƒ"ƒiEµfÕP‰ ìÏ¢Úóòûêué«a} Ëc±ñSA;6ùI��Ι!>­?{{Â!îý¼5†àí�‡g!P‘uÃÏ„m)wÈ7ûÜE¡ÄYT< ¤xÕ-Ç”íx\…¹‹ûvÕÚè"èÂLG;g«Zcu¤–Y³Üñ1€q’€(CÍI2bz"|%ʯÞJ¢$ñ��¬5ùø(Ó9ykøE¨[0ƒŸ€•ÞG§À@y„EúM˜­&@È*fÆZÃŽTÌM.QÇpô..�_üóÚ¦ø ï¢oˆ5ÓzCU><Áƒ?òfÅä˜o9°^‡ : u‘áíîÅüè17Öœ…>énÙàÕÙ¯„ñ— Ože¨I³<ò©Y¸mdxíÿAÄHòí ¢ uΕN•hÙBp"ø­O²#¿ÍaÙ@æ’%º‘V¢ÍõÈÌçPxßùpkÅÛ`<óƒ¾-w!%„ÆSµ„n´< Ÿœœåx UŒÇëëa2aI)N@"5nX–+3RG©ÐÜ3W¬J€7��8œq!Æ 7Ñ˺œéìºL?æ—| UlC¿ý(aÍ“‡Š¾zd¶ŠÔÀ°ÀAeÉr¿_ý,>á­ú ìUJ¿Ð>Ù{¶%;4L¬›ü_äÃõßB§_q¡¶q©=¨#ß _Ó=•0á}»Ûêy]Å)($ qò¦bÖºüæö¸ l”uAºŸViÿ–ôS‚0%òPê@jó0âxK|1f#Ý‹%Ú-ˆã=¡Ejå ŒÿŸ·„ð„ÆQÞÔê7ÚÎó’ŽnAR rÉ0uympQMd¶rí»ØWG}g-ÿãæçMN¸"·Š�`bÅèÌ$ /§PQÈ!é’dr3I§U<ë€U ™ÿ�X×_‡zbBÅ»Éd;€0¿6³bU‘U³±G$A–¬ÆÙ 8íÛ…µ.´±ç 9ªÞ[„Oób:NÐ)ä0(ë>³ªlV½0j©“ šon Ì]ÉæbE5'Iê*R¡§CcÇ.^öd2ÊñùsúÉ%--…ÉÁ Ñ \‡7µ«‘#£=P/˜{¸’t<üI.OqXd‘î¦9¢”¼¢fþHb÷ãÓ9ˆ™B³‰_�¢ïI)¦B{ë­Ì½Y�Urr~g;A;:µlµ2ÓUZV ¤ý 7¸6úñ!ØJU˽!ÐÀ[89Sñ”Ä7n¾ Æ™š&õç.µïß�ªÇ+ [£¾ež-)›ç91l&ñ ±5,+¡@ �@ŸXnGÿ™îkŽË�©¥‹úvcÞæ¡â¾qÃ�èHê,£]Ì"Ô'¶ËFà×½ï䎔’�[Hƒ¨Åý.>Ð+¥0XÓ­‘I¬Xš€³BŠ}yyÆfŽð]· ±y ]ܳ­õ’õé›=éGÇ]«ç¤)FMWØ«‚°{rN–,ΖRž3²^–:QÅz¸,šîzg¯C“¸Y…;Bä _ýtŽHp‰Â|¾4jš-Üz&='Gm Á[|nk„RÜÿ\Óó´*\æSƒa2ÐŽŒö­êXÆÌWîB–Ùt,ìÏúDw}{=gG|Æ4âfÄý…IŠ¢‹Ö¨VVë0!@éìœCâ‘CßËo}�Zþp4K» gUª®@[�±¤¸g×öî4 ¢ïLêb‚«ÑÆF|¡ >6UM†}åÈý³øHX[}EÙi : €(Óä±TšÉùàiÒ6JÙ�IC)ΆY]?�êÚn—kɹªÞ·èþSV߈‘aÒLí4…Ôˆ$£ÏÕšÓß“åFÍœµ#è ?eµ=D1º%ö�ýð@eFΩÕu¼*)¤�†œ?âÊ3tz¸9ù«êbkƒþœ…o­3ÊÊeTïu¬Æú>±€±Þ’+$(´ü€ð4±A›\5-dÊ`CÿýñÝL”^ˆÆÀNŠ|‘p¾‘¹Â/ÖJ�j¦¤—žÐ £ð@Þ½ïÉÓ_{ê&MôçêÄ�ަ¸)›·9N†4Eš@½ñœW85عWÏÍtn~lv¹é�·¼ýßí ¯s”«ÒC‰;¨Ð’ì6ð»–' +ÞWP¢å„dÅêÄù7Ä1t¦ÿ âzXÓlPft[‘¬œøñ9Xt9üêç’¬À+¢Óåuã ÷Ù1M÷¢µ{XZ{¿�[Ì�šµhÜ’q\‡]4ϪB “ÐPw6±È�Qá—(dσ­«ËšOä'ðCª¼šbŸZy(dìc� [Â6×8[q>PºMNâ€>BR9R?'ì©<,~21ìÛÛ‘åH’TзÛå™°z4üïEƒc!Þa<­…Ê~’–n?äÚ j× ¿¿ëV¿ûx2*ïBÑJùÍ6'g5,U„l�jéÈŸH2¾Í˜÷xZ¯¬�Ç~cåÈÎuœbû‹„ �­©:½t“íÎÿÇâñ8ÈÖ@¨»ÿF¯¯SÒ7›‚œpÿР¯�0I°½Ø�_˜×Âþp9Ïì7õS2%¼�ËíàråƒétYЭcf#Áê°ÚðGG†æDÊxwÔ}Ø ýÓèB f†i^š{²iÆníÓ@”‰ZMÖ—Ø62�ExÏXZž0�™Òš:¯ª—DØ3hƒÐeø2}™Ìöc•Q�‹Áñp¶d¨Iûr-£hÝ´#™–ÉÚöì£{|#õüc—ùÍ„ýwŸ²@ð^x”Ø'3Ú½I®§d½´dwW(´|ú%ûRÃæRd¶ŠåìI6~N'*‹½û]ñ‘³¾eõÌrcóºJ‰Uµ(d±¦{K6ŒOÚ”Zu�…B/ä­BPÜN4þ"°S°þ×î�–Iòϸš�šJÒ pj´c'ìæÃ¾«bìV¡‡á¸`‘¸Lt88ïßS bY"߆"¥H0½ö1×ÙËGÎî¦FúØû°‰î:‰Kâc¤Ü£`¼gF1¤®åÅMúLaa²•óé0ü¥�egmÄóG™[eƒº€ü¹ÿmºÕùx�&šf©¨2bhºƒ©Hq‹šÛU]‘K×úËåë¿Äœ¼W¾µh÷Î6í}Ï(Æ`6)¸aÛ.¶òJ·äw[s¢º#­×Nu~̓8çã� W %âšäËò=ïÍó|×i�Ý®¶^¶rç$U;™kµÖ(>MR#ˆ_e³µ>hzaX5_-�×ufã-´"¦§bã»Ú™›{®Ú~”Á%�_ýiëš}ó}™ST}Ë�¦ž+4vœA$—±7vÿUS¢„Q“/ï9�LdÀ8§;ìæ¤SC” …|ACvÁ‘3' „IbP9ÅÍ�}'Õ8I½óW®«¨„s}1 ÏÆmàÉ^¶bo(~¦v'Z7ž¦Þá÷Þ¢áCISSÀR„¸�yg‰_$Z¢±öK̸¿üOó}ϯdþå)¼ùÍhgIŽTÍÃùT³¶¶€Š]ñÞsš•d $¦Òýðv­ Òî3"Nx1²Ýž�±ÙGnY‘˜ëz!Ýv…Ùð5 3£K؈³§/Êúj¯v4¶™+èKʈ[‹íŒ~´Ã8ÌÍ‹éÚë¡×PØÐ ¿[VÍ ¥šXžâ tCòUqìå�¼ŽÙsøÉ)íBÊ ^6ždÝUë‘\™y¦¥¡‡D0á’œCÔ ä8¹ÔO�±bM.˜ŸbšÁX¡A‰»_¡’ÙöŸ‰¯6fçjΚöö��€ú_Ðð|J£dŸ© øÕEËu š¦gtfuø×M—tNiºÀr§ÅeR„h8E‡M¶C ¼ßÝ0EšÙ-½Üb¤ž¹Ù<¸r1þjÁküI€Ù—8ÏMm²‡Á0-•õMžj寲W×=+Ë#óûG,TQ.”ÖzÖ;ä…Ðå|xÞ«<Ö.WIIÿ;kV4\õ-l°ˆßH�|‘�\?qG۞Ŗ݀uJ,1©Û;ZÙOP'Ëà ¼ÞE$îD…øì+8äÜŒ q((ù(©Uõ‰-#‰ø›r+"–© ´çqw”€K|Sdzð=Ä’ø·ÿ¦’z¼ `œÔÚ2OΓˆ×—£ýZQÄ“ „0T ýØÀR¡�%óËL›ôèƒ,Ï�¸Rã5á{Ä+%¯ëÒ ¸ÆßRÂQ…È1õÁïúB¸»ó�qcÂç7E‡°ÁíØi3Z±¯°¢ÈêŸ3ŸEL!Dí²ToG, ­„] q™³mO¯›EÚ1ŸÕêB5¸Ø5²Ü‡óx“2º¥3LÝ €ê}äk–üšOD+$ª¤ÐIñÐ]’õuF¬'Ê”M.Õ�Iv‡±b¡u8%Ð ‰Èø{œæó,& ísÇüÃZ(®|Ö•m>æWOi Ê<úKäµÚ0~­Ë–r'Ýò FÕouüÂØ¢ÖgËç:“Tˆ« Ä¥}%<¢P¡G²Ð3"�Mt`Õm{¡dDÀNGÓàt„Þÿs0|ÐaN"ŽÁ: Èï²6GnýôÍÚm�jËF˜�€ªPÅx%Ñ �Ê-M¼&/3Ò™ÿw{Ô?öÅ}€z³ŽÇ¼øèL·1 Ä Y%%a …8jKè]>ËÓ°ArÓÞÛþðY`uýPÙÂEöF™�ô¾îùš�!PÖ×¾†¥buh� B`”5�= ·�4à&ñÆÿ¿ýë …]7û°œ�`O:�–OTNO%’5—ç¡Öì¨$%x”\¨:§�_ä|ƒ=8}0Ò›Á�Ùòã:Jø?ŽÎ?àH[îT#w¡}åh„]¾à··Ëp\¿˜²Ùb`Ež#)ªŸÂâž9ù9¼£Eš€'¢q¯3ˆ²ƒ…ŸÀ2—ßÑ©R²KãÊ)>?Cb¡?’ð¾NCà�–JÓ/î>&èr�êä^ÏOú<“%'ëM<� yÒÆHIËRÃü˜ˆjÇHO`–,ÐGRóqû“yÍ÷ é¥gMì„eÂàåŸÔF«iŸåHõDf,<5­;„gM%ìñ•¤™÷jôêÊ`黿}âí¤¦X�!$Ši¡IJ Æ £ê¦ãÇG/>Ö½;ÄóÛtË¥LúÕ˜‰é�×í©ÅÔ›º/ß T^žz¾+�š$/ƒß•~¤¥ç¾®%@xßqúæ·É· ?ZE‡Û²ñMI>ˆå4†¡í­ù`Ÿ·i”Çy'ÁçÁqþëKµÈôBfÚ´Çycä–ÝœÙf ?÷ÿ{?ðÄ®‡‡Àø�9½×Ô#Û¶ž€<‹Ïøø0ëø(F©|&ÜT šϰˆ·ÚpV)ÿ¸O�6wÇ‚ßoÜqÐÔ]è …I`m)“i„ÀÇ9tmpƒAMpÂÊPš»Ã’²FùA6™+;I�‚¾ˆ%kг¹ù5{ÝJ•)°íÊdz4¹/�KRæŒùÔETQ‘:Ò)J~ÿâ^Üèº}~¶ýQP$ó•r°<é;¯꼜N�d©Íd‚áþ�ž*L‹­Û“�dýz–Ð�dX¶:²`:éf(»“ØFc†Ÿý÷ä�ÐSr©òa<°„eÊ–¥p„ͱ•Z›Ù²mV—>éðöˆ )ü rVhšÈW÷œìzÒ:̨*µõ,äb§$Âõ¤ÆÉdŠÁßý O@‘ ì©î7ŠAS�1”Õð;f¢†0^+G ã#y‹<9jÕªá,F���yrÃYb<þ�¤ßœ:ì'€—„7C{´�²™:|zeÓñ)Š¿è’k|Õoóp6lsÙ™‚}@j‡ö¯D©]å·[í/„ !öf[�*Ìb:Yï9êé¢ ¸ëJ¶XßosHWp‘o�£ä-«Ã&¦dHCE¦û.è z=/Í–LüϽ,}/:ä]·–FUçl…[°u>nÑïâƒIöÔ²¢˜ Î’›bM(‡¨¸˜©ªãøÚ¾kg„ÆZ”˜ÿs\.ãܵ¿´ÌEq“½¬’Èì jë-Äýäu÷ý­¾Ò¿x 7ø/¯|•+ýRz22U ×êšqéÔØ( òQ÷ùÁGêPîãŸ-…‚k<¯¦g.zÖ(Úºˆ —=‡ÁyßÍ@Á¡™C&ö†-aí#Éwÿõþ­œôUä›T^�õ�wÖ‰ln÷÷" Gɽp*<›6…�Î-Æ`€S%˜�ä°4v=Ë‘ ›îy˜­Å¥ërÛøkÚej˜V±tÆÕŽ œP&ûÁ´(�Ë¡^í_§4Ëͱ–I�\Ú£Þ2~é[†3ÅÖŒ‰Ø…­Œ¬×²ÎúJ¿%b ¾ZŒ¤­§žpàŒ}�Œ½¢1˜Rd¯™¤ÕO¼vþÝ—¸îOÌ/†!hYÑ�I˜Ü�iØÔH$X«ô1ëO¤O(@®Ý È:Bo¤b!‘väÙmý+â(^Q¥çŠ�š¹k»’⸅=Ž:ƒ:ˆˆlîM~š™¨è�F õdFƒà¹Þq6då�¡¢-˜øN¢ïwHök4o2;Ù@ ¬cÓ˜oNØ¡w£ìs£–%}5}–~6¹E€œ³wçà(a„-Qaå+ú¦³) ÉJOÍÞï†7`9•"Ó¡¡È/°sÓa‡&¨ñ.Þ¬�¸*.¸7VÁJ9`“,vœ–²*x¡½†¥ÄIc;Qù¶“€Úû¡ôP‡x“9ø˜·¡×3K‰¾“:±~®E •;~ì›%VšëjBWî%*ùPü™P5;9QähúVEtŽk”ËoÂ; ñ£Û±zÚ–þh'[–_ø£t#G? Ñî,Æá•‚ áBèÑÙ$iŽ9=…[eŒ#Û‰ðÞwAZŒ 'ˆhåA•jïhÇã‘{#Wìߑ֘&!Y ¥ÅlÆÆæÖ9R6õÂù¢‘aÞ{£kÍ)Á—9 �Ú´-UÄì<*…îç>µÑ»´¾¢S[!^NÕ8�Hœ vÜ�§eñÂ~ÚŠfˆíÊÆfõJ» ¨–’„9SÿœyH°B·ó@êìg¹oñËFƒ˜P}yÓ‹ÃÔ%RbÉo� ‰ {zºÈ¬Ý>rM$¶~¡Ñù­¢qŽÿ)z}š1õ¯ ú¿Œ²¹óp+2çƒ /ó_¥tì*K#ÙxI…o´ì“@+¯ùj`ãÊ‚#½­n°¨¬A|ÿÐè0…=ò¹¨”îß÷cZIo…®Aëùø= ”VØnPï)óÐýkf!‡9+àAñ)»<[9ážD?I°ÂIþPZcEttRŒ/B0[âú?Õ,EÚç–_p­ï@éª^€Ù.Óâçš$t«v¨”}r"ìîÍmÛ²¿*VýÞü=?î@�åŒ à¨?'¤`•èÒ÷—í©#0r“ázS4´$4]¤5Èc�J#fT¸% ©D"ÞÎê§©#�I¶ =P-ÅÇN¹”ã#Mé§`*¨¡Ç}Ê0ãpiN)3l 5Ã!äOðBáåïëúYvo!t—Nƒ?=ÐÃL¦°Q¦÷±�,Ñ:'寤†€:%Ùø³ÿä˜V£íê�¾µûÝ;ïO?4�›ëü0}ƒå �2ÌõHí�¯l¼€ƒWö& Æ{‚3èì»vpú@#å;É|<êr(·º‘Ë¡ã\«  ¾ìãÒ¹¨Ê±”²ªp[Ü ð’í%§«MñÀH¤ÅH¿‚ô„K["gC³��Ž©”—fC÷gðî™rËWŠØþK¼ƒ v²¼±„|ß@Ÿ×SN¡¤Cª@Vûœëç^ŽÜ# ªL E>ôs Û&ÉríŽ_5Þì!*!ùFÐÇy7ô¬”Jɸ¾/]Jš÷N%¼"N\«L{\¯²€U>5�Å:@gìéî±ÂxæN©ÇÓ>í°SpDë ²?Ú?2ÀŸ2“¸b<ŒFRá²§` Ð$ÿÿì=Àg8±†04kÄ$Ìqðäs?=«sHÏ<æþI§PâFî9´rÅFæ‹tL³Ë8ß4IÈATÈ^½øÍF[qwÊ`I¢Çcch!΄$VN]ÍR—kAÍ•p줧QÉ�ˆ¸ãZc/ä®yê�½É¬ /åÍL´hq)Ͷ€+Ò,LãÒ^˜újéý�¡ê‚Bý¤ãì×Eº <ÖÔ>¦xz¨íYäD&“Ôgð½m³µÔ™Eå¢ «ëgÔí?®Ø“œ£‘óæàçhÑ–âjžò L-ä›Êë~Zèkz”˜?�Bª©ð®òš †�¶À-�µâ†¥�⢪ͤèFn²‰6Û–¤Žô£õàgï&˜�ñðfnŽvŽ‹Ìd?˜z­ˆÒ.ŽLnmñýÔ$ÛvÝÕ „‚Á @<�³÷ ›h5ìÛâ6|úê{î±áí)ƒ›¡ÙGÉ$ËšOÐ=­SR€ôCXOÕ$@· X]¦‚-»�?ÐoŒ—ÿƒÙ‘`Ut[Q9p´$Å9¹}U‘ËxÄvœÀŨ³bco"9m¶‘‡B{ T0Æ;ú_¿3A\a¡ÁSùz„X4«¨Ñôï2íÊ SH|&ኂ{›+×éjÕMÈ‹¡ÔXÉU! ‹$K'“ïã3÷ƒ—L©ªu¿õÔ¡qÓxÝNX§ýt@Í2a |†~Ù�Dü¯yý †÷^õO:dØF6æã;ù­\ ’Ä©•žÙyžQXq-¥£ÿ{;gúa—g ÷'øyѼî/œLAÀ|Ü‘ÙÁTO§­¿Fà6&DÌüuÞn=!º'ŒþÖÕh‘ÕyX\7…–\ñ=�ð5ú2T;apSê¶pŒ€M ¾ù2îy‡Ìމ=¯ÿ,‚pð’Ô#oÚýå—íä«íÏM'ÖYnÛX—Óz¾5vïå‚`”V[  )ƃ×cç¿úàl}»QÎYR§cm�°n‹!CsU0›°B§9ALϪ«^|(öK!4ï*e'õ%Ã^ŒÍ�‘/îžw÷¿Fj' 0Ö®®çwNî€ yÚ„²ÆœLtIé´XÝ;¹‚]%».ŒúÒyó{Û  Ö%‰S&•P¥£e_%I‘$é»´¾YNiÚOvŸRž5‚ªª|Þorìn�æ±ð ØJ=?׉ Ïi›ÚMå,‚ÇÎ��…? £ïåJÎÅ6šJä@þ Vµ0w¦ þ«éÙ�¾n¤y%áqàšg"í!Ž’‡ÇtÁ7x8·DÝØê»¤ÖbL/Dë¾y.* FD¹�…{ãkæ ;�(¶ŒT¶¥G2c£úVv*$ˆráÛþýnWLI®$‹°lø^[pUÒ¾+4hî�ôMæ5û+,Ö_ô¿<‰ÅacÆ(£òã„2÷Œër°@l)׿ØMÁÚißeP³!ÛjôÑ”C¸ÿY8OеÏq®„êßó—â'H™åàÊ­SzJPTÔš9¥[ÞUwëT â{x"+fôy6{zÚý?&­wæ¾·‰ÙÙ6(йÿ; ¾�:m…“W1€´Ð£ Ú¤E{ôÌJ‹éÌDPù§ ÉéÃ̱ÐTb.šúÃj Œ�:Ù¤úó�•–·çynuKÔ×q´ÛiÝF©Iƒ•p7ÞId#ýÂ,Eé/-ØìþêÉ4Íšû|¿Y�éºgÒ¤)úš)ŠÐš9(3=(n,ຎ.`+÷ž› ƒý5{Þ/›½p¯Ÿ´ž?ánÖ«.qNÆòáÛŠ…=²«˜ rj?_îg¸ü H¯ÀÕL¯³ZºwÑÕ¢†ˆ¬¥v$CÊ,Ð=,"†\zò‹ËF~¦)r­a¨I°V¹§ÔáC`æø—ä­éã]PqÈN»]ä#ìÿsÙc¯\4•/´ã5ÆÛ}+^¯z¶Q­ð)NŒÈ´?£�ëPRûkHòÁd¥é«ÍÄW“µßh;ms¸‚�Ïhºœý OŠí I‘ÝÂ(�¼*mU' ètÕ2)Ë®«ÁpÙ2¥uý¥JŸ£âáÙ �fíõW��FµSyϹy„ne¾E7msóæ¯Ì³BÁùÿ‰u;ÓÖn@=öÎ>¬âdˆ¢~œ'Ô’·T%s‘¡ Ѻ¨UÝ�J(ÀQ|‰èËK–²ùÛÏÃ÷W¤ä…�Òáæ€sÆœ§:0·—Ì? HQöÓzOæ¼aMùÚ̳§7ÕÞ6ŠØqŽ›ðFc˜ŒüïLݦ6|hhª†%ÛhhçÀ_å\ây¤3’ƶ……°Nâð‡¨¼…„]¡u×J‘?€ðÜ©ôg¡çÑx õ!…‘`�,A•�Âg·ß}]£oõÄf¿X¢YŒG¿ ÖýöˆDHÁ°´J¬ãƒÈ–1xòȸßA‘ºÖ,âùBÙ†š0É�ÁŸ"ŸEÀQ¶€�YYƒ}Ôc‡fݪǚY1¹äñþÿ‡)kŠëÖ$Cv‡u3¿‚² ‘µ±PcŸxª/ò¸8àg(t9CÐFn‚`UJ˜¨åwš#7“êÎ¥ò6‹7P‚&9½‡šþ-Äa}< ³Ô´5”:³ûHŲ øÕÝøÐèå¾Íî´σ¿ü¼HiÜÇgZ>Åã5ÓÜmŽÛ9¡°Ú¬ËÞ­šåµ¬þ6Æ‘[ĉW6Ù?v’©ULÄ$Å;2×dDŠ#¸´–¿ùÂͨ^gÜàlÒ.� P(³DK‘ÿ$u•ûïµ÷iÒidÝÚÿ„Ü!ÐóÆ"ÆC=Lªm{ûõÍÃÀ�?¬qH“3 <¥@±“{ì�Œ5ö/íŽ=×Ùw[è’–Š¦ðE ˜5(Ôöo �ò-#äbØ�×5lÉPr!~8�Ód#B˜œ„B¦F{>ÙbõK…¬­í°aM§Ý€]lnüTƒf*Jšæç S ±˜ÊBoÝä.ÎAË�@œŽ}A LžÔ„ðx enR²»ZopžÉǧö�µÎbµ£ –>3 ;"“9鯞'x-;»¦Àn½½Aê>Ñg»!±:½ñsÙv±ü; W£p¿:þØqÖ^�X‡�úùô·�kéÚ¨}FÚß“ˆ¦TÜô,Ÿ€àaz;Z÷yNÀLÉôm’‘3AmXÿ@:¢L¶š}(T¬‰çR»›uÍI<à«ì¨ê{¸ÊŠš«­6ýP¸-±vœ,ÞÍwžëûfá Bÿ €àtvŒ‡²I&ƒô …üÚyó«V·eÞKìPèæ¸H:Ä€ùÜ<\Mu–ëýCT´gY÷ñoƒ®n Ž:IYÂWNpÀò™@cØ~¬Ë¡=¤ØuztRÓÓ»"5¿:2ÛØ>+}þ÷« �RL0Õ¢¡ÂúÆà¿ÃÛ©û¤hÊ(àÌH  c€7yݼ&›îr1É\oB½×£µõih~U÷Ü?úˆ 'O{Z¤Ã#‰‰ª­Àkï¯X¸ƒ¯ ®ÂïèÚ¿lã— » žáäýßB8ÌÀ«´K̵SæšéÔq ¶Û°·}šÏøÄ‘YÌþä^\‰üŸ·Íp¡É˜úYD] `y‚[ŸÅ)WžÕš¡Yö±þ×~ɪÀ×ýú Ÿü€Zm~W©ÓrÎê¸ñFð_\Ö½è"[;œ¾=e¦‡mõ ØŽ¤ í–ÿ%”{¡í³˜¤DUå§fÑMu9j½â•ј­èe©¡®0ÐÆÒpêõlÝ#»\ÓÒmÕ]I?þJÛÀä>’�¿îŒÿ Ö_em 7a‚»oäºâHèÚ7IVÓô ùF Ž´,Z~![u…°Ü1ré(˜Rë8±ù«úÚkvAÉÙÈ›,ã–·HþÑ“?ýôltÀuƒé<ž©ƒ n¶Ý°1ü#Æ·a)¿{Ç–uÄ{÷�4˜öšGôäÜ9çóq:Â�"^cKSüÚKc¢W€º–k²3Ø‹%ƒ‘$¿‰ñ…+ïî÷ñˆ<Ö§Cñ¯g^‚o:ï{%iÙfU…ºp£affI" )ÀhÁrç)|kíÀË&zƉÎíØ@!@~¼Ü)ˆt³ÚEÁ*høþSàŸŽ2Öbq-‹£êŠ?J³=#,—uØü›ñ![ê@ÆÖƒúªÈ¥tí •I,/ü©µqÀ©Î 9¾Í·›†�ZTÕ«Ðs>° ;Ë äÉ«¨Ûiq+<{Ûa�ž/ï\ŧ‡Ö57×;¤£t9ÿÀ™ÍwÊ/]ÿÄ>CìÎ4ONÝU|Dídêòa^÷·ÖNˆx‰E4Nø†0�r{®J¥©Áýu¥xA\|K '0:¿ˆº¥Žóì¼F7ÝÝ–[i²’(<€ªLíÚ-©øx0ÿÆ4S9ÀR—¡pEO ¾‹3[êHt-ŸJ‡ÙZ憙�Œë„WÜ,³¿æÂ’ÃÊØ7ßÁCa4÷•ßJ·”ÓP¾õÜcˆ²e¹êõgâ: {ñÛ �‡î½?/t©ôîí’îÓˆŸ $æÄÛFã® iyVpVYzçÆA‘8Üí�€³ýh¨¢4æA¢ŽñäÉÞ³*òuo‡d]¦Ýæùñ4aÓUe]øž^KÈÏ“èI ‚z¹žßýw–¡êTV¥*Ý G˜k|7!×ï±ÑºÐt•èèQ:8UN×0UlìPç¶ç•߈›j? f¹î{ ±¼\Q¨ï 9¾V·‘¦?¨Še8¿-ºvª3TX¸/ÀjXr:!Xj¸jG•�¢ò<|Üí|wÉ.Íø„q–ª 3Ì7Ÿd\É>k“`óÍŸ_¯;§�x4׀Ź\ËM⢱¡ÿ–í•dßpn7ú–NFJBZ‹ßt¦þhÂ[ê)Ô› ÃæqýS`½8£3PÚ¡‰/§s?±­�û†-û \~i�]¨¦erœgòŸÄCÀazµGžþñ¤¨/÷tˆ¯�˜~’~úÞUó†¢IW”i" U¶=ˆßAF&:ãÛA¼¨ž Q{îÞZ¢w]pÁÚ×ë¢ã8@îýi™’˜!¢´ÕTâ O­Pe1ˆÕÆ 9UJa§2sœ™ÑRhp_OM°âšˆ ª!äùÀÛg”—]"wš?Ñy‰DÚåüa¡Ä%�¨@‚ÿÊ�žÊ²݋7þ IX ;ÐásÊ+ι¾$m—€k9#q±Ûÿÿc/çµUlÛÁš @�Ã(Bÿ¦IÞwEZ¯ž™•ÞPboÅ�p¯iêÌ?�ýΦo®œ’ögôÕaR¶¥%¨aGOñ|7ºI0--ýG¾½e©Qm†G$/Z¼®z+9ƒ¯tJ€�ÆÃban-ù#ä�ëœh˜øJ—G”دódS?ȪSø¦pcwFÐfûwù›ìÉuÙ÷Z¼–µ@œ@› 3Ôxdƒ®Ü{vûï£r¨ó8ç`Ì3‰b½göáÓŸœ"% h=Oÿr’÷•ÒM„Wìýä©ìÅÖuÐÙ8ö�n°= [Ý(—L\éE†«.­‡œ�$Ó‹…�_FûÄLRŸÅìåýkd—5}¸°$¯>‚噿'î¯ ÏýÙÿùÂî†äK3<4¶0ü-¥RT™åwW²˜‰½Hp©“/ÀÝÈÆ ï¡ÄýÐ}"?_y·z(´“Ê…)ÞÁÆ=!ô¿²ÏÈí¾ |¾€^ïÁPÚòÆzZÉ'9%e\‚V/¾¯“×+­ßÜ"`ý÷å½”z[ŠÓ[häÅŽÚ0–Ï1Vµͽyu­éVPX%´2l÷õ«Ià L—`¤c gcoÇeæ:tƒ3�9�Ann_ñWÁºü¿àâ—pyÙV† üÊböˆÈšTƒ¡VàªöÃPÌ»ñN%¢ +4ø�izúñÉ ·(Œ7´Öˆ²¨#ñwt…ŠU*\,1·\åŒJMEÑGéx}Â&'\ÝÝ™îtU:-çk ÈWb¢L�«·J¸®Äô›¯ 8ÇÁœ °oÖù ´\´Ÿ#–âbÌÉ☠RZr~[»{–±Ô/á¯Õµ ­ ­Y¾0_Ü)M�–ÆÌYŸr2 7¯0bTXH & ì:µûZ¾™J�$öÒ“îMŒRËwsë ߯°Nð1¥ \’ÁTÕ.Ÿ¬Ñ×gp^Âr¨r›°8Dí#Ùe*¶¹5ÄúÖAH±ÔýP›©ø=0Ðåh–˜ö†O¼Mw‚Æ ÀAZaM'ÇæÚý8…�ÇVÖgWpäì|-êÙi™ÑÈ›é¥öçÏIAÒ—²6²Z]—•}Vø®3u‰¿�M¯’ÈW }ÅM˜î>Áˆ<‚š~Bö¤Ök9™¡x”;ºÅ ™fñm3`M‡â÷·†åó–&\¡j"J:º.ÉòÙsÿéJj¶\Ë´¶Ýâ“f×O×4(Y�bN}ùy8QÚÑúº ®fq*�+NJâQ_ëäï'޽xeÚtW§_ö)¢ÉÞFÂ…Z´Ú§  E &‡þ駆,¨êjz=ÁòyµaJÍâ‹ÔòÊEŠ»Q€ç»|Yî#Œæ­Múãk³eðéW>­n«gD)ÛÇ'‘Ç"!ífQ.á4ü¤Ö ½¦dÕª’›» q™ìÄzµi³‚þžcÃV~JM´ '³>�¶§â‡Xy‡ÕZ´ä,}³AS�äE%2¸]V豪ZÛ³aƶFÆ%Ƕ£ˆ™ßn9Êt°Vcg”­s~Á lÀ- [ozþ[jW]O±9˸SØ ÇWpB¿ücY9‘üd¹€coWLžû}£t/£ß¿”¿WŒ•IÖ§H+�øù1²h€ê*Dñ6so>R4Bçxk´²l¹7è���÷›l€ö£€Ó–6°Jf(ª)tC+�àÎ7|ÙXƒãüºöôUW�{˜‡tæõ¿; D+ʪÇWÈpž§Ð϶�ŒøoÊfÍcÿí:kUGY ÚŠÒØŸ²…ùžÛËô˜Çw¤ y`µÏ¹±‰{ýoC).tÚ—É0Trr_MvËÆ™WC¶¿ÐòuÊ8"L–yC(J›V‡£jÞ�X!{h¤ïõó½Azö¶-Á*¬øÿ»U(yREpÄø�¾Ë0f¹H/óª† DTY™œ^0ygÆÞÍجä'S…Kß�N³öYÀ‹î&L§rù¬MMÈ"c VötX8ªò*äFÈ}ÒÅ¿v»ÂÝ}îmù'SñòWsÌl nÎéG8ƒá*AÀGSè\:¸¿úeힸ’ q…œ…˜ì8v�S}™£ yÁº=:»ïŠûËóôÙOèÉÙæ‰púª†tð`€'$Œ´9ýE‘œó8KƒÉ&ûá0#c.;tŸÿjGr“*U¬2uÒ¹ ¸†Œ…¯£ÕÌÇT œ�’dÐÃÐPÙ–`¯—‚Ì%wŠQuÈ·ÏNx‰C½­!Ûë7‹p†­ *ä ïñ§+N@òÙîy: ôÝ=÷G[‡À÷Œu€ƒµcGeœ* „#‹*š5I‡Ó»˜ji_‘ü‘IÆÛ¦‹àËDGJsçBÓžX·]§É¤ÂøÏÂyw‹ò-0¯YÚÆåÜB‹ä´)Ž^€ÓúGº“~—-̹kŸjß×+d&¹Nv-IƳhº¾âÓ¸ž7ßÈ®ŽW Í|0�ÀÊù%yzÓ[-ʨæHwîΓOíÛ”/Ö‰ÏGv™Öx~ÍVÂŒì9úÉkèœneªOÆEÀ ÓW깟5/giÈ'J -aÁT!BÜšõ6®a;L!K4úù4lŸ!ý¯L=½ø‰¸›8z¬,¡Ge©Üæbî£h`hü´]™²´°Õ2¿¢=ù ŰÕΙçëÀh+,ÞOffÊk¾ùs½Lqô†�µU:Ü+•ÿHÉ�Óò‚»¼…4T-g›ÀˆN](%ÝÂ6î’AŸ4ivÀt×âµK* , †§˜n•Y9Xéö{®J�èЙ&!÷2<-¡–dø˜ª!RMJ.u#-¦É×ÔþÀ ÙÀHK <˜Ñk¬a·eRŸÄÃ*ž§ÛN?Ž�Bÿ[ðÖb(�£³—éË °ìüÇg¢Áá-‰CRñx %ÝqÆU§¬NùO'ñÖ� Ô,bºVÙÙ‡¢@°Áæ–éú飅ťF{…l7Ûló{Ò¢Ù{A>ìi:ÿj�ÕÁ=CýÞ“œx¬7`ƒ¥Ä5ÞæÖa½Ê"™fe§èR.�ú#ŸþÌÔ8Ên”åŽ4?œ¢\?‡êö—¹š8šäb毈¶0Ü|aa‰^Â.àE”ž ûÇ�£Þü‡…š²s€ç9°tùt)�åýmD­þ —®Ut7 ¸ß–¸…êÀGšiØâ9'2±j�=ÓÔq¯ª¡®ÐÍ_»’ÙXjÑÙäÏm˜af¤H¢Fž¦ó¯&F´ÐÉNÂÞÉù¬¶¨f0+6°®–ã�Âä;ÖRª¥Dænµ’DM.…XÓäôƒ$74�›ïáÊ)ž�àÑ/» RÄJßé\d€ ÞQ¦/¥tüÊ�BgäŠ�ú”uí¥4¨§UòSRYFö�£A—»<Œ3e]Àh]l“º ˆ°ùÙŒ9 +ª·†ô£MéDì’„ø(Ð>Ôþ1;¿ÚpîØXïRFIþ$ÅκŒO™fÆ©0$¾“ÿs.]Û”¿\ÿÞÐÈõ‹Úùn±Î˜åÀù—nÝODqÎÕå4zÑ ì¡ó�ÿ¸Ý½i…åî æÆy_0ƒGrDÛ¡ܯ¤P|ZYgíî«önf‡Žwu ù)�Ê}§�Øô§eÿ›¨¦qÁ%Îÿÿ©0�s¢îö —¼j8N÷]ˆµƒ‹$€éÃËCpJG6®³"Ëöï.g²KP¹æòA©:cßj,Wtá©ë@ë�»ô{-î,ðÕ¼‡÷âcæè÷Á{´ãŸä qá~ÚˆÁ|Q»ââŸlS«–óJToDÛžKWi�n09~¥‹§@F,\°ûW½öl­t†°íg{Oµïå>¯.·?"eï?¾„µaù® Uü4‚T\ÚfåØÊ‡•áwÕF!R¯Ã“«”_ç„FŒÝ‚³ÀÑìd¸{Ø®ƒóÐI$P\-…ùÀT´*w§YÞy…òSx'ÈjÇÎ+þw9 sÍfLÛÈ5Sý’Y†^f¥¬sé7_{ÑEµÀ¹^yÜ$Æ/Œù£»�ö䎎´^]"õcô ¯[,³ÿ}õ¶)™,üÌ]š iº÷]¹-3~•�iÃÍ6âãþÛc]°O7&D[ÚCÛÜê:+i¶†¼ªý mµ6@¥çœXõYš‚sœ‰î?­O86¸XQ™8©çCµÈ si¤{2�iˆ¥TõÚ¦ý‡…xŒÞê ¿†þw²Ç`ÁPVÿ ô±Úÿ{§ ¨ÁŒˆàçú+‹”„÷ˆÌfùjCÍý×ê—GHòŠQ�9!ø‹(xO[ˆ<Ý�"7b,©ŽUvù.S‘AŸzd”TL#ÿðq d¾“j™o~N_þºÙxdñrØøLÄÍ�°K„ÏQdxŒÇ b'ûŒþ±zѵ‰Ÿ2ú ߘU«Í@¨…ˆ }‰FL{´ù�@>[½Ãò½‹>;²C&[ÏP™wîì¹cï^iTI“ÍfЀ"´I`,�ÇÜ\¸51+¸òÈǪ̀M“é| ¢åcîjÖPêHúƒþ¤…žR´B†HÊ´�›Öº �?q?€tK�˪”Ô§5?�ˆË‹æL ¿X½z“eä^¯ãh…JV®ñ€¿pœ[Ä}^rÞ)·ó³þÅÙuP˜ŒèÉ<ªŽ”óÁðíTa[½“KIbæµ[¯ðм…Ù¥) ÐóåíéšlGÇú€½³‰µ�ëQâ·½V±À¦¬{””ÕΗ�ÚxV ­±È¨ÈAd{ù®u.Biªv?¡£a¬¤`½œä„¶ë.ˆ‚�,�^·²ÑÏ�— ÆÕº“µ²:âæöJFŸ1t¦(j|ÚöMÈ2Zý¶gŒ#¨þ|ïTÝi[®bà4Q·�‡¿ö>ˆ¾÷qªª¸OÐ FùÈÉvô°tl q P믥غŽVX©#Z�^„g0L§ƒ]U,Döæð£l¡« ÏhåâÉX5"–ùˆ@2Ç߉�AùáÌbùWP9 Š.bÞ[Î &•H*gyÎNÍWHE–ˆ7Û†Gþˆ¥¬oàÔUlÀ(7@Ñô ùj"{kíP èäØô¿–±ílaŸ}45‹Lø™O�åóY>dÁ»UÏÏ(a�!o1WÖ¶¼>5µ,·´"RÁøD kó Q9 “ˆ‚õB–ï²ËkíçÂ�ëñ¿þ_‘@ëhý¸ò‘~™9TØ‘ð®ã¢´èf7n–>eÁ “ßû^^=â§yŒðÀ™•­ãt"½sx¿¢D^ùO“òµ>îl"Ð>œ”V~t+ˆHlk|�^¹(éC¾"w`Ø!»bíC èú”€ ʹûnž“|$-³þñR½\¥]Š@üÉ)”aQ’\ÈDãîS5–.‘`[HîÑMU+'bãqGÙ\•V½À¾¬•Ú4öi8G–¡#ð  Œ4}Œ¿¯÷¬}4òÂtcØ(‘½ºê�8ÀÊŠQ£äñQ/ î\Br†Ña‡ì47°æx¡P�V ;ÞÙZ p ¯üˆ©šX‘äý�¯ ä�’lÿ”�à­HÁ7§Båfe-ǘl¸Gø4QˆWa`Óñ®ÛI²úb¬ÄvF:rƒûóʲ9v®‘3-jŽM Ó„õ;£�ødFq{÷F9=øpÙ¡jGûòqqÊ&•3×Û¸ÆÈ ”°Ókw<éµß©ÖXâmrP8F¼‘‡ÿ:}ÿmƒ[×~ÃbR-6[-®r ½S±ÊQW[§€[@C·Ã%d@žLï\«•>àO"ñSOŸ½ÜAL|•º�Ô8¶yNÑ(~íÿÎ>9žµäÄ<”0[¸K‹åÒ¥î }E[ëm´V«°6É+Ì;Ue<Ìßn ¬oUŠæñL¿>Ãs 7]‘oʾڦXCD Ÿ›nGÿGøĵªf$ylp2¼_úídU²ð�ìÀa[H0þ•ÐkÒ)ݵ½Äd` … 6®k4ÌAÀo…œ%OVùºÖ÷¶2¢[FjeصWÃqhòåÚû¥i:%ØãÖ*pU{$¾aÁ*®Iý¸Az=òáÕÇëØ`@6¯™à¥¹¨pù³8Æ(p]ô…bSùE]9�éYTõÉ`mRhm#Šë6‚L𲀆�3ÎÄ;æ#k^$ÄëïðvÇj#ž¬.CòW§Âï–ò.v$š*oùV4ZMà Øè7(MȆ¯¡wËr ¢1nº§Î¦�çá—ukæ­„@jã( >‘w1aÇÑ�¦TgòYÆìjE)oÈõ=É›¼ t¤X÷X ò‘ºd"Å„¡ÂüzÃþÄ\i©IZ„+`å.zP©|«ÇšÌF_c‰JéOÝæýKáĽ'? iÕÆ;‡th5É´&ÕFìXÌŠWűؓd÷'†¼tSfÏSÌ·AØgà8�ˆÛ½©cCzþHqåšÉG¥Æ©}È·_~r&.ëÓØn¦cokyáÌe“Ûßö«iÖ¬/ß•tdm¹¸mœÒ9㔢kŽ ˜‚özÓíjKçÍY‘P½ú%©>1WÕi.…ÀÊ«úG{Ú‡ ,å®FÙÎ)Ì„:‚MÇ |˜_Rh:¿#tÞf´òüÍÚo¬"wÌ0�:4`ìÄ0¥@²µ ê`¬ÂR}P’î[�Žõ…Îì´Y&?]‚â¦X1Dä· ŽA›€5-©2˜ÿýñk$na6ö°ïû¤!õŠ€Ú¡ha g}x›-®9=–†]W+XòÈSÏ1”ç•UÆB¬cƒW@·ÀÑè @o_¼àyÒHÛÄ5Žv~̺�S&™äÌ£VæÜa°³ç¬~[u^oúy× Üq™b ¶éDt¹èG˜­çMU�¨ªhð�˜ÇP6 Nô;©/ùxn˜&L3IŸ`¼È4ìÔøsÆ:�ôöò ¹sì㎽àè«s¨ËXz6iÒ‡¥XÓ¹Sƒù¨{LWNPTÊÙÈ‹ñ ËtÙ­åæydy·«,�·«Gìòá.vŽ”.@ÂR�üö¨…-ž? åL£Í€kAד™�ÞáIš* Lüs…ŸR¶QsÓjû©uàœ:¬æ¤«ÅòŠª±öŒ˜5½góÖ! äddl8“E=$m¡�ç–ßT´ø©ÚÄ8Ê~lƳ‚ý–ÆTü¬üGC÷/û…¸ø�²hgÆôÕfUnSöÎ3—HLÛ\ÓÓ[~±<-Á�’4ü¶:§ŸÙ”\ª—sSŸÜ 0™àF›$±`HŒPû&˜ @­øðƒØ¤ûw;ÄJÞÜuü y:gº©¢,ŠÌ'õ—#2,P?�vû½z^gÒ1³¥üuðV¶F¬±ízž ÆC¹µé‚ *­¸õv(•†-õ1lBß,éZkùáÜ•Šþ>r>+3 %­>"½&Q«32,ëi\¨ŒæÆåE Ç—#NÈ@š €åQFªÉ1Ÿ  ½XÁS³rRc½ÆÚâ3u�Y;ÐÉúÕ;l"ØCíJå?§·3iâeE ¼ðP¬ÈØ’e\Òwä•YD¼'MMËvÞ-ë?ÖGyàï${fÙ¼²ixµn7TbsqègÔt\ƒ­ÔSÿ¯)ˆó{?ÿ=†&.E'@P1–AoÆií[ÏKaŸVËXÏ { ÿܺY ÎÞW/Ô¨¨êYcÎájºJáX£Ñãk'×í:ëR[µ…íBÚäA¾:<_†Ü.�õYçãO­õÅÔ½­"e$È=ñþEÿ¤ Ÿ_ÃXÊ«d~�áª?—jbà¾o(h–�fœ-74@Áû@«@c÷4Ñ%-üïŸ ©&VD]™:ÏåDz�Ãfó¥ýÍ-ÇR ®_áß³oý˜õF �fܪòÔO£°iråD˼ô!“çÊq’Ðp^ó¤î²h€*~¡-(ˆaQ©oxxƒöÙƒÜj »'÷^Á[„EE¯èˆ-™±1¿ÍY‰ée3+J¾Hr` ·/ŒÆç(;€ CªqÆ£ ïÉÜú‰M ¬TÖ€†ÐK9©‹.¹\¿*þE:£–Iáwê©Ç>ŠK¨;E¿0’õWy¡©jR¢Sk£v2ëÈ”XEàõ¿îé�à+”H¡4j‹¯\e;Ù¸#â9JÓ›.xuÅFò¸D Sª/Ñœo0©�M7/ß8žT_Ó/ œ­x©ÝùO¢ºÚ¸[9¸o_5I’§¸&c¨8˜ñŒPÞŽ†L”Fg%ˆ5Íh«tµØKtéŠBïPÙÞÆ ÷øRC@Kÿ)Ú“?¬Ñ�ä�R"Ú¥`À]°Òq½—L9Ûïnò>\Ÿ&QTÖÚ�áØ]Ÿ�p¡—€Þ]�n q[ ˜Ð»ý| #qZÿ|`Ü€¥I_2‚J7‘ìµ^â|>Þ¨@³i°±ÄȰ##¨ì­DÌtpQ^XÛVÁªÚvµ{3H;•1Mÿÿ[P•ššl;Œí‚ÕÕ÷bõ�´C³3ÚÃy«4ÄcÔ«n1‹atÛãN�Íç‘øúT9èéžÌHàŸ¬ÿJ¾M.¸Sg ;bº2ûf'z·‰;ï>Ba¦b©²K˜iÕ€÷rHxæ¦#·ä¡5ñø«lE8²áÖw!�Äâú9ãE°8ÃÛ?¿¹%²‡š¹ÆY!7Uñ$“0ý?‡ÙÖ¯"­?O-Ý~¢"9Fô\{+à0èýìm:f9ê+è–y¤¾Ãò,cÝ–S L >®ÙäÒ>M̘tùí÷½G§¢=›2³Ö¿%“·s{½r%XL„9Ò*Yâ7hêE_Äo$ÓQË1ù�1gêVÞ\˜`s;%x}˜éyöžpªâÄ6ò‘¡¿æôLxk{ Vÿkuû;ËÐ�}åÉØöj�Ñêžk¶¸Í¯ú�fŒæáEo<:'WøÇ«Íò~¹Â¸Öô^�d⯘ªð }Ú| EgÑŠŒ�ó­è�…ÈUjÌÚŒ-ÆÈ»iqêyõú�t J–^N¼ò)ì ·•U�£–\ÐÑ¿ÜÄHhb¸ŽÇ€ñ¨$[C\€é¿SÈ«?En¡ ·ÆYêlƒL} ůíž'Ù¨$ë6]qTðÕ«"&¬ZÿSôì h@9dÐ`çðõà Æg[ìsrsƒ.#¨Y~dÁ÷;Ö$C5B~ ¨ÇúÂK %ÆT“)[ïj“t´ïZ�â ¬Á ??¢{Ø%ÔÆ‹ÎPË>°<àKÔMG•v}"ˆ(r ÝV6¾ßzK‚.¢ÿhÃÝ�[Ü×ʼnÞÔ� ½DÙ #ñ@j½uÑD¼�†®Ú� 7µ;ÿRYë/Ç*—ÿ¯08£nÉܼʔV°¸Ÿ„Q×!Sëí¾E� ‹Aó˜ºqÀ1'ÒT.ð.Û)ÕØÁ0a„§ vÚ•@pYŸÝiÿ®ö¶6ºò¸ÓVÜ Ù -]f¯1ò�8%�‰+F?€Ã¬—´—Ùøò¥4»UoSnúŒ)?6¾� ð¡Ò°t)¼ñ(g a“ÞwÃL¨où)y.Fe?ÃOi´æç#*ò#ÎVVr™±�Åö·Ð¬?íšcóËÅ‚Ž3Êû¯ý£ö¸¶ÇðzÓ6×>/ß‹qaÁ‰ÍŠrþ]Öþ¸rwFÒ<�Œ Ó‹PNšèTjO*ìM(k±‡×XÈgä@¡J^0o’ös?vnµöKÌ®Sš)LÆ¢óÏ™Ëöç¹d Ný4O÷ÔÌÈwQi¤ð¾·Z(—?àP5ú‹ÌnžDü†$üøÓã}sÿ c…÷‡SËÔ]õuaq– Eë«eO2ÿmÇ»ô¤Ã[ÔËÿl&p#:"˜7Rîð3«u–`q„°Ç:šMYƒ‡ ½Àz•† ‰>|Êú®ã�þ˜>µdþ Gu½Aõõ­r°òbÓƒÞØNļ™”�3hùCD½äê/X­¯Æ*`†RãiMÞ^¬EzdÚQÕÐÂ0’ÆêIjf¯FÖ�vcë3 7¡þ?ý¼¹€š�¢Sø@$UsM¦®~ÖÁWgÌxäŸï{ÉÊñ>­î]Ä ÒÏlÃÿ~—º�•Úâí½Ø%ž6òCk¢æºB ï N6Yæq%áÐÕ1ƒKìéZs„”ü�ò]) ˜Jªº ½óÅ\ÖäȶD^Dh©É¸vVZÝg"§@F�‚x“FŲQŠ‹JX™hÅÃgLáÁ©`‰;s/¦9Óù³˜Õž¢šð%=A�œ÷Ôæ®,-ìè�½í6c:Çv4�ö˜LéÜVïÙ˜~`­;ƒÔÙ@»]¢÷ØR­„’C™ä¯¨-¥H÷ÿ ¼ŽX4…¥Kê|¦é¸³Q»úÇÇL~Ë-Ö»~³œG ˆ^7Çþ9AÊ¢GKJ¾'=ë\+iaÁ ÈÚ™^ØÎÂ*©ðêć�Wóc‡+ãÚ<„Ò‡ÍÓ›­Od?|ÅsÜÏ+•3¼Úâ-�¸„z˜ rtNžH«ËHãJº�"­A™ÔhJ_õ´vìÜxÖ1¸”â¶«í1ò¾¸óFü™dÔo÷ ·€D“/e^}þ. ø!G·¢ ÚA�RT²àÜœ·ÆH2ný)pÜ�Ï¿µñý;“$ÍpuÅ•sg½ U¿)±ï†slŒ‰ ÞéàÔ+Å�U?¤< “ü™8šIFl�OMÏÇvvM>‘A\8C¶Ù¡aæ Á›5Wâùæ.ŸÍ" Ÿ{Ï*­[¦Ý9üdQTä6ÅSÃöþÖäÙS8IÁ ô Uš«Šßd›2÷£ÒY€_&ìì’`‚Ÿ%?kãT•Í^f5Ù!fV*WCŒî …¡›%â׸j¡Ä(Ž‚½ HPçÎÆðT>¯„ÌF“œK¶éѧa�³)’VdMØH¿s´Zv<`8Ÿ{8Wå÷)ðJìŒÎ 4©ˆ†×…K³Ì)HßRø1¨íÊ/äh7„8ŸOà ;F×Ô½–;ƒá`²¡lÊ »¸¢ ‚õ¥f×XÍðµðNÑNsàÖäÞ¾ §ÝlÁ‹ã[&´“Ûrn#'BÇ–øTa¶Ò9ƒ_h1öq»KÃ×ã„ëLs1ôŠÇìc�ÞsÂ�Íž®Hç>&IF3ù•ñï;Ø ²"ð‹±¤›…ÚN�äV‘ÌÊÄ-ªe€È08«ŸßnGÿ™îk¼EI”Ö†·pâÝí ¡ FŒ]r t ç³ðF¾Zz?­Á‹¯1bÕ�|%†Ü4õ“èw=„+„ JÁÐ¥àštå ¬ãi• ãÿ%/%ÈÂ,§ïøiíÂÆ™�/>¥¾Û•6¬ãª2RÔ‡Û‚1úÚò(àS<¯ºÿÚ?nœG—ü˜AO…oÒL†lbÇ–nÙy>–ÓY}çDîA»¡ŽE2.æÌ‰Uâ²shó6“AôºyÇÀä–™È�$�ØÅ½Î}‰Íœ*{‡Ý€¡xx±N'!&¼ÁcÝâZ\óærý¹ý^›胊2õzZmÁ\Pa$4hÍN0ýÞ�á-ùÝŒJi ·ßàwÈüi~ZáYo÷Úæ|p¨¾\ ¯²‘Hƒ\ðƲåìycRr¿õMN4å5ÿéHߥøƒ6mDs;cÜ1é¼ùëzƒVÊ “x¨ÿzß�¦û¥x¶Ë¯K�ÚíÎ9ù?ì“e ÿÅî}¯U�õÊÄš}ü­DÏQŒG%¦DŸó@ÜhËoø¯×ÈV¿6ϯ XR9ƒ¯©£…À$0QªÃD$ vèàØ‡÷õÖïÊrЪ\³�¨Û½|Ž}™¬\Ÿ`”¿e:ï:´ÕÄ8Ä–6�ñ”ÜÅL·Ðà5ÕS¸Ò|l” €ˆViçBÌÒy\Â4íÏÞwÿíÌ(¢›ÃsJý´mù„ª¥7¾ÂÙ×b“ªý‡œìÊF]Çž.¸PˆŒŠœôÊšúÇšÝw©ÉÃ3Ò³ég6ruv‡¾£‚v—E?؈[d°cê&Ãè½°-å1;�Ù³„7™þvW��¾»ä@sÕDtEÅÓÂX©¹R•”OGÐl±j±P¨ÆÁ®£ô‡ו�÷mŽ® �Ý #a¡~|¥½Fœ7õxT¦‡æíkhit¤h›î'JZÞÏþ�Ìžì•%%<•ºÉýëeÀjºÕ~g!$ų¿ƒ]ÿCòþ[®úmŸQ<ãnÒû<—²v{¼£ùïpT K Ó(†£y=¶©r¸ˆš½8É)X [ß$¹H}·C¨ˆº³ãu"ˆ`î´Ë™½Óô*¾WV…ÍÑe½T�˜à¾BÒvÜhö ]Ð×rM„B|k >Ù ½(äS±Î™£–ÀOÖÌ’URѨãg¥]¡) ^àÕthŠ×~ay½i"¨F�Ms—~‡BYI~~)s‚šqPÁܧÉÕÁ XXƺ/H1z§ÇZæ9»&C´Ú ›™âòJAØ^ù�6Îq׫g¤âÍfJƒëõ]QS h0˜uP8A÷Yn[UÕˆÒ0]JYº\‡„yl˜"?ô;2J>ó0!éI¦XUç©+o&–t"æÇ3åùô�0Áêú `Vy’޲wøgÐú¯jÉ7²}ÍèðvGP Ù—G‡ë! (¢¿N]oòÝ"kahʱ}ãC¥1̳ÖIÿU7ᶃ]^eg|”n9üc)³š"Óü†-ÄùÁ ÀæÂºI˜ßF- ûݺ´£�‹Ü‘ò/Ìj8>3;9®F¹‹CÉU­QˆÞg¼Œïfx_Dm•ím¤B ¿×ûMk�&…F–,¦þy'1X€Y;êìfŽL9ÇÍøiU/“´³Òüuë©Ã�ã¯LHlÿ}«WÚÝr½È�ap')­fK d+ÿï¢1�Poh}õí#ëcèñ¢G&Ž ìm‚irçDÔtåµs¡w»?æ:óV”ëëœmXÔ ¬ÔÌφ™JËÈ<½hÖŠˆçZ~B�H…ß!ïÚ?!¡Üfu³/ƪ ùB“èú3ƶú3¾rõ÷ë¦ã�þ<¬ú¢t¢Ðr"çOM·TnPÑ6 Ø'Vê°.âÕ1*ƒÍ’ /ç[ÌÇ*ï`ï¼éâ›# ¼K»î¦DW혥¨y-žtJvàÀ÷3Ù[ßx!˜éX° !Rªš¸‹A‡W_0>â8Ò—ü”e}ü®Ä‚K¸Õ1ÐHgFÀÂï® y�Ã{2dùQc€qôÍ`1w§­ìäüɺõœ®‹j8éA¸Œ—‰ÔòàSåX©Œ¿tR§^�lôúƒn‡ åZ¿Á‰ò““]š°; zJÇtØIóµe9Ñ(™Žíп(lÊ–@ÙÎ6'åÎ\E¶]-3C><[|_ïWùóñ4àƒJ¶�¸�®× &ÐÙž½²º‘iÔDÄg&Ó׿¬4¡¹XaöîÕÑÎÜôÅP‘¡¦LEd€¾ìôSå;ß١ʹãÁ`ÕÁ&n,š@mI^Û0\ s2ÿ±Â¸Öö U˃“zîÛÑzy%¿²�Ìo-´RцÛô c'8µ!WU•Åy+Ó‘ª�dï�Cv®«þói¢ wŸô"1H³Š—ÍE»-A|?Ê‹ëØðïÕ¿qÄ\ã– BmXñ¥«�páÍÈuk<0“l(å¥Î¾®d:n�Y?èßbŸÝl«Eô£»¼ßlLå4”­i*ospó ÎE~—÷äR4Üî–PtR2_z“QRJ PEiµtÊ ‰“~ƒÕØ~w@[VÜóºpi×UOd–KnKKÇ\Reaï7 E|0�Á¡T`}&D¼â¶È�;>6ëÇü8gˆŸ(ã˦X#cÝŸ·Hl’ËXcw;¾®Üú �kË~!~ ºú–”4á¾cOð–ò-¸¿ùÙ\¢VdžnEY×>â nÔµÚ‚ê%AmcÇÃæ#†ª‚Ë󷈫;¯¯BU×Ö¸Ëä»z6p/] ôµ#�}j0zw Å5 aìç’^K‰Ý´åD¼×ˆøx¶ÿöñA?úqðØ1Ô2öÇŸùÛÐþŽÖÔ‹é¥Þ�ä: ŽÿñÎ>˶˜†.µŠ0†%Wx¶_`�CzÇ] =—(¿!ýxCÔ~z)œh`¯pYÚÄlwPqtÙØÛÃåà (“[ÈyW�ƒ(ŒÅþ;¬`ÔoŽ7šX·æ G"ÙÛr9ät@Û·5e“Sƒ„7@VRÃ"\ÎO|B§<+-Ý­bã1¨èæÐÆÙH$c�Å­Þ³«:ðû…½í;—BZÛZ»}K„à~Ü0ÓÖ¼ÁÐvMÄ£'bD™è÷µ!š]šîò!ON¸0]�D=c¬ÙC q»r=^úº‘¦KEèël˜²šÉµ©É[i%Ú3*<ß)·ì‹ÄýÑ=óc›¥ „¯±e¯ÿJÏóáûíÊ`á/C©~¨L´Žp‡ns*Ï1+SƒѰ‰ÑËÍÓ)üàUV½Ô3ݒ˰ÆèÝz`Šžô0ÆCGàODžz+[¤·©×>iÙ{Sš@›œ%Ú,Q¯\ìXáM"á®}H@áa¹e�9 Gš]ïKHÙy­’7z¨Ø¡?ê\ÖSóæÿd‘ÀT¶i*æI\j1?}àŠ[ž Õ¬n½ù)UÝ-ØW,Fn§ÞáñÔÑ P`¡³¹r]Á8k–Àõ ªü%úJûœ—:Âl9>ö .¥t�æÏýn;UG÷#Æ\ܯGó2<„åݙȫ*ݯvù$ªÒ]pE�sxª1š©éÜQ½74çÈíÿö<÷·!½•,³ ¬aTk.\ËH®bn­ϧ¿0TÖXéäöBTåÝ%eUJð—‡Ö»^�-´=d×q 9£�ãUŒ�NOüg:¶Ã¸ä2*I†¡Ëç,𥿚T¶‹=†y¤ï)žÞ£D«RAËZq¸ ðÈóÃH†‘cœa6!æ2ä³ç¸€¾5•’‰"js½Á#ÿ¼ö^¾×ª“eô/Jb Ïpuù‹¦'¢‰Jóá÷A>y ¼ù‹Át­á=Úl¶S1„[¡I/Ö�ÿØyÔî4@Õ;¡Æ§83ì}T·d‰1Ì çs-å-ëpŒ—Æ¡{kÆp8Eó‡ÏÊÖ‚Yc f3Ñ:}sê-š·Ç¤‹«s{»�T×iò—)&;¶u¸8>Ñ-´4É#ì„.ÆmÇ´–³õ@FîÏ“Ãq*$“ߨ-O]·6ÚÿsÄ3¦f%gwqö'ð1š=.áfõ5LBЬ’пk!]~|ŒôŒ'áN'3sZÚ«`âÁWj>ÖA9³‘ø‡.ÿo.¶'g@Õîi�ÝÅu Tà_‘â‰Â²cÙR¶|�X‘ÕˆˆÒ85­��¤�ü(Xýßz2ºyk �>Þ3Ì-ó}¾7޽W}¦›Ç£:Š^Ø{W0´ ¨lúóƒïš¼‘ÁBP "a€ñ±¯Èà`Þ Z ›‘‡;“)wö§î"/Ô¡r3 ±áC*†­?·Qý|¥Tl«é²[˜äšÎ¼ˆ¼1´}yn‘Uõ©¤Ø‡ò_K·à«(1pXª¾{¾�Œ‡°ïËÄ2?2#)xœ3q™Z^CмÅêÂPŸµÿS÷¶5-þ‹Ç&{«ˆ³ÊÁ™[¶¦ç1KF.:.qf‰K â£ßöf|]D1×)ÿ™U]ˆ­ç­³[äG\q…i@|i䵞µ6�çw>d}À}doˆºò˜Ì΀Æ1~ÞTÝ“¹”q­daoÅ¢‚Te “Ã|½"aåP‡9ÑóMºøÉÆ´Zïë°”r?�á¦FÝD” +'rè:p(‡Ôÿüä%ƒ´­®ú*z ÅìÚ¹^ZýÏ:ô®´U�3´Û¢IFº m<�sÚlgº�‘Eò=ŒÜf%o¨þp8;0¯‰Qã™m¨`gðE~YõKÈš)=sï>ðo÷°ì@ *=‹mJƒûPÖÀ*Qâq9 ž@Ät qñI¢d�,îÚYu°­öhÖàQ?êŤP8¸é-ÒÜH4†ƒ5(~©©Mï;À,²ÊoÙÆÉW"ç烒å"ðÙéܳ¥ýö±pµ5…É›rŽeOêäBÏk3ÄæÇŠxµSÑ[к„€û¿PI’÷KO@`×[šÀÚVžŠT”^D´ßÁÉJ »ØóQ8mqŸtÌÇ‹þ†pSµ7|{…Q&™Þs?|*]-zû¬Ä‚Ìúo¯îììG}ÝAs Ý’[ñR{ÞÆü`ð¾ýóàۘ暼Âú·©ÝÎd§¢È°(É—³nÓ07ÞÐssnu&¦8Y« ŠŒFŸú->¨!h5úd7lùÿ7,Æ,gK¼�°æ,­¾¬Ì¦Ø2=j;Ù¢+#ÿË%ÃpfáÖçO?\$ü°‡%×#ÿM� ™öÁ$ü¢ž �û–öOôƒ ‚ ¨ö*'©D^륋ׇ/PŸÂe@Â\ÊIU�x™z”ÃT‹}ư�¸Ë¶Y3Š nQÉTæÆol¶�™“gÛ†9Ÿu½¬ëÿ·ÞGœg'ñb¡É•wÍË™gW)Ko¸‘8\¸Ø²Ûœi@3v •%³‰øðÓažOÎ?®[0;¤“‘…ê:49ØþUq¤ÖÊâåÌßJÕj\¤ë‹9gØö…Ãy+0g ÑÕÕ[ãÓïJµ?vóíÞ"ØÈ‡,„ÎÚ©‡], ºyPŸ-ÄFrÚ<ãñclh\‘ê%òžs|•3îeñÃEóœFå(²»¥Ð:þk@\xia4VI¹ú  Øã³ÿËö”�ÐÊ–>BýV�H!*ÛĶ/¡r±Úñ´M·Ï0då¥(:­s4€[9åÇ0Ý´Þ7뇪>B%éÃ5:%¥š�ûÉï–øL4Z… pÚÞ‡Q·å4’8‰¤£»ŠôylýS»õsŸ!°Ò€'Hký\¦ñšNÅf�;Rmò?KD±ÅÆ7,>«ÞÒÇÈ>”> ©Œ¸³Ê£�:³+ÿ °Z¯±l.…÷& ô�ŽPŽT¬áŒ€±rb6ÿ2󶮀Ûgh .ø®Øb†î"]YB¯ªO4[ç5±"ïÿÂýÙ3KóRëy©Å‹Vì [ýäW¨c*0¢¯`’nIrŽ ~NK/I õu€¾?Yb#çO¿ôÅdd$Tצp¼äÓàÜ `\I( –‹úðÛ ˜«‡ŸüåWCøm”­›«”94ü É�Áöà¶ÙI-‹5_3{ýb2R„ŒF?uþVH¯8s¦Z\&y{„YZk(]cƒ¿¥®èþ7•L|L‘{lW¯™¾sH4ø,37J–ëF¶âÿW •›eè[·”�<½ a´ñ4›I+4kzëpð[WIc¶õ¼5¨Î¾(U4,º�â6‹�f1Y‰`5lÒZ¹584¦6=åËLSµ`xAà‚ºlÃàüf_§2 ?ûtÂ>­©ß¡óƒ~žàiˆ ªƒj×M“ é÷G[ùdÓN´ô"»(ŠL×Ãx¥äú[VWÑ”r×ÿày8æu¸•Ýé¯ejIC„^3à³´× @Lw Ÿå¢Geâ¢ax­ƒ{ê?XïÙ2!²©ijÎÙ·({Ñ¿-ÝêÚåoñŸjRƒ éeZŒ ¶™SÔ�©IªøM9²ËAqí–àÝ/øÏX„ÖL� %ýŠìÄÙž¶ g¼ê|›7 …P}ïMr™¨¨Öš¡#Œ[/¸8[«S‚<}7a¸À“þ=s#”¤QÓ¾’ȱ;[–3Z;�dº«—¿%¶�r~?Q¿­ó,XØý«KEj›/}æãuÖûk,•in’.‹–ÁÞˆRñ\(bÏQ�Ë¢6Ù ó °e´#¤Ã ú@P5{M KA"»â6¹Zk°r‰‹OJ‹—V�ŸLø³……]8uó‡ÇæØ ô1hëÓáXEÇ'µ¬¯Ÿ-YDI¿<Ë€õÅÙ{ʺm¢ï�„õ(²3"¦?fÃÚƒ€¯‘ñ”¨AKRfn-ËêþêEPûŸ8^leé^©<ƺÞ)B ¡”‘ :H±´³«ÔùÀéc/ê§Jt¼�ÒÃþ‰ú‹d4j¯êÅÁEþ/†yÂCìn'ìi/J^‰åš±Ì9ˆsË}�š@á…7j¹G'—¥Ýb6ô�šáeÈ"ÁYEµ¢™–èŒ×¥M÷±\é³vˆ·õ®³Ã‘NžœíZ¥îñëÉ+WŠž 5 B"ª{UK±Måq⟞zx±FÎÿ—Š=yñ·ÿ^s³´b�iÆaI)-ïÑožy, ^jÔìÌ‹#¢ž×ñ’¼EoþÄÇoƒ?µ—ÇXFÌA6‰ð¾Ïê¤ý/#ר;âÑ3±²õ^OÒŃü´ëõ7 ý€…~$M0ªZ�vzíÔ½¡ªÇ•d<ž’Ò³ÊG‘s’éѺw÷jäÓM#þûJ{£á¥ó8 ìj€ú�t HZŸ¤®ëâìG áfÆEŒT!¹ÒGyàÇŠŸ!@ÄZúK#ù¼ÊÎMé–ÑK�E¤ -kGåAÍÁЭuuu�‰¨ÙW@V K�LÝ¥ó\¥gUì[Î¥éÁw©1TŒŽ™·!æŨ€è·e`µ¬3”JÜ€Íí|Ó7õ±ª¼ÿSלì'íce˜ä\³/€Ÿÿ&íe$ò~¿á¾ƒ€°:è9†d- q[…iº.§‰Ÿ¹Œþ'™-xj‡è�~@»IâúŒ§w®b…b÷é!�K{1ô3k¿Ç-xÁíÞ$¨ê/4”jô¿f¢¯ÿ1T±Æ<*â`É÷ ´˜õºñŒÄ 쪩/—ÿ™6�o=OÉKQÙ�é‹%ÎOǾ½ì Ò+0-ÔM›q"öC§= óèþ×Ö¸Ÿu2Ús ¼Íÿ´d?CÎ8Aßš${™mETû%êxƒ-€—3g¥cåIp˜Ië„ÀºîY…êÝ/ë‡}u¯ºÖ£õ2Ãè‹ ÒXÀ‘²G²¼0›á_ÒþléÿYmžsBç/'=Ûd±VÅŠ3ëãFz!`D^[ „R;E)¦¦Î~Ý­Oéð,HbæÄQ§G^¨.œØ´mkÀó’ºP¼»óÙ»ÎWl×㫟,NÁŽÁÞÌ ã! "|1æ¹n¹~Ó>E¥t(CN»|‘�³w ØNÆ«¸.Š"]‰þžbëöj3œø�¦5¶·¨«z{Œ—‘F.”A'1>ïͲåÓ»ÌT¨ìÕÊ /ì„ÞB‚Ôãå�˜^’Ð"{i¢:±0BúFTc$¼ žæ¯o8”¯_e2µ³ÛíU¹sÀO#KKvÁÆ©�vÞ¨‘~Ñ3A"| !CO³¾ FèG›m¦÷G}´ùïhO�¿úÀP)ïñú:_NUXÈò,oNMc6™—¸¥­G j9‡šc‚»lù€$°[ûìgƒk¬‘`ãaí-x>–þŽ`ž„.ýÙïs“�E ˜¸+t^ UOÑÛé¯.<²Ûøgo 'Z9ÆØ'o:-‡7ЇjC/ŽBùöî:Ä[YÉ ™�…š~û¡Mç\òÝ´â‰ôqÌcˆÄ}+�‹Öè�…âQXYûÕ£`8¡qQën‡y"óÄK°wI†Ìã Ì�?ˆ$kÛ�S‘•¢þø¨“«¸ xÁÏcvf(€m,;sð[÷vÆàðéñ#A®ÃŽPúÎÒñóƒmÝ`¦òy¸ ™ÃtHªžkøÀÅ›Õ�‹�¹p-*û�\ =‘ ¤#o¸\Tj0N¿Pw(4˜ØuüÂü¬Ò!"¢_ÎV�ÿúzãÄQ®Çã1ºMÈ¢‚óФbì¨ÅlB¿«Í/xMò'Ïê§�Ú<6w�d×”àCT˜øö¼ÑŸÿû‰yçÀ¾$Æë+ÒD”fâYàŠÅ…·É1ÍQ€s­î&¢&Mà¹_ÿ–«\µ©!O¯¶ï?FÁ©ï¯ïú. Z—N× O ÀÈØØ@© ¹†(äj_¬ÈÅ�3VÔ¸pK§‚OæÇ�ᬂJ”A¸žó)ñoòy­*ÿíð%y¥­ø Y?ËæIys¦UfñM±²§é|hÍE)fHhá¢¶Ô “Ú…Aùó)¶]cSM�¯ç&[êëÚB3Ø/±ñV²`曚³éPE@xù×Ùòßùj×Á`0©©¥œû¾?´9 œ —÷0¿�ô˜†áã4$£€2¢,?RRtRO|°7´³Áê`ÏEeõÔ�  ÖVÞ„²>QbÌdÀ ¡Êfn”­ÒÍ0®Ž+œ~áºìYœN3^ Ñ2×sЭ*ËkdiÊ8ÎÔNÆã}­B�#¢HÑõ)†ë(Þ«¹º©¹ªÀŸ–›!ë4£ [ÎD±¥å¶ÄÙ”qU·'عä‚vÛFè¿û]uª�ŽRTµÍån,oþ'GȃÿR8ǃ<¼Æ\âíÚ·×AÎß5Á÷ü8¦\“y@5kÑñ¢½Þz!!´¾†.ÚºƒØQâ öʤñ-¤æ’4!`(öP\¡5¾þòUnië‘§„°…•f¯î�ÐF8ܱÐòýgH¦o)x°6ꦼd:w�%óÍMldyø†~Œ¶ïÃÿíV$£�ÿ}\Rmr½A‡f4IÝŠkDü09œ÷äe”Ú÷ð1D{½ÑÂ5[KÇËkâÛqÅî"š,‘,0-ë�ԕ×oÀU=å$ÉP&g�×Vôù�¦Ã€—nùXâÁ‚ØG>õæß 9Ìf‘¶m”¤&© y’$$ÚÏhr¾ýPù¸ Ü< Š¨) §¬&/¤Ê¸í‘X0Øøl~¢]P¸²Ç½É�A�¤ î™n–à€é6™5¹ÿÞ.ÎùuÆ@£\U1$è²@M)„3î"P³¾d&z¾ßh‚d0ƒôç½ÐöN­¸YÁ¨ Óûø¡QUˆn·b ÿ Œ,!ÕÄÍïs‡5,›Vöè;�íàÛ6 ì¨5�Ž3ßoPâŸb‰?¡n0q4Ù¬¿Ë?µÀ{Ü‚„,þ>»¹¥6­Ã ÞlÒ/åÃ8ÏæÅkÂN"<¿§Pv"÷¤%$(èWÝ¢qº#Ÿ¾ývã´à%3-‚¬ú›ç¶J6í”Ì Ñ¦âSVÙ>(~ôºˆ¥�”ÈANå;à Êó‡þÚ¢œÊâ«êE­+Œi}HÜTêGXï„é–£«nÃ<ÝN‹…ŽÆÅ—QNW75µÍÃZÙã…‡|0@S6zQi<\WŠFÕ¼Lb4z0zKwCšÇ`‚†gÄï"e&Ü�ÿ7‰À±ÐÁ Ó'÷T?%n� ;rô -†jûõ¦Jì¨Ànj̧=Yü‰}WxÓ›Ò¡« 8±¤h�n•r2ë8ï×ýÿ+L¸£Ý¹VD´ ΡYÛ5Di_üj�éžC™3a-¹ž5Y}n_Ø8w‹ :\†LÓÄEKìLˆ€�<Ÿ|éýÏÉÿs%¨LOÞ7˜©Ò ¼`’ý›\Y±@‚¦Vñ5¢àÐéÂ¥¨T>ÓÓH`v¹„fç?�Π CÆáÎ/ó·×�ŒPíA'Ía´®�7,™?qkw.©¹Y`¬{iõy!±FY]ºúªØÕà×øÝtŒXã¥)þ.ÅÿB°Vl›irŠP¢õê$¡^+ ^FgGðX=±�½í uÁŸwQ ­¼aQÌ£ ÞŠ'kì´n£¥»Su¢ádFQÈs^†MAuBÑ\ ñ˜sê”Ó_t‘Ÿ³Úöм}ˆÃ÷1Ðþò^*)„‰hð-á@ö°Jó}á2s¶ºY?BD$øNÓ‡ßg­ÏšßïÜžcKE�™¾4+–¬ç tÐÌžWŒ½ØpE¼�䨱a ®íõÇ:<ßÁÔ›æÍèl“z4e>Œ�(=Õ³ŽRÇ7gŽpàpBˆÍ¡$ÂâjG×0èâ5.ê·O3h ÉÝI¦Î:îi”N„ž´¶tè§ôín´à¼ ã©îèÅÀÔBàû‘6ß /Çu¨ºw† ï êwÞTø�¬±~L³¶}ÒÌT„‡ÂdHñ þß�­© ±÷¯×ƒ]1ÑPÖ7çd?sšf“štÿ¡²áËY@ý›‚8¥r5aQùÎuHÍQõMNHòž“½øU¯è�È£¡ð×>r¶ñ‹‘Üÿñ¿u €Õ9vHyLOóxýÎà9=žŠ¨«Åðta*JnM�Ô{,�üÎÞzì2‰?uø>ÀBú Ý͹â@ˆ¹tôCög�†‰…]xnÞé mçÇÜc–¿ó`™“ 4À£Cþø–ANÅa“›dà 6azø¶eE¬Ø¤=à÷:¢Ÿž(š/ GD+;�°£¶7G„×Ñßž6ü¥¡Hn†ÃÑý(k$çdüÇCšÇÒéúÜîǵ¤ô)Û®”HËg~Ä9ïÞ¿˜ ®ÕÉÞ2©_Ÿ!ï|ƒþãI!� l…i³ÁÕI¦ý2™ ‚/›Û‰f5âÛ�j‰f5Æ¹ŠÆTpÀá7uÈä)Å‹]{Ësvî9¬ èJiIç£ñtØl–ðËlÎqÏ R5&ÊÇ̺V&‡”(+DÁíÿ{¿M ±ciJì™{œ�1¦<ÙlG$réÑ[ y¨:³Ñg¶ô†\:õðjs#ìκŸ>Bžº›æ½yøõ ÔJ�¿qð'Óòi³Ôg9²±…´õ”Ö~­ ~ÿÅTV=áOšPV  ~”›ï…dû¦Ž-߉ó­±â4ŽvV‘$üÃuB×M¯¸99€/“ö¾x)@ý¨º@ôvoðV0®Ê¾»ëŒŸhjÓdN¸÷ù—Ñ«|SE ¼î0ni)»L�fC f\ðZ2÷&€å÷ÁÒïùøB<»ä:£À¿S®'U™-gÐíŒ)Cø›yb(ºä3pU×ÇI$s§½M?‹†„Dá ÝÍ¢N ­¡šñæøw9.ýäv~?)VÒÍÆéÑø×Oü÷&ž¤ñ£^JZ Ë«R©5]Ü(·•`×k¯Ã&“‰ÍX[[ã âßµåÁ©]ߊªé¬4�ÿ+«Bý ãHOë/¬CÝìSî›{¿±‘ÊH"¼O¹oþwî6 ¹ÆI�²À®¤{ lÞ*¥¯5ñš"S=T‰É;P¯ýfCý.‰ª#•*t´:þØkÚùþ€kÂePæŠâëu£á" ­ÿûÿ‹ʃ)�·"À;•êVïG†‰ ‰Ÿi[È”ï„È‚m±²T¯æ£¨ÑyÛþw¿¤Ó%d©%U( Â)¶¹áuX 9À6zAR׃õ&†(†—fT¼0Y Þî³Êæ…ƒæ0h1+Ï þ}L—IÄ|(2îsG"Û§ ¸O/ðm XA¿–¾Ò=ÔŬeÓ£±q2ö èÏ0ß'4øàÁmHZ>›¡ØÀÞØa¸UÄ()¯�ŽÇbfa,ådÙS :ÞMö'JkÒ(†iÜïù kÜY2©ŠùQr¿ÒoS„¸ô“£M%T¬Õ¬áF»¼°Â¦sy¬iuO>¡™û‹|ë‰ �÷sÖT_�P}êÏ"1¦á«‡ù�)””]Q;oÒ�B�û�J³ú|s… ôdðÚ7)qú¬¥®¼­Žô×Ë*b¢SËú{<8%KÈJK‚~WË<çô‚�E�Pä÷-ö ±Œ€>\ý…2î:;H ;KŠàp6šÑ÷9®óÿûÚÞ-ØòV=—Æ RB ~-8yƒUì8Y"Ì?l.rq±ÈÇOã[¨î(7éqÞ¯ÃaŽ¢ÑÍ-½ãuE­ðÖü{é›-³ÞKKZŠI¯„þÄÐǺ]ŽCR�nÁvHL±õE.Q:››®þ+2¯¿e53!“w.®íuÊjQñ®«J›¶QV‘&ÓBøXÚÞ‰ ïÃ&:cÊsËYÍÎj±ðÞ�®Í*iz¿õ©/€TÓÛ m25ÆëkãîwMža1Ä‹\ñ?ú‰ªT8Ò¡ËiãÐwAy©i/"1‰XÁ{ª‘jËób!mÑlit,Èüóå$¬Ü8}Ñ¹Ý ð¦…5eø#î¤aº=Û¡šï´hµt,Kéy6Y÷GåVµ‘MS5:+Gä´ƒséÀ§Ïh.|’‰dÁ~»;k›9‚gèäö :Ù¦&jž]Dé»%Ü„ –�áÀ��)R}e–•2âÌÔ%|Ï9 Ÿs¥ìY˽K¯]ôíPÌèy5¾H†¾ŒDôó!d‘5ä?m¨O¨§¾PÐ Ëp‰ã¦ ¢}Ç–cÈ ßàS©ØyV®)[yÈÈ$hSh8Ãw͉³÷q¼ P¶Ïœ‚Ö«z:ýSaŠäÜcõ Ç½(‰3nм§x—JqR‘ØõŸzYƒÎ»íçÚpH„ÅCo¶8ß&Å›—JÛ¢3zæH4VÌ/¥í É�(-Ûc0D ÒÁÃè&Fìר@Î?8 ÀA!dß"©c9f~íj-/ Ý�PßÓü;*ûT:” ž·ï*´ý•g jû41�²ì臹PÝØ�Û !Ú‹ùN©À˜Å9=ÃüwÇž´†t—¬Sáû?âõ­s`«ß–é¥v-~q–äÃ=ÿ‘9�€é3ÌFGçâ�¥ëØü.ÊŸEð±Þ YCñg<1ˆmOyùÖÞ §ÂøÍJÝñ€^ø0*ÒØRú,d�W�Öýq1Á²GgÁ§õM¼‘ctµ‡G•]‡£àGwˆÈ³�œÿý½Ûv£d`â]ÐÚšÜùפ:æãûxAbW§ò’Òƒ[ö.Ûó"®ææYÌ2xšQz°`°â=cS×ûG\º¨fãO¿ Û±÷5A�â‰7š+ã­†ßÅÏzX¿¶rîþ³†Tü15§1 ¹ùÖ¢Eºë?yáy’‰åì &œ5K=ö@à·Œn’¯›Z„eÒ £[q8µ>=TÔëKA�ý Ý1Ý|r‰æáfÑ糌P¶î`‚½#õj¶ïFEU(-çîêy´­¤ ³ùk4²]Õiž`!…(Ì�ù G¶ò±|Ó@J¿Þ"õ£XeqÚ„b²´Xªa�¤rUÊ@ó *Œ¥„.òaéöÇoÿn<Y;‹ÑxÞsòñ@� YSô.…L‰À9øh§¯9WÐ ö�k¡3ÈL8c~#è ßk0 8 jOÅïQï^¿®8Ëð„­„úö"e„«�Aô–}ÓIÀ¸röV$·Œœ ÔôÔ÷3·Ù.£ó‚�°D†ü?¢4®®X¶*âXKþÆz 7óÙ¨&Ò¯#pr�ù#ø;mÆV«U/ ¬¼�"*!É>‡%º!‡ �õ˜˜¿k|T5ª¡¯rÐÓ{謩T‰‚׳¹)�€Ì,A–:ü{©{ï€>Y‡õ3÷`–Ÿ×ŸJ¾'J—e‘iNÉ–¯ ËôŽ¢}6{6˜Ôx†*nÅT¸/‚[‚MœoŽÕ–´L¾›N{Ò{›?nžéqm[§ð‘, ç‰`.ð#e¢¢Þ:lÎvaÄj$Û“ñ/�8ɽZÞ™yô¤üØÕŸá.ùq¸ÔÁó� ¸‚¥ÂÍ 8Ñ„ã•ÛÔþ‚v’[_>GüIˆÉa.,zûª›qs°,guÈÌ0/Ë¿7Epìm5Jv쀠®ërÎì¾p×<¢w 8¬‡“©*&�Öo3RM 6€¦1¼cb]z…žVäìPXRbÔÿ†”0–Ó¬ßkJC<þ—3H"q±¦Á'ÊöÜoU‡L3ÄËzSÙ€~‡÷¾H1cýŒ©¾œìöסP¶f¾ cÞÃîç4èÔn~¾ò¹×áÈ»-211}€ˆÙÔ¿ö¡ÓFcÞÑ.ê@éËf,ÝÈ@øÛ[ß&‹´2¹(�AŸâd”D\'ÿ Ù"O¼Sæ/÷¤u©{¾Ô“y ME¾ÓQx²;“óZƒÿmBʶ¢ÔÞ3O,±”"‰Ià2H—eÑ ³½¤^ΨÐÒCšˆóŒe'22܆û&£–ÎUèÏŒµ1ìÑJÞK¾˜MLS’{//œÓçÏL'¶öQp&ZqÜ£Z˜ve¿CÉcä^êrÁ ±šP 44}w 1�? LÒkÄ/¹›Ö£l©c“4ÔÅô®¦ç ;bìÝ¡À ϯžiÿM”ϰcÏ{Ú¦`P¾´’E‰À‡Éé@ŠkÞ+]•E]©¢ á{£�4æ×�âÖ+ôv® �oæ }¥gTYƒ(\—Ü‘ÿÅÓ¿×~‚è Ø—ƒJ«Ÿ‡kÉž«Ö¼{¸_O®Ëã�­h¬³( ÚÖØ[´ Y(Pÿ¨Áŵ4–©ñ_ª§b(uIC+¿H4©R%F௄O]¬wX•³'ÿ€Gä†'æTÒPÏ ‹ìoF†¼i{Õ�@¯â6y)™–WÅbò ›* ¦œÉÊ£ÖñÓþîÈÿÈžnGÿ™îk¶±,²‡Y<€Ÿc.´”ÊȱFënÃÖTì¾ÃépF¿@!µº¥Ÿsø�`1¹ Ê?·w×G—nç$¦V1ØÐpà¡$ÿnŒuMʳ¸ ŽÿZ;�‰;ŸAù{Ùµ¸ægôì�/vA\¥h¨�RdzHãíuó�] ëI¯„“þÓáAGå DºŒ“QÀNß eÑ÷h0 4´ÆE?{zp?ÂÉÕ5†0U¢gÝEy¡ìgúõªÕü:®<¯�&|Aš5-©2˜ÿýñ±ƒ·<á—"W@?N]ϊ豂¿ûxfÖ¥Ç1�ØpÝ h”ä2ibW¤ï•¨ ¨Î9å÷ T A{âÿõ$ºò9ßDÌà„ÄZ ùbCtY–aF¬8¯ ä.+òdÿÐ ò’&¥³h’˜UÃqG‘¾o¿$ ¬1ܹça´F™P/¤Ü^Î �CCá,Žg[8Pw ò> Vÿ‘NÁ�4(¿Èﺖ`dœœ×²1ð±¹K¬"=×oJÑÖA¹¼Šõ¯³Cy˜h¸!ÂÎ'ÎÝeÂsÒ¡ÙQjÉ 7Ñźž]qK pþŠÏ t+Àû’f-Ùë:  þUA,lð;. Yß&uv FTHSÔKÚvÍÕ�þpY ,M2FmÞÊIuR— ~Vöî'£§`ÛÆ‘k(¿e2+A  JÂ"é<^¹aŸªMßO� ´ÂíŽb‘ºåŽlƒbê–›\fU‹1Ë¢ÄR¯ª¤7…ZUŽ@˜ƒÈ•ñP1)aŸ¬‹8E<½:‰Çæ9*�CþÏ¡3ÄòPíòo¹î‹d›j$^œ›sºNc4ˆI/´=Á#ŽßýM�€&mÄÜGc®Çu>Îþ‘¥º¤PÊ šÓí°÷¢¯¤;-ùÔåìqÞ÷e\>«ÏûaYwÖ[7”#–Þ:á X2uiq.Ãö�íaº0½¸Ìã‚?·ç!^û VCûr�m5i Åz;&éçЈ¾ZðÛÔ’G²éÙÖlÿ¢#„ ) LzÆX²U×£4üÿû“‡5WX"‹Yg¦Ó*Gz4§|�SjÊ¡ D¡*¿~Ì0C1Ä3AHv—ðöf ˆ~½¾EY`Ã/æVû™†`õ �ÌnrÔ¥ !zÆ¡‚ÿKáÔ諃™:�‡f»g_2ä~€YDl®žlÛáL褻zŠü0Î}÷yGyE8Júµ»‡+=š¥c¬$µÎï Âá¾ X=Î MÏc£^áÃ]�¤@�žò¼‘g7)½Àƒ­ÙŠ:ö<’}«kJZ~�ÄG%¦¹4뺳¹:1úˆ�38L×miÔ/¦1<6}0ƒ�´›¥{…­$çpo|NÈ‚}oÞÍ¿÷æ©'è½ó‚—@¥Ô‰ 2‰#¦–”¹zѲ-7¢œ‰�³!všÀðžP›!ßEKôBÎñÛ…>/Fµ"(¥¯þ,Ùb'Gbát×4&0}%¾%¿�³tÖ—±eû¡„¥ +—Vóψ“$»Fhû€ÉÞa¦üšò øIÿfiêz¿Á3mÏr¨é]À}6R0$à’ dLìa e!òüé,ÅÖ„5„ÂÁké­5½`)¨óM_:^Ä ÷$TŽXjKü«©Ú¨¦áˆÐl +_nkÒA¥F€2×Wúå;ý ¸é  ‡­Œæ =€çUZ&–?n’/ÿãÝ¥4B˜ÀÅLóXbüfPšþ;x©3¦¯+ÒÇ›°*«î›†Å–’ä£Üë>ûLÒw>-†b]ü‡ã×»² �ô/ïŒÄPk4!ĸDÿ‘ Ÿ°0ÿ8ºÓ²D˜£oÒ@ÅÁξFÊÞàOïËcÜÊ�é<E©N£"^ú÷] I&ŒyÞBv 2ɱ%U�†;ß™GFxma6¹Uü%Hõ*|/؇âŒ9t²5ÄLí L�dcÆÔÚnmdi”bõß^sûÖZk &2I«—~ŸŸ¶b¨Â8Ì «cÊš›è2ÿ;FtpljÊååíüö�÷4¥8Ä:sh€—îAal ÄáR32…óJðÜ­¾Á mÁã™QÉdMÒÖEéÂq‡4ba3߯¿X­¢`ëíV¢5í ¯­((›¦(ªüj[²nýT½t‚²µÕmuÌJŽ �L¤>‚bKÝù`@¢rü4®üÆCbyn޳ÿÜJ�8ÿbÝ»´bJG ¢vú½|? âçý.ü!£éé·$ÁÂ|‚]Hü3­¼R¢�BX†R„V�æp˜“×.¿/Yà`âú4U…a?ư‘‚åÊ»m~¬—j&iŒýÈñMŠÄ?þçªEAò}1¨­cªZxÜ>NV®í´Ü j/¾>Rµ¿¼ü/ÞOÖ˜–Ìüøìäßõ‹NŒÙ$d3fÃ"_tßí·-s—R³V?«ÎuEB¹iãç/w™æö�6#r ¬ÊWe8äp#LyHBÑ"jݪ°h§I@Ö|šEÄ€Û+5 íÅÚËù’"§:̘îÏìõ�Ì^ØæÇ•ÖÎÎÀa/JÜÿò)‡2Bü8‘ï7kŸwO¶ n°Íмç>AJÅúÄ¢•þsGÁâ6×.– >ãå+êSøè“p×_Aò3ix‘R ?J¿Y'Ö‡jª`Úg`[ôbí½ˆg© œÙMrtY|Ùè{¡>©dÇA‰K`Dª Ç?:~W]8ÈÜã�}°òݱ˜ï—*4$>»ë‚}…õ|M,yÀF12l†àgªÚM1¹jóVüøÎ|D*cOæ|@Y["´…›oFTˆ�ÉΈ7¼E�‡ã†DÉæñ«�³¶¿ÂÜ ŠU1Ú’^ÿóAÇ?á2Oyø3-å(‡óná;ø&e|€?™ß@¡ãŒD®Rçóç%‰ã¼Yþ32�y%r0ݦ™Èïð€f`ðtuÚ‹¨p´æœ¦ÉÚÄ¡Aí…D¾m‡P´û÷ ÜÉÜûg¶byeŸÃί’ø†O®âçÐrðƒÈ¦RÔ 2ƒýàùã"d~âΟµ9uBqÒx^Ç 2�`Áb·3¦#4>èxBïPxÐí1x²uÓö~•T ît4ŒÞºDüŽÈX¡„Ùi�–ÇÓZ¼@WÞ†sÀŒ-•œ¯l©÷×"xÚ`2e¾sä7L’)—{ov ·ßý/̘f¬Äà* ¾�¨1\?/–Æ–J~Ržt@œ›êOF…Þå´u4“èïBó™'^õi·±Áu ×ÿyš~gÜÜHûZ.Ú ¦÷‹IFÛ7œÕ톌Jl§Õ70#¸–½ž–ß< PYáQä«]yKSžk±¼? ùáß¿ÑU¨FÑÓEH_¯ô|’ú…ǶïzÄW§Gº°]#55j?H<“Ñø£ =Ú±…i•=‹±”ØhHÇWo#Ü$Y¨ÉLçצÁ"˜�î;,¡ØîÔæésˆ£˜ì€áߪg¾g›Mmä uŸöŽŒ•Þã%è¨Ë’•úPæL©š"“ºš!mžW²â³¡�Ö^xzæ–Ї`l4ÂòîÒpÕbýWFþ5 w°e^u˜¢Co”s¤R4¡ô9c�[xQèèÒm}ßúEk–Ýx®A…Öäl®7*éi< בNtôÐ>Hæ\Ó;;Ùh‰.ŒPéD½"jŒÀF�¬+•8÷lÔÐo~Æþœé,×É,‹°ã´D웳˜¾°Z‚Ú?ûðÈcu†”(äVÖÎ�Ø¡ôÏ´Ý@‘3õt°Ê–�:¾êÉŒeÄ”*4™Ñ}ïY%q£4¡ ðåÀ:Œï Õktü1Ÿc^KºíÉ7&Ü¢m%�“€¢µn@€öc9·ýEàÿð9ëÛË@4˜Ýë¬.Ão8ÖRy‰k%½æýöÑù ¼| „ïöˆXa&!D?°Ù2†ózI¢×Wœ�‹L‘½½"²Y(Wø»1@0-}’SêPµ²"Ü¢OÑTj V*ðe#-Ñar(ø"é£Ë=fž/+˜4Eé÷´×² mÔ D­áDä#9D�=Åý«%¦£{'@,p:§pË%Èî¾lÒÊsƒí/¢×û†f@ÜÍÂŒ0ryó\-è¤Mÿ Ôð->?ð’  �ÞÐfTÜõ8ËQÆnRx`q"B^U™47˜�æR²ÅñCµ± E}Þ´GDÔÕÂÙ'R÷W®ƒda Xµ\A~÷J>vÃñüÞÆÇþ×S’—:n�†rˆõ¶µžòªR^M{YÆg&D’ªRÍ‚,JøÖ/3: ­3Žª5F17i×<˜È�í— IÛÀîžÖ$ZÏ\OÓ²çŽ]£¡�üØ'c¬L·§aNe:´�!ç)BwTÐ�Á$Šz¡rÒAú’è¹2¬UòeÎjæÞIØ¥¿&H“»ß\kUVoÇØÊ›•†o¬¢§ÇÙ%Í(!Å“Gêð:cÿwþü�Boæw”!“³Ü1ñ S|Ž>‚éãâ?ô ·ÑG’Âë‰ðÜo@OþVœ86þçЕahM¹Ñ;,n«w·»"yn†ñ˜ò{”¡jò²K-Ä Áð‡”)ˆS$«¿»`RØy;o#¾q¤èïø¥é�ß"#_-¡b5,÷ Çé殺ÝT�SÕ*©y<1«”G=k/h( ÈþÓ¸ØÉûVWýƒÅ�g'Ôi`S,@# Ç&öÁ�9 Óâυйâöô¡_><¢Û`÷ûkº)@Ðø"3ë« zÁ Â/èJ¿ ÌKçq™W˜¿GKÑ*°ˆ–ãDHÆ÷†‘™+-–#ÓÞGÒb¼4uû4V#-Ÿ°?Hè´ª7ZÑ̓¸{†rVXAÛÂ"m—<´_ªp]¡èØ2,æ’òÁ§À•-Úëɸ³Ñר!ðEáßXAƒáøÿ@ ^FYYMR�¤oHüu»�Nui”'qY¦ê 0ã7‰27üÖ°î�ûæ�dªj²¸¬ÞFÄû"ˆˆ ÞéÓ"Ä͈րU�{ûM8IÆÜUµ—±’DK|èŸÁÃù‡çµÍ¡R\Å&ñßoÒ1,¸ëø#)˯qç7]¡2WNŸ±¶¥ÕTrîQLl¿Ûâ–…ï[-âø¶Âf¨v�  ëÃ'|ë²S|u¾¡:Ä8ªbýÛû:£!¡ �=èë©Ø¡NÒ��ð°Éú·Žöü÷EÃ9Œ,6{.*óm³£ˆÖÀtl;¢’ø(©WÓmmâl²´5ƒÂ2Á…eo¼;j˜å²~èáÇàAh8ö–ïHŠtî””xX/æ~W…Repi ¢ÎO)k„�«‡²8<òÄ aóõ›~;ØiÎÝ¡¹)G@]ýc‹Œò¹x±¾ÀÛV×ÿ‘aÿÔÖ䇢»F¶Ï¯£Å¹49AXñ_¥KN ƒ·‹ õOóÀÃ.óo@y;èÄóúŸAú©^óºmp# æWÃB½Ý)Ù×Ò,ÛÇv:®³‘^<¥×*WH1ßç€áÇŒØ ‰ÊKq¡z3+~‡T)(Ö�]ÔÉ4“Z7¢ÕÖWy*^$«½ñåÖ}|ŒøTM2W ô̯õ ooa¤ó’έ=ç§³<ܾËÍåúad N!Â6ü ¯ÝhôIf‘Ó'÷8…u´ný9¡Á©z .u’ áO>p*õDdCÂÅj8†&»Å<îªÛÝq�jªTú÷#Ç8âðAá í …¹bN¨±féLĺ�• üãÅQ×î/z¸½ÒÙZæ°ksØðU§vƒÙÆ€qb�7àöAuÅóF¿|.F£ó<^±Þ¡—ßëüán¿Ä•~ï׊ó… C±”ylÇoº!vÐúÀ2­µÈ¾¦§É¬*³5��S?…Ìš¦¡íZX’l[J5fI«ˆ¨Ò‹¦”Æ Â„áOÒLÎÉ_õzö0<dq»P¤ò^d·�gY5ò¸{ßkòUv/t9§�í…ÃÆÓˆ%Të*þIŸYl±$ª)3^@Æ–TˆùŒ4bÁlÛžýÁ:-,›Ÿ½v‚ÁZÆG ÙOŸ)"Éã>ô‘Ê{‡k§R6N§áf‚Ù½ÜÍXˆq@±Sº÷Æ Xg¢IŽRÊLí|�LWu§›«öào—Òbê¶ùç[ð~õ}UV}êK'K¾ –Ôi‹ûbÇÒnñͤ"ÛÛI .¨ #"/ÒKVF›×“mÌŠD B""†PRºªˆœÈhcH^Øáj(b©Sà=ìš/䀽t*¯u±çFy†´OIî�à,4kø)&Rê%–;yK^>°œóM:ˆYPÉ-^H¶9s‡æ‰A]-�Hi�:`Ê �º11´ Z¡ éˆ,�_Ãã{Žº^~ïÀ1 ‚ZaýGê¶…';ÙøxÔÁöË®_›v×­±w§¤%£ºÙ˜îž›[{h}tS¤~ÿa䲎güǺ<“ã ~W°‘¤é³·ù×Þ‡Þb‰¿‹H/ÅJ‹; AªÒ-~D¹¬…\œ}&;°šJu‰û“b)ÃÛK¹Ü¶0£ÓtÝi;T˜”WÌô梉ŽÚŒýaïн_-ëé6–ï’îDÒ‡Yý²«� c¹¸XÎ�€b »ÎÝ 0Ï{¤ �wµŽôÛáΨÚYCò�ÌÔâ@Úìˉ¤n5·¢#Þ£ï#ôŒ‚!6Ó «È¼xun8Ÿ$ª‡7qSýsJA:®§mBô!¦‘¦³T$о`"pÛµOùÖKºsP‡ÐVϵCDÂÒo«€Ä»™Ï¯ E”ö,yÂÀ¡½ÚküR¾ý¯hû$…©²*ñHD#e{�h©¿ 5†Y<ä…èMÿnf¦{YÐÊk?ß$Þ*ÄôPi Ï ·xýÞ/Ÿþ‰uMÅeB´6¤r÷û¸Ì �:ÄÎá7¶±œ‘ÚüPóRä žv؉ã;ߺû4¦üÐ8X ^|+Ü—Ñ/aYn@>æ¶¶b5Ïq¼W¹��:ýRo«b,Ç ±œNx®pƒ’ú„ñ³KÑ8DŽmõ.÷ið)p ÕïŒÝT6Ï¡Nôy‹€¥&Úz­f¾èñD"Q„Å牰ón”�‹0å@ÕGKh!À¼ƒá ‡Ú7+8Ä5\Ûç0ƒ€Òq5îCgyÿj½± <-T °Š�A¥M.á•€ö.©³ÉJc=êO‘ÞXô‚oÎôb’ñÌÔ˜SY1iÍÕvZìB*ù‰Á’mG ¾€›-Œ¾O,È ¯’#Ζª_B句Bv·e‡žü#DÅêÝÄзý‚Ý�T#®·Ô’ûù›M©ÂÅÕç9û8qzšN•#´ü ANN¸×�ýŠGòäË; ã¼a¹öp‰Ì–'e¼rr¨ …wà–Á¥|‚v.©4¼Ë†PðàÓÇ´$°ü~ð&o£^øþ¾�jlN©èO£Xñ¥pÏQb¢wÝÿy NÍ2ìÚÔ»|½'ÄïJ»8PÚ±óA¾¯~ƒ®ÃvQJП¡Rù^jfNóÉøO.ÌÆ![ €è«îÖ(No‹­ é”±1]òhàf®š,~c[|B�EBÊ{ŽÉ&,€G(·û€\:û³�DÁS¤<+ép«makä2ì9Šzƒ~KYè©F©i©-îñòð±9ž{-i/p‚SÏ÷~½v$!m<Îhù�ØÖô­Îû©ÌŠMúg³*^¥Ô#�ÁXRíÇHHýâ}ž'~2/´RrF#´\¹ÓúíÞt«žÁ#À p£z”Z¢ Hÿw z )j�ÈQ¹÷JÞºØ3L3aãýãpuž³_+ceYqa!7Ü—BM^ÚˆIXä¢âÒo:ý*@ ™ZmP6Ý“òô� 0o`r19:ãP8:k2#\eK�-<ÍýªÞ-N«ÀOˆˆA.vZ}Á1Ÿ›ÍŸñp¥•hEž’"¨·Ó«¿rãh'1®ˆ©cÒ £ŸW­IU#3Y>´i}5ø-W�X¥u¯‹§-[‘UÒ9”þtéµ-ÿ·‚ÝÜÆÌ ‰žðÒ"!C{¸.ˆ '.s[ãKc+*Nä@xªl?0ãÖ€ø³·R\"d{8é¬Oâè�3¬½Wôù3™Æ&$ÓáX³›ß)_úÅ�ç|-ñzhãÍShõ­:ŸcÅh>Ÿ ˜\~&2ÒÉv”ˬx4ü½3.‰hF¼‘¢6 '|úÙ�Æ—Óô{†¨,‘‘òöåNö}ÖÀE§8E²›åõv¸ß ‰x-]” ÔŒYZ”Ÿ ‰à �PÛOÈB=º²fb›òç./±¨’pÊ*.­9÷‹¾FÑÊó(˜‘4VŒ"Ä¥¯åß0Ðת˜m‹ç\DTTˆZÁm~®!Í�(¡ÿУF[x‰ñSc¢û ë?ûáÓ„yßèÛý$?9ïg…&xfÀŽ”XóY(g¡èšAÊé°`�fŽïÍÍY¥Eø5fŸìð½˜�ë—¨ÏV=Uñ‹…–—Ÿ‡†ò×¶êŽXcÁÄÞñiA´,…Ýùt‡ðÎ àÛáùR¹@” ^ÒnfØ6ecQn–H1Îå‚å~%;@‡$5‰v|ÌÖ–JþcS‚%6^¢VE¡¤=…°ÌUû8mo-ŽËàö¾ˆf/t-ÝùË0@¯—ãžô›5þ©!iWèL’[!zäå™òô�d?ÈàÄ)UB(¥e|^–#0Ãï[ÿ÷P»—»ý‹#zi,æ‚8‡wC•ЋôáW ”ܼ<‚§ËžR_O(b„Êg$ÓI2&�2Ô(Ü%]Ó6×l(Àõ××OTïSœBh0á <8‚�apÕ¦†v&É+ü­/úHZLJµUTú€±†™;Çß´ëkñD7·»dú‚nØïûý‰&jå½P÷5+ÙS„"èФšWµâ"ožªG"§þÖŽ .¨ ë?ݦ'ÒÁš¯ÿºƒååøã-TP¼q´'Ôi¿É‰:ÿP°DùÇ›%7öFBÁ ð«[€±œ|”ðPë�K&4çĆÖ]ÜvbaPxúé K€-™¢Ç�µ7 ZÄ9¹äÞL+à_íÛ.JQ2$ÓŒ-'ö˜í£kR¥$h?äõ²@‚‚×’P§w.mày^ ¼øSk’;\}Ï%lžÀäÀBHîTéCWs”Dí¨»¨ôæm"hµÖ„KâfžQmÖA1wA `Ÿ4j/wH[IÛ.€ÔîçY®|ì3 €|ê¾îj¢’r©dN%“:�Goú´ÆŒ°å‡�jk%ó„Ù¶{÷Ôè²^…_àå µ«ieáÌâ¿õH¾Ó¾·ºhQ'Fv¥H¦,ñÏc‘{`?£ÓI÷à"áù-²$”|‰ÕÉŽP�”Ü ”!…¬®?Säþ·†NPóVÛ€X/ˆÓ¿°K±]ä F¡ø³4òòûu�p%‚Ìt‘\"@«œ:Á™“÷áßì´5ž+þeµ©•Íßß2Õ(ÂÃôÅßgiÔÐ-;INáÈ|”è+¯š�“¶‡Pe¢"çÞ¸–XÆXr?ÇØ exÁ§‹õ Mz!=ŬöO¼7ÀCa-ì׃qh ØåNáúèŒ)]—ˆN¼Oõ;axqG‚~Ú%[hƒ}¸ª£¶ S:×4*g ê]5ΣP©žå;™tð ÂÒ�i-§²:lá:°µ�3üKþ27¯gzªj €½ÿí2ÛZÙ̉»ÙeÛk±ƒïˆÌ¹ëÝëèO!Èé“)h¨L÷¦<­;fµô é [Ѻ§­/�¹*øYÚ<Ù<…<Õ,"IóÙADñS£=›HèûûV ƒ€Žÿ’ý³JÀ6‹IsIY½ØfEKb`ÒÆ~‘âᲑ,aâ°°Ö—¹¸p£;½}¹é¡‹XHÍeÆÐ«z]%)å(t´/Üô!Ç7ÿMˆ¤�‚EÄ¢h=K#U¾¦¶öÓnˆÒÊ´ê¡–_�þ™üš-&«²Q\�ib„—Gâ?mD(�¾¶nˆO‰­öÞ�¤îG@ÍéàÍâ´õL¯Šè5† 8Va ˆ@;,‚QqÐjD�Üt.|¶� Àt5ý\¡ÄS2ÆJ³¡ˆ/’"Áš—£ýU°JBÆLM,QËn½ÙïUÿ]~ùûL,rt×ÊÄ¢4¾-óMïýÖ;VS@¶“lZØ"¼”ݰ ëá‚¡JvÁÕêgÎèÜ0úíÃã`³­ôîÌ·mîѿ€…Ù;D&½ë¹m²Ê †õôž29‰ìÆeOâ²êBÁEX×ϰ>‹®ïèn«ˆK‡p¿Q%õTŸ!ÊÇ’Øz ­9—çù©ˆ sÎÖã¢í^?ع9êþɫچë4ˆëÀéãpHåT™ –=ô•ÁôO.²UFÄѸg±K\™ŽzrY€Íïà”eXžÈ5tÅ-Å­¬zaùŒþ&™ w–‘~ò—q,þÁÜ‘xåy[é·*A;—®öƒöêõ¾N ãpë~åg¹ºhØ: ÚE£„tÇ6ºUáì&PºªDDUýSùTõEýû£³=Øa�´{&=é)Ô·24ÀŽDNË©iú:‰iZ^Sa²Y޹Ô+"B+êÊf@‘Ò‹Ås¾EþîfÍrju¶¾`¯üdù?|»y=<Gî@…ÐËґر:¤2üVÊ‘cÝôÍ𽛸�îz# 5§3>ÛÝ<­EQà—D@ «œ(9~}*—õˆP_ .ÖËóæ%NHƒ!‚°`”Œà«Ã–úSô°ÿ+È´Ó‚%IϵdL £S_qüh"þ¶û“ÊÉ@ñï?j<`I�ý‰¥—`B¬ön¿ôE¸šû²IQ(ýÔê•û û¯?ÎwOó uj?÷‰™Ì‘ÂMuˆhÏ(vÑÄ“_¥á®t¦HUÞš˜A/˜h·pGæ±qF4ë¡0ª±,éç3ˆMhšêò;ÒOyÖqE¿A©QšÞ O¸‰Z’&»ïAKm;7h]±Ž¿øÜFy›V]àc¸ÛÃ÷wÝpk$P‚¨ ì´òk5›q»8~’yÑPí“�|Š“œÇ¤§[áËŒÇ&a…ß��� )h-R]À‰•õäj(ç‚J/ bæ²úåøÞFH•g¶v4µ§P£[¦&Š8¾ðy(z×zPš93“ DJ�Å̧IÓuQpëQ‚ª›Ã6RŽ•DÕ?žI]£‰K|«¹˜ ááœS�Y$°‰A–�±XP ScÐyéÀÝ~é�ãçv¿ãa¯· MuCÛ¦îT´¾aCŒlÐ3HäÚÜ7 ŽÿÂáVMS×°¾½Û®±Ò¤ƒ=Pþ ŒÿX~v*¦+ŸŒWVPbfVG†½ñÔß_¨´T”ùA'0™QŠ ˜TýÝm`ÁÅì!Š%ižx"˜O¼&÷œ%©"ÖEѾ«$XÊŽ,àyÍdjÖc1»–òLL¬ÂøÝ¡±Š®Â7 b@o8í2V øø¶L™4×^Ôš ì„vWâ°éAL>ºHÏ�Ä¡mGÈzÒœÄò#ò¤çbàX–�Ât¸ šÔ&+^aEAž&d”D\'ÿ Ùs±“4 PUhן±^ªcI™ ALÆåÓŸ°óéª8–hÇ­ø_šž°—7™Ú”Ê"hë0�µÇ³ØÈ©N‡¯�¥oJ¬§<8³‹;œüåÈ(Ið„6%sÁáÜæɳ¤€¯^’K“pÿR‹QÂ�v}ðl/6ý) ß9:’‰QÐùUí¥Í½eÆÌ¹|×½”-mÔæ!…9ƒm+fŒ@‚ßw‹Nf¿ßhk´5•G+ðàFGVô™æÂI ¨=³_¥ÍØ?T¼OÉ•’é|ªcwàýÏ"Þ,5P7ý ¥­»‰Þ Ü&DÖ Ä'2aÙö̰æªw| ¨ @nòžö¦Ÿ;�ÏõUq&ü)—ÎPBCyØ ÿa�¯àúO¦_°ÃøŽÖB›ýœˆ$OƒŸ,i�²X« ô¼¥IOio¾ -ôB7v°\'â¶œÐâr5çÅÞrȽøÌ‹n¶ ¢ÂKÂ9¶©„@ð·s”%±üþ\™½2�Â7sJ¦O·hQ^Eädô½ÒßþôsŸméDLøz#}²…ßÚZfB­o�¹›v4ßå¿›Œ2šl¥Ò¨gÿ3Zó(U·cW˜o„TÀÂ4¦;„”|¡-ÿE‰<”ähÖG2Pm[¶¾sŽ»ásb™7]º>½Bàt¥òÕ©ÙÀÞ»ªãå#¡ð/m©?_Â÷CEI”Ê¡¦÷=ÚP ï£Bôm¨P°ÂŒU±‹jo:È_çŸÖìLÑq"¤û8C,f`‰8KÄ@m‰ÒJkZeá\¹Ï)¹)ý«±fœ Ç-º%/A&X´¢Oæ'wðÙ!çé`¥bì×i’FôÖ‰iX {oZ‡gMí”EªÌ¡ Þ[_„v�J&[N=7ÏC~`ÏcÑfÔØa¯ƒÁu•¨�Û2šÎ ¹ÎíUÕ.å¦ñ *ºKÅ3Փʽåöm˜Vʼ„÷Hõ‚H øª·ù}u7m×f¢ƒ{^Þ~,wżübg²HnqrÉ+�$G8ɘ|1S5_èÃò„Uªš÷¨1“á €lþ‹ "ágžEiÿmuZè6m}ÿs)«B™™Óý Å¿:µ#®ï^J$PAà`Ç&=J�ëgø¤~†y# Bæ¡N%ÔRÅñöÍtL)É<}¦¨’ä ÑÓ˜/4°pˆÅSL°‡˜3â#¯=…Uê ÊD®‰°­ gSW§ù´p¯³*v;Œ_"[Ü ›ÞFýg«\#ßÂÊÀŸQ×É¡1~¸nÍLo4*¼ÑCøåÜM5ˆíŒÄÞŽð”@˜B=øêß#x‡£plv©Qöñ°(‘Æ’‡ïv3½Ì³¨ó.4!«�G+I¦ÊÒ­`¯…hÉrXúì&K><æ÷úìg%_»p!§´d ÏàäÂÕŒ·Ó :è¸� þæ9·v‹Éо)cfaè!X•‘T•ãEPõpàð [ qó¥ž ‘hýâ£åºÍs‚s5XXúyõÎï©`¦ñშz|[»W» éžGnGÿ™îo,®ÍB�«ŠF�Zý�°|¬­%\&(@ëæÔH ºö;J æFÔEãu()Ò·´ígÔf\¨,$Ü¥¥Ué àŒ*îñ‹ÈãÚ+�åÅSýŒ_~HújÌçŸTÁ¡‹ž;x=R(è~§{õ[¦£Ÿ–q™Èú¹vßUzþ÷sþ˜ÚaÆ«Ö�+:Ò¦~ò?ÐÒбE²g6A(U»Ã}e'½¨þ…,ql9ø$è`EtåX•lî M²t¢Þr�´R,ˆvÑ¢N�úÂ`z¬ ðÍjZ)«4ÔÏò=µƒpÛ˜gÍúðŒ |eÑPv._œýµí~8d·"©‹ØÁV“ ¿2ü5 á8ªÏÆV ÉþØK>ÿ“kES3*LÛ¡Vµm�‡ñÞFeCyFNл¬Y«Ìö¶•§«‹ðò7Ç÷GŸù$蚎t–¦n0ÜË�zð™¥liíÑ©¡�u€W2q×MÞ»Ç;NøŠ*ª‡ÜÐ0ÀÖþF6LÊaÚD“)Wsuy  Ÿ}yAÝUre'-ô£9Œh=ÓèÜ>6žS¢‹>Ñr÷7¿\É•v`3ÓK*/.­àÿgýF˜›ñ‰`’* >ºnn•+ÑŠ:æÎ:T¡mä˜5kd“øöì}º÷ Rj‹€˜ÌUI3ºäTs]…h‘qp�µžÀ[jøÄÎå11Ð)ÜÔ‘DFáTýJiéSU(8Ä01PùêFæ+ú7¹Izgè’û`ºhö6ß„SœQQÛ„ÿL: ¨%—‡áÔ³þŸ:v–>UþK wÞõtóÓ¹rhHrˆñ—Ø2¹„親Ê?ГSP…ý…?¿¦ØtR’‘¤»¯j¸ E/ß8ïtÙ�H†²90©äF�ÔªV׌—îËGþ‰XiPêUåô›"+0ªúÍ9˜$šÝž ù£ì×f�öqCËI)ªýãÒ˜Cß4~ûDßêÄ¡4ºzDƒc­œü¡vž­2–Óo¾�¼ët�PÊo(aVÑŸ o7F¾áØ·.jëÍ{Ÿ“zèðfìÈþ…m*œ�½ChbÓ­*Þ 2`V=üÐû¨ç‘5XLJíéâïY�ùèŸÇù÷"‡Z#àÕkãõ—bƒyÆ>ݦŒqû_Æ.V&ùŸ&Û¡^ ]ÉÍ) ¨isn.L‡hcÕQÒLÒûhTªñ>©»A’F®² îybiG@5xùeœf ¿_A®$†ß@£‚M¿ @%¢�ÜâmMØÿÐ@ú8Ò�z–;ì@•íJÄ+,>ÉWˆ$f¤±ískq†\λwh¡”f︬u‡³ŠÆ|">to’ΓjB�èƒ r¬ÊE2‘pÕlI�݃|Z æÂl�!ÒZ‹†E•z4AäÀrÞQü¼0ò£&润~Dø(“Vc:Äl½aOû&Éw»×Êœtû­´H­'€IÓ&»Ù¨8éYáWÔi†tˆDY~^a`×ä襣½ŒG3Î'¥ÜÃ$uë4ã®2þª†HÍ*ž&oÉm þi¶0I]ƒ–ô‹¸s¢Y™l_8ø¼2‘Û¼?j(áM]E:Œc1–ßbczt-3 üƒ ôiÂ<>•uO�“"+á”ÔT±Žêè‘ IZ³¦6+´› A1³Ü�–"ý }8}'ëý’Q=ñ$æäF(qìâˆbh´`C¹ÄPº �–…w²Î\š\ÍKaA ?ýøô/Û¿&⢣ËÙ"Ü ïÖý$²m Kº›û²a¸ƒ±œÀ¿Ê8¥ÛàqhòÿïΠ£‘<>hÇnõ 3í¹ËŒtáZ'¶…X£Ô=;LeÃ7›wá Ûºt6ÄÓöÂôOG¥ú�'v7½8ë0fJÆæñ9ÐöV/€ª¿ éü}Ù•~ÄÁ/™¨.¼n¢3­ýŽ@—?\ ö<Ëq�?T7zŽiÛˆ‘XKÍMkþeÓƒ\pèIJ7—ŠïèR¶µ± Q8�“Çš~èb¤T§�îý <§ë2÷`E·×¥Y]·I†OjO¹MôÓÇ<Æ“Å@K”ý…£íVõµ»±`å"—ÛÖn9µM[åc†C¨¨jù =í'–Ðꊓ/AÀÑØb�±Sº$è½·Ù.d‰{AÒv蹪Ž2ÛYÒÂ�ÿbÅtê„AñùC¾­Ü.u–HŸè™ü§ø@­aç0+ Ãíž áå¸zó} ”àÔ@Ο4a5�ÏÞצ¹hÀ¹ˆŽÂ´�³$ž‰´TVÈ;ß#O:ŸœÕÒÖ[ß"�Öÿ6SZ`ÿexÖ é�AÚ¦:&/‚¡Z�f€þŒ|Q•ÔCÜ\°¢«ÌUyócÞ=ƒ¤=Aᵄ:º1×õ ”ÍØêßÃ…² âž´ 8 V‡iBE;×äÎOnïü³~ñå¾-Ô0)$(uÔÆ<õ^UB1Ì}(·âåVH¸®FRê«_XæÄYO#u©ã{Øëf€:·.hƒ³N\̄ז`Õ� +g,�C•J„Œ¦žè�®�|€Ðg¬µ«²Wê(ÏæL˜¹÷®0B¯¡R.àæK3å’Ëî}³fsIðð(Xí>xnU¸Š�.P1ÿMçÖâLuWO˜æ‚á �MUÙÒ5´ßšõ,Èõu²X¦œ·‹ú �kï`nVý•÷.[¼ÍO׊¢ûeóä>¿Vu ý ?�Ž××þ\Ò+="åÈ1P³â¯È%Iã�% s‹\/íãIû׃h±ðRÍ4?o ú®ã‘±öb ¦\>ÃuÛ¯oׂÏ[îþj1,â�ó&6µ"œÓi7œ:Ïc“„TeSÃV_­}_­˜± ªAÉ,x,ïç½ú$‘KÑ�CØ@Ñ&8Èð[ÝZ:¨Å4øž±{ät£Á\åIÛ7ÜxQ 2»9¸Ì\e!¨ïLm«ê¼Ò&)Ó˜Uk>kÁ‰z5? ƒ8>e×Kü¢Ñïzü�} Q¦<Ѝ‡ô ¶jº*´ø ¤>°‡Ù�á§õËóÎá‘Ù­¯Š´�ç왺j^EîÙ®Æ|ø\I’�.ëÑ”™ÍžÌUdìl[Ò�*¡¹$Ôt6´ùó�NÍ­ôžÁw—9SµG�QÚݦ¨ØN°])z+Nz kÎÈDWjîÒgÅvZðÖéÖÇoò�ç+Í)šØ�7e8¿D꿟ÌÙ¨Ý|mê\°�BP^ ÓAšI5-©2˜ÿýñ:& Ô][ò ‚ÿW¥Xð„z ›>ê/!f±¬ÊïÑëqHåËëX~&Í ×šÞ _"ZÑöAþxâë–ǰQ{bÉŠGºo@˜v(3éÌ„ä�ÉØžÅìàCÉÅŒi‚_pŽ>ä¤éVÿ'9‹ï§a#Šôxr‡BÃÙ¼ÙËô LŠË)'ó �� +|ÕV¡köæÏžØÁ™qذV_s¶àG’ Â®eëýkÿòËàÅà@AÖ.³Ý„Mï퓌(¾+wY7lŠ-Ô#ZñhAÚOXÿQ+pâNmaʽJü³3·z@:e§Õh»gýñÉÏV9h_ ÖsØp7¢VÃb‡~ŒÀóéÊ\ýU± -ûé!×bÜÛŽÜÙJ­!æP<§ó…!8R£ñ'bñê­µJp(ÔöU»ðp=Èeæiz”m.ùñïQÇn†Ý/Ä2ØábÌtØ8bîòvï~Ú²€M‡B·#Ÿ.NÚÎ�%ðš�m»ŒètUÙFƒh–¸d0 Ð'éáù¥ÆJ©ðÚò&ºõ°t¡uDŸ†öÇÐY]b �å*è™Ü†(:þ@ `q\);Ä]t4Í~² Ò`ªu=ûɃúñmPæ›ÝAÌ÷Z• ¤cWø�‚ƒû?p†ÐÇ~ÛkPñ»ŠVßnƒ¾�¿W”|Ï$Û¶à‹®ÄT€°rûdðW¾Ø'ˆž–hcr£ä�|Žæ a$¹7kÀ0»f"0QéIÂ3åÌ€…,s}Ük:&ºˆ]—õ¦1h®%w4MÓ¯éñFSMvÀ*5U,k“g:ò‰‡ÆìuwNöHíþ(IY*ý>fÃʰ¬‚f™q|;yÆF¿6ïË ïAŠúŽ“zª¹Ú­ËÈÄî„ ˜! ÀD0Üo'ˆ�¼~êù[U“s€×éú^ÛÈîÇîøkT·ádKç{Kzd£ô¢³ã �²þ¶r'ð7ŸXŽç›Šÿ䮀!mÓBN•`}9Â<¥ažíªžÆ¥_f}ªÒĽ�e·NÆ®M8GæG·Ý28fš7…ø&^Ž� fWP0Õ¢ì¬?ŠøÊ™ù) é.‘9ak(aÑÉcG�€o)z¹ÿC£³a{ÃóAñðë´…®ÁÿЖëñ¶6WS;Ó*3‡c(;´O½mßúѹx_…„‹&Ôl`÷K·£#Þñÿ¿úL¥]À$ï�æÿÀ\�b7˜|QŒøiJj˜¶2&û¼¸îç®dMÝûÏèw¶³�³[ÊjŽŽb$ZÍýP³’u†/èLW¥‹ìÑ‘¥óS�>+ €ÿV¶Ùü,| ¤ãrAL ñ „o€¦g++γ™¸]ÿ7ÖPí,Lh€¼Œ»àq9µõI q9¸í‘é|(oVI“è\Ö[ùØ¢UÈüÒZªÁ-ç?�‚srYþ‹ãf&Í‘ƳŬœ9Þ¿Î Ü+€Ðˆ™8ÿþùH£�šÙ×lL{�-ØYQSt,¾K‘Ï=ÆÜRN@+!îZâÙúî™>€¿Çwã¤w m'öD%×¥üô®FÛív¤êÞk¢!,F¢»÷=‰•ó�21wžÀ4&“Å…]1–�_œ?yäÚˆsttš.gCŽe¯æ«ò¨“¶q ¨� Ògv‘v”ŸÀ´Í¾qvqõ›5…~n�âq ÙL�·ãÃÈ~9dʧÇmR7yn†ðt@® ‰ÍjKV¢‘ü(è<áŒOwwufú/¯œY;ùp®ÌT Bn°Å~dC+1ÃàtM<€G©s°9Œ¾£¬©ð“¸�ýH×ä_eœ½A¦­¥Döì΄3g˜›HÅh{Á^� ’N h.\7Zžj1ó0Àºâ4¥`¿·•�#]≎»îÙp­l ¦ã¨Ì@=ÙÄŸ Hb jÂñ @·s`)|ž�òˆ]‰wAŒ\yÊgÙÏåÔâkÅÈcgÕÏý[%ѵ¯B].” ø©_•IÎýNWwf£®AŠÍøÚÆFªÜ,çæµÈÒ:¢VŒóYN(�Ö,pŽÌË:óp¡ Ó»çþ‘ÕÙªòp’ßI5òÞ :=ÍóÚRso¨7ÛíZuñ,t¸¿Ì~\Óp¾)$‘�"¼Ze¸;<ØÌñÓŸÝR�V¤?7ãpìu”òžÒÛI›é´€h#¢Úrw®Ï]!†CÙ BˆÂ­†Û �¥×Ã9ÃÜï3ÂÏû®®Íl³ã׌Ū�ø~Àd/èAºh€LýŸæZ²3ÝPeö§Àf;ˆ6—mÕ&¬¨†M¨éÉ¿bÍ_(.†QãDª÷­XêÅgRÕr?Îü_IÙA*ßjçÍD5U,ªx$]ý\ì(ÉF“‡’ê~dŸG+Úï…óÇ©gI‰=Pm”¸]XJM K`“¸¤‘¶ ¢»�›ª89d…å"óRÀõË|‡ýQFœÙæÈŒz(póg·øå.&Yd(wzŠò©ôXà_&a׈¼ÍaAãèÜ;_nöüöË=ø�böüù<=-6é¶{·ä\tǸk''du_Fä“# }qé}†Ö*aÁAm\? ÖEšž$½ÈMâß;®®ïF}ä�†„zõÞ‰¢.c/ªûÔ¾ªP(qÕÏÚålŠsØÁÄ€LÚ“„ÇuN0è³w¯§ã]‡þ¿ƒ”?‰u´¯¬>ñvÍZQŠ�ŸâÆ‹ψçÐ|¥Òê·_†Ÿ‰A¯¨7RuB[‡%•v9ú¤~;Ú mb&Òþ‡·bMšÌh1À±áheaTðþrärŸ;/ðk`¿®ÊòŸyÊÿëxš0Íüë#÷´e�A=9¹é˹”ko6h8kR·�³3déhÅv6YËûßthüðÑ9žÑæªÃ½ïƒÙêuU¸‹é‹o.±~Ôö,w©`…ú9ô®ŒÍmþ~Ö2´mÑev4ÞHÕAÍsÛb�£Cø¸Èé*Ò5w§¤×}Óá�¼gq giáÃ7öBÃÆ�¥ó/øé\¼S¿ÞBη þŸ9^Ofl¼d´M•wéÿz\ Žß»áö-Îjò5ܧ¨)¯ˆ÷™ EBÓÄïÇ•~×ò.Ó£­m”ÑœXx"ç\l†ñä‚W˜Jƨ‘oÒšXC7Ç_ s™Ÿ£žï]V^?¼�d½•"î»À’ÏÊvÝ)ú¸=¥) C&]IpÁ#ã�t˜.=tšlV1ø\5DÜ7Ár—fßw…sÏÛØê*µWÁ*Œ°£¥4˜m\Ü÷fë (Ö.¾µW•Þ=4»ÃÀü�Ùìe.ZÞ¬ËÔ'Û1ó@µ9ä§K×¶® bMnE¦QL¹,ßa¹æŽET à³åëHµƒªÉÜôI�ÇÐ0vöós§8íÜÏZüí�”ñSÍ>ÂS&”ƒ ÊUˆÌæÃï�\ýHåµË8S) ‰Axí/â=EqÍ\=Ù0ø{–šâòœ;´^æ…o>�ímk±ú4ÌÚ¡˜wôTŸYÚjItyðÀ~ÙHûŠÓ�Ö3(V.ŸL9ÉÇ"Ûg�„Ã둾„Ø%¾EÔ'W{faô8@ý~§ŽQ«ÿGüã€õ]r6¬º OÄ�ÕºŠµµ ½±U÷š^"[½íaømôIå`}¡§{z”O[(pĈ=Øj @�òÓãò2K7Ÿy!s1zY3üQXc"]aŸÿ ï\¢¼{ý?ÿ½ú!®,¦ú)×N\’¯xveÄ^+M¸#±eMÌËê¡UÂå¨Â0‚ i«g­Œ7òf {@wýìÕ#f–F¸…‡„|Bél¿~¼SúçM󯀘’)½.=ý쟢ª»ÞÄOFø÷ : ½IÛgÆB�šEû±C¨Àš7sò‹AëÇ5¬ }oÉwß·þ(‹¿ëðvèqïcÙm“5j£hY.ðæÈÇòжݜÿÆêDB‰Ûõ´è,`œ±F»3à:ÝÎ 7›—P$23çIú㋚qÿ‚Gbvö6ÐÇŒZ>ûÔ8µóúnoô¦YÃ~d«axµeÐø*Wù Gè¸æMÝŠÆPs_ƒþ_[–Ñ‹ÖLöÔL`ÈKÕcno!Ξ\é§r¦H`òDÚ«W&tg‹/Ê_Ϊ.úP¢eÝ®SwMéqà ÞHDÈBnI‰žƒê1³ú*M°¾{èÉXé½@�Å´&oò.ˆNçx7æ²½–QGš’|™,š8ž ö™ƒ}:o\ah¡ÿÆ×âxÉöÉÐ[¾QïTJŠäjg¸ €�AškMá [Re0?ýñs¡0QSÅ©w7þ½wî–%x¸‹×¿2 ï&ÌÅÜ›Ÿ‡ö÷^§5ÎÖ‘8]æxjnr,šîç1È€Ÿ@U«) t%ãLüÈ�á%S<÷€”y[*þõ AÙ’õ¼ H°gñ”Ó(kãù}×LZGÿàß«-jÁ½Õ@]ZNÂŽÒº<¶áòÙÿÑ ž쯦}¸ÀÁ¸¨0ÙöQh£ÂúÖø4ìºhdtZ¦}Yÿõ…û¦ª¡ø“èm–�þè%´äžbMÞ9OÀP|¯ ¼DÖ O‚C¤Ï¢rhÃÛ×á}�~ç˜Gx•}�gcú ,Q[–l+ixX=ËÑdø�-L¤ÔdÎM½ÈQ‡k¡’#œ�nYƒF‡Æ!9rnO®ä,ýOýíÜ�ýø{ó`¯R ŒÀkÌG–Åð"„aN8ÁòOu¤äO𚬴E¬‹3%Þn Ñ1R#:Éù°Ù_±© XËЬ]¦öºÉ슼eŽÿ§E~Pšè‘øméª-WUÙøO‰¯&å,E $ª‹èL+-ž«¤îƒ´9HØ',‚Sîÿ9~Ãm�òÎÂ=Hv~bÊYI—òÛÎ{[ì=•‡�øLEtŸåÊz?¤‰W͘� Ž‘pýÚÌ×`¢¥*µ| …ÿÒ\Wò�ìÿhÏí,yP&䇧 ))ƾYõˆúlp°wÀï‘Zô>Jp9(}ÔCÕÓÉñ‚¶!I~À‰*�…ÄÀšQl§l:šå�ؽTɧWÔg®EÒ+l:È FD=÷l/¤FäÚ åÎJ[}ûA´U°Ë?<7D©ºí’ØN"¯šÇQ_|ø(’ù.š”ÿÍ;W6ÒEA^bëÒð§ Há­4ƒ>/ÇšK£.nö ›\CPû�Üe†SîÖÙ+8Z'ÁèFŠðÛ‘¡ ëÆÛ  l¾J¢±ëc¬21’šx¾ZXIËyEvŠHÀ„·s‘~™ˆÃ//Üvw†ã–©Ý}}ö9¹ú!ñ@BĽ.MÃôY±|ª 6Z6@|‘zgçï#[¢„ å�®åx8í™Ð4†Ÿ �Ç´Î}Ëè@Iõ·3& Xa y³ô“jYäµ{øŸ�ÄÂpXRjÖØN¿qðN�ôh“á»bPæ1½R³0K¹äq*9ŸŰãr¹£DˆÂÔïˆx~Ú8¸ˆ D¶ÑCˆýlré ¾¤¡ní`— ˜¯ñ£?ô¨SÙ¡ºvU_3´ÏõC~zܵ¥Ü®>ŽÍPì±Û�=¬ï„kÒÂϾßB_p‡¯Ü*îŸºÔæNiðJ€w+{À ±®‡¢½4\L§ à¸# Ä~|ýÙP:K×/ñ=ƒ«Ü®—*>!ÆÉ ï_Á.O7©w{S4˜›ˆ´ IþÅßq&ë%7÷Ê®áV”£UCúÀü Y­…¡ž.þN—’3W`'ÊÚ�Ô¿Å[í«¥£RqÔýê{þˆdóòòU´ÆÙòž‹²ÜúÊlT\  ɆÀIÑ!w‹ ݯóò‡vÙ0ÓÔ…Lƒ¸Ë™.Cú¥J£ürWÒƒ5î~òá­YÜzs8Rß¡>+D¤üpµ(IM¨•Mmÿk¡®¤«BJ~5áêu2ÙºÇK7q%*µà >â„”�2; ñ^ö¥á½|”w94ðÜ£2¿[oŠ«¡T¥¿TE‹37Udt`àJÂÏz¢$ä$7xÓMñ-IE^:× �^—”…<·ðg¿âqÄCOÿR%×§Ñ\TÂÅè-@�V5–¦Ÿ´ØÈVpã˜BX!ïîêr€ŒwH¹(“Š�Í*œ… ãùWOñ&h5J‰Ü¸}È4~¥ßCÂ2…s+,ÙÈ3=Ð’¦V«A•¯u|ÔHåÞ‚WÑ®ú2»?—¸Žèf¤%—žOY¤Æ0¿22ïÉYVÌpæJ:3&ƒ‘ ¾c¾iOܱ¼ƒxÃc<÷Šå•kýÛ„ëïdž÷±ù¥=.ý0¯(çøŒ\Ç$\¸ö�jïsV ø\fó1¯1ˆÜîôoÿ·ó_Wvu©ÄZá³–¬Kè‘›˜þÞÙÛ=Ù%nÒ“ëÖøŠü=ý¯†û"† ¡“P) GUVY{Jr 9C›EЬEõ¸tïú"(!j®·ÕglÐ �œ Û¥�¥f…][ËK³’Ù€òÏ7 òSñ ç8øƒ•ÇsÒˆè¬ÏؽXËþ_­ŽIæHµ±Ò�Âx¨+«K_rdJw°o2"Yþ‹®»y-®�Ñ-9ž .¥¯'»w• ^ºi˨¡øø‘܇mÿͳ’{t¢üqÂÞÌùk– q‘Ò–ºûMúˆÁ‘í1ÛJºq|£ÄÐ —ðÃOÉÜGyû¯‚|�·ŸÎÛ‘€Tß|ß%�œm5ÌÕèïr–2÷ÞÝGgšÿ2tL×k”¦ó«±ïbW‘‡ÊßLH0:êOù€ˆmË+/GZ.ù°#S¯ñ*·�~‡¸œ—øÿ÷U ʇ÷óÀQw™]Â/³Ý`ð¥åÊEÔë¨ø3}Ѿõ™*P£–%¨ÂË9ÊwJ•žå1ü Z´ÜÔ¢ë:Òn\¨›` ˜ŽÈYHˆ©ŽÀ=Àæ?mµfì#{P±â›#­ò{ïtÞÝçÛfËr Æ4óO|�™¦×†‡Æ±Ú]6Q-À'òþ­ÄÇ"ä|Š3¦j3î9jOÿÁ?2õ!å±wëº7Ǩ8°Äê¤.ä^ѱ¸Ë§­Ãi�çüüwíØõæU̲¶NQÆ´/áR"äò�Ù³s0žÜ5Nöýª{ठX_ð•¬)Ü@(‚h"^H>%ÞÝ9¢ýY[žŠnGÿ g¡>0:¼Ž :øåJWôú/É]èú:Õ¿o,Ð&xÙonøù-Å&Ûßê@©ŽÙâ˜iBÇ%;Lê¥&‹Êæûبf6ñ¦Ñ®ŒËA�»‡²Ü^+™h+‹Zµl6ñ¼•\æ“Ùâê2Òåá»±œLó/Ž‘½ÓRœ’:pŠúV¢eP9ÜPr¦½6ŽÅñuz*ˆ{Çg)Z²Â ‹•]´ÁB€äªqi}~³f%=ŒI%pŸeA÷Î1ðÔÉ”’²t��ƒt-�$Õ|õÎFÇãft2Ô_M]£_.cïͳï]y8×9©z›õ�ʺ;~3,Põ«;/~ uðõ4Tš8½*È8¨xËKRÅ#Yo0ŠÀÕã—.š´î�Þ{m«gŨœ0­68;âe•pXîá x¼lÂÅ6� jH»£²;÷´¬�W5'0z}]ʼ1j±çÍÕÄD!ã»lšpaaï¿Òw@C®_²¨_.“ˆ£ø¸jå×´€þKXl–U:ÏÅWXþO^ô§m÷ø[èNJŠ€Ët’D§=Ì÷4Cw ŠO'ŽGº .ïáM¸R›Ò©�8þä´opùL¸H­׊]"\¢ïº" „g·«þ�›‘™yõž,¡ÿgr «�qX¯‹ë/›˜3Ê>‰naƒ�æ™�Õ>ê$üö¾.ŽSqò"Ÿ,ƒ3NCýë¶Ûi’e:jÖ²é`€SYÈ”ôéÂyÙݘÓð¶Ú;!ÃåxÅùáý´#ö‚GzR´Ó†Sb, s÷kZ†jN”Ïy ÄÃÜî$¶ƒ¯X8ÒÅ~zÜ ·´®§ïËõ�ýµ ß%“vo†—²Fy€£�åÀ—�̦¯_/ó4þO5ƒ»áu;.¾Ò �¾: DôcK ‡^cSLÅ,‡Aük1$@ƒ5bl°¦y€›`G™�úõýäµûÁð2:ÅñLH$dið€%z³Â*EF‹C–“&"»½,tÕ‚‚Ô‰˜Ó9±¦ÍrF‰æ¯1uñ)¤‰aùÔgi­<ÿ»…Â~·Y–Ó«ãñ}oË'd1Ùã`Gy‹èO®!œ1¿aHd��ëæÕO¡³"˜Ä%|gbk‰L¡G ÍŽK”¥`ª¶RÝ"ùïª/™^…Ë®„È^Aá|÷xÿúM‰³$ÆÆ�]¯€ñx³§ôi®È-Rä£!gc…)C (jiø¦uL­Î×–(Š;§#¿øC¦?`Ô×Fÿê0µH¿*BN<ý†¾:ú°-€0w¯^T‰KºD#óò�ïá·pj„|Þ¹Ú6/2Ù;‘„ò‘­å~;›r뮹åJ~¼,õ‰šþwú–Õ¥,ÎáÄ'ÆÓ˜ç�S!ä¡aÆéG#Ó=#�mV‹}ÉA$é­¥Lõ˜‘› ¼žbSä„ÅýjVY ºì¦ðnÕÑìþÞ§8D¹®/ÙcÎF5¢nð³ÔÊyÇÇF_*±R8×y'fþI©‡MPfvyÉä¶#GX‡ ¼Ç_²HšÍö’ 3W¡\ëè¶Q«u½À†':Ý’ˆ�žþñó"?WóÆ](5¡üZÊ›€ËDftàm\·‹à;â®ÿÛp(Ò^HŸ¹uúó ¨k2j&E.oyƒ5W²¿ ÍLoAKš-¡*¿]þ²Y,"àG»íWH,0‹ÌN¥ç¹‚ì–z½�¿v‘�öi¸-Ê"ó9_˜ÏÜ­ø• œº±Ãè1>̬�Z1B8$äññn›Â°.MóÍïTì+¬ŽŽó‰-VÞoå¬jqÿè �í¼Ñpÿåbƒ/(ù?wR®³ý=Z¥\h&i§þú8Way€Ivèà5hÎcÉXX+ î—8µ¬RD~¨ãçëcü|XÖ…)yy*ê6‘O·4�ËP‚A,Ô ˆ™pÇ"­ìúƒ?ÙŠm¶}N v‘ ÖjYËH(ã¿™œÏì ¶}D2†pá³\Ð�}á½7<Ç4—±@6Û™\�X¿@VÿÒ£ki4­ˆ¦7ûŠú¥g+1ì—/C�1ýÚ«æïž_�ÎßG¨½ó¿ýT²ÍU@]7õ40�òøá»¹§Úùä¾@-½1ít�˜sU ˜¯ÚÏœû"ܨùQa2“…m·ˆ`d�À÷ì|õI žŸ'€v 5úèY½:Km~M®nœµ›òç†Ñ\tGíµè™«EÐßð%~`b¢e¦¿Ï?h ¯,£¤ðÙ^Ù�¿îŠ ƒQ#L2q�Nseäo1Ü5_­EdŒ58·°ªñrVFÞ8¬I¾è/ÊŽòÑ[@²ÕáŒÈyÄVaöG‹«zú,�°w礋—ßßëíO –>·ðë€7Óiãü6ñß�Ï»¹*§–æ„)“°|È`h\fAëf‡êDP©y¢rM¨×™.¦CA•ƒ?ÆåbX]€ „æ›á;ǘ,¹æ‚ªû®¯’‰ö{�°¬?޶ý3„_MIô¨Ô©Œ/×´ð¡dÜn؃±‰F™Gr åÒs”Ÿ7ñ;ðR‚/ŠÀjH’\ø†ÿÄGêʇeýÕ¡J5ƒŒX!?{âeÒ’Ý5nfÄ�Mïýü•z4(é2öÈÈüð÷©:pNϾ«÷îvQkh*îZñzþàí4tö?°1Ö¸(­t5Œ DZ“ñBÛÄŸ¬¹Á>"#-¼)3Ë‰Š³‘×$°T0€±¥_Õÿ \’qŒ×ÒØòizÚ\$_¥e©ÏHê�æmo-êv!úRh{Z2¿™Ö~bͺL{þh§Ž×q 3ÓB¯M§$¸Ýàòg5>çcÂý[›îºŠ=ÏшWŒÑg '§½fUq|s ¿B 0Mn{M6¿;õ¾¸Å• ¯õV+RêîsšáƒG-–�Þ]K¾ß ž½u2ÏK…7.Œé£Û®k`Å—‘ ʹ^Q<§ µßÿ'喝iP…XD" v=/êÏd0Û´=A@ó鯣� ½œ.óUœÖ|Dˆ¥htòlð‡uÃk¡³ "9�ì�ÛÉ8]¡0Ø—•ì ‡böMÀ ÌÏ6ä¶ ø.�rnÆ©Þȃ˜CùÞØ°Ð«¥¨·Ï¬÷ãΕ®r&Ýb4ð*„ èVƒˆî/=J¶u黎n¹ –œãóí\´ö V?_ØFrg]ä\W3`%üT EÇVÐ?Ê4½7E÷õsèì¡™-ÝMôØc öŠmÀº(ìÙ‡ñr""?ÁÁ´uÇ7Ñg úûU¡ò÷—ÓÔò{ÉGé~g®MÖPÅ{‚øÄè#*÷5lÎÛ¾U �ó¥â“† ¨6ØÐ,xI¾¸)¹³œJúúÃ|² ã(“Ày¦ØP&Ôî” Sá6Ô¦ì*£÷…g?]nuth[Ú°ˆ*Û5¹):§ŸU» ¨ú(};pOÂ4WÊ=“mOá§i,‚#p ‹ñbê>™xñþ&ea°`³�dÔäÇš2 VÁ…§ãry#ËDÜÕF GÁ²ë/Âæ+sˆ¦ Baè’ƒò™&9ý¶*�Ù¹9™âZÙ¿‹�ˆÆKZCÄž+\úp¦¬˜…ÿ±*uÑùÑX�²zÚÔe‹ÞDÀâ¬íËM¤Q‰7o ¾ô–âŠ�¤Ÿs“¤ f�˜ÇÔ+%ÐþåQS†Ç’·, Ä£ ö(™ÑZ“s„?å·¯Ö\lJB²—– äb3€®(»i9ðÎèxZn~8ÜèÏ7œÔcN ›¥œ!¯+rt­÷�rŠÈ’†åqmدá‘1xdD 8éÝê%„ªYÎ;~UHóÏ«[MÎy&ÔÃvvEˆú›Å€Ÿ:/ݯ…7ùy½ôa’ Y3B?uüÅâž(ŒynZéý‚®ÇUXÓÔÑ7gº‰Ö'¾ '§›qª´Y¾lŒSsK£¦›þ’v5ï*làìÂÙÄ]\nà)>}�új=_ž §}c Œ†µž·­ø°ÇÝš«úƒ<&B(²&�æ�sU-cH¾’¨Æg?r©êĪӘn�ýV¿”ŸÁÀ"[GÜŠÐ=Øi9µÖ¦áŽqáBØå¬R¯ øoÔw�K3ûaˆ+ÓÐ!òvpe~Ô)óVbè\M7Z­¶³Ì”Ìl"qŠi?Þ�dÕ§÷¸Vó)¾<2`§¨û°q¢—ͺøˆö5ÙÌÓ:sq4ƒbí‹9ôšbÙV¹M¼H†�¬¸9ï~y‡™9 NkL§Õ*ñ—„ ÒX$?5ŽŸ|ŸTA&å_ªráBlúŸCWLe _•_”'Ε櫲çÜzôm2¨ÝJ¤¶Ý�ñ³�¬ü+æMwçª-Øêˆ3-ÑPÈ÷y=SÁ¯¸Ÿd÷Þ×÷JxïŽ�†w÷nòTöš(ß.¯ñ»¨=­jßU¼pÿg@IiBSG|¥3óeÐ-“i(ÁËÌ'Jü�î�?s¹ílÈ‚žÚµžµEÈqÂ’ ˜ÇyfSv¹^« ï‰_Ñ=sq;[úI\ç;/7ºv+L`�IIé¾Quuÿ.‹&Ï‚p‡¤×\àì¡„ø‚*ÒA[£÷Å3÷i·$¢-ŽT‹=œÄYmøî�ráAʲ•¼zï[*Ÿ­í^gŒ)ŒÍoÃË_�qÇÑÌ5D Êø)‚_V)Cáíø!—”ܱUø‰›ïë°£V‚Û·ŽX–Fò šìp«{Â0 B!`J4o¿4û£ÿ¸‹Èa.{‡`¦Ø@ƒlƒT¿cÓ"–.l9,ƒXurRšÄašµøÏû%ígrý$©·)ç±Îãv½¼n‹ºª‚×&LX:&èá»9(W^êÏY„.òʤJ¾G v7äúÌñ˜b€r±ï<|š;ņªê�±Š­Ëõ e¸_/ô¿û{|S`ºKè=î[ª#iœ—² <³Sú/Q…ÊwEmÍØ›ev)æîþÔ jf]8L³õ& $å ¥~ðP4'!t�fÆ™Õ(2›a†7¢B€‘d)‡ì¨ÔcFh¿;е­�R8›‹²#XFt‰îSÈ‹�,ÄÓZÌ£p�ŠjˆsþT²¨pòNpdo#"Ë©¤WêY8ÍÔ*1jGRJKÛX)o \Ÿ5 ’¾QA»ÖTОÙAåÃÆ%")l‹X€pÜcµÒ_Ê$ýsÐ!žëãFÛÖëÍx/!¼Ì}´�ªÔîÌ9gµô ,':ƒ~!�ãp§%fS  �•Ç?u²24]^Ä‹òŸ"Ù5< )XCæµJ(Qg¸G#ÃÂ�¢7¾R?âm¦¼Wj.îÊX?”U¾ HczÑp�Ó}ܦ°ÑuyzЏɻŸòübù‡¨L!ÑXVp£bK(~”:–n ×a”ùêu: -Þî{î…-µëñ~.QG¼÷c‘ià7ˆ0Š”ñ@![æi€Z¯æ1£'¬kêýûˆüüky(Àe¿Ÿý\xâÌk€]ù’èÙGu< N[Œ' 5mJ »þ. pM1{vyù'Ï£ó^oø¹4| ÿµ[*¥mB´8nâڽƭ. �Ò´ƒvV,h Q¦ uÈ´_2â;òÀÉýQ1ÀK¼È<ùØd#ðçÀ Ij°�â‡ţH­µïnF£ èIF³Càºt¶A=þ ïÏ¢”»¾Ü·ãÝ*Tx½©oÏ÷+ý *�``m5ëø˜è–?7´¨“d„¶?ÙuùskÑ»¤7*•>«6Pè¹7Ã{rø…ðèxcuO[iv`.ÖÜïÝá û6Òæá¿ÿl9ÏIz8FTwgí†5f÷-Þ^, %F&#ÙdŸ»Ò�úñèÄ€ÐJÕnXÆ-^kbvC®¾iÀsH%b"Xµö |.ÊYØé4È‘¹kÐÅ¥ŠD³Š�¼X.Úøä(A÷a%"£uÞ Zvc“½¦×O(ZÀÜf p)턪��ËÄe©8,K4Í’˜“ƒ HÄF.ÝV^0´¶—ótpÄë<Ø�1+37ßÜÝ´À|ÑIê´¼£¡¦SÌ¥O…£Ñ»µý`%@[ `&;·³ ¿ çŠÂßZb>9¬úîœç Ù… À×Yðã\„ÈØ!hÊ®i¡¶Ò7vD©Ëµ‹»Ë¾ صèÒxð( éBîÇž¬\5œÃ‚@æEö×DZ¹Ë¦L®<üª£R!<1. Î8zí3µ`N£±»Qgéd©öð]ëXêñãN˜Ò¸^±�–UjBIÏ©½Ø°ýçµWłʲp&ãM¢ÜŠ&™Jb ë®lqÄ‚Ïõæÿ†�l|˜šÖ†Ø é¶œËAÖu ‰ñKõ{z¦ÀB³È#Ö(^ËA ôÙ��ÜX: `“ÂÕ‡HÖù\Ùú'´(±!”hÒï™ Ïÿnâ`ïÉŽm/.Ñø;+#'™1©¦ß)eºgó ;ˆªO±Ú:Ð Ðkä˜�ÓгÁõff·GNËW©h“fôÀ¯*Ggq‘[ÓÍŠ¬S‰å¡âÇQ0.’=³‰uÞš‡—‡Öù?ãÃ^H_[»U¼�}fž´WU~¹„wh[¤¦HÈΨËs£ñ5csí¦réöy•`n¿‹‘Z³Å2ùo4´s¼ê˼nóÉ®"Ð×[áfVmªXñõ‡ñ†,áºX¼Õácay¯†’æžõcX<§!Uún÷Š’êPÒß¿@Ò˜˜úÝ q)yLÁδj%û–ÛL;¼cò†%/7¢ä™F¨%-S¾ºGw®A¡TzB&Ë„CsV_µá—ÔÂÛ£¨7¼&,|-—¡ôWl|ÂÛüèYZ¬ÜÞ¥™¬ÈZ-@š/4ÞL«¡ÇøÔewư{è(•Ï;)q7‚o�!Øç•-‹0yÐ)’ 2! SÇ3P>³ž •~ 8çõ°™P;×!/þæ¡ ¨Ÿ@5·?RÊQMøô)‰Ó‘9ôºî&2zYg¬põæÊ@ �p «8µ+(²z;j9çqmÁæå2rèÚ§—Å×WÇ¡†vm¥;jç2ß®Ãuõ·�ª”ïŠÁ¾~cßkP�ù}5‰÷ª‰$Òþ`ü[Ùå/~DÄ›p¯pOì[eE[gûºO½/OicciŠOH–ñ+¥:† Â-çþéPáÅg 5é¦îÌ�éo²šcQË÷³D¦EÁ²_ki´×†ŠEÞxÿtmKµsÕäáTÅ$3*´Ù¯œ­gäŒMP7}ólß9òGÅ«`æ©3ÜrÒÒ–j®_·>EªÚÈa ªÐK9£Þò)€ˆý�· p&¥Ëž´n›ŒL'€¼¶"Ö:ĈC¶ãe‰5¯YÎy§ÊË›Ã}ÐÀòD‹›ßô+°€oÁ%EÒäh´Œð?J¤Eû6œ&>œ1G×°*ÌÌ—Ï{Ž=#Yc9ºf-#ã"¼gí(ïg£µx`jÜ^vffZsgûI+¹ÔuID¤¸–}�MÿC½4�FœT?W¡ @‘ {”†÷÷Qp¥ʤÒgÖç²w%¾:¾q³°ø¢½1–=;`÷ä,^$ă GˆéÚirÓQºÛl“—z/Ýn‡&~‘uýÝg’ b£"Þ­Tä'‘ï¯úÕú5ñîÙ÷å*´p,âÈæ…O«Î|-ËÓHph6E$èŸÀŽ%Ð?´oeÔF]úêÓIÿÿèžÒûiÇSÓ’O0ÅŠíãé?å$¾ˆJ´Î³ìØL·—8prT¬¬bmv¡…“¿ö夳ÓÌ|¹c�™Ò1â1º2pÉ-ãýƒÙ ÁgZÀ]7@!ÊýÊ–(z ïçyŠ ´fõ·"/ui0úê�g@»M…8Âõ èÑY­ëæ/dDôyìøøªQENÜ\Ñm˜ €0€n‘‚“œHŽÓ:wSø^ÂÎ-ºÌõD-<¢ü Ï”ÚøD,æŒgLÙ·�¤—ŠÏn�xÞØf÷Cãõ ±½ã§ÏF±¯&+¨ÚwðõÚ‹î¼�)Šw¢c ›è�˜TË–ô–7±?3MQ®ææý^þ!2ž»7¡E„¨´e˜Rwf±X�ú‡£ÁõçkåÎ<{Åùál¿î²–Ac³)Kf-µ�'#P ~$›Ó’Fø‰jC�“¿¥ƒpůÛJ…>íkæš®¨š) cWÕiµ_`•;&¦ˆÍÜ›¿*�š´{ÖÃêàuÈF�¨¬é@»eé |ÌÖ@dCNS *3-Ÿ³.•ÙÒŽGÖ~ÏŠa{2ðԲϭQwÏÀ�€÷¹½Y�æ/„Z _φ·NÌŽôt4ð¶jP•–H{0ŸòTÀl†‹U)AI½Pík¨½,ö´©NÎ'Y‘4­[àµû\Rvø¿*‡éÀtâuÓBp�'î[¹5ã^‰qÿÎYãB1z°šQBeöõLÀºâép�E(CÛÖÖ>kÀë^-™V˦žð�ÖÆ vxÉ^7Í\>dX@ fZ·#óÿÅžg%A+;p::éüŽík¤Œ‰ îXÞ[}kgJé àîÿ~ØÛ(g”ì“1m—Žbã8íÝÍNâÊP¥ü™éß ¶v“þ‡4 <]�]ØÇÞY#Oê"'$˜Hu¶Dýä…Ž¥Æ…@™Ÿ“xšo"Þ�±cËú±´1ãñ8F)ò»Ì^¶þxýyÀéÁ€rìJdYNÅêc¾Ã€OÀ§½1rE›×Ø‹|bžtfÀ½«€ˆTϧáÝÇéºúq2AøBÿ õzÈÍ0÷GŽ”8õØÖ9­#�ÿU±�*�ý×U†Qá àt!8T£÷N€%�ÀÉï®…eb+a”Æâ’ç¢ú7ãŽm¢j)ÌB"u�¾j_Ίe0]<+ºßl|—ʿ̬5©‡aKØŒ~/ØsCs?r¼[—F�ƒFgŒ‹Ø›¤‚"¶ˆmÈäŠ0³P¥òt+)9ªŸ|KE_ZxoYwuI×Ëûµ“ �s®î0$Þ¦Æ ñã†_Nô[«)÷ëÆBgL÷Îíl? 1FêÕõ¬ñ7hP¤§Z°™ò̕՟¿ÀaLo ‚‡#�ó.ЇnýÿNLy•� ìT[=WªÅdB89§ofìÚÎýBì•Úlä#àóÌu¼Æ�£ËÕ˜F†feD‡6)¤‰Eî¹îœ*ˆ;ò±ºwÕ�k‚¹Ë¤Ý” n¢…xÐßhùO|”/ð:õ( –S6±kµ(Ò+Bšá^;ÁÑâH¶˜ÊW ÿ«Mwªš¯òÜeå=DquiSR~�yN‡ #«¨à>¶8iu•ô.tBç~¥¸Õ³�Ü A¨y4â¥ïŠ›zc¾—m >|঻01¯Sw$z*ivú]ñIGdÚy¤�{ä³s\�#ÊG Ûþz®B @-×èÖ‰q�‡Z&2Î"ºì‹¦KÏsÍ9¤èˆ|¼C´ˆ¥ü¼/Ô’S}6ÆÛ-tn}q׳LNtõWoFbà<{%0lw7å)ì€ÿš¦›Ña»•®æº–ߢÛw9M@ÅôN&¥å?í¨s*®H÷L#©ÚjeGR�ÁŒ\�Óï~QB—¼î(Rróíó:_ÞïÂÚS¸¨L zWµ¾Ÿ§VÜëŽ$�;<èaé) êïŒr˜N?~›sJÊYí„àLýê5«Mç�ÝÁ•Üø8Óc…©0Ôn– i‡;ti¯‡ÂÝÉ%ÿ¿(-µ]£uÂtA9ë ±C·ífÿ1LZª~€›š•Ì)³‹b÷õe;­8C)‰Ì­% )*Dr@¹Ë@’65Š�Õ]×ýºuø…#Ã[~Ú%K÷©—_�#ý¹ýåæíð#n¥Îæ*‚ëÓp^VÖè÷H�ž|[ªþ·œaGÓ�B[úöt¥O$µ{Àù�Ä ûå'Æ1TÖY¨|;fdŠÊ,ϲ¼>K»ùØãý™H† j‹T®«1ÚÃ;žƒßìQNÜ];‰ÍAìšå¿cÅ»qk'ò(‡ËFû>x®ê:Ÿ]�¤aÇ;~îl0ÛfžB·)Á�Y�Ëæl¯Ä-«ç,Î}ü<�G«‰*? Ö£Iý�ê¬}So€S•X‡|�^,®ÅÂ),ß·ÞTƒŠphfËÖØaCwHÝ(Z‘.vñ�;?�iYëIÜN{Íå9sÒ"órñ›Ç• ñ"ä Ç r0wòì•N¬%Ïê}\ºò~V Þ-!ïv>¸ 禚-ƒÃì¹A²ÿíšÉQªß±UÉ~ýæ´m<›Üf1Ýhß¶¼¹ K1�ÌAªˆ:&0²+ŽêØ–Ö±X˜é£Z™ð¦*}¦ŒJ C4{O¤þàG&Ó &߇ ›YòVZ¼cH.JN�ø¯JRì²A+ÔÛ¬·�ÊÛ�‰ÕÙ’ù»¬¶PQ�v“�-fÄš<ŸÀî.D§*½Y�˜MžºO=ĺ¯Ç¹$? ‹BFaúøÌ-AzI�¼ÙødÁ` ç¶Žgr†¯+ÊQÔUY3j%�}Ž]-{öÿ:®L¯â‘¤uâhãúÚÃ`(¾ª»O®•IÍ ðÐÿñåyФª(3=”²žË¬ñÄÔŽþL ·Àîþçg†p¾V„¼øäb4L‹f›3o²I¬ï<{â*)ŒE¥tC¶çšg\,=h%úÊXµ×£åU´ÐÖ÷)îß�q1Í£¿÷²‡ŸîjÞIEñÚyy]p“ö( íI/ˆƒDn„‘ðÅòeT�~*»ß”{7â¸f&cÚq ø=\'—Q­ïxã¥uòýWLïRSký&rû˜z¶Ø*í$c<Σ�í}ÔKÏm“NPã ^Ëøs<ÓŠ=„¾±ì³+�,l¸®îYöÓ/êj²dõOЄƒâ ÉÌJ üŠf1¿¢pYi/é-å Ê·‹-Ë¿¦¡�\–. ˜yjR3Ç^œüT¢�P.£†¦�èºM°«�ò¥Ø~ô€µ•_üþúÆ™»)˜qÇš<µ¯möT8)ül”ŒîÎ׎Ɔø"p•Tðµqð—id–“²�¯ÿÆ0ùrÙ^bå*FHêÈꞢ$³û+YhÀí é£Q1 ¨Ð–UqÁ 㪽'ƒ%ÎÁÃÑ7ïABÛ™uÉ‹†EGmÜtNƒu&Ÿ4s eCˆ ÎQ¢=ã †Š^çz7ô›ªÚ°›Þí¢³6cD(ՃݭY1K2S ÇNMâpðdO›ªVí—)â M�ò’_ÕcdA1�dhlDþ&¸�pîâ%l’z[ÂUŽ’ àôëæ̬¼-¦Nt‚(ù¹«ÀëR:_‚µO¯6O.‡:YÞr ÐùÅJQçR²ùV°¤o7}Rn]!?È ½ZHé@ê‰Å‚�nÀNm-0‹UHÓS;»ÞΨ_w·i“HÁ¼àoÁgÁcSï±îÆpi²JÅ-ÔK6>óêaß !§_Žn�–ã”AÙ”�¸ðêfš[ùu°^IlÆà8›]Xâ†J»;Bë7œa’çG›~ØfÚ!à‰bMx\“ç]ÜA½K:ˆÈ¢ÇžÏ›n {ÃöµFÁ§)Y€æ|¨"=>Í¢gïDªì£€O3¢Ôv†=Öd«|}i뢲_ öM:`”Å« �Ń7R–TÿŽo×DÌ7ÕÇ ½I#8¦ŸÝ±ß÷£ë¤óùèvŸ¢>šæ-þ ½9·®¤{­ýädÌUMÇÆ¨½1ð%o,èáKBU° 鵬5 $ØØLmµ3·AÅ&êDO! ‚èþ¡©N�öÚ>ᛀ힬nGÿ ›ù @ÀhOê•K Òèÿ,1¡ø`¥d¤ªÓ̦.œ$Rˆ÷œÞïX™MGNù½o4éGD5õc�œLÒÀ²Ë`šÀ¨x“¢Æ·“ê§Ûd°G¥áx(¶Ân2åäA–§ø‘Žö”õ®±ù|à•3]y‚ûŠmºyûÅs×¥ý;ê<í\‰Uúä¡J¶OªÀv+ï?æî£8vœîè¯Z¼•RáÇQˆ ë8ö-~,à|Û(}†Có'ãÞ?ú}ÙA>tj²Â¹Âzn[GKÄ( OáU–lBÑ”¡8Ù%·ÈÛLXWÕ½tÔáÜdçv4l”L³*‡ÔtºZïô|¸ï=(û· PdXÖÃg›¹­%L–©oÒ »¾§ºv�Ei¡K ¢Í*û†ÆeâÒã8%7é¢8f®-Kµb­_bÛa!L„!W¬/îrŠT7z+ë“&Vì@G§b`�mƒgÓ‘!0B!èxa5ÂNÔcrSp˜ºXl{¡ÞúžgrÜ<8¸);rŒåõû„¸å¨QÌaªÚÖ¼†t•‚à&.0�GXP¤uk©óóÿb³æUvú”Æã/ˆÕ€¡7šO0RsôR“àügæ ÂÉ�öîá‘�§L„|ôþìlÐܨV²oSÔÛÈ�G~û”Ï­^¾Wó‰›ÕN¨p�sö+†)F_ß­fâh6l‡®Ø—íîfâÈ ü™FÖ§ŽQÔD• |Èø�k0—þ¯´ÅŒÓtY+‡ê›l•¼<~ráZ–%†e‡Leš$rtåèOa0 éFdü6íHù(† #œ‰É¼kî¿GF< =°è˲ʸèg[ß—»–hP ~¦É^¿�¯B•‡ŠDÙR`iùPYR³^–0n|Cpë*þ+»0�àyä†ò~•aðÖªxŠÁ‡Òèñ°=•D}˜vz8Ѝ>Nƒ ¢’‰A:äêÖ…/§Ø „ŒÌ ,p»lÖlŸ YAš®íŒèç°¤‰AŽúÍk ù–{ÂH¬`()ˆ¤¨�`¯Ð�RqƒÝÖ»~ÿT§ýuŒÛK᳌ô¾�ü±cu-¿E‹ˆ‚d¡\ÇŠA˜ÍÄQuc|T†xûPx½+ïõÕ˜óãE´Êò¡û¯‚p"™¯ø\9µ7ïÚ¦8§ªˆíR³cD6I=­'-�Þé"Vf�Fro™X­Úiôg5¶u)s/óMùR­èà9?ÕQ²|4\w:O{ï98T›Ë䤀ð‘¹wkìŽ%ð6£-(ÚZg‹ºƒ»q…‚¼5%÷CäØ lpá,²f²GQiê½É«¹[x{=MRê�� ñ;½Ÿ+Õ˜Á„>ÌIÐÚ5×ì‚\rÖ�•GJ¹‰ÊÝí¤8°w÷bË^_ÕD£[µžNLðB¡°ýN']�`§êI80ŠX½rGÿƒÃàVP#æ¦Hûvb8´È1)I]ÓªÐ;wOõäøkô/PöÔ�.3bå£e( 6¤ÀùŠ Ñ¯‹—8:l0Ú¶hüD£Q?”üë¯×^4ͯøuuIáAœOæÆ9ß3F‹öëøè+Bkçͱl¨«#ÍÞÒw« Óx¨ˆ��mBlFZ$·jòè.Ï1ÃÜåmª Þ©W�ˆ†*üjBrªäFº>¸[Hb¥;‡:0—!ÅÓÐXœö­!‡ë…F¬@(�&^곡Þ|A"¿®Œ�ä�î È`o7æÉÀ^þÞozÈsW¿Kfê]Òô…”>£ô‡Gx)y:’dŠi&m¢ËJ3Ñ0¡]f¶pÅ>¦‚BÞüs¸�…æÌ–p½úïF#ß° á ­¦ª¤Ò;¨¤‰¿`ÇÜq P ”µÐZ=Õ‚èáÍžM>Kf¯QÇZ·•ÆÖ#÷±^.×NÜ0ðdýÐlBvý¼·äRRfgðçÏÜ›¶œ¶øeÖÄü¥�ªìIõK@�xy§A�³ßø<ÃĶË�XÑb³ ‡kGŠš>>® kK-Hà×qð�ÇÐm0^ M¾¾÷5ü|»„;<Ù=él»×0üT’ú0-©ºä=ÙV±Ù[~¨7‡H©sÛк6VöÍ„®Ã}Œ.4 , ù¥4¿Ké_;nnè§It´�3†#Œ´ªødGýÔ4µð ýc?*ìæWê� ç]ÚéNÍýŒÁ5iÏ šb%^D?xÛË "5  Ù²;zhD¬5Žç†f})Шå³a›ïUMo©ÆiWVel½×¦ "Ïë’eRǾn»MЦ²tÞ¬AVGŒ9Ü3éhÅà �ôSŸMл§�ù\ý‘ñ•Ý/eP%‹B6@’OoWä^:?e„ ‹8RIÇ«Óφ”'-‚ÃŽŽY6NܾÌ團×E¹·)N�~hÓ4³•X$vœèŒM*“« úü­K¤Q=¿öúþ[ʪÎ6T-¯+¼ƒ!ðuÏTüµ0ô±�`2Pg¡4càÚì´*Û0 Lµ²”9yȽ^Æ|$û)3aª0Ýlø�ð]�“ÞÈ“â&óäZ@ ˆmï„™mªŽãk!•fÇšc.¡—áûACð¾O$~ãrõ{Vaß½ÿÆŒwò¯ùƒh-ï”rµ �ÄÞ±0 Â:Ùy×^ô¬jó7Á(ð‚EþÁAF™ÿN3qÓ+ñîÓ—øç¥ÁµÉ¹�¬³3þ½µ²c¹É;ÅY¶ÿþ�<Ò<žÞ]‡æM˜ÂTÊRåñ‹”o/Ü�Âk­Í¼U´ª@ÚS—¾?%mrË‚÷dßY{XNaR¿½8”|e1\n]OÉ�[°ÆjŒíö¤$¸®Zgµ.PÐÅ^Ó�2DÿÄWCEx$¢Æj‘ªm§âšÖòS†c#zÝ‘~j_8eÈÿØþ|ëï5¿ÏÕ„° "cd4"C·ˆ è“îXìšð²"n寓–W¨šƒAçdqýú¹ñ®gi§µ_ºV©ÀHßÝ®1Uô¶Ïµ�&VzÕnW\âl;�@ð^Ù‡PŒÍ�®ƒ<¾ÏÑ'Õ0uClæj'á;wÜ[Ð ó¨F|PW—)ܹzoª¾”*BÁ&†{Cö�YQOÈ v‡ $÷õT¶C“9Ð ,x]:ü·©8LÖDáÝØ"NKxæ& Ç“³¼ªr€ †B£Ò3$9©ù«–ï,<ÌdJ0îY(2Z£ gýO,@ä¿m²v­Tèuõ`akü;*Úµ?¢9`Ëõ�Òâ2¢l¤˜ý td)i*#•)5°OtÚNFÓ‰*í=óÒCJ@™»5ƒ²VÕábüóä‘Ï@Çbï´åÁá®:ä�æAšÒMáè™L‚ýñ÷À>í3ÇIéõk¢ÑöÌð÷�fx¿íNïc>mÏÉlÝ.ì[3�²ZUiöæÏ@Á‘2º'ÍÀοc¶L�k¼e ySéIrù×$wJ{)Î<ã„{D@å ‘´©Rvê ˜¾Dw¸õË*OyÑ›¾§}žµð}<ü¬kOƒþÜEÇ?؈_Ü¢ÑÖ—ú\‘±PØ›†Í¥¸�|Eß�}<'}5δáòÈÚÒÍ+í»`›T1ÎÌKyLŸÁIŽ�Û@,—tîÚ²½j¡ VuC'çŸÄÇà‚Aû€>>¦TF¤LšðÑø¢õšâù¾ú�ã£/äîïÞ›SÏV Š8«3*#.Ê»€þh:œHmB=5Á‰Œ†d¢.<É“´�(Œ±mh5ŠÕ:»EetNŠõ˜À�I^§âÈ·�¾„ò��ⓘ·'nÄÅáÔ2Ú"*×/PÌø&U»Sá\5›nüú>mL×çú;Õû—É‹¾ìKIì'v¶Û¹ ÷ïIKžðê`N-SØúú—ør1Æ��u ýÏÐBqoJÁ‚IÒw§7mÉpñÙ[«ÝÌy¹ í¸¿€ròmÓ>qkªK[BO@J¹Yü~ `G.É$D `=¨J¢öfšë×¼¼W-¦3ÊâxðÐΩoJ_É=7ÿŸýUbÓwf€[+¬eqŽ2ˆšª$[‹Äÿa’9Ù¬OÕÊIóêˆqí!Øã–²ÂFyA�‹iv†Îy<îçÌ_Qf)¼ÿnQ’=æ d«¾4EÅ!"B8ؼ‚Ï^Á Â4‹‰„Ãû臮W!ÂLv«—`¼=Eë[ƒ—¼Òǃå5Ž…û°‚  Ëâõ»@»A‹B ]`å™�¿œT6‹! °9Îpc•;0Ý) ¾ _Ò‰�»ˆÒºÿ´&Å£T ilíâZÿjºÉý�›y��ïÇ'޳ÏaÂk£ïe÷T®%¯€ã3'ÙuËQe’"Œæ2ÒÙbŒ…ýÍiæ8(”ÚŸÚ¸:Ö®ÙõŠ·ñQGx�x+íWÖ8¢;Hgñ–kØBâ‰1ˆýŒU´—È!à/ Ü2ûñ­z�®óVü¶Õ§Ï±† 9Õ;ÉLÕo%0—Yî/Ö)¬,ÈÆJ‰—ÐHŒYú%ë‹�6؈œTPDÜŠuÉâ°™Bã`Éj&ÔCÅ·tF¾öe`²0’ÙÞè¾K‡—„-ÄÔ6sÌ�|Y Õ'[r,¬�»dLL/QÀ§CØ™­×¤<%,aØè¶‰›/ž&©¯ 3äœål,nW³€JÉèj@ùu0T+;ƒ¨óß�Œ\//šì|«§À½`q÷Ô?T®(ÀYSŠâÌ1»˜¼2Š"¦!Y6.‰ô½·ëÅèÝíkï,]¨B@£šF„m‰ƒùqu�ÞÅK6éß½¤Bq Ðjä#²…Æcgá)ñ�áo .QøOºŸ à·Æ’²½)Ve"‹è�Q¹—¦c�Õl�?qoçX¨šœ˜•Yÿ4»è"µ¤WõAÝl\ç“Ù¿Y4"ú[ ƒv}9·þ(É#Ñ€à”÷·þ)ƒÉmʾÃÌït HĶK€„˜•)«ì{nt#‚a`ñ^ã š6-2W†)à(ÂÖíÉD™SÄ.™Kàýàgáøåë»/\†_ƒ¹V`A~ë„Á*åÚ^öã¨Wûˆ‰þ^Ù�è·%`™WLª¢ ÿ�öõø G›óÑ@'¢¼µòxeˆv¤ý›€–‹kçÐPà<ñǰ(/ZOAÐqiy6µÚ4+ò—º1ËÃS“¡òo*«ð¤ŠQ`ѿɛ^Áïù-5¿ŠÀ*ñmç�]bþBÉ`þQ]í¹äYÈæ‹#˜ý¡W§²2*r+…é°N$Ë_�ÆjE¶— qm²EùÁÞó­\º…�úVQ¶…sÁpJíßXÃб|n€ÈòNÍ­2³v+á+ôÁÔ Å’ó%èîÍé£a©O­\ýñ�±‘µY*Ž˜T6Å ü±òÃÐÕ“ØG>,Ðt7åT®pkjà~Ôx=¤�ßu´|B¯JÁ¿hÎ9ü+ÈŽÏè0м6ÁÏ_h­n`G{ÎpôŠÈrMÓ¹³¬iKà8�Å] ,øœ³¿=]Á&+ιhY—¹ÃošY6M§‰öÇDɃ$<¡Q.zøó]Q`Wtnúžˆí^H‡¥>m|<>Ý…Ç{ì]†‡}Âið3}+A:3®Ž,Ã6t«>¦ TB?=µä�c0¿-ƯjLãäví×PÓå %Š÷dø¾:Pqv'h~”[Tq3E<ý°_$UUà,“hOÇ~€k�rï¹;C wºž$87 ÅÊm„ŽÇ)r‘ÆZwàb˜mï ^ÄÁtÓ«`П0€–Bs™è€«lí>jjöUí!àOð‰s„”H¸m=Riª¯dxv½gÎZþÊ™U”_ Ì�Îþ³ú”zW]žç†8¤’׺0ð+âLLƒG›0æ¥ `Ê£ð©}H®óHx5VHÌ–Îï*ÐÊdÊE÷}ö@PÒ5äj™ayÁ—”Õ XŸiÿ�ånt}©“*ŸôÃ# 7\C3,,¡Y˜0„CAo¥`Vˆ˜Ý”§×¿2ÿbQ­µóE �ŠªQ¢ÁÙ™ m¼â“Ä¢€Ož«:Jü†Î•[ÛšÃ/ßâbº_|Ýeo×x‚,U}0ò¥`¤ ¿.`¾Ž§õ`‘piu‚ì Ì ?"óT¨}[2WÉ[Aß#5�‰âWßÊ�ç‹•¥­L�¹AYv—�¿£/gûlÖ>ž°"Äé¹s”$šÇ)³‘ i+HÆÔð�çDìK´³#ŸnGÿ™îk†<¯u¾P‹}Ÿ—Ëh«g7xÛÄ‚r­Ìœäör¨^{eÙú‚ƒÅ‘Ü�_[ONÓßg½¾i%‘¬6 �o'¸H�»IR%‡ðÀÓn“EùCÕ8B?¶YÁté:7˜j¿Ýõè?�Èoh%½ÑÍižû$½˜zjÄi?’"¿ë(ášø-­è줨øPÎv«è’Œÿð!N€Q¶ùØ×©M½@‡fhë+A/¥žÎ÷פùQ�#J÷pk1ij·4=4Jaâ&Ë?\Ü€§qò÷xHòvéÑ]C€+ á(›¨›–G‹=½«²Üfë]J5Yvå\ ý*‡FGôÅN®âxi4„ )¾ö|érAÇ `œlaI%¯A›5-dÊ`CÿýñK4;H¼J+Í/¼Þ6äîŽèÊÕœGjÆûòþò7 ©6}ò'½ØHm—›­Æ›ßrihbZøõ:éÜû‡8%GòlVU;ã¹4ú7Ë÷ÉÕMsø´t„§)ܱÆÂpFðÏêùK¶õ奦„HuîÈjõ«¡76 { ›�Ñ0þ`�DÚ¤�#uñ”\�<+hSð‚²%;9Âî;— ­ãtôý†È¬{#ZÏ ³¼,"ŸÌ%XÎõý‡Ês¥Ëñ�òÉ É&8¹þëmá¯9Ç·>i¯�xAë˜ßàÆI;Å=:zŒ±]"žmk)�·ß!Çë/ëhHü¡o¿§ ¹l‘¥-+Ø b@fš{9½ƒœŠ<“„Ì2gy›u|�}ö$AUŸ;X¥f8ªJ·ïÉÔ‡) 2¿ì~‚¡7$xᨃÂ$šFùõ¬¬æYo‹X²w›/ìf2&Æë3a{ [æ×²}# ‡ªÙ¦ î=…”¦tަfè´}Cy–˜·“vß×f’ýÜs^š'°+3':zyzöŒ K¸L‘9ÿÑ�2>ŠÀWç ïÅ{vñ”µZ\Õ-³CL.-âV §¯rˆô«àñáä2š×e >ú�wþÒ˜¯Îú–ØÕh6í†e䳺³¡‰ç=SwŸ÷®4ªaâ‹olÚ.�owˆ=Ê>±Áè‘äl€kQLÌãâqlÓÞÚLˆ) g»•Ø»;‡< ›âõË-¡À/-8âã¾%R ñå�4Ç’n"+ô¥ìnðÞ~>.Í#N ƒ4c>ÅÀ%a-YµéÿÔÆá½Ë±ÍKGw˜ÅÙ�Õµ¡4–GÞ­v È~ÙÆ;…›µøïq,!'ýê˜äŸ1lñ ¤õû !¢©õÿ´6¶ÜÊò0m}/˜3ûêÀ¯ë¥ò j$¬îÔywo”¹Øù!#MŒÍÔ¬c B¥‚­ Ëô—,1EQÌZeÎý rAž6%± ¶Ù‹*’ûá’*áõ¢?Z•Œ:WV´ ¶oanhEB³Š/Ú‰½”²…™ú(iàÔ#B&11Œ¾‘±¦…‡’’´ä‡¦ºq<}ÿpÇK¿íË6I^À¾ånœ™Æ®šFÍóÝ&~ŸüÖ߯Z0·ß¬[�ñ�Á#ô« 'þÌbô)ŒJêœcCQLvGS U�‚í:ÑÍ™gOa¢Ð=üóšb[oä�ß²ÍâM 褘 È#Ü»‚"�äWDq­‰z¤%àï† –ÙD~µ'JnROg1tHCºý[ýÄœÿÂc�¨0;Ÿ•Ýž¯£X|ÙôWRÒeFö(‰ÏÞó£³'6˜â"{m£xFôë²£`M„ŽN,÷ÿCã´wõ;ÝÍk+[Òw’W7¥ WDyÿj²’| ³\þ\ ¡œèêt$*é­5ÈÚ„Öúç¹³lĂǞ‹"šAT жþ“‘|âzµž8–”=R$”ºœ$·h‘ên½:0¹*F¥péY¾ðòÂÇm`ÁÑüŠ˱ÁeŸAø�ÐþÅ7°aMç–ÄçtÊc†Õy{*©Û}\mêȘ7Ì@ ì¯>”Gß5€�áIã¢_T×Ùò`™$J^� ÿ¸BÈXd˜ç÷«I8;UÞ¼à€È+Æ’á®L¸sI @—ǵãqGÐÅÍç+EáÙÊS¹JÀ€&ØŒŸ�â/(ÏѬ‰è†×ñèR_ì/¥ê x_Ô Hô­üîiXA1C«ñÚÚsd4öÆÕ·�”\÷+Æ«Ðfz_¨3Ebæcš>ª–ðo´pAóË5§tfpN &ùj ­±v"³|¨�|´Ö¤îVK†ÕŸ­Ï$Ú åAØìí p7¬2?3§ T3nnP�9¨6·@�ƒ†éØÏ¹$«È§V�•÷8VJ§¶îmR�&£èê ݨÕù¶^7P œ&±ž®­¸¹ÚÏ6‚€g]¨Æêr Þ wúïê,z¤Õ%c)¿ – ‘‘¾ ‰ W+ô�é3G2KÁÉÿOU¦ +^»ªýøb 'šp¡-½×iÖ£üãxò)ì®�(ýèÒ÷ÀRljo=Ln©¾°Yƽ*=Žq�%Ï(Ôú´œ†°åX+�ܰ+šˆÐ‡^�]Ûûì¹èf³Òz .§A²Ô•M8ôÖ=x–@°d?Ö7…EÔq¦¨ÓT’ž‚:»ŠmEwÈ\×~}òq=U3‹Ü,&LׂžFÁ‘(ââ¾X«0}ÎH5h²®¯ChcôÐùÇ._Ešžªg³ÌœI¬ RÕ� 2wü^Ž|r~NÜJønŽWU·Å¡l?!™ïÖ�2ªÊmÈ'·�”g �¸ôOòÜéu’Ç�s¬¬5ué'Œ/ñ«W•£¦%'m“œû×w\¥:fg²Ô W_×o„�>fS×D=4{KT'"˜¬!dÌF‚ç6ôf�ZÉòwôxgÙZXЗ5<Þ¹ ßÅSŒ±?Ïn ÙêÒàjB¡lÀµ!©ÉOgG‰y= ;�aE!Uî$f!m¬avëÁ ’r﹈º,€4P#¶Š5]h³A“0ñ<·†¬ôã>oÉY˶7>¡œkǧ»x@r�‘Ûç:Ð3®³Ê”n'ý7Œ@,;’ó ªTþΟ‰‡_•m”!¯’ñÖ—»htÔ]æ$Ö Ð\‡mY˜ ¼Î{P‹$Ç@‘×ÃKk/R&;Œöðw²Ð©Ä(±‘Ú•ê븗e¿uÛ•Íû©ž¦•fÔ×üQ·U Lþá,l4LÚ÷ÙŒy6´Í ó”ÒJÝiŽ;UM«œÑÿ9- ýf#ÏŒˆ�íæ‚“ÏL¸íTèú¼‘`<¨1æ?»È¾Ü 쥄 ¥�ð7€ŒõDµ—GpÁùù=¥Ú†�¢nXOË –kËæþ3q�.¿ø`Xæ  ý°?ÎY¾ñ»x z剮hË£j-å4Åûš}1³rý š'ÒÌ^ªP -lW�gÎn–+}ví#²D?õ=zj>™®Lïå`Éö’­¶Ù´ΰÊE(ÈÉ·A÷Øbœ«ÒÉrƒY^ª-¶‰ï¡´>”LØæ±%”Ù@üߨÖþÎÊy,¸SJ�¬o¾õ1æÖR±,I›Ã×Xµ{&Œ â š�®\|vŸØã]¿þñS¥!Ñ|/gFfÂtéUâG¡×^ï²X¶VH’ ö4²Ñ#�ù©£yx**uL­Ý5sKyή‡'ažlþfzÛ´¨œ½LnCf1Lp'¨™e“…Š•zDÉCΞ7…Ÿk_+†ºç‚‚dë/Ä”rš{˜fŽ ï~ŸUªf4Cu¿QæĉKëØåñìã�±Ó}àÊaK?åšxô­.,GÂë™<×k”>¹l~ë=2úáÑ ¯€¨:eÞ”X_ã#¿â…ì,,Sm€[¨xDúΙîvE­óÄb'æÈq&âJ´�²Hã.€Õ†ûO=I¯ÿ\öëœÅÛ.𤥠籛£C¼¬R�{Ú¯XŒê'@-:TTIn»òÒý怱“KwœZ“ìp˜>ûnŸµK"̰Bâµh±/'זּ_žòˆ˜Z¨Ã¼†Ô¬ï@J¬ªB…êz°Œ~HjÒxÙ=°ò5ôÁŒÚ …Ái1¢Fö&štTªFpk·Èc«›¯SŸeúÊšW©È؇aéÉ2N ýWÏXé´�Ö“Â;à5ÑœásŠìPPºÈB)ÓI¡d­ e’„* šluÒQ°Ò<†)Ù÷��:àC;0$X|ïY€P@$n«°�4æóhø˜î°)Y¹µ²Âçý›úÓ·ÊP졦HâðšØáDô¯�˜ˆÇxáŠiÉ�¼sdzê,i¾¹~`g·¯ t[ p 3CN­6`ÈQ�1àÑûÈàYY|ò+Yß®~ bw³âjŒz^ì;33Ð_}§�2T¥ïÞÚŒXšQq"3­wWšÓJ….2M²ßå`u8È(1’(˪#ªÔS®áPÔÍE�ŽDBxj1Xë8LC±Ÿ� í£-‘Ñ BÕû>Êy8ûÕ`Õ�æh%x&½k\–xÊ^l—Û©uš†–­ó…çâdW¼WR+ëcó¯¨"):ÝIçl}ì 8Ÿƒwc}ÉéeêíÒÐV—›Z Ú$W0ÚÎ!F�ƒºâYöÂ3ƒùOZáÆòA�Oµ¡…è#UB´±´ÓÀ`@FmöE. ÂV¤áÊsMAЮÿÆ/ÐQR3 -ýR$ÅU¹4a;øÔú’;š�OQ÷i2D‚z�Óµ¤![] ‚É3Mâ<Ì’hã@49`â�Ôâ5 Ñ®{zŒ¼ìùÈ{q(’úkZ˜ ×>è3 hÀ�daêáfˆâZíÂ#|âÓ.´0$|/Χõ®Z¿Ó#ÐtÂÍí@‡ŒZB‡²@ܱódp;íE-}â)$gGËðO—¥¥Pd‚­í ?áÛåÔ/õTì\,>ªwnìëÍ·{M÷sáo´´ŠGnÈ⸠˜³`ˆ¥AHòÛ‡OûÄ>,á[ð¹%qMâä-æHµãŸ‡Ñ‚wÒå±h–[C‰A_�òБbD¢/Ê#ªT4:ˆ»Çj$¨ÌýÂ[&+R°IvS0Œ YyÏ–Ú¥~²``#BÕlÄ{³|AûM‰fˆ$IÅ #Y#¹HlLµœAZG:¸&rúùM¸…ÞúŽ3*òñlºM·æ¡M€Äü+¤T*ßw'nžªœˆ,á­F¯¥ÏBŸ”ÛùÀ¯ognv%ýqá¿ 8A»É¦÷Ìà°®@åÐßxǵûÿœ´ Ãç+trO—W˜‘Ñ®•Ip�Ö&®…òyä5Û$ F…\¤ßKÓ óüÎ`d„"8Úñ7òò…Ü4|³*AËf±Š©û³h!¼»§v¹Kt[åôbNßßXlÓðIW�AÑõWmkÚ£ h›§UN%uE 'uÛ©<~ ‘gmŒ=HuC=#»ûU.ðCD#ùp�a0¼oÁ•’¶–eK�Ý—‹¨Æª3)Q—�õ,©bt�Š2wÚáŽrÚ>«÷Ê•ôÁØ6.—’Â+Ÿ¤ñèòpÖÆ€xþôçÛB¢¤ydy6k½ÐWº½ªL}‹Ûç¬_gÇ‚ÛêïÙ&ßùé•Pæ©ö5aºeéç£.à‚ ®YQ<ÞTzä˜T.¸_s&¬JôR™FÞíꌸ;‹Õô7±EÀ l¼S¨æ6*g„_à“²ys0ÿ9nO «8ºry~ÔúòM´% |bªãÖa¨ãJÛŸíI)ÚI‰“»ÚôÚ’Q[1ywï=ÚBD¶žBƦ1{ïáÅ͸ ¤{åjõI®”Ìœëe„Æï9€<Ëmù|þ¾ƒ¶µ`¼e’¢”zÄèûV•òú›&A;yóC ,_Ùê® *«3u§^ظCíÈ$¼�;¯téªc77ÕrðÍ’„ó<´FÔz]PÛ+�š�¨u“¼ërÌH&°›)UŒù½É¨ø½^”08ÉÄõºie5 OyÜ;óÂcV ¸× ±!Â:Ûô¯ pQŠ»#ŸOü�„4U°!ð­¥èE¸rèKþ°SAš¸a„U¡hÝÓ"þ³�tÊ-6‚½”½zR]1Üà5 Í"Dv$ö‹„Ïtº¿DôÜûÈ©i4nAÇ+É鮑H˜Ò'F-ÀXÆ/÷)RëÆ,÷Õr¯’>ŽSL-ˆŠicø}í¾�¬9J!Ä,õd_t´’¢*ÔÎåÉ“› ýŒ2q*ª¹Ú¸ŽÄ¯ÁââÄCõˆ`ó+)ªíoz\sÔg‡Ç§€ð¬¹¹ US=:„cM*—¹ä°blEû§ö÷#žŒ ��J¼•Ëæ)W™ç4¶Ô߈1KnE?Éh(JSŸ”e§°˜·ÏYþ&¥|Å¡»c•)÷ÅjéíTT×Áztz¥™2éÕû÷�=Î3*‰Î}¸p˜ZÐ??ª‘”Ý­» mç³þ�¸“ˆ¦›÷ê±ìB!߯˜P Fú¥“3|á!/ÍæJJžm* ¢ìrý»J÷¼NœkFd´�ŒÎ5¤tLJ5¡Ú¬ôÖ�í#ÊI¼ˆx7S@ÊÏþÅ’�Û ¢`" Xžªï8VoÔÖÇ:LBnÃ5†Ë™ÊJ<ó�V¯�i —“Uß¿yå�:uØ/K¯`÷Æ)Ëmº?Ȥsôé‚gѹȽ:^^ÿ=&i�¦úP,­2ä¥ùòIo|×V“¾óv�þ�UQóW”-Ű¯�öpªS¯ÒžAZôêoè{·ù4Ì•Žö|y.óÆ,¦: ôÄOsÎèMÈ7Ê–ù¸² gsŒÀ “öØ“~�f×õßi&Ön‘>ÛªrzcÄ:Î]ãÍÝb)7#Ë&ú¦s1ý\®Â5Ò™”ÕÃ$,Báß:Rxá7!¦ 22ŸËÑÓ­f }«u%ó×þûé*àЇä èé`ÜÒú5sëÜmA´âKÖÃå6”m?CJ`ayx¡É½§z 3Ö=º2þE{=ûxU;áV€WÏÎzû®ÕÂ3¤”õ;Á…}ùŸ1›+¡À3ÅȪ—]û8«ñ„¢›Ðþ¡J•#áÿkÿFæÓ`o†É‹ÀȲŒ[��‰ˆÑ*â¬è>sÔñQÆ�ä4=­9Ü)ØTL¬¥‚xÛ¡Ú¾ÄÆmÞ}ø¦s€ šÂœ&¶�ÌNF6dÃêêqˆûfS€µU#ó�?»ö¥Mëù–dhûEU)w—8€ä›¶gË覌TEç4',Ù¤Ø":~¡k9PPvÏÄ\øW¸PBÌ 9ñMÇè¼qYn¶–†[ `…ðtÑÉ6yߨGÀAÕÿÅæj¸»OSuú½à¦ã+�ùùqJ~s'¨7æ@‚M¥…~;j¢ðiñç,ün¢q.ƒ±Gf™'âv/)k˜}ætþ O‘t|H ¼åð—Ì$>Ò7O�?I‹—%�²i¤öEê¬>Ä6#–‚FunÓ†ëÜWvBÄn¡ÖÂ6.X°¿®ØøcÛädV�ÑÒÁÀ¹FHq¹”U./s£BŸ<>cÇs$á�©ŸÓrÓåæ6�.â@;ï™k¤Å*M¾'©Óðí" ï®E>ÉÔóÍÔ0+_�N'3Ü 9ÉÑè§Ñðž3CK¬“Õ0a@ôd‚”é&-šDÂrÁ‚lqkÇáw…‰â…äMO¹Û«\ ÞïJØç/Ú%Ÿ^˜¼´Æð4Ú/<î‡4â’dº`¢?ûºÔ|�ó±ÃÌ$È®žSéB~kè_WñTÑ�ÿ*+T>ðÂ'›BE¼§½ã« ýÓ{…Êì¹_2"›DçóF¢ÿ›/ÛžÂaÚ¤¸'f}%=C1|Mÿ“nT|vì¯TkˆBRK‚gV°Jµù&궩ţƗËc\'®´Oܹ¬—ìÚÙ¬~Ñò—„ÈüêrÌ™:žð¤/Ú$'SÐÚ*ÿÆÔ.ñ0üÓQ!šP.>qÊ0ê8åý%—|AìŽhY³;tæ)¿Áóbé«ùVLr½…ó!à D»ŽÎ½V1 Y0t•G�i‡Öðïöíßäëî‘sÔ—„ÛOæ10:Wtpœ$Yà }Ä›ˆúm¨<�tðºíZÉ�ˆëù›ál¸€°'“³¬ž�A°ŒŒÁ; cÈ‘ÉmêOÀî\¡ÛJO@Á2Oûµ¨ëjJÉ%*€²»<•J?©A¥CwÌ‚´£èP¡lÊ­âQ±;Å—“ªXK+„�¹Í íbÃU°rØüâÌÓ"6(·X JˆÙ1òÉ» ®ÂCX a£¥Ú¯ï°-Öo„¹0hNuJž�P›Ô ÝDùÌ‹ÐjyÐ#Ϭ¨k�YøSh}i—Ô¦ý °I¦c7²ŽøL†U4’”nR(XQÌ«æ1˜xæ, ÀеõÙ�P¥I¯¶ãxì9Ûµ/’t•ÿëP|oÕå0E~4i»D–gý †}³Â�P;ìwOÅçx·ðÚÊý÷ù7F»-?7Jt’:Ñ1a4g}?ys”î`ò¿¹LUžtKÁ§èuëã/Ø„y0C‰þóRô|QIï¦H/ §ãÐ`&Q&¿¿ÏO²®±™#!K˜’¼ŸOÅ4FüUWEÈÈä£çÈôŽw¥KN(³ùqS@…�t’†§7DÊF‘òÊ™•ÀB‹-Ÿþ�&r.Ô!(%ánØû¹�ùàS0n°Ð�QzÌDÝZ¡V +³‘pCRO¢Ÿtºk"Ìr[óÜLm&�,ØLã°Ý·²¶/ý%û(±Ƀ˜BqÎáT­7$ú—ŒB.uÁ÷,�˜Yý¦—Fƒò{j˜5߿ʞƒÍ»Š³«¥ýìÿ=d[‚1î¸-Õ>^ÒQ12»žyÑóu×’‹õZL@®+Yø’b©5[ìCS”6û¼×Cn5/EÜ®å±áÆ`«q½ d©ì�ÈsêĨQ{•œ {&\„°¬žE H¡q ó‹È bñ ý“ëªÒ(ªFlW �ä€�³¹´Ãßr??-.…³$úÿΖ€º·QÀ£íz×Kv©üi§H©½ �Cô»;sT�6eã¥U‘¯d ²à/$¢—öÞŒ™ ¦]#DãûÈ2nf�ÃFMÔð5Ÿ`—�®¨±z“7&r¸ß'Šïù_ÛŠÍ�äÓõóê)¶C3eÚTóXÆÕá{d¤�E¥ÐIóAÁ·rö—Ùöq�6T÷1b°õGY“]EvׯÓr‹�Ä’6YŽuJ±ιÂô`ÐÃ^øM½~ ¦ÿ&Áœ¨]&ýÚI7¢³ÀœÏ¢ŒÎ}Sª€ÔóÙ°áé£[ìu=ÞA9m”çxïóÔ…±­½)8``0Kas@ws{u˜èüÖêøÞR`©¬§g°Ãp|¹àÄ……†ÂGUØò°î`ù œÀŽègÞE(Û+„èPóv‚T& »ÐOÎÉ¥¿É ~"»�à ß#üÙ%@í:‰Ìi–² ɲäw€¯ÖjPÿ¤*FÕzäì«,[¤RC# üU8úVömÐðmØäø ÿ!€¾ìVÓK�“P–ù©²Oý³Î5¼X@ß;*¨•â*Í*W\(±íë£S⛟“½­.”‘D©&%m¶ðn«¢F¢ëêú�¶è¥N"„‚[æßÔ�™R¼@QŸb Kê* ”{ŽþéTJ'M¨‘žÕ¿·Õ.>Ű{Br#g2×üz÷à+6>kÚ=ØÖ øôqKÚ­»Š>R³”°�–"­ŒzÚ^¶DÏ@¬YÌóR;ò1�,${"d™NcLswlKÏc°¦¬‰àŒôO^ŽDç•'jÈÿ8Y/ûa�gþ�ÿ2À†Ãg3C²Â° |…ÇÄQ`[›k¨r‘~f©à+™¸¥ä D*¥àÝ¡iµô?ú@_ÑŸªZêLd#¿0Ñ«œjÄFìÚ 'ÇœŸÐÒ+9Ý!c€°k«'SÜX$�‚‡¾ËýåÕ¿ÙŸß|ŒÑcgƒþ3³ÝB�ê`rf^« Ÿ\Ó“PCWó8ÍîÛÖ 9Z„§ï³2ʱåºî�!äïé¬ðÔûR¿fû€ŠAdƒ’ü9Ü5QêÛ6^€Ê±��76ùa=rx'Îôé|õ¦åŽ Š�ŒÙµŠß×9 úÖsg›ªuÆ«]¸$Ìž‡Çd¢‹ƒmò.CÐE‰�“¦i¨ZÈBÌ0^(¶ô×a²ŠasÝÕJòDË)ÚƒQž<­:uj£PÙ}Õ=•scLå!ÌQ]K9GiÝj†þlN– =Œg\-…ñãülÓæ|£§g õGQÞŒ8×겄‚îqmëö–FhBa¶Ð J̳2HÃj)qëÁý.®ËEX<¬0é<é [6}zçù!à¸d­kæ1ûÀ„Ÿ~˜Ž¶ãeþD›îþSÚá…#ªª\sæTÀà1­°K½Ä@ë<}wgg¤7 › ¹; �ÒºÕRzº‡Èb°úG³‰ûû}ÐÑÈ W0�¿ ‡Å“Y7äÐLtRÒªiÄ�øU•"ÛíC�T~”!'FKW~5cCM�jð@†ÛÚï½rñ|‘h¾ƒâÅb¨–¥#£C¢c5� ~å)Mæžö-£¼0xx\ê$kÉk‡q^¹æ¶� "Jû[Ö!n—µ}¢ëO;Ø8&XŸ=QJgÐpå· €ä‚μ&Oêʹ®à�–YxŸÛ4B_]F!+󃾦’›0<ϰ.ÉQ´EÁoU¡2|3Ãð ò`Ó,¶à>³¨–öF 2ÁùØ?`Üà_Fž…‚š¶aåjÛTimŸÿîïPPw¸}Òu`ΣS1d?.CmšuVZU\×ßÈ!Èfþ*¬õ²³,b‰)%-òŒtÄŸ¡&UÀÍÑgÅI¹™àkݬ=|ÈR�œiSn�ê3}!|§L2–ùþH\h�aMò*CÁ�¸¾u?^·G„¢oC^j­ c—Qâ9Óœ`ëáÜÑŽ…�ˆ+Ìaœ®2�º5™Çì÷ûôÀíëâöçS»¼—ÛWe¡«”ý ñ0¢¦�v°oà‰fuqþ9Ž?¾{S'n8rãB¸�J¤9…®£ßwÕ­2ÿh Ïi/ µŸˆ%ÂH2‡¹j©†5pNÎø­b½ f±ý5Õ{¸¨F—S+eôdi(©x²lé¢ XÌZfÊpXî‡ñmdzŒ`0½Ÿs¶q­ú–g‹à sZK…j­©÷™1t·Ûê’„w¢ÛËògYîÆ±‡wÇaw{‚S:á�6^AÐkY´‘U&|O7B>�¸ zÃç�wPA·#(¸Šžã�`Æ7’lö¤Œÿæ)O¨ŒµÈˆr?é Ý ’‰ŒøS0¡ÇPv¸åEEƒµ²iÛ ×/l#«BüœP-‚µ€DŽ€WNûáXrP�ôAŸ3d”TL#ÿ Ë]úQ‚3j < aÝŒ´‘ŹàÜ’“�¹ßgpÓàt8=H±u›6b©Sƒ Þö`&“ãräsß {P»)\ùv–n �2°c ‘A¶LȘ¾Ø—³_o =7¬(nŽfxÀLD`ì)y'Vÿ^¯EDÝR"•ß/››Øcy­×†»€hcíM¶3«“Å6¥d‰|¶íó<õ‚á„Ê/ e ð'ÎTðØè•ËÇ2î Oì$^Œƒ²S» 5ÏÀ�†`™Ö‹Ò9ôŠý¥L3T+]Z<ÒíJ <üjÉþÀ­ŸTnGÿ39’ìÿÌ©P…Ga‚\ÙüÅn ¯ä~"Ã¥è#®ÊÄ\¯Dû_Ä~ô"“â»áš$ÓHÒ‡¦CÒ ”RU?ÅŠKôu3I´â–爚]&@�“/¹+_´¨áó€ÉZ�Jš³šÐ’ pñÞI�ë£j · áÿ†».dѨg%\øH{tœLÍwšF£7gWü‚@߆8�ž®¨öµ“Lô D¤W(2=öY1—©MIä�ai ‹*“dX N×üzp`^úá~Ü Ì¶1,D¹�«%­NÙe}Å÷º}º·¢'–¶XsBg.’%5M†Àhü쟻æÍC1àkÓœ–Ý� ‰ROÚ-¡JÄCž—ÏM�tE^Œr;3ÛϞ袧œ“5`–Öôwäå®\–«™pâÎÀ‰4â™ec_\a‰¡¸Nêhµô‰šÑ– 5¬…`eLõûˆD|ŽIûÿËÇ]Ì47>(‚,e¸ºMþ»^íÿ™!;¿�g ÑÁh�Qà°F�óXŸ|÷Å*ù¯­`O¢Q±Ý‘]A›W5-©2˜ x!ÿýñÚ Ç:6ná0¢Y×O„Ïg�(Ùª =)³m¼ÍƒxJ/oî Ù3®_­Æœ$¥` :bÈ:úlm`�´›¾èŠ,T$8Öo+ÙἨ úG^L¬�5?—;¿•(pˆÇ¯]W*„‰ t7Ó¬dW”í78§Ì·È ù˜t‰Ø"2ãrÊVÀËÓ¨”+ SXâ `æUà‘Í«vHú'f™&ŒÔʲ–½—’²Û'Êå¶vüƒS1�Æ_ÕS]’�ŒäøÏ1$L¯–¥#Õ˜3«6a;º”‡¡ÍW÷²ÆÈ䤇�Ë?è×ò·$W”|9>E(ï§VÄŠ0‡ôcÔýćŽC©€3o �ÅY‡ú8ÉG‚‹¦Ü6[þá•LGEtÜÇsÃ%¹ëH«ž{¸vr‚ÀT+r*„ÜÔLXœC[*Ô ßÏŽ�„spÙZ®LWM³B«˜aí ‰.�‘8nÄ+¹¤üQ<ª˜žŠàšôý gÙ¾SU¶�¼·’­D°$E`Þbå�tIäŒ?Ø2“¥»ñ‘¬~^rë§�÷W5*mq§/’ Ò„t³åµÖvZò(ß,<Þü‰<—½uX'‡ �ö`k'‚ŽMUW=à”°E½EÆ&3äÕ¼1»fâ8‡è~hÃ'Y�FìßÚ;÷;½È¨ÅuúûÀãx¸€‹´Jåžê¥ù£�ÜQàN÷•ôóh÷…,É öw žôí!Ó.¤@EcNÝUJùÕ´›RB܈RuÑgÔ³|´õ”‚¼nëÈqð¼[·×€lalô…ÃÛkõZ2ÉfŠ¡‡ 4‘‡ ›ÛO- ÂjÞ¿É ±À»ý÷82Ø:껫àcîƒ9ÜÃP™ÞÞçðµ=øÅÞ’tm©ê1_=i›ÔñQŒ"=‚ûí¹äp‡ï ƒ¼j¡…|[o’èúµÿ_¸®ekküÿ~lå (¿i/è¨i5"Q•N¦}@êÝ|б¶….„�¸’äÿcßäW·T2 ”?gÝ�kÝ\WSÏ£-ún! ¢‘Êïrp¾Ž"€‰xu–·³%ìFomÖ ,¦~g\esùKX‹|z b»WN¢È =¹§ñÚvÕ}u�7=ÙÑx!/5(|'ÏøÇGD†5`ÈES¶H26X�84P‰WuÖóOç ñ/�Ê‘feïx,Œ`øŠ“Ä.¹×ðÞ},¹ÂžöP3´™$[ß_äŒeɺj õTÄ#WÅGþÅ:¯_sU.¦²¸0Ç=*!Õš‰[kQQvøë™ÑÄoJh³<Õ¡Ù8kHÚ·ØòìØ¼°»uÓ‰½rwÅùñ¥Í`œ%xág¸é6GI‡¼€îB2im9´$�,§ÀÞ>=ƒ¬km?”\ü¸l“ÅÜäyTWÐFEt­ŠHø(ºcéëŒ?çUYÒ ´–QGL7cŒ42T¿©¹�?Í×AÆ~õØ…¶õ>~ë}K$&ÊÄâ,݃$H¼¹â“ŽR]­¢z½Ù¼ÝaVxÒ¾Šhn �Û¶è,M™HÙnï£-Œp‡õ&¨tðÒâƒÎTÇx¼*n’zfú¥n‡²qj‚×ída«ymyCè›×–Ÿ@óÓç›�z]™O–g§ô¬ŽaÅ*=Ð<: QΆ­°Hpm¥È¼\äj(ˇ*Puݹ?<3ëÈ=¤3äæý«€_åÅ àYs´ñ.,æØz²’-ÀЇơ€)mø\"3lG§Hõ;Æ-tÿ<摾”ä¹±7þÜ9 ~@ÿè¼,Å}æG û„ZL¢°m úiož6|:dõ• xÜ_H¶9(ŽQb…s¨S�Þ?ªlê°åÞãt¿v§"Ýì‚Nîv¾FÚm–¤…iš�ŠÖ>E=µY†­}ÔzïÝóU ÜAàúðÌe‹ÙŒ[O„˜U[…—ñc{‚?é[køƒh:­Ç€ ¶§†çÓ|kÛWÝèb¹+á¢xh�úP¦H‘´§œ1yR‚¼úÀÔËùÌ»�—·Qšž©ÆtNÒ¿Á\A›{[)~j¢æbïŠE¤®Šؾb(è‘ÆTˆ‚ëyp"\Æšuð¯ß²†k*«£‘ß³-6—�óN²*Îéî´NïÊP@‘ˆ”-êmÙª*dÌÁEhI´mpáB2â8öñ.~« Ç…(VƳ77ð<Ðäf~ï: GÔ+F¤¹Ò2£ÂåFNo�¦õ»ò`" ÜØ¸L Ò¹¥±P ìê„[Ô6î.TŽÙú^8a‚�&ºÁUÅk¤{‘�^ø‰K ×MÛ²�¦oxºfIt>›>wºZ·¿Ñ5͈¼ßN{�¹`_2y˜¢Uh€t�ú¸¬Ø•SX»e¾V7VTjªgé ¡L ÕŠxp? È’üíÙÞL¥ÿ|2éã�Íí¦’Éïc£¬ƒíûI!á`6b¾‚kÁ°›6:꣓`l*þâÀE(Î]Ê€]³i/ÿ‹µrùe]F|¡ˆ9�‡â½Ô'a×ä±Â¥C„S<ô�a¡ÑM$&j_6€‘.4Ü7E{^u*îIM•‰Ð` ûVÒQꄹ×=²‰À»«›�ÖÚÐ�ì ¢@¿lÝ©±º ýP ”éV½%g«§h•Ú£çkKÁ5|’-ìØEEÜ*iê5i`Ó+pkã””7«ÅôWHê§Tá Îe qêF3º%A`€çÊ€¾4�ó¨ô?x‰bº)Z°Ú‚—ëØlò?Ä« ù[UCY3*£s©Í¤ß]†íæL`ÚŒò¨-Ṥ6~I�nè?ôWÕ®=�b·…ÏYø` {:û#lWȾ%9.ÜŸˆl�¥Yjÿë)á4Ÿ„ÆŒ¼P^˜‰®Ø©iv¿¹0­ÊëR# œ ð. :û‰/¯#ÆA¨“¯¨ÂvÙpn‡ÎL¸<"ª=¿Ø×”ðFK\àÙ?ÕTË”Z¶5>kæØ¥�'ñ—žcüÐ+$¸ÆÌ'0§l˹ 04uÌ8~¯r.ׯ œ/þf“‘_*!í:Ìo—òÄ9µ¯@³¬¯â÷iéX=³ìt–€æxÄf élL2Slâ=áÔ59¡·OmúÏ܆n#ÚE³áB'Í8e˜I‘ Ws<üOôe/þÑö`†$%Upûf\.*¿Õ¹E\Äàùy $ØvàE8P\ƒ4ÖaxŠQ{«Ñ¦öå´ §èþ1Š8�S¢¸¢íõÎöÂ~¸÷䉬îbê^¹Á²qöù£Ï½ X#JVŠÀjžX¶,²À%Ç.ÎGÛü©•fåw—‚Ø ˜: bÏ“5ªÆ= páäÄæêk×É+;P.hšð—æBü@f0¹«¼f�ßH †8òÏ�¬'–z¿AP’½Ö1ùõ*dz�‰ä=ÔÒ»+žðpNP|,×É¥ºÃ–±'D˜ðþ�ÌÓÌBšË<¸ŽB˜á¥z’DEÒk\LÒk2ýpùO¬6"›ºœôâ(É2½°$fµiIøØùáFmmXÔ!ÐíQü'ÚŸ~¸x)ͤ”]^ÈÍ ‘΋W1Úɱzr‚ëî–ܯ÷gP¬u�^Öu¯€$Mì!¼ú}œ#­s„.›ÍW~ ¿mÔÛ¢9>†¥Ðáj,—ÈüÒ×81Ë=Øï¥ÅûÕ¾{n‘‰ÍSVÓOQyY[¬Ptq¹ÇÈ/v~R Õ:(\Û6©�†ÓàxxA_H`÷�d¡õNU¨Û†«Ã~ˆX(:l%‰s˜ÆðÅ �{Ó<5áo`ý»;xeÁ ¼K dPò 5븜1 ô¦ßú ªcÕ zz P‡‡xîh<ª@”'ñ‡~ÓÉõçëpŸÚxÛ¨ÌAû}yúGû>b C#|–ýÛN™!“|£à<ý//�ǰƒ*5Mq»L`[cºB ;;í[š´/„”•�ÌÞðåxçþŒ“Œ¦ˆAí Õ-ð˜hÉWJX©Kª.}NËy&¦Œjðj;mJ, ½Y×§éÈÖëçvžÈi# Tšõ P/y8æ4ŒÝnŒ%ÿበ�èSÆùÓ?eÛ?Ô|Íá-ùâY˜�±w©Ó‰a½Iõ¡ï¾‚ …b ã²÷1P²yþÄá@M‘ ¡OåAì÷‰ª³ ®O>î;ØcÇ/s"N‹‹Ö=ý}‹Î_vhÆ!zè°pë@oØÀÌ÷Ñ{€º²t•)Œc6�cðÜT TØôÜ�Ømƒh¾Œ�ØC6µ°SSŠ„Ðƒ8È‘àÜ–ÃofšÅJůÜIû°Å3¦±^$‚&¢‹]åÛ�©ó*: ÉÖê&éãõIµ`Ú"¥Àû'U³#5u ÅK¢‹+*ã2” Ê,7ARÓD±ÂL­l…&ìÝQævâwÕ½½ŠA�¢É"ØÕPesþƒTèヵ+;Qѧ˜^åHP# ÈŒþy‚ ©£?5v‡Þoô:.5Ðn¦_¬üÿ Ñ>Ÿ^—§AíÜà@Ø2 kOªëôI•à =’­™¹€Ë¢CØuT&5µþæõ2• *~鑸5I£¡©z€�gp ŠYì’ÛfŸ ~ªÆ>¦¼¸>šx)5¿‘&^GÏ–÷—µ”Ë´p¥E» ‡�ÑÕôÚv(~ÃŽa�T¼É—ßeɺoVà_—ΓTo-ºÄéGsó{"Ê…zô;œØ/×Í–FT„^ÇŒ§u@ESó@ðÀã Â}m,.•@èT¿&·Š˜ßaõÎðÌ£›ôB-dì¿¢&�tçXZ‡uµÇ•VÓÙ~–Kó ¥è>e ¼“5ꦾxõvÈìÄK^±ê6Ï!¹F~äŠ\ 1U.ެÓ´ãdXpމC6QQ€— �>O3ë!|ÒH� Mœ$â�üóZD_¥C�ªá.þ6\ �¼£l׉][¨”êöthú¼ÝŒØÂ`z*:LÙ™:ßôˆ¸„Б‹8&âÐ]S1¼v•Š ‹YËÈ*°J$²¢5÷K¶zÏ%ã¦ÚqÚûåÀïL{®"nâ ËѵûœGcÃÈø[µ&vpI–á»*K FÃñˆÑ매:=  HÈó)§å3Êj-çÔ‰Ji ¢Z/ወ¾I�Wy’Vo|*á/åPl-(ƒcˆ%߸×ÕM¯Ø#¸Îùqo­–¥H�D~”±&µÞ0Š—y®¾{Q •íÝîwú”$M]«ÑÜ]æi‡�ÿu]Ú™øÇ"°ó´ŽŒYøSB’éõ#I=Å84öøR!NŠ>g¡ÿŠç<õÿwÇzÅV½ÑÔ¦«�ôÞª‚•yšHŒ\œÅÔ"ªF¢§4Äúq…ý@˜thÞ°cR 9äHcÖž_ î-;FjK½ÜØ«Oƒ7¾r :&‡j ˆÎM¡\‰La­Ám4ý¢`áN¢¹†8‰ÀÈA‹�¸•mHqà håâ÷1÷ï…ÿ8ƒßɵ®Ç.ÆEtUO£ h a¦˜nNâѹí+ýÂ6ÈGªîæ¢W‹Ý~ô¯fãÁ@VFý*.Ôä¹Ú±ÿ?ÿ=ò´]õØÔŽ�Ük÷ìú�fÜ]�vuà4ø#r[x·´ƒš}þWRé‡#–”ŠßQ“+0hä‚6{dOz%V2ŠÓ(-¸•RÇÞÅÑüš`0ud0¯Í\HÔÞ™Ó˘ä4~ïñ±ÁˆXéŠs�‡ éTùXpW~2 U²×á=ÿpÛ$]jcU` ÙÑõBföøß%¨ØÊ _JßvhBƒÙ®²�Üž2JÄ´$ACÑ6id) UԒ压�’ÓU×uŠN�í aç>{/]Oô >â 5 EïÛþn_�Õ¬’9b û‚dÄs³ Ç»w–oÚÈ)ð<§KJTºqmp5ð¬Í.{f)…ƒ„Bæî‹,¢ƒ­(…�¸BÖár.Z·*²×óçL�Ú…ò§ƒß…J¯ÌB³lA؃º®èCþ° G[· iÐØ™ëïÐåÁë…gB ƒ@A?¼6´6{9DIëÄS²Í[}I•»Û½Cf²]< ˆZþþù¢x"%š äePäûŒü+NkÜŽd¬j¡ÂîϾ]áEk4€(‹×V h�ß,´�°ÄJQ›÷“ÃǘzKºh‘錗X“º8BÑ!j~K ’ò›Gœ/áÐ?»¨yÕ¤Ÿ@›ún'M{P•pKuC/‹i„â,e^0žñiÆv±A6<�†�–fDT«/(Ö“k¸qZ^Ï—÷n�PèWÿ~ÚW]ûþWà… Òƒ™^AèZ'€h!UîÕ¨×N-VØØ!Äfñ¡73žüÍUxˆîÛ`òöM5cýFË«L*LÁfEx¸´jÇ̼qPEP€ÂeŽ8(žwûžŽmÁn6™…+z|{J£zìÊ›rüÿQ€™çäõÀí,xbž±ò œ¦§¼l ¿392àŒSćîh ɆêHñšylÿ19ª«¼¢.ÓÔªÈK£öê½ÑdÕ j¶Éåî�Ò�&5—#8˧5‡8LžšYÂç„î!g+ޏºÀcøƒÊí•'ý­ˆJ‘hg1bÊÒæ8 ó@,(©ÅŸdÅ�ßuŸ*ÀÁúgrãýC|“Áå„ü —Â0ÞR‚¦j¼ i‘Í­ðÔWH%c{u$½åŒïú§gDÀ95‰í†°eÉî&¼úÃ#˜´Û•õ/(È«¦)ZœÅ’C÷«^…&15VÂÀ¶j* …ïý5ȇ3ài­øk&yõqœÏ(ߨB½y> GÛHÞÆVR2ÖL*‡ÂP$>ý<øp>¿3€øÞAÍu=—$dÛ`^Œû0à õT¦z—fƒúè¬$/“±\b‹Cr[3ƒ�¬ìþå ÄeS�Ï’ÀvCŽ$0Õª- EdÏ6;�ŠeV‰Yÿ!>©[—ž•u¤ïxnS°OU�yK‹Z=½†þvL|èåáOô ÞjseÝŽRÌŒOÈ?¬¶¤ª™±éA_{eO=+¦ÓÙA=¶ S¡„©7îÁSŠÑi‚CtŠhúËÏP(MK¾Ó"\¾,ö…¢¥Í¸5QŸœ�³™©·M_RŪ¹€Ã]Ç{y]†Æ©áj²1ôÿêÚþ^œýÝO1ûŸQT‡iOÜ|ó¼ÊM¡ ê~H…á¶Küð¨ó"ûÊ™Ðß=yÊR„¹©6~²êßòºl�i½^õ¸Ë��HR”¶¢îSyC˜p%–yŸœÙÿ[½’ _íÙ߃ù¬gÖËÞ~£Ðˆý…Ñâr&Â!:hžŸ"àp3fŠ6g:ž­ «<ï¡�Ä,òÍ2ËdZd)Ä£äη¸ ƒŽ~0 +Þ™š{Ö3x{dÃÜÆ_ñØSæ8�Ñ´·¼ÀJ_jÆÝÄÛêRMþ«¬OÆÓŸFÜÛ Ü#rëÎ5ø˜Éÿrû¿QNÚX ¯Ré€L0™}Ûœ‚ãó›ˆRp>˜ùµrDçN{B[5•ªi‘Zàé,O�}µeKH_”²‡òÔ�–ãåvG“/ =Œ>óá”’ù­ºÎëˆU¼}áº$™2Þë†E;L³^Ï–ÆÑSaZþ½Š¾\Ä2¬ªíkÚÇ'üþýæ­*èvÄbx“êŒì)«JÜG¾1$¢ã,iÃÇrϽgJ¹ý0)!ÂéA2^ki \HøÝuÖy$Ðs¢~M– =ñuÎò£«%‡Ù¿S龜ÝSTQƨ¨»½~dw´B�0*Í�¡áX_DêDf׉÷”›THEr§{¿uýÃypâï)¢uÏr¼ë…‡ý@§õ[Ä„K µ}8XXòA›G :UP2s ,ÒšÓe^ÂúÞ|PlOöâÃm1“pu:ê3¼ä(L™8�—÷#ÁñÙ¼óÌIÏ‹Eÿ·³ªû÷ þ–|›’ [L+á>ê~`Y2c”­;cœTiàXKì[õ}@ÈžðÊXç9qÛ¡‡ ˆ¯q`@1¬ E5hºõEÀg¸�1E¤½\µ‚²ÂûÕ±2Å8qÌ.ù¾q5c |<ÈÌŠSrèUsê'3On¨à»ë†E*ƒŽ»)Ù&¼Ðq�Ù‹ÓÛ. µvõ\J”eÅ…g yÆve³Î§=L6EÓÂT‡"e•Gýøûøq]¼ÐUû§~nÈǕؘwj òUg݆±¾˜�ïÄ×W}—.$Ñè§ú�¸ç³X’G–ðsÄÅL$ÊÈñÜ�Š1@»´i&å´Áø�Ër¯Èr‚a¿5D”‚ùAläÈtqA–sP ÚRBiöt9"¤-)?ä2WìU‘(‘ÛÿÈy)À§;39P®pÍz�µ@šÝtçOc˃6¾/c™Ó�Ã4ù¸l>~Ùóâ¾H^ÍQ?¶îȉæ³F‰Á/ K-¤9ð4Ë-¸MšÕâÏ"ðé%ÊAM`¡©œ ØNúŠä€Ù.î—ÔÓG-˜ 0/Oòy¡²$Ú³HD(Ì|R{µIA*ƒ¥éù2ñà¡`Nn «Òß8XÑ/.ežb½_𞡼SòsKäú EBúÜóÓ5õûfTœHç›ÀCUnø“!MGÑéë=œ8ꤹd¬e+AŸ™d”dðŸ Ù"¦òÆË^Àb ¡ Õ¿yà-­ëñ )r§Nƒ­¨›Ðwä \žÞ¯Ë1O‚Ï¥”=ZSãòãjP¢Ó›}ì¤ï[U÷ł֌¢¢­8D4–OLZP·Õ�î¾ì-dtÀÙÁœ›gœ-hÆÓ ãO:ì‚4»hkxÍ‹‹ C}îæàÖ<…× BòVz>­k¥¢ÐRÂg §–îîcB¹ét¯_D\q* "̦".L»Ê}¤eLb9Vp�‘%¤�ž®–"Æûõ#ݸêG­ñϯ¥5³_ä•3biG›ScuëuØZõœo*MJRÚ9}©Å£¬‰7¶ $Þû¿bî9ú,KÚº>Ç�|€1ü6-�‹d·’OgÀ Ÿ¸iÿ ¹”„˜ÀªÉjx¼ ÀW)c)–X˜o)-n@Å‹(q`ù�ŒPJ(ä—º­výS<½š*OˆÑoˆo­pÇîObé½° åÈÒã=ìTåu"ZlÌMnüa¡K™ŽqñŽuì]*ê&6À|½g@T¿ER©{ºN~8}՚؎]…ud8í,v/i‰E"M¾ ‘ú®e[ƒÕp; ¡¤ïvHPÂ#Þd¼›0c ÆñE„IY‹²:9ý»¡{ÀDg�ŽhžÎ’9{IE=û.E?%«%uŸ�Š^U ØVù¤Êö¬]®<Ði�û8•êmB‚Ð=‚¥O¸”¹W”éÞ¤*�ñCž7zI Ð+_3??¹’JæH�‡žŒWžƒF(,•šeXe(2�þvÈ3hÂÔ×=�U™vZ±µ3ô ÷'Þœ%ài °@6Ž]®-Áøibʹ8*áûfÛ“ì™@jªS> Êf¦�Ö1#nË Âg}<¨_›* ­ñŠ®w5gÕf"¾ÂâOƒ=©lÒ°î­�¥ÿ»'اÞé™u�c�EÆ£ m)‘Æc(Sš«éË8!î�gœCå˜d.Eå±ÇˆøÐK¤Ú Dˆé»CywWY>,SÌÒ†ì2X zd…%DsìH‹Éã^¾Z+}?ÙÌA鯙À¢=kX$5ÜvB4¶t¬¢Rëw;”Ïb|Ú6,XýüB0-Ç=¿ck÷!µ,x6ˆïóf8n¿ åCŠé²e>P’›Ž$8iÙjƒÕ®ln’‰y�T°¿¶�zÊvn OU"*Ìoø´Ç¨€¿Ä62ö%± «Õ {²¿Ê 5ŸºnGÿ™îkÌì·Ôlü@õ¦æ)Ê­ Œs©�:R‰€9üiÞæUûM‰(oÂeX¯< oH°Ã¢õ´ñÝ媼A•¼Lð–0“Õܤ2×ê[¤Ã€Ù`;šýä|™ðÃÛâ�Ä¿pü£üÅàð[ͯp=SÈ�¬ ’ð‘æt¿ê+tnL52÷•Sñ$ý$mß µ"�’ C%5ÕO«ÕG«*x�µ¼”AÆÕ¯· ›qswÜç°#ÍÍÏ+__‚Ü00â¦Ù¥ìàp�hˆ'ëéƒÅ�J84ÿ¦kr÷í¦¿]|FÖéŒñŸÐ v oñòüÄÎcÊì^jìöx2]‡¡«CK/‹‡xÃ�$§8J5�·[1�o:KøöB‚›A²Œa¡ Lëû*Eþ+6ÉâPq¬toaøQ²¢cƒ•߉QÞÇ•|¹QÆmx¨Ó²)Dæ© BìPO `´ÎÓ‘} c„ `ù'’É´ëiô|Sì¯AbƒMj-µbÏ}r +gï/s¶­…惖-àùà¯�Óð…SbÌ:bE*/¡‹¿üg&+K“Þ.Ÿæ²'3¢Qhî´{v4jL§š¿ k® ÷v.æxËB3FW“°Ý©Jœ¬DØÓpa³ûrü}@ãq!3Kß‹/otîDãŸßž¿¶}Ü�Y]ic@ ¥)]Á§ßZ#‡Î†­f DÂ÷%fÃ@l†Åó㤓 �_ÿtg—Y//¶G¸Ž×u9¹™ñ¼ûw�æB:›"KH\Š}º%ÚBø© ‚�*‡›…wxËðÅZ�ÿlú²÷Ö ïrvÖ †s´,òÖf? Áƒš¥™eì ¥ÚîÉSå,ËCâá`ýýU‹9„õó„a…ÇÄ �FŒ}™-\�M¿L"ÊAÓ�0µôÂ�ÉÒé ¦KÊ‚¹Aˆ:Stš­ˆÓ¡Œ3AÉ}d%Ec&¬�gTf¬Öd²ù³N%,|bC!Oq,Â̹¤8¢¡@ X ÃA›¿5-Q2˜ÿýñQ�£Ù3Ö6ò›Q|�‘äN¼üª•W9º´wSö*¥‘šz¢Ôй”°àPÒÜL™ÄMœh:Mwò#ÖRÝMÑ6Vc›ý?�î�¦XÖ©Ùè߈ÄD¿}+¤ ¥�ƒÇÀà†„´‚×Úbw©îÍ®>ÈG‡çYÀ?‚ºÃßT»jǵ ¹ÿA!Ä|y´R)µÇ||¥Ã›o�’p/†”&¾—XÇ”«´'kŒ=œEÄàD5<ÖtýyîléȤ¥UÃͶê Ó̼³9¡îÖH�cò9…>¾þ9s¡�0Óô5Þ8ïBWc­mÁôb.¯Þ—"´ ¿ÜZ›qÔç[ðÖŠíùìU¾uj<EG¸+©Å?�ô[«º6íƒ0ÿõKÁ©7êz�÷ÀCÎfèWåXÿV6·k2\¼ø™’=£5¥´ˆK[‹VH‡{õÇîoÙ N#­E!ú; ¬PާŸÛñq]3Î8@Z“(A6Jd™Ý%d,¥è NЂ+ë#/È �9Ó>¾Ø‹@‡ŽŒ©ü®2޹‘s%æ€PÙ¬R"B áIfðYŸõRÎj@רEPy°:§¬&‰âÛ4¶Ú×vHâ$žo4·ƒéôo <®!gÒzÚ[ø™¶B¦±‹.1qµ¿ ¡¾HtÃîml,@yfê@þÇÁÀyÊPî–b…G–ÅÊ4µHO k{Zã³®l-  "ŠÏ°ïÇxñît C1(AØ‹‰\ñÖH: n 0é|ë!6‰{æ…j +~нÁò÷¹½ò+/Eð²’+§Jh÷ç‹´î¼õJ/Jðc»!1ƒ…šï;nh�.¶/*àõú�žËï@N*7A/$…@Sкö$CÛœc¬¹¼VønxÌÐ,&ê7Nn$Íh¢‹ŽXjMIõ-UÃëøÎÞt“•”Kmaò¼£ÊÕH”Ö“ÅTó�)mҢ户•_¢¢Uæ�r˜~w½ÏÖÛå‹l0ˆqS¥�y<.Í2:ú€bÄ«ÐF[”eµ £J³�EÇ ¤~X )ʼºÎJR&ôu­¹'”#æŠßPRN5 Û{l=¦e‹®íJÓ•ã^}ΙÈÞ;¬Ö3öʨEúbJÃÔC#2D͹ri4UìûŒœ3ÉY#]Œ‰Ã3»[ÞÀ^(«xVR†,¶Óoô¡þÈÛVzÃNƒùž°Z˜_@”)æub4jd‚^s?Ù "�v�W V[ñž6œ�_o’=°‘]꜆…:z£�Ôà﫸Q0P§ÜncQmH9ýk@ÿTSÇG|ãl@¤Xäfj8Ñ%8ç‘Á˜W€9»0ž®¸ß5 ´Þ˜;RŸz‚Tþ°Þ3ÌéËÓ+B *î„ó:7³PR¥¢CüˆÙ[3:~Ú2²Üˆà7JúGàS A\ä�€¸Ýý³ì&9&ú# ÀÝ„<ó º8/™ãrÔV�Uþ&ÜçªìŠ@òé¡/@1\× =«Œç#[2¯ÒÚÔ¡Iéh­ŒôW®L̆yUdî�W`ð¥]™¯_ +ÿô(3« „CØ^:®‹1D ;ž%qg/7ŽØcßK9ŠÖµ2QƒyÍì@Ù8× †œaæ“ïhÔykGñŸp(´¿‘9Á§*µ€ùU–zס´À_EV TÌñ†F ãöö‰“8U¥-–õñ›·ÿÜ.g7ÜDÚ ÐRÚÛW€›NNÞ¿L��“¼qÆÇHе¬]¤µk‚$*%Ó#謕:N&°~·Çªw�W¨á9Êçö¼ÊΟ¢vÑÝï_¾“Ã÷ü¶¿‡Yå5¦§•æ?â"äˆê/È|ÐxÖÛ ­‰¶ñÎmí«%I²AöeùC …}«6vPï¸i8w&@k®/³\õ½/árÇ'˜†Ê4ÁNðq¹ø�5^H®&-’}ws;¨wè›èŽœ�ƬgÆ×ràfZd&ò8ø!v&(Ʋ 2vQªÓ]5W'3óΪíô+‡ ]Êo÷#ñ@œ{(�•EÂ"•wVµlôS)Γëj@“òõOËM™ ä“G=’x!ü÷ë;ÛŒ:QGÄ§Ø xwüW]%xÓW•*Óª4Ãs ;èm=FËdúʸeëKõ@¿&Ô¡kä¸*KX·¿ •CSZƧÌ-~,˜ÉÞ¹ Ú{8¬ÍY+V‘-Œ?|÷µ’]�(«£OVñGüO?ײޛ†ÀÎcq.?ËS'004œJY²9m�w˜ß&þµìGü Kë,«ØÅ2QÏ_¦ÞÈ�âã ëÕhÄ>L©ÙW`kr:2s`­‰{¶ÂÜ#øÚÎðÔ‰³ÐÉ\Q\ö׎]KÄν$’z!ܦ⫡`£�.ø4ÏÆÌ~ƈúï»ø�¸úÙ—†,«Ú],§ë:/à§ûQ"€ ×М$ÑÝs*;š1Õ:“•Xpã¿Ô—ù‡€ó,È�V¸ X~Í“M‰˜ |w½k¿nhNEmHúh—°‘}^í ç ?h"²6u鉃G¿ì¶q[Nøðƒ½xÃËdýëJÆc¨öZ`Ê\kö ´¦ä÷슜Xš­OŠœ CŒ¶7HÙ�±/zFI¥J`¹·™$á[…¸ב�kvÊ-4ø4ÓýeÞ~·�r г5výçÁKØ )8+„%A”,œßÀóv\ï{�È'¤lC‘; qí�¸Ò(;Ÿ{IÅ Jóv Dø7s«jdSnm§µE* î‘I''&u>2«Tÿ·ž‡�³÷˜óýW’XíðÏp>tzD¡FDˆ šFcä Ü�¢¿ Ÿ·jN5ñ:à†Ú¾9(ºqê™á¤eÞýLú‚ø¯� Õr ÛÚÏkHmX>E‹xgÂ,-Eÿ�ÿÒ‰4Y rØ×œ*’Tyù„RŸ¼�PóЖ€M)Zt-tÎÈ”!øÚ€å ;!^›öM¯0ýêÐÌ$o6±õÆAe@Ì„.åÿVÓ1Ab�AzXú’Ý<î>Ì÷Š›÷ÊîHœu(âù®¦¡üWù"¼z¿Ñm·iç—ïµþ?^ „©S;(Eˆ¿%ƒ*Nûpa–ÂLP :vøÊŠ)_A‰Þ"çDƒUü&¨„{Œ‚Àˆ¨Z–¬švsigoqýƒÆãA,»Ì�rô€Déóê¯J/`x^ê>ÜjgV¢„Ö]ÈØd=i»!òD ª éÝ”CJT]ŒÉôeåÊ�§e·-žòdyÓEÜ91~gÅSÀ ­8$Œë|ªÿL~ŠÞTôÀ´ÙÒRšä@J÷,M1ëãÖ»T{íÓ¼ä!Äj‰OÊÇL6{Ö©VÚ@t7Ë£�GªP¨��– þŽ…öUÙaeM-t‚½‘$nw‚§vÄðð [WŸøÞW;Ìs{ÁŒ+ÿÍÈÑ”0/©âókÿ|”ùvlÅPÒ°Sg´È�9GpveO¿¥=ISüZWTD1fžq§8m¿�1fX—"Ñ2{tBŠŒóÊþ 5í’¯¦)}Œ^ó^ÔpNurªµI8ÿyA€Vª< ¾ýÄø (ïQ“«TÙ@‡z9Œ*eF™,™·o—£ù™¶Ÿ¼î:Ï(’Wµþ3ÂÍøßIî¤@ôñÒÉäIÞQË—(\†ž&ûô•ãèo…('án×»Q~Aå{ºkÀ(&†„hРôÿƒvù:³åÃHf5‚ù¬g²+Âu,E85T'¨i¢(êOÃáneMqò1‹w4üš q"´(%¹˜Ä ur¢b/ðB7¯$žÆ?=‰Ü:¸S…ñ®µ/Z„¯Üæn±˜n½ôœìª¹›k3¶ž> \ÿ'™±™‰ê2ÍK.Ý*ÿýW ZJm®1„"¡«úìÍ<·�‚:1ÝØ˜eø’Ec¥QZ7�¬}´êùµ™ f©ö¹. Ø*:aÙÁÉÙ�'|(Ôçí]IÕt|>æ€*vÌíCd ývÌ€ 6¹¼qÈ\ÃGs -ìÎú}£ÑÁ7ÃnÙít4ð„ÏÜ0P¤_WF¬{ªO {j;\Öý³ò/¡ ”­ôSFŽœÍòGd²–Wl~Ž’Ë èÃ`ŒüŠ?³%ŽU�z‘ì€þ³`ð7ñ =ÀŸyÔ³K/â0[ ­³*Ð��›­âà6òæöƦ�í`‚˜¦i{þ2“>7®ž�ÊáBŽ}“v™Ü»/p³ÈÞ1Æu‘ÍiùJ�š~í�‘‚Zî`Þ$s«„¿J'´…¡+ŒM¡çºò2üÆ|µ­,fŠ œYFÇz%´e€sÒŒÿ5],Ün¼xЧñ´”SSçÏ|pûi½&‹‡l3xþ@J^»õÏâ*m¶çEuÑEk¢¢‘«ŽöêB8x®ìÖÇÂÐ>Ö$|ÙÜì°Ž™ïÕ/ÑÑÙR¯³G¬A§h‰ ¡ žZÉ�ëo¨T¨gÅ- •Éõb›âøR7œÜáOãáäç3�&E�Èú�øè½ Ú–fpaìe™ƒc}Ë˵6åsE¯E|»MÜäµ¹§JcÁBƤ¯Ä�Ÿ›&ô8©²lÏ!Qän³Š¡&îÍ_s§-\$'ŽZ5¡"Ÿã‚Í�ÞÆ!+î�ÖíLþöî9Er±1 «\áò •Tfé·Sùº¡_s…¯êt�µy3@üdv™Ä²|’ÜC’¡Çà âd8Ÿ,Å'MhÞðìZÓ»ÇÁ:²åÂØA[¢Jñ8dƒRL Ìs¾_þÛØ9A† ¿Üò“�“ßTÈô»Nú5ŸÊÆ#*¼òýåÈ‘õÑÑ3›ÏÅO�Û:$7‘ŸóV:•ST´×[˜Sq·fá˜Õ³‰‹‰Ã ;äú\‡ÄBs¹`KÛý iõœÞɺÙÏuµ¾ñ&•ÆV¿õÛîc I´âõ‰ÎÚw–›â3äSÍñ�þŽâ­åDž[Æÿé×ÅB·ì®ïšÂl æ+hîyäÃx¥úÎ:-ÑÜ볡Áü ØúŠoV½£Ú¤ŒÔŸ²§"M)c®Œ$7´u¨�”ö_ðÛ èzì¡×Göñ®îfINºlG¬ê}ŒjÞc"‹™Ž•0d;°Ÿj0§ ídŒòía7ëX²‘›Q.Gn´"šÁjRi ¼(Ÿ¿ˆâè¾åýhOµyÂ%à ¯‡Œæ´OBa5…I-¼MadùvLym`™Œ*ƒÓ>�sÝ™ûA¶9rß�ƒ–õM‹÷Ì•®âSþ ÍRÊÞÄ@Ò·^‹ªà”>Ý5l�î-ËÛûIßà$^A™âHÇIÃ2t­l£¨í"kvz–ΠЩ#åñ8’^“g÷Íúp�P B7Í}/"Ã#›RUût.ù¿Ñ[ì’L—*Ž a!ñ­ ‰–ÏT� |ƒPÚ}õŒØ�°<2�x¿Oû²_Ç'—N½Á*!(š;ð²�Öƒ]ZÀO’%£+ë•pÁÿX6ÁÚä«hê·áu7�¹¡ñ/GSDüñÙ¨ þ�Ý"‡¦{‡š¨§zWž�ÓaÙR=¥p€CL=Ly©ÑDµine½ƒÕD@N´o6ö¥ÞŠâé¼0@%1_X4¬jßaCꄚŽÁL�‡2ð÷¥± |Ц~f�B8¸òÈÝÒ“ãsŸ€gËk„¼ñŸ‰¹CÖ›^M§DyèWÑÀîKÑ)a³Þ{ÒO§Üâ©_‰Í—*ØÝ;•óÝi\¤+*žþåU ç©ÛÜä–÷Ø¿ÜâÐ õ/CH,T^�Þ.f†1¸õÒU‚M4ÍØ|ohBxUôQ¬Ùr%[ c„ö;`'àÌà‚ˆ»¥äÒ àÛ½°|i£µä:xܼo³×#É—Ë®[o-Ã;.ROU± ›æFÇ@k ��«Í*ÞÅ 8tæsÚ.{iM,e¹+A®k6ŒU ^‰ÿë)_þüÊ“thú˜iZ)»= áoøÔåa®÷ú YOÙG‰:jâ_ÌÌSzÏá-¶>Ðlj†�K3ãGÒpx¡‹yÇc;Bªmöè«!MÏ;ÄÆ±”m0¸Ñ‹;‚ø9ò³§6R=Mê–Ö×Wz‹�–/Öø œ©È@º^¡“5à m¹³K´î,{Œÿñ’î‚I ÷�0ýòbŠ Y¶Í5ô"00½Ãú ‚ð�³Ð�*Û@¨âý¿5X{�!;½cMÕ!QÑ�Æ”Z_Æ×˜ùJ²¦‹T#ç¥DL¬l—’v"'Édïh@f ¨Bb”VlŸ�_¬3`^\Z%;�éX_ñjïc?…ç�8«EU@àÐʆÀpÆ–NÀ†‹ê¸ ”¶–1»lT(„tú= qÕ�û`Ò-­‹UÜæM-)z|�AÔh@5€Éø"|0c*|xðDS÷-‚y_a¡OZ h(ðALoæß‡d‹Sý[ï¯�ŸçÕë~ùS)Ÿ‘Ñ8oD‰\p®£¡¶ÙgQ÷×çu…-ú"ßʲM•÷FÂ;íTÊ´yMÀ®~läíê¡eTò@{¹o3å~hI˜\7ƒAK�}wL’„˜3$¤±¦º‚y5sö¢zBè)HÑf¾\.º¥‡Ž�H‘tHu²veà�Ä)†Ž ×/Qh™‡|‚|N€êC,æh?˹»]+Pdï‚.�ü«#&mÛ…­Hó#z9ߊ‹´®6€9˜FO½°!p7%…@Ï÷×åYù=­VbÚUÙãÈôúÐqšÝS¿)ÛËw¯çJI-Q‚çqóÉ×xÁö)ý—ÆìwËÛ@Ž 9Ï.ÐoGÝxùŨ«\: V7 }�†åO˜ªÐÙŸ¥f-l¡Ÿ²» �g*]r"oø��Í-LWON9�•óS ?2c=}«�ŸŽ‘H—¡)±"¹þ–´º=ª…éBÊây—âI �+ÚïÚú4@’fm¹Úé©}±/ÕÊ"8(àÆ¢DSbu¾;´c³L&‰¿\�M ïø¬äÃò:à gA3 *Ùí6�DÏþ¤· 7�ßFò•:r ×ë£Z\–R¼á®&(¾çípsÚ­4¤ÔŸŒÄåk¦‰Ir ¨+¾ÜÿѾc ¾iíÊóåû­Ñé/ïÅþ^c¶Ý‚Ée¥€�-~…nÎÌÜ�ç„Ç¡Ã,8#§&Y·aãš­Uྫ&£—rPÒûžæU/ÚôŸbÛiëm“ºÏVEw95|ˆÒ×l2ûCí¢SµeØZ”©»œ'7—øHެô‡E+zP0Žá¬,•¢`�®²’iVÕº? Ì{�Ø)-ι¾**—2=ÓÅñÈ·³/ðØÞ/ØvÃI(¶Ô~DÒ@4) 6qè¢Kqü}œþ_¤ô÷δ±ËÚ¬êtE›(Sܪ¶o]«X åÓUsœ–Цl³.˜u¼—·D<=7GÈîÎ8™—Ôè°Ó¶�^ù9ø‚9´%myv6Ÿa¢�§…O ù×7´Õ$�œ¬ k1£bŸ>��@Ë4n„ë�ç–3:™þ“Ž>1é2#V“(juÒ^ö9£Ù\Ü?×é¹cvµ©þ{>s>¢ztX•ÊÕ‹H^K"+¤ý‘/˜h¥½§¹#�dtÓ˜GàN9.øãwÆÑB‹TšK›”¸»g¶›R³M4:ƇqG.غèûWïññ¶¾5”ûa<,1¯Áû�^åǦÏÏR.\›Ô�€¡{Y›•I)ER:¶ÎV�EãÖÒ aU–"u©.]9Ü! S⺥ {ÀAœü*ÊteCÿáÛ²R£W\ �+þĶßé\ôªà%û×µ`#“É0^«Ü"äA:fPgáÎæÂžhÅÊÑ<&±xÌy`fŒ5t Ïà™/-Üë-["KDNÌs.{2óF{t›Úå仿¤yQE¼ñJjÍt Þ< Ú{7¢è<ý•NÛ-+}«ÊW-fw�ƒ2"$öû}”¿—öéËê­ã‚Qp½%a§Íp+XëqžVûLF«T·-¨ŽEê òÀáGÔG )3››w:2½Þ ³FCxü}.¶êD‹_r ÀYôÀKˆ‰9¯²�}Öú#&6¢²ff 7£ô6$üÓ4i“%bÍV{ks‰ö¾ë²&f°L€XÂìê>®\³¥½»Œ“’ï]p†ê_Ÿy¼N7iÃÅf‡Éî¤9±“yú÷y¬NG„Ð#&ÔwVÃë“qÐ0±Y¡ì"9¯ Gsà5Wõc–µü}ëw±жN€Å(ôJS`_<þRz¡Z õì � ö)µQG QÏU÷ùïoY/T6ì0çKç&ˆšíàsìv2î¹á5Lw{š�Û¡gGBð�ñÁq‘^:ÿÒQJ>4ÀŸuG¼m�Ì™1>Íøžý‹F"›˜Q(º>ãƒñÞº¦ ï‘9φ‡–”Ò=‰ô‰®?tCëÊymÔ`¿x_èô¯1±”vÅq9Ö+åOCàµ�v¶m 7ìO‚}âüèz³É'UPbpþ£x»³ñÎa8(‡1„¨“—sI1ìÿ˜í%ÿrà»éZ�|l¾ë*ú¦;èu‰ÕþÁ»)ÄHµØôý¹Þ—¸ª¤¢ÁEfÝhâcô–|Ø`ƒ/iŠT½�]1<öÿ%Ò�6éJÐ7û³'3°‘6æ x#-Éâ{†ÄÅîz¾P:#ja%Þòÿ‰aŒ@¹Môÿià`]MÜ«R6º qpjªãô0Æ�™Xß(n�#éQ@`uðg¤Q¡qR aw<Ÿß¤ßK EÔº¤rB¥À××ñ®b¢>탈-<ž&HW= ï¢bÕpý<¹^§iÄàLÌ^�<Ç™#r%hPKÀߟþnGÿ™îxS�1wôg±Ò_ý�("}„ž›u`Žî†h§P÷!½hOöTõÁª’ð=E«G]’– ~ pö Qä*¨÷(<ær¹�[Á°i�ë¬È ¨¹ÙÂíݺ‰sã¾èãèç;}} ]ÃêäªÅè~ñ¤6pZ*Ð4œÕ4apðÂ"0œUÖÀheñèK%eQO&£�BéqR·š¦I›öå¥ZþÁH?¢ïxžÞj囀- Y– ²"óxm°ñ{î}˜¥Çˆ6ÔËýh2u¨|A›ã5-©2˜ÿýñQžþG‚ïhèÞF3”˜$Zp¢™é\Aë}ÖzçwšòO£ié¹”±Æ}›7Ú®Ñôûo_šìX ÄÝ¡—uꬌ¯È�˜±/arfî@œc¦5Â×”…a“H 1/WÞ¯tжËVÅÌ¡?‰al\z!Ù:ýMFàñ±{ë÷‡0ÜÑý„º˜á›!` f­ ÉGÈiaf•5¦-þ¼KnÉŸ¨ÒV䯰^èѾºÝ[¸§5êžî3ôÔù$»<´]L¡¹¼ ÆW�Þ|½\ ¯úÏGxÓ•×–{àÞrëÁ›Eä6U¸DD²̈‰M.zuÔÓ'1£!=Eý€Ö‹;Ħ'V»x)+ìK1 8×T¢2³Ï†êvrç&Å[õ…I¹¨½›ƒz°ýx²út{ë4Ñ—{/AZ˜/\¬ƒÎ$ó”L�•fÒŠ<Þf ~èch}[•1ƒðË­Dö{‚ÕŽ±“cJw�«»�ÅRë¶%•YØrój‚àÔ{qq˜!µ9_r/ƒ¶–Êÿ©y·ôÅ[Éwú¥¬Íê®×„¹ê-4Âëa~C·`ãøÀ#8NZCö.²$]äùóc§‚7¢í½‡%Ô8Îû«LðHüåW±bd°’-ˆsç�‹6ŠØFË.8—ômÈü�‚Ø"DX¡ºý–7È�Ϋ:h¥û,ãuš­S´:$ÅfR†ØÝ»Ëö¤q[†lC½?UéÑë¯^®ˆ`&ãpýï1[YÙ XaßÊ{Ópø#ºÄoòËK$TZª¡ÿíÞݯN;s(†ÕxHœY}¬·a3C½˜)¥AB$>„ló¯ÿ¢wÚ%8F??~Š'€ÐŸV+×…„ D4·ý߯·)c?ìšgõoŸ-«Íz®Þb¡ÎªdN¼ ÎË•‰¹Ÿû;VS�ZOøåÔ.¢›Ž,Å1MtîÞœå(ãk¢¾H‹ÜÔbíwÖ+òrª'©�m‡D2̇�ƒ\ã7üÙ0Õ�A Òy¯uÊ&tPè ³Û>>OØõx?ïv‡qÃY“–ÿËÎÄi¿S«¸..æÀNücEqUñ¡F7g±ìäÉãéVPMS™®snhñ‘^¥ÊÖ¼R‡$X“ÒÔåA¹£º¸×GWS¸ïã9ÛúºNÈonôѵÙèýÍž0xÙ·�ûrh w)äÙãò�6£ "éѳeìdÏj·§B寜¨!a¯ÐÞ|€j³+ú»oèå· öåäª�᜷&KBN­ryøat�¶;4ÄÙÏŸíMoDýU­ºq?%W›;Pa�ŽÎ¥BêßKÜ÷¿yäwkÑ]óVa}(Ÿ Se ü^Uoa:Jèp&ž,3J²\ÜyÑ5ŸEŽmaP¬á8\“×™m¹%ÌlÚíp1 Åï_µÒÓba’´X ³׷lûèJ z°! ”‰WŒÄpͦ¾Ê'á­%_‚c° Ð ‰ÍÄ%rQ<ÝÒg8Íþ.¤±övû¬£,ÓŒH@®y|ËMÕ–•?é8›7K׋#}¢ó:ëÆa=!ä«’ph{�ÝV¬ö&»‰bˆÈ�bþ4g±M‡\*';I¬"É¢�+Ú‹¥ˆ5h1h©ÊŒ©Ú÷¾}pJÛ�“F?ë¯q*ÐþLT›{±àצ\MØhÿ¾Ð·)ªã¾J|ÀåßGq£%°ÙO.:‘Õ"²Þ<¶6­½Õx7ÿ=—ç[5ùõëJ޾߲‡q Û.àÅ‚}Ùª\€,œÒ\ë i"]r›²Ðh*9kŸÊÖ«›ÖÇFxzˆOª:7¢×Ð9ðgq¹IRÿÅŸP€èò·Ž©7nmš‡‚u¹¨5L;¦_!ùÀÔgå…¿Õëg ‚;Ë „8Ìì܈ü;\̧´<½*!g“@Ì�>a ž¬RL“7úŠZÚKÎ8šˆ5uœWC-I�+ (SäŽZ±�™_G„ÃH±QòNaŸ�¿²šTÅ=—dUу µ!—9®Ah Åñ=Rdpÿß…ÎùÌ5ÈàïŒq“ë•f™žºaÐ'CN¸dº =ÄÝ-¼Ir·”a˜=ohxl“…ˆß>AÞ¥5—� ‹.¹ÏðÂÀg÷ËAçUþˆ³Ã=]]‡jý…ÿp…š”Êg‘ÆjÏëΆ–’pHkÝþY]KÓÔ4úl∊gk Œ@O×û¯à†Àu´èK´¼ðlOat«ìÿ´7„OÂ�û¹Í$Ú‡ÝaÉLØ?S±H´¸¿ë$Éßt$Tèô’kÔ4Î"kÏ6`Y¢A˜¯%’ Ï03sŒõ–¢–V�ˆQ‡ènþY8]Õ¦0z nd(Ü:ólïç«âÙI÷à×G¬—E"Á†Y/“˜ÆP2€ÓMìÛnúi:É-Ëå²Ê4j^“ACC‡<%�Ó|œM)­³©Á7Ì܇‹µ_+Î�Ÿ+ÿñ*=Æ¥ÖBã­;ŠÞÝÖ0~jáý"«<ÀÂjŸ<Zj|’8Ûx-{YÔHö17ÿ!¸6Ž%Jª_ƒKYÔâžÙÔ‘„¯&;½¨„Ò¸„ƒáþU¹õ7ùV9z½"qÇŒ�ešl�[_x—ÁWXc;._LǨÀàäaıʎ=õ å¸U ïlÜ0¢Ê|U²üO´ú‹½z{‘f„*™‡†mo Ò1dkW½õayø OeA*&[Ƶi T2Æö5'k•e å›X} S• ζ¼&TDy€wù·ÿÔ“ù¶Iö­�‘£º^%P<ÚÌ.{#5ä‰g€® â„à¶Aø.�ƒYÍ�Â{­ÿ“ز�¥‚®®«•N¼ìì…;c¨ãê ÆrbBå;=0ØBöTlâŸ)Ýbj¸#´ý)Æ kFŨ{œ:­”Û ˆC„ €ìb¼@ÊÛŸŠMæc1\|�|ƒüOnƒ‚wÀ °T™•S%0ò!Ò”¶Õè#òN‰¬ô…NÔ·›[Ñ{ãÍ=“š±åçJ :~V™ýÿ‡|èo8p'¾n€Â¯]H8~ JôqÛ¡3í³ÒïÚ k€Éf0QëÃÀì„^‡8I›^ kŸÒX³Ñºµ”l9´C¸á"Scì@J²jja·Ø j°ìg"$8üÉê¸v,¸è`y¨êo° I×ÎY€•ÿõÏ–­bíQþ÷K¾‹Í;Ó·øó^;�ÐÞ@wðñ±éãv ±>+¡}BÙ‰È÷•ŠaJŸJP7Z•Ô›ë‘ò°#/uü+2ûH»¬ÕØD‰î�ðo´bXz§¦�FdµX¯Ò ú®�ª¶ªïŠBîŸ`¹¹fðöyâT<É—í�Ð:ÌÿqÄ ‘$ýóZvm!ªséÃ@­Ö—|ǼTÉxPˆ`k¢e^ Ûýü›6"d1±–OÐë­¶—N›ü;ù@‘C�pÁ 0ªÎe�hAeµBI8„ËñçqÓXË÷Êòa|Xò¯:ƒ€ÎÚb/@Lç?Ô“ÎâêÃí .’�Ù^øj¾YC¬¶¶{À˜’�3ÃóX´Er$6g=¸¶c Þ8¢D¶ÈaF‚—îd1ú¶ùí Ìñ?ÛŽÿ"ƒÇÇqä ·‚HfzA#EñQæÿ ³æáæQµ+háxe&Q—?H¢xððºUöý0“#!ò 9##læ¨XEœÐåÄt;¦Ø–ÈnÑmGÝpÐzãG�ÄÛeyÍX]rAT©5�4M=Ü‚ªÊ½3rº+Çmß(=nB‰ì1êÇûã§_þÄ<:þnñZÉÖ1r´EÆ–È´—x^ÂLø_<Ÿ»÷æ#ÿ÷Ãò–Õäùm™¤Éú·G”ƒ?}j»ÀŒX&PÊ:'‹Ò×�'Û¡ÛΕ‚Ù…“aœø’ÃtcöOÀ#ƒÕê럀†n�B6” ЈŽ}ð/0ñ£!çÛ›“8Á� Âð"¿ *F+JçÎ�Xˆ[îlY´=ŸÓj#«UÉÇ®1}>ÖP%;öýׂ„a`AðÕÙ@ÄœN@¯—RYŒá¨¿ÁHþ�vÑ6®ÍûA-(Пþ'¬=òƒi¨7jÑuSÉŒà^w˜P=m™!nhz5¼_’Ó4üJ@ìò+$åwã �¢¨nâ�Aïë&‹�ÌÓ5P’áÛűÐá'à)äãFWùØš;ÌP¡ûÀDNñU³Jƒw A…nfãটXœ½žÙ8þÒÅÚ´UÁûŸéÖcˆá^&ƒ8Ý„5à ½€Ù€&X~F·Èzš'ü4c÷éD3û<}Ìõp»z“ìÀ�}è¡Î£k¼pb °`F’Ažd”D\'ÿ Ù"­�‰Â.PJMO4‘JG^»b~~ýE™å©wB,%Fö¨*o|ExÁjµ´×Tºš†y¦"miCOÄ ‚ù€A�òÑ P1\ÌWÄvñlŠD*󱧾ëpÏ— Y„ÆÝ++I�¿ù°.ž ׂ?œW†eUâ0�ÑÕrYIœ8§>›ø}\vŸ½×ê)¾6~ØÑ�œ'¯4¦¬àp²ù‡UºÞ_fjôF| @ÔT§h^§TÕðhÖ∠ÅsPì#m H*×EÎð)Œü;¡æ–‚±�(‰H¤ñ aY±+`°BÅD[Ž[™ƒQ£@›ñÏÐ’Öó¹âúÏNý´ç¥RÇFŸÕ~ØõWôFßp¹Ì¿4�PA•í¾’PǾµRðÜzÜÇOvÐ}ñKyARöã§>´UR··zâhy¿ç°Agb+½"EÛ…KIPwfñS‰'M¨Á]êT…Å}q£ *[Í¡9éÊvdIç¬ÖÆÃna€¡Çlj=>ÊQ¨×âe`gÀ³�4á!Ï>ûàF@*±! �KPŠ«VdT„ôåGdl['•ØáD­0 \ê‚L¦¯á…ÖÉa]E<ü‘ AÈsÍ[¥8o;¥Q«àŸÆ<çòiªë/¨Ã�jO “Å85rG?7PF5‡A�õtîº ¯úF¸L{N€�ôØäáß‚FA8S—ÇÌ-©c7téZ i_x6yY$óK樳;h;e`ÆM‡ˆnPK D$‡(“Äiú)\録ìtô*Þap¿‡Øœ£ØNE °lO°ÓÒ ¡uÙzV˜ã)™LùŸ`Õ¾ÿ[vÔ0àbŠ9¿×hn úýÎßˤã\ùŶü°,Ðß§“`\Æ¿µÕ!-~DHðð[9áÍ7Ñ@ ­vbö¡ í ÞüêX$Ew™¥D^íÙ°Bñ“²\ÖñÕä =²T.àþÏ òõªŽNÕ�Å A•?6œ %Y®c-WïjNÓI>s32>;úm6þñýÏ.µîcö~¼± `—!ŠÑ_¾‚ÔµêÇ;ؼ&íÊüÝ�ªL½Ž(u 'Èq n±MãíO`cÕñž>c¶ö–«n ´7>‹œ×?ÃÂeC»ýÚ‡õ—?õ“÷˜´w£¼[¿~ªÐœ¦¦5÷Hc¤–³FáóUm–軿ب3›FA�¸:Nrò{a~)££ÿÿ”ÌÄîà¹=:ǯ¿5°lgrêá» VbH§²ùàv�¯@âs0?ü¯Ã)ï^?n?[ÍYvÜ\,c*@ ÎmK&|Ós%LØ<+¶^¾?Ý×üV•¬qE]Ä”ô„ ¼òºVgç)ÒðÉšar–§„*_Ù12äëÀ·ž iÿÏi+•­¢.F$x‰j–‹A+q1æ=ƒ€… 3ÓèS(<–ïñÚ¯zp,À4‡ëøQ�`©2jÉF÷ðm‡Ò›Ó­7—í2.Øó²ã±ùmˆ)P�-š©ôKûAy“�?ŽpGŬ[ö7e.Þ,ô9ƒù÷Qø.ÊXl»×€ƒQ»ƒ«’„ZÔ‚�|�¶i–ºUÜMvô†ûc¡ë ›þ›Ãzóƒ •—™U%¶[nßéSÄÚøþ%$—öN¥[8œf«”~ÌðF¢ >ó™Î`7”i·@o@‚ó‹iåËÚÉçâÕýËÂk’ÿÙ=FU/: ‘n:FŽ~IÖ8ž‚”¦1µ‹gÌØž\¿6ðÀ<&HçAâ:n¢šPÈŠfBØõHÁ Ü"zJž›ïX×¶‰%_E9íDe�{tyÚ%4l�ß²Gt &>1ëÑùlJ·=wÑ?[iÉnq�MNIʶbn±XQÀ6Õh¸lÛ×�ËE}~x‚šÔ÷Ï=ÚúSIäiÕ- iÀUŒ¯«ež?*+8þЬU¡¦±-¹þ† ˆ)\ Y\ÿÇ([ =‹÷àÖæv¾sZžÕâY€Ô!ZP¹b –Æel«Æ¿É È_½hNèÜ¢ÓN¼´ä+÷çõÖ®ÚuÎÑ0�;~(VTâW&yÆ% v™vÇ“ïtȩҮjf¥Íc[9sbR7>¥öyÁÂE)ô$¤�Ű!#†½²åæ‚3epÎØ5 ¸oKÞœa9 ~WÆœ¡ÔÀ2hê‹Àõ½™+êãvà–yyùµQ&»Ðßc[h(ŸäÔS“~–aÅ®©}Á;äL´“E ßýeTH‰tÞI¼Ÿg¸�£�Q^ 5•åê„8{$¦�rO|HÒ¥ŒÚ¦XGåÏ=Æ Á%ž"nGÿ™îxfÕ—Ò Tñýí­ƒ™Õ|]ZŒŒ �€­bʾI€auÀr„?¼ÍWì>‰‚1ŸË/B’ìiðž…ö”ØNÑO…+r)³}¼úöZ:øöÔ@ægÞ�È)ßÿf©²g¸Û™Ó´pH²»ój„1û®ÕF—Yû¦Ë]ˆ–süÜÒpé:t”‹wÞÌdJü‹D?\I˜¯ºZ^i ´0Ls»â ¥F¬d{)@À–^ù*Ò‘øL•më°¦Œð.~5õ˨ÞÊñþ$Yã…”¸±ë9“.8‚剔ÅrQdë3ýYü„׊¤¸Pc‰}Ë®WGf‰£»‡Åp!8Ç|ª½j;‰ÐÍ0ÀìQrû~ƒ�#pË”ìùU«£w­äÜð^qíg# %PçòãŸùøoNB÷ĸþýânÉšé÷Ù üRv ó©#¬ÑlÐIÑâŽK§+Ðõ°;#é‹ïŠFõ{heÉ‹s$8ýW1ÑD‡‚É,HîãœÊf(¶Ù«µª"f¤ 9�ê7éݵä$9²Û3'e‘6?ï´ôrsŽ]ÞÜž,…8ÄfF£V½ÿ03O,ØF�Þ�Íy™©Çž§¬¬Ä‚½="hpPJ õ¡\I6ÀkâX;ÙQ�Á®t€~ü„F{a ·ë?ɇPžÏíd€qà~òàšwºÀJžÞr 'gÜB.¡K´3 0 çIÔZ±ØëËïí%‚¡éLÝšŸ1]J,²¾1"³z8Ó3+uÔíõ½¹ûrí}˜ܺ¼ƒ‰ùô·’ó•IÍybìiX­ë‹…™Ò«@Ë‹Að°š Óê.�U¿–Ó±¢ðTÍ1ãj⃠"+½íöÀ/–_É$ˆBâç½`Ü ÉEA2¬/‘ù¸¹`&Å™ûÀ‚æ¢>˜~°Ýÿ�oÀœGƒœ Û‰BÂŽ«õºüKñóú1ôF8�€¶Æš¶Ó{›å5ƒÜôvŠà‘aÅAf2ª¯ïÛœ&zÆNæö6‹ÃÓ€sÿEEþey›æ =%åÎY¼ïÉl¡éÉ=õfGÂQú¾äçNNA1Ø5 ¸£ƒ4kßlÿ=¡‡a¡H°aéðõÔ»,pxR¶Z>@‡E¥ù±Qjc.•ƒ>¬ÍTö‡'x3}‡£ î‘; hë:óþN±žXp-FÏÕÔsúl3Ùcë _ þ팥ôc3�TöꤊWg‚3hbìŠMÐíå%j ¸NÍqPlÓxãàã\§ÚüÛ=�º’ÀÔ0ôïAË¿H¢´ �ËPøzCJâÜs'CZ4-ÕSoÕ:t/QŸ(úcÔÏÊ"ŠIŸ¢¾¥êcäÿb›ê*BUÄxr,aHy™„±iB�è2ñ¶·tÉ‚¨pdý�¯þџߥ NÜät¶nF”–èb\è´ ô¿3¯áøK]BŽØbCÂ*¢ßãy t'«‘ƒ†øÍºøs*ò*;WÆæ?ž?Å V�O´mnyñÓ�ïk8ŒzgÂ×�ÖŽaÍFÿQdÀ,â_è΋ê}¶¿@3«EM�ôù‰R�3ä}=²Ùõ7ý¿©òeäZ.X¬ j›"J]„ôèšœî`O–¼ŸfäØ>(DòìÿXÀÂçP‚°ã üÜuu…>y­¦ZÀ¦V™w{ÑC6ÍqéÂè \^YÃK±NƒÐC¦…NA;àŠÝ¼&Ë&ÐŽT7ºt=v�ÏøÙº®[H(™f7ËKlü4V^ ø;ÎÁ�*ý_Æ [´] bhÌÙþDЬ�(ZBÙZcãC�(ÚrJ ôW`!wÉgm¬W˜M-Ψðºîü–˜´Ηˆñ«ë¯9u~ ÌÆî[Msþ •žBÃ'î�VÆa‚q�:ú©pC´WÆ Kçò;Lµ U£ÎA-hH冦eŠë49fв�¼*dprŽJIñU)799€,t6‚i| ¨œh˜á¹¨¸c?žü {RŽû‰§6TþÒº^iãξ¶7è•!dj ØË®‚%#Z� QA ßdXy ˆ²éžá³LYž$ôÚ`B¾AsAšEMá [Re0ýñ{Ý~,ßP÷ gk'ÈÀΙɽÛû^¹;ÎËåc¯ð:Îè‡ .€ÑžM?†v?ðãSäÁ‘M!c0F…XC‹·UX0“ºžQ@ÎN¤¸l cÉB±�¬‡†ÏÃΨâ·Â­2‰[ɽ?å¦'¶yV Ü“fP�¾+0ç":HÝ oøîÂeA»‚Þ ¾ 52�ÜNVêÑjéܵ5˜/>MjBË®Ažö¨†RÇÊG7Ùñ—Yÿ�c“Å�Æî1«þùµþ~p¡šò0ìÔqî‹ÓX|&f¾…&Âxú$í®O:™Ú»ò…¯P$b¹8µ¾Ð �ä§óÝÑ}Lóûl­yY1œ\ÖnR”{ÍA?ý®ÝÖá²öS8ìÍKßMî‘ñ&ÿÈw�óX_¸¿T î{H †@É”±)øUCì™Ï±Dñög¶ƒÏ£«õÂ,¾×‰á3¤6d*Çi¡§ºfyæ3µçЃΠD`j¢Í oZü’û5\D›Â`í�~Ê›—[8XÍ•Hûy#óðªäœî@Ùo%îÈ\¦NKÏJ„ÎbJÛ8}e¤Ksò–¶Q¿&:²Øz�xìõë¬c[ {çv{!P BŽ@íHÆËpm|œ­ÖÅ\ŠŒŒì₲®‹ê:@.JØ€sƼ2‘AšhMá–‰”À!ÿýñj"ã€êJ»PˆöàÎP瘞Ó:;M«}$s™Ë¤>„æLåÞ«Ó ;q×)]'U²ø5}:;×Þ¿ê ï\Kö�]FSmNG‹üß&6¹ä¢‡Ì¾-V— `Z-ZçSÅÏ(—#Q½ñ[•J©µKȬkÓIdž6$cr:¥ïz‚ýs6¸gpð� J)´¿V·pØÁórCy¯„׎;Œ;é·†ê8²í¤qfy£UévoL̺›Ç�.ÒMcXò}ýSJÛðFžJË/m8a“³óþèâÃb°°wT Û˜åÓh—v}0Ìê.é!Å ÜºЕ¦ç„¥Ç´=Õ—3ôêdÑÚ¯‡›¦è`ZXÄÑÞÕ¼b ^Ä,ãæó¥+€(2…máËÁÃtqŒá¼S¦†Ã’BG™7pç ¼G\,•ÝÍh¸LY7¸_:‡T>i6bÞ0™>DÑöI8•Ûéib„µšDÛ"M<|Û¤Í5&³YwF>ÏÇ~¿!zS0?úÐt‚-TþiÅëçl€@6ž¯oûùÈ›úáØhèÞî\ ÑpàÚ54Ô¢�í×ä-ôÆÛu½–_Ñ͈–eÃΪ¿¤‚"#ð»* åRé¨Ñ §•p½¼ÐpDÌ5Ó¥nÿ]ç b„ÉL"úN̳,µ<7ƒÐv¨œzÙIË€Ëp<¶>¹¸9ùIg)Àö§kÿd¶ëzYÃ"º¾�×1=k‚”tÓ”±ðì­Ž¼ø�ôé0Ë2ç9±¿¿:žÆ|Fzu •f”Ó‘5JYÛx$¡ †$ÄiqÀ$óÜ€ãî^f!�’W“áƒqÛÊ熪�—ÄÒ Õ¹Þ×·®øadìZE˜gÒ~Œ"c02”GŠmXB hp�’=׎´ÈÃûrXíÄCpÃzSEh•ã<þ~(P:3c‰“Œì˜*nhÂ2Q€ê##…}`ê€ÿa㤄Žð‘V}>:y5=&£]M{ù½ƒmæF&ÍÅ[ƒ�-1to(,àÊØ$\§ò’±o.”çUã•~4Ègš–mTó¦axú4º1©�2L0®ÖHÏTÉñÓÑ’HĈÓUò§þ *i-cõÚm EÀ\®"ç;êw)A7ÖR¶b»ªãƃöiÿÁ�¼¤q¼ÁtãùÃ9|`˜c�å|Œ«�˜§Ú!” œïÉ—ZËà#7éäÛ"~:nÔÈßñX¯ãöˆÓ AwÛ$´[úÈÒ�¨L�ªIgÚ1T,¦6Ä—­’αb ´B¥éœB‘áM™Ÿ?ÍF°%w§Ž«“ìߺä£]ù­¶sÆâøòòæÀ3�ï.çW÷Ômr{I‰Æ´Ëkr¹¦¨ L%3”*» ®ÿýÐAIk|´” ýæ³OãÖã[TèÃÆ˜|ÁŠúÈÓj¡ƒP5ë.ºkº%ÀÔâþÜÙ;‚:)ä…ûüJÜ´²GÁ�é?Rá7¦l›ì¤z�[Q…òáI%ªRÏu‚æŸ7eÁ/Y smng¸‘´¥Á‚xˆÜt×�6?”û~ÁS­m˜@ýŽÝ†Ùé¦óŠÌØ­ñ§øYßŠÇªŠ¼Ý³+ýæ°€½Â8� ‰ý՚�±c>6Ž å ==ïyv rÎÇg:¾w*A5¼Q·ÄÕxMïÆ¡¦ÌHùm·ÖªqXÿ>ÿ¼ ™Wg"ÜkåýÏEuà¬.^-²QÙ”O£t;�Â7ÐWtK“¶¿ãeœ‚÷ó­…Ý1 ÚÍF‘súÏV�[u(ܲY¸è)iÊ;õ&#°ØoúYÎÂЖ%ì\§á… –mã§²K+߀hçú˜W<7˜Ä¨»«JM·­kº&éA† Å 5v]åÂEtµ{¤P,‹úS°ýKÏ€tÍlím­M›°¡•Ap|R!÷TŒ0aôxòGExŽû‡·F‚¶Ãá�Åd¬ó!‡‹º¾¾MA>»]ÇÄsC<_|6¨õ ° �¸€"áÍAž†d”D\#ÿR”û8YG+�þJã›p¹–›MVàŒíê|($ær^ZJ,v}ÍôèË‚:¦•×îþ>�W˜'× bÝÂVés§s=LŠf §J»Û‚½9¾²xv6L|;åˆ)z¶Û¯>¾4…Uü›f µ‘Ó n“!µ¬XÚ’w„rÓËúÛ£¿¸ɸv_9Á‘Ûã²ÇMoÕ¨w¢t6²ç ]Zuþ¯Y–Í.Ã~‘4º°«zÙŠ±'nTpó¼î¬åáL‡éÁÃhÅC4ÚJ”rJ§œºì£eY3bÛsÆk¤ºkÁv+¨#Ö*>ˆº\w)½�mànkÎ*Îô¿´»2¥SéRs` Y“µÏÉࢂÌ0øòÊúW «u7íwÁ²ñi�±]4Úñ¹§Ðè+ættÅ¼í³²pNNXˆšß9Q [ójþG” ençëgŠãIËoyŠÄþÙlK&(ÂרXצ¿±”h˜mG¿GéˆÆ›îžÚ³ß*P¢þû31�qY<È©í‡)q ¤#ð+˜Â˜ÉEz+Ÿa¨Økgî)—Øœ®x+³·–�ê3ƒËÅ ¢ÿ/XöÝ=Ãc]R¨OLÉámm²^—Œ"b¤an­ÔºÇ{úÁ‘Kæ*£Õ`þEaÄ~ÑÏï¯AˆtÓ,³kwOP2Œv½…Î…Põô–g #ƒi§ýì¹ ~ËÚÍÙ4œœŠÜµ¦ÚD¹™þî×.à¸Ý?Ê $âl°¥;[{üDÂ^h£öÓmïü=¼Áÿœ§Ž®Â„íì"³Û ¯#6'¾ö˾~~¨‡·6ÚXrpžÞ¿¶]¯/¨ç*òï‡f�£üä€. þAš¬5-dÊ`CÿýñG@D@õ™¸g@Å9¶³zÞ$m¹ú"Í ë_Ãä{žÕÄ㺟)=Vᕹ2�ò¯7Ýã¼ÚlM@ìļjw*¦®~biÄΈ1Kß±'É«vdŸG|ü7õ¹±·ÅAèZ¿Ê¦xk|µ¥utS/Áž`ÀÑ%Q­ h¾òÞÕVTÏÈ£ŸcÖ!y•“„;ÎFçªßóÚöM—.w]¨a; ÐO—šh³¸ÿ9Í×W‘ìKôüÿ®òßÓwzÎ CØF `ó*„+k½�Z„Âk³>çf)Fv¡ýˆ,añ÷ýî�t}…§°š»TŒY‹˜Vür˜VoQà[£åÒÞ_f\ ÝUGAÎ=L”ÍÚ;`�ßÔ9hh·Õ<—ÐX %­C¶ß�öCÏVM FR®(øÿŸÌ§"Díâooc¼±^™ KÐIQÉ£ŽIÜ‹Ö`aŒ6AQ½ bHGqÅæJ‰QžäÃÈ#xu0ÏóqÊÚ¯ŸP»IΡnY��ç®7v»·ÃÒA^IÚê%c¾Q!h�¿ÄG}fÉX¬°ºEܴдó7Ü�‚2Ò?nÕAQPé'õ¦28ÔÍ a~å¶aŠ0mû ð$ö ´ ’:³†‰"í1[ýßËÑKåÛ]‹ûÿ”¨®AÎgŠ;ÈKy(­}ŒI¬ÞWÌ?¦‡þšÀyRélAzSNß"n•»Ü\‚׃V‘Î=˜}£‰ãÖ�¨¹øØ?I‹ fB÷$ÈÖÞFtþ2G²díª ¯¥ç„pDÇ Ý-ÏÈÿøVF–5Æú»ZWÁy¿ÏZøqÍGu{Ô>Ñ1"|Àfvc7ìQÛ#s2=òíÀ�ßY¬i—ڤ؞FSÏžË�÷©‰¼5ê%bÙ °³t?4"4…L`x­/—,ïâÐu•È$b¹?üô_OŸžvˆ  \Ä€�½-ï´”Gx/S±nÆßp?õ׊S‡ ´¸WýŠ`׳ŽÅOpl§Á!mDÞ¼²„ÔÿpÄØ�TÑM†�€ìË—™RþE†4Š´AE>’íLGLÆgÊùUÛ½@&hÈÍwl~Q.Ÿªe‘è²L(�µõ0!8rê—FËräx‰_­¼@·6—ùV:†K©ó–¡³¬u„,ï 4ÿ¿gÖÙï §±üɃçœG®Ôµ=»óè9ïÏ!M»,\ß~ŠÌ©mü'zçVæxt}8è!$í0ª-#ÿÉmÇdfzkxÍ-“Ì V‚fìM‡Ü…€XSv+kf]/Uˆ±ŒMլȓòÀÀˆbûvߢ¹ f4ê®ì«3x©X…—__î*ý éà8<|”0.-ó2éí„#)9”¡h9V~ Lž³ÈEþ I¥Q!íé“ß°¾-*rÏZÝ*ÔÈZ –ýµòÁŸO [/Òtvëi.yÐõí®b&þzì^>³’«AÞo¢3P,¿“æ(ü§ÕI!4¤.×-Ä¢v·'úÂ$°õ`ŸË‰dSZ}ïL^2:Õï¥îS‘ˆž;z�_EÖðÐ ÿ°7ÚÉ‘Þvù¯' ¾¥‚ \›YÚ"Œxg!PZgb\6k‹,Jý1$¿T¤l\Ó‹¼‘e§^ÔÅ\è)¸J C,'‘‡<§™ªÒêhàG²ê‡] |œ�ÎÈ�=ÑyhÕ®)ƸY‹kæǯ;…Û²Ü-–”YcE3šŽ|¼ùëéࣟ’9Íÿ$ï…8ˆ³Ú;s"Cä« '°ëž˜@.¡€¿p[iAü®Ðñ¸ùï*þ|²ë3Ai€r>ßgêÉ€ù8¶í½ ñqF§JãûMÙÆ2}-°ƪO`&pÙNŠ“ÁX�$ [v›:!¼[Q8Ì%¬Ä/–¬CÓÙQùhE육w¤ï<¹ð+ß!ù†Yg¾ñîMÕÍ—…›¬wÞ#…À(Ñ’:HÚé³áDCëEDDohëºòÿ{eÿSd&NÛæ �«Ç[qÛ·²|~­Zµ;|B’˜Šwet^iNbO™ÂÏGM|´2Ú&¿IHª‹d•UïÄ× vàÙÀmˆ«$²®¥Ê+ÚìžNX‚®T»$=pêÇW¶%ë§ÝŽæ8ßÇ/¾UdMÙn«Úí<Åêfò“Œ`¶çv¿6RBosûðf‰³vžx¨“Œ³ÓH¼ òôðgôÃI�žFêõgù¦×ˆÑnmŽa¤õÅÀ? ^znZ®×V–}ÏŠhÀ­óaã¨ÿë�ֈŔpž¨UbG½±}¯¨È'ú"‚’¶Œúëª9e´4Û)p?¶“„bÐÓ¢‚^¤Úá‘ÏZk’%0»Ñ y‰$×VîنŹŸ}ÃÛªulZ6Q¤r`(U ¨K¾•Ï?ÁY±)&to·lé�šPo·ÉÙÆõ€.ÿ?€¤²®Z6iï3Ú³pMt猆jq÷{Mò3šE/ý“ÿ|@\ä-Æ?Q�\H ÉŸa…€¤JãkÒpùÑsßa"€D£µªÑ3JúªåY–Å‹Óï\öàzjû³"·­H¼ü&ÂÐøN9à� ;Ñz¾fTžI£Ò4$‘t2Ä3ŒÓ1e^Aj­‘׌Õ,8˜2à†*ùêuL´³K~øKþÏ’‰æ»ïÂvEY+�ªð öOMÏ^ �•’ŠÆù´˜�¡ØÎ˜ì2GÈØq×5¶>)ÈHMúçËêÄØÓö?ª>…âQÁr“ïõþǚē1äÍ˲²aO€÷1êVRò¯&Ù1^—A�ï{÷Ķâ÷Aè¤Y>;Óøðù€`š@î“ËJ» ›KEPŲ {X~±«ãÛXìÇ™íoZÔ|¶�º¹$m]Cí«8%ôÑÔRTë©Þ7È|j\]âŸtfùKÛoé°�Q¨–Ê$vS@Oó3²5û#¶�RqOV„ˈ¥¨@4=ª,'úVJ ÊÁIž ÷/þñŒäÎßh¾îáÛ�þ߯9-rE%¶{Ëb �pØ.ê³€�¡¡žýef9ŽO͉8>Ò ÿÇâÎa-¾P„{ûôò £'!Ù€�Î{�h¼×ºÞ{EBÄÙÓˆEÁm×ýd¾©PB”R®YY7­8‹M�´öDìD+o—à($ù„NˆL==³TÒí¯9 Þü_nY~Lè"7è~m2¦{ûˆ(~Û �»˜m»¬)óqœ3P«vþ Ì®oõ4�™:ñ‡q¡…ȳø¬¦Éoº›ôzuë¸×:1q6�pìu?0ï#Á²oÚ'ØÂ“§­C£±®{£å7Üø¹£³ˆV. §n®O`×+3j�ðÿ~©€:dFÄÀ(F¸øÄ�Ä`À¤ ™öe¯¾zÕÍu £‰Ìg²‘Ý�œxæÓ:V+ölZ2gç¨OZ³’RXàkÑä"éÐY<ºUF°ol.Ù1[û蛡±Rã$’Ìв#4Z]~g„rUçü ôÛý¹´â3.ÙŽò¬’Hf¸µ ïvZ½"ùƒºŸ¯/_¹ŽÞ84Áº� Øcw¦8Ï…ão¹è´-4éAHñØ lrIác’šþ;-}R,i8j âôÝÙ;P®¡éræùcé¸ýÃ%­¬…Ü%p>“;6îÓŸKAÿ°:²áúwÉe‡_/�¯Ç‡ye7à>Ípl+¾B›qÙ@@°]×ú€Óù�­®[`*ê‚^c#›s|5ßµª§hC¹<ð%g±~<<Úbr<Œ�'Q$bMw U»dË0*˜ÅŽ\,M�lh–fÏ-‡)ï{Òð˜ wc|©{M0.}ˆˆF�šñA¥Æ‰¦p.µŒ„SÇp4À.­)f"U…® ˜�ò%ò´ôzY»ècé+k:yKK‘ 7¢qVµÂxæÎÔÝkñuÔ¤Õ×XZ†zf–Òª|©¡Ê"(¹ˆ*€£BFœ[…Y÷F]ÅÆ×qPGRìžÖ•U¥†ìJß·Ášp{mNA’©Ú‚Îóf! Iÿ�CÛd‰ùz-o»:‚y¢…‰ 2@ =µ®h�D"v)€Ã3ãÏ“· k)ÒŒ U|ì´Q&#ðíz ÇͲé®2JÅM Z¿Aò*êü¬H:ȵnPB†«6 Žð�ÓË×%çZ„Š÷40Î6—kê\̪H±l‘rœ¹Ûà«­]L9¾Ð¥²Ûf$“„sÌ"Þgá¯h’åÈuzû›@– ²öHýõ >ú*%µ‹¤“¾­úiH~]HåD_aejJR×5ÅÞ’Teßç׊_†³õêJê±ø¢Ôä=a*Ç#“1ë±2ž”ÄÙZ hA§zæïãàTŒ¸äU²§Ð¤¼Np£«;ñÐ÷zŒçÖÙÑèõ½ñ¬S ±LöÁ÷¾¼:(9¬'ˆS P•÷mñ*@¥lÕó¡�°ZÅÒ[Ù�~$M»úÐ5‘­¢Á­m\„‰Ž™®c…¢ùÞö¬oÑ7ÅŒê¥Ì4Éó8EC%1"#ÛŒYôÁ”’Ó_ÕZ‘PÜì†)��€´ÔËt7|‹+Øæ Ùwý›–@l4BPý›°O:-:mTÛ|ì«Vì ò£†óSpy�C#ˆ>Hú&n'ÂŘ̺ª§¬Li6ž@ìÍ RDZy ºpà6,K �ü.Û)øMÀßAžÊd”TL'ÿ Ùq‰@xtº‰‚‰%ÞÛÆþÚ›[(DZíµh…~Ra†̰qL<áÞȨoeç~V4Lý1µ–êçeYH#ßÖáÞEUFhC¦u÷äì<þWyÍ>¨PbÀ³€^È”…4Vi·B �ˆòw®èÂZ{½‡£·b[Z L%}) L}�¶àÇÕŽ‡DÍV€�kj‹C¶øúg4�}¸·—é];×Oí±¡¾íÜ®/hu;ÚßBUfI!nÉŰ<1~ß²Õc½û)‰Þ²dóKÌuö9„_Ä�!³oÊb5Û3€iØÃ®Çå¡^nL9 ̺†2€·%‹(v.÷é°IIS«ùüTÖ�V¡‹ð�VßTjð6)“õÖš�ýðÏL‹<×6cŽi#Ÿ´ºù9"Û; ãí!-:{‘Wðd¼ãÈœXôïgusÅ’*B9Ú*­RV>šVD`–Jè´X¸Þ*;–P÷¹ªë¹kŒwÀSm“4‘çg\+é–îpFŽ+ð+g>ÂY�KÇ!L¼Y¬2ÔTÇŒ$N”¡uP[Žztpd8Ã_ÊE]nx{^ žÿ@ÀsšÌ´„Ç®‚YŠÖÞˆE\]¦ü5�«ÏýŠÔ|`)K< ü#• ÔSŸM �ïð’=„ÇŸV?þ¬71e3ù,9­È8púƒì¯Ñ4Àñ±š¸ ©l‹†ž ÷é«7;®e^±©œyaT„¡{’3¸W�x~\ÅgJC£Ò¿Ò­ŸaM¸—O:-æÂ€ŒÛ"Š‹uذ>¿ŒÁMˆÖżd$H×·2Sʺéì.ŠÓÊ ¦3G<÷ú*íÞº{0—�âë&ÎxQ¬XR4óŒêOé\’B¿±ãÓ“ƒðZ»6SDççf�¥³0˜–‹Œ À]ãëÂ,JÜsë.%ªR,žÝÑO@Ž|¹’Ùˆ1ÉË›ßü6N O¼ŽsïS)¯´|OMÕ^í>Ú}wxüÓ¯8VE¼‰¤íÆ‚’‹Ž�ÎI[Mòu¡õå­ÍVÓ,Ucâ±$é4NÍìœW™µÐnÝ–D®ÐŸoÖp»cGÎÂPøqê¢�TóƒïuÖÚJÝ�À�´Ûaó‹yËú‰È·&È'B4Ž©§’K fwu&L¸mC´ æðžënGÿ™îmÒõêHÁ}"Q*ÞÏ/æg»Y¨Ê1l)Zí 1Ò”õŽ÷ÄóáÐ=¡êEšÂìÁëñ£s²ÏÄ'¸Ïšžkò:•¨¯2�&rmíQÇŽW±B€Uº°�º$}™Ã„¤  �øP¢GBù:ë½5I¤æå0´ÚîËÚOõ;6‹Z<³žtï éùÅg?ºvå¥ÍvÉ�çüÑLlôºÚ,¼”lûóÅ 2“;±ÖK§ñýÝ â׈¾X³À]·áÂߣ<%›k ¨H…£BþçÛmZèò('y.�Ç‚!hçÅ8±ñ‰Â€ÝwJ:wÊÔߢ֓ÛU|¹GÅŠ€¦¯zVg¡z.ÆÏÛñwT£©Ò‡ù€ è »gkõ~7­£ˆ¶ìëØ½“–1m4|Ì&®öÍ£ó1Š–ÖMúj\}�¤#5NF9²Vü¤–ü¶ˆû”8rˆè-ÖG$ØÙРJ´`3¬;JžŒª|þÓÿóFËÍŽÐSê7¼–P-`Ìg[¡ìØíÆÄsåGÁ@Ù,²‚a"4ì,ÚùV�»°<+òÁ`6/m#y‰Ykû´èàaˆ/™w8}‘#é!¯Ã]€Ðì:J\6|¦[³ÚçöNÊæEÀ§|I‘9@× ‰lSHÚ Ašð5-©2˜ÿýñ©š^H5”�îÞ˜8|:ƱªÔ¾Ü³þ /¹àÑtu%Ï/ÔD„38q£•´¬dN¸RÙ³Ÿ>ìq¸�TÃq¾mUøŒ®I”Ԥ߫Lé42q8k~⟺3’ãs4­Wè8Æ5­Ç¬H0iz÷º:�ï5ê±zôµ³&áͬ#h‰WGp 4üÐf`s‰…¯1BÀ˜’êØ•£¦:vã:q>.ÅPP5 R"Éõa9©•ÝrK�ÜŸk0°ož…Î0°¶ëiû5iN:ƒ[ ÿ"þ’æ<Œz#1&}EÆã*€/÷­¾åz½¬wªd˜v:Û´pãº×ñÎ?Þ ú”2Ö„1Æ¢ í ×9™þÎjý*Í'`?Q²bDþ»Ô(?—VyªbhUyŒwÔÞœlÔ“­ùMîá­’”7ù-¾bÿb S�CWÅ?ðk�µÓ©· Ãñ”ðA<ÔDºêª—ãߢ$M._MÈckñš5Àós¡Œò8ç.‹yd¨»uöÖúokàä¸D2�Vlñ¬ibXí ' öy:ìË6 Wï<¼1KQ—Í �nÆóZÈÖÌ o¿®Qn$Ìq‡ŒÈÖÞ[aý–áÏDe1EÈ 峯íáZ=ì�·ãônG¤Òìƒ|¾ÛÞá¡“Jæ1¡…Ân‹YÂ�|r›s.š1ÃfØ…¼TÑ·;-P”�ê#Õö’Sõ#öŠU¶(M£æQôÍ9•rèG’ «Ê¾ì [æD³>:—A�¨6:&`aÈW!ÚåÇ·õ'K†ÿÿhœXogá@d�Û{ùxÀl]³ ·#™ù˜¹�yˆ°£>H•ÜÂëgHd%"ÎÿˆÆ+Î]w¿êôò‹lc;¡výC—»¡öBmlP�Šbãûu„j—¢å‹ÅâØ˜¹Ÿþþ0ÓQ;o’ì¡=ºcqƱOü9´”Nfuî7Ëá^û‹Û»¡`@ú„JX ëBRͶb&äð‘·µÓœã/ŸO“FÝëˆg§Ëy5þá�³”ÎÒ¦_ݶGîß@Ñ9çN‚q¥õ�@›»•zì Åßõ KI=éúAîCP k“œÍÊÀl€üâ¾Û®K¶¦Õ…Ïu—Ô¤ŒÍW( !§) U.²< ñçÉPÜWÖL}gG¶-°÷ vA8r…ŒîéYêHrýª)ÉAfþ,ë4œ\V£Î“»²ÖZ±c‚ú¿ÃìW«¬<П*Âþ­^Ò•ªï~Úó®¼r–ã< ¼>k÷KY3øúêÌ+ÚbÅ0^÷wÐ�lJƒ}»�sXc“Ћ&¡…´‚”18r>Z¨ °káÙ˽å­³@¾y9ráç„ÙK<ýu¨Ââ<'H+ŃÖëÉi€'š¢D^c‚†ñûඪ¶ˆîø&õÊb¦Og#þYÖËñߤ—¨Rx~¨‚ n’ļöa¬•·PeÜéM;ÿŠ`1­˜|Ü÷]?!�„m€N$è9.¥¹.B¿‹‘ÁLl›|¦r6 ‘rš‘§Aî ¦N¤ `Yî@WquÑò]lQ•��1À�޹Û“q•äybnˆ�’qÏ T§LL'¹ §X)é¦�ò(•;“¥k„8G‘Až’CXäb>üf·{2Õn‹Up�jÉæKùÅJOu '«Ü@dõ{ò°ã^ eÎy€Íò~š’/¶ Y_'²£qµ~« 7RƒØh‹ËÞ³k?tÐð¥œØ~+ôÀ+¾läcæ°MÌ@Ú7Çéaä²q¹ `®ëSnÖç©°K»•îâ °Ç0÷Ïú8ÉÙ}qI’kÁÉRž¾!ôÁ%™ùtÞ]÷/s‘0£Á’ãp« ¡¢g®&çQ“¶)ó¬Km±ÉB•:š%Í� 0Ti™>JHâîÉn;eÉñ[&m·¦ªõ8ÖEP%%@qf7µÃp]½àÔnÜÂàe 7Wù†§¤OµŒ§Á˜È@ã,3wO¥ßÆ/{Qÿº m‰Î0ÐÂ}ô5±ö¥Ï[\+STqÈŽ%þ‡¾xnr÷x؉ XÍž ¹j«6M¬JÊ+hÙå#ßT+ƒØ»QåË0jvÆaê mäh�I2ÌÔ-oOÏP Kì?3âÜrã…÷*!3oìÝKãRèœ/S5ççQwª�²IÔf"í=B2[ÐõHvÂ5?¢PO§2„°‰¸mi<öƒÖÙ-ï–î:ª6H´aª ‰áñ�’ωcQ )C‡õ…¨VNw xãkG¬L³†P\À“ªäYÕý‘�ªU#Ë©Q|ß¶ñÓ‡ªc”Ïcøð]®1Œ¹±p£É:ˆ²� ÇØX —°jÆ–qÁÅ¿©& XǾ|B«Š£E*s׸âh«Ü_í´/cÚ©s 2ÐŒFîs=ö�’83Ø™ÁDLàT/÷pQ®ôµŠØt†“ý3ÛaaHpÞYÈo?Z râ�ñ…½]ü?ÈÅFzJˆ~õ@Û²Þœ ¿œ�=Y‚]ü%·‘’fãØ‚Û0`ú­ùM)…û¾|po÷£BÞpžÓ-ª‘^°!E­�½üC.óüþSæS#zjÕö¶ìRå¢J,/é†VÊEÍô`<Þ¦°F.D‘5£™ƒžTÜ9H¼5BùsbGŠƒü©AŸ.Cq[Ôf"­Hnf5oÎ…3ÛŒ”×'Ëçí¢êð˜>êóß½¸aüj—h„ƾ„}�Ë¥œ^%ë�GÖ²¿¥é%ˆ»�±ìç¶ÑC¦•4Y\€ê/«úž%M«úHFð׫kúCþF M˜X¸Ù Y”>Ô¨¼´8H�Pß5➨މdÆF¤Ç±\©&‡ šÜÉäfUí3ó��Ük-GÙÿQd&1nñ„¬±�ô«˜÷Xv)¶¶ú‹%P…F¬@.¡�Õþ8“å�”éíEADýžPø§º×Œ¤¾Ÿ'�dÛƒª€'Y&«€6©ý4žbcæv›4me7}/íÞb@ìšR/ðßEòð9­Žª>Ù5­6ƒ°¸€:‰¾=”šªBRs2Ã¥R¯ÊpN{Œ3\#Çý¾¡ÈT"�šêµ�±¦r,R$JråoaÝo© &³än¾_JöɳÓ m‚Jû…ywô‰€ùa%š»âj5qúH6*Ö· ]¥^ÎP%ev‘¡9R(²SûÑ¢Oßš-{t½"ŒŽÙ@ÃßÏÒñ� lÛ2™ 殓�ÌædË`lR Þö?†ÑR‰‹dÖÀºâ&³ÀhD~o¥éibľ †®® ˆ%O:dÉ¥Á¥aUÄ=Š»g­4 Ši”W[(¿,ÁO0’\‰&ù"ÿØæ]Ás²¥ÿF½™gpŽ;ìxDÄ�¾Ó¾KܵÝǦƒY–ÿ¯®&"À&�<ë�œtŒ…›1ȶªZþmë:¨C&zµbºO32ÁîÖd²”¯2ŠwÅbâGä¿ÿÛÄ/ÞÃ�mQî{]R† |:™a�ïªÒS°žÒEè_lšpºâ‚4�ñq‚Éðk\¡¡~ܸ„ÁþÍ[Gߎåv£#b“3JCû·Á㣓kxŽ×ª¿”·…¸ ÄmwIÿ œ˜€Wbom²M—\DÍâ¼àÙ5T\M>nCåGfiUŸµlËŠoP "%’Л6ÔÍOKí„VÚÕYÒë(|)åZæÃrÓ®©ÕÑÑ,7ýiðR#«¯N4‘Œ€çÓ·À“BxŠ˜Ñ(�q4’Ònb°Óº¾®ÃjÎÙ÷ß”G§Ú´—Íuò·¾5³Uþ"{:×bŒõ´LJP”ø5a®âèÉjxx*’5™ª?¤¸BþfP ÃÚ½Pâù9 ¤w¹ßy7~ª“ǯpinô%töš£y;§˜ ˜Ï�Ù"€Þ�×Ò»„ÙîcÔŸÆ#xžœž8†±E²­Þ%:�ö}ÍVžØ¹¡|P¡æÃŸýÏÑ\èÒ/b�°.±ðð3ó³•&†/Œ½,§¸Cý-Ôõ;Kϯ# xÊ_Óûè×�èµQÍ  jGþ¡s­I†ïcAþl<ò¥<ÿK=L¦Ì�3] v…Ù_MiŸ‰T-ÐfªªºMµøQíòÁ­Ü>ÝÉV-ÀÖ¾ôAi*ü}hê£�6 Ì�Ñ�êëd¸Ÿ{ Pã<Ô}Ó,¨5¬-¢àl~²Ð??ž—ûÑDw ðév˜aöòˆâ~±‰nWõ…3ãr¯ö½áÞŸ^‡tÕÙý?«Ù+nìönýR(&µk¤ÈËZ“9“jM¢/�ðáJ¬j¤@É� WjFœ¸#‘}ÁS‹Bäâp ¸noÜØÅÏ…O¯%„¸ªŽ~n¿…Ö·j«ób+DS”Sž‚÷<õÍ ANºøM@K×"dn«),qšn¹àÏ�lrõpÍý~.t8COQõOg`"‡ä²÷¼'ïšj‚×Ê‹L/HüÞ¥}üÍ�—ßš½iì ›vþif§nõ¼YÁ5è*M!ÚVp±(]—ZÞrñ€ôéJð冩äo*Wí´�ÁÆÈ©µÈnì¹6nkh>5:ë®3+® ®™Ý Z[·AÑ«=‚¿…]¥ÏÔ%¯åç£n€µ¡‘¬§6Œ�(JøäD$¿0q¸À]»í7ÃAÿ±ÇßjbޏßÄÀ<DÁ€AŸd”D\'ÿ Ù¨MÆÿºx÷Æt³˜ÂÐM‰2�_gB®3ÚMqP€´ûŠª>j†y2‘çš�ˆ‚F’gͯ=º?ôhÌ„ÒeF†•˜jbSH25t#oâ í»ŠCÿü¯5ðÎ:��4ìQÒSk4êÉÃ.ˆ˜ÁÉ>Q[ЫµçH ($tFM8oÃX?¸Îš:Gyé˜8ÿÛHí&±²*: |Ð?uÁÇ×NMÇãüK³�NÞÛ‚â`¹�wóÿµ�{OhU~®ÝÁ»e ›£‹zìÙHRÉ€â4Ê»kvw]‰Ee(Xˆî¬4W­Kò–ÒWÙî«È=ibâ¤ÂN"m?*U>ÝnZÀÁ0¤yÓÀ’èîÆGnôˆWº¦½ò%EÒP õ$òˆ7kÿ`?�©ÆE•‘öÎ ’à™}!ßþ‹;Çê`‰o`CõØpjgÞÛŽôvu‡oXŸ\窡§¼�ì\;á± p°ª€@"z@¬üë!¦„*¿�½¹_çH4ÊÖ? s³F„"ºo\¬L‹þv�¸0”6ÜÂ9Î V‚l‡Àð©ytåœOœ`Gu´è—Ÿ‰€_´v  Ozן€|â ú�ØcVš¿ GxIws�ì¬eÚ :Ô℺d7Ú‰Í:÷öM»\Wôv3B0坹߸S<>Ô3i.CXƒe ª@c0L=�9ä×HÚDÄP&?–­#Q�| ÙG'ˈBôƒv$ƒÓZ ?æ¹V°¼ÜDHÐ*]})ª@¿ºßó½Ü)VL×±¡9îpî{ñ«ïÔ3&†&ÐÕ×ýž"à‘B&m&ºÐêËp3jàÉÇ!Ò�‹±g}ŵjsþ®Fœ•óËÏkÝD ¬ÑÞ6^~mã¹Ô;RÀß�Yü…ûÉ`¦­C«pk¯eã¸J~E>ÿð$O¿ùîÕjá¹ý…¸ºK w:ü¦ þæ(—¼èþ6ÏTLÃFí>žæð€À îÂî¦5³@ý�ºÍH3“ùØN\æ7ÛWŽ£‚rHAyQõgjúÉŒÔ2`¢R´ùÙôÂÉ<ç™yíu/Z˜æ‡Š3>m¡Oi�z”Oȃt†­&™³¾ÁÔ×µYCEðë8ò'fÎãäŒâ'�KºÙÏ0a(qMEt ü$'Ú½C,àã�Ÿ-iÿ~UDo 5` �ÛJ©”p?�î’�… {~WÒ þ‚̾¤œJ] [€�›BȉX Èõœ"œ†²ÿ¢j�È ü~oX@2Ï®F÷Ū:wâ€/w-k»…T$ìnô+ª°—ÙN?þ#7ÞÁ„ú4娭‹eƒo•^Eë- b/9Ò³l~V�Ý?’TZÀâf[6£ïm*H×3½Oozùlï8úó4™…;¹´]3ôsYcã;çzlð¿Sû©g•O/øÄë¡…Û&tëàÉR0É8€tWW½ÀÈìö_š3æÚاy·Ÿ;ÿ›­¯JÕìäû8£��C .;2—æûÒgžj•¤Óó–W÷ÿ`ÚÒBE‹ÎœˆVþƒksÆ›X®J"¶éò¶‹[âÏäwø·(ëáåÜûÆ ¨"ò XÑ"â €2¹#g—š):5”·ÔsÑt¸uDòVð�¯ufG–ûÖ™mÍUp<™ÅcÞÊET'eú/&„öõXi]Ýûݧæ:º4(xÏÂa7‰S¢Eüa…Jœ$Ý¿åeþ W�dý”»XU,±¨;g=ìÛ³‹1S‘„ª�rÅyA:|ì «–òW?’Sôè©Üc\Œ¨ÒË_ cIŠfoWiÝ/Á¨ a$L‘´Á*ÅíÎlÚ¥·†w¿ûX4ë¯Å%Lß�Ò)©¶•¢‘9öi-×éyzo½³Ã;âãù>õÍ-rdî<‰EÁå4šPGé@1  Œ„1ìf-†÷æ‡CºÙÖ¾ë÷@H'¹÷$ÏÅâ9�~£¾Ë{20ÃFÜøÐ~.%øœÃ +tÊ =Ù+|ôf0ØW 'o¨×52”{1Ü&Á°gÂQàMAü�d–Âùé¹» SÅ­b–%Gx{-,Hï"9ð[ç ñd>ìÎi»ˆ¾÷@‡..e@º-^#»ÛŸÄ“oË|º~yÑ›kšæ¿À‚œÄþûÓ^M¦7ÐUƒ¨ùÜZ_-NYq탷 -Éñƒ›­mEÃæÜó½ rÿë%šz´ÒÂ0²MÌOŒ­Ì0§]®yOÜâš›Në‚ØE$f0µZµG„°_cö‡Sc­Ÿ!Y”që KLl˜ÿÎB…3ª]uY€òV×G’þUÌΆ|þàɾC¯Ã3�ŽnƒÕ€[O(Ò¾' [0Œí0Y¯$ Ã¨†ö¢dÇâ9SˆµÇS¼Ä*àÈ��»Â²Så·Ñ¯ÖžÔn Ü.6ê�³·ï-òü:˜Ÿú¿È‰Áô�OV‚¸…[h×ËBpÞÙ~w7þ‡{úÕT潄ùãÄeí·÷±" 6�ï8jjS‘ð—¼æÀ­\A›UMá [Re0ýñR?`µqtË&H¨Ç´¹@w\qŸ�æ]&ÌD»ÎYÔhÓ7Ë©å®à_!ž�ÿý©øy¬iì:”tO¤“M�0ØxQªU§D¬Åø­eœG:åhîø×Ÿ¯â9ãØè!¡Iwû ˜Œqü›@YˆÆýôX¡ïÜ—ì$ÉeZPÆ6úÆÉNF{áÖh×.%ôµItê_¢<�uþ·Ðg�ˆ¾ß÷ú3Qr¨ö¾xz�4è”mê¡dïã×â‰ù›@âµ··íÛ9ŽkÝr£*(Àsì(yn: éWÒ"�ß©÷[ªˆ±çî’/ñçÉô9‘jô‡š‡¯[D;‰Ùœ_/5"Í1þ1ÛSý¦^âWß)T,² ÁI/¯†´À­a‚.ð¹ì¢+Î2ë�£q1îŒ#š^ªb�ûoò{Ó˜›A*¨MkÛKÌs² ÆtXÆ™ ¨ï�ñ;C…s¶çGP'NçÚf¿ïDÆ�˯L›°&•bÆ´YÁj�Gmõ÷“ÿú~wM\+­#[¡|„¿�å,ÅðvÁA¤ß^Ï…öÕ“¯Ø@;5äÂ*™ï‰Å2¡ÔuââkÈ…cžŠ‚+8ÀÄ*óë«Áæ��ëiù--a y¦wòïŠkÒ¦.¹+@ëU[¯0ˆˆ  yÒIé"þ‹ãÑC`þ¡Ï•�U�¥–¼Ìèvp@"æÏé‰ñ¤˜É·®PáÌ´ø?‘õdn ¶Ž#b]ô5ÀääW¦G„·\e¿¼x ó-ð}¹�áaË3€tZB™„¡ý®`JÒúM½²ª¿léÏéH<»“úàúŽ×¢Ÿ7#ÛGëpElhNjúoa6dèÙ«Eô~®ž#ìæÂêyÕ9]¬gh‰ÛEµîQ™ II€1„?j޶âsüqüð5a£Ü› sQcñÆúêaœ þQ! 4ž'+-¬FX;‹µáFæo³•\âÖ§)™ /ƒ@}lŽ  ]—þ]ßCí.goÌjHØ»z0Š‘€æq^)p}M¿bÐubÏ@ÍÓëõ iÚP‰Ö|/®¬Ÿ­òZ¤ÀÍ’~†žÏ¸÷O|â’Þßc¹°9&IVèƒj¶:×ý*ž­‚Wðwtä b¶eËþÜË®Á¼„,†ÿ·Ð�úŸ¯Î�ׄ¦‹O ëêNÆcÐߟ5oÜMq=° ÞKd®Ä8¦…Ôò.<� q�šv@H® uáÈ¥J¤è™e¬ß_¯ÞCbûcX/¸b²¼/÷L¡_üÚÓ„Nêç3!§/qDt…×±Ãùãp8&HO�~!°ü@pû§0èlWpXWè«ÒÊÍç†C­ÜîŽ~LŠåÛTŠE¾½c¡>´ü¡=öX3b1ýP·Nž5 05Gœ¶Ç¹k)�̧‹ÖšþÒÕÐÕ@¶"k¨@˜ÎÕ~Âs”FiYTñ¼` fʯûÓuÒ}´ðÒWoÑ�󨕑òv%åÎî6DÁVÍ2y®xZX&¨@ygj víHB5ãSMû`‰Ðùã˧FD¬Ö5~í€b:_öz®w#üð½ÍË5?.Æi�T‘RJÊ]~b„ª)‡]=IÌmU©D@±^BÅúÁhжe‹-·Âk©¬ºGµ†c!ß9ÆW Xò˜¦ úx³R·’Èã…-wë.mç»z>ly[�¿:9îjþùùƒßÇæ¶Ë`.f³" U4•e…õÜ¿z PÐ Ëj)„¥ ù£·ô¨azɦ ù‡‡ÿ™;ú†‡ñe8²Z HÍ/¢Aˆq4›:Çà­}Úè&ÙwëùèEjPI ,•ÀsÌà¼k§â\8nÏ}:»6‰túÚ‹Ôø>R•/¶Vé#4™Ù4_iê×z¾Ár‘[O­Gm9¹f¥ÓúAÇÏÎ3ôB™5¨ ._4UýþåÔ¨?ë#ü—êƒMÉ­æÆtx›gÎÒ<žøMÐLûI@ó]¯©{VºÜÀž× ” ¶ž&÷—×y¥!<Ž¢„³1±akÍÏ[Û;L1=^ȾfÈŽ Z ñùõY­Ân‰@ÛÇÆØÂ:‚Öúä@Ø�„mr¢cÝâR~X}¤4ÖDÞ»w1J8?Ëêº7S-ŠÄ†rE§GéÓ_ŸÒáv—ÔeÒ ]‡^õËs nfnn~Éé5fae¸/Ä¥@ÝEjI8÷YfD¡QàK—�Ø s�„àìcÀ¾KîV°X‚ý&.0ìm®R˜óƽݖºetÞz/ ¤¥Qè4#D¾ Úala|;¾_Úy@[©0tŒ y‹@>cI¯!rÍ"�_½iîê8÷ʘ4JjF†tˆúEž»©ò)/\z¸]¬q~F>N�Îc 4αKÚl~jñÀ’‰¤FòÀ©óº]ͽ›Ží~üÄš®ÚŠÂWg F½ùÑÌ:³»Dëx0\Îøyþîß +YqœM$\|dE„ÿžÉŽŸ¸Ø¸�ˆT×™ºBC–üØV,ÓZ=Õ[³ÇlãþE1¾Öl]ºsx²\MÑ÷‡ÇƒÝ&…;³rµNÏ“%�‹7Ù¼É�€ƒºÚ5 9Š»Rá„�uë-Ñôµ5�þЏhùS{¸#3"^³SXÍ+� VÓwèAD®[/\¢*£Óûã@´�¨®¸[ó2ÈÞEˆN;ã1O ¤vº‡Œ²xµÂl–½Nµ"õh>2Çmé¯ )û+†WÆãˆoQü¡~:RžèÝ7ü X§š¯ß̧9fcáˆâ�ûâû0îŸW&ýBÎw©Ùî~Ót™å‘H,tmÛD™ûª’i–ƒFé ¢ñ¤‹�)F±¨ñXC:dE ¶®æCKãB³%idÿ±B´êó5s•Â&äé´6M_Û ½¼‡µÇÛ%h ЋZšz½éOˆ§B õwôà}:öUR #·ôÒøÍÒ•«Œ&\ÕjzߊA£·mÝà``-©ãcd‰N¹ŸÐÿ÷Š]ISµõºø›¼‰�Žê.PÔÞüwR ß÷oà*) r÷n3kH€Ü…øõ�GÛÆ®c-1w@WÆoùÛüšôRXÏÆ&l,‘Wo•×¶ÂŽ#E¶Z…0À$\›Â¦£2ð~íoÌŒ€O>øÔsźO‰�ÛmªêD³EH¼2½jý*Šöh׸´Ù‡¶Ó•ÛqÌžš‡ )>-¥^_ßÇ?ì}Aâˆ[ÎÜMü…ŸMgl¸l!`BMkÌ?w Ú0+`¾Ê`f|ùN$}åžæEè=[ãù½‘®©yÔ£ƒdÓ­)S¿ ×g?² ºÛ»P“Ü=ÒWU! 8æzDB5�ÔëÜÉÔFt¿]¦b¾;rÅÅ“rø�O>â˜Ó=âG ‰ðZfe`pOû¡ãÍç8½³ô€6 ‘ï½ùž’ :Eœœ±¤Ö7ÈcFW‰±ç"Ò÷7›±ÒN¨fP ÆÝjQ%ð“› AŸ;¿ûKò£�³ífFqyf¸×åZ¡ìƒÎ§’�Ì,�=ücËäÈ~lªí: 1ß!hÂMj–ØŒþ ù7HVÖ! ý±ÏàU_Òç™�I»’e¡îz¬�ôSƒ^ÅÜ¢sÖÃP œ^ó�Ø%8 þL\ú�é¢d@µ,°¨hwy§DTb>Y'2ºV2»ì/Úa鯢¬Çþ.‘¡£ß*jùî»LtáƒÜòÖ@£Û.–+Ù, “�ýŽƒ÷Ôýf—¤VùÌéY‡ßåNø0°¤p‹FNGq™ŒåŒ+n¼VGc§Ý$9 žEô~fì©ËíÇM‡ÂáMá&†v¨°­ÈÇÙö¼ñšÿ~•®›Pà™Xœ·aà’Ÿý]üÔ©‚¨æc.W×J^(�ò® þ²¸z 0—¡äî@÷vUë\}Þǿ崷Ïfþ¯®Çqˆ6ÒÇ%:t¡±4”52!¸¹£†oj·b®Ã0®š /Eô»^”oh¡”üw`S¸Ü¸lwÐî*�Ù¨ßÙËÀ¤�ㆴœ-%4¬ýnOÇ:\”3ãä†åX(´LÓØ ƒð™UÁÂÙ‚?üÐŒÝr­cÛ+ç)ë½ÚÀÛ=£>Õ¦þÃ`:¬#¾'§¤}ð) ¤0V:””+°º‰#<“ŽÎ¹œS¿¿è1y›å@/AÇÄ|ÿû‘XÀ/¸R¿YEX´|à‚3?ÑúÊØÿà°Aî¥{ ’ßØÍ³Ñ©åŽ',¬q•åŸNùÚ6Ö¬¶Š+:S\Ë { iøMðuÕ nš²õ(œKîüšèA-å�—,Í&ãM¬¢¯”ƒ‡ÿïïâÃÿ~Sú|;#õæ1’º6v®ÒàÓåçµ±/Óq°?C5< š÷Åk=ýµ&]3n`$”š›Eå©Êo4Øgª/ãoPódj8Ýâ�Õä "A3AWaPÜ g%b�öè ]Uý¸ú8·ŽÍŒ´³äO¸~ïš‚ü?{£9=ÓO ~ÿ£B¸ýn}! �ØFQ8•~Äe\ÁðöGðÌÚt´(»+íjñƒÍb UÖ/ ¶A`'GÖØ$ÁðÂ?ì<®dÜs¡òDNéQ’¿Ás1*XÏtP;l‡Ü‡ýÜGx¶Æ½:_ø÷fWøÊ¼ñÍJq £7NN3¡}¶Ý4æ,6Ûˆú=Óɯ§gR^œ½Ë¯ ˆctm¢u¤cX‘�ÊG¶�ù¿îù·È"¿ÉiÕâ6 µ ¦ØãÆšÚä´–)u�^cîM>�j]¶Š¸šwí^mì÷ÌÇ=­!xˆ*DÃëòÌ™ùS×m¼à¦QÐÓ5îOf7æŒ=ÿÿps“�d·¬žÑ�‘Ð׳LäoÎIC uèëõæÑ%+MGÓmiQÈ#U–ñ�„ºg2¹ë®³ùQ5Wû™Ãm—3µt&êØZÀ{äÑQ 0A)D1Ý¿72íš,— ‹@oƒr ­“9ƒY01càp¤®Î 4ñ«ZÓ1w2÷ƒRz$•ÍçÖ/Sjª¥ª'UwqFÆwc#? ͯX<æiçJ¿À£Á¦{1ßhͧ‡í>Š,b'ÿ¢ö@mÆÖßg(éëS±Y.ÆŽm÷=ß�_ƒi'J áªiÝÉ· «ëÈA4CEðRÁÍâL.š¼ÉLÃv�©£#쪯»‘ í�d:®§¦çýYê�ë:²K„DÙP (þ뤻K*QÔÛ<ª>$‹Ëw×8¨äsbàn»_ø�;ÁÎù0Ц?Vû÷V+ç— Pñ�ºhŸÐ`D±’l¨k§Z‡‰Dÿ„ŽËÒ‚²†ëúðWÖ•§i× mè,йĤ�s#¨’ )"ÊãIÑ̪¡•[{Q0< h w�å‚ß C_Õ�£ïmöFÈÑ¿D:-ä4-!GYì‡F•¼.`œ@¿‡¿Ù£â`òI{—MðÛÓ<”åÚ:Yisï…�bÖÓÈ’ûr…¤�lÓÿ¨�a#³÷u­¥°Ü™«Ií1¼L4/èÿóÌ Ð[_¦âv¸’Ï4àT'¬›ë•ëDIü™Íö Ì/—]º6Mh ÿka=<¿Ú¤ÛÊ÷¯R©þ(Ìõ‚™PXÎ ÒQm!ÎvsÅ �oá”y «�b!¢o†z<1•þRCwz¬öaó¢æ¢Öªë�*"¤È.s4uÊUA1à·f�y]Vð{M.Ê×`e0‚€œ«KÂp]•ù63m/–¼0~„è´‰»á¾•nI»˜OLѧȣÙÈnäe~²ùZ‡ æ[™ E«È6äÍÌm ز¬>ØÆ¿”ŒÉ3IìF"Z†üvµ"¸ŠGq*6jìÂã÷Ò ËØt `GW]M¡á,‰ê_ã¢Bá5Üþ+Và ¿náñj‘Í %ùi#Ù¥æõ]ŒTB?l¥ãwKÞGQ*‘ÞÙöI‹vTX¨ôUbOc"Ð@{ÄÍØbíz É2 üÜÆY7Ljò–€”q]ÃÜŒµ9½“Dê„ØÚ¼)ÎâïöRùÛ Љ{Wt©½häíûK˜bY첨釵ÙÈá\†–HC8ç #a‹»UèÚ¹»­µÌœœçb;Ú#‹(lcù>¯`¸}R£ZÓ¸¯'û™�Uýx(ÜWu�gâqlö¦|…Âðýâ!Bà™ Fºçß¿`\d ä®ô†]`—Pus�ÕO¸\8š·ß5±œ¬µ¯ ,Ÿu¹¾Ð5½ŠoìMbwèYé!Ù³ìiìUÀþs þz‘ü� Bœ ÝœûÅÅÉ `ž‰Á�ßÚò�@èóÌ´¶Ðk×ï«‹|Ô2Kl©{¸a»é—$7Z´ÿýÿÐ@ †¬uª.®*#´¤‚ NbõJvA”G»Å DãusײSHIoé�’—ÌŒA[*–äü�ZàjY&iªÊ:Às|ï¥ßoÚË ý—K/½ \F™^É…�K™NY‰'p)Põ”çR"Žü|Ún|í˜kóðš$'ÖìÃ}Id“'44‰Ù6ù‘¤©-Y‹I¶•y �_á�©G¨ZÀm [Óç‹#´s£nÔ!ãÔt(Û�mÑ¢ÉátJvQŽ'Sé[cz(QÁÇ/Ô‹¬Ÿv.ßhà /ø·:5-þB¾ï ¸1‡¢BoÀ¾0iúmJcŽñ-ÛBM;H8^þ;„ »ü|¥rG_²J˜£"§êÔ{@ �´`×â>ê.J1Xîh¸?Ö´K›N�pºÂ¦N«¨ùåÇ«e·ÖxÃñÎÓýojÕú;¢®®ÎuµFég¨ç\�Gr®ÖÊ3™žïx,hG¸65}„é¤G¾ž8…ÞµÄà�h^~ÈC%}ë•~�í|î$¯ãŽ·Üd«ŸÏJ*Ûºð¤p7}ÿÑO`3|Íì‡Pâ$Rµ§�€~#ÀZÚêAsé7Ä�m’�îã’F+«BX'&pÄRÄ­‘V˜K\XãÁXoj^ªÚñO�¬N�?õsB*¥QrvIýo~P–›/X\{ªH'Å#ÞC-Μ&­zw}@,‹“„@Ìð-·²‘²ðÁÖÛÀÆÊPuB°=좇Ÿ~¥ ¬>;®J·µÀ6^Z!MÙ”W65ˆzõ#ä¾ð¢³·„†-,D¬¿Fa­$iôÕ=yÿôÝ l¢sŸ×°å~KIGdØLµ~p«�Çj#·¯ÿ ¹“¸;½s8Û׎ÔåX:nÎ�sv�è¿'g€î LwÙØ¶í{èZWªœÉ”è>Ö®ûÿÄJ?IOŸµ/ïlãuõ©'NÇ41§ƒ¾l>‘ U�H¯«ÈZÏ#ºP’[œMÓ½Ì'~œÐ-#Ç]Å'qà#ÁM�ƒ–r>áØ�Ö,[ñ“)‹W‹ƒÚ«Æó î�áý(AÓ`Òa¾7 q ŒÞ=&¸§ž{b´1¢psú'ŒÈ•)QO¶TzÄËIFv]Ê¥Н‡OµÄœX†¹™¾Æ8| ƒõ½×1FnÊøSó·"”! |…Í©vèÍ8Jéé匽¥¾‘êö•Є—8� e @ÃV«ÀÙ8/� Ìl¥ÄÝ„Ô-,°É ¥Ï¸>VŸ’iÿ~5€ÒÿÂ(P`Ý—8í Ö�ìZÕî>¼s{ øô`»^¼¥L�«ð¬¢]ÁQÌü£ð‚Ý|�wQÑ©êßÒ€Kz~ê|žì,Á·å�QÚqGâAÃf�ã#®"ä‹Ú¸à¶P-ªÖj°¬ñfvc²Ü„Ášº½ÂâOµ�ŠÑêgh~=‚} CÄ¡;úXœøÐ%á“'Ù”�ÕáQ´”�µÖžG!þQPœQìØK®”»):ÏÖÍ*f�$B™nl÷³Àó^Ñv㘎u„}²R‘˜zÛO¶Q×dÝUÝ®Ìà°9Ÿü½¥’øò&½º�"74p¸ßJ‘¥¢³°•´êü˜ÊðYŸ”nGÿ™îo,®ÍBƒ­f©áÑ„É LZxÆ (7Ëwàñ¿köhJÙˆ)îdÉà Ž=XÎÞK~-<5†j\ ±‚ˆ}/Ž26ýÀþq€ë6åª#d$h¡}õË�f¼ ë–bÕË�Œ7¢»îä€x¼ßúcž�uT(ôÿ"5`¶äã‹Ø(ÑüFÿá…°ÊÓz0–”oXuk<èÁYuë¿5hÓuŠjWvwËiM¿—x‘ÓÑ>Å«ÈA»•j˜3£`ŒªÜF ìÉt[y†K”ŒùBÅÁXýø¡ ãë^Ë€�{hk“öˆ ’‘y­Ö¿§¦ÿÙL\p_L«j90§¡æîîbX0±ÅUóº]8ö?3b~=¦.i±ß<1Ú*kWÙ»ÜÈRƈøÝ•Øø‘àl¼g·#Ä–¥)1Ç$@¶m[úwòÚÄÕy±SÅ]Ýx;F-¤‚6·ÃšÆìÙ©öù7çÈjZÄÝ�Rfèž+>¨ÂW÷è4!‚lÚ–,¬ø‚xª<6¶®:2jÚ»ƒóÜÇŠ°ÜËÐEÉ!„e—ÑÖ…ó»‹„ Ì ¹~M0x{¤9ç›y`ijpÁWl#X�Ç&QÆm/ (#*—Uœ°ç)<]w%2±Tñî’2Òy ¡�$Hr7aÉ¡AóH,×à~Ïž^t®Ì”4S:JpÀ…‰4X�ã.‚{²WõzÞÚÎb�x×Þg­‚’M”%2:oœµ™é x„Ki¤PeÞaòöœ ›,²a¿¾Ö§uŠœ¼q¡Á' :«ƒ»�ãC½ˆòÓ?ÙHïFö¡•xŒú¿‘tä†� ™Ž|#5‰Déõ‚sDAM¥Š¡þKæLU^Ê/+ÆóˆñmsZÁ¯z§&/WoOJ8¬1XÔjžpâîk�ëÑ>„è'Áó@t اšK´š¶X ”>l‰ì0l Ðg* Gí-ê«Ô¦ÎúrQ#ÜÄ’Ýõ]á=\´"T5uyGIÛN?é;ð9Ìu(ݦ¤A×vP² lÖþ« •‰öÛøAú¹�õ³YKÞŒ>’ÐÉxïË)%ðÝ!6&8\±Ϙ?�ü˜oðÐi3P‡ßñ»ŽA›–5-Q2˜ÿýñR‹€¡ÐÆ_ç p£ËFҵ΅�IŒ,?£+•¥ Ò)|rú»þOÿ¦žãÊA–á*·‰ûª;ÀoïÚà›x Û눵7âl5P>!R öÔ¤RˆOûè†[“nŸj9•œ8ÀEŽßW#NòEÿ( ËŽ'޶²ÀÂàA‡Éò�¹3ÇÁðò7[•¼+9ÛÙø?›{–Ò‰)$cG& 91²×/™Z¨4Æe¤‹ûÔ-InŒ¦ åd¢Õg¨sãƒ�m#ºÿß³Ðä�ÙAÒ2S)aEÛ67xå‚°î­Ïêx{ïkïw•¸²¨ô Ìa`°4kþË—Í¢Ø)ž$§¥šJñÌ'ÛbûXqê�|L<;ÅÁ`\ßíÙ´l…ø3ü•®&Ò?›Œë“8(ï³Þnë\Õ@l‡ƒs�EJuÜmPv“Ô¶®%•ß5°óNÑ‘ŒÐ<Å%ù;®{”¯ûà‡ä5¿‚ê?ñÃF3dÒFSn uþ;çbðž‰Óûæ>BRÜÈ_zlx¾Y�,,|œ¹ü\Ââ@6ý Àêßa¾ßFª^t¦¢ÅffRYQqs­ü K=dy~ÂþÞ¸Ò¾süLF†wüåßµlhZœ*"�¥›¨¬ÕRÔ.kŠ,äYAc �ûÕŠ`ê�'ðôoÇLZ‡3íTD´íºwͱ‹Ù2RÉÃ×�Î_¼À�œT!®¦<<®13qõ]E¹7¡“Õ—V€¹z†Ý»�‡“­©ÓÙ¹†rE+ÀO}4eï–K$x¯3†üÙ”ˆS—`Îáø„”(´Vwb#U%CO3I5@T“gÙARÉe2³&ͲË6œËª×+é“nʇ`Å•ïÐ$lù¦OiŸ L/µ‡…±9­rÂ’šÔܦ`]ÿÇ…@@l®9ó|¶½‘•Yð}ã9e!À§v¢‰Gœ³wÙƒ?˜`a®Mépæ18 ¸¤�À4ïZª1ò$­5CÃÏ8Ôo6 ²a‘±nóêµø@ÅÎäѲº:pl ùåj¡ëööÙa,’xI݆ü#ÞPžÙÝ@ ˜Ô´öÕý™–,éôt>ÈS>ŽÑ˜§‰tAÏç€ÑlÍlŒ3Z>JÓ«5ŒI™~—µ÷G-³dŠ`F�bÞlÏ¡ØÜ$��kÆà«°K„Nƒrošq'–à0nZÊ{XëäOD æ#cb³ScX£Ôþö¬Û’agÛÒøI;ˆO°=ÓZ$œ¢é¶'=fMÀ—ÏqW*€VrõËÆü¬wiHŽÃ¶mÛ]A{,–´Ú2±Ñ‚ÌRÚG*‘iј»)‘Ãɧö|[ÜDݦw/zÐiYGÄðØìŸe¯åýЯ¦¿ä}Sý·àç['ºŠa®#‚›¥nOn31– \ Þ"?öHy™µE@̪¡w­À@*VêÈéÛ¾ath¢¶ BIV‘蕟 Ô…$B«[]0Û.TÀÓjR346cná ÚzHøì÷êþ>AÁ>³#^\'ˆúñ·LOÉÈÙ�wƒ„¦ÆW™œÅS %6`Îú }ÆD˜ËÕê¢w%tµ¤Ã±®[„¢k°$˜¹`ï “‰(©9s;KÚ¼œü—œX7é:C„KÔiýªI0Ÿó�µ{>8"„y]Ø®¦:­‹dÜeô¯Ê-úM!$àêßR@?7výNÉÖz÷éøÕ•!“¼$$ï/Z½Ø¡‡q1Ó�K‰Fj¬ÊYèAaæ-<€}xθ÷ÙÛÂ7…j;‹U¢NæÕZJâ™f…`J Lz/ù¶ö"œß©º’%‚¶Žž Ä4黤…Mê£a¿‘‘gL˜ÂÚ‡Ï~¤ ôáyÆe†qÛ3Aö_j¾ƒ¢†’ãJ Ÿ¨(:�çx²­¢EWˆ‰Ùá &VÓŒ‰xzD;l¬„÷·€þÛZ*»æ#à–ßG¹³j‚Z*]žçRM7@Ù`Pêõ}†¤/üŠ·™hœ«� )æì׎2K˜h"¨Ô?æ’"̉×ÂÈ:^Vð²‚æßùh…{Z¥Ã�b}~ AùiªuŽŽm´l(zq7á¯ùq·ç¦ó± 9ÜÃÌEy‹Êß7a³tÕ‚A}Ç>i­µŽKØDtÈf1*EÄfu'꜅x˼k·Ð€�æ¸1aÒn™Ç¦�‹ëÀ•Jv Js" …vGqJV9Z?á9ªÙÖÞ& F¾COEÄ/�8/d 6ø>#Zp^p&tWÔ?Ñ8üXÐ#•8¦ƒÓ‚Ô@jé50CñBøÏÊ4 ¸­ÄU,­M}°V,‘)df.1õØÅóF!M“ûS‘"©×®†jýÖ8t©�‰ym!¶žGè&?ôþ°íLþIéü—Ÿpì@åCåa‹x‹CŸ¢S s.[i³ÐWbÊé|¢´Þƒ ÉUûqO¦G?‰L°Ì]ù‘|ô9>M©~„¾o;„V Í´ú� bÁ/¥ ôsÅ ¸óû·j^bim‚íÆ½R³|gpƒ­ÆCýµæFú�²…üú„èm2lM*Õ8ËÚ¹¬ÁBC lf_Öóvû41*s=_k`؈Žâ™SoܶFrµ'ÂìÞ;ŽQÇœQß Ì­{¢ôGùDa£Q¬ÔÈølÈ�D@%hã¿ÝÝÐÌ‘=n=q8Žd-Çú„dº|á@å?êôÜ \¦f’²ûVlTì|¬B�—˜âJ.ðmk ÊsŠ-ÓŒšKÍê¸Ò𽦠òµßéíÔ'ŽBî}Áx¸°‡¢¶®qEP�r¹‚Âöâ¹Rf«9'2§Ÿù Ë/⌙ûëŒ=m+æHÅ[òþ?˜+|Ç„�­´™•Üÿ¸´²PìsÐàŒá6ÄL¸AѰSÝ:÷%ÌíX“@*.BÊ ùù@qæW’›'}fŽÈöÒ’À¢l)SV}7L£¡•nkÝöÿŠñ›SpM´AŸØd”TðŸ Ù�# s¯öÞ(õgÓ�7hÞñ<÷¿ß\Xºc�Ʋ,Ô±SÈð|Z^Ø9ÑÀŠv앙Ƕ *öìMA4q/\Ï*q{Í.Ç!$JÕ@K†WNOŃùǕ욕J %m˜3E‰Ä?ì…7ªCã!GPì)ñW-ΪaeÒØŽ«Ød¯à2€\C8U°œÔƒ�0G»Áþ~Q&š�ÌQvp å_ì|YœÓ‘ôU}¸¡$#j Êê|)í{ЬÀ, –0N[Fß”òsͤmqò¿Šm£­Ð(#hp½q+ÈýLjŒœ ¤Ð¨–ï?×Q݉H²Ê†h�zá™Qz2½o¦R8Á �ñÖÊìP¼ê~ЧòaZ¤�D+ÈÆ ÙÚ?£5ƒû'gý â…ÜŠ{Ø;Ã{›�aÝN¨ß×IJ †³-‰°‘µ•® =›–1óÞãNÚ3vqªnl‰Ðs,`–ŸÐ±VòÖßÄÚR-Ô—¤öÓUÍÖŸ,²U™ºSËåQ Á.0 æb­Û|Óh¡Tk;WÊ/o:ïÊS¢Qøm ÛSŸ÷iÿ<ñJ>L¤ sg¼§0]yŒ 0 2©Oiá"xŠ:Á¦�‘ýØT|œ)àŠtBmçvÔ|òÀšb¿�¥×ÌÝG€¼\€JÝèêroèÅËJI·†íšH”{4+°Ùãïç?ðJžŽO”IùˆêQgÔ&ü¿>«Lÿºìtê�+x>†§)�BU¯"¼Ä”tä¨fü?6ÉÚ}¸ yßvÙ¥hõeß&sé[~™d3ì=GŽëëAÌeBñ§"î&p†4Z¢áD¤òÀZð‡—†Hí›’ˆ•¸ùgJ~^ÇY2Z>¯?‡h)Î7Ÿ�%‚U°,>º$bx³à�éP†`zVã—¢\©pñ4Á-о‚Ù iØçŠÃÜfØIE¢úkÉꙘ#@®�W+¦¿õXòš¥Ä&E±ÔâÑÍÃ3Ž%? ˜ŸùnGÿ™îk³¦:+³ÒQBšzõ P¯6Ü©b¶Ë0·hLªêÕ¸œªT4ͤÚÊÊDzduFº%u–L—Š—©òšÖMYÉ& ;öY?ô]ø EÍ«%nU?Ôã”hú©5þj­|Gëv»¡¤GYw¡H{+d]òJÜKºÃóßâ¢y*˜ñ:ai"ÞgÛùLØ@7 ‘Xª!ôÕ×ÂY{CYØX  pJÝÆi´rR­ ˆ²r®w<ˆmsœ„ÖÛü–>›ñ�ú& éÎwỜ˭T&ÉѹH™ïž�ìÜ;9–}4]á—õ«û§ŒSgi±k› ÍÞw…3—LE|î¬q_WÝ.]óÀ i+ˆA›ý5-Q2˜ÿýñ2‘�pûx)Yè‹Æu­N6[ØáU÷/­ˆi÷×WŽ”�'ñ­#Ÿv4¤–ÀÒÏr$J7J›F öZ5ñŠºê2̉å5]úR£k»?&ÛF;¹ï.�/1þ5sàXȉÏåEI…<‹z8ƒ-VÍ•W]QƒZÃ=åi¡u6Uï}L}÷}¢å2â’¿ÛÁP0UG|ÈPvù�ßݭş몞U‡gTÈð}‡¨mîÄÞ»š‹Ÿòv=mŠG)x ÿ‡sÚŽÃÁñ9¨º>±uä e�Mêre=Q¡C¾0?UZø¡dÃ%J¡}:ý˽â0®ƒƒº,OÃ,ÝÑ�hΑÙ³šƒB‚ëŽí#ÝwÅqgð’-ã�uÉÿr_N:M7‘iÄ<x E‹;Ý×mWo]ü`È'MZ´b+©òÖó �Nå<רa“HRçBçûS÷~‚OLjžÂ÷©•íìÌÛW<^ŒôÅ|·$- #lØq¾×ª\/X‹ S ¢�Ó8±a¢³iÄ†Š‘Ô¨Ã]ü|ј±æèeõ¥ 4¼ ofBÃEÑ.eSÆr8HøC‡hʳ–âtÝÍ$ö憓´½‡è _†¦� C‡í =G±ò?Ÿ±–ñ‘¢˜ŠéSâJap³ "­švK@�ÎhŸ>ÇŸ¨k>H´dCv˜’�7¢ÃÑ,šÑûÅÊ+6Š× b±6ZóaÜu¥4J4Ä=·ÿ¸³pŸ¤üâØ*«Z+PÇBe²Ò •ÞŽð-t7�ž4__8-@š!š“§Àίñ±ÿRÎh~‡Y«Q‘Â|}’+&ÚzÅÆÙ`§nÊV7rÿØŽCù:ÇþKÜŒ…ÚŽÇ©ÔÂÿÖ�ëñn{/Õ•ê†:ÜL{ËÃŒ�¤hVHÄ¥뮈~Óµ{Çë8Š@sx(¦2IÊ0Œ;‹U˜ÑMqÀé5÷Ûßh ™ÿsº ü®ÆO¦ˆ:þhâàBàÀÂQêµ0šyÉX!W†<@ïc³û†°Á´Ï®€Ó�Ú†„ç/Îq°êIMéEÂV__ ø;OÛ,ó˜¹ûtÜWðÚqç}È.¶ªôrå:ÅW¤ šñÛx<¬Þò"ùôÇ(ZDö£âô>„²Ö÷ˆc>“^3¡¤\Ùk—;ò~–åú›ÛÝs:ý·ŠEéßÍBGÈb󔶈ój<£Ëö½¥¹27¬”'ƒýa“„Ñüscš i“›MꃬivAÙpdÚe¼•d²•Ò*kÚ.¸ÊY÷a‚ Óß4«ãÁŽŸŽüKãàî+áDÁ¬ÝFTVI• +rÀ@sß†Ë úaÄüq€»tC°Æy¸�NF]½îÚts¨Rõ®;ÂïjUMaãÄS‚¦§ Û—õlî,'Z‡Tc´iéDQôÂÅN=)&£:Ž•½í@‚ŠgF†FX›ax•s‹H⌼Ǒ‹iÍÂ^Í×wÄÜÅ]ðš[¬�[õ Q¹õÍj3(d:¡cˆ¡(¼§T\€#Ãw‡ÜÅAÿmñÿª"�+À«ÕY2^뱩�à¶RØÎêVrµ(E/CRñ¥±­Æ‘ÖMŸÝÌg;TjJr²%ØÃ-Àð`z¿ë¤ £Pêâ"k®’,z¶X̃ù{¢ Çò…ÍÊߦVŒ¼@Þ¼šÕû[͘Wvûj„—ˆ�RgÌû­°ú-Å_2@oé3¤Ý[€”^�~ŸÂ0Q™ˆœB ;8c÷ÂŬ)×ø:§?ÑC§#‹zyΆ· D6o,±�]'Ý�k8²÷9.l£X¨eJPFW“òÃèB¬bÂ�=òðV$Ý,g‘¾Ûr9ëçì¼ÚFÖö¦O-�â`ˆc ™Ñ®-±€ÚÄkãii%¡�Ÿó�ÞJúniõÕ™o"òµFý7�ÄÓévQÃÙ(<Qm:RËw-uB2ÈK†NV´gA¿þhùòÙÚÙë¹›µ"ÔSù;ÈeÅî�3è lJGI‹tø\ÚÅAwTbÂQnª&\¥ˆp§~ˆLš" � 8WCítÿ*¬/à\úÛæh¥�9é`q]ë'÷d”Ð…Èž Q³¸Rsé'è®3 * †¯æZ$À•àë .èºÆL$�%&âÁŠoõ¡á£›ë… _ |_,õ´ßùÿ³û„ûDƒäA> º¾M©ùG-•~kL«‚š‡«qÌ£ ãò¡õ| RÙx-6ådRéo©Ðˆ•�ÝÞ�Б±Ô‡¬¿7°|Tü´_9N!朓(“ÐK Á�ÊÈ»’U¥2¦\�è$û([ÒœGS{vß݇5:møLád¬›ÏÇó�ë“4ŽNšÚV0æj½lôsè׋@£bã•r­i«Û¢uéñlá¶³(4¢I»+yê |¹½1þ‰“ûŠ„"„n`‡;×uÅ›Ià6›}mGxñÀ}�†Žær)Œw �pÈpÙ”Ÿ¶‰ûdX�zÁ6^I Ž}eÏR�¦6Ö/b/ÝïûQ»…žÄS¶™º,Y—‡ýÌKGÄøÐÐÌümÔBþÂü0fc]ñ"‘ØZ‹üuŒgHCai'àMlÆË±èWôÐ'®³âfë™nÐ#xŠ3Ä÷@0åöÚ‹ È�:ç{rµ'¼oð�G:òwªî £B\J� âë ‹�s}g(½‚üíÁ�Ð+|zþÿ)õ˜jT°îZ®Ý¨¹¨àÍ7è±Â7ý6©®¿->Ѷ‡‡h|·×ÂK-¡y…>µS<„Q>>/cåÕõûAĺÛSñ�ð@±�Hžé¢Ã£ê9yǬ»µ£B6!x$3#ï Nän A ÇÈqäÆ)‰€öIœîOŒvýˆœ¶~NXaüOÄãá½O°ÙÆÇN.º”G€DDgœX 8ƒÉqy:¾¶­çÕ‰(xE³j$`¼d ‡nµgI8 BKhëDîŸÖ6ú3\@ W/õЦxÁX²-5ô¶©H ��´©Ê€¼Eù(ÊÒ“bÔð ñ�/‰E¬X¨þ·%(æ âldŠ1N˜†’49ß)4ÈY!ÏögˆöoIØ¿úBõ…�죒ó®g~Ñɨ‡J%q¸?mÛ«Ävæˆ�ŸhsøJ!Jƒæçø[Ïs€Œ�1¾"3¶<›Ÿ»ZHfhèÆ÷@b‘y•exK?(øÎà äõ aú'qc9­Z»+Ø9=8Ä{~ ²œE|„g÷ò­P^$NäÌ”Àa�ªžÝráÕµ|¦ä/1öÙLê,‡âZàŒ¤Ðµ4�; 1”·dcŠš›`£�í.LÛÒ’§¬ ÷A·ë‹›q/m¯@b©×€'ªiÇm„ž:íÍŒ}R¢*± Ý@ê“3ª¤b?QsÄ·ŽÌÑC‘:¿ ·�=EêÏa  ÚØ”o0ެ+/ùÓ±&Ž©¡”@”�Ó!vß À¥Uy6E–(ÊY½Q…ò�qª— ߘ¨P/Û®rù3R N—‘ª+Øòßyc±7ÂÿìUÄ�íæÐ& ƒÅHµvÆ¢ìÿ×"9;èÚKÁPÔÂâ!ÚM�^‘+3�9­Í0.dÔ|ªûíFÙ.;ÿ ýn½ŠŸmƒ‹!–XéªØ¸Í�Tà *?ku%Œ ¤иA¿Þv ‡ãŽìm’¶7Fÿ;øDgnM­=¨ŸÜxû�T¾4„ä�$�u°Ò›<i/A±_SqîŠí‹\ÿsB8û3‹ëî@þ8Á¨Å/):æù‹€Ø¹aøµÞìøT9†E¿133„”¿,´s„Ê#–ð!¨=èÌ\�Ý1žeKB·¤�ùæÞdž„Ìérj‹Ò3ˆ}'žØUš¶\n2ã$ùkÑâC ÄqFN¼˜ïí�c3‡‘dI ŠIó}õ@?ÿ çKA¿þM%J4‹¥ÉI‹p P×;¿˜ôÓÁš(L+hÝ÷;æOÞÜ}ú«{Ô†_löÍ÷42„À@¿ad}‘À–hÚŒ€úå ù‰�ÎL¹j¦ƒÐËèÖQ½‰Ô�ùø+Ñ�zª±ŒÀ^Rø¤Ø¾m ’Ôr™/PÓ‰Qó…Ñßoz¯*3ó o¬L&•`îp¾yø ~“昹�`ÛŽBŒâÊ_†ré�»¨,üf~æ�+Óa ¼£ÿëu¢p>ÄnŽÏð¬ä‰T1�‹o�ÐðyY ídŸ²!ÇpTtè5ùwÁÕB)ÃhÓ*ýŠ_vd? |¸‹Ÿ9D%s»³ä´Öܱª’ §>}_[ýbÇT ý'_»Ÿz_áŒCŽ1æà§”oó4͉¾!OxjòÀ+ˆÏr¯šK}òüŒÚ|��&O:½sm•é �„ðŸw$\}M^œ[‹.ºÃ,;iÕ‚aÚxa©âuºÛ v®Ü°Ó ×û ‡‰–Ò¹Q/›}|ëD¼~’9Ç´D†ì4/ïô懴bûÒº1[É-èocšØØ;õ'vºVzV²$þçU²«âÆ%³px~E=pD¥{”Ë›ÑÿúêFˆ‚òg˪ †«¿Í±Ñ�¹%5ó5åjDeª\fïP´8€(˜ý^·"�ÊŽy<†´ÔfqjüÎûŽÂƒ…»³'HÒ2D[,\éOß÷Qo&X¡„±{ã·-ù”Õ<*>kn¡w›pb69£Ž�Ò·â]þ†Gƒ\vîýhµÀÁ¶Y¢Cê7¥È£G(ûè �ÈÍ»´&]$ü[š;ÙŒY\2É»õ–7í‡dá�*A¸ÅÒ!/^61•à¨ùR<"·ÄØ4ì»À&_(ôÄ¡•aç>ÁŒÍ_µZæöYJÓ¿Œ»Ø#VüO¾þ5Œ€ýŸœÐY>ô«9M&/ì\2mñôà; ÔŽ�+5®”GÎõÿ�ñ‰“ ¹VµXäýÚ‘¨+Ö"±Ó"â1SÞæI;`²^Õ°ÙZ"T ÈÐôTñ!ùNx”¡ÇhF”ß cÿ¸‚<Ûî-¿bÑž¦ÊŒÒŒ¿6ÔÐ~w>IdÅÚ€c®‡ EmK�Z\?žÖ_¾Yb)¡ýkx/Û®ÃGü}‚ÃU2,Kƒ¾Q²Å–ÑŽ;´XmUwgÍD-ê2z™»@‰J£ÄƒÁ•º^{ÑJ<& œMU�Îe‹cäÖïwhß‘÷µmÒð2j�Ø¿û—çž™ˆl?Ôò@‹EÛnç ?ÉH„Ê€ äslñ·­<˜$ux¢+¨µd¨> à镚A8ª[iƒÐ·>ƒgp^1ÎîÛ»w…r®�6Œ¼…6C¶ad pÏï Çü8Ûö`—qª¤³CØ<\`2k£¾—Ì—#ªÍšjµñ oV,p½* Ê1›IOEšž:ønŠu]vTLšöÀ‹ÉµÆaó¸á°ß Æ ^Ü ;AÝEv(çœk#oŠQ |¥˜[A�Äñ_T¬²’€?¾¾&/4ãìeûmñ©Zö[Ûm+±[¤K61ÖJ+lY­Pï‰(è›ó''GmÊé˜èVÑ“^äcsÐ ”Ou=®¡uµqspã¨nk”Ùü¥ˆÝ=zð£[µnÆDJ~®épî^b$ö�Ж„§ˆåXσE{¹Ú†]kãÍ«ýn?Y Å·�,ÐǹÔ{˜”#Ùöä{‡*ý¥ªÝÚž¶U=çÑ“Ñî�1A÷|T«P»ÕÖj‡�VgÞP\ÀöN‚8œM«Äw§¥©$Àt[ ¯DãÁTÜèá©Æ’á%!^ «ÂÝaC�%þß܈Ä@ï-‚=uQäXèöàWt•¿k¾ºÈS¿úEj{ÎIÐåz°¼ï¦³ñ½˜E46z´j®�dE[ÚŸŒ¢™ÇÔ1áÿìì”òIxd‰òÆÑS¡Ëߪý³E§M?–dØkˇɅƒ­”wf‡™G¦,ÈPІh€þÝ ½©ê{#Ÿö2•›+Ó|wÊODí»–<,tð—|•ùY†ˆT Kîú&Ðô Ö� ÛB®Ô,¬�v‹bía³Ž†×o˜‚º#(³Œ«Ý1# &S©ÀB%’×H¨‰�kÚ@C U6ð¾•3• 6+„µ‹>hRŠ@‡& Vx¼í¨Šî‚èzÒ1‚¢ùá–h�ÓêøÉ—L¬%DíÖŠp2 îZ|”˜Ga—Ý©S1bÛ ØŸ­Ôk+zý?¥ñà��–7£Ï­Es‰ •ô¸©&hé` šâ5¡RعÒqËP”#7>¾«‚–Å\�†•SËB[«TZx~!p\{lqÿ)£öó²îªjbâ“y¬îÄ(,N©ÅÕÌç”Õ§ŽlåW^4nXLתaß%Ó[6&&©ªvºB–&½Ö´Ë%ù$�‡Ò™ø³¶ÂîÌJ®Gð~a«Ž¹Y‹š–9qÀBkîókUÑå¦0 ?v×^èÍuvɽU4A+Díømå¶fÌwÔ×ßvøÉ��öA¦Ê?åFÿ-Õ ;â¿ÈR”Ël@«xa‹lôÖJf¶Åÿ~OÏHoŒ=xBî}-N»Ð]H-�}ª¹Ç�Ô,H“¿Í¦��–Ò§uûýë–æaANŽöÆßïG:?Ìnp«+eíàf«¦&/vÒþ°·!þG²ìÈ¡"êî+‘è{)çUÌÑ·d„0Êvgéû¤<º½s�ÓÆr|ëxÙne.k‚†Í]†½äóÄÝáÀbõŽx1x•ÇùgÿLc’!wî/ÞOc£J<¿ƒ_›SÕ /™“¹dé'8.¨~w§àÁ›dÖZ‚*åWýýº³Lý2ãÙw,¯�•Z/ÛEcçDËï’ùÏù ^‰:'‹¨û"W¸í;aQÚü¡<ë¸/áYû ™»RÀ—"1Í jý|ê©\x‰ÓùÒŽhÃf¸ŠûÒ�*¸öó¼Þö ~4¤ÕócyAoñ#>¢ÝÕÉ¥%‰M‡rþâZ²üL:VDÂ(à¥\Š+Õ eŒ´î<"pè: Ô~Èo‚âcõ~Ã{ eµœÍÍ¥®P_Òn‚LK$déŸÂ+óI£RÇ7™˜-·øÊ†èãó$‡zU0>¬ÍžÊ­ÁÃ]öCÞ4ܽù¤á®:§ËÓƒ¾q·º3ròçUbL;ŠYXˆ¬€¿å`4ô'â§�‹Ø±À†mp¡¹×ò’J Ï`�G¼x»m@äh!_Ž@u°ë]=/åÍF^J�B¬Š oZ–u烵{Á(é�Ÿ @6¥¼Ìä¸�g£q6²˜ê[@%¡�7¯Bw7¸¦tm€ )¸[5Ìð…�&+2JË©kœžùP²­Sc49-s+- PéÎÂx%kS¹KŒà÷÷m7ùJ°¤¯TB’ºe: l³6xµzÎÅ×DLCOiÐ>ÂhÐ߆÷Á×;Íæä=á¹é9tz<‡œò/ŸŠXÃD~¿‘*䑬¹-©þ„¯U´üÑNítsÜ )m¤À¾<É]Ù·7š;>?´2¥ä”ÿö…Îö!"T2+‚_AõjeVÄÒ ­¿_Á $÷£VΦ(%¯•1æF”qT¥,;)Kÿ†R³B;ûòéê¹wt'Ú§f2Ž“ì6¶46˜DJ›t¹ôXøÀ@ÒØÌï�X•UÔòùËšÓÃ6e%RWOÔÐu£T*Á!õ·Õ‡W=þ�ñÕSU ¢d�; 4ÝœNš|ÁJ|£ÚÌ5Õ~¿É¼�ïéÑ9¥u¦øü¨râ…(‘ ÿ9ý>å9yÔ}/tuý ‹ê_vR±1QUU¶"ö躯,nJíòÛçß*J²,¡ñ‰³ÆA…ªš{f°ûbÌõ•à§Sô7©dc/1"¾Ì±Ðܶ:œ¢+ªtŒì_”×Mwäð`P·=mûš‘ Blÿ²Ôu6Š-Õöd#Ÿi¨‡ÎŽ;éØÿrÝU`÷˜°lÒxqŠ0CŽ¿„ýp‹pßd ïAŽwy‚z£!·á $ø µÆãy¾a&;ûœ­Ó²äG Œ!–¹(z88aƒLçó™EKøÕñ™[¥Â°ÊrÂsªú˜*··í¨JC1³s ƪœµÖZg6¿fô ²¢ƒ!i8¥ô;Ú!“¤<èï©cÒ w0â¤%ä¥��à4å/¢y÷ÀìÐñ ¯Óˆ²0[?i>Þy;SøåZ§x¾ü9Ï”*`ÖnDXH#ÖâÅÛ‘‡?ÊêP ­Â`þO[ïh[ž•ÉÐÜÄT!æk‘„[QXQˆ3¢€•»äªitçn_O(¼WÚZ•-±«2?9৉³š6Lö_Ý{×,ÛZ7¿þrIÙˆ¸þÏ´*­K[�•�ðÁ—ÑþÈxyz5dY-ɼÑÖ+MžÍà¿™Þ]‰L»úÛ«¤“ËOÈî§ó ämxí�sÛóî' Ïö¤‹Gd(¶*[†ã0+ç…ß±¡W˜ÛKè‘ ?ãžð÷¥”Íìˆ!gyTÊ]þ]¼–½Çæ -�¹Q„WBO{mÄ´'xg…$>ËCPªîzÊr�¬T%'÷7Þ‘ø V•ÕBŸ2žÿ³ïAêKYF�$<ÎDb(Q0W6«ÈEÌáE¬lV$Â^üçðºØ4ãk X“&Âx»©ŠG¬Ê_Žï‡õoœÞµ¾á§d}Ë7qkµ¹-¢—»qûüÕ~‹td0ìáI²)«žùÊ‘”QY õDÌ5›Yß_ûIé­—SñMîVªu Œ3@«z£ž|j¥¹³<@œ7ðûøž‹�õVÃK·Z³lºb¹²äq»ï—�Û›ûA;D|WÜ9çr蚜LJËäqÒŠjÓé¶¢M³’Ø—ïåRÀÄ—ü ÉvìJ°ßîØÅŒƒFµ¥]Åš^Jƒ3v± N~ á\ª¤O=·Ì—æ'åKV·a‚t|a«Ì4w‘~ÚãU« ú[u`(²l‚ÀËAƒS¾\j¦¾â›G3ü5òñ(Ì©|os£Óž�ëåÜ{Ngç‹{@†^h”:ÍQÌäÛ6a„2ŒÐ¿Ôd5_u2è4ïxû­(�ó!Bm/(_êâ)™sÔÐïŠâpñ)&ÈþmŽ‚?æ4ël”,’��þ°Æÿí’Z¥X#žƒúƒš¤‚�¯N§¯iUœK¢©æ·ÍðX™p<³£µMÖIf?Ëì<úÀ+d¤ºü&­»X-ž'áyÑF1®~­±#éã1w]¾á¦ ÔwBÈù•–lO¤K˜åħ ظÈbîú#FؽÆÕúMÃ,´Ôa…Õ¬Ï�wŒøçzý¿ƒ¿=•6z^hñ¨Zêå•$ñ44Xqh¦�;ápò²N袢[ì°D2Áª­Tód8žÞum��n['mxë+"‡À¥"ÊÎÜ•,h#èùܺ·vGõù]íLu˜¡ùïôqÁ'((Ñø ŸnÂ� ƒÙ�ZÑ\±ž“‹kߨ¦oKÄ]²š9ó™ûÞï;PϳŸ‹ª”÷©�&dŠn_²°TE ï\N÷ß™‚T§uumhûéQÏÉô½ -•|P¤èú3 GhŒô®6nm4Ÿ=ñ§ÙªË#$Bn˜ü)ˆ»gš¶à©(Ü!Þ¸gŸ,íèýAí % ÃVI‚±¦I 3넨DÐõÝX+3›‹'D)¡î,9pËõVÂkPá%FÐY¯“zøqé|B(ž©ËTÆ�¼ ºHNÁ!Ü=†CL#xú/ÈI¹¬DÛ�M‘; WÐ5þ?x• l’7Œ¯ÿGQ0“�¶ °Å;ñ7¹1…^0f¬…gmùªph] nß8gq�»i¶ï�V´×Ðü ÄVn/�âfIü~žÂøsb4ÿD�)�šöžš¿�¿@¼ÛW ÃÙãÉYLÛµ9 Cn…Mj èÒ,øq‰Xc~4å ÁZ“µ–‰ÖhÇx¥÷­iÚ9 ùæ1Å9f׿a4§WØúZšSs †Ÿ¦î‚;@ ãw僷hn;¾<‰¯.J|@ J£_sGMQ> P·QÓ>úu#ŒC¦�®aÞ¹Ú̱-æÖ¶ÆkbÂé§_nj-»™0¨SËen\PI¼Âò#pëA4’ÎFèI�Î4S�ÊH ¯–"ÞÓ%¾päá5M±€9ŸüCÊpµ¿÷k»Ž ¢%˜©ÊÁ×h°¶îg@€Îë6b}ÖYA=fªÕTŒù,V*½s2fÐôDðiAР�p‹¶Ù—„&0§)ÔÝヴv™VÚ�òÌ€ÓKòr 8`ÔÄ12âãøx ’!O„  £õy\·á®¡ðx’1RÌ'³X9ÓbDùÎÅt“T^ñÕàÆÍ @ÍQ­gîñfv\ìKز8›Å_ù¾\»a¹Þ�³Ä—¤BÜ!i£òÊjABÀPÓƒ¦ê ¿<6å»ÃÞV‘{ÁË¿oúîýE®”6óVe~o‡“ˆyr9–*¡1¨AÅÃŽVw€ ]ê¢[œ®e'Ÿ¦"Y`éõOk ŸR..+GÖ…ÚƒÆÅ‚£&I±“øÑÈî�)k!v[€•楃ö âR?kÁzLŠš×o5l‚Ñ̨%‘»CNüxó9t`ß\Ì–lvŠƒoyñø]øk$‘f“\ê‡ õ‚³¦6 fpúû€€þþÞõÌI­ Ë?TÇþ¨ æ±FŸôm�Ïy‡qˆ»Ñ\!èŠBJC æX×sˆßUuàÿ{2ö¤°ó§´ÌG¤Xåà¬M{èXiÿtÐNü¶Ê5Hö.kuÐ2qõªœ°UXæy!Ì|ñ‡Œ T‡~ÐØ¼œ,P�MáÄ«ýn u— ÇØZ>Û°G>fùî¼i(ÿf8=�fÔà ¦äu ÄÁl‘?Mü½�½äRZm�ÞÉßÝÒúrºØ'jCgøÇ?Ç ¼–"Û�z¤“ô91ž‰Ö!³»‚¬ËBþÊûzJ‡ÊK|…ÿ‰Znfõ˜† &DÌz°Î„2ª„*¥}šÂôå/w_àZÍ”¨³4î" ˆÚ'«/†2¾ 2¶ù;mêüã RÔ}\�82�8Pé¡kÂЗ⵫JªŠahè:]‘þ6Iš©‰ÙŸUfüV `ß…åúM1’pÔV>ÅuMQ½g� �œx1÷üdøËP‹eÕGsQ• Ÿñ6ºÈQŽýç¬ÞcÔÿØë¿Ñ8ç"JŠæ½Zç`Õ¶=ÿjB9©Góþ´2˜§zÁø—‰þmBÊJ:À0y¸‰9å¸Ú�©�m=4mrâf]–.f_@¼â°²{÷VWÁºÈêxãtÌK5=•JŠÎ'òWãÜÄ÷Äo±ÞÝèîï�—CÝljȶ«¡®_qé®Ï¶¨H(¶°rÿÉs³|øháu§h*£%ZEŸ‘«æé¤$»`Ž$cbÄ+«©ÐõÝ»-ˆRxÔ¯cïk˜þËã� éÃõrRB!#½ËOñM[gUåJ»à|Gá K®ˆ-oUm‘•K*_øtqã%ºàÓ‹->åÁ,ªÄY\KKREh^�þFjÄñtÄedzX]à$• �OßnØâåhÆQÛ@:¬2ÿ?‚¶\m"²~Ö e"Ìþa Á:G·wùõ–õ8k,ËS§(Ìú8ksãhLeÎ9Ê:þÖ z±ðŽàÙÜLû�Cð „èVå¬0'ÑÌÀÀ¸†õŒÙì艹»[¼ÞÛÏðçˆ�7^voè¡jÆÑ\kBâüzr¼{r/ÏÃOÜ:êRÕm¨¡ø¦Îõ`mÔmÄ]×3ºak¨ð²îrâ�ù{vª}�ý£±Û*˜±á�䩾m …›ŒHR«KMг!×+^šò7 ä¡>ˆÓDgþ¿òœ”ׂ¾ÑúÕG,€E}L #Û–Ñ1™œ0ÔS‡ذ¿%s¨,=ô÷`?XŸ(ó8œ_ÎKÃ�‘¡C³Oá(j k:ę×ÙÅч¸ZŽŒÖU(sø-¯‚Cè)ES~È’náB¹§K+v½�Â>Ü$/†ÔÖ’M¼9bxÀ"èÜ.§£U)ƒÚ(Æ#?¶9Jw±éÃçy°�7]wb¡¹m€1ûè !Í/távù›8ßý(W¼hd¹ Òkºø~õºb‹•¾áù:6é›<P�Eë9 µÚíª#ž•»1ïÓK€ Ìk¤·.¶ì?ƒ‚ÍÓ-©cÞ7Jl¨’^Ð\²ˆêŽ€l+ì°ØÏŠšýò ³)7U%DØýjR4™£ï�/YCkÇúQøÀ “×(:¾u˜æïZ•Ròü¦?ùÏ)žŠ+Ï˺»3z:Q­®Ú>¯ çf¼Uáܰl„åÒS:º’S¹í\þ'¸ìAžd”dL#ÿ”`'Æjm*ó¸dX´å§NË T9ªßö&ÄZ4Û9ï³LVˆzyÀ)sÄ’w?þ/ ¦š[ÏÔ‹L¨!0¢¿ŠépNtYç»,ÓU\I¶Õ–ø W±µÇÁx�îgn‰Ì2Ÿ‰¨1h¦ÚbmB‰Aªš¤a?#2½Ý„ ±!FÝv.Ã}ƼiݵæšÂaz>f7×Ã4ÚAÕÿkb¯#‚>(ñZ>çØÀ,´ZøÑŸí®¬¬qLMë}µxã  ±æÉa¬`K:Ú¦Xå¡Ü¯qXžÀ7A{Šê²Cö÷kY«ÒI<ûÈ»•=-æ´Š(³lÊÂ` *Xàö[až²dþ¸Lüëá•2;Í}îc|)‡P÷‚ÊØf1Õ:â̱£§+ ›nq-„½g7Ú=-ÂÄ)¨=y ÞÑD¦À ô�-¡Ÿ25|>ÄõOæ¯x}‡Gó)0“DÄëÞfT¶Ä*hmd}±_wVj‚Kß g8ûÁ­Fq ê×ã¢Hãàå¥ ÇÄ—þ~�HY$Ãç½3ÀJ–3}™R�À-ŸúÔª�Ù\ÈAš 5-©2˜ÿýñ÷DÛÿ%J¯š~èðbÖÉÈ鯍}Q0‰0ÿ)˜K�H$²¼�‡�{6XU¬þ5W;‰˜�™`'<·Õp9 Í ¡T��ž:ºäóŠøRÊÒqݪòàãÇå>Ð#]FÐ÷tÛÂyªr�Yu´!k áÚÞÍ4Ó¨�âaQ}®¸Õ ÆŸ™ùp€¢MaWœLYˆzmóg§ۺDƒ_�ûÛyŠ—жó=xå ¬eð…—VÊ[°ÞÔ"ICùN⇖=("¤ù.6s�ªHÇÔbX〴¶_9 OŒìyfθt¥\ï˜+Æ{¥a½‹Ÿ@j-9opíÁz«Ä(„>‰�ØC |P´Úr[ž!i3(ïR ß)t G‰40ù‡JÛ€·Ð™ƒô´ü“©Ê{Ç#ØíÃ;çõÃÑHyîèZδµv\®”á·~Ìé,:{ e�Û‚ƒµóX?Ó³ûתôÀîáê.|)èp×n†8ò.¼—h‰ (@qšð†NGHBóO„ÁôÓ…Óf}_(,�H„ YWo2Ìšh?Øš€°kuË$Ž•�¸�Ÿÿ%i‰Ýx×�¨W»¬&B8Dêê®ð�©£ôB†(-ü7-FVB‰gÑM”÷”gÀIU¼HT®÷'·Xq[ÎÅ:Ÿ1{[l`Ù‹yhM±Ép=WÁ×Íñm×o ¢Ë|EÅ€r‡ùrOG_Ôo–èn€%[FkTãÈ ° ¡•×(@*Ñ`ûiÒ ˜åÉ ÕzÌèî�æí0ü‰XK4ç¼C´UzÕi#0&¯¡7z›@Ͳt$`OÛØìÛq²ãçKÚ<çTóÖø’ìf½ÜÁ‚X4ÚÍU0ìyú%h ~ypÆØì wÔ’J/œNäpš¿Á�·R®«Ó�,åÿ0+eDј: d&Öa)žÁ e~¿'²ôáNcòÙ-BZ´�ž±G«ºyñ«T�­¬}Ñþú¿¥À™‚hË¥ çb·CEhn^Y†ÉF]+SÐñKÊy·s‘ ƾ½ß&Õ­¶±WÖ¦^Sùï| ŽÒ�}™„–ºò�ÖEäõÇùˆ`ûÞˆ?YS‹ÈÆéÝ]¡€q;ô‰¼%~ó@'ûëNš¤Ü@¹·÷øõZ,=÷.Îk¾d½~t‘ÚG¸°V‡˜ F²F”+s¶S+u”ÙCÈbÛ~TNÀÁâV%ÊF\=Låd…çÜy´¤1!ºü-\\‰ÅŸ›Déf·ˆ19—¢НÖœÂÒŽÔý›w]�Òì ìØ †îˆyн(3­¬ÏÚÖ¯H˜sÇk㇤5Û¿�Œ™!MI»�ÿoŠ íÛ®«u~ßQ �ˆÊÀ£ü«Îóôo‚“•/�ØÏ>åmZú+Ò> 8[€kƒ€)¹QÃï*ž ¯¿šqˆ€^}èŠ_ 'é_µ6…Ø/°ýq�¹4R:&ÌøßT*ÝXˆ²ÏÉ­·!ôfÿA7Žß=ô:Åzûí[­Ûa\Ç 8¿WÓv}oÑÿÛ.õ±Ö8:Œt*Å ê¹ÿ¨™¸§lǘ=­>x“½³Itb‡>ֲޤÅÎð¤§á)Ú2Z·ìŒ¥œ)$„ºy«ÓZ7�‡8ðªAemoz.ÒI@Ñ%wü»ö\¨‡{3©ØCuÝxáÕ™Ú&MÕ¯•Á%ðôvœ•l)ƒdo„½½éßöGk=QpLn³/šCHý§E„þCAã/¦I-TúØÉñ–Xu `ËšÏø^>G_—MăM«:×�êîä™ôýflÜ똡æ$3�½ôÈâ޷ا+l¸ÎpÓíö‘ãËðšÃ¹ZŽŒ¯pßÙ£osIÙ+�Gí…<-ã#`)…Î2Õ�YÛañQ,«Ä:ø.ECÂi§fpVüîçžÿû·6’F˜ÁZXTìJÓªwƒ¹U3ÿyÅ ûÀ"øPyMbIsiJÎòŠñ" …³¶~‹öà:´ËnìCg´41JèPO<²ÖÍT8¯�&–¶¦yUº_³¹2bp¼%×s ²çëSæhöžó®Uo æö‡«›T‹Ú[Ý�Áâ•o%åõi¨G¹Þ~7{›¶0‚dí mEâ-¾EÏ—¡¥©Sm)|ýõô}1@�›GåÛÏœéºà¤cWC¬ï.É™¹Ì¸Í ðH¥ÿR}ÐØXçÒ9ç„RàœÍ˜ühø–n§w†Gß#°ÁIƒ#tdu„¦Áw\šô¬M‡ß ’x¶Žä5.À-Æ€PW–Îʨ2{ÃñÙ–]TU1ǘ=$E¥ñ[%ó4`_麔Vد{^a_ ¸E g42êÓ†è0PÌíïoèÅ·¦Ûæ/¦G¿;O¦ ÍêØI ƒ¬øì>H3qJË K z…Í™Æ=0zy7ÓŠ¾ã¸tø nàìøîs³õ�ªH+ é+ägó¹ñg÷ø&F£ºŸ )“�Lí2¨pB'�»¬ÕŽuV ›ö͘þ!rš—~£tü}ñÐÄNóêÿ¬ƒÃÕ±yÖñ$‹u}š¹¡hÚ°sÈ–,þ\å­RIÔŽó¬ýžÛýTt`¹­=‚µÜS’è³d÷IÊz’OUŽKÙ+xµøØÀ±�·hÅûlE�Âå™j9õxâ�5%Ïõ#þäŒ]Âó´ö-�ý'XKXEJÔ�+Ü„H?-€®Ÿ„ˆz`³øÉÝ �™ÿr‹¾è%°ü�…ï¡c§rœÔãøs}~¬oô£Ø0/ y3 ç“#Ì{ªk=ʆå9™•V½$ Wô÷0 ³Z—‡OøÓ­bEÆ:èè {þ×€žUÖ�õƒùG…|@eæ'#ÁÔoSìö·C;¦É.Ð:POv.5¦yçÚ„9SßzÁ×òa,4uNmí7ôÀ²‰¸T·ÅŒð»ß sä?&kèè¹ÈஂXõ4˜–Ÿ_BÖnaXe ½‚9N¡|GYèåêGý)xõ©e•ÏÌR™\¡[ÿh£Ð�/mojžªe˜~H“3WÞÀênl}EscHg|‹âW{Á4r›Ç¾+X£N™_d|Ü‹vë™ò1܈’Rxät]c×[RYÉJ8ìt£R`VæûAž^d”D\#ÿNNNå¸{o,Q@@ðÌeŽ%ml `:Á×3 BÊ,£öé8>âvjù�i˜ÇŽ>e5S8'~mfø�°�ž#Â_62¢šQ‚^×%m€ºEhpÜ œÛ€%Rxv6S >"` ^Ë™¤W©ò 8Vä/“Í·” U4Îz5�jmVÂŒõl‚¥Ž>>ë½|q×@‚\¡€¹@„ëÅÀ¾Þ«–Z¡ŒÄÛ˲ÇL~í2%“�¨]`HK;ÉË—Ëúe¨”Ù�À¶G*茣uºí•ÚFÈË 4uR@.]È íœ—óh1¤ñ(�¨a¬�F¼^I~œk±`‹•&¤þ’w`7æjˆ¾ÝÓ··ÄÊ ×ŽP~Àh8_@©I¹Ix‘ž«ºÀîUÇ&ÓßèÅWÖ”E"{Œ Œè>5E1}<�9Õ‚J±Ž0N$ØïŽ<8†f1¾ŽŽÛ T<šBdjôQÉ0®H…5l¦éW¹ðžsò^ D¡Aâ> qû‘$w©\þäÚlä,_ÈEé¦ò?ß*ú-›PÞ½hŒž6=¬€FÞBnù˜qZ€ŠYA‘Éÿíç§Ù,ŽHÄäÜÇKk;¦…o³Œ«@ 0¦áË©�ʼ~Äi¦ÚË k#%|câsÁûÑ«�Zm„?œ³a_cñUÁòcwJõHÝaÎíð‰E þüh+ÂŒº¶M‡Í«^BÂT\艊jnT14n†z¬Ÿ�}†t“Ú��tåZTýpá…ŒÉdèÜrÕŒJ4‚‰ô…5ðAV…6t$ÂKI«ée@µUkúÞ㟇©(@Tšs>Æzðæw.§þ]䔨9™{˜òÁZÿé”eÁÇ ÚEb9å&ų׼¨çÊÞW+f ÖÓ7½[Ð@é¡~Á¤´ñåDŒþ!:¢iºui<â}•U^âsÃS×a,¹ÎÊ ¿­J ª#£àDžnGÿMÚFÊȬÁ ÂWMI¼0GLB>t‡7’µ_;s­a�&[?ÆÏ<õ„hoq91 kÚÓylJ”ÒüŠcš?4«1XCUBÝÄÏgpJ~¯›0”�Iø 2ÿáÔPʹ�Ë�^BB�ºƒšó5_è½]ïÔ»E±ñL�k”1­vV§´6Ý ‡ªVtN÷hÜèHU’Â()üt” £ðYÈÊÓo�, áVc�íW&¹§“B÷ýn”"Ç„>·P´…±{O5À#fVˆ:Ž„‰1sÒáŽu]þ¾Ø©¶åÎ\’¯ÏDÉÚäN©ÿ=¼`¼]€Xÿ«ÓU8ž'"²Z0€ÆrôýybÂ&��0¤É,Äóöf ›Ñ˜íï©Mž£üdÏÜ»¥L!«9òÌ¡#æ�Ô�¹Ašb5-©2˜ x!ÿýñ_b#xžÂð?à"7è’ú¾¸Ћwþ–‰áÕûŠWÎZ‰jñ2n,~*+d© ƒ½®`½¹y^C™‹wCvñb$FJ ã$ÎÇÿ$±p¯¹•Gm0j‚нt6¹9ÊX6�¤Ü#¨B=õ›“f%Û±Z*ÞRcã^Œèú¥ª›„eˆ\C?‘Š%RíuWü¸{À}<�K«e>—qEi6,ðWé6ˆ“ 2´(ÝH'ÀØ¡så½¾�]#u�%·ò³P/¢EƒiÂ1ßö5+aMôüþëƒ�·l†9•ÐOj1ÎÒ·H¡èHòpÜ"sñbÎnÌÔ»:ŸÕ0Y=µyqD5Øâõ°ûp2ÛÜ55ŒÞF9ƒSézÁ´ h2zóe·:Sò�pd1ƒêg¢ìëûÖu))¢å '�€j´Zf<Ävžðû»?”ûÆOJM�œ£¥¦–2ÊÚŒ¬f$É:¸×â8¥Ì™;ƒR;w‹‡¯àâ^惡Õ@ƒÒ¤^Õë6þé1yÔ=ÐûaŒ»k=·úWQÐ 4-\*á.÷;ítõžŒÔœKÉÀÑ)ϵ&ïZÌ–·’�_µ×«öJ>ÔSüµÕuÔ‰ÜÈ3Ùº¾×2r“3|~fMEEd½ž�7¼pß¹¨æ8`ׯ'­&W¾£É�" =_ƒWUûðnÉzÀ&šVX|�1f¸£NI!™Áp‰jC ‡ /®Ëk¨Â®eà6”ætÄe"Ÿú¢#}›= iWs6\ÿUø’Ê¿ï”Eؘñã€j6‹+E÷ï/(&÷ :ûë}®°‰/Î1š¹œÝqu+7ØzlÑ"UÞ)cÒ”"Õøô¯ê-^öΈyЉ}ÉV™5AÔ.aPÐ3ÃÓ@‚é€êÞ•ì|…�\îuÈâ$oÁ·ééÍ*.w¾)#£ßšQ4—•7cÃß~ü~òò£È²œl\» ŒÙò¹òC!p4z9-• ”Ì ì`Ú'6?�%X×ëÁÇÍÍ1 ù\y-Âù‰Û<‘"{ÇD®vwð$ÎÕ  åCƒ€;gúý¸6ž�nGÿ+ˆÑTµô *ÜÇÙP~ PÀö0!$–´›¤ƒ$ j¬�'P¯rZbMiâŸ9[…¦š9Y {C»;c/7Ì÷$‰OK"Á®æà÷Ë£kÓHnΕ¨5ó Ï1±USn䤜ñ¡î;kôß½û„Íí¢ ñõ/!o+Д’Ø_m|~÷÷mر¤Ëö¸™ZWÿ¢@’EÄCKZI |㑘ÆÃ•ToNIö¶id…ÎTÁ¨( ~^<ñº’†Jëñ|µ™Ö†}Uy¬é3_ç%"’`k&Ÿ<®¦“ô/ðQ®¼þFëÀ1”[Ì #+[xȳ‚Ò?毷@DoOÛäUº(42»ÕIŠWÀ% zSè°0\½/]ëÐR¹¦JäŒÄ³£€SJPA(‰Aš…{ƒSyiª*&Yv aÇx\ÎQæëJ=ÄÑ;¹IAu­ AößLÇ<úÞh"g�¶‰ÏdL«½¿íD¶Ž«¬e²`ŽË{g„óQtQm=“§ÔÃÙÌ4tj³ü“-Ôîɹ+ñᤵ§*çB/‘X/G­¹[oÈE,l‘ßÄ;öf÷N®[¢ÜæÇ„}¿^[B6žl|•�‡ÚßFt·ÜX8¨´ýUͨ¨1˜„hbáà©Æ K®X­·Œ‘匸vf¦9ôSRå0Ú¡šÐVó`Ó @è@’r…R`F¦*é`&÷hþ:¸gĘ@q\a)dtñ ŽrË` €EBc8¾Š0ëÞhC‘ì"]º‡®ŽÀ²± el2å‚¢�¼¥t=ênq›I«Œ$–z‹©‹ªí€S¨£&3Ë5Í7„þBi*#ýj;•…*‹LŸòþ‹,5Åÿý�fiàÇ‹€Æ‹u] �â�¬šCª$-zg{ ~Ó½ø¯›Cc¼«ãx¡´ÕÏï|µNÝÏ�ØÎœuƒ´‰)YtAÒ0¥&‰¨]Z£Tçz44¹Íö/Ó‹Çtû/ "9qW“ñ ºF=†wŒ\¨^°k�jaâ®_ý•]ò—åÌt+O¶èw¨kmj€;<£„¾õšÖBpîVÉæ¿qÃó›çˆÊÎÓR¦Ž�¤�ÕlíßV¦Sݰû÷—Üü3îcˆK 4%Ù¥3ÂüŠi¢VÌ«þCì¥òO½T »Wu†ý*j\vÌÉ8/5.J+ à@ãäjÃ"¥Ì"–t�àeØ+“æ… d)Ÿû<¢ˆS¤�Ö¡ÝY¤˜ï¡Ü4„üáfÞ’æj¸Ú#?„ázütZ'{r�Ø“n®›Ì[Í5  sÒsӽ˵ˆ;Tëñkè]Ò@µÁXÅ®ªQ×#/êÒÍÄè•k¡;ß7þJÇÄ}¸7»ï›x~Û#ò B^t¨È¸~4�ç‰î¨+Ë·J×Õ&~¡Ç�þÙÞ}|LF)/¢CÖ(”~i2Â>˜!7>¶2ös�Qòpò€kÒDÆ‹¿îéÞ6°‡ÊYB”�}yˆ†)}Åè›xl�é$ͽ�ðc4ª?¼f• íoárR’œüGGË^[Æàì¤VIÿá“_Kp²9 Jó”#à.cà�±H´ôƒ»á€ÃHã< MÕ&Bêº4«†;Žm³¸ÓÐZ摨 U‹¡ö¦gõŽ_¶a‹eNôp±ÂH(¿êçŽô�Ûî$�û’JÚ(8\B‘D´¾•‡tï)%�o´Óº ÁhÅnmùwš¨—!Èûa¶å£>{`24Õå"ZÂÀÊôó�Œ„Â>¥$¦ °Òa¼ò¿Ä6¼¿ ¾WûÔxÅÊòÙ19·õíu^Úß–ˆÐßP@Ya1ÝÍ}ã#Àá�[½"vo ¶Ë„¹R[2ÒûâÆ15íuGgj¸±c'€Ž¸_á¦QTqwP²»’°¼÷dz¹ÄBj;·g ˜gÛ ¬`å®HÐ rœèÔªmaqþ\ò]ãóÄîþþuà8›E4e6É.AµR—p8¢°Ïã96¿¬,È>aQcÖ ¦ãZ®®:ýMCâÇØÃKçÉZïö‹+*G“éò±öÝÍ/â�‡NëŽà-Ã#D·el¸�ÐÔE¶lªËMVæ:œD”Í£"`ûÜšJ ”%¢®]¶,ÅìuX½-|JÛQW�e†]ÿ$'ã>D§ŸÓ¾ùÞšËnçl‚·ÝE…¶N’¯ÁJ¯  £Büf#”ê:Z‹ÖŸ==afú¾æB üGï§ U—e‘>âeeîÀžˆJ3JNÞìRÙSbnM–°¬>ÀŸ S8Ùø9Ñ[C"ŠA„UM¿\æj$©5Xäp€|y°ð§•öZŸ“?‚ S(`ùèË[œ.®¹’u‡sÊ,ºyDS”õü·BÙYÁì¨ÙSöÔVíbnŠ^Äc�ä!Ý~°– 9Ÿ¹Žñb’ä'õ|Z/…í{œx[OÂÇ�Q·ieÇÑ^øBÍ-çÄ;,o}5é�F”¯íñZ2+Yƒ€èXèOl²O‰°�¤ZE±}ëGËÐ�÷/ŸÍ Ý¢\Ü7ü^A¤Eާÿ0‘Ìúìå³ÿKÑØ 3ºS@ª}�"žÊ°eÕ®øàöÁ j…:bÈX„õý|sº÷s©ULä뤓4[ï,�,r²šÈ;Íb,!ݨõ¡Öír\!ïg8«ÛÆÙÛ!‡F¥–…hâ õ³ç~6HøÄ®] _JR¡"à b™€…òngí@+Fwi%ì0ˆDS¡ v‹ñP‚ì<²'‹i®'`28®wBóYBr^èÈ}„G‘Å�«ÏŸÑ•ò¯" Ô–†–å‚Nh"Ã\PûàäÞ«3æhq§ˆ_{=bUˆ ËÀÈ?¶r v–°¿�4Œ5*F×e<¨!ÓøûvT"W#µa„ å½’.Lèäu§I•¿Ö¸—ó.Ž~2=*!�òÚáãD²ië}þgŃŸ|°0.BKWR~Óï¼mât�âz“eh k�AÙo°&Q]5ÞqµFÜmÀuô)º‘ESsv]ùo§#S³XŸUñ‡[”ÜŠÝ<€·¤HKë`RÂ9¾%Ó=^�í†mCÃÌó„ÒOÎeI/[>ïD¡Ë#3¬®5‰*5žÂèøÿ©Ÿ?™—xª,�Ì&�EWà)¸2ÜÚ?¨˜Á^,Wa6 ŸºZ{‘¦ˆ³ÿ ‘;ØÑÄ]tÈ †'¶L¬G°æ¦‚ª 1a ×^ÿBƒƒÓ?¨¡E $+"�JBM,pÇ—Hñ­÷]—Áɶ: žØÏrHG ïà¼Ð—¬x[d…–sìI被ʟjÜ¡A˜ ã´„á�àZzÉž}wZpIÍ£�½í8  è‘�WlÄ?zW]l¾èœr÷ÄA¨$kŒŒ‘©^ÄC`mÈ.![;Õ²™u&[JíÙ/}÷ÔÜuµ+ÀœXì³·ÍÛ þ~.Ü,ÎôØ6¿•âjéÝê]áâŒÁ§ë{å&У ™ìµÔÍ7c£eÁoýþ‘C$yؽXîÛjm&9•]!0ˆ|ƒ€úê,Û¿‘’¬ñ6 tÔ¦úÝ´¿Ô8Y¿Â2Ì~öÂæ¢ye!¤éfF5ð…uBÃß,ÀÊ“LAÐf¿P‹¤61-æºå»î�ÑÖ›yŸ`¾¡Kº¼Ôîm‰Q3¢šZÁ[ Ôî ‹‘d?$&v`]ó ‘² æ·ëñ¢j¸L§É.iBÌBPÄ¢ÈWZÃÙš™ÙˆòѲœg¸¢¶Žùô‰m�.Û¶ }½Vê3®^‚’4!Z¦Ìx\>îËIæØµÐ)B›|/û_8zšù+[Äžsu™-ñ?Yˆær\=Ú¥‰õ9JüôD¸®/:‰¾‡´ñâ+„!ØZ)Œ70€Sáñ­ì�ÒlÏZlêCF¨¿?‘#Xø@A;¯Hío‘¸Ž÷U�”¼3«b Ÿz ÓoºahÖ›ô@usyCŸF»9|1nÃÍ'�H*ñ€a“} ½€Ç¹³{”€Î>¹`ì^àHO�#>6ù8Š 0uv=n0O’ˆJ5»á(iþêÝ¿˜öGíÔìÓT42€F®¾¯øúˆY‹ÔtSõ0”@q~ã©# éy6ïôQ`×�214ºTömVE©íZíðöê`üXüyÌ)XÓÚ=âw[[‚Z$|A.š•»Õ©°iXÓApõÉ8<ùd®xM/#k—©Ãî7žãªhHnÓü'–Ù™"3³l²,=õð„n)�o>¤œã©Ì¤!ŽÙ�ÜZctþfºI‘UÍ =xþ'™};ÏqI ,ú‚“czo–ƒß=sö¢Œ¾!†-Ú¥G'_`Ò?€^\°!Û+Æ‹¦ á~j_Ch§›ö zýþSlœëBÜ ÷€7:ÉÂ5õ>]:Cf�c†ÔOõ‘ÈØÙßål Wùt#vLW,Æ´6=Àé”ÿÜ~KÉù±5NÁÚ lC¤$Sl~jŽ+ˆ«€ƒ.¹Èj®Ò¬Ÿµöoü„Rļÿ¾_‡ò—Ü'âqsc’š!›‹:±TJðƒ6O”Qæ÷ú~x|¥]¾ð7ÄždŸxíÆã=°ÅpÆàÂŒ1š%š¢ }}%Q¶2Ó±b(sñ¿þW6.£Ÿ°îq€ã„…ZaŒ9A¢�­Wíqf8�Tz—Ì� ¹²Ê’¡²�­ÕD›tÙ’Î*ºûi�¼îYî¦ùîÿÏi/`VÒ{¹ÊtÈSZÃÝ:-îóõ„ÙŠ1‹ÊÉ› ˜iº«l= "hÓne^8›[¶;<Ÿ±:kEÿBC;儆GÊïÇA.!!¥ù,²�4Ö¶¢"@Ò,{¨*¬Êª›çÁÇFÝÅâÛJüqgM:w O:+äm£ÇÒÙ$5æÏÒ‹küF†$»’‚ý„¨#ò¸þ]UðÇÛ»&�-áw*¯ã³ŽZ�Îîk‰÷ÄO‰j¾xæ~õVÿfªäú¸;޽a5kÚ2Ø÷Gˆtª¹}yàýLöf«°êe{{B«|ºTÇu'+�Ûë)‚¸ªÝ,FÄ#®—fOc|]®œ×RV îÊåÆpñ�Ó<C¾RguÝ„ãBÏÄœŽùl Ö›°v–¦‘…ˆØË·EøÕùfdü]8è³×ê¥HYäpŽEÑ#ägGŒ­ÄØY°Aäø¶ —VQ]:Ô¯mÁ0 ›OcK\l@8ÌK`üu8'žõi}uæZÿüþÈÍ�Ú®ô<´UÂà´†~m‘†Ô¿ã²å3© ÁR­ý€Úh+^ßóúŔߟþnÂçÛØã~ >ïåòÑÉÈ[‡Ôˆg(MÁ’eÝãÃ\ΰ€ iMk ûªøÄ%Y}y)%Áï91s)³ÿ©%Û™�ëÀfä°4TpH+tJÕbZY�0‘ûh1º‡³oþøòëø@ˆdig¡îÇeVý‡ÅÃâ5�,�˜þ—Û–våÕ5RÔqNY‚Uo¤Ü2¡ÚoúƒjS¼K¨Š…¸m…ñd¤¥ÃÞª?P1èR¢qüÙ0/Ñx6Ô‘�sÆûv.ºm�uoýPo¬†€iêX³)ç„& )º8¦}›�Ÿ�è[YÐV¶»Ø€IdõÕÇb�½ö͇t¥ÿ¢ƒS>'qûT|0ßÖµ‡1¦ç –,H 6[j×'ëއqØŸÜd Ä\'.³Òæ¡ f¶Ê¸N•‡÷ŒÒTË2>@P‡�8m°2Qza¨Ïqú6qC»�^^`¢�Œò½r\ïç{óþ!zsIrx#åDë=.~Áª¢Uv2D¡‡ô\áræ{ïKTšB:Ïœö½,V¦?�r«Z4u˜«ÈmÒ:¸[¦ÿ®..cM¤üý¿D9er±mBoÝR%YQÜòm@|ƒ=•„ê®àÔ1x�åèà-•$uÛ(,ýû!YÃþq]¢ZÕŸFSÔþ¦4«Gnž Áƒe°FðÜQ[ÇZÎê(9–qwU\„‘7�p2™v)uGczJÿz=è�æ/%.FCL‰HÜ®?>uuLë‚Uóþ£Ì3þïíkÞ¯&…! fž)©äÛdªZÎç‡\K±ƒL ^}_³^43HÎÚD¹›‘y¼oEäÎýUÏÿNÚ£aJp„6²È³Ìä?ê—OkŘGÙf\Âesóà2‘´ºÞ0[Pµ»~±²é•U‰.Qӿܯäb÷q¸ÎÒØ�^S¶>èwã8 p,Ö¡Å0¬ï¬Ð8AÊfdýÙXº‹ëÒÔKÍÞ>=ñÅe™qE¬�ñd§ý_hý´¯þA‰¹Â`XY{ q>ƒ|3ž¾ÂVkÞGÇÈúÀoÛ¬úóW95â•,¥�ŠÇîl2ò�óŠgsrÔ’*ã�cÉú4†{‘Èe³ž3*Ìæ»�ô"è�¶zG«éù˜w0=.ì›Õ�Åmƒ-r;ý XE"Òu w> cb·¸aõpØ�ð)“”�¶üc =‚E~Ò­Êu*I‘Ï*u# ù{¿ú>µE“šÉ9 [ΨBƒ�¯¯£6vüšÁèsTÍε¹ýyo&#â̵ —Æb/Bï¤EªØ0€ê’3‹žú®¿±ž`�¶&òÀ×CÇ'òš÷|Õ=ì9n‡*hÅâArr¡b$ÍÜD]Z‚Ã0è·ìÖöê½$C§ºZÖ$ˆþzöe²XÙUJ Ÿ÷ýš39wáDä²lLÁqõÄ7<ò%7\)Ù× b��ÿûp¥o®z`XSÃvÄŠ%À@l=ëoÆX‡{+Cqƶ‘?]zÉÁ^/Teyá2ŸØÁû€Œ? éÐ#ÄdJœ¹Ac]©Œ#Y´©ŸLÆŽ�§ŸJ—ŽdãÕN•»â„اÎbx?åùˆk]3B\5I38Lä Å“f$Ákó…j …èá]Å/tÖg±[<àÀ‡eN˜04Êׄ ÇÇ�× õ.Í,�ªÔaѱïО²ÄǪ¦O£¾âàâKZ,´­MžªNͶß ÿìÅGñ­Çå’ ?üÀ(Uu7 õ¤n«’+¼K~8£ûåá_+è£sQ³¡*.ÿœµ#Ðû éÍ�;ô†Ýͳ°“¥8ö‘lŸX0Ïizóæ´w�²ç‡HpO"0.]„Ïìÿ6±ôß W$ °¾-$Ò�÷ˆqá»�b'9oßlzW.g‹A¥’Xÿ ïë¯ùËa˜7޽ ª†Yü›~--ìîð[6ÙvÅQ$/�R˜?ÅëEôî÷WÐñ~�ÃXøÐiG×™ÞGyÙ¯Ö[Ï€á²ô²ûÑš"ë÷¥ÌÅfœîž`dã‡>ÏÒ°·Y•ŠCÆ… ª+çÍEšdeõÄÐâëI+oRˇíϽžL}ï~_’[Ú>#©)ðI)Ï6ÌAƒÛÔuFñü¿b¨e Ç5ü~Ñâ¡jÙ£.ï,S¸KÉ­ ôý¯�á‹@vÉkµkYƒi‡žK’­‡Á­ B¾!+´íþùÃÆ²Åhü×ó�ÏËàj‡‰©Þ»{�TÊ—õ5åG•EB ßÞÁ]Õ¡zÈe…ÙÈ9Pq–Šîg~¯¨ÔGH¥H‹F ügãzTzà*�™|I3…ºÂ·³ž]R˜%'>êN˜ä©Bæsó´�ï˜w%›;]�"‰4Ö‹ ­„BH÷Šíè¥nÑ£çìÇrŸæ“µ“À�r5þ?€ˆ Sçð¦Ábv*!09bÔ¢JzFS[E>ïJü#íL@TYþL‚ Þ~ … Þá¡ Ê�ãòZ[Ùñ©Pö= £>è+Û¤õeäõ¯7•Øœ’xm”'Œ+å %'´*êÐn\T»m0Ë¢àjé9¢Yúdz=°í(U` PÇùÂË-m¤ô[猙SCŠ"½Ïu—<‘Ë‹k¾„²Õe|4 ã´§¹ À�3¡^_~ka3n®üµ¾gÕ�D'çia~™-}#kô'Ì™”=”â£J•• ÕZ¿Zh¿êv³ÒÞ¿¬v²<]Ò_&¿•0%m(¦ ëÙHK�h��­åÜÌ)â“ÔòÑÄ1D4_­¨ ±æ‰ s^ºä…¾nU[r–ïÞlÍ;Qü ‰ …¹Û—×$A©ahª,ñ\'?WÚ–—W£‡³ñÏtôÌ…wª´–�¸]ÞpÂMþ~0±tÒM�ƒ™~ÃÕYpn³"=0'Qâ)[í¹)S&?0MìÎÙñrWV"l7r¢my÷dÀVk,»ï˯ÑL‰Ø~:æÀ_-@IâÖ‚CÜ­¬1½MÞNÛ“]ê=+•v¾E6{rtù²Jkf:ôì<°…ÀÊK{ÌfŒ§jÌüwy½xN­è똠£Ø�JJ:3?~ØÔC µg¦ýCˆËz8è0”ÕÞ-“jå.!Ê cbGø4 C‡\ÏWŽÛ¸¾óBóK‰ŽÖÀOoæêš0A 11 ú4žæš ´<ñX.+cÖý³UXÞ ÈŸvÏ{¦Ûn-†Ê´Ó×[õàÔݦ¦)À‹úGÄ|ÕK�4Ôz!¸„åà fkªÙSƘ|šã9ø�[�ÎCô»}ÉÔ¹XÞUìÁäC-ŠøŒ³�Mù‡“¢tc®.Ï(ÇÚ“ÑÝÏ�xP-(30ØhöéD_ïýÉQ;vfEQi5´+ìÍ:ÓmBHí�¾Áj9Ë߯52l+Ê©ªDA{ —…e™Ið?g5TcæïáêÖu|ܯ,ô‘¸_ÏêÅUV.&Y´©ªl°æ¢Ùnn‡}y6“ÆýP绸¿6×¶ð;ÌŸ:Ê B˜-—z¢U·ò×zº«ÁðË?²<Û­L5æ¡Ë7a¶o%,A‚wMÀt$‚�R"¸8û€8+þ³MÓy°€ÞžY£î".P¾kô�ÄA<·AÓ"6¯gÆúåËo«®³ôHHú˜7•cÓë"w/¾†X™¤‡¶PÀ5ª˜ä˜î#8Ç�^þrN=ï¾MÌë(‹îMM‹Ñä¢Ã‘DÔÝøÆ�) ¦±‘tãW!¤|ï‘ 4*o$eSò‹O¶8à×ÈØ¶#�¼º�&èâпaÕslÙ°õ�lˆâû⑪ê÷Lxȧ¯^XN‰Ëu–º ïkˆÝõ=ç§oôãàã´N�¿;‚E*»­Zs5Á÷­”¾mÝCÔPmV/ï€=q»üÕ,s5°1ÚÆBår%úŸñฬ¢HÚÛIÍÊþVS tt=kO©'Út/L] ëšuå–ɽ•¾p~—M˜§Wƒ7¯�V5ô}æ`‹…åNÚg_ÉóQãô,‘ß:9ŠIårÏ΃´;¾÷¤TõK}X-[?jÚ¦*}†×gQ@Þ¥£›ZéÆJŒDL[U8ôHÆöGÚ°).gÂß!òä5ͺ¦ùåMÖ>^ƒg¢ ȳHVjuÉ*¨+þ»~<@å—O‚õÿ{C]*+\Á) Y…Šèb+&ÖÔA%T^eüý×§{£N„Åu/úJ…Ãã3óØ•hˆpáÎÇÆ3¹¼C†‰9B/Ý>—ôÔ.G­b WGcR«,ùëdè=Ùµ˜M©ÜÁú&î¹%ÌD1l:é)éQ¶9!H&Iþ62€L‚yÄz{$ ô¥Íf9Ã'Û£?Ç YY‡é_Ue"‡O.·>šµÄ zã§e�‰ßŽÑ½ûCa]K@i½È<=Æ–ökvÁÂèB3]Í-g·!ÿA–aç·ø®øL_ý' ’*ª6’¢§ìà2ŒùòrÙZÿȦ*¯Ûcn"²7ªëµ‘Öv¾sãà³4Õj°ÇìË‹~RÕ�/™³-ÇÁ”³Éíä=Å�#¹OûxIØk¤ÿ¸V†{Øj?É1P{ÇÅjoŽ:.œ>Ș K„5šµ%sá Ü™N}„¾wö AÂuà]•ç}íÖ0kõ o£ÌE÷T&‹âPt%pA“Ø�|ÈcÉÆÀ‹ïDÔ”LÖÊr¿ qûÎZƒ¦ÓÕæè—Éd§¶ÏY‹x¸"Zü›{xƒðÛϳ÷‰³Ü>inÿœtž¿gx t*s:¨îÅ5¢!oC[x¼k õšÏt=Uû„Ò:Oˆð)ȼyŽï¤é‘)Wø3†EÑF²¼gC‡ed‡…¼HsB¤¾¾™Ê4ºõʺ~.ÇŽ„À0p?Mâ]]Ö�Q[¶~ ƒXB”á­ûèOí¿¿ôáp0-Yõi�4ªá.ljâÑÿF…zñÚ‡›Ùûᙲ‰æª!wû-�{ný2:�ƒëWƒJõC\}˰î[À¡meTdÌ�·¦ö@›ã5‹Š�bI8÷.þ†³%éì&u0�RøKŸ5a¤éŒÁÁM)3 ]¿ì×Vz`)p¸êײ(Ä»=¬¥º $Ãñ.ƒ(·uÚ@fj('+©gøQ€ ‰�~ŽñÒ’/�÷ÞC¥4ÎH�þà& «�ãP-$HÄ‹2 ¤Úl¡Ÿá ៈ¡nÉÌž°íTé/¼ÄR‡1‚îÚ«¦ã#4ÁÇÕnH4>Ÿà èé[ÛãüaDÖòVÅx’&�Ú¥–nÇ9#›§J$ È'šÅÍol*:+za#m</ðFž‰Þž#į®j¨ nøùªâ @í:B«ÌïÈD…'7�‹°-$#”°»3O”ÒùI&î˜bJUx¯†3îhÝÀRð�¿¯ EÚ»T0Ûƒdè`#7žX¡º 8[<íN¾¬P¸�/í ï¡7½4š ‚3uW­7U^}v±¦ãØEîíEׯt.VÜ·Ô|›¯ JPoýLé$Qz­§D<Ýu�¥íœLL{¯ƒä½¾‹«ÙyÅÅ9NÅ�A‹@ñ¼•Æ_¯L �‹„“%¥+øì ¦èçûÅ&Í=€vŽXFîÅ_¬‰ÓÌÂ… ºÛ1…»u1„ˆü"Ò,S5ô^k[ÔZRÞÔ¯-޵¶uÊþ€&¾¶}ˆÆ,»úÆo…ëJ~Ï=»^N½\ÇR5´•#O„ú„ÁÐíA‘´ÿsòÓ™³Ó9ìÏl*Rå?ómvš`Ã÷ ê!Ï×rª¿)ïÑ^ìPE‚Ÿ®.8n"Fª¬6¿10køsáYÐ)Øž»ç}†Jº0Þà`µÕ©&&ÜÕVðGÁE«be��‰á«ìd¡×ÅÏúq’ñhã7œš*¼}Ü93‡X¦—,Φ­À±¼SAž£d”dð� jù c!Ý ×h¹Ó+Øg“¾ˆÇ�Ë*RÕ¶µ‚é•�žë©(Òn�zl®‘ÁIÑ ð5Ÿ<½ž�„s™Êé¯ÉT™eueU4C>Y Õ¯8j®| XzznQÂWIñZ€Á9½q©€zQ. îS&d{ùa0¡óþR׆ßãú±ã` F«�ZÍS!”m:Âê?YÕä`e/·‰þ"´ÈP4ÉæõzJ¹mÀxW_ݵb£ÖC¬=Æo(.Ìk¶/tÐä–pÞ_u”Ò:¾¨›SÙÙ×í=8nõš> æ#S`«'ø‡)SÌÛÞåÆ\¼MÀß‹i V— jºãï6®ø;E7$»º%C(âa„šÁžÂ�¨íe'@YšŒL¹§x“Ú«=#¿ à9t¡Ìy&�ß-©T«ž�šž��žÄnGÿǘÑáÃÝx7©*Ø@¬A�,H²8fâmÎ�°PÐP5º\+]5½í“¹ âA >Ú_oC† >5âÎu³Ç± �vuÃ`¡_ÿ6$©»ÿ§3˜õèϽ¹‡ZªÍÿºàöþDk"Æõ£ß›‡oƒ9fM7½'ä‹�ΆœUÿâý7.Á‡§ h‡SÁ-³jóQÚ…ƒŒ-¨íÖ½knÒ¾»#'ÕŠLhÖ‹FeÓ\X‹�ÒõÒŸw­Ö>þ|ã ñÍ_|´9n¿—"$vj χ®ÙÙèà4”š¿Íuézdµl¾ùÒ¾EñMØ6¹Ÿ½°|á9÷JcØÐ¥¯/f12¾ Ó‘‚•&,ãÞ&0½6³G×v¦ó“<¤$v牖L\sgÿ²Y¸È©ö¬µš×ÕC?ÿ½ª �|�Î`�BÓ©›A»ˆÕ N6ÃzÓ÷ê(íìÝ/ªð7Ó'‡åé±sžK2k!TL6†£Tljx!k´+"»¯©<¨=óÀ(% F^þæÌK›¿´ÀþÕ?¡ß͸à•ß;SéðÉ  Z#Õ£7öà™£1Mür—.L‚U ˆ\Æb ¬r£ŠØ_#c48k©]NŸ¬ _�³Ž½XT7ÿIÎ\® @SZhÍŒ¡¯á×}Úºt¹é0äÌú5;Åõ»š 8D¶š,Ho À»/™5‹¯D,‘}ÈÇÑaTý“L”wž­ÊPˆ°þ4[èÕ‘6–˜7¾j‡PŽÞ7ú6P,8ì—oˆ†W#wæîš@V.}ñzHƒ�UD$á#'ßÜ7qÒöúaÊ›\‘´‘¸òaQ¸rï}øŽ‘/(#;Té›g0†Ôuð=ðÒsk€E‰È¹ÊÌá¼î™9ÂÀ“DM°Ž½[€–«°†ær‘E`M%¬»Í8ö“1{ÃïÞ €-mT¼÷,.ž$Ù³ôûo%;˜r'×2Vê/̵؉j¨0tÇkѧ¸í{ÎXñ5KöéŠÜî$Ù¦dMØo.¿Ž6HVóE47W›×¸-A\ ®Õ-½¨Ù�ѽ�9LÿÝúš×�¨ý7ef:ÁŸ–ù¾J©›óÊW�ɺ.ÓÖC[,ˆŠ\6³Ûw@ar‹Ì v¥,œS[“;n[Ól�üF¨Õ"U ªÈ©7[—‹¦e‡•îÐå}éG)àõqh¾#¨¾ÝMÔ<8Å2ƒo(Àðop9S‘Åî¡#§G±8AšÉ5-Q2˜ÿýñs‰1®±Ó@xJ»GÌežXY ÎÌšwθx‰Ð9ßÕÏ`(­'£¤K’Ac$«ClÃÁ\èd­‰‘xDFÙUðµÃj˜‚]¶÷þ^­Qn ;ù®`çP�=Q²z:`1 /’9ì?àj73*áouȳÐUdbeÖL^ÏFHíò�Ò.ž!@šš¨m¤I¾G4˜€#È�`ô¥e̦7&Y² 7!»ÜO¬¹˜ö¸¥Ã`ú÷\T‘üBñ„Äõ¼CÞÃA3Y�“bù­Ûeó«Ðj¶4_/ëŸKÓÖOåðk }µÐÍ­’D–œ>$ÓV*K[#Ü Dþûh²JÓaßm‘`‰ü0*¡HŒL³{\H%�¢]ó/ «¸µ(å{6hägºfâí)/>G$TмãÅÚ5s؈ySsz,ìÿ©èe™ã›×ub8»>AÑå8gOÁ:ˆÚìô¼Ú0•,n{Pâ÷ù3aÝ*O0ÖQ�2-MÃéO¥ÿÌf0V>D â§§â.ô¸zí×#z.®¾r’ ST¨Æ1�ƒžœŽÒ†ëÑujÌjfW>éœ/òæ‹�ÓË©uvˈr‹9G¶§ÿl‡s ÐúlÊ4îGÄõ£á VãcÄéÒWÉûßù(*#]#—&4ƒ—\¯Äe°×Ä'eÆÜó°œÙAÄÒã9ï璘vlFš�å!ŽÈ»×.]éÖ|MÈéE ¨•ŸnLƒPuœËóáÄzbH*]âE„ ä †9CÈ¢ 7y£%$=(OY;ÇÉrËjµIF’0"l5jõR®eš�‡_ÁUźzÆiÛ‹ˆ¯Þ\‚jã¸ÝíïÊG¢±ÝÇ«€ãÕ¢ gñ…„rbÏ·q6gŽ� f³ÛÍXÏs�÷Ý@(’x¬Êu¡>(ùÈ 0µ'|äˆØ»Ñîâ×ýÁY)sgbÛ¬ªˆà&¦Zê;±… œù•üÛ  xM?”üj±‘övÏ �#OÇ{8Ûi¢g±�'rìœ2 —¼yM¿ÙL²íØ"×8ˆ|‡ m¥�”=1‰É¶“t¾ñ7Ê|.Ñ.„Ç Vt �‚÷ÁM£äO°ù¾ziaò ÀÁ̆»†eÒ%)LoqXÖ×W>1(=WŸ)oã�Ùði1ÒN1v—WzØm*š¯zè462Øõ(¯±‡èðš÷Þ™QOo¿óWv1Á‘Ç«ëT±³C;ËqV= dl°öMÉš!hüq¦Å§ð%ÝÔ6„2c ­–œ¹XyÛÔX‚r�'�eó¾P±8šæ¾Xz§³ÉKîø´ç½¬þAVœCà2á_U¶Ç\' ³g¹ÿ5|ówöä~½x\�º.`,ä1$‹zê'®Ê*4UZ+Ð0æ5d³ÂF­m„êJ¦ ûݯМs,"öàÂ3¿ðÿQ)SÜ#QŽ~î7WY{[EõüÔp­”Ï»¨‘òç¨ÑAË ì–ºt�-]=ü·€ |Ã<¹x‹ׯ‹wG!0¡�âŽVÔCº—F2‰è³;píX¢0I˜ìP¨Á ™ &ZMSùrÛ[nÌ vÂh¾Ëåô{ î`£¦r؇Üû|(õËòV+¾�þ úÒÈ­ß§¢ü¨­oc‰ÒNÎëŒ'0ŒÐ :ÖÊßÚ|‚^Òæ�é<Ùà¥Û¸InY4¼ÏWŒ6ôxNmßÃââ¡n³ci�ÞBÚ¼¹wÿ!P«Ïï]0 ÒÐ¥½·qH83èóϾ�+ãUZº îRZå~ê¯íîGô_�cÕׇ¾çeeÂK*£^5+öL)™p†ò3Hç @ÄÀÛÉd 2<¿L•´  4ý#pwáRþ½#r'.ƒQĶ*Ä6L-`NdƒHTÑÚŸiÿÆ‚%‡["z2Mw>¨e&ú�0±ÃfÀÑ“o4¨± èï(oJênÿã5õaÉ?�>0Û”šÊ¨dêY !m«8iXܰÙ1â³bPà@Þ\3¶a€¤Øó–Cö»)ÿ"‘"?Û‘¶3u¾x¡9™GÐýxÑ¥ùÌΉ¯ṳ̀qž‹Z)$Có‰QJìΕà L˜düY}>ÒŠ¶1·I’öEÁƒóU²ÃãþòóU²¢H‹œO™-#ãü¸ß¶n'ÿêØ‰žšÄÔ¬"€ÖnúvHôÚV;:´´ësŸÔcÙ(>ÂOGi²Ä×è·&<Û÷çµ9zž:f�wßüáýð"ö¡>[-ëï†&T-jáCQ`g*ê¡Õ¢ú(ÿËÕ¿9àò©r&¢‚óeÖîÔoñ6\¿³%\‚Å�hÇ[zR}ÓÅm ^Ù­}.öè•ÉSCF9§œëÝ ê;áã#Š&ó¹yÀ"6`Ыðí\½6–YSy›¶_ôò‡o†R÷G5ù"C@}À+‡\ß²fÂåw 2à7z‰YKõhr5 µ³SÖ˜£ÇTÿSŸ”>¦’L=3ØRtuºÆý.E_Ü1eC@a–»Á÷ùMEªjÁG€O±ÿ£ƒ‚5a"0R·â$ £_R‚ÎŽóó­z³§ü+:¸ƒ!ú‹˜þ…ïbKÙ ©"�î•‚,þHn“©Gekw½ö¨OõL“6¼îží&cD DX¹TlÂ+*²08B=ï£;Š€ÎLt{æŸ�4¯ˆ$Ó_FòÓï"97Dfè¬Õ©´D\ :&Íp·2Öf�ó>[¿ Ö°ñ0®¯ í±ÊÓ.tã¿[²%d[>k$㇠éÒk×°XwyB^€^Ø»Îe�þS…õMlÀø­wÄÏIü_‚‰… ЭðÚ_.Ô9Öòµ�jp"6épAo@óÏà/oz)…·ØÐè‡@ 9˜!8íž#GŽ¥ÈÏ=ÍuãiƒýF“2# Š�Ý{·öT‡ÄÄþ%ruó'¼H˜Ø‚+5­›l4;H¶œÔçH³×pë( Ò\ 5†]ÉãüÎ ú¾ 0žŽÿ3„A?BÎüu2ž’ï—ªŸ 3/±]бwrI„ûSA§÷Âçž{e*ò>D\8E¿ÜÅîÒÀ>ŠP•©ŸœZè)û”. ­&®¡õKfØBÄWØ8ŠîP;?aܸ0ªñ®££,uí¼‹ÁRÌG™Cè+ÎÔãÑàí¦ÊšÛFßb ÷o)ؘ]¯¹ø÷T¡…çÛBûŠGtºnþtLã× ´~ãB x Õõ¸7¤h;ää�âjV ,�Ê—P¹®9N;Étv~F½›�H÷%x RÓJ–} (]$9€ã¬•ú€�mÞ¶Ú*ÀCÛpÖš\M²—Œ²ÿ�r„Ga{âØBÿáµx%X¼WnÒ“�ЩÛH'òé÷)ãøqíÒe]�`1XÜŽH¡r¹Ù»³,©N+®Z÷ÿoÐÛÝZ·"ÙG=®å„f"ö{t˜ Ÿ—Z^™Á[rûóQ8±˜dAÇoŸ&]ކh.ýAJ„ü|ó_÷]¢Cvvxì13JÁ€ú|ŒndѦ’áÚ-±YhA¶:÷¶p®2&ÏÌG�0¥@ÞU9ZNXy˜„®Ø 6/ö¾Ñ£aŸñÕz‚õ?–9 R rv«=š±!/ößs7˜ø¹:F{&2mõ]ìæùDØÌQ” ß»«gw·Ø,dÆ•ê0Èñé`ߢü®1kØ¢--áÛkÇŸÿyP")çz:¦ïæc¬?UEèê°þ °÷|_‹Âa:]Ïøš:7Ú›Aû-Åæs±Šíž# µ¢ŠÊ‰‹{®ÊEä1¯Õ_äjž––?Ò7’Ð&í‘=V¿uQõñ£9¿*0wÛVhdSä2ž9‡2’ ÃÞ`ÿI{ý�Yj=j—ÃVùR‹]罂ŒcMoÚšŽjˆ˜£søãNP?OqXEJu Uõ^²7�ÌÒ�uÚÙ�¼.™XŒKúþUü^‰€—!©ÅQ•ÖYÃ…á9hâÆëËçÿ°]šÒýç¡Ï¡â³*3Zuƒ“ WÑЀðh AЋ3-ÎК.&|‰M�•”Ã;ÔªŸHLÊPÓ¼—;ûÌ×è-ˆ¤Ùæ:§nqüÔc•mBHAj;�=/CNÝÀ©®VSrZ¼�Æ%ý Ýç¡1ŸÏ·OÌGЙù­�ä…ͧÖòM9H?éLŽÕ¯¶á• º±mºJÙ¬a�ñ¸6t•.rÆòÅ hÑ�þËFŽªB@w:E‡˜wJÿWÍ¿ÔÕÌÒ‹òüך/®Õùd�‰ÃÞ´õÙðw@6çV>trU°ý•P¯«=+“îØÕí�7SòØ�ñÐdеUèÃ"÷»8ÒD'ÖQ©É(%™½ýÕáÀ±:wÏIù] ¹jÕ{Ù,A � YSTí$}Ò7ÿŒ¸¨·}žÌÿf`ÕÒ§a¦3¢!Èv‚£bßqc ÅŸÑVàºQŽW~&)Fª*Ç¿ñmÍD“Û�a~%8_Æ[L‹˜R»Ú—ÈÛä:÷Vñ¿ð•¼úø MÆöšE9jIÉè� Š•Ó~þYPC°jnNš¶Ô“iô°×in¹)7 Ÿ_Òz÷¬›FÁ£> ±œv‘Dª9)?ãLVryž¶Ê„ƒ³uñ¡^™sþ)³*itÛ‘aô‘š€ãX ]aÐ\ä! Ûëàd(s’�|øƒ=�NvOQ�Ê9{ù.¼c¦j¨{A`á^u³À ºÑ}S ±c¹<¢=7Öè붤x–· ¡G‹“`$²¶K)¸Øj ZÿÿI°YŠÅf‘f�ѱ x¥‹ã92 ¦á"'nr† ´Ùó+S.Ó`s€@(Öâ/=Ç—ïR#»7˜1“†äúJ&f¶_²_1 Ê —·,»Œ1,S™ É}Í`*ˆ|ôžF4zÓi�ÜN‡Ï,_ú7ö&ÊnT;��¿e:,\IÇkÁP⻾6¸>þT‰ð4Þ´UxÙ™»l.‰[Ú(–Udc&¬°`úm_T!�.íÛ¤ D.V€à9-Ïâí- 8.­YÖ$`µÍu¿YÂ^#ãL T™âr~Õÿ\cú/¡§x0ÁM®{muŒÌžšt²Ûð®ë¿EÄþï¶ÜÙýyÌ#²à1lM™º±êÁ!1 WbdnF¡Êu�Tòãë¹íhEoûˆf6ß ÅAÞ[ ¶ßæÄ,/·–ÜÉ�é€ò“�¸�ož'©Ík¦zÝì¸rxÙh.½8_x´½\ry^™;ÄÐi�94E|÷J£De/q›ÍKhÔg=¶¤ØBERËÜ#Mvî$Õ}ýøUDÈ\êý< Õ½²)ÿO£ãç¯Ü]ÅP¿ìÝÎiŠßkUX$•‚�ƒWȸ<ÎÁ7s+/yuçËõ5HÍðÏ”užxJŒkµÖêZ2A¨Aî˜úS×1€Ÿ¼Úo äl`ñ‹V–È«š&!r>¾kö»Y6^à>=º¤âµO–Säµ¾`¤ÿΤ¢Ö:L#,IJÅî_t8†U‚’L6°'M8puòñ 5%µ{G/œC!•³[¤ÑéÞL�°Mm‡í¹/óWøÑ_ÿõ0la#<‡ÑЙÁ3’ø’拺 —z?G zó)*™_B¥µ.埘#¶9NÒG>„S®w–¡fÓÿ½«U’‰8’Ýð”ó¾“7�ŒÑ+TÕ9¬ˆY# ó-ýýÕæR?¾þÕgþþ*På.ËüöGöÚ-òf“ßSº\¿VÃ�¥šóFO-¬þ%™ý¢uyÞ4³!UãZÜKÇovNS”—QÀÀ1Nz �sM +Þœå°yüùi åíw*ûyÁDÕíöd ìëW3ÈÆÍ—¶M©#*òù¯NÃUÌçÍÊ Ý}ÎJ7ë½À8‚ËO/Tc2WCÛáa°NP»R�ü¢¾À(ûÍ?Œ``ù�ÀŸ*nGÿ˜Cs¸ÜÖsÝö í”À¤¨~üç^À&áãLK]Xº~›Ig‚Ëͧá¿[ü×Ot®_ŸVÁ¢†ÍäÎÛ˜À·Qr§ñŸx ÆÓäAí§8¸I>�Óž[¾ÇuêàúPNáHE9ßX'[#^ÛwÓ†ét]™ü9ŸÌ¦Ï*Ÿ�S�;N2€b݅។hÃjw™x‚x|j‚mr¢ügßÖˆ";dì-lë›ÛzêDD2ã`ô]µ4P€GÀ4A›/)ª§ŸfWô×êKp$¼˜æý,Ú¨t~;Èñy!µøòÚúgqÎö/�ûò>:Ò3¾Pk{ÉÔãÊ" yïb¹ÉP™‹4£ÿÞTÜ!Í—°O/øTÔM©��µ@&ìÇ7Æ :k^£+Ín瀽*úv Xq{d–kŠ e- ðÌ¢rñ{6ÈéË®Âh‰ZsÆE¹K‚:ÝËöŠ«åc-�ä °œŒ^7…X¨Ò-ï沯֣ØiZ0U© Iê±VÈoÂ*=f³˜RNØ ÅÀ¦÷×g t!|ÇJ(,Uû–oÛ*y“J¤k”WD©Åǘm³n²–À¹Ÿ „Ñ-þÛï$cÕVR–↟Qm:`/þCq(‚�ù®.ð•¥8\Ä”€/š¯J$›öIÙÛ‡î0‚MX4OúʪFE‰zâHgЃ«œ_¸�ƒl¿L{­î‘Òìtý/|/âxT|K¿~¥fïu|ÍÚ,º*å?9pºÃ솑&—{.‰ßgžÚ‚æESh4¢ þªÇƒ̬�“Qt“Y—~ô €»þËÏMòý(H kûÀøÄ|D�Yº•5œSñTC ]¡³6•ǵÁz!ÂI,º5Óൻ$¥¼ÕâÒ·P‰)Â{ÒÇQHYK‡y…n°b©[ƒ`Ü�¹¨Ui˜l¦´ñU,\pÇ@GÊ5$Ș¥B™zz•…TÉï{¼ÌŒ)ð7€…óÕíR°4ûÕHòU«Å¯‚ä8s牯òDÍ5W?².:Pð½˜ÀQHÆR#Xy%Ã9≱¿Á!:'8ßE-LT�â2UZÜ®=ÔÊNÅ`–'ªˆÁCg¨ ÕŸÆŒ“núj’ÙÓ cõ×ß™ÆÛ™áLmÄûëžPÔ»1ÓÎïÃ,‚x‚Y÷¾ÉC¥ WuØÆ%tZÔÍÕ!%Zˆ¼ÇÉL©¨9\l|Ž0ièx®¶2#ª¢“üu)Gm›w±äãì)o|ì|UÜAˆ×Z>s�þ}ç‚ dô—¹.y :Í`¸ÄÛp‹PYæËÎ4Nùרz/ƒÈ °G<ݶ€Á×èåÒvAä³Jv,³»Úªç.u?�w!·;¨b^ ÞçÅ/ R:3bÞ±k–ˆ† �Å£S­Ãåìøõ™`ˆ‰v$±?SGóãJ‡¹÷EɼMWcAHqZKVQFº¬©ÍU¶:V@˜ðA¥R-Ês†1){Ñ¢4²„m®•´I¿$¡ž ¦)ÚÑŽ%âû–ÂùÏ›v.Ï8›gZÐAñŒþc̤šÃJš^UÿûeÉî` Þ¹ ßkÛÿ&dJ¯¼U5»°TôÀx@3z2*qéõQôÔQƒò º¼sš6{P8¿x\{üœ‘°DÂ?RšÉ&ò]‰ë�!(“>tãÓÈ1IyàpŸv<àÎ*·@œ­ÄÏü’ÛY–µ…„ ™d‘ù'À{gNÀ¡¥;gõš¡3…ãƒþÎ3“úÔ`D×]£¯õ™;o‘®.ɱYwG8-*µ‹ï¸RÕüGå�AÊ<#Iö6ž¨�ì#¿Þ½ùëî›öQ£¼Z¡C�2†L½@ üŸ6ß=º³\£8žCÚ+³Ax½udûFÝãïú–¢Ž}~¬2i ¤.ôÝÏ¡É[7í£ºþ¯óiÙh}üZ¯™Ù±qR½1ÀhÒÔ �Ó±EZyNâ¾–dƒàåë¾äL‘µúEwY'HÄ+Ïò´þFW #:œmÛmífÙ’?{¦sÄhé¦%} €Ä¥þ¶{aIzÊy´ó_Ÿ %tÇü•uBõqy…¼O@_AðBtÿ\t/COúm2†¸´EÕ$ …)ÚÞ[†Ïœû‘ªJH,·¥Ý’Qð‚`QQܬ^CÂÃÉȰ+ ª§‚´èã�î*4råH?v´ÿiš`˜Îþ\âJX¢Ë>ƒðò˜ã¬9;Æl.*|�‹ÌBÙ’UÍ3XÚDjÂûšÕ˰nEÅQK6™êaì#?»æw¾K�APŸ{˜÷9´˜O ¸Š–ü¿wýÆ[�ë̲°»6‘ñã¯QŽh…æÚ ß¾£p;?³ÎÐØæÞAœÆ ¸ÕÃIØ´úŸª±^Õ?J}ð)�V”ámøyÙ¢ Ò]3™¼÷¬šz*Œ•WA¥^�®£®ŒñcíÆÿc,Ó© èîÞÅöºó–p€ý~)T½Í;½[Çš$ãgóÛ]ý·%)…[ UJXÿë×N+ïÇ5<Þ}�a!5ã•B¶YÐòŸšºý<êã*¦*÷D2Ñ8F!éýö€Äíi»hk,'8TƒDM^NMK¤¶ƒ„¡Šè«5"ÉäƒÔH¨è,büµ+ÈEL‚Æmyï&?ÆEýiç!=¯¾q~†Ž<²ÞÄ+¬Zï,ë5�fQÔò'í/ Û(‘Ó·ìäÅÂßÓlàÔ |Õ�Nêü ²�Ê�›¯™¯EñÊ娧ÅÇñŒY¯ûJ|Ö“ÉqÒK>K|° ¹±áf·eW·`2†¿,QÞ¨B£¢ÏŸ~KZ–TýmU2â¨ÑO\Ý1¶?O—^ËI3/ùú²ëƒºyüEïè¯ï XÊíÊCà±1û/©ÀÖ÷S-¸XæŸ2ɨo–4ožS6,ÆÄ:M'oaÔóó…A¦25>P;µJÈf¢®¯V,¯úšjÖ@Û1j®ê"u€#ÃŒKFÅÀÔÚ‹ŸÚc\þÒùñAÄ%$<‡ €ßóZIͯ�pu‰Y¦�I²ñQI{ƚ⬗™¬-a…5ÿè‡ 'JÒ;elpšôz…øKúáÕ­ÈÒ‰ûÃiT|z^ßGóÜ…`düÂÀMI{l2à ¼Ê¡ß}Y·¤ðuòŽnÀ¤½•cˆ–ImEl8Ù³ÆbçÕСô:ñ¯øø/z§ø³åã„’‹iËêÝ @ gÚ‚z¨ç„»%õx#?\h¼Í÷œƒ?r¡�¢‡ñs¾)r¨eÔ`°I!þ.éûøðÚ>¼l½�oÙê1k ƒ™¿%5°7µ—¦‘Å,G[b•Ü´C€# Á�½)¾(@—pW ÷Ýî;»Z;ϵfŒ¥¢f+]«�õ1>ÿUÄa®˜ˆª››ñí‡3H÷õ¤Ö Í�Ž}x¡Hˆ¡%Ãß\..„2Fd|È]EÑ—KÀóª˜]¯c –YRçþQ- «Ê†Á³Ì;ý€ø™6š«ofX° mûHÆ0ßÁ[{÷gGÛ3zÉû!¥É+Lê.9…-‘É�Ó6ÿ._ÛÔÞÁE{Õ¯¢<÷ôÓ âÍœŽiÊZ‡[)¸ñ`±Ò¸¥®µüïþù¸MÞ·|?fýòûÅö5{T]€*½½•P�¾ž0VýÑW†ß£­YDÍ]7ÔììÈo�•¸öh“ÿÇL·Ð[žb �µ„ŠðõYtK=ûÇ%�~ÍrùsBS z�ß`õ5Tûi᫵PÛ@ô0âE¤Õ�LU”bÀ °–õÎUl†1x"·ú´³˜£ ì ñtÆÅµúN¤«¤:}â50ô&g×lÄ!–ñ„b-½swr{‹#íã.« ò«ÛG¦ŒjÈ<³@èÑVO„ô]7(ßÿ3NGjÞS8™—wÙèlñì‘§Å/Î(ÊO´L=T(I ’¿)Ò– jøŒY³�Už¯ôÐÒ¦q__öþ=Ò6A9º÷à)?Z8-¶0eÆËã¾õ¬0»ÁZ¨`.Z½L/ßß5Áï2“&\ `ÛT!èd·ûê‘å8ö_˜Ád»­C©UáÎëþ„²j{3òÁ¬¡r™uû†4²¦fD~?…ÐÊ=ŠH ®âï¶Lõ„û~=q�†ñ´_jº´Éד÷ˆF1/¨ëíÅ´€e¶üÃVlSZ÷%m¼‡Ë þÂé$ëœw�4'~ÝN»‚ãuØÖ›÷HB ´¬„ VuÕ"÷ Ãp‚ÙAÊ™y,›?oýÈhK¾Æ’&Òeae…®N»˜ Ü/„À¦ñ¥Ý‰¼Kh>LþZDÁdÏÎ ¿ù@®j׬p‹% ÑWþ3Ìpnj°rônõ4sä8h”w4#¤�Ì2¢þæu€z‰5RIž‹£;@RŽš¦­…fýi·pãD£Ê½¯“ƒ}ÔÒnž�ø/·íÅg…9Ç ÊžUjºý3óÝ>¼¨‰< 3‹¨Îo<ØܾO¤îÈ>zÜW.e ÖF°®¥üƒZ"VÐ_åí”ØÊ{ „—r¾x�G)CÝbiüôëí�›€pÒÓéS!Žéôš¯º<Ç/ÁvtJ {^ÑË]‰œC[þRøf2°Û9ƒ�U¡6s@r–)››�Ì•¦SC—ˆuH…±?~3ÐŒG.ÃÆ(³�Õöe×§A?‡{GPbÆQøŽê»”�©ü/E9Qg2ð&g¼åˆiØâ¸½õÓûGNÔÓV…Yr¯Ê#?úW`¦¨ ãÀîo‹Yv>Á8Ñ Nl¼(�¿3ºË‹1Á!³ø7'³Ø–È]ç§�’¸†vUFüO‘Èv¦»©å«–7�Äõ¡ KE½…)•ÇX°d¹D¼â`ÉÑcGiZ7.^Xz>Áx´§[2„ñ²%8Bá'ãȼ0øoODFü¹<¿•ÍG'ûˆŠQƒ�À¹wÌŒyÁt��‚§òI^{/¼VÅû6 ²ð¯Ï9v¸zûRäš·ò½+lÉ�|Ê’ÂÙ»USîúÏ;<(… @$ëcG49“ñ� Í‘�…€ÚÛ‚œ([ø™/qX}¡ ¾ùõn§ôo¸}A¾£ìàÄ(æ..¥”&™ëý¾-Ar6«çb„û`Z~V½TÅ¡E;œv¶ú�æ¼m+«Æƒ˜ ƒ�™ÔÏ<6ï¼-Hz¯†ýؽyÅéÂVQýÕ¹¬ èÄYQ1u Æ`«ú_'I39Êß,¤8P`µÛ¬±ÄœÅ©”±³AñA( W�[Lqîz/·— !²K["�}ûô#£ØŠÒa—éi*Ì÷½ÊF™©5”²ÕP\’ú2á7zaêh¤õG?:G¨çõ.ŒÑsŠYƒöÛ2ásd^rRm¸"‰~Ó¾aþEù¶+tE„´½ “ÂA)thx<½?w»& þ•BÒœ‰ßôöœ¼BVÿ lEt{Y*8ƒ³nß½µ–Pw1¥µ$Gáló¨x>Ž•1sˆ1Ÿn£Ã²UQŠx¬ê‰S;[¼~ì@ wÔ(’bm#`9Ê©‘ ðlaÊ"CŸmzÂÜ�4³Žœ›�ï%u°í7~ø S�Ì ©«ôÂ�ö9Í\­¤¢â–Óó×àesc²¹{å6ån;žÞ�J‚ÂÞ”~ ‹6.Rà5;û0Ãù“ùŸ€EÕÃ}þKî‹ÝËìÈŒÍu¦«5Ÿ%Œ£<ÐBó&@-¶^WàÉìö9Ö¶ú=‰!˜ïqÈ2‚6þßwƒ´'?‹< �¬n2u€zŽä+¨”*ÿ‹Õþ–îÝÔ©ÇÎÔÛŽš’ÛŽuÝît?G#´l<*Ðoß{Ÿà{|ó׎ðÄbÇcìs’ݾüDß>BŸÃil�¢ LdØ î8§AÉÔøÒA çà áU 걎/Ú ÃVj¹z¡‡¤“{\‚œ=Œƒ™J¾Æ6z´—ÞýÅ%,Š­ª?b‚ëÕ2xE.Ó“ÇûO¡{å¹4c“”‰bý¯š/–ÝÙ´òpxPF@�ÐŒ ²nbôlã}лãméï×àHâüõ’Á!�û¶ƒÞ¼G‚Ôqö>Õ˜?£öØDˆPrj‰˜Ž“È~Bøòø'×^5ãTL²™}ºö?`�÷" QÒ°.ìþHGøõÏHx«¶e)zS8É~ça¯Ö~Ym;ÏŸ›ÛÛ~ESQ¾2lp®‹ëäцˆåö:ÊÞëG­hc¡ƒøc‘Þö$?DÄO;ÆÓú×PQ–dɼŒõìk ”tðŸ¬ä x›{P£…³­Ãþ)ÜJŒMC½®À�sb¯Û†ñ?`8%¶(^ps’M•FAŸMd”dðŸ Ù"{ndBÑR.Ø,­�“À‡È ¸ê¸Á@·q­s³  y{C±ÀIî¿Ññ‹¶ªÐ¢æ27A¼2Ã2ü yØ\ô,ÔñÌ ƒOÈ?÷ç!”¤|sÔØkÕS2}¹Põ›_…IøvOìNuíG[ÒY�¢$µÊ,UÚ$Š-f*!¦hóÒ«åØUM©!Ä­uë׿¥Ò.¦�þuE„=/òëeN&&% *¦™·"É*<Û÷D¢É.†!’i)—ŠÂ¸(«L õؘÃÖ$�M¾cŒ^êP¹:Ù,Gˆµ, {Ä׈>\®ÀæˆØ\qŒ)WúL7=Q *r¹è4Îë­Ø™¶KK±4Ï¥Ñ[)GÿG7zGë•Ê÷‚Ø«�ƒn8Ὗliÿ i“ô˜ÀPÎÑÒçÕ™ÒGõîŒbì`ת֡r:ÑôZÀÔã6êQCk3,8±{ÓAÁ÷Œ–Ó©T�ö;ê=fÔÛ„<ý]Å)ÛO·spàk�ÚsšÑ–�‡Í• ·&LüÃÅ�é¥ãN›CÊÓÅùžË9`’¨±±Þ²·Ðé¾£àSv�Sä~&Ÿ@»õ¾^6Mfï5þÓÔ�räé®~ÁB‚T| ‹CáºRX…Vdì,CGÝ[ŒJ>¥Ž±00ä�…\ŸCx!®vëÁµ…'œZ¦“M‰ÏجŽN~ç�çFõÈÎ:„SnpÁA:×Ìц־YOÙ»Çéhu@ŒÏ ئ1­«‘H�ímRG±bÍöUýç �\Ø,åÉÏØÒwvÑp9 Š~ Kaû>¢uíÑ¿l¼Ã²)˜“T\Õž]å|™žYŠ0¾ :á(j[¸Ø|¨â�Ñå$ÔÔó†ÌWÒ£'ÏݸgËð;+ê“ã…ì¬ÑBµd›u¯Í2)ñYv— ³£/gùŸF€˜#Jó^I5ŸnnGÿ™înp’†ds^°4…ºŽ*Õe¤%~aÙCýo6«£  ˆnÅ­ ·I,¢"�•ÿ*CzW)&NÅ Œ„W“0±šÇ‰Š•­ì$s"µÍ‘«((:‹·H�@4£»ÔkfÏz!¯ÿ=4,Öûž¼ö`ìQƒ²¬<ŸRlÀê˾�ÑbÇåKFJ‘CÓTÕ³º:¼D%—ªó‚¹“íVzGÆ_Oó1ß‚GRX¾ˆ’}ñ ‡ñFï¤Ìå)�Ü@¥ïÕÁ—Y;bÕuù ‘ƒ7Yu��Wìj,˜00ŠZë*ÏÙcš‡ÿöVÆ;‚ `ñõ¼Ñ†mÙ²×ã�}”sŠW˜˜æ¦‹…<ÃÆ¶oåb(aâwËþ ÜÌ î¸üf¬�ö_"hÄ4J²HNËï�¬»�$áA›r5-Q2˜ÿýñ°Â'ã–·�Ù(™¶Q@em£—hÀJÃsÆb¡ÊÜžùƒz¬� [ÎȆH=Þ?ˆ7¶Nj¾*P‰Ó‰ËC¸zŠ/R“Ó B²8%3NMò¦Lñ¸ µiLh™ÿ×iKý,Ïèž_îoZvzÛ$HŒìféUijÕ=/ýeeR4ì©i°º~QDm†ø`¥ ±”äƒîÔè_mãˆm‘2ƒúRAŒ¡xÓ>ÉjŠ U­D1?C·‰v….áÁÕ&§ôAPpÖœÝlç—œ_•�Joë98)ß?•=ã÷_Hè¼íÌ!ËaêˆÊÿ ¯t¸!œqöÛÉÁø,u§^Lç �a{ˆ?«3z86‚Õc¤#YB¼`©X÷õ¯/•¸ClÎ,0>ڸЦeEÅ+’ËØZ›ÏíT|`ö`Ì}nªwSšoœ«yµA»K‘3 Ö¦&Ö>ÑAÍh0uݽöräórî�²¾û‚ê�úÒ?6¶’&2¶°–«ë6E¬¥XÉ0Œ‡‡}Æ„S÷ã>u¢ŠŽ«U<IðÃ|ÌÇÂPßj5q¶¤�ÖP@åd*Z|禤èú{�`,8’ð+RâËø Á‹°Òo"WRfصØÇ>*ñÙZIï«X¦öþyªŽz6"øûª˜¼òË…ÙR®söÝŽ' º z¯>G¬ ¬5þÃÁI@~zã‹§2ËÅþ¡/u¡ÜÖªìÞœš<ðßlp÷ 2À©ãÒÕL¢º‡ØZ|sЧòxá½z¢–À�!M'–4¡=‚l>6IÖöÀ=ìtìñËó]3ó3[þ*Èqå P‡m’W»Ð÷&É Ì¦9�<'ýÈ�Xl…^«^yŒ¬“d‚OYc¬´ÑêØj›…•}vÐ(© 8pö½gƒ¡^{–šüÓùSâìõu@šñ8Ï[F¢ÝíCPýË?Ó({ŸM‚qFZ!®Ù“PÕNùıv©|â«Z{§QÊó¶£0 s™UôgT92ÊÈíˆy 6«áÂÏu„(E‘󛢡E> È ©–=Þ98>æ‡9*¸‰ÚÖ_»›ûz¼¦ö†ªœÔ°#u�@1d<“ÂŒG€*E±¡ƒÇ×w¸²Ë ÓbRù;4Aï«w³¦!dþ|à~³vs&Âø0 µYóÇ!؃‹ë_bhBgá]Û(¿hÜI/§Ó¢¶ã}  ó×{Ȭ@¼r;˜Í.‘]IbnêÑËCÉ£­ß&�ÏF2«&ö(é9u0cðb�ê�o€¯¢«²³I_À#[¼wý¾#@Ø ºì‚e0��‡ž½éПœ*¦X<@ˆ‹øìK`džØ}øÜö§-�/Ô`*éøÑ»晃hFq¸©Î¥Ÿmï�ã×?ä`˜x° fÒŒþ‹ÎÚ¦æ»ä=Tê”-`¿*wÖŸkPßÚVÌdE廉 ^€Ý:uJ¨Óø-Q¯ëß`ˆ~ƒžú“ت´Å? ~¯6e˜x`3uhòÜZ³ÛêKÂUƒºd¸¹Àzp›a:ü)î!8ôH…£Ô§eN¼ßÈ:“äA¡¦7,ŒÇ‘1Òl0i7HˆœÅÉ4ƒÃç�ôçhªìØï¦b2sO�L7Gñuõ8{Ç x:„Ajä·µ¸•\B¿Žy÷0Ð�TP†]ÍP÷åu­D ¸pÎøÁ¹W»ó�@G1EŠk‡(›�ºAûw…î" ýAÊ}>ÀžÙ Qɾ‘³—%…lŸ ð¸V¢ ÏxÐp..oc2Õ$í´N»ÝÛ¿ášœmë´buæT-�¼þÉû´¼�s«`S&6½âӫز|'B� ãÚü› OZSgÙP¢ ¹„òÐÐ l-Žf¹—U3ÿÑ…L´ÀW_¹âV7O ƒè'©®²md µôûäUðýnlßcžWظ;ùµ!äÕ%t“ß69Æ2.8ņ‘¤#G1öjìµìWÿ[�&©køY5 A{ß>E1.ÐI•"‰’qÊÆo©aÐüÑPVKOnìÄ}0¿ääLЖâKs9áðóù^IÐ?«âùï ˜iu�¨†D-õç ;MµG‚˜3*ò3Ê v3sU;`DNÇ7¿äñ¦ÌËP(vð¹*Dã.™`6~¿Á’Úýâ�¼6FŸ#EtÕšÝRZ´SyÄS¡HÕ'lÓ¡#q·°O¥ÚL·Ö�Ø¢Õ�séŒzj¥Ð‡Lü2Àuœ�u¤[>•åa¨òµQ85Ë HõßÅ™Ê)ƒ3„�Î%Ÿë\�àøW­¹ÀÄ2bª±¾¢!LóÑIåI£ Öñ^ˆŠs–'S,ô³EÏ_üû´ÈÔœÃV”¦8³"‚sTè{!Þ—n8õƉeñçÁ¥¾K|"2,<òº^×Ñ47^,G²°®„ƒä±¾‘OTÜD^ •*y?iÆ‚]x€óåʦ¾ŽÑGˆ§sZ=¹d D{Ñ(J¢ðOÖÍÊÚºÚR[L’4\ M‰š­ eæHÎR¡ùê}¹r›�Ä$èSaéÓ‰£|‹x:â1ªt® D#s"˜1~›¿V�> ÛÉiø,�Àµò‹Ïš„5r®˜h'´f…C_`|–�äùxç�긅N6šÕ'‹ü°R-…L]�8Í– 俦¢º÷×ßœ-j¥¼Z²ó]�ÿÖœ¼!D±K¨‹.ó:zZ3™ã©v¿›bÈ».Ù7< ¤„‰ÛÔO1wƒL(¹3G¸RbSÅ!6C´—£9ë³Ö 0yäHÙäº5ÎWS–C9¡7Ÿì,5h}ÁºlÛÍämÉaÇYÿÀ:Û„ÕrÓÒ`ί}�`ÓNÏ–á•:¥/DÏ‘òÝáÀµÙB�Ô37Hð²z ê[8á„'c�åV(ßëdly°Û‘Ø€-gz«•8E˜ñ,$ÅS+µ(}¨PËpI©²ðçÃ�ø’([ÿšûi±ÜàWÅàö‰°©E©0 »Ë¿7ÿß `¿_~ A7ÿboÿ“1þÓ…ÛÇ�¤ ù®v�-³Ëï¢/>D¯OÆ$ þ¦Õ+á.æü!¹']ƒpéz^ÍV|o€(îßõht7sÿíç,�KŒ6V2¼ùrÊ àÇj€´E´*}‘?±Ûb’Þˆ§1%zÔŸ¸`×FB,k×¹gñ ¯êןðâAû0õd$ç�g3��Ò ¦d£”n6dó/á³Òc=��âs¹}Я�ò]hRV¾*p߸LÑäoBHé<á™ ¥£�ӒĪÒwx­MOkO”‡Èû«„ýïQØsÞJ¯¨Hs•…)G¾‚JÝT}»7ç,ÞfPé®íŽj (þ/û­Ñc›<ïCmy¦ò±•� Æ~+¦åëú¥WGè½,ËÀ×ÎË�£\\Qõs$×ÿüëŒã?Î^p*éPkü›ž„ݺƒ�Ã¥øÞâÒfI™Iç``í‰AŠÎ造LYðà4K¢;ZëÙý­Æ²2¡ÊÆÝÂ5ð 'mÆu"F‚¸ëIÌ…Ñ↠§h‡Ë[Â!7ü„äÃÐ@V«DÑw½–ij’¬¿¸°ðõ’ÅêÅ�žÈ„Y–%ÝJ;juõxrˆ-š´T=B¯ 8[íp¹7ÇmbuÔÙýsÉÞqê^Ët !y`Ú¼>‘ü‡\Ã~Žÿ!Û;—2=YBmF˜˜÷¯‹YŒô¨`7ý²Ör4>qÒ‚½ LÁMIù�ÙwÑäÔùVü ExSztnòcTx¡pj›ãUäˆ÷öŽš›!'“ Ñ+ªe¹ŸƧåö¤›"ûm­›}αË$�ŸG3[é]`ÔÒüQ¢«xÚSíF‰‰EJ>ÁÊín¯µEžaî¼S�ÊŒ‹†ÄjÿÞú9 @|#"£…×SÇ7ˆ _B6)mYÇÿ/S÷4 ½Â&÷>䱡Ìh ÏÜOaòå�@ÙöOÛ󅺬¾š0$Š—¡Cû´¤Ç—óª@"°}¸VDÈ£áD ¯ WPýó.íÌÔJ˳î›Ô�á|`¿ÚG2圔îŸÞS^êš�—ÅëL‘:m½ºÛ’+iWˆSê«u7Ä/ŸýVÎÚŽýõS~æe�%NL®QèCYðväi1êÌnÐ~´ D ×TÀ¦cm®ösÛl*f~… ‘ÝK3§^âþ¢¦CwÓ÷õª,ÄæÆ“]”¹-'†ª`Ñ–XøÌ×—SçòµnÇ©á¦tÁRë¦L ±¥0œzjOã0€8×2ÌÃj—ÞäB§Kûÿ" *©4YݯdÌÇH2uâ±iQ�ÐlEÎw­" _ƒqÅ7h Öe3Û{S×=™¥o–èMLß åŽØ+š<åþ¾p=o+Ý+±©Î餀ÇH—lB[õŒÿt \G|6 H®èDY–å=H4¦ò?UVwù�iÔj�ØÁxÙ55†¿Ý¹âê?ïé‚Q‰½%ÉñIoØOi/>)]Š›±T/ƒþUÝŽ=RƒŠÈ†f=OePºÝÈ�H’Åv Óuzé�¿ã¾”Ë�'D|V„eõ’Ĭ#Ú—s@ŽŽÆ1\6â{ïLÛ’Îrýu -J¸³Ùo£g¶éŸú-»œL6ª?ê¹kk]j# ~8¿”ŒbÂ’4; ñZÁÔƒh�%]Tñ!²¿šU¼®­ýYl˜ºï_’Ï*,¼Ñ?`±UÓÑÛáƒúÕ‰ ¥„'™�ïð;â²!%3†Ì—›�ãáEž»±GÒÅÊ z#Y,Ì}É12~{AØ~}Ÿd{øV¤*•üMÌ3Ëœ�d³´ŽìÊ�‰‡#f ¦cxÚ �æâõ¹vÉ7Åv,»ØG:£U,´EÉ5n~%͇ Šm?n¿ßP/  ^ƒ%Z0¯1¾ø•­4¶8Ä…öï€[R˜ƒÜQ˜¼Ëg œlMzç’Rª¸“ºßßN×1ÄÛGVHÑiu�ÏÒQâTÍÛ­èç牕³R¢Í·Ã†¨ÆÜ³ë¶kb¾ˆô9|Û¬’^{Wº›1ªŒ•ˆä^Ô(2Ùw!k¹5cpBÞ‘Ç€ðu�ª^ô0ù}tN'â÷ÿùq!Ä7Ű©kîĤé±Þ¤L §÷=Í[§r)gÖþ–¹Î�/¼‘rM†y&xAª�<ªJE;a¢ä�€"ñ·Ÿt¾S ˆÁ`s@;P2ÖX!hÁÅun_²‰'V 8¬û‚*ⳬ.Åwb)�ÕŪ#ÝÖ³[ô3õìž°Á†ê3{|æ ³€È”;ÊFËsOœ íjbÿ▒죲_à0Âåsýe®R—]·ËSYÃÊ^Û¬×äœF5 ú+ë�h7>bé8Æçæ^ÿiá)>´Ö;”fS�²^­NŠéqG×­¦¬†þ§‡xžz ÛÄß$xŠÀDþ£âmD´ äÆ˜OO€ùìˆë�>û €O¸ö’ù²üò»Z’é pžqvÀÇãõ¦é<› Ë"ÅBÅ8 "`ŸÛø¤í”i}�jëEK!CLrÇäF>¬p¸Yþ˜‚l¢ƒRæÅýÑJ)Ímûz“܉Ú˼0BIì]ë¹5_ 2«`Û¢AFcÔ˜·Ñÿ¦Ø!ü5W¹§ רyJߦè·úšbîoµzäæuçñìW"à@)Ã?DX�Ö#¶Ìß>V-ܵýzÜÓ_%7Ĩ~‚ŸÝÎqªG«¾Ë·]Ž(—›d,emÅ2Í#ÅÉ*Ç-¼˜ƒeÓ©ž|÷€L!›¹�ü�ù(ã\A€Ò™r.[Ȫ>ðýÎJÑ¢>­¯�0:Cv‰ø¢ÊñísfST?ᦶòòÕ‚:?UptV>�F¹ˆŽ ´ ¨óAïÃÖƒòÿõ$]WZjáÑ�ÐKš~Tcÿ–Š]ˆ�¢É饂 ç�JVxP\ü¿¡´›ò¸ˆOÃXÞGQŸ~uxyÓgÿ‡HhoôóÙ¢ìþƒû€Ʋ—Öï6AM7À¦ â!®ûr:nîhÆÈωÉÚßžB“Ú[~ðj¾©¸Ç«P€E—³“Z?ÀU÷›áÐà9ó²tÈ9>Í“ØQ4'xÞðµ÷ZQššüKO柩jºSpç´ ( ²èÌ'ÒðÆ4j!Ù›˜YÁÌh}gQörP^ä󇯨½áÒ̹¾Ÿ¼JéºÊ4ôPJÔ–­ .¬=/ëü•µÍœ!K’4”kq¸B©€æàÉ-e@%x�ŸúEë–M a (‚¯›:ËDúø™rnpnÀðÒ:…àqΆ�N¹hJÁêâðóJÌÙ«³Cò}…�-L¼”Õ“°`lÀ/ï¶Ë”¨4öÅuøÂ§–ú¨Észö|[hyùÏš�tw¹©u�}:Ë|±‚Á·®%s^ra`J1=pˆ®þºIFçoŠ ˆnK[í¿ÑXo?©X?$Ñ\µ«�þø‰ºùLÐU3ÃDƒdÆ›ØÛ­æ@Œ»aƒö¶àNäP¼}¹ªx(k6L±¶8쉋âõ÷’�.ýZÝÜ„âxp^t¢>͇yÜlä÷¼/;ÿOþ§qŠ}7§Å¬KOc83)© Q(eyÂ%ËS³úÜ¿¦ëŽuž�]¨HO�E龡–€êÑ#S&PY½N+�åµ *ÇwZû¿âO^¾ývÙŒÎ1þfRÿÿ·Öøß5.w!Fa;k½âÐçü� í4’Q¥¨�œ{drÙ•KêÃ�)çû(Ö¤ZI Ñ5{·¯e üÃŒ @ ¤¿Ùš·N–‚ÕB­š°bþß¡«Š Ïiáû¡ë¨4»¶˜?ˆ¾4COO¢Õ1ËKss2øªô™<ûcü&WÉZ-‹�R|BÆZlÒþ>ZŠòXcJnA‰ázŽtžéYxàãRC¶nXiÇ2n&„È£Ú�”YÓ�)ø|‘Çqy¬Òh†Ë/s½2ës™¡0³Ò>70fö‰e¥WUõÚ™«LÆ uxR¢¼s,:k[‰¯þÁ4i´ƒ¥÷Eb“2ñm‘õ“©¶=w@RêýuW ?ö5‚�ù‹6]ìš™ä 4I…~Ú½(·ÇáìlFç¸WYçÅ7�SÃkT²�`°A©Gú� ‘¬ßDp*vYaaY‰àe°ô0BƒÒí ¾=[ꤌ»‘iAÂJä4lùâŸô2Ûˆýˆ“$Ÿž$¸3'�Âce!²fl`¬³¿hSYÅN-aw ¾4ÙǼÈt„7ÍÓE:„HÈΔƒ Ãk]þx± ‡…rÇ-¼Uþyñ,…}šm”D~7Ñ%ÙöæûÖdŽ# í¤q³mù[6òØüR¿LW¥+k/µŠü@áÅúÃG‚RQÆ·í1ÜçÇˬT¯�'ïÐ'óðwïfrÄ Ÿ;ç¥Ûñ÷jü¶¶n_ùRD3{AûW°´¶Hc1|’yÞ'4¥o[Z‹Ñ6Iš\jn VåÞë¢w?ẏd ¬Å�Çì`2•‹Þ…5É>kvŽi¯/S©‡»;ê7ÏòŸÛ~�[Æ9®ÁãÍ(eÃúù³XOå­@RÏ<z¾soÏ.õ-ìצ›Qõ‰É‰a‰–ä#øž…lÕF2vñ»}Ü£Û§(0jáø«Z›¹! wÕØ½ˆF°N#ÿ�AÊ2Aˆ‚¤ÿ.÷Eí¯ÉîT+ /0ÌÅddõ/­+ %S»ø!v°3œÇwÃη}`X‡øøé£òÈm9=ñ�ûS„b{ϺW=³Ø •†fQˈ™K,,ൠ�t~L±ZxíÙÕ¿Q²¶ñ”!È¿ü¡ÈZ8Ëų\špPi¯”éÜ’¼$‘ÛìÜ÷È eÚ¶fUn³æÑ‹ ìwf¢2îïø¬²nš£’L�ˤ[„<\ÀîNgÞ#ÇÙà÷Ës È#¯ç´aHâiùojÜ)ŽéÃúŽ1u¶K¦*X•ë³.ÂÔØT3[¡µ Ûó‘7Ea‹´9"4ŽRN$R½�²¾ÞÚ.lóp<=…QÀh]ÀfTxçØ­Ö~•!Äýx&q2Kĸ“ á±¼Õ:réÏ“¬D Ñü÷fpóÿ¼C¦áëÒtøX»´Ð_»28¶“F2uO�µæy5«Rƒ&;†³½tªòÆ6�þ�ç­}§ÕSqSeæín¶øs!í+Ìi'ƒ[ w ïÜv?ÿ|ë6Õí{cËûáËy\„/þ>ÈC õD!¾¡‹Q æ#ë/­b ªˆ$ÿ·Ëº¾q–ÿL¨¶h�¦€²0Ëœ �±6›>Å® P­ÉóõåJ,PÈÖØ¤² C¡eÅó9èáNÛþ$­�¬h#>É›T1OÚb2Î’a°x€VÙÃOá“<*àgmL�GCIE(Ô�%ù à8g°o>yNzeÎpHY¾wÎ¥ó1´G¾¡Ç͘ò°<¢ÀÞý6þÕ€‰�s\ù[K4q Ô¦±|t‹[T+œRå þö¤+©‹§“†‚Ü«hV§�§]VK§Wã{P×üÇs#5¢ù!¢ ýc»¨ ÷#µÂý‘”6èC¢dxÓý—ºÁêÌWðXu‰2ìbTgÈ+cÖ°ÒXUyO@Hó®ëН6Jf‰ï3U-l(_úoáuÍIéYAõ£¢ ³cýn ”¢¯)Lôöþ®ÎëûêâÙ]Q:s9tý�qå0êM„Ú¹õ‚ÌTÙt%Õ&¶?ßZ;»ò*Í,•/ƒ9óß�â Æ@Ïßæ¿8ÍeL*Ö�åŸe¿�61š¼ƒ·ä9»~óK1õØ0@mF¬(F §í°0x ¶°§œG�ö…qÉåä�·¾%»3éT\ªã„›‡á`%AêˆÖöe¦¤¼s…ß7B.*G'bÉdØÍ�ZŸþ«Ï+‡Ý]Ïz¿¦C—g>,¬žeç¦f‰Þô“$M¦J4ø²>U*™Øú[YûÝ�LG›¥¥[aåYQŸ&é3]§¦0`RtúijÑGˆ}§³T�º°Ÿ ¤Ç�eC\Ý9ã“Í#Sèòö5-Ü–JÉ©/{°ù'•Þ⫼г)7ÏåÄG¡}åSÏ‘ |e¬Cµ�p/„�nÇ�6Q¾Žc4€€ß‚Í�ËZ˜Ì~ýÃE«ïÁ©ÚË£¢ÆŸÓ%XèoCJ¸,-2¦ªÈ6ÊÕæ¼^�w™î¹Â£¼PcˆŽZ%R��RDA͸Så ëÔMâë�PÐ× ;^³íE¨À¥úÀW]F•Íz#à†mª\c®W,‚fË'Ú×Ú¬´m-b0¦�ÚOÓßjx="d[8fcq·£LlLyé5¯”ë1ï,÷[šÇ…�ƒ¤Q/ÄĈ( š2oþ·nÕ&Ôp“ ÜëŒÖž<öj|e'Ð<’òS û$²220xšœÚ¿E]Sù‰ªîr&"B7«íq ÙYúžæÅôBØÊª1�°]Šï!Q\÷r\çHœøYR¥8kK\]qßáþ©Š‡D >状(Œ×üž/ÑœïÐC^ë)÷„’·„aê6�&Ò7|û^s+&eŒ &)¹ZýÞÎPõ¢iÎ(Ÿ ¬L!¸ëÀÅÍPcHÜa1ùõgå‹o€vìÆŸ¼Àš=}¦kê׺_}õ˜Þ–¼-k5p_!þm~ ˜cä"üÞÃ�i#tXÏKéï£1_ÀºBýÔõW‘F›Óh$õhQ~žêÉ�3:pÃvÌME7÷‡W%‹.ÓߟoÚpqpß:½np °äŒ�󣓆\£’+˜Ïû(ˆËå§ û ^³«íeð¡|M-rºêE ìêÞ1ÃcK’’pc6 ‚ä­&1Õ ÄUöŸ L<9måö B¸ÞšÈ6CußK!â$Ÿ¡žÉ챿Š2 ÷a½ëMMÜdi–Ü@áM"vž¹÷Àxú-øŽ¢,+‰‰°Öf|E\@–¯µµzü›Ï¿žY½xˆÄížðªÔ‰®7ôÓý×Uט`J£žüܺû‰_AŠàzŸ6üÑò*°¨qTØ—À¯æõ4‰�%fsMÞ$w.pã -=­/E©êó¯‚5E gm;áM;ȰŸŸWO ’¹ÀõUÿž1ußÊCke�öõé Ê%'ÍÌ\³ˆ~hºg¢ ÑâÞáM†ß(ónP¡…ZÆúúXa,ýµS€ÎPœ�»S£VµÆ{ �;g.‚Úùü‡OtT³$šH÷sÏÝwÓÇ'ÉCÀƒèÆ /Bÿö ˳wFÓ‰*ÅÍük ‚–‘êÝúƒ—¼Ó2³¿6GPâþXûåM™aøÙ VëͽqC«–Œ\ŽÆY�zóBÔ°©´Iëíþqít.çÛör‹DÑp¿Î­Lªœ+PçÌ妉ºbš¾&–<;_OqpÁ»Ö»�Ú®1ÂLPÑ•oΊ¼ùäü©eªàÈUí uo=˜¦‹. 'K9œ$ lýñ£½¼ÉÄû%:—w, ‹ª ka’™4Ópµ‰ÃÒÖðL è*ÁaHƒ]:/ØýK õþí•Íy¸¢hâ\¶Æyôcê{鑪hÛq~Ø ÕVýËÖiöoЧœ©„A÷ ÖyByhc2£ÀÏJÍM’vP*Ÿ±nGÿöb»6^Ü­/_òåø} %„–`eˆ«Pàx ‚€Ù½Ó2®ñE¨PƒàáÎ6‹¤Üâ2å“•¼EF[ëkjü@•j@ÀÍÜ  ²—ãvóO¶™1ª‚ªusœ–UëILëF†¥Ýœ{p%ð¤vñ§L½ÐDQçùž# áî,ï>ëÀþo–˨W§— àj�ýY§%p[®ËK’21n)àÓá¿^QH£[ò(<¯wÓy>†�=v®ÐƒU®Ñi_CÑknó§Žlj„š ñt0:FÐÁlÉjÐC¤À¤EË£0,Ý‘#ÂïÙ(1óÌôˆÇÂÖñ±{; Õ*ŸºNj½Ç°­M¹^åÐ å�Û¾³ib³Ãñ[a½ñ¼ÂoV«×¢ ­ž&òS,µT;ËѦ˜§e},G Ùù­7Ã�í:Ãä½”²mìp‚ç” pÝðîñÚ>µ]…tD’h r@Öa”¦,V1ób̓n.è{ü-ŠB×é‹náŽW¯&vdH‘M‰Ùç‡[$ùù4o¦¿÷#¾GÑŸ° ‡xQ�É�C@ñÆOœå�þßvB×*ƒöÇ�ƒ@övÎ pha‘Ûz}IQEµãÌ¡6&Ë20*><ñ—ðwÑ™èÝ`ÓN[£VåºO«­´Ïø©wÖ&wXHœ;À[“@[Ô§å¶w°þ+W¡\…lèùEÎÌæ{×$à©‘úôHó£NžÓ"G á ‡™4’09?¦�â.b¾ß“{|,“lçÓ E°g:ÓðÞk*5æTœF?ނ܉–)�KÛדDÔ~x"!&uX×_+××{ùtDÁ¢õ“Òü5e,´S\³d.2®ö5¦ƒX|ö÷”8ÏH¬ö]«‡ý�=@.EZððr%6¾ÔKLi*¥¨ükOª£Œ¯ˆÁMFâÎÙÛÞWϧ¨‡É|ñ¹øƒ![¾  þÌsÌCǤK•fý]ÈZˆÉ2ÖË#„çXÄUQ/<¶Ž�ÈÕÍ¿¨q� Óv™´²ê…ö •(–=eÜ5Â�*WU}Ð ÉÜ\0©iì˜&ïŽI‰�é×|]Ù‰{Á1ê2¡‡ò‰¥wSÔ–jùçOCª^ìÓÑ{à�…aúÚÓO察Ákw³óé‘Á±D�œüqË¿ß%oIê´ íðǼ<¨O¸‘X0<ñw°Ÿ°Ø��”ø8[nÀ‰—7ý™l7}” Y²j‘Û L$MòÖ¿åýúX™3N.w&¤ÞùÒ› ÔïP];G½ÌÒM¥®5¢ ƒF\>=˜îM[¥9Þ-Ü&T�0c„$ÞÀ£‰Wmuq4/`ˆÄA ²´2懽ðùЬpg@J=ˆÈéÖ•)^_W>b_(¿6±;a&AØÛòµìw[:+�-gPz7[³ μ ívsw{ˆÏ~)0&R°!Ú™<¹y‰–o#E¥ž—:ù;ÒUé¹çöL{‰e{ÂÊ�©&s»ö.-cœ€¹ëETß]Ðè´žm¸ú(‰‘ƒ³°bu d2¡‹s¶uðZ• TažÞã¤ü¸/¬sˆ¡ƒ—9ļI�Þ ê�þ-Æî«Ìd=ôäYa\¡®p‘d{#�6òŒ¦‚ KYÄVå:" XúÊÒšÆvL<Å´æçåAܸòŽÊõ};(h*»¼ª }÷5 ™làS½9gò†�­‚ãlPŸîS£Y߃{qk¥òsº‚ê×ê¥�ከ7¾í�^A1Y1€Å°yñ�9m�}€>K‡B¼˜v+ưʅRv­V§w‡˜LÓ<0ò©8ì1²Ý‰/½Fç–¹‹c³s]Ó#ŦŽQ}ì7�µ¸BÜ5Yå&%¸ñ¤ð©päëJ©mq)‚™36 i¤=J‘à¡DÈ7ûœÞ’èrÀxì’1PôeäD�J©¶N¨çøœf… Û…ûŠŠ1:. øþßùËäP§Ë3©Q}9>ÿ(¯/è¼£X‡íL]À˜ ÅfO·fV‘>ÃÈBѬìÔ¥ ¥ÓŸ0-Ùj¡.q¦ :�£Ò,†·üI°E¢ž»ø�¤ømg~Cü§ù<Ü]žÝšdÁåè«ÎX»5\ç°ì)ïҘȾ‘‰3-àý��\C'îî�öÏ�yk~z@ÃÚ2ì &]›ÏÏ&÷Ø” ³Í;\ßÃä"sEdtAÛšŠKN_”¶¹ÆÂ¾'ܦ«E}ðwO�]1.êËßûD›ÊÆÑSKO(…Úªj V8䟹hý)šˆ<�#u¯TxóqB 7Á±´ê‰Pù¬Ž@ ºK@‡m!˜#Y'”Bm¦�$„.hØÏ—(�KîåÓÒåi]¼¿¸ÒXÍ‚õO­µÔ5o�{ ˆ àdñ|ÍBþ¨E0íTõ/¨ò×OnEMÀBj~`Ò~£Ø%&ÐÝTBØj*‡7 ÷ç‹KØT|iÈXŸOMˆ>¹ T$yå†@Îä9½I‹²É¹=‹ÛùÌß™¦Ê°@åË“ƒˆªuØÝìg˜×Œ½jÈqÍØKluêh©¨¬sz?¡ÆŸœf©Ì H»N¤%%tɆv÷`|ÔI‡‡ò4/rŸMÁ½¼øÙc*<WÏcÐY È!•ÞaGÂøµ™qüwù diµßI/ðú&¼º©¨¸?l�“»“¢ê6V•ñWîkIöe¸2”ÏñÆ"IJhWErRØ–-79ø{Bãœ{~¾ðÙ5¿ÎÝèF5î6[”P4lÀ fdöñØ1[/Žæd®§12/M#ÿþÔ3ØFØ'I¤¾‰Ê!ÆÓ¦�§N™9dF’!¶tû3í¹^I%ü4ÆB©w�t‹ËFT MoÜOGPÚÎÌO¯¦H•Åo¢Æ]éVF^#Nij©sÕŒYò± t¿ £áðl½PŒsqZuõ¸÷ðœ°-¸ .ö*~įnÐ{~ºt¹¶bæ®ù¬y/¾S ˆ½BŽéC„Çü¥¨<‡›6ÛŠ¼ø4ŒaÕ|¬Ïƒîã?îš0ÍÔuÁ$YF²7|ÛæÜ… ³8Ù l‹ky}¬0Scväjñ‹Ü{*-'>ɰCa�ídÊ»cõŠ*Qá¤hšL×CÞÏMðX™.ÖHT(5jÐH<|èÿµö»S5´sNØOhqý!›FB a pÍßj7+%–K~ƒd9¼ ”âЮƒ·¤°¿ÌUÿøÀ+Óg€®dcqðà&û¼š¥a.¹]V™D ¬:¬“ÿ7äa¿£Jõæùx`òªù0‘¿p†~˜C|d/ þÝDçÔpgjb:ÌÊJ0ùJ'BqS÷4\² ¼Rá…Ò|pK41·º±ðÞéº [cÈ@Ž*4à@A@�á@Vá7ëž³&Þ7‹Gì�ÚÙ¦õAŸ zÔìu±€ð�Õ7W6­Ñ2Ù-:–ãmáb?l‡0‡<—Ãè{Â}GÈ,Ö b•*¶…U+ “ã&A™¶ZV�iõÖ_È$&Ø1‡ë²Š.kªCœC´ ¶«+­ql�4l8ÇAú<;ÉX�౺Õ.O§À&àýå+Mþ kœ9°”„r¹7MMàï�à êF%,¶·-|Ê=Lu-0tu×¥=+ÆÜÔ«ÏkõKDá¢L>£µùtøòž ɧq‡ç ½™Å g& Œ`‡¦’kcÁ�F<òÊÑfö?ü]ÀP�†Š$ïg`îK¦ï:ÔPèî�硲0I8܉ÿÏÂÿr ‚(1‰ú"¿”oè*k5:\'åô6V?žž{²V×yÍÌv¬ÿãrñ†öã~Ò^þÝ/^›^ŸÈˆ#3U’ÍÊ_ØSZ^.ù+·„ó†(š¹V.JÔ+ÖQÔ¾‘¤‡�7ÇÅ;¹Ö̺ Òƒ½›!\L'Ïú>Œ‘êª_ ÀJá½ ‡¶a|2ÖâFü‡Øœ·³ÊÙYüÈK1l)Ï…ÒLn¸8Ý#¨½Ó˱‚ä�­8/ëÁ©`ôÃNÎG/ìl$œßvwœ}£?ÿ_×~%,@Äì'ùÞˆçóÕÎ#lŸŸ�ÒF2)'›½í¼#ù¡ :ÜÙmZ”^R)¢tvͤèdY¹B#ןAËÕh{‘c¬%¼hFþÉÅ%VˆWÃÐ0=(Jpïæ.%2j´SÝ’\üd‡Óî×XA O¿Ž[Ñ¡ú)÷) ÑZ¥÷Ä_׃Ù.‰>xzwå…¿/1Yi­ I&(CpÓÃJ¼ÿB¡OëYOµõ|ô|H¥²/ˆÞî¦n$~„Ùx×÷±œ,ç¨U£  S#1f׺+4Îæ4K£#—Ûƒ‘½)]Ä¡<[Æ!xžI8 2ÂÀo}’.ß1A—‰‚¨zdx¥ÄðŸÐ¥¢j#"Õ£6>¼Ç³»+ h(‰1oŸœÖöÀ¨šHÙIæÀsñžÎ¶x¹÷HBÞxã©­ŸDþËãc­j£wÇÛÿõ—UÝ1Ó'Âz×c¿ÏvvŸ‡\Û™¶6O¢41ñ ‹A›¶5-©2˜ÿýño”o²ôeotoDZªƒ\YS÷’œt~€„Ÿ2ß|×ЫÍÈ©á�ˆ+Åß ¹j³mm3âí—EÌ‘‡çÅ“Âÿ¼“,8Ëà峦ùûÎ×»¨ú�L‚Ãt�3?‘c6î!ÿÏe«Ê“šŠrà°¹…1ãsð�ܶÇ)Yœ[¢ÆÐ)�Ç‚ÏÎIz߯IOîflˆ¸Æ­�ïör>B¦ÙÕ9E^Ìý”EÌU p5¡R.°dcôZo‚×ý*äà Ê ØLd–iq&•CÇýS«ÝÞ+3h–êpeþÒe'Þ=Æ23{Y2ÈÚýNu"Á9ÊÖÅ '//Ùuùõû 4!ÉDÚãʨéVx4‹Ì­o£åèPžY9%›¬„ôþÿnÎ§Š˜0ퟮf–ç9¨ WÙS¢—{ ù¿àw ÐIÈÃÛc†œíüdž4ºMÎq'àÔhõæÑ:vy7t{N÷ØÉ¯)O6ùH™¦/Iàÿ�ö8‡È{›3|ncV@Ðð³iÁÒ�ĵ&Úu¤”þ­Ð䛊Ñtðæ/ÏûF‰Þ›ûεBy“8¿TlnËšçÛï “T×E)˜é{É;ârpœ¾Æ.3^›nü]Yælqï埅¾‡ÑF ÑŒ ¨ÆÈ‹´(q Y+bBݡâˆÏªª RKÑ.ÕËï’õ1Tå÷ïT/ú™�½´îx±@múõ›PµþŸáÄ7Jõ.U.Ùw3×àP£Múmä·ƒ¶¢Ðß«ÒGÛ×µcxGXVT§P&ÿl)1ÿÔÝç.¢”ÇÜÈÃåOöHÕ†ÿ¬ÀRÉh$ªŸ_¢Ž§ŠPlœ•ÝO/ªülBñüF¥x[Î2ä,g÷M‚—'Ö4'g�0ôX’y]—/fÎæŠÔQ Bÿ¾C«Q¦Š�üÁ$7P6«æ™£lÇ“Kë�@ùZL ÿSbå>^Ý^À¥Yë"-¯’ŽónG Ø<¯ ¤sÒð@3bèT )Rãý]Üù¿g­´�ÇðÚà,HúèSÔÐ� ÕzýÔ…õ“߈Ýw0˜vQgm¤–cóÕ®$¹€D”"ßÌù†Â¡ÅÓf#ާÄBkLçÛúߣ‘JWûèª3ãr`³KÅzª?ž±Aæë;ÛÚ’ƒA˶¿î5J3Ñ‹±9Óõ¤k,š %Û²€­ž%¸¾¸ /úWøƒ*”g`"yÚU|t�ÑNVžø$wÿäÿ¢HÀ?AŒŸ|¯AxóýZʼn­ÿ/³@_´‰ÀÊüâGç‘peÞkÖ“¢ <¥ù—9°´J7/U€Ìêx`þ˜WÔN0-ç_-^¥›>m5­Úአ«ƒÎÒ5h…ªºµ3mÃa.ŽöðÎ:ü¨·“l- %Š’C´8j ÿä'bÌü5ž„™Òñ©ì6kàÙðéö³nô·`!‘ã$ÿ �¤`b#€S»SJ\P£ œŸ¾nü»[wÖ«§ aÓ›·Þ«ŠÛ+ŒÛUá:ã$F'])ó¯ÌPCƒ¯Jå�{8Ä]ÞÌ…¿bYBEõ_Æú~ üµ]&DÚ’8Ó&h·]cáa¨îãÓÁÉìÍd{,Ñ>(Za¥?ßR¶¶‘aT}l’þÅt>=wîC�) Q�Ëù_o¥Û]K0ØÎÖùŒ»ÈsFùgA–Ë&-Kf|s<1`%[貘¨ÿ#¼ã—ræ4LÄè;¼Új-]±——FŽ–ÆþyîpÔübIqÇ?æÆ®– ~9°ì`32úlõ�œj°\²O©Ð·…$ïtÈ¿ë†×¢¶”uД³ùªî½2™E ]îš9�1ö¨/Öì ²®Å—$Ýݛ̋ssÐBw±Ä`PÐÓ ÷¯ŽˆŸ)0j±€šºà´žñ¢`@Ü~²²^D± )�4x'côybbéÔÄõfx„�I‚ANËwÛ7–,|þÔ57eOû&6U”®¹zùîW7S¯Xb«ïdd>¿•‡k�t”­©§êt±7=S¬3´ääš5,C®E="ø#øråàŠ­‘k4{R…@ád¿Ð½wj(×�[>ðlê#tÛÏð`ý¤ºWÜ>G+ZqL¼œû$TØ%jÿè ´6l’Ìþ&óÈ3œË?†r±FËE¥ Þ)ØžA¥RW^É¢:†5 ÅC›,Åñi²€±Ý&f½‹ÿA7jSRch(…é↬ìî üÐ4PI“ ›£b9kYÂŽsšÁ ‰œ\¨/�ŸЩË릟¯"ëŒY’Ÿd8˜ö­©Å–J *:³ØfÍ%ü4Y[àÙe.!Œyí  À~äúQŽ¥¬™J7.6Ÿd %…mE¸>Œ æƒËošý üÏí)K»™�¸Ñ2º²�pŒ¥™Üþ¹ïφp Ah&¿‹0KR”–vŒ|² (ýƒÍ-qM?óµó­FQ:‰w2†FE:Baòñ‹.f}'íPáÇeõ­�¬n×cjm`= /m¤ì"õ9Y{ÿ Ô ÄnULð«C5É­ßïirËÔ�‡¼žS dWÐ4pQ6fò?T¢Cmu, !ÏÓm±«jÎÄÁ_Fw{¿ÁÁ’iö¡÷Üfõ@¢EMgùÝp乪£+ßYÚ¶§_ÿÉ"3«G–;Ñ›¿OøðƒVÿ�íð,W _—=6DDØÃ *L„Z™Á^"¦orý~Ùã C—ÔõËxþÐ%ˆe‡ñC>CE0,¹`½¦ž2þ*Ðk"/2V˜ô¿Ù!ÆéwW¼±‡Ÿ ƒ×­×­õñx“¾.U*ÿÛ•Û«/¥�Ïð‚?ËsŠÏ¼DÔÔ…ú*ˆÞý®²ÑÜ NmÎ`ÓæQÏ|Häu~€CØónP?Xݰ9?÷¹“´úZ£ÎÛüÎ蟤—D4 ƵšÖ`ß{9UgW�J—‰À’Ÿ6Ûô³p�Õ0Ǯٿ°á8omJgkþ‹}!ä6|ù\|YÃ̺ÞaÃ0H¡kþ=×ï—–DméûÓY�Ãg(ª{ LnšŠÒl]ˆ1]ÜæÙBãι>R‘ø‡yf¦  8 ¬Ÿï*2ƒj׿¡‹3L…© 1Mç6°�•ž½y5Ý êÜkÀ_&Æk'muâß0f�޾Š:§ù~w¯q˦ŽÎ˜} Cì -µïÅéÊØÍçQœdhÑã¥âàšë¡÷ºÊ>#õKh\Þ™À/á °²P«³¦·ÏG¯Á½½úülõQ§×^3“Ð&w˜¯Â�©P€[µŽé&lrþÓhÌj²µûèN#i)m9¼n©_%„í]*c-if(~¦iZøGÌï¹dDOtýä;|Ó°0]røõ§²õk¾86÷ò¯Á¨QO!U‹ÆRó‘xö¢§û¼ZÝfi}F7XI»¶½ ” è>›>Y�tÈÑî�ú¢†Ëô 8˜äûÐüKF+þNûôêZ-gLoÚ Ø«�/$éÝç ›[¦miç¦ÁàF7ÎÏçm.|Í·²i£ëoÅÈÕ#lPCIgæGäÉ4†’)<Ö[¿ÆéB½gÔíý‰öàFCB“‹P­t'›jÜð‡OŽ0Z})XX1¼«•¹²ŸP™mÞÑ�!¯†à¡¢ohÑpI-ôxÒNØõ¼·�ËßO÷0Ï+ý·™*{ Eâek´Õ½ëô�•p–§—A\)ºô7Ž—9Ó5»€ÖIÛ�¹EÚ�"ÖÙ¥¹/ÕÛ ûá•6rεôpP³+ Í…>Ä&g¢ŒYGxè;d)X4 =[öeÙ! ŒÌúe¤ÒÀ¡3q—"ÿ䱊"ýqñŠ€½8ñ6 ,zY¤Òƒ.‰š|ümTìP w¤šm¬9Fl•Gbá¹ÍôJ/TÕPÇ„èR1­Â•¬ÛHËÛwÉáqpšYÄ„ÿà±,ˆ¤�Ô€Ú¯vK‰£d�f“´(ßÓCqv)›hêAŸÔd”D\'ÿ Ù)Pxà`¾Þ£ù€”›§­DISuØYù£JƒIdÈ"ó„h¥ CxX—Ú-UÜœnZ)ôUGãö÷^�@ŸZ2¸8 *xU;V˜ƒZ˜áÇŒ¾x�Öqz@u8ãØ×TZô‚ö€„Lÿ2úîfЖ–GÜwu×#vk]�+ÙäS¸è%°.–¢g;'Œ.÷�Óbü œPs˜æ(”ñTg\F/ 8¼}' ®-¿ª -S­\ËAeˆ›‰¨ �“zYà&3"^ ß{Ö¤Z‘—tØ.zB’¿)cÔ–o¶¼5¸0±Úïl˜’‚�ZéyIåÇìÞ}Š”GñOgD«ßFŽ=BF¾¦m,ÞØY·Yå:†!Ù¢©V¹,øÉ<,UòÎ�¶ ñ–(Ð’U÷¯/ÁºWº©†,Èó-lÂô‚%oj1ÏßêÓç÷®ˆh}|5X˜ÏLxy2¬ ¡8³j«ë¡B¼ý¦ÑN¹öl‰ãJßðçé Hô‹°RaTÍj«L4›7*Ýõ’[oÙl„åðZYDØÄЄo¤–�¯Í^ʸ4È&hÄói 5Á8Iù¶v¨rny)f±_…ìr«ÏYùüQ‚RíƒTWá ÏÛ<™ªÅ]µpY"`¤¼Ò” ‚Û¡‘qQ¯@ÿV"#,Cí ×h Å;h†\7ÎKQ7ÑH� Üé0”'K-‡¹déq~·Ì�Œóe¼šgdòhËâ»�oˇ³%`aÈÕÈGéz/®¶¾Ý”Ö¾K0Ö5EáÂä‚iqãiÿJ-ýÖÅPLÚ¾L'͆ÇÏ@¡`ÙÐãl†|…aW©�ÆaËyí š Ú²H¬ˆHÅÌùÇדƨ‘¢Ô?€aÒµ‹–ŽCC$õòlZÖœ·õ�½T¨z¯'Muøó>5h$�28kr�J]2 :AhSp E>*°ZŠ ;H·�®¿ME'YdÒ[ƒY @g5G¾ Èjwö«ùÞjÔdá ?&p ÷OúÛ¢"�GÀa¯™lÆK_•ü+¬WµÐ ƒ–Xm#g Âíîœ[^CgnîI†õÊ£­gf*™‘Œ©sÀš$H›Wöà&<Á“;2VYÔZ-1Œ¡@�z€/%õ±»õ3Œ(0¼§ZL´O^ðG’ꥰZí¶Ò#Á/|öÖuBË›´(ýЃøc–]ï1ج­Õï¼4Ó�(°ßêú!jbuBYž(½=)—@׎ ZßéYÞ®–q*¯Ød(ø'+ÝÒ°,¶˜ñA/ðÃ^ií¶cN¹çŠj�>â±n25Ä+{Èpq–òÑÓM¬wd7ÊÕÆxóÛ„¡nðü´öë‚Τ¡¢ï5á%JM¯²˜ÖhÆ#oƒÂqK¨oC\ç;QÑŒg˜Vn�®0£,“ì�Ý :pò_ó,±ÛT㙣Jyö91§6�{%Ô0¸ì›¸¦þ�8rÍ(œÇª¼µ¶:¥¤ñ‰þDK´O ú? #%ÄüIs[°ÙÒ;äã)mº¬ŒÓä ÎeÑ3C˜k“�0þ×fÕœ= ±–פú7ÿã*z‹ÄU,CföË¥r€ÿOÆ*¿3#ÆšJ¢ÄkørÜoÜ{¨1û¸Sn=¸6HÊf4Ë~µåšööÁŽÖ9pck‡62†J=û0oVzN­©asu¨Ä¯ý��Üé–` V8Ô^»Y´!ŸØ¥Ý$Á,Ü‚METImç1®9 o‚–ïÙgÎ|ôÊaÜ­ýx0^Í¢ÝÁ€ewÇDßóiÿóÌìUœÈ˶Cç–‚x2Ë�ÐIO"쇇¯XýGºhÐ2�*’œƒÃWž:Ï ‘èïÇùÀ‚³K)ˆ_`�ïz‰¶,j�™ c"Qǽ.CØ—ûÈLh¹]ªerÍáG Áš)÷ ïrf §efÊ.À½â7v㕜 Og;\ k5Mö¶û%©;ü.lýZ-×Õºz»íw.åDÿù»%^/…F�CGKÊ?O£8¡0â+ÿS]±QµÚ´¸Õ–M^¸Qyæl•ÄEàôá|…oîºóZARÊ7 ΢’á|-cŒ%õ+¬„' z‰ç”sZŸÔØ¥·ù�vôeÜÞë ò¨t8©®Q C°ìþëÊLj]üš’h× Y·]µ‡4!™ã#µÃŒÿ.¯"ÇͶ`<‡_s�¹W€´„jKÛt «õåëËÜú*kÉLûTáòøÿ,j¬z\ß5Û¨;ýÂI³ŒÙ°�ôüñËÛö4³;õ,”~õáF·i,ÍÜ£'Û4ëÜ6{Azj¿­‹‡irx a‘’n7¹F£îz0=G#Ÿ$Ðû‚Ã)#ŸõnGÿ™îk‚Að‰Z´–Š�mý\¨öÁnÆŽ 5Ƹ¨™X¾ªÁFJ“Ÿ}|~–Åzáó4 _fÎn[ün¸¬ž¾©E/'ñ>¹AÈRXâKVÃ÷ÔC4Äy"•¡ñ�ò¼©ÊŒþ¹@õÆÚ=7Âiû¯ï‡C7JékªÂ†óáW¥š¸ë³þx²@ ·ùáOͤÖ~›�‰u^ØrÙ™�ËiÔ%­¯Vš³3t}óG…ä !вͼjH³Ê5Ø(‹î舧{ÊÀ ܈ õWƒjÇ£ ©?ýµ ËŒ£ðeSê�¯äAø¹5ðé·GÅå¼gÛ»ÙFh›3é�àƒµE1Q&¾E‹óÅ3«CRŒ³Y“ûÃA¢t¾b¾’n˜Gc1eˆ‚ÿð¦~ûwÁxÔ™ [6e2�ÿ!–l@�Œ­<ƒØ•×:O*(ç˜õWi$»V1aR}(xü©¨ÁÚÉÇU…n$—¯…­ù–œ¥ä'bŒ0Ñ+lÙyèÐ+<°"<®’Íæeá¥È™÷£PÿÿR=«2¿yPªèrzåF´Ê„†n}Qé0å´a, y«ß\¹^Up÷6Ñbe8…ÒºÊK# Ê/ø{k­j½XUíåúRº«±Öu¿ ý�\Lªì›Þõ26E–L’¯L´4â‡RÔbƒ^‹2�V•žüÔ^¥OïÕÒ€ÇE(Ý2±â²÷œ¬íÌ6 î<ì&ÎY`^úëò8ª  ÔçÍ Ÿx Wù wRºéF6—èW⸽å2Ê�ÓÄþÜʰg7z²1TW ÒŒð æNT)!HßtÀ—fÖÓÙSå$ «íPæÝîU¿ eä�¡z¢JAWº‚˜ß‡ñÍ“}¢ÖjÔuAÈ�ý[“�+8ʪ¬Yn8¦ m¸ ÑOšV6S%ˆªžÕÏÌös«Ý�\ÌhÑ, èÐÈ)þ¿­Û6dÏìÞ1³Ÿâª�»ì·*bœ»_ø�bZœ³5¥^z�Ó":Q>‰Hí v`óaï+OÝ?oµ®µ°òVáVJ[`ê¨i Ñ>á—€!`’îWR‘“w–ë# eš©ô… ZºüHE0'ÿyÉÜñKÔ�ÚGdD0*5š“„�*GXQ­ƒ;¼�ö-gsR’B>¯KÓ`ð]µ¹¢6 ð[„þÿaì4è•‹¨~ qÖ§u¶¦…§�û�–žXª@¸ûw–L> ËõÌöJx À V‚ÎKÏä½ÁäöEšð�Ã� MØë¯€ÄÎ[[�•vŒÐl.{-Ò¦ÖÕÆÓÎàqd5é‡ÇHS”*B€|šyÞ}«D‡lY_\ý|1;†+¼…õ×)�)Fö  æQgÝ’gzi0&ؘ,™ß\ì{B.ÅÝ ý´âR¹Í¡®“®õ«¤ò^¯Z]ÎÔ‘ô²?‹;á{1)5ÀÀ-¼Ë\L'H|õ­þ›¤ðh™vYÅùvM§Æ[±ªƒâæ}æà‰·bO|ÂÚó4LÈóž9Ôø©Â “%ü|dÿ ,)ˆ2! \4YãýeÍ‚U—û‡Íª} ƒ´ŒKyÙnÌ`Aâ™D[iˆ¤ |þÆê‹[<ûÈþÆ~/Ûè8ôt³Á9 ™ÖÞü„†áZ­;K'x̺ ‰ÇÔ€^Å+¶š?>�ÞkáA‘·çzˆ¶kGçªÔв�B¡—‹à©� ¥sa/ o¸‰éÍÂ˜Ë sBªt¥úö8¯ÆšÓø™åƒÈj\�8¦%W«î�Tƒ‘Xœfd5 v¹ÐÛR±7mÇ©@„Rí;é((ÕD«·úžì} ¤Žj¾zj§ÚÁ›E‡ÿ6|g­ìX|?JnÑÔS6^²iW,!Þ´] g&G¸‚Ò}˜Rt© Pµbˆ€‰@¾X„Þ8éœSµ±q¯¸òz¯PÝì$îžÂŸ”¹]nþFR!LiÛÇÄx&Kc3ÆûsDû#¸Áv²˜÷È Ð@f†@(/ÅÁ9ÜD°ÜPxçTºÕìú¤8ïÌpòÈ5ÝdºY)¬j>ÃÐ[öç|E†ÿyë÷;K—ݤo+¶. i9g´‘ÚüÙrwWÆ€;#°§wH'+…ޱßÓN½Zê7ê¯a«~üK¯G÷æÏ,Ârö2%ûj£¢Xà™ÿ•¨ž¹«%�ëп3�<þš~zÎ^ˆÒ·š ³@?!D7¸EëN©Î®eÁ2 íC�7š÷Måê®Ù«kÏÆ ¤NÉßÏ>Œ1ñ§˜:ámh1ì‰ÎãÑz\©y»yÀ;VÂ[#$Êû  üSA‹ürùbÅKË r²pzñ:•U·{5#>×ðU~Ç—†©ä†"t®ÄøU$öìµé °)¸ÓÁ —i°õ™ì¡…}²Ò¸À1ûfíÊlÐð­|M÷³ëߎ|&y30ÀàÉR]Û…t¯„‰,XlÑìÔ~Û!Äî©‘‰Bþ3 iŽÞ“·ö6ÀnÊ´„€•|Aø;ÛØ�º‰,èoÍ•.mËøCqJœ#HvÏ”Or‰€…é{!] øE8ç”+VùÓÇ5ËÀ÷Ÿ'´­�Ðg¨S¹ÃäXwi!ùXñÑ!=—yºv”úÛá4*Ô ãªO�"tØ)`e •KÓN6�§ÆÍ^rùÁŸ 8ܘ¸È]å+þy®q½èYéGørŒÙ—‚„Ú 9Õýa΃LJyYA<Ê æ–Ðu·Ôg\Ãïwý‡Cx,À@ú¬ý?2WGX»—›mU1ËqöúCva�5Ú·í|Ù™½üæ¸­Ñæô _M°Ä@N(jYT%*+c´uÁX¾&£;±Hqi–’Þ[wce¡FxòáWË療¹u,÷2ñeoSµÉ ¢òkÿË®C†\DÝ0�-˜1êØ¢©ƒé›2« ÒjŽ—F3�Ìëb̈nHÕ±M¹Æå­x%Ø )–A$Hɼ ûÀÞQ øïÌ góèH7~Ê-øzl“™ÒýJhùÄžB­?Îpi€qm³ !ÈÜiÖ­Kó �[´ÑÊÞ#”‘ƒÈl¡ Gìîì|ë3]Xš«]åµ P•͆qå‘’ëJ“J‘üû&£ÎéñÚäudnÃ�œi7)æMNðîrþì‡KÚZ;Í7ݹÜÍß„"š¶(¾R£øx;âWž€�ÂÕ¶Îi� ϪŠu×®÷Ä#C1š¹d+G ûÝ–íè~ÿ(QUxN(Se-n‰^ô«A‹UBÄ0:�z "ˆV<Ãqã²üâÌ~,VLÒÈðÖ–âB"ª�µ'Áq×€r¨VŒ´YúXR> wPŽuj”¯Z,7,‹ýýþû$dæÆåÉû&“~"© x}ÅYûÈ ©X;¥'‰ÃpÎ4 �½Ï§¾1íæBŽg c!8!,ü•—�ÑÞp÷ÐZzM>ßžÊY¥I ä –.îàøV‹y0E»ÀEZ° —j_)F–PÏù‘à¯ýy§r‘Aë6ïÌqUÜ›ZqçgºðvE‰ÛÏê#ß3ŽÙ$’JœCJH9Ý0pkŠë¼t¹ph&àÁ"ÞåQ‚G§XLãZX‘Ç\âxi�’û!¾ÿRÒÇצGZ4hTÇH[ÍVàÔƒòÚb`V,ã‡ëi:yOBt4Á—3‚@0µ÷ª7[·ÕÜÍÊwò÷ÎØ¡ÿ®{¢<§¬Veö×Ш0\jQÀ £³/•x€Wñ諵ü#ÞÑj`æâ‚Ý+\‘{D·~¼J�º^óÇñu)Îm“TûŽÅk¢¾ˆŒˆã+2î X&î…D¾=ªhO&KJb�+ø(5Ð7q½ù¹­I*ðI°øÀÚ¼†tOÈÅÔ^—š¯õ-v±Ñuœ*&X·Ol~h.y±”Ñ…I~ʙǟÀïÝGXÑÅÇYM8°3`Ѻ'a¹Q¿Á›ÄDõD:Q¤uueê·Q�[5”çr÷Éa/ÃÅfjú¿ÆLoËYÄ7ߥݷÿ³ÿ�%-üÍëé™/âžY÷F¤¯Ïßw‘ØÁqôñS Dþ¤!qxF±5�‰Átœà3¬Y�¿ðWaƒ©1Ê©Î·Ùæ>4ÿAäùLU t¢y'iŽ{"y×àß.­îAqJŒ4v¢K&¾`¡3^VŒPR}¦‚�ñ¨ÄX„ë�ŸóYG»æKÚ.Þ§ÿ‰h4YÓo"” ÒJœdFÛk¬�/ó,¶�}W6 €,í+°mJZ×íj[‘æQI ‘ŒPìçíY º2„ãÉå©cÀ¸Ð\Œ(ÔŽ…MÉ[ZFEfCtL<œ¾ÑªÂûmñ ¸ÅÈWÙÈ…o_”õiœÍe‚¦Yò‘P\¸>•¯¯å—\œA!‡$|1œN•í ã #Ä\‡ýq‘¡m�aq»PއN +’q½¸øþ Õ\mø4ªÀpŒ“QP¶ì¥‰ ã¾ón¬K-$$gœŒ%� øŠ�t_ÿ µ‘‚q¿-†æ¡ Ò (Vÿ§òà6˜Æun£C7‘'üÒ±cÃûà°.‰�1ÅNÕ²Ó®�>÷pD”…øa¼Â¤•–4,ûÎC€+ˆÿöN镼RÚ›�ú›ª=¶P>°p˜R�α‚•ÏH麗v\„Þÿ�h Ä­ñgÀ;yá¦Kœ-õ†‘6 |5^}e„\I‰fv®Ïo9”� yàÉÆ*êu›¯`B5:ÏG·ê¦0æq=Sô $”gLgFÑ8±…2²£Z#`ds`™P ñ4ÑXOÊŠM¦‡¿ûäÚvÍE¾oÁjr6Iõ s'&&Ιb¥ü*N²Ö¶¨qFÎ�·|¥ó˜O;9"ôG©LéC÷SáÞ.N¼X±^½‚ñ*ž½t:À¥ä>»åG´\ˆn$GIo!n�¥\ЉQ¥µôëÂâ.‘ÈçX‚j7§­ˆÁ•S|±@3¹þÂ~ëR=ëcb'î-ÿÀ•ÿ п ÚOàÝ ôèì‰ ð@k) 6À  Ѽ Ƙê§çàck¬`‹ÐÊUkþo¬”&<°s�AÕ„Ù�YØ»j[´H@°LÜNåᎷŽ=;Ü[G.ÒŒöÜ4Ýý© Àì�€§ÑF'‡“V�Íú.8ÅÒx¦ò �ô ˜ÏMÚ \?W\÷—ª;g%wâ5óú¾fCù¾Ðþ‡/·º„»¼ ]‡h˜«ÙrG_§ª¬=­3>p{ΩFN/(_€Þì_ïàÙ¿^�K�æ§l�ÌpN=ɹ{PK? ü¢p雨Šëvçm°ÌÌ1ßÛ*�ñËÚ„èÛ‚‰õ)¿HœæÐhŽ× ”ÒÖ㳆j§cÓK‹ÕZ:¸’6,Êy5ÀZpöÈ-N6`Âi‡½!ó ÖÙŸ ùÖ�{ôS€(=UÞœ‹}Ýw#È…,’j ¯­î»•¥.ŠQ-K餇“³EàÀñ‰@J4¹7°ò5ð¼g¬]ïb:„Øì0wš^Ë.ñ}gs…¹'jÞǨ­bƒÅÄŽúÙ¾SCå k/p:ÿd¾Pù&–k‚’Ö£¿#{ÜI³Œe—$Ë£�_vC æí®ïÀ'fëÞ…4XµÜï¶Vä$šIŒ ²ûˆTßd5;Á”þÎ9‰CÅïè꺶�ÞŒÓ#pûG ïþ—�:Ä¢@ÜÖ°ÚÔý(?Û¶ÿöª¶B�·e}uåDй¸ù(0Æð—%›S€“Jã`™A8¼ò A©¦…Àà¶¢Æ^´Ë;¾§¼Ë¦u’ ÇÆÊh\7 0޹T«?Ñõ·&åP#ï6óaÖå–ƒW„*†ñmSôä( a• ´�/;+ó' !ÄjPûr£Vëý}.~xêõ‘oÕÉÄWòñ¦.µ…: ®®h@ZÆÿG>âR˃¡íÙ” äírôÊûÞ/•[ù=­½éÅÕzä¼™I‹º×¦„¥~Í˺šòcмKšg,ÿY¯¯J/WwT�Ÿ¬•F‘¦ÆiˆÂèÖæÑ%y‹Bï,“£Óš¡ã¿ux3ÌãԆβ¡ åa®7�jª"š«Uaþ¾§Yâ/^¸«´j´º‹2£%Û}�~sb_lYmo‡V¼TƒÍ™›Ú0ÀùÛ¦ô²¥ÄüNß’{`zývêUQ\ム÷#PZP^xûÙ&-Æ_d@'™a¢5×®½ÞõÆ7•´ØAÈÀü�î¤0dê™®ÌX45àž¥…zuZŸz¸ ݪ_tm4‘Ѧu Ø›Ò!+«(6ב㮳˜¾è\p¿krŸB§†‘ÀòÚ oãJNéƒdÚ8ta-Ñ;õ s²ŠÐÌŠºÚ ϱ›X û—†F]nØoð:´ÆB£©v[{`¿]Æ‹Ò/Í´=„/q7¸•àã§Ç˜œ7wÿÞ¶…/]g^È‹5ÊÆ` YAzÞœl˜°Œí°IË h, ‡"ð#€öË´ñJô<”ÐPô½ÛÝ¥;‡ã+ƧhXŠs‘ÇCéæÈ jxD2ÖyÉÝÉÚ*åWÌ+iÙ¬¯f“�Dym ~ 8w+ Í®�çwÁÆTê qÚ¢|, —Ìûo”ÇÅvî*ŽÜqXeØ(¯¨a³Ý V•î�DdV-÷�K÷ò,5d s›D´Á‰^Bôü<ÅU£S¸§Cý¬fV×ÞŸ!vðGCÎÒ¥†­¥Ý°àÍÄN—ò{½‡VÜ?y-ô«€ˆ½g�óŽòyÒ-�hÿ 5o™v�Ü�!}ôxÆÁsÎIÔÈxÑùã'ŸÒçÈ�L ½6Ô¥ea9?Eâú§ËþTZÍ”.›1tt™<¿ÞY[ŠjùÅ3¡¡ñƒx0�‚Éxæ Ú‹Ì•á9Z6ŒcÁ_Ž+­kè ûG†œ<M`ˆ-ûÌ4‚>9ëCó Ò\H @>r^á_|_úÐâšIL*<ãîÇ¿%æšãRéMÌDÎ"Ûsgš­«¸î­¬ªŽ8çÅR[² ÄÈKùƒ,ñ®4¹ÎGÅÚ@ô+ÿË÷÷^¶gãÆ˜ÁÀ™+— §ð¹ðJ.?Û 'ôx%”�¯G0:Ü}‰ZjÏüŒu]e½;G“ *o¨^žÎ·Í ç< âðD&áÕs|#R-äOþ&‰& ëÒ�Ü—ß%ÒÇ0¼Z32zJgeº?BÒ­˜O²š…l”öSJßBAÂÂø[ê XèäËGþ@P|ëRþR=¾GÜYü-–2a�ÎÖÝ!R"m¨ $/RŸCµNÜÞ°µÃÕ!xÀßP¨QKÿa:çð3íÒçÅ×y£DjžëA-PT¼+ÙÈ-uuÃûø�î�OóúB Þ4m¢hUòQéœZ%²)•Š65gÖ¼ÀÁÕ¬«@â˜Å^®Aílš,K` Xø{Dhx¦7vió»¬GŸE–7>ùT�=bˆíPÛÈJýÜþFG]é8ó  Ço,XtrMóŸÜ›L™ËÞõ]…“@¼¸î¦h�ê}$…¨F¡e™¢ øí˜æ¨„x/ž}g"iåÃG‰½’Ê4<Ý‚`ž•^M m…eüžØºÿÛ‚!¯�‡BÑ8²‹Ùº÷ˆ"ûÙù;ò€ 1(ì Û—/0Þ±Gì™ÉC&EäK­rjÏ€f«Ù•˜\ÎLÀ^ìUÑ ‡Nt–»©rg˜½çš?k¢áû[.I‡˜ž§Öݯ6‚ùßgPÆIÿsjbhŽ„e6ä{"÷$8ÏÿýIP¤RÆ{êŒü矀åód=ø–|ÏÚUH :á÷Jè@Åî.….[ûd‹Ð3§CLý(“8¸°2ŒÍ½Û VâÅUthfج�ÐÁÆ ÑnÌKß7N†½DʤÁ…?±çí(±tÎm‡$gzÞ³)ÞðþKÄÜÏ©¨ëëa뢩\“ —úÀû)¨¾“VZy÷\ŒŸ^o“áôôãç¬|«³÷©(ƽŸ2Öb Î`·² ¦$ à¿3÷zÆûî¤ B@å+òýèÓךÙP€fÏ!•KJê 6¡¿CTUZ ; k›?X"V´ÿÈ�Föôø¤Úà~ÕcÊë–†=©J¦}§¤©¶`—Dãr&€i/ª»q¦‰Ï•L¸>ÿϰ¥ø2wö¡„ºÜf§r»�JÜV˜ƒœL2×›èqÈ@~‘Œ�1ÉiüÁö×�‘=ÁðÈQ8¸fc€�9)Á mØ(¬è5¬'téƒùç §,BZŇI¾¤³“ä\£ÆÃt•tF=ÝJ­L䎒“q-ÒÍ]õ œÏ2£¢#ºc ‹AÀ,»Ú×|ª‘Ú°Êà/ éÇUç¬�l xä�À©N�Ù…13ZB¤c&Û»Ã7~Xši¹;\$%c� Õ¨`zŸT¬`1wùÙ<)d€"¹Þò!ÌMÂsÎãBˆ�Li´CPñ(Ä àÇ|»çJ:|îeH÷–¦¡ß ᇢ¤VЦÔ8��ïIpÎã«¶�×¥ ¹?ˆ°S")2V˜ÝL–ðoµ”Ø‚a/âíÓCgÑ4�¥›/hvæ G�Þ7»@GÊ.A62Œ‡)öÁ›—‡Ô;Q5ý›Õ ¡¿Vßóï°vž4TNw'syÝîk®@)RM? ËrVÑ[èâ*‹e™0í„BP¶³cŽƒÍ¸ž…²h1’¿Ý4{f06y~�Ñ]ÝYÆŽ¾µ%º…¡¥¯ ™ÔªoS‡�r´hðqMkšGýwRѹÕ¡9{Ä�‘ç¤cl莑"lòšÄ_dÙ¯«ªY6br�}×¶Nç-Ð1E*ZB•þjX}»ªú©Á*o|¿ð#ùAo‹VUÿ‘!S€ÁàÈøfٿظCN�2ðî!õFž_¾Å†ØrxtZFGŽ9ÕZôä‚ÈZ³]lqÒ7 Io3Kßi‹Ö4–×>›!QÅõ”O»rbZ�Ç>¸ŸÀý¯[�_Çû>*r<@¶¯`+H‚ɉ}ô�Qé¬+ µäw��ÑD}Á™;³¼Më #6ãïÂt‘©\;ôCt`IƒbêWÇx•z¾÷x’™†¨y)ÏÿZ±§@ñ wF'®æ=9 Ýì ºÉ@ª˜ÀíK"^ØE8&óÑ]ÈAüü¯«ÏÖ«/ëX\nµ8Ÿ:l3v¤æóÞˆÔnâW®ý€©ø× %'¼v‘Ý[€A¸i%Þ5ϸˆ]¨W£–ìÙg4Ž´V ·×“hsY^£¦*r‡ ØùR†>o¨£ï9\ÀñmâÉqzKÖ37Á†t0LÐk²–þÞ5ú-àV¶FjET Â�?[ì!þæÕ–‚‡Iú§¤|ý0Ê´EÀ’™¼R”ÿ CæMŽÉm4‚´Üw´»zc�h*ÐE`ºÃf¯,qES<µµZ%¢d{ðï@ÙˆSŠæ�\ød!/}¡ü1e}~ þ2¶”Ìà`CÕð:Z¶Äû´*hC�Ê£¦*ÝÿœÛ¸�3ÖYU Br¥�ŸLÅ…ð‹œÀ�FL¥Hª|ç65¯A*<:d]œçaìR‚^ÈÕ‡d¥gxõ˜³â§ÖÍP£Õ„Éù»~{›êÎ$Å�̸CŶËT¥UXw%öΰØÊ”bʽ– •¾d_ÅšZð7×�[ðê𠣌60‚•M|üx—K¥Ù³nç[wa*¿Ëƒ’—$‹/ÖMtØ¢åŽ >ÔÏÖ³ ·ù?àš3F5˜+ñÄÁÛ¥|tèRo�¶»»š™ƒªƒq«¬¯V5ÜÒähî¹dKÐÂãCf&˜ä´ tß[VÅÔ·ø}¿í9Ü;ñ 9 Z{b†nIÚ#ZU‚(©ITeñ€-—H²éõ àÜhPË/~F8y5:ÂIÚv] q N=“2ÁÙyÔëʨ4ªïåq jNÏ\æÎ =,F†ÝH�]l‹*.Òä�IwÕtb Èmç3ì¾0) 7U=%Â@"/Yåæ]mjFHìÑį|ǺüØÉ±]–pB 4Cº!�´ªµLš}´Lµb ¾’ÔDý‘lÂÒÿS‚ø2`,#”s|¨ýfê-Í'"òPÝúÀ–ÀÚ‘3™ÑÛt{(å"¶H¡\üD( ¯ÝÁcX<ÔºˆÏׂfx>ž/GÁ«ƒ}«…MÙ¯sÐÞèl‘z´Åð1]‰×¬¹×ÄfnœÞü»^›𞞈Dh»¿ßh¹…ЬŸMrêС`üh¢3Ë(/‘t3“d¿‰¹¢“·'p$ÜeVÒ&¦@Xà`ÉŽ¸¥¶ ç.Ý�Ð÷*°Ì%�¯œï�Ýù»¦­#j.Â#…g˜¯'›Úç"§õxE- ¾?‚]þbÈ“dúó¾ú Þùœå¬|ñ‡Õ;¨©éñSߨ禲•4a‰ÍW•ˆ¼E§€Çf&ý´¹æ3WŽ$!ä9D^F¡lé9xÝ�‘C{Y¹…=%íÏxyÕNÆ…OåTÂ[r³WAåÞ·ì÷¶ò~ÐMíÓ´³�C"i8 ^ÛSM ý´aï»­< YVÁðö>¶fµû]Çp ý¼¥ß×XY|ªšˆÔ¿D0ùPÀøƒÙñÍ ZØ¡Ê?Œ ù¿—*ØÞq~_¥ƒÉ45Ç?,å—Öy¶gø!Ý@Ùb�{ŠÅ8²9ëÑ?9áÀ±ñ±>öZ{äýçH�ÅîQÖÌ< Ž¢A´îŽ/…Xm©>g&Na�ÜÂÐJâgø|‘!JÌ’Y»ývdcŒ(ó„³¢Î:[ö±dÐåJ3c´¾­zŽI^ÅÆ4°òD›t3Ëñ;g·û«Jêì~ϸؘ´#ïfF^’¶MP•PXÍÈ1•—VQõƒ«M.#¶©“­ü)tµ U0Æ-µªÝ«J®x��ˤÞRa}ú¦°-‡qà8]uìK€ \ª´I�e6l²WÜ)ˆûÃð\¦(ƒÝ�ÚEàL+žÈ¶E<³\ª  ØyÀ�—’¬ôHmí 9þ¬àžÂ?”wBn¤ÑÕhX–¶¹ÑÈå b\@({¾’ýä_L°í@vBÍì1ö`·d ‰: Ô{€ƒ%àeÝM)7Óïážê–²JHQ•Á�­ªQËÎ/˜QÓI�²_hÒ<¢‹/ZÞAêÑJÒÞ—¶!\N§J$†*�4ÀG´¹ã¢M”±¦Œ¡5èXøÈ ×°<2*–ú|Êm‹"_ऀ^ Àùb ‹‰àÉßåj`I¥’PÓÓj`_�ßCÐà�²¼‘n»×†§DòÌ!'$óP82dü‹U¯y�K†cP6pøÅgÙGŧU Úéx”6~¤à][Wh»‰ðÈlUç_î;38mO=«´1�8”¶fÉ3ô?HðXß¶‰¥mÿ¬•GLÀœà ¤»½9tXœËP»´M›ý¸ßqà ~ÊY”‰ô¦Ú;n‰J7çö!‘¾ ö…¡Cë8–1|À6d0||‰A!V% wÂÀ%{©‘Î[¿�C6Ù*Ä^ù×U¿�è39vKÜãÿHú¢Àrµý^Œ)É>`D°4ûzõT.²—`_ç美UŽ1]ž`#¸<ÂF@>÷ø"V®ªà}&ƒ²\²ÿß`t)Aða¹Mª6Ãþmʨ¢ž÷¶ ÿ÷†Šh‚ÌýY"¢N¾äFyì}g¶¬FLÄÞQòwï)}§– ü3 A»!Üf‘Ÿ|÷Vê;�Cù¬  9 |È{hM)ñ|Ž[îcbV¹]_ÿÿÉHþ-à,_ûÍ÷eŒþß�>1Úÿn¯wXPÛ7’<œGmiÑîgsæ+ ´¼t÷?Bi©¡ŒÂQLg=t•è!9c‹jÓ� S«Æ ]ƒªŠPŽáÛJ[±pľL°PË÷þ6xm%• ¥F¤ £qµ�j\=ƒ6Ð% ãóÞèÖ”¸oKK¡Ðw�a§ø�õ�lln¼Ñ�ï•ø0$ñkt„é:óˆ"*Gˆ\pD0|q{t…Åc²=™äÀ5Ç# êøÍc½š(Ú$�UwÙAÎVê{£ÍG-ʲËÙ´y-<`\ÁfÖCoÉÓ;Ù;>òñÅ-p,@Ï:—2–*ì5­s€ÿÜöFûcÍWu�2±"`+ø~o ®M&m\sò£áçÍ~¤<Ãê=‰ˆË šV½Ž5µqC#ÿ2Äiðm�Áùñƾ¹õ‚5Q' ÆD¯Ó›“kTJ‰>À:møjD¯ŠÎ[¿ã²Iê÷Xffc¡§]H»’ÖEÒ!ß,ôØë€œXxÐåÃð´Há¡”â#‘ØÞÂÊôlf¶±gQ› N:B4]‹šœ•È–Ûn°DnœŽ(Ìœ¾¡ž]#à¼6dþ´7à¡ÖÊ\vò¼œDÎEÚÚ ¸ËAi”0nÁ©„7VŢп_ž—[�äùù³Î.KE„€Ò„ñœÕï6³}D +–Pðnåcq§V²´L¡_O·%j¢ÐîýKW™¿°r¼N8£ò¢ä[y‡‘á®­Þªäôžºl0��ìÓØçZ°²%Ó•Ä/F3³±Ë^„¶¹J–'u[Âå-˜âFc3¶@Ÿd˜d]¯w‚áAQó \ÞÇT‡îOgN5äÙä1Õt#³¦”–Mˆ'la-Úä‚Å­KÜ31býB®ªAؼÉnšâ b³ÊãFá[9í™3¢ Sê­•joæâ·]±lÎMš$ÂcîzQ,~åÓ“† •Ñ¡î„þÁ:�0PÌD¿ìáûС2'†Ö2ÞBöô³9@Š0–\Qtç–ÿ9ø¨.¸eõœ¨ñ7£ýÛkÄ©ÖE�±gPÍoNf‡–\‹’«ÞÚOMå½o*0N}~@øæA”Š3¬÷õvèøGmi¦§¬ÇLç¿UÚ9y‚wâ�Ä ¥•#F±Bb@âû S‹.'ý¢ˆ tcáÀ­ÁÖ#ÛD¸óeÞ røÚ˜•¡{Ø2gÛ�*o2U ˆÀzy„ sˆ®ÔQ%ì4ð£Èë®-d~»•ì`ð3�ž.zŒ¸R`É�$| ¹c�**¿'e(xáœPƒxÒå¯Ö›uþÄ uÕc,òÔ ùR•º;ð¸ŠzŸÓHøì÷í¡Gâ=ß5]0B9¦ÃˆúI ËfؿǖÌ>‘!ú<~Ås?XîHLáxÆ#@sHæk  „>‹R}&^Ý«°T°yqB�ò’Zü&vÄ C1ོ6ûzLHZc0_·UÑ€a(ÕKÔÔ ý~çõ4³JÛvÞŒzŸ0W›D]R9+mc×bN<µxƉÁd«¸Ò'<ƒ˜…×#ž×±yRÝFw�s»U$‘æÒe=¶ ¿ 9èGűÀ›EëW’¼ÈŽ*§KãÌ@"ªÔÇýÌ6äæ¶q~$~åý´xeë5‘¹¯ rŠ’Ófyùï×È&ì^ªNìÒ†i¿'ÛÍR0ƒ.•ÿü�bÈ!Óäb� ‡E·ŒS¦²‡B#áá'}xž,°áp‹Ç¢ôosΰhù E�0QŸ_ŸC0bÉ©ƒkÜLõº<÷jï{¾¿U‡° ¹‰†EÖ£ˆ« œ Ok†c¨×/©íÅ=m‰¾ûaË" ½þ{}6ÕH£1Ä †:ùpNU¿œGé¾Þ©*[{Ø à–÷¿øß…ÞW ŸIœ—K÷›á�àjnޏ�o‘G§©½lüŒÍò$5׺hѪçß-ÊÔ08•AðKÞXéé…rŠ ¦*?ZI�'²uÖ1{¢�EŽ/SÑÎ�%¾Í]­'[Hµ-8u7°á€¿&á@9¾ Ó“~wŽÃLKû>591‡ñšUÓ{#Áª$#ÄÙ7aEâ ¤¨(F0ÜF?ØùnÐsƒc¾ô)ZŽ™^ ÉbZe¹/b4à‡ÅŠ:\¸·P,§†5`ºDýËOãÒÔŒöùe�n7ú˜0yNwþRSTŸ8V“Í�ÊçÞ¦“ßHV6&OŒÝ§¾äH´C¹;qŽ òBÁ@P!ÔžHjw÷Ò+wü7wúœÈ|½@áå ‚‡”–ÿxöÐBÊq…±�@Íè0¶2ËÒïŽ%³Vg¯Û¾@!ÈÎÝ»ˆ|9ìFÑÍÝQ„ÓHøõ0{ý«g¼‚¦€ÓUrk¥  ÅÐS1µS‚5Uý%Š:óÄ›ì-n­²ÔH€+UéÛŠUÈ\cis²nñ:Ûº‚lœ8P?ÌÄâ�™7¶³�$ôfDéÖ–©‡S(e`²�•kÛ’ms½z{ã¶3e‹/«ÅÇïÓ¹ ü^D¥\jHôD“ U1šÀwH*iÆäwŒ/è1ZÐ;¦µÀ<ÀPøM¹Ó/3‹Ëšÿ†"NøÇÏhc ìžêHŠ”9Ôå²aXQ Á °éû©¼åÞO;ÏŽà9?‘K)°³L\€«Úå�äWÜ�l]@?ÿĪÇ$pôÝÛù%þ$É!N‰:ÃTÚØÞ홦sϸûGa¯´¥[Í?ª©(ê�×#hãõœž=®i^ìx�ѺLæ³�ïÏ@§è„lßyáÞ݉c ¤ý«aûâM¿°œþ°¨×KBÿ Dß9Ë�DeUî;"Œ_«Êý Ù2B /×ýªñZÖ;D¾1³ÖH?Mvè;¸5€ñ§ÔD´T•Å+î´š?w9`¿i¨Ë¼—ÈÖ�ŽâHâlµÛbÜoIÿazF…¡r³‡ª�uf?€*¦A¢ŸE²‚T)Q9Šª€ß€„ÄhÅñáL!ŽÒT8¾OÚ+RÞÒ]ö…G”K¦¦Ø)Ø)ƒô‘Su5�–‘á‡Q¿Ç‚e冭#¡×A|®•KðYg�N¸[$cÔ-B=Ü®¤´ÙäN?,��d.Ñ[Ÿ·ƒÚw ‡*í¾ÙÖúy´‚ÓhµÛÈì¿‹gNÚ’�Yò6i¬cK�_N¦4Ã-…´Ðk`º¥U³¶°x>“mÍ{»•i¹ýb¹Ïo"µï¿]"ëZ^¢á©³òRΜ¼�Aõn0 eÈ1nýSPÆ«_¶K±àë‘€m$^"*m°¢U‘áhÍ�ú³¹ú¹Ñ¢¦ÊâÿÑÿÚÄDÎŒÞÏÒª¹�OZÅ«+s¯^�Ä7>$ì˜n &'ÕÁ3®´ÿÙtއï,aµ¥ââX�1'ßæÉÈÔÆðÐç«uűá¿M²É¤)ô7â…rƒ“¡E¸Èø²«nÎB¼ä{_¤îâëz`øÜ‚•�ÁYuþäpL¿ý‹'áÏr•a´8ƒÍˆÊŽ’² +K,†>–º/_»´Ü;8ÛÂÿ„š*�k1»)o±½Ü’KÜ×òФøëø¥3® åÑϸ—v›¹ÙE`ùU]«¨~ ˜â ü¹qù3²¸B¢EÒ}·0\­¤²~ˆæäÝÊÙÍ7jX\�ªê ¸U…�©60ÄÍâ ó)àÚgPÄÒ?Áø 2Ë÷Eªì?¡(æˆ\µø”i”r7 oÂùÏ�·LXp¢�o Å¢¶Z‰< &Òfv™½àµŸ–$¡q¡™DMÀ¶ªrš™‹ý�Šo‚(6Ș¸÷'�Àî!ÙTÕ2“ú¬dAÊæû1z�לë4üÚÝ%˜Ê÷Üã58}üÊ–ñÐG¾wýjHkÎÚ»)˜íâ!BH�dt>6NŽ—‹à"kÑ:½¢âÿ餆Эº³un0Ú�éö­öí¬$4DÒi§Žù}¤–ƪ-¹½“¼jüú¾¥ãø µá|º#Ý^Gµq”óåÕÝüØ"WÏ´úDüYzE§è3ØJW":/ “6B­H>`1óUj­KxrjC"²vú[¹Sà˜5�¯kõ-M³C*Q5OO`RDpwèqD°ut 3sz.ôŒŽI®S¦Â„b{úxàèõ\�‡Ì'nqCøVtA’ø·"ÊyÃŽÊtÓ‹ýb°Å+mày®}ŽÖû’0Vô$�vÂGá&0¬Ç\6&f püÌ )_ÔiÅd´r^Pomn!“O?­ ޽;ÍÙ’³X 1¦´ Òoùð±ÝÆ–h\Æ#US[c-È«zé—·=S£ ›Éœ!â2‹dËàå}Á¿â›ùHC§‚½¿rô0Û+æ©h‘’ÆI\õ <Ž`IÇk&޳wÊ6�z(ÿçB¹VH“Õ2ڿ͈ä?�Æ�!¹…ô­O~D_6WS:e‰xZOvÿ¥ B³_nò‹4”> ì.(ªŽ¶Ù™Gó g [ÃOÈ3 ÝV†@Û´0Ì´€H¿� ò2Zü&}²(SŠÍ0�‡›ãqÑ…~'‚€ØV_þ�¢Äõ8 ¢X*4ÞÔ‰D—˜sWIAÝàOѳ¢íÀÿ/ƒç0º†Û×y_üw¹ë¤>ß>¡_q°0a'ÇÉ!èï‘ã"°zŒÙ�Ô¨Ò+Vev¡B˜͟�Ó£jÿ¢¨×Í÷+âZ�ïIH{>|¥BÀ¹ô×£t BŽhNW56ð&¬ "ó/„Ñ|s÷:+¹ðÜÀ° Õà­þz>Þ±Ôª…pCªÃ›Eëñ™½¶nV*<±ü"=JûpB¹fðÞø–¶³0÷%ÅÇrMxå\ Ô@Ç&ûBÎŒX³}….¾´hdZãp0éÜ«©‚÷Õb9ÓIÎÒØÕž%ŒâÂhI‡r•Á>ß~ h “ßî;Èf»<à²MˆoÖÄ:³6¯ñŠÏØè»½Ðêš"Ü£ºÄ; Ȉ³™á0åûUÇ?­‘[Ã/Ú½ c­­¾õçV¶^šæýŽùâû \ÆŠM‡J\ 8Äœ! -ŒfNTtí} j®v¿ dž`¬:«u?3|XëMQ›˜ÇnƒS ˆ‰áac[K{4Q“Uš–£¿G@ÕÇ•s0ƒÏ6úªD¯¨›ëš ªQlKBarcÓ ÙÒéøÊLßE$ß™ë„=äÜÖ�½†Wc#KÃÙ×#®bGEäeªv”Çloæ©RÿÞΕîÐxÛD¢Óeë„+±GeÄ[OÊæB„tÔ&~#8½/ª|sÚZ¼ú|½4öÊÏàºò0žÉ$^�‚öQõ¾1ãÜæ§JHs½É¿òb hpÙÄz^Íò –ðGÐèm÷ˆö�åQµ!†÷õ$Ü1ÁÂåz¦ÏÉíÅ»Ǩ�æ^ý>_Ð#\o,ùŠÃWwû“ÃM'ßï 8L™F.¿ Ì •²ÑDº%C¦€'12ßÎ>hj-(½Å‹3XªcDx«�~@¸Ÿ†H’Ì~B�ãÄe°ôx‚ª¼C…áY¶ÊÙ¶ò >pxedQô·¼JŠ óêkSM6/¬Är JJ¾à“«ÿ1S*8Õ!oŒSszâö·Vý‡ˆÔ]‘çî¶¾�¯´[g*ᨃ_é4zu nÞ~ôïѤnêð�ýéå¬�ƒ"¢q¥g¹SÒÉH?Fyƒx)qOr¼vËÊ?°WÎͯL‚.¼Sp$aTcç#>V´XN]œË4„Î<`�#²o’¤ìyÿ8ñ˜â­‹W@s~XS‡úàò1ÔE=&ZÑúćjÎ_ã¼ ßÑ8u…°&38²¤#dF�Ö½ˆêX+y·.ý›ãê+ù0Êw¨ .Û¹ï-ô†|Ô×w¤î|µ7$Ù7ülïÐ_�üìçc»Îè„6ê.�(ÕÿÞD›&ײœ�T9…h±‡÷ºy õTê¦VIÓ>yE9ì�;®�àSj_�ðmÆ&?y¥so·ñœ‹ÒJL_Ú™É"ÑêÒ0�ô“Ì_áÿ¢LwܨY<æ›ÍHQÞ×—"sùìÍ@‰ÿÎÞ*i„©<mFÉ’"ªøtÄÎò¶Ü0[bJFÐ~­q±Ûý1GÍr·‚ìx¡¨°êNª®ñ»K愹͉ւÀö|Rñ&ïó¤ã�H€ Y¨ÙÁ1בKr^=3àŠmAá�½nûW_ÉÿÈ=þ÷ô€$ã¤-Õr_E­¢%’9TÊ#ËÈÑ>Ÿ~§¡í¢ÔA”Ó]Ô°ªØÖûÍðºÿµáë�yŠóé ƒ¬÷l9_—½Mô|dú¸Ã÷ÜV{Ú·œ$èýýÞL5{ùÊãW~q¾á\”;™úuÌ÷Œ¡}ªÔœ¤·µœ¤�¹Ü]9ë»…¼Û@ë²À¯5hïñÈÒÀàJe"†> R]O”:ØPj<0ÇWûs—èµ¥éò_ãþûÕ¹QÚè¶”kÒI–@t†â½ÒJƒíPÒ°½F$/ólv6à¡+€ëèà2Ð8¢C»ø§ßœZîPD+�VI�WOƒ3×UV9Q悪º ( 0s¡—ÈÕ}ÿÃbL0”•W§F0ð™1”•öCÞãi²¾êJȦô,u"žƒz«  ö‹�D{lˆoƒFÿd<¿WœìÂ%€ÏÛÆqê¼\VÖ=Jƒ éh=¥M™×>Çž¬¯:fMÌá77¤V埿*CØzNRü$‡ V¼Y€*OFo<Ⴕ^Q¥¤Ðþn ‰e@æÔJxŒõ¾Îîõ*!{ЍÓ}U� #Þ«¯+Þ  | ÖÉhÐüa^ Öv�í˜Z C€"¹‚4ðݶm¬™-ßßz°"¿¹x³Ù2n:&’OéÚ×ͽ÷¹q‹ÌùµÙàôf8d×µ�é¥þ´ƒ·ÿ‹î>×}>¦r¡]f#ß¼P_QÙ_¾Õö[ Þdìû?žÓVJ ŒeT’tE‡ø†Ðµ3EÎ×L 4Í·-÷-%i¤,í;Ci;ƒÏ ÛÇr ÅÇÃíç/1Îq–Gˆb©¥oqñ�¾Š-qM›E6yxia„: ½µcYÏ_0Í»ìýº¹Æ 43Mm×j¾Á× FR~Z14 ‚ÝQ¨ñ£èú” Òz KUdoc€:iÇØG+n7Kg2Ë ý'Á‚8ïïÇÙ¤øÐ戅ußã�’º!L;?Mêq×ëJ2Kòr|<S¸‡ÚÂBQç4�?¤©€OxiYÜQÃAÁ‰qWºß9f9kJQÕE�øiÖÆÚ;!\%òú"6+ÒWA¦LãW ²G2éÚëbݵ²0æX¹+ðŸ'–~Ÿ\›ÏÃ¥o¤ K™–d�D+ÝÏy[û…lž¾ëxCêé D·’ì…Ùr=tUó8ÿ%¨ÿC€p¿œ›íòüKJ.U[`x Û�djè�CŽÓß«C¨¿lˤ(Þ =§Ûá½Õ©!Q|~\Ý5PX‹ª(wUlæ£$DÞÂîXrHØÔ_9ö'÷£že–.�6&)8»Ë˜ÈFI?Q?ÂkiÖÝ¡.AÆV©ËzÛy)TóA’’Ôh€¶ ˜ÜF!Ê‚¥tÿÁ|y¸E qÞ p©áíµMu%,2C�5§u%øAí…î˜-<·sùtSf9š1}Ù…­�ÆW-@µÂûõ਩*­fé(�ê¯kæ&ʬq… êCÞR} Šp¹zEäFü¹•ú4¸‡Ðái¬tÀ;fá°«_~9›cKš9@)âa„òÁ —«"…Œezïw¨°*}«ÞÉ¡mÙÕÇžÚÉݢι?/ÜïŽÇ�CPœ‘'Ý#hD#ø4º–G}U—ýÙ‡ &ì`)àØûMž“’ÿ!ÝÞ½Þ7¯N‘Æ ³~èlgDí%Õ™~áZ0‚w¬QpKéwkÍuÿ¶²^}w}V\å•„~QG…Àˆ´¬¦êj½MPrÈPÜ4V”[�ˆNd½_ÜnK ®�©êŸÉš„‚Õq¥+ÍòüÓhÿO>>ÐR�MšÇF.þ©Z7nÖAÛgB£ÈÌ»>doiÚTÓ%S°¦#$muˆƒ÷ø¬ëzâùO;mhp´�Æ¥÷ÅÇ "Ö ØC�#…nÃvlgë[Uwã£Ð}_j�N2U<-9#ƒ­\F¾\ͲÎö „Ö5Óó6+Ò?(˜mÑ_ÿ¾ª`Œ…§£?ª#¾,ôNÅ‚«Ð øåhŽzÄäGö,×Rïe}ˆÖ¥1ÃÅ|KÂ@Š=”XçÄúDw�ÆxŸ;&pþ˜¦·RaýNô�Õg&v:uˆ†,¿q·}6ŒÅŠžbÏYL¡`wëªH–&ÊéÊaî4}-'O_XÇOM�ê¿b 2z©Þ³9P^ Ç#ŧòBxöK|.(,¾ 8³‚�Ëíø&MG1 hm×­œ�(h43ûo´ˆ|ñG½ù+9\ê.iÏè ÂÊX{IsÅ^H²ÎœSwÙ”"s7›\wÐù7î™výÅäc�Áô0ËAl€P�·ú ¦EŸ5실\&îäŒ_b½oªI½}ã$4©Õõ­§Ò‡(uzx9¶ïo*«¼ÂØóhÀ¶ñXJ‡`­»�·‹Üí46Ž‚Ïi+<¦Nºt� OÛ0l:Ö»–/²$:x°¨‹vÏ¡ƒÖ·TØßþ±Œ½°ezCpàó ³Ex^Þháý(79WI‹Dµv„�dŸYj`>s\¦˜y•7©-85¾Ð­�ÒÒ!“S²ðÈÁ¢°�XŒWÍ8‘oÌ:ßòÿÆ!foÎ.L´ãoæóîþÈN339.€àJÐ|ÆÎÌHÞ~£ÿ@ӌڂ�&Õš“VÇ ",¥º€ø=ƒ—2¡«~`¡ªS4½çÞÞUÀYÃMGðÆõýØ àôuA¯�û¦ECüÜÓ#¡ØãÍ“Ì9W ¡ ËÄ10±¢($�L Nº‚Cý>�ý Õ’:(úLbÈ¥Î�‰7±� Ķ{ìüÒRýø©2HFîWˆf^=ºº~A·(¥¥G£™èß¼Öø ,‰Eá^w—d ªIúyo%¬ñ8¬ñà=¯ !––+�1ÚëÜ×'^´óý‹òݨU^®Àg›~r×øê¡-ŸfÜÌÓ·ûQ±31=à bºð«"k‚=@ÅœÅ#¶°@—7È1Ä]ÚkZ|W@q~*S Lƒ¨ü=èW‹’ %Lž§çÒD?ÿý)\V(µx$¡ŽÜ´Z¯ýòò6ÏûÆ2û Sñ \”֚ѓ+ª-üùOŒ5(À7ÂLQ¶|úYþ¡¨GÎÅÀHJÞ�ö¿&p<^#‰Ž7ÇéMÏ0lû¢ŒûÑn+WÞ1il¦�xFEoœµÊJ‹-FØ)yìØbBaÿùæwJvËU­í�dÂT¢U ´wùa‘=6Æa¡Äßú¯eâÂ’n\¨ÙXôË�úlÚö%Љœ�ß%4u†uE#~8gûtG}|ŠÔ+½Ú[�×>0þ½‚k3„ÞÀvX{ép…?ŠL–õo Ü7–¡Þ/ «°G£áýÒ(:È\-@×P<‚½_L¾©ýg‘"×B‰4ñ³îžƒMü,9Òñ¼,¾¤ï<½ö|‚š}¦–h�^Ëãåš>�$ãæ}]¦{Ì�dÕªº!Êa´³¨¯�ùv°Ñ@é°‰¶ÏZƒä/¢ÎrvsY´z­ã7Ö“ý¥ðƒ‘‹Å“�Ù�À 0ñ¬Ï\”¨IŽ!G™ÎYs/€Ý$°…l­$ª§ŠˆÁ&yV%wçÕKÏ(ðJl)JûHYÙñ„cªÈÍÛ]¿Ât¼ZÜFd”ùAÔu¯`þê©Ý èT§æû±ÆðˆcŸðcìy‘@&rûP†ªõçàÂc1¶/~ÄE„ót¸#ýöã¼#’ß1LaãK(þé¸ÚòÑY¬j¶Ï�ó ­àüZL3•¡`æX#ñgÂ<œÛårˆmB`㯑Pÿ)ö þtÕ�V´� DéJñ挥b»O'ª®¿àè«ßìLŸN^I¦²qÊ*Ø× |!N"� hrG70›šâ|H/ºT§÷ÿÏ¿),ß¾>WI€’\ÿ§3{ {wåS÷K€•D‘¸¹�Šä~àI†pçPV¬ KâeQ¾ïwÂW{pc œÇ÷aì÷lÏlAu™¢¼ð6⟠؜ô&v פ“>r¡÷} §¶³2‹ÁKÂæ)4¨ß±d3ßë<µ¦’Š åaP‹_véÐ �ê{;ÀäCëWÝ[t åâ-ñŒdÇpsϦæÀÅBèzÕàïŠa�EHM-zåðJ®(h—ÄV7 “Œf b¡³žÛ5ÑÞ�œXiK(eÝvY†(û·(E2%Ò3?Tù‚}6Òmü²�aW‰wÉ\½3 ;àÂ=»ñâë %yŠÓö…(êsc˜'¿ŒL\+4*$ë2ÀÜ·Þ³Ü$r›á –ž/Ï·[�Sz£ú¿òþ«¼ù`Š×ö^@¸æ+�v\ŽÆyéªxÖCjÎ?#jé�2Q ž’“é± ,êëŽÒp]àâ2ô�c¶zåëæUŒ‚­f‘…ž¬®GKÎÁ�Z…|½ti�„™¦Ó’lêÿ’áâñ¹Ø"sÇ _}¿×T»î‰œÆI$¼%ôÒÔûÆÖBÊ2Ì EÌõÑG)Lý.Ùªv+ :ÿ°ÑNM$k!k›úá*tZVUûÉ/1è´~Ƕ€4ö ïpVñf‚®J{ÐÉ»Ôýã%®EfÅšSšÊ n5ŸbdÀ­|x^5€¿þ2Ô4ªw0>\JJÚŠ0¹%„¸äý��€0RºÐšÅ¸?ϰúÊÊ·.™ 8ç /ekK:hÒX÷ÏA=G›)ád@Va½ãK.@ó!x$†z?j»fA… à i% LBˆìÁ½¢Rö±iJ�Ž Ë þ=ñT‰Î¿û²Æ¥æöƒS¨ÆGŒ3üpkºù¤@2¶é s¹G\8”4«¢NMÉרr}RºV¶]ð©óæ±V`&N8·_œýÚÆ�$~íþëDÌ¢ë:²êòÙÞÉ�vþø»µ%'ï´J7ÖÖšå5„±Nä¼#Äü2ÎW&µ-íb` «D/Ÿ5Å.KÃè2=Ö@’–†Å|�t6Q~ï\R¶T ™y.¹° â»§0T– çN÷‡^I¶§¨T�çâ¿7©UñÊP ý×1k¹€ûQèuvKÒÅÜSø™aïÑ™ï3ÀÐó§9ÊØ‰˜MYGßnDb�øÌ\Œ+ÅÌ[<Ð^«à[I”5ûÌê$}µ� ü¿±@!e¡ÞÀ8l¬ ¶t€Idí¾,ŒÃéEŽç ŸMQ-1Š®cM]ëˆÈó>Ç­³,¶£°åœ³Œ9}¾Ü˜ÏYýy‘ý#-œc’»l¤q†æ|‹/Vúêô¨j÷âdñ{¢9Ǥƒœdrg\«è“Æ剎}$ Ñ ý›g_˜Üç7� …IÕ2²®I�ö”¨ª)¤¾’÷¥²[ÄÝ�hDõÞ¦Yѳ>AK¤Ö@){ÁS‰j¯ŽŽæ[“ü(ª¶Ó ÆIr»dzžÚ÷._RÌó,2œ=Í¿R]}Õö#‰;o¾É’FCþ\V|ªB„®X4?Y†BŠÃ˜ÁÆÛI4ºI÷¡'fªÎ+*R‰-È‘Óy™Åèð°&82ÃXäNö{y‡¨�\ÔêZ�Z¯@å�‰+æ&zOxGo¸NÄC~'IE\Œ^4¶ÔR F÷´=˜•q=½:3œ”Œ…w[ÁÆF½ÅšÄNFÞr¢3[íÛËÆv}â+iœ!ÕK ÷¯Xæ¸KM7ÈëÍXÉaé(k$ù Ú}~¬Ýõ;‚g·†C4ƒ†½‘q)ÚÝÊ‹„Ž\}«g<¦ã­Ü#EÊÜ01WàÍ’¸’{è¹ ] j ¬Xbfý�¸'‰Â�EôÙÛì4‘<<WÝýOŠ+•ë8Àv¸á'31�™H‹½a‹R•KZn{ÿõ5™gá£ég¢dëH‰Ü�Þ}d6'&3¯¯7rYK‚ˆîbZh,®’QB:·Ëµ2ƲGbö{2�—se„ Iª~< ¿yÆádO Í18’÷¼xýÑSÓ•[ç„ÍÒ3—Ì´ÿWì.(�xÉ}$dZ�AM~‘�snÓå1oT¥ŠG0w;¶;úó¬¡t øÒ½+?HaHÛx“Ö¸†p äzd²woÏÕÔ8…~Þ®fu�B-ñ‚³kÅhï”}º¤8�tß1uh–»ýÇ©HÚXÜσ×3#Y–u"e¨Z+à=ÈGú7ºt~¿ãünŠFV›á„@¢ý®¤¸Ñ»[ ^à ìxÄžƒx|×/³y!ÿB@Êuˆ™g›Bš1–æùÉžNa1¢úŠeDˆ 0°¡ô”z‘Ñ ¢‘%ÎLËÜQ–Ñ¸Šø,`M&èžÚP­0­×&WaÌì­±Ò5×RÔ¯¯™íê}YOÔ4º8Bð $µÁ Â]q=V˜Èèú¤¢½XE‰ð£«Co ÁÎü`®8FÄáüT),d€ E¼7ü{†€Æp�Ü3Ðÿh1–´ öÕÐ+‘ÏûÂæ‚âC¸ƒØO58-ñ…ˆ"”¢¾�"Q*%=2�mŸ’ÆÞO·CCt'D£,bÈÙÙ ÞÖÈ›"7úÌaSSÍOD‚¡SF_nªÎb; ��À ‚³§�ÊRT’T�àÔÎÄ[Ì¿hÆbÒaü mï0oÁT²™ú*.ýÖí  ÝdTГõ¼ÁÁUJ©� z’çÀ:çIó¤um¦Å$¾pžyÙu3Dš'`]aø¡*ùzŒ�[ýktͼl°Ô*g ©ŒN,“±N‚•nØ};F5Ü-Š˜P¾:òH˜¶T{ŸÌ©¨^y/æ=@9².)¤”ØmÃX³y]îØÆÌ®!]:X_�œèÏH¶:<ŽßVâ–þ&ìÃ0W:Â�z ¥`FØ]æE‚¥”?Œ×ÊP°G¤6û°½Ò~Î÷xÚHþ2�`˜~JTáE�ÝD‚u48*"œ›%9 î³Mf¡Fó'Aô{¢1|û¦Œë4°1RŸ¾è® ØBCä—úÏÕ\§Åu7“oË^ áƒÃô6r ¸cOÒSÿs¥ðB¼ãÔôQ¬j�váÉd_{ÀM�‡Ã½\¤f"ÊÆFþɸ‚¹[‰þVÓ…Œ“Ét,-Œf_¼ij¥Aÿ#ó¯ò¸ïÚä¯|Õo�ŒkÒ`²kˆˆ*â äj ޲Òg°‚³&³ìKõ\g„uùj‹ABÕÚ©óS~Ek«+‘&Ù,q÷•I³{[ü‹)ÿ\ú“ M¸ï(?C·Y€1AØ¿ÕÑÍâµÇ°�^n¼e¦A"2ùŒ©ºµ·ê„ÿ=< é¦UVYk[n’u+üŽ¡Ñšx¤#2Ø™ø“¡{Žr8ÐÜ’”�ªÒ«ùpò+SÁÚŸ©Þ�w_Vh4µ ˜Ó|mnNö2òEtðGpã�†)M ¡ƒ¥¼8Ú}r0 7ÔUOkG—/¥ : Ëýyë4F6„2ó]ØO¤guJæ#Ý‘ìÞ¿!X}Þ?ë¶nè´ÇKW~c¯HE&‡ßÖ¬[˜rðŠòc äùüân‡qVÈY·"}ЪQÓ"®]$²9*)qÉ;§ŸAù.�º{ î|E‹VŽï,Ãiœ ÖAéR(Ò}òà­¤ŸPÝ 8fokžY¨È/ó²4�ýâðÓS ”K,cr©B¢ª&ÀÝãÒþ �ªç™Ù³ŽèÇ>3;�ªóYhµ\lìì|lùW˜n«¹0לüdKšÑI·ÁÈÑ3Þÿ®‚ÏÚÈû!%>;�Wj:±E¢æqÚi°÷»9l½¢ükήÔÏq}`\ž²+g0|>5k{÷S*Œzvž´t4še>Ÿ¤RKg¶úËÚæ%ÿ¢h'D!Ÿžf²ö Ó“x8Q+ÅwÝò+eüˆéÅÚ^sžË>ü‚.xdà.¯’ºœ2 hŒøŠµ|à¾{"vᕚoò»¦Eƒ5E5¤Oÿ,“”ÖNyÓn›[4ÿ$w¥{WIåšË눘ÌT]V…½®ûkÇä¾ÅhÖƒ–h$"ò¹Œƒz*²`öêÙß‘;µG+ö,ò’wÎoW-Ú‹´4Ø3{¬˜¢ xàº=˜µ¨¨&h¤ùM1µêS6/ï‡yTSf|uÛK&hIÏd½†,d:\†bð'¨æÛA‡¶!(÷Šg† ô™É‘«É›Pó˜‚7í<‰/;ŸÐþeŒ9^µÊjîX•p¸I˜´ý£®:Ÿýãt'"àÉ�æäÆr0tR"w_Zàbå—zÔP9ÒÕ#Q/·fl¯7ûéϵÁÞó¤’R\'í#)�“>Ùýcÿä>e2 ô[^ï7ª2-B׊̕0vPfæPPþ 4ø÷œ±bÆ:û0›w[f=±*WŸ¼Ï58reˆjCª‡ßo2.®Ë6³3QVÝ$�^ÕwAÏO%H¯o°µ£®zYö 1«,cÔF4Csa.±ÿJ ä¦Ð¦‹8Ä(ökåé˜VõŸñ1à¨óÃ4_�-`?�(×úÏ\ñ±|tQU�>ªusy§5ŒÄŸæSÍ© Ád˜Å¿Ð4£¤æiš ‰þ‡;”!y˜üJœ¾ƒ‘¦ú=Ú[Æ.XSR¨’pr€Z˜ªnðQÎTÄŽý‰VÉ�I`q2ËÏ v½Qˆ€áiÕK. Í/Ÿ }µå…å~. ¡¯L:ñsÂï,fÈG2êí{köC÷. • ?8àtóË\W¸2þå‘ÙZJ¯FðS’1Á>L/aD Ù'Aš$lAýÝ'‡Øã•c£ìƒN³btF”MdGfR¦$²ó!•h®tÚP‰®ÅÃÜ� rgw>tŸŽLŠƒ¨bľˆ¤Žq¾ôèÛOŒz8Îu÷;u. – m]ÌðoTbÕGXå7ÙŸBË9wº­îÜΞVšŸH­Æ‚‡â hv;Úù{~+þöø$ø¸U–�?Aí¥Aâ�̯7\™w÷!§õ+zÕ&^iË«’ÌvKrÔ”.¯}AÝp#…*ÓJžäIJAí#¶òâCO˜NÝT³Þ{*ïL/æ”Áµ½¨®#¿íyhÁØ_þM§ãŽÑGÓ&뵟ArêÎ8ñ6Ð Á4Ý´5ÆÐ¦ƒ ˜�m9aql¥Á N ÿL`ƒ’ÓMËPÉKâ )êFÒ±¸‘¢áôG@v±| À8¶—ÈÝÍ',SãÒÃ2pHYlµÿ?V@mÃ_ÖreÛîeÝàÃÚé)JŽ“µÇ#Äü¾'éR›å-BÝ»ˆóK4P¶X˜�œÑ¹µ@ÿ¶×z|Ú�îïýÿ?!S¬ŸAKÀ!H«L×x½ï{´'´‰),óÊlmNKI6ó¾U±©@Rc´�€ǵ·=jªr[ ˜7Ëѧ�¼eJ(ö(žh$>ŸYªÂd�u*MOª…fP"1§z|.àÁd˜+Íou“GË÷C/t½/SÓzäªJ à™¶5qìäîO[Ù&#Rœ9^‰ Yé$iºšÙêËV÷ãÔ’‹MNàC‡7ã%¢}‘…³&tˆí�›GûòCÃýšÊṳ̂MìzÏ+ð$ƒï¹4¨ª0�nMÊà˜O NeÉàYa%ô¾¬“m€þ.ß¹U¼¾Ž0_Èõ]þ…vÄ•eÄ,ÖüÉO-1¡ü�Ø .[>CÎUôq@’h—l:jà5_µ�v+ˆVÇ&2¹~qj„%È'L³ÍºAößIá’Œ/ëÌX)A�ÈòWŽW‰5J‰@�"àò~ž2”ï8~žDŸ¨«ùR‘)îƒúèÜ„B³ dâ¯o7#ný>,dc-_×ýåÍ.Éås“»ÍÇc1‘¢>„Ütny4|àÅQožl!@l̵¾­–OòoSfÿ»ì«F¥ßâ .n±Èêßþæ š�$Ln™ð,‚/ÆQŸF#oÁÍRb Ì:í,Aåø­¡JfO“),‰ï…$ëÉ@hÜåêü™9žX&Ô`MAk³è’•ðo¬/xçɳþR÷éI_u×5 —Êx°ŸSÍéJC—_ÙÕá}ýnì=½;R‡=–ùÇšþ"ý$%{÷‰µ‘$a8ËÇ�ƒ>ü»íJ퉑Yûïß^X®ûÈç?ÿÈW¼¨`—ºgõ$ï�¤·fÁmË;`}uúºÐZ¤›MŸi•Ó. ÊNÂ"M�OÀDÜ·’�ŽEI¶¾!ôQZ¿a”вc­Y)þL¦¦©Nª!�+ �ÐyY}OQàR³›):ã¨"ŽêoÉý¼Òoî1®J°OÒ’�‹zÏ?“ÏâÁ1Õ²l¾ðäÊ@gÇúº·ê޶¹®Ð ÜѯZ•€®¿ŒBQ§w ³f,%«´ˆ €8 MÍþxÔÐT(‰»ÜPÒÈYBy ,§‹òajû&9·RNÞ;)ÄäÐ:±Á?éLM0M /;•7-¿ÕVê»ðŠ—Åÿ(<÷ûz÷ª4éÑØ�7 àºëCP®�mÜÞö^šå�(X¬»TÕòû x"qFãË@nƒÄ^c2�" Á¼÷Û�Av … Túá‚m7»O#�Ìg5 C2ùÒë´µ hó»ÊVPEñõ¨ßχf†~ó²Ìý;†å¾=À½e¯S³”ǾC q—ÒFRöuÍúîñº¾¤}lpöºTý»œ'Õ 2Ëa6)‘Ë™Ä#hÓ»+äk‰!ÜU\¥›^]‚¦í}\*×No Önµz6òGuØÆê=P !5޵ãvF‹¡.®ž|DŽÖî"ϲÐú|rê!–a×–•»ˆ#£äh*µ[rOÔû©¼³¾Tr—¹LbKOáØ†ÎØà9ßÇ9 aÈÉ³ÈÆóßr %;„òèÏl¿�MÎ1("Q¹²+²œúê¶=¿0$þÁ} ®_ w’‰ÎV®à±¸6eÔo¸¬qvD˦Ó^nóu䊤ÏìT‹ÚVÀ�û¤p–$èø{Ÿn¶<žÜÙK™èõN¯‚¡ˆ1ÕÑ>X¢y¶©—DÎñ V,/Òíï*6–‘(9j@xÔçÖˆBO®ôbÕX*;…<©òtÑb7 RÔFÿ§¸ÕÈ-²££.$Ü\¤›}ô4Í}�èaík šYÙªtžÈÑÙçº!ÀݬÂÎíï>x8;\ý3åËA}èñ¾Š¥†§†½+$Ž‚9´ž^¶n;{®<¥á±Q—¼Ñ5ïâ5:�|õekÖWÈt°á7¼wy€—"Ézì$�]Â…yö(9¹«W_fè\£¬CÅC§úÕö£ãÈh~0.í鬤È#«} H´Uý ?x–ì{_@ ~Å…¶ëžNßkÚç‘áø{Ú¡;èèb�k€Þ{‰¢[[ßÑÃÇæž`"06R0yÓÏ r$U+ ÑlˆÊŒ·Xø<üÒevpA6м4zšçW\u\�€H¿™Çk÷Zí¡:ƒ¨ ¡i�òÑù{ž9*åy¬v—Ô&õÈn^s±ö1Ï_{ryc’¼éP{ÛÄ-%¹PVИ´�Â)xõ Þ ÄfVý(¡¯Ù }±&Ô>²Øä¿›Å^Þä­ßG- ötïNXãõü«U§Lˆ+竟’æ‘6߯§ø;jTÊ}+É2Ì+ó;•ެ€×­ù4!ªV9ŽúŽ×2),kÀƒ¶ôES;îç4d‹4�–WoêÀ`m) ÇÕ©rEA ¼™iÜavÒÇl,潌ǻÐи F‘¥Ñ—sƒD’ð/³C2¿ã¨ø?½O¶@[‚ÃŒÐ妊F?”( ÀR’®¾ñ¼[¹KV'û'¿—>Å-TÍLˆ€Ùü=Ÿ.ó¾Ëž ‘5‰ÖMª ¦¹AQhPHÄpRÒ…ëÄhö‹ï�}§$çìzb]-�Î-Æ¢OD)�ÃÈfš7l‹Âº£6<.S° Çk¢hìô9ùF¸4�‹—»ÂØì5§ü43�SàS_RÂô6Pê!Kí,n’ d ÓÕdþ‡�³Õ¬@IJ¿7J"€új[òþXFF4-f l˜!¯ßq¼Î‹ê¾@"ìfLÿÕcæ™*̨Ŷ’™XÝF’”X3î´ ¯˜Š˜�×^�¿qÞGð,xŸgª½æ…µ`äÏŠFF�oÚžo#ßÕ–’ö ¾3}n·¸¤Öoè8ˆ{RÂvîzÞc\° ìw™�°›�‹f?�ZÆU!¾&½teáõH=kWV‘®í=,9¸”A(óÆ·´—˜/[}ó•Uié÷ªØÕe‹^‚I3Zñg�4Qó\=âúÊÖP{çŒÔkÞ Û‹!GL®"ð òP åzß "ç“X7Jõo ®èL:÷�aAuþŠô,hH‡g㡳B©g!’ ©†~kÇBóŠPodÝSyõ`×ü—©q’àªi7÷¾—ðRº²—4´^Ðø½áš³ÚDô¸Æ¤[½´úEý Rj«dz¥«Š5åYå$o�hŽœ&PÑ�r:cí>[ç—@gsסØ[ #‘Œ¼qԆ—\ÙXŽ–˜Î`�ß rÃðÍ‹R)º�a©L‰dHü=a§K9Ê}>éºêǯygãæ¡TðX“‰‘-úS¨by:ž$'±!>OßN¢ña… X›x$®BR¸Xþ�9nzO÷h{xëråÚ§S¡®/ÞXƒVGX4Ìê\a×}„’¬²DvÁÃuþGÿ¢f§ÒDk±N§;Q^ÊŒÀ8Ž�Õî‘|`EàôÉ�hÀu §eøàoó#!òM~ã‹ùË×¾tKŒ â <îÒHÂô‡ôψ̷ùà�fFRžˆ<œoT�Óì2¿˜ù.7aŸtšîöÁv#¹Èžµÿ5­ Ç\"Ùgƒ&©—¿3Øó�WõPQU~ø”®.‡Ú°¥ ´0Þç•h@Z ј«$š)àÕŠRcÕ›Ö²)ºä›Ü±b¼MAtÿbAaûšú@+½�÷®MÊ´þÏÉü­1³«:Æë3÷ÔøêþÑIkSã¥Xvô�Q¬5ÝIs]Eê‡ œ0<œ@½ïæ�fJ/2g¸§Ã!9üP‹p'3cÞ�dÈÒí:rjÙ»rµí66W¹Á$¢Œ»"r—hÿ’uÕ‘j÷p~ ØÞÛȳ—’¬_SÊsX�Þ¤_¬Ï¨·yå{UÓØ·¢SZ:mW Øægê^‡èѬò�z åÄžÇ 7CÛÚ! À°ÒÉ4"ÚSÖã$_ NШ8l‘SÛ¯Àø.6å‡ÚÑ4 „hd�ɼïë �,ÐL^j$zÙ½Õ <ƒ*>f Óq‰k÷}¹…(,(§“»ìÍ ñ>wiv/K7]Àg'!3zEÓ`÷]„1ðÅÖŽ%¤ñLߤèÔÔ�9Z F¸Ö@«êfê:3nŒQsKð`zm""û <”&áE¯b1¦öS&þKÒÛõi°ç«øhjÁ‘΀ÒrY�wîÚQáÆÏ÷%“X�J�Æ� 0�Ï ½Ðy¼q _ÔUØó�ø-;ƒÎ’G ‰1m’:ƒ†Á?'ØÌÊs8ñþ†PPu¦ø¿ØÂÑÿ­åµôU쎋´=×ä¸T ,=ï(sqç8^Œ «m%à {ò€„¨âý³2p宯ᯤ[÷°¨lK—Ã4ùÛaKn„S0 —Fj°×%å3Äî:„! ÷­UÅuŽ õ;½Yv,8ýÝsàô¿ó°ôZbÅœŽ¬ZÞð9XQ‡††BüMeyfÇŸ c(ä4þB¿kÒ rGû·±ˆG‘Ð{+²îÆ»-Üþ£·/å£LA1”@,žG§æ$@bBÑþsC@q~žxƒ�Ü6÷Fý©å*ïæ ÀCëÿл1‰Ø_¢ëõÈ:Ã3&ž|#é <&J]‹õ³zO/·^Ú+œútB|p(>¬¬±Gg´Å[ž¼Gƒ"±Bæõ`ˆLú'j:S�XJÌ>ÎpFÕô‰¬1̉æ' )Úê°¹†Ë0¾;î Ê›‰˜Ä.fûvª‚GÂEGýÝé a3�¯Kãêá¤çò¢‰P¯õßqËqÔÕ#ç#v6MÑ‹nV’+.²άÑi˜WHË[lž¥¤„.î«}-F#Œã§èÈ-ïÕ}‹«Ô瓈�@zDaåx-LQÇ,›»ŸäX… xKèýä§p~™ è®·÷Yº‚¼‘1…#®KU¡ÞI[øŽçµ†ªVïF&ç•èŒÍ#d>Ÿ–:'sÑËןõŸµëúYæ`Àb©ã‹QaúN�Î)�§p†S[;õS,N —õƒÓÌTÕïc \íÔ7ý4~ÃÓD«{ϦQ8Ø„µ–@îþ!>?�î5—ñVÆ>|†´,c8ÜÉè´Olàë�<ï©þo`ìAkj7*·c¿wúûxÖÑ‘7(_ê¬QcsbrîJj«Þ4ýCߣÌù{ÍòÉ”¼|ïD²Î¶n%•ª›YÈ?ÌûOèô5\5„p:ëp,ØÞB=“œï!×г’Ÿ Ç—ÌÐg‚´âKL4óî?4:]Ø"Îë"ISÿ‚jŒþÎÝþØ Šêú(3YÕ÷¤ÞÁMÍmÒ$=H4:ÒÛKëÀyΕùJÞìü4cRx´GÚåžÌŸ,üÏ£Ç~cc¦0^¬�ï�½à¨lŠHLÇŒŠ>§ë¸:,¢!骙¼,wÖ§&;AÚ— Y¬—~îh²Â$e…LJýÒ– Ã8»õúyy /´ÍãuíiŽ‹¯ˆ³'­MNé©Àª°â92‰·Û²2°×$˜ccí�œÙ�™Ð/É\/¤Â ÃE�õW@÷©í×” Ð~wˆiöëÉnW©ÂþŒ“ÁÞ@wß²½5•’Iü57—½Ó¨Cè%õQÊJY•ìÊ`)iæU#ôÌ{¥rºõ3ÑÚ?Wå&Ý=F!î2çso³•6U€²6`”)€z7Šó÷a×cÆ4[wA[ðz}ijsLñOѽ7Ì£YøÕ,§!b(ãAðsjv7t¢¢->/Ü»;&ïˆ "é´oFÆöØí9£ô„^Uo°ü/íÔøf¬)…¸ÍHjŠ”z#.Üß½‰Á„«ß@L¼Fzô�­ƒlîʨ‘—ð{½£Ë?cîï;»‰µ‚•v…MæâùmR¼Qx*]«7o%W%ym��®õx‚Hš8! w{Áäs�¶±",{Œ? }áÐ¥�q߀§ïÁÊ{"�‡H{ôB!Ck ÃJ„X²,xˆÝ#‘«þÑdŒ7‘£ìÅ÷'ê¸ONpÃõ›IÓ7«ªw,úxÍäk()µ ðSäˆ.Òä/×PWÂèp6,ЛMÅitoû§ûi#4ªF¤Àÿè‹°QA ™bͰhlp¨·ì¸\®á)ÚZjØ¢ŽXe¼r>tÂ%\€Ð„¦b´‘Ni…€·™]¯ï-.pD^‹ ÕûFö1a47­‡M÷û*î:�uk,Ïbõ¤½qk\kã *Ê8ÚÓ{wÜK:-¾.iû•ˆXoOÜ,ô±úRÚpLšáÔ”€ßm/t£ÉËôB(ïÌ5ÊM;­zÞÿ)Lùn+HÞÛè¯MMPÑZµHý*3®¸Ö¦U7°çí(V¼ýZ³ŸdK#ç¿Ãp�ƒ³ßuô ·žW;'ýä–}L‚3ÖE¤Rpï¹AšK’ݨ{èÀ’Xr�¦²3E4ý§F�ùMŒ8tvMµŒ¤5Ì•ý"³fS¬,laÞ!SÜEm̼:ƒÚ©_ÃÛ¢èÍÉ·F üDm£·ÚÓÄí* ˆ�Tè¦ñ\�êñ¯WdçaPv3ua]å÷ ±õ?Œ� ‰ƒ�T:¹(x@~º8\Á½±àêR€^ð×F¹“YÈ¢ªÙÐk‚¹åG³>*v‡Æ ‡M8{¼1ì,x±tQÈ.)l§ÇÖ–Îñgz<«¤î†d‡Áã5IpÂøsz†¬ WVEÂ:¼©»=î¯y÷£N)Ð+¨…�¥¤ÓÅÕ&ía@Úm¾È”ô;’�ð€¥‚÷êâV†UäÕß¿%µ±xÃéâ n.�C¨ŒO_"¬nÄòÌ2& Å௬/¥8Ò…á©u¡ÆÚgµÇ¢*y $BA ‹ˆà*Y›ê+wibÕñ‘v—x³žF°« i´T [ 2p%– kL>±ÄûìÇ2‡»6òã=Ê¥2G^B½‰¶Ý‰ÆLß‘FËYßÕ¤hªò«Pµåß;fÄPH:Çvèô8ÀØÃ�eB%m74"ë|Há,ü>Û …ïyRõãâëpOÈx¡â¦‘,z™^ˆšÄU„)Q:cBèFz�V„çÉßú”,qŽ � Qtk@¢¿‘<JóéþÔ-—¿g4ÀÎ'†i£$á>ÊŽ5ÌÖPïÖj ô+=tg…Xiûé/UÔ=ÃÆlB¶ò;®ºV7¿JëÛÔó�8¾>bGB€ß®vÒëÒƒ…ó$a;³\mK…AÓ $yþìAŠY}=t›^6g6¥Ó84ï®¶+Ö¢Þ~–í3PL*¡¦·h�Ç1|�¼åƒ$õ êŒR”-šI¹P¸8Ô3&þ�égŸEâ_Ég7ËI>U«4§vü~äšÄÉ‹áEøñô«¥óÀ±<N—-ïƒ6ó#ÿwþ[!r›v3 J n9­È!ˆíé³_(‰@¢C2# i8mQeˆäшí$°! §zK©ÀÁ¦:Á†òZäÔ^^-øH±ÀŸPØIH|D*�°ÄY\ª:ò?®ßà Uñ«[wrEº�¸5ç_ �°¬nk‚È(¨”—ÔÈ2í| Pº䥞bÔUiƒžû£ ÿ¥ž«Œ½wÎÀ:²?dUXä횀×?ÇqðÅdþÇ*·PJ×ïGI:‰ShAdjTë|7¯%!…›ð.Ul‚øü…´²äè„%.ïÁÉ ¤0õk~Ç›©óÏ¡µÏæØ3™ /Ýåä)0ÔtŽ÷¦ J/-V .÷p¬ÍQðµÅƒ—ZºÜ> (™¢–rÙήå²ÿøòí¬i˜@à�rõÌ Ï[ÊJ·ÖíËÃV‡Á[¬EѰeœÈ¢½‡ Z_]¥�F£Þ-š¼t�™j·_fz[O[Y‰gOBs[éic¡�DWSQý [ž.R²>0 •øá°ÞÌ€Y¨žUž,?O²¾kkV»ªîl3Ÿ¡È7¢ü¬Ï…ù]ç=´Á_3¶§ÍE-\vèúiž9ò3wįä…ÿQLû3lÇ6Ž0 )¦àNÁgkÐû¤Ïï9¨è,Á u]$Ï5@öŒ›²Ôÿb¹A®ªìª¾‘}Õp\¾ýÎ�ûT-wcëpTÓê`‘s%‚ú˜÷c?NÏ<Ù°ïâ*‡VÆî%9Ta™òåC™u´ç]+\‚­0¢ê@ïânÔ”ÓµTdª'ŽÚñ…¬®Þ`ÕmºÂWjvšFc}¢U),V�(°’Š#ÿ‘n+Í70e¬L²ƒK¹ð¹Bå™É“,À¬ì£þÙ¦ù/8¸ÔÝN/Ù»ùM±æÂUµã(¡aiάIs'IŒ®ÞÓYyƒp™œ¥/†IÜð‘‚âЮÖ°²f·Ø—¯Šß+7|zxqà”²�­�C¥Ûì?�* Zþ��è¾b .®:Go à ë Q¯àÕ0ý_+~,�¾•êù䙵ÿÞ­èVm²'¬?³X9¥híVÃKÿÏ'wS+>a«>“VʱÀ›Ýp+F¶ëi_†f_²˜ä÷½,:Æ‹tÀ/–±¿ì©T²¦öñ�»¸¤ShBxÀJU?öÂèíÜ®²i}Xýï‰5þy¼÷Q f(e·ù×ÿA!� (ðPY3çcøY5ŽŒJƒ{±˜ªYõ(Õ⬭ <Tøµ¼R0AàÙ4r%€àCËàùÀ½o"ã1ð±DÜ ®Ä5—Uôº°.µ´î$¾’Љý_‰Á;¹Î >zä´¨6ÛÞ”,FȘyŒX „5`��”ŒÛ{ßÈñ´*Vs%À˜…FHÂ.‹‡%)u·òÛÂ\CýØ ´(µÛÑ·{PõO´?SÞ*a–'ÔØÁ\V­à´~ˆ!5Ó\HwÏXX4Çh}\v… x}vJ5"FËãõ–�vPp’ÑÏè{Ó¸ï½gÓYë&1€ö�V6A”¹ë˜>=ÎÍ"ü:áû(žÚk—4Ô‰ÿ>sùrD¶´I¯pÇ\ðš¾çÔÒX¨] [@©»ÛÔª¿P _ð#z2+�ÒK1N“ñfa¡‰`wÃY>¶êLaº=T×5€Lt�õ.áW¤©sRö–sÙìlÊ¡�@f¡ü3ȧ` >'ñÜ¿•i�§©{BÎü�0ü?©AžBx„ÿfvW.+CsFýLkÑÇ 9Wiz¢ kfð 'tcÐí‚vx4tŒWSêï×}‚`´MÆf'aAd�ÏFu –g~ùÐs9Ã�-Vpe––Õ«4çÚ¹øTwtÿâteó„Z@Úx;AG©Œ‹~Yîb^ '=§Ò¯‰ŠI@‰w]u÷Úi´ñ�fó`û|Ví$j¿˜^-´‹êábGK, "Z™�Ëì¸}·R\³ªÅ^›ø½PcùyÛÕqt™ô�Ð ²;_âpEúÃŒî6=†6ÍDלïßÄ7¹ºj±H|Ý™€»ƒ Bé§´ç Pý¯>E–׺)œ�÷«\™;›ðÄä­ ¢jûqØ/¢sbkæm™BÜ7¦.Xa†¢K2áÙ‹bŸ½Vܱ�ZwzÊyFn®xÈfLð[ò2�rÏø;–/®¶ž”B&ÃRsK¯i‡w JZÐTUï8°ôG¾Ñ5~)ÍböCR¬v0.`º^¤ƒ¶ÈÔ E­ÃÚp¸Ú>³³â¡¤– FnJᾆvBïª2œæÑ-¢€úÜoYИðÌÆ³ ~\j%BJÔRøà–²7?ç· C¶ÿ«¤©S/&ßì~_ÝQ#Y•Z Ó- $Aô "ˆ0H ת èÐýmæ¯òK‡œ =�SSaäì€SÚÔ2ï÷›ïlgejŠÙû+QkÍ”¯o1Q²‰?ËÊû¡`ŒÑÜ7â#´»†n3œ–�’è û4{õù0“¸%v ‘@ÒÀnº|n¶2ßrîä=šˆ¿>ºhÓ$o׺,šRÐR¦;'WŒF†9ÚS70Ÿ®è>2÷”žãëõ ¥½w–¢(Œôb5£�ü«Ï)¨tÍú·þ%tT9ßñ†¼  ]„ ¶;[ߘû ˜pÏ’ùO£žsÇéb,‡äåpÒ¬5 cW„8 ÿñÃT7 Jm>CHÝ ‡f Ë÷ÌT¿Ã65ÒInŠV‡¤”ûS:f`öIA»þ>BìÑ]Sá-6ÿa÷/>ήY— ‘¬$Áf«ç‘ÛO³=«£C³Kü„±Ð`2ö*V¬ÞŠA ¤ ^§3@dÃàžŠ-¶#ö÷+;t:8äÚ0÷¥ C~Ø£Î@aƒ¬ø�qýÛã�É<_(�Z ‡®p²�ºçcAgdDg—ªltqäšñ}5 M¿¸ì4Gõ¸3:%7ʆRúHôýúH±¬ërzèœ#þü\Cç+W!̬ŋ�<>:Öð틤…ó>ìA)ÌÆŠúÐÔvùïðÆm\{(¨±ž+Ñü]5íì±hhLö‚Ÿ †Žþù%ÂÀ®ê‚¿J$AHšéœé!¢ÛŸÍ·0åDˆ„ßÐ2uŸ g)žˆö¨;©ž�,ùª=ƒ³Ÿòî]¯W‡û½ÊûÀ¸K )ù“S*†�ë¿ðð„…ÒN*“Ń=Qž5ÆJR R5XQxï̘H€�vì2n'3”4gã~Y1°Ö‘Ní À¼ tàÙ=/ÁDäÃj—îÅMwQ�%Ô.Iû{j/©À&»-ýCzTT¤…?áÔõFUgÍà;Ÿ¶á-MŒC•ášÑ[~—™nÇ®ïd?¥f"gZCv XJ#²oe�C©ž-Å]u:°§Y ÝW¤PëâcÚ¦X ó-¨Ÿ'ëà žatGÿfZ$»¶i¡UQ¶| TAôYÍOƒÀë>³÷—Äñ€6“5©'Äç�Èô YÛIJ 1€}~Åë _ÎÁ+…�÷,�*ø$µUSp[Ê?áÖ0z µ®4éí@ "sF8¢žÉEïíÛb-1 «£ïùB2'Ç$+Ê4𶯻U³ ¨€úÙã×VùŽÐwZðŽ}* %¶÷£!Âáÿ€U›½A&w¡=7±ÖX\ÅýÁ¤£4Ìúqåš;û&~(ýš1Ð}íBVJƒ#å~PYÝ�‰©H& a‚Bùb 0ênþT—dˆ¤Ç¤µè^°A�iI­NÝT¶� -m8¤Ž”q*›Ž-ŒZöÎ`(˜!, ¢d@ùˆ€r²0®“Ã*„ö)¤³s>%(6�pùÝ.ÉÚBðóÖµèüè˜*Wd_‡i¿¡9¤ÇÄ{‰¯×Hü4 œQöøL­_äï}Œ ï$ã4�«HpvÔHçƒÀÇ�mÜ%Ÿ©ÿJU�¾š[î©RmKJ]î_þ‘ÐuÕ³y}I(í{e tg¥Á�$!âƒT=[ǧ¯H_¼©i ¥13îg•…˜zÚN”aÀÝ�¯Úvà…†œÙËÆÉ®„mŠ”é8¥ÁÆS-!É÷ÇÅ]¥2õepGÜq©Ôª\ÖnI­HÀŸ =lßuÿ•ø¨ò¡·Ég[꨿\{wrÅÌ q�ÖÀ,»ÞTÐî?j Ó_ncb2ƒ¨È‡UUŸƒ$Lÿ¦B/ëJpüòï¼ËˆøRÿ7\& AÝÐT íúIP£²ìÆq¬£{ßpŸ("½ )ËÔò¦Œ¸ƒõHñ�{vMwÙ†ýÞvÏÑaäf_O‹Ç®»5W'�ÛÙÃÃO:¤»¸Y®G¨5VÂ'1¾›Lÿ£�²�ÎÂéé2Ïß·¨ËÐÃÛ 01“°c´<|Oܲ`‰"ˆ©§Ý8ák1,åµ¥4”ìnùx¨mªs=qCÉÛ³¿áèÞÌåŽ~Š:c+†Ù†gPrÉÎþ%^d¿N™Æ]\¾ aŦΈ¡ÃrÄ'Æ�%ÌÙØNRñW±x y°‡ÿ—M‰…ÊE§2€æUÓœå{¯\YÊt€4a ©ðêg:H.�×ÿ4¸«n@éXöI®+a»3À²b¦Ïç�FÙ«-Ûá]U¡¿0cW²h™ïn#‰ÓmDêñäq²ÉÞ8;XøÄb?æGÀTÔtT!:åÀD½<;Xº³÷ ù ö}Œ;ƒ9¶1D¦ºQýû<¨àmØ›M· ¶L½‡Š–ã7N@´H©¨›9ÂÃŒUKòáçG°c%É•µzŒ“’EýÌ+ǽÕÊgŒS?»7"h¼]¡—¯V‚�dyYÓ­Ö*>ñëŽZÞ‚Lwi™&îd€Fy‘ýŸŒ‘,ag=q+û€\W¸ bß·uýv©½VNL>ÑŸ³—¯ÖÍ|óu ‹ŒÉg÷u;´¤yÓ>$IC¡†¼ªTÍ/ÝyžëO¦Œmç´q8ßj�Ð;]›Óià4w{qDhó´ ÔVÉð…— �ñYÖ0dìÎ# �?@úÁ²Ò €ão%„¢{Ñò²¡¥p.´>‡þœÑ$„�s~Ò}@Å=K~_ªôá¼…·è[´$3F—zÙw–,ƒ)ÞÛx§=¬‚x¢Q¢RqJ^£›ïW X6@P`M£/7–�#;‹ŸŸP�DO/r QP±Æ½B f2èyoÓ3Ì¿!Üø|‹÷ÅJÃ…X äÁcS;x.ѼÇÜϱJ¶žT=ˆ;6&™C[e`I`BÛ²Iz’@¥}¾Ðv]´ˆ^ÒÚ~Fús-Wo2ÇaêM´Žæ•­©<«D¥¯Kšª¢üß@H°˜«ÞÇB”;†Gù±èfPCsCÀ2˜[^o];�fGIìë%�j±.dj ±3(¯„º€—™'«ñMÍãtyÆ�S"-Ä4‹­»R™%üÌÛxÕ´‡ HýÆÐA «¦ßfVVT:ˆÝLjöðpß•&¯  ¿Í ]Õæëv¦µJŸ€"¿�—btS�‰ÎWó•�èc´ß0¿³ÞsÛÐü•�YüÈÊtœ˜»½lz³ WM|†Câ¬n6M¼Ó‘ðÆä•u‡q S[g®ÄT½o¢ì±æyb”«_DY#Ÿâ(6ê àdª&DéœLAÁX€ä/ˆ0lœ¾i%ó"SÐÚØ+C-?ý½)TÇí«í©ÆMÖùÈj_ h…yjþØûæê![�àﮋ} vIR;hÍ1}CZmh²»·òÀ°êfš†\½wÁKÎJÔ²p;*¿î²Lõ¥^ì¾opÞæ(ãÙfWÖ#‚㈾ŸýÌþªc·bN=åÀ+HP ¥Ù¾h0‡%ÙÓŽ]x”‹Lù{û­ÊŒûZÌã˜Q0¯:ø¯á $cI¨ìãN\ˆ�#;9I˜x‹†79…»�ÊU%ÅØÌŒRÃlânŠ“z™î6 O7ɯý#Vß�²�G—Ï{}†¹qûA¡…á¯`b áR–�BQß�Ó“ãbG_—pâªx´�þõá`U'þŸ~¶ÒdY°”—KX,¥‹€ÿWüû#¹'aÏ9 iÈŒ†œ$ÐRõ ­§ó~Zéî]ÒÀÖPÒ82ŸžEtÆ7o|wÌíuÕ¨–¨¿¨oÝ65yÀ*w/Y˜BÈ�ÐX·‡1:÷‡þ£”žuýWÉ@Èg2‘)oËR/!GÒÒµÎfþ�\†;ü£§–³£Ïô­2pä'P ü\;=Ðû�Ñku„Bµ§½%E÷„pi<ªQ•ÏëØ½Ÿù7¸�þý ËŒu[¦^÷x*w×”P“w¸|H‚ùPŒ„©e«Pds·š@ýýÙôE µ²xßÜ%I=?I€~ÐJ?Ù¿aâµôŠ(¸«ÉEþîºÿ¤þéùFù<†D”��ÏôZaoxöiHC饔ŸÉ‚ wWïþyÌ ~*÷F€-i¡^¤š¾ôæ¨î?‰¥ÉG�¾xœ0ê³K–zºc%œ`cðÿSºßïObKqìÑ0¾àÓ݈ÑÓ‚ÜÚ¹§ l޽œNÐ]Ž*å þŸ¯¹±§ðªæTj�”LQ+�æ-¦â¤2n>eHãhX ŸëvuI æ£Í8g«ªdcI/¯Ú2?ší¢£§œâ~ÞãéÛǧþÁǾʉOv)9+ø]8û°G--†zïמþ"n¡•UnŸ]ÓaÁ§€ÈS᜞cjGÿ¹cßÕe`ò ¿Àk§B£WÅ`Þò$NT Í<][¦Õžqò÷á¨,ÅæÎžI’MIä&éš_$iiúøi‹Ð¯à<·–"ÊÐôm`îŸöÌSÁ�‘!I{ÀcM<v•U!–.í³ðÐR ·ÿJß¾0 NX¯}6V5WK4��7¨~ë׫”lßÌ==“&VþhJQ€A€Þ¼µ €F¸9šñL5ç;Ég£U9S“C³um™�hSØ‚½[ÌÕ‰ôö dù}ib;Éhæ»LÚL¤Ë˜‚ŽÒÕ/W`uˆÕ&èCÖèS„{蠉 ·9Çf¡ÌÖÚæ< ¡ÚýwówXpÒÙœBã[š�#¨–)®oô}Ù#Ê_7Uu–Ò8sKß´ÒÍTHdím­ð÷�NU¶6Náõ;ú&ð”4áΙ+þ„”׳®Û`˜î.ƒ>8’M-ÿ,Zx™]4ò¦ØðéSÌp‚µ³*ÇL‘ì®×nìðÀÊååˆÀ‰tßY[ù+ÕÄÈý¾0æ\QÕ«<@vÉÏzäðIöh›‰�ÖŒ¡Z�®mß·J�ù+|¢T)PÜÃ|íË»^ &Ì?ƒq°„1¹ \/v‰ñÓF|-‚§ºßàbXiåöuçGîgŽVbÂùÑêJ´‹ØÃ!>A‘ÈÂì ·ŽÙb»¤÷K‹�6µHN¶öGj ~èD M�ø¬«þÀðÁ7¢›}IøàJû¤«ãˆï;Pe:5%ouÔ�Pß³jØ¥¿>)8ŸV°7ÍÒ(:bSc ‘‹`ÑL>Ã�!ýêŒ2åhr÷N$bçÔˆÚõ/©¦ 7!Þùר€®Àèšô‚% ïrÎ rŧž8ð¹�:{ÕŠ‚�‚ÝtèÍKTzÈ}˜íRÿ%óÞ€¿¿áîÊ+ —ER=¿½IVMÞr¡gvdæã; 4„’ï rêd�H !kÕüzØòó=]JO}æ­}Ú® ¾öQß íøRPº¡h­fÝ·)# ô˜€±&qür_‡yâgˆODŒu ó¸hí÷{Þø 7øæÑ‰ô¦c¨–Dm‹³†í¤Œœ ‹OûË ¨ooËzéîX'Æå,7ÒïÞ †õKh ɯš1×ÏD› ˆ¦4ð×M·_²r[¥Âä µýz>»‹ç~|!ÅO`¹G€µAšeI¨Ah™L!ÿþ9®Úd¶ `#$•ÕAFW?Íw@H?¾¨žmcgZ¾TÖ-ÖÆ¬ðb5ÒtÕ'ÑᎡà ÙA061žFÞ�‹/7TLs¤…Ü4¨ÅÇpîˆî_£©ÞôýyÃK½»¶ÈÒu ^3*¤DnHÚG׉YÒÏëÓfÙÞ?Œª_V–©à!sÍZ�.å÷êÞ áoª Œ|<Øœ‹¨q¿.P,è¬ì: „ûÞ;ìë†k¯ì ¶xÖõåÓC×S@r)@CiÈ"ÁŸ&õ÷�F`ïùX0†®K¼±ÚõŒÞÇ•gßn}SÇ–ùH<“ОSÅô¡\»½žM5»­²ž}±X.šÞ˜U±2N÷aAUf²A{k®¢ÛZ×¾–¨æÇîe>_5¬â¾/�g<Ã� kkqxB¸h.À4oì„ÕêÚ­ã�¤!eè®ÂûsãúÙò�jnQº IL¼ÊzâºG>Žß«z ì×ÁtôŒ7r¿x™.AÃ÷ú\mãšõƒÍÓÞ¶¤bŸ§ŸLà¼@Z#Žü†É£½Y«ñ䩆=–<´TbXD`X]Æ�žá©¼ ' µâ•&±™»úv=a”ƒ^²¢ ŸÁ†W!Ýñ¼0“°Q9ëÍ]ª¬½�ßGLTOæÄ5ÂúU¤¸¢Y§ã”‹…>KÛOÈÕÎØù€©™Š½ò^!`xÐùF!$Ø.†Åÿeu h€[z’B‰É’£€B&úç¥#VØ:ŽùšÍòÞMe?¦ã9lj?Tò&T}GãÐÿr£VÊ�Ъ}tq¹w[:Í6>e«|FúƒU«ÒŽüÚŒ¤yQˆ”Ý•Moãwh;]PaH|ج¹�¡á=Ã0ó@R¢‰Ï^Å_.ôCޤÎÑ(.œêüÓûP˜³žC„sAR¹+5ΗN�uœ—¡cô;BO͉_E ‰Úÿ¼OgðÜ­¶žg×b{ˆ¯n�Oh½fÞ™+­‚ô¬€A‘~é\h?õ1VÔ Û{š€GFu†Ý¢ÀdgÜ"Ÿ›°+ø#spò„Ùà“ÕÞñ (Ò¿îb˜‰½ÆÀëRâ–€�?ý2[À§…)¹Dô —+>‹woÐ5ËÞ%¸È†n—÷p9c¶†¥Rxnø›§ØÃÒ}RóN F/Tº8hÒÖ·¶ET –tŸ4ú�ú4]†×âËãÀí'Ó�ƒ;ÕfÝSûÜåTá·!†X¥fYˆ*µ¾ˆ É�åa,€ËRŽœp'.T, üň¥THA3ï˜é\©ë¯½¤‡¬HŠR½€ÄýV}›Lð;):Ø¥{ø¦Ê#‰*š,¤9«§pÐÏndm¼¦R~Eü- =ò5sÑ…�«ê\Àß|ó¶CdèO%¯JVW¥fu㘒´t´¤Û9~+»‚ñwÂú«“À/zô fvl›ÏC¬q/qâ Ø°„GWÐM¨tG¼ÒWOrq[µ•3žZAþ¤{p^rôZ—ì3p©ÌwÎÃY’ó_«Z ­†¼àÎãè%ÂX…@‹ó­ì�)×™cæèÏŽñásNGva>Ú‡F8 :¥ ½"u# ÎU½@2D¬WzŸúÒÈ»…õÖÕÓÌzü'Í/Y7ñy°çŸzâ0•™t7ñû z—x`¨wœŸ]–rtx€{°Ðãmú£*odD‡„eqÇ‚Wš=j‚ r”deœ©÷ðƒ‚oà‚—S˜˜Bcöl;$MbÚ~�e}” &§žë»¦Y¬&¿w+ú œz  ªh¡ßn�üö{ÏÕl0€!l RåÕ¹ÄBD-˜®ô„4¡·‘ÂCaEñ µåê*þQ/BFåÝsî�¬àQĽí¬Èw²Àð‚ñۊìëÀišhÅ×UJ‡�cF¹Nôȉ‡Ðö…(a÷±K,ž É”)rfr¼_~;“â/J6Aû7ÖJÖ!L‚…yj ~³¾<[+<®eÜdOãµ³^…Apmp_Ø0)öÅ-Âô‚ …ܷ޾ò[ÝéóûQ˜¶_ªaŠS( »‚›ú7�4iä…‚™“µ·•Áè^–:i´v¦˜6Ÿ»r«yßÉGòç&BCÈ›*ÉÉ è– �õ†¦À‡–Ί¡d; iêõÑ(§K#ÿQ ¦¬õF rS žËèZÔFš\Ú&jp»õàßè¯-B�˜Ž¿nãüÚa^Lú`òÍ�<Ĭ9‡TF\ó¤yáR*PËúÑC–ó®÷ÀÅÎà¾gÍŒ¥üŸV’ªñ@g»§`üºJ*s¢ÎàÕ­©ü¬b�¡@Å¿­\—#Su½�eá.¯ªCþ-$»~ãs÷ù�ÀA÷êð¯_$”–x«mÌ”°Þ,OŠ_ÜÖÌÑ›äE(K—z¦ä•ë„D~Ѐ;w��ˆ÷“¤Küqr~ }7•Ê0øwÍýïÄKZ¿/Ó‚“¦µ¿<`4Šxù“® ÿëu@Ñ$Aš‰Mu£ÓE”i¦¼‰ZÁJ‰­Óî `Vvµx²]þ�oº>†|ÚS›²McèIÛ5¬FFm.j¦ô”LR¸ç–Ïó+m×øc‘?òâxXÍsõÈpȪ4ÂlP=7žÉ&øÒXè¬ÃË2´pXãµ.àDi0?îJª@*bµêÄ^“„ÍŽf‹°�ejmœv/[5ˆÚ¸ß<}»—.gö¡Ð«ð—bh²tk™Éjªù1e{ª~/�ó–àóç‚ÉØº8@z|zÄœCm°‰Êj“ç Œ ƒµ%Êôþyíeœ›_ÏóÃP>¬¤ÝÔ~|ñß¹÷ EH¹î*ca‡gdæ„úQØþ Æ|ƒ7Vm>A”÷ju„€Dêß?wkª˜P䌰Ó-ü Ä׸¨‰Z1ä�IÚ`R’µA‡§Iz#¨Ó{ö6TIL¥_ÙSN Ì5sÔmZ’ÁˆœvŸÞª Å—&ÕJ“Üñ5B?†.Y´�}M˜OÕ>%‹cºI¥¦,è±wà²Ãj;5ã’� r~¤6ömeÆË‰Ay®õß÷Iu¨”a¾àÔ[p³ögÔ‚l½¿Œ„t¯:áK¨ò·‹wPM5‰¢qo^‹ ôƒð2'Zž2Ÿ_Egvn“ÿàdÊÈJbwƒ?\�}ž0~Oæ& ¯Vÿ@|U®/æiaš0'… re³ÏN¡�áùæÜ‹“ÝC7Õ_£ˆ)ëi5ÀJgYÀ�Î_´^/X!ÅqTr¦u•Ð$oGäîŒ.(·˜%^óæB&*Ùá �›2±_q¯7Éd¾€¼‰H{©%ÓÇMË¥˜t‘ aÊCP‹[°Qi¦¾— )yl ޳f“ßó­^¦= Â…™®y›‹ @5°~}Ÿ¸ØuˆórälžlÐè” �.ê¶Øžçè�‡¨^’«IåüådBgiû*x]àå°z¶£…Uû›�ÌdŸùÛ=l X»b´ýAÚQ‡ D© ~õÄ$�®�¥už 8�Ö· � ¿’Z8DµÌ:Ô6ˆððœO€ý Ì7a¿ó³>4$hN7†”7=^Âð!8µl€¦±†ÄJó’¿Ö×\ÓGñ§Vh|™àƒ·8?‰ÐsX²Â>EÄkíäûD,n�*“èa½ÏǾ›öÝÒÁ†›QÇ��·#õû.ƒÐÛfŽ…WÌLA“tY 2{©¸D%ö[±à7"çŽT_N¥/ᬌ‹ò­oI$ó´‘Á@ŠZr/x*&éMa¹+1$ \�éìMÏŠ.Ì0aùÆÕÔ$f&Ú(mÁÿ„ˆ6«îH}×Þd¦Í6Ò5ÇJ¥Ë)ƒDÿH†Îw[‘¨úŠŠB—}6ç[ü½>y©oèÄÝlke·óº“Šcf”-•"2Ò"ÕŒ6�ÝÆžŸðÓÛ›_�õ~Š4LàokHxÅ_>¬å‰L'@k)À`¤-��œÛêêùÝáâ`TØà[ø;Eꢇ%úƈùýCh$»HÔ~ro@¸‘râ,)æÀÌSzŒ©HúoäiÕ^ZD8âJ�)i„¸w]`Õÿ¤Ó[¶ýˆÌ[qqÌ|Û²2+x±¡W]O4QÇ€ ° ÓKV®]•Q‘¾ö�Hü&ìÔ®8ŽïÚòÖ|úçÇ«-FE’eù½·öN—Ð_IDà‹ÇFàÔÜ6Þ”zü ׄh¤’á÷]ÁH§qï?U�}¡’úãçéoÓ=¾1ÑÎ@ÚFI7°â·AúÍ¥f›Ã¿ eÁˆµG9ïãîG#²-ó%˜µ¬‘5&W`æT(Õ8�_PÔk ó úñ·ÕéËŸ³Ñæ^.n˜!^—ÑàÖGj:T‰ûNi]�IzÉí¢—kG+6œqSþŸgÿõªÛÇxZýÄ,ý¶—h |:ºÔ77 {m±]§:%Ïå¹î#ƒábÌP ßô‹R–L‚¢%ïtr_òÂ]¶ �€ÔqºXa>¡ÀÅ=}1. §í3óMŽ$y5ÿ})ö(Ôß!Bpi~æìQzT/ÊD§=æ}ôû $äK€Eª-9jŽ àî³ õXŸ³»å9>ÌóÈ:Ì-„²G&3Nè@Ù‡lhÜßÃEÿÅ@&¤ÔS×¾ÉpÆ ¦PÌ>¶CÓ ©ÏÁ×"y½ÛRÂíÀW1z®&2ä”ÍyÎe£‚§,'çF `Âk‘pY¹œn7lvøvR^40IIJ³í”U‰¡›Y«¸jãt|1åIGRKÐÌ}k3&h)qÄE×¶rш\½�mi¬ƒipNÉ:²ñÎÞè™Öâý±Æ 5¸xfäɇ¨·ë…xX°5ЖØ½b¶hÔI°ßŸ™"-zÌU¹#Õ -P®¹•D¹�]ëB¡"ÿl°zè»…h <¥Zêó£8ÒÁB=‘»ýn¦ åµ5RXŽx�·cóÞÖ;d�¶L$Æ•sö°óêäK¶ë÷Üí�MÔ¸¸M­ä`ÜQŠJ�I>ÜU�J €R{|É-/‘œéŠ!ÔØˆd‹Úœ�ãj¾2ͲÖò|ܳ6ü|»pHìèX_é‰Áû'¼ñ2¨Ç™óËÖë¥)ÓÅ•~(÷¦áN¢Ë’*lkж÷(ry!£Þ±Ü•üêÅJLKCi Ñ%*¿½ëPÃ@¯®ð±„@˜à}Ùçj{ ØÆcùÊTã8{�Æ[~¬/¼sº_‰†¾ËÁa¿¡ÿÌVÄz¦DY&¬\�©¨Jê'Üdd´À„ùÌÍŸG œleÒÅÈêt^–þ÷Ù ]àzœÎίsNŸ}Ù+ì«@ŸC„¼A�ñ ~(4Jèg݉¬ñÜß‹šDnÊtvþH0> ‘Õ(enËy­¾ÃëÍD¿øØ>F˜�È%Ëc_­>ÞÙšfVT‡ÉÖßžz^—Å'½ˆ�:iŽÒ…‰ÙéGà‹ÿLjƓUF¦Që{wY¡*ê¿êÓaì;‡Ì{M ËvšŽ}VÀÎ¼à‡°ø"ükaéI4›Š™¶¹õ¯¬•²f?T„Î>ë#º"|§)Ã0CNTw¡¥Þ£Ö rÍ>~¢Z³Ê(îê^ÓÈJ³¿†Ðõ)î‚ØoyÜ´®÷‹tˆvÑ�ýQû.±XâÑt朅‰wE¾Ìaó÷õ.ÝÉ™õÙwt}êkfˆ‰T1—àÝ@ö×¶¼¯ÖÖ(¼áÚÁE'6Ô"ÏI…ü áöý…ɪ¾ˆÀe+÷,Ž û›À>:ÐÐ^ZÀ5¥kRK²v{;ÜÚQÉPÿ:7^L Ô ƒL@S!bÌ1¹‘W?ã—04h)*Í£|zu�)çPò¼ûle§U³ÿ‡³Þ4œ5èDVÁWÅ·â�î¬2ŽÌL[ö`”;û†õÙ%|ÿæöq¦?Ϙw:¨'îÉÝULéïêé¡‘—0ÐÉ?À!i,Mlcß—ê �LÛÇšÝB ¾u…ÑDH›±?óu4·Í×—vª­Q+ôX²°+Ý�¹¿eÃÎÀ"–TF•%c”?{¹¢U(›ç9yá7WßÐ/"îŸ}¢Ö™sÜgW½$Áþ·E.’ðÈZh*Vj\¶Ìt mÂz ö„ü”5›ÉâG‘E=ššsÑOpœ"AaO�&qK¸ ƒÇµ{ô%ý‚p¬ãsÀùB)Z«D+ÙZ¬§m¼k »žvø‰±±�ú ‰ßÏ· þ‰'‘k?¾µæÔf8¨ÑvQªÈÏ×Ä\"ÇJvBD¸%¾CE6ò˪ #$•wFÙÇÍyVí=út"ÎŒÅßPÚ/¼ZXẉÆT˹§¿VÈP$®ç ºÛîH° —åÀýcÓÝ^«ÐÅ›µÍÕÙbàN7Ðy†àS2Ú˜·´(å¦òP Ðhœ8úbc”_äÀ«š&jË=vÂŒtƒê=* 9«mwöò$œ“0òÁ0½²šW �Î0:ú6ôŸ´ìRŽƒˆûé…"×P)Ý“¡'‚n-ê�c�”YaঠF»³ß[Wʼ¡µH+ã¯løÍ#¾aOÚ]F·T+Œl•(oû T Z7Ðݳ¤p+0’½p¸ÍS™ `Ôš’iîÁc·™ÜÖx:íнYÏa-R�Ç{€ÆÂð”Yÿÿö©·ìÿ`º oMûÆ]7¢¤[¢õŒòuî/’ŸÃ^WEP}›éˆƒ·˜ªÉûmv× s.Ô¿ 7¾“Uå!‰zãÈÙÉë5ZwS¦Z‰­ÿ–#jò•Ù¾r\Q;"ѧŒB§N°.·×üHIMˆGÄã–_0‡2ÁÜ(÷´ÒÉrÕÆE[¸¸þ'ßÎןa-�K.5Uÿ¯<"›ƒ®JĨP÷JÜu`Rš[ �—.û*Ú€£ªo2¥2òª†^å¨Sn)]§â7mãò®�•špâqsæ-9²hX;˱-ÃUoG«$�²—Æâ±ÔAò•‰õkÐùЧ•-ó×c†P0Ý*~-z é ± Hʪ{£h„š;nöÒò' ¯Ûrû™í¿Â¸ô&LÉf­(ŽíÊøk“Ǩ3<¾Î§ªx¤—ÁJ/#ÃsŠ×|!µ‘ež5Ëö>ú(æVèTj)»vn�™¿Öh+ƶ§ž2¢îmJ½Dñå]¼n‘É5ˆª?"&ú/oš¿ê<Ø÷£¥Áà³hÁø˜ ëÒ0C… ÷ad»™o ÏÌo* 7Å¥S´È³¡•®$©Ðx‚«‹U‹TlL~SÖºÁ\e¼îöá.“¨iÈ.q–@µÎUïuC‡>Ç)Ü)…¿³“Ë[zœýëµ$ §Üä¹ÃtT²…Íí·.ÕMbTLb å-‚äo.ûY’½ÅmÓÊ2üù Ì‹b¿ßýàkh¨Ò0ñ¸ÕWâìYÃú1}ò‚Leæb,…y‘eM :Üjªž€ièäô¡QsÇE“óúvË“1?($‚ï ÉÉkv»~.Ÿd¢H© +²¤ìë{Ë Wùeð9Ûû2rÃ6áÒ“ó.�D&ŒÃ.¦¡?PZaòº­Á•JØt?M WNdÀPäó ç¬Rö 1±�x¡š”£rθ²Cú7†"Œ�q Ÿ•Ù¨ÏIgÜ«å/“‰ Ò?²ø}Á´«;LWñë0ä‚*ªT4­O#¸ÀŠHE3K+ú'©WAI­F[hÄÇ`Dª•ТL›¨y™C@¶Uç�gÁäçÂ×,G;%M˜ïòÌ4Ò¨Ïà œþƒÊïÙ™F2u¸'ðd#iÀê˜+7²¹çÍ>,¨J‚;fyŽQŸÿ9aûþ¡Œ{qñ�1}Ï|¥8€ÖJ(À‰8ø˜r°°!–N(h�Q;EtõwrŒÔ‚:¡‘·�;n‡ðj†îûg®÷:à ‡v�4�'®?eëíç™ Ha¨ï84^€›&Øk‹Á:¥ˆéWX9•¡yJ�sÎù*“ggo0è 6‡[èn �4HZ­ö1ŸnwËLÑw˜{£éœ@H|è÷¼>n¦f?„àp7Æ p®ïhxó•Ñ5 ™%!£ªR޴ǯ·p&Ò*QÕðY�EÜo) §.?<øJ³Z¨š#\;‚ÐÑå±ÙwMólí'fÊ)p:×hGdifÜÔ÷ôݵåËÁ, Ðû¨ÏÛbÃky¦WshæÏ ¯O±É6T²„ŒRñCGäwýÑ˱¨€Üø8¬n8¼åê°nÛ›�0ìÛèZ oàœZÉ(T®ª2•´‡ =W\Ì À2䘭N›²� ÷»ñÒ´Cê 'üç&‹½\Srœ´Nû©3æš�ÙxZ�ñÖÐ?k1€OŒ„PdôG¢|N-øÝׄÊr(vQ±fÀKx %Fv-¸¡t¾ÄÎLÒô.ièРÃÐ6ÏyvE4ƒï]ª“{÷=–d•¢|oYê ,ˆTh+ºÒøF¯"ôbi@ ÄŽ%ÃÃLØ+†¬ Y´Ñq¶äùíÁà•1a5ìûxQGö`nQNÑcöé%AˆÑ3-¥„á´¾)À²ˆ±J‡¹G/ó BW/úôÐÆŽdû>µ‰ŽqŽFKÍà°\û1$†�“m¶à!í`sü‚ª£ñ_&[c¤>"™ó[Ãü®½Kw6m|„.µOsßð¦1èú¢=Ao€Ú†cÌ­\ ‚1¸« aBß ·¾ÿˆ2ç,[í*Oh¨]+ú·UÕï÷tèXÝ�kIå¢\W¦f<7rqee�5”jUÑÈÏC_"ÕÕFA˜Ž/cH¼W!ñD¹ ÇÓ¬âhI^Gx§k0!Ó.§ïþF„1ù}²ºé3ѯþKÈÚµ9bä&Yú¬|÷4×Qà �ÄUQ•IÇpoŽ�Tërð_­BkòuÝup¯~hÌÅóî"ävŠÖ­®è‹—TBÆxW 7Ž,gžÛ¡ò¼/yÚåè¤�ÿÎr i2öÕ‚åßï/@QSVIŒ_'ЧY͇m —é‡ÅŽ_ãWF\ñ�²ÃSVã¡y,ðW%ún€.°t¾©’6< ìuÕŽP—ûíÏ·±Ö¬>@ÌMl1K@‡Å7…#C(7>иGï`™Àˆƒàœó`놾㨥¡…³V߉o²Â)ÞÂifeŒczÛÞ³k4Ø$q9F4«['÷Ïå©]j Ò�‡®ZwÓukĶ ŠÝäãLTcCA:QÛÅKÕ¶R‰´ž JÙ®ôJ7iÉŸ5`‹4·^´æ×ã[ôHñªG§LMÎÕ¬uJz|0untvE·èYQ½l°ÖÏ‹ }±SHlt¢€`jaI·‰·sέ/8, i0ιöuûˆäœŒËCØ¡Ù;NàÓÿɰ³4¥Úý°½Øy�‹Múïh“µC¤üsã¹²$=%üµ Ò´^í±è»`Q•`¥Àñ°øÀ…WÅBßtÞGBÖîðÞ‹ß’,§ÎƘ-|x D£ž{íÝþ”S,Y¯XrP¤s&ë ðæ«¡zpÌÓJÊö`ÂG™½Ö°×Ó; z¶zÛâ|Þä•ûƇÐE�·k%>Y/OÍ”ñi›ºê/ïì~¹¾"ü‚‹è‹v¿øIVã&›¸Þ jß�­ê\sÐ~ ˆ®jÏô@߃›Ólžãü ôY ÝÇÏžÕª»ECémS ÙϤGMvR#*NCzûû‚qè< ·Ê@I .w\é¡&+üŒN줺’Ô?,ï•£kÑqu€w§vaë] Zï°ŸªÔÕä»bäù6Z«\ _z(n:7eƒØÑ#L EI›WGaµï”Û…&š4‘.m‘mPEÇ­ðýü\ £´w¶å8ЂN»Uƒ])üÛ*4Ø¢¡žaM(rÑôT¯d?x�Kþ'wþ.P©QÌ«^•{R#ì¸ÚH¶7Ç¢•õ[S_p½2ŽÍc§b»Tóƒ4·3o¦8^LˆØ&§°cd6ŒæÂ0‚#ÄÓ,oü«ž&×ŧ¸<3¥c׬þ ‚�ÿgY‹ò�ǬÄbƒXßíÅNÈÖ½h8ˆž“ÊM6šp�ˆ!PpÂÌj05‘•ÌÔ$ì��ǦS–«P[žöI1ËlÚ�ÅœS‹ÃN²R>ËìÁD/ENCËGóšòt,º ¬¡É3°à'#žÉŸ¦ßN²  È51`É8̦Ó�Y¶ 6ÝsþÏ?åhP"ýjmCa†\j%q* Ú“;-³ Ý1Y¾rÁÆû¬v樷ü­ˆ¹ù?‡o·4e'óiù]˜>¥þ³�P/èöãßýŸ_£R�á“üTì•æüWðVygr´úZŸiºÌ¢¹üШ™·“¤#íÕlp}!_ l<—Kèã ð KzN`siß'Â.ð,uEù{ _ÍW/¥&bEÈ%ƒ´‘!€˜÷iþÇÏ›Ýʉµ(b>]ÆÖl(;”»h=êÖÆ� ²2H$‚Êkw’»s¼Ôb,!pƒÎ äp(Ô!¾ú¿‘ªBÙÌÍJx¶æ"R/ Ø>ÓR–K<“Ó)'`ܬ]d&ÔžçÔÔÝ«ÑrFËQ.Wzá•~Q8¾µè ªžT‰Á£¥ÇNcÆ¿ÿ|`ÖjBrKÉ“Z¯Fb¸ùbÆÞÙ�ïzýÁnW畵ÝTß}:´šV•† gCWÚz€’1~".÷LwË¿RBÅTÍÛ€L{y,­-y¯Y¯”=ÿÜìÌ›à`8&éVÕz\¥Ÿ¨±¯gôHß�»ëm‹†o36œoGy¬�ðŽÇÇ$l 5Í>Ò �[š‡Èn8˜áÒ·Íçj�ħwKI!žÚeжÍ3 Ÿ|Âήª½šœ¥z, $Uƒ\!—Üʆµû?�\ÒÝ�œt§€9a÷0;W|5Šudoäçˆæ¨…$© )ÛC”<3-¢Àé@+�ÀnÇõ/¤„JÑE~fìHé²½›Ðº¦RXüÝúTÕnC]m�"0š*}ž�D« +×÷µŸ>‹ÖÖwçÖ!›¯æzªx¾ ƒ³== ´N­v�­Ÿ5™ ~éo®W Kò^#b}ÕÅÓPe¹(‡ØPð𠫎쿹lµ×UŽ€Ž'�CSÙ�åÉ[Œ’›ýf•�ïaŽÝc)_Ê ;gËá�Wá<2ÿµ Ñ~x[Ib­CohAl;û}Ö#“0kœ–ÞÅ|aOkNu¬lFÞ1‹±q_&%¶åÜ`©µüsˆA’ö&�Ît�:}ÿþ¾,�‚¿/fiîǧX,`¡=ž^vÊ´ˆdÚr4l@Õ:¿:bBkʤ3ÌÊY9ùˆŒ1øØ®¿»+ð`°CL ÓÒ]7ó* ˜`곌e/°¤xÓèÈ˵dÍ…­^4Òòî‚¿èH¡�…ûyäû½Ç- ¶É𝮼ìÇw¦�>,/9Š+›½è%…âÂê•€ׇ�S2ñºrÇ㨸B€¦ìƒ{kÖ 4ì ×»_p-V†ô·í•g1¹± ^p“CöóQ¶[LÁï(®dχþ &�xlõtç]ê^H=TüŒ,T`v¬&�¨týŸ¦öjz„Œ?yV¥®$A[#¦“ôáÇÉgp÷ zmk<¤™þŽŽg‡«Jü©v6èkr‡)á!¶®"-¸6ƒp¦á:6߃@Ór&�:UtÙ½»hÊŸj’í´4Ù‚õU¨õ À® E“ÙÖ·iûLeÓ5-RTŒeÚaZr‘ey|vÕ )ªÉI÷ÕÚRªF™‹¢>o÷›’É„™B„OQ" ç4A7PK|7'õ­å#üüF˜q®*w)Ý€ãú/)U5È\\Ù_c73ŠJXù¢˜—³ÐσÝ�(©ÁÏúù„ß cN¡Uh«¹b”\1Ò“ûw›�\* Y%0˜`­#rJÍXÙ8ou/�ðã8Õ,+()Zö“¬&è—&b¿žn¤Èôp`Ô?ôÕ7€úøvác–D4¡ qm}Qf©›�?R Ü®;¦ïb D¨B1’=rx&¶Ûô– `zU2Ü;íòcCçUx# mïy©—å‹Ú8)«Ê÷�`v3’Žzezˆ ÙÞ? bæz £E e²¼a©$j£Þ±½SoêÀAµùœ©n#Tâ ¤O9·èGÕ×åÔÏ#ˆöǹ㪔Œù*”Nî)‰Ôµ¢Üqﲨ#_äÚ~z8ÐenUZŸ&›Fš§üCCºæ ¬ßŒ¶€Ðšlý ƒƒƒÝ_NZÍ$Ç<æ10Nã(3CB¿¹È•ª wÌ* ƒZDüèŸ�È’K>~$§F!…I’CÎõ �8B� o’ʲòÍ&…Ë í/·ÿiy„�§Rõý®€¨mùS ¶P?<¨/ÎP·ØˆÐãl vÂQ’,-½»DÀû¾OÊ?LùKè-ôI.û+”rî›ù'ß�Z|S…#©}Èz—£:kxÜÀÃ׿îðŽt9“~1âm¼Ê‚ìŸ'nIÞôâž-7;´Õ• A/z.ø2…c<5­Y”T�)ä`å0?}Ý)'¼|7Œu5"!|{¥ñì�J€•)AÁE'-¨kVVÐ*L�s~¾àxmŸA4;_̧AhµÎJ Znsåå^Š•*U-˜lîWjV[Á|Ž"ï°êÞóY«�:dÛÜ'ðÇPÁ, |}¤#� ï–Ëm^a°þ/ ¶câ#¸Ýã}Š„Ÿò¥Þ°jŽïôr®Ãʵçoœ2*ÔI [´Ø_ó½N«ÜUõNª?²°©„Å}”º†›Tc>ã)ó7ahu‡,ß<Ä�ü|óØßá�a�à/%e±têòì"?[œcžS§\OV™¾Á*Y"fÄHxfcãâ§j;½&þ—�»]å ¥@ Ù9©V'þÇ'XcÈ'ýÚõòÓFóS t°×d >]Ã÷øCRºœEZ3ŒùDu ×5Oø{l©$m—+¼iúîf_ûŽ·�Zɼ`4¨�¶Sx•¨¢`ÉÍ\�DmŽ�‘7 ةģP�—Þf× ÞDÿ¡ãFI£ez¹î¶t7º„#‹¶(û_l�ðÞb’>Tù˜C»pÎ~h¹{´q%\Lí»8(XDõ=�Y••¾;“áxÖøúœ1ØOU6Ôò þÓNœ–-¡W=³p2�áäñ\â®—™ë[ Á ö.Øf5Û4”^Ý¥Q¾õÑA¬0 qc9ÛæîÂ{>«íÚ†f“ øå2eâ<éU5ã aklé¥Ä¿r^\€ß�Ù˜ÐyBQ ͵o\~+—*Ä‹Yk±c¢¥ìÚ¼� ¢r`£Ý04ÇÌ£�4QøL/õ`I¤ç{¡\ój9æËÖ”œÅªós|Úû»T¸d«ý-"�BD³–Ù.ñÚÅaP{+Ü'Îà`šŸ;qÒäÖ¥6Nž¤õ¦ä÷L\<¾ÉD`cøÂ~ °%wv?Чm¥<Ѭ~³ øÇ²™¾G‘^uÛM;Ó\Ý úg¦JÀ­…µ©î“æ÷‰¤%0¥4™%½F—¤f­máÇXñ…ðU¨›´ /ç]Iý£ªÐ�°ÉCùˆ*}?]¾GýF4näà=möYH':âCG‡~â‹.iD¡éqÑ[›á];^mÕ.Å™Šäãi'˜Ègk£Ý�hñËqÐ)¥©E£¨ªì/�$¬&Ûäs_öbÖoÞÄLIT¯Ó½4r?•Ýø?Ó/2¾jW+Ó±¸ÖíŒ\}kŸ¼Âz £çŸ1ÝõtPç’0ï:¼î¿°vŽØÇ³˜ÃWÆ-Q“UO|ú¬h"æ°¢MoÝ‚Êð œI*ªe}Ãi” ¤!Üï`õ, qøÿ >.rëfwtmÜrúæ©Þ~VÖ(É'¶cˆýö¼Wé„ç×öÝCmºy—uˆÄ|;ºS™æäÞ1„ÏS=_mxS�ìU’|-ùÚL�ÄJSÖ ^™2 v# óß`<¬»�2.3JBëj-µãSíaœ‹‚O ü˸�Œ«µŸé9@S±'Üc.ëóÿýÌ|ÜU’öí¬qãê«Vµ/“´Ž?�~Œq›÷è= [dG,génùȽ}Ê™5š¶Þ°ïb›‡e@ FsÂtÓ±äÌ…5÷nš.Ðýˆ 'Hy!�ÅN{Zè¤ó«9Õj�ª¼ Íø»†.¥¬#`E Í«ËJ„ZpBI˜oïÓ2tõL°D7J“.8¯žÆiÿ‡cèÑ5æN¤KŽ{V¼fìm¡4ä€\UC÷ 7=aD¤/¯R÷{²ÔMY4üd`O§Úò°oümX„£±Å t™ÃóN¼µa¼oEn^/Åuµs÷z?ÔY¸ˆ�±—꾂‡…ãnšùa%ák5õÀæ¸!½¹žÁþ‘ÔFvŠÑÿ9XaøcîÀÜêêCc éBîÔ§¹ünRw^©d¹¹¿ä°Ý‘ĸ²dUB»’=Z)9óµs:gðÙ‹‰(ô›Gµâ”L‰èz& SÎo5¬?lÎ?d¬i‘”kº€ 9’&nUî…9쌮ö?ŸÞÆûŽø1oõã¾ίåúZýñ"ÿ®¿”�…œ©ð÷šþpk5KTûÛ¾m穚“E*Ùt¦ñq ÙIƒè}î”>¬ì&;Ë3hÃ^y„mÎ#õ;¥ävs"WjÙ… þPCë% ¤eø7ÇVN�ý» M޳àê®M9ÿ}xZ C¨ ™ Ž“#hžœ��·�ÿ$m5î/ #¬×AàèöÕI'ëp�ÄV… b&sŸ²aMuŠÑwެc ½5‚_2žŒP¼¸èCà›x-š·¦÷æ]¶Žú­pRþ«ë�áá×½“nd!ôWl®@U÷N[# ã¹Éè®�³Á4$ˆmJGAaå"“3Ž9�ê�Iÿö¢”�ï>¿þÄb¬/¿À�Æ žl\—Ðõ�¿\Æ{»ZâI1Uî�¹ ¶›ÐpÌ{H‰Œ¿¹ÆP݉1*þÁ}uI¸äãÔ……Ô {– 7rИ“BA²íëÊõqdTŽ�¦kñÖë×uµ34bÛ{ªC„EîE²z2€T”!ŽBè¨hOmzæ5†Ã‰§Α%zb‚ °õÍ2ñ쎩dæ¨6«fL*bVಱÆ#™Æ7†³«‘‹$e°Õ»Óf!ó?}ö~‘¤[6N÷R¿½¾Â“žcÝÀ?9›œ;åìNR;z�à �åüÎg%%ÎqVÅ.«ç÷m¢*V¡¬íÃv=Y $a#kLÚÇxÒ2�Ë«Òäâ­ê Á^O©[ÄO‡%FWœû�6š•Þó6‚Lž×ó�?öj¤î>Î T² Ó¼íWÑ�yß›à«\6 òµ°ü_èi>røñ<Ôrƒ$®¾æX[Elý $¤ñ0øYÄuÓípøhÜÌ!A¨aKÓ‰<•½Ñ, ±é@_ìMª*_ñZ¦A*ñ>!@·­Â¶P¦-iÁ.æÍImC`"t_Ô1Ûå­W:áSx–Æ=.<üMÖ'·¼Šg(ço[+ÕûcÅß��|~Ïth¯’âêe-'5žÐÞ¸1|&gžP1m)‚†Ðób;[õ,òUZp‹ù{”€™Š)ûL@üÒC¬u»šþ%ˆWŽ«;«qø’§ÅîÅx5èÖdyg¯{Ju"q|Øå V|¢Tä?NE½ ÝGHò»Éb>¤²y²Ã';vŽDF[É÷žM#ŸZ'w*z0>q“ÝÝÀô¡`–÷î† ›@qa1êO©;`ž�Õ§-ë ‡§£Ó]æ£7K€å{­a -qïZ¶ÏhXrQ«!p2Ž&çW Æ*~AˆŸÙ5R%Óýg&QNE�áAïç8Õ‚€©$Z½xµJ×-±$›– #uŽo– ñÊÿžÒÛ7€) L‡ÈÐìûa ðW7Ü@þG?›Ê�J àø}Ç :†ÉrëÞ¸‹*eœÑÿ�Vì௷43)í8ø21RÆ_ø*Iáyê½P®ž@=ùØõWEXbaLë¼Âµà+‘�¨�D­°™‚ÁZêÓáNqÄAl¬ðzÅîW­§AÊúwæCˆ®oŒéT‡“‚œ0!ÉaõÆ®ôÉÜ}FÏåUâ¿do@…ÝR­ñÉPUXt§ç]ÈR˲i'ëñî‡�5á²b„`É¡¾EOÇÿn¥µ’��ü7UžÒÈæZšÉ1.@: ?Q³ó‰ŒoòÊØmEébñ75¡t…‡&Þß|.0,®ðžûa´E{§< éM¶ó<"ªWšƒ£<ñ?ïå²íÖY#Mb.}Z"K2ø‚ɶîs—tÉCn¬ø25Í€úÈñx³FþRÒU²g•kR¬�Û‡:Úzðn਽º§7!“œÔŒ0Xϸ›E*§`8øèHÈôתÆCI¸Àë+(ÀØ'ÆDy£‹ÂD÷ö-Çf‰ÆÁÄÈÌé!‚®Þ]ýL%ž8ʽ¨?¯iŒô'‡—výð‰Qu:XR�4�Sk^s@Ö¶+ûÙ‘:ùÞ ‡¤Úœ ¹P‰¯WH×eœ™ ­ x'¢š&ûL¹éÝ„h8£×A*`̈ŽÍM †žHŷ̪/Xp˜# „ûEDŠ­2q›ïoìËy˺ˆna(-gúþÍÌrBg®­ú‘c9÷œš MÍiVq:H³]î¶)$V5´…–Åœ<0ñ³í£Y4x5œf�ÛÖ¢({“‚‰‰+Šè×M6&<'á´²÷¹f=rð¢2ÄW·•²˜í™ïÏóDÍî©”IQ‹I/� [�Š�íù{†€î/‹84䳟åî·„ü…Þ²[¼�ö^›�E£T˼/Å¿eGñžÕâx‰8§” ˜ñüÄâÁµY¿DWÏù›¸LBè u®¿R_iT Úw •7n½œ ´ˆ-èL«øA¹�hîLú�ÐåèK²"°nƒÏËEj>}ò*‡¾,¦^è7lnt¨ i3Ï©<Î$¶ P¾7rˆ¶uª¡1"a¸W<¹þûíûÄqÇ�*ÖÆŠ |J=;&Öy¸žÈnGÿ‡cèÛ|(°óR©ò…Шd÷veª$ »C;Ø´òѶ'áá@iS!jk ç.ˆFÌÉú]³IsäûûÂçÀІ|j²tRqÖëD>¼k`@:Ì—õÙGüO‰ùæñ% x÷w·ºR½�§¾Xë€ÿ©S,UÐá·†�xSˆˆ‚½t‚€ÚS1K"põys‰r»\ `’€ôâ5*€Ùȼ=eU"¥AšÍ5-Q2˜ÿþ)-¥ÀàxWé1‰fþØ—%UÁŠìq¿÷¦:ÏçÖ0R‘›�}/Ï?rÀ Ë™€ÐGIµ’eÃ{,Ê-9 ¼{Rõ|69  ±^çW�ÓN›?fn›2&§|.�ù|”-OÞ±ê…x½W7Ëq èªEÿ)¼²Ä�wqÜ735Ò_zzm3ÇYZW¡r<×ï’ ø&RŸ�êYLòxcWÚÈ"D!žó¬dgú#…åšòD4íõ$˜¾P‘[«]·Ð è]tØE ä4Jèö:®>+š¨DtÚ´âAMЕVmé¶3fÉù‡õ%MÐÅ È- ’R䉻lÕŽ‹>OÇ M�öÍxå•È=TÃë¹°¶ @ÿ–'=ÛéÇA · t÷úÛÍ ª®¤,žã¿�¯çá!«Ýu-¦ Ì©aîÛz&ædøD¨}Œ€Zo°nU&dÍ”ïÕ‰O2ëÝZ$ìúü  ×d¯Õê'ïv­ðz-ŸOó*›Ÿar´±HÝÔ~àCú¾•ÅÁ•Ì“�Ëéwg_ ŸZÜgZ?Q%©š³Ué'³œcsÖ ÊŒaŒÇµŽ¼ƒtöãßCÏÖìgˆÇè^ŒÀ†¡ bí5¿�Ý[0ÿÌPCˆ‰C�óJMø›^z¡f�ž'š¥»MÔ¸¢X•ß¼ªlö 4¥;ôßÅ�^JÚVÖ®ÐëÙ/+À—#3X«½ø¦Ž»uc¡P�¼‡HÃWââH+ݽ ¢ºš¸gB°†11Óg ÈZÖ–=={Õ0?=ý¤]ä¡9JÍ=%ímcü!6ƒÓÏ7mŽpÉ9Z«k46¦¹Øc©MUJ¿F¡%Ô"¤|ø Ð/ùÃ. ¬DQ¥”Ù¡2Äù„¤WÓÑ;?ýâ ¦—‚Ч(÷Ÿ�ú²Ûj\{“†‘pýøÔÃ5&Ö¸].à¯~j§‘‹®]¡Ï˜ôGõœ•JÆmb¯ û‘¸íÐ|0.•0´)$¥F7‹]—L‚3Wá5ÆÁ ÐéHôTO¿DÜô{ã�•{'ñ‰yÏhò%©|ì‚y}naÒn‰ú™@�'lì�ïçÅÑ›6ÒögA×~Có"K±KNÙr.ûì1î2MR€Í·ÚþJ¡ºA@)F)ÈñZ×eÀVCw€ÆBÈ mج@•Pô8ÒJ(Ó/$¨W%0&•À©€¼,cyÊd ~¼£ÝÕ4 s•±Ï¥/|áÌùªjÑF[¯ŽÂöLª?'†¬×9çikÐ&™x Gb|7ŽxóWâbM1Ù#›rTC�€(Ñ%ýHÁ‚¯´½Gí}%{sc(ÎÀ´QktàcxøÜ2F˜Óö»©2'RO¶?úÙ}æªS5¯"ë9·SJán”ÍòQª‚Õv¤ÊK¬.­AX@ñlú…tå_@RÒ¤3S8¥H_ŽV 0qP(LìÍYhË45d·8¼YõÀ_SMî]€µG0Ô¹’uÏà¯ÑfˆÚ¸ E ºÒq'#ñ Â¡êd3°÷bV~áiÙòk�UÉfÐP0·-É fÞÁHŒÞOsŒrá§sÓW«½©l“vÌ–¤¨-¯1˜[\Ízþ|UŽ¡T@^~ÿZ—ÿЬ9È}ŒÌðô`º×B/äðàð¼gfïW”+Pu]Y™>^+�~�c”`¤ EuM'²•µM¤~î�ç5�m"<‘_Ã�ܲ�Bâ^L“zµ‘ªZ²°Ê掚۹÷W'×¼^u W‚Ò Q:w½ô" :„8,¬BwÊŽk8ý]ü|¦ÎŒHaï½ö¶T…J/8›"Ä+{¹ Zaïé—]uüà++Cú¡*NuåäìnÚh¼˜8Ç`µæ­/4:Œø¾Dõ µŠU>�VáAã�ˆ7Ôá�wo0>~±ÚÜÑ‹F7ÍþÂa“@Àéæî†Çm¹0d ¢™_Þ!ˆ �[»±¬÷wFjt­Åæ±a»›a*ÇÆÁ)ÍøSê›_7¯G÷Å‹'‡ ”J«ñ·Wb�y%®BÁ2|úy1âÓfhdÇÝ ]ÍD¬Eìÿ'ôÑ:# æöÕÌñZ‰ˆ9jÄJ¯5Ml’ö†y‚Rbž¡?kÍ”SØÀzyCX#ÙÕúªøÒG%"’³?:N# É/úmµñ¬iünÿßÔÞÞá9¤–*fmق˨Œ¢1¼ž–ù™•›&Ÿ›ÆÃñö8�$ݶ%~ÛJ¦Î¯¿ë#³\&ÕL¢Øà�‹L«âæ·«\;›·p5$_€`gn+Ož·ýC´ß<Å¿È_ .ÇJ{'£ßN.¶¤L1ôB²Û+ÒUÚD.¥·B�Q�•V9ø@6Zdv6ÒøtzgÝ|áêb3ë1aÔ\cޝÇî“>k©PNÒQ3¾¶¹/D—왓£ u¢ñfŽ´•l¦Õ“vÏ)#"$�>å;cB•FÝnˆ8S¸<ÓW~Çœ5_�,ïÛg@£,kæ·ù"ØËFIý6•Ç=Aò<Ê9¿+~D­@†: Ç:˹/LÉ�ä—ÛÔ1oXMë;Ç e�²[& ·ŒhÊ‘dt9«O DQÜÝãÓ°kL'¥õù & ´ÅëÛÛ‚)nó$‡]>Ûôöœc‹A’3V#9ß �¹¡'¼E“y;ˆ5pŨ¼T/=^ÔV%S©e ³¥Tê†' 0ÏïíØÝ ÏAÚ§!G"O­y( a~…ÆÒÂ.<Ñ*ò™Âû§åòŽÿyæÁ47õ× _Ìž¥f^‹§/|h:t}ˆþÑД]‚F—áF ª „�hDypJÍÂ?ÿÕèJ�ü0g@=Ruž³VÆsÈ??'¾{°Í°…HB¬‚!ºH8¼Ä¢-ˆ»Þã·Åéþ�(‰��Ëïé\·ëå gÒ*ô%¬Å=ÞXSTÖQVñoùÊ��œwð9ˆ¯BýÆ0¥3< ï33="[&(j³”·IÑàç~0H_±-ï¬ñ- ¤U½Á“s(ód”å 3�ƒ_ï…š_ ç’§ÓÌÑ)Óz^š3,âgòkö=QÞúØçœÕI‚œÜ“Mìx“gpX%Ó½â5ë¾/ÐnqÞŸÊAK¼mú76ßé×)-³/ 1¦²™3 ÜÓ/·ýÕa9¿Bׄß)²:}H€Kõš±¹á«Ò&ç�bK{v’hÿ¦¶>Wúôxœ¶®ý«‰ÿXË\¤ÖÒüò Œ@ ,“g�¶õë)a\}VrsI�ègö}Æ#¹âÁX¬!M³b@�ÿ×ʃ[ËXÉ“*Ó&(­ó¨-ô‘mïsø—Øí¶ÀÉQµ`úN„ù„šþ®Ò��—t·~W.†5µ×™qGê×9Náýܯ5Æ›Çð²K¿“ð<í¸@¶÷´æE‡ÜƒÝ Úøfºº¦„ïU�Žm*ùŽÖné­ô�G韦¬ôw.•?x´ÍÎj×qÛ‰2mO@©e%dûÝP»C¼8ä²Ãu•‚ï=ïðTb ŸÜ‡•øðy$ÛFŸfhgvz@þ|9~…àJr'[R©AˆuªŽÞm.6w³Ãé}/ñBÆ e˜¾aÂu õé0÷íL…Ñ*(z#†zæTÎxL0»HÄÁLÏsLµÄ.5xÝãÊsPa†øÈ1RP.ÇöÝ•o'd·ïmKºC¶.t~„›:Lèiq[¯OvåŽ^äiñ‹ž»«�»-M Ì 1²_‘t“ßZ[(µ´)”Yvša„?î÷Wª›¢úÐ�ø�‹7tŒT�Ué¦KØYÚJNt”mnß…é„ÔO~VÅ»°a%†*ÄÈ€'Ô=—í¢6ŒÅ6[¹¯«’;TÿÃÆ æ=¶Xð:d–(wÇlU –´­Ûübƒíù²Þ纆٭<‚`Ø)݈é­ÂaÏÉŠqÝ¡>J±Ô ã�¯®ŒûµñH¿é-ç�2li8qÆ…íîÌ}6NúÏÕ·q0yĆ•Ñ`ú›´_‘ÃôîtŒNöÂB»a`³ $2ÚÇN:ª"cß�û;‹d7ƆT‹Ü+·×0Sœn¨\?4=iŒXÒ7×45à “{©Ô; ?qÄ©1îdØŒîïF“n:~)¡94lF©½§Ždö sXWtYøBh¤§mQ.½Où‘×~xQ=–òG>ý*Å”K)É'ÅphöŒåó(H�8ˆGÀþF�ù`üãýêø›pìpí½:*€)™�FA¤DLœê£ÁëÝmÆé–ì[Ñe>>ØÅL9mž¡u+ï\n¿y¬NÓŠ‰dÙî�j…ýên ±þŽôhŽ’rù"_®€ÈzƒÉ»Å"fŽ�ü:àAÞ÷Ž™?‹5OÞ²Âl&ø6êlN QŸ¢Ùô- Q舭º¤Ò Qé±£«œÕA¸\žó¤ûm6û:køb5)àÏzYìœkg>:iUÆlFO›ØÆ�ÓNsK¯Íß!åì ˜b[:ÐýB[0Au+] ¼­UvÛÍ%TsŒÎ˜›ß¸/�÷¾´ë–I ?ÓCçÍ@% �ýkéYXû™MR[R¦ÏJû¢Tžuj˥، ÕÿNÎ,è4ê]cô{öõ–Ìœ<Ï%`r¦*‚H-ò@ã³8üàÅ‹¤m™ùÙj]¹Ü¸�>ç—…æoPÚØ!Pïª�ä�HþXŒG»Ål,àå�ô9Þ×<§ö¢p¾­ •hø¬åq�–àuMš–îËçâ¹iSÇ‘¢å&g(åír/œå”.ºMÔûÖNë÷J.é¾v}=ªjdM/ð¡J–ñÄ¥†g‡`¨,X$V^�f‚2ù¾pWv¤Hš¸b/“ù½Âù¶Ô�º‘�ü‡‚À7f=YQÿÓî?1÷z¡fÚ¿ØäQkgPøZEË#[àƒl㦠}ÿN8(Í¥ùœVâqøjz`é[a ã ³ªZ>á‡%2Q7¹q>~<ó¡ÜPÖo)G¾¤æ/"Ðß4îÊsŒX‚Óå[kÍB|ÓP…„¬ßz¬Þ„Pp�Õ¼ö˜ÄŠOãû%>¡ùþ¿˜’È-Īö'b]v¯ 6¢Òugæ÷H¿p?èGVˆÎfŽÖ }ˆ|ƒ†ñœxNÓr‚‹™yQëj†ƒ 4^õ�ij#z=±«dò2-·A¦§´$sÚp&u«¥ïZm`·]€¤h æ`ϵ°lÌŽ¯Å�¹��t,÷èôg:ÆS¾µˆ+ýŠ#¸ 2Ñ)H@¬&þÉ ׸=`­‰âˆhÝŠE†yóÇAÖS/•J ¡ÿ¦#©Þu¬ÅKI©·z¿ßNFB´|S©£éúÃê*× ˆ$Eï„âÒ¡“¬ŠÇüOÚÀ½ôñ•¸¢0Ù�î¼l#h<ö¤à–îÍè6cùÉ’MßD‘<¡óմنݾ?7„ípþBÕîq$™C‰#–oûás¼ [/JS†¤Å| Z�—>{ŒŒ¤¾tt�5 ð¡÷—/9A¡¯¬9Ü�FãšeM«�û%GôÈC”ŠòRC~©æE §[ò½©]š+ÆY¶þò+b0êɲÏ™½� îÁ&Šr壟÷.!ºÑ]jdš\¨¶—[y§$ -\ChJòI ZHò XX²Šà²ŒS‘\@ø¶R†k.°(4žXçQ2Ç·|™÷�‘¯‡Ä vH_Ûf7'}§¤Ñ¹¨ª(wû)ÿzëý.Ýa^×Vé^RÇÏû T»ÐQàùzYŸ@߀-ÅŒÞ%OÖ¼ñÖJ, k¤ƒ«H%¹�ðŸ 3Ö)0‚fÆ.¯}Eª¦9/´)Tz*Åûàq^`,gÒ`¾ÇT‰ü5çúNdï“�¯‚qX‰öÖzFqmšKîRÿÕä?ãR;…_ŒîèZoç‘™¥q~ ŸÒäXéCøz‰¦Õ"ïW=­0`dú{àeã1N®–gÛW@~XÈz¤~£pŽ‚‰nh«DT,FG¡OªD "°•v¼mÜ»U•À¸úÍù�]]-:¨©øí Ó9“y†Æí²á1òV�XP὿àõEaûv³¥^H'ºÇ‡DÞ¼¯�²!*µj8´™JÄÅpJØSËê•*ÐÏôÏôèÒ‘0£Ô=[Ls!y…KmÜ´`u‹}>YÙá¥'ì+‰s’pm£ï_}™M¤Ä�S‘ˆ£(Œ&ÄŒuˆJ¦µðŸJkÜŒIÁ²ÄæÄ¼÷¤‡âOGh\´~úJ<ÅØ�J‘—.ªŠ‚Ô Iœ¡Üf%ÈÜ{Dâóº �zát$¥ÖŒGêðªà—¸A¼þZEI¨è—°æ²-EÜ] è˜wQ¤š ½7½ “˜GŸMZh—>‡Di‹ƒbªã(�‘~ÀÓóU·uQÄWx{4>ñ”®'®�Yšø!ºÐD�ãÃ(‹»zø»=÷o#;‰âUÅUž—RkB"ß•f"ÀSöÜpzó%â. e�Ô›:‚R ¼ÄáRZ¹ÓbÓ9Õd3xÈáM6¢P¹mñnºd÷7§‡¹¡Ò5ÚŽP‹¦µ ¨ˆPêË®ÜrÜ|°ƒ-ɪ¬/»óë7¡íè¯m<�N̰˜rúîó²Cöi3“Í;º›K–`ÿQX>¦¹¶ØŽwLó6-¿kZ¢ ´y�Àoå¸{з»oT˜ý\H-��EßX9Ü߉UNÐq/�ïNb?œOç¬Ø *rþ}™‡º¤¨ë÷úr…èr˜â8¥öËVˆn¦ÏCÎŽ‰@~—G›{ýœýŒÁ_[²w¼ÆJ‡} hw™% Ž?ÍmpÙ¢|þ˜>íl‹D];¬è·�/' :»DÏ2‚vkFè�¡$,£gv 5iº)›6P %»ËÁIßçN±‚¤ÁF<²@ÆäDŽ9#0Š¿JóžO0¸ªËHåîÔýÉãD'�}„ÚìÛôrooSjI0” w¯} $z/Cþ�›¡"çÝ@''þ3ŸZ © Ó�ÂÚ<ÐÐkÂ:Æü‚ SÆøÊE’8ÃÇ+[Œó³kÒmÆè>âZ€ˆk`ÈV/.YÁÆÂNs‚5A¹tÃ0t1£ß;™;Àh+�«Æe²B×ïêÉi�a•iô^îs“%ÛkriL|c‚o�cÿ«[)ps¡3dbu±¹˜«{Z²—³J¥啥˔½IœÐÿ‚¬xãÜõ8–�p_ø!ÍÀÉèVÓŸC^¹òytðE×îJj]úÌÁ*ô§��P·~ÖTä~7~‘$pÉK›¡3ëÑ5¯ÕOérÑçm5ž@Ø�1‚­„úrîÓYªÜÕ¸m«ú0ŽŽÒ·5^C‡ûã'ÝÇ ˆìZ0Ël™CFQ»ÂM+ú¼gá^ ¹�Ÿ¨b%K(^ Êx Ò‘ì>./åc™)‚NÓÅUoANõçôU©Ç�rð ‡ÓƒŠçú5Ã7Ýwm˜ÙòZµdÖ†_DQ´€ Ð}Û/gågébÝ[/­�q‰ã*€y°”Õ!¬ÁOa!…Mœoü•5W% ¯êVÝ P–}ÁX µÚDÑ“Ÿ‚Ý�7›�ê‘IØ(®ÂO§$'hÝð&®Wr5åš¡?Ìúî�îbË—²;„ƒŠÚ,;5f‹KŽ‹®‹1êp½]gÔ>ÜU…ŠÖŒïn¢¡HkeºU€ÈŸÊÄ ÞÞo¬<*”j(ÔV)µ’˜óÍ5§×¶¹«hk\x�ª[Á•�{иº¥—œ ¢¾¼ÃÈÕâ#­‚îy�FU.šö5h˜z4® Jýɇ’—¯AÍ#m†b÷û|»¾[çîù¦9“]¾ÀGxR¬CZwÆA"×åv}Eµ ê¢guöJ¸Zz¨¶£´Ñjý¿ÛÛÔù¡‚:¤„î—Ñð/‹p�“6¡áÖšŽºqÈ™Œu#ãÿX3#1fÔ²þ›•¢.ù®ý÷ã4Oá•¶VüœM}öoÐ9ILp ‘6ûÙþ²Šr„¤CÑ­S:h5‚Gʰqü¤éŽJfèù�³“ ³}ÑSs¸ºuböì *©bUï~ZÙÏ £õÉ}¨'õu;ƒ;ÉYG\ .çFÏ*2OäÊjNi’5«2·ä¶dùþ”H3Ñq^xwž™\§8ˆp¾·t ù…Cke¹Á²xßÒ)>Þù#æéŸk²5 .•íP?6ØLòF ޶xZ6h°9@ë±C• –ð%Fˆv�óÍT*Û°»+»¢¤zÍæCL—$‰/ŠêSÝÚ*{é/š €äKæ%P>óõ‘’ŸiLq”á–Èçü¥IL–ýÑ©'ù=ÄZ±Ã„�ݲc�ÒôLôCñðûùÄ�9¬0,8�Ú®Tžš7¢Ïï>'¦6iÁË ÕS%ûÃ]IùýU¶L ̶U+ù¨ÌɃ3‰¢Þö4#储0Ût[6ÑwD.„ |“ЂÅ÷%»Mæ0me²ž_›�#PþF¿ô*ª¯1 T‘ZœäYdZ{Ös¤3h¹üNybé°’�¤ºóFd官L4¸}§æNܦXôâL¥7mT¯Ä—ß×V7’¹ Ÿõy�×R>*QÆêÞÅœv¿QÒF†I³L–¾œ}³Ë†Ap“ÖŽ³|耰_‹Ð½2I�“‚«cɤO>vø·®Åê–Úñ•»>ùd‰uJó)�ZoÛ6ïAB @D;‰,Ëq6òÇ<Æ0üh€º§2˜èo9Øj³K½Ù$f0•NoêrPèY„ÿ}„’±·ä°ž«ïuda`ÉÊËk`K¯³ô{,yo¢Ï!Æ ý.‡Õ ¶˜ŽÕâõDšc•U'D>°{ntN¡V#Uà†˜;'ã&…¼^ž‘Èx/óÍ5{,bå`Ó˜Ý1<æxì@0wù`gbÅM1œ K“Œ¤ÙX•³Í±Þ5�ÂÕ äÜq¥¤`Û½4¸QB!âÙѶbÐßHJ»±Ôº.@Ç ~—r³÷Çúði‰w‘ËlLd²#ç³3°)rßeÓw«Ã޸ãL¯Ý‚8�5è!'ØsÖ̦ư­ØÏaMøÖ­*2›„.ƒâÒJ¤>tE€¼$ÀÏîxƒÔï{w�v¥­a”•£4ò¢,sZ‚Ôp§ù`x¨Ø~_DcÁ’à6"ºë4Ó2í¤ºé×N©ߔ⓿t“=÷9ºôâ=ïtä»)ö0¶›&¤ÃÛ« ‰�e"§z‡ÎÜù7¦!aÄ©*º4%±Úç¯ËlwÚwžœà|1„éÞWb¤°K ªÿÈrÐåêz©™4Š ¤£qV ˜q“ZU§ã™yŒÛfÕdWv|’=¡ÁÛ—’B ùq@kdKrff˜Ôi( £kå¼l£6rq?×÷…LiÚ骤" 0aÂUø¯Îï l �.éá’Ñþi}÷ sv×o¥ñ=½3mÀ) (*È̸b§„E tÁQ|y¢ªaƒ #u,ãå`ãÆœ¾”•ïz«~,þȰ–ðäßénîZW¯?=×›d4±žÅ}ø¥aŸŒ Âþ<õAïà½Îߤ“«,ÿï!œo²±NàÇõ¡Vážš€9ø{é kþ³H™ñ¾þÎý�rƒr¼"}ýœ†¿ËZvãÖ‹jmÑôz΋5GjΠæäŽW‘¾w•­NÃÓÛÂST9›�û¦ínzv³©]¸¬Á�r¾H7ðÐ?Æ^V“f¾•Á' BÞIn bkÝ*^bœ¢Æ¦ýrsÎÇD0Y,„(9†?´Ó‰"ùÚYQë/%RÚã}äéæ\ ³ùž@Ó•ÃršÀ¿<t‚gB^štv}pA lƒHÂnµFpZ¹{e‹-ò÷é ”¨P�ºŸ £oÞ˜g©V>Ï|‹Æ› ïbo"µ§.ÙjŽàu>HŸŠñ„pÙ¦¦#m\Ežb+¯Svm7ÄŸ¶m9Ç#ϰ¦5 €*7¥mN 陿ÝÀwzÌ|#’‡(noÔþ“r cx/˜{˜ËûèÉæ9FãŽõöýA‹Öðy‡Ý‡¨y´Ì_õYØO±b~ß™¦8]öÛÒÖ»Šœn¢®"åSe� ćdqŽR2¤Û† kˬ~áÜ)Ž©ˆ#"B MûÜu¼�Ó½dï½pR˜Ê’*öNêâ–¥">2é­~LoÿMúICyœyħü?âcµ!¤Æé´î%Y±'6óV¢{Ö9@riLíBhqí'†›vþ�òVg§ºÁ›¯æe9™Ó%¥•Д­BÃôËgN‹¢æ©ÿMÉã"—Ë2|¶xz[ûþßó{µàTAžëd”dL'ÿU=òÒMà7}X@ ƒÖ\=¥µLÆŽ>È­ÇÔ`\éþ˜5¬&ƒ²3(\OÕ†x–Mà–�æÖl|ƒý ÛdAZ¸JüƲ7¸ŒÙ¸E—{äÎÉYWên§d¤ŠVóÄpka¬”°Ö)1î˜d“±Ÿ(¢Ó0q¿kødBWEbÅ¢ò¹[OÀ¨ ³íd]κ±1ì £¬¶:+5CÑ<,C>âïü:’�n¹W$LˆUîÝ@U¿’�µ/Ú§õ 9óz‘v1%GbúÕvɦ?Î�³S·ßbadååFŽÓ«;×:' Q!•©!�/“Äväºç3"òZÃ?µ³º•n 6>�hk¹×½­Ýû``xxµ)Šbq�I7˜rϪÆ.zJ+ÃHiÙõ÷ÂG3=‘ÃTÓbßoöàR‰#†ûaÎ)¶XÒÚrrÅ”é�ÂkM·z¸P#VÇ£×lûwÉÒäúBF¬ºÈßÌX­ôc2œb £õ¯ò.ý§Ì„ðDm{›Æ›èv¤UyØwÄ)0E3šÞo)«Iªj½¡üÑÌÞå*ê1¢çŸQì%@i †ÕÔ�Gó °í0»v�d©0î Bþ쑵­RUò†¥Œá‘6ÿâWw81õôÑY (Ø? ‚všWÒò/cænOùa /á]À˜Ð¶`Öb±¡ä%ªñÖ¾´KÝôíê‹¶Åð.¹¢ù­9á3�ÛL{´Â]ª”¥ÜL.êI‚½�ƒ¨O Æ Ñ7VZí(é̀ؗö.Þ›� µ<–دá…åöõÄ—Ló\Ô­‹yþ@6jßâÄg Ìçrj�½p„Ѿþ{_¥›~e�T•æÅÒµ&„Dæf¡âvƒ:ÞÞÃEò‘ŒbMq}ÛÙd€VŠXu¯û–ñp¼+‚8ú53W¡>¿‡dä+ƒÚìs:Y½2 ù'£—¾(ë)ÁȰ×Õ„(n˜óžȩr í†Ù i5þöÌ@ýŠ\—�¢ùß6¿Üðð®¦h®Â*â{èžÎl3!Ø.ÆU%l×04ê^š¦œå^f=²7zoË»»}/h…Öš&šÞùÒ5/äæ¿qÍ«  &5þbÎ~Æ«¼s 5æ·¤ñR]ÈrûOhç6XnèïhkyFûw+Y¿±uJ²ziŽŸlQyµ1CM\„8LÙðžR‘šÀJ!ùÇŽ�>ó⋤ˆÂ×T,†67Eºýw©DpðÈ×ál`/£Zïª\:×v(¦æÆ¨�ø&æ3àÆ.˜š0‡¯_˵ªz§)y•Úª,ÿÄpÚ5}'Ièï•wõáç$Dº3yû�Œ9™yöQYxº‡IÎ8èr7½'§"ˆÔøå[A›Ù&ɈDžª›ÛÓЦ.ÔmS,ÖHͨÆ&'ޱ]Ÿ iÿ«AšoˆQäß^cRƒèÓº °Ú Iãî¹}k€ÙÂdtƒkär¡“�X@üÒÓ–‚ƒEžhßjpþ;PM–]M,p“Qh …²¨¿ ùa¤ˆEæ�—Ðå�±‰@R‚¨H¶l"Š˜½[äQ½nŸ5O¯Ÿ»ŒvDV˜)‡ýÖãOêM¬¯#i[fŠ¢aþZ§æz –ç ÞΤî ?ðQ@mfͦõ‰i‘ˆqKøÌŽâ ÅsÁYŠ ‹r›"M2J+È;¬Ñ H0ˆZ.$6wÛ‚�’œŸ +)ñn—£Z+±vYߢ>5 juçõ„ Öõ�õù:ˆvÿÿiÌ›<–B樀¦ó/ËJzèmÝ!kŠ9#Ñe¼¼ÞuŽÔ†iê`’Ô[žAV³a‘­WðÞ0q^#™WñM�Æ §*Ö©–óøs­êÖÈŸ nGÿ­;èü%Ÿ<®Ôðï¼ýÑ6¡I%z×�m¾A‚Æ¿žš1&w°]lÒVY¾ô™9Çö£ƒ%Ð�@Zü(c�[Ú}N/â–-šOm¯Öm^B³Ó!…aS”íYïnî}ÂW W“$_³ ~ä¶Wí–¶“c׸Ê{Øáv­o§^0±€B6›uèÉ­*Ñ{Gð¸CÉûý8mw‚Z%s§O+á;hëî`;kZBµ×»9Zit~¨ +?¥h¨› ÔœG�¹xû¬–'^Ë8à%Û˜²©ð~˜´k€ø}¨8ðZo'Ê–TêÐ�1dŸs55'Û²QêÙ„YÆ1‰èÒ¨ßÍü%�–A›5-©2˜ÿþ)-¥Àà7 �0MÑï? ¯ÔuÎ/³Ä|{’ ›‘SCò´Ì&rÊúÄÐºóæ† ’œ…SÚ=ËÒ+¼þM¦�~{{BÈàÚÓ<ôš{ÛÚ8J{G×m[ ‘¿Å“×­z—û#w5ù�¬ ¥ÄåIÐ�‡ãPY9†!ßa·®Ñ®¥à¯©Gtþ@‰ó¢HfšÞW}ŸK²Ûö’ °¬~­Ÿ_ü¬LާI3L“cXM{xÔµKñ¾žæsf,_]›˜—Ð’ÜúÑè¿°ÛòCî¥Lô2SY° IûÉÃÍȸHÞ§–'øÚåq}Ìd‚DV*êš@@1"33ÓX&ómF¤îñMÉB�µ ¯k é £•F¨O™µˆˆ !MiôX‹fbùGýuå+�â£ÙçS/i(i½J 4æQä ¡½Q¨RöÒG—ÕÕ€;!�X|$ûÀ%�ܱfÒ?4A™LÜq ‚ìÖq ¹š7d¨Tò[©Lx3Jþ›Àµ n«YyEà!¢dåµ´õB~'h5ÙË‚KRíT�Ãl!Ž¡é.ƒIŒPÐ'oc#àäó�œ28ž/Y¿!ÛÑ3ÎÌÕ<£²ŸÒñšØãó—Ì#ÜÍ.r£äù–ÍþvÒ]éî¼YãŽË¾ùŽÌc‘%GVõæÂTâ‘ÔA5Ôs+ò÷L6°jâñ:f7úe4Âõ’“¤^!,‘ýxÝÛ£‡ ˆT ª?úÏa�›²—™¥¶P¡Èiû‹°�lNÍòö0Çm�"N1V»™ÆMÌK>Õ &¹WÖ2,ã@ecï^ŽÄw>¢×v)ÐOÊßê(Ï↬ ¢J6 /D®趼عs•ëãMváX Ù­aZ2Åͺ(Y‚†Y�!’:�îú+³~‡�¼ÜÙd 3lE¾¡ˆ¾ÕàC>p7s4[÷éõ[ÆÃž ú•‡ 2uËLž†”®Ê“f1zÜ�÷ ÛKG'›”Þ$ì8T¥óø¶Ð“ݦ.¾#ŽñÕ×êh’°ü½9‘FæÓ[ýK±árÐƒå ‘iªš��³ª=�€ï§0¯ûÕ›3S¹CÂÚW9Ÿä×”5­8c)óVÖ:ÔÛ%>Z°lrx¤Ìô¬º„怎O{;M²©ü¥±P[½4|#ÊuKy“fB@±øh„�pD2õ`‹ra¯*LóÅÄÑ™E;¬%�ämÚ/é=?"5þé£\"mkgçÀæ¯ 0ÓÁG¤¹¡†¹Kîsƒøâ/eáp†ä¡iÉ=ã*ÄÇ®`Ç‚b#Õ²�爓ÕÀ.A2÷´ÅþL÷ºàWg�MKc€óu®ˆŒ™,ÆþóÁ•þÁ!‰–€ý¸èR±Ò?›4Ú1¤ìñPt|ÿ qMfÅÏ™O³ÉŒÚw„m™‘æï#a–˜0â'¬Ñ“Õ¦M¥XTÕß’õ\fAó/ùÚTrÈë¤Íýé‰Ì‡çÏãJQúØmy”íg €Øòß™Ð�.ABçã²ØÐõÅ©°÷ÆÁ²6¡¶�”y?ž÷ÿ ÞBÓ´ö­ë¤CÆ×«»z À²–àWå ²áZU4µŸ÷#+ÄwÛ6©8�6ëhõ!S±ÿcà®Â OÏpÎ4ûú÷[t²g©â)sT·€\@› KÑÒH+¤ðØ~ù*‹vÀsʪåÙêÉ[×F:3 Rtcœ=º°wâ†ï¹§]›-]eHòžû8=ÿªzBŒB#ʽMM4dz`ú­ýÀZ£J'á«[Ž:`[ÒwGˆ>`¹ .„3w„ ­Wî¸_”höt³Á†)*‹ïøMWÀé$=ÞZ,GO;Db&iŸYä^JƒÃè‰0¯�Ȫ¡þF'6�Ù•Ç@â»d®¢U¸‰&¸¹D†Q¸ X®:eÞBWq-a~ìÈÇ«ö¨•BÂÑÐú!M„‹P�K’2yžXḣëŒXL›ttvÁÂÎÛ–U®—�š¼û‘~ Þ|iæ[�Ÿû_ps�³CîÙi 쉞�~*Ý}�,Snt6ªÈ}5V|ãtv:­bìÞ`r4Õ«+öÓÞW}S2OŸªüÕŽü˜°íßÀ˜�´X)ÄÙ‘�ü­1ñNïn†wȯ3§&ömÌi8›vC$bÜ%‚=’5âö.¢¯—¦b%Ÿ¥¶  ¸Ï;\ä§NÚP•P•Mw}’àþIð't‚›¿jøßÕÔ¿%ÚØÙýosó¸­uÉœ×4¬¥pþm�—ŽˆìlF™\^p%EŽÛ¶2å�-Ñ’÷H› d“"w‡áMAg Õ ŠL_¡~;ÑÆ¬¨¿NÊRªÂBo§²‘0½š“û×u.±F@ëÚCÚ„ä‹/?ÀòÒd$,q”"`‚pFä"�á}ýNõ]0·Õ>g^pDní¦¹þK"BÙÕÏèÃüCbaíÅ´:!på{´âŽZ#©=QÇ„=ƒ‚ºÅ§¥Ù.þ#¨’Ø"kixh뺃 Ê×áò?±ÉØ»Ò.–ŸõÊ’ÃÆr³º¥ªŒ´Y¿2àþé¿<þØ–;o™|£êOR ¶Ðÿ3—V�v(#4ÓwÖd\ŽÅ\:5<Œ*Gó�­þ ÔŸ7ÕÐ=x[‰*Y 2 Þµº«|Öq[¶¹<ĽÆ¢ Ø=Ç®‰.þ±mž†Îð|¶¯=Hë7·Â +µŠáaŠW¦²›3µ[9ß��g‰ìp5×K›øDyìÁ“óÇÛ»#þ ãÿÔ†„p°õCâC(º|¡úã€ä[Z·¶-®]ôµÑ»~�<ÞK𱾩e0î”4twæIpØ“‹á×�[®ø/&3LÄ¥©îdùúöÌ]f!Éy ÎÓ;#G¼J°’××t­}`»B—ÍI Iëø¨È-…ü=Æ{KL)�ß^ªŸ‘Ætª Åy\úó/ÖÅósPœ˜ª+3  ¬@JËÀM!ýlóÌlû)èÑXb¶}­Î·Fí öD¨‡5F›Éí‡ÂZº)}ƒKãÂÁa�õ?êÁÇ÷'ø ž¥„=ŠOZ÷ªÍØ}ùeËeNž¶¬ä´¥ÜÌØŽŠíœëò§aG!M0ò^=óaŠù‘UfÉ�IŒ‹ZH”ÙÏÈLóa à¿õˆRÄÑ_¯gG a²Üœ G?*hÕ_"&õ2—苬Ó0E¹¯ª®Äƒ½²}I‡RH�ªéürÌfyÿzbcé€y;ݶjèžp¹HÚŠçv¯�u DãþÆST�îjOª²‰‚È•3 2lßVrÕY¦ŠÅpšlh0bé3ÈHh^vèÁÚòÇÇŒ¡ƒbæÄp�ˆ„³W´é?0רäCt³Ã†^e{ø{\=»îN`þ∠áI}gª» ñŒyá†ù,vXƒË<}׋#b€÷!×Ç9ÚCËXæ�ì.øR„nx�ºXè$ê<>“€ýäôD1ô¦®»bhY)p“èû·{Gm ˆˆ´hj#ÍÑY [þÙÿBĈQX+#f^%QŒt�²'囫lÐÚr̓Õèkªd�ekgn  f×,ÿ9D�3.¶�eÒ¥ÂÐ�Ï9(E¿ÖŠÕÏä Wc!f×k—,¦4AEˆ¿`õî€n�íà“Ø. €àfÉÙ¾Þ ù­o’A1Áqý¬T2 O3¸õ˜u�_$Ÿ_¶zûQoTºàIì'0øO#ŽÏò.WýUýÞg°ÒF>4'ÕÓ–�©Á2m„Õ$ÂÜ»8:% ð·Ây ú-žýúú+è²�£\ Çømö"ÖBNyšÔÙe�¢wu¢ hó÷¯”½yA RÂG¿¦± Û®rôï«Ë·Ô%GÔp‹@K1R=6�Äõ7paÌ8(¼ûP•·-{¹ ,À}ÑØR@¬=÷m Vú¢¨FûšôÞdÌ�úªc¢aïbR‹9ÏáO´·Ù¾Òc™U¯„=LÎÓ‡*8È€gtñèý!qÛÜ�7êRÒ¢ñ¢�k#Às œ¼àQUGv,Ê_�s‡†þ¼ë4,��Ú©X{ °O:TT0×Z……Æ�¥z¾_è±áàgsi·Î[ýü!À¨‚|€å«WåÐ ïY3~R@·/$7ðÇs‚{Ÿ¸2ûGåu Q_‚} æör‘–âOüORçSM-ó›-FóØœ`1¾g@"‘惰¾Žlξ¥Ú1²mÔrF]§h;2p�窞Y‘á! …žî¬! ¤9ûÒ$�Hö¼½VWðÃU+¢7%¹Ü ñyã²ù Ø&ØñE@Óz|m—<®‰xß¹Úê3Cˆ •¯pTx®këT9I&ß�ûÿz æRtÉJ8ì^ɤ>Ù¥|KàæÆ ªûZ±³}ÒʇW~(Šõ&ödiÚ¿2}xVl8ßdp¸¥3RpʆäNky?"î¼_}·d0×[#¸‹$!ÁÖûxÛ%¾Stöû¬n¦ï‹ûR#Ú¶êy¤ZÒK7Þ¹ûXëD'‘¨Ëœšq}eó­ÆåÑ+f  ±‘õúÿ?Oœ©öÆã:©šÂ#`8 ¢ ÖüD‡9~˜ Xw`›•Î.ÚQÖYbN){3ùR® ED>/cŽ™afíCS®ôÇ©ª¥˿Ռñ÷?Ú-Å\ÏQVÑ7àì0>€ `ú23Ö`®dv5ð6A4¶®éŸy‡©ä3êŸÖTzDò¨™…åð­Ò-oˆ ÏÆ‹ÃD`Zyb¥¨’×êÂõX$™¬Žù?0××ÎÐzB@9],~F7­¸" ¹Ê;Ûô}u5Ý CIÞÆK±ƒ`‡'Ún§“r—ï‡ÛvH:Ùð0tX’=ÄQóyt& ù?JÅK^ àzt!i@•ˆ¿]Ñ(ó£* &5§¹@Cé  Zès 41v}ŸCìeôºˆ‰ö ÊUùó@ Fõ¿¤×ÊÞ¯ 6b§9 ù6œ—ø÷[üö‘‘vB�bzÞMĺ~u 5½¿bQJóºM§þ]+Ì#ðLa-"¯„†áÎΚFe KÄßE²ˆ�» a8ÌÅØ�”ÚÙ è']Opüãz…A¡K+©ˆ�÷Xà`ú<¯Ì²l+�tÖ–M¾{ ÃŽÈû¸ Þ‘”QŒ¥Ë‹HÄÄ] MÜ©ÈvDkôzx½ Pˆ³/Gh²éˆßHîMƒp•Ûä/¥GæHc¢P®•jô­ðϦ§â>«õ%{4öW´ ”ÿ}ó1ÕÆ"8ûôV¾Ë„Êü’ÈE‘ùL‘á îA;g*}J[RßÂlø½C´¯�þWs~€¥²ÌWVªü�³§üê¼â:õ1€væ”¶œN1‡¯=èµqÖ¦¿Ûµ7ÜÁ6¤azÖFß<0&ù°ý+&ÈR’>@£Ú8¶Cnhaª7óµ)†0Lh '¹e�¦£0+:=V{‰%\²•eEÞ{yú]¹ÏhÃ'F®/]£æõÎï!^#¾üh“¸Œçv%¿úcsV;Áo<ô*õ"”|¢8Û?qǶ:]ol`M7þ4)­®£|¡‘)Ë>oL0PŠ )õñ˜Èˆ¢uúºãËE3†“Ôûv†}Kçg/r!ì–ÈSÑ [µ$@)S7M®ÜYûHµû逮7 ×,[g9xød‹É€\%< çœ E �üô*èhæ›CÔV˜�Ù^ïV{öææ$¹ÊV%4¥WÉûãÚA½õLJîÓÇ¢î£*ÊZ&ó¡}¬_Ô®«¬‡Œ/3[ó�ñ¾�Ôa¼‡~ÓBdC}©³4ŽRä^äð�ë;[âVá¢è|Ÿ×—K×Lôd·àC˜_R‚{Å”„„¢5æ<š#/UƒŒrÅ´M÷Múˆ=F³HÔù˜*"l‹¢1í.e¸¼ÕM˜£0-=ŽÿÉâœIV;úÛ¸þi»©p³m�.Œ>´K—ÊO«ïê]Oß¼�7]ñmÖ�¶„ê@RÍÓÛ‚¼5Ÿ›©×^" ôX¸æ`$KïéÓŒê~ VI; ^7€íDN¶…¡^ï»Á£}Yóκgˆ ðó³²ËbäkV˜»î^gjvâì¾ )¾Éþ÷À ¡v¡^œûØËdNX\Æï9¡w3­6›-�c€Œ0ø'ÝI'¤Ãø'a~d.èY?�óD_Ýã�éÔh7:ô;œžÚW´˜Šw�ü–šÑ$s±Šntñ ‡÷HPÎB–G£2�¼>Õ)ÔHë2Dkh‘ð8çsþçÇ2ÇÀ\5R]îvù3à üú±´�â®-ô“‚}„åô­D{ROÇ{¨Ó1–ªpŸÌsÿþ`(ê(qÈ®4ÔPÀ�V,À¥¥Ê Ý5 Ž€ âË -h ˆÃóUAŸ/d”D\'ÿ^=î™`™0C}Ö™¬)•ûš9uŽÕœJ£&”bŽ#/þÌ´d’‰T¤wqÒ{b<ò†¦·ÑÖoè®ÏÖ�Ôë5=m¨/¦ˆ‚5a¾Jý¤Qø÷«�´OpZ´‹�4ÑèÆ&µF$Ã]’5WªÆ�nÎI¥u:à[Ø–€*)6”çcç:Ñ®@Lí¶b¨¢t$ý_0¯¼ ÑÄ]÷'�Ç’åý) /V°b:½ÝÖÏr®ÌáÉ…±[1;bt.šœZ„Òð$ZŸ®°ìD’æC=eͽðUÅÔ ?Ú„N†Ö£Óªd-J¿=¶õ]‚X½½æ_J?Ž1D¾Or´= °°’ºlêb[m À¨QÌF$‘>=’.±˜�oRK ’M™ äÁo%5Äf²¿)”©ÏÖ'„ýê=â'HšòËsÜå´ŽúöGJìȇÏ8¿.Œ¬Ã3Bw†t6XìQ0–¨4)gƒps9\wY6ލÕY׸ת»(´[J¸Â�ó"ÙÁXPß JhâjžŸê¦;¶#ÑqGC¥èòj»Èï<µôŸ Ç'[‚kÙð.Cf„™ñ«Pô^Ú”¶]pµ 6œ&³[jþ>÷ò› uæ8DÚM�IN-±ÿTu4 ]8önx‚›ªPtó ™E¬ëL `þ%FÁg±ÞÉ€@Æì®š,MK+�Úw¼¨€C5‰ìÔ˜˜‡%»9óòqÆòe°»Áeøõÿ/…:×€= yKñ”Ë\wmÊJ_9@µÜ›S˜Z („ø2¬wÍP@VVµ\ø»\HABcŠP�ØŠPXΕêÊü4%UCà©F¦ÈþC[mI|„,]´Ö7gt§3ÿ1(¶LÿëŸITÖñŽ‚ä–ñúUýª'˜ºš¦æãûŽH"–%·tV ø·Ý“�ߎã1^5ì^§õÉŠ¿ÿ�\výÈlå™ê´_f“uzÏr—s|É9bÐ^õÕu$SMï‹;í‰ûû+À`µ…i&›'øv²³_}�i-âî͔Рlú—]�røNmÖ³ÄScQ+‘à'3͹uø¤xe‰öLrX/X˜|KÃÿ¦°GÚô.O1@ÌšSþIÃ=g¯³Û°_.c�ù[G ÷î•ÈÄÑ}/‚”{sáJ:íEß8·tÈň35c30Òŧ™¥ˆX“veÑ Úxja°hÚ¥Ö¾HàÃLM™CISÜPĈ’*Ý«ó¶vî¶œ½Ee�2A8Tsõ+gB¹€´nÿ¢’®¦ìåËë[cOCKƒØSfOî_�yØC€ž¦ºÆŠßg„·"k"í”zÄ0fïDZk°+…Ly.ÄôÙ½ÿü— �öÜCØ_3¬i¡SÀwî$ Ói±–´1-+òO;&¦yäÃO­Â3®æK®˜b a.§¿ª_µ7J¸ÎÑ]ïpS“þ+Ïðz& y*Oú4MÚVñj£.•úÄ|‘ecá…ñÆXÔ^7”bM’w‡R £]ì³ZÎûœ °8(!ý*Z mA­á‡«1Tã}!ÎÆp°0RÐ¥�&�SÕI1-ìNÊJãìÿ/x"{°N]<Ã7ó›!_øO´£c¸uð†ôXêëö“[2ß�fI°!šµ›Î�É kÆ~yàíú–U.wÀó‡ïìÕïcù¹ÿ¡Œ… å†X £éöÐûRbƒ0ùÓt�;[ìÞ„ôõ]¨t ŸØâdúŠcú/ÕôÑAg ¦«ÌÇÛ3SĸµBô8£éŸPnGÿ¹cá@\¬*è¥ÉåÒc[Qéžgâ&‰÷’ ;±ƒà¶ˆ$Jõj(Ñ—6Å­¦}¸m9ì0—˜A—ï‚ÆÁ%‰«Qñ<íí}¾7U4®õ{4wÖY¸÷½ã$ÊÛØ4¸žƒÀ_R×°¤^¶„)•]±Ù²lIÍ«0˜ÎØ¥€‹Øy¡˜.ŠÕÕ~†ôõÈ-~4‡») ±àª€Rï”&[¥‹j@T™×=xìÈ2y%û ¸ã½‰”Œ¡Gè=Yß _ªïïÜûú@efåß[·Ç£_I�ThlÏ•/·¾=A¤ucå1€­½Ù@Fq.©–-ËgÛVˆ@"RA›U5-©2˜ÿþðèl´#<ƒÛ¤°œy¤ªzf”çÃø<΢E­mé\þæÜf"D »Ü|ë@²žº�,ÀVj¥ïâ5?éŽ-º‡Ã`CwÕ] `&ØÕ³¥»4eIe�l·*îRßOšfs•„ÌpÖ�Á/ø�,öÎ^ ‰›hJ¦`© ¶²½— )@yÓáÄw hì5%Š´Ç…Éà¥2•Hw`û)ò|*èrÏòön³‹ÚRêAN‡–é“e×!äd¼ZÞƒŸè·Q)�”Úkd¾Ó¡)� ‹ÑÜÔü”£D÷x¥Ê.í³l'I)®4&Ïö~BVF˜§S8 R"œ|…Æ·òw�WúÚßT±Óx~# 4±*¥_Ý ÉŸí"• $…óð¢õò—]êHB.ú'ÌõIi~Fó*ñ#­DñD]:õ”Ðnbæ½¹XmAýE7-P‡íü±Ãa ¡\»c‹~jeÐåÌì9?4ÄCMÊ� ™åbÓ––Üqc]4»ÃX°¤ÜJMSŠD˜Ä$ªÀ­ÐAÒð&»kœB—« ½ÚF_Dö8G_4ô"µböÃe?؈\e£G¦Ç�„“E„.(À+ߪŒD u8fO‡)ù¯«ÎCÝïr¸_ÔÕ®¯ö›H•æÁÌt—�¹x—è'FÕDµ^3"Õ=n¯¦˜*’âÖ5Ösµ2­¸’†Û>åxÉ¡Ú{@j¾R!½ç`C{¹ìC�ºIâqiäD©jI ”ö á„øNi„vž¼õ¾¾%×ym¯Ë©¿o´³âf|cþì8VJ °âEå·ÿ�„ꉧ0<ù³³hTÓéS0C}J»àNp—î žÌOgÉçµ™ë¬!$Ð…wÉxóš!«{ûÕx«‘Ûe«]½sd‰¡b^øªÅÓÀlü–q'KÃ(´‰#Ï¿9ÌFˆcId‘Ù…ÕnsuŠù< Üò¨*_»W¸l§ñµ±/þT¬¡‹Ÿ"ROäæ‘›X‚9óÀLÊ«“ìºÿÉtbõÍ3eòÑõS½n1ÊPeØsá)óîö»„ @ÓèH•öGõs>.^t¼ñ‚íô�ý©cP¡~ÞÂ)SØíE* v%myg"\)G*ǘ _Ø ô¯D‹°üD~ °Á'cÈ/xÚàò²y½O¯MƒëguœSŸcBÞ�»†^úÔeO>E¢~ѵyâ}èuCžÍhQÈ?.MöCüpvåãK›·/%ä\ÌkŸ YÑ 7*BõÞ7•ÛgmfÚ�êïð€H¦Ï†~átÕîç$³;=Hcƒ”BB£qá¶A£æ\·–‰^œËWé! ac¾ˆ$„;ß]¢˜­Jy+@‚@š¨ïFûL�ŸÅÌÈ6æ©~L°tê[„´„5ÖŽ‚Wš3“à›ôQ†­È޼ÖÙ"…‘n€7J5‘šÕswmvÖºå˜Eõ%ÔªV! ÑJp¯Ö†G‡žº æy¨dÑ`�XÜϳó³R­VCÛ¬GŠwÞ×HÄC;ØBÞ9?3“ö|[ý—�•Ñ,ÿ½H­ã€šMó‘,V纓±öm…®”^)„óñÜ¥/)ü¥CsIP©+}“riõR”à Ób–¥NÄ= ¨g1(ÛŸHàûŸk×µ•€ûhF\«½ä¹ãâÞ�ÙŠ“ð9´±§ÔhX¢@¼˜qóë7 )ò‡�PŒ‰»‚<~–ÑÚ&¼Ä¿Œ@&œåþâ�UTîûÌÍ&¬eÕá <­è6|È¡‚w†Í¡ä©1ÒÙ„å•ly×UòEò5‰®Õ�¼}ªm‘"â‡kññÔ þ�ð=2tô�sæÍ޹%k›åi·ÜÖÈi f2H-øÄ…ùúµ¯zãOqo‰(Ê~Õ+¶q„µ,F¢ztªh}!çè\õÚqÓÓdM¸«F.÷è軵VN^œM27Ên"ªúT¦n‚©ÅH=ˆlÈn²S*�Eqæ\’æû�HÈDº5’/&Àô¾h5çÕ–ÊŽ;µ'ݲ<è—ƒ:ûos²+"tÆÔ‹þÙƒ}–™N�[œÀê<Žâ žŒ“ s¢i¦Í"³—CZí¾‹W*âM½Ö쀟‰•%ܰ§JÕ³µp7ñx„ÍeøOß™o5|\רL “\+ùÍçø«ƒ2‘zsŽÜLQðǨ÷™21ã°fZ/Ä®ï�E't–+àWƒ)E�_~£wÇ! š¯æ^ïÂïù‡ä =KF;™L`Ï�Kw‚;�ýÎÀòÑ…héÌ|@�‚š ÚÎ×à¨"6MâC™/n¶ÜZå ý€KàŒŸQ–ËUªQ+wž‡Oq”þ³ó•Énƹ•øÂ¡?íT­®­Ö¶,Fc:£¯2l†Ïš¯ÎA±pë§nšŽ±®vŸ×Wj(M»ˆQ=S„eaŠ5…ja¦»ÚÕ^qtÃäs•#äM+¤‡ùIÖ¼ñb˜dM…1šM–$³¨† «õ°}âè`Aþ-€á·}‹û¹jª³R…|âÒË�:-GͲ‡åÄ“ž6±`å]�Œ]5õVC}®˜¥� ¨ÜU¶3fþ½ØåX†dø¡„û³¢²Â"þ‚³bª2<ŠõY»žsø Z`fMR6°É~Qp…Y¥Óc_‰55É=|J@Ï!u ¦Û;”’¾Ò]ÍF8 {ʇÇz9K ç¤7G; èJ¦‹üzXbqºÙ_CÖÎx¬Éž¾‹¡ì×½é` =,a ÞÆÈ,øævl€–9šèCmüXཇ ÇêÅØ£ÌMrö 2<Õu…vuh‹¾¹cŸÙðF®ÇÉÈ—&ѧ–À¦+œ3`‰5:âl¢äBa–Yþ  ^p�û¹(4 Qq|¤1ÆØh\½Üt!u,ª €ŸÚ O¨} /m³KÅZº´_ÓsË£#‰rÊ�¦Ëϼ»¯¸c�°˜ ¬¥aù#ÀÇ*ûÞ íQ†Z½·�®õÚ± ð* F›é ûd ‹3´šùÕ;l€‹u¸­¯h*"œÍÎê™èGTÛ­›­}œ8®ïðî_¤X“!•` wj!°é² y²Îó„~ Ö?Q¬+D•Ž � ÝM”¨.šbs–íÚ¬�vEY$^Ь–q‰ú°4Ë5ÃSé“Ñ¡qÕ¿ZêGחŸ3 Ñx©Ý¥‡þtçŸCZ…cH[1Ô@7I6‡(¸IŠd‰­*s¦®K¤6§UY×-aõÜ`áœý�8Îöj ¶µ3²«KÃf§ÒÕÙ@�×&�%'ðŠ«±j Ê)Ú1Båm0ÁzM•ˆ Õï‡P„‘€×n›#Å‘aHNBzDNu8ç/Ù˜ì—G{ê3†Í²ÜjÄ?STä�åiE¸i_¥ _ߊJ¼Y1K% �݌ȸ‚9;ýxóë�ÛÅËßÀf©âFk½—}Ô�Àxð #„¬ýSl')YÁ²S½ÜæÚw«_U¿% j †¨êö.7ÿBÐΗþ9(k[Þ\SPX2~?³ä(-s1&σ½ŠI $>þRËoÆRñZšIFÃ&ä_öf…s�Kp«“$™‡D‰ÿ<‡ù§‡®éÖ�U&ËÛcV ²ŠƒÎmyþÈü’c"ÖÆL¦Äb>¤Ô¶Ò¯vî3\ã㽨È-ì¯,Î÷l‘†q3˜³]-N‡÷>Hˆ¼‘5¼¦ß´™÷0WÀ§Ýá¯Â*Ǹ-ÐVLJ Ç‹4€Ž�f~ùun”ÁÇÌ2YµÍk\vAÊ%,›ùÞ™ ½óÑé¶üpÍqÜÛ;ŨÓéàv ™)5—ûjO„rÌûGeË+½YÜp9›i2#s²g´OTiáe]i3[6|´ƒÄ öPIk‚7î¤N0³õîçc~AðÜF¾µ‡ÍbXYÙ9ŽÊ R¼§L¨¯m‰^Ùv„plŽá’Ë9 GHlˆtht%ôt^,¿¼S:3º”–ÀÏS~â 6PÍükËȯÇ}Ôßô>©^’Š/Ä%ði�‘[Î| ã¸U{‡ÇÔ½æuA2­è ÎâÑÔW3µSºáEƒ° ¶EçFþî ÎÞmàÁ+ÃCÓ^ú×|€�.ã0PC6õÒ£Q;©+c.Unòá2a>þ¬#À½9ðýçÏ9dn¼Yà˜u–LE½?mr>�‰PĦD��è,UúˆÑB²„B>RÿÍh5FÕ^àzÀÉ#õæS=–-8:øHõTÜ¥1Ès#ÄÍsÄPO±±ý÷Ñ(¼•ˆ*ÓDH9«G›ñi¹Æ:=³S`8e¢µ„{F�°—V§Pˆ®§Äßr-„åR«°}º²Õ…)‘ÔϽobEö¯Ÿ2õw©€Á#î`±.hö}–E#Ô/þàCéKß¹ øŸ‹M¡qsÿù$;¤ã¢"î²ä‡"ЀàsÎî&†!ë¬o ù‹Co&®èSòíæ½í Å6ó†¡ß­‚êĆÁ÷�.Ÿ†��W#·MÄŠ$Ò79;*f³C¥Ì ŽÌÈ÷zšW�ù¯pñÿ²úÛgÍü!ˆå§ÖÕNËšz©Ríüüw1ߘmœ| §ƒ("Ï›<Žu“(¤LMðtêѺÆt�°‹ˆ€Ï$Yå~qõi­NÛòGÛËЫ< ÖÐlëÇW™¯ÚçÑyCÅTã¡3¨ ,‡¸b1¡fºýÒùyÍF¯­«ÔöMŸPtÑ*1‚ô¸‹ÓîWþò<à!õ°_;âò#[³¿6 ØoþPô¹y­XfqYȶè0©»&-³<�`òOµÊ,^™Ît ªFüTëö�®îz=ÃBð7É×q‘¿÷äXc~»&–‰Ha‹ ß­Á7Ǫ€Å¥aÖ§ÝgY*žohøÿ¸RÓÔ¹�ws¸5Û’LÙ � ¯]/Xž(³e¥M±k¡?kï€LÏ¥yÓù÷Fkí¾Æ+7¾á�Û®ˆ½êÎÀâí³\ìÍo³"S&“&âUÀF%‚6°”äRlLÂYYa’Õtk•yËhœ²¥5â¯ûpjÆB_„ÆÉ:Ã�×ÂvÛµsÚ�ÿQ$MKkЗž „œ{dʈ÷Æõ™M3oîþ¢D3&‚-¼W— „æX³ß¾cmÊ…†'˜œ¤�&oycLWõ|å[¸e5L ¬n[º}_û\ŘÒ%;-a}ãû¿W%éÍïËBû cÙt�ºùg6-,ýj\Ðwzà*±[Æ|¡Á�ÎVBÿõ•æEªÓ­ZJðñ×€b9Mä«}(Îú[sÚ‡ÍædeÓ¾Èyq²ªwÝÀÞÉßztõMüvt¸gEŒÇ—½%ÛÌ#© :y†¦Å®ÔñY¨I ŠÎÕGœš¢­G£IìØ š… êcѾo0ÿ-²ÃÐd’HiÔxç=Nâ¡z‹·Ñ†ÃŠïf"”È¢ú6tC9t•ç—ᯑZÖì`]”©Ôü‚mæ�Æòtªs7!K8 ¸³."›:5 ðí+ …®}±¡çˆÚ 5Ái`zñ¾«ý"¨Û Ûfõ|“Ó&x1~Y*ç4õ˜�-é^Ð�ÝjI‚äL £(ý¹“›¹Ãá ¯¬t²€êjäáKK½$«ys_%¿žô1Å–ØŠa²§«Àž›§k?Û׿æ? $¿ùE·óGþX Å%I �)œlÍ1qÖ½2±„ˆ�žG„úC 5ʹ ¹{õþS ÉbËBÊÛW,ü¯mÈ©ÿ^~‰ÖÙ¢À�œBÉb`aM,·ôðJÐÁ¸·ä&—Êöï}fÔb^⟮݈ø�¿süÏéÅm— w4Ê‘ëI¢�ÀHSFåȹ® ®“8›ÿ °j…ØZ“å ,å¡`ƒjG‰'2š6\ÅøÊUnF\¦ §)¬˜ÙcºEŸL®ùÄ;Íÿë4l2G«ðEÕ×ÅÇþ�dËÎ÷¾Z‹�Z*«ßÂ3Äî«ä(?Àº\r SN\&.ì?²�¼D’‹*ìal-âͦf1å§pÖ6#ƒn4’™o`¯µ”âê“÷ú\4ʸÞ©9o”%*œØ:…P¡+â²Q»"šp1¤S²è£ ¿óEéW›ARþaþèõMÞwí-`gNI›Líxßï•�cȃ;$/#­žœ´ƒ�d�&œËU ˆÌëù‚û( Æ `H'”sI“ªÂ1"2¾0‘Ãw¢~#Ä•�a'͹•A"ŠÚ¬Æ!Wà·íUZ¹ð&â9ûUKG¼* ò”-6‡Þ}r¢ÉØ‚ .àº7˰¤�ôFR²H‹Ö6x%¹'h­íòåfÈ:Œéì1,@r¦#.¯JîRÁöm�Ô¤™2ÂÈ•¾ÑËž1ÀGaõ+è(™B°KGk° ¾âón-ˆÏ™ýrB¢­¢G ŸxÐg¸ô;ߌƒÿ,né˓47�N£ÇÈå@«Ù=ù ¿¬žº«B!ªª¿ïnâR™Þ‡[ÒÒ r?£þckì@>IºçwÖclkFßGÍ�ET™w6qj|Ö0�JìßÜU“�»¸�Iúøá÷wª€ _½ ˆ4ÿ¨2c–¢ñiöÍœi ÚOúCÚ ÍDC Ʊçâ˜õ£¥@Ùà>J€†)Hd�x”Nô*x½ðx,u½uªÁ®š�$ƒ=�“ÜïÆêLŽïÏçe@Êæ;€nšÈLYB~-¶ð‹A(u*5‚Ï–A9þ¼Ð½ÒI­-~'¢t$ÍìÁeZ˜«CÐ,0Í¥+/¼üY •à}dQ¼� Ü1ìªû˜Ûš "Ò= ±˜ùPxN·Ï`lH†#÷ÙÕƒº�/­UšxïÕ¦jÙ;ÉCì'nlÃÚ!­º ¶ûÛ¯ß& +¼Ý�«Mpß ý“žù_Òkrp³: øtýÓ]Ä{È÷’4 [×ú‰ÙÁæ:?h÷Â-^>P�èªÕ ^éwS{UÍšgÇq3ð[üO[�n ûb~Ýd2ÆÕ‡V':þëcU]\ëv…¦ØL g:1Ôc©Yðü㊠<¿NJ9 âHÛ–»Q;i‰{ �¢äÜX9ëåúñŽ(sÒD�æ’ _ü7°Ìž°w"gUä!Á@²Û£‚Qðž¹~…ý¦Ìë„…ÑÃ…Äâ)òÆòPu ,Æöý_}˜ó¸føò=�•z½Kù‰¨ÙRÔ å:0¢‚§±ý²ñÛH�© e-*DdñeRvåØ#àzÏC6àœb¤Asƒ^S¶ZœŸDß_æëh)s‰ƒ¨žÒTMÜɰŠ@Í < Øs?{‹Ž›A…ïŽ, Ú»C¾@¥¢.ß’@-pµÖÉÆ Kâ™Â®’û{v—OnQùõ.&›ï-8âü™]` +NŸF=­^æçÛwAÿÇLç”:2ñú”Ñå ¿2 ¨®ÖÐkL4 °,[Á�;js«oLg÷,>Ÿ*“€T^VN•™›Š¥¯¡ °¡§éèT £ûfÜÖT0&4ð0Ó&üØ¥HJ�©ù³Òê"‹+¶*ñׇx²„ºÀQÂÿ¿7¿Ì'ðÈ %äD�jìâC7\dñòFS캾�”ï¤Lý£Õ»ÆÊçÅða»j–8ŽžªsšÉõèÎk4Þõ�aôdj÷ü­gXÚÊ+=Ëžk™DÑeÌU|™ýo\ ̵3÷ÄùÄ; àˆ(—só;v‹2¸¹v8:ÚCÀš•Ñlx¸n›ºSm»0–oÞA˜aöÖ`I´z {ÀA8_ª&{†¥ÂÏ!�Árq¢ ú⣙IVÿŒâ ¶¸$5…¯-ÿúUZ]ͰÑf}g ›l�m½:Ã<·ø–t8þ½I&ÏÀ.-Ü„¦ýv_5Ñûe§>ó»‡ ±UG8Þ-ޱl¾@»MëZ ú†ºðC­­ï4¼�F-ÛÓfL<¬Ö€°q­âÌ;VÝ›uO_…{w$™�¯çhψ;»}†´à± uí?iIú[ŒG̓¹KìlæT±åÎ2¾(—/nn€0 ¼+ÿP�†¾gúÇÿM¢]Bð>ÏŠQÎŒ4s-ݨv:‹0P~›ô‹ÚPÉ·å v¤�ïkìÚ5™-5ïêú3#z.ý“X øx\¼Æ@®TÅ*tg 2�o ß�íä�ÒŽöe/si)–òÓÇ×} çºá'áh5kÔl¦@8èZ5'¤(ßšÒcQ„¼L�—{QgˉÞÑ,†6»_Ù³ÅSTŸõ–öÖ Ïlâ^DW–y2õ¡ÉƒºQóuˆFömt�/L[TBüp¥AWmô¸}1½ãIã®Nuq þ¥eïÒÑ(Ïþ(öò™ý?:›¬�#ˇ¨3'Ûèüxh„AÖà�7–‹÷M|€ÖkCL:]›jüõg€u,‹HØ¥]¦}ܳö�н9·ž˜v&¹R.zS’c›Ó%q@2ˆ«†L�x¤�×+#/¹¶DÁëÕ*Tüíq±¬)¦­^wÃþÎÞ>¤,¼6G=2»B8¼1Ì•âœK¿pà2IáŠ^Í Ž!ð]°âªJc¼GÒ—|^œ£©ød€¹„ýIÍ–úI å=ÛÕRÄlï�FÂ!˜ÎR�ž•$"6ÔLÕsi�Ê}|"'Ä�~¦m E¦¬‚¿‹é¥/ÑŸUá˜>ד:T²ND•<*úÿ²8`,“ñ”¯¶/r³ËUQu4ŽÐhE£³ƒÜkM‰Î_¯@ƒX1-ì? ó’O[ùÛ$Ž*™‘VRÉ·ŸË�¸Ó§G¾ªTc¼¹¹ËìÅsò¹hc ¡}u~ßõ^V~Îrƒ²yDÿֻ݇Œ¹CÃꩆàmÞHÐ8Ÿúù—úpAöý¹ÏEåÛ Ç[ ¾tÆ 6¼þ[£ïÀXŒŠm~Jß¹<¶Y޹ûìàíÙ‰ó±½A¢ú8\� rÌsЖ¥Áäõt%]YtгTÞíØ¬þ�1%¾™T În•b‡ö}ãMݱ•Gü:3®¿A/ï+àƒ &›,J¿¨g¢yMZÙ³q6ƒªR>£½Ý!åÆ ª–~ —& p]ƒÝy/·}¯ýŸ;"v,&õZdÞ~'â½­¼ÛÌæHï[‹b¥«@´C,»‡ç1 ÉùÆq+!w=°ÈIŸ „Í�¹þè¶ä•ÉÔ>V’×*Àï"Ky�`!�Hö··Y;ÃúY1?’r¡I $�93öOÓ òš>òÿ�vh½0&äÌd=£ÚX%!‹âÇ·ôÙôÂ)ïò@ÇÛaìP�ð8Þ)iåyÞý0Ú'ÇSç›tò¨ÀÞ#ÊÔ×zmÐøØÔ3ç“51É+É­vÍÐhR�¦èR'UþVâËÉî-•pZŸÚµñÍÆÕÉ:Fÿù·v‚…zŒÑ`pÄwéTÙú„ÎkÁ¨¯GÖôkÀùð¶„‰Ž q¶É¦þS¿£ŽrWÆÿÖ÷SÏYº�JêîA Œ€o/¨ÂG~6TæBz5ƒ^?Eq²Îèü¡á?ר~�-æØÛã&²!6Q—ù± ¥>L3’ª¦Eÿ×b’Hü�TlÃ/6ÃÌ„¨L:}Õ˜´¡[ \ß~³²;à}=Ü\;G_˜ß£"�}Æk×K}J:bÝq0#Î~ÄÒîípúņÅ*Èt[‘9{öNj¸”Íû0ª¥Ø(ŸW=�ÐçM»NèD;y7c5ºãHoœ>‡õ6…øõ'{¹:‹cä-~lŠÊ„Õ$3Ôtf†ÏªÛŠOõù`cË–T`÷õZTO-fæÂžèÏ€L;>¹¦SUjí:·u½´ÒœìÛköQotàwï³w�Bpõ ©2ݿχì—õ ™¢€ÉÝIã #U_é‰âT›@2£¯…‚•—¶FB{­ù°E‚òÎ:œ¥g˜=*7˜ƒØc”(o÷ UTÉÓ¸G/®(qOÍ|vúqt5Ѧb„ 1Þ¾÷©|¡�p!sèšqÇeNöA—3<‚½[Õ’G�Œ˜ºø"@EÓôuS&íï�”Џ›!@–„ËjR._Ôš𤹵jñÆkrƒŒúWÚ: L©M4%êè¶\Áe@9Ó­Z`9F8£Âg»±x5Î|g@Ë:4i~$ßMî½A¦‹W_²uѳöa.Ÿô1t¾ŠÄµD$ÌÒ�˜}B�÷–ù›N6JèP[ ¦fÙœ~öCÜ¢×âšß÷ùûîjf­�à!ÌkXÅRD L6s…´ˆÎL0–�M¬'ØÝ¼� é b„éL>Ê¢˜Æ¨ƒë—AŸsd”D\'ÿ^=îÝ¢&Lßurf0’½¦Ðo<Å£õ�ì1úËªÔ ¸’�ëå¶I/üJt‹Ð‰�ôŒ+F9—¨¡€Í�pèÄNšg_H$TÛØ£!ˆ{!xÞú¨?‘êv`0~œ ûÐr‡›†6½œ>l,k$zÓ2Y‘ª\Wð^Q% w &E ëþ¸5*É7íK¤NB7yïÔÒgÞmʆÒÄ#Ïý¤Ï ròWð$à»TJ‘±…¦¹Xý9�é- öÝ~§.£5Ê–uTžýj¼Pð•í¢MÕªH�®1 ‹;†Þ(XÌžÙzeyÆ…y2Áz_òÛF³TM¢�› T+ñ+Üö€©$ªÑAËÎ`Ç%SÐ8¡#ÞúÈë›"²�=–�]=K#$µ*Zn?H ÖÄ~Å1–¤‚%«F÷ âã'˜x¾g(þür{^��ĨÔKÀÉ€Éo© "sA>[ ÷×à—ï"`XJmIL¨GTÂkÞŒ·x!t𜟘 ßwåz®§´Ô p©R¶u~4±{Üp�ˆ˜ƒõè×ÌrÃèÒdz~67ÕÊ#*„Ej1 ‰²Î$§r¼«Ø€Ê-~èeŠô‰Å)¬ N›Óh˜4Og#Gêº!à,;æ¸fLM—Sl'cÞiÚÞ­²Ž¹ÓÝíx¦¯E©Ã´zƒ: EkžgŲÿ+A’„ÃØŠ™Ý4d‘'áÐRª s“�Ðë&u™‰ó›Ú¼oZà8‘žñ*—[›XßÒ…¾€÷xFÂ_Gºm3eha¼�ÍØdÀ›ãÀyš:äOYˆù´Úl°¹t‡Öo—ðñú×[ ©†$4ß Í+GBÆípOGõŒ.aA•Q…L¬=CÞr|Ì&äd)Ì�!¤…ù*�‡$Iéèj#©àã€!dª¾Á¤F%¥–_?`š_À 89»»ç$:å+‰Œ=!Å–å|ØçptOÐÑ] �”�3ÚêâhãF9Å â²�¶VSŒ°Ÿ`aé½Ô2Ï:¾eÎÂæ.I¹`ILÎ`xè§9¹*ƒ\SUö��tkM;üA:;½ì}@€å+²í°Pýñ™+îªmnºµ²Ã±5‹óüÈ0«7ŒŒÙxϰ7OâZ*÷IÚeðØ®°#ö~Éq–ZÅïµÓèñ÷%)vJ}•¥Eöù¬{´Eq'8Ò‰Ä!ù4·÷e$M-òê#êkÓÇl7ø·Èw,®î­40!¿Šãäsü•/k¢º[›S¢Uo£× ú®50âp¬=Ms„±ÃÞ©³O6—Uce*HFµßYŠhÖÜý“J6�¬Ïv•sXˆ�SÀ ûÌ=]| ¾/9™¾2Kã3ã÷|ÒP ,¸µ2é~O’g³‚ïyƒ÷B—Õ:ýÞbÂД«uûUM|OÓšUö¯Ñ¿g9ç[Ô+a�’>'ÉoOî6ÈÎéšBÖZµ6ÙÛêÍ�*AHèdˆ^cë’“z8ý Xntœ»¥«ä˜{2\R?Ïf ú)Ç´t ¢I#€0:ÿ%¸NÞ’™ÝyØö ZQÄ$ŸŸBýié™�CÎãCyyVîÐ6ìÐQèË¡Ó5gŸ’iÿ‡cèÒsâä,blA,ãÄ0=É<< ³—8;RgdcBR8|úu� Pä‚ýõoÃèO‚ÒÿíÓœ[€ý¯åƒà|<%ÅXÈeTžžÞ�¹òýØ«Á2RÝÍ@5JZÜ•e=¦ßcxÆk¡”?Byn“=u¡êIó=o…\I<æý«»Å2–p`Ñw’ÿíØоÑ€¾†´r¬:ôY'™ag\Žò%턉n¼"qË+°]”ä¾:ár»+dE… Ô|önáSINÌÜÏ®·R*žƒæ6j|:S­î^ŠèÁ<%sY+¯£r,0U¤{Ëà²æ+4îP‘hQuú°¢ÖãæDë­& ûù\ˆÈ:x5Rèÿzÿ ÀäÓ¯çÀúä€�òŠ $Û5frãwgYôWCu!¸ XrÄf×kêø¢¤|:ŽCTæ´ç}‘夃ÚßSÞ�»b |Û8H[RÕ:øʹnVI¨½\HëÇzéi/r‡[é+N»–»r uÌÐp:ý(.@‘HúÍãL)‘-Sä´¸¸ˆƒEÃûu޵ÑuŠY{@.9= ƒ²U„a){BmaÕ+«wÒ$…bùn¥¯¶Ã¥½&¹Ä¶?�€lÿÀïÄ(%}–ÞëQë× ßW'ý¯7âPЗLÀ¡nï½bÆë½±I½°¦Æy#Îj”C3{C«àÚ( @ ³C8U&¡TB§…ÀPö+ðknÖÌé'ÇØìè§zõKÀ1Œ÷pH—˜Q>v7åvªa»išMÓ{ÁØT�å#Ÿô*ܤ x÷i\p¼áåJo*§µ ÛV=¦~Õ-oJïd·"¦²K·ªk<ü|?=Óöý¯ÜËWµå<.‰§h®l‚ïqd£†�8 JŠ ³IÙR'R©M&'0¶Ý¹ƒÓ¿˜b_WµâG‡›û\â?§5Pý$\glMÕà»ÛÊw�‚„¥¸^5XÜþ­OÑCþÑWÆÝEo†S¦1��¸€¹ÝÞ˜qyVqö±sn�%Hvs”§pZÐøÑ_*ñ™×D æû5Î+�tß9Õ×wˆ™^¿˜±ëɽ3�µ ÎñÕ¾6ðôb¨Uƒ÷ß+Íëó¡Ï©¡ŽòÛÓ8ËÜú;UÇ𠻯E†)@ص¯ûΨP‘ˆ#u—ø…â‹ñÌ]zÀ\Í@ööóIeFo‘@AîÜ�)1óÛ˜Œ\P"T‘Ê ¯{Ôi¹«]ÊÊbÃÒ¹¤ˆ!ÄGÆl£_t±¥ô®C&ñM/º±x¨±+(2£ÚˆñäÌaáAQ´‰>Ž�ߊuì=o¡û±<¸_Âôy+SÈ y(…Šåè‹»¼ÒUÒ宫I>tuF9#že‡4¬¹y僛îBTuç�[‹q=ÊfŸ²Ñ‰`tà{™¼·A©_IsÚòÁôèà??�c–¹Ï¦æÖ×ukÞçlT芢jCŽà1á¸ÿW<½Y%3EÓ}Óª…tÛ™×éëhG4uä+ÅÖˆ\?6Û>¦Ž�¥zÓ|`ÚüwýW–Ñ{Ëc#Ö “u\yzÍ:Öæm£Ñ3“”Œgë˜íÍÝ—ÿgÛ!ÃÅô*EÙ3ÁŒÌô_’9�Ÿ.* ÿØ–ëäî�®#1 ò÷MX ¬ÃÒqƒÌȣ˱ç’èXSõs1jàÚ™ƒ&pø ~§ø{’àIÞˆý•aÄfú3�ä…ÊEãVü‡oŠ›?4ÉÆD×�~éªË‡˜Õª†ò"·žÉ懛z�eKùc¯!(a¡ñ•ŸOÆaRÚ)²ûÄ›¯ÂÊS÷á5¡D÷¿NSL鵪ì.:�>‡kõUýäÈ�0òOŸ–ôÖ@��Çݺæc«I‰Äɼƒ±g\eï§MñCøý…`G]Ãj÷=šn&u=¿à¨²h§r|$Ü+ê}>¿¬pFˆÅ•XwZµ<‰Y-‡F—™¢|$ʼnãY2ÙÆ@¸é*Í.<¦ötÎÞrhÑ8¼¹^U¬*~•qÅü@ÅÖT�<:\¦^00¥±ào*Àþ«�ëÅ#\b31T¦¢øU¢9ü(¤@+°?”úO�ÌXrLüÓ­3Ó%¯0t0³è8jÍÛ¿g¹]!ÉQØÐr × ìÀæÞ=Æ"mF:ÒMŒÞ`꥓Ã(ªÊ¢L¿n]¼E nŽ�5™¤gãoÖ"0iΊƒîs,ô¶áU:öë£Mj^|Ý“G»¼"bOf÷_îƒO Ñ]3‘™ÙeIÂë€p ”ŒOo$¿H0¢/5íÈ¢Q¬¹®‘Ó×(à'�L^¾æ�Dë¹�eyöÊEò’¶ !àB'&ô—Îc´N}dëˆ2Êãt/š6I^µ8QšpÄD7u·IȘ~CÒq³‰í°+û~Ÿ-š1Gn‡ž�t0ApÛ�]bÎŽW°Œî¶d"Ìf~wV=�/¨†[?ŒåÜÐFL°#PÇ:Ф©/Ο8Ά÷±üüè'�ïu¸ÅþÕ*}¹G9k!ÒÁ@½iÒ5¹‘ÆDX7_¡'[U£Ëý©G�ù¢,/ÙÛ‰tƒchXC‰„vX‰rÿŸ·=1¡GrP}ÂwèqøE9–«—NmÞÿ©”N‚=Ô(OþÁ±`7…%ÑS<rþþØO}úÔL$…¾6;ðÙáµµlbmK­d3b²ti¹paTû¦�€:ŠBFùUvóÞƒøB_}®hqzY¢{t½»K²~!w×�§­&÷�cº».{ñCŸ Ã>m}6㇠öóî ò”¿ÃŸ«‘íóãQ6E °r’Ê¿þI‘QÅþ½4Šp>®_ñ”ïQ„cUÝ:² ¯ÎÏÝCE± ¦Ã§sA@~H Iv$Ãüx'tS¤8"‚VÕòG\Í“/õcQ€�#@tn¯­ƒK᯦¡~¸1ã·`BÿÖ agÕP¯i‘ZÑEêL¡ayüD‚¹«Ë2eê¦Ôý}‘ dß’ÛÍ[ao4é©Ëa%§VfÏÜj¼ïK ÄO‹ò²ÀĬƒJBjÌðép V´,.6k7á^İ6ЧRÉüá4úÃñmìà é·º)¤m W‚I Yõ,–°@錯¸È/Ô ÇÜëL!ÇìK@¡„ -¥ÜGòÁÂ5�ã^A—áömtkõ†}¾Ä'è§ÐQ´à™*±X:pc.깤*³DgDÓEžwk�WGçå^ñŽFá'­t8"}–}Ø ¸&êÍ©( @’ýAv·Áë= í#–¼3�_)÷ï�š_öÁÏ#˜<Àæ,G¿ö¶ü$�¹âÒ~�eUOÁßÀKíí<ªO™Quà×W¬ôÊ0AW~Û•x<€QQ¾Èn¥ú (‡ô̵ÛjÓïkr¹-¸—ð¿—0íhÅá‡í©Ãßj2 iI2¦‚€j­¡íG壕¸šÉ<Œ›H+'ú| ¿ýÅz.‚�ÃÝßœEb±˜Åìiûf¥�`,¯Géø±ÙôŒüpWv…Û»[†óÃÐJ´d2 ̇ÿ6ß³–·D¤ç“Yj VNѨ—mv›ÑXÕ·F.è/MÃ<ö¹ßJíæ`À|èC°X47š^I³ÐÅÐOçy«]Ȉ#¤' ØØ}ËÍ„Ÿ¶nGÿ‘cèÎ__grЀ¹|!Î V¶Ë€.U«âïß#œh,È·ÁïÁáíÚC6ìŸ]Ç@ÉË…QL°]B9­{-ìŸx�³2ÿÈ=ͨ$-Qøs¹wßâE(’ööòÇ@Ò•'ד>W’’w¦r:u}Í&04Äl ì‡< bï+À·ã¦Ù’¸™lÞom»KÎrOb¬NIðM�4⽺ë2««•ßÝ¡Ûk¢›q5»ñ—˜ÏÝö°ò: Ny+û»Eu;¤Å¤A£ {²§¦ YÆdQ¾5¯2$wj{� K0n�ÍÄ}¾mÎbŠ¢/üŒ%»ùššR�E++ª¸, R6µL¹–¨éo±bt 8&¤ÿ�•íþç,æâlxwiÇU@ »¶.¦ ;ÚôöÏyx­M3ßG}9—Ó(á9ý‰ ¨ˆTÅ ÉÎïÆeò*X©„Wü¬$éѸ/‚8¦Œ=“l 7LŸ è1ñbaþÔ?{EÁà­-A›»¨\¿®Ǹíï=zbí¡(š%Ù�+«¡Õ©P�~•ÛŸü»öEÀ›lz•jÆ’bv†Ð1àˆàýÉ»€Ù6°Pçòå—4³ØFÅà[eÉJr¥×®_�Áï¼$;'.nnÛULץɄÈföm„c´GãzÿÑ!bAÖ/„OËýݧŸ°Šf�‘Zòý€fuò¯ªÆbæÀÏóƒ’äèážÛoôû5ã 诊Þîvf¿ÄDOE�µcg”?—)•`sКP™tÓôµûñ–=™9°h_Ø:‰ù3{´òš•L3ËðÄW¨‘ãtb,v¬óïøË¥ïCM¼êå�êÆgÒu$g}F㣤5~êæÁ”õJü€•cŽæÈkkŠÌòÞ�S>äËäHÜËÚf‰ýï˜8ú~Õ’–¥”íÊfª¡}¬+;&m–•"k§�A*É4HM¹^=l[Žq_óÍ]&~ �ïë¯vG¥®¬u™+i\øÖæ¸ôâ½3ú«ð€ÞÉšIr{èpdœ ¤©ºé1•x+7Ê‘æ6ôw�}uñ Ì$åɆĬ&>Òÿî“• Þº·óS{Ý ¤É_‰èJõY‡úàÝÚVTFä>Ov ÐÜ(¸Ã ÿ<ëI7|°p¸•Kv‚_^i·ôX–"ÎÓÀ¨ó¹Ì ¸—ûÕĨ?÷Ž„ïÈYRévn(ÀmßNt~8 íqFL,4§!YÆ1€{×UéšmÕLGL$˜â’Ê[*iÆ}Ø+—x ÃÝmåSRóaÞ¼{ö<ç•6ŒïÖËœ…ÊžËÍdèÚQØãjñ„~ï7î¼X7°“œuuÎc«Ð–]¥T˾…–ËêšÓ5B…ë1yÇUe<Ê”X  QÌê‘F{>7’ŽÓF§éNUO"|RùÚ»b6¦‡¨ìéîébúöoÜ_õJÞÕÔi�ËÀÿܰQ5%žØ‰÷Höx«l{¾°+Õ#U»èMËÚ©¦â#e «HmävÁ·RáÝd¬{u+;^� ¾ßW¼¶�yòàá‰�%‡Ô«®º±ŒÖ*K2‘X®2™ƒ7A‡äÅäþdni%ÒBŠÈ¹§ø©ü‡t�Ûûpê*ã®ß^ÄYÞOÞàZŠ“�æƒVPÕ�veþ)7ŒwO4ýyô£†½ ÿ”ÿEggLag–0°âçÔ1œ–hwwV�£ ž2ÜèL¥Í¨÷<Æé¥¥‡�ðƒÒ=[e qP\Mê�¿Ìfˆö)ܘ ­_•�u:�×Pjn‚ä7Ü8f6~ÁÌà]˜.pÌÇìº2ä|ôàžÍ� —Ag=É#Nﺯæ8½›|Gu"ƒV6ò¸ÇÔyÝ äi;W9ì @³Ë%*IÔ¿¥=u?e´p»zRJñó@D~ýá¸ÖEºÔÝ–è¬j§ör®¨ ¿µpO²v“WpŒÝò¢×䳯]«¿ *[æ|÷À+Ö‹¥ 0õáBåÖçO¶¸?CÆö&©Æà µQÀÏê€ C__ÜúD¥3©4²å1Í“GNž·èl ‘$Íè¹Yu²1–¹¸0L­Z£œ¶‘S¯@¹¼v9…t�íOÎ Ó˜™`GÃË#×{·„kÅ0oL-o1¦–\\lu€8âMâþi9' Î4‰kˆ}Àh*xžË@úM×W]禞ƒd¾z ?Ó£µãvÎ,â,‰»~èd«dжñÎÕ]¾UõdgáË,ø‰©ÑdçÜ»`Qi’¦ ûq¦iÉ‚ÏS¸H SÍ‚6±5Óª3o Ç5×ê™psg�³4]À>×-ƒ;ã†HñN_¨ ºŽ†m ?1Gá‡õS”!Ev¤Àc ‘ˆÁF“a�¹Øu˜Õ`¢{1oÒïÍ'/UaÍ÷ê«DÇ•è¤T`ŒêÞ”b(©@ŸÜpã áˆC#µêº&¡j…»X¥…ìº!¢R—–{�o¯¬Bõ“6˜Sø¬!*¶añµàÌfñBÀ2á*&&°KáOšÃš.G”ßÍŠà!¬½ÖKÉá�^‹3a7 Îì½ïÇIçºÕsϪ, þ5Œ¶È^ Á›½_ÊÂ×�¼’‚fYg¨dQ§eׯaù‘±JÁ$¶ÐøJ#õ1.岡O•_G€×ÂPϲ¯Š ­µ%3…ú‘œ‡ UÎâzCîs±ü eç»3-¸ü^xJ ð¬A”ßî.Š€¿ŽX®=P{M€5ä¡‚§Ïh±\ ·5)>°•b~îœðš”UÐaâÊ`O=0½êŽ¿#I¢ÍÖ`œqJÞân ’D+5ÅÞ·#v�¾s3V]Äa”Kg­– Ì|Œ¨½1ãjX0�=¹¹‹XRÛš6¤d1)H8—à„š†X²ÒB3ùýÂ@MþV¤§‡gÌ+37èá´C/p„Ⱦaöaœ2¥z´ÖGGߥZÐâpÌ7ãÞ{ÙzëáÜÚy¶&Áæ1*‡íErØ)ÈýªÀ�Zã¤p#…~Zmpà·ê¨O¤‹“š%¼ù/ŠÑíâ’$w$–Q¥Ó IžSÕÂÁIuG×>ŠÕ‘ »FÄv·$³äîO‚wJIUñTEž�€j\‡ßöFýêËÎLWœ% ké|HñiOe�p±› ¯BCº'h„Î|@cð8ºåýã7ÕÄ=© À”¹iwmÝ»t¬E0¸£YtÔBBd¼i`s RWƒŽPwKþ¼º=ï¥`Öâqü�RI*-ý{ÅÏ*7•qïŽùµÉfæÀvÕ#=ôª”ºÙº|hƬËáϳ(W>5æó¹»Ä$žIsIA¾¸ì Äͨ™àÇÆÓÁÝâÇBÒ„qvíÒÉ%6´2œ,˜õ¬Û^IžIaÆ÷ÍþW?úðóÂþœ!Q¸�{¿†,xÕ2ógÚAÒòM˜ÃÈÂãa¥¬ãfG wNôžòŒ†¸RŸT[onbœÆ¢…:3t§@ž\êÀ?éFS·©™P6Gý“¦!™» ¿‰­ÊHð åðì%üSxwlŸè`hĸà ¡QT•ˆ¿õâ3LÁXD?œ r¼! öyß¶qÀ‘|ÈŠß|Œ­1.}Œq–÷Âmãßý>'ÐP @tD±~Ô0ð� =Ìö½œ}·Å˜û¤hç‚©æz!}¯P:W@ò[&øâÏ�ßRbý«v²zÔ] P¹DMŸ÷7*R`YóQ<4ì>ÁÆ1ÿ;¦‰Ñp°aäæt«)¦�¸>»xŠ“¨¹{@>ôÉt‘'©álÔ?X‚JYdž{§z Wõ·6¹g�b8t[–T¨Œ»âÇ–*)Y ÀÁ†/é}§¶;¶�1SuÄþ䨿×x®p‡ø'dÊŸT² ò+ü2·iDÚ‡ÖâI{t&èrYi^üÛg&tt0 /¤½ Ù[F­_7_¾$ È�¯Ï ã¼Å„¾ŽòɆýq5!,�Ð �ÉÓÜtÂ'8oû®xÚ+”ø«CŽÇÞKÆ�g›c(À¥!ÀÌ]<ö:â[�WÁó�v3ç-]ô´.«ê‰åí�þï¬m4u):ï×CûüÓ< ý[2U(9Ù&€QX‘„w»Ç1d J%(“Çf@k=HLí�QpDm/Ð(X�~fœ½Û&µ8Ým‡ŠBAѹ:êÖÏ ÕN:€‡E ‘îhŠ«£2©K³YÃlØú¬hÙ9œM*²gGøå†g�¸„¬­†ÕHJHî2ýü>4©u®–¤ÙÿëS°) r@.T³&šNŠÔ †µfrW:ÖSÊ¿X1<¨h‡8ŸŒmZF.¬Çý¿ ’þýÄíòÉ”jt•Ì|I¡zÑŽZ_‘ö4ªÍEêÚ᳃Ò4àUan� qí«M<Í�4¶„;\÷r°žag¹Ä— ”é£j6ˆ¸Ð:~+œ—›³®z¿y 0h<�ƮШÌ6íMÖj¦Möu¡x[¾Ü&‡¹QgУCòikƒ]ºθüÌÐN ’Õ¨[éIÈôœÜç1Y#í� ÛDôv8äø%ø¯½15^�?§s™ÕŠZ&ôsˆÎàø>@(²Ô¦ŽpÕ„Õ‹ gΠmÚõI® ½´j`Üb‚uå‡b‚xçªuúoë{Bâ·«®<…^~ðò½]øÊ��òz¹nª¸½™AD¡Í’ñŒ ‘Õ>Î"¥úµ‘?ûEÎ1óö€…dì4«¡D¾•7’˜X×vp/ƒµ�|| ðð܇¿†Â¾›«†Z(N…Ô¼[BDtd~[DœÞã�«Dg1%þDòƒI¥~u˜ ƒîãÎ÷ð�¢Ýf߸s4 ìô·Ê¾là@ŠE÷xYœ±£ñ¹ÞFµ@Å´mïãþÜ*z\/€. ½ã“[«sxvÞp‚ 1³;ý‹Nñ¤`âqöØ?éÆ ýË· RQ§=žêœÕÅßtÍ©>ýa‡7^ÃÕ³ã…:È·¶Æ „±8þwh3?i¸whâf¬ìñCì\¥å›yÞ´§¸ÚnÈm¤£ª)ã àÜ(~”–Âì�Dóñ­•hÞüo…W¼Sµàâ¡/uä  5<ÊOñ=ˆ$Ù{ (²Í,Rd£ñI§‹0öwÑc©l[7d©¬˜½r¨@}ˆsÃ~?]b8×_Ñ·ð«{HjúžAüæÑGßÜ.ι]å&êh–‚kTH©0ÊŒúŒç®ÜeÖa˜Ü#"BkÞ§bä¡4™ÈOtq«B±S¶C¡E¹�ncvl(Sªô:ÎOšnµõjr¡«Qhò¦>fVW¿XÖ�ÓúªÓ¹W–lœÍܤdÀŠ7Ï$kÉä[o.œ’#ç sHy<0ž ”ñƒÞ(�zÔ“ÞB ¶K{ÇçŽbÓ‡h' ½—ÊÓd}ê#…i/zó/Ñ'#L쑘[YíH�RV…¬Þ´Y”QÓ‚«HîEYœ½¢F º?<ˆ�P! ýÒä`À”ÚÝöö9ËZži�‹eã£FDYìÖˆáçæÍÄž;d£þmw|TU¢=©*†Q§w¸ÖÇKVé€á³`  MJ^sèÏ¿ý‘œ^æÈ~oWûÎÍ+{„ígQMòvu�°‰š§úPÍ¢—ŸW ž8j *  EÉXvìÄ@»ŽÌ_מ7oFíØ=<u6‡v.+ö°ÞLüÆ/ªÉ‹á!Ó`öwOBò²^–„ü6½ d ¥%iCýǾ޿ë*XË_[®Ô:#¿ôP4mêmDr.�…kÓXÆe™FÞ2MZCûÏ´îÌA"“hÁdÿ±ê§‚ËwÈÂüó£ÇV³$G!Ãÿ-£¿ë¨w)£27ÄŠù‰ñ§1ÿÖÓÖw”Œ.(|@—† d1€©84×àf�š«êÄ#êJX4:1â†9™Ÿâú8#;Œº -µ,ÔnïIâÈ)²>¤p[t—‹¹Z}}‡OI:šˆåƒ��{ÁœïŸB×Ȭ×lÎa83san²%pÔ L퉒ý7T4¤9­DÖŠ~lÒ¹HguŠ2 œ«%¦êOÁ,*>y@DA2õ9§ò«J8–ÚGán]…÷ñ,€}AÈ`¬Œ z“Gù¬­º••Ù÷mÆ¥c€Œæ!ÃôcÙŸòàmq_@½9;sÛ^¿+U³å]øÆ5Õ‡�É]ŠÓI‹1ÓŠµð¸jïóqÅ)ž·ù…ä/°äÓ{³dŽ€7·„1¦ÑØ­—4üfMp²Ò¯4î3?!à$’€‰?$šqh3RÕŠ�½?u…Ü·qÊØÊÍ>¤ X6r-Bš‘çÈŽï’™ÜHFõëÉ<ž(Y;Há€A«l�ÂSfS‡Å¥þ.~éže™Í&ÖN—ÿjA«ÿg¬"›=§e¬é»¸|Ž‚~Žtr FH™3�"G££Ü ¸ÈÁã² ¹7_;¬™-¶Ò‹3¥øž(Š>-§y懒�cW#ÅŸÂŨϥíãHu^@€!¸Þ"vSåžþë\dÈ×f~ÉÀ»ä:ß^|€®©8¶aGóÉçH }¡8 a|¾!ìC¼wGE @“­éS‰‘:»Œ” ükóÕ#=ß@e£óØ�¾¼"*¨ËŸI%2R ûU�Âj} õü9Ãôy\Q‚RSp›FS–á#Rç=qÍo—´ ÂUbÕŒ¦Þ…¯”Z¨Ï4oNþá±¹Þ,ß±ÁµŸë�\ML…e¸�.5AÇÞü„PÀ¯Œ¡QïÐ Vµ<wùLX\½�†YÐ1—®fÛo|ØûCüDB�„¬1òùFAR}Ž5ó©q ‚7¶øŽœõa™®¹ù®ÛØå¦ƒ‚VæöÚqÙ¹~:ëq’ÔðѺö”¬ñ¦kA!)a@í|" .‚e;’ |«¼æ(öû8\Õó¶@X¤Ý¡t[+û¶p‹¤WE ªä‘Pqác ÀPè]>h¿�«²äœH^°8”€´�t.ýùt¬ÿW³ø�_¸Äe „øè"°ûË2O›P)´·_?$}ï·Pëýz¸Ÿšzf·ÑÓbŒ¼®ÅSFI^OÕW‰ËA 2KkÝÍ[Õ°raY5„„Óí¹28:…“¤K×fðe© 7ɱôž®˜º›À”�®=³jd?d<ÝN�ñï\Aö_'÷êt±ŸOƒˆ¬¾qÎOãÀX¯úp^RÄ4PÁ¶V7 Ü+N°ÊâÜéq` ‹†šÜÛDg¢ $3Èžô6ºUo&-óRVIÞsYQú˜†m¡;)ꨶ7¯3™u¹ )sÚÙ5c`°4´`tÀÝ�œ½Ëv/ÝdUt-ý‰°Ÿ ´s�»ÐcyôM‘K4]{p?…uõøu<Ì£gu“XbpF¾]|x•¾ô{í <óc_‰.-ðþÂ~’0ÂW ¯œ�U.jïµ «ÆÞÚµ «ÖÔ ¹ª¯p~>B ¯V|4I}“x|ÌnPˆéÇ{6�ü° |k¤D`íÑP’ô÷ Œ1-é:¿;Ï øãB†í.û¦ÙDq–(°‹r òi\PO÷w%ðÁJQ'œc�fàŸÌ^�У¶êþB:©ïŠòGÖZçŸ ¡8tÍ ¡ AŸÙd”dðŸU=òÒMà7kêû•âëL¼Ïø€D¯I½n´;)t=26 oÖÈKƯ�B¾ !ƒ–0MÀÙn\i+ãinvÄÙÓu¸ОCñì›<Ù‚M¼ð¯7Ì Ø2!ûëzÅÕ#ÏH÷Äœoÿ¤‚+X\<úÔ>�£œ ¨þï¡CŒ¸}®–Òà ã�ÅÃGÇ"~I,ÎI±�þ`‡5ÇPåý¯¹+Øç ’ù`jõG%˜oû�àýÉSfµò‰^¨›½¾�äÓîÁ˜�™Ð]€Â4¢…À1^ßzªº¤~º*ØiNq Å*ÅíÝ¦Š€eðà `bS-6–…8¢BÌý“º‡HÖ@\zÎíÌ•aó€;Û2¡‚¼àÜy¡r¡¾y›˜%’ÖÃ{¾Æ»'®\QÅ–6¹U³:Ý"T®h¸Ý*±‘غ2U“/w•&ñQÌ/æš”Æ�¢%'.ïkÀŒ[lCö‰·kéøÅRqõqh8™@X–r38§b‘Ñ b|©FÜZ˜ÔÀ_ÂÆÿïn¦N`ýÐ ˜{׃ʞö«ò–¨?¨�²ˆ;X=^ñ›–Öz4Öà‚Œ³j÷þŽá73ÿRGØvB·ïîGèûÃlr=e^<Õ\y¾ÓüFÇ…Ç”�а\yxû%›P,4Q�X¢á@�“SðÌÿÊW6 ,ŠÓ$«Ê“çSñÎuÿB2>%x¼¯£;%xýÓXkK#ØL™ vŒ¹a ŒìÅk¦™indW DìÖ@n»I)­uU†ˆ “ßë¼*®Gz¯6o_6å�G¸áéÕšñ O�Ûû‘h´ƒÇOˆŸ¢g&Üoàñª¥™”hÌÒ�DËUܲOÂN£©?mí:•Š oRîoöRqçQX;7{*ö†ŽJ!ßvl|1'i†#éK‰SëT3ñ‘§AD’ÚÆ[»x táUì)¦mÍŽ0vzSP,?wxQ“u-¤ÁÚŸ™éž“þGÿˆ|éQ\1u01R9-ÌUó}ü…ˆ›æ9N­+$Fa¹¬ wWIfÝ Û5à·5³#±4Яn9*ê¹Íó[®éžO¹•d‰pQûqÌÏÌWõc/ÎÜ3(ÍWA�ËhÏ©Ûëù¾ÍØÙ¾Ê½Øu hL'DÜÒ/i%í7œËØ×ñă1¾µ.;ñÔÂ{ô¿ N²hwZø!¥d¡Hf+¦°bèÖãϸõË»Íí¦÷�æ6¶QÀsÖ›a°XdŠÊÞ°�pù¶TË%Ò·u呚N˜¯uçÆô�!œ7·4-´ïGþgŒ²•7“X�­ê?”Z+Ë�l�†¢–4uKPF6c¤E,‰ºl꥚F.›gúa2:ÛY·VÛ ÃÛ‘¾Ûi䕟’éhÀÑ�ìÙˆŽ»þ*Ø[!´°Ï‚ 7aù„ XÌâ­åÕ™—µæ.t™m1$;D“4qΰVX² üPhÆu¿ÁJ¡•2ú}ÿ®1$pñ¨ùõV—ÙN`˜“<ž5r¤Ðð#X™]Ø“z!Û!ÇÀ�ô;³ole¡1}¬í�¦…€A€…Z†±·ôÄÿ%Þ+ðWáNCdà¼*¡õYæ¢"“qü?NCÞ’½˜í­vïi!ãΠ缇´Äª4@Ãw…½_ aF«ò’%óˆg-âGÃDl˜�xâ€>�'õ®ãfM®âŸ¹ FÐ’AãÓ(ñDùlRú³÷š=ðCtt‚‚8³DJå|ÿx²Ð}I‚~r¬`cö B£dÿ¬6²&çóZ×ë1¢%§ç%ç.bOlüÍÍùfB'Sãí”7ÞíëørÙËWu¹PW›~ e%YJÞ“ç^L‡ùTèY��wëò| x¨­ëƒ$y”Á0¤ 7‚b'Ugª³³äçߘo爼™E„vàèjLÞ,÷kNŸQuÄÐ_° úù+@M5qI‘Ò™ýÊƒÝ 8­ìQqp¸ÚèÓ§ç×ÀŸE|õ®¨^›Ù$t™Ã©½›äjÃê�¦V©ìx±û¥@N~ips‹Œ×&@1—‡Õ_z¥½¥—[Íy¤= õ¡$=³À¨QsÞY;#ZÝÝUo‘¡ZNºóK37/Y!¥\Å«kffOÀ�¯$›Ù–€%4œAtÊ{ãìûW•›ûºÂË$×aн2cÖ?´ Þ£%*À¢£ ßÓƒeÄ÷~²78Lk$˜˜jú, Rî©ÄoYR=&|¨µÇ¢q—zš ´Fˆ1¾yÌ¥nr>é—ÐVšl&9âKî&’ÞÇàÛB~!»F‚²j¶Rz—j‹Ç Ÿ(ý?˜K ]tœmÑ ^_ óêÃ�—{š¯žz¢¶–U¯0$�lëlbUÌ®Ö FJx,FõÌÖ¥nÍÒt¡\z¶Î=ïOää-Ð1Ñ‚G"ÿÿœ�aêý[­aÛ»Š‡W„ZtêÎ3f­oFÏÔ±$ƒä]'–þН�2éஂV–ßžmà'“V�o‘á!ØÖ»8¥öl"~š'Ͻcõ�|ÓŠ%:ŒÓ%•Ÿš¶/Ÿnˆ�jÙbG¡S#É}…AL L0¡e¸G,¿4öpX~ä`ËÒŒ9? L!¨CÀ =+(Ò›OòÓÐC�Ä“A¨°ùÃê;‰p“6S¥˜#ÁdÎ’ì~$²|Ô ’›™½DGM!¡µÉûÿèV,Àîq¦éNT”³ïiÉlôw¹Øð�â°V´ã§ ­ñIôÂgoå¡ Êv�]ÿU€…ºãçx©�Oy$k~“&‰î@‘Bé°¸~ÅcÊ3͇�Åábì÷€s$Ñ�ï)ƒZˆï¨5eUA^`O¡¾U+1ãÒôábW#€¿ˆÖ~ºg“Çh8Ϲ(ÖNÀÔ”ã†ÅØúuèQmÅÎ-nT¶Eш6×X™' <2=Ö¡~ù„g5ùަ ®½vwÆ¿Ÿ�›\`;”™�eNò;™‚«ÏAÌ”K’Ú“©Ÿápa…ñocm·H�}¨U): ‹�©/%AšBe†+H€@‘f5�È�9ïíi=™ !ÿO>w¶µ=d»\Už„�DO(ï]Â=+,ÃWx°î=_â¥�ëc½rSã‹~�J“%ÏÚ‚>=ß½heC{ó%[R$ùä‹s£ò¾A½Q—1²‰ˆ+ßÕüËã°7ôˆ@3Ÿøiÿ«Ašo—@EœJ¬‚H# �ÂÞ#W/Óï!’ö¶£S÷ÐÒ�aùØ~ºäm«{êàçÞו2Ö)d¸±‘¿h'ìçxDJè› Ô¥œöiû¬—€úØO��žt`k«4ð=˾�¥OìÒ¥šú´#LYçƒ5ÂÕ¥èªz<÷j¼’io6¤W*kR¨šÅn›€fŸúnGÿ­;èü$©ˆÅAäÆÚ}ª“z'Ó1Ãb:kë�^käjëL,È“d�…Ð?dnÎÑ+V™�E#O^q·¹e²s¼äxñ¾­ò �XËÉ€÷|OpoOBbN®W*` pž+ˆž4k_^„×bÄN,±÷G-Áº…¤Ê6:8cÍÃf5Ê ¸bн§¬ŸÎzÂ'À!„_ˤl¤3SX�^æc_)-lñ¥!yIoqޤ­ÞœrlÐëãPtVäQN&M÷B #ð=�ù²*2{|!ø9Žü‰ˆ\;A.e‘J�c _�’ )Ì,V˜¢€EÓ¢°ÎM‰‘éÇ:i…�0ðö› ™æ\sŒZ‰9c¥±WKÂý–QSÓþÛ­) ìT ½l•�ü³¼Ö *óÏÐØy!L@)ºzI@Þ݈f Ux}Mê/€ÒX}dö=³Q 3A›ý5-Q2˜ .ÿýá(ܪ¨ÁÕ¼H¹½1CWîé: �zÑW‘?�3v¥¬k¨Lk€!{†QD ÑÙud��Jgבv¦â\ÝÑÏŠ™¼I85ƒžêÿµ‚l3&ÅÑ(‰ñ`ì­’Âÿšuw1�ОƒÊ•{Ï xߥQꂎíšÓ­}%?1QÇà�Ì„÷ÇYÈÄ­Ç¥:q ¦=Ø.Çû,Yß‘€Š:·?(X’^üwo«û (qçGœ¬ÏÙ8ËÕ9ÊÁ ÖÄ6XæC·»ß R:Ð×èÏʸqÏ*�. Áš þ ´ýãHó:kËuÂ…‡¨Þ×%]!—'&AÚh$œ’‚^'i†à*NušÂ;Ó-Zé¬ÇéËúÿ6‰ON¾ƒ‰¼=³_¸â–²êõx}Úr� :‘Ù>´¿²XVµµp3 d¬ÈèepÖK¦¬ÛHÔ¬Ó¬5ÿïƒ}yÎýÆÙíÅì› ^¯¨Ò{x F�É[ÝŠôiÄ�ïTðùfÉ^¡–ÎÌ]Žÿvì�(2I'í_d>5" \éø] 7œ@F]Yr\ßþ42ÎY»Wî57^'‚@ʪ_‚²[̃±Ø:)…ðç“CWÿŒó)ÌDrÓÛ×GEhH†,„€LãË­ŠÛslÅ8‰ 2Z¹ŸtÊ @ÈL‹“K F�oÖ e‡|jÅ…¼üú’M‰ ˆÉø ¾u.S~oæïi´|ó½”lp�y}‡ÏC ÿøº:heÿÉ©œIc„:o!½ÆeúªdðšÙä…zj0ìYK¨ô¥Ôy7Ë/š�üÒOá1<>ð77Wô®Õ&6¨Œgç}$ ³ßIm#¤žJ ”_î*W¢‹‹°™+æ—e¯Ÿò¸›t¯ÌÞd!:t@wLýNÙ«.Z–C�ê“”óÿ?oN£š=TÕb¹ íÀßޱpÕQjÌËó9%Ù„,ŸlþO¢Á'^"\™œKðD3ªj|‡-µá´Hj{ƒßœ2s‰±å"¨Q6Q?ÃH7Ópâ·%?yß\O0šZ=6ˆ KˆßÝóô¥¡8ÑÔ¤ÍÙàH‰÷4Ç,×ö‘àÆ.S`åCq~Ùàñè»\MëÅñU˜oöëô¦Ä$VjÎ�`{ê$çvÅ�d6±nnYc®~³|˜š¶´2ƒ›Fc1W‘ç‘åéa0w'1x&ÑXTè¸åvK~ë`å=†2÷šü6/©½Œž4sv�›µ¦vº•~s¯0®ŒZgäè6æ%€<ÄeKÌm@®F•©³*Ñ{@-¶Ñ²�|æÑ)ݯ½ÖŠEóyûØ”’ŸW7öž{·w£-.Ý’Ø­ÊÄše,Q”œ{ú¶=/aÀqûCìÚ¬§£¬ m]Ÿðmƺe<ìHz@îhö/^1®dߌ"ÉË‘é=ß%n s„)èJ[†úDh¿dU¸?KÙàú¦½·Aæ NtNZ’ f1/³ íÈN%M3Ú“3póÆ€~îF[“,�7VSú¢·W‘Ju­”Õp+>­ »ïY£‡'’y_b0˜^ÙŠa~�`—ê6)Ÿ?¼nþxPš�KQ’Þ#ÓÞ“õÞx>ß¿Å{ÒyŠÜ'td½e÷»Þ;›ä_–PY)›lE¨)ý IÏéH:�·+Ûž �ß^›?öDõUü»ôØÇ'Mo¯’¯f¾Ü¿�Üj”÷Ÿ� F�¦¬ähà!þÛÞ]^Ù óö‡NÚ—’×ð4âwÝóÈ‘_/‰‹i§ÌU\N¼�$áìæ@}>n�ZÙ{³¸•¡#üâ.!ÞnT �’'¡hª¤£æþÂÔ†+úÇ^ò—˜„û—t´‹\9P\úh,S}# ÷ W�ÄÀMÈŸH] y tîUipª >!Óã¼;8cç÷‹Ó›Âw§! 9gH¤äÖ›Ù¸¸–JÈ}r¼D×4p :^�‘[b¬õŽ–ÆÜ£,AVûÁÖÒî ªR—ÀÁ œ°V¦•@œ€7C)s³?£xÉ\K³¶ø1Nqô‰hðÈf‰wxf�-†sÈVíÈÃkÝâÉG!§§µpátk Ï¬wáÀ(%•˸Bš´Q}pK¬˜œ›BT¾èèí[‰–¼–Ö‘�¬ 6}§Éÿ °ŠgBÚRüã‘w€Ñ%é¦ü �Q ïëã?{ÊœÅÁ>–'øöÌ}ç[�#Öò  Ô`¡ "qH°žî�¬»õ6<Ƙ¬Ÿ:wòÜ�˜Ö±{+]ƸQ4G 1DCQ½^ ¯ÇÀ¹r5ÆÄ–ägp£‹Ato‰U0FÚÿH¤ýJ¾Ò°™u†Ðƒæ³ 6—±yV൑Ì:ÞXñ�Æ\«àøÆ Âë8ÄþÆâî<2 ¿Ÿ²'×öŠoQ´7WÁPx]'íæCX}¹`žçæ,óÏp”ýÅ‹›�æþ9§„¢4�cuÕqbD2eýÞÍjRr�¨ê©ÒWE� V˜#O:éŠú�dÝ–ÑÒ~ rÙînü¨~5çhÕLÏi!R׬6ƒÛLOcɘ˜=ˆˆn¤ØÙ¦Wl8Öׯv"RºÓ¤~èyÞžÜ�,Ô9Ñ®µÿU·Þ=u/H+[ÉY �Æ�ü�®ÄPlcó"Ì{Ú³£Öl‡B¡ÛJ¨ ŒJ»lå0 ƒN”ÖgX¶1£6 ¬Ãeâ$2ëAŒ¼.ÉÍ‹:Ò:O&fM£x ‡•¾¿®då•It�¬KrIû‚gL {ª›¹tDn™tOßiËÙZ×°5 AVÒ®×ÕaöÏNðÃnMø˜E¾ý$\÷aÏ¥¦nÀÁÀÈå¶A’JLæ¶øÀ0% ÿÔ˜õ{¸†Júp& ø1\_÷æoª÷Z qxWIwý] ÚÛýº =Ëæ ©¥Á8˼ï0Ü~m1ý]ÈÖ¤¯’�‘ùƒ<&ª”Ü,AJ”–†¸Y›‰ÉCÌW>$ñý³¶”ÇĪg¬�ôd§ù²o$m‘EúAŠCMÖ\¦Ìá_rJFÞf¯m~ÌE½6IOl›îŽ)XJQ&ä p§ápÅ©u9þ–ŸßsDÆ'ÛGã?aV.†Cn}ˆ#¿q�ã�+®»š!ùÙ°ÕesCÑ` ®vºñV×}”*�à$ùƒ�*ñÀìØg<òGý±Ž‘ÿñ°wΊãq©{ßËo°G(­%Ÿ?ß°†hìN(;áû'ÜgÉÙÄÁvPÕ°ƒµ '¡¥k˜ÙôšÄEg{®±-¥ðFëçóŠ=€Üîüþx–¥óN׃ËË›)ßsý› OÚÄŽE ÞàƒótyÑ‹�qšvÍË߈w—,Bú†ã‹3ó¥¿ÔmÁ‰Óàq¯�P†×#üxZ¬SE£J¹pÙ’—œÝ³|Šª0jb ^~\çEㄚ¾ú’ßMq Ý…¶Ž~{²›|5ðÛ‹��ãbs@11î=ê"ÛÞˆ´!ºÀBHT 3÷!>*]«1ЊGz¿4s�R?•êþ qHA:`ɱ %Ýåýü¹Ž$qw3~ ÿp¾½q:¾øF‘I‰}"6ìiÄ1íÙ(ŽòpÛ*±¤Ë’´G…H pg¢5›8¡—/ÎS“¾°b �ÃVžŠR›ëÀõÂÅå£ÿüž¡âçt§èyרÅqVZË�k$µXðV_às|¤ô澌)BÈ€^±î´þÿ0Œ�}¸}ݵϋ}FaPp�«ßtLµ}C/ß»Í,Ûl,© C èl.ðtvÙðrJÑ6ªÈ ¯#›g3¢Blt{a¯ËÍ!&?v4wúS´ÓZýñœ±x"õø²Øn˜ûÞoñGJô†1Õ}ÇJ*EÙ6rj«ÔÅ$4‚ÙW{²é�È–þ‰ƒd´Yü èˆ÷ÑÆ­TÏàlæÛŠ+W×ÿ,óù�ÛœÒÛ{V#¶n´±Ÿ´á1såæ‚·(ÉYÖ?8­àneò¿ÿ$¼‰£Cfý¹Â-~_@@û5BŒ·ÃôÃÍÅ¿M,�s³ HüßêÚ�¹¸FªröžºKòP¨ Í×:Å¡4ͦ‚Ì[¦§’•r.—¾ 5¤>ævU-£çõŸæ¡qRƒôê½)¥¡D¡´. ¡#[֭Ϲ³ÆŽ¤z{:gR&¿¥$€ö! ý뢉 û–ª›p­�zôù³àÔêÊwà0�vµ§åm¡‹Ou¦ží˜êÃEµÝsØjéžË.•. }wÐ'‘;¿þØä6V.Ç –[F. 4l šª0*Ê&ß•¹Ð“‰m^Ð[ *V§¶êz`¯pS2Ný\e¦›îµ)XÒ˜˜Íðô©y2D<õε۷sDçÆÿt Ä÷5c�ck¿‰¿mÊ÷Q=Uݺº�7´Íüˇ¶ÃµN‹;¸pVd$v;¤áÅÿ<A^[ aêºTóRas0—+룟ûáÝüüµæ²|m¢»V_3¦?V°;¢ÍÔ¬QÍÿk7âC –+±`DëåVg‡VÞ/¯ÇeAÚW±@‹—ðŽÝ…þþÒô§]ÈoIöPýd]Îä R‚ï4bü)NAþ@„´§ÏÝi7øíÊPèT¯º¬á[,ïÅ÷Î$¾ƒå)  0‘??;UåúRЈúíŠH5bp¨ºÒÐ!p‹˜©F±´ hÿ¸Ÿsî€ËB¯¢Í0.Ó]ÄŒ ]7ð=ÕŽðc“­ÂÕWnÜ&•”âÓýÂòDxdSHL³’ZoܽÄ0}í¬ì¸>Q{QoöÁ/}ûÒÍ%…Ýî]é‰::ø¥tÐñÀæ*h·ºù×´¯Ÿ¬˜vdân¬Ï6£:Êέ²l´ØFhýÒ§)#.Bm„ºÃZ´=¹½C‘ôK )À1ó©‹–QÊq >ÃXXNá(‹ªh‡ V‹àéx p/eÁiî…n|bMÃÔPÅ>þ #ÖžŠs!‹€}CYW–­FË’?ì äáêÛDZ¾>|Í zöõ‘{,“æ¶Ò›!a¾qò—Tþu¥¬†L$[éõ¸ŠÜÆ ßTØ€è.a8a�=eh¦ŸƒÄ¿©œ—5LÖpæÐs÷ñë·ÿ§ý{&–hí7;Ÿˆc‘@Å»ž2Сèâ›ìn ˜©�\åºÙÏÀs€³°ªcè¶úý¾†2“qík…)Ñ·`¢¦ÇK¡ÓTÁ÷}zƒZZ!™±aoþ­ž å°%"r#.„û¡Ÿš½æÄji‹¤˜F~X† �lí ¹¤û»w«"SY¹SºÕ:—¬.þÕ䩆[ßq“×€¯ÿÃb­tÅ$è42®a‘,ÊÉðÍ /I£ÀÅ3ïÕ î&¸·a|gƒ¦hŠö È#äÒÇ~ÁEw¬Š‘1Ÿ=p1^Cž hoÆ�ö�Ùë‘^µMŒ‘0Å|ÂkJ}ö›î‰ ¶¢j ™ÕWÂ(ûG¿Ýb}¹z”2(�îúö¨Ò¹ùPÛa….œ3¯�“­&ÅÈy�ào š‘Æ]l ØÛš§�û峺ò!Ì~EçÛf�yȲ†íßGZ `ÎL¾@kbÊF¯©òÄçiOžË]q—Ô¤ÿŒI�@9�p—¶¦þ¡ˆ ËQ*ŠxfÅÆ z‚0¯}OðnplZ¸¶C>­Ú™éÄ"”1Ý’’H.õñ‡`{R°þ0¦kÐH"/‡B²60³<4™„ ««ó’ Ûœ=y²ÐØ�R¼˜Ø[À{~u‹eK÷iôžÇ,‘ôª÷5éùøA Ÿb¬ßÀOœYï$Ú»uÏŠðe*5T „�zå„ò3mP ];¯cHzÖ²[LL—©ëi‡xˆ[Àm;–¬¦óŠŸÂߊöáâ_Ô×I{ÄJøññ÷'Ô-¯Fœ¢&gÙÛ0ó~ð|ʃÂ7SÙ4_Éõ$öaª×Òu[q/æÝm6UÂ.IÒ…ŸÒÎ9òqg®<ð i!Â#(»¨ÐüB,U‘}!IŽù5·X&†gñ+­J)ƒ_\}ÚZ"ëøA"a7¾Y+¦^EüüzŠº[c ØÚå:�:Sù˜ÙÖ'ÿð3~•&\.ÇÚù×ò�ˆiª” ¯ûnÖ/;ˆ1æH"ˆ …Rñ ³»Ï,XM®GÆRT3yïÿÛHÇj@Öbï\‰\\A�"°cQn€ýï¯ëZ?e?*"ËËÞ&Aqÿü¡›¸•q£Q¨‡¤Nv~¿,ôhoöÿÇ?k¤Ãè�ƒý6{X˹̓)‘æÿÇk)fatøXB¼3ã‹oí…š.ž¬âþ6D‚Âø­¾[›÷e ›áí©½±,»x;@«ÕD:#ð†×�nŠy�…ÌûkìÔw}&ò8¾'5j¥?^ Qu?xr•â­[!÷« ¢Ñ‰Þ½Ýx�¯bæÁµÈ÷óûka1á 8qb†“ÖöKÝŽH�õm˜ÝkE¾ó!ã!‚µ8Ö”žÑc‰ê…“Èóƒ{QxÏÇŒ?!ÃB8„èðo 0:|=Ž0 ‰Áo€64¼�Š¥åã}o尤ףǾQŒí"Jp#¢¯Ó¡Þ'ÚÏA™,kmØÐÔ'PqHËŸ]?­ñVF°ãsC/EÁ1…ÚÄuJ¶œÅ:üXÄ?žæÃ/ü"žTi´¶-¼fyõì±ô̼Pïþ¦­m¢ËE·‡Ë#J›€{UR =Ë»2/v Á*9Äq+€f-fc/A²#E4JSÀB³Ì7\}R*óã¹�î\ši�oaF ¾¡Oþ�ï÷WO„‹É7›êCLÞƒá¶L[Žïwåãf[Ïñ tÀ]lC@ÅÜ$íÑëˆ5^�ÚLðr…œEulÚ–œN ÷�…UßÍ +¤GLÃUL]ïL³§µÀü³0†�“ñ^1“úá²'9ëÇìƒ[áÖòCœ…Ã~¯ "ܲ€&oÀ‰÷Koäz!Á Ï‚º d‚¶¨Ç`ñ>T¶:‰Ø¨ð|¸'Ä#-�Ç$ò¹ÖhPÛ Å `ˆèýöeä¤ì,È@8�j(õo°8ÜÞEÈNn>­sÈ-¹`+�’ÖëÎÎo<…cc,Á!JÞ;µ’ ?½6 J ‰�Ø(ƒøí¬»[Ã=!kX#Ï—_GHÀOÂ�=Ê-óñ2·[«:¦ >Ä]ÄË_øÃaÆ£rî5&à‹/ÿ)]"ŸRˆ¸¶â fÎ]ÞüÞ'Lâ/îËÎÝ9^gl°‚U�f¤æ)@£QÜ´¢eUý�ù)»‡æ;·?å‚þÕ÷è1ϸ(`Ë˱W4a„®Ö~Á7|Æå3m¦Fèæÿ/4††·H:öh�Ù¯a,mÒÀ·zj¶ÿaÁµç\bŸÐÜÓÞÐuÉÖyJÄÊ�4„FŒÝAÅHn²›)˜.eb®+ªëõeÊä•ÙÇïdT|¹hÊË&… q·»b¥æÇükÄj¬<ÄU2†zEtÍŸ yâÅÞF±MlNîÔÔ gÿU˜LÈÊ@éøˆ;ÏØ›°ÉM¢Õ”3£ {@ENxÚ‚È£µ£‡õcÖˆ/ØÚ¹û.;ì®Ï5鈼aàEÕæ4–@˜¾:* ¡CvËÆeé2‰èXòÌ5Rß ÇM]y‚Z,ädç°éDTs´u�M„­?¥§4àìÑž1¾c ùºñ1üZ=²‚�Õd‰>BT_ÍXùxXj£êïKýƒð,/$h�$«t3Ì<½ÛvŽieEâ¾,N0ý ‡>ÇUR�Hùˆº>€Ïp� ÓÂÓ/ý£iÉë´£xˆ¾9g* ÊNýœÇvöËh=xwÿïîB½•(„‚Õ¾"N+ΰÎܑЅ5øÓ«ÒîÂZP&Håcs€o>ì>͵y‰zŸÃµGÿç…§ ¨@p pAšÍltkQ4WÂHF·Ü.¦Û¹ HÈ©Û á1ˆ%î{­Òù9wè£= �¤Õò° ÀÍŸr¿±ä¾‘GàöÛ¤�xlL�C¨(󀇄«æ� |W›ÞµGG­´ý H'‚4+ö@«×$­ÕqÙçœo × ‚TÞ{r®èÝ`O€Åã–@�­€@ßoÔ÷èÉG _‚ÒÃ.ÚãàN€ªT…&%àÂ=iý<'Ï‹fß_쯡"Ç0Åï{4 @°ÒK´SŸžü©âÓ‡SmézÓg‰ô/Ñç?.›†¿ÐmbÆÃ¾úk)iÊrqµ‚ðm„Ð^ô¡íPäE<2΂¯Qå1`Dëngð¤Å| ¹–„„:ºAœRH–^^´ö±.Èî NKÂVÙÔ¶5ôª÷p¢¾«8ØàHÖ‚æù”ŽÄ^÷`èöÑ/Y#}¸‘û>‡|6n&û¥¼fÀãï.›!ÇÉщØœ¾ÀÝ œ'�Ö¨cÈñ¸UjK"=)‹!d§ù�ÆáÏÍ<{ñŽ«°¨®Ù‹ŠzM€Ì2Ðk©ó*æâWÉ4¸JX¥Hß‹êôœtC“뾪WHU„ܬ4—pHwJäç•âim³–<ûdu4¶å¶mdíq|ÇÆ¶ÙÞü 3âJáТٳœO¿P8MO1MFe²ì‹jÑb!ÍCÑ—ƒ-z ÏÐ`Mcä„ûç$¼1�|Ï —ÄýïŸ6V° ÿú@1Òý|¨P‘ú‹—ˆ¯¦þà6ž¢’£ž¾à·Èèr Ȧc‰5ÙŸÍí0á†:M™€€ñà…²Îx¶–ehïJ'p2t!úzRwÍTyž×ÝØÕ0¯à+ÆTœlRÌ!Ù_€Kãv ò †Õç¤òø~C»L-Še±Ã‚‘#·6KQ ØFfÅ\²:î€ë £Rܽ�Lôæú}�Šˆ'úTM*H ÄÖ¶6–€*¹I¹ö¢‘ôº¯¨DBNÈVš§çö7èõÃø!l6㺇 3ÇÑ' ý~�¤\š*ˆ§­-€£ÏÒ™˜�ËB¨ —è™­½ýnžÍE;j“§nÓš×qÓã?•ð×I÷`ì_Џõ_ëOIµnø|Ýý %a¼<¢ IäÕ”!Ví÷|6ØH[ eu­ÿõqÃo ¤2û�¤q¦UÕ­BÝ3~³Œº±÷ªá�Ö~Y!Æ ‡6Ó ËðN�Š¥³€K$³OjîóÄÊýä Ã=sP˜£¶)êò’Û 5·ÀoD2õ+:`u•Ð×S<êä‹°VæR¹ëœÂ®bU@y‡fÑæb >u¬~[l\¾¬eµ%ø2bÑ‚gú­ªà©¡“LZ–ÔØÕÊÓ~uÑC½€™ø‘rRbú­Ÿ$—`­P°£»çgèX�^é›T'¡àJâs×U�îí_PÉ5M©ºâ2á4ËÅR²ð턤thFÚ_#ÌIvvà¦WFî× ™+ñÅðm¾Q�Ѽ›Õ©Ó- ›Œ;A«Žð þÃ:&>q_OÞ|ëôùb6®@ÿÏÛ”$Èÿ»£:m8”`D‰îŸâÓÅ|AtëjcÈc¯€RŠ{Aˆ0ŽPõa×OûÔÿx}“P=BŽ2w�Ó _¢Ø�9yEÞhœ@Š{²Xp©Ä¡Â1a lóÕ‰Òh¨�5ÒFZ$™K3V Œ|BÓóÄ’¤•Ò¢OoOy‹‰a� ®Ü“]y!¾ñæ"÷Ýï3;úÍÿCŒ1ã*ê^+¼íO•Zì¦jëˆÑ+·àíæ®\¼×%,9×QL®ÀâÕfauß{uÓ°ÙÇãû­nTeiÞŽ“]E‰_lÍh:Þ*Ï¥œ�C+á#lÛ®X²�tÒƒe,Ï÷¥Ïc…¸$šs�Éæü^‰/3RzJ�.12Œ6 �;�þäâZº×îªâ=šLYʲ5a+Ò5ÙBî„TiŠš½Uª_�ÂHœ•±ðÃéßùÒÄOÿ´3àa5­É¥%„BÖìùW�P.KàKw—¨/ ŸäÎÆË³gÛB6}Ómqàì=͇�ùšE¾¢$p@h�ßfƒ ­þ¼•uKé¨^â¼ÔìG\dèU\«eˆÊsMÒ¿AÓʼn ~8?ŸeÑüoìM™²xî­÷Çw¿‡£s”¶‘£×¡ékì—úJ+ƒ|EeDþ†màþGB†;ÀÑ m ÄËÖuSÊj¬9›á™f–îŸR“q=ä[Õ{á*¼íxPiQ^e¿ys«gÐÎZ¯ÓV^ÛZ4º½£þ¹ü¶K^¨·ëë¡X³�ªE{[eá2è¬"¶ò«tÛ-x[éÅt—cèÑÙ(˜Ø]-Hˆ2�†?üRñ÷t)i»õ¸(î1ÄbÌG} âVè!½ÍÈšB†ÙÀ-wqôÁ91¡n¹ÓÁYjµ¢™™_}7ô»ƒym¦âÁJM÷.üø–§¶4øv¨·ÊN¨áNAš Má–‰”ÀTðÿýáÖC¹àNæt©…v<†oÞé¤Õë*ÓšbíÌB óÚC:èé¢<ãBa*‚ZŸif¶5 Àô­9ü"=27zü½άë+ò$,Î;lÈh. "hÙû&êL¤° Z¢9ènùh$±³‡Žþÿ¨m¤$°T šá”^„Äò.Si£y4rÊ{¥§¨sϹmtôÔjD[Rå3Ä¢¦àÜ ÿ1 �füBÁ,ˆ|DÆÞ¨ÀUô’ÞÆ�³g¼¶‘~Ý;÷K·8 âþ”Ö �Ò÷ZAËÐ�i"�~6!ÓmŽó†0;)g*Û€ D°½Ú¿Ú�*ÖÚŪ�ÃæE?v˜9‡‘ S€U3>ñ«"¥\V%ÀËŒ÷lJ ÕMÕyι¼fÐj“/ƒc�ÈieAéŠóýËINÿìVåM:™4Må'(Gÿl*E ´ÉÀ zÔøST Ì©¥ D]º�Q&*Âé»ÖÁA4Ÿ|×Ú¦R½ l"×\{ñﮙǿdpðñmåjNP'´¤‘FF9š:¡½ù˜wMšŒ*ºlv¡×†ÛÓ‚ Ó·ÎuÚÿôä;-NO­$ë„®ð[•³îÐ\OäF *�:W·.2�Ë! p†Óç´ç‰]Å›nÏCBí 8s:$ «sH¤ì¾ý÷4ãפY~)H¥Ö�Q(Ó ‘Ä B&YuþV”l²UMýB^n0®^+Vv|ütðAÝœ|ïKTÊAD¼Õ d5ªøZOS~HwËÁ|¤_ô'¡C+9Ö›aqsb^�± çDk”#+ò^ Ì‚—-¨zÝ›öšN˜--‡Q¤ê—Ò÷õs*Ï´g¦ÜPü%|Xd£RæöŒ8K3á%Ó‹´5#Ó�áþwoìàOe ²ñQSÃÁõ~cª´»¸Ãî$b¬¹êéja÷p¶ÎïˆC/u±e?‘D(ÑÊìRGÝ:žçÜÄ8Ô@ÄòÏÜ_ÊOÕry){1d-Ì·�+Ný“îdž„NxÖ¥à/„1"½†õÉ�³®2ÜÝ0ÿ⇕ ŠŽØÔ•¸ˆ8b�ˆ&÷¸÷«ÊVõ1&.DÓã'þ| tà×£$ÈQ(ÎpÍáÐ팊uÎ"°®Á—JÄ XçÇÁèáÖ’¶: znÚÚNÀ¤c¸¬}XXÂëC{¶C+â»8ÉEÁ5EÈ]S¬ò†ýᥜ�fº»2‚AÓ¾_lŽürT²1WÔ<÷Âê×})”ÐpÍ“yÈïEÓ'cÓ`Þ}Ñ ŸþöK�¸gTµ@¼9ižÝ–èò›�]Ä.;aÒò üÒá‚.¦«¬ßÛ64ö²Ì*AÜÑTçyQÀu4�Ƚ-W„©ºÚ‚­ª©/H)éUz1HרíÜ–Òi|¯W47 C3�ˆçk|O¡ á—ýh=[¤Ð9TxŸœ’Ï?¥ï5óÈÓKäs•*a[þ`Ü»Ì;hP——–O9;›¡{‚H4ê_k÷,`)çJóÞX2®±;.îô÷Õ¬ ÃúZ� „F¶ˆž¿ëæ×/ú—ú°5Ä®·7xáàï§ß6=UéÕLeû;*Ÿ.ÕQáÅ ­¯F_ü¢£ ìð³dòÜ&€vû’Q˧X î¯×¡ nŸ ~JHö᪯Ámê=[ÂsŒtÛ²ÚXÈãÊÅDh7ÿ9Ã0°°fÂA8U RÖ3RU”¦Ä&@Æè_iÖ!ÜZÊÀ‹‰ÉüZD;¯¯k¦¸Ö¥äÅécØm!ª–ž‘¯üy…}§î¸×^ÎI¢ù„ÈÈôçl÷¸1ÿ ÆuÔ‘æ##VÑ‹Ÿ“o‰a¹ZÝ÷¥P4Ø�ÎxŒ‰ÑÍiÛ~²�Ê…ÎS0}C/F…"‘DOjõnjN±�UÕÒŒXÂpÊ«/ø—xQ·ÿÏíÀ÷}¶£ ø?“?ôSßqϯ�ÝØgHÛkýŒù~lê�ßêzÖŸjAO:פֽÁæGW…½c'I¿YMˆ%ç7oô£5AŽ rtXí¼.ðY¯Ìr‘“@•±} V•Lyh…hƒbi)R#õ ëx¹bB¿)iâÍbR@]M…ôñ‹ˆ¼Vˆƒ°¾j~º ²1(�n¬ÍáþÕWûC�p‚t `¨?™#@›úrÈ@f³w×C|š´§”<Š© ?UÕ¿ÒW_>¼$k"%…o2ÈíŽ?ÚILÃÍÔÈÞ Úâ^Ù5ÚU©&”m5—„¯j' ¡ÕViR¥#\¢¥:té¯c𠌇5/$Am/GN·dõ#qÎZÞöæ�·´SÛºû¨ïV±kcIßÿÓä„i§8Éê-ý:̘@М'—ÈüË=‰|ŠzÙ ȃ)ÇË-²�U"é2oHÖÍï•-YnñËF�"ÇÃñ€H:«½n•ÿÛuÙ½Qý¶¹ë E9b`<¯~4Iõ¿ ¶Üþò%ÛŠS 'ë!'ŽCø˜=�¦ãã#€m`ö–Voÿ|ÑÜeøSûMå«›'Kzü9S &5OB’‡ÇÚ õ[±Qv+i¶�Úõ†“Fø0zþŸL�Á -�´´?h××Ô ";Ô;P§iÜõ¶ ÖSºÃwÁõ–­:Jñ�‡8õ²JcÄS ]xžÃäY`,(?õ_Ø x f+·|÷/Á„¡Â€iŸFŠ#D€Fs‰‰…ÏÙ TÒy(Å6l°QÐýÕ«Ç&Â`a?Ø;8iƒ/݃ ;”#¤CKøb/©…Ìœžv«€úÀO©ßZjÄ}“?u…|>)ƒÑ—«?R`èϹµVRö¶¿4ôÁØbhÖ¶$ÿpàŠ£ïÂ…ÕÇ .‰NÍÞCÈà”(_\…7Ṃ’¿5¶fÃ.×c82掠ØL�›–t>Åiõ{{‡ãËTˆC�4½–êá?OY}CqQQ¾'øÊÙi£O+¿T ˆjÖmþ-É;Xapc~ò0„ÃÁíì>Bpa·ÑƒäùøH€,thÇÔÿ>Œ.®‘–^5-f ÷/³B^+:0:³Œ]lH^ÑÍÐIw“ÖN ˜¿ É;¯¨$S`IZ[rº®|alØôi˜ÐѶv±Áî}ø…÷-ÜÒjæ^7Å7>™@ %¼ b¨³.z‚5z×ë?Y­q®€ild¢¶öîrt}Fða'`AXM‹gÂŒmþœ`�.Žeç[ <©{¶yß.@O�ÍR%ceA0ÏGoæ^è�ç‰]S5h^ÐPÏÓŽ€°7Ü[oÌN #…²øbêÑw÷±Ê°×ìu›ï$º÷×·“ÀÇeߺf[°g»wÖ±¼!8füˆ›ý¹º{>ÈSËÎßq†>_ò*µE�}UÔ¶š êe‰ÉÊJ^ݤžÔÿÿŒF–bXâö^ÉÉ­ 4O±-c™|Iè; b›k²—þ¤Fì/*!Wü�¥ªþs“¢)Í*ÅJuñV^×À‰Ô}?¬¬L†‘‰ü¼h·G2J#ý>,è]n›I;²¾×ýœÊ} —x"¿¡Ðé«�½À�;2UÔ¦³ÖAþ¤x3lë¶ï¼›†NÒu–z�nñNÃ�ZYidâ>•§Ú ]‚ެðh½d=nÜnhe’¾1Q=ûn1é®›' Ÿ#— íVpT÷åc9̽Žþš|..X—Î È�¢ÎAèó„Ç€EŠ“JGÚÿ¥n99x¨È1`~>gxÑVòQ4Ý8EÜ2XA1V54ââÝZTlc7óÞµðe† GÑ`_ú š^ŸuBÌqUü×[*º_l¦×³ÌðNí½iÿV4¤ááþCÃÖu2†š—™¶ŽrK:E•`ûuóÁý»—Åûöù� q��ñ˜�Ï �0Eœ;¸l±‚) +›hã$QY¿ùð^8«QMI¬¡nVt�ý׫Ou_›ËSæ™ÉdV3p/>�vÛöÐ,G]TëLPêNq_*%ð¼Ê®êëç�µe½d—Ø…JÊÉË¥þ*6˜Um^/«T6@<ŒÙ«|FRîÎ N‰`1Ck[㦪j¯]¸ÛíW{?W¢"¨F¸�ù­P¤|Y½ßÔ{úçÓNÂ??[S€7Yt¦Rø9º�iô‘"ºIú8§�¦z>ˆu§œ õ8!?kûˆ3”÷«ne�$“�g´ž¿r#°m{˹ĀÎxcfwzŽØå*)WeJ�gê2Â,¡«Ê¼½rs^åÙQ\ÁÈL—> IÐM¬oŒ~GócHÑ#Ïö?{+ÕÈÛ0†ª~æ$K§ã{IDZë�Š‚ý›Q�dꚬ~„ØCw“W\RË×›4Á\¤éµn¼ãYpn”{mÄè³9+¦wPf³b†^*…ΰlr}¦«¥&wB’Lr%Ð?j5–Äy³õÛu‡ßÿâLj‡�fµ&í” o üL³"þžóìȬ<˜bÆp¡ÓŸúãAýzÃcu8�©cÚ'‡±NeöÚ3õ·¦�ÖŽ-’èÜZF²ì ùN V!ZiͰŠßn‘Vñ E£0îûœÑ¦g�þ¯X0fç˜h:Sˆ,Þ2ŠŸ”@ô—¤<ìDÅŽ¸¤ñ´ÑÃ;\ý¨½Ø�ˆ¢Fq?S7d%˜œã…ˆ~_þwÇÚÊ|”Þ�ª´ª? (6Ý©kK¹-Še5Ô&¯¾±“L!¿º.ó :§»ù„'Q^/¨Ï=ÞE½^®8´UµÞL3ÍOèE7€‡Iw;@ýÕx �PbŘŸÂ�óÈ�½€ÀÍä¶ajÔ-íJÛ(¤¨„e†¥“ ª8E§ëÓµ€ž_nGÿ‘cèΓéGq¼ÙKÝùÈX€l6’îH¿�Ó(¼ÝÞµ°Ž/F‚»èPí)“ùA2£`ã4 P"&‡ÇoÁÉ]×�ŽuÎw:‹¥)´Š‚ð±�ô¤Ñlc€+Cc¹^mˆX\KЇÂ:k‘ämÁ ØNk0n‘M‘,/ûÈä© ²7âE—ÄeÒ*Û•nÁòIÁ~ÊA6æª]Ölááô ’a¨Ž3‹3vè‡Ú9À¾ôΛ�´& ¾¸ˆ=G3bÔ^9é»Úó½‘iÁ¦†vŽ5æŸäÔw”çyÝßHøËê|bd¯Ã¼ª§7¥z²|² {ó"0 ˜Oz®Úm•ØÇcrÿÀà^ênw]wÓ…¦«Õaô:‚(yöÆ2š1ÐWÂEøš5ÛÁÍVÔ÷Ã~ŸþßiÒÁÈõ?!/R³R“yiÞÇè•;LÁ­Œì¾ÿ�ƺ)�ÔV0€<„ée×Ï3uÄjµïÞÜ Ù>NŽÓ|d eéG¯„›÷#ÒîrJ¥@1%ÓXó¦Ý9°Á—cÇ›]S�·bÌ„ÍÛc ˜Ùu¤ÿL±‚×a:ÖŽEã¶™"Ä¥®®ÏŸ­økú VDh5Τ—VÙÆJ5û—³ÃXÉ*í[4±^]^®ûÿ)ÌÏ@ Ö¡zoX¡°Urr�‰§1ÎðraSïÇð3;hM¾g@#qªZ¼Û€_@Úù}`PYWÌ©ñú˜{þ]ê‰M“š4?ª#Œ[Ÿ<5ƒœ.!y~qœŸ.î$ùþÒ>eRÎ÷ÄÚær<„³þ®þýÀvÓŸsC¬‘ï {üÑeÎ0¼Á-ÂÝ»M¥S‰ ¬_gîÕÜQ×­È‘<R’?ñ—‚{%9… qèV ʉ49ÑO{t‰ÿüo‰tS¼3ÉÅGlF+ êýÆ´g‹ø´c?Q— _~šØºÅŠlw1À ÿ9¨å'p­;Û\ŸU9»Sb’qþKl#åæˆ ÍVö[”éDTÓQ^¥ÛMÆslA €AšBeý©ÚœJïÆ4�ä"L6ϱ>ÀAÍ!â°Å¥Ð0K¥•tE –û±¨÷ˆo"ßP&b¼§Ýççù| ñ4@âðã ¿-Œ;=ãknÁ±)A2õ‡ ËàÍì²/•÷g"/dãì�_oCߢh-Ü }cQÿÑ÷©8ŸMœÏíMy4ëž M]i´¿miÄ«À\:PW#´zu‰€¦Šíå �-6ÏÜ@¦[ô7í–j¶–ç‘upÀ‘mÑæU<êízg!Å‚÷føFœ]‹þÁ¦[ DÖ³­›“#tÖpdîÓ: #Dž$ðÕUìG‚²¡¿´žMü»ÜßJAæùˆt»d«ÎÙ „†»V}ã>'´qŒÇR»EñËÈShÇŸ<~ k‹âD£qÆDª*?e��@É5O�ÌFm"¿O¬Íäãt§Y¡oã¥xRà/»­®=eÑÓWÿä€0§˜R‚ ˜š öŒ®š*j|V#}¼Ã ° qí%�†d0½v�RE£3�m“d�Pl|Œ]˜D†•𞊠l„éäCgVƒ>Ly=ð »ãölïBœô<ëxÜVæE±Åîÿ[Îÿ�íÀ4\Zœ¶§½[ÊÔ*XCSÚ6êæ<üðÃßï› ûÛPRŒç^õ|k[Äû#úœØò¯:®Âï$Û7Ø·8ø V©A!êWac;|3OÁ?ofÑ‹O¿Ø�ÏÓ|Là�n˪,àÐL‘ymâ“þ R%¾Š?7Ýn†Ò¶Ch‰©¢ |ãîl�QYÿÐN1é‹rüVm?Šª;ç¬âÂu*LŒ¹¢¶ªv8ùÁþ(‹F,dŠGYä• Zz WáÈ­¹‘ôn›«â#¯‚¼ƒɬ©â€á -ØÍ5ÎÁ‘K0÷(—Á‡NóNÓE¥0˜ªÏŸ® …ã'G£z£ŽüŒâÚ€ÃþÿF»GYww§±‹'JX­2f/FÇ\ß$Ü5ûÅd fà.!ZÛ8DAþO´Ø¶Ýœ�å¸�/Ó>ù´!>:„‚¯lÔᤠ5¦–5�"�¬± ÿi5§6¦2¿2‘Hõ¢Œ?«§TI|¤Õý? ŠC�Áy¼kç6ñÉ‚E4^À,*¹VX+ÂÉM¦b•¬‘x½´<Œ£3͇W@íÞGÇ•K¦a2Ö3QÑ.t¿ÎÝØJèY¥“gÜÓ©h÷í-5îzHöÜ�)ÿ:²÷ÑÕ(\sNYlóí$ž >‹¿Áë3ý¦"÷SfN¶A_ÈpSàd­”p?”¥uĽöAÇüLóYÇGé%¥ÿJ…ê¾’ý�:œ ¦í€-ݘq„¿ó€�Ìe°Ôñþ•¶Ýœ-îáN ­$d\œþ{!ðC”'“oý¯á?_$ô!kÑQŒyW‚zÇ·xŽwâ-oËÔf%2ßOy{&­0^—ÝÞúvwg•üöFỈž Á�e“ž ûüdD&°§Yvã‘ÀÕPäâê³K3mTE\CvŒàü â²‡áëÇÞ �ØRÄòô\Öà y¶F,püôÿ�Tôû=ÖzŠ2é£>‡ž¯�@>q…ý3kðÖûÔþ9^õD 7xÅÆ¦ˆ'(.BŒuwŠ©Ó&Às_%¥ÐHìP‚6–‹ÝlÅ,®›´~ðÏÏ�Öª„Ç�=’ïý]0½E×XE!2à¸ÄC'~š÷c0öøàqLwFC'R•àº^ÈLº»âÝÇ<®=ŠÞTVî † ÝО}k Ón~Ì�Ó¼éØ y©m‘ÞîO6=Ó™C©Û E�ÁÒãã§4‚×o? Ž‰¥ZÒïMP1.ÔÖT½PAÉÉÿh{‚÷ºŒq.$Cá x Ÿ¬e+›ùEw‹a—IPÌËͼätŸÛ6’p|KQ õ l1…÷‰�\?j›yd%ümÁ�ûÚÒcNe$âû‡9:©­ê?@Hú”DÇ-Ž/ ÔÞ±ï�HúvÊ™o€ç†8¥±³ú‡ˆv¶3µb¯ ‹YT ¢ç)TBƒ_d€>…—æžú(O– »W–«ðÞ&÷yiº÷Õ¶:ª1†4º™Ôø¼¾û<•¿–E†ÿ?õ¾ z8G5ÒÛ‡N €�Ê›PHZ�ø�ù:Mvlx¡…�GÖHå`è/�˜-â“Ræ MûÉb#.+TÐtFb½!:Øç­‘rݜШ�cM„Îò¿;kÃè>|KµÎªJ<åÑ×4nËõÄ®�¹ Ù #—RJF60Acßh†5&çv4§GF\�YÔŸØ­ØNž�á"š†¾æF N·×0ü>ÊBë×aQìdÝLÿ=ÐAN¿~±q'…¬^Þ¨ÿ¢ÿ®€–¤oxÂQz(]F7!}!µ îhÎÒ´íÇÁW~4Nïf! "ýȽô1¡;¨‚*ŽÖtmî}‚~1M—Âqy¥� Q_à !7§fíqí‡T[Éã'@+YxD’ÒžbKÍ�ÎKPT˜ÉÒ�ÝŠ‹žK›Ì}ÿÿ ó/ºTÃHömça–µyd:uêzÝÒï%¨H„œSb{ví^7Ì­+ÖÒBÜ ÅÌ•8L0¶ÎX?Ì ±æ—úI…~ë‡Yˆš(²-~Ú…Õ'©Åï1Í£’ñï©T¿¯"[$íAšfe~»Š™¼QÐŒ¡gu¼-0¬ëŒ~£XÛ\ù ŽuLÂè#y³ýáûžºÞ¼÷™ccwW�îñ‚ã€Ëf‹ˆ•t‚à÷}„ò£7¸YƒQÔ×X�}Ÿž]1Ð,ÓÁ[Û˜xëh%}VFWúÍëú/Ú·õw~⓳Èê!6&ó½–•D¼Zc÷4+ò3éysUÊbŠáS†± %PF¬¤dH$r,!$[Ð�ú„úéµ(F‹¾3¹uçúØØpø¡��|/­~ ½]ˆž€,Óà¹áÕž£NÏúO¬V ¾h;¢!€ÙŒfÂ\ö ë vsÝÂÀjôýöýÆN5=ænu™ÏæÜÄRÔŸZ˜Z¿|§4_Ð{^Ý «ÿØQFB4æÛªÜg“\‰Î(Wk ²`ƒ?È=û ¯ÍÄÁ÷‘Õœ%àÌv¦¥H`0ן‰�Ú$üä¸ Ç—9ªÑÎ�ÿN6e¦TñÓ Wgøc¬8KiE�R›s†?ö³Af¿½¯Rn�± ]’vž¤:�}ÆPÊ´-‡P$o̾¡hMnŸ®Z�Êààœ:Êý:׎ÞÞ…†‚À5‰'“õÕ éè@‘ñ…áÏH,s� *Þ3l傎nU]-NÙ‰%“€†1P.:eB$vb�x�ø^_¤ÿ,øòwL—©ýëN¶%j2§ÚTåIÈ&Ý] LyötoFÞtÛ7 ��ã$:\»—h™& ¶ä!Gb3mõŒ#]^¡Ê¤F璗ד~J�[ÈUb jŠª>²,%¦gëÖK›lWy×Sñé sEbE—ñD/Xtk¸\äСãœÕÇ;ÓóxØF@噺;³ä%RMDvlú°ÒH`ž/ØÔhLk,A¡¯]Á|µ¾ “]e¸07m�­‘f ÿ5ý‘á&ºY¹µi ûº/LhéÑ ;—È©—=êºBZÛ÷m < ÀÚž°BÈ~wa EæKYKmæ1¬QäÀ´TQã¿¡·gQ•Q¹}V!zEóªk% {CLÖ¿´gÊmP€Í¾ý•|Ýî©‹+_‚ 1fÑcš³™Á»z Á»7”/¦~NC•’RHtûÅ 9ÅZ!GÝ.m"ª¡Ç7~-¸ôIôï]F&½eÁaŒIñ‘!>qÞg­½<¿'ÞÑÛ´‚�ΟæÊ�Æt¸�…¤ ‹[¾0ã²ßL›kNYº°f’<4ïš]Íö´|\½—ëát�Ð#š«°`©—ÓA.±ÈÅÓMt"V÷0�ªuÉèÏIïœ!¨X0C ü¼‘Í0S¿lü}¢@Ì·.ø\ÞÕ:£“A•?ÿüL¤øI*³5»w_iµ4ýñ ›!F•­~sñ[f©»–H̤BýàKßU`Aª¶Rq�ëTrƒÁåÜžŠI©#´`ö¾Ú` aõîjúœþÛ¬�·(@²®?,"eŸä*ÖIJC ˆ×€ÕÙ¯ºZÒ÷Ó;€”Y\shÆ‹V“i2w…ÃÀ�ɬ˜©¶Dœ`Eñ¥MdÙøwò ÖœÊÆ¾þЬ &»º¤�Ë“IP‰C¡–@ ¿r)Dƒ-®Ôå©\2ê¡Äè[ö[àF2™çήWÏ» ø‹0°%�„ß® ' Ìbxâ"EÛãYh想³•(R±Ò¦~bý™ØÎâ9�\d@õ?Òù„2V)„Z–HÁÛÓv;Cgàk–J@ú Ñ¥Òñ¢Eò³ ¯Ž)!;Eí´ªÐ÷œH%»äY5‹Q«ÐÂïÿöNf;×îp‡4¯XтҤ‹«ÿWœyÂÊ“¶ZWíi½Ï$ù“; ÙM&Ñ�ÙiÂîƒ éS@6b Ø©Y”SØgÓGïÛ[ûzÍ”aSa4H]Êq-MCý²ÐÂ~5/®@R– ㊵šš×,ÜVË%#Ϭ@u˜1w¿9oá¾w„?ÙÝ„€;¥ù^êC·úæÅÚM.3ÍNwÒ”ÒT=П§©Ñ•TË>šk[çcd$ÞL%BZ^é¶2+2zBœ;" @áƒl©äÒ´Ÿn­[ � õj¯…Ú_¬·ÃÒ¼4üR;Æ2&ã—â~_ºK¼‘¨+p4>\D×}\›b˜£ÕõÅÿ;Ùÿb¯ÆËx1W6t{ ÉÁj6òKŒ=é°¥©ÃaeœÍùÝ”(îmÿõ»±xÅÆ})‡ääÕÇô¿éĤs&¼Òí1°DW2íå:pÃ#äW´Ó ©nÇW݊ɶ9_ÿGžš>µy�Òm˜´¬ÄMç&øôœÊ J‰®pñMñE¹>¿N²4‡œŸø¡/Ü ½d­ö�J¿S†ŒŽF¦+ãéJšJ%”†ðÝ£±Æ¤*l§j„¶9‹gØJVwiê¶æO§-ÇIÙÐÍêŽ? ¨d1�Ѹ]5žÎ€bY‹Ù,¯ó1;Í…ñÚ×;–0�ÿɯÒ�ˆïßËwû“+½dªíèGʼ} V³®{Óˆße§Ð\›J4iÊ…Ò%[A£ ÉH‹ê*ç8I�%Acy¦ÌŽ?T¦õ!Ì�,€ãZÒçóéCЕ¾“‘oP4¤hcïBÑ�S*å•/–?¹?}øÅ~b ;s¾WÈ üü,²cÕ©4†g•u®›¿È©Òýë‚fÇ,?˜!Ï�Þ ì„M&YÂV�}Úaó!…5 ZDÓ.dä·ËfhÁ['PgePNVë¸d>hõÊ\amŸ>àË^úÉ$1Ê!þWËl_£DNm‚y§sz¡f¡Ê£—ìÖܸV·=ߢ ¤Äqf¨Èzà$Ž’Èɳ7fål'­é±÷Ys˱­OäܘëpºÌfuïf9~)Ç*¿Þ;AÃíˆÀîÌŠ ¬îIi¯i•Þ^aÎ@ &;Å5Ÿ˜óc#êÍ,sUo„§I±¸Ö«®Þ–­�M*~@«�…“×ܳüààvÊUdDto‘Ó¼�Zµ>�e•/àöÝ Æã´„/§‡’æ±ÉÃDPâ%˜ý’GosMèéîfeYG´±ëI5:QÎ[Ûf=Ëe‡|¸Köìcó£‘kð¤�ÊmÂ_$u L)±æë_Ûe…Ô§ö·�Þz#Ûà¤W”»©v4+€Áù[,Fw*¥—]9“Üné9Eq8s�È\Ru(P0hør.»*œ™3„™é7fá(Ãñ¯©È¬r»/Ò\æÀ ã¯Ù 2Ö>é™î�{®J x·×›’ùè)#ï½_µ‘)œo°8$ׄþ+£‡ñ„U“Û¬[ Ò,¬P ðŽ»ÀÙ_||¿W5Wµrœ®ûBñIã`üÃýcx?%hF<êŽî½Âo 7?€`½ß�ã*1¢¹�kâŒ[8ìÜ÷&¶”yÝZ¡Úëã4¬H” Ѝ`·9O7ƒ£]„é]{±ˆjÌö”<ý…Ja!b’ïm`×9JÍTæè³ª{dkk,Hô†u5ߛԹW}Vb»~*½ ×›Ö²f°6GçÙã¹ð²‡é†äô™j &‹¥�KGïép �|7å?ßÊ2iýrD-ƒlnoÝõXgì>"iÖ‘%7ô“}S|r8ÐáM:òM\3„€ÝÆç„Cä]õ²°VÄû’KÇÃUó4adµú·aCýŠUsnd]�À¼H jrˆ<•Ê[°Ø©¥ÿ=09ÈjÞ4Ô¬­©¿l Ô¥ø§±fωòn÷áfâÞ›Èïe?îÝcqâûÅ�8oM¿TÕš‚M>ÂõÜâ¨aqÎNþc>¨71ôo@–‰™ÊÄÚùîæ{É»J¬�‚¯$bi¡nëe-YkŒ©t!gn s”’aòJÍŒ55c× @[4GS.fŽíúØþ‘øhKú?52õl¢¬–ãC³óo߈®¢ ݸ10ŠÛŒWu¹ª[!(Èüèw—b‚Ç�Ì”ïËçÆõ°¤ÈJ«ýÆ/»•½òNX¿û´g<·Â©pºnïã ž=çù¡C¶‡ÓhTÇØŠw@ˆ¤R´ôèÓôýø@#õô ŒÀx=9*w‰%Ÿ$Ébb’uMöÒáÓ‹È We§]cÑ0_´9ÒÖxG]‰MÉþž.öýïïäÿÎÿ1yƒ‹:†{±C ‡¼PªÛÄ&Óµ ËN«¥©°ÕR8Âó�wF–É`{­�ª·(õP0m|¥�¤_T5*�Âó·ïVØ865Î9áñ6×&û‹Síº,±fÊòÆ�“Xg±9d©úx¬¬†áO:ÎíÛÚ²BÎR. ¯¿XC"d`í4ñLME¢£E¥%&lÙ›÷®ó[ñŠža }öþœÆƒf3ÐV$ãJ©‡ƒœ-Í{`ã3Í%zÌUúÿ*DçÖÚ•ŽÔÎÃÖ æ�¬Y‹Òu@ KV öÔsa+ Xv"ŠÌª†�ûø\º9âŽ.§Cò‘Vé»Éc:ðm’ä;TÚvÂ]údb]KÑ‚¾´9�ä÷=”´-‚ÂÈð&ç4ÿù’Þ®ýH¾Ú’JÕ5±Â€¯Š�P–0ZÃ}ÉCvxšâ޶ÖÞ1ºzéIc;ˆÂ}­¨87¶\mQ—šõ$…sÿgu|N¼BìcÖ5rÎÇFYÄVü|À£Æ„-b÷¿p6-ï èiKŒ&m¡;ÁODRéÒí¼ê º±zUg`ëM }¦+凘æt×Mòd…ÊGW–]šî %ÚEwýø½8ÿ^ÃmîÕ+ô>ùt¶ÏTNn5¡Þæy`äÖ…Ö3gýUýþê¨P7Æ»Òv4š¾ÿzç–q»ø~0ÿï»Vžò¢ôÏt)� ÀÎÛ÷/¡ŽœP¡p£tv‹$¿]±Z††×&çgÁ8j`×(O •g³åê¿t¤ñ,çíé :ãû ¨ÝÕ‘ƒâó/Ñ­‘/Z1¿ÍhFǬ–¨7ÿ×]£!F<>å”�ëB˜ÜT̸y»ë3N0X†7làåø/¼÷SÙÃèÈJÐ¥¾`µ�Y˜²¬v‹vÌX‰‘à´2ú¥ýºJey*Uχ•÷ň\—‹m2OQ\ §7aòxߪøÝKÌWÖ³a`žu˜VG1TC%’ƒ`‚?{£¥÷_øg¦¼¸ßЬ‰7wS—*ŸÞ‹ÞZ®¿Øv¦?o Í"*ö/§?7c:„Žê¦ÒÎϤé!§ žaŽ�9hkaMç{?•£š‹ä” „Ž]¾9]øVEá‡Ƙ•}W·$†ˆgB„�p'Êh|-�J�t¨�’Ñ6€¤B(�"»ñÉ ¼“™¹*ßYþ0Åħ<Ã.yŸ -ÜÖ)(³c,¯×ÿÜ}` =uuÞdM€ ª©ŸÿhT‰í54<4̺ì‡-÷×ÙÖ3@î�ž0Q¾ò�xº Ø,@†ðÒ¡¤Lߪ¤˜•�o=«ê/r¤·ÍÓ{«( _tÿ ö±lã!Í´7jz3>™¤8sŽ$âœ#–Ãì{³\‡ÃŠ�Ã{àþGÞÇóÓE Ÿ¾H|¡ JßY)À†È–͆1 Ja�[Ùö¯Y¤8óøõûTæ8Œ< •Ãöe[ÙI«œÛQÙ¿ýP1Vwç‹Ò¡f$³ô“²Ê×=öË!¢®Bo ß×üÏoY…4ƒÃÞ¢w­×k 8�¼FÒ8'„„ç�Üú~Bù[eŸã¼²²ÜÑ´b#û ðãè“�$î�&y9\ûõ¶|îê—Ñõ Áû¨i8Â# Þ�;_š2 Ê�­Ý?CzçÉÇß­ d~Ï»^²��…;­Â"‚Ðwp}]òÙ9Í`ý�ÃÁ™fÙÅ*üÇ~5”{ZV\ Ý*&^Ti±OöfùæéS2ù…&íÚo�!zºK˜çÿؽÂêգШX•c�RK&>€"à™Ôò鷌܉ÆÎ5†ïGöôâW®þüBMrb§¬ÿzW¿úì§G‚õàpX22Áü aJX vá6~¯µdó£´¨ËþéÐõNYH÷ÐØE­nKìA"9ñV4�Z�wD¢–?Äòìç¼ÁÁØØ•t%4 ­>g�æÁ¿$ýAÖ7–ëeöf¾ô§$DŸŠm£Vòj¦†‘$±V¹y5ñ'ã©-‡GNû7Ll'Ï�r�I(Ó„²˜_tì4>û{«ÌÿJòwò‚±QŠë’¼v¨o’#ñP× Ž3BU_«Ùm3ŒÂç ŠC H}/D«§éðªe†Q9�ÓÉ>L4yIä"<˜ò…¹/ýj0ò¦Lµm8%VÚ@«k¬Þt3¥i O4‘î>j…†P<¦UYN˜Dôj¢Ð—\Îþ`¤ó ª¤ ÚÎØ„ÚÊx\áëú’Äžžû§)ö aÉžv—\ǯ?oW«¢k(¡(ÿÊÛîíùŸ–ÅPÍô>Ô¢S,Ù³™ª½Â(ŸÄWWg" 6ñV$%=¢ðzZ§A¦É7ð+“�u¿‘õ(QäG¸+pQ€(„ªÃ:4áhæáðÈîS˜7´R¨þ­¹II;÷> Äó\HO½VM9.d ³üpì S¯fŽ÷á�0ˆu]õr�§ïÃåieî·.8ª–•‚ÒîÛJñ¹“¦lL®4ÿ–DNn Æ µªÑ1<¢Cª+¯Y˜Áw1Ö}ÊÖ9ÞýJ³ZÜùêßHÎè­×ù:ЧƒSa2³xøÁ\Z¶»¨aI@}�»ZˆƒdØzNöO�`žñÑ›ñļkéLPÊÖ±…05\ý�!>Z‡¨õüVEµ)H·#¥ñçÔmGÞ ûš³µÍ =Žõå”Õ‚ØXÇU13åí OŽ˜È? ÒxÛ�C æì˹ÙÑZ±ÖžT4Wž¨·^b:/`àú )<ïÊ]›zsŒ$ª �æ1‡ì]�ä5ÿ¯0hЃ AÎzša=0–äß[6én{óˆPx0²ÅèCv²ð“¥Džù-¶èEÌý“rJ÷‚^‘rúS>ùï÷œçõž,åSàgçœã„&˜!j/g^”ˆº(ÚŽî>ÆB’0YÈ4v>§Ô 4­Ä›’¾¨¸?äÌ*Õþá±×'-¶Î~{&3¿Ô[Øš€£,ôÓnã;Ý™ºî,*-¯'…këBrÜ‹>Eô¸_Ê�F+©’øJƒ«‰uÝÒ„¿¨�Å †ï¤B°ex•x8¬ÎËg?*•LÁtYî? D¡åö€*TvA+.šÑ�Ιïý¾¸ÐôÆP ùÄŠ´q ó©”–�–&E#W©èf««äÜd°v¦cá�e9|ºÿWUÌnþ&›ÙÓ¸­'¬þ ´[½W²"kéêòÏoÆ óóëO#'pk¦0�|Û•_6Èw7*-ÕHìȨ-"ÊÐh¶Þ×~iÝ ÙÉ[€¥ÀJNy±ÇwH÷z(òuE¢¼ã ï¯(}mÙ:s?ëcµØÞÝ© ¿ßt88gã(¡»<’ÁÁ53`nÔŠœ6› O¤¥Ü†ÒdC�ö©1¸t!x=”`u@� c£+T%7À¬èà@ Ôcµ‹F&?{;éÇ]¦ƒ�BzæçŸ¸®½,>ÝÄä(Dý|³HA–¸è.^ÉÑ)[œù+Ó×=�žX×>j`¤ubÈ0©\ÉÎk¹Àß�ßü.ÒéPÊáÎh�kÔi±™wèS£ÒV« ñdŒæÛd‰wÚØÒrL}‹[*ÍbPÔsZОŸ ˜{„%‰¶ù‡Œ¯ˆO¡èJƒw„,ÄD”ÕmãÜ%QDìß�öÓE-§=LÇß©˜† Xß„àŠ¬@N¢,à‡Px¨]›òh¼ÓÅR’ey»|­-ãðІ¡ß£'„ŠdŽM—iló×A¿qÔ{ÑmW±hV3/ÓNÿ�¦-{‹ËBûÏ<¸4ãc©©™àx¦ò”²ä» MºŒíee]QvW¿ý¨ÿ˜e<.Ö?*LÀÍC$LðÌÕ˳f;G¯¦bûzâŸ:¡Ôõ‹¢òÅgT€@ÉÖW3àº_¼AdV)¾Šee"Û™´Þô6õ@*ùC(‚ÍuáÉ¿ †o•±pÕa²q˾oÓ(º¥¤’‚•ïTÕ1k`ÚZWµêuÐp²4—(Zjå và©o‡ë¹{Ü0 ‰ë7î $]øEÕíeû>û“ïE‘HV-+&b�ø'\0²ŒaeN»ïr¼2hÒ=CÃüþE†Ïlúÿ�|ª6üXÚº2J¢»T¨é O¤ðbäÀ¦öie¡ 7[õŒ™¡â*8±gÒ@þZHÀ@�v‹!LSÂd(Û¯V]$Ëx¾Jt-á%3ÛË�â²G¢Ê%]ª2GïÀ|÷:=.¦¡“^¨„ðÏ^%#ôî%ºÖ¹=þCvϾ9#½Éå©å�(ó‚‡7 ¶@è¢)ª b2è°s%ꃥ•²oÔsöÀVÞ[õYTþœKÓ"ÙŒ¦2ŸÔ¹OCàumzŽýY�\†ßmÄ¢àȹ6¬8¨~&Qi$eXØÇÀJì‘3q&uÓ— K9@À y,„&xÏ(�À�?�Üé©­ãt®öJIz*‰žSìðÔx|¾ùç¨úÊ´­nWZø6f  S5ÐØ‰3ZoçK¶e®ª”AÜÜXÿwŽ4«ЫÔë‚WÓ�}x¯¿G½æÂ¯)\8‡AL{~δ�E� lñ±“„¥‘=Êô˜þQ,;…óÁ|s˜˜è34 uÏoÌ)¿ íCzä ÕWæCV6ðØý/ïvµVê>(Ǿ¬G—„c"XFùÈξ~äÊ ºSl-=Õà�‰p’IÔ¬ào˜þÅdhZ¢u×ò3+··¿ö\1 +ú¿ª*,+¢‹$§%œ�Õ—ª<öËal¶+<†Õ‘y¥�Ë-ôZ­ñiy÷ ‹% �è“a §Ê Š|B-½ –N»øy†<‡{4†&]|Ùcèþ²çÖöÚ×gõTCÉC.ñŒºK¡ç^o¨±áBÊ<ˆ« ³Y×§Á²ú—A?ØÆ…€,’ÿȼ½=pÏÚqILXDõÿƒ‹:ÍØ¦ÂNM%§vÎùÞQÀ¢š,ç­ô±ÎðÙîoBÇšõzÒ=$ 5Ét]•æ¹+ýMØB__½ÁŠ‹œEý¯ŽQG#Y‹é‘8–ýXnݵ™OU¦G�«Ž/¯T7#u¹—‰‹Š”ƒ³„”S)f´KÀjjѹ!²g ÊgX1ôYx<7ØBìä<{ðL"M1Z4 ²g)_ˆ6qm@ä韣—ìV$PÀÚA�þv˜æÞðlzª’ 75Ꞻ?lè\#ãçï…ôL¤• WËLÛqsåýDHOQ£ß.$o‰ˆ)çRË�7f�ú�ȵ.xZ�VáB:IŽó˜A†èñüÞ£7` Ã^Qr÷UIýJÉü,-ïÇ2 Ímäk~{Ÿ¼B" Íæ�-äƒPðЋîê•}x—^±ôËÞœSþ¼Ý×ñw˲V½3¨ËuHÎ!#ô­“˜„QLYØ'—ë0è'B5¾§ÊM1ýª|Ì#Kœ}�¼—ÝP•±É†%ë zsœå-°¿Ú\Ðå}¢‘Íy‹ŽgoÁ< 5ÄC‚'Ä'=¥Q¢äZ éIa"P‡„‡Ý|VÿVòk;‹ÇÎý�Ê&ª3+ù�à€|R’ÇìF½P¬~®»Mc B'r£c®«Mßþì=|ó‰-½Ã+a}òûÎU}YÉðËùþLʸ,‘ªT¤lêó Ühš³ÐC� –¥ »,†ÞÑ~œÐ]¬áW Ù±éþ`…L5 ËÎH0%Š+Ûød÷¼Zd¬Äž®Hß¡àzê¬HPÊŠB¢n†½¥Ð³–J#ò~V yÑA'ÚKÓ(ò¹•ÌXì×ÐÌ=Jå‡üh)·ÒŒ®È7ê È"-¤�÷Rï¡qÀÉmÏ€Â"c»H¹Âø_“™¨,g�m¾Ì_Œ-Q.ÂòõDÖÕ*€AVÍ«‰HV9©!Ð%«Wæ¾á;$ëð÷ ˆ3AU™:¢Ì'@dS·@å¯S£MÅëÝ�£ÛÛ)¿,z}k®][ü&ÿ­]fñ h,9{1eÇ“�©ÛCI²ÁžÒ‰S}2ò€…݇xîüeÓ(6#÷˜#öà¨/mÍN|ʈ«KL}Î$Vóåã݇ G*íTÑ™!!÷]†·òíNîÌ}7¾Êºw'!ƒü,›xš¡*o ºô;Чp„z‚ å%*;ú�>î°”‚Œ¨è8U˜V ¢D* A!d$x-»â¡;Öätä8“žÓ•r<ÚÜ í•°ȵ]Û—Œ³ÀÉx$u"!6ºÌ‹’Ö½CvÞÙ 1§D0�ÑZ휒é�Bžþ—šm�C`jŠÀ±ï÷UÁaNf?R”ãà²tz>%ò—?¡H ý%áyprÍü¿ œ.�¢‡sÖk 1Cõ,;…¼|Pˆ~_�WÃT{Nã0ZŸ_EáX+8>2´F•]úv•ëh3»„P0È`ˆ¯êÀdÆw¬—iHëÿŽ&£°ò¯³’BäY&UprrÁ�ì×üŸó™ ûÍ-P«S¼Î©&~.\¦˜hO×!Gáãüd|fD!i7ð„ˆû9;¨Ûzæ^¦\Ûãm­ÞëIæ|á¾�ˆ÷ÐËPt=S„š{ÿdx¥rH¤;éBƒ(y¿—Hˆ�]2èÿm-§@ì]Óc¿¸©ÖUY‰áÓ~2L$2ÍÂ9Ãmß ùЉjåèÜ7�©ȳŽÂòÌ.¦á¶REpKh6ŒW�¦”†ÖC$y �±œ}Ë.ÈšÂA¾†g±¦7*@ù]Ã¥j@†í~‚©ƒãz7~ {}…_Î÷¥¤ÝLº'¹’ñƒñ>•K‘—j�úÂS3Ê#˜ ¸£Þ ©¶ÏäQ=ýbœEh@B¨f~‡Vª5×£(¯iFÀl<œt„)·8B[V>ì\Pøó…¼ƒ~Ï[uû–ZR2+^4aO ®Ò÷‹¼�µÏÞ’àåãSKãö`=4Åé@Ö%¾M ƒ0-ÿE„È!Ö¹5ÅeBÀƒƒ¶AÝnm üÿ´Âñך/á©¢�â[,'%xäe¨Q•Ò®í™U–Ãû"ÿÞÄ«è.z+Òh—¬�?¹]#š”Rùêíg;È>“Yñ~Ü¢…ÖŽ)×KPö èK>.•>R)#çqö¼)Û9ÿ*YŽ7þ1WÌ|âýÆWš�%¯ðT¶ÁÒÓ›¸câ„íz|çžP_ù¦8Ã?_(~URø ©¿Ôj–«þýOb†²cæ¯v¨ªÅÓÜ#ŽÚ�´ãú§Ás‘ª ái%tÒPÓ ùHb­x* ÿÙ7t|¢;h~‘·ü»æ¥sÙÖ)å£òè@ÌÛꥦr¯2¼Ád1Ñ‚Ú6†Õâ/âkšö_~‡4d(ø²f¹oThúéìÓt-ªIÃR[Ä/ÍÐè&ŽLÿ8†j5BÔæí/˜¡¹›Áa™nw/iK6yùA×NòÈjºpZÂKHî‡ÅK™83EN{„åÉE“Š#q"Ý$š8ä g¹¸[“,¹˜x}¨1û²6“ #®*E²>Ê œÏŸ)‹d£ؼËf½—´¯�ШJO‡­VrZÀ#6Þ=Žm"İÆwnúœMìŽíá‚Ï�,€Nf˜Õ%L/³†8ÎhQ¸�\è‹M…0þŸLÆ´%ñÊš™•KF~RÝñöÜÉÿ€¢>ñ¤ ñ½´#CˆØ¢ˆ¬Bܘ¶ zš�€±IupÝdGNˆYåÀIè„ÎÏ—YUž®dÙ2_qÂR_o–ÚÈG{ÁxU&—@ÓîГ½ ¶-¦†äú�ú#�y”� {Oµø‘¬-º¦Ù„�Ÿå"M¯øÙ�kðÄ—E£çN³Òäª7‰j ¯Å�s´Õ޽†‹Ñ¢~ºd’�zºÓ ÏY ä’ =C€úñ”Rúþ8ï¡&-!ŽƒØ\œ²Æ“�¸?EÆFŽŠÓHßoRUé\í워µýIÌ‚ã|¿É͇yàÆe}�Aã°|þù�ˆî�ãÊ %!̱+óZÖ JWY)¢ý7Ë"oA�Ùþ,Û‹5›±Êd7áË,fòCs�èØÔk¼U‚ÌE{hÑ Æ¡3Që#!õ¾Àîòg7‡n(渧?ŒÄw�;ásùTØ òΆV#‹n¡!ËG:£=XR¸ Î ‹YP _*Xêä9{ëÍZ¼ígÿ€-¼1Ãi?Üjüቦ1ÕCúýÆc»ƒ ÐpŒ#xùSü$æ&&GÙÑŽEÅív‹òæÃCZe‘7z:¬?g›ùCºÊÉ0Xô›9Pϰóœ}×9 ãé\NÙû¤`Â;S1‡xe³B¿«ýY’vPWÂMd9 ÝåO3Ûò°tľñÜÂÿSáE©Îr¥Þ”~®DXÒ¹‰Žy\è;êá9óEHUšÈÛÕYq¾–mj–(º�ú=¸R[tæˆç@͂ͺØuR=ïÜ$Û5¬ÌwÝ—pñÔ d¥Fk˜û³çª•›ªUÅs =l'Çõ4:ìõê0„c ÚþÒ—Ÿ4š[Æî³ß½¦Õ”wäÿ{¥Ó�N@âäœËté=ìåht©>Lvó€g(Œˆ†eîø{žŸ‡y/{d {“WIxØâ°&íQ‡£Ê›>Šèîî 7§(Wzà\¿Žž–Û~Â˳6éb±ð—„Óeƒ¼ &K¾Ð-›€A–ò²<½‡Žôêäq¦?þCkH'þt{�ÊV}“t�r±{ø5Ÿ�¹>… ¼ªŽAñ°lÿPTqu}Û”‚¸­Ð ÑhãvÆÑÄŸ2Ó·‚ù/Ät&2�Xt~eºa½`÷ðÚ�ŧú6úã…² eõ7臮”j½tdC³\‰ö M°§øÊê�]LYYZ>âìö8(ž£iÿ«AšpJH&#$Çß!�p©¾äF¨B†æY�ÏKfjiàIÚˆ,øïÀ NQɦ%�‚tzîEì/õÉ8Š ¡¨Ì`‹Ñ³òe�áÇáWsÑ\ qàfÊø^ EØsHÌAy“ÁY!)ôäþ ÿZ[T9gªlu·ÚØyHfÏl_GÁ\“°.R«uÐ=¬†9ž-¬H£ŽÃò#È(¢omS,œ­ç"ù)£ž¥nGÿ­;èü$x� =”8,Ç€ŠrÃDt†Rñ9G�„|ƒ¼ðì…Ò–“¾SU™ëI+eÕ³¦Zu6cƒÿ÷�ˆú{érõÊz�R˜,ù¥4¡M|« $”¦c7ÔÐË€’„ßT߃ƒÇM3“"¹5·w0;µTmLŽˆ„‡ô¿¶€‚ñ�Ss#æ¬{'ißxF·µ”çÌÉ¡hHìµÔÞm)Áˆn.¨²òÝtªž `ei‚´ ;(É�zÿÖÅí¾™@¼Áh${²AÏœ‚B¿ƪ8·å\6X|ÛΠ1¹ h¬!§ÍrýÉ�`$=[Éu*d®K¢YÉ=‡`î…ËT™è.8±ê¿Ê�2\µ`©!&Ö¥Þì)ê",Y ×ôóÞ8¾ºæ)w/8³S§åÝ*I„=GˆÕŒá¢Öuí+�P!©È$.{Ðø¾gb©Xøí™ACȺßëÔSºSF$Ä6—ÓšO±{ŠáÿûG¨»)‡óVC…Í Ùæg‹ešQgÄÌ»RêQLGÎò¯ÑšS‚²Ë x€ `òÛVþ}%v�7âúH{8X  \¤ç·gæb­·Zqœj‘\þ; rðDû(ºPY½ 93<šZBÿœ}ñð�üö!èîÝÕË)ºEJL¸ÒòêJÒ$Ö‚¸ì./…ª®æM¯ë‚÷&"xî,ÄÝ K*L2mC%jv­Ó×Êžöz™üX#ÕD{^î%Ñ…ÑíóœW.ª!ïMá½Ùåæ÷4˜ÄËA8"Ê ˜¨ôZ ŸB´ø®3¦Rñ’6vTz퉕p˜º˜†9ó•øÜµÓ–§ðsµúA'{Âúà�ð‹L¢ ›)ßÒ(¨FÀÌkhxÙ§R‰0�Η.Si¹E°d2Ïñšè�¯Žªfh,AZb¥þ¶ÖI©y«¶Ê/gWÖM.µ‰òa™œßœ]¸"붬„€>­WußHÆ?;_Sù¶ÍÄìäD9FXù`d&C'LqHÈ2 ß.±È0h€bTóßÕÄõb}ÏûX`9ȸp±èJìæ”GI4Á<4—ÓùÚÉ‚JõsÚ‰‘(fs.f؃_a¸£oO59§ë…'` )ÿ #òéÆˆ‚L5>”nù*¨°ðå j÷s5V^Crz²+Uû" Šw øÄÁ¬<ÖO²ÚZïo.ÐÊ‘fSYõQZ¿hÊühóøÈ=@é€�<Ù±ÈÎ_äÙ/+Êèì‚oÔ‘ßixEû9 Ýt)ÿyDéßж_!:ø¾¬¾×Â9±½‹+”>µ²«oîÁã8ÄDÃŽPÐÕ‡1!¾ôQZxëEueÈ•º|í�æ—ˆ*VS1©¦jSÙ1Y>Ii›µ–wŽÇ˵‚M Æ i2¤Úad½æYµSj£Þ•wò³’;æ÷â-ÂV|»ŽÚXHh5ºSÔò[Ýy[ïäy̲áw8ž5ž “] l“¼‹v ;7I–ßÈ÷ó†vôx�|d„õ°C¸þ8ÄïÉJSSm†a g~ÿ_ØÎꯃ@wRa£×i¿y»�VñÁ8Óª"m«â ŽÀÍw âú¸ð‚¿†ÅÜ­†QxT4vÁŠª$ꈗر¤-¡ÀVÒ b’(Vѧ©tL-ê,9;Ö+¿MpúÝs¸{ã5X‡›Àæëù¨�mL˜hŠ£ÂHïð&Ælͨ"k¼Z(˜<«1pswgu¾ æ¢ ÍÍs>³.ž™ÇW*2Ë7jqqcq-žÌ"°×}¡ô gv±cC„B‹ç 5xM|„Eæò„ï3·fTD§µt�HÓrüH÷Æ>® Ñ{B÷¿ÈÑGDGZ»¥ Qîk„oõ©]ŽšÈ³K(º�xXÅ B•dãÚ'¢4Zƽ�;À"!ÿÔ³tÉ(‘áGcâ™o®vZ1¾7¼D¹[ƒmíÑ:Qí•Ñ@&€íÄ(e˜§#n˜–ô®àüáO˜DÄîÜ- …k´že¶¿^ÑÍÂQ ÖŽüßtu—ä)‡c=óSœþ�cæ° Ü(%»>7ç ¡ëÐ'„dX$ÇKn‘`ï§6g‹\©‘!z°º¸*ü„S º?c`B›M–¿˜ O„jÂQL(·q'Õe®þ»ýc"ö�8‹›ÿÒÕDeÆ""VÁ¹ž¬}ÍìU©¼–u»Út—Û#b*RÉä—}ž[,+^Ï;hOÕÀyûãŸ`j¡ ±” �iEJäÅ Fʰ¥„9æöë¥"Ÿ?ÜW0QÅœ—RCAâGK¬•jãEwĹ)6MçŸgqà$°Ÿló’h9]¿¬BhEoá'#¯)cjY¿RÝk!ªX«ï˜ èì8©‘{i&{¿µ,Ø�0úS,ª’U_$: Ví 7�å`ʾ²2xj&>¤bkz´·—ºQÇÛÐ ÌÖÍ𳵯p³î}ÒwÇ$Ü¢ž?¥0ŸWy(ÑÆÁª Í’ë-îu‹jé170¯ÎF³‰fäT\gò¯¹�¡goˆŽO¡L|`¯HÑ Ï°O`â:¢_Ê&?ÔÌËðËPÈ�:ÿ¹×Ô<ÆÃ¬Drid�²±ìŽ Wò!þ;÷ÉD?à”.?ßʺ‡‘+OàL?VˆÞÜ•Ô5ÙUv¥ÁÀ¥3Añ즗h™qhEèƒRd5‰öKÑX ÷Ü{›ÍøEc�x¾6z%¡©Áš ³Ñëì+ u®Ä±W˜ر:Qç�ãH ²S7¬ŸMÍŠ¶æ'­z/� ¨DIN$ì’0¹˜Œ3º¿­ ªB”iæBç·®è»íØV*^êݘâÒwX�Dö õž›¼ËCun{ÑI‹fIiß¿ÎõE7 K­lJäá±õb“G �„Õ 2½¢ÉÊD¸AgûªzyZÖé$€ïŽíR‰73(k«±âXJ·J ×ìKþõGðQDæ³DtJçðû­~Õ|à;súO¸—UKâ~zCD)hî ©]µ}‘jrëÂñΓ<‡öóP¦mèZdÝÛ5k@x„ˆÕãR ]eÈNV-‚X�胆`ÂZqVµ¹Ö0‚”¤)4þ˜p®a•OcÁ±0N¶�1Å%¡F2¤Õw®ÿ¼µ1«ŸU”¬¸E–O ƒu€wÈ Åo«×ÑC)®%�¡µ¶‡Ðy‹[û.!š¼BG1í¿ä‘å26æa!î¹Dx�ë“5NÙþCq®•€œeÜ«i9«4ÍÿTúXTåGÂVÍ|ƒªè 6 §jðUP]2NK:ˆÈ"0‰ðêˆTꈹ²ø ±°‡ÑvèA> ¨ÅbÖ&úk«LWëñs§ª!φbÙbº°†]lFš«Ó4íåd…KÀ�ÝbDi‡Åˆì™%µ»À/ãé“CI˜èøQ=ÁÞh/C´�Õâí¹½ÙÒÍÀxÁŒ‹Ž-‡“×ÓžðV¡�Ó¡ôÃU#˜m DîªíϱÖõ`¾¸®´Ÿéô+XSL*y7.NÏwæy†çG1f,®~©Í³½]¯ÚˆÙ ÝQÔä�t�£fvqvbƒ܇PBˆ±î�f­e¨Ó#yšYÈÀ€þ‚Q)õòNkãɼ(‘Ë:/[<}ºøAsIá×w“Pˆ„¹oyQZw6ˆôîÄêi>wµXì\d9óÅÕ8Íkᙄø¯¿Ð¯Åp åïTrZÃT�t;6h;¸ŸA„(›1„ÁÍù}G�¹6…Ö¬…C(ðe|›’lO2VËà‡Fœ”m%DÙÀê»�» ›{%úmòd< Ì®IZñS&âò§ â®Þˆ]ÎpîØª½EË ˆaÉ ir\϶´+i��b)pÛýª7ltd�Þbíú“2½…-?éØÖ�.” gÁ/—Gb.WªÓó¹V�¼<ü [Cðwøp�މÞñdôßàC·C‘bšs2Ožw#Έ5l&¤“SuÕ¯s‰�°™ÿOV18À�¬´OàŽ¶) Õ‰ÙgÕGžuù纤(±>7Æ,óÿZ¬�äªòkF–¨û;ˆ [C^[´ùü�\åîS'‡?Ãú"ðéú#IœÖ”– ãTyíï†6œäÂñž!‹ ©Ï;¾1Ø3ÇR‡Ž…âR:Ý3¿•ßõW*‘$¶pShJ/ �& +HÜK·hz?jDÜø k¦€r®±ø%ôíp�9½’×£`fiÅ�=Ì’=«ªþy†cÀ�ä Ç’)//Þ½'±m©4îßNÀ±ó.ƒƒ¶r8ø ca'IŠzãîŒTÜl­ÛþºªØ]Ó¶' ò¤à\í™þ:e¥�™ð^ß§ªÄ°%À»Ú‚…†ùÛ �…Cû…ƒ./¶ÝmÆTcAâ_`7§{-ÊÓ|Òª�gdãiâðoå` –¾ÕÝnvJÕ”‹/oÿÏ\û5¬hD�¼ÁtÆÈm¬ª›h𰙜¿Ðk³^1!dž/¦Ll%3©”•cøõ,‹&ó32—p$éFõ|Ž:›)W«ZwÔ×êÜIÙ ‡»GI*pÅ “}ê¦ÀH£4*1É´GL(4wØé®Q²³ PT“Γ¨BP‚%oB·õ8ª®Ï@B¾9°0ŠŸWy¦Pøô>4œá•ù-|o…T±'%(Ø!WYès�¡HëÀù+2ÔhÒ€pûù> 5ª8ûðÙòªÄ'�°“ÇóHµe"ŽÄ(½h0ÊSš%È™ùy–�®°=à œ\)O3°z-m˜aKzS†Ç4‚A MÕ2QTn‰ÂäXñkÏb•ÛᄤÏÁÏ Ççæ,°"ÅÜ4Ú�Rv]ïC!qªÅjýC38 MT6ž}�ÉmÖiyàÅ7éÜé„5[*Å¥f<Åé:»ìÍ!ÿÝe]» »WQ¦�‡PTØ�G;J~ ða3#ç}¾ãF¡¿ˆdÎ ¦çUr7yf55Ê(Á=$ËKòTÊc¨eÆÉÍYàüL~ ¬'gF¨øI+'n�¾ƒÂïZ>õFp{4o-žéÜ‚Á@,<»Õóz›¡Œ}ór‰,¶.R<*{‚ÎåûX1«iÐm®Byûl·Yova裴Ý«±èlKå4S„Í2þbÞì Ø´©¸Î·Hq»jð×P0%=)ï^ø�BžØœðš�å�^µN`ÑhÝ{Î`¹Ã&½Äœuâl2dŒé¿ ¿®ºË“‘äbŠq3äˆØâ6‘à•=vovÕ �˜Ô‡•ª§%ŽBÃÿz ΢¤ø/“ð¥K‰Ó·áu¤<·Uo¶)dÆA�Ó…±å 9# gDÅ¿4ɳ=öreÏ÷Ê8 )Úbñ»ƒ�Ãá"àÀ‹´wx‰Þ¶¥EÄÉ0¾6ç½¹an“×M¨vN«^ÐÐõÇKkª‚Æ EþÑ|Spކ¸6V¯×íŽéöwP\#×e™F¢‘Üyâ*¦§Ã#pWç(1/ÄIr¾8!À_)œw½/7JñHgÿ�õùTs—®Ù¬äd¶yÒ„ïô¥•ÏJ}' è‘ñCzº1Õ¶ÙðÔ_¾í¿ÂbLŸ£ÒÝÛ[þ öKJ¾‚uÅ#ÆûÝÙZÃkf§MŽ�ò?ú*­ØÑ»)1éä¬pmJ¿ú¬h?Â*47äÞYã— æšË‡Ü[6Ý:òèó‚AÒTÇüá/¡~ã¾N)ubc7ÔçEm»å°Ør¤«Q+»n».î—Tþ›í~wmà ––q€ ·0SÆM`ci÷z¡m”$à¸w'|¬751Èý•Æ‘hÊ�‡ü3ìVʃqN”š ‰ßÕÌÎZÄ,G˜?¼zw Ñ'á‰awÒà”¶ðÝ6ÈŠX{±¢U¢AZq÷CïQšs¥@W^QJÑèÞü]#&OE¦™ø!”—°2µ¥�¨ÕÄéxhË*ÑZ\�ù0LÈ=ŸyNm’KÀ{H©8•ëO4åÝá*º+ì88gU,üv¼²`äc²«¹ÎK÷¿nÍ÷ª»>"e�>:c”BXïñ»2”Óu:�‹xþÀÌJ#¿Õø„ X{Ë}‘Ôa)ɦQª»»èò¬cÄr"$]·GÞí í€Tò>Ÿa.3Jܤ:ü�* W¡Âá¦Tfù]d‘>Æc5i$ˆ™ÄßÛ>3]CÙñ¤(5ûô ¯ÁEu¡C㊠Û;,©Hµ %Hk¾l[Œ’«cu5ûáž-f„G�±1àßööý¶¢Ãƒõ˜Q#Ç@âž,»8¾�ƒÇÌ>ÌwtêyæÆCeƒð'é^wî³hVº/>l?!É Ù8/Ãù›C½!3ù¿£©é/BÒÉøã*TëýµÚ�©œ_"£Á>. ,9H#¿®“< RJ ì�£…Y«“ûŽ`§Žh»pc?aóË0râ–»[#Âæ¡H(Óè³E Òâ"Á)Ñté{Î]Ÿ‚œŽ•Ù�"nñçÁÂß•&lЍ°�í˜ᙺÄXa(nIÎ$ï” Œ—(¨Žž*¯1»Á&”wd×ãÒh/Ë.{õÌã�€tÜØOJjƒ�Mh|B þx›°ù3ÞóôHKuô‘ÿ?’³òOø•$¥âñÐHÆ¿RaÈ8óL ”)ȵ£Çž&Va¶�;Óúñ—­°¤­ÑN¢Ú¸aÑ&xM¡à ¬öAܘ> ëf¢‘¬�Ï_W¹ÆiG¤mÃP; yÅnYÞUC‹Y(¬ÂKP/ѼíL©"J¾Úú>fÈÝžÐP4 ÛZÓ¹;² 'n¸ËÖä¥á:zt¯£D5b�eÏô¤Loù â“æE¨Ð1µz@Ãàð!IªAêÒJVY¬9E(ÞL˜V(êgé~àžŒ1—&uŽô[¨An$À*6e„j±ü>€#_ì[ªý|&[ÐÀ B’áz  žÅÛ9ϧÙxMÆ•õð úcj›à¢£“¥jŒlÒÌGÕà¯dóøÄκu„ÖÐV«×ÞŠe)rx+aÿ©¤du‘Ž(šµ²Ó׿_hi¤»2¢‰ذØCõUæ MÀëæ�/¥¯¦zr¿š—¥¾¶~`&õ¤#eΧ¹Â_'ÕMÊ2ÍÓ¼á�ÐXM:G|?ó<)òsÕ’e– G…£ý?ÖEPåñ| ^^¦�%Âs ÷IO0ÉãR‘žÛµ‚f‹ÃÊ· Š·ÙÚÔf Ð�³rùÅ»sÚC”ü}-FZ©IŠŸÜÊæ;KBóJSG�§hpIÂm5 1DnÂ\/¾·"<¡]Õ[:Ât[(½�•«�‰’<òE€x ;�‡ìº¬“>´�è~š©v»œa6±•7Ç(N¥ ¥°Díö¿<„»n› c°IÈ![™¤²»äÃkÿ½_ß~"Üø{4XnŒóC3ö¢›¶KûÄšF05úxRé²ttž~œ›VCòn3‡t¬FB³Ÿp0ÁÆùè] \ó�*ù¨QÏž”¡-N"³áÙï !�ùJ ³ÆéÑñ!ºñEìL¹:•O�k +Q ÷œ#_™Ü“•,íÔ‚$ÅôvÖÖëà@ ÜyåÈ…Ça~?ëößüMUö’Äýª®ýô)^¡LXY–æö×0‰jW#L³,Ï›KW ¯ö†s:¥»~OâågèØ Â„Â}ûºÖng\J+qãÝwµb*3[!ñûŒªé‹qÿþ´Bù�‘ðø¸ýÚ ¹!W{› ¸^Ýú#â˜G¯CŸØÇÌw½d·Ú.i9»ña!Ç‚bо—�®X>YnbÐì/¶bº+‚ö—+‰ÍëW³ê�y¾ƒî=W�EÞ5:}žhêƒ8î²ÁßÅ�ôå,³ŠjGK€6 §v­ ¿ÒH9x#q° °ùpÝwØ´Þìî[^:ÐkV¾sg}<3ýƒÂ‚@bפ"·ˇVžÈ®‚/¨JåDxD¢U9%é&thg]‰WI®[ˆê”‹oË#è]@R‰  þñ´[üÜÊvÞŠ;¸˜P—,^I±‘.Jè� :R»M2µPmc¬ø#|ƒË 5›ÿV™½i³q+½d¬ñt�‹êQtl�ò1œ|+ðŽX¤)A‹Ä€øæQÈŒ„E“NÊ�GI*q¨®ÈøI—óòt¾unz¹ä1éSb]…H»=lÛÕ…*/Ó=‰i×:D¼Ÿ(ÍþBkîšØ&PÔ ¢"[,NÜ$ˆê|}¥¡ôÁ™¬dâ¨d*»/ �Z…ko–H$LÊ](æ^ùb炫ɯ­×@>—tú‘EÐQÈE9ô0 c&«€@ZÉQ�ºš2�Kòú�„T ƒ ÚSHíä5ßʸÍX £kXG+Ыg¦Úå™ç%D›“4ÿ©±ÝˆÉ£’»Í÷C¨�³h\a.ªÍþT-¨¥šfÌ6íëÙ[»ít:‰à²ô'ÒÇþ¸Qž.ü1WßÄÿ8’>�Až�YR®Ù xê)ëé$j¨D{�«xo Gc¬Í’8Xv2¼ˆíž1Ú¢Û±nÃÿ«Í¿öí¢@ùKLžíeáñ Î~QîÃt}í‘$ÂB–tŸ^Ñ”`àŒ$S¥‚x9íÈŸ½­ú@CÌ–ùˆˆ­&ß{ ^pÔkKS—;5ŽwÍ.…›u¦úd¹cè[C€^u!䉽餿ZÒP¼>³³ }Øå²µÒfüòµÂ&âwc »t¸©ž ½ï\!æ`_¹†POíRáövœÞ‘ˆ³IÎ�jí}H' +1ª\Kfš)¶x€ 8NAµ|ÀÁà’ ïµÅm84¯GŸ­þ�m,6€˜Š«/íO– oH±×’Ê…c¤c¥AL€€ h°àBJˆú€"~üØu�Û%Æ' >S&ˆ(ÓóÃÖ ã�_Ïæ$¥1-ýhZ(Ø7ÎmÖÔqØÃe^“×PãT^ôQzž5ÓÌœ½Ò'”æg2IØ@å0ÕAr /†ø=[µŽ^ R6^¼¥©b­rhk÷üLÍÁᓤ£[Lè–Wĵµ}$‘›[N†j`^_L&ÿœÏTU¨Ø‚�6¤^‘7ˆr¡D×=6;…U 6XtD¬=O¡mDð&Ïð¸OãŒê¡jyI™û{CXàØØÔ¸“<ì›ÿr46›¯G�e½phÝ`v›§JVŽþlÀaJÌ£Ù»`Îsð ÒÜA :é>ðµ¶19„P((ß©w5ñFþ¦e Û&Ñ'¹’å¾)†?eúÀ(:.ÄVS,È}~¯¼¢xpv%‚–Ãsu£åoò–¼£ ¢Õ,¦~}Í {´WÞ…Ìéð¢˜¨ß ÌÀ@Wí4›™…/O©3¢Gãæh+¹Z;ëǘOó4OÅä²À)x�³'þÃ)¿L²»‘¡´Ÿí•³£ÞÈx�tÅî_Ó¹GÝùÑ1ÇSemë6¬s4§ím)Üõ«RŽJçÝOå�¿ê æ°Æü¼#s�%'Úï†�0î±Û�OÛµwõ¾´ˆMáq#ëK|@5cFrY]/>Ô›–ûnmÝûÅàQ´qEØ­ÅjàÀ ¯,WÃ6”­`&�u,ÿŠŸþC#ç¤íZ;™¸�›¥@¸óç¬�,ó!§Ë­ž½Ïs ¤LÁ}]øŒê3kØX9ˆËi›bGò$Uec›ý<Ú_‡'ÑÖ£uî¶n/.>H»3¥æ€BíɺLIÒßke>Àd½›J)“üë>¥ô›ç–ú§.ŠÀ ^Ä­2zÒ¥Ë(§N!–„ÈÄý ê@±W÷9ióSí_bܤfV“d@ÙJ8¬ÌÚPC'Ç'¢Y]ä¶#À“T¨ear�™Ó¸Ô®A—9ÅÎ>[xÂ:—�³u®)œþ³g3z Lºf¼%8F M�»x'c¸Á xÃŸíØ¶K{ÐøÁ'¯à) ·çhÛDɸú “ÐSJ=ždܵ|_{T`DFŒ4¶ÍUж®üo2 lÅ™$‘wÕê (Évyì₽¡˜ôùv çhc`JK2 ³ýtœÙ§X\sÙs¾=-æ_ µlJæÖþ¼Á1—CäaœÅ¾Žú7k£;zwM0ÈpÐÔ_`«£÷ßЇjò^É/œ�ä–ù˜•av+ôV ø²º dJz‹ØñДÚQ3™”Œßy{à;óã­ËõEwÔl…ǦñâÆhG·ryLm4¶¤tÔŠðDZmñ±˜õÉub‘ddØ+FAôBµý;3f h(ÚxT¼ûÙ"žÔ²?ƒùpWuß )õº¯§Â*�I'z|c�¡¡(ô”m=ÃùÁ&N x·òX­¶_eº,­®+Ê | + Ç@rLó?¬X«Wbï†h§ ׯ&0G^+é‘wç1âtémJê·Í°ûŸÅuÚ ±;ŽTkˆ8ö©þY”¹!gÔ|pí’( ž&cŠ ô©cÿöYTE�s†6JY·À‰Åš¨«W;_ñÉÉÀ[®M&CÈ–kÒÿòž5¤—¨è2 0Ì´Kä"â+7 lƒ5‘å”3­Ì~žJgå|Ÿèüñ)§gs‡cFÏ?¬¤b«¸°¬µmrúÕ÷–4¼¤0Qž³-îï‚<.ñ@‡ *;Ó±Ëaª#ŽéãHµò ¸nñSS—낎bTÑvîá�´öx óæSϘ„ÐŽ•¶hã“´ïµ`®6Óô #9m:4ŠDE½èj¥èkåÄŶ•–ƒ¸>ÙùUoÙ”Ø�'‚âf×iG™j¬D4¨f=6ç† 0IõŽ2M@aÓú–p }û´êÅ€Ë5Œ1eÏÊ_'7ƒÐjó¼®R¸À#’5;V¾ 9‡Tdºð»Ñ¡Èv2îï3uHåø|t7h™räÈ)þ*ª”ðýŸQŸ*{ï2E›¹†ëºJlCl° ê�2n(Ð [3*S7ßÝÙ·ŒIgo3ùnç¿Øà˜i³gUGàçcX*”¿ôO(ÿ°èx—Ú�å5·wÅf¯¨%Ý$²Æ±�Y-CÕ9¨HvÛ9BPkcR>2 ´P�0äªSæ~xúÄÖB¥­!�Â1�֚ͬöÅá’Ï?}Y_Þ›nø‘\;…ëBµÝnŽ2›ê­Ž�áaþ‰<Žš/ꦆ²\¶Ûö�vß&œE2ë¨ó&¶)Jg~>cgVó/ðP°·ˆƒv©LK^,–äŽ×Tw3"æõ¨ ›X8‘�žPù³‚ŠzÏG¥§Û—O°*‹‹ª2#F•úçàœºçî·Šä>Íìí~0¯,Di·'Þ6¨5!C˜:ƒYLfÅÚiI Ðráâ¤u×Za²óÙ.³‰+÷sû¢ÖõpRêÆ8 ‘ØùÔQ74Æ.m<žUZ¿¨¼Rk½Ý�èìÂ.olÒŸ%ðÌ™kéØ/yë‘åL‚V0=¯12P)ãÞû«{《2é…':¬R‚k4qb[˜ÌçË~‡›¶d†{•!]%&û1sÝ�Ô.ÉoÞÊ^õž¢‚à.Û¨ÃDŠ îqñ·{¹U㿺S؃d°xõ‡HrÓH—Èš–ˆÔëí'ÜAÀ,/8 ƒ+9Ø)—d°3c ú¿ÆŒ«FLù¹èï�QbåVïLD5„ žŽ…•âëÆ³-ŠA†^§ŠÈr(â÷ãi Œ›²þ×ÞúSÄ¢ïÒb„ayÑòÑ¡�à ¥øRÖ²¯sÜ™J'C}F¨CÍÏ™>Ùr›µ)¬%mâ¨Ã콎}�»¢ªÿÃÌ4LÎÐsçžgÛ�ÊS™ÑÉÓÏçe¯®å·Ê¨¶g¯]Í�EK~5A©©GÑ¿�<‘éèx©uUn· ‰ŒZ¡…;Ò±ýÅnaˆáÉ;½äñ=ÚýkG‚qÁôBáLо·®U,Rv×»Uî h– *‹»øH²Ñ¥¿ª×�²Öx43 ô±’ŸäŽþ—bæj C¬¶ûï¢t7/Ë0½‰Ê>�KŒâì¦yípɺâ‡A[B¢XíßÖ6jò2ÃÍ~þÞæSN j&ÉQp@L:­W/-ÚFoLAc‚/޼5âhJµ"ÖáèUþ5NÑ‹ZpV÷驉Žçle³ëi#4³Í»aœ¿Š,øÑç4þ‚þL¹õhü¬Ë¶Í.å¾Ç+ú¥›Ð;´E*ž¹ ˜›ÅèŽ �½c4p¢Ý³¼p xaQÅZûNDÅI õ'ñѸÏü'qœú)аÎT�Ê%Ýiæ<¢À™)�¾v†Hü„_î-MþèUÉ >@añ\Ç�L„œÞ¥UivÒb»ïäRc*øÜúsB˜@®\ô3ŠA�Òó�P½Öaj«CÍåŽKûš;ð�Ô,µpxfºý¶dÕîdå®cÃÊö ’ÓV5Žm¿ˆE¢�ØÃî"À4Ÿ8t´Ó«5š+*€ëÐ4¦ýj:ÝŸ‰Ñ¿W�ÎùԒ�ýz«ØWS‰ó‡#9T¾U[§²Êiž3ŠØ\Nhž¡š¼Pæ]Hà¹t!ùR›™^½M  {�«’ýþ¼ÃݬgQ.§ÞMÌ÷Qî5Sj'4ë=øv*'L‹Lñpá¿T€cµ4¯‹`wö`ÑDª_*J‚K:¿�½oÒ© $¤�ãø¤ ¨¢±·%Jpý0'ÊWoZÛDkž \HÊIñü&2«S/á#:zawDOtÿd§6 ç_Ñ>r1“#,êÈ|ÆGl40&µ2þ~lr&Ö»´þàGÅî;hÌ4ãä»V—éýý²¤ÖÝËõ:½‡Ú"cô3”²þfi£¸¶zn !W=<]úÖyù‡lV‚¢k²fa&¹lšŒ)¹]R [Qó½…{ïôBŽ÷)Þ ¿úE¹gœHŒ÷ÿÔOu]çi(>‡é¦Æ'ĨnÁ›5L{±zîÓ7­¡ì�k¯·ìRägh•ì0ÞÚµÛO™Õå*›YwvmIÏȯ¹Xº�ÓjOú¡‘¯yó_oqLyßfÐ@è|?S|Â+± ˨ùi'Ë­ú‡§ô W.êuåù‡ürMˆ?€–[eή�Èÿ¦_#'™X÷5)¿þJ€úÉ9T÷KùT,£b³_CòD©;œ2¸m^Ëê]ÁàS&†Œ%Ë<££†?ñÔLŒÇú ^�2¶w>¥•ʹ cÒ0²ôj˜‡Á¤*ì�}Ûù½Ç²”ð "8¡êŒŸ‚ûï£ÿ­Õ|8ˆð™üSŒšŸø"Š€Ì=»{®¬1e¦D–Ç/c4øE¾ÆÎ„Ì:¯i v”XۼÒÑÅqÆïèäDüoÂ=ÕÆç¢Üò={2‘4Œê$ÎŒP ox3dYp�7U`¬:I‘0ôµá�™‹µyTîon‹š=b\ÓÆ“|#¹V¡î~¼Sc"�PŸOnpLß¹ƒáŠ4%YýÍá„X°Ž/Ô˜:wæuΤ€ànÏ5„d¡¡O=°Ô¿.¸ 8™õLç` %ã·«}š„ðJÍþ¥ºZ›_&ù>õH°M1ùÝnzL›·!$5anfð QvGR çS$9»ià+$ÂCæ)Ò\È4ü趦¬´z³:<±ýUÛz¼6"ލ\ ‘òÔÖRìÕ â¿ ‘%6ÞÈa)öíÆ–¬õí‰ÍÅ%Û¢™†ç‰ÙýH-% è¥bg&ww°Á ¶¿ô{2ÿ>¥F­’Q&SF`œ¥¡lp7x9vAÚ*ì½;�ÿé@½2mód»yâ^¿¢=}‚·AÜ!¬û«ç'¸ñ/މg/4>m|]¹¼HÏ�g؇”ÉT;ÿsǼÏvv—|ñ;µâªî‘£µÇ9§y> Îå=k!�ï+`HéÎÚe]ET\£ îÛÍ»GS50å&ç�sµò-A¯ƒÆNo²Ù7ðAdˆRe§Vjbq6…ñè\ýl6@hˆ©èïê’€¿\ Ë¥³Øœå[÷[(<+ʘ·…±¥…¹ç1'½¹ÎD%jiÝÞùx+j&î s ç}'wÑÑÍ‹Ar 6¥ˆµhØö¥«W–ªîà × *ÔÀuÜö$‚i´Ò¤$j‹k˜ÜñL¾CbÞûgß�õYÉßÁÆsÅÛÎq·õ·i]¿€¦£—:p1(•¤Ó y.³Yÿªµ®³b6"¹R÷ú OšÐK®&\*¾=Ï?Më(-¸3ÔÊ™t‡¦ 1ñ½ç,›=e* ‘‘„Z?þÓM©¤¦‘hZ׬ä’ÔuÒ¼�¶$˜X$ÏaúŠÄ2I ȵrÀ¹æÇtAà¾Þˆñù„}?š;V\Iša¼ß#ÌA±è±! círw±oßNå R â#;D�õ"£'ÄÂ3ßô[õ%�A'öM÷އþ÷a‘¤ôD'ãVÕÐM?Jp�RÉ⧎ǹ¢\/ɶ¡g¯§º©PÄ2´?J¿F×Ã@ÙANÊšÍ~Ò{*™ûH0ÏJ²ZÆ"åAýêÊ®¯€º+Y€‚UÇŠJëœéd"ÍIhCßx]®mÄÀ·õÙk‹°mL½1!>H ¡o8&ÈpuËr2›o0(ü§=k –åF} Ù zb¬ü£vbäAY°RÅ­ÝQªw…©9œ¼â®ô�Òænû ÎÌ’fáòªÎÇna¤3Ó×m¡"L"reƒoð¡GR aÊÄ#™ËÁW“ÿ5B?¿Û=Ú§yú7¦Á\Ž9Kß 4­=nûÜ—n¥º2£qüÈ+<óî[�TˆÐ½l)Û-YHÏþ…nQ)ƒú¼Ì^�žÛ„¤ýÇrŽÌž©KÏÞ(œA]Ál»jÜ"B[aè u0ÇüMµò95Çß$ÕÏ=i-Þ£Ñ\¦hŽX@�¶;[Ç#xµåÉ>!1ß,ËÙzA¶ôX­«iÕ9ÝüÁÄž½¾M±F8¡õ�;мL¡ð�©kÀ„”‡;É,à´^<¯™œµQÎ÷,pj€ß_ëân·túÌVy¼[4ÑçJx â¹Å½¿¸™õÌÓ‚¨‚F+#��%½‡ EÍýÎJ@|B§H('¾îÖÐCG!,X†3ðÉX>_AõˆºúáUÛ¢Á/Kc¸VÖéÊÿÉdmÏ"+ðôFBÿÐS|̉”³ ÀÆþÒ¦ý£Ý Ä'XêÚ“}é…Ùø�ü¡ßÅõ‘sÁ�íƒ -3:GÕN6lõlCı¦¼6cA¸d¦Ù¡ÒºðÍ^gÖOÃ}Í?lr0ÓÏcìXŸÈa,{GØù^“ÆÄRö2Ù¬¤ˆ­ƒ™ñ+„» nÂÐAc8‰bgЉì-"^»ï-tÒ´$�®¿þ,4Ò°âÞ}Ž€­Á¦÷b�²Ðì½§ |àj0æahrÓ#:ÔÏÖOV ë߯VÞÌÉV%aþfÒŒ gðò7ƒºç…fÕ ~/ñ6±öÌ9AžÇd”TL#ÿšüÜ/kÏuŸãp"ºx–\ОS›Þ Õ) ĵÀäøå0ÛiÀ IÉc«Ø)æÔ�¬ 3B®â*a…äË�¸¯;ÔÝénKeNi&µäÛÍ'"pQÁ¿š„¾²r¾.3þwÞË&r²æˆGܼ۶PEõ‰I{”ÉÝM_ô5®¦*Š,W¾súm0ÝŠÁ®z.”O=Üú‹:¸wþ@%·Øv6L|;ß�Y~{—̆¾œ%ÎÒ¼åŠö¬Øà!2% (â­ „7\r/ÊÍ Q�Ÿ”‚×X¿@Ø~w)­«yNÞ)‰Yhå‹§âW¬ „Zäà¦ÿºì;[ŸiÆò9(·Ò¡…sO®y÷²ÿ‹'ŸvËñΞIÉ]‘()Èщvk𳑨(äóº@JÉì^cæý�Áú⻌ÁîaFjIµÁÕØ(LŸºFÞ>�ÝÁ>C9$äAÑÕEhÁ ÖY=ô¨ù ÷ÇÁ´ ¹%`4�§û5¢ú™Þî¶Ûô×C|ÏKCj{Lj×ÅŽåÌä]&}—¶+Öí:…çõ˜ÿ±“Œ Ó¡æ#AOy¼�;¢ÿ4BµUª•üšwj/v·!~2�y`O]S-Ò~ ü¹Û!Ð ETWºá]V? W ¿ŠØ½cT¾f]¬¾«®WD‡»)”ÿp`H9ÓïØà´h(³\~áDìw!h.£0Ú7§Ù�¸rÑ¢,†.%ê&ÔËåŽw—?†\$F>ß”œCóZ9ZÕWÔ£¬e­[,Äó ¶‹„%�Æa1mOa†]â´ö[B�{ï6þ[e×~ÚCw“ûôYX‚x‚5Âa‘v«I˜' Ÿ¤�!,·Îö$ôÃóc4^ý&«rž ?t`hÇ¿Ù2ù?cSà ÿèt�/ÔŒiQ¸rþ*)n:c„¿’ ޽D°ßHzÖ:ˆ˜~Ïâ:Û#E—�ÐÖòÿžöL¹ÝÅî)0¨bYqCyABwdú9PeqŽLn¬'™}oiâe™(pcõ'±PÑ;*™aÁrÏt˜CžènGÿ¹cá@\¬*èÉZ³u©K¦}ûz™SëȧL�(°?e œY¹4À"©˜¢ÃQçÜ9=P¤wRç \<‹þ+¾ƒÐèÂnå{n ½6U4§=×Å€¿PJ9Àòš§%?UâßûF´Fø`K5lš7Å…5G†x �;²åMDn#ìU”éAÞ­¸'ýžr>Ï~,¬PèÍ]ŠÄyâö\ÂãÏ=¾MŽÙTNøN€I9¾ªjyƒCCÄz sžœ‰�9ˆµÑÓí,Á9Þ–AyeR̸Q49å?ºÉH£ûˆÏü€I)¶�sëvþ!!š,0Vӓ׈IŸ*U44äÉMýM3|-Z^�ª§£ÀyË=ǧàµÅ°ü.÷S�~2Yu52–9°¡Ašê5-©2˜?ÿýᱬÝtéôðœÚÍg2êýPæÊ×}³v͹ÍL‰ËövÆ\â#7[€à·-éî$êIêŸßm0€ “LÊñJ«‡Ü}¹ZÈþ¦ó•ÌŸÜC×ÜÎ4š½ÌÎ}Tä¶Þ½¥êùðms²i$U˜å×j»){v…ÐÌäU~ßÏüù©ã“g{d²“i#Ï;xÕ^lA�SÙ1û}©?Ì+j¶&™�{vÌ$åô`IæEgç^ä6M¦2«5?í4¸_ï$TµÄ+f­9çü‘3¥5× Æ.-5„žJ¼Uç]œjá'bEäV…rJÞ”~³�yb…kÍÚ*Á\'ß“æ½úü»}ÜÕò�¼Q0 �ÿÙóqp‹^IFÙWÖûÀèeÙk4¬=égaÕÙº•@ù¯”§Šf �…¨Ø1Ok7¨¯k¦ ш_9ÓÔa7z0’†˹vÍë oÊå�OÍ:ÀPw*¡½¥¹Aâ¼Æÿ²Ÿ^ýcý5Ú#®õ­L´Ž›çcÍk,V,†ÒH<ï–8^ò�iwTO¿slÕÑ÷|�0�3×»×)ÓU·TžÇ”³8Qá�õàrˆ÷6èÞÞ°FªµÓÂ-Ø}´�ðtcŽšœ<½E½ðäUÛç² û»¦5—¸ª,(bÏBuÆ;A5µ“‡álì6†UCóDDw�Æž§u=Ê‘ „Ë‘ìÀ¨ cÝ,ד>LЉñÃþÙE æ�Êï‘’�Ýš»!ah¹ŒL¹¥ý£’lüo»” ÷£Ÿ±cÔ,šk¤¢@6Ú¾ZÆ�@¨ åöó¡}\Űæ™_w³ead(Lª%«�?„:Íx/7£ùøÌUxštÚW˜ûòÔ´Áùâè1©~‡Å‘L •ÑM˜M}.ª’²uáìw±Ôó�É# î9Å÷"$ÍÕɧŠ6a+‡ewáÝ«n€Vò:qTD!±ZÌ~±§ÐII'—&·Ux§g+zQn¨L‘l£{�eE %ÿfÑ�Kë’c�ö¯ ½‹ˆÛlåX‘Çü WMÊgñT꽂»Þó0‹¼3T¡-âd@LóhíˆË{þš2ùL”Ø“§d ®’Ü” ?ÔmœHæxב‚‹BèDÂ=bÖnƒ4‚§I{?!ã@£QvÍp€j Š„Gr’§9�OmFß_zt'O@JÃL›wþŠþ Ò(«<ùÖ•UŒ]â²ólèÔ0ïv¼,n—m-Œ¼¶ÌKýfg§Vp?’•]z_g ®”»Ó~3”*cRØ\®uDLöF1~xwV@Ù¢‘�™ºÃùŸx:H»·#çî�œc€ã—ë©qëYHŠk«ç#L:ÙW¬Ñiüм<Îtmz;@]v5”×:Ë­Âf/ÄÖ‹|/¸%–(=¯ãø U¥Ç6bÙOOüÜ3ÙKò�ÓïÛ½BqÇç5böDX3b§�kÎϘÒ@ùdÈÝ„FßO),~×r�¯,pvž’�¿®ÓغiÝTÔÛYgVÃ$ ÜæÑÚEXýËm#e7Ó±²C !Úumv íñ?{‘Å®Ùþ’ŸP£ÝþÏIhÍ…­dµè¬x*Ë&òß/35/$øc¢ž‰åÔª¥N+U”‚ô'^8ç¨pó2`?�¶Ñ[-«™@ÄXñ¼Ï¸Ã#Vó·Z§Íe@|B“âÔZB·Äy»�8¦þŒá5aµ-«¶ªK­.¦ªH4Ä?�Æ*²N³r¾šä\åÃK¶z„š®~�p˜Ù™æºŠk5Ýé™i4÷�3¡þ�+ ;J¨¾Í´.öýTG²vª¡>ç3ØH-’ÅpU¥s[B\åHÂ.ÇBµjºµÎÜ9½'?±¯Z¢p®Va˜~ŽCû‚ÉMǸ=ïrþ§È„ò‡�ùª]ÒõCõ¸@S4-Tæb}¼Ýaìm‡›�*•f"�¯8ÒŒ‘l}< Q.šv˜³ô½5ùWVN mÄI-øƒ5×âCh fA›Má [Re0ÿü„³ŽÔS3¼5ÍeùŽ‘f|)@- YJnÉ `ÝÌ!'ö¢ÛËЫòÿøe…”…�µÐ+ýa{07ÊE‘ ‚ÉPXlôæîn8o5‚Ưâsê‘ôÇõÆMùäP. ;Ð7²9ׄ)€àÊŠ4ðôÄù�}û––ù2aÝ Ã¯´Õ4y<[Õ´†§’‚kÔò^«÷›ðˆþÞKþ>«±ù!×®o`9„Sï¢y@SoÄŒ±¤Ê“ì&Âåu.¬�“×aÏ$:œƒºó0J{cq 8F`ß‹2oŒˆ¤DSëKHכţv®ÛåPOcÿW*äç ¹ç9¾)ÛŽëîAY?*NÞþ¸o¶p…ìgí0“|ÿ 8Ï~)°RºÇÙ’=åþ�êr4—Õµ_d;ÝŸ»5C91Õ¾o‘>�ù‘»˜�ÃVƒß ú­á¸S¾;4ÅùžÑñ’“2û¹‹ªµ›|«iö:·o‹Ö–ûç–è5{çqqï:ƒf¡o uæ«Ο®Àï9ò ®Þ0‰ÿ»Bì¤ãä^Lßm9ô0aË™hÞ—Iª`Û…ŠW?G¼Ïˆ!;Eä—9|:­ÌS7…A˜›eÕäA\ËwÔ%wBx×.?rÚ‡àÆSÄ…I8€9“ØÂ7õ�ãrH胛�à9)T„U8ŠÙh< ^á Fsó [ÕCÁܸ|Ã7í ©„Çâ¿Uú6áUЇ6޾?T¾û€o¡/Õx¾lUž#1/긎ÍÙ!õX”ÚT¡£c|¶æPïTæA³IƒÍ$ `°DåµxLK\5ãº2ÿ ó8 œ&\$ÉGãצ®Úò%0æM!û¾¦7LjSsÊýî�AÇüü³Ë2„ùDÂ×H£»M;³Ž³8ìêË˳°Ã˜ ";–ØöKÅ”´hW#D‰¸­ŽF‡qeËSÊ W ѯ(qÏá¸þqоU»½À·",õ·U|%ÃÐzýœXyDÏ�h‚\ÉÈEC`®¾MÞço™ «)\æ2¼]ßs�ÓÞ`W55ÕÜ+ ÔØ’»¼ŒØäRÀ÷˜Z�zJ²þ¤°¢ƒ·"„b-=#/óV |w�ÛK‘€K×K[·öµT­Si•ˆká·F—‡þœ�?�2ÄÓÈcð•sümö?\Rwîoãêã„Ùù†æ×¤ËÎÆ/½má°�"Vx�-ŠÁ·dPž‚ÏtÛ°¤ —�M*K4]gø×7áfM×�­§ÄÐ3SȪ»¦ýZ2yßn±W´Ÿ=ëX ycäBþ±B9‚ÐæØ�Q cn†Kô‰lóÙîdñM€9‰ù\�v?‡zÃwY3ó&7“Ÿ¨:gN…ŠbËõdÂÒKÏbáº{+¢CÏ*š,'i–V˜eX÷8×·qò#=À-|ü•Eñ9:()|ˆö_/×R¬ev\<ÆÝÓQkI«š<ŸY5êp,±h¬ð„bà@6K6ð 4pÿÆZ!¹}^“ vÍFã–ßjÕ þ .õ`œ\È{ ªb"=o²½˜|ÌçvÕ¨Ì:F–ân–Žw6ÒtÇЈiž ”|òqðÒãU@´Ùcƒ6TPr“ž{ñ$lŒ–՚ÄÒœ÷Û2¹éÇCÙ“qÄÂD°=‹‹65¼,�Tø« LǼ´õ‘øÿNÚ±ÀS¸¡ã�g[Æ',‹]lÁ«êN¸§œG%´SÐOÇ–uJ…®ÓÂdº)NWa;îöºë¼ðnþú½�þPç3Ll¶? ™Ö¿fN†˜è\dåÿ/=Ë â[¾QJžñ(-ëX(;üDéGr`èlXÁ=’×p1g‚#”ÔCéáUSî€Û>§›¤ì’»¹íX†£ÿ¨T&Ôû³Ê& þÇœšæÒ;(âË0w®¡»¼7*�R h«œç€–L‚¯‘<ŒZÈ´Ó“˜ÒFSuS>%W¥Õ#ì„îÔO»|,gÊÊ›&ÝŠeà‚Åxß¡©]gqxOáE¥ é1H3'µs†-ÉïÞ3ÊÒhð+ SfŸF4¹Jú™-Órb© �Ó¦�©…Ò%=Þ½zø“œ�T¢ � z¦Ð¥]Ãâ½ ÛüÖ¿Þ£áSHj_ƒ*�¬€yvv%éSeÕæ)[Yß¼‘ǸËE¤7Ö- í üX¦ð£Óã€÷—çàÁa¥bÙÖ&nwFG÷XÜZ�y¥b¼„•§�2ð}åK&ú}ëXew Ù—[Ç™fjTh]Ä®‡è‹Ÿ;�S+eóúaa¥K)΀šöÑ:Idí5·Z]©æ÷9qâ…´mOÚqYŠ Õ²òÜ–Rêì­¨óhþjz_ÄôkÞ“ÄTKì`óÌ|ÍB.ÇAÛÛ Ç´žÝb¡F$KȈj`›³Þ,ÛHæ©@ãŒl²‰�ÊÉÃ�·“jXí}?ÐÅ—•þtL"§MˆÃ­+ºõ�'?É2Aªß¡†ÈÈ®¼ˆ~²š@/÷2W­”¤µu@m [¸ç‰©„ö€õy˜„i û$;‚·ŠyÊàW³²— 1±‚ˆPô›;g ágAŸ,d”TðŸ^=îÝ¢&LGÕ>¯w7ÃÇ,^*jä% "¯»Íž�>XV‚’TôÓ ÿÀˆ’‚®�ð9ÐX:š€¸áO1ÜGrÛNÜâ— 2åÇ98£,Æž ÊL^Â7Üó€44ró=†ë‘€â—Ù"A«»8båBä³@áMac…SWQ‘ÄD%ðßdŒz´6¼œ£Ëæ$Ì̵èYC?Õy0Ò€-F‡™ngÝpÛ#&]47$¾¨U¹ƒ÷sÄ×ZÎ ØÏü[7v“”Ü9ŒEÊ�$¿šó‘Q¶'PisEÕòh—È<ÚGkÁkT¿‰œæ+Í(¸VwlP°,,) nÌb«+3ïŒ;ÞŠd "£a±³à ím˜$ŒSG±A|�ÀV–"/é�Ž U\§ÐH¼äïGëa‡¢æÝo¶»ÚÓ§£…—>Ñ@‰x¯Uòª/@'· #VkâF�ï±Grïö}K/¢.HcbåÒozr+1¸_m3 #8SöÝŸD)ö#é‰R½g�c!ÈmÛ_il;øÖé¿”âBá‡åhÒ]ÁÌúlµ€5À»âƒj+ O},Õˆç3A¾ü)‚¨b.šªŽË½Ú ;JÖ'5ŠrwŠËqW4råQ?+ÚA‰l0»yù™&mõŸ÷ [ãòHÖw šµˆðúVw;>?¨²œ¸1âG8ÕF†›:Ò/ˆ‘ö÷èí;ÐqMMWyP‘Q‰(Á¦´õh¨%ßûvOG]ç†]½¯/BÀµ{8Yh†ÊåËÈR<â9ò0t‡Õõ0ÍŸKiÿ‡cèΟ:)LÍ+%$z‡iT¿â] BWB¸çpÝæˆ�òòüãÝP§�[}åV= ƹ--�sÁ¯…R°•OXVÁ\Ü4°›BÊž:‹ÌùôéÇ©3êh™“B6ç¾³(#°ÏóƒÈÙBp�Þ~ðWÿˆèWdmUæù!=(§)äY¾Ô ΢ƒ"‹ù»jÏï Ù†-œ'Ì”ïÝ•ói$b‹²ÂHÀ{;ÊÉÎÄjðg–®—i^õÉÉ"Üð�±ò•Bâ1·�ôŸMnGÿ‡cèΟ:)LÍ+(ô>ô!`»ï0\ê 2a¬…èŒB­®‚9Ë/áG? «çâ]‚›c¡;íY³N¦a™’\5ýN‡ºâ#€PwÌ¥ÿ!¥„•Ÿ=x™ÃIÿœ7±ov2ZàŠcüÎfŸâêËç•euKûçF�ÔçË…¡ˆδ"w¾M½…™ÐÈYi)wzÙ¡ègO±„‚LîçÚߥ˜ @¢º†€„ïAÎJ*-ßʯçK0ì@ä5_¦~Þë7²ç,–H.ZŸiy ^ŽÊ¦“@»ÆÔyòŽ6Ö0f!,gl~jžn8AA›P5-Q2˜ .ÿü„äyÈï„;Òk‹ß® ©¯ï�JÁéÓDV/{_Å#ûïžT(‰Ð‹ôïr|ÂÂéÖ=r§ôkHóá|‹K¸Gl·áÍ%½s0. ¤&ŸT´qÜEžvÙ"©C¼ÈG!×õWwéd²›iÆNI0Å C¶Ñ«ŸW_Ç#&¶äÌ©ØâÊÇ’´YMá*Ì®äʯVÛ1;²�¯ÆH©Û¸—¼Êœ¤y{!S’­‡¢—«s™ç‚W0ºØ%´Q̨ë »q‹§c¡«‘ É+Ê„À |9§?šørØ‹‹¶ÉÁ�Ñ d»^z•—S®7pi`~£x°¿ ê°±Þc«V6²]œn².“e l^Vún¾Àí<…l !›‚?¥Ø•+Éß`“‡°§ Œ ª{eQÍT '0 «vVdgQzQ¿™13(Ì^†ÛéG’ê­ûÝ-'>”_©TŸÂO$>¾²™Vþ�ùùá»dö߬2 €é,¯²Ï[N.gèºÀI�·O¼ w—ÿb(YKµÈ¨ùŸÖê¹)�Ûõ(îþj��:d»d”Âg­¾AD#mgÂëÙêö[“°¥³L8Ü‚›¸äÚÌ) ¡Ž+ Ú=t³r÷x þiqA𩉠ÑìäÌ&þjP£ÛH` '�Al5mEž,XuwqàÉ$î§zUOžî\|ºO»��†3¿üõ,:¾|ƒÞyŠ»­¿ó|k“·Ù(?Ì”=ÿÕ«5Q>Nsq>[¤^ò7ÓhV"Ûbã—Ú¾'8Ê ×jÅÔz_SÎc6:² ¨_3TŒœn$²ÊQð�Ó÷ïÚ/ð=åÄC[éð1\†7ååV§S�¾bþžÏ«Ú@$eïÐ, TâæÖT‡’4BZì&o±À)ØeH�¤Ì�å–l±ÍÐXÿZ�e ð˜Ìïbí¿J©åç?ü¿g ®�«›¢P¸†IÇYœüÅ?I‰ÊLŸ*—Üœ™þrüÉ«MäŠ9sÛ�¾6™.ˆ Ìur¥ü–.uÆÈ¯?ˆV­wóô…’ø€õFŸ¸¾ƒ#µ­8¨ËÞ"�çtµgž À¸©X�Û:ÎA8p£BÕåe6Úü®ÆrŒ‰®bÁhð–Ÿ“Ú;<̆�_¬Ð0ðù“¶Q^¨u}†:»tŒÉãðùqÊ''Á�l¶…É}ãÎX˜dʲŒû…Wsµ¥Âê]Þß_y�­áSî¾{b �jÿÝ¢�®ãÜ.WÙ{ß.�Q2 ’PGXo·<÷¤ÜfY®Vâ<ü»T÷ÃSó¼àd’ë髸s·asÆ9ÊZøµ3ò—8ÿE«æ–ÄÃÙÖ¶wíbÏ»­1‚¹¶²i›/ðZÇÚÐá¹â£ V¨D6_×üHõ1àc» F#ÁiÖ@š$š'جJãà+rq ìàßV„þâB2ÿIØ×éí½)¤´IOá§µ‚õæaŸ6ÎÌð'@)À<%EÓu‘¢ÚÏ ƒ„_m«?¨¡*,ç?8šI}Æœõ¸;ÓäušŒ‹(#Ăx¼õL ˆlýÍ¡±ï?·ìh.Ë7Wη�[b…uƒ¢f€<:]õ3‹òñ &Ø=¤Õ0� y÷ðÒ„2Û'ë–ùï1T§ÀÅ®jX4[Ý'Ýýï”Mµ#“"îŽQ2ýU!ªZÇ7ã(ðQ=³›ÿþ›V8c½÷*ƒ�2uÄØßhzž" ’, DÀpÍ‹ ±6•¹’(gOÕ']©•~§}½m&?YÏÕ†ëqO›Œal±Õ`ýè»vWúiOß�¬Z;#[‘{ý«ÔþW¿‰•¯²5€+•æŸÙ]“šo:þkØ'JþÒÑ“öAnû5[æ_+ñ�´ ^ép²é�CÖ[Ž ‡ÇòHiüÉ:Ù‹Ü8¼«Mÿîo÷Þ»ç³WánßZaे¹LJ2'<ɬHIÏôȉH©JÞ!‰ ÷©œ¢ÇíŒX#�¸ÜOb§ŠÃo¤3¿˜BؾYu£rÆå^ puSœ½’Fá‹ô~Cô©8‹•\õ §a>7Îrß±\’Ãé“í²FÙèðùÎÌ/“ŽR v\ÜD­è†PÑŒ­µ,#ëf0a]™úH³ÆtσI Š.%;LÛð³A´0nïÌ�û¬Çp�¾%òæ`.EÁ;�¯¿Ðì`/²Gë`ý½×Ð8Ÿ÷…Δâ-6ò«˜“…n7~Ô¶›÷Q5|eò4ý¢6œ¸Lq‚eи Lm±\Aþvuɘ¿:-+Ö’§öD¾h‹öå3jVc–-›7÷¡iWÅÃSèäøã.MO Á×—ßZ6L±Ã�äí5uŒùxsOx÷bAxòb‡‹X·®¡}&Á÷‰ƒ?M›ŠÅ¢LB7ÛØê–»ËêæÁpœ<³×¦¶¡Ûªÿö×$$;Ûø"û :ð\‡°®éSá"7ê 0�­n¸°l¸¬ÿg̼ôa¡ž¾iÁùn\‰z3ËŶìèÐ¥EŽ×ç&ÿì>ï°‘.šÙ®54uW±ãÂŽ…W2«cmŒ@0$éG )(ZqEã'ÌÒ8Úf�ÒÕ×€´¼ü?’Ï:ù j¡5ÉQ9àÄsÇs´’þgú–ÓüódФ€ë7=m9Ä:M;­mÑàå­Ø#´i Úù€-LNï:;Q}p¨f_§¨Ó€ bM(‡ê˜«?€^°pÎu‚“ddÛ9kßÖêXbÃ'03'oí:H/kfür£ÁòïU $¯ý�"œ£•Ý;äû� r/€è¦Ï©Ýê²Î&s®�W ¯ê\«D%Ô²I¿ƒÍ„ì/3ËHXµÐ[šTäJδuO¥¯‚µä; 2µ$£Þl¬Ì”êê}Ûüª;ÆVÖAÚ~ŸÑÛ�æ4fÂJÀ÷þ¥éί` IŒ¡²žßJ…q¿Æ|e_wßÙ\?ô”ÀFÖïÒ£îZT°{H[Ø7”‹ ÌR™V rK „±ù`øg£7dß`»#BZÆù¢štä٠Ⱦ ˆhQ¨k0&üµ’‘y¾ ¨VGñâ—qâÀ樦%Åqö›Œ{7Buâ¡VÛ6 ‹¤ÍÂj¾êö¢Àe¨7,ò5êÒ¸ûÌ�šÏn orîÚÕÿ™Î·-’/«´w­ºÿk]ŠgÈT„Î —¯ì¥é§O�–Õæ‹Bf@¤ÐP¥ß£Å%‡gçÞôÊŒ-dÀÿ-³’ø|!ë§­bM].U¡ý8’�6œø„¬ŽO°ó‡ÝƒÕ ÔRG.ñÜá�!w<¢Ñ¶¸”炼•ØÕ,ÁAt¹Àbö}GèQ©GÚÆÓÛ‹Âá¥s¬&;A«ÐubNr`x#lôc¼�’-ÆóïÒ{¤//ªÜ'ki”‡³M}ñô£a¿öÇä5,ðªGç ·<)Ýòbì4 –·žv3v–´fë�ÌŒ0ì¼N£ºy΃‘¤„®j§ŒÏºTK´×óñèÇ£~ûIâømnL'� /IÞQ¸g¶©¼×xÊz0"6@“-…ÚˆSPĬ´¢�ôxû^}ý\Q,ckÅßO,MXÙ_ØJüWÈ­Æ«ð ×wÑOìr;m#@Ò÷蓵±YSÍìî+Çݽí™ß¢‰çw;ÉPž”< eVïrÓ#Üž¤‡7§’ż�M6­G÷ ÕóæeXPö.AÐ12@/ØŠ­Ó†$²žøªþ>·¶œè�y„G1ºu\3ÁÉÝ©ÆYÜÇ ‡�]xeasM ÍBdz�}ù݂؈gàŠ¨Záf©"(€ÞúצΛÿþ¿¯“ñ,’Ê~ù» ÛÙà+’v¤Yh ”+"OWùÿB&jbQ÷Z³Šjq#¡ôž2×?™æ«ë`®0{Œè³�[�æó"ÃL¨åƒˆq\¾$2�k Ye.y¦õFó½dù˜Ò+ì=®~Þš[?:hÌh à›áÈçö¤h½ÓÑ@Þ•r!咽<‘LèømwÄ®ý‰ºãÅ'�òÈJ=çÌò³Áû¤¯"uDa»Ó×E¯üMñ7üÜ­Ü·"£ ç1ÓPÄ|‡ç¹p¤‚~‰¤‘a)j¤Gn~Ê5#N¹Ý»ýR°0ø_ÿÕ¦öŸm™ý¬í×|–ÞÔ�kþç·ÂxýŒ¥~Œ'ƒ)–«ŒöØ›»rˆgB5Ÿ#¡ù)º˜4]gÛ«ÉE‹ÍK‡Šµgã™IÒ�›.N²A _ÝçZþÍçG°g’5ˆ…ÐL®“‰ˆá�´I±°C£`í·²óD•rO>`�ê%¥_}ý–jc@äüW·Œjv#zþ�Œ-ßÍå÷œ®Y^_[òn d½èŠïÏ޹ä�K„u8& –õ&!ßö¯1¶¿‹tŒ\‚ƒWÆÊC˜G–™X\u¾Œçª”wÊmÏT@D°ª+�†QýgzG,¼> ¥¯*Qu¨p¯ ÍÆ£}jÝÊ;]¯•‡,”_&½wi ârhEv€Ð­P·Ó…ÂÛ„ZÓñ»\§>?º]°/ƒqâ#øaÖš=йÀfÏ+âV]دÇîZ…þ$MV¤Î{´š~ôi™ZKuH¥ÓJ6!¾æ°�*ÊSþÆ@B ”‚OèÔvðÕÕ ‚å€|¹�Ìç—SZç ÇiW¾0O.Àri“F”¨þipÑ3n‰Yפ‘ض¨Ô½.‡“eîP|pµå­pøN£šJ`êòi³S䜕BÜ�Ø›öW\üW�}õ¡©µ…oú9騣Ýa"øðþçææ¢o‚“ÊÎ<Ym@<¯!èw×Z@¸Íeñ»ÓoÖK,ص¼lßÞþíK½�ÎÆp'vãæPo�i±÷Jb�ø@Û²GšE6Hbñi¼£¡`"W4Ä=œ\Û.ãpnø0¬vzˆlTš�gòµé¿…÷Ù®ïkü€ñlÇ"+ÈÁ8ÌË$ß¾Jk>L+S®£Ì9ÙÖžv+àäƒ-98It: ÖFí1“»†ecæºÊp�àý¨øY„ ®4,ˆÀbÔN?¢°CÚMÏTFêú×i»*OÊçuÅGi¶Ž¯26»ré4� °;^´*s“ºÏ¨lï^ïM¥«½�ÈÇbTÆ–ŠWOÑ%¿ÈƒìŠèHE-Ü>f:ÏéÒØ?Ç(Ùƒw¾ºÿ ì¶Š*°Ü}g5‹âD©¥¸ÅqØ:ø‘-ïf¤vö¯Ø²*�ÀížBÐö‰¢Š5P)CÖyÃÔKªòÁ_Ù¨sWñÎÜ.­”[.â�N$!•Þ{T+̧¸†WÒéö÷EãedbsŒr ƒ–¡'2ÞêX[!›ËkK_hǗ̹0¡Œû‚»ÕEñËÜxâìðwzƒ7Gw;/Ìéã^�A�f ·Õ–\ñOl‡äï÷yê?ÿƒþ5Z�ÒÒ'O. ß+š"!KÃChe[€(™šìu¯æìb¶(jÊéf\xBßp�Á<.“ìÀ’AÏ.óF$ÐÎíV¾ü&¥—æ¸úé¬&[ji#°—3á "¥Y뺓¸‰ó¾‹y®t‡wk¯té×af"î÷shù’§ÖªÑ^¬ûbðåðM¦„¤ˆ�É·2ØP±ƒ`(')˜… Þö[{Ÿ6jŒA!:8DÃ!G =$Ñ“øäÏÊ…‡vú�»5Œ+É•ñ•$BÔ¬MC­ ªóÏ�ÖÝ ã8”s¡Wée›v“Iá‘€D úb¼D `uzõ‡ÌÈsàcY 2*XˆWå3GÎ[£1N‚%û]‚ÌŠcîß_Ácœ�>³¬ÓŸ¢Úâ4!Út£üI±y¤¨í;ØWž[”F(““{À•‡¢Måmj)#h#ºö’`ô¢Ë�L]_Ť{Oß„áªtŒ}ð—@·Jé}í™DkáÛâ:MÒFÙ¯mã,]þ•Ü{`¨JKö)Ù�½w©äÅu@›p8'à$æ ü<•›å§òHï[ÊßÙø}ŒÑUš„é°æßÜ;`ü¦ ù(û B±}¶ý¼ÂíëÚÌ®,ñ'uí/ 2æ�’¨•èñÚt,>Õˆz?ÔQݽ!â¶"3 ¨È°ÎJ·ÛƒÍþµ„Þ�·&–/·ò¥?´O)�>„Ï'€¯�š�èÿsI5À�`!áÓ¯r(óSÐÓ™š YüÄã²\[Vœ«9…nÌf†Ù¡'Tèeä¢ñ3ÁLŽ ±ð"Å^‡HÐààß— Ešzóž‹|nnÏ›°AAã%döaã ×z$"!ó�œJÜ4·B™÷c‡fúVf ü4Ö3…á ^ôD#+îm,+ƒNœÞàÕòæóù]9‹­^Òºw·¡\0(Š6=¼­aÍ7t£½�<à¯Ó®Þºå«p¾o£ôBT…“ °2uê>EËQ6Ñk-ûò¹s‡øAÆ!AÁkÕ–A3�6:è�NR†sðOu#œzëÉø ~D²Ì0ÃWÿ7‘uBEzé¦TíÛó Æ Ù¿–65'ªk�[ƒ++Mf²ŒJÝ-ªFSc>©§ÒãqÀ<#cÛ‘´Ö šSRvù˜è*Æ¿µ•F¬¹Ïõs„‹äµzLÂSçtg]�³yB¤ ¼<ïMÁEg "ÉTu‚�ÝIÂã­‘Î(ñ´Ûäõ¯¬îH®œ¯Á Þ.4ˆ½I-¾×ÕÝÌߟB›(³ ¦:M‘7�Ùf»Ã< ÉàŽ€¹x™‘+”ìÐæé Kp³Üî¾_ä]8Nèy0Ë)6ó¡û0šªi{Zå_( ì'cÒ/OyÒ±ôéãYq‹Wò  6Ùç·âÊTç“Àï¹*VôæÞôýÂ^¢ •$µ+›—~9O}·Ùuîѱ¼¬¨[Ö¼õLªçIpõCÕqK颣þxn:Ì`m«apô¨ý“$®E7Z)¢ö<Û»As ¡ 4u±ë^î ¾•NölÁØnÌçTX™6t샷ývÙÆ4D«H´¸`íœZCc½%ò”{–Ï·H2[I¢ÍW€’eUå$w’™±5 ,VüÕm&4BtjLP<£I&¢sáæŠk?Êù,™?ÕO ß¿k;�¬tteÀ6>J�WβËí7«OÑ�~ÛvÛ¡„6’DØú{ +fTìaY”>Žd?zOÔEžS3óÏÅ’ñ\�?,îeéÉ3‹û¢aó¡@²õ€ç<'C{&[o-�é4ƒ.}â�MZøåd”/d™Ø;†ÑàúErHžbe8Ÿéc.wî-©íyÆ“Ä|ûkiúÂNé±ö`šœæ¾°Ãñ`ûùÂ?r4u›WfyPÃc�¹ëÆâN®B^‰•"ṋœÅÊ8üOgRæ¯ÍP~üÝS'ãú$Ôn…‡¬´&¨î®5Æ,�fMLŽ7€sùüîˆ�çÆ¼cêjïA‡YG"IcÁñXÚ"Ã?zàºM:fíA_s—xþ‰ûjáàhO›ÀÃÌÝmsÕ,¨Eµ†ÓAÆ€ÙÀ‡È0$ÐÏ鎦˜]*•Œ€Ó=Lé¥5ºWÖdõ–±$§´¤uÉ“o¸qbcÂÁOÐÖB³9†a«©¦¹\Ü?\ó–…a±ß` =†È‡ôG2ö 7Uò–5—ÔPKðA„îíé¤ÇkY‹kW©2/ÿ¯«롤4±î¿fSNFäÆ(A,/Ý•|ÿ”S³¡æ§�ÁÑîo x¦ô?ýñ\²{þ;çeC ÖžBC#ŸK9[�‡R�iÞS›ûFÂ)˜Zaˆ‚æ«^5�Õˆ9ÍÊHs½›J’õ¨¾a5ã ˜ÒOž¨|ÎÄŽ \HE…­8GRÍDÞ;êÏ[¼0Ï#6ëBL!xÀ|ÛFå¾×nèƒpeb°¿ /Ӯ߰SÂècÆI¤”(ºÙl¡ï® b¸üÍYØq‘ F3IãS”vrY5ª¦FÑÇ*»¾ƒc”Ð^g2¬ØßiêX²^¡hÂ%�7öÓËb~…ü°Ä�,<û¿½;_„SMg�Âc½ì^ì1+, Ü¦‡Yþ»š—­ÜóS€o´Ù˜Ÿ±yrç 5±;¢šm£L¼”Uöò#äƒWZŸ”%Ò)ûÚjþ5K½9$•c×ýMy¿}²ò¬ßIº·ïYø_È^.›.¶cqL²úÊz¹c¿H?.Mö´3F�£c¤:IŠB9çAš^Ò$Œ+fNS¾ÿ3'lªRÏ “bŸâä¸á¼[ç%>ô¢ŽývxÝ^¾î „î„k·oZI33¶3Ð0NZ˯DA ufAâ‰V”3#Æ\ ½Фgè“2›MDÈxþÖËüö…2´¼`•’%]»º€ƒ€#( ª3Ž’§þžµÙ¨åm&µ] €IkW­*EêÏ^¢ØKx�ÒH>¦²ý 4 ˆ@nK]}í&³ì„ÀìÚ¤´q«B   TságÀËׂØ1* nyˆƒŒ¾‘Uto±òÛ¾Û$� (ý�ãgþï­y�¸Ø¦¼º�ûÂH± '›ž×ö^ƒIùÅq³F¦•ŽeZVöÊy%w%¯t2Jy¸^�{Œ¹Ïjñ‡lÃjKa@&³"Y…«¶Øé’­L�ÏýQÀ»úº~ú²¡|íj‘]¶æèèëlï‡ôÂ+V/ºyýР‚”äòúÌ|ãb³@}_dãZ…À,*Úšñ õ¿=«WVŸü,ƒ²æ¢Lã7‘ ÏJÉm-8ÐëÉÚÁŸ€TîfH_ˆ¥ð±²h³Q›Â|v1�°jÍT+i‰¦û )eœl„½Š0–2W‡}0Ñ,Ä+–ÇÙX.Ö�³—`£|ꔚ“Ga³þ‹Q€6?^âÝätKÍ þù�¿¥ m•Õ!­ÈsÚ¬HSIê‘¢ÿr‰u8³xùëïï°'‚1ëÄn:/O𖼬ÿäJ6JäçW3Ó·Ú\ ãçÎ7³S?øÉñ„¦¤TÎ…—ð:]±_ÄVœ„âï›)ö�õ_àˆ¡žµ‚ãEy{�CºÁ©„‚SSBÕ¤' »Ý]Ñ̪³ø;Yë3ÀR£¾§ÁÎÄOÅîe’°ö—{aPolÜ(šélfë¹Âf¤!e¨cÓ$¦ËnH*¿õؽ–êËBkÙQø¼fÀšÔÓ¾;ZŽxÝÛÃÎT½=í™^×rL3·ÅäƒÇÞŒ•\!4ÜòŸ ¿Ë £éæC£ ›ñq�²ÊY„¸ÿ–ÈUi³\ÆÙ€µ(nöMÊ#+úë.ëä|êk€ïÛÿsøS}‹ƒ_¦Ô¼.àjþ V ±®(¯¶V ³V¢™Qé!2%<±´�̉ç`õ4ä� ݃y-¡µ šÉÒ†]íh7Â|¸6É {ì`‰Î…sµ WMÿþïv¡›ñWQzrmåÕÖš�¬ƒ@’ TÞ¾"ZÄŒP!ætÔýª¬«õµŒ ›ž¡e±q5ZÛ’:á¨|ÛÅWœ‡qeÿ6þ‰‹‘ovÌ/P»p+#=zTÎÑÔD!Eƒ¹6àÉ0Ê~³ k[öÈ’wieÑe± 4"ÏïɃ«È>�>ÊàTÓ¯Ñúóéû†›µÐÛ�²¨îõçÅy#ÿ=ï‚•uÌÔ=iýº{’-±E £4© Y²®ydƒÀÐkb×Ä™OMæN©àŒãBÈ7ü ø&ÚßbNÆD 4NÏ Øe2ð‹—øk!¯ñ²8EÛ¿¯ƒ`7œjÃ8Ðâ+å·î4çs[yÏ×é¥Ð-û¸ÁÎùçoî£NIØFˆ X,*; ÊÀxÖµ"„SµD§à(€úÀØ0"ºcm\2Ü6›¬uÎÅFÉ›´-låm°€mJ—[M ZØ„S�méÚ’6,ÅMõñm„K©–ݧ�ÞãˆZrDÝ@B4\fG+ã6-¥YËÍéɵ<‘¶!'±®ú_ª§ý¸t™•ò=Õ‹¾D¶­^EF îÅí“y\5äÌiµ‚ Ë!¸{ª4ø:ÖS¦uSÄ-‰– 4�°SW­¾Gð:¾DnÕǦ‹—Ò Ž¢èÁ¬/å�Ò]RL>[î��ö2îyƒb!D�m"Q¤S÷”J)˜DàõåÜ]VÄrk-\ûK=ôïBâ!€0ÇM÷hÀ°ÐSxÃŽ¸-›Ü½÷ÑQg­-uÕü¥C·^ #5 `Í ÛS¬œlŸL‰C^+™ïöI)R`K¾ß\øã…K¨ kPkì ;@67C¢Ý½ìœA ÙêC­¶dIH‹,4¾Ç¸¬Óx¬$…Ýi�pØ;„FíS´Au|…`®Ä0 ß •Qòb *dï$ê7 ½¹ü'U•Àßÿ|n«Ý¨Z!@ÉÁ4+j#2Ò·ö»ôÒ®ZˆùnUrÝ«9Ísîq÷”uIlé�¨Ü{Ä£E>Oô¤C„˜É—„)³ñN�~Æ¡‹¸"»Y±UÐgôïþr—AÑXšõçbl[¯ÛF÷'‚‘µ×'Á%ïµßëùŸþcçBþˆë9:}#Ä·Ü)uA{‰ãÜŽ,¹]«»IJLßè´‚øü³·™ÂHÝ,s@b¿ ‡™g¿dG|Ö&ž_­ál¼xª«µþR°ú ãÒw¾é®ó;—1UÄÀÀSû÷à8Ìø é¥D¶Y¦él†�âxí€véõúôn¦ëþ!�×� ´ˆ”)ßÔõ¦è³ ä]ÅID R¢BÚ˜‡åt‰�÷98MRì!® ›×U~RR€?" ÿŽËp#ÖZχ?›¯–† »t>ãr—™gã~Sulù¢$ž@%‡Ba«5®Ü× äØ¿ õЇ?²sèLôy.~Tß6§Û©’Ãë$�8<óÓ�©Ù²¨P¢ÎjC+?MÈI(2¬šõ©•DŽ|rbjñïS/ó3x™5ÅK=•é(%²c®�èÞ²ÊWõk‘@‚èÆ�€> x˜wMæV–O ø¹ùµ2}y¡�™µTáÛ^Á—ècQ¥ 7>\ë„7<:Ö¬t¥î¿ÇÃÇ:BbŒ-…Hõl±.îzÜÆiŸ9Ë�.¢ZhËTûõÿÞwžRÎ506×Ì»QßÕò‹÷'ªZÚE¸ßR_ä‘dgœ�éHŸ©f“÷2%TÚ˼äY¾¦,KçÞmAˆ2  póÄѹ­ß[ˆÀw¿tz¤¿%D�õÒüBÙõfvŠ7eº§ûªˆÊÓ›nÆãMOÈÈ[ÐZŒn�›ˆµ[éö\G»1^ð'\V“©èKóG�ˆ1UŒ^çòwä,ĬÅ5Ï”„)ԬϞî*�}-ÿƒPl¿Ôr¼Áòx_Ø\tÙÕ߯›lc¨W-1�…˜d¸ƒŠá8S{ÇWÚ[h½ NEÄ µ#J}§¥›3,Nîë}–³S¨7î䩚’Ôš¬)HjÆ,‡§Ì«øå¬´ë&$ÌîBëYnåN’[*±4-šõ^I],‰9á–ÂYÖÔB3ú�Yz{ü=,«Ö+*Á68§�v±.ZÜ8HÑl¿ÀοêöLmv4滑|¨ž¹ÔO¼˜=+ÑgPÄ:îŒï'‘#€þ?)LÁq¢@ˆ_éœ×t­ãzæË¬[õáTÄlX*'`ò‰>!wÏUâek¹¢yŽóajò•ü.«˜#Ïâ—ÊYWƒt„ðåӠĸ•Çî…M)Ï+s—ªfÄÎJ �æRŸZ�r|jÆß3ÀôßuEUoŸÙ¨Dé¿,ÓSÞ¼eÏ‹õYµ4ß�sN‹ZÀ€xFŽ@ÕK™–ðÃ5æÛª8é¥DÜ%3Ìu ªX]Ý+°#f$ÜíWH7ýzÐÚœw¡&“! ®U޻ӽ wk»@½ª¶Ð:ë̇V=°n~-¯¥O,â§³[`‡Àm¶¸ò\ÏÊ5Ž‚ƒÈ82žš½åªF ÜSØ –°àò@(0&$@ jœÁ{û4; öíŠýÓ";µK#'jyp¨Áp‚ËÚ(¸ñŠî©8rT�ô¤¥.›¡É�{¶ÍRÑD»œžB}²&OmyÆWZ.X+�\ bMàØÍ ¬Ý+!wc»~ëÐ)¾°äH4°=²•;PÂhÌ ½ ó@uÜÛhg˜ë}î+qþåµwE?�•ý1®•:ŠÍ–È MØN°ÂN˜†ZoR꼄 p7ØÑ8i´›Cwbz¢úŒÒQ�¼SÌ÷�Õ´ÝñÍKÎÿ‡˜¯ÕMÙà»Ã÷”£ZO�Ð ?Œ3Bÿ�ÞQîÂŽX´¢1û?kÈÜé‰Mî âdHÑþÀÒÔzëAËwØøglä©5ÛÖÞõ ¯�Îzg^T½ÿÈE£;}ÃÉ Na�3>ÛñÌUŒ<Ðy@D¢!I9ºÙ¿è ÷ºgä¤�£vÓŸjOŒxç‚˽�°*ÕÈ'©)‰ã•qmžíœN„\U÷mð^Õ3A?`‡–†¬Y�#—‚™ZŒ¶‰8vê·«))Ð~�è£"þ/"ˆj´¬s�ḛ̈� {ó-´ ÞÑYÉ@$\•¯"ILÚ¥{å©l8Ö!Ÿè <6QÍØªJ»8WÔ^—]CÂÇëJ‚òøQ"µP9P¶xãž°Ï0�¦A³( 'Ã�çýs=îéÉMY=éL­ºÅ–K\a­à-*�‘ä>‹ý;”�Õ+{ðÓ¿óÓ›ˆ#*uâÏq—Y‚ΓšH Mãóψ‘ñØŸ~ò ÆV§‘?B¯¯—&xì†1žõ#ÅH6…ª>4×GW6a;¨ÀÄ^z.ûIzcA—w%�mVp’^q€•`?·È…º£Ÿ£äªÏêŠD;‡Pù’o@^ñF9ć0Êó=_H@®ˆràwç÷'-Yq¦«+¡~I89«yÐà)ˆPYƒH¡îl2!+þ*ý:t»E\�)ªœ¥;æ9"Äú¿^µwU\´5Ê%I´È$þ`؉`ת:°Ia�Óбï³ÿ�ý¡EE¼Èw*œÎNQ…ñmíƒÅŽôô’Œ¤]X“Þ‹.Ê)^f/�w!Ôÿ[hù‚ÉÊÁ|¼Ž6ÌÚ.Ð)?áƒ8š‡õ"Ö2€f} æŒm2Ÿ¶a– WC‡¹õé‡GöÓ��ÁÉó’LÆ1ïÍoŒC.æw«1ne°¶ØÀüYM6Kí¸�®ˆùùi@*k�vçÿ;½âZdöCRl¼œÀè‡&ŽX‚àn*$p0/$ÖøB¸vÀß ©ËÈ_n2Öºð‚( è-‚ó2ÍåÖðìçîÉMVxÿ('º}ýSm=’DÆ6¯*ÄíˆéFç§ÔËšð´%iÔÓ1¾ÉÏÁFœæ.ûÓE÷T0}€ãLÁöÀ�Ú¥¢½676WŒŒë +Ü-ßœçǽ7—Ñ@�d"Þ‚FЈã¢]P¥Š¼LPAPŠ�a¤Ó¹ýKñ·w ¯å¡[ÚÒòÛĸ•j*Ù®tß7ðÁÎØ_¼2‡Þ‚v…”¾0'î&Ð'rë`ú 0"p Gb¡°ç NSnåùuô‘#)rüïêòIÒAÑ->A š‘" )í$€¢ú‘®©Õt\O˜ Ùë½ÜÈ^�6qãÎò² [AÄûÒòúËä”6ëÍ€wlHqönv>Zß_q^Lzü¯~�ÉozqF6Çx\òj% ÁªÙTƯž*¹sœ[D÷ Øòf¦{¿gÞ³²£¯üT¸Ãíà¸#^<`_ ޵Si¡0w<غö[ÿ§4Y(¥çÿ_8[ÞM?ƒŠÀ`¼€§j~ô+äÝ|̰¡5]@•®mv—Ú—w˜Oɾ¢Á_ãMVØž£3Ňz %¾Ï2óSÇnX$2äV�J�¨" Î{ëÜnm¢+žÚ "¢ÔVçÒéÜ+Rz#2¶Vçzž*ÂÅùQŽŸzp÷帅'ȺALgÄm0ô{iaZ.mØt’Û�ÓÉ’)8_V¯2Á’ýPé"a W¹÷Ò3ÛBJæÐó3´´”Z‡ÿ}ÀªætÂVÆœŠ»Ï>uOªåqÒ òQb‡=ÆÁS«º;™æ‡Ñø‰þD9•ö—d¿Ô”(É9q“ÀÏ$|u˜=M^z ÿoŸWã�-�Êks¢ùæ 2‡ü8FÍpëýÌG Å”‚‰à…igŒÒN¸ï&/¬ñ¯¿_Bk;iöMßóz 2�ý§U„Z#¿sm}¢-²'^À/5×çjòì/ZusŒiz̧Ñ( V %Ðû×µÑ,Q m-5»D~½Æy�Þ…¯o6½cd¾â‡HM!�}Ç!n‡þ'}AáóR„4qÛÊ{è�ýiqûyYŠѽåú=ÝçÝ+'öú_]ÁE¡(�BÂÎìr`§ í(¥ù«ð&Ü7µ¢]m›E‰˜MNgN9Ü;y—µ‘Ë”ª‰I³\&3ç%`Aa7*_"§U]ç–õ4„ûýRì�”ü“ˆ…¬E§Wðí'„±“IÐ@%ÔŸ´V+^ØÆP¾?9�cIóš‚A‚Àoxo„‚ƒ­ab]o )¬[„qß³ì†ÙÁ¥Ù~T/KJýBš�†b†¾œRüy¼÷í8Dý»Çø‰t¢;Ïs;7 `ö‰vCðcëe\'Z\Þ©LX…Ÿpæ{.Ï‹\ ¡ špŒ…ëé‘'«%¥&*vÀ6>NІ: Ÿ_×MO2w\¡ž&4ˉ’��`Nž�¥_zWrtý-ØPÑA �“±w&ƒƒ¾×Y‚|ÂE¬˜0Ñ,'ÿö†%2ýüFaRýonJÛ8JÄcc!¼)>8̤“bç´Û™;'ÊÌK?G‘A¶ùã«êZ%€[Sƒ]ŽT'“sÒÑ„šËmÌNòœ| X¢ð¥Má52ÁuÖ#žþ†P*ãƒ�½��4UkÜnܺrTà ƧÝ�‡þ3õ@Í ö¾¦ç.œÉŸvJßÑs)GÙ¿Ÿ:ì ƒ¥3}¾NÀ Šôþå´�…�€@«½Cµ—\çéH¬�PÛØï¿ w{úÃI(ÈÇe™ÏH ¦nÐÿ\t ¶ú†¥±orJ†ÄÙí1T¼ ÙD±4—K�3“#ÿø²v‚|ú‰~ü¿ýþá¾xºÁ£5F׉þÐêqŸÁÛ£‡Ç½S¥ºµ�ðˆè¿Qñ$Œñ5VÖøÃÝ“�óÃ÷Ð<¬ˆ®6ò9›ñŽ…/µg�šß*qH’¢?˜ iÕð€Xó aº!¦IÓW¾“NC‡ÙfÍ5¨ú›yRÔêz\køÒÊø�m¸ð/úc“ê+—AGM}¹�b­lOÖT3cüòY… b·ÀÕBXwA�bìÍ_éQ–FGýdqôî{`Z»’RàkãJ€»4š)�”¢qܵNZ³dì™[s÷í=›³py…Ÿ$oºé'ÉÝ"t©ñáõ‘ƒ‘»u›Ÿ%ï¯p`µöq#ÎCÞ”) Ñ8¿ãò+îk¦ŽŒLÍ¡×o5›n#×)ºÌKl¬TŒá 2ÿº;°Àb¼À@Deú±Sä«á \€á¦†Ê»±P¨Ûž´6WC»M1’0øVû+$fˆÃkw©þÜPã�Åm/Že>Æ&Ò =2Ù™,˜ò+ó3ÏøÇªåQ¹GL;X»ñäZûÿAëE;D ¿VŸonGÿ‘cèÛ,×Â_P,˜À¼YÓKX ÑVÜè©õŒ¶�Šj$î;¶3€Î€xHâÙÔþE4Ÿ¡²ùT̈wÄ#”a^6–pãÝÚ ‘Hd£½]AņÙÖ�wb± &aâa¤­nøºé€KÁo|ócYfãs$¬Øb–@º¬âßcQ„E¹ÀÑla´Ã¹=˜¥&ëÿTÞäCìÐõÛþ÷/pCx¿M¼WÕ3Äüµþçãžà;퉾Ç™¼lyÒÖcgæmüv×XåÉ;û¼Ïq‹g�Iû”Eך¨~²¤lþ•¢¢l+QÞBåãî²؉ô&ã®dwrï­Ûö–ÑËÍxš&½çÙSò·K›Û¤í ê=é^g›´× V— j©èðó[»Ø_ñqF¬Th—{“�21è‘““ä"pª¦XI�î'A›tTôïØÛ´¢Žû‘K„Ù¬´·^šç“Éy®š0_‡Ì¢ÀN=IGh¿œ&š�´Ué«‘ÃÃU8‡„8ºí–\£eL~&¶Qc£ºw톔îùW;%&)3q6IaéSŽjø¹Å¯sÚð¾ª2­ôÌ=SäþC9yc3�J[¿!JôqÖ C`?¿æˆè€L–l*�m’ sø_ÝjŽ3cø¥žÄÒmi‹ÙÏÓ„w FÆx¥.žú’WV’»ˆZZó1ÀO£_‡ ™©Ê3ñÔ\õG¹‹B Ųü«Ø39‹êâúØ_Cí;p\Á" LdÓË"“o'Y£Þ”\ý!×3àõ)®°ORI/ž=fÞô.œO·Ï·[_|[YÁo P/D.½¯“["†šºšƒC+Ý“Àœãˆz_ØÀB~ÖèÅ%€âˆª‹êGÁû|ìÔ¹@I©TâyÂÎë�`ßÎ*&^0õ('â*MN¢–€Ó çz­OÆ$:¯R,©(Ö%só^ÅÏŽNá’ÍrmpW•Ü£(åkÕŠ¼s¾{Ï�'Ÿ‹?¸ûö8œ! Ü6H×íí;rgýÍßO;FÆ­·Y‚l.;yX/g79ÍÒüJ¦¹(F,<¢ÍÐ Í"®qƒ.ú/ÿU| ·ZBÁ¯Ú#œðYåÌr�ˆ£C^r·l†pø1›Õh‹´6ÖÁœ¿¡"d qE3Ð὇ÅY*aÝßwNªˆ]4„�—Ü Bˆ?q�ÒØ#¤¶°Ðíëa�sͽøËéÇñ¨£ŽÝÁ¯«í|öccOS•Û Òr¤A8†ÛGð¡uT4•ŒÃv(!¡ƒA êÙ�ØYrØ/ýi:v„óÎ’he÷Cim1‡†1Æ mÑa!Z7ê!gü-8ßÿßž|à¢�VØ~Tj³hµý]“ÐõJéeëzˆ zÙLKç �uP0U IŽ)ùbñ8 ² š> PÀÇŽc[¸©Æ±|•ï¹ùl;òaÐ*PWñÝá  C|ƒªl·�Ï[3ØÎn%f,ÝH‘”D°:ó* "»rJ§Í \XÑ¡¾Ã†|ö½+‹³�ò1è”òÎbtBó÷šþKƒmh§åë|Z9&x8e:Z„jr|ÙýØ$\&ù@&uú%ýeÇnEC ¹¾V5àx×ôNÈ-óΘõ•?*ÁʜРRf}dÇÖ¬f›¥ô¯Q“�z>.Y~�Ö gŒæ†9ÆõÃôֻ߶5ê‰2fëEXý;*œ"—«ÐZ¹úfß™ÿ Ás)5£Õí³T0›IèøõˆÀîA"M;³¾í½zRCQ€*´f©Ä%X‘[Æœµ ? ø‰”[÷QÕø+[1Ž29 ý÷KŠkùs±;¡¦øWiúÈz"Š^GT®©±ø ˜7ÀØU YCªUÜfvØÛ¶Üõ ÄöB»Ö…_ežä:¢¿ä yICe߯†V[åeL¬Ù{Ó1bDDåªÉÊÎY‰ÑŸ”�ƒyiÿ6ä¦ÓP�ˆQ"1´€ì )¾ÿÑ<Óý Ã#鉼V‚Ršw²l•nÛ\Å`‚ÀÖ9@!ó¶#¬Ì- XÞi•k�·Ä%t,½²~w<©nà>Ö&,“Þ0÷È>,uÒ¦p?_÷¨î?¹¯pÓ§~ù•ûì¿“‡Ñ¥ë´¨ÕJƒáül»¸\(€ON%G9xÐçK–º4ŸÞ÷5/ÛžEI¦Ÿ�?Žd‹àË8[PaÜŽÿ–jÎÍOK¤µÚIÕ¬–ýß·k¢Ï™24ŠªÊ¢÷H,y#cï.Ü@â j³˜/×g2›Õ<ð¬Út¾J”ÙÓ"u½÷Ê�«:0ßÙjÉ^¤  ë÷š[îÊo´9…iÌÍÉáªz=†?ÿ��“k±l$€:ƨû«a�Õ`”n/öVAb®vd½À�×°õºÍópÒoÅ<Ðð1ªʦ˜A}çÚµ>�Wëu«pËþ‚c£ç€æLì¶qIËr…[§ù.5Oäœ]A¦Ioبaïóip;× t‘ºœÂÒ7˜Ñ€é€§Î!×·Á'wÄÙ�„î= orÉïQ—uVrIpwëX-ùi±^^X áÖ÷'òjB|š½Üìä¦}ÄÓÅ�¸²íÌÙêÝØ·Ž{GŒÔ}.ô¨œ$Îú˜çÆÿÏW)ÌraK+ñ$ñoçñ�¶;ù¼åϸrrß[I{ýq”&®ÎhÀ83Ý’mˆMy;¯÷å¿i`­l¨Í+{å…€2…tgâób#d'ZÎüηÀÕÕ�J19–(ÙW3¦X1î³2ä|<þî‡ûKÞŦµÊl‰bíhã„¶ž°3QÑRõkåö­³DCËú‘¾7 –ÍDIoˆB=ê݆ƒÄô^‘ £i.ž“p.Ž¢6YX9ØxQŸ[bû-(2^µÿkÑg.­ÒOãûüÓ[ðDŽ*×8eÎ[‰‹ÎŠxèW˜È1xkí¨MŠHWß¼ÍÃ'ìPý°í3jš…‰É†À¬³ª«!—ÍóÉè8~½hwÞ:¬Wpa ÇÄcvºONiËg4›€j!`;$Z–3²T³~d/:ÓÇêáŒ}îR·ÎÃó(¸ =Jj�$ù0LÉÀ»¨õ dO!æW¡‹´@áô©Ç¡`ò&ÂX&~êšqŒÃnñßS(«3­·<>BbbÒèÝpõÅ©œÿýÜþUQ<ã8I?³ÒJÃγõìn¸–vsˆ–OË“ÖÞ=¬$¡áÑþ¨šßãiÀ¤ÅvIvR굪žþ/·Vq+ê‰CÓ¶¯� Z±›™�]V "œb[ƒ R‡+b�zGÚœøyÃÔñþ'ád¬¶ ùT0Ò�¬‹¯¨ZÌ©º¡ª¯� t¾ÙªwÎ1c<õñ8[žp>°ã À˜`¢OÑЧëÅ_ˆuè„dÓ¾}ž ‚Ð Êû�×*áé —„xŽ©úa„ �xžÙÿG+‡¬0ÛT©Ëö%ž�ù‹ üb]×ci^UÓZD…Ð-Å%î,,µHÇFY$ôÆôqt@8î¾8X‹n™(hþ'µ»òGt“Þ0%ïvãPC×buŒ‡É=9^ügŘâì¨!rØé F€ 'X™ÏãC�H Ù+Ë®¤ä?�¡�Ì�Øà [Çx¬ãÅ‹›Ó çq úâ‰åsöV”Ñ›·EÈ,Žå5¢óÎÖÍ@GòãU%zh4ÕßʺjÇZp·|¹÷6ô¦ÍÓh$+"Bå_eF¸g/ú¢‹Ø^ìw¸S¿gDéu, °²ûÊ™äp¤;Twɯ FwÒïÕ‚Ñ’ƒÁb°æLìš{¦Å2!aKu ó�âéHTTËiàºj` ñy Z<ˆR deûÍiud5Óì©$¡®)*€G›2A-Ø¡�s½ÐáKlWã�–£Ìy¹l;¸Ù[™dw—çBìßêÓ+S€ÆWì&‚Už)Ý1šž¯ ^é*$9™ò÷èXn1»ôHK‹â@¦aóåN�@c0bAƒ3©~.Π|Ó eÈï”kFëy^fÝ“bqò»WùÁd=ZÒqŽw¤Ži0»m|²ãL0nÛåF†1ø2 Æßa^o¯ÑÄn ±ÚSC3¬Umº8²Zº�f‹Nã¶Aiq£}åm…€É}²…Ó{)дwNA¥Ï7TßÑîÂôûèèc�é–Äv'&Ùûuòò©�#ÙA’6ý5ΆÍó÷¢cýØ‹ŠÙ: jÃVÓ ñJ÷;¢ê+¦¬Ëü;µùÅk½y] b3;x<�FSð8pÀ/¹W·µ— ­+£¦ñÕI$ØxÜß±Ôf}ÓØ|ÃÕîMýóW; ‚~˜u;’åZ#Iays[®ßºÇ徨­4­Ñ_^k?.ɺ¡Awò$þú!•ÃÒÓýàØØ¢ÉLö°½ù5u�q$0ª<\{‹Ñç" Ê—ã[¬¿¤ôJ‰‰Æ pëSË‘ú0{ziË t{ëäCŽ„àóÓ¿dûšxý`&”mv–­¸k•C®êÿ\(ûé=l¥¡‡HíMçJ1Ìc•Gù^[òb¤7¯mdÆ~؇wÈŽfÀ!§o³Ï'¸£id$Ën2lµ˜¬ÿ=ÃÊ[e‘¼Þ)A‘ ?‰Ð }r_Š Mƒ ¯_>u¥qôWBzÙvŒSëêR¤JÌïgc.Ñv�sÔD)€ZR ‹ëŒ5ȤH±,{©D€HÖÑž(ƒ–& F÷¥õ܃̚;cg�(Ž|)—¨éI¼´Y¾àYe�ùQÝþ~‘9[ýGÊ�aI4³a&¶-h m³…÷'š ìá³5ÁNBæ÷�0*¡‚€!ÿ�Õ´“·½˜1™hF ”ùÏv&Š-|UãŒi(%>b;=×G·˜a·öé:k5‹0h’¤\£½ðUR×âÂ>Wr3ÊÞM-ì!II ‚î„b…¿Ïy‘jBmd�Nކò%ä­M›ò“zW໎)³ø7A «‘0Åsâ`¿›ŠRÛ»þ�cMJ7(<€b¸)ZÅŒ•_Û¹Ûdd†Ã…Y¦#qÕj”͉žqŠ‹ñ´xšîš·˜”Åcÿõ8õcŠ miD Dã–tÌâ#�’G ¦“oiˆt‡òn÷ì¶ÕÞ”QGþA 6€Xc�Ì”6~kDòŒ•“+Y t¸YšYx«×·;U7–ö°~ã:ï3‰˜ÍEO™VØ»NÑ?YÕ#*s%µÅ™ ²®l"%ÚWô8&ig^˜C¿�õf£ãtôQÕ)ÕQG }‰sò<뼓°o*åÃu¨ä�,àÁÿœ T ù±Ú`…­kªÆ!z aD¿¥· ÕyÎs© éòÎË>+ì ¼qHN'ö‡j‰PZ¡ëž_ /WÌe~¥8… ¿.Íˉ¬¨YýP*ÐÅ.6kç•UR¾Òœ­;«‡›’›ž,  �§”é}ʃ\wŒìœï€"ÜTB‚øŸ´!hÄ›È\¿wùhÚô|%Ÿ*W.�ÈÌ,¨Vï—ÄhàqùEßJ¤ ^ó‚ñÐAk®þmú%xøÖËÙ#§ß´‹ÉÎíɱr· Ú¸k;nµŸ1ÖÚ\!`§¹{vÚà–žÎá áŠãaúlQ]Ü`O›åZÐŒœ­b8� âoI²šÂÁã` üÁô{‹MQ@ÿ:�¬X¦[³ì(� ½‚æïC²94°1:2­�¶öl0ˆdâ×$ˆé¿Ã²$ó_ÊÐ3%ò € cÝÕ±ÿ º½;@ð�@h uþ¬B,…f /bõ§I !_9ª¿#„[,\´¥‘Óñ£ KÏ’0»²lÕU'•RT9bD¸0~ðAÓë6.jéUkŽs‚\�o±U˜Ÿ“ž±5÷nÔEá9�Öb‹Ã{ø¡€²+´)òzá“&Zˆ�·ÜÿÏøcÌÏ­@¬cþ’|@¢ó³åè«‘tõ÷{ð#ÂlðIÞª6•¿gÙVpRÌmGÅ=WÎMûB‹1¿öRúQKgPŽà—µ%ØS‡TΟcÅ ûŸÛáp÷]¦‹úÕ=—à옷÷L1åmZÑH½eÃ8E¤Gû¾GÄ?¹ï·‹\®_ìªÔïß­q¯pö¹a¶3€üb95Úwš‰Ôÿ•»[">;¿ðª6y—·¥1ãQ NãÇ’Ü”3c½rÙÙ�í”Íæˆz.Núë[_˜È¼”hgZU¨>àcš²ysÞ›¨ÈÜ©¡){@~K²æïO[nfL.!ž¥sµBH}ëÿýû2I]ªø‰¤% 8;(­¤56qß5½T“‰¯#Jÿó„¶3Ûºžç3¸@i•˜Y‰Š8µ�wæ{ Y¯o_«£V®7茄ŠqÄhÕOUè�Ru�?™�äÂYÝä¡àâ„¡ûë¼}?9è§l¥^�<&µ·IåÿH»²½ »«WZÓÁFwí»g{öFŒ£ÂÍv‡ã2ñ¶éú´ÈP‹|6•–uó…¯Y£­ÙfvA4¶~šØ�uIÈØÎDOQÑÇ¥ˆ|%@õÄ›qÞºlú^e¡rŸ �×È:CQrBÉÀš9ü�^ <íFiÂàІÑKÁ­àoP¤—âÖ¼¤¯æ>‹•;ºÇPÞ‰Ýð åB”@K‚ìª.Ipê ¦_Ì‚{Úýc»úrïsû½ºåÛƒ+ë"œï+'('@Ï;›o‘ôÚýJsa[êsÕШZ�ˆºÐNP®´¯–æU0I ¸ÒÅ<݉�î ¥ÙÞƒ‹&;æ+bÞ,ØÆ6Ga’žßåYs©]?*/˜\fQ ™Ðé¬{}ˆrl�o‰IJ+!Ð¥xbò~ºýS rI³Æ”/á33tmŒJ"Þ«›q2'�CVb›*î]Á¥ÚɈ×щȽ\ovAhñљۚ}ÜSf¼§Lƒ—';]h“9ºlñéÒ Û&&Öoo” _`'ظS ¸Lªm3=ÒûËÑ|ŽF¦(Y‚ºR„}ìô{d@Á£ÔnV›]®![ž•Á!Äÿ´w·GZÆãïŒrë)ZKíàs(–•éM²M<þ,Rº( ª7¨ºi~Ð�•šÄùÞ§²T™‰T°Jƒ0ñf•ºtDC¨Bëq©CÊ+îFÒ”Ùñ­%Ô¹JÓ…Ýœ?jÎWTÀ´™ kÆü%g ™‹ ÜMŽÛPO÷›F“Pßû¹ÇU†WÝy[ G/9Mdå8h�N-HN€Ýü§ö$ EÄ�LïßtÄrÃëà<�ŽWÔMïO°ö‚›à¥¨*Q¾ü)ióÇ“ñ+I9ø³–7!‚Pm0¥ó¿M.V™ Dº6à&¶–° cV¸Õğﻼ6¾7›A ›¹bE²`p3ˆ¾EÁõr'Ôôm' “ÆfµípÏ®'­�táÀ:–•‡³ÒðL§’pãð?ÒQ 6Ý ËZŽ# pJ$I6$/«£‹v»g=5R¥5”´‡Î©akzŽÉ¦Ä×){mg‰JD�ž{ÞúÍúMPû¸>¬)^©@ÂfÛ [ Ï‹X~ìó±ù”ètÆÿé—Ÿ¹ ]ã]Ц~ûÜ~ôDÊ é’±4#ƒ@™ †GßOvó÷sH_ÿ«9y;ÀOäÆq„+G¥æ'èŽriâp-Œ`Ï’‡Hdé]¿À:irŽeX^y%‚FÆCsê|òN“ĹÈJAW¶¦¦tÉê£ëœä$“b/]T˜7�×.ùÈl7ð|™;¤Mí í·,qFZU賤¢ µBÔ/kõ? X!_“Ñy» §¢ˆ‹ÇfƒÓÇ�š‡?9á«Â¹‘°k ‹wízÔ~Ãcí™Ä‚a$«“ ²îåª%›Eù±r1¡‰=­Oi ¡ùŸ�GÜ<ƒ’Œ“P>Öj= íÙ Wšaú ”ÐDꢉ²—Äì£�5T&Ј ò÷ÉãÂK1× jhq7O¿üªXIu~n K+”g�b£¾2ý¯WC“ƒ7ü ŸÜÔ�B¦]ž M¡j´1Iîå"’4DcL«xK]@Ñ�t—üã³×äèNÝ “×ßø‰oižŸÇAx[©ÎßÊXº�›ÒãÖî…þŸ4ó˜u³pIÅÙžD6Q~ Ü…•j¬ \Ô¡WÐzb=‘±Övòú;Â�·–}1>2®V¡‚Á!° ÷·�¨îê_Ëõ��Œ`fQ£²)h ýŸ’íôœ¼,ð#ª÷¡5 _N…ËD ÁÑY‘rí¿E÷Ó4ìK üÛµ3ŽÊråôæÖ}`@,ÖãÜf-Ëe¼Ó¬!S€«è„Þâߊþ~–�:2Xh盃X3YÍ$b=Ü( DÄÆ:[v~è ¹8ºV ŸÍîðO4«^ÕV(] mEr»íòy ÑÉ…Kõˆ >Ú¸zÛŸhåßFP“¢%_V_Šl&{þ8vÌsÌ…ñaÀe‘º¬(غžb CU$ÿS9ÁŒã]d8팩’Q‰®Í ¶Ó™¾€�ñD«d%¡¦ã¡ÁàˆöG¢ç!¬Xs "ô�…ûf´1 �GÂÏüŬr¦Û'œÂÝv páÕJ^f¹Ø}”0/fbØÊ¯B«í¼Òm†€!®Ä=/ˆ÷É”9»’ƽ4lÓLò›Ü–™É>¶àÞ7“tw™OSã€% ;Cn’öáNÔ\¼kÞI*i(g²áÚ4í¬Ëÿ˜¡&póË ôé2ŒGªÕÏñlFàv7ç<營”s´›ËrÏìòwhŠ#ÿC|u]^pus7]–Æî‘�»°{×€oÙœÒÕTêÃÁ‰·îmlä°n¨ÓHZT]‚õÆ"ѽGþÜ—e-EÈ]{{ëÂvÑ›]|Înû7cãšHÉÊ�+þöTÙ‚æ檻‰®Mw°`¦ý‹ÏЇyÅCK {ø_BW…[vz�õWÕ‰ <ÃIòå”™Tí!¼8µÐ7¡ÏÅnÓÙ|nwQw-Ø,2a½³tÿ,@-”Fùˆ@ùúûdÙ ÊmJŸPF�jÏÓùw¡ÕÍN%à*¶©†x@0@Û�Rüô°Ýž„ŸrhÓàªVý>ƒâ}�2ƒ`ï0ë¾/–]¥†_Ÿ¦"¿e„cAí'%È“SᨸXµ¤ÔS?£ÐUÞG7aü Ä}�1o(YY@zM–w!#œ–¤Ÿš ÂÓr ù”? ‹^‡L‡86ü-íI":.¾åÎ[6 —(¨o*F"š®)÷Ž eÁæØõ)ãYÊîͫ޾êÖ>¨0tú۰ÿń¤ßáC¯L1ë2zB�JVëEäÔäþ:éÍ8�Uÿh�qý»t>çC¶dWžÀw©ÿY Ø!“·�S“²ÇÑÀÅ÷ÔDŽÔ‚ÔdØræ“þ?vl®ñ`9›¥âÕñüÅÙÒe„óÍv<=Áð%¬oû¼°áZõšÆÛm,_×;«Cõ‘|‘ˆ­ŠË O¤º7n¿­HÞW¾K«ÌG!È òl‹( $\Z{úÿõ,”L3�Cgé�©�0O¥e6%#EiΫX§¥W²¯¾ÐýQ�<r­DÎ}(üá,�8øžÿðeÅ¢ÈÕ�h{)'kß½KfÑSÍaÖHtE°­ÙÁcÔ›!Š…iÞ,öCq#v *púßjE˜>çÖqÃeð‘2£/¤ ßÖð¨šÛ딥ôd vˆsÌÏÊ0` ÝNFòBÕã�*øL�’<@}ƒ“kƒ"ÓlƒfµŒ—lq»²¦šqlŠH�&ÄÀk×(xl°çy¬ÖSL›ÿ䥮3pPP†ªFÛY½U€"䈡8éÚŸå‡F½JÍÌDgHZ Bˆ³[¸Æ}Óžssœlœµ`(|Ý%=B>×V+º¡i¶î绌ùÇKCåK!¡à[bÛ*Ö/�Ó™jHÍ5S3+äâé 7l£5 (1ñ-=Í£zÝý'ÿ+?êÞx2ì/d¯{™�Ö÷c(E8J€´ªd#´BgËSmÍ¦ê£ +=ämŸÇ_Hð|u*Òy…ò–)1[ÔU@Jhܰ2Zúj{G¿cNîã£Ø5r"6ìgùŸKFX¦¹rîÜX!;H’ N¾{j9ìPþôHÒ„Äï|‹'.$�zWr*Lã¯À©b{e�\ÀÉvHC,A€JAŸ’d”TðŸU=òÒMà7}X@ s–*±|g²A-ׄDþP`…Žrúc´Y6’óÄnQãQ|“/'cñù@öÙ¼äÅ{À0÷èÁ2¸µðLäUÆÔ´®j/ÇÍŒCpèÀõeÁˆ€fª"n€­~zÀ»�9®KØ{ËÛö4^S¾IêÀÛ «ž^¥àÏlAëõ”'?ø”økx+¥.WÕy¿!íé-ãÿŽsz,«:'ø³úœóf3 Ù® çâD8ãö5ÎÅB½·¤‰']òÉÑÈ(uñ*SgàGÆ † arA;r³¥.n%r`ï$ŸÌ�ÉÃ(V�ìüZ´º9¬ºöòaâ ]è1ýK�qkR/…óõX‘ÌEZg~©¢�WqmÙ/ý½9c¨`´Jžßæžòÿìë�Ñ7Ø8Rn;LïÙb¯âƒ0wÕš 8`»¦Aÿ�{6Ø»}«�/‹cý½trŽíâôiä9=´’p[´†¾£CƒÚ�[9{:F;dTb½­[ (Gã"Ÿ‡¶õí�–ÎjUaÔ环øí‹}í ¦FNžóÆbr¼Sã©¥½ƒ•*Û¸5:ú–®ãªðm)@{x*?|Ñ K@£ŽmÞñÞÝdA„T´í.×1ï§`Ï3iâȘ'jÔuêKˆöŠX)}?cñœï±Xäý8>*[ÞpiËd! š�Yé�¾ªøŒämhA6 ,Ò¥ÆB/18= ¹�Õi �"ØÛ�Hp7l‘Ãâï4ƒõ}ö*˜à}lgÿÁ¬;Y¼Ûx­»çï qOþ´KÓàÅ�VÖ$¦p\H`^³XŸzD‡l€ógñ�fÛCrq¬+ ÑX`# ´àÎ�Â�Ñ%œQ�"F�C$Ϋùžð’óÂ0®huK{âóY{X*ÖC‘/[A9øÌŠŠ@?þÌÜeÅ�TËîÂÞä0Ñ®@‰5#t v—g·¼Šµœ�¦A*÷ô¡™¦!.fîƒþ[Ÿ 4™mÚ¢`$°*¯W ,°Cˆ„‹ »îe÷· -U¬ümÖé§»¸"fÿq�†ÿ½Áö]Â÷oÕåggâoËƽ¬ §\[»Î¡ˆ—H;©›xZÈ:@®o lïãç˜ý>€Ð‡…�³“-´d9÷Èÿ?@¿¤¢ âñð–-R_HÀ0)ð,pJ‰n÷¤0ÔD6^ÐK31¹gmhGQ.Πܯ8_±ÜMàK0û°¦Ï.?Ö8êÎûáXÁ¤ëXàTX¾ôäèNñ›½œ ÇѺÌ×{šwp…Ze…lSÅÿšZ =_Ï›¸Ú$ÕèG¥ èøÿ¦%€ÇÜ–¼² ¯p²in ,è’Õ°x)Î/ˆ¡€ÕÄ¿nHÍ#Y(¨Îžºu-ùZ°¸GëyAe.œ(« Ò€Û>΃‚ H¤úÈ-^1ø…·€KÀ•�â‚=&‹n¬‰½¿Oœ.ßöñ¡¶ðèReê�ºdÙTŸÉAò}Ý�z³÷¾#fr�³ìùv0n广ªÒÙÚ‰»Œ…Æ"w^a1™Ä`¢ûλZ(Ž¿|茑Šg®.}34e€å#8À›ÄÙñ }yÐÙ„�ŠÍ Ž©¥À᥆EÜdv7Öº4Å¿ŒÚ´‚´¸‘gñ¸ ÷€OÁý‚ÁúØVÚµüh‹wfs ëíï ±šð’%õDþÕ…]+ÚÔ%¿À;=o#„ŒÊ΃§É`íhvÓÑû»^§Ül…>{?wñuX_MV©ãkjÉø¹�?"ŸÁ]�°˜ÉX–u‹Ösœ‡N­ @ÂXRRI~âžà…ûlôt�W§H/ Sˆˆ—t¹Ìè§©Ûv H¸ªÇQ]ËŸ§Û¸ó÷8f~'.Ôrháû‹•¯—>é¤ÖÒŠº‹äÏYû¡£kWw�Ç·… ´<ŠÄ@¶M.C@`4°`2MýÄGßO»øL\­Þl®¹ßïg'MÄ/vƒlÜS-¬¨+”t,PÊŽGU>ºtòr8¦Cg94Ah�nÚƒÕ\¦¾ìê–›MÁªuã#?Ûjà™“Þ›ØCÃRf\ŸÉ‹]’ˆ»Â›3SY&‰Ó¼à6ËüÖi›v]¤ãhUÍW`·ÅL.l¿³rþ(=XãdN¯“£µämâò¯Á¯ÓäG±'`y²Aä¨ÕÍ}!#b4pQÉS,%QŸ:Ÿ³nGÿ­;èü$µ‘dPðÅ瀠€´NdÒ¿�Â’­MÂHY+F>§iRžˆ±g¢Óo¾——Áè#¸cXásã´ 0ï$¶µJN‚ Y¬Ê‡cÊQŸ®†N7¸Š8Бó"^ôe¼ GÑÉ‘ªÛ%ÿ躄ŽnP“*Ð9×°†ÑÍf?ÊÜãq‘ˆ›>\<ý%ÜnâqîþT¸(ª³°¨–*™ÅÊ™>T üUýÿ~ãÞ™ž.;ÌÑbSíp%BŽÁÊŽY™Y¾ÐPvdK«th±`#ùYèÓ€‚à¡Sª÷WšTQ�v4TÖÞŠšlʆ$«OîK ÚÚ¦&6Qxl2‡–j®ü\ÛÄ›NYQ‰ Ý÷±ÝØú1 ÀÏu>ì‘)6‘ájü×ù©zæYnñ2žöŠÀù'w8iÎ|I<"M ¢ÈÏŒ’6 NÙ¼Ú¹x×Óƒ¿¬' ‘ù�ë¹í=©[ñòñÖtÅ%l½²¥—dúÎ^‘jJÎÇ(žûmbÙ $"fž(¼:3P Mȇ�ñjÉ hú2ÂèüMãwíÿ¢�?äsh–‹D2.`Én>Óé/ åy"qæT=ÊüÌ W3¾‹¡¬vë¹T=-Œÿê#e=ì:§±Õm2i—¸c\Ë Ÿ÷þ!ÑrvžØ¹`Á·‘Û4 ’édÑœ+2ùzæ°7œ¥ú\Yÿí‘àxÂM>B@ ŒÙ~ýÇ>à+qŒãT#࣠s{Oöó$)Rï�Û™ºÃxEHU}s�S°=Ä€T„2 ï…­†éœôq$ïÇUºæ%ÓÞìÁà€´¸F omøÜQx_åç7¼Vc†k/Ù'‚×q&©}‡k厾ˆ÷ƒÎŸêëvûଞ߹ØF¿‚9öê�÷Ðò?—ƒg‡äY£}²wIRv|Yƒÿd®·ÊY°Œ·Æ%wJ¼(0uZ¢®i?Ç›×O±1,¾�î 0�d¦Æ j|€±pãúŸ©xµÁúgžÊæB’”em9¶6׿:) ¢³�äéÝJ8 íu#ÚD¸<Û[Ê4wlñŒàúî½J¤Ý˜AULt†ÍT’½R0„9�>“�ÉQF4ï_B’bf|‹ Y¯Y²j›9𨔍\6ó©óî€Xbßã‚; ²ðë’¬è5ˆ§Çû‚êQ¨ÚlŽG~C‹²& ¥Í”Œ±{À_ÈøÑ½ =¦ÇOz�¤”ä–²: ÆãŒ”ÝÒ‹mo½�ŠQJê1àzî€|?Þ@nû“ã�úÁ¤DT¾äaÃ�ÑðHž±öŸá5;HûÍö)ã¼’ŒÄò·ð½0ýr×ùeßæ-ÖT]ì@´˜RBý?˜ÎýÕ‚ÎLRõ›Fzв6ÙzÚ§;[”Âgù†µž}]†Ã�¼àüg…#zÕºåŠÕÜÑê7—+Véihpžó°-œ«íjÝj„°‹¶#e@BQv] ',=Âûüçw6XWy„ïFM,I>ùZôRüZ0°ÎìãVIX]¶ùÚÚ‰Vøàå«<öÑ>ó´•’íyÅ•"ñü�²[™oþJ-î“ðZx£Q{‘㶉ßj©enÓû³ÚNˆ µ’þ%éAÍ—ž dÉÞï–ó5½äÈ·�®³V�]Ãð¥ubÙ$]®N²ü äTÙÚ“´m³~ò,\~PL £ÑgKf¤VºŠ8+2u ñ Q¥j6O¾—ÇlA#îªBŸø}¸¥ÒìžZX Õ%š¢÷ÊçI%�kX‡$ŠgE”ˆà4}Œ×@|�™Ô·¥v%è‚ûǯ´|p†ñO¨…È\ñJ k˜·+J"�Á›«ª6O¼á쇂F³áy=Îê±ÏìM�E`ˆ.†[9Át\ÔÈ{eIª3œgg¬2Ä|]¿ô•*hÝýûà�áúšk·o~•† ^D�Ÿ°¥1Ý—þaÎr[l–ü‹’æ|à_ ÛN¤dâ\"½cÀu§«D©Î®Ñª Ì,µ}qG…ÏZÂq¾Bvk®„k5|òÏ22¦Â:Vvÿ£Öð´dÿñr�56|kÈ xj9ƒl0Î zmÒô÷ðÎ(Û¨<‰óÂß–—ëf[Å#oz^Ã'sÝ )`àáú‹å÷D¦¦;ò­CÕDãÌzÅÞÍ9;†!À²e´éÕÙ°§Ýó$zæ°:lnU!œtûx xrê¹É»¢Ÿõ@HxlïãK ^ ËÔ�§adF:š=Í|Í«Ì#^º$c6ñ«êAúéÄ0€7ÍîOÚW ³nÉø÷Ÿ -òževºÜVηi•˜æ,>ìÛèÌÿÕ~•¾ƒ�1ðÊHêAƒ†)ê®'V°N@BæÔGä ß€ibÒ_}`YätgW†QR‘ÅbñîÓWKàÏ–•€�H:´: ”;Ÿ;×p~«%�©÷vߨ„ÃF{È=_tÎ"/€'PðÇl U "«/’�Ué&NYFª-rm×J}*¦Å¬°ˆÙ¼–9FÄMçÛVld6øQ¹³Ì¶xïNq@üYeM¨”°ßNêg0£“€ó´?¡“¢þ³„4æ}¡ÁÜêæ_Qw½¶édJEè×¢FÈБäWí²y–©ZbJ¼{@6ÿiü„Â8µÀ Ðí-åú&°Åͳ,¾m� éO¹é…ÖCW*�á§ÇT“9·œ*�ѨðÞËé¥�Ç;Ô†,—!IëBðúé�dCÍyž=&š3ß%4̃7ûÇF•,½Óöï¿#Y{…κS>KŒùçRODŽxH¯È‰1 ÿà¡„ö¨iiœŸŸ1‹×£‚z’2jm\z¬6òW(ìÈl®‡Syé^üýhoCÞ•™RK™Äá8J]ÒCt  µMèÙZ¥žghö—¥èôñþ%QÓ.ƃ͇5ÞØÂï”ܰPX§&X n—0lVƒ‹Ïn‰ºÂæ€jTC)z‡i 9üÍ#õNî:lŠ”Á\Tã8|ôú†ò®*ƒJX%Ys¡Qžg0†è€°­ÄåÑ ¬â×yÿ Zÿáù¥v$lL­ ð& ¼•‰�2�2emÑaJ§(2±n�•˜Í9Ë,µø`M àEoǧ„IV(ÈÀ¶°ûõ½ðÃC8a9Ê“QNŒÇFz|Ö¾ód}—rl‹xë.}’{'«aéJ@^½"ºT9\¹ÓË»uÁ÷åQðÐDP®á®W€]áE®æé«ÞRS-?ЉÖб™ ¬æ¹÷=,°ØÍaËÿTG×+Œbé•K£è)¤›ðâPwRzI4ØÍË€˜ÐÖ;Ÿa©Ê'íxä1åóû7Ýb"Ú�‚�E�¼ñ9ŒHÀYžÓwæ^„<)¦Èâ¦s H¸õ%rZT¬¡+ñuŒçƒ¤Œp…¼£W—£çÍÓNýóAÙˆuGÇõ)¼1B­µHDVv¬Ìm¨`¥©°­q1W·oã¦*Ûn—¸fÔU0úSX k¼†UÇ99ý©d½|EÓœÌ åÀ¡¸ ’_ˆ�ÑppÖÅš½ŒR„F¦ðvŸ7°Vr±v½nï 3B˜©LV}§ ûü:Óì�Ž[*  ›2¨5zÐÖK.b8ŠNÖ¿Æ]u&‘ÍŠsðO ´ÇIè˜&;.bÉlŸ+ 3[ ¿¤¸lB.1ÂM膾×:™LKwôÐ:ºqþ+r&C(—%Vt=«¶�×¾ó¨"õu³p³ƒTKmBÓžÎ[>d{ç¹êÐ9é |ì¢qxÓŠWk·Uô;œ¶Û�ÙZjÚå|Ûf~àÛŒ’û©®Ù,Ï“PŒð6+ò$wF|ù\¿µ~&êi@ö¤ûg`0—Ë+Ï” 17Düèž(‹ê10Ž1è“%³â Q§:€K¸Œ½]ø²ÛÜ©ŒßÊ’ßg‹k%’i§hð5´™ ì�¼Þë- q�"ŒxUø:ñ[œR²¼äMаêžC›QlÐÉò^`–Øá`¿œßâoë<÷k`ÿšÿçœG?;šß$­f¼}¨GÃ’Vê&ò(Ï“*à× |KM¬ÕÇ+ºvU» § (}1 %pÄhQɦª¬*m-]n”—ç Öf¯�ú˜nÉÿ ™\÷I¾~‹¤½OÿâŠó]„Áî&L ÚŸÕnGÿ¹càØb°vÀ*âk®>k‰‹2ŒCTíH€&€RœR1ã6�k¨ŽÂà4å¿hgü–•ÙvžÏ�Q�«8´Ú°ŠQ£¸$,(- µ5´Dà?ìúTÿSEÉKgD@_ÊÀ9ÑOEÓ• ŽnòÙt²±@ë§œú $Q—`ÙâÛ4 ív³Í.ÜiüéŠy¥ñ…%7Ú`Õõ~R¾˜ÝóŽÅ‘ë†5Ñ�èÅFPæ®ÀÜ(pœb˜°ž‘1Â3òBö^âm,zŠIO�2 ‡\µB_2�× 6DÑÔ™¡¢³ï±l%I¨�x³È]G˜±Qê•£ú_evÍ hYÎåFpÏCº0¢Æ” 8»<Ü 5Míü@7àPƒì£™-è(hì'‡Ù@ægFEç6TvŒ'¤†(ô|¨þ°ˆuëjM 'ß½8!ÞC¯ËžEÈ”{ç ÚéVü¡ûñ(Kãˆ".Iü~¸ÅòVÀ‰6Ï ÖÃÑœêɲ»h_ÚÇrÏ@T–YDwº¸Ë�e&Ù´ô7îd^Ûü²Éè3™d¤iá[êž¹{+˜¸ÜŠ#9’»j¸»\õ¶¢ŠK^EVGKg}\_«e}é%®‰ÝÂOx^g¥r'¤_\µ³[úŒýªsXœü1±LóÊÊ,¿�©U�ëÖ†[‚~xá’(Q%Êm6p]È#é i€×€5™½Ã².|øÖDÌ—xfµñð@ªÿÅ,�ÚálT Ha랮ܚ˜ûB.oÃêÂ×÷—•öîÞiªîóîӟή Œ_�Åe0YÁ³ƒÖN¦°2`þ¼Uμ4O¿ º¦ûôÓÁ4ƒŽ²×È@çÞ}Bïi`°Ùû·ÚÓ •ÓdÆ›|˜lÚÛY�‹ëhñ(Ž‚>³>Z€ Ÿç­ í‹/æ9çöˆÚ’ð�®d¬ŸSg†¦Æ x0PZeÄ4ÓÖ‡u =y·ô­‚ÿUUÏñ?3 Ÿw4¹Of0*6yjŒ_†;0HÐ÷ìÿ[cüÞ^TœAs¶=ï߯—^ÑþODÂÇî%ÞÈÁ/zÕ aÊÑÈIŠHRÌBöšú ö^’�#wB|“Rn1ÂlOø½ÉbA±2{ôùeðY¦ÂxF˜nNweB0§Hô˜9;ƒÓJlà‰QÑ|y��ŽÃWsbæ;6Æ-ìÏ‹©í"Ö8óføt˜ºgêQ�M®¸ì#j-ƒŸ?I«rIGLÁ“<\ÕH¤E_h˜;‰ËЙF^¼Ù°àÐQ(Ü;¿AƧÿG¢Ô O ¬K;#[èR§šVÏÊ�ûÊðX Kaw!T¬Nœ·@üúJ�•…lš7œÙ¼üëoéŠ�£°ìm¼°é"ÊÖn‘éÒ{¬¢ísá•‚�<IH|œàPWÎÕÆö!l1ÕãCbV�ÍÚ%Ì*×Åiêï®ýº‹ˆ>=aíü$ˆQ¯è¥Ó¡2UèÚ26ìngj?[ý{[w‚s+ÓG÷qÅ :i`öSš/CWKà¬7`?Ù�•4¼t�•+›Ã®dh”Vï“Èçýr ¾wã<&Àƒ/ò§íb�aQ{¯w¢ó‡'C쟂Xª.ðOÇd(�)LfÍnÊãY„Ö+äÀ¶S~ávý¥´ l•ƒ‹Tbtþa¿³h±‡RãJ£¬4>´ÙÒ¼D•QÐc¬SïeͼV$ÇD$}t0�І{¸ ÆJøÐø(ÚÅ/+GY�»ÆW%?ñ„Ÿ®o©ÒÖ%qÙíôÒL".Nÿ3‡ZºË§ñ`íçÍ¢ã~ÛË6È/¹_­b;’‚@ò¶Bw�Âp pò*M ~oÄĬdšfˆyIVñð.bçþ¨´Z°ZÀà"³ÄU ˆ�V"~�Ь˜¤–á”W�AðêOÏÖç䟻À-â-#é¡ÒnSäf‘ù3ÝJ% ¨MÀÉ�&W!}âã�æ^…JÃ|ì=²¥ÖSö‚n š �tS¸Dê<•V$²)Þ¬h-¬† 8hG’ÚÿƲƒÊ –>üʇ§=~Öªd±¼ÀÚ_)ZŽŸ“Ràch:«ß”™é2�Øž|ÃÕŽfõZ¯:6XßÚ2¥Å>§OŸ�+Xç¦ÄÃaƒ6bÿo¾á)°Ë„ó¿b!DQ½(å+ši­y-:µ²"ŒgoOM½Á^ãŸÔÖ§¥Íßð��–* ,®:T™¥›­ßß�ìkãgÆžJQa¡òz‚rb“qsŽä[õØ ŠêLê¨971xŒ8ªk ~ßA€ù=¤8�¤�ËQä*÷Z;7{Ì ;ºÿHðÈ`kûÕÉa\&'Ev™í?+E=ƒQ›sÔÇw¡sžlœKáõ¡S¹–M,°Oì•'+À¤?°ÜY” Gž²ÒûHH›y�÷~~Ê>BžL_í_[?‡ò'ŠÍ²]äéø¢hý3ÛÒ�bŒ„‚‹X£ˆ9/]F…µ·~Ó:§&ÐÊ{ ×I’Æäh–æÄ$£¬­iÝ‹rqÒƒ8¦§hšÕo<‹AÅžßüë�6¸´3EÓpR³Êï®tnø�ªáÕ§F‰Ôbkn)¢ž:–½˜E9 Þµˆ­}i’ºxß@¶"ë½²ÞL,ÉG¤�ÞýYQ¯1â- < ¬ÔØZIa·&·²¦m¸ªÌ;&ŸtEY»z�$^0OÈêLQè—¿Ûq�8N[Þà~q ÒÔŒ D‰P޵úÙ³[äØã¢Š´ßž0ÊÔOu²Ÿ�šŸd„çKÿ-|ùƒ[ùüžÉ £Ða_ ÍI8‹fÑOkiÍé›ÍŒgE 6Ô�+÷ä9œ7Äg¼€#[U�.i}JJ/êèf? =QXÉf€à €ÅªíèWi¬ôÙ›jHzd @~Jt÷˜gÖËxÖ¢OÜŽ¡úÒÜý} ®ï@£ }°óüj»ûú_ÏnBý—PQ•ÈÅßpöwp9T<�àÖj®°'½—áù&]AV% ´�lM¾À]ÊF–|‚hA×Z�•gpSÚq£Läk`±rÂm%?îd6�…G)yÈ, 5‰a°Iyìt@4í82«wZGÁw�$‚KªVÛ&n8"Ù ÔUµoÁÀXŽÜz]O¦Z2¯ˆÞ3œš›:Ýñ¸˜Š‘ÌÖà)r[ >'æ=·fC‡IýŒofE.—{Ö“’Ë}¸Y¾3œˆ~Ťm}?­=²­äpÎÈz´ê${W ‘…#4ÒÞt˲ÒÓuX·^°´*[ª�ö¯ƒqÄã¶­°'ªrŠ8á‹þU(rÛîÀgâk‘V}Ý‘}•?‰(D¤lgLÌ_0t\á3’ô4Vå'�™(<›¤ùÌD±˜æL„m®YNÅJZÎ3Dzìªo­0—ùöÒ*n}”èa€FýLÍ9Ëû·ßO «”Ø&Ø8NZxš�Ê|v@]§æÍyýX)¤‰.ºdPø5o�ÃQ<ƒ‚¬]HÕåèe¼Öod•ÁïÞ‚ý} wy­›ØiɆâši ØÓZŸBCò2Ã?Ö÷e„\ÛK» Ÿ¬PpaÒ! ³— Ã/kzJ5èÏëYŽyš„)*ëâN<Ž š)NH MxjÖç Pô2Ò•š'/äBÏ‹ÚüTÒ7B’Büäsú¸~œaÌwö ¦¥Ö3étmå)Iº´Ó²­|YÇŠçø°¼·¦ÐÞ1ßÚÓQ8â˜Q¿+(Àâþ7¬¥Ó®±¸ˆÄ†¤: ¿Pž|,�3f¼Š„!Gწ“àe`|}. nLt¥|òvRV Pñ—2$ÑÝ{£B»Â§Ãå ¥K§KY}5Fº’Çž² YíkMòŽÖßÇ28ÍŽ;ÍÍÌT/^㌮îzÛd‹k5‹öCk$‘'¬3:�6£`µôø]j WŒÑAƒC©L_ºr±gqµ¥Àêª$l:�ECØé´3eõص„™q‚çicDýé®:yÜ“'’jÏüx\‰râ4QYÐIfL Œ/æ$\¶Úv¥à9]3ôØžQ§K2º/£_*!_œmSÜ6Ɇòl5|b°W^À%…Çò&U—þU�p2Éù‹š[LÒ$õÐ×AÄpôL ·™›“Jc „¾êžŽä÷ÃV»ÑSQP¦¿ïÍò\?ûWû·˜‚¶÷YàsW[ëX©�´ý·]¢º´i‚‰ï:F‹GJlŸù@�¸­b+¯K®öèwc\ëjzNPéá;ðž8�Ä>5±Q5¯ó§+“·³sCiíÍÍ÷O«}jx§ÈiY f÷'5£9˜E…mUMÈaï¤wäôeµËÐ —€ÄÞû%£‰‰…êw¼¡»%ÆfXì<<[ A›Øâv=ûp¶+s‰ZØ·(�úOW…�„ºÕG9 3„²hÌ[;Çšþp}&‰P…Hf˜Œ·½>:¹¤‡fOw’[R2ذjU‡L5W¦Íé‘‚CET�QËoR$%øóyÔ'gYcõ6>k‘�kJµLáâ Þ ÷ÿû`¥ùÙ!LW],3X<¶lBP¬*ucšŠ«›"‹t©tÃöŒãçIìJ�(é�ÝvÐÃp/:vñéi•( Ò®å¤ WСq§à´ßà&{�Õ¼®Ô1¸ÈTÕò{sªmݨ•¹‚9)E^®²x¹Œo­HúˆÿµnŽÄ2¼®6pW@”XNàÏ9RATÅCºTl÷UÖÑãÚ03Wµ„'fq¯JCú/�|+‹G:3¦i/nH6hb?¬öÿ02ÝdLï8u–Óv!Ð� |%q­G£�“##iƒaýs¬!‹vãÉ4êêƒu-äÓ©°PªUT^›.ØešeûvB§Æb¿“0uêÁ–À„Îtß~¤µrÝi¢5œ°q}ë{µ6›´êÉg¹h Éå”™<Ùâ‘SvFÓ¸ŸŽàl£|Oóóè"ÚÙ$÷!»ú3¾ŒL3«…¾  ú&Ó�h*õ«¦âý¦a<±*! ÚàÚ°å߯E¬WJ¾K}Ú�Sèm[Rªã•ÊvX¤´ZaÐF¹(àm6®‡n¦Bjªªè,?dìo‘W7S¿=ÙM«¥’òêIá�Àí†ObsfΉ)íà…Žg‡CÕ”– vâÖÁŠðVÛ á#e¼•‰_܃mÙ�¨a©ÉÖã Ú|ˆ¿…Ñ+ýïòï#Ý@.$?v‡ƒêsï­¥M÷+QÂ[ÍI_Až�ûÓ‘n›í¢ÿÿáRü®Ìâûà?*½ !U/¢‰+¯0aÙ‡ˆ$K™¢#Ja¼ Î Ùø-ǬN…­ öj�œó¨AzÅkUc^ ³qÉðhL€¯ÔQÍä:kXHôãSƒ£ ³´kû Ô_%äs0F“ó¬G‚Êc&¦}ü)÷bæHŠ1 ‚.È{h# ÊiBï;Ü+ÅÍe¥Ð�}õšš:—nÖ9 I‹¯Bà.>{õù¿p»³nŽ >Ý/ÁšÖ©Ú1ñô³)ƒ¥ÆÕü1Ú ³õªƒ¥±² È}l4äRuøS4ÉÚ4 Ýp�Ⱦ²/k6kÁ;#Q}f‘¶Dîx2Ü„yE”o° ÷&õë$ ]Þ‡tù$òSU%Q^çׇQÌ @hŒüv½ùÅÖõo+×üeç¢ñmÿ q”�ûW±Ì,-L6‰Jz7pìeO¬fï̹míDzyËʸ —S;í>‹;à_òô ýê̦€Üiiը䷔^öm“v\… ¥bøò7«¼Æ=³º¬çä4Ø"GÙfwÅú@Ê÷÷ßÒ�åßUÖnȺXÁÍxš(­w×Í”µO¡¾Ü¬ÇHOy HeW?9†ùLìeö� ÷‰#ÿ¢hì–ýÉñNPµ H’l3‹Ô¿ÒÂ1ÎÖÿû' =.LÞþ´X{c½uŒVrâ÷V»™£Åú,j™t)áSŠâEp›ŒÁ1ŒÔÎtU¿èÅã7aQ²VŸL› n[·ÌÛÆD>t„ +ad©&¾.`ÆMÁ±šEµ+-àã­WŠ®¥8òC»&z7¹æiu ØkiÅm‡w{›§)â‚$Ìð«o£_†îºTï›#=¤n9Nõ÷ur÷°SÊ”÷Ìyíÿ/´½ôê×4«´dÝc"£Ï™eá³ì´cý.9ľ�öNŽé¥>îR±os«öåšÊÏN�³¢~^¢š[æZú)±^™±ÚÇfÑÀÀS³›TËü›¤�¢�åA›üãk”EXÂຼ.3‘a‹MRï‡)œ|Ûi±+ÜRÈá�¢õ–.eúÂpÖÆLž£› a|¼úˆÂÓ–¤–=7蜧V qF{GùüÕ£­iÌ®Ä]˜ÌE‹L]ƒÑí¨¾ºRÞt0[6ù|hH@ÞýÕzЏÐCð«dZ­0òjðÓ�¨O1³t�M^5Äq§}þÜžBù`NÒP:lžµ™´Ù%© nDD·Òî¶`3?x­ÂÊe:rôzân¥NüÕ5�¯w¸ðÉ_©œµ¡Nr߀̎þÍ�FÌ$M"Ön¸¬\=4›LR¦ÛZá@JDøz,õõO†¦ô÷[ÒÌ~>n½̶ْQʃ…x{h|XøÝ¢‚0¼Å™Œ?±ó!<ã[V:ÚÃ×g†™N.‹I’E\W­À’.í/"³Tw(Ô2­Eô)† ßQKò|¬­üž/¼Gåy¼0ûr”w(3EIÒxÜCÑ\”‘. 3q`”¤m�ßA™¡NƒÙMýã;‘Ð� kcìó 4Ém*TE¶áiÉÌJáÜÁQµÆ�jÀb;GÅBÞïûm–ïhæyáÀëþÌ–.è ²íJuÆâ’ò0Ìüà»ÄLiË×m˜›5«aœFÜ·eˆ›*%º�}*˜7|)N‡¯�૨… ‹rqå>,îY�a2Ã'Ì©­¬ÌVO+"ñ¿§¦ëŸs\”:ss”‹D"N ñû£úö¶f=öâ¾HþBàäÑÏ,¡) Íóæ¾\â–Í\´O>Ìô1×ö†Ø[æ&²WN-U©6¬níNÆO�e»çï�’I”þŠX6z¢� ˜ØJyÏrR8‚ühÄ]¿‡�`¯%~.ü‹Nä!јnEðD펻ÿŽCWÕ4Ÿ§›RY½Çø€‘”ïá|éŸ^éAé ß‡\–û� XÎþ‘‡½æäS5„9ÆØyPó�ËÝñ}‚}ßï¹<ˆo¤ëî00=#‡y]ºtS¤tÚ'âUDθ@ˆå£ Ij-míªE'ÚL²!¥Ïú½r«Ð$GI;}Ôpš…’ôÙ&\eA3¼`qlgX�'¿Ã¨ˆ»‰ëé …¢M¶<™Guû1´{­ñ ÍÆî±Ì5ëçÀ*{N³€,Ù0ñ׉iàn]un¢ùs�h榃è$„^zbœ‚\%_fèŒÙIøØê5­¥~>ÁíZ�^ZçÚ2þ hôßV;†’µÔ‘Ä™Zׯ P”î…Ë…ÛYºl F†Š3¡p†mŒS {Š ´z  ®?›q2ÏGé/c_ä¤ú.^¸ž7Õ=%w4U�5á>8ü•BŒPaÈ÷þŽ÷“®{?º§ÿ}—R}NP‡€Ê‘Úcµ4²ަˆ&Shú«{ÖÑžï†tò'ë%E’Z(À3A*ö�?,ÿùÑ®ŽÎˆe×ÅW4Ä ÎŒÃ_<Ï2]–¢o2¨fC1”^¿’í|2LSUFn°™J%{‹�ÐUƼd,wU¸ý¿…—étñ˜È, žŸ>(Õ÷(pÓyEæõ®ÏcR77c™¾®s9x·á2F;Œ‘D×zME5Šú8ç±GN…ÙÇ(4^? øpŒÑ˜‘ u A ó&ìIÕ>w[7þoŽ®ä½áå‘þ|Êäuêðs�°ì·îré*Žð s8;»Ž£p¬# üU…;GA0<‰8½ÉÒ‡Û%Ù­×k¹PsÛnR�|Áfà$K–Ý«YlF¸eŽÅ«µýï+�%ƒbª�ÒƒãSÉör$¾ˆÂ]Zîâ «�¦MCLذ²+§â$®�…\ÝBë»-Ë�í–À`vóJ4éK„ g܃I ÷ FþþµlQ!DY²Õ"Ôq�´È�l?ã¬Jµwyðš*Nx´¦ûå}ÜòÔ\ ¨AåuÝ8Ù׈Péè™ø�"¯Äÿ¹´[;V‰J|ŽÝa³gè:‚šó°³iA+†llMK‹"¢3DZz$DôEÍA¯…FE5Ñto�h»HŽÂŸÍ6¥&»òõvò£ö´L8{¨_ðñÒeès#O�u›L†Zœuécý“³,3ÍÒl%“®ß;ÄŽxrqÏ@Ñ‘Ì;eäæë6¶´WÀØÀ“¦TÀÍ€@v DŒ¥ú°ÒõbÇÓ Jqæ–dTaü­Á!Ðè$†Çí³¹K)‹X qAè^5¦ºÈ”ê:2DfVL¨�ÿ!\G-@qÊí†7Ë �m‘ÃèµSR‡°Do^¥¶>3 -…ÄæV|( R3¶j*ɉ&7jâÑ©WÎ3„> ¨�™´jf„Ü 4 SjKPÀªÆ@×gÆt\V,)·›âÖA -OüjC$d‹aÈ'?S6åû¸ú×4 ª ¼/ÜBàŒhÿÇö©os²o7@(Ôj–Àƒ¥ÈزaÕz›Qµ!óµè”"›”Á¤ïÈ9| §?ô ‡ÆÞ,EE Û¦,®VJÐÍvGec?s¥e–Qç?O HoZ�Zù^8ȇÂÍ„ç¶ø‘üû G¦¸fŒ³?Ýì.ƒ;]/.¡ÂO�ês ÎYë§ÝOêJÍLÌb¤Ær¡Ú�vÈ0á™FĤ߰œ;õÓW¥a"t…}kTC  ÅŠUu%æ_r;–åò�‰¥ {?ú_>H#ÏØ¹Å]O –JÔÁ*s,‰aD“N4-¿s¸ÞÇ^2A]¦,ÈS˰“ýJë%F=J™ú\fXNõBÊßÑ'ÉÙ/¯Zª<¸†ðˆ�U›ŽdL%’ðãð–õÿS0UêåoÄ twÏ “¯Dg6rŠ©;‚U…²â­‹üR2í‹XŽ�^�†°>>@‡ý5[ŽíMu„~ˆ%cÈé÷ws((*GCØYæ¢0ƒùbt¤¯(úÔ*ŸþMcCÏÜ@8ÁdW˜¶(tõÅ‹W–¶òðHk}|\bÞ×gB–6ËyÅ¿4hd`¶»n½®ôËš„#øÖ»¸‚b^ÐqA'51—ÌÇe½!â¸FÎÉÙ+ˆx´â©N¨ç¤)uù€5œ37x§UÉ‚aAJÙpå‡BH|¡•_ÃÏôúètWõ… ‘ëÄU›†Äˆ\›n TÁ!U|€ t[PîÁvåp§·Ã˜œìâ}üª(e?÷Oc—µÐïlœDÙÅ{¹vi£òŒ;éø×qfPä$ñwÔ¹ÖTy:ý?¯¡¡sôM�Å I²“õ�…fƒîãþJäWC’Œƒj1öb $eкF5]Zë8� È{ C”þ‰9Ðp¡T:ZA¡N.°;) þS•qÃÙRööGòTÑÍyÓÌ fžª�U´ ¦_-°Êxùª¯¸jnaš–ûPð¹ì‰ïÖ¹=¿ê�¥4y»¢¯¢¥©¾ß½´q7š›Õ{íÃ1©Èuªk•ø÷š”CP¨‡KÆo6‰ Ç»Â98ÿ†Oã™N\o¥z�ÎûvˆI ìZs¸ûÆŠ°²,/ÙZ~ðû�»žãQ¡pýõÜ>uÌܚͣs•üý«ìFRb°ÛÙ .ÀQæ Ýd¶bûÿ>Äa~0ÖÎø–=öOQ•°§[ƒË"œ »œ›¦ÒÜLàÚp_‡‡$ZŸÓ®ìÌF±ç<‘ÉÚ™…­=_Rj'{JuîP̵†›(9ÓrïžêæaZÀñÌ÷ñgu¾C¹›Å•Å+¡u }9ˆÜæ[)Ê›ªPj—�Aßýeïª1d•¯åÿ—ò…X^•´>ꮟù‚8{+BZR» �t ¨YÙE& ø Lzvýó:Súá–Á@ÉzÇ—~•ÁpRì‚q&ró´P€*�)„‚`�", �WJ�É:´Õ|ñ ˆ°;•Oðbf|4øŒ5E‹4FZs¤‘Ð¥MG|UA7IÒC‹‡œð ’ùQyùu×úÂ.Í…ÚL�@ýé‰R?ç½Ëå3=ŽÈ8‚Á›ü:|†F”˜4—Éh^í'Dƒ?“„mŠü^†“`…t€Sš® ô/·;²†£ø4§ #sÆ£±&Ôwma¯V_ ©Ÿ:p®©ï�ò ќߗH÷;Hhàƒêˆñɽ-Öv0Ó2÷ägLÐ Ê·ã:å>P/ЄæL´t±€_&ݰI4çÒ�¥ ü?øbµßF` ÐѾ úƒ"héÌûC¥gÕÓ¡ÅdR�”"ÄíÚNv¦Úà0ßKXÐ “G_ ÁA^àùð¹¾àw˜=ä‹ 3f­;m&ýÊÔe ̃óñ®Žÿ#®Ç/jDÿ»“æÎ¨�CJÇ*ú-“ïS K–‡~Ó9›µ—ÂÕ1³â‚›iY㬴·$1/ †ˆ)iiÏê—•Çäi|Ä¡0[ö£<ž¶{(fÀ¾“ñÛvˆ¢´‡˜ŽÉ/ò=O*ecaMþY‘Ží¨õÙ�Üì´i­ˆ Ã�A‰@ŠdÉJ…m€¦!ð÷Qͼ:uÕmRV�¤ÖÞlT1Lí´õb§…·þ 9ãZÿcxP¸ ÝNe7ƒ£–ÂY6a#‚Ä~5Bq”ó~[,ìÕÀ‘òwŒxyÀf.d´DEY˜à+6Rò›Ô&b“¯’i÷I¨‰ñfÇœ×á-úEÅÆðѯ› 4�ÕzΗV9g•‹ÕZé* z•À ×.SÃûWž©’åR–²|»*©.XÀé÷U£�)µþý²®E“L5@ó¬ºê�‹ºÎÿdä‡-Y³ #`1aàö÷ó �*¤}±�r²ê¤ß¨%Ž€˜ŠkÀéM¯^è~¯0† ò’:mÞ,ÅÃîZ¤ëø•ÀÐÈôÓf¦ñ�gá“ZÝ™óƾL<Ø=Šß#ž.çu"c6§†Ú,“óÙÜŸäÍ:ñž5àJC¸\nâ¥ñÜõ c†¦HˆWrg”¢mˆçãñ\sÇ£†«õ=Vp&ë]ªö�HKôJ”9P¿ÿÒ"@}ú#É" v¯ š‚‡ž�^ÜHàrËC^Þ«S… û’O-än!¶[ X¥ aùXF‰;V]#ŠŠO8ŽÕ± Ä=G÷ûV“±ˆrï&W8ž œk.§>5ÝéauMmö5º¯¬à??‹y8rc´ÚÍ|‡~é Ü}CoýŒÛõßz|ë5T[ö UX°£N64eû†¾qàDÐüɈþ6š®f+âˆø²"›õR¹ÍÉ�dßÎÑBùæZtò‘ä8ý×>�ª÷A00P¶ôé1`’@d«W"¦ýMk‡É¯J`M¨�ÊŸ˜œŸº$¡ †Ê*Šß†Jý™Ô*i WzÌLxÿRS·…®üý·ˆ$äGÿ(f¬GZóUÀ2Úÿ8â‹¡±?ϲOÃÖv±á‡�$¯�"“)‘¢™�DŒ”ˆ'c$7KCRbcÂEV{ïÿ8LêøÖ½¹ §_+ÙÉ##Nm”¾“‡G'“ôÞ=“ Ö‰Ìï¤w]„ÿM[7ZW©Q$…0.aÃrÿ1ÍÑDZ~oŽDyóøq|I“öü䂽­ØÜ(®m^m”€¥‘…¨8ì‹D À¡`Ãyläu³ª•BŠaèv+pd…]¤�Q® LtÕVîcsºo›~ði$u4ÙòïÏ¢ÐØFq©˜ñCÌUÉ=ÃË´l=ºÙiêTl«œ9 ÍUܸå]øùY›Çˆ�Aïǃ 5/ 1>h[ÿðVç� R7zQn SйÄô‰¨dEÉy¤±9'³‰6ùeûöú[Ø'Ý*ÍyD^ï…h.½¨± µ*Mn†oA¯KP¢ê)˜Ë¹Ë ¨Ï�“Ì”7©"Ç×b aWè‹7¢ƒ_¬´X}²¼²@‹Ìa í"جbŒ:ö,=aP%ïÊoQïô~_}€ßšeÂ|g³°Å�¾z¿)û¥»xÓAü¨\[½1€[,£Éƒl¨¦%rV�=�pÕhõ¡äæS[™nYçâk+BõÓfñb?ª Y÷ØÃëtCÇÑ\Ø1wKn¿T'D¡Èü%�˜iÊ!ÞËΰD²P*ª}þ;c K×x:ð™,ªYTÆÿ,,Û§…´âÊ ÎÂ^g÷Ü4l_‡áŒ±¼ê�:e�úiíŠéÝÆÛØk M™¯óšÂo#t‘K®‰�DóÞ®®ƒŽå¼QzÄŠ…ÕÂB]‚Dy‘ÇXî‹ZrØÝ)½�A¹‚ J)jŽâ'¼òl4F´F×göù˜Íûý`AßYáC¸¡ A9´î"Àh­ä¯¸³-BÈå”!{x˜Th¯0êcÌt Ú–Ãt} c öïYŸ@mqk±œsIþ¨[ç~Õÿæxp¥DõH€ “9ãðèc« RpOÂíJÓ¥N£­óýAêh&Ýh´�2�Y”-U7$b ö­ú_&5ï…É8lGîFÞµÛ„d縤xÀé§,98ÒÐwtdôìbù�„©ÿ3Òå›3Q doºç¿éfÕÐûŒ8{Qò,(ënŸÿµV¢©Ã/�Ò�MÃÑýé]]xÀ^ÓˆÏIxÜ›»’çIÍ}ê™®å��åwì°¯üÚN€[j>|dš ›nHÐKôÏRЦV/¤üõ�¢6üüYe´aYHŠTÅ©­ÅuŽ‚•[E’‚�¢ É1‰°f޵PY.Á%ƒ5ÿ˜í>i-ŒŠ#‘QBý’ÿ°Z¥S ‹Ú/æZ7,<¾~Ö9À<Á…FS�Ú™Çåà,6${Ç‘ë8ããN°§©B Éb®Á,Œ,“N²0?@—�;ÔÞŽfóQKfp�€Ë}ÊAòì ©$lw4"-Aû›,gß"q}�;fm1¯ÈJj€³Â8¸±UTûS´@g*,² ’±!ï2-þ9I[X T³V8îÒ8 „IeN¼›¦ÂW㮀wÙ‹^µÞ¤©Œô>q—Ðä!7ä´>Ðd‘"éSPçÿÄÒ¸V#˜ü%õ<ÃN©x©™aªÇnɈ¨ ¸Œ#ñ¾ÊÊeqðqB”}b•踶•¯‚sÞÙv½K%ÒöÔC˜ZÚìööšïb`íéN7�e\ †@H?ùº1‰ð¥"åêÞÑÉžd ÏJU2·Ž  ràWD&Rq×�òÿòZTÚ(¸CbÞ,ò1 •›Óø÷ÂÚBº[j6ø;ì½G‘Ñ×Vy€µŒ}Qqsà¹|�lMÉ×ÚÊìrÝàÐË% Rð”(h¼Õþü™lc©qÇJ°yiÒÔñ›YÝ'í?M-Ñ]µt›`ØÛ�rã c¯ “7Tè›D¹ƒ•Wý'³ÆFd¯YJ�ñ-ie®bùàó8ÐÌôä¬KŒgEt¹IÌù€2ÞÚIgã`#(­W6 ƒoZ:0¥„ùKEn.x4â5M� ¶DQäªû›;~yzEkfIö&DØKÑ¢SÍô÷Ä4–IT·$€*ؼ’­'}b(²µ`•¶CËÀ¥"�'¯2«íüDÊÁ¡á ˆÕ«(XÂ!7­·_W`íéY³Æº¨h†]%ÐÐG™…Ù³a¹ÛçÿûyñfÈí`�S³(�ßc ÇÐ ~g7£–|8bgë…O°ŒuY7ÏçêæÃ1A©¦®SE BŸ×óo8{†ËþRlÁ}³™÷÷Ì(¨H¾79;ÿÜê¿B2{q>3l"2×!ÎŒ £çÛ •KPbSfDÔþ9Fb¢y…r~ �Úšà)( 4÷Í¡Hάé_³=Sˆõ‹Ä3MiµrV)]p›·Ôð_b4"¾ƒðJ�\‡bJSqtCJwÑcqnL7³•�á¹¼ƒðý!]\œ3¤¥¶Ìx—íõ�q uÏ\™%,ç¾åé=½Ìæ«ûwPŸ3*ø|QíXŽBÚ2±V![éáµÀ£ñŠ‚,™æÌI·Š¾‹K¨fÑ={T™XÉ=U9à2¶ûØùxœd¢>¹üæ’ÄñÐ ^þµNaêsC„û�Õw4VÉ{Á÷ü2ë)fJ-JÍxa1gñÆESÙéx×.7§<å²¼ØZÌh]»Äì+ªÜèÈ67ñéÁ�[m¤|ØPFÚõÃÍÒÊʰ¼K3ñ‘Ð7vÔ­.„µÙ˜}c¦.€d\]‚9‚à"1´‰gæ!ˆƒ¼õ•öN;t;%mØAÐøPŽ 0;õp6ÚÝ•kZÎ>]tqí�x¶ èa�•r£ÃRøiDù°¡ ptÊxÖ Ÿól°¿EÆg–m,S™¹êÉJ—´€¸Rœº�qâ3:Ó–�§UÝJÀ¦&Ìéf-Äc .’aM®ýq¾jˆÉ…pßì8©]¬Ñ¼ö�¶—2êï¸}´kÃr¨”j;¥Ù6gsøoazˆ«‰/»y”œ`*Ž¥_¢R÷Ô©‘„ÙC1Ê4eN?÷ R‡MM­ ÕA³olÁz¬vS�¥ù;Ên‚ÄDì»HÆG0‚ïx|?]íJÀ jÜL5Èàp‹«¬j+Ò¤ü¤Öˆâeüö�à üƒì•ЀA”Zç½Ìq:b7=¼‚`øQÛîàV*…,FkM^QÀÝ¢oG§¬B§h9ëkåÎÂOK¯zèXEæÕ£!Ðw*è˜T¬¿m–F.Òù´ý$‡“æ‹g%3”/è ¯2›°©Õ\˜XøÝÂÒV‹…*ž¶NXTómX™ì×ìš1Šâ ª±o#‹6×7dœf®ãl}vInx 9­(g¢¤[3iMMàD1ÐÉÝ�€kö~Ú[&Rïž&S ƒ%]™o�©N,ÅçLi°|ë´‚ü[ïþâ×:§§¹«~‚ú°ý0eҗÕÏÈgåíÏö±Ù&‚ËK:\nÏúÏi�MJb·dZ;xy‚  ì3+œñ Èå@.j¬»“Ó»Ÿ¥çÁÛ/Ø€Ó²¿)ŠÀß@!à÷�ùqñßv N|LhÝfdNôˆóé¹pGç tíé@xn_\Å$K8MB+Õóý²¼Ûï)3·Âàí²¹?,kŽ�V€†“P œ�µ^*%^ü³Iúkå¦NŸÃ"¨æÑ0ßp·nxW"‡äb¾ ϸ¯~$sMMV�vÜÿ_ÈiS ÕÿãiòöÛšžu²oÏk^ËñŠ£ní­·|Api~:ÁÁi�Õn2EF—ˬ‡xVÒ½÷0W]�™�yˆ¹ª“½–(�2—_æƉ÷`‡Pƒþ%'_3Ýo\¯°‚1ƒ^H>,¤/¡»…ö&¢Eþ@5¶ÿ.kâðÕÓ]ÙE7Là eÂ.zÊo»®,g¦“@9õ·\pÔj`–G: p°ž‘¯OyÊØ2­Î:MÓØ{’ÜÄGçE4ä�žM•B´Wåb³²Mõ_Ní–=ta+ o®ÔR®éZ®šØà¸cÞz©Qñôº*ÓÝ‚UѲ?×guZ»q�ŒçqU)Øg?1"N/ÂÍ7Ù!û¸\©bŠ×•ù‘-å¨ Ç.ñ´_ ¹[voß~‹¢]Êâ=S쎈Û7;¥§:ð2ê_|bÖ[54_!ƒo²*ý ¼mÃÙðó³ÛÜùŸÈiÖò޶#Cly0Lú“»Vä÷¬šq:¸QDÉ\sut¢BÒŽ´Úa¨W¥äOF\À]ý³=ÆçXan$G`âzé:¬\éOòóš@ø»Á¥Èå8r¸ äÿkçwbج²¸È*¦ 5©…¿y“sRB5§]Dž~wÛSIåj°Ý– y3w*Fa¦ÇÕ�BÁ)ø-tÃ,ŸÝ�qßíKõÑn(ܨpq¥+h�CÁý’›¡áþáÚ”&CÞlIvz£ÚNŠÅbPóHný¾µ$E@¨+ßSíO^7m &Èø‘n1¾o›å3eëö›|¾O– \|XLSE8Ó£-Î\+A©àsã^=ÅÏÕÕ˸QU­Eü©0”rÖ[i%—™ñ¦þ¦ÁýSÑÊ;X˜ ÆËøFîœe×°ê * 2Àñô I1¾È6…‹F ðéë{9•õdŸÙìý—G ðèÏŽtÒõ5õé�ÕE@¶–ƒ£ž JÐ÷Ö©D¬¦¦ #`Ö³ÂØåV/ñ­ô’e/UÒùw ôÈîŒ(íÛ¯` ˜ úAžd”D\'ÿ^=îÝ¢&LËu¦N›!ÀI¢©i`5PˆD"#!”Ï‚¦eû•¡ùŸÞ”\¸á`b�#PBž&D?/Þ˜ � ×\6sZI[8gþ/ŒhŸËóYº  ö�ØÐp×�lZçý¸öüFÂ÷ŽR³Àô�±bt׋\<2µ³£_¢)H8…kjû;*‡ÒàLM»ona6Œék ˜à£ø2¿3@�S½'éëÊ£;*ìl†¥À€iT—ÿ�€X¼Oô}®’Ø­YÃýt=ª8 ”>Ȱecm"´£ Äâk£ƒüK‡GÙi�o�Ù”rÄŒ©'ÉÞ•Yé]€iM“6“È¿¨§�L#¤"ZÒ_4L2�ò¨@¦P¿¤¸:MÝÔ¤^àÓÕ=Hì»LÌ{}­Ø6¿YÏ5ý UÙÄú¤®o,yƒd¦-„`kk2(þ Ëp¬@ºÖEÝÄ×xób{Ìæ­žöwî tákÅ÷&ýþ9-TýÞeS`A2ó"æ­›©¨jܧüEDÙÆ÷›4)öb÷ªLWôãF®Z+W]/- †„&#õ�À•ë”ê丄(gÌÐ]ß@“¶÷·ÙKtõyáý{b&È1—o~ Aµqé¥ÇÆUå±&\³•Ê “ÍÜ~ÄÐ 6ÐYBü—DËŸ¼€öël¬ØÂÙ øÞËI�\š\Ø!‘_ˆòÓµ ²> öþµ6r2øM„ ¾<%¬S‚D*ÿ§†Kbî-÷>~þZÒÀÚû½sS…þ¶Ó’;ž¿­°8h6úÁÇá¨JfyóAÝÚ1ûu8¬ �@‘O£ÖEçŽþ´ë6±kê3«ë¾�&¨RÔ”ÒlîÉQ“¾k—Käy¡UžisZ.óy–¼Ø:Ì+JKÒËÍKr¦Ee.ÜjQƒÿÞ ¬aÚ=G>íui‡Tw)Ãã©�5:‡†‘MìðѶ"ŒÎV‰Ý �ê¶°6Þºy NôYjK�1\ð½½9NöO+Í„íÔŽ~’áÒf_·|W¦‚XžÜ,0+¬:ñô$‚•ký�(#{C8'„/äFú!”¹Ï Kª(û-„é!KwxÏ%÷¢œšßrBÞ¨Ô0b÷pÙ6ü³’"Kà™�¹.“tS8¨ô›.Gð=ä@y]̃ P±xTxq·°ãåò¿Ä9eE0]Eê¿(ûö›@‰¨“‚\Ï­ªê±r´ó¾'uËšOˆRÛërõCvÿÒ¤žìðÜ»»Q²Nr‚"ñÃ÷Èp'ÞM¼�¾5g�¸•ÄsÁ eÕ}uµf ^”÷œÅ±lEjóêQˆ}-×_L­óœm(vGQò«ƒp5»dʼ èóñ€5¨L´„ÈftùŽÝÈ;xbÊý’)5÷V�¹HV‹¡-Il‚|Cñg4OQšÝª`wP@š[ ˜õŠ{35gœÆ¼�%£ÈŸ’iâë/‡ß™íåîKÊ �†jñ@Ô–wV`×`_s̯‚ ùÛÍ•”Öˆ„òæOmûœ0n‰Ý©×)†ìëÞ¹0Ò7l¨¸”(¼îâýÊr=ŠOÌ}¹ŒTVû @y{Í>iEÞQtÔøq ZÑ K­¼V’%”ïÓ Bêd bÜ#Ÿ— ¯ª¤è6ít?Õø×ª”Ä ;[Xt>÷\ð€Œ@y²ÀŠËš\–œ÷#Û&Ôt"‡…h~‘Èdô¦‘pÖ œ×2�&Gÿr'íÜ\ƒ»æ‚>"*,VºT­‚ÏÜœŽÎW»¶®>Â] ]ìpŒ¡ì Íç,8©3�ç¹Pûõ*”F‚p-÷sÕ=3W25­¸ð©`|òÀ,ëd.l F–°þ0Ñ@T£‡Å\Ú\Y �iô´Ý7¹º;ÅKÁ“e³[H63îÑ犵¼½1ToÏ…CswþôÀ)‘ZiG®®FµJymé¬ê5èêÏÿL‘÷„šóÔØõ{ ¼2�j]”@ÚI~í�ü G‚ë¬b¥i/g,ÇJÎ@Ñ.Í €”æš[λ ßUØ ®Iw™ä¾:`{[d±àíH‚ÔHªV¸×“a�EÑ1áP)»Ù£€ƒô'5¢;!(äÔx‘µnhÌ$S�Py�Ù&ù3ŒK64o‹ >‰4“îƒô\™™ã¤‚šïb^¸ð;¹ Ÿ­±«už»ÉMìlþÝæpgÅ$fK7ŒÀ4yj�9àÞfþnz‹¼K…MΩ5òRõD€�,¤73¬Ž #ʤQjŹºKN;å]MBµMyžæ <~Ü0Ïù¸Ø[àIø2P‰Žd‘ãSYÞ·FAè¥~Œ¦x!Ïè‹-�iDò=—µ6Ð>åžì‚þn\hDÌAo~Õ@�ˆN€a Û¤BIìÙ�ýΈ6Æ4úÖ˜(ëJdJ5»0(j7ÒÑ…mZàxwÙHî¤Ï@²/¸c¶Â«˜&oº‡UíHb²ºz‚æúz¼$éÍóL¤÷ŠGë�—PQ§~@�B-'Ú]Ærðhó Q;`ÍGÀ_—C9N…kF¬Ïô„S9l>’®ŸOw_Ãöݤ×î9[a‡o�7z/‡í0¶¡¢ÐÆ¢2‡åPf"‚Ôÿ€ð¹îöÖ˜ +$IŽë×Ñóy‚› èßU;ÝÀ Ó_ÇÂ4‰’ëd9mtïs»nßþv¨%â.ª^®`]‹§†ŠiUdK›1ýŽövç�K¢oo¦*íD ¦#§eù ]¤ú†Ò‚ãÖ{ÒÑt›1 ÊQÀiø òc(ŸÑ¤/À<ƒ¹LÛä¹—¸Ä8ñ-µŸhPJ€2Àé�vž;nGÿ‡cèÒ'¼x„nŠYõ=�Ñ@~ûz·JÆ~'`A{š’~õÎßvÑY¨vz]ÈMQ'¤�@Ëë%4›/ÜŸˆØÖs‹ï(«à¡3‹IuwšÀˆºª÷ÛŽª4:ø#8$& ’áÜ,„ØüWá»7!Iºï³þ(ÅcÿPö|DµÕ/?#ú-…‰,Xê¿�?•sƒ¬ø Ǭ �Z<í„Ö¬ÔH#FÐo/µÃ_8ä–£UØŒœܱÁ«!˜LÊc'‘øCu'¾ô~˜i.²@´k˜:5;ÄÆÀ@Å® °„ ùt=| ÒѹóT9õY� ì ¤ÚnAMq›«Ò¤÷Ÿ�”t“’8…acln 4L÷˜2J0NV ¶ÊshŸÿ0¸ÄO«m¥ÃMò5Ðã2Éz¹ËŸ·Wó¿ÝkšçÀÆÕÁ'é›-‹èx\â�¼®×<×½…ç\EãO_i‹Q-Vn”;ì¸aUæ!ЛŽüíL¶¥Ús³¦3‡œ·F€àB‹�̵:3IŸÐO¡%^©w2¤ b§)Y:I^ž@íÄøuf,êfÁ&:g Ê9ňE /oÀ½ý¬…dÜ`c­ÔÖ�´ _çxš2õÚ„c4+8ù@J�)Ô{_;T*€’D I�žîòOIÞ ÔzsS½ÿ�€ä¼Aëï±¢W_ð‡PZ”ݱR9&°mš¦dè[µüÌFi7ôÒðæL ï“÷‰]éãªuq ȶIxÈ3ŽÎýÓÙ Óq"ß@ñ«WhQ+aœ0¾ÀË`d"\ÞË™?D8ªUvø�LAš=5-dÊ`ÿ :o‹¯�¶jpÊ[èe–ÄM™x”ð}ÖMõœNt¿΀–ÿ|¸�,’«#K”Vs¶DÛ%z Q!€5 heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/000077500000000000000000000000001526573132500230705ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/000077500000000000000000000000001526573132500272615ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/LICENSE000066400000000000000000000025001526573132500302630ustar00rootroot00000000000000License for quark-sphinx-theme ============================== Unless otherwise noted: Copyright (c) 2016-2020 Felix Krull Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/PKG-INFO000066400000000000000000000003311526573132500303530ustar00rootroot00000000000000Metadata-Version: 1.1 Name: quark-sphinx-theme Version: 0.6.0 Summary: A Sphinx theme designed for QTextBrowser Home-page: https://gitlab.com/fkrull/quark-sphinx-theme Author: Felix Krull Author-email: f_krull@gmx.de heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/README.md000066400000000000000000000111371526573132500305430ustar00rootroot00000000000000# Quark: a Sphinx theme for QTextBrowser Quark is a Sphinx theme specifically designed to look and work well within the limitations of the Qt toolkit's [QTextBrowser](https://doc.qt.io/qt-5/qtextbrowser.html). This theme was originally designed for the bundled manual of [SpeedCrunch](http://speedcrunch.org). ## Installation * Install the theme: ```bash $ pip install quark-sphinx-theme ``` * Enable it in your `conf.py` ```python html_theme = 'quark' # generate QTextBrowser-compatible HTML4 instead of something newer html4_writer = True ``` * Optional: enable improved design for some elements by rewriting HTML: ```python # To enable more QTextBrowser-compatible HTML generation: extensions = ['quark_sphinx_theme.ext.html_rewrite'] ``` ## Releasing * set package version in `quark_sphinx_theme/__init__.py` * update changelog * tag release commit with `v`, e.g. `v0.6.0` ## Changelog * quark-sphinx-theme 0.6.0 *(2020-04-15)* - Bump minimum required Python version to 3.5. - Bump minimum required Sphinx version to 1.8. - Fix `html_rewrite` extension to properly load on other HTML-based builders (e.g. the `qthelp` builder). - Change the way the `html_rewrite` extension modifies the HTML builder to be less invasive. - Add a `sphinx.html_themes` entry point to allow loading the theme automatically, without setting `html_theme_path`. - Miscellaneous tooling changes: - The build system was changed from setuptools (setup.py) to flit. - The CI pipeline was expanded to catch more issues. * quark-sphinx-theme 0.5.1 *(2018-04-30)* - Sphinx 1.7 compatibility: - An internal refactoring broke the integration tests. This has been fixed. - Every commit is now tested on every supported Python and Sphinx version using Gitlab CI. - The entire test suite is regularly re-run with the latest Sphinx version to more consistently discover compatibility issues. * quark-sphinx-theme 0.5.0 *(2017-06-05)* - Sphinx 1.6 compatibility: - A change in Sphinx's HTML code broke the HTML rewriting extensions (see issue #1). - A change in the `css_files` variable in the basic theme's template broke the `extra_css_files` theme setting. * quark-sphinx-theme 0.4.1 *(2016-11-22)* - Fix `python_requires` in setup.py. * quark-sphinx-theme 0.4 *(2016-10-18)* - Add an explicit dependency on Sphinx. - Rename `quark_html_rewrite_features` to `quark_html_features`. - Add `quark_html_disabled_features` to explicitly turn off certain rewrite features. - Style changes: - More visually appealing code blocks on full browsers. - Add styling for compact lists produced by `::hlist` directive. - Correctly set width for topic blocks. - Clean up definition list margins. * quark-sphinx-theme 0.3.2 "I'll get it right some day" *(2016-05-23)* - Include a copy of the lovelace style for compatibility with Pygments < 2.1. * quark-sphinx-theme 0.3.1 *(2016-05-23)* - Skip CSS syntax tests if tinycss isn't available. - Make sure to include theme itself. - Include test/util.py in source packages. * quark-sphinx-theme 0.3 *(2016-05-22)* - Remove `hide_sidebar_in_index` option. - Fix styling of index pages. - The `quark_sphinx_theme.ext.html_compat` extension has been renamed to `quark_sphinx_theme.ext.html_rewrite`. The old name remains supported for backwards compatibility. - The `html_rewrite` extension now supports wrapping admonitions in tables, allowing for more styling options. The theme has been updated to take advantage of this. Admonitions, topics, and sidebars look very different and much better. If `html_rewrite` is not enabled, a fallback style will be used for these. - `html_rewrite` supports wrapping literal blocks in tables. If enabled, this provides better styling for Pygments styles with non-white backgrounds. - Smaller design changes: - Don't use background color on code elements in headings and normal links. - Display terms in definition lists in bold. - Remove left and top margins for definition list bodies. - Switch default code color scheme to 'lovelace'. * quark-sphinx-theme 0.2.1 *(2016-03-02)* - Change license to 2-clause BSD (in practice, it's the same thing). * quark-sphinx-theme 0.2.0 *(2016-02-28)* - Add `quark_sphinx_theme.ext.html_compat` extension. - Add styling for citations, footnotes, table captions, and `rubric` directives. * quark-sphinx-theme 0.1.2 *(2016-02-27)* - Fix compatibility with Jinja2 2.3. * quark-sphinx-theme 0.1.1 *(2016-02-24)* - Fix spacing of navigation links. * quark-sphinx-theme 0.1.0 *(2016-02-24)* - Initial release. heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/pyproject.toml000066400000000000000000000017421526573132500322010ustar00rootroot00000000000000[build-system] requires = ["flit_core >=2,<4"] build-backend = "flit_core.buildapi" [tool.flit.metadata] module = "quark_sphinx_theme" dist-name = "quark-sphinx-theme" author = "Felix Krull" author-email = "f_krull@gmx.de" home-page = "https://gitlab.com/fkrull/quark-sphinx-theme" description-file = "README.md" classifiers = [ "Development Status :: 4 - Beta", "Framework :: Sphinx :: Theme", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Topic :: Documentation :: Sphinx", "Topic :: Software Development :: Documentation", ] requires-python = ">= 3.5" requires = [ "sphinx >= 1.8", ] [tool.flit.metadata.requires-extra] test = [ "html5lib", "tinycss" ] [tool.flit.entrypoints."sphinx.html_themes"] quark = "quark_sphinx_theme" [tool.flit.sdist] exclude = [ ".gitignore", ".gitlab-ci.yml", ".ci", "doc", "tools" ] heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/000077500000000000000000000000001526573132500331575ustar00rootroot00000000000000__init__.py000066400000000000000000000006041526573132500352110ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme"""A Sphinx theme designed for QTextBrowser""" import os __version_info__ = (0, 6, 0) __version__ = '.'.join(map(str, __version_info__)) def get_path(): """Get theme path.""" return os.path.dirname(os.path.abspath(__file__)) def setup(app): app.add_html_theme('quark', os.path.join(get_path(), 'quark')) __all__ = ["__version__", "__version_info__", "get_path", "setup"] _lovelace.py000066400000000000000000000065241526573132500354120ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme# Note: This file was copied from pygments into quark-sphinx-theme. The original # copyright and license apply, as below. Since quark-sphinx-theme and pygments # are released under the same license, the reference to the LICENSE file still # applies. """ pygments.styles.lovelace ~~~~~~~~~~~~~~~~~~~~~~~~ Lovelace by Miikka Salminen Pygments style by Miikka Salminen (https://github.com/miikkas) A desaturated, somewhat subdued style created for the Lovelace interactive learning environment. :copyright: Copyright 2006-2015 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ from pygments.style import Style from pygments.token import Keyword, Name, Comment, String, Error, \ Number, Operator, Punctuation, Generic, Whitespace class LovelaceStyle(Style): """ The style used in Lovelace interactive learning environment. Tries to avoid the "angry fruit salad" effect with desaturated and dim colours. """ _KW_BLUE = '#2838b0' _NAME_GREEN = '#388038' _DOC_ORANGE = '#b85820' _OW_PURPLE = '#a848a8' _FUN_BROWN = '#785840' _STR_RED = '#b83838' _CLS_CYAN = '#287088' _ESCAPE_LIME = '#709030' _LABEL_CYAN = '#289870' _EXCEPT_YELLOW = '#908828' default_style = '#222222' styles = { Whitespace: '#a89028', Comment: 'italic #888888', Comment.Hashbang: _CLS_CYAN, Comment.Multiline: '#888888', Comment.Preproc: 'noitalic '+_LABEL_CYAN, Keyword: _KW_BLUE, Keyword.Constant: 'italic #444444', Keyword.Declaration: 'italic', Keyword.Type: 'italic', Operator: '#666666', Operator.Word: _OW_PURPLE, Punctuation: '#888888', Name.Attribute: _NAME_GREEN, Name.Builtin: _NAME_GREEN, Name.Builtin.Pseudo: 'italic', Name.Class: _CLS_CYAN, Name.Constant: _DOC_ORANGE, Name.Decorator: _CLS_CYAN, Name.Entity: _ESCAPE_LIME, Name.Exception: _EXCEPT_YELLOW, Name.Function: _FUN_BROWN, Name.Function.Magic: _DOC_ORANGE, Name.Label: _LABEL_CYAN, Name.Namespace: _LABEL_CYAN, Name.Tag: _KW_BLUE, Name.Variable: '#b04040', Name.Variable.Global: _EXCEPT_YELLOW, Name.Variable.Magic: _DOC_ORANGE, String: _STR_RED, String.Affix: '#444444', String.Char: _OW_PURPLE, String.Delimiter: _DOC_ORANGE, String.Doc: 'italic '+_DOC_ORANGE, String.Escape: _ESCAPE_LIME, String.Interpol: 'underline', String.Other: _OW_PURPLE, String.Regex: _OW_PURPLE, Number: '#444444', Generic.Deleted: '#c02828', Generic.Emph: 'italic', Generic.Error: '#c02828', Generic.Heading: '#666666', Generic.Subheading: '#444444', Generic.Inserted: _NAME_GREEN, Generic.Output: '#666666', Generic.Prompt: '#444444', Generic.Strong: 'bold', Generic.Traceback: _KW_BLUE, Error: 'bg:'+_OW_PURPLE, } ext/000077500000000000000000000000001526573132500337005ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme__init__.py000066400000000000000000000000001526573132500357770ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/exthtml_compat.py000066400000000000000000000000651526573132500365620ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/extfrom .html_rewrite import setup __all__ = ['setup'] html_rewrite/000077500000000000000000000000001526573132500364055ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/ext__init__.py000066400000000000000000000024061526573132500405200ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/ext/html_rewritefrom sphinx.builders.html import StandaloneHTMLBuilder from ... import __version__ from . import boxes, literal_blocks, compat # List so it has a stable order. Descending order of precedence. FEATURE_OVERRIDES = [ ('boxes', boxes.OVERRIDES), ('literal_blocks', literal_blocks.OVERRIDES), ('compat', compat.OVERRIDES), ] ALL_FEATURES = [f[0] for f in FEATURE_OVERRIDES] DEFAULT_FEATURES = ALL_FEATURES def get_overrides(enabled_features, disabled_features): features = [] for feature, overrides in FEATURE_OVERRIDES: if feature in enabled_features and feature not in disabled_features: features.extend(overrides) return features def setup_html_visitors(app): overrides = get_overrides( enabled_features=app.config.quark_html_features, disabled_features=app.config.quark_html_disabled_features, ) for cls, htmlvisitor in overrides: app.add_node(cls, override=True, **{app.builder.name: htmlvisitor}) def setup(app): app.add_config_value('quark_html_features', DEFAULT_FEATURES, 'html') app.add_config_value('quark_html_disabled_features', [], 'html') app.connect('builder-inited', setup_html_visitors) return { 'version': __version__, 'parallel_read_safe': True, } boxes.py000066400000000000000000000030131526573132500400740ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/ext/html_rewritefrom docutils.nodes import admonition, topic, sidebar class BoxesMixin(object): __name_tag__ = 'Boxes' def __init__(self, *args, **kwargs): pass def visit_admonition(self, node, name=''): self.body.append('' '' '
    ' % ('-x-quark-%s' % name if name else '')) type(self).visit_admonition(self, node, name) def depart_admonition(self, node=None): type(self).depart_admonition(self, node) self.body.append("
    ") def visit_topic(self, node): self.body.append('' '' '
    ') type(self).visit_topic(self, node) def depart_topic(self, node): type(self).depart_topic(self, node) self.body.append('
    ') def visit_sidebar(self, node): self.body.append('' '' '
    ') type(self).visit_sidebar(self, node) def depart_sidebar(self, node): type(self).depart_sidebar(self, node) self.body.append('
    ') OVERRIDES = [ (admonition, (visit_admonition, depart_admonition)), (topic, (visit_topic, depart_topic)), (sidebar, (visit_sidebar, depart_sidebar)), ] compat.py000066400000000000000000000016001526573132500402370ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/ext/html_rewritefrom docutils.nodes import citation, footnote def visit_citation(self, node): no_id_node = node.copy() no_id_node.delattr('ids') self.body.append('
    ' % node.get('ids')[0]) type(self).visit_citation(self, no_id_node) def depart_citation(self, node): type(self).depart_citation(self, node) self.body.append('
    ') def visit_footnote(self, node): no_id_node = node.copy() no_id_node.delattr('ids') self.body.append('
    ' % node.get('ids')[0]) type(self).visit_footnote(self, no_id_node) def depart_footnote(self, node): type(self).depart_footnote(self, node) self.body.append('
    ') OVERRIDES = [ (citation, (visit_citation, depart_citation)), (footnote, (visit_footnote, depart_footnote)), ] literal_blocks.py000066400000000000000000000012341526573132500417500ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/ext/html_rewritefrom docutils.nodes import literal_block, SkipNode def append_epilog(body): body.append('') def visit_literal_block(self, node): self.body.append('' '' ' {# hierarchical navigation -#} {# right-hand misc links; prev, next, indices -#} {% endmacro %} {% macro sidebar_table() %} {%- if render_sidebar -%}
    ') try: type(self).visit_literal_block(self, node) except SkipNode: append_epilog(self.body) raise def depart_literal_block(self, node): type(self).depart_literal_block(self, node) append_epilog(self.body) OVERRIDES = [ (literal_block, (visit_literal_block, depart_literal_block)), ] quark/000077500000000000000000000000001526573132500342235ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_themedomainindex.html000066400000000000000000000033761526573132500374210ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/quark{# This file is part of quark-sphinx-theme. Based on code from the Sphinx project (http://sphinx-doc.org). Copyright 2007-2016 by the Sphinx team. Originally released under the terms of the BSD license. #} {% extends 'basic/domainindex.html' %} {% block body %} {%- set groupid = idgen() %}

    {{ indextitle }}

    {%- for (letter, entries) in content %} {{ letter }} {%- if not loop.last %} | {% endif %} {%- endfor %}
    {%- for letter, entries in content %} elements so we move the id. -#} {{ letter }} {%- for (name, grouptype, page, anchor, extra, qualifier, description) in entries %} {%- endfor %} {%- endfor %}
     
    {#- QTextBrowser can't jump to
    {% if grouptype == 1 -%} {%- endif %} {% if grouptype == 2 %}   {% endif %} {% if page %}{% endif -%} {{ name|e }} {%- if page %}{% endif %} {%- if extra %} ({{ extra|e }}){% endif -%} {% if qualifier %}{{ qualifier|e }}:{% endif %} {{ description|e }}
    {% endblock %} genindex-single.html000066400000000000000000000017171526573132500401770ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/quark{# This file is part of quark-sphinx-theme. Based on code from the Sphinx project (http://sphinx-doc.org). Copyright 2007-2016 by the Sphinx team. Originally released under the terms of the BSD license. #} {% extends 'basic/genindex-single.html' %} {% block body %}

    {% trans key=key %}Index – {{ key }}{% endtrans %}

    {#- Also set width as table and td attributes for QTextBrowser. -#} {%- for column in entries|slice(2) if column %} {%- endfor %}
    {%- for entryname, entry in column %} {{ indexentries(entryname, entry[0]) }} {%- if entry[1] %}
    {%- for subentryname, subentrylinks in entry[1] %} {{ indexentries(subentryname, subentrylinks) }} {%- endfor %}
    {%- endif -%} {%- endfor %}
    {% endblock %} genindex.html000066400000000000000000000023021526573132500367070ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/quark{# This file is part of quark-sphinx-theme. Based on code from the Sphinx project (http://sphinx-doc.org). Copyright 2007-2016 by the Sphinx team. Originally released under the terms of the BSD license. #} {% extends 'basic/genindex.html' %} {% block body %}

    {{ _('Index') }}

    {% for key, dummy in genindexentries -%} {{ key }} {% if not loop.last %}| {% endif %} {%- endfor %}
    {%- for key, entries in genindexentries %}

    {{ key }}

    {#- Also set width as table and td attributes for QTextBrowser. -#} {%- for column in entries|slice(2) if column %} {%- endfor %}
    {%- for entryname, entry in column %} {{ indexentries(entryname, entry[0]) }} {%- if entry[1] %}
    {%- for subentryname, subentrylinks in entry[1] %} {{ indexentries(subentryname, subentrylinks) }} {%- endfor %}
    {%- endif -%} {%- endfor %}
    {% endfor %} {% endblock %} layout.html000066400000000000000000000034761526573132500364400ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/quark{% extends 'basic/layout.html' %} {% macro navbar() %}
    {{ shorttitle | e }} {%- if parents %}{{ reldelim1 }} {% endif %} {%- for parent in parents -%} {{ parent.title }} {% if not loop.last %}{{ reldelim1 }} {% endif %} {%- endfor %} {% for rellink in rellinks | reverse -%} {{ rellink[3] }} {% if not loop.last %}{{ reldelim2 }} {% endif %} {% endfor %}
    {%- endif -%} {% endmacro %} {% block extrahead %} {%- for extra_css_file in theme_extra_css_files.split(',') %} {%- endfor %} {% endblock %} {% block relbar1 %} {{ navbar() }} {% endblock %} {% block sidebar1 %}{{ sidebar_table() }}{% endblock %} {% block sidebar2 %}{% endblock %} {% block relbar2 %}{% endblock %} {% block footer %} {{ navbar() }} {% endblock %} static/000077500000000000000000000000001526573132500355125ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/quarkquark.css_t000066400000000000000000000163421526573132500377000ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/quark/static{#- Template variable defintions -#} {% set text_color = theme_text_color or '#000000' -%} {% set link_color = theme_link_color or '#0000ff' -%} body { color: {{ text_color }}; {% if theme_body_font -%} font-family: {{ theme_body_font }}; {%- endif %} {% if theme_body_font_size -%} font-size: {{ theme_body_font_size }}; {%- endif %} } .document { margin-left: 2em; margin-right: 2em; } li { margin-top: 0.3em; margin-bottom: 0.3em; text-indent: {{ theme_li_extra_indent }}px; } {% for x in range(2, 10) -%} {{ 'li ' * x }}{ text-indent: {{ theme_li_extra_indent | int * x }}px; } {% endfor %} blockquote { text-indent: {{ theme_li_extra_indent }}px; } /* Definition lists */ dt { font-weight: bold; } dd > * { margin-top: 0; } li > dl > dd { margin-left: 0; } /* Compact list produced by hlist:: directive */ table.hlist { margin-top: 1em; } table.hlist ul { margin-top: 0; margin-bottom: 0; } /* Header/footer navigation bar * * ---------------------------- */ .navbar { background-color: {{ theme_navbar_bgcolor or 'transparent' }}; width: 100%; } {% if theme_navbar_color -%} .navbar * { color: {{ theme_navbar_color }}; } {%- endif %} .navbar a { {% if theme_underline_navbar_links -%} text-decoration: underline; {% endif %} } .navbar td { padding: 0.2em; } .navbar-bottom { margin-top: 2em; } .footer { font-style: italic; font-size: small; } /* Nav sidebar * * ----------- */ .nav-sidebar { margin: 2em; background-color: {{ theme_sidebar_bgcolor or 'transparent' }}; float: right; {% if theme_sidebar_border -%} border-style: solid; border-width: 1px; {%- endif %} border-color: {{ text_color }}; width: 20%; } .nav-sidebar .nav-sidebar-td { padding: 1em; } {% for i in range(1, 7) -%} .sphinxsidebar h{{ i }} { font-size: medium; font-weight: bold; } {% endfor %} /* Special index page markup * * ------------------------- */ .genindextable td { padding-top: 1em; padding-bottom: 1em; } .genindextable dl { margin: 0; } /* Links * * ----- */ a { color: {{ link_color }}; text-decoration: {% if theme_underline_links -%} underline {%- else -%} none {%- endif %}; } a.headerlink { color: {{ theme_headerlink_color or link_color }}; text-decoration: none; font-size: medium; font-weight: bold; padding: 0.2em; } /* Object references */ a code.xref { font-weight: bold; color: {{ theme_xref_color or link_color }}; background-color: {{ theme_code_bgcolor or 'transparent' }}; text-decoration: none; } /* Footnote references */ a.footnote-reference { font-size: small; } /* Code listings * * ------------- */ code, pre { {% if theme_code_font -%} font-family: {{ theme_code_font }}; {%- endif %} {% if theme_code_font_size -%} font-size: {{ theme_code_font_size }}; {%- endif %} } code { background-color: {{ theme_code_bgcolor or 'transparent' }}; } code.descname { font-weight: bold; background-color: transparent; } code.descclassname { background-color: transparent; } pre { margin: 0.5em; margin-top: 1.5em; {% if theme_pre_bgcolor -%} background-color: {{ theme_pre_bgcolor }} !important; {%- endif %} } /* Extra rules for literal blocks wrapped by ``html_rewrite`` */ .-x-quark-literal-block { margin-top: 1em; width: 100%; } .-x-quark-literal-block .-x-quark-literal-block-td { /* Use td for padding on QTextBrowser... */ padding: 0.5em; } .-x-quark-literal-block .-x-quark-literal-block-td:only-child { /* ...disable it again on full browsers... */ padding: 0; } .-x-quark-literal-block-td pre { margin: 0; /* ...and put the padding on the pre instead. */ padding: 0.5em; } /* Code blocks in headings and general links */ h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { background-color: transparent; } a code { background-color: transparent; } /* Regular tables * * -------------- */ table.docutils { margin-top: 2em; } table.docutils td, table.docutils th { padding: 0.3em; } /* Footnotes and citations * * ----------------------- */ table.docutils.footnote, table.docutils.citation { margin: 0; } table.docutils.footnote td, table.docutils.citation td { padding: 0; } table.docutils.footnote td.label, table.docutils.citation td.label { padding-right: 2em; } /* Boxes -- admonitions, sidebars, topics * * -------------------------------------- */ /* This section has good styles for the improved boxes created by * ``html_rewrite`` (the 'boxes') feature and some fallback styles if those are * disabled. */ /* Part 1 -- common styles */ .admonition-title, .sidebar-title, .topic-title { font-weight: bold; } .sidebar-subtitle { font-style: italic; } .admonition > .admonition-title { color: {{ theme_admonition_fgcolor or text_color }}; } .admonition.warning > .admonition-title { color: {{ theme_warning_fgcolor or text_color }}; } /* Part 2 -- fallback-specific styles */ .admonition > *, .topic > *, .sidebar > * { margin-left: 3em; margin-right: 5em; } .admonition > .first, .topic > .first, .sidebar > .first { margin-top: 3em; margin-left: 0; margin-right: 5em; } /* Part 3 -- x-quark-box styles */ .-x-quark-box .first { margin-top: 0; margin-left: 0; margin-right: 0; } .-x-quark-box .-x-quark-box-td > div > .last, .-x-quark-box .topic > :last-child { margin-bottom: 0; } .-x-quark-box .-x-quark-box-td > div > * { margin-left: 0; margin-right: 0; } .-x-quark-box { margin-top: 2em; } .-x-quark-box .-x-quark-box-td { padding: 0.5em; } .-x-quark-topic, .-x-quark-sidebar { border-width: 1px; border-style: solid; border-color: {{ text_color }}; } .-x-quark-topic { width: 100%; } .-x-quark-sidebar { margin-left: 1em; float: right; width: 35%; } .-x-quark-admonition { background-color: {{ theme_admonition_bgcolor or 'transparent' }}; {% if theme_admonition_border -%} border-style: solid; border-width: 1px; {%- endif %} border-color: {{ theme_admonition_fgcolor or text_color }}; width: 100%; } .-x-quark-admonition.-x-quark-warning { background-color: {{ theme_warning_bgcolor or 'transparent' }}; border-color: {{ theme_warning_fgcolor or text_color }}; } /* Misc markup * * ----------- */ .rubric { font-weight: bold; } .versionmodified { font-style: italic; } .field-list { margin-top: 0; } .guilabel, .menuselection { background-color: {{ theme_code_bgcolor or 'transparent' }}; } .accelerator { text-decoration: underline; } .caption-text { font-weight: bold; } div.line-block > div.line { margin-top: 0; margin-bottom: 0; } {% if theme_full_browser_extras -%} /* Some extra niceties for full browsers * * ------------------------------------------- */ a:hover { text-decoration: underline; } a.headerlink:hover { color: {{ link_color }}; text-decoration: none; } .navbar a:hover { color: {{ link_color }}; } pre:only-child { /* This gets us nicer literal blocks even without html_rewrite */ margin: 0; margin-top: 1em; padding: 0.5em; } {%- endif %} theme.conf000066400000000000000000000012341526573132500361740ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/quark_sphinx_theme/quark[theme] inherit = basic stylesheet = quark.css pygments_style = quark_sphinx_theme._lovelace.LovelaceStyle [options] text_color = #000000 body_font = code_font = body_font_size = code_font_size = li_extra_indent = 0 full_browser_extras = true extra_css_files = sidebar_bgcolor = sidebar_border = true navbar_color = #70705C navbar_bgcolor = #link_color = #295173 link_color = #33658E xref_color = headerlink_color = #AFAF92 underline_links = underline_navbar_links = true code_bgcolor = #EFEFE1 #pre_bgcolor = #EFEFE1 pre_bgcolor = admonition_border = admonition_fgcolor = #606060 admonition_bgcolor = #EEEEEE warning_fgcolor = #C43838 warning_bgcolor = #FFCCCC heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/setup.py000066400000000000000000000016361526573132500310010ustar00rootroot00000000000000#!/usr/bin/env python # setup.py generated by flit for tools that don't yet use PEP 517 from distutils.core import setup packages = \ ['quark_sphinx_theme', 'quark_sphinx_theme.ext', 'quark_sphinx_theme.ext.html_rewrite'] package_data = \ {'': ['*'], 'quark_sphinx_theme': ['quark/*', 'quark/static/*']} install_requires = \ ['sphinx >= 1.8'] extras_require = \ {'test': ['html5lib', 'tinycss']} entry_points = \ {'sphinx.html_themes': ['quark = quark_sphinx_theme']} setup(name='quark-sphinx-theme', version='0.6.0', description='A Sphinx theme designed for QTextBrowser', author='Felix Krull', author_email='f_krull@gmx.de', url='https://gitlab.com/fkrull/quark-sphinx-theme', packages=packages, package_data=package_data, install_requires=install_requires, extras_require=extras_require, entry_points=entry_points, python_requires='>= 3.5', ) heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/000077500000000000000000000000001526573132500302405ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/__init__.py000066400000000000000000000000001526573132500323370ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/test_core.py000066400000000000000000000005431526573132500326030ustar00rootroot00000000000000import os import unittest import quark_sphinx_theme class TestGetPath(unittest.TestCase): def test_get_path(self): p = quark_sphinx_theme.get_path() self.assertTrue(os.path.isdir(p)) conf = os.path.join(p, 'quark', 'theme.conf') self.assertTrue(os.path.isfile(conf)) if __name__ == '__main__': unittest.main() test_html_rewrite.py000066400000000000000000000115431526573132500343030ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/testimport os import sys import unittest DIR = os.path.abspath(os.path.dirname(__file__)) sys.path.insert(0, DIR) from util import SphinxBuildFixture, with_document, with_elements # noqa testdoc_html_rewrite = os.path.join(DIR, 'testdoc-html_rewrite') class TestHTMLRewriteOutputTestCases(SphinxBuildFixture): source_dir = testdoc_html_rewrite @with_elements('test_footnote', './/table[@class="docutils footnote"]/..') def test_footnote(self, elems): for par in elems: self.assertEqual(par.tag, 'div') self.assertEqual(par.get('class'), '-x-quark-footnote-wrapper') self.assertTrue(par.get('id')) self.assertFalse(par.find('./table').get('id')) @with_elements('test_citation', './/table[@class="docutils citation"]/..') def test_citation(self, elems): for par in elems: self.assertEqual(par.tag, 'div') self.assertEqual(par.get('class'), '-x-quark-citation-wrapper') self.assertTrue(par.get('id')) self.assertFalse(par.find('./table').get('id')) @with_elements('test_admonition', './/div[@class="admonition-test admonition"]/../../../..') def test_admonition(self, elems): for par in elems: self.assertEqual(par.tag, 'table') self.assertIn('-x-quark-admonition', par.get('class')) self.assertIn('-x-quark-box', par.get('class')) @with_elements('test_warning', './/div[@class="admonition warning"]/../../../..') def test_warning(self, elems): for par in elems: self.assertEqual(par.tag, 'table') self.assertIn('-x-quark-admonition', par.get('class')) self.assertIn('-x-quark-warning', par.get('class')) self.assertIn('-x-quark-box', par.get('class')) @with_elements('test_topic', './/div[@class="topic"]/../../../..') def test_topic(self, elems): for par in elems: self.assertEqual(par.tag, 'table') self.assertIn('-x-quark-topic', par.get('class')) self.assertIn('-x-quark-box', par.get('class')) @with_elements('test_sidebar', './/div[@class="sidebar"]/../../../..') def test_sidebar(self, elems): for par in elems: self.assertEqual(par.tag, 'table') self.assertIn('-x-quark-sidebar', par.get('class')) self.assertIn('-x-quark-box', par.get('class')) @with_elements('test_literal_block', './/div[@class="highlight"]/../../../../..') def test_literal_block(self, elems): for par in elems: self.assertEqual(par.tag, 'table') self.assertIn('-x-quark-literal-block', par.get('class')) class TestHTMLRewriteOutput(TestHTMLRewriteOutputTestCases, unittest.TestCase): pass class TestHTMLCompatOutput(TestHTMLRewriteOutputTestCases, unittest.TestCase): tags = ['test_html_compat_alias'] class TestHTMLRewriteOutputWithQtHelpBuilder(TestHTMLRewriteOutputTestCases, unittest.TestCase): builder = 'qthelp' class TestHTMLRewriteOutputWithBuilderBasedOnQtHelpBuilder(TestHTMLRewriteOutputTestCases, unittest.TestCase): builder = 'custom-qthelp' class TestHTMLRewriteFeatures(SphinxBuildFixture, unittest.TestCase): source_dir = testdoc_html_rewrite config = { 'quark_html_features': '', } @with_elements('test_footnote', './/table[@class="docutils footnote"]/..') def test_footnote(self, elems): for par in elems: self.assertNotIn(par.get('class'), '-x-quark-footnote-wrapper') @with_elements('test_citation', './/table[@class="docutils citation"]/..') def test_citation(self, elems): for par in elems: self.assertNotIn(par.get('class'), '-x-quark-citation-wrapper') @with_elements('test_admonition', './/div[@class="admonition-test admonition"]/../../../..') def test_admonition(self, elems): for par in elems: self.assertNotEqual(par.tag, 'table') self.assertNotIn('-x-quark-admonition', par.get('class')) @with_elements('test_topic', './/div[@class="topic"]/../../../..') def test_topic(self, elems): for par in elems: self.assertNotEqual(par.tag, 'table') self.assertNotIn('-x-quark-topic', par.get('class')) @with_elements('test_sidebar', './/div[@class="sidebar"]/../../../..') def test_sidebar(self, elems): for par in elems: self.assertNotEqual(par.tag, 'table') self.assertNotIn('-x-quark-sidebar', par.get('class')) @with_elements('test_literal_block', './/div[@class="highlight"]/../../../../..') def test_literal_block(self, elems): for par in elems: self.assertNotEqual(par.tag, 'table') self.assertNotIn('-x-quark-literal-block', par.get('class')) if __name__ == '__main__': unittest.main() test_html_rewrite_features.py000066400000000000000000000024101526573132500361720ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/testimport unittest from quark_sphinx_theme.ext.html_rewrite import get_overrides from quark_sphinx_theme.ext.html_rewrite.compat import * from quark_sphinx_theme.ext.html_rewrite.boxes import * from quark_sphinx_theme.ext.html_rewrite.literal_blocks import * class TestCreateTranslatorClass(unittest.TestCase): def test_no_enabled_no_disabled(self): overrides = get_overrides([], []) self.assertEqual(overrides, []) def test_some_enabled_no_disabled(self): overrides = get_overrides(['compat'], []) self.assertEqual(overrides, [ (citation, (visit_citation, depart_citation)), (footnote, (visit_footnote, depart_footnote)), ]) def test_no_enabled_some_disabled(self): overrides = get_overrides([], ['boxes', 'literal_blocks']) self.assertEqual(overrides, []) def test_some_enabled_some_disabled(self): overrides = get_overrides(['compat', 'boxes'], ['literal_blocks', 'compat']) self.assertEqual(overrides, [ (admonition, (visit_admonition, depart_admonition)), (topic, (visit_topic, depart_topic)), (sidebar, (visit_sidebar, depart_sidebar)), ]) if __name__ == '__main__': unittest.main() heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/test_import.py000066400000000000000000000012311526573132500331600ustar00rootroot00000000000000import unittest class TestModuleImport(unittest.TestCase): def assertImports(self, modname): try: __import__(modname) except ImportError as exc: self.fail('failed to import \'%s\': %s' % (modname, exc)) def test_main_package(self): self.assertImports('quark_sphinx_theme') def test_ext(self): self.assertImports('quark_sphinx_theme.ext') def test_ext_html_rewrite(self): self.assertImports('quark_sphinx_theme.ext.html_rewrite') def test_ext_html_compat(self): self.assertImports('quark_sphinx_theme.ext.html_compat') if __name__ == '__main__': unittest.main() heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/test_theme.py000066400000000000000000000107301526573132500327540ustar00rootroot00000000000000import os import sys import unittest DIR = os.path.abspath(os.path.dirname(__file__)) sys.path.insert(0, DIR) from util import SphinxBuildFixture, with_document # noqa testdoc_theme = os.path.join(DIR, 'testdoc-theme') class TestThemeEntrypoint(SphinxBuildFixture, unittest.TestCase): source_dir = os.path.join(DIR, 'testdoc-theme-entrypoint') @with_document('contents') def test_contents_nav_elements(self, doc): self.assertHasElement(doc, './/table[@class="nav-sidebar"]') self.assertHasElement(doc, './/table[@class="navbar navbar-top"]') self.assertHasElement(doc, './/table[@class="navbar navbar-bottom"]') class TestThemeDefaults(SphinxBuildFixture, unittest.TestCase): source_dir = testdoc_theme def test_quark_css(self): self.assertSphinxCSSValid('quark.css') def _nav_elems(self, doc): self.assertHasElement(doc, './/table[@class="nav-sidebar"]') self.assertHasElement(doc, './/table[@class="navbar navbar-top"]') self.assertHasElement(doc, './/table[@class="navbar navbar-bottom"]') @with_document('contents') def test_contents_nav_elements(self, doc): self._nav_elems(doc) @with_document('genindex') def test_genindex_nav_elements(self, doc): self._nav_elems(doc) @with_document('genindex-A') def test_genindex_a_nav_elements(self, doc): self._nav_elems(doc) @with_document('genindex-all') def test_genindex_all_nav_elements(self, doc): self._nav_elems(doc) @with_document('py-modindex') def test_domainindex_nav_elements(self, doc): self._nav_elems(doc) @with_document('search') def test_search_nav_elements(self, doc): self._nav_elems(doc) class TestThemeExtraCss(SphinxBuildFixture, unittest.TestCase): source_dir = testdoc_theme config = { 'html_theme_options.extra_css_files': '_static/extra1.css, ' '_static/extra2.css' } def test_quark_css(self): self.assertSphinxCSSValid('quark.css') @with_document('contents') def test_contents_css_files(self, doc): extra_css = { s.strip() for s in self.config['html_theme_options.extra_css_files'].split(',') } for css in doc.findall('head/link[@rel="stylesheet"]'): extra_css.discard(css.get('href').strip()) self.assertSetEqual(extra_css, set()) class TestThemeNoSidebar(SphinxBuildFixture, unittest.TestCase): source_dir = testdoc_theme config = { 'html_theme_options.nosidebar': True, } def test_quark_css(self): self.assertSphinxCSSValid('quark.css') def _nav_elems(self, doc): self.assertNotElement(doc, './/table[@class="nav-sidebar"]') self.assertHasElement(doc, './/table[@class="navbar navbar-top"]') self.assertHasElement(doc, './/table[@class="navbar navbar-bottom"]') @with_document('contents') def test_contents_nav_elements(self, doc): self._nav_elems(doc) @with_document('genindex') def test_genindex_nav_elements(self, doc): self._nav_elems(doc) @with_document('genindex-A') def test_genindex_a_nav_elements(self, doc): self._nav_elems(doc) @with_document('genindex-all') def test_genindex_all_nav_elements(self, doc): self._nav_elems(doc) @with_document('py-modindex') def test_domainindex_nav_elements(self, doc): self._nav_elems(doc) @with_document('search') def test_search_nav_elements(self, doc): self._nav_elems(doc) class TestThemeAllSettingsUnset(SphinxBuildFixture, unittest.TestCase): source_dir = testdoc_theme _SETTINGS = [ 'text_color', 'body_font', 'code_font', 'body_font_size', 'code_font_size', 'li_extra_indent', 'full_browser_extras', 'extra_css_files', 'sidebar_bgcolor', 'sidebar_border', 'navbar_color', 'navbar_bgcolor', 'link_color', 'xref_color', 'headerlink_color', 'underline_links', 'underline_navbar_links', 'code_bgcolor', 'pre_bgcolor', 'admonition_border', 'admonition_fgcolor', 'admonition_bgcolor', 'warning_fgcolor', 'warning_bgcolor', ] config = {'html_theme_options.%s' % s: '' for s in _SETTINGS} def test_quark_css(self): self.assertSphinxCSSValid('quark.css') if __name__ == '__main__': unittest.main() testdoc-extensions/000077500000000000000000000000001526573132500340235ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/testcustom_qthelp.py000066400000000000000000000004621526573132500372660ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-extensionstry: from sphinxcontrib.qthelp import QtHelpBuilder except ImportError: from sphinx.builders.qthelp import QtHelpBuilder class CustomQtHelpBuilder(QtHelpBuilder): name = 'custom-qthelp' search = False def setup(app): app.add_builder(CustomQtHelpBuilder) return {'version': '0.1'} testdoc-html_rewrite/000077500000000000000000000000001526573132500343315ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/testconf.py000066400000000000000000000005251526573132500356320ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewriteimport os import sys master_doc = 'contents' html4_writer = True if tags.has('test_html_compat_alias'): extensions = ['quark_sphinx_theme.ext.html_compat'] else: extensions = ['quark_sphinx_theme.ext.html_rewrite'] sys.path.append(os.path.abspath(os.path.join(os.pardir, 'testdoc-extensions'))) extensions.append('custom_qthelp') contents.rst000066400000000000000000000002511526573132500367160ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewrite.. toctree:: :maxdepth: 2 test_pre_block test_footnote test_citation test_admonition test_warning test_topic test_sidebar test_literal_block test_admonition.rst000066400000000000000000000010101526573132500402530ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewritetest_admonition =============== .. admonition:: Test Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. test_citation.rst000066400000000000000000000010151526573132500377310ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewritetest_citation ============= Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. [Cit]_ Citations --------- .. [Cit] Citation. test_footnote.rst000066400000000000000000000010111526573132500377500ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewritetest_footnote ============= Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. [#]_ Footnotes --------- .. [#] Footnote. test_literal_block.rst000066400000000000000000000012111526573132500407230ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewritetest_literal_block ================== .. code-block:: python3 def lorem_ipsum(): return """ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. """ test_pre_block.rst000066400000000000000000000012161526573132500400620ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewritetest_pre_block ============== :: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. :: import module class Cls(object): def meth(self, other): print(other) return "test" Cls().meth(5) test_sidebar.rst000066400000000000000000000010471526573132500375350ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewritetest_sidebar ============ .. sidebar:: Sidebar title :subtitle: Sidebar subtitle Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. test_topic.rst000066400000000000000000000010001526573132500372270ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewritetest_topic ========== .. topic:: Topic title Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. test_warning.rst000066400000000000000000000007721526573132500375750ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-html_rewritetest_warning ============ .. warning:: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. testdoc-theme-entrypoint/000077500000000000000000000000001526573132500351375ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/testconf.py000066400000000000000000000001101526573132500364260ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-theme-entrypointimport quark_sphinx_theme master_doc = 'contents' html_theme = 'quark' contents.rst000066400000000000000000000007351526573132500375330ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-theme-entrypoint.. toctree:: :maxdepth: 2 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-theme/000077500000000000000000000000001526573132500330055ustar00rootroot00000000000000conf.py000066400000000000000000000002221526573132500342210ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-themeimport quark_sphinx_theme master_doc = 'contents' html_theme_path = [quark_sphinx_theme.get_path()] html_theme = 'quark' html_split_index = True contents.rst000066400000000000000000000010771526573132500353220ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/testdoc-theme.. toctree:: :maxdepth: 2 .. Force an index entry. .. index:: Aaaa Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. .. Generate py-modindex. .. module:: python-module heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/test/util.py000066400000000000000000000077071526573132500316020ustar00rootroot00000000000000from contextlib import contextmanager from io import open, StringIO import os import shutil import sys import tempfile import html5lib import tinycss from sphinx.cmd.build import main @contextmanager def attrs(obj, **kwargs): oldvals = {} try: for k, v in kwargs.items(): oldval = getattr(obj, k) setattr(obj, k, v) oldvals[k] = oldval yield finally: for k, oldval in oldvals.items(): setattr(obj, k, oldval) @contextmanager def capture_output(): stdout = StringIO() with attrs(sys, stdout=stdout, stderr=stdout): yield stdout def get_css_errors(filename_or_fobj, encoding=None): if hasattr(filename_or_fobj, 'read'): source = filename_or_fobj.read() else: with open(filename_or_fobj, 'r', encoding=encoding) as fobj: source = fobj.read() parser = tinycss.make_parser() css = parser.parse_stylesheet(source) lines = source.split('\n') errors = [] for err in css.errors: try: errors.append(' %s [%s]\n' % (err, lines[err.line - 1])) except IndexError: errors.append(' %s\n' % err) return errors def run_sphinx(source_dir, build_dir, builder='html', extra_config={}, tags=[]): args = ['-b', builder, '-N'] for k, v in extra_config.items(): args.extend(['-D', '%s=%s' % (k, v)]) for tag in tags: args.extend(['-t', tag]) args.extend([source_dir, build_dir]) with capture_output() as stdout: try: ret = main(args) except SystemExit as e: ret = e.code if ret != 0: raise Exception('%s returned non-zero exit status %s\n' '--- Output:\n%s----' % (args, ret, stdout.getvalue())) class SphinxBuildFixture: source_dir = None builder = 'html' config = {} tags = [] build_dir = None @classmethod def setUpClass(cls): if not cls.source_dir: raise Exception('source_dir not set') cls.build_dir = tempfile.mkdtemp(prefix='tmp-sphinx-build-test-') try: run_sphinx(cls.source_dir, cls.build_dir, cls.builder, cls.config, cls.tags) except Exception: cls.tearDownClass() raise @classmethod def tearDownClass(cls): if cls.build_dir: shutil.rmtree(cls.build_dir, True) cls.build_dir = None def read_document(self, name): path = os.path.join(self.build_dir, *name.split('/')) + '.html' with open(path, 'rb') as f: return html5lib.parse(f, namespaceHTMLElements=False) def assertHasElement(self, doc, path, n=1): self.assertEqual(len(list(doc.findall(path))), n) def assertNotElement(self, doc, path): self.assertHasElement(doc, path, 0) def assertCSSValid(self, filename_or_fobj, encoding=None): errors = get_css_errors(filename_or_fobj, encoding) self.assertEqual(len(errors), 0, 'CSS errors:\n' + ''.join(errors)) def assertSphinxCSSValid(self, basename, encoding='utf-8'): self.assertCSSValid(os.path.join(self.build_dir, '_static', basename), encoding=encoding) def with_document(docname): def wrap1(func): def wrap2(self, *args, **kwargs): func(self, self.read_document(docname), *args, **kwargs) return wrap2 return wrap1 def with_elements(docname, xpath_expr, n=None): def wrap1(func): def wrap2(self, *args, **kwargs): elems = list(self.read_document(docname).findall(xpath_expr)) if n is not None and len(elems) != n: raise AssertionError('expected %s element(s), got %s' % (n, len(elems))) elif len(elems) == 0: raise AssertionError('no elements') func(self, elems, *args, **kwargs) return wrap2 return wrap1 heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/quark-sphinx-theme-0.6.0/tox.ini000066400000000000000000000006621526573132500306000ustar00rootroot00000000000000[tox] isolated_build=True envlist=py{35,38}-{sphinx18,sphinx20,sphinx21,sphinx22,sphinx23,sphinx24,sphinx30} [testenv] deps= html5lib tinycss default: sphinx sphinx18: sphinx>=1.8,<1.9 sphinx20: sphinx>=2.0,<2.1 sphinx21: sphinx>=2.1,<2.2 sphinx22: sphinx>=2.2,<2.3 sphinx23: sphinx>=2.3,<2.4 sphinx24: sphinx>=2.4,<2.5 sphinx30: sphinx>=3.0,<3.1 commands=python -m unittest discover test -v heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/sc_lexer.py000066400000000000000000000067571526573132500252650ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ A lexer extension that reads and highlights the SpeedCrunch expression syntax. To use, enable the extension and use the 'sc' or 'speedcrunch' syntax. """ from __future__ import print_function, unicode_literals import re from pygments.lexer import inherit, RegexLexer, words as _words from pygments.token import * # noqa RADIX = r'[.,]' SEPARATOR = '[ _\'u00b7\u066b\u066c\u02d9\u2396]' SEPARATORS = SEPARATOR + '*' def opt(string): return '(?:%s)?' % string def either(a, b): return '(?:%s|%s)' % (a, b) def casefolded(s): l, u = s.lower(), s.upper() return s if l == u else '[%s%s]' % (l, u) def numprefix(prefix): return SEPARATORS.join(casefolded(s) for s in prefix) + SEPARATORS def digits(d, required=True): return '([%s]%s)%s' % (d, SEPARATORS, '+' if required else '*') class words(_words): def get(self): return super(words, self).get() + r'(?=\W+)' def floatform(d): return digits(d, False) + RADIX + SEPARATORS + digits(d) EXPONENT = '[eE]' + SEPARATORS + '[+-]?' + SEPARATORS + digits('0-9') CONSTANTS = ['pi', '\u03c0', 'e', '\u212f', 'j', 'ans'] FUNCTIONS = [] class SpeedCrunchLexer(RegexLexer): name = 'SpeedCrunch' flags = re.MULTILINE | re.UNICODE tokens = { str('root'): [ # comments (r'[?].*\n', Comment), # regular operators (r'(\*\*|<<|>>|->|[+\-*/%=^!~\\&|:\'"°⋅â�»])', Operator), # keyword operators (words(['in']), Operator.Word), # additional punctuation (r'[\[\]();]', Punctuation), # built-in constants (words(CONSTANTS), Name.Constant), # built-in functions # (words(FUNCTIONS), Name.Builtin), # any other identifiers (r'([^\W\d]|\$)([\w$â�»â�°Â¹Â²Â³â�´â�µâ�¶â�·â�¸â�¹])*', Name), # binary numbers (numprefix('0b') + floatform('01'), Number.Bin), (numprefix('0b') + digits('01'), Number.Bin), # octal numbers (numprefix('0o') + floatform('0-7'), Number.Oct), (numprefix('0o') + digits('0-7'), Number.Oct), # hex numbers (either(numprefix('0x'), numprefix('#')) + floatform('0-9a-fA-F'), Number.Hex), (either(numprefix('0x'), numprefix('#')) + digits('0-9a-fA-F'), Number.Hex), # decimal numbers (opt(numprefix('0d')) + floatform('0-9') + opt(EXPONENT), Number.Float), (opt(numprefix('0d')) + digits('0-9') + opt(EXPONENT), Number.Integer), # any remaining whitespace (r'\s+', Text), # keep docs builds resilient when examples contain newer symbols. (r'.', Text), ], } class SpeedCrunchSessionLexer(SpeedCrunchLexer): name = 'SpeedCrunch Session' aliases = ['speedcrunch', 'sc'] tokens = { str('root'): [ # results; any line starting with '=' (r'\n\s*=.*\n', Generic.Emph), inherit, # an ellipsis for use in examples (r'\.\.\.', Punctuation), ] } def __init__(self): super().__init__(stripnl=False) self.add_filter('raiseonerror') __all__ = ['SpeedCrunchLexer', 'SpeedCrunchSessionLexer'] # Sphinx extension interface def setup(app): app.add_lexer('sc', SpeedCrunchSessionLexer) app.add_lexer('speedcrunch', SpeedCrunchSessionLexer) return { 'version': '0.1', 'parallel_read_safe': True, } heldercorreia-speedcrunch-e7ca37f/doc/src/extensions/speedcrunch_domain.py000066400000000000000000000214471526573132500273040ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of the SpeedCrunch project # Copyright (c) 2016 Felix Krull # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. """ A domain for SpeedCrunch things (functions and constants, mostly). To use, enable the extension and use the 'sc' domain like any other domain (e.g. 'sc:function', 'sc:constant'). To link to the function index, use :ref:`sc:functionindex`. """ import bisect from collections import deque import re import os import sphinx from sphinx import addnodes from sphinx.directives import ObjectDescription from sphinx.domains import Domain, Index, ObjType from sphinx.roles import XRefRole from sphinx.util.docfields import Field, GroupedField from sphinx.util.nodes import make_refnode from sphinx.locale import get_translation _MESSAGE_CATALOG = 'extra-doc-strings' _ = get_translation(_MESSAGE_CATALOG) _SIG_RE = re.compile(r''' ^ # start (\w+) # function name \s* # optional whitespace (?: \( ([^)]*) \) )? # optional argument list $ # end ''', re.VERBOSE) def sc_parameterlist(*args, **kwargs): node = addnodes.desc_parameterlist(*args, **kwargs) node.child_text_separator = '; ' return node def _parse_parameter_list(params): """Parse a SpeedCrunch parameter list into nodes.""" paramlist = sc_parameterlist() stack = deque([paramlist]) for param in params.split(';'): param = param.strip() if param and param[-1] in '[]': p = param[:-1].strip() stack[-1] += addnodes.desc_parameter(p, p) else: stack[-1] += addnodes.desc_parameter(param, param) if param.endswith('['): node = addnodes.desc_optional() stack[-1] += node stack.append(node) elif param.endswith(']'): stack.pop() return paramlist class SpeedCrunchObject(ObjectDescription): """Directive to document a SpeedCrunch object.""" doc_field_types = [ # l10n: Label for parameter lists when documenting functions GroupedField('parameter', label=_('Parameters'), names=('param', 'parameter', 'arg', 'argument',)), # l10n: Label for the return value field when documenting functions Field('returnvalue', label=_('Returns'), has_arg=False, names=('returns', 'return',)), ] needs_arglist = False def _needs_arglist(self): return self.needs_arglist def handle_signature(self, sig, signode): m = _SIG_RE.match(sig) if m is None: raise ValueError name, arglist = m.groups() signode += addnodes.desc_name(name, name) if not arglist and self._needs_arglist(): signode += sc_parameterlist() elif arglist: signode += _parse_parameter_list(arglist) return name def get_index_text(self, name): """Get index display string for the given object name.""" return name def add_index_entry(self, type, text, target, main='', key=None): # To accomodate for an API change in Sphinx 1.4. if sphinx.version_info[:3] < (1, 4, 0): idx = (type, text, target, main) else: idx = (type, text, target, main, key) if text: self.indexnode['entries'].append(idx) def add_target_and_index(self, name, sig, signode): targetname = 'sc.' + name if targetname not in self.state.document.ids: signode['names'].append(targetname) signode['ids'].append(targetname) signode['first'] = (not self.names) self.state.document.note_explicit_target(signode) inv = self.env.domaindata[self.domain]['objects'] if name in inv: self.state_machine.reporter.warning( 'duplicate SpeedCrunch object description of %s, ' % name + 'other instance in ' + self.env.doc2path(inv[name][0]), line=self.lineno) inv[name] = (self.env.docname, self.objtype) indextext = self.get_index_text(name) self.add_index_entry('single', indextext, targetname) class SpeedCrunchFunction(SpeedCrunchObject): """Documents a SpeedCrunch function.""" needs_arglist = True def get_index_text(self, name): # l10n: Index display text for built-in functions return _('%s() (function)') % name class SpeedCrunchConstant(SpeedCrunchObject): """Documents a SpeedCrunch built-in constant.""" def get_index_text(self, name): # l10n: Index display text for built-in constants return _('%s (constant)') % name class FunctionIndex(Index): """Generate an index of all SpeedCrunch functions.""" name = 'functionindex' # l10n: Function index long name (title and links) localname = _('Function Index') # l10n: Function index short name (used in the header of some Sphinx themes) shortname = _('functions') def generate(self, docnames=None): content = {} objs = sorted(self.domain.data['objects'].items()) for name, (docname, objtype) in objs: if not name or objtype != 'function': continue entries = content.setdefault(name[0].lower(), []) e = ('%s()' % name, 0, docname, 'sc.' + name, '', '', '') bisect.insort_left(entries, e) return sorted(content.items()), False class SpeedCrunchDomain(Domain): """Domain for documenting SpeedCrunch functions.""" name = 'sc' label = 'SpeedCrunch' data_version = 1 object_types = { # l10n: Label for built-in SpeedCrunch functions 'function': ObjType(_('function'), 'func'), # l10n: Label for built-in SpeedCrunch constants 'constant': ObjType(_('constant'), 'const'), } directives = { 'function': SpeedCrunchFunction, 'constant': SpeedCrunchConstant, } indices = [FunctionIndex] roles = { 'func': XRefRole(fix_parens=True), 'const': XRefRole(), } initial_data = { 'objects': {}, } def __init__(self, env): super(SpeedCrunchDomain, self).__init__(env) def clear_doc(self, docname): for name, (i_docname, objtype) in list(self.data['objects'].items()): if i_docname == docname: del self.data['objects'][name] def merge_domaindata(self, docnames, otherdata): for name, (docname, objtype) in otherdata['objects'].items(): if docname in docnames: self.data['objects'][name] = (docname, objtype) def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): try: docname, objtype = self.data['objects'][target] except KeyError: return None return make_refnode(builder, fromdocname, docname, 'sc.' + target, contnode, target) def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode): try: docname, objtype = self.data['objects'][target] except KeyError: return [] return [('sc:' + self.role_for_objtype(objtype), make_refnode(builder, fromdocname, docname, 'sc.' + target, contnode, target))] def get_objects(self): for name, (docname, objtype) in self.data['objects'].items(): yield (name, name, objtype, docname, 'sc.' + name, 1) def add_index_to_standard_domain(app, env, *args): # workaround so we can include our custom index via sc:functionindex std_domain = env.domains['std'] std_domain.data['labels']['sc:functionindex'] = \ ('sc-functionindex', '', FunctionIndex.localname) std_domain.data['anonlabels']['sc:functionindex'] = \ ('sc-functionindex', '') def setup(app): app.add_domain(SpeedCrunchDomain) app.connect('env-before-read-docs', add_index_to_standard_domain) for locale_dir in app.config.locale_dirs: app.add_message_catalog(_MESSAGE_CATALOG, os.path.join(app.srcdir, locale_dir)) return {'version': '0.1'} heldercorreia-speedcrunch-e7ca37f/doc/src/introduction.rst000066400000000000000000000026051526573132500241470ustar00rootroot00000000000000.. meta:: :description: Discover SpeedCrunch, a free scientific desktop calculator for Windows, macOS and Linux, and learn where to find its user guide and mathematical reference. .. This index entry identifies the "home page" of the manual, which is displayed when opening the manual in the application. .. index:: SpeedCrunch Introduction ============ Welcome to the SpeedCrunch manual! SpeedCrunch is a high-precision scientific desktop calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard. Some distinctive features are auto-completion of functions and variables, a formula book, and quick insertion of constants from various fields of knowledge. It is available for Windows, macOS, and Linux in a number of languages. We hope you have fun with SpeedCrunch! This documentation is divided into two major parts: * The :doc:`userguide/index` serves as a user manual that can be read from beginning to end. It presents all the features of SpeedCrunch and how to use them effectively. * The :doc:`reference/index` documents all the built-in functions, constants, and units that are included with SpeedCrunch. It's not intended to be read page by page, but it is still very useful to :ref:`look up ` how a particular function is used. .. only:: html For a complete overview, see the :doc:`full table of contents `. heldercorreia-speedcrunch-e7ca37f/doc/src/locale/000077500000000000000000000000001526573132500221305ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/locale/pot/000077500000000000000000000000001526573132500227325ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/locale/pot/advanced.pot000066400000000000000000000133711526573132500252300ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2016, The SpeedCrunch Developers # This file is distributed under the same license as the SpeedCrunch package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: SpeedCrunch master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-23 20:56+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../advanced/colorschemeformat.rst:4 msgid "Color Scheme File Format" msgstr "" #: ../../advanced/colorschemeformat.rst:6 msgid "Support for custom color schemes using this format was introduced in SpeedCrunch 0.12." msgstr "" #: ../../advanced/colorschemeformat.rst:9 msgid "SpeedCrunch uses a simple :abbr:`JSON (JavaScript Object Notation)`-based file format for color scheme definitions. New color schemes may easily be created, used and shared without having to recompile SpeedCrunch." msgstr "" #: ../../advanced/colorschemeformat.rst:13 msgid "In addition to the color schemes integrated into the application, color scheme files are loaded from the following directory:" msgstr "" #: ../../advanced/colorschemeformat.rst:16 msgid "Windows: :file:`C:/Users//AppData/Roaming/SpeedCrunch/color-schemes/`" msgstr "" #: ../../advanced/colorschemeformat.rst:17 msgid "Linux/Unix: :file:`~/.local/share/SpeedCrunch/color-schemes/`" msgstr "" #: ../../advanced/colorschemeformat.rst:18 msgid "Linux (Flatpak): :file:`~/.var/app/org.speedcrunch.SpeedCrunch/data/SpeedCrunch/color-schemes/`" msgstr "" #: ../../advanced/colorschemeformat.rst:19 msgid "OS X: :file:`~/Library/Application Support/SpeedCrunch/color-schemes/`" msgstr "" #: ../../advanced/colorschemeformat.rst:20 msgid "When using a portable version of SpeedCrunch on any operating system, additional color schemes are loaded from the :file:`color-schemes` subdirectory in the portable application directory." msgstr "" #: ../../advanced/colorschemeformat.rst:25 msgid "All color scheme files must have the extension ``.json``. The file name without the extension will be displayed in the color scheme menu (:menuselection:`Settings --> Display --> Color Scheme`). The contents of the color scheme directory are retrieved when SpeedCrunch is launched, so to have it pick up a newly-added color scheme file, it is necessary to restart the application. However, color scheme files are always reloaded when a color scheme is selected in the menu; that means after making changes to a color scheme file, re-selecting it in SpeedCrunch will reload the color scheme and show the changes. This allows for quick feedback when editing color schemes." msgstr "" #: ../../advanced/colorschemeformat.rst:33 msgid "The files themselves are simple `JSON `_ files containing a single JSON object mapping role names to color values. By way of example, this is the color scheme definition for the \"Terminal\" scheme that ships with SpeedCrunch:" msgstr "" #: ../../advanced/colorschemeformat.rst:55 msgid "Here, the keys are *roles*, each referring to elements in the SpeedCrunch history view and expression editor that can be colored. The values specify the colors for these roles. Color values may be any valid argument to the method |setNamedColor|_; the recommended form are simple HTML-style ``#RRGGBB`` definitions, using two hexadecimal digits per color component as in the example." msgstr "" #: ../../advanced/colorschemeformat.rst:65 msgid "Any unknown roles will be ignored. If a role is not defined in the color scheme, corresponding elements will be using the application's default text color (or, for background roles, the default background color). However, if the file is not valid JSON or otherwise does not follow the format described above, the color scheme will not load and SpeedCrunch will use the fallback colors for every element." msgstr "" #: ../../advanced/colorschemeformat.rst:73 msgid "Supported Color Roles" msgstr "" #: ../../advanced/colorschemeformat.rst:75 msgid "The following role names are supported by SpeedCrunch:" msgstr "" #: ../../advanced/colorschemeformat.rst:79 msgid "The cursor in the expression editor." msgstr "" #: ../../advanced/colorschemeformat.rst:83 msgid "Any number." msgstr "" #: ../../advanced/colorschemeformat.rst:87 msgid "Any parentheses. This role defines the text color, both for regular as well as for highlighted matching parentheses." msgstr "" #: ../../advanced/colorschemeformat.rst:92 msgid "The result value in the history view." msgstr "" #: ../../advanced/colorschemeformat.rst:96 msgid "Any comments." msgstr "" #: ../../advanced/colorschemeformat.rst:100 msgid "The background color for matching parentheses. When moving the cursor on a parenthesis, both it and its corresponding counterpart will be highlighted by changing their background to this color." msgstr "" #: ../../advanced/colorschemeformat.rst:106 msgid "The names of defined functions, built-in as well as user-defined functions." msgstr "" #: ../../advanced/colorschemeformat.rst:110 msgid "Any operator." msgstr "" #: ../../advanced/colorschemeformat.rst:114 msgid "The names of any variables or built-in constants." msgstr "" #: ../../advanced/colorschemeformat.rst:118 msgid "The color of the history view's scrollbar." msgstr "" #: ../../advanced/colorschemeformat.rst:122 msgid "Separators; notably, the semicolon (``;``) used for defining and using multi-argument functions." msgstr "" #: ../../advanced/colorschemeformat.rst:126 msgid "The background color of the main history view." msgstr "" #: ../../advanced/colorschemeformat.rst:130 msgid "The background color of the expression editor." msgstr "" #: ../../advanced/index.rst:2 msgid "Advanced Topics" msgstr "" heldercorreia-speedcrunch-e7ca37f/doc/src/locale/pot/contents.pot000066400000000000000000000016411526573132500253150ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2016, The SpeedCrunch Developers # This file is distributed under the same license as the SpeedCrunch package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: SpeedCrunch master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-23 20:56+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../contents.rst:2 msgid "Table of Contents" msgstr "" #: ../../contents.rst:14 msgid "Indices and Tables" msgstr "" #: ../../contents.rst:21 #: ../../contents.rst:26 msgid ":ref:`genindex`" msgstr "" #: ../../contents.rst:22 #: ../../contents.rst:27 msgid ":ref:`sc:functionindex`" msgstr "" #: ../../contents.rst:28 msgid ":ref:`search`" msgstr "" heldercorreia-speedcrunch-e7ca37f/doc/src/locale/pot/extra-doc-strings.pot000066400000000000000000000020141526573132500270300ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2022-12-23 20:56+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" #: extensions/speedcrunch_domain.py:86 msgid "Parameters" msgstr "" #: extensions/speedcrunch_domain.py:89 msgid "Returns" msgstr "" #: extensions/speedcrunch_domain.py:149 msgid "%s() (function)" msgstr "" #: extensions/speedcrunch_domain.py:157 msgid "%s (constant)" msgstr "" #: extensions/speedcrunch_domain.py:165 msgid "Function Index" msgstr "" #: extensions/speedcrunch_domain.py:167 msgid "functions" msgstr "" #: extensions/speedcrunch_domain.py:190 msgid "function" msgstr "" #: extensions/speedcrunch_domain.py:192 msgid "constant" msgstr "" heldercorreia-speedcrunch-e7ca37f/doc/src/locale/pot/introduction.pot000066400000000000000000000041211526573132500261750ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2016, The SpeedCrunch Developers # This file is distributed under the same license as the SpeedCrunch package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: SpeedCrunch master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-23 20:56+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../introduction.rst:2 msgid "Introduction" msgstr "" #: ../../introduction.rst:4 msgid "Welcome to the SpeedCrunch manual! SpeedCrunch is a high-precision scientific desktop calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard. Some distinctive features are auto-completion of functions and variables, a formula book, and quick insertion of constants from various fields of knowledge. It is available for Windows, OS X, and Linux in a number of languages. We hope you have fun with SpeedCrunch!" msgstr "" #: ../../introduction.rst:10 msgid "This documentation is divided into three major parts:" msgstr "" #: ../../introduction.rst:12 msgid "The :doc:`userguide/index` serves as a user manual that can be read from beginning to end. It presents all the features of SpeedCrunch and how to use them effectively." msgstr "" #: ../../introduction.rst:14 msgid "The :doc:`reference/index` documents all the built-in functions, constants, and units that are included with SpeedCrunch. It's not intended to be read page by page, but it is still very useful to :ref:`look up ` how a particular function is used." msgstr "" #: ../../introduction.rst:17 msgid "Finally, :doc:`advanced/index` covers more specialized topics that may be of interest, but are not necessary to use SpeedCrunch. For instance, it explains how to create custom color schemes." msgstr "" #: ../../introduction.rst:22 msgid "For a complete overview, see the :doc:`full table of contents `." msgstr "" heldercorreia-speedcrunch-e7ca37f/doc/src/locale/pot/reference.pot000066400000000000000000001307261526573132500254250ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2016, The SpeedCrunch Developers # This file is distributed under the same license as the SpeedCrunch package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: SpeedCrunch master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-23 20:56+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../reference/basic.rst:2 msgid "Basic Math Functions" msgstr "" #: ../../reference/basic.rst:5 #: ../../reference/statistical.rst:5 msgid "General" msgstr "" #: ../../reference/basic.rst:9 msgid "Return the absolute value of ``x``, commonly written as \\|x\\|. In real mode, it flips the sign of a negative number, thus forcing it to be positive. When given a complex number as argument, it returns the modulus of the number." msgstr "" #: ../../reference/basic.rst:11 msgid "The argument can have a dimension." msgstr "" #: ../../reference/basic.rst:13 #: ../../reference/integer.rst:113 msgid "Example::" msgstr "" #: ../../reference/basic.rst:23 msgid "Return the square root of ``x``. If complex numbers are disabled, this function is only defined for *x > 0*. In *complex mode*, any complex number may be specified, yielding the complex root in the upper half plane." msgstr "" #: ../../reference/basic.rst:25 #: ../../reference/basic.rst:312 #: ../../reference/basic.rst:318 #: ../../reference/basic.rst:330 msgid "The argument may have a dimension." msgstr "" #: ../../reference/basic.rst:29 msgid "Compute the third (cubic) root of ``x``. In *real mode*, it accepts any real number. Negative numbers will yield a negative cubic root::" msgstr "" #: ../../reference/basic.rst:34 msgid "In *complex mode*, this function accepts any complex input. The result will generally be the first complex root, i.e. the one with a phase between 0 and Ï€/3. Real negative arguments however will still yield a real (negative) result, matching the function's behavior in *real mode*. Use ``x^(1/3)`` to get the first complex root." msgstr "" #: ../../reference/basic.rst:38 msgid "Compute the natural exponential function." msgstr "" #: ../../reference/basic.rst:40 #: ../../reference/basic.rst:225 #: ../../reference/basic.rst:234 #: ../../reference/basic.rst:243 msgid "The argument must be dimensionless." msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`ln` (natural logarithm)" msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`lg` (binary logarithm)" msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`log` (arbitrary base logarithm)" msgstr "" #: ../../reference/basic.rst:49 msgid "Compute the natural logarithm. In *real mode*, the argument must be real, with *x > 0*." msgstr "" #: ../../reference/basic.rst:51 msgid "In *complex mode*, any non-zero number may be given. The result will be the principal value. The branch cut runs across the negative real axis. Nevertheless, in SpeedCrunch :func:`ln` is defined for negative real numbers as *ln(-x) = ln(\\|x\\|)) + Ï€j*, extending the branch from the *upper* half-plane." msgstr "" #: ../../reference/basic.rst:55 msgid "Compute the binary logarithm. In *complex mode* the same rules apply as for :func:`ln`." msgstr "" #: ../../reference/basic.rst:59 msgid "Compute the decimal logarithm. In *complex mode* the same rules apply as for :func:`ln`." msgstr "" #: ../../reference/basic.rst:63 msgid "Compute the logarithm of base ``n`` . In *complex mode* the same rules apply as for :func:`ln`." msgstr "" #: ../../reference/basic.rst:69 msgid "Trigonometric & Inverse Trigonometric" msgstr "" #: ../../reference/basic.rst:73 msgid "Returns the sine of ``x``. The behavior depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:75 msgid "In *degrees* or *gradians* modes, the argument is assumed to be expressed in such that :func:`sin` is periodic with a period of 360 degrees or 400 gradians, respectively: *sin(x) = sin(x+360)* or *sin(x) = sin(x+400)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting." msgstr "" #: ../../reference/basic.rst:77 msgid "When *radians* are set as the angle mode, :func:`sin` will be 2Ï€-periodic. The argument may be complex." msgstr "" #: ../../reference/basic.rst:79 #: ../../reference/basic.rst:99 #: ../../reference/basic.rst:153 #: ../../reference/basic.rst:165 msgid "For real arguments beyond approx. \\|x\\|>10\\ :sup:`77`, SpeedCrunch no longer recognizes the periodicity of the function and issues an error." msgstr "" #: ../../reference/basic.rst:81 msgid "The argument of :func:`sin` must be dimensionless." msgstr "" #: ../../reference/basic.rst:83 msgid "The inverse function is :func:`arcsin`." msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`cos`" msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`tan`" msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`cot`" msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`arcsin`" msgstr "" #: ../../reference/basic.rst:93 msgid "Returns the cosine of ``x``. The behavior depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:95 msgid "In *degrees* or *gradians* modes, the argument is assumed to be expressed in such that :func:`cos` is periodic with a period of 360 degrees or 400 gradians, respectively: *cos(x) = cos(x+360)* or *cos(x) = cos(x+400)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting." msgstr "" #: ../../reference/basic.rst:97 msgid "When *radians* are set as the angle mode, :func:`cos` will be 2Ï€-periodic. The argument may be complex." msgstr "" #: ../../reference/basic.rst:101 msgid "The argument of :func:`cos` must be dimensionless." msgstr "" #: ../../reference/basic.rst:103 msgid "The inverse function is :func:`arccos`." msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`sin`" msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`sec`" msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`arccos`" msgstr "" #: ../../reference/basic.rst:114 msgid "Returns the tangent of ``x``. The behavior depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:116 msgid "In *degrees* or *gradians* modes, the argument is assumed to be expressed in such that :func:`tan` is periodic with a period of 360 degrees or 400 gradians, respectively: *tan(x) = tan(x+360)* or *tan(x) = tan(x+400)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting." msgstr "" #: ../../reference/basic.rst:118 msgid "When *radians* are set as the angle mode, :func:`tan` will be Ï€-periodic. The argument may be complex." msgstr "" #: ../../reference/basic.rst:120 msgid "The argument of :func:`tan` must be dimensionless." msgstr "" #: ../../reference/basic.rst:122 msgid "The inverse function is :func:`arctan`." msgstr "" #: ../../reference/basic.rst:131 msgid "Returns the cotangent of ``x``. The behavior depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:133 msgid "In *degrees* or *gradians* modes, the argument is assumed to be expressed in such that :func:`cot` is periodic with a period of 360 degrees or 400 gradians, respectively: *cot(x) = cot(x+360)* or *cot(x) = cot(x+400)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting." msgstr "" #: ../../reference/basic.rst:136 msgid "When *radians* are set as the angle mode, :func:`cot` will be Ï€-periodic. The argument may be complex." msgstr "" #: ../../reference/basic.rst:138 msgid "The argument of :func:`cot` must be dimensionless." msgstr "" #: ../../reference/basic.rst:147 msgid "Returns the secant of ``x``, defined as the reciprocal cosine of ``x``: *sec(x) = 1/cos(x)*. The behavior depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:149 msgid "In *degrees* or *gradians* modes, the argument is assumed to be expressed in such that :func:`sec` is periodic with a period of 360 degrees or 400 gradians, respectively: *sec(x) = sec(x+360)* or *sec(x) = sec(x+400)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting." msgstr "" #: ../../reference/basic.rst:151 msgid "When *radians* are set as the angle mode, :func:`sec` will be 2Ï€-periodic. The argument may be complex." msgstr "" #: ../../reference/basic.rst:155 msgid "The argument of :func:`sec` must be dimensionless." msgstr "" #: ../../reference/basic.rst:159 msgid "Returns the cosecant of ``x``, defined as the reciprocal sine of ``x``: *csc(x) = 1/sin(x)*. The behavior depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:161 msgid "In *degrees* or *gradians* modes, the argument is assumed to be expressed in such that :func:`csc` is periodic with a period of 360 degrees or 400 gradians, respectively: *csc(x) = csc(x+360)* or *csc(x) = csc(x+400)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting." msgstr "" #: ../../reference/basic.rst:163 msgid "When *radians* are set as the angle mode, :func:`csc` will be 2Ï€-periodic. The argument may be complex." msgstr "" #: ../../reference/basic.rst:167 msgid "The argument of :func:`csc` must be dimensionless." msgstr "" #: ../../reference/basic.rst:172 msgid "Returns the inverse cosine of ``x``, such that *cos(arccos(x)) = x*. The behavior of the function depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:174 msgid "In *degrees* or *gradians* modes, :func:`arccos` takes a real argument from *[-1, 1]*, and the return value is in the range *[0, 180]* or *[0, 200]*, respectively. Real arguments outside *[-1, 1]* and complex numbers are allowed only in *radians* mode." msgstr "" #: ../../reference/basic.rst:176 msgid "When *radians* are set as the angle mode, :func:`arccos` maps an element from *[-1, 1]* to a value in *[0, Ï€]*. When complex numbers are enabled in addition, :func:`arccos` may take any argument from the complex plane. In complex mode, *arccos(-1) = Ï€* and *arccos(1) = 0* will yield the same result as in real mode." msgstr "" #: ../../reference/basic.rst:178 #: ../../reference/basic.rst:190 msgid "The argument of :func:`arccos` must be dimensionless." msgstr "" #: ../../reference/basic.rst:180 msgid "The inverse function is :func:`cos`." msgstr "" #: ../../reference/basic.rst:184 msgid "Returns the inverse sine of ``x``, such that *sin(arcsin(x)) = x*. The behavior of the function depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:186 msgid "In *degrees* or *gradians* modes, :func:`arcsin` takes a real argument from *[-1, 1]*, and the return value is in the range *[0, 180]* or *[0, 200]*, respectively. Real arguments outside *[-1, 1]* and complex numbers are allowed only in *radians* mode." msgstr "" #: ../../reference/basic.rst:188 msgid "When *radians* are set as the angle mode, :func:`arcsin` maps an element from *[-1, 1]* to a value in *[-Ï€/2, Ï€/2]*. When complex numbers are enabled in addition, :func:`arcsin` may take any argument from the complex plane. In complex mode, *arcsin(-1) = Ï€/2* and *arcsin(1) = Ï€/2* will yield the same result as in real mode." msgstr "" #: ../../reference/basic.rst:192 msgid "The inverse function is :func:`sin`." msgstr "" #: ../../reference/basic.rst:197 msgid "Returns the inverse tangent of ``x``, such that *tan(arctan(x)) = x*. The behavior of the function depends on both the angle mode setting and on whether complex numbers are enabled." msgstr "" #: ../../reference/basic.rst:199 msgid "In *degrees* or *gradians* modes, :func:`arctan` takes a real argument from *[-1, 1]*, and the return value is in the range *[0, 180]* or *[0, 200]*, respectively. Real arguments outside *[-1, 1]* and complex numbers are not allowed only in *radians* mode." msgstr "" #: ../../reference/basic.rst:201 msgid "When *radians* are set as the angle mode, :func:`arctan` maps a real number to a value in *[-Ï€/2, Ï€/2]*. When complex numbers are enabled in addition, :func:`arctan` may take any argument from the complex plane, except for *+j* and *-j*." msgstr "" #: ../../reference/basic.rst:203 msgid "The argument of :func:`arctan` must be dimensionless." msgstr "" #: ../../reference/basic.rst:205 msgid "The inverse function is :func:`tan`." msgstr "" #: ../../reference/basic.rst:209 msgid "Returns the angle formed by the vector *(x, y)* and the X axis. If the point *(x, y)* lies in the first quadrant (i.e. both *x > 0* and *y > 0* are true), it is given by *arctan(y/x)*. However, the function handles vectors in other quadrants as well." msgstr "" #: ../../reference/basic.rst:211 msgid "The behavior of the function depends on the angle mode setting. In *degrees* or *gradians* modes, this function returns a value in the range *]-180, 180]* or *]-200, 200]*, respectively. When *radians* are set as the angle mode, the return value lies in the range *]-Ï€, Ï€]*." msgstr "" #: ../../reference/basic.rst:213 msgid "Unlike :func:`arctan` this function only accepts real arguments." msgstr "" #: ../../reference/basic.rst:215 msgid "The argument values must be dimensionless." msgstr "" #: ../../reference/basic.rst:219 msgid "Hyperbolic & Inverse Hyperbolic" msgstr "" #: ../../reference/basic.rst:223 msgid "Return the hyperbolic sine of ``x``. In *complex mode*, any complex number may be used as the argument." msgstr "" #: ../../reference/basic.rst:227 msgid "The inverse function is :func:`arsinh`." msgstr "" #: ../../reference/basic.rst:232 msgid "Return the hyperbolic cosine of ``x``. In *complex mode*, any complex number may be used as the argument." msgstr "" #: ../../reference/basic.rst:236 msgid "The inverse function is :func:`arcosh`." msgstr "" #: ../../reference/basic.rst:241 msgid "Return the hyperbolic tangent of ``x``. In *complex mode*, any complex number may be used as the argument." msgstr "" #: ../../reference/basic.rst:245 msgid "The inverse function is :func:`artanh`." msgstr "" #: ../../reference/basic.rst:250 msgid "Compute the area hyperbolic sine of ``x``, the inverse function to :func:`sinh`. *arsinh(x)* is the only solution to *cosh(y) = x*." msgstr "" #: ../../reference/basic.rst:252 msgid "In complex mode, the function is defined for any complex ``z`` as *arsinh(z) = ln[z + (z* :sup:`2` *+1)* :sup:`1/2` *]*." msgstr "" #: ../../reference/basic.rst:254 #: ../../reference/basic.rst:263 #: ../../reference/basic.rst:272 msgid "The function only accepts dimensionless arguments." msgstr "" #: ../../reference/basic.rst:259 msgid "Compute the area hyperbolic cosine of ``x``, the inverse function to :func:`cosh`. *arcosh(x)* is the positive solution to *cosh(y) = x*. Except for *x=1*, the second solution to this equation will be given by *-arcosh(x)*." msgstr "" #: ../../reference/basic.rst:261 msgid "In real mode, the parameter ``x`` must be *> 1*. In complex mode, the function is defined for any complex ``z`` as *arcosh(z) = ln[z + (z* :sup:`2` *-1)* :sup:`2` *]*." msgstr "" #: ../../reference/basic.rst:268 msgid "Compute the area hyperbolic tangent of ``x``, the inverse function to :func:`tanh`. *artanh(x)* is the only solution to *tanh(y) = x*. In real mode, the parameter ``x`` has to fulfill *-1 < x < 1*." msgstr "" #: ../../reference/basic.rst:270 msgid "In complex mode, this function accepts any argument except for -1 and +1. In the complex plane, it is defined as *artanh(z) = 1/2 \\* ln[(z+1)/(z-1)]*." msgstr "" #: ../../reference/basic.rst:276 msgid "Special" msgstr "" #: ../../reference/basic.rst:280 msgid "Compute the error function, evaluated in ``x``. The error function is closely related to the Gaussian cumulative density function." msgstr "" #: ../../reference/basic.rst:282 #: ../../reference/basic.rst:288 #: ../../reference/basic.rst:294 #: ../../reference/basic.rst:302 msgid "Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments." msgstr "" #: ../../reference/basic.rst:286 msgid "Compute the complementary error function, evaluated in ``x``. The complementary error function is defined by ``erfc(x) = 1 - erf(x)``." msgstr "" #: ../../reference/basic.rst:292 msgid "Evaluates the gamma function (frequently denoted by the Greek letter Γ). The gamma function is an analytic extension to the factorial operation which is defined on real numbers as well. The relation between factorial and the gamma function is given by *Γ(n) = (n - 1)!*." msgstr "" #: ../../reference/basic.rst:296 msgid "The computation of the factorial operation is in fact implemented via :func:`gamma`. This means that in SpeedCrunch, factorials of non-integer numbers are allowed." msgstr "" #: ../../reference/basic.rst:300 msgid "Computes ``ln(abs(gamma(x)))``. As the gamma function grows extremely quickly, it is sometimes easier to work with its logarithm instead. :func:`lngamma` allows much larger arguments that would otherwise overflow :func:`gamma`." msgstr "" #: ../../reference/basic.rst:306 msgid "Complex Numbers" msgstr "" #: ../../reference/basic.rst:310 msgid "Return the real part of a complex number ``x``." msgstr "" #: ../../reference/basic.rst:316 msgid "Return the imaginary part of a complex number ``x``." msgstr "" #: ../../reference/basic.rst:322 msgid "Return the complex conjugate of a complex number ``x``." msgstr "" #: ../../reference/basic.rst:324 msgid "In *complex mode*, this function accepts any real or complex input. In *real mode*, the imaginary portion of ``x`` is stripped to ensure that the value returned is purely real." msgstr "" #: ../../reference/basic.rst:328 msgid "Returns the phase (angle) of a complex number ``x``. The unit of the angle corresponds to the current angle mode." msgstr "" #: ../../reference/basic.rst:0 msgid ":func:`abs` (absolute value)" msgstr "" #: ../../reference/basic.rst:337 msgid "Converts the complex number ``x`` to polar form, i.e. the form *r e* :sup:`jɸ`. The angle ɸ is always given in radians." msgstr "" #: ../../reference/basic.rst:341 msgid "Converts the complex number ``x`` to cartesian form, i.e. the form *a + j b*." msgstr "" #: ../../reference/basic.rst:345 msgid "Various" msgstr "" #: ../../reference/basic.rst:349 msgid "For *x >= 0*, return +1. For *x < 0*, return -1." msgstr "" #: ../../reference/basic.rst:353 msgid "Convert the angle ``x`` into radians. Independently of the angle mode setting, this function will assume that ``x`` is given in degrees and return ``pi*x/180``." msgstr "" #: ../../reference/basic.rst:355 #: ../../reference/basic.rst:361 #: ../../reference/basic.rst:367 #: ../../reference/basic.rst:373 #: ../../reference/basic.rst:379 msgid "The function only accepts real, dimensionless arguments." msgstr "" #: ../../reference/basic.rst:359 msgid "Convert the angle ``x`` into degrees. Independently of the angle mode setting, this function will assume that ``x`` is given in radians and return ``180*x/pi``." msgstr "" #: ../../reference/basic.rst:365 msgid "Convert the angle ``x`` into gradians. Independently of the angle mode setting, this function will assume that ``x`` is given in radians and return ``200*x/pi``." msgstr "" #: ../../reference/basic.rst:371 msgid "Returns the integer part of ``x``, effectively rounding it towards zero." msgstr "" #: ../../reference/basic.rst:377 msgid "Returns the fractional (non-integer) part of ``x``, given by ``frac(x) = x - int(x)``." msgstr "" #: ../../reference/constants.rst:4 #: ../../reference/index.rst:23 msgid "Constants" msgstr "" #: ../../reference/constants.rst:10 msgid "The mathematical constant Ï€. Since Ï€ is an irrational number, the value is an approximation with as much precision as SpeedCrunch allows. This constant may be referred to either as ``pi`` or as ``Ï€`` (Unicode U+03C0 GREEK SMALL LETTER PI)." msgstr "" #: ../../reference/constants.rst:18 msgid "The mathematical constant *e*. The value is an approximation with as much precision as SpeedCrunch supports. This constant may be referred to either as ``e`` or as ``ℯ`` (Unicode U+212F SCRIPT SMALL E)." msgstr "" #: ../../reference/constants.rst:25 msgid "When complex mode is enabled, this is the imaginary unit such that ``j ^ 2 = -1``. Using this constant, complex numbers are expressed as the sum of a real and an imaginary part::" msgstr "" #: ../../reference/ieee754.rst:2 msgid "IEEE-754 Functions" msgstr "" #: ../../reference/ieee754.rst:6 msgid "IEEE-754 is a standard for the representation of and computations with floating point numbers in binary systems. It is widely used by floating point implementations in CPUs. These functions implement encoding and decoding binary representations of floating point numbers according to IEEE-754." msgstr "" #: ../../reference/ieee754.rst:11 msgid "An IEEE-754 binary float consists of three parts: a sign bit, the exponent and the significand (sometimes called the mantissa). From these parts, the value is then calculated using the following formula: ``-1 ^ sign * 2 ^ (exponent - bias) * 1.significand``. The standard defines multiple binary formats of different sizes that all follow these rules, but differ in the number of bits allocated for the exponent and significand. The bias for the default formats is defined as ``bias = (2 ^ (exponent_bits - 1)) - 1``. See `this article `_ for a more detailed introduction into the subject." msgstr "" #: ../../reference/ieee754.rst:21 msgid "The following binary float formats are defined by the standard:" msgstr "" #: ../../reference/ieee754.rst:24 msgid "Name" msgstr "" #: ../../reference/ieee754.rst:24 msgid "Also known as" msgstr "" #: ../../reference/ieee754.rst:24 msgid "Exponent bits" msgstr "" #: ../../reference/ieee754.rst:24 msgid "Significand bits" msgstr "" #: ../../reference/ieee754.rst:26 msgid "``binary16``" msgstr "" #: ../../reference/ieee754.rst:26 msgid "Half precision" msgstr "" #: ../../reference/ieee754.rst:26 msgid "5" msgstr "" #: ../../reference/ieee754.rst:26 msgid "10" msgstr "" #: ../../reference/ieee754.rst:27 msgid "``binary32``" msgstr "" #: ../../reference/ieee754.rst:27 msgid "Single precision" msgstr "" #: ../../reference/ieee754.rst:27 msgid "8" msgstr "" #: ../../reference/ieee754.rst:27 msgid "23" msgstr "" #: ../../reference/ieee754.rst:28 msgid "``binary64``" msgstr "" #: ../../reference/ieee754.rst:28 msgid "Double precision" msgstr "" #: ../../reference/ieee754.rst:28 msgid "11" msgstr "" #: ../../reference/ieee754.rst:28 msgid "52" msgstr "" #: ../../reference/ieee754.rst:29 msgid "``binary128``" msgstr "" #: ../../reference/ieee754.rst:29 msgid "Quad precision" msgstr "" #: ../../reference/ieee754.rst:29 msgid "15" msgstr "" #: ../../reference/ieee754.rst:29 msgid "112" msgstr "" #: ../../reference/ieee754.rst:32 msgid "In many programming languages, the ``binary32`` format is available as ``float`` and ``binary64`` is available as ``double``." msgstr "" #: ../../reference/ieee754.rst:38 msgid "Encode a floating point number into a IEEE-754 binary representation." msgstr "" #: ../../reference/ieee754.rst:0 #: ../../reference/integer.rst:0 #: ../../reference/statistical.rst:0 msgid "Parameters" msgstr "" #: ../../reference/ieee754.rst:40 msgid "The floating point value to encode." msgstr "" #: ../../reference/ieee754.rst:41 #: ../../reference/ieee754.rst:51 msgid "The length of the exponent part, in bits." msgstr "" #: ../../reference/ieee754.rst:42 #: ../../reference/ieee754.rst:52 msgid "The length of the significand part, in bits." msgstr "" #: ../../reference/ieee754.rst:43 #: ../../reference/ieee754.rst:53 msgid "The exponent bias to use. Derived from the length of the exponent if not specified." msgstr "" #: ../../reference/ieee754.rst:48 msgid "Calculate the value of an IEEE-754 binary float." msgstr "" #: ../../reference/ieee754.rst:50 msgid "The binary float to decode." msgstr "" #: ../../reference/ieee754.rst:58 msgid "Encode ``x`` in the half-precision binary format." msgstr "" #: ../../reference/ieee754.rst:62 msgid "Decode the half-precision binary float ``x``." msgstr "" #: ../../reference/ieee754.rst:66 msgid "Encode ``x`` in the single-precision binary format." msgstr "" #: ../../reference/ieee754.rst:70 msgid "Decode the single-precision binary float ``x``." msgstr "" #: ../../reference/ieee754.rst:74 msgid "Encode ``x`` in the double-precision binary format." msgstr "" #: ../../reference/ieee754.rst:78 msgid "Decode the double-precision binary float ``x``." msgstr "" #: ../../reference/ieee754.rst:82 msgid "Encode ``x`` in the quad-precision binary format." msgstr "" #: ../../reference/ieee754.rst:86 msgid "Decode the quad-precision binary float ``x``." msgstr "" #: ../../reference/index.rst:2 msgid "Reference" msgstr "" #: ../../reference/index.rst:4 msgid "SpeedCrunch includes a large number of built-in math functions and constants. They are documented in this reference, organized by categories. There is also an :ref:`alphabetical list of all functions `." msgstr "" #: ../../reference/index.rst:10 msgid "Built-in Functions" msgstr "" #: ../../reference/integer.rst:2 msgid "Integer & Bitwise Arithmetic Functions" msgstr "" #: ../../reference/integer.rst:5 msgid "Bitwise Operations" msgstr "" #: ../../reference/integer.rst:9 msgid "Performs a bitwise logical AND on the submitted parameters (at least two). All parameters have to be real integers from the range -2\\ :sup:`255` to +2\\ :sup:`255`-1 (signed or unsigned 256 bit integers), non integer arguments are rounded toward zero. The result ranges from -2\\ :sup:`255` to +2\\ :sup:`255`-1 (signed integer)." msgstr "" #: ../../reference/integer.rst:13 msgid "Performs a bitwise logical OR on the submitted parameters (at least two). All parameters have to be integers from the range -2\\ :sup:`255` to +2\\ :sup:`255`-1 (signed integer), non integer arguments are rounded toward zero." msgstr "" #: ../../reference/integer.rst:17 msgid "Performs a bitwise logical XOR on the submitted parameters (at least two). All parameters have to be integers from the range -2\\ :sup:`255` to +2\\ :sup:`255`-1 (signed integer), non integer arguments are rounded toward zero." msgstr "" #: ../../reference/integer.rst:21 msgid "The :func:`not` function is defined by ``not(x) = -x-1``, giving the same result as the one's complement operator ``~`` in C/C++." msgstr "" #: ../../reference/integer.rst:23 msgid "This function does *not* simply flip the bits!" msgstr "" #: ../../reference/integer.rst:27 msgid "Performs an arithmetic left shift." msgstr "" #: ../../reference/integer.rst:29 #: ../../reference/integer.rst:41 msgid "The number (bit pattern) to shift, -2\\ :sup:`255` <= ``x`` <= +2\\ :sup:`256`-1." msgstr "" #: ../../reference/integer.rst:30 #: ../../reference/integer.rst:42 msgid "Number of bits to shift, -255 <= ``n`` <= 255. Must be integer." msgstr "" #: ../../reference/integer.rst:32 msgid "Note that ``n`` < 0 results in a right shift. The result ranges from -2\\ :sup:`255` to +2\\ :sup:`255`-1 (signed integer). ``x`` is rounded toward zero before shifting. If ``n`` = 0, ``x`` is returned without rounding." msgstr "" #: ../../reference/integer.rst:34 #: ../../reference/integer.rst:46 msgid "Shifted out bits are always dropped. During a right shift, the most significant bit (bit 255) is copied. During a left shift, zero bits are shifted in." msgstr "" #: ../../reference/integer.rst:39 msgid "Performs an arithmetic right shift." msgstr "" #: ../../reference/integer.rst:44 msgid "Note that ``n`` < 0 results in a left shift. The result ranges from -2\\ :sup:`255` to +2\\ :sup:`255`-1 (signed integer). ``x`` is rounded toward zero before shifting. If ``n`` = 0, ``x`` is returned without rounding." msgstr "" #: ../../reference/integer.rst:50 msgid "Returns the lowest ``n`` bits from ``x``. For this, ``x`` must be in the range -2\\ :sup:`255` <= ``x`` <= +2\\ :sup:`256`-1, and ``n`` must be an integer, 1 <= ``n`` <= 255. ``x`` is rounded toward zero." msgstr "" #: ../../reference/integer.rst:52 msgid "The result is always unsigned." msgstr "" #: ../../reference/integer.rst:54 msgid "Example: Getting the two's complement of -1 in a 16-bit system::" msgstr "" #: ../../reference/integer.rst:61 msgid "Takes the lower ``n`` bits from ``x`` and sign-extends them to full 256 bits. This means that bit at position *n-1* is copied to all upper bits." msgstr "" #: ../../reference/integer.rst:63 msgid "The value of ``x`` must be in the range *-2* :sup:`255` *<= x <= +2* :sup:`256` *-1*, and ``n`` must be an integer, *1 <= n <= 255*. ``x`` is rounded toward zero." msgstr "" #: ../../reference/integer.rst:65 msgid "Example: Converting a number in two's complement representation to a signed number::" msgstr "" #: ../../reference/integer.rst:75 msgid "Numeral Bases" msgstr "" #: ../../reference/integer.rst:77 msgid "The following functions only change the format for the current result. To change the base that is used for displaying results, select one of the corresponding settings in :menuselection:`Settings --> Result Format`." msgstr "" #: ../../reference/integer.rst:82 msgid "Format ``n`` as binary (base-2)." msgstr "" #: ../../reference/integer.rst:86 msgid "Format ``n`` as octal (base-8)." msgstr "" #: ../../reference/integer.rst:90 msgid "Format ``n`` as decimal (base-10)." msgstr "" #: ../../reference/integer.rst:94 msgid "Format ``n`` as hexadecimal (base-16)." msgstr "" #: ../../reference/integer.rst:98 msgid "Rounding" msgstr "" #: ../../reference/integer.rst:102 msgid "Round ``x`` to the next largest integer. Only real, dimensionless arguments are allowed." msgstr "" #: ../../reference/integer.rst:106 msgid "Round ``x`` to the next smallest integer. Only real, dimensionless arguments are allowed." msgstr "" #: ../../reference/integer.rst:111 msgid "Round ``x`` to the nearest number with ``n`` fractional digits; ``n`` may be omitted, in which case ``x`` is rounded to the closest integer. Ties are broken by rounding to the nearest *even* integer. This rounding strategy, commonly known as *Banker's rounding*, serves to avoid a bias (for instance when averaging or summing)." msgstr "" #: ../../reference/integer.rst:127 #: ../../reference/integer.rst:147 #: ../../reference/integer.rst:157 msgid "Only real, dimensionless arguments are allowed." msgstr "" #: ../../reference/integer.rst:131 msgid "Truncate (rounds toward zero) ``x`` to the next number with ``n`` fractional digits; ``n`` may be omitted, in which case ``x`` is rounded to integer. Only real, dimensionless arguments are allowed." msgstr "" #: ../../reference/integer.rst:0 msgid ":func:`int`" msgstr "" #: ../../reference/integer.rst:0 msgid ":func:`frac`" msgstr "" #: ../../reference/integer.rst:139 msgid "Integer Division" msgstr "" #: ../../reference/integer.rst:143 msgid "Compute the integer part of the division ``a/b``. The result is guaranteed to be exact. While ``int(a/b)`` covers a larger range of arguments, the result is computed via floating point arithmetics and may be subject to rounding errors. This function will instead yield an error if the parameters exceed the safe bounds." msgstr "" #: ../../reference/integer.rst:145 msgid "It is possible to apply :func:`idiv` to non-integers as well, but be aware that rounding errors might be lead to off-by-one errors. If the result depends on the validity of the guard digits, *NaN* is returned." msgstr "" #: ../../reference/integer.rst:151 msgid "Compute the remainder of the integer division ``a/b``. The divisor ``b`` must be non-zero. The result takes the sign of ``a``." msgstr "" #: ../../reference/integer.rst:153 msgid "This function always returns an exact result, provided that the parameters are exact." msgstr "" #: ../../reference/integer.rst:155 msgid "You can use this function with non-integers as well, but rounding errors might lead to off-by-one errors. Evaluating :func:`mod` can be computationally expensive, so the function is internally restricted to 250 division loops." msgstr "" #: ../../reference/integer.rst:161 msgid "Returns the greatest common divisor of the arguments (at least two must be given). You can use this function to reduce a rational number. If a rational number is given as ``p/q``, its reduced form is ``(p / gcd(p; q)) / (q / gcd(p; q))``." msgstr "" #: ../../reference/integer.rst:164 msgid "A closely related function is ``lcm()`` (*least common multiple*). While ``lcm()`` is not defined by default in SpeedCrunch, you can define it yourself as::" msgstr "" #: ../../reference/integer.rst:169 msgid "Only real, integer arguments are allowed." msgstr "" #: ../../reference/statistical.rst:2 msgid "Statistical Functions" msgstr "" #: ../../reference/statistical.rst:9 msgid "Computes the arithmetic average of the arguments (sum of the arguments divided by their number). The arguments must share the same dimension." msgstr "" #: ../../reference/statistical.rst:13 msgid "Computes the geometric mean of the arguments, defined by ``product(x1; x2; ...)^(1/n)`` where ``n`` is the number of arguments. All the arguments may each have a different dimension. The geometric mean is useful for comparing sets of quantities that are very different in order of magnitude and even possibly dimension." msgstr "" #: ../../reference/statistical.rst:17 msgid "Computes the median of the arguments, i.e. the value dividing the set of arguments into two evenly sized parts." msgstr "" #: ../../reference/statistical.rst:19 msgid "First the set of arguments is sorted. If the number of arguments is odd, the element in the middle of the sorted list is returned. If the number of arguments is even, the arithmetic mean of the two central elements is returned." msgstr "" #: ../../reference/statistical.rst:23 msgid "Returns the minimum out of the supplied argument list. The arguments must be real and share the same dimension." msgstr "" #: ../../reference/statistical.rst:27 msgid "Returns the maximum out of the supplied argument list. The arguments must be real and share the same dimension." msgstr "" #: ../../reference/statistical.rst:31 msgid "Computes the sum of all the given arguments. These must share the same dimension." msgstr "" #: ../../reference/statistical.rst:35 msgid "Computes the product of all the given arguments." msgstr "" #: ../../reference/statistical.rst:39 msgid "Computes the population variance of the arguments. The variance is measure for the spreading of a set of numbers." msgstr "" #: ../../reference/statistical.rst:41 msgid "The arguments must share the same dimension." msgstr "" #: ../../reference/statistical.rst:45 msgid "This function computes the *population variance*, which assumes that all possible realizations are all given as arguments. A function to estimate the variance from a sample (*sample variance*) is not included with SpeedCrunch." msgstr "" #: ../../reference/statistical.rst:49 msgid "Computes the standard deviation of the given arguments. It is obtained by taking the square root of the :func:`variance ` of its arguments." msgstr "" #: ../../reference/statistical.rst:53 msgid "Computes the average absolute deviation of the arguments from their mean. This means that, with ``x = average(x1; x2; ...)``, we have::" msgstr "" #: ../../reference/statistical.rst:62 msgid "Binomial Distribution" msgstr "" #: ../../reference/statistical.rst:64 msgid "The binomial distribution is described by the parameters ``N`` and ``p``. It gives the probability distribution of the number of successful trials, when the total number of trials is given by ``N``, and each test is successful with probability ``p``. Not that unlike the :ref:`hypergeometric-distribution`, the probability ``p`` remains the same for all draws. The binomial distribution can be thought of drawing *with* replacement, while the hypergeometric distribution describes drawing *without* replacement." msgstr "" #: ../../reference/statistical.rst:68 msgid "Binomial cumulative distribution function." msgstr "" #: ../../reference/statistical.rst:70 #: ../../reference/statistical.rst:88 msgid "maximum number of successes, must be integer" msgstr "" #: ../../reference/statistical.rst:71 #: ../../reference/statistical.rst:89 msgid "number of trials, must be a positive integer" msgstr "" #: ../../reference/statistical.rst:72 #: ../../reference/statistical.rst:90 msgid "probability to succeed a single trial, *0 <= p <= 1*" msgstr "" #: ../../reference/statistical.rst:74 msgid "The function computes the probability, that, for ``N`` independent repetitions of a test successful with probability ``p`` each, the total number of successes is **less than or equal** to ``x``." msgstr "" #: ../../reference/statistical.rst:76 msgid "Example: When tossing a fair coin 9 times, what is the probability that we find Heads at most 5 times?" msgstr "" #: ../../reference/statistical.rst:86 msgid "Binomial probability mass function." msgstr "" #: ../../reference/statistical.rst:92 msgid "The function computes the probability, that, for ``N`` independent repetitions of a test, each successful with probability ``p``, the total number of successes is **exactly equal** to ``x``." msgstr "" #: ../../reference/statistical.rst:94 msgid "Example: When tossing a fair coin 9 times, what is the probability that we find Heads exactly 5 times?" msgstr "" #: ../../reference/statistical.rst:103 msgid "Mean (expectation) value of the given binomial distribution." msgstr "" #: ../../reference/statistical.rst:105 msgid "The function computes the expected number of successes when an experiment is performed ``N`` times, each successful independently with probability ``p``. The result will simply be given by *N * p*." msgstr "" #: ../../reference/statistical.rst:110 msgid "Computes the variance of the given binomial distribution function, equal to *N \\* p \\* (1-p)*." msgstr "" #: ../../reference/statistical.rst:114 msgid "Computes the binomial coefficient, equal to the number of possibilities of how to select ``k`` elements from a set of size ``N``. The order of the ``k`` elements is of no importance, i.e. permutations of a subset are not counted as an additional choice." msgstr "" #: ../../reference/statistical.rst:116 msgid "In SpeedCrunch the domain of :func:`ncr` is extended to all real numbers. The result is *1/((\\ N + 1) \\* B(\\ k + 1, N - k + 1))*, where *B(a, b)* is the complete Beta function." msgstr "" #: ../../reference/statistical.rst:120 msgid "Computes the binomial coefficient, equal to the number of possibilities of how to select ``k`` elements from a set of size ``N``. The order of the ``k`` elements **is** important, i.e. permutations of a subset are counted as an additional choice." msgstr "" #: ../../reference/statistical.rst:122 msgid "In SpeedCrunch, the domain of :func:`npr` is extended to all real numbers. The result is *Γ(\\ N + 1)/Γ(\\ k)*, where *Γ* is the gamma function; see :func:`gamma`." msgstr "" #: ../../reference/statistical.rst:128 msgid "Hypergeometric Distribution" msgstr "" #: ../../reference/statistical.rst:130 msgid "The hypergeometric distribution is described by the three parameters ``N``, ``K`` and ``n``. It describes the probability distribution of the number of successes when drawing ``n`` samples from a finite population of size ``N``, containing exactly ``K`` successes. Unlike the :ref:`binomial-distribution`, the hypergeometric distribution describes drawing *without* replacement." msgstr "" #: ../../reference/statistical.rst:134 msgid "Hypergeometric probability mass function." msgstr "" #: ../../reference/statistical.rst:136 msgid "desired number of successes, must be integer" msgstr "" #: ../../reference/statistical.rst:137 #: ../../reference/statistical.rst:156 #: ../../reference/statistical.rst:175 #: ../../reference/statistical.rst:190 msgid "total size of the population, must be positive integer" msgstr "" #: ../../reference/statistical.rst:138 #: ../../reference/statistical.rst:157 #: ../../reference/statistical.rst:176 #: ../../reference/statistical.rst:191 msgid "number of successes within the population, *0 <= K <= N*, must be integer" msgstr "" #: ../../reference/statistical.rst:139 #: ../../reference/statistical.rst:158 #: ../../reference/statistical.rst:177 #: ../../reference/statistical.rst:192 msgid "number of draws, *0 <= n <= N*, must be integer" msgstr "" #: ../../reference/statistical.rst:141 msgid "The function computes the probability that for ``n`` draws without replacement from a population of size ``N`` and containing ``K`` successes, the number of successes drawn is *exactly* equal to ``k``." msgstr "" #: ../../reference/statistical.rst:143 msgid "Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. What is the probability of drawing 8 white ones?" msgstr "" #: ../../reference/statistical.rst:153 msgid "Hypergeometric cumulative distribution function." msgstr "" #: ../../reference/statistical.rst:155 msgid "maximum desired number of successes, must be integer" msgstr "" #: ../../reference/statistical.rst:160 msgid "The function computes the probability that for ``n`` draws without replacement from a population of size ``N`` and containing ``K`` successes, the number of successes drawn is *smaller than or equal* to ``k``." msgstr "" #: ../../reference/statistical.rst:162 msgid "Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. What is the probability of drawing at most 8 white ones?" msgstr "" #: ../../reference/statistical.rst:173 msgid "Expected value of the given hypergeometric distribution." msgstr "" #: ../../reference/statistical.rst:179 msgid "Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. How many white marbles do we expect to find in our drawn sample?" msgstr "" #: ../../reference/statistical.rst:188 msgid "Variance of the given hypergeometric distribution." msgstr "" #: ../../reference/statistical.rst:194 msgid "Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. We estimate the standard deviation of the experiment::" msgstr "" #: ../../reference/statistical.rst:199 msgid "This number is an estimate on by how many marbles our sample will deviate from the expectation value." msgstr "" #: ../../reference/statistical.rst:203 msgid "Poisson Distribution" msgstr "" #: ../../reference/statistical.rst:205 msgid "The Poisson distribution is characterized by only a single parameter, named ``mu``. It represents both the mean and the variance of the distribution. It describes the probability distribution of the number of events during a fixed period of time, when the average rate of events is known. The Poisson distribution requires the events to be independent. This is usually a good approximation when the rate is low compared to the total population size." msgstr "" #: ../../reference/statistical.rst:209 msgid "Poisson probability mass function." msgstr "" #: ../../reference/statistical.rst:211 #: ../../reference/statistical.rst:238 msgid "Desired number of events, must be integer" msgstr "" #: ../../reference/statistical.rst:212 #: ../../reference/statistical.rst:239 msgid "Average number of events, must be positive" msgstr "" #: ../../reference/statistical.rst:214 msgid "Computes the probability to observe exactly ``x`` events." msgstr "" #: ../../reference/statistical.rst:216 msgid "*Example 1*: In a manufacturing process with yield of 99%, what is the probability that 2 out of 10 manufactured products are failures? First, we note that according to the yield, the expected number of failures are given by::" msgstr "" #: ../../reference/statistical.rst:222 msgid "Hence the answer to the problem is::" msgstr "" #: ../../reference/statistical.rst:227 msgid "*Example 2* ::An insurance company expects 10 claims over the period of one year. What is the probability that instead as many as 20 claims will be filed?" msgstr "" #: ../../reference/statistical.rst:236 msgid "Poisson cumulative distribution function." msgstr "" #: ../../reference/statistical.rst:241 msgid "Computes the probability to observe ``x`` or fewer events." msgstr "" #: ../../reference/statistical.rst:243 msgid "Example: An insurance company expects 10 claims over the period of one year. What is the probability that more than 12 claims will be filed?" msgstr "" #: ../../reference/statistical.rst:253 msgid "Computes the expectation value of the given Poisson distribution. By definition, this value is equal to ``mu``." msgstr "" #: ../../reference/statistical.rst:257 msgid "Computes the variance of the given Poisson distribution. By definition, this value is equal to ``mu``." msgstr "" heldercorreia-speedcrunch-e7ca37f/doc/src/locale/pot/sphinx.pot000066400000000000000000000216041526573132500247720ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2016, The SpeedCrunch Developers # This file is distributed under the same license as the SpeedCrunch package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: SpeedCrunch master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-23 20:56+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../_templates_standalone/donate.html:7 #: ../../_templates_standalone/download.html:103 #: ../../_templates_standalone/entrance_navbar.html:6 #: ../../_templates_standalone/layout.html:183 msgid "Home" msgstr "" #: ../../_templates_standalone/donate.html:8 #: ../../_templates_standalone/entrance.html:31 #: ../../_templates_standalone/entrance_navbar.html:22 msgid "Donate" msgstr "" #: ../../_templates_standalone/donate.html:12 msgid "Thank you for helping" msgstr "" #: ../../_templates_standalone/donate.html:14 msgid "SpeedCrunch is and will always be available to you at no cost." msgstr "" #: ../../_templates_standalone/donate.html:15 msgid "However, if you use this application on a regular basis and you find it very useful for performing on your work, studies or private affairs, please consider supporting it financially." msgstr "" #: ../../_templates_standalone/donate.html:16 msgid "Any contribution, no matter how small, will help supporting the expenses of server hosting, internet domain and computers for further development." msgstr "" #: ../../_templates_standalone/donate.html:17 msgid "It will also somehow compensate for the many thousands of hours spent by volunteers since 2004 on this project." msgstr "" #: ../../_templates_standalone/donate.html:18 msgid "As a result, much more frequent releases will be possible with your help." msgstr "" #: ../../_templates_standalone/donate.html:22 msgid "Please send us your contribution via one of the methods below." msgstr "" #: ../../_templates_standalone/donate.html:23 msgid "If it is not working for you or think we should support other payment methods, please get in touch." msgstr "" #: ../../_templates_standalone/donate.html:29 msgid "Service" msgstr "" #: ../../_templates_standalone/donate.html:30 msgid "Send To" msgstr "" #: ../../_templates_standalone/download.html:21 msgid "Use the portable version if you can't or don't want to install the application. Take it anywhere and just run the file to start." msgstr "" #: ../../_templates_standalone/download.html:52 msgid "Download on Flathub" msgstr "" #: ../../_templates_standalone/download.html:60 #: ../../_templates_standalone/download.html:104 #: ../../_templates_standalone/download.html:114 #: ../../_templates_standalone/download.html:134 #: ../../_templates_standalone/download.html:149 #: ../../_templates_standalone/download.html:156 #: ../../_templates_standalone/entrance.html:29 msgid "Download" msgstr "" #: ../../_templates_standalone/download.html:77 msgid "If available, we recommend installing SpeedCrunch directly via your distribution's package manager." msgstr "" #: ../../_templates_standalone/download.html:78 msgid "Note that the latest version may not be available." msgstr "" #: ../../_templates_standalone/download.html:89 msgid "Version" msgstr "" #: ../../_templates_standalone/download.html:108 msgid "Version 1.0" msgstr "" #: ../../_templates_standalone/download.html:111 #: ../../_templates_standalone/download.html:131 #: ../../_templates_standalone/download.html:147 #: ../../_templates_standalone/download.html:154 msgid "Installer" msgstr "" #: ../../_templates_standalone/download.html:112 #: ../../_templates_standalone/download.html:132 #: ../../_templates_standalone/download.html:148 #: ../../_templates_standalone/download.html:155 msgid "Portable" msgstr "" #: ../../_templates_standalone/download.html:122 msgid "Unsure about the installation?" msgstr "" #: ../../_templates_standalone/download.html:123 msgid "Have a look at the instructions." msgstr "" #: ../../_templates_standalone/download.html:127 msgid "Older Versions" msgstr "" #: ../../_templates_standalone/download.html:137 msgid "32-bit RPM" msgstr "" #: ../../_templates_standalone/download.html:138 msgid "32-bit Deb" msgstr "" #: ../../_templates_standalone/download.html:139 msgid "32-bit Generic" msgstr "" #: ../../_templates_standalone/download.html:140 msgid "64-bit RPM" msgstr "" #: ../../_templates_standalone/download.html:141 msgid "64-bit Deb" msgstr "" #: ../../_templates_standalone/download.html:142 msgid "64-bit Generic" msgstr "" #: ../../_templates_standalone/entrance.html:27 msgid "SpeedCrunch is a high-precision scientific calculator featuring a fast, keyboard-driven user interface. It is free and open-source software, licensed under the GPL." msgstr "" #: ../../_templates_standalone/entrance.html:30 #: ../../_templates_standalone/entrance_navbar.html:8 #: ../../_templates_standalone/layout.html:184 msgid "Documentation" msgstr "" #: ../../_templates_standalone/entrance.html:48 msgid "Efficient & easy-to-use interface." msgstr "" #: ../../_templates_standalone/entrance.html:49 msgid "SpeedCrunch displays results as you type. Select a partial expression to evaluate only that part." msgstr "" #: ../../_templates_standalone/entrance.html:50 msgid "Previous inputs and results are shown in a scrollable history and can be easily recalled. Customizable syntax highlighting allows you to spot mistakes easily." msgstr "" #: ../../_templates_standalone/entrance.html:51 msgid "If you prefer the old-school way, an optional on-screen keypad is available as well." msgstr "" #: ../../_templates_standalone/entrance.html:63 msgid "Powerful." msgstr "" #: ../../_templates_standalone/entrance.html:64 msgid "SpeedCrunch comes with over 80 built-in mathematical functions. You can also define your own functions." msgstr "" #: ../../_templates_standalone/entrance.html:65 msgid "Variables allow you to store your results. Perform calculations with up to 50 digits of precision, using complex numbers, numeral bases, unit conversions, and more." msgstr "" #: ../../_templates_standalone/entrance.html:66 msgid "Auto-completion allows you to speed up your task." msgstr "" #: ../../_templates_standalone/entrance.html:78 msgid "Library included." msgstr "" #: ../../_templates_standalone/entrance.html:79 msgid "A built-in formula book allows to you to review and insert commonly used formulas, such as the volume of a cone." msgstr "" #: ../../_templates_standalone/entrance.html:80 msgid "Or insert one out of over 150 built-in scientific constants." msgstr "" #: ../../_templates_standalone/entrance.html:92 msgid "Cross-platform." msgstr "" #: ../../_templates_standalone/entrance.html:92 msgid "And multi-language." msgstr "" #: ../../_templates_standalone/entrance.html:93 msgid "SpeedCrunch is available for Windows, MacOS, and Linux, and comes in a number of languages." msgstr "" #: ../../_templates_standalone/entrance_navbar.html:7 msgid "Get It" msgstr "" #: ../../_templates_standalone/entrance_navbar.html:15 msgid "Help" msgstr "" #: ../../_templates_standalone/entrance_navbar.html:17 msgid "Report Bug / Request Feature" msgstr "" #: ../../_templates_standalone/entrance_navbar.html:18 msgid "Join Facebook Group" msgstr "" #: ../../_templates_standalone/entrance_navbar.html:19 msgid "Send Email" msgstr "" #: ../../_templates_standalone/entrance_navbar.html:20 msgid "Translate" msgstr "" #: ../../_templates_standalone/entrance_navbar.html:21 msgid "Code" msgstr "" #: ../../_templates_standalone/globaltoc.html:7 msgid "Navigation" msgstr "" #: ../../_templates_standalone/layout.html:136 msgid "Search within %(docstitle)s" msgstr "" #: ../../_templates_standalone/layout.html:145 msgid "About these documents" msgstr "" #: ../../_templates_standalone/layout.html:148 msgid "Index" msgstr "" #: ../../_templates_standalone/layout.html:151 msgid "Search" msgstr "" #: ../../_templates_standalone/layout.html:154 msgid "Copyright" msgstr "" #: ../../_templates_standalone/layout.html:213 msgid "© Copyright %(copyright)s." msgstr "" #: ../../_templates_standalone/layout.html:215 msgid "© Copyright %(copyright)s." msgstr "" #: ../../_templates_standalone/layout.html:219 msgid "Last updated on %(last_updated)s." msgstr "" #: ../../_templates_standalone/layout.html:222 msgid "Created using Sphinx %(sphinx_version)s." msgstr "" #: ../../_templates_standalone/relations.html:4 msgid "Previous Page: " msgstr "" #: ../../_templates_standalone/relations.html:7 msgid "Previous" msgstr "" #: ../../_templates_standalone/relations.html:13 msgid "Next Page: " msgstr "" #: ../../_templates_standalone/relations.html:14 msgid "Next" msgstr "" heldercorreia-speedcrunch-e7ca37f/doc/src/locale/pot/userguide.pot000066400000000000000000001621641526573132500254640ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2016, The SpeedCrunch Developers # This file is distributed under the same license as the SpeedCrunch package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: SpeedCrunch master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-23 20:56+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../../userguide/advanced.rst:2 msgid "User-Defined Variables and Functions" msgstr "" #: ../../userguide/advanced.rst:8 #: ../../userguide/interface.rst:26 msgid "Variables" msgstr "" #: ../../userguide/advanced.rst:10 msgid "When working on more sophisticated problems, you will likely find that you frequently need to access results from previous computations. As we have already seen, you can simply recall results from the result window. However, SpeedCrunch also offers another more powerful way: Variables. Variables allow you to store and recall any value, by assigning it a name. Variables are defined using the :samp:`{variable}={value}` syntax::" msgstr "" #: ../../userguide/advanced.rst:17 msgid "Now you can access this value via the name ``a`` much like you would use a built-in constant like :const:`pi`." msgstr "" #: ../../userguide/advanced.rst:19 msgid "Naturally, when assigning a value, the right-hand-side can be an arbitrarily complex expression::" msgstr "" #: ../../userguide/advanced.rst:33 msgid "As you see, using descriptive variable names can make the calculation history much more readable." msgstr "" #: ../../userguide/advanced.rst:39 msgid "User Functions" msgstr "" #: ../../userguide/advanced.rst:42 msgid "Just as you can define your own variables, it is also possible to define your own functions. While SpeedCrunch comes with an extensive collection of built-in functions (:ref:`sc:functionindex`), defining your own functions can be very useful when you find yourself repeating a similar computation over and over again." msgstr "" #: ../../userguide/advanced.rst:45 msgid "Defining a custom function is similar to defining a variable::" msgstr "" #: ../../userguide/advanced.rst:49 msgid "You can now use the new function ``f`` just like any of the built-in ones::" msgstr "" #: ../../userguide/advanced.rst:54 msgid "Functions with more arguments are possible as well; simply separate the parameters with a semicolon::" msgstr "" #: ../../userguide/advanced.rst:65 msgid "Complex numbers" msgstr "" #: ../../userguide/advanced.rst:68 msgid "SpeedCrunch supports calculations involving complex numbers. To use them, select :menuselection:`Settings --> Results --> Complex Numbers --> Cartesian` or :menuselection:`Polar`. The imaginary unit is now available under the name :const:`j`::" msgstr "" #: ../../userguide/advanced.rst:76 msgid "A note on the syntax of complex numbers: ``5j`` denotes the number ``5*j`` while ``j5`` is a variable named 'j5'. If necessary, consider writing the multiplication explicitly, i.e. ``j*5``." msgstr "" #: ../../userguide/advanced.rst:78 msgid "Some users (especially mathematicians or physicists) may prefer to use the letter ``i`` for the imaginary unit. Although SpeedCrunch does not support this notation by default, it is added easily enough. Simply defining ``i=j`` allows you to use ``i`` as an alias for :const:`j`." msgstr "" #: ../../userguide/advanced.rst:81 msgid "Not every function in SpeedCrunch supports complex arguments. Refer to a function's documentation for more information." msgstr "" #: ../../userguide/advanced.rst:83 msgid "Caution is advised when using functions like :func:`cbrt` or any fractional power operation with complex numbers. With complex number support enabled, the power operation ``x^(1/3)`` will return the first complex cubic root of ``x`` which is usually non-real. However, when given a real argument, :func:`cbrt` will *always* return the real cubic root, regardless of whether or not complex numbers are enabled." msgstr "" #: ../../userguide/advanced.rst:87 msgid "When complex numbers are disabled, the constant :const:`j` is not available. However, previously stored variables may still contain complex values. In that case, the imaginary part of these numbers is discarded when passing them as an argument to a built-in function." msgstr "" #: ../../userguide/advanced.rst:94 msgid "Units" msgstr "" #: ../../userguide/advanced.rst:97 msgid "SpeedCrunch includes a powerful system for units and unit conversions. It provides an extensive list of built-in units and easily allows you to define your own." msgstr "" #: ../../userguide/advanced.rst:99 msgid "Just as in common textbook notation, you specify a value's unit by multiplication::" msgstr "" #: ../../userguide/advanced.rst:104 msgid "Note that this is an actual multiplication internally. However, the ``*`` operator can often be omitted (using implicit multiplication), as shown by the previous example. By default SpeedCrunch converts the quantity into SI units::" msgstr "" #: ../../userguide/advanced.rst:111 msgid "This alone would not be terribly useful. However, it is possible to convert the value to a different unit using the conversion operator ``->`` (``in`` can be used as an alias)::" msgstr "" #: ../../userguide/advanced.rst:120 msgid "Note that all built-in unit names are singular and use American English spelling. This is independent of the language selected for SpeedCrunch's interface." msgstr "" #: ../../userguide/advanced.rst:122 msgid "As seen in the example above, you can use any SI prefix like ``kilo`` or ``centi``. They are treated like any other unit, so separate them with a space from the base unit they refer to." msgstr "" #: ../../userguide/advanced.rst:127 msgid "In SpeedCrunch (unlike in textbook notation), prefixes can be used on their own. This limitation (or feature, depending on your point of view) means that their use follows the same rules of precedence as any other mathematical operation. For instance, if you intend to express the unit 'newtons per centimeter', don't simply type ``newton / centi meter`` -- this will be interpreted as ``(newton / centi) meter``! Instead, make the order explicit by using ``newton / (centi meter)``." msgstr "" #: ../../userguide/advanced.rst:132 msgid "For the same reasons, expressions like ``500 gram / 20 gram`` and ``(500 gram) / (20 gram)`` yield different results." msgstr "" #: ../../userguide/advanced.rst:134 msgid "An important feature of SpeedCrunch's unit system is *dimensional checking*. Simply put, it prevents comparing apples and pears: If you try to convert seconds to meters, SpeedCrunch will complain, stating that the dimensions of ``second`` and ``meter`` do not match. Indeed, the dimension of ``second`` is *time*, while ``meter`` denotes a *length*, thus they cannot be compared, added, etc. When adding, multiplying, or otherwise manipulating units, SpeedCrunch will track the dimension and raise an error if it detects an invalid operation. For instance if you type ``meter^2``, the result will be a quantity with the dimension *length*\\ :sup:`2` which can only be compared to other quantities with the same dimension. Currently, the available dimensions and their associated primitive units are:" msgstr "" #: ../../userguide/advanced.rst:136 msgid "*Length*: ``meter``" msgstr "" #: ../../userguide/advanced.rst:137 msgid "*Mass*: ``kilogram``" msgstr "" #: ../../userguide/advanced.rst:138 msgid "*Time*: ``second``" msgstr "" #: ../../userguide/advanced.rst:139 msgid "*Electric current*: ``ampere``" msgstr "" #: ../../userguide/advanced.rst:140 msgid "*Amount*: ``mole``" msgstr "" #: ../../userguide/advanced.rst:141 msgid "*Luminous intensity*: ``candela``" msgstr "" #: ../../userguide/advanced.rst:142 msgid "*Temperature*: ``kelvin``" msgstr "" #: ../../userguide/advanced.rst:143 msgid "*Information*: ``bit``" msgstr "" #: ../../userguide/advanced.rst:145 msgid "Since the current unit system does not support non-linear units like °C or °F, the only available unit for temperature quantities is ``kelvin``. This might change in a future version of SpeedCrunch." msgstr "" #: ../../userguide/advanced.rst:148 msgid "Defining a custom unit works exactly like defining a variable::" msgstr "" #: ../../userguide/advanced.rst:155 msgid "In fact, any unit is simply a user-defined variable or a built-in constant. This also means that any variable or even expression can be used as the right-hand side of a conversion expression::" msgstr "" #: ../../userguide/advanced.rst:161 msgid "As mentioned above, the built-in units are spelled out to avoid ambiguity. However, this also means that longer expressions can become tedious to input and hard to read. If you find yourself using a particular set of units frequently, consider defining shorter aliases::" msgstr "" #: ../../userguide/advanced.rst:169 msgid "Some of the built-in functions are able to handle arguments with a dimension. Refer to the documentation of a particular function for more information." msgstr "" #: ../../userguide/first_steps.rst:2 msgid "First Steps" msgstr "" #: ../../userguide/first_steps.rst:4 msgid "SpeedCrunch is designed to be used via the keyboard. While an :ref:`on-screen keypad ` is available, it is disabled by default. The powerful keyboard interface is the recommended way to use SpeedCrunch to get the most out of it. However, the keypad can be enabled from: :menuselection:`View --> Keypad`." msgstr "" #: ../../userguide/first_steps.rst:14 msgid "All examples in this manual use a period (``.``) as the decimal separator. By default, SpeedCrunch will use your system's default decimal separator for output and will accept both a period and a comma (``,``) for input (:ref:`more details `). Depending on your settings, it may be necessary to replace the periods with the appropriate decimal separator when entering these examples into SpeedCrunch." msgstr "" #: ../../userguide/first_steps.rst:20 msgid "When starting SpeedCrunch for the first time, the interface may thus seem a little plain. Don't be fooled, it can easily be customized. At the bottom edge of the window, you see the the **input bar**, also called the **editor**, with a blinking cursor showing that it is ready to accept keystrokes. To try out SpeedCrunch, type::" msgstr "" #: ../../userguide/first_steps.rst:24 msgid "then hit :kbd:`Enter` to evaluate the expression. The result (along with the expression you just entered) will be displayed at the top of window::" msgstr "" #: ../../userguide/first_steps.rst:29 msgid "This region (called the **result window**) not only shows the result of your last calculation, it is a complete browsable history. Any previous input or result can be recalled by double-clicking the corresponding line." msgstr "" #: ../../userguide/first_steps.rst:31 msgid "Let's try this out. First, perform some more calculations so that more than one entry is displayed in the result window::" msgstr "" #: ../../userguide/first_steps.rst:39 msgid "Note how multiplication (``*``) takes precedence over addition (``+``) unless parentheses are used to specify a particular order of evaluation. If you now wish to continue working with one of the results, double-click e.g. the line ``= 300.756``. The input bar will be populated with this result. Similarly, you can also quickly recall previous input by double-clicking them in the result history. Alternatively, you can use the :kbd:`Up` and :kbd:`Down` arrow keys on your keyboard to recall previous expressions or use the mouse wheel for the same effect (the mouse cursor must be hovering over the editor for this to work, otherwise the result window will be scrolled)." msgstr "" #: ../../userguide/first_steps.rst:41 msgid "To continue the computation directly from the previous result, you can use the special variable ``ans`` which always holds the result of the last entry in the history. Try this::" msgstr "" #: ../../userguide/first_steps.rst:52 msgid "As you can see, ``ans`` provides a quick and easy way to access the previous result. Sometimes, SpeedCrunch can even insert ``ans`` for you: When you start a new expression with an operator (e.g. ``+``, ``-``, ``*``, ``/``, ``^``), ``ans`` will be prepended automatically. [#f1]_ To try it out, type ``7`` :kbd:`Enter` ``+3`` :kbd:`Enter`. SpeedCrunch expands this as follows::" msgstr "" #: ../../userguide/first_steps.rst:62 msgid "SpeedCrunch comes with a number of :ref:`mathematical constants ` like Ï€ that are available by typing their name::" msgstr "" #: ../../userguide/first_steps.rst:70 msgid "Let us finish this short introduction with a word about functions. SpeedCrunch comes with an extensive list of built-in mathematical functions which can be accessed by simply typing their name in the editor followed by any parameters (also called arguments) in parentheses::" msgstr "" #: ../../userguide/first_steps.rst:75 msgid "The function :func:`sqrt` calculates the square root of its argument. Some functions require or accept more than one argument. In that case, separate them with a semicolon (``;``)." msgstr "" #: ../../userguide/first_steps.rst:79 msgid "To repeat: In contrast to many programming languages, parameters in SpeedCrunch are separated by a **semicolon**!" msgstr "" #: ../../userguide/first_steps.rst:81 msgid "An example is the :func:`average` function::" msgstr "" #: ../../userguide/first_steps.rst:86 msgid "This is already enough to use SpeedCrunch effectively. Try it out for yourself! Alternatively, read on to learn about its more advanced features." msgstr "" #: ../../userguide/first_steps.rst:91 #: ../../userguide/interface.rst:328 msgid "Footnotes" msgstr "" #: ../../userguide/first_steps.rst:92 msgid "This requires that the :ref:`Automatic Result Reuse ` setting is enabled." msgstr "" #: ../../userguide/index.rst:2 msgid "User Guide" msgstr "" #: ../../userguide/index.rst:4 msgid "This part of the manual explains how to use SpeedCrunch, starting from the installation and continuing to in-depth descriptions of particular topics and features. It can be read in order or simply used to look up the details of a feature." msgstr "" #: ../../userguide/installation.rst:4 msgid "Installation" msgstr "" #: ../../userguide/installation.rst:7 msgid "Microsoft Windows" msgstr "" #: ../../userguide/installation.rst:9 msgid "SpeedCrunch for Windows requires Windows Vista or newer (32-bit and 64-bit versions). You can use choose to use either the installer or the portable version of SpeedCrunch. Both of these are available from `the SpeedCrunch website `_." msgstr "" #: ../../userguide/installation.rst:15 msgid "The installer installs SpeedCrunch on your system and creates an entry in the menu to launch it. This process requires administrator rights." msgstr "" #: ../../userguide/installation.rst:18 msgid "Alternatively, you may use the portable version of SpeedCrunch, which is distributed as a ``.zip`` archive. This version requires no installation, simply extract it to a folder of your choice and run :program:`speedcrunch.exe`. In addition, this version of the software is fully portable: It stores all its settings and user data next to the executable so the entire directory can be copied to another computer and run there." msgstr "" #: ../../userguide/installation.rst:33 msgid "Linux" msgstr "" #: ../../userguide/installation.rst:35 msgid "On Linux, SpeedCrunch can be installed either from packages provided by your distribution or from official Flatpak packages." msgstr "" #: ../../userguide/installation.rst:39 msgid "Distribution Packages" msgstr "" #: ../../userguide/installation.rst:41 msgid "Many Linux distributions already include packages for SpeedCrunch in their repositories. The exact steps to install these depend on the distribution. For example, on Debian and Ubuntu, the included SpeedCrunch package can be installed by running this command::" msgstr "" #: ../../userguide/installation.rst:47 msgid "On Fedora, this command will install SpeedCrunch::" msgstr "" #: ../../userguide/installation.rst:51 msgid "Check your system's documentation to find out how to install additional packages. Many desktop distributions also include graphical package management software that can be used to install SpeedCrunch." msgstr "" #: ../../userguide/installation.rst:57 msgid "Flatpak" msgstr "" #: ../../userguide/installation.rst:59 msgid "`Flatpak `_ is a distribution-independent packaging format for Linux desktop applications. The latest stable release of SpeedCrunch is available as a Flatpak package from `Flathub `_." msgstr "" #: ../../userguide/installation.rst:62 msgid "First, visit Flathub's `setup page `_ and follow the instructions for your distribution to set up Flatpak and Flathub. Then install SpeedCrunch from its `store page `_ on Flathub." msgstr "" #: ../../userguide/installation.rst:72 msgid "Development Builds" msgstr "" #: ../../userguide/installation.rst:76 msgid "Development builds of SpeedCrunch may not be as stable or well-tested as released versions and may contain changes that break your session history. Use them at your own risk." msgstr "" #: ../../userguide/installation.rst:79 msgid "Pre-built development versions of SpeedCrunch allow you to use newer features and bug-fixes before they become available in a release, without having to compile SpeedCrunch yourself. Currently, automatically updated development builds of SpeedCrunch are available for the following platforms:" msgstr "" #: ../../userguide/installation.rst:84 msgid "`Windows `_" msgstr "" #: ../../userguide/installation.rst:85 msgid "`Ubuntu `_ (16.04 and later)" msgstr "" #: ../../userguide/installation.rst:92 msgid "Building from Source" msgstr "" #: ../../userguide/installation.rst:94 msgid "The SpeedCrunch source code is maintained on `Bitbucket`_ in a Git repository. Clone the repository onto your machine by running the following command::" msgstr "" #: ../../userguide/installation.rst:101 msgid "The main readme file (:file:`README.md` at the root of the repository) contains instructions on how to compile SpeedCrunch." msgstr "" #: ../../userguide/interface.rst:2 msgid "User Interface" msgstr "" #: ../../userguide/interface.rst:5 msgid "Widgets" msgstr "" #: ../../userguide/interface.rst:7 msgid "Apart from the main display, SpeedCrunch offers a number of extra panels, referred to as *widgets* here. They can be enabled and disabled via the :menuselection:`View` menu." msgstr "" #: ../../userguide/interface.rst:14 msgid "Formula Book" msgstr "" #: ../../userguide/interface.rst:11 msgid "The formula book provides access to commonly used formulas and calculations. Simply insert a formula into the expression editor by clicking on it." msgstr "" #: ../../userguide/interface.rst:14 msgid "You can help expanding the formula book by posting your requests to the `issue tracker `_." msgstr "" #: ../../userguide/interface.rst:22 msgid "Constants" msgstr "" #: ../../userguide/interface.rst:17 msgid "The constants widget shows a list of over 150 scientific constants. Just double-click on an entry to paste it into the editor." msgstr "" #: ../../userguide/interface.rst:21 msgid "As of version 0.12, the constants have not yet been adapted to make use of the new unit system. All the inserted values thus lack a unit. This is likely to change in a future version." msgstr "" #: ../../userguide/interface.rst:25 msgid "The variables widget lists all :ref:`user-defined variables `. Any of them can be inserted into the editor by double-clicking it. Additionally, it is possible to delete a variable by selecting it and pressing the :kbd:`Delete` key on your keyboard." msgstr "" #: ../../userguide/interface.rst:29 msgid "Functions and User Functions" msgstr "" #: ../../userguide/interface.rst:29 msgid "Similar to the variables widget, these show built-in and :ref:`user-defined functions ` respectively." msgstr "" #: ../../userguide/interface.rst:35 msgid "Bit Field" msgstr "" #: ../../userguide/interface.rst:32 msgid "The bit field widget is designed to make working with binary numbers easier. It shows a field of 64 squares, each representing a bit in the current result. Any bit can be toggled by clicking its square; the resulting number is automatically inserted into the editor. Additional buttons allow you to shift, invert and reset all the bits at once. While the mouse cursor is hovering over the bit field, scrolling the mouse wheel will also shift the bits." msgstr "" #: ../../userguide/interface.rst:44 msgid "Keypad" msgstr "" #: ../../userguide/interface.rst:39 msgid "The on-screen keypad allows inputting numbers without using the keyboard. However, it is very limited and doesn't provide access to many of SpeedCrunch's more advanced features. For that reason, using SpeedCrunch's keyboard interface is recommended in place of using the keypad." msgstr "" #: ../../userguide/interface.rst:43 msgid "The keypad was removed in SpeedCrunch 0.11; however, it was added back in 0.12." msgstr "" #: ../../userguide/interface.rst:47 msgid "History" msgstr "" #: ../../userguide/interface.rst:47 msgid "The history widget lists all previous inputs. Double-click a line to recall it. Note that the main result display also provides this functionality." msgstr "" #: ../../userguide/interface.rst:53 msgid "Expression Editor Features" msgstr "" #: ../../userguide/interface.rst:55 msgid "The expression editor provides some advanced features:" msgstr "" #: ../../userguide/interface.rst:60 msgid "Autocompletion" msgstr "" #: ../../userguide/interface.rst:58 msgid "If you start typing a name (e.g. of a variable, function, or unit), a pop-up with matching names will appear. Pressing :kbd:`Tab` or :kbd:`Enter` will automatically insert the first suggestion. Alternatively, you can use the arrow keys or the mouse to select a different suggestion, or continue typing to refine the list." msgstr "" #: ../../userguide/interface.rst:64 msgid "Quick constant insertion" msgstr "" #: ../../userguide/interface.rst:63 msgid "Press :kbd:`Control+Space` to open a list of constants that allows quick access to the same constants as the constants widget (see above). Use the arrow keys to navigate the list." msgstr "" #: ../../userguide/interface.rst:69 msgid "Context help" msgstr "" #: ../../userguide/interface.rst:68 msgid "Pressing :kbd:`F1` will show the manual page for the function under the cursor, providing quick access to detailed usage information for a function. Pressing :kbd:`Escape` will dismiss the manual window again." msgstr "" #: ../../userguide/interface.rst:74 msgid "Selection results" msgstr "" #: ../../userguide/interface.rst:72 msgid "If :menuselection:`Settings --> Behavior --> Partial Results` is enabled, selecting a partial expression in the expression editor will show you the result of the selected expression." msgstr "" #: ../../userguide/interface.rst:77 msgid "Import/Export" msgstr "" #: ../../userguide/interface.rst:79 msgid "SpeedCrunch can save/export your session in a number of ways. The :menuselection:`Session --> Save` and :menuselection:`Session --> Load` menu entries allow you to easily save and restore your entire SpeedCrunch session. The data is stored in a SpeedCrunch-specific file format. [#f1]_ While the session files are human-readable, they are designed for use by SpeedCrunch. If you want to export your calculations to work on them in another program or hand them to a colleague, the other export options are preferable." msgstr "" #: ../../userguide/interface.rst:84 msgid "You can save the session as HTML (:menuselection:`Session --> Export --> HTML`). The resulting file will consist of the contents of the result display and can be viewed in any web browser. This feature can also be used to print a SpeedCrunch session by printing the exported HTML document. Since the syntax highlighting and color scheme are maintained in the HTML output, it is recommended to select a color scheme with a white background (e.g. *Standard*) prior to exporting if you intend to print the document." msgstr "" #: ../../userguide/interface.rst:89 msgid "The final, most basic option is to export your session as a plain text file (:menuselection:`Session --> Export --> Plain text`). In contrast to the HTML export option, the syntax highlighting will be lost." msgstr "" #: ../../userguide/interface.rst:92 msgid "SpeedCrunch also offers capabilities to *import* a session from a text file (:menuselection:`Session --> Import`). Select any plain text file and SpeedCrunch will try to evaluate each line of the file as if the user entered it directly." msgstr "" #: ../../userguide/interface.rst:97 msgid "Settings" msgstr "" #: ../../userguide/interface.rst:99 msgid "SpeedCrunch's behavior can be customized to a large degree using the configuration options in the :menuselection:`Settings` menu. This section explains the settings that are available." msgstr "" #: ../../userguide/interface.rst:105 msgid "Result Format" msgstr "" #: ../../userguide/interface.rst:107 msgid "This section allows selecting the result format to use. You can select one of the following formats:" msgstr "" #: ../../userguide/interface.rst:111 msgid ":menuselection:`Decimal --> General`" msgstr "" #: ../../userguide/interface.rst:111 msgid "Use fixed decimal form for most results; for very large (more than six integer places) or very small results (less than 0.0001), scientific notation will be used." msgstr "" #: ../../userguide/interface.rst:114 msgid ":menuselection:`Decimal --> Fixed Decimal`" msgstr "" #: ../../userguide/interface.rst:114 msgid "Display results in fixed decimal form. For excessively large or small numbers, this format may still fall back to scientific notation." msgstr "" #: ../../userguide/interface.rst:117 msgid ":menuselection:`Decimal --> Engineering`" msgstr "" #: ../../userguide/interface.rst:117 msgid "Display results in engineering notation. This is a variant of :ref:`scientific notation ` in which the exponent is divisible by three." msgstr "" #: ../../userguide/interface.rst:119 msgid ":menuselection:`Decimal --> Scientific`" msgstr "" #: ../../userguide/interface.rst:120 msgid "Display results in :ref:`normalized scientific notation `." msgstr "" #: ../../userguide/interface.rst:121 msgid ":menuselection:`Binary`" msgstr "" #: ../../userguide/interface.rst:122 msgid "Display results as binary numbers, i.e. in base-2." msgstr "" #: ../../userguide/interface.rst:123 msgid ":menuselection:`Octal`" msgstr "" #: ../../userguide/interface.rst:124 msgid "Display all results as octal numbers, i.e. in base-8." msgstr "" #: ../../userguide/interface.rst:125 msgid ":menuselection:`Hexadecimal`" msgstr "" #: ../../userguide/interface.rst:126 msgid "Display all results as hexadecimal numbers, i.e. in base-16." msgstr "" #: ../../userguide/interface.rst:128 msgid ":menuselection:`Sexagesimal`" msgstr "" #: ../../userguide/interface.rst:128 msgid "Display dimensionless and time results as :ref:`sexagesimal values `, i.e. with minutes and seconds. All other results are displayed in fixed decimal form." msgstr "" #: ../../userguide/interface.rst:130 msgid "In addition to the main result format, some further options are available to customize the result output:" msgstr "" #: ../../userguide/interface.rst:137 msgid ":menuselection:`Precision`" msgstr "" #: ../../userguide/interface.rst:134 msgid "Select the number of fractional digits to display. **Automatic** always displays as many digits as are necessary to represent the number precisely. The other settings explicitly specify a certain number of digits and will append additional zeroes to the fraction to reach that number of digits, if necessary." msgstr "" #: ../../userguide/interface.rst:140 msgid "Input Format" msgstr "" #: ../../userguide/interface.rst:142 msgid "This section allows selecting the input format to use." msgstr "" #: ../../userguide/interface.rst:151 msgid ":menuselection:`Radix Character`" msgstr "" #: ../../userguide/interface.rst:147 msgid "Select the decimal separator to use in inputs and results. This can either be explicitly set to dot (``.``), or comma (``,``), or both, or system default. When both dot and comma are used, the decimal separator is detected automatically in inputs and the system default is used in results. With that latter mode, mixing both dot and comma in a same number to express the decimal separator and digit group separators is supported, but might lead to unexpected results." msgstr "" #: ../../userguide/interface.rst:154 msgid "Angle Mode" msgstr "" #: ../../userguide/interface.rst:156 msgid "Select the angular unit to be used in calculations. For functions that operate on angles, notably the :ref:`trigonometric functions ` like :func:`sin` or :func:`cos`, this setting determines the angle format of the arguments." msgstr "" #: ../../userguide/interface.rst:160 msgid ":menuselection:`Radian`" msgstr "" #: ../../userguide/interface.rst:161 msgid "Use radians for angles. A full circle corresponds to an angle of 2Ï€ radians." msgstr "" #: ../../userguide/interface.rst:162 msgid ":menuselection:`Degree`" msgstr "" #: ../../userguide/interface.rst:163 msgid "Use degrees for angles. A full circle corresponds to an angle of 360°." msgstr "" #: ../../userguide/interface.rst:167 msgid ":menuselection:`Gradian`" msgstr "" #: ../../userguide/interface.rst:165 msgid "Use gradians for angles. A full circle corresponds to an angle of 400 gradians." msgstr "" #: ../../userguide/interface.rst:171 msgid "Behavior" msgstr "" #: ../../userguide/interface.rst:176 msgid "This section contains several settings that allow you to further configure SpeedCrunch's behavior." msgstr "" #: ../../userguide/interface.rst:179 msgid ":menuselection:`Save History on Exit`" msgstr "" #: ../../userguide/interface.rst:179 msgid "Controls if the calculation history is automatically saved when SpeedCrunch exits and restored when it is launched again." msgstr "" #: ../../userguide/interface.rst:181 msgid ":menuselection:`Save Window Position on Exit`" msgstr "" #: ../../userguide/interface.rst:182 msgid "Controls if the window position is saved and restored." msgstr "" #: ../../userguide/interface.rst:185 msgid ":menuselection:`Partial Results`" msgstr "" #: ../../userguide/interface.rst:184 msgid "If set, SpeedCrunch will display partial results as you type your expression as well as results when selecting a partial expression in the editor." msgstr "" #: ../../userguide/interface.rst:189 msgid ":menuselection:`Automatic Result Reuse`" msgstr "" #: ../../userguide/interface.rst:189 msgid "This setting allows you to quickly continue typing after evaluating an expression by inserting `ans` into the editor if necessary." msgstr "" #: ../../userguide/interface.rst:191 msgid ":menuselection:`Automatic Completion`" msgstr "" #: ../../userguide/interface.rst:192 msgid "Completely enables or disables autocompletion." msgstr "" #: ../../userguide/interface.rst:193 msgid ":menuselection:`Syntax Highlighting`" msgstr "" #: ../../userguide/interface.rst:194 msgid "Enables or disables syntax highlighting." msgstr "" #: ../../userguide/interface.rst:196 msgid ":menuselection:`Digit Grouping`" msgstr "" #: ../../userguide/interface.rst:196 msgid "Visually group digits in long numbers. Requires :menuselection:`Settings --> Behavior --> Syntax Highlighting` to be enabled." msgstr "" #: ../../userguide/interface.rst:198 msgid ":menuselection:`Leave Last Expression`" msgstr "" #: ../../userguide/interface.rst:199 msgid "If selected, the entered expression remains in the editor after evaluating it." msgstr "" #: ../../userguide/interface.rst:201 msgid ":menuselection:`Complex Numbers --> Disabled`, :menuselection:`Complex Numbers --> Cartesian`, and :menuselection:`Complex Numbers --> Polar`" msgstr "" #: ../../userguide/interface.rst:201 msgid "Select the complex-number mode. ``Disabled`` turns off support for :ref:`complex numbers ` (so :const:`j` is undefined and expressions such as ``sqrt(-1)`` fail). ``Cartesian`` and ``Polar`` both enable complex-number support and choose how complex results are displayed. ``Disabled`` is the default." msgstr "" #: ../../userguide/interface.rst:203 msgid ":menuselection:`Always on Top`" msgstr "" #: ../../userguide/interface.rst:204 msgid "Keep the SpeedCrunch window on top of other windows." msgstr "" #: ../../userguide/interface.rst:207 msgid ":menuselection:`Automatic Result to Clipboard`" msgstr "" #: ../../userguide/interface.rst:206 msgid "Automatically copy the result to the clipboard whenever an expression is evaluated." msgstr "" #: ../../userguide/interface.rst:210 msgid "User Interface Settings" msgstr "" #: ../../userguide/interface.rst:213 msgid ":menuselection:`Settings --> Display --> Color Scheme`" msgstr "" #: ../../userguide/interface.rst:213 msgid "Select a color scheme. See :ref:`color_schemes` for information on how to install additional color schemes so they are displayed in this menu." msgstr "" #: ../../userguide/interface.rst:215 msgid ":menuselection:`Settings --> Display --> Font`" msgstr "" #: ../../userguide/interface.rst:216 msgid "Select the font to use for the expression editor and result display." msgstr "" #: ../../userguide/interface.rst:219 msgid ":menuselection:`Settings --> Language`" msgstr "" #: ../../userguide/interface.rst:218 msgid "Select the user interface language." msgstr "" #: ../../userguide/interface.rst:222 msgid "Keyboard Shortcuts" msgstr "" #: ../../userguide/interface.rst:225 msgid "Editing" msgstr "" #: ../../userguide/interface.rst:226 msgid ":kbd:`Control+L`" msgstr "" #: ../../userguide/interface.rst:227 msgid "Load session." msgstr "" #: ../../userguide/interface.rst:228 msgid ":kbd:`Control+S`" msgstr "" #: ../../userguide/interface.rst:229 msgid "Save session." msgstr "" #: ../../userguide/interface.rst:230 msgid ":kbd:`Control+Q`" msgstr "" #: ../../userguide/interface.rst:231 msgid "Quit SpeedCrunch." msgstr "" #: ../../userguide/interface.rst:232 msgid ":kbd:`Escape`" msgstr "" #: ../../userguide/interface.rst:233 msgid "Clear expression." msgstr "" #: ../../userguide/interface.rst:234 msgid ":kbd:`Control+N`" msgstr "" #: ../../userguide/interface.rst:235 msgid "Clear history." msgstr "" #: ../../userguide/interface.rst:236 msgid ":kbd:`Control+C`" msgstr "" #: ../../userguide/interface.rst:237 msgid "Copy selected text to clipboard." msgstr "" #: ../../userguide/interface.rst:238 msgid ":kbd:`Control+R`" msgstr "" #: ../../userguide/interface.rst:239 msgid "Copy last result to clipboard." msgstr "" #: ../../userguide/interface.rst:240 msgid ":kbd:`Control+V`" msgstr "" #: ../../userguide/interface.rst:241 msgid "Paste from clipboard." msgstr "" #: ../../userguide/interface.rst:242 msgid ":kbd:`Control+A`" msgstr "" #: ../../userguide/interface.rst:243 msgid "Select entire expression." msgstr "" #: ../../userguide/interface.rst:245 msgid ":kbd:`Control+P`" msgstr "" #: ../../userguide/interface.rst:245 msgid "Wrap the current selection in parentheses. If no text is selected, the entire expression is wrapped." msgstr "" #: ../../userguide/interface.rst:248 msgid "Widgets and Docks" msgstr "" #: ../../userguide/interface.rst:250 msgid ":kbd:`Control+1`" msgstr "" #: ../../userguide/interface.rst:251 msgid "Show/hide formula book." msgstr "" #: ../../userguide/interface.rst:252 msgid ":kbd:`Control+2`" msgstr "" #: ../../userguide/interface.rst:253 msgid "Show/hide constants widget." msgstr "" #: ../../userguide/interface.rst:254 msgid ":kbd:`Control+3`" msgstr "" #: ../../userguide/interface.rst:255 msgid "Show/hide functions widgets." msgstr "" #: ../../userguide/interface.rst:256 msgid ":kbd:`Control+4`" msgstr "" #: ../../userguide/interface.rst:257 msgid "Show/hide variables widget." msgstr "" #: ../../userguide/interface.rst:258 msgid ":kbd:`Control+5`" msgstr "" #: ../../userguide/interface.rst:259 msgid "Show/hide user functions widget." msgstr "" #: ../../userguide/interface.rst:260 msgid ":kbd:`Control+6`" msgstr "" #: ../../userguide/interface.rst:261 msgid "Show/hide bit field widget." msgstr "" #: ../../userguide/interface.rst:262 msgid ":kbd:`Control+7`" msgstr "" #: ../../userguide/interface.rst:263 msgid "Show/hide history widget." msgstr "" #: ../../userguide/interface.rst:264 msgid ":kbd:`Control+B`" msgstr "" #: ../../userguide/interface.rst:265 msgid "Show/hide the status bar." msgstr "" #: ../../userguide/interface.rst:267 msgid ":kbd:`Control+K`" msgstr "" #: ../../userguide/interface.rst:267 msgid "Show/hide the keypad." msgstr "" #: ../../userguide/interface.rst:270 msgid "Scrolling" msgstr "" #: ../../userguide/interface.rst:272 msgid ":kbd:`Page Up` and :kbd:`Page Down`" msgstr "" #: ../../userguide/interface.rst:273 msgid "Scroll the result window page-wise." msgstr "" #: ../../userguide/interface.rst:274 msgid ":kbd:`Shift+Page Up` and :kbd:`Shift+Page Down`" msgstr "" #: ../../userguide/interface.rst:275 msgid "Scroll the result window line-wise." msgstr "" #: ../../userguide/interface.rst:278 msgid ":kbd:`Control+Page Up` and :kbd:`Control+Page Down`" msgstr "" #: ../../userguide/interface.rst:277 msgid "Scroll to the top or bottom of the result window." msgstr "" #: ../../userguide/interface.rst:281 msgid "Format" msgstr "" #: ../../userguide/interface.rst:283 msgid ":kbd:`F2`" msgstr "" #: ../../userguide/interface.rst:284 msgid "Set result format to general decimal." msgstr "" #: ../../userguide/interface.rst:285 msgid ":kbd:`F3`" msgstr "" #: ../../userguide/interface.rst:286 msgid "Set result format to fixed decimal." msgstr "" #: ../../userguide/interface.rst:287 msgid ":kbd:`F4`" msgstr "" #: ../../userguide/interface.rst:288 msgid "Set result format to engineering decimal." msgstr "" #: ../../userguide/interface.rst:289 msgid ":kbd:`F5`" msgstr "" #: ../../userguide/interface.rst:290 msgid "Set result format to scientific decimal." msgstr "" #: ../../userguide/interface.rst:291 msgid ":kbd:`F6`" msgstr "" #: ../../userguide/interface.rst:292 msgid "Set result format to binary." msgstr "" #: ../../userguide/interface.rst:293 msgid ":kbd:`F7`" msgstr "" #: ../../userguide/interface.rst:294 msgid "Set result format to octal." msgstr "" #: ../../userguide/interface.rst:295 msgid ":kbd:`F8`" msgstr "" #: ../../userguide/interface.rst:296 msgid "Set result format to hexadecimal." msgstr "" #: ../../userguide/interface.rst:300 msgid ":kbd:`F9`" msgstr "" #: ../../userguide/interface.rst:298 msgid "Set result format to sexagesimal." msgstr "" #: ../../userguide/interface.rst:304 msgid ":kbd:`Control+.`" msgstr "" #: ../../userguide/interface.rst:305 msgid "Use a period as decimal separator." msgstr "" #: ../../userguide/interface.rst:307 msgid ":kbd:`Control+,`" msgstr "" #: ../../userguide/interface.rst:307 msgid "Use a comma as decimal separator." msgstr "" #: ../../userguide/interface.rst:310 msgid "Various" msgstr "" #: ../../userguide/interface.rst:315 msgid ":kbd:`F1`" msgstr "" #: ../../userguide/interface.rst:313 msgid "Show context help (dismiss with :kbd:`Escape`)." msgstr "" #: ../../userguide/interface.rst:317 msgid ":kbd:`F11`" msgstr "" #: ../../userguide/interface.rst:318 msgid "Toggle full screen." msgstr "" #: ../../userguide/interface.rst:319 msgid ":kbd:`Control` + mouse wheel, :kbd:`Shift` + mouse wheel, or :kbd:`Shift+Up` and :kbd:`Shift+Down`" msgstr "" #: ../../userguide/interface.rst:320 msgid "Change the font size." msgstr "" #: ../../userguide/interface.rst:325 msgid ":kbd:`Control+Shift` + mouse wheel" msgstr "" #: ../../userguide/interface.rst:322 msgid "Change the window opacity." msgstr "" #: ../../userguide/interface.rst:329 msgid "Starting with SpeedCrunch 0.12, the session format is based on `JSON `_. Previous versions used a simple custom text format." msgstr "" #: ../../userguide/syntax.rst:2 msgid "Syntax" msgstr "" #: ../../userguide/syntax.rst:4 msgid "This part of the documentation explains the syntax of valid SpeedCrunch input. As you will see, SpeedCrunch honors most conventions for mathematical expressions. You will find using SpeedCrunch to be very natural and intuitive, especially so if you are already familiar with a programming language." msgstr "" #: ../../userguide/syntax.rst:8 msgid "Number Notation" msgstr "" #: ../../userguide/syntax.rst:11 msgid "Decimal Form" msgstr "" #: ../../userguide/syntax.rst:13 msgid "When you would like to specify a non-integer value, simply enter the number as you would write it on paper, with either a period (``.``) or a comma (``,``) as the decimal separator. By default, these can be used interchangeably, i.e. both ``1.234`` and ``1,234`` represent the same number. However, this behavior can be changed; see :ref:`Radix Character ` for more information." msgstr "" #: ../../userguide/syntax.rst:18 msgid "Trailing zeros after the decimal point (like in ``12.300``) or leading zeros before it (``0012.3``) are redundant and can be included or omitted to the user's preference. Expressions like ``.5`` as a shorthand notation for ``0.5`` are also permitted." msgstr "" #: ../../userguide/syntax.rst:24 msgid "Scientific Notation" msgstr "" #: ../../userguide/syntax.rst:26 msgid "When dealing with very small or very large numbers (think the size of an atom or of a galaxy) the notation above is inconvenient. These are more commonly expressed in scientific notation; for instance, 1.234*10\\ :sup:`-9` is preferable to 0.000000001234." msgstr "" #: ../../userguide/syntax.rst:28 msgid "Naturally, in SpeedCrunch this could be written as ``1.234*10^-9``, but there's also a shorthand notation: ``1.234e-9``. Here, the ``e`` represents ``*10^``, but it is considered a part of the number literal and treated with higher precedence. For example, ``1e2^3`` is equivalent to ``(1e2)^3 = 100^3``. The scale of a number (sometimes called its exponent) always begins with the scale character ``E`` or ``e`` followed by a signed integer. So ``e+10``, ``e-4``, ``E-0`` are all valid scale expressions. If the sign is '+', you may simply omit it: ``e0``, ``E10``. The significand (i.e. the part preceding the exponent) is required; exactly one exponent must be specified." msgstr "" #: ../../userguide/syntax.rst:30 msgid "Compared to most calculators, SpeedCrunch can accept very large numbers without overflowing (e.g. both ``1e+536870911`` and ``1e-536870911`` are still valid). However, only about 78 significant digits are stored at any point. Any digits beyond that are lost." msgstr "" #: ../../userguide/syntax.rst:33 msgid "Non-Decimal Bases" msgstr "" #: ../../userguide/syntax.rst:35 msgid "In addition to decimal (base-10) numbers, SpeedCrunch provides support for binary (base-2), octal (base-8) and hexadecimal (base-16) numbers. You can enter a number in any of these bases by marking it with the corresponding prefix:" msgstr "" #: ../../userguide/syntax.rst:38 msgid "``0b`` or ``0B`` for **binary**, e.g. ``0b10010``." msgstr "" #: ../../userguide/syntax.rst:39 msgid "``0o`` or ``0O`` for **octal**, e.g. ``0o1412``." msgstr "" #: ../../userguide/syntax.rst:40 msgid "``0d`` or ``0D`` for **decimal**. These can be omitted since decimal is the default base." msgstr "" #: ../../userguide/syntax.rst:41 msgid "``0x``, ``0X``, or ``#`` for **hexadecimal**. The additional six digits are represented by the upper or lower case letters ``a`` to ``f``, e.g. ``0xdeadbeef`` or ``0xDEADBEEF``." msgstr "" #: ../../userguide/syntax.rst:43 msgid "You may even enter fractional values in any of these bases. Note that scientific notation is not supported for non-decimal bases, however. Examples::" msgstr "" #: ../../userguide/syntax.rst:52 msgid "To have SpeedCrunch output its results in a base other than decimal, you may use one of the functions :func:`bin`, :func:`oct`, :func:`dec`, or :func:`hex`::" msgstr "" #: ../../userguide/syntax.rst:57 msgid "The effect of these functions only applies to the immediate result and doesn't carry to future operations::" msgstr "" #: ../../userguide/syntax.rst:63 msgid "To change the base that is used for displaying results, select one of the corresponding settings in :menuselection:`Settings --> Result Format`." msgstr "" #: ../../userguide/syntax.rst:65 msgid "SpeedCrunch stores integers with a precision of up to 256 bits. Since this would be unwieldy, the binary representation of a negative number in SpeedCrunch is *not* its two's complement. Instead, like with other bases, the value and the sign are represented separately::" msgstr "" #: ../../userguide/syntax.rst:72 msgid "See :func:`mask` and :func:`unmask` to convert a negative number into the two's complement form." msgstr "" #: ../../userguide/syntax.rst:74 msgid "Any integer larger than the 256-bit limit will be silently converted into a floating point number, making it susceptible to rounding errors. To specify large integers, using the shift operators (``1 << n``) is preferable to exponentiation (``2 ^ n``) as the latter are floating point calculations and thus susceptible to rounding errors." msgstr "" #: ../../userguide/syntax.rst:82 msgid "Sexagesimal Values" msgstr "" #: ../../userguide/syntax.rst:86 msgid "Sexagesimal values in SpeedCrunch are angle degrees or time values represented with minutes and seconds." msgstr "" #: ../../userguide/syntax.rst:88 msgid "When sexagesimal mode is selected in :menuselection:`Settings --> Result Format`, dimensionless and time results are displayed as sexagesimal values. All other results are displayed as fixed decimal values. Actual sexagesimal math depends on the result. Dimensionless results are handled as degrees with minutes and seconds generated from the decimal part. With time dimension results, base unit is second and the integer part is divided to minutes and hours." msgstr "" #: ../../userguide/syntax.rst:90 msgid "In input, characters ``°`` (degree), ``:`` (colon), ``'`` (single quote) and ``\"`` (double quote) can be used for entering sexagesimal values. Degree sign ``°`` separates degrees and minutes. First colon character ``:`` separates hours and minutes. Single quote ``'`` or second colon character ``:`` separates minutes and seconds. Additionally, postfix double quote ``\"`` can be used as an arc second unit. Because the degree sign is difficult to produce from keyboard, at sign ``@`` is automatically converted to it." msgstr "" #: ../../userguide/syntax.rst:92 msgid "Amount of minutes or seconds is not limited to values below 60. It is possible to input time 90 minutes after noon::" msgstr "" #: ../../userguide/syntax.rst:97 msgid "Dimensionless input values are automatically considered to be in current angle mode. For example, in radian mode::" msgstr "" #: ../../userguide/syntax.rst:102 msgid "Only last part of sexagesimal input value can contain decimals." msgstr "" #: ../../userguide/syntax.rst:104 msgid "Following tables show some possible input notations and their results in both fixed decimal and sexagesimal modes:" msgstr "" #: ../../userguide/syntax.rst:107 #: ../../userguide/syntax.rst:126 msgid "Input" msgstr "" #: ../../userguide/syntax.rst:107 #: ../../userguide/syntax.rst:126 msgid "Fixed Decimal" msgstr "" #: ../../userguide/syntax.rst:107 #: ../../userguide/syntax.rst:126 msgid "Sexagesimal" msgstr "" #: ../../userguide/syntax.rst:109 msgid "``0``" msgstr "" #: ../../userguide/syntax.rst:109 msgid "``0°00'00``" msgstr "" #: ../../userguide/syntax.rst:110 msgid "``°'56``" msgstr "" #: ../../userguide/syntax.rst:110 #: ../../userguide/syntax.rst:111 #: ../../userguide/syntax.rst:112 msgid "``0.01555556``" msgstr "" #: ../../userguide/syntax.rst:110 #: ../../userguide/syntax.rst:111 #: ../../userguide/syntax.rst:112 msgid "``0°00'56.00``" msgstr "" #: ../../userguide/syntax.rst:111 msgid "``56\"``" msgstr "" #: ../../userguide/syntax.rst:112 msgid "``56 arcsecond``" msgstr "" #: ../../userguide/syntax.rst:113 msgid "``56.78\"``" msgstr "" #: ../../userguide/syntax.rst:113 msgid "``0.01577222``" msgstr "" #: ../../userguide/syntax.rst:113 msgid "``0°00'56.78``" msgstr "" #: ../../userguide/syntax.rst:114 msgid "``°34``" msgstr "" #: ../../userguide/syntax.rst:114 #: ../../userguide/syntax.rst:115 #: ../../userguide/syntax.rst:116 msgid "``0.56666667``" msgstr "" #: ../../userguide/syntax.rst:114 #: ../../userguide/syntax.rst:115 #: ../../userguide/syntax.rst:116 msgid "``0°34'00.00``" msgstr "" #: ../../userguide/syntax.rst:115 msgid "``34'``" msgstr "" #: ../../userguide/syntax.rst:116 msgid "``34 arcminute``" msgstr "" #: ../../userguide/syntax.rst:117 msgid "``34'56``" msgstr "" #: ../../userguide/syntax.rst:117 msgid "``0.58222222``" msgstr "" #: ../../userguide/syntax.rst:117 msgid "``0°34'56.00``" msgstr "" #: ../../userguide/syntax.rst:118 msgid "``12°``" msgstr "" #: ../../userguide/syntax.rst:118 msgid "``12.00000000``" msgstr "" #: ../../userguide/syntax.rst:118 msgid "``12°00'00.00``" msgstr "" #: ../../userguide/syntax.rst:119 msgid "``12°34``" msgstr "" #: ../../userguide/syntax.rst:119 msgid "``12.56666667``" msgstr "" #: ../../userguide/syntax.rst:119 msgid "``12°34'00.00``" msgstr "" #: ../../userguide/syntax.rst:120 msgid "``12°34.5``" msgstr "" #: ../../userguide/syntax.rst:120 msgid "``12.57500000``" msgstr "" #: ../../userguide/syntax.rst:120 msgid "``12°34'30.00``" msgstr "" #: ../../userguide/syntax.rst:121 msgid "``12°34'56``" msgstr "" #: ../../userguide/syntax.rst:121 msgid "``12.58222222``" msgstr "" #: ../../userguide/syntax.rst:121 msgid "``12°34'56.00``" msgstr "" #: ../../userguide/syntax.rst:122 msgid "``12°34'56.78``" msgstr "" #: ../../userguide/syntax.rst:122 msgid "``12.58243889``" msgstr "" #: ../../userguide/syntax.rst:128 msgid "``0 second``" msgstr "" #: ../../userguide/syntax.rst:128 msgid "``0:00:00``" msgstr "" #: ../../userguide/syntax.rst:129 msgid "``::56``" msgstr "" #: ../../userguide/syntax.rst:129 #: ../../userguide/syntax.rst:130 msgid "``56.00 second``" msgstr "" #: ../../userguide/syntax.rst:129 #: ../../userguide/syntax.rst:130 msgid "``0:00:56.00``" msgstr "" #: ../../userguide/syntax.rst:130 msgid "``56 second``" msgstr "" #: ../../userguide/syntax.rst:131 msgid "``:34``" msgstr "" #: ../../userguide/syntax.rst:131 #: ../../userguide/syntax.rst:132 msgid "``2040.00 second``" msgstr "" #: ../../userguide/syntax.rst:131 #: ../../userguide/syntax.rst:132 msgid "``0:34:00.00``" msgstr "" #: ../../userguide/syntax.rst:132 msgid "``34 minute``" msgstr "" #: ../../userguide/syntax.rst:133 msgid "``12:``" msgstr "" #: ../../userguide/syntax.rst:133 #: ../../userguide/syntax.rst:134 msgid "``43200.00 second``" msgstr "" #: ../../userguide/syntax.rst:133 #: ../../userguide/syntax.rst:134 msgid "``12:00:00.00``" msgstr "" #: ../../userguide/syntax.rst:134 msgid "``12 hour``" msgstr "" #: ../../userguide/syntax.rst:135 msgid "``12:34``" msgstr "" #: ../../userguide/syntax.rst:135 msgid "``45240.00 second``" msgstr "" #: ../../userguide/syntax.rst:135 msgid "``12:34:00.00``" msgstr "" #: ../../userguide/syntax.rst:136 msgid "``12:34.5``" msgstr "" #: ../../userguide/syntax.rst:136 msgid "``45270.00 second``" msgstr "" #: ../../userguide/syntax.rst:136 msgid "``12:34:30.00``" msgstr "" #: ../../userguide/syntax.rst:137 msgid "``12:34:56``" msgstr "" #: ../../userguide/syntax.rst:137 msgid "``45296.00 second``" msgstr "" #: ../../userguide/syntax.rst:137 msgid "``12:34:56.00``" msgstr "" #: ../../userguide/syntax.rst:138 msgid "``12:34:56.78``" msgstr "" #: ../../userguide/syntax.rst:138 msgid "``45296.78 second``" msgstr "" #: ../../userguide/syntax.rst:141 msgid "Note that when entering time values with colons, no additional dimension units are needed. Formatting itself works as an unit." msgstr "" #: ../../userguide/syntax.rst:144 msgid "Operators and Precedence" msgstr "" #: ../../userguide/syntax.rst:146 msgid "When writing an expression like ``10+5*4``, which operation will be executed first? The common rules of operator precedence tell us that in this case multipication shall be computed first, hence the result is ``30``. We also distinguish **unary** operators (which act on a single number/operand) and **binary** operators (which link two operands)." msgstr "" #: ../../userguide/syntax.rst:148 msgid "SpeedCrunch supports the following operators, listed in order of decreasing precedence:" msgstr "" #: ../../userguide/syntax.rst:156 #: ../../userguide/syntax.rst:227 msgid "Operator" msgstr "" #: ../../userguide/syntax.rst:156 #: ../../userguide/syntax.rst:227 msgid "Description" msgstr "" #: ../../userguide/syntax.rst:156 #: ../../userguide/syntax.rst:227 msgid "Examples" msgstr "" #: ../../userguide/syntax.rst:158 msgid "``(...)``" msgstr "" #: ../../userguide/syntax.rst:159 msgid "**Parentheses**" msgstr "" #: ../../userguide/syntax.rst:159 msgid "Parentheses mark precedence explicitly." msgstr "" #: ../../userguide/syntax.rst:158 msgid "``(2+3)*4 = 5*4 = 20``" msgstr "" #: ../../userguide/syntax.rst:162 msgid "``x!``" msgstr "" #: ../../userguide/syntax.rst:163 msgid "**Factorial**" msgstr "" #: ../../userguide/syntax.rst:163 msgid "Computes the factorial of its argument. See also :func:`gamma()`." msgstr "" #: ../../userguide/syntax.rst:162 msgid "``5! = 120``" msgstr "" #: ../../userguide/syntax.rst:166 msgid "``a ^ b``, ``a ** b``" msgstr "" #: ../../userguide/syntax.rst:169 msgid "**Exponentiation**" msgstr "" #: ../../userguide/syntax.rst:167 msgid "Both variants are equivalent. Note that the power operation is *right-associative*, i.e. it is evaluated from right to left." msgstr "" #: ../../userguide/syntax.rst:169 msgid "``2^2^3 = 2^8 = 256``" msgstr "" #: ../../userguide/syntax.rst:172 msgid "``+x``, ``-x``" msgstr "" #: ../../userguide/syntax.rst:172 msgid "**Unary plus and minus**" msgstr "" #: ../../userguide/syntax.rst:172 msgid "``--5 = +5``" msgstr "" #: ../../userguide/syntax.rst:174 msgid "``a \\ b``" msgstr "" #: ../../userguide/syntax.rst:175 msgid "**Integer division**" msgstr "" #: ../../userguide/syntax.rst:175 msgid "Divides the operands and truncates the result to an integer." msgstr "" #: ../../userguide/syntax.rst:174 msgid "``5\\4 = 1``" msgstr "" #: ../../userguide/syntax.rst:178 msgid "``a * b``, ``a b``, ``a / b``" msgstr "" #: ../../userguide/syntax.rst:182 msgid "**Multiplication and division**" msgstr "" #: ../../userguide/syntax.rst:179 msgid "In many situations, *implicit multiplication* allows writing multiplications without the ``*`` operator." msgstr "" #: ../../userguide/syntax.rst:184 msgid "Implicit multiplication was added SpeedCrunch 0.12." msgstr "" #: ../../userguide/syntax.rst:178 msgid "``3 sqrt(2)``" msgstr "" #: ../../userguide/syntax.rst:188 msgid "``a + b``, ``a - b``" msgstr "" #: ../../userguide/syntax.rst:188 msgid "**Addition and subtraction**" msgstr "" #: ../../userguide/syntax.rst:190 msgid "``a << n``, ``a >> n``" msgstr "" #: ../../userguide/syntax.rst:192 msgid "**Left/right arithmetic shifts**" msgstr "" #: ../../userguide/syntax.rst:191 msgid "Shifts the first operand left/right by ``n`` bits. See also :func:`shl` and :func:`shr`." msgstr "" #: ../../userguide/syntax.rst:190 msgid "``0b11<<1 = 0b110``" msgstr "" #: ../../userguide/syntax.rst:192 msgid "``0b100>>2 = 0b1``" msgstr "" #: ../../userguide/syntax.rst:195 msgid "``a & b``" msgstr "" #: ../../userguide/syntax.rst:195 msgid "**Bitwise AND**" msgstr "" #: ../../userguide/syntax.rst:196 msgid "See also :func:`and`." msgstr "" #: ../../userguide/syntax.rst:195 msgid "``0b11 & 0b10 = 0b10``" msgstr "" #: ../../userguide/syntax.rst:198 msgid "``a | b``" msgstr "" #: ../../userguide/syntax.rst:198 msgid "**Bitwise OR**" msgstr "" #: ../../userguide/syntax.rst:199 msgid "See also :func:`or`." msgstr "" #: ../../userguide/syntax.rst:198 msgid "``0b10 | 0b01 = 0b11``" msgstr "" #: ../../userguide/syntax.rst:201 msgid "``->``, ``in``" msgstr "" #: ../../userguide/syntax.rst:203 msgid "**Unit conversion**" msgstr "" #: ../../userguide/syntax.rst:202 msgid "Convert the operand into the given unit. Both forms are equivalent. See :ref:`units` for more information." msgstr "" #: ../../userguide/syntax.rst:201 msgid "``1000 meter in mile``" msgstr "" #: ../../userguide/syntax.rst:203 msgid "``1000 meter -> mile``" msgstr "" #: ../../userguide/syntax.rst:218 msgid "Deprecated Operators" msgstr "" #: ../../userguide/syntax.rst:220 msgid "The following operators used to be supported, but were either removed from recent SpeedCrunch versions or are considered deprecated. Generally, these features were removed because of significant problems so you may want to avoid them even if they're still supported in your version of SpeedCrunch." msgstr "" #: ../../userguide/syntax.rst:229 msgid "``x%``" msgstr "" #: ../../userguide/syntax.rst:231 msgid "**Percent operator**" msgstr "" #: ../../userguide/syntax.rst:230 msgid "Equivalent to multiplication with 0.01." msgstr "" #: ../../userguide/syntax.rst:233 msgid "This operator was **removed** in SpeedCrunch 0.12 as it was confusing and not very useful. The reasons for its removal are discussed in more detail in `issue #239 `_." msgstr "" #: ../../userguide/syntax.rst:229 msgid "``10% = 0.1``" msgstr "" #: ../../userguide/syntax.rst:239 msgid "``f x``" msgstr "" #: ../../userguide/syntax.rst:241 msgid "**Simplified function syntax**" msgstr "" #: ../../userguide/syntax.rst:240 msgid "Allows omitting the parentheses when calling a function." msgstr "" #: ../../userguide/syntax.rst:243 msgid "Use of this feature is discouraged because it allows for very ambiguous expressions. It will likely be removed in a future release." msgstr "" #: ../../userguide/syntax.rst:239 msgid "``sqrt 2 = sqrt(2)``" msgstr "" heldercorreia-speedcrunch-e7ca37f/doc/src/logo.png000066400000000000000000002176751526573132500223610ustar00rootroot00000000000000‰PNG  IHDR\r¨fsRGB®ÎéDeXIfMM*‡i   gêI@IDATxì½ °eÇyö¿{ß>o™³c`b™0X@$APHB¤D‰”èØŽbU¥¢8ŽË®R\YªRªT*‹$')'å¸Êr,¥\ eRŽ,¢ŠûB¬³a³Ï¼ý½yûÍ÷}ÿß}ι÷¾Á3Aåõ{÷t÷¿õ߯§OŸ>f«nÕ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j��š:>j }xúüfíÞ{ŸßÔmvÕòRc»Õl{‡Õ6,/767j6Üa�nkttY‡uVtZ®Ä |…®aÍ�†Ó…ÇH)2Àìò({¹•ŠD�X´º8�× B@–2"‰”rêË�p‘ƒ` �xEAº™Ÿ�-“ ;)­Xø$¡0Û2²XÄœ òÊ" ’v2Ct[¯£cyÑ–;æµÆ|c¹c¬V³s�qª¿Û¨/7ë>sðàöóf__j+à¯9ðÿ7À'îøÜ¦¥Î®�¡ÝÝè°;P®{Њ®±ŽŽu�uUòjo.ýÀ–‰:¼ue��RCÀÿ!Ì©Ê�—t6qu¼Ó#,Ñ…¬ˆJŽ(C�‡³të q‰D¥ ˆKt¤ f÷œ @Yõ‘±‚ž€ô ¼ÁNJi°¿êˆü°³úÕeˆCÁ|Ét \‰�é%W¡õD#{®oè‘È¥Af§n„À¼7Ö1Šð1@Þ@ÝxxÎ:_;pà…³…Œ¿¾¡sý5ÊjÇ'îýâmèí?Ýèh<‚z'~[jèPøñK£)ã ÈÉ�6&ajÆ{µ1ÑQÍg…ó� Ë ª_ “@MGÌA�pT< „‹ô¨´bé1€…‘�‹Ôõ<2¬¼:…ìà\Î$>"⬩Hp‘^‰²À‡:ä–óx¢Kl).¥@zOh.•Nèî‰M|‘­àc™–P âÀ“’¥´þyÁOŒ @…ÁõTÍ:žÕwê ûó7?ý*šç$!ÿ§ÛcÎÿZ¹{ïýù›kË�ŸG~CáþZ­ŽY>JSÝ 7jh­^·î®.ëííÕ¯¯¯Ïº»{¬««Ó:;»ŒE­�EŒð¬ª?qiΑ;Uø$—T æ<Î(¶2Α„@MN»QÁHXüCsr2¥ÔQ$ ÷%Øã”“ÒÁ´—Î� D©ã”ŽÉyHG´ÓÐÃÄœ…JÀ�DèCž`–è$E ^ ]ÍÆ5¡~wâó d‰~‘¨$S_‚B;!o  ¸@º°Œ3ÐÕ‚Ž^渵³¥¥%üm¿ùÅ9[\\°……Ä—0ð{~™;‡–=„5–—çx…ô‡¶XûÖ�£O¿¦Äþš\ܶ?å™Ù¿ÿ ý=�Ï£Õþ-Ô‹‡ëµz?+ U•ùëBc´µÃkmxíZëëëWc_F[\X´¹¹9›ŸŸS…˜Ÿ_**ñE Y À£ŽˆP‰¨t œ8  Œ Ul´‡è˜§NFÕ?äÈÓ:Aè#@¨ƒpÒ2ùáHƒJî�Ë1ÈŽcžB‚'Ò _î`‹¥1J¼l“øtâ”ÞLE°‚• {ÒÄ{COú9­ãJ©“2þÉU8Mú‘×~¨V¯wZ½³n�08€°Ã–°L°°0o.ÌØ…ÙÕƒ%”?qš)x¡CÅå¤ùˆúýéÙå?9qâ¹™"¥ŸÎ�Šì§Su³ûî{t½-tý{X!ú1bïea5Øp}8A#ï³M›6ÙÆ�›Ôø™Ï陳ÉÉI›žžRÃçÈÀûØTQ“=Z�ãV±Ž€$Œú&Xb ‘_©Ã(° pšt…¯`4u0i¡„L÷%¦UÑGçQ¤º‘F[Íeã¿»—ò@8u" `Ù8‚ˆÏåòI*çL¡-øŸøLHI¶G2,‘Á—)m Π:I¿Ë JA}:£šHHë>õÎNëîì¶Þž>üz1+Ô„õbÖ¦f¦lú´j\Ì ¨kãùç KÝÿêèÑïcá§Ó…I~º”ß¿ÿg‡{¬ïWÑ­ÿ}4üݬ$±1]³îžnÛ¼y³mÛ¾ÝmvvÖΞ;gçÏŸS£_\\T%I…©Ê=|³ ã°¶E,*ž¼Ô¸€U¼¹¶-å2˜GVè@Ÿä”ù=$¢#? T!ñ.J€‹ÆSȉ„,䥟õ zÈ#Hb� ’zò)”¶SÇ¸ìø°CU¾Óé2² +º0aºB§T¼”¢˜ôSHp‡–¯ÒAä‰ÇùÊ44þ5ÓCeà­_n×ôXïݲ3Ÿ·t‹˜-°îèöЭu°ÑQû'XOüýC‡žoMç£ )[飭©´ûÍÚ}ûŸû* ýW˜¾ÝÌÚ»´„©(FüLïw]½Ë¶lÙ‚{»E;yò”�9}Ú¦0Ês*¯BÓ &…ï™×ªabäË\©òxý�–-,ëS@áSŠW0B³SCòXjœ¤sÞ‡_¢“˜RCsýœ'R=¹“̤JŠ»*„iù, šf( ú`v/$H¤–³%¬ä1ÝB_ÀÊÁB—/Eg‘ YË€O9…í‹�’*ÑAïÜ:%h,…²¼¬®gŒ2øÇšÂu¡�¾[³fP�Ãôô¤�OŽÙ’îÞ{Û__ªý÷hÉã§FÍxxØ®¿þzÛ°qƒ�ŽŽÚ;ïµÑ‘Ü×-©ÀØðéÊWò¯äZ1‰ÆA¾¢nG(U òŒ  rÄ5ÕNܬd ¿Dëa¤F¢.ò‘“a•.bÉ…Ü€‹®…>«¥„”¬^Èg:%~æBÈO (ï€9²l$„SSsO Èƒâ´E–)H¾P¦—B3&)IF*ã°±JìUyЯ„++¯ÎH. öaÁxxp�õàV�kc£6‡u#jÇ5†Hãqlkø/|ú9|´¯¡õGWI.ðuu4þ3¬êÿFG­6°„Fφ?00`{öÜ {üSé�>b“S“((ŸÆ1GEæJT�#’ Þ©ýJ yà…ËdŒ—j‹Ã ϵ3±ò$©!ª©ª±¸œ$·Y4"ááa%îzîÒ�žMÌe¥+|ÿßáÞȨUðAa�ò&¨øuQšNGLÁŸ)åI¹Ïú)bS" ñd¤Ð©0|à3[äd]Ré éÎòÎr‰B„˜òÀF¿ˆQ½»»Û®ß}½íÚµËΞ=c´),èu`E·V+²ã!\`³ Wn¡"ã+ëGÅ9 ƒ£Öä8iQ ‚2�Ä)¢©9<Ó'ÊL+ê²ì“Eò£±%pš)haÒ™]¤Æ*>A9Ú¹>‘ ’]€R@ºfY¡ŸÒo'3ƒW<1¡Lò¹sù)‘C¼ °ÊøR®°‘¬s¤‘<å¯T"5Ù®’\b€_•U¤‘HÊúK+twõØúáõZ+˜˜·Q̸ÅAˆhž¨-/ÿ½·�<ób’óQóW²ÇO\Ï{îüüT¯Õþ4êµKKþHoË–­vËÍ·h…ö�7^×”¿}Çúñ£á«<#«ðª™.u)×UA%"× 4EQàt¥Wi¨�% ÿLBM�ÇZè!6„BVšI$�| (Ñ39p;�®�~ˆòN¡H§Üˆ¶Ä�tÃ%¥F€ÃQÈe‚¶èDqr‰'јyƒ„^R�Ùs猑 @¥PLÄò%Wå_£3©ÐË€pº%‚¤W¥ò°§»×6¬Ýˆ¨ÓÎ��µ<9È�@cy kÿèàá§þy’õQò ;D´Ú»÷‘5ý]]¿…éþße‘,c‘¯ £þ-·Üb›7]eo½õ¦;vTÚê9n) FÁ«Y«õÿÈa‰�rŒ¬­EßjÑð„”\K\Š¢Í�€Ò ¿h°Eº©Ñââ\#q\}ÂJ¦"¾¤Ÿ¤ª!$zçGŒ$)O8ÃDÛV&0€3Mý#¯S’“‚´¢‹ƒUl‰"é˜âN’” •(%! /xJ0* <5uIGgN|Œ…6l|†›3Øø7lÜh·ß~»MOMÛ«¯¼ã^ÀfßÀ¡Ú­s&*�Pÿ�|e*§®€BšÍà5£\ø‰B°@Г´¨ ÎÍL,©±’Pô¸$ 2�‹V㕌©1 Ë‘^æ“Oð L|9•¤gøìRPÊR4%‹¿Y&ãJ¼èLH*¸N.£*Sò«ÃpÎWJ³èÀD ”tó¸¬Í4E°Rú‚äú@¢ ÉJVåm"‰‘Áñ¹»OXøn î6ìÄF£ ë6a“Y·�9c³x„Xš |§s±óWß<öĉóO4È–ô‘pwÝõØ­ÝõŽoÕ;j÷²ñ³²\·{7:…}vèà!ûÑ�^Õ#¿zÝ·hÊæÐ<•9§ü w¨€òÿ a,LÑÂO.h )AK$øõ«âE ¡•hÉè`ò•bŠ€ŸÀ‹@ÉwHÂ$´»qþ¸`B’ç(ò'B¯º‰ÅéDNŠj€€& 2 ÑŠ¤À œj¦Î)4#BZ�/B¥„ÚÛPV@Q™e~Â*D£@UŠ”òEº¦Ê q\¤žžñAž;ý¹ùY`ÐqtÔ®kÔ—>»nýÖ¿=q¦IÀO$ºr~>Duî¾ý³w×:;¿�G);—±+ÓÛ·wŸmÜ´Ñ^xþ9ÞêØ£ïÊâZgåQH Çk¥^f ×ÂÈWŽ)€K”2] ÆXF—ðÍ£–£ª×òèšfi~{ÀB®B^y=áf>ON€«Ë 2ñ$I’î W¥roR Dšt YÓÌ„H úLªr€4‹@˜� 7®ÛŒYÀ;*îG©ƒfù((¿|èÐ3ÏTe|ø±Âî~ÚJñîÛ»³¦oàáÝnÉåN¾»öߥýÚÏ=ó¬¦Pܮ銆ºeï"�¿¥#@Šb þTA<š€T+¤TôK”{µøË€àIt—+éØ,éb aŒ³bAESÌÌ œƒ/ñÃ�ÿðIä4JZI‰1 y‰–`ǧ†ëx\³€��ëBvhšõ“>ÈŒg½*›,Â+Pºx¢@¨U�9/%Ó¹ì"TÄ Ëéç ÄW%­Ê*ãKÈ£ÜT ·:0€ Ù„xÚ•·«›Ö_¥G×gGÏ`Çá’ÞIÀvõ“¶ÔøòÁwžùA«¬ò½¸çŽÏßU«w|Û*Ñø­{÷?~ßǵ?ÿYtŽKØÑÇ�VÅ#GÁÈSã§á}z\nðÎãļêÎø˜F¾cdq–âH¸ä;YŠ•¨J•LМ…‘žú!àáÂ* é!¹�L^òÅXºÜ%3â麶.·D�ƒ‰-ÙÊã¸&D¦ É-¨ÌQP6ñfó�¢ ×”lVˆôP3£M yñF_³¤÷Œ—”n“Ä ì^Æe$íÊ÷RfpKÐ×ÛgCÜšŽÙÖ:êƒx£ô±uë·wtôøOlMà'Öܵ÷‘[k�µ?Ä*év¾žÙ�·óî¿ÿ~³_xQƒ3oXÊ^(Š( yŠ‹:™†MȨ~”E!ˆ¨³§ „E_ò…w•§ÈЈ�W*yXØRz’áx¢È'ùô•nøŒQ>ý€ËÄ/Œ—($G˜à+‘–‚‰G©)�IF’êÉ94Ë+E†kÀª]Š_›™W3¬xf€ˆ48/â�²L\—$UÁä©B.’@!¥ÄséܤlO�ì7�'|Ç`x`X�·°ãöêïg7 m|düøOä¶°Ý=pÇÃÛjÝ]_C/¸“ûöùNþÇï¿{ÎÙË/¾ðìÜ ¥ò�ž…™ Õ�&ч“1âQA Ðà)ßÿÚg?ñ¤Î�ýŒÏ$É…– ½#o< |“XÊ£K¾Çüš`ò¥W`+ˆ2Ã@ú¿åT[sbžDi„L‘•}ò¼+ë™X ¢2°Åܪ…´ÌÓ‚$ ‰`…h\�%±íý-ò”\J�•üK  · s`vþ‚n xk›†v5:;þàê«?±u¥~œð}Àçüµzç×1òß»ŒÕþîî.»ïã÷Û(^Ñ}õå—µ›�od¹Cµ–}q ;{”Õ!´ÊŒCî4Äì8Ñ�VxÄ´?„“ã¢9ÑD™+ˆóQ)�t+ãöÔE§DA(ZgðNȵpx‘o¿›LôR I¨øŠðâ"áE |Æ$ӊЌȇ5·×š•hZ‚"XŠU4 ¼ŠËÚš(›¢‰¡ öX†å2 êŒHÜ ^ ŠP•¦^†”Ã%>€†ª\ÀÛ©|D8¸fÈf°�˜Û‹q;º¹Ö±tûΞõß8=}z¡Äýc¦÷cO(%ÐÛUÿmt-cäç}øþýwë±É+/q䇅òH Ã%˳¢Ñ°ÒÔ?Ém¡qªªÞø“0úÄð�5}å_™’´ú1¡%ù €’“~$ \"q*qIm�+HÎP°=OÐäÌ2^ð¥PÕ�X2•r¸HUGµ# ¬¼"A“Is@�°*wŠßDÓ-S¦p•g†‚ØCJ*há½7W¢H~³ÀR¼E¬ƒ²�Ñ©D†7‚µJ�@Çg¦úû~«Äý¡?ÔÀÝw~Žwü7Ì07Mpƒß°zöY> AÓÜŸ&qãæÆ¶ lt�FAƒ‰ª¹ñ ¯FOû’j¥?ö�)¥$�qvJ@è­Kw®ÄÍtšœØƒJzCJÖ_H1h NšD¸t§õ´O¯ÌSz-‚hN&Ô bÇêÚLH ÂÒ/â²K ØŽ�¤­® e ¨�®$$¤…ÈEW2ÒD¶O:4a¸�ߎÒaƒ@KBcèÂÜ Ö½ôn 7·Ñá6áîõk·½;2vü>„ˇ6¸ãŽG÷¡’ÿ6ó´´¸d»¯»Î6a—¿ß ¹*^´0^¥àÈU²h,üe- Ë`’ÑÚøÓhOŠ ÊLdL?è"9\¿Ï”%ÙÑ P-8I¢2É ? qŠ,“X§(d«OJl.D×DYen'©°WöÊHÙ ý;"£s ”¢`¼”�Yp)t3-”\*YÅ pBƒ2“ŸQÁ ›ü‚ª’EDÕPÔ™l•Ð qÚ•àÄúœ’iW©ª1ÉÁ#‘ñsèzm[ˆùÈÿ`¬ÿÎu×Ýw›h>„ˇÒð¾çnÿ3ŒðÃ|Ö¿ Ï�7ÚóÏ?¯G~¾ÚÏ̯œcG•ªJÐ&úå2-7~of´.“Á�âŠ6‡Õ!ˆÍ¹\DH¨v!܉•NâË ð¥,"ÄÈÅ\ ïÁÐ[]RÁX"+ɬ@AŒx§SHòP_�•(ØšI„)€E(ŒWp6… J¦#u3(Ú˜­À5 \9Z®( ºt £Œú’*U5–•‚l £xg`ë|¡ˆ=¾µµŽÆ?Û¿m?εüñ»¥èî¬ýÞ”ú8Gz.€Ü�©ÿÛo½eçGÎã9ÿÅTHÖ,1×£€5Ul6“rã÷âˆÂaÑ� <þ— , àAàd$eˆiè¿;]Ñ ˆNâ@Cz£ä9¢Íµ,Ÿ¬A’ü‚£Q ÌEC¥-d!J«Æªò¯JE@">�ÚÀ³Ð&\S4‘UÁŒU!‰îâ~Áóþ$|+É�b,¡/ÎÃYîüÂN­š°µ8h„m¡��B¨K÷�÷vþFIÐ�-øc_Ø¿ÿÑ;kVÿ]Lqºy4·øòàÎW_{Õ:y*k®œÈvª<%˜—±7/Ç“Žöpã–»€ZÖýàsN—Aþüeû“BÒ;¥® û¿ ÃQŽ ]J tßóP‘<‘ŒÇDœ8}‰²9­K–j,D†˜3ETù.¨<&Š2}9œØ['Fé%)ìz�µY€H36Å e3D�•¸«Tmbѱ uPÊ P+)$… )f%âj¬¯ ‹óÚ#Àóøò�¯‡uܽaxë�Œ�8U帲±Üv®¬X—öàƒvֵ߯ÂßѵïóóÀΗ_yæ)¨n5�°•‚tùj¨Iqј^á\ž§£´ ‰T�aاèÔ¼ç/ÇIW4"†ùï4‰šqçR@xî0^�Ïã—£Q)ÔÌ_N£™ÌiGÒ±D…`ÂЪŠÄ'»4•�“T@e¹­)$ÒJuaILá§�‹,bdO±ðSÔ%‡üf âÊrZ$’Zx T9TM�±*¤%ÞŒ–°è¡"^Në=ÃíØZ`-€&±mðM¶hCÑ$#E/�$U*ƪ�$­Õ÷ÚY†sð™™›Ö+ïkzý©€ð ûÍo|`°L{%Ã?¶`qnùïàEž¹Û�GvïܵÓ^í5 nldí ÕÖšÕD%—TÆ­&-ó\ò‰>õÐæ‘&aAËWô Üc…ïRƒ†‘R°MT)8�_¥/xšØJ$ÄØJ~‰°5˜ŒÑ„iæU<s ”ê{ú"|¥~´IRk´“qUÁÕX&Œ@[l“-ÚÒ4 Rü(AR¥ªÆÚŠÍ²Q—HÞŽ�·§f&±5¾O‹è©@½vScqùWW–yy˜KpÛm�­Ã¦†  ?˜ÊìÙ³ÇΜ9ƒ3üF4½iU¹�5ªTÉf™²5P�9‹=¹0E&/:#” … ŽfŒ±pV]Ëá6ñgòˆ•yr8²øYÉÏbÛÀ%ÅÛ"+›&“|§,bþoªc¶Æ§¤úaífû6øÎ†ÿ/ð‰>ñóYv!µ½>‚’¨ a+¨r©Ž*Ùb…dV‘:úЧzRP4é×-èvÄŽŸ8iãcãÚÎÎ�û:˜¿÷vÉr…EßÏŠ´[HNT„ Ó—àÄÛ* 8 DåLŒ™?YÞ×Ó�tB¶@ÿøwÀ|E;€R’—�£÷ Ù¿ÿ‘›jËü&Z?¿Áþ‰Ÿù”6ýœÇ×yu/)~T(Ž^pj†V|Â…&]¢"©Œàò�.â"N8ÿ)St¢Œñ9‰`IN°9�:¤‚__FB£çô¾¯¯#ú»æš]vÃMøJÒ5רZœ;×Û¿iöÚìBÝÎbê>=�¯)- !~ª »†!¾{iÚj #j±ó§$A»yK��À”ýÔÉ Ö…†Ý�;ˆ%LùèxØ1P_f‘¼Lãcwl´¾œ‹?Æ™r…Þ¤ÿ¬ áÖ ïú~›~ÇaMñ˜7Ã!¯�ÛÛiKkºl¾·a˜kØÉ©Svðôa{ãÈ[vàð!;yê´ŽƒgÞ9ƒdg�lí‰3u8¤O¸VSvZ@+ 6PNY¦sn‡dù]•çi9¾šN! 4 P ¡š[(Q$¾@6E}êÞƒ��CƒkñÒ ò„§;–—î|ãÐß*Ó^NøŠÎ0¢ü"zÿ*ÉÖMÛÔ‹�¤•¶†T©£¸Þ[q*[Rä2.BÍ~i'µ™š…ÄN¡WkeZ„%:E¬Ù�øœ|åps,âàq*¿VS-øY 8�x Fù�;·ÙMÛc7Þr£]…ÙU÷ð:[�ûøÓçpÚÌ$&Ý>²Ï`ké,n0™–ÉÑvÔ€pS�vŠ‘Ù. _Ðû@æ1e£Þ ž>³sGqž}gÚ!Gä§“f` -Û?;�ÄK9_µÛîîµ®Ù~ãÇs{æ—l`ßqê²¥yÜÛâ‹y’ ¦å9ìyŸÅìclk]¶¡{�mê»Ñöî¸Á.\û);ó‰óvàÜ{ùÐëöÚÛo؉Çñ ¸)éÌŽ 8�Iª5Õ‡µ¿FfÚ#³°*U5v1VâV¦nƒiÀÙž a)u¶ïfÛ„ï!6°`7a]6‰‘�#ï6Ì´è ^ŽÐ”3�š®Ž0§î4;GqÒ0Þ¹|Á:—ð1Kˆ#œ�~ëÖvÙLmÁ™4¼Á)zŸ8-žIk@™L�³ :™}ÕÚ ÝvÓ­;íÂQ„'pë‡[†Þë0+9¶`óg‘&Ø­øX@ßã”±ÜÑ…õ|ãO'gý6×»h§ÏÛëgÙso¾l¯¾õº�:uJ· ìøK6¤Œ²k�”ʰLè*� “²N�òr"¼�ƒÎ*Á2Ži¶ºVMÊt.Ÿúâ³ä� H¸j»ÓˆA§¥ §ª�$Fú‰@0ׯŒfÒ\áåbÏÝ„ûù;ï½Ý¶Ý¸Ûú7­·nØñ…©<^Tc퇎}¼'‡®·÷£’šfÃbRø äñ]2NÙ¥åWGá̈…f /ÖúÐè|=@:�¶MÝ&1{›˜YÔèŸÌKŸy¤=Yú  ´`\�CdMjÔÄK§lz?¦ÿë‡ ë€6wO( 7ìÀÅ0:æõ£Ö]·z7|ÐÖ{Óß‚èB.)›O0“Dçwëâ»åSŸ·‡î¹ßž}îy{ê•íe|(ö ž,ðIˆn cÕ5Ç«XÅ@B*¨®KÐö>t¾„$È+² m)!² mùU¾)ÈO‘cÞªm<Q­*?œ*ü&|Äóܹ³ˆ¢àpßé¹.L[6"³OLÙ0¹â%x0$º¶>€¬¤’“k�*�hœ[é2Hý+"5pEyIpøHÀc “—BbW‡Pâ ­‚EÒu&G®M×Ûþ»öÙ>4ü��[í$>1=c§�ž°ûPðýXZF#éœýž² =tغÞ:4zÄùÙ<ųéЇªñ'‡€Ï u¤y–ñ…šE̺<ŽÊóàºN;tnBê’–›yÈTCÂLdêlÔ Hô£²2gƒxÑ«ƒÀ±OÛõ÷÷á´››=3kÝx¬XïC„†^GC¯adïÀ= Æ{å 1 ûÖÀS ›ÀcÄy<‹\Àí¦�Ç)HGcè\ƒ|¯Agvrѹã^»­w«¸y¿=uðGöü�^ÁZÁ Ü¢ø÷$¤0•¾˜k‹n \AÊÅ?帬,1(.pº•�ø‰Ò“]:3 u²w£ñ0˜ÿ %\®ã@rÙnÿþ7b.øßBÐü¸þú=vøða›Ã,@+þȈ2&Ÿ™£Ñ¦+�|ä¹—>â#¥ŒPæ'šü"[OYÎ…Š“ˆâÌ!ÓżÇÕ‚KºÂGjôâv¸‚Ò­WÐã¥Ø£oÛ¶Ùùì§í±_ù9Ûv÷>;Œ�¢<9>e?Âo•¿ §¦gmߺ[ìÄ”˜­N¢qÙÖÓe§F—ØF4âcpÄ“w6AQÄU,9L\R…&it aqV Ó™ëÖ7ØaOL•ìåé‘�R“tÎZ(HP"ô«Ù¬øàG…ñ¢Ñ±d›oÞ Ž«s À¬mÜ%8 Œcçàù9[ÀºÀÒ¹Y[Dxi›„¦ñ”a–�;¬þ#-Þ®pÆÀî¢sç;‡ÇŽ3§ñý=¬ b¶0|zÉöîºÎnÄ–óþõC6‰‘rjÒ_¬Ñ�›¡õJ½KΣMÀÞ�—Ê´W¥ªøIŽÛN¨B„õ]Ÿ¶GxHjYD®³25ÎÎ\ƒ—\¼ÅІ »ïܹÃ~˜`fzÿv­—í�ž�á±ÏfŽhÃÃ�×À³ÿIóì:G¼*†EJ™ªp‰™óFq(A +bˆaB¹ÍaÒ¤N€ÍƦ8„H[–Ë(Q%�ô][ÇâªD ‡“¬ð"M�Oñ” �ðØp¶o»ÊøÄ½vëÇï°Ùõëì%4ò·N�·iLq»�‘>T†~T>~›Ïóïž²»®ÛeG–¨Fbˆà>‹yØ?Þaqê�lÐ4a+%� m£JC¢á-ï@»ˆÇ†¸ÚÆáº�š¸€v‡5vÆáÈ«ÉCïûTÌ ŽÊü:h�tð¯{”Þ klä v ¢AÏ™ÃL‚8êI=VÁ!Æ‘aÞP87|êŽa¼ý«-a¯¶(Ï÷ap‹‰OžÀlcÏ�u­Ÿ´Å£#vã`Ÿ]·ç»ÿÚ›í»X0|úåìì|“�üL¼ì¤dÀp[`3‘èDÙB¥å D1€_ÚÛÀÑ^åÒÂAºÌ%»pQ�~y˜OØ0'»ª^_â:À÷ƒý{Wd°móu_Á‘_�RQnBéˆõî»GcJ£\‡i¡ºò†j˜ý*>e‘�i™MDøA…^@â$2s“Éé—èê±òµ ÷ª›*}¨##ÿå23À SävÙ ˜ê?ú¹í±¯~ѱªÿZÊ#vt�£âTˆAŒ½h|hE[MÌa6€pvö�ažÉlëé´‘‰e»€GmÌ;þ0qιôlºŒ¤+›*œÚ–Û´ tã±__o— -ÛïNˆ¦lÏ�"é ΑÙoïÐhì†þÃ\ïAjÈð{»lýî«ìì�yëßÞm]èÀ–°¨Ç‘\r$˜%É,ç!ˆ‡IAçU}6Š]ƒsçpžÞQ`Ús ¶vÏ[8�…“¬6=oW¡S»mçµvÍµ×Øl5Š­É³èœ¨[‘vœüRZ ´‚ª·Á“5Žä"Ï5�ôíÓNÇ‚½à¨°‹€ú²žñI·R×ñ˜V{õìÙ#O x—+2XîèÀ±_î¸Ýt û¿UÙ’bŒÐø,ëplXÞë»É¼$,üà“†õŠLœHàty´CKEë •é’R±�áE� ¢¤¦èD-±¦ÒøCŠÏ(¢¡¶€Q}M¯}òS÷Ú–·\e?Ĉÿú‰ó6‹Ù@/ý0zõ.d ›8õÕz%d°‘¾qnÜ6`¯þ|Vj�­Cðè¬/þa ΃¾|þD€O9:1=`ï�¯¡ßårQnJ÷ñåèÒ…—æqNû¤òLy’½¡\Âøãc'0§qÛ€t‡*@`&¸kÈf§¹#tÑΙµí»û¬6ƒÜÍù(O[»5ÙÝE®‘°Ê2¥O ¤WÄ×÷ÚÔ[x£·Hw�——æa‹wçlí>ì:}ò:\ÜMÏY'ÞM¸ ;!o¼ça{òšëíñ~hoý€½ÚÙmß9;f‡§°¡´C¸!Ä�#>GSïPR>³v)Y;ƒ…Á°0Œï(LbôŸÀ¼Ÿ | �x .7bó`Ý®‚�ß<Ò¬Y/Í:0€,`Ñm��3‰QlÄ9‡…ƒs3KÖ‡­¿‡ sǺ.;7Â¯Õ }å'lTE5vÌH2<5ƒÀ¢ì”¨;±zÕǶØÄYvL°nU¸V1¼½Çαƒ J5$R�´’ «Ëè°è\×m“=xJq3 tV¤ë@çÂEÄ<µ¨ ôYÿœ©w Ûfi`¸eÌz€»~§P_{­uÃ~ç°-}zjJx­;I’RJ…-\ë…Šê¢[ÑIê-Ȳ˜ÎŠš1-¹Öö¦ûz5znLBÃg�eú4T%~÷3º\%@Œ4Ô/éX,J‡Î;þÞ©SG±i・4óüÀz::6C�u\äG>ÙHæfçÜ`Ô³ÔË—€JOh„*dí4�%ظ؀dE„qôÕÔ”U©‚szá/|BéTá<ˆkÍ B©B"K *Ôðƒ1vÇ7Ûc_úœ­»~·EEøÚëG5-_‡¡•Dõ|šƒ—lè¨6]ʇÇŒ\#¸„Æ5;Ïv/Û[Só6Á{q Â�· |ÆOués ÇIÖ/¥‰K. °�o‰®Ã¬áöpñîÈØ¢íÝÆqêßqvÂîAÇtõ}Û··î°¿xîá{*ÈgjdL²ê܆U˜Ç¨KnðQãÈn�S�V—¡iüΕ)ÑaÓ6\ÌÄvn¬µÁ­›�­_/ |pwÙúõØ´ÐIù™/Ž€<¤Å *hV% VbE÷ªú4!+… �Ô¢%i‚‹Qøê=ó))""‘6£…I#aº&ŒÃ„(�Š2å¸,ܯ߇ÇxŸ}ì!»çg²w:‡0ÕŸÆè‹ïƒr÷ØjK¡3¥°Ê2oÌ*Ç@†é¢ î¤ "6Ök7 Û‹Ñwaã ïíçQDZc•BæQ»Q�¢\¶!éK^—$›£Ai«-ø¹1„—q–¦¶}�Ø@v·×ïÄÛ\|��à(’P¾ê\!«šÞTµØ�Ýø«qm¾¿¿Çú6àþzòV@«“˜q×À}À¹#ó¶íº<îCçÅõ Õ¾@Y?XCذEÚ\D­mî·1<&l`!‘ÓjŽêEI’Ÿ� Þv„¼ñ£S¶ö¶­6òäAØ’8’Ò@ø/þæ'flž¢üÝŸû‚ÝxÝõö¯¿óÇxd}²‘?MÈ@'N×Ãe�ƒÝô“’Žtê¡ø«ÐJ¬Ä[æb8R.À°,ÙÁbû@Ù¾j]µÚòv]Ö† ËîõÆvŽÊ±ðÙ¿žßb´£ÚÌ+y‘ù"Ä‚MF¥“œXs˜öj¡‘YXeœž£µW ÆÎF'™CF‚‹À‹:oDA"€d¹˜šã™ý®]Ûì«ó°àt—[î²Ù™9»ií ½{h\;÷ÈÆF(¶Ð«œo"˜NÒ]#)bü'ïˆñå~l¯>€lFÐ0÷të^~³柲}¶â²°0«íÁ=¨¬|½·ñ>اS÷:>F±ÌÅ$×Ý rà½.w¼ÿK�+I!ü# Ê ³âCUðl#�•Ãb‘pàñ’¦ìª©”áP0Èõª*Ñ^É‚B†S­#€Eäé;DáUJ�ñ&Ç—xzñÎWÿÖ—ìúÏ œ*º| ¨ �ø©�4?+r7£Ððg1E?þî {÷Øq{î…çt2Òf¼mzí®ÝvãýA§˜@IDAT5·Øõ[÷Ø–õ[­ÏÁºHc�ÅÑt`?z`›xgÂ6`= wÛ„Õø(°£Û§Ç¹nˆÝ„ G>™¦2�û4v(wnÜjk~éWìÿxü�ìùgŸÕhZhôÜúKË”Eª�\™ œBž=·IBµŠÆ�¼’…åÆr÷Ó¹$ç}ú—Ý@'¾� GŰÈ…—õ æÂ;¤u„Ã&żÁ³±°23óš °²)¹YY�8JÌÄt'õ+é²#Q)šáMV\.ŒqÚÿ•¯þ¼]÷™OÛ7ðÖÚl7eãg#D£ëCÞ7cßùilÑ�}7uÆGû³€ÁÈ}ç–õöÖü6ÎõTþ˜¦èáCµåu<Ç[ƒCÙϼø²=ñ½'ì¥ç_²“8Q—:Õ¸�›¯|šJð»1_ü•Ë qÛ/Ñe4S”áJé³aK–�®—l 8uT Ç�”‰¿EE8Ñ@Ù¹n¤Ò¬" J:ƒFÅ£ôCËœ�-щPWÖ�),ÜMŒ°ƒØ÷z¿kqêôuWï¶[vïµ›¶ßlÛÖm³¾¥A<åÀíf Ì¼ÞÆzÀ�;p �G›xw >܇W’±ÞÑ‹Y’Î"Àþ ÜŸq;´æxŒý3 ÞôÙ/Úÿ„Nðit< Þr¨§Ë™A€zV]†” W%QŒõ*»R0Ãߌ*Äj°ÍƒoÁ÷þB—Ýää¨iÔ(÷Xð^!<³,A¥¤ªf*eŒ¼ª2€#X©’ø,„év‚‘tÈ‚|RËp`§SÅò�î ¤ÉGãÇ´’ºýâ—?o{ù´ýlF9#?ëv/*·õÒ±xÓNŒ'Ð!ôä=û›“ó¶ë{ÖÍÚ›£¾ õlRcÚÊÛJÆÐð¯ê·-Øhsö©Ú7þì»öòK¯`´Ç(†´p6¦ø´ò©ÓŠFÅ2ÌFÎwø¥GØÆ->èŒq?R…ŸbÀ„à™2áB†!hw&Ç«ÿ‡Ï{o+œ¦ªub çóyf–h&’:„Ô)�Rp*À¼�‚A†ñcÞÙÌãLA.pò÷ÃçžÖhn¸f�íÝs‡Ývõ­võÎ-š‘Õqbÿ3àOcç ; ß!)5t‘FÌ c^(R!aRΜN´MdŠÂîð[ÄXe¢Å/×]‘€9ò,¢=z1Bó²X™�é!™ŽQ8ò²ÒMÙ£P þ(G‡‚�€øˆN²BEJ)çWÈ¢ìpÞR,ù.w÷ƒ÷á½ýOþÒÏÙã³uûÑØÉyãGÝÃc8¼E‡t¹QgG_:¬N‡~ÔÖu–†Ò•ûðŸÇawlßhß;|£ pÌFêí8õ÷&lØY:zÔüÏìé§ŸÁ—v0SÀ¢cOOn&XâHW²Á‹çÀ>�‡ï4¥EÐ2/´+°Wš5…IEãö Ý"Jq…PÈ|ä×Ó§,dz±;”T”_²<îÌ19¦å? Š×aä†`_æGKÉĽCÀ¢!m¬t!é9ãáìˆ2æPn°CØá÷'k¿c7]{ƒ}‡Ô^[ßl·ì»Á6îÀëç°Š y J ¾ªKèÁÓ‡ØÐ¹&p#Ö~þÞÏ¢Š§LÚá.Ò©@Z¤»y…­P3 ¥�.Äó¦»öÚöØßø’=[°§OOäsòˆ_‹eNÿ¹pÆC<8êå⟸Cu’ÎŒ³ââE¼Ìr¯uÞ�õîXƒM*·á•­ø*ì‹ÿî/ì;ßþs;uú,Fü.,:bÄG‡#«%µ‘‰%5 p�¡Æ•tv= t›2�ðL™QØNöp¸Ð´³�Ô�pÚЃj _Šs‘j@žlB“�lêàA\¡o�±ì˜°w¤`ùi..ý¸vÁÂ[æñr˜¹ó*ÃVXÉà,…ƒ°Bâ¡,>UÃçÉžyÚ^xíel>ÚewÛg?÷é‡ì¦ ë­ç)6æ°+å§¥,6zv訚ö0é x³ßbøO?ù°ýc,$þèUì¾…ü4S–Rfir©žg0…WœÂ:L.�”ÔüÑR—ë.»ÈJ Àb‹ÿ¬—ÊÚªy’XyE š°8Y€ÎædÞˆUÅÏ2F•(**eP2ðåÙ)ËJÊx¥¦Œ)1Yq–q–]¯}éW¾h'6o·?å}#ب/+#ŸÁóÞhôÇŽ¼c8Êj½_Ñ¥štÔ!‚‚3†70S¸¯¦Þ³ œ–¼iÿ÷7¾e/bºOåº1âóK;Þ �•£ý2¶Êú,‰»þ¼ò+ïÊ,óÌ’}¦"‚ñ¢’Ê6RxíKšy%�Xp�ˆ$Õ•)ÃHNt.^ &—ÈTB¨[šå‡0lÆ-]©ŸÊÚ}Í<Øa�ši#!Ú‚!Y¹SÇm“nB7Þü0î· \/˜··ßz�Ù÷_|Úî¹õN{覻±â¿Ë†pùO$FTù:7g˜ó£ÇÁ ›¨ö¯é³_ÿÔÃö;8\ä�·ßö­—ÔJŠ¥œV}¢.îœâR? qôSøâ)\ {Ù…{ub¨È.U+bÄ9ª£GâJ^‡¥8QªLâ�U7‘�ØÄ»Ä+–�£R„òP2“‹$ ‘Ë�ŒJø¨ˆ¸Ï{è Ÿ²=÷Ým¿wú‚M#Î~lðýhàCX…’xÐòìüuXQ~¯£²Ñä >ï(9¶Tn3ˆ|õ?ƒ=õ­ÇíÿÍÚé3çÑðqp&:ê¬ÇgÔ÷õKÜ#�šN ÔëløÌã"ô<‚V �üÒDÙŽ$¢°3-æÚCÆv.àȰ‡ªt êœ.�YžÈ=eÑ€„eã�!ä! !–bC²xIK˜ßŸ{¹j_°z§ˆ§´!—ûåÉÃm³d„&0o�˜Apç»ï¼cÇ�¿kß{î)»ëÖ;ì³{ï·»6í²µüŠÞð<¡W?äëÖïPà�°uxú³�ÙÿºðM;9|±ªÕ9¬È53TÊSâHt)>ÁB%¦€·ð6á›Ä\Jôò;€PÊ=š!–‘ /ÜxDtµAãÀÍÊ-0<@ «¢Ç BZr¼Â8T^B¥�'@¨ô‘€|qy.“×ELý÷Üp­íô!ûÚè¼mïï²C“u›âpèÖcô§ò±CØŠ}ÿ#Øu6�—t¸> �•6‚pÊ.©CwŽr·õÙž‰³öõ?ø×öøŸ|·øxÞ¤d%•ŽÃû_.êÀŽ b ã¢òxá+û®T9�+J%¿‚ÒŒÊ9žX9—`‘ÜÏàˆ¤Kü‰ÃK§D˜òƒ!ì“bDÉn(Ÿäw[øœ/€È;†i3ÎÐprmÒóñ!oô‘ü á)ÕìH{ùöÙoÛ_yÁî¾íN{l:lEæ[ŠxaŠ­�P]l`_½î»éF»åÍ›ìüùó6‡�¯å[¦L§²Qˆ‰*�bq` åð ÈÁ«±A3\¦»ü€ ¨V¥Â@<´e±y³À#îEéªi«•+äF]Ñ €¬I†�L�v zØ¡¸’Ÿ—С\R“„rœÈáVË<‚{ä‹�Ø|vë/��Ùµkzíg6¯±ÇONÚ:Ü÷s Où¬ôÙ<Ç(¨“ôñ¤SZªC”óµWÞpî¸ýÉïý¾ýå_=‰ÑªŽE¾n 6@ûÔ Ÿò4’±+/¨¸$ÀÏó$`)ŸHƒ£&°t´ ctº ìñ&ŒtËt‰$8M™¡¤ DÔ© oÆKN»KèßXš �Ê_¿E®•팜Á°>K`‚Œ3ç|Àè��ö: ±/⣨ºÀ̉OChKí- ÏÛ8”ùÈéSöøù?±ç_{Ñ>¾ï.ûÂÞìΡÍÖ�Û†ýÉâØo1‚m7ßy×þð»ß²×_{ÝæñÞUr;SSw^>9’À%ßi Ž*mÊ{b �›Uš Ö™Hß·:€¢ÄRá„° ÿ”ÒÞdx�,§‚#QT^e�2TÑ]€ÐÁ” ”¦ PÑ&^ÄK �#*R:�Bq!>‚”ÆGI÷<°Ï6Þ~›ý[ìÝge:ˆ—Y¶`ÿC›ì� ®òS¾À殜ä‡;�&gÊ«tEI>f¨vË`¯]þ„ý¿¿û/ì{OüP/OñÅíœC&—0ÔÃç‘�ú„*¨Vÿ©9e*�©¸îjÊ�Ù@ÊQµ`‘!/)U z¡*Ã^éddêâ3Š¡L†±¼âÓèEcK£½“#c�/Œ–ŠÉ•H`4@øšìÞ{ï°þ®³gð2J÷ܬý¨ˆkq(ÅÎMÛ§7 ØØüŒ]@%ái:kpOxh çÕS –aä‹ÚrK4§ìlüCØLrgmÞžÿæ7í»ß}‹}ØÉ~º¥Eð~>ÊÓ7üù¸¼ ç�€‚¡0sLç×ÀHaT¡hRRJ´Ò/‡Ÿ%dû„ÔŒpB�–�ÔÁã¾BOº„?E#-yí`�W>Ñ!rQ�êú*–¥"\éÜÁÅAÄÍ*†AÂ2¤%½~±Á¢\Ù+ëö€ ?'Æ:Ä$Ø °ÌðÃÎÀ¯¿f¿{ò]Ð/ã^Ÿ_çÅÛ7=\cà"0ë‡óQc׆2à*­Ìeš¨Úû!°­Üö— ½ü€%�’u€F¡kÖ•`öÄÂD˜ßá¦AQ`dJ DYz!Êei¹|VCÁ´ åÕÕrÊ$“p† % ¸¯¯ÇîùäÇí `ÎaySCNÅ×c‡«û$V–^‡3îÜÐkßÅWi¶aD?�m¤°ªÌ|Æz¥¦Á$" ÞÜ�™ÂÈž°oÿñŸâ|x¾©çôKœòÏ•}Mõ¹ÀY Ó…æ §˜ë\ºÒ€¢ôü*ïÊ\؆ÜNžusˆÄË‚Æs &¼`‰„Ëò"XU4È¥„‹‹«K­³³Ó—q¢ágáâi’Qѱ,:êƒÌ†T¢ñ»](x”¥ê¦êKŠjacÇŒQ_,Ä£?–˲عÍâÀö*~ž9M{Ê¥<Ñ>Ù%…S}­æ®©€ÅåÚf”åðVº÷~B—ß(5W‡\QWÆŽÌám›F)>cÞ“‚€4àiîò(ãJ>å"䶆djòRºˆ¨˜šcðèi 4L�g®ß¸ç:[wãuöøŸ@eáh¼÷ø�ðyoß…Q‚£ýzlÜÙ»¶£ݾ{ÖÏ>`z|BÀ A8¤o¸lLéÇh²­¯ÛÖžz×þ÷oý‘Mã»yÎâ# ÅaŸÊÆ5ÄÑ,â—žÀHÍ�¼„§3ìx ¹/ÎrÊáéä‚ËVñty­84å%ÚG3a"\”ˆûz KÈ ßû‹\‘À«”g†W…pa…”¨l¾ªïȼÂ�L¨ªâR ;æÒyy¼µœËT–)‹ydá:2Ÿë"‚h@ÄE• 27ä@ a+îî[o²ƒ¸¯»ïßoÆá–›ñâMîÇ9½çfJ@{Æ©¹öÙ��gpï÷ÔÙÓØæ‹7ïЬ¹¥„F˜·�R:×®Å[{çðèO#Fg?z�)JßçÁï)I‹§Ðõ¥·ØY…os±¢hϺVúÑ€†Ž:*¯”“¬R~8<ŒNyœJsŠìË@!#P,‘It) JP­vÙPRƒ!))Äœ/*A �iªO„éde*…JE(¸( ?”DR( ž¡BVAV„2 ÕˆtÛ§<‡¾²+XÁ[Ãm 㤧Ì«;÷•÷P»¢=iHô.µœ�,Ç«DÈ-{à»§ª`!®Lø¾Â—ß4%W®F ç)=è\@Èa„|šŒ$ž° �¦BBÜ9âaY¯øàeú‚EÊÁ+¾¤›ð¢L÷1ýïÆBßÎkwáäÚ½äÓ ~;§ó˜J´Bè x;° ¯?��K`�…Š{ÂN—YÆQ�P w’ê©©P'o°¸xúÔ Ü2 ácæP«óS6ürã÷ʤœGÞ¨\Œ|Ðá^ rã=1´èE”ÑøÉ·%дH‰T$¤É�ßEÜ=^®˜Ó µ©†«ùœ'W–APÒ1á -Ê™ÎX²Œd«*ºˆ¥t›ý,@�xa\ÊäÛ¥‰”€ÍüX2h¬´,�JeUÍ -—l’‘tRr’•d'ǃ– „1�¬ˆ#²\‰úÀ—´~?ò|¢{$抩ʆ¾òâ $‡IxV ºœY†ÛÅE$„ÒbzΩÄ) 8�Ÿä!)|N[øh _²é·u[6áì~~íü¨ì¨ G|Ú9ºlûíÂáKv�'ÊÏ…£,â-×p6#Òt]DFl#ÇÙûKË\åÇœ ƒ�D•‰Iñ�*ƒÑm8Ï‹çAaf8uJ9½˜) Pg&a§ô°@*rgL$�Ù¢�Äœ Èœ^N@@á¹€ÉSŠø ìJãÖù� ¯�M`á²H¡OªetÖ…rhp——ê‘ç“yå_`S¾ä)^ðŠJvsB6xŸö³¬@‡¸fR‚4tÃØå$X•&å,Ñ&ª$‘ñ‚ƒÙeÛàßYá±ë—ë˜ó+à˜Ž€ò¤³ ^†ŒJ ¼æjD`®*°ˆ{v ú¤œ:…\àΛIðt"ˆ�‡¼þç`­öB0wÿ áÈ휺;»ÄwùYYذSã÷Õa–ûöÞn;Šgj«n¢e®Ñ4:¸ÂÏ9ƒ§ÁŠÂN†âT%Âí@ºÿ$ŽùIV8�–®�Oò•¬¨¼Ñà‚­ä”?Y2ˆJtUi E;®’Á�TÃçû˜id,X<”Ò=Yœ-I !Í<Š'FD¢1ÒVÍεL’ã8^…Êȉ$d¨Ñ ü‘+'„,½¡{ç °Ú¿ ñT¨‘Çýš4„@­Ã«4‰Ð&DE(µ!ÔÕ%¼•ÊÏîñ€Zê쥞Òü`þ•»­ [Ò°03À|ÐÔ {�ò$†¥…Õ™ur—¢Œ£0eÇ1�i’æuEBÄ–(‘n® 7Ë i�“n`q9æ quÉHWiÔ Ó&œæs&£‚qæÄ[(]AÃô²aœ9ÁL‰€Ó•’É0µ€ uû¨Ä—|éM4Ä¡O.\Y� =\k$šä':ùMyK8ÑVª±D?)�r…rÓGh0b±®úÖæï^¡4‘áPäðóÔ¹Q%£6‡•ÙT9“%— Ú†5‘¢)“á°å¨PC®h¤@ Nœd‹Zzä�ôâ}¾w ¬ð“[_Ìü6@•]Â.<Ò;ŽOé=óH+Ý*ø}$bèˆâLq´ ³}¶mÇVåƒ�E+ÉI­”ÆñsG #@÷Þ»ñ2š„fÁðr">�47~×8nÞ©cÄ÷]qEÕ‘™�¤zEbL¯ì<'eHs8iœYüï4 "E. ”u]J.µ¸/ùNW¢.E¦d.±ñƒ¶™=Cš)Ê…é%Œ ü©`&I�)'Ú’Ú(X”âbOL´~YOT‚ J¤8!A'/ªq`ç‹«÷îÎã#©cp6O¦`V”&‰„§‚î€Aãç�‡ph±Ÿ'À!Æu…} Û„±«oONá4`î Ôa• %}ê0ô¾>F|œ5�ÏaMÚécçìüè€ÝxË͘eô!-(¡ÿ¢è µ<Äk¨ 5¥¿Ò!XX‡Ë¸Q *v]Âpð0I„åI/�H@4Rzþ‰KPШácš¯{| )IŠ$(¯ì¨oK5­’€<-pçLW§s{KeåìˆH}øÁìrðñ¨¬ ò@Æä.ÒøIöË|%`±*0SW "]3-”çÔž_Lâ�4^v+ÐV^Vì²;tªgÉOy¥‚|�N¥$$‹ .{a 0èOQÒ»l’±rL™~k@`QJ� ìòòÕW÷?=ÍW:%x…†Í‚m8n_ûá·åXw8ò—}‘Ð7÷Lã'O�¶Î…N;|¼ÃÖo»ÅnÇëż£SÖpq e½êå9e T1$‡ö‘T¿(_I²G” ©*�‘LY‘”…'½\Ÿáó4bvN¸z ÇóêÜ~- ¹Ã”XЖ©<\妦 ‡¡=wìŒKòœÀзÌﵤœF$7þ2—Óë5g´œh’çùH±Š/¹lNIÛÈG)Îùeî±gñÍD6ø%6|„Ì‚©cú‰\Ñ!ó]zà²;€””ÌÌ É\¡’$5½&»€Ê*\fMùS,ްrŦ<Ê%©&)Oš;‚2^4ä‚'/%ùC>¿·J#9vªpôñAÈÞŒC<�ãƒÜÌ[æ…³�úÍY& vaðÀ;åK�në¶!›œY´Ãç6اý<>!¾C›Ž’:Ì ¯Êm ”YR>ƒŽžèUÓP$BÚ#Ëôˆ²�[â 8•—K�p¡”7NõÕð}çžÄ¹2Nî”)¹€…Gº”ˆ@´¡•Â%8é�7–3�D"°ƒ8G9 Ê®©s"*“€×%–ŠpQcƒ©` €7 ~Ò7Â!.Ç"‹fÞ‚yc£×HÏgÄ¢K\ág}=žX]Ò/d~@ï t¡ZªtR• ú%¥¥\ú¢ c+Ÿ Lþ—r&þË#•ÿˆM0ŸHxb"‹ÿ(O„.D�â ¸ÏêÀ ïãõ£\6r:Ü"lÄ-ÂÞŸÆcŽúlìü1-ÍGV¼ñÇ~øò vv5´éçíc‹6Û¿×~á«_¶«®ÂãFÈ¡FI/Wž¹)  ;•rOÝ�g%õÆ�HÉ1[äÖÕ#& ÿÎ$Ð5(E„*,Žô<�˜Çkƒ)£ B†œ»qñ(ý`NBÀS¢ªˆ£SbÙþ‰‚†Hzhj�Ô!_ ”D¢…˜ q«B[ÞJ €šöáUüY¸Ã\˜S¨ÜEéj©í‹»"¡$-åÎK€��—QþKøéÄáÈKJ)ûäp¤—ôX ãø÷½ìÀÇQO˜›gTþŠz8eDHvÔÞ�Ï+;Â*$¯,2㔩?J¢pй® XâybSÄy„—\Ãý:¾%‡^˜ûýU \£{̶aÿ>éS~¤ <;ˆDËYÁ… ùOyã×vQHèä'™Oü=÷öl¿ß~ùWÿ†]sÍ.9ÎW�ÝX”Dý=_Ê/ÉIO¯`’VF‘KqʦÁW¬ø‡|’HŸD>ó‹MJiq�Pׇ�`¢ = ¢åÊéR.eµpÊ^@¯±Éžn©Ä �pL'Ñ9×Ày¼i%!¿ªú‘/ |ëVÀ ò’ï¶§]JøÊl’Zà :R3�|n¿¨Ù_º·' Ó)\ÁŸ1€Zu)ê Yï/tÙ€ÛÅ«Œ«”«4A8ÙH±ÒΤ@¥Éâd ÅÂÞcEJɈªˆ‰-1&?D—ÄU�¾¨‹OLuaôcãÖ |6òA<è›a£x�WÏþ çÔé³ÂòàMû�ãþ ›ƒ`MêÕ‰­Ã�Ë8jZ· üÕ²=‰£ä;¶Ügû?þ5{à¾{°“°Ž×�¹ßœÊ'1è‡âLQve8PB3¬¸Û7~’OÚ›Œpº CÜG|<Ãç=þÿÇÜ{>yšw~ÙÞ»q=Þ¯™ÝÅbX,@‚$@$¤ŽæHŽ¡Ô…â‚¡Ýé?Qè…ôòg#îG�È 9 b,Ö»ñ~¦»§½wú|3+Ÿçùu÷ìîìŒâ®ºÏS••™••U•O=õ”)Ž/¤’¶'ž„É¡ Y)%bKB!±¸¸k¢Dªܑ²òœLJ”çÝ „"¥ܢj$RQà©?U ZÿäÓÜ¿„È£² -å]¼%cažiˆÈ]kó©ÀÄé}ÞGòYkRû¦Ä�­^Dåšþ ˜žL¼„?7i>ùþäæ $õ¼`½òHÁrª¸(Ú.ªÍ =U ¾8Yã]‹�–‚òJNá:ˆJ¤¤S½¢‰ôšJsæ)žßUffæ8-vÕú†Øù—ødÉÏïh_¿MÌ.óN¯÷}É Á#O| ·…E=ùïÐíW¼vö‘a@>vÿYïàäàíd%E¬ƒó÷Úì‹Ï=g¿ü½}vâ©óöÚß|ß®_»Áà"8n€œ9 ÄIþH³d[ »‹p�·‡7þB ™ä…Pzñ´$”@~ �RMçé»8 Ë{Ò&ÞQDäÑ %$ðkÙžâK™6H² Lü�H¡(÷ïJÇu•qÜ�¼0†E²äîòD‡†|5Úqž¬`LƒÊjìÞV6›øUPi4"Ò›w±jIȺ™*XI»ÕüÊ£^Ÿoö¡;ò–*Œ=Båmg7. ;±E'âÖ°WB�JÍÈFá‰ó§„¢#™ðI?ΫDˆ­{¹ú“¦¾kBËn.?˜·ƒtõyð¢ÑÓ_[|�2ÃïÞ‚ÿ‚gõy�°ÞùïÝáɯC#<¾¼�HÙýõ7¹3U³–ßHÿµwWíÇWöÛ¾/|Ë~ãøCûÎ?ø®�:uÜ{úîKŠ|Fš • _ªH9*ùJòÝÚíw” Oe �ˆ|Öž?ñƒ>\ÿ…$Y:†'é):â¤Cÿ/ÂŽRѽàûM°„KG„¨àÒ‡¯…B'â™iJ°Â%uÅÓÁ‚6D)Ø©sP3îÁ½é¯ìDå8ºìú(ü“De¶Éº�MžöòWªH„Â&‚ιÓYv¥«¨Ýi·2zôÐèȆH±Yt ?¥ªÊìrãs#�yÍ)À }fïÀ)Š’³ZA$dU–*�*$1 ˆ_S¸9¶Ú}åäÏ–8xóÒGWì—¿xÖn°õó"�P‹|ÆûúÅ_·5MfÖ[¬õ§!Ê‚7þ»ní'|àP[T‚¹Õ›vo³>/yEwÑ UÛ›šÙ²™¥.;tø¤ýÚ¸�|é vûÝwìý7Þ´k×oг`§!xúŠº’'‰™w_ñ†Ÿ$ ãç?´Rà"!N||ö"~wEg%´;£¤´šM¡+HðIV‚;AZ Ò� ^ãbn;ÄØ®hZp+h-L“»G‡®º�‰*¿VñÀMv¦P竺òü©ïiz¡DòUJ5UkdÖ‰ ±‘�V|B.ŒÜ‹ßç¯ìB|4Àãïêds+ÖOÊñB—qÀ�‚ô.–Xõ+�"¯¼ù@k�þ<ÓÅDI‰%i „¥°.8/ n-ÀŒ& wºGz¼‡_¹|Í^¼7egŒÙ{óÞ°vØÅIŽã†O|çÏN¶õâÉû.Ö^ôÄ0�Hk TJSãZaØÁ"£®¶[ÖÝ»Ÿ÷ÁÓÑPÚà¨ÇÀ[…ݹÓaÓ½6Æaã?wȾþÒmáúU»úÞ{v•£§îOL²”XTˆFºðL•,*’I—ð»Wù*Î×â“XP%´ÐUÁ¿"miü%ž›ûˆká× O–ÊdˆÔÄQò'§k»7r >UJ¼ Z0€ó_AÝ#Ü?}âY9á%Q…€·àȬ¼?å¹×N~( q3¦æ'_#FÁ*²òÔ,›¾¢7�² 5£ÇÿØ ÞüÉ€j¢ç¯d’°º¤¥yœŒ(«ÊD*Ôë4QIšc‘)á *gïXcbŽ˜º �_“a‰QÐÓŠ”Š?�¯]¹fÓ“Ó¶ÊàÝÉ}£6Áο[ì2»Êfn’€þ–çmòÞ=v j·a ée}@_ùõ²ÝW·O“¥uÓXÌ ØýÛ·9Qè]ÿÒ0ÚþŒ÷ªA>Ò•!Øâ¸ê‰û=‚vëµg_äd¢çìÂÌ”Í\ç«Ký(« ŒÁ"½ŸPä´Jñ\?ÜÃËII_ïùÑàj�92Á ²—ß•çì*Ž 9Í�¿âå$Aœc+÷pi¦WKá”MSÑJ—ò ZÅà Š¼ÖQ!Q˧¿(xÏ…s¨Ù´HÑ»LÉSÆÚ_Í0ôþ0óØÄŽ{•Dí�6–k’zê­M·Ênê¸"kaöx�Ç6™|4ê6–änR;´f7 ä$³ÝÚ �â‚$²,*ý«ê_Îa%Pƒ@Òµ¸@ÖÕ}ŠÈŸ0HLïÅwx¢Ïßy`ó�L ñù£'íÆ½;ÄS¼—ׂ~zdÏÏmÛS£'XÔÆòáMVnú+ÃÜÚ¢Ýâua�Ù\ËüVèlÐ#XâP‘Õ¹yFügmü@‡­­žõ× º@E0Ú+5¬Û–g»ìê†]ëY±�Þ}lR:jçžyÁž¡×±tÿ®MbîÞ¸n÷1Bff˜ŸÀɶzAï+óø² §~ö\™Ê§;ðâ¿”2p —U Ä "ïÎÆ˜\Ó91ÔÑ$ @È4½y¯,x¡mÐyÚe8Y$å÷"W“•ûÉ/r�„Ò›Ž `CæŒs0�7ÍÔó†äÑŸj2Âß F¢ôЈB# ÞJÞöF²I¯b-UùÝSzÑ|V÷Ø@Yl±ZEº"¨Q#2ˆÞ€•å€Ì9­‡åH8xDÁ“y�ŠxWA°rzg tW‰S"KàF(‘Ci‚)…H<ý£Ã9ú>xû{éìWí�{¼;göõZsv8Ê&8Çïê­[¶ÈfŸË|Ò[U§á©gÀø=*�ȯôlã:ÀÔ>D _ì¸foÏ޶熿À‘àÜMSƒ‹$òÊ"eß ÉL; µ/ƒ?`#ÇŸ²}§Ÿ¶£lU¶9;mm ÓÆØnìÁÔ¤ÍÍ/ðºÀ$_.Zr(=#NÉwx*��êØ®¶ ½ÓȪR°rQ> :¡ópÃ]ðÑ‹>PĽæ/ú…æ »Àm”eÍBx…"*GÍ·ÔŸúé_S‰o#ä4‘b\#Nœá�Ðjøêî—ŠØ0AurÁ1dI¨B;ÓɸGº{ÞŠN GµÍ[ˆ{jᑸîB~l  {ÇãúòÂ! ÚEˆ‰JV%çÏJöP³‚‚ã±*Hþ�ÚïE¥À¤hx7®É6ë Vƒ hдtS©ho¿ù޽ô5Ž‚:rÒ.¯ÎúŽÀîa–íöÍÛ¬ÃF^üÔЕ‡Núïnd4 x*0ñÞ¯]eúöí³s=öƒË·mz}Ù^gƒ�³ƒŸ³Ã§¼'ჇEö"°wíÅ¿«mœ κ݄öƶ#™í:h_õeë˜ß´Ë‹¶=?k+W5ÏîCnßâèª ›~ðÀØÓ~EF�ÑéMNÃùçNÂEÍá+ºN´ŒÛUÕ*V!¸‚N–CÁÉ6Z‘TåShO‰:¨0ð@–¯"1c«¯Bª\“ÒŸPULñPNñ—aÊÌŸôÑÍþª£µ£8q�UOåZ�šÁFD’*m{a#(s�¦•NåÄ,ð3yÛxv+!•áR¼ã÷Œ+3Ê”þ¥ý{Dè ˆçÝ3ÓÒ#DJqÄÄt–Šðÿ€r­£#=ç–—R¨Â‘¸4_m×uƒ§éµ·/Ú7_ü¶ýéìe;9¸ÏNö ÛŸð!£úFƒ×>�ÂÖ3Ÿ‚ª JŠWïâL¹WžÕøivvh�§÷áÃöàÚ}ßRlmsÉÞ™}�™wHãY[Úd¿ð[^ $NE›ˆêȪn[Õ6ÌÆ¤ë¶Dïá÷Öì'÷±{qßh¿õï?ný^¶Q}µ`¤³xÿ¾Ýºq˦&0 “6;ý€eʳÌ\äÕdu-f§!¿kDÙQ9 ‹»â)¥Y€Ü\Õ�$õÉ—$‰$ÕšåáŒ�89ž0ñT ;eI§ Ò*Up[c„�xú7$*^ݲÎÉŽœcóý^°Â¥ÄW€Ýé%‹‚éAˆwËB·á­ÓHŸGF…—ÊÓ]Ìý—ž$üì÷'`$jiT•p‚HÝÂxe®²VÀ™Éj�›0e)óžI¼ÄWl#nNTFx„„S\ÄçÍÁîõŽË*çþýø‡¯ÙK_ÿŠ íë³7î^³ ]£vbxŸ]}0É»{LÕãYOwI"ù×¾Þ5Ó¤ñ¾…°�ß?bLÏYçè˜m³¨h�w÷v*Ý{Ó—9]hÉ&gú¬oàœ cpøš,®µÈEl1T–$k�Ú}h’ñˆnÞ÷5Ëp…½§Úhø¼jhÎBûLö ÛWÏ�µÍgè°uTÇ]½…uz Ëô–d\àÕa~zÊæL3^Á|N»Õ¸‚JñYŠŒsT%îN¯;’±QVnì�JHòï˜Ys ‹ØÜà]_•ßš0SvdÒÍzQ1)žHÙk]@ Lžy÷X«ÑûÎ:™AG¬ ©¡JÁ=M4|z!.yÍÐ^÷à×ä–ÜwâGÜ }Ôðc=Sà–b£”rsI�Wã øT"×/™pXpHCÐ|(CUÅ*ô‘ÉRЮ')Ç¥pr”TaU’�¯,6•U3ù>üð¢½þW?²S¿þн~ïŽýÀîÛ7N?g3ÌõŸ£aÄû´ÒRCWzÑPšÓT!ŒpÕÿëó .^×Ó)†‡¬½#À“x��…~tï�}q¬ÏþúÃ÷lüàóvüÐSÖß;è¯2 î‚yø¹z$¯ @ÏÄbèVq¢Z¡Rß\Zµ¿¹Ï+[“_™×�¦�Ö=0fÝCû­ûøy…ï=ýÙ·ðhצÝ{0k| Ù˜ãkÈÜŒ­Ló rnÖ–ÔcàëÇÊâ’­,¯Ú*ej+u}úô=�¨.ŸÒø‹lQÆ•èx¢tTÊ®B?�tˆS$™îuTE! §¬ÊD|ø3:ù£#â4k36Ù(úZK"A·gR:nàDºÅ¯ÊÝ—¸uú޹'Yâ–è*¯ ¨¼üt«¢+�îylb4E‘(N—Å&èW·ª¬¡/("�Â3¥láJð)½ ;X£Ä ¤V¹’†ó°(Ý­KâÕ´N–A5 çÕÎSoÍþó_ü•ýÃóÇí(Oþ˳w17ì 'ÎÛ__|Ç嬺ò€œþ�9 §Nã“!‘Ìävfß~»Éã2«¿Ô5g �}»¶¶ù9›š�·kË=öÅ“ûì?}øÛ�ß±#Çìоcl"2æëôj }¹$sÊ­L”pªEÙÕD%Ÿ‹@o`ŠÞÁ܃†½m¶"Yéa´kO7;a©�>öC8>6dW{lkàr¶ûIGý䥃YŽmk ƒ®ð9”ÞCÇú¼­rr’ŒÂÒ4½z3ËüÉÇ"ù\_ÕxƒzZí&!¥ßÖ»ç!pDéºÃ5@AWâ�‡Jv·S= ÞÁ·ÖQ`# _“väÙÁ£ÈÖäêõA—4+E—pÜJsÂ’ŸdRÑ é>Æe&›É�î’{\ƒÃ*P’| ×OõøÀ%E`*©,wXooÒ.„?Õ:ÕåªR�uX õ‚QEǥʂÄt%^Ác î 4qpÎE¶ OÞ«P(S•GOú%¼g_»vÍ^ÿË¿·—çk6Ý;o7gïó9pÈ>ì´ýäÆe YOùBßÎH§¾Ú?Ð9Ñ褶?¹rÇŸþzÒÉHPÙ:ŒEF#£ÖÑ7`1(xp_¿½pxÌÞ½Ç7}œÄð ö Ù�±q=hýƒþy/¸GZ!üÒ¹@Š””Œ�Ë£Šƒ<Þñ¯} 9OJôòzcyÅÚ´,ÚŒ¯™*,wêe´qNB½”‘ÓãÖÅɸCÄŒÐÃhS×™ÞÃ=£“[kvƒ5 SS¶ÂëÄ&ƒ�ðÏñª±¨„^-sØôµïªÒy$å&aÂyÍ!XC€;é¹W8YW*ŠB¨öë³ôdˆ$o! \ x£^8°Â_›øžna(F�^­ˆ-¡–@ͤ‘|á‘ò6ð*¯$*o ñ™ï�oTk4Ü/—ÒI!Å‚za»‚¸ ´¼>×Ïa„�¦d¸<ʪJ otrŽÞ*�¦Öˆ¯ BQR3¾�JÀ’¬‹4!´¬þ¦Î„£Öÿï¾oÇNŸ° ¯ž´Ÿ¬_²ŸÝ»Ê«À vz߯¦0ìëïœ4Ú¯›èÀËÄ» û§¼©eVb4d½1"‹zrmLêÝÀ^§Ký+Ï>eSKoÛÄ⤠Œ3ÝxÎæ¦¬ã&“Žè�Œí·CÇ­³—}iÌZi¸«g�ú×=žRëÅѸè©ÉЇÍc¸ö ±ó�νÓ×I‰‡…Т|\�÷ [Z# ­dÉ(švJÝæ¨óû½]öÂñö³Û“¶�©ÔŸ;vÄ>˜[µÍ¹[à h0rŽ]’æØ,e†9 sèp‘КÏc€§AéÏï)®ˆ WP¨çÆ&â+ÿôy{ýþ%ûáÍ�ì—O>ËÒà›çi¦ò“T2Qê¨ë¯‡¢¿ðÔ9Ë翟N<ð§°7xÇ[8\¼áøm$Ûa?Ûì¶ï~ýçí_üõk|ÏŸ¶¾ž}¤ÑÉSsÍLÓhfîÛ™þyz ýìc8`ƒýƒÖËø‚Öñëë¤÷À”é"ÊiúuOW`²Ý’ßÏ`TëqrÎðë×}ðÔ¯}�ßJàe⋽´-NTšëܰɑ.;ÚÝg�k6ƒaX¦«ÐÉ^ˆ]G1Öð¬C9½¼t²´zsfÚ–9…éþõ›võòU¦Vßv£°Ìk„6Ëð¯)e�£j'E¶fÒO”?åe°ÔøÝ  `f=ðT7ñ‘ÝB1îÙ °±·Õ‘R[75žÂ;\•©dš¨ ¿5ê¿Ã½ÔÀq“WQ}Ï“1Í”¥ —_ Á];\JFÕvmÃD†£�„^úÒ9xÁÇël¤^”Z'ã„W®£DI>7ΕJN‹Ð °Úï&ßÓÿä_ý±ýö}ϾðôsöîÄu{wyʾxêiûë�Þò§c›?.i"ꈬõE`´·×wÖ¹Á`š¾çû+ y×€àÈtÄ»¦Fî·ÙqxÁ>dzñ·¿ü’ýû×ßç"£üÆf¢N¸EÃ9¾ÀVèyLòäì`$¾:j¼Ÿ%Ë}¼"ôõ÷Y7{v°¡M}ÿÒR«^‚t ´Ë/nQ>�Zû…ê:Rž<Ñ(ŸÔ»z yWÏaí>_Úö1¦ÀD©©6vRêbƒ�Æ^w´Y²×´.Ûë·õÃlýÜSvø‹›öÔâŠ-2ž0˲êûW1×®ØÄ­›6ËŠeEi…�—9å›íFáxÕ„/BùöZåý>%•ä‰ï02R‡•“tÎ=0Tމo¢”ØTû½f�üšš –ŽS„¨8ì@«ùMâ¡:-¨Ÿ5 cÿXîÀþ¿G–ŸS�:pØ–1_d�¼ŽÀJ%J%ž‘êÒPR#CÍpæé;M”*�L(ò^x4Xe ÷€¯|*ð\V�ÂuÒˆîO0¹æÎ´½xöY<±ÏnlÎÙèЈ�Ýo÷Væü�Ù–Dàd<Í©ˆä»É·xÖJc­ðÍ�OxsjÏ=÷´½¿Öc=½‘gàÞÈI=t­�Í6m•I>‹�ùé›0C£ãû>†EïÛZùè¯+?î ¹uÏFßÁ8Fe”+7 µ�PO!q�|Tøn$ M‘ÉKœÛ¾ŽžÛ¬w¦Ãú':mà^§õOuZïR‡uc44¦°MÏA½•6 Bïà°í?|ÒÎ^xÞ~á+¯Úè‘lÿÑÖ;€1`¢Óy\çsdt÷Q^£MK• ¶:Aó1­¡‚M­A\7꨿I—w¡Ê/½è®Y«€¸5ŠØ&�*_†Eí½ÐUž�, âlÿ«5T¢çd�g}=€Qß´v.¹2�9ÅÙÉ|).Õ'�T±N¡rmD— J]•ñ{ $ªî^Y*\1jžÆnÝbzí� »pôŒ�=h—'˜ÓØf´j�üÝÌöë¢rïã'‡Ç8R¼ÍÞŸ˜àI wç�ré}LÂ@IDAT”¼“Gý)µH: ¬ñ�zŠ~ß8}Ø>¸Ëd�¥yû…s‡í~ט=Xߦ;Ýo�ƒ#Öů£ÀÚØÄSº–1ðéÈ0�\pÇšmëÉÉ(ÿ6=ƒ&uóç³ÞÙ­Uëd?Äö¥Û\eè\=Õ5¼ÙÁ ‚R8 �¦>«ÁG� Ü , úTºÊ0HǦ¢õ8†[º–Û­wºÃ1ƒw»làA‡õ¬’–^_ºÔ3ضƒ¤¾ÖËëÃ~;~ò;óôKvê©lß±ãè¡›/&>=êŸ'¨¿4?ªJ'è^1Ý%eÖÊ,¥Š¦ 8>~7ÀITÝ¥((²ñ˸Uqxä—sX ˯*ãˆë‰š`¹ô(ôwï>fà±Çh÷^XWŠöʧÊÔ¨ÞŠñ—5Ï,•Ò‘©ôòxîóÈ€†4Q|›`Ea9'q 6º&¨ðm ;Ðñó">ùÁ ·ón¿¹Å2`æÿwP;»ºì�·Þ¶ùÿmÁþ›ßÿM;ýs§íúʼ=7vÔ~Þý†XžlÖ‹ ¼][ßæªuo¬Zƒ‡ôÊØ™PuÊÕ@vX©¸e]LBša”þ£;3ð$Ü�tȯ3:XùØÑIO£‹ÅP� âñ°«½› Gì 7™7 „XþÄ5L™Œ‚ÊSö{å/å\àD^Ç%ªèd�±g¹Ó†GPƒÙìcUå~Nk>Ùf7Vذ•õQtÈø2`ÇP<öŒ½üÒר‚ý¢]¼ø¶]þà-Æ ®ÙFÎù‹¹ ’eK¢Å Üê$MÔÉfœûë $âQ2%…¥¨«€àî2=âœG©¿ ±ô•XÁ7B?WPEñ*¿È¢øxî± €„÷n³W2Á¿d̳Xe$â<Ö3‘�QIXyDT–à&¨ó÷Âç05dç¡~ÊïŽP $ qÏ üÈ+CÐÎ|{Ý5²ßÍ'»ËW®Ø¿þ?þ¹}óÖ·ìô¯½b]§ûìÂØa{ëÁ—qw¿¯|@#ìf?@ÎÜà;ÛÚ2†€™y«Ì ã Ï©˜6ìßãyz+ßz‚ççÄÞœ´oŸ=bß{õy» RÏÖ§Ø ~�1HƒÕ‰EÝ’É¥ïuFÁWiåzÇ^ÄðÌ1sO+×´ h�'=½m]õâX»]z°ak¼Oõ­¹²ôÕ+ÄS†7ÚæC?0–áÒk‚oÎ<‰®Žn BkzI›{[¯õðë3H•qІ¨N¥^€*ºØc(tW‘–U¬Wœ 8ê²ÀXìœk³¾YW69�•¼ŒnÛS×0•wòE¢£cÌΟxÑÎ9oS/ý¢]¾þ¾½ÿîOÙ?á[dF€úOä5 �Íž²Ž€çöƒ�˾8FWlÓKЧGÿÑ+�aðG¹‡jãñ£ëû¥\œbŠ0¸ó›3ðј‚PÛíÌȈ�?©Ê|\ï³Á5Œ¿~ü}]LI.F�º¬â‹òU‰+0ß@Æ`Ëç6mX‡®2�y]>é³ÅL[;·2÷z¤‹›§_¶§Ž]°+Ÿc×Û?´Ëï¾n‹2ú*‚!�ü~)u%2°ÐY‰×-]‘�‡Ü%o�\ûšèäLY“a7ÎnHâúÝ)„£_”AÀ?Ûõ± €l•FF”»Ò˜[õQé: ·d´*ˆaqiZÚ�ºSv[�� rÁ=üy-Æ'ƒº75áЗ¤hX|$á)©wüÍ *j§*Q,VeºÉ‚ýÏÿ•½ýÓ7íßù¦ ~é‚}åÀ —  Ù{¡×[ó6�]]5p"²DO`–nººê+ ì­ðN¾Â¾k�c#U½ P’¿B{4¥¿7F‹�xl ,9UZÿUÉ'¼ÝÈŸð¼™znJ–Ò(“"u°Š»Ä;Ma^�"�¬ýÁ¢Àœ.üz:ÊeLá²Ç ¼’¸(üSﴚɧîú†*'ŸÐ:ü!¨tEõ)ê�7ˆºrÅ^|ñsöµoþ¢zú¸Mw¯±MØ,û ÒågÔ{‹­F­7m,»I{ô.˜JÛÇä¡ð6Yº»¶¸lƒÈ¼‰±¹Ç¨ý Vé�Ø?jϱ·ïÏðÚ@Oañ® AFÉ6¾ËMF•eo.4&õ˜ûyï㩹 -Ëxõ Ò‡ …dÚä=¾ckÉi!>Þ ù¬©GåUa‡'þZø ëÞ`¿Âá.¾Hh7"ŒÂ:Ÿ‚·øLçFãðîÝö ¯6Ë|â[%=½Ç¯v¬ÛjûºÍô°Þb�ÃT7Õ+ê²aŒÂÉõkŸî±±u^‰ô †4zmˆÚàRûz†vzYûÙÖ}?K£gùbp÷@¿-ðy53ÊÁ.‚—Ž~Î.œ|ÊÞyå-ûË?ÿS›ºú¡mòUÄçC”|ºÎÈÓ.ª€]¡»P*€˜|¬ I/å¶¢+Ô IVm�“XþS¡?¦{üyšÔ¦‰@ú È<€ÆgÀZ62@�ñlTy©<^‡àO` pð @uUM¬p¤^ªX'©¢ƒÁC®M¬FÍ€—’PõS3ÓõLÚéöè“UÝs…5*þõë×íÍ×ß´;ìþÓGe>8²ÏèÂ2AýHÑU�WŒ¤b¯xÚvOŸ½pê˜}Ägº» äµS™/óIðΡ‹Í„z 2J›tÛ;;ûi”QŒ!gr ‘{zÛmP³ñºéQôõ؇lBÅQš’GÆCt±Û�~›q.SÁI¿sv+�.¸0åw°·ÓÞ�]ô *�±nòë¿A¦*3°—5m¬_`ò´={h¿Í»ñ9¦�Gv›æ(5þ7píêgoÅÎ%{o{ÆnöÍØm$g¶YW@~»HV³.´K¦4¾¦èÁ뽨ƒ3‹Ö�¾Vz:mÙ¼‘Ðû:~„×¥ÎQ:xÖ:œ�_š¶õ……�Á3—9Ì»gܳ—ЇjÀž®�éæÞ›€ ãêèäý��¼T¥Ï€�-�¶ù xù¿ðD †8(P&éIáNyK¿«§T®J u6å T|òDT<”«@°õ«ÇR\=±ˆ*´ ìâ•ÒwFî7Ó.²«á–Zéè³OG}!ð8ùy×׆·nÞ²ßyß&.Ýd²Ë¶�÷�Ø>Vÿi×&_ÇŒWR8Sx—tÔ¾z0(§Y¢û·÷؈„oý�|û_ãéyŸŠ¿~ö˜]›ã «±ŒÊÖ&Û„ééKúîJVtÓS`8è@w‡ ñUãÒ4Ÿ›ù#Wµ,zaaܾ¥ Jž3ïGÊÇñá^f<.Ù’µæyN‹¾¼sk­BWO�­a(G‡ìÙ3§l•‰>Œ ô0˯“J­¯ Ñ[Ù²ƒÌ\œš%_bÁ{ý†uŠ…70 ×;0ˆ«ÆP(F€µÞMZü|÷AvN>43k]¼®,2pÚ>À—‹¡mÎ[X°!Œå‘Ãglèð1[ÚZaYóó$4V£<ÅI‰î•VÂë¹� Ãê‹ÊMBe„ð‹?Å}Ú¿š«|!‚4DËyõL@:W—þ+2ûe}ï|Wª¿l¡€†n#›u®Üçñ5’TJ(0ÝòGAd% $¿ù“:à…CüºREfT¹7ƒò+]ÿ¦�ùHg‹¥†"^ Q?�:|—•oßûЮ¾ó‘­²ëð0g†m„©¯<éy˜cÔ�U»‚§ÖéÑa{@ú£éYk4áÏзíæþâÉcv•5þÏ7ÿÍ Œ‡ª2ŠÃ68Ì{6ß÷лñ³C=vsŠFA£ÊòÈJ–ùô ulkM0Ž�ó{`‰¿ð4ãñ0qoL0è Åoò ¯ ^d™ q¥Ç0HÏ`…¯½€>ü2#c,‹±17'—¡D„-V Òåò€ o`¾lù.¯WYtt«cÃæy7Ð{?x2Õ€á(›¤îc¯‚žÑn»J/cf�S›áÑÅ+ݾ<~ÖÖ{ù¢03É+Á2t0W#›x2¨\DDøÊü¨‡Ùø�¤AßÊ(u^°·ÄK¾ùšÕjöŒX/ùkGïÊ‹ó?kvÂîó]ñ*_n‚¢põp€ŸÏÝ` r„} :§lŠ×“•Ÿèù w ØáÃg­}tÔ¦ç&}«4ÈY OZPÝ,•­ˆ‚:Rí­|Å#bçÐ iááH­…,bšñ�›÷øTì3±ò<‚Þ½sï¿°Ø¿ï¸/Ò`ØÁýãa0QàµðM¥DEkBJî]áõj'†ëµÒMñ”Ê«8ç+E˯—Û�®Užc�"Õˆ}É­žìzJ!²¢ÈÈil@ ‰\-�<µ!��OlSSSvõÒe»ôÆà½�låú=ë£ =Æ$›Q*û‰}c¬³ï²·¦ˆ�7¶ÜØBi‹ÿU*ôWÙ@dž×�%žØ�Ú0DkìëéG^åDì…?ýÏ vc„ØÞ|™…D6\†TÝ]u40)xãâÓÄ ?�•Ïžo±�Ø* ]2%VâêØ,wI_pÖèŽ,0÷ì�›æÉœ®¡�îõ{˜AvCWýé൧‡3û˜ö<84jýýÃ<{ý•!ç-¨A w‰|݆ÇeæÜ×@-¹â×…û˜ú|j��I˜<5­ýTNÐqv“;f½Úô2ç,ð•@¯?uÝE>”ÒÚvk™Cc™îUǧâ4€Y;Å' ·ªÑ+Ÿ&£1ñŠŸÎ¥ÌÅ@ÿu€Ò8¨W”­×€Z‰UŠ'²©«ûª\WžŒi�W-k8…²Ò ±éw´@ˆDÒ¯ç%«¨ËS;¡¨»¯_ð@¥‘ yˆ¢7xÅéµ@ƒ„2ŠÆ=FÓã.ƒ"š5¶ÚzÀŽ97Ø�è2Æàú[ïØÌ‡—mëî„-LLÛƒeûØñw� ÛÉ{´œÚ‹RYfÿþü¢ýÒ‰v]Ë…•Œº„T|í¸BÏA{wh[2mú,ˌ߻¯\¿ÀÊ]Þ%gS‡:­h«q•Ö(_-:xê¾Ë¡ªiPœùRžù4ŒT¤éb–IPÝÄŸ±È*7ÎÀÝ6ošƒù¥Áy©�ÃU:ëàà–>zMýzÝ=¥uZ’z¾Kxsdú&ƒ€‹‡»mŽ÷†A„¥‡tfá�uÓ+¸ËO›2èðî.¯}‡Æmz•½Ù6øD?Ãep ¹(ÅÕ>W§Ôç2úÝý.‰SÕ¤À÷«è">y?ìÞ#@oQ'T…Ø~ìÀc¬„%ùÐõwZiNÚØåT áÜ'k¬`=*ÔñŠS¸¦r3¤Z�çlæl•ˆ§üåÏ”">®:VK _.øáà§”•¶Ct¡±k±‹ïÝçO^ oðY‹êŸèަ1ˆ=Ô3Ыƒp˜ÍǤ›{LV¹ËÎ9o¿ý¶õó”á½xôÀ9ÂN@l+~˜ F69:lƒ°À{ô¾-^¼;i_>rÄþnRÃbRS4ùÕ#Ó+ôAÍÜšå\zƒ<»yRvñS/ÁÅWN*öò+ªQ­ÜlÃølÇh¹�ÕTU¶ã|{Ÿ­¾¤‰,Åù“NLq®#pƒNÝvõfd˜ÊKoèÝÉÛÏ$žƒ ŽN27Œ¾>`z²:Y“+ÍÂÐ:ùe�ä#ËÖÃÀ*_:ö“}~dïE>»®0ÏB½ƒNŒÀßUÿüþŠ½Æš‰—ùñç>¾u‘ΠòfeÀ‹f5¿( Â¦Ð4CÑx#ÂTÞôèý^Ÿô¢«/Zqׯæã¾LTÆ«øõ$Ò{¼ �7DMg¥ŽøDñ: î¥~Á[ãa Ö°Ø"_–ïØ­;w¬ã�·™õÇ B̆y_Ú¿ßk‘q˜½;fϼ°l¯ °;[�¶Áá:X�f�'«>=žæÓßϘø³ßYš¾ € Aþ´³°Òö!Dù¡`S­‘-Æ;5?@²AÛG7ZËwo±lY}#�ä7 ‰^e<ÅL´‚,óÿÚÍ{öõ~5â~vbÎ?ë&z�K½ÉÖ‹°t øqÇßÅ�âq�‹·Ú¨lÑLÍ­�a–J³ërºã+@ŸïÍ.1êßk×.?°¿è´÷�²ç™öü›»üæõ7ì/Ž^°»}£l¼²ÅLÂ6;3tÌÚ^ý¶ýˆù“ï½CO@e¥%ºŒØ^ŽH�×W‚Èk‰Ë ßUwB'Áÿ^hèU¸N�¿V�x2 à•d‡0MC��%P2·RBíÔ äüš(utñ©’QÅ £àÕí!4b’•r#Ⱥ멯§²œËÜ<äÀÆ%ÅR~”çúé@:j@½Dc÷�B1Ê×féÄ`aƒˆ{×üÂèU¡Ìdâ#Ú“ìœÓvE“Æn@½ô.3Š>Jï wL†á�õaºö´ö1æ pÐiÿ£ú|ø?@×1æ4ê ËDrÉÛOW¾¯“�n*ºVj5"Ce¥4Iˆ¯m¬Üfý�æñá»Áü Pê\Ø„¾”oבÊ"4äù+Ç!¿ž›Ò²04ò'ïØwŸ9Ç»y‡=\ïýaT%£^aÔÀ•Ö>vø6+F0‹¥ÊJZðÛX¹¸Ÿ½õ:zó=Þ):gìĉm»zeÚn1­z†Mk.žý¼}#ð­[oÙØŠýòÐaŒeEZ§�Ûæ—~ÍþžeÆÓ—>ò‹,N扔qÊiäÑï ¯G—‹dfí2y Mdl2ÉpÜ}ÂRrJù¥·ûÑCOÆxMUæ2ƒ{ ¢F!ù]-ç¡.x¨!¹s|.ÀšƒðSÑø�\±a]þš@è•ScSãW#®åOgVáVžXùqƒQˆŠI‰êëˆ,½îñ´�^�^Dçó4³œøE*G�óF$¼òº âƱÂÚ�å•Y?$ô&�ônçµ¥›‘în>i›°!º×ﲃQ7’ú0=#œ 0ºÏÚTkce!ÛípX Ï?h6ix-ÂO� C¿NÒ‰/ž}ä’§$&d˜†ú㛋žždS¶]’K2¸Ð\0(ú:!éÛµ[F~Y¼€šçý}£»Í.ñª¢ÏM vÈhzg,’ÉpRšn´•˜˜ÑÐÔëÚ†Núæh…ÉÞï4ÜÚ¶ÃGÇ1š—ìòeŸvÓ¶ÐÁ:|Þ. ´WØï±‹òþÐQR‹•Î �¶ÕW~Å^c0{áÖm7JÊV8e(]ÉX¹ Š·¸ðÕá°r‘ˆ¡¿*”žÈg„WuM~~RÂpOÄH%^¨žU¢íÓÕçÈÍ Vèáq¢ZÑžéT”G·0®qƒA„[  $ ~¯@tg«îkd )˜}Ì5Sȼ.¼•–¼÷à½Í`Sô âɯä д˜ ÂÚ„?`%yú�i@ z¥/Þ àL`œa»ñÛìkˆô(ôde5?Ÿ5ˆÔMÏ¡Ы½‡ùÔ¦�¢‡ÍLºðwb4ÚØtt›wçmpÛøô´M7ýðÀ–M3Áf�'·ïuHÂj”R+Yuç¢x=�d´c.aʤs—V9e="¶;wbØÞcÿ�fb„&YÑ)c(™ÅQLÊÏó CåI «Á{ÚE] åµ�õ Þ¦{CXîÖB¯½ðò ð¼fwØ«aiæS®Wí:‚&O½l/Lݰ3‹÷íR÷ˆÓhÇSŸ±…—ÉÞ\ø�¶Ž.Û|0ØÙq)™U°x�FÒÂ(H!ñ.ìD*wGt¿Ø$vÍRýR³Žú™.OÄdÊUuIKAe¤ß3+ dÅ-Jɨ¼Wt ¿pðŒ¬èÒSñzR꩟Ü3”Ú`\G<Ü×àë9QÁ%a¬‘š )EÞå¯J ô§ÁÁ”Y= 8«Qp×[J4øÀW%ŸH3è<¨–éšÑ]OU~¬:\b|�Ý@”œË(-ˆg=!}mèäd_´óP/Óyûxì¥ÑÏëEÛ±q›#¾›øâÚýÓ#ë!`àmåǹ’fd:Cž˜r.‘ØŒˆO¼vPûƆímzlüñêþ&*±F€®¸÷�à!Ï�C[TTG;Ø‚è}(É¡>¾0–°°*#Qt|Ú¥Év{ú¹£è�5 Ì^œŸ™°™›×¬ #ðúÁÓvhqÖ†˜U9Ïú=g{ÙÅô¹S/Ù,{=\zíïp�AQâúW¼ „¤ò'}è_˜­Ø-hpÄ ÜÄNú]ì+ìG÷‚‘>á*Mœ,gñײd¤cÔÀª!’¯"òX/œ‚Wסšpo_ÅE2<¦{B ‘¼©‡RöJ+i3¶!yäÕÑ+hÒíIÑ –7Ó#ù¥l¹`¬«žú2î zRpçµ!ÔΨ*œé ð0nä£ÁJ•%‚“Ûlhâ@8> ‚TູWñîWã�¡üäO<¼jU†¡ä^i*”iT†S¾1–ßf¹3o>Žàƒ’à䀲x\¼¿eŸ;1ÊVê³nŸXGF±ˆKs)ø¼PÒ‰ Í޳•Á¯Øñ§l×^ÿ �¢$ rF¹A O…é$nñ‡¾%µ Udí—üª@ÅSÝT8ÊÊ—dÓ kC·“ÀN=¶{l ‘Ú:ÿ)QÞ[勌Ì+æÎL{T¬Ôܸ¶Ee =Ö4™¢‘4ß ©wc)¢0MÂêþx”ªcíͯbžÂ&UƉ’\T IWïòºL‘ËŒQ>Tù£A˯”ï@¸;" C „å�´¦TÅþڱȟr-=9¿ °EO�§ª\Åð « žO<Ùg Ä"' Oݺaío1ÉêÚƒâæÉ—`/MAʧÙ�Iq1RÊ“Æôš#e«ž®c.=h·³çGíý·§|U¥^qz™a¨ý7˜T¤0ÊÇð0Ÿ?™Ñ=ßoÏ}ñ—lâÆ[æ T5>ñsç™Ö¥Õyl ¸%P�%9p!7£“·GD´0½n(N4S…ÅnM÷QC�mªÉ€ŒAÔŽ¢œ*W®°#¦ä=ó©ñj_M“>¯d ¸Ò„•Àã ú7}Õˆ†kå×j }¼·*˜¦¤ ’Rˆ•|U”Òû˜4 _½Ÿ»S#®h¡ôxòXXD}Ž8XpT-s Pmg†¯“ŒSœ>3ÌxÀ¬ëןøôu Ã.ôØßâèk€‘ƒÓ§_´‘ñ2½¥%$ ÂÉZ©õRǤ–[äÅ3Ñ' "wÓä-€ÂñÓõñÜ0™mAž¬®�J¾Ä)€ ^”æ•QäàÑ ¤‡æ±ÆQ%k>õ³Ò £¨:¸Ô$åºg„ZDf„ð6{í mÂ6*S0 ŽEH�¶ `•äÔ#O\%V%p' @Â¥ í’KK�^ÊNœÅÛ¨—�k{,‰Ä˜Þ…E¥"¾JÃcýB”¬E®VU‰OäÐwAOg_%f90T¿[?û‰o2r줼ð‚ݽð¢u}þ‚³ÛKZZìT.‰žðžX{ú܇Ùèô�‰Uê@äAJÉÁA 篒^44ðS›öÜÑA;<¾Ê²m–S—.½«�ND«*‡ö Ûõ)rO††û÷Ûù _°›.íØ¤×€Ðuˆ¤+¬ýÒÕÃ\K�Ü…Ú °x† ÝG {üûc€02[DTñúO�¯r± fé4zȈޫLÕ‚G`WXÝÇúÓ^`äµ®:0ó¸dô'Ü¡‘¥5µˆô±”Ÿ„邸(ÅW¸íEçP¯ÊÝ1/¹dŒj•ÜJ¼Z O}éÕûÀðˆæ˜ZH|e±Yõ´¦~Ž¡»Òð€àp¡®Iyr»'ÇÔ½ázšÉGr?Ÿ %bJ9—™é¸Ä®Ë÷Þ{›y jïŸ9o_üêWlä©ÏÙБã>ÿßB0É"f¼`‰îç,=}úóž(ðº× |¥©š@ÿú}”ãœÈ¼´¨±àíßxì{°%Ù:¯2š—À‰‘Ì(|Î9j·/òE@ï¡ÔÈXaë B0“ÓVå(X*³_ŒQNYÈ•×ÿ?Üc€¡\ÊVI=¤Ì(#•.§8›f(é’¿*R­‘³ùÔOܼ×X‚´†çï ²†÷ÈöÂ,yÎ(»±vCvUèU]Ÿ’¢âS;Wžx4�è�oo¹ªXz–+� ’Ï©ÊÅ@iå*J%’ã ) ~5&ýš52=m Qõé:Kݽª@æ†DòȨgB„î_–8 ôî[¯óŠpÜŽ}þ vîÕ¯Ú‘³Os *{’²Ï—@€}tÿ¯Ìñ SlÄS¯( ð½@ÀâëIy• ­5^.s\Ù™sŒ¼Ãî@ ‹¾ƒé�Ž ÛÝ9“a›•�ú·ãçžµ»W/ƒ+L½IÆS¹¦?�”A ¸húᤠ˜ õ ÀøK~�ÀE«%ñÐE¿:S vH}q¼«öÕ Ãô¯Ê„ú5ª•#�t’.1#ÜJœ�½·–Ô)|µKÅÛ€¸¸­µ†J5nM€Z¦Jè@èü¢µpöJkå�—†¨'q]ŠÖ˯¢Ä\ݨÑÞˆ•}ý‚»Ò•Ù §t£Ò—X$üñø�x!Å $…<Ú‚o|ŒiÐðU‰¹ñ %Ÿ› '¹ø2³qæò%›½~Õ®þý÷íØK¯Ø3_ýe;þÔ>ûõø"!m‰x�Ozµñ§¾ ­ç‰œŠw$áwç L¯Ó<ù‡˜Ð”ãú‚°Ÿ±‡MV .3¡H ¤�%Å2�œ–tüÔ3L¯þk?sQ=NéÑçB{`+¥½ùrv›ÎCõ…( _yù‰W–G“öQý�m\±˳„–À� :ª ¨@[•Òd8ޏã¢÷/ŸÐã•D‘ BVSÖ¾,>>¸ƒlG°Ð6eMP`îS§ʧç—Å­�¿5rR{Օκ¢Dõ´­u⥹‡044ï–­6§2I*[ø2¾ÂqÚÂÆË!M‹xÉ_8É�×M‰žöˆI�e·JOOe"±~žº¢ö2ŽiÔ‹Œ|tïÿ±[oþÔNåí¹_úU{åÙ³v‡Æ¯ýXNà©•ƒ^r“°,ÖÔzP�dr<`œñ€7Ölü([²-�p>˜}œêˆó1¶}c~Û¡ˆ¯z ‘{n™×–.šõ i‡«J¢¦jàJ_µ ¿×஢:ò3ùÛ(U)Ü ·Ö|SÉžT@Ç�œC[¢’&c#Òßõeê[pCAÖ¤ ê��LP±;]2šä¹k7ǤۉÙƒRc‰C†Üð6B b°U�“¤Äx#óî~4|Ñ: —xî%·„ÂCùŽïV¸5>BJ¯<áð:.ª×].ÚSV`5Þò¤%Nåêl ¶§ä…-C²‚�!Ð+C‡Ÿn¤n‚­Ìó¼zŠàƒ'~”» ÜÒ­öÞø·vçÝ·lë·Çzžy…[‰�$¹›“„RV1PO@ K=²o }ÈxÀóÇG9ui�ÃWý¿¯we<~Úƒ ‡ËÐÀ!*=e7/^T.ùß]‰(®èF U‚dœîJ \å«<‚§n ’Cj¿�C4‚ŸÅûD €çC‚KÉ{f´)Z ìÌšC ­ë E*|uÙ4›oGDa½ZCöi/`ÔX/¬¤Þ ­™›ð'öî˜ B…nÅj„HäáéO�‹[!Ikg`ý¼–„¼ f>ÖH'½ž˜,7"’oaEd³ñƒSè“�ž^áãüÁãcdž�@È%ÎD QxîæëÒ×øÁ˦ÿv7àÊ/C@ æ[ìm0Íšý?þßïÚ™¯ËžùÆoðIñ�ºõ&d\<µ-ýú$(†šuÐÉÜí3 =f˜©øÒÛ§�=ÂzàZ©Þ�6i㌂��A;>~‚×�.Fa"‘Þ_*…(SY³ÄŸq~ÏŒKÑ O�£e@<à Rý`ì8#?ãýÉ€LÜ¥‹ŠåyHÝx^üâ˜á«•ÑP�Ç'm(P ?ºü¡³&]$üjþ;ù¥x{¯JêQ¨›i6¹7d,(­˜„@i`5‰‹_±AÕÍ— 4Àçƒ`UE*Uª ·¦W±òF—‰=¼ñ“¶ –\…œžú®4¼ºë 'Á�Æï�hüª¬.gæ)¤sÞ¤C“v<½„?ˆ6SÑa,êÄa,;H}>a”ÿµSvéÿý¿mujžÿÍïÙÐøIÏ£‡ŒHÂp$cíÖ‡íg̨�§¹ü½ðêÂhÙsÛŠµ±&¡ƒõ ¬?æx &éìò¡wÕcÒ.Í#ãlIÆ&&Ó:D&¤ÕÔ¥`žC¿Héj@í+qOåO:@JÊß¡F}$ß5^ ;’wÃE–ì;â#ؤL hò]Ÿ »Ñ9cÓS…½ªf¨ÉO)$8¨-Øy·qt»Žl�ï‹ÇfªZåx㇇n6ìkßûC{úÌiëGo=0ïFgíüô×› l2¸·¹Ææ¤,=Þâ§7Î=µ}ûºìÞü[¯sžßýg9Ó�>'é¨`¶º¶l K3,\ZãT¦V Æ8@kƒ,ùUÆ>�ûx®#]¤$ýäBî‰/­]‚…´^ü*LâòÐL€�•õ§¾†i帢w'4<?…x«Ü*ªV°BQÛþPò]TƒY’*õ|‡Jö¢ÛK6áQ‘¸É§Æ°¥§‘ºû-.h�k}iÁ�†„åÑã�²BL-‡]ëúI¸+ÎãUA.&Ê�AW󊰢äã?篮3N�Ûë´qê”ëšò,™|½-T«$u¼Ú¶¶>ã©ì{-òz°Í]sã5õøöO^³·9GñÔo�†ö±/¸ðÐÜUGZÜ%‹ºõÞ{WúD·ÓÝïçäá/²àiqžü2çò¹q•eÊK«‹6·ø€=ç0¾|Ðf­L]¶í[’ÐùÁ÷¸�?µÜ‚cí‡}íšþúȾ'`¢ w§Ü*a3ä…Ìá�Hínë#ü^ñ@jÄ5MpU÷¥‰ç26�ÊÝïÎK�8ÿs�ä”+¹%ä¡T±Q‰hzÇßd“ËhBI> _ "VÒ€6ÅmDC$Œâí,0�LQUlC?©8þ’§Q°ä@ é®Ä~„hl)Sbø§@OG†A¼C‰Ê#þ~ ¿ÞïµRÏŸØ>NÀÎÅôd@:ÙÅX=€w~ð}fî·¯~ã7´ÓÚ~D¥…«ÁË/d­)ï’ ug—vØ<€‹ì¤ª�É·>¸k/<{È®°KóâóÿÁ§fº\Ú‘xˆmʽ_Ž0Û$àé¸+l¹µ:OÝAµ/1jˆë§€+h(%‘Ÿèý± €téƒ**,¤w½†ª+A«ŒT�Úãæ¢oݨœ]„¡ž\ûjŽ­¾ hÀH…–HqÙ…× ©½Ÿœžd®±<±Bþ)RPmç_MSwýpMÕöŠaåÙ¤8S™‚5…¢[B ™R´Äw´&näC�x×U2…¨ Å-Õ霫¿'ñC$…�͉ÖK´*ªÒô�@4:õ¢7 9|9`C“ V%~𣿵SL:÷ôçãS*ŒÁF¥ƒQU]ÃçuWîÐh'3ç}Eàü g7Ðð—ÖïØéÇl~Q»…ü:Ëp`�CKX$$ 9=/‘BéZµ?pëÜê$ ^D7)šØâò<¶�"½‘¸Qõ\¼:'-ÕÝßõYâ(%—Ü:Ïdç÷0íA±ƒñ;RÍàÃ0iƒÒŠÕJN-wȃC4Ur ðé` §æ:©yU¾¦Ç™´–@­K¾ã9Xd.i;lϧWÁ“$Ð'¿„Ö<[rTá>×OÑø]Dg£´øWcw¼J|~ž;ºûþ9èõúzúoj¿D„Òl?-C^œ¸oïÿô‡vìÄy륯ž+õ%Aã*2²23ô8k Ý–·17®ð´ç€–Kéï_ºk‡X0~p�mÛü³`›ö>`»4í»G‹_JïÏE\êpå«p“¦�^¼’/\Pù�Àɧ³›Á#@¤Û'ã�H*•`þtP­�šû±üÛ9"J»Í„•ñÈ©û g#@‹KU´wœ °rw’Ï™:\á%¾ß“åÃðJ¼ç?quˆ|…MªGÁÀUÃß`€Šå¨�ÆïÑ ^Wy N>�Üä/í=À%´�£Ž…|Qb-h�XÁ¡‚>+J¡®¨ä •¤—Açç�  ¸ºø…w¡¸’�L9 Oy�ºkÔ_ýx5¾vÖÃk#Wíñ·Ð;èÐ+ǰi�P¨Ðß¾ø¾MÞ¿QøD6ÄÓJË!C²¸ÊH~ל½qí#»?{‡¹ÿŸ¦±'Y~ÿÆeŽoã©?À®ÊœnŽë@�Ð#9¤'0÷ø…f—ÌñÈž7d‰{†kák¡jFÆØ)f™�ÄgvO‚GI<š“^¸äVEÝ6jA+7}Ïב[zßoqÒ’;§Æ'qVvUª`^P?ÍÍ…ª«djP‹ÏŸÄŒ*³V~%T²PËÝ;óŒ¿E_Ö¿éïHÐóZ`u45‡×Ð$­ ÞªÓ’—zì�ªñS[Õœýå™ –y<¹J§$ܦŒ\v¿ˆÏ´ H\TBü�lñf œ†¦Í0´¹‹Ãe Ôk”qàs`¿N¶óņ)ਰÙi»ë 2è]�¾T5Í,ÂnijvkêŠÝ�¾jœ:|ùîù Báê�ö­�ĽyÑNfýsº9ËQ8êi¸aR9H9ÜÜ�$]íKˆî»¡‚TÁs¹Ë1"¦µ°šŒÙÿد‘bfHJh¸r%-PÌá—õÜáøSƒÄ;C*žâx’5zCaÉ!ùïu×H=œÐ3É÷å5¾Ë&ãÇìûÌÍ0F@¯-2 ~Éš _ VÉ[yˆÚÃytâPW]w‰×J}uÔˆO’G½?! d%Mþv‹¡§¨æñ§‚„Qw�B‰W”‘:©9í†ÔqM_C+ -í¦Þ¡lXhÝ Oþêw^±_ý£ÖÑË3¥ýKöÿõ�lbâuQŒƒÙ^ü"òã¯êæûæ»@uC| ZI•2ŽÖ‚Û(‰¥ÙA‰_™ `-’kU^át„Z-MÆV‚Tø­œ\^!¹$’¿á¼?à„5uå× €F§Ÿ§>U³<á*ÜÂ3ÂꄎÔb£ sQÆã¦Í�U›œ½Í&Äô 8Ê\ TõPâm11ht°Ï–(óÉyŽ81‚h*ròBXb¬ÞÚ›—&í;'—mU›�2VË‘•(ñE‰(H\äy¸suîRò’Ï­ó/å¨ô£¶®³þ69ˆP­—õîŽ Ùƒ•e›Y^a©°Æ>”~xÔðÔ¸»1ÜI�ÖY‰Þ“ rku‰CE8%Èÿ‚T4ñsjBqâ»#J!Bp¬â›e,gò}B*;Rxxð ä"SšÍ§‰!üâíªrªÌ… Bx‚=óQãÕ¾�£gdŸÇüá#ÇìŸü£Ÿ·oÿòd§‹·ÙÃPŽŽ^_çÉÎI7[kôéU£Nväs… )#‡ûì·þÉ);0>hõ'oØôÔ=—W•Ë_U\N ªU ‡Ö—ŒT÷”¼gP®é² l ´‚ ËZ™^EJâåRÇ =ĵŽI;ñ‚—„vÑ×Qâ–NØNQ_€<¬ñÞÌìKEH²s^QÝ «`–›L�9Q˜~�ôïœ�šÞ@IDAT?vÌ:8éx­�\Û:ÕKó-¤SÊ~lˆ#ÎïxWEe[ç;ôä�´’Œ>Õvôö[;‡¢ªg ™K³¶¸°ˆÐs¨Z÷"ò%Šl?©’ÀW|8ÂñóÞH‚ãþØ@Ó&õÔ×rÍÚIä»]GºOùhq;s´Óú9òNª:\ûZ¸î ¨ñ;~Òþð·Ÿ·o>wǶ疙ö¾õ b g…-¡¦Q®ŠYU/ Uo©Ê�”5 ýtÛ*§ãÞ·oýþ~;xü«ö'ÿæ »úÑ%ïöǤ!ÑíJz@•Bê �©‚zp7q@’oÒpß�ªJ˜OñJLOÜŸþŠO± WòºGð‚Wñ˜SBÐä’üüžG þq­i*ZÿÔM²ôWxðŠÔ½�„çú“GèO{`hÐöŸ9g J›í,ÜÙ\ÀlÙ`_/çr‚Ðܼ !H�l"%YùÄ8fÿa¦±íôW8m‘Þƒx®.éÜN°÷ÅwGEj%Ç%iaEÚ‰ñ¡�‚›Q�yohô³qÒ(«EJœ÷dç YÀ:bwvC=É*Ò]OeêL½å®õô'O�¶ú{ÏÛ¯~ž ±Á9ñ}‡ÙØá»uõ‡œ÷ïûš5–•+ÞgU< ’ïå)?PºùÛmöÒ×·ìþÙ—ìË_ûçÒû+@V�H|o™kÁ‚»RˆŠ¸;7¤ò$Ïà•O•�â”!%º#SSªcÄÎYæ¥YIÅ£ð nŽäQKÚ…µÃ J€”Ní2¾¢U½áI-×$K⥴iÔ’@xž—$p.h‘ðaʸïÈIã¹OÔ¤y@µ÷ÙàÇ‘_bO~©ŠÅ}¡²Â'Ô�ÃI»ÙýG\ëäUpþÁ„­°tX_$W-«$Š_ä  䯓܉Ûù“*(GOq›WÝËŸ›]Ç}ôK”À£ÓµPd!Ñ6Zkž2ÒâB=�¤ˆ–œ¶`î d"‘Œ›ü¡yO.tû±ÞgΜµ?ú½çì›ÏÏÛöÊ]ëì;ÂúïYN­]´µå)»uýM޾¾€Tâ[K…0¢lP#ÇþäàÁ²>cÇžš±ø?�·ïþÁ/Ú¦‹ºš)æ¾”¡®Á©¡zÏNæ)ñã^AÝ“y+qª€ªrÔN5XI­ŠºËaˆõª¡¨¨B€Â•óVß{J¸ v>I¥O<-!çJ•Ž¿?8«]øké’ã§kü4f*àȾQçd¡µ¾Á8Ñc½®ßv x9°Ë.Mr°Œ:Ɇ®»åþ:zX€Ä >亰íËsö`r"61uÜR[²€UyrXª3Z|ÓˆÏâå.hö*jÖ Üf:»8zÀc¿DRµ`�<Ô¯õEž+¬‹8!Ÿ|¯¹Ô¾‡QÁŸ ­w·óçÏÛýÎÓöUëúꤴ žà|ø7|ÀO›CÎL¼ËZïq> ž±åÅË”€z7á”–ž*}*fñÎÆ4—n“饽C÷웿{Ð^üÜïÚ¿ÿ—cïþìxÐËðFZ7ö½eÎÆ[óT”VqNÍ'*CáJ`5¸f”GÔ<ˆ%ÃV¾ ÕÓ²Á °è ¤º…§Æ+ÍZ==Z�§HdÆ{l”�ÞÇ6~!Õù*ÜXøz*Oy(c�õÜ‹Ÿ·çŸæäáAëgk¯þžNNb�Ï‚û{mŠ)ÁKl!Ö… jð2бŒ¨È_ñ :õùOó¨D�tÿ7g'˜®O€2 ñôIüÒÖ­6dÔ«,Pº*Êç Oªkf&ö™î^ìPrOa#O%�Åù72çaE6Ü}i(u'‡ÝÈpTãG §Ÿ~ÚþÙï?c¿tž.ÿ �Ÿ¤:{ÆX¾m«‹Ìó× 5ò÷ú÷éÞ qÒ,ÇWÓMÌìHQú•*î=õäTìZÊ;È@ÑSÏvØoýáÓöëßû§Èœ¡¾kóJu�B5î)—ÈC3'¡ƒL#¯»øà5¥¶š\«Þ@"¹d,ÈêTŠÏo\`„œ"bJ¼Ëˆ_Áʘ¼+"üäO<à—ñ+VîWù±ü;Â~ã’F§ÆVÞ‚¢pÒ�_܈up¥Æ©îø™çŸ±—åÑûA;x¨Ë:†¯igâÎÊŒýlú¾Ml¬ØjOŸ=ä�ù¥t²�Å«@˜øÌ‡u ‚C=Bön†îݲ™¹%O/v3Bœ"ŠÏPEwùœ»RØã(]��„pwu¸°¨ {ÒÔè�â{B=%)åefw‹ �&sž‘*7»q b#äÏÐøÕé}îÂ3ö?ÿîû≠žü3žzßï;†N±¨ã †‰FLÃ÷N›ò�ËÃA�ß´Î�7bi)�¦ÞÕh0kT’§g#ÉŽÃvëþì»l?ÿ+£vú™Ÿ³þå {ûGØ,Ç\)_úTìÁ[î%·žFê&ó\jiè7Õ’HIXó‘lÙœv`²€ð…Ç#CàíÀÞ¬¹Š�"á@bÑ`šÈ™z U!ÿÖ/ÚtJWtFT‘FØ£CXž± ¥—šNœ?mû_yÙ~ªˆ¯ß 2à¹d÷à@Ÿ-²è_\¿gß>yÌ&ÅŸàSÀA郢�]d‹[;=¼Ž~uÿI›'o£ÿ7nÞ´%–˰«ì¼ˆHG¹—¾¼'‡ ôÉ-±ü¾˜º«q$ÿÂkà¶à9¼DªÛ_ Z@¤CùâZrÒ`F\! ,0<\€`ú+ <�Ÿ?eG~þU[K׉¿2â}jtØ>dï5ÊëïïÏØ«O�µndÒȾò §¼ðtL¸ÂúæßÕO÷# µ]X†­‰ÛvûÎ]/Õõ5ðšùÈÚQ ¿t’:ðÁýî?ñjd3ÜåÍ«ûBh‡>ÎåÉ€” J‰ ¹ ¢ßÞÎc¹deoAEIYiDJH>É·õî�‹w÷/¼ôœý¯¿ʾp„yýþäåjbOÇÐ [X¤ ×9æÙÿZ‹NÖ}fâ{05k½ýg¼—ÐÌSÈ¡t™ºNdÉéPÏQ›�¿S V²êµ`•×ÝI{îå ŒÀóöëÿý×ìü ϳ�kÊˈ©²(Gs5©YÄÏÁŠáo‡Kä"T¹9R~ÒÚECl$¡˜Ú—é·hwq“$åå|7R—ŽS.³Ç{?ÍŒ  MŠ æ“™Ä›°GE¼05çB«3O>sÖŽ~õ+¶Ä¼w‘ÊC¼ªS4ân~×f™ÝÙn÷Xÿqyþ|î=>Í̪݀�Áÿ×Þ›Çzv\÷�õ¶ßÛ÷î~½/d³»¹4ÅU¤¨È¢[¶á‘3EPf<ã ã?æ�Éd`xH$ƒ OØ’œxÈ#1²cI\¬…â"ŠK“löÂÞ—×ûÛ÷}>ßsªîòû½Ç–ØMŠ^½÷»·êœS§N�ªSÛ­[W<š::¬b×6?†Ïœ 7Æ'1|B)E#6¹sEJ¼’s©ýjùŠÞœH/g×aºxãïð\s9‡÷ë»õÀe�’*yqæB¥{ųRÊ‘%ŸQ¨@Ä©@ž8”ˆ«Ö#°}÷“Ýþ×/ílºÌùïœÝž)W½,ýuÛ¾ív’^‚7ÇHC¼­÷%a)¥Ü•ó/p|7ë½Àó‘€á�« Ø]ךù”ô4‡Ij2‘Tb}$K‹Ó,.…G?[ ó|0üúï|6ì¾çÇKµ�£²JmœÖ¬DªJæÎêÁ”–c\K~„xþoútñªŽç˜ QÌø‰Wäg0«=)M¯ÀYTÀ$.ú 'j�‘QFOÎG‰.7þœ^k*­ Íï|àÞ°é¯<&¶ÞòwŠ,“SOxôÛÓαßc>êY#ƒ#7Fà óû{¶æëZ�Ó½ŽEÃ&Îþ׈@Ÿ¯ÐûŸ?s†ž¦äÌdt)³°`U?ÕEú*œÓ èùõÔ W¥cõ 9ÝÒï­ïmàAX®›„£¸ äÊ!‡éªˆÅ_ŽñÖÎâ�+�R4G9AêšÂ§=þñ—¶…ûú/aüçœ$M FÜØº‰9Ü Ãõa/Hd�„*(Û‘‡ßÂ+¬\<ýcÛÐoU1ѽâðÓˆ¢¥y«Ã×øªÌ¢ã‘¯šÎ†šK¡§o8<þk­áoþÞÃá×~çɰç #‚ö.Ï•ÕubŒuÁ% ¸9¥ æ¸tM©Em%ªe&‘Å{N�‚àâÍé*fÞ'I #%E'ÉJQ³4lKåÇ`ÄrcMñSÂÆ…¸)ºQ¥€âÄaÃ@¸ëÓ�†ŽÇ £}0~\̰¤²�4èçßw‡'˜îSb‚C£´^¾<ö°cpSg»}sAp› ±¾¹™€Í¶ø×Aï?~êë;CÐi S2lÛ `†š w®ÕáøÕ�8À(„Ž¿D^Œ ^‰“qWT�nÁ÷{Ï[t>w2ýëRr?�„¦þ˜)ç³Z#U©�m˜×5?óØ'Â?ùâæp g�-½<‚ËŒßÙê5Ñй“O;«÷wÙtÕ±æÖ[Ëoœ#==Åìôö¼ZÚXRÌžâ60âhjè メS�0“A=…ŽÕΆþKã¡·8<ö«­á‹¿÷@øÍ¿ódØ÷Éûù¶]¿I ' ^ÙSÜœWÆ´(ˆ€R Ù³rNši’Ä#e¡Ì#zÇ¥«ŒÏ PÆŸ€ñî«Ý ¨ZVEL4ºëEýäÍèœ_Ë}vå’àFʓޱhm©„Ýwßv}î3aùàýa„G}|÷ò)¥³”…µ÷c3Æ=<·Æxô'çtæ sZ¸>ÆzÀÊ�’‡Þž È&mþ¡ñâNh»r)œ>þ®-þé%1åßæþÙ‚®Ín¬^£ ÊÅŒšô—r*¼»èK´jTÊ ŒÌAÎ%F¼¥Ûmz + êu¬ÊÀ{J�R4«T»U£ªÐõÝö'Ÿx üÃßî»Úχåyú[œQÅKdlî Óõ•°09hC|1TŸëJÅxI_üìÙ0_­<'™„Ñk‡m@OÏ.žíŸ#‚Wêõþ-[ÂüÔCù¾7×ÈË'|I&Vz)C<”F.RôGƒã¡§·><ô+maÿûÃÅSÛÂÑׇÂù£—½ÍçÖIŸ(8;†ÊÃÒ½Wqnª¤UV‹nQJÅs6Ρ„,TʼŒK–®Ò'Çêý RxíHÔé®Äpªðîãs­¹ÂËB›wn ý÷ õwÜ&9˜s›–ij†ázƒ �8Šæe¸¶wu„W®ðôGpè ‰X^®pÐéÖæð8ë?:~šá> ƒZ# ‡ÎèŸ� £ÇŽ„sW®AO~T/€k#‘ý©Îú&}–“”¡t"ÈAI²•1*€bt“½vïãzË €*¶1Át‰ž$¨Â™ ™gIKÆ¿ >i®€RA7ó\÷³O<þáw…íMg8 RFƒTBFž–,«ïu»ÂäØy,’¡:Æ*¸~Pfþ$¢Á# ßðBhmÿ-v“�…y­+XSš+Ûxè†.Mðh�^ež (‹¤-¾–ÿÈT�d–ÒB¡™dßJ}Øÿ‰Å°ÿÞMajü‘ðü�ß—Ž …ás| b|:ïÁ$©þŒ7wOÕ+½’3gÌc¢EPô;�ð1ƒpŽ%ÞYENñ2–.ƒÀ¨ÈCP{Þïý¾§$®N]â (ç–d�žxìV©„Þ�M¡—iÒ]Ÿy›µ†F'‰+óaãž�¡Â«ŸõKSà¤)n�ácêVaH˜½rÈZïˆ2œzh9Ñ©>yßD$,±¢ñô áλŸ ‹‡l@¥ÒÃhƒ¡&OlqâFJ§“ý£z;Rüø%'³U¥õåDUq9åC�«4·l ›˜\i½ö}n"ìylC¾8®ž˜ WO‡Q欳|ŸŽ§Êœ=㎠�8™;~º¹+™[„—œÌ…ÉâDObÁ=òI=|‰ F6¶\âÐ?É�ç3ã’ñMƯ§7êÅ55kc�¯gë–ÐsÏÝ¡éà}avÛöðßãûF¹c…}-Ç(‹ƒ3aË…}íáÎqF—¶‡ë§gÂ�3m}e$Ì�M„E¦;z$&‘½B¦Ü¸æÊ!ÁD¨{,€xÄ�ÇH:ðÚ–p1ª3àZYVH^ëân?a�[òy(q³a» ×Ti ]½=¡gçŽÐÎæ­ÀvÞÙ Ã8£í·ÔþÅ‘©ð«ýía„•øiò¬òÒÛjhM…ù©,* ùžG835^�-£-’R?îK=9zGf‰­µ„·–çöÝ~xñJ蟜s‡…ÃÇxËS±eü46êý¥gû³´+ýx­öZ8�.‡$Úµà‰’ì$Ò²ÔV�—QülžÛÔHªCôæICh•%«†(8+C�¾fØr8wædø¿þ˜óÛ÷óûÃÞÖ³¡ŽW{µÃK¿EöýÏ\z• À�¨z¼£ªzèÔS«r˜?Ч”ª×F®½Íë¦z_ànºþÖ07yÌŒ›mc,Vx|„QcÜíM­a†Ç|jltæœZëe�Næy1e–ó&9cþw½‚¬óæB{eCb°»gwØ0ͱS3œ3@ÃPGœ¶îq~Ía`_+ ÑÖ0q}{>¿FÎO„qæ¸S cø¨ýÒŠŒ[”£Ž“®­’¦Údúv]憜tK0Å'(LNWÔ}¤Å2d²3°DZ‘/Š÷¹:jA'-¼dÓÚÕz¶ „�ûÂGn/nÙÆÛ;Ùa©’€V+1ôçlÏ×ÇgÃCèáÇÃÓfÔJ2“Æ* úîÖÆpinÑŠŠ1p:kˆ!E®†Ehš‚p�]„g)»'z:Â¥×^ÿé¡023Ã!åóc úþ ò™†ÿJ<ûIZB.¶²«i& %O&wpÇ¢3šB2Õø"íûñ߆à}ˆ$�gN�� …§¾ó£pîò}áïýæ�áWv¶²�÷jXiê¥"ðL˜7þ¬ðHNÏÿÕ¤¢Q¹iH­´TÑ5rHÉ f•�F—Ï>:ºþVhgQ±gó}¶[L-ØràŒu £^^c:p% 1EY`Ⱦ°Âùô¦†¦jt$µ÷DÚG¨½eG8zêÏ8/ðtìÍÑ0|kÐgÈ‘Õ77~•¶¥i×òER˜Ë<®ò%â’Ü.£d—n *Ö–�:lïÖÜ-7|[}¾AM6NúõÖ3_#ZÁø× ¨‰’ ÚRZU?Ñ)}SÏŒÏ3%øƒÿ÷z8|ê¾ð»_Úv¶PQ¨˜KÙðY²ê†Ñzd¢^‘²F –ŠM¤~ž&´wmgz‘#¢O„žÖ]aaìu’e¨¯Ø42V>‘O'²,PyæIÏx"£«¬Ð_ŽžæáÂ4£di¢½<}>tußvõÝÎ ư|#’‹Cõ‚�Òqžêáçð/„¦&>rÁ2ysgCx|ïCát˜['ûiêÃÜør˜_³cóaf„¡-Gå-MÌ„‘avÅ1\^œ¡aà ‹eíNdÃFqô �›Ò€Êì8¶×ÖcÄ œ²£}ó�¬¸×wv±Õº“ý]áží¼ÏKFJ) ´ö‡k‹•0Ì衞/ä®Ð`%a™»üKìn / ó�?‘¡Ü†ì%hõ_Sªƒ0Šex…L%Ø�ú°côF¨ÿÁsáÅ¿ÆX ¨Ðˆ®0ï—q{ﯧ4zZ#IeŠ*Yñò[õµ\¸ÖCÞ¤1P5ÛÑÑNO.„9êb…0^b_å-V1>šÇï»Z~ðLxñ¹…kSÓœ ©~QòèäL;¬÷×ÈG�€žÚï*Ýçàä·»èkœòéÎó™˜*~Â(ÏNgy¦þhê)P“d{·èTGoѱ”�ÀÒƒFêyå·Ý­dñ9UÊhº‹ Úå ¨Æ¤°�´U¥m¢RL=«ìËK΂²EʺV›é¥f&ÇÃK/¼þõ¾þýw–ÃñÑÝô\œLáªZ*EUuë©ËÚ’=ÒÂocíê߇aò8‘ôs…¿¡ñãÌs Rzº)gÎS19¨’«…J/Ê�ZuÅimÚ®M_$}5^¼Š¥QÀGŽ]^ºö — Y/èÃ^׿çÕý2º+<½Ê1×{yJ²ÌÆ-¾)›¦,\ßÜÜ-çáÙÇ5/�–tP¦}�=ªôÑœ4cøö({2˜ó?8Ðm š«Rç.,‡{7õ„SÚÒg�”7ÖÄD:P.å<·)Q|=൱ÙÐÑÔ¶·0ú‚¨—FüÝ ì$޲¢Æ[{­,�æ Ò:Z¨Ä6šRo+YbIÜejÄ÷:žá÷ï|$ÌÌ�Qâž&ðÅÅI6atœ1¸0{ QÜ�Å"9É«E¦YzÏ»f{…ùyè ƒQ˜u�Žˆ£S£0N#ÐÇ>†öP £L;t³‘Ä‹vzå{1ÜÑ¿?,t4…asž¦¢¶D¼o¿>?Îê-¤´Œ�sÞ½ä/’#ËÞ®-á�‘±0ͳòÚê P·bDψøO ô„az× æ´o¡£}`×ÖðÚ¤¿@¥ì*®ñPÀ\® quþx$¾ÐÔð¥6=ÐÙš‰?Êæø„>õÍ >”[;Cù>F [YØÕV {ÛšÂ~î÷ñ˜ð!¦G3Ï|7<÷ôÂeŒ¿Â‰Nê–”Gxi Ð(ã§ðù¿ôâ¹O黂QÇì*™)ɨöBôò~.¼8触JÈÄɽ†Í/FÓÆ#Ó¾I¸ÀtMUûë'Ͼý†Ç|×[n6nܱ ‘ÿ{ê6‹l�¡­µ=LL�Š92Ñ×.£2�å8ÆHþª¸€…Ñ·ûÔók—'%Œ’öqi å‚·Ý[i¥aœ>:tíz8òîµðî•FŽ�ÞÌË9]œ!ÇÊ �z'¨­Âiè%§–·½÷ÎP¡Á˜šcóOœ« -ƒ™›bãÎnæó ë™Xé+ž"ãt÷±Q]˜CÅÓ ´�CG.L^e«éƪTqé.?NÐá…á°§÷Þ0ËñV³ >ÕpÒElŒ UoµǃáüÂ%“ÙbSç¤ò`æ 7æ&Â=Ý»ÃÛœÔóG*ÉÝGï_©ïïŒ3ò©k5T”4ÒEm!·š"é73,›µ¨ðüŒ>Æ92fX|€Þ¶£ÛVñ³|‹¹£ñ…�r§õ»[øAƒ mºoÅh»iPžèkµæNŒü>:k w6Õ…-ÈÒM}ibŽ8Ç´a‰wú[N Ǿýíð½ï¿ÈÉ@3l;fASÕ…y¿JŠA£-ë-Ð|ñ/æ-Ðs ÞT–Ä·{ "$¯PÊ«îj²È¦½r¿òµó±“9ÑEA¨×ÿîÄ™Ã'ûý:MvnÕ]b8¦f¼qÃ2ead29å|W(¢¥¹Ù.EŒݨLKZ¡Ž=°t¨ÆÇ[f†‘†‹áEÇÊóB#…I/Ï|Φ”4O/X$œoüäP8ñîùðÒý{Ó�m÷ïšã‘ÜuF¾úšŒË¥õ�&º7ÞÅÇC.!se\4>¬^ão‡Íý³À£�Ežák¯�Çm�z'wùÛ0xõî¦_¤eTf(ûiù]a:1§¹<妑…ÊTû&éi ƒ#K¬þ7„βòEIº”mœéW9òFxõÇ/„7O_´éƒ÷üh‰Ö\½#_‰Òãbm\Rg–M¡àd¹ö¬+£. ¦ÊUnœÎ‘éê±R½TL¼ÒNÊÔ) «Ç®ê¼4åU’ñ‘Å–z}’ê–Ü-7o�úü�}ûž>�p›ÔòÊ@+|îɆ))Gï)âMˆ@˸ísÝ*ms'Un�¬N‚6EZÀ{ ÕMÅ÷†@ SÜÒÉh@‘TÀR¬‚±ëWË?¼Þ9¼!ì¿{wxì¡ÍáÞ�‹ìлz�'V²% †¦VZ%æÅ-!ùgø=1#4,ô‡¾îûÙŒóxŸ¯{e¶(v¾\¯v—5n 7FÞ´Ï䆷 Å�d–áxá™�†K¼ŽÜï�½ÂÙᣌjØ`4ì% §®pŠÍøô9òÅ&þÜÐ5!�Èmg"�g3~Ò3U…"�&*üñ‰ á±¾ask/«øCakûfŒjœFŸÙ`8 ¢á¸`äf88Á@©ñscש;Œ¨…_SÃ*p†Õ�¡z÷æpŽÅ¿>>Ñ­<ÎѦÏ`Ô2ò+¸9GY˜�s_ä§²Q’ÒŒ­È“aM–Ó£¿~ò{˜C>ø ý>â±§:鳇†y˵Á0öÚOÂ�~úZ8{}Ô ªB<² -¥ÈHÑæü2~›ókÅ_‰äe�%H¥�Ò—OÕÁÐãM®èw˜CŒ^”¦KïLþpäp¸cߎðÈ[¯²›°«ñ$sC>6©‡ä¤¡Ç`ª?*8ë÷à­÷ÉG'N„–¾‡9Qvz¸€ÙÒ¿ÓsªhE¯G=¬ü_ž�â‘o/j$b|Tœ—‚^ROèâu’݇ûµ?àFå˜sUT�·÷݆WØî,nä—É"9™¦1¥ñ23…�ù7¼*ºÁW¡±Óá±Þ½ì¦›¡Wæ;z#çˆ(³Z4Ùë06�ÚhðZx¢�F¨]ë?ú¡C-ÆiÛ’Æßú›Þ˜ålƒIzðð'Yg™¥“xm‚½ú,ÉÛãCè5š°™»½» _¹Pù·Í°ez<´Ÿ>Ž¿ürxƒ{ÆÙð¤ó(oH1*MWyRD]°žßŒ_=¿ÒS'BšºD'Ÿ‡\«1`t S¤M~¿‹Yæ«ò,•ÁHKC“>NBã¨ÎL²38ö�o|£hÎïç¼Þ†@ ¯#ëï(í9¶Å¶ê%sHn.æ$†2-dáÕ=2|{Ó-CWóÉe� O5;iÛ|”6�Õj4 g× <.Ôas>u‚ê%W¬kÑ\pÅ>õæË7ÂñwN‡ç_:îxwxèáþ°w;ߘ«LaÔlžQéXj꥔.½—ëcï„m}†¦Å1z8 ]&Aº~úï¡óìfø ëúÌƉ‹Ï£�‚˜‚e*mɨ•þ“¬ܵå±ðûf™×¶òùòÞÞÍáèüqÒ'ÄS�/§tíNl»Ó8?õ|L@ÔD)…ÎÏ?Á÷Ûx�iÁ,ÃôŽÐÙÞZØíW׃Ì:)Gã¬3 eàsø4óé9½Ô†=O²¾K×júhtÚÜ~xéš=yp÷®ð;}(L³…í_uJÅÏ €9^ör®ÜÒê’à¶4t�¯ÐÚØsléìlï6%«ºKw…þ&Î*¯Ö²øŠpóx‰­Q¢49·ù%ƒ~*X*—� ¨œ‹Úî©…ÞöR4�§êgW¨es£áÝC#áôÑáùç¶„ý÷ï0=¸û®®0ÐË#§†éШ§$¶?«ˆ¬\?º>G^RŸŒAê ´`è?ξÿæô�ôˆ£±d”¢“ÝJÏÏ’;^£€ â^e�bßÀ'áóßÛ{öñú1ûüy«�õX"“âɨ•½£àCtÉ'#h­ì@¬0dnfŽßÌ7[ðWtÄx¹v`­¬ p[‰'é­Ç¯Y«×ž×ha±Òp§)ET¬‡eD)(OÊ‚-èñ•ž ¼¤4É¢à>Ó}€MUïŒÑ ßF«Zä#�hhDô¦@:q¿>PñÕã½™Yž2 L3{Ùܵe”#ᎾÞä�¾£ç.†)½ÀSåÙö}ÈøããÌ&z~­Y¥G}>)VÒe±\2Dl¬ÁÇ©¯ì2Ú¼\UÎr)òòŠÄÖµ‘QË䬯mÐH®¬46ýDô·ênKP_?te¥é*•vó<ÛD%¾öÌÎqVk4D4i!æÜ€ æ>ϩٔiœrõ«QÈSúnC !•«0ÕP©’¯°o`ÁÞú¢BXCà4öÉs†ºªtKLo®ž=®]8^}¾'l¿cG¸çÛý{ž ¡§c–RïçóP„Ê?;w5ŒUzCgç=a|üm`Ú¬ÂY­;yëìj˜£âaŽìJÔBü£xªØ6/èNòË0ä„W/wqê ï% »ûî =¼Ÿp�Ï›SuIG´MÈÂË8|³ÂÏŒC·3 ˜rˆNy_dê°ÀxRoêQä›~f�_ Cã|}x‹^´ny ZFðœµÞC‡ƒŒEÇl§FÆnרHÍ�!åO^=ZÜÁsìó“¼¥Hzjž9u>|é¾–ÐÇÂß5÷¬×…^š÷ÞÝ ÁúA5,ä[W{—¿\=Û?}e1ôÓðmåiÊé·Âzýc'Ï…!Þì«gž¯çû¶(Hšú3ãGG �]¨tGöêž?ªÜR&ªþÝ™ÇùåÀÞchÝëyp¿T¢!\âÙ[55·\ëj¶xyåZëJ8¹ÜÒ-ËÏ-q!ò¾}Oü9Êû--nê°W`Gynœ 0ËÙ YåÑØÏÇP%ÑÒ}�ˆX…Qˆ–Á“GX»8«JIÝ 2 ÿGÞB NÅFD[PÄ# œTÓÕ¿!ì¼k{ØpsØ +ìØÊsé66kÐè-Á�Þ‡xÎvŽI©l­¡©ó‘pìÚë W5Sõ‚×]�u×ó{4F¡¦P~Ã+‡ZµÂ€ui#¿–¦^�½Ÿ©Ër¸>Åzr�`|O½Ÿ˜4�qÏ3M˜cíb×#DíŠÓî8šõà2lý0jí”»“wÆGÃù‰ë¼Ö¬‚zã‘Þve#ò°Àh)ãçg~i5úYPsy�§Ó„ðÉ­á/Î ò^Ãï,òFåRØÂ¢åoÞ{ üp”3¬d�Öˆ‘_ÝåÜ8¹+ F†_?{}?Çó¿ãoqÈë™ÃáÂáCáÝÓgÂ5>Ý¥Å×Fz}é‚,_妊Œ]ó}ÖedôöSc¶–ñÑÿ•²; ëÂ/‰Ì�*YM$Ge41®(KêÌx©Îuôñ^OMFù(I=kØØù‹çþÓUŠ÷>·e ´ÉÏÓü~Kþé™i¦]òzí^CN •Q«üe•Hµr—©®Lf¡ŸÅøEèÃKç,~‘7†¦·Ô0"XäÑ¡> ÕÀ£¡ôÈF 0V‘¨X*çF<£—ø^ÜåKáÈ+m¡kS?Ÿ©Úî¸{SØËa�Á\Ý…pç†{øvÀ‹9<1B!jtäêWC"IÄO-¼+.RO/¬EÇF5ìBTï]!Žž“×ëq(=õ"S� ’ÖAS¿<ÆyM™¥:†æ ²¦$2L F=« ÀL?0ñQ�§ÆÂzq P B •¬³®3œšfÑ5-3’¨£!S³$“·†Pê´X2.¾´ ü—!"ˆ¥0Àžÿ‘YN3bK¶í§‡Wºd:ðæù‹áQNú±½¿ïÆjë6Fö²µµñFžÒ韞 w\½.9μöz8�lèQ¾šX”ÔN9Ÿë“>0míÕÝ÷ökäÂhLCòì½¾îPèb”ñ*˜Aâź8TWó)åלã#I„n²p6®HcP*ñÒM¾fÎP˜æô'95Thù ܆ËmlV¾�!óÖk]E+¾½ìEoâò<‡a(I7æWXr¬CþNºr•íš”[�\Zöç¼ÌÇÅ«”Ê º”-abC Â±^J[#`V£† ^'ˆFŒ¸¨²éYM‰=õÃç'Ãоøb[èd×àÀ®>VÙ5<¼ÿAž³7Óò” Ò…akë) k:¬NÃsŒ�©¹´XYGo­¯ -±°ºÀü{C_ �5ÏZQ‹ža²Lí±^ŸLô‘©ágÍ[ê™ké]�%å Oô)˜7ŠƒAÈÈå“Ah}¡Õ,-ê“ ©ÄjŒV€Bc`ÃLòF#8:xÁ~'_m/ý—×ÂSÛ·†mwl »ïbqï�°­ŸsðZ9y–ïÔ/Ý CçŒ?VàXÈ’qÛ¢"iÈpeЩ—vƒÕ —mº Õ/Lðí‚ëGC/£‹�þÝ̧Ï!?ñÈ`=ópõ¦röÈS žTÆ�ðr¢‘>Äsß9|÷Ú3D¡‘ ä–QF�¶Ö©q‚‡tdû"Ä>¶ûzC0:�©5ð]Œb´Þ2È�¦Z3P“#žò-מ�§Yøòýíá‡|\gc€ôË+¼J=úx­»�¯òΟ9®œ<Î_¸®��3e=¿Os|7h’°òZ^ò�õúZìÃðõR�Þ¥°5«µÆ¯|¡ˆ²&W4~ᥲ „ã æó •<Ù}-H-\¬I‚ïQðípYbó˜*Ù¦þÆôâàm™ÿ+‰ÛÖè™ä¾}ŸúÏèãq1žœ™ Ý=aœÂ«vòkG“œ²ž2«PI¥€‘.^p@Á[Žh!»XJÐUácPª&¶zIUò|Z ¾�?z[õ(�§Q�Ýáj;¸Äþfs\ŸDÀq#œ¾Î>^á4œÖî®Ð½¡; lë;vt‡m›[Ö ¼¸ÂQW¼ÙViä}öz½'/öµ´ìO&«^¹Â*}' M¼AOÚÞüIx¤ý7BWSŸí´ NQ+ŠcÍ€Œ™¸2Èzä3^À¬ÁÞÍIÇ‹à4«ý2–Ô£“4ù¢ºèÜCï«I ¾â"“°Ö˜˜Ñ‹2¶-­$°³{C856Lº6Œ”ñSN0KÓ£xòLø�{þÜÛÊK[MŒfÏ�åhô³áí‹—xmxŒ''< '®æî:°Ã YwtbL½|Ô`Û#^kMl¾O~l•b§õ8±ø­VÈ/m$˜¤¬1~ô$|â!B~-F,ÀoŠ2hõ%¥¨:&glµ´pÈÊäˆÞúU½”Æ—žúÁ~ 5ãÛân[ ið[Tøʽmfv:ôðˆ§™E2M ’²ôl_C~å°¬+•TTd´^sà·VþË •@¥@ÆÄ TÎWt€ÂÆk†Œßk°Q�ÍÅhÈè3ÉŽ*¿Ѫg“G•Pñ©/ƒz#þ ]f.rîÅðà¾'yÂð޽~‹P¦gåFvkZ—•ù%Ÿ$ÕbãÃÿ«×¯#¾pþ­üêåWh4§çãáO+ðjs­¢çùH@FÆæÙ� rò# ‘Ä» ô¾~3ômÔ‰^ԩܸL,42%8wîB¸Î [Cã¼ü¤åRF3ä1m‰UC¢a¼ä·_� ³Æ0 k¸o�ƒz}õøÒƒ È ÈÍMWÅ÷‹ßL#˜èõ“_3~âh„±`~ed›ï��J­‚E'N*&�>›õub2£€´^Ãtyºn©î[‰övÜ‹iß~aÿþO›,}AsûÞî~¶Ü¾f¼mc�e¯œéêÐÚ‚íTå Šë•ä/”Æ )—ª¶ #”ùdÍäÁþ($j Rõöªqxk�A^ºfJ:Å®ú7>¡��‡†´4 Þ£ocnÜÝ×z9:«oC[ØÐ×zº™:tÖ…];ö‡ ãÇXàE^ƒ^—ػ�3 öìÚËVÞ£–Nzº`mÔë뇡¤°ã2~=2ÜÓ¼?¼Å“vÊò£|©¯×Oέðtm_b=@rS+ù÷jFå_b¾´ƒ:À$6¼xîG¥³¸¹ÀÈE»ñ¦9½˜…­e~³Cü�1F‡ÇÂðø8Yå)�Z+tá�ç¢ñbØ2jlÁŠÕŒÓôžV÷1|MÍŒNq4ßç®jËü©ÜS‘Æa| /©ã²à*Æ/¾…î5^ҖŲPvI f'y-xSÿfk�ç™Ç(y“èµ�„)ßMÕ5 ÜlDù¨ÞÊà™Çñk¦&�3Ú”rL3òöÞK-´™³¥iÑdÐ2èT–2°¥Eâj˜m zT’Ð/Ñ¥» Pi[òfTÔ4§ÚLqº/mç0‘ÎÒ‹©ahЙ ô ­<>ëè>ÅÈ�í·]-ü*|1·B¯Á³öæ¡0vckhîÖWsÇCS3뽫´UÓµ‡¬ÖÂ[ékZ0к=ŒðmeI‹“± ¤2Ÿ”cÝëWXdgcÃâ8PiT[j5«cgP¿¶.ñ²OÛÈr¸põZØrƒ“Æ9˜ƒæuÜ îôl32¢×ƒuš”œŽP—á62¼—ñ™ÁsçßÃ.º¥ç=¾hÔã3™ ñ³Þ„ò(>fÈÂÛŸ%}Ê‘;å×ü Z9»’O‹q' Á"�•Ÿ—¢A"Êðº^=“{"wé82•.#a#@g-NÞàT'Ðê4¸ý‘ܾëmoX¬ün[ÛòÛâA‡===ÅñÙm¶UT)wòÃ9¦Ö‹bMò‘ù2�¸å�¨â âe‘ã«ÓN•@ä·BY…JÑ ¨ÝÕ,¨!Ž_èÔƒ.jåP�Ý-Ž$³ÂÏÓ÷Guâá’x�P˜gþëC ‹,¬r.ÇÁˆ_\Ô´Ç�7Z´rüBËq>eÖy·¥�)F+�yù¦Âι k úG8=+—Ñ5`pÃ탬ÙLZc`S[-š%o�kW8€^|…9;�'X¸äi„ÅØõlžÞ{Ž£ÀæìÝ{Œ›­ÄòÏÏó£7[´CÌœ Éeè¬à³+GªÐºEÑh]WÒ…ëR£¬e¨Ìð½�UœhøjTR„K†_¥gñËÊÀT­Ä-™¢UQo&ŸC,6Õw*{‹nó%R¿2!…»—­ÃM#B”_G§/LókiÕ6e¦Í‡›§f¿ãÌnßõ¶7/¾4æ­1Z»÷IDAT ?Àþí-ûèøˆm j⥌%„,÷–‡XÌŸÔS�¹¨äµÐ™Zs@0«�X‚¤Ò¨NÖb–(�•I#°‰î•Dýcª¶F ´•®ˆÀ¨PñZåeo� ©bÛ6¾¯†!OSô™ÓP—?µ5rÆ´·= Ã9És™bÞ¸‹€_"FÞši˜_Ãb›CËp4¬&]åÃŒ/ŽL”,=ñ“ܰVƒ ø·]µç¨ü�:±ß• ¶¤zwƒÄp2xÑ$#’,ž˜P�î¤Q†�Xðú0_�qÕZcàyóÞ?ñ'a¥+1J×2„]$s®z¥í8’“²MV‡%|â+5ärg!Ž, ÑfPKÏ뉓˜Þà«7ÿš;8ñøâeO—2býå¾ñÒ78¤âöºÛÞH¼¶ùé?™¨kúŸ)ð;¨˜zA¨‹Ó_†9y5W[uF¼Ú”¡‘:×Y]Z¨ ‚¶�CòÒ.ð̽%9kÙÀZ.¦P¨=©W1û7S0Sñ^”™´Á52 ¶ ÜŒœIºæÌ2X_LÄ sõnÆBbYMT]á5ņç&qT�Ý¢ßàб "Ú0½Vª'ÉÙF(Çœ{RPl5¼VϪô“ú¬a‰‘¤3}ÌL18z“ :õ/˜ãa€_æ ¹‚7�t—L5Zé9EÑ=ùórˆÒV7å[wåñèô�˜+`=Нr‰øŒ Xdž ,”2]fÍDo)2m>>ß´üU§¹ý×(éíg,Žwî~ô˼M÷uÕkžF:0T��æjÉZÏ·B°²¸*�J�ŒIõÌàÕžbAU%I�SÆ/1ÈÉ#N^AÄÇì:Òæe}ñæ1ˆ&¥ "?7‡P}åw0Þ”–ËŸ‡-m‰ŠùN2Ø´B8ød1À[ƒ"˜¥›aòrÂÈô(Á¢Z‹¤tE/ˆdJCœ}Ä]Ï E¢¡¢¤Ÿ~ Kñ’þäçGk� <—ÍyÚÈÀ‹ÚØ+‰Ì) tK¿ ¢|Ö½ �SSÿMÙJÛœƒñÆ´¢^ó°¡*%\Ô¯ëÇA‚ñï2óG€ÖZ{8˜¶§›¾^D*7=Þ\ùo¿õôW¾ž¢Ýîû6� §ÎîþÓ½wœ}†ŒüšöŒr°doWo�ñf‹EÕÎTõ]�Ë+—•�££®W ¨Œ.…JìSÀ¼9a*øRN$�”ûm„pS…·¼pw[sœ_Ýà­¢‹Žèš›§Û‚‘…E<3ÖœÆ{V¢¨!µ^Wé¹_ô‹l%,åœVLű4“0Áëxü'*KÛ|„d¤ú‰FN~¶`Gzš»+¬4ÄÏŠ×â&s‹ñ…4¼ Þùßš ¡œ�ù,¤˜‚º“·4¿ à­Çϱ…(¦Î7qò»ç¥œ è"/�òXH¥Ýq^b„€©BÔóœ¿�wG&xd*ÛÐöf¶Ô?;:þO=ÆsMò|0Üáº{÷£45Ô?O¥éPÅQ •ÛáÑë¹Â’ªÖ”&Gd¾Ì#Ñ=`¶sRF—B‘Âoµ…TBð¸«r0`£:à»b ÉvSÂeºD‹ ‘îD�h†p-:(«  g´º$‚ˆÈø%BÇÛÁ¦Y¢ÑˆU9ͲRe�L™�ÖÙN"goF#¾ÑHŠÔnÜ)Q0‰N´&ü ¹s;Ny¶xQ>'�r'˜€"�átKq#:%’ñs¾Õ”Â1`éá·»'ã´‘[©¡ða�©=¿â¥GÂ1ŠÝÄÑs¡Q4L§ÚúzìÝ�¡óƒÖ ø©Ú ¿ÿÔÓ_ûß‹q?ÿ:HOÍ,þËÖæÆ_çÍ­OÛT`Œ©@_ÄaŸÀo{Å’Iä…{R,¬<M)�ÅÉ ©T3LÙ“-p+À2^üÅ+ã—Ð ó¦ŠÄ«sPî«e�ã܇,x|è�‡€:}ÁÌ Jy•!Ç ’Zæ‘I&e”ˆ¸T‰åW¥”út@t±AHÐ`X…:Ao$‹Ú”¬âïÕÜdT0ʘ´šÁ…ÒŸ‹äL�­å<>XãY JñWAU_ˆµª×d‘Ú"6¿ËGŽ#Àn¦R|F/ˆ#mØÅWØua3±_µúª²†þzæ¯G³úÚ2oþ½¼ÔÜò/,ú|qi?àDÄþŽ;>ÈòG(¨GÛfÛÙ²ÚÑÚ†Çx™E/‘$­g²ä¢™/BQ ÔÆH%”aÊž¬ ¼*+Ö 2@æ1Æå�@Ô ¬Äà\ÒÀ骩 Û¿*‰\5~-”5ÆÉã{CºI†Œ§xçü«õ`[” í49%ÑØe¨E)¹ÄßÕ,ª"'ü…ˆ&c2ÑÙtÅ¢˜$ÛÃ1�œóÏ¥ÎR‚,á-FŒ–ðI†Œ›èIÆdÍh‹áSE'° &‘€O^„ÈÒÒ #_ ®èYùC ßîËH7*…Ž+ëÙÎ7xËqŠŸùÁfleeá³ßúÞ|Sl>hgEóA'"þ§O¿ö6™cs�[odžϱ' ‡5)׆Cø‚bá—vM¿bp—Ñy)¬I]â˜E*’;°•2�Eª )-X*&hþl¡.Ùq EPæ—"%(wô`Ó+t�ß«þAŠº½÷¯Æþ. !nÎ#ñN0Â0ÊðÎÁ%—ªZ’ÏóR ½G¹•èµàüÖ¾Þ,BÄW‘åÁÜ—¥Q‘ã ìžTˆª|I' ŠTÒS÷–ú˜ Ó£ã™Þ8Þýù°Œ_²~h €;}ú'ÈN§«–NŠŸeÅsÅöTf& sQ?j?5ì ó_®ÎÜG7©D¥‚*–†„3W[Pœá£§¦@³â­á%ŒòËгÌ”Ï4BH¼W½+oüœ›ÅJ±#yLGFWÌmWÅÜŒ5ËM‘®è§¼ôeð¼ Ÿ\¢c¼ˆ.,R�½ “ØîEºšˆºµ½eå�bEH"æ¾,�¨ˆ$†¾LI'‰Þ5°Éêþ¯ô€2wîÜk—9¿âË(äœÎtÓ"àÈÄ�}K@/ ±ù™ŸÔ§_­«.”Z ‡äÅ)Js@ 8C•1åPF”Ø`.çZÓô¼­‚M,¸ƒÕäœ{ž�b ù a‘b{¨ Ih‡®ŽK4_$Ù¯š>›/"åÜT–‰¬"³ŒH‹Z4žßbÜj®‘&K ÍÓÍÀJ? Ty\ï^ý"ý*ÈŒ§ã̸ä�¤]ôüfü—ÜøµâÏñhlû[þò/Âø•‘_H „Oœ{ù(«Ô_D9—µÁD„j:ÐDOÓÍQbåJZ¬›ÂN\s—•E­XlÀ2¦S V!ÊÁ$wMŽm‚,XM4ƒ9T|ãï=骢ĠßÊRQŽYŸâWÛg‘G&½²$D‰])àÑ�Ñ®‚wªx-à ÞDâÚK¡Â=£Í<äͽ«:nmjÕÆ2§ŒÃ~ ÄíZ-¡Ì®Í›8›¡™Ç}ƒìóç¬GŒŸXWiþÆÿ÷½¯¾ss ?Š_X ìœ:õ“×V––¾ˆ".©ÐG3G8öY«Ö}L 4:ðgßžùLùf Õ ‘Öý—Ñ)\2¼D£¸ÅÆ$ÂÍ@ßD» �H2c^�N‚»+ÓZ=z‘ØsPÊGbV´¶H�f›1µBÊY$óTs-còå ;‰­g¸×iÜod%�UG,Йwu|ι€/xÞd#PƒÊ™ÇÔ_·püÊ$S9ED *Ñ­£Q¨™ÖOØ4zÞFeÿDÏ¶Í æø›.qþ¡ÿÊÊêû¿ùݯüT¼QîÚ(Ó'Ͻò«Ÿ¿�ºl: ƒ×;ú\U_Ï›–•E¹Tkô– ÀY¤"™kP5�S R ,€„T-ŠDºeô%é<�âµ�·,JŸ32ž%ÖF·z,‹f¨5ð…¸J){ÀãëZË®–wFWà¿ Ó(^!~ômQ)(r6Ô%Çæ¾DñUˆ,h«{‰Öï)m/I¥ uFÒ¬sŠJS[èMÍ ‹}M­­¡wÇ6NYæ`œÁ˶ê¯9?îüÂòâ_ÿæw¾úBdõ »ùÎŽ_XòžðÈÈàåÞþmO³ðò+l6�õ‘Q)½‹£Åå9XÄk}Vl/^JUdU2Ö 2@æ1¶å�@@j�$D‰4%PI:ãï—XÅ –Wð‰÷+ÞÑ+:÷ê�‘³…2°{Jr‰cüÌ[¢4ÞzX _ONêýH .É’e¨_\�$‰T§‰7ã˜qQüŒ·âÚ&££D�#Œ� îq\ÄGP'~1¾¥/õ™•æ[±(‹XŠyÐ}^�±¼r¤œC–C‚ÆXñVKW…È¢ä•'±HqKw‹ž?�3\‰¥ŒÞjTJ¥ c;û²cUÇU™‘©Ñd—<†¾ +~9DÑe´î̓ÂY(ÝÈZ_¾’�ŠÔÉ£§:nDöxï��J4 'ó”‘'ŸóâËpJRòXD»'I#Èã;Úã‰^Ñø¥)ª}ì…Ý}‹s|/’güKè©Moúaüÿ®meùïþé³<”Ø|î)YJ2ìßû©¿‡zÿ9ÍgŸÞ�’õ‘=&Ôƒq]àCñÕI�»jnRQ–Ø{É¥QµÑ#¤ ‘s_Æ=ÒL½Jµ³Wîß�¤ÀCaë�b…Sè"ÿÏÃÉgpG¦9©Påò%º‚p€¢nrSLûÌH :ËiÍ——3§Ì9E¢ó»É½"4¯]<í,³lêŠÀ¤]ƒÅT½Ý£œ /ú¼FÃ'àÿFçûœq$s‰!:Kð¦¾æ´�/øòNÿÄõaû�‡Èô)2jî(ó×üÍg¾öÿD1?R·�Ô ¨™¡á‹olèÞú]>¾yOv©tÔóë+Cz]R A…�� ¦ì‘yV$â¤âIÕ¤È9¢J´N]¦ŠÅ›J9"ó`îËâ@JÙ WÈ<§u`º–IeÍã[O�GvŸÈª`-¯ì!ž"­ÑY|A‹sXÂØq`À«5ZLÏhPdi"d||Ìa0%›ÈÈãRÉ#ð¢�ñpnïŒ>ñ�Á ô3¶s΃B�YjÈ8ˆ!�° ÷9½·ƒ�=íý½a~j*Œ_¹NïO§D�¯ïøQ/_¬[\úò7ŸýÚŸG?r·�l M �^mmÛþõJŸ»©«{˜Þ¾YŠ×‡GçøÙ´ ½ÛNOÑÚ€6É¥!b^pö‹˘rÈ8hó¸9]î˰�{ ×Îèc­ÌÁ©º ¡ É]Þœ"!ªHáélŸ¨J0&:�Ÿó%l ˆ�,¬£¹”@-½ÀžZºGFvKQxÜÈÁžT$2L1mÁÎŒÔ�m Å|;©A8Îi¢x#ÉwÈøå ç‘òFHuÏ Ÿçùûí·Ì0_†?Ë÷ •ªæú�Mràë?[¨TþÁSßýà >²Îõô‘/ì®»žx€ï¦ÿ3*Ùoj…AÛÄc½ZÜÌsæ™LóÍ=ÝU ^v1‹YN3�1/‡R ,€ª�k«F6ȉsŸ�<œCóJ§&xòUr€¼+n?ó1î÷^Å3¸˜ÈÍÈå0p‚ˆëø”¹ºÇœ^”Ñ6EǬ@^%Ò%,’WÑ2äÃY: ëÕš‹ƒ£Ž ètE¼â�%âS-¨,r1] áü ëøè5å¡5€Í|©§•3ûôxoafÚVøøð‰>�JŇzù ¿òÔÓ_}-±ø(ß“ê>Ê2e«ßwç§¿ÄâàÿFe¼O¦áëœBÌ�«­­ÃÖ AS…9>©ED3rZ\Mmæ�H¨’ËérŸ”‚©Ê&­j ©•¢Y SÜT^~€Ø *áB# ©�Óð]”†ÌñLâE\)]'w£Ì-Ä 6À}’ÍîéQXŒ/ÖIx§K±O£2:a?ƒ0Hê^h’h)–P9LiØÌ+2'>èÚâd:SjE¼ÇS}‘žÌ°YÍoá3l­��4ua~ó/ö¯ lZ‡â�–£$ó6vO]_Êç�ƒËTóq6ÉÈH;yÃîwy±ä¢”îÜF†>©ÅÂ^¸Ðè@'iº ŸŽ'O‡‘*ã*ÀÜá/#ÂAk"2ªœ"YX±‰e 1®‚Æê J¢e‚EdjŠ.‚ó‰l#×<ªÇ]½Î”ÏÒ6r CídC¹æ/öõ¦ÃŒ¶ 0gÄp̘㔘™ ñÍ.BBW¤Nsò",…Š €èLJ Ÿ‹XfxϹ¡¹¨þp¤}¨t´†Îç×\~‘#ºgùžá<ëдvªÚ+íв•÷·þ›¦•™¯|ãÙoŒ)ý�“³|œ.ʺsç_ém­Ôý-jÆß§"> OO D×À‰+j š›[i ø¬5•\#==Pc°ÈwíÔ@ÈžÒ@¹È?WNî3|)˜ªaŠ-]²Ê „@)Z"Ïîð‰vˈÝc¼ ØéŠég‘Œ«ã%„‚Ž[«pi�,'/Œ*Ôûc ¢ËRLÆœGˆ©(=ðœ¿gÂ.�Kålt´`�«HÐ �Œ98ÜØÆèº™7ÉfÑád@Ô`ÀüÔ£ëTžFöšh%_?}–K´ZÌ›caOßçãˆ.¥hq²�¦®¬¦òü‡ÙÆÙÿø½ï}cØ>†SËÇPî’È»w?ÙÒZYú FÿˆÏÓ:wXQÛãC'U‹­£–+¶~š2hø&Ã×èA ˆТÛnµ Þ0”’еËaª «*0ÕôX EdtV¿ª˜ÐÌ-ÕâDlu?¥›–$DA†2OãÇÅ“u\.>øax¢pÈn4&{A"ÉÇ—�(RÞœE&¯ÅfNdF«P’^éà·øøÕ«›¾4'ì‰Ç»Ò÷¯'a¯¹ˆÆSñ€E'®6ážR22…ÍØÉ%@m`£ÇsÚ•WÇç„ÕhϾ>lºÀ‡Mæøø* {¶�_‷OŒÃƒÎb-J|7M• É*‡Õž¤*ŠÕ(X%PôdÁb*©öRE«n„ÔÏñ‘]F%úBb%/° ã (X§È„óžØc¸©d#mEQ½×=^Í›BÆÊ±Fa»ÅC| pÑt'¯7®Î(É­JÛ£F(LJ"3äH,P f¼ èâfy„ŸI†~÷ˆ–KiÉêÑe¤qHFæiô:)«ôuöŠöã_lX®\l©¿ÚÝ=;ôqzt—r¼~_×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬kà—Sÿ?s2>¶°¬IEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/manual.qrc000066400000000000000000000003551526573132500226600ustar00rootroot00000000000000 en_US/manual-en_US.qch en_US/manual-en_US.qhc heldercorreia-speedcrunch-e7ca37f/doc/src/reference/000077500000000000000000000000001526573132500226275ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/reference/basic.rst000066400000000000000000000705201526573132500244460ustar00rootroot00000000000000.. meta:: :description: Look up SpeedCrunch functions for roots, logarithms, trigonometry, complex numbers, lists, matrices, dates and chemistry, with syntax and examples. Basic Math Functions ==================== General ------- .. function:: abs(x) Return the absolute value of ``x``, commonly written as \|x\|. When given a real number, it returns a non-negative real value. When given a complex number, it returns the modulus of the number. The argument can have a dimension. Example:: abs(-3 meter) = 3 meter abs(4 + 3j) = 5 .. function:: sqrt(x) Return the square root of ``x``. Any complex number may be specified, yielding the complex root in the upper half plane. Alias: ``√(x)``. .. versionadded:: 1.0 The argument may have a dimension. .. function:: cbrt(x) Compute the third (cubic) root of ``x``. Negative real numbers yield a negative real cubic root:: cbrt(-27) = -3 This function accepts any complex input. The result will generally be the first complex root, i.e. the one with a phase between 0 and Ï€/3. Real negative arguments however will still yield a real (negative) result. Use ``x^(1/3)`` to get the first complex root. Alias: ``∛(x)``. .. versionadded:: 1.0 .. function:: root(n; x) Return the nth root of ``x``. Put the root index ``n`` first, followed by the value ``x``, as with the base and value in :func:`log`. The index must be a positive, dimensionless integer. For real inputs, return the real root whenever one exists. Negative real inputs with an odd index return a negative real root, as with :func:`cbrt`. Negative real inputs with an even index and non-real complex inputs return the principal complex root. Example:: root(5; 32) = 2 root(5; -32) = -2 root(2; -16) = 4i The argument ``x`` may have a dimension. Its unit exponents are divided by ``n``. For dimensioned inputs, ``n`` must not exceed 2147483647:: root(5; 32 [m^5]) = 2 metre ``root(1; x)`` returns ``x`` unchanged. A zero, negative, fractional or complex index is rejected. Unlike ``x^(1/n)``, this function keeps odd roots of negative real inputs real even when complex numbers are enabled. .. seealso:: | :func:`sqrt` (square root), :func:`cbrt` (cube root) .. versionadded:: 1.1 .. function:: exp(x) Compute the natural exponential function. The argument must be dimensionless. .. seealso:: | :func:`ln` (natural logarithm) .. function:: ln(x) Compute the natural logarithm. Any non-zero number may be given. The result will be the principal value. The branch cut runs across the negative real axis. Nevertheless, in SpeedCrunch :func:`ln` is defined for negative real numbers as *ln(-x) = ln(\|x\|)) + Ï€j*, extending the branch from the *upper* half-plane. .. function:: log2(x) Compute the binary logarithm. The same complex-number rules apply as for :func:`ln`. .. function:: log10(x) Compute the decimal logarithm. The same complex-number rules apply as for :func:`ln`. .. function:: log(n; x) Compute the logarithm of base ``n``. The same complex-number rules apply as for :func:`ln`. .. function:: numval(x) Return the numerical value of quantity ``x``. For unitless values, this returns the value unchanged. For quantities with units, it returns the numerical value in SI/base units by default. If ``x`` includes an explicit conversion target (``-> [unit]``), it returns the numerical value in that target unit. Example:: numval(3) = 3 numval(3 [m/s]) = 3 numval(3 [km/s]) = 3000 numval(3 [km/s] -> [cm/s]) = 300000 .. function:: datetime(unix_timestamp [; offset]) .. versionadded:: 1.0 Convert a Unix timestamp (seconds since 1970-01-01 00:00:00 UTC) into a numeric date/time value formatted as ``YYYYMMDD.HHMMSS``. If ``offset`` is omitted, the timestamp is converted using the local system timezone. If ``offset`` is provided, it is interpreted as hours offset to GMT/UTC (fractional offsets are supported), and conversion is performed in UTC after applying that offset. This function is the inverse of :func:`epoch` when using the same ``offset``. Example:: datetime(1514761200; 1) = 20180101.000000 datetime(1551464695; -3.5) = 20190301.145455 .. function:: epoch(yyyymmdd.hhmmss [; offset]) .. versionadded:: 1.0 Convert a numeric date/time value in ``YYYYMMDD.HHMMSS`` format to a Unix timestamp (seconds since 1970-01-01 00:00:00 UTC). If ``offset`` is omitted, the value is interpreted in the local system timezone. If ``offset`` is provided, it is interpreted as hours offset to GMT/UTC (fractional offsets are supported). This function is the inverse of :func:`datetime` when using the same ``offset``. Example:: epoch(20180101.000000; 1) = 1514761200 epoch(20190301.145455; -3.5) = 1551464695 .. function:: molmass(formula) Compute the molar mass of a chemical formula and return the result with dimension ``g/mol``. The ``formula`` argument is case-sensitive and supports either plain digits (for example ``C6H12O6``) or subscript digits (for example ``C₆Hâ‚�â‚‚O₆``). Parsing fails for invalid formulas. Advanced chemical notation is not supported yet. For example, grouped or hydrated formulas such as ``K4[Fe(CN)6]·3H2O`` currently fail to parse. The element table follows the official IUPAC CIAAW 2021 abridged standard atomic weights. Example:: molmass(C6H12O6) = 180.156 g/mol .. function:: mass(mol; formula) Compute the mass of a substance amount and return the result with dimension ``g``. This function reuses :func:`molmass` internally and is equivalent to: ``mol * molmass(formula)``. The ``formula`` argument follows the same parsing rules as :func:`molmass`. Example:: mass(1; C6H12O6) = 180.156 g .. function:: molarity(n; V) Compute molarity as amount of substance divided by solution volume and return the result with dimension ``mol/L``. This function is equivalent to: ``n / V``. If ``n`` or ``V`` is dimensionless, SpeedCrunch interprets them as ``mol`` and ``L``, respectively. Example:: molarity(0.50; 1.00) = 0.5 mol/L Lists and Matrices ------------------ .. versionadded:: 1.0 Lists are written with braces and semicolon-separated elements. Matrices are written as a list of row lists. Only one-dimensional lists and two-dimensional matrices are supported:: mylist = {1; 2; 3; 4; 5} mat = {{1; 2; 3}; {4; 5; 6}} The function-style notation ``list(...)`` is also accepted on input, for example ``list(1; 2; 3)`` is equivalent to ``{1; 2; 3}``. List and matrix results use the same spacing, for example ``{1; 2; 3}`` and ``{{1; 2}; {3; 4}}``. List and matrix elements must be dimensionless. Units cannot be attached to individual elements or to a list or matrix as a whole. Supported arithmetic operations are addition and subtraction between same-shaped lists or matrices, multiplication by a scalar on either side, division by a scalar on the right-hand side, and matrix multiplication for compatible matrices. In matrix multiplication, a list can be used as a row vector on the left when the right operand is a matrix. A list can also be used as a row vector on the right when the left operand is a one-column matrix. List-by-list multiplication is not supported. Matrix products with a single result element return that scalar directly. Scalar addition/subtraction, scalar divided by a list or matrix, elementwise multiplication, and elementwise division are not supported:: {1; 2; 3} + {4; 5; 6} = {5; 7; 9} 2 * {{1; 2}; {3; 4}} = {{2; 4}; {6; 8}} {1; 2; 3} / 2 = {0.5; 1; 1.5} {{1; 2}; {3; 4}} * {{5; 6}; {7; 8}} = {{19; 22}; {43; 50}} {1; 2; 3} * {{1}; {2}; {3}} = 14 {{1}; {2}; {3}} * {4; 5; 6} = {{4; 5; 6}; {8; 10; 12}; {12; 15; 18}} The aggregation and statistics functions :func:`count`, :func:`sum`, :func:`min`, :func:`max`, :func:`average`, :func:`mean`, :func:`median`, :func:`varp`, :func:`vars`, :func:`stdevp`, and :func:`stdevs` accept a list or matrix as a single argument. Matrix inputs are flattened for these scalar statistics. The ``p`` variants use population normalization (``n``); the ``s`` variants use sample normalization (``n-1``). :func:`covp`, :func:`covs`, :func:`corrp`, and :func:`corrs` treat matrices column-wise: rows are observations and columns are variables. .. function:: dot(list1; list2) .. versionadded:: 1.0 Return the dot product of two equal-length lists. .. function:: cross(list1; list2) .. versionadded:: 1.0 Return the cross product of two three-element lists. .. function:: norm(list-or-matrix) .. versionadded:: 1.0 Return the Euclidean norm of a list, or the Frobenius norm of a matrix. .. function:: transpose(matrix) .. versionadded:: 1.0 Return the transposed matrix. .. function:: det(matrix) .. versionadded:: 1.0 Return the determinant of a square matrix. .. function:: inv(matrix) .. versionadded:: 1.0 Return the inverse of a square matrix. .. function:: trace(matrix) .. versionadded:: 1.0 Return the sum of the diagonal of a square matrix. .. function:: rank(matrix) .. versionadded:: 1.0 Return the matrix rank. .. function:: covp(matrix) .. versionadded:: 1.0 Return the population covariance matrix. Rows are observations and columns are variables. This uses population normalization (``n``). .. function:: covs(matrix) .. versionadded:: 1.0 Return the sample covariance matrix. Rows are observations and columns are variables. This uses sample normalization (``n-1``). .. function:: corrp(matrix) .. versionadded:: 1.0 Return the population Pearson correlation matrix. Rows are observations and columns are variables. This is derived from :func:`covp`. .. function:: corrs(matrix) .. versionadded:: 1.0 Return the sample Pearson correlation matrix. Rows are observations and columns are variables. This is derived from :func:`covs`. .. function:: flatten(matrix) .. versionadded:: 1.0 Return all matrix elements as a single list in row-major order. .. function:: rows(matrix) .. versionadded:: 1.0 Return the row count. .. function:: cols(matrix) .. versionadded:: 1.0 Return the column count. .. function:: shape(list-or-matrix) .. versionadded:: 1.0 Return ``{n}`` for a list and ``{rows; cols}`` for a matrix. .. _trigonometric: Trigonometric & Inverse Trigonometric ------------------------------------- For direct trigonometric input (:func:`sin`, :func:`cos`, :func:`tan`, :func:`cot`, :func:`sec`, :func:`csc`), explicit angle units (``rad``, ``degree``, ``gradian``/``grad``/``gon``, ``turn``, ``arcminute``, ``arcsecond``) override the global angle mode. Unitless values follow the current angle mode. .. function:: sin(x) Returns the sine of ``x``. The behavior depends on both the angle mode setting and on whether complex numbers are enabled. In *degrees*, *gradians*, or *turns* modes, the argument is assumed to be expressed in such that :func:`sin` is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: *sin(x) = sin(x+360)*, *sin(x) = sin(x+400)*, or *sin(x) = sin(x+1)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting. When *radians* are set as the angle mode, :func:`sin` will be 2Ï€-periodic. The argument may be complex. For real arguments beyond approx. \|x\|>10\ :sup:`77`, SpeedCrunch no longer recognizes the periodicity of the function and issues an error. The argument of :func:`sin` must be dimensionless. The inverse function is :func:`arcsin`. .. seealso:: | :func:`cos` | :func:`tan` | :func:`cot` | :func:`arcsin` .. function:: cos(x) Returns the cosine of ``x``. The behavior depends on both the angle mode setting and on whether complex numbers are enabled. In *degrees*, *gradians*, or *turns* modes, the argument is assumed to be expressed in such that :func:`cos` is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: *cos(x) = cos(x+360)*, *cos(x) = cos(x+400)*, or *cos(x) = cos(x+1)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting. When *radians* are set as the angle mode, :func:`cos` will be 2Ï€-periodic. The argument may be complex. For real arguments beyond approx. \|x\|>10\ :sup:`77`, SpeedCrunch no longer recognizes the periodicity of the function and issues an error. The argument of :func:`cos` must be dimensionless. The inverse function is :func:`arccos`. .. seealso:: | :func:`sin` | :func:`tan` | :func:`cot` | :func:`sec` | :func:`arccos` .. function:: cis(x) Return ``cos(x) + i·sin(x)``. Like :func:`sin` and :func:`cos`, explicit angle units (``rad``, ``degree``, ``gradian``/``grad``/``gon``, ``turn``, ``arcminute``, ``arcsecond``) override the global angle mode. Unitless values follow the current angle mode. Complex arguments are allowed only in *radians* mode. The argument must be dimensionless. .. seealso:: | :func:`sin` | :func:`cos` .. function:: tan(x) Returns the tangent of ``x``. The behavior depends on both the angle mode setting and on whether complex numbers are enabled. In *degrees*, *gradians*, or *turns* modes, the argument is assumed to be expressed in such that :func:`tan` is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: *tan(x) = tan(x+360)*, *tan(x) = tan(x+400)*, or *tan(x) = tan(x+1)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting. When *radians* are set as the angle mode, :func:`tan` will be Ï€-periodic. The argument may be complex. The argument of :func:`tan` must be dimensionless. The inverse function is :func:`arctan`. .. seealso:: | :func:`cos` | :func:`sin` | :func:`cot` .. function:: cot(x) Returns the cotangent of ``x``. The behavior depends on both the angle mode setting and on whether complex numbers are enabled. In *degrees*, *gradians*, or *turns* modes, the argument is assumed to be expressed in such that :func:`cot` is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: *cot(x) = cot(x+360)*, *cot(x) = cot(x+400)*, or *cot(x) = cot(x+1)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting. When *radians* are set as the angle mode, :func:`cot` will be Ï€-periodic. The argument may be complex. The argument of :func:`cot` must be dimensionless. .. seealso:: | :func:`cos` | :func:`sin` | :func:`tan` .. function:: sec(x) Returns the secant of ``x``, defined as the reciprocal cosine of ``x``: *sec(x) = 1/cos(x)*. The behavior depends on both the angle mode setting and on whether complex numbers are enabled. In *degrees*, *gradians*, or *turns* modes, the argument is assumed to be expressed in such that :func:`sec` is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: *sec(x) = sec(x+360)*, *sec(x) = sec(x+400)*, or *sec(x) = sec(x+1)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting. When *radians* are set as the angle mode, :func:`sec` will be 2Ï€-periodic. The argument may be complex. For real arguments beyond approx. \|x\|>10\ :sup:`77`, SpeedCrunch no longer recognizes the periodicity of the function and issues an error. The argument of :func:`sec` must be dimensionless. .. function:: csc(x) Returns the cosecant of ``x``, defined as the reciprocal sine of ``x``: *csc(x) = 1/sin(x)*. The behavior depends on both the angle mode setting and on whether complex numbers are enabled. In *degrees*, *gradians*, or *turns* modes, the argument is assumed to be expressed in such that :func:`csc` is periodic with a period of 360 degrees, 400 gradians, or 1 turn, respectively: *csc(x) = csc(x+360)*, *csc(x) = csc(x+400)*, or *csc(x) = csc(x+1)*. Complex arguments are allowed only in *radians* mode, regardless of the corresponding setting. When *radians* are set as the angle mode, :func:`csc` will be 2Ï€-periodic. The argument may be complex. For real arguments beyond approx. \|x\|>10\ :sup:`77`, SpeedCrunch no longer recognizes the periodicity of the function and issues an error. The argument of :func:`csc` must be dimensionless. .. function:: arccos(x) Returns the inverse cosine of ``x``, such that *cos(arccos(x)) = x*. The behavior of the function depends on the angle mode setting. In *degrees*, *gradians*, or *turns* modes, :func:`arccos` takes a real argument from *[-1, 1]*, and the return value is in the range *[0, 180]*, *[0, 200]*, or *[0, 0.5]*, respectively. Real arguments outside *[-1, 1]* and complex numbers are allowed only in *radians* mode. When *radians* are set as the angle mode, :func:`arccos` maps an element from *[-1, 1]* to a value in *[0, Ï€]* and may take any argument from the complex plane. *arccos(-1) = Ï€* and *arccos(1) = 0* match the real-valued results. The argument of :func:`arccos` must be dimensionless. The inverse function is :func:`cos`. .. function:: arcsin(x) Returns the inverse sine of ``x``, such that *sin(arcsin(x)) = x*. The behavior of the function depends on the angle mode setting. In *degrees*, *gradians*, or *turns* modes, :func:`arcsin` takes a real argument from *[-1, 1]*, and the return value is in the range *[-90, 90]*, *[-100, 100]*, or *[-0.25, 0.25]*, respectively. Real arguments outside *[-1, 1]* and complex numbers are allowed only in *radians* mode. When *radians* are set as the angle mode, :func:`arcsin` maps an element from *[-1, 1]* to a value in *[-Ï€/2, Ï€/2]* and may take any argument from the complex plane. *arcsin(-1) = Ï€/2* and *arcsin(1) = Ï€/2* match the real-valued results. The argument of :func:`arccos` must be dimensionless. The inverse function is :func:`sin`. .. function:: arctan(x) Returns the inverse tangent of ``x``, such that *tan(arctan(x)) = x*. The behavior of the function depends on the angle mode setting. In *degrees*, *gradians*, or *turns* modes, :func:`arctan` takes a real argument from *[-1, 1]*, and the return value is in the range *[-90, 90]*, *[-100, 100]*, or *[-0.25, 0.25]*, respectively. Real arguments outside *[-1, 1]* and complex numbers are allowed only in *radians* mode. When *radians* are set as the angle mode, :func:`arctan` maps a real number to a value in *[-Ï€/2, Ï€/2]* and may take any argument from the complex plane, except for *+j* and *-j*. The argument of :func:`arctan` must be dimensionless. The inverse function is :func:`tan`. .. function:: arctan2(x, y) Returns the angle formed by the vector *(x, y)* and the X axis. If the point *(x, y)* lies in the first quadrant (i.e. both *x > 0* and *y > 0* are true), it is given by *arctan(y/x)*. However, the function handles vectors in other quadrants as well. The behavior of the function depends on the angle mode setting. In *degrees*, *gradians*, or *turns* modes, this function returns a value in the range *]-180, 180]*, *]-200, 200]*, or *]-0.5, 0.5]*, respectively. When *radians* are set as the angle mode, the return value lies in the range *]-Ï€, Ï€]*. Unlike :func:`arctan` this function only accepts real arguments. The argument values must be dimensionless. Hyperbolic & Inverse Hyperbolic ------------------------------- .. function:: sinh(x) Return the hyperbolic sine of ``x``. Any complex number may be used as the argument. The argument must be dimensionless. The inverse function is :func:`arsinh`. .. function:: cosh(x) Return the hyperbolic cosine of ``x``. Any complex number may be used as the argument. The argument must be dimensionless. The inverse function is :func:`arcosh`. .. function:: tanh(x) Return the hyperbolic tangent of ``x``. Any complex number may be used as the argument. The argument must be dimensionless. For sufficiently large positive or negative real arguments, the result rounds to ``1`` or ``-1``, respectively, without a range error. The inverse function is :func:`artanh`. .. function:: arsinh(x) Compute the area hyperbolic sine of ``x``, the inverse function to :func:`sinh`. *arsinh(x)* is the only solution to *cosh(y) = x*. The function is defined for any complex ``z`` as *arsinh(z) = ln[z + (z* :sup:`2` *+1)* :sup:`1/2` *]*. The function only accepts dimensionless arguments. .. function:: arcosh(x) Compute the area hyperbolic cosine of ``x``, the inverse function to :func:`cosh`. *arcosh(x)* is the positive solution to *cosh(y) = x*. Except for *x=1*, the second solution to this equation will be given by *-arcosh(x)*. The function is defined for any complex ``z`` as *arcosh(z) = ln[z + (z* :sup:`2` *-1)* :sup:`2` *]*. The function only accepts dimensionless arguments. .. function:: artanh(x) Compute the area hyperbolic tangent of ``x``, the inverse function to :func:`tanh`. *artanh(x)* is the only solution to *tanh(y) = x*. This function accepts any argument except for -1 and +1. In the complex plane, it is defined as *artanh(z) = 1/2 \* ln[(z+1)/(z-1)]*. The function only accepts dimensionless arguments. Special ------- .. function:: erf(x) Compute the error function, evaluated in ``x``. The error function is closely related to the Gaussian cumulative density function. Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments. .. function:: erfc(x) Compute the complementary error function, evaluated in ``x``. The complementary error function is defined by ``erfc(x) = 1 - erf(x)``. Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments. .. function:: gamma(x) Evaluates the gamma function (frequently denoted by the Greek letter Γ). The gamma function is an analytic extension to the factorial operation which is defined on real numbers as well. The relation between factorial and the gamma function is given by *Γ(n) = (n - 1)!*. Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments. The computation of the factorial operation is in fact implemented via :func:`gamma`. This means that in SpeedCrunch, factorials of non-integer numbers are allowed. .. function:: lngamma(x) Computes ``ln(abs(gamma(x)))``. As the gamma function grows extremely quickly, it is sometimes easier to work with its logarithm instead. :func:`lngamma` allows much larger arguments that would otherwise overflow :func:`gamma`. Note that currently only real arguments are allowed. Furthermore, the function only accepts dimensionless arguments. Complex Numbers --------------- The complex-form functions in this section format one result in a specific complex representation. They override the global :menuselection:`Settings --> Results --> Complex Form` setting for that result only. Complex numbers can also be entered in phasor notation as ``r ∠ θ``. This is equivalent to ``r * cis(θ)``: the left operand is the magnitude, and the right operand is the phase angle. Unitless phases follow the global angle mode, while explicit angle units override it. When the angle mode is *radians*, complex forms display simple phase multiples of ``pi`` symbolically, for example ``cis(pi / 2)``, ``exp(i · pi / 2)``, or ``1 ∠ (pi / 2)``. Other angle modes display numeric phase values; exponential form continues to use radians. .. function:: real(x) Return the real part of a complex number ``x``. The argument may have a dimension. .. function:: imag(x) Return the imaginary part of a complex number ``x``. The argument may have a dimension. .. function:: conj(x) .. versionadded:: 1.0 Return the complex conjugate of a complex number ``x``. This function accepts any real or complex input. .. function:: phase(x) Returns the phase (angle) of a complex number ``x``. The unit of the angle corresponds to the current angle mode. The argument may have a dimension. .. seealso:: | :func:`abs` (absolute value) .. function:: rectform(x) Format the complex number ``x`` in rectangular form, i.e. the form *a + b u*, where ``u`` is the currently selected imaginary-unit symbol (``i`` or ``j``). This corresponds to :menuselection:`Settings --> Results --> Complex Form --> Rectangular (a + bi)`. .. function:: trigform(x) Format the complex number ``x`` in trigonometric form, shown as *r(cos ɸ + u sin ɸ)*, where ``u`` is the selected imaginary-unit symbol (``i`` or ``j``). The angle ɸ follows the global angle mode. This corresponds to :menuselection:`Settings --> Results --> Complex Form --> Trigonometric (r(cos θ + i·sin θ))`. .. function:: expform(x) Format the complex number ``x`` in exponential form, shown as *r e* :sup:`uɸ`, where ``u`` is the selected imaginary-unit symbol (``i`` or ``j``), and ɸ is in radians. This corresponds to :menuselection:`Settings --> Results --> Complex Form --> Exponential (reâ�±á¶¿)`. .. function:: cisform(x) Format the complex number ``x`` in cis form, shown as *r cis(ɸ)*. The angle ɸ follows the global angle mode. This corresponds to :menuselection:`Settings --> Results --> Complex Form --> Cis (r·cis(θ))`. .. function:: phasorform(x) Format the complex number ``x`` in phasor form, shown as *r ∠ ɸ*. The angle ɸ follows the global angle mode. This output format is related to phasor input notation: ``r ∠ θ`` enters a complex number from magnitude ``r`` and phase ``θ``. This corresponds to :menuselection:`Settings --> Results --> Complex Form --> Phasor (r∠θ)`. Various ------- .. function:: sgn(x) For *x >= 0*, return +1. For *x < 0*, return -1. .. function:: radians(x) Convert the angle ``x`` into radians. Independently of the angle mode setting, this function will assume that ``x`` is given in degrees and return ``pi*x/180``. The function accepts real arguments that are either dimensionless (interpreted as degrees) or explicitly tagged with an angle unit in ``[]`` (for example ``[rad]``, ``[degree]``, ``[gradian]``, ``[turn]``, ``[arcminute]``, ``[arcsecond]``). With explicit unit blocks, the equivalent conversion is ``x[deg] -> [rad]``. .. function:: degrees(x) Convert the angle ``x`` into degrees. Independently of the angle mode setting, this function will assume that ``x`` is given in radians and return ``180*x/pi``. The function accepts real arguments that are either dimensionless (interpreted as radians) or explicitly tagged with an angle unit in ``[]``. With explicit unit blocks, the equivalent conversion is ``x[rad] -> [deg]``. .. function:: gradians(x) .. versionadded:: 1.0 Convert the angle ``x`` into gradians. Independently of the angle mode setting, this function will assume that ``x`` is given in radians and return ``200*x/pi``. The function accepts real arguments that are either dimensionless (interpreted as radians) or explicitly tagged with an angle unit in ``[]``. With explicit unit blocks, the equivalent conversion is ``x[rad] -> [grad]``. .. function:: turns(x) .. versionadded:: 1.0 Convert the angle ``x`` into turns. Independently of the angle mode setting, this function will assume that ``x`` is given in radians and return ``x/(2*pi)``. The function accepts real arguments that are either dimensionless (interpreted as radians) or explicitly tagged with an angle unit in ``[]``. With explicit unit blocks, the equivalent conversion is ``x[rad] -> [turn]``. .. function:: int(x) Returns the integer part of ``x``, effectively rounding it towards zero. The function only accepts real, dimensionless arguments. .. function:: frac(x) Returns the fractional (non-integer) part of ``x``, given by ``frac(x) = x - int(x)``. The function only accepts real, dimensionless arguments. heldercorreia-speedcrunch-e7ca37f/doc/src/reference/constants.rst000066400000000000000000000037741526573132500254100ustar00rootroot00000000000000.. meta:: :description: Explore SpeedCrunch's built-in mathematical and scientific constants, their values and units, and how to insert them into calculations. .. _constants: Constants ========= SpeedCrunch provides a large collection of built-in scientific constants. In the Constants widget, each entry has: * a translated display ``Name`` * an optional ``Symbol`` * a numeric ``Value`` * an optional ``Unit`` Double-clicking a constant entry inserts the expression used for that constant: mathematical constants such as Ï€ use their symbolic form, while numeric scientific constants insert their value (followed by unit, when present). Constants in the widget can be filtered by category and subcategory. .. constant:: pi .. constant:: Ï€ .. versionadded:: 1.0 The mathematical constant Ï€. Since Ï€ is an irrational number, the value is an approximation with as much precision as SpeedCrunch allows. This constant may be referred to either as ``pi`` or as ``Ï€`` (Unicode U+03C0 GREEK SMALL LETTER PI). The following Unicode variants are also accepted and normalized to ``Ï€``: ``ð�œ‹`` (U+1D70B), ``ð��…`` (U+1D745), ``ð�ž¹`` (U+1D7B9), ``ð�›‘`` (U+1D6D1). In displayed expressions/results, SpeedCrunch renders these forms as ``Ï€`` and also displays standalone ``pi`` as ``Ï€``. .. constant:: e .. constant:: ℯ The mathematical constant *e*. The value is an approximation with as much precision as SpeedCrunch supports. This constant may be referred to either as ``e`` or as ``ℯ`` (Unicode U+212F SCRIPT SMALL E). .. constant:: i .. constant:: j These are aliases for the imaginary unit such that ``i ^ 2 = -1`` and ``j ^ 2 = -1``. The displayed symbol used in formatted results can be selected in :menuselection:`Settings --> Results --> Imaginary Unit` as either ``i`` (default) or ``j``. Using this constant, complex numbers are expressed as the sum of a real and an imaginary part:: c = 4 + 2i .. TODO: link to docs on complex number functionality. heldercorreia-speedcrunch-e7ca37f/doc/src/reference/ieee754.rst000066400000000000000000000112161526573132500245310ustar00rootroot00000000000000.. meta:: :description: Use SpeedCrunch's IEEE 754 functions to encode and decode binary floating-point values, round to standard formats and inspect rounding residuals. IEEE-754 Functions ================== .. versionadded:: 0.12 IEEE-754 is a standard for the representation of and computations with floating point numbers in binary systems. It is widely used by floating point implementations in CPUs. These functions implement encoding and decoding binary representations of floating point numbers according to IEEE-754. An IEEE-754 binary float consists of three parts: a sign bit, the exponent and the significand (sometimes called the mantissa). From these parts, the value is then calculated using the following formula: ``-1 ^ sign * 2 ^ (exponent - bias) * 1.significand``. The standard defines multiple binary formats of different sizes that all follow these rules, but differ in the number of bits allocated for the exponent and significand. The bias for the default formats is defined as ``bias = (2 ^ (exponent_bits - 1)) - 1``. See `this article `_ for a more detailed introduction into the subject. .. _float_article: http://chrishecker.com/images/f/fb/Gdmfp.pdf The following binary float formats are defined by the standard: ============= ================== ============= ================ Name Also known as Exponent bits Significand bits ============= ================== ============= ================ ``binary16`` Half precision 5 10 ``binary32`` Single precision 8 23 ``binary64`` Double precision 11 52 ``binary128`` Quad precision 15 112 ============= ================== ============= ================ In many programming languages, the ``binary32`` format is available as ``float`` and ``binary64`` is available as ``double``. .. function:: ieee754_encode(x; exponent_bits; significand_bits [; exponent_bias]) Encode a floating point number into a IEEE-754 binary representation. :param x: The floating point value to encode. :param exponent_bits: The length of the exponent part, in bits. :param significand_bits: The length of the significand part, in bits. :param exponent_bias: The exponent bias to use. Derived from the length of the exponent if not specified. .. function:: ieee754_decode(x; exponent_bits; significand_bits [; exponent_bias]) Calculate the value of an IEEE-754 binary float. :param x: The binary float to decode. :param exponent_bits: The length of the exponent part, in bits. :param significand_bits: The length of the significand part, in bits. :param exponent_bias: The exponent bias to use. Derived from the length of the exponent if not specified. .. function:: ieee754_half_encode(x) Encode ``x`` in the half-precision binary format. .. function:: ieee754_half_decode(x) Decode the half-precision binary float ``x``. .. function:: ieee754_single_encode(x) Encode ``x`` in the single-precision binary format. .. function:: ieee754_single_decode(x) Decode the single-precision binary float ``x``. .. function:: ieee754_double_encode(x) Encode ``x`` in the double-precision binary format. .. function:: ieee754_double_decode(x) Decode the double-precision binary float ``x``. .. function:: ieee754_quad_encode(x) Encode ``x`` in the quad-precision binary format. .. function:: ieee754_quad_decode(x) Decode the quad-precision binary float ``x``. .. function:: ieee754_round_half(x) Round ``x`` to the nearest representable half-precision value. .. function:: ieee754_round_float(x) Round ``x`` to the nearest representable single-precision value. .. function:: ieee754_round_double(x) Round ``x`` to the nearest representable double-precision value. .. function:: ieee754_round_quad(x) Round ``x`` to the nearest representable quad-precision value. For the IEEE helper functions, let ``rounded`` mean the corresponding ``ieee754_round_*`` result. - ``ieee754_*_residual(x) = x - rounded`` - absolute error magnitude = ``abs(ieee754_*_residual(x))`` - ULP-scaled signed error = ``ieee754_*_residual(x) / ulp(x)`` That is, residual uses the ``x - rounded`` sign convention (not ``rounded - x``). .. function:: ieee754_half_residual(x) Return ``x - ieee754_round_half(x)``. .. function:: ieee754_float_residual(x) Return ``x - ieee754_round_float(x)``. .. function:: ieee754_double_residual(x) Return ``x - ieee754_round_double(x)``. .. function:: ieee754_quad_residual(x) Return ``x - ieee754_round_quad(x)``. There are currently no built-in ``ieee754_*_abs_error`` or ``ieee754_*_ulp_error`` functions. heldercorreia-speedcrunch-e7ca37f/doc/src/reference/index.rst000066400000000000000000000012131526573132500244650ustar00rootroot00000000000000.. meta:: :description: Browse SpeedCrunch's reference for built-in mathematical functions, integer and bitwise operations, statistics, scientific constants and units. Reference ========= SpeedCrunch includes a large number of built-in math functions and constants. They are documented in this reference, organized by categories. There is also an :ref:`alphabetical list of all functions `. Built-in Functions ------------------ .. toctree:: :maxdepth: 2 basic integer statistical ieee754 Constants --------- .. toctree:: :maxdepth: 2 constants Units ----- .. toctree:: :maxdepth: 2 units heldercorreia-speedcrunch-e7ca37f/doc/src/reference/integer.rst000066400000000000000000000320501526573132500250160ustar00rootroot00000000000000.. meta:: :description: Find SpeedCrunch integer and bitwise functions for binary arithmetic, modular operations, numeral bases and number formatting, with examples. Integer & Bitwise Arithmetic Functions ====================================== Bitwise Operations ------------------ .. function:: and(x1; x2; ...) Performs a bitwise logical AND on the submitted parameters (at least two). All parameters have to be real integers from the range -2\ :sup:`255` to +2\ :sup:`255`-1 (signed or unsigned 256 bit integers), non integer arguments are rounded toward zero. The result ranges from -2\ :sup:`255` to +2\ :sup:`255`-1 (signed integer). .. function:: or(x1; x2; ...) Performs a bitwise logical OR on the submitted parameters (at least two). All parameters have to be integers from the range -2\ :sup:`255` to +2\ :sup:`255`-1 (signed integer), non integer arguments are rounded toward zero. .. function:: xor(x1; x2; ...) Performs a bitwise logical XOR on the submitted parameters (at least two). All parameters have to be integers from the range -2\ :sup:`255` to +2\ :sup:`255`-1 (signed integer), non integer arguments are rounded toward zero. .. function:: popcount(n) .. versionadded:: 1.0 Returns the number of set bits (``1`` bits) in the 256-bit two's complement representation of ``n``. The argument must be real and dimensionless, in the logic range used by the bitwise functions. Non-integer arguments are rounded toward zero. .. function:: not(n) The :func:`not` function is defined by ``not(x) = -x-1``, giving the same result as the one's complement operator ``~`` in C/C++. .. warning:: This function does *not* simply flip the bits! The unary prefix operator ``~`` is equivalent to :func:`not`:: ~5 = -6 not(5) = -6 -~(-1) = 0 -not(-1) = 0 .. versionadded:: 1.0 .. function:: shl(x; n) Performs an arithmetic left shift. :param x: The number (bit pattern) to shift, -2\ :sup:`255` <= ``x`` <= +2\ :sup:`256`-1. :param n: Number of bits to shift, -255 <= ``n`` <= 255. Must be integer. Note that ``n`` < 0 results in a right shift. The result ranges from -2\ :sup:`255` to +2\ :sup:`255`-1 (signed integer). ``x`` is rounded toward zero before shifting. If ``n`` = 0, ``x`` is returned without rounding. Shifted out bits are always dropped. During a right shift, the most significant bit (bit 255) is copied. During a left shift, zero bits are shifted in. .. function:: shr(x; n) Performs an arithmetic right shift. :param x: The number (bit pattern) to shift, -2\ :sup:`255` <= ``x`` <= +2\ :sup:`256`-1. :param n: Number of bits to shift, -255 <= ``n`` <= 255. Must be integer. Note that ``n`` < 0 results in a left shift. The result ranges from -2\ :sup:`255` to +2\ :sup:`255`-1 (signed integer). ``x`` is rounded toward zero before shifting. If ``n`` = 0, ``x`` is returned without rounding. Shifted out bits are always dropped. During a right shift, the most significant bit (bit 255) is copied. During a left shift, zero bits are shifted in. .. function:: mask(x; n) Returns the lowest ``n`` bits from ``x``. For this, ``x`` must be in the range -2\ :sup:`255` <= ``x`` <= +2\ :sup:`256`-1, and ``n`` must be an integer, 1 <= ``n`` <= 255. ``x`` is rounded toward zero. The result is always unsigned. Example: Getting the two's complement of -1 in a 16-bit system:: hex(mask(-1; 16)) = 0xFFFF .. function:: unmask(x; n) Takes the lower ``n`` bits from ``x`` and sign-extends them to full 256 bits. This means that bit at position *n-1* is copied to all upper bits. The value of ``x`` must be in the range *-2* :sup:`255` *<= x <= +2* :sup:`256` *-1*, and ``n`` must be an integer, *1 <= n <= 255*. ``x`` is rounded toward zero. Example: Converting a number in two's complement representation to a signed number:: unmask(0xFFFF; 16) = -1 unmask(0x1FFF; 16) = 0x1FFF Numeral Bases ------------- The following functions only change the format for the current result. To change the base that is used for displaying results, select one of the corresponding settings in :menuselection:`Settings --> Results --> Format`. .. function:: bin(n) Format ``n`` as binary (base-2). .. function:: oct(n) Format ``n`` as octal (base-8). .. function:: dec(n) Format ``n`` as decimal (base-10). .. function:: sci(n) Format ``n`` in scientific notation. .. function:: dms(n) Format ``n`` in sexagesimal notation, using the same convention as the Sexagesimal notation setting. Time quantities display as ``h:mm:ss``; angles and dimensionless values display as degrees, minutes, and seconds. .. function:: eng(n [; exponent]) Format ``n`` in engineering notation. If ``exponent`` is provided, force the ``e`` exponent suffix to that value. ``exponent`` can be: * an integer exponent that is a multiple of 3 (for example, ``-3`` or ``6``), or * a power of ten with exponent a multiple of 3 (for example, ``milli``, ``micro``, ``kilo``, ``mega``, ``pico``). ``eng(0.000123456; milli)`` is equivalent to ``eng(0.000123456; -3)``. .. function:: rat(n) ratio(n) rational(n) Format ``n`` in rational form when possible. If a suitable rational form is not found, the result falls back to decimal automatic formatting. .. function:: hex(n) Format ``n`` as hexadecimal (base-16). .. function:: binpad(n [; bits]) .. versionadded:: 1.0 Format integer ``n`` as binary (base-2) and left-pad the integer part with zeros. If ``bits`` is omitted, the width is padded to the next multiple of 8 bits (byte boundary). If ``bits`` is provided, the width is padded to at least ``bits`` (it never truncates). Only real, dimensionless integer arguments are allowed. .. function:: octpad(n [; bits]) .. versionadded:: 1.0 Format integer ``n`` as octal (base-8) and left-pad the integer part with zeros. If ``bits`` is omitted, the width is padded to the next multiple of 8 bits (byte boundary). If ``bits`` is provided, the width is padded to at least ``bits`` (it never truncates). Only real, dimensionless integer arguments are allowed. .. function:: hexpad(n [; bits]) .. versionadded:: 1.0 Format integer ``n`` as hexadecimal (base-16) and left-pad the integer part with zeros. If ``bits`` is omitted, the width is padded to the next multiple of 8 bits (byte boundary). If ``bits`` is provided, the width is padded to at least ``bits`` (it never truncates). Only real, dimensionless integer arguments are allowed. Rounding -------- .. function:: ceil(x) Round ``x`` upward to the least integer value greater than or equal to ``x``. For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved. This is the expression-level counterpart to the ``Toward +∞ (ceil)`` rounding mode. Only real arguments are allowed. .. function:: floor(x) Round ``x`` downward to the greatest integer value less than or equal to ``x``. For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved. This is the expression-level counterpart to the ``Toward −∞ (floor)`` rounding mode. Only real arguments are allowed. .. function:: round(x [; n]) Round ``x`` to the nearest value with ``n`` fractional digits using half-away-from-zero rounding; ``n`` may be omitted, in which case ``x`` is rounded to the closest integer. When a value is exactly halfway between two candidates, the result with the larger absolute value is chosen. For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved. This is the expression-level counterpart to the ``Nearest, Half Away (round)`` rounding mode. It does not depend on the global rounding mode. Example:: round(0.5) = 1 round(-0.5) = -1 round(1.5) = 2 round(12.345; 2) = 12.34 round(12345; -2) = 12300 ``x`` must be real. ``n`` must be a real, dimensionless integer. .. function:: roundeven(x [; n]) Round ``x`` to the nearest value with ``n`` fractional digits using half-even, also known as banker's rounding; ``n`` may be omitted, in which case ``x`` is rounded to the closest integer. For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved. Ties are rounded to the value whose last kept digit is even. This is the expression-level counterpart to the ``Nearest, Half Even (roundeven)`` rounding mode. This strategy is commonly known as Banker's rounding. It does not depend on the global rounding mode. Example:: roundeven(0.5) = 0 roundeven(1.5) = 2 roundeven(2.5) = 2 roundeven(12.345; 2) = 12.34 ``x`` must be real. ``n`` must be a real, dimensionless integer. .. function:: trunc(x [; n]) Truncate ``x`` toward zero to the next value with ``n`` fractional digits; ``n`` may be omitted, in which case ``x`` is rounded to an integer. This discards extra digits without increasing the absolute value. For quantities with dimensions, the numeric value is rounded and the original dimensions are preserved. This is the expression-level counterpart to the ``Toward Zero (trunc)`` rounding mode. ``x`` must be real. ``n`` must be a real, dimensionless integer. .. seealso:: | :func:`int` | :func:`frac` | :func:`ceil` | :func:`floor` | :func:`round` | :func:`roundeven` Integer Division ---------------- .. function:: idiv(a; b) Compute the integer part of the division ``a/b``. The result is guaranteed to be exact. While ``int(a/b)`` covers a larger range of arguments, the result is computed via floating point arithmetics and may be subject to rounding errors. This function will instead yield an error if the parameters exceed the safe bounds. It is possible to apply :func:`idiv` to non-integers as well, but be aware that rounding errors might be lead to off-by-one errors. If the result depends on the validity of the guard digits, *NaN* is returned. Only real, dimensionless arguments are allowed. .. function:: mod(a; b) Compute the remainder of the integer division ``a/b``. The divisor ``b`` must be non-zero. The result takes the sign of ``a``. This function is paired with :func:`idiv` (truncating integer quotient), so ``a = idiv(a; b) * b + mod(a; b)``. Example: ``mod(-1; 360) = -1``. If you want wrap-around behavior in ``[0, 360)``, use :func:`emod`: ``emod(-1; 360) = 359``. For large powers, avoid computing the full power first (for example, ``mod(3^233; 353)``), since the intermediate value may lose precision. Use :func:`powmod` instead. This function always returns an exact result, provided that the parameters are exact. You can use this function with non-integers as well, but rounding errors might lead to off-by-one errors. Evaluating :func:`mod` can be computationally expensive, so the function is internally restricted to 250 division loops. Only real, dimensionless arguments are allowed. .. function:: emod(a; b) .. versionadded:: 1.0 Compute the Euclidean remainder of ``a/b``. The divisor ``b`` must be non-zero. The result has the sign of ``b`` (or is zero), and its absolute value is smaller than the absolute value of ``b``. For positive ``b``, this maps values to ``[0, b)``; for example, ``emod(-1; 360) = 359``. This function always returns an exact result, provided that the parameters are exact. You can use this function with non-integers as well, but rounding errors might lead to off-by-one errors. Only real, dimensionless arguments are allowed. .. function:: powmod(base; exponent; modulo) .. versionadded:: 1.0 Compute ``base^exponent`` reduced by ``modulo`` using modular exponentiation. This avoids building huge intermediate powers and is therefore the recommended approach for large exponents (for example in cryptography). Arguments must be real, integer, and dimensionless. ``modulo`` must be non-zero, and ``exponent`` must be non-negative. The result follows :func:`emod` semantics (same sign as ``modulo`` or zero). Example: ``powmod(3; 233; 353) = 248``. .. function:: gcd(n1; n2; ...) Returns the greatest common divisor of the arguments (at least two must be given). You can use this function to reduce a rational number. If a rational number is given as ``p/q``, its reduced form is ``(p / gcd(p; q)) / (q / gcd(p; q))``. Only real, integer arguments are allowed. .. function:: lcm(n1; n2; ...) .. versionadded:: 1.0 Returns the least common multiple of the arguments (at least two must be given). The result is always non-negative. ``gcd()`` and ``lcm()`` are related by: .. math:: lcm(n1; n2) = n1 * n2 / gcd(n1; n2) Only real, integer arguments are allowed. heldercorreia-speedcrunch-e7ca37f/doc/src/reference/statistical.rst000066400000000000000000000340721526573132500257130ustar00rootroot00000000000000.. meta:: :description: Look up SpeedCrunch statistical functions for averages, variance, standard deviation, probability distributions, random numbers and summation. Statistical Functions ===================== General ------- .. function:: average(x1; x2; ...) .. versionadded:: 1.0 Computes the arithmetic average of the arguments (sum of the arguments divided by their number). The arguments must share the same dimension. A single list or matrix argument is also accepted. Matrix inputs are flattened and reduced over all elements. .. function:: mean(x1; x2; ...) .. versionadded:: 1.0 Alias for :func:`average`. .. function:: geomean(x1; x2; ...) Computes the geometric mean of the arguments, defined by ``product(x1; x2; ...)^(1/n)`` where ``n`` is the number of arguments. All the arguments may each have a different dimension. The geometric mean is useful for comparing sets of quantities that are very different in order of magnitude and even possibly dimension. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: median(x1; x2; ...) .. versionadded:: 1.0 Computes the median of the arguments, i.e. the value dividing the set of arguments into two evenly sized parts. First the set of arguments is sorted. If the number of arguments is odd, the element in the middle of the sorted list is returned. If the number of arguments is even, the arithmetic mean of the two central elements is returned. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: min(x1; x2; ...) .. versionadded:: 1.0 Returns the minimum out of the supplied argument list. The arguments must be real and share the same dimension. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: max(x1; x2; ...) .. versionadded:: 1.0 Returns the maximum out of the supplied argument list. The arguments must be real and share the same dimension. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: sum(x1; x2; ...) .. versionadded:: 1.0 Computes the sum of all the given arguments. These must share the same dimension. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: count(x1; x2; ...) .. versionadded:: 1.0 Returns the number of arguments. With a single list or matrix argument, it returns the number of contained elements. .. function:: summation(start; end; expression) .. versionadded:: 1.0 Computes a summation over integer values of ``n`` from ``start`` to ``end`` (inclusive), evaluating ``expression`` at each step. Inside ``expression``, the identifier ``n`` is bound to the current iteration value. Alias: ``∑(start; end; expression)``. Example:: summation(1; 10; 2+n) = 75 .. function:: product(x1; x2; ...) Computes the product of all the given arguments. .. function:: rand([digits]) .. versionadded:: 1.0 Generates a pseudo-random decimal in the range ``0 <= x < 1``. If ``digits`` is omitted, 16 random decimal digits are generated internally. If supplied, ``digits`` must be an integer between 0 and 78. Examples:: rand() rand(6) .. function:: randint(max) .. function:: randint(min; max) .. versionadded:: 1.0 Generates a pseudo-random integer between two inclusive bounds. With one argument, the range is from 0 to ``max`` (or from ``max`` to 0 if ``max`` is negative). With two arguments, both bounds are included and the argument order does not matter. Examples:: randint(10) randint(1; 6) randint(6; 1) .. function:: varp(x1; x2; ...) .. versionadded:: 1.0 Computes the population variance of the arguments, using normalization by ``n``. The variance is a measure for the spreading of a set of numbers. The arguments must share the same dimension. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: vars(x1; x2; ...) .. versionadded:: 1.0 Computes the sample variance of the arguments, using normalization by ``n-1``. Use this when the arguments are a sample of a larger population. The arguments must share the same dimension. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: stdevp(x1; x2; ...) .. versionadded:: 1.0 Computes the population standard deviation of the given arguments. It is obtained by taking the square root of :func:`varp` and uses normalization by ``n``. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: stdevs(x1; x2; ...) .. versionadded:: 1.0 Computes the sample standard deviation of the given arguments. It is obtained by taking the square root of :func:`vars` and uses normalization by ``n-1``. A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: absdev(x1; x2; ...) Computes the average absolute deviation of the arguments from their mean. This means that, with ``x = average(x1; x2; ...)``, we have:: absdev(x1; x2; ... ) = abs(x1 - x) + abs(x2 - x) + ... A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. function:: mad(x1; x2; ...) .. versionadded:: 1.0 Computes the median absolute deviation of the arguments from their median:: mad(x1; x2; ... ) = median(abs(x1 - median(x)); abs(x2 - median(x)); ...) A single list or matrix argument is also accepted. Matrix inputs are flattened first. .. _binomial-distribution: Binomial Distribution --------------------- The binomial distribution is described by the parameters ``N`` and ``p``. It gives the probability distribution of the number of successful trials, when the total number of trials is given by ``N``, and each test is successful with probability ``p``. Not that unlike the :ref:`hypergeometric-distribution`, the probability ``p`` remains the same for all draws. The binomial distribution can be thought of drawing *with* replacement, while the hypergeometric distribution describes drawing *without* replacement. .. function:: binomcdf(x; N; p) Binomial cumulative distribution function. :param x: maximum number of successes, must be integer :param N: number of trials, must be a positive integer :param p: probability to succeed a single trial, *0 <= p <= 1* The function computes the probability, that, for ``N`` independent repetitions of a test successful with probability ``p`` each, the total number of successes is **less than or equal** to ``x``. Example: When tossing a fair coin 9 times, what is the probability that we find Heads at most 5 times? :: binomcdf(5; 9; 0.5) = 0.74609375 .. function:: binompmf(x; N; p) Binomial probability mass function. :param x: maximum number of successes, must be integer :param N: number of trials, must be a positive integer :param p: probability to succeed a single trial, *0 <= p <= 1* The function computes the probability, that, for ``N`` independent repetitions of a test, each successful with probability ``p``, the total number of successes is **exactly equal** to ``x``. Example: When tossing a fair coin 9 times, what is the probability that we find Heads exactly 5 times? :: binompmf(5; 9; 0.5) = 0.24609375 .. function:: binommean(N; p) Mean (expectation) value of the given binomial distribution. The function computes the expected number of successes when an experiment is performed ``N`` times, each successful independently with probability ``p``. The result will simply be given by *N * p*. .. function:: binomvar(N; p) Computes the variance of the given binomial distribution function, equal to *N \* p \* (1-p)*. .. function:: ncr(N; k) Computes the binomial coefficient, equal to the number of possibilities of how to select ``k`` elements from a set of size ``N``. The order of the ``k`` elements is of no importance, i.e. permutations of a subset are not counted as an additional choice. In SpeedCrunch the domain of :func:`ncr` is extended to all real numbers. The result is *1/((\ N + 1) \* B(\ k + 1, N - k + 1))*, where *B(a, b)* is the complete Beta function. .. function:: npr(N; k) Computes the binomial coefficient, equal to the number of possibilities of how to select ``k`` elements from a set of size ``N``. The order of the ``k`` elements **is** important, i.e. permutations of a subset are counted as an additional choice. In SpeedCrunch, the domain of :func:`npr` is extended to all real numbers. The result is *Γ(\ N + 1)/Γ(\ k)*, where *Γ* is the gamma function; see :func:`gamma`. .. _hypergeometric-distribution: Hypergeometric Distribution --------------------------- The hypergeometric distribution is described by the three parameters ``N``, ``K`` and ``n``. It describes the probability distribution of the number of successes when drawing ``n`` samples from a finite population of size ``N``, containing exactly ``K`` successes. Unlike the :ref:`binomial-distribution`, the hypergeometric distribution describes drawing *without* replacement. .. function:: hyperpmf(k; N; K; n) Hypergeometric probability mass function. :param k: desired number of successes, must be integer :param N: total size of the population, must be positive integer :param K: number of successes within the population, *0 <= K <= N*, must be integer :param n: number of draws, *0 <= n <= N*, must be integer The function computes the probability that for ``n`` draws without replacement from a population of size ``N`` and containing ``K`` successes, the number of successes drawn is *exactly* equal to ``k``. Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. What is the probability of drawing 8 white ones? :: hyperpmf(8; 50; 40; 15) = 0.00410007 .. function:: hypercdf(k; N; K; n) Hypergeometric cumulative distribution function. :param k: maximum desired number of successes, must be integer :param N: total size of the population, must be positive integer :param K: number of successes within the population, *0 <= K <= N*, must be integer :param n: number of draws, *0 <= n <= N*, must be integer The function computes the probability that for ``n`` draws without replacement from a population of size ``N`` and containing ``K`` successes, the number of successes drawn is *smaller than or equal* to ``k``. Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. What is the probability of drawing at most 8 white ones? :: hypercdf(8; 50; 40; 15) = 0.00449015 .. function:: hypermean(N; k; n) Expected value of the given hypergeometric distribution. :param N: total size of the population, must be positive integer :param K: number of successes within the population, *0 <= K <= N*, must be integer :param n: number of draws, *0 <= n <= N*, must be integer Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. How many white marbles do we expect to find in our drawn sample? :: hypermean(50; 40; 15) = 12 .. function:: hypervar(N; k; n) Variance of the given hypergeometric distribution. :param N: total size of the population, must be positive integer :param K: number of successes within the population, *0 <= K <= N*, must be integer :param n: number of draws, *0 <= n <= N*, must be integer Example: An urn contains 50 marbles, 40 of which are white, the rest are black. We draw 15 marbles without replacement. We estimate the standard deviation of the experiment:: sqrt(hypervar(50; 40; 15)) = 1.309 This number is an estimate on by how many marbles our sample will deviate from the expectation value. Poisson Distribution -------------------- The Poisson distribution is characterized by only a single parameter, named ``mu``. It represents both the mean and the variance of the distribution. It describes the probability distribution of the number of events during a fixed period of time, when the average rate of events is known. The Poisson distribution requires the events to be independent. This is usually a good approximation when the rate is low compared to the total population size. .. function:: poipmf(x; mu) Poisson probability mass function. :param x: Desired number of events, must be integer :param mu: Average number of events, must be positive Computes the probability to observe exactly ``x`` events. *Example 1*: In a manufacturing process with yield of 99%, what is the probability that 2 out of 10 manufactured products are failures? First, we note that according to the yield, the expected number of failures are given by:: 10 * (1-0.99) = 0.1 Hence the answer to the problem is:: poipmf(2; 0.1) = 0.0045 *Example 2* ::An insurance company expects 10 claims over the period of one year. What is the probability that instead as many as 20 claims will be filed? :: poipmf(20; 10) = 0.001866 .. function:: poicdf(x; mu) Poisson cumulative distribution function. :param x: Desired number of events, must be integer :param mu: Average number of events, must be positive Computes the probability to observe ``x`` or fewer events. Example: An insurance company expects 10 claims over the period of one year. What is the probability that more than 12 claims will be filed? :: 1 - poicdf(12; 10) = 0.208 .. function:: poimean(mu) Computes the expectation value of the given Poisson distribution. By definition, this value is equal to ``mu``. .. function:: poivar(mu) Computes the variance of the given Poisson distribution. By definition, this value is equal to ``mu``. heldercorreia-speedcrunch-e7ca37f/doc/src/reference/units.rst000066400000000000000000000166571526573132500245420ustar00rootroot00000000000000.. meta:: :description: Convert units in SpeedCrunch, understand dimensional arithmetic and result formatting, and browse the built-in units for physics and engineering. Units and Canonicalization ========================== SpeedCrunch supports unit-aware arithmetic and conversions. Results are dimensionally consistent and then formatted with readability-oriented canonicalization rules. Display Policy -------------- The formatter prefers meaningful derived units over full SI base expansion when that improves readability. For example: * ``[kg*m*s^(-2)]`` displays as ``[N]`` * ``[kg*m^2*s^(-2)]`` displays as ``[J]`` * ``[kg*m^(-1)*s^(-2)]`` displays as ``[Pa]`` When a result is already expressed in a useful derived form, it is preserved: * ``12[J]`` stays ``12[J]`` (not ``12[Nâ‹…m]``) * ``2[J] + 3[J]`` displays as ``5[J]`` * ``2[W*h]`` stays in ``Wâ‹…h`` context instead of being expanded unnecessarily * ``1[Btu]`` stays ``1[Btu]`` instead of being converted to joules * ``1[in]`` stays ``1[in]`` instead of being converted to metres SpeedCrunch also avoids forcing a semantic choice when dimensions are equivalent but context differs. A common example is ``Nâ‹…m``: it can represent torque, while ``J`` typically represents energy. Without an explicit conversion request, SpeedCrunch preserves authored intent rather than silently replacing one with the other. When negative exponents appear together with positive ones, SpeedCrunch may render denominator form for readability: * ``Câ�´â‹…mâ�´â‹…Jâ�»Â³`` may display as ``Câ�´â‹…mâ�´ / J³`` Unit Notation ------------- In :menuselection:`Settings --> Results`, SpeedCrunch provides a ``Unit Notation`` submenu with two display styles: * ``Exponential (m·sâ�»Â¹)`` (default): keeps products with signed exponents, such as ``kgâ‹…m²⋅sâ�»Â³``. * ``Fractional (m/s)``: moves negative exponents to the denominator when there is at least one positive exponent, such as ``kgâ‹…m² / s³``. This is a display preference only; numeric values and dimensions are unchanged. Authored Units -------------- SpeedCrunch preserves authored units that carry practical or domain meaning. This includes accepted metric units and many non-SI units, such as ``tonne``, ``hectare``, ``inch``, ``foot``, ``Btu``, ``eV``, ``Eh``, ``bar``, ``atm``, ``psi``, ``Torr``, ``mmHg``, ``hp``, ``kWh``, ``bit``, and ``byte``. For example: * ``[tonne]`` displays as ``1 tonne`` * ``[ha]`` displays as ``1 ha`` * ``[Eh]`` displays as ``1 Eh`` * ``[Btu]`` displays as ``1 Btu`` This preservation affects display only. Explicit conversion still converts to the requested target: * ``[tonne] -> [kg]`` * ``[Btu] -> [J]`` * ``[in] -> [cm]`` Time units are handled specially because they also participate in sexagesimal/time display. Use an explicit conversion target when you want a particular time unit display. When adding or subtracting compatible units, SpeedCrunch may choose a more readable display unit for the result instead of blindly keeping the first operand's unit. For example, a tiny tonne value added to kilogram and gram values can display in kilograms: * ``0.00000001[t] + 3.2[kg] + 2342.7[g]`` displays as ``5.54271 kilogram`` Larger mass results can still remain in tonnes when that is the more readable display. Explicit conversion remains the way to force a target unit. Time sums use the same readability principle for explicit time units. Results of at least one hour display in hours; results below one hour but at least one minute display in minutes; smaller results display in seconds. Sexagesimal expressions keep their dedicated sexagesimal display behavior. For units that support SI prefixes, SpeedCrunch also uses a best-fit engineering prefix when the unprefixed unit would make the displayed number unnecessarily large or small. The chosen prefix aims to keep the numeric part in a readable range, typically from ``1`` up to but not including ``1000``: * ``1[ps]`` displays as ``1 ps`` * ``0.0001[s] + 0.89999[ms] + 1[ns] + 1[ps]`` displays as ``999.991001 µs`` * ``0.0001[s] + 0.899999[ms] + 1[ns] + 1[ps]`` displays as ``1.000000001 ms`` * ``0.0001[m] + 0.899999[mm] + 1[nm] + 1[pm]`` displays as ``1.000000001 mm`` * ``0.1[m]`` displays as ``100 mm``, not ``1 dm`` * ``0.01[m]`` displays as ``10 mm``, not ``1 cm`` * ``0.1[g]`` displays as ``100 mg`` * ``0.1[L]`` displays as ``100 mL`` * ``0.1[s]`` displays as ``100 ms`` * ``0.1[Pa]`` displays as ``100 mPa`` This prefix selection is not limited to time units. It applies to supported SI-prefixable units across dimensions, while still respecting special display rules such as hours/minutes/seconds for ordinary time sums and explicit conversion targets requested with ``->`` or ``in``. The small SI prefixes ``d``, ``c``, ``da`` and ``h`` are accepted for input where supported, but SpeedCrunch does not choose them automatically for result display. In scientific notation mode, SpeedCrunch keeps the power of ten in the numeric part and displays a single SI-prefixable unit with its unprefixed base symbol: * ``0.0000000001234234235234[m]`` displays as ``1.234234235234 × 10â�»Â¹â�° m``, not ``1.234234235234 × 10² pm`` Scientific notation displayed with a multiplication sign and superscript exponent can be reused in unit expressions. For example, ``1 × 10â�»Â¹Â²[s]`` is interpreted like ``1e-12[s]`` and displays as ``1 ps``. Composed Units -------------- For products and quotients, SpeedCrunch keeps authored composite structure where possible, unless a clear canonical derived target is recognized. Examples that canonicalize: * ``V*A -> W`` * ``F*V -> C`` * ``V*s -> Wb`` * ``T*m^2 -> Wb`` * ``Pa*m^2 -> N`` * ``J/s -> W`` Examples that preserve composite intent: * ``J*Pa`` remains a composed derived expression, because there is no single broadly expected named SI derived unit for this product and preserving the authored structure is more readable than base expansion. * ``N*W`` remains a composed derived expression for the same reason: no common canonical named unit is generally expected by users for this product. * ``W*h`` remains in ``Wâ‹…h`` form because it is a common domain unit for energy usage; preserving ``h`` keeps the practical meaning users typically intend. * ``km/h`` displays as ``kph`` and ``mi/h`` displays as ``mph`` instead of being expanded to ``mâ‹…sâ�»Â¹``. Speed units are usually chosen for domain readability, so SpeedCrunch preserves common authored speed forms when they match a supported named unit. * ``nmi/h`` displays as ``knot`` for the same reason. Dividing energy by area or volume keeps the ``J/m²`` or ``J/m³`` form. For example, ``4[TJ/m^3]`` is expressed in joules per cubic metre, with a numeric value of ``4000000000000``. Prefixes and scaled area or volume units are included in the conversion. To keep a particular unit expression, use an explicit target such as ``4[TJ/m^3] in [TJ/m^3]``. Preserved display forms are still normal units. Use explicit conversion when you want another expression: * ``[km/h] -> [m/s]`` * ``[mph] -> [km/h]`` Conversions ----------- Use explicit conversion to request a specific target unit expression: * ``[N*m] -> [J]`` * ``[J/s] -> [W]`` * ``[V] -> [J/C]`` * ``10[m] in [cm]`` * ``10[m] -- [cm]`` SpeedCrunch supports three equivalent conversion operators: ``->``, ``in`` (keyword alias), and ``--`` (shortcut alias). If no explicit conversion target is requested, SpeedCrunch applies the canonicalization/display policy above. Built-in Units Table -------------------- .. include:: units_table.rst heldercorreia-speedcrunch-e7ca37f/doc/src/reference/units_table.rst000066400000000000000000000270441526573132500257010ustar00rootroot00000000000000Built-in Units by Quantity ~~~~~~~~~~~~~~~~~~~~~~~~~~ Column meanings: * ``Canonical name``: long built-in unit name. * ``Symbol``: primary unit symbol. * ``Symbol aliases``: accepted alternate symbols/aliases. Absorbed Dose ^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``gray`` - ``Gy`` - ``—`` Activity Referred To A Radionuclide ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``becquerel`` - ``Bq`` - ``—`` Amount Of Heat ^^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``british_thermal_unit`` - ``Btu`` - ``—`` * - ``calorie`` - ``cal`` - ``—`` * - ``joule`` - ``J`` - ``—`` * - ``kilowatt_hour`` - ``kWh`` - ``—`` * - ``quad`` - ``quad`` - ``—`` Amount Of Substance ^^^^^^^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``mole`` - ``mol`` - ``—`` Area ^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``acre`` - ``ac`` - ``—`` * - ``hectare`` - ``ha`` - ``—`` * - ``square_foot`` - ``ft²`` - ``—`` * - ``square_inch`` - ``in²`` - ``—`` * - ``square_kilometre`` - ``km²`` - ``—`` * - ``square_metre`` - ``m²`` - ``—`` * - ``square_mile`` - ``mi²`` - ``—`` * - ``square_millimetre`` - ``mm²`` - ``—`` * - ``square_yard`` - ``yd²`` - ``—`` Capacitance ^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``farad`` - ``F`` - ``—`` Catalytic Activity ^^^^^^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``katal`` - ``kat`` - ``—`` Dose Equivalent ^^^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``sievert`` - ``Sv`` - ``—`` Electric ^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``ampere`` - ``A`` - ``—`` * - ``coulomb`` - ``C`` - ``—`` * - ``ohm`` - ``Ω`` - ``—`` * - ``siemens`` - ``S`` - ``—`` * - ``volt`` - ``V`` - ``—`` Energy ^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``electronvolt`` - ``eV`` - ``—`` * - ``hartree_energy_unit`` - ``Eh`` - ``—`` * - ``joule`` - ``J`` - ``—`` * - ``kilowatt_hour`` - ``kWh`` - ``—`` Force ^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``newton`` - ``N`` - ``—`` Frequency ^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``hertz`` - ``Hz`` - ``—`` * - ``revolution_per_minute`` - ``rpm`` - ``—`` Illuminance ^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``lux`` - ``lx`` - ``—`` Inductance ^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``henry`` - ``H`` - ``—`` Information ^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``bit`` - ``b`` - ``—`` * - ``byte`` - ``B`` - ``—`` * - ``hartley`` - ``Hart`` - ``—`` * - ``nat`` - ``nat`` - ``—`` Kerma ^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``gray`` - ``Gy`` - ``—`` Length ^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``angstrom`` - ``Ã…`` - ``—`` * - ``astronomical_unit`` - ``au`` - ``—`` * - ``fathom`` - ``fathom`` - ``—`` * - ``foot`` - ``ft`` - ``—`` * - ``furlong`` - ``fur`` - ``—`` * - ``inch`` - ``Inch`` - ``—`` * - ``lightminute`` - ``lmin`` - ``—`` * - ``lightsecond`` - ``ls`` - ``—`` * - ``lightyear`` - ``ly`` - ``—`` * - ``metre`` - ``m`` - ``—`` * - ``mile`` - ``mi`` - ``—`` * - ``nautical_mile`` - ``nmi`` - ``—`` * - ``parsec`` - ``pc`` - ``—`` * - ``rod`` - ``rd`` - ``—`` * - ``yard`` - ``yd`` - ``—`` Luminous Flux ^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``lumen`` - ``lm`` - ``—`` Luminous Intensity ^^^^^^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``candela`` - ``cd`` - ``—`` Magnetic Flux ^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``weber`` - ``Wb`` - ``—`` Magnetic Flux Density ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``tesla`` - ``T`` - ``—`` Mass ^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``atomic_mass_unit`` - ``u`` - ``—`` * - ``carat`` - ``ct`` - ``—`` * - ``dalton`` - ``Da`` - ``—`` * - ``grain`` - ``gr`` - ``—`` * - ``gram`` - ``g`` - ``—`` * - ``karat`` - ``Kt`` - ``—`` * - ``kilogram`` - ``kg`` - ``—`` * - ``long_ton`` - ``long_ton`` - ``—`` * - ``ounce`` - ``oz`` - ``—`` * - ``pound`` - ``lb`` - ``—`` * - ``short_ton`` - ``tn`` - ``—`` * - ``stone`` - ``st`` - ``—`` * - ``tonne`` - ``t`` - ``—`` Plane Angle ^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``arcminute`` - ``′`` - ``arcmin`` * - ``arcsecond`` - ``″`` - ``arcsec`` * - ``degree`` - ``°`` - ``deg, Ëš`` * - ``gradian`` - ``gon`` - ``—`` * - ``microarcsecond`` - ``µas`` - ``uas`` * - ``milliarcsecond`` - ``mas`` - ``—`` * - ``radian`` - ``rad`` - ``—`` * - ``revolution`` - ``rev`` - ``—`` * - ``turn`` - ``tr`` - ``pla`` Power ^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``horsepower`` - ``hp`` - ``—`` * - ``watt`` - ``W`` - ``—`` Pressure ^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``atmosphere`` - ``atm`` - ``—`` * - ``bar`` - ``bar`` - ``—`` * - ``millimetre_of_mercury`` - ``mmHg`` - ``—`` * - ``pascal`` - ``Pa`` - ``—`` * - ``pounds_per_sqinch`` - ``psi`` - ``—`` * - ``torr`` - ``Torr`` - ``—`` Radiant Flux ^^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``watt`` - ``W`` - ``—`` Solid Angle ^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``steradian`` - ``sr`` - ``—`` Speed ^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``kilometre_per_hour`` - ``kph`` - ``—`` * - ``knot`` - ``kn`` - ``—`` * - ``mile_per_hour`` - ``mph`` - ``—`` Stress ^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``pascal`` - ``Pa`` - ``—`` Temperature ^^^^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``degree_celsius`` - ``°C`` - ``ºC, oC, degC, Cel, ËšC`` * - ``degree_fahrenheit`` - ``°F`` - ``ºF, oF, degF, Fah, ËšF`` * - ``kelvin`` - ``K`` - ``—`` Time ^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``day`` - ``d`` - ``—`` * - ``hour`` - ``h`` - ``—`` * - ``minute`` - ``min`` - ``—`` * - ``second`` - ``s`` - ``—`` * - ``week`` - ``wk`` - ``—`` * - ``century_julian`` - ``cy_jul`` - ``—`` * - ``year_julian`` - ``a_jul`` - ``—`` * - ``year_sidereal`` - ``a_sid`` - ``—`` * - ``year_tropical`` - ``a_trop`` - ``—`` Velocity ^^^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``kilometre_per_hour`` - ``kph`` - ``—`` * - ``knot`` - ``kn`` - ``—`` * - ``mile_per_hour`` - ``mph`` - ``—`` Volume ^^^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``barrel_beer_us`` - ``bbl_beer`` - ``—`` * - ``barrel_oil`` - ``bbl_oil`` - ``—`` * - ``cubic_centimetre`` - ``cm³`` - ``cc`` * - ``cubic_decimetre`` - ``dm³`` - ``—`` * - ``cubic_foot`` - ``ft³`` - ``—`` * - ``cubic_inch`` - ``in³`` - ``—`` * - ``cubic_kilometre`` - ``km³`` - ``—`` * - ``cubic_metre`` - ``m³`` - ``—`` * - ``cubic_mile`` - ``mi³`` - ``—`` * - ``cubic_millimetre`` - ``mm³`` - ``—`` * - ``cubic_yard`` - ``yd³`` - ``—`` * - ``cup`` - ``cup`` - ``—`` * - ``cup_imp`` - ``cup_imp`` - ``—`` * - ``cup_jp`` - ``cup_jp`` - ``—`` * - ``cup_us`` - ``cup_us`` - ``—`` * - ``dessert_spoon`` - ``dsp`` - ``—`` * - ``fluid_dram_imp`` - ``fldr_imp`` - ``—`` * - ``fluid_dram_us`` - ``fldr_us`` - ``—`` * - ``fluid_ounce_imp`` - ``floz_imp`` - ``—`` * - ``fluid_ounce_us`` - ``floz_us`` - ``—`` * - ``gallon_imp`` - ``gal_imp`` - ``—`` * - ``gallon_us`` - ``gal_us`` - ``—`` * - ``gill_imp`` - ``gill_imp`` - ``—`` * - ``gill_us`` - ``gill_us`` - ``—`` * - ``litre`` - ``L`` - ``l`` * - ``pint_imp`` - ``pt_imp`` - ``—`` * - ``pint_us`` - ``pt_us`` - ``—`` * - ``quart_imp`` - ``qt_imp`` - ``—`` * - ``quart_us`` - ``qt_us`` - ``—`` * - ``tablespoon`` - ``tbsp`` - ``—`` * - ``tablespoon_au`` - ``tbsp_au`` - ``—`` * - ``tablespoon_imp`` - ``tbsp_imp`` - ``—`` * - ``tablespoon_us`` - ``tbsp_us`` - ``—`` * - ``teaspoon`` - ``tsp`` - ``—`` * - ``teaspoon_imp`` - ``tsp_imp`` - ``—`` * - ``teaspoon_us`` - ``tsp_us`` - ``—`` Work ^^^^ .. list-table:: :header-rows: 1 * - Canonical name - Symbol - Symbol aliases * - ``joule`` - ``J`` - ``—`` * - ``kilowatt_hour`` - ``kWh`` - ``—`` heldercorreia-speedcrunch-e7ca37f/doc/src/robots.txt000066400000000000000000000001111526573132500227330ustar00rootroot00000000000000User-agent: * Allow: / Sitemap: https://www.speedcrunch.org/sitemap.xml heldercorreia-speedcrunch-e7ca37f/doc/src/screen1.png000066400000000000000000011237571526573132500227570ustar00rootroot00000000000000‰PNG  IHDRR /“+Í@iCCPicc(‘}�¿JAÄ'‰†"– WY�Ac,c„(¦8£‚Ú]6g"$qÝœˆ V>€/�ÎÒP+ÓÛˆ"‚½­ ëlNMüƒ ócîÛ»¹zú])Ëa•ª¯r™Ykm}ÊBEAG·¹¼âââôôôÿÿÿ{~ƒýýýõ£Ÿí_Xé80øÝ‹ãÄ…òÁ0ð¹ºÍÒ—¬€UºV9®:ìQJž´„íaZÌÒÕ³ÆÊœ¡¥��”þþþ¨«²ª­³nmsYYZlr~œž¡ÈÌÔjmsèéìÖÚä‹�”lpw€†”]afÁÇÖafrYZeEJU7:>I=BLBFQ(*/ADN26@.3<)/8JLUSSS9=Fv|‰‰Žœ\bm ¦´UZeñõþ|��Ýá봺ȑ—¤diu59>•›ªY^jÎÕåINY›¡®sy…QVbLQ[‹‘ž¥¬ºfly…‹™inzºÁÎ�£²µ»Ëèìõ�”¡¢©¶ÈÎÞ¹ÂÆ©®¾ƒˆ–­´Âqwƒ’™¦V\j™ž¬SU\y‹"'-–4£3£‘Žržz½Îë¬Z�TEÛ^e¿e¿Ïv¶³�ílg;ÛÙÎv¶³�ílÝîãW¥ù”‡CWù>^el3nU­rü_>ZUeÛ^Åv¶³�ílg;ÛÙÎv¶³�íl/y»Í¿\²Vest<{¹ý¹ÊùH•}KÞ¤Í÷U½ñêÿUæ;­nz·°�ílg;ÛÙÎv¶³�ílg;Û n7ýÊë_>~æõ7·ßÁâ©´3A½AÆ›¸*ÿƒI•ù&V­²}ìÛórí†ílg;ÛÙÎv¶³�ílg;ÛÙ^Úvÿòú™Íß܉åU¤‹/jf·ã꛿|äXåøÅï]€Åb•ç†ËÏ\þf¥“¯2ÒÆÑé5i•Ÿo¤-k^åÒe¨hwùF¼0“¦íÑç*bÍ+À°óõΠ¤ð4þ °ÒýÚL_& ‘ä�vħ±i(Ö­WºNWåk{DõéUÆìê¾V@ V]µR#Õ¬‘ó×j3ý™ð4@±V½²ÖÕR/™ 5,œVW­ˆè´!Õ åÔ+$Rmü€°ÐZ]õ€ûtyĨ«ýïU³�ílg;ÛÙÎv¶³�ílg;Ûç³}¹­ºêAQ/µ:WWÛïŠ{Õæ{.ïT›·«ÅÿÕ¿Uƿꡪü}¶³�ílg;ÛÙÎv¶³�íl_ÙÛ�þäô+ÿ²ûÙ¢ú´ª~PgQ/\Ê·zsªÍ7EÝ®2ÞkõÖšTÙïVYÿ„Àv¶³�ílg;ÛÙÎv¶³�íl/¸ÝǯòþUeÛ^eßnú›r¹s«å¥X4+,]Ûþ{IUÁ÷Ê[$ÜŠ�.D°zůD]ú[RãºWc>TcÜÿ«©Q7kÌí¶ûî¿lg;ÛÙÎv¶³�ílg;ÛÙÎöÐíN¿Ê‹YMˆ­)ßÅuÕƒ§Ó« Z´þ¬^½fÍšµ:_|V4R…%겸zµøÂSª0©.dÓ5«×¬ýúß|ãßüÛo}ëï¯óð·¿ýÈúG`…²þ‘oûaá‡R¿õ­¿ýæ7¾ñ7__»fu¯^!F]]³ækßøæ·þîÛ|Z ßþ»o}ó_[S³¬ºª P¯þÚ7¾õ>�ï|ë_[]^üû�pê°IÔÕ«¿þÍ¿ã³ÅòwßüúêêBkjU~Îw°R×| ¡€R¥úk5v•²°œï5ßø(•o}cMu¸TW´O‡%}í›Ïû¥ó÷ßüZux‰²ª žG]’ôý·¬�óbý߆$W²P‡õ×Iú€yó­¯×<ˆ‹iUaÔ°ÌN]©9ßÁR]�QÀÒ8uåiuhÖwõ×þ–÷†¿ ­QVy©ß¡‰ìÕk¾Ie2X ÖsMõ•ûöbVƒÕ³`Áøûo¬/QVI�êªð õטH È· ,O]UABîÔk¾É» É7×T=%ʪ ©¿þw¼Ù°�üÝ׫„Õ©« ×&ã½€…¥@…²ªÊêð¬ïêà õcßýî?þ“Î?~÷»�¾X�}ïñþ¾Î??þ½({ÿ`ÃÿEç‡~ð4€¦®.¦®ªð¼ïêêšoø¾øõßýÑ?ýÓ�þQGüýn�E¶ÖOØ´D¿ñ½B{oÔ}ú‡ýïFðxðøFM�iÈ¥. Ôk|Ë}û_•O+~ôOÿúí° õ½6…ZIõ?/lïM?4|Ú°ênâ£ð ñ­5ÕÕÕ•\¢¬À<êjÁ׿ãóÊ¿û#›PK©þÑwCŒÚ.ÔJªCœúÇÿâ0j©þ1Ÿ5€ŒïˆÌïR]ÁYßòÅùæ}÷Ÿ\F-Õß�lÔ¡Nýc—PK©ŽîÔë`îõO~úÓŸæ³Í¶M>º^oóßè2ߨ)¦®p£®^íSïûÛ?òµˆS;²Q‡8õ&£Ö�:Rî÷ú'~úäÏ^ûïOÍómýÅÏþó§ÕÍ͢ş?ùï›çûQyD4C�°øæj™]¦Ôe©® ›I­Œºz­w*õúõ1jÝ©ÿÕ·ŽØúö1jÝ©ÿÙïú+õ#Ô(Û,TXòÓùU4³”zý/Íþ0J ° |km¥.ïÔïÐÚdê•Uíï<¯ú»ÿô�¾ø§~Ïרu§ö Soô5jÝ©7|3žúyž_Í+WÛTêõ¿²5ùïóKÿF©œüÝ× ñ¬®È e…Ó¾««¿îIç~ìG?òWêýÈÇ:û~�RßoïRÈh{RŠïÃOlç•ûm*õ¿+=ÿ÷_>#þþ¥X@¾ýuÓ¨«+P©«ª ©kþÆó¢ƒ‚Ôþaê  µ˜úÿdÔÿòƒïÅf¡½�è7~ö‘úýè£ë7mÚôÈ£�mzøá§ò:¾ùáŸüÛÃO[w××=ñïOl²6¯ꉇ7[J-[|Rìü´ W‹‡ô6×?úÈÃO<ýèÓ²y±QÝP‡[¿éßžxj½ýhO=mSêÇôÍ›£ãèüMM!¥®l£ö+ø]œR?¬Ô�{÷Þ¬Ô ¼OYaàõ¿üå/u¥Þ¤?ðËM2vý £ºÙÓF&÷O «}BÝ57?,£ÑµOJ-ƒÔjÓzq³îÑGkÅ#¿’Qð‡EL\>KÝ�‡“þó'U1³GžTÍ×®7•úy€g¡ã%¿ ͧ.Ó@uaŸ¿½Jý�? Rêý£÷ ýsÞ½B�·b³;ß[8î“Ï(«}FU{Òª_ö3S†ž—ÜMæDìg”R?iJó£J¯ÿ])uíÏ•Ú<Ü“BÙŸ¶Žöä#J©a<ò‹§é9�~cµM?+¬FYpq2»Rÿ­ç5©ÿñÿÉ{…¾lÔß÷îý/ÁFý/ÞŠÇTDø‰Í�Ù”Ú¢Vt½�ág~*gF –õÌjÿýIC¹Ÿ~Æþ„§­È´�Zs³¿R‹–ÌúàÊߟ”ÿþT)µ}3ÀŠço£(uY.N]ɨ«×TŒRÅÄt¶<¼ÞRêg6=öôOÅ�ÍÊ}Ÿ4çH¯ôgÂvŸxôÑŸýT9±ŒYÿdýú‡ ¥~ÚœœíVêŸnZÿôz¥þåúÇž2Œý)#mÜ8Ú#*üg2ý§ô€Gÿv�ͨ+¨DYØŠÔÕ¥þVÅ(µTcƒ:S©ÅTh/~øÑG·˜™á?‘÷7›“¯×«BÉ)ŸPJm¸°G©å>�ú+µØ]œÆ/ÕAd‘ðŸüâ¿xJ)µô©åô€G¿µÆ¥ TWÒLj‡QW¯­¥~ôg›~jån?¬÷™GM…þw57úÉ-:b‡{´NF´Íû�I]–Æý´RêGŒ*ßn¥6rÁý”ºVÜín± ¼âól6±š€RêµN­˜ÉÔAQêj·Rÿ�ç5—iy2ÉúMÿ¶EU³9®)¹ö©Òº?ḿþÑgÌ<ïŸ=“ŸKý”W©7+õ/MgÖ�öŒ3mÜZ—šª·¶ÆaÔÕ2›:8ñ»º R—é"Zy­þ© /o²2¬V¶+$÷™'ŸÞ|ò'jîô“ò¾þèz¹µÔåÇÔóös5×Z²ùá‡Þ„R,¨RWG SWdm2�¯ÍW©¿¬Ôßóîýƒ`¥þA�·bS]]�JÓ^¯&QoRùÜ�ªYÒ?Q‰ß6É}Êt`ƒ-f)n3ãû—B~�ÉÔ¿’¹ân¥Þ"nü›¿R?iƸ[¿~ýc(5€G©¿æ2ê Éý®Š8•ºÆG©ûQ@æ÷�~ô˜÷ =öý§þþ÷ýöÎû~¬À[ñSki£T÷&5eZ—Øg”ÝþÔŒ:¯ß´i“ªÁ]/�ù‘M›Q3®…Aÿì—†R˚ݿ´üùçÎ(õS†±ÿìWþJ-޶ET2û¥|*J àQꚨaêªJ˜Ií¢¦ækßñ¾è 0µ_�:8Lí¤~ôÑ�aêÙXè­�ÖûÓG[ÿ”\hú1c¡èêá'�bÛR‚ŸzìÑG~¥[øñ–õ�>ö„ÊWËT×=õSc­Gû•Z’ëõЯ~æPjËÞòÔæŸþÜ_©es?yzýêlPjßñ*uuÙ;uUPÞ·»6™Pê¿÷¾èõÿê¦þÑ¿®÷»DëÿÙש¿ÿÏþ{ÿÐשÿå‡ë ½ëëíÕÆž0Vµ2‘+AË•«Ÿ‘†ýäcFôúçO>c”!{¬Öþ‘C¾ÙþÀ3B¥mJý³gÅÎNý/?Žòf<öï†ÿj“©¶¿\/#Ó?5–—~ìßäÏüĈyoV+nÕÂþˆZ±zý“rQ-iÙf“?U÷kíÎdFù/ž ¨øm�Ï“OüÌ0iYüi”ÀRêššhó©W•GœZžˆ¿QW¹…:H©ý®;Ný£}7ø*yœ:Ĩ…S»¤ú_¢µ`ý¦‡ë1 ™ŽûØ#�Ø’Æ{zÓf{ùúG6=ò˜ýîÓ�¹[¬{øáMiçO;žì#ù�8�.¥®vÅ©¦S—{½o¿ uÍ×öáßþW{ úGÿô¯ß»Lßûg»Të·¿¶÷&ç|êùᦒޛM®E² ¬xXE©k¢–(+ç‰ÔU^¡®©ù› U^ÿÝý“²jñ÷»b±ë¿÷}Sªõß+´÷Æš‘jýïÆã¼(5@Yóí¿QF)õ»l2¿#Tû®©) Ô�>úØw¿û�ÿ¤ó�ßýîc…¯Ôcß{\Øô÷ÿùñïEÙût›Ö}zÃ+õ½A©*A©+(J´‚–_ÖwMÍê¿y¤bß›G~úÓŸ>ÌG lµíoV×ÔS¡¬2fR×䕚êZ°(¬/N©Ë@ª«"ͤ6ó¾Wÿ ï1,–RGXœºLV¦Ž\š ¥€¥Pj÷BZþ1êª2 RW)õÿâ-€ÅáYQê(qêeSG+NVƒRÀR*u´u´Ê2ï;ȨQjX ¥®ˆÙÔÅÔ&C©`‰”:ÊlêªeêUE5J K£Ô‘¤zUùIu5J Ë ÔÅ…©W-³TÎûv5J ‹§ÔEF©ËÛ§]õ¾‰RÀ"*µ=L]]SîE¿‹›IM”–H©k¢Ôü®*7£¶;uM5J ˡԅÒÒµ¶Ìò¾ƒWÐB©`q•zõêJ™L]TÞ÷j”S©×„…©Ël­ªbgR¯^ó¿XÜQêrVêªâƒÔ(5,šR¯)2ó{Õ2©WœJíUêÿˆ,,ñøÿK½ `ézÿ}(‰ÿð(u‡© W's5J (5J (5Àb+õê¢ÖÑ*¯Šß¾J½š(5 Ô(5 ÔK­Ô©RW•�SW‡N¥F©¥@©¥XÊ(uMÁ0uÅT'C©¥@©¥Xt¥¶Iu¹f~W­ŠnÔæ‹B©¥@©¥Xt¥.¢@Y9-K¶(5J KªÔ �ñD2•ZI—"•J&â� Ea©•zö6ú Ô¤Ô&S—gâ7J Ë¥Ôÿ»1‘Z¹W$•hüß Ga©”ze÷6ú Ôe«Ô«ý'SWUûå}W-O�zU±Aj”–D©\•±3X¥¦·Ñß`‰”:%)ð O„}V¢R×Ô”ëdꢧR£Ô°JÍŸA>,•RÓÛèo°$J�ÚšlJ§››Óé¦äÖe޲À SêÕe>™ºàªÔ5…•zÛ¶ÿ”lÛ|I¢ì(už&®ˆIcRX\¥¦·Ñß`I”:O7X¤ãI¿O`”}V°R—ãdêRê}»”ÚpeØ„:Â>€Rçùߌ"ì#,¦xÂ"*5½�þK¢Ô©ŒM–¥0g+G©ÿÁO©« 8õªrÉüvuµŸRÿÃڲǗ£ì³ ´lo]ö`A”š–N+�N[™"Ö>�ž}J5÷hZVÿ“ÝÌ`*J©+d­’¦RJ½Í”ã¼&{Òº·)õ6�÷ÖþJRr:JˆR×vuÕîÞÜÞ^�RT€R³B®/ F¦°ðJMo£¿Á’(u\Ùr¬·§IuSOoLùrÜLë6öIµl±hI¹ö)yÔ¬?G(u,ÛG÷†JRêBËhU—mâwÁ%´L¥Î‡›ýn)‚#×žŽžs<�õ½·Ío£Gˆ³¾MçžmßãÛz¥('¥&la3Xp¥¦·Ñß`I”z« @§{;û÷J§nÚÛßÙkܾùYñèæ]ííϵ·?+¾?ÚÛ{Ä.‡ÛXBÜb<·×Ó´9{ÄѺãŽl¡õÙö~�X>¥&l ûÀ+5½�þK£Ô†+•ÞŸNïï7ÃÕâAõ‘k²”úàÞm’½;·4:öñ5;Ã϶�ÛçúT0IÜn? ïüœí®Û‹mn?âjÛžtx]ûsº~?ÝÃw”�R¯]SÒÊÔelÔ56¥^+•Ú'íyè?ƒ•ú?•ºõ¹öÁúXý`ûs­²Ÿ·¬Ïeõ¯ŠöážØݦ;Ûb½ëÚ·ø+õf±¹«®ý){Óm}}=½uíuYwëÎC‰t£>Ä'`•º‘+D#cSXX¥¦·Ñß`I”:e%“N][k7ꆴœ(mî£+õ®mêæ¶]–R§S•º}g®oûsíº<Çv´¯Û’ëÛ²NN|4¿¥R{†Úù'mÿöÈÊU© …©—\ª}–¥®.\�Ì¥Ô¾mÄ~m‚•ú¿äœ‘'b±�í›ÅEnsûNÙÏ•âêJ-Óýíωo„‘öƒ¾J�miÏ­m_—µ5­‘_?ŽÖ�‡Ò[Ð�ºŸ0Àr*5™¨�P0 X©émô7Xb¥nhÚßßyèPgÿ~˨KRjkÔìVj9jÞ-îl{®]®u³gÝ&·Rûµå“ÚÚÛ…e÷´ìç;ÊD©}œºÜª“•Pžl��Rÿ§Û¨KRjų"Må¨|ìh{§ìç-†Rkò{A~cÄvÉÞ稜äzÚÛûlM?»yóæuííÚhÌÕºóPOµï|–Õú–Y©S Ö` S8êûYÆW(ÅØV©+»·eéoP1Jm[p:]{¨³óPmÚ¶ì´Rêæ0¥nNŒšÝJ-Wªîƒæz[|É¥Ôî¡vþI±çÚŸ:ÂH(K¥Ž¥^úÄï’V¥.A©íIßAJÝrDP+:»’è–öͲŸï�å¿*t¥îTßJ�Ý~ài1oÄ¡Ôâ—¸ì~­}ó6WëÎC‰IÛ…Ú€ÅUêàÉ�GjµÝí8t¨%¸±Öc¢ÀÊÈö"ÃííµEì~ø�˜“öKù¯qNGóQƒT©+¸·m;|hsûæ'zéo°B•Ú5»•Zè="ìØFù)µ{¨�R¬CL±®Û—cPe§Ô«£Î¥^UJí?—ºÆfÔ%$~GQj«ó>Û®þÙ+|+N©suúÁ¦ÿåUêX¬§½½ËÕºóPR©7ó%°œJ<¹ss{ûλ»÷í}Îø ÿ©â–ºßTÜ Xþ’§)2¹CúuÁ&w‚*uåö¶l§qÌ!ú¬ÌÄïÀ¹ÔûmJ½)H©}‡ÚJ©c­»õßþ4!&(;¥®)ÛÌï–¥^SBy2»RÛ ør8`ü'r¨ý¿ *u—¸³3¯Ô½ííb2uŸŸRÇž‰-ŽÖ�‡zª}¸ç9uX&¥Ž‡Å´žË"Ž´‡ ò·ˆ§Ç¶UK]Ì9Ô÷ï+bïì:1ç,§fžÅº6Ïg„ßg,YÒz($Ôgp ©Ô•ÛÛè?Ô±C—ù=ô7¨(¥^Œòd¶Á°ÝŽ»‚¿}‡ÚG¬¨vßÐÓíuŒJ \”zME–üް,õÚ"ÑòUêàE´vµ?%6fŸjßU@©ŸU߃y¥Þ­J}wø)u«Ìêv´î<”hA8ã °|J�ä«R+1ÕïƒùÛžm_×aÆ�·/Þïo.&Ê!>'G&ëÚÛ;KWê‘öM⛪çYùmõ’`A•ºb{[½ÞÙ„Ô>×>Lƒ PêÅ\DË1¶Ûqv�Jêè­;¤žÓf)µïP[>©¯«UýTö£(¥^]l}²ò�Jí¨NæTjK’mN¢ÔV ;X©»ÖµïÈÅrÛ×uPêÁöMõ²¸¥Ô[Ú×é_]O{•:×»Yf·8ZwJ¶°³Ý˜_Ë¡ÔÉÐA¾51l´=d�ßÓ®¾(ôŽÿœµ¢ÞhW�ík§¯Ë6Ç#[ï]€3×ÚÕçü–jõ„³¶Ëï£hâºö§�ô”®Ôm›ÛŸÊÿ’dp ©ÔÛÛör «q{ý *@©“F¬¹ÇPi©Ö=F\Úè‰IK©;î’ì´”:¨ÔŽÁ°#à<Òþœ~¯þ9,ê3r:¤Rûµå“Ž´¯«Õûé!’6¡ £Ô‘ÃÔ«ª–=J]©mùÛ~·li_¥Ž*µˆ1¯ÓÖµ«ßÖ”ºWü7ÿÙöÍy¥î{®½}Ófý‡R·?'V¸oºÖÓºãŽ*pÖÙþóG–M©S!ƒ|½ÿʸs¬}�äׯ[gŒô·¬[gUëÊ�ÿ÷¶È~Ÿ=ú´ø8¦Æé¹ƒÏŠÂ FÆhíSzSÏ�?Ì[§~˜ï: K+¨˜ÛÁuÏféÏ_×i¼ïè³9;�÷ÅÖh‹ÍC©c£ú7™>Â+ç°•Á),¤RWlo;¸Ù�÷�íí{éoPJ½UÙsº× N §î5Üj|⌻-�6ZœûøŒšƒa‡Rçž‹Þ轫O¹tûÓ; ¥öj«' ë­unn_×˨ÊN©Ë6ñÛ/ï»*,íÛ¡ÔÛþ3@˜m¿Moó.¢å¤¶fxN}à9ý?¹ªàÏfC©·8”z§ZBo‹þý°nÇ>[ÅïÖaý bеˆ–๺=ÞÖwT 9­}3«”£Rz¶}Ĉté·ž#ùͲ\iLÌ {Îê¸ÙçÚ7; %õµŒž�*͸÷_2øµÎøŽ6°»}�x¬Þ¬·´S=ùi£’í»!»®ÝÎÑØa°+½ZR«0-t2*«úÀ’)uY÷6‹'ìfAƒòUêT\ÕíŽõöùÝM=½1Uã;nôDsŸTË‹–”s¿Q³}0¼Ù1-ºOÔ8xnDu’®ÿZ'VŠÝ¬Êú µ ?¨wÉuOu1(�²QꢿËA©#ü6•Ú¾j–·Bû)u�K˜m�hµmžs­ÿûêh=ò¡` ”:6ÈßÕ¾NýZÖÑÞþ+9ÈßifÉ­³(> �Ç÷Ù‚\{ÚÛŸêhíxJå½moßÑ—­­“õ†sºÔfG··ËœU5È}¶}ÝîÚúíúXd‹a#µmG4{)¤ìöíú±wlß®·¶{ûvµàм”:¶·ÝÌfeˆK¢ÔÝÛd�{ÎQÒ˜þe«Ô±¤Š67§­Be鴲崕ÓmíÓháÙ'â`8¿iÔ6BÎm‹4Ôncd å¥Sûå}W•ç\jÿ(µU ,Ĩ#íI©ÛÖ©HV¬®]‹ÉAþ¨‘uº¥ÝHhQãQ|{ÝðŽ^5,èko×dIMÖ?ݤbm}ê~)SæäÏôÛëêræ ÿ c4ßúœ,Тòe¸®g]û ý„jÛŸ¶þ�Í_©Å€*ÿ&§°dJ]î½M(Á�|v:ý Ê[©cÛÒÔvš3ù�\”}V®R׬.ÏÌïyßõ¾óJíïË®”î(ûDQêX§Ÿ·¶·ïSƒ|}¸¿YEÊ6;~cQ™¢Oïѳ^Óze”mSûÓùàT¯£Ê¿ä›U–¶Ë{ú�Ø\ì)çAT¥¤�*£uÞJ­ÛÁ³ϵdˆå¡ÔåÞÛ”Ž?Aƒ QêT“¯/77ÙRº£ì°r•:j”z‰•Ú7H]¶*õg”Ú×—=¶¼ £€RêÚvYXe‡X3W ò·Èxn�}~¥ŒA5’Úµ6™{ÚrDpXÈ�>’oîàc†È¯uxê—­öA~VÎ7tÉ\Ô~smχå²#rõ‘NÛ*<óPêm�íO·Æj×/ÿË–V©Ë¼·ÉCÈÒß B”:¶ÕÏ—››uÇ¢ì°r•:zæ÷Ò*õª"•Ú¥öñe¿ÿr‘õ £Ô±Í"4'ƒKj�¯ßÞ-‡úÞ•ybõ»žko¯S«êšôëO‘†×Õm‘ãüÞu*ÀVo òõ¡ýaÃÚÅp¿ßL6=däï¯Õ…c Vü»»¶¶mÞJ}P­5 ŸÍv†øPJ]æ½-¶¯=¼`7ý ÊK©ý|¹9î²å(û Ôå¶0u±s©=Jíæ€ðó6BÔ° J½GŒæ··×›ƒ|}ä½Yd¢>åûœž§EÌKÔ+Ú‡ex­ö�Œ©©%iÛö ËAG1ƒüœ£±¹ÿ<”zÿ³j- ã›[âCy(uy÷¶Žvw©qú”·RÇR™´Ó–ÓOFw”}VšR{�ºüÑ*¼,µS©ua6Œy[ˆ,GÙPêBƒüÜsíÇb›D0Ìä×¶·wåÖ™Ãl5o³ê;�™¹¤6ê�=ÝnfœÆr-"”Ö˜Šêä×?+–àyÖü·~ÞJ˺þ2ćåVê²îmGÖµoî)ýë†þË Ô±X2nætÜ·Žw”}V¨RG]™º¬ÖЪ0j·R,•Rëí§÷«²ÁÆ _üÝҾΞz°}�9Öî!¶G�b“>Çú;»ÛÛ[Ì‚I›Ü“|RQE¥$Q‘øh{gþ¡ù-¢§°„J]νmÿsíÏö,öwŸXh¥Ž¥¶&›Òéæætº)¹5 üe€¥Ôå=—Ú¯>Y5J å¬Ô]íí϶?›µ ò�µo> ÖݱFÛíí‡TFLÏÓ¢´R›9çòÈæÍ-±Öáaµàíf1–ß=\'“G·Èus–õñäwÊMƒÆBC(5ÈÃþg�eZ5«”ÑÁ¬ž+Ö‰y‡¨:,þ_§�ø³Owž³ &ɘBÆÄüù}r:h[{{¥†U©Ëµ·=a«V6@”`¥)u¸T¯Zêe´ÂÖÐ ,ø�RÀ²(õâOö9c>¥5ÈßîUçúÕ0}³QG)+Ê#µ¯ëT­ú:±u³Z[wÛÑÍbˆÀXÖç9ùà^¹òÏfµ¾ÎAslÿ„(wlR+ï±?$†ü{Pjx ”º¬{[¿M©wÓߥX!JíWñ» –Ñ Íü®A© Œ”:�]r•7m½[~e oëéê±÷í©·mËÕ{ëåê»ÚÊï18…¥Qjzý Pj€²Qê5EVü^R§®*q -”ÊH©Ûžk?°R®ƒSX^¥^I½�þ(5@¹*uuMUü^µŠ(5T¶R·ˆLÒ_1ÄX|¥^Y½�þ(5@™)uY®¢Uê²Ô(5”�R?»¸“)âJ½B{ý Pj€²UêêðòdU«ÊÆ©=Qê5(5”›RÖ=ÑÂ`)”zeõ6ú Ôe¢Ô«W»0õª2œLM”ÊU©W Na9•šþ€R,ƒR¥®Zö(u”5´Pj@©âJM@©_©+.J6—z åÉ¥fˆ(5ý ¥X2¥^SÆJ]E”Pj†ø€Rý Pj€ Pj_§.¿¼ïðE´òJÝýÿXPâ òâJMƒ¯·@Iä*"J¾*µÍ©=F½öNð&ÀBÒЀR3Ä”šþ(5x”zM˜RW/³R{¥º:bâ7J ìÔ(5C|@©éo€R@`”zuÔ(uÕòæ}G\—¥”š!> Ôô7”`±”zm¥^^£.¾â÷j¿¥fˆ(5ý ¥Xº(uy'~—dÔD©¥fˆ(5ý ¥XŠ(uÑõɪ–7H]A©‰RJÍPjúJ °,J]]F‹h­*u-”Pj†ø€RÓßPj€%WêêJYD+¸à7J ‹¢Ô °$ÐÛ–®·@©J\ñ;¼>ÙZuUÔêd5$~J €RJ PþQêªå-ø)L�RJ €RJ °Jm“êe^D+|&uÈZ$~J €RJ °ÌJ½¼‹hUù–'‹T� ¥”¥€JQêL"™JQuÊ‹T*™È„)õš²WêBåÉXD Pj”*^©3Iì Ê•d¦”(uødêU˺.u5Qj(O¥n€PN©¹– ÙÛÊ!Ô©d"$°,¹‰¤È�HFWjŸúdUÕå\ž,L©*V©“É$ŸX¢(uS<<àiN76¦Ÿ/²Åt<ž&ÖD©ç‰Þ‘šŒ~ØÔdv*ÛÍp}WÿÂh {’ýEöù"šÖï<Ÿ.¤Wϧ­}lmÛnòC”z‘½E—–T‚�”' ñùÌ­Ô5å\ò»ºø(õÖ>E¨3ïãK£ÔéD¢Év·1£c�»3'Ý>X}[&£F¾â–…>o~!‘hfd(õ<›H¤�NšÔI»nÚû _ÿ´÷]ù¬Æ�o³Õ°>ïh_töÖÛ–�gÂÚnT‡Ït7»Ú¶Ýä ¥^ô5B å,Õ�êŠ(O}]j×"Z®Šßãcн(5”ƒR7'’öÑizB�6GÍ&žsZnSÏÌïf<7�L2ùPêyæ�$“Ư]B'ñf×M{ô¯³ïÆ3ÂH=Ôj5¬Ï;è»tÓtÃóÚî¶v?ÎÙÛ¶†/”z1cÔº®�ð eMÀ‡tJ½¼‹hUW_ž¬¥€rRêü°ÝfÇF,Hl»»3>c`c䫸n¥Ãh23¥ž×¯]yƒÜºu«Ñm7}Ðý\oßM'·nm Š$›­†õyg0YioCô¦�ŸëŒ¶»ÃD½»;ÿÊlmÛnòƒR/)Œ*Á©SE*u�¼ïªeUj¿(õêp¥Î$?ûq�‚(5,‘R7Ÿèc¼ž¾Û¨�À‚^ŸÑjpŸ÷Qöî|¿�дl»1ÿ=Ó$êÍù#4»ÚÎßä ¥^DSa5T Ÿß~lJ½ºŒ×¥®*-J½ÖSñÛTêlGG.³wÏ¡CG[­ŸÆz�þæÐOöXJ�ëØý›þ=û3j÷Ž­êÑÑŽŽ.>K(uTÒ¿mŠ7™Et›Óé´þïoU�ïD~°nŒhìqªtÞ¡»]æ-ÿm6v<áÑ�X¬‰±!¬@¥nÖ{ÛoíYÉé&[Iì´è~ÍúCiÏM±cS¾v:‹™z¹m›yæMWô‰özúnã¶mAÞk¶Üç½í7Ú•ºpÓ ¶ÝÚn´=þ¼y*¶¶m7ù‚A©-H�b„•ÀVo˜z>s©«–1ï;bÅï5AQêÖ±±}ýjfõ)µ¥ïÇc&ê§²ÿóuo �'ô}wËß#b?›ìᣀRGêN*^P1eýVó‹â¾(F{é¥üè¿ûå—õQìÄË/[Jm �_~¹[Ù�h#-vÓÿ}ùåfãi÷A_xé¥$cCXqJmõ6+YÙ¸oÌýÕ{^<-{£çæ‹Î'Æ_z餩¥ÙlÜuÓÕ�žiwSwßmhÌf·Öï^ôÊlÕïyÍÞ²š'D—_æñ 7Ý�îîn,Ðv&ߢíµXmÛoòƒR¤ÂÔn¥~È2êP¥®ªˆŠß^£Qj�ô mÎɰµ~ë?éŸ4•z�~Ïÿ9¬‹ö€2é±Þ¸rë^>I(uÄ1þÉ~Þ>:nÊf_bl+M©m½íEÙ9^È?7”Z=ô‚ïÍüNf³ætáD.—qÝtõA£gú`ö]]Hs9%¤Í±¼¢{à~žwg¥¾Í¥.ªé†F½í´ÏÞÆ�siûÚÕVÛŽ›|Á Ô‹¥)©¡BHy~þQêµ�‰ß5e²,u�¹ÔQ+~»”z /OÛ.Ø=6¶[ÄðSýJ©ûÆÆŠž�Ô7´ª'L¶Åã‡ÇÆvò9@©#¦¡ž|饗N¾QþÃÕ—^’�¼ ‚Ö/¼òJ,? =}zBýq'efNŸ>-¹±\.g·ÑxPlínœxY¿›ÏæL¿òÊ+”ä…¦ÔFokzAü}Q˜Ÿ¸2.ï¿$2•_”½ïä /4yn¾¤ßLŠÕÁþû•Wš‚•ÚÕ=Ó·ïJ!M©W£ï+使ó¼;Ë£ê=½[}_ßtÚø¦ñìý²h·ÛõUbµí¸É J½8$}—û(C¼V¿ÄïÕ~åɼR½ªl*~×”¥V ßY…nû�ŠàåÉÆ~“÷c†swŒ�ý8©?íý¥Ž8ÈÁÛ«Á|ÜPj3ü•m �c¯ä‡ùùá¼ Ÿ6°ò6³gÎ0×V˜R;{[Zv6UQ?mü¢•´qß”ÆÝ�>ù’š‹Ñ|æÌÓ·þú× ïM‡RÛ{¦oßÕwþõ¯·©ï+ö_Ò¼­:žçÝÙüíÍ®ÔQ›nllì_j¸kïfñ äù*±ÚvÜä ¥^ªÀ@™âM©È=m.uUÙ…©}¿kŠˆRך�üFÿ÷ˆu_)uæV4úÇÒ¹ã™�±±þ˜¢ (uaNf³'Íš¼)r½_´¶ž9cŽw›_6F±¥[ÔÀ½)ûÊÉ?¥¼ì¿tæLœÁ!¬,¥]L…„›_yÛñlö%³j·ÞïšäfõçM³S6½¤¾ÓºR›Ínûõ¯3Þ›ö>è虾}W é¯ÕÍä+Y§Ž:[u>ϳ³ˆ_§=J­iS—�Srî-5þ´ù�í—€_{^_0(5J (u*8J½:4J½¬ËRW­*®<Ùš"”úÇò‘íÆ”jS©cccc“Š1éÜzOõË&[ù ÔùöüÈ&y[<ò[ssìÕWùГCŸv)uó„í‘fŸá¼}‹i—Í"Î}:ãi`e(µ½·¥›šÒ '_É›®~;Ù`Äyó¥fçÃM¯¾j(us²­­­É}ÓÙ=3¨ïöµµÅÒ>;»[ îó¦øf µ~¹Ø¦M¥öm»Qý4רÜÐܘwj{Ûù›|Á Ô‹‹RCÅ�‰Å|”zm”Šß~‰ßUËXñ;4ñÛ¶ŠÖC…”ú7ò‘�±±¤]©[ÇlKY·é7÷ñ!@©£*uüµ×^3‡­iýv“ü×ÚüÊèhwƒÏp>¿]Œ¶�!~ltô$ƒCXQJmïm*”úÚkùŒ�×^;)ÿ}1ÿÀ‹ŽmŠ_{MÞŠ�Ž*¥Îý‡Î6÷M�Rûâì»[ÅÓí™�ìi5¸Ï›Û\J¹i±Lß˧C¾QNŸ~>ÿUò¼»mÛM¾`PêERjÆP)ø*u©‹h-ådêÑŠ¥öWj]Ÿ�æL²jË)a×#@©£*µ1>WèþœJýª¥Ô/¿þº1>>ýúëv¥žxýõ×}G×�úUžìÄ sXßýºùä“££1‡°¢”ÚÑÛ¬çØXX©_Pô…ÑÑWä}!‘Fê‡í¦«د«ïf„âºËù{[ îóFWMd^ýtÑM˳~ùuçwŒù›ßëVÛê8OÛù›|Á Ô(5 ÔE(uu¥¯K½6r”z�+ñ;96¶Ûu©êÇÆ&ÇÆHJ@©£ò󱜬W©ßx#n�ÍÁ¬S©ƒG×~Ãùfk{ã F¼€R79U9P©­hv“ê ‰7ÞPQêÿxæ™gr�î›Q”ÚÝwÓ)Ñ€×{Ý­†µøz0¶Ù•:jÓùFN{߯[÷¬“°µm»É J],¹¡ÞÅUêñ#mÁûŽôf¼g£�tf…•ú¡µkÜN]Sns© Uü®ž”ºÃZnÚ¨øýcw!²ÜÆ~�;d ”ºð ÿw¿³ºùµßýNWjÛ#B©Õ„ÄÓo¾ùú„âõ7ß<=aNvœxóÍ7_ö´7ê›<[ôvÔ88ûÆäe Sj{ß’J-z\~ã+º<ÿîw–G;næ£Ôª‘øoŒª§r­­­ÿ‘vÝ éƒ–»û®xö¯·y²³Ý­†ôyÝ£ÅFõEa|gÓ´½•ç½�ë_=oz¿JlmÛnò³¢”úÔNɾޞy•F4­§$¥>¥iâè{öÐí1-djæqMKzÏF=éÌæ¥.Ÿ’ß¡Qêš°ÄïˆQê63§»õJ©÷�� ý¯ëˆ[ÿF¬O­{õÊPêhƒ|}|þ;«`’~»É©Ô¯œ={ÒÌ:˜°†¾A“5Íá|:“é¶ŠÕ3Ïœ=›dp+J©í½ÍTê|y²ßý†—òí¼ùŠm?ÑA›Îž}ÃŒ[·Ö×g<7 )µ§ï¦ëëëýû¤£Õ°>¯|ÛIÔ¦3™L³ý¼}2¿…¤{¾JlmÛÃÌŠRjÝ9 ¦ZJ–ê’•:ôþäb*uíá7 I9’,ü˜_”:ÒºÔUÕˤ^5�Äo{”:ÕÖöƒ±´µmõ*µ˜Lý›ÚÖÞQŽL^»ë’]Û—­?uhl�~ÿ'cc‡E—ûA–OJ…ô¹sçÌ=_Ôo§Å#¿³6gÏžUÙ“¯¿åBŽf»ß|ë­ÀÑu£¾—ØÖýÖ[o¦m�©¡òïΞ}�Á!¬(¥½ÍüÔÇOžlj8yîÜ+VŽÈ¹sº^¿tîœi‚Λ–‹«ýÒgÏž5»Þ¯ëë·zoÚú Þ¾ÛT_ÿLÀ‰ÛZ íóºR»¿(ÞŒÚô›Æ—ŠÔký‰�þ�›—¡Ûü²µm? _0+L©'Ä– �ͺ°l,¬,¥½ÍPca×/6¼pÎÒfÝ®Ï5…(õ9c­“†–‹dÎÃÞö‹_¤¼7C•Ú§ïÆñ‹ÿ8ï|«Œº!�ÿ¢�ýĉLÔ¦õÝÍyßò{Âç éüÁÅ.J¯mmÛnò³Ò”ú�ŠKuèZ{t1ÿÛê¯ÔêèÙƒš¶g¡”ÚçQ”lJÝßë|¨·?‚R?TzÅï%¬OæcÔU¦R»”ºÖO©ËNç~#6ýfô'†RÇ“§”eÿøT6~fÒ N‹è5+i Ô‘¡iéÔé×ÔX½É®Ô'õ�©ûoš�f1ºvÎxÔ¿Àó%�ºÍáüiË©Å-U7¼Io8ÍàV–R¿àèmiš>÷‚ÞKše?y!*Ý๩ßÑŸØ,ZPV~6ŸÙ¨ÔVtôLß¾kÒf}縿÷zŸçÝÙS~½ˆ¦EdZ•@L›ßž½_~ËpjiÔ§‚•š/˜•©Ôú0Zwêzãv2×—²§�'ú”a$ûl¦á¸c{4U¼RÇ“Syé�µIÎÄúrI»R'ó÷GWòs� J ¾$wé]o¤^`W”Äïµ�‰ß5!‰ßb ­etêË“…‘íjuuò­mõ}„¤ T¥nxím�ײò�(GÜôöÛy¥núýïŸö*uÆ ÙãÛ3{÷öx‡ó�bÇ7OOœ�@Tò÷¿?ËØV˜R7¼"{ÛK²· _Ž‹ç^yíœø#‚ÎYõxƒç¦¾Ç¹×^û½­fXŸùýïÿÛÔÒ_ý*æ½ižéÛwõsùÕ¯”�6íÝ»×9ÙlÕçyÞ�ý”ºpÓê··^?ý²œdòzÚoïfy|ý«ÄÚÅÖ¶ã&_0+U©…„È};Dø  åíѦ’Ç&õ»=ñm»Å”ë-J²OM‰;ÇäÐú°6)Ýš6Þ*fGOí-Z©ãû4-%[Ô´Z³}íXÎTê¬8¸6”ô]Èó¸¸ß©DI��Rjy{PM×îŒç4í°õûÅ“V(±]¡ûò÷ûô»±BŸV{”º\¿E½ïU‘Ê“y�º¥X`¥NËá½ä1úþ­]©ÎþÏÿ¸g$¾e(u·wÎdÏÞ½Yïp^9µÂLíüïÿùŸÿfl+M©›_±zÛI#nmÞW³¬_É{´ëækÎ'6$ÿçÌúdÙ¼Ggý•ÚÑ3}û®MHºÉ:H3[õyžwç0¥nºÁ1[¥w{÷nÌu0Œ:@©ù‚Y±JŸR�ÝܤQ2¬C<8¤Õ ¨»­S꯰ҤYXl0+}X¤€Æ4íè°zt¼h¥îÕ´QÑ‚çZqX£hZL)õ.ãà;2ž£ëò¼Ý¸ß·ÎF)µ¼mþ•èJ½w|<‘ýæçqÊLÎüHY¨úùó‚§Ôb­,éϯ™ÿß¾¤Dù¥tC°Rë:}²ù¤´oë‰éÿ9ÿ?†Ufkk-¥Îß´÷AGÏ PêLm­ŠdÇÆÇG�'m¶êó<ïÎ>J¡i¹›!ÌÆª¾mO¸¿J¬¶7ù‚Y¹J­«s[<¾M7Ð}­¹^-–n»½¯O*îÑÑœ®¾Ã‰x¼E—Ûúì^]€·Û•Z«Ïåë’Å*õaÀ¢…áÃõ£±øMÏÕeËÆDÀº+7®«´˜žé<úqaÞÇûZ÷éÇÍú)u,;¢Me³úñ;4MÊSJÓ†í¬Xì™ÞÞ<ð`¥^[ZÅ者)OV�R@ù(u³“tü…xºÙ�øùó¿oŽJz|¼Ö¿™æÆ‰—_ž˜HÛšýŸf€2fá”ÚÛÛ½$Ý¡)ü\¤R‹gÚ»éçÏÇÔ­mµµ¿nöÜŒÖ3ól­­}FÞ83>žunòo5`çy5Ý81‘éo»{ÂþU’oÛ~“/˜º·…+õ)Më’-WœÊMj“yW;¨K­ˆo‘Vº§ÿ˜P’D�6bWêá>ØÖúŠTêØ¤hH´0WMH¦}\)õ€8xJ×ý˜ûèB©ÛÄÎJ”=J�ŸK½ÍÈü®1qX±ˆzdªì·(öí®Væ¯Ôÿ²ˆ–Mª—wUêU«Š3j”Ê$Jjgßy'uçÄøxO´=ϼóΫD[`F©Kâµ|ÀÚ–]òÎ;Æta]%»<7‹í™¿ÖåVÞhw½ÿVv^°¦‹lÛ~“/˜¥îÒ´#â‘u÷ˆ¦å¤ËùÌ-ÆìãVM³M•Ö•7cSêòÁÇ.”:Ñ:¨i§d »UќꜘҎI¥Nš§Xï>º.Ïj~wfÄ&ø¾JïW™ß;(W¶¢É‹t^®KPêÊMüö©øýJ eªÔ É F£î{ç�X4Q?á<åx¥ŽªÔï¾{Òçç® ï¨e´š¾ó�ïüºÑ}³¸ž™ÞVû�ï¨�ö¿3îŠú·°ó‚5]dÛ¶›|Á¬d¥Öz<¡²©uúŒIÍ“òÞ¸¦ÉÅqrb'A27Z¿¿NÓ6¥>7v�ªÔÚ�ä\ç£Ù‚ �‹P¸‘—; xÌÔ|ë¶£·J� ÙÎÆ_©ke=e¶+3ÝÛ¯Øwa¥ö:uu™,L]îÔ(5T¤R7œ½p!jSgz{›"혽p!ËÈPêù(uà .ÊžùŽ Éu³˜žY+žõ+)°éÞ^ϯh¾­í¼@MÙ¶í&_0+Z©‡„›öY>œ”r=¤Õ™J½Í¦ÔõýFE0‡RËÀŸH¯Ž®ÔŠÉ={ Ú”±ÇaMÛ*”Úœú\'ãØŽ£—Éà2ä(…9L©“Ã"ó»ÖøyV,ª(™o±ïèQêh%¿W©u´–¬æw„ÌïÕn§¦â7”µR7]¸u5š³-ã‘öK_¸ð?ÍŒ ¥ž—R7¼qႚ•ÑXÿtš\7‹é™ßÑŸô+õ*â--ž�¶o«A;/PÓE¶m»ÉÌŠVêašÑ”z‹,¡=rpþJ}\§·/cÆ #)µóèÅ(uü¨ˆzhýŒuV8¦%}ñ’•:â"ZK§®ŠZ�ŒòdPQJÝ�}ã�ˆ9”mgs‘öK¼ñÕx¥ŽÌÉ׌zü.}ã Ó9“¹žgÒž›Ñ{æüGn«ùbΞõIÄöi5xçiºÈ¶m7ù‚YÉJ�K7û$~û(µnÛS£F±²ù)õ!Ç.f á‰ß®£“ø-æy÷%ýWù‚E½2êúxd¥^Sbâ÷ª²©ø�R@…*5,¯R@4¥ŽM©•¨=åÉ|”ºÞtßþÅQêðòd®£G*OfF½3SÚáZmŒE©AT&ó+ö½QêåTêê**~J €RÀâ+u¬SÓ“qŸE´|”ºKÙw|T[¥‹hm7ò‹hÉRàj-×Ñ#,¢5`å†Çk¤¦Ã G”ýö+ö]©óëRׄ*õªUeRò;L©)O(5J %)õàþýûkOí5Âä´Òmº¶îÉõʼïÀÄïºñX®el‘”Z¤t�ÔæZu½I*¥ÖŽÕçjG4m_Ü}t¡ÔS-¹ž}úÃÛü•Z7óÝ­ª"YNÌÃne¨ñä‘#�Ù E–'+ã¹Ô$~J €RÀ¢*µÅˆQ;7i< CÁþåɶ«=†I©ã;�s˜’ÏÓvM©ûÅjçÑuyÞgì-UÙG©[e=3ëOeê@( º.õªe¬÷í0êê`£&J (5J óP꺑£­–g¶‰RÚÚe·{ŒiȵFî´®Ô{õ?-BqGÚ:4-#’©‡ãrµç#¦×FUjGém«…x<±E:ô±œ¼7¬Îˆû;Sò¾ãè-º< vÉ�êlZ¤R«ÛñøÞ~K©{e¤ 8¥~(b”ºz9çRW•>—¥”¥€”ÚŸd®/V(’ëKÍOR �ÙÖ—K:OÊvß}ôL¶À'·ÓfOÉ•¶JŽR›N]³ºÜÊ“ùÄ©}Ñr5‰ß°ôJÝ ¡,œRs-²·••¤,ÓiLjèÀ‚(uMy­¢Uå[ð»Êg*5s©€(5QjXÌ(õâHJÌ`îêèÔ´Q:N¦ôòd>F]UUËRW3—Pj”:˜/]¾è¹‰+—/]¼Ò­íb,Ø6ÀŠQêT,±üÿ�S®™I …HÄR>J½Ö­Ôå–ø]°>YP”z-Qj(o¥¾zYç„~£û²“FFw ¦ÔßÓyÓ}³aBïjWƒž“¾¨oÕu÷ŠxÂ¥t”¶‹n°PÛ(õ’2Ð?ÔÅ0JPêÐòd5áQêUe¥f.5T¨RÇß»¦#”:~ÍI7£;€…Rê ½K]¾tÅuóù‹¢«Å—O\[Ÿ×ŸqérÈnók°@Û+H©“±$ ¨ ¼V{”:t-ß uUY(u�Ç©Qj¨¥n¾tÍTê¦÷ò Ô ªÔzG3CÁù›q©¸>Û|Uý¶%wmÖUù½Âm—Ô`hÛ+H©½�?€2Å›R1¯¹Ôˤ&J €Rëƒì÷ ¥v=|™é• ¦ÔºëfÜ7¯ !¾Ü}éšÍ€Òï™·BÚ.±Á°¶V�Rgbå�ù åçO-½È‰ß˺ˆVÔ¹Ô«©ø ¤Ô"ÙûÊe�R§Åà îL©¯å­Õ¼)r´ß›¸îoÀ�B~¯ŸÈ?ÍÛM=m—Ü`HÛ+H©ãIÂÔPlõNR°+õšâæR/ëTêðòdD© ”Z¤}_òO‹Ø5Q+€Uj÷MÝ}/5Ьm?n’?kÅó|)T©ç×à%”PjÂÔPÑAjß¹Ô5«#%~/�Tû.L1JÍ"ZP®J}EN™~ïÚµ ‚ÔK®ÔW›òœžˆ; ør¼Á߀ãé ¥.­A”Pj+L]KSüíÇ[I/|.u�òdå2™šÄo¨@¥© W¼J-ª1“`q•úê Cg/š?d]µu΋¢ úðÕkî™Ïól¥”Ú"…SC%µÏ ßu©k"F©W•{”z-QjX>¥îþƒ §:_zÿ}Q„ì½÷ߟpšöûï¤(N©Ã{Ûûï_ó¹©z¡4à+ï;W‡ÖL[û)íÕ»§«γAÇM€•­Ôº¬àÔPöFí÷!s©K]D«ªÜª“ùUüF©`Ù”úÿºxÙ¾uâƒä@úÚ8ÿ?øàAj€"•:¬·5ê�Ê{Sêì\4ºã—=‡Ö4«‰™ÝT¿áì°ómÐq`e+µHýf>5”3‰XÌwõȉ߾N]µDB½ªH¥f.5”£RÛÇÍékÆÐÛ¥Ô�úý«Œìæ©ÔÎ߯®yoÚ ¸ùúµ÷<^›É°¹_ÃÄ{×.57ø·]RƒŽ›+\©ã™T,¶©†rê­±XÊ7‘"t-»PW—ï"Zy£®ñ&~3—–K©C¹x㆚UyíÆ ûÈûºþ8Aj€"•:ŒïݸqÙsSéì�†ÎúôºÌ�7ÒV5'h4µ]jƒ¶›+]©U :•L$H‡²"“H$S!ê¸Åïò›K]UzÅo”ÊQ©ã76lP£èkæ kû`Ã‚Ô §ÔWßß°aƒúÝÊvÓ4à ®>3£ïmp£ÞO7|p=¤íÒ h`e*u<#¤ ,IýÔ¥.�¼ï”z Qj(o¥¾üá‡FhëÚ‡ÚFä—>ü� 5À*õÅ?¼q©Û}3ßáB øÃ?4«{7^×{ê¥�¶çÑ Û+T©E<0™JaoP^¤RÉ�Ü {y²°¹Ô~‰ß«–s­ê(õÉPj(O¥¾²qã†&C©7nÌ+u÷†� R,¤Roܸñ¹†•ý¦ùÛÖÆ�!¬ïnðÄ{ú�Ë!mÏ£Aÿ¶V¬RTö(õšâ¢ÔË9‘Ú.5Qj¨¥Ö=úÚu….Ñ—/]2¬ú’þ8Aj€Tê‰KzwÛxÑu³H>!Üùò•�¶Ko0 m” ’”ºäu©«Ê}.5ëRÀ2*uãë.ºíJíD Êã R”¢Ô!½­¡Y÷Ükž›… øDÞ€Å�]i¿} ÁÀ¶Pj€ÊSê²-O¶ªÔ(5åÉ`•ºûÿuñr!¥&H PšR‡ô6©²7¼7‹1àË�?vÍ¿ÁËü�(5@…+õ<Ö¥^µTRí·0µ_”z5ëR@e(õÄ‹úüÊ•¸™ÊØ`¡•:�×ÞtɰÎÕü n¥¨¥^¤.—Äïðe©Ã£Ô(5,—R§_vÑí·×ûŽ¡5Aj€R”:¼·Ù´×߀›¯_¿>Å€'®_¿èÜkž ¢Ô€RL¶]BƒÎ›(5@¥G©C•z9«“ù9µß\j£F©¥XáJ}-?±ùšÏç‚‘ân3c{bãÆËÁm—Рã&J ðà)uu�Ìïe SWWGŒRSž Pj€•­Ô—7n|"í¾iãƒ�7‚ë4ŸÐù}yó¢7ø<¿m7Pj€ Vê5Q*~—Ù\jßòd5D©¥@©]ˆº`7^rÝÌ“öŸó\•ϸ*o_ò&iÏ«A{Û(5À¥^]ä"ZK¥ÔU%¯K½–(5 Ô+]©®ÞØhJ®í¦]‹ƒµö¢°ÞëÍFHúý°¶‹nÐÞ6J P©Jý�7ïÛ_©—s.uÔ’ß$~J €R{h¼zýÒUÏMË€ß{¯;ð©—®_5OâÒ{CÛ.¶A{Û(5À¥ö:uu™”'«ZUZ”šŠß€R Ô€R,©R×ÔD S/Qy²ªð‚ß>ëR¯!J (5J (5ÀR(u¤òd>ëRWU•Gâ7s©¥@©¥X¥~ȧ<Ùê2›K] >YM SSñPj”Pj€EUêàòd5áQê²-OFâ7 Ô(5 Ô‹¯Ô~åÉü”ºª¼æRû'~×TNy²X_’OPj@©Pj€ŠWê’çR/c�:r”º<•ºgPÓ´ƒÛøüq¡¥”¥¨d¥Žšøí»ˆV¹Õ'óY—Ú¦ÔÉQƒœë"npÒwD‘�÷UïÓ$ƒK?ÍŒné¬›9âÞÔ6:ÚÚÑÑqÜxý}±Ìƒõñ^ì �2>[—éõ%ì# (5J €RÀ|•zMqs©—u*u¸R¯ñ-O6®Œ¸.Â~sÃ�ÐkµÇØ«wÞW}·ÑÒ‘%Ñ®óåi{\›²š‡©¡Ñèã½È:sP5?œ[¦×«3>Ñ ¾ÊPj”Pj€åRêà0u�ŠßUåšø½Úw­¼@Æœáh�r.–R0ZZŠwxP TêmšƒõÌÇ{‘/ôñ¥üiÄ—.ã öñU†R ÔPÑJ�I$S©@Y’J%Áé¼ö¹Ôá¿Ëx2uÄ(u|Ä”Æqg®3ïY"¥t™ÞøaEj¾�lFQ©5m{e=½—qpQ•ºÍh½¿ âð­h.J €R@å*u&‰µA¹“Ì„(õÚ@¥.ãu©KˆRÇ[Leð5#m*³DJ½Ë¥ö�‘”~^ÚW”RkýéÔÞ˸Ë÷7”…úê7¢i[Î4sΩß(5J «ÔB¨SÉD"Ã(Ê‘L"‘9É"¿#Î¥.—u©k¢®Kmä°Ã?¶DËû^@¥Î;gÀ.¢RÎçsò”' TêÊL$ö^F÷…^Pöûþ@³Ôì4΢…ï:”¥€ÊTêŒ.+)ÂPæ$Äç4¥ö$~¯Ž¨ÔK$Õ‘«“Rê|æ·#Mv$ZÞ÷*u¼OóX*¾øJmÆi§ú|6+µV‰ó©}.£ëB/诩Seq©Ì4„ºßs(5J •¨Ô"D�PC%Hu@ :¼â·M¨—5J¦[C˹.µ•ù½Ýö`,bÞ÷B*µþݱ5ê‚ E¿ÑtW¤kÍ„+u¬Ã\úX;pÊ+QÙÃSV&õñüæÃS 1¥{Ÿþ×*›&��›m‹3õMå|­Êÿ,ZlMË')¨Ôñ>ó¡CâÞQë¨õ2~=UðuçŸÏ×ñP½ë‹2ÕÒoEÃu¸.[ëAãbÔÛˆÍ z²Ïet]è"N=³ßøíeøP`5ï!ÿ ù€w<ʧ%àªôšoýaó‘óõ Ç@Y”IC©¥@©K3æQC‘ðù (r”º¼ê}G,OæQj+¢·Ãz¨Ç–�t”é Qêä.gM¯cÎß,RÎÍæå?j´Í8ˆya;ÕG´°L@©Pj(c¥NÆ(± ÅVo˜:j”ºb¿¿m™ßÖ•ØçÌûn›r»Ù‘@¥îtï;hŸ�ìmÊ4ËJmÍî®õœ·O$2ø,JRjkI±„í°Çížúº-/uÜ]O xÊ‹´´5ëlz—[©ŸQ©£œzëˆs�nß\¤>¿2ñÁïxÁOKÈU±~N9ªîo7ï�ºN¥•¯8”¥€ÊRj‚Ôð„©Ã×¥®.ßu©«".¢åŒRç3¿­‰§�޼ïVŸõ¤¶(uϰwß±¼Öø55’Œ¢ÔI3.¹ËúýÎܸß󦆜EIJmù|Êf™Sv¥}Ýæ3N¹v˜2€Ìô¹.Æç2évÒÃN¥~r4¥Žtêý®öûõ¥ŸÐpÈ;^èÓvUƒŽiÛY÷l÷ŒÞ>ÌWJ €R@e)u‚ 5T)ÏÏ@¾ëRGŒR¯Z*©–‡Š¥^íSñÛ¥¶2¿‡Ì°¨CPRS~k4÷ø*µÿ¾–:úoˆ¢ÔÖcÖôîúÀÜÞ°³(I©�ÛuÈÝnÁ×}(h¡kó‚�ûn­u`=ÝBOŽ¤Ô¥�ú”_Bõ€w*uØ;^èÓzUZmõœV/|†RJ °¢•:cæTÞ­}­P£^ÎÄïU¥Î¥ö*u>îjÜ?âÈ¢Ý�—�‘N·S¹”ú˜¿€ ¸œËOÏ )u—{%«=�yßagQ’R›çVPêð×¨ÔÆk±Å¡'ëò;å�9-\©CžI©K<õ^Ÿ®4èú¥ À;^àСW%ÿ2ćԺFù•ÆÍ\ýI¾áPj”*K©Sä}Cåe~§B”:<ñ»zùò¾}•ºª4¥îu­}4`[áÀ)Q£:fÅL;|”º'ŸÛ[ŸJÕç}¬Õ•|¨5kµ’‰ºM/W__oeîê·ë“¶*äÇ]çÉA=‹¬Þšéj§DÓ±ÂJmESGÜ–9¹ãèÈ¡‚¯ÛþŒ£½½;mó¢�×eH’GêÂ=dî‘=“n¥y²ßet+uôS?0Ô{8ÿ“ÊQŸ®4é™îúŽGý´ø]ýM1�ÖŸwsÛ¯+õöéï€R Ô€R,±RWü.TžlÉê“­Š4—Ú“øí©ømËüV¶š4g¸n·ØdŸÓ¿;}”ÚŠÉPbfÈ)`»\ Ï[ìU¼ÝS|= *ï´ëXþ¤‡=™1Î"¿.õ¨ßçÁG©�9 8¯~;r™HGÌ?cD6³j}ÕÉýO9 e�Úc®+VÛ)Ÿ»u‡K©Ãžìw]:ò©ËŠt‰}ŽõÄ\ùÞU©#½ã‡.ðÂòyá­f-²É˜Ïg:ÆWJ €R@E)5‹RCÅ‘‰ÅJMü®*¯ŠßþËRû”üv+u¾•3<(”39é®]Öo�:”ÚÚwÄøȘ O&íª~ÈÜÜo KTjó´Æ”C›%Ãv{Ì.ü,ŠVêÔNgøÔ²ÌþdÄ#ZÏ4~½IZŵÚlqÊüAò íŽ>÷ãÄ!§R‡=¹°RG>õS®�J]È•³~£ }Ç ºÀ Ëï>rÐ'=ãž'(5J •¢ÔŒ+ ÒðUê£Ô"x\«hyÃÔ!JÝë¨ôµÝž÷Ýå‰JÖÚ%Ë¡Ô]žE”¬Ðâ^ýÎ^Ïæz[ ² R[ñÚVGèx¯ûý,p‘•º5§Ó3¾=Ÿj­*£YR™ŒzÄCž’êõSM$æÖí¶�Ç5÷ëìs*uØ“ +uÔStÿ°á³às›¹Éúa5ô/tè/Ì;Ë|Äñƒn�ûšJ €RJ °tJ½6ŠR/gu2?§ö›KícÔ^¥Ž9\fО÷Ýa¦[çLöÚsyJmî;l¹�µ–Q‡ms¾bTâ`¿¤+ŠR[•ÅöÉ–ë‚ò¾ œEd¥öÒâˆÓD>¢»ü›Mø|¦$'RÇlòhŠäXÞGÜšøäÂJõÔ�z>*ÞïúzO;ô/ü>…¾0�Ã~µÞL=»¥@©`¡”z~³�Ç�´¡Ô°‚•ºº@æ÷2†©««#F©ÝåÉœæ”sÔûÞ(˜;ûóÍ;Ç< 8‹Ò•ú`Æq­NE>â!ûSô{ jek‡F§ÆòGØåmû¨�Rû?¹°RG=õ^K{Ç•úˆç¼BßñÂïSè ÓIp,×íÿ‘îà¥@©`A•:·eÇ”6¸«·t­S!"”l¥^¥âw™Í¥ö-OV%Jme~‹ÔæGšóî@Ãñ(õnoèõ¨Mw‡‹Ž¢ÔVàQÌÕ=”÷]è,JVj÷RÍõ‘�xÈ+}Û]>ÙvÔg�f!�½m·¸Õ5ðÉ…•:ê©·zâëÞïúSž9¡ïxá÷)ô… ZíKйÒì¹€R Ô°PJm-¨2R²ú¢Ô°¢¢Ô«‹\Dk©”ºªäu©×úE©c¶äÙƒ ^SyÊ£Ô#ÞÀ`‡MGB㆔ú”mÙ¬þ ¼ïBgQªR�d]áÏžÈG<ä]îËÑMîò=ä)[Ûǽ"i(uÈ“ +uÔSÔ{<ÁøÐw¼àûþÂâ®|Z>O»ø†C©PjX@¥e…îÝs@Óê¶¢ÔJý�7ïÛ_©—s.uÔ’ß‘¿­DäSù¥�FâSŒRÛôï¸�R/U©sù¸f20ï»ÐY”¨Ô‡­Ôž`¥:¢�R›+@wRùTÜ/ÍÜš³¬”:ìÉÑ•ºÐ©GQê}ŽºññBïx¡Cxa‹÷YžÜœz½“o8”¥€…SjQ0WfI&�‹Œ¢ÔçR¯Ž˜ø½tJ½ª´(µ_Åï|æ÷ˆUˆYå}[ù³Q”zÀk1C¶TÞçÅÅ+µiaSùHm—·¡gQŠRw¶Ø>#^Ë,tDó[¼ú9v�OÙ¶óÆrã…ž\X©£žz¥nñLŽ}Ç ºÀ ³ÿÆ"?Iÿ‰ó ‡R Ô°pJ�µF”É:sÔ“ÙÖ–µ­<’ìsŒ“}9õp.—°+u²/‰RÊRêššˆaê%*OV^ðÛg]ê5¡Qj+ó;5䜃jÞíȺIy”zÈ3™ÖR²!ÿÍE*µ)m9SI'}¾‰ œEd¥:.éíjs~@¼–YèˆÞáVv½H’îË'—µì¯Íí´Éã�·Ù1ûC¡O.¬ÔQO=ŠRï÷6}Ç ºÐ ÿùrı‡üƒà½|áÔ(5,œR÷iV„¹­KNëRWU•Gâw‘s©óA½Z³ ”QÚÿ”}å*/¥>åY3)>ió ïæÌ�"Q©cÖÑ:ƒ'Ê8‹ÈJ� ø¼x-³Ð}Ñš²Õæ2¯á¤9ؾóï:Ѓv¥}ra¥ŽzêQ”Ú*ralïx�Czañü„tç'Öu…÷ò ‡R Ô°pJ�Öc¾aùó~ÒZí4+7ÕTcÀœ9„Ú—‘J½ÛªA©áUê‡|Ê“­.³¹Ôê“Õ:µoÅo[½,gÞ·¬Ààœ ¬Ôû=+[™¹µöÍ9·„m‰¨Ôfpw æ©ºí –œÅ"(u¡#Z%Þ¬§ôØW~2#Öãq×KòhNœÎWñ²Œzra¥ŽzêQ”:ç±ÿÐw¼À¡ ½0½ãNº Èeìg£ù}~¥@©`~J-Æ(SGRŽ,ÊCûsûõAS‹º·£>»w·Êø¶Ý¤­-Ó z{O_Ç ú¹LÓÆZú²-Ãö¨ J šR—'« �R—my²ðÄï|æ·+*�ÒÜþ™ìœ’Œ{”Úªlfe8[óaS¾›wÙfD)µ#Êhþ¤ù×o9Àg±J]舖R�_š‰»ð ºÔr›}ÖpÒ\‘yÒØ;àPêÐ'û^FÇ…ŽzêQ”Úú¨l ¾0¶w¼À¡ ½°|¹ïã“>9ÞI�ÍJ €RÀ(uLRF¶×'Ì�á%õA—þÈžþcâ^Bͳ֕úXˆdË!LnLƩƌÀP‡ï¯ÿ(5<JíWžÌO©«Êk.µâwM¤òdùÌow­é9“†›dŽÚǥίid„T�;­ÉÚ|Ü—æVê¿òR¦(M…­p]à,^© 1¿Y¿têäó¾üMÀ´^#ñ'_éú”Ã3'»DvtPs(uø“ý.£óBG<õ(J�ñ®gúއºÐ ³¢õ#+…ÜvN}Þ„y@©Pj˜¿RÇcÇTÄ£n{J�HFÍ¡IŸ#“3#MºÏ‘ét][NI¥î”÷²*´�RéÔ%Ï¥^Æ uä(µ¯R÷:Ëyg<É»ä×EÎToUÌ©Ô]Öó�õe2¹üºÂ*Fº×º¿+—ÉdwjöÑn¥6‹p �úêr`ÞwÁ³X¥.pDÛÚÞu[öïßRgÝÝm—æa¬ÏØœù”³mmðØ€½ ×`á'û]Fç…ŽxêQ”Úš¾œŸíúއºÐ KNYoÝ´•E?â™Ø (5J ¡Ôú0d|@Žˆ:c²:LW«`ÜŒ$s£õûëdÌzH›ÌQ¡íöÆŒÀP±" J +1ñÛw­r«Oæ³.µ¯RÇ|ó¾íIÊÚàîS®ËN¥Îò_÷h$º¹ÞO©ç—°:ØŸóÊkPÞwÁ³X¥.pÄC� ‘õ8_éàîþaÏrQ;‚ž<áÉ>—Ñy¡#žz$¥±•1�~ÇÃ]è…m·Mò÷ÆÇ�Úþ”¥€Tj™·eRŽC\ë�Ô[™ŸR©ëäÎm¶ò0J©�±6J +A©×7—zY§R‡+õšðòd®Ìo[õäܰŸ÷Hù(u<;é·ï¤i§þ›ûã~J]ëŽNÚ[8ðŽ8‹…WêG TêcfÊOØ ÌžÍ“v¥.ðdŸËèºÐÑN=’R›–[—)paú#ºÀ ë³7˘YâƒVš·ÕÞÅJ €RÀ"(µ>X©3ÌvhÚˆB9e,Ö28rЩÔ}®ÒÞ(5¬¥S¨ø]U®‰ß«ÃÑrf~OÙ‹'�ûy�7v)u>MÜN­ÕT­_°5å«ÔŽzÎõžè£3&é¢ÀY,¼R‡Ñ|ÆQ×öá¬÷5ùXq«Ó<§ZKUx²÷2º/t¤S�¤Ôõ>%ÁBÞñ‡}aVîÄ.ç‘Íÿ*¥¼ï: Ô(5Ì_©“1«Ú÷…Úâ¨Ü’Ô‡j£µÍ¦Ô MÛƒRÃÊRêˆZñ»Œ'S¥Nùæ} öz¢‰Ã¦Íº•:^ïÙw²Ën]žÍ\^Yë'cy¥n-˜÷]ø,A©C�h=ã˜sóøÉÇã»¶¸æ$÷MÙÓ¢ûr¥.ôäÚBJíÔ£(uÒÏcƒßñ‡}a-®w©ßeóõžêã€R Ô°J½'?¼#�.Gvg½9*îw(u¾é/ô>…¼°mæd„íæ¯®œò}Îk(5J £Ô£úHGÙq¶NNŠrDj™ÔÖÁÁ.!ØÆ^¥Þc¸snX;„RÊPê‡".¢µœJy­ˆëRÇmE’µ)÷¦LO^ÌêvÛòz÷ùÄ%G�Z³¯‡�z×ÚëÉožÚ“×Ê!ï:Ô­#>¥½�Îû.tý®%��-ăžxD›—ö™/iª×±ºÓ^³Õƒ}ùÕ¤l‹*dúºZ·´nßà{íe³#<Ùu}.tð©{_ìçß¾Ÿ Éd”w¼ð§%ð…™z=™òüp�süðÒÁ÷J €RÀB*µ(Ø2Ò•KöõNª÷ë÷k³¹Ža1JêCåñX®eÌ¥Ô1}µ½'w¤SÓºPjX)QjOâ÷êˆJ½DR¹:YJN²moKǩڶ­Qöíëê=uª·«-ÐTWoǩ޽m™‚ µövôv´ìMyCÌÚTb~g±ÑêMõôî;ÞÕç9ùTÏþ½{sÞ×”ŠIRÞŸ1Ž~rðe\”‹•˜ÁúއºÀ ¢µÐï"€R ÔPšRÛ²7÷ˆ1JÆŒ÷Œ‰p�Q­uxÀ©Ôñœ9Ûm(ƒRÃJ‰RGY—ºjY£Ôáaê°5´æRWù©Á[*æœRÅ#‘™tlj­çÃå÷Jw:Ó¯— sÒú_o„Rß¼u«)xëÄé·Þ<ÝXd“·oý1Í@Pj/±[·Înl<ýæ[¯OlãÕ[·ÎòÁƒ¬Ôñä�ž ëb%ËyqÇTg‹È•iëдŒÈ÷¶r?û亨#*î0lŽãPjx�£Ôk#(õòÎ¥.µâ÷šJUêd}Ûh¯mbpå|ÙÌG©­,õº½*ÂÛeM&-¿WÚWUÁ¶jó¹âPnJ}fzú‚íî[éXƒúÓ=.øø^CnüDßQ=üòG6>Ñxczú<E@©=4ßžžyAÿû©½ÏL˜]êcÙÝ>sKµ{çô­é™&Þ$x�•ZèC}í¨-½.“íËæ“êb}þ‰�É\ÄÌ;”VP”º²Ѫø(u«³�ÕÑÊ9óy)µm†ûЩS;GÜ‹;—GÝÅÑ–…^‚Ô’R»FçrPÿ²qïÍÇM>uª_–²­”úõÇm|*¼áŽò”Ú�ùkÓGö>£ºû3óþǧ�Oòììú àATê%–€ÊTêµÑòKü^µœ«hUG™Lý€(õTj…(ub$`}沌ÀÆŒÙÔSÉe<‰Ä w}l¨\¥þ½# Ü¬Fõ†R¿¥ßüèÓ·>#úÏqêæÏÕð>mí÷±É'Fèû&#E@©}~Á’�æc[—ùX*u·ìføüSѱ^w<Ë»ó�é铼K€RÏGN2 , ²È”¥.¯zßË“= JÝZAg>/¥ÎW³pR[ž¯uK„©Í õßn‚R§g¦§“ù»o‰±»©Ô'Ä_D§Ób”ÿ¦íYaÞ[J­ûõio³1†Š€R;9?=}Wv½k¹6}bšôi½g}ÔlïMÞ�ÏNOßã]”ºtR± ¨,±T‰QêŠMü~¨â•z²’ŒzžJÏ VŽQ[AõÉåËXJ³Í“|»=Jýêôôó÷DÚ÷›™J­›òG*ß;ý‘Jè6è6ýÉ„¥ÔŸ˜©«y.�™ (µ‡?NO¿*”rt(A£Þ©ÞR7ߴͽðß¹!>=ý'*J�RJ]îåÉ 8uè"Z¥>VY½óTêxjß°K¨�eËöÅf� zÿ²e, „-;˯Ô'Ož4g1¿hÞüí+çÞ>—5FàÍ'O&uI~åí·E ìîôôÿXÏmþTŒÝ-¥Öï}’� }”?ƉÇÿøÍ†¼Rë;v»N#ëPu€S©ã'O6544½öök'ó†›ÖûÛkqûÍ/ž{[$j¿0mä}Oäû–ùsÖãV/êv%…xwnh¸===ÊÛ(uÉ$cÄ Âð~h}ץޥ^µTR-!J½Ú§âweF©û'µÉáÎc‡k+mŠì±:E鎗êè³|zdKYËâþy¿Úy:½:üT/ßmå©ÔÍ7ïßÿB î_øòþý·õ¿Mïè7t¾|W>þâýûnþ‹x@¿Û|Ëž ý¦®Ê™¼RòÙgf>÷[†R§Ï$¥R‹šÄy¥þìñÇŸw�GúOÓÓ ÆŠð€+õ_ïß?÷â²Ý4&7ÿö]Õß¾�¿YÉ=^{¼Û`Ë×>ýøãŸ;[zù³Ï¬PôG†R'ϤýwÎg� Ô ð(s¼©öE´B�z9¿W•:—ºb•Z'“X¹Åmõµ-µãõ£Ô€„ÊŽR¿¨�çß‘·tm¾©�È�¿ô¿`(õ»÷ ¥ŽÙóG»UêéGάSÉTêiúÖÌÌY}ÇÏÓ v¥þHúvºÛîÕw¦§Y:V€R¿ku0éÔ/äûÛ_Óö=ÞU±åóæ¯W"Ë»»Û¯ÑF£®÷Ù™™[é€�ÏLOÏ4ó>J]òˆ7Fæ7T˜©xkêE_—ºzùò¾}•ºêWj¨x¥n8gŒí_»ÿËuѽ)fïþNëo6K¥�üõm´þ½=?û“Çÿ¬ÙW©?Rq²Ö™™™;öLU©ÔÍ¢ø[¢^ñGŸ[£þ Ôü†¡Ô¢{½vNt3ñ�7ú›zà¯æ_Þ|÷í—ô;3ÆTj‘öqzB,Cýñ§§=�Š"�¢gÝÑ»[OÀÎñij~J=’„©¡²Øê�¬`Oü^Sty²%«O¶*Ò\jOâwÅVü€B©�Ôï¦/TÚ÷ÛF|L�íÏJýv^|­ôÑÓFlÌG©uÙþXÈrNãßö(u·®Ôæ’º™uÊÎNOßf¬+@©oþVt;‘ùñ¢­¿5¿£›t“Úã £¼AZ÷àÌõ¹¹Ð´;©;ó±ñØm½»å‚v¾5=ýß¼O€R¦†•¤Žžø]U^¿ý—¥ö)ù�RÀ²)uà ÊüW“nøÂø«âg7•R¿kî{7¿*uÚˆDû(õë�ň›�ÿæNÖ£Ôr¬ÿñgI§Î¨­¯LOßb¬¾R oýGïv¯¨þ¦¦C¤Õ�Zù=du²?Y?R‰ÎòÙÇ^§nüLß ›ÈÞùMGsÐÎÔ'”z¾aj–¦†Ê!ó©¨7�(µ—Ç*ZÞ05J å Ô2åûœþ;© ´¹îôKúí¸Tj+cô^~Æó[æ@Þ£Ô/¬2Â¥Tç¶”Z„·?~Sß’±4cÝ­Ôôô cExð•ÚœßpS$�$m½ëÅW^yQîñsï˜Õ)DVǧ'žù£Ç­Å³T‹À›ùÝÍÁ;ߣX Ôó#…SC%µÏL…ð¹Ô5åQ�ÌÏ©ýæRû5J Ë©Ôjú¦HòVzmÖ‹Ëá¾®Ô_ZbüG+Ôuâcs ïVj±XõG>e”,¥~=›~ËZþç…ééiÎ…_©ßÍß|[ô·ûi÷æ4 Û*ðYáænýæG¶_ª>q)vÐÎw§§ßá}”z~’‚SCŵ߇5T©« d~/c˜ºº:b”šòd°œJ-æQ¡±sù(ZCßïßMVü¶¹5=ýŠºõ©ªéíUêÌG¶Ò¾J�yóMk»ÕŒ˜6g°¼RŸ3n¾#ÜÙÑßÜ{Ø ¼þ曦y¿lÔ0PˆD�?¸â»óVÑ”zž$熊 ‹ù.¤žø]¾s©}˓ե€2SêQ*éwòÖÛö!þMñ¨[©Ïȧå’Ô>J-âbûµm-æÖ MºR71X„•¥Ôo‡*õÓÓwÓûÍFmÛÙVY¥žO :•L$H‡²$“H$S!j¡Ôyó¾ý•z9çRG-ùMâ7”—R‹e´¾42¿_±Íí|ÁœK�Wê›f�£�w¡ÆíéOuE~¹!\©'NŸîöD©cTü†•§Ô¢¿5*õI³J °‚‰\žÌg]ꪪòHüf.5”§R§õAý_õ?J åª>©¨ñ›*`íPê³>éÙùòd°­�«Fôããã1�RŸxÜ\Ekâ#+ v—‚İ•Zô·›âÉMB®ÓN¥åß0³9 MþÄ,ñ-:Ïg£ÎéÝ-`熄nç/ð>J °’•ú!Ÿòd«Ël.u�úd5�NMÅoXN¥~רLö’Qõû/b�ê›B-TÛ©Ô/øÔå¶”ZT~ü# ýÁÄÌÌÌ«¥– ÿ|üé[Ÿúq>ª}ËZñ`å(µZþæ;²¿½ÝàRê»f™nQHÿñÏþðÖ'⯠MËGòÝMLŸ¸;3sÇ熆QjJ €R‡”'« �R—my2¿  ”ÚœD-Çò~¡¡!-�Zò×´[©þh-LíUêOœ³«uW>£+uÚ«ÔJ¾%¦Q§§§ÿÄZ°ò”:ýW³»}ùv³[©gM‡èþÌê3J’'œ½í3ý¡Û33ïøïÌZ€R€oy2?¥®*¯¹Ôþ‰ß5”'€òQê›F©ï††¦?«›Í¿“³û7•i¿àXæçïÈþäù†¥þjf&뿳ü-,ËÛ(5ÀJWê’çR/c�:r”¥€åRj_šNž<é3k]E_>ºcffÜKóÄ›o½õf~ë›,ñ+@©û[ÀóoÛúE÷ëo½õÖéÆàs˜™ùM:`g±Wš· Pj€­ÔQ¿}Ñ*·úd>ëR£ÔPVJLó­b¢]÷ffb‘vüퟦÿDñ$X¡JÌEdodgfîm{‡¼o@©Pê°(uøÂÔË9•:\©×Pž *N©ÅúÑÑ+s5óU´�öÙééw)Jíþ ëNôBÝggf‚2=Ò·¦g(U(5J¦.Pñ»ª\¿W³ˆTžR7Ü›ž>q×ôÌL4ýÖGü·HK”ÚCÌ\ ¾0½33É€M¿g^ Ô(õ?D­ø]Æ“©‰RÀ¡Ô‰?ENE�ÍÌ´FÚñVДڗ»‘gZÜSKhùÐ43ýG~²”¥ö®K]SëR¥€N©ÎÞ½1‡4uï^´“¸p—´o@©}[¾{÷�h{¶ÜÛ°%{÷nŒ÷Pj€•®ÔE\Dk9•:ò"Z¬K ­Ô°dJ (5À‚E©=‰ß«#*õIuäêd(5 Ô(5 ÔK¥Ž².uÕ²F©ÃÃÔakh1—Pj”Pj€EŒR¯� ÔË;—ºÔŠß¬K (5J (5À²G©+k-¢Ô€R Ô€R,‰R¯�°ˆ–_â÷ªå\E«:Êdj”Pj”Pj€å�R—W½ïˆåÉPj@©Pj@©–=J]±‰ßTü”¥”`ñ•ºlË“pêÐE´ˆR@ù*u÷ĉfFq‹¯Ô鉫¯œ(°SæÊÅ«î.Ù|b¢ÑÛ”û±FñXÚñЉ+úé߀R¬¥ö[—:b”zÕRIµÙªHs©=‰ß•Rñ{d,ÆG`e)õ 1âÓ1›/y:}ƒa8ÀÂ)õ%Sl't7~_LoNëìÜGHð† Ó­¯‰ÜïækæóââÖó§°ËÏ›�ï«fÄ[¿EPû†ùL™N7@©VH”º|�:ê²Ô>%¿+A©3ÃZ’�"ÀÊRêë7¾×lÅ«�£û‹ú°ŸQ8À)uúC+![è²ðæ¸Þÿœ;]6�ZítÕøÝËøm+ý�úáKþÖlÅ«¯‰›WòùÞqãHæaô'ä� €RT,‰­©˜$µ5±°Qj<.�U´¼aêÊRêmÚ T€•¥ÔÍïA/eÐR,–R îV7 KžðÌ­øÐöÈ{êW.áÊ�ù@÷{ª³ZMÞ,ö6gU_¼|ù¢zè½üßçM” ²Ù³±5Ø(fZw»¢ÔB–?0²L/½/Ê›]:a)¹™ Þð¾; €RT‰˜‡DH”zu‘‹h-•RW•¼.õÚʈR÷km|XD¥þ]¸ù�'NL\|o£3m´qA-€â•º@oSmm0üVWãKŽ5à›]s©¥R§Å>ï]º.–ºûðª¡ä޹ÔJÿ¾|å†ÑÖ†Æ^4ØcI<@©¤ µ7L�{È›÷í¯ÔË9—:jÉï Mü®£à7Àƒ©ÔÿŸ‹—½ñiQ@xÂõà5‚ÔÅ*u�Þ&EºU�‚˲ë½/œV’­?ò¡­â·Y–+SË^ªê›ÉŠßj~µ\EkcZβÍ\“÷åÒY×íå.YëW Ô•Hʫԩ�(µ×©«Ë¤åÉV—Ù\êõÉj�ÚYñ»k—fп¿UÕiËÖî› ô,æÛ i“‰�íÛµ#|VV¬R«èØU‚Ô‹ªÔ"‚|ɧs¥­Ÿ±Tš÷�ËÝbõê+Ê�mÏVÓ©Ó×e-²kW�å¯ÛWɺ(+– 9·Žt�Šß€R¬¥.OV¥.ÛòdA‰ßÛ ¥ÎÙkÕïw,êÛЫi¡AðZŸU€¬Ô¶1wkØ,ŠR ͽÜÐÿ.šz}bBxs·ZWúF~ƒM¼š»'N¤Ì”î‹ÆR×VÈ;-ÿ5Ïšu©¥XJíWžÌO©«Êk.µâwM�òd['•RÛ£ÂÛ4m÷â¾ ýš¶7lû”ã³ ð *uãë.ºó—«Wóu¾/[“- R”¦Ô!½MpÅaÔ�W®äûßç½*3ºãŽã¯yò·E øUUüŠ=JÝ,ýÛ|è„Òs€C©c+€•ºä¹ÔË¤Ž¥vVüÞ§”ºÓöP­¶ÈF»U?`Ø"YImEx •:d¥Ü«FI$ç`=N@  4¥_—ZL‹¾ü|ƒ=˜l¦tg”9_¼tÉôçôòG®Æ�®(õu]�/]²’Ç/ªXtó Ï\j1Ú,IvɾF5J ð`*uÔÄoßE´Ê­>™ÏºÔN¥Ž™ß=öò"Ó�}Àó`bÔºÙ§� (+M©í‘­ÖÈ� 5Àb(õ‰ 7¾g[«.�·åf½×ÝHËÎ÷~Ú²`žÖÍúZÚæÏWÕÔ ã‰ÝŒÕ±®oܸáDÞÜ/©ŸÌŒw|S©áARêrOÏe„‹óÉ*J©×7—zY§R‡+õßòd£BÙ1›ÐjÛ÷]Ø­iãn¡>2•ŸÏ½_ÛÉGà�TêôË.l©¨×6nüP ͯècî �f¸Œ 5@)JÖÛNܰɱeÍÖïXÒ‚ãæ‚Ó*GÜÔhUñ[x÷ÆŒùÓd'm|ÏœC-Üú†•׌€IDAT¼5±ÁÈòn~_tqÞ�×ÌÞ €R£Ôð`+up˜º@ÅïªrMü^í»ˆ– ÍS[×á¨vtA®u&;ÚËølHkZÊ#ÔZþ°[´ã¶½Gs>¸ˆR‡!ùß¿|ý’X’çÃ+VÒ(Aj€R”:„F±ˆôÆL„.wËõà/]TëK§M·¾qéâu¡Ê7äìç´¬~íÒ¥÷d�ï+æï^ß»~ñÒ�üÚYjùêëׯY{I-ß 7vÞ<€R£Ôð *õ?D­ø]Æ“©‹ˆR‹5¢‡ÍK¤i}¡×0¹Í÷šX©}Â’µ±!o_îÒ´CŽêõ]'meÇwkõæ±öuê�Oð…ðà+uC“µ¼íÆTŠè ‚Ô‹ Ô'6:¸&CËùþ§ŒZ­=m,Lmäq7_Ï?kƒÑ7'>°²fU_Ý`=fN縘ߋ·Pj”V‚R¯ Tê2^—ºÄ(u|¿R꺤">~ [4?j�;õè–\wHl˜ôúQMkqâXOË�Ú)?êÖ|@KÛ`�¦mñ{RÎ SwåÇ{Å“[Í£|zPj@©Pj”*!J½6‚R/ï\êR+~¯ñQj1¹Ù\G«^›JÌû*ë^®©"g#¦Û6NÕ?;f„©;´SâO²Î,D^ï#æ€R ÔPÎJ�íÝ-µ] I®öðþü=”ü(ue-¢¥+Q›ëhõkó¿Ê=Öª\}ºSdÜ›òZŸñ¤£*U\�•|™?>À§¥” œ•:Ößo‹Ní5f3z’¦m�Q¤~ëÞ¢(µ~~fhkKÿ~0°˜J½6Â"Z~‰ß«–s­ê(“©}•:~È\G«ONº†õýè±í1n[è:ç¾¾‡ƒ¿&4m� mËZdªù>�âÆ Ÿ^”Pj€rVꜦ%£+u¶³Sx‚x9¨�Œ÷Y÷E©õóëL˜ï0°ìQêòª÷±<™¿Rï5×Ñ:áW±Â¿k!5º;µÀ’âmš6‹g†eh:¾Åy€á _”èmŒR›{'dH+©imù{‹¦ÔÚ>”Ê&J]±‰ßy•Ú\G«Ã½¼UiJ}L3Ê“ùuLÎÖ>("ØÛŒ€ô.Õn›«h Ô€RTˆRg2v¥v††¾S3m8ž•):¼ ÔZ�S©� 'œ§è¾ °ëRW—ïºÔUÑò‰RÇ�›f|,ßyr‚Ljÿ©.g?еú‘ò(µ¼[·ö£�oO�¦ §Z�iÓ»<+pÅÄ¥âÉÚÞ$e”¥€2Uêú£uc#õ†R'� LNíR¤Î¾Ž­n@‹FhÚ`çqÝn;Ûâ‰ÎAMëì<¬î9ŸÕÕ94ºc¸na”z‡6•Ì+u¢cdxxäpÂ8·-�Úà‘ø¶]uÚˆ!ÜmÛ;µC§(tE*µßºÔ£Ô«–Jªå¡"D©WûTüö‰RÇSÆR·å/•XZ“®ÝY¤Áª”mÿõ­G4­+ø™ýš¶¯Å(î­ÒÇíëmuˆ³li�TS®¥@©  •ºK ¬¤RgŽÙr:§4Y$H›LÅã“âÆØ>1‰º5žãܱ±!uÏù¬Zm°NÊÂ(ulJÛe)ubDEU›Òª¼Õ)mLÿ#—àiÓJ±@©½‰ß5åVñ{U©s©”:>¤ºÓ!ûcr)¬�¢;ï*î*«ÂbZ�ß iÃ!]²Uß¼ÛH"?"L¸\}hXC”¥€rTêܰ6�Ë´Ò¤RÖ†»’©Ãš6*µUëH¥z'åŒf3¦­$Z&gò÷ìϪմ©ú­E[­¿R'ê5m¿©ÔµÚX}"U«Jéç6žHíÖ‡ãúcr�žmSÚ±\ftJÛÁ`JUêðÄïêåËûöUêªy(uNYp—+d,ÂÁGµÐÀ²Æ¢\ýjbFÆÞÿ{ ¬†5’•·ªVލ µ‡F)ñƒ[Æ´^>Ê(5J e©Ô§´A1þ�M ¥ÎLª‘ô1™fi„ˆkÕÚñ¬Ú(åŽ"+u|H«‹JÝ×Õ§Fý[ä¹íQ§Ñ¢öL‰É¡# ë@QJ\ñ»Py²%«O¶*Ò\jOâ·ÅoßµAGu‘ú‘UKä™hÝo.Ê¥“8fKÔ—3ê4dUrù Ò7,Óµ*M&I©2”¥€2Uê•4ß#”:g¬[³_†¬§ÔPx¿œ"¢ÔŽgÕL¨,Q©“ƒÚÁŒ­âw&uL’ç&-~R†·2ÒŽ; ®Ø(õ¼¿«Ê«â·ÿ²Ô>%¿ý•ºËv*uÎ�^˜6cfö®¾Üþ»�'µB¿q�h2ËD 2¿µÉ½Élï¤\“«–œo”¥€òVjÃMõÁ숿dÄ&‘þo-¤ÔŽgÕʘö‚)µª·JÝ7Ô)§t+¥UJ-£WÒXgÁŠ[°DQj<.�U´¼aêBJ�Ñ{ÌdÒO©cZñåŽÙ–×´µº¿ ïÕ¬ïŒd§­ù[_­Ñá¥@© l•Z-&[+”úˆ>üŒŒ‰`Q•Úñ¬…Vêøm,'•ºkLÓTê)ã4´þqF;Pb”:T©—³:™ŸSûÍ¥ö1ê¥ËMo‰û)uJËŽ£’Øi¹ðH̩ڽáÏÌtæ£ÚÉ~«•íqS©ù‰ ¥@© Œ•ú v\ÞÛ.”ºM³¯~U©ÏZp¥NŒh#;ĨzDs,÷)õ*ÁÂ+uu�Ìïe SWWGŒR?ä¯ÔÉa-æ«Ô"ñ»ø"½“j&ôá¤ó‹+ì·õÜäQµ¸×”Y£LSõ¥@© L•ú°*ê•J�4Jï¦zú|”: ÔŽg-¸R‹šä"P•T¥¾õC(õm‡<§¾Ê“A±J½&JÅï2›Kí[ž¬&z”:~Äý#”¡Ô=úŸ}Å_êL®¶£¥Þ™Jž:\ðyƒö꙾#GZq”¥” "”zTÓö$ãÉcj­mJwÔØ!m·[©SúÈ6ã¯ÔŽg-¼RËšEb®ôÎL<1˜øÝ¦k@2ž×´>F;Pb”zu‘‹h-•RW•¼.õÚÀ(µ¡ÔºfïÓÔ2zKEëÖÀMGHü@©Pj(o¥*µN]¨¥R'Eõ]ýžPd§Rëö¬Muø+µýY‹ Ôº²‹QõM«;4¬F©e@kdÊœ„ U©òæ}û+õrÎ¥ŽZò;zâ·¿RkÛ«a•Cú åS €R ÔPŽJ�5fG×…x²¥K*u<6$–†=&g?:•ºo@Êj§C©Õ=û³N©³Æ1âñT� T�šÔ¥ºö°±f¶W©ãµ‡Å$Ì ƒ(5Jíuêê2)OVµª´(õšàÄo_¥>5¦ •I'R5ÏéÒ(5J e¨ÔyRYû�5–Møï–L†ŒlŸU²Rûý �-0¶Nä˜G ¡Ô55ÃÔKTž¬*¼à·ÏºÔkJŒRg“£= >7€R Ô(u…‰#XF¥ŽTžÌg]ꪪòHü^¸¹ÔY>3€R Ô(5J Y©ò)O¶ºÌæR¨OVèÔk‹LüF©¥@©Pj” (¥.OV¥.Ûòd¥$~�hÔË”¥@©Qj€b”Ú¯<™ŸRW•×\jÿÄïš’Ë“%�‹Z`G{øÐJ €R Ô(5@J]ò\êe RGŽRGTêÔvÉ)>4€R Ô(5J U©£&~û.¢UnõÉ|Ö¥Ž<—¥@©Pj” d¥^SÜ\êe�J®ÔkJ(O€R Ô(5J P´R‡© Tü®*×ÄïÕ%,¢€R Ô(u1jð QŠRÿCÔŠße<™š(5 Ô(5 ÔË£Ôk•ºŒ×¥&J (5J K¦Ô+‘R¿#Î¥.—u©kd]j”¥@© è(µ'ñ{uD¥^"©Ž\� ¥”¥”`i£ÔQÖ¥®ZÖ(ux˜:l -æRJ €RJ °ˆQêµ”zyçR—Zñ›u©¥@©¥Xö(ue-¢E”Pj”Pj€%QêµÑòKü^µœ«hUG™L�RJ €RJ °üQêòª÷±<J (5J (5À²G©+6ñ›Šß€R Ô€R,¾R—my²NºˆQj@©Pj@©I©ý֥ޥ^µTR-!J½Ú§â7Qj@©Pj@©O©×©Ë¥â÷ªRçR£Ô€R Ô€R,‰R‡'~W/_Þ·¯RW¡Ô€R Ô€R,·RWü.TžlÉê“­Š4—Ú“øMÅo@©Pj@©–$J]¾FuYjŸ’ß(5 Ô(5 Ôe¥ÁãòXE˦F©¥@©¥XÊ(u¨R/gu2?§ö›KícÔ(5 Ô(5 ÔË¡ÔÕ2¿—1L]]1JMy2@©Pj˜—R�is(ÄPïÿÇuôH­ºÑW{øTbÞÍ•~‚™Þ¡\¡—/IÎï ûŽôfŠ;‰}éj¯Ð“X˜ÓYÒ7o9•zM”Šße6—Ú·‰€>yðàÁC„Â$ƒÞ³]÷;X@©G5mq§cž�¤·ÈKbžåº–2Jíuêê2)OVµª´(u¥Tü¾û’€R b·n�7n6¾üæ›§»�;¯Þºu–á ÔÁœûâ‹·��¼}ÿË·—úlÓïÞüòþ—iuçæ­[–ÔwŸžˆdÚ§ßz=`Ï�Mvø²€¥Qê…ÇPêcÚd¦”§�h‡¤ûµíÖ´Ã vŽ—ŸœÒ´]ÒD»&Kü �RýÂã©Ý©�’ÕH'áUêRN¨Šõå¬Ô55ÃÔKTž¬*¼à·ÏºÔk*+J�™½�¤ Ô"¾u{zæ%ÔŸü¸à%Õé[Ó3MŒ÷¥äíû÷ßuÚí—÷ï±ÄãôÍû¥Ôg¦§/¨‡Oú‘Þ™?þìó´÷)§?ú裷Ì;/&»ýG§½ûnúô#|YÀâ*u²/ç#`¹œ­šX2×—²;q¢OÙG²/fßÉõ”¤¥Ô»µÎ’þÛl‰\²N™÷ Côl_ÂO©kZ§qÚ4mwÀ…4ì²YÛ¤2³­-› 2ØZÝ©ëÛR}IßvcmIÇIÄNÑG©31÷gÀqu£)µë ±îy_½çpɾԒ�û²<™ÏºÔUU呸]ñs©³s�€•ªÔ¯½ûîkÖ�7¦§U�ºQ ŸÅºÛ5:@©£(uó÷ïß\â“}W÷é›ï¼›vüÖü¹Ù›ÿ¬ÛíàŸˆ‡?7î½iíø–»åàM=nc‚/ XL¥Îî–óc“Ê*…ïѦ’G§ô�žÓ·Cì2Ø+Ç&õ»=ñmâ©S[l;��³�S;ÅSŽm“JmLQ®›‡Rë·çu‚IM“3zûú‡õÇŒÓt(õ”6l¥AhZLü{È”ÂþÀ†];J�8%ÎoJžà zù�ÆIä4͸dGd0WÆû†¨Cþ,�Wà<œ8õV1Q{jo*õC>åÉV—Ù\êõÉj�ºB*~Ÿ�;»¨í'ê»’X@™*õ»6cp9oþTÈôçŸ ±þ¨Qn»3=}’ Ô‘•ºá¥›7—ºÏܼÿ¯f`ü÷ædŸÈõ'2Rý‘Ó©'Ôog†RŸ–‰)o}"2TÞtŲƒ7é}l1Á—,¢RïšRʳC„I÷icú¿CZÝ1õà Ô¼œYµ«#®¶¨»­ÆSeFv®ÎØiŸh(ÑoÔÖ:fSêÉùE©�Îëu}›±ê¶ÆZ;Us›.EûZs½ƒª¶Øº½¯OzÑÑÑ\¯¦ ëÓwÚÞÓ×1(¢Ÿ"ß[ÏíÝ­D:›=¨»e¶„‘±)r¹ƒ*„\ú *}LNic½}}ú3¶º”z¿w¶¶GýöUêMÛQŸ¯»~m²#ÚT63O¢CÓd€6&·ê»ÚŸÛȈû¬îñmæK?¥¿ÔT¢§_¸r¾]½%møpýh,¯ÔÚÔñ¾Ö}šV—u+u2«¿ÔãÙlÒTê-òͪ×_×HÒ{u£)µã)ŽCþ, ¥vNœzÝx.wXÿ³´ÁÂRË“ù)uUyÍ¥öOü®©Ìòd·g3‹×xê¨ú¹Ê_©ÿ8=ýª9~þ´Ù p©t|zúOiF|€R—±R§ïß¿oNc~uzú�òÆçVonøÔ©¿ŸË¹ÑŸ˜J-~IS3¥'>våw‡lÊèÍ»/_°HJ= ¬©)™élë1ñà6·2Ô*7)kŒ å°{é†Ô'=%w™ÀYÝèDä'³C›ï\jM¾ÖÝlPJaé'¨ô±¯¿_æ·¨ùÉv¥îõÖìòŠ£OþJ½§ÿ˜Lÿ6f€›³‰ÕIÄŒÌï^ñü”!²I]G‚ºFw™/}D]ÈÔ@¯­]½ÅáÑxþ ¥nw;dðÛ©Ôù¹ÔÖé�aº=ʰ]W×:¡ÁVE›ï•q½!¶ƒu–FœÝy8qê}F캯•ºä¹ÔË¤Ž¥®¥þjfñÚÞ6©  .ÿ‹©Ôñ“'õñuÓko¿v2?Àýí+çÞ>—U÷Ó'Oþåþý¿œ<)·¿0mä}‹°ÖËjïn+Ïóöôô(#>@©C•:þÊÛo¿Ödï…»¡¹Ë‹çÞ~IÍ‚~éÜÛÆ¾Í'O&EG=÷ök/ÚùÅ“'u¥~éäI¹çÝééÿ1 3KнõøãÛNù¾¶”úÓ¼ë�}dq!›ôo‹OÜׂ/ X¥V¡Á.阖±¶¾4(eÊЧ#2º:dÄX[ Ok•qi}'KêÚ¢ÛÔ^ÓáRóWjƒ]õ¥.úÍ$ç¸y^§\J½Å«t^qôiØW©MtmÌx”Ú8mýO§\ZÉp½ãøv¥Öß›#y¥ž²yŸM©�rj–R«éÚym•ºÞÜš˜ÒŽy¯®ç�˜ò½2®7Äöap)µëpú©ï0ÏmigS/dâ·ï"ZåVŸÌg]ê2Rê½÷’fï,ÞA÷��JìÔz‘ €åPê¿Þ¿îÅ/d `sRgÓ;_Êû_Ê F'dO×|Ë6hþÔ0[Yá(µ¿R§ßý2ß»DÈÛQº¡Úå¤Üå‹×šÏ©�eÌûÅû÷ÿÜðšñìÃw¾iöæ/„IßšžŽ©ó믧óJ­¢ÔÉ3â¡O>~«¹ÁRêôÇ�?þzÞ“ψÇÎ$ƒ6™œv%“óe‹§Ô†ŤcZƪ⥻„>%dz² O&Vs¢Ç5MfrçŒY¹ÛmͶ¦'ŽÌ[©÷éìSiÙ%Ÿ M©c}­{Ç•sÚ•ú¸wá,�8ú5¤ÔÉÜhýþ:u¦.¥®•nž’wDZÇ¥8û)õyõÒE*÷žÖ¤W©[\Jm¼y©Â•z‹õ#À€vÀsu£*µí)®ƒK©]‡‹mq5—v2u‘J½¦¸¹ÔË:•:\©×ø–'»{ÏÀxwnÊ;w‹½ªgoÍÎÎÜšã»7£o¾çW‰~& ¿;5wwñ>­ú‰v?ÀÒ+õ»_˜Ãl9˜Ѻ{ÿæ n¥¾m–3úÔw²ôúÌôôL3C>@©•úKjo¦JÞ �»œ|ÛÜö®¡Ô¿3øóÉÐ�JóK¾6{öÙ™™[úÆ7'Œ°óç¦+Ÿ0vlVÙ)é[33gý7Y¼©Á»íuÏø²€ÅQj³(V�ˆsZÕ¿Ôc;… õYª£TÉܪ+à6K,Ûœ>´Ã’±£ ´ˆVnÄ–ý\ š6›2Êey”ºÖÆöWj¿†ý•º¾ß4P¥NNŠ£1ªŠçòWê!)Âê¥'Ê=ûk“.¥îu)µa-2¹<\©¬7ë°œaùI_õׇÁ¥Ô®ÃY§¾­L•:8L] âwU¹&~¯ö]Dë­9ÁÌ]C©ïÎê÷f‹ÕÙ{²‘¹YÿeÝÏÏÎÝ9þÎÜìyϦ3s÷ü[ì™[Üä…¤cÂ,©RëÃëw_;'ÆÚb9¹jíïþNŽÈo674�›nž;wN$¨ÎS©Åª8ŸÛÌ�Ë‘y|š2¾€R‡)µèUïžûëŸõ¿ï8”:¼»Ü|ûÜ_ÅRÖ_ê·^{W4ò‚Têû_Þÿâ¯çäÎ_¤Ãv~åÜ9ýïÛçΉ e¿7§RÛøüñÇ�’Ü333=棦R‹®þ¼ù úhÕ÷»ã¿©Áö£Ûé Q üãO­%«ù²€rVê>Gˆu”ZfhþJ�K:Muð*u«¦íZ0¥Þ"‹\�ôWjýªtŠýwÈch# m䔿R�Ȩ¸QÜ+ÓºK–Ó–°—T©¾2ÖräQêˆZñ»Œ'SGŒRë-\8¯—ÉÙ¹™b Æ]˜›ûêöŒhÇï™m³j‰é»s³žÀðݹQÿ&ÏÏ�YÔ�A�gÁ{X:¥¾ù[XËÕ¾¨FýïZ›ÎÉ©FQ¥´> –!3±*ކzYL«øÓ­ééÿfÈ(uˆR¿-{Ò*mSêÝPüý‹Ðå×D#–}Rï~ÑŠyË5§ß ÝY–'3BÓ¹×ݧßúÔª1v[Wåœ[©íó=ŒxvNßï¶ÿ¦ûÓÍU©-ÕæËE©}¿í‚äÍ«öË„Q¹+/K •øm‰Ü”8Õ’OÐÐGýĶ‹Rß ¯R'‡m‹FõõöÆlâ8E©GòJ­ljÔ¨`æ§ÔºÚæRÊk·8æ^û½ðœ\ÔÙZ‚J·êÜ–:õšC”Ú•øÝ%ïÕGKü.B©G|”Úõa(˜ø]ÞJ½6P©Ëx]ê¢ÔúçjÚ¡Â‰Ù Ë $5;£÷û„Uû…–ïÌ͘-ßvo›ªë}onÁƒÈ»ÆâðÇ�VXJ¥þRUJJÿùþýW¾0‚b*PvÓ©Ô/LOÿIm{<_ÏHÔó}|B Ã)9(u¨RÿUÝ|ñKÙ«òJ]¨þÕ@Ëäí?«[‘m¥þB�A³¾í‹æ°�íJ}לÆa†’f9{ç7Ín¥þÜ^üY�¬ùøoîdý7ÙïŠÂáŸ}lwj¾,`Q”Ú·<™Ã©<Õ¿üÄÒªHÕÚ;¾ åÉåó3�Íç•>ŽhS #$íVjý­ÁubP›Ô¯Ë1£¥ÄdˆR»v’J]ozb¿©ÔS¥ÎLi§ŽÈCˆ ßúÂÅŠT¥×uX¾f³]¥¶—'Ë™aãã–R׿OÇ[ž¬°R\™übû0XgTž¬Œ•ú¡ˆ‹h-§RG^D«àºÔtοgçn{I練vbfÎwôìÜWêÆÌœ»Š÷«î¼ïŒiØ·¦ ›|[[,žÜßÑÛ£ÞØúŽ#9� grûOíÏ%Toì1»ý~`¹”ú¦q󦈆‰©ÓIã�—ôÛq‡RǦ§gTD˲hïÕ�{ÓÓgòJ¬ÔæVïÊùÌy¥.Ô õ]þb=ó/V{UJ}ÎØù¤ ~ïlWjgw5”ú³·ÌéÕÍÎ0³øû»*nÜQûùn2øL¨ú‰††ç_þÈZÅž/ X¥V¥¢]‹h9ɳF•ŸXî1$.7,ËZDk`¡”:3$�«ô4•Z.~œðIü1n£ætfŸZ¦û¸Q�»W Qj×NR©»” w•J=`$b[5Ò¶h�ý*ç>fäpÇ[»|^x¬SÓ“¦�æFFZŒ˜}¿­]¥¶/¢•ÖÊÃO)�í3¦mçÑ‘ûü"Z…•:àÊOq~¬³Ì/¢e;\å%~¯Ž¨ÔK$Õ‘«“Vêäìœ)½2¦|¶ØKšIš‘e¿(ufvn6eÜp+µ+ï;ñÎìÓÃÿXð°zw=Õ5)§Cèj½O s§ë½<"·kÃú‡-³M’4³_r8Àr)õ»ù›o‹DÑ/­e{ŒRIy¥¶Ö±}Þ¥ÎûõÝééwòJ¨Ô_˜·EOk¶—'+Ð ÿj¤ŒÛûã9K©ÍYÉi•Þ¼³]©ÿ舟þüóO>ÊûÑ„çÄC¢Ô6‹ŒRç§Vwë7?jæËQ©µcõ¹Úå�¾ÆºM±Ã=¹ÞAÛôËØMÛÞ“;Ò©rŒu]©ÍuÓæ¿ˆV—Ní)ýàÃÛæs‚Vâ÷±žTk¿Oy²x|»¦�íË%³]úQÇb*–} 5•£ƒ•Úµ“™ø]7˵ŒJ­_ŽÝ¢¸°¥Ô91¼WqX\ªl®cXE­­>¸ÿþÚS»Å쳄4£¿Æ–l&»K‰¨Ù®ŸROµäzD}pqª‡ô7'kU»[Uî@]K_Ò<�-òÍj2ä>ŠR\ã)ÞƒæŒW{ÌO©E$Ü�K‹Í36—Úµ“*O¶]=6< ”ºU¶i_ÉKaƒj(Ÿ1Gûc­þ/|$k“彿£ý)[»>J½ÏØO6Ú6¬î ÷廳ß:��æ%ŽÅ#*uÀ•ñ¼!òÃ`ž¥™ºî8\ÅÌ¥^S¶s©K­øí]—:«+õm+nPí;uÆEÊ'ýŽy»çÖ¬(#ž0Ëo'âÉOݳ¶¹›¶{_ÍÍÞžS•Ìô-ª©äݙٹÙ[¯úœPB|º‡�Žwˆº}ƒzçîmÝÜþiê.½·mïͽúy—Jà€åWê·ícy}xþ;Ǩü�éé;>`6+~‹Qò†|€R*µ˜m’¸”Ú§†*õ—ö�ß.B©ÏxÎñôãùõ¥=J-Êz7{cÏ6ÙÉ/_Í—,‚Rk‡³r§�)1–QEC¥†Œmrå¦J}Ì­µF:oΤöí�þWkŒ»¥(îÞ¶])õ±ËêZ!§]ó<Á¤ÊÏ ›>œTJ=,»Î³_¯nÈñ'ä’[sešuÀ+wîÔ¢ªoÉAýH›>”—â¼·ßTjcýè#ærÌúóËÞÇr>/¼näh«DS/=žë1xJ=j´›²jl«½ÄIg`æ’Ëõd˨¡Ô±íu†RËÓIl™²��çê'ÔïÐß+c=Åùa0ÎÒxÎÃY§3&xWb”º²Ñ ŽRÇïÌÍÍÆ -ž  ßžsá)5vϲñÌ]]§ï ©N‰ås_eoÍ͸-ü朽 Àù Iè–�ð¼Ê?33wûîWs~ËoÉò7™û1läaȺ&ƒšñãÙÍù9Ö?”[P €²‰R[©©Í_ÊJI¶Qù™éé[Þ0T>>å¬w€R»”Ú2å“¢Ôîn¥6gh‹ºf‘£Ô·§§ßðžäg>:l*µˆ1gÌóúرøtÈ&wóoñe‹¥Ô*”Ë% îÒËDh'QT« H¤TBç8K7¹úÚz‡Jdû"¼ ¿�b}oHn >j&Û—�^Ö8ã8Zp»ú~¶K’ìËÚ¯O"µÕ±ï¶¾¢ß­ð+ãú08ϲ”Ã-—R¯�°ˆ–_â÷ªå\E«:Êdj¥î™3s²ÏÎÝ ¸ngïºpM¹NÞ››»`¼Ýænéïó]¥eõ±Ü¬tð{IOXÛSƒìÌœ¹à–!ã­Êæg³ž:¢‰•âÌ¢Tz·æøoÒ¬‰·µ££Åñä¢,#”ƒR¿bK"}Á3—ú¤YžLhôg¶ñ¶¡×T”:T©ÿlÞþ�k.u¡n®Ô/™Aàû²ÄíJ}Óì®™×_Ÿ°ëó§AJ-bÌf … {‰ÂÐMݧO[…DûM¾,`Q•`²�Qêòª÷±<™�RÇgÌ¥©oͽQÒUÍÞ‘Ú|KZsÊu‹Œo•Ø1-6zÊž�ú$™ÿQ�È�Y%ÖRɳ>1q1‘ÀHÞÞ£iSꇣãš#¡{JÓ’|äÊ[©_° ÏÍIùQy|zzºÙŠIƒæî|HêÎôô« ù¥Tj±è´ÙÝn6)µO7 Wj£™,þBT¥¶âÄoZ5ÃTù“ ¥Ù)¦onŸ<ºI7ì�»m¶ý2_€R”m”ºb¿r+õ;ºñŠÜ꬧&wT¥¾÷Õ¬• ~wn¶MpÁôèä-¦¾àzÒ½9ïé6u"3·T�ú‚lH7~ïyujæ:X­é;åÂí©}‡z¥b“õúb|èÊY©Å\Ì/~«¢c_Å”òëð¤u¥Vkû4d  ÿ` ˜›g¦§_bÈ(u°RßL[îûv RûtÃp¥þR•ünúÂZÄ:‚R¿3=}Óò\{„ù­@¥~Óú)-ó±+AÜgS·ºŸÎ7Ù¬·ôqš/ @©–U©Ë¶3ó›€Öš_~ó­·N›;ffÆ65¤óÏê~ý-}S#_€R,”º|�:ê²Ô>%¿}”ZxðÜÜ;fŒztfnöÂ…Yg¦vAÆçfS*â­VÑŠÇf[ÅRÓ·­ ¶M©ïÙCÖvÎξ³sÆÂÖúÎ_Åô‡ï\¸e®OÓ4MÅÐÖúÔB³mËM�LMÉéC(5@¹+u0oä3¿=¼C*' ÔK΋¶Õ®‹£ùV`¨8;3s/R÷ffb%š/ @©*&J-‚Ç届–7L®Ô¢¶˜-_ûŽ(4vFÔ,+‚[*ð,œXÆ·³3¢z·5µú¼ýAyßÊg„æßNèÖ|A$”;ÒÉ»4mPÝêÓ´á„K³M‘“®ÝVg%‰@Å)uó�À:½é[Ó3M ø¥®¥n83=}×ËÙ™™³‘šøjæ«æâÌ— ÔË¥Uêå¬NæçÔ~s©}ŒÚW©uó5CÂqiNü•¬à]08=sG윹;7�4ÔZšoϨ°÷]U<ž¹e¯~v6(ï[VúVËm�Êå³îÜÑ¥\oxnÚ¶ÏaMÛ¥nÑ´CêV½¦°íÒ&ê’ÚÒ!V§žLñɨP¥¹¢7ý·üÞž€R—½R7Ü›ž>黡wf&É�gfî–p\¾,¥('¥®.�ù½ŒaêêêˆQjŸòdÒ|sn¥¾m¥‚‡!‚É_]¸;3wÇ#gg�…¶ä$êäWs³ç“ñØ)ÆùdƒÚË̘ âwÍU©ÅÉ8”º_ÓZÔ­£š¶ÏÒìcövj‡5ƒ‘|€ŠUj±Ž–o®hÓÌô™ (u%)uâO9îÙ–Ð ý‰mf¦µøÃòe(5Àr(õš(¿Ël.µoy²šˆQêxjöVÜ«ÔQ¿Ï+í�É/«•¼#º«fbgîŠJgs³wö øLHØÛÒí³RÎg¤;”zJÓŒSÑ4c©­Ý–f›oäÀ”ê}I>÷¬Ôñ»wßð{<{÷nŒá ÔKMÓ_ÿúnÉO>{÷®ov˽½‘žŸºw¯„Ï— ÔË¥^]ä"ZK¥ÔU%¯K½6 Ju(µ¬Ý=IFcoŒïÍ9 ™¥Î^hµMœÎíÝ{&aßž¸"ë™|U´Ì™wÎMkqùv�ö%øÐT¶R@9)5J €RVꇼyßþJ½œs©£–üŽšøí䶘÷|Ö˜Ó¼ôo’ÏcɹY‚Í(5 Ô(5@%E©½N]]&åɪV•¥¨øíQêÙ™3s»�™››iåó €R0ȧ·”…R�is(ÄPoyÿ·ºôÌôå ½üÒŽf´\ ­Š¹Ä(u¸R×ÔD S/Qy²ªð‚ß>ëR¯)2J=zf”¨0 Ô(5Jí˘Y#W1¢i=eõßæSš¶Sg¨×Ô—~‚õšÖþòOí”ìëíÉu9Œ–]—2ˆ"^AßÑ�¶»É¡£G™ ºäJ©<™ÏºÔUU呸]Â\j·RóY”¥@©+T©GÌÅo´©Üb+µíX-™ÀË;|8WŠR×n)öwé§b“¼Zý.ÑÂ¥Uê‡|Ê“­.³¹Ôê“Õ:õÚH‰ßwÌu¬Pj”¥.¤Ô¹¡#åõßf]@vÔé69Ù7¯ÌôîÉRêɃ: ¤z t9F5m¿oË”ú 6Xì%J½Å©ü(õ’+upy²šð(uÙ–'+&ñ;y~vîN (5J €RGSê²cD;$­µm·¦^øæ]J-�Ouèîz4è)^¥Žv)M¥.¡ÔSVªwŸ†R/¹Rû•'óSêªòšKíŸø]SBy²äY�>>,€R Ô(uˆS&ûr>ª–ËÙ&î&s}){ÍßDŸ²�d_¬Ð£™mmYÛS�Ïp&H©õ§Õi#ó?AuBYk�Z_¥V)ÖõŽç$úÌ×àTêX[2Â¥ôWj÷){.…Pjm¯yoȦÔóº¦P”R—<—zƒÔ‘£Ô¿Wwßá Ô+W©O\¹xåDóž[ãÄB·PÖJ�Ý-\mHÊÚamRÿw�6•<:¥?x,eHwˆ]{å±õؤ~·'¾M%íU-Þk»WWÑíÞÄ*uî 6œ›× *ñMNic½}}ú3¶†)µîämæÑ’ÃÚ�ÖĶ#¢°w2»_o'›M ¥Ö†×�ÆòJí¸”N¥ŽeG´©l6f¶ésÊÞK¡+µnÞÛÕ�N­\)õ|¯)¥ÔÁaê¿«Ê5ñ{uQ‹h­Î.rQó\³Ñ¥ž7'Ô¥X`¥ž=ëòÅKô?Wƒ;�íÞ¥óJmJ´TêfáÜ^»tùýï�‰††Œó R©õÃåD©áPêSMMÉõš,c=&ܦҟ‡ =Óõn2#ïîw{mÑ´¾ GSš6",0©+ž®µ{ú�‰{ 5/Úu˜¥ÖDnÝ<[ãñùœ ß¾þ~99¹EM–TêSšÖe­Þ˜ÐÜÛߟÌÏ¥Ö•zX-Ø›Wjû¥t*u~.µõ \§ìs)t¥Þ6¤MÊÈt�~BJ©ç}M!ºRÿCÔŠße<™š(u!.Ìe±õävÍü] ¥.™‹b ¾¥Xh¥nÖUY&^ÇÅ�tP§ è‚éÒÃÅsÅV¥Ô"ì}­[>KÜrõå�ß×÷J{6T¶R'M}«·ù^›aƒƒR5 9<"³�‡Œ\dÝJ¥å¶JãôT·Q¥�õRkMöhZÆs˜ ¥6ØUïÒ¢OÐ_ÝKO…)µ~9ŽØ”ÚVlܦԻãN¥v\Êp¥öž²Ï¥JÝ§ÂØñcÚTB)õ¼¯)¥Ôk•ºŒ×¥&J] ·g3‹×x×”´HJ»qå2J °ÐJ-üwBÅ¡uk¾Ð邺 änaÓ—O˜J­ïv-mmߨíãà ñ�ßãýƒI© µ‹IÇ´ŒUMÄÝ¥MÅã +Æ¢ônȨ¯¥ žŒíää€ÑÿQìmŒKEþ™­ß_'àd™ÚL|¯¶ƒÞ(õ<¹x”1XP¥ÅÉ2Æíf{�2g§óï‚�† 7ʵ²,¥¾´qã5cIê«VpÅu#H-6ˆ$óÆFÞDx@”Ú7ñÛîeÞ$åèJ½ÅXöÉÒÇ©Q£`XÑJŸ§Zú *ñ=¬ï+J}'•:'—�¶”Zœ{—�ÖT¨Rû'~�DJüTjý”‡“õ2h®”zÞ׊ŠR¯� ÔË;—ºÔŠßÎu©/ÜšÌÜ5>]wgõ{³EÊfâΜÂÜø™Ù¹[wÿ87w'é{ÿü\ž[>Û=í©ý´M©Í&¾R÷fçîœ?gnö¼çÜÎÌÝó?éž¹½‹úAÛ'ë6 Ô.ºÿ¯‹—#ĪQj€”:¤· ç}Þ¼ó¾§‹9;�» An¶îYJ�3«å­+œùÝ�Li¿¸qã•—u%ÿð½+¼�ð (µoy2‡—yJiEWê.³Z–¤Þ´Ðþ”ZwÇcó9A%¾#Ú”œkܪԱ)µ^´M©ãRÇ»¤R×(µãR3Î"1i*õT^©ƒNÙO©³ú�¤á+¥ž÷5…�RWÖ"ZA¿ï ‡Î/gžœ�›IyMoê-Ì7Vzà †0{îÏØ”ú¼Ïvw{ŠÛsy¥NÌO—ë`µÍªïÎͶ¹Ïín^Ã�œŸ;³¨´~U&¥v òÿ_(5Àb)upoÓÕöëÎ{ž ΡJ�d§R7\ù@oõòõK¢øµ´¯ƒ_Òå\Ø ²•ZÕ­v-¢åð2Ï‚OÑ•:f,øoì2Ø!Ó6KHüÎ É\éÒOÐTê:¹äThâw¬SÓ“–þîé—ªU«i=2¬< ÔŽKyÜ(ÌÝ«©fä£�‹h+µþÌ)u,¥Ôó¾¦P”R¯�°ˆ–_â÷ªå\E«:Êdj·Rg¦u�ÍK´.«£E^Ò3s³ç3ñ„tsy-¿š›‘áå?Êëºß67{ûÂy�nÉ)ïvO{’³s6¥>?wç®à‚|Þ�¹óÜo»On:¨®÷½¹ÄB¶v ¶¨Ë:)²[PjÏ ÿÿs�R,–R÷¶ëöŬtɽ\„R_Ï'x;•º!}Ù°å W›ý\íðþµYo¥ÖŽÕçjEeíx€±nÓ�îpO®wPÅg‹QjÙ©Íæ:†Åòʺ{Ö�Çr-cÅ(µÖ¥S{J?øð¶ùœ •ø}¬'ÕÚï_žlpÿþýµ§vë'ûòú««ôHk2Ù5¥Medííº–¾¤¯RÛ/e«¦hMåÄTg©Ô{tãnµægœ²¯Rë-©¸Rêy_SXø(uyÕûŽXžÌ³.õ]UÇmæz«ØKzwöŒ£¡³ft¹unn&á½{ö¬¥µ·|öw·§Þ·ÙÙK©³³öHú¬‘ÿŸ™sWñ~Õ�÷�1 ûÖtÁÖצ!ôõžÚ/?!‰¾ÚŽVo?ÙÚÒÒš2~oìQ"Ö³”z¡@©JRê}ݳ²U˜R»‚Ô6¥n¼~ÃŒ@_žðwpÀ¾œihx~BܺÈ[ ¯Ô»Œ Ø3AJ-B© -J©3G�§Ž‰ÜÇíêöð@1Jm2Õ7¯Tâ›3^í1_¥¶Q‹Þ¨£%Í ÃûU§,Tæ£ÔŽK™9fœ¶ün•eĬdrÿSöUêÌ 7”z¾×NFåýCzŸÍl“(ë®ÕvÑÙ¥.Ž‹—�\B©I©ç¥¾ä Rç•:-,yÃ{—.‹¿óS¥»?Ì;x~¡­îkŽÙ©ÔÃÚá¬\•i§‰Ö†e@Õб!ãF›(Í¥P in­52™ucÝô¨>r=\'V.@oÒ9ÒÖ¡iŸÃ„(õஎyž`R��³bà;|8©”zX.ví¿]ëRgu¥¾mEuª}§Î¸ðùôén.~šUEÇdÈ[4ì¾oÛ_&™‡l—퉷Ddz[Jm”û¾kö#‘!~;OÎx*«µÍÝ´‡Óçf-Ko›SKv%ïÎÌÎÍÞzÕç%wÈÔ•SµbNÈÔ°6x¸VdŠØ´JNŠ !­=“j±ÇÏ‚mt6@©Qj€òTjQñÛ _+¦â·;Hm)õ ÛZ\�ùh´×Á Ò�TšR Ô…Ñ 5êåLü^Uê\j¯R “5ê€efgB¶·ç\Üöî3£BÜù|í{2¥Ü}ßú‰hVimÐv³½x<13×Ï+µY1|&k˜­¨ÿýUöÖÜŒÛóoÎÙÅöü…¤þZU˜ú¼jëÌÌÜí»_Íù-¿%j j{Ä ÈÙâibÂE.¿Ç~M›”×kÛ°æ,ð�t,z€RG¡û„“ J °HJ-BÄf#Žu© )u“ggS©/nÜxÃrm[b¹ÇÁm&Ïdj@©V‚R‡'~W/_Þ·¯RW•¦Ô=s¦Ôž�»pÝÎÞuá�rmÜÖ ]Uðþ•÷¾És³'ýöw·gÆÎ-¥N½zö®ÔêٔĖŠ}Ïm±™YO ²3sæ‚[I%ã­ê¸³YÏë™2ªùËŠ#ò sš\+ϤE3× ¨ïèès„ÇÍõòPj'�¯»è޽F©ŠWê�Þ&BÄWlNœ‰ªÔ^A6•Ú1#ûŠþ`£:W»ƒ7^¹’Ïõþ€(5 Ô¶RWü.TžlÉê“­Š4—Ú“øí©ø­Â¾jiê[so”~i/Š+V¿RõÆnÉ`¶û¾‰‘÷¸Ýl/>* �ç•Z²wZšù@nÚZ¤ÚΨOûÕK½3«}Ï�woÔ}›f¬ˆ'*(¨eée…Û9Œk«O§Ô¬K °TJÖÛÞË ð%ûÕ”:î�hÛ”Ú¥6Ê€;|Â2톆 s©¥X!Qêò5ê¨ËRû”üö(õ;sj:sÖS1»NÎÓ”EölNÕ ³2úí¾o…��)ÔÛóíMÏæâ¥S§­’·d˜ú‚ë”îÍyçH·©—:sKùB›@oÊóÊ÷jæ:XmÆzvj�,]óSûõfŒ µ¶»5A·@©*J©¯ZBß`ô°Æ…•Ú'‹ÛTê«®¹Ô×,qÎ;x:¿rV³Pð4ï% ÔD©½>]U¿}ÂÔ!J-¤vFm/]·dÊ…gªð½¹?õÂÎ G¾sGfcŸ÷¹¯è1‹ol·Ú»m<èRj]µM‰ŽÍÌݾíuê̬ß/·D˜:!ÃÓ¯Úæ†Ïº÷Û§iGÕ­^ͨß/V¸š½ÇŒN–Õ¾'‡rt,@©#òÓ/» ñ`‘”:¬·5¿¿qãûqÃ~7ˆÈñÕ7^KPêŒ7Hm)uú†£â·¡Î—�~ÉÚ n]â­”`%D©C•z9«“ù9µß\j£ö*µÌ½�'fgkj,OÖj+·ýª ÏÞ¾g.Yå¾o(ó­ ýí��›}U¢ïtþÕ3ö8²qÉ™¹¯ò58s¿G}Ë—� o?#í[oàlàOýÖô»4s%{]¡ÅrÓb‰ê-ò�ZcUú=Dª¥Ž/Öà¥(I©C³�7\ºxý†)¹×lº¤Ô—}J�YëR_٠ߺa®K­ôü„ËÁ»…l_»tñ²ø{™ 5 Ô+S©« d~/c˜ºº:b”ú!�RÇfżäq¿2Þ¦¾Þs1îÜž�uøJ½q&#¦hß ¸oËûößžoïŽSåSö(ôÜ•œÏ‰}EúúLÆ7?Sï•eÉ.˜“¸}È kæ:Xƒr�{›fwä 'ºvM §ÞG×”¥¨¥º T°Xˆð•p¥>á¤Î+uÉkù5ðÞKû;xw~ŒPj€\©×D©ø]fs©}Ë“ÕDŠRË töV~É©ÄÞTrïxô•ÏS3³žu˜Ïêmž ¼?:ç‰Û·ÛÚ VêøW2 �œ5²¶Eœ:g7nÿ™á­ssçïÎÅ”RÛãØ¹óñÖ³¦“÷鞬BÏ[õ[Æc“J³{÷Ùê{'zë4ÖÌ”¥¨(¥n¸¢ìöƒ«Êy¯|°ñrs¸Rû®‡%’ÁŸW7Ó—nBm¸y·×ÁÓÆô.=Ï (5ÀʈR¯.r­¥Rꪒץ^ë¥E»æþh•èJÞœ�Û+&8�F¼ªÉ™YOåëÌŒSX]÷侀ÿv{{­ç Dûüy{†õŒLô~Õªüý•#óû ß¼où´iUðûl>Ó<63zknú^¾�qÍ\«UÓ¦ŒO†¥ÙNFõÇûè[€R@)uCóÄÕ‹'¬XqºqšYM SûWüŽÇS³·â^¥Ž�ø}×^�[ºÏÞž™›½�wO÷}Î'Y»¶{Ús+õIåÜ·òç–¹+j©ÍÍÞMØÃî3ÁçK³Íã>=µc”Ž(5ƒ|”¥@©-¥.OV¥.Ûòd¿uÍu(µãÎÌ–2C¸íÂÞW“!÷å5¾°7t{8¯Ž��:øÊäöî=ã(Æ�¸â¹™|ݵ̙wÎçÔ=c-®¢Hô�ÆèU(5J °â”züˆc ÙÜPïbÿ×¶¯öð©DÉÏ.ý3½C¹B/?â+8Ò›)öŠÊG}O¡lY‚ÏBù+µ_y2?¥®*¯¹Ôþ‰ß5ÑÊ“¹¸-f%Ÿ5f?ˆŸÇ’s³Ô@©Pj”:’R�iûìwG4­gqÿc{J¤G¦ŠÙ}§ÎPïhrž'X¯iýá/ß8ÖžýbMÇÍ •E\Qù¨ï)x^ñÑ�vïÞ»óhW Ö¿3O©n°øŸ…ÊPê’çR/c�:r”:’RÏÎÌX“•W£3ss3­˜J €R Ôe¨Ô­ºPŠny#VÕŸ©Üb+uþXýÉÅTêØáÃ!ÁêNM²ÅÖhÎö¢Ñ¥å)2Õ:;”ºˆÄoßE´Ê­>™ÏºÔ‘”zôÌ(1[@©Pj”:Šæ†Ž,îk;¬Uh"+õÀÀÀŽ:] 'ûæu‚™Þ=¹‚J½cÇŽƒbœ‘äB)µqÂòQãF5mè+¶-l+~‚(M©G¤Š{ªuv‹þY¨0¥^SÜ\êe�J®Ôk ”'ó(5Ž(5J €RGÀE瘫Pna¥>$}¸m·¦^øÓq)µY!ãwK£ü>Za-7Oœ B”(5Pj¿êéYCሆáÈ"¦Ù˜Ó…£YazÖi!ÉtÖ�d£®5휹 MuJMOÔN Ûo ÙÊh9¥Öô"ÉÙõÞú…RGœ{«ôõhuJmõQ±•ÚqÞ®´ãrcY½Z¥Ö�?ªdÄz§h�·oÝ=¿¯•úa3~7ðdêmE©õ/_o݇S Ô@©€R+uúó61¿y�lÐÿŽ‘¢¾T¤W¤geϰ"¹ Ãö®lз£Z;´Ø&·FÏo°™Ò|˜hŒ�Õ‰AúvLO¶²ª ÌL7ÄìÞö”š¾Êm«�:!½¼èxž5§µŒRk“<ƒ­'6“'EoýL©WÙÙ;äÙ=Uú{TŠ6kB«œâ<¡­X#¼§_­ÌjÛf)µëÚ(ïüœXQWc�™îM)uÖ|·Ì§G³ŸMŠUP”«%×YÅzÍvëÌ–ûûÖÕóû_©�*u¯K½cQjý2% I@©€R¥Rê‘¢�¨3Iî’égIûŠØ˜ãÑHCª0ÐÄÞñ6%][ÏŠwLž#„,‰·#2½X�¥ÔµE©—¶Õ@ê³ç5ÛEÑ¥Îp©¥õ̱†{ë§J}Z¾çù»¼U*zÔRêóVé)mŠaÈ}¢if+¨²ŽÈPt‘U6é;GF¾Ù`ç�˜iÕf‚”ºÏ|7Ê_°ŸM^²ª‰“?¢¬£ufË}}ëêùý®Ôo†\D«žJz­ÐëRƒâéWè¥@©ØÿJMÈÊ�±ZÁPÓXéÆT$5(»=T'SF&'�í=�Ír[Z6¨Þå£bk.ctP¯Îé\ÛHn"=Äì²½5=:Ε,�ž#¹t:]½Rs$ol«�B©õ"¹˜Éfè§‚•zŒífŒ/öõyë?Ïìó|65I/-­¨RÑ£¥ÖÓT¥Ï§Óº¦oH žt¦å.�³mæ2cTí¹R»Ï¡çÉt*Ú³(ˆ¯ÓÅ¢¬‡GC+5i_5Œú�.*(,KlÀ¹Ý:ÙrEß:zþ D©}¿�†Tê=’êÐÙÉ Ô{Mòõt€R Ô¥žaÁÔX‘k�e¬+lc�ˆ|ÎJ}26xn±Y™¼kN–¢˜å[Û¹*Ÿåò‘Ñjjsl¯¥�ÕÏ¥&sssóTèr)MÛN…RgÇÇùhç^B:•:²Áb³³D5ýL©ûØû¾Þ•¯JE�:”Ú1[yVæ9+’9g+ÎFdHX§½Å•Ú}Ž>0[Ó2ãlµ¯‚èÒØÌxÆ©Ô)AL¥Ôù¬<–¿-rƒ_â{­ÖY]íé[gÏ„(u˜u©[ê¥.¦.·†V˜Œß fÒ[_£”¥`ÿ+µœÏ;ÄeÍÒ¨>©t9.yr¦ï"!ßkH½ã¢–â‚7kŽbÖ‹d…{¼œÜ�Ï ñ«A©%#.Ï«º�ºst5›O¼ ÔÑTNìÆé¯Ÿ*u›Bœ)Ó¬*=ªVêeÑg}f×™JM{išy«Ár�Mçèpe?/�¢/›c]êV•RŸ1ßNðÚÄœp}½mÙ§Ôþ¾uöüAˆR¡Ôõ�K]kÆïcPêÝåò®%K�v a©p¥àn Q”ZS„Ëše¬b¢ì›H%ä´(“å‚6+çB¯ÂÃÒw0ÓcYp8Ç«ƒ‹| 4[=+W£RORF …FÖÞ@[©#ÙÔĪÐbïºÔÓÓÓ|"ôR’ŸE,øå­ÿ¼5ªÚj‡«JE�ª•:™ã¡ÞI²¡»•:%Îpší°”Ú>Ç)–.cÈtdlüùXJ¯J©×5Ù1«<ˆÊq¨[©ý}ëìyD©›r-D©÷ˆ¯·Ò»SñhΜ”(5 þJ=+_µ“sŽì_bÛYæMY3‹SÂÓö^ªw=.¥¶OgÚ–‘J}v{J=/å† ïÐv(}VŸ•ÉÔJ-³~�%5ÇY¼õŸ·¦>gÄ�rO•ŠU+5›Å¬³|ßKš[©…kël»Pj÷9:D6±Iþ%†>Çß�·ê.¥ÒQ•R‹ŸM¿°3n9v+uPߊž?J}<Ä"Zª�߇깊Öá0“©¡Ô»Ìƒ×Éݨ6Æ2?æÐ½J ÀÝÀ¾Sê‹»ªÔì4³ÛWêt޹èàüŒZ©ÏS2Ù¤ƒ¥Ô¾*Ã+ušE~³Î¼bB©Ù˜õ4˾mH¥öœC‹œ/˜‰¹5-™igo ºS©Ë¦'s*õ ”zûQêÆÊ÷2=”z—ù}3L)£minf(|­=$·âú(5Pj@]•Z9ðÛéMþ±¿Qj9ðû ™ÖvA©iM…í4Pøì-ˆ9G•J=ï:·YO…�ß¾*Cüf3’gh‰bÒ«Ô±º²� Ÿ-�"Ÿ œªB©+¤'óU"=™™ŽŒ6QŸvæ“JÍ.lYäõæJí9‡dÁTe>4ïÈ•æVjÃ|b?¯Rê”Y‹žÉd­ HOv`•ºaÓ“Up겋h9¢ÔO•H?¼Çß<­ºWŸÞýú‰½sä×Íׯ7µzö2ݽùÀ1Ç8*Nôë=öÅ’þ«Í—f�/_ÿê8AŠÕ?p¼ù½ÐÓ'¥-EÓ—·¶–ƒÚá­×S^yÁfÀøîØVˆÞ;ϧš° $Ëcc«az8E=(³¥J h¥fì[DËåM¾u””z£G]vA©“³Üÿjo ©Ô|)æèL5J]~-_•Šu)u–XcÃõ<³ÂûN¥¦eŠB£¥R;Ï1Yç†ÒʆŒ…‚™n<@©“y±J—^T)uŒÈ”á³|¯Õº€E´–R«Ö¥¥>´WRÍO"J}T‘ñÛ¥þúþcó©Tꧯé»×Õ*õ'¯·î?ýqk뉬åË×[O¾üòÉÖk)È¿ò“l½¶?ž_Š-[¿;ß0î‹[äkÚÇòÎO黯²ê:žóWz%?~Ýç÷\½d)²¯¾zÝåUç1/yëWu_ŒnMTì¯è!gú´(mì˜ý{¡º™%(5Pj@#(5Yé0ZYfm-ÀX{¨‰-Œ™œˆ_*5ÉeŒý7ÛI¥&C”Öuzò|Ïvh ü^�¥ÆI5Jí©Ÿ)u±×e©¶{U*zÔ¥ÔÔaÛ{³B9FØhͯÔ¤n”Œß‡j�K}Ì3ðû)sL[Õô×[›Õ®Ô”Rúµ)Ä}¯ÅÒÌO·^óo¡èŽßl²ó˜5G_KUåëMm:”šKøßøîÎ6^æâþ«òxiñ¯SÊÖ=Ø2Ù×_½îòªóØMZVwÆ—[ŸTì0–i0mý®k ÙÍ£ž_@©€Rê©Ô#2•ô\2H©Y„R0 •Qêö™/›]wP©MŠÙm5Pø¬!¯v¥¥öÔOtR¾gOî¾*=êRjmÜÊ,ÆF]{¦QJ¥¦Ú,’ q¥vŸC7{%Ï*™0;h<¤Ô}yQbF©Ô,ý}k“‡”êùdkÓ¬‹iqìõ&ý�FYˆxÂòÎ'O_³ãú¶^?øúKµYþqŽ\Öï;”ú“­­ù¨ô-s}*×ñRŽï«˜º¼e*²¯þz]åUç±(åõþu«r(yŒÏgá]tÑ3^ÅÍÈ £Í->oPj”€QêVuz²=ËOv(Ô\jßÀo_Æï¯©B®:Œò~µ]J%ôkñ�ÛÚÚd>ùÚ'½ÉÝú©{G7·ÌÖÑ׉׼¾léè}G«,¥¾/UÝ0·¹�ã³_«�:òúõ¦Td_;|õºË+Îc3÷ŽûNš7âýR…îJ÷õÑs¶¯¯/Ú×7Eï²å¾>×G0iL­OQq¯2¤IŸ³¥J ¨·R‹ž†¡W,’�”]c•‡/“él¬NÄ+6оFtûõÓKµßûª¬Ô£ÑØ)YÐ4çj›­gÓIgc*þ�å}${²EëªîÛý¥n\£»,µ"å·[©õ×ΩÂOücœ+ñÀŒú&_sG¥ÿ¿¥/˜R'uS˜Í(õW®ÙË¯ÍØ5-ÿ¥C’MÍ�PçUÐú ÿñÜåƒbë÷·¾¼/wzÛá¯×]ÞϸïèW¯¿6¯æÇ Ý5o Áé°^�vì_#Dòv‡rd»‹åâÙ@©€Rö^©w{”4¨‚IB–Ñ û1JÍ‚Ç�±Š–?L¤Ô1çlGK[¯Ÿ|éÿ.å5¯ÚJMízÓ:ÓSÅñŽø·—/·žh÷=¾m¶ÃW¯·|P;™8¿v µ5x^·[�(¿%Ë›=Ýk)µ~Ö—¬�çÜ?‰iOâþPj”(5H·ŽÏ`sаQê²J]Ïìd*§VÍ¥VµW©ÓŽT`OƒÜ4ö‰Û4_o™Áå'¢"6”üATÓ7]™Î’¯·¾²™ñÔkˆŽqßN¥~b¦=còÿ@q<;ŸR_5ƒ�Üö(µÕ_½ÞòAídÓ¿ï9Þý¾õú�9ø½OV®?Ý|½õúþ_ýcCVÏ’[\\ìÈ..²aÝô¥Ý™Ì¥'ú&hâN>$2ø¥üèöV¯¡Ô {Š.bg³*õá #¿ë¦>|8d”úM·R3·|‘ºùZí¦<¶ ;·#þU !gCÉ·~OßßÚŒ¹„ù©}€Xº+í–M˹ÝJM‹?1…ŸK°÷øÝœþúÁý_½cÖ£›[£šW©­vøêõ–h§Æš9Wˆþòk�…¾u¡áüØO6·<ý}ËZFÌókÓ\8K·SKrD&Oó~ñ¶à\�(5PjÀ>Qê¡ÓxÊ«–Žù™…º¡Á•úX˜Œß 6—Z™žìHå(µ6ºeJñeS2}\~êá²ÓÈEÆoæÝ¿‹`/WÑ_1j�êö×2/@쯗Ÿr]u§ûÛÖëK*¥¦•ýj…£_û�ÿ+{%=ß�]@ÄÜ]Jíh‡¯^où€v2ù÷å ûdË\8L_*¤D¼NûûÒ^8k”xþm˜iûO ôºöœ!¸}”¥`ß)5û;J}´ÊE´öJ©[j^—ú¸?Jͱbzñý­¿UߥO­U©¬•¯Œ’{1çôî¼÷Æ;ÁЏÞ9îÛ£ÔÖLç­­¤ïx¾²ö—‘¾Þ —Er‡R»Úá«×_^ÙNVÐ?<þGÑ…O¤›sYgËZ?ð•d¡é¬x9@ÈŒ{g‘nÑq›(5J ”€æUê7ýã¾ÕJ]ϹÔaS~‡ø­}µ%¦C§Í|]UÁÆy¿6¨@~mI*[VzËœ^Ì*þõ÷×îÑâ›jírWg¾o§R'mõe“¦£¾ã©Jó9ÛIæÔޝôÒkCó(µ£¾zåUíäòïŸ#Ý'ºpó¾è‘¯û›[Ší#$/¿˜‘+¿k±Éù ß¶Âæ…ôFp£(5J ”€}¥ö;õáIOÖr¨¶(µ?ã·�b¾‚´-Á>oŽyp„R/3§~"ÀÜŠ#›[¸œZŒ¸ÞÚrƒÖK®£[ÎE •Qê§r€¶ûøûf9æ ?�ŠîVd»ÞzÕå}íd2®úæá> SGyxú¯Ž9ç¯}3„ÌÛ1i1Ì{ŒÈW=Eží»°ŠP5€R Ô@©Ø7J}äHÈ0õ¥'k)Ÿð[±.õ±2Qj>vzY‹¾~(reÒ“Q…d�Ü×~•KIé›[¿Gy�®E®W·¶¶\Ùº&\µ¸Æ}{Ò“)•Ú<~Óšýľ¼õú¯ºÿË¿~âo‡§ÞÀòžvªÇ}ó%þÔ>áòM¸¬øêA²d­C¡ò,öÒW"/EäœXB«Ø‡›@©Pj Ô4©R‡JO¦X—º¥¥1~W7—Z‹¼f‘ÞUÅÄ_K+õ°êÚûÛ'IËmQ`6œ|3éŠãº]4ùzëGç›/ÕJmÍÐ63Š{ŽâK3fúµ“˜¯žzƒË»ÚÉ‹¢„©'xZ²¯ÍÉåJrÖ:Ô„äÄ+¶v–¹ @z Àœz£¿”¥J @3*õ›ŠôdGl.u…üdG�Z‘ñ[¡Ó÷í¥¡¢1}bµºÌô—iÌ5õ×RlYœÚ¹\ÜמÔÚïÅ^v�ûv*5ÞÕN.Žj­/=±µU ¡Ô²žzƒË»Ú4î[ÓR[[_>å dín§ñ¥–ºl}· Ûö7ÌÕÍ'¬²äÓ­’.MöW*«±'î|ß?j¥~bµm“‡•õͭͨêxºŸÏO¿jü«ëR,Eö¶Ã[¯·¼²�,ý´Ì× _Ë/¶äºblÅlÇo�/œe†¦sÔ©s#){_ËK6ß6ÀV§ÞˆánPj”(5Í­ÔǪ›K]שÔå•úXÙôd܃ ¯R?°†‚Wà“T?í\¿o½þR×"O¸Pò1å¿ýtsë‰nžiëõýß_o=M:B¿n{Oo²™ÜæþO¨¯/_¦QO÷oND—¥Q³©Ñ¯Šìm‡·^oyU;y§¤ƒº!iMº~j®JÍjr)uŒÚ²yº¾\V«cokžH nV¥@©h\¥^]t­yjÌfûouí Lff�J—_ÛÙdÍêÚ½.nøZs+up˜ºBÆï–Fø}´Ü"ZLõ^ß×üJfà÷åTJ8ï³äSfµ[¯ŸFeÀ™É妹ìÖ%>o›Ê¬ã÷¸oýµ4Ò¿™?’ßùRØ‘ ã?á›6¿4#ÞÊ(µ·Þz½åUídáüÍ2¿Y-ݾÌ/a“÷ŠK©G )ZýÔ[t,ž%Z4SäB=©ã^Pj”€Vê‹dÒù¶@ÈhCým^'ä,e6³¬o³�„Œ—¿üõ³œÉŒ5ý2ÜÙdÍž® "üôž=kB:{6½íAµJý‡°¿x2uÕQjmuÙ¥Ô,ܺù:ŒØõ}=ñWo¹¤11ñ‰ùAŽümuÂpFzÿºººìÖl|=Q!>q9RæødúòekKòòeeZ5_;¼õzñŸ‡M�.ó5CÒÎç–üä«/åÉ\1szÌ×Å‘ål7*€R Ô@©·CÁüHŠÆn+µã\½ÉÀîˆ,,µ(uëBo•]<àL\ :”ºJ}ÇF:ÏrÁZ ô¿c¤¨/±l³+2!Oö +’Ëð7lïÊ};ªõ°C‹mtã É CKùÄâì8[¦Ðj›ÉÛÙmkQjú*·�j:!|2³«eJ­�'dÆ:›¦�²iÖù¹´�mÆ[gu5ǤWÖìéʳ¶9Ö!9qØ ]§¯É® Ú»AÎÈë#¤ÍÓvûü²Æè:« (jP÷ÐEyÙZvŽ�|¼ï@?÷U9—úXÃÎ¥®5ã÷±PJýÄ\  Ô@©€R+”z¤(lï ‹‚N’‹ô¿³¤}ElÌñ¸¦±!Er@{gÄÛ”»æ2ñ=¯y[¤Ô=P7Ϧeä!£ÖáSl¦ó9±”¬¬ÙÓ•g̨ú8«VîÉYuúšìº É!ˆ'ùú:®¶Ûç5êfvµ\ZÕCírïdÒqò�½àíF©›k­j¢Ôú—¯·îéPj Ô@©•š�•!c•úؤÃXéÆT$5(¯=Ô'SF&'Æ!³½§³YöYZ6¨oæ£, zNÆ[©êEr1“ÍÐOÉ#Æûj‰‰šškÌ‘¼±�Jñõ´,P©©“÷™gÓód:íYd‰½õô­'�Ö™Ò’üBÇrÄVjWWº•:’.�b:1ëT4ÙqA&£„,ÊÐÁÛvûü¢Æ^ªòé ªÙ§ýFè1§G³9_×bôŸõ¾¾uB¦cPê°éÉÊ-¢¥ø}¨ž«h3™:”R_¦d! (5û[©ï'j;0Ç@© ™aqËu®ˆÃXWØÆ1üyVzž±A6’üí{;'Kµ’e[ùÈo*3l€ò8_[¶WLIfõÕ¸¼*õS–…›:`.¥iÛi _OË•z�/`%ÎÖÁ=TÓ2ããº=—š*m^L2µ•ÚÙ•n¥¶çR[Wài²ó‚LhoÎÛjín»}~QãØø ûDÅœs­óÓ]d£ÐÇäíU1œJ½ý(ucåû™ž,Ü\jØ¥~þüù_\®<~Õ|}ïþýnóõðÇkaýÿzÿþe<(uتž?{Þ]ýa½|þìÙUÅ}ÌÚÇ_|þqnS°Ï”ZÎ�âžfù^Ÿ´ÁWM)‡‹|øñ,ÿ/7;n¹)nœËÂ;G¥~ bÂäf¹ÓÖªÔ’‘—�VÝ@)¾î–*õ—XK©ÉÆJ}Ns+µ«+Ë+µ¿ÉÎ ²X ¤G\oÌÛvûür(¹„úrRÕC"ÚPÛ:{7g^ñ ”z'¢ÔM;ðûM(5 Q”úÙ³gî§ñ«Ïž]“/?)•¾¯>þéá‰'ýüK@`싇”5:»_ÚìÆS €R‡ƒÞoÏ®T}Ô§/èaæ�jß§ž›ÑÉÇì¦÷ð?â¸MÁ¾Rj©vîi–±Š ò›ÿC‰5ž$«•íùµV IsíàŽ™ÌñE”ÇH»ŒGG²© �周Z•z’2R¸(¼¶öÚJíhY R/òcÄÙNQ¡ŸÏIŸR÷z”ÚÕ•e•Úßdç9”ŽÏ›ŽnX TÛm·Ïo)µn,wLµóªÜêÖéôä…§XÓüöªÔ ›ž¬‚S—]D Qj@3(µõØ�øå„ÉÏÃÊø×#¶ïCÕó=Pê2ü�Þ�ŸV{Pœôâåµ�:zì¼m>·n៺p›‚ý¤Ô³òU; zZٿͳL¹¨ô­ZîxÚÞ»*"¨ÒXµu¤ME}ú¬ÌÇ%•º½Ö¿Í–æÇPìZ(Å×ݲ@¥žån)«¼|qÒð(uÆ£Ô®®,«ÔAMäºþA~þ_¯Úç7[9nô£Þ û¬ÓI‹·‰@©«]—:d”úÐ^I5?Uˆ(õQEÆoD©Í ÔÿQ*}É_<æêÇ\¿qßJ¥n�Rö�RÿµTú‘¿ "ý“ÌLFÈöUÁFš~þÐzŠ×J¥"1€Rï×ì„ö}ªº%ô~(“Å龟p›‚}¤ÔÊôd.Áó¥ÒR+u+­ª(–Y.�"ŸÉ›ÚA¥¦"¸²� ñõ´,@©ÙšSš7ñ×z¾,Óe+”ÚÕ•+²Ñ S©‹Ž˜r@“}J­�#ÓS2»›»í¥î0ߎ+”ÚNO–ʬ²wgðÔWõÀïcU§'Û³üd‡BÍ¥ö üFÆo@�•:ñþ§W?}?îPêÄûW®\Š{”úi©ôÿòâô!ücGÌWÝOì!Ýñÿ TZÆs €Rwj—.uwv¾÷éÕ+i‡¾þå£+ö†Ä¥K—Ä?:ÞKWè­ií`[>07°»ö=nÅ—.½zöì%=î/ÎûT}3Z_…=–/S»Æm ö‘R‹¼ÑžE´\>æ[ðI­ÔzžŒÉ¹¹ÒÎtÚÁ�ßÉY>VºöšJíj™Z©#ƒ„ätK' ãñ�åaåÙ¥vuåyBøW"ª�‘}°ˆV�RSU.òˆ¹·í¥_0ãW(õ˜ LyÖ˜Yù­@t&7¥Þ‘�ß-�•ñ[½,µ"å7”PG¥¾Ê“?{qÅRê+Ïù†Wq§R'î—J^ä³Ï>‹ÛJ-¢Ôú'–"|N5;é|Šÿ²TzŠç@¥î¤ê{¥û¿ßž_•#=º¿’7 ˜BÝM_2a~öì·ÎOù�øìwh¶%!ʾêî|泌…îúô™Éß]÷©êfŒÂÇ„?þùgÇ·bq›‚ý¤Ôd¥Ãhe™µµcí¡Ž¸0jdrÂÄ‚”Z¡u�›ñÜ•ÑXj|'Ò“‘!Jë:=y¾g; ´~;[æQêÜÔÔTëú9ºs#këo+Ë�­ëCERLò%¬Ú{³ºR©�]™"d:3Øg®ÔÔjÏ¥¬ùÙMö+u´�˜©ÊÝm÷ün_�½•J™&äô¨±8Èíizò¶ÑtjëRï^”š�c-˜J h¥Ž¿²È_&„R_y!7¼J8”:¢jF».onÞ—;‡�8ñE§S©?)•6xPjz³]}þÌy{u¾o½vï=·RÿÝÜñÛ%¹åªY²Û<êù{¥vݧޛ1~sÓ³þô?äÀoܦ`Ÿ(õˆÌ"=— RjJð8h RS‰ÑOÍ�u®ì„R›³Ûj _O˦¿t(õ×®q¡ÃkkÁ²‹ñ£裺Á_}L·1ËvNß¼_*ý?xPj>$„¯­Ñï·n~{É\¯„d;”úÙ½¸ù­×5)Ù˜þâ’¼iŸË"fz2ç}ê» zŸ>pµˆJ÷£aܦ`ß(µpBÃÐ+ÉF’ÕüQ�ÆžúZøÖÔ2=›¶k�ÆN…ëÊtÖÕ¯ú©è¶ú´RÛ#ÙXùŸrÔyAe ¢~¥Ž*”úX˜Œß 6—Z™žì¢Ô€Rê}:ÿ€¿êþôÓ�„R¿»>�ë¦R?u­vû_ìöÄOrFfúÉ¿ðA£q3èåTj$>PjS›¯Š—¼àµŸ‹Ø´4å{.¥~.jMÐÏ|ËUóΔ¯ØzÔq·R;îSÿ͘8ÿïOÒÎ}v‚� Çm ö•R€0µ"H­LOv­½Rê–š×¥>Ž(5 ¾Qê—Î)Òr<*{pëi™Jýk©tÙ§Ô?a›°¶?Œ{•Ú}(X©Ÿ›ó•_²/¯˜›‹H@_kN¥–7"/t‰oE»ù{.ÍôÕûn¥vÜlª›Ñ=[úÃGbd8nS¥ Ù‰•ŸIM•úMÿ¸oµR×s.uØ”ßø h$¥~Å“_Š;”ZN¨L¼xöì=[©tŰ>þå—Ç?Ñ'õלµ]xdw*õÓRé+<(õ+1»‚s•�ùôٳ潧ñ{Ï¡ÔæÌæø –ç€ny‘°DZô›O©íûT}3:a‹V?Æm  Ôì»8µb4¿r.õÑ�¿÷N©Õ¥FÆo@=•ºûžXÁçå§qS©»å.·Rß/•>ò›øÌäbüd¦v=Å�åy”Z(µ©¾Ì¦ë¼âplæÇŸ:•Úúžë‹Xóeµ*+µ}ŸªoFɇ®¯Äp›(5MMô”ŒTÇN©&©«”úÈ‘�aê=JOÖR>á·b]êcˆR@©;»¯ÉõxÄÂÔå”úßÁ,ÿÑg®·�’J¥þ‚JýÊšJ͇s¿`w—­Ô÷Øìj[©_8w\­B©?)w3Ú ?4öã6Pjö?¡Ó“)Ö¥niiŒ�ߘK hP¥¦Oè\¡ê«å”úA©ô7ÿ±?›Kð˜ïþ"xtâÄOÿøÇ‡æˆÒ/ñ  Ôž(õs¥~n úxÁ²�;¢Ôæ�È„ŽR[÷iÀÍhÑõ³Û¨q›(5û[©ßT¤';Ú`s©+ä';èÔÈø ¨³RóXõ•ç"sR Rß3“%?ûÌ~l .•Ñ07"™0ò(µTj+(}�½þÈ1¾û=ï\ê:m…þ4¬R[÷iÀÍh}‘ö5j—eã6Pjö»R§';R>JݰéÉ0ðÐ@J-Væy¿ŒR[1¬ÏOœx˜pÄ¥WTê'¥Ò_ñ  Ô¯ÙÈî={öŠkôöHw:”Ú#ÎR�¿V©­û´¼R'˜QìjnS¥`_+µ*=™J©[k.µzà÷¤'4ŽRðêÕ5áÇrež@¥þªT¶µf"añÚñ¤þ±Í£'~ùøc>—3±Y*}€A¥fùõ_Šûí =3±~þ¤~Η„w(õ ‘ò»û9�m‡Tjë>Uߌ¦Q?ö5nS¥`ß+uÍs©ë¤¥†Rê¥ÔìÉ�?ŒÇ¿´@¥¾\*Ý·"Ó�„G³gõGlcuuÕ]±##R´T*½‡A¥~ÅSÐÛ,ñ½»žÇÅà�—ìŽÓµC©Ÿ=gºÜýR,QR©íûTq3&è}a/þáø^ ·)€Rp ”:ìÀoå"Z�–ŸL±.5”P/¥fQ²gÏ¿ºÂÓ~³§ò@¥~�>q‹=k|=êŸ~yÌþ}Ä~?ÝÜ|¨ÔËŠ‡|¦R?g+Ö½äYö?e›˜0?»÷Š'|ÕéRj–ÞàÕ½l"´RÛ÷©âfŒnnn²ÁÝ_°�à->Äm  Ô(¥>VÝ\êºN¥.¯ÔÇ�ž ÐJý¾Hö͆™^M”Sêέo“?[ó3å²¶67¿ Tj,ΠԦR_µn¸+Â�_šïŸ½Š»”ú·^È÷´ÎÐJí¸Oý7ã'T©Ù‘�ݳ¬?Æm  Ô¥SWÈøÝÒ¨¿�b-@(ugâ*�˜=¿wÉôhS©éãºæPê¯ìGîø/??b�â�Ëù™¿on¦•š>ã§ñ ÔL©¯Ä¯ðîž9o9ñw!Ù÷xК)õ S ßçºýÛµ¿ðð³µÞVü…¥ÔÏù×^öMê¾O}7ãåÍÍ�J�Û@©ØßJý‡°¿x25¢Ô€ÆTjöˆ®_ Q:R*ÝOØ&¾öñÇkfòbmsóßãAÇ]*•6ãxPj®Ô¬ø¥K®±ÙÝ—<¬˜tüÒ¥÷«¼yÜ÷©›�ÍÍUܦJ À�Uêã�JÝÀëR#J h ¥ξÆJonþxÜWP  ÔN¥�=Ì{ïÓÎ_77#¸M”€ƒ©Ôo†\D«žJz-¬K hN¥îü¤TzªÞsysór`ü~i³��J½7J]æ>íü}ó÷nS°Ÿ•zu±o·þ¬./¶ŠÙÖ…õèþŒHff�JE¶Ù å~Z!Nl޳™ðò#®Î=ìüZ£Ô¾�ßGC*õIuèìdPj@³*u篥Ò%åŽÌæ¦tДJ—ñ Ô{¥ÔÁ÷i|só)nS°¯•ú"™Ü­?«§Éÿw�Pb5V²~ö¼õ:uö¬ÞÀ�„Œ—Ûß7’#¤0Ûº ­.÷ÓªtzgŸr&3£I¹¥@Èhè ù‘ W§øÎå¬�¾;�¿�(u˜u©[ê¥.¦.·†æRšC©£ÿ,=P?Ã{—вéÞ,ýˆ)šJ½wJxŸF67S¸M”z[J�¢B=?[« ȼõz€�Hã<5´.ôVcuÑ"™�Õ|NÕO+²°`T'•³%¤Ø› Ô_³Þj•Úì—*”zˆØTù®þ꫎R¡Ôõ�K]kÆo¬K h¥î¼üô©rphï¯A‡¤Ÿ>�à!@©õêR¸’ݯ^]Ûñû4öë¯nS¥Þ–RSNÕ^Iã*õɹ7$3cÁc�£ãTgÎ�©ÈfwR©— ™ªxzOŸnÌÍÍÍO3ƒ�áßu³‹�õú.°ÂGÆìU�ÁJ]˜“Tù}CõW¿+QêæZD Qj@Ó)5`J hv¥^!É¡Ôe9OHžOAÖgˆã’vP©«ïÓíP²TIV«ýÈT×/¦R×ú­KõW_µR±ˆ–jà÷¡z®¢u8Ìdj(5J ”°#J­gƒÇe'ÓYGà0ÙÓ—v r4+bƒºa8¦ë«P*õ92¸�¿Í¡”:T“‘¬ëhO1Úæ˜û(QZwå<Æ¥Žf?X•îÓ±±@¥ö\4;е«8¡y»×{õìgTäŸ>þ ‡ïÐ]‹R7íÀodü@©€R¶©ÔçŠBK¨iN™¡Tj}ç5m–´Ÿû6D vV̬xÓÎt�êªÑ.·O²X$Ÿ5Ìv¬8”zcÇ”ºÆ6š°&¥z¹Ši†l&�G͈·)Ù7 ¾ªåŽœã:o�·;眑élŸÁ›/Äq”¿PŸÓSH*µ)’¬µæë)yú)3j;Ê/Ô¼° # OéɨO’‹ìMFV¶1ê¨7BèVó/’ÙÄ3It/ˆªÆYµv¿È:}]»"KDƒ”ÚsÑôüKyq̪·{½WoÿŒŠ,Îï=t{JݰéÉ*8uÙE´¥@©€R¶©Ôäbo6Ý›gj¥oð˜%Ó!6Äz–G�ê¬9�ì%d~ʘšVÊþÍæ€IDATöŽ/öõiªQ§G³9-dã½IaÕ˜8'D:�ž#¹t:½cJ][³ôúÚ–³½Ìøz}ÅzèæÉ”‘É ]gG�Îf¹�--T4óQï1‘t�ÓéˆãÒê<Ý!ÈqsuâSjÕ9•J­ÉÅL6;@ÏsJÓÓT¢Ï§Óº<=ížs2LbZŒžw½¯o��阺O©Ç÷™ú«çÉt*ڳȒgÛõFXàz¡c9b+5!+CÆj�pÁw+µÝ/¢NE×®¤"©A3¢J©Iûªa,ÐtO÷z¯^kã¾zš‚î;´¥V­K2J}h¯¤šŸ*D”ú¨"ã7¢Ô(5PjÀv•ºCêê(7]Ä.ç„ÿ´s>ËcŒ1á)šN}(Ê÷®De`p�ëÇE6ò7MH‘é[ò Ù™¹Ô3&9S¢«oã9ÛfjÝ«*Ö+#ª,•};&F2“•¤ð´¬ïkΰuiuîî�lø&û•ZqN¥RgÇǹ«÷Š�9›Ø:=ù�,²oÆäe¯Ò¦VjjÛC¦þvÈ/2ããº]/õÒ¼To+õ kb¬Èn¥¶ûEÔéïZ~y=D~1b*õ@JS)u>+;:ëë^÷ÕGÌïÆÌ·ÎCkTêãAAêFÉø}¨Ö¹ÔPj”(5`ûJ-„7ÍÕgY(XŸRc¬õ"YáÆ%ÔªÃt›¬4´‚á<ÔFeg¢Ø)µ‹H�mþ­ñÉý¾bÓ  1øQ†tV~))®šžcœJ�u§»;I—A(µâœê�ß’˜�K�R/ /åÿÌË.8ÏïTê!>âßRê»”C©EÜÛVj9]{ˆ;}y¥öwmŸ,œs)µI«J©Ï˜o'|Ýë¾úóÐ(ÿ4xݦR—ø}¸~㾕JÝ¥@©€RöD©Å*JQÇLæ¸zM’ ]³5Oj hòHâ*×°Y¹8•™ÓŽ Ø€c3À¼#Qê“A®Ôµ´1bEi—¹R»‹E­+Èr§›•S¿éN7¸¶yªv(µ\$L޼vw‡ÕÍ…JJ­:g RG²© zö(5힦m�² +ˆào‘§hS(õ"?Zèï)–å-c$}JÝëQjy-îôe•ÚßµDÌ¡q6¨’R‹¯& 6#ÚÛ½î«o³Æ×Ï�i*upÆïJéÉö,?Ù¡Ps©}¿%ãw2 JŽÄ…µ.<ذÓJ}áÖõ[ª=ñµÛ×=w]òÖõÛžÂþRlË­ å·tv¯©ÏêiÛí[ñò[öE'¨èbÇõ@(µ”4ágëÜI¦…gSÿ‘z5É6Ï8¢Å³<Ó”é†N]9c¹ÒÒ.-¢UCSÖRK1.ˆîbYë „°™GQgí±õÖSµC©Û�ÆÙ§´·"É'+(µêœj¥Öge0•RÓîÉëlÜ·È*î ð+út–W,S‰uˆÌ^“†G©3¥6“—·³øuY¥êZí¬G©‡tAT¥Ôâü=¬.o÷º¯~ƪu�M4wºÝ(uãuØe©)¿wO©³3ê§ZW‡äk}cšr†ï„R§ùr`ƒó3j¥N³AΣ|€u1ÛLеRxäRk‘ó™A{¯•ºlz2‡{»w”ºÆ(5 7Æ*Zþ0õ^(uF5ZC¹r£òÍ(Ÿ_t檓Ÿ¥QûÍÔ@’ÀÁTê üiÔ|½ b×ñpÀŽ)õmëÎúÜkÔÖM÷­iž·¬Âw.–ê²¶üp+hKâ®]“<̾Å)ËÎP*&eÓ0=yÚ9ªÖ¥’Q™XËv™�øíSêÚ¨͹Ä®ÔîbþÑÉ*½õT¤Ôžî0£næ”o6Ìu5ÓÁÅQ„æ:Ê+µ³�øiÑ>}J3Çêû”švÏŠ6Ƨ»²’©úÔàKH[JÍŽbK‚ÅÊ*µzàw!ÔÀïPJí¼h·{»·ÒÀïŒR—Uêzf'S9µj.µÂ¨wQ©—Ì�!&ȠÙì}cÊ“�=¹á¼×râ–8¥NÜq*5:ýö¦ˆTßÄÓ;¤Ôk\>¯ß`wØm÷-ø “Æ»wÙ�xÇa¬wnÜøÎ¶^©aþòÆ]¶CTéßÂíó­;7x¤ú;áÔ´?XðʯÓ�ßß¼~ó[«nÿÓÍEÙ~«ú‹"i×ÈÃäšoƒó«‚oÜ_à1¥¾á.CÝ ÊJÞž�SD¥¦J§OÛë0[©¿ÎqñéS骕0*•YÝ…ôd~¥®¡�3RÓØ*ɽ¾b¾Z*½õCÕ±¨RjOwh–Pn˜aê)n¢†n=_F©=…ÄO«@Š|>rÊRêV—R·’<íŒqagÊö)[‘jÀ­Ôâ[‘!»^…R»Ò“­˜_­l˜J]´•:¨kË)µç¢=^ìé^÷ÕûÓ“í¦R®0ò»ŽaêÇCF©UéÉbFržªs$ ÚŽaç|C¾åGÀ‘z æü¨’RÓgãïß2•šû5ר+Œý`g”šÝZ|”5»³¾�{Ã×7Þ¥E®›NÈôû­5sŸPZ©æÍºF%ôÛ„r ßdÅ7ÌØoœÖèn[Ò+â}ëLqü|´w¼�}g[Ïϰ5âôñ¹8>…¦pð”:IŸjoß1•ú‚AcÏ­7ðxÀŽ(õmk(È…ÜÁT&Û߈ \7¤Þ4eRw[Y*n×#+÷oaê+�b•r•Öc¦;M?6•÷ŽØéÛ2ÌlúæK©oØsE¼H#Vn ‡Ý¹mžŸ…½¿¿uÓ§ÔÒÀ� ¨„‡¬åEk? L}à”ZaóoÍ/5®Œ‘¢ÿæb"zYhMyžlÛ²£È4!§G�ÅA c¥Œ¡²kJ]C™ªrÎ Åsë¡ò¶0jdræÂ\*½õîó\*íWjOwHz6èÑC}¹�È¡Ëó´˜I±ÉË�Jí)d ü^�¥Æez²!í½YÝVjÞ=bIì4½°¶ÑtjÞ³.unjjªuýûemýme Âu}¨ÈÕ›õª”š¬t­´Q“âÛŠéTÌ`×5¯9úEÔеå”ÚsÑ/öt¯çêÛø‡�}Ø»“ž,ì"Z{¥Ô-5¯K}Ü¥ÖçÅ}²a­ã�'ú‘ˆ°åÆi—wÚ2ýÉÅGÀõÚ ?jZfÁ ‘œ$ì@þóa%‹æ�ðÿ̲�Ft„6;Oø=•coØ�?KØ(ÎÃR8xJÍF“Þì´”š=žvÙ®ßàñ€QêoìÛ‰ÞYß:ö¬Ùó.†¥:þàø:ëaÂþRÌoÍIÕA[ßÚÑdjªoÉóy¾+»io‘mómIÒƒowÚJ}Ó:S5Aj~– Ó:¾îô)µiàŠNPTÂw½kžéæM(õASjjHæÈLê?#ò›‡„“KÒK/¦œvÄGS‹DØlÀht\¼)®ìšR×ÐF-òdo èB©ÝÅì+Ђ•Ús k›6ìUjOwXC¿‹VîírëË‹w3å”Ú]Hü´ YÓŠ5ý�'³•:E¬™ÛY³-3QgŸZÒŽAÚº¹#?å¨W¡Ô#²sì“+òç-Tf¿ÈÁäê®-«Ôî‹öz±§{=WVîd¸Jý¦Ü·Z©ë9—:lÊï¿Ù¨�õEúA±~¤Ó¢Kì³ÖJ&1my�MºÐ‹ä´Î~T†ûu4GÎÅ´Ñ‚•��ùßHE“ bžû²sìÆïP`Ç �bŸ9Mø¤@ŠY-2.FC̸>€£ÔôÉô-ÍVê5ë‘™?Jc25;¢Ô,€lºíG¶.aœwÜrÛåœtq]Ü“þRkwîXßyɡҾ-�·nߎ{Îs˾yçŽÃ»¿UmIž¼“ìt(5ý•ñnÕAjñ¾ÑéPêë‰N¿RKWu‚¢gÇ‚ Ôy9'ÙRêdÑÊ/Fý':À¦ ÓïFÚ¹Ë"iIQö ×3©q1®žçzN ¥^ñ-É\�R�[¯Ï›J]Kµ¨‘2¢,ª™ñ£ÞÀrr‘éŒæ<ªUžÏ`9´ýÇLŒsu´Î¡› 8»»Ã$2+L±` Ãnô.sq :§«�üi¥™FæÌäc‘ÓíR*eÞdÚ=y3»Ó2WÎb&ªù”º½°”’Ò¿@òüÀuþ½Ãœ¸@YoÌúúBž�6"ÍW;+~Q¾¦×œ1'T²_d�ꮥ?7‡Rwg‚gÏE[ç�È/ ÜÝë¹úh[ÑþùÝV”ÚïÔ‡$=YˡڢԊŒß91 O6ÌOÌ7ëF„ýôÆ“|ˆÿ;ì÷ê»Þ µ½A¼²løúÙ¬»ÞßI·;Õ� ¨„vìld{üB>§A©}è"6d†“é¬ã‰–¾K«¦5ê†u½Ówóvõm4úú’fwTYL7²‘ŠY™¼Çœ ˜âéîkëòTkÖÙ1z6]9”ªPÔ]4vªÜñÙ*”Äu¶2õºÄi×eyû%T×V¾è îõ´2ٓݹOŸJ©� ¦Þ£ôd-å~+Ö¥>¥Ö ñ lŒ�y™‘» fÍìë�Y9O™a³ܯGeE1+-âÒsüˬg"p¾VÖ2›:ß!Sò�°Ñ Ëâ[8±ÂVZf�ì7¥þŸ>ô>eßI8”šOÓäNÝÅf2ãñ€ÐJ]æncNhé§ûÛ*ç»ÛÜY‡�Ú»b®°¿”;°ûC¼³ü–»¦•Ò]·.ܤâúÃ7¾ð.Ë p7x‹¥Ô –/ì:ËXöí]÷o‰®·ªO©'e¶)Í5lº±¨¾�mfD7g‡ß£Ô¡Ò“)Ö¥niiŒ�ßÕÌ¥ÎWîw1†€MŽfÃt1ìD룪›Ì[Ó¼¯£b\@Î\"–=›á“©�‰ÀÅZY½lèÅy9Hæ n÷Š¡3" =E–ð9`*õÿòð¡7tv¡Ó©Ô|�ØonÜekîüpOwT¡ÔÁw5¿ïœqiÇlf§ƒ®ñÙÐ Ï4bf“þRŽæù²f»¶t]¸°výËPé-~õü³;$ý}WðK©»¨ÈšË[—T±K°v³³’R[®êE%´ú›·¾—My N}À”:Ý:Bì‘Ö�©Ô5µ1v‘�ÁÙ¶¥¼µN2!”úMEz²£ 6—ºB~²#�NíÏø­ˆRkZt꟩Þ'59Cfµiïè®×iy?Ù“±gÅ4z­È¦LŸ’Z.z—§YaãÂO ¥Ž™d¯ˆÄ~+|îÃis*?`¿)õÿöàTj6+‘?ÍÞq¤ïå+Só%t£ *¥¾Ûî:W®r�®ŽŸtÜ}ÝâK.ª™?8’]Ó»TUÊy»ÇZ»·È¥o®YË¢Ë|éy�‰ßö­ììÞb)õ^Çw¾åN­… RÓª¾®¨ÔwÅÀ™NU'¨*a}É®Dþ÷pꃥԋlÞ­ÑØJ][SÓ2�vÏ; *¥NOv¤|”ºaÓ“üÖÅ\êb1'Þëz”‡Š |™´ˆÐÞ 0GÁæˆÃÉy®ð‚9±Ÿ%ã_€MðåÔSıš[+9ËãÖ––¯ nîAM.­¥iÓw;”zí3€õÝu,ñ @J]—EßuJ¥kÖ³4g¾$ó-j–ñë'…MªJI7½KÈ{¶H¥¾s×Ê,vòf²³óݵ;ƒf§½“è Þb)5Ûþ=K.ÖÍ*wøü]o Ö™·¡‚R;”Üß ªJÄ×»è>Vì{|x ”ºc~fÁR �nkÀ¿Ö5¶Q_›ŸÍdñ¸ªPjUz2•R·4Ö\jõÀï#•Ó“±Œß­óvÆïI²ÂƒÎs|q¶…¨¦¯pEžá××Ûg<¯ l�ðè¬=5C[æ–�Ýà“¨œ«¹Í²ìq1ž¨Î d=¦÷6Ê[,­%whíPj R'­\¹¶RópÐ�›7î°Xõ�wñxÀN(up”ú]§Ks¾Å‡1ßdÎûý7Ì"•¥¬Ú<¡eÏ–µ»woÜdñä;äÝ.Tßq�Ò¾@}õ[×°oïK©Y°XöÉug²µáGòç „œMrûî°OV`®�âÎÎÒù³á'L²;DòA™±l†Wt|8`J}Óz°·ÑúÁ|îæ“ªoàñ€�PjW’îJs©Íï¶øPæ[wÊÏ¥¾ë»QïªnÝÄí漏޺n­«µæuí;z6×¼hßK©µë××WsSeÄî kÖ×å”Ú­ä¾NPTâú=uÓùÅ€RpÀ”:ìÀoå"Z�–ŸL±.µW©5}‰M‘˜·fVhY¶¢Ù _ͬ¨S·ÞXcD–Ùöù¬ïukŽ-ç\9/:V¤5ˆ…Á‹öq-JòQ·s1&F gG¹d¯‹É×òŸì<[d p ”úÖÉ“?t{”š=’vÙp£(Ø ¥fvh¹æ� ¿¹‚òßßf+Lß ÎøÍnÓ �½{¶ØAßÛîMq‡Á²�µ;½—ËoªqÆç¶Ç©vl¼œR{”ÜÓ ªJî:¯Šå9ǧJ ”ºüÀïÃõ\–º¥J¥>˜žŒñ¬‹’¥ø’ц­·ºcA9çëˆ?¨œ®gŽe¹ig•ö¬#H ÀASê;lv¥à­“'oÞ¸A­ú{Ç€Ñø¾'p Ô5±æXeÙ¿.õ ‡Z‰ÁãÖØWZÃbEë€RÌ®o&¼ò~3pÇßõo’7<Ëhö֚˷}[ÔJMUý­ŠAjæó7Äoz%ßݸqW¥ÔÝ>ëwu‚ª’ëÎAðkªö(5G©ƒÃÔ2~·4êÀï£�‹h•CF�w…!ÒÞCÅ»€|ü ¥îúÌðóiÚÍõNÍ•öèF~P…R—¹Ûâ?Ø Ã.IVDy“1œŠü]`©[>voÑnß^ëtÖuë–½é;Sa™?ÿà3j÷gz²[·†‚/Ç´k^#¶7Üöþ¶yK¥Ô>%ww‚ª’ ÎLl,J�ÀÇJ ÀUê?„ÍøÝÀ“©«�Rp†-½K$ç ) Òÿ# ÀÁQê2+å*”ºë¤'J�\?ìĺÔÎÇ7œkT;'ó�)èu>fD܆߉¥D®$‚ž-·�ùÇÄwd¬"srGÒü-qÓëÏþ-N¥þÆ=�ù›JAêpJíVr'¨*I|�¹ÔPj€©ÔÇ•º�×¥Þ…(u¦m}7º^Èç`Ô@©e É„>•Þ½uKãA«;ÎIš·ñ|ÀN(õmkˆö–”È.¡È‰o-Û¦ úV—ø×\˜ê†ow‹R°sJmÞZßÝžyë;+5w—”Ç›öyn/õÛÞä)N©;ãwïüÀ¿!»Ùm¹ª4æ·n¼ÛY•R³¡Ùfî³[ßʳ˜¢î5âá€d AJ­H÷­èU%Ú7î¦(5ˆRW©Ô »ˆ¢Ô€¦Qj7]k·n­]ÀZ4ì¨Rw&Ön_¿¾fÍuŽw9üóÖõë·Üƒ›‡oݽ~«Û³ÉW*Ôy/Ð;Ú5ź‹6äú­øö¯æö…ÝíyE'(gÝÚý¦€†PêÕÅ><ì É̬±Ó¥e©ìb&¹ã-á”úxˆE´T¿Õs­Ãa&SC©M¦Ô€ÝPjÀ6•ú"™lè¿ÍëgÏ[¯SgÏ6ò";„ŒíËžåÌ®·FB”öÕyž}›-ðuìÒY§~Oœ]“`íQêÆÊ÷2=”¥J ØïJ] óÖëB"�Ó²Ö…ÞðB;D,fŒàÒAuVPêÈ‚Q­R2ëˆoO“ÿ 4v”ºi~#ã7J ”¥® s$çÞ�ÌŒe”º077^h§N½ÑX:¨Î J½LÈT¥ø;–äí:SJ]I©6=Y§.»ˆVÕQj}[«GëX{(5J ”J­ÖßrP¥NqéMQ•½hT[gH¥®®c Y´ÞÍ@©ÕJ­Z—:d”úÐ^I5?Uˆ(õQEÆï*¢ÔÙ�öÝKÁ³yac5tþ£Pj”€ý Ôz6XØ’élÌñ®§/í 4E³¦F²Q׿"(•uÖL«ŠºBVΚ·£Ô¡Ú˜Œd]G{ŠéF6æ>*"QãÒ_»deFT©ÔtuY·WD³ëJí¹€rJM/ÖÐËö5SêAóMq(õöhûK©�©%ã÷¡ZçRW§ÔrZÓVI»û“­�“åàc"®¦ÿèZðTZån”(5`§•:;ÎìŠE,W¬±ÀÓLûÆH1z~ƒîœ—ÍÑu6p¹½�?Ó½±™<)j1BV'éŽ1=ÙZ¤ÿ¤ f瘩�Ë”âÙñ<Û×Ê^³CX¼–'ªUêÚÚ¨iS9vºÖ˜ŒÍºŠÑÆ�aMÍe4y”¾BëÌ�j=çØQmþªsbbô ã:!½veÅ•ú”Z‹ÐC³šUz”uC~.]¶N¦Ô«¬kù ñ¬YuéQ­UNÒž°êŒ®³²dÅ(Ó×B¦ µÙJ½?´ý©Ôå~®ß¸o¥R·ì¸R/±ïm¢YÏ—7ùr(¦ÈY×·GÞ£kÂSi•»Pj Ô€VêsEad‹ìa”ì#伦͒ö³b߆�äY)o³âM;³¯¢!dIlÿ{¸Žl86Å� 0­¤‡äÅÛÕ*•º¶6ZùÁ&¥uºŠYMå�cG͈·)Ù7 ¾ªåŽœã:o­¬ÝÛ:¾±dm0é8Sœ>7*ο0^_ç;£ã+Ù³ÅBÿf*;’+ž™rTªémóí…Y>bu<Õ;^\ésî@©€RöJ©;¤®Žr•ã³E2'Ô²�?%Ÿå’Š¦éƒ„DùÞ>l:"cšTô؈fSzÇd8y•Ê,A<γ—Ÿ�’ÏÊxj¶‚Ro̘äL‰®¾�çdc˜Z÷ªŠõÊíF’¿coçèÑI¡¨Yß1Ö¼gëRhéûu^ÙEÇŠVN¥ŽòÉÔ¢t‡ôîÌø¸^¦N¦Ô}òÇ4ëUj{.µ(>Ìçûš*uDFåµq2¨ ¥Þ™¢Ôܧ[#ã·"L¬ÔÑ3bBÁ6^ƒÞwí„,°/‚bdš}ÞŠÔºåL�Yö�‰Ò�D1OŠì×@lšï¤,±rÅ -Å&ääÑŽ’^~>ö!›ã;ùÝ�%Å�ü†’ºH üÎ2+Õs$?-GbÌ�;Šý2w Ô@©{¥Ô"GUš[å²0ª>+Z+ÆXëE²ÂõO̽íàJe‰U->€8¹!Ç€Îó: \yù‹GÄ‹?Gx V8áD¥v©±�E³1çùuzŠÌÁ«‹„ü(C>éssMñFzŽqê¯8‡Ô_Z™ð=Ô¶®TjZ¢èPêÇÕÕyž.ëcÞÔòJÝaî�ò. èkªÔÚ92Íšj°QÿB©w懶?£Ôe•ºžÙÉTN­šK­0jŸROR!�ê w�59š#çb|Êÿ:ûl­ð[í´®õåù]2ÈþÛKŠY-:ÂwȈ®e§ù—TrTø:½Iu-*�v�7ÇF*©¯³±´ê³=šQäwz7öFévöÚv›góºUé™ÑµÈ åÝNÓLý×+ŽD@©€Rv\©—ÌÐ)}ŠMæ¸IMöèj©¥T=úl;”b¬ò‰×³<¢+”ºWz«¨k…•f±X^:UäéÁXÁljB„?#2’ËlnµR”zÅd�+u-mŒ˜JÊì³×[Œ6õ´5&»•%Ç´ŠÙ£7VOÕý•ý ‡r[•9q)u‘)JŸb‰Õ2FÒ§Ô®:™RËÃgYˆ¼¼R·Y+nͰ¨`@_3¥N‰ÃO³®äJ½C?´¢Ô‡+Œü®c˜úðá�Qjoz²#<ž,CÈãì³8Å?+mâ VÙG.ŸÔbíü ûÌœ_ʤfØg%#î…3r4?ÚU€ÿêÙàßU%—fÒÚ™�ò‚l€Ç,¢o°;<ÇGiô°Dú²ÒS�ß“üûÀ±bŸ¥J Ø+¥–k' é!¡iáÆTß’VìJ×fÑâYžBK3•:#Uñ¬­ÔYOpYŸ•Ù·¤�‰Cz*+õ¼õZ.¢UCSÖ*S1®ÔîbY«‡ͣ¨IöØJí©Ú¡¿íšCû”WäTêŸ8-e¹Cä›4 ËlËÊyÊ ûØŒ²ÏrÙ`Îçi‘çšZKâsÙ.?½üèï¢[Ylj‚ø`÷ñ/µrb¨F;›È?Iò“YW¥Z,µØ»^`Å)rNŒ19íØ €R¥ÔC©Ó,L›y¥©Ø]tê*}Î.Ha½¢R³™Õ²t±ÑÒ| «Áù™í+u mì1¬¬Y½š§X8¥öT¤¿Y¢J8ìTjjÑK–,k‘ó™¯{ mO³´Þ†Têú¡íÏ(õÑ*ÑÚ+¥n©y]êã¾(µã;)¾É<‘r|n‡Î¶+>�Ÿ·b£+O‹$áiù©æG» ˆ�t›ù2™&ŸeSGtÒžäŸ6vtŒgì3ìJu¹ÊÓîIñÁ<Ë瀨“ Ô@©{£ÔÚ8™¡O¨Å¤æT}†�µ»µO­Ô:±Ÿ”…Ý�fY„£ÛWêZÚX4§g¸R»‹ù~«”ÚSu�þFen³`¥!dÈVjvàМŒ –QjÏÀï!ÓÎà üTêXžjQ�G ¹RïÐm)õ›þqßj¥®ç\ê°)¿+üfQêÊTG‡ü ¥åGqˆ%L0Ø<åiïèì^Ÿ`ʱ!M?$ÎÚø±SrB?ÚU@~¤{íâ ²E6„;%¦îOÈ¥ÞŒ¶"ÙˆZ•¶‘Ü@_:ÍÆ�kó"wŸÖ­›·J ”P¥¦©OÛë0[©¿Îq-ì ¯ÔÔÔθԸȃS©PêÚ8#%”-»Üë+æKO¦RjÏ1T‹JýµÒ“¥2«*¥¦ÆËf�;”ZÈëP™:=éÉ 3~ÞRêV»´?=Y RkgIqY$3Ó“íÄmF©ýN}¸AÒ“µª-J­Èø=(ãõ¥RQ똟…^¶Nù,6G¬òEöºW.ï®Y;õå>Í’bs¡hçÑ¢Gm,Ç´hžt£|8÷€øÌOÒ'užk¿ÀÏ‹JuñUZ+û:ˆÅwó)×'¥J Øk¥ÖódÌ üR]Ýè‘/¸R‰¥uR¹ÜPe¥6e7:“›cOä|-ãè ü®¥�T ó½Fº5'Ö¥öó,¢¥RjÏ1ÌÒ#*ý“=iäM·”:ÙKD¿ˆÒ“…ñˆ° >Ž=¨NÏ"ZɼHñ¤EµY1»Û±ˆ_VØZD+X©³lÉ"îÍB©w懶¿•úÈ‘�aê=JOÖR>á·b]êcÁéÉN³Œß},ïwÔú ÌŠU²–Ù'ª•Jgé]²Þ>Ã>Eþ)Ú ÚÝ3Ø>ʾá#1Îñ!!\oçeúzq´³g™¯Í–ͳRslÙ:z²Á$;M‡“²Ì2 d¹i/›• ¥6dþ�Ø(¿)2Pj Ô@©uUj6,ٌٲ鋹Œ‘¢ÿæb"”ZhMyf­¤Ôiê{m£éÔ<¯™»2K�ï@z²ZÚÈô˜sVس»Xmꨑə s©”Ús Ös©´_#Ó„œ5ÍÑÙR©'§¦¦2“t§È*J·²Ûº>TãØƒêdJ]ì5F©ê´÷pI!§�HŠÍÂfJM�£½7«›¥ÛXCy—°ïÊ*5_¤¬M³”zg~hûK©C¥'S¬KÝÒÒ¿«™K­Eçä�b-“6A?F+Å<ŸMPà_d�æÉàJŽ ÔÁ'T$Ï‘üÌxžO XΓܹ¢X©>KÈx«½(gO‹£�Ä·L+$?7/–í¢;Ïm�bÿD²:ÉCÐ#dcer�›¶¨”švûÈLž·sQLµQm¹¥J ¨—R§ˆ•_‹ŠÝˆx¾Ï¿I3#ÐÅTˆ�ßZvCŸ‰òxge'”ºú6jZ†5`c@Jí.ÆÇƒs´`¥öÃÁ.Ô«¿ve³I§R[ $íÒº¹îv~ª\�T©'eA‘Yfˆš‘ïÇE‚3³geÙbD«¤Ô­DvªPê�ù¡í#¥~S‘žìhƒÍ¥®�ŸìH S+Ö¥ÖôY6’£`/ù¦±¡…û+)×v[fŸÚyz^wLtŒ~RŠmܜ٠Öù3üÆÑ&‹ôn3ä×_æÑÎBãY^ùbFì¤n½qN|n§ÅÍÇŽŽ.´Ò~V·*Õbô3¿±^`wè¬Y±"¢Úb7J ”°GJ�—s’-¥N­õs¨ØE˜bFå³/{°¥†eˆaœ2±tÌôÛ¢œR9Âòõ²'onzÅ ÒN³7ù‘Ë:$bN…Vj{…+ïuõmd;Œ”egÎøŠQGåÁ¹éŒæ<ªUžÏ�1;Ï1ã\­sèæúÜY¶)8/¬CŠêôøùˆ«tr�«þ\ù:{ ÑYÁœ |óõFï²TêÈév©Ô¼Ѷ¢ÝЀ¾.ȱârnQ~v⇶¿”:8=Ù‘òQê†MOVfà7ÿùºgƒî-¢§=i»µž˜½ÓZg]KêIE¯: HÒŽ£ÓIå�"Òã©Ô߆rç@©€RvG©ý�»Ö,G+M¦³1Çãj:ð «®,ë88jÑ�ùƒ]}�¾¾¤àUÓ�l¤â£¸÷˜S¤Ws©zÖ)�u²“;Zè>J‹ÆN¹Êöd ½ÖÞÝ�Zs*µ*=™J©[k.µzà÷‘ÊéÉJ ”°=¥ž´V¤u›n,ªoc› ÂGr|!B+uÍs©ë¤¥†R Ô@©;¨ÔéÖb�´nL¥®©�±‹„ ζ-å­%¨¡Ôa~+Ñj´üdŠu©¡Ô(5PjÀ*õ"›Fk4¶R×ÖÆÔ´œÍ|Ï; &¥>VÝ\êºN¥.¯ÔÇʤ'(5Pj@íJÝ1?³`Ï£:ÝÖ€­kl£¾867>›ÉâqT§ÔÁaê ¿[uà÷ÑàE´J ”° ¥8•úa3~7ðdjD©Pj Ô(5õQêã�JÝÀëR#J €R¥@©¨³R¿r­z*uèE´B®K Pj Ô(5;¥ö ü>R©÷HªCg'ƒR Ô@©Pjö6Jf]ê–ºF©Ë‡©Ë­¡…¹Ô(5Pj”€]ŒR¡Ôõ�K]kÆo¬K €R¥@©¨{”º¹ÑB”¥J €R°'J}<Ä"Zª�߇깊Öá0“©¡Ô(5Pj”€úG©+ßwÈôdPj”(5J @Ý£ÔM;ð¿Pj Ô(5»¯Ô ›ž¬‚S—]D Qj”(5`[J½ºØ·ggõÔÀÂèþ}ŒHff�íÖ‘]Ì$Cï•'?Bc6ÓD¦Ú,�U®K2J}h¯¤šŸ*D”ú¨"ã7¢Ô(5PjÀ¶”ú"™Ü«?³=EBÈé*Z?{Þz�:{VoàLjBÆeø )œ¥ ,GËÖqž=ô^yBñ#,RñëŠìÒÙçW³KKÑê¯sý¬Ek�]¦± £Ôǃ‚Ô�’ñûP­s©¡Ô(5Pj@)õW¦CMsŠá�}„œgaÌö³b߆aÇ5ͬTtï31-BÈØ†{ÇŒx›’U/hZ¯<´Ú±ß>¥®­�V~°IÙW1Í�í'�à9FîÈ9ΡóÑÊÚÍs%J­m0õ´æ>5•æÓò=Ïߥ›¹Àriÿ^yB¡Ô“䢣Už^²[A¯ß°Âå“\©Ý爘ïf¼oÔJ}ÆTöq¾™^ØŠ¬-êí »ÏxcÝî:´á•úp…‘ßu S>2J�ôd(5PjÀ6•š\ìͦ{óÌ®ô éN“|ˆõ,� ÔYs,šIµx~ʘšVÊöŽ/öõ1¥¦š™229f;Ng³\@—– ªnù¨¦§;èaétµsw}J][³ôúÚ–³½Eiõîbly¯Iq­Aà9&’.�b:qœCn„Vvz4;�st·•:F˜[yN}žyöùlŠ^\{ZœóLGzâœX}̳ׯÔV«<½d·‚Zìiñf�Œ¯r¥vŸc�¶'çÖîzR© YIERƒ¢g]�a÷™PjE·;m¥>&ãwƒÍ¥V¦';‚(5J ”° JÝ!uu”[ wÞ"™ŽÃ½N;ËãˆT l¯N�'Ê÷®ðhbÄ\nšêZ^ìcoçh§m#$«Õ>—zcÆ$gJtõm<'£¶L­{UÅzål$ƒ.ÀsŒ5/Ø:‡4\ú~�Wvѱ¦–­Ô“¼Ã­ƒ<§fÒÜ',>6¾Â‡f·sqõìõ+µ«UŽ^²[Ñ3K6øŽQB†„R»ÏQ`³éÕÎŒg+l(FëE²Â—Aó•;¸bÎ SæJ-GêöòQųrlq¯ÔÈ”péZ•ÚE¤Æ6Zfyž_§§XÁÔÂÅ2à9Æ)¯âÒpiebÀ÷PÛºO©#§ WZë ϩϛ«\% Ž9Ðlž1Iúö–Sjw/9”:+·¬�btÕ•ñ[œ£@ŠGï#e~$E¥R÷É·9g¸•ÚßíÎCC©ßô�ûV+u=çR‡Mù��ß(5PjÀÎ+õÿ7Êm-™ãÂIÉœµæÝrZ'dˆ'WùïYZJ="Š �›•¹§h1?6ÄRÌ5G©WL¹R×ÒÆˆµó2Wjw±(1CgË\€§j‡RË~†«[•9aS¹§§§ÙÜá�¬ã ï©Ï[ÑìY g9±—;¦Úù;ÏÞrJíî%‡Rkó\dc,|l)µãlPùXJ·Bêö›°J-š=Âöz;Ã¥ÔþnwÚxQj¿Sn�ôd-‡j‹R#ã7J ”°}¥–+0 é\ç’5-<{–‡-¥ZéÚŒ#Z<˳Ii¦Rh¦TNÚ;V™Àm_©ç­×r­Ú˜M*Ù«yŠÑ–­Zp:èçAÞSŸ·¦>gD»cÜ<0êÛ[N©Ý½äTê)^1ïK©Ô®sèsüÕx+äî|cÿH ºD¥Ô²7Î2/öv†K©ƒº]Ú¸J}äHÈ0õ¥'k)Ÿð[±.õ1D©Pj Ô€ÝQê4‹fe6ªYrÑ©«g¨ Ha½ŽJ]C{ä”^.y½š§X8¥öT¤ÔY¹J—O©çÎS†NiZ5JÝÆ`æªWjW/9•:ÚNfµ$&/”Ú}-™áYºùÄq×Å�¤‚R{;£)•:Tz2źÔ--�1ðs©Pj Ô€=Sj*F3TxŠI6Lošæêå V:•Ú3ð{w•º–6ÍŒW®ÔîbþȪ ðT¤ÔQ™Û̧Ô)MѰ ¿i•Åe™!­º�ßî^r*µ¶@òz¯‰+µçŒ¤ÑÖn5Ìõ¦ŒRJííŒ ¿P©ßT¤';Ú`s©+ä';èÔÈø €R¥ì´R3Ëš¶×a¶R�ãBÖ Ôžôd»¬Ô5´q†�!Þ– ®Ôžb¾þü‹ÏÖ*U8üá矯Åö}¼–0_?¸ÿcO‹JŠOŸ?¿æ¿%«÷8J­çɘø¥ººÑ#_ puãS¹Ü�[©E%ÔW/F÷@©khcŠ�|¯‘n͉u©}Å<«9©.Às ³ôˆJ©ÇdOyGÓ•ºü"ZCrLý²5ð»Ò"Z3ÖØpg/¹”š–) �æJí>‡Q(ôʸþ¸ûM€RŸ—‰Ð3D¥ÔžÎ0[°ˆVsÌ¥V*uKcÍ¥Vü>‚ôd€VêgÏžu—ÛŸxPÚ|� õãG'?›RýáC�åÆäãîR6ÿô�îxôó/âÉþo¥Ò—xZPêP\yöì•÷–¬Ì°}oâ~B©µ6sÖÒ=’Ë)úo.¦±äК6òr(‡R“±”‘É QÛu¥®¡�¬1œ³BãÜÅz¨b.Œò h ¾÷1ÌÏ¥Ò~¥ŽLrzÔX”�ñòJí95“æb¯1ÊRm÷ð*ÛW#FïE[©Ý{}Jm¶ÊÝKn¥NÑy]³~;Α¤ éM'Ó#ìgéz Ô´²éTÌ`²Jíé ³u¢±ݾoæR×1H:J ¥4�R›OâÃ?Ÿ�<úXìù섃ŸÄ¶µGÖ–/ô –æË¥&ÓY‡—Ñwé¨çˆ·T=kD÷êvõm4úú’fèvTYL7²‘d¥{�9pɺQMgxOMÏâxÉÆ¼m(ßP³UŽ^ª„ûô ºúM勸;ÃÓg¡º½¾J¦®�ñ»¥Q~Å"Z€æSêK¥¿²‡óGVÔùsªÄJË^óÅd©ä#w˜šŠôO23ÙO'NüÌ_|]*}�çE¥®J©å-z‡>üÜRjÜoà@(õ¤L7¥¹†M—õ1×LÛ½ ú6¶É |$G6¢䱯ÑK V¥þCØŒß <™Qj@£*uâýO¯~ú~ܡԉ÷¯\¹$7h—.ñ W/Ñ7ï•Ä Sdû‡éËÏ¥»+¦[¾+_þÓO¥N<´CÚ_œ8ñˆ¿H—J?âyìc¥vÝL�ùèÊÕ+iyŸÅ/]z¿Óõ’îì¦7ç%{€G<}åê§ï9”ZÞ’ ý”—¨çäÒ;uí3[©q¿�}¯ÔéÖbëmL¥®©�±‹„ ζ-å]+,ïcܽ¶¡ÔÇ•º�×¥F”ÐJ}õÅ3Æ‹+–R_yÎ7¼âò¯ž=»òÛÀÖì¹\*ýÊŸÎþÙ|0ï|(•úç'ÞuUä Þ©Âkýì³Ïâ¶R‹(uüŸ¥RŒ`ÿ*µófêþJÞx×ø�ðѳgæÔæÄKVø}~+>»wI~uõ7þþ•f)µ¼%»ÿÓ»§>Ñ­Û‘Þ¨ÿèt(5î7°ï•z‘å™2[©kj£–š–™°ÎŒgw/�Z•úÍ�‹hÕS©C/¢…u©�¤ÔñWÏL^&„R_y!7¼Jˆûkü¹ž)õrá®rÀ÷ÃY}ÖW|âÄ#VCך½¾¼¹y?î‹eË%·ž”J—ñÀöµR›7“”e.Ìï)õ5«wê„u³>¿j*µ¼%ÕJ¿¿¹iÞR¿œ8ñ°Ë©Ô¸ßÀ¾WêŽù™{VíÐé¶0é§O÷íá_ëšÚH[¹867>›É�gw/�mD©}¿�†Tê=’êÐÙÉ Ô€†RêkÌ¥?½tåý÷S¡Ôô�þê§WÙÃüñ`ÿìÙ‹{×®~@ßlúçm²qÛL’'Nüÿ‚'ðþeØ??æ«O?–Ó¬ŸlnnŽºŽ§Oú�äί‘ƒìw¥–7SœÝpϯý�Kó½D€R³"Ÿò{“ï»ÊŽ~yåê=ñ�/,oÉøý×ýŸÿüÏÿó_ÿe¿èìLÑÛ퉨tMŒq*5î7°÷$º´¨‹PbzTëJì®RL]n -Ì¥ÔO©Ÿ‹ðsgâ¥xl7ãÑ�¡Ïí/åƒýs¹€m¼T*yÖ²eyÇxÂîa*ÐæZÕפ,?þØ\˜ZjóúŒoÈC‡×Ö>þ‚­ÂeŽ¿\*=À#'ØßJ-n¦«æ}Æ·] Rê{a÷&ûÞëýÎÎîæÑYJí¼%ÿë?ÿó¿ø‹ÿUjþ ·›¸¥?‹Á N¥Æýö˜x·ñ wÇ«¾Û5G©�‡PêúÎ¥®5ã7Ö¥ÔQ©ôÑüþªûÓO?JýRìú”>¿‹ûfð÷J¥º�ïúÙ\kM˜óϹS';y‚áÇ|aêŸm§N?ù÷�„ßæËäZó­?*•îã©ìk¥–7Ós›f–q�´R©eáøoÏž}ÄS’½7+7òWÞ[Ò¯Ô‰óÿþ$Í_}NïÀa�Rã~{+Ô>Ÿ–V¯ònìj”º¹ÑB”Ð Qê—Î9Ü›=¸ˆõ´^YŽÝÙ)•6ÝFn™ÙŠY�>§–�d+M?ìkWŸ8ñ}�föüH ·úI¥þù óü1oõì7¥7Ó%zsé¶A?ÓÔJmn¹ÇïÊ—ö­˜x.•ÚyKú•ں݆Í$‚N¥Æý@¨«–jü}`J}<Ä"Zª�߇깊Öá0“©¡Ô€z*5ŠzÕ^¥ÇÌ„DÆ_<{ö/pÕÜùWï²;�í•§?“±iéÊŸK¥þ¬Ó ’¹Ö¥æþË/�zh�ç·R�ž`?+õUsÈ ó£®ñ{N�žÌuÜsÇ­xO*µó–T)µ}£þœð*5î7°wB5õ9¦ëÑdRӒɨ.&U3¢ñ*î6ÀîF©+ßwÈôdPj@=•º[¤:zñòÓ¸©Ôæ0oK©¯˜…½“/Y<úòuòóÏ×Ìí?ñçv¦Ô�›ªÎŸøì‘ù´Ïç…jxøûY©ÅÍtÅèÎÎßXf@õ"ZrËW\¦9פR;oÉ`¥^3Óò»”÷Ø+ºc¦O'ݪ’¦UǺ¡Ô4H”ºi~#ã7 nJÝÙm.Ô#¦.«Ô+•ž8eÑèǪŒ­_pþÅR‹Äàê|lë¦�øÝxúû_©¯:•úÞ³g£Ô/¬$¼‚WÞ[2P©Yn²tú”÷Ø2D‹ªþZE¥TGaï6À¶•ºaÓ“Up겋h!J ¨ŸRwvÆ?¸&BÕW+)õ'®|FŸ5_‘Zì_sŠs—úü?Ëœá�:}ÄOàùˆ(õsË7^°äc!”ú¹"Jí¼%•šÝ|�á°Ñ"ÿøî7°‡ÄO•j†ŒTŸŠ‡¼Ûµ)µj]ê�QêC{%ÕüT!¢ÔG¿¥ÔS©yÀê }^ž¨ Ô—œùŒØsúOöùÚÇ»£ÔkÎ(5Ë8lN~ö™%Ûl€¸œE�� ¥f«`™þðžw.õ§J}Ïž\mÍ¥¾T!=™švó÷Ø;£–)ÈÊýÅ’©Ëâáî6@ÍJ}<(HÝ(¿Õ:—J h¥æÏñlíÛ²J­9ÂZ>¢&ü®}üOö´j)ɉ‡Ž¹Ô�]s©©`?L8¢Ô�Í ø�x@©ß³¯3S•]¢ÿµ#ÐJ¥v¤�¿�Jí¼%«UjÜo`ïŒ:ZþOV4¼Sãï;; Ôå~®ß¸o¥R·@©�­Ô¼zuM<‘w‹\ße•šå3’Kÿ¬1£v>ÿüBÔ»ì}_ÈMk¶€ÿb^³ÖÞ¯E2poö3ö©R³(óó¿»~ÎׯŠ[3¥ÿò<@©?µV¸K¼4×¥vÜ’ÁJ=ü±ûj‹þƒû ì‰SaŒÚtêS‰0w f¥Îø])=Ùžå';j.µoà72~ê¨Ôï?“ƒIã_‰e}Ê*uçýRéoƒž8ñ³+¢pᄹŠÛÇ¡~d:53j>¯ÚX]]•‘éG£?~d-Yý´TzŠGPp”šéñKv§i÷dÀš‰4ßÀtY©ÔqZäÅGÔ9âWŸ™Jmß’¥Žüçþ'¿9ôv‹¸Zð¹#=î7°ûUNVþ£•ê½]¥^]ìÃÀÎ�ÌÌ;]Z–Ê.f’;Þ­.56o”ºq�:ì²ÔŠ”ßPj@½”šEËž=ÿê OûÍܺ¼RÓ‡ð¯yØ‹-'}â¡ÉO2L}âÑO_üòsä�í§?ÿòËÏ'̨ôÓÍÍ'¦vŸxøÓ/�Ù¿�>³„}� à (u'çg÷^ݳäø»_]{ùâÙ‹¥æþìùKZäÙsS©Í[Ò©ÔIªÔÿçÿCÛÝÜÜük Rã~»NwX£6�º;ÄÝVŽ‹d²¡ÿ6¯Ÿ=o½N�=«7pS;Ú—=Ë™]o�„(í«ó¥¾&•ºó~Ìó+ K©Í[Ò¥ÔÚÿJ}ysÓsK9Ö¥Æýv�hF-�:ZùnƒRïs$çÞ�ÌŒe”º077^h§N½ÑX:¨Î J½LÈT¥x˜%Ä*:BHO@±*j&ãwƒÍ¥V¦';‚(5 Ñ”º þ¶½ÈVzsó× }ùgéŸïá!¥Þõ[ò×ÍÍXàý¶YÚÄýv¦È±jþr±qâúö•ZÏ [2�u4)ÙÓ—vÎôŽf õ1®P{¤¯æ9С”:T“‘¬ëhO1ÝÈÆÜG‰Òºó(ç1.ýõôƒnQ¥RÓ]Ô© îÁÙŠu ¥ö\@9¥¦k¸ú\Ïz>X92-_MÒZù§æÝëªÐ}½ÞÀ>‰R­r­½Rê–š×¥>Ž(5 y”:ñ¤TÚÆsøåÍÍÀÀØåRé+<ƒ(u•·äƒ~õdó÷ÀE‰.ÿóŸ_â')H.L]Q©³ã„�ÁEúf…äåé§™ö�‘bôüÝ9¿,%o� \noãúD÷Æfò¤h•,òpgvJ] _on~ Üûý÷À{êËÍÍ¿ãv=H]el/Z9L]I©ÉÅÞlº7φëd†o�äC¬gyàÖè Îšc‘á^Bæ§Œ©ya¥lïøb_;꜌¦ÉÅL6;@ýð×/’_èX®y´O©kkc–^_Ûr¶—Yk¯¯XÝ<™222œÎŽ:�Ír7\Z6¨õæ£Þc"é)¦Óg?ýŒÐÊN�fr,n¬Rê,!gL¥Öód:íY䉵ƒë<Ïüø|6E¯¹=íUj==EK¥ÓºYº��ªÑA+)èâGоj ôçˆqRLJÃOþÔd+}{z®×ݳûQ©� ¦Þ£ôd-å~+Ö¥>†(5 •Z{úôo5ÜûëD <Űo¥®�V›ó¥§OöÕ×ö vùƒY}�Z„©»·§ÔRWG¹Êqë*’9¡–Là4í,OÆ„¢iú !Q¾w%*£·|,v²Èd7;>ÎM²—WLõ+¿¼�¿Í²1c’3%ºú6ž“±m¦Ö½ªb½2X½‘äoÇØÛ9ztR(jÖwŒ5ïÙ:‡ÚY¹$•qÑ‘õË©ÔQ>™Z”î�Þ�×ËÔÉ”ºOþ˜f½JmÏ¥¥iŸOÇäWâm>++Í:zvUVÂÕ:è§&jôïuTè¾^o/í¥•žL±.uKKc üÆ\jÀ>Qj@C)5 ‰^íLjî<G~WRêAþoš[å²0Ï>+Z+ÆXëE²ÂõOxV‡©RÒЖ…Ž:ò̭ÖÅâmým.‘Û(ü[Èi¯¯XÁL¶È—–2˜ê•Ò™âæ9Æ©¿Y‡~²ÊĀu¥RÓE‡R/8®6¨NÚj1Ÿ;É›Z^©;̽QÞ%÷ý|X€|Iã»'ƒjæPrÏ^g…îëõöR³+õ›ŠôdGl.u…üdG�¿Pj Ôì'l wÕ‰’“ì¨Äv”zÉ �RiKæø¨êI²¡kε‹¹ê­2”b¬ò‰×³<¢ËÛ�cê¦�‘v—ŒdS«¼ÂÈvÇÿÈÆŠÉ WêZÚ1•”Ùg¯·XÔœVÌÆd·ò£Ì8.€ÜX=U;ôWöƒ$mUæÄ¥ÔEv¤(}Š%VËIŸR»êdJ-ŸeÁßòJÝf­¸5òzGd™]†s2µ6B6¢ü{#ø§f+µk¯£BÏõz{i(upz²#å£Ô ›ž ¿Pj ÔìGºã¾£z¤ÇED÷ަe#¿»¶£Ô2F)¤s�ëØ´ðlªoÒõ&ÙæG´x–§Ð²=*¯³qß<#•>+ÓlIýÊlS©ç­×r­Ú˜²V™Šq[tËZ®)üÐ<ŠZa�­ÔžªúÛîÔÏ>�¸ú•:Â'NKYíyÄ& �R»êdJ-g£gXð·¼RÏð çŒ6÷ÙúôxZF;eÈŠÐüÔäùÕ{y…žëõöR³+µ*=™J©[k.µzà÷¤'@©€R°Ÿï ÿ¸ïhÌèhuÑa‰ýÔD�{y…žëõöR³+uØ�ßÊE´-?™b]j(5J ”€}ƒî_B+Í̦- 3Ù¨gºu´R~²ê”šj¤>m¯Ãl¥þ:ǵ°/@©[Iž–\äW‘Ú=¥®¡�3RBÙÔ½¾b¾ôd*¥öCõ·¨Ô_+]W*³ªRj*�l¸;ñׂh_P�žôd†>o)u«]ÚŸž,@©ÙbbzàOMÔ°WTè¾^o/í#¥>VÝ\êºN¥.¯ÔÇ�ž ¥J À>$¦ÊN–^]Êå͹©ùÜÒjÚ[‚)ulç”ZÏ“13ðKuu£G¾à*Å×GÒR¹Ü�[©ÅQ!g|õãèî ü®¥�Tó½Fº5'Ö¥öó,¢¥RjÏ1ÌÒ#*ý“=iäM·”:ÙK„ÿŠÒ“…ñˆøN‚�cªÓ³ˆV2/˜ëEQmVÎ[¶Ñb1e{­¥fª,³€ýÔL¥V×ÛKû@©ƒÃÔ2~·4êÀï£XD ¥J À>D™ð[7ZgŠÒ©óÅ™VÃ7ª–§ü®]©ÁJý‡°¿x2uù(5~AU©‡×.¸W4¹pëúí[q<0°ãJÝuaGjŠ_¸uëîQPw¥öÿmŠf×çd¶åâÜz6ê/¥`•úx R7ðºÔá£ÔøÍ Øégüy4¿uó»“'O¾uç®õx~ëÎIÆ[7ðÀÀŽ*õÚÝ›wîÜùæÆíw}ŠüùÍ›7]ßlݦnÚkôÝmë[°ëßÜááá4œRk±¾ó¦Þ(œï‹iPjöN©ß ¹ˆV=•:ô"Zªu© ü�;©Þ6‰»'Mî Ë'ykË7pjvN©·¿1¹áY–÷ÂM¶Õ)Ú/g*ó»×Ù»Û®Òœ[øÑ€º*uR¦Ž¥Æ ̨ÇFO)‚Ôø ÀnF©}¿�†Tê=’êÐÙÉ Ô€¦Qê›qƒ¾ºÁžÖM“Ž3Û¾Ž‡FvH©µ›7oòù 6¦Ûqo ߸)p(õ-±å‚ó�9ð›_¦M_á{/P/‹h ôôÄJ.wn*­\ðw›‹hÊF©�‡PêúÎ¥®5ã7[—ú¿G`gÙ�‡ü»'O~“°âÕwÄ–oÅ3zü݉‡F*+u" T¤ïÊ—×oÞ¼amïb¶|=É”ÚÚ6̬™ óy }E�¹Í÷±YÕ·ìb·ÔîÆJiÖ�Ìäd&««…›™8”€:F©›k-g”J h<¥N|{ò¤9nôúÉ“o ³¾!·Ü v •`‡¢Ô7dlY†�í 5:»Ò“Ýeaì2JMeúó8ûïmsß ³ä­ë×1òÔí®Rj–¢¬£c9¦ÞÇ”ZƒR°KJ}<Ä"Zª�߇깊Öá0“©¡Ô€�Rߺ};n+5‹Rß¼sÇ!ÙPjvJ©×ÖÖÞµ•ú†C©ï ±¶~³@t—C©o%:-¥~ו€úÑÅ&E«ì£1º+ Ûô°.(5õŒR7V¾ï�éÉ Ô€UjŽð´¥¾‰‡FvH©\w,ˆÕgÂìRê8•é[�–R¯iÎc.Èpv|³¨A}I°?DÉjŸùyÂ:F©›và÷›Pj@�”zøzøPUŠ-¦µæÚÿîäÉ»xh  ¥îú̃2žÌ‚ÔIï}êPêëlÖ5á}Á¥á·äÁw;ã·Yf²·‡ñ“uDù ?¨J À.+uæ'«àÔeÑB”P7¥þ_ªÈø�(5 nJý¿=|è�O³µ´Ü1êÎÛXC €�ŽRß"|ݼ¶•úÝ»RžÝJ}[n¥ÿÞfuܽ˫BœÔ�8ûK­î‘Ÿ¥ �Ä¡Ôì–R R7JÆïCµÎ¥†Rê¨Ô•�J}ç®ë!g�mJà‘€j”º¦RßJ¨”:a–¹û®Tê¤R©)kôv�¯1³ÆŒjP?ôêÃÔ±Šã¾¡Ôì„R—ø}¸~㾕JÝ¥4·R¯Ý½{ãæ·Ì ± ߟ<ù-†}°³J�¼uëÖm^þ|8H©»¬aáŸ+µ¼W™Sc-Pç0uU³©õÊAjz·áï;5ñßÿP.ãw¥ôd{–ŸìP¨¹Ô¾�ßÈø h`¥æ$nïŒJkß�<ù}Ï‹ì¬R‹»í•êëž8u—©Ôl`·Øt]©Ô,Ð}Û±Ó3@3…©C©¡ÔlG©�7¼Q‡]–Z‘òÛ­Ô==ÿÆéé î’0ePêãÖÉ“'Íõá;'O¾…¥oØ¥îì¼p÷î]Ï ÖE7%ä.9>äúÝ»N¥¾{W(µóØ5ú?Ð|8d”ÚJOæ³e…/‡)Û_—úöÉ“ß&QêÜn¨¨-J]æ ¬ ׯÛÓžo_¿î�RÓÝæ�RÛáfÕ+O�Ú¹öôY¾ÿ�xîÇ�ÛÜ2œV¼ Tê´B©áÖì{¥îŒß½ósç·nŠx”€]RêÎÄš�êÛ·„X$n]¿mÖ¯¤ÔkŽiÓ¦œßêÆO4‚S‹±ß±@©Ö…瞊‡¼Ûì¿sºæ8&nš¹›0e80J*=™b]ê––Æø]y.u�Õ]/!èž`¥v‡©;úûÛÄ+ãOý|0÷Ôò93Å^ö’M þé�·ÇD�sÿòÆ; ¯È;ýïB <½”ç�?žK{ çßîï›ÌÒW­Óê{éÏØçJÍžë/ܺµ†µmØm¥fw[—¦uÙêOÔXO¼ûÂ…$¦Qƒ!!‡uÇ”£¿£2pM„½Û¬ðsÒó§)žô¡Ã”à (õ›ŠôdGl.u…üdG�ÚÌøÝóo.§v¥•JíyåVê³ýï˜/—;ú˜Q¿ÑßÏþÇœz¡ÿí?³7<$mä©%¿Ã_�±mo¼aDÒyöo{ÚSøVÅôÕÂýïP½þÓ(>�ìw¥ì•R°?é–Ó=¹¿“º¹§;üÝ&ÿÈ�êöIx¢û”ûa˜2$¥NOv¤|”ºaÓ“y~+оMÿ¬Ôî‘ßóýy×ûÔ;ý¹ŽHG®ÿ�³äþ·‡"ÿíôS{Ž´õÿ9I�õ¿Á"Îrà÷@ÿ™´ÑÖßßê)l ü~›}»ÒÔk”(5œxÔ ëz4JÅ:�êº0ŽÆ«¸ÛmÙçËaÊpp”Z•žL¥Ô-�5—Z=ðûH@z²++ÐÎ-ξ PêéþyOÔúmfÄÆÛýg¹%§Ø›7ú§"‘íÿ¿X�Å^ÃVêŽÞ!öÏûG<…M¥îG{§ðéJ ”}@y©.3‰Y�Wu·É°¶r x¢Û1®;L™zÑv¦Ï) J]ó\ê:©CG©=Jýo^£®E©ç\ïû—ø¿Kýƒ|,wD„š{#‘Óýo,Y÷�éÉzŒÁþqOa+JýNÿ‘ž (5J Àv¤Z�Wy·ñ£’S¯I»æ0e£ííæËñöÅðf—ÚMªþ ÝWÕŠ<ìŒR‡ø­\D«Ñò“)Ö¥®Z©�ƒ¾~»ïn!Ä‘H/ä¹3Ï6ìïï{|Ê¥Ôãoóe­Ç=…-¥`“ªÛ' |8€R¥ÆÝ@©îöYµÞ¯únsxx"n—éüls·ÊtYøÊˆÇ^{=›|ÿBø?³…~“žÐÇœ#æIOVÍÀïŠJ}ÎNOÆùs†ÿ›éÿ3³äi‡%§¦ßöl)u/æ·ÿ˜“J=­PêHêÜÛô ?uàÓ ”(5ú€0$º´¨˜BÓ£ÎüöU*µ¸å‘̨ÌkÖ=š‰ˆÚ4sX·,ëm³è�yÊlS© ÿ�3UÍ1"z•ƪ9 .J¦®�ñ»¥Q~õ,¢>=™S©�[´ö÷›·÷Ø\/>ËßÌöÿ¯%SzZs<™yŸÿKÿ4›*=WF©)ÙÙ?õ·ãÓ ”(5ú€½ºÛ"ÖÖñÌàøwêî‰ñÁŒÜ(³�™ezLv¹Ê+µkzcÀ›Bù4½érJT,]©jWê?„ÍøÝÀ“©+F©Ã/¢¥Tj÷�“ôŸûßþ¿ù«!.Ë#ýdÒ2ã˜Ã’;†øèí·ûÇø}΂ÕFÿ¢Ø¦Rj–M!;Ä”;Òæ‰… Ô@©»«ÔºxNÍŒz|T—£ºe™®¶ÁÁ¹ÎÜààL·«L€Rçþå�wþ(Gf�yû�?.ñdbÓdhæíþÓJ=&„é%ã¢àÙüú)ñT~zð�wÚÏÒ'ñòNÿ;„ÐGïᱯ©3ä rF„ÁܵNÿ©ÿíyIJÁ+õñ@¥nàu©«ŠR÷¸ŒÚåÔe”Ú d{fq ô÷·³´÷Oýd¿Þè?cDŒ¹þ7†<–üG¾útÇ;ý<.ýv–»ô|O$ý¯Š�ßÙ~®Þ‹ýoPOOÏË}(5PjÀÞ(µ¹Š5Wé©x|jÜ W³�â�`·¥Ôs=œ‰¹Á¶.WµRùþ~–Tˆ óKÔßÏ48òç~–�H­Ôýý<Û¯xnþsÿ4?ê®Äƒüuÿ´cÿ¾ÁÖ¥}›‡¯¦Dåop§v´ðFÿ;o÷÷ÿiO3`ç”úÍ�‹hÕS©C/¢´.µcü¶ê•# ­Tjo§�cS�ÿø'ú;¡C*ö„Þ¦�%÷Ò[wºý .Þ¼ÔÛFd…nûã;ýŠ(u„ÝÝgÙ»~2øvÿ|:€R€‡|ô{§Ô1+)wêÖV§QwÆÅ\í¸¥Ô#=âeψ¥ÔñX¥nëÿs*’냺íòŸúS=SoKSîŸë0Òa”ºÿ¬‘=ý/p¦ÿ�6#Ûö†*ŽáJ�z§?×éÈõ¿“òô6ûïèÛ凖Pu”Ú7ðûhH¥Þ#©��,X©{þ-@˜èÿ"ZÊ 5Óc–?¬ÿ�y™•›%!{gš�ai“–üGnÉ­Ì´ÿ|Nü~X¢·3=`éjÎ +l%.wáÈÐÿxƒeý7æh‰7þ8„'Pjð��» €º(ug÷Ôøàüüàø”eÔÛWêíÿ¿ØëÅ^ƒe!ʧE‘,“ÞyçŸÙBÿÛb†v«_©çE|‹¾éyGĵÇÞø¯RŸí›=¦o÷ŸõÔ×ßÏ,{´w O3`G£ÔaÖ¥n©k”º|˜ºÜZb.µkÕ,^…V)µªßR‹çp‘t* ÍA:嘩a hbBßûRÈš”¥`�•Ú‘)<Þ:?88ßêX‹+!”:QN©å”útÿKæsð ·]©À6ûšJ-Yð+u�gõVûiç1¥ì_­þAÏA‘wúÿ¸ˆm°óQêã!”º¾s©kÍø}ÌRêžÊFª @©€R¥®A© 6cúíñ)¡¾&g™ôN¹•zp‘ÓçWêÿÆãÜÌŽ¸"+•úm©è½ýo{Š °)Öí“fÀÞG©›k-”ZíËž!ÝaÊ”(5ûS©wvàwŠ�ê–¦Ë"Åi6]’gé�ü‰Š-£¿}A¡Ôçì7¥žr(õ¿)õŸûER¢LÿŸ=ÑF�c6ÿ§<Í€Uêã!ÑR ü>TÏU´‡™LíPj•/ûl¹F €R¥àÀ+õޤ'K¿#Õ–­l#¶§5Ç—¡�¶|WRjžaè¬O©‡‚~O÷Ïò7³ýÿçԬ5³êoÇÓ Øû(ucåû™žÌ©Ô~_VtGF} Ô@©8˜J½Ã‹hQµŒH·}‡þ·cÈÖ;‰ŒÈ4½C­ÙòJýg¡Ç9ŸR§ßàëíD2íóü˜q[©GúÿÈÂbé?ö�xÊñÕ©Ûx{ØÛ(uÓü~ó¿s@ø¹!j”(5R©uk•*ÍÕzTÆ¥uñGP·”zpn„37h)µîú{ùÿíïŸÿ¿#c¬Ÿ'Ýþc{šŠõ;ýT¥ßè?g°ÑÛ,|]N©sýÿÒÁËy•š{gŠW·BßÌõ¿�µ”šV~ƈsýo yZ죕ºö¼zvZ©6=Y§.»ˆÖþ»K˜¥1÷”‘å0ePj@Ý•:(KÕJ}JØsTë\j(5J ”R©#ºˆ6'âV¢²x\ØrÜÓm•é²ð•±1Z³ö»t*èMúR�+I÷-;ÎäZ+xP™êØ®R—ø}¸~㾕JÝ¥@©€RvP©#É€Ñ≤ýg0L–Rgü®”žlÏò“ 5—Ú7ðû¸w.5@©€R‚”:Ö­ôåD·cHw˜2Ì(uãuØe©)¿¡Ô(5Pj@8¥ŽœRùr¢Û•w,L¥®ìÔ,xÜ«hùÃÔPj”(5 j¥VùrBóØr˜2Ä(uY¥®gv2•S«æR+ŒJ €R¥„VêH,wïŠ'}#ºÃ”JM…ºÂÈï:†©¥Fz2”(5 ´RG"ºæ渦«þ†)À�Qêca2~7Ø\jez²#ˆR Ô@©ÛSêHì”Þ�'ñx·~* ü¦ -J}´ÊE´öJ©[j^—ú8¢Ô(5Pj@uJÍ•™Sþb˜2ì{¥~Ó?î[­ÔõœK6å7~ Ô@©; Ô€ê£Ô~§>Ü éÉZÕ¥FÆo”(5J Àž*õ‘#!ÃÔ{”ž¬¥|ÂoźÔÇ¥@©€R Ôì…R‡JO¦X—º¥¥1~c.5J ”¥ Jý¦"=ÙÑ›K]!?Ù‘@§f¿ vR©÷HªCg'ƒR Ô@©Pjö6Jf]ê–ºF©Ë‡©Ë­¡…¹Ô(5Pj”€]ŒR¡Ôõ�K]kÆïf]—:Õc1Lô ~Äbz4 ¥  •:ïêÆãÝ]ñ”€ÆŠR7×"ZÍ¥Nêð= ¥ ¹”:‡N`kuuV�`J}<Ä"Zª�߇깊Öá0“©›R©™PÇôhù`W¿ØŠFu6RD‡RÐDJ�ˆã·nºPjöD©CE©+ßwÈôdM¨ÔIú‹âƒ @ý‰²»1 ¥ Y”B €‚8”€½Pê0Qê¦øÝd¿YˆB @£Hup ¢@ƒ)uC¾PÒ�€R°wJݰéÉ*8uÙE´š+J�¤ðð @Ü’K©¢ �8”€ÝUjÕºÔ!£Ô‡öJªù©BD©�*2~7W”:£ Ñœ:¥ ñ•F À¶�ýÀ6”úxP�ºQ2~ªu.u³)µ£ ñœZßJ}ïþýnùríã/>[«nm•®?ÿüãá*ÊüõþýË�A°wJ £`ûN�n`”ºüÀïÃõ÷­Tê–ý§ÔIÌ£ áˆª¿éj6-ù¤TúZ¼úð猇« ~üÐÉc!Ë¿<âÇ<]&~¿´Ù {¥Ô0jvÀ©ëþ Õc1¬à “XL/³“sà÷±ªÓ“íY~²C¡æRû~7YÆo=`„) ŽœR†©_D>½víS[8,Ãýü„Éj¥>áä'nË?›o‡.c;<»®Ô ü¢ ‰FWê¤k�Žž,£ÔÇÞ¨Ã.K­HùÝDJ� 5�ˆ:LÝø"ríÙ³kÖ›ÿ(•¾´møñ�YHùópJ�ø‰‰ò/¿0i~ضLç“Rétì�R#×7énp¥fBÓ£QL��éiѨ ^fQjcþ.=ö 3´¦LçåRéWè Ø¥Æ°oBod¥NRY‰!²]ÖØç4¤ÔÇÃ(u=³“©œZ5—ZaÔͤÔzÐ÷€†»5›K©ÿZ*ýh©¯˜D½öH=ôÛ§ËÌÂK S¦S+•þ‡‚=Pj û ‰ÆUj¢†Pƒf�ê€@uY¥>\aäwÃÔ‡‡ŒR7Qz²~™Ð˜¿>cµ*µvéRwgç{Ÿ^½’vØå_>ºboH\º¤wvÆ/]¹úéûΰ-ó©ó,—>½j—ˆ_ºä~)jI\ºråMn}ùìÙËK—.ñÓ<-•þ_^ú'9õY¸/õâáµ53ùw}÷ëòµðÅËa9ZèÓ{ÏD‰øÛ�è+Yôþ’×"zq•Ö{é™ ; q¿TŠpõxtâÄg NòiÑ_XŽýhدË_86P#¬RjE™ÎÎ/K¥§ðA°ûJ� 5!I4ªRÇ`Ô ™œ:¦Vjoz²°‹hí•R·Ô¼.õñ¦ŠRã× �úËsJ}õ¹)·¯øÃÌûÖûg÷Þ“JýwsËo"¡×{v™WÜ»¯Zï_\ Tj«ÐK¯RGÌ1ØL£/˜"ÂÉL¤ÙäêÎOpÝö鲥ȶ:‡)Ãs~o& „`וAjBoP¥Öñ šë±Ð?ôÛxÓ?î[­ÔõœK6åwsüV=¶óÞ ­Ô/¨ò^½ò’�™ ÇY¸ùùµ¿_cÖ|/Áe˜–yþê ßò¶ûQjc6S¥^]ì ù�_f6ü•ë‹‹ö'C‘Ån·2‘{¾“LzÞ{—&4wÇñm&h¥¾*Õ÷wÞç"6-cÑR†…/w&î a~n:vgü9;þS*ÖÈ9Õ"L­Tj)ÐWå>‡R?5W¥þåĉŸ­Æ=–©Ê~as¨Ypž œêò£Ç&¿Ð&X9Â)Iúf-\ä'{¤Ô÷ @hâ�¨ÔRƒfC¦�žL±.uKKc ü®v.õúYÎdft7 „ŒîÁcû:!¬­cSrßE2®²BÆCŸ¹�DWè½…vRœptšqzpƒä-Aè½ØY"¾c;ëdÔµÏõ tuišäf;¬çb!O¦g­>0Æósë1EñhŽôânÍ¢ÔÏÍ ËÀÍç8ë¶ ?Ó¸ _‘[ØÞK�:ÿ¯àý�>z_)¹ÇEY©Ô—¬J^x”ú×Ré2ñ;á7Wiþ&Ά|[³¡YÐÚâ¡Èà½fÉ‹¥ÔË8O À.*u~E–®FTê(‚Ô Ùðç”fs©}éÉŽ6Ø\ê ùÉŽ:µ:ã7µaI±·f©Þ#¥¶Û:®ïšR§/ÊkÝ0ÏÖjšì¤Õ€Ùh¹ÞË’çòÄIƵÏùûóœ,q^¼×ÇÅÛ�¬xŸ’MÉ¥ŇÈ~û‚Á5B#pÛ¶”ÚT_=~ÎÎf”@ãì�áÎø‹gÏ>å‘hW$ážêæ¢|/@©å1ïù•úG3\¬ŒRó¤eT�»”Jý®3=¬VjUÿ Bv[©1•€Ðt7¢Rë?Ðd��¾mùôdGÊG©6=Yù�ß²1777?Í m¦Ö»Ø˜]ÜéŸN€RŸ9sf.G›ZЫQêdf,ôÀïsd^h,óäÉÌ$³Û1QË ;qÛâ:Û4—,Ó{Ì´‡Ø‹ºwŽ/²ç:\ûÌÑzÏO�¦â,Î#Ôž3SôtíÙ”üØTï<­GW$gq7ƒ�`q||Ò;á`r||q•ÚÔZfÊ¿u^q8vçoL ßw ô=±v•±ÊI®*õo¶©{•ú~©ôQà\j±Ù 3³yÒš¬Ï¥®TÆ9…€]Tjü <�x7aYÐtø‡V(Ó“©”º¥±æR«~ •ž¬ 26@Uo©q~:j¥mMÏ Ë ­ÔÕ|; ƒÉz‘�.°CT]SìÅ*í¡ K·Ï÷žÁ Ûþî†�-`'KÈ9ö t4O ò=wçIBN ËϳÀ9 Nw(Н‚05Ø!¥ϸ7eÆwV©­ø2�}Õ©Ë÷Øìê÷¥Ûñè«^¥~aDZ™˜?¯E©?á/X6n+;��¦›–&l¥v�Ý™Íû³¿?33~3¥þB Ô@©¡Ôà(uÍs©ë¤¥.£ÔšÖJ„±q 4²1ç0ðhVq7Ãߌ‘¢¾Bm27ªõ°9¼Å6!ÙëEöfEúç3@BVSl\sqb—•šÅoc\©³löà¢ðÍËnSÔÆX§ùg]‘NŠF�£u–°‘_­HòVgÍp‡�"dÄ*6&‚ÙªÞÓ’E²’&v2§R{÷‰Êr²–BXóA3A•ç,½²\Nv(!gŵW~¶ÛÍP…ÎÚï³ôíL$ĽYý\j> ú#Ç0ï÷¬¹Ô˜s©Ÿ1yþÈ)ÙvJ2«Æ—.¥þ4„Rß3ó„ÅÙ“ž×¬ÁÞ,�·ó�[—¿pÌ¿~°vµ¢ Ò“(5PêŸhðÇÇrJ}¬º¹Ôu�J]^©�UHOfI!ÕHÂâQ†™—k€mœ%í3âmª(þe~¨›‰¹xƬIr‘õ'!K2×ê.+u†�e¦Ôçd“¹XN‹�gȆ®EÌΩ=/®EæcÒà*a“§³Îͱ¾>�Ç„—í� !sêÞãÃÂ;èž‚J©½ûÜÌò*’ÅxoÞŠ)gŸ÷H÷YyƲ�QB`Gp;´×°w@©­ld÷ØzÑï9Z¤*{ß^g‹ç�§-3£Ò—®^½Ôù•-Љç\”/٣ů…Pj;\ü“�òûÓ‹‡ž8ñ9á‡q¥Rhϳ–�í0e(OJ¥¿B”(5”¥SWÈøÝÒ¨¿�–]DË)…3<êÙCÝp2edrb<1ÓÐÓÙ,·Ñ¥eC&¬î%äLGz✘ík)5i_5Œú�¾¿Rì¶Žq™¼HÈÅÞlº7Ïß ð�.·âY>Áx2ç¹È¥RÓm…Ecb‰�AÍSÂdT¢žrÖ šÊ̈^$EeïilÜv{”I¿¡Pjï>i19:mf)c—ÒæØ?f�-wç? ·3Øœ#½ýãÀ·¯ÔÏ^&̼bL”ÙÒÓAêç<àÌ”ú…˜*Ýý\¸ó=k¥ê÷~c#Á?°×Ùº&òƒÇ­éÕy^F©Í¥·¾*•¤“n¹oò‘9ÿ™gþ6ßút9ñÐÒð°¬C–¡7K¥ „J @ó+õöâ«‹}Pj°Ï•úa3~7ðdêmD©×y.êYitÆÙHò·ä{‰� w•0’MϸãÃŒv>Ûn Iªz�ž,Ï”>b{´C©}û\¿¡çD'³D¤!˘án6˜Ý"ξâ0Åùøð ÜÎ`g°EÚ–ëTj¦Ã/_>fŽæfüìÞ+&ÔÏ^u ¥¦{Ÿ¿º÷‚íHX&~ï+^† ¿Äv=ù’ýóâ}3ZýüÕ5ºåE�RÄ+yÉŠ¿Gå¶ÛÊ>vâÑ/_üòÐLHÆÂÓìEâg1ôÛ¯ËqºçÄO_|ñË >¬Vj™ÎÎeKä€RЬJÝaNŽ,Ô¬¾Pj°ÿ•úÍ�‹hÕS©C/¢v]êy§ONiQâ˜ÉÛÊÌmƒ¿[•²i˜ñ[ÝXî˜j'$êPêuMYÝño+™žžæÓ§—’ü—’X·**ÆG·r މVLÒ>–Ò�JÝÆ-ØÂUÂd]Žî>ïüæ]3 çø…ûz�›=÷åV«‡Rûö¹O=ÇýeÂÞ[”_R°)º²Šó¯2¸�Áa÷V%ûÞ¾R_åbüÌ»i¾ö*.”ú·^È-÷D½ñWf‘W¹cdxö\žf-/®)uBœ˜½þÑ\˜Z®AÍù‡9»úá»fº²Ç*]æ“­R˜)Ê` -¥`(5[ßen!36MŸ!OA©PjÕÀï£!•z�¤:tv²”z–I[Öòa�Ëõ,i7•ºÇ¡Ôãòk:—R ³ëÙ=¥lŒ%]¿”„Rëy¦®­Býõ9^r¼U·”ú Ÿþl›ƒ³„Éiu絜÷œ}šä¡åvÞ-¾ÞãO(“ÖBÕ¶Rû÷iN#/èæW‹ÎŸ'6è^*Ë.®i§Ìï2؉_Œ<)™2Ù÷ö•úJü Qß3§'þ.\÷žHAÆeø}nÈ¿]û‹YæS^æù½´Üðþµ¢„yâø5^ëË÷/q¥~Ï^x«ÛL]Ö}åž©Ô_9ìöc!¿?O˜Që­|e'ÖTºÜ9üXØòãdg�RûÊp�OÔ€fVêdQŽ Ô—¬g5(5À“cu¿B]×(uù0u¹5´*Í¥.0 §Ôm<Ûwan¯•ú<%“Mz~)É,^Klä÷ ¿öR#í|dŽn*õŒ[©]%LÚd”:å\1K0îLF¯µ ê==¶Ð=Jíßg1A»3âUpÖë‚ÛñÅy÷âv;³iN6ô½^©ÙSÊ¥K®U±º/Ùd|9~éÒûqO×Iâï]ºôž·D¼Âù»»…¤GJ¥û +—؇ŸñÅÇ…9½ó€IDATñª¬føã/¾øl­ª2—J¥Í8|@©hf¥N[“õvsìb²§/í¹èY×ÉhV<;ê†u*µžÕ¡Ô`ÿ*õÊ ün”¹Ôµfü®¸.µÁ3aû~+”šZ_qY&+ÛK¥žWÏ'•z”�¬î8wÒhkçW#”z�/fí¶j³„IF^¥ž'9ki6“‰ð$hö’­B{}½Ç¦?¡#Ä +ÛŠìßgB¾˜6ßÍu¦‡Ì±Þ,ÙzPqïZ[l“ñ1íoV¥Ôåp ÙÞ=÷÷>büÆ}(5Í®ÔY{5Ó¾!þ„]gÑ™ö6ñÌ]g³‹+üqsŒc3yÎÉž¡›/Zͧ×,{\„RƒýªÔ!£Ô͵ˆVØ(5›¬; )Ò“)”ºÃ´çñFRêd‘,´’‹Îïýb|´Pj+“¶žÉd=%L&Ì´dçd¢sö 2Ǻfž7cKwg•½·l¹¯¾!ãå–R+ö™¿˜óNEž3ãáBx7$WÜ9ÂÝÅ‘ñì4,3™*Ù÷>QêÎOJ¥§{ëAñû¥Ínè €RÐÔJÍ;ÆrfåØCž0V7g(æÒ|W;ÌI•Úh—Û'E& sEñvJ ö¯R±ˆ–jà÷¡z®¢u8Ìdê J¤¿tM±ˆ–B©‡„?2Il ¥ÖÈôŒXvÊ(ÄXè"sW¡Ô1"s|óYÏî&£fÀ7KÌ4ÚÉIù�ä!Ó"…ž“#”½gvò’Lèf)µbŸü൓¢ãGÓ*k§~?nxZ ,¸Î55ÂÒ~OF÷¯RwþZ*]ÚSú�Ré2l@©hn¥fA�â¢cÈc/!óSÆÔ¼xt¦ïÎt¤'Ή§6fÛã‹}}<êrz4;�O– ¹Ø›M÷æ}“¡Ô`)u¨(ucåû™ž,H©sSSS­ëçXÖ/„í¡wþ¨‘ɉÁÉA¿ÛW#FïÅÆRjƒ}çǶIÚúÞt2=ÂÛ$”š¥ñ\L§Æø è½ÙKæ¯Ô¬C©UûÔJ­eyÅíVw–Uꖥ͡Ô(5M­Ôô©nu†? FxâÛ¡cÕ|Ö�厩vošåó']+¢Ê€�XH5j=½B©Á~SjÕºÔ!£Ô‡öJªù©BD©�*2~¿vÊ­nd#ÉJÝ—�íñc{eÖ�ß&Óþ ’=ÎÅ %\Ù³�ŽÖw;ôìÐêDß ³ÎNµŽ†<�™¥(5PjÀn*5HkÛàénfA– ¬cÜ|µ‡yöyÆnúÇXB©Á>TêãAAêFÉø}¨Ö¹ÔÕ(uc>¶W>hƒÌm÷Äóæ’ƒMC¡éZ  Ô(5ͪԚ–ngÏR�Â:_Y–�\aέÔYOjo(58PJ]~à÷áú�ûV*uË>Têdµ‡ šsZ¶A¶ÙÒg/»’‡°Ë$¡Ô@©8�J­G¬šTŸûØ# uBŠËI±Ï¡ÔQ{YV(588Jœñ»Rz²=ËOv(Ô\jßÀouÆïF%‰V{H‘Ø3©·Áìö#Ý{*8×’Õì2ÑH J ”€¨ÔcöT;¾0êój‹3·Í¸K©íôd©Ì*”¥>ÞðFvYjEÊïý­Ô3ã³C;qæÓ§›iIªÈéI¬  Ô@©¡Ôì²R/²$ì8ÝÎÒÙFä"ZZ*—b‚= K¹”zLº³‘ç+×@©Á�Pê£Ô,xÜ«hùÃÔM©Ôz¢@³Üš Ôì{¥ÖrÔ¡‡ =›Ùi¼èûÖ´1�':øÝ¾1z/z”:2M �‹ƒ„ A©ÁAQêãa”ºžÙÉTN­šK­0êfRje( Po”H :@©ØÿJm Z¾ÇØÃä’|w1Eß�¯ó3n¥ÖŒ 3+xJ ¼R®0ò»ŽaêÇCF©›(=Y2RýÈoÀî٥ʸC¶Ðµv!gJ @ƒ*µ¦Ï =ÎÉu±¢ |‘êñ€ÝËÒúúI²ñÞEó¨ìV¨ÐÊßäÍ8Pj°Ÿ•úX˜Œß 6—Z™žìHsG©�Y�Â)唌�P…[7¿=yòä[wîÆ¡M@©hH¥fúÐѺìøK˜LgÓv(’U?½ê†.R¥ûD©½éÉÂ.¢µWJÝRóºÔÇ›*J�05 ˆ:H½J�¸{ÒäNÞ”€Uê=–šP©ßô�ûV+u=çR‡MùÝÜ¿Y˜ºú¥©»üM—^ýcI£¾I]ú‡;7n~Gÿý~ ─ƒ©ÔxøÍ÷pèUjÕ\ê£!~ï�Rª-JÝ\¿5– ¿Vh°_š±KBp›E§‡Ù«ëìÄ (5Q©c£ š Ni•R92L½GéÉZÊ'üV¬K}¬I£ÔìñN @3Ü’Ûö„›Ô£åjæÔÃ0' Ô@©hV¥•žL±.uKKc üÞ7s©5>ô¿Xhœ_™‘ åâ·í wNž¼!_S¥ÆÈo ÔD¥ÖƒþÐÐ¸Âæýв¹Ô¾ôdGl.u…üdG�úx³ üÖ´d,9© „úT$KÖôXN©ïÊ—]T©/Àœ€Rp•:Šo@³áZQ>=Ù‘òQê†MOÖ´¿Å÷ô1^�F1€ú}·�ê±àõN(õ�“'ï$ìiÕXG (5Q©±à h6‹Á(Ó“©”º¥±æR«~iöôdâW “j@ÝÑ“µ>–˜#ºÿ§‡í}IêÑ7¹HßzË€Rp ”ZÓ¦ÍÅ)Èe[s©ë¤¥nB¥f2=ƒÏP?b1½üH‘pJý¿<8”ºóÖw'O~wóî�;'íDe(5L©¦M¤?ð[¹ˆV£å'S¬KÝ”J hîÇS©ÿ·§RwÆÙÊÔŒ·n'àM@©8˜JÍæVÝ\êºN¥.¯ÔÇš7=`ÿ(uYºî~/•úäMäûJ ÀAUj-§ÍdÔŠ™ ÎŒßÇªÍøÝÒ¨¿�6í"Z€¢Ôq6àû­onÜdÿž¼qJ ÀUj*)pjÐ4F­ú°:çR—ÏøÝÀ“©¥4™R'بï»|À÷…o©[c- ÔP¥æËÝ`>5h¢ËÁ83~­.=Y}×¥F”ÐÄJ}�õmsø¤üJ ÀÁUj-‹DNAªA£ õ©H$¦P¡ør.u£¬K}d­K 8J}ýäÉï­¤dwOž¼sJ ÀAUj¨ŽéÑ(€ƒ†$�ê±€µ0ðûhH¥Þ#©�� J h$¥îúÌðµëÆÉ“7­7·Nž<ÙuJ À�Uj-©cOÐèèA_ù”ÏøíêºF©Ë‡©Ë­¡…¹Ô€º)u™u©ox¢Ô'±255)u7~–îÆþ‚*Õc1XhLb1½Ì ç\êc ;—ºÖŒßͺ.5~¥Ðп8w@©o{æRcà7µ)u4 €°taÌ»BØ(us-¢ÕÜQj | Á‡÷„Uêø‡ì�ßñï]¿O^‡9P“RÇñ(@XâPjvM©�‡XDK5ðûP=WÑ:f2uS*5Ò3Pÿ/¶Ê'¡Ðv`]ê[oQ‘þÞ\—úÆ}P›R'ð €°$ ÔìšR‡ŠR7V¾ï�éÉšP©Ù"1,"@�-•°JÝy�»´à55*5&S–îN(5»¦Ôa¢ÔM;ð»É2~c©{IªƒÕ;` ñßK¡¾m f¥ÆÈoB‡R°ûJݰéÉ*8uÙE´š+J�¤ðð @Ü’;â ‰ ·nÝZÃòYlG©1ò€�$ Ôì’R«Ö¥¥>´WRÍO"J}T‘ñ»¹¢Ô15�æÔ±ÝSjÀö•ajÂÑÕ ¥`÷”úxP�ºQ2~ªu.u³)µ£ ñœZ‡RÐÈJ�05¡H@©Ø¥.?ðûpýÆ}+•ºeÿ)uó¨h8¢êoº :4ŠR#L @â�PjvQ©ƒ3~WJO¶gùÉ…šKíøÝd¿õ€¦€:rJ¦†èÐ0J�¤ßT¦»J Àn*õñ†7ê°ËR+R~7‘R#H @#¢SCth¥ÆÐo*’€R°«J]c”š�c-˜º)•:Š 5�HLõeD€ÆQj ý ñN(5»ªÔÇÃ(u=³“©œZ5—ZaÔͤÔz舆»5!:4�RéؾQC©Ø¥>\aäwÃÔ‡‡ŒR7Qz²Æ}Ј(�@th$¥†S°m£†R°¥>&ãwƒÍ¥V¦';ÒÜQj(5Pj@MJ §`»F ¥`;JíMOv­½Rê–š×¥>ÞTQj,J @C’ŒD Ô4ºRw&�÷%݉N(5»«ÔoúÇ}«•ºžs©Ã¦ünî�ߪÇv@cÞ›L©¨@I¼Š» P›R«æR 9ð{ï”úPmQêæÊø ¥J ¨Y©;]ø}€›®D'”€z(õ‘#!ÃÔ{”ž¬¥|ÂoźÔÇBD©ç-¯.ö©È,Ö¨çÆlf‡”:¨m òa w�@©»¡ÔTªãþ €EwÇ&/ÏÊÇê¡}Sl�I¥Ž®ÙÞ^1ݸ:1HߎéÉV¶½ Î' W¸„.� úß1RÔ—ØÖ•Øv•:ºÞNëio“Úš=Cß],´jbP;c‚·l•¶¼µ–kÚ”uы☛Ö]œÐ4orÖToq�®öÐàDf¨Bg¿èÛ™Hˆ{�^@©€RZv­9j‘‹±2JMÈÊ�±ZÑì4ÄÉÑì3G¦Ôm„V�*•�Ë&ÉM¤‡ØÞöÖôè8!´P/õñŽôuÚÓ¥¦õ¦"©Á 9Ù¡•šÖ>?eLÍ‹Š"ôܧis,6­§§9ŸNë¼eù…ŽåH--ÎR�n[ÎöÊ‹fÇ´¯ÆýG÷6 ’.�b:1¯ÓÕçHoÿ8p(5Pj Ô€²Jý‡°¿x2uuQj-‡*NwDƒ”z†…WcT éƒôUT¶wÙ²Ëi®ãc|;}»aˆJ mé|¢öØø {D�ŠÉÚ–R¯°z{¬¹Ü¡”zãœdÙTê˜pcM§råõ®óåE2®Ùs©iËòËòEÕ->Ç£ÛB­ÅEç³2:�õ5ÀšKm]§³=4:,™HûÍ’}{³•A©€R¥TPêã�JÝÀëRo#J­EV.ò�Éí§cJ¥Î‹ˆÕ!š6h¦0c ;ÌÒÑ"Yá²9ÂÞ%7d±y¾~´ µØ¤C5ûøÆñ€ÙÖ¥n5•š6aYD׸àHA °j[w+õ9³TÕ-.’9ñö¼©ÔgÌ.šð5À£ÔžöÐèØ"mË5”(5Pj@8¥~3ä"ZõTêЋh…[—šÅWWgø„ßÁˆJ©¥CGX¸U#¡…a÷òqßrˆè ™æeÄ(î"Yâÿ®˜¾¬ËSí<Œk)µxV!Å*”º}DÒg*õ:!C)Æ*Ëf7PàPjѲZLË´YµõÊžà>™ÚÝ�R{Û@Ãc÷V%û†R¥J ¨¥ö ü>R©÷HªCg' ¯ÔŒlÛaC“ýJ=+K´“sl¯ÈÈÅßêeZjúð!§˜lf¤ žu jǸ\v(u»8ðlUJ=ï|Ë•zÆŽ\Ó¦Ú ô)uFŠtÕ-NY qÅL¥Çôð“¹àQjo{h|DR2e²o(5Pj Ô€JQê0ëR·Ô5J]>L]n -Õ\j –yLߥnã9° s»¢Ôg)Ha�­¶¸Jíjq�•f—ïWjw¢›I¿È¾ÍÛË3wO9”º†kZ†õÁÆ€®TjOxåÌëô¶€¦J ”(5û{ÀÁ¤ ¥nØôdœºì"ZªŒßú¬�¾œœëËÔ½ËB©ód!Í—‰:+Ó˜M°áÏÅÖ˜ôÊh7î^qÌœˆ]”yÂG¸új½¬L¡o€�$ êæy,WšôlíJMÛÆ›°Ðn7AÓ²gØ»B«¬æt;Sê˜�y»ú³ƒŒ”ÕÄE[ÇDäDmO&ƹR‹ëô¶(5J ”€}«Ôªu©CF©í•TóS…ˆRUdüX—:ÒѺìå©gÓnöîd$ÛãÜ�ìÉzÅ_:ÙØ<¶‘LgÓQWsSÞâU¶Øèë“)Æ Õ€SQO÷EáaJ €R°�”z¿ÿmßOç{;ðûþ�ßG-ã÷¡ZçR+5ní²´Éc‘Ù€(5”(5Pj(5”TVêò¿×oÜ·R©[ö¡R7ÌÜãØEBgÛ–òÖªÜ\’Pj Ô@©¡ÔPjPF©ƒ3~WJO¶gùÉ…šKíø­ÎøÝ¨Ä"�NMËÜçq�€O4ƒR¥J ¥†RƒŠQêÆ5ê°ËR+R~C©kC_›ŸÍdq‹¥J ÀÿŸ½ýjãÊó¾aãÓÐλ~q½â…_°zÝÏšî¥+Ïð@¤TºŒÄD0˜-�8càqh/bV|áŽs÷83i9žžîp°q»c'™ÆN'“žq2ÝkÖ²�;q’žë¯yö©Î»¤*Á÷³fbUÕ®]'¹]ýöþý ÔPj(5؇(5 £Š–;L]•J­…5|!¨’¿šxõJ ”J ¥‘Rs©O#;™Ê©Us©F]MJ­ …*�r ^½€R¥†RC©A)¥>^bäwÃÔÇ�ûŒRWQz²d8ŒìÚðÇ.Uæ@¼z¥J ¥†RƒH©�ßÁ�K­LOv¢º£Ô aj‚Çyå” ¼z¥J}D”zx 8¥µ‡wµ ìw”úä‹h”R×ìº.õ骊R#L @Õ©ñ’”(uxhHOe[?4ZåJ½04¤ÿ†ž²mΓÑò�Ý=Æ|ýnl%\¤ÒmUp\©_q�ûV+u%çRûMù]Ý¿Y˜:8¥©ò—.eÞ@¼z¥àÈ+uŽ�n']U®ÔÚ4Ö ‘ýWêÑßù@Õè ¹VÎvxn¥v;õñ€¤'«9¶»(uueüް4HpjfÔêæðê”(5ÕÁ‘âԑ‹d\~šp\̾)ujaat²›�‰�—ý‰*ÞOɬç6pÐJ}â„Ï0õ¥'«)žð[Q—úT•F©Ùë;œ€jø+‰W/û’80‘`!Ö>»R'mÿnFm¸>J©S„³í$$l»¥Nîíx9ýx³„\TÝëgÛmµßcóôó© ÑpØ«\7¾Z˜ï)‡RG&¥Ã[ïŽ6’'«r‚º60¾º:Ô•G_è˜n 7¼»SÜäÑ<)L¦èçkÝ«¤¡»[Ó·Ñîò$ßÞ)O:·X mˆÝíÏß„WéÉNl.u‰üd'<�útµ ü¦™cáðyH5AêóápÌ럈¥Ôÿ?À�°;¥D„•+u4/æ±wÙ™â ]r…þq�KÞ¾ª[«ø?òª Ü#dHªuÈ~)B© áy¿¯1áŽ$ÅöÐî�g*µFÈ€ãîhôøÓ„‡�“ýâXStCˆL4²Ê§§øM–çщ\f»_¹¢éÛDwW"l·î_šÅûÝ~)µwz²Å£Ô�MOVµ¿ù_ª0}�×¢Qüˆ@å~ÛŠFµ˜wˆJ ”(5—Âh#á¾É•:D®4Fc!"m�\‹Æ¨ NÓuã¤@WµRÌ% ¤#�J�Áâ™Öì—¢PêY2Ý£Åf Y(ƒRSžtÜ�)ä"ÑËäJŒEÍIHcçr™­'…Æóš©Ô¤#›ÌÎ�Ö¿>ð›oË5�qºiœ4dønÙäÂ8!˜f½/J­JO¦Rêš`Í¥Vü>QíéÉÄË<“j@ÅÑŠü°ÑJ ”š*ud’ëWêl¯©5Dê¹í FxA§6Ñ’ºÜe’� ÁSjªÎì\/�yÇ¥¸•:¹Jø˜ïE~‘{VjžÍvw&Eð?Õ‹$§Éû|ùJž»qÆÔfz“yf³X�7±)u—ؤMˆ;øn!�ðß}Rê]Ï¥®`�Úw”º •šEÈ´X >@åˆÅ´â#E :@©€R3¥¦Î6•´düNÆY̕ڗÎU.qI®t‹²‘ÐÁà)õ¡Ò]•×ÌKq+uŽLóׄQ¶ÇÞ•z’)µíî r=c¹Ë:!Ò±)5PäçiSêE¹é:Yd»�É-=ðßJüVÑ Z~2E]êªTj@ÐÙ¥$n$ H@©8LJÍd·I¥ÎNv¯²»B©„Ró—qî£cF%æŠWÜR*uŒ�e)$—âVê�q%$¹ÛãY”:O.8î›KMÆ&;­-”zÊ®Ô=æ�v¥Ö7õ°1÷!1Mœhïpû¬Ô§v6—º¢S©‹+õ©êMO8ÄJùòé—-Û>þä“–Ò=¼ûûß¿í½õ>ùäWP0¥¨RGêÉ•Wêž+TgÆ=•º@ȃ ] ¤RGÆÉu饶Kq+õœ¼’ü•¡èn�g*u”go³ßmtœ)ýd’0_D©SrµB©ùB£Pê)(õ>+µw˜ºDÆïš ü>YµE´‡Y©ï<}úô¶zÓ/··룇ßôQ¯sÝû�)ËìSü“í?¶ÀÁÀ‘Pê¦æÈQœ$Å&¥Dš›  XJÍ“|Sê<gÖ9è¥Ô<±u P+õ0™Ð®ð¶]Š®Ô|r³ÓNÒ°çã™J}��¬âî$ûÆY*ï¬}à·C©/ó¥v6ÿÛ®ÔãrÓe6¨J½ÏJý#¿¿<™Qj@U(õ?Q¥¾¥ÜâS†{?úè÷ΡãËOj)oïD̨n¥þ_ÍÑ#žp$mþ_@¥Žä¦ùheMäÇù«UJ]O:ø0él_0Ó“E¢ ¤�Ç{í—"”Zêë8³S=ÏW¬/»w¥n$ü˜¶»“ͲmÉ1ÒÆbØÜƒ‡æJÍSši<±š˜ù-·]'3¬»è ‹€C©÷_©O{*u€ëR#J ¨:¥Žðåqå–ÞÞþ¼ýÑG_8§g^k*uÓ¿mo¯@ÂÀáVê¦(2(2¢ˆUƒà(5Í¢ÔcäB2�ôøÝIȈIŠ l•:BÏ]ÄŠm—’—uÂò9Qžâ ºž!ý{Têðèà4™f÷Èvwò¼"vvš™ûE²Joen•ew)5Ô"ÚEr%Çcêc1c[–�vºi�w¥Þg¥~Åg­J*µï"Z‡¢.5àÐ*µ·kÿq{[óÑî‹�>rN¥~¿¶öÉC©µ½ýï�0p˜•B ©ATjj˜L©ë i˜™&žQjžÕ+O5°½âÿŽ{(5ÕZr>q\ŠPêFº­»@ ÜNYú°B7áb½{¥–De+ëÝ&dµcˆ�v¬Ú„®Ÿˆ©¢Ôô¤ˆ¨ ¥&ŒšÕlIߥÞÿ(µkà÷IŸJ}@Rí;;”P�JýÛÛðÓî÷}´äöýÞcC©#ÛÛÿ‡…�ëÔ-i+-°@PY¥Îù®c <‰÷õUj¢¡Y^¬Y¥Ô‘ÐÔ4ÕùdÅÿ÷Pjj£2ìl½”!¢¡ *¨#s¤ƒw0É–3»?^FúôМžøÛzwR,åwa–ÿd¤ÇjXŒYÜ8Ò­§'›¥ûÌðÂÕ‘äõ/j-¶EFiwÓS£›R£ˆÖ~E©ýÔ¥®©h”ºx˜ºX -Ì¥TV©ã7oß¹%Û'VVä°ìÄ�[wnÝ0ä÷OÛÛ¿¦´œwÑ\|*uâ³ÚÚÏšL¥nú×ííX8¬Jý¿4X´ SªAE•ZeÙ™ºÍÅ‚ð︗R¿”pΚß;œ‰–óxλc»SáVe{ö»…µ]RÓìÝEñÊvPQêÓ>”º²s©w›ñu©•Uê·>øê)ãË;L…[è'¾úŽXû•Lÿ�ød{;Lÿ|þÌÅëŧR¿W[û$iUêÙÞþ, R¥n:‡vrƒ¿AÀ”ºZð©¸U{<È(uuÑB”¥¾úåS�¿Ä ¥ŽÿÅXûgtËáÚ¥”úÝ�>z×Öï“ÚÚ÷›¬JýËíí?& aàP*õÿ‚Q«œqj¥†Rƒ(õiE´T¿�U²ŠÖq?“©¡Ô€J*uüc þàÖmöç_ ¥þ€¹ô­¾–×Ôúg9•ºõùóŸQ�~Ρ~öüùù¢S©?­­ýüÖ­ÝBMZ|zñìÙy{w½}ô_¶ô;µµµËM6¥núd{ûÿ�†�èÔÈLæA/T@©¡Ô *¢ÔU;ð¿Sjê΋dqúñŽTêýï/„?ߺuSf'ûJíœJ§*ÍWX•ùÉÀ!Uê&¸³˜N  ÔPj¥lz²N]´ˆ¢Ô€J)µFÝY„}ãæÍ–(õŸm•®þ}{ûW>”Ú9•úýÚÚÇq§R[úà0)5êQ{×§† (5”TT©Uu©}F©�”TóCùˆRŸTdüF”P)¥¾E Ú¦ÎR©ÿÂS€¯˜›þ`F–‹)õï>úhÙ²¸ô¤¶ö�&§Rÿi{û7Ð0pø”Aj„©”J ¬Ô§½‚ÔAÉø}l·s©¡Ô€ *õm9UÚ©Ô-‹Z¾7æ?ß,­ÔÍ}ô_oZ–yIj—RÿU´À¡Tj©‹�„ (5”D©‹ü>^¹qßJ¥®�R‚­Ôw<”º©åY\K¦¦JýËÒJí˜Jý/I­RêßBÃÀ¡Sj©‹‚BZà`”×ÀQŇR{gü.•žìÀò“ó5—Ú5ð¿•�R©Tꦦø/>¡ê;2¥Ø?–VjÇTêÏkk!xR[ûÙï~÷v“#Õ‡G©›ñBWŒfØ €RPY¥>x£ö[–Z‘òJ ¨”RߤÊÜ¢Vj¾tûKêܬ*ÖǾғ9¦R?®uð>Ò“�ëÔ÷�e¿*{ˆR³àq0ªh¹ÃÔPj@å•:B ú–ü¼rçΊC©Eþ²M>‹h±©ÔñÒJýoÛÛÿ ‡N©ce³ÏÌÎwiú»€+u 6 ÔTV©OûQêJf'S9µj.µÂ¨¡Ô€Š)uÓÇOŸ~)š^ýϧOoK¥þÅ_þòAˆZ³*[¿ÙÞþX¥Ô±"S©›Þ1yR[ûÅ;ïð‰Õ‰?noÿ›R{O¥žŸ™IY»ffÚ¼Í3µ8öZú\¾}‡Z=�N‡vÐ|vfŽþ÷ïø)=óoüä§#9äüPjŽ¢R/1ò»‚aêãÇ}F©‘ž P1¥fQè�Y[–ãû˸Têô¿ð Õ¿yúô+xþÕöö'*¥~^d*u“=`­§'‹noo_…†�æÔÞS©Ï¥Ó?µ/ö{¶¸”¼Ú¹#_ýÉΔz:ÝEÿKøÃáö3☤“©”€Ã«Ô§üdüØ\jez²ˆR‚¤Ô¼õÓ�ó±LD&~³Å/s›§ýæn}•zp‹S©F?½xÝs*µ‡R/˜vÀáQêH±ò%3<—.¢ÔõtãØbûÕî×~¾³�ß#;Y~&� ‡sé4�ž_ ç73¸ø*=æ.ãÔÙ™¬±Ï ®G ƒJ @ ¢Ô'wXDë ”ºf×u©O#J ¨¤RÇÿòTòÕ�„¡Ô7>¶­¥üÁ(Lm*uìsj³«�>ú¨¹´R£†8”J-¦Ôévci¢ˆR·¾‘>Ãǹë.eg4}‰þ7ÄÿËzŽ©uëOÓé¶Ýõ—Oÿ„Éxßé‹ÈO ÔR©_q�ûV+u%çRûMù¼�ßɨ‹…UF,¦E“ePê¦Ä-®Ï_~œ‘s§¿âkï|)Ö®Èf¿1D¸ÙPê¦×_X•zù£�~×TZ©©œg`aàÐ)µVT©‰¾°�.¢Ô}ét·ø”»”~Uߣ§¯Õî±D’3�î¡Ú¹TOÖ>;;å ·§ÇèùYؼK?úOw÷?G�çÒ¯æä=Ñ ƒJ @ ¢Ôn§>�ôd5Çv¥®tÆï¤3 zÑ’{WjæÑ++Šæqͺ6¼½ýIB±kKÜÏTj +ÛÛŒÃÂÀ¡SêX¥¾”Nÿ½\XLŸaJÝxæŒôêú3gæô–=¦m·ñ¹Ñ™ùר‚¿¶(¬87õ]:7(š„^¥]]ヷÏ\=Œ1e?'"ÜSgÞÈÌÐýÏt[%»£»›6é–ÿ ÷\¸ {O§‡vù?E çÒcÔ¨§‹ ?Pj¥Ô'Nø SPz²šâ ¿u©O#JÍ„:¦E‹ÇºÁ#�jì^+‡Rû fR2¸üÅG½]º£ß`Ü78rJ=óF:/ãÊôỚϥω5céKF9s)}Ξ–lHf+ãáãN"—þokR±K̽ûÓgø”j=»Ù±ókÝbñ\Æ:�Úʼ%¹®Þ)æúä稢 ÔW©}¥'SÔ¥®© ÆÀï€Î¥NÒ€X_1ª•(û;œ<¥núåööŸŠÏÊþ/ï©Ô–VŸlÿ±ŸRK¯=s1}&«këßs¥¾�N÷ðÐðëhë1j¿#–�ò`:ýjWªëÕtšE¦çÓéŽl&ÔÀ³{ç¨~‡2 íi>B\(õÂé3ý¡Æösét½ôñ|¨sŽˆÝ¥R··Ócw´·ÓÞúÛÛÍò^m—ŠG™‹3L�Õ‰ÂÔJ @P•úEz²“›K]"?Ù O§®dÆo¢†PPÝRí¨.»7üûööJ±íŦR›üóöö¯à`à¨)uç77¤I˜+õ‚ã]ŸN�Ú&%§Óg¦;DT9›Nf¹9’>“a•²xd;;Öðwáð€Œ)·74ät¥þ©tçÔ%žyŒ*5Ž÷�IOXO(”~Íø¯`jìÕKéôXv×F�£žŸž)Þ: ÔTT©½Ó“�(¥lz² üNÒß0à€*Çû/rÙ½!úÛÿZl»¯©Ô-ÜþfRƒ#§ÔánaétzD(5•ës".}Ζè+/Æe¿ÖÁôv@÷íÓþIú53LW-šû ¥žÖsšµóúXC2~Õ~‘—ì‚?®—µ¦ö>’Ù­QgÆÒot]JOA©”€€*µ*=™J©k‚5—Z=ðûDpÒ“Å`Ô§ŽŒR7ýêO*6dûí÷ß_*ÙGæO CÁÀÑSêP:Í’�u° ÕB©ë¹ïæÎXg3óxïìÄk\p;ùHï¶9Æ,SqêÍéKSsrpöÏ©{¿úw)«RgΤ;Œ—‚R(5AWêS;›K]Ñ©ÔÅ•úT¥Ó“icEUÇye˜¢@€”:w)½þ =ëJJ§{rglR›ë4”v‘M£^ÔGn[#Ø‹¯¥õñÝá\ \g=~»•ºñ Vîê ý¿Ôð;S�f~ñÐ.çR;þ„R(5ÁSjï0u‰Œß5Aø}²ÂE´¤à°‡©!:H©©Ö¾6*’tK¥fÖ§Ïäl¨Ïô™©Ãm¶tà:ÙKéŸX“¥Ûôôd?q¦'S üfyÉ&xE®î°LB®ç.ëH§‡Ãût@©¨œRÿÈoÆïO¦\”:Š 5‡‡˜ê'2ˆARêžtú�ô‹R/¦Ï�‰*WÆêtz¦Uø})îLËRÑsçε…SÓÓ¢¼ô9fÎýÓ �² Wȳˆ–R©»yF´ YÖ+<"«q…;ß`Ç„R(5‡T©O{*u€ëR:J­y•²TʿЂ¤ÔáWÓi‘c[Wê›ÌK"í¾F˶\£»¨u®±§sç§’ 5¶†ÃPjp䕺‡ŒûyA÷«Ô“dÈõOwžÌí;µ*Nd"¥å‰RŸö¡Ô•�K½ÛŒß§*¦ÔøfpxØ/¥^ÞªclmZW®?´±®h©lÒÔ¼ñðá‡qï®#ëubÝ2{{y›Í�´ÅÙ­û÷Ù|ððášr©y}ëmþ`ÃêØ%î‹[I=ÉÅì¾jiiËÖ#7jóÔ¶"Ž3¡XuKœÀ²ÇõlYW,I;Ó—mªû±ßÃ{ûñ$âÆI<è-Ó“Pu¢zö~K= ×Q”÷Ôy»§¢x€OBuÛ-«Öè§ÍTê66nûï¡ÔM©¹û&SyB®”~E÷©ÔIÁ=í£ˆ–jà÷±JVÑ:îg2u1¥ÞÛlçây Ô@©KFF¹£¬­3õ¹k‰�>2‘Vãl©h¢;XÜ«ë%öyk}ýžt¬¤½¦Ô܇m­o|ÈÂÌËVY³«Û}ÓÙlˆø¨”eæy7vãºH²(ubËTaÅõœµìõˆë_ï¿€ûüî*û1â·u;SjÿO"Á޾uÿ>?—xyž„¢Õ“°÷[òI¸Ž¢º§®Û¥¸÷ôxªÛn]_ߺŸ8@¥fÓ—ûÃPjʪÔZ.«Y¥PËfmêÎFmê;Å’v¥¦+©Sçeƒd8›ÓЍe8v©¦õÈÑÒ®mï+I®’IaB¤¨y—×Ý3oL‰ë6”:ÙÚ™ÁäÒêŽR+ß·Ïôd^J�«ï(�‰‹»×êâ?A©€R—šûJÅ„¿�léúéš°ú�+K±–² ÛRwV.Õ[zHqÉÝ µ¦q�ÜêÕ=x‹x$úêf[â.Ë…Š|S7¨�fÝÿÖäp_eh’âáYgtÙ¸ž¸<¾u¶~¸ezEú‰SýpJíÿIð[Ć´'Ö\£˜Ëò$d'Š'aï·ä“PEqO‹Ý.ý’ÝÐãI(úÙé“(«RO4ü´- ¥ œJ»Àæ/¶êR˜�bËC<È#äÚp7]Ô’¡ý3/_À³|Âò€C©#á B²\ˆ¯x·¼½1„{��>¡–רæîF›R[�‰ô‰�b«¤Às�¥×åQB¼ã้‰añ‰��6#„tq��!Wö>áÚu÷¬7fœÌˆVS|V¸óº¥vD¯³ó õH‚\ÅQêªø­ÊøÝ(�ü®ÕJ ”zÏþe$ø‘Ç$S‹êzµMz™km,éÂ¥ØaÓTÀˆ³]ž6êŒüQÌäzÅôׇ›RÝìKKfˆ’™Óº.�͆wñi¿ënmæS¹éI°i×ËêKޏ<,nžõ]KTZÕ=äÖ݈œÿ'Á.ð^B?ˆ]‡Ëñ$ô㸟„½ß’OBu”ˆÇ-ñ¸]òTÜÐãI¨úÙé“(wz²0”€r*utH¼=…æäëô*{Õ2//vÉf­ÖFBN-J¹FDþ°IÙ Àþ©íÔM¦jÙ.7÷Y”Úvd®¾\¥¹À‚¿cB­sò %þ…'ž¯ôÚ„œ>GÈõ=¿IxÝ=qŽzÈ~ˆ»µóº¥vè·j/fÁVêÀ¦'+áÔE‹h)¢Ô!úeœš#¤á<”P ¥¾gª5�EB£EZÊ&ɺº³w› ‘Sì@Wm½©ËÒÆÆšJž¶ôÉÀÔà„+Qi»×Û¤«›}‰I[³y”{r”ó]#•ÖÆFDìÔ« ßc#”ÝJ­_ò²y*–)Ó²£fó0ª~ØY,{ˆÜæƒk{x˦BöÚ=—çIèÇq? {¿%Ÿ„ê(î{Zìvé§â~€ê'¡êǾ*±¼¼¥†RƒjVj*yùk¹á~æ²,ê:AM³³ó:!c1n¦db8ÓÃB« ¡Lß�pÅVº<’Ê Ð¶!‡RgEx¸ž÷ÚHm1¯©”š.gSTš2†RÛ�Ì4TŽðîà:+gG'WÉbéá‹Ì¥^ d( ¯’üÞãÂŽ»ç¸1n¥¶]·ÐŽ6BfFs£3„´áÍ,xJ­ªKí3J}ì ¤šÊG”ú¤"ã·;J�¤_b>ÖC›'dJ ¨€R³XߦER"ž¡Ñb-e“$Ob¥ —bë*/_d"§§!k ¬6êÖM¥¶.-›©²˜Èmˆàé–s¶,íôMe`ølD¡ÔºÝoš§b$ÎÞ2dí¡!rŠ~âÜG=”ú®«ß�< öç–%ñÖz™Ÿ„õÇ Ç“°÷[òI¨Ž²©¸vïÛ¥ŸŠûªŸ„¢Ç*öã”J ªX©3D“B … ²hs=Wj3¦NÌÇsk«d\ÄUÛdLv5iWê(ŸLÖ½˜vwY©Ô|tw—Í ¥¶9鿇bÿZ¯’ -+bÕ”¼»´–‹!SÞ[©�_‹,’é½ç:vÞ=Ç�Q(µõº¹vÄį­› ý¤RŸö R%ã÷±ÝÎ¥V*5ýRË¿yZƒþvÌöײ¶7èhVt¢årQ«RkY J ”z·ÉÉô\Î GÄSÊ”%4êÑRoÒÌK-éÂ¥Ø�®zÄd7¾ä.¨|_—§uӈ֖¤ ÕQÔ÷Ôãv§¢~€®'¡êDZ J ¥U®ÔÃºíÆ„æuͳ÷jªÆehX¼[Ï�n¾M¾iÏñ‰ÍV¥¦Û ‘H£¾&Z`1e·R׋uÑ‘Pjû‘#‘™7Ïq$OÆäëù8™(éA«úèqI§mÒt4OV©¸ìýEÂ}÷l7Æ­Ô¶ëæÚAoÕ_Ù(g¡ƒ *uñ�ßÇ+7î[©Ô5»Uê¬9i¢³‡½í³ýEš„¢üͬŸæJx�+ù�®ÔY6)¢{J ”ÚƒÞß;xÛ6�×°”ªâ}™û©HËûÖôP†p)vàáÕæu^êxÝ>ü¶ù¬.OI6]—ËðæYkvÃvLc‰Í&Þc¼i¯½"¥ôfÓæÏ5}7¡‹äV|�eÍzp¿×ÚSF—R×CÏwsiƒjÝ£{›ªXW?KÂ/w ÔþŸ„më]Kl¸ÛŸ.u4fXú€viÛCs��üw¬ö¾lׄ˜ˆ}…�+mÙLÛ´²æ<”(5³ˆÿrð¶Õd·¬™‘7¡Q1ø×»¥cî²%´sö_VwIØÑÃ¥&µ–Çu!>{7ÑTJ©e=d®Ï½º3±nq™[OÈsb%–p%‹slï7)”Ú¼qx¡e‡³½Å@uU?TàöîL©ý?‰¸5Áu‹9è¹Ý׈9+”ºØÀï‹„ô¨~÷èÂí5ðÛqäH¤AÏGÆ|•È$Ä‘’s©£SŠâX¹˜}ñ S†2$ó;ð;ï=ð»^ÆŒRUêJf'S9µj.µÂ¨UJ /^á£&ÚcÏÙþƒ„$ù79+¿ây1“¢§þ:Wên¾”Q&²‡R¥.N©Ø¨™¡Ê³åº#Áv‘Ø(W¬»f¥cÃ+{™Ç¢Žugï­oðÐæf)¥¾Ëzc]Ì�~S*µ¦ÜLû8+jj?Œ˜Ç½+KIo6)”Úr=f©Þ-Û,eÖH*¶ª£ §R/op¸£rîîâI¼i�R÷ZüºOÂډדðPjדPEqO½n—==šóºž„ª÷*(5”ºôd%•ºHz2*ˆ«š+=YNŸQy¹hz²Û™¿YÿmݤAþ£=ÃõÔ‹ä¢,Œ]̺ó¤rü®(‘žl‘4ˆ®z§'ë‘YÀAõ)õñ#¿+¦>~Üg”úeÞ{íÚ8ŸÝVÍö×r �£ üg¡IžÚ^–arE&_ˆ*ÿžA©€RÇ–0Ú=ƒ×¢º^-­6ìœÁëÜaÝ:'yÃ"zyâQÇû|aé�už¯Z©—±ˆ´1•w]8“Q‚J&§Š¬­-[NeCt°Ñ¤Pjëõl®Ý�[‹[ýW¿E?ˆæ:•ún�ƒû»x^s©Ëò$,�x> µR»Ÿ„ò(î{êu»¬×£x€®'¡èG± J ¥‡¥ˆÖ¸QŠÏCŽŽOLy*µW­$P*>v^†².ÓõÓ"›·V(RDË~d6XZF£c’Ov•}H‘ë™t¼Ú«¸Î¥v”CewÏzc.ËøÞñ.¢–Ãj#©‰‰¼šQ©OùÉø°¹ÔÊôd'|F©åH‹úU™Á>Û¿qH_âJ-~5ê4æ<èJ-§m@©€Rïæx Kñæû^¡QÏ–ÎШ-Ï´c‡ûÖ#ËÓ¬�§%K›æ-»’)”š‰Z³Ù#ÕK6Ú�¦ÄYû€m1P{‹—G~Ô¢RêuEUkYbÙzêb޶²Ÿ„yÖ;PjÿOÂ+ãw9ž„µÏ'¡Vj÷“ð>ŠõžzÞ.�'! ëI(úQu ¥†Rƒ*Wj&½ùP®g‘)ÌPë­ïˤfôºÔ*¥n¥�fûr‚©R�ŒŽŽŒŒYt‹E«i¯©Ié‹´·ö\8ÅrK¥.´åúFih5”Ú~d~bbDt?[ª—­n-^ž¥]�J¼2zgùÄìÖi2±÷׎»ç¸1)BÆR±½†R[¯[hÇ,ë"“ëšæñ}Ü(õÉÑ:(¥®Ùu]êÓ^Qjù‹Qû;è˜í_ϳ}ç§ìJ�u¤ö†R¥Þk]êˆg5äË�–-®�¬Õ�;¬Yg/«e�¶y˜P�†V+õC‹2KíýÐ*Mîx/•à³Ü,·î ¨uo¬¯/{]�©¢k�Ý0dž;ûÙdš'VÑ£¸¾nžv|‰Ã_‹OÍ»x¶k2³y—åIX;ñ|j¥V< ¯£Øî©×íò|⺞„¢U×HO†ôd Ú•:*cN…E‘ö+»*CPãQO¥fQXAWD(µA—Ù r¹Àÿ©íœ–}êJ="7óè¶Pjû‘¹�ò­!1’[+�UÖ×p±èrØš6ÜCPµnÑÑeKþ³]ã¼{öÃF¡ó­Æ\jÛu íHÎËuWRx3 žR¿â÷­VêJÎ¥ö›òÛ×Ào-ld¨gÙì³ý5úu^HŠm¥Ž2¥J½#¥n~×A¯-P¸i1¥¤ghÔ£¥;”¨ —b‡%ë”\µ{F¬òd›FÌœ¨¹˜RGlã±EPÒ:Ž™ù5½åÍÍ^ûë-g¼xÍ}=Í››ËÖŽîš'¥{œªW(ú¬ŸôdþŸ„-LkŽ;/Ç“°uâù$”J­zŠ£¸ï©×í²]�ûºž„¢U×{Qê&À¾aýW­Ä?†1®tý­í2“ö·ÄÂóÚ˜{*ÈOeÖ¡N¤"c·¥Ž ]6þa�Öó²´‹ò…�¨WÛ¸L¶Ñwô9¶YŽtn“ïìÖ#Ów÷iþ2®­’1¾•ºt?� ’{Rêëòš¢ùrdývÞ=Û�‰D'ÙeNå¦xdçuO‹YßÑÙë­A�R»�úx@Ò“ÕÛ]”Z™ñ{��Vùq’¥°ÏöoÔe²)µ™ž,5p J ”ÚW-ïºÔÖ‰©ëÖòÅ.ÕU·Œ¸C‰†p¹wH õÀoÅ“PÅ}O=n—ýzÜÐõ$ý¨º†Rp”: ¤TQäTy Jà[©}¥'SÔ¥®© ÆÀï�Î¥ž ݓӲ«"ןm¶¿FHõp®íŠC©Ãc´q_n®[̃R¥.IümæÀo®g"Rš¸�Ý}$ÕÈ®ºŠ–®&váRìÐK-è!w¬å³Æàæ ›<ÅÚòL›‘OµR¯Õéy¦™¡Õ}(‹F‰œUÕ}¨³QF¥vß.v³¶T·™_àÖÚûÅàAsÙž„³¯'¡VjÕ“PÅ}O•·Ëy=®XìI@©€RW„ÌQƒÊB#Y�áý¨R{§';QÛ?ì‘kAË墻~@©ÑQá8Þ••–?3‘“s-Õ•ƒÙÝ7=v`¯J÷¤IýìuË`|ý¡Ô8k<ÙC©�ƒÔ}¸nè^&wvÝ�¶Íö㚘u©Ý×—r~výͦR"·å[©{ïÞ]òñ$unªosóº”ÒHùž„êò•OÂÚoÉ'á:Šëžªn—êËg€Pj Ô…Rïz.uƒÔ¾£Ô?Êä¥v�X¾»¶¶lÈg¼ÙoËw-tpsmM­”ænK›››ËÍ~�Ò¼L[/%ì=ÐoÆ�§R⸪¾é^öŽöçíjö>n/½‹›É*xŠ£ìîžîò:_Û¡Ô@©8´Jíwà·²ˆVÐò“)êRWH©“øjpXHî›RpdX®«{¥J À¡WêS;›K]Ñ©ÔÅ•úTÑôdûO,Œšq¢á”€½gÓÃïA©€Rph•Ú;L]"ãwMP~Ÿ,ZD J €Rp`¼Éç]¯A©€Rp8•úG~3~x2uà¢ÔZXÃW €Ã‚ò/4^Ãð¤æ)ÝPj ÔZ¥>í©Ô®Kè(µ2¨¨N”ÃNð€¥ÞÚX_Þý ?n Pj‚­Ô¯ø,¢UI¥ö]DËg]ê}'ÆÈo Qe¾A¼†pP/ü¸@©|”Ú5ðû¤O¥> ©ö��,0JѦà°p^9‘¯a@©ý‘ˆ'ð”€Ã¥öS—º¦¢Qêâaêb5´*3—ajy�J @•:ÚéÇ¿ùöåË—qŽy 6Ák�Rê[/_þÀÃÁñïé§ œ¼Q†R(5‡C©›ž¬„S-¢U±(µ TÇ´hÀ¨2’ѨóQC©šRk„ƒ¿yùòû2ÈðÕ«-æÇ«2è|uåæÊUË@î«+·n®Äõ�¬Yœ®Ñ\½zƒŠò ¹{|åæ­•«–vËÊÍÿ¾*vn¹ºB[®ðcÒæº[·ð�ŽŽ­ÇäýÞ¸yól@©¨¤R«êRûŒR;(©æ‡ò¥>©ÈøýJ®’¯åLªUŠVäç0¼†(¥^YÑ5óÖË—ßîý°+f/7ô�7¿ùÏþ[o#Òy¿yÅZ^¾üNÌ莛š/øŽ¥¿ÕÇ�¯ÈÎ~`­Ð[~Ë÷ºaû�ÀÖ±ý˜t£\þö-|U”€J*õi¯ uP2~Ûí\êJ+5‹ui±Ì€j#ÓŠ�/Ák�Rj3hûkê›û¡ÔñÛº÷¾¼ÃÃÅ7�å_¿%•ú›—JýÖ¯�Æ7yˆÚììûJ­wì8¦!æ´É |W”€(uñ�ßÇ+7î[©Ô5U¡Ô€Ã ^äRsñ-ƒ]º•šÕú½rõ&ÓßÑâåw·ÿz‹‰3›ÆÝ"ùöÍ[ #rþW¦Ð+++ ÖèÛ[½ý�<;¶ó¯¿YY¹-4zeå¦l©Vj½cç1ã´¿ïþzcå›ïÊšPjÀž~ŸÚqz²ËOvÌ×\j×ÀïÓ•�K €RP©ù8èÛe8¬[©¿“ÑïÄ|™Û,�ßzišï-‡à˘õM=:ÝB÷ú>ÁeY”úZ‘-Ìôdj¥æ»ŽÉö~KžãK„©”€D©ƒkÔ~ËR+R~C©PjކRóqÐß”#W—K©†´Æy0™6øN$KÜá9Æ[ÜFmˆò¯ Ïgž®Z§~/º-¡Ô·ô“²Óœ7~ceå-|Y”€ª‹R³àq0ªh¹ÃÔPj”€#¦ÔÌW}Ö�Þy”ú{QøZç¶ ‘æ!Ë*¥¾jÙô­C¼ïˆ3.¡ÔWÕÇ\Ap@©X”º¨RW2;™Ê©Us©F ¥@©8J}Ljâ:¹ñƒÁŠsé¶±p»˜R³iÏßß2JhQݽ}UÀĶ…›oB­Ô¬�l{õ[C‹ñ–«7V^úRê„÷1_Þqŧ‹]­} (5û­ÔÇKŒü®`˜úøqŸQj¤'@©8Jý�gŒzå¥5ã¶}é;s©˜RÇeïÄ�mË^/y¬¸…ËR*õ_ím`[þzÇè¡´Rg\Ÿý˜Mÿ-³†sÕïÕÚ—€RP&¥>å'ãwÀæR+Ó“�@”¥àˆ*uœGn÷K©›â·dË¾Ü�Rß²·ýÖ,'½3¥v“ž§^ËZ˜J  ÔT,J}r‡E´J©kv]—ú4¢Ô(5GG©=R“ůÄ�K-æRQ¥njJ¬ÜúÖ"â·WLâÅ”šÅ’-moðÔÝ/¿ýæ&ýüý΢Ôöc2ZDi®—ß¿åëjíK@©(‡R¿â÷­VêJÎ¥ö›ò¿PjލR7Åãe³D‹R¯Øj>ÇÿÊ*Y%\iÆŠ)õŠs𵥿Õ ¥ÖG¯çPêoÝ9Å…ê_e½ÿŠ/ €RPù(µÛ©�$=YͱÝE©‘ñ¥à¨(u¹j ò-›RËdc,[Ù¿JíJ~ËÈQ· ü~Kwì›¶mfÇ®cšRýmyÊq(5 LJ}â„Ï0õ¥'«)žð[Q—ú¢Ô(5G-J½rµ\‡�ÌiS¥¾qûö7"Òüß´bÖëºúÃwÅ”š…—¿•ôoX¦ío ¶fü¾ªëö†xÛ•ÚuÌonß–Áîo”º²s©w›ñu©»!z>æÄÎG¡Ô@©€Rö¥®®"ZˆRöÀù°…óPj Ô@©Å”ú´�"Zª�ßÇ*YE븟ÉÔPjÀΉ…mÄ Ô@©€Rö¥V¾oŸéÉ Ô€½Å¨½âÔxõJ ”°ƒ(uÕüFÆoÀŽˆ†]D¡Ô@©€RJ*u`Ó“•pê¢E´¥ì-H­ SãÕ (5Pj@Ä£.µÏ(õ±ƒ’j~(Q꓊ŒßˆRvDÌ­Ô1(5Pj ÔO¥>í¤JÆïc»�K ¥ì”°(5Pj Ô€’J]|à÷ñÊ�ûV*u ”¥J €RPi¥öÎø]*=Ù�å';æk.µkà72~ Ô@©Pj$J\£ö[–Z‘òJ 8âJ�ˆ&ð¦ Ô(5�‹R³àq0ªh¹ÃÔPj@•)õ—_~ù–üþä“ÑWÇ—ßîÝ[Ç-/ž½hnjú×OþÇ #€R Ôìc”º¨RW2;™Ê©Us©F]Z©Ã€#MP”úéÓ§-2ªü¯Û¼Ê?5ÿîó'µµµ�?}{Çݽÿ˜²Ì>=öìÙëMMÿ¸½ý/xaPj”€ƒTêã%F~W0L}ü¸Ï(õ+Pj@u)µ!¿Ë�kuÞÛaoËLÅk¹‰M•º•Šú¿é¢”¥à€~w.µ2=Ù‰ÝD©(öƒ îÁÑ»÷Wêø'ÛŒZüø³Oy¤úýu–ø¼ÖPêøóÏY¿ÜÞþoŒJ €R°Qê“;,¢uPJ]³ëºÔ§QD @©qï«M©ÿe{ûOüçµµOÞÑ£ÕOv4£ú}ºÃ©Ô:ñ?no‡ñÊ Ô(5åUêWÜã¾ÕJ]ɹÔ~S~ïfà7PjÜû@)õ¶·ÿ�ýÙl:ñrmmí;;è‹Å·ß{ìPê¦ßnoÿ¯ŒJ €R°oQj·SHz²šc»‹R#ã7€RãÞWR©#++-M‰·ï¬°¥–›·ïÜZ1·&®Þ¼s{%îPê«ÛrÜ÷{µµŸëM«F~ñûß««c%>«­ý¬IWê„v>ÊWg¶·ÿ€WF¥@©Øw¥>qÂg˜ú€Ò“ÕOø­¨K} Qj¥Æ½€RÿåéÓÛ¿ø’ÊòMMo}ðÕSÆÇ7åÆ[_òå¯>n±)õ¯¶·ÿ]„šß}wYwäǪ(õï?úèMåa©Œ?IJÝòìÙ3¾:þÛÛQ¼3(5J @¹•ÚWz2E]êšš` üÆ\j¥Æ½¬RÀÅùƒ¦ÈÇOuîpKþ‹±üåU«Rÿ«¢ØøÝë[©{Ÿð˜¶K©›þm{ûWxgPj”€²*õ+Šôd'6—ºD~²žN�ŒßJ�{_a¥faèîü"ÁŒúãnÿå?éŸlðw†/ߺõ—¯èŸV¥þ£œJm5êÇl ·o¥þ´¶öó„J©‹œßJ €R°Jí�žìDñ(u`Ó“aà7€RãÞE©E ú¶�¾ú%]E…—*öÇ|Êô-*ÝqS©ãÛÛÛ–òÑËËËï}ú„:r³o¥~§¶¶–�w+õ¯¶·ÿïŒJ €RPV¥V¥'S)uM°æR«~Ÿ@z2P9­ÈàŽUP©Cíár¹¬Jý•˜)M ú/bÝÊWúè#ñá K-­¥'zrp·R_ÝÞÞŽã¥@©PjöI©Oíl.uE§RWêS{IOF_ÛÉ”xhÝE2.?M8¾PêŠ*u$cÿ]$³SêÛüÃí§6X’°øí?ÿ§¾lQjÕ|çä§µ¶"Z¿ÿÈ�%Xý™‘ÉÌ­Ôlž6ô@©PjÊ­ÔÞaê¿k‚:ðûä^Šh1¥&}v¥N&m¯î¶?\ŸÁ¡Öº!bäw'!aÛ—ÃC©“¸�û«Ôö¿|AUê;.¥¾ú±eÙ¢Ôÿ¸½ýo®~T”ûRêwxIj¥n¡JÝ‚—F¥@©(§RÿÈoÆïO¦.{”ºƒ4S©£]ùééü,qŸêÎÖw“‰¹HëÅ’—ÂÝÙÞMf®#7ôÑкdAÊ\;™²9„Rwwó}zº'ÙÚÜøja¾wr_”šÞäÜb�L´ñŸ-Æ»;#׺WICw·Ì(õ-É?ݺõ‹¦ø—¼ˆÖ�[·V¾´)õ/•)ÄXo3CY´ø`)Yý9uo9üImíg¿ûÝÛ¥Ö¨R'ðÒ Ô(5eVêÓžJàºÔû¥ÈEC©£yÂb/ó2ź ä ýã:7ê+|Õ_ãA•h]d„ IµÙ¿B© áy¿¯1áŽ$Åönå~(uˆtøýå�é ’Š\f¯\  R땲 ~AWüB|üئÔ+F ±wÞ}ר%) cÙP¥'{\ëà}‹R‡‘ñ@©PjÊ­Ô¯ø,¢UI¥ö]D«,u©Ùk{#ávÄ•:D®4Fc!BR\©Éµh¬Ÿ�iºnœèªÖYÌ% ¤_§#¡Ô91à;E¦5û—C¡Ô³dºG‹Í²€{¹/JM&²É…qBbR©ƒ;ðûêSQ)Ëà#GYü+›RGŒH2µã÷¬QêÞ=+õ/í©Ï€R Ô”%Jíø}Ò§R�TûÎNV>¥ŽL’†°Têl¯©5Dê¹RFx¹ž6Ñ’¾É_&ù¨±¿RS›cOÿ™w|9ÜJ�\%|Ì÷"ÿÚ€}Pjv³5B:¯Ô,ý±Œ9ðç?ß²(õmû\j–BLã>«­ý\Ófs©Ÿ$ü(õ;&Ojk¿xç�¤E©U©Ï€R Ôì5Jí§.uME£ÔÅÃÔÅjhín.u4¢M�©¤%ãw2¶H&¹RsEZå¯ðIþB¿(‰zpø•z€ä#‘èªÌag~9ÜJ�#Ó|–ï(ÛìƒR�É¿{=ÁWê¢ÆügæÔñxÀúæÓ§_ñ°õí¯ìJÝôÉöö?‘éÏyª±æÏU´¼•Ú°v¤'ûÓööŸðΠÔ(5åŽRŸö¡Ô•�K½ÛŒß§v­Ô,�s›Têìd÷*›¯)”zA(5ï–ÛÓÑAÅ­£¡Ô1öÜ{H!éør¸•:d|7ò~ï‹RÉ…áà+uÓŸy¦ïßü™¥%û‹îýôËþBí¿™÷þVìÂJg=ùüÓ/>{B?|Ö¼w¥¦¶¾€wF¥@©¨D”ººŠhí=J‰Ô“+9®Ô=W›÷Tê!C 2t ß§#¡Ô‘qr]š›íËáVê9ùÝÈ_B™µò(µ>»b‚¥| ñ ëÕ¢Ôñ?%³x´úæWréƒ?Û•úŸÌÑÙï›S¢?�7íY©ãÛÛÿ�ZJ €RPv¥>í£ˆ–jà÷±JVÑ:îg2õ^”:š'ù¦Ôy2ÎiÐK©;ȾGGK©‡É„v…l_]©Ù¤€H³½NÒ€{XÆ{]%�ÆH�lµ)uSⶨDýñM±¼ò1TÿS‚6ú'ºü•Têø˜âûög"ÝØã÷T½/¿ýv‡R7ëJ½€©ÔJ €RP±(u°ò}ûLO¶¥Žä¦ùXnMds¦ïëJ]O:ø ÞlÒ“¥Ž6�v>;ÚþåJ] —E${ÊÈ›‰õeq/Ëqï;H¿A™4$½”z2HJí eeå†%ÚœXY‰(œø_··e.õ¾ÃRŒ•…�m¥@©8À(uÕü~e×JÍFí²(õ¹�ŒD'=~w2¢E’×xØ ¥ŽÐoƒ›`ûräeåµ|Ž�ûæ¶7N t!vPRÍå#J}R‘ñ{çQꌑ�9ÖÀ“x__¥Þšå¥…UJ MMSišCNç#£ÔÔÞdØÙúå˜áb MP©™#¼ƒI¶´˜Á­,Ó½èfùÓÇùÏ^¦R³"ZÝ\©“× {-_q¥n oo\þ^ãŸlÇ#€R Ô”_©O{©ƒ’ñûØnçRïJ©U–�)¡ËÑæQ)¥.þåç¬ù½Ãdû.ç½×R©âÛ’š¶×#WZ©Y­LÙ;ý *h(5J Àþ*uñ�ßÇ+7î[©Ô5¨ÔZŽÎ½€RGþô§,{§¿ý†}(5J À¾(µwÆïRéÉ,?Ù1_s©]¿w•ñ(5”º²J €R¥ £ÔÁ5j¿e©)¿¡ÔJ�{¥J €R¸(5 £Š–;L ¥PjÜ{(5Pj”€ƒŒRUêJf'S9µj.µÂ¨¡ÔJ�{¥J €RP ¥>^bäwÃÔÇ�ûŒR#=€RãÞC©€R ÔìŸRŸò“ñ;`s©•éÉN J  Ô¸÷Pj Ô(5‰RŸÜa­ƒRêš]×¥>�(5€RãÞC©€R Ôì›R¿â÷­VêJÎ¥ö›ò{7¿Ã€# ”(5J @Y¢Ôn§>�ôd5Çv¥ö“ñB”ºbJÝ»¼”À[{Vê„vÞI÷(5Sê'|†©(=YMñ„ߊºÔ§�ž ø�ß›ÖÕÕ�ݺÇ‹{Sê–gnpï€Rp`Jí+=™¢.uMM0~c.5 ú”:q¿Ng«or@©€RP¥JýŠ"=Ùɀͥ.‘Ÿì„§S#ã7 ¨J½Á#Ôë‰"Z€Ê+uïï¼­jÅŠi-ãU(5PjªS©ä7ãw€'S#J ¤RäÀ¡ÔÍKKËk÷êÌYÕ(5PjªP©O{*u€ëR#J ¼Rÿ—ƒ·ÝñiVK 1j Ô@©¨Z¥~Åg­J*µï"Z¨K �R—B*õÖý8Þä€R¥ z£Ô®�ß'}*õIµïìdPj@5)õòýûë˜T/áU(5Pjª6Jí§.uME£ÔÅÃÔÅjha.5 °JÍIÜ}H�:�w9Ê¥ÔágÏžaèPj2J}Ú‡RWv.õn3~£.5 èJÝÔ´YWWwïr”K©“T©_ü,‚{”€@E©««ˆ¢Ô€êQꦭººûx— \JÝô‚:õ³ó¸w@©80¥>í£ˆ–jà÷±JVÑ:îg25”PA¥n~×A¯ùâr÷®™ç{£®nïr”M©#/ Ô@©^”:Xù¾}¦'ƒRƒ ’ŒÚ—£É¢›ËOôpÝÏðìHYÿšL]ê»uu–(õ:Þ娣R[‰·´ APj‚¥®Ú�ßÈø öB¬ý }M¶k¼�Ÿœ‹‰¥ÔÍlÓCsÊöTgçòÓdlÒp´ÜìÐôêÔõ˜Çfëh¡É|a¼~ÁØ6|áBªÈi¨}þÚü™˜lŒxu(º.\�¸î4¥ÝÒ&´JHcõ)õR]]ݦåóÞå(£R ÔTD©›ž¬„S-¢µ_QêäÀdn_wÔR]³}ñ ˜(Ýha.ä·éµ¹ÎCô÷#U dÚ¶¦�&ÄSœ%†4GZ©ãé’çhцÄòjVaUnÏ(7[Ï œ—}]–]ÍŸ•§¡P÷Û;qv0ò$/?]&VVÍ&�„\ ¬RÇßv`üf‘éG£7ÏÖÕ�mÆ»Pj ÔT¥R«êRûŒR;(©æ‡ò¥>©Èø½_Qjú?´Ÿ;¶R“"íâ,¤´¹·s…ñÕô 94;¢#ÌÞlJ]O—çÛê©ø®òoÖ<)L :Ìðð1”ÚÙ>r‘ÚóÀè"! ÜÒRtûàhÛ !M±Ùz1ú•˜™m»°*õ7;aš°ò4”ÐsË_m§�´©: ®R÷ðË£§;Äþì· èÎV©‹±ô°®®îÁÆýuêÖu�6ñ*”(5U«Ô§½‚ÔAÉø}l·s©w¦ÔáÙYÿ�÷ªÔ¥F«a~xŸ|h¶íð(õŽ�o2ô‚Çò6¥NH�Ç�»©gv�I÷­%d\*µ«}VºóˆüÁ¤ŸL÷ÉØq£{³í æéb“®³«\3YÔvQaÕi(¡èg3©û¦…«:: °R è�Ñ3çŒjÑHu*uS siÁ‡Ëx“J ”€êWêâ¿�WnÜ·R©kÊ®Ô „ŒúnœÜíÀo¾c‰ƒE¯�¡ä¾>ù)2!¾“s¥ ¥öÕ´"J½£GçªÁµy›Rw"çöH·P¾ëÎÝbÔN¤R»Ú_”gJ]¡n˜\•.œ#dнÙvyùÄ"ó„PÃ#¤!Õª+µû4’­�Å7¨�ïKYCÄ�V“RËë³ôc•*uSüþÖ#&Ôg7Zð"”(5U¬ÔÞ¿K¥';°üdÇ|Í¥v üÞYÆïýñ²Ý,'Çåî¿Rû¢Ý:wõè(õjˆ©¦U©S„„ôaaÊל»QYÍéJíjßMòIÝm³ô9OLÈ¡„t¸7ÛΠ­+eh%Sê©pÄPjçiD¯7PÛl¨w¥öœ˜1~/ètwZMJÝ™âdªX©)‰¥ÍÍå8^ã€R¥àPD©ƒkÔ~ËR+R~—Rêd&Ux™–ËÆ¬1¾hV¼SkY×»u2œ�•¾Ñš£‘BiG9]²„¸G}‡å©†³QkÇa[á"ǵF.ÝJ­årîâJôFh ¥¦·-¦>sS©µlV5¯W}~î·³CóÚöG©S¹ˆS©Ã„Œ'õìÊ™:DzI›u×Gt¥vµ¿¢O�ÏÚO™nqoVœmÔÍÝ5Ú¯®Ô®Ó˜”Y¼¼‡ƒOšnjé´š”ÚB+5J ”€£¥fÁã`TÑr‡©ý*uvhšzGžCRB˜Éf;xæ×#mq•.öEZY¶äŸ«É0rò:Ë#V¸hLjC)]ôú"‘!×Rl�jaØØÑz0#®È:"‹ì|äæ}#ëc¸›®Ô’!Ö.Ÿ³ìTX”Ge « !ÚzÎu\{ärB ›åŠ¶Ì¯ùJ>d»?± üœZ…R‹¦ô~D/³4Õ3 î37•:Ëst YÓ{]…ŸûmïÐ~mŠ»Y>B;Â.4©±<ÜYq"�ì$úõ"TÚ™ˆJílŸ1FÄääj=zÌwPnvœA¬Ã”q]©�§ÑFŸÎhntÆ{¬CfÚæªÖN¡ÔPj Ô@©»ŠRUêJf'S9µj.µÂ¨‹+µîb¤ËüLÅ"·j®fἆq±˜*˜³75)3z8°�5zíÔ•º�2?-]Ów´ÌW,„ÍÂKm–æ¼Xu±K6ke}é�D¦¹4Â÷t×¹”W2Áå ÿ"4è;[®QYÑ©°ÈeZ4¥÷ã‚,d”s�¹¡Ôú=\ÍÙ"±ª«ðu¿íÚ¯Mq7÷M©#£òFuógœ£+–§¥Sϲ1•ÚÑ>EH�ìh•,ÚBÛS^›-gÐ955A�hüî¡+µã4¨aç™xjÝ„D•W�â§©ìJ ¥J ”P¥>^bäwÃÔÇ�ûŒRKO¦È•�l¶‹šÛùˆ–¥~’Éh¼~ÕH*70!æÁ2clÏf¹8Î/䨶D ¥¾Nåe.7{(5Pj Ô€2 üî\jez²;ŒRg‡††å0ÙÆˆ9!wR†‡™ç$ù"ËÅÌ ú.&…Bfu¥¦jWˆ í‘­Têé¬ìרÑ9û7¬»ç Øì˜K–ÆF»æŽ¤­ò™¹ƒC‹L%¢ Ü;úe*,¦Öm®ã:#—ú\jÓyÊèÜKm°Œ¼ºd‡C©¸^àFìí¯ˆVLø¤îeÆXÓ9BrÜÚrR¼õ±»Ãº7êæ¤]¯_ðVê}qØK©õ}¢>à×­ÔyÌS¯X=t…�Ö²Y#ª<ácÐùÍÑ•ÚÙ>Ë—ß=¢g"‹Äºõ[ªÜìzž›0bÙºR;Ncœ˜LжÔ1ntÞ!¦–N¨Ô׈ž�J ”¥ `JýŠ{Ü·Z©+9—ÚoÊïüæoÏÙÔ° ¥J/‹KÖåS<‘¿‹¶ÊÈ¡½£º׳!ãNÜJ-,5ÇC‰j¥®7LaœŒ)•ºMÆ.çùŸ‹z~f-·ÐȦëFY^ЕÚz\GäÒ®Ô�³0+Js±±)µ¼§¼ ç™s¥¦÷0/JDí¨"Wáë~;:t\ÛÁ)u‡qKÚÌiϳ�²_&2­”az“Ù°zg{M³ù™ëöœ×Ka)7»”šÝ§A»R;Nƒ5/ yzŸr%£ÆO%.E4; b”ºA<¥J €RÜ(µÛ©�$=YͱÝE©KeüÖ&e,«RgõA´R4'Iƒ®x­N¥î°c¥ÐýÇS©Ç�Žf¹¥»•z@Êè«R7éÈ(‹EŽQ÷6×q‘K»RwwyeëÕÍÛ•:iÑç™s¥ÎZf–;V_…¯ûíèÐqm§Ô«<-O‹^h,£_/J•³ž&»1ÎöôÒûÅr�ÝŸÒPn6ÎÀRãlUL#ã·ý4ê‹z'ý¢2úßE§TꈖMB©€Rï�Þå¥Ä¾œarsí®½ëøòݵÍ%[£fºÊGz_'Ùìjä>윖›KNqæŠsJ,¹zRž¦¯KPj§RŸ8á3L}@éÉjŠ'üVÔ¥>å/J�á5§ºgÆw­Ôã•Uêzžµ;?Å•ºÕ0³N•R;"—v¥6ûQê+%•šÍ––+äˡԎ+¦Ô ¤ /¾‘+ò²* ¯›Ý"—R;Û³â9éŠâ·†ä¢™Vm6ÏÀö“I‡]©§ÑSlwç´iÔÊNƒ@tþbHžU¿m”(õ®ØÜø°®®îìÖ}—â5o<|ø¡míÚCʲ¹ëƒ‡×ÄÇ�‡¤xnnÕ1­}Ä×ñU[f‘õ:ûªekOë'éÑè�óJì§�|h§WœÓYç9)î‰âÌÝ�š×·X«›Ž;i¿o®KPj·RûJO¦¨K]SŒ�ß»žKM°��ÛŽ–øí­Ô×�q½v¥îÑ-ʯR—ø­�QÚUaAfðвmrÚò€J©�‘K›RG•£~K üî`§ªø­Ù‹.½ _÷ÛÑáÁ+µJ±;=¤ÿö  ñC¦ôß1B„ f�f%sôdsîö¬JÃD…'mcî]›Í3Hô ÐõÆÍ°dü¶žFXŸ+�š˜èqþ�§–oþ�Pu d,*®ç2”(õ^IܯÓÙêµoZf‚ZgUê%ÞnÙ°L¶t_,lÕYJ½iö,»ÙhõH—Îå³F+)çw­=mxœd‰FIÝzí§°Tg‡Ý¿¸yæ÷ßô¼'î3W4ZÚr^‹ò¾¹/@©8ÄJýŠ"=Ùɀͥ.‘Ÿì„§S—Èø�'…¨©Ô!ËXS3]–·Ru„µ�£‘1 örq¥¶.�žL!£�úÚ!®ÔãòdXg·R;#—S2ºìHO–0G€—NOÖï�ž¬Ã¯Rû»ßöJ½_e•¥Ð.Š#ðjU©Xnt‚�‰(WR2˜Kæºè²V¡ÒÓ“9ÛG¢cô˦%SzŽïYVO[’to¶ÆÉiӱќÖ7O�¶+µó4hÓ|(“ëš6¢×ÆÈ ÚrV/«î4\ d<«±û°¥J½W6x u�\?ìU¸¶E©[V5”)•šjâ#ƒ%Ãz·Ö×?4$»w‹¯¹�­¹+:9+Ý3s­ÎÒÕ†ÇIº%X£G²‘Œ;O!ižâ#©ÔܨÏnˆsÚðº'Š3w7âªü`CDª7š<ï›û’”€Ã­ÔÞéÉN�R6=™Ï�ßyQ°9*~ge­^WQ'o¥¦®YË} JN‹ìÔZ¡ˆRg-…�…#ŽñDgžE´2Ú#ê:3cJMõmº-— M•R;#—ãrd±ðäA£ÌM“-E´ÆJ½Ú*¯¹Ë}æB©uOL•Rj_÷ÛÞ¡S©ws”º ��jЇuñ~VŸ�¿jûÁÂ(¢ålÉ®Êåëò–˜h®Í6¥ŽNê 'ô/µ‘žÌqÉy¹x%帜IËñFÔ�‚pƒ#K9”(õ®añÓ 6ù7ÁBÎë–¾¹jÚ•šzìóº®= „RÇ©%:bÜló².¶[¬›uÝG—é¾2¸-¾LÐòcQ•ß,y’îFw�p1Óí-�S°]̃¸0ã�7õ8ô]�ùÏÜÝ(atÀïݦÇ}S]2€Rpˆ•Z•žL¥Ô5ÁšK­ø}bgéÉf Yì‹¥†dz2êÇ mY-ÒÊy}¹� aqÅ”š¢»ç2)ª“y³ßBÚsáTžQjý`:õ,®˜KMJñõ;ð»áZ8×vE(5/5ĸ Rjgä’žr*£{rxŒžs_n®Û–Çz�ŸTÏ"q(5™à§:sŸ¹Pj ­ïˤfu©UJíë~Û;t^›ón–5\Ê�Ï])ˆ(tf‘Ûk¾^¦õ ‹ qCöÉË ÆO,Îö‘,û^�†¹ˆR©í›­gÀ†AçÙ£›�Yîh›ò4¢³\I]ß~§R+: â>¬:Œš)uJ ”zgP5½—0b³¦÷2›ÞX²)u’êäÝ-©†,†ýpsCWêíÇþ>»lÚ.uÍø#Ûàn¶qÓ ÔFô­ëæiï“t7Ú0¥™9u¯òLâù nÆ¢o¯ÞJ(§8sw£%óñ­?OØî›ò’”€Ã­Ô»žK]Á µï(u1¥ÎÉÐÞ¢ô>n%£bä4§+RJ©™uŠTT–a¿�ÓbÝx¥6fé*:â/ïþÒ“µ‹]¦Ç¥g ° ZíÒ”Jíˆ\òbź'›×<™4• Å ‹6¥n¸(#¢9Å™ ¥6£­ãÑRWáë~Û;t^›ën–Í¼ŽØBÖªuÚBh¡¨æ9ÚG²£¡¾"ú_ls4Û祾ŽÓHf²ŸòY¤Ó ’Ì ‡²ÉʄȡÔ*¥N<0éTDÏšHî6Ù”:q� gÖÕ�zä½Þ&C©—m!nÆ#Ëš{\:—¤é²�°ÔO¶áMýøk²çÞ’'éjÄNL?^¯Ô^÷)¸‚Ô̾›-qõeåáÜg®h´iéjÝò ƒý¾)/@©8ÄJíwà·²ˆVÐò“)êR-¢•a&6=«ç¾ ·7/ëd9´ÉØ€ ÕŠIÇ!9R:ÇmW“ñÁäu¦±…~Û+7P¯¶‰PeLŸZæQX}Gã`º×Ô,qÅœ½ê±ÑGAp¾HºÙmlŸ|g—^×*šK墬õ€ë¸®ÈåðWêY9¬8ÛÁƒ©ö)É1®áý­í\©ESª¼Ñ.æ·ù>Õ™OËüÕ Ür ÑÒWáç~Û;t]›ón¥J-Ù¼{7nšá–E©YŠ/›Rߥæ±(õZ¢ÉTêMcRu“©ž›¥ý,omžùЈ[;“c³#¼Yò$Ý�¶Ì3h3§§à R3÷5.:.‡±»ç>sU#ËÖ-“©í÷MyÉJ ÀÑPêS;›K]Ñ©ÔÅ•ú”¿ôdÜAsÖP^4v^†ürÙ°ÏY²5ë~ßÖ²™’»3;Êíxìr8ks��2Å!}êSµG.µó¶0¦f¿ÆJÇ9ñ(2í)Vê̵lÖwðÓ×ý.Ú¡ón¥JídÃhnæ•¡¬JÝü��RÖÕpmIîs_÷Fom6j2/É„ÚúVû8m)½ÔB±ÑÓñ%K-çë²U½o;Iw£u9l[.^üî‹ µý¢ë\Â7\Á÷f#¡¹³Q¯ið,†}_}ß”—  Ôn¥öS—Èø]Ô�ß'ýÑ:dèe�Âduç›ê³€R‚¢Ô½¿wð¶ªÕý:×ôd›Roeݲµ2”z�êäÒµÇG÷„VöZCÄ÷�¹­ióGqßm^çդץ¨&Øœè5–àëÁý^¯“T4J²YÑüd7Ϻ×y Ígå¼gk”:Árw—º'òÌU�ÖÙìrÞ;›ÄÝ«¾oªKPj³RÿÈoÆïO¦ÞC”ú0»BH÷dýü´­Ò1”(5‡_©?ràPêæ¥¥åµ{uŠ7^C¯€IDATÉ¥^–ÑY¥¦:¹®[æqÝ„c"³M©#rˆ5µÑ�͇r·³KzxK¯ïüaÒã$U�6?¤Ÿ7î¯oéÙ½‹œÂ}=ã¸s.õ£÷$rÖ2ÂÝш×é¾·~ŸÕÕzt·I}ßT—  Ôr¥>í©Ô®K�(µ›Ô˜Ìàuy?�¥Pj(5�Sêÿrð¶;ôËB¼ËMÞJ×§*{(õïâ/É,VÑ5�,é¶­S­YgdU­ ¶‡Ðã‡Kú1Y�é\—#ê“T6Šoè¦z7ÑTôŒ µÈø-.‘WÑÒAð¸'Æ™«ñÊÔ|U¯eÛ}S]2€Rp˜•úŸE´*©Ô¾‹hí°.õ¡C›œšÈîëAzÚëñ÷@©ñê@ ”ºÒ ·îǽ•ú=]%=”š âF²©éÍå-æE¡7©ÛÆ×êìJ�ØÐ»Â�ך©Ï²F{å~Yê³v^†¿ÚORÕ¨ù¾üÕ%×óî›ó®7ôúÒIõŽ»'æ™+-ßÓOàÃ5¹ÊußT—  Ôò(µkà÷IŸJ}@Rí;;Ù‘Wj”(µ‚åû÷×7X¼wkÉK©“Fžjo¥–c¬{·ä êM0Þ`¦úðžuÔõº1›û¥ó!Ø÷E<ùaÄ\uWy’ŠF,\wöÞ:? í£ˆ–jà÷±JVÑ:îg25”¥à(uó»Ì”X‘»w—­!ç O¥¶³æPêæÍM³Ÿ]�仯ˆêM›—.Y³}±�-?½¹ÙkYõ@y’îF6Þ´”Ær�BÄè–¼Å7xÜû™»El5¬Eœ\qßT—  Ô J}üx°ò}ûLO¥@©8J]¤.õ]½>³©�»Rêe‹Ã&…[®™±ìø‡º˜²ùÆošáá‡î‰Å÷ì«î)OÒÝhÝ¥fç­<{�zi}}Ý3�xÝÇ™»5×9¢Ô÷•÷MuÉJ ¢ÔÕ;ð¿PjްR[c¦Kº.5;•zyÓ€áýÍ͈C©ã¦O&˜Üƹ¹ê°ÖõîÒYª¿Ö‘Î÷�DbÜY×Ū‡² k¾¦dæØÌ¶Õ}¨ÃWÔr¾ßRLú>¯%½vß8#ÅI*1³­{¨×¥ÞRŸ‚=3¸´®»wmý¡QÝÊ}8Å™»Åyrñ­õõ{묦�÷MqÉJ ÀáVêÓ^Aê dü>¶Û¹ÔPj°g¢ÉÝ알îÏÙìW¿J ÀáUê¦s¾ï‡Ëz@wçJÝÔkö#ŒZTg–U¡—ôÞ,ˆƒÜ=k¬°–Ù0ºH7sË2#·_ã¿6Œ0KdJ�šÒYåJíhyQßJ�tÝÙ¯c_g[;Î3 >ãìd‡ˆ<ïF(5Pj”€Ã¥fÁã`TÑr‡©w¥ÔáÙYÿ�÷ªÔ¥F5®a~xŸ|h¶­´ÊêgqpJ½£‡°ßô“ivNÑ~B,R—,ˆ¨ur’�¶¢ƒLZ÷ÊJ‘¿‰tb² ½Ò±‹Pjy;zûLrUšhŽ�A[ìZüÖÑJÄö¼=.|Q^Bl•\ÑÄ�(I{Œû¢6oWêIáÁŽ–ivökß×%ØÉÖÎLÒø½â:”J ”¥à •úx‰‘ß S?î3JýÊ>)õ^)q°ÜN�t×Jñs Ô•x¥.bBŽ ¤Ã\ÝÙÕ¥éÆÇ•º@®Ywë&y¡²m„°YÏ×HÁº¹k5ÄFb[•:#=ØÑÒ!ÍÎ~íû:;z�Í®n¨ Âg¥†R¥@©(£RŸò“ñ;`s©•éÉNì"J�Ìd£ ›ÓrÙ˜5`ÍŠwj-ëz·N†³>R>iŽF u¤åôècV�„ÚÞô婆³QkÇa[á"ǵ.ÝJ­årŽ MÆYìH©ù9˜Jm=¨øÎYËj�UjkèWuýÃâ\“lXxl!+/2yE—�Û»H>Í¥ôç�bßH»Rëìhi—fW¿ª µ!Ø“2±w~ÇB©¡Ô@©Pjö#J}r‡E´J©kv]—út©(uvˆe·èÇ�tæ�Ùžæy€·$mq•.öEZûéêB½|Ûçʘ¼Î2x.Æl"šÒõ°�J#!×RyÖhØØÑz0]ÚyGd‘�ï€3Ñ1ëc¸›®Ô’!Ö.Ÿ³ìTX”G�`K!ÚzÎu\{àrB¦¬fÉ WÅY³k¾Âo…ÄrB©ÇÉŒ®ãCløq�6Elu{ŒshsEKÙ­œgg,OXd cmLõøy÷%gÈTH¿›dÐ6—Zÿ}bxšä5ñpÙ£¡AZm›ñÔêùÞãâ™Íš?%Ø”Úð`UKÖ–K³«_U�Z¶e�ì™ÑÜèŒØÇq†Pj(5Pj”€²)õ+îqßj¥®ä\j¿)¿w:ð[78Òe~¥7eÕ\Íâ} ãb1UΊ·ýËÖh`ÁŠÛ©K`ÿ&d^–º¦ïh9˜%Ú(: s!â´Y¤óbÕÅ.Ù¬•õ•'Ö"O=ri„ïé8®=p)¯d‚%»ºÂ¿z¦#”i9 ¡Ô$/¶ 1·¦Æ}��ØTkƒÕ‹@ɳ·EKé­\”fÎÖO<"Ïü/dLtØAV+�¤š^Ó”S²§fè—dŠ_8Õyó¦DëÙj•,Òÿ.ýû´˜T*µîÁÊ–¬ûùˆª_û¾¶¶Ô¡¹íkÝ„D]g¥†R¥@©Ø�(µÛ©�$=YͱÝE©KdüÖ äÊ@6ÛEýò|DËŒRÙÍd4^9j$•˜ $$¥°=›ån8¿�£&95”ú:u—¹Üð<øz*5i¸–ËÍŠšK|Gó`:õ´£k¹ÆIîBZ¦‘©e3ëcb8ÓÃL¸!”éºO¥·£13Ü/R@g©@×/dÛ DWjëqí�Ëp&O ™LXWê0Ý©½/Û5a‰œ[ÎB¥Ôt‘ágmÜ U·‘>~K¹RÛ£¥ì.¦Â©n±HoÞH,Ê.¦Ož‡y_ºä|á©x²êÜ*Yu~‹ø�ÝsQýW„ùl,5Hx;úÑ‹xOðÆjp…Z3¡ ñ„K©uV·dYÉrrЀ½_û¾¶¶ôÁ wnä·Ñq†Pj(5Pj”€ýTê'|†©(=YMñ„ߊºÔ§üE©³CCÃ2ˬPŸÆ;)¬L¥’|‘§{ž’±Ãzn)B©©¶Ší¼ex²[©§³²_cGçœaÚh,&dzÍ޹ÔaéB´knšÚ*�ì-2YŽ6pÅê?pµns׸4æR ¥ž”ÕŒsW¬µÁs©J^%ZÖjü>ðàý‚PjÇA'å-l�é¼ø"6>4`DËõûÒ*m*¤ËaÅ`¿6¸†ž_«Ÿ�£RÍLkTÐÅÏyØl^àYÍ&H7ÿm$LMYS(õE#ЬjiH³«_û¾¶¶× éI1®ñ9Ž3„RC©€R Ô”S©}¥'SÔ¥®© ÆÀï=̥ĄOê6—×ÍqŽûʤ9=5%ƒ’ú7ê!Zízý‚·Rwè‹Ã^Jݨï-ðA½n¥æ3f“«òÜf,QqîáI&Zrxòe]©­Çu.J�׳I÷Ô_÷«ÔLòFòdÌ:.»[o"Ÿ;:©Z‡øÁó|”{$b9ó¾ ‰‘ß>“ï+±nùK…‹h—øe@Ëf�èñ ¿is†²Ñ9=eܨ)Å¥¶šU-uivõëRmÇ‰É¤ë ¡ÔPj Ô(5eSêWéÉNl.u‰üd'<�ÚGÆïp65|M¤{’6%–ÌÊ!æ�"m•‘3ª›q=2îÄ­Ô×uÿ¹æ¥ÔõFXrœ«¤[©Ûd|r^Ê“4M-·Ð8ÚÀbÀa#iÕ‚®ÔÖã:—v¥6%ÍÆ/®Ô,FÊm[HöÓÃÏÁqÐI g;„v7 ¦4µR‡ôØze+*³éê—½6Rsµeç¾À®ÏôÀœ!ÁÆS¼îVê~ù½R·ÌÒ¬ê×¾¯Ù¶ƒ�¼€ä¯»ÎJ ¥J €RPN¥öNOv¢x”:°éÉ|üŽh“2M—U©³ú(Y)ˆ“¤AWêV§Rw¨ »•z€/¶Qêq££Ynén¥�J}ÁªÔ�Cz,2Ê¢ç£FÔ½Íu\GàÒ®Ô�DY¸¸”RÇ 7ûù©Õo%5;v¹Úß0ÒJ­M3� )|ó ‰N¹�>œÓýªM¤tÏèË“ü‡‘é7~VH±2múœxK-.S©MV¶7o€£_û¾ö¶æ/4â99ÎJ ¥J €RP.¥V¥'S)uM°æR«~ŸØYz² ¯÷Ô=3¾k¥¯¬R×óäÙù)®Ô­†üuª”Ú¸´)uÖOõ©ÔUêÅbJí8¨C©#ÉÔEž‰šÍ·v*5µÎ1v_†*ù×#¹¨�º!2!óq·ó�쌜äÝ|@Ô>ü:OH˜ß~9z`Ø,‹f*µÅ™-­SÕýÚ÷µ·í1S™‰Ûm?C(5”(5J @•z×s©+¤ö¥.¦ÔÔ^ÛÙ¸íh‰�ßÞJ}Ý1òW÷JQí¨Ñ¿R—ø­PjÚUaAfL‹²mã¢õ€J©�K»RGe 6ŸJ�—J=鶴møÝÈÏÁqP§R3iÍÕ7ð�\JÝGHVSGÏŒI[^ ¥ØÝžÓO1\ ÓŸ\/~ˉ qHL±f^̘‘)ìbyÓ€ ¥î´¦ws·´J³³_û¾¶¶a™.’š˜èqŸ!”J ”¥ \Jíwà·²ˆVÐò“)êRSê<)èU�¤R‡ÄjGz2o¥6jkFajcªëåâJmMzU:=™B©õµC\©Çåɰ²Ún¥v.©RL¥6Ó“¥®y*õ¢¼ÑU¡Ôl¾t7i°Ú†‘žl–Ÿƒã  ¥f9Ív2•ZÞ—d�̆ȕJŽSže%²%Ižý‹�[ì !ƒ Z.TÆGO” æ’¹.BVÙ— :F¿OZ2¥g §_£B£¦¥òŸ5”ºÃhvµ´I³³_û¾ö¶ôÌó¡L®kšÇ§�g¥†R¥@©Ø¥>µ³¹Ô�J]\©OùKO–›£ràwV–@vÑòVê‘I«'-…–’Ó"õ¶V(¢ÔY{½eVD‹':ó,¢¥PêQ�šW¬Šr¿ŸnËñªÆ ¥v.™€‡M¥”cŽsÓ֔Х¾,ówÞ(V ÞIôØ8碼w Æ9XjWê\>¯ç\2”Úr_fÉØ¸}\ùA›•e&¸˜$-έSŸ�OfùïY}yUü~�]•Ë"4œÔ›_L:•zÁö5pµœ²�ì¶÷kß×Þ69/›^I©ÎJ ¥J €RP>¥öS—Èø]Ô�ß'ýÑš%d±/–’éɨ7´eµH+‹>öå&DP²˜R3ËìžË¤¨ åÍ~giÏ…Y¬Ñ[©õƒéÔ³°b.5)ÔïÀï†ká\Û¡Ôì 9TJí\2‰îOet• �ÑsîËÍuëaw•RSgKÅrl7Sê~ž“{ÐngòÙ…ìå‚PjÇAíJ�¤7¸-“Ì\ä'*•Úr_r„(*BWP©ç®DŒ7¼È®ozFºYâ†t_ͲGOŒééÜh #†Q³ÙÍüÏqGú5{KÇï.Ž~]3©­m£³|–úbN}†Pj(5Pj”€ò(õ�üfüðdêÝF©s2v·(C´\;F…rº"¥”:¢Ç –µ�ÓbÝx¥6fJ–ì(ñ«Ô,=cz\–FâB¶Ú¥)•Ú¸LñÔf†Ê×<™ôTj–¬‹Ÿ"ŸK¾£ȪÅ7R²Q—ÚqPÇÀïa]W‡bÆyXï ÈB2PŠg Šõe­§¦-„¬Õ©²£¡>ë�õÖááVÇ(ÞÒÙo’™l&ê}†J ”¥ LJ}ÚS©\—ºQêH†ùÛô¬&•:ÜÞ l®“WwF:(çý†äHé÷LMŽpN^g[è·½róõjÛWê˜>µ:Ìã¹úŽÆÁô°b}ÁVÌÙ¢ÅfмHºÙmlŸ|g!ÂT.ÊZ¸Žë \q¥ž•C�³<÷vÈöíÐÏbZD £¼èØTnŠ E´U2ÆåŽŠq¿eŸažF=“Bo;¨~+©[ó¹!öãÃÄõdÄ<Ë}0‹NP¥Ji äkSK3^”¥ ùÞ ”¥`ïQj×Àï“>•ú€¤Úwv²](õa¢^¶O�ÕÃ0Ä7¼*Ò¼PµJÿêéÓ/exÍùåööoŧw>{\[[ûäó/â;í£÷1åS~ZÏž={‘hвýǼB(5J Àž£Ô~êR×T4J]íC©+;—z·¿O)¥Ž¤Ædº¯Ë‡àbجm̤U®ÔM¿øøã•2¼åüóöö¿ZüäóOy¤úñΜú�ZC©›b/^œgþÛöö Þ!”¥à ¢ÔÕUDëhF©#mnpjhràPL@šìÁßOPíJ]âÜÞÖØ‡e&Žz´ú‹�ôÑL-ü±®Ô:¿ÚÞþw¼C(5J À^•ú´�"Zª�ßÇ*YE븟ÉÔGM©‡Q©ÿa{ûüéÏäÔìÏjk?ßIŸR£~ϩԑííÿˆã%@©Pj"J¬|ß>Ó“A©•TêÈÊJKSSbeEkjŠÿâέ|í�[wn]5Ú$®Þ¼s{Åb¶ñ›·yË–•q˜?moÿš·|\[ûŽlô~mí×áÞþýïßUŸÈÛµµµËïêJÝrþ¼ÈKö¯ÛÛ x‰Pj”€ˆRWíÀïW Ô€J)õOŸÞ¡ ýôé&~óÕSÊ_Zš®þ™}xú¥Ðë¦[_òů>Ö“oßùϧ¢åmúnÒŸlo‡ù¦wß}7n*µ;JýöG©•:NeüwM†R?öì9ÿð/ÛÛÂK$€R Ô”I©›ž¬„S-¢…(5 J}ç©àã–/å§/Y :ñ—§O­Ë¬”µ¾|G*uX5<û³ÚÚOý+õµµ�›JýËíí?&ð  Ô(5{PjU]jŸQêc%ÕüP>¢Ô'¿¥T^©Ÿ>ýê/ÿtçcfÊÆ'æËfÙܺõ—¯d¹­[tÅþùö��EP›­úg}*µÝ‘Ÿ,ûVêå'|ĸ[©#ÛÈù  Ô(5{VêÓ^Aê dü>¶Û¹ÔPj@0”ú«_ÐÅ83鯘Ã&þLåšþIW|—*ýýp•šô—|øÊWºRÿÖ6:»wyù�÷?«5gU—VêÄç"¤íVê¦O¶·ÿ¼E(5J @y”ºøÀïã•÷­Tê(5 j”úN“ƒŸVè'ªÐ·nÝ’s¨¿|út…ûþJ†�ÿIWê?éU©9ï׊Ó £öRê÷jkŸôª•ùÉ”¥`ïJí�ñ»Tz²ËOvÌ×\j×ÀodüC©y]首§\œYÀš~ºamúç§Ooó¨õ_ô5_ÊÏÿ¾½ý+—Rþ~ܯR÷>®­}¯I­Ôö¾€R¥ì%J\£ö[–Z‘òJ ¨¼R•0DZªðJ�h¹º²ró)Wê/ù‘Jý[$ù�/¾øô3*ɵ�-s©—¿à|DŸÞ¶œÄ§TÀJý§ííßà-@©Pj*¥fÁã`TÑr‡©¡Ô \$“ÊÕÑäúЊt-¾\lß=Ä <;RÖ¿æû“ñ»ÉC©ã·ÿüŸzŽo*Ó_=}ú }g=ã÷'ÛÛ7ý&Þ}¢{²ž¶c V/³’ÔMJý[TÑPj”€²E©‹*u%³“©œZ5—ZaÔPj°§¿“r%?s®žš^�ºÎW÷]0™Ô5xòÂ….£ñb�¬Îô;ÇÚ/ êš;—Ÿ&c“†¯9—#©©)t\–:œ2�DE»ÝràÆ? \›#“ÖV¶S .]®G\Oi·´ ­ÒXµJ}õã§&B©o*”ú—®žß¡¢ü®¥f¹É~×TD©‹·H¥@©Ø'¥>^bäwÃÔÇ�ûŒRï%=Yvn ‰¯ÈQ¦“Ê£�²­NÉÕº0G,ÈïK;ý˜—�妋r[ª@È´ÔÚ!±i5«^NÎË}óÂèfÍQ›o°·¾x€º_6»l®³žb€É'yÙzŸÉªÙ„Þà+Õ«Ôñ/y­;·n­|©ü¾£ïüg©Ôÿº½ý�)a,4/qÞýè£/ħf›{*FƒV[ûøw¿ûÂ1ðû_ð  Ô(5{SêS~2~l.µ2=Ù‰�F©¯Âc‹ Êѵô%^ÃWä³@ÕyèòÀ8U¸¬Õ¨©޶ÍPÕÖX YgUWêbújvš�Éá¶‚ÔÞèÛ&•ú"µò�ÑEBÂÊeª½ ³¡®<]Í;ž'y¨zà‹úqéöëE¯cŠžÍåÑvz~mÆ¥‘jSê~­ô>±?ûÍ&=ÝÙ¡êUê_ÈêZM<1Ùm®ÑË}ãzz²�õbÉwß5çOª‡œ-¨Ò“½[ëà Ò“(5J ÀþD©Oî°ˆÖA)uÍ®ëRŸ.¥ÎA¯B.JšmÃw20$©¿ñ±Ñ!B¦,ëûÉtŸŒýZM.LÈEž C©�°�«ä Õ² ýÊ�å¥Rg…“G¨e·«–st™�-�RÕf+:Ȥê< ):ƒöÛφŽ÷M~j;ÅêPjÁˆùwrdœ3ªE#U¬Ô ¾ã_q¥6«l±ÊÕŽ"ZïÕÖ>NX¢ÔŸî]©ÿm{ûð  Ô(5{PêWÜã¾ÕJ]ɹÔ~S~ïtà7õúNÞÑ`k[Y¥ž"øN†”îÈlĵ9ô;¹*Í–*ï ¥ù¤n¶´uã”TAÚf"*GDÔG"]´Km^*55åQögŒê¶Vd9¢M4ô‹ï«*m¨|$ÙÚ™QLUh#Dá"0î<ÅjUjùƒØ,ýx(”ú¶˜KÿøéÓ¯n·Ð}~óTWêßlo‹È5K4¦—£fŸß÷£Ô½ï|J•œþaQêÄ··�·H¥@©(O”ÚíÔÇ’ž¬æØî¢Ô¥2~çÉ 7‘Î~ñf¥dp8é$dÞü;31!WÒa¶Îèf›ct_í!D$&Ó dœ*õjˆ�ßJÝMòIÝy³îåd²ŸP�\Sœ¦®òÑëì·¡†zWjïÁ‰ñ� }§û«U©;SœLu+õM*мNõí¯„R7]e³«Ÿ~Éþ«üþÕöö'Fdú‰ðèwžÐ�½~”ÚÂ{®ôdÑííí«x‹Pj”€ò*õ‰>ÃÔ”ž¬¦xÂoE]êS¾£ÔÒ5´ãÍ]ËecI«RgrÖÀ_4ëè0œ�Úþ�d-¯àÉpÖñB®e-)¤­¡E‹RÓ½ršçNà¸nL¡Öˆê·Ž0!#n³MæICÌðUj±çÅöqÖEŠ5‘J�¼"Æwó‘Ù£îå,ŸúNuê_¬$h[ÈÚцÊOÊI “ž4)}Ô~ŠÕªÔªX©Ùpï§_~ðjÏ_ÉŠÔ+_Éüß¿¹-•ú*õÞšæõ¨?ûâSöç·=ïX© [J þ¶v­Ô¾Ò“)êR×Ôcà÷^æRÏŸ„2e;x&çC©G „¬ŽóêARˆ�O“‚¾wŒ�kÃÝ´ù – X¶'q¬èu¶PX”<:Á–B´õœØ'ÅF¬d ÓZœJÔmôAsú�l;�¡‘��ø”¢7ß½}Ð:—Ú0Û¾—î«óFnjÚZº±Tꌑ-,Æ…;—G I¥Øwbu|A_ÝÈrw7ô/XÎb^ª|!3£¹ÑK2}.µý¡Ô•Tꦛº@ðg©ÔM7¸`ü‹&]©›þ`¦N~nL‰~¼Ü´w¥F -¥@©Ø«R¿¢HOv2`s©Kä';áéÔ§ý üæQj>°7'«#‰¬TT©eä¯;Æc| SÌk-AJYäèb—LrÖÊúÒ“žñKlä/gDÄé>ÓbÅ5Wh± ÷³¬.„#Š�À� 2Ä-8y‘(L.eKZ¦›mx•¯Õ}5Ï!‘Ê›³)uJ‰¬’E÷2ßëzÉ(>^;GmZ,O›N�“cÒ©oçÙ)j݆º;ˆÒoï‚â¡Ôû¯ÔWŸ>ýR*õW†RSofC®W>æ�êJüåéÓÒw‹¿Å²�éu©Ùdj]|ã_|þ„çû4©8\ïÛo÷9w]j*ë¼D(5J À•Ú;=Ù‰âQêÀ¦'ÛéÀïÜ™fíZ©Ôޤr"<É*áN5†fÄ_¦¹Cs��¥&Ùf ¡Lß�0qªN�™á~‘¶™ÕPª_Ȳ"JR©Iõ\n–þ¡9C‹áLž2úö^OýèZ®qRh’s'p@ÐDzHox”ÿÀqÞùWg•¬æ\fËrŠe,¾Ú`L·6RœI¥Ðg6³ñ y÷2õéir!¥õÑÃó#±Xù|6–$–#_”¦Þ(}™}È*¯fRî8ÅjPêó©h1¥çÊú÷¢œJí‡ÄÊJÄÈã�ˆÇãúg*ÙðáííOfûåwÞYŽ—åÐ+ÛÛŒã%@©Pjö¢Ôªôd*¥® Ö\jõÀï;NOF¦¦¦f¨AO¤¤t´é¶”äJ=£‰ö�غh�ÿ…¥ÙtʲÅÚ*K@b‰ŠéÙýrð0Sk¡ÔÓYy¨¬;´(çRÓVc|Ø8•§Ë®�ÀAc¿¢ ÑG7¥—œ6·¬YÀ ³MÉѺ¯vÞ:g³TjÓ±#&ÞÎåz¢'Í«E­GõQ ]f6=Cå©€÷ðt]×ø Yaj|ÜøÆÒSQÕ)V�R‡�ò_#‘2ð •Ú.¹OŸ>]‘¿ÒãÖ‰Oö)˜üŒûPj”€2(õ®çRW0Hí;Jý#u©/6ZBb\r\©‡¥­*„V/^”\•»Íƒ|¥'™ÉÁÁ—u¥QË>Þ·3´(•ºQ—«h��vìŒÌÿv4 /S¢%±nc¢µÕl£²f–î«ýÆD�YC¥Rg¹û24>¢Á¹ÜfNà¿éh٬Ş‘ŸõáäãÄdÒòÕÖL£ç¿Þ¸O± ”úÑë€~¥núøéÓ/o¯$šâ·¿|úô?eù—ÛÛÚ‡cÅ?Ùþc Þ!”¥`OJíwà·²ˆVÐò“)êR—RêÊÅüö‹KÊå·àŒ%Œ2¥^M:”ºMÆç¥ÞÈ´ÐZn¡q´�íñEÊ‚®Ô×u»æ -êJ]oxÃ8síŽdörÿà\,ÒmûµDL˜¿lYî—_ú•™keÌ�îLFã"ÕãØº\K¥ÖŒXsŽ?}çrÈTê~Çüè úrÖ¨îÕA•Y@òôÛrý¢Dî7LÈD8¢<ÅjˆRõÄŽ€Rÿ‚ç+ûê?y)-£dô¿oo¯”ÿXÿ¼½ý+¼B(5J @Ù”úÔÎæRWt*uq¥>µÓôd¹­üXŽÐ¢®ÔãÖÐæyçNàÀÑ¥©X¦¯ë–eÃl‰•kÜ‹³ú—mÈ®Ôô{Ó/VôˆQ Žåœ™þ¬Ÿc]ìôjXì $~õ±ü £‚~ ™ˆú«@©#š^9ì(uÓÊ—2øÓ�ÍŠÑÑÿØþײ©å�ÛÀLj¥@©Ø»R{‡©Kdü® êÀï“;.¢•cÎT¥®çY»óS\©[ õêT)µ#´¥™‘‘>ñ©Ý>â>¹hNf¶›­ËWº/¤vÒ¡ÔSú í¼ÖìXNôaÉUþ…¸@V¥NvËqèô{!bhx§ç•tNF]J�¿’?DõÛ6¥nŠÿÓþòË?ß¹iÕÝ_ýéOe¢�ùÓŸÂxƒPj”€=*õ�üfüðdê½G©™çU¿w®ÔÔÆ Ɉ>Z¼ÀS–Ex>g·R;C‹ž¿¡Ô•ˆM7�1M~ luv ¦‰ÛmÆj˜m&+É“‰l–¶ŽŽ‰0u²ÛL>¦+uˆˆ/Ç0lçò5‘iž{ädÄÌ+ÆÎ;‚ÔìK"æJ§&&zœËHÁø{à:Å@R cQq¥—�žR Ô@©¨2¥>í©Ô®K]æ(µÆƒ‰îôd;WêF}íßi\f¯ÝJí -N‰ð´;=”ºtQMíÓ4V&-$†2Œ%ÅÐ2*áaäÓlu†ô¯•‰l$v�ã¾ ¥fº]¯%Szîpç2ÓðÉl4;HHû'é†Á\2GOk5kWyqVùP&×5mIJ ‰¦ûÍÊóÍ*N1ˆÐû5žÕØ­X€R¥®Ñ™úÎ\Å��Rpx•úŸE´*©Ô¾‹hí¶.u$9ÉeÕ]DkçJÝ#ªS³¿l§!Óm¹Lh‚¨”ÚZ#€Y-^Ù(¢¥®H˜zJÝ.í˜=ž°uà´&õdÄK©“ó²e!ìTêHvUn»®^î,ÈåaÂY}yµSþcQyã@WRŽs™´œïH•(u¸Á}ÂPj Ô>yñâÅA'³‡lyñìEó~bù�÷ß{gG½ÿ� ¹ƒ]úÄ.ÿÛµ!¾ÛÌ ß~÷Ý[ôÎ|÷ò{än€Rp˜£Ô®�ß'}*õIµïìd»PjÒC ]§Â;ÝJ••…óúr"*¹Û�ß ×¹¶+B©yýÆ•R;C‹T¡ûS>ò;Ê¥&…qC©+E²~šÛ°¸ýZ7Ð.¥w©-ª¢¢�ñŒ%«WäÊòZW s�嘘øœ×¿Äa‘ùnHuÖ®òÑY®¡‹®o¼‡R»ˆ–¸«£fJ…R¥.å·Ïž%÷zÜ&?;ï÷�ÏŸ={özù®ý�Ç�¿o|®e<ù�SLß~láSÛ¦ ´²QìòìkW¾ýîåËo¿YÙM ™îÙÒÔtëåË—7ñm†Rpˆ£Ô~êR×T4J]¶î«-„<�2™Éf¢‡æÎç†CÙdeBäPj Ô¬“ç ‡üš¶m-וÇ?eý…Xx¯Vç3G úÝZ Ÿ9•úPv±o¥íÿ�C©ß¼”ÜÞE Y(õ Ý{ßf(5‡8J}Ú‡RWv.õn3~Ÿò©Ô»dš¦N>ÔwLl›®Ô]ÜŽ�<ÜÒ”D-i¦Ô"XxQ/nc�ï¤; !ˆæR¹(k=`Ù',áÎÐâð�Pêh}Á\íÚ ¥J}`Jýìg _‡Œ?ñ¼\Û—?¯5•ú}úéñgïÊBÕŸÛ�À6=ÑqE©wsäœ]©·™Mÿ=ûï·;¿:¡Ôño¾ÿ“©¡Ôõ(uuÑò¥V¡å²á½ÆÆÂf"å\g§è-EHŸŸÐ¢v^,$[³9 _P Ô@©+£Ô_s¡lievýüi7å'L•¥R/1“fÑéøgôÓ{¶†_ÔÖ¾ãÑGy”úª O¿õ-ýð×]*5€RpØ•ú´�"Zª�ßÇ*YE븟ÉÔ»Qê2SOH=KŸ «Q|߀RªI©™ÇÒÏ/â«Ô_°°ô;ŸJ¥¦K�ÅxïøcçènÚfy_•úÖË—?ðsü{ú J ¥ì>J¬|ß>Ó“@©cW鞬ŸŸv”2@©eUêè×ϳ±¸Õo›[_þµž]¬åüyê¥Éìëa®§ñØë¯Ç,¦ÌÚf[ãn¥nŠ={öLäøJDZŸgÏǽ™ÐÎGYÏçÏë~M?Fe÷ìp¾vSQþ¬·IWêÏjk?57<¶µ¤Ûzý(uóÏÿþçò´±0½)ñÜß¾.î�öúß¿õRêo�YÐß¼|ù½¹þ­«WãM‰«½y•_èÕ•›+Vw¾ºrë¿oÄu¥N\½Êš]eûȧa|Œß¸yóÒ�C©8QêªøýJ…•:’“¶/ãÛ”ÚÅÚCÊ2Þ䨳RGÅôç_JÝü31ú…HF—^×^ȉ¬h®�èÖÛ>““¡­J׳޵ÊÖz¥,ç![èkFW™6Î?Fô=}Fl?}ò~¢ÉPêO?ÿ\Üý¾S©?¯­}³´R·ü‘Êû§ËÎý�øß|E}KSôïø§¿ÑÔJ½²²7âÕßšëo¿|ù×T˜_Þ¢wè¶È_ö�ž‚ìêú²œKM„žßp˜zË·b×oß—=Û€Ýðú+U�ž¬„S-¢Ué(u$¢Í N Mda*@©],Õ1 ÔìY©Ï¹Ä^—JÝb¦{]*õs}U칑͛ï�4Û ëU(uâgf›ˆò�žJÝjvóu5ï-Ë�ôŽ ¿sü~Ì;Þûf1¥Žþ_?Ö™� ¥þ{¹üÿ‰ü�üô7Q¥RÄýòå76¥þ†5Uê«ßé9Á™_3£6VÜ,¡Ô+FËïnàÛ¥ Z•ZU—Úg”úØAI5?”�(õIEÆïŠG©PjO[PjÊ¢ÔlÂó³ϳ?òÊFa‹5¯ó51¡ÔlÅ×ìÏü÷ꈹ÷׼틄C©£te”›2k#öWÒK©›YÃ×Ï·2£ažsïï¼íŒU»”ºù±cU‚¥ŸeüE¯—RÇÿ'3æÿñz#û³ž+5ûðÿý{fÚ?eŸþvRl)¢Ô<}æÔ,¸|ëÖ Óã—·o®Üü^¶ˆ3Oþþ›ÿ¾-|¹ˆR³–ßýõÆ “óoñm‡RPÅJ}Ú+H”ŒßÇv;—J ´R¯ÕÕ=< ¥`ïJý\8sÑe~ûº¾† ºfšÌU˜�aþÚ¨‹u^é6öæ�¾v(õ]'æK‹,e_‹e÷!½”šíÐ"-aêÞ�”Vjºæ‰Íœ{©R.«R?^öPê¿eª¹€³ÑÞ-B©sÌЙcÿ˜Ý�ÄßýøÇÿW1¥æ´o7Ù•ú{~U7ô¢ÓñoE˜ú–®N|[B©Y½ê·ô>¦†Rp”ºøÀïã•÷­Tê(5 Ê•:ù¨®î=+uBjs“ï�äü3±‘‰óynË/Œ‰ÒòÓœ°bsï¸ $›Jù™TçÖ¯¿–3¡_01VÒK©Ÿ+bFL‡ÿËAI¥~—Šóû¶5Ë\¦Ÿ|þ˜;uR­Ôã?þñq½Íóãÿ=Wê¿åË?§ŸzÄ™ÑOÍÞJÍh·+õwb¹eeEÚð �5'XÈYÜ™·¾+®Ôæôì++oá률ú~ŸÚqz²ËOvÌ×\j×ÀïÓA˜K €R{HÀ½ºº�&(5{WjMŒÍæ¼Îý6jYó‚;1UãP“Šž3‚Û?k²µ ‹ˆ2óe�5™¶þZqÈ¢Qêó»¸x§R¿ý¤¶öó„­É;L¨ß£ë’¼îV³J©ÏÓzl\ûùÏ5®Ôâ|"Ƨ8ý¤y*5+N­'þ6•úE³ïDã«rÍ_KG©œ†Rpd~×+ã·º,µ"å7”T¥¾[Ww6¥  J-ÇbAé$Ÿù•ˆ€õÏdš2.ÒÏ þ™˜%mwúkæcƒÄ�Èr¢9�µòÁáîCz*u„u2÷õŽë3;”z™õcÇ„éwÍØôûÔ©ßS)u'ý`+RÅ”Z˜y³¹é§Å”úuå«MN¥¾iYŒ¿uõêÊ-®ÔÌ“ã/¢Ô-LÕï > ¥àÈF©Yð8U´Üaj(5 ðJÝü°®n­ J @”úuKÞ¯fî·¯?³ñ¢˜R[÷f2ÝjWêVÝ_¿f¬þZqHïŒßYyÏ£{Pêäc÷té¦ä{ï«>sdוºÑ˜&m*õO›v¤Ôß9cÔ¢ˆ–�þæ[#q7�LÿÚ0íâJÝôßb¯ï¿¹Šï:”€C:—úD0²“©œZ5—ZaÔPj@Å”ºD:ß�ºº­”€r(õs«s¿}¾¥~îPê¯ù_o¦ÄÌÚÕ«f­8d‘ºÔF­; UÛ”º—õ“¢ÿcá¬Y­+õß:yÇJ-ÅØC©7_š|Ç'Hÿ`•ñ¢u©W~x‰ÂÔ�U꧸JøiÀ‘Vêã%F~W0L}ü¸Ï(5Ò“*¦ÔEÓù.×ÕÕ-5A©(‡Rg-~ÛÂý–†¿6‰SjëÞ‰gz”Z¤'û™ž­[ÖÌzýëÖßè>d¥¦"ªyíÈ©­JÝüy)£f󪟨”:õãÿÍÞ•:î©Ǫ̂¿»}ë¿WVþ›+5ýï÷z«·JD©ÙÍû«(¶õ=œ:PJ;¯µÄã‰D<Þ¢�÷Pf?mÀÀïàÎ¥V¦';�(5 HJ],�oœªôý&(5eQjëlè˜1—Ún�þæRGŒ¹ÔB©“ÏdæpK,¾Ñ}H…Rm e'·žçÀ|ö]½ÞJÿŒúòÛî _~ç�ÞRQêŸóÊY{Qê¦xÜiÔ¥¦v|Gl¾ášK}éÔ+fôÚJž¸ÊJrý_÷)µ±<òxDSýÛè§ G.J}r‡E´J©kv]—ú4¢Ô Ú‰–ÚžÄ=rñìÈÞþÖÔ\ê÷êêġԔG©#–‚ÏϹßF, ¹K)µuo–u¬ÙZDëg²£çFQ®8øí>¤®ÔçÅrà Ë)$ÌÊ^M;ªK�`FýŽâÂéúßYš+çR³´Þ?×{èé ïB©Jm.Ò“µXÒxß²)õFJ³¸#ƒ8«`}_÷À(u,éø %žt¡ý´à¨(õ+îqßj¥®ä\j¿)¿1ð”•É :ÃÆºö &�|M¶k¼�Ÿœ‹é-´Ð`¾ÐQßg.Oæ ãõ ^Û#‘á Rª®“×fVIaÜ<¸s×ÜìÐôêÔõØ®®¤ZÈXO::y¡�¼`År3C«„4VƒR³’Ô›MPjʣԼ蕨 Å„VÖ¥–ŧ›ž¿xñu1¥¶ìÍJLÏ5Y•ºEÌĶ(õ×ÏôéÖŽCJ¥Ž5³šE•ëŸýìg1ÃÏçv¡Ô‰O]F½,‚Ó_Ð ²rKþ¾J©›.P…÷1IÅ9µ›(õÊUJÿž+uÓ¯_¾ü^ôÊ‹o™Jmβ¾%”ú›Û·¥|óòå|݃¢Ôç[Îm‰–óöý´àHÏ¥>ésà÷Á)õ±ÝE©÷˜ñ;;7à`r`r÷ךë„0—D#íÆÊs%©g+Úä„|­y¹bV|{Âúòeõöˆ6/7:»N^” óšz×Ôª¤TjC¶yo"1Ú ~Ú ãÈìÄÞvà9ðûwµµµ6£Ž^ûä=öa©V¯¢µÌÒ—õ*•š�ü¾ÀN …Éu|çJÍÌø/¥fùo³NÞúV¤'ãŨ`k®~gWê=6½"ë\ÓN¾ã:ÎZÞÂ×= J­°e—/ûiÀ‘Vê'|†©(=YMñ„ߊºÔ§|F©¯Â"\“ šjóeB´àŠU‡¡ÝÆøb„ÌyFù€që™™\3V^”k¦òBîê ™žo«"d•×ÂTŒó³“Ôv/°åX�ö2ÛvaU:µs{$;¡û¶£ëè"!…ÉPû!‹Õ®)zèÁѶÚLÛÅ•TÏ`BŒ¿Æ iåÆÙÅл^àWe:tOwv¨*”z³®îQ ”€²)uBäþb)À^¿m’kB/älè"JÝ4gì-WX”šå%{‘à±çg/ž‹6l£û�ºR?çëŸÏ鹯cb××Ùòg»HOÆ*N×>6x›—£–󦿠Ÿž|öþŸ=q² ¥nš¥ü?ÿ÷ÿdüý.æR³˜òw /¥¾Å‹KË:ZL©üã··YÐÚ¦Ôo±Åo¿‘MWÄTë—?ܼɦR÷¾îÁPê˜Ê–™/[Æuûi³¿,tt9Öt¶wy.�ôdŠºÔ55Áø½û¹Ôy#ÈUÈB©C³meWjUŒo˜:ŠW”töÞ:ÈE/Y …,[ì’Aë9BY 93A®hb¹‹-gåspn§ß2²h„°­]_#d‚_£ßÓÕ®ýdšýí/9Ò¹ø•�Bfõoó´í[¯™[²ãœ~-©¥¦½u_p¶®nc}V Àž”ZD„9ç_¥n6‹^…â%”:>g´ýYÜ¡Ô<�ajÑ"$6º©+u"¤o�Å«Í"Ù/vR™ZWêOkm¼Ã“{×~.½o¬wN¶6•:Î�šó·‰](õÍ¢J×ë`}·"”ZÄ«97lE´Ä@pÆm™©Ì¬¿õkT¦ŠR'¿[%Íý´aô54è‡æ|ûÉOfõ�ý ”M†Òg²ö5sésžKìÿ\jWz²“›K]"?Ù O§.•ñ›ª } ï`ãmW³APê)2±ƒ�߃þ~+b|ƒ¤Á3ʬ?@x�ürQȪˆ)�nöG™ßjÄ=üK&Ÿé¼ÐZçvBR­v¥–]Ï"tǦ…�;vM®’I1£šª¶î˜Ù¬¶Ó+ ìÔ†ÖÎŒ8ë 2&×�R+u�üqˆ^~€”ºH:_ªÔvÖð2Àž”º©YT¢žK2æ{%¾Îû¢•7(¦Ôf[)ÒV¥Ž‹Ñ|Ø6k‘ø™Üè«}¬ ô;�ÅêÏ�S±M¥nJ¼Î#Ô?ý?9~6JõRj]þk“—R7%n}Ï5¹åªTê¦ø->äûÎU{]ꦦ?° ßý5ñƒ~•¯xùí7q|Ù¢Ôšx 3Ë{<.:näô6Ú4¸ÚpÓéŒü8�žõí'‹†ç.¥ÕÑæÙô¹V(5¨Žôd'ŠG©›žÌïÀï<™á¯î�ýæ›yÕ(õ^b|Ýr$±UI€‹k¤Pò—Š”áx3¢u^߉naƒ¬ÛºRbyD(µs;™ GJ-»^ŽÎ¿\®»æ&&ä�~B:D¤vŠIåPçή$˜D¯³Ÿºê£b††¼¦qýW×÷7–$¥ÔErA©(·R³„Ãç5‡˜µh®´ÄÞN®Å¢ÍÅ›$¢Ž¤ŠCê½97´xµÜÍfg‰å÷Þÿ=÷P‹R³ãÇZ“¾zV¥'K\-qîñ«Ž‰–ê}W¯:Æ ¿uõ*|:@J-þÊ%Â}r’BKß@X<²ˆ>¬[¶‰µÕ´Åmö¢Ô©tºQ|êJ_ʨÛt:×C©AÀÒ“©”º&Xs©Õ¿Oì0=™TjúfÞ` ŽÖrÙXÒªÔ™œ5¾Í:: g£¶?e¬Ðò ž g/äZ6¦ŠÅÙ”šî•Óœ�Ø>ÈçÑ-®sû5º·]©e×IBúåš BF‹tM=£Õ2[Ùjn'WÜ ÔœIqGÚùÊóò®+”ÚBu(õò¦Áúºû››¼Ì°W¥Å”Ú7>‹h�CªÔçÅïñ�î¡aîÔ-ÃCÝr¥Ì>¦·ië¶0Òlkã­Ô6öXx5Ý/>Œ¥‡ÿ*+-[HtÆ¥Ô­%÷ ¢s©+¤ö¥ö§ÔÆèÜlO <`(õH�ÊxXLp-ÄÆ§Íp_Œ�kÃÝ´ù – Ñf$Ÿ“á5¶PX”þ2ʲOB,#˜Ø'Ŧp†Ý±¸ áÝFd1§ȶ“nm^ÛJÄø #ƒRc�Œ‹;ë.=¯§a�)©¥ ò¦fÈê°É šFÌb‡Ðbåv»Rë]Aé=‡.ï®ÙÔkæ�1úºÞÙI÷XlWLÚ™Í�Îðo9•äBRŽxOU•R—LçËy€ôd@©¡Ô J­ÉÀú†„S3£ê“ãä¨nÙ¦¹¾»{ê"gª»{¼ÅÖÆC©sý?9séU9–»§ãÜ™Wç;¹:“žñsév}¿‘ôüÏì™ô(õàùéK—^íÏXΑ®Èæ&*Ñ?ïx#-;”J�kŸ¸ôÆL›è54öZúÜLþ*7ð[YD+hùÉu©}G©ç­a>.0L©e¨¬;ÆÃf l\mÁœ›/vÉ$g­2™”¥²‘>Ås„»ÛGæ»æŠÅä~–Õ…pD±“n—½¶•ˆñ��†$”º4‹Dÿ>,:g"çˆøÆ°ßLdí«n){á~Âê8Ñ›®�2蜚¢¶ÛòÚnWj£ëÝsD>&Å®bø”4ë�ôÎzÿWLbTÿÙ5jÝ„DM•ÖÕºj”ÚPj Ôû¥ÔCIî`—×iûŸB©�´Rë)é¹J�Æã£Cz¸š­ÿ(¶J=5ÜÊžê®o¶µQ+un:�>w)-bÐÃgÒiú$G?SN§M¥Î�Iÿ=ûóï˜gèNghÆŒ¥aWúÕ°}Ó\ú�Ÿð’3•º›¯I×óé×gÒ—Î¥Ó¯õAÁ~*õ©�Í¥®èTêâJ}Êwz2¡Ô¹)2ÍÚµR©Iå&„›°\ÌS�á…1®–YêÐ\g§E©ÉÄp¦‡™pC(Ó7$L¼��ŽÆÌp¿ðØ,õÝú…lk$”š4\Ëåféš3ÎäI!“ óÂLùk¹ÆIáÎ�J­ØV"Æ—C”¡Ô%`Õ©B­™Ð„^ïÊ䢑ó-ÙÓ-½�Å¡Ã#òç�Ѩ™Œ fÈzm·+µÑ5«‘Å2zgôrÒŠ]ùï@«2ª=¥¯Çý_I`3Ã-è²< À¼e„ûùT´Ø÷7œÓ Ô@©A“Ìñ­í`—F± ”úè*u̘×Î�:²uSœO”ÖÛP¥¾(rÿ5µ^4”:+¢Ôõé7RáÌ ÏÖ½ðZº;Õ:z.=ÆM9=Õ˜3‡ew‹߯¦çÙ|ê3™\}:²4JmÝ4ÇT;›ë:“ž1”º?}©-—íOŸ¥ ç˜É÷�ÓÇ”P^¥öS—Èø]Ô�ß'ýÑšššš¡ž1‘’¡Ý6]R’\©g4Ã[£ö¬\e:‰ò«­r“Zd;EÅôì~9dj-”z:kΆuÄâô¹Ôa}èî ®ÍÖ�œJ­ØV<ƧÉË„R—`‚ts7 O8ÕY‚ÔÔrW§F&óúƒÈPž˜Ÿo0#¹úúÁ"ïºb»M©-]³Á…~zð)wVí äÓ�Ò‡.2tØP YTj|Ú¢­GèõŰÙP(µuUêEŒNŸÉèJ})Ý&}*îL§Sôs_Û(ìç\êâ¿<™zQj�‹�bY¾©ÏñWwªÔÃrrëª;'”^êˆÕ2ÊËP`·}‚k’ æž2r� ¥¹™ûxߎXœ®Ô�úˆßh�¥ævìäTjŶâ1¾”y!Pêbäô¼r£Ž)¼‘E#HM7åÙxÿHè )P[�vKuŽ ÙÓxç&ø”våv«R/Zjž]ßÎñ¾�r×X·žrm|?ôHr!1c°}³ ¿DQ3�¼¾Ó Çv‹R[ºfÂ<<¹x=Å&ä«we3÷å®l´DžC ùp$wQ2ZìJ‚J‡~-Ô¢Ù 'Ù�K9™©>,†�@©€RªK©sl"ô¹¡Q¡Ò:˜);bÇ,MD–ðÆ!6ÿ:-•zÔªÔ–Msé×Ä®?a{q¥®7q†ªu›»Ý0’ƒÿ�ƒøís.uPêRŸØk]jê£y¦CYÃJ5./F]êëR©œž5 •ú‚U©‡ôðZ”×F�±Øm–}Zù±œ±8©ÔãF´YBÎ;wr*µb[Ñ_dF¶¡ÔÅIf2šñ¨G1T9q:²jd�ÏñFmfx‘}´\.j4row*µ¥k“Y•Uì�2Ysg%+}%A¥Þ9@}„\ÑêõŸ/´lJ ”°J]Þ�ß)>ª[£YްLר%)ǯQ¿e¤fJÝ“¾”kLŸaþÛFUøÜ«*¥¶nš“YÂï²4g\©GÒi~ˆŸœá©ÍRýLã_k„‚ø}Ò§R�TûÎN¶{¥f:4Y&¥®çY»óS\©[ ãéT)µ3W.¥.ãÓdBs(u Z G6 yë‘d#ÉWƒ‘ƒº‘Ûê€ AhöU:ÜÛJmíúÚH½è:<ͧ¸wM.ZŸ_Þü©Äï•–£ð›yÏC®´kPj Ô€ýQ겤'Ë\JˆOÙtZªlkh‚§3|+”:LÒ]‹é¼ˆ:�±IÐS ¥¶nšK§Î7]bM¸Rë�kƒìäké 8،ߡ®h”ºx˜ºX -¿u©©çU¿w®Ôô%¿°�4F‹t P)µ3ç9ð{‡J]4Æ—Ò'ZC©K0C üŽÅò"tœˆ¹"ÉCºçjC\žéëV8ÁÍÈkúC©wow(µµëËz׋âƒ{×Iã+—ø¬êèøÄT‰+©†¡öâ¶¥&&zä_Ö‚5]”(5 üJ]æ"ZÔ›»Å‡Éô%6N»''"ÖƒáðEžê;î eUJ=™žà³¬Ã¹4ÿƒîäRjÛ&ªÔ#<÷Y:�“J�9#ZgC=ô?=̾ÃõüDØ·¹Ô§;—z·¿}×¥f¯æ‹ªôd;WêF}íßiœ¹¯ÝJíŒÅM‰ð´;=Ù•ºhŒ¯žLG¡Ô~ _ƒB£¦¥òb~sŽ�±¤p`V¢bYÀæS±Ü(ËϽÊÅúX½«�h06šÓúæ Y +¶Û”ÚÖµÖ@Èõp²uRö¬êšŒJè‰e¨sÖ÷eR3îàŽ+©èµåC™\×4YÕô©ê¤! ¥J ØO¥–E×â}R¥¹Z÷ɸ´&þQÔ ¥îž‰[¦º ¥Ölÿ~þ]:=ós꾃iž©ûU^AºñRz˜ªô™tŽ%èfák·Rw¦Óé7Z…0Ï´†3?U ü¶n¢*}&D;�«ºÈøÝ�~ƒvÞù*û9¾93#M€ D©««ˆÖŽ£ÔÉI.¤î"Z;Wê9¬z�üæµ…Ûr¼ °B©�±¸q‘ɘÑ:ÏVÑæbJ]4Æ7¤çv‚R—šL=hd„g*’‰¦§l‘ÞTƒÞhˆ‚µE}yZÄŒ'õ剜j»M©í]OË–ñ-v춦øf�;»*ƣů¤îý¼<á+)cÜ<Ï ¥J Ø?¥>/ì9> §™SÈ•çÅ?Šz›¶n mö6:‹,Ùô™tzŒO‹N§/�5œ©Åº¨O¿‘Nw(~‡ÇÒ²‚4íâÒ«—ÒŠ(µmÓ\úµsé7h粆Rç~B½œœI¿–â ÒÒ¤û\úÌìgz²bE´T¿�U²ŠÖq?“©}Ñê¡„®Sá�n¥fCµs¶/70!‚€»øÝp-œk»"”šüa\P)µ3Gŧ?•ác„ó¡\jR˜ñΕºXŒ/zÅ’óJ]œ�7Úî¡Z7ÐY‡Úey£|½î±m,ƒ<)Œë•ÊB|yl>æ±ÝLïì:'ʼõ_bÛ®.¥Ž,ðÌx…�h‰+©¢³ü·ŠÅœ%'\'”(5`_•:&þÊ%Â}r|wKß@XäøŽÈiÒz›X[½A[ÌÞÆ �°ŒÛç¦DæïõÛôýb¡ž¥*;7""Ñ.¥î2f_ÏÓf¯Í.²âÒFC™ñÛ²)”>—¢~)Ï÷ q¥w�£âžçC¾sS´ñ™W{à rQê`åûö™žÌ]jRÈêó9]‘Ý*u¤]ÆÇ…R —YíÒ”JíˆÅñZ¬“ úi…#»Rê"1¾keb(uÉeÃíæíòh[ÈÚ,6šë³9X4Û+¶Ý›Xj®±u»jÙlÌÏ•TE :“ÍD+2‘J ÀaWê¥Íµ»›qÜ\ÜJÖÄ_�DÜø+� [Žcº�6Í®6&¹Ð\Ö’±,åµP„¾>Ÿ›r)WåéN˪Î SƒJF©«và÷+~”zâb—ô�N–¨›Œ è‘]áP]ÜŽ�<܆¥ÎI¥²z‘çeŽ´1‡ÎwÒ�’R‚R¹(k=`Ù'¬§’²Çↇ„RGë æj×Nº ·ym+ã벦.ƒR¥à(õ惇×ôÏ[uŒ³ëÒ–ZXÇ-G\©ÃÉ„zs"iþ³è§ GS©›ž¬„S-¢U4J­ óå²á½Ž ›‘Â\ggROcÕç'§� ÉÖlNÛ�ß”™æ¥à(u|�9ô}±p·Nç^ܱ‚²�[ŽºRÇZ”¾œh± éöÓ€#¤ÔªºÔ>£ÔÇJªù¡|D©O*2~¿’«ìÛy½Ì¾ž «Ñ èBtqi Ô%¥^ai¡ÔkôÓÃ�µ�ôÏ­¸¾æ‘”y¥ŸWùr¢Å–wÌOŽ”RŸö R%ã÷±ÝÎ¥€RÇ®Ò=Y??m« \A:­S©Pj»R¯=bü¥R'u“ŽoÐO|,øýººMÜh ¥Vùr"â°e?m8ŠJ]|à÷ñÊ�ûV*uMu(u$5&'l_†.\¶N¥@©8äJ}Ÿ…¥77¤RÓ¥²ÖÏV]Ý=öa½®n7S©Ã±¤#}_<éÑí§ Gpà÷©§';°üdÇ|Í¥v ü>½‹¹ÔeG›œšÈD†Û»àL@©82JMeú^o“®ÔôO=UérU¯rÏÄòòõ„͵»K|yéîÚݤ<­å忦¦äÚšH_^[[F qph”:Ö"–/t<¢©þmôÓ üŒQû-K­Hù]y¥@©TêµD“©Ô[[ú(ï5©Ô[uuo*÷\ª«{˜XYËš›’üÓƒ%©ákKl:vÝÃͦÄÚC¾ ÙÂÁáQêpì¼Ö�'ñx‹vÞ#üì§ ˆRŸ(>î»&¿aj(5J ”š™³îÀ÷Öe~ïë²[ï›*¥^Ó³ƒ÷~(?}˜”Ýé+–ßÓÓ…ßÇó‡F©¹2sŠ«„Ÿ6í¹Ô'‚‘�LåÔª¹Ô £†R Ôz¥îý½ƒ·]±j§ðÆ?«,_ÙK þà~¯S©ëêmܽÏ6>¬;»qw힬³Å#Ö[÷×ÖùúéîúYúÿÓ•RÊ ÔÇKŒü®`˜úøqŸQêW Ô(5‡]©?rPZ©© ?l¦6S#Þ²F íJÍ2—±Lfu�اígK*5/kÍ‹Zo°ÔÇË�êêîâ�(5øí™ñ;`s©•éÉN J €Rp•ú¿”Tê»z -.Îu�¶øÌè#¥æMš6�Ol]œw÷Pdf¢¶ýðMý˜M  Ôñ(õÉÑ:(¥®Ùu]êÓˆR Ô~¥.‰S©—ÙÀí„þé!Ë`ÖÂÊm=ˆÛ•Zäúî5>Åŧ 9Ûœ‘Íësmà�(5GP©_q�ûV+u%çRûMù��ß(5Pê’J½ô�Ús³®~(Âr‘ݵ)õ£„!ÒÒµêJ½f(õ}co(5€R€¹ÔÎÉÔIOVslwQjdü@©€R;•:ò!õh½ÄôÚÚ²¾þžÍŠYÆï&(5€Rv®Ô'Nø SPz²šâ ¿u©O!J €R¥V+uïV]ÝÙ%E«÷Dò1(5€Rv¦Ô¾Ò“)êR×Ôcà7æRƒŠ’L:VD� +¢É� Zæó�+žÙýß|(5‡]©Yï³ËªV›t”@©;žKíJOv2`s©Kä';áéÔÈø öH¬ý m…šÌÆëôåÜd�\ÉÆ _½6³J ãÃÆçg» ÉOf�f‡¦W§®Ç,}ö\¸pÁú=Õ&/\èòê/2|áBŠþÑ~Á¤Ñ¶E�¹%:—Ÿ&c“á ßøë.ŸS.hª6© VÚ-[B«„4B©8JJÝü®ƒ^o¥fFýÈ4êåÍM£1µâPj¥ìX©½Ó“�(¥lz²2 üÎÎ $ƒëÉ�ɽý\šë„2— U dÚf[y"�Â×¹* ÒX“åöy)�Ù¹bNö(w˜È}¶²UVl§Ëy�þ´yyp½_F½m‹ ËmH챚 ø�Ï“ãs!ÊŸ.+«æ†FB®@©8ZJ½ƒºÔ¬´´Å¨ÙüéuK«{Pj¥ìy.µR©k‚5—Z=ðûÄÓ“]'„…·&4�7v-¸ÎAµah/1¾µ¼A[˜¯ íp=ÂTͪÔ1ªØ3³mV¥¢.ÐC—Æi3î¨ÑEjד¡ö1BùÚ cîÚ$m0Êíop´m†63ʱ+õ1”ÚÕ_vB÷ù‹S*ù×m[\? Y¶PCŸ¥½6„«_©{øõÓG2Äþì·lèÎA©€R«•šuݦeË}£ÄtÓÒYÔ¡ÔJ 8ˆ¹Ô RûŽRUê¼á*ä¡Ô¡Ù¶ò(µ!&$7m ó @¢mdè÷c,oSê9BºØÈ…ì*wÞ$Õ9>B;DÈûó5Vv³5º+¾(d§I7Û±ŸL³_.¢ý¦DÓ}Ç­J� …¼Tjg,.»èçAú Õ[ÌX®¾%+U~„�öêWjÁˆù×tdœ3ªE#PjŽ˜RÇßvà9ð{ÝaÔMIV¡š…UÖzÔ ¥PjÀþ üVÑ Z~2E]êRJM_À;<¼RO‘‰ üÌíEHICdœE÷†¨fñp_#,Ú½qµy›Rçõ4Ïojж˳„°¡ß3„ˆݱi.Å9BºE2°Ë �ô¡­’I1£š9G;Fí|ÁªÔ´«Æ)©ÔÎþiHµÚÅ9,ÎÁ¹EËfå—×ºå¢ –Óƒ^ÑŸRËßÈféG(5GL©K¢+5+=]÷¡Á²S×�ÝX»¿Eÿ|dµm(58jÛ»"÷J±(uñÂÔ•œJ]\©OùLO&_Û“�ýâ5¼ª”z¯BÒ-‡G4åŃH×jˆ¹³U©ÛºR†ÇÑ›:@ˆÌÖIÈ<ýc•t›£¹© ·bNŸ›˜ÖE·C|X$$gUêSd]©�ý‘©pġԓ‹h¯íZƒž*¢å²±¤U©39k޲hÖÑa8µý)C„–Wðd8ëx!ײ–|ÏÉÖÎLÒ­Ôt¯œæ¹S¤H‡þ”ú¼1ÐJíA*q*µñtºù“ºnˆ©ÆE/Iˆ>£w‚ǃÇYÒ,-ÛèzaBFÄAXr1‹R'ó¤!¦+µ«¿kô›bWêŒ ”Û¶äd´Õœ}KòŠ>Þ;+ÃÕU©Ô/¥¶¥Jí_©›6ˆ¥-{e­¤M©ß4”:iUêûPj¥à¨+õ�üfüðdê½F©#æ€Þl�‚ J=B_äWÇù õ )ÄÆ§Í÷ù!׆»ióA-bïûyq¬èu¶PX”–;Ê’CB1žó™í“bÃS 2X½Î†�7ÔG…51º�>ÈbN?�m']âÚ¼¶)„$dΙ±µ�V„R{¢TêX‡0ÒFy3¹~ßõ¯ᓨ'H^äuÖ^ zPJ´6F&¢V¥à]êQjg »RÏ‹ µmKŒ~“®wvRá‹Ù¶døwF~§ê«L©ÃN½sÂ8”(õÞI,ß][»»„Û  Ô€Ý)õiO¥p]ê²G©ç­Ñ=a/T©'¥å23™$ SÖY˜�y±ùb—ŒžµFD&)K™¤¹4Âm†í#s‚]ã�Èð¶sX«¾ºŽ(vÒMø²×6…�\s(õiHB©w¡Ô�SSÔXBòÖ qUæµ®4®wbdxNLé]%»å]_´vHÉtflâôBÄ¢ÔáU¾AWjg.¥Î‰çö-ƒò_3¼Yn¡‡í‘mWõqÿ�UêÕq� Ë8‹ìç‰C©€R ÔTR©_ñYD«’Jí»ˆÖNëRëâ™›"Ó¬]+•Ú‘Tn`B( K•<Õ^˜ƒt™æÍuvZ”šL gz˜ 7„2}CÂÄÛéhÌ ÷‹œÊYê»õ Ù6ÖH(5i¸–ËQ“jÐDã™ÑÜèŒØ˜É“B&CßÞë É_Ë5Ò#æ5÷N¥VlS(µ&b|Ù)ÄD‹ñ”zJÝÈyP„øéƒ[¤·=Ê9/jd±ÉÓ¼u;¸ÍF(dÂläå¯Ýª“ÍŒ˜­6•ú¢ÈG¦+µ£?·R_´©�-yéëæC–[Ñ¿¾ÆT‡ *µ ]iÏ�‘nñ=?ŸŠSêpn÷y Ô@©€Rv¥v ü>éS©Hª}g'Û…R“©©©jÐ)2nÓ�'É•zF1ì!±uÑ:z7,çªvÊ¢ÄÚ*˜Á!&Y‘¨˜žÝ/†L­…ROg塲|ømž¡›�hĘKÖGìêÚlÝɩԊmž1>– ++÷nƒRïF©sõõƒDÞ¾ðû�eˆ>Ü)B’â÷ RèŸàËõ\© |°B¦`¿pA>‘†óV¥N‰Ó†R;ús)µ-H­o‰Òo•ÈÓUÐÇTÈ-ÃúqÙ�ˆŽ G©uº�op²Cþ Oë·h¤ìY¡Ô@©€Rv¥öS—º¦¢Qêâaêb5´üÖ¥¾Ø(–å[úœ^êwXjÕªKZ�êE¬0’^ñ¨Û²y�;VA^Ö•Z˜Lï»QV/Ög6K¥nÔÍ'Z`£\;9•Z±Í+ÆÇ¢â!ÝݲPêÝ(µø{3!ã½™1~ƒ†ùw„g,cŒ/ðç½j$�›3sǺõ§’t¥ŽN°™ÕV¥vôçTêEk�Zß’u?zsËœñÐÛ®ÔÎqŒzcäú5ãÚ Ô@©Pj*¥>íC©+;—z·¿}Ô¥¡\Ì_áV%–|È!nÁýE>Ê”z5éPê6ð›—~#óuk¹…ÆÑ¶S؈-.èJ}]/^ã¾ÔÃÉׄëH¥®7$aœŒ¹vr*µb›GŒ�y·~êœ!×Õ¤Ô�æW5,†Ž@©€R ÔTG”ººŠhí8ãw.Ï¢_YÃJE ϨK}]*uCÄ¡ÔR©/X•ºqH�FY0XÖ*ŠéJ= ;Î5fÌ&“¦R�9ÐfÙ ]ÇNN¥Vlóˆñ… $/EzÆ÷ ¥ö­ÔZ.§ÿ±ª�q'mûÍò»¾h Èêw9:eÈuÎ6” À›[¸æîÏ¡Ôãú�>‡8;³yëûô¢\=æðêQê½éƯZZ6 ¥J €R¥>í£ˆ–jà÷±JVÑ:îg2µÿ"Z‰JíO©µPŠ>ÔdA¤“ã�¨ž'®Óä¦Àâ×—õñÔ‹âCt‚ø7�¥'ã?gLZ&1G³jÞmYÚ.£¯È“‰l6æîϮԎ µ±eRNÑŽŽOLÙ·„ˆø>{�½*”ú¢™¯J ”¥ Ê¢ÔU;ðÛ_]j¦•‹ªôd;WêF}íßi\æSb¯ÝJÝã�„)žv§'+‡R‡,i­êÉtJ½¥^–:KÈØhNë›'d5,îm¾OÓX!5Q¨º��ëád+•Z‘gŒºka8.ȹ״2*1gæ›E´$Cò›èêϪÔ�Ž µ±…ù{}_&5ãÊ£«´dªôqߊopýžŠJpa(5PjÀ¡SêdT‹ÅÂ’XL‹&})u`Ó“•pê¢E´üE©““\HÝE´v®Ô=rHõøÍ ·å2¡ ¢Rê°,¢IMLôˆ°cXôvPRÍå#J}R‘ñ»T]êJè:ÞéV*ô­}¶/70!bŽ»øÝp-œk»"”šûa\P)5 ZæC™\×4YÕ„B÷§2|Xq>”KM ã.‹RŸ# YäÓ"Ñ+¥‚Rジ¹+‘g,ÄÒÓ±y9©7YÏ�·0`ü�õËú�ï]O·@1'Ú[©íAc³ˆ–«?#Ó|Ö™ÍÌAYgumÉòþæ"�WjóGŸË¥np*uJ ”PÕJÍ„:¦E‹Ä¨èŠ¨ÆÆPhÞJ}Ú+H”ŒßÇv;—Ú‡R¹¡²úðlNWd·JÍU1¦Çå›þS�Õ.M©ÔÉyyÀ+\©R<þÉENžV8R&¥ž3¯uÀ®pPj_ÿKoh[4ÛgM’•̆B�Ö¿^±Ô\c«µAn4”ÚCÕÙŸÏóås±UdGC}(”(5 (J�¤²‹â›(ûž&K)uñ�ßÇ+7î[©Ô5eTꉋ]R?:ù@Þ1a©mºRwq;4òpKÕÑ3Fd´ð¢HÊÜÆ:ßIw·<šK墬õ€eŸ°žAj–1åi ¥ŽÖÌÕ®�tnóÚ¦ˆñ]³*u—5D ¥J ”üm«dˆB ªAª=ÕÖ�ß§vœžìÀò“ó5—Ú5ð»TÆoå_ê\6¼×1'a3@˜ëì½¥éSÿ.—Éf,ÿ+¢� ÉÖlnßb‰S– 6J ”üm«XŒšþC‹ß *ðø²úø]¬Œßê²ÔŠ”ß;Vê2S/“.‡'Èj`~~‹N#. ”(5 JƒQƒjrêXY£Ô,xŒ*Zî0up”:v…�îÉúùiK9âŠÓøJ@©PjŽ‚Rk0jP]N­�RUêJf'S9µj.µÂ¨+®Ô‘Ô˜œÁ|98_…Ëe/;”¥J½CÁ8¥>¶»(õ) üB¥6­8þi-å »}M•ºÕæã@©UêÆ}ƒjÃ=´B¥Ô'Nø SPz²šâ ¿u©O!J 8ÄJýÏÛÛÿÂ?,^»¥Ž?ñX¬)¡Q�D È…Á´ÌF%(#nÖE0P¡ä»ÿ.Ù$"þ�MÌ�a½Æqö°ÙÝœä¬íØuª§v“=çW¿7óïÛ™î™i„IøúÖn<ÓÓÓÝÓ‰ùÌuõu=y²Ö�ÿƒõônR uÇãg´„¯gæž|÷‘°dÓÃOž­ñýÛ�Ùþg²“_îïG(Rõi2„Ô_|áCêŽï¿ÿžnü~ÿ[xxRƒ@ pHýj«�§{©A'©¼–º†FêÐVj@jÐ!ˬ²\È:ªèÖë·)25š9œJÇ€ÔwŸ>áz‘dHýÙc^ðŒ2õ²Sá ÍX�xáì?Îõ˜u~Û/q[uµHý›ýý¿&áéH �*"u¦ùB å. ü1f�RƒN8R‡uüÖ&Ѫ·ødš¼Ô€Ô WEèüÅ‹½b'5QB¥ ×|V<åfÓp¡t¡yÐ9Þ>Õ‡P!oËçô_¼x1£ë¨û¢«VcPÚ˳šñî‹Ãâœ/¡…ÂpüµúHšŠµò‰¿(«[_©¶Hý “ðݵçÄð¼&øøé‹�Ö8?%X‹ûÙ󻫽 cß#,½º¼FÀ{•ب‰ûÅÚ=²ÿ˜rðÿáK©¹€ÔÆ>ÄüRƒ@ HÝŠÿœRŒ¾€Ô × ©ß®n-uM—R—Gê·'<™==TÇö?k(Ÿ9ȱ“¯òþEU«›üáó:£ÿ³â-ï,ðý)~Ù-¼`Ú=©“ü�jÕu$*5ÓÒ¢í¥JM²szøºRê5ú€[Z3wMžTÔWª-R?yr›>¨`bþ®ƒ!õSºlz o™ÑèMNÎÑÄcf¦~ʘ%Ÿc„ÆÅxÿ)íù¹ê¶}¤Ž~¹¿ÿÿÁÓ#�U@ê&ü×ubjhø B-í€Ô P0R›©+Dü>U¯Žßo…L¢µ‚5ý Íj�vñÓºY¿Ÿ%F†ìAŽ�|•ÿå®V³ÈEj ½-SM½˜s–‡ºåòfâÂÔPãîEz<�·.L/æqKcÎIHEj·£K\¸Á#%ö&Š©c£¤"CêY\”½64Ž ì×çîï³³bæúéÌ”ð4�/ë+Õ©ï²Í›Ïž<ùˆ!5³'Ó‚ë««7Y�UŠÐI\�t¬®Þ¦¥Į̈`ìçdã[‘•úàH ñÉ@€Ô ¨2R[ø/ìu¥›Qì€Ô @j©ÿ-lÄï:^L}`+uÁ±n•2u�ÔMS]'©#SS™ÍС"u,‡JŽÔ|£ëØ%þ÷E|‹<åÓ ´Nçнƒæ¢Ýö$ê³Ü×¾ã2RË #$Mb¡K¸Q|×^)0¤&èzyc'ÿçktœjÌŒZu¿ªÁ•j…ÔOÅšeÄ©Ÿò‚{ž|ZËìÐS\/¡4ñ‚o¦1]“#ÿµ¿ÿÉ+"µ§ �iþ$¦ñÓ Û2[Ÿ½Îž´dY0må�dÌf�.f&“ÌLÛ¤�h¤~'©ë8/õ¡X©1œà‡ï Ä϶h×RO \èºÖÐpæ ÇŽI³²AöxgèP‘z cïÿ#rI\“™k‘졾ò h’Ý8‹õ3äîcV®µ´p§ôxfe¤–;RÚQžv/.4gR§œ øìèú±cò¿üØÞ FêàJµBêÇb›Áô]nif–Æ�å›÷RÓEÖw—U?ƵL&ŒÔOˆÏø¨&fR/}CõÛº¥Aêo÷÷?ƒ§G 5*�Ô6rªzúé“Fl…<7·4³¿Ð±•±LÍÅ™% ŸD%rÞ\¼Phfvï÷MRƒN*R¿2‰V-‘:t­jóRÐU  =—Ù#xC!u�ë„ u†@+']«Eoû÷•è_†¼‹øŸ.„½'Ía>–‘ZîHehéE1áçÞ"þûÄ‘zȱ–÷ 4s’~©âxæFúðŸßaÓj"­ x&zRTé²H\©VHí¢WŸ<ùNä¥V�zùžN‘ºƒ§Ìz¾J©Ú�NEœÆ¿Üß¿ŒÔ·¾ðèC RY´@€Ô ¨"RÇ&QNý˜çž4bª)>siz¨…¬jÃAfÔ¢f—K¾�2€Ô “f¥ö9~¿©� ªCG';(RËÎ,†™±ã–ŒÔ錥qg 2¤i|`¬ˆí™vÓ–4Ëî30â³2fàIF™Có8î¸×—}sL[ë©pÝN]©½MDzLï3±àåêò ©Ãwí"µi¿âÏ´U@-qAº6B]x4©ž˜ï ®Zž+›ùÆ8 ›eÚ­Ò`R$ð˜„ÔJG*C{;EþÑzÅYBm¢“ó6†èyÈ·K½|mF§|<©ƒ+Õ ©ïŠíeŒÉ¤NÞ•€™ú„wÜãMS?S‘ú&Cêß¼:RO� @jT©Iä—Ò´ô$Ù…ÐÕ±ÌØUúìCö.´¦G.#ÔÍi;;ÝÓcD0AwÚ½9öê¡….;Ý5©ýk H :!Vê0y©OÕÔJ]ÞL].‡V¥µÔW�-$ÔO冤Å? ÅñˆÇ�%Ø�æõ�1Œ±ÙkŠÓWsäœy£WâÖEÙ}&ÇØ¡ÏiÍeDGÊI¢ºª9–!G5M�„ÇéÚÌaÒõ•.F«6 ¢•í©d@ôÔmâ/'G–¦ô`–/oD¤–­ÔO5HMC€¿¸»¶zsÍYf�¸É ×w©•úÅ*×ÚêjG”Æû]0R·ÍS}øÅß°­6 R{"œ�@€Ô Hû7‘>{º[câ¹­@þâšøA— gçÈ^Œ™¦0RÏŸ`…bÆõã[àÏ;½¯=@jЉ±R¿©k»–ú ¿ß‹Ôf s›ÍˆÜ{½©¹wK_\qg)kHS}`Œ~áùÂL™øœIV°èsŸáN19©¸14' l¾VÕ±œ°cfQKÌã¸ã^[D \ž�b¦²Q®+�zÌÓ>÷2Ùi’.J)_]3Cô,uÐ ©=ŸÃÁ¾/Eõ‹“.ÆÞ‘¬©GånOy„ŒÿAÝôŠèR¯0ÇÞTL!4kHH­v丂Ï6Gjü9géß.ëªëðôAjzôðXæfQ„Gi<¤vÖRߣÛ>¤~ìD#[v#—ü]{Jc›=– Ý\�!<� R‘¹úÓÒg/ó™ù UÉ52Ls’8^zT`Ï;ýÍ+ôÁ¬OXº©A¯µ•º±’hUk¥ÎL IR¯#Ûh*3Äí¢$åíDkdö* Íำ”7¤©>06fÚæY»‹TbH�Z3ŒT-¦×}&’. R:�?£f„ ‹™Ö<{è=ɃÍa�õr&‹Ð‘©Ž;îµa8�ÇÈÅ FÏÄJO.»¯d@Têšé1<„tÚô4AÎ�œj��È�¡<›óio+¾êî ©ÃWÍ‘Zý& ªi—tq/“èbÊÌ«ïüå‘Qþ®aŒ¯E7›ÒbÓÏsZÎ2R«9e™ ÀæHmàë'¯‡côCûIú¥â6y«È§ä*ÿs,ŽÓUí©X9¤ŽdÌþL*R?“ãŒù‘:ñŒ…‹*ÁÀ…YûÉ ÒÄsO«‡�Dë?÷÷ O� @jT ©ñSåâ8]Ý¡Ï<ý4fÉ¢Xmff[ÇZ¨Í:�Š Už½ø#LÌq˜¤�@¤~'D-�ã÷µÌ¢õf˜ÅÔ!’hMLL\Å—Kq“q·”’ߌÔWMfÃÎÊî,å iªÌenb%hÍ�zÒæ]Ù>÷±R8"vX ±|’›Ã‹ð²!²çéÙ½¶C—øxvˆöOG¿(ÿ]·ZW¬¥V‹É�f½¾Ý|Î'c«‹ò _4Gjõs8�RÜo‰“n3Qìš•¿ ¾ò4þË’›™"€ˆUš u‰šÊÓ%†~YÔÒ.#µ§#�‘Zl�Ô‘+ä]Hß\ôýðIBê.î˜ÀfaN³V<2)ækôPmô‡�—ú9Ë¢µ†7WýHÝñD uâ)Eê›/^ÜcgtÐhd·1•¯²ÌçÏicŸíï?~5¤Nþuÿ&<=‚©A Pe¤¦Ï±ÍEš u¹"Ö�֬أO“-´r�â:)¹¤½öVêúŠ÷2Ã�±UdDŠ•Ðœï$/6‡>–e­gÉ0==»×V`ÎæbgBlŒWºnO]�Ôjq„¯.–Ë1–ï¢s^¡º4Còð•A{"~˜5c9>6Nº]îze%Æ··<ÖÇy0ž¥Ÿƒ�ÿ 97Ö u‹§ï R{;â l¤v�ÚH_aÞX#sô=IH=Ä‘úb R/â+�4R?¹›À {ûæ„Þñû1d�Yx²Ox�ÄgÔÄMHûÙMBÒËO¹Áú“ýý/_ ©cûûû×áéH �Â!5³˜Æ„ L¨°Â¬ (W˜P‘Úö„ö¤�•ºÑ¿+å¥źTX fƘã§bSæ¹Æ¼qé†äÎRÙ�æúÀDœ�Y�Ô+‘ýî3›@GW|'y±9ô±& iqzÌÓ³{mNZ†S¦pÐ)°”D%w yÀu{ër¤öG¼«hÜÔË=dÎ+U3ä¾fÉ/Ù4µìyzv¯Í¤·Q¶É¤Xç*Rþº½u9R{Š�s¥Æz�1�V¬îÎ�2|yÐÎ/·â‹tÍɃÁ3ˆyxÂ%\S¶ +å]ÂÉ€6aÒÿÚλš)R_RÉß¿B‰¡=€-!µû‰ç_;¤6LÛj¤¾ë$�^‹ê�:ñœþŽ…�ÞpNxv—z€¯:y´QG£ÿ¡$¦>RC- 5 �ÔÉ$–4™g?ájG­â¯uV}Rv“¥†©A¯RëòR‡´R¿q\PM» a¥~Kñ;\^j/êp�Zñ�é†bbºô#µÇ}我ƒXùÕ#Þàžž¥k³R—hŠ‚IWKóJ¥B¤öÖåHí)®„Ô•ª‹òNœ4hñË­ú"R[%aË·Š’ÕÞW>äú;è-4í\F9©ñ½xQŠ ØR§GGy6ŠnÙïÿµAjGu�Ôk‰5j¢~|3êAê5ŠÔÑ$KCýâú ž,y—<}Ì:zã3 ÕÏî Óôg ë‘zàÖ­oY›@jÌäixxRƒ@  H�çf,áø=i’¿ÏôYËHårý°{y-åIy˜³sf’>iRƒ^ ¤~'ÈH]/¿ß8èZêðH�ŸÜ :Çïê‘ÚãS‹�‡tHÝì!�@ÇïÃAêA„2q†ºžžÕk³2Í-d.LýO_Ðu7{~ƒÇ _±©eÇïJÕý3ä4ÿåö|QÚæ* œmÇéÚÝQApÔ&lQw(Où, ŠiÐ jd¸±*Ñû�„'ë4b¢]ŒÚ]vFÓ‘—¡{TÀv“hµ +&¿aK±õKu’�š<¥,/w”«Ö±¼œP æ²ÒCâ†ÒBdÿËä+<5-ïïÿ5� @jT©ÉâµBÆ´‡Šì!k ï7¥3½“¨h’‡­–ÅH¦kÁƒÔ$zj÷`fº�8�Rƒ^3¤.ïøýfíü¾µH}êP‘ÿ&Ìé“U�Ô˜qöcBÓ-û‘ZuŸ!ÀXâ~4žðd‡ƒÔV ­L“Ÿ@_ÏÞk3â4˜r�Ç7 C;žº³<—Z¬CjOx² �ºdø‡¯ šýr{>‡WR–ßþÓ�·cö0þ ’a¾ W,My–äÌÊÄGEJí\0��”ÔÅEn-OG^†¾à1R;Žß½øÛ i’„fM'ë—ê„!õa+ùå«Y™?¿o 5 ƒÔ™>Ç�n˜f�á{ )æ$G49îyR&�½lužH z]�:8âw¥ðdÇŸì�Pk©}ŽßaóRVžB§?‰VõHíñ�Iáß™®Lº)‡tH­ºÏP�°–¯´sÇ™k‡ˆÔF3êË2ûª§gçÚ2…‚ˆ=–¥BI-6ž›¨D;žº67äªÅ:¤f¿³xÎb«K3$ _4ûåö|‡‚ÔFO‰ÿ…h¡k£›ÄsO¹éxrO6‰WòŸ–ÊH=¡0ô¬o¡´@j¾ˆ½Jòm@êDêèoö÷¿=øÙ‰/÷ÿÚÏŽ @jT© 3Ïð8Ç3cSt©Ý{Àî"O@…ž^š^eØ]g_ ëñØcÐ$Ï5 H z-¬ÔõKÔaÓRkB~WJ¢Õ�Õ´‚�w²£'þ]˜Ì å×Ôñ[ö�¡‰~ˆ.ê�ZuŸ¡}9•¦ÎÊ…¦L*ÏÀñð�š®âeÙ§Ôž�k³ðµw¥­ô%z.qTnL§®zòRëhÇS7Žç¡Ë6=ÅZ¤FÃ):çC¾VüH-fH¾:hÇñ[ù^Enn«8ƒå»«Ì>aKVËñ_D•Æ�¬kýôïO±ÙòXòSÚŽl•¡½+© ã¢H™e5OÒÙC'ì—*.Ö£—øL\*Ñ|ôÕ?äCêèíï/øäÿ³¿ÿ <:‚©A P¤&[›f¥7×VÚN»u#v\�â™Lì`p½VVjb<®�,Z~3ux¤v‚DÙŠŸ 5p,<™êcCäý]±×Ô"µê>ClÚlõíE1¬ˆq˜HM®8Ç#i)=»×6"f$K~!m1!㱊DO]o{ÌS¬Cêü$é`øZñ#µ˜!uøê ™‘÷s8$µ§šFÜ{Ê (7ŒXfPù²Y™±¦”yßiËnjê1á·íP&©cßÿÓAÏíøëþÀJj 5 ‰ÔÇ ' Pc[©Ë"u-£“é˜Z·–ZCÔá�:w©—¿a롎´WÇu ¤î¥T6,Gy.cHS|`(\¥21R{H:'"œ÷c$ËZ5—ÜbßI›»ª>6íD W{–®-“%ˆ›[aƒŸÍ2#h,„Q­énaÊä⸠Ûås›T˜å]”­.Í�2qÊ ¹‘÷s�Ž©?zñbùh|>ùöÛƒún§¿ý6OŽ @jT'H Ïi “UR¿YÁó»†fê7ß i¥.žLï§b¿òW[ò�ÉôôX¼:¨ÿP÷Ãlg;V§�9bÛ£§g¹\êÙ´l¥®ðÛ×àþ¤Rƒ@ ºBêóßÿÞa0²Ð{í!ªÿ½�þðý÷ߟ¯\ùã3LwàV�P¤öü@ :—ßµB»–ú­�ŽßLJÔoÌJýví¿ ÜžÈæ‡l¸ý´³ÓÝݳ¤�@�ŒÔßKú!¢:FêqÝÎÊm}æ«¥ä‡gÎünÐ Ej+žß ÆRÌSO‡Ô§O‡4SSx²Så~kòR¿]GVjH �^¤þþ½dåê©?¼ü!D:»¿}M|¾¿:ó7¸@'© ÌÔ ÆR»±Bèðdš¼Ô§NÕ‡ãw]¯¥�@€Ô è¤#õ�äßdG'¡ë*W·ªëàΙ3°˜tb‘ÌÔ †7RÓµÔ¾ðdoÕÙZê ñÉN2õ;õàø �©A Ðk€ÔX ¼ý2qÈH½ôÕ™?À­:©Hm˜�šÔ@²"šˆzåÓ�.o¥®Ûðdàø �©ç·Ö·æÃåÑIÎ/…<°äi.±´½î;±m©|§mä¤D…–5EÖÖúvÈË©þbÃ\šfI2Ǿ·æááùd!uÒl÷*Vö„Dçù: ©ÛpÑ�"ºXG{;¾»,û|„Þd‰øùóqéKaþøÃùc¤ŽÆ¿ÿþ{“µ×þ#íÂQìÇlÒCjU_k©õŽß§ë1<¤Ö[žvÎílÉ…{Š6ØóõÆÎ#\óÁ¦¨ºä¯�nm>Ä•Îîì:þ‰�³¬ éq|kó�§nsoï¡óX¿qÎ{’¿eMÑ»œG´ÄR¯cÏ1±­“=ÚvpѦ³ç½Xý¥í²KÛp¡Z'½rÜ€IDATã¬mV¶·ñ¾;'�|sj|¤îøÞ¯rþ[þü^‡ƒÔmï±³^²�axï¼ù’$mV]xtwòÅÓ/ã~¤Nð¨cN{âHì¥ØgHÝÁ†ˆw".™ÓÎ Ñ<{tˆtÒ‘C 05¨aˆZw³¾ÒZê©C[©©A P}"õö9¡�¥ÒÍsŠ(.Ïï8ûëÞs±Œ&w�‚ί ÷¼]Ž”r-Çõt‰@ö9¢Kg½�iZÖm¹%Ä<¯^Ç91c¬\åzÍ÷EßÅ–¿´Ö= 'º³¹c|%�¶àùùµEêä{¢ÎË8Rw¸!ÆÎs¤þAÅp¢yÓÓø^­«Cêv·=vR»{N¤îtO�3¢þ35èd#5qý†õÔ FP,Ñ&Ríø­M¢UoñÉ4y©©A P]"õ¥áujGÞ–¬Ô�\q¤¦�û`“o?¯$Út¸ôìÎ5ç>p°óìæî}‰»I­G¼· `eH=O:ÛÙØ¸ï2­¿eM…||)9‡‘ÖR¯C urÇ�ÔŒ…ïKD¯^¬¦·$ÞÎî.im'Õ €N&¹ÊÍÝ Rm�V gl°9Ù†蓃ԉ~ üò‡Ü�àÚç ®NŸ¦jrK½¤|}þ½—dßcÀý#ù—¶÷#i2˜ÙÙç_ èU�:† c,ø{ç;Ï‹ö¬û=Ög¤n#Ï·wÒË`y©?ýøã�?„[t‚‘Ú°â‘H;@5¨Þ�º=‰k*d¤~»ºµÔ5]J]©ß†ðd ¨¾‘š°å!?cGàžö(õQ ¥ôGªž£¶Õ]þ¯+býÝ$NÐÉ aÜ&$ºù¾°Ìn îd†^å;N£g¤ÞæÛy1.MËþ"ò‚àì’Ó…z=¸¯ gsï¬ŠÔ ÁRë.V3Ò ñåN® ð× `Ë9qWTÛÍ/ad�„'èƒÔÜxÌ0úGÊ¢Á¢ÐJ›íH}^X“‰ÓõË$CjfìG'/V;³?·½.Ù„žI]©§qa‚®¨¦NÜ¥à–íDAY¤&Òæã”Æ¿>ÃôÜ  “ŒÔÌP7c1pÕ¥¬XÌŒ˜¨ 5â÷ÛÕFü>U¯ŽßoA-TßH½íØjç¹.Î:�wí©„>78zòZêò¿ëx15X©AGùRªšâš9¢¼Þ/u#S£‡øE?&¤¾ï®Ƹ÷ ØHM)·Í­zŸ£¥šR'ùÀµ[cX>Ë™¹Mò2_b6hÌl€Y¸òvÔAj<¬Ék}ss]Û²¦è‘Û0mCo¤&þÚ›Q©éФÖ\¬¦·%‡8?k°$±}Ûææ¦Áˆ�O\x~¿NH½tK�ÑxZ|sKsom¶?P¤nbûï9µÙºëE爨K©›‰º‹+�èM:Sêà|e+u;|î ×©É³•�µ�êSñ¸Yæq[ŽøýVuáÉj›—¬Ô ã ÕéÂ$º’÷UûTB…¼Mwº/ºjeÇG.^L•=Bd¯Œ— ùiÇÄî¥ûn\~©.Q?n…Ü̓R«yö-žÊN'Vâ'iæW.^ã[c/öÒ�ÔEYÝRå¦"B­�†ÔÄ\º%ùl�FjJ† —27¹{öûjí­íí„{â·þ:Ý�=wn—�·u‘’¬y¦aÊRËà nÙ_ÔvN:o]°j¤Æä|ÖP‘:A)ßAjÝÅú°.]Ú&eiÝv¹i^«�ñ"#ºHýú õ‡_|ñßç¾tcwsó4q�q±’÷Dè1·YžpK>û=ÖÓK9*Ú{NÒ¶D‡ÕÞÉŒÎ?Rwp×^© ºTûÇøèA¯Rƒ@ +­ãwȵÔõ’—úôQ奶§‡êØög å«»¶¦é¸á«“™ETE[½1ZX1š&{b‡¨™ž5ƒ·®•=‚5Íô¥Ù~ßÏñOU®KÔ‰±‘rã´Ô*"7hªÈÏLŸ ©/ «üMB-lJ®ÉŽŠnÝV„© :ŠˆÛI­½´M ߀K‹Ä`K‘øá¹=òÀ>ð¾®m™â¦s.f']Çgüˆß¶+ÖKs|DŽ'æÛÊ´ì/RÞ x\ªw#5¹¤õ¨ŠÔ쨃Ժ‹õྐྵŒ½yÐà>sòN–n©z›Å tâ‘ú�_|ñÅ-©;¥“ÞãñÊ\½¬€ÔÎÙçýH-޵;ÃI•óÒ�ÚÊ#uÔÁÈcð郩A Æ@j�ã÷[!‘ú˜ :tt²ª‘z!jêšÕ.5Ç�ðfý~t˜#²ÕØøâ˜ƒí| �.aN›ÃP'#U#ì…éÅ<æº1Ri‚«€Ð îâ0|Ä0z1^ìšÂGZèMÖŒÐäLW3fø"½eåºTˆ#uJ´:Q¤H�Âg�u]E¨džœ©H=ˆ¯Ž¿ ê§]Â÷=ù÷²d¿ï³³uŠÔôÈ}¨'Ôçð°†kºË…·˜÷ò¹sg„ï$ÖIü®»š)²ÊVjBí£ÔÍûÜ&[4}VÆc�ÔÔüÛ¶A3Wo̵ì/��Ä»çäÅámg�› èe¤žg':H­¹XÍä c¯t8Kжvhóí¤Æ àQž _¤þ#µt?ËžÕ “¨©å³;¤>߆wRf%Ï«Íý ©R»Y´^‚©H 5Š•:L^êS5µR—7S—Ë¡U~-uÁ1y•2u�ÔMS]‡ƒÔßB™@;Hë¦À)u!ùõFlú–žD}²Ã0žafK�S`XwÄ*1£²…Á¼Ÿí—lŽÚ͆¦•&„Æ=ÞÍ„.á.£ÉAüOìò¡:?× RgŠ¥”£î·rtœjÌŒu‹Ô_xtKº‡ÎÎ}¿ñW&Ñ S}c—$‘z´Í-¬;"¿òCË=g~~iý¾€KïZêG”¤IxmžVJŠË-�ÃèæÖoùì|@Ëþ¢¤g)³„Ôî«�%n–�šDÛŒÊHí¿XÍÎJfý%ºTN¸Æ¢ex�:øˆAýñǘ!{ÜâíqÝq÷ 5uÙ>z²�Ú,pû¤–Ô€H]ÉJ-ÅcV×�Í ¶*ø}nÜ5r‡½—vw76PŽ–Xrân®EgïolÒC[z¤Þv[ÞÕ·¬)Ú¢–oÚîÞ}×ñ{à‘hÏr‚‰»Hí\¥‹Ôþ‹õ÷ö¾l¥à|íEê×L6¡L¯>8èµ@êNÇü›lróRóäÓÑ^¾ü±R»gS86¤î`K§]¤N¼t Ù<¹ ø-!µ»Êú†Ôï½÷^Üáói¸@€Ô Ð ²R×W¼ï�áÉB#5Þb,k_ ¡“‡¤ÅTZ§Ô蟤6Dª8B‹#}¸ú°i5áj¨ÀúŠ­��Ò§Ü1gªÔ§ö6rNŠø«–8êÆVˆÛyK3áñí´�æ2¢#å$aÞì :¦±ñµº†V@êpJÓæŸ@³SœCs˜~PSrnê‰pUp>bX#“¸5þ¡Ìe,3Ur?'·®yåb¤ îhø¤­¥Ž�ë^œ¤^—sQû×R»$Šiò‘ÃÈ„IMc}}I:YáñäöžÕÄŽc‘Þ¢k·©qv—› /––¿Ý¡lzòKK-kжE_{[;.¯º¯6�q:H½äX›Ý$Zþ‹Õôæ_K­am' ø¼òa÷œfõ:èä uÄçÆ­Š`î÷�ħ�†%{�Qø÷Óy“ƒ‘Ú9;ùã÷‡¥åÕœ‹‰�™ ¡ã%¯s^$¬¶^ªHMýGþ"€!5®H¯Ù”]ÌA @j¨ñ­Ô ëøýnX+õ �žŽˆÙÆ0Rç9審U°…D].IVÁvøR/rÖIÚAÏXN£~¾7JùŒœ3É …©‘Š8ÿ–øyRq)bhNH}-è˜ÆÆ7ŠZ,@ꪔb‘ÃˆŠŽ×<Ù¾ÔÇ?ž9×�!ƒØ-äçÀ#ÃWñý6!^½ð”[})Ý)„f RÏxŒÔx´'hòñ|‘' ;¡HMøÏ�Ó_¤,ÙHMȶÍ%ñsž(Ø{À—Ùkq&˜›÷Î6ÏäÍóh½ä^ܤƒ—´K ©tÿÀ‘¤Ž³ Zç‰ù÷ž H 5R×mx² L]6‰V(+ufM’z�jGS™¡[ØJ¢.O´Ff¯2cÁÜìtO�„Ô(7’î'$ÜÒ”Ì2‚íBèBkzä2‹mcÞmžµ»H%†Ô¨e1“™â¹“på«c™±«ì`º€Jét„fT*,fZq�Ä„é=ɃԚc_�úRW¡!„z\Ë´cX¦¯:šÒâ™�w*_’ WAêÀ#ôÝKß43u[ýœÓói_Ý ëHAjÔÙÛ bæM~Az·EÔžŠ•»{#™C¼¥�//µhÄŸ—ºC.Ù“`0ñHÇ´g=�KˆžXšO8¾å˜%÷’:ßs)‰–»JyÉ�Õh0üËE‰ù¥îŠmy_ ì�…ÐL˜n776–(o°" Ã76v+^,ïM6ë˱ÓÕ<”�Z>e[t¢�šñq{™ªNŠ«iŽÉÑ67·tS¢èBë®§¶ÐYíÅjz“-óþþÅÇõ‡«oQŸ|¤6^V@êhœ�Ï'&G“?r“2‹V©£Ö{ yèˆú�š/žN2 õ{FL¬•ncɯ§-RÝ`ë­é�KBDü޽d%?@Pz 5Ô0HýN�‘º^"~¿qеÔ!�šëR+Ûç�íÓ"�0[ âlRW'ÛYŠnʉ©‹N ·i7ö÷œB¸ÞXÝú#ôîeáÈÆ0@’eFÓË…-Õmâ¯ed¤ö©ã}NÄð“ƒÔÙØ_ú`‹ønŽ4 R—ÉK-/�Þ�sT{H”…·V ·+í&õ™Þv²?;(:¿±áx7¯3£ø†ÇJí¡R'÷|k©5-kŠÖ‰Ù™�ñ¡siÒ«�pH­»XMoî"lz™+ÍÖ=ï ¸:nuó}xt>‰H­¼Eêè¨ðÞ¤­½Ý[¥ÃŒ[!)6a´·êv´ÇÔ «ÝÔž“ŒµIϹ&ð4�jD¤.ïøýfíü¾µH}êp�zëRa�&ÑŠ!)Âs¥`æ„ÛLmÈyjºV�º‹›0g8<ñxÝff¶•,��‘:<®Õ¬@ê�D‹†±‚P?Í´Èè�#u³C ãèŠï$/RkŽym|d5n1H]�L'µZFÎå”s9ã$“¶U•À9øˆ!>b7Œ ô¿D]Î n^×,¡\º ætš³Ýeqo²‘|Íž¤6ék¬«ô¾�0O‘…ÔÛŽ=Ö8Ë]§Ûæ5Fjj_ÝIHh¼Mix�ͳE²yyžqi‡‹§gÙZåmÏZjŸã7iY-#칡mYS´áæòÚp®Ì’£‘o9ÂØ¾»µeDÜ"rÅøíÅjzK>�©ýl[T;’ˆŒ›£i6î61_÷�UN>Rƒ@ @jèX‘:8âw¥ðdÇŸì�Pk©}Žß¡#~g „cl‡J™UÒÉK½Â‘ºÅð õGê‹2R·f…í;FŒÃ<ûR\ õ�À¥EŠSŽò.R�;1Цj÷žäEjÍ1¯��XÐݜŀÔ!UB—ÙF¿ìU=çüm‡¹Ç•Á9àH$#>–æºèŸÏ8KàyÝ ’UÒ€zlÂaû„ÔWù»6¦m5"R'ny$Û"TøÀàhK¡pû§IK][½î$ªJX|˜`5vèæ1Ÿ>`æÛG  ·Îº”y–¶ÓvŸ[u{JÄo× ì 5�ï=ÚÙÒYî�®iÙ_dˆØÌ¯Ú5sk,…dçnçÃý ‹Õ `[\ǶÈô¥À®CF#�oˆùÚ¢¤�@€Ô ÐÑX©ë—¨Ã¦¥Ö„ü™D‹€:¤n¦Q» ©;ÖéÑ!õ„ L¨°rÈH-ÛøHå^@êj5!ìÑáuL4í8~w ã5¾s.Z¤:’E9ŽˆÝ4Z *ñýÖ0H­€º5ç ýICjƒ¿_9ÐXH]V„üÎn¬Ó˜ÜwI{H4AYïllÜßs’IïÒÌë»äœG[‚Ï=ØÜÝp‹xŸ»¿»¾±çäŒ"LznOä¥vÙÒAjžzw×M\­iYSDx_ìžå4º­©u«é�¦ÛY_'¨ü -0Zëáæú&i€š¦ÛÈ‹„s…6á �Rƒ@5´Rãq}dÑò›©«FjŒÅ�ãwõH�áµ4kÂ[¼$mé�ºÙƒ�ŽßÕ#µjãK‰EÛ€ÔU¨‰­s&qʨױ=Dœ³c9T¢w OÖ©3EKHtdZ¸/DJhÒ$ˆÍéÜÌ:Ž ¼nÌæÂçtÙþ~Fõ¼¼Òû„!5Yd^LŸP¤¦Y&†»;!}$šÜ•–o{O~Äñ´Ã]­ü�-=t»àŒ>/­i–üŸ]¤ŽnŸu*l¶ì/¢i¤y^èù²Fê²H­½XÍÚœ"ŽÏºD6=;¯.ÞÞ�'h@jH ¦•º,R×2:™Ž©uk©5D©1ŸÎé“U�Ô­¢4KOçF6bmó#u¿›¦‰#u‰*=áɆԮ�¯MÆ©«Uì Bͦ•âÑ´3]±a—Fâñ\¦@rOÓ¬ž¤�@€Ô ÐQ"õÛa"~×ÙZjmx²ÓÕ[©Q?VÓ ÞÉNÌ0Äd8˜ʱŒDuünYŒdºRÓì?DuHM,Œ…¦t¦wM†Ð—Siêù]hʤ¸�î�šÛøb rø*@êðLM³‘µpŸì>Ávý”‹ÍŒ¨m™pÅ­ÑUþÞš#P=y•{yiº� Í1]©™ó‚âM~b‘Z¼"®#ÊÝ;9H �©A @jè$Y©ßª2‰Öq!õ©ç¥~'t^jT²ÅÓ»›Ðù`áɺY “ãüш�R±×Ô"µ5Ã;\ °”¢¡ÍðÆE1¬ˆñjHÍl|³rÄj@ꪠz¬iЙ-gÃÊŒ5¥^yヶ⩟µc0ãµ 5H Rƒ@ ðHý®ßï[�Ôµ\K6äwõŽßL¹K½ÜÙ¶‡êFW¥v ôì¥t<ìÄáæ$"J•¸)ò꣧†.ôà“/Å2©LŒÔ’Ή0C¸›¢Ï9>Ì‘,CêXsÉ-ö�$�º+è˜×Æ×«@ô1Øù@ @jH Rƒ@¯™•ÚÏÔoÖIx²SoÌJ])â·NfÆŽ¼j�§ˆw&¸§‡µ–¢é‡5²ÒvZ"\³�íX�væÐlÉnhsH Rƒ@ @jè‘úôé�fêc Ovª|ÀoM^ê·CZ©�AÍ5Ó§ô*ÖÌ4›xó®‡; w·]&É:¹Ž­ùJ=x*ÎFbþyxýì¹sçήÃ=H 5Rë“é�úT}­¥Ö;~Ÿ>„ðd ��:YH½´sŽhgËÏ“»gé¡ ¶íìíímн-vþ£�D¹6Û6vá’›¬ÈÚS5ÀšÚ|HÈqg7pÖ¦|Ú¼2„³ÒÚp½‡|7±ñˆ gÉ9ì+iu)pt�+]éfùÑî’ÜÊF˜ÏhûÓÜô€Ô P#"õ�×R×ÐHÚJ H �©A ×©­�;÷±—¨wÄ‘Ê�MRv_0¤sþÎ|p›óN[稩uþœ*r%É]·©ýiX;òióžîî �]z@vü €8üˆ#©¦'Þ-[ œMçJWºÙ°Ü“¶½ÓƒµæCÚ9··”Ü YH ÕR‡uüÖ&Ѫ·ødš¼Ô€Ô �z­‘z‰bÝúÆY—ø¸’÷ îî"Ü‘�¹ ïKx¸³±ñP†L_›Kg©™–™k Z�\ ¤Þ¤vã j?~8 = ¹§Ò×ñÁ½ÍõÍÎ@2Ó�z»÷]¨õ÷Ä/yGFjÍø;WºÒÍÆÒ)Â×à¾a vZ EÉ÷wÈ…=@j@j¨±‘úíêÖR×t)uy¤~»ŽÂ“�@ @jTC¤&I=˜ ²‘ðš¯7ÞÇUÖ%1±Ýb^|(�šÐóÙ%Q�­¯MŠª”fI‘×}·ÿ Á,Ä›ÄÃ:¹Az8-�{QO·DljM>PZû¬àÜ ÑÈóɨ®'w${g¤öO€¿sµ+ÝlàA�¥#ŸÇÈÿˆz�ï̃{Kù@€Ô Pã u°™ºBÄïSõêøýVý$Ñ�@€Ô ¨–H½íeç©ÄFxö>‹²µ¡Ð6ÞÛÙH½)’5µ­osÞ5� W—'öØÁ]§?ÒêNÀi†ërεˈ<ʵñÁ‚¸›óœsîu‰�ù{âpŽ«nïˆÁk&À×¹Ú•n6Ú9ˆ>/^ l¸¾åUhþ칇ó�j<¤þ·°¿ëx15X©A  5H­×}1è=�Ž,¹Ð²S8-w�ú‘È÷9žúÛ$®âmnÑ}�‘:ùÀµÝ⢳§-y‰œpì†Ò�…ÏÞŽ Î%ÿrßî6všžCß'ÞåRk&À×¹Ú•n6¶%fßãp¿éŒÈû�.‘ÀàÖú: ^žXZ__rV‡ï9¸¤� ©ß Dê:ÎK VjH RW1á ºœçKš]ØÜÑP+±oDR·ÉnÜëŒ,5m.¹ñ»önêŒÔÑ­íí„Ú·î4ŒÙ»¤ÞÙ‘™"õŽu8wigç¾Ä´ÛÚž„aù¬á"µf|�«]éfc~{[Ä)K>ä‡qïk?ÜÍú<�v¶·M®ï±p㌨ϞÛ¢¤�©ß ™D«–H:‰V]æ¥�@€Ô ¨fHM Õħ(»/¡ïºkÀfnÖ© ç~Õš6\Ö$&bK]¿mŸáYwÚ6³ô¶i] w·í ë´§Ý67‚šæeA3";H­™_çjWºÙ�4/ŒîÏí‘w ïk�z÷!�¾ô±ˆ ¾Ë`þÁ<Üñ€Ô PƒZ©}Žßo…Dêc‚êÐÑÉ©A  5ô:"õÀ=º•¹Ï;vå½mOùz`�Ô²]v—EñÒµ¹Aí®„AÉrcÙë¹í¬7Ò8kh)ª? ÃíÖü&¦ßG÷}!¾È‚ë]`½I§ñY }OŒgw’Rk&  sÑ•n6$‹ögô$‰\¶Nâš=ØÕd'ÛÙ]'QÓöÈÖ6�šnÐþ×·±à¦¤�ÑJ&/õ©šZ©Ë›©ËåЂµÔ ËŠyö­°gÆ<5c¯ßäÕæ’©A FDê/<º%CæCÙ.-­>ëY?Má/ɱP uÒ³z˜@¤®Í�Äû»$mÕ£m¯‘:éöüüÒú}‡L5§á’ a¾Ýð©÷Ú‚‘Ú8+A²§'v�Äì µf:]éfƒU˜ŸßÞØ1ÀÛð†ÈUýÐò"5M­M“qm’y!aÊ·�|Øgᦤ�ÑJýN¤®íZêƒFü†¼Ô WP÷EW­´dP*É‹jýxGÜevïx©�ŸŽ;H8]˜DWò�eò%´PvŽñî‹ÃÚ¾2SÙÉâÄŠ¨i-^-¢ÒøHåQ§Ü†ÌÆþmj¾PB¹KCÇ�Õ€Ô P½<ØWƒÔÿíÑ-hwd"uW9'd¿åá1�Qoo@Bj��¤×YõmÒÓìÇHÍ“3�E¼ÍˆÛèâ‡rü®3³l¿h³ýž"Û/¥ÄT–šÔõ•â5siFÔ—ø±™Š˜<å6oäÙoå3€ @j�úU¤Pô®‹[Yw,ð²MĬÞVòRo%q•u±îWÛæÒ}aÝ}¸žP�Ô;IRïpøÔœFìµ›V4úþҎdzš EjË‹ÔÉM%#¶·§�o ¤ÖM@@çóJ^ju6$¤ÞÛtC‰ï­ãZdòBòMgêÜIÜõ„sRƒ@�‡Ôï„H¢¥sü~£–Y´Þ ³˜úH�ºO6I6££ÅØØD M^íó`õ"*™¯R_šà* ´ÂX”L¤ž@R7c>žéjÆ]d·áÜÐØB-ô‹8‹ÏÊ^Ç'PÆŽ�’s'5}¥pñðX×UĦ:†›(固¯ 4WiÔ3¨Ä›ºÐÈŸRž™‰©¡a|É-í€Ô  õ+(ØJý¾l¤àx¹! ÕAjšèêÜÙM‚˜{÷)fêÚ¤6Û�Í�btÞqÃr 툵ÔÞ6É‚`†®tuô†Ì¹²‘šÛ“·÷X±î´­u'Ö’ ½ÆC<ya²©w5k¯Ýž$ûp¹µÔ�K]ùfCúä„™ÜX__’æg���tÒ‘:Œ•ºa¿ß­ RO \í?Ûâ2ºJÿµ[*滺òE †ê,Ž ”~�¾$.?;Ê ÈŽQa–#u�0f%ÔÇ�Ôc¼Ò‚IMϼ�)„R”¼/abœô÷e9g"K­¯Š �O¢‚€ÎΞ´.ÒYA ¢¡•Fhœm™-Î%Rƒ@€Ô!@iw*DüNºFZ ©¹söÞæIû¼¥m“Óns)þÜ@€‘Zh‹oƒNãJHg«ñY%Ë”ŠÔäô�d`OøŸG¤Ö‡<×u.wå� àïËö{¦�•"@j@j@jÐÉFêº OV�©Ë&Ñú7@ê*ȿ±>„&¨ç°yÑÁ.³HAïuQÞg¤N;p<‡� ¤ÆÈÌ—Ù_E%òOŸp¡ï¢žÞCÜðJá{#u±‰øiOúûÊär¼&Bð‹ Ñé‡Êà:¶BV_·4ûcw•Ðâ ˜s¡Q¾ÙÓŸ¤�©_AKR&e^ê H2üÜØ¥ÂnlâLÌ/Ú` ©5mîI[™EµFj—ăN“jñã$¸ØY脌ěezÚ!«ª™ÎâšKº èÜCïêlxù=á+: H H H :ÑH­ËKÒJýÆqA5í*„•ú-MÄïJVj+bÇ•½Œ²Õ”�šÛ,ƒÔf&ÓЬi«_,·–z­j›šfír1�ƒ›/‡Ô1~–÷lJô’{ºÂ¯ÝºìeÊK _¥Ë©SÄÅ[ u¡qKl�y[ þÞ Ç c…/¡ÆÓŽÈg“"m¨Híí+BÉÒBè2/ÈqÃwžûäûœ¼-2˜ø¬m5ö¤Ç&™«{�þRƒ@ ‡Ômz4 ØZ·$0´ôöSæí85ŸÓ§tÚfÜéoÓ�=´¥Ɇ ñÆööRTéPwZÛÖ–[ôPœNˆú‘JÔ çn)DíïÉIRåh]7úε)°�ÙØÚv|ÅéÍG£K[[«?¤¤¤�t¤~'ÈH]/¿ß8èZêŠHm­”HüåKŒctÍÑSâ-¦ ä(·Æ/Òƒ� ©Ç¹{4×,£¦ øèB¡‰aQŸÓdiŽv0ŒJæ ÙŸã¬*�Cöh «¬M»�öz)2¥íµLóî <'‘jsEÌtƒFçerv³Òa–»Ùö¡[²\«è6æ³Ûž`Í©Í+(s�š¬™žËX& ãm³j|5{œ.®nu¬Ø˜Ä‘Óúd™¾†YÓçb˱»º:–»êôàwÕJ>֖˳ =ëøËPš®QÈr@j¨‘ºL^jy-ï†j‰uNÓà×Ûz¤^§]Ƶy[¾6ÛÎyÌÍ»#õ¶lŒò³î42*á n äNnú‰Zæ\²&{óýhpOZ¤öO€¶s¹+ÍlHäMÉ~@5oÊQÖ©©©A'©Ë;~¿Y;¿o-RŸ: ¤¶>UÊÙ‹0ûàÌ$Û§Ž´1ž©4Gáö‚Xà™eÀšY�F-£Äó±pRn.¤ëVø»Õñ%—(ÍØñÔ°çåLãý=œ[ sÙÒ}ì¶j@j¨‘:qË#)ÌáÆ¤™¶†�ÑíGœc ï&ņڤžŒø2o¶ ìf@›ëN²*‚¢ç&@Ê+©‰ó6Ê­³ì<Ýin.,'ø†Ž¨]Î%Ùµv¿lO’8Ögÿh:WºÒÌÙØ¡ŸSb“7c9Edh�©©©A¯‹•º~‰:lZjMÈïrH�©¹çVÇٻ¨Ñ5zpRØ®mêÄKëZ´H�çÁž3 Ô¹Z,cÎÎÑ´Â,h1®4GìÑ�l©­zÎ0gÙEž€‰Y‡E¯ãZ¤.Û¼3ÿP‡ÙaV½Y¡²~¾7Ä×ì¨ÀÝÝ_K#µ¾Y–2Yvü.NŒæ üÖ¶eâ3@¢ŒE®Ïþì$BNZk©=}‘w.¼�^âq9GOl¦ï‚úSD‹4ÃÔè8WŒúä/ŠS<Õ™¹8N î}Çý— �j@¤.+‚|g7Öw÷-îÛ1Y |ng}��àƒ¶¤¦l¹‡Ï'�®E+_› {gcã>)âü;¯†C£|yîÁæîé÷ÑVÀi4—ôÆ:Í)½™à¼~î¡#¯7vÛåø¦¶'-Rû'Àß¹Ç ®™ Rôhgc—^3–ïÒäÕ뻾î©©ë iG†Ò5í?Œšº#:j+51×G-¿™:R· 2WšgÉã—X‰˜`#,Ö2µÛŽHx×"uAÄvîo^1ü‘Á†)Aå…Õ2K«ç„£uA ¯íôjNê�ºlóe�šÎIo;åÄ¡&šæ¥ОºH塳ñzi~,š 6R7ñ· ©1Í:é�š�Úv2*›Ì�ÀH_a†×‘9'Æ�ŒÔj_ñ>gí5…h¢ñYê‚0Ž\åÉ-ÃeÒwŽeüjãO¿Ý\DÇþú�:iH͈”jC˜p9ó¶9+Œ÷<¡«%¤¦£y­ù 6£É]iövTg¤ŽF;ÜÍŒu§ ¸µÔnª« ·<œ;¯ÞÑ÷¤CjÍø:÷ µn6ÜÉ8·‘ð©KÀ©ORG²YñÜÑœ«[¤žÍfEàL6Q­DcGß?™'¢™æƒxF�ˆw[Ý1P�¬Ôe‘º–ÑÉtL­[K­!ê²HÝìxßò=Sðâz‹®‚Z¤«fãâ«çGjÓs?KHmff[ÉÛ…Ù7s–¼çÄ0ŽQ»cª$EÓ–{Õ#u`óe�šÑÜ"‡çŒb�^á³0$\‹¯8k²eÍ„È$v"dû�Ô—ùÄ™%”Kwb�`tföâÓꢫ¨MÇNœpmÙ×.OÇ�>'+–„Ôj_d¡ü5 °Gòs+)âE0B{*0¡¾KW.q)ëŽ/úÖY7¤Ò-Î�¤>°�šaâÃmÆ·[�àØm7}ýÈy©·÷8/�mº%çnpGç�s¾¬X‰Ý�G”ž7;OãÔÔþ~´ R÷ê÷�ZדЎfÜ?ÞΕ®fc‰µ‰ÁÛ�Ÿ|4*лH½ H}�?áôÅÄãs½ÄÙñÿÕ6'ûQ³ç™öx�:ã˜BÆ«_Ï»âÚX\Fè <ª3¤~³‚çw ÍÔo¾ÒJ].<Ù%Ô¸³7EP;Âó3?êE¹îŒ©{�š ØAêÖ¬øQæm°SòžcKvGñ�0¯Eê2Í—Aê�Ô�~¤îæÉNŽåáËX-¼)3îV{=¾ 㜟5��‘?22åEÇ,œa+ÑK"÷U¿ë.¬Öy?R+}Å&Ä;õ”ÞÍÁ”OGœ[æ¸QôeFâÒ»®@j�ú•\Ú^__rŒ® ÉÉ{`k}}˪ÔÀÀÖîúVG¹6)Ÿ.mm-Í'+ŒeWªtZn{}+ñŠWíëIiÞ ¨Ø¹f6ÈE,¾ùÙž‡ûù¤#µ¾SÏHm\r|@sžaR§fgÇò}åª:‹Åun”S�Ç@µAê·ÃDü®³µÔÚðd§«´R�R».¾*R7SoaBǼê9=HQ©©Ë5@¤°–VVâ–¨ïmz|R¼‹×ÃJ�?¤‹A�íCêTâ ¤[Ùß— áÈ]  œtÞHŒø�ZéËš“?€ÅÑfÖrd’š·ûƒ)2ü§º¯‘?£a~wRp@j�ÕR£A©-KÁAåßö1!uJØz¸åÊdR[‡ŽÔ¦€ŒKºy�·• TgÓל/dN¬Ìè8­ÔoU™Dë¸�úÔ�óR¿SÞJ½â8êÊ0é:~ËHèø] œã!¿¤VŒÔyeYÀ5ÑòÛˆð$ZF*—ë÷ýÍ`Æí&¿Ëzi�žýÕH· Ipü�©A P�"õþÄÈ�:Ö[˜œ,LÑÇœ‰>»¹å¦�ÎK-¨À�»§»]]‰íßq?!—¸oh7‰]$’!u‹…ÚßG½Íéñbi¦ÿ(�š<áE¼ó`ŽbºàKÑÍ¡ñb1Ûk±ÑÌ^˜Ä�íã}=l:Çð³xžX·ûЍ¥¯ÏÇpsTèîá‘™+¡\—e€Ž©ßõû}둺–k©Ã†ü®ÒñÛÉl Ùšðd2R{ÓÍq0�Õðd©¡EJ³%n¬âöa óªçx44E#N5žLíµ|óbÞ¡–Gê–¬[ZÉÛK§  ÿdZãŒÓ®ž„ÐW•åò3�Ù&ö‚Âë î„'£ù«RñÌXŽg�]A¨Ù´R"r7žÇ iö—¤¸cR÷ÈFê)ÜÔ—Ea­D¬Î¼HiŽ�šÒ™ÞIÇ&-ýÍ@Ã+ƒû*Ú <õx ýÓ*Ü @j�¤‹Ô‘³»R¤Žñ�©Ùurœ ;½%DcÒWþ=,EfŸy¤Çýe£,Ø)~LjRÉ�š?Ý-Ò`ÁÄU�¨éðúw‘ÚdOïò<�ð9¹Iæžh]f}O˜äÉ;×B±#GŸ#1Ÿ°cƒ†q�œ¾°`Šc³¬¹…YjTé+ѽ)T+µŸ©ß¬“ðd§Þ8˜•ºBÄoLÇ¥aÄ’hµsŸÓk>¤–ÓY™Ýp–[u¯²s¨‘93IwÇÙ¨~Ä|`fµžÙê9yþÍ��ç&œz“h©½–o^ Â;ÔòH=(öÚ‹h¡É±\“QŒäkb&ï±JødkÂåç’“ƒ:o µ‘jnàYæÒ`ù>3›⸠‰RK}ѤèH ãmŒL ÿrv?[3|!å�]⇊= ýËÔçLÀðqû.Rƒ@€Ô  uX¤Žµ²gGŠÔMh¡5oBœÑb,Žq—±–�˜ 3ÖlIgH:R¤Î°§âq}S©Aê)4ÙoƧD¤ÞÃEjÌÀyÏ<4‘Ç»Ø5´§&­&“Œíu8,µ¶›.R£ ¶e_E-Éñ›Ë´ q|hµ¤éi9ÛšWœqA5@êÓ§Cš©�)<Ù©ò¿5y©ßg¥&°Ù7�Na¶-0÷éBS&•gNµ¤&Œ�ö“÷CEf‘¼’ŠgÈjf©$ãp÷`fº�¾qåË©4yÕ²Ét-h™W='�¿(̓éÔUÅ\êuÒ×kùæÅ ¼C-�Ô'ÊD±¹¶FÒM„ÞZ)ó ‘Ú �“æ×àÛaKü<½P² ]¸2ŠÔlÓs”g Ímú´E,š·š)—†Ü“Ūt¹/?RöBõ²¸�cSßç4·w„ŬËö4öä›yö>"·xì]Rƒ@€Ô  uh¤&�–ŽÔv¿Íü'›)³‡š.V3N½ 1gç8‘£s}ìšñ Ò�ÔV‘y±Î©«: ©i¤4eòÌÌŸê�Ö$[êwm¡@Ù8íb3žNÙ,^¢U¤îe‡Ì{­AO3�=¼ëk�ԡ“iòRŸ:UŽß^KM©“ÙþlF7|/bø‘:ƃk—XJaáRb ”�Œ°Gæ-îLVw³²Éq-óªç8ÍqÉ('z-ŽS¤öôZ¾y1ÏIå‘ÿ²ˆ,À‹“Õõ2«w!¿I‹º‡¿vßR3œ­4>k+í±¦Aɹɲ›šzäìOM·vÊÞi;0$s¶iö$D¥ˆ´6ÍÖ"h9 5H R‡GjLr–ñÛŠÏQ;A‰¡i‘>4Zôæx¥J3RûY¬Èc©¹ƒô#u†>ëƘFt¸H�'H­ÌÃB+ii>…šDÊU�Ô+œ^ò^¤žã‡VÈÚÕ&Šé7@džÔïj“½Ugk©+Ä';ÈÔ"~ã¯Ó ±*–.³[?Ö\r-q*Â=²ãÔ×örg73+Æò¤òDf‚#¨}�Ú'¹¯ôH–¥rî"• =½45Õ°ˆß�çê9³YfÁT`ˆõšµG™°§×òÍ‹A¨'‰jMÜ/<ãFŸ&êuƒAe²laÆ›Ã)òm‘þ¼ ;±­A '@j�¤�Ô$LGj;ßGmD ©gRÓIJ­WTsÍ1"uœôßÏ`åAú‘ºÉõ´« © d!¥2d-5º’ï‘)š=ªO¨HÝï¾P‘Zê'ùMM Ê>èè‘:8<ÙéòVêº OÖñ›@u§Qö2Áf13£LÛ¦ç°DÃf;Û‰Øå<[<çØšÊ¬×Q'0´Úk…æù ¼C-#[6ZÇì±1çÌTŠÄ²äç'ÖâK-Rƒ@ @jèuDj£-d(R÷/`8¼:ˆÔ%„²D(»x”Çu¥ãh…s¨2H?ROó1²±ÃêßEê�°£Îƒ96^d^«‹²e܇Ô)^¬AjÕ§•!õ õñ#µ.<™©OÕ×Zj½ã÷éê“5’\¤>j]e‰Ÿ4o&Ðd‘*K‰°à  5¤�^s¤ŽPáAê'l:„Ôø²Ê#þ;®+A9s�E¤@jº¢±—Ðh�XIyˆý»H½H¢}ó` Ž“PÞ¶êøíAj–‹§›fßQ�zœºFâ©k…Ô^K]C#uh+5 uµÂ_æ€9‹çK-s„¥'ÀH ¤�@€Ô  5CÀÌ$õa6yÄÖ\R7£ Ô™Ú<îðdÄDz›ÚwÕA2¤æ¸:NhTÄõŠÚ‡Ö¿ƒÔ­"&²46õµ® .bæÜš�Ñ 5 ifæh µ9Ö–[AWIs±«ÄH]¤ëø­M¢UoñÉ4y©©«VM”¯ÐŠŠ•H �©A @jfU�fË‚¯ ‹–Ë:~÷ 4jÖâ‘ú;ꑚä«e¶ae�ž¬�¡ä ºCr–F®4cl RGƆ'Ñ$™ e 4C¶=IHþ*ÎÒÆÍ¤Fæa^B jc¿wŽÙuãCô9@êZ#õÛÕ­¥®éRêòHývØðd�£ÖîcË×ïî.¿ðº©"‚©A  5H-•Ç)R7#ÔruZ©i쯆Ãî#ý;®-Æ‹Ú Ã3H†Ô­øX_ •(�’pa¥>DÁúð�Zäb9säyA¨x!ËrÝšWq\ž‹ë¬Ôx�ˆ=#y}œœÕdO¤®R›©+Dü>U¯Žßo…M¢�@€Ô  5:R§�¨ØñÄ{¥ˆyµiЦtÖ!µÑ41‰¡qÚ:Ò¿ãúòœ0;˃¼ÊÀ³)‡�tt]  äÉÞ\úðúOsžÎN ³•<)ò»4E_Nćqß-sq‰��>žl Ÿs•e$¢Y‹ââ˜1†››œ3¤Ø1"õ¿…�ø]Ç‹©_+5¤�©A P=!µŽ²Óp9–‰õßñƒ 2"'á1"éØQöï�eN"�Úúä …\Ï2Mµ¹<ÂÕ©ß Dê:ÎK VjH Rƒ@ ºBêzø;þz÷ªR¿2‰V-‘:t­ä¥�@ @j�‚o 5 5èàVjŸã÷[!‘ú˜ :tt2@jH Rƒ@ @j@jÐñZ©Ãä¥>US+uy3u¹Z°–Rƒ@€Ô ��t„VêwB um×R4â÷Û€Ô ¨A‘:‘¨í£UòFž/A€Ô  5 5 5è°¬Ô�•D ¬Ô ¨¡‘úöó§OžÜ}•"_~ù{¾¹tçÓ�ï´UûdõôÉÓŽ€c�¿ü²£r þñ�·Ô’�;K¦ÿéËÿHø7A @j��ÔˆHýNˆ$Z:Çï7j™EëÍ0‹©©A P#"õê³'X÷^ÅÆü§ý¿^§[wþ|†è«?T‡­wñÖô‡~³¿ÿyˆþøÅÒî�¿‘�|õõ7l¿ÛßÈ/m‚@€Ô  5 5èÄZ©ë+ÞwÈðd€Ô £�yÌû ×©÷îÝãÔ›À8ûìù½Û¯Ðšƒ©Ÿú[U†ê�ðVõýrÿ¯!ŒÔ_|ñG×u<ù�3ޝ)h'ÿS0¿¼ Rƒ@€Ô€Ô “j¥nXÇoˆø zÅ»/{¾2s%T¼Úlûvïx©�ŸŽ;¼Ý4\(]hÔV¼è*ßø³¿X(Öâ¯R­�º3,'Õe¼yãÕøc/åóO1ÃþùoŸþ…Xˆ¿®ÆN�¸÷ôž¾þÿ gT¾õÅ߸{¡ê¿PKõŸ¸­û±kö~ ϲ @j¨î‘:½¦ª©ë6w—dnu6�Õ©A P R¿d¤®—ˆßot-u��ºiª«Ž‘ú*B-3#Ç='=Ef9-¥¬½u¨4þ¯T¤Gˆ¸DŠh!r ûV •lRÞË{¡a2céZ0uâ™mø_§9rƒØ��ÔÆòrG4ycíî2…æÛkwW—eƒ/)`M]_Nc¤N//ßH,/¿xòäùòòòäÀòêÝ»«Â <¹¼l’ÓîÞMòÍ›âà�Õ»«Î‚äëûÜïóë_xÙ_0]W.îkm9átŇš$MßpœÀ¿Ýßÿwr1í>)kµ•¥ÔIÌówøö§gÎ|E7Ò.›§Cb:�Rƒ@u�Ôå¿ß¬�ß·©OÕ/RO 7ÌNWyæ1 ule�Ÿbg1Qg¯ �;ˆäµÆÖ£0¥^2g¤Î ”‹‘�6ð£ÞïAh…õ\böÚ h’}ð‹õë*påjø(q„F‹5p¨8T¤Æl¼vó) ÞýÁ=ÆûÉcuL<½‹Ñóñ®Ç«bëÉGÑè*/|“qó“'ß%Ÿ“‚ÝüŒ¶ð¢#zý9kг÷'ûûÿÅ8úë¯%”-�Ô·E_×…Ñœße£|ÆÃ'¿dNÚ?|ïÓy¹5u)õ‡~˜pÇÁ¬Ô‰¿ïïÇ¢ÞM�¤�©ƒ#~W OvlñÉÞµ–Úçø]£ˆß©«×1 u¦ËS-ŒÎ½Ô€�ЄÖÚ[—H]l2 ©ûȆYBãǰŸB¨I8”˜çC‰íã#‹º ÜÀ~ŒÔÓefP)ÖèH}ï)ˇe8ÐÌóM_ê¼H õ]g›-áè{O¤‡wˆ¶ž2CõŸ4ÄþPÁñÛíë»›.R'^8ÅÏ©Ñ9²¿ÿ÷D¤þð‹/>ÔöãÎÿsÿ“¨o¤�©A †µR×/Q‡MK­ ù] ©­ˆWö2 ªšòQõÄΞ´bíÍdb�Hmfì¸Ø®iG‘rˆŠ¦m›º‹t.ËFÈëõm¥m["|7¢ãZñàË�Ù™àþ øq›B(¥±ÆÖ¥Rä’T¤îE¨ÝàïrǰAhœN3ÙàÖgÛ�6|NŽ‘Ú( ¹sZ©1 ?¾w÷f’0óã{k/¾Ãÿ�ê)xzou�üû"zs� íݵµôõ5Rôxmmíú*M¦µv÷11ßdHMÎzq÷^‚n>{ñÑ]ÚŽ³õ‚öûW¾”ZRÛŸyX°ñ¾V‰éüÙ © À?_]¦£¤9µþ÷Ñîüá‡÷0Fÿ@…7Þûá‡v¹=e)µ¤oΜùj‰m~îúþb~ƒ©A @jèõ³Rãq}dÑò›©Ã"µµBbu•.1VŒÑ=4GO‰#´˜"Ñ•K# ›ÓYŠTmÁ‡Zš)£’9CN�#íäØá>‚�EF±hDæ!Ãß®è´DOUHÙߥ¯â8º* >Ëzš =e{”‹”/kˆ¯`rÛÙI\PhƒéûæÕDÎ*døÆ®‘ÅÐWgE“êåÇÇ'©�TÛ?ë–s|B3klýJEêþ‘’«F±£ß7FÉg™$ò8Eét *Ž˜F¾Lëy+œ#5õ§ˆµ ¹†Gjf8^Öibœ~šdFaƒ,ùfØ]x²Æï§´'ó;é†kä&›Ïn 6F(�¸„?%ÇûûûÞDÏÁ(;<ÒÄSFÒ¸ág´wŽÔOÅ(Ÿó(äŸóXâÄ��Išm½üþûvµ½�/¾øï¤§hiéΧ$ð¸pEÿdÿOþM�¤�ÖJ]©k�LÇÔºµÔ¢®€ÔyN˜,“³aV¿™I¶¿HA™[ž³¨%æVͳóZæx"£YÓÊ6 í,Ð9摹˜ë³§]SäDÊ¥½ÆgµK]Å ¨ j\•{*f´q3.¹¾ßMH�ÖËOêdxQiÙ{ù„¤KAý3[4ç=i­±�‚ÔgÁrµõ¾aŒµðW4<®[ä2ÞY AÛù�â­À}ŒÔÍEè«…cϵvÈHýŒaòca@Ž.?£fj̪�ÍÞÕ!õ*‡fnC¾É8šÇ¿áÀõª³EòY“6¯ïïÿÝ3’1Ê~ZÁHÍycú–àH�äæq<¼ÕUzü[×§¼R«K©©HŠl’KKuôöþþ—þM�¤�NR¿YÁó»†fê7ß i¥.ž “^a:32ÃRõàGøÂb¦ãbÁ¤t‰Z3™)ü�I0ɸ›òÎÕ±ÌØUƦ0çR‘TÝ�¤ ¨”NGR“¤U£©ÌPŽ­zõ´‹[ºÐš¹ÌòZ)HíëÒWуÔqÜÅJO¾ª+q…LÜË2Ó­x�é´Ó‹YB C¶Ý[¢ŒK—I÷“×-MéÁ,#í<5²gZ1WçLCwùÙéžž€þ‰Z�¿)\Ycím¤nAøÖu8ê}Ãêïão/Ò÷Fù»Ž16m¾ ̾;Óð?MV‰º^Ì"4}Ü]2R?wX„í~LØäþßôàíÛ7tHý\œÍNºÇšYv‘š¥‡îp ¼—Èþþ_=„ûÕ™3_«Vã¥[r„n©¯äíÛ·“’•úyB>í¿ÜUÏå�Z³”š#õןŠöâî0㾃àÁ�¤�©ßñ»ÎÖRkÓ�®ÒJ�²çF½Ùc$ˆ!ï=8)l×6Ý¥nØCd/ΨÛ0û(âsd=k'_Î*ÖR3¤Îs›p¦ˆŠ–¯Ýáìi)ÖBéXAj¥KmERsp]”×'{.Ë»–ÚÎfG¸Q´•V¦æ™Û,Ò+ÂCm¡Àv‘"¶æò¹¸¦a›ÎÒ*Ö%DGî·Æ6R÷‰'Þø=G¿Oüº‹£ù‚¸kÒ-åf¦Æ[ø=ç«@té$©Kc²¾ÚàHíZ’—M&j°^åeW~¤~,ÎfE�)G?K:HÍ7nSß1¤ö¥Ž^ÂDýç/óþ·ÄÔO¥¾œáD¹ëúÝew¨ÿ±¿?©ÿðÅKžÉ¸óÍ7ùÛŸ1Tÿ™¹¾¿¿Ÿðm‚@€Ô  5Ô°Vê·ªL¢u\H}êÀy©ß)o¥n¡�Ì•æY²Ç\gc%²|Óåñh?B©5Çàµ�ž8+Z°)Söp²Íù‘º (iš‚Ž·]×Xky£ŽÉ]j+z�ºÀ£iã�qù"åËÒ…'#ŠÓdL"›±Uä-_¥}ç…‘Ù¤mø/ßæÝjú7x;ˆ¼ˆQ�ñv�5¶A�ú²V{Š~G½?†P�¸ÞM ¨D&°�¿ ‰gÙo…c¤&ﹺ{±ð “nl¤f¹§Öž(zL <ñ¸üHý�Æ`Hý]ÔAj¾éGjïÊdëÏ.Ç ýñ‹/¾¸åîÊ}ÉHÝÁB‘?{¾Ê»ørÿve¤nÃÀþ¾nF’ºör²ä›O¤´ Rƒ@€Ô Pc!õ»~¿o=R×r-uØ�ßU:~7; zùG’qt…Ò劲蹉qœ‚Ì Bý)¢EjIË ßåK ˆ¤Ž!‘Yצ`êm—„Ÿm% bc^¤–»ÔVT‘÷T £J•¤|JžËÒ!uÄN�0ËrD¬².q(›£—âÆ�¦—æ»ü"µ—zú·Ç¹¨»ûâN¡MÐW>klƒ õ”ã¦Î>ë£Þ¿€Pܱæ÷S÷~7qwoÆýÇ¡‡/SD @ÇþH�ú®©ï†@êg®o8±j? �Ô¿ÛßÿO©å�?»Q¶}ó…’[òCW�:Úq臭Ƌ õo*#µf)µc¬>sæ ó ïÀͯXÚ�©A @j¨a­Ô~¦~³N“�zã`Vê ¿/È™|1qJÂvB—Ct¯“Ç+’'ûi2iÜ}Ú'ºò¨…�xQƒÔ¶ gâýÜmøÚmÍŠ–|H-w©­¨"µ-� E.ˇÔf¾ä‚‹3¸º¨"5O˜5Jú ¸|Oÿ)±9J¦¯Ðí–‘9ºŠÚk�m¤nrâ¬èJߣÞ/:^Ï:‘]®MŽNœ·ûN€‘zŒ¾ƒ!BèŠuB¬Ô«\­®Þ$O+!õSÉr|·+õo”`_m_kˆ::ðÍåÅÎOIlRãöoÞ{ìæÓþÓþþï*#u`Vj¬¯E6/s4wc—6A @j�jx¤>}:¤™ú˜Â“�*ð[“—úípVêñj�³Ua× Ì4X`B…•WCêfÄ»0¡Cj¹KmE©Éh>ªR!,R§IίRßÕñòH½ #uÀå{úÏ\â£G-ûÚåáé¸ÑG]ɽ֨FAêYÄs:¥X¸ó£ÞoA%>󭔘‡Ü`]z x+ÐOü©ñ—h’z<H½J£hKºít R?vÂ{‹@g!‘zYö•ø&ê[•F*÷åAjº·ÆsE‡ OæYJm}ø¡»û—3gþF7".ùG â7�¤�©C…'Óä¥>uª>¿¼–zÅqšåÌêqüV‘z¡L¡1¥*UY¤Ö8~KíbÌ.ÍZ¬I?RK]j+:H] Hmj=d+8~c¶í&Þï± VêŒ0ì_ ¼|3Œ‡®ÉPÑk�­{¤6›RdöcWØÀ­>f.>êý¬@h3KïŒÜ}ŒîúY62oúfãbãÿ0EÜÌÚéc¿ #Aêë^Çjã‰k‚^¾{w™1¬¡ õg®sxò©ˆø© Éæ›$D}§âHIø3~JbíîZƒÔ,Ài;T-²”Z~ƒðñ™3NJVê¿Ð�߸QÔ~ã ¨‚{@j�j¤~Wžì­:[K]!>Ùé@¦®ñ;%VŸšCC¶&<™ŠÔV ­L£¢Ép¦§,R—\¤Ö„'“Úm{YRK]j+ÎñŽcEžì‚ÿ"+„'+ RŒÏEY¤v“]¾|mÿŒŠFG¹¡±›uïµÆÖ=RÏñ)hÂ$kñ‹ˆ¿ 8â}â=?“ŠgÆr,é9ùøKM™ø I¥Õ¤«@|N€‘úšHï«âñ® 8¤&V`ž†:zïùóUZð”µrý;ZËÍ…%�úæçô{ì`H¤&Á¾LNÔ EÔ´¯»N_ORß|ñâ^Ò±Z“á}¶¿ÿX‡Ôq¹5ïRê¥3gÎÜ‘¶Y†l)Šš7 ì©A @j¨‘�:8<ÙéòVêº OÒñ;Žñ$ �'Ñ¢ÑÊœ$Z*Rͨ/Ëø/³H©\®ß�Ôã|)sP-©Ý~–ø™ ¦©¥.µ¯ñÐÛCˆ"µ ߨxnB6÷É—åGê𛫂ã7*vò‰ê ¾|mÿ Å[Г[ê)Â{­±u�Ô%ŽþÖ _!Îîœ#ßOµˆ%éYêQaΉýÉ&m…ÙzGN}¨è¤+âö÷Gê�žðÏ NÇÄêû˜4Cbjc„�&Ÿ=yòYBFêÄÓ'OžÝÆD›¤•£¡‘šÄã žÿ Ál9%ÉréUÑ×]áøM²_S‡ðÄgÜuý×E[AêäÖ|K©ÉrnÆÑw¾Â›,Ÿ×·ûûßòãÒ&H Rƒ@�…Ôºðd:¤>U_k©õŽß§« OF�´o:�°Y üŠ M™Tž£©3„[Xö¨)R5�é�¤ö3/Rãö.§Ò©;1�M f†r 8}Žß-‹‘Lׂ©Ý.µS—Sñ YfM�:�{jL§®*Øêei¿çã©l¥ðd(7DÛÈŃ/_ß?U/>cÐ4ûKÂÞíµÎÖ­.ÒpjÆôB‰yªÇš'ɇ2.,ÁG½Ÿž£áã Í‚0» ä(�Ûú 'c%uF~1€ïÊË'©£Ïi¤ïÏž“øÙ/ø1RðØ üõ˜&«ºë"utùÉ ýü9ùçÙ�*�êç´àÓ3$´£2KªMÒÉw/ž÷„>wü&ƒzúÙ ûMÇt] Óí õ{xëåy·1_Vê%š�úoßü…üûÇí/Ý×Ò&H Rƒ@ ‡Ô^K]C#uh+uY¤&ðËL‚6£'É@èGj*g©¶Ä…”áGjë:'�š˜§™z »ÝÜä8®Ej©K]E‹›,K÷Ù=�Ç(”힤Îðxßs呺å«VÌ”¹ü€þé� aKí6´Öغ—é\R<ÕÔ/ßUG½oÄgme>c™AuÒ¼@u‰Ô‰çN -j­Ž&^ˆýgw©oušç×r‘:zû™¨ót9ZR$ü¨ÿrFQ9{õÍïœ_×£Rßxìeô?œÄÔ.RÇ¿'Lí4•øâ‹/ÚÔÖ­¯�Aˆ Ù‰ýý¿wø6A @j�j0¤ëø­M¢UoñÉ4y©Ë#µµBˆ²t9 „”/çè)q÷)" «d1ôŠ š©·ê°Z�ç#YŠÔS =½4OU—©¥.uc4ÖDf‚Ûzgi¢­Ò�J`òeû_¿|4MN™œb±ÅœÁ•¸‘ð�Ï�¡9ÖKp¹0Xîòúg3ÍŒ¯¥!#À �p¤Ž&×�>¾- ViÁÓÇi^°üâCê»Nøí÷(Tw�/»vSo¹›‰gR?}òä:-ú;GÔ*�:z�õõøm #õ3:Ê»OÙ(EtµÏ„<Úæ uôüK©—¾øâÞÖß|ýÂW±xɬ»~z–Rƒ©A @jè$ õÛÕ­¥®éRêòHýv¸ðdõ:툲—  ÉJÛé`Ó Ù®33v$0·nÄŽ‡|Ò×ULÛÊ€M[S©üeÅ2™ 6Nj‡Æ¯|ùÚþÙvSS�YÎ �8¤ö¨cyùFÂS ´”èèHxQôúòòõDµ=ýÉMuU…H_𮦢¦c/ïU°”ZÕgnÚ¬Ï ƒ�zM�š-B,‰¼´e�ú`JºR`Hm#t™¬¤œ¤ér�„”?è5DjÐ ´Rû¿ß ‰ÔÇÕ¡£“Rƒ@ @jþdôí·¿;ª¶?ùöÛr)¯n}úé|Å6>ÿö3Í&H Õ/R›×eBÓVƒäFxRψœÜŸ·>yœ•‘:Â"òZiÏL˜‘ºìÅ�êÚJ&/õ©šZ©Ë›©ËåЂµÔ èµDj�&RÇ/Ò ª�‚ mš$6KfÇZéûæÕDÓ¾òpû©”ò µ5‰&¯²l¶s<[LŽì5ÅROÑ~ÆÑUv�gŒ5‡É)Wº‚üÆ{‹M†Á‘z8wÕál2ÌE7ï«‚Ô£F%s®ˆG?ht’EÙ¥æHMÚZÌÑL¹v–$Œ-4é¦Ï¤×h‹ ™eëÆ+]¨®­Ôï„@êÚ®¥>hÄï·©A  5H �^©cYØ«4Ç�:SdûEò¨Ah†í^êåÕ:åJÌ&í"µQ$¤løÑ\š›®Yè0†Ô£hÿ÷óÙ&Kø8"NfŠ ‡#µ£½X=òå—¿÷þéËÿ¨2d_Û��?ýpéUÆ�(×ãòÏ?ÿ#\3·þyÕSôóÏ?C“€Ôt ‹™‹„ ã9„VzzVº§ ‰r#é~‚ž-MéÁ,ÉN¼?šÊ 1«­„Ô6†Xê˜}¡5MšìÆeé\yÐî%m"5îo4#í—‹îAê4_K=ŒÆ™z*æEjÝèóïm›üƒff3CMÆÂ 5šœj��˜%´0dÓËi÷OŸ©Ã]¨^‘ú�I´tŽßoÔ2‹Ö›aSRƒ@ @jèuCêïž<¹ñªcxþ”ëñó»U5öäÉO¬�»OžÜ ª�üÓþ_ý ï~·¿ÿûª€ú/_�!úú P½üÏŸúéŸÿXNÿߟ~Z ×ÒêO?yáû§Ÿ~¤>H�F¨DÌ»ÖƄÌ’�E„š)HRk5fDJ©f‘ZZó|Ut¦ˆŠ–„Ô�„ZqÙ9b<޵Pâ�á¹®fË!uõ‘�øxv(4RÇ&x0´9$Œæs–©FOÓ[OðúÍbéu¤ž¤�ÙÙ,MÏÕE/Õ;}Z¤wq †¶R×W¼ï�áÉ©A  5H}K÷I�—� ©õðœüOhjàë3\_Ý9ȵ&ÿñ×Z�¾yôgLX ‹¡éÆ8ÉKdÇ*r¾Jé° xx¡ EêñáááüÄ$BW¥õÂÃ4lXŸ¨OM¡˜^z ¡‘0H­ÄóµâŸ¾¤sq F¶R7¬ã7Dü�@€Ô  õ�úÙ³gœ©Ÿ­…>±*¤N|¹ÿWnþ¦šÌò&ê?|ó7ÕV©É5BÓÿúùï?€ÔðÍÓkŠͦT‹™0†P!EU"1¿""Hw‰8tSƒpŽVêfçØÔ¦Ý�åycff¶u¬¡�L^¹¿ RcÜnNU Š­ õ BÌa;‡ú虑[[-!µfô©Y¶E„èZï Bca�Ú W±S#ÌŒï™>=R‡»8P½#u݆'«ÀÔe“h�•Rƒ@€ÔÕ#5]ü�¹F Ö¡™º*¤þýþþ·ZÔþëþ~$l�$}ç«3gþœ¬úR¯sóôÿÄÿ H ß<½.8ѲgÚHR„€ä‡Ò‹.”âJ‹œœ)/cVîËf³9j·%jÍŠ&b/yåt¤6i˜q”m2Ã"õ4†^9#a�1”•�Z3zžL ug5H=į9σš¤öLŸ©Ã]¨.‘Z——:¤•ú�ã‚jÚU+õ[šˆß`¥�@€Ô ÃPr> “ðú!5ÑÚ³'Ož…m±*¤þ�ýýßj|¾¿ÿyÈÛ0HÊ6?Æp}«êKÅü?ôÞNü oRÃ7/R“eÇ*T*T�Ô)†Ì% �Í4Úwa¢ ¤6¬Ô¥rZÁ ‡Ô#¸‡ˆ†{WŽ©Ó4#XßÕñðHîâ@õŠÔï©ë%â÷]K H : ™Ç¼S H]�–<è—XÚ^ßšWŠæ·pI%@$ç-µyžÞ½�kk… rV‹¬¾v4E…¯m{KiÚÂ%¾«õMS¥¹´žÛ0¨o¤6Wï®-'d¤î¸½vwU,„6–—1ìÞX»{“~�‰›kw—¥�ô\w-�Ð u4MÖS‹�åÕ»wW`ßXvš¸Î6)R'—?ºûѲ©•ñàSö™ß·ÙÞ..Ób›éýýÿyÕK˜£ø ‹7?¬ØÑÞÞÎïçÞt.ýŸ?ýćô�Ÿ~ú—úõ^þßÛdÒ$¤ÆE«ÿW\tâúuñþo^w�úƒåÛ·�‰‘�úúòêíeø5&R{<—M Š~�T TãøM r˜EÔÆm”fyÜ/Ùñ»U‹Ô‘ Ú°2Í-Nå H�Â}¤Åyé´é wô¨‘OX7 õ+ïøÝ/.9öâ@õŽÔå¿ß¬�ß·©ORƒŽ^ñî‹Ãž¯Ì\ ¯öÛ¾Ý;^*ä§�ŠfÓp¡t¡yP[að¢«|ÃãtW¡•Æ{�ý+|ŒH½õ`ooýÀõ­=Uì™zkóá¹sçÎîì:O­‰�GçˆvÜXÀK;¬dKlÊ qøN장µ6\¦ÝÚ|àiÜSkCÒéË[@ŸÛ6ÎyÇÔ¶±CÆù`s+¨È׸¦7‰Ö �ÁÝÏŒÕ4k~,¼Ä+«I´®ñXCˆ u¦P�IJ!�:Ó‚J \e—`Ä ,àØ#u ÍÆ¿½ÓÇ�ÚšdqÓÍ™™�ªw+uýuØ´Ôš�ßµDêBÕ™Ú¯±„‡XѯN+á`þ$Õôº@=jd-^-¢ÒøH i¶>%@§ µ=‰ÿŒt•Ä{ΣÞoÆýÏt5gyÂD#Ò‚Paj(_äé<RBÅFGêY�4:4J— ŸL¤æÀ¸{àúÖ#W©7©UuƒZWR §ílìÞ'U¶ÐRl\ß8ë”Dñ¦ÛÏ$9agw—žN‡“¤ñG¼ñ=öØî­µ¡Žiƒƒ¨SÆ`uþ,ÓÆ} )d?ØdféM}‘¯ñ€Þö6ש5� ›Â2îì¡û¶@3MšQú*%6vva1uý"u‚0ñÓ{k/ž>!@‹‘:Iö1.!¬½Ì�Ü]{�+<}†·Vï‘C„ �éÙQä~œô!5Ù}A€‘pòóµ»�I7ƒ�š×!ÿ^w‘Ú7žhô¯b)õy̸qüï�ø_fœþ\�ù=ðG�´K¦?=sæ«2à6ìäj_ ‚W§� ´´dœ"ðÿÜ^e„¼Æ™û§ýcù„¬ÿ™ @jÂÌ«ÿw�X¸ÿ!!õ21n¯ý/mîà«ÔxHM¼µ M™þ9Ę0MžUÓ©«"/µJÉCçÔ`f(ÇøÛAj‚�‚•-‹‘L×CjÌÝhjÖ¾VR�?\IÅ3dÙ5Fj ·Ô•¶Ò—œ `å�šŒqjŒÉf–‡R«i¦ð:�ì}ÔŽßsƒñT–…'óNCj’Ö«;!Â3òâ@'ÌJMŒÇõ‘EËo¦®-R7MuÕ1Rã/oËÌHM‘ÚºÄÍ�3¦Þ4[JãðJAEêqö+)¢…È1ì[%T¢?ö½œ±ñƒa2IéZ0uÜôK ýËDþØ^¢·GQv†:AH½N ðlx¤._áƒ3\ooÎ䆰Únn^ < �±IÌ¿Ô¹Û lM)†NO‹„D7Þǵ×ön+æÚ�€ZîÓùëx×oÚÝóy12&6L2(z‚¦È߸·À$�Øä"ïÎ.9ãOû¾gšü£ÔTÕ5RßgJǩׄ5ø:æä§I†ÔÏŒŸ<'_‡ågŒƒï:æêÜíAê»t1uÓðS: ókS�ÔO©“øG¤©}ã‰&ö÷÷Yúé$³Næ=ïø„ÿIFê/<Ò!µõÕ™3ß”›¤8&ö£Ñd·oGÿüI B–ÀLüswïfGd³Y!ô½ˆÔ·…Íû§ëRÓæ>àîå?-Ã]ÞxHãѹKs,·”-¼ÉÆc�PJ1™Šš£¤&Ï3 £››§HMߦ)y©­9Þ-[K="\زñÊH�—|÷Èc©5Œ”'Î#Eê �÷=ÇžÐ<ÓÇ‘ºg’Ï!�™pªw+uY¤®et2SëÖRkˆº&H=Á~EŒL~ú¨˜õàH[@Ùƒ‚ë!!u ÿ¸”òMÝWðÏŒÖ4['ê%P§d6$?¦¹÷Xj>†ý'ÍD õ‘. ISü¼÷ë*på隥Öâ¹#é5^>�HMœŠ÷¶6C#uùú¾ÞO:†XB½‰Gê¤\’þÅÔ(ø<µE´¼© ޽›çœè\ ôµ¼”OxQ·\ü6øæ]ƒyâ!XM‘¿qoÁ®SN<Òï³QŸ]r'`;ª�&Í(5•@õŒÔɧܺŒÏxÊ�š–98/SZ~ê,”þŽm=g¸ëžMˆü±©1?¥,þŒô*3Sk‘úÆÏXôoŽÔ¾ñ�èdsæÏå—)˜î næþ ]Ë?{V9/»ä»Ê‘ú_Ž}9ñOJÐz¤æ\~ýgà ©qÕŸùûƒ»A�ÅAu�ÔF|†ÐÞåÎnž®y–Bbiˆ<¸ÄÅ¢àb±\.ñÇ’šêÊ�0¡pcS,‡P�a�g?Tèéå®u#4HvSœQé{‹Ñ\T™ æ �É Í­”}˜½È†èEjâœ[eg ¤ý0�ÒÝDÒ„±§´‘ŠHí´e¤ÉüLN‰@nêô™ÜË�¨‹]³ìeC¨‹5R¿YÁó»†fê7ß i¥~·†H}„Ìzp¤ÎÈèkƒÔ‹<��YàËc¼¦ÚzAêb“šÙ�¾^íFÔñcØO9 ‰¯²Ÿõ‚ÈÁ�b©&|ø¯x£©ñµÉŒäp¬÷Åñ 5¦´ûQ="o=x°^M}(“\[+.:ËÁT,ªæDyßåg ’¸+¸Ç »äpwt€Ÿ·ãVàG5µ|väMgBx;ï‹ann®sÊnsu__TÑHM:ÛP¯í‘ti÷k¦É?JM¥äÒÒ<2w„©M[÷Ûq•Å„p"zM³õ¢TÆð"u/BíórǰAhÜânDãü}«mH¾ 'ÄHmË—ïé9Ö?/Ç…ÔëÉh"okJËÕw sk{;áb ÁÇ¥�FY-b·Þ’œ› †¯»>Hß‘p~ƒ!µ¨ÔÆ—%kjùìÈø´÷ÕÑ>ò»‚6O¸,¼©/ªh¤ŽnîìHü€�tKªE›ôO“”šJä­üâ‹ÿV™:F{yéoù®cDú—pòÆúÊÃ…Å"èèºk-Rÿ,Û¹“©ÿ‰›¸ÎDÊ;à6oD¤>i:j¤½žVê·ªL¢u\H}êÀy©ß©d¥¶VˆÿGé#ÊÝCsî·±H�1J#Œú8ìMSÏŒØ ÉÄÞÒLIp•Ìrêi'ÇüKúˆÃ sŒ±/ЈÌC†¿]Ñi‰žª�²¿K_Åq‘N€ûÂ6õ®Éª±¶åËâÞ/CAs ÖÓ�žR‡\ý\ï�—IKÍ©Ódå}4Tt\”'(\{M³u%©gøGJ£LÄŽ~ß%œe’ÈãôG?Ý‚Š#¦‘ÎÐÞ 'ÄH=†ÐTÍ:?¤^Ÿç©ËÕ—Ü�³¶ÇðÌ9˜ ªˆ×�ä¦åmæ~ÝÖ&[’7£ œ®ÝIº.Ô }-Ñ™cG~xn�pôÀû>?¢ËHçÝî\ò%æá]}‘¿ñ ÃÅKÅõ]3M¾Qj*R×5R¯I‰£©×ž(zÌ’hé‘Z>›¤àZ XKý�T¸ŒÔޱ—¹•3¤ö�G]/MÖQ?í¾{ÂH]ÕÍ7˜¨ÿà)û£Ñõ©Ûý§ÿì[ß,—üƒ"õíŸ~úwõ°©ÿG¶|'Rÿü“¢p›R×Rw_»V]à#óÚµk%@j�©ßõû}둺–k©Ã†ü®Úñ[¬±`žœ½³úÍð�‹”sâÅTKÌ­šgçµðÐ ÄØÊƒäDXOdO»¦È‰”K{�Ïj—ºŠDÚº,C_ÑS1£½Èˆ›q©+hÔÁz:àÃSëà«g»)~éS ©/ñÝ “·å.�ÍÑ8^Ól#uÁyÐEíÀG½�Ù²…¿¢áñ<"ä= �ÙÍïo6è7R“w?c'©+Æè �Ôåê·�õ実1ó>J0®tÀ‘³*>´5¿‰¹ôÑý-å€ Ð$ô×&%÷­³D5µ$ÊOrjßI¬“cv\›oÛÍp½1ïðíº�,~(ò6XÀÖ_ï*`®K,-¦É?JM%@êºFê»2?#H}· ¤VÎ~LÍ̤~Në=“pyUØ­ýHmH–ì©ýã‰þnÿ?UØuŒÔÑŒÔÕXr?ÅDýoío0R{–+´}ï®×–¿1~ñäåM`zMÅebu@êxuÀ��ºþ�ºê48iz 5(ØJígê7ë$<Ù©7f¥®ñ{¡Âtfd†Ú”I:¢Âb¦#fÁ¤è‹Z3™)DÓÊõrH‰Ðoæ�«c™±«ŒM ”Î¥"©>ºIP)�ޤ&ùFSNþO»¸¥ ­é‘Ëì ­ µ¯K_EñÆq+==øª®HŽÜÊe™éVŸ?mÌ�g°Z¤öÔ!WßmÛ”Ìgf3˜…&c©ñ¤ôg È·¨ÚYl0,÷™fë©[H|Jªê:pÔû†ÕßÇ_Þ¤9î�ò7 cl¦|˜ƒÃLƒÿ05Ыî�ºRŒÞÃAj(Ûæç—ÖïûS(g|~(£7½n(Ù�£2¥/ñõØ[˜Rnîn¸yµtµ<”߆ëŠüÒ->ÜÍ­=^t–?îÓ¤Û÷7vIʪGÛAE¯tï�·aVö¬¥v�Z�&ÿ(5•©ëÝJýÔ¡QÇJ½ÊõÑêêÍ Vjçì$ææÛ^¤îxF]¸ŸJ…w`¥VÇý�‚Ì¢َ‘ºŠLSëˆ::ðÍ?ôQÿò´H�¨d¥þ¿lm4›¦Ÿ‘úŸAVêµeW°–�º”î&j­ÎJMÏi†UDêÓ§Cš©�)<Ù©ò¿5y©ßg¥Žð¬ëĨ—"{ŒD‡iX{¼;)l×6ÝmæÖ3›8oê6Ì>Š€¸Æ±ÄvòõŸb-5CjO–{O»ÃÙ9š¾…«‚ÔJ—ÚŠâ桪å%ÉžËò®¥VçÀ;X-R{êäyÚà > †ø"ßxÉ[jT¤PÈ0“¶ß4[·HÝ'&„xã÷ý>™«âÄh¾ îšt B¹™©ñ>Û¾ D—ÞHMnµTÍ:?L¤®£÷P�Ú”» 7=6j›z‡ïÊá«ù"åMzÊššö���Ü"¡sbS€ð6}t××âƒàNâóô„G;(­¼OÒcØ=qMCMG¦Hm<¨€ÙÌ×ù”=’"~;ó§N“”šJ€Ôu�Ôd¥² ´›b-õ3•Û‚‘ú¶töuÝZê{N̲{RkÏ•jO¤v2QyÖR{Æ]–B�‘4ZßKé¢#jÄï¶=RÝ)î`¢þ[綠ðÜ×ÊOD ¹ÿ”ÖRÿÓYK-juP#¶„ÔË•×R¯Â­ H �\¤žL“—úÔ©úpü>ðZêV„Ø‹)s¥y–챇øX‰ävŠ n0d šeœœ%ø×Ê#U“ ›BeÏœ© ‚’¦)èxÛuí³–7ê˜Ü¥¶¢‡x hB˜�Çå‹”/Ë‹Ôêx«EjO «‹w”b,ˆlOý¢G¸Æ$Y·b·0oŸi¶~‘ú²c`Ÿ¢sqÔûch\ʦTÂû±>þ>#žeoH¼Nˆ‘šä«¸v�º¢©=@É1pgWy>Nn [«êk—…Ò&p»iE£ï/í0m“ùX�sÛ®°-sÈÔÖòP>1^ï‘Ðjd`ê—¯·áj$^Ø#ƒ¥û¢í‡ë|䚢°FjÒ+›š—z o&ÖÏi�šO“”šJ€Ôu�Ôן¸æâ»©¯Ëæâ H-ŸÍÑWAêeî©ý™ë N²vÝ£vhÞ&ïM�ú…¸¼�HíOÔ�,Ñ$½•)¹~ÿF]VÉçåÖW˜¨ß1MdÁö�ïiã“ù ÿ..'XÄïÉa›áõu W݈ß×ÕœˆßwáÖ¤�N(R¿« OöV�­¥®Ÿìt SWˆøÝì¬áå{IÆÑо+PÙ3~†»F�¥ûSD‹4÷\^¸+_b@¤ uÌY£aS#²·]={¶•,ˆ�y‘ZîR[Q%^ÜS�Ž*U’ò)y.Ë‹Ôêx«Cjo�[ë,½¾m·h×± ïlnìÃ4K±¥)ò6P�Çìÿ€;ÐnQ³:ôÞ}×ñ[�&ÿ(5•©ë© ?e‹�IÖgž—ú1'Ç{ÏŸ¯–CjzöŒÍŸ²DY2RßþŽçš¾ùDn‚²’ŽK 5?“¤¸&tîæ¥VÇCC�ñÜ]$wœ¥�fJè² H½Dˆ:”'5¡ižÛk¥^¾î)!Ð|›½>XãɦÿùÓOÿbýtüL 9á4¡n�ÔÿL8 (y©…#ùõÿùŸ»I¸Í©A “…ÔÁáÉN—·R×mx²�ŽßäL¾˜8%a;!Á!º×É㈠ýMS/æq)s|žèb'^Ô µ-È™$uï6|í¶fEK>¤–»ÔVT‰×–FåúZ{.Ë‹Ôêx«Cjoqõ©;¤ÎóF[H \�]ß ÛŸ¥6W¯i¶Ž‘ºÉYâ[ 1Ð�z¿(B®“iu]°æè\y+°±á�Ô†9É«Ñ+:�y©µˆ¼}ΣÝHíJò¼½§ï:‹¤ÕÈÜ|-õÖº“0Чšö¯’¦vî]Úäü¾:`-µLùÆúú’ÔÛ&£û éŠh®¯Gâ@BÖi_!ø ¢ÆCLÈ–oV÷¶v<áÉœiò�RS �º¾‘š,U~NpôÆÓ' ©?"%äÎNpü-ƒÔ«âlã17X ¤Nv¬>' R k·ýì6¾’«Ün½*zõ™„ÔÏ–“¼Û{Q©}ã‰F¿ÜßÿÒ—Ôç›üÃ~»¿ÿ­L¼·<’¿—þ|æÌסˆš$¿Æ_ Ûô›,{þ‡²IŒnz!“)R,þÒÓÿäëçýÁÿüä"õOk¤èúÏ<äCêÄ¿xsÑëÿƒ5 5tÂ�ZžL‡Ô§êk-µÞñûtuáÉÆ«AjÌV}-/0Ó`� V^ ©›iï„©å.µUâíAbX¨T‹ÔãÇ„Ô+—¸'ÅGòs+)â>â7ÍÖ1RÏ"ê=O­¨ùcØoA%/½•óu‹àÌMnoú‘6¾‘ššÚ‡…ïDO`^êCCj?PºÆY§œX^7¤XkïøL°öü±¼ç¥Û¸Y; â·–ò±>¦ü¼ëÙ#NÖmÒ`´E!�ÔÄÒ~V2Ñ3ò½Í’™{«Ì4É£ÔT¤®o¤N~öø†Þ§ ©£…öü)÷Å.ƒÔ¼î Ò+ æ§XÏX€nnU¥ð§ÏŸ“ž‘>ŒïÈy÷>#Õ¤&cxþ˜VM¸HíåæÏ·or¿G×oLÛ³á®|õ™3ú[pÍŽ—ÌðZê©C[©Ë!õŠã4Ë™Õãø­"õ B™8ÃÅf•|Ë"µÆñ[jSii–õò#µÔ¥¶¢C¼B¼¦•,è²¼H­ÎA ãw¡œãwR+ŽßzMQsº×4[�Hm6¥ÈìÇ®°±Z}Ì\|ÔûY�Ðf–N+Fî>Fwý4O›¯}³rñü2Ÿ v£Z£þ ñ'©óTÄ›mµUFê |•i™ÐîfR²&‹á'ý@e–Üû’]˜ÅÇÿÝKJVï�¨®}l?§§|‚¦gÏ˶mü°½'™�9ÔkŠ´�û ˆƒúY58[b~i€{n[ÁÓ¤ŒRS �º¾‘šÙ—™‰ø;†Ô‰çNÊ*j.‡ÔRÝ ŽÔ®žÞv|ÀŸ9eË.d}&Eü~*ê˜Q ©½ã‰F?âÞÝíI“€Üó ÿ{ÈZKg}\Ó!é˜Ïõû¶©i!ÕÝÛœ w�,XÔÍ|©þ×M¢õQö�¤„Ô Ñ©~†Z€Ô ÐÉBê°ŽßÚ$ZõŸL“—ºR§ÄêSshÈÖ„'S‘Ú*¡•if.ëW—üú‘ºä"µ&<™Ôn«ØËê�ZêR[qŽw+òðdüY!<™:ÞÁz:O€Ô�áÉG›™e52I#¯yM³õˆÔs<š:ÆÿœmÄ/"ÿG¼Ÿ"™ÉRñÌXŽ%='©)$©´štˆ Eú$ü4u#´0š1Óý¼q¬~߇‰ÔbôFx2CJc{{I®»éY¢¦x*LµóŒ1Û¶¶ÜóÒeSí¦ð×ÞTì¶mºZ>Ê_ÚÚ�¨ûëtK¶R'éU,É»¡+ g¤&DýhI;}ÛŒú5Ó䥦 u�#5ƽï(­Þ �¶¯3Þc`ü˜±‚ÔwU¤Ž&?âuù jП>þlYºÅnÜ£ ýÝ=1®›ÏI·ß­‘•Ó¤|¸£ã=•×Híòß8Öu É$ê÷¬º”úP�ºÓõ÷þÁõûƒŸ1ûθA-Ê?ÿoò9RG“Ë´è§ŠHk‰‡îŸþç:O¢u›8�/ÿK®ãÄ ¿Îøûç@-@jèä"õÛÕ­¥®éRêòHýv¸ðdqŒ'ÆÄ<‰�Ôå$ÑR‘ÚhF}Y†|žDËHårý~¤çK™ƒ’hIíöÓÄÌ”*5H-u©­x�GB”xóûbã¹ ÔËò"µ:ÞÁz:H¢€ÔÄß[›Dëš°¬Î± ¯i¶‘ºÄißšákÂÙ¬ù~ªE,BÏRosNìO6i+ÌÖák‰ÉÊ;�rÇœ¢º±òR+@¹-'¨v(”,JÞ”bKk…7c.1@¦²Ê.¹¦ä6Fí+51.ûky)_1doÒøâÉ=ßZê¶s“ô®®È߸¦ ¹©õúƆØK½Pb\kž¤‘Õ„%ø¨÷Ós%²_hÁºº djKã¶¾Âø 1Rc�±˜v-ùãY×H-\Â-(eûï¼@Òù³jóÜþkœu³Ps|MrƵ“d£óÙ6všèЬ¥&æi-ŸÙx—µ'F²ÎŠÄRg‚ûÌ4¾“p­Ä¤#MQ#µ›,Ì=þÀ]âM/\3MþQj*R×?R7ž~`Œþàïû‡åÆ @j¨Q�úßÂFü®ãÅÔµRSøe&A›Ñ“d ô#5 •³T[âBÊð#uŠZÖRk.S¯áo·››ǵH-u©«hq“e‰-u6lÑÓxL�BÙîéEjϨƒõtÀ‡§Ö DêK%VkÂòNûȤè3£5ÍÖ£LgJ㩦~ù®:ê}#>kËŸ§Ë ªóä­pr~žZ›ZkpK"R—‹Ñû*H�Ø9÷hÛ1òJ@I|žo�åˆKòIí¨)ª1?083 vSl9Áµ·E|ïm&-±§Düfõ}µ¼”Owwèt‘‘<¢KšñØö(S/�å«›×�¤_„éÏ=Lh‹|�û 6õ?»¹¾ë IdœÞÝu\G4(÷ÎÆÆý=Q¦)ò7î-XW®öá‡ì=|µ¤9žYË?MšQú+RR�"ûû�5¯ã¾ÜÿÖƒ©A †AêwC&Ѫ%R‡N¢Ue^j ”�vDÙË„ô2µÒv:Ø4h¶+ÇÌŒ±àíxÈ'}]Å´­ Ø´5•*\–:ÞÁz:qArµ ~ã©éÖÎr¦Y�:°þ–@javì8 ¸(ORè–´ã‚'•X@<àž·ÉäÛœ"‘âyޭ丒ûjÍûÂ}»½9kœ·Ï:eܤœÜuÛ>»TäkÜ[°©^.Eó gwo>hšt£ôU¤¤> }»¿Ÿö~:ƒH Õ‡•ÚçøýVH¤>&¨�ì H �@u†ÔÛÛóeë'7Ï=fÓm�qkwçeÐÍŽh RG·->Üvã€s=»á2kã,ºé\lbc�µë[í­¥Iêµõ€wîF 3îûŠø˜Î=Ü,ªî[ƒÔàù¨7ŒÀiÒŽÒ[ ��úH®õÛoç+üü[pûRƒ@�e¥“—úTM­ÔåÍÔårhUXK �@5Dê«­ŒOhr~kk©‚Ïhri{}]­Ô†KÖ·”¢�-\byÛÞZRÓeûki{ó¼&hÛò-á¶ç“Š¢�­Ýõ­Ž Ó¤¥Rɤ¤�©A �ÞJýN¤®íZêƒFü~��D¤Õ@KçÎíÁ,Rƒ@€Ô è€VêÆJ¢VjH :L%ÈRòû0€Ô  5Ò õ;!’hé¿ß¨e­7Ã,¦¤�@€Ô CÐût¡õ:L 5H �j¥®¯xß!ÓRƒ@ @jÐa©i ¶$L 5H �h¥nXÇoˆø �©A¯ŒÔ;›K0 €Ô  5*‹Ôuž¬S—M¢VjH Rƒ@ @jèˆ�Z——:¤•ú�ã‚jÚU+õ[šˆß`¥�@€Ô  5¤�Ž©ß 2R×KÄï7º–�Rƒ@€Ô �:¤.ïøýfíü¾µH} �Rƒ@u­d›3ãä[7cF[²º{@j訿m€Ô Ð!!upÄïJáÉŽ->Ù¡ÖRû¿!â7¤�j¤D‡éý.™ @j¨Ž¾m€Ô Ð![©ë—¨Ã¦¥Ö„ü¤�@€Ô P ñ͈Vf"ôƒ= 5tÔß6@j¨¶Vjb<®�,Z~35 5è°dÅôÅVù}#Va¿ê¼ŠYåv >:@j¨ñC=æRƒ@Çõm¤�ÙJ]©k�LÇÔºµÔ¢¤½ŠbÓ…It%ïªL¾„ Ãñ }kñj•ÆG‚ö«nÀ°{ÇK…ü´{ÂTv²8±×*^íoà™_¹è¨ �j¼Gü˜øòÄM3F^ZVÌdË<‰b @j¨.¾m€Ô ÐQ#õ›<¿kh¦~óÍ�VêZ†'Ë䇪<Þ²·¢Ffªwj°Ì~(ÍNëA'ÎÆÛ 2³ˆªh+Å=EV\Jé÷­Kl͘Úýª0ºø~ŽßÎ)~B.­Û5ZyõKVÃN}9ÊRƒ@�¦Ž¸xÂ÷úãˆçüx 5Tß6@jè��úí0¿ël-µ6<Ùé:³Rc*¨U¯!dnE¿:K˜Rºƒ÷é}e>Ój€�·q„É6746‡P‹| ³`³×†Æñ¼Ùºý>¡”o꾂Мn¿êŒf„&gºš1àéýœÂûÃc]Wq5Ó¿kØ“˜CGºðÛÜÀH]œà:A WS’ÍâÚwª1þ˜KRƒ@µÿ¶Rƒ@‡l¥~«Ê$ZÇ…Ô§œ—ú�ÚX©›¦ºê©1xµÌŒï©}¦ÕoãÈæŒ:ª¼s°0ªöÒÏ¡ ;±ˆAœ ˜‰o€YÍ~Õ à %:‡½’/£IrgÅ.#Ôêß50› �ÑBþÎ( «5ë�z%%ÚË<âÓ?ì1¿=H ÕüÛH R¿ë÷ûÖ#u-×R‡ ù]'Žß(Ç&7?]å™Ç€Ô±”µÊì©}¦Õoc©ÇÈ¿q̦ît§ºÄ¶¦Jù÷ÉK 怟DÍ~Õ ô ´Â*”PAì"w†Î 4ìÛ%ÿäèו6SRƒ@ ûŒÏƒ"•û–ñ`J @j¨Öß6@jè�­Ô~¦~³N“�zã`VêEüH]½Ž©1ou•Û?0R{M«6ÞFR*°· ]Ü#›j!nÔǨ;ãß7Š”{Ù�@ØØ»_u˜¹›„KA‰|f¹?¡ ¾]£!˜Ì,¡q@j@j¨ÏøâhÄÊ?åRƒ@Çõm¤�Ž©OŸi¦>¦ðd§ÊüÖä¥~;¼•ÚŠØqe/£ ª)UOììI+ÖÝL&ˆÔfÆŽ[�íšv$)‡¨hÚ¶©»Hç²l‡ßüûnûìGØf“g¥í˜r-¦©½¦ÕoÉZïl~)·ýr¾6ù¤½ûB—yÕ9Ï»_uF¡qzû� …ýõïö"ÔÎ Æür��:�’íažñÅS~{�ªí· �:$¤žL“—úÔ©úpü~…µÔÖ ‰ÍUºÄø6F÷Ð=%ŽÐbŠ„.�0[.w¡�¦¾¹±•|¨¥™þŽ £’9CN�‹3 "ê#n¼ ;í 4ó�áoWtZ¢§*¤ìïÒWq\`Çʲž&HOÙõ§Tº¬!¾Üyȵ¸Š}¥}|IññIjµ³“¸¼Àͤñ‹´­N?R{M«6ÞRÚ1àÇeêVÇfœÂSáßÇ4X2„Õ˜,’öîWÝ1ôÏe,3UòÌä0_<­îÎ8Ÿ .hÔˆë€Ô PcŠ=¼‡XNd1¤�jûm¤�©ßÕ„'{«ÎÖRWˆOv:�©+FüÎs¢dÁŸœ½³øÍL²ýE ÊÜÞ—E-1·jž�×2Ç“ÅÈrW¶I@h�Î1ÏpÄBPyÚ5E² šÿH1>«]ê*^`æ`RãªÜS1£½Èˆ›ŒIøz»ûjûø’�—hÈ,iô1q¬4çEjŸi5ÀÆÛ@J jò¾`Î5Ó#”¥ Jã±™¾}À)ñVMù÷«nÀ0ÆZø‹š”g€šÝ‚ór¼�š—½€r)¦@j¨qÔö_<åwRƒ@5ý¶Rƒ@‡„ÔÁáÉN—·R×mx²°Žß+¦3#3Ô¦L23­˜@ &E_Ô²˜ÉLáLêL›áDÜMQåêXfì*cS¬s©Hª�îFÒTJ§#©I’ªÑTf(Çl‘žvqKZÓ#—Ùzc©}]ú*z�:Ž»XééÁWuEr+W.ËL·âA¦Ó¢w_mŸ\Rvº§‡,Ç]²íÞs&î¦�‘Z>+µ×´`ãm !Ôã¼%(¸åøcŸÃ£ï*Úýû$§‰Àm·°ôdÞýª0¬þ>þ '-y‹ÊËg·…®¨&lÞˆH-T¤�F‰x(?TîBE#'©A Z~Û©A Ã@j]x2RŸª¯µÔzÇïÓÕ…'ìZ¢ì9CÈ#"Ht¡kôर]Ût·™c–M‘P·aöQÇZ\c޼%ìä+]ÅZj†ÔyŽ–„x,_»ÃYSF¬…2›‚ÔJ—ÚŠ¤æÄ‹2Âz.+p-µÚ>¹$ú3mg³#ÜÞÙJ1™Î˜uÁ�Ô^Ój€�·�$iÉ¡T2¥WÈ â?��åß'/CPérŽî7kö«nÏmqb4_÷FIfw·Ïáÿi÷¥ 5 5tLލ¡×›Ä�Q©A ãú¶Rƒ@‡„Ô^K]C#uh+u9¤n+QÍ•æY²Çˆ$V"Aœ¢sf'g‰A»•Ç´&6åÏN¶9?RàLS«³·]®aÊRjÔ1¹KmER„pA b幬²áÉÜöóÞåÏqšÇÉ�̸©½¦Õ oãO Ï‚fªAËÓW(뵌p÷wï>q Ÿå¯S¼ûU60†P¡“7-° êô#ès–`{v/;:uðôåµGê‚ÉH 5ŒÙ¬b>UfPb@j踾m€Ô Ða uXÇom­z‹O¦ÉK]©›�ÈÈ|�ÿ4�£+}W„Ñ•,zn¢@§¦^ <ýt™ç"…®¼u‰±Œ‚Ô1$-)nò·KBh϶’µ²1/RË]j+ªH�{*°Õ§%ɲ繬rH-µŸ§uAvj„Y¾1¢ÅñöçŠùM«A6ÞÆ‘É2ÓÏJI1nÙ×.OÇ�>þ¶Ã»oÄGòs+)’ÎjD»_]œiïrLÿdíû5i¬Òî””ìR L¼‡†ÔWkÖ7 5t@‘‡öx5ß6â¹jRƒ@5ü¶Rƒ@‡ŒÔoW·–º¦K©Ë#õÛá“]P€c\¶íµô¢{�<ŽX‘pâ4BRÕUžÆòb'^Ô µ-È™›:½í¶fEK>¤–»ÔVT‘Ú–F…"—ŒÔJûÎ%fžÇ[#cqgŒE•v¼sM¿i5ÐÆÛ8*‰ˆkýú5É&�O´O¦Fd´±:ó,Q¹o¿êð䣙T<3–ãS¸`ŒËòí’W9Ûˆ_D�ë÷ H 5ž:ª7›1ÃY 5T³o 5tHýnÈ$ZµDêÐI´ªÌK�¹°áF>–D‹F+s’h©Hm4£¾,s¤�ð$ZF*—ë÷#õ8GÈ $ZR»ý4…3õÕÕ µÔ¥¶â5y|QþÈs"‹�ç&\

    &¨�¬Z¤&Ø7�NaØ,P~E…¦L*ÏxÙ�Ô$ß2Ož5Eª¦3½“Ô„ìEjÜÞåTZ ug ¡©ÁÌPޝÏñ»e1’éZÐ#µÛ¥¶b ãr*ž!Ë  ¤qO̓éÔUÅ\½¬2Žßrû²ã÷Ü`<•eáÉÈ¥áÆú15û�Úg‹õØx“©i¶îv݇.2ï�fм¥!áMàÙ72,nÛåLÀ~Õ ¤çh�¸BsÌ�ÔFŒµ7žnÜ_¦ZFV¤�¢$ùªXÕ~ß,rV²üC>Ì-t\ß6t`+u˜¼Ô§jj¥.o¦.—C«ìZjJˆÌšg3"–l{~¤&Ì9öæ˜R†©S4Ò—@jbžfê5üív³C“ãZ¤–ºÔU$Q©è€¹IÏ1ªŽËëk”Ë O¦¶ï\R†ÇûžcHãaÁKsþµÔ^ÓªÇÆÛ¨P=Ö4è|&Άe75õH•w߈§¦[;ËìWÝ€Ÿµ«X5O5õgà÷ �:>µi¾m èÀVêwB um×R4â÷Û•�ÚZ)ÑdÊì�9ÖLùqŽž~ÌîNMC 8ŒMµ¸U‡Eì<ßÉR¤žB“t·‡úõ^a$ím·‹ôYèéEÈ¢i‡U¤–ºÔUŒÑ W™ nÒ›Í2c§ò#ª\1|÷{ áýþö�K2Ò¤ÉÉ)û,N_&\îìÖ„'óšVU/H �`~OÔX<ÓÚ¤¨5÷<å_T�ª�o:R+uc%Ñ m¥ÆPÝiG”½Lȵ)VÚN[ Ív嘙±ƒt"vÈÚŠi[°ik*…¼¬€�Ä2™˜r-ÁmùL«Š�¤�N¬bº‡üž¡îüEGùî¡ÝC~ �ª�o:0R¿"‰–Îñû�ZfÑz3ÌbêH �@€Ô Ð+Ëô'õ±bvïxኣÂx¯ó¼_ŽUŠ˜ß6èø¾m èh­Ôõï;dx2@jH ‡âºxIéÅ™œˆ³�&s3‹¾¨‰ä!?H ÕÇ· ©•ºa¿ß¤�@€Ô ÐQK‚ØÌ4�—øSþdi¼É¿pˆ!¤�êãÛ�^©ë6ÿ|–o,ݹ³”ÐUúýçŸ'à÷ ©ßñ»ÎÖRkÓ�+5¤�j"3Ø5Xf¥xICê/^©ïÞ㺻¶ZÕ^¼xáÁßÕ/‘:ùûo¿ec]úæ/T»ÌÓö)Þ'»éo¿ýî0Ð1|Û@ Ð+[©ßª2‰Öq!õ©ç¥~¬Ô #�yÌû¡ß?[ðÙRƒ@5SG°/j°ˆ'jÇá#õgŸ½:R&éîõð'âꤾýÙg�H}óÛoK7nýEèSq:ƒì÷xÞ·èè¿m è`Hý®ßï[�Ôµ\K6ä78~ƒYñî‹Ãž¯Ì\ ¯öÛ¾1rñb ÿÓ}ÑU«1(íåÙyùZ( ÇOÈį\¼æl§.^4�³o@jè@JD‚û‹.Ž$©ÁñÛ±R3-WÓ¹çŠþ_°ãwâóo™K÷ Ïß||çcBÑŸ¾Oí×waÓ�åo¿ýn1ÐÑÛ@ Ð+[©ýLýf�„';õÆÁ¬Ô5Žø�ÉUy†==dnE��5Õ;5èì-N÷þ•ûÌ¥fƒ~?R%„&•’VÄtÉ:ž}sïºlA®š�ii‘ª=E¶]J�Œ_¦ºêl÷"¤�õÊ×zñŠž¨µDjŠÑ c™Òõ̓#u:©óùç•„uú}âë}‹”��oR'?ÿüóÜb #ÿ¶�@ CCêÓ§Cš©�)<Ù©ò¿5y©ß®+u¡Áêθ†�y¸ýêÄ”ˆº�Ý4zèo<æRŸÝµQ%�ª µ=‰P~¤«D°öXösˆ#õ¥ .|[­)±7Q¤H=‹ÿÉ^Ç•m@j@j¨v†³ªþ6™•Íf5Gjj#¾WE‹U…'û÷Ï?§½Üùþag½ÿéþði4ÚöÍþð‡�-üŠÔÑÙÏ?ÿ-Üb #ÿ¶�@ #u¨ðdš¼Ô§NÕ‡ãwÝ­¥nšêªc¤¾ŠPËÌÈÑ!µÏ\êµ»6ŒÒø¼RP‘3+q=ˆÑBäöñçŒæR;FHº©#xb àÞKï=„&©ë©“󉪎üâ—TÚ'ø~vÌ7€¶?¼¥ ,ÝZZz¿|IÂZZšo«<€¶X¼³Ýr†g‡ÏÃS-è g!ÌfU!uÇòÍåë ŠÃüîMÜÀE¢…Äur°cyùF‚£µ�ï©{C¬ÉÎÞ70'¯9#ÂÕ–Å·£ãºÓߤH�$•®û‘Z>åóÏ?£ÑÈ>þæ›;¼ìÎ7ß`¤øæ›o–èÙwöúçŸÿ;Üa #ÿ¶�@ ƒ!õ»šðdoÕÙZê ñÉN2u�"~O 7×NWyæ1 ulee¶=l¤ö™K½vׯ&¹K挂Ô„rtíÒ »œ£ÞG¨%Õ©"5chGy Ø)§p ¡áú}‚�:qçSüPüͧ[á�41u`²m—ËS¿üeæ—ì˜oó*R/ѶñSz2¸$q‡—´ €U‹·òý_™ìÜN¾ µ W3œ…1›U�Ôk,B÷²ƒÔ‰U¶"zí­°Š)Ù %woD“ÌŸû^Z ž×½{;áGjr*·=ß`½ˆ6ñÞ Âop¤¾Î*­]W‘Ú3žh4Âý¾£úé’øªr¤þt *!uò³Ï!@èè¿m èÀHžìty+u݆'«±ã·@êêu H�¡­Ë8:¤ö›K½vØBêb“a¨HÝ�s`7KhüöÑDÄð u^1R§K!Äzš¤®'¤à K-N!�¢ý5Vb°©I¶wàr3ƒüBƒÔ·>üp^"j§í�A% gŸ¶ €ö*€šh�YøÛ <Ô‚<ŠU3‰ÕŽV|ÈÙ¹qWhÿŸàgbÍ-¢\|÷îMQp}Yl1¦îpªÞ]£·ù?‰]D7ïªmâjR³M>&“Ÿs;ªO4ú»Ï>»í½Ž;øK�¶Ñ—_.RG?ùì³›p‡�ŽúÛ�Xºðd:¤>U_k©õŽß§«OfE츲—QPÕ´ƒ¼j¬Îž´âÉœÉÄ‘ÚÌØq+°]ÓŽ„#åMÛ6ué\–íÀ—„Ô¦|R™+£¿Êv¹)õ™K½v×RŠ\¨ŠÔîÚ þ¦ w û‹øƒP‘:­3R“ÉåK¨Mtà:€Ô‡†ÔIW”›?ýðÎÇäß[ÉPG’É_þò—ôßv¼‘p‹Ó¿üå/èÆ¯~ùK#éч~8àìÜ¢mߢfð�ß×—$?&EwîÐú`YÔ <õëLO+Ùèoãåó¿üåù$¤*¯â)Ÿ>ãǯ†ÔRß”†ÓË«ŒY;p!ص›¬ä:Þ§kË¢ >”U)í®ý¿åÛäß�’ìäeéÒðî*þÇ$'¬.»m®±ˆ>ÂH�ÿa�¯.ß\�cÂþIÍx’Éßÿþ÷¦w?%¾$âw‚ 5Ûüíï? w訿m èÀH}àµÔ54R‡¶R—Gjk…Äê*]b|£{hŽžGh1U GGrœ¦¤[!˜[šéOÙ0*™3äÔ9ÒNŽ­î#PYd{�ä† »¢Ó=U!e—¾Šã;&P–õ4Azʪ1¼åËâ뚇d¤¶³d¼Ó¢và•‘Ýøø$*sh’�ó *(�ùÌ¥^»k£IEêþ‘Òͱ£ß'R‘zFg¤&ëÕ›œw�ºŽ¬Ôw>åîœxãÓD¨#Ñè/~ñ fëÿÅ/â’ß÷/~‘¡ƒ¿ø…wm©ÝÜ"µE'?ä½øK¢KxƒÚÁȆº ÛB+Þþ5ó75Îãí_q¿ñØ/~k©A~ßkú… 9âU+û2‡ý¶ó15ã2rþ ]Öà0Ë®1+5æbâ¼M¡—.Q¾ËLËËâìèm~ÖG®ù9Ê*¬2c53b«ö«&–L¯:Vj^g™÷²ÌÚö�'šÀHý�æG#á:³|ú)ÿÊ-ÿþ÷¿ƒ tÔß6t0¤ëø­M¢UoñÉ4y©Ë#užfÉVöÈósá$Û_¤ ÌmYÔs«æÙy-sl—ØcK|Ó0FÑ�c¯‹9D{Ú5 ü`.í5>«]ê*^<›eü!z*f´‰/«‹owIH}™�xZ©­¹2²K˜½dŒ ‚ëñ„Îò›K½vׯFêyUBÕEÑö¨÷}H�Qýº`ãÉÎR·.¡ƒG®«/¤.Ž å©øyØr�—‘‰6#sk.fODçýH­,¥¾å<“'?þôÓµ%ôߤÿÞƒÔö/$ªO¦ñ^§ƒÔ=ðH Ò;£†yÊgÏø!òB…ý¶­q\æþÕPÚ½íú„”–ë’CkIÁÁ7ùÙü6ÿˆmú‘z�±8'h¾©GêóRûÆíø÷÷Æ[R~$¤¾þïÿ™©AGþm�@¯ŒÔoW·–º¦K©Ë#õÛ!Óaþ+LgFf¨MÙhÆ{‹™VÌ”“¢/jYÌd¦ð?&%à 'ânÊ;WÇ2cW› �KER}t7’. R:HM’V�¦2C9†¡žvqKZÓ#—Y^+©}]ú*z�:Ž»XééÁWuEr+W.ËL·âA¦Ó¦„Ôh¡ËNwM²®Ë]ÝÍN÷ôf‘[œG½°ã3—êì®�‹Ô-èß¡®G½ïCêKŠ‘Úlü�ÍáÏ/F߈´Ÿ¤VÔ°H�ŸŽ?Û*8Áêïïç�7xËYçœîïç|}¾¿ß;e)5fä;îæÇÚò¨>àµІ·2’“-=à[ýý6<Ñ‚üŽØí‘PÞ¨ Ú“‡†Ô.ÈFÙZj¹d•Ú‡ÓÓÞtz™.¦–ë^g¼ª"õ ŠÔ·�Œ¯ê�Z,zN08Cjÿx¢Æÿù?L¶>uÞuy�Ú_ß¶Ãÿ¶�@ #u°™ºBÄïSõêøýV¸$Z˜UKqnëK‘½+ܽ™ Þ�¶k›îR7ì!²gÔm˜}”q�9‹±M±–š!užÛ„3ET´|íg ±JÇ R+]j+z�z˜ã좼jÙsYšµÔ¨•ü QáÊÈnLزé@KÞ”M>s©ÎîÚ¸HÝçø¹O#Ôsôû^¤ö©]ÀŽ\!¯;²“MÐ<Õ'ÁJ='Ô×ÀH=°´4 ž}>V¸5øVkk+?ô«ÖVa#N¦œíó­­¤vcŒÝù؉"ÎÑÝ_"3½ÜžDð–lÀîÀû, ‹ÕÚúkx¢i\3"ažòÙ3~ÅøÃU õ�µµ5� Þîˆ^'ÿåZ][ÃP›^[ãaÁ–å­´zvoã>ñ)2R›kkÑB'fÙ͵µUZâ 5Û\“NüˆÖ_¦½ûÇ�}ò‰êÌ= –hø‘:ñÉ'Ÿ$áþñ·  ©ÿ-lÄï:^L}P+u+§IÃ\iž%{Ì,+¡9Š¢Ì`8È4Ë89KW�-Ø”/{8ÙæüH]”4MùÇÛ®kµ¼QÇä.µ=H]|[�V-{.KƒÔ¬õ4%ÿòW–w¼ºg½÷86iG^s©ÎîÚ¸H}•øÖýŽzß‹ÔsFjüù]¡ÖÜ–‘9Ç- Á‘úªì¯Ñày©�GãDÈ#Ѥžß†K·vk«gM\âÖ­[Ú§í[^Z%2FËx­ §µ5£9/ ©AåŸòË®@1Ã?ã‡Ej“® Å�Y·)›^¤6)ÜÊg&¾îCêeZcÍh~Ž©;$ì^½ùÇ5?ùdV¾ˆ¶�ñwQÀߦ"un/ÐÛ@ Ð�‘ú�@¤®ã¼Ô‡a¥nV\d›†GW(ú®n!‹ž›(ÌÄ)Þ¬ ÔŸ"Z¤+�ó£ù"©cÌS›Ál“¿]|¶u¬…¶¡"µÜ¥¶¢ŠÔ¸§Uªä€™ï²4Hͨ,FMÛå¯,OíìÔ�£Ô>ŠŠ¤ñQ±è5æ7—êì®�‹ÔSŽó:›‘£Þ÷ µ­©/#”vv,ûÚåáé8žð>@êzDê¶}l|ÅA¼ÉŸÎÓ©” [Û)t°#µöyËg%ò�%÷±Ý3€ó©”©œI¥Iîp@ õcÞ¨ñÀÇ|3ÎüPÃbÈoÛ2ƒTФDÖj9¤VÎf0íAêÛ´žŒË×½H}ÛAê„4ª›¢7ÿxR$Ïþ1øx H ªÝ·  ©ß ™D«–H:‰V•y©/HäIˆS2¶ôDC㈠rNÓ‡ûqi‘gžFíb'^Ô µ-È™øDw¾v[³¢%RË]j+ªHmkמz.KŸD‹ˆ"uù+sv){›$Þ÷ Ã.Óo.ÕÙ]©›;}�Y?ê}R�Ë ílç.ËR×R ,Ýúøã�ï$ÂùÕ¯~%6ý«_1oïäù_ý*æz�zéÖ­y­‘·žÐ–à¤À;mº$ñ†z©æ¯~Å¢’¿ú 5H¯$w4�kýQcqî¬Ò‹9¬ã÷G¹Vê�>ú(AJ>ºÎuãúuÜÌÍ�>┼üÑGËÎy7Õ³“ä<ÌÊNeÑä ZèZ©é9¸D ð6;ø‘[Bz\½ùǽ®X©wð7q@}ã†Kø8È¢€ƒƒçÅCѯ=H}ëÖ­6M×– ÎJIR~voó>È‹$½=áñœã¤©ƒ?ÈÇMOlËG:¶òÛv�b4?…nã’U$–õH½LÏ^MHôÜá²{*©pÛ9�ÝTª­:Hí°8.2EoþñD;~÷;w-uÒOÔ Rÿîw³pg�ŽúÛ�l¥“—úTM­ÔåÍÔårh•]K½‚�Ûãø­"õ B™8BcJUª²H­qü–ÚŘ]šµX“~¤–ºÔVt�šò‡)G% º¬ H]þÊ$¤Æ?Ž/° ‹›Kuv×Dj³)E.5v…]ŽÕdžõ¾ŠÔª‘ºGl³]1ùMVŠ�„_¦…ÔRݹ5úÈùóNê¬Þ¦OC‘óç�dV^æZ·ô~ߤu}IâC)žYï hÐsþ¼šw¥ýüyFÒÆùóix–º£ÆÄ—'nš±þý´b1S<áG"±ð.Ì!¿m‰ÕÕUñµ¸�·´ä©WWo8[ËNÝeõìëôìèÍÕU©;pÙMvžˆæ½MÏtÛL®²3V�¶i³†ÜÇžAËH}Ëû=Œ²„ó"â÷ï~÷¸±@Gým�@¶R¿©k»–ú ¿+ä¥N!ÔÏ€dhÈÖ„'S‘Ú*¡•i¶v¸_]ìGê’‹ÔšðdR»­b/«Cj©KmÅ9Þq¬ÈÓ]ð_dåðd2R—¿2©ñ® )ow>s©ÎîÚ€H=DZ5!”³�øEÄßõ¾ŒÔ=ª‘ú‚ ؘ: ƒ¦Ù_òŒ¤®9R/aÝ!ì¼öHO�›ò9ÒÓCP:i÷ô8�‘¶)ߺµäï¸ ·­ú”»% E+|­ ÷Ô®´‰‡aO^==�ð( *ó˜oFeV³&8ì· #ðmÖî«ßä<º¼¼|݃Ô7d¤&uÓììÄm§ÄAjc•ã0ÙpO$E¦ 焟 R¯²1'qÄ0íö¡Ž'šœ��”½¤!j©ÍÙÙÿn+ÐQÛ@ БZ©+‰VH+u¡R„‘#O¢E£•9I´T¤6šQ_–Qa„§š2R¹\¿©Ç9%Ñ’ÚÅÛk0ðÔ µÔ¥¶â5Ÿ{QþÈsœŠ�çÜÔVžËª€Ôå¯LFjs k²bùÌ¥:»k"u‰¿°fø²qvçù¾ŒÔŠ‘zVyEaNˆõìÝ'ã—é†'[ºsçÎ@È#¶í¦|6l›Ä³l;㔥m[Eêù[xn÷N[P Þ²"Ç; íâ¶QÍØ6‹ïÔaÛ€Ô =æ›ÕÙ ûm#ÆåeÒt"Í‘Ú)Iš —J62¾Îp×=û&7X ¤N&ŒåUAÒ’ ¹ÉëÜmpÛtôúm ©o“’˼ΠOb<Ñèoggùˆô¿ä;Ë‘:2;�› tÔß6t`¤~'D-�ã÷µÌ¢õf˜ÅÔ�š ißt:…Ѱ@ùš2©<£J?Rg°°SS¤j:Ó;IMÈ^¤Æí]N¥Rwb›Ì åðú¿[#™®=R»]j+¦0.§â²ÌšðG÷Ô<˜N]U<ÀÕ˪€Ôå¯LFj’Ù æ-Ég.ÕØ]IYNªé…ó_�5O’e\ÀíQïÓ;¦‹¿¤�Íüª¸a±óJC'ä—I^&píd$ÑJÞÂÏÆ!�üú×n~ªdæ×¿ÆOç‘_ÿÚ ½ÝI‹ds·f)uÂGÔJ Þt Û–ûØî@ o)y©-ºÆ[ð|ªô˜ßá{Î7;ª�ZöÛ–\¾�µ¼|óömü?j°æ%¤èö2Ûç{ãöm�ÔìPÔ=Û-HßĺÍtƒ}E:ÈöÍååômÞG‚l-›ËôüÛd¬·én²’› Ö›ÕŒ'�ÿö·ËQKð#õíßþÖ€[ tÔß6t´VêúŠ÷2`nÒ³EOã1 e»g¤.{e R“«œöO©Ï\ª±»6¢LgJ㩦~ù®:êý°²ì¦¦~Óê©©)8îH&ãZ¤£f&ÓMà"÷Ù(’É´©Pî÷û¦ Þ\²$!õ’—é�$ñV\:ЙÉpÛt‡z Ý6#ÆuÆñÏhÛBV‡þ¶%–ÓL7?¸™¦^ÜIQ’N3JN§R§Ó©ù1©®™ä•]-;/±:n⛬ìQpŸAŠð¦SF‰šôq#ª¾¸ßüæf8¤Nüæ7¿�Z #ÿ¶�@ #µR7¬ã÷»eáÄZ)Ö»áB²‡æè)qŒguê´H)�«Nµ¸U‡E(ë<ßÉR¤žâÁ¢{(e^a$ím·‹ôYèé¥Iœ»¼H-u©«˓‰Ì7éÍf™¥R P¥\1|÷ËG'ÅzhnÚ.weÃrÌn«¤Dw 6—úí® Ðë‚ÔIÙFÜ∩Ûð^ÒPÖ‹ÔmKKÞZIŸ©§dþÎ�[:¼ö †7]‹¸áîRƒŽIá_`%n«òÍåDtù&cÙ¨±ÌŠØm‹� ¤v¶®ß¼ÉáZ­e{¤`ùÆþ^nÞ€ÛÁj^Oâ©Ç8îœWâuûˆ&nÿ†-@ꄃÔ¾Á/tôß6ôÊH]·áÉ*0uÙ$ZÿVÁÞguÚe/ÒÎg¥ítphe³]9ffìH`lìˆù¤¯«˜¶•›¶¦R—UñÊÜžŠèrHséAí® P£#õ- bÕËÁG¼HMº#žÉH]Æ=H=°´ä]„é_˜é)p9>á«ë IìÒ¢3#írt1žƒ@õ„ÔdÝs"á1Í%üEÁLžø ‘׋ÚfÂZ2 _ϹËÌY¼²\§u�ª;¤Öå¥i¥~㸠švÂJý–&â÷»€rG¤Q±°¤ÒÒ­[KIw›š…ÛÞ:â(�–óSét{gºSz oO§•øù¥¥6_Çž€eÞ’ä’ã-N½4€D$�›Œáâ¸c™Ã£‚çOP�!u^�ã^ãor'r�ªO¤~'ÈH]/¿ß8èZj@ê£RºéRƒ†�Ž©Û0¬.%Á޲ؿÚ#’:;å`Ú‰Þï4¥’öÎNùá:9¿4¯šÃ,QûKD·¾þ•$âx�¸©Æð¿íN?ê�@ @êÉñQ¯0 ާ:H Õ5R—wü~³v~ßZ¤>H]CM“ÕÒ0µ @êJš'©§—,‹þCÌÒä_íI¸Gy—†qmS ä‡ð¶ùy-/)jÓ•`”'`GT#µ3€d‹NÙgÆé¶H�HýÊJ„ú&%ã‘xî 5TÇHñ»Rx²c‹OöF¨µÔ>Çïw*¯¥H­Wǧâ0 @ꊒXÖ"OÄm©}G$an•w;ÇÊUÌx\Fê/RÏûÚ_�¾ïî{­db©‰ÈõÆø6Gêx�Hý꺮~�&!ï€[H 5‚•º~‰:lZjMÈo@jTC¤Ž¶q;´ f9ëž½G\µ·+Ë”“f{»Òa¬½ÝƒÔêRjËЖ©£INõV"hÉv.ò4oñmFÒ‰öv ž?A€Ô¯n¦6ŒŽ0¤w�:‰Vjb<®�,Z~35 5ª¤&`ÚÖÖæzV'�¸Vh³¼Ø2M©¥„\Õéý¶��¶Dõ `š€Ô @j�UXK}º>¢“é˜Z·–ZCÔ€Ô ¨ÖH]µªCêFêcCj  5H �Ê#õ›<¿kh¦~óÍ�VjO� ©c±Xù§žXLBjbi>椎ŀt@€Ô  5ªàø]¿k©µáÉNƒ•�¤¶,‹ô‘ zâÁÇU¤~ÿ¥‹?É \�¤�@Úðda“hRŸ:p^êwÀJ �Ž©“¯*ÞG"Ü1²”ú�UnX v¸# L‡‡Ô0— Ða~Û@ ÐÁ�ú]¿ß·©k¹–:lÈopü�@'ÀJÝÆ” w ï爕šN€IVj¬Ô H»–ú­�ŽßLJÔoÌJ ¿A P"5¤�©A FFêÓ§Cš©�)<Ù©ò¿5y©ß+5¤�©A  5tH*<™&/õ©Sõáø k©Au,橼b¯t¤ÓØè 5H]VU¯4�©A �©ßÕ„'{«ÎÖRWˆOv:�©!â7èÕeæ/^ìÛMÃ…Ò…æAç ½2^*ä§ÿöþn·uìJûG—×פêìŸ*är¼€P¨µ· o RðòrÓ–eG6ì)‹”d[*ImQ¶^Ûeb(…BתP<¨lô-}Úè÷ét'ÝÕor{~‘â—$J¶(Ê~Y¢89Çœ“’K?Ž1ÇÐÄQñÀ•xÇlÛäÆªøÁÎèìÁú¹o/†Än6ÆùäÓ�Vw×î뢳œAmŒ7TFT¼Kˆ¤† µ¡ÿ¿Tï|GÞ7 ß6‚æFêñéÉ^LöR§6=YJ¿Íö¬~2£_Õ¶a"÷{Ç>ÙÛ~é‘~GvˆKg[êÉÕïËã²€¹qÅ)º4v‘åFgIÖEæ#ùÎe$5N9ýxe‘ ÷õ>!Jd#zâÐsÅPó©!Há”vÝÒs¦D† 5A!ê‹JO…ÔkéÚKøý"]éÉ(͈®×„hÛ0¬-›ÚNNîî7Ùrú8¿"WÄEj…B±Õ«¶)(8H7<ØîÑ�ã·ã’Ø¡]v|EÖ¯«MÚ�A�ä¹mזּ: ÀÝÎìœ2ˆ0>åôSGjų,&!—žË³E 5©!RCPBH=÷^ê%:©c{©—�Ô™ÞvŠ‘ú‚òße#L0Öý&½D¤vÖû!Z…¡¶Elgqú„Ô˜{ºÒ"7lùu›´˜{ZoKoé.i{=Ì6!TÕ¼gýŽ\‰r)Mu,¼i¦QÐÇö«J$bãõ6]Ñ3óìB„N?a¤V*\YB®½àLøN·ƒ ¤† 5A@jJ ©_�Eê×¥~/µã´ ßûý¬rÙÇ·ɤ›±Nrªß•Hr‘ªºÎ´sœÝð5–•”úÕœ²L<Ï•Ïùì7Õpס†ºàÇÒÐŒœ¤Â��k{RûÖÀ%ðáqÐÊ&}àµvCNäÌûá+ýKà_¯ÑgÑ)2uªO»Dq£é]oÿ�»+3±Õ�çs�:¯0`¾aÓÝÛTë\Бv ò)ˆœC÷Jø¦ë|‚¼–6zTâ ?uvY›¬4§rNçZ™5|ú)!õ°é¨åÙKmÜørŸS”¾ð¢5�‚€Ô©!(a¤þ0f­e"uì"Z³Ö¥¾£üÒ7—Â{™¥G·æz[@�¼�·¦Ù’ö¥kQá¨ü®D†šƒ¢R,óC¥b»RQ¤fE«N‹fµ%|–�~iO»ë•Ɖ¨kåCê�ÉPÃR¨‰»R‰ÎêÜãþõMK«¬ÓAV*Ú¤ö¯�Ö%çEu«O¸<<éVÕ\§\ÝÒ8R“›m£²Ýå#ó_Xÿz¹Cíû-™>ù:ÅÓ‚z\g)ÕGëí_¢qwe‰ Ì#¤>•ÎÔÑÂq×¼ê8£/�B±&Ÿ3Ð¥ÐÅPù³ˆ�QŸžÏ$½¤Ëž:9QÚlÝÉì½Î£Æƒ§ŸRûäܸ�sRÞ�"_sú=Úw;°EC5•ym©!H A@j‚îøý2&R'Õ±³“ÍŠÔ”Uí‚ Å-²£s1Ì"Kéa×ñ]ü0+½¯FЕH[ ˜cu‹{MG»vR·%8šC2ÔCýÖê ºòjŽS›©}&#�º&�oÝ�qÑ‹wZ“÷R¯Ë¶Õz]‹˜tŽGuGò ÛG,® .Ap½\g:O—mÞ0 Ÿ|‰%"¸ ÍzÕ³Þþ%wWfPQÉøMZ—½fNvÍ;Û»<§P͘ëŒÈôdûÂ¥¬œ³0üz—�!z”“š7%öI‹7Éò‡‡<ÁÖ­p»N?)/õÀQÙEj}× ÁPd t“üÔáCÖíRC�‚€ÔÍ䥎S—zm©^êÉnêI5´&î¥^—˜×î²WìHÄØª6ûyNérW�r:¬ "«3˜ ¸)¼•$Ù¶ÂHí&þês÷d°_'~˜3—?ë˜×ddÃR[Nõc˃ª�iMFê@ãuo°qxÒb£°&ú½‘£¬pö]\‚àz¹�ufï¦]bÉÀt¡ ,‹%wWâKmÉÈt‰ÔªãV/Ô}ûyóê¾ÀvÍp’–µD8r圻Xs��ÜVŸÏ‚i´îdûï¼éñ̶çŸR_x;(nÈÅ¡|”Ḯ-ù�\RC�‚ 5-ÉKý:R/w/õ¼¿§Ô¥ÎŽ¢qÅ‘ÄÙ&9çè{縙ë1ÃQ¨ÀY*àJls·-�éµCH­º»‡Ð`¿,±õÕúYŽ÷áGj¯ÉȆ~¤¦–,QBÈöäDLk2Ro°ìcUSwÐ/0iÓK´7ÒùªroªïÊà×KLÎØ<å’SŠ©µbDÆoÏ�»+ñE¹¿ÅtAÊ,V¾äJ:ÂGj⎤qݸ>©õ ù²óXÄ8© 7Úƒ»"+©Ü`·”XBĺ Ÿ~âHíyR£ädJ¾*û ñ @jRC¤† Ôz©W«ˆVL/õ®·¥"ç¨ÇP[qÒboÉàJl“œRa¤6r–Ðìw½îôBj¯ÉȆ~¤6¢öž§5©ƒ�×ÅÎáS31i'”ù”�Å­K-”½W— ¸^\%â­é<å�g6'õŒæƒeß�»+ñ5ðíæ½e{µ‹£Sl¿½»]w›‡»ܽÚm‘3§n5_Å1å¥{ü¦eÇUGëyîéSEjsHênU5MÖ*Û ˜­ut£9�‚€Ô¤† h&¤~£ˆVTà÷³eVÑzg3õ¤n΂ÔùKæh¬ó¨í€+ñ>H�åy¨­NR{MF6ô#5…R9,b[ƒÔyåZ¤‰:‹˜ôÍ$¤ö^ © _Êæi—èÅ#ž[›ïîvÖÛ¿D�ÔÕÑ->ç:iÉ5ØáQæd(o_™zWNO�ÝÓ g^>·§YÑ…ÒåŽìC'\=úô“Fj­,søuBÎÏuÂ�Ô¤† H A©óR§+ßwÌôdS�úέüö#õ1!f�#bЕ8©#¿=ýR`´¯tÑe©=&#ºHÍùC‹L`uŸÀoÁ´‡ŒQ áI;�ß»¼i©=W†£¸#�š6ªå½GÓ.ÑÍlN´’ëX¢û#uÅ�²HË0 ù+™…Œƒ/ë¬/î ÏVÞÕFéÌXÈþ%PŽœkr¶pRk™"뵃éñB‘� òÅVë0|úI#õ‘ÿqƒ£uººû¼H A@jRCôà^ê• üž”ñ»èä:ÒªU#"=™©u›Üõ…2àJ Û=Bêˆôdž~×�£zR{LF6HÃêP¦'Û�Ž éÉÔË#ždŒ‚ûIDã‘Ëú0<éQz²“h¤v® ç‹@êQz²bõ6æ%‘õY®w`‰ÆÝ•9T—ƒ¡Û³pÌJi±Én©]ifÆ{|éý"5S7) �‚Ö±¦ÚÎZ•FNê�x�b7¹Sô­¶S¤›®˜•©˜û]~ßC§Ÿ0RoÓE®pùùVeñ ×@jRC¤† ¥#ujÓ“Maê‰E´&y©)GŠÄÑm§ˆÏVæÑò#u>KÊu±%6àJ Â[SnýWDËÓ@Å Hí1ÙðZ&á®ÎåªÍVg„þi½Ô69W…[õ:ÜøÔª+Òézž4nÉÅÛ!µïÊpE¬(>®I7»l2/1-k[޾>ZïÀ�»+÷@jÍ ïJD¶�7züq€áùÓ¹å{TRº3ÚImËíÕ�®lb‹Oª~)�oŠQ§Ÿ0R»kífO}rvŸ9�‚€Ô¤† (>RGÕ¥Žé¥~–TsS1¼Ô/#2~OòR3$-÷+Eú“\F=[³ØèFj“ýš¿Ê‡]‰Ax£ý�+Ro1æ±Ym à ~çnsû&©G&#) &ÛCÌø£B-e�+Å Ÿ£Ø?­ RÒ4´¢-ÍøgXqîeµõð¤ iUyÓV!„Ôþ+K�Ô¬ˆóαÙ/sÇöÄKtúîvE¯‰µ”ëX¢qweuÜüÞÛëÝn:;w•½îÅ™s,¤Õ¥?_Ïr"¶Ågkßvúìߨ¢Sì9?q>¨j�ïÈãà駃Ôuï÷Ô‡Ô9Sº¬�µ ¤† 5©!š ©_�sR§%ã÷³y÷ROCjîßâÌcH¼GJ> ©YN*™ŽÊïJ Â[‘§Ér�š9Z…öóá~w¤×³‰Ô“Q ué5µ¥KÏp,5U?5�¦Dj%'ÏžF4Ö,Ç){5é#é3äKìGjÿ•�%ˆFêQ£¶>í’†Wõ‚g½ýK4î®ÜSªyìǫ±¡{µ«Ì•gõu#“)EæðÖÜV…b}ËsF¯OÁÓТ¤† 5©!š ©'~?_^Üw$R¯=RëwÌõeŸˆÌjÖù N>(ÅÙ˶õÞE¹k¶å‹F�Ã[�tùa‰Çÿž ’ö»ÍlZ¥}^“j;ˆÔ“Q Õ6{³cv¤Kïª.œ¢¾m·¾i1Ç÷¡ÏÅÇáwxÙX¬Ï°c†'M‰UÝgØk‰¬Ö]§b°p‘û¯ô/Ah½œ¡ìò$Þ™—˜uæþmÝéÞõö/Ѹ»A@jzÌHýÅþôÇÿøÏ¿ü‚ž°þòŸÿñÇ?ýá 5%‡Ôã3~OKO–X~²g±öR‡¿§düæÐ¸e(¾#S‹·rWbйá;§™†¢�ýobþÒ�jX1|ÖŒˆF§¥›�Œ×Ïh¬=jÒÜ L�Ç�Ýwåä%52Õ˜—辉;ë=y-w‚€ÔôÈ�ú‹¿þh ‚ý×_¿RCPÂ^êôuܲÔ)¿bâ&/DíàŽVR�×»Í_¾ÅÒBÐÛ_n¾[ Rÿæ�`(òë�¿RCP"H=§—š9�ÓQE+ì¦R©!(5Hýn8 A#¬ž�ªãÛ¾øoà…õß_©!(¤~©—™�,Š©£öRG5�H AËEêw›XSòë—ï©7p¶Oÿî‡ï¾Ò°ÏzÒRµ¯¾ûáwÎÆêÞ©!hyHý|Jä÷ÝÔÏŸÇôR¤^Œw²XHãw>V‚ÂÚ|h¤þµ¤‡?þ¨au!HHûQî…øÝ¯�Ô´h¤~'ãwÊöRG¦'{/5A©Bêwù† H½}÷ Hýãÿpø3V‚¼ú³xØô??©!hÁHLO·ˆVRH½6w]ê×ðRC´D¤†‹‚Æjó‘ú¯œþã;Ë A~éßý_þõø+�‚ˆÔ†ã¾£‘z™{©ã¦üFà7A)Bj5Ý›©ã|Û~.j„|CP„4á¨þH A‹C꨽Ô/c~'‡ÔÏæóR#ã7AËCj5ÝŸ©c|Û~Í£¾5EJçLý?¿RCP’HýâEL7uBéÉÖ&'üލKý ^j‚–�Ô jz¦žþmÛä¼ðG,'�ÏRö»w@jZ RÇJOQ—zm-�ߨK APú�ú–‚¦éÝC õœ°˜4^ü¹Ó@jZR‘žìeÊöROÉOöb,S#ã7AËBjäú† ©zûHýÅ_õ ASÄc¿ÿò�‚‡ÔãÓ“½˜ì¥Nmz2~C´d¤FØ7ÅÐæý‘ú¿Y®od&ƒ ‰ÒXÞïÿRCЂ�:*=YR¯¥k/utà÷ ¤'ƒ (H�°oŠ¥w÷Eêß°€Öï°�4Yß±oÊo€Ô´0¤ž{/õ�Ô±½Ô@jèÁ¥%|Wúã |ÔÕ•Ej8©!(–~y_¤þ#¾!(ÎPYè÷�Ô´¤ŽøYD+mùÉ"êR©¡û¨°sP |e6^&vœoé?;#­ç�=Gmq]Û&7V­ðxÖ^=Ûµ ±/úIt>RÃI A1õî~Hýs½ýËAÓôgö]ùH A‹FêW³í¥^êVêÉHý*éÉÌvuÆ+Œ~U؆ÒŠû½ãq'oû¥¹è'hã‘|?Š”éº¾w։БžÌ±vI®é‹)›ï{ŽkZŠ×vñ±üm2ZÎü†ë+ˆÔpRCPLmÞ©ÿŠúYO,¢ã¯@jZR�wSOÉø½–ÖÀï—é(¢er<ÛׄhÛ0¬-J‰dgÜÙr:k‡úíÅ�ØÍÆèCô³®ªÔSt>¤6º„´Û6ÃÚDŽ9W2¤>êHÑ�Õ]¾èu†©¯è?õëj“66ÇŸ¦cºÄ:½«³û«‡ÔH÷ A1õö~Hý_”~Ä*BÐtýH¿,ÿ¤† … õOâfüNñfê´y©3½í#õ!¹ËÆÃ!µ~$}‰—rDA?ëʪBoà¹åGjʬU]Cr£$pLï3¤vU#Äó¡VèBÓ›@|Ÿöé<Š¿L:£þ‰R³I?'x¤FÜ7ÅÖ»û 5�ûFºoŠ!mjä7Ö‚î�Ô¯Ç"uŠëR§ÙKÝ!-±¸íY�k µzCêXwf¤V)ñÙíÌÎ9e?þFÐϺºÚ§´ª]ú�Ú$¤ÅƒÜïÄô}LH®¸åGjÁЮÚ°‹î›=BEè÷)!uuô!Ñç�Ôˆû† ØÚ¼Rÿ�%'ÃBP±eRCÐ"�úØE´–‰Ô±‹h¥¤.µƒÔ³+¤¦Ð¶�@¤¾¥ÈxC³¹boý®+ŒÔÃL>ïGêCBD@»f“fǤ£äHÝö9©+‚¥«„ÈÀƒ!—�à“j“œû ×ég«²bHýKüÇ‚âê—÷Aê?QFøkAqôýºü H A‹@ê¨Àï—1‘:!¨Ž��l¤Ö£à;2}¨ªã2(ë[¥ŠÏÛkšêX¤ÖL£ �íW3”x¤£¡fZÔ$Ýi.|EžæH­ùûP Õ÷¯OíºÄʇý¬+¬"ûìø‘zŸ� ñªÉoò¢�oé§Æ�Ô•('5[l­‘¹è¤IôcÚe ¹]1¤ÆVjŠ­·÷Aê?¢(5ÅÕwÓÊha‰ h^¤þ0^]êµ¥z©'»©'ÕК²—Z¿c¹ºì#Á·*?"~I�þŠ/ZìlC€¢äÃ>¬UïXæ\–Ãc�ØÚ%»tÀú‘yŠË,w(ð`—½ÑªæÃý:Fm~©�”Ã&C ›äÂ�øº°Ôa–êþ¤ÝÞiUå>çjôiŽÔF� ¿ï ¶Q¦‡5MϰfVh9‡l¦r ®ƒ~ÖU—©/å-åÁÈêâ�™üH}å¤fû×3ò9½K�`ÙY6WëÉ>žy¤Æ[ (¾îƒÔÿAá+,!ÅÑWôëòøo-©2)ð;-{©çÍø=µ.u[¦møŽØïg…�Ë®8¾å ,}u’SGMÛâºÜ@2ÿ¬-_²í 7|�ey#‘?*Ð/‹—í+¤˜Œj¸Ëý¼Ņ×ÒÐŒœ$�Ö¶|½}š!õ‰œ@_VæÛ—­¶%9qÇKÎÂ~ÖÇ…Ô–ûa›£í¢�CHmúãºÀÖœ�Ç'õ°éGq@o˜Ê�l¬þ²Ÿùö'Ðyö€Ô¤ŽÐ_(#¨XBŠ#•~]þ‚ÿvAЂ�úuŒ"ZQ�ßÏ–YEëyœÍÔS�š£]ØDñEqH´Æ†vßµÁyèi•$jeN�´Å@ìÃC��½Ô©ÛÒ'lÉPõ[«3Ê«9NÇ>¤ö™Œl@Ꚍþ½õ†É¦ÜK<}#½ƒû¼˜"=Þ%YÆH†‚¹Oô£ØÃ¸'ÊÏúx�ºì¬8s£–DꀓzØÊ9‹øg5œ;¼NõªË~g€Ô¤Ž« „„ xbßü· ‚„Ô±¼ÔéÊ÷3=Ù¤^w‚Kµ»ì;l¨Ú¬¥Iá0< Zœ\gĸ.“[³‡ã’$ÛV©-‡’úœ‚ýJÕ8ù³ŽyMF6 µå”²<à˜V©ƒ§o¤±Šð¸Ë­ºúPZºð�…©HH—Uß6Øæò�h?ëãAê×'ßãw`ÑÇA¤ŒqRÓvÎós��&°ÊÒF ò<œä H A@j 5©!(­HÇK½²�ß“2~g}!²Y—ašäœÓä�Ã-lÓs†ÃL�ã ý…Xdºå[ŽÛN„ó‘"R«"R[Àl&Ü/K~µ~–ã}ø‘Úk2²¡©©%‹�ªh»`šV©ƒ§o$¤©ÜÓ­8»®mùö€Oí´)ŦÍ6YÛ'-îÍFûYR÷Ü`vq¯}@jÃï¤>ñÖ–Ò�ë“Z¿@o@ù1üeª»9Ìóù�±“Ü+ ¤† 5©!š ©S›žl SO,¢5ÉK½ë!O†”á£ÉªC4<�Ø�#ÅD…—^vÕæéÉÄ…Hm¸õ4×Á~×ëNO!¤öšŒlèGjÃ3*¢Œ™V©ƒ§ÝºÔRW%Rx�ÚÉ”&{'^7¯8GùYRg\гx’õE�ºé«ÏlD• Ö’Íäµ0wXdF5IÛ@jRC�‚ øHU—:¦—úYRPÍMÅðR¿ŒÈø=ÉKÝœ©)[•»îr'–±îî‡ÔYžÄÛêD!µ×ddC?R³ ÏrT¶µP¤¾;’ÕB£=¸+²ºG�h?ëãAê+ÂÃãy¼{;�c?RÓ{wà»w.`WNO�Å«�pÝñÕý¤·Å'©J’uR©!H A@j‚fCê×ãœÔiÉøýlÞ½ÔS�úŽfì@à·©� 1 ¼N”§)×D¤ŽüöôK1Û¾ÒE—a¤ö˜Œlè"µÅ�Z‹,Þ;sàw ¤ŽV�ûÆ£ü¬�©µL‘­¾z.¦§—ÅFñEû‘Úï¤.y[Ë‘sM~ÈìÇ‘üV«RßIÌÏ+‰šRC�‚€ÔÍ…Ô“¿Ÿ//î;©×î�ÔEBů÷jÕˆHOæGjÝ&w}2dàrèß%Fj{„ÔéÉ<ý®;Gõ(¤ö˜Œl8�†Õ¡LO¶žäÌéÉfDêÛÓ¬H0­tù&Þ(?ë#@ê�Ì9�!¤eä NXò¢�½H]ò;©w½€½Oˆu¬i¬ÜYæQüa:;»òòg„Îÿì,Émù@jRC�‚ ™�z|ÆïiéÉËOö,Ö^êPà÷”ŒßBlE0±,¢Å³•¹E´üH�Ï’r]P¢"‹hå‹­Öa©›r+ó¸"Zž~e¡ç«ÈÀo�ÉȆ×2r•p¤nKœR›­ÎüÓŠ*¢å==3R_ó m:Ù‹(?ë#@j[> Ð/å6rñÉYø±©;>'õ•ï‘…Öqö·ï<Š?LU1™S�Ô$j×8�‚€Ô@jRCPJ�úuê‰:nYꈔߓ�šá`¹_)Rš´8¿+cÛ‚—ÃHÍ /ËZ>=Ö´bîw¹ 9ˆÔ´¿“bÅAê-Jc½c³ÚÀ üÎÝ*æöM4R�LF6,R.L¶Íš!u…ZÊWоpÿ´‚H<=3Rk9Bî}‹vÐâÇ~ÖUÖ�¨IÕ¿±E<»šíòdlÜ.úx”vÝð»ýýQày]\gWÇ&‰Ô=©“ŒxRC�‚€ÔÍ„Ôsz©™ó8U´Ânê˜HÍàW¸ AOa©Y¢ë–rv}‰7ÌDê"Ï$æ 5sO íçÃýîˆSÝf$R{LF5ÔrÀ|/5….ÇRSõA¡×ïDêÀéÙ÷R7ºN¦mlå1}S4wI ÅÌ¡÷Sµèã¸Ò�L¦¤áo�‚€Ô©!(a¤~©—™�,Š©£öRGõ¤Öïl^UYü`V³ìˆ ø%' Yqw§ö�’Ò´i/7jZsR[·å‹F�#uO&‹.ñ Üs§Á~·™M«´OEçí R{LF5TÛìÍŽÙ‘᫺ðTúTù¦Å߇ùñ§»Ì1è"µ;X[z �"Š›¢¦Ö‰évô³B�‚ 5©!èé!õó)‘ßKtS?ÓKý៾e(¾#3¦ŸO¯•ñ©•µ ß9Í4}ìx£ó—~TÊá°fD4š2­f­B±¿¾å;žÏÏ A@jR©!H A+‡Ô¯âdüNÙ^êÈôd/föRC©!H A@jü· ‚îƒÔÁôdq‹h%…Ôks×¥~=ÝK A¤† 5©!š©? Ç}G#õ2÷RÇMù=Gà7A�‚€Ô¤† hN¤ŽÚKý2fàwrHýl>/õ+~C¤† 5A@jJ©_¼ˆé¦N(=ÙÚä„ßu©_ÁK A�‚€Ô©!( ¤Ž•ž,¢.õÚZ:¿±—‚ 5©!RCÐ2�úÈôd/S¶—zJ~²c™¿!RC�‚ 5-©Ç§'{1ÙK�Úôdü† H A@j‚€Ô´x¤ŽJO…ÔkéÚKøýéÉ RC�‚ 5%‰Ôsï¥^¢“:¶—H A�‚€Ô¤RCЂ�:nàwd­´å'‹¨K ¤† H A@jR©!hñHýj¶½ÔKÝJ=©_!=A@jRC¤† $�z¼›zJÆïµ´~¿D-‚€Ô¤† H A GêŸÄÍø�âÍÔðRC‰J[ð±Gº:¥m°AèH A@j‚€Ô´X¤~=©S\—^j( vj�¯ÌÀ&ËÅçEñJí[]rÞá\±c{÷Ú¥æ�^™«mŒ;^YUî�Ú>ØRC�H A@jJ)R³ˆÖ2‘:v­”Õ¥6ÛÕ¯0úUýaFH+î÷ŽÆŠ8ýè\¤E›�®ï�u"t¤/æX»¤×âe]œJDÖ/e[Kž‘“oô£�WWÚ�XÞ%¿RC�H A@jJ)RG~¿Œ‰Ô AuììdiCj‹�ãÙ®¸&D{؆amQJ$;`ÅlÛäÆªœã�Ou奞2>õ!µÑ%¤Ýئk˜]Ìq‹¸H}DH«z6 $'Öt‡¾êeöéǪÅù»2$d·Û¦œE¯²è$Üo.]‡- 5©�Ô¤† ”"õ‡ñêR¯-ÕK=ÙM=©†ÖRöRgzÛ)Fê f—�Y¬(½^Ä*–†Â#jË(å OuõU¡7ðÜò#u“�*[’!¹QpLWœ $RtmÙòŸÊ' &=fÏ/TŠ˜üþцûËËzÄñ*ëŠ�ž|©uI=Yã@jRC�‚ øHý“I�ßiÙK=oÆï%Õ¥î�–XÜö¬¸ µzCêúlùŠòz^Q¢®_W)ÁÐAŸêêkŸ�#íÒ‡Ôk[<¸ýN¸•ú˜®^qK"õ‘\öÅmÍsœ×Z¹qmYÚ_çr¥ðñj«EÎå«3B2@jR©!H AiEê˜^êÕ*¢µd/µƒÔ³+¤¦àµ=ãp¢�Z·¥K4CH‡ýô©>¤R”ó#õ!!"‘˜f“æŽIGÉ;H]&–xö±ÍŸZè¹€³v;±=sPDšuGˆ|,Ð$]-YÛ@jRC�‚ ™�úuŒ"ZQ�ßÏ–YEëyœÍÔ1�ZWŒ‚ïÈôý|×¼gýn•*>o¯iªc‘Z3�‚>¶_ÍPâ‘rŒ†šahQ“t§eȨáñFFc�€ÔEBŽÄ«!,ô;èS}*²ÏŽ©÷ Ùp@¯µ€ã[ºò©õçÙ„Á—ÖàÏB”bÉù˜5É�ÝïueÌñj«â<šÙp?i@jR©!H AéDêX^êtåûŽ™žl*Rëw,W—}$øVåGdÀ/)r[´ØYF ¦“>*ßç©Þ±äʹ,Ç›±µKvé€õÓ[ŠË 6‡‰vÙ­j>ܯcÔæ—úH9l2Ô°I.ˆL£Ã,ÕýQ¿ÞiUeJèê#þ±r+y‰Ä«î%B.ó!Ÿê£‘©/å-e7�¨Ì$‘ºâ†øM:£7¨È>\Ãæ»E,­Æ?j=5êxÅU'6ÿ@ÝŠf’*„‰º¤† 5©!‹Ôq¼Ô+ø=9ãw[â¢møŽ˜KJ¡¤ØÇ·œWZÎ/ýœ:jÚ×åâ�틵åK}Ã×Xæñ�Ò�~5KžlUH0Õpש4TlíXš‘“T8ïrmG ŒÕ‡Ô~Gõ� ΟkЧúH‘Úb�Jœ'æÃ{�ºèÄ„çóC2à1îä­–Ä»GeùÆ@�8^q9(í u‚Ú#õ�‚€Ô¤† h*R§6=Ù¦žXDk¢—š"ŠÕ7—ܧœÏÒ£[s�¨¥qô%¹[ÓìÑ4¡kJ"Þáüsqfž]6eÌ:(*ŲÍ­XÄ®T©YѪӢYm‰,K�~iO»ë•Ɖsõ!uÈd¨a© ÔÄ]©Dguîqªù¦¥UÖé +-ÚH`¬ÜŠV9£Œç¹„kÝÍEÑ�„}ª�©sdW¾jpâ{ècRWÝÍÄÌÿÌ?¬]rPÔŽÛ♉Γd*JÆæ�v‚Ç«.­Ë£èó4iÓj©U 5©!H AP4RGÕ¥Žé¥~–TsS1¼Ô/#2~OòR+²*Å&Š3ŠC¢5Ž4ô°ëø® ~ÈA±ÊŽ ‚ºóZ™Gë¶¥[�²K1åî¥HÝ–°iÉPõ[«XOjŽÓ±©}&#�º&1÷Ö µ�i÷Rû�Æ:a/µFH�c†~DX« Oõ‘"uÙYq(_zøcR�;o3ðΧ®T–ß3†Ð6‹XÈWlv‚Ç+¯#2T½ÞûµÃI ¤† T õ_("¨XBŠ#•~]þ‚ÿvAЂ�úõ8'uZ2~?›w/õ¤^'d]ðá]öŠ „QmÆ„”5…ñX0h]pr�9´iÓ+§¢%I¶­0R[5õ9û•¢À«³ŽyMF6 µ%ro³Mï$½Ó ¥'ó ŒuR­ Bã«<¬|#äS}¤H}BlùªÇ׿¡�=HMoTß}|±#böe[‘û{èn‰ïó\ßÁãU—xJc-åÓT˜º“H Aé@êÿ¤Œ a !(Ž4úuùOü· ‚ŒÔ“¿Ÿ//î;©×î�ÔY7ݲ<’ÿYn²’¸}ïĉMÏ™Ž;wôÇ~‘é–cOÛÉ,u$ɇÔ*ñl2΄ûe)¶¯ÖÏr¼?R{MF6ô#5µdñQmÔBÓ !µ×Hp¬¤6šR<€ýœ%B«w é0ÈúT)R÷Ü$bâ^?ô±©5Ç)Í>)}~£ˆ ö쪖ë¿5ùg*x¼êÒÙ3 s”J/QmLóQ©!(Hý”¾ÂBP}E¿.ÿ�ÿvAЂ�z|ÆïiéÉËOö,Ö^êPà÷”Œß»òdÄéqn0ô­:„Ãóˆ Y´mŸ…5©ÍÓ“‰ "�ÚpÈY:ƒý®×�žBHí5ÙÐ�Ô†gTD3­R{�Ç@ê¢Ó9ßÜZ9ç¯s�ËZô©>R¤Î¸YÙ,î)~ècRçmr"Þ8ä�+Lâ!0¤¦÷eà^kpú¯¼è÷GËRXŠquCzª ê<ðÿq� ¸z{¤þ#e„ï°†GßѯË�Ô´ ¤~�z¢Ž[–:"å÷$¤n΂Ԕ­ÊŒ]w9‹KˆXw÷Cê,Oâmu¢�Úk2²¡©Kı­ØHí52©Í#)®×'µ~!_f}ª�©éRˆ�âE‘ì¡�½HÝq¼ÎÞ¡Û|;[ø!¿§}×�»Í—9~ìAê¼1”çd®±’-�s†ó,ÇÙЯG¯º $Ͷ?ÃfjzMÙJ=©?û/ ?b!hº~¤_–ÿBjMZR¿Š“ñ;e{©#Ó“½˜ÑKÍ�±Ü¯)lZ-‰•1‹mÁËa¤6¬ˆâY=Ö´bîw¹w7ˆÔ´¿“bÅAê- B½c³ÚÀ üÎÝ*æöM4R�LF6,R\.L¶Íš!5 øÍWоpÿ´"�Ú3¯ÀXåp(Ùä¶�€`Ÿöw¬i‡¶ÃñŸêcÑK¾–Ï÷olÁ±j¶ËÖ«Y‘çú˜B¶Å+Ãâíî‹. 80[îgú0ÇŽ‡Y}Ìñª«éY)¤Fä7ÅÔæý�ú¯,áV‚¦‹%óû+�‚…ÔÁôdq‹h%…Ôks×¥~=ÙKÍáW¸ AO‡a©YHsK&ˆr|‹7 ƒHÍ3c·¤f._¡ý|¸ßqªÛŒDj�ɨ†ú@˜ï¥ö¸5›ª ½~Ð0R{ŒÆê ‡çl§Ö:ŽKtGò_À§úȤ¹KZ(f½Ÿª‡>öÊ8Ë{?ÅLÃÛV7Ï2Emü1´4¤Fä7ÅÔ»û!5�üþ3–‚¦éÏSã¾�Ô47RŽûŽFêe›ò{ÆÀoJ w,–Ö>A·j–GÖø%'k²âî$î�pQíåFMkNRí¶|Ѩs¤îÉdÑ%NŸç‚¤ƒýn3›ViŸwf›Gý<ä1ÕPm³7;fG[_qøµ«¾ý§¾i1Ÿôa`¤æTýK`5åßþr6žž ©?ûì7>A�_üÍ,ß6‚æCê¨Àï—1‘:!¨Ž�� H AP:‘‚ 95Û·í‹¿þ ‚ý×_¿˜íÛAÐ|Hýa¼ºÔkKõROvSOª¡…½ÔÐ=¥ê‹¾TÇ–¿U\€¥©UÿáOü�ÿü h zÊúËþÇÿô‡/fþ¶A4·—úu ¤^î^êy3~£.5tÏïG¯Þvî â¨}à¨!ÞÐ25ËÞÍ»í ;µÈK]ûMÛj÷Ý·Õ¾Õ%çm…½>>©�ÅWÏvmBì‹~:Ó÷t (¥H AÐÜß6‚ê¥^­"Z)ñR›íêŒWýªþ° #¤÷{Ç9ÏÛ~iÚlg_ŠT¨8$\­ _8âj‡ŸÞ²äaOÞŒ"EÀnÔ¥®¶å-ù¹ÔêâxhЃ>ñHꛌ–³Ãu 5©!RCPŠ‘úuŒ"ZQ�ßÏ–YEëyœÍÔKFj \3¢ë5!ÚÃ6 kËv‘pNÔ98�‹ºÑæ/oÈé´Ùξ© j ȵ³í Bl¶ÚB.:B·ì´’#ÄêUÛž¸Wõ”ñ_7êRGYúöåv–rôP¬á¥ëêÙ€�œB/ê8©�»t1­Ó»:û·¤† 5A@jZq/uºò}ÇLO¶$¤Îô¶SŒÔ”òr—�{Lï��¢ð°Ò®X|²©�É/©•^Ï|¨V\'¤ËF­žÂü¤%Bïé>!5¾•¹¡w£B'ynI¤\*¥ÛÄfîèü>!YþxB"÷©ÿ)‡BÈÑÿËT° 9áŸq5K™ÚRC�‚ 5­´—ze¿—‘ñ»CZbqÛ³:×@jõ†Ôïçu�Zm2Ð]¤–³u&øœµð3^röP­8‰ØÑlRv¦ÿ¬\Ç»¤+nÂ-!‡“�´K�ÔÁK¥(”߉W6)K'5LaÈ©ÜQ›�§žà”�º“š¬FHH A@j‚€Ô”z¤Nmz²)L=±ˆÖO–ˆÔ³+¤¦Œ·}¿é9H}@A‡C�@ê{O>uHm¶ZÒ›OÈ.'g;àz—ÇEBn)R3ù¼Dêà¥y·aƉà×–‰%(}Û눭ÀI­Ú$ç~Âu‹� �‚€Ô©!(•HU—:¦—úYRPÍMÅðR¿ŒÈø=ÍK­+FÁwdúPU3 ã.Ü*U|>KÓTÇR¥f}l¿š¡Ä#å 5ÃТ&éNË drÔwh¬£‰ù�:Kˆ%:�©½ýÑ‘)÷¼+ªáÜ/,ëC�¾$>R»RŸá>±òªY,x|ɆçE‘}Ô.�ôdþKGGMÝyÁFyãÄ{ÞQÁIÍÖ£9:Êòg@jRC¤† t"õëqNê´dü~6ï^ê©H­ß±\]ö‘ $•‘¿¤@ÅYFg»!|»YqIŸ¥z—£§rYŽm5bk—ìÒëGæ).çó=2x°Ës¤™ 5 u�š¸+•è¬Î ¾ ÙÑ´´Ê:d¥¢E ŒÕ?1/RSÄuWÖƒÔ£É+.jýÚƒÔ¾þ JºÙ+cÛ&¾þg¸+Z—œÕ-Ê_u:µ3j‹MM³ÉMÕ0öi¿ÁKF­âG†ò«ˆ•ÙªdZ²hV^9•´¦F#µ{©ë€?,Ëg1ùD ä>Û°F‘—OþÓ™/�€.IH A@j‚€Ô”v/uz‰:nYꈔߓ�šÂ–]�nÁ";$ZãH»Ž—Ôà‡Y A‹ÒåÛˆ5ÊGÂeÍÝ–[rÿ§³�ØåÈm¯ôP¿µú€õ¤æ8Qù�Úg2²a©k2ùÕ­7L60­à^j¿‘ÀXƒs‘z{è Õö up/µq#œ¯îRxû;‘ãeh½=×]Y—“©ÖëÚh—´Q¯ów·¹§3pÉÌ{©Û)Ö"e~w”–¸M•!­Ë^3纭H=ºÔeðaç´mÉ15Fçm7�ÙœÔücêüΩ!H A�‚™—š9�ÓQE+즎‡ÔëNp©v—½bGoT›a â¤j>ØV¨Xg®SÚôÊéA€hI’m+ŒÔ–ý}ŽJÁ~¥j¼@“?ë˜×ddÃR[N�±å!àÀ´BéÉ|Fc NÌEjîš-LGê�sI¡.R{û³�ñ^{‘z–»²îó^a¹À±,¸à3"u¡ìâœé¤R;›Ûç}¡.žV‘ÚséÈ÷jm±™^�ÚpŸLhnaj8©åzœø®€Ô¤† H Ai÷RODêef'‹b꨽ÔD=©³<0Øs$q¶IÎ9‰Ý9ˆÃ¶íf8d8<Ñ_ø‡E¦[ŽDmî«æþE;„Ô*ñ$u΄ûe)¶¯ÖÙ[5ˆÔ^“‘ ýHM-Y|TEÛSí)0­R{�ǜة»!}Rë»Nܳ‹Ôžþ×™~åEêYîÊÊEÕŒÈø­ņðÖ|6¤f[د#Âîx‘i¹Z2t €Ô—î"Dló]ÔšûHÀtáú$�£’WÝSUl#Ç@©!H A�‚V ©ŸO‰ü^¢›úùó˜^êIéÉv}u†›îQ�A�â¤ÅÞ’yĆŒÏú„(¬éHmžuK\x�Ô†[ÿG8"ƒý®×�žBHí5ÙÐ�Ô†gTD3­R{�ǜة‹Œ³Ó�:ëfßrÓ“yú+ºl[ð"õLwe]8ÌOMRkm'9Z6¼à3!µÚ ëîlQk{µ=pïÛ©½—::)ÚBŸrGý‰»¨EçaœÔ"¦ î‰Ì¨¦o„øéA@jRC”Ÿø�Þ½Ô‘éÉ^Ìè¥nÎo–ÊŒ]w…³Ñ"ÖÝý�:Ëó_[�(¤öšŒlèGêq†El+6R{�ÄFêK‘¼8©=aÙQH½å"gɋԳÝåÚr3x;°\᥹ÊÍ{#µ>ðD–o¹¼Ëêh?¹FjߥŽrÄÖݵ9å«%÷M[ÎS�&œÔBtiÚ"¦�.t �Ôø‘A@jRCôR¿œ±ˆVRH½6w]êד½Ôwn®dÖ@ˆ±ÞŽ)ýŽeýä;©#¿=ýRtµ¯tÑe©=&#ºHm1¤Ö"‹÷N üö ~�Aê¢àÊaeRSè®ë�:o;[¾«^¤ží®°¥9dÏ #X¦ð½³!¦sO¤n» Ât!÷�,޽´£²â¬H+@jÿ¥y£Zà�>$…ku1ŠŒLüÖp|²%'›ø“[¢:½�*]Éó4>eÀO/RC�‚ †=†ã¾£‘z™{©ã¦üž1ðÛ­ ¬U«FD",?¼é6¹ë“¡&ª4©mG†Ó“yú]wŽêQHí1Ùp «C™žl7<ÉiéɼFÂéÉ& 5ƒFK�@jÙT+{2˜E"uS®?sxoÏyW\ö!gÜŒ˜…­Êž¢‘:nöèsKé|QìuM+Z26»ÎŠj™…cVJ+@êÀ¥&ÅB��ˆ\ æYK–æVÏé5½è¦ß…“Züa:;»r?ÿ]³ë³³�‚€Ô©!(í^ê0S?OIz²µgóy©§dü.P$R$ŠrM "µ3ùmÚS…K‡Ô¬€6×�©g¹+–ä\Óm¾G™ÂxnÛÐØÝŠõèôdN«Ù‘š‚ž-²¡9ñìÛ»vÓÍMMg6ŒºT+ËxîÊ€waeUy�Á÷‚çä®lì¤ö#uÏEêô=iÀO/RC�‚ ü éÉ"êR¯­¥#ð{î½ÔœÿDÊhCà�|ÓŠ@j�‘ÀX§ 5£�®@jgò¶K”ñH-u¸¯ù�z†»¢YŽ›˜o�®‹De¦´=ˆDj§Õ|Új4¶¼Çªy¬Äºpt_ W†÷öä�³Ì±†?E+'üô‚ 5©!Ê‹½Ô¡ôd/S¶—zJ~²c™zJÆoʤwŒ¾ìAEj–³Ø€_Rp2I)îFÙþ¨*’ÚË�šÖàlË�:§ÊžÜW[bé³È¹»`¿Û̦UÚ'Dç®]?\yLF5Tyµ¨ŽÙ‘É­®8.ÚU²ù¦Å|Ò‡�Uðñ�541®ue-ßgé»<µµ3[9ùRçÜ“áþT³hªlMªóÝÑtØsSvr–+lº=‘¯-t#�V¤† 5A@jz¤ŸžìÅd/ujÓ“Å üfL¶e(¾#3¦ÃP¯u¼OrÃwN3 E×V1 ñLF6¬øc˜5#¢Ñ Óš2Öx=l¨ñ>|¥’0TAúìwE3*£áª… ‰êæ„18­ H A@j‚€Ôt?¤ŽJO…ÔkéÚKøýb¶ôdÐr••{¾•ªXH A�‚€Ô´’H=÷^ê%:©c{©�ÔéUá†�r;{Ùõ—p† 5A@jRCЪ uÜÀïÈ"ZiËOQ—H�bÏåvëk¬¤† H A@jZq¤~5Û^ê¥n¥žŒÔ¯â¦'ƒ–+­_ëÔÛU+©!RC�‚V©Ç»©§dü^Kkà÷˸E´ ‚€Ô¤† H As#õOâfüNñfjx©!RC�‚ 5-©_�Eê×¥†—‚ 5A©!hÉHýaÌ"ZËDêØE´æ¨K A¤† ‚€ÔÍï¥~¿Œ‰Ô Auììd@j‚€ÔA¤† d½ÔqêR¯-ÕK=ÙM=©†öRC¤† ‚ 5-ÐKý:R/w/õ¼¿Q—‚ 5A©!hé^êÕ*¢/5A@j‚ RCP"Hý:F­¨Àïgˬ¢õ<Îfj 5A@j‚ RCÐò½ÔéÊ÷3=�Z„´{¤ëXn 5A©!hõ½Ô+ø�ŒßÐ}TØ9¨¾2› /vœoå©¶Mn¬ZAž(¸âÞvÍ3mËnf¯Áº×öå«ìA[>VÈ€ÔA¤† ô"ujÓ“Maê‰E´–é¥6ÛÕ¯0úUýaFùX‹û½ã‡�iЗª«�äûQ´ éúÞY'BGúb޵KzpÍ_–†â”- »G\1´ÔF‡;ü¼bÉÃëÕ_x‹ Å‚°Y�÷€ÔA¤† ô uT]ê˜^êgIA57ÃKý2"ã÷2½Ô”pfD×kB´‡mÖ–í2ØC=9ðùRójßê’ó¶²úßõ”ª©�.!íÆ6]ÃìbŽ[._Q¢®_W›.S^»#´Ën~…� y|Ëê´“‹ÞöÁð10uÖ™4{ä°ïÀõ MCÄO/‚ H APÞ_Dk"Q/3ðûÙ¼{©—„Ô™ÞvŠ‘ú‚�Üec† ”^Ïô¿ð)èKÕêâxh¬ú—£Boà¹åGj ¸,ô@’eÇô¾’�@bÝ–,™!¤Ãmï’¶oá ñ=¶èÓöÌ‹k ‰µò˜®_¢]‘ºˆ äH AA@jJ1ROü~¾¼¸ïH¤^K/RwHKºoû3^™R«7¤>[ø,¥›3ÿ ßÙ /õˆ�VõŒranÕýÔû„i—>¤6éäxPû�p+?ô1]µâ–@jJ�GÂh��¢xDsçÞ:!º?(B|ìò—Ö^É�!iòÜk¯Ée¨©WMïò_ýÓûï¾}@}÷þŸ¾Ê¿ƒ]¿6óþûþö÷Ôß~øþýo6§Îw3¯j,5¿ùvawv! 5Ý ©Çgüž–ž,±üdÏbí¥~/)ã·ƒÔ³+¤6÷ßà uÈ—jb³¡�>ltùR�z˜a|êEêCBD"1ÍæÈ÷ÐǤ£ä%RW i¸îèKö¯í÷ÒÞÛ7Üí}'pú�:ß§+„ÔYá­T�?½¦kó«¥Kg~µ »#ýú»¥iW÷ë‰óÍk R~va7i»�‚ÈK�^¢Ž[–:"å÷4¤Ö£à;2}¨ªãr ë[¥ŠÏIhšêX¤ÖL£ �íW3”x¤£¡fZÔ$Ýi.©M^—Š¡ÆAê�/õH6* É�¶Ú_Ž¢™"õ>!òµp|K?%©ïÜ´\áçt†–…+CwÇbåU³ú€êå”±ç\ª–¿Oˆbó‡3tj@êÕòPyõíÂtõå;Ø•òõ‚€šCõ×c!äÝ[m�zûva7I»�‚–å¥fÎãtTÑ »©ã"µ~ÇruÙGKT~Dü’!·E–BÙnß®HÅ~ãYÓ=•Ërì¬[»d—X?-±•¸Ì s((v—½ÑªæÃý:uò!Z€IDATFm~©�”Ã&C ›äÂ�x±ÝÔè0Kõ’o’ÞiUeNèj°� é{Ž�z—6²2ÂûÌÕp_ÉÇïK-K0ß¶‹„+-?R_Ê[Ê÷øªÌ$‘z��ŒûØ‚ˆOÎú ûÔ�\É+švg­ž/¿za7*>õþ2‰é ±è"µÄGôH½R.꯿]¨Æ±ÞS³ûëÿûBõïcÕ›ª¶P©›° »ÉÙ…€Ôôp^ê‰H½ÌìdQLµ—:‚¨§ u[b¢møŽ˜/X¡„ØÇ·”¥ç¯Nrê¨i[\—ˆC¶/Ö–/Yî _c™¿KHúÕœÂG­JÐùì7Õp×ÉCUlíXš‘“T8çr9±ßêP¸þN‰ØººÍc†zf#v^Ÿ¹/|+ô¥ê7N¼·ñ(È.€Ô{Tâ<10þ؃Ôt=뜕õ#±›˜BfNÜ‚.gêq>XÇq]êtZ´Uæ1üi²Y~oúù¼Ë7ø&êìüù€ÔËÐÛ÷ß.XïßÂ.ýüÛ¿/X¿�ü¬oj ×&ìÂnRv! 5-©ŸO‰ü^¢›úùó˜^ê‰éÉ(Z}³qÉ}Êì7»uk®Sµ4޾$wkš=ú�Æ#tMIÄ;œ.Î̳ Á¦ŒYE¥Xæ‡JÅ"v¥¢8HÍŠV�ÍjKxýÒžv×+�±ó؇Ô!“¡†¤.Pw¥�Õ¹'Ø7-­²NY©¸V‚éèЇŒßš¬GÍ&7UÃØ·YT²V9£ˆG¯p_ø–0èK­¸¸^p½ì�©sdW¾jðÐ�‡>ö 5KÍ> ‹­òG"b�/�B±&Ÿ™Ðóvf«’¡wý`t7¨j�!:€~«l¾×À`nÝÇF@êUñQ/œ0)cnÂî¯NÔ”©½ò‰dØ…]05�‚ÒŠÔ¯âdüNÙ^êÈôd/fôRSVµ ›(Î(‰Ö8ÒÐîã»6ø!Ä*;*êÎke­Û–~Â-éêuöR ¤nKÈ4‡<áR ßZ�aS^Íq:ö!µÏddÃR×$ÞÞza60­à^jÚ¶Àݰ‚_ú�ôXØw½!§,/ÔĽÔA_jqž;LWáAê²[ŸªOHéá�½H­œ³ ~‚ßṽϜ"Rû„Ý¥|‹”ù‡Ei¹Ÿ3›­í’™Ð¥R öD)Kl�}¼,Sý�z…öQómúúÝS·»ùïO@ÿb�wj裾ƒ]ØMÂ.¤† õR¿œ±ˆVRH½6w]êד½Ôë2•p^»Ë^±#á&TyÈ)¥Lá@< Zœ\g^]ÚôÊéÁàp\’dÛ #µåPSŸ{�ƒýJÕ85ù³ŽyMF6 µ%ëÓMï$½Ó "µÂ8C¬†i¦¯’v�pŠ™\D+àK­ºdH‘Ïzß?RŸ¸Y¶{ü<ô±©ó•sîtÎ5|ǵfîʲÛm:ÉêÎ\·øN·F÷`…µÁž X|þ5êW©›~zMÒ—ß&¢/ŸºÝ¯ÿžˆ¾…¹k‰è-ìÂnv! 5Ý©? Ç}G#õ2÷RÇMù=càwÖM·,�$Ó4É9gMá3…s0Ã�¸ÀqçŽrh‘é–gõj;™¥Ž ù�Z%žÍÅ™p¿,øÕúYŽ÷áGj¯ÉȆ~¤¦–,>ª¢í)¯˜V(ãw™ o@înY_UþÍPÛ(6¤·;„ÔFS*ö¥Žâ—ó¶Ôüx�ºç&÷ú¡�}H�×�ë“Z¿@ïQÙ7¦÷*籈Ï�k¤-7ö|²Èцø°Ò¯Ji_ÕR¯HØ÷wÉ æw›OÛî¯ÿ– Rÿ-úýNKH›° »ýRCЪy©ÃLý<%éÉÖžÍ神’ñ{×WØ·éun0N©:„Ãóˆ _öyú®&©ÍÓ“9¨FjÃ!g#½“õ»^wz !µ×ddC?RžQ� ¦BêSÚ‡>$%…E€„{[kËkÑH]tŒœ†}©†LîL÷‘!uÆÍÆfñ$ë}ìGê¼»’, ^¡âÜÔ6»ûº»­]áwBUqº}­²²ÄnÈïƒMî:ä$eãÃO¯ R¾KHÊÓ¶ûþo é}àWwR蓇]Ø]¼]H A‹Aê/bº©JO¶69áwD]êWñ¼ÔÍY�š²U™±ë.gqb ëî~H�åI¼­NR{MF6ô#u‰8Ã"¶©)o”HN§L—¡èÂx¸Âê€Ù勿¤6�¤Î¾TMìó®Åþ£CjºgÙÚ 8ö uåôTáïˆ[v@†šY0äÍäŽùÿHݰüyñÇ„Ôå³�6±º©û4á§×„�ÔIæwïß=e»›J ©ÿôn)ÎDMƒ]Ø]¸]H A„Ô±Ò“EÔ¥^[KGà÷Ü{©ïxj®‘S,øíGjú ß,l Ôó™ˆÔ�ßž~)�ÚWºè2ŒÔ“‘ ]¤¶Rk‘)¶§~k]²~Çv¬öȑɫ1öÞañꤎ–ô¥ÚŽ7ñпÃwÅ‘ZËÙê«ç­¬—Åìú؃ÔZŽœkòsc«‚ºïW9Ûa|!“ë,~Ût[äÌã·ü1äZWY�0á¯ç™Ì+@êÕùQ–b~—Êv¿ø[búMâi™#"tavù ¤† ´"õ‡éÉ^¦l/õ”üd/Æ2õ”Œßnvj­Z5"Ò“ù‘š"Ë]_8 ý©’ÂHm��:"=™§ßu稅ԓ‘ Ò0…� n)Â99%=ãòÓ †ÊW$WÏ,�pl}$Rg¤U<ùR;N}eË}¾úH=�s§8Û2ò…"ý§}KÚ qŠ´©W"9YrˆùåS¶û>9¤~¿”øÜ@„.ìÂ."¿�Ô”b¤ŸžìÅd/ujÓ“Å ü.P&QË"Z<[™[DË�Ôù,)×Et®"‹hå‹­Öa©›&ÇÑòôKá|_ÒjR{LF6¼–™Ç«„#u[²—ÚluÜ.Ó #5åhî­×sôÅŽ€á¯×%¿ '&Ù'�|ÓA_jFVk�G±¡×Aj[Î]¿”ûÈÅ'çÁ�=H­uœ=ëN˜ƒ³Ã}Èèè5çüOÜ%’®óýæ£øãD?Ö¶ûÜ'üÑR§Wÿ”bþÓS¶û}rHý£×®žúè° »‹¶ ©!è!�:*=YR¯¥k/utà÷‹ÙÒ“1$-÷+EŠ&çWbeÌb[ðr©MF+¢xV�5­˜û]îB"5íï¤Xq�z‹‚PïØ¬¶ð†¿s·Š¹}�Ô#“‘ ‹—‹“m³fH]¡–²Ç•â…/ð×?­0R›òjæˆm:»Áq¡X—éÉ Ôô¶¡y^xô¥²P欦íÇ÷Ív0óƒ[äS³]vSšNòCóOˆ¨+­‹SvÕ=#2ÔÕ�‰*glûÔI…�±ØÇãü²ðHþ8�2—WGåÎ�Ô+ o’CÌož²Ý’Cê¿zíªÉ¡� »°»h»�‚©çÞK½D'ul/õD¤Î;~>�K^‡a©Y(sK÷ûoŠù0RóŒØ-©™{Zh?îwGœê6#‘Úc2ª¡>�¶Ž¥¦êƒB¯4„Ôùs¹G7C¤uSzCÍ9È�y_xÝÔ!_ª3ˆ»GõMÑÜ%-3‡ÞOÕC{¤™LÉû‰Ð®2WÞ{»Õhly/P�ãþª©—­÷É!æû§l÷OÉ!õŸ¼vµ»°»h»�‚©ã~GÑJ[~²ˆºÔ“‘Z¿côhŸ(ÒaÈYrÀ/)8 «wq„‰j/7jZsâSÛòE£Î‘º'“E—8už ’ö»ÍlZ¥}VÔ9¿Dj�ɨ†*¯vÕ1;2Èúª.Üšª³¼Ób®¿€¿¯- 9Ñ‘Éxñ ë¦Ûsò�);9AÒî ß}©†Å‹jõñí‚€ÔOSß%¨§l÷o ¨»@j 5A±�úÕl{©—º•z2R¿Š—žŒá–¡øŽL-ÞÊ飢Ž÷inøÎi¦¡èãÚ*FLÇbdÊ?[3"Í0-ÃGEŽùaa#ðb¢/Õ8ËkørA@j 5�H Ôƒ] 5�‚žR�wSOÉø½–ÖÀï—ñŠhA©�Ô@j 5ì©! 5Ý©7ãwŠ7SßÇK A¤R©�Ô° ¤RC4?R¿‹Ô)®K /5A@j 5�H »° ¤RCÐ’‘úØE´–‰Ô±‹hÍX—‚ H ¤R©aH ©!è~^êPà÷˘H�TÇÎN¤† H ¤R©av�Ô@jJÖK§.õÚR½Ô“ÝÔ“jha/5A@j 5�H »° ¤RCнԯc õr÷RÏ›ñû�‚ 5�H ¤†]ØR©!hÙ^êÕ*¢/5A@êeé}‚zÊvÿ” €z° ¤RC4©_Ç(¢øýl™U´žÇÙL ¤† H ¤R©av�Ô@jZ¾—:]ù¾c¦'RC¤R©�Ô° »@j 5-ÝK½²�ßÈø A�H ¤~0¤VìÂî¢íB@jz`¤Nmz²)L=±ˆ¼Ô©�Ô@j 5ìÂ.�H A B꨺Ô1½ÔÏ’‚jn*†—úeDÆox©!R©�Ô@jØ…] 5�‚‡Ô¯Ç9©Ó’ñûÙ¼{©�ÔФ.˰Û²v¿ h÷8›øòêY#Ö(•ÓÎàL»¿EüôR©�z° ¤RC”Ÿ¥.õóåÅ}G"õ�Z¸´LͲw³ÇAª½½»Ùpß0ö›¶ÕîøÁÎÁHëô¸8:ä$×v� ;5úϱçÂv´ý�^™«=‚ÇÆÁA1òRs`“áÅa䈦L€©Ø±‰½{­F^îëÜ…ZzÖœ¼nã–/Bw;º;¹pÔ'LUÿÍÛ¶rÔ̾ÿO€j³–­û35~z©�Ô@=ØR©!Êû¿_Íœž,±üdÏbí¥~ÇÌøû×õm¿·©Ñ¯ê)¡Â~_;ôbü=EmYD¨ç»™ú‘|ûR~t¶åq‹Úrd¤,=î�²j£Ãy(åu].”Ò£ìNß}ys/éëë¨K×åë#=bDS&@\Ê7,%ârçÎZ éë×mÜòE‰öp缦£S¦|ÈmR­´IËûÞñÐsÆûv•X=ÕR©�Ô@jØ…]H Aí¥N/QÇ-K‘ò{RG{²Æè†œÆ]ØkB´tÜâ,±ô±C¿%¶†oÁ8)”%­^µMÙìÀëçb·3;ç„ ä“îåv¶NÈ�}ŽŽ:R /‰-ߨe‹]!äBßòîNöu¹gØÑ�sqÈ~…¾Úíß¶iû3NØ-"‘:x©Ñ%¤ÝضF4mùü!¹^fŸ6oéá ù;—ê©Ç¬Û¸å‡ÔĈ�Ô…:®¢©‹´û´zJ'Ejž÷Ïv Öû�H ¤RÃ.ìB@jZ²—š9�ÓQE+즎�Ôc‡ -†xž+¶ˆ6±9ýíû3Ÿ¯Â>~»¤í}·äÄ íåÜâH=byBŽ¢ìSÝÏ ¦-ëüCF©ƒ—6E´2$7JhDS'`ReuõˆøÜ¹rBQ�gi:H=fÝÆ,ßx¤niq‘:/úëùüÖäˆ_H¿ãżÑä:á‘ìgñíÄO/ 5�¨»@j 5Aùi{©_¤#;YSGí¥Ž ê)H=Γ•B¤îø£Zc·:!“†Þ ¤‚¯Áí’®æP gßð…³f….±#Ëe›”ÃtKéðÎÛ뺈Ìv´ÏÐïÒ�Ôm‡Åýö)é–EZ¯ë\®”Ï’+n�Z\J[¶xË;åËM�À‘ô‚çµVî$tyTç…!±®¤ŽX7}«TÑ£—oz¹½=tÁ¹Ãé°èÚ…s�Œ)§Þú½´ÞFùýa†Å†{‘ºâ²¸ß>EK_Â/ÒQò¤–—:,K?âÍЈ¦M@Ï‘zÔzÈË£:ÐS.R‡ÖM½cÛ±sY5jùÆ­½Uv¾“>¤.Ð>eÆÛšža©Æ,¾ÈÚ± žëmÒu¿úMz}¡(¤su?¤R©�Ô° »�‚ ©_ÅÉø�²½Ô‘éÉ^Ìê¥z²„?M1Lm R‡Ú„œf©#°J¯õþô×L£àËádšžúBC‹€e-Ðíè’Ro‹”XãŸùò#¤áÁo ûQÉ·¸7W!¤©K/n3 Æ:#Í•¡»ni+¯šEçCPdŸP?R;,´ß$Cvó×�»K» µ¼tŸ� '[ÁM�€AÈ6=(–ü•®œ Et^dþj©CëÖ–.âv”õqH]7dø¹©éeî´£}ñ¯½E¿(´½÷ixoE¡TÒ|áü�<�H ¤RÃ.ìB@jzx/õË‹h%…Ôks×¥~=ÅKôdq¯±30åïrá&»"Þ É¾6cœf ©oÙayÝÔüZûH•±Ëó,WåNU[»d§â¬VcçÛ:‡¦²kÝmü—xZ9ªËØZ9t#Gr~Çà™Ä7(¬JŽ Z¾RQ Ï ›'boó)û0èKÜí)�|)W–~BÖO˜“öäJÞæ¦ø ôTOÛn]Cö[ÄÒjü�.õ#µsé%ƒogû³Ñ´ ÐÏD±È>Læw³³sy¸s휅‚»H7Eâ‹3óì‚“zØú8¤f_¢AR“V£rÈ–0—©×Y'*ín³ÙÔ<ë1I2ô:ÚòH ¤R©n׬ �m�Ô@jzÔHýa8î;©—¹—:nÊï¿£E#Î^¦“m_œË d-#*ŠS‰¨Éà_¼/’:‰×•Ð%£Vž(Ùš©Q¡Èð}Àó) …oXµ+¯ôÔùX˜D‚Û™,3U.úöÒy!Ow¯DŒ´s×z$R_ºO9ö‡ä¨¼Ô�Ô#h.�ÂÌàˆ¦M JÈ�´3,…'î¼Ç�¹H7ýZì_­Ì ¤v/-»¹´ûòsèCõ)Ⱥîãì(§÷èòPçu’Ûð"u`Ü”Ðyj°[‘,h}R�Ð5d(Ó·óûzFêÑ¥'î~åž ßÏ®ùÉ KdÃQîïÑåÁÎ32ÂAêปd¤vØú$¤Îó²Û©)�s²vÁ–N~?RËV™ÀR§©t—Úþÿ>ùôc¦�~ÞN©�~ÊÍ~üi{%‘ZOP+n—ì˜Oh¾+iRCÐí¥¥'{™²½ÔSò“½ËÔS2~‡=YY—?šä| RÚŒqš�ún{òCeÝ\É=ܸWƒC‰ÛRdáf1ãµbDÆoͼZg›_ÕÐ%!¤¾s{Cšv¸º¯?ÙäWɽ?2&À=ÜhîŠ, ÁÊ0;{x·Ý:ÌÆÈ%<Ò�ç£ ü­wa¤>q+K…ì·\ª5ÝK½H=º´çZr3ºûG4q™RŸ8y.t®Ù¤UÙ¢jÒg»‚ã¦Ý[Bĺ [ŸˆÔ–1Mz©ÞOAjÙªè¤xR§©o?¨—Úžüldõ§ß'†Ôß¿™Í}ûø‘ZÕ!»ßþÔgöÛGŽÔÇ7¾?­LrÈUêtG†ËgÉ£‹û¾~ÌHý¿Ù©-R6´·››ïÞmn¾Õ6Æ sœ6ôdÓ“E!õZºöRG~¿˜-=YØ“µh¤n΂Ôy½xÄ1ótÉ,gù�«©³#/5Çs—2TEw]§ðR�ÝkßwÏC…·§YÝÙ·[æÁѶîöŸ:·ö`ä›jÎ&ä!gଛܫBjº†ì÷Ý ¶ÝS¤ö\z%ËO±Ïx;4¢iÐm¾·_lg°C—:!up܇îvîHë“‘:/çû2~ODêѳ'©·Úrï�:}3‹BH��éò¹í~S1ßåÁ…ˆþ¾HÈnYºÅ.|äÿ뛹í®Ro IP‡I!W±ë7\LõXÜ÷ÖcFjHý˜‘ZËoŽNlæµ(ŠˆÓ‚°—zÚ^ê%:©c{©'!uØ“ü>ôî±ø=©#¿ï|Žâpà·Ÿ�Ò˜Ùœh%a™Â·}¥ XŽ�Ô”n¶¤.ìºöÌN— w4쥞(ŠŽeÅÉòÖ⟑‚Ü0Ðw|°}¾�]ku'á�×%\t‚´3‹|!SÔ¬Q#©K~tõÛ§l(ò˱ôd[A¤ö^ªž‹9zÙùzG4u·Î£�S‡È½—:W )JüÛ†·"Ÿ å‹­ÖaØú¤ÖÊs!5ýJɨrö«ö�ßéEê÷·®®9cÞ&„¶ÜIýiƒ¾úö箓±ûýÏDœù7ß\q¸þÙ÷É"õ?ÿŸD‘ú:DÔ¤™r•DMI£žJÿR_è@j õJ"uAßôŸÚÔCNè8m �ß/õÚZº :f]êIHödR�™Îoþë‰éÉÆ uDz²¢ÃèZµjD¤' !5#/‘¸#Þ[wÌÕÇ µí›ac”ñ{'_�źXñ®¡åD _¸Q¿P@uV³Ê,3OC†ÎyPqŽB²¢oµeq^%«X0ÏZò Ý2Ÿ/©™º¹OÈÐ7Û^×´¢åÙÜì"õ®7<;`ŸßN»Q(4ìÑw„Ô¾K)¾·Œ|á€H2õ�hê,· Õ¨’3C—‡:=X�w�2u¦bîw¹·8h} Rs8ž©™wûæÔÔ*‡t�o uz‘Ú£ß]üMBHÍ}Óm�§üÛDì‰poþ4!Ç^·EjûþDjú=ß-Œ-kÙl~ä2é_šnCs ï̶«ùAP�þM$U 5�z%‘zãí»à¹wo7ü§ =E¤~5Û^ê¥n¥žŒÔ¯â¥' {²X�¬ ™O›‚ŠÞ{J5;PDËÓft£Kn Ž8u�QREät><� c8Þ�nF�¤X݆ãü�5ÉŠ9§]½ sÉy÷-¶<;䟽æ´>ÒƒH}åý´í‹Ï�Ìœ­‘Ú©~é Q‰ÑÔ ”œ!猈˃�‘:8n·ýM1Êú¤æß¥Ù‘Zo�6oHO¶HýýG³;©ï�Ô|Kó6ù-{ù‹«Dì^0[uñš»åö>A¤þ7f±›,Rov·A.öÙc^\R³m+……"æFænçz�§^+‹ÅÇ\úâJkº™ÙϘ‹Gji¬Ú7Bj³Ð�úA‘:‚–C¼§ =)¤咽’ñ{-­�ß/ãÑŠðde™?Í,¶e¨ê!;¦Âü‰#¤´™€Ôö¶Éu¹-_’ñr¿R¤Pe o1é›Ué=öó±NßÝ®è•#a€^rR¬°ÀïÜ­bnßD#µlåå�ÓRs/g�‡÷z=@[jCÛ[h»iÈdéª5-Žj'·«2àjeÝìØmo/ŠÈ(WwvWykûT÷äFæóÙç¡Ô~‡YÝs‡·£.U³\›•ÈM™@>_Tl™‘—û;÷ u1zÜj�{`F[�FêŽ Çu/RœÐ[ŽéhÜŽì3a&×Öò@ê•@ê‹9œÔ÷ÝÓ,ضÇc±“±Ë=Ó=ñúŠ{Ç¿O©ÿ•ü q¤Îìkºøÿ¤�Zc_ÿ¾þ¿³Œ' úÿÇK@júgµ³P¯í¾x>iË}Û¤B_”ùCW�-À±xœy¤.©™±’¨—¸£&‚Ôíà~‚k õC"u!Š–/{âºã´Y˜®v÷�pPz÷ROÎø�âÍÔs{©#ÿ›³«éEj›ñH}ê¤DñZt<”¶!ÝÓBûùR3þõx‹|�N¶&ÒmF"µÓ*äì“C?å)ÊŸä­°R:�—j�pnÄf…b}ËÛ®pe¨üÝW™+ïé­Fckû|wýY¦‹ ÅÌ¡9áì” l3 sÎÎÃãÖ+FE�`}12×3ëÊ¢:ÇO¯‡Fj±Éø61¤¾eö~1xÿÍû;î?MÆn‹ÙÚõ¦fÛN©ÿÎ&ÝJ©·(În°øœLRH­îÒÿÂeuý‚ K,MYsHÍ‚É2‹Dêªó#ahè:‹¦#GºÎ©삠\Kžï%�ÔN1’>�ú µþ.úô;}qÚ0çrÎËz®PŽrYùª‘+OÖ÷>0ÀpPê�úõX¤Nq]ê‡ñR‡=YjÖöúÓ¸ƒz¸-ýo]Q¹È×fŒÓl›­ÏšµýÇÞ´Oäý/”u^•¸m;á½ü…YgDߺÉF]Àò6ëÀ*íóòXÁKÜVŽöI—ÏL]ï0§´E|w™.ŒêgR/©ÿŸyœÔ÷@êoN9Ãÿì§Í‘ð{~»|Ãø›ïF~ù�kIî¥þ—7Ÿ·þùžH=Ë÷„ooR[ô?ZG„å 1Èl 1ç´Ë€«-9 ïºì©õ1ñ¤5Y˜Ý`ÑîñweZ[þØÝ:`^é\…gZ!Ä`)Ñø†6Ë—e}AóåHí:eXçÓ!·Ö¹çc8ìãï÷"µ&²Ž½Ût³�mn €Þtsz»m~é*Ô†k}o¯"_v÷zñ¥¼7�¯ª{¿ žìí½Ù¢ÿœ��”æÀï˜{©ÓR—úżu©£=Yú–azþ+¨•0rÚŒu‚W E�¸ÖkN3#Úx:ðeCøù£0ið†êß.~þo± ùJ�Eõª9oÞ)‚ð“l9HÍ�Ô¿¸M©¿¹m¹•»rÕ¤ìns{?g·w…íΪÑš©ó•s'd+¤.òÄâì¿¡GNò‰ä‘šÅ}ŸÜçïJŒþY9 �mÓÙÉó„«dw›M=ïPîAE;dȹ›Rõ 4ßHh�Ù³CÜìþ~?,R‹z§T�ߊ·ßWÁËy'¬[¶)lg]mm‡ÔJ‰÷ií�€ä 4~¿Œ‰Ô Auììdó!õ#×…ø¯«Ÿºmþ8¹#~yy‚ð“lÉH]žËI}¤¾j¿q‘úÓæ÷IÙåiÑ>þÙÏsIÛV"Hý¯!ý[rH�¯0Ô:Ë'…Ô¬X�x­çxhr~ H}ìæ?]ŒÝ’³ÍK“®a…ùm)@©/ØöÛ8žã@êžsŸ�„ÖH½0¤ÞèÍj¹ÞàLý¶Q/Wå›2û˜Óf»ìÑé/}mÆ#uÅÛ`ÌA4Rû{‘º¤ƒ–漏S—zm©^êÉnêI5´¦ì¥~2x}®€ í²}qÇþcÛ�“‚€ÔËGêÆ/ærRßm¿ûùÇ^}ú}Bv¿ÿtdôçžôß‹Eê¿R+9¤uXBÏd�zÛ)<(ò‹t¯–�ÔtÎCí>W¦4e›¦I‡‰ˆt¥y¹·ºšw�ºê7),©yÁŽp• Rÿo õ"�Z“ÁÞÇuÁÔŒ¨ëÇ2\FuË6¿Ì–Ë�#®N¹Ü|ëk3©Í“Ÿðù'2½Øáî›>¹,±—çä°ùfogRo“ÿU,úÁ›{«O.¥G>ßûœþÈ t AKßKý*µ{©çÍøý HÍ~ÑLø�Í:ò©—ŒÔçó9©çGÛ÷Ÿp®,ß5®;|SõO¿MÈ;>bêóûÿ£Ç�Ô2/'eêd�Z+ËÌ Å®SÀ0q¤fqÙG÷ú»2¥éµ/;óLó,aÜ'/)W$G=¦I] RóD§@êÇ€ÔŒJŸmnžÕw5{SàÃ[©;�-®F§œý¥¯M4R›Ý½½7Ÿï ÿrヽ=ú?†Åʯö>ÙÛ�Ô½½7¿bmù…û{Ÿ(J�}ð�éï‚Òí¥^­"ZðR{=Ò;;ã”gv󩗌Էs:©çG[‘mû@ìoæ1Ø—Iíáþ¾Ììýâ§§"Ú}' ¤þÛ2‘ZaL·uÎ<Ç ¥'3s„tKœðÚêÛ]œ8RÇí¢�z›çc"9›•ÇÌk-þü@q‘ZØ·ÉôÂ@jh„Ô7)gêLÆKÔŸmò�ÒNŠÔG[âåÖ‘‹Ô›… H�ÝûUQ©ÔxÊî«O÷ÊÅ­³7{ç©÷:ëfeÿ&A¤>áÑÞsûÈï7ß÷�í[–ôûÍÌuÃæEê?ýê§AÕ“óR_´Šùü–ÕJ,ã7¯€™«ä÷s¬|d-WM©YÜ·ºH¤f ¿ýéϲÂa}â"5/ÏY 12�?RR—Zg õâ‘ú³·gõòÅE¹~æõý‘úíý?àÿ¾Ùë3¤ÞžŒÔodÛí R{»„ ”{©W6ðûC 5A@ê$õõÌâiºÎ¿žCsÛå´>úÆcÿ§‰Ø½ã¦Þ³—ÂI]ž{¾s±ñ¿Xÿœ0RŸH7¤æÙ»¬‘sö,!¤Ö†„\æè/©9Çv bSuYâìYÕm±¯úö°MHŒb^+ŒÔ,³úÐÔð÷{e�Úd;¦ßÔÏ;:`H}6©s²“R{»„  ujÓ“Maê‰E´à¥† H�n¤æµšÑH©yf°�ÿ‘³íÉ/fFú¹í~Ó“ýãÕ×_¿¿¾ùD‘šYÿב:KH·yéj�›Ñ£xäºcpy$ Íhx~»=‘+¬£rÕ=í² ã„œwe�2ÓV^oÉ*Õ–'wY×\Ð|Ó€Ô Ÿb¿Sø]äQÝÒÁœ¥ÿ_Ù?ÿœ"p�¾ütïƒÓ^®Bjk¯#_ísÿt�o¸ŽDjo—´ÄŒß¯æôR?K ª¹©^ꗿ᥆ H�n¤æÞÚü:Q¤þV”…þéÅ宬¦UMÄî×ÜØG¹‰¿Ë_'‰Ôÿ‡™|“ RIHÙ„�šG<{•IÄn�—hfõ°wŒÔùÒЙZOV¥¾ï oy©hyúpQóMRç;@êt§'«|¾W¯Œ½½uñj+ÓÚÛË(Êù(Áw©Û{?—¯:{å)Híé‚–ˆÔ¯Ç9©Ó’ñûÙ¼{©�Ô©ÓŽÔwó;©ï�¶;¿ð'À¾HÈîûŸúÊa;ÿ|˜]ÿÂmÎqáÜè³$êº6ï÷læ/iÏgØR“±{ÀêQgDËùì–:bf,Âüȉï®Ó’r×™ÏÚÎ,l¾KEjf”ýÂ+ €Ô‹Ô\D‹rsÙ�äÏY ø¡)<Ö5E9’˜|˜1BHÝØûàP�8o:©¹cÚÛ%¥©'~?_^Üw$R¯©!R¯>Rs'õ=Ðöë��ýNDœ6¤@=%ò{‰nêçÏcz©gHOfô«©qç=ðX´~?äî+öKyhÚ/#›�®ÿÎädöؾ8^—‡Gâ~©'òøZ®ü¥|Ý÷fžÕ#:Ò/�´´âW�bù{âÚá…GgµSdÅ.®ÜÚç)}ƒŸd@j 5�va¿ï…Ô…·‘¼üî­'¤;NBàwÚ÷RG¦'{q?/õ5!© 3}à±d‰"ô[b§8ª6ROÐù�ºB9o·Ëê�žqÂîÒnlÛN*šEÞë³Új›Ÿn9P\ì8r¤vÄh9×ËìS�n±{U ]^ô¶†^¦¾"1�Ú;ê+zyýºÚœ)0%O3؃€Óê)+SR©�ÔéAê· vawÑv¡¤V6¢xùÝ[_Þ±8m èI§'‹[D+)¤^›».õ뙼Ô†±J¯g¦ ©+7$\?D·HÔ"6¸yÒn^3Dê&²5\WF.á çL+à‹¦ë|KoE©…“:Ô‘Á7_+ÅR°¬–^v:Ö-’+Œ�Ú”Ù»†æøQß¹[¨5â_ÚE×£éJ% H ¤R©av�ÔÉ!µRØÐÞnn¾{·¹ùVÛã~ŽÓ‚�žl"Q?[[KGà÷=öR«w,ír.«z‘Úëý+rÛ(³Išž±Yn(3ì"d�Š,?³ÝÛV¹¬{v‰=à@[#v¡Ù¥; ] ç¾}±Æ.m|ceœ±œÒ‹‡ME4ª§|þŒ¥¿²3™7Ú7Wõ1ŽÍ3AwÐ$ù‘ºE,­ÆKŽöTqv(ÏÐw=«^éºkîGjé¤uDïE±Ènæ°é«šUØuŸÏTyêk© ´ñ]©D¡ù¼0vÔën¶l–ìk•–�®GÚwúã§�H Ôƒ] õ#FjŽÌ\“Q"Nz {©CéÉ^¦l/õ”üd/Æ2õÔŒßm‰¿mRû¼ !²¶ÑѾ¬F´•�jÔÇ·#¤>ËkN¤V…ÛÊ1 µ-dœ`\l™NQ¥S��EŽ­Ì€iLO,îX\"LûæãR™›19àØ4eî*(6RÉQY®ñ@ç;žË£P€ÑGM¥÷ç*©/e³`G”—ïäñÐ å.u:”›sŠ•!Ï0æ uM~Šn�\ãQ£Ö©sb×�HŠòÙÇPõþ›'€Ô@j 5�vaH}/¤† è!Ò“½˜ì¥Nmz²¸�߃.Î̳ ¤©ýÞ?…al£rÈ|ĹLå¸.(4Ü(wkš=ú�–×*”™¯+�u¿»^iœ²#q·Þ/•Øæf`—,#&jbçØØoqÿ6KÝYW®èÐNÅ@£zbœ²W+áÄgàŸ�£c჎M}H`æY�ZçU2…E,°ç9²+O5¼ù¿Úž§>¤6å–æPGô¦tÉAQ;n�B¹EÉëšá„éólrR[N oË!5ý( è‡ZåÏZ6VhÙ³é¯ú…Ÿ^@j 5Pv�Ô@j‚Æ¥'‹Bêµtí¥Žü~1[z²!óÜie´+�ÚïýS$à”da_‰Ã¡F]C’”áÙK]«3œÉ«9NAôä@õì³e˜:>‡ù‡®–§ŠŽå‚Md­ÓÓ‰CëíÐ|<)´ŒhǦH‰Å@j›§I¯Øü&–Ýøî>ÏG&Dù¸£F"õ‘tR‡:¢)#�³®ÛÙÌfk»òi ‹Ü柉Ô*½×E.›…+M©ŒÔÊ9{üR§Ÿ�¯†½2ºN†rüôR©�z° ¤RCtß½ÔKtRÇöROBêu':w�C§@j¿÷Of]KºýÊùˆF»Ž?¸‘gü®qši»~·+�¶%w£«èÉÈs˜½ãciäý›u#zr™üšsW`>ùìU¢›ÍÕJY•ŠÀo'yzŸ§ì>q3¼õF�Õ}ùh#ŒÔ¦›w;ØÑöh¯³?÷·Ù⬮¶dµ.‰ÔñHá[¥Å€À¨+çüí\càû ¥^™@é1 5�H ¤†]ØR©!hÅ¿#‹h¥-?YD]êIH}GÈ!wôÝòì^©Þ?ʼn¡¶% …†Ý9ÄtëGjͼZ?Ëq§q› ¥›Poq¤=%Ãxi"¦Û㤫8>Ku\OŠëϼâà ÌÇ3M-±âu(Nz2gÇ´ÉozÏ�¥OoÒòda÷"õ‰[ <ØQf„Ô'¾Ï5þ�èo1]�2ÛTÀÂ&,.b[JÞ<’: ŽZ7®OjýB¾ìîú^ �*j©�Ô@j 5ìÂ.�H A«‚Ô¯fÛK½Ô­Ô“‘úU¼ôdM�£¯-‘:àýSg¢MFH=®ÑV©×ëN#Â9?äž{+—Ä¥¤Öœ¦ê¸žŠ.º8RæãhG†üF-΀™gBê�ëÿ7x vÆ=vƒè‹NHw©�Qqè`G¬;#¤Ö<õÔòCÖóÀ{óèGE‹ÌJ6fÔâ‘M{•–]ëJ¯<_¢ju©�Ô@j 5ìÂ.�H AéEêñnê)¿×Òøý2^­]ÇÑgëNblÀû�Ôã�:Ëst[�RWXÈ·Á~=¾Èþx¤ŽîiËñ޳m‡æãÉô¤ÉFÞQSÀK=#R÷Ýxím~Ãè­8 -�µÔõµ©›®“:Ô‘n;A ú�ù»}�KvÃHM~wú¨+§§Çîs•ÆJ­û‰›§ž½Q—H ¤RÃ.ì©�Ô”þ½Ô“3~§x3õ¼^ꬿ®ÇØ€÷/©Ç5ò#5me_énð¶©óuÒÌŸÛ“/JD©Çõd;Éž«©³Ñu’èÉ-é¨ÌÝôØK©µLQtg›NV1ºªê¹ð6ëe™NËÌÉH]"òCÑË'öAŸr8§ˆ-÷c‹teCÊ"-Ã(ð õ|'¾ÚluÆ�:GÎ5ùÄÆVWjÝ â<ÐOÝ-â@j 5�H »° ¤RCP‘úõX¤Nq]ê‡ðRz’4çGéÉv§"õ¸F#¤Îˆ$aU ÐA¤¦ü¤�Ë ÏÁôdÅêm©ÇõÔ$ä�sÜ�#u`>ùÑÞ^Cš86/Ș9R$ÁÒÅ´…BÖ�@2„"n¾p@DÜ7äÞ™�DêÝ‘“:܃ò¶¡5Br¦Hwv~fjÇ—„ ½QÏu™'�YÊWŠ“êRç÷ ±Ž5��ˬØÂïrsjj•C‹¾P€Ô@j 5�vaH ¤†  ü޹—:-u©_Ì[—Zq23[­CcýÞ¿1H=¦‘DjCŠÖŒ°ƒH­uIÍÍO%T“hdvçú‘z\OEBºÛf%Ó•–óqtìć›9rfŽ‡Ô¶ØÝvw«ó' ú¥<´ßÙQòm©¯üÛ™åK¶<ÎqWÝó-ßçÄAê¼1”ç›êx¤Ö:N/;«¶ðúh-[©,Q�Ÿ^@j 5Pv�Ô@j‚Æ~¿Œ‰Ô Auììd³"5óZ™Š¹ßå{5Æú½c�zL#‰ÔŠEÛ†¦Ñnsû&ŒÔ¬>±[ÑXòý9Åžc³_æžçPàwtO·’9Dbrÿ|¿„]Ø]´]H AŒÔ©MO6…©'ÑJ£—zý¢Ù{ šÕúµN½]�À]ØÙ å|ÎìâóA@ê‡×—É!æ—OÙî�Éõ€z° ¤RC4©£êRÇôR?K ª¹©^ê—¿?4q“!R©�Ý?, ©7™˜6avmRCÐ!õëqNê´dü~6ï^j 5A@ê¤õErˆùÅS¶ûçä�úÏ@=ØR©!Š…Ô“¿Ÿ//î;©×€Ô©S¨·É!æÛ§l÷‹ä�ú  ì©�ÔMDêñ¿§¥'K,?Ù³X{©C�ßé-¢A�ú±ê]bùº¾z÷¤í&‡Ô~»É¡ìÂîÂíB@jz`/uz‰:nYꈔß@j‚€Ô�4òû‹§m÷ÏK‰ûNÐ�¸ »° '5�‚¹—š9�ÓQE+ì¦RC¤^–6rÛ~µùÄí&…Ô»ï–äL„]Ø…“H Aé÷RODêef'‹b꨽ÔD ¤† HýHÝÔ_° » êGŒÔºjƒÒ.MŸ€Ô¯âdüNÙ^êÈôd/ॆ H�†ÐïóËMØÝüqñDýc„Ýw °Ïæ;Ø…ÝdìBé@jÔM�à„ ¥ÆP¨‹¡Ð¦{©_ÎXD+)¤^›».õkx©¡„¿o�ÿÿË «X£‡—Ò;Mþ{ŽŸ^Ëfê/7a÷³ÏÞ.œ©|‡°¹ò�]ØQ?R¤Ö)¬ð J¹Tö9�|êc~ŽûŽFêe›ò�ßЫ°sPó\9O©EùmjÛäÆªÜoW¯ÞvîÜã�^™«m°×Ç£ŽÚNƒCzàýÀºÇ;žÖëÃtÇ1¾Ö­5T"ÿlù—)3$dHýÔ˜úËMØåvûý‡1vÍ>ãÈvaDý(‘š¹¨ÔÐ*@õGuä^ê—1¿“Cêgóy©gËømô«© 6IÇX&Œ"M‹µ@mBºÞ7zÄ• eí’¾¼æ/KCq–„]”Ç­Š\³œ¼²OúÄ#¹”[쎎sžÆÙðˆFc�o¥ÿjÑioGÞß2­r¤Nã~ê/I˜_¼ƒ]g÷B3“�'�…²Ï„ý®° »ØGýø�Z§˜‚€oh%4æÃ…Ô/^ÄtS'”žlmrÂԯæòR_’Ç^:Æ2aiZ¬Å!Ý)CSR_»#´Ëço´ˆƒ³W€ë×Õ&=6$÷ukgÛ”±yÓ =¿Û¿mÓógôlÇÑÐEêñ#õèøÈilrz¼1Ch|+-Êʤ<©ËFH�NGõ òÜ~ùÅ&ìzìþyAÑß?þy¢Ýw› Ó;؅ݤíBKEêˆZ%¦.D#u¬ôdu©×ÖÒøýP{©Œ•^ï¾áæ@ê¨BùõÜò#õ.i–� Îê6!ûì½ !öï é3.?‘ü7�ç�.){þár$^Ñ ›^V 3Õ1÷ÂCh|«­qOD"õi“ëLSó@êÔzªß~ñå—Ê™´»/Þ¾ƒÝ ‡üÏïÿð \ýãÞÿù‹évB?ï`v—bZRk jhµ˜: Al/u(=ÙË”í¥ž’ŸìÅX¦ž-ã÷ƒQâwC©W]ûvµK?R[~'1!¹â–ÀÙ¢‹Æ=BŠôû6”tkRÿ”Å6¡ë\®4ê¢í@raH¬+B�ýü­†Ch|+­!§C²3©-àÞ£o©!‚ hE‘ZÇ>jh¥¤F<šœžìÅd/ujÓ“-9ðHýH�z˜a‘Ô>¤¶É­©;J^âl•�†x³DÈ%ýjµZ ‡ywéÿorå w!y@ÙÚ‹ÐÁc/<&¼^ Œ!4¾•VŸNö’Øê8¤.¹*@j‚ Z]¤Ö”B‚VHa7udz²(¤^K×^êèÀï³§'Ó·J=H‰# ô ªïßÈFšQˆ@jÍð¥,V�IãÑLSõŽ¥bêÞþ£zÒÿÛžùø:6 ãBjB“-i~nö�ÂÊg\¯꘎VSE¶Â~¤ÖË® gEné ‰³wnŒ²FHËïY>¥ÿ4É�-öz …µë¤.²Äc„{ùÛ”‰Ï†¦ ¡ñ­´,bvMû‘Ú# 5A­&RÃI =7õ½öR/ÑIÛK=©Õ;–J9—U½Híõ¹m”éaMÓ36ý×’ýYªÍÜ’™p¹Áºg—ØÎÚ5bš]bç¤+Yóœ2ÃHÆ.m|ceœ±œÒ‹‡ME4ª§|þŒe¦²3‘EÚ?ǤUÍóèã¬ë,FÌã–v˜ñr³w¤¾ec*K–1ê]¶<™ÈŽVX~¤¦3[?aK|rå¾'qvÝ�/>⹦&ø¯E,­Æ»ÜS#œÔÚ9i©„ËÁpþ.е½+•(ÄŸ|cˆߪÊdé¾Õ©!‚ èÑ"µ '5´j*„ÅüŽ,¢•¶üdu©'#u[âoÛƒÔ> BÈ¥8<Ú—’¶òQ�ºâøv„ÔgyMnöU”Ú$ÇðÕΟ9ìUr¢uÅ­p %�ê|,rleöwfLOùCçYlÈ7·c9Vž«å8Pë$§†çÁṗÔÞQ�zGvËÙ�Ys#¡Ž RSÌ“·©{@j��:ÿzéGÄ_”Ùʆä¨,×h !™oÀ¾Ê{:x,­_JHçK{ë> q�:j|«ª,! Ÿ«¤† ‚ ÇŠÔš¢å!h¥þÐz‘úÕl{©—º•z2R¿Š™žl›�‹3óìB©@j¿PaÛ¨2l.S9® f 7ÊÝš&¥ œ–×*”™¯+�u¿»^iPºÜ‘¸[ï—JymHšÜü)g)…šØ96ö[ܿͲ8wÖ•« 4<¦'ƒ‚|öÊØf£ÛÍÇ!>zö´hV…×x_"œÂ» Ï£Û[¿R<ÜìE©‰}méró5›ÜT cŸÚÚˆèèÑ 5s@_…bM>…ðâ,]¥ý©ü)Ćç�o©óç1™ŠÂ‚ÚAHf/Ø›.B�¹Žäͳ¤³Mÿ¢Æ·¢ÒmR+Р*�Z1“ÿÏ1~zAA@êE8ü (å ‡Vx3~¿š5ã÷ZZ¿_Æ+¢U Äb¿Äµ2!ªƒÔ~ "Ѥ$«ùH5êÒIläG{©ku†X,vÕ'ªãç`;d$ß乚ÍFt,|h9Îcz:‘Ã`h½šÏ¨ãm‡ít6VîØ¬ò¡†çqàfï(‚HÍ£Å÷9ûõzC>¤X�èèÑ õ‘é¿öE¦i/Î*çìQ‹︕¦ù“’b^"µÍ©°b�¯$³ � /B�½ü­Òû,2sÙ<úß3†¨ñ­¨ŽKS²¾�žùõñH½ á§A¤RC@ê¼/õäŒß)ÞL=¯—z�ÇÖŠ†ƒÔ~ S´HÊmϤœ�h´ëP@#Îø]ã„ÕvÓW] �-ù"£-b ;ÌÞñ±4$Ñ Ç÷ä2ù5ÇæÀ|F‹}Žouù]�žÇI�›£F!O‰˜cÝòn/𡎠Rk†³°-AzœÍWÎyÈu®1p—«Pvoò��ª{#ŽNêŒlæ tð˜kà¤û&)¾1D�oežììSÑ9Vøgݳ�H AA�©Q”Z½XJE‰@ê×c‘:Åu©ÂK}GÈ!wöÝr‡Gê€Pqb¨mÉ>F¤áFw!Ýú‘Z3¯ÖÏrÜiÜfNbqZÜÕ}J†£hU�ø ð^ ŽàJÕq=)îVÚ+>ÌÀ|äc·cƒcZ†sY�#ظɎÅiSJ¸ô‹®Üɇ^l¸îîíljÔ#¸‘.Rçuãú¤Ö/äËüyE^ì�¿vW:¤ÙÇD�>‘ ¬Ù¤UÙ¢jÐ;WQBÇÎýŸA2aqÛRc�o5¥ G� ا¼ç~à€ÔAô˜�„­šÂHýaÌ"ZËDêØE´f¬KÝô8ûÚ©@Åq-Úä`„Ôãm�z½î4â œó°¼Æò}_ŽÆR"¾‚ÂnA¯;AF‘=]t/p† ÌDZ[/µSTÉrG©2~cFáäHco^»ûÀE¹Ö¶GüêèÑ uÁá[7z?g5gùÕŽ ÏÜÇl¸·¤ç‡dÓ{#ˆ:v>®§ÿl`”nÆïˆñ­¦Îx=!çì ’YðÅ—©!‚ H Aé@ê¨Àï—1‘:!¨Ž��lV¤Þuœ}±î$@<€ÑH=®Q©³ÑHM±Ìâ¾wóãç1fwGRj©+¼˜Wù¢ùÈ‘úÀ�,(»ÁÝg+§§ò~îÈxy}àÝÐÜweÛ¹×.$ÇAjz#dW–ÜhFê¨ñ­¦:n©¹ýÑ¥qtT�+¼üäkøéA=¤¾_àÛm¿¤†¿—:N]êµ¥z©'»©'ÕК¸—:ëwäq€ x£‘z\#?RÓVö•žw¦=HM‰¶™?%¶gïˆJHm,ÌŽëÉv>W9Rg£“ÁÀo¶áÛ,¸#ŒœÇ8_¹ÿ”7ð»G­lk�©µLQ�âaE†¸1N­9×ä:Ûª\™Ï�h›Yz²-ù DB²jHQîÞ6Ìб�¿yÇ|§µÚluüH5¾ÕüKåÔëæ œg ÎsÛÝD¤† ‚ …"µ™ÝµIë¨:?Vß„ Ç©¡Gè¥~©—»—zÞŒßSêRʤÕ>€ô{£‘z\£RgDtjUt©o©©sJf7=Y±z„Ùq=QÊ:äwqÈ‘:0ŸQÇ®›”Ws²É]_:3ÇÌ#R{Ó“Y’"‹�©âžÒÅ#5S7÷ 1}Ï:Ö4Vp�s_�'—b·¶AQ»Q(4lçéÉî’]"šGÇ#þPž=®/Bu©£Æ·’ºö,„åºÞ)]wÏ [5Ê@¤N©Þå¿ú§÷ß}û€úîý?}•»~mþæý÷?üí憎ýðýûßlN�ïf^ÕXj~óìÂî2ìBc�zÝInbÍ�¾@j^ê•,¢ÓK­È¢Sùb«uè¤ß8©Ç4’Hmˆ½´‡¢†5â Rk]R Ä®Ö$™]–ªÙ³ãz¢ÛÝ6+™–¨K˜ÏÈ¥é)¢Å]ÝåºÜì;fñ�Ú[DËb¹Y?�©�„Ó†³e|è>½p³mwœHíùéI“«-7ºëòn¶ó±‘ºãåoÃùÏ[3˜"-b|+©2ºŸ¸ê(Ý_ω…OAÑmüôš®Í¯”.=œùÕ&ìŽôë=\ýݯ'Î7¯-HùM؅ݤíBã�:Cÿ«ÛéUkçD”÷RCДôd“ŠhE~?[f­çq6SOAjöÝÊTÌý.wƒ €ô{Ç õ˜F© ô¯Î¶¡iôŸ[Åܾ #5«Gì­=•U�wŽÍ~™{žC�ßÑ=ÝJÂ8ØìŸ�C|t¬½c³ÚrÊ9ñ�ºWîÎY‘ÚÞ6�Oéж¸åÁq¡X|éÉÄžäþ�-¼¾ŠHW/yŸÌˆüæz¶Ëq¯š�FêüaŽÃnVwb *H]Œ<6üü}U–Ôà"Æ·Š2½ÓõÔdS÷ù—S@Ô@êéê/¯¾]˜®¾|»@¾^Ps¨þz,„¼{«-PoßÁ.ì&i‹Ô,ü�'ˆÑ.ýY€Ô�z/uºò}ÇLO6 ©õKI<7Å@ú<€c�zL#‰ÔyN5g,‰S·Fê" ýa2‡ffÇöTeNÉá¾&ˆÊ?ŸPÇûn -iéîΑúT^Êl™Ò9:xtHí¸  ]e®Æì'Ò�L¦4!ѶnžeŠ“ˆ[3ŒÂ˜3ãÇ÷´qœY/¤b$øé5ÍEýõ· Õ8Ö{jvýï_¨þ}Œ£zSÕ*uva79»Ðx¤®'o�–sœAúV©¢{‘øèB•9`4ÓT½H­�zò^ê• üþp¢?Kíq¿á€7Ú–éõòµ¥×ìH–Žl¤HG°²“ã±ªÛ 4­Ò>!:‹ì¶ýý‚``ìò�*ïXX\531¶'Õ,Ò¿Xɰ¾ù¸*ñˆäs—rûžÒN‘ópEàTŸ J†˜WX?ÝžHxV˜ÿA&­ˆðÓk²Þ¾ÿvÁzÿvéàßþ}Áúmäg}S[¸6av“² M@jƒ¸æÒ!wبwì·f.+~ªwìÇ =à?jéÔB³Ë¥òµ7âG-CjƒýN,÷�ÔÐ@êÔ¦'›ÂÔ‹hýdJˆ¨^1*j|`ÜFjAì7Qƴцn,«÷Ýѽð­‹èÉ,•tÇé}´cCÑç™ÇÔÅu«N<©Ÿ˜�zá„Isv½p¢¦Lýë¥�O$ûÀ.ì‚©“FjµKZ~xp2ÃpW“fÉ£V…ŸÊuDñO3'ß?Õ9RŸÈhÆ>�z¤HU—:¦—úYRPÍMÅðR¿ŒÈøý¡™Êqêìf¾—²2¥™Òò$s‚ H½ì}Ôß|›€¾~÷Ôínþûßп‡ä�šú¨ï`v“° MNOFÙî{|/Û„\œ™gbË!=Ú]¯4NDjVFÛõ~©”Wl– ÈØo‰�Ø7„Ül•ínTµW 5ôX�úõ8'uZ2~?›w/uJ‘º’9z˜*@ú7ªÜÎ^v}�!R/W_~›ˆ¾|êv¿þ{"ú:æ®%¢·° »IØ…&#µÒâÛwÖ…ï¦ «Ëhe¾'°VðŠ/bŸ5Eê�*=Ù|‹¡yÃïÞÈú%ûnP%�zÄH=9ðûùòâ¾#‘zmu‘ºÿ`U€Šç2®æŸmR§&ìû»dó»Í§m÷×K©ÿý~§%¤MØ…]„~/©óÊà†ÿÔÌí0_õºfI_£F5žì§í¼gKl <ÌÞq¤‰ˆ*n} 5ô‘z|ÆïiéÉËOö,Ö^êPà÷ëé{©—¡õ‹fï�’kýZ§Þ®øhC�:5R¾KHÊÓ¶ûþo é}àWwR蓇]Ø]¼]hRÓ›·M¾5º¬ð0‡E¦[gc´f^­ŸådIš!'i-=yC.ù¿ªÜ°¤†µ—:½D·,uDÊ¸ë©“ÜI�a~÷þÝS¶»ù§¤�úOï–âLÔ4Ø…Ý…Û…b 5“‘òM‹M2KP¶^wޤ¥'+Vo�ÔÐSAêWq2~§l/udz²ðRC¤^¶¾I1¿yÊvH©ÿ굫&‡>*ìÂî¢íBS�úŠ�KAÇ•éjyEÑÊ[­CØû²•©k’�Í.¹RCOÍKýrÆ"ZI!õÚÜu©_ÃK A�:a½O1ß?e»J©ÿ䵫%(Ø…ÝEÛ…¦í¥nQ†>45£:i¼{ô8S1÷»d¨±ÀïÜ­bnß�Z9§��Í~™�C 5ô$�úÃpÜw4R/s/uÜ”ßü† H½l}— ž²Ý¿%( ì©Ÿ*R›e7Ãw�Rs^¿”G7Ez´#^w›~¤Î›C'+¸¤†žš—:ÌÔÏS’žlíÙ|^jdü† H ¤R©av�ÔsfüÖÚ�[².–ÚãEªâö¶M_[¥}Btïm;W»¬‘•á]ÒRCO©_¼ˆé¦N(=ÙÚä„ßu©_ÁK A�H ¤RÃ.ì©ï‡Ô Ö3Wž<ßzŨ¨£“F!ÅMS�N h5‘:Vz²ˆºÔkkéüÆ^j(!þÛ ë�ãà;´xÝêê}Fñ¨¥§w²øé¤Rõ`Hý4�:a8� Dê#Ò“½LÙ^ê)ùÉ^Œejdü†î©ÂÎ�,­¨ß^ž“V{Ýýê´mrcÕÜG³jßê’óöèVìØÄÞ½ŽbB­}p°?î:ã®i[í>Çñ�ƒ‘Ö£Fñ¨`œíÚ„Ø}-•ÃÃO/ 5�¨»@j õCÀ‰Žß›Ðй|fLOöb²—:µéÉb~ëÕv’À­÷{Ç÷ë⪟Á§8I)Óuß�ÈD×âLI&Þ°‹òîÖÅñÐ�.'}‡ñð•e󰢯Ë÷åuå =È‘‘²£xÌ2ZÎ̇©|‚€Ÿ^@j 5Pv�Ô@êð^(*~pB+æöQ‚Û"Ó“E!õZºöRG~¿˜-=Ù:!õä‹%pع_;dˆOq‚ß—SžÆ’¿îP¾>Û¡ ½ÍnÐõëj“ž,|DH«z6 $§8Ôœëeö-úvèáë!uðº}J�Û=z]N£g;Rôø.<ŠÇ¬ã.[¤Ó»:û·¤R©�Ô° »@j 5¥©çÞK½D'ul/uz�ú‚BÒecñH­ôzËvÏôòU(Çž[© BNTzŒ…u›¹�!¤#ÏÛ,>ùT>61é1û²©™ƒ7]mÛ’H¼ŽvÜbîi½-J9:ªb†Fñ˜U +|Â#¾Õ¬ûÜH ¤R©av�Ô� ©5EËCÐJ)ü¡�øYD+mùÉ"êRÿdbàw-9øToHýÞ{Eâ õ!gKÿ¤uHkõ¿.û„i—©· ^ä!•‹ô”hÔ#¤(œÍ|Õ Cr£yŽóZ+wè—^²Þ‘L¼®èø!mÏsa/0ŠÇ¬SBêêèyBH ¤R©av�Ô�©Ã?J»ç'ZáEêW³í¥^êVêÉHý*…éÉ̇ˆÕR'ŠÔÃL>/‘ºÖºp9»”ÏW]ßs‰�KúO™Xâ�É6÷¨ê¹ñ&Ãc©×åKûûâ±—æCê6wRGñˆ¥Ú<ð]>û²©©WHïÔS¶û§Ôƒ] 5�zQÒD~C+ö35œSÏ›ñûÕ¬¿×Òøýrö"Zš1Uªx—M5Lù¯÷mÍ0´ˆ?†é¼k„€u)?Í4 ¾ûã-èGOj�ÚSüϋԚ¡ŒŸ¥¿``pšÒ;j(m\÷“�Z•WiFÊ«&Ù�–Hí…[z#îÜPdоtªú�³MÞàËoð(J±þ�åÃ\ÁAêàu#5¼Ç×)îÅ#]Žæè(KÈ-�H ¤RÃ.ì©!Rç5¸©¡ÕÒFx³‚w/õäŒß)ÞL=¯—ZãÜS ?׋ËÝÌ�w@ºb‘t›ûÕ;–t9—åhT#v¡Ù%6}yÌ®èv¤ïÌè°„Su¿ãP½c ÉÈ€� *sW=hÅOÛGòψ±ËηDjH»d§âlá€÷´%�ڱƜž�Ýko,– <# 5û¶èÂ?Kÿ5Áiº:d9—í3±NA«º—©šËù|“\8Œ]—ó é4�ó[,wµ�Mý—&€Ô±‹y�¹rE: μ2¡ÀSsŸÑÅ*²e6¯Vù¥©ƒ×¹Žµ£yÄQ¿ë _�³5�WSœ+Ê6½ÕBj•Þÿ+ñÑ;}õ#ÂÆÅQ2±!ðÏÇ�óñ?hQ†|_°Dêàuâ�Jç‚~:£G¶¦.�â«Oˆ§r–ød©�Ô@ê%"µš `vmJRç5”¦†VHº‘Q/2ð;æ^ê´Ô¥~1o]j©IîÖ4{¼l‘6$'ÒQÌ@Q¾83Ï.F|]ï—Jy­K΋êV_¤ /´(@•J”¡Î ¾`UëÖ\§×X´ÛÊ:í¢RÝÚÚê›�KîÌå¶N‹fµ%¼ŸÌР¨ËÂîïªÁüºH­ÐkwŽ�ýóMk•3:+fˆ}w½Â.ÚÉgé¿&8MÇJ©û”¶±IROê^©XÄ®T”¤¦Í ƒüå•IÁ³›öç’~¤n;lG—j@×QåSÙ`í�s‹M™ÞÝ.9(jÇíàƒ–#±-X"uð:.þ°¢ÜW½×Ö´ù_«3ß> 3�Ï^ðÓ H ¤êÁ.�Hý *€©¡U"êˆ� ‘�ß/c"uBP;;ÙÜHÝ5$¨ìÿyä·n³½œ"Âo5ʶ*o1Pe *ÿÁ_­×5Nß< øÖžª8€]ãV‚{©Yd‰ÅôyÏÛÒY=Ô…!ö·e‹ï(­È¶ún$R·eŒ¬yÃßÙK]«3æË«9Žj¡Yz¯ LÓ…I>p^E9ŒÔ»w÷R‡‘º–ç§Åü²©¬Ž4©))wÄ)çìñ «™L碳�ÏEÙÆ&»|b³þ˜å¢\x‰ÔÁë¸n³½KÚ}Yã¤�âñÊ~g€Ô@j 5�vaHý8‘šB ˜Z¢Žú°NÎøíê¥z©'»©'ÕК¶—Z õ®ƒŠ � ÷`Ý °]w@Ôp=^3Ë)ñcyR*­;°¤Ú<¢7€ÔëN`«v—½bWZnÀ«É •$‰¶<ÜUˆDjËI}˜½Ë‡3~×ògé¿&0M©²3¦lROì~Róû±-»(†s¶¥©ûd´Á¹rÎús ŒOïnßýPíˆ@ÙЗû[m‰P~©ƒ×�î�òs üNjï(­èrœø"¤/Ð?½€Ô@j ì©�ÔôŸ}û©¡•�ª(‘…Ô½{©_¥v/õ¼¿_ÅDê;Çx›Ïë-NÀ5’SùOùÃ"Ó-GŸ6w!SmPbº¨šâ@¥ˆÃmž¹ÌåP¹àMrFê, ÝâIüœáè)þ°±{nb+©,æEjͼZ?Ëñ¾ü³ \˜f�ñŠc�zl÷�Zd,¿•E‘Ì4üŠ�Ô BZ£$åºq}Rëòe¹¯¹ÏXL¾„™RŸx=ÿ×ôìÓ)³èüàu5�»nø�ÔþQd¸¸î|Jz2· ±V­éɼHLOæn»½ö§'+VoRg„ýªôG0¯ÿšÀ4¥éÉüV'wO‘Ú–^Y1u¸âH]± é� ±=¾û„XÇšvhË\Ôê9!YMgå¶ù½ÒË¥ Õ¨’3ÅLϽ_ú\Üàu…BjWš™±å.ë’×IÅã•yvv;äKpÆΟ�•€Ô@j 5�vaHý¨‘‚V÷—ë‡+�žl SO,¢5‡—Z뒚ܭ8É•‹­Ö¡‡tO­º"è›íwm;XÕluÜÎY-ž€,ºˆ¥c[˜YDË‹Ôn­¦@j½+6êj‚ÃjÒKnv9¶Â-J1y_:­#˜×M`šRG²ˆVIÑò[�Ü=s­*¿¯dìîj#uÛ¯ÍÜÏZÇ9r †òXFΗlyœ3ä'…(H=þ:ÒÓeüsÅóLÇ?ŠÇ«ª;É3ñêH ¤R©av�Ô@jJ%RGÕ¥Žé¥~–TsS1¼Ô/#2~Ïá¥f,é¤FêQØÌTÌý.jÒͰ$ßÜGiëÂw˜=®/|àYv©YlK\ 5ƒÍr¿R¤lËØj‹¹�ÍjKй©Ó®ÙF\ž1›Ú1•"ÛÍ]%’wŽÍ~Y8¾)¬ç¶ �N.w«˜Û7‘̸Æ?Mç³Á¼„ÇÆµ-�Úour÷lÄ'Å wÆŸ &Ûx½¢H} –<³z¶Ë3ÔU�†ß\Ÿs÷¨ľiK|µ²wG´[D+â:eÀ¼{!Æð$Œ{‚HÝs‘º ¤R©�Ô° »@j 5¥©_�sR§%ã÷³y÷RωԔ…Û™‚Ó¥˜›¢—t5K¾Ý=óy›ªÆ„„7:ˆÔŒ:ÅiÃáW®ý|©U™\Û¾+u¥9-ì^ÛÖ…”§MÛ‘#lF2¯ÿÿ4å›Ò]í·:¹{~i‹v,óqÙ+»—z¼t#“)y÷ g™cïñF1Óðl¿ÛQðº|áØ@¾ËÔ ?½€Ô@j Þ4™5¡3 -�H AO©'~?_^Üw$R¯=Ros¯®ð*HëNf(F³½CÂ�)(ØIÞ¬ß1Wâ°#{¿ª �¥¯ žšµG—2z<ôïÂ>‘áÀ%I|^Íû µÅ‹GÞ“­Y×™»Š‡ÛWr®±Ëý¡ò1€²“㤺Íú·Jû„è³ô_㛦«F‹™Ùß�à~«“»oÔ9RçÕ6kÖ1;ÜïïÌ+#£ ÍàsR©�Ô@êÇ‚z=ùdúh ¤RCÐcGêñ¿§¥'K,?Ù³X{©C�ßS2~ÇtFVŒJTíyͨèÞ#£¾tË0'Tÿ¡§½Ûk5ÓPÆ:'5Óß“ß:;í£ZØ|1¦q×DNSW˜M"uÐê”î7dwCà R©�Ô@ê'‡z- 5�H AOÍK�^¢Ž[–:"å÷OLÜäûj„Ô©�Ô÷·ûÝíé v{O»¿MP@½¹Ä²{îö¨�¶@j 5ÁK=&î{-¿#ÜÔ@j 5©W ©O?âz“Ú~ò‘Wÿ˜ R;øüc¦�~¾½ŠH­'¨·{J‘ÚLЮz¸¯¤e�c�% ÷RCÐ{©'"õ2³“E1uÔ^ê¢R©!H�~¤þV@æÇŸ'‡Ô?ýØ«O’CêïG–ÑR?f¤>'ÄJÒî!7…”¬s¬±©�Ôô�úù”Èï%º©Ÿ?�é¥þH}o©;;ÇXR/©Ë'ŽÔ- ©¿ÿÔk7÷ø‘zçr¤Ã% ^Ÿ›U./Õì—–µ³®ñ×,î{?Éù²RÕ” u¬±©�Ôôˆ�úUœŒß)ÛK™žì¼Ô©—­of×¶C˜ŸÏxáüvßÿÂ�ÔIÙýæ1ÑOÞüŒ¿¸žÛîª µS²‘)»ÔËR×õ«™ÆsÛ­Üðyž¸qß•$çË*y)AêXcR©!èz©_ÎXD+)¤^›».õkx©!R§©¿c¡ÐŸ~”(RËxöòÖQ#)»×¤ëß}óMã {õs õ‚‘K벡÷fòßÎm÷„�£S:c¶�Xµ ¹Ht¾æåE?-ö±Æ¤RCÐcAêÃqßÑH½Ì½ÔqS~#ð‚ õê!õ.cË»OEê³yûÍœšß.wRÿü={ùýG3�áHý÷¯Ëÿš0RÛ-¡ê2Pïˆ�†nRHÀn¶¶¯S[|qiö0lìYR©!hå½Ôa¦~ž’ôdkÏæóR#ã7A@êÔ#uƒ…@ç¾I©« g¿O©¯Ø\&1úûÕûd�úï¿úø#‡©[ÿâ_“EêR’ÈU(Rq~f/½HÈ�BH3Ô+Õmé�gqß……ÏW)nŸö¯äæm:ß ñ�¦›ýÓ¾ñ0v7®ú§ûë[â5íÜеû3vtUíe•¹Ç2ã|#ÆQìíjæ�Ô@jZ:R¿xÓM�Pz²µÉ ¿#êR¿‚—‚ õª 5sÜ~ô}ÂH}Ç�šâì··ß¿O©ïœ�Ûï·ßÞÏîLLü7eþ�`ês–kü_/R+Ìb›¾hÐoL]·‰ÝgžêD�ú�9å¹-ŠÖ�EÏWÛõÝ ;º ¯Ž™—œ®x“¿¿£>€Ý¾ŒÝ?b´ºÎjmgèÿµtÝl‰…9Ç2Û|Ãã8î²ãV)lH ¤† Ä‘:Vz²ˆºÔkkéüÆ^j‚€Ô«‹Ô=¾«ù›„‘ºÍ8þ}›ýY®šR7Ùd;ßœòädŸ6¿M ©ÿ™™s?µÍws·/RëUÂëA«-™q»ÇއZ2H­4ömž˜ëŠÍ,z¾–»M½çÇØº|»»m׆¥ ”m 9RWlç„mÎ7–™æG9'Ík!ó@j 5%‹ÔF¤'{™²½ÔSò“½ËÔÈø A�:åH}ŨöÍûo¾ùi¢H= Ö~ú�2ß÷Ïî’²{ÁÌíäœDão®Bêßþ›ÃÔ‚¨íù¿gý®0üºÒ„îó=‹§«“|ŸÁ—Ê~é0Îj/Þn>¯XÖ‘ž¯ršÏ3§©¶àùÌ+{ºÝä� òy†±Wù¼€KáÒµïmWá;8gÿóùu\[ÜG]æÿ2ßXf™oô8DÏ·!óøû ¤† Ä‘z|z²“½Ô©MO†Ào‚€Ô+‚Ô†Ì6'‹Ôu_ ­Y™zn»â?þùUBHí0õ¯æ!ê{#µ£E#¦‡4I‘ùPKü˜qÝqHÍ‚½mf팿߳™.;mG³íµ;z2vGOS)Ôå=ßQÊ®ºéÇØ’kïi·Ôr‰H”Ýuo¬y¿±Ì4ß1ã( ¤˜Çßo 5- ©_Ͷ—z©[©'#õ+¤'ƒ H½ HÍj;}tËê3s§íGwwÕd�Ú£÷¼Vt2H]ûØS»Å^ï&‡Ô2+š[Ÿ:9¤6à{6Ó…Q¶‰¿îïTKIÙuuìwá.Ê®ž¹� ™«,©=Q!¤6î7–Yæ;n©æñ÷H A‰#õx7õ”Œßki ü~‰"Z©W©?駉#5÷�|•ˆÝ*Ÿ£'ëølç÷BꡳÄýî±#uAVWJå]±¸o5»Êá)s¿öa¬á`lé¾v™“ÿ¤¨qtmº[™©Z< •Z(æË,ó7©ýæñ÷H AÉ"õOâfüNñfjx©!R©g*ÝÕ¢j‹×ß1/õGÉx©¿y©I!õp´Æ33õª!õ«îäl¶M©7noo·Ø {Ʋ]óÙ­˜¦éÌw°¤Ö»2Uw6ˆÔ‡e›<¡ú·]�ÑWüõÎÌfç·Ë#Ý?nò×b/uv^»suùŸ?Ÿ‡©ï‹Ôµk¡„°eµxвjÂH­ÑÙ^æEÜ÷ñâí²Çûy‘õºº /5søWõ|£DêsŸ*…m–°LŸk,³ÌwÜ8$RÌãï7�‚’EêcÑZ&RÇ.¢…ºÔ©W ©ú©+Ž|Ÿ~úI"hû5GÛ7ßÓWw<ã÷n2Hý5ÏÇöñ%#joþÑwÉ µ jë·¿L½÷–’ñ;›Újç|#3ÛO=TîýýžíJæC¥6ÛNZìÅÚíó¼æMž·KYRx!ê¡wsÓsFèt¾±Ì2ßqã�H0�¿ß@jJ©£¿_ÆDê„ :vv2 5A@êÕBj�˜Ïöó¯™ßK}.ëRŸ�ݯEeêÏÿñçœä?®�RÿÛÏ$Q;Lm?b¤f“ëy�sÍ„‘ºÀë0ë9·&öBíjMwi·ó Bê’¼�!¤Ö]ë'Ú|c™e¾ãÆ!‘:`¿�Ô”,R¯.õÚR½Ô“ÝÔ“jha/5A@j uDvÎn^KÊî×��¼vß¼ŸÛî3éÿP¦¶ÄKÆÔä·3]}ŸÝ9Rß%�¶&³ô¿ó"úš“EjæŸjŸ,{o»}î–Ö9¶Ö…Ù‡Eê¼ÉºÉm †-zžSh;sËûóŽe¦ùŽGÑIýí3�¿ß@jJ©2)ð;-{©çÍø�ºÔ©�ÔÑL½;ÛŸ�$g÷ëÆ›‘áŸÿuBHýÿüÂr^þó§of#ê–õ£{í2 ¯R®>OÊ®j+ ž¯j޳ W® uþ±Ì8ßñã˜Ñ<þJ©!è¡‘:¦—zµŠhÁK A�z‘úÓÑöëSóýñ/~~ûu’vß_ˆ˜ï�?|óubHýÃ?�^þýO?©e·Iˆ�›=Æ}eç»êv! 5=R¿ŽQD+*ðûÙ2«h=�³™H A~’­ RÏ£{Ú½mïv§ß'n÷›Û�ÝÝvõ~vHP@½ø:1îæS™/�H AP|/uºò}ÇLO¤† ?É€Ô�Ó.�:¥v-¾¿h ¤RCÐÓBê8^ê• üFÆo‚ð“,Qý9A=e»@ê”Ú-^Rm�Ô@jzšH�ÚôdS˜zb-x©!ÂO2 5�H »°‹¿ß@jZRGÕ¥Žé¥~–TsS1¼Ô/#2~øÿQ ‚VøI¤~ºHý6AÁ.ì.Ú.¤† Bê×ãœÔiÉøýlÞ½Ô@j‚€Ô@j 5�vaH ¤† D�zrà÷óåÅ}G"õ�‚ 5�H ¤†]ØR'„Ôøï?ôtùÅü~5sz²Äò“=‹µ—:øÍ2~©!R©�Ô@jØ…] 5�‚†Ô¯SOÔqËRG¤üRC¤R?B»MP@=ØR©WOS1hÅíA)MO6#S3çq:ªh…ÝÔ@j‚€Ô@j 5�vaH ¤RCËÝKý"ÙÉ¢˜:j/uQ©!R©�Ô@jØ…] 5�H -©ŸO‰ü^¢›úùó˜^j¤'ƒ H ¤R©av�Ô@j 5´ŒÀïôLOö^j‚€Ô@j 5�vaH ¤RCKñR¿œ±ˆVRH½6w]ê×ðRC¤R©�Ô° »@j 5�ZRŽûŽFêe›ò{jà÷ÖÖ?pmm�ÿ­§ A@jH ¤êÁ.�H ¤RC‘{©_Æ üN©ŸÍç¥dü–¬,‰y PÇhA�R©�z° ¤R©�ÔP4R¿xÓM�Pz²µÉ ¿#êR¿ŠòRû`y 0ÇiA�H ¤Rõ`H ¤~ÉåråƒC~´··ë=[ý`o/z—ª¿÷Æs´½×•@�H ¤Rõ`H½ÒHMNW©óG¤)_µÃ]R¯®ÎÚeBZÚìL�áÒ{JYz²(¤^K×^êèÀïcÓ“ýÃ?Lçå8m˜zOêƒzTy³Ç¼Ï'dGœ}³÷óÞ¡ó.�‚€Ô@j 5�¨»@êGŒÔäØ�ÔºîÃBß?¡× #u‘A¶%Bß`Ç µ~o¤öz„EÍßûÚ·pþU�ÃAêqË©‚nWo/õ�Ô±½Ô©·8ar(¬{kRo…�:sx˜9y³··Î˜Ú`oZ{'ü¤¹·×PÜw�Ô¤R©c÷ßPv�Ô@êqH½Klm„Ôê¾ÕíZ=v�²‘-“V?¿u”#–îÒN™\Ü)KBjÝ&·üÅéø+�º\æ×–ÛÍ.¿¹ÑœsW¢»›«<»¬ló£w¹Hýj¶½ÔKÝJ=©_Ò“myXÙ÷Âã‚Þ�Ô[‘H­”ù~é9Szäó½Ï 1+äÍÞÞr"Þ¥:Ü}óÁ'—%/RW/>ýà“*�‚€Ô@j 5�¨»@êUGju�påH�!7ëj!C$ ’[µ@Y±Kßk›¾µEùÐÔ¯l²»$¤6…³¸Hºš°HÝ#ÝC­Ð#äê�š2p;0ÿ ±Í¼zMn ÌkN2Ë5{ŸØëÚ©É®¡$§x¿ù93GšôT“ä*ü²–¡_5 Á6ëåfü~5kÆïµ´~¿ ÑÚúS{�Ò‘Hx�Ôr¿ô›½¾Rû€m­þÀ¬|þû÷‰w¥Á÷öˆ9Bêí=þV H A@j 5�H Ôƒ] õª#u¾Ía�#µqÈkjÕI–³`-ÏË=m‹–”ô®‰¥ºË@jŠÎl4ä20Ø0RëCr(v/שyf4ßüÛ½_<,äõ.é³××7gãÊ›é2òÌf›7ñ!õ¾8¥µÄã ~™FH „»Ô½Ô“3~§x3õT/u„:ôÖ?ŒGê"uÉ0Ž«¹½\EqàÙøÍÿåï^}ºW.n�½Ù;w‘ºøùÞ?®+‡Ÿì©!H ¤R©�z° ¤^y¤¦D×Ñ=¿õ€yd) r$rÄÓ9ð d#‹Ë@ê*¡ÐªeNµÑ`ÃHm’.ß•|Æ®¸?R·Rûæ_%ä®âYGGRÎû�š‡Ìçk|œ>¤ÈSwdÀ.;—gA¸KÍøýr¶ôdË­K=“—ú&´÷Ð÷8¤²Le2R·÷º º×÷ö ©�öÞ°«JŸ©!HýHõUr„ùÕS¶»,¤þeräóKØ…ÝEÛ…©Yúìm‰ÔF»lÎÁëõˤæ)Í´O¬&v~Ëswä‚u§^08�:-{©_¥v/õ¼¿_ÍœžÌ‹ÔÑáà#¤¦|œ�ˆÔç{;£ËRŸïµùÑ.�‚€Ô�To“CÌ·OÙîÉ!õ@=ØR©'"5‹’f^êsr çÕöØÀï!§Z^.Ûå užŽNøŠ}ƒµd%0Ëäå?°é�rANî‰ÔÊY­Kºl|ó·xEl£ËÈýˆ éb™C–}<„Ô¤¦åµ#rcrŸúyÁ=g²COÕxw@êUðR¯V­1u©cÑŠDê1u©é‹õR×ÃH}ÄS}+ÊaÆMOv²÷ ËXf¾RC�ú‘ê]bùº¾z÷¤í&‡Ô~»É¡ìÂîÂíB…Ô”?Rg É]tÉX/5ÏùeQHÜYZà7ÃZ²‘Ï+�z�ž+ÛÄætÊÒ‡ÙeÂÁz~¤–²K2¨{4ÿ!ÃÝ:!ÌÖmBßo¢¼ÔtPDTÿΟÑ-·f5;rN©Ó’žlR­¨Àïgˬ¢õ<ÎfêR»�ìaê Hí:²#‘Ú¬¾Ùû•ÏJgï�BêÃöNLäÍÐ[ õÙ{S1Ë(¢A@jD~?hôÓ³ûç¥Ä}'èNÜ„]Ø…“:íH]q³ar<‰÷Ý�rj¦ÇK9G!u>ÓéRxìëËCjJ£Òíìì…ÑL‹êiŸìòÚìhP™ß^Eòt½ï$þöοÈR~Û=þP¢P£¶rƒ‚w/uÙIOÖ£×\ôÅæë;›µçòg´»nç,ïCjÑJ±—:]ù¾c¦'s�Ú¿õÊã�ŽDj%ˆÔ{ŸþýÿO3.Rïïí}ÀÊcù�š¿ÛýÕÞÞ®ø­ÔXÃö>RC�ú±j3!·íW›OÜnRH°ûnIÎDØ…]8©Ó‡ÔQ”]™‚˪YH†rÆ!õäÁ*¦7¿·RQÒ^pþ¾µP¶"Û³'Þvº¦ù»S´«ã¥^ÙÀožñ{䦳ǽ.¢å¤vêRžÛ=ðÌÀpØæÑ€IDATZ¹üw^��š¿›=ÿ|oïÍ){™H­ÔºôÚÚöÞ' RÃMý€NÛ§g÷ËdˆúËÐ3“%9avá¤^¤N�b"îÊÚƒRŠÔ©MO6…©'Ñ^joÕ,Ÿ‚…Ô1c›fÔ»•¢|Ë8�@�úQï¦þò«ôå»'o7‘:Z;õ6—D>° » j 5�J%RGÕ¥Žé¥~–TsS1¼Ô/#2~ /µ› lQÇjA¤žú�c~¹ »›?.ž¨Œ°û.öÙ|»°›Œ]H ¤†©_�sR§%ã÷³y÷R��:š—!ÝqÚ@©SÀÔ_nÂîgŸ½]8Sÿø62as9ä»° ¢R©¡”#õäÀïçË‹ûŽDêµÙ�:Š—C´¼¢† H½ Lýå&ìr» Žýþû‹fŸqä»° ¢R©¡t~¿š9=YbùÉžÅÚK üv3~GòrÄïä-D}C¤~�ýÔ_,’0ÿÿíý[sGš¨ ó Ñv„oÚ­¯Û{K¤ù’í6$S6M °@”Dƒ‚(u`Rx�“l¦âwÂÖRKË“ ’¥” J ¡Ë“…ÝD+.¥î�¼/õYj@©Pj€®)õ)ï¼o¹R÷r-uØ’ßLü”¥èmy²!'~ǧÔ}ѲÔ'™ø (5J §R†LSÇTž¬?¸à·d_ê“d©¥@©âPêPåÉ$ûR÷÷'câ7k©¥@©z´–ÚSžìDÂÖR7©O6èëÔTü”¥èªRû—' ÎR'¶<¿¥@©z²–ZªÔýÉZK-Ÿø=Hy2@©Pj€C±–º‡IêÐYj”Pj” Ç¿¥›h%­>™d_j”Pêq3ó‡zýÃ÷ä‡×ÿô‡ÌMâ:¹ñ�¯üç¿ý½ƒüíŸ|ý�7šÞï�L6×a²™7‰KÜ^Ä” #J}²µµÔ=]J¬Ô')O(u�¹ñ‡ŽÚ¥Í3ÿpƒ¸ ~÷CGmÚæÕ?ü.ð~3¹.‘¹A\âÆPj€6•Ú?MݤâwR'~Û*~Ÿ*3ÈÐqøÕ«i¦éÕÞ÷]cïÕMâòm—„Z“êo}%äæõ\¹~“¸Ä�3. Ôí)õ;a+~'x1u`–¥”:þõ·ßw?×;nq÷—¿w•¿ø$ªods]%{ƒ¸Ä�/. Ôí+õ�¯R'x_j²Ô€R'–믿ï2¯¯Wùø_þÞeþEúY¿‘ë:7ˆKܸâJ ЮRŸ ¹‰V/•:ô&Z²}©Qj@©ãÎQwÝ0ǼAÜßuݨ§þ]OÌGê>Ä%.N�R$5Kí™ø}"¤RÇ$Õ¡«“¡Ô€R'aõwßÇÀ·7�{Üù{ üÅã 7³q¨Oö&q‰G\@©:’¥³/uO³ÔÁiê =´XK (uܼú>^÷¸ßþ=¾õLsÏÅÂuâ7ޏ€Rt$K=B©{»–:jÅï“(5 Ô±Oûþ!ÅüáÆñŽû»¿Å£ÔsMý¾™‹‰Ä%.S¿Qj€£”¥>\›h‘¥”ºg¤ˆ‰ôñŽûúo1ñÚõ[w\ê“!.q»ZWê½�TRþ-¼”É…GÙ€ÓS;³Ž÷EõŒ�\¯î&ûh'¬¶­c8‰Sê¡›hÉ&~÷õr­�0‹©Qj@©c_I—aþðúæqŽ{ãÏq)õŸoö$™˜Ë—¸]� ”ú–¨%åßâÀKY*‚œbÇñƒ]팞©Ã”3!›N ±Ì¯b‡2K�¬zß!Ë“¡Ô€RÇþKYlŠùCæ8Ç}ñ·ØøÇØË2Kfè—¸ÌüF©[Têúúúz@–zÅ­Ï©õõÛ‡J©ÓÛÛˆÎáÊRÚ‰ßTü”:Þâdñ)æ«ã÷u|Jýº'ós]3t‰K\f~£Ô-*õÃà³—Ä„çg ‡C© �–ÔËÜâ1¿‘%N©[ž¬‰Sn¢E–PêXù§øóŸŽsÜãSêŸíq ñ©O�¸Äív\8ÎJ=/ö«R ÔÉQjÙ¾Ô!³Ô}qIµ*D–ú„¤â7Yj@©c廸ó»ã÷ŸãSê¿ÚãfãSŸ,q‰Ûí¸Ð’RçÊ¥œÝcs¥’c©rº”uüiž”/øt˜--ÚKyÛ»éYûQg0÷¥4Sêl)mô’¶ì#ýU¾Ñs[Jíº�\©œõ»~×Í¥ÕËj®Ô9ûóA©“¦ÔC~Iê¤Tü–¥”:n^ǧ˜¯�sÜ?ǧÔ¶ÇÍÅq‰Ûí¸Ð‚RçïªÅ»ö§M�-m¨ï—µ¢Ùy!^®Ì+o—r…T]ù³jü^º­6ª<’u¸PUmn,ª¯—D=û¬¦¼ßÚ3ôô`By71nH©=˜÷R•Zé:·¯t]YÈL?TN«�ëÇ'…(©šº¤^ï“™B»Jm»õq”Ôòhµméõ»nî^E½¬TÞ¡ÔkbK±¡.›V{,ªê+š[«MSBg…_Ê’¥ÔÁ¿z7ï[ªÔý(5 Ô ä‡9Îqÿ#¨qQj”:«WÐõ}ÝcË5ý}MýU;-„^.[<˜3šMÛ‰9o‡�ŒCµåͺ˜¸këOý�ÎzÆÌs)ÁJ­t½¦·/Öõ?·µŸ¯Š E£ÓU#ÐZ›Jm¿åq,Õü¯ßusEãÝ-‡RßUó>¶ô¼©7{©+õ3K©IT'D©ý+~7+O[}²¾Pk©=¿©ø (5J�R£ÔÄ%.JÝ®R+ÂW}Y^Qó¼ªÇæ+BÌÎñ$¯Ÿ¨¬,ÞS�u"µ¸°¬Kô´ò~µX~¤´õl �ÛOŠÙé½võº–Ë.O*^]QçGϱõ¸üxK·Lg0÷¥4UjÅVK%Mcw÷ÊŠúnjÙáªfÑJŸ«ù¬zÁ m)µãvÒš/ë7¾ã½~çÍ-N(—°PšSŸ]�R‹‰—åò¶òGÎPêÜâcå�ÅÅ¿”%+K�\£»-µ¤ä7J (5J�R£ÔÄ%.JÝŽR/ QWu°p[÷Ø%Ã’_ 1®Ÿ–€�Ælêšæ«ë†$–k¢æ^O=iÌX~´¼œÓZNh3Àïj2žW¤Y5ÅܼYw0÷¥4Wê%õÏ !öÕ‹7.Q¿¶ª˜Wæ×–µ¥ÔŽÛQø–q㛞ëwÝÜ®ªÇmat Ro–Œ»)JÍZ꣑¥V“ÇÉØEË›¦F©¥F©Qj”š¸ÄE©;£Ô+BµyÝc«bC? %{ã{ ¾)Ô ÜÒLµjjáŽ×T'Í Ø¦÷êyì\]­Ã­Ü3[•ÜÁÜ—Ò\©µØ3ÆiE]~‹ºYWE=m;©¥nÜŽò8*ú:é­?çõ»nnÞ|H«ÁJ}Û¼À”:ÙYê@¥îeu2™SËÖRKŒ¥”¥F©Qjâ¥nK©·…È›Z¨xlVˆjQ£.êšñé6X»ÚŸû¢¢5º¥ŸSòÎüžRk‘=*2ïU“Ém:ö=­÷—êÌiW0×¥4Wj½‘Ò•–/ëº-jYÝc'–ŠíWüvÜŽù ƒ–¶O¹¯ßys9ë!Ý Vꃌqõ/QêC¦ÔMf~÷0M=02KMy2@©Qj”¥&.qQêv”ú¶*ƒ»ª¢–„�´j|� ¥¾ÛPê’^K+“±y£#¯«–[-J]°rµ¹Ìš­÷uw0×¥4Wê S©§mJ½¥§}sZ)n±œÊµ§ÔŽÛI[õØ”_u_¿óæf­‡´¬ÔúžF©«Ô'ÃTüNØZjiy²A²Ô€R£Ô(5JM\â¢ÔÝUjuÑtUCÔ«Ñ”:“~Vµ*V¯‹¯íJ}Ûì½*ªî`Qêœi½…âuG+}ys;›hÙnÇ¥ÔžëwÝJ}´²Ô'ZÜD+.¥î�¼/õYj@©Qj”¥&.qQêŽNüÎi…¶:)UêÀ‰ßºqÞS“ÄyûÄïÛâ‰VBÌVÇÚ¬å‰ß2¥.š šU«.�O—Ú†RÛnÇ5ñÛuýž›»eå¹eJ]E©ƒRŸòÎû–+u/×R‡-ùÍÄo@©Qj”¥&.qQê®—'»ÝT©Ë“Ùùž³<ÙCmYñ¬­�3XËåÉdJ=nl¥e�ßÔ/µ=¥6oÇ[žÌ~ý®›³Ê“m;”z߸ìl-P©SüF–¸,µ×©Rž¬¿/Z–šŠß€RÇÍë9Îqÿ#¨qQêc¯ÔÖÎUkºÇšœ]«lø*uÐ&Z«Õe­ÔvJÛZiY›ÖX�3�6'b+•{î`îK‰¤ÔËÚvØ™rµjÖU[nK©·£n¢µjÜø×YÉòßÜã!¹6Ñzf¤Ñ ¥.©‹±!©J=82MSy²þà‚ß’}©OFÌR//„"l»nµ<ÌWÌ8žq”¥F©Qjâ¢Ô(µÎ’"‚©ò½}¡{ìb]ˆñ…Åâ–¹/µL©§•FÛ åGI65¥–ÁÎåîÕE½ I§¨<*•?+y=c[M-–ç6E-çæ¾”(J�ýZ¯ ]P.mf±°øÀ¸�ÈJí¸U©ÅRQ»ñGž‡åº9E»Åö^éYÝ©ÔE!žóåq Ôy!&fJ9~)K†R‡*O&Ù—º¿?¿;·–•C©@©Qj”¥&.J�R»É.ë5ªëûºÇ–jFÑ구¯Rkº¨1çé/W5mêåÉ&èokÚ¯î…]ãè×EO0Ï¥DPê=sòøŠY{{9ß–R;nGyë›ú[ýq8¯ßusEã�s_ê¾q“k©3Ëfy7èµRŸ’”';‘°µÔMê“ ú:u«¿:Û®û-ß3‡g¥F©Qj¯Rgc„¸Äív\¯Ô™¼&‚§o»§ù\ýQVO—îJ­ÏD~ æµ?gµ=ªž<’ôW8Pó²µ c­‰ìœê�ÕÃà·µ:ÜûÆ/òö`ÞK Tê%£@xJÝÀJWê•ÌœU"¬¼¬Êoå@Ÿ˜}-µývT.©W¼¹š•]¿ëæV*ê±TÞÔfã ¬«n”7Ô)éÖNk ÿœaßé[(ub”Ú¿<Ù`p–:±åÉ¢NüFåPjÆPj”¥F©‰‹R£Ô²Ll¹ì˜dœ+•ò!N*¥U]Í:' dõ�%ÖZ*¹°hïOy·˜õ æ¾”¥–²¡¦~�¬¾Ú*OfÝŽžSΕʾ×ï¼¹Bº4]�t¸Ø|Rw6?ÅïdIPjYy2™R÷'k-µ|â÷`›åÉP9”šq”¥F©Qjâ¢Ô(u§y T�GÍÙÙ$H©³›b[z íŠß6¥†c¦Ô‘×R÷0I:K�R£ÔŒJ�R£Ô(5JM\â¢ÔIRêù”ºòìÙLVzlÖ\Jí øìÙ:J ‘”:ìÄoé&ZI«O&Ù—¥F©”¥F©Qj”š¸ÄE©{ªÔ¥{Š1(µŠ|æô3é½jJ í)õÉÖÖR÷t)u°RŸ¤<JÍ8 Ô(5J�R£ÔÄ%.J�¥æÞ­ñNwùè–Š›ê$ÛìCËåãj»¨XÜ“ªD©ÝÁK†Ã­ZiO‰ÊÍ ‘¶ÝÇKÅÂÕ÷9%ÈžãœÛbÝ~Ã…º¨— µwõîjj’â�³¥+¸ç"+µ»c÷{¿»ÒH ±æUjWÊýkIç‚âÿ÷‚ï*hlm¯]§¹‡Ù¯wåR©·&¾–|qb»åŠõ§«ül#°¥ú±]RŸÿbE|�C©Qj”¥F©‰K\”¥è–R…ØDK6ñ»¯—»h „YLM©ù�××;?›˜P7j¯ŠŠ™ ÕEÈT“f6W™x¨èNÍP;¥‡%·î¸Ú*û ·ëUjOpó¼|M&FÆëI3s¬³%„>;9¿éú *\’j¼¯‹y×»šš(òéÊg»‚{î ²R»:ö¼÷»+ãqU÷¼Jíꢨ’ÉL ±Ø2plm¯]§¹‡Ùÿ™U´gvàýjÃy/Eë�m!ŠA-3·ÅfÎü†åJ�R£Ô2V¶w®|{Ün-½Ükó~ÿ%FP=â¢Ô(5´Ÿ¥NV½ï�åÉ¢)õŒ ŽÏÌËVW�J]˜ËއY©µ¦„¸í#wÛ¹ZJUt�R{‚Ï‹jÁù>Ö¸ÛzÜ÷Ï̯F¥.Äq‰Ûí¸€RĘ¥>´¿#Tü^5ÅmJ“i÷ἑ®6Ô¤$ÄL&“.κ÷ÛJ ±ê#wÛb9#UjwðÂ׿|斨ܜ¨f²å¢Q›« ÄCãxÅ8Éü@Õ­ü^©Ð¸Ðµ‚ùÂyÅ$µÕÒ\öø"*µ«cÏ{¿»Ò-r<#QjO+žuß~-%ckí:Í=Ì>½Ï 1e>½Š»wǽXK¨sÂùiôÜõºÙt]öeL8rùt—ÉçÃ5 Ô]W꣚d^ŒS©÷.ŽXŒ½ŒQ©7qG×��R—wwwÇ«\E%d1VÕK+ÇQ[”¥8ÖJ�ØòdMœ:p­Yꊨ斴*ÐÛWÎßvIíc!ŠÅŠZŒ{mÏÑÏ’w½­´­D©ÝÁ5×›s‚%*·$ÖRuµ˜¸~’•ŸÌcå­ÑNécò¡ò³‰‡{VÞ}¿\È©U©]ŮԥF©ŽŸRËö¥™¥î‹KªµP!²Ô'$¿#d©kâÁ¼±ûо™øœÝØP|x"åP“GB k³GŠtíZÒ¶¥v/Zu³”Cû~*·/jö“VÍe¶eu%[;å½±ÁÕ¦aŸ��÷óî-™¼Mõ+¶’Ô¶‚jŽà’ÇQ©]{ÞûßÕ¶V–M¢Ôž.‰ÝØR~¶‘oÞÒolí¯e§I”ÚÕ¬jÍÔŸ1°}33Û½ä„XÖœ[Û'-Ð2“I«ß3|­îÓ•‹41Ùl Ï&áPê®+õ­á‘(õª®Òg'¾Ô^\Š+î®wL{qæ˜(uJ¨cV®GÚ&‚1ª^¥F©Qj€c«ÔC~Iê¤Tü–:’R´MS‹i5�hV’Ö· ^rfrGÞw‹¹…õÆTê3­5ÞY#mëUjOpå7‚YkwÕOåÔ­�RÓ‹©Š¾_’ºá“ºžYÛ ú–­�šÙÜ-å‹KæEîú»îÞmÙÓÔ�×]�F:ƒË_D¥vÝ•ç½ï]•õÈ¥öt¡ê¬ú;ÐN¶yK¿±µ¿–�&QjW³ s}¶:½èþjÃq/Ê™ûŠþeÕ=ÊôÙâ~-3éUcëÇÙ(ã›Íøl®¥n�ïZãe#g{ñ»V‰W[Ï|éûï¾{]Ñb¿Œ)®fÒ{Ê«µ6ã&¥Î«ÿ-Æ­\9õ»Ë2JM\”¥ˆQ©ƒ'~ônÞ·T©û»©ÔuM0ëFPyNããK·…9 ÛP“q3¬¾2÷Τë¦Ù%FÚV®ÔŽà+�Îê†wIT®"æµ MWô+žS»y¨¼Ù0‚5¦ªë…ªæŒ«Q¤«¶±º®hå¦kâ·§©Ê[’Újé .{|•Ú}Wî÷¾wµ,&¦äJíé"“y9¾½ûDù-(Ý´¥ßØÚ_ËN“(µ«Ù¼ñm‰¶ó•³Jºû^ÒʵŠååMml A-•_a+»Ûkî¬~âŒÚ×g“p (uLJ}övÌJýZ]½=ü½öRË’�Ç÷Gméöë†Õ ¥ÞQÿâŠ_¹ÔïWQjâ¢Ô(5@Œ¿O¶\ž,¶úd}¡ÖR{&~G«ø]Ó÷ÖýÆ^¼º\1|§Q�[‡õ¼óóÖjW»ÄHÛJ'~;ƒ—„Ø1ôÂܘZ¢råRÚᢑWYÛ3¾0ÚåJ%Ký¶ôæÕiõmêk}÷ëFï$u#;ê .y|•Ú}WÞ»”ßUʉR{ºÐÉÎyʳÉZúŒ­ýµì4‰R»š=´¿o»¾†ðÞËâmh'Vö�Ø>-³óÆØç—…xÖú8¤c%¹×€RÇ¢Ô£»¯×cVjMmÏ꯵:e·â‰ûò’ÂýõüñÉR¯)kíį\ JØJO”zjeîÑ‚rÅb1ÛŸ{�¶Ç省·¥GÛ«jX³ZZqfug/×^Ü©½�Õ¹Éiýµr;¥BîÞ�Vh.Ÿš»µ3kuïz›[™»u�Ê_Kã;«\ˬöЕ{(5J pH&~÷'«â·|[jIÉïHåÉÌTlY87<.{7$ÆÔä‡fU©\Õô§ÄÈÚÊË“9ƒç¬qÙ”k©Ê™b^q~e}ÿ ¨îδ"•©»ÚEÜ"o)¿ßÞÅw­ë}hîw-o©—<¾ˆJí½+×{ù]åꢲ8­°¢<±Åtе6X3ŸD@K¿±•Þ¡-€D©]Ͷ­GüÀ¹™™ì^ ¥g—vò™yc¶OËYó+˜LvB²d QIjŸq®¥ŽE©/)Z·RÿðHaE}&Ή߶D¹:|øõqPêÜ×Ñæ}·«ÔÙ͈3¿ÛUêGj`±µ¨Î<Ïw-®ú=¿G‘®êo+úçnEFRíÄÝ1 ‹î{ÉMˆ'9c @=ÔrÏ*¹vOýõ'áJ�Nê5ð+ÙÑWêïµ"ac{±Æ5¶ ;óàõwÇB©o ×W’q)õK!¬ âSjõñ(—½×U¥~lx®ê«"§Ýªº€kOýs\/Šª.UºU©T¢Æ}Y¯×·õ_&ÔÔ,¶–ZÌM«k¼Äíl&÷@?â|[¨kiíLVÝÊQùÇÕ÷ZÚ_µóÛ3‘¾­áoi”  J}2LÅï„­¥––'ìL–Zµ×úJ>¿R7–No ñäq9·°«üSbŸF­Ðz)[Zb¢¬7� Ü5–Ým}”Ú\µ­ñ\¡XwÉ–;·]ŸÌåŠU]ïé´b�»viÿÌ-• eåßûZ)cl?UÌ—WÜ-=Mµ…׋2¥t÷ÜAd¥vwì~ïwW&’òd®.ò_+gîåÊê†_ÛÁw4¶¶×žk”+µ»YJyþ¥Lþ®õ½‰û™Y÷¢Üdu!—»W·*¥ùµ\V7ê*çÔg)”¥F©ƒŒúýgßõB©Çæ_Æ¥Ôÿ¿ª›8•ú�pT¢ˆO©U©­Æ®Ôª€j_�?ê¦R«·kßÔo+Þ;©NiÓ¿ö×/BýGk«Ü¡¸“º¸jJ­ÍèÊ©®œÖ¾�®×—ÝogµuÎê?²ZÙ÷ZÚßtMŸ PK·5¾€Rt8K}¢ÅM´âRêþÈûREÊRk Ic·fMž²ÖûŠ3ç™™5W2M¨*—¶O½õlålë«Ôîà™’QãÃZÇ+Q¹Â’yÒí¤•Mk�•óœ’y5}šsqÂ^ò¿–öÆW¯z6_@©Qj€De©½N=��òdý}ѲÔÑ*~kQ—§Šö"ÙÒB^&P™©bj¥¢Çfmm-=ÁK�S ¹L Rg2Ó++Ó¶sòÅ�ÉiY»Ü^j/k�œß+eåWìiê{o®à®;hc-WÇÎ÷AwúZ3ù…R!\Kÿ>wpZ@ïùbê^9æ™J©Ôl¸§›-/¤3‘Æ¥æW²ã Ô†Qï~ÿ„s• m=uÔÒ´¬²Új±Îœu4Ä— ~qMSÞò(µõµ�¨%oŠ=t-mŒ¯¶+õž±Wv ¥F©z¯Ô‘×R÷0I:K�R£ÔŒCLJ]¬þÃ�//ΠÔ(unÅ­Ô_öF©¿�u„=û:rÜŽ‘vé^‹Xò»Í¸ VÕ¬˜•:“Ý{ÙÚZêž.¥Vê“”'C©‡˜•zòË;w–ç–ÆîÜy€R£Ô‡@©Çz¥Ôß~¿eHõû—¶Û¹ßäԹ‰0+z;­¶Y5‰»åzÛ‹[Ô*„•KÏž„©¶�4ÅEØvÝjy˜¯˜q8ãк�Vîܹ¥ü1ûå�_΢Ô(u\θ߽\}ð`ýàûöâ&¥Ö6.¾·r©¬Æ{¡zó�Z]åã¢Ôüý�RôH©ß [ñ;Á‹©;–¥FåPjÆ!¢Îïܹ¤'Û�”¦F©Qêã¤Ô�‰{¨”Z[ñÚz¡°¶âNÕ„¨d{¡zé «RXµE©Qj€ã¡ÔC¾J�à}©»’¥€ˆ:;sçŽ^˜¬R©c’êÐÕÉPj€^)õÖ�/�Ww~¹ˆR£Ô(õ‘Uêë1B\âv;. ÔÊR‡Ù—º¿§Yêà4uÐZ­­¥€ˆ:{ñŽ0^-ݹSD©Qj”¥Fõˆ‹R£ÔÇ'K=B©{»–:jÅï“(5@´¿©ø ‡R�ß¹3©¿Ú¼3Ñ£M´ §_¸u{=Ey2”¥F©‰K\”¥ˆ[©[ž¬‰Sn¢E– ¥~|çNU{±sç·ìK�R£Ô(5ªG\”¥8.J-Û—:d–º/.©ÖB…ÈRŸ�Tü&K ‡R/^2ª’‰;wR(5J�R£Ô¨qQj”à)õ�_’:)¿û¢®¥F©bRjµÐ÷¥{éòÖ�(ó¾Qj”¥F©Q=â¢Ô(5ÀáWêà‰ß½›÷-Uêþ.(õòòA(¶ëVËÃ|ÅŒÃá‡FªÈôµ2Ø?Ì¢Ô(5J�R£zÄE©Qj€ã¤Ôþ¿›•'‹­>Y_¨µÔž‰ß­VüFåPjÆ!²Î.>øR-µýÛ…4J�R£Ô(5ªG\”¥`âw’Œ:ì¶Ô’’ß-)õÁAgÛu¿åá»bÆápŒC$'-¥¶gŠ�ÓY”¥F©Qjâ¥F©Žr–ZM'c-oš¥F©‡ø•ºÃ:‹R£Ô(5JM\â¢Ô(5À¡ÊR*u/«“ÉœZ¶–ZbÔ(5JÍ8 Ô(5J�R£ÔÄ%.J�RôB©šÌüîašz` d–úJ�R3(5J�R£Ô(5q‰‹R£Ô]Sê“a*~'l-µ´<Ù Yj”šq@©Qj”¥F©‰K\”¥èI–úD‹›hÅ¥Ôý‘÷¥"K�R3(5J�Rɸ‰T�¸(5J þJ}Ê;ï[®Ô½\K¶ä7¿QjÆ¥F©Qj”¥&.qQj” 'Yj¯S$¤Ýðw•X¥Î‡Rç“z (5J�R£ÔÄE©QjVêS’òd'¶–ºI}²A_§n¯â÷½»wïªg/Üm°ÐN£¸QõÛϲ�=*¬[]®dšõ©jºÒ~®™ÊÙOÊ¥Ö«õµñ=éuØ{+¼Ü}"*ë“~Ú帒ü­»KMž–æq;ÕMñd=ݶR—ÖêÕõ�œu­[5Q_[ñöëj˜)Íiïó’+°7õm@ŸSÛóBT×K�JízîîaöïÝý -]]zÞû·,o/oÖ6òQÆ!¯ÎN%õPê(ü!>ÃüÃqŽÛ+¥¾Ÿù\%.q»Pj€)µy²Áà,ubË“udâ÷tM¡šæŽ°Qðo§:߮ѬšêQ‘ŸF�·‚[êÜRûl¢Ôö“ÒU£÷g2™²õ–}èlèÖ.Ç•ëBl6yZêÍ-ë]ÖJm*µùäçõ§ûÀx¿›sõëj˜™1ÞW¼‚êhêZÿ>KÆvÆÁõÜ=ÃìÛ»çY[-ÝCé~ïß²X3žÂb„qÈÅ«³¹¤^J…Wñ)æ«ã÷çøŒúO¨qQj”ü•ZVžL¦ÔýÉZK-Ÿø=ØÉòdœâ†IM¦ÔV;ÝU'¶SsŠÚT ™ –‹Bl�¾Ì¶ÔØ!”ÚvR^qß­í™»5S¯½Û{SNª>{|Ki8#Õ.[§ÙUõõf“§¥ ˜oåÑã}åY¤ÛRê9ÅÊïÎl+OsBµ�¬Òc}=uë‰ûÎ~] 3ãÊeîÎŒ+f_+»®ÀÙÔ;´¾}.*-nï¼\Wnó±ï8¸Ÿ»g˜ýz÷ŽºÙÒÝ¥gh}[•§°ôxfKyj¹ã�„eÌI^J�R£Ô=�û§)õ�«±qƒ¸Äív\@©:¤Ô‘×R÷0I:KY©SB¬93Å™´Û•{QgÙf©\ l9+D:|ìlEÔ«Í”Ú~ÒŽsª!–jÆYös콕„x¨NR_Ø4»wj—­ÓEÅÿžT}”Ú¼d8ܪ<z u=¿ZP4öžòçKÅÔÕ‡–S.dÏÞ¯»¡ò¾^2ÄuÜy¡õë3£ø¼6W¾´)æ ~ãà~îžaöëÝ;ê¶L½£KÏÐú¶|(6Œy“Æ!—€q.ÁIj”:€ñ)æ‹ã÷§ø”ú'T�¸(5J íOü–n¢•´úd’}©£*u^ñ’=—R+þSl÷ÀÌ`æ*[NšIÑP±·•7M”ÚqRUTôŸîNg?ÇÞÛŒé|Š1æ½ÚeïTñÓ¹]¹RKŸ‚òïsm(uÑü^bZu¡ó–ú æü¦ó‹wCEd�€u1ï¼VwSÏÐúõYb^_ ÿlbbÖoÜÏÝ3Ì>½KFÝìÝÝ¥ghýZjF×Ê¥/Eùj#—›Í%רQê®Ç§˜×�sÜñ)õ T�¸(5J ¡”údkk©{º”:X©O¶_žLQ̲K©Ý™Lw»Â„XÙãKQ»¬n¦ÔŽ“fæŠúOW½Jíèm©²eÍDöŠ¢£Ó¹ZJµµÍ¦W êËzj1­&�׃”ÚñÜ=ÃìwÅÞgmkéJÏû€–jÏ5k'1”¥Žo5õ«?ÄÀ«›Ç>n,ûhýɛԻÑ#ó!.q1j” ©YjÏÄï!•:&©]�¬cJ½,&¦Ü2ù@’Étµ7³§ê«ñÀ+b^›lš®¸×0»[�òÕ�J-¹àòøøÒmaN¶U¼võf|°á�Î,{ 2¥vµ[1“ÉjÁíÛm*õËñíÝ'ŠyjK˜çT­}¨<± ãñÚúu4\¢¶±º®Hë¦dâ·£©{h}úT•º®ùùb]¶êÜöE„ý¹{†ÙÏÚ^PÎ1”ž÷-•ÈõÆp Ô(uŒS¿cpÌW7ˆ{ãçîõÏ’¸7cpŸ7‰KÜxâJ Љ,u˜}©û{š¥NSí¡i-uʨíªº½Û¬ÝŒ"3F ³ö·_�å’!t�Mãñi™­¨kl›(µì‚õ0#elœ#é-£mhÜXXlõ.íT¢Ôîv%!vô9scêöÊ“eçÌ*cÆ´úµ=C]ýš •gZ�Ö.ík}‡lï4út ­_Ÿ5!YOk!@©ÏÝ3Ì>½KžµûŠ­¡ô¼j™Ÿ·ªŸ£Ô(õsêW7ˆ{åÊõ®;õÏ×¥ónôÆ|ˆK\Œ¥Hh–z(„R÷v-uÔŠßÑö¥ÎÕEeqZaE‘ÃEÉš›"´K5”ZižmÒ£‘E4÷PöiùLùS}?½%æsR• è¾dìIlœ#éMK+WÒí’wêUjO»œ™ªW]u§J­–Û66Íί¬ï3÷Œm�=ýê o›ÍÕ/9îù\�Õ§shýú¬X™ì²sÄäg•¬½ �Ã,ï]ö¬=-Ý]ZïZæªB<Ë Ô(õQtêW7ˆ«ÅíòÜï?ùÄí¶ûø™q‰‹Q£Ô‡7K}¸6Ñj/K]vꦥì6mWn‚zè˜èëiY°|ÖÚáȧå¾ã/¥*ç9)W.›ó¸kzºÜ8GÒ›:¼.QJÙS�)µ·]ÝÜìêž+ßâ8¤Ë¦È»7…Þvî¶ínX[�ôªã $}:‡Ö¯Ï}«xxÉüÊÀ«Ôîçîfyï²gm´twéZ¿–½êÜA¥F©{´žúE7 óÅMâšë¸»Z™Ìß@ºê>ë]‰K\ÖQ£ÔITê¡›hÉ&~÷õr­�0‹©;§Ôk’L¦W”뢦v.Ôbäi9m®µVSÄ�:®ÔEk¥¼Ð—3û+õì¦Ã¨; ÔfB·j˜oD¥^£¶ö-m&óËÕqý}zSÌÛûu7œuãý¤[©ÝM=Cë×çŽ5ñ{F–{×_»Ÿ»w˜å½(µ»KïÐúµT>…ûÖ„”¥îI¢úE—2·¯^Ü ®-îO]šýýóO�qoÞè7‰KܸãJ G–:Yõ¾C–'‹¦ÔÙ’�¢Q3%íüY«0w`»—¦Á­še¡ýZn‰º6í8_5…Χå¢ùƒª¨”Jy©ÊyNRÜÞX=î,äåí­¬øgY¦]’§ Ujo»”±LYÑÈåh*§·ß11]›9}ÖºùÅ€CjÝ —Íã¹e÷¾Ü¡õë3[1ž“ZžlÚG©=ÏÝ3ÌòÞeÏÚhéîÒ;´~-µ:î·2(5JÝÓLõõ¯^uÔ3•î^\¿I\w†ü§×ê¨Wÿü§×?½h·+ös“¸ÄíI\@©ºž¥>´¿£íK­Ó(u[šÉô´+Ì+*]Ê––„˜(¶TÜ©>™Ë«Ö¬cߨ3¿´/µë¤m!ž<.çv…¨¥e2eö¦ âöc�’\»šïKíj—}¢(]®PlÔšŽ¦Ôù¯…XÚË•Õ}«ÔdknBˆƒtaZ1E½ÆšÙ¯»aQ(Oµ˜/?®¸[zšz†Ö¯Oõ ‚úJ>¿R·*KÆÁýÜ=Ãì×»÷YÛvwtéÚ –ÂÚÇ”¥@©º­Ô‰-OÖÄ©7Ñz§J½×ض9XgëÆä݉Rù^2§ù>(tA©³ëf÷©Ú[½­Û&¯vH©3¥šÑãAÄì¨ÑÞzšb[{H+›æÔè²³_wÃâ„ù~9ïºwS÷ÐúöÙxTëßqp?wÏ0ûöî«Ôî.=Cë×2mŸLžC©Qj” +J-Û—:d–º/.©ÖB…ÈRŸ�Tün3K­§Y×ä™LO»L&¯¯V®–›¶|¤IU}µÐ´¥ÎF8¥6OJU¿Vº²›—KíFKJݸ’»¢â)”ªÚ× ;™ö”:“ÞWÒæÖcóÓªõ+zž®»á¢ö^Tǽ»m»šº‡Ö¿ÏÌ=MÔkã… qp=w÷0û÷î~†�ÞÝ]ºßû´D©Qj” ¥òKR'¥âw_ÔµÔm*u¤vSÅÔJ9TËé••éÖcoÞd#[ZÈ·Ù{ô–¥Ç©…\„>=íó %{7_Ü™œ–öëj˜É>×ênê{W®†…òãT1×lÏÝ=ÌAWìî.�ïƒZF[@©¥€–•:xâ÷@ïæ}K•º?¡JoËÃwÅŒÃá@©¥€Jí_ñ»Yy²Øê“õ…ZKí™ø=ÔÞZjT¥F©¥”Âe©“kÔa·¥–”üF©QjÆ¥F©Pj€Äe©Õäq2vÑò¦©Qj”šq@©Qj” Î,u R÷²:™Ì©ek©%F�R£ÔŒJ�R Ô½Pê�&3¿{˜¦™¥¦<JÍ8 Ô(5J Ð=¥>¦âwÂÖRKË“ ’¥F©”¥@©z’¥>Ñâ&Zq)uä}©‡ÈR£ÔŒJ�R Ô]SêSÞyßr¥îåZê°%¿Û�ø½¼|аíºÕò0_1ãpxÆPêv¹™ùÃ?½þáûòÃëúCæfRãÞøéÏüïÿþäßÿûÿüÓ�¦qÿñõ�ÿü·¿w�¿ýó�¯ÿ±iÜ›72Ù\‡ÉfnÜ$.q{Pj€Žd©½N=��òdý}ѲԭVüFåPjÆPêNqãµZ›ßþáFã^ÿ[GmÚæÕ»÷w?tÔ¦m^ýÃïŸs&×%27ˆKܸãJ Ða¥ ™¦Ž©%)Ov"ak©›Ô'ôuêV+~ Ô�àúëï»ÌëëIŠû�ÿö]æßþQú ð¿ü½Ëü‹ô³~#×un—¸qÅ” Jí_žl08K�ØòdLü”º—9ê®›­â¶7’÷z×�Zqj‰Ëÿ®ëF­8õïzb>R÷!.qqj” ‘J-+O&Sêþd­¥–Oül³<JÝ�uÔß}ßÞLJÜü�ø£Çnüåï1ðOÜ›Ù8Ô'{“¸Ä�#. ÔQêÈk©{˜¤�¥F©¥Ž™WßÇ«¤ÄýëÄÂ_Ýq¿ý{,|ëIÊçbá:q‰G\@©ÚWê°¿¥›h%­>™d_j”P꘧}ÿ�Úþp#q¯ÿûÆÂ¿»\àw‹G©ÿæšú}37ˆK\¦~£Ô‡M©O¶¶–º§K©ƒ•ú$åÉ¥îéb"�Œ¸ÿõŸ1ñ_θ¯ÿ¯]¿uÇ¥>â·ûq¥èŒRû§©›TüîOêÄïl¢(u¯VRÇe¶?¼¾™„¸7þ=.¥þ鵎K©ÿ|³'ÉÄ\ޏÄíz\@©:¡Ôï„­ø�àÅÔd©¥NÎ/e±©í™$Äýé?cã'{Ü‹�Œ½,³d†.q‰ËÌo” ÁJ=ä«Ô Þ—º+YêååƒP„m×­–‡ùЇÃ3€RG,NŸÚ¾JBÜ?ǧÔîɼo×ÌïL|ê“!.q™ù�R¥>r­^*uèM´ÚÝ—•C©@©ÛåŸâSÛJBÜÿŸRÿ7{ÜãSêŸíq ñ©O�¸Äív\@©:”¥öLü>R©c’êÐÕÉÚVꃃζë~ËÃwÅŒÃá@©£ñ]|jû]âþÏø”úÚãþs|JíØ¾+Ÿúd‰KÜnÇ” CYê0ûR÷÷4Kœ¦ÚC«µµÔ¨JÍ8JÝ.¯ãSÛ×Iˆû?âSêÿá˜pŸR;&œçb„¸Äív\@©:”¥ ¡Ô½]Kµâ÷I”¥fPj”:f~ˆ‘$ÄýϱÇý[Œ zÄE©Qjh;K}¸6Ñ"K�R3(5J�R£Ô(5q‰‹R£Ô±(õPˆM´d¿ûz¹‹Ö@˜ÅÔ(5JÍ8´£Ô¹|ºËäs‡áPj”¥Fõˆ‹R£ÔÐn–:Yõ¾C–'C©QjÆ!ú8äÒ±�Kú5 Ô(5J�ê¥F© í,õ¡�øMÅo”šqˆ61Ùl Ï&áPj”¥F©‰‹R£ÔN©[ž¬‰Sn¢E–¥f"�Cl6à³I¸”¥F©Qjâ¢Ô(5)µl_ê�Y꾸¤Z "K}BRñ›,5JÍ8D‡mÖ×g“p (5J�R£ÔÄE©Qjh¦ÔC~Iê¤Tü–º'J�óm™-8[fC· §rg¶+dÛ¾ŽZ¶ø|ƒ:vö›u=Ý‚ÿD}R¹Ö•:ÛKQ.d£�C:V’{ (5J�R£ÔÄE©Qj«ÔÁ¿z7ï[ªÔýÝUê\j½Z_ß³~�¿uwÉÛ®t°V¯®ïXªUÞ¯‹ÚÖ=I�åíåÍÚÆAÞ”�—[5Q_[iÞ2SšÓbäƒUÎ~Ö­» &›ô>µ=/Du½Ôì:Š�.sÍ®X}~ëwïε­ÔžGá|Ü�~ /wŸˆÊú¤ßÙ¯Àsµ+wïCŒƒÿØ:_7>)žAv> [\÷»Ÿ™ÑtÁ6°ëÒ–¶�©{d[‡\¼:›Kê5 Ô(5J�R¥F© ©RûWünVž,¶úd}¡ÖR{&~G¯ø�® �gÆŠu!6=ívŒVó‹úûIãýƒ‚»e±¦©è- Œ–»¹&-33FËJ9HågMˆãÁ½—̶;M®c»Ñe¾ÉkV¯¼¯¶«ÔîŽÝ�Ûê7ûÐ9\ž+²]�ûXn×6Ìwå?¶®þ­OŠw�_ÚØâzÆØÙ»ÕtÇ6°Bv¶�©gd[‡|¼:;•Ôk@©£ð:F’÷ßcÄ÷Ï1‚ê¥F© T–:¹Fv[jIÉïhJ�WÌdk{ænÍ�žìªê&¥ž¢vwf[Ñï MšJ›B¬¯ÌÔM‘µÉ¡röÒã™-!êjËì¾òb=uë‰ûÁ-3ãÊûÝ™ñe%TÙ_åœg=Ø0P®ì °÷Eåoï¼\Wîîqðu슺Ñéí\pK•=Ñ¥vwì~Ü�~7”`ÏßRnfF~E�+p+U„T©=í|ÇÖ)÷�OŠd�íólq½cìè½Ñ´hìFM¦Ôö�©wd[‡xm6�Oê5 Ô(5J�R¥F© [Yj5yœŒ]´¼iêv•zGˆ9ÕXJ5Í ‹{Rõ(u¡®§0 Š·hó�ׄx¤š@M|�vöøPl.ÙTuròK!*j‹œÒñ^`K%F½døä¸¿Ê¹Î2Y¢ØN±¾9Cç �-o‹uŸ§%‰�­ˆzµm¥ö> çã¶ú- ñP]5¼°©Çô^Qã \Çž)ʹ/Sjwþckmÿ¤H¹qŽ=®dŒí½{.Q½ !xZ:>¦Þ‘M´R§“z (5J�R£ÔÄE©Qj�¥Tê^V'“9µl-µÄ¨#*uUTô»B¤5Õy�Ûõ(uQ}™ì´Ð|³¬8”VêÀ­¿…š!¤Ju©ë–útâü¦)ž>-gÍ÷ Ó¶R»;v?îF¿K•-K*g¥WÔ(xæ:&6Ò™R»Ûù�­S©mŸÉ Û”ÚW2Æ¥v_b&³hKRÛ”Ú\2²(5J�R£Ô(5q‰‹R£Ô1OüNîZjiy²ÁŽe©M óZººXÎÈ”ÚbE_¯ª�QáhÍÌr»[¦…XUºâ¡ñƒŠ¹ÔUÞRýc­`¼P9×Yñòi·&jŠ$–&ÓM{,¨óŸó{¥BˆØ…ª˜È·¯Ôò›j)²Anœc�+c{ïžKt&©mÕlSÉÈ¢Ô(5J�R£ÔÄ%.J�Rt5K}¢ÅM´âRêþÈûRµ¹/uþ¶­¶“¯RV6E5§µ¨?Z"+íqI_™[µ²‘ÂXòê×RÍ“ï— 9µ”s©¹R/Ù×Rï6Ä˧]E¹ð%­†öv6¸e^ùC-«=ñp¯iìGZÖµsJí¸©Æãöö»Ø˜aí:Ñ{¶N•Úh×dlgŸÉ ;ÛYq½cì¾§R;’Ô®–FpÉÈ¢Ô(5J�R£ÔÄ%.J�Rt^©Oyç}Ë•º—k©Ã–üîØÄoušñÆFE1ÈT&X©—6¶jBläu‡2gúθ˂™yD¥©áPEsŠ´Øj™É<66Cš/fš*uã,½ïÝ&íjâÁ¼±ÕÒ~!°¥Ò™q›{Mb§kÚ‹Ž)µý¦ì�ÛÓov£QÌu¢ç ì�)µÙ®ÉØÊ”Z2È>Jíã`¥Þµ'©åJ-Y”¥F©Qj”š¸ÄE©Qj€®f©½N=��òdý}ѲÔ'Û˜ø­oC¼Tj¢ÔÚþÕó;Z&pÂZǼbÚ”SbÊ5c—$u‡&u©«¶wð­ –™Â=C�Ö›*uã,•²VŽvµßzj1�ª›Ë“®Xì–òÅ%ùf^öØô•Ã�RjÇMÙ·§ßuá¨Jn?Ñ}ŽN”Új×dleJ-d¥öŽq RÛ¿+ñQjÙÈ¢Ô(5J�R£ÔÄ%.J�RÄ¢Ôƒƒ!ÓÔ1•'ë.ø-Ù—úd²Ôåññ¥ÛÂØèØ_©_Žoï>Q,Oýu|Þ’È­L–[bÒuÓÆÔ¥¹¢þ°"ĆY@Ú¯åªâ°«ëŠKn6›øm;Ë-^òvªxÕ5‹[¬›«�}z|,ŒòdsòŒk£eѨ_Ý!¥vÞ”ýq»û=PžfÖçD÷êlG§þJÝh×dleJ-dÿ‰ß®1TêŽ$µ¯R»G¥F©QêîÄýc¥&.qQj” ‘Jª<™d_êþþdLüîÞZêL¹búSPy²ìœ^V꡵xv[&¨ùy«²³æ*k{¦´û´TT¶:­¾H}-ê¹@•sô¯m(UnÖ®¦o¶¬‹âBPË\É”½ŠØ ê3[1v›êŒR»nÊþ¸]ý*wPÍù= ç¸:õUj[»&c+Ujï Ë•Z2ÆAJíJRûMüöŒ,J�R£Ô(5JM\â¢Ô(5@ç•ú”¤<Ù‰„­¥nRŸlÐשۮø�)5öZ¨ø�YÓöCÞ6 WeH6¼ÊUëaó+ëûEus¦• –·µžUfÌmœ|TÎÕÉ!^>í*–v—ͽ‘ý{4¸+)ÏekùLˆ�i•-1¿¸˜kS©å—°f<{¿+BTlNä:ÑqîNý”ÚÞ.xl}”Ú3Èr¥–Œq�R?´¶ä PjÉÈ¢Ô(5J�R£ÔÄ%.J�RtE©ýË“ g©[ž¬Ý‰ß¹rÙœA\˾J�.›¿„ë»§¬‚ÍUó¬†Ä¨µ³$F³­m|íß²fæ„U5Z P9wÿkñòi·o]qÉ[&ÍÑ2¿hÞëº7Kko¹/ì¼lO©—à~ÜŽ~‹æDgùÓ°_�g$|”ÚÑ.pl}•Ú=Èr¥–Œq€R—\Ij¹RKF¥F©Qj”¥&.qQj” óJ-+O&Sêþd­¥–OüìPy²¢µwV^Xe©¼J½,*F1å[Úüð=!öÍóÝž û ³Éd^®Žëg¦7ÍJÒ>-'D݈1¨Ôγ4‘º›iÚnÇš¬XêNPË»¢fLIž7·“’·ì¤R;/Áý¸íýÎn:ŒÚý4ìWà9æ£ÔÎvAcë£Ô’A–+µdŒ”zÍ•¤–+µddQj”¥F©Qjâ¥F©º¢Ô‘×R÷0I:KI© usYî¸UXJ¢Ô;¦y§ëbSiŸ}¢§ óVñ+KbÖ­¢ÏæìhS@w[.› rËf4©Ê9Ïòˆ—O»lEÔµ¤±šjiSÓµ»A}.– ª¢R*åÛRjç%¸·­ßò„q>OÃ~žc>JízRcë£Ô’A–+µdŒý•zÖù]‰ŸRKF¥F©Qj”¥&.qQj” w¿¥›h%­>™d_êhk©·…xò¸œ[Ø¢–öUêü×B,íåÊêFEÛ†nVJ™ü]aÍ7{T:� Š;M(†š.L+ÚVɶÔ6¯*æË�+VS™Ê¹Îòˆ—_»!ê+ùüJÝZ3îÓ² ¶(ÊsÊ)÷i}Ðny2WÇžÇmõ«jã¶Ñ°$½¢ÆH®VªÔîvþcë§Ô’A–+µdŒý•ú¶;I-WjÉÈ¢Ô(5J�R£ÔÄ%.J�RtU©O¶¶–º§K©ƒ•úd»åɲëæÌåJ9ã«Ô™ÙºÙl[³³Â®ñ¶žv¶LÛ'C« Ö•M³e¹IËâ„ùn9ï«rž³6ä%¬<í2Ö�®‚[–Ì{­Í6ë³CJíéØý¸íÙl‹UéYW »Z™R{ÚùŽ­¯RKÙg-ïû*õžsïm¥öŽl J}ï©ó}ùq4JýãÖðˆÊðíïQêä+u!FˆKÜnÇ” CJ=ä«Ô Þ—ºÛYêî ZGZ¾+fÇ8´&£ k_*;13m¼Ÿž¹¨¼{¸�R?VõýΓËï—T¿Û-¡Ô‡C©_~9b2öã!Têÿ#(õᎻ°»»›BmQj”àÈ)õ©�›hõR©Co¢Õ©}©Q9”¥ÏãyÅh¿\žtíÙ–ÒÄm^Ãìƒ153½m…|ôDyÿË­I”ú(õËá‘‘ÈN�R'Z©s;û•©¬ùvfww'VåÊ)»û4Aª·£Õ·@mQj”àf©=¿O„T꘤:tu2”¥fâVêÅ95!}i©le¬o©Èlõqûâ–:ЯcìÁ¬ùƒâÆ—ŽÔ5J�X¥>«»ôÅ1íÏߢÔGH©hõ$n™)Zåõl¼J­†/]¥.ß½{w.)j;§\L¥F©Žo–:̾Ôý=ÍR§©ƒöÐjc-5*‡R£Ô͹£zë£Æûm§ØÆ¹‰Ö½-uþ÷c×úî@©cç»–8ÐLzãõw?TµW/[:;zÜö8¬Jýw…?ǦÔ�„¨ßª ±¢ûmEÝ®!VåÊq¥V·`ÜJŠRoExÖ(5J p„²ÔC!”º·k©£Vü>‰R£ÔŒCוú–ýýò�;—f;Sm»õ^Š_Þ¹3gÿÁ¾ry(u•ZKR_|­¼z}I}YA©»¨Ôï+OøÿŽM©×„˜,¼4%rIˆùlÌÊ¥*õJ�R£Ô(5@2²Ô‡k-²Ô(5ãc–úÒ'eGµí_nÝë…RO.éÌRoo’¥N¾Rï�ªýL{½ª•ý~�RwO©GbUêºùBYˆª©¥¸U¯Öú\óVâ΋Å\¡<³�šRÞ•­¦­9ç+s·Ry«éÞÎÜJº³J�.(ÝUŠE}ºuùÞÜjj6g¿°�Õ�Rû÷;µ·³:79­¿V:.r÷«ïò©¹[;zÈ…bE¹˜95l ×Òúøæ•ÞŠÚcU_¤Qj” 9J=b-ÙÄï¾^î¢5f15J�R3]Vêô£ Å[¿¼mía5»¯ŠíŹÅx•zzF½Ž¸ûÔZÓýP½Žùk©®Ô6�þáý–g~:¥~ý¸ù·#«ÔY!6µõÌuU1¿�={:¡h^Ë“UUc¿­¦Âë³Ù]má¸1µýQMØßæÕ–bs¦£JýHì+o7ô×µ¢uakúJöl›÷»cÜÊÕ�'•·SªÉ+o¶�ø)ãË �r+×Òúø¦kÆ#\QþüºŒR£Ô‡,K�¬zß!Ë“¡Ô(5ãÐm¥N§'·\{X­jk˜wgãSêÒÝPBn6<>5ï}”:±J½¯JÞ%ã�¶›Ö­#­Ô¯þ?nŽ®R*B,f…XV^¯ QÍÆ®ÔuÝñº©Ô˺>VnJ9cNð¶9uÖh¤5îŠR—-¥ÕV®Û.Lì´w¿ëVÇÕœ®Ô•š®ÔãÖ‘U‡R·p-Æ÷‘$«%Å …­Š�I”¥Hv–úÐNün©â÷òòA(¶ëVËÃ|ÅŒÃá‡Ö¦\ë{X]ºeÍÿÞÑö°:}/¥Öë’Í?n8½pV!G©¬ÔËÚRjã�¶˜úJ�l¥ÿ_ɾ©Ì3!ne2Ú´ïÖGi÷—ý'JØÅL×âj¹gQ7|±¦©dUùùcõÅ×[ÚûgÊûmac½S÷»RÕ"W«Û™Ì’MËoY¦«m½­ûMk!öŸh…Þ2™Ió.*Ímk[›BÚe-d½Z�nåZ"Œ¯¦è3ê—Õl&S·?Zñ˜¿¿Qj€Þ+ubË“5qêÀM´ÞA©QjÆ¡ÛJ�N/n«û©+u=�R_RÒ iÇzîVgž£Ô½RêyUòNo&´âß(õQQê{BlªùɽŒ:í{NùÉâd:ògQ~ÇQS™é絠ԥ̢&œãÙ‚º¶Yä2Zr¼šËdª³½s™Œ:ÿ¼¾�--wT©õ/*¶ô­×+‹Êïtúè[,,j“ѧڹߗõz}[ÿzDlJ]K-榵g{;›É=Ð�d¶ténéZ¢ŒoIëO}ij”¥HŠRËö¥™¥î‹KªµP!²Ô'$¿[ÊR@4¥Ö3ӎͨK»cObRjWBzî—ó�#ÜJÝ¥Ö,ú¶ñæ´úfëH+õ_~ç&¥þÿV5´}Êô—ÿg÷•:£O ÞÉdvµ”â¬jaóåˆÿ�Eù›LÕ¹|w•zFùsÎHÀj›v•3³ÂHŽçU—^Ñ3½ªÿåëÝRjû•ô?TÍ]áf4�«ºôš¡Ôê­dÔ=¿7Õ¿6ÓŠt/Û•º…k‰4¾«jd¡M~ÈdÖ¶ìùû¥è�Rù%©“Rñ»/êZj” 6¥N§‹®™Ö‹qMüžvÍCß‹tù(uï²Ô¦E?9úYê^UüÖæÔ;øc J]Ø8WÒE¬¬¸—>ù7í¿³¨J�ë®R/(®è¾©gÅ˵|×¼Ö@�ý<§™oE{¿Û=¥Î-Ìl/= ��TúD›$ÐÞý.¦VïN4”ZŸ½½`Lr·°)uèk‰4¾9ãs”‹þ/K£Ô]Têà‰ß½›÷-Uê~” YJÝI½~%‹g-õÄñYK}¼”Ú`ª®-)¾%Änz_ˆñø”Z�i]è®R«)Û{Úò^K©Ÿ™†­-+^Ê̘‡µ#]QêÜ­ÆìçRãÂ4ÏmO©µ©:†RßÖ~®ÞÔ¾T©[¸–hã«/è^iã_8þ–F©º Ôþ¿›•'‹­>Y_¨4µgâw«¿¥æW²ÞUü;ú¿�¥R?Pį ùmIMn®Å§Ôk››µv•«u¥VmsCkpW-‡­•ÒÒ=ô KJ]¨ŠF°Ž*õ=ÛJe�R¯É”º•k‰6¾)}G.”¥H–R%Þ¨ÃnK-)ù�R Ô(ur•Zß—ZýúìKýÇÿrñ¯ñ(õæ°†&ÓúËÿ+6¥V«”©ÿ+Ž•U—àÖ£ýwç߀-(uÉ«Ô+Öìè-m±õ¬õþa—”Z-ÙUÛYÔ–¦½Ÿmç~Õ ¥sZ¨5kIuF¯j®ÏfŸÊçs6¥nåZ"�¯¶BÝêô‰�IþþF©z§Ô³Ôjò8»hyŒ¥@©QêC¡Ô{£ªä=òèõñ©øýÿ݊߆Õõ^jÝë\&¯RçÒ‘NkO©ËÂf—bA«ä%^*ïg»Pñ[{šÏŒ¬mNtX© ›F™îq·Rk7¹gÜä–êe‹×i|ÕEÚóæJn*~£Ô‰QêPûR÷²:™Ì©ek©%F�R Ô(u¼|ÛgµÅÔê«ï´—¿méìèq ¾_ý1Êi(uxöÍõ¾ËªQÍeű(õº»ËåÉ$J­ý¼^Ì-ÌÊ«-GŸœ©wX©5E?(OiSË+ùL~£ÓJ­íÿõ¨�YÙt+uF½¹'ÅÜžëQF/ÅV-.¶t-QÆW+ö¦•({„R£ÔITjO–z`°É¶Ô½KS„ÍRSž ¥F©¬ÔÛÚ\äŠQoh¯fbUê�Ñ‘÷çÛTêk‰R·rú!Tê!6µW«Šw–nëTÇ£ÔO�=¼âVêò„%y›jEðI»öuP©§ô÷õ”±¨;J‚uF©÷µeÑ5ûZjC©gk�{RóØFQ²r+×a|sO´ âêzêšò·öCÇ&Z üý�RôN©O†©ø�°µÔÁ¿ÉR Ô(õáPj½Ì÷È¥ŠþçÄ·q*õ÷Ú´ó—(u÷”Z]øúÈ@½vô|.Úgþ"Ó³¸ñ+µM7õÕ½¦NwV©µM¹´ÂÛôþë•N+µy'[¥Ö¶ÑÒ ‘i…¾Ë›ºR·r-ÆWÝ•zÙxökQÿ…ãoi”  Jí?ñ»É&Zý½«÷n_ê!²Ô(5J�h¥þöå°­ õð�±*õ¸™"�M©=åÉþëߢ*õ?G@SêçEÿ¥{W ý7Uª–;¯¶¾lé©Ì8”ZÛPJ� ­Ýßì†.¢ÆFÍ™9ÕL«³©+unG½„»Ê«m5-¼V^î´Rëƒ61³ lÑ.²Å-M¨7Œß³Jë5ýöÃ_Këã«åÀŸšB_D©Qj€„(õ)ï¼o¹R÷r-uØ’ßíNü^^>EØvÝjy˜¯˜q8ã€Ró+YlJmwê/W¾íA–z%F¥n“çÔ.,å"ÿw)`i!ʶÔ�¨4>UZ(åí¡•s݉›m%@”¸Ù²ïߎùÒ´ã…Ö®% Ý¥èp–ÚtêÁ!'~ǧÔ}­)õɈ¿Q9”šqè‰Îæ“z üJ‡Rûã¼f¶#£[?~¯R{{td4ÖµÔ=Vêÿ»Z­þ_=Tê¨-q‰Ëßß(5@Jí^K=8.MWy²þà‚ß’}©£*õÁAgÛu¿åá»bÆápŒC>^��Jê5ð+Y,J­HõÁþƃƒÛSÛh¿Ú®ø}˜”:*¨qQj”ZRê�¿ûúû2ñ{ Sk©Q9”šqÐÉÅ«³¹¤^¿’ŤԑIB\”Õ#.J�R{¥ö”';‘°µÔMê“ úÖ'"K�R3ÑÆ! ˘“¼”š_Éø)F’¥Fõˆ‹R£ÔÇ[©Ë“ &¡àw„òdLüF©‡6Ç!—€q.ÁIj~%C©QjT�¸(5J šRKÊ“I•Zš¤îOÆ&Z¬¥F©‡N�C.6›K®Qó+J}l•úzŒ—¸ÝŽ (5@‡”:â&Z}½\JM–¥fº<¹Øl.±F�R£Ô(5ªG\”¥M©ÃNüîé&ZÍÒÔûR£Ô(5ãqr °Ù\R�¥F©QjT�¸(5J n¥>ÙÚZêž.¥–+5¿QjÆ¡sã íT—7²ÊOåÃ5 Ô(5J�ê¥F©ÀO©%k©CnKŸTK7¦™¥f-”šqˆ¬Ô€R£ÔÉUê¿ÆªG\”¥€@¥Ž˜¤NÎbê£>ñ;[è¦ÊåB´Ì"¥.d›R»Æ·#WœC©Qj”:®¸ÿOŒ ÔÄ%.J�R$:KXž¬?aûR‡ÊRµ‘¥Îߺ»¤¿Z¿k²"S“•»w‹¶·÷”ve¹Ä4ºÌ”ÖêÕõ�\¦iËòöòfmã Fål§9^ô¾_µ­{AÚUx¹Uõµ•‚VšÓî*ßY¥^¸Û`½I¿SÛóBT×KM¯À;¨�×êÕJ�K­Wëkã{MŸ„w|®Ã9¨þ}zF¥F©Qj”¥&.qQj” ;J}*`­&ó¾ûþÔQ•ºXbS—#aqËÛ.·«üüY£‹éšò~R*1�.3;F‡ó‹ÍZkzËÊbs•³�æxíßû¤q ¾ÚUx`´ÙÍ5´£e¥ÜQ¥Þ6 �ý–&Œf;M®@2¨A×êÕæJ�®½?kÒ»d|ý¯Ã5¨~-%£ŠR£Ô(5J�R—¸(5J е,µÿÄïfiê¸ö¥vêÁA_§ŽªÔÙUUIt{YbkCç¥GMJ—7m¥¶w9'Díî̶¢]¹à–EåÅÒã™-!ê¹&*g?Íþ: ÷Ò¦ë+3Ѝ�ûiWv_ ½žºõDˆý&‚6®t»;3¾¬Ü\¹“J]Ü0©5QêE¥Áí�—ëÊ >¾É ]«kT›*u^y¤[Û3wkn§v÷._¿ëð ªOKÙ¨¢Ô(5J�R£ÔÄ%.J�Rt-Kí»‰–]¨Ã&ZƒÞ‰ß‘ÖR/*²û¤jØË¬i?5y¦8ξ]›RB¬I•ÚÞe¡®'% ŠûÝ l™y(6T›zhëT®röÓ]ô®\ê#5¥Z_§}´ë¥õXN9o/PД»ª—Œ/ Æ;©Ô�Ô¯Û)C1gHå|!°¥dPb»Gµ©Rï(¢^@©&ª�½ËÆ×ç:¼ƒêÓR6ª(5J�R£Ô(5q‰‹R£Ô]ËRG¬øÝ×S¥^K}¢½òdŠ>Èíö2éJ�ÚÕDˆ‰â´M©óŠBíI•ÚÞeQ}¯rêz`ËBÍhPb)Xåì§9®ß¿w¥ÓŠVËëÀ&Á.íÚBŸ’œßtÙ¡»¥b©Æêb¾+J½.D9¨�r?ózm²g³�=JÕ?¶gT›*uUTô».uw !_ŸëðªïSðŽ*J�R£Ô(5JM\â¢Ô(5@üYêdÌûö)øÝn-u4¥®¥TÚ4ò´u_‰éŒ]©÷éóQj[—³ssú,ßœT©m-˕ʊ)ï·›(µí4Çõû÷~ÏL’çêbÍG»j–o˜ríÓ²(DÊÔðz7”zÑ�¤v·›b!d�’Aõ�íÕ¦J=3gT¬[ Vjéøú)µgPå-¥£ŠR£Ô(5J�R—¸(5J Ð5¥ö­ø=08ñ»¯—»h „ªOQ©‹åLÃ^æD5“-ó25yYÈØ•º¨æåJíèÒdŶæ7¸eZˆÕ`•³ŸæíBÚûœSúO×̬ª[» B<4^VÜ ”]‚¦\âZÁ|Ñ ¥ö$©ÝíÖDMÉÒdºy�’Aõ�íÕ¦Jm=¾ùƃ |öñõi)ý\HZJG¥F©QêîÅýï1‚R—¸(5J �è,õÉÖ²Ô±Îúî UžÌkÔmìKmÚË’XKÕ…Õí¬´]C©sOÔ)·{~¿ÝBTXÙÕ\˜–êE4[Kí9mׯâ·uhWUP³û¬¼Çª•ÎÆBe_A[b¿\È©e©K]Pjo’ÚÝ®¢<Î%­�úv¶I�’Aõ‹-Õ°J�¿Ýäkéøµ ¡ÔÒQE©Qj”¥F©‰K\”¥èºRŸhm-uœSG,Ov²J½/Œ}ŽÄ~!X©·µ ^á”zicKév#J¾ÕDéF•kM©«Ö¤î™FØÕ£âÉúæ²ò¶ƒí±±…Õ|1TÖ¹E¥Þõ$©½“ÔÌ»‡Ê§GÉ úÅ–Œj¥žÝب1‘ õ$ãÛ¦RKG¥F©Qj”¥&.qQj” kJ=b-u/ÓÔÑ7¦î„R«¥¦SŠ Ý Tê²¾2:œRkûÏïdC)u¹fß—ªcJ=a­ß]1ÅY¶BZ«I­íø|+PÐ ÷ ¡]³Çr«J­<ÝÝàv5v=µ˜VóÏëÁ=JÕ§¥lTÃ(µ¾9ôR¨|½s|ÛTj騢Ô(5J�R£ÔÄ%.J�RtG©ß *O6˜ ¥–mL\ñ»“J]óÚìì´¢_¹ ¥^S¡•úåøöîEªÓ!”:]w¸QÇ”zÞªá½#Ĭ�vÍ©žúP¹÷ wiÉÄïÚÆêzU‘ð.Lü~àMRK”º®ÙübÝ*Ÿ%ƒêÓR6ªa”º<>¾t[¹¢™æOÂ5¾m*µtTQj”¥F©Qjâ¥F©bSêÃ;ñ[RñûTÛJ].ÚûØ©R§ŒŠ×¡×Rg²s¯Ҷ½e~Þª¥ÝY¥~h­“Þnˆ¥G»ôÔóÚ^=TOuZ{_‹z®ÓJ-KR{'~k2ë2¹œ{öª¼¥tTÃ(µ¦â²ZY;÷ø¶©ÔÒQE©Qj”úè)õ_bÕ#.J�R@(¥,OÖÓ‰ßýÁNÝ]¥n$­�—eJ�«‹Êâ´ÂŠ;‹é0J­Ödùf-sUÛ.]Uêm«|ՃƞR^íʯ¬ïÕÍ™V‚í¶u/3æ6NTê‡î-¼$í*V"»l U³+H·”�jh¥Î”\ûMKÚyÆ·M¥–Ž*J�R£Ô(5JM\â¢Ô(5@lYjyšÚ#ÔêÿÅ6ó;ÔZên§îDÅïÂâbβ¯U¥. ;õ •M—M7³í¤ì§ÔÙ� ékK©SViîªXnª]Û®-–½9â­FFyµÃJ]’%©Ýíö­û)5)¥&TiKù¨6‡\¹œµžÊrð�yÇ·M¥–Ž*J�R£Ô(5JM\â¢Ô(5@lJ=n­øòÔýa«“u£<Ù´µ„xÅšWܦR/‹ŠQfú–ßfK� ûn;ìœRï ±¯½/ÚÊy¹z|¹:®_kzÓª$-o9!êÆ]Mv^©×dIjw»k€f„Ø j)Ô*uÑÚ;+/¬baò;“Œo›J-U”¥F©Qj”š¸ÄE©Qj€n)õɤïKÝ´â÷`—+~×µ Íùª¥u2¥Î– ±›)•ƒTvÇ4®t]læ‚•zÝ]g»ƒJ�}¢'4 ó¶Å®Ÿ™rºï¶TwËe³An9ìnÌ¡•zÖS˜[Ö.[uíÁ«åɦ{” ª´¥|T›�C¡nn8>îªéæ¹3Éø¶©ÔÒQE©Qj”¥F©‰K\”¥H^–º—J=ÐWÅoE¦ê“¹\±Ú˜{ì³/µ•%lRž,ÿµK{¹²ºÙÓv`Ku¶µxlPè´R«s„+¥Lþ®°Ívõ˜›â ]˜VÔ¯’ ´¢r©»Å|ùqÅÓ´m¥¾-MR{Ú­(Cµ’ϯÔ]+˜½-%ƒ|­­•'S†íÉãrnaWˆZ:¨wÙø¶©ÔÒQE©Qê8ùC|fû‡$Äý_ñõÿJ‚R_�Ï|®—¸ÝŽ (5@—”Úrê�Á@¥îëKHÉï ,uûåÉ Kæ¼ß…Î(uf¶nv¹]l™¶O;Îu\© »æŒæ´¿¦nšmšíœ\œ0¯t9ߞʹÛïy¦0ûç|�­± Á-%ƒÚI¥ÎZR)õ.ßv•Z6ª(5J'¯âSÛWIˆûßþglü7{ÜŸã3ê?¡zÄE©Qjˆ¦Ô‰YKÝ“‰ßwEÍxõH3àúª\Ӯͥöìóm�cu™ÞW»ÜÜzœ nÙªR7®ÙùÚï:²ãš0¯-hW¹ªEXn*´‹Ú]‰êx¶M•s·—¯¤–õ{OÓúÚx¡iKÏ 6Uêbx¥ÎdRÕ¯•îŸì¹Ð²R;Õ¯¥dTQj”¥î^Ü�O©ÿÕ÷O=RêWcãq‰Ûí¸€RtI©¶‰V³$õ€ßÄï¡v²Ôv¦WV¦#©‰ËüB©�i»Ï°gù¶ËS÷ÊMZæ‹;“ÓáúÌ­<…VŸZÓv…òãT1ªG× vz²¥…|‡zo¹¥gTQj”:N^ħ¶/’÷/ñ)µcöOñ)õO¨qQj”ü•úTÈ,uo÷¥î \K=°–º3JÝ1ŠC©Ö’qHÒ8J�ëñ©íõ$Ä}ŸR;²ã/âSê¨qQj”Be©Od©û{ZžL¦Ôá”ú”¥fPj”:NnÆV'ì7“÷Æã2ê?:Tàf|Jí|Îñ©q‰Ûõ¸€RtX©½¿›•'ëeu²~ÉRêA”¥fPj”úØÌü~‘Œ¸�K©ÿêŒûSOæ}ǘN¼A\â’¤F©™RŸhq­ÞîK˜¥>ÙéµÔ¨J�RJ–1¥‹ÿp#q¯Ç¥Ô®ítoÄ¥Ô®û½Ù£d"q‰K’¥8‘¸yßMŒÚ?KÍÄo”šq@©Qꬦ~õ‡xu3)qoIJ�Ö¿zTàf,ûhýɛԻÑ#ó!.q1j” ©Yê!ßòdƒ‰HR7[KmKS³–¥fPj”:S¿cpÛW7’÷z Êþx]r¿?wߨ–ÜïÍÜçÆMâ7ž¸€RtB©}'~n¢Õן”,õ Yj”šq@©QêãåÔ¯n$)î‹®;õ_Èâ^ïºSÿ|]:áFȯ¸ÄŨQj€$*õ© ŠßIÙD+¬SŸl/K½¼|аíºÕò0_1ãpxÆPê;õ«ÉŠ{½Ës¿ÿõºÏývyî÷Ÿ|î·Ûîãg>Ä%.F�R$:K}"0KÝ[£îk­<ÙI”¥fPj”º·ë©_tÓl_ÜLZÜ?ÿ¯î õÿúù†ÿºõ®V&ó7�®ºOÀzWâ—uÔ(5@•z(L–Z6ñ»—iêÀ‰ß–T·¸‰JݱDõ‹.eŒ_½¸‘ĸ×ÿÒ¥ÙßüËõÀûý©K³¿þ)ð~oÞè7‰KܸãJ Й,uË¿ûú¿˜ºÅ,5JÝÁLõõ¯^uÔo•î^\¿™Ô¸7^ýå¿þµ£^ýÇý¯¿¼jšZ»ùâ§×ê¨Wÿü§×?½hþœ»b?7‰KܞĔ ;J<ñ»¯·Nj_j²Ô€R Ô]SêSC'}7ÑJòZê�à™ßd©¥@©z™¥HJÉïà�©™ø (5J ÐK¥¬øÝÛ¥ÔQ'~¡Ô€R ÔÝTꈿûSžl�‰ß€R Ô½ÌR·>ñ»·ó¾û›üF©¥@©bUjéÄï�äü¶I5k©¥@©bTê“~ó¾4ñ»¯/ÔÄïÞ45J (5J _–:y¿ûû#ïK�RJ €RtO©‡ÂLüîuy²¾ˆN�RJ €Rô6K�¸M´˜ø (5J Ðk¥ö­Nvh&~{³ÔLü”¥èe–z ){h…_L-Ù—ºð9@(„›ø-ꕺ¿¯¿µ™ß¶‰ß(5ôR©{»‰V“òd�¿Qjè–Rû¯¥Hpy²pYj”z­Ô=žùÍZjHžR»�Zº‡Ö@¯Ë“…ÛF ¥€•:Ô¶Ô=ÎR÷f©}7Ñ:9ôÎuºÁõ†RŸluâwRŒ:`â7J ½VêW'k²˜:h-õ¯®1ÊÐy®ý*\y²~)qî¢Õª<™·ä7J =Uj‰T÷ż15J ‡Q©û·/uȵԿF© Jýë_xÖR†ZKÝ×ëeá6¦þJ ÝVê-)uê“…šøý‹__a˜ ó\Q”zÈoâwðZq:uä‰ß(5tM©Ýó¾ÃUüî‹9KÝG–®Ôa'~ÇêÔM²Ô^§n(õÛ(5tC©ßþÅPÔ=´â­NÖmæ÷Ð[UêÂøgT;K×>/0RÐ¥~Ë_©“Tž,òbêŽ*õýÑ‘‘ó�2Á÷.L…¥Tê›nõ­òEêÓfM¾9— ÛÛ§©/bý _¾ßÍ‘êÒ7­�Qç>Ã|ðÁ'ëí®ÒÛóÿ�¤Ú[øÄ$A©O&;KÝâÄoÓ©Í,õ…sçL�¸rîܹˆ¶õû‘‘‘±È{ú\ƒçŸ622òÄ«##ﵩ…¾u)nÖäìÈÈÓ�½ »ì'ç>“_ÄÊE+Ofü£¿V%ÕÙ‘Ò¿¸è5õÒÚù=5MÎÏ�9ö©}£<™Kþ…>°ýÇ¡|b?¬0¦ôV}>ýæZˆO{ Ÿ8€$(µ7IÝpêþ�^—'kY©¿Ÿ›¿újýÊ.µ­)Õç¤Oi\9¢e§•SO·#Q…(uáüùoz¯Ôg}�YÏfô\KS¶O+§L{¾¾hk¤4QU.hÜç˜ï“ �ynkJ}6à¡~¤=µÏ:¢ÔÚ(äÍwçÔwŸtJ©ÏZ#|f ¥€£Áó ‰ß‰ÙC«Oø0󾽿ßl(õðT R_V~~Qú”.*G>Ò^¥.~}¶®"Qg' ®ªÃjYËJ-ïû‹‘‘�£*õ7BOÃm[©GF>lÅ©§>¸(¹¶¶FÊüä¬Ï1ß'óÜÆ¿‰RŸÓŸYç”ú‚ñæÊp‡•zø´ÂY¥×±é¦Ÿö>q=Tê7#üîýZýa²Ô'ß|×RꑳWÚUêv%-Z/-+u‹"B©[  ¥;=iÔ.u=äÃYö»sJÝJ­‹ïÈpÈ%Í!”z̘Dþ›‘+µþŸ×ós� ú}ÚbQêwߌ¶”:YFPŸì�w¯Zª ›šM©Ÿ<~á“ßh —?Q]ãòe=u8õÙøùO§5µxzù’rdüòå+Ÿ_½|ù²aYÓ©óçß3f¦N+?~þùTê|*ß¶R_+Ll9ÚûÓ÷$£0}Õqæ”dAíóéûþ2we*Å®ÔÏóÓÏ=JV_3~xeÚæR×¾Ê_i_©Õg;uV÷CýY?ÿì횯þæ“ ¶ÞW3~!¥�ñôÕ Ê|þ“ϾÒ4FÊ6ÈÆ�¯\>?þY“µÇW•ÛöS{û“|>å|HÍ�wä�9´R›ë ~ãûaü"5>y_ù„_¾<åPê/Þ;>Uð*µ9‰|®Ôö¼ú|>O=µ+µk„”ZýŽjøŠûÓéÿiîzSŒŒé1=:zY—ÐÑѧŽ'9}ú}õc�2¥Ùãiœ«�‘ë1GQj5�þ›ÆÒqχQÿ¬¿÷žþ�’¥Ô}móèטiö‚vΤj�úc�~òÅŸŒêZ®ö˜ššü@0S©㙞Vþxäƒ/¦R£#Ã×”hc#éiõ:ß¿Ú ¥ÖžžUý’>RÏ]2Œî½‘ÆÀå-¥Voãâ{wÏèh*µs��NG‡Íï´“eEÈ¦Ôæ×ÆŒ¢_N¥n<ÉÂe„>úæ½3ú´ë�§q®1þÎÇA©?Ö¾�9oí$æþ0êßÒŸÿ†Rk¦=öáéaçÊu¥�ú‚–?Wþ<­?M÷^KN�¼?jV¯w��ü±6”ZéVÇÓŸ}¥~þ.H>íú'ÎÙF}À~T¸|Ö¿;@¼J}j(Lu²^Wüna1µ{æ÷Ð;¿ºfÛSU~o)µ*_µ9mÔvj”'»46væ+]>FŸn+OfˆÚ§†21ª‡¶ú÷òç…ÔŸ+Vù•*ßÈ”zü#�û–Rß9sezTËKßÕ„øóçŠÜ*æû�!êuK”zø+ã…nÏg®š3LòŸZÙŸŒ¼_Й_õ*uãIž3äSÑA5v¨Çcžk�‘ý1GPêÓÚgñ©õáu}¯©Î|vÊXËÐPêO ;ž¶òÛÆ(\<¯ë°Òåègú“w൜ôùûÏ?5”Ú5BòÇj)uJpaâCõû�+cÚ;÷§]ÿÄ9Ûœ3ŠÁFÛÜ!  3\ûÕ;þ{h%hÞ·Ô¨å¿=Sÿâí+†°]ù½êÈÓ†R¡¾Q­ôê°6ÑXRñû¬ayn¥>mNÍþDד³Æ߯Ì"Ñ燇ï~.Sj“O-¥V òüÅ‘3ÏõOÍ–Óª:—s^ªÔú6ÛW´Lêg¦óéo-]ÓÅã#Ýâ\J=iž£<€aín'ÌÛ>­õ¨çÙ¯~òÉS›Rkߌ§~¤=8“«ºVµ¡Ô—¯ÞŸþĘìý™¾¤Z¿n=…ûü}EµÿV%°pfllÂRjuYxÊJÁ#åäÏÌoI>0V sqä¬lÆõíÙ?5R¿~Jm—Ä©��ǩԮÇܺR_Uî{øŠ¶Öàý‚ù¡µ}Õ•éÃê�çgJ}Ú\p·±c»¡ÔSú§XyD§¿ÐUÙý�?g®·þDWj×ù<Ö³#c>T'©_¶ýüÂÈè5ï§ý¼£ ½Þæœ9‘ábpN &®¼›Dó7IDATý‹¡F�„M´B–'kd©M§~KÛ˜ZSjM .t¥þ�Uùø·ú¤`»R_ùhüü…F|”úŒ©#š±éó™.b†^‘-õ”+µ–Ù{ÿ©!(Ÿ]VùTU9E/X'j’qÚàJÃÞTݹ¤�yÕ|{ƦÔz}¬)]š\J}Þ:ç¬j/Ê9gµà—Ϩ�§Ñ£ÑXWj]s>5jRMY=¦?šüTw¹ìK=ú™þ´ÎhG´½œ~«¢>©+O]“Š�‰ßz®‹ç/_³�”{�­Í¦Õ¿ÕH÷ž2]Z7k?¥nŒÐ´–áõxœJízÌ­+õ§†Ý~0bdÌ]Æ�­Oõ9‡R«GÏÏÔ¶O–ªÔ꣼ðùóaåB ¥và/šï ºR»FÈç±Zë±GΘF}å›§Ÿ}¬Ä¼&ù´›JÝh£Ü¨þÖÆG ·<û-w’úDB·¥«Ôƒò’ߺRßWÿ8­+õ¸UÙø‚î ¥¾rÁ*u%UêasŽò}}r­™ÍÖ~áû´ÕŒäU�k6¥¾:f®f=m³Êsª¦ÙïtÉ0ëL�<×ìÍ(Ô|W}ÚÚi[eK©õ嵩R7Îù@µ—i[ð‘ûºš{•zLæŒWÏ�±•k_©U£Ö‹skGÆG—öžkR±¡ÔÓfcã�‘r²ÕéeK©¥(‚za\A+Jç«Ô�ºò¾:„¡�S©O‡tC_¥V+‘½îܹaóËׇñëi�;”zxÄñas(õ§jâ[ûC©Ýøakaƒ^žÌ5B¾÷0<¡0jm¡ýÙEó¿³kÞO»¡Ôö6ÖV^ Ô�®ZÛRK²ÔMœº÷‹©g~[J­Õ'Ó•úóËïÚ¥¹š7~?¹kWj#�6¤Ô_®ª mx¥þ¨ñÎRjuFR_Ô¹ø‰W2>ùPçƒ+v¥>¯+õ™J}ƮԪ=ÁÏ\¼oî¦Jý•¶ÍÑÙ‹§;£Ô—>xú¹C©µrdgTFÆÎœÑ”ú´W©?ÿæ‚ÙÅk¤ÜƒR©¯Ø„ó“v•ÚõxÜJ=Ö–RßµËì”W©ã“¥VïpL{¦Ê£=ïTj-A­¥ªmJmÿÀ�Y³1F5¥v��ï=\4®CÿXª¶?|æìoƒ”ÚÑ¥€¤qÿÔ¾ÕÉU�¬YÉoÿ‰ßCïüúŠ¥Ôæ.Ucz¬3–“Ù'~«ùÚáÔW×´2¥¾d.?½¬ËnO©µù哺·ŽÚ&Œ{¦ÂÚ±Oü>ã?ñ;H©Ý¿Gmóµï‡Tj¥£ Wõ;jS©ßûâ‹/î7ž–aÎ;º1pWïßÞPjå¾xOÝZý¶Á)÷ ‡Tê�_/h§a®xþ¬ÉÄï�Ç3ñ;ÔË~Oí=G~ø¯R[k©¯8×R_² ¬»Gá¢ö‘Ô»1”Úý�?m¾ÿFŸøí¡`¥. �ŒiEøFGÎ<½¦ý&~;Û Ô�0®üú�¡ˆó¾“ Ôáf~i‹©M¥6ö¹3l@Í=N�êÆ|Ùܯژ!«%ë,¥NÙ”Z]ý|QýEÿCݽJýô£ÐJ­ÄY½ìógN![žì´y2·RjëÂ[žÌnEÖžÌWRï僕ú¬± ÷Gm+õ´ói¤Z¡&aŸO?}ªÜÒÖž«wÑTêçSSSê3üfÔ¾ƒ¸{�½J}õc‰ÒΫ¿>7> Oµ+H™o?²=IOy²�Ç<÷Šù=Žý1·üÔ´Åjѯ FU7÷‡Q«ø}±ðùÕ�¿?4w޾ÿôéÓû.¥þÈØ½ÌTj÷^ݲKÛ»í´®Ô®òy¬æÓ:oíþžy~åÉ\mPjHÏß~Ë,øÝê¶Ô}‰HSÛŒz `1õý†R«ûê¬ºÇØå+OµÍt¯éú0ò‰âeêA—î~ÿ·æÄïyu�ê寬ܧVgìBá¾Vï8%Qjåϳ×Â)õý1EV¾Ð7*è»J+¢uéÒgM7Ñ+/6Ñr(õ´}Ѭ&|ú9Æ&ZçŒM´®�¾¤Üãý÷�Ý�Î96Ñ’;£¶8öÊé.)µö|{ÿókãúzauÀÎ|tåéY}c]©?36…šÕFÓÜDË5È¥þlxdôc÷¥F­ÅÚ_iÏLñRÍ¿ÕLïG¶'éÙD+Äã1Ï5ÆÈù˜[}j_™Ó½•‹~_€î£>/ą̃k_j­öùäµÏ§Î:öPוúÚcoC©ÝxmŸ³‹¿ùøCs_j×É«©ÔWÇ´¼ùg¶�÷5ŸM´\mPjH÷ß}#êRê¾C“¥>9ôÎÛWJ­ï±«þfžo,˜VmæªþúC-ç¦4yß*OvÁ\©jŠÚ¹Æ\[µü¶Ûbžš¹ÑJ}zd4oí }^•¯¾Ö,LµÑóO§ÇÇF¤J=r)5uùœáÅŠì\üT{«J¹\©Õ=�ß›n”b¾ �óÙ‡údÞÏ c#£Ÿ<-\¾¨O Vìè¬à‚îHM&~øôþ剑n)õ7ÚH�ÑþW‰÷EcàÔ•�M´ÔóG/N ëÕ¶Ì‘r ²G©'<;§é·nIæE-a­.,þæþ峯 óIΨ#4•º¤_¨ÇcžkŒ¿ó1·úÔÆ­ŠæÖîYîãµyãþ/:”Zÿ ŸQ?å—®¹”Z[¬>[C©Ýø+íÓÍ ž’?V+§?®x>:2öiá›ßëë¤ÝŸvsâ·½ J ‰âÊÛïDMRÇ¿‡V_t¥~óÝû6¥Ö&¯j¿™[j6ª Ô†Rþ¡±àÚ\oªg¶mJ}íCS'&®|îµ­xöÓPJýݳžë‰;ã Çÿü²Q{J:ñ{̸†á)˱GŒL­�Rk¢c[N}mÂ8åC½¸òô°Íš¬/FƦ›(õ”QìÃn)µM¢µs?2ß_þÜZKý™Õæl¡¡Ô®Aö(õi³��KÆTm•÷´[4ÍicÍ'ù�Ùûøça�y®9ñßñ˜[}jæ&ÔŸ|F2eâêiU›ÇR)§R7>Ãút‡Rõ¾þœL¥v}àõÒùê=�éJí!écµ”ZMö[ùó‘áÓš.»?íú'ÎÙ¥€Dqߪ÷-YK=`sêþ‰Q'6M-)Pö¶šÃ|ßФ«gÌ’U_Ìk¿Å_4ÊWRgGGG>P�W'¾žžš0ídúÜØÈ訮Ԛ‘];¯9Åð…禼8,æ´D(ü™ëJ¦ìäïësò?R÷rþ½Qñ»ñ$¿˜W/ìŒþ�G¨Çcž«�‘ë1·øÔ¾²w3­Oª¸è­•÷Õg¿yúÜ,0eî¶uÅø Ÿ¿ú¹G©Õ“'�>ǽxåÀ„vªVóì¾w„d�µ¡ÔêIêCý½zöÅ/ÆGF¯y?íÆ&ZŽ6PjH²$µ´:Yö¥Ž°1µ#M}Mþ ®N4íp™+FÃÂÔsgËkW\ï§ž>�ºâ÷l§¦¢ŽÊµÂôW¶‹-L¤Í´|ݵ)ûÅ+gú_�ÙæêUçgà›o§<Ïç¯:z,„ü,}Ó4t3¥nöýÏôGöKUÞ~åmTxúÅóƒì¸ò§!/üŠc\Oòù7Ó÷[|<®Qó˜#>5%ô{ Zp5sü{÷gø‹û¡?˜®üÕo¦®ù�PÈÇzßùì¤âþô}þ²€ríþ»oš]©[˜ùíQj5Mýüˆ�Þ¹�û'�Èrx¬‰þÔÔ‰à§/5©NÝ~ÿž$@‡x˜¤¶+µT¨û{Ÿ¤vÕüpê7ßýõ•£5z(5JŽ�m…Ä.ð :Ä•_7VR7›ø�„µ4I-UêƒÞ4õ[ïÞ?ZN�R£Ô!IYÅÜ>å9tʨï¿kÛ“údà¼ïÄVüöÉRK”zè¾Ë©'Ÿ]øä�^ùø…ÏøÏ/Ö§Vÿð왋RS6I-­N–ˆ]´FäÔCCCo¾óö[O ±så¾–£š÷�À,µlâwè™ßÊݪyjœºmÔÉ«NÖJ–Z²�ÖIÍ©ßýõs&@D®=ÿõ»šQ·£Ô}=YKÝ,K= ÔCZžú­wIT@D®ÜûÝ·´µ¤8™tâw¿œÄm¢5˜¥Ò¥úÍw�jˆ*ÔIÉeèêd2«îI–ZnÕá÷Ñ2Õ§©~ŽU@+>ý\êSZŠº‰Q7]JÝ¡Ž²˜Ú­ÔªT¿óîÛ¿¾õù–U@S®]y~õþ¯ß~÷S¨ÛTê-¦=ñ;H©‡ÞxãÍ_œz÷Ý·ßþÕýûW¯>þüŠÎ5>+ÇÚŸU MT„ñêÕû÷õöÛï¾{êo¾aµ¤8™ßZÉXJf5õ`³šß6«~ëï(^­šµÆ¯U~õ«_]¿^€cÊõëŠj‚hÈ¢ê�§ÞùÅ[vŸ¶ õ!ÙB+ÔZji�²^¥~CçÍ7ß|ë­_üâï¼óÎ)�ÿ-€ÿýWþŽAög¢¢ŠŠ0¾õ–¢ŽºCIœúd“urÖRGËRKÓÔoØxÓâ-¿€c‚Óžh·G™RË’ÔƒÉÛC«Å,µlæ·sê·¥Ô6©ÖÄÚ¥ÖX6ÀÑÕg—öupŽÚ'KÝŸ $u+»hIÓÔ'¥iê7\Ní¯ÔoýBÕjÌà°êt R¿é¯ÔCM”z0¼R÷÷õfcêþ¾‹©}òÔRýV@¢ZËUë·Z4ÙŸÖW$ç8Ç9ÎqŽsœãç8Ç9Îñ–Ž·æcºJ%¨SÔM“Ô~+©$h%©<™skêЫ©ýÖS7ËS{²Öúpª/ãû–1Ê®ão_‡èÇß²o¤À9ÎqŽsœãç8Ç9ÎqŽsœãMŽ{üJ÷/CŸ%~‚7½)jŸ…Ô'Ã'©“³ƒV¸­©›¥©}”ú ï£ ­Õv»€žÓºŸ½ùÖ›asÔͦ}4uêþÄ:uÔ<µÌªùÞ|óÍÖg}‡˜÷�,¡n:ñ»…e!”­8ò:Ý4Eí—¤1ï[Zð»wNÝ×¶Sû—(“ÎþÆ©޲NËÖP¿ùFKÓ¾OøNûHüZjßÅÔƒ'[ËSûdªß«ލR¿ÙlÒ·C¨å9ê-­¤îKV’ZÑþˆi ½á*Ræ3û›d5ÀQÓi?ÞhǨ›Öûîëa’ºÕ4µM©}J” …ÉS“®86-1j¿uÔr¥n¶)uoç}‡YLíçÔ'Ã9u TS¯ à¨Ê´Ä§}sÔ‘§}÷4IÝbšºùÔo‰S7µjm¶½¾Œý-ûœð7ßzËõÎqüM{û79ÎqŽsœãç8Ç9ÎqŽsœã9Þð¯·\~Ö8ïͼ,Ô>³¾F=¢8YÂÊ“…+ú�§–HõoFã-ÿÍrœãç8Ç9ÎqŽsœãç8Ç�‡±PúܼÌw�Qû)õ`²ç}û8õ€š:ÒÜïv¤!oD3êÁÁVæ}÷õzâwô™ß~»Sûå©ý €ÀÑöé°9ꃇh)u¿ßÜï–�z(D¢šT5ÀÑviÙ„o�O;„:d’Ú'M�À$u�R‡ÍSûI5V pt•ZÎÐP»9êdü·œ:œS{¥ÚgU5SÀއL7jgŽºÅÚd}½-ø°5u¿¯Rú*µÛ©‡ÞF{ê|ð«GkNä}Cêÿ 0êጺ ¡9ê0‹©ýwÒj&ÕͬZk3w�`‹n&Ò¡SÔþûg…Ú@«?JÝ×âjjgžúD¥zcè�Шƒ¢ÿŸù]‡¶´]/˺9ÎqŽsœãç8Ç9ÎqŽsœã=<�!©µ­}R·ž¤î}š:T�²€åÔMóÔ¡RÕp´�Ùa@ŠÚ™£³�V&~÷õõµ®Ô�N-•j¬àXÛt¡ŽPí;!Fí3ó;äNZa¥Ú·8y¡>yòd RmI=�\¥ö›ùݘ¦ Rj?©&Y p”eZͤ†4ê¡�º?ÑYê�NP£L&Õ¾V=4D¶àê´?-¥¨CUûNFq²ðiê'Ÿ �jÄàxØ´*ÔCMRÔQf}'D¨U±oyoê0N}²‰S7患ׇFŸ¯›:ŸÄ[3jßzßÉ‘ê.9õIí눖±Få }þÆþÖz�3óøÆñ7ŒãoÇß�ƒãç8Ç9ÎqŽsœãç8Ç9Þô¸Ÿ5üLo’“’u“eÔÞõ@¢}:p5u`�2�TûY57¤6Ý,E:IÝ— úû£ìNN©u­Æ¬Ž“OËg|7ê�Ð ©%Õa ”¹÷Ò:Ñ‚UÀq�é!?1ôuÄõaêæU¿¥RíkÕˆ5ÀÑÖé“A>Ý\¨Ã-¤îKÔ¼ï «n¢ÔÞÉßͤ³8Š6}òä�¿ ÊÔñ„G0Cç¨�S÷7uêÁÖ¤š„5ÀÑÐhC¦‡š+àÉ(B}(æ}ë[SG]O-OTŸ !Õ�´uc,†$•̰o€dY´ö¿¡9&Gí•ÏÓ¤ÈS‡pêÁ>œlïÔã'Cf)ñ“æT}óÀÇ9ÎqŽsœãç8Ç9ÎqŽs<âñFÖ"'¢Íù0êþCãÓýÚbðH‰êŽ(5RNÈJ|ûõ` F�Äuø eªR‡ÏTŸÄ«ާS·!ÔF�@¥’ê�ijŸ2eˆ5Àq3i™–ú´´2YÿaZH­—(k!Q-ÍSK5^ pÌ�:”PÕúV�:™RÝŠRKÕÍ´º‘®F®Ž–Gû¯œnQ¨ƒ‹}÷¾,µ|Aµ\©O„«8ämæLÃi <1Ûâ:êD µ‘¦ne9uPª:4'µ²àš`ßi¸¾ã°¿€®ùq€Ù}Íð7Óè¢e`%>-+õ¬ÔýÉuê Í´BVþnÕª=Ší·ÛÈmÛZY_†œ4åÜ^}|­šíç8Ç9ÎqŽsœãç8Ç9Îq¿ãR¿rþo; úæ§[›óm¤¨“jÔý}-ÏýðUêæ«ªàè3è+Ôr£>œ³¾�m´úZMTH5Z €Ow,G�p§ÎRû䩃­úÄ V p<…:@§#¤¨“.ÔM�Úת›ÀG ›n6ç»™R÷I§l.Õ†X#×GT£µ‰ÞMmÚ?C}„º¯¿Yáï(ó¿ÝjÍ„p€#ãÒƒ'|wÉ �¡>F"Kí+Ô-Iõ ñ°­jê'Ha$ßžõ\´nÐ'Ì Þ'B›`�Qûô!qêÈë©ÃO—ɵ©×Æ7�!Ò“Ú'ÖmýŸ5œ'NØ�›œÇ�qœãç8Ç9ÎqŽsœãçø±?îð«Fc¯Iý,2š2úûô@“Êd‡D¨ûÚÊS«ÿ¯‹œðý�•ív¶á8Ç9ÎqŽsœãç8Ç9ÎqŽû���àüôјõ݉LuëSÀàH38å»™OŽ ´EÊš*u«ÖžŸtºYR¶©N÷ª$us¥‘¨Ф­8ÎBÝÔ§�VŽ:|íïVM¶—Žœ >”:.Q=Ϊ�µÕˆ5.ÝšO¾Òd!“Ôa§{¼·8z&­þO >Z©eš:´T·dÕæF[æ*ëÖ[kv¼hä¤[’é¦ûPêu UÊ ©nY¬m†mþaØõ€ñÛ�Ù÷€ÿÐ6zŽsœãç8Ç9ÎqŽsœã縯_Ùük`Ж0^:t®UúCç§±Q÷‡ŸüÝ]¨5ÛøžcPÿÓö�‡U†]?Þ0qcxÇ9ÎqŽsœãç8Ç9ÎqŽsœã¶ã¦_y�Ëü«Ã¾×>EÝxSÔÆþÔ¡§÷tÚ«ÛrqŸ�ç8Ç9ÎqŽsœãç8Ç9ÎqŽwÇ•;:áû(µ.Õ­0 ×éV¦|k>}Ø�º¯¿5«@¬ÀcÓ­úô¡×éÖj”!ÕàkÕ-ÑwrÔ-m¦ÕÕ‚epHez ‚V �î3¾è�"Öý˜5Àñ•éH6Ýwd|:z¢Ú6±8f.ÝM§�T†ÚÜ :b–ÚiÕšXc×GС�‚Þú4ïè2}$³ÔmJµw•µmN¸û=$ÝžíÚ\º}úŽžNë©êIµeÖæÿõµÔ ©î7««ë#c1ûqèˆ{_ºüËëg{n;+}ôsÔV¢ºƒZ´ —cθ¾y™1{ÀÊ~ÇxZ£mvŽsœãç8Ç9ÎqŽsœãçxóã¦_Öåð¯`eë<}}GÔ§ §îë¾S‡õmÉvØç8Ç9ÎqŽsœãç8Ç9ÎñPÇ»-Çǽ*Y§køétß‘NQÛ‹cÖÐq§>yjrÕÐI�>6ôwvS-8æ>}Œ”ÚÒjíÎ|ˆjÓGwˬP[UcÕI§�ÍúißJeúÿñY€}ºï+u: ÑŒZwêcO¿­Xz A.mù#˜V­¯'ǪÀ_§ûmþ؇T»Åº�ze ‘iãÿ!ҡܺñààØûtß±/G~aµ•Ìïïg>8ÀñóhË M?d®wxµ6ÖVS¸ à8y´YÍÛü™é6wÙ2'ƒ÷ÛÖFÞ_úüàpø³ÇïÌ §ÿº±—µ±8½¯ñФšL7@|®Ü Ñ} qnüÈL§"ÑÝÊT›·ßöœû�ï/ì3úÝÅÍú|mºÙñ~Žsœãç8Ç9ÎqŽsœãçx¨ãr¿ê“ﳿî3*�¹ýº\ÄÌÚx«Ï.Ývóî·V°›;�»’ÛÖx6\œãç8Ç9ÎqŽsœãç8Ç9鸭.–Ó¿Ü~殤åV=H‚p{ʈ›£gÃ~û4}³Ç9ÎqŽsœãç8Ç9ÎqŽs<Äq‰_¹ü ŽÔ†×�—ýÖH÷›õϼÇû9ÎqŽsœãç8Ç9ÎqŽsœã¡Ž[~EÎùXä°û9ÎqŽsœãç8Ç9ÎqŽsœãÝ:Ç�ÿ?BYªZëD-IEND®B`‚heldercorreia-speedcrunch-e7ca37f/doc/src/sitemap.xml000066400000000000000000000035311526573132500230570ustar00rootroot00000000000000 https://www.speedcrunch.org/ https://www.speedcrunch.org/download.html https://www.speedcrunch.org/community.html https://www.speedcrunch.org/donate.html https://www.speedcrunch.org/contents.html https://www.speedcrunch.org/introduction.html https://www.speedcrunch.org/userguide/index.html https://www.speedcrunch.org/userguide/installation.html https://www.speedcrunch.org/userguide/first_steps.html https://www.speedcrunch.org/userguide/syntax.html https://www.speedcrunch.org/userguide/advanced.html https://www.speedcrunch.org/userguide/interface.html https://www.speedcrunch.org/userguide/session_json_schema.html https://www.speedcrunch.org/userguide/theme_json_schema.html https://www.speedcrunch.org/reference/index.html https://www.speedcrunch.org/reference/basic.html https://www.speedcrunch.org/reference/integer.html https://www.speedcrunch.org/reference/statistical.html https://www.speedcrunch.org/reference/ieee754.html https://www.speedcrunch.org/reference/constants.html https://www.speedcrunch.org/reference/units.html heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/000077500000000000000000000000001526573132500226655ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/advanced.rst000066400000000000000000000220551526573132500251700ustar00rootroot00000000000000.. meta:: :description: Learn how to define variables, custom functions and units in SpeedCrunch, reuse calculation results, and convert between compatible units. User-Defined Variables, Functions and Units =========================================== .. _variables: Variables --------- When working on more sophisticated problems, you will likely find that you frequently need to access results from previous computations. As we have already seen, you can simply recall results from the result window. However, SpeedCrunch also offers another more powerful way: Variables. Variables allow you to store and recall any value, by assigning it a name. Variables are defined using the :samp:`{variable}={value}` syntax:: a = 5.123 You can attach a comment to the definition by appending ``?`` and text:: a = 5.123 ? calibration value This comment is displayed in the User Variables dock widget and in autocomplete suggestions. Now you can access this value via the name ``a`` much like you would use a built-in constant like :const:`pi`. Naturally, when assigning a value, the right-hand-side can be an arbitrarily complex expression:: mass = 100+20 = 120 g = 9.81 = 9.81 weight = mass*g = 1177.2 somethingelse = ln(sqrt(123) + ans) = 7.08027102937165690787 As you see, using descriptive variable names can make the calculation history much more readable. .. _user_functions: User Functions -------------- .. versionadded:: 0.12 Just as you can define your own variables, it is also possible to define your own functions. While SpeedCrunch comes with an extensive collection of built-in functions (:ref:`sc:functionindex`), defining your own functions can be very useful when you find yourself repeating a similar computation over and over again. Defining a custom function is similar to defining a variable:: f(x) = 5*x+8 Function definitions can also include a trailing comment:: f(x) = 5*x+8 ? affine transform Like variable comments, this comment is shown in the Functions dock widget and in autocomplete suggestions. You can now use the new function ``f`` just like any of the built-in ones:: f(5) = 33 Functions with more arguments are possible as well; simply separate the parameters with a semicolon:: f(x; y) = x*y + x f(2; 3) = 8 .. _units: Units ----- .. versionadded:: 0.12 SpeedCrunch includes a powerful system for units and unit conversions. It provides an extensive list of built-in units and easily allows you to define your own. Units are attached to the term on their left using square brackets:: 5 [ft] = 1.524 [m] If the left-hand side is parenthesized, the bracket applies to the whole parenthesized expression:: (5+6)[ly] = 11 [ly] To raise a quantity to a power, put the value and its unit inside parentheses:: (2[m])² = 4 m² (2[m])^(-2) = 0.25 mâ�»Â² The power applies to both the value and the unit. Parentheses also let you raise a compound expression to a power, such as ``(2[m]/1[m])^(-2) = 0.25``. Input such as ``2[m]^2`` is rejected because it is ambiguous. Use ``(2[m])^2`` to square the whole quantity, or ``2[m^2]`` to enter two square metres. By default SpeedCrunch converts the quantity into SI units:: 60[mi/h] = 26.8224 [mâ‹…sâ�»Â¹] This alone would not be terribly useful. However, it is possible to convert the value to a different unit using the conversion operator ``->`` (``in`` can be used as an alias):: 50[yd] + 2[ft] in [cm] = 4632.96 [cm] 10[kn] -> [km/h] = 18.52 [km/h] Displayed value-unit formatting uses a narrow no-break space (U+202F) between the numeric value and the unit block, for example ``1.23 [m]``. Input accepts unit attachment with or without that separator (for example both ``1[m]`` and ``1 [m]``). In the result display, final value-with-unit result lines are shown without unit brackets (for example ``1.23 m``) to improve readability. Interpreted and simplified expression lines keep bracketed units (for example ``→ [m]``) so conversion targets remain explicit. When a result is inserted back into the editor (for example by double-clicking), SpeedCrunch uses canonical bracketed unit syntax again. Note that all built-in unit names are singular and use American English spelling. This is independent of the language selected for SpeedCrunch's interface. As seen in the example above, you can use any SI prefixes such as ``k`` or ``c``. They are treated like any other unit, so separate them with a space from the base unit they refer to inside brackets. For astronomical distances, ``pc`` supports positive SI-prefixed forms such as ``kpc`` and ``Mpc``. Since units are now explicit in brackets, short identifiers such as ``a``, ``mg`` and ``l`` are free to use as variable names without conflicting with units. Information units (bit/byte) ---------------------------- For the information dimension, SpeedCrunch supports both ``bit`` (short form ``b``) and ``byte`` (short form ``B``). Prefixes ^^^^^^^^ Positive SI prefixes are accepted for both families (for example ``kB``, ``MB``, ``kb``, ``Mb``), while negative SI prefixes are rejected. Family mixing rules ^^^^^^^^^^^^^^^^^^^ When adding/subtracting information quantities, SpeedCrunch does not implicitly mix bit-family and byte-family values. Use an explicit conversion if you want to switch family:: 1[B] + 8[b] = error 1[B] + (8[b] -> [B]) = 2 [B] Result unit selection ^^^^^^^^^^^^^^^^^^^^^ For sums inside the same family, the displayed result keeps the coarsest unit used in the expression:: 2[MB] + 3[PB] + 4[TB] = 3.004000002 [PB] .. warning:: Prefixes cannot be used on their own. Always attach them to a unit symbol. For instance, if you intend to express the unit 'newtons per centimeter', do not type ``[N / c m]``. Make the order explicit with ``[N / (cm)]``. An important feature of SpeedCrunch's unit system is *dimensional checking*. Simply put, it prevents comparing apples and pears: if you try to convert ``[s]`` to ``[m]``, SpeedCrunch will complain, stating that the dimensions do not match. Indeed, the dimension of ``s`` is *time*, while ``m`` denotes a *length*, thus they cannot be compared, added, etc. When adding, multiplying, or otherwise manipulating units, SpeedCrunch will track the dimension and raise an error if it detects an invalid operation. For instance, if you type ``[m^2]``, the result will be a quantity with the dimension *length*\ :sup:`2` which can only be compared to other quantities with the same dimension. Currently, the available dimensions and their associated primitive units are: * *Length*: ``m`` * *Mass*: ``kg`` * *Time*: ``s`` * *Electric current*: ``A`` * *Amount*: ``mol`` * *Luminous intensity*: ``cd`` * *Temperature*: ``K`` * *Information*: ``b`` Temperature conversions also support the affine scales ``degree_celsius`` (short form ``°C``) and ``degree_fahrenheit`` (short form ``°F``). The input aliases ``ºC``, ``ËšC``, ``ºF`` and ``ËšF`` are accepted and normalized to ``°C`` and ``°F``:: 77 [°F] -> [°C] = 25 [°C] 25 [°C] -> [K] = 298.15 [K] 298.15 [K] -> [°C] = 25 [°C] 77 [°F] -> [°C] = 25 [°C] Defining a custom unit uses bracketed unit assignment:: [earth_radius] = 6730[km] 3.5[au] in [earth_radius] = 77799.78416790490341753343 [earth_radius] Any variable or expression can be used as the right-hand side of a conversion expression:: 10[m] in (1[yd] + 2[ft]) = 6.56167979002624671916 (1[yd] + 2[ft]) Use unit symbols by default (for example ``m``, ``s``, ``B``, ``b``). Full built-in names are accepted as an alternative input form. Built-in short forms include: * Length/astronomy: ``au`` (``astronomical_unit``), ``ly`` (``lightyear``), ``ls`` (``lightsecond``), ``lmin`` (``lightminute``), ``pc`` (``parsec``), ``in`` (``inch``), ``ft`` (``foot``). * Time: ``min`` (``minute``), ``h`` (``hour``), ``cy`` (``century``). * Angle: ``deg`` (``degree``), ``gon`` (``gradian``). * Information: ``b`` (``bit``), ``B`` (``byte``). * Other common aliases: ``u``/``Da`` (``atomic_mass_unit``), ``nmi`` (``nautical_mile``). For units that allow prefixes, the same short forms can be used in prefixed form as well (for example ``kpc``, ``Mpc``, ``MB``, ``kb``). Common examples include ``mm``, ``cm``, ``km``, ``mg``, ``kg``, ``mV``, ``kW``, ``MeV``, ``dL`` and ``dl``. SI-accepted mass unit ``t`` (full name ``tonne``) is available and equals ``1000[kg]``:: 1[t] -> [kg] = 1000 [kg] 1000[kg] -> [t] = 1 [t] .. _user_units: User Units ---------- You can define your own unit identifiers using square brackets on the left-hand side:: [two_cubic_metres] = 2[m^3] [ten_metres] = 10[m] [cm_s] = [cm/s] User unit definitions can also include a trailing comment:: [cm_s] = [cm/s] ? centimeters per second Like user variables and functions, comments are shown in the corresponding dock widget and in autocomplete suggestions. Some of the built-in functions are able to handle arguments with a dimension. Refer to the documentation of a particular function for more information. heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/first_steps.rst000066400000000000000000000117451526573132500257740ustar00rootroot00000000000000.. meta:: :description: Get started with SpeedCrunch: enter calculations, recall results, use the keyboard interface, and explore built-in functions and variables. First Steps =========== SpeedCrunch is designed to be used via the keyboard. While an :ref:`on-screen keypad ` is available, it defaults to the **Basic** layout. The powerful keyboard interface is the recommended way to use SpeedCrunch to get the most out of it. The keypad layout can be configured from: :menuselection:`View --> Keypad`. .. This note included since the code samples aren't translatable; people in comma locales might get confused. .. note:: All examples in this manual use a period (``.``) as the decimal separator. By default, SpeedCrunch will use your system's default decimal separator for output and will accept both a period and a comma (``,``) for input (:ref:`more details `). Depending on your settings, it may be necessary to replace the periods with the appropriate decimal separator when entering these examples into SpeedCrunch. When starting SpeedCrunch for the first time, the interface may thus seem a little plain. Don't be fooled, it can easily be customized. At the bottom edge of the window, you see the the **input bar**, also called the **editor**, with a blinking cursor showing that it is ready to accept keystrokes. To try out SpeedCrunch, type:: 1.234 + 7.89 then hit :kbd:`Enter` to evaluate the expression. The result (along with the expression you just entered) will be displayed at the top of window:: 1.234 + 7.89 = 9.124 This region (called the **result window**) not only shows the result of your last calculation, it is a complete browsable history. Any previous input or result can be recalled by double-clicking the corresponding line. Let's try this out. First, perform some more calculations so that more than one entry is displayed in the result window:: 54*4.514 + 57 = 300.756 54*(4.514 - 5.7) = -64.044 Note how multiplication (``*``) takes precedence over addition (``+``) unless parentheses are used to specify a particular order of evaluation. If you now wish to continue working with one of the results, double-click e.g. the line ``= 300.756``. The input bar will be populated with this result. Similarly, you can also quickly recall previous input by double-clicking them in the result history. Alternatively, depending on :menuselection:`Settings --> Editing --> Up/Down Arrow History`, you can use the :kbd:`Up` and :kbd:`Down` arrow keys on your keyboard to recall previous expressions, or use the mouse wheel for the same effect (the mouse cursor must be hovering over the editor for this to work, otherwise the result window will be scrolled). To continue the computation directly from the previous result, you can use the special variable ``ans`` which always holds the result of the last entry in the history. Try this:: 2+3 ? By the way, you can use question marks for comments. = 5 7*ans ? 'ans' is now equal to 5 = 35 ans + 3 = 38 You can also write comment-only entries. Any line whose first non-space character is ``?`` is treated as a comment and stored in the history:: ? start algorithm ? this comment is also valid As you can see, ``ans`` provides a quick and easy way to access the previous result. Sometimes, SpeedCrunch can even insert ``ans`` for you: When you start a new expression with an operator (e.g. ``+``, ``-``, ``*``, ``/``, ``^``), ``ans`` will be prepended automatically. [#f1]_ To try it out, type ``7`` :kbd:`Enter` ``+3`` :kbd:`Enter`. SpeedCrunch expands this as follows:: 7 = 7 ans+3 = 10 SpeedCrunch comes with a number of :ref:`mathematical constants ` like Ï€ that are available by typing their name:: pi = 3.14159265358979323846 pi*1.2^2 = 4.52389342116930226339 Let us finish this short introduction with a word about functions. SpeedCrunch comes with an extensive list of built-in mathematical functions which can be accessed by simply typing their name in the editor followed by any parameters (also called arguments) in parentheses:: sqrt(144) = 12 The function :func:`sqrt` calculates the square root of its argument. Some functions require or accept more than one argument. In that case, separate them with a semicolon (``;``). If you leave a trailing semicolon while typing, SpeedCrunch treats it as an incomplete final argument and still evaluates the expression (for example ``average(2;3;4;)`` and ``average(2;3;4;``). .. warning:: To repeat: In contrast to many programming languages, parameters in SpeedCrunch are separated by a **semicolon**! An example is the :func:`average` function:: average(12;34;56) = 34 This is already enough to use SpeedCrunch effectively. Try it out for yourself! Alternatively, read on to learn about its more advanced features. .. rubric:: Footnotes .. [#f1] This requires that the :ref:`Auto-Insert ans ` setting is enabled. heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/index.rst000066400000000000000000000011011526573132500245170ustar00rootroot00000000000000.. meta:: :description: Learn to use SpeedCrunch with guides to installation, scientific calculations, expression syntax, custom functions, units and interface settings. User Guide ========== This part of the manual explains how to use SpeedCrunch, starting from the installation and continuing to in-depth descriptions of particular topics and features. It can be read in order or simply used to look up the details of a feature. .. toctree:: :maxdepth: 2 installation first_steps syntax advanced interface session_json_schema theme_json_schema heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/installation.rst000066400000000000000000000127241526573132500261260ustar00rootroot00000000000000.. meta:: :description: Find SpeedCrunch installation instructions for Windows, macOS and Linux, including portable downloads, package managers and building from source. .. highlight:: shell Installation ============ Microsoft Windows ----------------- SpeedCrunch requires 64-bit Windows 10 (version 1809 or later) or Windows 11. Windows 7, 8 and 8.1 are not supported by SpeedCrunch 1.0 or later. .. note:: For older Windows versions, use SpeedCrunch 0.12, available in the "Older Versions" section of the `download page `_. You can choose either the installer or the portable version of SpeedCrunch. Both have the same system requirements and are available from `the SpeedCrunch website `_. .. _sc: http://speedcrunch.org The installer installs SpeedCrunch on your system and creates an entry in the menu to launch it. This process requires administrator rights. Alternatively, you may use the portable version of SpeedCrunch, which is distributed as a ``.zip`` archive. This version requires no installation, simply extract it to a folder of your choice and run :program:`speedcrunch.exe`. In addition, this version of the software is fully portable: It stores all its settings and user data next to the executable so the entire directory can be copied to another computer and run there. macOS ----- SpeedCrunch requires macOS 14.4 (Sonoma) or later. Download the macOS disk image from `the SpeedCrunch website `_, open it, and drag :guilabel:`SpeedCrunch` to the :guilabel:`Applications` folder. On first launch, macOS may block SpeedCrunch because it cannot verify the developer. Only continue if you downloaded SpeedCrunch from the official website and trust the download. Try to open SpeedCrunch once, then: #. Open the Apple menu and choose :guilabel:`System Settings` > :guilabel:`Privacy & Security`. #. Scroll to :guilabel:`Security` and click :guilabel:`Open` or :guilabel:`Open Anyway` next to SpeedCrunch. #. Confirm that you want to open the app. Enter your Mac password if asked. The :guilabel:`Open Anyway` option is available for about an hour after your first attempt. macOS remembers the exception, so you can open SpeedCrunch normally afterward. See `Apple's step-by-step instructions `_. Linux ----- On Linux, SpeedCrunch can be installed either from packages provided by your distribution or from official Flatpak packages. Distribution Packages +++++++++++++++++++++ Many Linux distributions already include packages for SpeedCrunch in their repositories. The exact steps to install these depend on the distribution. For example, on Debian and Ubuntu, the included SpeedCrunch package can be installed by running this command:: sudo apt-get install speedcrunch On Fedora, this command will install SpeedCrunch:: sudo dnf install speedcrunch Check your system's documentation to find out how to install additional packages. Many desktop distributions also include graphical package management software that can be used to install SpeedCrunch. Flatpak +++++++ `Flatpak `_ is a distribution-independent packaging format for Linux desktop applications. The latest stable release of SpeedCrunch is available as a Flatpak package from `Flathub `_. First, visit Flathub's `setup page `_ and follow the instructions for your distribution to set up Flatpak and Flathub. Then install SpeedCrunch from its `store page `_ on Flathub. .. _flatpak: https://flatpak.org/ .. _flathub: https://flathub.org/ .. _flathub-setup: https://flatpak.org/setup/ .. _flathub-sc: https://flathub.org/apps/details/org.speedcrunch.SpeedCrunch Building from Source -------------------- The SpeedCrunch source code is maintained on `GitHub`_ in a Git repository. For build requirements and instructions on compiling, running the tests, and installing from source, see :file:`BUILDING.md` at the repository root. License installation is optional on every platform. The CMake option ``INSTALL_LICENSES`` defaults to ``OFF``. Set ``-DINSTALL_LICENSES=ON`` to install SpeedCrunch's license text and Qt usage notice. On Windows and macOS, this also installs the license texts and notices for bundled Qt components. Windows also installs :file:`COPYING.rtf` beside the application. Both ``BUILD_VARIANT_OFFICIAL_RELEASE`` and ``BUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE`` force ``INSTALL_LICENSES=ON``, even when ``-DINSTALL_LICENSES=OFF`` is supplied. ``BUILD_VARIANT_DEV_DEBUG`` leaves the option unchanged. CMake keeps the value in its cache when a variant is disabled. To stop installing license files in an existing build directory, disable the official variant and set ``-DINSTALL_LICENSES=OFF``. Package providers can leave license installation disabled and use their own packaging tools to include the required license files, such as Fedora's ``%license LICENSE`` directive. Stripping debug symbols is also disabled by default on every platform. Both official release variants force ``STRIP_BINARY=ON``. Otherwise, the application keeps the symbols generated by the compiler unless you explicitly enable this option. The option applies to the selected build configuration, including Debug. Package providers should leave it off so their packaging tools can extract debug information. When disabling an official variant in an existing build directory, also set ``-DSTRIP_BINARY=OFF`` to reset the cached value. .. _GitHub: https://github.com/heldercorreia/speedcrunch heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/interface.rst000066400000000000000000001451751526573132500253740ustar00rootroot00000000000000.. meta:: :description: Explore SpeedCrunch's interface, session tabs and panes, calculation history, result formats, complex numbers, keyboard shortcuts and appearance settings. User Interface ============== Shortcut notation: :kbd:`Ctrl` means :kbd:`Ctrl` on Windows/Linux and :kbd:`Cmd` on macOS. Platform-specific shortcuts spell out :kbd:`Cmd` when they differ from this convention. Widgets ------- Apart from the main display, SpeedCrunch offers a number of extra panels, referred to as *widgets* here. Most of them are dockable panels that can be moved around the main window and enabled or disabled via the :menuselection:`View` menu. Panels docked on the left or right fill the available height. Panels above or below the display and keypad fit between the side panels. Use the cross in a dock panel's title bar to hide the panel, or the square to detach it into a floating window. Hidden panels can be shown again via the :menuselection:`View` menu. Opening another panel leaves floating panels in their own windows. On Linux with Wayland, drag a floating panel by its title bar to move it. Use its square button or double-click the title bar to attach it to the main window again. Drag a table's column headers to change their order. Each window keeps its column order between launches, including for panels that are hidden. * Formula Book The formula book provides access to commonly used formulas and calculations. Simply insert a formula into the expression editor by clicking on it. You can help expanding the formula book by posting your requests to the `issue tracker `_. * Constants The constants widget shows a large list of scientific constants (including CODATA-based entries), grouped by category and subcategory. The columns show each constant's name, value, and unit. Use the ``Domain`` and ``Subdomain`` selectors to narrow the list, or search by name or unit. Press :kbd:`Up` and :kbd:`Down` in the search field to select a result while continuing to type. Press :kbd:`Enter` or double-click an entry to insert its value and unit and return to the editor. The mathematical constants pi and Euler's number are inserted as ``Ï€`` and ``e``. * User Variables The variables widget lists all :ref:`user-defined variables `. Any of them can be inserted into the editor by double-clicking it. Additionally, it is possible to delete a variable by selecting it and pressing the :kbd:`Delete` key on your keyboard. * Functions and User Functions Similar to the variables widget, these show built-in and :ref:`user-defined functions ` respectively. * User Units Similar to the user functions widget, this lists :ref:`user-defined units `. Double-click inserts ``[name]`` in the editor, and the context menu supports edit/delete operations. * Bit Field The bit field dock is designed to make working with binary numbers easier. It shows a field of 64 squares, each representing a bit in the current result. Any bit can be toggled by clicking its square; the resulting number is automatically inserted into the editor. Additional buttons allow you to shift, invert and reset all the bits at once. While the mouse cursor is hovering over the bit field, scrolling the mouse wheel will also shift the bits. .. _keypad: * Keypad The on-screen keypad provides clickable input for common operations and symbols. It supports multiple presets and a custom layout, so you can adapt it to your workflow. You can also adjust the keypad zoom level for better readability or touch area on touchscreens. For fast and full-featured input, SpeedCrunch's keyboard interface is still recommended. Available entries in :menuselection:`View --> Keypad` are: * ``Basic`` (**default**) * ``Scientific (wide)`` * ``Scientific (narrow)`` * ``Custom...`` * ``Disable`` (shown as ``Disabled`` when selected) Both scientific layouts include ``ln`` for the natural logarithm and ``log10`` for the common (base-10) logarithm. These buttons insert ``ln(`` and ``log10(``, respectively. Copying a scientific preset into a custom layout uses the same labels and function names. Since version 1.1, both scientific layouts show ``â�¿âˆš`` for the nth root in place of the cube-root button. It inserts ``root(`` so you can enter a root index and a value, for example ``root(5; 32)``. Copying either scientific preset into a custom layout includes this button. The scientific layouts also include ``x²``, which inserts ``^2``, and ``;`` to separate function arguments. These replace the ``x`` and ``x=`` shortcuts in version 1.1. Related buttons sit together: ``√`` and ``x²``, ``xʸ`` and ``â�¿âˆš``, ``E`` and ``exp``, ``ln`` and ``log10``, and each trigonometric function with its inverse. Available entries in :menuselection:`Settings --> Appearance --> Keypad --> Zoom` are: * ``50%`` * ``100%`` (**default**) * ``150%`` * ``200%`` The zoom level scales the keypad buttons, including their text. Each window keeps its own zoom level. The Zoom submenu is unavailable while the keypad is disabled. You can also right-click the keypad and choose :menuselection:`Zoom`. ``Custom...`` opens a dialog where you can define the keypad matrix size (rows and columns) and configure each button individually. For each position in the matrix, you can set: * The button label shown in the keypad * The button behavior: ``Insert text``, ``Backspace``, ``Clear expression``, or ``Evaluate expression`` * The text to insert (for ``Insert text`` behavior) The dialog also includes a ``Copy preset`` selector with an :guilabel:`Apply` button, so you can start from the ``Basic``, ``Scientific (wide)``, or ``Scientific (narrow)`` layout and then customize it. Custom keypad settings are saved and restored automatically. You can also right-click directly on the keypad to open the same menu as :menuselection:`View --> Keypad`. .. versionadded:: 1.0 .. versionchanged:: 0.11 The keypad was removed in SpeedCrunch 0.11; however, it was added back in 0.12. * History The history widget lists all previous inputs. Double-click a line to recall it. Note that the main result display also provides this functionality. * Main Menu Toggle the main menu bar visibility via :menuselection:`View --> Main Menu`. This option is available on Windows and Linux. On macOS, this option is not available because the application menu is managed by the system menu bar (outside the window), so SpeedCrunch cannot hide it like on Windows and Linux. On Windows and Linux, when the top main menu is hidden, a navigable Main Menu (mirroring the top menu structure) is available from the right-click context menu on the result-display. .. versionadded:: 1.0 .. _tracker: https://speedcrunch.org/issues.html Session Tabs and Panes ---------------------- When a pane contains more than one session, SpeedCrunch shows a tab bar above the result display. Click a tab to switch sessions, drag tabs horizontally to reorder them within the pane, or drag a tab away from the tab bar to move it to another pane. Dropping a dragged tab outside the current window creates a new window for that session; dropping it on a pane in another SpeedCrunch window moves it there. Use :menuselection:`Session --> Rename...` to rename the active session. You can also double-click its tab, choose :menuselection:`Rename...` from the tab context menu, or choose :menuselection:`Session --> Rename...` from the result display context menu. Choose :menuselection:`Session --> Clone...` to copy the active session under a new name, including its unfinished expression. This command is also available as :menuselection:`Clone...` in the tab context menu and :menuselection:`Session --> Clone...` in the result display context menu. Use :menuselection:`Session --> New Window` to open a blank session in a new window that copies the current window and dock layout. Choose :menuselection:`Session --> Close Tab` to close the active tab, or :menuselection:`Session --> Reopen Closed Tab` to restore the last ordinary tab you closed. Private tabs cannot be reopened. Both commands are also available from the tab context menu. When a floating dock has focus, session commands apply to its window. Use :menuselection:`View --> Split` to add a pane in any direction, and :menuselection:`View --> Close Pane` to close the active pane. The tab context menu also provides :menuselection:`Split` and :menuselection:`Close Pane`. The tab context menu's :menuselection:`Clear` command removes the session's calculations, unfinished expression, variables, functions, and units after confirmation. Global user definitions are kept. :menuselection:`Delete` removes the session itself after confirmation. When SpeedCrunch restores multiple windows after a restart, each window keeps its own dock layout, dock visibility, keypad visibility, layout and zoom, and—when window position saving is enabled—its own size and position. Private Sessions ---------------- Use :menuselection:`Session --> New Private Tab` or :kbd:`Ctrl+Shift+N` (:kbd:`Cmd+Shift+N` on macOS) to open a session that stays in memory. Private sessions are named ``Private-1``, ``Private-2``, and so on, using the first available number. A shield icon marks their tabs. The window title also identifies the active private session, even after you rename it. The tab bar is hidden when a private session is the only session in a single pane, just as it is for an ordinary session. Private sessions do not save their history, unfinished expressions, variables, functions, or units automatically. They are excluded from the workspace restored at the next launch. Closing a private session discards its contents, and it cannot be reopened with the Restore Closed Tab shortcut. Copying and explicit export remain available. Cloning a private session creates another private session. Choose :menuselection:`Session --> Keep` to save a private session, including its current contents. It receives the first available ``Untitled-XXX`` name and behaves like an ordinary session from then on. Choose :menuselection:`Session --> Make Private...` to convert an ordinary session. SpeedCrunch asks for confirmation before deleting its saved JSON file. Its contents stay open under the first available ``Private-XXX`` name until you close it or exit. If the file cannot be deleted, the session remains ordinary. If a private session cannot be saved during conversion, it remains private. These actions are also available from the tab and result display context menus. In the result display, open the :guilabel:`Session` submenu and choose :guilabel:`Keep` or :guilabel:`Make Private...`. Privacy belongs to the session, so renaming it does not change whether it is saved. Ordinary sessions can remain open alongside private ones. Enable :menuselection:`Settings --> Window --> Open a Private Tab on Startup` to open and focus a fresh private tab whenever SpeedCrunch starts. This option is off by default. Saved ordinary sessions are restored as usual, with one new private tab in the active window, even when several windows are restored. An empty active ``Untitled-XXX`` session is used for the private tab instead of opening an extra ordinary tab. Sessions with history, unfinished expressions, or their own definitions stay open. When there are no sessions to restore, SpeedCrunch starts with just the private tab. Opening another window while the app is running still creates an ordinary session. .. versionadded:: 1.1 Expression Editor Features -------------------------- Turn off :menuselection:`Settings --> Editing --> Automatic Input Adjustments` to enter text without automatic text adjustments or character restrictions. The expression editor provides some advanced features: * Undo and redo Choose :menuselection:`Edit --> Undo` or :menuselection:`Edit --> Redo`. Press :kbd:`Ctrl+Z` to undo the last edit. On Windows/Linux, use :kbd:`Ctrl+Shift+Z` or :kbd:`Ctrl+Y` to redo it. On macOS, use :kbd:`Cmd+Shift+Z`. Each key press is a separate undo step. Automatic changes made by that key, such as inserting a closing bracket or converting an exponent to superscript, are undone together. Text committed through an input method is undone as a single edit. :menuselection:`Edit --> Cut` cuts selected input text. Copy also works on selected result text. These actions are disabled when unavailable. :menuselection:`Edit --> Wrap in Parentheses` wraps the selected input, or the whole expression if nothing is selected. * Automatic closing parentheses and square brackets Typing ``(`` or ``[`` with no text selected inserts the matching closing character only when the cursor is at the end of the expression or only whitespace follows it. The cursor stays between the pair. If non-whitespace text follows the cursor, only the opening character is inserted. * Autocompletion If you start typing a name (e.g. of a variable, function, or unit), a pop-up with matching names will appear below the editor, aligned with the start of the name being completed. It appears above the editor when there is insufficient space below and shifts horizontally to stay on screen. The list becomes shorter and scrollable when needed to avoid covering the editor. On Wayland with Qt 6.6 or later, the compositor chooses below or above according to the available screen space. With older Qt versions on Wayland, the list stays within the application window. Alignment follows the visible text even when the expression wraps or scrolls. Press :kbd:`Tab` to insert the current suggestion. Pressing :kbd:`Enter` evaluates the expression by default. If you explicitly navigate the popup with arrow/page/home/end keys or click a suggestion with the mouse, then :kbd:`Enter` accepts that selected suggestion. Enable :menuselection:`Settings --> Editing --> Autocomplete --> Accept with Enter` to accept the current suggestion with :kbd:`Enter` immediately, without first using the arrow keys. Pressing :kbd:`Escape` dismisses the autocomplete popup. * Function signature tooltip While typing a function call, the live result area can show the function signature (parameter list). The parameter currently being edited is highlighted. This also works for user-defined functions. Pressing :kbd:`Escape` will dismiss the tooltip. * Quick constant insertion Press :kbd:`Ctrl+Space` to search the same constants as the constants widget (see above). Type a name or unit to filter the list. Each result shows its unit beside the name using the theme's unit color. Press :kbd:`Up` and :kbd:`Down` to select a result. Press :kbd:`Tab` or :kbd:`Enter`, or click a result, to insert it and return to the editor. :kbd:`Shift+Tab` moves focus backward. With no matches, :kbd:`Tab` leaves the popup open. Press :kbd:`Escape` to cancel. Search text does not change the expression. The list follows the cursor's horizontal position and uses the same below-or-above placement rules as autocompletion. .. versionadded:: 1.1 Search in the quick constant popup and select dock search results with :kbd:`Up` and :kbd:`Down`. .. _context-help: * Context help Pressing :kbd:`F1` will show the manual page for the function under the cursor, providing quick access to detailed usage information for a function. Pressing :kbd:`Escape` will dismiss the manual window again. * Selection results If :menuselection:`Settings --> Results --> Show Live Result Preview` is enabled, selecting a partial expression in the expression editor or in the result display will show you the result of the selected expression. You can dismiss this preview by pressing :kbd:`Escape` or by clicking the :guilabel:`×` button at the top-right corner of the preview. Import/Export ------------- SpeedCrunch automatically stores your sessions and lets you restore them with :menuselection:`Session --> Open`. Use :menuselection:`Session --> Open Sessions Folder` to open the folder where SpeedCrunch stores these session files when you want to back them up or clean them up manually. You can also export the current session as JSON (:menuselection:`Session --> Export --> JSON`) and later import it with :menuselection:`Session --> Import`. The data is stored in a SpeedCrunch-specific file format. [#f1]_ While the session files are human-readable, they are designed for use by SpeedCrunch. If you want to export your calculations to work on them in another program or hand them to a colleague, the other export options are preferable. Import validates the selected JSON file as a SpeedCrunch session and opens it as a new tab. If the file is not valid SpeedCrunch session JSON, SpeedCrunch shows an error and leaves the current session unchanged. You can export the session as HTML (:menuselection:`Session --> Export --> HTML`). The resulting file will consist of the contents of the result display and can be viewed in any web browser. This feature can also be used to print a SpeedCrunch session by printing the exported HTML document. Since the syntax highlighting and color scheme are maintained in the HTML output, it is recommended to select a color scheme with a white background (e.g. *Standard*) prior to exporting if you intend to print the document. The final, most basic option is to export your session as a plain text file (:menuselection:`Session --> Export --> Plain text`). In contrast to the HTML export option, the syntax highlighting will be lost. User Definitions ++++++++++++++++++++++++ .. versionadded:: 1.0 To define user variables, user functions and user units that are loaded globally, use :menuselection:`Settings --> User Definitions...`. This dialog provides: * A multi-line editor (one definition per line), with syntax highlighting and line numbers. * A clear reminder that these definitions are global, loaded into every session and override same-name session definitions. * :guilabel:`Apply` to apply definitions immediately. * :guilabel:`Validate` to validate and preview results without applying. When applying or testing, SpeedCrunch reports: * Imported variable count * Imported function count * Imported unit count * Line numbers with errors Invalid definitions are ignored. Variable definitions that evaluate to ``NaN`` are also ignored. Settings -------- SpeedCrunch's behavior can be customized to a large degree using the configuration options in the :menuselection:`Settings` menu. This section explains the settings that are available. Resetting Settings ++++++++++++++++++ Choose :menuselection:`Settings --> Reset All Settings...` to restore the default preferences. SpeedCrunch asks for confirmation before making any changes. The reset applies to all open windows immediately and is saved for the next launch. It includes appearance, editing options, number and result formats, language, and window preferences, including dock visibility and keypad settings. Your calculation history, open session tabs and panes, and user definitions are kept. Existing calculations keep their recorded result formats. New calculations and live previews use the default settings. .. versionadded:: 1.1 Result Display Interactions +++++++++++++++++++++++++++ The result display supports mouse-driven interactions for navigation and editing. * Right-click context menu Right-clicking an expression/calculation block in the result display opens a context menu for that specific block. The :guilabel:`Copy` submenu starts with :guilabel:`Selection` to copy the selected text. :guilabel:`Select All` selects all text in the display. Open the :guilabel:`Copy` submenu and choose :guilabel:`Calculation` to copy all displayed lines of the calculation at once, including the expression, any simplification, and every result format. The lines are copied as plain text in the order shown, without the blank line between calculations. :guilabel:`Expression` and :guilabel:`Result` let you copy either part separately. :guilabel:`Remove` offers :guilabel:`This Calculation`, :guilabel:`All Calculations Above`, and :guilabel:`All Calculations Below`. This menu includes an entry to toggle the main menu bar visibility. Use its :guilabel:`Split` submenu to add a pane to the left, right, above, or below the current pane. :guilabel:`New Tab` and :guilabel:`New Private Tab` create sessions directly. The :guilabel:`Session` submenu starts with :guilabel:`Open...`, :guilabel:`Import...`, and :guilabel:`Export`. It also groups actions to duplicate, rename, change privacy, clear, delete, or close the current session. .. versionadded:: 1.0 The :guilabel:`Copy` submenu also offers :guilabel:`Calculation as Single Line` to join all displayed lines of the calculation with spaces, for example ``120 / 8 = 15``. .. versionadded:: 1.1 * Hover highlighting of calculation blocks When :menuselection:`Settings --> Appearance --> Hover Highlighting` is enabled, moving the mouse over the result display highlights the calculation block under the cursor. The highlighted block also shows quick-action icons for deleting, editing, and copying. .. versionadded:: 1.0 * History rewriting from highlighted blocks From the hovered/highlighted calculation block, you can re-edit an earlier expression and apply it as a history rewrite. SpeedCrunch then recalculates all expressions below that edited entry. .. versionadded:: 1.0 * Calculation settings from highlighted blocks The calculation settings action opens a tabular layout with one mandatory ``Main Line`` row and four optional extra result-line rows. The table shows line enablement, notation, and decimal places together so the stored calculation context can be adjusted before SpeedCrunch recalculates the affected history. .. _result_format: Notation +++++++++++++ This section allows selecting the result notation to use (for example in :menuselection:`Settings --> Results --> Notation & Precision...` or from the status-bar notation selector). You can select one of the following options. On first launch, the default is :menuselection:`Automatic decimal`. * :menuselection:`Automatic decimal` Use fixed-point decimal form for most results; values with exponent larger than 14 or smaller than -9 are shown in scientific notation. With a finite precision setting, very small values may switch to scientific notation earlier. * :menuselection:`Fixed-point decimal` Display results in fixed-point decimal form. For excessively large or small numbers, this format may still fall back to scientific notation. * :menuselection:`Engineering decimal` Display results in engineering notation. This is a variant of :ref:`scientific notation ` in which the exponent is divisible by three. * :menuselection:`Scientific decimal` Display results in :ref:`normalized scientific notation `. * :menuselection:`Rational` Try to display real results as fractions (for example, ``1/3``) using continued-fraction approximation with bounded denominator. If no close match is found, results are displayed in decimal form. For common trigonometric and inverse-trigonometric results, SpeedCrunch prefers symbolic exact forms such as ``pi/2``, ``7â‹…pi/6``, ``1/2``, ``sqrt(2)/2``, and ``sqrt(3)/3``. Example:: arcsin(1) = pi/2 sin(45) (angle mode = degree) = √(2)/2 arcsin(sqrt(3)/22) = 0.07881114207211010205 .. versionadded:: 1.0 * :menuselection:`Binary` Display results as binary numbers, i.e. in base-2. * :menuselection:`Octal` Display all results as octal numbers, i.e. in base-8. * :menuselection:`Hexadecimal` Display all results as hexadecimal numbers, i.e. in base-16. * :menuselection:`Sexagesimal` Display dimensionless and time results as :ref:`sexagesimal values `, i.e. with minutes and seconds. All other results are displayed in fixed-point decimal form. .. versionadded:: 1.0 Angle Mode ++++++++++ Select the angular unit to be used in calculations. For functions that operate on angles, notably the :ref:`trigonometric functions ` like :func:`sin` or :func:`cos`, this setting determines the angle format of the arguments. * :menuselection:`Radian` Use radians for angles. A full circle corresponds to an angle of 2Ï€ radians. * :menuselection:`Degree` Use degrees for angles. A full circle corresponds to an angle of 360°. * :menuselection:`Gradian` Use gradians for angles. A full circle corresponds to an angle of 400 gradians. .. versionadded:: 1.0 * :menuselection:`Turn` Use turns for angles. A full circle corresponds to an angle of 1 turn. * :menuselection:`Revolution` Use revolutions for angles. A full circle corresponds to an angle of 1 revolution. .. versionadded:: 1.0 .. _complex_numbers: Complex Numbers +++++++++++++++ Choose a result form via :menuselection:`Settings --> Results --> Complex Form` and a symbol via :menuselection:`Settings --> Results --> Imaginary Unit`. Complex numbers are always enabled. * :menuselection:`Imaginary Unit --> i` Use ``i`` as the imaginary unit symbol. * :menuselection:`Imaginary Unit --> j` Use ``j`` as the imaginary unit symbol. * :menuselection:`Complex Form --> Rectangular (a + bi)` Display complex results in rectangular form. * :menuselection:`Complex Form --> Exponential (reâ�±á¶¿)` Display complex results in exponential form. * :menuselection:`Complex Form --> Trigonometric (r(cos θ + i·sin θ))` Display complex results in trigonometric form. * :menuselection:`Complex Form --> Cis (r·cis(θ))` Display complex results in cis form. * :menuselection:`Complex Form --> Phasor (r∠θ)` Display complex results in phasor form. When the angle mode is set to radians, simple phase multiples of ``pi`` are shown symbolically in these complex forms. Other angle modes show their numeric phase values. .. _radix_character: Number Format +++++++++++++ Choose how decimal numbers are displayed and interpreted via :menuselection:`Settings --> Number Format...`. This shared setting controls result formatting and, when :menuselection:`Settings --> Editing --> Group Digits in Input` is enabled, digit grouping in the input field. .. versionadded:: 1.0 This dialog replaces the older separate Radix Character and Digit Grouping menus with a single combined Number Format selection. The default option is no digit grouping with dot decimal separator (``1234567.12345``). Additional options let you choose: * no digit grouping with dot or comma decimal separator * SI grouping with space separators (integer and fractional grouped in 3s) * 3-digit grouping with comma, dot, space, or underscore * Indian/South Asian 3-2-2 grouping with comma separators Some options include grouped fractional digits; those are separate explicit choices. The apostrophe (``'``), commonly used as a thousands separator in some locales and contexts (for example Switzerland, Liechtenstein, and some technical writing in Austria/Germany), is intentionally not offered because SpeedCrunch reserves it for :ref:`sexagesimal notation `. For input, SpeedCrunch remains permissive across styles to support copy/paste from other applications. In clear mixed-separator cases, it accepts the number and normalizes it by ignoring non-digit grouping characters as needed. History Size Limit ++++++++++++++++++ This setting controls how calculation history is stored for the active session. It is available from :menuselection:`Session --> History Size Limit...`. Calculation history in ordinary sessions is saved automatically when a session changes and restored on the next launch. Private sessions keep history only while they are open. The history size limit sets the maximum number of stored history entries for that session. By default, SpeedCrunch keeps up to 1000 entries per session and automatically removes the oldest ones when this limit is exceeded. When a calculation fills the last available history slot, SpeedCrunch warns that future calculations will remove the oldest calculation from that session. Set the value to ``0`` to disable the limit for the active session. .. versionadded:: 1.0 Window ++++++ This section contains settings that control the main window behavior. * :menuselection:`Open a Private Tab on Startup` Open and focus a fresh private tab after restoring saved sessions. If there are no sessions to restore, or the active session is an empty ``Untitled-XXX`` tab, start without an extra ordinary tab. This option is off by default. * :menuselection:`Save Window Position on Exit` Controls if the window position is saved and restored. * :menuselection:`Always on Top` Keep the SpeedCrunch window on top of other windows. This option is hidden on Wayland (non-X11 Linux desktop sessions), because many Wayland compositors do not honor it reliably. It remains available on Windows, macOS, and Linux X11 sessions. Results +++++++ This section contains settings that control result output and post-evaluation behavior. * :menuselection:`Show Live Result Preview` If set, SpeedCrunch will display partial results as you type your expression as well as results when selecting a partial expression in the editor. * :menuselection:`Notation & Precision...` Open a tabular layout with one mandatory ``Main Line`` row and four optional extra result-line rows. Each row has columns for enabling the line, notation, and decimal places. Extra lines are ignored unless their row is enabled. Applying changes from this dialog updates only the current editor previews immediately (live/selection) without rewriting already displayed calculation history. * :menuselection:`Remove Trailing Zeroes` Hide trailing fractional zeroes after rounding to the selected decimal places. For example, at three decimal places, ``3.140`` becomes ``3.14`` and ``12.000`` becomes ``12``. This option is off by default and applies to the main and extra result lines. Changing it refreshes editor previews without rewriting displayed history. .. versionadded:: 1.1 * :menuselection:`Rounding Mode` Choose how displayed results are rounded when formatting to a finite number of digits. The default is :menuselection:`Nearest, Half Away (round)`. Available modes are: :menuselection:`Nearest, Half Away (round)`, :menuselection:`Nearest, Half Even (roundeven)`, :menuselection:`Toward Zero (trunc)`, :menuselection:`Toward +∞ (ceil)`, :menuselection:`Toward −∞ (floor)`. * :menuselection:`Nearest, Half Away (round)` Round to nearest; ties increase magnitude. This matches the :func:`round` function. Example at 1 fractional digit: ``2.250 -> 2.3``, ``-2.250 -> -2.3``. * :menuselection:`Nearest, Half Even (roundeven)` Round to nearest; ties go to the nearest even last kept digit. This is Banker's rounding and matches the :func:`roundeven` function. Example at 1 fractional digit: ``2.250 -> 2.2``, ``2.350 -> 2.4``, ``-2.250 -> -2.2``. * :menuselection:`Toward Zero (trunc)` Discard extra digits without rounding up. This matches the :func:`trunc` function. Example at 1 fractional digit: ``2.290 -> 2.2``, ``-2.290 -> -2.2``. * :menuselection:`Toward +∞ (ceil)` Always round upward. This matches the :func:`ceil` function. Example at 1 fractional digit: ``2.210 -> 2.3``, ``-2.210 -> -2.2``. * :menuselection:`Toward −∞ (floor)` Always round downward. This matches the :func:`floor` function. Example at 1 fractional digit: ``2.290 -> 2.2``, ``-2.210 -> -2.3``. This setting affects result formatting (including live previews), not the numeric value of expressions. Use the named function in parentheses when a calculation must apply the same rounding strategy explicitly. Like other result-format settings, changes apply to subsequent calculations and previews; already stored history entries keep their original display. * :menuselection:`Complex Form` and :menuselection:`Imaginary Unit` Configure the complex result form and imaginary unit. See :ref:`complex_numbers`. * :menuselection:`Unit Notation` Configure whether unit results use exponential notation, such as ``m·sâ�»Â¹``, or fractional notation, such as ``m/s``. * :menuselection:`Copy New Results Automatically` Automatically copy each newly evaluated result to the clipboard. * :menuselection:`Simplify Displayed Expressions` When enabled (default), SpeedCrunch adds an extra symbolic line before numeric results, simplifying the interpreted expression for readability (for example, combining repeated factors into powers and folding simple constant terms). This interpreted line also makes implicit-multiplication association explicit. Disable this option to keep only the unsimplified interpreted expression and numeric results. An extra line appears only when there is a useful reduction. For example, ``ans / 9`` stays as written instead of becoming ``1 / 9 · ans``. Entering the expression ``2.1 − 1 cos(pi)^2 cos(pi) 5 cos pi / −cos^2(pi) + 3.4`` gives the following interpretation and simplification: .. code-block:: text 2.1â�Ÿâˆ’â�Ÿ1â�Ÿâ‹…â�Ÿcos²(Ï€)â�Ÿâ‹…â�Ÿcos(Ï€)â�Ÿâ‹…â�Ÿ5â�Ÿâ‹…â�Ÿcos(Ï€)â�Ÿ/â�Ÿ(−cos²(Ï€))â�Ÿ+â�Ÿ3.4 = 5â�Ÿâ‹…â�Ÿcos²(Ï€)â�Ÿ+â�Ÿ5.5 = 10.5 .. versionadded:: 1.0 Editing +++++++ * :menuselection:`Automatic Input Adjustments` Automatically replace operators, adjust spacing, insert closing brackets, convert powers to superscripts, and restrict input to valid characters. Turn it off to keep typed and pasted characters as entered. Tab still accepts the selected completion. Digit grouping and automatic insertion of ``ans`` follow their own settings. Pasting several lines evaluates each expression as usual. Invalid expressions can be entered, but still report an error when evaluated. This option is enabled by default. Changes apply immediately to all open editors and are saved between launches. Switching modes leaves existing text unchanged. .. versionadded:: 1.1 .. _automatic_result_reuse: * :menuselection:`Auto-Insert ans` If a new expression starts with ``+``, ``-``, ``*``, or ``/``, SpeedCrunch inserts ``ans`` first. * :menuselection:`Group Digits in Input` Group digits as you type, using the separator and grouping pattern selected in :menuselection:`Settings --> Number Format...`. For example, ``1000`` appears as ``1 000`` with a space grouping format or ``1,000`` with a comma grouping format. This option is enabled by default. A number format with no grouping adds no separators. Integer digits are grouped in threes for decimal and octal numbers, or in fours for binary and hexadecimal numbers. The Indian format uses 3-2-2 grouping. Fractional digits are grouped only when the selected format includes fractional grouping. Scientific exponents are left unchanged. The separators only affect how the input looks, so copying the expression keeps the original text. This setting works even when syntax highlighting is disabled. .. versionadded:: 1.1 * :menuselection:`Blinking Cursor` Make the cursor blink in the expression editor. This option is enabled by default. Turn it off for a steady cursor. Changes apply immediately to all open session panes and windows, and the choice is saved between launches. .. versionadded:: 1.1 * :menuselection:`Escape Clears Editor` Press :kbd:`Escape` to clear the focused expression editor. If a popup or result preview is open, Escape dismisses it first. Press Escape again to clear the expression. Cancelling a history edit still works as usual. This option is off by default and is saved between launches. Changes apply to all session panes and windows. .. versionadded:: 1.1 * :menuselection:`Keep Expression After Evaluation` If selected, the entered expression remains in the editor after evaluating it. * :menuselection:`Autocomplete` Controls how suggestions are accepted and which names appear in editor autocompletion. * ``Accept with Enter`` lets :kbd:`Enter` insert the current suggestion without first selecting it with the arrow keys. It is off by default. When no autocomplete popup is open, Enter still evaluates the expression. Tab always accepts the current suggestion. The setting is saved between launches and applies to all session panes and windows. .. versionadded:: 1.1 The following suggestion categories are all enabled by default: * ``Built-in functions`` includes built-in function names. * ``Built-in variables`` includes built-in constant names. * ``Units`` includes spelled-out unit names (for example, ``meter``). * ``User functions`` includes user-defined function names. * ``User variables`` includes user-defined variable names. The autocomplete popup also shows category icons for suggestions. .. versionadded:: 1.0 * :menuselection:`Up/Down Arrow History` Controls whether :kbd:`Up` and :kbd:`Down` in the editor navigate history: * ``Never`` always moves the cursor inside the editor. * ``Always`` (default) always navigates history. * ``Only for Single-Line Expressions`` navigates history only when the expression fits in one visual line; otherwise, it moves the cursor. .. versionadded:: 1.0 User Interface Settings +++++++++++++++++++++++ * :menuselection:`Settings --> Appearance --> Theme...` Open the theme dialog. Themes are listed in :guilabel:`Light Themes` and :guilabel:`Dark Themes` groups. Selecting a theme updates the preview immediately. When no saved theme preference exists, as on first launch, SpeedCrunch uses the *Duskfox* theme. The :guilabel:`Preview` area shows representative result-display and editor content so that syntax-highlighting, result, and background colors are visible while editing. The selected ``background`` color generates nearby OKLCH surface colors for the expression editor and surrounding application chrome, followed by progressively offset surface colors for dock titles, dock controls and table headers, dock search and content areas, pane splitters, and scrollbars. It also generates the primary/accent color unless the theme specifies a ``primary`` color. Text on generated surfaces, including docks and popups, targets a contrast ratio of at least 10:1 against its own background. SpeedCrunch keeps a tint from the theme where possible. If a surface cannot reach that ratio, it uses black or white, whichever gives better contrast. The :guilabel:`Colors` area provides per-role color selection buttons showing both the ``#RRGGBB`` value and the actual color. Changing any color creates a custom theme based on the current selection. The dialog also includes: * :guilabel:`Import...` to copy a theme JSON file into SpeedCrunch's user theme directory and refresh the theme lists; * :guilabel:`Export...` to save the current theme as JSON in the same user theme directory. Import and export refuse theme names that collide with built-in themes. Import asks for confirmation before overwriting an existing custom theme. SpeedCrunch also supports loading additional theme files from the following directory: * Windows: :file:`C:/Users//AppData/Roaming/SpeedCrunch/color-schemes/` * Linux/Unix: :file:`~/.local/share/SpeedCrunch/color-schemes/` * Linux (Flatpak): :file:`~/.var/app/org.speedcrunch.SpeedCrunch/data/SpeedCrunch/color-schemes/` * OS X: :file:`~/Library/Application Support/SpeedCrunch/color-schemes/` * Portable version (any OS): :file:`color-schemes` subdirectory in the application directory. Theme files use JSON and map role names to color values. Supported role names are: ``number``, ``parens``, ``list``, ``unit``, ``result``, ``comment``, ``function``, ``operator``, ``variable``, ``separator``, ``background``, and optional ``primary``. The editor surface and scrollbar colors are generated from ``background``. For the full schema, see :doc:`theme_json_schema`. .. versionadded:: 1.0 The :menuselection:`Theme...` dialog, including live preview and JSON import/export. * :menuselection:`Settings --> Appearance --> Menus` Choose how menus look: * :guilabel:`System` uses the system's menu colors and styling, including highlighted and disabled items. Menus follow changes to the system theme while SpeedCrunch is running. * :guilabel:`SpeedCrunch Theme` (the default) uses the selected SpeedCrunch theme for menu backgrounds and text, including highlighted items. Menu icons also follow the theme's text colors. In popup menus, disabled labels, shortcut hints, and icons appear dimmed. This setting applies to the menu bar shown inside the application window, dropdown menus, context menus, and dropdown lists in attached and floating docks that use the SpeedCrunch theme. Closed dropdown controls follow the :menuselection:`Docks` setting. The macOS system menu bar keeps its native appearance. Popup menus drawn by Qt can look slightly different from native macOS menus. On GNOME, popup menus use the GTK theme's popup hover colors when GTK is available. Otherwise they use Qt's system palette. The choice applies to all SpeedCrunch windows and is saved between launches. Selections in the expression editor and result display use the SpeedCrunch theme. Dock list selections follow the :menuselection:`Docks` setting. * :menuselection:`Settings --> Appearance --> Docks` Choose how attached and floating docks look, including their title bars: * :guilabel:`System` uses the system's colors and widget styles for lists, search fields, dropdown controls, scrollbars, dock title bars, and the tabs used to switch between overlapping docks. Close and float buttons use the system style. Dropdown lists also use the system appearance, regardless of the :menuselection:`Menus` choice. The Formula Book and bitfield use system colors as well. Formula and navigation links use the system link color directly. On bits use the system selection colors, with a separate hover color for off bits. * :guilabel:`SpeedCrunch Theme` (the default) uses the selected SpeedCrunch theme for dock content, title bars, and tabs, including list selections and search fields. The choice applies immediately to all SpeedCrunch windows and is saved between launches. System colors follow changes to the system theme while SpeedCrunch is running. .. versionadded:: 1.1 * :menuselection:`Settings --> Appearance --> Status Bar` Choose how the status bar looks: * :guilabel:`System` uses the system's palette and widget styles for the status bar, its labels, and its buttons. Colors follow changes to the system theme while SpeedCrunch is running. * :guilabel:`SpeedCrunch Theme` (the default) uses the selected SpeedCrunch theme for the status bar background and text. The choice applies immediately to all SpeedCrunch windows and is saved between launches. Popup menus follow the :menuselection:`Menus` setting. Show or hide the status bar with :menuselection:`View --> Status Bar`. .. versionadded:: 1.1 * :menuselection:`Settings --> Appearance --> Input and Results` Choose the layout of the expression editor and result display: * :guilabel:`Modern` (the default) uses a rounded input box with compact padding and a small gap around it. History aligns with the left edge of the box. * :guilabel:`Classic` uses a compact, full-width editor directly below the results and a small history gutter. All editors use the Modern input background color across the whole input area. Text and editor popups share a small inset from the edge, with enough space below the input for rounded window corners. A top line marks the active pane, using the same thickness and accent color as the Modern outline. This line is hidden when there is only one window and one pane, regardless of how many session tabs it contains. Vertical pane dividers remain visible through the input area. Both styles keep the same editing features, including input that grows as expressions wrap. The input grows to five visible lines, then scrolls to keep the cursor in view. Line spacing follows the selected font. The choice applies immediately to every window and pane and is saved between launches. .. versionadded:: 1.1 * :menuselection:`Settings --> Appearance --> Input and Results --> Font...` Select the font to use for the expression editor and result display. On macOS 27 and later, SpeedCrunch uses Qt's font dialog. * :menuselection:`Settings --> Appearance --> Keypad` Choose the shape and spacing of the keypad buttons: * :guilabel:`Classic` uses shallow rectangular buttons with smaller gaps, similar to the keypad in SpeedCrunch 0.12. * :guilabel:`Modern` (the default) keeps the larger square buttons. The choice applies immediately to all windows and is saved between launches. It works with every preset and custom keypad. Each window keeps its own layout, selected from :menuselection:`View --> Keypad`, and zoom level, selected from :menuselection:`Settings --> Appearance --> Keypad --> Zoom`. .. versionadded:: 1.1 * :menuselection:`Settings --> Appearance --> Syntax Highlighting` Enable or disable syntax highlighting. * :menuselection:`Settings --> Appearance --> Hover Highlighting` Enable or disable hover highlighting. * :menuselection:`Settings --> Language` Select the user interface language. Help ---- * :menuselection:`Help --> App Diagnostics` Show system information and app settings. Use :guilabel:`Copy to Clipboard` to share the report when reporting a problem. * :menuselection:`Help --> About SpeedCrunch` Show the SpeedCrunch version, the operating system and its version, and the Qt version. Portable builds display ``Portable`` next to the SpeedCrunch version. * :menuselection:`Help --> Check for Updates` Trigger an update check and show information when a newer version is available. Update checks are enabled in official SpeedCrunch builds. Other distributors can choose whether to enable them. When enabled, this menu entry is available and SpeedCrunch also checks for updates after the window first paints, at most once every 24 hours. Each network request has a five-second deadline, including redirects. Receiving data does not extend that deadline. Oversized update responses are rejected before their contents are parsed or saved. Closing a window requests that its update worker stop. Cleanup finishes in the background, without making the window wait for network setup. See :file:`BUILDING.md` at the repository root for build options and package provider guidance. .. versionadded:: 1.0 Keyboard Shortcuts ------------------ Editing +++++++ * :kbd:`Ctrl+O` Open session. * :kbd:`Ctrl+Q` Quit SpeedCrunch (:kbd:`Cmd+Q` on macOS). * :kbd:`Ctrl+N` Create a new session in the current session pane. * :kbd:`Ctrl+T` (:kbd:`Cmd+T` on macOS) Create a new session tab in the current session pane. * :kbd:`Ctrl+Shift+N` (:kbd:`Cmd+Shift+N` on macOS) Create a new private tab in the current session pane. * :kbd:`Ctrl+Shift+T` (:kbd:`Cmd+Shift+T` on macOS) Reopen the most recently closed session tab. * :kbd:`Ctrl+W` (:kbd:`Cmd+W` on macOS) Close the active session tab. * :kbd:`Ctrl+C` Copy selected text to clipboard. * :kbd:`Ctrl+R` Copy last result to clipboard. * :kbd:`Ctrl+V` Paste from clipboard. * :kbd:`Ctrl+A` Select entire expression. * :kbd:`Ctrl+(` or :kbd:`Ctrl+)` Wrap the current selection in parentheses. If no text is selected, the entire expression is wrapped. Session Tabs ++++++++++++ * :kbd:`Cmd+Alt+Left` and :kbd:`Cmd+Alt+Right` (macOS) Move to the previous or next session tab or pane. * :kbd:`Ctrl+Page Up` and :kbd:`Ctrl+Page Down` (Windows/Linux) Move to the previous or next session tab or pane. Widgets and Docks +++++++++++++++++ * :kbd:`Ctrl+1` Show/hide formula book. * :kbd:`Ctrl+2` Show/hide constants widget. * :kbd:`Ctrl+3` Show/hide functions widgets. * :kbd:`Ctrl+4` Show/hide variables widget. * :kbd:`Ctrl+5` Show/hide user functions widget. * :kbd:`Ctrl+6` Show/hide user units widget. * :kbd:`Ctrl+7` Show/hide history widget. * :kbd:`Ctrl+8` Show/hide bit field dock. * :kbd:`Ctrl+B` Show/hide the status bar. The status bar provides quick selectors for :menuselection:`Angle Mode`, :menuselection:`Results --> Notation`, and :menuselection:`Results --> Precision`. On narrow windows, selectors that do not fully fit are hidden automatically. Status bar visibility is set separately for each window; the main menu always shows and changes the setting for the active window. Angle mode, notation, and precision selections are also retained separately for each window. Scrolling +++++++++ * :kbd:`Page Up` and :kbd:`Page Down` Scroll the result window page-wise. * :kbd:`Shift+Page Up` and :kbd:`Shift+Page Down` Scroll the result window line-wise. * :kbd:`Cmd+Page Up` and :kbd:`Cmd+Page Down` (macOS) Scroll to the top or bottom of the result window. Focus Navigation ++++++++++++++++ * :kbd:`F6` and :kbd:`Shift+F6` Move focus forward or backward between the expression editor and visible dock controls. Focus navigation applies to the current window, including its floating docks. Notation ++++++++ * :kbd:`F2` Set result notation to automatic decimal. * :kbd:`F3` Set result notation to fixed-point decimal. * :kbd:`F4` Set result notation to engineering decimal. * :kbd:`F5` Set result notation to scientific decimal. * :kbd:`F7` Set result notation to octal. * :kbd:`F8` Set result notation to hexadecimal. * :kbd:`F9` Set result notation to sexagesimal. * :kbd:`F10` Set result notation to binary. .. versionadded:: 1.0 Various +++++++ * :kbd:`F1` Show context help (dismiss with :kbd:`Escape`). .. versionadded:: 0.12 * :kbd:`F11` Toggle full screen. * :kbd:`Ctrl` + mouse wheel, :kbd:`Shift` + mouse wheel, or :kbd:`Shift+Up` and :kbd:`Shift+Down` Change the font size. * :kbd:`Ctrl+Shift` + mouse wheel Change the window opacity. .. versionadded:: 0.12 .. rubric:: Footnotes .. [#f1] Starting with SpeedCrunch 0.12, the session format is based on `JSON `_. Previous versions used a simple custom text format. .. _json: http://json.org/ heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/session_json_schema.rst000066400000000000000000000216511526573132500274600ustar00rootroot00000000000000.. meta:: :description: Understand the SpeedCrunch session JSON schema for calculation history, variables, user functions, custom units and startup definitions. Session JSON Schema =================== SpeedCrunch session files are JSON objects with stored calculation history, session-local variables, user functions, user units, and global user-definition startup lines. Session files include a schema identifier so JSON editors and SpeedCrunch can associate them with the current SpeedCrunch session format. Schema ------ .. code-block:: json { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/session-v1.schema.json", "title": "SpeedCrunch Session", "type": "object", "required": [ "$schema", "$id", "session", "limit", "history", "variables", "functions", "units", "globals" ], "additionalProperties": false, "properties": { "$schema": { "const": "https://json-schema.org/draft/2020-12/schema", "description": "JSON Schema dialect identifier" }, "$id": { "const": "https://speedcrunch.org/schemas/session-v1.schema.json", "description": "Session schema identifier" }, "session": { "type": "string", "minLength": 1 }, "limit": { "type": "integer", "minimum": 0, "description": "Maximum stored history entries for this session; 0 means unlimited." }, "history": { "type": "array", "items": { "$ref": "#/$defs/historyEntry" } }, "variables": { "type": "array", "items": { "$ref": "#/$defs/variable" } }, "functions": { "type": "array", "items": { "$ref": "#/$defs/userFunction" } }, "units": { "type": "array", "items": { "$ref": "#/$defs/userUnit" } }, "globals": { "type": "array", "items": { "type": "string" } } }, "$defs": { "historyEntry": { "type": "object", "required": [ "xpr", "itp", "rst", "ctx", "edt" ], "additionalProperties": false, "properties": { "xpr": { "type": "string" }, "itp": { "type": "string" }, "rst": { "$ref": "#/$defs/quantity" }, "ctx": { "$ref": "#/$defs/evaluationContext" }, "edt": { "type": "integer" }, "prt": { "type": "array", "items": { "type": "string" } } } }, "evaluationContext": { "type": "object", "required": [ "lns", "cpx", "ang", "uxp", "rnd" ], "additionalProperties": false, "properties": { "lns": { "type": "object", "required": [ "main", "ext" ], "additionalProperties": false, "properties": { "main": { "$ref": "#/$defs/resultLineContext" }, "ext": { "type": "array", "maxItems": 4, "items": { "$ref": "#/$defs/resultLineContext" } } } }, "cpx": { "type": "string", "enum": [ "off", "i", "j" ] }, "ang": { "type": "string", "minLength": 1, "maxLength": 1 }, "uxp": { "type": "string", "minLength": 1, "maxLength": 1 }, "rnd": { "type": "string", "minLength": 1, "maxLength": 1 } } }, "resultLineContext": { "type": "object", "required": [ "ntn", "prc", "cpx" ], "additionalProperties": false, "properties": { "ntn": { "type": "string", "minLength": 1, "maxLength": 1 }, "prc": { "type": "integer" }, "cpx": { "type": "string", "minLength": 1, "maxLength": 1 } } }, "variable": { "type": "object", "required": [ "id", "qty" ], "additionalProperties": false, "properties": { "id": { "type": "string" }, "qty": { "$ref": "#/$defs/quantity" }, "dsc": { "type": "string" }, "fmt": { "type": "string" } } }, "userFunction": { "type": "object", "required": [ "id", "args", "xpr" ], "additionalProperties": false, "properties": { "id": { "type": "string" }, "args": { "type": "array", "items": { "type": "string" } }, "xpr": { "type": "string" }, "itp": { "type": "string" }, "dsc": { "type": "string" }, "opcodes": { "type": "array", "items": { "$ref": "#/$defs/opcode" } }, "constants": { "type": "array", "items": { "$ref": "#/$defs/cNumber" } }, "identifiers": { "type": "array", "items": { "type": "string" } } } }, "opcode": { "type": "object", "required": [ "t", "i" ], "additionalProperties": false, "properties": { "t": { "type": "integer" }, "i": { "type": "integer" }, "text": { "type": "string" } } }, "userUnit": { "type": "object", "required": [ "id", "qty" ], "additionalProperties": false, "properties": { "id": { "type": "string" }, "qty": { "$ref": "#/$defs/quantity" }, "xpr": { "type": "string" }, "itp": { "type": "string" }, "dsc": { "type": "string" } } }, "quantity": { "type": "object", "required": [ "val" ], "additionalProperties": true, "properties": { "val": { "type": "string" }, "dim": { "type": "object", "additionalProperties": { "type": "string" } }, "unit": { "type": "object", "additionalProperties": true }, "unit_name": { "type": "string" }, "format": { "type": "object", "additionalProperties": true } } }, "cNumber": { "type": "object", "required": [ "value" ], "additionalProperties": true, "properties": { "value": { "type": "string" } } } } } Notes ----- * ``$schema`` identifies the JSON Schema draft used by the session metadata. SpeedCrunch session files use ``https://json-schema.org/draft/2020-12/schema``. * ``$id`` identifies the SpeedCrunch JSON Schema for the session format: ``https://speedcrunch.org/schemas/session-v1.schema.json``. * ``session`` stores the session name. Empty names are normalized to ``main`` by SpeedCrunch. * ``limit`` stores the calculation history limit for the session. A value of ``0`` means unlimited history. * ``history`` stores saved calculations. The compact field names preserve the existing session file format: for example ``xpr`` is the expression, ``rst`` is the result quantity, and ``ctx`` is the evaluation context. * ``variables``, ``functions``, and ``units`` store session-local user definitions. Definitions from global startup user definitions are stored in ``globals`` instead. heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/syntax.rst000066400000000000000000000671571526573132500247650ustar00rootroot00000000000000.. meta:: :description: Learn SpeedCrunch expression syntax, number notation, arithmetic operators, complex numbers and unit conversions, with worked calculation examples. Syntax ====== This part of the documentation explains the syntax of valid SpeedCrunch input. As you will see, SpeedCrunch honors most conventions for mathematical expressions. You will find using SpeedCrunch to be very natural and intuitive, especially so if you are already familiar with a programming language. Number Notation --------------- Decimal Form ++++++++++++ When you would like to specify a non-integer value, simply enter the number as you would write it on paper, with either a period (``.``) or a comma (``,``) as the decimal separator. Accepted decimal separator and grouping conventions depend on the selected :ref:`Number Format `. Trailing zeros after the decimal point (like in ``12.300``) or leading zeros before it (``0012.3``) are redundant and can be included or omitted to the user's preference. Expressions like ``.5`` as a shorthand notation for ``0.5`` are also permitted. .. _digit_grouping_separators: Digit Grouping Separators +++++++++++++++++++++++++ To improve readability, SpeedCrunch accepts grouping separators inside number literals. Grouping separators are optional and ignored during evaluation. Allowed grouping separators are characters that are **not** letters or digits and are **not** number operators. In practice, this includes many punctuation and symbol characters, for example: * ``_`` (underscore): ``12_345_678`` * Space (U+0020): ``12 345 678`` * Currency symbols: ``$12,345``, ``€12 345``, ``12Â¥345`` Not allowed as grouping separators: * Letters from any language (for example ``天``, ``é``, ``Ж``) * Digits from any language * Radix characters (``.`` or ``,`` depending on settings) when they are used as decimal separators * Operator characters and other reserved syntax tokens Some characters cannot be used for digit grouping because they already have an assigned meaning in expressions: * ``#`` starts hexadecimal number notation (for example ``#FF``). * ``!`` is the factorial operator (for example ``5!``). * ``:`` is used in sexagesimal time/angle notation (for example ``12:34:56``). * ``°`` is used in sexagesimal angle notation (for example ``12°34'56``). * ``′`` is used in sexagesimal angle notation (for example ``12°34′56″``). * ``&`` is the bitwise AND operator (for example ``6 & 3``). * ``?`` starts a comment (for example ``1+2 ? note``). Examples: * ``12$345.678$9`` evaluates as ``12345.6789`` * ``12天2`` is rejected (it is **not** treated as ``122``) .. _scientific_notation: Scientific Notation +++++++++++++++++++ When dealing with very small or very large numbers (think the size of an atom or of a galaxy) the notation above is inconvenient. These are more commonly expressed in scientific notation; for instance, 1.234*10\ :sup:`-9` is preferable to 0.000000001234. Naturally, in SpeedCrunch this could be written as ``1.234*10^-9``, but there's also a shorthand notation: ``1.234e-9``. Here, the ``e`` represents ``*10^``, but it is considered a part of the number literal and treated with higher precedence. For example, ``1e2^3`` is equivalent to ``(1e2)^3 = 100^3``. The scale of a number (sometimes called its exponent) always begins with the scale character ``E`` or ``e`` followed by a signed integer. So ``e+10``, ``e-4``, ``E-0`` are all valid scale expressions. If the sign is '+', you may simply omit it: ``e0``, ``E10``. The significand (i.e. the part preceding the exponent) is required; exactly one exponent must be specified. Equivalent examples:: 98e3 98*10^3 98x10³ Compared to most calculators, SpeedCrunch can accept very large numbers without overflowing (e.g. both ``1e+536870911`` and ``1e-536870911`` are still valid). However, only about 78 significant digits are stored at any point. Any digits beyond that are lost. Non-Decimal Bases +++++++++++++++++ In addition to decimal (base-10) numbers, SpeedCrunch provides support for binary (base-2), octal (base-8) and hexadecimal (base-16) numbers. You can enter a number in any of these bases by marking it with the corresponding prefix: * ``0b`` or ``0B`` for **binary**, e.g. ``0b10010``. * ``0o`` or ``0O`` for **octal**, e.g. ``0o1412``. * ``0d`` or ``0D`` for **decimal**. These can be omitted since decimal is the default base. * ``0x``, ``0X``, or ``#`` for **hexadecimal**. The additional six digits are represented by the upper or lower case letters ``a`` to ``f``, e.g. ``0xdeadbeef`` or ``0xDEADBEEF``. You may even enter fractional values in any of these bases. Note that scientific notation is not supported for non-decimal bases, however. Examples:: 0b1.01 = 1.25 0xf.a = 15.625 To have SpeedCrunch output its results in a base other than decimal, you may use one of the functions :func:`bin`, :func:`oct`, :func:`dec`, or :func:`hex`:: hex(12341) = 0x3035 The effect of these functions only applies to the immediate result and doesn't carry to future operations:: 0x2 * hex(12341) = 24682 The same applies to :func:`sci` and :func:`eng`: they only affect the formatted display of the immediate value, not the numeric value used in later arithmetic. In particular, operand order does not matter:: 1 + sci(123456.789) = 123457.789 sci(123456.789) + 1 = 123457.789 For explicit decimal exponent notations, use :func:`sci` (scientific notation) or :func:`eng` (engineering notation):: sci(12341) = 1.2341e4 eng(12341) = 12.341e3 To force the exponent used by :func:`eng`, pass an optional second argument. It accepts either a direct exponent that is a multiple of 3, or a matching power of ten (including SI prefixes):: eng(0.000123456; [milli]) = 0.123456e-3 eng(0.000123456; -4) = 1.23456e-4 For assembly-style fixed-width formatting, use :func:`binpad`, :func:`octpad`, or :func:`hexpad`. These functions only accept real, dimensionless integer arguments and also only affect the immediate result:: hexpad(15) = 0x0F binpad(1536; 32) = 0b00000000000000000000011000000000 To change the base that is used for displaying results, select one of the corresponding settings in :menuselection:`Settings --> Results --> Notation`. This affects only subsequent calculations/results; existing history entries are not rewritten. SpeedCrunch stores integers with a precision of up to 256 bits. Since this would be unwieldy, the binary representation of a negative number in SpeedCrunch is *not* its two's complement. Instead, like with other bases, the value and the sign are represented separately:: bin(-1) = -0b1 See :func:`mask` and :func:`unmask` to convert a negative number into the two's complement form. Any integer larger than the 256-bit limit will be silently converted into a floating point number, making it susceptible to rounding errors. To specify large integers, using the shift operators (``1 << n``) is preferable to exponentiation (``2 ^ n``) as the latter are floating point calculations and thus susceptible to rounding errors. .. _sexagesimal_values: Sexagesimal Values ++++++++++++++++++ .. versionadded:: 1.0 Sexagesimal values in SpeedCrunch are angle degrees or time values represented with minutes and seconds. When sexagesimal mode is selected in :menuselection:`Settings --> Results --> Notation`, dimensionless and time results are displayed as sexagesimal values. All other results are displayed as fixed-point decimal values. Actual sexagesimal math depends on the result. Dimensionless results are handled as degrees with minutes and seconds generated from the decimal part. With time dimension results, base unit is second and the integer part is divided to minutes and hours. In input, characters ``°`` (degree), ``:`` (colon), ``′`` (prime) and ``″`` (double prime) can be used for entering sexagesimal values. Degree sign ``°`` separates degrees and minutes. First colon character ``:`` separates hours and minutes. Prime ``′`` or second colon character ``:`` separates minutes and seconds. Additionally, postfix double prime ``″`` can be used as an arc second unit. ASCII single quote ``'`` and double quote ``"`` are accepted as aliases and are normalized to ``′`` and ``″`` on editor insertion/paste. Because the degree sign is difficult to produce from keyboard, at sign ``@`` is automatically converted to it. Amount of minutes or seconds is not limited to values below 60. It is possible to input time 90 minutes after noon:: 12:90 = 13:30:00 Dimensionless input values are automatically considered to be in current angle mode. For example, in radian mode:: pi = 180°00'00 For trigonometric input, explicit angle units override angle mode. For example, ``cos(pi*[rad])``, ``cos(180*[deg])``, ``cos(200*[gon])`` and ``cos(0.5*[turn])`` all evaluate to ``-1`` regardless of the global angle mode. The aliases ``deg`` for ``degree``, ``gon`` for ``gradian``, and ``rev`` for ``revolution`` are supported. ``revolution`` is equivalent to ``turn`` (that is, ``2*pi`` radians). ``deg`` is normalized to ``°`` in autocomplete insertion and displayed result units. Only last part of sexagesimal input value can contain decimals. Following tables show some possible input notations and their results in both fixed-point decimal and sexagesimal modes. Sexagesimal round-trips (for example arcsecond → DMS → radians) are designed to keep precision drift negligible. In the first table, fixed-point decimal values assume angle mode is set to degrees: .. list-table:: :header-rows: 1 * - Input - Fixed-Point Decimal - Sexagesimal * - ``0`` - ``0`` - ``0°00'00`` * - ``°'56`` - ``0.01555556`` - ``0°00'56.00`` * - ``56"`` - ``0.01555556`` - ``0°00'56.00`` * - ``56[arcsec]`` - ``0.01555556`` - ``0°00'56.00`` * - ``56.78"`` - ``0.01577222`` - ``0°00'56.78`` * - ``°34`` - ``0.56666667`` - ``0°34'00.00`` * - ``34'`` - ``0.56666667`` - ``0°34'00.00`` * - ``34[arcmin]`` - ``0.56666667`` - ``0°34'00.00`` * - ``34'56`` - ``0.58222222`` - ``0°34'56.00`` * - ``12°`` - ``12.00000000`` - ``12°00'00.00`` * - ``12°34`` - ``12.56666667`` - ``12°34'00.00`` * - ``12°34.5`` - ``12.57500000`` - ``12°34'30.00`` * - ``12°34'56`` - ``12.58222222`` - ``12°34'56.00`` * - ``12°34'56.78`` - ``12.58243889`` - ``12°34'56.78`` Use canonical symbols ``′`` and ``″`` (insertable with ``'`` and ``"``), or the aliases ``arcmin`` and ``arcsec``. Full names ``arcminute`` and ``arcsecond`` are also accepted. .. list-table:: :header-rows: 1 * - Input - Fixed-Point Decimal - Sexagesimal * - ``0[s]`` - ``0 [s]`` - ``0:00:00`` * - ``::56`` - ``56.00 [s]`` - ``0:00:56.00`` * - ``56[s]`` - ``56.00 [s]`` - ``0:00:56.00`` * - ``:34`` - ``2040.00 [s]`` - ``0:34:00.00`` * - ``34[min]`` - ``2040.00 [s]`` - ``0:34:00.00`` * - ``12:`` - ``43200.00 [s]`` - ``12:00:00.00`` * - ``12[h]`` - ``43200.00 [s]`` - ``12:00:00.00`` * - ``12:34`` - ``45240.00 [s]`` - ``12:34:00.00`` * - ``12:34.5`` - ``45270.00 [s]`` - ``12:34:30.00`` * - ``12:34:56`` - ``45296.00 [s]`` - ``12:34:56.00`` * - ``12:34:56.78`` - ``45296.78 [s]`` - ``12:34:56.78`` Note that when entering time values with colons, no additional dimension units are needed. Formatting itself works as an unit. Comments -------- The question mark character ``?`` starts a comment. Everything from ``?`` to the end of the line is ignored by the evaluator:: 1 + 2 ? simple sum = 3 Comment text is kept as written, including in the result window and when editing user definitions. For example, ``examplevar = 4 ? 2*2`` keeps ``2*2`` in the Description column of the User Variables dock, without changing it to ``2×2``. The same rule applies to user functions and user units. A line can also be comment-only. If the first non-space character is ``?``, the whole line is treated as a comment:: ? start algorithm ? this is also a comment-only line Operators and Precedence ------------------------ When writing an expression like ``10+5*4``, which operation will be executed first? The common rules of operator precedence tell us that in this case multipication shall be computed first, hence the result is ``30``. We also distinguish **unary** operators (which act on a single number/operand) and **binary** operators (which link two operands). SpeedCrunch supports the following operators, listed in order of decreasing precedence: .. Note: When making changes to these tables, also check that they look ok with LaTeX; these big .. tables can be problematic. .. tabularcolumns:: |p{0.2\linewidth}|p{0.5\linewidth}|p{0.25\linewidth}| +-------------------------------+---------------------------------------------------------------+-------------------------+ | Operator | Description | Examples | +===============================+===============================================================+=========================+ | ``(...)`` | **Parentheses** | ``(2+3)*4 = 5*4 = 20`` | | | Parentheses mark precedence | | | | explicitly. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``x!`` | **Factorial** | ``5! = 120`` | | | Computes the factorial of its | | | | argument. See also :func:`gamma()`. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``x%`` | **Percent** | ``50% = 0.5`` | | | Postfix operator equivalent to | ``1000+12% = 1120`` | | | division by 100. | ``1000-12% = 880`` | | | In ``a+b%`` and ``a-b%``, the percentage | ``1000*12% = 120`` | | | is applied relative to the | ``1000/25% = 4000`` | | | entire left operand ``a`` (after normal precedence). | ``1+2+3+10% = 6.6`` | | | So ``1+(2+3)+10%`` is interpreted as | ``1+(2+3)+10% = 6.6`` | | | ``(1+(2+3))+10%``. | | | | | | | | .. versionadded:: 1.0 | | | | Contextual percent semantics. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``a ^ b``, ``a ** b``, ``a²`` | **Exponentiation** | | | | ``a²`` is shorthand for ``a^2``; | ``3²â�° = 3^20`` | | | ``**`` is equivalent to ``^`` and can be | ``2**10 = 1024`` | | | used as an easy way to insert powers. | | | | contiguous superscript digits are | ``2¹â�° = 1024`` | | | parsed as one integer exponent. Both | | | | function notations ``f^n(x)`` and ``fâ�¿(x)`` | ``cos^2(pi)=cos²(pi)`` | | | are interpreted identically. | | | | text-operator variants are equivalent. Note | | | | that the power operation is | | | | *right-associative*, i.e. it is | ``2^2^3 = 2^8 = 256`` | | | evaluated from right to left. | | | | Fractional powers return principal | ``(-1)^(1/2) = i`` | | | complex roots for negative bases. | | | | Positive and negative powers can be written | ``10^3``, ``10^-3``, | | | with either ``^`` or ``**``. | ``10**3``, ``10**-3`` | | | | | | | .. versionadded:: 1.0 | | | | Integer superscript powers and ``f^n(x)`` function-power | | | | notation (equivalent to ``fâ�¿(x)``). | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``+x``, ``-x``, ``~x`` | **Unary plus, minus, and bitwise NOT** | ``~5 = -6`` | | | ``~x`` is equivalent to :func:`not(x)`. | ``-~(-1) = -not(-1)`` | | | | | | | .. versionadded:: 1.0 | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``a \ b`` | **Integer division** | ``5\4 = 1`` | | | Divides the operands and truncates | | | | the result to an integer. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``a * b``, ``a × b``, ``a b``,| **Multiplication and division** | ``3 sqrt(2)`` | | ``a / b``, ``a ⧸ b`` | | | | | In many situations, *implicit | | | | multiplication* allows writing | | | | multiplications without the ``*`` | | | | operator. | | | | In the expression editor and Session Import, | | | | these symbols are normalized to ``×``: | | | | ``∗``, ``·``, ``â‹…``, ``∙``, ``*``, | | | | ``⨉``, ``⨯``, ``✕``, ``✖``. | | | | In the expression editor and Session Import, | | | | these symbols are normalized to ``⧸``: | | | | ``/``, ``÷``. | | | | Implicit multiplication has | ``6/2(2+1)=9`` | | | the same precedence as ``*`` and ``/``, | | | | evaluated from left to right. | | | | The result display makes this association explicit by | | | | showing the interpreted expression before the numeric | | | | result. | | | | | | | | .. versionadded:: 0.12 | | | | Implicit multiplication was added | | | | SpeedCrunch 0.12. | | | | | | | | .. versionadded:: 1.0 | | | | Multiplication and division symbol aliases. | | | | Improved explicit interpretation/association in results. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``a + b``, ``a - b`` | **Addition and subtraction** | | | | In the expression editor and Session Import, | | | | ``+`` is normalized to ``+``. | | | | In the expression editor and Session Import, | | | | these symbols are normalized to ``−``: | | | | ``-``, ``ï¼�``, ``ï¹£``, ``â€�``, ``‑``, | | | | ``–``, ``—``, ``―``, ``â�ƒ``. | | | | | | | | .. versionadded:: 1.0 | | | | Addition and subtraction symbol aliases. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``a << n``, ``a >> n`` | **Left/right arithmetic shifts** | ``0b11<<1 = 0b110`` | | | Shifts the first operand left/right | | | | by ``n`` bits. See also :func:`shl` | ``0b100>>2 = 0b1`` | | | and :func:`shr`. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``a & b`` | **Bitwise AND** | ``0b11 & 0b10 = 0b10`` | | | See also :func:`and`. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``a | b`` | **Bitwise OR** | ``0b10 | 0b01 = 0b11`` | | | See also :func:`or`. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ | ``->``, ``in``, ``--`` | **Unit conversion** | ``10[m] in [mi]`` | | | Convert the operand into the given | | | | unit. Both forms are equivalent. See | ``10[m] -> [mi]`` | | | ``--`` is a shortcut equivalent to ``->`` and ``in``. | ``10[m] -- [mi]`` | | | :ref:`units` for more information. | | +-------------------------------+---------------------------------------------------------------+-------------------------+ For negative bases, fractional powers return the principal complex root. Use :func:`cbrt` when you specifically need the real cubic root of a real negative value, or :func:`root` for other odd root indices. Complex Numbers --------------- .. versionadded:: 0.12 SpeedCrunch supports complex-number expressions by default. Enter the imaginary unit as ``i`` or ``j``:: j^2 = -1 (5+3j)/(8-2j) = 0.5+0.5j Syntax note: ``5j`` means ``5*j``, while ``j5`` is a variable named ``j5``. Write ``j*5`` explicitly if needed. The displayed imaginary-unit symbol is configurable in :menuselection:`Settings --> Results --> Imaginary Unit`. The displayed complex form is configurable in :menuselection:`Settings --> Results --> Complex Form`. You can enter complex numbers in phasor notation with ``∠``. The expression ``r ∠ θ`` is interpreted as ``r * cis(θ)``. The phase follows the current angle mode unless it has an explicit angle unit:: 3 ∠ 90° = 3j 3 ∠ 200 [gon] = -3 Not every function accepts complex arguments. Refer to each function entry in the reference. Caution: fractional powers return principal complex roots. For example, ``x^(1/3)`` may be non-real. In contrast, :func:`cbrt` always returns the real cubic root for real inputs. For other root indices, use :func:`root`, for example ``root(5; -32) = -2``. It returns the real root for real inputs whenever one exists. Negative real inputs with an even index return the principal complex root. :const:`i` and :const:`j` are built-in constants for the imaginary unit. heldercorreia-speedcrunch-e7ca37f/doc/src/userguide/theme_json_schema.rst000066400000000000000000000112221526573132500270700ustar00rootroot00000000000000.. meta:: :description: Create and validate SpeedCrunch color themes using the theme JSON schema, supported color roles, metadata and an example theme file. Theme JSON Schema ================= SpeedCrunch theme files are JSON objects with supported color-role keys. Each color-role value is a color string in ``#RRGGBB`` format. Theme files also include required schema metadata and may include optional descriptive and format metadata. Schema ------ .. code-block:: json { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "title": "SpeedCrunch Theme", "description": "Defines the colors used by a SpeedCrunch theme.", "type": "object", "additionalProperties": false, "required": [ "$schema", "$id", "number", "parens", "list", "unit", "result", "comment", "function", "operator", "variable", "separator", "background" ], "properties": { "$schema": { "const": "https://json-schema.org/draft/2020-12/schema", "description": "JSON Schema draft identifier" }, "$id": { "const": "https://speedcrunch.org/schemas/theme-v1.schema.json", "description": "Theme schema identifier" }, "name": { "type": "string", "description": "Optional theme display name" }, "author": { "type": "string", "description": "Optional theme author" }, "homepage": { "type": "string", "description": "Optional theme homepage" }, "version": { "type": "string", "description": "Optional theme version chosen by the theme author" }, "number": { "$ref": "#/$defs/color" }, "parens": { "$ref": "#/$defs/color" }, "list": { "$ref": "#/$defs/color" }, "unit": { "$ref": "#/$defs/color" }, "result": { "$ref": "#/$defs/color" }, "comment": { "$ref": "#/$defs/color" }, "function": { "$ref": "#/$defs/color" }, "operator": { "$ref": "#/$defs/color" }, "variable": { "$ref": "#/$defs/color" }, "separator": { "$ref": "#/$defs/color" }, "background": { "$ref": "#/$defs/color" }, "primary": { "$ref": "#/$defs/color", "description": "Optional primary/accent color override" } }, "$defs": { "color": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$", "description": "Hex color in the form #RRGGBB" } } } Notes ----- * ``parens`` controls highlighting for ``()``. * ``list`` controls highlighting for list/matrix curly braces ``{}`` only. * ``unit`` controls highlighting for square-bracketed unit blocks, including both ``[]`` and everything inside them. * ``background`` also supplies the base color for the generated application chrome, expression-editor surface colors, and successive generated surfaces used by dock titles, controls and headers, and content areas. Scrollbar colors are generated from the background of the surface that owns each scrollbar, so theme files do not include a separate key for them. Text colors for these surfaces target at least 10:1 contrast while keeping the background's hue where possible. If that ratio cannot be reached, SpeedCrunch uses black or white, whichever gives better contrast. * ``primary`` is optional. When present, it overrides the generated primary/accent color used for active selections, focused editor outlines, cursor accents, pane splitters, and primary-hue keypad fills. When omitted, SpeedCrunch generates the primary/accent color from ``background``. * ``name``, ``author``, ``homepage``, and ``version`` are optional metadata fields. ``version`` is a string that belongs to the theme author and is not used as the schema or format version. A non-empty ``name`` is used as the theme display name. Fictitious Example ------------------ The following example is fictitious and provided only as a usage example: .. code-block:: json { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Example Theme", "author": "Example Author", "homepage": "https://example.com", "version": "1", "number": "#6ED3FF", "parens": "#C8A2C8", "list": "#B39DDB", "unit": "#9CDCFE", "result": "#E8F1FF", "comment": "#7F8C8D", "function": "#FFB347", "operator": "#F5F5F5", "variable": "#FF8DA1", "separator": "#2F3640", "background": "#111827", "primary": "#6EE7B7" } heldercorreia-speedcrunch-e7ca37f/doc/tests/000077500000000000000000000000001526573132500212445ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/doc/tests/test_website_seo.py000066400000000000000000000220471526573132500251720ustar00rootroot00000000000000"""Read-only SEO checks; never invoke Sphinx or execute its configuration/extensions. Set SPEEDCRUNCH_DOCS_ROOT when checking a source tree from outside this directory. """ import ast import html import json import os import re import unittest from pathlib import Path from xml.etree import ElementTree from docutils.core import publish_parts from docutils.writers.html5_polyglot import Writer from jinja2 import Environment, FileSystemLoader ROOT = Path(os.environ.get('SPEEDCRUNCH_DOCS_ROOT', str(Path(__file__).resolve().parents[1] / 'src'))) BASE = 'https://www.speedcrunch.org/' TEMPLATES = ROOT / '_templates_standalone' class WebsiteSEO(unittest.TestCase): def setUp(self): self.env = Environment(loader=FileSystemLoader(TEMPLATES), extensions=['jinja2.ext.i18n']) self.env.install_null_translations() self.env.filters['tobool'] = lambda value: bool(value) self.env.filters['toint'] = lambda value: int(value) if value else 0 def context(self, name, description='', title='Manual topic'): return dict( pagename=name, pageurl=BASE + name + '.html', title=title, language='en_US', encoding='utf-8', release='1.0', version='1.0', project='SpeedCrunch', docstitle='SpeedCrunch 1.0 documentation', theme_bootstrap_version='3', theme_bootswatch_theme='', theme_nosidebar=True, embedded=False, sidebars=[], css_files=[], script_files=[], parents=[], master_doc='contents', theme_navbar_pagenav=False, theme_navbar_sidebarrel=False, theme_source_link_position='footer', metatags=('') if description else '', hasdoc=lambda name: False, toctree=lambda **kwargs: '', pathto=lambda name, resource=False: name if resource else name + '.html', ) def render(self, name, template='layout.html', **kwargs): return self.env.get_template(template).render(self.context(name, **kwargs)) def test_all_templates_parse(self): for path in TEMPLATES.glob('*.html'): with self.subTest(template=path.name): self.env.get_template(path.name) def test_distinct_titles_descriptions_and_canonicals(self): pages = dict(index='entrance.html', download='download.html', community='community.html', donate='donate.html') titles, descriptions = set(), set() for name, template in pages.items(): output = self.render(name, template) title = re.findall(r'(.*?)', output) description = re.findall(r'(.*?)', output, re.S).group(1)) site, app = schema['@graph'] self.assertEqual(site['@type'], 'WebSite') self.assertEqual(site['url'], BASE) self.assertEqual(app['@type'], 'SoftwareApplication') self.assertEqual(app['downloadUrl'], BASE + 'download.html') self.assertEqual(app['offers']['price'], 0) self.assertNotIn('aggregateRating', app) self.assertNotIn('review', app) # JSON interpolation must remain valid even for special characters. context = self.context('index') context['release'] = '1.0 "test" ' output = self.env.get_template('entrance.html').render(context) schema = json.loads(re.search(r'', output, re.S).group(1)) self.assertEqual(schema['@graph'][1]['softwareVersion'], context['release']) def test_additional_page_without_title_and_offline_context(self): context = self.context('index') del context['title'] output = self.env.get_template('entrance.html').render(context) self.assertIn('SpeedCrunch — Free High-Precision Scientific Calculator', output) context['pageurl'] = None output = self.env.get_template('entrance.html').render(context) self.assertNotIn('rel="canonical"', output) self.assertNotIn('application/ld+json', output) def test_nested_manual_and_search_metadata(self): output = self.render('reference/basic', title='Math & units', description='Roots, "matrices" & units') self.assertIn('Math & units — SpeedCrunch Manual', output) self.assertIn('href="' + BASE + 'reference/basic.html"', output) self.assertEqual(output.count('name="description"'), 1) self.assertNotIn('noindex', output) self.assertIn('lang="en-US"', output) self.assertNotIn('maximum-scale', output) self.assertIn('content="noindex, follow"', self.render('search')) self.assertNotIn('application/ld+json', output) def test_manual_descriptions_parse(self): paths = [ROOT / 'contents.rst', ROOT / 'introduction.rst', *sorted((ROOT / 'userguide').glob('*.rst')), *sorted((ROOT / 'reference').glob('*.rst'))] descriptions = set() for path in paths: if path.name == 'units_table.rst': continue with self.subTest(page=path.name): text = path.read_text() block = text.split('\n\n', 1)[0] self.assertTrue(block.startswith('.. meta::\n :description: ')) # Test only the metadata fixture, without loading Sphinx extensions. parts = publish_parts(block + '\n\nExample\n=======\n', writer=Writer()) self.assertEqual(parts['meta'].count('name="description"'), 1) self.assertIn('

    Example

    ', parts['html_body']) descriptions.add(block) self.assertEqual(len(descriptions), 17) def test_sitemap_and_config_coverage(self): tree = ElementTree.parse(ROOT / 'sitemap.xml') urls = [node.text for node in tree.findall('.//{*}loc')] sources = [ROOT / 'contents.rst', ROOT / 'introduction.rst', *sorted((ROOT / 'userguide').glob('*.rst')), *sorted((ROOT / 'reference').glob('*.rst'))] expected = {BASE + path.relative_to(ROOT).with_suffix('.html').as_posix() for path in sources if path.name != 'units_table.rst'} config = ast.parse((ROOT / 'conf.py').read_text()) assignments = {node.targets[0].id: node.value for node in ast.walk(config) if isinstance(node, ast.Assign) and isinstance(node.targets[0], ast.Name)} additional = ast.literal_eval(assignments['html_additional_pages']) expected.update(BASE if name == 'index' else BASE + name + '.html' for name in additional) self.assertEqual(set(urls), expected) self.assertEqual(len(urls), len(expected)) self.assertEqual(ast.literal_eval(assignments['html_baseurl']), BASE) extra = ast.literal_eval(assignments['html_extra_path']) self.assertIn('sitemap.xml', extra) self.assertIn('robots.txt', extra) self.assertTrue(all((ROOT / name).is_file() for name in extra)) self.assertIn('Sitemap: ' + BASE + 'sitemap.xml', (ROOT / 'robots.txt').read_text()) def test_homepage_links_and_download_headings(self): output = self.render('index', 'entrance.html') for path, anchor in re.findall(r'href="((?:userguide|reference)/[^"#]+)\.html#([^"]+)"', output): source = (ROOT / (path + '.rst')).read_text() headings = re.findall(r'^([^\n]+)\n[-=+]{3,}\s*$', source, re.M) heading_ids = {re.sub(r'[^a-z0-9]+', '-', heading.lower()).strip('-') for heading in headings} labels = re.findall(r'^\s*\.\. _([^:\n]+):\s*$', source, re.M) label_ids = {re.sub(r'[^a-z0-9]+', '-', label.lower()).strip('-') for label in labels} self.assertIn(anchor, heading_ids | label_ids, (path, anchor)) download = self.render('download', 'download.html') self.assertEqual(re.findall(r']*>(.*?)', download), ['Download SpeedCrunch']) self.assertIn('

    Version 1.0

    ', download) self.assertIn('

    None: self.total += other.total self.translated += other.translated self.fuzzy += other.fuzzy self.untranslated += other.untranslated def completion(self) -> float: if self.total == 0: return 0.0 return (self.translated / self.total) * 100.0 @dataclass class PoEntry: msgid_parts: List[str] msgstr_parts: Dict[int, List[str]] fuzzy: bool def _parse_po_quoted(line: str) -> str: line = line.strip() if not (line.startswith('"') and line.endswith('"')): return "" content = line[1:-1] return bytes(content, "utf-8").decode("unicode_escape") def _finalize_entry(entry: PoEntry, stats: EntryStats) -> None: msgid = "".join(entry.msgid_parts) if msgid == "": return stats.total += 1 translated = any("".join(parts) != "" for parts in entry.msgstr_parts.values()) if translated: stats.translated += 1 else: stats.untranslated += 1 if entry.fuzzy: stats.fuzzy += 1 def parse_po_file(path: Path) -> EntryStats: stats = EntryStats() current: PoEntry | None = None active_field: str | None = None active_index = 0 with path.open("r", encoding="utf-8", errors="replace") as handle: for raw_line in handle: line = raw_line.rstrip("\n") if line.startswith("#,") and "fuzzy" in line: if current is None: current = PoEntry(msgid_parts=[], msgstr_parts={0: []}, fuzzy=True) else: current.fuzzy = True continue if line.startswith("msgid "): if current is not None: _finalize_entry(current, stats) current = PoEntry(msgid_parts=[], msgstr_parts={0: []}, fuzzy=False) active_field = "msgid" active_index = 0 current.msgid_parts.append(_parse_po_quoted(line[len("msgid "):])) continue if current is None: continue if line.startswith("msgstr["): idx_text = line[len("msgstr["):].split("]", 1)[0] active_index = int(idx_text) active_field = "msgstr" if active_index not in current.msgstr_parts: current.msgstr_parts[active_index] = [] start = line.find('"') current.msgstr_parts[active_index].append(_parse_po_quoted(line[start:])) continue if line.startswith("msgstr "): active_field = "msgstr" active_index = 0 current.msgstr_parts[0] = [_parse_po_quoted(line[len("msgstr "):])] continue if line.startswith('"'): value = _parse_po_quoted(line) if active_field == "msgid": current.msgid_parts.append(value) elif active_field == "msgstr": if active_index not in current.msgstr_parts: current.msgstr_parts[active_index] = [] current.msgstr_parts[active_index].append(value) continue active_field = None if current is not None: _finalize_entry(current, stats) return stats def find_language_dirs(locale_root: Path) -> List[Path]: dirs: List[Path] = [] for child in sorted(locale_root.iterdir()): if not child.is_dir(): continue lc_messages = child / "LC_MESSAGES" if lc_messages.is_dir(): dirs.append(child) return dirs def print_report(locale_root: Path) -> None: language_dirs = find_language_dirs(locale_root) if not language_dirs: print(f"No language directories found under: {locale_root}") return print("Translation Statistics") print(f"Locale root: {locale_root}") print() for lang_dir in language_dirs: lang = lang_dir.name po_dir = lang_dir / "LC_MESSAGES" po_files = sorted(po_dir.glob("*.po")) if not po_files: continue global_stats = EntryStats() file_stats: List[tuple[str, EntryStats]] = [] for po_file in po_files: stats = parse_po_file(po_file) global_stats.add(stats) file_stats.append((po_file.name, stats)) print(f"Language: {lang}") print( " Global: " f"files={len(file_stats)} " f"total={global_stats.total} " f"translated={global_stats.translated} " f"fuzzy={global_stats.fuzzy} " f"untranslated={global_stats.untranslated} " f"completion={global_stats.completion():.1f}%" ) print(" Files:") print(" {:<24} {:>8} {:>11} {:>7} {:>13} {:>11}".format( "name", "total", "translated", "fuzzy", "untranslated", "completion" )) for name, stats in file_stats: print(" {:<24} {:>8} {:>11} {:>7} {:>13} {:>10.1f}%".format( name, stats.total, stats.translated, stats.fuzzy, stats.untranslated, stats.completion(), )) print() def main() -> int: script_dir = Path(__file__).resolve().parent locale_root = script_dir / "src" / "locale" if not locale_root.is_dir(): print(f"Locale directory not found: {locale_root}") return 1 print_report(locale_root) return 0 if __name__ == "__main__": raise SystemExit(main()) heldercorreia-speedcrunch-e7ca37f/gfx/000077500000000000000000000000001526573132500201215ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/generate-icons.sh000077500000000000000000000065441526573132500233740ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" SVG_FILE="$ROOT_DIR/gfx/speedcrunch.svg" ICON_DIR="$ROOT_DIR/gfx/icons" RES_DIR="$ROOT_DIR/src/resources" DOC_DIR="$ROOT_DIR/doc/src" PNG_OUT="$RES_DIR/speedcrunch.png" DOC_LOGO_OUT="$DOC_DIR/logo.png" ICO_OUT="$RES_DIR/speedcrunch.ico" ICNS_OUT="$RES_DIR/speedcrunch.icns" require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then echo "Missing required command: $1" >&2 exit 1 fi } require_cmd rsvg-convert require_cmd sips require_cmd magick require_cmd xcrun if ! xcrun --find actool >/dev/null 2>&1; then echo "Missing required Xcode tool: actool" >&2 exit 1 fi if [[ ! -f "$SVG_FILE" ]]; then echo "SVG not found: $SVG_FILE" >&2 exit 1 fi TMP_DIR="$(mktemp -d)" trap 'rm -rf "$TMP_DIR"' EXIT MASTER_PNG="$TMP_DIR/speedcrunch-1024.png" echo "Rendering SVG -> 1024x1024 PNG..." rsvg-convert -w 1024 -h 1024 "$SVG_FILE" -o "$MASTER_PNG" echo "Generating Linux PNG (256x256)..." sips -z 256 256 "$MASTER_PNG" --out "$PNG_OUT" >/dev/null cp "$PNG_OUT" "$DOC_LOGO_OUT" echo "Generating static Linux hicolor PNGs (16..256)..." for s in 16 22 24 32 48 64 128 256; do mkdir -p "$ICON_DIR/${s}x${s}" rsvg-convert -w "$s" -h "$s" "$SVG_FILE" \ -o "$ICON_DIR/${s}x${s}/org.speedcrunch.SpeedCrunch.png" done echo "Generating Windows ICO (16..256)..." magick "$MASTER_PNG" -background none \ -define icon:auto-resize=16,24,32,48,64,128,256 \ "$ICO_OUT" echo "Generating macOS ICNS..." ASSET_CATALOG_DIR="$TMP_DIR/SpeedCrunch.xcassets" APP_ICONSET_DIR="$ASSET_CATALOG_DIR/speedcrunch.appiconset" ACTOOL_OUT_DIR="$TMP_DIR/actool-output" mkdir -p "$APP_ICONSET_DIR" "$ACTOOL_OUT_DIR" for s in 16 32 128 256 512; do retina_s=$((s * 2)) sips -z "$s" "$s" "$MASTER_PNG" \ --out "$APP_ICONSET_DIR/icon_${s}x${s}.png" >/dev/null sips -z "$retina_s" "$retina_s" "$MASTER_PNG" \ --out "$APP_ICONSET_DIR/icon_${s}x${s}@2x.png" >/dev/null done cat > "$APP_ICONSET_DIR/Contents.json" <<'EOF' { "images" : [ { "filename" : "icon_16x16.png", "idiom" : "mac", "scale" : "1x", "size" : "16x16" }, { "filename" : "icon_16x16@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "16x16" }, { "filename" : "icon_32x32.png", "idiom" : "mac", "scale" : "1x", "size" : "32x32" }, { "filename" : "icon_32x32@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "32x32" }, { "filename" : "icon_128x128.png", "idiom" : "mac", "scale" : "1x", "size" : "128x128" }, { "filename" : "icon_128x128@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "128x128" }, { "filename" : "icon_256x256.png", "idiom" : "mac", "scale" : "1x", "size" : "256x256" }, { "filename" : "icon_256x256@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "256x256" }, { "filename" : "icon_512x512.png", "idiom" : "mac", "scale" : "1x", "size" : "512x512" }, { "filename" : "icon_512x512@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "512x512" } ], "info" : { "author" : "xcode", "version" : 1 } } EOF xcrun actool \ --compile "$ACTOOL_OUT_DIR" \ --platform macosx \ --minimum-deployment-target 10.14 \ --app-icon speedcrunch \ --output-partial-info-plist "$TMP_DIR/actool-info.plist" \ "$ASSET_CATALOG_DIR" >/dev/null cp "$ACTOOL_OUT_DIR/speedcrunch.icns" "$ICNS_OUT" echo "Done." file "$PNG_OUT" "$DOC_LOGO_OUT" "$ICO_OUT" "$ICNS_OUT" heldercorreia-speedcrunch-e7ca37f/gfx/icons/000077500000000000000000000000001526573132500212345ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/icons/128x128/000077500000000000000000000000001526573132500221715ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/icons/128x128/org.speedcrunch.SpeedCrunch.png000066400000000000000000000466001526573132500302000ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËbKGDÿÿÿ ½§“ IDATxœì½y�%ÉyØ÷û2«ê�}OÏ}ìÎîÎΞX,€]Ü'q¬ÌAˆ Ф(ó0)Šô?²éd‡$Ú²dɤƒŠ°å%›ƒ"M€„‰ƒA×À^Øcf¯™�{¦§�×ÝשׁLÿ‘™ut÷ì4Pÿxs·ç½W••Çw_~™¯•×ÊkåµòZy­¼V^+¯•×ÊkåµòZy­¼VþÿRä?u‡oxÃÏÆq~ém¨ìÝ(}§î@ô~ SmA"‹E¬«oíşk+×Eü§ÅZ‹Öº:Å3Ö® k-¾’«‡¿oý½PÇ]À«\§èÇ7ïÚ•$|—²‚„[vba`­¬!\´ØÓ"œá/¿ØþúøBö]ö.Êxä‘G×/Ù�Ä‘ú QÑÛ: 4› :�­v­ZkL€v@,[�bð ÖXŒ‹°Æx¬XßžC2V°Æ`¬5X@°Xã‰ÅX,Æ·oA,w%ˆ±€XË�1%‰„f¥ 7Rã¿ò Œ5¤é˜ÑxD–gˆ{~Ý Ÿûï[­Á?óÌ3“¿aÔüÍÀÞðÁ‘Ñÿ•ÒÑO*ÅL£ÕâÀ¾}$I‹e2Ñï‡LÒ”<ËJ ÌS‘ G—÷Jv÷¤�ÔÇÓå=[H×xq½àú­H ÌìI§6*œÆk‹‰„¶DAEš8ŽHâ­K–¥lll�æ)‚¬ ø×ôÓùâ•Ç—¾[8ÙZþFàᇙ&“*Zÿ´FµöØÏìì,£Ñˆ«W¯2�ÙÖ¹øÈ³`¥*r+\UA’ u«ˆ«!_B­mb¿”Úþw¸ú²Ö#¶ >Ê!Š!� ÖQUÐ0Eqj§Pŧ«çž‰¢˜ngšH)†ã!›ý DTß`³ßý÷W¯>Õÿëceçò]'€‡ÞðÁSÄÿ\”ì?|è0³³3\¹|…ÕÞZÙ¡¨m�‹ÿ·€™-�ê¥wM¿ûJ‘R ®àh õb¾‚ðÑ$pm ùTª®~çû¾·q¾8B cÛ‰*”QJßa¥n³Ñ¢Û™b4™°¹Ù8¯¿üüKõ‡-ÄÜ |×à oxC[ÌÞ߈µþ»Ó33;rŒ‹—/²¶Ö+æ�ˆã{ë.„Î!X})9 töì7OíW;•ïˆ|ðC÷Ǩ/4›­¹“'OòüéÓLÒÔá4 ¹‚|ñÈV¾gµC«A<–¢¿É5$O©:¶yU1_Öµ8W°h¡Ö.¡Ÿp-XUL׿T$‹'ÜB0Tl—0çÊsÅÏ mÉ®HQ])ÅìÔ,ë›kdy~Í`ÞyæÌ7Nïkõ²vU^ÿú÷‹�ÿ·ÙjÍÝqâÏ>ó´ÓQ¯‚|Á¢Ä‹}¥¼QTÿ³¢T¡*DÂ_Uexù!‚òvEA`…h©|Q˜p;ˆeññv %�>ŠTQh+)jl÷eÔ6ɶӷZñsÚùnuB`Œamc•©©i”ŠöjÑzÛmo:²sÃ7/-xË[ÞÒŠ$þtœÄ‡îø¾×*ùøm·ÝÆÕ+WÎõ¢¬°øÝŸ¢û5C°ßÚqjE}P*C #�p·Õˆ¬Ij¿]±E¥h/¹` ö*ŸR¸®vkMn„ükU‰© ä­e;uî$I¬µä&§Õh“f“7ÍÏy|eí·e|[àž{>Ò�lò?ÌÌÎ`òŒžî„�Ù­¬>”`U¸-¥„"ÚI… P� T…H¤"*°(› ¦ÐÃÛJ•z‚z¨>W¯ZÎaglŸhõëöë5ªÚ.„vn¿Voû½,Ë�(Š@ñ÷³c³7(ß4¢µŠpèØ‘£œ;÷JEÌVŒ´Ê_0øª¬#S•^ å¹¢ÊÙ•ÀH1ìÄxý‚lû¹µ¦lù¶sÝ�x4´½�Ø_M¨W+ßù[‰d§Q¸ ýaŸV£ –££©î¯½Jç¯Úã«–ûïÿÀÞ†VgŽ9Òî÷ôz«8k½DbÐÙ…e^1öJÏ €.Œºr5ω8üyï^• 9•@Ž­ºr7�àê¿¿ŒTƒBe½-QA‹�3øç«±€àö E,  Õ‚Aeì¡n[û^¸Ž•»R¡üjlJþ×ã(&Ršq6ê£Ò[žþ›×wƒ×h7•beM)iOMMqñâÅZD¯6°0zu#Úrœï‡_Mx ±5Ø)cÊîq[­áîÕAnK zt»]öï[d~~�Å=‹ÌÏ.0Ý�"j4È�%KsÄBž§´“„¥ÕK+׸tõ~Ýé9”$h›«3‚|’£é“²|}„¶Š|4FrKŒpçÉCDÒ R��׉Òe®__áâúO¾ü O¼ð—._!§[¢�e° Ój°B¼EÀ¨àì-¡]Ô�žb B Ž´RŒ'ãëq£wh7ù»’W/O~XK4;33Ëå˧¶ ¢%ݽMqâ(ÛWÄsg•w�H®üF(’)7׸ßlãüCGñÀ›àä÷±¸xˆ‰™bb®næŒ è ’|H”ç(QÉ´bõÚ„\ eQ2k¸ru™}s{!S,N, ¦é®7¹Õìãíw=@ÿÁãÒø/^™/<ñUN½|Š~XÀBöjÜ¿ƒô”ß«ß/ëTqšNhv¦™LF{L:ÿ·€›®îNXùX£Ù`4U”OèØ¼Íˆ)ȳŒ­Õ`PP¯ð�k,V¹‘P­+†……9Þü¾·qò�¢·¦h¢XZ�l ›yŽUAi+&¶�Ø!b ÄšÞxÌD F â3Œ¬2ˆVV$z…ãQ%šÉ(Ǥ ‹¤tG†ÑîX<Äöá·s!½Æ“Ÿã÷¿ð)Î_¸TÄIj°Ù2¯íȯ‡‚E꿃´°ÕßÊEP“f“ ~‚ïül,röíûöïçʵ«Û¼`oò°�jkn™[þ´[ sk¥¦óëKÁÞà °*$‡�WwÝs‚‡>ônòùyâƒ{¹’tiHDd,M`˜hÁR„ˆ”̘VÖú)ã4#RŠ@9ÌraráÃ}ÓtÑ£ˆxJ¡#ƒˆA‰“!6ÇX¸=YäØÝ‹¼åÄ<ýòÓüÁWþœg_8M–fÛá$¥ý»3çË3Æs~€‹(”D9ã{bRI;¾>¢á÷¶R_­Ü4ôúûæß!J~vß¾ý\½zÕér¿¬«¤´ô‘Ò3óAÝ�/bø¥µÓ|«*!XúXŸâž³ÀýÞÃüç?Fë�oà[QÌekÈÆ)³�˜F#¡¥fCKŸ ‘‰@HDÇBÆ„ÞpB`Ô0yŽˆ05Ñ ±±¦»šhfœaGv˜‘÷'Ø~ ƒ12a'†Í˜ÁJʱùž>Ê]wÝNo2âÚÊJ¹Ò¨j(Ý õÛÄ~ár+…Ò:Ò(Ïù¾ÍF“47ç6>µ´|îU—Œw!Ì;K:)ép¨¶«ú e+œ;L4,©~[„bÕÍó®]èã¶ãÇx×G¿ŸkÓ³üÙx‚�iZ4ý,ãÚê‡ã‰»Œ3˦µXmI´ÐE"B¢ "Q4µb0È,o ”›O®@° ’јÆh„$ÑT‹å¥Œ…DcW¥e�Kk<2•ZšÍÞ&vœ1 ¦»g–ûÎ�9ù–ïãÑ»^Çÿý¥/puér ±[‹lcï^k� ë#5­°ÝÞ²‘~'ðW;ãÕ•›J€ýûoû¹V³y_«Ù¢×ëU¬þJ¼_*Ö©Ã÷!àŠ&¸�ϱ͑*Èw\ÛétøÈßýQnä½|n,¬æmÑ4”`Mæ Jaœ¥$b9>;ÍX i[º-E«)D‰`#ÈŒ¬eŒ%WÂRfèˆa8L�Wâ�Y=N™Ù¸Å¤X3sp‘ñ†�XÑjh쨜kÐÑJ`<³¶s–?û�ßã‰Ç÷Û»Q3ä(¥ÑÚRvŒˆ¦Û‰ £%µ…¢VÃbÑ ¦ÆbEcŒÅšØmI39ƹÉi·#ÒÔrõÚŸ¸úI>ùçŸ`n~ž‡îyˆ7Üý&îÞMÝ¡1‘MÑ«#beÐXÄ*~ñuÓ‰þÍŸ|‚,KÙçW.ÃÜ–bö¦YB»ŠÖ6bT8Ü1N%‰SycOl‘²å?ÔüÃÊ”~à§ÿ6Ï9ÎKÃŒN¬˜‹"Ö'iÑ7®Íüô4½^�af8ÚH˜[ºÊg~ëw9õÜi”ÒDZ3œX´Ž@åt»‰_‡ðjŠNÅv±•9Ã2BH µÞg²Ž°pùy ±VÈ��ç9&�È=Q´ZšµÕŸùÒgøô_~†}{÷òƒoþï}ð!n™^ µ`2@å9ä1†Ÿ>~7ùû3þíçþˆ,3ÐlG~iX*²À#w+ý7uì;þñù¹=¬¬®øq¸E �ö¹Hð•�Y\lE\Õæã~¼ã{Þ‰¼ã]<ºiH”°i[1ËËÚ$÷y¤ÎÊOâ˜)¥¸+òü’ÿøo~›åë+¤Q(�F#¡‘D~‘$Bií‚SaK•`%õ4’ 4]àÅ]P¸Å®°Š)¢P¢P*r®š‚("í ÂÆä¹Ðliúƒß|þ)>õW_äÔõKÄ ³ìmÏÙÐè,çþ= ¬·šœ:w¶4 ÃX¨¡º¸*P  �¸IšŽ¹víÌ?z5üÞT„µò@eÁÀsR_|Š•-\[1DªR@ꓱm‚eÏÂ'¾ÿ|f‘s±¦¡…~fä9 ë¸5dÝÒ_ãw~ý×¹|ñ*ã‰%ŽÚíœH'ÙAFy./6Ž–Ži±ÆT£(Æfqª¡4ÍlEüziWÀ^!$Ö…‡cLN–¥ä¹"ÏQ¾ø�/óåÇ¿Æëﺟ�½íÞºp”f.(¥HlÊϼå�œº|ާNŸ.U5öBTT*s)Ÿ*¤q³²/ Œ7¤‚jw"ߥ¦ï= U<,):€ô}?ñÃ|:‹1ÀñVƒÍÜ q¶ÇêÄIc\Ÿ3‘âØ™SüÖ?þ' ò\h·ÜŽ[­^ÇWæ_ /c,u½õRªØ4RÌÏ™]VLI¼¸Ei…Òn!Áx"H0äyFši²ÌÐøÆÓ�óøsOñö׿…yèÝ<4·Ÿ'{×ù¿¾ôE¾õüóa;{u‘_E~½×ôëŽew ²Ã&p´¨2#FlÁGHŠák«Ø÷ A½å0£ãG¹Ô²/iÓŒ„HJY® L±ð£DhŠpïò%þý¯ÿ�¬®i$MZmÐ*F)]J¹9Äq°õ¶K¹Ó7Œ¥žQT YðϾ`¥”’L”B´ Õ–p“Rí)Ð2J4JC[L¦È2‹Öðßø_ùÖ7xÝ�÷pêì ô7&$‰ |æT€eèûÆÈ¿f]Ù�èc!ÒÂ’—ŠJ¨XýÊs¿T²y�2uŠùËÃ?ð¾”eÌEš–¶ôò”c­&)py4bZ+b"±ÜË„Oý/ÿŠ•å>­¦"IZÇ^·ÛBДž¼H ‰"åná@ÔRãþ þƒ�[ ¶ E\ÊonQÚϤ–ÄQš¿ÕPVEh@+�È ³ˆ,²Ìé”o~ë ´ŒQX«*¶e{å¡ ¬ò¾•²ÞÍÊ® {vKpGª‘=qaV·‚(0Ø à(àØh6é;HG[7ãBþNk¸º<äpš9gŒ–ÆÏ?Å Ï�¡ÙÒ4â&JGµ°°ïµ@¤õÇV+Ÿ 2 +ßcºˆ^Zë‰Û– ‚ãv¥+†yU­Q⾊¬ð[B¤ÂZíԖΉ£ˆ4Ó“c­"I Zé"s*´V¨£0Nê›Hñk"Áþ¹YÙ� `l±k&ÀA°…['¡ÅlK[€ê5TÅp7Nœ¼�t¦Ém¹“™5ä²qNo’…¬&a¶ñÍÏžF³I#Ö(”_×ß%bKŽ/êK^¨´ð¬7bƒš«q¿_wWZmIërmWäG)y„ á¹þƒZqë"‚Ø«4Z¬U~m¿á=«R½T8¼¸[M»ßAãÞ¨ìÂ|>^¡ï cÔzIP.Vxš(tn�¶$|Zk¹ý�;Y·)ãÜ!?3Š©H±¼™’!b”M‰ÄÒ˜ 9{æ2qdQ:*€Y"ß´VE¾»VŠk+ã¶5eKµ¸_¢¢ÀÁË)ÕM�Ç‹ÙÖ /µ‹Å:ñSž8Â&QU©©jb?×å5)† Ö…³ c+q„”]H‹©‰ö�Ýã:Uõ5°jz#lëù9žxö:À+Ù%š”ÐE¸’¦(«@ùˆ›MÉŒ%Žr”Ž)ˆ­@àȧŽü­È®sm ˜Y¢ºàx[^/~Ý_�V™¾Ä1rá,†AúêyÖ{Õt»ðhõŠR?@Ûƒ5†<Ë0ÙÍ àæá¢b2�*úÒOÞ‰JKHÙ*þ Õ°Û#kâücijMŽ"g6F£Œ<ˉÈüŽ¡˜q ½¥„[î8�®p`Ñ>®Î2Üb(È ,(ÓôU �h´V5ÝPXýV–jl ÁJ”�u W¥!Ì2ºn½oC~í)pƒµä™!KÜÂée»)7%[X°øËÓ8Jø”›&‚•í‘!%¢ª§qc1Æ bQ’ù¼†ÈXÈs J,š”<Ϲ|õ*g/ļñƒ¥ÑhRØò•ö©Œ«pI$½_Œ9è|¯Þ´v)V‘*$AEƒZ·ˆoT¸ßEG½x¯ «`Ž‚GakÇŽ :a=\BHÕ°sÞ‡É-&ÍÉSS„§�wµEr¼JÙEÀXÜáx¶äªàÞ…É9n—Êw(Ü­J,=DáBN¿±“ƒƒ’ŒŽFØ�I”AIŽÉR®^z31è¼Í¹¥CüÐÏÿ}šÍ¤ðçm ‡"ͬ4¾ª¨4úJ;E H¤ÑQŒ 9Å3…[ ×l¿®ÌÒ-v0B°UäWu»'ïR»ÿa mº ÖßÝàMž‘O&àÏtDçæ¦j„ò] €êf�ªh­�θ«:ù²bÙÅ%÷g,ãÞ&±´2(rlžc%GIŽÍ'\½ü 6£½i»Ö‡Kã»ùØóqn»ëD©Š*ÜX;¦†|)�¯Ñ 97²x^¼Mï‘/òU…(p¼ˆ¯ð„”²€r[ò£XÊC3ð¨öÈó„å> ÕõvÁE³ÌE­u’³š?±k^ÈÜœnNX&Vr‘øQ°-9ßW-®—OYâÔËϽġ¤�°7YÞ““gc._|…l<“‘Û×Òg@`cž|y‘“þE>ü~…÷Þ‡ÖQ¹��06J±ïǃ´Re~]Q0ÂP©Jéê^´’¿\Nl�(œ�V"Ï �’Ãd,{ •¤ÈKpÒß“Bž“e&˱ު¯È“ò,‹` †ïjkFñÎeWq€Rzùà"�~Ø20´ÍÐ)”¥Žg·S�?˽z�ùÙã~J¬ yfé//1×T·M¬cPŠž¾B:ª„ÔK€pM®Ü°ìJ˜ LÊŸ£NUˆöR¸Éšb…ææeDi>ñ»Ÿã—ßq?Ò„DR«œkh,9.QrÿT—Í\1ž›ãâJ�áÆ×˜îeÏÜ]´;ÓxÂ'Ñ &ÒàÊØ(Â4çQÝyfÞÆëßü.6†)zØÇŽ61ý>Ãõ×Οcãòy–Ï�c<ì3È3gŒY‹ß UG~`D©€½°ý¶(ë�Ì)~Kžåñž›¥@`ÉùR[[Á�PÇm•øªêg» ÙZvµ ·[çâw+µ´™êI!…ñ÷Dèonò�O|‰ö;o­XìNqucÃUhN Ææ­„æžÒ4g°±Ì‹çÿ iâÀÂ!ö¡”.ˆA´ü:† c�–`›bé2%Bo`Ðw>À¢XŽ"tíÆëŒW×`­ÇµWΰzá2+—.0 öGÞúÀÛqøÂ¥ •ç!˜Ì‚1åóRJ…Â_È/Z�åV®–ª×Q>¥v8èl§² `)Ö Ì÷ˆ°¬ïÐvÕfCÀ IDATc)„“Õtv4AkÃg~ÿsüä?ÅÆ-m" Ý$fs’�Lí(¡Óˆy~i�XEk™Äv~ûf&\¿B2î>8Ç+#‹¡ÝnÓî¶iu;´g:DÍÈ‘½vIqîÿ²ð©¶_Ë…Ä*TË¢; M‹í€R–É`HïÒe–/^äì©gyññÇX_[Ƥ>Ø…q1ù°°DÕ†,!T ëh³µšUéY]“•Êg§§çX__ãÉgþôUq|S8yç[íÑÃÇ8ñ¼ïÃ뾩R�ÿ]Z¬RLlÇ­Åú·g G9ûöÏñáÿò'ÉïÙƒ"çÂêãÍŒy=ÃãWW™Efµ3�&C“Å‘v›qo�Nk–xï­¬‡0êc}T>A{U�4’nƒÅ¹*N@7hÅ-£·‚çj!T¯KùtN6ct í†+^>ý2gžûÏ>þeV—®yÎ/QY•¥x$5¿•k‹W¡"øSÔ*—Š#ìJ´NMϱ¾¾ú�À�'Þj�¾…ó_ñâ«°N 6;H„­nŒTŸÝ¢×¬µ“1™Œ�,³³M¾ïç~”cヌWÒU¬Md /¯õmŒ™ô32#Xa%ÂHŒR··›L%1Wd–(î‰ø¿™Œ`4ÆN†ä“1‹lnŒ‰¢ q%è¸A¬[$ªI¢Z´¤M‡6�pë-Ã8r!7ŠÜDLŒ0fŒûcç2*Å@7IBÜÞKuP↬Åy1G÷$tEqmÝkClG(&hq‰�6ϱلÈääùˆóëëŒ}ÌxÄt«ÉÁ=óŒuB’ÁôhŠ…Q—=à ý�̢͸ †Í¶fi!¦ßÑ`,/]z‰¯>ö§<ûõ/ƒ1•ÀjÉÍr·`i'äÆb­º“ëë«7•7ݲgáðǧ§gè­¯{+Ú øŠ¹¯¤âãoqIêR¿›’-ßBû"­r²\clÆÓßx‚—¾òó6b®5…jÆô²Œ‘ɘä0RŠæÔi«Å3×{$XÚMVëÄq ¥b×ÂÂBÄt¢lZ·ËXV”KFÁ8 ¦Qœ�´ÄÝ›qBkfŽFw ÕêÐh4Ù·w�4Š«1kq�~·ÇÓö:çí:LË”µtÆCö®­3Õ0h'ì;x€ùýwÒ^ØËõ¥ ¤ƒ~Ã>+hÃ.€>HØjh~�Í&ãш+×^þG¯†ß]À‘�ÏLͰ¾Ñ« ¿ì¼jÜÔBŸUU° Ù[;ªØ Zk¢¸�Ž Ï5ij˜LƼøôižùò7Ø|é2‹q“Ùf›¨ÓÄq¬ÙÈ2zX&D$ísó{YnILÒˆéÎ)Z˜µ×úyÍ6�ØÌ×eM7^ZÛp\*.!J“)žé)Ú{éÌÍ3¿°‡¦š"ÄLLβpA�x>š°¦ ±Ö,‡¼¾„˜1—lÄâÜ!¿‡•Á*›×¯†³j n+›ÿ%•{E¿ìç,æl4[LÆc._{é;#€…ùßšša£¿±åŽT¨Ð¯m±ñÄ‹Ü×Û-6pIÀ(%hù|?åS²@)CžG¤™ÛÉ»¼´Äéo>ÅËõã³W˜Ía&ŠØgH3Ì& Óœ#sÓ ;³Ø†5Z„…8b}Ã�º@ei°ª°€’�ucÉÉX� «ÆæYaSôú#M·I#Í‚ŽYYŠH¢�îSÓ{h4:(¥XÉ'¼"/¶"s-ö^_á¶Þ2×Zm’ÖG�ÜE_eô.ŸÁÚJ©Ô,€Àþu5à?wZõkµÛŽ®¾:ìú¤Ðb�¢À[‹ªú≸/ÅZµ `mÑ¢lÜq½Ò*´ *¤™kbÕDëc#²T‘g–fSÇ<ÿÔ“œ~òI´Vt»ÓÌÚÏ�;N-,²Ú[çÄ]'¹”L3Îal3$â|?¥¡„¦rA°#¤ª�˜ ÈÙÛŠyfyÕ�=à'f¬øHab2.\[æð�} {1 -¨¶ÐH”"Þ3M$3h‹ -¯õ85^ãË£„¦Å[¯œå¹¹½\èìå]~/(áåG?ï_Léu{Еh¡Óý‚;!¨âÒsÕ+ÞÄMÊîV‹OvR!8D†U³Ò(‘bI8ä Ë’ªnEm?==HƒÝ'„ì*-¼º9´à]:ªZ¯PMY®]¯þ#n�\…¯<‡Ù ©U‹ßWÂ�#”ŠÑÚ�XüAŒ1y–“K«¥ÈsHSKÚÛ`cm•s§O;]îw'Í�F“öüffjÿZ{ö25·ÀÂÁy®H5(‰0º\ž5ÞjÏ­¥5Q\+6ã sKd„(m]¤1R.Ñ;ËP2½ŸƒÝ9Ö^9ÇW7&š›§› É¢o|àƒl\¿ÂòÅWÂÌ+¶”T´lÈ,ªA©"\Ù�ý­²ìn-À¦µlU8Õý¥ß¿éJë¶QGª˜LE9P>6¸�6,JUõ�KÙ�R~­" [ª "NB¸½ú c ÓQ乓X£Á˜ñpÌúê —_<]{ÿo%4Z-ZÓ3ÌÞ~;3GŽÐZÜC<7G23��#ì@Ñè&Ø$a-µ,ÄŠHûð¯�!XÜ:@YŒ‚•aF„Bt¾[��[ais“Ît“f,vxÇû�?þ�ß$Kó»s{«(‹ªÄ_j 4–„·ä�Þ°ìrwpXZ,säGV©®ìܲ“ab]žÖE89¸Ž;–"¹aç1Q<ëÎë 7´vÇÖ&[°ÚïÒ5ä¹Á-l%4›Ðßœø9[Úí°˜\È2C¶Ù§¿¹ÎuK”4hOͰpÇ,¿“©»O²ÔžB·ZXq ±–gX%NòãvgÖ24«ÁËÈQƒ=fX¹aÒÌ©4<øÀ›9ýÜãœ~ü+…K\…í6JT kíîY@Šݽ»<+Še?ÊN«ëÜá[E’x#/ª‚^…<«íÜ_i¯ú)Õz®}¥¬ÏÌ1νòL5“e4b��C²§ÿ3±?¨)ÇZÁhµ5ynÉ'9++l<úÎ|í+<®#Z{æ9úæwpä�7ß{/S­&ýÔ{¯"7–NKqözJ¤Ý�Vb,ë©Ðì´hvGŒ7ÁŽsÚ{RÕ徇ßÏ‹ÏqUƒ †ZA ¬N§×°b˜››g33:p'Gn½�W^x)vˆ2�ú”ÙösWåæq€¹ÃŸššbssÝ÷R·B+¿êCq'\ƪÁÚ5ç×JÝ"X¨ÚÇ¡j0W­ Öâ6Qd•zcùvñ"W¹¬a‰üA�šHÅDQD;»#‰•?=,"Ï!Ë@k!ÝìsñÉÇ8õ—Ÿg³¿Isf–Å=ó\æEª—§KÈ X‰h7`ª£É㘭5©éóò³OUÞ‹h *¯b¥˜}È=ŠF«I:qáâéôjø½¹Px£$ @U€fæâvѺÃËTÂŒ½*²%x7ã|<òëíUUŽò)çøÝGyVF5.²PP1Π>‹«Ö§GXÀþab¯2ÜúE–kŒq§•HÄ3ø»œþüŸððÇ~†¾›FÜtF b@iˆŒ0A1=Ýf¶Ñb<‰°©Ð@sÛÑÛø‹XiiŘ·WÕð{yOyB¸YÙ]@l‘šU®ú•h²A ˆwít©˜+CÚ¹m7«È©Ö*.¹¦·f¼yEàÙ"ÏŒ^Õ`­¶éÓÜj†­-õ˜#šÊq3a�®ËzóA«È ­&‰sŒi�ç)Y®˜¤‚l øê¿þMNþ­ ¼é‡?F;iÑ0†ÄX’ Ög0e-­FL#¶X#( Í9Zí›ë„%áúõ~¹“�Øw“ôí�$Ê´p)+8ÄëªIPáÏ�+°CÛ[Cžå�²ãj¶JVuãPD°¹!Ëó" �/žÍ‹½�þZ™äYŽ'<'ªÌ|ߟ£/Ÿr­¬Ç ¬MÐÊ¢#�Îsâ²\1Îržûì'™i'|àý&B£� 2Ê(9,�ÖѸ£ß¯¯,ÁdÌâþƒl®Ÿò]Õ.ÇÎ p£«ûwÇ Äú}æÛõs‘øè÷ÕQ!ˆ­¶ÁV8ƒ´ì€þí#©N~ËÁ`ËRlqÔjÕvÂAÔuä—:¬œ· ¶!¿Ô·ezwHÕÅ1±Š$Ò˜È-?ëlÌxlxìSÄÑ[ïäø­÷¡3ƒB¹ ‘²¥<ýâÒÑw;DŽ¢Ýé2Õ�r›q*@jxð¶UÍ ®HƘٵ²»#bB'¶èÕ]÷û犣`Cm €î0”Wóñw²¤z¯2p\msLö W¨ßZ¬uǶׂıAïWãéÎ&(¶‘í„|ªÈWÝ ,î½6ŠPâ·3(Ç û^xê1Ž¿Ñ102c&ã5.®_gy³‡d/_¸ÌmG�’4§iw:[ây[˜°²ôêè\ ôˆøµ”›”Ýí®| /råݨJ0ÈU) ¹ò­^å_Ð[‡¦Tĺ˧ð_-»�m¹)ÕäÆŸÎ¶l•ú§8,Œ+0�uFž öŒò9™_T[‘_; ­¾Éœ=¡DC£”r ë˜$nÒl(Î<ù&KÙÌûœ_;ËÙ¥çÙ>K 9–ëë›lô{´§¦ˆ´÷dÄ:=¼+¢|Wc•°K¡PÕ¤�–]ï *E£;OD•¨¶U£ck§uýZì'¨\Ž¢ˆŸú{oçÁwDÜö‹üÇÿãkdùd åWŒNŸf½ÕF¨åæ QL)9>ÜWáPfw€T«q†UÅY*ZѺ-ÜI¢¨ÜsJÅÄ1Ø4ã•«/ú7’ ÓíW}&Ö‡°”€1¼tq…÷ô †EÌB¶0Zu†5׋Eíú¤¸›J� Tžë‹…ˆ k$ðAÉ¥ÛÐ |ü$IøÙŸ{¿KÞüÞ˜û•wÓh6«#pÅZLž»Ð©5e_õaP£‚¨—z&®õ–¬C–®ˆÒ°U»øYèûX…Ø·ä+ˆ’-Èd玒�´¦3Õ UFÜ*cÒ‰Y�ÈÅ`5«…dºÃµå&£ ÏõQ~l~ž…$PUÎw¼_“7)»[ Ðq\Äð5€V%bØÚÌvðÙjò«¿ò=ÜÿÆ“ü:‰îÐQð¶·5™�zÿö_|‘õžKD1¹q/qªØ ®øó‹^…°É¢Ø¯X­iñ¢1„‹Ýs^3ªìx+Gìÿ)Þ{à9ßFq­^ùˆC µÂ¾;N`$Éiµ, ‡Œó ‹Åˆuž¥…¤Óeuc�¥kW¨¾€³f T°[¦Ž×\¯ª5vÃrS  ´BG•‡R²ú�Q¶$ЏsE¤Špž4š-þë_z'ï~`†eYÔ° rflÊB¶Æ=÷�ùÕò.î¼ÿwî�ƒW}N>Þ¯‚QçOÛ Ô�ÅÖl5,L<>vîÍø°nàªW8: Ÿù" %¯Ž|ÿ¬RšÙ£ÇIUcI+b#3Ì3ŒÇý ˆ4ªÕ$í¯Ñ[Y)CëÕПr¶�•B1‡{QáT™›–›«¥K¼{á¶ss�ÿÂÚ ®Év¢èt:|üßÈ[oëÑ[?ÇòÕóX›“e˜|€ÍÇt²Mæöø©x’G~äaâ8¢FdÁ Ä/W-‚Þ ˆUn·/ÎÑ) S²e¡Ë°ÞáÛŒ¢› ?p ,¿…dßrIh4;ŒÒŒÞxùFYl$ÄÝ6V iï:£tâ‘ZwýJå?wˆ–‹V:-ÅX¾+ !PF‚ cY¤ò¹µTP‰´©©iþ»_¸ŸŽ\'K°¹òƒQJgêõÄñ.- ÓYŽm÷ù�Ÿ<Ìíwàÿùí¯sþ%÷¼b µp©¤D[(•¿_ÿnUæ"Üa¦X²6.¹¥|ºŠ|W?nµxýßO÷è6�‰D»×¨�³(S¤Ã>Ø”n{ÈÃïiò ÿø}¼ãÞD³Ý®Ø=Rš#>€`5ûQ“ Ô-#yUÈúÉV¿€¶žûCŒÞVîÎhv»ÜñýdýàÖÓœ±ÉÉ+š‹cèL1Ûj“cÈ•E·Úkò3Ïsùê Z´'¯’DBÚz‰ òd1]dû 0nPv€rNÕ·èöâ�[õ;Ú¿Èÿôó'¹kÏ5rc±q›q6Âäc”õ@Ë+×^D©Û™žm¡de@ç­Ô°™çÎ %cqOÎ~x‘ßý^žzô:_ÿô)ú½µ¢¿ª§PXÏ–â`ªm³©LKUB©Á+PÕjqì]¿…ê “Ò,Üv+{Þú&†‹û ·ÍX8Ðíð­• D„—ûcN..2¼è^0Mwh¤CÎ=ñ8Z§(•/„®‘q˜›Ô1â¤Z¹—`7z`—9�¦®K·–C»îבÃ{ùç?wwÏ\*R³Ò¤ËxÔÇæ”8� ˆdlô®'{iwš ÁdŠx°J3RŒlØ�`Ñ’²g1å�ß;ÅëÞö0/>=䉿8ÃÕ—®`ò¬:”éénìOÕ (¶L|s·Jñî+ QL�7åê<…- ´bzÿ~î|äýŒn½…QÔ !‡Ü LFd,�Ž1f‚É × ì™›eie•ÆLõØc<ý­i6ÝknÊw/{˜n…9à~l!Ý^½ÜüÍ¡”º¶ŠzÊ}‚Ûž —ey“͵‰òM¬Ž§ÒÉ&È-DJÈŒEYE6ZfuÉ�4Ž“$ŠñÐB>aÆFd M.Ê¿*B¢Q{f#Žß’0ÿ½+‡¹üüˆ¿z‘�+=læN £»*¾…£[ôi1qn!L]©«DˆÍü­·0ûð›Éï¿�hï-c‹Ó;µ'´ƒÍ˜óà �YK[ Êä ¬e!¶ê­Ò¼¶Ä3_ü2¢"¢8.Þ^Ž—Jÿá«SS…\óx·nàn^W:ÆEñÄ RWÅjrÕòÒ¹+üÒ?û¿ð#oå'ÞÑŒ ©$¨I…KxTø³†Ä­´e“MV–®qôø›°ãëDs‡0ZÑŠ5J‘INNÆ„Œ #ÐmVÒœ½S3èè*Ócn}Ë-ô–bV/æ,�é³|ú £Þf’€³6dïVd*å>ÛbV¢°ù‚Ñh$t�fæ®»™:qû³Þl¢¼4Ì8ÑŠ¡o�K!Wš~nçþ-§ÖbE)XÅ‘V—å/ý>/¼t‰énâ�¹ñ M¸òýˆlŘ &ÃÂb§²7pb‘¤ºÓ'«ìÀ–ÿV¬Ok]ÎþúzÆ¿úwŸã±S÷ó«½�nã¹8qª¬%/Ú­;Õ#ÏsÆÃÃÜ%c²lÕ½¸r”3ŽŸu›#‰žæúè*‹³‡X-ƒÊ�æ&ó‡íEØÌxr;-³ŸÕ¾emiÈàzŸÑ•5z¯¬��'ØÜ�ËgM޶9 ÑqäÿšÄ‡ö1{ät§µÚd�Ãf›}G²>5ņ�˜p –åjj˜�mëÆ0+–a›¹E "ŠBšeôÿôs|å _¥ÑhE1Z«âEu RlˆüS#†`£ˆRnRv#6ó<ŸwIîí];©"¶ Ï»g^EôÖ3>÷Å'øæ³gùéßÃ{î›&Ñ›äJ¼;oŠØ=béÎfcð"3­y˜ Üúúli#Fü6­HÏru´�±9ײëì�»�ë½³Œò1Zb"ï4“œC‡ÛtØ“·Èìm^G›ˆÞæ€á8#›é8§-³\ÉÚ¬«’&yÜb¬"lÒ@�'Œ{}Ö†fcM–Ä ¬rI£^S*`5ÍI”0§….ŠÌ «Ã”,wï=±X­ˆóŒý�~‘¿ø½?d8¶t;‚Ž"÷® gÔœ”â‹C¾xP‹Kv·mrPÆöo†Ý›&…ÎÏýÅFÏäyN¶kƒ¨k;I(%þÄË !#Ma2óµÇÎñô¹&Ó û98çŠÎ¬�‹ò[w"¦÷"5›äVшºÀ¬Ap»oÆÚS¿^du< ³¹Íh4¦�,'ËÆ îŽ�³0uÛi2&õ£U ̘fÒ ÛÒHà m˜šï 3Ó¬4g5bL“k…AhÇ1³‘fy8b¶Û¦5=ËZæ¶•‡8‹c¥8ÜŒ1–&9- m%´µbÖdìÿÚøÂ¿ûÖ6SÚ­ˆfÒ"R±'’Ò«)þ«¬ (¯|Ã;wMENz¥iºüÒÙoýÏß,.þˆRÑ¥#²,Ý‘óKפBÖúómÝ •Òˆ²d™b2ÉY^éñ¥o^åÚdžùù=Ì´‚­º{ïÀ4,¹ddù�¨1çöï['Ñ´5d¢PÉ4)ld#¿¬äC:Í«¥}÷£˜šÙƒtZL̤XÍT"LLN¢´UÄF>¤©›ÓàâPÐR®] .‡`‚ Js´Ñl´X�›D±ro4kFšv¤h‰ÐRŠØÂ¾X3ÜÒH'Ì›Œ™,ãÀf�äÏ>ÍgþÃï³¶9¦ÝÒ´m¢8F«ÒS©®ü á·öºy‚pÄ�4î•¶™yßúß_ ¿»ˆÈó“,}k·Ýa4Ú©†aâ" “çP€nƒ‚§žähÝ$M'c>óé'ùÒ—;¼ï]'xËSܺ0 jD Ö(ŒÖôÒݨK#lº ¢˜5)+´H­Á˜ ZÜš…Ø1�f›™l†5VhD-Zí6+f- È}0È�Ù ëYŸiÝecš±�¸Øß ‰Œµh±$¸E¦ph{,šƒ333Y’H‰óf´8O²¬­g$2f‚Ð^¾Ä…Ï–/ùQÆchµÚ´±_R®Óa+�-ÅnÝ“ÁÃ=P„…8Ilö±b^¸~oî ÏåyJ¤vuy`±Ø,$dÊ–P±ó—ÝË› J\Òd–„!Ÿü£Çùìç[¼óÝ÷òž÷6¸ýxJ#‚\ 36MŒ‰¦ˆ$'O7‰¤Icb¦}"¦¯Ìò1¢›t»‹ WûDIÛ0H–!øèšä.ÈbœîÛ”=­= 2H¢ V;CÊZTž"&GÙ ÊStu›4�™(ab,¹Ɠ̽­Ãs©˜�5724H†›L=ûuûüg8{~‰,ÚmE»á^o[uûÜþ‘Š[ºñR|sf g@«@G±3j±§¿cÈÄ~)ª¤CÝùÆßéö{Å•BTy=¥r"-! >û©¯óùÏ>Á÷ÞÂÛßs¯»·Íž=*1B1ÕØKf†Œu“QMFä‘vVµrÓ"d&eS æO`"ꤴU«"l8(ÐFXÑxö¢+Bå*·æ)#Ó%C‘!Í©u“ܽ�ôÌú:ÃIFk~/½T“æŠH J9)v=ÏKôÿµwn¿zWÿ­™Ùû»ž›7‰ã¤.â`UB~/È IDAT)*¢!!!•RTñÀÿ@žø*!/¨/ѤDBªEA ¢†ˆ6IIÚâ\¨¥Z-vÍqìsûÎwÝ3ÃÃì™=û;Ç=Çx:Kú.û2{Ï̺ÌZkÖ¬áædÌÃW¾ÃÖü¯¼ö:• VÀ ¯èu¦‘Vɲjm©ý¿r 3£Ýßx‘:§BÍlªó¯Gá÷Hxü‘ÎkׯÏwÕbU+ƒuU†à(ò«ÚéqøÔÂr‡Ôé̽VˆÒ(í0ZamØRU”ç�·®ðö›W语ñ‘�žçâÓ�òÔO9Î=:åLç34;“mº¦K!k4•W!¥,aSë½uTÇ ÝͰ†ßÅ5þë¡ÂR9…£b6ž2¶ \µÏ¾�`½¢ò ç4EØÕÈ{Îô{|ss‹[ã)MÁ ·ÎH…moŇ÷{çù�ªpo½AõõWùÚ¯±?�S8Å ¯è–}LF–�Ÿ IW�4“Iò½Ð6ökKA•WYðì ×Ç_? ¿ÇñðäSÿåõ§ý»£,UŒó8o›Êö‚V$IømƸ ÀÂ|ƒÃQo‡b•­èuÃú;Äâ=tVWyê§?ÄÇñ)žx|�ÞÊ.«½6h"Î#õt²sŽJy|y†i¡¨ºSfÌYx¨¼Âz�²�ν°®Î°»cÍ+¼›3¶Xg²¬åŠÊi:Ê0²Ž«»cv'…~ìì9Ývª‚[±¾uså=6ß|ƒï¾û³¹E낪º�.�ŽPšn²õ£¨Ï¸^â�²$öóþŽ~Lô7֘쎨*ûw_ùçç?un�·0d¡Ÿ·Ê}Z©"� ¹oÛ"ÙN=, ¡Y RÍÔÞd"r•„ÜÁ…ÓX[a­Á:¡×ÓÌ÷öùö+ßæ[_û¦Óexz�Ÿ¸ð(çÏoðØÙ.|L18”®PjÅ�[û7ØžLxø‘sè¬Ø:\Úƒ8* #%Ê*œ�"ÞáU'lY烲ˆ_ W9Êî ³ÙŒ…›SjÁ/¦ØÿÍÃNßø6/¿Ë¾ó6ïïŒÂ918§(t‡•�`LAQÛùª%Ú—�_;Åš(Ÿ¼‡ÛXÅE°x´Ö!zÊÊóÇAí±Àtn¿PUk·ç‹é©Òt˜LÇ�6%Ì)1þ‘(©Z÷´ýÙ•l"CDƒ× ­ Î8œì¢Â:ƒsžnOSÍ+v~¸Éë×oò:  Á¬¬²qj•GžXçôœ=§¨Š��e2ñðcë¨NðIHB#"ôÔ€j¾ ²‹°§¯wa³ÈjAáöð•`œfMú,¶wÑ›·yâæn4fró67®^ãí­ÛŒ'ó�š²S0Ÿ�); »P%ZiŒAµMf•¬_j»/!2»?öp$Þ¬kw¼éõXLç[ý›Ó/·Ç.\ø…ÏYkµ¿Êöî­¬øò#ò‰”æm±Ÿ]Y’Í„ „á!Ž˜ª¦²ÞÆìžþ ¤„ ®!›)F­ E¯Ü«eÁÊ©+ë]ú«=ú+}”1Áä›{¬sÑt%ó…PÍf,ÆSܼb´³Çþö.“ÑŒélÆx2MHZe0Z1›9Œ)) KQt0Ú„Y½ZÜ+•bŠÂo=™#ÒèFiú9êJD‚h�áZÍdX9ó»›ïƒÈ¿ðO_ü½ãàõØYÂØ›ý‘+ù­ùb6ìf‹èfn[­¬UùËc?ù­Sq�©M"ƒˆG«oBôž«CÅqëÖ+ðž^/¤”÷æã s™–Ñ-¸iPëÔÚqª ¸¶2jß™R%ÚÓIȨU‰’Šá°G¡5JÅ� ¢Ð¢ÚÛÇxH!èÒ¾ÄIIô)Ø£á·Èù¤ˆ¸¢×¥šNQJMæFþðNh\†£SHÔðþÞµÉéSçV«jöÌp°Æl>M*±U‡rþ�DþÒXs}v&ˆáO*r‹ )µ2eÐZ( …)E¡ƒW‡÷Þ«�6Æ)¬œ¬…n·@kSjž§uðƃQáÚ|FíÒ1 Q%Zåéu:t»�ÒP SÖ{êÚ®Wõ*�fuH³Æ¿îĸ”,RSI m"“šd�ɬVŠÁÆû[;8'ŸÿÛ|‹×cgÏ~´?èêËÆç;e‡Ñx´„¼ì±-Ã`YI\"†¥ò-«WÚeÛÛ©Çoßz-HÈÛåÖ“ÔÚÑ:“ŸiùUùRHèÌ/luTÁŠÜ-R»�¥ÎˆR³e,“ÖÑD$ÇV&ÿ}Màžl¡G.1jû$Çt7ÖXì�±³Å¯íl^øÆ7þ~÷òîÇ€ë׿9þñóûì¢ZüuYv(LAUU�/°4A}\ä/;<–�OИb2RW‘k˜ug©�­ËÇç4)íâΧâ¿…RÁ�!EY�Å’E êÌÎù†ƒc�´D¸®U[åi·-Óó®[þÓ{*I<�‚.:ˆõTóŠÊéß¹äÃ] ¶¶¯½»±ñø#óùüg†ƒUÕ<ãöƒ�Nßíñ‚äÜ<¬ƒ„ÈOCŒ´žš�—ËÃIŒ™Ï>µH\«ëI– ˜έ½q… «z•ÔºXFjiPoñ.Q7�ÈîKç›z7çIÇih#ê1ýn=´$yšr!úX´¦¿±Îþ­mœâÙ^úÂçîŸwÞ€uÝÏ òæh�aDð^Õ R¯Ð‰ .ÛˆOÊpxùËR#a]Â;|œœ‘´ÚŠY’((ãG E$™LIºHó “Wñ8[ܦ[m»ãŸ#Ú’�›KåSkÒ¼€0<½ÁèÖ^üå�)ŸáàžàêÕ—§ºÒŸ²Þ^Ýï1ì¯dÒ¯Ý!I͇ò2Âi�4ç¼J÷’Å#¶2d·$D�@9€¶ð*kÛÇqgä«ÖñÒÖ>³DIWiµc¹mùq´XBÉÁC§Ø¿µ�wîZeý'Ÿ}ùÙCçj�‚{"€÷~ðêuãÍ'¬s›“Ɉ•Á*JÅü˜q½>4ȹÎ�ÉêçIöŽT"ˆÆ¥‘ö‚hÞÜŽtlGG#ÿR-6¡U½ìo ù¹>ïó²}ÞƒQÂðÌi&[ÛXçn+ååů~ñûÜ#Ü3¼÷½WßSÆþœõîÊhWZ[ ^}>&ëhâü³gg ^£qø´»¹RŠîÚ Ê+ÆÛ;xñ—+ë?y?œá®­€ÃàÖ­ì�:ý‘ç4“Õ¹­~ÖãöW´«sw�|YB~Îåõ™–„oÝÑgÉÊÄ4Þ¿Aá§vÅjCB¥Dž¤µ"_Š•�˜Õ_¢ËWšfÆã@4™”’ ý·öd”�÷ è÷¬¯1�™�Ç î/×fêW¿ô/ÏEü}Á‘9|øÃÏüšÂý‰À»�¦,˜Ï¦ÌÍÎáÍ˹‘‡‹íš»ë¡1qr~êÿFJ$o[ä«ÚU­¼Ôúazrr2‰)hâÃó"±¤0씉#^Ï%]ƒèÔ¦Zê·'y â}±–BXQÜ[PM§LGc¼çšóúw_üêŸéÞ0s8< �ÃíÛßÿ¯óÝüé¼,©ìâéù|VE‡Ao€1%ÎÚCt££�Ÿø¹î¥œ”<)‘bÒhrOsœ81‰ÞFʤ=f3i’Þ¹8eå€M+ã7}&%b‚ÉH”QêÄçêÒÐ[]¥;‚sìom³XTcŸ÷Ýί¿øöÖ]¢ãHxà ‡ >vÚÛÎo þ3ÀCJ+º�AÈ8BÈß[UÖU!¡Ï²Œ'‚ˆUÌíù¥FdŠ|DL•ÙÿuÚWÉvc ¢6ÞëD›äÒmÄ; ÁdÃB‹ó³gÅýrçUÿµ ‘PeY`Še �Yµ�C„l)Q_˜Šÿƒ—^ú‹ÍŠ˜¼ïþ¯œÃÅ‹˪Zÿ„òú7þ—¬CXogL˜xÑCÇUªUky³4N�†:…,"*^n €’- xT� v–Á‰`´¥iôƒF3oòc5KGE·ßŠé¶e‡ ÒÕ+ç±Õ‚Åb�·6¦¤Ý^+Ï÷oN¿|éò¥#WöÜ/ü¿@~C_üÉͧîA.xáI�ÇAÖ�!B*¶Tµ%¤.ï—Û¶4K qk­<$€,s·¢e5(��ê�æâ“µ Òƒ¤lc��dÈ•ÏZö/´ócDí‚».¢®8áÝŽ2/w7&ÿ~éÒ¥fu'p'p'p'p'p'p'p'ð@á®?ƬIEND®B`‚heldercorreia-speedcrunch-e7ca37f/gfx/icons/16x16/000077500000000000000000000000001526573132500220215ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/icons/16x16/org.speedcrunch.SpeedCrunch.png000066400000000000000000000014001526573132500300150ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“µIDAT8�¥“Ïk\UÅ?÷û½÷½éÛIÓ“ªiK’þ ŒPµˆ¶H"ÕnDÁ�]¸u¡õ¿p¡(UÖÔ…¢BAÅKšjHÁLšÕÄö‘fü‘òî»÷º�@Ïê¬ÎâsÎ�Û”¹eŽ}îgä ’îM)8_y|ðør_U„ˆ!•˜0m£=93÷ã—›ã�<û|DN9u¨|𔕧ôë”Þã«’1FHƒ�$ïtÎnʪzSÅ"Ö "lm1öøwŒ2è·3¸°B±p�ÓSßòËB€<Ë^6RŠûbŒøÊS;0ÂÝ/½È¿ó³Ì|õk¿ôEË®¾!޵Ÿ¤=4çӓ1m PÅèLªHZO=JoòW®|ô!!|ð,¥H÷Ægç¾'WA�ÁÉ ÜV­s+±Áîã/Ózð!êÛúQÄN•!ÆH ñÿÚÇST•þÑýÏ<ÁÍj„�­†·d4W+ò¹%~úa‚˳Á$T3¦¦¿1 00pïÛ„¡ük�›ç§�]þ.–X[é‘–ÚÈßÓc¹¾xqŽÅ?;'-@ #ŠQb0QY�¿�.+)1oÚ×àé¯1öÀÃ\ºtQe“�8‹Q¸ÿÀ�¼ûÎ>F5¨ÊŠ˜@DpÖ’§Àl1C7^'³Jf-›-�b™Ùá=޽ýÂ+'†9wl'�ß KEÆê–]lm·±ƒ;è|| 窮܄¸ÿ‘‹¡Š‡RL´šuÆÛNÿÁqhË óGq‹WKÌÏçÈþéáT1Øé3ß}p߯*ó–ÀQ¡×+™ø¢€‰‚”*Èkuêµ:¹s8g©¹Œ*É{ °¼|m¶ÙÚ=i�ŒuM#ªV-¹«‘Õêäy§묷b/côÕÓ_¿ÿÉí>€ÿO!Y%kLLIEND®B`‚heldercorreia-speedcrunch-e7ca37f/gfx/icons/22x22/000077500000000000000000000000001526573132500220135ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/icons/22x22/org.speedcrunch.SpeedCrunch.png000066400000000000000000000023471526573132500300220ustar00rootroot00000000000000‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“œIDAT8�µ•ß�ÝUÅ?{ïs¾÷Î̽Ó_#8ítÔ© ´PJI!Ʊ5ü�D#¤ôÙHâ³…¯â‹>hªhSŒES¡D$K§…B¡Pft†™ŽmoçÎÜùžs¶׎ >³_vÎÃ^ge­�½à3*ùÔ[|í;ß Âƒ¦Í–k&'JòÚ=ç’rö”ê’“»g÷LíÅëkdþtæÜ‰£€ÿðÞ½S[7m{){È‚ã”RH%“r"åDNu¿—Œ—BqwP�¯æ²üèùóo.èu¦Ãƒ£¿¯ÓÚ)B ‘hfSCE1UDQAPEDŠ�SýÕ ­ß^'+¾rðÉ¿TŒ+bˆx�ºÔ ±sj?#íQ† Ù5 3¼=s†Ξ Ó]wG4Í9óÎñ£°mlòG9å»ESÁ,�>Ìø³á¶[‰�A–.w�åãƒ[™šØËƒ·ÜÉZZæýÅy,U ŸÌÍ_x1¸øÆ\-…”2¡¡|îûßcmÇóoýƒ¿yŽ+³á"ä”ɹ¦a-îÛÅ“÷ÜËMí!~ñÆßú¦™nè§âÅ39÷½Üz×í„/Œ#gÏ1ýÓg@„X �sF‚b¡uNÎOóÚïÞ$¨ ÿk—±n^]ŠçœI%Q§DsHÙR/ѹÜ`ËäNJɸ;¨¢ÁPSDúã1V˜U�ŠCNÜÀ¸.9÷‡U�™Sï ·�seh€æ}O±û A¹JýÉ,½ ï27}–«‹ ¨B©�ä8Ь3urO9¼8‹ÉG^bÛÁ‡˜Y»H¯Œ22´‘­»6sóä½|þþ!—:œ:ýžù½Õe@QÑuAnùâ㹤ÝNÿgaui…Ùã¯Ã‡é][@KFB`e(qyC¡´‡k�2¹c¼7MÊ=T 3›ž�{ï¹�½öâ)‚DEEÀ�` zó‹0·À…ã¯p¾î‘²ÒÚ>ÆÄþìÛÿ›6ìdêOðÒ‹?GD�úqAÐ`N³) ´*þ½Ø£ä‚猨cƒFC‘K |tô«3³ÜÿÍC„V ˜!ÁLÖ�ƒ Y Üi·#?þá—hnoóìÏf8ýÚ¸ ¦‚"XˆhT›Úœî~Lè.Í‚Þ`žX_sDᩯ�°û¦5–òU~ðô$}h o½Þá_o¯²º´‚£šø2›îÙGë®;©{«,¾ðgBP�Ð_á€ÇKΞ�Ÿþ€WßÝÌ¡Ccl߸ÆÄà î¦+›¹–Gø°³ƒËi Úh»]æõkÒü•\ H\úŸÆž�•ìO—œQ œœîð÷S§ßÄŽ[[ŒN¶‘±.Qº _YfåŸ+\úø*—Î�gP¡Š� Ѝ‘‹»ñËm“S/眧De½«PñŒ©ª&ͪIŒ‘`Be�ÊŒ µøÆá?<»ðë÷ØSÑÇb¯˜„¾V¢¸ 1b ªšTÕª}£DúºŠjñdNúíë)òéh’;vÞ÷-Sp m³(&®‚¡&,ˆ6«M$ZU+Òk;úÇgßMŸYýRaZBëEIEND®B`‚heldercorreia-speedcrunch-e7ca37f/gfx/icons/24x24/000077500000000000000000000000001526573132500220175ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/icons/24x24/org.speedcrunch.SpeedCrunch.png000066400000000000000000000026611526573132500300250ustar00rootroot00000000000000‰PNG  IHDRàw=øbKGDÿÿÿ ½§“fIDATH‰µ•[ŒÕWÆkíý?çÌ•¡Ã0t å^@*AE /%´)jmJjLc¢QŒ/>øêƒIã“F_Ô¨ñn(*bÒ&m!%$)a S  ÌÀÜËÌ0çœÿÞkùpN§¤‰�]O;;;ë[ß·Ö·|Ä!¾Ø·åpo±ºöl¥RlóÒÌÌH¹ôܳ™YÓ=—–EÜ,af®¼i¼g¦O O/ü_€Ïîæ;•Zå϶²cn˜Ù2)grNäœ(sÆrÆÜp3\EP Ó!È÷†/ŸþÓû9Ãû‡Ïí}úÛ1†_ädµ ‘ Š¨‚ 8n˜ƒ¸ã8ˆ´ët0³Nœ#}ëÞšš½yq™Á–-‡{׮鼞ÊÔWÄ E(ˆ1R¦D¶D³Lô®ìeý¦í¬¨õ MáÞÜo\ý/cÓÓ¸ƒ{» B�ÉjÇÂÆ .,F€WÇ#ÍfÙ'"­Ç89ë?ý ÖìÛÍÇvîE šãstLÕÙc=T?¿Äùk¯óÛ3'¾5Ú’D q@}ð‹Àß"€KÜVæE(07R΄BÙñüבÍ0opöüëLœ“…± dqž—:ûy¸oˆG×ñ£§¾ÉÉ‹/ó»ÿœÑVs£nˆ’­ŠeL”,‚»3ô¥Ç™ôãı[œÿÙÏYšº"XΔ©dÔG8ü!5\1Èó{cýÀjÞ�žn1 Z](Í=™ƒ$¢lØ»�¹ù&7ÿýåì4¢BÎFv•p4(³õy~úÚ1Ü‘€ˆCKá€çlf™DO˜º}‘ùÆ8=›An�;…· àÖb*¢€ €!¸¸c!�Ý,çî”Pq.�:E±{7=JǾ'ÙýågÑXÇçÞƒñL\æÎÈ0÷ðì˜9�QDˆm‹µrr³Œ;¨;¦Ê…œaBÿ®O1³x›ÉÆý¡à�¾•¬Z1À�M_`u£Êô�79úÊŸ¹6z ˆ‚ hŒ²l´ÁÕ•©<ÐRÍqsD“#7¸óÊ9drœúâ½µŠŽ Ína¦g YÕE¥{%Ÿ\ûu Ü»ŠJ@Uˆ±rúæØÈË­)77ÃÜ#ÚGD`áê(\y‡sÇÿIJ@Pz7n`óþϰû±Ãô®{˜ýý_ãÆ­f¦n·T 0K¸�Ð2›(˜9îFNFJ �j%P+ùæ-®ý+ùá÷iÞ½M½œâ¡µ ¡ Ä@T–DD4DsghM?~aŸZOj–X.ÁTAƒªUª׿.127ÊRΪ E�å&«ÖYÄÍØº®—Ÿ|÷Aèªó�¯®eÇž~Nåú…i,;ˆ âH¬Rôõ³åÈW¨¯ÂïÍ3qý"1„v!áþ1m6Zõ9oßx�£¯V8t°�î¢Î®í}T°�w§J¦îÔXXèfª\Åbç +ÙJèí‚¥¿þ’•"´„‘P4>(¹¬99)¿9>ƱWgyâñ:{:Ý5ˆ¬êâž=ÀÍ™5Ì–=,4�æù7{ñÅÝ9b ¨*¢D./×;wîìNeß;©L«DAD!¥:µÎ.†6Öèè Òµ‚Fê`n¢ÁÒíYŠÔ¤«³‡”жF”XÌŽM�o8{öäÝå�¶uÓ�çDí÷à¢",µÍ£Ú^D±Z%„HT%¥JŒ�ŠŠJÕ“ð­�ÿòWËSpåíÓ ž ZLªÄ69iÿ4Ú n9µµÍ´¥7Šj@ceöþäËÝ»v=ÑEÓž”Bw`Þ#!ˆHÖŠ*ŽHA´Z�� !‰ª•ʼ½493þ÷³gOÞýpÎ�4þþ�H¶ž‡IEND®B`‚heldercorreia-speedcrunch-e7ca37f/gfx/icons/256x256/000077500000000000000000000000001526573132500221755ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/icons/256x256/org.speedcrunch.SpeedCrunch.png000066400000000000000000001636731526573132500302160ustar00rootroot00000000000000‰PNG  IHDR\r¨fbKGDÿÿÿ ½§“ IDATxœì½y°%×}ß÷ù�î{ïÛ×Y1 f0ƒ¸‰à"ÒRY²lY¶lª,G‰�Tâ*9‹+)ý‘JÊñ©¤â*/ªTÇ[%¢é”¬…2E›„¸‚ @@ÄŽÁÌ`ÌúöûÞÝúüòÇéÓ}z¹oÞȼ‰y}OŸ½¿ïo9§OÃíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐíÐ}ØH>è|0ôÓñc��ÞazR•»­DÇ#Ãm*2ŒŠš1D§P¡�K»IS—,éj�–‘¢š_éo$-¢ˆˆ¿›þ_ÃÒ6UÉS²öÄWêîh–ê®%mKƒ:D|Šeóúú¥Ø7ÉÛÏëpyU„êXƒQ?žòIö;˜ŠbšP˜¿ûªÖp³"ÐSeÕEYÕ6Â²Š¼‰•WUÌ+"¼òÆ·ž…/%å~Òéÿpï½›™üœZói#ò1sL„F1×�§",W¤>S)Efö‚!ÃId2¹s /™°äBê~¥ÂG +!ˆ(hÚéLxDRyÑ‚�æ`P‡x0ðu‹†™²¶]7n Å™Îû^šÄ<¥8¿eÉÀÎÏY¹.-ä,ô)¨¹§ª/á¨~�(úÆéÓO­”kûI£ŸXxüþÏ?bãèW1ú‰ˆøÀ Ï]Ò&@™q˹µÊK (²u¨é¼`¥ê@À3~ÈÙT”„7­¯"£ ¨™ R²B+#ð:+ ¸ŸjþÀк›'Ja^òI,–  €¸¾Î’ðg雀Ó|R�¥!îŸ�Z~(bþ�Qý¿_;ûýçË5ÿ$ÐO<~ßçö ¢ø¯cþJd̃µ£A€V«ÅÄÄccãŒ��36>F#nE‘‰h4D&rZ>Tµ›äšúÓk.™ˆYŸ-OC‹€µ©vÖ =ÇÔÖú‚¹À¢�E å¶ëË´¶b3\°ªˆ*~D®+^ø¬o¢0–l¬bI» âÇ¥é}, iºÍ'f8>A³´¢™�ëca^ÁÚ| !ÈZks -eV±I‚µ Ib±v@·ß¡ÛëÒëõèôº ý fÉBàe«òÏü“7ß|æ~Bè'>òÀçÿ¬šè7Œ‘�LT•`Œ055ÅÜü<óssÌÎΑ$ kkk¬µ×i·×h·×é÷{ ’› èõØd� B^]ÊXeÍæ™1‚ì2dÔš<^ˆ²Š}~)X¹ÿ\t¤â Tµu4 Æ È{”ié’…RkdC @.”£L€4ÌZ¥² ZÊ›™eƒ ZGÐ/Áˆ!2b""#˜(¦ÕlÒj6‰Mš�‘Ö×Û´7VYßX§ÓíúX kùZÃð?½væé¯ éÉ� ý8€|äÁ/üEÄü×bÌ)gã§#Šâ˜}{÷±oÿ>æææèlt¸¾p�ë×Y\¸N¿ß¿áèCë3ÓúR侂©L´˜1(LT«€€�B< o³a@�xTTƒX@ Ðj‚Š¾Ò $JU‹ÊØ¥Xg0“dÉÄ.“è`ŽC -VQ& o“ Ï"16:ÎØèc£ÄqÄúF›•ÕUÖÚ«X­ÆUyÎïôÙ§¿Ä�.}ØéÇäáSŸûµ¸Ñø;‚¹qB'€av~žƒneïÞ},.-ðöÛïpýÚ5ºÝni´›½x·ª}_j!GÕ.Õ yš? Ðå«‘ýB×!X‘(ùîêÁ*¶áV€ï_�à×Y!Õ@ÚŸ¢uÌa!/A*úûéÌ ­3«7uâËåj ; ú_î*ŠbÆGÇ™š˜¦Õeµ½ÂÊÚ�õR¿Åþ‰‰äïž>ýã?VðØƒŸ¿O1ÿ82æqoŠ Bd"n;t�#GŽ2H¼uá-.¾ý6½!B£AWÒF � `ÌL$•"0š° “‚6Ï#éZà 4ÒÄÌ 4{Ñ µ>Ôõ¶EÁOÿŠÉ^pkJõ&L«"X ÔPAy×Ïs!{L-P­É ¬  ¥Ò…ÈÄLML191‰˜ˆ¥å–W—�{¸„"|K‰þ“3g¾û£º¡|éÇNžü¥‰‰‘µÿVÄü-Á4¼Ö�ãˆÛâö£GY^Zâ�Ó§Y\Z®*¼8úÇ]Y¢ò0låªùº{б€²0æÍ”-o¸6ÂHº/[p2K¡ä³ZAŸó¤Ü ¨³$ŠU„½NE—J̤ ~¢Â”0òà~¹| eîIPM8À09„–i+uf=a¤5ÊÜô­Ö(K«‹,¯.ºØmÞ÷˜ßŠ›Ñóê«ß^­ë⇉>ôðȃŸûe#�¿o„½`@ 2†ÃGŽpìèQ®^¿Æ¯ŸfuuE¨<{%R“N𼥘^š™[TÀ *–/�Š_N�7�¢¹-Y~ ?¿_gä}ÎÊÕŒ­âdE °�Ä»%arQ¸4G¯ÒØsm ©X~(`U~Ðåæ ¢h�”jæÌS«5ÂÌÔ£#ã,¯,°¼²˜­°¤ô–þã×Ï|ÿ÷êºùa¡-<ôÐԈ텿'Qô‚/ü»víâž“÷ÒÙX祗_¦Ý^#F�ð‹)þÖÒ�«E‹B cäüXcxy(D±¡¢(,@D­àÛq8àWCa—r@�aõ—%a å¶Ô‡T£ê°: CMÈ 7UD¸åа�jz�CL™µ=+SßFñ¾V¬Çf£Á®™½ÄQÌ•…Ëtº¥ŠÌ?[ý/^|ñÅÞ�¦?PúPÀC}áh_2b #£#œ8q7»æwñê+/sñí‹€Ó¡ÉŸ ¾�iu-f(›ù›ÇSaËêÉ/Š@�oâÉ´VHΈ.9ÐÁ5‘zWMÑ ÈÍqK(is­‘¼�,†P*Ÿ�¶,!Xå™ íàö8%ˆ‚P•µh!þd«ÓÒ% ,ç­ÔQ#¨R¬„RTfkP¯;altŒùéÝôú]®.^%IaÆg¤Ÿüòé ϼQßãŽ>tðèCŸùCó·3é„ɰoÿ>N�:Å[o^àµÓ¯e›bjM~0EÁ—âà I*e‡˜–Ù� B‘‡2Ço¼Y V„Úç—bþܺ¨³òÀ�û[4¡<ø:3EŸ—-[¾�®O©”dhR\̵h0Ž¬Ñº9¤T6ÿíÒjwX*._5冀LžRŒ*)"†é©Y&Ǧ¸¶x…õ�vØÖ¢Dòk§O?õ;•Ê?@Š>è„ôЩŸù;‘iýCAF%2wÜq'ÇŽçÙ<Ã…‹²¼õÂ/äŸZ™ð …+#‚¤ÿaÒ8A�–ýWl%+Zî§Z‘U }“‚’·Jò6ŠùŠ­m•“‡yK&�ý.6’ÿ•R™ŠUT…K(쯮Dßk JÝuu7&Ö¥€ê4\mnДl©”ªÒélÐén°kvqÔ¤ÓË\‚Q”_ž›½umqéâw·ÖðûOxä�Ïý÷QÔøï¼\Œ�Žñèc�7cžþÞÓ´×ÛNP.ü‚¤ W„T„:סàæÐ0È0§%œ¬Oj—°–Çà …VÈæ"€ŽÒïôºØ\…j°À™ò5uç•…@W®h˜�U׉¡9o@5 R°ô¹æd6oà†T…àaU$IÂÚúããLMÌÐélø�D|nnîÀØââÅÅ.ÂÄ�Üÿ¹j¢Æê…fnvžŸú©Ÿâü›çyùÅ—Ü䉕Ÿß t*ü’i×@ûfÚZ &Æxd(üçA¢òÐE1á4dÚ'“½¤(¸%µ’‰Y!½¨É*JUŠYs(1Y†¬ Õ±²PîÖ0Y“h¥�V­)__Tj›Ù„›£­ƒú*è¶UÊ�®”rã2~vTYßhcæg÷Ðéuò¸€ðѹ¹‡O�:þ{çÎ�³ÃjüÓ âGøüï˜(þóà˜rïþ}<üðC<÷ÃçxûâÅŒãsM[Òj™ðK�/ÏLë*Æ‹³÷ L. åÿåämôžHh.�R²EÆ’ (ŠŒš÷ ò~—5èFý¶1¬�!{•n¯ˆm�Ù/RjµR_(X›kÕ"l C)¹€¤7+üåJj@·¾@m¦n¯K¯ße÷ì^úƒ>Ûw¹”ûWWû'ÿ×ðÒð°ÓûL$È#÷ÿÌ?3Qô‹žQ¼�ûî½—ï?ý4 ׯçÚ²Æô/ ¿K©øÜ™:á÷ÏHÄ4¼«;èUP¨Aš§Ìì¦Ø¿¼Ñ!º¯0U¡Q)X•§¢öÉ¡j˜–‹‡\'4ëo¦•’6Y}ç ÈXÌP/2Ãa‹Â_ø±Éà›ÑMi~OÃÛ$îíÃù¹]¨Zúýž›9åäüüÊþ…Å‹¿ûî:úÞé€Gøìßÿºg¾cG�qôø1¾÷�ﱺ²‚xõšþ%á‡Üç¯÷µ5RñëT*¨ üy7@ƒö$µry˜DŠ}­êü¢j¾ÎáV@>¶|Ü!y•-Y^Ÿ¢Amþ–æ±Vh‹Zì_±Ö:d ±¯®}©\ £ÔÛŠð#uˆuã–Þ•ðç ?Œ›Ðín07=�*ôú]WFyh×ü­ÑÂâůßTg·‰>xðþÏþWQÔøM?á·¼�£Ç�ñío}‹ÎÆF¯©w ~xUøA2áÏõ¢êj °žrð0AÈЙ?ï–ðºè³ïb8¤˜\½®)3TC–ÊUV ‰5¬k·Nø‡Ñfè u?ËO²ÜÇ-�Üd+97)‘·µ ë�uVé ÜÞ U>9;sÛòâÒ[ßÛz‡·‡þÔà¡û?ó+qÔü‡¤²ºwï>î½÷^žúîwé¬o¤À]Ô¨Uí,õ…B�iJ§ûÂ` Ö ½dB^]ú+3„`mº9¿ùüfˆÖ.‡©€[¸Ór»¤‡iߪ%– ë+!…Ïá&|?׃Xå^-”¯nD7þú¤°[iM*ùÞ]‡”*Í…ªÒév˜›™g0H$}—Môsó³Ÿ[XzëÕ-7¿ ô.�¤wG�<ò³G"ÿ#À 03;Ë<Àž~šµöZEã•™½ ”)“VÙ½,ü F ” =ŠßSù/ß^综EK¤(Ђ@~¯(eh)�–O5Üpí[Wg±ŒŸ´°|mëµ½«jÙšìá\lÚljØ{þìºn«`e’¶Cø‡g©«}�ô¹¾t•™é9ZÍ–¿iTôŸ:ôèá-waèO Nžü¥¦ö“…È4ãcc<úècüðÙgY\Zú0³÷ÏÆÚL(L�ð4\ éÞÎúÿ™\L50Þ�À·“ö/_` GP¥¢Ëb²~d£Ê0N7á³´?,òtaïš�o ÝÑV¬=¿YZz«�V0%€Ð!€7Œ¶"éU/¶^wÉß¿‘Á�ó[]ÆØ ~O½~�…¥kÌMÍ™ØW1ÛŒøNž<Ùܼ'ÛGj0ÖXþbäpGt=øðC¼ñúë\½z%ÍQë‚,Qf¢ú¼^ø)L|Uø) >ù“ÏþóûÜ-S‚ rò€�ûÖ�HJ0* �üÒèÂX^á^�§tOût*¹•2Á|—WÊ™*u×%”K  C!³Ô™ú\7/y±Žª®Ð�sç¸\J¬R·×aec•¹™ùŒ‡­šGz�©¿»å.½GúS€GN}ú—1æ×ý¤Ÿ8q7ýnŸ3gÏPÏàeÊ}é"L„LQ\ÈS) ªõË‚zû•k¿B�µè�Áƒ@Øa­J(‚«ac-m�¯ÌÁpq �¯Ô‘M™ýÆ÷ª†ôfÏl+¬_G%H•ú{[®}³†·$üå;[Ùºœ›—k·WI’“ãSøq«ÚÿüÈ‘GöÆ ¾wzßàäÉ_šÀ4þg¯§÷îÝÇ-û÷ñÜóϺ µóãoAɲ*8“Ú/ç¥uåÖ„eB"Ôü¡+ฯ;Í_Í´‘�åFÃ݉`Jª‚žk ­¸³Nßxk~ˆ ædj¢ï%lðË­7ìç�Úª$¿ ­_*÷îÀixç<Þd9`iu‘‘Ö(£­‘¬ ùÇ'OþôÄ–»ø.é}€Ñxé‘[@hµZó×À|ÀáÞ{îå…_(ž”R¡|œå/È¥‰é¤×GùwYûûäÜ~ADýžD…HŠ+ÉZYi" •®×[C:žÿÞš*–2m›·v I,ܾÙW[êdmèÞL½õ£¼qMïFóßLÿªÂn“ÐêÚ2SãÓ9?©~âø‘Ç~ñ&*¿)z¿@ŒDÇ]Á‘ÃGÙè¬séÒ%ê·™…ȹùDJÝ�‚@JùVpß›ù¡ð«÷Þç@´P[M­Õi9§TK^íÀ†3Y½^‘å¹AWnh·.{%M¶Tq©öj SSLLŒ1>>I«Õ@Dh4›˜Hh6ˆ"1ô=’�Òïv±(]¬Mh·7X[[eeu•A¯ìæÕÿ–ú·5*Œä]oðÙZ®enXÁpá/Þ°É€~ÒcldŒõŽ;WP ¿ üþM4¸%ÚvxðžÏýœyÀÃí‡óô÷ê^rº9�•åÞ¢¦ÖVE#„  (9üdŒ²Èe`"uw‡V³…ÞÞ(ãÖçpllŒ}û÷²{×þÄo|çßßDÃ7¤m‰ùÛþú¶Û±¼´ÄÊêj‰Yß�¹ºu3wX-›>¥ò5›aŒ1<×óå&xyËÙÝ–±Ú[»wïæðáƒìÛ¿›={ö±ç–[˜šš¡Õ¡Ñh"ÄÄŒÐë[lß’ôÀZ¡×U:…ì9ÜâÅWéwbŒ„QHz b]ÛCDÄÚÕ>GîÚÇ´i¡£ 3 ñ€¨! l�nom¯ÐMÖyûêUN¿}ž —ÞâÒ¥+\ºô‹ KïR°Jó¼�°ÅB[Êò^Ü©¯ R�”.IŸA¿ÏhË[þ6°­ð.g»žN�zâ@+j¼©‰žøÔ<óÃgY^\ üÞ|£Iý¡‚øœø»B¶CÏ›b®‚à¯NÒ‘<('þËÁa‚“w²gäþÕâ?¸ã­Ó#®Kgîƒf_éɿɧPÄßOÝŠ´NÍêtM„çí»[Jø¹ðüoT•86Ðb~v:-’®EÄ"XPeru�Ù=Ê` ô¯õ  ÝØ²·¹¼z•·ßá¥3¯pé�wxûÒ®^½šÍ[NêEá·ç†ôn�¡µn(}6EeÎiXmu-Jµø Šð9�VÚ÷}.¯ìJ˜GhÄ ¦'g¹¾tÅßô{ëÙ³O]Ò�›¦mµb¢¿n•Hæææé,-- G™áVv@Å ¾È°µ„BÆrzXHIƒ,NRµÂ�€—ê”Ê�ºA¤�ÕòJ8Šê�ÍþŠ““ãÜuâÇŽåÄ©{˜žšGâqˆÆè"Úå­å6QÄ0*D›4£&±Y¯ÇôÙgÅThN®\ïÓé'D’žƒ€’(`Ðù‰ý¤Ï¥ó †Ý»wa1š¸Æ××Ó¶ß`°��\M@”–½Òd×ÄNî9Á§|’E»ÄµÎ5Î\>Ëó§_âì¹ó¼}ñ"ƒÁ�¥c¿„»É‰!·”åÝÆ$²Ü•"U~© þ£?èJ³Ñ¤ßïÄM1ø_nª3›Ð¶€ŠüeÇ­nåâ[o…7)EP†Õ\סg (¨ø0]1‡ÊiÌ“0w&¥–tÆUF†MJhZ&üíjÈı¶üí‡r׉;8vçqn=t�‘ÙY’ÑI¦›M.\²,.Y"£Ú‰e îDM-�ˆ-Úk±ê6õÇÒŠUƧ"Öz=–×{nÔ(X7_b Ö&X#Î P°PËõkë´FV˜››cíŠ0ÒOÛè “1´bú—;¥5  ÑJV;ˆi±ÛL²{t’{ã3G>ÊÅö%Î\{‹¼öçÎ_àÂùóôûþdݲxnÕÏú „¿Z×páÏDzÑ]g´5æÎAZÑÙFØ6à¾ûžx°ÅÏÄ&æ3Ÿý,O>ù :½~pn_�i_vÒgù•&ææ»¯§ìB˜ôU7‰F´¦|°ÁG†>-%—-š~…ïߥ÷óœ¹YY}E7¢à¨äõ¤€6;;ËÝÃý�ÜϾÛo#žš¥Ûl±Ø³¬t,{FÄ]áú‚Å:ÅÊÀ mM@Á(‡©à„<²}⤃ARÓĺüÓ³ ÖésîüjZVRÁ¹ $–¤ßCŒuu’ºb…±Ñ˜cwï&^eòò2‘Qš»bºK–Þ¥NºÜjÓÏ�ÙìZ°¨6j¹g¦ 4�‰ˆÞH�·{×xñÊk|çùgxãì\»¶PxTµÖTÅf¾—�¿þWø¼ë©n¥¨^Äê{˜§)Å‘a÷ü>®/_Ëo÷“û_|í[ÏéÄMѶY1æ‹þzïþ},,.Ðíöj| �RA.'û€N~4í¦åÓB…$ñסöOµ¾ªçÓÕi��%¼vö"Z||C˜¡ìcjÐGê†åêãÁ‡ïãÞûOr讣D³³¬·Æ8Ûµ,ö-£ƒ>#DHdhˆÐëC×*±¸Q¬IâêO§OÕ-¦~ÜÆ�ÐĈ"I+Æ ±@Ü4HS¹ri›ÁÏWfaE‚\ïm İ Æ(�o½q�ŽÎ“\6¨X¢¹ÝWÖÜ›šé§ÊTŒ *°ð�G=ˆ#´ÕDb!Š”-NLÜÊ{òùSå�…‹|ý™ïñÜK›çÏÓën¶»tøŒ×eÙt™oS#Cn°"›ß”âÏÚ¶ÄŒ1˜HHÔ222š}xTš­¿|¸@E>å¯oÙ·Ÿ·ß~;¿¹ÉÄ„þyª°Ë5S}xR{Ëø�ŸË+®€zKDÃÇRj—ânÝ@KÚ¿n|Þÿ×àv‘rEâÒöØËG?ö(Çï?I<;E49Áúø/w’õ£b˜j&qÂ<ÕˆˆÛ N®”JêzãÃÖ€±nrmê´Û@LB¤I6+ £¬n �Ô5ðg([oU!Ù· } 5sÃÒÙ4ç¸ÚLصw�¸Iût‰�€‹+Eé_A"ëÞLj÷I8 Ð8r/y) ÑFB+Qî?z'w;Æ/¿Êso¼Æw^|–W_=M§³^fžšç:„¤ü7•æJá­lðÉ®jü}þ„‰$;/º½#­T“O±M´-ð±{?6Û1æpÚfn~ž½ø‚»YúP£K£àgežyI® 5Ðà1—Œ ”7ÒØƒ"…X�ïšïHÙ p¦zv•Éjî¯äRþä·†ueu䩯NÞ{ÿÔøã£-^ëöyíú2,,sln†#{÷pM”(5åUœkt¡£Ja °nóƒD³ÑäS�ÅœïoèËÂF5ÂäLÄë—Wœà ™ËâAT¬­8P0)8xÀ™\k#ɀ˯-0úP‹ù=óÈ4›‚‰ÔY^F‰ÜÒ¢6›I$±Ø®E’úΕØØF™×j IDATõc0 šŠY»Ø¦½ÞåÐÔ>n96Á#û�ò£ûÎó�žæÕW_c}ÝÁÖ´þ‡V°ùÿ�…ßAL”íüËx1­¸Ûë01>|äØ±Ç¦NŸ~jå&:ZKÛQó3¨FLMϰ±Ñ¡Ûí–Œû¢à¦ß«Ís„³èAcØÄf%Ï›iý|Ï^.rH›ô•eB[oÚçŸåÎÓó%¿BÖ`,Ab�IpæÝÃ�œâ£Ÿþ(“·ìå*ßY_çÜ•ET!5†µµutªÃÔÈ+=笋qG9ÏÆg¯ö1Ô*kÁ¸ ÔÞ>Èç´·OWcÄ#4’&2hòÜî;‹Âú²®bckSA7îv‘à+Á"Œw6h ú¨@Ŭ·»ÌÆ–æ”�¬¹8Ö¢]Ë ±È ��…$A‹� ÖÅD]„Ñ}Ô¥çÚ4-tªI7I¼Óac_‹V«Åìeáã9ùɼpòß|ù‡¼úê묮®a ÿœ¶œ84_Qøµr¿ð+H1©™/…JêäÁª%±–FÜ ?è#Çñè'€ßÛbg‡Ò¶€Uý´ß¶,æcà???Ëùó fþP\,l¹õ~e°ÊSkÜ€,Á=Š”ÓE|ÀJ$�Éã’ûü h„� Êæ›ð:þôª<&ŸãžSwóÓŸyœéC·q9nð{Ëk\M3B�„f:6kÓ¯•£´{^¹t…ƒ{÷ry €=#1çÞ@ªÑÛb3óõ‚#©¦wî‚AˆÅ=ð†1Äb„X„†LBÔ¡;HHĺƒ” ] ¬¤‘~Õt/€Í,¬f/ab}ÃåQÁÝ5J<>ÂÕs]¦çb&öÇØs€IÍ?&êF�žá¨Î¡Hy þ› ƒÈõ¢f µÂÆ’EæL�8ÀÚ+I–ÚL.+Ÿ>ÈÝŸÚÏ·Ž¾Ê“Ïý€ .`­­aBŸ´uÍ/hmåÊý•D^Û×7^ãT¨ßï1:2ÆúFªšT~z‹Þ”¶"4:î;>;3ÏsÏ=—Þ ÄW„ºkUÐÓL™�©òB¹�["kËX£¨ý=Èd¿òú´ Vyí)ZË&¯ ÙƔܪسw7æç?Ë­'ïâ�F“o/®r©»†´Ä0¢d�1`%™¨œ[isËô:­ D„ö†ÒµJ"JG!%6^˜…¡‘ ½!J-Mƒs#LÖWej"Â&M#1´(Nëg–DjNXoaDµ %N”Év»¿±�‰ˆ›ô:}Ö–ÀÌDŒí‹è½£ñ‚í*÷¯h#6CbõŸóÖ”b�}ã\;»„ÆF{h"(1 }Æ�N]¸N¿ÝµÈÒ:óFøsïáž½øw¯þ OÿèyƒåÃ2?m¦ôÓ¼[~ãzqÄfG¬Õ+Ä*õú}¦'G²~ŠèIø¥¾”ܨכÑ{€üÌ$4FFF$úý~Q * ¾já(÷îMf˜ì†7¹5ÛÖëëË@ ×ù®šÿòB= —³u߀Á©~ßY×x³ÙàÓŸù�}öc,5ÇøêJ›³í1† 14ÓcÌ™=èçÆïpÍ&‰å™·.sï­Â�©i6”É–Û'Ñ! j*Ø&Õ¬Æ[<®O ƒD!�d‰…0Xw»üƦÇѾe¹=ÀZMu0ÁW�Óý V•ØÂL»�[ÃT°(ÍÑû&i_K01ôº «Ë0~¨…Y²hÇ9n.·ýÙ¦¼Xk¤¨…�&lˆ!Y·øo4ˆZdЅİx!bî�ÛYüÞè jkÑ+«Ü1Òà–�qêÀ!¾úÒ³¼ôòK©[°U­pȦ¯#Ð+ø %á.ãȦ á,.ÅŽ­U€Ö½÷.úÑ�8sƒ¨Ð{$wûnŽ��ÓN/eÍ>¤t)WQÛ…Z‚g„øüš~�;‘Y™0‡ŸÛÊ÷â»áƒò}+&y??(]~E¸çžãüÌÏÿ ‡NÜÁ/¬ðä;×° cF‹"’ƒ`8¢Ü Êc çwE¸¾ºÊm“Œ�74lˆ ’YM£óÖÅÔ4�$�DM,h’~!YÉ6ýˆ £#†(^¸Øc×X“û&Y;·Hߺ^‰·I[1®�Smñ÷–�Íɦ9J¿ß#JÝšnW¹|¡Ç¾#M:¯Zô+4ê�“�:w Ø„Æá)®ŸYv(ç�CpÁBµ –VèÌÍÓ:8O÷Â5l¿�Á¸>u•f{�GÆæ8ôè§ùÊÜ.¾óüó,,,ŸóP*?¯Ò]Ћʚ­Ä@¥§‡6¡P‘&¶OÇØžûœØ`�Ü0r—¿žŸ`m½�þÒìç¶\ñüoå{E^¿ï't2Õ^@WWÎGù5ŸTÿ’Ž©Ã[iy)LoFAÅ�%H«~”(nñs?ÿiúøO¡s3üÑâ O_^&B˜‰ còrä~µ³`ÒÑf‘õ¼°ƒ= mº�„kË A“ôe#›Ž]±n¥ÀíÿW"$Ý+à´¹·ž"4b¸¼>ÀXê+ͨÉm·LræÂrõwZGHãs)xLö:4’>êw;Џx�Âîc»XºÒ‡H°é¸Œ*�vº…æ®È½€óû�éŸ-(ºçåãªDã ÖºŠ¸úL¶«Óà7 ˆ+g¯³ëŽt}ƒÎåUTHëCÒÞ`~Cøâ±¹÷¶#ü«oý1oœ=ƒµ›S7LFÝò]\X¾+îc†s47%ü  qÔ O?mŸ»€?Ø´’Ð{·ÄÜ™Z™Œ��Ó^kûþ–3悚íÄ+i튚ö.À—¯é§ÁR‘À+ð gmã­�‚IKÖVÙD«&傚i>T¹õà-üâ_úyöÜy7oô„öj—kë=F#¥I”ZâÞ%É,sWgº!_5_¾ �%±0GŒŽŽðæ@‰Ti5”µ®¥åÝ!£Ä CK#Üá ÙþÿVd˜ˆ…½†kÝ„C³Q2 ² sS Zû´7Öa�¸×€Õ-Õĉ¥5;@æ�{&‰k×XÃx³E<9J³3+ØHO°‰ÂÀrõÌûïE:Š®i”ß=Z8¡Í@ÁZdÏ(+K]z ÆÔ¯Q’º’ΚMX}{�ñ¹IL2 su Å�†˜M7ž«k|òÁ»8qô8ÿô�~Ÿ§ž{–µÕµ _~ÉvéU–ï ü²½Â�$â(ÊZÑ;6­d ôÞ@å6/Ìccã\»~-Ó£‹ÔL…¯€\©—¬€p>ë݉ÀÀW /Q2÷S{+‚´ÖÀ’(Phö‡}õi�ðì“ás¿ø³˜]ûx~}€�­q:D&ÊÖÔ}~oöäKA麺I?A|Ç ½ÍH£Éîéi~Ø`D¹c´ÁÞVÄBÏm¤q[sM ’6í_K`*rË‹-ÓÝ@ÖÛtÚ«HÒçô+k,_¹Äò•+,.\¡³Ñ§ßíÐíwYßèÐÛèb=¸Zwf@«†8Ž1Æ7Œ4›4[MFFƘ™˜afzŽ]3»™�`tdœñ± F¤ÅJO˜;ØB¯&ØeÐÎ_ÂØ€��7ÙP¡·á7ߘdƒçfIcè®öˆGÆÙ7ƒ]^cÐéc%1Øô•ææÜ£c컼ÎöÄ/pp×>¾ò�opéÒ•ü9•„ß­×GŃbCV©ÿP–ÊÍÞ!T|'&OØcÍñ<њۇײ5zï«¢S¾CÍF“A¯— ªfFræ}øLdK"t¸"�­GgË�áuneäÖY�n™0ŸàPËnJÁw}•(âÏý…/ðèg?Å¥ÉIž^jÓU¸­Õ¤-†ñÑ&Û¬Ž�Êæ]ïgk¸#ÒûJl û§'x;QT-Ë^íôyh¢ÅB¿ë”½º`l…™X˜¡ÕïbWVظv�«W.óΙs\}ç׸víKË ¬­­gËcªáXË|ZtƒÂEl-dQ<";0Œ�µ˜Ÿa|b‚±ñ1¦§f8rÛí9p˜¹Æ43£ÓÌ5§™‰Ç‘žA;ºÎ‚�‰˜ž�µ~úÑŒTÛg±ƒ|ÙÐí+0t6`ªÁø‰¬ÄÆ™e$rÒ\éðÄþcìù¹iþå7¿Æ ¯¼È`�8Ð.<—\ÍßœðûÃy-~ JZµ€‘&(Q3H„Ñw¿9'ÜM­€pƒpy+oh=‡ñ¸©àkª$7õ3 €L‹ki µ£ËÈ¿² »öÌñ+¿öËLž¸“¯´-ç;ˆ#FØÛl€ ×{šF¸ÚŠ9>3ÉéÅUÂw,nù.s}‚±å¶?ˆ�{öÏqºgéˆÒ·n–æ"ˆ8„2yõ2_x™ï=ó,ç/^äìÙ³´Ûë…ý‚`$Ê,�@ìÀdñYÉþ¨^ùkþlÂÙ)ï~tõGérUÁ6–e-ÖZ–WXZXæÜ¹7yŽçø·ÑW˜ššavv–¹ùyî9v‚ƒó·³wj»Fç0ý:}´Ÿ‚� É�']6ÔDY>ßf÷ɽt¯­!+ë€2ºk]ë£.0�˜EÖ{Ü3:ÇßúÂ/ð/ææyêÙïïy¡^ø«Zýæ…¿¾Þ̆PE$ÊÛûPXȸïoE úňjÅâbø·ó1÷°æ/ð”vö«É…*­/�!¤Ö`‚Ý™Ö 4¿.·ƒÖ`ÏÞy~õo~ŽãË‹]û‰³~f‡Æ<³°A¤Bbáåö€Ïîžãíµëý~qƒMD«Š‘ ]8ŒŒŽñŽU¬*Ç vÛ>råK§ßà·¿ÿ4/¼ø"çÏ]À‹º×’n7·Q än¾óµðÂyˆ%] V!ˆ(¦ó‘ïçÈ4£ïlö¼”8|$_‰ IÚnú‚“ª;wqq‘ÅÅEΜyƒ<ýSSÓìÚ½‹Ý³û¸ÿÎ{9¼÷{çocL&°ë Q§ƒØžã›4(¨ê,˜•‹&ﺕ•gÏÐHb&5Þ;mL¿‡š(]ÅpOD:öE¯?þã#-þýw¾ÍúúZÎ7!ÏT4Qü«Â_ïf–ß—&ü‚³¦LŽÔˆ|@Ñq¯¯3 Óbš[ì€lgDt¾¼š´ŽÌÜ/Ö›ézï:ã›4Ÿ�[ÙCÍžMý Gº{Ï.~õoþUôØqþÕÕuÖ“|/ûLÃ0n„¾ÂrbÓõ{¡Ÿ(ß[îqÏþ9^xç:ëýAöæœoÛol ô?ªJÔˆ9>;‰6[Ü*†ã×h¿q†|÷)^záEΜ9‡ÕÜ×F¢Ì$7Q>wHâ^ã ô¾ t:þ#)™pÈ\^ÅÍ\"��µïA¤†Bꪸ–ÖHþN¤�ÅÄQúK£4°§Ø$Êêp|aYYYeyy•78ÃÓÏ~—]»v1?¿—»�œàøí'9¼û0Óñ,¶3@Ö;íbt€É•uº“3ŒÜE2è`×tàeÄBl�¸�4âôUeØþƒOžñV‹ßÿæ7X[YųÊ0­M¦õC‹ex5Yb~«¼ŠeÞó׃·c@#»’œ)BM?Ü ÈMñj Ð3¡æ à—MŸoïÍ1:Û±›µã�'0ûE Ï'ÿbS³×.¾ø7þ*É‘ã|ùJ›µD3AžiÄ…£“-^Xédfº·M®w6ÆFØ71ÆÅ•5º‰ukÙ©¶´Á<„VѾFƒSSt¯\áµ<ËמüÏýèGÁA+ê6¡àÞ!Ï£ÇI6n¡Ó�0…/ ‚!ŽÒ‡‘îÇÏ® ÒGñûô(xv]zZ©@{ðñ÷c}·Ë_Ôƒˆ³h8¤¯‹Å©„[îJ“2½kÇÚ„+W®rùòU^|ñ¦gþ�½{öp×Ñ“œ:ü‡÷eÒLC¯‡ô Fûl¬ô™<°‹‰éÉr1±Û±'Jl "=ÈÒ8�0ªÌZËßüÄ´¢&¿óä×X^ZÞáÏòݬð§ó’Å% µi#[ í¦d‚Lô2­^µÂÀ]¸wG2³Þ³qi˜¡Þ’€ŠKäëõåjýC*›ýãã|ñoüeì±c|éê:íÄ�!LĆ–�1ch÷•Nß’hðüS ÿÜJ�û¦&8(pza% e)ÎL6Mœ;±»Ñà®™qÆÚëüðwÿ€'¿þ$¯¾úzqû L$™–”ÀÌìv¹<‹G~nüˆúd´Üø–%A%B²g@îi&òAZ:'Ôþ©yUqûü”&¨º±«ÒïkZ¯¢ÖýQKƒZ‹еQ¶¡I%aue…•å^ý4ßœy’={öó詇x讇¸ëðQZ‰µ{Œ6cF§F!YÇøS‹U‘~‚$ :@º±JÔ&Œ[å‹wÝÀ¿ùÖ×YJßr­•X- ÿp(¬(lQø‹ ›ƒËÍÐ6,æº;ÛöEh‘1—¿v»tsW ¼9HŸ öx ·¼¶É‚Џ}ð�5€¯R‹ ×tÕ…�ÂÀÅD¿òk�øøüË«¬ô“ôEh˜4ƒL4Xê¸ÖµÄ&¬=}×Z.ö ûGG90ÑçâFl˜ˆ#îgf°Î›ßú._ûÃ?âì™s `Lœu+Ž$ÝåæÖ§76"ŒDÙ& (§9{Ùá ¹ÖiäV}É òs%ù&;òCUÈÀƒ±¦¹ù�tºå0õ|‹®ïªéÛ‹šZÍàݳî÷RQçÏ�Œ8ÈŒR·A4F‰H’Ü’[^^fii‰×_•¯îþ*‡á3÷?Î÷g|lžõkm÷íFèZ“ô0I$ÎZò±q€læÖ»üµ÷‰ðå'ÿˆ•¥¥M¸…!š?T)[~S¾÷>?l×ëÀ…È~Ñg 5¸ûm²;¦0Y�ÖÀáÆ @¾Dèë ¬—â�€€«7{`i½ÖòþÒϳûÔ}|y©Ïr/ɺ‹0ŨÀxlèZe±ïÆïÄÇ34�+�4#féí>k¶Ÿšt–»¦Æ¹Õ¸öÊ‹üöW¾ÊŸüè%Å×FlÜ8ŒI@…n/r–€�X�ŠÁH7Õô5ZâÔÿ÷Ì—ùN�õ䆜ÍO:ÈÊŠìé†ý=gÒ}Á ‚QEM�_]›6›+HPëêÒ ¨ºçÝëé$´ZNƒÇ‘‚8« I"DåÚõ®]¿Î�^z�}·ì籓òàmwq|þ‡ïC_éb16`Ôb’¢ èÀ�"±ŽscÃäj—¿r×}¬t:|å›_g=Ûîî¹¥¼\\O[1û7Á„ô!…ÖÁf lk´ AÀœ²�$)ãäqÒ›bð®€T\WVMYÏœ5 àÔza÷\æŽh0QÆOWqŠ3ë pÏ1ÛŸú(w~ê£|mC8¿ÖÍKŒ27k•‘¦a"2¼¹Ò&ŠL°ZDùÓ~/”3"Ü»oŽï\¸ÌTdxpf så¾ù•¯òõ¯ƒA?A0N›Ç‚;ÂŒzÝfj¸M1ˆôSP�Fn@æÆN6gþŒ-asA6~SR4ýó‘p%xÞ…YÍþMí¨9<¸C=v¥ý·ÞÀiÒM>�K~…53sC0(™½Ž$ø¥ì?°�Oþ¹Ïó}å¹åv¾F¯ÂlÓH7EØÕ4¼¶Ös~“ýJ¾R€f{ù5<ÕGSKgLB&+£o tè(»wÏñðç>Å3D¼¼²F¢ÂOÍ�óÌÂ:»ZqÖ7«B#F†ëÝ$;ÇÏ×™/§ùæ�ýØD“Ñ×_æKÿçÿÅ«/ŸF$¢¹}í�ŽE âØÛ-¦�‘#1ˆ;§Ï ½¤`(Þ� æ.O>r�RŠ&òÎj–¥P’£•q!´nnŠ'7Ó^¾?éW‰"“*ä4€¬š ¥’ï=q§«&¨Ú´[MT…^/Ýeè­‚ÈBº‚ @§½Á‹/<ÇÙsgøÃ£Çù³�ü4OÜv‚™nŸf_Kb +ÍÏl\á·û÷xí•Wh¯®ÖèÔc+©í0ïL@Jš*ç`_·l>}7AÛ±° ��ò÷A='œ&ëº�%ç;Õ¤ ¸ÙË=&—7&p(ÜÏ WUå§?ýq:{vóÇ—Vixm­Ãáñ&wO�°Ð�¤ïÓ'j966¹Õëé{òî”\'lüã7™j1vîu~ûýß9}ú¬[Ÿ—Œ¥×M?5õ�æwf>H¶ôHêåç)x™ 4°æs‘©Ñb–Så)�ïòmö³Ä̸ùžÜÈüϬ‘JZ‰Œ‰?6;(SÐ'ÞjpûŒñ–ˆ‹¨EmQq« 6¡5¢Ä±³’Ј�v›ž†·.œå�ï¾�_xàqÝu; ,/·¯óåï}Ÿ§_x�…«oaÒ˜Œ~n]¾› >Å„h~ÏÛ ýa[öB¬YB&ÀùæÿÐòµÞ"˜Ìª”4s�¶ÃM8äšÏûa‚¤Ñ~¾?®«9äªÊ¿\© {öîáècò­�>V„ËKË>¾k‚H„‹ëî¼Ã†ZFXì[º‰ÛQ–™ÿYßÈŽôºs¢ÅÌÛoòåÿíÿàôésıóï;�„(jEczî<9iºÓf2?´ì¥s¬ÍãGTâ‹ìg&ýZÌZQ¥ *,VÀ…’º—Ÿ4û0ó_*)Y5FcˆÒ€j=…îœPü eš.!Jª”Ü·T›¨1¶ëýf IDATôzŽgZ­�Ûl¤†$qà±¼¸Âw¿ûm^;ó�Þû{§§ùw?|Š+ϳ¾î¬4.RÐÖï^øË.Ѱ_Û§ù=më×�!àüh.Í?ÐãÎðAÁÔ‡”Ô䯂@Zs¸ó$ ÄåëÕž‰ý4gïÕÐ9„PóƒòÄg?ÆÆü ϼ³ˆ¤/•ÌE ¬Zζ{ìiÆôF,—×nm°n-—;ƒloÁý1Y¢°w$âXg•oþë/óò‹¯¥ëöJ·›¤j 0‘ÁH#îsX&]þÌßþÎAÅÉlY°$øW?$K¡,’…_šÛhE€¨ þ¥æ7ésö÷ nÅ0æBb ™ì…¥0vS¥d+R*SÜ;¯ê´¿jB$M¬Zz½Uhµâئñ°V¹òöÛüÛ+Wi�6èvz¸ÓŠâ<‰ºÃ^$ýaB*!+’Kõ¿tX½ï�¶g+°H¾ XAø [úчÌÈ®)¹UðÛ‡œæË—ÃØ@&øþá‡æ¦Ì#9‹øzææ¦¹ýáS|{£¸£«GLÄtÃ�¨òÖF—¦�µXî­Ó0ÂJßÒíP1¨q}ôÇp7 4#È>6ÑäÌïüO~ã»4bœs&¿óó£Èïä‹Ró>ÜTã…!þðß@È3Ó?\f˜‡€>£Ì÷/kÿ¢Vö�¹nd**ú½ ×kÌ‘ªöwûˆŒûF å2¥†H¾Õ9k)³ $}ÓPÓ}Þ‚¸Í>âv öz Ñj Ò¸JäV+t@g#ɬ±jË¥‘†—köª-æ-ÀG=”Dj»°`;^ÎÐÉz¡«Ûä“ µ�¹ÃÓ‹ �†U³Í)(¤R\Øö[²\zªÆ™ÅªkóþO1˜žä¥Å%·ÁF 3±ÁªÓ `ykÇõØü8Vyv©Ã®±&ÍHh™ˆ¦QFhâ^ei¢Ü>Ú¤qþ _ýƒ›j7¥×‹ˆbƒ‰D&Nµ¾I7õx@“tžêMòPø >{&ü90�çÊæ@Kùë}ÿ’ö÷šÔCK†,:„»‡«|“®px4®ÊÍVY<ä� Í÷5˜O?9$ 6Pµôz T•‘V‚ Þ±È@A${6îNpBOŒ-ô¥¾Ûå;á—šL9V—ê{ï0°MûrAM Çy© vú»h 1ÒÝ‚8S9Ü/_xߤ/�×Õ¥?ï7ûj9ñÀIÞ4î;lcư«Õ¢%±ûà†‰ˆMD$N£ß2³°1à€QF�c‰l‚IÔÍ�º7ݬ…9Ûçkø5®]»Ž`éõc¢(&Šú§>¿É+~†Øÿ\¬²Õ�Pøý~ eÂùÒðf!%' ~Áó«äÓa7RÜI?y�}¯lÏpHe Á�{Hno-J:S*é\+ªQºñȼÈÀ½o/ ljX�M[¡Ó1il¦ŸZl†LgW–@r{´Bs¥bCÒ‹V‚¼¾=6À¶ìÌ×ðs0pwJ;ý€º¨~äÚ?Û°’Y¡öÇ}6Ú·â5†„.0(›\šjÿ£G±ûøí¼¥ '&Ç˜Š›Œš¿פuiz‰rö�UšÚ¥;€¶º“zUgR "œh±zõ2ÏþðDœv1‘É„?r»Yð¯ôfïA°á”¾æÂŸ»ÂZZ-™þ›jÿŒ¯‹Eѯ¨rD˜(".ªE…\U6.3õfæ`ÉÕe=™oy†\¹�z³ýjÝ¥ÒÄ .Xˆ{,î%«‘‰œµ–À¹¶a›5B]ÈÞ±…_©˜S@Ú,Õ[õîÈ»¡í88ײÖûX© ›œmœP¤{Âo&µÓ2 #ÞÞ¼+»)7”„`ü̬µÜqçF§&HÚKìo4ha`úv@× =+ôz L7bÎ-.lDhߺƒ'Œ{ÛÞ­X9ŸÓû[ Þ|ú%®^¾L·EB 2ÍOúA‰Â»%aÝ\øµ$üÁøKÁ¹j}~fŠ�?MŸU6‰Ì{€Uxªj1é3¤¼cÐ µº³­¦ƒµÉ¡ð×H籜 ʦ滑¯¡;ðu¯‹1¨Á>_N2Íïbשe$e®ÑüR¹¨þRßNuðžÇóW鶇¶ém@È•­Óbµ›|ÊK{Y0/�\XÝf_oÆ,&óês¦-ÞwöŒ2œÓ¬Â­·äÛãrg�‰¨…µB¢B‚5)Fzî˜�àO.v!±ˆÁhÎ;êÏÞMzœó4]CEÓ'’†ŒLøÙºðÒë„ß�¹¹ÏÍíá�¿’˜´¹É¿5íoŒ Q,Y–t}*ü&”z\Ïäéø„Mr¥ui(—U d®ê¤G¨ ØôÐÑðyd1Äí-в°Jæri1¹ÈÍë+õ<Ûó0ŒJ–Å6xÛâd/ÿ¤Z¹ºÓ¯l „ùëAÀ qH5zö p¶û/ ÛÃM€ÂåÉ÷D-QdØ}èV.ö×™4`Ý:´zÓÚbÔÐWË�ñ×Ûúë¶›b°¶�±6;ÙǤí6$"ô¸té²ÛÍg"ŒQ÷R�÷3&}š?˜ƒŠðg…ó} ¤sŸÍ�Vµ¿Ï“ u*} ÿŠ˜ôc˜õåüÜí�Э ž‚ñlZw`‚ç¦t1£),Å%f<á]VIáyäæ7NÁ¥ËÅåÊ™ÜDó�©TŸ/‹ ¥+ÞÒ~¯´§£€æÑ¹ªà§ÿüø�tw_Z¡5àÑ<é*Xž²oÖ¥eò€Z¬*·:Àèô8ƒ„Ȥ§õªn#›�=/Ì7l¬ZÖz}'È(* ¬XŒvñL"Åz,-öÒOHõ²�}ž¼Èd ©Ãë„¿eá§ üZÒÚ¡�P¨­5 †|~%0JäwÅU98óô3S;Ì"¥¼õ”ÍN¥ká¼å7ÝÇJCú%ÅR¾â|Þœçr¥¦~ÙzIA»b5îF†?ÃÌþ '5Óî’ünÃ<=IÒW¡ýçÎßmC À «Š¤ÇA)ùÆo—Ý PÜ÷ï%´ ;£~øv@ò‰×xøj*Æ,»vÍ326N»{îs/››î)·*Ì7È@¹²Úw¯�’~É^5M’D‰è¡iàÈûú®¦'¹º/I¥ „¿0›)€Ü„ðg®Î&Â_l!»òªŠ>ØSPêИ2‘‹êûÕ‹Š×òw¸n1ŒÂ�„ ¡œ+|w¿²°Ð fº_‹Î ŠÔïî+[05Phþ à”+”ÚTB´ò? °ékÈCoж!œèÙ¤¨Á} ç³ÜÔüÿ˜{³&K’ì¾ïw<âî÷æV™µo]½LOOOwÏ §�f€h E�"ŒI£IF“éE_‚úzç‹h¢L&É´Q„D€$€ƒÁ,½/Õk­Y•{ÞýÞˆp׃»GxĽ™UÓ•”èÝY7÷sþçøñãÇËÒ$è@“ À”¸i6÷—'ÏìŒ_áEñÎìoãÎf¹Ûm‘Õ<ÖjÊÎý*4‘Ø-½kZèÏçÖàçóŠ›+V lèkûÎÑ\“ê:«k+ˆ¸íÒEÙk‹ªäߟÇWb~Ngþ¥ªå%á{òn«0¶+G” â˜(Š(y'.“þUC\ˆ á“KÅ¿gþê5 ¤ª ¶Oü­hmÙ8êµò°:‹2})¯••¼U­dù·å? X`µÙ,ÓdIJ–¤ùNÅ›Ÿ==;8�n)z©¼ö,×ò3Ç N J@§�g S¼#@†* .C«ÕvÛQj× 6”�¿¿® ç5îMˆ•—2(,�Ù…(Zšy]v¦]¶ÎoZ&pÓ‰‹’Ì ´EØfOdþ*ÇO÷WkS%«’Æ q£æ< ÒYʼÛ«’ñ¤9þJ­óo+skÑo¡üÏýoT!y}(±ò8>hŸeC�¼Ú¡`bI£Tᡚ787‹�ç59Aò Yš’&VÚ{ÃdËgÃüpPbÁ]OË£�ÐN:�c#ym �â�ÀÏÍÛë!_•Ø=ƒüeÚþg4�n›4¶Æ!¯Oäv±@Ј-£Ìæ8Hž×V@TŒ‘:LJ}F»#ö¼þæ›Ôj�À¹'T†O�úùÐ%—Ã#rãh•ùË…åäôV÷»uþ‰báUñ.DPQDT«Å‘ïÁRÏ/.ÎÄT5”Ú•gÄ?Yfz¯¾"ûf3ºÜÆ>•,î'0¿ã©ÌOŽm'=ü„KËÕ~Œ!K3Ò$#KS»sÑ’¼K'´ž!=»`B2%_ùã*T‰ÙþHQV.ü m ËðŽ�ƒ89ßJU’þ®ÚbÆ"UàAt.õ=c{°¸ÞiñÅÁ(7T*´ œàŸÓ§ìïïg>þÒ°zùe¾ý­×<§çßJý¼)‚f9©½ +ŠY`þ�~ÓçåHÐæ„Ìo‰q-.öÈsÎY%>¬x�dálQÛÈË(ù}ðL&B ñ£\ÈÉ3‡ÍYÒ@$̾ÁIJpk+ÜÍjàŸ@,Žé˜^¤r°<‡à]·>µüW0w‰ÖÕ<¼zx:˲ÌôÒ4Ÿ»/» /)×ãÆ)§Ù2ž6��  ‚ïõ½ ÇÄ^Oè&¿[2Úò‡¥÷~åËÁ@ aøW®¸a4šPÓ@Àü"MÆÅf‡džÑŸÎˆDœ„ò³’úý#vYäw€PK¥žJ2ßÿ,ƒÍoñ÷þëÿŠþàûÔë5üÚßïe©ï[ ð›È™ßjð™ß,2¿±í£"EÇHT0AYë(˜?¯•ó€i —ßE…µœ|¡ÚT¨+S,Ñ6•1¹ [.ÇWW¯ Á˜yQrª@òÚïðvŸ2sKõ»ó”Ù'¬šÎ Kµ3èéñIø¯,/Àð„V\ºÎá—Ogâà ''Â\euòÍøW™K,[‡@àÉÜ’à`hàKXo@’ð/¯Z`€í‡;D‰¦ENªÛ2›±"2†ù<%#+ „brI?:æ7¥¿¬6!eR4‘ØÕñVÆîì¯ÿí?à?ù‡Ÿ—¾v‹ÈM§�Eûå,¼TMО…¸x"óED5ë½òrù-^$‡R.<*˜¿|;�ü%�Ä{™›U”ûFWË ž\Êüf!_q[|£÷½šÔ¥ÄðEeø m!êév2ÅR¥Öš,ÍÐYŠñN•|KuüÐÀ²1ø‘!„<[:£iÀ2ÃÁj4/<#»ç $p%˜Ê¹ËŸç 5_ ©t�e`1ÁTc^µ2 ˆû}¸½Íà¨Ï�ö†í0,s·¢ˆ�¸Åƒã±óXT³ýþû;^òkBç!CÂÃùÏK~Ûþ›Þú$ã­Ïz´_þU~ëþ—üþ?øn=úÒz;E.#ž`ì+.¸f9…ùEˆT0Æ7a»U˜?@……q¿?—2Úç‹x|ECÆw}¿ˆÆïtý"oXvÕß YÜ3ˆ ¤¤äe˜à8hŸJùKM ÏÅ¥šmÈRç¬ãÝt+U\¢Ÿœð9�ÿò?¥y†t!ÁÄÍù:©Ÿ«iâÔûS[•Îøöó„n¼Ô V¢récɪaeßrʱJF�g¹(¿éëD <º¿Ë‹WÖéÆ1Ã4%V1kQ�½ÁܰÀ® °åq°»‹…Fc´Xð0`Œ�% ãt‡Ýéœï|Ã>tâh(¼óQ�îæ*·¾ý~û¥×8øò6·ö >¾ý)“ñh ƒ–þ)1ûÐxVsœï\´ó ùJeW­ŠR”·x¯Âü¹»Ì¾%»MÞRtÅRpó`Q–æeM"¬PYNK©Ã+šç¯UV–0—gh /a´FkM±lx9[Và¢\×%ZMà †3úçél¶3~nV—#{)"…\)šªcDɩͯն,^š ƒÀ÷¿lð ’תÚaxP$”#–»ŸÜcý¥-®­¯ðñpȸÜ\áÇÛÛ68§±’K#±»»‹Ý° ""j±"ެkl]Õ £t„È6©^!–ke:[Vÿ É;C{M¸úÊwùî ¯òÆÎ#î¾÷w?ÿœ»wï1Ÿ'K¤pø�¦ô99눊ˆ"´Ë"óWQ¦ÂƒÅA~¯bkC…-íê\’àáš�Ê7U_\âɼþ [žôÉ™¿ÈoÊ7ËÒµT…SÔj)¾Óhc‹–ÖáÌ_¶“˜ñeOàj7T<»P 6�Ñæ nQޱÌjWåyÍ hi–/þ¡ª �1<¾˜bª,h0U_±¥Xê¹Å9»·?úˆWã†L¹Øë«:÷ö�QÊJuqqûƃ1õÙ˜ëëkÄq”/ó%he5� A‹Požãxg�„É’9Mý¼¯^‰u& Û|8L‰Zš‹[W¹ú;×¹92ÞÝæáûïñèÁ}ÜÈ`8¬€\”AË8_}}§ÂüÕ¦( ˜¨Ü~'1y‚Ïõš©2±c³Pbp¶DI–0gEÒã§ ¥‚.w¸È'wýf�Ïk¿ä‚«Ú;i_¡ôY½~BÉ jU°`¨ÚMRpà þ<�YTà\ÒxR{M äu&ù�À^:MÈa PG%¸æÎK` ¦BZö^±B 4v/j>|ÿ6³Ã »ó1jç¹²±Åƒñ€KÝ.ˆeðÑhL¦&Ô7šdbu�Œ””ŒTf™f–šüo® ‡i¤?¢×xŸ Í”¦y©ìÉ€�d1zÜãÞ4ãËxH«³yþ:W/?ÇsÉ”ä考»_ðèÓÏØ;Øeww‡ñhJèÞ«¢ æð—1><8�ù4™?샠�à ۜ�ƒ°KSia%J/†¥"ñž‹'rEþ¾€ ?/™—1¿_�§Ó¢æªDThgN`þŠ*"K²”€‹œtýæÙ!áLâ`Œ³¼ã©ÅI›Ã/f(9²È2mÀ/ TÈØòí%•·ÔÒ!Bq¡¤|yIfg lÑÃј/?üœk¿þ2ƒÑ�蜡ÙfiŠ6šÃþ€�ã]f™aše$žÑµ!Õ�jÈŒ8;�3E}m�é<á|»I¦ðóÇy}ã{ĪYhùy$‘^%�ÁÝñˆ4Q“Œó½ó¬~û"_ãMâÙ”8›°ûÙ—Üÿä}úýƒãûÇÇh�º=Ií?�ùs&(FÈxaL^h‚åï äCøtéÃ�(¨0¿à½ÆÊïÖ†T9Ú»†çhSË2^ tˆàK,½šL£+®¹‹ETµ�*&Ii¸VŽ,þæ ­¼ì(œ¼<RŸ:�Ñ'½MNÁ†$N8$ðyƒ9¨çŽ0•±¤û'ŒX“ãç20pe„)´¬Û‰€9"Š�Þ{ŸÿÊ×I7jè#�p0òp�GÛ;dyh°ÈVDæ¢ÌF.®ŸAÈŒ]”¦2m¸|õ2­Ùœ�p¬güìø_ò�ÕoÓ�.•\&Tµ Õ¥ÙžŽx0™`²[�:¿ñÍ[Lo~ƒ×ëwQƒéè˜ÑÞÇ÷î²÷sŽŽúôûÇöÉLZê°B §¶ Ç­Jƒ•!ïô¢…ƒ>/¾#oc©<ȯR¾ò?,Jæ²<ÏïœÀG%ØX’Ç»ô†·¬? üg²J…UõuSú)¹æ¶‡Ea•:yÜò™ Ë}ÿ¥òûÕÓ… ˜Ø³¼[8’‡ò %O® xí`Ù“ Øb+o ”ÀÀÖ¡h·ê� 8ÏOñöÛïñ½;?äÖ�Wx§¿ËF½Å1¿xø€HÕP‚[öc0Æn‰ #®íöThe C#ޏuý¶}@¬`’Îxëð/xuãÝèkÄQ¯ÜŸ!ù¼q»ÞÕe˜©Œ?ÙNékMZq›ö¹.Íó×8÷êw8Ÿd<×Ð<~ôˆþöcŽw±w÷KƃÃÑ�ápÄt2a4/aþrk-cþp"-¯nIê]ØŸa©á«¤èXß{x�ŧNPI<@ˆ×üCp„“‚´¬_¾ßàUÔ¯€‚埞ž(�OÇ¢òTçøMþOqîÕªgçÿ3ÚDÜŸŸq,_è—á�Sô‘~?�j× @‚ö(kùe*RÈÇ�y^ß­~Kn� ÿî_ý)/~÷¦fÊçÇG¬&­͋|q°ërƒ]m¦í ±sÍÚØh€":Ÿ²4¢©E/ŸßàOî?¦q~‹´?$=>FkÃ÷ùõ«3noG\Þz�F£µ TÁÀþ †˜ñb¥0ô•æx®‘H)«†k5^yáy²óשgš«Y‚�HÆÆÇGŒ;p¸w‡ÉdÌd2a6›2�N™Û½µz»Êü¶nÆi€¶¢â¯…�²øTÐ%!Ñ{É»Dõöß§•ÃÆùb+ åú­Ét†ÎB)i‹¦ò\p¶„ùOLOÉüöõa]—}d¹~g±4øìv¶Ðd»8`è|Ì–káíÓ!Ÿâþ_‚b髺YÉJ-–pÃÛï¼Å§?û€ó¯_äßnߦ[ëðýkϳÝ?`žj§ë…6ÅêAEäv“±ûË5cE3®±?£â•ªÙ"9Øc6KùÅÞ¯žkñ§·ÿ'._xƒËçnÑl´ËŒï+º ìOx’ ™>¥Œ´a½ãT3Nl Ò¸µB½³N|þ_{�M~ØTEJhÇ04šaÄ`bm JgÄ$ÑœkDŠð±®3Ù¸HÝ@MAM„M—" Ó)j:!6CæýÃÃC&{Œvvlï0�L™ÏgL'Æ“išæ½P®¸;2Á01è¯êCËüäOÒID¢â~EêjmÇ÷h]%Ÿ·Âü¢«*Nþ³¤JxAS*e󟔜Ñri$ƒC§÷y9½È§Mg0 HáÒ™šwÖmȧ…*Âe@àÆtù¢4®,:¦ 2P¢òË‹*¥^Û�<´‚ù,âÝ÷ßâ¹?{Žÿêë·lyiãWÖxÜ?·9v]€ ®}½�· ½z�ÄC»ë$ˆÝðÄ mh­ÕUh÷x8à;›kÌÓŒ/öØë ƒ]Z�6›ëçÙÚ¼L£h¿$ä#ß¹û­ Dû)Œ�æH¬#å,#–« É ^oÐÛlÓ¨�#FØ»ŠN!�̸lfl?xÄÑã=fGG$ƒ»_Þãø`ŸÙdÂdÚæÞñøÎŒ‡†Ç}’ùÜwPA[ƒº¢ú¶¯ýŒ�1Þz:Ï!Ñw¼Œ�Â’ËÌ_½[9ZTb‚šž §Ì¿lE™ùÃòü¹ ò>[:CO@N.��q(bœÊ_YÀ³ ”íØP#S6 ºT64+J¥%&ÒbH`د´¥Ú=ì´XgžO?ýœý?ü ~÷ý-Ô‹/óÉá#zÍ—e‹I2g4ÏœÕ_9£ `D£�­ö¢}b1vøb¼Èg ¬ö)×ý!Y·ÃoÿÊküï?¿Mb A3:"ÆÐ¬Åè¸ÁÑшádÌÞÁcâ(¢ÓéÐêôh·[4:mò½òv DOþ¸`x, p`PÊc¯)m·Oo& ÆB¤AíZ¯‘ 4Z°Õ1Dm¡Þƒ¨eˆLŒ¬sMû2.\À|ã|çG¿ÉèxÈÁãGìßÀƒÏ?çþç·18>¤ ‹¾�ƒ�€N5Y–•sTŒ‹e¥rg>ó‡ä´PÞÂxÅýVJY SY8< ªÎB 8G oìóÓ€n~ƒÍ«·hu{dYÂ|>'™N-¯xpuíé7)1ÿ‚´�Ëž}OÚY¥RIBå~ñÆ ™åýSRÆLp;,_ò@e ¼°²ºÎ ”_}¼ûùÃ3¤3ˆw—P±¼šÏÎø¹Zã® H1T€bh�µ, BŽæ�vÜ´‡²Üèëç#¹ø¼VÀ_ÄnùGü¯éŽùáßù]š¯lðÉp‡ï¬]a6fâÖ:™†d”°µy0`tŠà6uNBùt¡ÿÛ/�`j’,ã';ÇüÊóWø“ï2J¼~µÃ{ý”L)j+«Ð[C0d³ Ùd„žŽÑó)~‹òX VB¬ n2êãñtL|)ÂÕ•Ýv“s!‰kDÍ&ªÞB¢z ,jœ¦„×}>–ÜsåÖ&Bs£îÕPi/c¶¦™ŸËH{�eB3‚®Ši÷nòÊ«×ùú+? ßÄýûŸòù‡?åáŸÒßß³`0ÐT$÷¢<�œŽ—+Ø'ª’îÒ$³*˜?LKkÖÁ·y¥N²ä±¯šÎd€3˜üÜEg—@Âç›98vó@à8<ûåžÇ=ïI…ã3ÊC5o‘„ÊññË-æ¡Ä¸wY,Š”‰™Í ^ÏP‘ð“¿üýþ�ßüOÿ:׿u…íɘ¯¯\â­Ã{nÄaz ¾~þ&ÿë—who®“ŒgÌÇ3Ä3¸=1Ú¹+0ö^&1±2|¼sÌÕ[yþâÓɘ“‡ hÕEËÜõ8¢ÑèRßX¡¡  q:GÏ&�Ì0Ó1:IòhF‘ûF­ Qf˜ì�ï�ˆk¦!Ìp›œ×DQƒ¨Ö$ŽÔâuÕ$ŠšµBj=Ã0¡zOihFtbÔ§5Íh3¡s&�¦-Q;w�õµ+|ýko²¿ó÷îÜæƒ÷þ’ý÷•ú×òõéÌŸ«ÌŸ ¡Bå¿�h\ÊÇRaþ ¦ ¿œs¤R^yõ�MÞ©u =•t6A°žo¢ËŸ$%aÀÀ9¸Æ)i¾r!Ô Ëšâ (‚„? Nn,�BSAPD )F,4ê))>þèÿäŸò¿ó;\úÑ7è\]ãrk•G“™É¸Ñ>Çgýc$êݵn‹z ÉhÊ|4Ǹà‚]C€�ÌXøó‹‘ЉŠwö¼q~�çW.óù8c“1½v›f½MM¬Ê‹!!ÂØðW�:mk7†Ù,a23�NN­‹¯Ò)‘’‰¡�¢¥ÌSØM§h™’ȱkÉ#a)U£5©E Q‹†jÒ ECÚ4©W@á€8íž;V3X{ ÈýŒk‘f¸f8>'$E ÁhEB�k^àÚ¹«¼ñ�7ùòá§|ðÞO¹÷ÙÇ ï¢MºÄxXþ=I²Ì0§¿¬k~*ŸÞ·°9 °–ËtWãpá Ä?gµÀ«îž1:ù8ö´ å°_ ¹t)¦m‚&Î×¥šJã…ÃJT€BQÇå*ž+Çi'¢<Ù[7ºÙ<¢Qψjƒ‡;ü�ÿôŸñ«Ÿ�7ÿã_çÕï¼€æ.÷†Ç\h÷øéþs� •÷Ú¨^�@6™ÁÌîEE15S�bjQLM)»ØYf8רsu}•$š�fšzvLÝD(Õ Ë2£Ì�C’2í£͡ڨNéBÛÀjCøf'âÇwŽÙˆç˜é==ÆdÎ{ÏOáº*´:Ð:afRæé�±kjXmÄdbØîgtã�¬IOz¬Ç«lÈ*bjf~ÙB;º1ÔRÃÆnÆæNƬi8^‹9h׉HÍúD¬6"^¹ö/]ý:wwïññ§oqû�_p´ý“&eµ9ï|)è/à³"_Eú-TÉRh®þ™el*EÎE?˜¥¿ÅiñìIÛ_.��'`Ñ–ö’q�q„¾Œ&èlþÂ8²L+^äÊ++<˜â¹òÑ’Û~‘‰Xµ•z)˜˜ÙõŒ8’yÆŸü›?áþ—wøþïý&¯üð ^<‘�G†éŒVQ“ÕˆÄÇ*"–ˆˆÈ®èN4LgÈdŠÌ3k3˜[Ç›,3Ì3ÍœŒíºÐŸ¦OöÇ3P}�ËDª¸À—âãUŠSõqþ ž¡ì_ ×V›gÐÛZC (9O¤Ç�Î0YB6OÐ铦d©=Î�uŒ×Æ(�¯µj¼½wÈLkÆó±�º$nõº¬ol¢“6­y‹î¼C/iÑ�·‰‰*��WÍiƯÿ7´&íÉŒK2à¨Sgw½Í´]G+C-64L�—/¼È­Í[|óå7yû½sûýŸÑßÞ¶{µç ¹� ‰`9¥xÕÜ�™“å~>” JYdÓ`1SIS]|wÐÌ废‘ô‡3›$@€Bz[Û@ñµE8¿`hºø¹óBf‹;‚{¥F Çø†µÃ’¦« ¿í`«R£”«_:f:·Ã)´¾¸s—{ÿä¿ãÕ÷ ~ã÷ÿ*/çëÔ{uFÙ”ÈÖrm K“¢3D$ц¹¦QÌDiÆã)“þ�ùÌJöZTãV£Î~ð9 øîË/ðÿôÇ4"a:xD§w ÕÝB¦B åmDòð$Óh+^X¯ó'wÆöÓ�m™Œ&q¬QQDÜh*¿xeØ`Ò“&è$A§)Y:'™'t#ÃþtFš‚U €A'†Ï޼R‹Q�”ÃzßÒ„�È@{ÞfuÖa}Öc}ÚemÚÉ™~9hlÄgÍfÄÖqŸa»Æã�ÃU»0K)EÅók7¹ôkyíëoòó÷þ‚O?øãÇ�¬‡`àPáE(}Aqc‘¦–RÈüK³#üœùÃTuÒàIS<Òà૤3ˆäÞH¥RÅuÀ.l Ÿ¨ ¼»c¸NSbÝjè/›£¬gIÌ¡¨cñžÓÎ 1œV"¢mP )5æNe�zÓÄðÖÛ¿àÓÏ?å�7¾Å›¿ý=nÞ¼Ä NÙM†Œ“Œyf˜e0Ï ‰2m£e(´Q¶íZ-jí.Ñ<%šLi¦šs½ŸÝþ I ÏmmðÊf�ÛC a4~D»}‰8ªј‚¦÷qŒ$‚fOñʹŸìÎs dĹ%«˜L7‰™�ωwO¬\VµR¯‘±´�¯m¶xÿ�fûÒÌîy7‘Φèù Ü;p=Šè´Úôµ5HfÀ¨6fT›°ÝÝCi!Ò¹´Ã…i›Î Åú´E;G+~»vëTå�ae4am8dÔŒy¸Õ`Ðk¡”�~\1-ºëÏqëG×yð½_ãŸÿ_ÿ Û·?b>ì;Ú´íPõÆ+4Ê †»e¤s²¦^ §O’üËŸ 2§åþåÒ³ûœ»ö�ýñÕË×¹÷àž×ü‹äv(_¯4X0n*¾ªf͟ȱ0Wá—#©T~ONá3Þ‡~çB†“¦Å*ªÅ cI’r÷î—¼ÿó÷ÙýâubV[=T£Æñ¦«c.5{¬¯­ÇÂ,Óè`$hŸâ]±(žÛèòãǘV‹¨Ý!©×8ê�yíÒ9ŽfóLƒÉHÓ1q½WDÁÎ>5:Šn/"n´ëLdžÝq†ö‚ Ê‚€˜,¯—5õd™ÁÀ¹v�©I¹?™3@^óÈ2û\$DQ�4®Ñê´yåæuô¹M:+«Ô[-âZlµ�,C ¬Åƒ¡ažL&Ìæšc™q?s»6d;š2MÝX£¦˜Ì�€ÛÏ1I¸xxLk6gÐj�©ˆ­«unvLS5Ù\¿Äú•çHbÃxxH6›/Ò€û†ðû—q¿§Wk2–â? Žƒ;Tó•®THÛóNÅ�³²€ðhç³ÿ€àòuî?¼WÜôñþ–"bȨa¦-eÙ#9Ñ–Ë %¸GR~xYUN8§óù§•(¢8"ŠbD2�iªˆ"».@ÜZ išñxç¾ý!oÉøÞëq‹ ½uV»]”†&Xðd‰!5†7.mòóÝ=¦s±;ÉFŠC#Ü8·F{m�‘æI:Cëµz'çj¥ ³ªh4ýÔ"\®×� ‡“ÌOM/¶±‹�d%£Î™ÝÿSà­Ð­ÇtëŠO�†ŒçiÜ>O¦³\ì¼IšQÃÅ^—aÑh6iv{t××émn±²²Â¥v—ݱ`�ëU�©hvUÊçñŒ/¢„±²`Ð5eÍ ;�piŸz[¸Õè�Œ†k�5.^»…îµéöH†£�¸¨2àÉPf_Y²KÏI4)Ë(0¤ËâJª�R¤ÜÐy·ÿÿ€sWÿ±8±såò5x¨8RœRº¿È¨Rº\Õ*ÔWYuzòåB*«8BÅŽA\=E2D2²ÌA­fǨJJ7¾7õ�¹ûå]n¿û!{Ÿ~ÉüÞ>="¶êÖz+D*"ÑV3¨Gkí&w#Žç3Ámí"Üï�ynµÃú¹s6zH³‰1élD­Ö¦Öˆè­EÄ‘W[…�FDÏDÜ;Jì’ÙJS–¨Sì7*“”yB(1y]):MÅíã!*ÐÎü�ÉÊZ„�ãÉŒ½6YT# Dz—»-¦imztçèvש·ÚDQ„É2»!‡ß•bØ� Ÿ×4_(Ã4ºM�"&#"£wxLoÿ�í¸É<Žl_mšl®_¦uî<û£CÒ¡�õàÙPÿ. A¶0ÇÒP•@)›JOUè]–çñÿ­¬n08>Îý6¶ÿþøêå<ؾw.A9—Z¸¿Ð¼^ª+\{‡® “5'Ãô©—”øýô¶¹ 5¼º—5²LHS!®9‹µ(Tä]¤…4�³·wÀçŸ}Ægï}ÄîÇŸ3¹·MO ›QƒÕV›¯mmÒOç¼·¿�Ÿóõ š4Õlµ›4[MŽ2E­ÓA:-L¤iwb"Ϭb]�ÏÕb¢D¸?H‰””°Ôÿz·¶»Ã½�Š>%vxqk£ÍOwl¨4/o7‘ܯ Ô"!5šãÉ”—×{ ŒäžrÂEóp?#cm*¢^kÐêôè®nÒî¬P‹Š,›—úz&°«à#%<¨Çt☕dŽBÓžÏyapH&Â~£•שI�õî&+®rœŽ˜ö÷1i~Éò�Îü•›Ë¤œáòL‹s%ú=%­¬m0ôò\ºÊƒí' X›ìͲ3S—h KZ'WΤÂî²ä/¼Yˆ%õU"DQ„Š¢ “)çwc4X4s5² ÒT¨ÕÀ QÊØr|(jQ$éŒÃÃCî~y‡Oß}—‡}Äáû·ïî!³” ëíÝZ�HEdYJŠ#MçdiÊë[«ì$†D‹Ýû/Š˜iÃ8ÓÌ2È04•ðb§ÁíÝ9&ÿ5e@�AEH>(·y«Ѫ+>=•§ª©è£ÿøv A`f45£Yk·˜+ Ÿë1ÃcÃàÐÚ|œiïd€HÕ¨7Ú´;kôV7i4ì°'KçD ¢j5!�…5ÃÞùºÖ¤=�ÒÌR®ŒûlÌÇ<ì¬�9õÝ º¬]¼Æq6c¼÷8·_@…ÿs–E’ éP‚¬*¼Op?8÷ýñä$¬­¯Ó?>̯<+œQ@@¤Ø–Û3ØÒ¯ ¶cæ6‹¼¦œÓ9”÷†·Í—笑tõYRÉü§r:L–ñ]P’’÷€•€>�DÙ ˜öº€$SC$bž¸�bMJ³¡‘Ø`t²,r¨o˜Ïç<|øˆ‡·y÷ý÷étZ¬­m°ººÊÚ¥Ë\¸v… kk˜Õ5F­&£D˜ÎÞ½·Í·®_åLJÅþ�~ñS‚&K…vd8eÜ'´cEC •AÀOúcŸtÔBéaÉN‘hÍÍ•.¿Ø?$5¿r ÛM¹Ð cà{ï¢3øpÿˆ_m5éõV8¨gÂqß0K5v£v瞬¬6‹Å‹P!V1ñÚ ‘¬ Z3™ŒûL&L¦©7b’ºáߎG$ÝU^‹#^?zÌõá!ë³!ÿêÒ‹ âC¬j\o]Ä|ë·øy¤xøöOÐÓYe">Ô„ ßÓ_�Ûu!(Z;”þÆiip’«zHÙO7¼ýåÒÙ€¯™ ™wÊõ/æësâXÈT^¾,SAN)5ouà¶0‘SêM§•(AEQÎÜË7¾ôÙƒ®ñv£ˆEc°‘i´ÑSCg5fsFÓhØ�'âØ`ŒRØXþ]ãñ”Ñè!<@>|ŸZ-fee�••º«kt.]aãü&je�v³Îw{lg !Ñ03��÷VZüù—R£¤†‘€Ê ¡"êJhE–�힦Xsa@‘Ò$ffí@¯^£Ÿ%ŒÓÔFVÅ3>œqâÏ„±ø:ØPêöøƒ�}ž3ðüú㘥šnSQS–ákʨ±K«ùëÜ@nÀ˜ˆNw…¶^!I4ƒÃC¦£}†:!jÕöûüùXññÖ ^NÇü•½ûü�»ïðo.½ÈÃÖ†[E)\‰7ˆ¾ù›üTk¶ßù é4!ß³Àû©,¥‡@ͬк)�Uˆ(¤ß˜Û’Úâ°í¬ÒÄÏÌËdªµ H)—ý·`r�Êô¨)=ã½ ß@³! .?ÑãúWEQ¾…¶1†ÓšÚ+�ù”Ê$B»�‘Q“¡D£uc„$§.æžñ;)GhÜÎjš$ÉØÛßgoÏÖ÷­ŸQ«Õév{|Ö[¡Ýî°rñ2Ý+—énl²±º�¬­Ó=·�Ì4+Jˆ£ˆC†!30Ë2fZf6p3R4D¨)·£ƒ¸KÒ Ó‘$dưթ³3žp4KˆœÚ`\#潨ATd·Î†Â�¦ÀІãYÂönŸ›õ.ë­6“ÔPS–Ùs)¶?Rm�š2m0è|DƒN#¨Ì‚CÔÚàÖåMÞ¾³ÏH¸z]øäö!»�0[ÛàË›ßäõÇüèáGüøü->ë]´–w%\¬oðí×~ƒŸÎ'çcZFŒQ(•¢µ±’T×ÐF˜Ï#Œ14›.ˆ¥Óa¬ÙÁ…¹6‚õ^59£�&IR988°¯þè} Ðl´h·;´:mêõ&owº´6ÎÓ>�Æê:µî*µî ¦½ÝÔêdØi»©X@PJh(?\0dª�1šN¬IŒæ`6³ßæ‡D¶¢è|8àBÀø‚V)Ö\˜Ä0œ¥L/iÚmC2·›¬¦L Y hFÌT*”øø„8  ºb ͆b†A×z´7{´: Ïé;ÜùìÇGûÌg3~rþ2Ÿ¬lñƒí�if ¬]WÎ¥ú9¾ýÆo3™ŒØ¿ýqî]¦­àÃÜ¡*ßÉ©¯š$Ð:O¦2YJ÷•õÀÏœÎh_ÿ�'âP1_–×p²�À?'T~Z‹¼Pòòºùƒp˜¦*RH.ÅN,ø”)¤òÕxœ\Ô–BŒñ1S§i4˜Ïµ;¶á­Œ�F#£ƒí*[V–E®|�¿Ï�!Æ0uË~9ØË×5ˆ{o½Ù¤ÙlÓh5©×Ô Zkçèm]¤¾qŽÆÊ­î*q§‡tW�Î ‰QÔ”BT�Õ&$ÙœGÙûzÛ¨B1ZÊ!Ôƒ6�!L {€I@&Bg¥Æ±Ô8&ˆ��iFìJ�œÀÈãž*¬k6‚DÆnÀhŠVPÊ�eÂÚªðñn’×i{Tã[¯¾Œ’o?b<è“=¼‡¹x…~ýu¾vôˆúÛ|ØÜ°ë$âbëßzíGüdpÌ`û~ó˜ ÃK‡ t¾0¦wšjeª{9µªÄò7.÷ü*é쌀à¤Áø<ü¼ò§š€ër0XÚ×–ŽªÃùù6T#lR�‘o±SŸ ùªWÕLŠÑŸ ¢·ŠR(ã½ØJ͘¥Œ;®¹_H…qËb- ª¨µhòI†Èmsåô-c7±Lª�ùtÎ|:‡#S¬Ñp ¥”¢ÞlÒh´©µÔë í«—®°vù2ÝõsìŸßDµjÔ§µViÔÐÆ)Œ{WnÈ5¤B@ø–Ñ©AÆ ­ ߸¶ÉÛý |«É ÑÌ2Þ>‘38¸ ªn7J16Þ’1ùzˆf]˜jÃ$ÑöžÃÉ�v2®ß§¡<œu_IN&|zK IDATxnùH-Ô;–Õ¹<.<-ò`‘=KÆn)æ‘‘µÅ;¢÷¹áêm­éI90PAE³‘æj¿`™;Š­(´39Yfœ}Âq¡AÕ‚M:OÎ�1ÇÇŧ}ôJÅ4:mÚ�õv—ÎÆ«7®ÑÚºHce…úê*j¥‡R†$S0µŽQ*RÜ:¿Î½R7LØgœoÆl´"&™5üæoíšÏ†S3ÖÑÓŽ@£Sm˜¦šb&ßj  ÷ö3®¬¶Øºîô©7;l5Z �QÆ‚œÉ2Z‚Š„ËíóüàG�Ç÷>gøx·0øçíã™VgÊ΄ˆPÚi¸qK…d { |MÁUF›RþÓAâ—KgÄÖXWê b04ï�¤öFÃ'å­”VL@E*pæY†Á'³n^ÎÂ#UYÿ´©øãËv¼%O~›³�ùq„`H1N2§-`êVývUJ³&õà /õm�†WûmlXs�Èç‰ Ÿ V{Àµ6 &·› Z§L¦šœÏ€Ÿþ…N´º4z=Ú뫬ßz‘Þæešë4zkl®¯0$bìLF ±>:šñõµk�ˆ½If×øKalÌ1 /0ìP 5ÂfG15šý©¦¦lHreLî ¤ L„­Vƒ­ MövL*¬¬m’Φ¤¤ö; vÇ'Ö×»¬¬žã…o¾ÉûûHšÙ¥à" £Bæ/4•¼§•×% Ð_ )c3ªD)ðýú)H‰ IáÞP¸qc•�?ÜÏg*D)HìT¢Ž„µõc]G—¶nqó•oÓüGdY²0 WÖ ÃÏ?�Ö–x÷™�o-³D{gÅþg¨�ÈÅöÝ>Ç’f©H=‹t>Æyª�,òŒ�ÖsS{^}.-§|–ÁSà!· ™{ç§ôwv�Ö[nÿÌŸ*ÁN7ö-ßÝÀT~Ï&�¡�²¤ ÇB!9žÚéu|BZpðyê©2;T:LžT¿%ÝkÄ)âR€©YÌkŒ•¦Ö}Vò—Ih> DKî®”c²rŒ]†×"·½ÆÍé+¯ùù‡Ý½S#¬MÂ`¤bý¬×cd«%øaƒq�]²¬èÓd쾕—$ùTdRÜ?+asˆW-Œc¼�! ¼ F7eHÒbÖ¡Ù´3Ö›/&Ë|£Æ÷ïñÞÿüÏxøÎÏÈþöÆÅ—¾É,«S‹”ƒ¡ÂIHrú´vÑö\;Ù$ ’L³3Tlµܸ‘BTãh,4šBŒÛhU ±ŠI;®?÷"þì'¤³»‰ì’Î ZñI÷Ëí]zòô'–íøK¦3Xì᪘†‚“êªýå�+�ù ¿‹´VåÏAKJ>éÊËœ8D“rNÉú¤·/f©:!gˆ ¥|¦X"KÑÆZ+/ds³D Z‚–NS)3õ1m™¿P*ò²rY$Á¯g~�R”&1£èæhF«,_'aLc4i"hc�ŸšMcƒ©«v¤™ÂÌSöÞŸ?Üùoyî¿Ås?ü=ºë›ˆ›yÐÊZó½–aË‹°ÌÅB,68JŒ"ŽÀÄ1ç/¬Š�#¡Ö²û.ÖP( ±”iqcë íN—þü¸PË+Ò?ÇUþr¿”hޔ$Ïû$¶§Kg(7!‹T$û2Ò?Yå/À@œCOUê—?½B’_½þ¿t §å ê¸Lí?AÊ/>_&"cÈ |ÞoÝçÛzákrð(€(4œ.c~!ÜÆêdˆ¯[SÀ!üÚ©ËBS(fU­ ‘sa¶y¼ý@™ZáìÚ.›6šX”6(f{û|ò/þ7Æ»»¼ò7ÿ«›—‰¢Øn‘I\¤.B]Aì f„š�Xk÷kˆC›&‚U…]?¡A§š,f™� :õ-š­6ýƒc;ŒÈõ¡°�N–üK/K e m˜à }üÕÓ™®¥így¥—���s§â¸Èa‚çËtÍ©*õ“šê+1^«SÊ ~*ãù§+ÏNÙù¶3Æ8bôŒjT,i“ ^ýί[f~cµ•Ò.LÕ Ç+ËüVÍ÷‚« v<ÙÚqº²N[h v¾ÞˆFLìîÛ©ÄHk´Ô0³™�­ÐhZcc¤ifГ9÷ÿòÏ�,ã×ÿþÁ…KW¨GŠ83Ô0Ôµ¶ ®!ÊŒÿg2Á¤�æÔ#ÅönÂ,Ki57-(œK±1Œ&}ú³CVV»<¾ï§WÃY¨Ÿ:yü,÷PØ‚äC?õìj˜Îx9ðIFg¿.�QO,ÅÎUz–hË9„cÑÓÊ<1I…‰ž*�’Ó«óAŸ-SùN¯›e—\’;ÎOý&�ËJ-5j„ÞY'|»”Ü£JåY¬x2ó ¸ˆ¾ÅÒâe]Pa‹âÈ9c™ß2�ˆ²ÁOÜl‚…`ƒ©5 6pˆÑšF3#ŽcŒ@šÂ½Ÿÿ˜¿l4ø[÷°¾²áÚÍ S˜d��I±A~Œ ™ý¥­�Àµë5>y0`oÀ›oÔi4Ú$s!K3ŽÆûô‡è4�r~ó·ù¸ÒOZÍ·$ɉ'Á¯N{�Чš>9�Áb ecN(+¡€—-Jsðn¼A°âÊþlK!Wj—´Ê©íû•üú«Î’´‹Â68-Dd Yæb :�¼¥mP]¾(Ù3~µ.æ×ÓçyÞ"¶Y8—B…]„»�ùMþ ö `~ƒŸeÀyðFiŒ$Ò ìP@‹FK�y£Ñ45•‘¦†Oúþpe�_û�¿A«ÙAŒ]C ½)·ðF0H$y ÓN+b8O™¤+>þlŸkW2F锇�wí³Æš£ã¸AouÃÕQ“/æZüèR¿æG ˆ\œœ80öëBÎ�ùáÌÙ*ÀIŒU&¨�qm ýÉòìÅÛ*—Ÿkà„“ŠÁïéõ)`¢Äpa{<Íœ–$v7 “eÖ©f R.OAÀè S†ÅWÀ+wéu?§2¿—>’NÞOÃüù!Ìã—[Öô¯•Ünà¸3”±s|6¼š&lØr]#™gÔëÖÛ0›Nøì/ÿœ›·^æÖK¯«Ø¯±KqAD(\‹µÖ´{5ö§SÆó”ñ|ÄÃý†ó6·6©7óif‰š½5šÍµz�$IsïÄER\DƒÜÃõÉä±±Ôúgìý¦g_ ÔÍ@É/àôj­‘ ÔQv«<é‰ðÊiŒµ¬�“!éôtRÎ'ûž”Fú™{ï`Ë’ó°ï÷uŸsÓËiâNØ8‹ÝÅ.°à ‚�‰9Y¦iRrÙ”]¦íRI,ÚrÉÿÛ.Ûeýi»JöV mÚ– %Ò‚L‚Dv�M³³“Ó‹óÂ�'uû�î“î½ïÍÌΠŠ=uçÝ{NŸî>Ý_îïûÚÁ©Å¦)ƘbmÎÊÇ[­|©rò©½†£úœU×kòÁ «Xõ˾¤òÎŽüyýù¥ö”<"8äë”(ŒRh›!&CI†Qq,4›)‚¦»³Ã[ßù §O?‰ž[œ??ÆNBÞ)c…VKKÆÝ½nlß&öÉ’„÷¯÷È œâ$7ïöÜ¢­ÎÍV‹ ˆãÌüQݦ9dŠ·<ù‹+ã§W¦W&ïý3s¤FcÂ�ñg_ü½*˜J³ ù­±Þƒo¼®çþ–"ú.— ê�MÁÆâW…C׸½¿4Žüª’ñp –bMëÝ£A1Övñ*>›áC"¹5X"?‡"elþðÄ……;¬°n&�Øën2¬“&±Ó¹…â`Z±–¥ÕY¾ýýÛd€Îƒ˜À#£sþ±"dÆðöµmÎ>êYêwhŒøªØ—ê@�(5h»Ï¡¸SàÚ5ÿ@å‘U€bŸ¡¡.æŠ:&�ßõž‹K¹9®TJ ú€¯yß=þI±|ee™_úÕ�ñ“?;�eƒ Xçs¿ºÂOþÜ�1;;[46ù�.ÖZ²Ô`ÒüÀ�r¹�¤öÚc‹=­‡†Â˜)uõÃÕ© Ž)U=Ü2'%�Õ¸³G~¡Dþ ‘ßC~õ€È/UÎ>×X…°ÕÞ¹ÒJ!ckoP(�¢DHSE·¿KœF¥þï_3Åpîä ïl¹ÄiÞ(èv¤Øz3Ê+œJgf¹|ë#´²dq¾–SÍ!þcZå’Ø:Îïç1whxLåñzVå¥}Øîp™$ëu XMQí®?Ùû>ÇV�ñk¿ùã|ä“–Ô®#þ€Ï&wøÔ¯œ"h~œ¯|ñuövî�wvß¶M–a2[·)m’ c¢÷D?^ZÈZŽÜ+ÀVæ²Ä�ñ§cåeåêõ’#åïâ¬gpr%ç´ÕU„®"17:ð¢tµî4"V‚š*ˆB) V¡”¦Õj£´�J¥q[¢ÕRìÝ’˜%•ŒŒÖ»RàÕf»;`6“ŒHÒ<�˜ÛQRUûÍ” ¾ËW¿_»U{Þ-Dá'ñ˜|,€TÂv ï’ªžyÈcµãaÃU¥4¯?F> ¥ÿرãüÿþçxæ•”(¹McQÊÐ6·ùØ/œfvá|韟Íõõû·nóh½´=�8-ª6Ò’ƒØq,«rn_\.o!˜B_ÝSSÐųqñÄ:?½¨N^ʺ2v·FtŠ^&ûwÈ_—jÈ_´_Ép«CD�×=ùËÃɽ*à±DIDgy#¹Ã�—b2c9·ºÈ½Á�­ƒ¾{:¯—%íÎd̽Ñu  [-Œ±¬ïì3êî'îT'¨"5°�‚üÕËS�¸LT�­jSùLü¥!hµ¶âÔCåz¥º:œÆ�_¯_š¼V# ¹‡1`¹Ï<�8q’ç7?Î+¯¶è%— ubU€Hˆ¨€Ž i‡š¥ŸyŠã§Vø¿ÿÑŸsóúµ F×ÍŸÖ:=ßú̕Ӥ,%ŽÅ“T[¬|uow? ©J �C•ëTX«hU ¡äÉ5*v[„©ïVòÒqÊt4òóPÈ_GQž[[%„ªÉâ©SXR­%CÁjag$ǨŒW¡<-–ü¨3ßGsf#.�X–Dlon»3”G±å*SfŒú•qc_õͤþ®3ÖDK�ƒ<Ö¤ ¥¡aIc2δü§ñZ‡cL‰’Óg€'ž8Ãoÿ‡…O|â9úñUfƒS(¥�ÿ¸T FŽÝuƒ]æ>2ËÂúY~ÿ™á½·Þ ÐÉ“sä×î‡ü%ÉëÕ=úJj‹EŸ’ ¦Ö~ŽV¤*툭€ÏŸ©øL�¼1ÓÌáymµ¡âýjÏVÀÜê`Œó—ßî‹üctÞ* ƒÎÂ,�¥â°�2£R5†N»ÍL§Á7®ß*­Už@äçX«ÊÃM3³n}Ä¢%cog«`øã;{‡-¸ëç(v—kûùO;^al6½<žsÄ…íª"¹ÜÛâ4z`ÇTÁäA_s’„<ÈógÏžã·ë5>ùÊq¦Aj ‚!#Åd)Æ&d6#3 † etÀ¥Óm~ãï|ˆ/ý_s|ûÏÈ`Ð÷ÖýŒj<ÄÑjZyS�ëÏ"'Sˆ%ÕTÔƒœ#åWsÄ‹BGþâtšb|½*â×XÿäÉ}‘¿ÜϰÁ¸Î?Þ^ùk.2’¿¯¿/ùÂâÚ�¹bi9¤µ1XP�¢Ýl°9�Ø�®©f¹Î_Ú/,(MØicÄÍQ:ìÑÝï•t²öåˆE? *S~¯pŽλ8‚±=Lyd ”By®_ÑbË ‡¼ô²NØÅ¦Ê»ö0Tñܹóüοû }rHÖ½Ä~´Ò#Ô{DÉ>ÖŠóÉG¼aÜi�¡³©¥D̯îð‹û<«'gøòÈÆ­ÛµqÝßF“ƒsìcsš#ÞTr ÌÛ«.RîEOóÆ® ¨E ÖÁ4ä¯ÛpÆùP�¬S¤‘Š|QGj­ùU½cÄÓwÔh49ñü dí·–ÒF™‘ Dqzm�/¾õžëÛäy]›—-÷Û-PÚ5¯Àöî1èkN>yÕC×ý€([eŠ[· ‘çË£oj]ê„7ñ7êˆSÛ±Ïäjü€å™gžáw~ó/Ÿ¼K­“¨�õÆöú5‚æÓ(Ä»›ºm%åõT…óÛž1 k2ÂÆ~â—ù�ÿäS|èå —ì²\ëic®þt\ÞÚòï´"_ÆæÓûÊ‹¨BžX)çL*ó–#ÿ„èêx(䯽ã®vDš² Ji^|áyþþß<ϋǷ‘tßq�惤�I{þ¤‹5 ×ÞûœGIãЦÅBÇXZ9¥¶`²Çyöù€ßø;?ÆOþÒ§X9~¼6˜ñ1Or÷þãÈïŽóòܾ"š�#i•/gAÆøSµs©© µs§"ÿø{ä[¦$Ÿ@þñï:ôu<¬ØêþFÙ³»räwõÝûžzò ÏöSÌ_df! ˜:q;¥F4BL³ÁÒÜ,¡Rd™÷þÃs±…îoÐИ�-¼µIH÷×¹»Ùu^‡ùÈ}ÂZÉ�a"Àê>ÒéôÅ)KñØ4G£G+�×PJÀËKmQ=„ŒKSZªÿs zÐwW*à£y‘ßý'9·°Ž$âéP IDAT=ç°j jñûw¾UÌe¾l’]ö÷¶XXX�l‡ÌDätÒe‘ñïga.KHÂ�ÔZZÁ,Yœ‘™.óó{|þWNòìK+|å/qõâUFýÞØøÄž~ó:Wñër@?d&*íT}þe˜JÁu‹;)Ë+m×YÚØÊ:ê‘GðÕ…‹òùB¤×A™Dñ-µvmýéJÓ‘?fõäq.|þ³ô—æØ‰dÆ’xNŸË|3DT�½È0³°ÀS"\ÚÙqg'ú$¨VáN.ºÂÙ/]@3pp÷.÷öºˆÖN_÷;_õŽ¡U[IN0ëóì×mlÙ¬O!DæÑÊãËPÌNV©T• îÇôëa­ã6„ÃK¼öÑùÏý4O/l MŽ€Öqÿh“Ž|ÊœW‚1Âæ­¯Óïkt°Œ–€1“NÑ¿60—dX2fÂU²(c8ÚE hµÍùg~í?z‰_ü­ÏræÙ§ aå]ê«'R†FäsU„O¼q>GÊD�Ut𯱡lSŠ9e¢æøÏIß3[êúx¯¡sYEiD«¢-ׯªü—h ¬¿ò[ÖNçÜg>Îöì7‡ ;ýˆƒQL”fd>Îb¡Õ¢©C.mír7ÊXZ^dµÕvç'zo©ÛК°Ý.îµûûܾ~•ÌâÅÿܘËXcI<ÆJÍ’Ÿnkÿ*;"RÿLèüVê™›?`y< gTãj«»ÊQ[‘n&wŽtí=\¼ Ã�O|ì%þÁ¿uŠ'gî L¿X1jþiú½ lÜó–\‹öDUá¢Âv·Þe4ÂÆ*BVJ y;¸È½–ɘ—6�iE]ÜÑݾž iw¶ùÈÇ[üæßû8í×>Ëñ3gÂÐ!»*_±È)@n,ïêäæˆOOüÔ‘rÆÆÐmZÅ) lœ¾6†*’3Á»É%Ô�» ì¶VÛ·Q#(Ó‘±œ8{‚s?ñI²³g‰M4•í8?Îv#d¶Ùàân—L+v†#®^9ÿD„%®½jÒ�pv«F •­ßâÎÖ®ÛòjY‰¤G#cm^¦VuU� Po_ ·—<æïû{ÔR{¯q­t¼ÒýY~A <¤ªR=@ ‚&ŸþøGø/~í8§;·<òÛ�‚æQÜ#‰¨r?] F²V7ØÙ¸N’vh„‹ˆ�F@YË‚ h1G°åRXÕêY”겸x�Oýô2ÿößý4?ñKŸbí‰3(;'Žð˜"TaoŒ×׈¯­"~ÞÖ4Æ.ŠÊÑÔR±Põ–aBF¨p,«ƒJûRo?(òaÀù OóÄO|šøÔúA“bª§-Æ¿Øiq·;pQ‚îôGÜŠ ¯=y–Ì— @Üù= 1ç’ 0õXï"›Û=·ûBìFë½FsÏÑiŸÚ=5­Î!D[ê’�™ÚÚ?jy¬‡ƒVþ0íר“c¿«À3Éëk pjóB£Ñ೟|…¿ÿ««¬7P6.˳¿Ò\ –D›(Ñëü»�8`syê]Ú¬ao�Í»gžü0’¼9Á•pjšj‰ÁþÖç\Rš ŠzƒV{¬�Püä/ŸàÅ?Á›__çío]e÷î:i–L™Ÿ*㥌ãÏ‘�ñcÃkS7ÞΔvÅËùV‚±Ä•“10n좵Ûó÷o ¶T>¤þÀÈ_/�ùμt�Îó/Ð_X wp¥?Ÿ6‹åCÇ—øêí—3 ²6ïîöøëgVYÞÜæ`8rªQnfg°™¥a"²[×¹rë"y*2UWw(œOÅÃà^�51•0RáØSðáËc=´$òðƒó¯\ñD;ŠÖ¿­V‹Ïæ~÷Y ®�õŽEUƒjÌ’4Ü»B–º!úd±n«È7i¬£ÚÆ& n±»s’Å¥óŒWAÊ3 Ô4§Ø_ÿ.³Ú2@¹>­7,’ý3bäÇ�kV~å/~ê—ÞØæÍ¯_áÞÝ ¢š±p ¾&>*D~ÉTèèýŒ¨2åb¾Ã¡&A¶T]þ¨·èòý;îïQÁ‹°Ó‘¿>Œ:ò»>t X;}‚c¯¼ §O³×™qƒÉEø)´®©4XMwc«ØÄÖðÍÍ}^}ú<ß¹t•ƒaäR�‹%h¶Ñ�Y³Ü?`ýÝ‹lí TèÅã½.ëž;‡ÉbÓ¸Ö$”Û¢JÍ ÒÖŸ÷“x”òØ‚�Ü�|Nz[_Ô.µm¾#$„±ë�N›¿þåw~nŽu1I!NW'͈�4æI‡wÑu±Üå´JÎME0&cãöwéÌý,A8Gš*omh6�3Üß@lÆL±2$¢ ©¥ÐñÉSQç󒡹DZ㚥Ï/ðâkáÚ»]Þøú]vn®Ó»ç,Ô5»ñ)°ã¼÷h1I¦^ç²¶"EL („L]¥´ˆÛ „Ê;—y'Ç–ÇL¼‚V0¿¼ÂÉ?OóÙ§vføíÄœÿº¦ë¢W’>vê?ÜÙ#ʲ A‰°5±1×áôÚ Ùúý8F´"œ›Á(˜‰Gd×®ñþÕkD‘ %)â �CÖâ­ªRì//�Áù´`!iܵû18>¦` ÿ·4Zÿ¿Ôa÷¨ßo�*½fg;üÜç~Œßþ™5–ìe´�Ë~¥ä¾ °KØ_ÿX‡üUÎ\w…ÏgA‰3býæwyâüÇÐæ"™ñúŸ@3x‚~ÿMÀ ¬b.MÙ �A5Ço";q(Zï3»`øð' ¯¼öanß}‰|ç×¾w›Þö6£^· ÑÖ½D5G"UE´)HZÌwI¡Ü/[ñýŸ´ûW9Ót¾_\µöÇz•m×ÇRYo©ó´V”–—X{ö9.|þ3¨S§¸tÐ"Ì[ ™E”u' g2·##l–ÒCÚž!fHÛ¢}~ë£5s2öí=^;¶ÄycxûÖ]Œ�pnLÊÊÞWð{û(¢•Bi*FÀºôt8ç?ä÷e‚\z -Ô»oêÐòèƒy×V¾B Ž´ôß¿ç0l6„8S$Á:¢ÈÈ=»ò‰²ºE,M²Ñ^É…)qªz-— r^f¬"êßäÞö WÑì�fCZ­3Œz[X“Ï6 ̤)½@»§}úî’(/�ˆB£ ´F‚�a¶ š]’…!ç_;ÇÖµ3Ü}«ÏÖµMz»÷ˆýbÔ“Ây9¹‡ðÙ:€VnäQŒvâ‰üÁrv&Û]•vQ~cÄj¢¦#Ð XX^aå™§i¿ú æü9ÞlÎñ©•9V¢”õ(u}…ªto½±Í5ÎwŒŒ¥g›Ì-QºÖ˜Ìogc¸¥gæùðÂ"ïß»GÐl³ÒÛ§÷îÛ¼så‚ •B”ãþRÙ³�œ­ª:[›Ä‰ù+žç�¶å8ÖFî3nñÊctºêN!U‹ðCQ42ÖrïÞ¿ÿ‡_ãÒÍø�ù^kÑIn Œ)œvÄ$°ú2½�‹`R Œøª†’j�ÔTuw)&.‹ïÎú4›Ÿbfvcnè%’x¥±6�Nj‰´�H(í€Æ'QJ#:p=('¦Xe ‚�N¸ÆnüakÑ]žXhqê¥9ϱ{Dzþöë—7‰öº¤ýž3lÖ¦¥"&L])Åø©ûÈ(Z£5Wäijš(ð9J6Nb«M{K½‚ÎüóËK,¼ô�çž#>uнæ I 0Þ&œnh2p7Jt)I’‹ï¢£�x~/ÊȬ××­'ì"Î/ Ð}`7Ð\8Ý¡«CÌhHëòe¾ÿúèG’¬áÄ->HLœ�Ur¥ñ®_›×É9ÄóìïM·ãþåQJ„|Ðú¹èYf\ɰx§C_®|ÖZ¢á€¯ãÛÜÙØæßûÅ�ñó/?Ë\| !vœMwˆ¬�Å`RDåàuƒ”ã îÄZ©,Œ³( bký-8ñK«%éG¤£acTˆ(—IH©€¦è…!(…Q ”u &•Á*ƒ!ÅŠÁ�‘Ø cSŒžAô a{‘ÎÁ]öÑj„R#f�ÅÇ.txzïyúÛ–{ׇl]¼Go�ÑA—t8¤j�ŸÓ¥¸_÷Ù˜aj ¾æõ¦È ªâ¯T}-ýõZ}�@)Ús3Ì--²ö⠴Ο§wü$ñÜûͶcþ!-p}˜Ð8Õ è™Œ~ê2ò”š§ëÕ3Jh¢¸9J¼FäVÜ%øð‰?)Àì¦ïKÀ+ǹû­ËÜüö÷¹zwÑ mÝ DJ¼<^Ù±wÿOÝX?LR˜®ØNXurÚië÷þ?ð†q„±oÚI¿%Q(ŸËQòŒºÆ\ºx�ÿiØãÚú«ü­Ï<éÆutÖÅ,œc�F{.�¤-÷|sI Z YVý u{€É„h°Åîvƒ¹…çh¶WI£¢Ü÷V ¡$X•Ð×KÆÈº#I–ùœò)©±¼¤"Š•Îïí½�1†çN}’ïÝø"ùê+m±v@C†«ŠÎrƒµ§;œùä1†»gén't7ö®m3Üë‘ôû¤ƒ¾;κÐv«)¸ÇWOêÇ–UM¹VT”’¨ ˜XÑl•¢ÓiÓš�¡³¶LóÔ¨•ŽŸ;ÍÚSçùÚ@�FP¹PƾäÚ­QŠ <× ùîATìÜTûÓ(f´æN”C¨Ê”Ý6Ÿ / �âi�ƒƒí$Eïïýà‡¼qé –Œ4nÊ%•ò¨2Q¹�ÄÄd2~ñЩŸªiOK…¨*=xtð8@ 4gµ™’õ¶Z}äêeòÙ·r«êF숀Ká±qw‡ÿó¾Ê›—Ÿç·~ú Ÿ>¿ŒVM¢x­- @�ñ{ä“ê@Í矒(Q†$: 1)­C03 ³bR2›`³„Ô¤d6ÅXÃ(ÐD y’‰2$XùùpúeÅÝè=R±ì·VybñEîì½Gæõ}ã¡A¬%P1VRš-CxB˜=Öäøó-¢OŸ"îk†{†FÒâÞV�í÷7‰÷û¤£Y<ÂF1iš!ÆT©².Sí2¦ö«t÷Í ¶ âU Ñl4Z4Z íÍÕ5ÇWa~3;˨Óá@…4Û-ž8}‚˪‰ 24£mEKÉOFŠ,ÜŽN4Û<Óip©VN” ZYN64¸7DKi)‘œ  Rd«ýÛßåÚŸ™¯}ý»Œ¢!q¬…Ri±¨|¶ªòã :p4œÛâ¿Êscz@íôl/5»ãÈý|;Ü{¤ò8Œ€=‹]0þ¬tkÇrß•ï‡ü‡ôSÚËcÀÊcÂrªÐëuùÆ×¿ÍÍ›wø?ó*¿ü׎‘vß&0ÊíïVëò`p()-ôNô÷ ¯;"ˆÕ„Í2=b¿ß#ÌRâáíB¤th⃇DXÈ Û:,ÞÃRÆ�çýZ`¥ýW®ãü¾,7úWùðÊ« 68ˆö0XÏÁ,y<�UÖŸQoQ*•ÐÒ=ÂtB^<û<;ʲ=|’Ñ^Æp?%ê& ÷#Lß�í8¸»Ëp·YYêˆY’¹ãÉ­;s@2¸Ø"¢AtàÜnÀ š!�Î ²´D¸ºFki‰ÕÕ"#ÜEÜls€�ˆf”çS°–†ÒœZžçû÷"B‘§ÎÕ¯ ijîÈÀ÷†|~e†�(e�§]öó<Ô\ÄÞg¿�ü �ñ‹S‚=qYé÷˜{ý;¼þ§_cçàÀ;û¸H�7J™™¯ê!ÊøQ0.¢º“#5é O½®•F²ÒáI,ý#ºx òÈ 3ôEXvß J¹tØõ×·�ˆü‡ÜõAÕ¶ÈËg¸qý:ÿóïíð½KüŸ=É…4Ì–ÛÚ¤‰[úñÛt¶n´d¬�~�^÷"™I8uìS¤É™@[nñYë†B]J¾bÎS ±¶Å0ëc1h+$6åRÿ"§Ö^@¶ßew´…;üÂ`¬òcrÀxLÉ¥„@É™S„30JvhÍZš3ÂüiM–µÈ²Y¢T8Ö\bEͰÝße·7 ’¡%� &ÊÞ¤ÖÅÎ#´T‡F{�Ûý!ÊÞ¡Ã&Y3ÄvÚdA#B,š¾hâfÈ'æ[¼uñ©?±Ç©[N×JxùÄo 3/ÊÛÂx8>n½ýOkégðV7⥹&ßݹìÞp¦Óà�6û®Ÿ\¿óHã4–Šóš÷XõX}ûû\üã/ñþæJAiÂP£unùW•,Qª¢c|ª:ü‚MÈûž ø›R©]ewùN£RÊ»Ž{uNþÄtó7˲%î|¶š'W%œ÷°„ÈS~ * ‡ÈØk„Qbi63�Ö†^¯ÇW¿ü\¹|žŸúÌ3ü•�=ɉÎ�í “s#šL[òÈ$ñ°4 Zš�SX�`'æo¼ÏâÌsпHšEµmá|);Bä e…*`lÆjç9î 6‰²‘‹ðPôâ}¢ÙgO2Jú M!plA0nOÚ€ãEEAL@§ÝÁ„�% âx5Æ×• BE—Ú Ã‹KÇx}ç·wom@fÖjŒU„¦„œ™9Ë·÷ IƒÀˆÂXw$†õuóßÛ™åbdù«ç�óÇW×�õÝæÉO,M­9¾8Ï›ÝÄA†GH)�³²Ö#±çŸñÞ0áD+à‰vÀÝQÊÈXžì4¸ÜKˆ2K–ÙÒÅ6ù+àgpþØhŸão½Áûÿêÿã×#´:pȯT€R íÓÄ”¨b€84Is~mÊÅÊ÷T@–ô¤âŸ¢µ?}+Ú<2xôœ€PšgLîéÕó\�ñ¢vÝÚ\×;'Z½_¿*§™âbº�I¥ˆ"��!¢´`Œpëú5þ�þçü÷ÿøôæ {æ<Íb )ÜÑ>bÃhM„ΕÕ/H -KÇ?DšnƒIÐ" 7‰¥�nž@«ÐsâÂ^SD.¤nǯzßÒÐMR#$&ÁšÔE%÷…[ýë˜v‹'–ŸGYEq�¸ùtê¯ñÏ8KÃL£Ãòü*ëÑïg.^œÇé�޶“îŒz<;wÁqbw Ѝ ¥3´2¨@ÛɥÄx1Õ¢ò¶Å–}ø÷~¿Ñžépn¾M ƧǬ^=±Ä»#Cšts˜±%¬þÍïãi´^?ˆX 5+�€ÔZ–BÍÎ(fekI­%µ�\h°ëž†æÍ3iŸ'ß{‹÷¿øE¾{é.UaF’„þÄawúp º°þçQ€y�Z�ÛWa»9&®�«’³eˆ)÷ðã6”.Þʪºßø(úþUŽ.+Ëg~‘§f;sDID’&¡N¾ŒKJõ/ãŸûñm-&ͼ˜ç'JR„€4u® A`ü¶¤iÊæÆ:¯ìrs†…Õ,Ì7ÑväCHM©‹¹ÐPÁ(…KÐZ¥³|œÌ`²¤XØ(Þ%l� ¡BLº�A ©¢ú–ÚXF•˜xc3f›'I˜ãfï*:°â—�8ÃÒiÌÓ²!ƒôÖúøÉm»Ibã:/)Yla¶•¹QlDûœéœ PÂ0b­e.ì U›õÑ€~šbèø6ò禭aî\%d¦Ôí÷�a¾ð‰Õ9T«ÍF¦X5+ ÍZ3àxås¬°,5‹¡bN+:¡µh ÖX2k¤†aêzÄŠ7v"Fö¢ŒƒØy Ž $Ö2 9}û ·¿ü'üëo~�Íý~�üIùí¤gðZx.ú�v‹@έó¹ÉÅz÷‘ZMPe›5h¦|¦*Ì,-1ê÷É’ …�ù¯\ÿá; öåÑýâä]§»ÆIL#âçU¬µ˜4?l³þ\•V–Ò€»#¢—¶ kSŒ4ˆ#'ò¶š™;ÄC–i’(áê;¹{ã_9sšOüØ^y~‘S³]ZºK{æIº]lW{Éþ;(2 ;Ñ:ºõ�™§H7 ÎVu4jØŒN¦h„'¹·÷ݘ\xV¾W#5Š÷{ùÐò‡Äû ¶�¢7À-4–iç�$…G‚�å-‰Ë`‚Ï¥q¦¬AW<ÑZâX{�ë½MN7�“ËΨK š¤Öû{àí#Æ™% ‚F 4D”FkM š†hoE_Ï,vèYEo?¦­øx‹¼X÷Ž-ı!2¥†Ì:Nžo©•"8¼4Ûâ;·"Gèm‹€rG&4§‡û„ï¿Ã¾þ|ûÒ5²ÔÒ"–8n­3t�s~gô+� T«Âº­_¨© 5h­ˆ¶zуpî@]>kZ‚°A桰Ђòˆå‘ À;WÎ^yîÂ�l3ˇ JÕƒT¦–D~æ^Í#¤RìÄ�ê}UX¦ÝÔÆeÓ ŠÜve³i�ƒ–Ì(¢Á�«ï¾Çík7øê§yù¥3|ìåóü䋯Ðï~ ­œý\ü^¶[÷2rPaØî]áôÂKÄÉ.˜e3Tn�°†cÍ3\íÞ)‘ ¼M¡a Ý7·d&b=ÞàØâÓX“±my15ã‰Õ爂£Ññ‰K¬5^<÷ž >g¡XâBiÝÖ²Kf¶ïÓÔš“�Nu2Å�ÑJÜ®�R–¶h4¡Ò* @£•&A‹F[§¶hkQ”qNFXA'‚í8Ǩ†öâŒ(ƒÈ[é3¤Ø0ùÉÖ…k�ˆy ¾#–ÕfHh&ÎÓ¨Æ&(kXJœØºÍöëß᯿ÅÕ­{ˆ¨ù“ @þÀ#¿VªÔù¥&˜MEü¯Aüñ+cÂ]a0¶¹�ØN€³V.£²ÉÒ¢öñäÊDYY€·íêÚÙ8!@«Ù&3IZõRŸŠDþ,«œ´û€Ïùz*ߪ)¤JQL n?]‘eŠ@·ÿ¬¢œ !Ë2º÷îqåò-Þ½Òçêí"–h-. ”ÐPi1¤ª<""df„Å\ûiv@‚!Q�/ð:lçiöz›˜Q ÉÇU÷Ós œ®ÝOh7˜ gˆF=RF´Õs‹+ôõˆÄDü±€¹<†´’%ɇ*›Ü†"ÎÛ,5­C.Ìž!Ð-¶£KÍYVš3,‹¬5¬é�­YEX²d3æÒŒNšÐLbT‘E £ÑˆÞ`Äî(bw£•âÎ`ÈõÝ=gg¸Ò�‰Œ-tt ._¿gõB™o¯D½rŽ2à£óm®ÞKè%EÞ%Æòäþ]Zo�w¿ü%¾ö½7Ùî ÝÖp PÊütàÄþùµ�õÏUÈêêæªS [Ó�¿TÆÿ9_ÖªŠþ9ŒVzª€Akf­4Ãn/_¼‹ÿâ_þþÿÀ#–Ç (òe±ömpz¨ IDAT€a4¤Õl3V}ª|úþ®‹Mª'íƒ#9‡uQ¬´•¸Í5¬ÁØqê| š-gsÖ~«.Ë&5l\¿ÁݼÅ׿ºÊ©'Ÿàµ�Ÿã¥¯qj5¡tQ*-9ƒ-½á-Zá‹áÆÞuñ¢‰ÉètΰŸ I“fTF_Ê“rœ$`k€gÇŒ‚ Åv´ÁZc�ÓËÏqíÞ÷˜ ç™�]æV4°6Ãzƒ�-Ba5¡R4Qâ>Z´4и@ 'ºÏmzÝ Îƒ²LÌÈ´H3·¿d†ØX¢ÌzȬ”AÞ)4‰…çWgùý÷np0ŠøÕùyN5C¶ˆ�%MŒ'Fij‰h,¢ÏËMÍpdéFN=h[Ãéh›™;—Ùyã›|ïÍ·X¿w€ˆv= uFåÖ~§ó«‚óO"MáãÞ9°•±G@jQ×ÿÌ·›ÇˆBqÒq¾¯Òh·ˆFÃÂÈ-b¾rX7S ÈŒýSmù{ÃÑ�µåµCjæ >~­,Ƙ"cËauŽ*“’Xu§À‰}Ö (ïáG‚µÆÛœøY¯dîÔý­Mö·6¹üæ;,;É˯>ÅK¯¬òÌ3mÚCšz€RÊ:ÿÝÞU–gÏÑMoxãEe«çéF†®« -d‡)ö¿Ý™‹‡I:d“-N„Ç93ÿ"´ØJîÒÔM”4b !Z5PhïÌâ„ýJj‹'c�‹@1Œ†Ü¸w1}¢Ì�èëÜæ.Iþã=÷;pœÛGjZH­á©ùYÞÝÙu ™ÍøÊµ[üø“g è'¥;–“‰sÑ8OîR¸cKÑi9Ý ÙsÉsw.qðμùî[¼wË%yU!A ˆh”š4øi­½÷Ÿ‚ü2±]•zØ´Œý�Â¥¤—ÏÞÓÑÖûªPƒV»Í½Í�¢ß,‘?9ª< á_[XDñ­°eöAÄ÷‚ ’™Ì¥ã=|�(2ù+wýaœ.ë¯ÏÑ£œûªõn¿V¼D¬µ´Z. Fk d&ÀZK<±yí*rý:ßüê2+'ŽóÂ+gxöÂ"O?2×Ñ †dÙ€þhÕ\¢Õ8Î0Ú —1¶Eox�ËSØ´þT"q"mŠó^³>{P®*¥½³PàœS$$ÑðÔÚˈ‚›ñuæZ‹Þ›PÈS”ˆG k3R›�Cb ©1ÄÖ�šÌso7†Í“ÜØ[§Ÿ¥�f)Öjg¨ò†Më¹°±> …±¹'€7{Š‹¶´&ãØl“ïnÞc”E(kÙöy}“ãk«˜†f+2Þ¯B@Jìj³s�výΆŠF” w»\¸u‰þÅ×ùöÀ•;›dÆ *ðˆïÖ<Ž­C‚ %ÐB B”Ö.ȧ8~í�?—.'Ôƒ*X—Èì~—·Jƒg©ÚmÚ²j±v�F…Ù(ίg‘þå!/~­{á¹O}ßÂkàÔ€f«C༄ebëÅ‹1UC_¾âª�üU‚Rú†çíç¾ÖyØÙ#Î¥7Žc”—*„ +Cž{[Ût·v¸ùîE¾¶²ÆÚéc¼øêÎ=9ÇÙ³s�˜Øt95ÿ q²Ò"B°ñ.V ò(;…² ¥¡4øg‘F/(´·Úkk‘,e^…X­XÖ # ™u Gâ,#³±1Î.c�¡ÍxÝZåã(Ææâ¿ìµp™w‡7œt Ûˆ‚ÍP’9nœ‹¢ÞÀ¹¨[DÜnù–Ôdœ™Ÿes0d³w@–$d™�ÔòÃÍm àôÚ™óÞtÇ´©"PÇ�„·�‹“–¢!Ï´ïÞâÒ7¿Åõ÷.qñΆ�G P:pº¾8u*ŽC‚@¡uꈀ ò‹r¶ ùKï¼1¾–aÅ­ç‘ [¯^^ò„À™ÝõÖL›h8tp‚ÅŠzýË_þÂÞ­?pyl)Át þ$MÍkýA�Ù™9Oræê�?ïÔcÆæjÚÌ�«eÝñ-šñûµo±«ÌôãFœ²©ãj4eIbã DF³å�õ‰E3£\ˆišq°±Îþú]®¿ù�¥æ×–xêùÓœÖðÊK]ž^ûahØ=¸NÐ^%”¥B—žJ4Jt› Á[Ñ[VYŒÅm…f¤$YJB ²Å "c°�Ýt›Ôoü�G$\ÀŽ ŠC-…<¤Ô-–̺c²N¶Nq¯¿Gš%ˆ¬h¬m *B2c!6ß[p•‚®m\æ‰WÀ bè§ ÝdˆFƒ’"#Ò¥í àÅÕ¾“‡ã£s]èd kñ€Å{›Èõ+¼÷Λ\¹z�;[{>í—“Š‚Pùù̈bgØsn¾Y‰ü¢âKî=ú È/5øq`™;b�ùN�Éɨ"}Ý##ïÌgm³´çft½Ñ@!Æ>ý#0£ì#�0õY^XE«À‰õ•RðxC‘­¦Î½RìϨCî×&·Ö‡ ž{J®qzo3kS‡øb°6ÄX!Ž�^Ûn9¢h ¢É2UëÒ8f݃»o¿Çwø—K˼ôÑg¹ðâÌ.´9{z�ÅfƬŠh©- ˜Æd22㋤yö ›9ýƒ±#BjŽ­|”k»W¸»w‹Wžþ)3ÈöÝn†çæî܃ÜCOÈ ŸõØï(ÏÕ;Òf?§JU€ƒ’ Kà=þðۈΰ긾Ñž¨²$c¶Ñ¤ ßßÞñ~Ösr¢8ˆbÞÝÜæ³s3<Ñ Y�2·ui-�$c%í3ßÝ#¼sƒÑ­ë\|ë"×¶6Øï=â(Q^ÜɈcƒV!a QÊåT: Ö«üNõ}þ‡Fþâ—ÏN‡äñX‡²¿q±?—4[D½õœÿƒÕ¿wÀ?tyl»o¹pá3oXk^aui�8‰9èíOÔ3Æz�¾ñÔŪ£GwçŸÒê¸7­T|çód!yʱ"ë�m8=Í/%d´Zøººx?ks‚b*M[3-sËtxò™UÎ�]àäZ“Ó«Â\;%P#šjD#L�˜ŽÏ&¤ò8;Šk:hј}Š+;9ˆ¶™mœâô‰'É}zÉFiŒ÷Qð»ø¥èoç¼”‡ñ:„[l¬1›-quû‰1X´ïOc�!NgÝšVùPaçlå¼-ܵÌl–bŒ{n©5Ãüì tíØ 1N¢ÔµëÇplv†ŸáY¾yw�ùÔ0s°ƒÜºEïÆu6/¿ÏÆÎ[»…|#~÷$ Ü»ˆ²(Q$‰ßÕ.“OnäËÃyEçª÷¯ÃJ©'�?·sŒÁÔÑp6Å0ùtM"°ÀÌÒ": ÙßÜÊk¾ù‡_ú§žÚÈ(�õxpcì?‘ÿ ×ï²´°2AL–ùà•ñR^±_ª5üÂ=fäÏqú}[P·�ùï!.�¨"Ž�+j³é¤­ñN‚1u£N<ˆˆúwé®ßeó¢åû��¹EÂN›•Ëœ>³Àñ㳬-78¹f™i:%T Z'(å]kMÊLë8{ñƒd› »ƒ[Ìì/°¶zœX‰³Èe+.z'òûWsf;¼W ã„ “Z¡0¾–xnMºìAbœxnm‘_ãR£)ƒOZâ\¦OÎÍñ�Í;hÏÁ¬§Bˆ¥a3ÚF˜ËRf7öÙØÞàéÁ�õ+W¹|õ»»líõœqQ@ÈÕ%Akçç(ⲠDZËÛyOŠŒ>*Gþ ׇ§ NCþJÝ)\¿Ü2ÚǦ1q2r®Ú©%‹²Ì’ F½!£ƒ½nŸo�b¢4&ŠF úýÁÈEMZñºvŽzn;.G<]$ÒpB¢„x§ò†¡såÖ:q±*,¶ôJ‡)J‘k¡º²ä¯q'a’XLCþ*âC¾Ç/LÖzU““kCÊí¿°Ù¤Ñl°§LúcSù‡“�>ZyìÀsÏ}úëÖÚOš4e®3O£Ñdgoó>Ý6”-òµ‡8nß­ÿÌ¥‚\B¨HEJ«ü»Å؆—(®Y/ùµZÆÛ¼ ä”€‹ŒË“e–aGYÃcJUEܬÀ¼R.Ë ¡ö‰.ZitS •#PJ@…5Ö‹ø85qi©s¿ k\¾€ÌljHMB§þ=„êÑlùE0²h?V·-ùR”H¯Dˆ"ŸÌEK. (•xB¡¼£�ó ë¾*²ñkéç+ÿ�ûåÜ_Q©[röq×ìiÈïèLM¦œ �U_ÂQå—÷|Z8yœd1ØÛ÷Ò$oüÁŸüÓ�ð˜Ëc—ŒIÿ›™/ô†]NÎÍ!iê’?N/Ó¬£d�úý‰+G7\_¤©U½ËèX¥2S±�ç³±Ö¢ò-Åœ(Ø&Ö»Ê&IÀZš­Ìœ{>ÐàæG>u6�Ëøã¹F9ŒøœÀïŠ5nkŒò0­ÂϦ6õù¾û8[ðº4¶2C(/ZŸ:+Ǩ‚hùí6íÏÕséÍs„”O«EMÏÕÅÈáÄ|‘ħæ2ˆ„^ðö�À⽫Vúbˆv|¬•·TT®Ô‘Ÿ‡@þ ¸cF2æŽ9€{Z7›4Ú-Ö·}ÁZþËñ'Gù‘H€<ýÔ'¾æUæfh5ZlínNïŽÚÑ8ZÍ4ÌÄDOo1ÿò¨È/Óo ”’�ÓYŽåŽDù}o´¥ä€me:²ÜŽ�c¨sM.¼((²ÒZ,AeTå$›ZÙâqJUý=Ê©‘ÚSFð‰ª0XM%âZ«Š¥=§>{Rîw¡¼…=y±]y�H/¾»½ú¤ÐçEçNLå}'Þ™G¹‡|½$u2=Áý ?€|¼î¯óh,¹ÕàçW¥‚üB}ê¤>±Å3~îÇñ@J•`ñôIâþ€Áîž·¿ðî¿øãò“O=rù‘H€5Öü·Zø}€^ÿ€N{†v³Ã0Ô+N}¥áüåN"¿ûý£Dþ1EnŒó” ”o'zª�µ!«©î[ƒB»´�¤€±Å³NCp» ­¦õ hžÜ=+ìû³¡»#%×ÜPÆXT èu)�¯\ „ãÐâùAW‰@4 ©úÜçºz:Ä¥@x*Ü=¬ÈíÕÃ9�ÃOé©^«$Û­×­"eÅ(¸U”8ù« †åý‚¬V�N.æÈÒš�E!ÃýƒbˆüWü�¿6äEÛÏ<ýÚŸbù�F‹•…e6¶×+I'vH2ùë/ ç¯~q«¯*—r}¿¬k‹ëåS¹–%(¶ÅzÐpÄB*i­Ú1®Ä8ÄÓ�³L£f©J9Äæ\RéÀ�¹J| žJ©Ðs_ôʉ<¶ß!pRÔË%Š“w½D@GŠqåz‹�=¡FØþÿö®-Ö®ã,ÿ¬µöÙç~#vpã¦r§B¢„àR Båª> xª�@ª T„ÄE­€'Ð'�‚ú»‘RHIÒ(A%N«¢ä!TAU[‘FnœØŽÏÕçì³÷Ú{ sûÿ™Ù縵ÏÅa}ұמë?³æ¿Ì?³fßÚ:ÙüßIùƒ]|IŽf­ÃJ€ˆúÍwïøÈ/ÿ¾]!Â"³}²t÷Il\¾bœ¾Ð@ƒWž~ásbŸÀ~Y Q«ßC©ÿ @5ì`gÐÇÌô6®ç¾cš"ÖÂ�0¿ŒÏü [�aþ]d‚ȧóÎBy诔þ6À(mˆc^÷=…ÑÜæ,X`L ­Ýö‘”6šCÛ¢ê¡ù†AkçLŒÇ•qÌÜ£ hEPMÉèÀ1˜Ù‘‡H}£ÝáÂaÍýʧ1àÏrôBÀíWÂþ Þg±é�¾r4ó.LxLnL%CC‡%R$ÂÊC{ëÈMƒø²áôò";=ÔÛvÝ_«z„òØ'æ÷´î'î»çÁ¿ÕZÿ`æ�Ç—îĵõ«ÔòÄ ŒñÉSô¢òƒÜ�ýd~J‚ü Ŷn©ùãjØÇHç?8N —«nÁD¹ JäïôŠ}M�øºÌ�Àpª!ך@7Ò^}hE ¢òe›R[fcé ÆÔ÷?à÷Ýûý÷Îa‡ @æØ/oŸx?s0º8ßÏN£»NµmáóxÑçR¡½níßg9v$:Äâ)\“íÝ Œw��Å<6L£êv1÷žãXùöwì72 úû§Ÿô÷±�ØO °Õþùt·|XC¿¯iFXÙ¸†Å¹e\]½lÏ ¼yæ$�ß:æORDQ)óçò�g~òÿû0‚ÃÙ€ÄÚaî ­ì�Tv°É8cd†=³JaŽKIšPeRÎ0CW¹9‘d42 Ëz®m*\ÍEJ|ï™Ð͹#Çï½DÇŠö&ß›ëªdëÀn9\W“lÚoÎêr—²ø)I¡0{ü6/_5æL ߺ´~ùSã(¸UØw N�úñ_!MÏØnÂüì<Š¢ÄÊúµ[ÂücCveþ±\)¾·AÄò*¤SñÄ´ñ¨ óÈ;ü~Ë1JŒ2-Jt#ÙA)™ŽçeŽ [ÚOh™Lq^ø8m`b›Îp¶‰Ó!Ž åI&¿1+;ïæ«?е" Šw89­ÎꆓµÌÂ�½%Ì×_Ö_h'DÞIj2 ‚ÏÇ:rA˜?q'†õׯ¬X+Mëf¨í‹/žûö·àPн±ºúæ·–OÎøIè×LugÌ—[î±Äü‰ö%eƒo@ƒ¸c¢(*;Ó"øÈÓEŽ<©øëÃÜa™îâÙÓJä½í ó�|HvË‘?u7„óò•¿$CEõFåðgXO¾bq�ñîmx?{o©`ÚŸB|,˜¼Ù[0 �Ä _©�‚)¼7ó |€–õ`»ŒB‹˜Z\@5ÙÅú[W||Cú‘/ž?÷w8|7ûqo 'ïîþ 4ý`4âÚæ*¦§gPuºÖCNþZ~-&Ý…ùÉ�Œ,æSÒ™�Äd)É”›g~ Ö~ØÛs³^W 7âm¿Y† ‡\ÆŒJ¾«H!ÃÔÑŸ‚)Oñp…±Ìo…J I%T‹vìòÎÆgºñ¨½Kÿ.ß[4óå;+Á‹‘®3=…é¥y¬_ »dÂ×:{ŸÜ“Ü[„.\¢ý@׈€Q3ÄêÆ5,Ì, SuXʰåL$)ø],.‡{Øý5ó[Íaéç‚εSÌÁÇÏÛËs¦ÌïTÓ^Ôº´ÄóŽý+‚iŸHäÌûØC`‹Ð=ßÛžEíÊ T^èXæO´Ï 2?h»µ7¸sªîæŽÃê›W¬ÓéÍÑ?ñ�'ùòn=LÀo¼r‘´þ-@7€F]×X¿¾†ùÙ%”…¹,Â!7ˆü�wË\^cš¯Õìu¾á�kÄ[ÊüŒi|}F0 ·×؆3råîB’ˆtfe<”#í*ÿƒ÷L�)÷†4#Ü®»±ÄÉ_ÊüãÛ–‹O~%ç|s–ßÕ$�?ü£]ªŒœ°þ½i ¬*ÌŸ8Ž�·¯bh?{†Â¨á·Ÿ=ÿèëùíÄÀ±²öækK‹'®ôË0 Ñ4 æfæ±3ØñëÙ·v¥ÚQþ…krš4s\DE<ˆÌ5Ž61n⡦e<ÓæR#ÅÚ;�!Ç~Žfx‡U^躚˜4)TRJ°˜"Þdòu¹ß2«ÛWÅZ÷É–$Çq¹×àWXyZåHÓòO~]ÿ2JA‘(¾Dàòh×3bÛ< 4PT%î:�­wV±s}ËÔJ¨›O?õâ¹ÄãÀ¬¬^úϥŻ€ŸC{áçÜô<u|§ ¤IÈ®óýhè�Ñ i ðƒ$f�¬>IÆ)so%œçü"Ÿý7³T@9ÁÄË⃕ecñ¼�²i‘UÖdÞs®‰e‘”Êr#úÁž— r4ñ4”¾ZßFÓ/‰Qâ…�tô¹÷@2Q>­¸LHðþtå áÄ9ò@‰y]v*,Üu½Õu»Õ×¥é3Ož?ûiEÀÊê›–N.ƒð ‡5´Ö˜Ÿ]D=¬Í1᎕?òQºcþ|æ,«§!©’’ÿ&£<~ôÞÉ�g™vð|\ã‰Bˆ !¢'A¿ÛÕë� ¾’™J˜;~ ª*±ñÖŒjó©´ý¢ó‘'Ÿ?û»88d `eõ;_YZ~ïU~i­Ñë÷P•%f§ÌíºM|ihÀÑb~MáÌ.‹Â y4ÏO2]hU†~Ï ƒfòRT®ì/•Öñ–Ð@QZ^62ýÀHˆ5¯ŠÒ0!•„Q(#n“¾mÄè¢Hó³8 2S8$9¾M$ê� åÄï:�Aëo]6þ,Sͨé?}êüÙ?ÃÁ‘°²rñ•¥å»^%¢Ÿ0Iõ#Ý`~nJÙ­ÃñûP™?e>9ØóyCZòióä°!HQ4ñ¶Gm 60sí÷ÅEÚOüÃX@léÐ¥%žA0ž3»}C[=§¢,m�éÇÄûRH–ÉW,Øž_Ÿž}…é¾fd5±Z4 R¡MªÀÌò"fŽ-cãÊ;è­n°,z½á7Ÿ~áìgq„°ÛÐ<4ÜsÏN(pƽa¥f¦çЭ&°¹½‰ÞŽ9Yèð™|¹¢ŠœsÉo‰–Œ"ÚÌz²­1:ÿ�ÒL…¹­f†¼œØ~%I\àg%¦EÕ±Ó\ʤõ,å#ÈÞ+ ©ãé(t-gD[‡¿‚‘G¬’ð)±h¶<>L3Ø™¢Þ@ö LÞ«lÂäÒ±þŸ˜™Æì˨û}l^Y1§%{è¯�hôð3_zì51) ÀauõÒÆÿȽç67 àC€™ô;¨‡CÌNÏ¡;1‰ápNÃü”‹Ê0šN’4ÝnÌï±à2m(%;AˆFvfN2@]6?«ŽÚ)3!Ñè>Md•{Nwšž ÒºÀØ�!ÍêÀyyëCE¤.àEóIDATE M2¸Ì�$>a_D¯™ßÍÊ`5ÄÓ–r¢ƒ¹;�£;;�ÍËï`{uºñcR7J?Z]ì}ô©—?Ï�Å>2ȲÍQÂéSg~‰”~DïuaŠSÝLMÏ  p½·�á0v¦Ž™ug82MGÙˆ¬¶Í¹á!@Fûš�#,*Œ Dðüt‘XC±¶¹ÇÔ�«ÒȘ‚ÓD•%@Y1”®ñGýáꦘ¹•襱u³²vgaR¥’m•«Ñ{ é!œ(h–ï*�²ÓÁôò:Sè­®a{mCïÂ¥f¨ÿà >é½I €ãÚêÅ×'ºÇ>Û©Ê!€‡(B= ×Û†*æç0Qu1j†ñCFb󇧤ÊìÆ”š)ѱiÒh³�ÏǦáä��(rËùøÄéHy 8¥v�IU6^ OÒp^@|FI·fâÁwUå€ok'(¢<‚Ÿ ¸ÜÕäf�Ãôòú›[Øxû*êí¾_x8"}¶óNï£O~åñWqđ哣Š8õ¡û5ú Ñää¦'ç uƒ��z;Ûv7¡Å�0¿c6ó+±²Ì–ÂØw鉗 :aDYÍš%‹œ ¢È[5ã߆¢òK^Œ?Bû(¿ˆ¤u‘f4$€W¤CšC‹WgŸÝa)AÚ< ‚yé$} ”e‰‰ÙYLÍÍ@Q�­µ5l¯o"þ0‹ _©ßyúù³_Åm‚ÛJ8¼ÿ¾3¿ àSøÑjš2Ñ™Àdw ݉Ic%ô·Ñï÷íñcqê(dWþ+ìOή&Ä3�"éÈ0Ìéã¼P‹+cì\n9�Ï8Š�ˆ2� õ #Þ2G‚“ÊhK„çÛ±È8]ÚÜŒ5¡I:m„81�µ�û•¦‹g7üDý–¬ý—ºÓSèÎΠêv1¸¾…ÞÆ&êÞŽ|Ó¦³¾9‚þ«çΟ{ ·nKàpúô?H�þK}��!"t»]t»Sfz ôû;ÔÔƒ�H Ü óÇÃ<l·Nz+LTKF‹¹á)qƬðr8ƒê4�³\„ö³VEb T”t˜ÅÇëà1œÉaOR$⯴ß4·É[ †q¹ÀPÍâuH'\§°×^¨Õô$&¦ºèNNAU%úÛÛèon¡¿µøS”áZãUé¿yæÂçþ)z{á¶÷ßsægIÑø¸ƒN#ªª �Nݪ‹ªÓ�¹M»Æp44CóY²†6ÂAóÛ|ve~7h£c ’!Ât‰X£å¾DnexV²+æ’L°kBEV¨¬àè2fsÒNp˜:B€�³ö¥VÃòãéÌ!ÊEN«r„¡– ‰“’«ÊœRëÜ޶Â$d¤Ãr%§Ï-ú® ï¬ݸb�à”Sò2Ä =‚«[ó¡.kõX0j4¾V/©Z=öÌ—Ïy�þ÷‚w­à¸ÿþ3³J?Eh>¬Qü  „ ž&a¾|ä 0¿°‰Žóã8f~@ø2^’Áýør%À$•ßñ§À2_¯æßÅ‹º\¹¡ TUp7’&Ë� sͬ•ø´·rB%tc|.”XX|7_ÎSþˆ8d… 4#|« ýïº)_¬7{ç_øêëx—ãÿ…Hñ±âôé·î®¨<Ý`ô~Ýè÷i¨9¦ÌX0‚?±ôƘŸ1^"rÌ$+,M(–" €h#ŽM²—s°:¸¹�À\‚ˆ¢´WuIàõ~�àf±¶Å‚–ˆ3÷8À­€�W~˜äĉ«ÕJëm�ÚôiÚÒÀ)ýmÕè×j­þ»,êo|é¥^þb·K+[´hÑ¢E‹-Z´hÑ¢E‹-Z´hÑ¢E‹-Z´hÑ¢E‹-Z´hÑ¢E‹-Z´hÑ¢E‹-Z´hÑ¢E‹-Z´hÑ¢E‹-ÿ,GAž~¹(IEND®B`‚heldercorreia-speedcrunch-e7ca37f/gfx/icons/32x32/000077500000000000000000000000001526573132500220155ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/icons/32x32/org.speedcrunch.SpeedCrunch.png000066400000000000000000000040531526573132500300200ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“àIDATX…í—Û�]uÇ?kýöÞç2sæÖ¡´ÓÎLo KAî�ª„jˆ@0‰ÁôÕƒ&yÐãƒÆ˜È&5$F*„H�éCËE ”‘Þ§�±´Ã0�™Îœ9gÎÙ¿ßòá·gzMüt''ûrvÎú®ïú®ïZþ×¹ÔÃ-[îèëêý©ª~• ƒˆUÌ „€>äøðÞ‚ÇÌ>`!© GÔ±k¡1óÛÑÑ�&þ+€[núÆ÷j�¿k·ZÕà ‘øŠ†™/@ä ä>‚LJ`)¸ÃÌà D'nÎÔï8p`ïÎsã¹ ƒw”+O6šÍLq$I‚S‡ˆqV¼Lb€â‰…"[zS$>4#„Pr’<°¢oèã©Óã#1°åÊÛúV j6«NSÒ"¸S‡·"kÈ‹Œ½Ï‹s ˜_.C°%Bb‘…ˆÃp.=ãM6>¼g YPë¿ü'Íf« ‚ˆ`*Ѝ" ”Ëe>÷¥ëZw5}•>Ê®„k)YC¨ÍO²ÿØ^?øûÿ}t‰ –¸̬«ZÊ;€ wçy›$I#­¼‚ÌH²Œ/lßN×uW1<0Œ_¬âæ=í¹Í©9úêž+V]ÃæÎaîÝzïí‹§ß~�§Æª‚åTMî½@í!C"} €H {ÍZ6=ü­R‚_ä³V�¹Ñ¦>>ÂÌø�ÉÏèuÖ¬XͦžU ®dÓšÍüòþõì|ÿoì|{¢‘Y LÙ°w€7© Ä ÃèìëaÅŽ‡˜îé'm6Yüç;ìÙù,‹ós8—a€…À‘àyÛ{Úí­Üìà¡Û·±ãÆmô”2ž|s7RÔC�ÚEÌX Eà‚ÑÏ�¸Î~š žÙ]/räÕWH4¡”uDñ…È–ªJ¹R¥"Âl>Ëo^ÛÉ»«ôw÷ÄàK‚8§ùÏàñÁÍñ–`T„�× RÏëtÔ£{þN¢ Þf�Pô» §BVô¢P.•ðæ™˜›BD£&Å0oËt¹>`!‚ˆn—“O%_$ó Æ�âÊ¥ë²Ë°!`³Ö$AÌ@5ÆÁL±ØŽø€åž¨ì ¾ž�xÃTQ1Nü˜æš3´º§/gø[�1ä§ðs'™=°�ÙñãÌœ8ŽÏ¥`D‘ÈŒåVŽÔ+‚:w1o…•š¡ Œ€ð�göpÃ#Ûéèìd̦89_guµŸÎMW±ò–-lÌ}‹ŽR}�0=Éñƒrðݽ|26 ¡]Ô^�Æ(*gE°|uÝ5Û¬�·A´0 A Åh­ÌMßÝÎÂÀ gê9Ýtw¯¦Ïy:òJ¾EÉRú}�áù>*‹uÆæŽñìî�=²¯°ä‚„$My÷ý—Ι+W®ÿYžç‘D‘„¨%ÄGß|�‰=Àô$h uŽ®î~\Ö‰TfJmêµ]Ûɧy G„ë7|žIùäÄQÜý"$Îqâ䡟Ÿß!Ä¡A@ƒbbhâPUÌŒ,«‚ÓûÒ~ïCFsÇ»>§Ô×C÷šAz×­¡ox˜Ž­eV ^Îd~bŽ[¿|Ó3?6‚Iå%5€Á,¶… .ÑØ2� ¡”TH4D•/4¨´ª�ŠZ©´•úRU­Z‰R"¤¦)Q�†�AбCœ 6Ž/‰íßâñe.ç¶÷Z_Ö:gæ8v â5[3Ú÷u¾ëÿû߆7¶7¶_k“_å¡];wßnmé“#ÍÑ»fPFñÅ{EÕ£Îãã¹÷U�÷.ì�â¼âq¨WP�÷ ª(Jøó8§^çzyç1ÿà¡C{öýZ ÜzëîmõrãŸkÕú{½zZËËx /iøÑðãQ¸ ŒâÕ‡ïùwxU‡z?xW5,ÎAH³,\p½ovœÿÜÑ£O¿ôÿVà¶w}tb|ÍýεN»ƒˆÅ ˆ ¯Aß·¼G}ÚKÞ+^^ï\<÷(ºJø¨�€ô¯Eu’$EÄ.å®û©Ã‡ú�+Éi¯tqç-¿yÏôÔº[Ë­RžçI°b0ÖbŒ1ˆP# }K)T„ÆÊ¦ñÕU–“UïöÏ%‡0óY9Mï©×Öî½piîÐ/õÀ­7ïÞ6>5õ“Nk¹æá�'¬´j±�‰»*¾U#†mwîdã»Ø°éz‹uÚ¨vsʾËÂÅš÷HÔòæòZÞ¾u3Úø.ZwÞËž¹çøæž'Ø{øýÕ°ïŸc-ÆI«¥{€++Po6ï^^^ �Cháâ~Õ=϶wîbd×ëz��4¡SóH"PËXZêÑIR%9¿ÄòXJ5©“õ,5Ÿ°sÃÍÜ8±‘ç�üŒûŸù>Ç_=�¢14% Ÿ áªY’Ý üå@YëœÇÜñÚ+ƒ (i)åÝŸù:׳Øé E‡ånÁYq”Ë9�Ó'8qlŽK§NÓYXB––9BÂds’5õ5\_ŸäÚú8 ­KÆÎõoæ¦õ¸ÿ™'yl߃µMVBI”õ«EVš°‚ñ6" *à"'B©Zææ?ú,g7m¦äs\^ =¡ÔéðÒCñìÃ�rnî#�„vÇÆ0€Âxïq.§È•rÊ;oy»nØÁÛ¯ÛÌL¹Áçïú(&§øò“�…$ 0@?±L]Uç½õê1bB¹WÁ!aÅ Æ�nº÷œ_=¶ð,¨aÊÚ{Ÿæ«÷?@)«QÊ “ã£xUª5BÐ;R ëªf±B{~üÂÿòä3?"I,÷]|bûoð'·¼ Wä|åGß�’| :ˆ½ªêܪ°±õ¨78ñQð†vnãü�[M ËN©ø‚Ã_¾�—÷<ÇxslˆJh̛ո®1$©%É2²rŽÿzêüÇ“ßæCoÏŸ8áVè·‘H/ŠG1^ñƃ7 1‚÷Á1±ë-d™‡n�,u1G÷3ûì>ªåR~AÓ>ÃéKïC%7 "‘BhÅP­X(§<ºoåÌ ÆÞ%¡²K_™«æ€jà+F±ÞáW@<ˆ8X»nœ–öèä–vž ó-Ò¤Ô/6�¤ÅJÛÏ'0‚‘”mÓ•b%ªèªL­”Ó@ŒÔ@Œï{§ nHä!:àbÙ'PaV(�S�HNê»y›…ù3ØêÖß²=’´á½z´^xá™'~ÊØ[Ö‘N•©õàlžsaΞû!3KSŒÌ¬£:Ù$»ívêÙmL冒³4(0—.оø*'àô¡CÌî?€+òàuïPu� F‹k_x)Æ {`˜ÌíØ­íV ˆÙ¨`"› ¦ð»?÷q̦kxå¼ãÌÅ‚DKTìÕÚ½N—ªÔ+BÙXF’*cZc,¯Ñl•©:!©C'Ydßþ=üìÇßáðÁg‡ûŠhuÐÐD© bH“Œ=ûÈ=TÖNoúB/Ïã*:ĉú‹i좞{t/cÞ³aÝããMb(kA¡J³9ÃH³ÉÌè(©MÈL›Ü,sBg9î_¡7ÒC–zŒ¿jx›Ÿà¶m·qíöœš?ÃÒ¥ù(|ðxèÍ ù“$aîÔ¡¿¹¢kf6}!/ò˜}üÒЩöÙ'¡/¨V+ÿÅ ž}øIdvq�ÄÒ*•±�•j‚뎱�•SÄÐK…‘™åkšœÅs"Ë‘ö2[½gË�;™wžWO1@ŒÁ;@’4eöäK†“8b¹¨ÄÄ húƒ$0C¯ŽRÙR.�2ûÒq޼ð2½^efóõÔ¯ÝD:>Íè5ë˜\·†J³J‘f8/œ;¿H¹Ñ 6U'©Ñ^7Å‹.`gOr÷íDµ`ÿ¾Fä‰y@DÂËzÈaVF‹<#‚I Æš@Еû„æ;I2êõ ªJëÌYææp¹!Ï»…ÇkÁäºi×m`fë[Éo¹•kß¼•†Éèv ÚÕÙ5É.\äÎ÷}„cÇöÓY^Z!q"�¡¦é�Ã!4½ñ yÌ�A{g 65� úƕ毟*áŠÐBÔ�$B)M)—KÔÊ|^Ð>s†“ÏïçÅGæÅï>Ni¼ÎȺëhkÔ«F›ct»mN;B'ŒI’rìøÏ!4\‰u…·¨zÄXLùHnÆqHÌŠXµU•"/pE¯Çü!T[c,iV¦Q­0>:BÖmóÝú"ÿó/O=_dÜwiH�”.kÆ'‡}¤öuÈÜ O4!\Ä0aã)W+´[D‚€ª¡GÖ~À º &’1E0Á`¬0:^áÜ û˜ûù3T6ßÄ+ó§i]ºH½RŠ˜¿j ‚y=2§^c¬Û8~#4�1¨ÊÇîy+o{ß4_úÇç8~ø<Þ9|<òõÈqúl0¢ ŒøP¬Œ�4Å ”KuŽŸ;†�¨0¿Ô"_n“dåÁ mezñÚB6䛆þ3ô¾á�/«ÂgiO~hŠÇñ×Ûyçû7ã�[5ÏéÿX +Õèóù8¦ÉÒ¨”!I3F×_Ïræé$jeæÏ�ÆÚ÷bBŠ =òUè[½_´Pôç÷ÞÀïÝ!,œ;Iwq�5¥¿ÿéëøÃ¿º“µ×O†Å91¼¿¼€‰ó¡¾åEeÐÔ¼éwÞ�];I7I)2C:ÞàÔKbS?\ä2½,„G£QE°æuÁ©ª¥ßdÄ0øò·_溵[Ør½P¥µÜ¢uq�æÄ&m‡ù$aÛ;&˜Ü–rêäs‡Ý‹%.žî²tú½VŽñ–tl3=E23E}ëM$[nÀ¦ Í̲”; ï™X\dÿ¿ÞGš•0‘@J?VT0v¸£f£*óŠL›¡kžù K|æoŸâw?°‰�¼·L½¡ØJgZ4u‰ŽÍ¸à)eLLYªõ�Ú@ÏÖÈ´ŠóU޶¦yÕ×1…%s)”Ëj(¼âs�éŒÏŸãЗþ ×Z¢”–Bš•™¿º ³Fd:ໄ¹ qU«–ùÖwOðí'z|øƒo⽿­¬¯A5mÒp‚+C¥:Fµ‘ÒNÁhAj È=MÓÁCJ–Y–m‚óJ©€´›ÓÝóž{ð$Ï©”ªØÁ<Õ€‘•(2æôj™‡RzllÃÆÄÚw{¿®xã5@X’XŒÉøùÁ¾ñõ<Øe±W†´J³d¨©£Ž¥–•)gJÅB… Û)�eOÅyLá¸ØZba¹Kê…bß^æúOö}ó[4Ê%ÊYcc ¶Ï¿$Pû¬RÆçî«/}îñ+z Ï;%¦òyWƒ1Èê©úƒrf©”F8ðÂižÿÙ)º½�±:oÝ>Í̺µ5eJceSMœ["/Ê,öé.vi/åœ?y‘ÎÜFÞÍiÖGY35…5‚�He!ÒÔF0ª®xp(j¸l»qË_÷*.Šb`y‰Y4D¬bÁ2‘%¢ç{E‚÷E\ªIR¬±$‰%M3Ê™P)W±6|< 6Vg q"“X“&há{èÑû>pÕèþs%›½ÇZmöð%âÐSãp.ˆ±$I•,Œ”£!@Ÿ¤¥°ÁˆÁâÜGß$~J��å#lK"²œ{ýÓËå}ÍŽ£Gz¨ëz÷Z“8‹ª �­Úëkö2 QýjÛ/bÁY!†…U°_¢«¯GãKZ*ûv×}ú¡Çÿý¿T�¨Ä#¹/~+³ÉÅÄ&«,NŒG]5êë_7«”•¸�…Hú£™¾ðºêÙøœö€àm“&˜4m·—–?õ�ÇïûÚ•d½âG>€óçg�ŒŒ]ó5+v}’&[ceØÂ+B?øâ—Ä�ýc“5ÜCDŠ ¾¿‰I%Ã&%¥ðßñyñ‘ÿþÎWž¼šœ¯Iâ+m[¶¼k»>–%¥ÝˆYo„ivµÅCÃ$‘·´"&¥ˆ iŠƒØðL2PÒ„b%âŒÈysÊw{Oæ�‡¿wÿÓ¿Š|olol¿Æö•RÈeÊÒIEND®B`‚heldercorreia-speedcrunch-e7ca37f/gfx/icons/64x64/000077500000000000000000000000001526573132500220275ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/gfx/icons/64x64/org.speedcrunch.SpeedCrunch.png000066400000000000000000000142221526573132500300310ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞbKGDÿÿÿ ½§“GIDATxœí›Y�×yßß9Ý}ûn³af°’ A�")HW‰�H‰-FŽ¥8RbENÊQªâ*?¤§’<éÁJYyK©*®Ä®TEVäDRäD,j#mwÜ� ‚Ø1sgæ.½œ/çtß;Àp±’<™]5sïíéÛ}þßþÿ¾3ðîñîñîñ7ù�_ç;7ßü‰ýþž»¿™¶7'i²9Žâu€ NQ¥´D§þ}éWâTq¢à¥ ¯ª¨:@qNAêÅ¡ª8EQ\™÷³¼<žå£“Ö˜KÕ{_y剧þ @nÜ{Ïç;�Îg§§/WU%Ë2†Ã!®,аü BD‘ !¡�4Ä6f�õŸŽÊÏ;öä+ÿ׸å†{îžžšùf§Õž={þ<" XDã?Ô‡ªLÐp%ç¼ «ógU�w çpµ‹8´º®ú™¯ë,"Aá™"AHBš¤ä¥;§£â³¿:öè�~mܼï7~snná^+&ZY]AD±1ƒí‹VJò �€zsvá½ÖàÆZ¡êð^1v *¡BmQ¢øçVVAˆ Aª�Ä ˆfùhxÏáWŸúé›a4oö‡½{?vM·;û—ÆHÔ[é�‚ÁˆxðÆ[�E0XŒ1ˆ1`Œwã¿•±ˆ¹‹„ë&ÝHÀ{–©µ#–&ÕÍjÊ„Çïò"%±qó[»v}àê¿®¤·¾Õi·fzË=¯yÄ›=âÁ#ÞŒ%2ª¬Ä_7F–.&Üg755xŒ×§ Ô_žÏÛ€—±�ó"'2vSdä«ë¿ø6¸qïÝŸŸŸßô¾3gÏŒ¥„€kÌ»ƒ¢1ÞB‚¨‚†Ãu&”X¯¥¶†ê¥zÆøŠðý Àó&à'®Fù�8j|p÷•øÌFX£ ÎIš¦<�&(¬_« À›=Z•Á?ÃÅ:^^•“:Ý»¯½Žm—íbÓô Û¤•6 @‡ÍV„ËGôÏŸâð±WxêÅg8}î eYÖwÀ‹„©"‘ê©‚ª#JìŸßºìÅ'öí»kÿ–…­Ÿ?·„1•™ ÆDÞÿƒ�[ñ~_™¡ê8µ9u!ŸûÀ¶¸u3ïÿÈ~.¿þzæ§wra˜PŽ„fÖ'uÊ ËX[ÊÐþˆ¦X®^ܶ~†.õÑT9::É�#OsÿóñòkG©Ò¡?Æé^Ç'/�ÖLSrWÜô ?zòü% *Ÿñ’Ôñmªˆ+B�qp¾2«òr�£P'ìÞ{=;ößHs×Nf7o¥U69}†8VÈ“ ½~†³‰…|8B—Þ hm"™K1ň÷Dó\sÃ=|âÆ�ràÐã|ý‰ñ«GükÍ�­£ÊÆb±l£¹ùmà­`ŒÙï\Y›±¿·¢ª±ªUÁ¨Cƒo×àUÙ|Ù6ö~êN.næœË‰V‡´º«¸FŒv-­Rˆ�¡á ÃaI¾jЬÄZGkm•~c޾ vJîr2W°góõ|é®íúÏþ-WîÝ FÆ-®ÐôTÜF€VEW¥ATQ„Ì#þ|ÈDUÇ@#êѨ£,KÊ2÷ë5Š'ÛZ÷&�Kc@ˆÒHèðVf¥WóoW×Gg_=ÁüuW�EftŽÅYË ¹FïÔ¯ÐÕk˜ûè°xçYFDzöú1^ÿÅ3ôVV°&Ä7îõM4y¼ÿà>T©Që ¯ruQ¥,qUF!4bÔÈFIàR”.&!˜ŒÿŒQ£ŠŠAq<þ½Ç¹òνœ8sгyƨlP˜Ù|Æñ³Ó¾�ÖÔ6ÌÕ‹ÌîulþÌïÑè/3:õ:k§OÒ?wšs¯áÂñ£ 9H|Ì¥E}öQÝW&.u%eâK¥ •`M‡o ¾“4(.>lTª…øþ¼8Á‰xKè]8Ç�oÿ„éí&µ… ‘MX* «óp¤ws®ÉæÅíL¥›)± fç0›ç°Ñ�eqíD±ýUè�fpî,g�½Îé~ʼn—^¤ÈFu¯AÄR®Ä>¨oÅ\gCäwhýÛ»@hV™×š‡@|ªTÌÏËCß|�OîØÌ¶›.çØé¢–Q@%䛦i�}3 wîælA»�ÒžiÓšj ¦I×$´Ö ­Ñ-6Óšƒx‹!½C˜>§Îáð3ÏòÜ#?åÌ'‚MR8Z•æ5èðZ³¡PðÊ¥1ÿ‘ÜzóoêÊJ¯nW‰ø¦‡A!ôô|¦·¯œ:z½5îþ½�óž¿û^)K½œÁšc´V2kRÒ´CÙÞBÃÄ—C¦Ë²F3"š6%Õ&í¢Í¼Ì0·Ö¢;ŒH¤ ?5d)ÍøßÇŸæñ‡àð Ïø!K]îW]Ī|— °J�Ðh¦<þäwÖa¾T7ý-­»ÀÕOˆÀ¼BLí 8W°ºÚgÇ®­Üô©;™zÏ•¬F FYL6„^VPÆ]Ú�Ë0¶Î&H®(hÈk -97\aii‰ùNJ«Ñbf%aþ\‹-« [³eœÜÜàÀÉ—ùîw¾Æ¹7ŽŽÕ^y«C§ËFšòØS÷½5Ú¶e÷GùD?P«û+j@w�ªñ˜¢Ø(¦ÙjÑ»0๟àµÇžÅôÖh[!k68e ¦5…‹„îL“T E&8 Æ(‘–�XúH"$Š™^ØÄ¦[XÃqòJâÜñÓœ>ú:eá(]N«#ÆÐY˜gûûoáÂûnàª}û˜›ž!Ç!\è—8c™Ý¼ˆž¾@ª%·Ýý;}õέ'>ãÉ“Á&ñÛ  æ&¢µ)Uu»1¡ÙhdLdÖ�óø †:7W΄€+qžÒF I�ç=ïÈY=½Â/ðž»ï^™îpÝÝgÏ]¿ÅŽ+¯f�’$2¬hÂô¦M…N²ƒË¯ºžc‡U ƒ7gl0Ôùca„ÝxÂRdžIVL�ñêÏ”ÎQdžœT’®õ˜Qd-QÒ¤ÝJ˜�ê°inŽHÏß÷=¾òÏÿ)�üà`ã’8V’“¦ ín“™ÈríU{ÂìÒ`�ŸcZ‘º�gÌ;p�JzO7LMh=H&è¹j>Rëx2€VÂ1eî5?¦ê–ÐOMˆAÖ@”´I‡s-ü³?cÁ6¸éÆ;Hr�R95ìQæ#¢fh†H�bì–F6nÜ „ÂFc-•*«1t@^_?3Û¡·<¨„VyM�˼êˆgž•R*ž1 Þ3^ƒ ˜¨Ad-ó�”Gô×ÞpKƒN]x�óVXhOÓìN…ÑåOÔ‰8 —dý�&C~q6ŠãîÏÆ:ûû®«ùƒµ‡gŸ_ãþ”ßÛƒâÊjÃC¥ ó¶©K8 ê }GSÕñ"Á-FAM£UŽœ:H$–5 ”,�†LçÕ¿º³NÄ� <`DQ-+ó¬† x/Š÷^·•ý/öÒžÉØö±Ýùñµ/ ·Ô«¯6H˜*Fç:‘”�©�Ì7H&ëù îf¶ìÞM. Îäœ 0V(1çÞ8†�¨«VXµ†ñŽƒñq‰LÄF’í ±¢¦u/ÎkøÖ=Ûø“ß¿œ.KDÙˆ®Ë¹íý%ÿòß}˜÷Þ|y]EžB3µâçu;¯-­ÀKmþˆ 6 à%€Wld¹ì–›I§;±eDAA4Ýáì‰cžõ…!®‘ñ6ƒØw ª, LðrÓNàö}ÛøÒ?ž§õX¾ð½óÐRèjÉŽø'´�ßý£Û˜Û:C]…áy¥„:ÚÖö¥µHàñ~c‘¨"\¼‰®ûÌ')7/2Œ`9I0i„6,±ësâð+õ~/à >³AoRIퟓ>ïƒ÷Ç?p_ül—8-8íüƒ×z9QÜ`jnšé¡ÒÓ5n¸©Í5{?À¡ç—yì�£œ8tÚ�ÔÔG~­f¬jBûÊx_�âºí#¢Ì]³›Å»>Â`aÇ P.äÊâô ý¢àä£�£XIêèïxA(`ßQK S[€¿Oå9Þ|—Örέ5Ù’dý³D¬ËY½p†öÔM³%‰XŽ#ZÖ0}g—]·Îñ¡ã¼þbΉCοtŠb˜…*3d—zwˆ‚mМ™anßû‰÷í¥}íµ´Ó„D¡›XÎŽ š Šcó¡gyð¡Çi·šT¡ª¬v¦h•VÞNeQ®c;ΕãöóDîçŽsÏ�WøÒÞξ]‘…(ÏÉËŒQ^Òi´ÊeF¡03 Ó’mWÄLm-Øqk‹8¹ƒ^ÖbpÁ1<»Æ¨_Ræ†�™"‹Ú47m"�ZäÍ.»ŒQÚ$CiŠ�  %+=1³çÏpà?}�f#ÆJ‰×<1!°ëè¿­ò²>Þl¯°æ…û\Q¸3Q”Ôµ|]\˜ñÅŒ_=xjB ¸žOø¦„—� >k=à qkí¸tõR 2&7ö7Öa͜ƣsc I£�Ë‹^\ÿh#ðo%^}õ±WË¢üûªšÅ± ¼@PLxo|-^UMýwÔ®ºB~íˆ1W_¬¤Ú0½¾–‹}tà Ô–ÎWM�(NP!Ãßùï?ú˃o†óMpøÕG¦®¸K�œN“FÍü,¤¢Ê,q‚0Õ «µÞ3~?®õ'^e}SsRÃãh%<O„ª•ÄÍeYôÖV†Ÿ¾÷ÿåþ·Âø–xñåÇV3ú`^ä�6â†ÿG&ÀMh­^z½æõ¤[Mhvܾª`Œ¿wq|Y×C©¸¤Tí8%J$íÃÁð™Üå·Ü÷£¯~çíð½YÜðÚk¯Þÿicâ/E6ºã»Bõæh§‹U?­ ®!¢„ mhTjL„µQD«‰Ž_âÕÿƒ` '–(NüÎÅhx¤Ä}ñ;÷í«ïÔ_Cõqýî;nÀðwÜY»=²Ñv±¦S›­„-,Z)³ú¯‘Š¡ùÍ ¢¾{ë-‰“ðw©!b4\ïÓœ AÑPŠÌ�Ò²xC�‡i&õýïå±_ϻǻǻÇßÜãÿ„ÍQîErûIEND®B`‚heldercorreia-speedcrunch-e7ca37f/gfx/speedcrunch.svg000066400000000000000000000224341526573132500231520ustar00rootroot00000000000000 heldercorreia-speedcrunch-e7ca37f/pkg/000077500000000000000000000000001526573132500201165ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/pkg/COPYING.rtf000066400000000000000000000476671526573132500217670ustar00rootroot00000000000000{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Verdana;}{\f1\fmodern\fprq1\fcharset0 Courier New;}{\f2\fswiss\fcharset0 Arial;}} {\*\generator Msftedit 5.41.21.2508;}\viewkind4\uc1\pard\ri-22\qc\tx284\tx568\lang1031\b\f0\fs16 GNU GENERAL PUBLIC LICENSE\par \b0 Version 2, June 1991\par \pard\fi-284\li284\ri-22\tx284\tx568\par \pard\ri-22\tx284\tx568 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.\lang1023\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\par \pard\ri-22\qc\tx284\tx568\lang1031\b\fs16 Preamble\par \pard\fi-284\li284\ri-22\tx284\tx568\b0\par \pard\ri-22\tx284\tx568 The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.\line\line When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.\line\line To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.\line\line For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\line\line We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.\line\line Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.\line\line Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.\line\line The precise terms and conditions for copying, distribution and modification follow.\lang1023\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\par \pard\ri-22\qc\tx284\tx568\lang1031\b\fs16 GNU GENERAL PUBLIC LICENSE\par \pard\ri-22\tx284\tx568 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\lang1023\b0\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\lang1031\fs16\par 0. \tab This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".\lang1023\fs24\line\line\lang1031\fs16 Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.\lang1023\fs24\par \par \lang1031\fs16 1.\tab You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.\line\line You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.\lang1023\fs24\par \par \lang1031\fs16 2.\tab You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:\line\line a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.\line\line b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.\line\line c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)\lang1023\fs24\line\line\lang1031\fs16\line These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.\line\line Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.\line\line In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.\lang1023\fs24\par \par \lang1031\fs16 3.\tab You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:\line\line a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\line\line b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\line\line c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)\line\line\line The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.\line\line If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.\lang1023\fs24\par \par \lang1031\fs16 4.\tab You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.\lang1023\fs24\par \par \lang1031\fs16 5.\tab You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.\lang1023\fs24\par \par \lang1031\fs16 6.\tab Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.\lang1023\fs24\par \par \lang1031\fs16 7.\tab If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.\line\line If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.\line\line It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.\line\line This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.\lang1023\fs24\par \par \lang1031\fs16 8.\tab If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.\lang1023\fs24\par \par \lang1031\fs16 9.\tab The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\line\line Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.\lang1023\fs24\par \par \lang1031\fs16 10.\tab If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.\lang1023\fs24\par \par \pard\ri-22\qc\tx284\tx568\lang1031\b\fs16 NO WARRANTY\par \pard\fi-284\li284\ri-22\tx284\tx568\b0\par 11.\tab BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\lang1023\fs24\par \par \lang1031\fs16 12.\tab IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\lang1023\fs24\par \par \pard\ri-22\qc\tx284\tx568\lang1031\b\fs16 END OF TERMS AND CONDITIONS\par \pard\fi-284\li284\ri-22\tx284\tx568\b0\par \pard\ri-22\qc\tx284\tx568\b How to Apply These Terms to Your New Programs\par \pard\fi-284\li284\ri-22\tx284\tx568\b0\par \pard\ri-22\tx284\tx568 If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.\line\line To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.\lang1023\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\par \pard\li142\ri-22\tx284\tx568\lang1031\i\f1\fs16 one line to give the program's name and a brief idea of what it does.\lang1023\fs24\par \lang1031\i0\fs16 Copyright (C) \i year name of author\lang1023\i0\fs24\par \par \lang1031\fs16 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\lang1023\fs24\par \par \lang1031\fs16 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\lang1023\fs24\par \par \lang1031\fs16 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\lang1023\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\f0\par \pard\ri-22\tx284\tx568\lang1031\fs16 Also add information on how to contact you by electronic and paper mail.\line\line If the program is interactive, make it output a short notice like this\lang1023\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\lang1031\fs16 when it starts in an interactive mode:\lang1023\fs24\par \par \pard\li142\ri-22\tx284\tx568\lang1031\f1\fs16 Gnomovision version 69, Copyright (C) \i year name of author\lang1023\i0\fs24\par \lang1031\fs16 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\lang1023\fs24\par \lang1031\fs16 This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.\lang1023\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\f0\par \pard\ri-22\tx284\tx568\lang1031\fs16 The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.\line\line You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:\lang1023\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\par \pard\li142\ri-22\tx284\tx568\lang1031\f1\fs16 Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.\line\line\i signature of Ty Coon\i0 , 1 April 1989\line Ty Coon, President of Vice\lang1023\fs24\par \pard\fi-284\li284\ri-22\tx284\tx568\f0\par \pard\ri-22\tx284\tx568\lang1031\fs16 This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License.\f2\fs20\par } heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/000077500000000000000000000000001526573132500231775ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/.tx/000077500000000000000000000000001526573132500237105ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/.tx/config000066400000000000000000000006551526573132500251060ustar00rootroot00000000000000[main] host = https://www.transifex.com [speedcrunch.desktop-appdata] source_file=desktop-appdata.pot source_lang=en file_filter=.po type=PO lang_map = ca_ES:ca, cs_CZ:cs, de_DE:de, en_US:en, es_ES:es, et_EE:et, eu_ES:eu, fa_IR:fa, fi_FI:fi, fr_FR:fr, he_IL:he, hu_HU:hu, id_ID:id, it_IT:it, ja_JP:ja, ko_KR:ko, lv_LV:lv, nb_NO:nb, nl_NL:nl, pl_PL:pl, pt_BR:pt, ro_RO:ro, ru_RU:ru, sl_SI:sl, sv_SE:sv, tr_TR:tr, zh_CN:zh heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/ar.po000066400000000000000000000071321526573132500241440ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Arabic (http://www.transifex.com/heldercorreia/speedcrunch/" "language/ar/)\n" "Language: ar\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "آلة حاسبة علمية عالية الدقة" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "حساب;حسابات;رياضيات;علمي;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch آلة حاسبة علمية سريعة وعالية الدقة. تتميز بعرض قابل للتمرير مع " "إبراز بناء الجملة، وهي مصممة ليÙ�ستخدم البرنامج بالكامل عبر لوحة المÙ�اتيح." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "يتضمن العديد من الدوال الرياضية المضمنة ويدعم ميزات متقدمة مثل الدوال " "المعرّÙ�Ø© من قبل المستخدم، والأعداد المركبة، وتحويل الوحدات. ويتكامل ذلك مع " "واجهة مستخدم بسيطة لكنها قوية تتضمن معاينة Ù�ورية للنتائج، وإبراز بناء الجملة، " "والإكمال التلقائي." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "يتوÙ�ر SpeedCrunch على عدة منصات وبعدد من اللغات." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "الناÙ�ذة الرئيسية مع لوحة أرقام اختيارية" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "قائمة الثوابت وكتاب الصيغ" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "واجهة مستخدم قابلة للتخصيص" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "دليل المستخدم المدمج" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/bg.po000066400000000000000000000074641526573132500241420ustar00rootroot00000000000000# Bulgarian translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: bg\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Ð�аучен калкулатор Ñ� виÑ�ока точноÑ�Ñ‚" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "аритметика;изчиÑ�ление;математика;научен;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch е бърз научен калкулатор Ñ� виÑ�ока точноÑ�Ñ‚. Той предлага " "превъртащ Ñ�е диÑ�плей Ñ� откроÑ�ване на Ñ�интакÑ�иÑ�а и е проектиран да Ñ�е " "използва изцÑ�ло Ñ� клавиатура." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Той включва много вградени математичеÑ�ки функции и поддържа разширени " "възможноÑ�ти като потребителÑ�ки функции, комплекÑ�ни чиÑ�ла и преобразуване на " "единици. Това е Ñ�ъчетано Ñ� проÑ�Ñ‚, но мощен потребителÑ�ки интерфейÑ� Ñ� " "незабавен преглед на резултатите, откроÑ�ване на Ñ�интакÑ�иÑ�а и автоматично " "довършване." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch е наличен за нÑ�колко платформи и на различни езици." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "ОÑ�новен прозорец Ñ� незадължителна цифрова клавиатура" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "СпиÑ�ъкът Ñ� конÑ�танти и Ñ�борникът Ñ� формули" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "ПерÑ�онализируем потребителÑ�ки интерфейÑ�" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Вграденото ръководÑ�тво за потребителÑ�" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/bn.po000066400000000000000000000103751526573132500241440ustar00rootroot00000000000000# Bengali translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: bn\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "উচà§�চ-নিরà§�ভà§�ল বৈজà§�ঞানিক কà§�যালকà§�লেটর" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "পাটিগণিত;গণনা;গণিত;বৈজà§�ঞানিক;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch à¦�কটি দà§�রà§�ত, উচà§�চ-নিরà§�ভà§�ল বৈজà§�ঞানিক কà§�যালকà§�লেটর। à¦�তে " "সিনটà§�যাকà§�স-হাইলাইট করা সà§�কà§�রলযোগà§�য পà§�রদরà§�শন আছে à¦�বং à¦�টি সমà§�পূরà§�ণভাবে " "কীবোরà§�ড দিয়ে বà§�যবহার করার জনà§�য নকশা করা হয়েছে।" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "à¦�তে অনেক অনà§�তরà§�নিরà§�মিত গাণিতিক ফাংশন রয়েছে à¦�বং বà§�যবহারকারী-সংজà§�ঞায়িত " "ফাংশন, জটিল সংখà§�যা ও à¦�কক রূপানà§�তরের মতো উনà§�নত বৈশিষà§�টà§�য সমরà§�থন করে। à¦�র " "সঙà§�গে আছে সরল কিনà§�তà§� শকà§�তিশালী বà§�যবহারকারী ইনà§�টারফেস, যেখানে তাৎকà§�ষণিক " "ফলাফলের পূরà§�বরূপ, সিনটà§�যাকà§�স হাইলাইটিং à¦�বং সà§�বয়ংসমà§�পূরà§�ণতা রয়েছে।" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch à¦�কাধিক পà§�লà§�যাটফরà§�মে à¦�বং বিভিনà§�ন ভাষায় উপলবà§�ধ।" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "à¦�চà§�ছিক কীপà§�যাডসহ পà§�রধান উইনà§�ডো" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "ধà§�রà§�বকের তালিকা ও সূতà§�রপà§�সà§�তক" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "সà§�বনিরà§�ধারণযোগà§�য বà§�যবহারকারী ইনà§�টারফেস" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "অনà§�তরà§�নিরà§�মিত বà§�যবহারকারী নিরà§�দেশিকা" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/ca.po000066400000000000000000000064441526573132500241320ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Catalan (Spain) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/ca_ES/)\n" "Language: ca_ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Una calculadora científica d'alta precisió" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmètica;càlcul;matemàtiques;científica;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch és una calculadora científica ràpida i d'alta precisió. Inclou " "una pantalla desplaçable amb ressaltat de sintaxi i està dissenyada per ser " "utilitzada completament amb el teclat." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Inclou moltes funcions matemàtiques integrades i admet funcions avançades " "com les funcions definides per l'usuari, els nombres complexos i les " "conversions d'unitats. Tot això es combina amb una interfície d'usuari " "senzilla però potent amb previsualització de resultats al vol, ressaltat de " "sintaxi i autocompleció." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch està disponible per a diverses plataformes en diverses llengües." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Finestra principal amb teclat numèric opcional" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "La llista de constants i el llibre de fórmules" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interfície d'usuari personalitzable" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "El manual d'usuari integrat" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/cs.po000066400000000000000000000063771526573132500241610ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Czech (http://www.transifex.com/heldercorreia/speedcrunch/" "language/cs/)\n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Vysoce pÅ™esná vÄ›decká kalkulaÄ�ka" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetika;výpoÄ�ty;matematika;vÄ›decká;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch je rychlá, vysoce pÅ™esná vÄ›decká kalkulaÄ�ka. Nabízí rolovatelný " "displej se zvýraznÄ›ním syntaxe a je navržena pro plné ovládání z klávesnice." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Obsahuje mnoho vestavÄ›ných matematických funkcí a podporuje pokroÄ�ilé " "funkce, jako jsou uživatelsky definované funkce, komplexní Ä�ísla a pÅ™evody " "jednotek. To vÅ¡e doplňuje jednoduché, ale výkonné uživatelské rozhraní s " "okamžitým náhledem výsledků, zvýraznÄ›ním syntaxe a automatickým doplňováním." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch je dostupný pro nÄ›kolik platforem v Å™adÄ› jazyků." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Hlavní okno s volitelnou numerickou klávesnicí" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Seznam konstant a kniha vzorců" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "PÅ™izpůsobitelné uživatelské rozhraní" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "VestavÄ›ná uživatelská příruÄ�ka" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/da.po000066400000000000000000000063531526573132500241320ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Danish (http://www.transifex.com/heldercorreia/speedcrunch/" "language/da/)\n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "En videnskabelig lommeregner med høj præcision" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetik;beregning;matematik;videnskabelig;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch er en hurtig, videnskabelig lommeregner med høj præcision. Den " "har et rullebart display med syntaksfremhævning og er designet til at kunne " "bruges fuldt ud via tastaturet." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Den indeholder mange indbyggede matematiske funktioner og understøtter " "avancerede funktioner sÃ¥som brugerdefinerede funktioner, komplekse tal og " "enhedskonverteringer. Dette kombineres med en enkel, men kraftfuld " "brugerflade med forhÃ¥ndsvisning af resultater i realtid, syntaksfremhævning " "og autofuldførelse." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch er tilgængelig til flere platforme pÃ¥ en række sprog." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Hovedvindue med valgfrit numerisk tastatur" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Listen over konstanter og formelsamling" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Brugerflade, der kan tilpasses" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Den indbyggede brugervejledning" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/de.po000066400000000000000000000065121526573132500241330ustar00rootroot00000000000000# German translations for PACKAGE package. # Copyright (C) 2016 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2016. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-05-01 17:29+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Language: de\n" "X-Source-Language: C\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Ein hochpräziser wissenschaftlicher Taschenrechner" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "arithmetik;berechnungen;rechnen;mathe;mathematik;wissenschaftlich;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch ist ein schneller, hochpräziser, wissenschaftlicher " "Taschenrechner. Es bietet eine scrollbare Anzeige mit Syntaxhervorhebung und " "ist auf vollständige Tastaturbedienung ausgelegt." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Es enthält viele eingebaute Mathematikfunktionen und unterstützt " "fortgeschrittene Funktionen wie benutzerdefinierte Funktionen, komplexe " "Zahlen und Einheitenumwandlungen. Dies ist verbunden mit einer einfacher, " "aber leistungsfähigen Benutzeroberfläche mit dynamischer Ergebnisvorschau, " "Syntaxhervorhebung und automatischer Vervollständigung." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "" "SpeedCrunch ist für verschiedene Plattformen in einer Anzahl von Sprachen " "verfügbar." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Hauptfenster mit optionalem Nummernblock" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Die Konstantenliste und das Formelbuch" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Anpassbare Benutzeroberfläche" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Das integrierte Benutzerhandbuch" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/el.po000066400000000000000000000100441526573132500241360ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Γιάννης Ανθυμίδης, 2016 msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Greek (http://www.transifex.com/heldercorreia/speedcrunch/" "language/el/)\n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Επιστημονική αÏ�ιθμομηχανή υψηλής ακÏ�ίβειας" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "αÏ�ιθμητική;υπολογισμός;μαθηματικά;επιστημονικό;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "Το SpeedCrunch είναι μια γÏ�ήγοÏ�η επιστημονική αÏ�ιθμομηχανή υψηλής ακÏ�ίβειας. " "Διαθέτει κυλιόμενη οθόνη με επισήμανση σÏ�νταξης και έχει σχεδιαστεί ώστε να " "χÏ�ησιμοποιείται πλήÏ�ως από το πληκτÏ�ολόγιο." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "ΠεÏ�ιλαμβάνει πολλές ενσωματωμένες μαθηματικές συναÏ�τήσεις και υποστηÏ�ίζει " "Ï€Ï�οηγμένες δυνατότητες όπως συναÏ�τήσεις οÏ�ισμένες από τον χÏ�ήστη, μιγαδικοÏ�Ï‚ " "αÏ�ιθμοÏ�Ï‚ και μετατÏ�οπές μονάδων. Όλα αυτά συνδυάζονται με ένα απλό αλλά " "ισχυÏ�ÏŒ πεÏ�ιβάλλον χÏ�ήστη με Ï€Ï�οεπισκόπηση αποτελεσμάτων σε Ï€Ï�αγματικό χÏ�όνο, " "επισήμανση σÏ�νταξης και αυτόματη συμπλήÏ�ωση." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "Το SpeedCrunch είναι διαθέσιμο για διάφοÏ�ες πλατφόÏ�μες σε πολλές γλώσσες." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "ΚÏ�Ï�ιο παÏ�άθυÏ�ο με Ï€Ï�οαιÏ�ετικό αÏ�ιθμητικό πληκτÏ�ολόγιο" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Η λίστα σταθεÏ�ών και το βιβλίο Ï„Ï�πων" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "ΠÏ�οσαÏ�μόσιμο πεÏ�ιβάλλον χÏ�ήστη" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Το ενσωματωμένο εγχειÏ�ίδιο χÏ�ήστη" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/en_GB.po000066400000000000000000000073431526573132500245200ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Adam Jones , 2016 msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: English (United Kingdom) (http://www.transifex.com/" "heldercorreia/speedcrunch/language/en_GB/)\n" "Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "A high-precision scientific calculator" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "arithmetic;calculation;math;scientific;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch is available for several platforms in a number of languages." "SpeedCrunch is available for several platforms in a number of languages." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Main window with optional keypad" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "The constants list and formula book" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Customizable user interface" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "The built-in user manual" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/en_US.po000066400000000000000000000061531526573132500245550ustar00rootroot00000000000000# English translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: en_US\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "A high-precision scientific calculator" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "arithmetic;calculation;math;scientific;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "" "SpeedCrunch is available for several platforms in a number of languages." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Main window with optional keypad" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "The constants list and formula book" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Customizable user interface" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "The built-in user manual" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/es.po000066400000000000000000000064421526573132500241540ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Spanish (Spain) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/es_ES/)\n" "Language: es_ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Una calculadora científica de alta precisión" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmética;cálculo;matemáticas;científica;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch es una calculadora científica rápida y de alta precisión. " "Cuenta con una pantalla desplazable con resaltado de sintaxis y está " "diseñada para usarse completamente con el teclado." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Incluye muchas funciones matemáticas integradas y admite funciones " "avanzadas como funciones definidas por el usuario, números complejos y " "conversiones de unidades. Todo ello se combina con una interfaz de usuario " "sencilla pero potente que ofrece vista previa de resultados al vuelo, " "resaltado de sintaxis y autocompletado." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch está disponible para varias plataformas en varios idiomas." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Ventana principal con teclado numérico opcional" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "La lista de constantes y el libro de fórmulas" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interfaz de usuario personalizable" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "El manual de usuario integrado" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/es_ES.po000066400000000000000000000063571526573132500245500ustar00rootroot00000000000000# Spanish translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Una calculadora científica de alta precisión" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmética;cálculo;matemáticas;científica;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch es una calculadora científica rápida y de alta precisión. " "Cuenta con una pantalla desplazable con resaltado de sintaxis y está " "diseñada para usarse completamente con el teclado." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Incluye muchas funciones matemáticas integradas y admite funciones " "avanzadas como funciones definidas por el usuario, números complejos y " "conversiones de unidades. Todo ello se combina con una interfaz de usuario " "sencilla pero potente que ofrece vista previa de resultados al vuelo, " "resaltado de sintaxis y autocompletado." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch está disponible para varias plataformas en varios idiomas." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Ventana principal con teclado numérico opcional" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "La lista de constantes y el libro de fórmulas" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interfaz de usuario personalizable" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "El manual de usuario integrado" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/et.po000066400000000000000000000063001526573132500241460ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Estonian (Estonia) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/et_EE/)\n" "Language: et_EE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Kõrgtäpne teaduslik kalkulaator" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmeetika;arvutamine;matemaatika;teaduslik;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch on kiire ja kõrgtäpne teaduslik kalkulaator. Sellel on süntaksi " "esiletõstuga keritav kuva ning see on loodud täielikult klaviatuuriga " "kasutamiseks." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "See sisaldab palju sisseehitatud matemaatikafunktsioone ja toetab täiustatud " "võimalusi, nagu kasutaja määratud funktsioonid, kompleksarvud ja ühikute " "teisendused. Seda kõike ühendab lihtne, kuid võimas kasutajaliides, mis " "pakub tulemuste kohest eelvaadet, süntaksi esiletõstu ja automaatset " "lõpetamist." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch on saadaval mitmele platvormile mitmes keeles." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Põhiaken valikulise numbriklahvistikuga" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Konstantide loend ja valemiraamat" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Kohandatav kasutajaliides" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Sisseehitatud kasutusjuhend" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/eu.po000066400000000000000000000064251526573132500241570ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Basque (http://www.transifex.com/heldercorreia/speedcrunch/" "language/eu/)\n" "Language: eu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Zehaztasun handiko kalkulagailu zientifikoa" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetika;kalkulua;matematika;zientifikoa;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch zehaztasun handiko kalkulagailu zientifiko azkarra da. Sintaxia " "nabarmenduta duen bistaratze korritzailea dauka, eta teklatu bidez erabat " "erabiltzeko diseinatuta dago." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Matematika-funtzio integratu ugari ditu, eta eginbide aurreratuak onartzen " "ditu, hala nola erabiltzaileak definitutako funtzioak, zenbaki konplexuak " "eta unitate-bihurketak. Hori guztia erabiltzaile-interfaze sinple baina " "indartsu batekin uztartzen da, emaitzen aurrebista berehalakoa, sintaxi-" "nabarmendua eta osatze automatikoa eskainiz." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch hainbat plataformatarako eskuragarri dago, hizkuntza ugaritan." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Leiho nagusia aukerako zenbakizko teklatuarekin" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Konstanteen zerrenda eta formula-liburua" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Pertsonaliza daitekeen erabiltzaile-interfazea" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Barneko erabiltzaile-eskuliburua" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/fa.po000066400000000000000000000072661526573132500241400ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Persian (Iran) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/fa_IR/)\n" "Language: fa_IR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "ماشین‌حساب علمی با دقت بالا" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "حساب;محاسبه;ریاضی;علمی;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch یک ماشین‌حساب علمی سریع Ùˆ با دقت بالاست. این برنامه دارای " "نمایشگر قابل‌پیمایش با برجسته‌سازی نحو است Ùˆ برای استÙ�ادهٔ کامل از طریق " "صÙ�حه‌کلید طراحی شده است." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "این برنامه شامل بسیاری از توابع ریاضیÙ� داخلی است Ùˆ از قابلیت‌های پیشرÙ�ته‌ای " "مانند توابعÙ� تعریÙ�‌شده توسط کاربر، اعداد مختلط Ùˆ تبدیل واحدها پشتیبانی می‌کند. " "همهٔ این‌ها با یک رابط کاربری ساده اما قدرتمند همراه است Ú©Ù‡ پیش‌نمایشÙ� آنیÙ� " "نتایج، برجسته‌سازیÙ� نحو Ùˆ تکمیل خودکار را Ù�راهم می‌کند." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch برای چندین سکوی نرم‌اÙ�زاری Ùˆ به چندین زبان در دسترس است." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "پنجرهٔ اصلی با صÙ�حه‌کلید عددیÙ� اختیاری" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Ù�هرست ثابت‌ها Ùˆ کتاب Ù�رمول‌ها" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "رابط کاربری قابل سÙ�ارشی‌سازی" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "راهنمای کاربرÙ� داخلی" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/fi.po000066400000000000000000000064071526573132500241440ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Finnish (http://www.transifex.com/heldercorreia/speedcrunch/" "language/fi/)\n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Erittäin tarkka tieteellinen laskin" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetiikka;laskenta;matematiikka;tieteellinen;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch on nopea ja erittäin tarkka tieteellinen laskin. Siinä on " "syntaksikorostettu vieritettävä näyttö, ja se on suunniteltu käytettäväksi " "kokonaan näppäimistöllä." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Se sisältää monia sisäänrakennettuja matemaattisia toimintoja ja tukee " "edistyneitä ominaisuuksia, kuten käyttäjän määrittelemiä funktioita, " "kompleksilukuja ja yksikkömuunnoksia. Tämä yhdistyy yksinkertaiseen mutta " "tehokkaaseen käyttöliittymään, jossa on tulosten reaaliaikainen esikatselu, " "syntaksikorostus ja automaattinen täydennys." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch on saatavilla useille alustoille useilla kielillä." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Pääikkuna valinnaisella numeronäppäimistöllä" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Vakioiden luettelo ja kaavakirja" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Mukautettava käyttöliittymä" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Sisäänrakennettu käyttöopas" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/fr.po000066400000000000000000000065611526573132500241560ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: French (France) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/fr_FR/)\n" "Language: fr_FR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Une calculatrice scientifique de haute précision" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "arithmétique;calcul;mathématiques;scientifique;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch est une calculatrice scientifique rapide et de haute précision. " "Elle propose un affichage défilant avec coloration syntaxique et est conçue " "pour être utilisée entièrement au clavier." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Elle inclut de nombreuses fonctions mathématiques intégrées et prend en " "charge des fonctionnalités avancées comme les fonctions définies par " "l'utilisateur, les nombres complexes et les conversions d'unités. Le tout " "est associé à une interface simple mais puissante offrant l'aperçu des " "résultats à la volée, la coloration syntaxique et l'autocomplétion." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "" "SpeedCrunch est disponible sur plusieurs plateformes dans de nombreuses " "langues." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Fenêtre principale avec pavé numérique optionnel" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "La liste des constantes et le livre de formules" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interface utilisateur personnalisable" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Le manuel d'utilisation intégré" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/gl.po000066400000000000000000000062711526573132500241470ustar00rootroot00000000000000# Galician translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Unha calculadora científica de alta precisión" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmética;cálculo;matemáticas;científica;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch é unha calculadora científica rápida e de alta precisión. Conta " "cun visor desprazable con realce de sintaxe e está deseñada para usarse " "completamente co teclado." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Inclúe moitas funcións matemáticas integradas e admite características " "avanzadas como funcións definidas polo usuario, números complexos e " "conversións de unidades. Todo isto combínase cunha interface de usuario " "sinxela pero potente que ofrece previsualización inmediata dos resultados, " "realce de sintaxe e autocompletado." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch está dispoñible para varias plataformas e en varios idiomas." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Xanela principal con teclado numérico opcional" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "A lista de constantes e o libro de fórmulas" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interface de usuario personalizable" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "O manual de usuario integrado" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/he.po000066400000000000000000000066361526573132500241460ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Hebrew (http://www.transifex.com/heldercorreia/speedcrunch/" "language/he/)\n" "Language: he\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "מחשבון מדעי בדיוק גבוה" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "×�ריתמטיקה;חישוב;מתמטיקה;מדעי;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch הו×� מחשבון מדעי מהיר ובדיוק גבוה. הו×� כולל תצוגה נגללת ×¢×� " "הדגשת תחביר, ונועד לשימוש מל×� ב×�מצעות המקלדת." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "הו×� כולל פונקציות מתמטיות מובנות רבות ותומך בתכונות מתקדמות כמו פונקציות " "בהגדרת משתמש, מספרי×� מרוכבי×� והמרות יחידות. כל ×–×�ת משולב ×¢×� ממשק משתמש " "פשוט ×�ך עוצמתי הכולל תצוגה מקדימה של תוצ×�ות בזמן ×�מת, הדגשת תחביר והשלמה " "×�וטומטית." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch זמין למספר פלטפורמות ובמספר שפות." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "החלון הר×�שי ×¢×� לוח מספרי×� ×�ופציונלי" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "רשימת הקבועי×� וספר הנוסח×�ות" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "ממשק משתמש הניתן להת×�מה ×�ישית" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "מדריך המשתמש המובנה" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/hi.po000066400000000000000000000103001526573132500241310ustar00rootroot00000000000000# Hindi translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: hi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "उचà¥�च-सटीकता वाला वैजà¥�ञानिक कैलकà¥�लेटर" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "अंकगणित;गणना;गणित;वैजà¥�ञानिक;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch à¤�क तेज, उचà¥�च-सटीकता वाला वैजà¥�ञानिक कैलकà¥�लेटर है। इसमें " "सिंटैकà¥�स-हाइलाइटेड सà¥�कà¥�रॉल करने योगà¥�य डिसà¥�पà¥�ले है और इसे पूरी तरह " "कीबोरà¥�ड से उपयोग करने के लिà¤� बनाया गया है।" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "इसमें कई अंतरà¥�निहित गणितीय फलन शामिल हैं और यह उपयोगकरà¥�ता-परिभाषित फलन, " "समà¥�मिशà¥�र संखà¥�याà¤�à¤� और इकाई रूपांतरण जैसी उनà¥�नत सà¥�विधाओं का समरà¥�थन करता " "है। इसके साथ à¤�क सरल लेकिन शकà¥�तिशाली उपयोगकरà¥�ता इंटरफ़ेस है जिसमें " "तà¥�रंत परिणाम पूरà¥�वावलोकन, सिंटैकà¥�स हाइलाइटिंग और सà¥�वचालित पूरà¥�णता शामिल " "हैं।" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch कई पà¥�लेटफ़ॉरà¥�म और कई भाषाओं में उपलबà¥�ध है।" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "वैकलà¥�पिक कीपैड के साथ मà¥�खà¥�य विंडो" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "सà¥�थिरांकों की सूची और सूतà¥�र-पà¥�सà¥�तक" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "अनà¥�कूलन योगà¥�य उपयोगकरà¥�ता इंटरफ़ेस" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "अंतरà¥�निहित उपयोगकरà¥�ता पà¥�सà¥�तिका" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/hu.po000066400000000000000000000067521526573132500241650ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Zoltán Csáti , 2016 # Zoltán Csáti , 2016 msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-10-17 21:14+0000\n" "Last-Translator: Zoltán Csáti \n" "Language-Team: Hungarian (Hungary) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/hu_HU/)\n" "Language: hu_HU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Egy nagy pontosságú tudományos számológép" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetika;számítás;matematika;tudományos;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "A SpeedCrunch egy gyors, nagy pontosságú tudományos számológép. Szintaxis " "kiemeléses, görgethetÅ‘ kijelzÅ‘vel rendelkezik és úgy tervezték, hogy teljes " "mértékben használható legyen billentyűzetrÅ‘l." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Számos beépített matematikai függvényt tartalmaz és támogatja az olyan " "fejlett képességeket, mint a felhasználó által biztosított függvények, " "komplex számok és a mértékegység konvertálás. Mindez kombinálva van egy " "egyszerű, de fejlett felhasználói felülettel, ami lehetÅ‘vé teszi az " "eredmények azonnali elÅ‘nézetét, szintaxis kiemelést és az automatikus " "kiegészítést." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "A SpeedCrunch számos platformra elérhetÅ‘ különbözÅ‘ nyelveken." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "FÅ‘ ablak opcionális billentyűzettel" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Az állandók listája és formula könyv" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Testreszabható felhasználói felület" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Beépített kézikönyv" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/id.po000066400000000000000000000063741526573132500241450ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Indonesian (Indonesia) (http://www.transifex.com/" "heldercorreia/speedcrunch/language/id_ID/)\n" "Language: id_ID\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Kalkulator ilmiah presisi tinggi" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetika;perhitungan;matematika;ilmiah;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch adalah kalkulator ilmiah yang cepat dan berpresisi tinggi. " "Aplikasi ini memiliki tampilan yang dapat digulir dengan penyorotan sintaks, " "dan dirancang untuk digunakan sepenuhnya melalui papan ketik." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Aplikasi ini mencakup banyak fungsi matematika bawaan dan mendukung fitur " "lanjutan seperti fungsi yang ditentukan pengguna, bilangan kompleks, dan " "konversi satuan. Semuanya dipadukan dengan antarmuka pengguna yang sederhana " "namun kuat, dengan pratinjau hasil secara langsung, penyorotan sintaks, dan " "pelengkapan otomatis." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch tersedia untuk beberapa platform dalam sejumlah bahasa." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Jendela utama dengan keypad opsional" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Daftar konstanta dan buku rumus" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Antarmuka pengguna yang dapat disesuaikan" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Panduan pengguna bawaan" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/it.po000066400000000000000000000065151526573132500241620ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Luigi Toscano , 2016 msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-20 22:52+0000\n" "Last-Translator: Luigi Toscano \n" "Language-Team: Italian (Italy) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/it_IT/)\n" "Language: it_IT\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Una calcolatrice scientifica ad alta precisione" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetica;calcolo;matematica;scientifico;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch è una calcolatrice scientifica veloce e ad alta precisione. " "Presenta uno schermo scorrevole con evidenziazione della sintassi ed è " "progettata per essere completamente usabile tramite tastiera." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Include molte funzioni matematiche predefinite e supporta funzionalità " "avanzate come funzioni definite dall'utente, numeri complessi e conversione " "di unità. Questo si aggiunge ad un'interfaccia utente semplice ma potente " "che fornisce anteprime al volo dei risultati, evidenziazione della sintassi " "ed autocompletamento. " #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch è disponibile per diverse piattaforme in varie lingue." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Finestra principale con tastierino numerico opzionale" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Lista delle costanti e formulario" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interfaccia utente personalizzabile" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Manuale integrato" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/ja.po000066400000000000000000000065021526573132500241340ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Japanese (Japan) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/ja_JP/)\n" "Language: ja_JP\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "高精度ã�®ç§‘学計算機" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "ç®—è¡“;計算;æ•°å­¦;ç§‘å­¦;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch ã�¯é«˜é€Ÿã�§é«˜ç²¾åº¦ã�ªç§‘学計算機ã�§ã�™ã€‚構文強調表示付ã��ã�®ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«å�¯èƒ½ã�ª" "表示を備ã�ˆã€�キーボードã� ã�‘ã�§å®Œå…¨ã�«æ“�作ã�§ã��るよã�†è¨­è¨ˆã�•れã�¦ã�„ã�¾ã�™ã€‚" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "多数ã�®çµ„ã�¿è¾¼ã�¿æ•°å­¦é–¢æ•°ã‚’å‚™ã�ˆã€�ユーザー定義関数ã€�複素数ã€�å�˜ä½�変æ�›ã�ªã�©ã�®é«˜åº¦ã�ª" "機能をサãƒ�ートã�—ã�¾ã�™ã€‚ã�•らã�«ã€�çµ�æžœã�®ãƒªã‚¢ãƒ«ã‚¿ã‚¤ãƒ ãƒ—レビューã€�構文強調表示ã€�自動" "補完を備ã�ˆã�Ÿã‚·ãƒ³ãƒ—ルã�‹ã�¤å¼·åŠ›ã�ªãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェースã�¨çµ„ã�¿å�ˆã‚�ã�•れã�¦ã�„ã�¾ã�™ã€‚" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch ã�¯è¤‡æ•°ã�®ãƒ—ラットフォームã�§ã€�多言語ã�«å¯¾å¿œã�—ã�¦ã�„ã�¾ã�™ã€‚" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "オプションã�®ãƒ†ãƒ³ã‚­ãƒ¼ä»˜ã��メインウィンドウ" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "定数リストã�¨æ•°å¼�集" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "カスタマイズå�¯èƒ½ã�ªãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェース" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "内蔵ユーザーマニュアル" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/ko.po000066400000000000000000000063611526573132500241560ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Korean (http://www.transifex.com/heldercorreia/speedcrunch/" "language/ko/)\n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "ê³ ì •ë°€ 공학용 계산기" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "산술;계산;수학;과학;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch는 빠르고 ê³ ì •ë°€ì�¸ 공학용 계산기입니다. 구문 ê°•ì¡° 표시가 ì �ìš©ë�œ 스í�¬ë¡¤ " "가능한 화면ì�„ 제공하며, 키보드만으로 완전히 사용할 수 있ë�„ë¡� 설계ë�˜ì—ˆìŠµë‹ˆë‹¤." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "다양한 내장 수학 함수를 í�¬í•¨í•˜ê³  사용ìž� ì •ì�˜ 함수, 복소수, 단위 변환과 ê°™ì�€ 고급 " "기능ì�„ ì§€ì›�합니다. ë˜�한 ê²°ê³¼ì�˜ 실시간 미리보기, 구문 ê°•ì¡° 표시, ìž�ë�™ 완성ì�„ 갖춘 " "단순하면서ë�„ 강력한 사용ìž� ì�¸í„°íŽ˜ì�´ìŠ¤ë¥¼ 제공합니다." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch는 여러 플랫í�¼ì—�서 다양한 언어로 사용할 수 있습니다." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "ì„ íƒ�ì � 숫ìž� 키패드가 있는 기본 ì°½" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "ìƒ�수 목ë¡� ë°� ê³µì‹� 모ì�Œ" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "사용ìž� 지정 가능한 사용ìž� ì�¸í„°íŽ˜ì�´ìФ" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "내장 사용ìž� 설명서" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/lt.po000066400000000000000000000065301526573132500241620ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Moo, 2016 msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-21 21:06+0000\n" "Last-Translator: Moo\n" "Language-Team: Lithuanian (http://www.transifex.com/heldercorreia/" "speedcrunch/language/lt/)\n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "(n%100<10 || n%100>=20) ? 1 : 2);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Labai tikslus mokslinis skaiÄ�iuotuvas" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetika;skaiÄ�iavimas;matematika;mokslinis;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch yra greitas, labai tikslus mokslinis skaiÄ�iuotuvas. Jis pasižymi " "sintaksÄ™ paryÅ¡kinanÄ�iu slenkanÄ�iu ekranu ir yra sukurtas, kad bÅ«tų pilnai " "naudojamas su klaviatÅ«ra." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Jame yra įtaisytos daugelis matematinių funkcijų ir jis palaiko tokias " "iÅ¡plÄ—stines funkcijas kaip naudotojo apibrėžtos funkcijos, kompleksiniai " "skaiÄ�iai ir vienetų konvertavimai. Tai yra sujungta su paprasta, taÄ�iau " "galinga naudotojo sÄ…saja, kuri pasižymi žaibiÅ¡kai greita rezultatų peržiÅ«ra, " "sintaksÄ—s paryÅ¡kinimu ir automatiniu užbaigimu." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "" "SpeedCrunch skaiÄ�iuotuvas yra prieinamas kelioms platformoms daugeliu kalbų." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Pagrindinis langas su pasirinktine klaviatÅ«ra" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Konstantų sÄ…raÅ¡as bei formulių knyga" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Tinkinama naudotojo sÄ…saja" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Ä®taisytas naudotojo vadovas" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/lv.po000066400000000000000000000064551526573132500241720ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Latvian (http://www.transifex.com/heldercorreia/speedcrunch/" "language/lv/)\n" "Language: lv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " "2);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Augstas precizitÄ�tes zinÄ�tniskais kalkulators" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmÄ“tika;aprēķini;matemÄ�tika;zinÄ�tnisks;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch ir Ä�trs, augstas precizitÄ�tes zinÄ�tniskais kalkulators. Tam ir " "ritinÄ�ms displejs ar sintakses izcelÅ¡anu, un tas ir paredzÄ“ts pilnÄ«gai " "lietoÅ¡anai ar tastatÅ«ru." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Tas ietver daudzas iebÅ«vÄ“tas matemÄ�tiskÄ�s funkcijas un atbalsta uzlabotas " "iespÄ“jas, piemÄ“ram, lietotÄ�ja definÄ“tas funkcijas, kompleksos skaitļus un " "vienÄ«bu pÄ�rveidoÅ¡anu. To papildina vienkÄ�rÅ¡a, bet jaudÄ«ga lietotÄ�ja saskarne " "ar rezultÄ�tu priekÅ¡skatÄ«jumu reÄ�llaikÄ�, sintakses izcelÅ¡anu un automÄ�tisko " "pabeigÅ¡anu." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch ir pieejams vairÄ�kÄ�m platformÄ�m vairÄ�kÄ�s valodÄ�s." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Galvenais logs ar izvÄ“les ciparu tastatÅ«ru" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "KonstanÅ¡u saraksts un formulu grÄ�mata" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "PielÄ�gojama lietotÄ�ja saskarne" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "IebÅ«vÄ“tÄ� lietotÄ�ja rokasgrÄ�mata" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/metadata-tool.sh000077500000000000000000000062021526573132500262710ustar00rootroot00000000000000#!/bin/sh set -eu SRC_DIR=$(dirname $0) require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then echo "Missing required command: $1" >&2 exit 1 fi } require_extract_tools() { require_cmd intltool-extract require_cmd xgettext } require_merge_tools() { require_cmd msgmerge } require_metadata_merge_tools() { require_cmd intltool-merge } run_stats() { stats_script="$SRC_DIR/translation-stats.py" if [ ! -x "$stats_script" ]; then echo "Missing or non-executable stats script: $stats_script" >&2 exit 1 fi "$stats_script" } extract_strings() { require_extract_tools intltool-extract --local --type gettext/xml $SRC_DIR/org.speedcrunch.SpeedCrunch.metainfo.xml.in intltool-extract --local --type gettext/ini $SRC_DIR/org.speedcrunch.SpeedCrunch.desktop.in xgettext tmp/*.h -o desktop-appdata.pot -cTRANSLATORS -a } case "$1" in extract-strings) # Extract translatable strings from the appdata XML and desktop template # into temporary gettext headers under tmp/*.h, then generate the POT # template used to update/merge language PO files. extract_strings ;; update-po) require_merge_tools # Merge all language PO files with the latest POT template. # If the POT template does not exist yet, generate it first. if [ ! -f desktop-appdata.pot ]; then extract_strings fi for po in "$SRC_DIR"/*.po; do msgmerge --update --backup=none "$po" desktop-appdata.pot done ;; update-all) require_merge_tools require_metadata_merge_tools # Full translation pipeline: # 1) extract current source strings into desktop-appdata.pot # 2) merge all PO files with the updated POT # 3) regenerate translated metadata output files extract_strings for po in "$SRC_DIR"/*.po; do msgmerge --update --backup=none "$po" desktop-appdata.pot done intltool-merge --xml-style $SRC_DIR $SRC_DIR/org.speedcrunch.SpeedCrunch.metainfo.xml.in $SRC_DIR/../org.speedcrunch.SpeedCrunch.metainfo.xml intltool-merge --desktop-style $SRC_DIR $SRC_DIR/org.speedcrunch.SpeedCrunch.desktop.in $SRC_DIR/../org.speedcrunch.SpeedCrunch.desktop ;; update-metadata-files) require_metadata_merge_tools # Merge existing PO translations into distributable metadata outputs: # - metainfo.xml (AppStream) # - .desktop launcher file # This consumes PO files in this directory and writes merged files to # the parent pkg/ directory. intltool-merge --xml-style $SRC_DIR $SRC_DIR/org.speedcrunch.SpeedCrunch.metainfo.xml.in $SRC_DIR/../org.speedcrunch.SpeedCrunch.metainfo.xml intltool-merge --desktop-style $SRC_DIR $SRC_DIR/org.speedcrunch.SpeedCrunch.desktop.in $SRC_DIR/../org.speedcrunch.SpeedCrunch.desktop ;; stats) run_stats ;; *) echo Commands: echo " extract-strings - generate .pot file" echo " update-po - merge all .po files with desktop-appdata.pot" echo " update-all - extract, merge .po files, update metadata files" echo " update-metadata-files - update desktop and appdata files" echo " stats - show translation statistics" ;; esac heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/ms.po000066400000000000000000000062521526573132500241630ustar00rootroot00000000000000# Malay translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: ms\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Kalkulator saintifik berketepatan tinggi" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetik;pengiraan;matematik;saintifik;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch ialah kalkulator saintifik yang pantas dan berketepatan tinggi. " "Ia menampilkan paparan boleh tatal dengan penyerlahan sintaks dan direka " "untuk digunakan sepenuhnya melalui papan kekunci." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Ia merangkumi banyak fungsi matematik terbina dalam dan menyokong ciri " "lanjutan seperti fungsi ditakrif pengguna, nombor kompleks dan penukaran " "unit. Semua ini digabungkan dengan antara muka pengguna yang ringkas tetapi " "berkuasa yang menawarkan pratonton hasil serta-merta, penyerlahan sintaks " "dan pelengkapan automatik." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch tersedia untuk beberapa platform dalam pelbagai bahasa." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Tetingkap utama dengan papan kekunci angka pilihan" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Senarai pemalar dan buku formula" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Antara muka pengguna yang boleh disesuaikan" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Manual pengguna terbina dalam" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/nb.po000066400000000000000000000063611526573132500241440ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Norwegian BokmÃ¥l (Norway) (http://www.transifex.com/" "heldercorreia/speedcrunch/language/nb_NO/)\n" "Language: nb_NO\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "En vitenskapelig kalkulator med høy presisjon" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetikk;beregning;matematikk;vitenskapelig;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch er en rask vitenskapelig kalkulator med høy presisjon. Den har " "et rullbart display med syntaksutheving og er utviklet for Ã¥ kunne brukes " "fullt ut med tastaturet." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Den inneholder mange innebygde matematiske funksjoner og støtter avanserte " "funksjoner som brukerdefinerte funksjoner, komplekse tall og " "enhetskonverteringer. Dette kombineres med et enkelt, men kraftig " "brukergrensesnitt med forhÃ¥ndsvisning av resultater i sanntid, " "syntaksutheving og autofullføring." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch er tilgjengelig for flere plattformer pÃ¥ en rekke sprÃ¥k." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Hovedvindu med valgfritt numerisk tastatur" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Listen over konstanter og formelsamlingen" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Tilpassbart brukergrensesnitt" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Den innebygde brukermanualen" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/nl.po000066400000000000000000000064761526573132500241650ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Dutch (Netherlands) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/nl_NL/)\n" "Language: nl_NL\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Een wetenschappelijke rekenmachine met hoge precisie" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "rekenkunde;berekening;wiskunde;wetenschappelijk;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch is een snelle wetenschappelijke rekenmachine met hoge precisie. " "Het beschikt over een scrollbaar scherm met syntaxisaccentuering en is " "ontworpen om volledig via het toetsenbord te worden gebruikt." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Het bevat veel ingebouwde wiskundige functies en ondersteunt geavanceerde " "functies zoals door de gebruiker gedefinieerde functies, complexe getallen " "en eenheidsconversies. Dit wordt gecombineerd met een eenvoudige maar " "krachtige gebruikersinterface met live voorbeeld van resultaten, " "syntaxisaccentuering en automatisch aanvullen." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch is beschikbaar voor verschillende platforms in een aantal talen." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Hoofdvenster met optioneel numeriek toetsenblok" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "De constantenlijst en het formuleboek" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Aanpasbare gebruikersinterface" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "De ingebouwde gebruikershandleiding" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/org.speedcrunch.SpeedCrunch.desktop.in000066400000000000000000000005711526573132500324750ustar00rootroot00000000000000[Desktop Entry] Type=Application _Name=SpeedCrunch Exec=speedcrunch Icon=org.speedcrunch.SpeedCrunch StartupWMClass=speedcrunch _Comment=A high-precision scientific calculator Categories=Qt;Utility;Calculator; # TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! _Keywords=arithmetic;calculation;math;scientific; heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/org.speedcrunch.SpeedCrunch.metainfo.xml.in000066400000000000000000000103071526573132500334230ustar00rootroot00000000000000 org.speedcrunch.SpeedCrunch CC0-1.0 GPL-2.0+ speedcrunch@googlegroups.com <_name>SpeedCrunch <_summary>A high-precision scientific calculator <_p> SpeedCrunch is a fast, high-precision scientific calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard. <_p> It includes many built-in maths functions and supports advanced features like user-defined functions, complex numbers, and unit conversions. This is combined with a simple yet powerful user interface featuring on-the-fly results preview, syntax highlighting, and autocompletion. <_p> SpeedCrunch is available for several platforms in a number of languages. org.speedcrunch.SpeedCrunch.desktop speedcrunch speedcrunch.desktop ModernToolkit UserDocs https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/advanced-features.png <_caption>Main window with optional keypad https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/keypad.png <_caption>The constants list and formula book https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/constants+book.png <_caption>Customizable user interface https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/ui-customization.png <_caption>The built-in user manual https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/manual.png https://speedcrunch,org https://speedcrunch.org/issues.html https://speedcrunch.org/contents.html ar bg bn ca cs da de el en_GB en_US es es_ES et eu fa fi fr gl he hi hu id it ja ko lt lv ms nb nl pl pt_BR pt_PT ro ru sk sl sv sw ta te th tr uk uz_Latn vi zh_CN zh_TW heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/pl.po000066400000000000000000000064551526573132500241640ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Polish (http://www.transifex.com/heldercorreia/speedcrunch/" "language/pl/)\n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Wysokoprecyzyjny kalkulator naukowy" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "arytmetyka;obliczenia;matematyka;naukowy;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch to szybki, wysokoprecyzyjny kalkulator naukowy. Posiada " "przewijalny ekran z podÅ›wietlaniem skÅ‚adni i jest zaprojektowany do peÅ‚nej " "obsÅ‚ugi z klawiatury." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Zawiera wiele wbudowanych funkcji matematycznych i obsÅ‚uguje zaawansowane " "możliwoÅ›ci, takie jak funkcje definiowane przez użytkownika, liczby " "zespolone i konwersje jednostek. Wszystko to połączono z prostym, a zarazem " "potężnym interfejsem użytkownika oferujÄ…cym podglÄ…d wyników na bieżąco, " "podÅ›wietlanie skÅ‚adni i autouzupeÅ‚nianie." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch jest dostÄ™pny na kilka platform w wielu jÄ™zykach." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Główne okno z opcjonalnym blokiem numerycznym" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Lista staÅ‚ych i zbiór wzorów" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Konfigurowalny interfejs użytkownika" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Wbudowany podrÄ™cznik użytkownika" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/pt_BR.po000066400000000000000000000076421526573132500245560ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Thiago Vieira , 2016 msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-11-21 20:43+0000\n" "Last-Translator: Thiago Vieira \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/pt_BR/)\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Calculadora científica de alta precisão" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmética;cálculo;matemática;científico;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "O SpeedCrunch é uma calculadora científica rápida e de alta precisão. Ele " "possui um visor rolável com realce de sintaxe e foi projetado para ser usado " "totalmente pelo teclado." "SpeedCrunch é uma calculadora científica rápida e de alta precisão. Ela " "possui um mostrador rolável, com destaque de sintaxe e é concebida para ser " "plenamente utilizável através do teclado." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Inclui muitas funções matemáticas integradas e oferece suporte a recursos " "avançados como funções definidas pelo usuário, números complexos e " "conversões de unidades. Isso é combinado com uma interface de usuário " "simples, porém poderosa, com pré-visualização de resultados em tempo real, " "realce de sintaxe e autocompletar." "Ela inclui muitas funções matemáticas embutidas e suporta características " "avançadas como funções definidas pelo usuário, números complexos e conversão " "de unidades. Isso combinado a uma poderosa interface com resultados " "instantâneos, destaque de sintaxe e auto completação." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "" "O SpeedCrunch está disponível para várias plataformas em diversos idiomas." "SpeedCrunch está disponível para diversas plataformas e em várias línguas." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Janela principal com teclado numérico opcional" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "A lista de constantes e o livro de fórmulas" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interface de usuário personalizável" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "O manual do usuário integrado" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/pt_PT.po000066400000000000000000000065031526573132500245710ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Portuguese (Portugal) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/pt_PT/)\n" "Language: pt_PT\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Uma calculadora científica de alta precisão" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmética;cálculo;matemática;científica;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "O SpeedCrunch é uma calculadora científica rápida e de alta precisão. " "Apresenta um visor rolável com realce de sintaxe e foi concebido para ser " "utilizado integralmente através do teclado." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Inclui muitas funções matemáticas integradas e suporta funcionalidades " "avançadas, como funções definidas pelo utilizador, números complexos e " "conversões de unidades. Isto é combinado com uma interface de utilizador " "simples, mas poderosa, com pré-visualização de resultados em tempo real, " "realce de sintaxe e conclusão automática." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "O SpeedCrunch está disponível para várias plataformas em diversas línguas." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Janela principal com teclado numérico opcional" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "A lista de constantes e o livro de fórmulas" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interface de utilizador personalizável" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "O manual do utilizador integrado" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/ro.po000066400000000000000000000065771526573132500241760ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Romanian (Romania) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/ro_RO/)\n" "Language: ro_RO\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" "2:1));\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Un calculator È™tiinÈ›ific de înaltă precizie" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetică;calcul;matematică;È™tiinÈ›ific;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch este un calculator È™tiinÈ›ific rapid, de înaltă precizie. Oferă " "un afiÈ™aj derulabil cu evidenÈ›iere a sintaxei È™i este conceput pentru a fi " "folosit în întregime de la tastatură." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Include multe funcÈ›ii matematice integrate È™i acceptă funcÈ›ionalități " "avansate, precum funcÈ›ii definite de utilizator, numere complexe È™i " "conversii de unități. Toate acestea sunt combinate cu o interfață de " "utilizator simplă, dar puternică, cu previzualizare a rezultatelor în timp " "real, evidenÈ›iere a sintaxei È™i completare automată." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch este disponibil pentru mai multe platforme în mai multe limbi." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Fereastra principală cu tastatură numerică opÈ›ională" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Lista constantelor È™i cartea de formule" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Interfață de utilizator personalizabilă" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Manualul de utilizare integrat" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/ru.po000066400000000000000000000100531526573132500241640ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Duke Soft , 2016 # Sergei Neumoin , 2016 msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-11-20 18:34+0000\n" "Last-Translator: Sergei Neumoin \n" "Language-Team: Russian (Russia) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/ru_RU/)\n" "Language: ru_RU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " "(n%100>=11 && n%100<=14)? 2 : 3);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Ð�аучный инженерный калькулÑ�тор" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "арифметика;вычиÑ�лениÑ�;математика;научный;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch — быÑ�трый выÑ�окоточный научный калькулÑ�тор. Он имеет " "прокручиваемый диÑ�плей Ñ� подÑ�веткой Ñ�интакÑ�иÑ�а и предназначен длÑ� полного " "управлениÑ� Ñ� клавиатуры." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Он включает множеÑ�тво вÑ�троенных математичеÑ�ких функций и поддерживает " "раÑ�ширенные возможноÑ�ти, такие как пользовательÑ�кие функции, комплекÑ�ные " "чиÑ�ла и преобразование единиц. Ð’Ñ�Ñ‘ Ñ�то Ñ�очетаетÑ�Ñ� Ñ� проÑ�тым, но мощным " "интерфейÑ�ом Ñ� мгновенным предпроÑ�мотром результатов, подÑ�веткой Ñ�интакÑ�иÑ�а " "и автодополнением." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch доÑ�тупен длÑ� неÑ�кольких платформ в Ñ€Ñ�де Ñ�зыков." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Главное окно Ñ� дополнительной клавиатурой" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "КонÑ�танты и формулы" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Ð�аÑ�траиваемый пользовательÑ�кий интерфейÑ�" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Ð’Ñ�троенное руководÑ�тво пользователÑ�" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/sk.po000066400000000000000000000064641526573132500241660ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Slovak (http://www.transifex.com/heldercorreia/speedcrunch/" "language/sk/)\n" "Language: sk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Vysokopresná vedecká kalkulaÄ�ka" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetika;výpoÄ�ty;matematika;vedecká;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch je rýchla, vysoko presná vedecká kalkulaÄ�ka. Ponúka rolovateľný " "displej so zvýraznením syntaxe a je navrhnutá tak, aby sa dala plnohodnotne " "používaÅ¥ pomocou klávesnice." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Obsahuje veľa vstavaných matematických funkcií a podporuje pokroÄ�ilé " "funkcie, ako sú používateľom definované funkcie, komplexné Ä�ísla a prevody " "jednotiek. To je kombinované s jednoduchým, no výkonným používateľským " "rozhraním s priebežným náhľadom výsledkov, zvýraznením syntaxe a " "automatickým dopĺňaním." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch je dostupný pre viaceré platformy v niekoľkých jazykoch." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Hlavné okno s voliteľnou numerickou klávesnicou" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Zoznam konÅ¡tánt a kniha vzorcov" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Prispôsobiteľné používateľské rozhranie" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Vstavaná používateľská príruÄ�ka" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/sl.po000066400000000000000000000063671526573132500241710ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Slovenian (Slovenia) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/sl_SI/)\n" "Language: sl_SI\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " "n%100==4 ? 2 : 3);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "VisokonatanÄ�en znanstveni kalkulator" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetika;izraÄ�un;matematika;znanstveni;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch je hiter, visokonatanÄ�en znanstveni kalkulator. Ima pomiÄ�no " "prikazovalno okno s poudarjanjem skladnje in je zasnovan za popolno uporabo " "s tipkovnico." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "VkljuÄ�uje veliko vgrajenih matematiÄ�nih funkcij in podpira napredne " "zmožnosti, kot so uporabniÅ¡ko doloÄ�ene funkcije, kompleksna Å¡tevila in " "pretvorbe enot. To je združeno s preprostim, a zmogljivim uporabniÅ¡kim " "vmesnikom z sprotnim predogledom rezultatov, poudarjanjem skladnje in " "samodokonÄ�evanjem." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch je na voljo za veÄ� platform v veÄ� jezikih." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Glavno okno z izbirno Å¡tevilÄ�nico" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Seznam konstant in knjiga formul" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Prilagodljiv uporabniÅ¡ki vmesnik" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Vgrajen uporabniÅ¡ki priroÄ�nik" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/sv.po000066400000000000000000000064221526573132500241730ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Swedish (Sweden) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/sv_SE/)\n" "Language: sv_SE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "En vetenskaplig miniräknare med hög precision" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetik;beräkning;matematik;vetenskaplig;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch är en snabb vetenskaplig miniräknare med hög precision. Den har " "en rullbar skärm med syntaxmarkering och är utformad för att kunna användas " "helt via tangentbordet." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Den innehÃ¥ller mÃ¥nga inbyggda matematiska funktioner och stöder avancerade " "funktioner som användardefinierade funktioner, komplexa tal och " "enhetsomvandlingar. Detta kombineras med ett enkelt men kraftfullt " "användargränssnitt med förhandsvisning av resultat i realtid, syntaxmarkering " "och automatisk komplettering." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch finns tillgänglig för flera plattformar pÃ¥ ett antal sprÃ¥k." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Huvudfönster med valfritt numeriskt tangentbord" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Listan över konstanter och formelboken" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Anpassningsbart användargränssnitt" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Den inbyggda användarhandboken" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/sw.po000066400000000000000000000063421526573132500241750ustar00rootroot00000000000000# Swahili translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: sw\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Kikokotoo cha kisayansi chenye usahihi wa juu" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "hesabu;ukokotozi;hisabati;kisayansi;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch ni kikokotoo cha kisayansi cha haraka chenye usahihi wa juu. " "Kina onyesho linaloweza kusogezwa lenye uangaziaji wa sintaksia na " "kimeundwa kutumiwa kikamilifu kwa kibodi." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Kinajumuisha vitendaji vingi vya hisabati vilivyojengwa ndani na " "kinaunga mkono vipengele vya hali ya juu kama vile vitendaji " "vilivyofafanuliwa na mtumiaji, nambari changamano na ubadilishaji wa " "vipimo. Haya yote yameunganishwa na kiolesura rahisi lakini chenye nguvu " "chenye hakikisho la matokeo papo hapo, uangaziaji wa sintaksia na ukamilishaji " "wa kiotomatiki." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch inapatikana kwa majukwaa kadhaa na katika lugha mbalimbali." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Dirisha kuu lenye kibodi cha namba cha hiari" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Orodha ya thamani thabiti na kitabu cha fomula" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Kiolesura cha mtumiaji kinachoweza kubadilishwa" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Mwongozo wa mtumiaji uliojengewa ndani" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/ta.po000066400000000000000000000110241526573132500241410ustar00rootroot00000000000000# Tamil translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: ta\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "உயரà¯� தà¯�லà¯�லியமான அறிவியலà¯� கணிபà¯�பானà¯�" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "கணிதமà¯�;கணகà¯�கீடà¯�;கணிதவியலà¯�;அறிவியலà¯�;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch எனà¯�பதà¯� வேகமான, உயரà¯� தà¯�லà¯�லியமான அறிவியலà¯� கணிபà¯�பானà¯�. இதà¯� " "தொடரமைபà¯�பà¯� à®®à¯�னà¯�னிறà¯�தà¯�தலà¯�டனà¯� கூடிய சà¯�à®°à¯�டà¯�டகà¯�கூடிய காடà¯�சியைகà¯� கொணà¯�டà¯�ளà¯�ளதà¯�, " "மேலà¯�à®®à¯� à®®à¯�à®´à¯�மையாக விசைபà¯�பலகை மூலமà¯� பயனà¯�படà¯�தà¯�தபà¯�படà¯�மாறà¯� வடிவமைகà¯�கபà¯�படà¯�டà¯�ளà¯�ளதà¯�." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "இதà¯� பல உடà¯�பொதிகà¯�கபà¯�படà¯�ட கணித செயலà¯�பாடà¯�களை கொணà¯�டà¯�ளà¯�ளதà¯�; பயனரà¯� வரையறà¯�கà¯�கà¯�à®®à¯� " "செயலà¯�பாடà¯�களà¯�, கலபà¯�பெணà¯�களà¯� மறà¯�à®±à¯�à®®à¯� அலகà¯� மாறà¯�றஙà¯�களà¯� போனà¯�à®± மேமà¯�படà¯�ட " "வசதிகளையà¯�à®®à¯� ஆதரிகà¯�கிறதà¯�. இதனà¯�டனà¯� உடனடி à®®à¯�டிவà¯� à®®à¯�னà¯�னோடà¯�டமà¯�, தொடரமைபà¯�பà¯� " "à®®à¯�னà¯�னிறà¯�தà¯�தலà¯� மறà¯�à®±à¯�à®®à¯� தானியஙà¯�கà¯� நிறைவà¯� கொணà¯�ட எளிய ஆனாலà¯� வலிமையான பயனரà¯� " "இடைமà¯�கமà¯�à®®à¯� இணைகà¯�கபà¯�படà¯�டà¯�ளà¯�ளதà¯�." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch பல தளஙà¯�களிலà¯�à®®à¯� பல மொழிகளிலà¯�à®®à¯� கிடைகà¯�கிறதà¯�." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "விரà¯�பà¯�பதà¯� தேரà¯�வà¯� எணà¯� விசைபà¯�பலகையà¯�டனà¯� கூடிய à®®à¯�தனà¯�மை சாளரமà¯�" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "மாறிலி படà¯�டியலà¯�à®®à¯� சூதà¯�திரபà¯� பà¯�தà¯�தகமà¯�à®®à¯�" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "தனிபà¯�பயனாகà¯�ககà¯�கூடிய பயனரà¯� இடைமà¯�கமà¯�" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "உடà¯�பொதிகà¯�கபà¯�படà¯�ட பயனரà¯� கையேடà¯�" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/te.po000066400000000000000000000106721526573132500241550ustar00rootroot00000000000000# Telugu translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: te\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "à°…à°§à°¿à°• à°–à°šà±�చితతà±�వం à°—à°² శాసà±�à°¤à±�రీయ కాలికà±�à°¯à±�లేటరà±�" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "అంకగణితం;గణన;గణితం;శాసà±�à°¤à±�రీయ;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch à°’à°• వేగవంతమైన, à°…à°§à°¿à°• à°–à°šà±�చితతà±�వం à°—à°² శాసà±�à°¤à±�రీయ కాలికà±�à°¯à±�లేటరà±�. ఇది " "సింటాకà±�à°¸à±� హైలైటà±� చేసిన à°¸à±�à°•à±�రోలà±� చేయగల à°ªà±�రదరà±�శననà±� కలిగి ఉంది మరియà±� పూరà±�తిగా " "కీబోరà±�à°¡à±� à°¦à±�వారా ఉపయోగించేందà±�à°•à±� రూపకలà±�పన చేయబడింది." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "ఇందà±�లో అనేక అంతరà±�నిరà±�మిత గణిత à°«à°‚à°•à±�à°·à°¨à±�à°²à±� ఉనà±�నాయి మరియà±� వినియోగదారà±� నిరà±�వచించిన " "à°«à°‚à°•à±�à°·à°¨à±�à°²à±�, సంకà±�లిషà±�à°Ÿ సంఖà±�యలà±�, యూనిటà±� మారà±�పిడి వంటి ఆధà±�నిక లకà±�షణాలనà±� " "మదà±�దతà±� ఇసà±�à°¤à±�ంది. ఇవనà±�నీ తకà±�à°·à°£ ఫలితాల à°ªà±�à°°à°¿à°µà±�యూ, సింటాకà±�à°¸à±� హైలైటింగà±� మరియà±� " "ఆటోకంపà±�లీషనà±� కలిగిన సరళమైన కానీ à°¶à°•à±�తివంతమైన వినియోగదారà±� అంతర à°®à±�ఖంతో " "కలిపి అందించబడతాయి." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch అనేక వేదికలపై మరియà±� పలà±� భాషలà±�లో à°…à°‚à°¦à±�బాటà±�లో ఉంది." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "à°�à°šà±�ఛిక కీపà±�యాడà±�‌తో à°ªà±�రధాన à°•à°¿à°Ÿà°¿à°•à±€" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "à°¸à±�థిరాంకాల జాబితా మరియà±� సూతà±�రాల à°ªà±�à°¸à±�తకం" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "à°…à°¨à±�కూలీకరించదగిన వినియోగదారà±� అంతర à°®à±�à°–à°‚" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "అంతరà±�నిరà±�మిత వినియోగదారà±� మారà±�గదరà±�శిని" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/th.po000066400000000000000000000103061526573132500241520ustar00rootroot00000000000000# Thai translations for PACKAGE package. # Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Automatically generated, 2026. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-11 16:00+0000\n" "PO-Revision-Date: 2026-03-11 16:00+0000\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: th\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "เครื่องคิดเลขวิทยาศาสตร์ความà¹�ม่นยำสูง" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "เลขคณิต;à¸�ารคำนวณ;คณิตศาสตร์;วิทยาศาสตร์;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch เป็นเครื่องคิดเลขวิทยาศาสตร์ที่รวดเร็วà¹�ละมีความà¹�ม่นยำสูง " "มาพร้อมหน้าจอเลื่อนได้ที่เน้นไวยาà¸�รณ์ à¹�ละออà¸�à¹�บบมาให้ใช้งานผ่านà¹�ป้นพิมพ์ได้อย่างเต็มรูปà¹�บบ" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "มีฟังà¸�์ชันคณิตศาสตร์ในตัวจำนวนมาà¸� à¹�ละรองรับความสามารถขั้นสูง เช่น " "ฟังà¸�์ชันที่ผู้ใช้à¸�ำหนดเอง จำนวนเชิงซ้อน à¹�ละà¸�ารà¹�ปลงหน่วย ทั้งหมดนี้รวมอยู่à¸�ับส่วนติดต่อผู้ใช้ที่เรียบง่ายà¹�ต่ทรงพลัง ซึ่งมีà¸�ารà¹�สดงตัวอย่างผลลัพธ์ทันที à¸�ารเน้นไวยาà¸�รณ์ à¹�ละà¸�ารเติมข้อความอัตโนมัติ" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch พร้อมใช้งานบนหลายà¹�พลตฟอร์มà¹�ละรองรับหลายภาษา" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "หน้าต่างหลัà¸�พร้อมà¹�ป้นตัวเลขเสริม" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "รายà¸�ารค่าคงที่à¹�ละหนังสือสูตร" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "ส่วนติดต่อผู้ใช้ที่ปรับà¹�ต่งได้" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "คู่มือผู้ใช้ในตัว" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/tr.po000066400000000000000000000064211526573132500241670ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Turkish (Turkey) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/tr_TR/)\n" "Language: tr_TR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Yüksek hassasiyetli bilimsel hesap makinesi" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "aritmetik;hesaplama;matematik;bilimsel;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch hızlı ve yüksek hassasiyetli bir bilimsel hesap makinesidir. " "Sözdizimi vurgulamalı kaydırılabilir bir ekrana sahiptir ve tamamen klavye " "ile kullanılacak ÅŸekilde tasarlanmıştır." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Birçok yerleÅŸik matematik iÅŸlevi içerir ve kullanıcı tanımlı iÅŸlevler, " "karmaşık sayılar ve birim dönüştürmeleri gibi geliÅŸmiÅŸ özellikleri " "destekler. Bunlar, anlık sonuç önizlemesi, sözdizimi vurgulama ve otomatik " "tamamlama sunan basit ama güçlü bir kullanıcı arayüzü ile birleÅŸir." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch, çeÅŸitli dillerde birden çok platform için kullanılabilir." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "İsteÄŸe baÄŸlı sayısal tuÅŸ takımıyla ana pencere" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Sabitler listesi ve formül kitabı" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "ÖzelleÅŸtirilebilir kullanıcı arayüzü" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "YerleÅŸik kullanıcı kılavuzu" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/translation-stats.py000077500000000000000000000115731526573132500272550ustar00rootroot00000000000000#!/usr/bin/env python3 from __future__ import annotations from dataclasses import dataclass from pathlib import Path from typing import Dict, List @dataclass class EntryStats: total: int = 0 translated: int = 0 fuzzy: int = 0 untranslated: int = 0 def add(self, other: "EntryStats") -> None: self.total += other.total self.translated += other.translated self.fuzzy += other.fuzzy self.untranslated += other.untranslated def completion(self) -> float: if self.total == 0: return 0.0 return (self.translated / self.total) * 100.0 @dataclass class PoEntry: msgid_parts: List[str] msgstr_parts: Dict[int, List[str]] fuzzy: bool def _parse_po_quoted(line: str) -> str: line = line.strip() if not (line.startswith('"') and line.endswith('"')): return "" content = line[1:-1] return bytes(content, "utf-8").decode("unicode_escape") def _finalize_entry(entry: PoEntry, stats: EntryStats) -> None: msgid = "".join(entry.msgid_parts) if msgid == "": return stats.total += 1 translated = any("".join(parts) != "" for parts in entry.msgstr_parts.values()) if translated: stats.translated += 1 else: stats.untranslated += 1 if entry.fuzzy: stats.fuzzy += 1 def parse_po_file(path: Path) -> EntryStats: stats = EntryStats() current: PoEntry | None = None active_field: str | None = None active_index = 0 with path.open("r", encoding="utf-8", errors="replace") as handle: for raw_line in handle: line = raw_line.rstrip("\n") if line.startswith("#,") and "fuzzy" in line: if current is None: current = PoEntry(msgid_parts=[], msgstr_parts={0: []}, fuzzy=True) else: current.fuzzy = True continue if line.startswith("msgid "): if current is not None: _finalize_entry(current, stats) current = PoEntry(msgid_parts=[], msgstr_parts={0: []}, fuzzy=False) active_field = "msgid" active_index = 0 current.msgid_parts.append(_parse_po_quoted(line[len("msgid "):])) continue if current is None: continue if line.startswith("msgstr["): idx_text = line[len("msgstr["):].split("]", 1)[0] active_index = int(idx_text) active_field = "msgstr" if active_index not in current.msgstr_parts: current.msgstr_parts[active_index] = [] start = line.find('"') current.msgstr_parts[active_index].append(_parse_po_quoted(line[start:])) continue if line.startswith("msgstr "): active_field = "msgstr" active_index = 0 current.msgstr_parts[0] = [_parse_po_quoted(line[len("msgstr "):])] continue if line.startswith('"'): value = _parse_po_quoted(line) if active_field == "msgid": current.msgid_parts.append(value) elif active_field == "msgstr": if active_index not in current.msgstr_parts: current.msgstr_parts[active_index] = [] current.msgstr_parts[active_index].append(value) continue active_field = None if current is not None: _finalize_entry(current, stats) return stats def print_report(folder: Path) -> None: po_files = sorted(folder.glob("*.po")) if not po_files: print(f"No .po files found in: {folder}") return print("Desktop AppData Translation Statistics") print(f"PO root: {folder}") print(f"Languages: {len(po_files)}") print() print("{:<12} {:>8} {:>11} {:>7} {:>13} {:>11}".format( "language", "total", "translated", "fuzzy", "untranslated", "completion" )) total_stats = EntryStats() for po_file in po_files: lang = po_file.stem stats = parse_po_file(po_file) total_stats.add(stats) print("{:<12} {:>8} {:>11} {:>7} {:>13} {:>10.1f}%".format( lang, stats.total, stats.translated, stats.fuzzy, stats.untranslated, stats.completion(), )) print() print( "Global: " f"languages={len(po_files)} " f"total={total_stats.total} " f"translated={total_stats.translated} " f"fuzzy={total_stats.fuzzy} " f"untranslated={total_stats.untranslated} " f"completion={total_stats.completion():.1f}%" ) def main() -> int: script_dir = Path(__file__).resolve().parent print_report(script_dir) return 0 if __name__ == "__main__": raise SystemExit(main()) heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/uk.po000066400000000000000000000076471526573132500241740ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-05-23 15:41+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Ukrainian (http://www.transifex.com/heldercorreia/speedcrunch/" "language/uk/)\n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "ВиÑ�окоточний науковий калькулÑ�тор" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "арифметика;обчиÑ�леннÑ�;математика;науковий;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch — швидкий виÑ�окоточний науковий калькулÑ�тор. Він має " "прокручуваний диÑ�плей із підÑ�вічуваннÑ�м Ñ�интакÑ�иÑ�у та призначений длÑ� " "повного викориÑ�таннÑ� з клавіатури." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Він міÑ�тить багато вбудованих математичних функцій Ñ– підтримує розширені " "можливоÑ�ті, такі Ñ�к визначені кориÑ�тувачем функції, комплекÑ�ні чиÑ�ла та " "перетвореннÑ� одиниць. Це поєднано з проÑ�тим, але потужним інтерфейÑ�ом " "кориÑ�тувача з миттєвим попереднім переглÑ�дом результатів, підÑ�вічуваннÑ�м " "Ñ�интакÑ�иÑ�у та автодоповненнÑ�м." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch доÑ�тупний длÑ� кількох платформ різними мовами." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Головне вікно з додатковою цифровою клавіатурою" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "СпиÑ�ок конÑ�тант Ñ– збірник формул" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Ð�алаштовуваний інтерфейÑ� кориÑ�тувача" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Вбудований поÑ�ібник кориÑ�тувача" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/uz_Latn.po000066400000000000000000000064751526573132500251670ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Uzbek (Latin) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/uz@Latn/)\n" "Language: uz_Latn\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Yuqori aniqlikdagi ilmiy kalkulyator" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "arifmetika;hisoblash;matematika;ilmiy;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch tezkor va yuqori aniqlikdagi ilmiy kalkulyator. Unda sintaksis " "yoritilgan, aylantiriladigan displey mavjud va u to'liq klaviatura orqali " "foydalanish uchun mo'ljallangan." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "U ko'plab ichki matematik funksiyalarni o'z ichiga oladi va foydalanuvchi " "tomonidan belgilangan funksiyalar, kompleks sonlar hamda birliklarni " "o'zgartirish kabi ilg'or imkoniyatlarni qo'llab-quvvatlaydi. Bularning " "barchasi natijalarni darhol oldindan ko'rish, sintaksisni yoritish va " "avtomatik to'ldirish kabi funksiyalarga ega sodda, ammo kuchli foydalanuvchi " "interfeysi bilan uyg'unlashgan." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch bir nechta platformalar uchun ko'plab tillarda mavjud." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Ixtiyoriy raqamli klaviaturali asosiy oyna" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Doimiylar ro'yxati va formulalar kitobi" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Moslashtiriladigan foydalanuvchi interfeysi" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Ichki foydalanuvchi qo'llanmasi" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/vi.po000066400000000000000000000065611526573132500241650ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Vietnamese (http://www.transifex.com/heldercorreia/" "speedcrunch/language/vi/)\n" "Language: vi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "Máy tính khoa há»�c có độ chính xác cao" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "số há»�c;tính toán;toán há»�c;khoa há»�c;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch là má»™t máy tính khoa há»�c nhanh và có độ chính xác cao. Ứng dụng " "có màn hình cuá»™n vá»›i tô sáng cú pháp và được thiết kế để có thể sá»­ dụng hoàn " "toàn bằng bàn phím." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "Ứng dụng bao gồm nhiá»�u hàm toán há»�c tích hợp và há»— trợ các tính năng nâng cao " "như hàm do ngưá»�i dùng định nghÄ©a, số phức và chuyển đổi đơn vị. Tất cả được " "kết hợp vá»›i giao diện đơn giản nhưng mạnh mẽ, có xem trước kết quả tức thá»�i, " "tô sáng cú pháp và tá»± động hoàn thành." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch có sẵn cho nhiá»�u ná»�n tảng vá»›i nhiá»�u ngôn ngữ." #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "Cá»­a sổ chính vá»›i bàn phím số tùy chá»�n" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "Danh sách hằng số và sổ công thức" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "Giao diện ngưá»�i dùng có thể tùy biến" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "Hướng dẫn sá»­ dụng tích hợp" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/zh_CN.po000066400000000000000000000060311526573132500245400ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Y.F Yang , 2016 msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-29 08:09+0000\n" "Last-Translator: Y.F Yang \n" "Language-Team: Chinese (China) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/zh_CN/)\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "高精度科学计算器" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "计算;æ•°å­¦;科学计算;计算器;å…¬å¼�;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch 是一个快速ã€�高精度的科学计算器。它具有语法高亮和å�¯æ»šåŠ¨çš„æ˜¾ç¤ºï¼Œå¹¶" "且å�¯ä»¥å…¨ç¨‹ä½¿ç”¨é”®ç›˜æ“�作。" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "它内置许多数学函数并支æŒ�一些高级功能,例如用户定义函数ã€�å¤�æ�‚æ•°å­—å’Œå�•ä½�转æ�¢ã€‚" "è¿™å�¯é…�å�ˆç®€å�•å�ˆå¼ºå¤§çš„用户界é�¢ï¼ŒåŒ…括结果预览ã€�语法高亮和自动完æˆ�。" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch æ��供多ç§�语言和平å�°ã€‚" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "主窗å�£ï¼ˆé”®ç›˜å�¯ç”¨ï¼‰" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "常é‡�列表和公å¼�书" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "å�¯å®šåˆ¶ç”¨æˆ·ç•Œé�¢" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "内置用户手册" heldercorreia-speedcrunch-e7ca37f/pkg/desktop-appdata/zh_TW.po000066400000000000000000000060761526573132500246030ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: msgid "" msgstr "" "Project-Id-Version: SpeedCrunch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-10 15:46+0000\n" "PO-Revision-Date: 2016-07-18 23:45+0000\n" "Last-Translator: Felix Krull \n" "Language-Team: Chinese (Taiwan) (http://www.transifex.com/heldercorreia/" "speedcrunch/language/zh_TW/)\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #. TRANSLATORS: Name of the application, usually shouldn't be translated. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:1 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:2 msgid "SpeedCrunch" msgstr "SpeedCrunch" #. TRANSLATORS: Short one-line description. #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:2 #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:4 msgid "A high-precision scientific calculator" msgstr "高精度科學計算器" #. TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! #: tmp/org.speedcrunch.SpeedCrunch.desktop.in.h:4 msgid "arithmetic;calculation;math;scientific;" msgstr "計算;數學;科學計算;計算器;å…¬å¼�;" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:5 msgid "" "SpeedCrunch is a fast, high-precision scientific calculator. It features a " "syntax-highlighted scrollable display and is designed to be fully used via " "keyboard." msgstr "" "SpeedCrunch 是一款快速且高精度的科學計算器。它具備語法醒目æ��示的å�¯æ�²å‹•顯示,並" "且設計為å�¯å®Œå…¨é€�é�Žé�µç›¤æ“�作。" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:6 msgid "" "It includes many built-in maths functions and supports advanced features " "like user-defined functions, complex numbers, and unit conversions. This is " "combined with a simple yet powerful user interface featuring on-the-fly " "results preview, syntax highlighting, and autocompletion." msgstr "" "它包å�«å¤šç¨®å…§å»ºæ•¸å­¸å‡½æ•¸ï¼Œä¸¦æ”¯æ�´é€²éšŽåŠŸèƒ½ï¼Œä¾‹å¦‚ä½¿ç”¨è€…è‡ªè¨‚å‡½æ•¸ã€�複數與單ä½�轉æ�›ã€‚這" "些功能æ�­é…�簡潔但強大的使用者介é�¢ï¼Œæ��ä¾›å�³æ™‚çµ�æžœé �覽ã€�語法醒目æ��示與自動補完。" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:7 msgid "" "SpeedCrunch is available for several platforms in a number of languages." msgstr "SpeedCrunch å�¯åœ¨å¤šå€‹å¹³å�°ä¸Šä½¿ç”¨ï¼Œä¸¦æ��供多種語言。" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:8 msgid "Main window with optional keypad" msgstr "主視窗(å�«é�¸ç”¨æ•¸å­—é�µç›¤ï¼‰" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:9 msgid "The constants list and formula book" msgstr "常數清單與公å¼�手冊" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:10 msgid "Customizable user interface" msgstr "å�¯è‡ªè¨‚的使用者介é�¢" #: tmp/org.speedcrunch.SpeedCrunch.metainfo.xml.in.h:11 msgid "The built-in user manual" msgstr "內建使用者手冊" heldercorreia-speedcrunch-e7ca37f/pkg/org.speedcrunch.SpeedCrunch.desktop000066400000000000000000000167061526573132500270160ustar00rootroot00000000000000[Desktop Entry] Type=Application Name=SpeedCrunch Name[ar]=SpeedCrunch Name[bg]=SpeedCrunch Name[bn]=SpeedCrunch Name[ca]=SpeedCrunch Name[cs]=SpeedCrunch Name[da]=SpeedCrunch Name[de]=SpeedCrunch Name[el]=SpeedCrunch Name[en_GB]=SpeedCrunch Name[en_US]=SpeedCrunch Name[es]=SpeedCrunch Name[es_ES]=SpeedCrunch Name[et]=SpeedCrunch Name[eu]=SpeedCrunch Name[fa]=SpeedCrunch Name[fi]=SpeedCrunch Name[fr]=SpeedCrunch Name[gl]=SpeedCrunch Name[he]=SpeedCrunch Name[hi]=SpeedCrunch Name[hu]=SpeedCrunch Name[id]=SpeedCrunch Name[it]=SpeedCrunch Name[ja]=SpeedCrunch Name[ko]=SpeedCrunch Name[lt]=SpeedCrunch Name[lv]=SpeedCrunch Name[ms]=SpeedCrunch Name[nb]=SpeedCrunch Name[nl]=SpeedCrunch Name[pl]=SpeedCrunch Name[pt_BR]=SpeedCrunch Name[pt_PT]=SpeedCrunch Name[ro]=SpeedCrunch Name[ru]=SpeedCrunch Name[sk]=SpeedCrunch Name[sl]=SpeedCrunch Name[sv]=SpeedCrunch Name[sw]=SpeedCrunch Name[ta]=SpeedCrunch Name[te]=SpeedCrunch Name[th]=SpeedCrunch Name[tr]=SpeedCrunch Name[uk]=SpeedCrunch Name[uz_Latn]=SpeedCrunch Name[vi]=SpeedCrunch Name[zh_CN]=SpeedCrunch Name[zh_TW]=SpeedCrunch Exec=speedcrunch Icon=org.speedcrunch.SpeedCrunch StartupWMClass=speedcrunch Comment=A high-precision scientific calculator Comment[ar]=آلة حاسبة علمية عالية الدقة Comment[bg]=Ð�аучен калкулатор Ñ� виÑ�ока точноÑ�Ñ‚ Comment[bn]=উচà§�চ-নিরà§�ভà§�ল বৈজà§�ঞানিক কà§�যালকà§�লেটর Comment[ca]=Una calculadora científica d'alta precisió Comment[cs]=Vysoce pÅ™esná vÄ›decká kalkulaÄ�ka Comment[da]=En videnskabelig lommeregner med høj præcision Comment[de]=Ein hochpräziser wissenschaftlicher Taschenrechner Comment[el]=Επιστημονική αÏ�ιθμομηχανή υψηλής ακÏ�ίβειας Comment[en_GB]=A high-precision scientific calculator Comment[en_US]=A high-precision scientific calculator Comment[es]=Una calculadora científica de alta precisión Comment[es_ES]=Una calculadora científica de alta precisión Comment[et]=Kõrgtäpne teaduslik kalkulaator Comment[eu]=Zehaztasun handiko kalkulagailu zientifikoa Comment[fa]=ماشین‌حساب علمی با دقت بالا Comment[fi]=Erittäin tarkka tieteellinen laskin Comment[fr]=Une calculatrice scientifique de haute précision Comment[gl]=Unha calculadora científica de alta precisión Comment[he]=מחשבון מדעי בדיוק גבוה Comment[hi]=उचà¥�च-सटीकता वाला वैजà¥�ञानिक कैलकà¥�लेटर Comment[hu]=Egy nagy pontosságú tudományos számológép Comment[id]=Kalkulator ilmiah presisi tinggi Comment[it]=Una calcolatrice scientifica ad alta precisione Comment[ja]=高精度ã�®ç§‘学計算機 Comment[ko]=ê³ ì •ë°€ 공학용 계산기 Comment[lt]=Labai tikslus mokslinis skaiÄ�iuotuvas Comment[lv]=Augstas precizitÄ�tes zinÄ�tniskais kalkulators Comment[ms]=Kalkulator saintifik berketepatan tinggi Comment[nb]=En vitenskapelig kalkulator med høy presisjon Comment[nl]=Een wetenschappelijke rekenmachine met hoge precisie Comment[pl]=Wysokoprecyzyjny kalkulator naukowy Comment[pt_BR]=Calculadora científica de alta precisão Comment[pt_PT]=Uma calculadora científica de alta precisão Comment[ro]=Un calculator È™tiinÈ›ific de înaltă precizie Comment[ru]=Ð�аучный инженерный калькулÑ�тор Comment[sk]=Vysokopresná vedecká kalkulaÄ�ka Comment[sl]=VisokonatanÄ�en znanstveni kalkulator Comment[sv]=En vetenskaplig miniräknare med hög precision Comment[sw]=Kikokotoo cha kisayansi chenye usahihi wa juu Comment[ta]=உயரà¯� தà¯�லà¯�லியமான அறிவியலà¯� கணிபà¯�பானà¯� Comment[te]=à°…à°§à°¿à°• à°–à°šà±�చితతà±�వం à°—à°² శాసà±�à°¤à±�రీయ కాలికà±�à°¯à±�లేటరà±� Comment[th]=เครื่องคิดเลขวิทยาศาสตร์ความà¹�ม่นยำสูง Comment[tr]=Yüksek hassasiyetli bilimsel hesap makinesi Comment[uk]=ВиÑ�окоточний науковий калькулÑ�тор Comment[uz_Latn]=Yuqori aniqlikdagi ilmiy kalkulyator Comment[vi]=Máy tính khoa há»�c có độ chính xác cao Comment[zh_CN]=高精度科学计算器 Comment[zh_TW]=高精度科學計算器 Categories=Qt;Utility;Calculator; # TRANSLATORS: Extra keywords for finding the application in the desktop environment. The trailing ';' is important! Keywords=arithmetic;calculation;math;scientific; Keywords[ar]=حساب;حسابات;رياضيات;علمي; Keywords[bg]=аритметика;изчиÑ�ление;математика;научен; Keywords[bn]=পাটিগণিত;গণনা;গণিত;বৈজà§�ঞানিক; Keywords[ca]=aritmètica;càlcul;matemàtiques;científica; Keywords[cs]=aritmetika;výpoÄ�ty;matematika;vÄ›decká; Keywords[da]=aritmetik;beregning;matematik;videnskabelig; Keywords[de]=arithmetik;berechnungen;rechnen;mathe;mathematik;wissenschaftlich; Keywords[el]=αÏ�ιθμητική;υπολογισμός;μαθηματικά;επιστημονικό; Keywords[en_GB]=arithmetic;calculation;math;scientific; Keywords[en_US]=arithmetic;calculation;math;scientific; Keywords[es]=aritmética;cálculo;matemáticas;científica; Keywords[es_ES]=aritmética;cálculo;matemáticas;científica; Keywords[et]=aritmeetika;arvutamine;matemaatika;teaduslik; Keywords[eu]=aritmetika;kalkulua;matematika;zientifikoa; Keywords[fa]=حساب;محاسبه;ریاضی;علمی; Keywords[fi]=aritmetiikka;laskenta;matematiikka;tieteellinen; Keywords[fr]=arithmétique;calcul;mathématiques;scientifique; Keywords[gl]=aritmética;cálculo;matemáticas;científica; Keywords[he]=×�ריתמטיקה;חישוב;מתמטיקה;מדעי; Keywords[hi]=अंकगणित;गणना;गणित;वैजà¥�ञानिक; Keywords[hu]=aritmetika;számítás;matematika;tudományos; Keywords[id]=aritmetika;perhitungan;matematika;ilmiah; Keywords[it]=aritmetica;calcolo;matematica;scientifico; Keywords[ja]=ç®—è¡“;計算;æ•°å­¦;ç§‘å­¦; Keywords[ko]=산술;계산;수학;과학; Keywords[lt]=aritmetika;skaiÄ�iavimas;matematika;mokslinis; Keywords[lv]=aritmÄ“tika;aprēķini;matemÄ�tika;zinÄ�tnisks; Keywords[ms]=aritmetik;pengiraan;matematik;saintifik; Keywords[nb]=aritmetikk;beregning;matematikk;vitenskapelig; Keywords[nl]=rekenkunde;berekening;wiskunde;wetenschappelijk; Keywords[pl]=arytmetyka;obliczenia;matematyka;naukowy; Keywords[pt_BR]=aritmética;cálculo;matemática;científico; Keywords[pt_PT]=aritmética;cálculo;matemática;científica; Keywords[ro]=aritmetică;calcul;matematică;È™tiinÈ›ific; Keywords[ru]=арифметика;вычиÑ�лениÑ�;математика;научный; Keywords[sk]=aritmetika;výpoÄ�ty;matematika;vedecká; Keywords[sl]=aritmetika;izraÄ�un;matematika;znanstveni; Keywords[sv]=aritmetik;beräkning;matematik;vetenskaplig; Keywords[sw]=hesabu;ukokotozi;hisabati;kisayansi; Keywords[ta]=கணிதமà¯�;கணகà¯�கீடà¯�;கணிதவியலà¯�;அறிவியலà¯�; Keywords[te]=అంకగణితం;గణన;గణితం;శాసà±�à°¤à±�రీయ; Keywords[th]=เลขคณิต;à¸�ารคำนวณ;คณิตศาสตร์;วิทยาศาสตร์; Keywords[tr]=aritmetik;hesaplama;matematik;bilimsel; Keywords[uk]=арифметика;обчиÑ�леннÑ�;математика;науковий; Keywords[uz_Latn]=arifmetika;hisoblash;matematika;ilmiy; Keywords[vi]=số há»�c;tính toán;toán há»�c;khoa há»�c; Keywords[zh_CN]=计算;æ•°å­¦;科学计算;计算器;å…¬å¼�; Keywords[zh_TW]=計算;數學;科學計算;計算器;å…¬å¼�; heldercorreia-speedcrunch-e7ca37f/pkg/org.speedcrunch.SpeedCrunch.metainfo.xml000066400000000000000000002014361526573132500277420ustar00rootroot00000000000000 org.speedcrunch.SpeedCrunch CC0-1.0 GPL-2.0+ speedcrunch@googlegroups.com The SpeedCrunch Developers SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch SpeedCrunch A high-precision scientific calculator آلة حاسبة علمية عالية الدقة Ð�аучен калкулатор Ñ� виÑ�ока точноÑ�Ñ‚ উচà§�চ-নিরà§�ভà§�ল বৈজà§�ঞানিক কà§�যালকà§�লেটর Una calculadora científica d'alta precisió Vysoce pÅ™esná vÄ›decká kalkulaÄ�ka En videnskabelig lommeregner med høj præcision Ein hochpräziser wissenschaftlicher Taschenrechner Επιστημονική αÏ�ιθμομηχανή υψηλής ακÏ�ίβειας A high-precision scientific calculator A high-precision scientific calculator Una calculadora científica de alta precisión Una calculadora científica de alta precisión Kõrgtäpne teaduslik kalkulaator Zehaztasun handiko kalkulagailu zientifikoa ماشین‌حساب علمی با دقت بالا Erittäin tarkka tieteellinen laskin Une calculatrice scientifique de haute précision Unha calculadora científica de alta precisión מחשבון מדעי בדיוק גבוה उचà¥�च-सटीकता वाला वैजà¥�ञानिक कैलकà¥�लेटर Egy nagy pontosságú tudományos számológép Kalkulator ilmiah presisi tinggi Una calcolatrice scientifica ad alta precisione 高精度ã�®ç§‘学計算機 ê³ ì •ë°€ 공학용 계산기 Labai tikslus mokslinis skaiÄ�iuotuvas Augstas precizitÄ�tes zinÄ�tniskais kalkulators Kalkulator saintifik berketepatan tinggi En vitenskapelig kalkulator med høy presisjon Een wetenschappelijke rekenmachine met hoge precisie Wysokoprecyzyjny kalkulator naukowy Calculadora científica de alta precisão Uma calculadora científica de alta precisão Un calculator È™tiinÈ›ific de înaltă precizie Ð�аучный инженерный калькулÑ�тор Vysokopresná vedecká kalkulaÄ�ka VisokonatanÄ�en znanstveni kalkulator En vetenskaplig miniräknare med hög precision Kikokotoo cha kisayansi chenye usahihi wa juu உயரà¯� தà¯�லà¯�லியமான அறிவியலà¯� கணிபà¯�பானà¯� à°…à°§à°¿à°• à°–à°šà±�చితతà±�వం à°—à°² శాసà±�à°¤à±�రీయ కాలికà±�à°¯à±�లేటరà±� เครื่องคิดเลขวิทยาศาสตร์ความà¹�ม่นยำสูง Yüksek hassasiyetli bilimsel hesap makinesi ВиÑ�окоточний науковий калькулÑ�тор Yuqori aniqlikdagi ilmiy kalkulyator Máy tính khoa há»�c có độ chính xác cao 高精度科学计算器 高精度科學計算器

    SpeedCrunch is a fast, high-precision scientific calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard.

    SpeedCrunch آلة حاسبة علمية سريعة وعالية الدقة. تتميز بعرض قابل للتمرير مع إبراز بناء الجملة، وهي مصممة لي�ستخدم البرنامج بالكامل عبر لوحة الم�اتيح.

    SpeedCrunch е бърз научен калкулатор � ви�ока точно�т. Той предлага превъртащ �е ди�плей � откро�ване на �интак�и�а и е проектиран да �е използва изц�ло � клавиатура.

    SpeedCrunch �কটি দ�র�ত, উচ�চ-নির�ভ�ল বৈজ�ঞানিক ক�যালক�লেটর। �তে সিনট�যাক�স-হাইলাইট করা স�ক�রলযোগ�য প�রদর�শন আছে �বং �টি সম�পূর�ণভাবে কীবোর�ড দিয়ে ব�যবহার করার জন�য নকশা করা হয়েছে।

    SpeedCrunch és una calculadora científica ràpida i d'alta precisió. Inclou una pantalla desplaçable amb ressaltat de sintaxi i està dissenyada per ser utilitzada completament amb el teclat.

    SpeedCrunch je rychlá, vysoce přesná vědecká kalkula�ka. Nabízí rolovatelný displej se zvýrazněním syntaxe a je navržena pro plné ovládání z klávesnice.

    SpeedCrunch er en hurtig, videnskabelig lommeregner med høj præcision. Den har et rullebart display med syntaksfremhævning og er designet til at kunne bruges fuldt ud via tastaturet.

    SpeedCrunch ist ein schneller, hochpräziser, wissenschaftlicher Taschenrechner. Es bietet eine scrollbare Anzeige mit Syntaxhervorhebung und ist auf vollständige Tastaturbedienung ausgelegt.

    Το SpeedCrunch είναι μια γ�ήγο�η επιστημονική α�ιθμομηχανή υψηλής ακ�ίβειας. Διαθέτει κυλιόμενη οθόνη με επισήμανση σ�νταξης και έχει σχεδιαστεί ώστε να χ�ησιμοποιείται πλή�ως από το πληκτ�ολόγιο.

    SpeedCrunch is a fast, high-precision scientific calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard.SpeedCrunch is a fast, high-precision scientific calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard.

    SpeedCrunch is a fast, high-precision scientific calculator. It features a syntax-highlighted scrollable display and is designed to be fully used via keyboard.

    SpeedCrunch es una calculadora científica rápida y de alta precisión. Cuenta con una pantalla desplazable con resaltado de sintaxis y está diseñada para usarse completamente con el teclado.

    SpeedCrunch es una calculadora científica rápida y de alta precisión. Cuenta con una pantalla desplazable con resaltado de sintaxis y está diseñada para usarse completamente con el teclado.

    SpeedCrunch on kiire ja kõrgtäpne teaduslik kalkulaator. Sellel on süntaksi esiletõstuga keritav kuva ning see on loodud täielikult klaviatuuriga kasutamiseks.

    SpeedCrunch zehaztasun handiko kalkulagailu zientifiko azkarra da. Sintaxia nabarmenduta duen bistaratze korritzailea dauka, eta teklatu bidez erabat erabiltzeko diseinatuta dago.

    SpeedCrunch یک ماشین‌حساب علمی سریع و با دقت بالاست. این برنامه دارای نمایشگر قابل‌پیمایش با برجسته‌سازی نحو است و برای است�ادهٔ کامل از طریق ص�حه‌کلید طراحی شده است.

    SpeedCrunch on nopea ja erittäin tarkka tieteellinen laskin. Siinä on syntaksikorostettu vieritettävä näyttö, ja se on suunniteltu käytettäväksi kokonaan näppäimistöllä.

    SpeedCrunch est une calculatrice scientifique rapide et de haute précision. Elle propose un affichage défilant avec coloration syntaxique et est conçue pour être utilisée entièrement au clavier.

    SpeedCrunch é unha calculadora científica rápida e de alta precisión. Conta cun visor desprazable con realce de sintaxe e está deseñada para usarse completamente co teclado.

    SpeedCrunch הו� מחשבון מדעי מהיר ובדיוק גבוה. הו� כולל תצוגה נגללת ע� הדגשת תחביר, ונועד לשימוש מל� ב�מצעות המקלדת.

    SpeedCrunch �क तेज, उच�च-सटीकता वाला वैज�ञानिक कैलक�लेटर है। इसमें सिंटैक�स-हाइलाइटेड स�क�रॉल करने योग�य डिस�प�ले है और इसे पूरी तरह कीबोर�ड से उपयोग करने के लि� बनाया गया है।

    A SpeedCrunch egy gyors, nagy pontosságú tudományos számológép. Szintaxis kiemeléses, görgethető kijelzővel rendelkezik és úgy tervezték, hogy teljes mértékben használható legyen billentyűzetről.

    SpeedCrunch adalah kalkulator ilmiah yang cepat dan berpresisi tinggi. Aplikasi ini memiliki tampilan yang dapat digulir dengan penyorotan sintaks, dan dirancang untuk digunakan sepenuhnya melalui papan ketik.

    SpeedCrunch è una calcolatrice scientifica veloce e ad alta precisione. Presenta uno schermo scorrevole con evidenziazione della sintassi ed è progettata per essere completamente usabile tramite tastiera.

    SpeedCrunch �高速�高精度�科学計算機��。構文強調表示付��スクロール�能�表示を備��キーボード���完全��作��るよ�設計�れ����。

    SpeedCrunch는 빠르고 고정밀� 공학용 계산기입니다. 구문 강조 표시가 �용� 스�롤 가능한 화면� 제공하며, 키보드만으로 완전히 사용할 수 있�� 설계�었습니다.

    SpeedCrunch yra greitas, labai tikslus mokslinis skai�iuotuvas. Jis pasižymi sintaksę paryškinan�iu slenkan�iu ekranu ir yra sukurtas, kad būtų pilnai naudojamas su klaviatūra.

    SpeedCrunch ir �trs, augstas precizit�tes zin�tniskais kalkulators. Tam ir ritin�ms displejs ar sintakses izcelšanu, un tas ir paredzēts pilnīgai lietošanai ar tastatūru.

    SpeedCrunch ialah kalkulator saintifik yang pantas dan berketepatan tinggi. Ia menampilkan paparan boleh tatal dengan penyerlahan sintaks dan direka untuk digunakan sepenuhnya melalui papan kekunci.

    SpeedCrunch er en rask vitenskapelig kalkulator med høy presisjon. Den har et rullbart display med syntaksutheving og er utviklet for å kunne brukes fullt ut med tastaturet.

    SpeedCrunch is een snelle wetenschappelijke rekenmachine met hoge precisie. Het beschikt over een scrollbaar scherm met syntaxisaccentuering en is ontworpen om volledig via het toetsenbord te worden gebruikt.

    SpeedCrunch to szybki, wysokoprecyzyjny kalkulator naukowy. Posiada przewijalny ekran z podświetlaniem składni i jest zaprojektowany do pełnej obsługi z klawiatury.

    O SpeedCrunch é uma calculadora científica rápida e de alta precisão. Ele possui um visor rolável com realce de sintaxe e foi projetado para ser usado totalmente pelo teclado.SpeedCrunch é uma calculadora científica rápida e de alta precisão. Ela possui um mostrador rolável, com destaque de sintaxe e é concebida para ser plenamente utilizável através do teclado.

    O SpeedCrunch é uma calculadora científica rápida e de alta precisão. Apresenta um visor rolável com realce de sintaxe e foi concebido para ser utilizado integralmente através do teclado.

    SpeedCrunch este un calculator științific rapid, de înaltă precizie. Oferă un afișaj derulabil cu evidențiere a sintaxei și este conceput pentru a fi folosit în întregime de la tastatură.

    SpeedCrunch — бы�трый вы�окоточный научный калькул�тор. Он имеет прокручиваемый ди�плей � под�веткой �интак�и�а и предназначен дл� полного управлени� � клавиатуры.

    SpeedCrunch je rýchla, vysoko presná vedecká kalkula�ka. Ponúka rolovateľný displej so zvýraznením syntaxe a je navrhnutá tak, aby sa dala plnohodnotne používať pomocou klávesnice.

    SpeedCrunch je hiter, visokonatan�en znanstveni kalkulator. Ima pomi�no prikazovalno okno s poudarjanjem skladnje in je zasnovan za popolno uporabo s tipkovnico.

    SpeedCrunch är en snabb vetenskaplig miniräknare med hög precision. Den har en rullbar skärm med syntaxmarkering och är utformad för att kunna användas helt via tangentbordet.

    SpeedCrunch ni kikokotoo cha kisayansi cha haraka chenye usahihi wa juu. Kina onyesho linaloweza kusogezwa lenye uangaziaji wa sintaksia na kimeundwa kutumiwa kikamilifu kwa kibodi.

    SpeedCrunch என�பத� வேகமான, உயர� த�ல�லியமான அறிவியல� கணிப�பான�. இத� தொடரமைப�ப� ம�ன�னிற�த�தல�டன� கூடிய ச�ர�ட�டக�கூடிய காட�சியைக� கொண�ட�ள�ளத�, மேல�ம� ம�ழ�மையாக விசைப�பலகை மூலம� பயன�பட�த�தப�பட�மாற� வடிவமைக�கப�பட�ட�ள�ளத�.

    SpeedCrunch ఒక వేగవంతమైన, అధిక ఖచ�చితత�వం గల శాస�త�రీయ కాలిక�య�లేటర�. ఇది సింటాక�స� హైలైట� చేసిన స�క�రోల� చేయగల ప�రదర�శనన� కలిగి ఉంది మరియ� పూర�తిగా కీబోర�డ� ద�వారా ఉపయోగించేంద�క� రూపకల�పన చేయబడింది.

    SpeedCrunch เป็นเครื่องคิดเลขวิทยาศาสตร์ที่รวดเร็ว�ละมีความ�ม่นยำสูง มาพร้อมหน้าจอเลื่อนได้ที่เน้นไวยา�รณ์ �ละออ��บบมาให้ใช้งานผ่าน�ป้นพิมพ์ได้อย่างเต็มรูป�บบ

    SpeedCrunch hızlı ve yüksek hassasiyetli bir bilimsel hesap makinesidir. Sözdizimi vurgulamalı kaydırılabilir bir ekrana sahiptir ve tamamen klavye ile kullanılacak şekilde tasarlanmıştır.

    SpeedCrunch — швидкий ви�окоточний науковий калькул�тор. Він має прокручуваний ди�плей із під�вічуванн�м �интак�и�у та призначений дл� повного викори�танн� з клавіатури.

    SpeedCrunch tezkor va yuqori aniqlikdagi ilmiy kalkulyator. Unda sintaksis yoritilgan, aylantiriladigan displey mavjud va u to'liq klaviatura orqali foydalanish uchun mo'ljallangan.

    SpeedCrunch là một máy tính khoa h�c nhanh và có độ chính xác cao. Ứng dụng có màn hình cuộn với tô sáng cú pháp và được thiết kế để có thể sử dụng hoàn toàn bằng bàn phím.

    SpeedCrunch 是一个快速�高精度的科学计算器。它具有语法高亮和�滚动的显示,并且�以全程使用键盘�作。

    SpeedCrunch 是一款快速且高精度的科學計算器。它具備語法醒目�示的��動顯示,並且設計為�完全���盤�作。

    It includes many built-in maths functions and supports advanced features like user-defined functions, complex numbers, and unit conversions. This is combined with a simple yet powerful user interface featuring on-the-fly results preview, syntax highlighting, and autocompletion.

    يتضمن العديد من الدوال الرياضية المضمنة ويدعم ميزات متقدمة مثل الدوال المعرّ�ة من قبل المستخدم، والأعداد المركبة، وتحويل الوحدات. ويتكامل ذلك مع واجهة مستخدم بسيطة لكنها قوية تتضمن معاينة �ورية للنتائج، وإبراز بناء الجملة، والإكمال التلقائي.

    Той включва много вградени математиче�ки функции и поддържа разширени възможно�ти като потребител�ки функции, комплек�ни чи�ла и преобразуване на единици. Това е �ъчетано � про�т, но мощен потребител�ки интерфей� � незабавен преглед на резултатите, откро�ване на �интак�и�а и автоматично довършване.

    �তে অনেক অন�তর�নির�মিত গাণিতিক ফাংশন রয়েছে �বং ব�যবহারকারী-সংজ�ঞায়িত ফাংশন, জটিল সংখ�যা ও �কক রূপান�তরের মতো উন�নত বৈশিষ�ট�য সমর�থন করে। �র সঙ�গে আছে সরল কিন�ত� শক�তিশালী ব�যবহারকারী ইন�টারফেস, যেখানে তাৎক�ষণিক ফলাফলের পূর�বরূপ, সিনট�যাক�স হাইলাইটিং �বং স�বয়ংসম�পূর�ণতা রয়েছে।

    Inclou moltes funcions matemàtiques integrades i admet funcions avançades com les funcions definides per l'usuari, els nombres complexos i les conversions d'unitats. Tot això es combina amb una interfície d'usuari senzilla però potent amb previsualització de resultats al vol, ressaltat de sintaxi i autocompleció.

    Obsahuje mnoho vestavěných matematických funkcí a podporuje pokro�ilé funkce, jako jsou uživatelsky definované funkce, komplexní �ísla a převody jednotek. To vše doplňuje jednoduché, ale výkonné uživatelské rozhraní s okamžitým náhledem výsledků, zvýrazněním syntaxe a automatickým doplňováním.

    Den indeholder mange indbyggede matematiske funktioner og understøtter avancerede funktioner såsom brugerdefinerede funktioner, komplekse tal og enhedskonverteringer. Dette kombineres med en enkel, men kraftfuld brugerflade med forhåndsvisning af resultater i realtid, syntaksfremhævning og autofuldførelse.

    Es enthält viele eingebaute Mathematikfunktionen und unterstützt fortgeschrittene Funktionen wie benutzerdefinierte Funktionen, komplexe Zahlen und Einheitenumwandlungen. Dies ist verbunden mit einer einfacher, aber leistungsfähigen Benutzeroberfläche mit dynamischer Ergebnisvorschau, Syntaxhervorhebung und automatischer Vervollständigung.

    Πε�ιλαμβάνει πολλές ενσωματωμένες μαθηματικές συνα�τήσεις και υποστη�ίζει π�οηγμένες δυνατότητες όπως συνα�τήσεις ο�ισμένες από τον χ�ήστη, μιγαδικο�ς α�ιθμο�ς και μετατ�οπές μονάδων. Όλα αυτά συνδυάζονται με ένα απλό αλλά ισχυ�ό πε�ιβάλλον χ�ήστη με π�οεπισκόπηση αποτελεσμάτων σε π�αγματικό χ�όνο, επισήμανση σ�νταξης και αυτόματη συμπλή�ωση.

    It includes many built-in maths functions and supports advanced features like user-defined functions, complex numbers, and unit conversions. This is combined with a simple yet powerful user interface featuring on-the-fly results preview, syntax highlighting, and autocompletion.It includes many built-in maths functions and supports advanced features like user-defined functions, complex numbers, and unit conversions. This is combined with a simple yet powerful user interface featuring on-the-fly results preview, syntax highlighting, and autocompletion.

    It includes many built-in maths functions and supports advanced features like user-defined functions, complex numbers, and unit conversions. This is combined with a simple yet powerful user interface featuring on-the-fly results preview, syntax highlighting, and autocompletion.

    Incluye muchas funciones matemáticas integradas y admite funciones avanzadas como funciones definidas por el usuario, números complejos y conversiones de unidades. Todo ello se combina con una interfaz de usuario sencilla pero potente que ofrece vista previa de resultados al vuelo, resaltado de sintaxis y autocompletado.

    Incluye muchas funciones matemáticas integradas y admite funciones avanzadas como funciones definidas por el usuario, números complejos y conversiones de unidades. Todo ello se combina con una interfaz de usuario sencilla pero potente que ofrece vista previa de resultados al vuelo, resaltado de sintaxis y autocompletado.

    See sisaldab palju sisseehitatud matemaatikafunktsioone ja toetab täiustatud võimalusi, nagu kasutaja määratud funktsioonid, kompleksarvud ja ühikute teisendused. Seda kõike ühendab lihtne, kuid võimas kasutajaliides, mis pakub tulemuste kohest eelvaadet, süntaksi esiletõstu ja automaatset lõpetamist.

    Matematika-funtzio integratu ugari ditu, eta eginbide aurreratuak onartzen ditu, hala nola erabiltzaileak definitutako funtzioak, zenbaki konplexuak eta unitate-bihurketak. Hori guztia erabiltzaile-interfaze sinple baina indartsu batekin uztartzen da, emaitzen aurrebista berehalakoa, sintaxi-nabarmendua eta osatze automatikoa eskainiz.

    این برنامه شامل بسیاری از توابع ریاضی� داخلی است و از قابلیت‌های پیشر�ته‌ای مانند توابع� تعری�‌شده توسط کاربر، اعداد مختلط و تبدیل واحدها پشتیبانی می‌کند. همهٔ این‌ها با یک رابط کاربری ساده اما قدرتمند همراه است که پیش‌نمایش� آنی� نتایج، برجسته‌سازی� نحو و تکمیل خودکار را �راهم می‌کند.

    Se sisältää monia sisäänrakennettuja matemaattisia toimintoja ja tukee edistyneitä ominaisuuksia, kuten käyttäjän määrittelemiä funktioita, kompleksilukuja ja yksikkömuunnoksia. Tämä yhdistyy yksinkertaiseen mutta tehokkaaseen käyttöliittymään, jossa on tulosten reaaliaikainen esikatselu, syntaksikorostus ja automaattinen täydennys.

    Elle inclut de nombreuses fonctions mathématiques intégrées et prend en charge des fonctionnalités avancées comme les fonctions définies par l'utilisateur, les nombres complexes et les conversions d'unités. Le tout est associé à une interface simple mais puissante offrant l'aperçu des résultats à la volée, la coloration syntaxique et l'autocomplétion.

    Inclúe moitas funcións matemáticas integradas e admite características avanzadas como funcións definidas polo usuario, números complexos e conversións de unidades. Todo isto combínase cunha interface de usuario sinxela pero potente que ofrece previsualización inmediata dos resultados, realce de sintaxe e autocompletado.

    הו� כולל פונקציות מתמטיות מובנות רבות ותומך בתכונות מתקדמות כמו פונקציות בהגדרת משתמש, מספרי� מרוכבי� והמרות יחידות. כל ז�ת משולב ע� ממשק משתמש פשוט �ך עוצמתי הכולל תצוגה מקדימה של תוצ�ות בזמן �מת, הדגשת תחביר והשלמה �וטומטית.

    इसमें कई अंतर�निहित गणितीय फलन शामिल हैं और यह उपयोगकर�ता-परिभाषित फलन, सम�मिश�र संख�या�� और इकाई रूपांतरण जैसी उन�नत स�विधाओं का समर�थन करता है। इसके साथ �क सरल लेकिन शक�तिशाली उपयोगकर�ता इंटरफ़ेस है जिसमें त�रंत परिणाम पूर�वावलोकन, सिंटैक�स हाइलाइटिंग और स�वचालित पूर�णता शामिल हैं।

    Számos beépített matematikai függvényt tartalmaz és támogatja az olyan fejlett képességeket, mint a felhasználó által biztosított függvények, komplex számok és a mértékegység konvertálás. Mindez kombinálva van egy egyszerű, de fejlett felhasználói felülettel, ami lehetővé teszi az eredmények azonnali előnézetét, szintaxis kiemelést és az automatikus kiegészítést.

    Aplikasi ini mencakup banyak fungsi matematika bawaan dan mendukung fitur lanjutan seperti fungsi yang ditentukan pengguna, bilangan kompleks, dan konversi satuan. Semuanya dipadukan dengan antarmuka pengguna yang sederhana namun kuat, dengan pratinjau hasil secara langsung, penyorotan sintaks, dan pelengkapan otomatis.

    Include molte funzioni matematiche predefinite e supporta funzionalità avanzate come funzioni definite dall'utente, numeri complessi e conversione di unità. Questo si aggiunge ad un'interfaccia utente semplice ma potente che fornisce anteprime al volo dei risultati, evidenziazione della sintassi ed autocompletamento.

    多数�組�込�数学関数を備��ユーザー定義関数�複素数���変����高度�機能をサ�ート���。�ら���果�リアルタイムプレビュー�構文強調表示�自動補完を備��シンプル��強力�ユーザーインターフェース�組����れ����。

    다양한 내장 수학 함수를 �함하고 사용� 정� 함수, 복소수, 단위 변환과 같� 고급 기능� 지�합니다. �한 결과� 실시간 미리보기, 구문 강조 표시, �� 완성� 갖춘 단순하면서� 강력한 사용� �터페�스를 제공합니다.

    Jame yra įtaisytos daugelis matematinių funkcijų ir jis palaiko tokias išplėstines funkcijas kaip naudotojo apibrėžtos funkcijos, kompleksiniai skai�iai ir vienetų konvertavimai. Tai yra sujungta su paprasta, ta�iau galinga naudotojo sąsaja, kuri pasižymi žaibiškai greita rezultatų peržiūra, sintaksės paryškinimu ir automatiniu užbaigimu.

    Tas ietver daudzas iebūvētas matem�tisk�s funkcijas un atbalsta uzlabotas iespējas, piemēram, lietot�ja definētas funkcijas, kompleksos skaitļus un vienību p�rveidošanu. To papildina vienk�rša, bet jaudīga lietot�ja saskarne ar rezult�tu priekšskatījumu re�llaik�, sintakses izcelšanu un autom�tisko pabeigšanu.

    Ia merangkumi banyak fungsi matematik terbina dalam dan menyokong ciri lanjutan seperti fungsi ditakrif pengguna, nombor kompleks dan penukaran unit. Semua ini digabungkan dengan antara muka pengguna yang ringkas tetapi berkuasa yang menawarkan pratonton hasil serta-merta, penyerlahan sintaks dan pelengkapan automatik.

    Den inneholder mange innebygde matematiske funksjoner og støtter avanserte funksjoner som brukerdefinerte funksjoner, komplekse tall og enhetskonverteringer. Dette kombineres med et enkelt, men kraftig brukergrensesnitt med forhåndsvisning av resultater i sanntid, syntaksutheving og autofullføring.

    Het bevat veel ingebouwde wiskundige functies en ondersteunt geavanceerde functies zoals door de gebruiker gedefinieerde functies, complexe getallen en eenheidsconversies. Dit wordt gecombineerd met een eenvoudige maar krachtige gebruikersinterface met live voorbeeld van resultaten, syntaxisaccentuering en automatisch aanvullen.

    Zawiera wiele wbudowanych funkcji matematycznych i obsługuje zaawansowane możliwości, takie jak funkcje definiowane przez użytkownika, liczby zespolone i konwersje jednostek. Wszystko to połączono z prostym, a zarazem potężnym interfejsem użytkownika oferującym podgląd wyników na bieżąco, podświetlanie składni i autouzupełnianie.

    Inclui muitas funções matemáticas integradas e oferece suporte a recursos avançados como funções definidas pelo usuário, números complexos e conversões de unidades. Isso é combinado com uma interface de usuário simples, porém poderosa, com pré-visualização de resultados em tempo real, realce de sintaxe e autocompletar.Ela inclui muitas funções matemáticas embutidas e suporta características avançadas como funções definidas pelo usuário, números complexos e conversão de unidades. Isso combinado a uma poderosa interface com resultados instantâneos, destaque de sintaxe e auto completação.

    Inclui muitas funções matemáticas integradas e suporta funcionalidades avançadas, como funções definidas pelo utilizador, números complexos e conversões de unidades. Isto é combinado com uma interface de utilizador simples, mas poderosa, com pré-visualização de resultados em tempo real, realce de sintaxe e conclusão automática.

    Include multe funcții matematice integrate și acceptă funcționalități avansate, precum funcții definite de utilizator, numere complexe și conversii de unități. Toate acestea sunt combinate cu o interfață de utilizator simplă, dar puternică, cu previzualizare a rezultatelor în timp real, evidențiere a sintaxei și completare automată.

    Он включает множе�тво в�троенных математиче�ких функций и поддерживает ра�ширенные возможно�ти, такие как пользователь�кие функции, комплек�ные чи�ла и преобразование единиц. В�ё �то �очетает�� � про�тым, но мощным интерфей�ом � мгновенным предпро�мотром результатов, под�веткой �интак�и�а и автодополнением.

    Obsahuje veľa vstavaných matematických funkcií a podporuje pokro�ilé funkcie, ako sú používateľom definované funkcie, komplexné �ísla a prevody jednotiek. To je kombinované s jednoduchým, no výkonným používateľským rozhraním s priebežným náhľadom výsledkov, zvýraznením syntaxe a automatickým dopĺňaním.

    Vklju�uje veliko vgrajenih matemati�nih funkcij in podpira napredne zmožnosti, kot so uporabniško dolo�ene funkcije, kompleksna števila in pretvorbe enot. To je združeno s preprostim, a zmogljivim uporabniškim vmesnikom z sprotnim predogledom rezultatov, poudarjanjem skladnje in samodokon�evanjem.

    Den innehåller många inbyggda matematiska funktioner och stöder avancerade funktioner som användardefinierade funktioner, komplexa tal och enhetsomvandlingar. Detta kombineras med ett enkelt men kraftfullt användargränssnitt med förhandsvisning av resultat i realtid, syntaxmarkering och automatisk komplettering.

    Kinajumuisha vitendaji vingi vya hisabati vilivyojengwa ndani na kinaunga mkono vipengele vya hali ya juu kama vile vitendaji vilivyofafanuliwa na mtumiaji, nambari changamano na ubadilishaji wa vipimo. Haya yote yameunganishwa na kiolesura rahisi lakini chenye nguvu chenye hakikisho la matokeo papo hapo, uangaziaji wa sintaksia na ukamilishaji wa kiotomatiki.

    இத� பல உட�பொதிக�கப�பட�ட கணித செயல�பாட�களை கொண�ட�ள�ளத�; பயனர� வரையற�க�க�ம� செயல�பாட�கள�, கலப�பெண�கள� மற�ற�ம� அலக� மாற�றங�கள� போன�ற மேம�பட�ட வசதிகளைய�ம� ஆதரிக�கிறத�. இதன�டன� உடனடி ம�டிவ� ம�ன�னோட�டம�, தொடரமைப�ப� ம�ன�னிற�த�தல� மற�ற�ம� தானியங�க� நிறைவ� கொண�ட எளிய ஆனால� வலிமையான பயனர� இடைம�கம�ம� இணைக�கப�பட�ட�ள�ளத�.

    ఇంద�లో అనేక అంతర�నిర�మిత గణిత ఫంక�షన�ల� ఉన�నాయి మరియ� వినియోగదార� నిర�వచించిన ఫంక�షన�ల�, సంక�లిష�ట సంఖ�యల�, యూనిట� మార�పిడి వంటి ఆధ�నిక లక�షణాలన� మద�దత� ఇస�త�ంది. ఇవన�నీ తక�షణ ఫలితాల ప�రివ�యూ, సింటాక�స� హైలైటింగ� మరియ� ఆటోకంప�లీషన� కలిగిన సరళమైన కానీ శక�తివంతమైన వినియోగదార� అంతర మ�ఖంతో కలిపి అందించబడతాయి.

    มีฟัง�์ชันคณิตศาสตร์ในตัวจำนวนมา� �ละรองรับความสามารถขั้นสูง เช่น ฟัง�์ชันที่ผู้ใช้�ำหนดเอง จำนวนเชิงซ้อน �ละ�าร�ปลงหน่วย ทั้งหมดนี้รวมอยู่�ับส่วนติดต่อผู้ใช้ที่เรียบง่าย�ต่ทรงพลัง ซึ่งมี�าร�สดงตัวอย่างผลลัพธ์ทันที �ารเน้นไวยา�รณ์ �ละ�ารเติมข้อความอัตโนมัติ

    Birçok yerleşik matematik işlevi içerir ve kullanıcı tanımlı işlevler, karmaşık sayılar ve birim dönüştürmeleri gibi gelişmiş özellikleri destekler. Bunlar, anlık sonuç önizlemesi, sözdizimi vurgulama ve otomatik tamamlama sunan basit ama güçlü bir kullanıcı arayüzü ile birleşir.

    Він мі�тить багато вбудованих математичних функцій і підтримує розширені можливо�ті, такі �к визначені кори�тувачем функції, комплек�ні чи�ла та перетворенн� одиниць. Це поєднано з про�тим, але потужним інтерфей�ом кори�тувача з миттєвим попереднім перегл�дом результатів, під�вічуванн�м �интак�и�у та автодоповненн�м.

    U ko'plab ichki matematik funksiyalarni o'z ichiga oladi va foydalanuvchi tomonidan belgilangan funksiyalar, kompleks sonlar hamda birliklarni o'zgartirish kabi ilg'or imkoniyatlarni qo'llab-quvvatlaydi. Bularning barchasi natijalarni darhol oldindan ko'rish, sintaksisni yoritish va avtomatik to'ldirish kabi funksiyalarga ega sodda, ammo kuchli foydalanuvchi interfeysi bilan uyg'unlashgan.

    Ứng dụng bao gồm nhi�u hàm toán h�c tích hợp và hỗ trợ các tính năng nâng cao như hàm do ngư�i dùng định nghĩa, số phức và chuyển đổi đơn vị. Tất cả được kết hợp với giao diện đơn giản nhưng mạnh mẽ, có xem trước kết quả tức th�i, tô sáng cú pháp và tự động hoàn thành.

    它内置许多数学函数并支�一些高级功能,例如用户定义函数���数字和��转�。这���简��强大的用户界�,包括结果预览�语法高亮和自动完�。

    它包�多種內建數學函數,並支�進階功能,例如使用者自訂函數�複數與單�轉�。這些功能��簡潔但強大的使用者介�,�供�時�果�覽�語法醒目�示與自動補完。

    SpeedCrunch is available for several platforms in a number of languages.

    يتو�ر SpeedCrunch على عدة منصات وبعدد من اللغات.

    SpeedCrunch е наличен за н�колко платформи и на различни езици.

    SpeedCrunch �কাধিক প�ল�যাটফর�মে �বং বিভিন�ন ভাষায় উপলব�ধ।

    SpeedCrunch està disponible per a diverses plataformes en diverses llengües.

    SpeedCrunch je dostupný pro několik platforem v řadě jazyků.

    SpeedCrunch er tilgængelig til flere platforme på en række sprog.

    SpeedCrunch ist für verschiedene Plattformen in einer Anzahl von Sprachen verfügbar.

    Το SpeedCrunch είναι διαθέσιμο για διάφο�ες πλατφό�μες σε πολλές γλώσσες.

    SpeedCrunch is available for several platforms in a number of languages.SpeedCrunch is available for several platforms in a number of languages.

    SpeedCrunch is available for several platforms in a number of languages.

    SpeedCrunch está disponible para varias plataformas en varios idiomas.

    SpeedCrunch está disponible para varias plataformas en varios idiomas.

    SpeedCrunch on saadaval mitmele platvormile mitmes keeles.

    SpeedCrunch hainbat plataformatarako eskuragarri dago, hizkuntza ugaritan.

    SpeedCrunch برای چندین سکوی نرم‌ا�زاری و به چندین زبان در دسترس است.

    SpeedCrunch on saatavilla useille alustoille useilla kielillä.

    SpeedCrunch est disponible sur plusieurs plateformes dans de nombreuses langues.

    SpeedCrunch está dispoñible para varias plataformas e en varios idiomas.

    SpeedCrunch זמין למספר פלטפורמות ובמספר שפות.

    SpeedCrunch कई प�लेटफ़ॉर�म और कई भाषाओं में उपलब�ध है।

    A SpeedCrunch számos platformra elérhető különböző nyelveken.

    SpeedCrunch tersedia untuk beberapa platform dalam sejumlah bahasa.

    SpeedCrunch è disponibile per diverse piattaforme in varie lingue.

    SpeedCrunch �複数�プラットフォーム��多言語�対応�����。

    SpeedCrunch는 여러 플랫��서 다양한 언어로 사용할 수 있습니다.

    SpeedCrunch skai�iuotuvas yra prieinamas kelioms platformoms daugeliu kalbų.

    SpeedCrunch ir pieejams vair�k�m platform�m vair�k�s valod�s.

    SpeedCrunch tersedia untuk beberapa platform dalam pelbagai bahasa.

    SpeedCrunch er tilgjengelig for flere plattformer på en rekke språk.

    SpeedCrunch is beschikbaar voor verschillende platforms in een aantal talen.

    SpeedCrunch jest dostępny na kilka platform w wielu językach.

    O SpeedCrunch está disponível para várias plataformas em diversos idiomas.SpeedCrunch está disponível para diversas plataformas e em várias línguas.

    O SpeedCrunch está disponível para várias plataformas em diversas línguas.

    SpeedCrunch este disponibil pentru mai multe platforme în mai multe limbi.

    SpeedCrunch до�тупен дл� не�кольких платформ в р�де �зыков.

    SpeedCrunch je dostupný pre viaceré platformy v niekoľkých jazykoch.

    SpeedCrunch je na voljo za ve� platform v ve� jezikih.

    SpeedCrunch finns tillgänglig för flera plattformar på ett antal språk.

    SpeedCrunch inapatikana kwa majukwaa kadhaa na katika lugha mbalimbali.

    SpeedCrunch பல தளங�களில�ம� பல மொழிகளில�ம� கிடைக�கிறத�.

    SpeedCrunch అనేక వేదికలపై మరియ� పల� భాషల�లో అంద�బాట�లో ఉంది.

    SpeedCrunch พร้อมใช้งานบนหลาย�พลตฟอร์ม�ละรองรับหลายภาษา

    SpeedCrunch, çeşitli dillerde birden çok platform için kullanılabilir.

    SpeedCrunch до�тупний дл� кількох платформ різними мовами.

    SpeedCrunch bir nechta platformalar uchun ko'plab tillarda mavjud.

    SpeedCrunch có sẵn cho nhi�u n�n tảng với nhi�u ngôn ngữ.

    SpeedCrunch �供多�语言和平�。

    SpeedCrunch �在多個平�上使用,並�供多種語言。

    org.speedcrunch.SpeedCrunch.desktop speedcrunch speedcrunch.desktop ModernToolkit UserDocs https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/advanced-features.png Main window with optional keypad النا�ذة الرئيسية مع لوحة أرقام اختيارية О�новен прозорец � незадължителна цифрова клавиатура �চ�ছিক কীপ�যাডসহ প�রধান উইন�ডো Finestra principal amb teclat numèric opcional Hlavní okno s volitelnou numerickou klávesnicí Hovedvindue med valgfrit numerisk tastatur Hauptfenster mit optionalem Nummernblock Κ��ιο πα�άθυ�ο με π�οαι�ετικό α�ιθμητικό πληκτ�ολόγιο Main window with optional keypad Main window with optional keypad Ventana principal con teclado numérico opcional Ventana principal con teclado numérico opcional Põhiaken valikulise numbriklahvistikuga Leiho nagusia aukerako zenbakizko teklatuarekin پنجرهٔ اصلی با ص�حه‌کلید عددی� اختیاری Pääikkuna valinnaisella numeronäppäimistöllä Fenêtre principale avec pavé numérique optionnel Xanela principal con teclado numérico opcional החלון הר�שי ע� לוח מספרי� �ופציונלי वैकल�पिक कीपैड के साथ म�ख�य विंडो Fő ablak opcionális billentyűzettel Jendela utama dengan keypad opsional Finestra principale con tastierino numerico opzionale オプション�テンキー付�メインウィンドウ 선�� 숫� 키패드가 있는 기본 창 Pagrindinis langas su pasirinktine klaviatūra Galvenais logs ar izvēles ciparu tastatūru Tetingkap utama dengan papan kekunci angka pilihan Hovedvindu med valgfritt numerisk tastatur Hoofdvenster met optioneel numeriek toetsenblok Główne okno z opcjonalnym blokiem numerycznym Janela principal com teclado numérico opcional Janela principal com teclado numérico opcional Fereastra principală cu tastatură numerică opțională Главное окно � дополнительной клавиатурой Hlavné okno s voliteľnou numerickou klávesnicou Glavno okno z izbirno števil�nico Huvudfönster med valfritt numeriskt tangentbord Dirisha kuu lenye kibodi cha namba cha hiari விர�ப�பத� தேர�வ� எண� விசைப�பலகைய�டன� கூடிய ம�தன�மை சாளரம� �చ�ఛిక కీప�యాడ�‌తో ప�రధాన కిటికీ หน้าต่างหลั�พร้อม�ป้นตัวเลขเสริม İsteğe bağlı sayısal tuş takımıyla ana pencere Головне вікно з додатковою цифровою клавіатурою Ixtiyoriy raqamli klaviaturali asosiy oyna Cửa sổ chính với bàn phím số tùy ch�n 主窗�(键盘�用) 主視窗(��用數字�盤) https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/keypad.png The constants list and formula book قائمة الثوابت وكتاب الصيغ Спи�ъкът � кон�танти и �борникът � формули ধ�র�বকের তালিকা ও সূত�রপ�স�তক La llista de constants i el llibre de fórmules Seznam konstant a kniha vzorců Listen over konstanter og formelsamling Die Konstantenliste und das Formelbuch Η λίστα σταθε�ών και το βιβλίο τ�πων The constants list and formula book The constants list and formula book La lista de constantes y el libro de fórmulas La lista de constantes y el libro de fórmulas Konstantide loend ja valemiraamat Konstanteen zerrenda eta formula-liburua �هرست ثابت‌ها و کتاب �رمول‌ها Vakioiden luettelo ja kaavakirja La liste des constantes et le livre de formules A lista de constantes e o libro de fórmulas רשימת הקבועי� וספר הנוסח�ות स�थिरांकों की सूची और सूत�र-प�स�तक Az állandók listája és formula könyv Daftar konstanta dan buku rumus Lista delle costanti e formulario 定数リスト�数�集 �수 목� � 공� 모� Konstantų sąrašas bei formulių knyga Konstanšu saraksts un formulu gr�mata Senarai pemalar dan buku formula Listen over konstanter og formelsamlingen De constantenlijst en het formuleboek Lista stałych i zbiór wzorów A lista de constantes e o livro de fórmulas A lista de constantes e o livro de fórmulas Lista constantelor și cartea de formule Кон�танты и формулы Zoznam konštánt a kniha vzorcov Seznam konstant in knjiga formul Listan över konstanter och formelboken Orodha ya thamani thabiti na kitabu cha fomula மாறிலி பட�டியல�ம� சூத�திரப� ப�த�தகம�ம� స�థిరాంకాల జాబితా మరియ� సూత�రాల ప�స�తకం ราย�ารค่าคงที่�ละหนังสือสูตร Sabitler listesi ve formül kitabı Спи�ок кон�тант і збірник формул Doimiylar ro'yxati va formulalar kitobi Danh sách hằng số và sổ công thức 常�列表和公�书 常數清單與公�手冊 https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/constants+book.png Customizable user interface واجهة مستخدم قابلة للتخصيص Пер�онализируем потребител�ки интерфей� স�বনির�ধারণযোগ�য ব�যবহারকারী ইন�টারফেস Interfície d'usuari personalitzable Přizpůsobitelné uživatelské rozhraní Brugerflade, der kan tilpasses Anpassbare Benutzeroberfläche Π�οσα�μόσιμο πε�ιβάλλον χ�ήστη Customizable user interface Customizable user interface Interfaz de usuario personalizable Interfaz de usuario personalizable Kohandatav kasutajaliides Pertsonaliza daitekeen erabiltzaile-interfazea رابط کاربری قابل س�ارشی‌سازی Mukautettava käyttöliittymä Interface utilisateur personnalisable Interface de usuario personalizable ממשק משתמש הניתן להת�מה �ישית अन�कूलन योग�य उपयोगकर�ता इंटरफ़ेस Testreszabható felhasználói felület Antarmuka pengguna yang dapat disesuaikan Interfaccia utente personalizzabile カスタマイズ�能�ユーザーインターフェース 사용� 지정 가능한 사용� �터페�스 Tinkinama naudotojo sąsaja Piel�gojama lietot�ja saskarne Antara muka pengguna yang boleh disesuaikan Tilpassbart brukergrensesnitt Aanpasbare gebruikersinterface Konfigurowalny interfejs użytkownika Interface de usuário personalizável Interface de utilizador personalizável Interfață de utilizator personalizabilă �а�траиваемый пользователь�кий интерфей� Prispôsobiteľné používateľské rozhranie Prilagodljiv uporabniški vmesnik Anpassningsbart användargränssnitt Kiolesura cha mtumiaji kinachoweza kubadilishwa தனிப�பயனாக�கக�கூடிய பயனர� இடைம�கம� అన�కూలీకరించదగిన వినియోగదార� అంతర మ�ఖం ส่วนติดต่อผู้ใช้ที่ปรับ�ต่งได้ Özelleştirilebilir kullanıcı arayüzü �алаштовуваний інтерфей� кори�тувача Moslashtiriladigan foydalanuvchi interfeysi Giao diện ngư�i dùng có thể tùy biến �定制用户界� �自訂的使用者介� https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/ui-customization.png The built-in user manual دليل المستخدم المدمج Вграденото ръковод�тво за потребител� অন�তর�নির�মিত ব�যবহারকারী নির�দেশিকা El manual d'usuari integrat Vestavěná uživatelská příru�ka Den indbyggede brugervejledning Das integrierte Benutzerhandbuch Το ενσωματωμένο εγχει�ίδιο χ�ήστη The built-in user manual The built-in user manual El manual de usuario integrado El manual de usuario integrado Sisseehitatud kasutusjuhend Barneko erabiltzaile-eskuliburua راهنمای کاربر� داخلی Sisäänrakennettu käyttöopas Le manuel d'utilisation intégré O manual de usuario integrado מדריך המשתמש המובנה अंतर�निहित उपयोगकर�ता प�स�तिका Beépített kézikönyv Panduan pengguna bawaan Manuale integrato 内蔵ユーザーマニュアル 내장 사용� 설명서 Įtaisytas naudotojo vadovas Iebūvēt� lietot�ja rokasgr�mata Manual pengguna terbina dalam Den innebygde brukermanualen De ingebouwde gebruikershandleiding Wbudowany podręcznik użytkownika O manual do usuário integrado O manual do utilizador integrado Manualul de utilizare integrat В�троенное руковод�тво пользовател� Vstavaná používateľská príru�ka Vgrajen uporabniški priro�nik Den inbyggda användarhandboken Mwongozo wa mtumiaji uliojengewa ndani உட�பொதிக�கப�பட�ட பயனர� கையேட� అంతర�నిర�మిత వినియోగదార� మార�గదర�శిని คู่มือผู้ใช้ในตัว Yerleşik kullanıcı kılavuzu Вбудований по�ібник кори�тувача Ichki foydalanuvchi qo'llanmasi Hướng dẫn sử dụng tích hợp 内置用户手册 內建使用者手冊 https://heldercorreia.bitbucket.io/speedcrunch/_static/appdata-screenshots/0.12/manual.png https://speedcrunch.org https://speedcrunch.org/issues.html https://speedcrunch.org/contents.html ar bg bn ca cs da de el en_GB en_US es es_ES et eu fa fi fr gl he hi hu id it ja ko lt lv ms nb nl pl pt_BR pt_PT ro ru sk sl sv sw ta te th tr uk uz_Latn vi zh_CN zh_TW
    heldercorreia-speedcrunch-e7ca37f/pkg/winsetup.iss000066400000000000000000000062541526573132500225230ustar00rootroot00000000000000#define APPTITLE "SpeedCrunch" #define SPEEDCRUNCHEXE "..\src\release\" + APPTITLE + ".exe" #define NUMERICVERSION GetFileVersion(SPEEDCRUNCHEXE) #define VERSION "1.0" ; GetFileVersionString(SPEEDCRUNCHEXE) #define URL "http://speedcrunch.org" #define COPYRIGHT "2004-2013 " + URL [Setup] AllowNoIcons=yes AppName={#APPTITLE} AppPublisher={#APPTITLE} AppPublisherURL={#URL} AppSupportURL={#URL} AppUpdatesURL={#URL} AppVerName={#APPTITLE} {#VERSION} Compression=lzma/ultra DefaultDirName={pf}\{#APPTITLE} DefaultGroupName={#APPTITLE} DisableProgramGroupPage=true LicenseFile=COPYING.rtf InternalCompressLevel=ultra OutputBaseFilename={#APPTITLE}-{#VERSION} OutputDir=. ShowLanguageDialog=no SolidCompression=yes VersionInfoCompany={#URL} VersionInfoCopyright=Copyright (C) {#COPYRIGHT} VersionInfoDescription=Keyboard-oriented high-precision scientific calculator VersionInfoTextVersion={#VERSION} VersionInfoVersion={#NUMERICVERSION} WizardImageFile=compiler:WizModernImage-IS.bmp WizardSmallImageFile=compiler:WizModernSmallImage-IS.bmp [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl" Name: "catalan"; MessagesFile: "compiler:Languages\Catalan.isl" Name: "czech"; MessagesFile: "compiler:Languages\Czech.isl" Name: "danish"; MessagesFile: "compiler:Languages\Danish.isl" Name: "dutch"; MessagesFile: "compiler:Languages\Dutch.isl" Name: "finnish"; MessagesFile: "compiler:Languages\Finnish.isl" Name: "french"; MessagesFile: "compiler:Languages\French.isl" Name: "german"; MessagesFile: "compiler:Languages\German.isl" Name: "greek"; MessagesFile: "compiler:Languages\Greek.isl" Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl" Name: "hungarian"; MessagesFile: "compiler:Languages\Hungarian.isl" Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl" Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl" Name: "norwegian"; MessagesFile: "compiler:Languages\Norwegian.isl" Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl" Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl" Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl" Name: "slovenian"; MessagesFile: "compiler:Languages\Slovenian.isl" Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" Name: "ukrainian"; MessagesFile: "compiler:Languages\Ukrainian.isl" [Tasks] Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked [Files] Source: {#SPEEDCRUNCHEXE}; DestDir: "{app}"; Flags: ignoreversion [Icons] Name: "{group}\{#APPTITLE}"; Filename: "{app}\{#APPTITLE}.exe" Name: "{group}\{cm:UninstallProgram,{#APPTITLE}}"; Filename: "{uninstallexe}" Name: "{userdesktop}\{#APPTITLE}"; Filename: "{app}\{#APPTITLE}.exe"; Tasks: desktopicon Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#APPTITLE}"; Filename: "{app}\{#APPTITLE}.exe"; Tasks: quicklaunchicon [Run] Filename: "{app}\{#APPTITLE}.exe"; Description: "{cm:LaunchProgram,{#APPTITLE}}"; Flags: nowait postinstall skipifsilent heldercorreia-speedcrunch-e7ca37f/src/000077500000000000000000000000001526573132500201245ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/CMakeLists.txt000066400000000000000000000346471526573132500227020ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.16) include("${CMAKE_CURRENT_LIST_DIR}/cmake/BuildVariants.cmake") include("${CMAKE_CURRENT_LIST_DIR}/cmake/MacOSDeploymentTarget.cmake") if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) # Keep direct src builds using the version declared at the repository root. set(speedcrunch_root_cmake "${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt") set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${speedcrunch_root_cmake}") file(STRINGS "${speedcrunch_root_cmake}" speedcrunch_project_declaration REGEX "^project\\(speedcrunch VERSION [0-9.]+\\)") string(REGEX MATCH "[0-9]+(\\.[0-9]+)*" speedcrunch_VERSION "${speedcrunch_project_declaration}") if(speedcrunch_VERSION STREQUAL "") message(FATAL_ERROR "Cannot read the SpeedCrunch version from the root CMakeLists.txt") endif() endif() project(speedcrunch VERSION "${speedcrunch_VERSION}") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) message("Using C++${CMAKE_CXX_STANDARD}") set(CMAKE_C_STANDARD 17) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) message("Using C${CMAKE_C_STANDARD}") if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type (Debug, Release, RelWithDebInfo, MinSizeRel)" FORCE) endif() message("Build type: ${CMAKE_BUILD_TYPE}") option(BUILD_TESTING "Build the test executables and enable CTest" OFF) option(ENABLE_UPDATE_CHECKS "Enable launch-time and manual update checks" OFF) option(ENABLE_STARTUP_DIAGNOSTICS "Record startup timings and detailed appearance diagnostics" OFF) option(STRIP_BINARY "Remove debug symbols from the application binary" OFF) if(ENABLE_UPDATE_CHECKS) add_compile_definitions(SPEEDCRUNCH_ENABLE_UPDATE_CHECKS) endif() find_package(Qt6 6.4 REQUIRED COMPONENTS Core Widgets Help Network LinguistTools) message(STATUS "Found Qt version: ${Qt6_VERSION}") if(BUILD_TESTING) find_package(Qt6 COMPONENTS Test REQUIRED) endif() if (MSVC) add_definitions(-D_USE_MATH_DEFINES) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) # MSVC's /Wall also enables normally disabled padding and inlining reports. add_compile_options(/W4) if(CMAKE_GENERATOR MATCHES "^Visual Studio") # MSBuild parallelizes projects. /MP also parallelizes files within each project. add_compile_options( "$<$:/MP>" "$<$:/MP>" ) endif() else() add_compile_options(-Wno-shift-negative-value -Wall -pedantic) endif() if(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() # Windows resources require four numeric version components. set(speedcrunch_VERSION_RC) foreach(component IN ITEMS MAJOR MINOR PATCH TWEAK) set(version_component "${speedcrunch_VERSION_${component}}") if(version_component STREQUAL "") set(version_component 0) endif() list(APPEND speedcrunch_VERSION_RC "${version_component}") endforeach() string(REPLACE ";" "," speedcrunch_VERSION_RC "${speedcrunch_VERSION_RC}") configure_file(resources/speedcrunch.rc.in speedcrunch.rc @ONLY) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_COLOR_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE OFF) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_MACOSX_RPATH ON) ADD_DEFINITIONS("-DSPEEDCRUNCH_VERSION=\"${speedcrunch_VERSION}\"") ADD_DEFINITIONS(-DQT_USE_QSTRINGBUILDER) include(SourceFiles.cmake) if(BUILD_TESTING AND CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") set_source_files_properties(tests/testfloatnum.c PROPERTIES COMPILE_OPTIONS "-Wno-strict-prototypes") endif() if(APPLE) set(APP_ICON_FILE speedcrunch.icns) set(APP_ICON "${CMAKE_CURRENT_SOURCE_DIR}/resources/${APP_ICON_FILE}") set(APPLICATION_NAME SpeedCrunch) set(MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Info.plist.in") set(MACOSX_BUNDLE_ICON_FILE ${APP_ICON_FILE}) set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${speedcrunch_VERSION}) set(MACOSX_BUNDLE_BUNDLE_VERSION ${speedcrunch_VERSION}) set(MACOSX_BUNDLE_LONG_VERSION_STRING Version ${speedcrunch_VERSION}) set_source_files_properties(${APP_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") elseif(HAIKU) set(APPLICATION_NAME SpeedCrunch) else() set(APPLICATION_NAME speedcrunch) endif() if(WIN32) set(WIN32_RES_FILE ${CMAKE_CURRENT_BINARY_DIR}/speedcrunch.rc.obj) if(MINGW) add_custom_command(OUTPUT ${WIN32_RES_FILE} COMMAND windres.exe ${CMAKE_CURRENT_BINARY_DIR}/speedcrunch.rc ${WIN32_RES_FILE} DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/speedcrunch.rc" "${CMAKE_CURRENT_SOURCE_DIR}/resources/speedcrunch.ico" VERBATIM) else() add_custom_command(OUTPUT ${WIN32_RES_FILE} COMMAND rc.exe /fo ${WIN32_RES_FILE} ${CMAKE_CURRENT_BINARY_DIR}/speedcrunch.rc DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/speedcrunch.rc" "${CMAKE_CURRENT_SOURCE_DIR}/resources/speedcrunch.ico" VERBATIM) endif() endif() # Embedded manual set(HTML_DOCS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../doc/build_html_embedded" CACHE PATH "Path to the HTML manual. Defaults to the bundled prebuilt copy.") set(speedcrunch_RESOURCES ${speedcrunch_RESOURCES} ${HTML_DOCS_DIR}/manual.qrc) if(WIN32) add_executable(${APPLICATION_NAME} WIN32 ${speedcrunch_SOURCES} ${speedcrunch_RESOURCES} ${WIN32_RES_FILE}) elseif(APPLE) add_executable(${APPLICATION_NAME} MACOSX_BUNDLE ${speedcrunch_SOURCES} ${speedcrunch_RESOURCES} ${APP_ICON}) set_target_properties(${APPLICATION_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${MACOSX_BUNDLE_INFO_PLIST}") else() add_executable(${APPLICATION_NAME} ${speedcrunch_SOURCES} ${speedcrunch_RESOURCES}) endif() # lupdate needs an explicit source include path to resolve translation contexts. target_include_directories(${APPLICATION_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") if(STRIP_BINARY) if(APPLE) if(NOT CMAKE_STRIP) message(FATAL_ERROR "The macOS toolchain must provide CMAKE_STRIP when STRIP_BINARY is ON") endif() # Native strip preserves the symbols needed by the dynamic loader. add_custom_command(TARGET ${APPLICATION_NAME} POST_BUILD COMMAND "${CMAKE_STRIP}" "$" VERBATIM ) elseif(MSVC) target_link_options(${APPLICATION_NAME} PRIVATE /DEBUG:NONE) else() target_link_options(${APPLICATION_NAME} PRIVATE "LINKER:-s") endif() endif() file(GLOB speedcrunch_TS_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/resources/locale/*.ts") qt_add_translations(${APPLICATION_NAME} TS_FILES ${speedcrunch_TS_SOURCES} LUPDATE_OPTIONS -no-obsolete QM_FILES_OUTPUT_VARIABLE speedcrunch_QM_FILES ) set(speedcrunch_TRANSLATION_TARGETS ${APPLICATION_NAME}) target_compile_definitions(${APPLICATION_NAME} PRIVATE $<$:SPEEDCRUNCH_ENABLE_STARTUP_DIAGNOSTICS> $<$>:QT_NO_DEBUG_OUTPUT> $<$>:QT_NO_INFO_OUTPUT> $<$>:QT_NO_WARNING_OUTPUT> ) add_custom_target(confclean COMMAND rm -rf Makefile CMakeFiles/ CMakeCache.txt cmake_install.cmake DartTestfile.txt install_manifest.txt WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") set(QT_LIBRARIES Qt6::Widgets Qt6::Help Qt6::Network Qt6::Core) target_link_libraries(${APPLICATION_NAME} PRIVATE ${QT_LIBRARIES}) if(BUILD_TESTING) enable_testing() qt_add_executable(testtranslations tests/testtranslations.cpp) target_link_libraries(testtranslations PRIVATE Qt6::Test) target_compile_definitions(testtranslations PRIVATE SPEEDCRUNCH_TS_DIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/resources/locale") add_test(NAME testtranslations COMMAND testtranslations) list(APPEND speedcrunch_TRANSLATION_TARGETS testtranslations) add_executable(testhmath ${testhmath_SOURCES}) target_link_libraries(testhmath ${QT_LIBRARIES}) add_test(NAME testhmath COMMAND testhmath) add_executable(testevaluator ${testevaluator_SOURCES} ${testevaluator_HEADERS_MOC}) target_link_libraries(testevaluator ${QT_LIBRARIES}) add_test(NAME testevaluator COMMAND testevaluator) add_executable(testfloatnum ${testfloatnum_SOURCES}) set_property(TARGET testfloatnum APPEND PROPERTY COMPILE_DEFINITIONS _FLOATNUMTEST) add_test(NAME testfloatnum COMMAND testfloatnum) add_executable(testcmath ${testcmath_SOURCES}) target_link_libraries(testcmath ${QT_LIBRARIES}) add_test(NAME testcmath COMMAND testcmath) add_executable(testdmath ${testdmath_SOURCES}) target_link_libraries(testdmath ${QT_LIBRARIES}) add_test(NAME testdmath COMMAND testdmath) add_executable(testserial ${testserial_SOURCES}) target_link_libraries(testserial ${QT_LIBRARIES}) add_test(NAME testserial COMMAND testserial) add_executable(testeditorui ${testeditorui_SOURCES}) target_link_libraries(testeditorui ${QT_LIBRARIES} Qt6::Test) add_test(NAME testeditorui COMMAND testeditorui) add_executable(testoklch ${testoklch_SOURCES}) target_link_libraries(testoklch ${QT_LIBRARIES} Qt6::Test) add_test(NAME testoklch COMMAND testoklch) add_executable(testdocksui ${testdocksui_SOURCES}) target_link_libraries(testdocksui ${QT_LIBRARIES} Qt6::Test) add_test(NAME testdocksui COMMAND testdocksui) # Compile the application code and resources once for the component suites. # An object library also keeps the Qt resource objects in every executable. add_library(mainwindowuitest OBJECT ${mainwindowuitest_SOURCES}) target_link_libraries(mainwindowuitest PUBLIC ${QT_LIBRARIES} Qt6::Test) target_compile_definitions(mainwindowuitest PUBLIC SPEEDCRUNCH_UI_TEST SPEEDCRUNCH_ENABLE_STARTUP_DIAGNOSTICS ) # Start the longer suites first on a build without CTest timing history. set(mainwindow_ui_tests testfocusui testdockappearanceui testdocklayoutui testprivatesessionsui testthemesui testkeypadui testeditorappearanceui testsettingsui teststatusbarui testmenusui testbitfieldui testsessionsui testdisplayui ) foreach(ui_test IN LISTS mainwindow_ui_tests) add_executable(${ui_test} tests/${ui_test}.cpp) target_link_libraries(${ui_test} PRIVATE mainwindowuitest) add_test(NAME ${ui_test} COMMAND ${ui_test}) set_tests_properties(${ui_test} PROPERTIES LABELS "ui") endforeach() foreach(ui_test IN ITEMS testeditorui testdocksui) target_compile_definitions(${ui_test} PRIVATE SPEEDCRUNCH_UI_TEST) set_tests_properties(${ui_test} PROPERTIES LABELS "ui") endforeach() if(WIN32) get_property(speedcrunch_tests DIRECTORY PROPERTY TESTS) if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.22") set_property(TEST ${speedcrunch_tests} APPEND PROPERTY ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") else() # Older CTest versions require the full PATH as one escaped list entry. string(REPLACE ";" "\\;" speedcrunch_test_path "$ENV{PATH}") set_property(TEST ${speedcrunch_tests} APPEND PROPERTY ENVIRONMENT "PATH=$\\;${speedcrunch_test_path}") endif() endif() endif() # Embed the same generated catalogs in the application and test executables. foreach(translation_target IN LISTS speedcrunch_TRANSLATION_TARGETS) qt_add_resources(${translation_target} "${translation_target}_translations" PREFIX "/locale" BASE "${CMAKE_CURRENT_BINARY_DIR}" FILES ${speedcrunch_QM_FILES} ) endforeach() include_directories("${CMAKE_CURRENT_BINARY_DIR}" thirdparty core gui math) ################################# INSTALL ###################################### if(UNIX AND NOT APPLE AND NOT HAIKU) include(GNUInstallDirs) set(BIN_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}") set(DOC_INSTALL_DIR "${CMAKE_INSTALL_DOCDIR}") set(MENU_DIR "${CMAKE_INSTALL_DATAROOTDIR}/applications") set(APP_DATA_DIR "${CMAKE_INSTALL_DATAROOTDIR}/metainfo") set(ICON_DIR "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor") elseif(APPLE) set(BIN_INSTALL_DIR ".") set(DOC_INSTALL_DIR ${APPLICATION_NAME}.app/Contents/Resources) elseif(HAIKU) set(BIN_INSTALL_DIR "apps") set(DOC_INSTALL_DIR "documentation/SpeedCrunch") else() set(BIN_INSTALL_DIR ".") set(DOC_INSTALL_DIR ".") endif() option(PORTABLE_SPEEDCRUNCH "Enable to build in portable mode" OFF) if(PORTABLE_SPEEDCRUNCH) add_definitions(-DSPEEDCRUNCH_PORTABLE) endif(PORTABLE_SPEEDCRUNCH) install(TARGETS ${APPLICATION_NAME} DESTINATION "${BIN_INSTALL_DIR}") if(UNIX AND NOT APPLE AND NOT HAIKU) install(FILES ../pkg/org.speedcrunch.SpeedCrunch.desktop DESTINATION "${MENU_DIR}") install(FILES ../gfx/speedcrunch.svg DESTINATION "${ICON_DIR}/scalable/apps" RENAME org.speedcrunch.SpeedCrunch.svg) foreach(ICON_SIZE IN ITEMS 16 22 24 32 48 64 128 256) install(FILES "../gfx/icons/${ICON_SIZE}x${ICON_SIZE}/org.speedcrunch.SpeedCrunch.png" DESTINATION "${ICON_DIR}/${ICON_SIZE}x${ICON_SIZE}/apps") endforeach() install(FILES ../pkg/org.speedcrunch.SpeedCrunch.metainfo.xml DESTINATION "${APP_DATA_DIR}") endif() if(WIN32) include(QtWin32Deploy) endif() include(InstallLicenses) if(WIN32) qtwin32_deploy_modules(${BIN_INSTALL_DIR} qtwin32_Qt6Widgets qtwin32_Qt6Help qtwin32_Qt6Network) qtwin32_deploy_default_qt_conf(${BIN_INSTALL_DIR}) elseif(APPLE) include(MacdeployQt) macdeployqt(${APPLICATION_NAME}.app ${APPLICATION_NAME}) endif(WIN32) set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION ${BIN_INSTALL_DIR}) include(InstallRequiredSystemLibraries) set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE) include(SpeedCrunchCPack.cmake) ################################ UNINSTALL ##################################### configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") heldercorreia-speedcrunch-e7ca37f/src/SourceFiles.cmake000066400000000000000000000274041526573132500233600ustar00rootroot00000000000000SET(speedcrunch_RESOURCES resources/speedcrunch.qrc ) set(speedcrunch_HEADERS core/anglemode.h core/book.h core/complexform.h core/constants.h core/colorscheme.h core/evaluator.h core/functions.h core/manualserver.h core/session.h core/errors.h core/numberformatter.h core/pageserver.h core/settings.h core/opcode.h core/sessionhistory.h core/sessionjsonkeys.h core/symbolicnumberformat.h core/userdefinitions.h core/variable.h core/userfunction.h core/userunit.h gui/aboutbox.h gui/diagnosticsdialog.h gui/diagnosticapplication.h core/startupdiagnostics.h gui/startupappearance.h gui/bitfieldwidget.h gui/bookdock.h gui/constantbrowserutils.h gui/constantswidget.h gui/customkeypaddialog.h gui/displayformatutils.h gui/dockcomboboxchevron.h gui/dockliststyle.h gui/dockwidget.h gui/editor.h gui/functiontooltiputils.h gui/functionswidget.h gui/historywidget.h gui/genericdock.h gui/gtkmenupalette.h gui/keypad.h gui/lineeditstyleutils.h gui/mainwindow.h gui/menustyleutils.h gui/manualwindow.h gui/numberformatdialog.h gui/notationandprecisiondialog.h gui/oklchutils.h gui/resultdisplay.h gui/tooltipstyleutils.h gui/variablelistwidget.h gui/userfunctionlistwidget.h gui/userunitlistwidget.h gui/syntaxhighlighter.h gui/themedlineedit.h gui/uiconfig.h math/floatnum/floatcommon.h math/floatnum/floatconfig.h math/floatnum/floatconst.h math/floatnum/floatconvert.h math/floatnum/floaterf.h math/floatnum/floatexp.h math/floatnum/floatgamma.h math/floatnum/floathmath.h math/floatnum/floatincgamma.h math/floatnum/floatio.h math/floatnum/floatipower.h math/floatnum/floatlog.h math/floatnum/floatlogic.h math/floatnum/floatlong.h math/floatnum/floatnum.h math/floatnum/floatpower.h math/floatnum/floatseries.h math/floatnum/floattrig.h math/hmath.h math/number.h math/rational.h math/quantity.h core/units.h core/unitdisplayformat.h ) set(speedcrunch_SOURCES main.cpp core/book.cpp core/constants.cpp core/colorscheme.cpp core/evaluator.cpp core/functions.cpp core/mathdsl.cpp core/manualserver.cpp core/numberformatter.cpp core/pageserver.cpp core/settings.cpp core/session.cpp core/sessionhistory.cpp core/userdefinitions.cpp core/variable.cpp core/userfunction.cpp core/userunit.cpp core/opcode.cpp gui/aboutbox.cpp gui/diagnosticsdialog.cpp gui/bitfieldwidget.cpp gui/bookdock.cpp gui/constantswidget.cpp gui/customkeypaddialog.cpp gui/displayformatutils.cpp gui/dockcomboboxchevron.cpp gui/dockliststyle.cpp gui/dockwidget.h gui/editor.cpp gui/functiontooltiputils.cpp gui/functionswidget.cpp gui/historywidget.cpp # added here explicitly so it shows up in QtCreator gui/genericdock.h gui/keypad.cpp gui/mainwindow.cpp gui/menustyleutils.cpp gui/manualwindow.cpp gui/numberformatdialog.cpp gui/notationandprecisiondialog.cpp gui/oklchutils.cpp gui/resultdisplay.cpp gui/splittertreeutils.cpp gui/syntaxhighlighter.cpp gui/themedlineedit.cpp gui/tooltipstyleutils.cpp gui/variablelistwidget.cpp gui/userfunctionlistwidget.cpp gui/userunitlistwidget.cpp math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/floatnum/floatincgamma.c math/hmath.cpp math/number.c math/cmath.cpp math/cnumberparser.cpp math/rational.cpp math/quantity.cpp core/units.cpp core/unitdisplayformat.cpp ) set(testhmath_SOURCES math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/hmath.cpp math/number.c math/rational.cpp math/quantity.cpp math/cmath.cpp core/units.cpp core/unitdisplayformat.cpp math/cnumberparser.cpp tests/testhmath.cpp ) set(testevaluator_HEADERS core/evaluator.h core/functions.h gui/resultdisplay.h gui/syntaxhighlighter.h gui/uiconfig.h ) set(testevaluator_SOURCES gui/dockcomboboxchevron.cpp gui/menustyleutils.cpp core/constants.cpp core/colorscheme.cpp core/evaluator.cpp core/functions.cpp core/mathdsl.cpp core/settings.cpp core/userfunction.cpp core/userunit.cpp core/session.cpp core/sessionhistory.cpp core/variable.cpp core/numberformatter.cpp gui/displayformatutils.cpp gui/dockliststyle.cpp gui/functiontooltiputils.cpp gui/oklchutils.cpp gui/resultdisplay.cpp gui/splittertreeutils.cpp gui/syntaxhighlighter.cpp gui/tooltipstyleutils.cpp math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/hmath.cpp math/number.c math/cmath.cpp math/cnumberparser.cpp math/rational.cpp math/quantity.cpp core/units.cpp core/unitdisplayformat.cpp tests/testevaluator.cpp ) set(testfloatnum_SOURCES math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/number.c tests/testfloatnum.c ) set(testcmath_SOURCES math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/hmath.cpp math/number.c math/cmath.cpp math/cnumberparser.cpp math/rational.cpp math/quantity.cpp core/units.cpp core/unitdisplayformat.cpp tests/testcmath.cpp ) set(testdmath_SOURCES math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/hmath.cpp math/number.c math/cmath.cpp math/cnumberparser.cpp math/rational.cpp math/quantity.cpp core/units.cpp core/unitdisplayformat.cpp tests/testdmath.cpp ) set(testeditorui_SOURCES gui/dockliststyle.cpp gui/themedlineedit.cpp gui/dockcomboboxchevron.cpp gui/menustyleutils.cpp core/constants.cpp core/colorscheme.cpp core/evaluator.cpp core/functions.cpp core/mathdsl.cpp core/settings.cpp core/userfunction.cpp core/userunit.cpp core/session.cpp core/sessionhistory.cpp core/variable.cpp core/numberformatter.cpp gui/displayformatutils.cpp gui/functiontooltiputils.cpp gui/oklchutils.cpp gui/resultdisplay.cpp gui/syntaxhighlighter.cpp gui/editor.cpp gui/tooltipstyleutils.cpp math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/hmath.cpp math/number.c math/cmath.cpp math/cnumberparser.cpp math/rational.cpp math/quantity.cpp core/units.cpp core/unitdisplayformat.cpp tests/testeditorui.cpp ) set(testoklch_SOURCES gui/oklchutils.cpp tests/testoklch.cpp ) set(testdocksui_SOURCES gui/dockcomboboxchevron.cpp gui/menustyleutils.cpp core/constants.cpp core/colorscheme.cpp core/evaluator.cpp core/functions.cpp core/mathdsl.cpp core/settings.cpp core/userfunction.cpp core/userunit.cpp core/session.cpp core/sessionhistory.cpp core/variable.cpp core/numberformatter.cpp gui/displayformatutils.cpp gui/constantswidget.cpp gui/dockliststyle.cpp gui/functiontooltiputils.cpp gui/oklchutils.cpp gui/resultdisplay.cpp gui/splittertreeutils.cpp gui/syntaxhighlighter.cpp gui/editor.cpp gui/themedlineedit.cpp gui/tooltipstyleutils.cpp gui/variablelistwidget.cpp gui/userunitlistwidget.cpp math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/hmath.cpp math/number.c math/cmath.cpp math/cnumberparser.cpp math/rational.cpp math/quantity.cpp core/units.cpp core/unitdisplayformat.cpp tests/testdocksui.cpp ) set(mainwindowuitest_SOURCES gui/menustyleutils.cpp core/book.cpp core/constants.cpp core/colorscheme.cpp core/evaluator.cpp core/functions.cpp core/manualserver.cpp core/mathdsl.cpp core/pageserver.cpp core/settings.cpp core/userfunction.cpp core/userunit.cpp core/userdefinitions.cpp core/session.cpp core/sessionhistory.cpp core/variable.cpp core/numberformatter.cpp gui/aboutbox.cpp gui/diagnosticsdialog.cpp gui/bitfieldwidget.cpp gui/bookdock.cpp gui/constantswidget.cpp gui/customkeypaddialog.cpp gui/displayformatutils.cpp gui/dockliststyle.cpp gui/functiontooltiputils.cpp gui/functionswidget.cpp gui/historywidget.cpp gui/keypad.cpp gui/dockcomboboxchevron.cpp gui/mainwindow.cpp gui/manualwindow.cpp gui/numberformatdialog.cpp gui/notationandprecisiondialog.cpp gui/oklchutils.cpp gui/resultdisplay.cpp gui/splittertreeutils.cpp gui/syntaxhighlighter.cpp gui/editor.cpp gui/themedlineedit.cpp gui/tooltipstyleutils.cpp gui/userfunctionlistwidget.cpp gui/variablelistwidget.cpp gui/userunitlistwidget.cpp math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/hmath.cpp math/number.c math/cmath.cpp math/cnumberparser.cpp math/rational.cpp math/quantity.cpp core/units.cpp core/unitdisplayformat.cpp resources/speedcrunch.qrc tests/mainwindowtesthelpers.cpp ) if(ENABLE_UPDATE_CHECKS) list(APPEND speedcrunch_HEADERS gui/versioncheck.h) list(APPEND speedcrunch_SOURCES gui/versioncheck.cpp) list(APPEND mainwindowuitest_SOURCES gui/versioncheck.cpp) endif() set(testserial_SOURCES core/numberformatter.cpp core/settings.cpp math/floatnum/floatcommon.c math/floatnum/floatconst.c math/floatnum/floatconvert.c math/floatnum/floaterf.c math/floatnum/floatexp.c math/floatnum/floatgamma.c math/floatnum/floathmath.c math/floatnum/floatio.c math/floatnum/floatipower.c math/floatnum/floatlog.c math/floatnum/floatlogic.c math/floatnum/floatlong.c math/floatnum/floatnum.c math/floatnum/floatpower.c math/floatnum/floatseries.c math/floatnum/floattrig.c math/hmath.cpp math/number.c math/cmath.cpp math/cnumberparser.cpp math/rational.cpp math/quantity.cpp core/units.cpp core/unitdisplayformat.cpp tests/testserial.cpp ) heldercorreia-speedcrunch-e7ca37f/src/SpeedCrunchCPack.cmake000066400000000000000000000102661526573132500242400ustar00rootroot00000000000000if(APPLE) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install") if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) # The parent install rules need the same prefix as the app bundle. set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE) endif() endif() set(CPACK_PACKAGE_NAME SpeedCrunch) set(CPACK_PACKAGE_VENDOR SpeedCrunch) set(CPACK_PACKAGE_VERSION ${speedcrunch_VERSION}) set(CPACK_PACKAGE_INSTALL_DIRECTORY SpeedCrunch) set(CPACK_PACKAGE_EXECUTABLES ${APPLICATION_NAME} SpeedCrunch) if(WIN32) if(NOT CPACK_GENERATOR) if(PORTABLE_SPEEDCRUNCH) set(CPACK_GENERATOR ZIP) else(PORTABLE_SPEEDCRUNCH) set(CPACK_GENERATOR NSIS) endif(PORTABLE_SPEEDCRUNCH) endif(NOT CPACK_GENERATOR) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/../pkg/COPYING.rtf") set(CPACK_NSIS_EXECUTABLES_DIRECTORY ${BIN_INSTALL_DIR}) set(CPACK_NSIS_INSTALLED_ICON_NAME "${BIN_INSTALL_DIR}\\\\${APPLICATION_NAME}.exe,0") set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\resources\\\\speedcrunch.ico") set(CPACK_NSIS_HELP_LINK "http://groups.google.com/group/speedcrunch") set(CPACK_NSIS_URL_INFO_ABOUT "http://speedcrunch.org") set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL true) set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "WriteRegStr SHCTX 'Software\\\\RegisteredApplications' 'SpeedCrunch' 'Software\\\\SpeedCrunch\\\\Capabilities' WriteRegStr SHCTX 'Software\\\\SpeedCrunch\\\\Capabilities' 'ApplicationDescription' 'SpeedCrunch is a high-precision scientific calculator' WriteRegStr SHCTX 'Software\\\\SpeedCrunch\\\\Capabilities' 'ApplicationName' 'SpeedCrunch' WriteRegStr SHCTX 'Software\\\\SpeedCrunch\\\\Capabilities\\\\UrlAssociations' 'calculator' 'SpeedCrunch.Url.calculator' WriteRegStr SHCTX 'Software\\\\Classes\\\\SpeedCrunch.Url.calculator' '' 'SpeedCrunch' WriteRegStr SHCTX 'Software\\\\Classes\\\\SpeedCrunch.Url.calculator' 'FriendlyTypeName' 'SpeedCrunch' WriteRegStr SHCTX 'Software\\\\Classes\\\\SpeedCrunch.Url.calculator\\\\shell\\\\open\\\\command' '' '\\\"$INSTDIR\\\\${BIN_INSTALL_DIR}\\\\${APPLICATION_NAME}.exe\\\"' WriteRegStr SHCTX 'Software\\\\Classes\\\\SpeedCrunch.Url.calculator\\\\Application' 'ApplicationCompany' 'SpeedCrunch' WriteRegStr SHCTX 'Software\\\\Classes\\\\Applications\\\\${APPLICATION_NAME}.exe' 'FriendlyAppName' 'SpeedCrunch' ") set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "DeleteRegValue SHCTX 'Software\\\\RegisteredApplications' 'SpeedCrunch' DeleteRegKey SHCTX 'Software\\\\SpeedCrunch' DeleteRegKey SHCTX 'Software\\\\Classes\\\\SpeedCrunch.Url.calculator' DeleteRegKey SHCTX 'Software\\\\Classes\\\\Applications\\\\${APPLICATION_NAME}.exe' ") if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) set(CPACK_SYSTEM_NAME "windows-x64") # When building a 64-bit installer, we add a check to make it fail on 32-bit systems # because CPack doesn't do that by itself. Using this variable is probably a bit of a hack # though. set(CPACK_NSIS_DEFINES "!include 'x64.nsh' Function x64Check \\\${IfNot} \\\${RunningX64} MessageBox MB_OK|MB_ICONEXCLAMATION 'This installer can only be run on 64-bit Windows.' Quit \\\${EndIf} FunctionEnd Page custom x64Check ") else() set(CPACK_SYSTEM_NAME "windows-x86") endif() elseif(APPLE) if(NOT CPACK_GENERATOR) set(CPACK_GENERATOR "DragNDrop") endif() set(CPACK_DMG_FORMAT "UDBZ") set(CPACK_DMG_VOLUME_NAME "${APPLICATION_NAME}") set(speedcrunch_package_architectures "${CMAKE_OSX_ARCHITECTURES}") if(NOT speedcrunch_package_architectures) set(speedcrunch_package_architectures "${CMAKE_SYSTEM_PROCESSOR}") endif() string(REPLACE ";" "-" speedcrunch_package_architectures "${speedcrunch_package_architectures}") set(CPACK_SYSTEM_NAME "macos-${speedcrunch_package_architectures}") elseif(UNIX) set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") endif() include(CPack) heldercorreia-speedcrunch-e7ca37f/src/cmake/000077500000000000000000000000001526573132500212045ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/cmake/BuildVariants.cmake000066400000000000000000000046011526573132500247560ustar00rootroot00000000000000include_guard(GLOBAL) option(BUILD_VARIANT_OFFICIAL_RELEASE "Force the official Release build settings" OFF) option(BUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE "Force the official portable Release build settings" OFF) option(BUILD_VARIANT_DEV_DEBUG "Force the developer Debug build settings" OFF) set(speedcrunch_build_variants) foreach(variant IN ITEMS BUILD_VARIANT_OFFICIAL_RELEASE BUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE BUILD_VARIANT_DEV_DEBUG) if(${variant}) list(APPEND speedcrunch_build_variants ${variant}) endif() endforeach() list(LENGTH speedcrunch_build_variants speedcrunch_build_variant_count) if(speedcrunch_build_variant_count GREATER 1) list(JOIN speedcrunch_build_variants ", " speedcrunch_build_variant_names) message(FATAL_ERROR "Enable only one build variant at a time. Enabled: ${speedcrunch_build_variant_names}") elseif(speedcrunch_build_variant_count EQUAL 0) return() endif() if(BUILD_VARIANT_DEV_DEBUG) set(speedcrunch_variant_configuration Debug) set(BUILD_TESTING ON CACHE BOOL "Build the test executables and enable CTest" FORCE) set(ENABLE_STARTUP_DIAGNOSTICS ON CACHE BOOL "Record startup timings and detailed appearance diagnostics" FORCE) else() set(speedcrunch_variant_configuration Release) set(BUILD_TESTING OFF CACHE BOOL "Build the test executables and enable CTest" FORCE) set(INSTALL_LICENSES ON CACHE BOOL "Install license texts and notices" FORCE) set(STRIP_BINARY ON CACHE BOOL "Remove debug symbols from the application binary" FORCE) endif() set(ENABLE_UPDATE_CHECKS ON CACHE BOOL "Enable launch-time and manual update checks" FORCE) set(CMAKE_BUILD_TYPE "${speedcrunch_variant_configuration}" CACHE STRING "Build type (Debug, Release, RelWithDebInfo, MinSizeRel)" FORCE) # Apply the configuration before project() initializes the compiler and toolchain. get_property(speedcrunch_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(speedcrunch_multi_config) set(CMAKE_CONFIGURATION_TYPES "${speedcrunch_variant_configuration}" CACHE STRING "Available build configurations" FORCE) endif() if(BUILD_VARIANT_OFFICIAL_PORTABLE_RELEASE) set(PORTABLE_SPEEDCRUNCH ON CACHE BOOL "Enable to build in portable mode" FORCE) set(CPACK_GENERATOR ZIP CACHE STRING "CPack package generators" FORCE) endif() message(STATUS "Build variant: ${speedcrunch_build_variants}") heldercorreia-speedcrunch-e7ca37f/src/cmake/DeployMacOS.cmake000066400000000000000000000065361526573132500243370ustar00rootroot00000000000000# Deploy and sign the installed bundle before CPack creates the package. if(NOT IS_DIRECTORY "${APP_BUNDLE}/Contents/MacOS") message(FATAL_ERROR "Missing application bundle: ${APP_BUNDLE}") endif() if(NOT EXISTS "${MACDEPLOYQT}") message(FATAL_ERROR "Missing macdeployqt: ${MACDEPLOYQT}") endif() get_filename_component(MACDEPLOYQT "${MACDEPLOYQT}" REALPATH) get_filename_component(qt_bin_dir "${MACDEPLOYQT}" DIRECTORY) execute_process( COMMAND "${qt_bin_dir}/qtpaths" --query QT_INSTALL_PLUGINS OUTPUT_VARIABLE qt_plugins_dir OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE query_result ) if(NOT query_result STREQUAL "0" OR NOT IS_DIRECTORY "${qt_plugins_dir}") message(FATAL_ERROR "Cannot locate plugins for ${MACDEPLOYQT}") endif() set(required_plugins platforms/libqcocoa.dylib sqldrivers/libqsqlite.dylib) foreach(plugin IN LISTS required_plugins) if(NOT EXISTS "${qt_plugins_dir}/${plugin}") message(FATAL_ERROR "Missing required Qt plugin: ${qt_plugins_dir}/${plugin}") endif() endforeach() set(bundle_plugins_dir "${APP_BUNDLE}/Contents/PlugIns") # Qt Help needs SQLite. Remove old drivers before macdeployqt scans the bundle. file(REMOVE_RECURSE "${bundle_plugins_dir}/sqldrivers") set(plugins ${required_plugins}) foreach(category IN ITEMS printsupport styles tls networkinformation imageformats iconengines platforminputcontexts) file(GLOB category_plugins RELATIVE "${qt_plugins_dir}" "${qt_plugins_dir}/${category}/*.dylib") list(FILTER category_plugins EXCLUDE REGEX "_debug\\.dylib$") list(APPEND plugins ${category_plugins}) endforeach() foreach(plugin IN LISTS plugins) get_filename_component(category "${plugin}" DIRECTORY) file(COPY "${qt_plugins_dir}/${plugin}" DESTINATION "${bundle_plugins_dir}/${category}") endforeach() # macdeployqt scans the copied plugins and deploys their framework dependencies. # Disable its plugin selection so it cannot bring back the unused SQL drivers. execute_process( COMMAND "${MACDEPLOYQT}" "${APP_BUNDLE}" -no-plugins -always-overwrite -codesign=- OUTPUT_VARIABLE deploy_output ERROR_VARIABLE deploy_error RESULT_VARIABLE deploy_result ) message("${deploy_output}${deploy_error}") if(NOT deploy_result STREQUAL "0" OR "${deploy_output}${deploy_error}" MATCHES "(^|\n)ERROR:") message(FATAL_ERROR "Qt deployment failed for ${APP_BUNDLE}") endif() if(NOT EXISTS "${APP_BUNDLE}/Contents/Frameworks/QtCore.framework") message(FATAL_ERROR "Qt deployment failed: missing bundled QtCore.framework") endif() execute_process( COMMAND /usr/bin/otool -L "${APP_BUNDLE}/Contents/MacOS/${APP_EXECUTABLE}" OUTPUT_VARIABLE linked_libraries ERROR_VARIABLE dependency_error RESULT_VARIABLE dependency_result ) if(NOT dependency_result STREQUAL "0") message(FATAL_ERROR "Cannot inspect deployed application dependencies: ${dependency_error}") endif() if(linked_libraries MATCHES "/opt/homebrew|/usr/local|Cellar") message(FATAL_ERROR "Deployed application still links to Homebrew paths: ${linked_libraries}") endif() execute_process( COMMAND /usr/bin/codesign --verify --deep --strict "${APP_BUNDLE}" OUTPUT_VARIABLE signing_output ERROR_VARIABLE signing_error RESULT_VARIABLE signing_result ) if(NOT signing_result STREQUAL "0") message(FATAL_ERROR "Bundle signature verification failed: ${signing_output}${signing_error}") endif() heldercorreia-speedcrunch-e7ca37f/src/cmake/Info.plist.in000066400000000000000000000015371526573132500235670ustar00rootroot00000000000000 NSPrincipalClass NSApplication NSHighResolutionCapable True CFBundleIconFile speedcrunch.icns CFBundlePackageType APPL CFBundleSignature ???? CFBundleExecutable SpeedCrunch CFBundleIdentifier org.speedcrunch CFBundleShortVersionString ${MACOSX_BUNDLE_SHORT_VERSION_STRING} CFBundleVersion ${MACOSX_BUNDLE_BUNDLE_VERSION} LSMinimumSystemVersion ${CMAKE_OSX_DEPLOYMENT_TARGET} heldercorreia-speedcrunch-e7ca37f/src/cmake/InstallLicenses.cmake000066400000000000000000000072511526573132500253070ustar00rootroot00000000000000option(INSTALL_LICENSES "Install license texts and notices" OFF) if(NOT INSTALL_LICENSES) return() endif() set(speedcrunch_license_dir "${DOC_INSTALL_DIR}/Licenses") if(WIN32) install(FILES "${CMAKE_CURRENT_LIST_DIR}/../../pkg/COPYING.rtf" DESTINATION "${DOC_INSTALL_DIR}") endif() set(speedcrunch_qt_notice [[ Qt is supplied by the operating system or package provider. Its license texts, copyright notices and source information accompany the Qt packages.]]) set(speedcrunch_qt_replacement_notice "You may replace the system Qt libraries under their applicable licenses.") if(WIN32 OR APPLE) get_filename_component(speedcrunch_qt_prefix "${Qt6Core_DIR}/../../.." ABSOLUTE) get_filename_component(speedcrunch_qt_sources "${speedcrunch_qt_prefix}/../Src" ABSOLUTE) set(SPEEDCRUNCH_QT_SOURCE_DIR "${speedcrunch_qt_sources}" CACHE PATH "Matching Qt sources containing license texts for bundled Qt libraries") set(speedcrunch_qt_modules qtbase qttools) foreach(module IN ITEMS qtsvg qtimageformats) if(APPLE OR EXISTS "${speedcrunch_qt_prefix}/sbom/${module}-${Qt6_VERSION}.spdx") list(APPEND speedcrunch_qt_modules "${module}") endif() endforeach() string(REPLACE ";" ", " speedcrunch_qt_module_names "${speedcrunch_qt_modules}") string(CONFIGURE [[ The bundled Qt components come from @speedcrunch_qt_module_names@. The Qt directory contains their license texts and the SDK's SPDX documents, including third-party copyright notices, license terms and source locations. These documents cover the complete Qt modules, including components that SpeedCrunch does not use. Each component retains its own license. Qt's open-source license alternatives are recorded in the SPDX documents. The LGPLv3 and GPLv3 texts are included alongside the other Qt license texts. The presence of a commercial license text does not grant a commercial license. The SPDX documents identify the source revisions used by the Qt SDK. Match those revisions when obtaining sources or rebuilding the bundled libraries. ]] speedcrunch_qt_notice @ONLY) set(speedcrunch_qt_replacement_notice [[ You may modify or replace the dynamically linked Qt libraries under their applicable licenses, including reverse engineering to debug such changes. ]]) if(APPLE) string(APPEND speedcrunch_qt_replacement_notice [[ After replacing frameworks in Contents/Frameworks or plugins in Contents/PlugIns, apply a new ad hoc signature to your copy of the app: codesign --force --deep --sign - /path/to/SpeedCrunch.app]]) else() string(APPEND speedcrunch_qt_replacement_notice [[ Replace Qt DLLs beside speedcrunch.exe and plugins in their category folders with compatible builds, then start the application again.]]) endif() endif() string(STRIP "${speedcrunch_qt_notice}" speedcrunch_qt_notice) configure_file("${CMAKE_CURRENT_LIST_DIR}/LICENSES.txt.in" "${CMAKE_CURRENT_BINARY_DIR}/LICENSES.txt" @ONLY) install(FILES "${CMAKE_CURRENT_LIST_DIR}/../../LICENSE" DESTINATION "${speedcrunch_license_dir}" RENAME SpeedCrunch-GPL-2.0.txt) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/LICENSES.txt" DESTINATION "${speedcrunch_license_dir}" RENAME README.txt) if(WIN32 OR APPLE) # Install notices before macOS deployment signs the complete bundle. install(CODE " set(QT_LICENSE_DESTINATION \"${speedcrunch_license_dir}/Qt\") set(QT_SOURCE_DIR \"${SPEEDCRUNCH_QT_SOURCE_DIR}\") set(QT_SBOM_DIR \"${speedcrunch_qt_prefix}/sbom\") set(QT_VERSION \"${Qt6_VERSION}\") set(QT_MODULES \"${speedcrunch_qt_modules}\") include(\"${CMAKE_CURRENT_LIST_DIR}/InstallQtLicenses.cmake\") ") endif() heldercorreia-speedcrunch-e7ca37f/src/cmake/InstallQtLicenses.cmake000066400000000000000000000027701526573132500256150ustar00rootroot00000000000000if(IS_ABSOLUTE "${QT_LICENSE_DESTINATION}") set(qt_license_dir "$ENV{DESTDIR}${QT_LICENSE_DESTINATION}") else() set(qt_license_dir "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${QT_LICENSE_DESTINATION}") endif() # Keep the SDK's build-specific copyrights and notices with its license texts. file(REMOVE_RECURSE "${qt_license_dir}") foreach(module IN LISTS QT_MODULES) set(module_source_dir "${QT_SOURCE_DIR}/${module}") set(module_sbom "${QT_SBOM_DIR}/${module}-${QT_VERSION}.spdx") file(GLOB module_license_files "${module_source_dir}/LICENSES/*.txt") if(NOT EXISTS "${module_source_dir}/.cmake.conf" OR NOT module_license_files) message(FATAL_ERROR "Missing ${module} license texts. Install matching Qt Sources " "or set SPEEDCRUNCH_QT_SOURCE_DIR to the Qt ${QT_VERSION} source tree.") endif() file(STRINGS "${module_source_dir}/.cmake.conf" module_version_line REGEX "^set\\(QT_REPO_MODULE_VERSION ") string(REGEX MATCH "\"([^\"]+)\"" module_version "${module_version_line}") if(NOT "${CMAKE_MATCH_1}" STREQUAL "${QT_VERSION}") message(FATAL_ERROR "${module_source_dir} does not contain Qt ${QT_VERSION} sources") endif() if(NOT EXISTS "${module_sbom}") message(FATAL_ERROR "Missing Qt component notices: ${module_sbom}. " "Use a Qt SDK with SPDX SBOM files when bundling Qt libraries.") endif() file(COPY "${module_source_dir}/LICENSES" "${module_sbom}" DESTINATION "${qt_license_dir}/${module}") endforeach() heldercorreia-speedcrunch-e7ca37f/src/cmake/LICENSES.txt.in000066400000000000000000000015111526573132500235550ustar00rootroot00000000000000SpeedCrunch @speedcrunch_VERSION@ ============================== SpeedCrunch is free software under the GNU General Public License, version 2 or, at your option, any later version. See SpeedCrunch-GPL-2.0.txt. Source code and build instructions: https://www.speedcrunch.org/source.html Qt @Qt6_VERSION@ =============== This application uses dynamically linked Qt libraries and plugins. Copyright (C) The Qt Company Ltd. and other contributors. @speedcrunch_qt_notice@ Qt source code: https://download.qt.io/archive/qt/ https://code.qt.io/cgit/qt/ @speedcrunch_qt_replacement_notice@ Source distribution =================== Distributors must provide the corresponding source code as required by the applicable licenses. The project links above identify the upstream sources. They are not a written source offer from the distributor. heldercorreia-speedcrunch-e7ca37f/src/cmake/MacOSDeploymentTarget.cmake000066400000000000000000000016051526573132500263620ustar00rootroot00000000000000include_guard(GLOBAL) # Set defaults before project() initializes the compiler and Qt toolchain. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR (CMAKE_HOST_APPLE AND NOT CMAKE_SYSTEM_NAME)) if(NOT CMAKE_OSX_ARCHITECTURES) # Replace an empty cached value while preserving explicit architectures. set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "macOS target architectures" FORCE) endif() if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) set(CMAKE_OSX_DEPLOYMENT_TARGET "$ENV{MACOSX_DEPLOYMENT_TARGET}") if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) set(CMAKE_OSX_DEPLOYMENT_TARGET "14.4") endif() # Replace an empty cached value while preserving explicit targets. set(CMAKE_OSX_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}" CACHE STRING "Minimum macOS version supported by the build" FORCE) endif() endif() heldercorreia-speedcrunch-e7ca37f/src/cmake/MacdeployQt.cmake000066400000000000000000000007711526573132500244350ustar00rootroot00000000000000# Macdeployqt.cmake # # Copyright (c) 2017 Samuel Gaist # set(SPEEDCRUNCH_MACOS_DEPLOY_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/DeployMacOS.cmake") function(macdeployqt target app_name) install(CODE " set(APP_BUNDLE \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${BIN_INSTALL_DIR}/${target}\") set(APP_EXECUTABLE \"${app_name}\") set(MACDEPLOYQT \"$\") include(\"${SPEEDCRUNCH_MACOS_DEPLOY_SCRIPT}\") ") endfunction() heldercorreia-speedcrunch-e7ca37f/src/cmake/QtWin32Deploy.cmake000066400000000000000000000252421526573132500245770ustar00rootroot00000000000000find_package(Qt6Core REQUIRED) if(POLICY CMP0177) cmake_policy(SET CMP0177 NEW) endif() # Basic stuff; locate the Qt6Core DLL so we can determine the other directories from it. # TODO: This might need to be configurable. get_target_property(qtwin32_QTCORE_DLL Qt6::Core LOCATION) get_filename_component(qtwin32_QT_LIBDIR ${qtwin32_QTCORE_DLL} DIRECTORY) get_filename_component(qtwin32_QT_PLUGINDIR ${qtwin32_QT_LIBDIR}/../plugins REALPATH) get_filename_component(qtwin32_QT_QMLDIR ${qtwin32_QT_LIBDIR}/../qml REALPATH) set(qtwin32_DLL_SUFFIX_RELEASE ".dll") set(qtwin32_DLL_SUFFIX_DEBUG "d.dll") set(qtwin32_QMLPLUGIN_SUFFIX_RELEASE "plugin${qtwin32_DLL_SUFFIX_RELEASE}") set(qtwin32_QMLPLUGIN_SUFFIX_DEBUG "plugin${qtwin32_DLL_SUFFIX_DEBUG}") # Determine the Qt minor version (so '6.4' or '6.5') for version checking. There's unlikely to be enough changes in # patch releases to make it worth distinguishing based on those. if(DEFINED Qt6Core_VERSION_STRING AND NOT Qt6Core_VERSION_STRING STREQUAL "") set(qtwin32_qt_version "${Qt6Core_VERSION_STRING}") elseif(DEFINED Qt6Core_VERSION AND NOT Qt6Core_VERSION STREQUAL "") set(qtwin32_qt_version "${Qt6Core_VERSION}") elseif(DEFINED Qt6_VERSION AND NOT Qt6_VERSION STREQUAL "") set(qtwin32_qt_version "${Qt6_VERSION}") else() message(FATAL_ERROR "qtwin32: Could not determine Qt version") endif() string(REGEX MATCH "[0-9]+[.][0-9]+" qtwin32_QT_MINOR_VERSION "${qtwin32_qt_version}") # qtwin32_check_qt_version([STRICT] ...) # Check the current Qt version and warn if it's not any of the specified versions. Only the first two components of the # version number are considered (so '6.4' or '6.5'). If STRICT is specified, the build will abort if the versions don't # match. function(qtwin32_check_qt_version arg) if(${arg} STREQUAL "STRICT" AND ${ARGC} EQUAL 1) message(FATAL_ERROR "qtwin32: Not enough arguments") endif() if(${arg} STREQUAL "STRICT") set(mode "SEND_ERROR") set(versions ${ARGN}) else() set(mode "WARNING") set(versions ${arg} ${ARGN}) endif() foreach(ver ${versions}) if(${ver} VERSION_EQUAL ${qtwin32_QT_MINOR_VERSION}) return() endif() endforeach() message(${mode} "qtwin32: Expected Qt versions: ${versions}, actual Qt version: ${qtwin32_QT_MINOR_VERSION}") endfunction() # _qtwin32_internal_deploy_dlls( ...) # Internal function; install the specified libraries from to . This function uses the 'install' # command, so may either be an absolute path or a path relative to CMAKE_INSTALL_PREFIX. The specified names # may include extra sub directory elements, but are all considered relative to . The library names should not # include the '.dll' suffix or the 'd' infix for debug libraries; if such a debug version of a library is found, it will # be used for debug configurations. function(_qtwin32_internal_deploy_dlls targetdir basedir) foreach(dll ${ARGN}) get_filename_component(dlldir ${dll} DIRECTORY) set(dbg ${basedir}/${dll}${qtwin32_DLL_SUFFIX_DEBUG}) set(rel ${basedir}/${dll}${qtwin32_DLL_SUFFIX_RELEASE}) if(EXISTS ${dbg} AND EXISTS ${rel}) install(FILES ${rel} DESTINATION ${targetdir}/${dlldir} CONFIGURATIONS Release) install(FILES ${dbg} DESTINATION ${targetdir}/${dlldir} CONFIGURATIONS Debug) else() install(FILES ${rel} DESTINATION ${targetdir}/${dlldir}) #else() # if(${strict}) # message(SEND_ERROR "qtwin32: No matching DLL found for '${dll}', aborting.") # else() # message(WARNING "qtwin32: No matching DLL found for '${dll}', skipping.") # endif() endif() endforeach() endfunction() # qtwin32_deploy_dlls( ...) # Install the specified DLLs into . See _qtwin32_internal_deploy_dlls. function(qtwin32_deploy_dlls targetdir) _qtwin32_internal_deploy_dlls(${targetdir} ${qtwin32_QT_LIBDIR} ${ARGN}) endfunction() # qtwin32_deploy_plugins( ...) # Install the specified plugins into . The plugin name should include the category and the name separated by # a forward slash, but no file extensions, e.g. 'platforms/qwindows'. See _qtwin32_internal_deploy_dlls. function(qtwin32_deploy_plugins targetdir) _qtwin32_internal_deploy_dlls(${targetdir} ${qtwin32_QT_PLUGINDIR} ${ARGN}) endfunction() # qtwin32_deploy_qml( ...) # Install QML modules into . This function uses the 'install' command, so may either be an # absolute path or a path relative to CMAKE_INSTALL_PREFIX. The module names are specified as in QML code, with the name # components separated by '.'. The major version of the module may be specified at the end of the name, after a ':' # separator. If the major version is 1, it may be omitted. Examples (QML import statement - module specifier): # "import QtQuick 2.0" - QtQuick:2 # "import QtQuick 2.4" - QtQuick:2 # "import QtQuick.Window 2.0" - QtQuick.Window:2 # "import QtQuick.Controls 1.2" - QtQuick.Controls # "import QtQuick.Controls 1.2" - QtQuick.Controls:1 function(qtwin32_deploy_qml targetdir) foreach(module ${ARGN}) string(REGEX MATCH "^[^:]+" modulename ${module}) if(${module} MATCHES ":([0-9]+)") set(modulever ${CMAKE_MATCH_1}) else() set(modulever 1) endif() string(REPLACE "." "/" modulepath ${modulename}) if(NOT ${modulever} EQUAL 1) set(modulepath ${modulepath}.${modulever}) endif() install(DIRECTORY ${qtwin32_QT_QMLDIR}/${modulepath}/ DESTINATION ${targetdir}/${modulepath}/ CONFIGURATIONS Release PATTERN "*${qtwin32_QMLPLUGIN_SUFFIX_DEBUG}" EXCLUDE) install(DIRECTORY ${qtwin32_QT_QMLDIR}/${modulepath}/ DESTINATION ${targetdir}/${modulepath}/ CONFIGURATIONS Debug PATTERN "*${qtwin32_QMLPLUGIN_SUFFIX_RELEASE}" EXCLUDE) endforeach() endfunction() # qtwin32_deploy_default_qt_conf() # Create and install a basic generated qt.conf into . The generated qt.conf simply sets the "Prefix" field # to force the Qt libraries to load plugins, QML modules etc. only from the installation directory. This makes sure the # application doesn't pick up these things from an installed Qt SDK. function(qtwin32_deploy_default_qt_conf targetdir) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generated-qt.conf "[Paths]\nPrefix=.") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/generated-qt.conf DESTINATION ${targetdir} RENAME qt.conf) endfunction() # _qtwin32_internal_collect_misc_libs() # Internal function; collect all d3dcompiler_*.dll and ICU DLLs in the Qt installation and save them in # qtwin32_D3DCompiler_LIBS and qtwin32_ICU_LIBS variables so they can be deployed without hardcoding the specific # versions. In a function to not pollute the global namespace as much. function(_qtwin32_internal_collect_misc_libs) file(GLOB d3dcompiler_files LIST_DIRECTORIES false "${qtwin32_QT_LIBDIR}/d3dcompiler_*${qtwin32_DLL_SUFFIX_RELEASE}") foreach(dll ${d3dcompiler_files}) get_filename_component(basename ${dll} NAME_WE) list(APPEND d3dcompiler_libs ${basename}) endforeach() set(qtwin32_D3DCompiler_LIBS ${d3dcompiler_libs} PARENT_SCOPE) file(GLOB icu_files LIST_DIRECTORIES false "${qtwin32_QT_LIBDIR}/icudt*${qtwin32_DLL_SUFFIX_RELEASE}" "${qtwin32_QT_LIBDIR}/icuin*${qtwin32_DLL_SUFFIX_RELEASE}" "${qtwin32_QT_LIBDIR}/icuuc*${qtwin32_DLL_SUFFIX_RELEASE}") foreach(dll ${icu_files}) get_filename_component(basename ${dll} NAME_WE) list(APPEND icu_libs ${basename}) endforeach() set(qtwin32_ICU_LIBS ${icu_libs} PARENT_SCOPE) endfunction() _qtwin32_internal_collect_misc_libs() # qtwin32_deploy_modules( ...) # Install modules of files into . A "module", in this context, is a set of Qt DLLs, plugins and QML modules; # it can also have dependencies on other such modules which will also be installed when the module is installed. For a # module , the dependent bits are installed as such: # any DLLs specified in the variable _LIBS are installed using qtwin32_deploy_dlls # any plugins specified in the variable _PLUGINS are installed using qtwin32_deploy_plugins # any QML modules specified in the variable _QML are installed using qtwin32_deploy_qml # any other modules specified in the variable _DEPS are recursively installed using qtwin32_deploy_modules function(qtwin32_deploy_modules targetdir) foreach(module ${ARGN}) qtwin32_deploy_modules(${targetdir} ${${module}_DEPS}) qtwin32_deploy_dlls(${targetdir} ${${module}_LIBS}) qtwin32_deploy_plugins(${targetdir} ${${module}_PLUGINS}) qtwin32_deploy_qml(${targetdir} ${${module}_QML}) endforeach() endfunction() # Modules: # qtwin32_ICU - the ICU libraries # qtwin32_D3DCompiler - the d3dcompiler_*.dll # qtwin32_MinGW - MinGW runtime libraries set(qtwin32_MinGW_LIBS libgcc_s_dw2-1 libstdc++-6 libwinpthread-1) # qtwin32_Qt6Core - just QtCore set(qtwin32_Qt6Core_LIBS Qt6Core) if(MINGW) set(qtwin32_Qt6Core_DEPS qtwin32_MinGW) endif() # qtwin32_Qt6Network - QtNetwork with the native Windows TLS backend set(qtwin32_Qt6Network_LIBS Qt6Network) set(qtwin32_Qt6Network_PLUGINS tls/qschannelbackend) set(qtwin32_Qt6Network_DEPS qtwin32_Qt6Core) # qtwin32_Qt6Gui - QtGui (without QtQuick or Widgets), including the platform plugin set(qtwin32_Qt6Gui_LIBS Qt6Gui) set(qtwin32_Qt6Gui_PLUGINS platforms/qwindows) set(qtwin32_Qt6Gui_DEPS qtwin32_Qt6Core) # qtwin32_Qt6Widgets - libraries and plugins for a basic Widgets application set(qtwin32_Qt6Widgets_LIBS Qt6Widgets) set(qtwin32_Qt6Widgets_DEPS qtwin32_Qt6Gui) # qtwin32_Qt6Sql - basic QtSql libraries set(qtwin32_Qt6Sql_LIBS Qt6Sql) set(qtwin32_Qt6Sql_DEPS qtwin32_Qt6Core) # qtwin32_Qt6Help - libraries and plugins for QtHelp set(qtwin32_Qt6Help_LIBS Qt6Help) set(qtwin32_Qt6Help_PLUGINS sqldrivers/qsqlite) set(qtwin32_Qt6Help_DEPS qtwin32_Qt6Core qtwin32_Qt6Network qtwin32_Qt6Sql qtwin32_Qt6Widgets) # qtwin32_Qt6Svg - libraries and plugins for QtSvg (does this really depend on Widgets?) set(qtwin32_Qt6Svg_LIBS Qt6Svg) set(qtwin32_Qt6Svg_PLUGINS iconengines/qsvgicon imageformats/qsvg) set(qtwin32_Qt6Svg_DEPS qtwin32_Qt6Widgets) # qtwin32_Qt6Quick - libraries and plugins for a basic QtQuick 2 application set(qtwin32_Qt6Quick_LIBS Qt6Qml Qt6Quick) set(qtwin32_Qt6Quick_QML QtQuick:2 QtQuick.Window:2) set(qtwin32_Qt6Quick_DEPS qtwin32_Qt6Network qtwin32_Qt6Gui) # qtwin32_Qt6WinExtras - QtWinExtras and dependencies set(qtwin32_Qt6WinExtras_LIBS Qt6WinExtras) set(qtwin32_Qt6WinExtras_DEPS qtwin32_Qt6Widgets) # qtwin32_ANGLE - libraries required for ANGLE set(qtwin32_ANGLE_LIBS libEGL libGLESv2) if(MSVC) # This DLL doesn't seem to be included for the MinGW builds. set(qtwin32_ANGLE_DEPS qtwin32_D3DCompiler) endif() heldercorreia-speedcrunch-e7ca37f/src/cmake_uninstall.cmake.in000066400000000000000000000016141526573132500247060ustar00rootroot00000000000000IF(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") IF(EXISTS "$ENV{DESTDIR}${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF(NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") ENDIF(NOT "${rm_retval}" STREQUAL 0) ELSE(EXISTS "$ENV{DESTDIR}${file}") MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") ENDIF(EXISTS "$ENV{DESTDIR}${file}") ENDFOREACH(file) heldercorreia-speedcrunch-e7ca37f/src/core/000077500000000000000000000000001526573132500210545ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/core/anglemode.h000066400000000000000000000011301526573132500231530ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_ANGLEMODE_H #define CORE_ANGLEMODE_H namespace AngleMode { inline constexpr char Radian = 'r'; inline constexpr char Degree = 'd'; inline constexpr char Gradian = 'g'; inline constexpr char Turn = 't'; inline constexpr char Revolution = 'v'; inline constexpr char Default = Radian; inline bool isValid(char mode) { return mode == Radian || mode == Degree || mode == Gradian || mode == Turn || mode == Revolution; } } #endif // CORE_ANGLEMODE_H heldercorreia-speedcrunch-e7ca37f/src/core/book.cpp000066400000000000000000000416161526573132500225220ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2013-2014, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "core/book.h" #define STYLE \ "" #define BEGIN QString("" STYLE "")+ #define SECTION(s) "

    "+(s)+"

    " #define BR "
    " #define INDEX_LINK "
    "+Book::tr("Index")+"" #define LINK(link,text) ""+text+"" #define TITLE(s) "

    "+(s)+"

    " #define SUBTITLE(s) "

    "#s+"

    " // Clickable formula without a unit block. #define FORMULA(link,text) ""#text"
    " // Clickable formula with the same unit text used for editor insertion and display. #define FORMULA_UNIT(link,text,unit) ""#text" "#unit"
    " // Clickable formula with editor unit text displayed "as" separate HTML unit markup. #define FORMULA_UNIT_AS(link,text,unit,displayUnit) ""#text" "#displayUnit"
    " #define TABLE "" #define ROW "" #define _TABLE "
    " #define VARIABLE(s) ""#s"" #define CAPTION(s) ""+(s)+"" #define END "" namespace { const auto makeIndexPage = []() -> QString { return BEGIN TITLE(Book::tr("Index")) SECTION(Book::tr("Algebra")) LINK(algebra/quadratic-equation, Book::tr("Quadratic Equation")) BR LINK(algebra/log-base-conversion, Book::tr("Logarithmic Base Conversion")) BR SECTION(Book::tr("Geometry")) LINK(geometry/circle, Book::tr("Circle")) BR LINK(geometry/sector, Book::tr("Sector")) BR LINK(geometry/sphere, Book::tr("Sphere")) BR LINK(geometry/cube, Book::tr("Cube")) BR LINK(geometry/cone, Book::tr("Cone")) BR LINK(geometry/cylinder, Book::tr("Cylinder")) BR SECTION(Book::tr("Electronics")) LINK(electronics/ohmslaw, Book::tr("Ohm's Law")) BR LINK(electronics/power, Book::tr("Power")) BR LINK(electronics/reactance, Book::tr("Reactance")) BR LINK(electronics/resonance, Book::tr("Resonance")) BR SECTION(Book::tr("Radio Frequency")) LINK(rf/antennas, Book::tr("Antennas")) BR LINK(rf/impedance, Book::tr("Characteristic Impedance (coax)")) BR LINK(rf/propagation, Book::tr("Velocity of Propagation (coax)")) BR LINK(rf/swr, Book::tr("Standing Wave Ratio & Return Loss")) BR LINK(rf/wavelength, Book::tr("Free Space Wavelength")) BR END; }; const auto makeAlgebraQuadraticEquationPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Quadratic Equation")) SUBTITLE(a·x2 + b·x + c = 0) FORMULA(x1 = (-b + sqrt(b%5e2 - 4*a*c))/(2*a), x1 = (-b + √(b2 - 4·a·c)) / (2·a)) FORMULA(x2 = (-b - sqrt(b%5e2 - 4*a*c))/(2*a), x2 = (-b - √(b2 - 4·a·c)) / (2·a)) END; }; const auto makeAlgebraLogBaseConversionPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Logarithmic Base Conversion")) FORMULA(y = log(x) / log(a), logax = log(x) / log(a)) END; }; const auto makeElectronicsOhmsLawPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Ohm's Law")) FORMULA_UNIT(R = V / I, R = V / I, Ω) FORMULA_UNIT(V = I * R, V = I·R, V) FORMULA_UNIT(I = V / R, I = V / R, A) TABLE VARIABLE(R) CAPTION(Book::tr("resistance")) ROW VARIABLE(V) CAPTION(Book::tr("voltage")) ROW VARIABLE(I) CAPTION(Book::tr("current")) ROW _TABLE END; }; const auto makeElectronicsPowerPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Power")) FORMULA_UNIT(P = I * V, P = I·V, W) FORMULA_UNIT(P = I%5e2 * R, P = I2·R, W) FORMULA_UNIT(P = V%5e2 / R, P = V2 / R, W) FORMULA_UNIT(I = P / V, I = P / V, A) FORMULA_UNIT(I = sqrt(P / R), I = √(P / R), A) FORMULA_UNIT(V = P / I, V = P / I, V) FORMULA_UNIT(V = sqrt(P * R), V = √(P·R), V) FORMULA_UNIT(R = V%5e2 / P, R = V2 / P, Ω) FORMULA_UNIT(R = P / I%5e2, R = P / I2, Ω) TABLE VARIABLE(P) CAPTION(Book::tr("power")) ROW VARIABLE(I) CAPTION(Book::tr("current")) ROW VARIABLE(V) CAPTION(Book::tr("voltage")) ROW VARIABLE(R) CAPTION(Book::tr("resistance")) ROW _TABLE END; }; const auto makeElectronicsReactancePage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Reactance")) FORMULA_UNIT(Xl = 2 * Ï€ * f * L, XL = 2·Ï€·f·L, Ω) FORMULA_UNIT(Xc = 1 / (2 * Ï€ * f * C), XC = 1 / (2·Ï€·f·C), Ω) FORMULA_UNIT(L = Xl / (2 * Ï€ * f), L = XL / (2·Ï€·f), H) FORMULA_UNIT(C = 1 / (2 * Ï€ * f * Xc), C = 1 / (2·Ï€·f·XC), F) FORMULA_UNIT(f = Xl / (2 * Ï€ * L), f = XL / (2·Ï€·L), Hz) FORMULA_UNIT(f = 1 / (Xc * 2 * Ï€ * C), f = 1 / (XC·2·Ï€·C), Hz) TABLE VARIABLE(XL) CAPTION(Book::tr("inductive reactance")) ROW VARIABLE(XC) CAPTION(Book::tr("capacitive reactance")) ROW VARIABLE(L) CAPTION(Book::tr("inductance")) ROW VARIABLE(C) CAPTION(Book::tr("capacitance")) ROW VARIABLE(f) CAPTION(Book::tr("frequency")) ROW _TABLE END; }; const auto makeElectronicsResonancePage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Resonance")) FORMULA_UNIT(f = 1 / (2 * Ï€ * sqrt(L * C)), f = 1 / (2·Ï€·√(L·C)), Hz) FORMULA_UNIT(L = 1 / (4 * Ï€%5e2 * f%5e2 * C), L = 1 / (4·Ï€2·f2·C), H) FORMULA_UNIT(C = 1 / (4 * Ï€%5e2 * f%5e2 * L), C = 1 / (4·Ï€2·f2·L), F) TABLE VARIABLE(f) CAPTION(Book::tr("resonance frequency")) ROW VARIABLE(L) CAPTION(Book::tr("inductance")) ROW VARIABLE(C) CAPTION(Book::tr("capacitance")) ROW _TABLE END; }; const auto makeGeometryCirclePage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Circle")) FORMULA(A = Ï€ * r%5e2, A = Ï€·r2) FORMULA(A = Ï€ * (d/2)%5e2, A = Ï€·(d/2)2) FORMULA(P = 2 * Ï€ * r, P = 2·Ï€·r) FORMULA(P = Ï€ * d, P = Ï€·d) TABLE VARIABLE(A) CAPTION(Book::tr("area")) ROW VARIABLE(P) CAPTION(Book::tr("perimeter")) ROW VARIABLE(d) CAPTION(Book::tr("diameter")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) _TABLE END; }; const auto makeGeometryConePage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Cone")) FORMULA(V = 1/3 * Ï€ * r%5e2 * h, V = (1/3)·Ï€·r2·h) FORMULA(A = Ï€ * r%5e2 + Ï€ * r * s, A = Ï€·r2 + Ï€·r·s) FORMULA(A = Ï€ * r%5e2 + Ï€ * r * sqrt(r%5e2+h%5e2), A = Ï€·r2 + Ï€·r·√(r2+h2)) TABLE VARIABLE(V) CAPTION(Book::tr("volume")) ROW VARIABLE(A) CAPTION(Book::tr("surface area")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) ROW VARIABLE(h) CAPTION(Book::tr("height")) ROW VARIABLE(s) CAPTION(Book::tr("slant height")) _TABLE END; }; const auto makeGeometryCubePage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Cube")) FORMULA(V = l%5e3, V = l3) FORMULA(A = 6 * l%5e2, A = 6·l2) FORMULA(Df = sqrt(2) * l, Df = √2·l) FORMULA(Ds = sqrt(3) * l, Ds = √3·l) TABLE VARIABLE(V) CAPTION(Book::tr("volume")) ROW VARIABLE(A) CAPTION(Book::tr("surface area")) ROW VARIABLE(Df) CAPTION(Book::tr("face diagonal")) ROW VARIABLE(Ds) CAPTION(Book::tr("space diagonal")) ROW VARIABLE(l) CAPTION(Book::tr("edge length")) _TABLE END; }; const auto makeGeometryCylinderPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Cylinder")) FORMULA(V = Ï€ * r%5e2 * h, V = Ï€·r2·h) FORMULA(A = (2 * Ï€ * r%5e2) + (2 * Ï€ * r * h), A = 2·Ï€·r2 + 2·Ï€·r·h) TABLE VARIABLE(V) CAPTION(Book::tr("volume")) ROW VARIABLE(A) CAPTION(Book::tr("area")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) ROW VARIABLE(h) CAPTION(Book::tr("height")) _TABLE END; }; const auto makeGeometrySectorPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Sector")) FORMULA(A = 1/2 * L * r, A = 1/2·L·r) FORMULA(A = theta/360 * Ï€ * r%5e2, A = θ/360·Ï€·r2) FORMULA(L = theta/180 * Ï€ * r, L = θ/180·Ï€·r) TABLE VARIABLE(A) CAPTION(Book::tr("area")) ROW VARIABLE(L) CAPTION(Book::tr("arc length")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) ROW VARIABLE(θ) CAPTION(Book::tr("central angle (degrees)")) _TABLE END; }; const auto makeGeometrySpherePage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Sphere")) FORMULA(A = 4 * Ï€ * r%5e2, A = 4·Ï€·r2) FORMULA(A = Ï€ *d%5e2, A = Ï€·d2) FORMULA(V = 4/3 * Ï€ * r%5e3, V = 4/3·Ï€·r3) FORMULA(V = 1/6 * Ï€ * d%5e3, V = 1/6·Ï€·d3) TABLE VARIABLE(A) CAPTION(Book::tr("area")) ROW VARIABLE(V) CAPTION(Book::tr("volume")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) ROW VARIABLE(d) CAPTION(Book::tr("diameter")) _TABLE END; }; const auto makeRFAntennasPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Radio Frequency")) FORMULA_UNIT_AS(Pd = Pin / (4 * Ï€ * r%5e2), Pd = Pin / (4·Ï€·r2), W/m%5e2, W·m-2) FORMULA_UNIT_AS(E = sqrt(Pd * 120 * Ï€), E = √(Pd·120·Ï€), V/m, V·m-1) FORMULA_UNIT_AS(E = sqrt((Pin * 120 * Ï€) / (4 * Ï€ * r%5e2)), E = √[(Pin·120·Ï€) / (4·Ï€·r2)], V/m, V·m-1) FORMULA_UNIT_AS(E = sqrt(30 * Pin) / r, E = √(30·Pin) / r, V/m, V·m-1) FORMULA_UNIT_AS(Ed = E * sqrt(D), Ed = E·√D, V/m, V·m-1) FORMULA_UNIT_AS(Edp = E * sqrt(1.64), Edp = E·√1.64, V/m, V·m-1) END; }; const auto makeRFImpedancePage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Characteristic Impedance (coax)")) FORMULA_UNIT(Zo = 59.959 / sqrt(er) * ln(d1/d2), Z0 = 59.959 / √er · ln(d1/d2), Ω) TABLE VARIABLE(er) CAPTION(Book::tr("dielectric constant")) ROW VARIABLE(d1) CAPTION(Book::tr("outer conductor's inner diameter")) ROW VARIABLE(d2) CAPTION(Book::tr("inner conductor's outer diameter")) _TABLE END; }; const auto makeRFPropagationPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Velocity of Propagation (coax)")) SUBTITLE(Vp = c / √er) FORMULA_UNIT_AS(Vp = 3e8 / sqrt(er), Vp = 3e8 / √er, m/s, m·s-1) FORMULA_UNIT_AS(Vp = 299792458 / sqrt(er), Vp = 299792458 / √er, m/s, m·s-1) FORMULA_UNIT_AS(Vp = 983571056.43045 / sqrt(er), Vp = 983571056.43045 / √er, ft/s, ft·s-1) TABLE VARIABLE(c) CAPTION(Book::tr("speed of light")) ROW VARIABLE(e) CAPTION(Book::tr("dielectric constant")) ROW _TABLE END; }; const auto makeRFSWRPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Standing Wave Ratio & Return Loss")) FORMULA(SWR = (1+r) / (1-r), SWR = (1 + ρ) / (1 - ρ)) FORMULA(r = (SWR-1) / (SWR+1), ρ = (SWR - 1) / (SWR + 1)) FORMULA(r = (Z-1) / (Z+1), ρ = (Z - 1) / (Z + 1)) FORMULA_UNIT(Z = (1+r) / (1-r), Z = (1 + ρ) / (1 - ρ), Ω) FORMULA(RL = -20 * log(r), RL = -20·log(ρ)) FORMULA(RL = -20 * log((SWR-1)/(SWR+1)), RL = -20·log[(SWR - 1) / (SWR + 1)]) FORMULA_UNIT(Pr = Pin * r%5e2, Pr = Pin·ρ2, W) FORMULA_UNIT(Pt = Pin * (1-r%5e2), Pt = Pin·(1-ρ2), W) TABLE VARIABLE(Pin) CAPTION(Book::tr("input power") + " (W)") ROW VARIABLE(Pr) CAPTION(Book::tr("reflected power") + " (W)") ROW VARIABLE(Pt) CAPTION(Book::tr("transmitted power") + " (W)") ROW VARIABLE(RL) CAPTION(Book::tr("return loss") + " (dB)") ROW VARIABLE(ρ) CAPTION(Book::tr("reflection coefficient")) ROW VARIABLE(SWR) CAPTION(Book::tr("standing wave ratio")) ROW VARIABLE(Z) CAPTION(Book::tr("normalized impedance")) ROW _TABLE END; }; const auto makeRFWavelengthPage = []() -> QString { return BEGIN INDEX_LINK TITLE(Book::tr("Free Space Wavelength")) SUBTITLE(λ0 = c / f) FORMULA_UNIT(L = 3e8 / f, L = 3×108 / f, m) FORMULA_UNIT(L = 299792458 / f, L = 299792458 / f, m) FORMULA_UNIT(L = 983571056.43045 / f, L = 983571056.43045 / f, ft) TABLE VARIABLE(f) CAPTION(Book::tr("frequency (Hz)")) ROW _TABLE END; }; } // namespace void Book::createPages() { StartupDiagnostics::Scope timing("Register formula book pages"); addPage("index", +makeIndexPage); addPage("algebra/quadratic-equation", +makeAlgebraQuadraticEquationPage); addPage("algebra/log-base-conversion", +makeAlgebraLogBaseConversionPage); addPage("electronics/ohmslaw", +makeElectronicsOhmsLawPage); addPage("electronics/power", +makeElectronicsPowerPage); addPage("electronics/reactance", +makeElectronicsReactancePage); addPage("electronics/resonance", +makeElectronicsResonancePage); addPage("geometry/circle", +makeGeometryCirclePage); addPage("geometry/cone", +makeGeometryConePage); addPage("geometry/cube", +makeGeometryCubePage); addPage("geometry/cylinder", +makeGeometryCylinderPage); addPage("geometry/sector", +makeGeometrySectorPage); addPage("geometry/sphere", +makeGeometrySpherePage); addPage("rf/antennas", +makeRFAntennasPage); addPage("rf/impedance", +makeRFImpedancePage); addPage("rf/propagation", +makeRFPropagationPage); addPage("rf/swr", +makeRFSWRPage); addPage("rf/wavelength", +makeRFWavelengthPage); } heldercorreia-speedcrunch-e7ca37f/src/core/book.h000066400000000000000000000006331526573132500221610ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2013-2014, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_BOOK_H #define CORE_BOOK_H #include "core/pageserver.h" class Book : public PageServer { Q_OBJECT public: explicit Book(QObject* parent = 0) : PageServer(parent) { createPages(); } virtual void createPages(); private: Q_DISABLE_COPY(Book) }; #endif // CORE_BOOK_H heldercorreia-speedcrunch-e7ca37f/src/core/colorscheme.cpp000066400000000000000000000166161526573132500240750ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2010, 2013-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/colorscheme.h" #include "core/settings.h" #include #include #include #include #include #include static const constexpr auto COLOR_SCHEME_EXTENSION = "json"; static const QMap& builtInResourceNames() { // Keep persisted scheme names while using ASCII paths: rcc emits filenames // in the Windows code page in generated C++ comments and dependency lists. static const QMap names{ {QStringLiteral("Ros\u00e9 Pine Moon"), QStringLiteral("Rose Pine Moon")}, {QStringLiteral("Ros\u00e9 Pine Dawn"), QStringLiteral("Rose Pine Dawn")} }; return names; } static QString builtInResourceName(const QString& schemeName) { // Internal filenames do not reserve additional names for user themes. if (builtInResourceNames().values().contains(schemeName)) return QString(); return builtInResourceNames().value(schemeName, schemeName); } static const QVector colorSchemeSearchPaths() { static QVector searchPaths; if (searchPaths.isEmpty()) { // By only populating the paths in a function when they're used, we ensure all the QApplication // fields that are used by QStandardPaths are set. searchPaths.append(QString("%1/color-schemes").arg(Settings::getDataPath())); searchPaths.append(QStringLiteral(":/color-schemes")); } return searchPaths; } QVector ColorScheme::fileSystemSearchPaths() { QVector paths; const auto searchPaths = colorSchemeSearchPaths(); for (const auto& path : searchPaths) { if (!path.startsWith(QLatin1Char(':'))) paths.append(path); } return paths; } bool ColorScheme::isBuiltInName(const QString& name) { const QString resourceName = builtInResourceName(name); if (resourceName.isEmpty()) return false; return loadFromFile(QStringLiteral(":/color-schemes/%1.%2").arg(resourceName, COLOR_SCHEME_EXTENSION)).isValid(); } QString ColorScheme::filePathForName(const QString& name) { for (const auto& path : colorSchemeSearchPaths()) { const QString baseName = path.startsWith(QLatin1Char(':')) ? builtInResourceName(name) : name; if (baseName.isEmpty()) continue; const QString fileName = QString("%1/%2.%3").arg(path, baseName, COLOR_SCHEME_EXTENSION); if (loadFromFile(fileName).isValid()) return fileName; } return QString(); } static QColor getFallbackColor(ColorScheme::Role role) { switch (role) { case ColorScheme::Background: return QApplication::palette().color(QPalette::Base); default: return QApplication::palette().color(QPalette::Text); } } static bool hasSupportedThemeSchema(const QJsonObject& obj) { const QJsonValue schemaValue = obj.value(QStringLiteral("$schema")); const QJsonValue idValue = obj.value(QStringLiteral("$id")); if (!schemaValue.isString() || schemaValue.toString() != QLatin1String(ColorScheme::SchemaDraft)) return false; if (!idValue.isString() || idValue.toString() != QLatin1String(ColorScheme::SchemaId)) return false; const QJsonValue versionValue = obj.value(QStringLiteral("version")); return versionValue.isUndefined() || versionValue.isString(); } ColorScheme::ColorScheme(const QJsonDocument& doc) : m_valid(false) { if (!doc.isObject()) return; const auto obj = doc.object(); if (!hasSupportedThemeSchema(obj)) return; const QJsonValue nameValue = obj.value(QStringLiteral("name")); if (nameValue.isString()) { const QString name = nameValue.toString().trimmed(); if (!name.isEmpty()) m_displayName = name; } const auto roleEntries = roleNames(); for (const auto& role : roleEntries) { auto v = obj.value(role.first); if (v.isUndefined()) // Having a key missing is fine... continue; auto color = QColor(v.toString()); if (!color.isValid()) // ...having one that's not a color is not. return; m_colors.insert(role.second, color); } m_valid = true; } QColor ColorScheme::colorForRole(Role role) const { QColor color = m_colors.value(role); if (!color.isValid()) return getFallbackColor(role); else return color; } bool ColorScheme::hasColorForRole(Role role) const { return m_colors.contains(role) && m_colors.value(role).isValid(); } QStringList ColorScheme::enumerate() { QMap colorSchemes; for (auto& searchPath : colorSchemeSearchPaths()) { QDir dir(searchPath); dir.setFilter(QDir::Files | QDir::Readable); dir.setNameFilters({ QString("*.%1").arg(COLOR_SCHEME_EXTENSION) }); const auto infoList = dir.entryInfoList(); for (auto& info : infoList) { // TODO: Use Qt 5.7's qAsConst(). const QString baseName = info.completeBaseName(); const QString schemeName = searchPath.startsWith(QLatin1Char(':')) ? builtInResourceNames().key(baseName, baseName) : baseName; colorSchemes.insert(schemeName, nullptr); } } // Since this is a QMap, the keys are already sorted in ascending order. return colorSchemes.keys(); } ColorScheme ColorScheme::loadFromFile(const QString& path) { QFile file(path); if (!file.open(QIODevice::ReadOnly)) return ColorScheme(); // TODO: Better error handling. return ColorScheme(QJsonDocument::fromJson(file.readAll())); } ColorScheme ColorScheme::loadByName(const QString& name) { const QString fileName = filePathForName(name); if (!fileName.isEmpty()) return loadFromFile(fileName); return ColorScheme(); } QJsonObject ColorScheme::toJsonObject() const { QJsonObject object; object.insert(QStringLiteral("$schema"), QString::fromLatin1(SchemaDraft)); object.insert(QStringLiteral("$id"), QString::fromLatin1(SchemaId)); if (!m_displayName.isEmpty()) object.insert(QStringLiteral("name"), m_displayName); const auto roleEntries = roleNames(); for (const auto& roleEntry : roleEntries) { if (roleEntry.second == Primary && !hasColorForRole(Primary)) continue; object.insert(roleEntry.first, colorForRole(roleEntry.second).name()); } return object; } ColorScheme ColorScheme::fromJsonObject(const QJsonObject& object) { return ColorScheme(QJsonDocument(object)); } QVector> ColorScheme::roleNames() { return { { QStringLiteral("number"), ColorScheme::Number }, { QStringLiteral("parens"), ColorScheme::Parens }, { QStringLiteral("list"), ColorScheme::List }, { QStringLiteral("unit"), ColorScheme::Unit }, { QStringLiteral("result"), ColorScheme::Result }, { QStringLiteral("comment"), ColorScheme::Comment }, { QStringLiteral("function"), ColorScheme::Function }, { QStringLiteral("operator"), ColorScheme::Operator }, { QStringLiteral("variable"), ColorScheme::Variable }, { QStringLiteral("separator"), ColorScheme::Separator }, { QStringLiteral("background"), ColorScheme::Background }, { QStringLiteral("primary"), ColorScheme::Primary }, }; } heldercorreia-speedcrunch-e7ca37f/src/core/colorscheme.h000066400000000000000000000033031526573132500235270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2010, 2013-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_COLORSCHEME_H #define CORE_COLORSCHEME_H #include #include #include #include #include #include #include class ColorScheme { public: // Theme JSON schema documentation: doc/src/userguide/theme_json_schema.rst enum Role { Number, Parens, List, Unit, Result, Comment, Function, Operator, Variable, Separator, Background, Primary }; static constexpr const char* SchemaDraft = "https://json-schema.org/draft/2020-12/schema"; static constexpr const char* SchemaId = "https://speedcrunch.org/schemas/theme-v1.schema.json"; ColorScheme() : m_valid(false) { } ColorScheme(const QJsonDocument& doc); bool isValid() const { return m_valid; } QString displayName() const { return m_displayName; } QColor colorForRole(Role role) const; bool hasColorForRole(Role role) const; QJsonObject toJsonObject() const; static QStringList enumerate(); static bool isBuiltInName(const QString& name); static QVector fileSystemSearchPaths(); static QString filePathForName(const QString& name); static ColorScheme loadFromFile(const QString& path); static ColorScheme loadByName(const QString& name); static ColorScheme fromJsonObject(const QJsonObject& object); static QVector> roleNames(); private: bool m_valid; QString m_displayName; QHash m_colors; }; #endif heldercorreia-speedcrunch-e7ca37f/src/core/complexform.h000066400000000000000000000017141526573132500235630ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_COMPLEXFORM_H #define CORE_COMPLEXFORM_H #include namespace ComplexForm { inline constexpr char Rectangular = 'r'; inline constexpr char Exponential = 'e'; inline constexpr char Trigonometric = 't'; inline constexpr char Cis = 'c'; inline constexpr char Phasor = 'p'; inline constexpr char Default = Rectangular; inline bool isValid(char form) { return form == Rectangular || form == Exponential || form == Trigonometric || form == Cis || form == Phasor; } inline char fromString(const QString& form, char fallback = Default) { if (form.size() != 1) return fallback; const char value = form.at(0).toLatin1(); return isValid(value) ? value : fallback; } inline QString toString(char form) { return QString(QChar(isValid(form) ? form : Default)); } } #endif // CORE_COMPLEXFORM_H heldercorreia-speedcrunch-e7ca37f/src/core/constants.cpp000066400000000000000000001337531526573132500236100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2011, 2013-2014, 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "core/constants.h" #include "core/numberformatter.h" #include "math/hmath.h" #include #include static Constants* s_constantsInstance = nullptr; static void s_deleteConstants() { delete s_constantsInstance; } struct Constants::Private { QStringList domains; QList list; void populate(); void retranslateText(); }; // Internal domain/subdomain identifiers used in constant declarations. static QString domainToDisplay(ConstantDomain domain) { switch (domain) { case ConstantDomain::Mathematics: return Constants::tr("Mathematics"); case ConstantDomain::PhysicsCodata2022: return Constants::tr("Physics (CODATA 2022)"); case ConstantDomain::ChemistryIupacCiaaw2021: return Constants::tr("Chemistry (IUPAC - CIAAW 2021)"); case ConstantDomain::Astronomy: return Constants::tr("Astronomy"); case ConstantDomain::Uncategorized: default: return Constants::tr("Uncategorized"); } } static QString subdomainToDisplay(ConstantSubdomain subdomain) { switch (subdomain) { case ConstantSubdomain::Universal: return Constants::tr("Universal"); case ConstantSubdomain::Electromagnetic: return Constants::tr("Electromagnetic"); case ConstantSubdomain::Physicochemical: return Constants::tr("Physicochemical"); case ConstantSubdomain::AtomicNuclearGeneral: return Constants::tr("Atomic & Nuclear — General"); case ConstantSubdomain::AtomicNuclearElectroweak: return Constants::tr("Atomic & Nuclear — Electroweak"); case ConstantSubdomain::AtomicNuclearElectron: return Constants::tr("Atomic & Nuclear — Electron"); case ConstantSubdomain::AtomicNuclearMuon: return Constants::tr("Atomic & Nuclear — Muon"); case ConstantSubdomain::AtomicNuclearTau: return Constants::tr("Atomic & Nuclear — Tau"); case ConstantSubdomain::AtomicNuclearProton: return Constants::tr("Atomic & Nuclear — Proton"); case ConstantSubdomain::AtomicNuclearNeutron: return Constants::tr("Atomic & Nuclear — Neutron"); case ConstantSubdomain::AtomicNuclearDeuteron: return Constants::tr("Atomic & Nuclear — Deuteron"); case ConstantSubdomain::AtomicNuclearTriton: return Constants::tr("Atomic & Nuclear — Triton"); case ConstantSubdomain::AtomicNuclearHelion: return Constants::tr("Atomic & Nuclear — Helion"); case ConstantSubdomain::AtomicNuclearAlphaParticle: return Constants::tr("Atomic & Nuclear — Alpha particle"); case ConstantSubdomain::AtomicNuclearAtomicUnits: return Constants::tr("Atomic & Nuclear — Atomic units"); case ConstantSubdomain::AtomicNuclearEnergyConversionRelationships: return Constants::tr("Atomic & Nuclear — Energy conversion relationships"); case ConstantSubdomain::AtomicNuclearXrayUnits: return Constants::tr("Atomic & Nuclear — X-ray units"); case ConstantSubdomain::AtomicNuclearMagneticShieldingCorrections: return Constants::tr("Atomic & Nuclear — Magnetic shielding corrections"); case ConstantSubdomain::Masses: return Constants::tr("Masses"); case ConstantSubdomain::Lifetimes: return Constants::tr("Lifetimes"); case ConstantSubdomain::MolarMasses: return Constants::tr("Molar Masses"); case ConstantSubdomain::Electronegativity: return Constants::tr("Electronegativity"); case ConstantSubdomain::IonizationEnergy: return Constants::tr("Ionization Energy"); case ConstantSubdomain::AstronomyNominalIau2015: return Constants::tr("Nominal Constants (IAU 2015)"); case ConstantSubdomain::AstronomyCurrentBestEstimatesIauNsfa202604: return Constants::tr("Current Best Estimates (IAU NSFA 2026-04)"); case ConstantSubdomain::None: default: return QString(); } } #define SET_CONSTANT_CONTEXT(DOMAIN,SUBDOMAIN) \ domain = DOMAIN; \ subdomain = SUBDOMAIN; #define PUSH_CONSTANT(NAME,VALUE,UNIT) \ constant.domainType = domain; \ constant.subdomainType = subdomain; \ constant.name = Constants::tr(NAME); \ constant.value = QLatin1String(VALUE); \ constant.unit = QString::fromUtf8(UNIT); \ constant.domain = domainToDisplay(constant.domainType); \ constant.subdomain = subdomainToDisplay(constant.subdomainType); \ list << constant; void Constants::Private::populate() { StartupDiagnostics::Scope timing("Populate and translate constants"); domains.clear(); list.clear(); /* PHYSICS: CODATA 2022 https://physics.nist.gov/cuu/Constants/ PARTICLE PHYSICS: PDG 2024 https://pdg.lbl.gov/2024/download/db2024.pdf (relevant info starts at PDF page 8 / document page 6 ) https://journals.aps.org/prd/pdf/10.1103/PhysRevD.110.030001 (relevant info starts at page 137) CHEMISTRY: IUPAC - CIAAW 2021 https://www.ciaaw.org/atomic-weights.htm https://doi.org/10.1515/pac-2019-0603 https://pubchem.ncbi.nlm.nih.gov/periodic-table/ Astronomy — Nominal Constants (IAU 2015) https://arxiv.org/pdf/1510.07674 Astronomy — Current Best Estimates (IAU NSFA 2026-04) https://iau-a3.gitlab.io/NSFA/NSFA_cbe */ Constant constant; ConstantDomain domain; ConstantSubdomain subdomain; SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::Universal); PUSH_CONSTANT(QT_TR_NOOP("characteristic impedance of vacuum (Zâ‚€)"), "376.730313412", "Ω"); PUSH_CONSTANT(QT_TR_NOOP("reduced Planck constant (â„�)"), "1.054571817e-34", "J·s"); PUSH_CONSTANT(QT_TR_NOOP("vacuum electric permittivity (ϵ₀)"), "8.8541878188e-12", "F·mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Newtonian constant of gravitation (G)"), "6.67430e-11", "m³·kgâ�»Â¹Â·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("vacuum magnetic permeability (μ₀)"), "1.25663706127e-6", "N·Aâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("Planck constant (h)"), "6.62607015e-34", "J·s"); PUSH_CONSTANT(QT_TR_NOOP("speed of light in vacuum (c)"), "299792458", "m·sâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("standard acceleration of gravity (gâ‚™)"), "9.80665", "m·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("Newtonian constant of gravitation over h-bar c"), "6.70883e-39", "(GeV/c²)â�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("Planck length"), "1.616255e-35", "m"); PUSH_CONSTANT(QT_TR_NOOP("Planck constant in eV/Hz (h)"), "4.135667696e-15", "eV·Hzâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Planck mass"), "2.176434e-8", "kg"); PUSH_CONSTANT(QT_TR_NOOP("Planck mass energy equivalent in GeV"), "1.220890e19", "GeV"); PUSH_CONSTANT(QT_TR_NOOP("Planck temperature"), "1.416784e32", "K"); PUSH_CONSTANT(QT_TR_NOOP("Planck time"), "5.391247e-44", "s"); PUSH_CONSTANT(QT_TR_NOOP("reduced Planck constant in eV·s (â„�)"), "6.582119569e-16", "eV·s"); PUSH_CONSTANT(QT_TR_NOOP("reduced Planck constant times c in MeV·fm"), "197.3269804", "MeV·fm"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::Electromagnetic); PUSH_CONSTANT(QT_TR_NOOP("Bohr magneton"), "9.2740100657e-24", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("conductance quantum (Gâ‚€)"), "7.748091729e-5", "S"); PUSH_CONSTANT(QT_TR_NOOP("Coulomb constant (kâ‚‘)"), "8.98755178617079867048e9", "N·m²·Câ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("elementary charge (e)"), "1.602176634e-19", "C"); PUSH_CONSTANT(QT_TR_NOOP("elementary charge over h-bar"), "1.519267447e15", "A·Jâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of Josephson constant"), "483597.9e9", "Hz·Vâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Josephson constant"), "483597.8484e9", "Hz·Vâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of ampere-90"), "1.00000008887", "A"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of coulomb-90"), "1.00000008887", "C"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of farad-90"), "0.99999998220", "F"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of henry-90"), "1.00000001779", "H"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of ohm-90"), "1.00000001779", "Ω"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of volt-90"), "1.00000010666", "V"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of watt-90"), "1.00000019553", "W"); PUSH_CONSTANT(QT_TR_NOOP("magnetic flux quantum (Φ₀)"), "2.067833848e-15", "Wb"); PUSH_CONSTANT(QT_TR_NOOP("nuclear magneton"), "5.0507837393e-27", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("inverse of conductance quantum"), "12906.40372", "Ω"); PUSH_CONSTANT(QT_TR_NOOP("conventional value of von Klitzing constant"), "25812.807", "Ω"); PUSH_CONSTANT(QT_TR_NOOP("von Klitzing constant"), "25812.80745", "Ω"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of magnetic dipole moment"), "1.85480201315e-23", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of magnetic flux density"), "2.35051757077e5", "T"); PUSH_CONSTANT(QT_TR_NOOP("Bohr magneton in eV/T"), "5.7883817982e-5", "eV·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Bohr magneton in Hz/T"), "1.39962449171e10", "Hz·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Bohr magneton in inverse meter per tesla"), "46.686447719", "mâ�»Â¹Â·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Bohr magneton in K/T"), "0.67171381472", "K·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("nuclear magneton in eV/T"), "3.15245125417e-8", "eV·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("nuclear magneton in inverse meter per tesla"), "2.54262341009e-2", "mâ�»Â¹Â·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("nuclear magneton in K/T"), "3.6582677706e-4", "K·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("nuclear magneton in MHz/T"), "7.6225932188", "MHz·Tâ�»Â¹"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearGeneral); PUSH_CONSTANT(QT_TR_NOOP("Bohr radius (aâ‚€)"), "5.29177210544e-11", "m"); PUSH_CONSTANT(QT_TR_NOOP("fine-structure constant (α)"), "7.2973525643e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("Hartree energy (Eâ‚•)"), "4.3597447222060e-18", "J"); PUSH_CONSTANT(QT_TR_NOOP("Hartree energy in eV"), "27.211386245981", "eV"); PUSH_CONSTANT(QT_TR_NOOP("quantum of circulation"), "3.6369475467e-4", "m²·sâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("quantum of circulation times 2"), "7.2738950934e-4", "m²·sâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Rydberg constant (R∞)"), "10973731.568157", "mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass unit-hartree relationship"), "3.4231776922e7", "E_h"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass unit-hertz relationship"), "2.25234272185e23", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass unit-inverse meter relationship"), "7.5130066209e14", "mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass unit-joule relationship"), "1.49241808768e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass unit-kelvin relationship"), "1.08095402067e13", "K"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass unit-kilogram relationship"), "1.66053906892e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of 1st hyperpolarizability"), "3.2063612996e-53", "C³·m³·Jâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of 2nd hyperpolarizability"), "6.2353799735e-65", "Câ�´Â·mâ�´Â·Jâ�»Â³"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of charge (e)"), "1.602176634e-19", "C"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of charge density"), "1.08120238677e12", "C·mâ�»Â³"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of current"), "6.6236182375082e-3", "A"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of electric dipole moment"), "8.4783536198e-30", "C·m"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of electric field"), "5.14220675112e11", "V·mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of electric field gradient"), "9.7173624424e21", "V·mâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of electric polarizability"), "1.64877727212e-41", "C²·m²·Jâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of electric potential"), "27.211386245981", "V"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of electric quadrupole moment"), "4.4865515185e-40", "C·m²"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of action"), "1.054571817e-34", "J·s"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of energy"), "4.3597447222060e-18", "J"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of force"), "8.2387235038e-8", "N"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of length"), "5.29177210544e-11", "m"); PUSH_CONSTANT(QT_TR_NOOP("hertz-atomic mass unit relationship"), "4.4398216590e-24", "u"); PUSH_CONSTANT(QT_TR_NOOP("hertz-electron volt relationship"), "4.135667696e-15", "eV"); PUSH_CONSTANT(QT_TR_NOOP("hertz-hartree relationship"), "1.5198298460574e-16", "E_h"); PUSH_CONSTANT(QT_TR_NOOP("hertz-inverse meter relationship"), "3.335640951e-9", "mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("hertz-joule relationship"), "6.62607015e-34", "J"); PUSH_CONSTANT(QT_TR_NOOP("hertz-kelvin relationship"), "4.799243073e-11", "K"); PUSH_CONSTANT(QT_TR_NOOP("hertz-kilogram relationship"), "7.372497323e-51", "kg"); PUSH_CONSTANT(QT_TR_NOOP("hyperfine transition frequency of Cs-133"), "9192631770", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("inverse fine-structure constant (αâ�»Â¹)"), "137.035999177", ""); PUSH_CONSTANT(QT_TR_NOOP("inverse meter-atomic mass unit relationship"), "1.33102504824e-15", "u"); PUSH_CONSTANT(QT_TR_NOOP("inverse meter-electron volt relationship"), "1.239841984e-6", "eV"); PUSH_CONSTANT(QT_TR_NOOP("inverse meter-hartree relationship"), "4.5563352529132e-8", "E_h"); PUSH_CONSTANT(QT_TR_NOOP("inverse meter-hertz relationship"), "299792458", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("inverse meter-joule relationship"), "1.986445857e-25", "J"); PUSH_CONSTANT(QT_TR_NOOP("inverse meter-kelvin relationship"), "1.438776877e-2", "K"); PUSH_CONSTANT(QT_TR_NOOP("inverse meter-kilogram relationship"), "2.210219094e-42", "kg"); PUSH_CONSTANT(QT_TR_NOOP("joule-atomic mass unit relationship"), "6.7005352471e9", "u"); PUSH_CONSTANT(QT_TR_NOOP("joule-electron volt relationship"), "6.241509074e18", "eV"); PUSH_CONSTANT(QT_TR_NOOP("joule-hertz relationship"), "1.509190179e33", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("joule-hartree relationship"), "2.2937122783969e17", "E_h"); PUSH_CONSTANT(QT_TR_NOOP("joule-inverse meter relationship"), "5.034116567e24", "mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("joule-kelvin relationship"), "7.242970516e22", "K"); PUSH_CONSTANT(QT_TR_NOOP("joule-kilogram relationship"), "1.112650056e-17", "kg"); PUSH_CONSTANT(QT_TR_NOOP("kelvin-atomic mass unit relationship"), "9.2510872884e-14", "u"); PUSH_CONSTANT(QT_TR_NOOP("kelvin-electron volt relationship"), "8.617333262e-5", "eV"); PUSH_CONSTANT(QT_TR_NOOP("kelvin-hertz relationship"), "2.083661912e10", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("kelvin-hartree relationship"), "3.1668115634564e-6", "E_h"); PUSH_CONSTANT(QT_TR_NOOP("kelvin-inverse meter relationship"), "69.50348004", "mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("kelvin-joule relationship"), "1.380649e-23", "J"); PUSH_CONSTANT(QT_TR_NOOP("kelvin-kilogram relationship"), "1.536179187e-40", "kg"); PUSH_CONSTANT(QT_TR_NOOP("kilogram-atomic mass unit relationship"), "6.0221407537e26", "u"); PUSH_CONSTANT(QT_TR_NOOP("kilogram-electron volt relationship"), "5.609588603e35", "eV"); PUSH_CONSTANT(QT_TR_NOOP("kilogram-hertz relationship"), "1.356392489e50", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("kilogram-hartree relationship"), "2.0614857887415e34", "E_h"); PUSH_CONSTANT(QT_TR_NOOP("kilogram-inverse meter relationship"), "4.524438335e41", "mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("kilogram-joule relationship"), "8.987551787e16", "J"); PUSH_CONSTANT(QT_TR_NOOP("kilogram-kelvin relationship"), "6.509657260e39", "K"); PUSH_CONSTANT(QT_TR_NOOP("lattice parameter of silicon (a)"), "5.431020511e-10", "m"); PUSH_CONSTANT(QT_TR_NOOP("luminous efficacy"), "683", "lm·Wâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of energy"), "8.1871057880e-14", "J"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of energy in MeV"), "0.51099895069", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of action (â„�)"), "1.054571817e-34", "J·s"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of action in eV·s"), "6.582119569e-16", "eV·s"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of length"), "3.8615926744e-13", "m"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of mass"), "9.1093837139e-31", "kg"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of momentum"), "2.73092453446e-22", "kg·m·sâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of momentum in MeV/c"), "0.51099895069", "MeV/c"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of time"), "1.28808866644e-21", "s"); PUSH_CONSTANT(QT_TR_NOOP("natural unit of velocity"), "299792458", "m·sâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Rydberg constant times c in Hz"), "3.2898419602500e15", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("Rydberg constant times hc in eV"), "13.605693122990", "eV"); PUSH_CONSTANT(QT_TR_NOOP("Rydberg constant times hc in J"), "2.1798723611030e-18", "J"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearElectroweak); PUSH_CONSTANT(QT_TR_NOOP("Fermi coupling constant"), "1.1663787e-5", "GeVâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("weak mixing angle"), "0.22305", ""); PUSH_CONSTANT(QT_TR_NOOP("W to Z mass ratio"), "0.88145", ""); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearElectron); PUSH_CONSTANT(QT_TR_NOOP("Thomson cross section (σₑ)"), "6.6524587051e-29", "m²"); PUSH_CONSTANT(QT_TR_NOOP("electron mass (mâ‚‘)"), "9.1093837139e-31", "kg"); PUSH_CONSTANT(QT_TR_NOOP("electron mass in u"), "5.485799090441e-4", "u"); PUSH_CONSTANT(QT_TR_NOOP("electron mass energy equivalent (mₑ·c²)"), "8.1871057880e-14", "J"); PUSH_CONSTANT(QT_TR_NOOP("electron mass energy equivalent in MeV"), "0.51099895069", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("Compton wavelength"), "2.42631023538e-12", "m"); PUSH_CONSTANT(QT_TR_NOOP("reduced Compton wavelength"), "3.8615926744e-13", "m"); PUSH_CONSTANT(QT_TR_NOOP("classical electron radius (râ‚‘)"), "2.8179403205e-15", "m"); PUSH_CONSTANT(QT_TR_NOOP("electron charge to mass quotient"), "-1.75882000838e11", "C·kgâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("electron-deuteron magnetic moment ratio"), "-2143.9234921", ""); PUSH_CONSTANT(QT_TR_NOOP("electron-deuteron mass ratio"), "2.724437107629e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("electron g factor (gâ‚‘)"), "-2.00231930436092", ""); PUSH_CONSTANT(QT_TR_NOOP("electron gyromagnetic ratio (γₑ)"), "1.76085962784e11", "sâ�»Â¹Â·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("electron gyromagnetic ratio in MHz/T"), "28024.9513861", "MHz·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("electron-helion mass ratio"), "1.819543074649e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("electron magnetic moment (μₑ)"), "-9.2847646917e-24", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("electron magnetic moment anomaly (aâ‚‘)"), "1.15965218046e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("electron magnetic moment to Bohr magneton ratio"), "-1.00115965218046", ""); PUSH_CONSTANT(QT_TR_NOOP("electron magnetic moment to nuclear magneton ratio"), "-1838.281971877", ""); PUSH_CONSTANT(QT_TR_NOOP("electron molar mass (Mâ‚‘)"), "5.4857990962e-7", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("electron-muon magnetic moment ratio"), "206.7669881", ""); PUSH_CONSTANT(QT_TR_NOOP("electron-muon mass ratio"), "4.83633170e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("electron-neutron magnetic moment ratio"), "960.92048", ""); PUSH_CONSTANT(QT_TR_NOOP("electron-neutron mass ratio"), "5.4386734416e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("electron-proton magnetic moment ratio"), "-658.21068789", ""); PUSH_CONSTANT(QT_TR_NOOP("electron-proton mass ratio"), "5.446170214889e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("electron relative atomic mass (Ar(e))"), "5.485799090441e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("electron-tau mass ratio"), "2.87585e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("electron to alpha particle mass ratio"), "1.370933554733e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("electron to shielded helion magnetic moment ratio"), "864.05823986", ""); PUSH_CONSTANT(QT_TR_NOOP("electron to shielded proton magnetic moment ratio"), "-658.2275856", ""); PUSH_CONSTANT(QT_TR_NOOP("electron-triton mass ratio"), "1.819200062327e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("electron volt-atomic mass unit relationship"), "1.07354410083e-9", "u"); PUSH_CONSTANT(QT_TR_NOOP("electron volt-hartree relationship"), "3.6749322175665e-2", "E_h"); PUSH_CONSTANT(QT_TR_NOOP("electron volt-hertz relationship"), "2.417989242e14", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("electron volt-inverse meter relationship"), "8.065543937e5", "mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("electron volt-joule relationship"), "1.602176634e-19", "J"); PUSH_CONSTANT(QT_TR_NOOP("electron volt-kelvin relationship"), "1.160451812e4", "K"); PUSH_CONSTANT(QT_TR_NOOP("electron volt-kilogram relationship"), "1.782661921e-36", "kg"); PUSH_CONSTANT(QT_TR_NOOP("hartree-atomic mass unit relationship"), "2.92126231797e-8", "u"); PUSH_CONSTANT(QT_TR_NOOP("hartree-electron volt relationship"), "27.211386245981", "eV"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearMuon); PUSH_CONSTANT(QT_TR_NOOP("muon Compton wavelength"), "1.173444110e-14", "m"); PUSH_CONSTANT(QT_TR_NOOP("muon-electron mass ratio"), "206.7682827", ""); PUSH_CONSTANT(QT_TR_NOOP("muon g factor"), "-2.00233184123", ""); PUSH_CONSTANT(QT_TR_NOOP("muon magnetic moment"), "-4.49044830e-26", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("muon magnetic moment anomaly"), "1.16592062e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("muon magnetic moment to Bohr magneton ratio"), "-4.84197048e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("muon magnetic moment to nuclear magneton ratio"), "-8.89059704", ""); PUSH_CONSTANT(QT_TR_NOOP("muon mass"), "1.883531627e-28", "kg"); PUSH_CONSTANT(QT_TR_NOOP("muon mass energy equivalent"), "1.692833804e-11", "J"); PUSH_CONSTANT(QT_TR_NOOP("muon mass energy equivalent in MeV"), "105.6583755", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("muon mass in u"), "0.1134289257", "u"); PUSH_CONSTANT(QT_TR_NOOP("muon molar mass"), "1.134289258e-4", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("muon-neutron mass ratio"), "0.1124545168", ""); PUSH_CONSTANT(QT_TR_NOOP("muon-proton magnetic moment ratio"), "-3.183345146", ""); PUSH_CONSTANT(QT_TR_NOOP("muon-proton mass ratio"), "0.1126095262", ""); PUSH_CONSTANT(QT_TR_NOOP("muon-tau mass ratio"), "5.94635e-2", ""); PUSH_CONSTANT(QT_TR_NOOP("reduced muon Compton wavelength"), "1.867594306e-15", "m"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearTau); PUSH_CONSTANT(QT_TR_NOOP("reduced tau Compton wavelength"), "1.110538e-16", "m"); PUSH_CONSTANT(QT_TR_NOOP("tau Compton wavelength"), "6.97771e-16", "m"); PUSH_CONSTANT(QT_TR_NOOP("tau-electron mass ratio"), "3477.23", ""); PUSH_CONSTANT(QT_TR_NOOP("tau mass"), "3.16754e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("tau mass energy equivalent"), "2.84684e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("tau mass in u"), "1.90754", "u"); PUSH_CONSTANT(QT_TR_NOOP("tau molar mass"), "1.90754e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("tau-muon mass ratio"), "16.8170", ""); PUSH_CONSTANT(QT_TR_NOOP("tau-neutron mass ratio"), "1.89115", ""); PUSH_CONSTANT(QT_TR_NOOP("tau-proton mass ratio"), "1.89376", ""); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearProton); PUSH_CONSTANT(QT_TR_NOOP("proton charge to mass quotient"), "9.5788331430e7", "C·kgâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("proton Compton wavelength"), "1.32140985360e-15", "m"); PUSH_CONSTANT(QT_TR_NOOP("proton-electron mass ratio"), "1836.152673426", ""); PUSH_CONSTANT(QT_TR_NOOP("proton g factor (gₚ)"), "5.5856946893", ""); PUSH_CONSTANT(QT_TR_NOOP("proton gyromagnetic ratio (γₚ)"), "2.6752218708e8", "sâ�»Â¹Â·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("proton gyromagnetic ratio in MHz/T"), "42.577478461", "MHz·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("proton magnetic moment (μₚ)"), "1.41060679545e-26", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("proton magnetic moment to Bohr magneton ratio"), "1.52103220230e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("proton magnetic moment to nuclear magneton ratio"), "2.79284734463", ""); PUSH_CONSTANT(QT_TR_NOOP("proton magnetic shielding correction"), "2.56715e-5", ""); PUSH_CONSTANT(QT_TR_NOOP("proton mass (mₚ)"), "1.67262192595e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("proton mass energy equivalent"), "1.50327761802e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("proton mass energy equivalent in MeV"), "938.27208943", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("proton mass in u"), "1.0072764665789", "u"); PUSH_CONSTANT(QT_TR_NOOP("proton molar mass (Mₚ)"), "1.00727646764e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("proton-muon mass ratio"), "8.88024338", ""); PUSH_CONSTANT(QT_TR_NOOP("proton-neutron magnetic moment ratio"), "-1.45989802", ""); PUSH_CONSTANT(QT_TR_NOOP("proton-neutron mass ratio"), "0.99862347797", ""); PUSH_CONSTANT(QT_TR_NOOP("proton relative atomic mass (Ar(p))"), "1.0072764665789", ""); PUSH_CONSTANT(QT_TR_NOOP("proton rms charge radius"), "8.4075e-16", "m"); PUSH_CONSTANT(QT_TR_NOOP("proton-tau mass ratio"), "0.528051", ""); PUSH_CONSTANT(QT_TR_NOOP("reduced proton Compton wavelength"), "2.10308910051e-16", "m"); PUSH_CONSTANT(QT_TR_NOOP("shielded proton gyromagnetic ratio"), "2.675153194e8", "sâ�»Â¹Â·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("shielded proton gyromagnetic ratio in MHz/T"), "42.57638543", "MHz·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("shielded proton magnetic moment"), "1.4105705830e-26", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("shielded proton magnetic moment to Bohr magneton ratio"), "1.5209931551e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("shielded proton magnetic moment to nuclear magneton ratio"), "2.792775648", ""); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearNeutron); PUSH_CONSTANT(QT_TR_NOOP("neutron Compton wavelength"), "1.31959090382e-15", "m"); PUSH_CONSTANT(QT_TR_NOOP("neutron-electron magnetic moment ratio"), "1.04066884e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron-electron mass ratio"), "1838.68366200", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron g factor (gâ‚™)"), "-3.82608552", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron gyromagnetic ratio (γₙ)"), "1.83247174e8", "sâ�»Â¹Â·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("neutron gyromagnetic ratio in MHz/T"), "29.1646935", "MHz·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("neutron magnetic moment (μₙ)"), "-9.6623653e-27", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("neutron magnetic moment to Bohr magneton ratio"), "-1.04187565e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron magnetic moment to nuclear magneton ratio"), "-1.91304276", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron mass (mâ‚™)"), "1.67492750056e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("neutron mass energy equivalent"), "1.50534976514e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("neutron mass energy equivalent in MeV"), "939.56542194", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("neutron mass in u"), "1.00866491606", "u"); PUSH_CONSTANT(QT_TR_NOOP("neutron molar mass (Mâ‚™)"), "1.00866491712e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("neutron-muon mass ratio"), "8.89248408", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron-proton magnetic moment ratio"), "-0.68497935", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron-proton mass difference"), "2.30557461e-30", "kg"); PUSH_CONSTANT(QT_TR_NOOP("neutron-proton mass difference energy equivalent"), "2.07214712e-13", "J"); PUSH_CONSTANT(QT_TR_NOOP("neutron-proton mass difference energy equivalent in MeV"), "1.29333251", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("neutron-proton mass difference in u"), "1.38844948e-3", "u"); PUSH_CONSTANT(QT_TR_NOOP("neutron-proton mass ratio"), "1.00137841946", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron relative atomic mass (Ar(n))"), "1.00866491606", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron-tau mass ratio"), "0.528779", ""); PUSH_CONSTANT(QT_TR_NOOP("neutron to shielded proton magnetic moment ratio"), "-0.68499694", ""); PUSH_CONSTANT(QT_TR_NOOP("reduced neutron Compton wavelength"), "2.1001941520e-16", "m"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearDeuteron); PUSH_CONSTANT(QT_TR_NOOP("deuteron-electron magnetic moment ratio"), "-4.664345550e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron-electron mass ratio"), "3670.482967655", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron g factor"), "0.8574382335", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron magnetic moment"), "4.330735087e-27", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("deuteron magnetic moment to Bohr magneton ratio"), "4.669754568e-4", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron magnetic moment to nuclear magneton ratio"), "0.8574382335", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron mass"), "3.3435837768e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("deuteron mass energy equivalent"), "3.00506323491e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("deuteron mass energy equivalent in MeV"), "1875.61294500", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("deuteron mass in u"), "2.013553212544", "u"); PUSH_CONSTANT(QT_TR_NOOP("deuteron molar mass"), "2.01355321466e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("deuteron-neutron magnetic moment ratio"), "-0.44820652", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron-proton magnetic moment ratio"), "0.30701220930", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron-proton mass ratio"), "1.9990075012699", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron relative atomic mass (Ar(d))"), "2.013553212544", ""); PUSH_CONSTANT(QT_TR_NOOP("deuteron rms charge radius"), "2.12778e-15", "m"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearTriton); PUSH_CONSTANT(QT_TR_NOOP("triton-electron mass ratio"), "5496.92153551", ""); PUSH_CONSTANT(QT_TR_NOOP("triton g factor (gₜ)"), "5.957924930", ""); PUSH_CONSTANT(QT_TR_NOOP("triton magnetic moment (μₜ)"), "1.5046095178e-26", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("triton magnetic moment to Bohr magneton ratio"), "1.6223936648e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("triton magnetic moment to nuclear magneton ratio"), "2.9789624650", ""); PUSH_CONSTANT(QT_TR_NOOP("triton mass (mₜ)"), "5.0073567512e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("triton mass energy equivalent"), "4.5003878119e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("triton mass energy equivalent in MeV"), "2808.92113668", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("triton mass in u"), "3.01550071597", "u"); PUSH_CONSTANT(QT_TR_NOOP("triton molar mass (Mₜ)"), "3.01550071913e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("triton-proton mass ratio"), "2.99371703403", ""); PUSH_CONSTANT(QT_TR_NOOP("triton relative atomic mass (Ar(t))"), "3.01550071597", ""); PUSH_CONSTANT(QT_TR_NOOP("triton to proton magnetic moment ratio"), "1.0666399189", ""); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearHelion); PUSH_CONSTANT(QT_TR_NOOP("helion-electron mass ratio"), "5495.88527984", ""); PUSH_CONSTANT(QT_TR_NOOP("helion g factor (gâ‚•)"), "-4.2552506995", ""); PUSH_CONSTANT(QT_TR_NOOP("helion magnetic moment (μₕ)"), "-1.07461755198e-26", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("helion magnetic moment to Bohr magneton ratio"), "-1.15874098083e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("helion magnetic moment to nuclear magneton ratio"), "-2.1276253498", ""); PUSH_CONSTANT(QT_TR_NOOP("helion mass (mâ‚•)"), "5.0064127862e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("helion mass energy equivalent"), "4.4995394185e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("helion mass energy equivalent in MeV"), "2808.39161112", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("helion mass in u"), "3.014932246932", "u"); PUSH_CONSTANT(QT_TR_NOOP("helion molar mass (Mâ‚•)"), "3.01493225010e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("helion-proton mass ratio"), "2.993152671552", ""); PUSH_CONSTANT(QT_TR_NOOP("helion relative atomic mass (Ar(h))"), "3.014932246932", ""); PUSH_CONSTANT(QT_TR_NOOP("helion shielding shift"), "5.9967029e-5", ""); PUSH_CONSTANT(QT_TR_NOOP("shielded helion gyromagnetic ratio"), "2.0378946078e8", "sâ�»Â¹Â·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("shielded helion gyromagnetic ratio in MHz/T"), "32.434100033", "MHz·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("shielded helion magnetic moment"), "-1.07455311035e-26", "J·Tâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("shielded helion magnetic moment to Bohr magneton ratio"), "-1.15867149457e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("shielded helion magnetic moment to nuclear magneton ratio"), "-2.1274977624", ""); PUSH_CONSTANT(QT_TR_NOOP("shielded helion to proton magnetic moment ratio"), "-0.76176657721", ""); PUSH_CONSTANT(QT_TR_NOOP("shielded helion to shielded proton magnetic moment ratio"), "-0.7617861334", ""); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearAlphaParticle); PUSH_CONSTANT(QT_TR_NOOP("alpha particle mass"), "6.6446573450e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("alpha particle mass in u"), "4.001506179129", "u"); PUSH_CONSTANT(QT_TR_NOOP("alpha particle mass energy equivalent"), "5.9719201997e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("alpha particle mass energy equivalent in MeV"), "3727.3794118", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("alpha particle-electron mass ratio"), "7294.29954171", ""); PUSH_CONSTANT(QT_TR_NOOP("alpha particle-proton mass ratio"), "3.972599690252", ""); PUSH_CONSTANT(QT_TR_NOOP("alpha particle rms charge radius"), "1.6785e-15", "m"); PUSH_CONSTANT(QT_TR_NOOP("alpha particle molar mass"), "4.0015061833e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("alpha particle relative atomic mass (Ar(α))"), "4.001506179129", ""); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::Physicochemical); PUSH_CONSTANT(QT_TR_NOOP("atomic mass constant (mᵤ)"), "1.66053906892e-27", "kg"); PUSH_CONSTANT(QT_TR_NOOP("Avogadro constant"), "6.02214076e23", "molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Boltzmann constant (k)"), "1.380649e-23", "J·Kâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Boltzmann constant in eV/K"), "8.617333262e-5", "eV·Kâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Boltzmann constant in Hz/K"), "2.083661912e10", "Hz·Kâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Boltzmann constant in inverse meter per kelvin"), "69.50348004", "mâ�»Â¹Â·Kâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("electron volt (eV)"), "1.602176634e-19", "J"); PUSH_CONSTANT(QT_TR_NOOP("Faraday constant (F)"), "96485.33212", "C·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("first radiation constant (câ‚�)"), "3.741771852e-16", "W·m²"); PUSH_CONSTANT(QT_TR_NOOP("first radiation constant for spectral radiance"), "1.191042972e-16", "W·m²·srâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("molar gas constant (R)"), "8.314462618", "J·Kâ�»Â¹Â·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Loschmidt constant (nâ‚€, 273.15 K, 100 kPa)"), "2.6516467e25", "mâ�»Â³"); PUSH_CONSTANT(QT_TR_NOOP("Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa)"), "2.6867811e25", "mâ�»Â³"); PUSH_CONSTANT(QT_TR_NOOP("molar Planck constant"), "3.990312712e-10", "J·s·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("second radiation constant (câ‚‚)"), "1.438776877e-2", "m·K"); PUSH_CONSTANT(QT_TR_NOOP("Stefan-Boltzmann constant (σ)"), "5.670374419e-8", "W·mâ�»Â²Â·Kâ�»â�´"); PUSH_CONSTANT(QT_TR_NOOP("lattice spacing of ideal Si (dâ‚‚â‚‚â‚€)"), "1.920155716e-10", "m"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass constant energy equivalent"), "1.49241808768e-10", "J"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass constant energy equivalent in MeV"), "931.49410372", "MeV"); PUSH_CONSTANT(QT_TR_NOOP("atomic mass unit-electron volt relationship"), "9.3149410372e8", "eV"); PUSH_CONSTANT(QT_TR_NOOP("molar mass constant (Mᵤ)"), "1.00000000105e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("molar mass of carbon-12"), "12.0000000126e-3", "kg·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("molar volume of ideal gas (273.15 K, 100 kPa)"), "22.71095464e-3", "m³·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("molar volume of ideal gas (273.15 K, 101.325 kPa)"), "22.41396954e-3", "m³·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("molar volume of silicon"), "1.205883199e-5", "m³·molâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Sackur-Tetrode constant (1 K, 100 kPa)"), "-1.15170753496", ""); PUSH_CONSTANT(QT_TR_NOOP("Sackur-Tetrode constant (1 K, 101.325 kPa)"), "-1.16487052149", ""); PUSH_CONSTANT(QT_TR_NOOP("Wien frequency displacement law constant"), "5.878925757e10", "Hz·Kâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("Wien wavelength displacement law constant"), "2.897771955e-3", "m·K"); PUSH_CONSTANT(QT_TR_NOOP("standard atmosphere (atm)"), "101325", "Pa"); PUSH_CONSTANT(QT_TR_NOOP("standard-state pressure (p°)"), "100000", "Pa"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearXrayUnits); PUSH_CONSTANT(QT_TR_NOOP("Angstrom star (Ã…*)"), "1.00001495e-10", "m"); PUSH_CONSTANT(QT_TR_NOOP("Copper x unit"), "1.00207697e-13", "m"); PUSH_CONSTANT(QT_TR_NOOP("Molybdenum x unit"), "1.00209952e-13", "m"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearAtomicUnits); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of magnetizability"), "7.8910365794e-29", "J·Tâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of mass (mâ‚‘)"), "9.1093837139e-31", "kg"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of momentum"), "1.99285191545e-24", "kg·m·sâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of permittivity"), "1.11265005620e-10", "F·mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of time"), "2.4188843265864e-17", "s"); PUSH_CONSTANT(QT_TR_NOOP("atomic unit of velocity"), "2.18769126216e6", "m·sâ�»Â¹"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearEnergyConversionRelationships); PUSH_CONSTANT(QT_TR_NOOP("hartree-hertz relationship"), "6.5796839204999e15", "Hz"); PUSH_CONSTANT(QT_TR_NOOP("hartree-inverse meter relationship"), "2.1947463136314e7", "mâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("hartree-joule relationship"), "4.3597447222060e-18", "J"); PUSH_CONSTANT(QT_TR_NOOP("hartree-kelvin relationship"), "3.1577502480398e5", "K"); PUSH_CONSTANT(QT_TR_NOOP("hartree-kilogram relationship"), "4.8508702095419e-35", "kg"); SET_CONSTANT_CONTEXT(ConstantDomain::PhysicsCodata2022, ConstantSubdomain::AtomicNuclearMagneticShieldingCorrections); PUSH_CONSTANT(QT_TR_NOOP("shielding difference of d and p in HD"), "1.98770e-8", ""); PUSH_CONSTANT(QT_TR_NOOP("shielding difference of t and p in HT"), "2.39450e-8", ""); // Mathematics. SET_CONSTANT_CONTEXT(ConstantDomain::Mathematics, ConstantSubdomain::None); PUSH_CONSTANT(QT_TR_NOOP("pi (Ï€)"), "3.14159265358979323846264338327950288419716939937511", ""); PUSH_CONSTANT(QT_TR_NOOP("Euler's number (e)"), "2.71828182845904523536028747135266249775724709369996", ""); PUSH_CONSTANT(QT_TR_NOOP("golden ratio (φ)"), "1.61803398874989484820458683436563811772030917980576", ""); PUSH_CONSTANT(QT_TR_NOOP("Euler-Mascheroni constant (γ)"), "0.57721566490153286060651209008240243104215933593992", ""); // Astronomy. SET_CONSTANT_CONTEXT(ConstantDomain::Astronomy, ConstantSubdomain::AstronomyNominalIau2015); PUSH_CONSTANT(QT_TR_NOOP("nominal solar radius"), "6.957e8", "m"); PUSH_CONSTANT(QT_TR_NOOP("nominal solar total irradiance"), "1361", "W·mâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("nominal solar luminosity"), "3.828e26", "W"); PUSH_CONSTANT(QT_TR_NOOP("nominal solar effective temperature"), "5772", "K"); PUSH_CONSTANT(QT_TR_NOOP("nominal solar mass parameter"), "1.3271244e20", "m³·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("nominal terrestrial equatorial radius"), "6.3781e6", "m"); PUSH_CONSTANT(QT_TR_NOOP("nominal terrestrial polar radius"), "6.3568e6", "m"); PUSH_CONSTANT(QT_TR_NOOP("nominal terrestrial mass parameter"), "3.986004e14", "m³·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("nominal jovian equatorial radius"), "7.1492e7", "m"); PUSH_CONSTANT(QT_TR_NOOP("nominal jovian polar radius"), "6.6854e7", "m"); PUSH_CONSTANT(QT_TR_NOOP("nominal jovian mass parameter"), "1.2668653e17", "m³·sâ�»Â²"); SET_CONSTANT_CONTEXT(ConstantDomain::Astronomy, ConstantSubdomain::AstronomyCurrentBestEstimatesIauNsfa202604); PUSH_CONSTANT(QT_TR_NOOP("average value of one minus the rate of TCG relative to TCB"), "1.48082686741e-8", ""); PUSH_CONSTANT(QT_TR_NOOP("solar mass parameter (TCB-compatible)"), "1.32712442099e20", "m³·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("solar mass parameter (TDB-compatible)"), "1.32712440041e20", "m³·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("equatorial radius of the Earth (TT-compatible)"), "6.3781366e6", "m"); PUSH_CONSTANT(QT_TR_NOOP("dynamical form factor of the Earth"), "1.0826359e-3", ""); PUSH_CONSTANT(QT_TR_NOOP("time rate of change in the dynamical form factor of the Earth"), "-3.0e-9", "cy_julâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("geocentric gravitational constant (TCB-compatible)"), "3.986004418e14", "m³·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("geocentric gravitational constant (TT-compatible)"), "3.986004415e14", "m³·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("geocentric gravitational constant (TDB-compatible)"), "3.986004356e14", "m³·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("potential of the geoid"), "62636853.4", "m²·sâ�»Â²"); PUSH_CONSTANT(QT_TR_NOOP("nominal mean angular velocity of the Earth (TT-compatible)"), "7.292115e-5", "rad·sâ�»Â¹"); PUSH_CONSTANT(QT_TR_NOOP("ratio mass of the Moon to the Earth"), "1.23000371e-2", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to Mercury"), "6.023657330e6", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to Venus"), "4.08523719e5", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to Mars"), "3.09870359e6", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to Jupiter"), "1.047348644e3", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to Saturn"), "3.4979018e3", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to Uranus"), "2.2902951e4", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to Neptune"), "1.941226e4", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to (134340) Pluto"), "1.3605e8", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of the Sun to (136199) Eris"), "1.191e8", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of (1) Ceres to the Sun"), "4.72e-10", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of (2) Pallas to the Sun"), "1.03e-10", ""); PUSH_CONSTANT(QT_TR_NOOP("ratio of the mass of (4) Vesta to the Sun"), "1.3026846e-10", ""); PUSH_CONSTANT(QT_TR_NOOP("mean obliquity of the ecliptic at J2000.0"), "84381.406", "arcsec"); domains << domainToDisplay(ConstantDomain::Mathematics) << domainToDisplay(ConstantDomain::PhysicsCodata2022) // << domainToDisplay(ConstantDomain::ChemistryIupacCiaaw2021) << domainToDisplay(ConstantDomain::Astronomy); } void Constants::Private::retranslateText() { populate(); } Constants* Constants::instance() { if (!s_constantsInstance) { s_constantsInstance = new Constants; qAddPostRoutine(s_deleteConstants); } return s_constantsInstance; } Constants::Constants() : d(new Constants::Private) { StartupDiagnostics::Scope timing("Initialize built-in constants"); setObjectName("Constants"); d->retranslateText(); } const QList& Constants::list() const { return d->list; } const QStringList& Constants::domains() const { return d->domains; } QStringList Constants::subdomains(const QString& domain) const { if (domain == domainToDisplay(ConstantDomain::PhysicsCodata2022)) { return QStringList{ subdomainToDisplay(ConstantSubdomain::Universal), subdomainToDisplay(ConstantSubdomain::Electromagnetic), subdomainToDisplay(ConstantSubdomain::Physicochemical), subdomainToDisplay(ConstantSubdomain::AtomicNuclearGeneral), subdomainToDisplay(ConstantSubdomain::AtomicNuclearElectroweak), subdomainToDisplay(ConstantSubdomain::AtomicNuclearElectron), subdomainToDisplay(ConstantSubdomain::AtomicNuclearMuon), subdomainToDisplay(ConstantSubdomain::AtomicNuclearTau), subdomainToDisplay(ConstantSubdomain::AtomicNuclearProton), subdomainToDisplay(ConstantSubdomain::AtomicNuclearNeutron), subdomainToDisplay(ConstantSubdomain::AtomicNuclearDeuteron), subdomainToDisplay(ConstantSubdomain::AtomicNuclearTriton), subdomainToDisplay(ConstantSubdomain::AtomicNuclearHelion), subdomainToDisplay(ConstantSubdomain::AtomicNuclearAlphaParticle), subdomainToDisplay(ConstantSubdomain::AtomicNuclearAtomicUnits), subdomainToDisplay(ConstantSubdomain::AtomicNuclearEnergyConversionRelationships), subdomainToDisplay(ConstantSubdomain::AtomicNuclearXrayUnits), subdomainToDisplay(ConstantSubdomain::AtomicNuclearMagneticShieldingCorrections), }; } if (domain == domainToDisplay(ConstantDomain::ChemistryIupacCiaaw2021)) { return QStringList{ subdomainToDisplay(ConstantSubdomain::MolarMasses), subdomainToDisplay(ConstantSubdomain::Electronegativity), subdomainToDisplay(ConstantSubdomain::IonizationEnergy) }; } if (domain == domainToDisplay(ConstantDomain::Astronomy)) { return QStringList{ subdomainToDisplay(ConstantSubdomain::AstronomyNominalIau2015), subdomainToDisplay(ConstantSubdomain::AstronomyCurrentBestEstimatesIauNsfa202604), }; } return QStringList(); } void Constants::retranslateText() { d->retranslateText(); } Constants::~Constants() { } heldercorreia-speedcrunch-e7ca37f/src/core/constants.h000066400000000000000000000033761526573132500232520ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2013-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_CONSTANTS_H #define CORE_CONSTANTS_H #include #include #include enum class ConstantDomain { Uncategorized, Mathematics, PhysicsCodata2022, ChemistryIupacCiaaw2021, Astronomy }; enum class ConstantSubdomain { None, Universal, Electromagnetic, Physicochemical, AtomicNuclearGeneral, AtomicNuclearElectroweak, AtomicNuclearElectron, AtomicNuclearMuon, AtomicNuclearTau, AtomicNuclearProton, AtomicNuclearNeutron, AtomicNuclearDeuteron, AtomicNuclearTriton, AtomicNuclearHelion, AtomicNuclearAlphaParticle, AtomicNuclearAtomicUnits, AtomicNuclearEnergyConversionRelationships, AtomicNuclearXrayUnits, AtomicNuclearMagneticShieldingCorrections, Masses, Lifetimes, MolarMasses, Electronegativity, IonizationEnergy, AstronomyNominalIau2015, AstronomyCurrentBestEstimatesIauNsfa202604 }; struct Constant { ConstantDomain domainType = ConstantDomain::Uncategorized; ConstantSubdomain subdomainType = ConstantSubdomain::None; QString domain; QString subdomain; QString name; QString unit; QString value; }; class Constants : public QObject { Q_OBJECT public: ~Constants(); // For unique_ptr, define after Private is complete. static Constants* instance(); const QStringList& domains() const; QStringList subdomains(const QString& domain) const; const QList& list() const; public slots: void retranslateText(); private: struct Private; std::unique_ptr d; Constants(); Q_DISABLE_COPY(Constants) }; #endif heldercorreia-speedcrunch-e7ca37f/src/core/errors.h000066400000000000000000000102471526573132500225450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008, 2013, 2015, 2019, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef _SCERRORS_H #define _SCERRORS_H #ifdef __cplusplus extern "C"{ #endif typedef enum { Success = 0, /* a NaN or an empty Variant was submitted as a parameter. Only a few functions in the math engine accept such a value. All arithmetic functions fail on such an operand */ NoOperand, /* This error is returned if a result is mathematically defined, but cannot be computed reliably without extending the working precision considerably and/or requiring considerable computing time */ EvalUnstable, /* the result is in absolute value smaller than the smallest non-zero value the math engine can handle */ Underflow, /* the result is in absolute value bigger than the biggest number the math engine can handle */ Overflow, /* operation requests a division by zero, or a function was evaluated at a pole */ ZeroDivide, /* One or more parameters to a function lie outside of the function's domain */ OutOfDomain, /* a number exceeds the logic number range, so logic operations cannot be applied */ OutOfLogicRange, /* a number or a result exceeds the integer range */ OutOfIntegerRange, /* This error indicates a failed conversion from an ASCII string. Functions setting this error may also report a more detailed IO... error code*/ BadLiteral, /* A request to calculate something to more places than is (currently) acceptable */ InvalidPrecision, /* A parameter violates the limitations of the engine, or is completely meaningless, e.g. the evaluation of a quotient and a remainder in the same variable. This error indicates a bug, because the calling program should never submit such a parameter (combinations) */ InvalidParam, /* returned when an operation request is mathematically valid, but would require too much time */ TooExpensive, /* For correct conversion of a digit sequence, the IO routines need information about the radix to use. This error is returned if none was specified. This error indicates a bug, because a calling routine should always supply this information */ IONoBase, /* This error occurs if you request a two's complement conversion, and either additionally specify a sign, or gave a non-zero fraction */ IOInvalidComplement, /* You must specify at least one digit of the significant */ IONoSignificand, /* invalid characters in exponent, e.g. a decimal dot */ IOBadExp, /* the exponent exceeds the allowed range */ IOExpOverflow, /* internal (string) buffer overflow in a conversion. This indicates a bug because range checking should be done in advance */ IOBufferOverflow, /* request to convert more digits to another base than internal buffers can hold. This occurs when you try to convert huge values in fixpoint format */ IOConversionOverflow, /* request to convert a tiny number in fixpoint format, so that only leading zeros are displayed. */ IOConversionUnderflow, /* a function was called with the wrong count of parameters e.g. sin(12;13) (sin takes only 1 parameter) */ InvalidParamCount, /* parameter type mismatch */ TypeMismatch, /* occurs if quantities of different dimensions are compared, added, converted, etc. */ DimensionMismatch, /* occurs if a non dimensionless quantity is fed to a function that requires dimensoinless arguments, or if an invalid unit is specified */ InvalidDimension, /* cannot overwrite an existing key in a table */ // KeyExists, /* could not retrieve a symbol by the submitted key */ // SymbolNotFound, /* no matching close token for an open token */ // CloseSymbolMissing, /* unable to clone a symbol, most probably because it was of a special type, like a close parenthesis */ // SymbolCloneError, /* unable to perform a requested type cast */ // BadCast, /* used with variants, when an operation is not implemented for a particular data type. used with formats to indicate a not implemented property */ NotImplemented, /* this value is used internally to indicate the absence of any error information altogether */ NotAnError, /* */ } Error; #ifdef __cplusplus } #endif #endif /* _SCERRORS_H */ heldercorreia-speedcrunch-e7ca37f/src/core/evaluator.cpp000066400000000000000000012206411526573132500235700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2011, 2013-2018, 2020, 2022, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "core/evaluator.h" #include "core/constants.h" #include "core/regexpatterns.h" #include "core/settings.h" #include "core/unitdisplayformat.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include "core/numberformatter.h" #include "math/rational.h" #include "core/units.h" #include #include #include #include #include #include #define ALLOW_IMPLICIT_MULT static constexpr int MAX_PRECEDENCE = INT_MAX; static constexpr int INVALID_PRECEDENCE = INT_MIN; static bool isSubscriptDigit(QChar ch); static bool isSubscriptLetter(QChar ch); static bool isIdentifierStart(QChar ch); static bool isIdentifierContinue(QChar ch); static QString superscriptDigitsToAscii(const QString& text); static bool normalizeUnsignedIntegerEquivalentDecimalText(QString& text); static QString rewriteListBracesToInternalCalls(const QString& text); static Quantity s_cisFromAngle(Quantity angle) { const bool convertedExplicitAngleUnit = Units::tryConvertExplicitAngleToRadians(&angle); if (!convertedExplicitAngleUnit && Settings::instance()->angleUnit == 'd') { if (angle.isReal()) angle = DMath::deg2rad(angle); } else if (!convertedExplicitAngleUnit && Settings::instance()->angleUnit == 'g') { if (angle.isReal()) angle = DMath::gon2rad(angle); } else if (!convertedExplicitAngleUnit && (Settings::instance()->angleUnit == 't' || Settings::instance()->angleUnit == 'v')) { if (angle.isReal()) angle *= Quantity(2) * DMath::pi(); } Quantity result = DMath::cos(angle) + (DMath::i() * DMath::sin(angle)); result.stripUnits(); return result; } #ifdef EVALUATOR_DEBUG #include #include #include QTextStream& operator<<(QTextStream& s, Quantity num) { s << DMath::format(num, Quantity::Format::Fixed()); return s; } #endif // EVALUATOR_DEBUG static Evaluator* s_evaluatorInstance = 0; static void s_deleteEvaluator() { delete s_evaluatorInstance; } static bool s_isSummationFunctionIdentifier(const QString& identifier) { return FunctionRepo::instance()->isIdentifierAliasOf(identifier, QStringLiteral("summation")); } static bool s_isMolmassFunctionIdentifier(const QString& identifier) { return FunctionRepo::instance()->isIdentifierAliasOf(identifier, QStringLiteral("molmass")); } static bool s_isMassFunctionIdentifier(const QString& identifier) { return FunctionRepo::instance()->isIdentifierAliasOf(identifier, QStringLiteral("mass")); } static bool s_isUpperAsciiLetter(QChar ch) { return ch >= QLatin1Char('A') && ch <= QLatin1Char('Z'); } static bool s_isLowerAsciiLetter(QChar ch) { return ch >= QLatin1Char('a') && ch <= QLatin1Char('z'); } static bool s_isAsciiDigit(QChar ch) { return ch >= QLatin1Char('0') && ch <= QLatin1Char('9'); } static const QHash& s_molmassElementWeights() { static const QHash weights = [] { struct Entry { const char* symbol; const char* mass; }; static const Entry entries[] = { {"H", "1.008"}, {"He", "4.0026"}, {"Li", "6.94"}, {"Be", "9.0122"}, {"B", "10.81"}, {"C", "12.011"}, {"N", "14.007"}, {"O", "15.999"}, {"F", "18.998"}, {"Ne", "20.180"}, {"Na", "22.990"}, {"Mg", "24.305"}, {"Al", "26.982"}, {"Si", "28.085"}, {"P", "30.974"}, {"S", "32.06"}, {"Cl", "35.45"}, {"Ar", "39.948"}, {"K", "39.098"}, {"Ca", "40.078"}, {"Sc", "44.956"}, {"Ti", "47.867"}, {"V", "50.942"}, {"Cr", "51.996"}, {"Mn", "54.938"}, {"Fe", "55.845"}, {"Co", "58.933"}, {"Ni", "58.693"}, {"Cu", "63.546"}, {"Zn", "65.38"}, {"Ga", "69.723"}, {"Ge", "72.630"}, {"As", "74.922"}, {"Se", "78.971"}, {"Br", "79.904"}, {"Kr", "83.798"}, {"Rb", "85.468"}, {"Sr", "87.62"}, {"Y", "88.906"}, {"Zr", "91.224"}, {"Nb", "92.906"}, {"Mo", "95.95"}, {"Tc", "98"}, {"Ru", "101.07"}, {"Rh", "102.91"}, {"Pd", "106.42"}, {"Ag", "107.87"}, {"Cd", "112.41"}, {"In", "114.82"}, {"Sn", "118.71"}, {"Sb", "121.76"}, {"Te", "127.60"}, {"I", "126.90"}, {"Xe", "131.29"}, {"Cs", "132.91"}, {"Ba", "137.33"}, {"La", "138.91"}, {"Ce", "140.12"}, {"Pr", "140.91"}, {"Nd", "144.24"}, {"Pm", "145"}, {"Sm", "150.36"}, {"Eu", "151.96"}, {"Gd", "157.25"}, {"Tb", "158.93"}, {"Dy", "162.50"}, {"Ho", "164.93"}, {"Er", "167.26"}, {"Tm", "168.93"}, {"Yb", "173.05"}, {"Lu", "174.97"}, {"Hf", "178.49"}, {"Ta", "180.95"}, {"W", "183.84"}, {"Re", "186.21"}, {"Os", "190.23"}, {"Ir", "192.22"}, {"Pt", "195.08"}, {"Au", "196.97"}, {"Hg", "200.59"}, {"Tl", "204.38"}, {"Pb", "207.2"}, {"Bi", "208.98"}, {"Po", "209"}, {"At", "210"}, {"Rn", "222"}, {"Fr", "223"}, {"Ra", "226"}, {"Ac", "227"}, {"Th", "232.04"}, {"Pa", "231.04"}, {"U", "238.03"}, {"Np", "237"}, {"Pu", "244"}, {"Am", "243"}, {"Cm", "247"}, {"Bk", "247"}, {"Cf", "251"}, {"Es", "252"}, {"Fm", "257"}, {"Md", "258"}, {"No", "259"}, {"Lr", "266"}, {"Rf", "267"}, {"Db", "268"}, {"Sg", "269"}, {"Bh", "270"}, {"Hs", "277"}, {"Mt", "278"}, {"Ds", "281"}, {"Rg", "282"}, {"Cn", "285"}, {"Nh", "286"}, {"Fl", "289"}, {"Mc", "290"}, {"Lv", "293"}, {"Ts", "294"}, {"Og", "294"} }; QHash table; table.reserve(static_cast(sizeof(entries) / sizeof(entries[0]))); for (const Entry& entry : entries) table.insert(QString::fromLatin1(entry.symbol), HNumber(entry.mass)); return table; }(); return weights; } static bool s_tryParseMolarMassFormula(const QString& formulaText, Quantity* outMass) { if (!outMass) return false; QString formula = formulaText.trimmed(); if (formula.isEmpty()) return false; for (int i = 0; i < formula.size(); ++i) { const QChar ch = formula.at(i); if (s_isUpperAsciiLetter(ch) || s_isLowerAsciiLetter(ch) || s_isAsciiDigit(ch)) { continue; } if (isSubscriptDigit(ch)) { formula[i] = QChar(MathDsl::Dig0.unicode() + (ch.unicode() - UnicodeChars::SubscriptZero.unicode())); continue; } return false; } const auto& weights = s_molmassElementWeights(); HNumber totalMass(0); int pos = 0; while (pos < formula.size()) { if (!s_isUpperAsciiLetter(formula.at(pos))) return false; QString symbol; symbol += formula.at(pos); ++pos; if (pos < formula.size() && s_isLowerAsciiLetter(formula.at(pos))) { symbol += formula.at(pos); ++pos; } const auto symbolIt = weights.constFind(symbol); if (symbolIt == weights.constEnd()) return false; QString countDigits; while (pos < formula.size() && s_isAsciiDigit(formula.at(pos))) { countDigits += formula.at(pos); ++pos; } if (!countDigits.isEmpty() && countDigits.startsWith(QLatin1Char('0'))) return false; const HNumber count = countDigits.isEmpty() ? HNumber(1) : HNumber(countDigits.toLatin1().constData()); totalMass += symbolIt.value() * count; } const Quantity gramsPerMole = Units::gram() / Units::mole(); Quantity mass = Quantity(totalMass) * gramsPerMole; QString gramsPerMoleSymbol; if (runtimeUnitNegativeExponentStyle() == Settings::UnitNegativeExponentSuperscript) { gramsPerMoleSymbol = QString(::unitSymbol(UnitId::Gram)) + QLatin1Char(' ') + QString(::unitSymbol(UnitId::Mole)) + QString(MathDsl::PowNeg) + QString(MathDsl::Pow1); } else { gramsPerMoleSymbol = QString(::unitSymbol(UnitId::Gram)) + MathDsl::DivOp + QString(::unitSymbol(UnitId::Mole)); } mass.setDisplayUnit(gramsPerMole.numericValue(), gramsPerMoleSymbol); *outMass = mass; return true; } static QString s_toSuperscriptExponent(int exponent) { QString result; if (exponent < 0) result += MathDsl::PowNeg; for (const QChar& digit : QString::number(qAbs(exponent))) result += MathDsl::asciiDigitToSuperscript(digit); return result; } static QString s_renderUnitExponentsAsSuperscripts(QString text) { static const QRegularExpression caretExponentRe( QStringLiteral(R"(\^\(([−-]?\d+)\)|\^([−-]?\d+))")); int offset = 0; while (true) { const QRegularExpressionMatch match = caretExponentRe.match(text, offset); if (!match.hasMatch()) break; QString expText = match.captured(1); if (expText.isEmpty()) expText = match.captured(2); expText.replace(MathDsl::SubOp, MathDsl::SubOpAl1); // Unicode minus. bool ok = false; const int exponent = expText.toInt(&ok); if (!ok) { offset = match.capturedEnd(); continue; } text.replace(match.capturedStart(), match.capturedLength(), s_toSuperscriptExponent(exponent)); offset = match.capturedStart() + 1; } return text; } static int s_parseSuperscriptExponent(const QString& exponentText, bool* ok) { *ok = false; if (exponentText.isEmpty()) return 0; bool negative = false; int pos = 0; if (exponentText.at(0) == MathDsl::PowNeg || exponentText.at(0) == MathDsl::PowPos) { negative = exponentText.at(0) == MathDsl::PowNeg; pos = 1; } if (pos >= exponentText.size()) return 0; QString ascii; ascii.reserve(exponentText.size() - pos); for (; pos < exponentText.size(); ++pos) { const QChar ch = exponentText.at(pos); const QChar asciiDigit = MathDsl::superscriptDigitToAscii(ch); if (asciiDigit.isNull()) return 0; ascii += asciiDigit; } bool intOk = false; const int value = ascii.toInt(&intOk); if (!intOk) return 0; *ok = true; return negative ? -value : value; } static QString s_negateUnitFactorExponent(QString factor) { factor = factor.trimmed(); if (factor.isEmpty()) return factor; static const QRegularExpression caretExponentRe( QStringLiteral(R"(^(.*?)(?:\^\(([−-]?\d+)\)|\^([−-]?\d+))$)")); const QRegularExpressionMatch caretMatch = caretExponentRe.match(factor); if (caretMatch.hasMatch()) { QString expText = caretMatch.captured(2); if (expText.isEmpty()) expText = caretMatch.captured(3); expText.replace(MathDsl::SubOp, MathDsl::SubOpAl1); bool ok = false; const int exponent = expText.toInt(&ok); if (ok) return caretMatch.captured(1) + MathDsl::PowOp + QString::number(-exponent); } int suffixStart = factor.size(); while (suffixStart > 0) { const QChar ch = factor.at(suffixStart - 1); const bool isSuperscriptDigit = MathDsl::isSuperscriptDigit(ch); const bool isSuperscriptSign = MathDsl::isSuperscriptSign(ch); if (!isSuperscriptDigit && !isSuperscriptSign) break; --suffixStart; } if (suffixStart < factor.size()) { bool ok = false; const int exponent = s_parseSuperscriptExponent(factor.mid(suffixStart), &ok); if (ok) return factor.left(suffixStart) + MathDsl::PowOp + QString::number(-exponent); } return factor + QLatin1String("^-1"); } static QString s_applySuperscriptStyleToExplicitUnitText(QString unitText) { if (!unitText.contains(MathDsl::DivOp)) return s_renderUnitExponentsAsSuperscripts(unitText); QStringList parts = unitText.split(MathDsl::DivOp); if (parts.isEmpty()) return s_renderUnitExponentsAsSuperscripts(unitText); QString normalized = parts.takeFirst().trimmed(); for (QString denominator : parts) { denominator = denominator.trimmed(); if (denominator.startsWith(MathDsl::GroupStart) && denominator.endsWith(MathDsl::GroupEnd)) denominator = denominator.mid(1, denominator.size() - 2).trimmed(); denominator.replace(MathDsl::MulDotOp, MathDsl::MulOpAl1); const QStringList factors = denominator.split(MathDsl::MulOpAl1, Qt::SkipEmptyParts); for (const QString& rawFactor : factors) { const QString negated = s_negateUnitFactorExponent(rawFactor); if (negated.isEmpty()) continue; if (!normalized.isEmpty()) normalized += MathDsl::MulOpAl1; normalized += negated; } } QString rendered = s_renderUnitExponentsAsSuperscripts(normalized); rendered.replace(MathDsl::MulOpAl1, MathDsl::MulDotOp); return rendered; } static bool s_isOpeningUnitBracketToken(const Token& token) { return token.asOperator() == Token::AssociationStart && token.text() == QString(MathDsl::UnitStart); } static bool s_isClosingUnitBracketToken(const Token& token) { return token.asOperator() == Token::AssociationEnd && token.text() == QString(MathDsl::UnitEnd); } static bool s_isOpeningListBraceToken(const Token& token) { return token.asOperator() == Token::AssociationStart && token.text() == QLatin1String("{"); } static bool s_isClosingListBraceToken(const Token& token) { return token.asOperator() == Token::AssociationEnd && token.text() == QLatin1String("}"); } static QHash s_buildBuiltInUnitLookup(char angleMode) { StartupDiagnostics::Scope timing("Build evaluator unit lookup"); return Units::builtInUnitLookup(angleMode); } static const QHash& s_builtInUnitLookup() { static char cachedAngleMode = '\0'; static QHash cache; const char angleMode = Settings::instance()->angleUnit; if (cache.isEmpty() || cachedAngleMode != angleMode) { cache = s_buildBuiltInUnitLookup(angleMode); cachedAngleMode = angleMode; } return cache; } static bool s_tryGetBuiltInUnitQuantity(const QString& identifier, Quantity* valueOut) { const auto& lookup = s_builtInUnitLookup(); const auto it = lookup.constFind(identifier); if (it == lookup.constEnd()) return false; if (valueOut) *valueOut = it.value(); return true; } static bool s_isBuiltInUnitIdentifier(const QString& identifier) { return s_builtInUnitLookup().contains(identifier); } static QString rewriteListBracesToInternalCalls(const QString& text) { QString result; result.reserve(text.size()); bool inComment = false; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::CommentSep) inComment = true; if (!inComment && ch == MathDsl::ListStart) { result += QStringLiteral("list("); } else if (!inComment && ch == MathDsl::ListEnd) { result += MathDsl::GroupEnd; } else { result += ch; } } return result; } static bool s_isUserUnitLhsTokens(const Tokens& tokens) { return tokens.count() > 4 && tokens.at(0).asOperator() == Token::AssociationStart && tokens.at(0).text() == QString(MathDsl::UnitStart) && tokens.at(1).isUnitIdentifier() && tokens.at(2).asOperator() == Token::AssociationEnd && tokens.at(2).text() == QString(MathDsl::UnitEnd) && tokens.at(3).asOperator() == Token::Assignment; } static bool s_isBracketedExpression(const QString& text) { const QString trimmed = text.trimmed(); if (trimmed.size() < 2 || trimmed.at(0) != MathDsl::UnitStart || trimmed.at(trimmed.size() - 1) != MathDsl::UnitEnd) { return false; } int depth = 0; for (int i = 0; i < trimmed.size(); ++i) { const QChar ch = trimmed.at(i); if (ch == MathDsl::UnitStart) { ++depth; } else if (ch == MathDsl::UnitEnd) { --depth; if (depth < 0) return false; if (depth == 0 && i != trimmed.size() - 1) return false; } } return depth == 0; } static bool splitUserFunctionDescription(const QString& expression, QString* expressionWithoutDescription, QString* description) { const int equalsPos = expression.indexOf(MathDsl::Equals); if (equalsPos < 0) return false; const QString leftSide = expression.left(equalsPos); if (!leftSide.contains('(') || !leftSide.contains(')')) return false; int depth = 0; const int n = expression.size(); for (int i = equalsPos + 1; i < n; ++i) { const QChar ch = expression.at(i); if (ch == '(') { ++depth; } else if (ch == ')' && depth > 0) { --depth; } else if (ch == MathDsl::CommentSep && depth == 0) { *expressionWithoutDescription = expression.left(i).trimmed(); *description = expression.mid(i + 1).trimmed(); return true; } } return false; } static bool splitVariableDescription(const QString& expression, QString* expressionWithoutDescription, QString* description) { const int equalsPos = expression.indexOf(MathDsl::Equals); if (equalsPos < 0) return false; const QString leftSide = expression.left(equalsPos).trimmed(); if (leftSide.contains('(') || leftSide.contains(')')) return false; int depth = 0; const int n = expression.size(); for (int i = equalsPos + 1; i < n; ++i) { const QChar ch = expression.at(i); if (ch == '(') { ++depth; } else if (ch == ')' && depth > 0) { --depth; } else if (ch == MathDsl::CommentSep && depth == 0) { *expressionWithoutDescription = expression.left(i).trimmed(); *description = expression.mid(i + 1).trimmed(); return true; } } return false; } static int findTopLevelCommentDelimiterPos(const QString& text) { int depth = 0; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; continue; } if (ch != MathDsl::CommentSep || depth != 0) continue; const bool hasLeftWhitespace = i > 0 && text.at(i - 1).isSpace(); const bool hasRightWhitespace = i + 1 >= text.size() || text.at(i + 1).isSpace(); if (hasLeftWhitespace && hasRightWhitespace) return i; } return -1; } static bool s_isSubtractionOperatorAlias(const QChar& ch) { return ch == MathDsl::SubOpAl1 || ch == MathDsl::SubOp; } static bool s_isMultiplicationOperatorAlias(const QChar& ch, bool keepDotOperator = false) { switch (ch.unicode()) { case MathDsl::MulOpAl1.unicode(): case MathDsl::MulCrossOp.unicode(): return true; case MathDsl::MulDotOp.unicode(): return !keepDotOperator; default: return false; } } static bool s_isExpressionOperatorOrSeparator(const QChar& ch) { return ch == MathDsl::AddOp || ch == MathDsl::SubOp || ch == MathDsl::MulDotOp || ch == MathDsl::DivOp || ch == MathDsl::PhasorOp || ch == MathDsl::PercentOp || ch == MathDsl::PowOp || ch == MathDsl::BitAndOp || ch == MathDsl::BitOrOp || ch == MathDsl::Equals || ch == MathDsl::GreaterThanOp || ch == MathDsl::LessThanOp || ch == MathDsl::UnitStart || ch == MathDsl::UnitEnd || ch == MathDsl::FunArgSep || ch == MathDsl::CommaSep; } static bool s_expressionWithoutIgnorableTrailingToken(const QString& text, QString* out) { if (!out) return false; const QString trimmed = text.trimmed(); if (trimmed.isEmpty()) return false; int i = trimmed.size() - 1; const QChar last = trimmed.at(i); const bool isPlusMinusTail = (last == MathDsl::AddOp || s_isSubtractionOperatorAlias(last)); const bool isMultiplicationTail = (last == MathDsl::MulDotOp || s_isMultiplicationOperatorAlias(last, true)); const bool isPhasorTail = last == MathDsl::PhasorOp; if (last != MathDsl::GroupStart && last != MathDsl::UnitStart && !isPlusMinusTail && !isMultiplicationTail && !isPhasorTail && last != QLatin1Char(';') && last != MathDsl::DivOp && last != MathDsl::PowOp && last != MathDsl::IntDivOp) return false; if (last == MathDsl::DivOp) { --i; if (i >= 0 && trimmed.at(i) == MathDsl::DivOp) return false; } else if (last == MathDsl::PowOp) { --i; if (i >= 0 && trimmed.at(i) == MathDsl::PowOp) return false; } else if (isPlusMinusTail) { while (i >= 0 && (trimmed.at(i) == MathDsl::AddOp || s_isSubtractionOperatorAlias(trimmed.at(i)))) --i; } else if (isMultiplicationTail) { --i; if (i >= 0) { const QChar prev = trimmed.at(i); const bool prevIsMultiplication = (prev == MathDsl::MulDotOp || s_isMultiplicationOperatorAlias(prev, true)); if (prevIsMultiplication) { --i; if (i >= 0) { const QChar prevPrev = trimmed.at(i); const bool prevPrevIsMultiplication = (prevPrev == MathDsl::MulDotOp || s_isMultiplicationOperatorAlias(prevPrev, true)); if (prevPrevIsMultiplication) return false; } } } } else { while (i >= 0 && trimmed.at(i) == last) --i; } const QString prefix = trimmed.left(i + 1).trimmed(); if (prefix.isEmpty()) return false; const QChar prefixLast = prefix.at(prefix.size() - 1); if (prefixLast == MathDsl::GroupStart || prefixLast == MathDsl::UnitStart || s_isExpressionOperatorOrSeparator(prefixLast) || prefixLast == MathDsl::IntDivOp) return false; *out = prefix; return true; } bool isMinus(const QChar& ch) { return ch == MathDsl::SubOpAl1 || ch == MathDsl::SubOp; } static bool isDegreeSign(const QChar& ch) { // Accept both DEGREE SIGN (U+00B0) and MASCULINE ORDINAL INDICATOR // (U+00BA), plus other degree-like symbols emitted by some layouts/IMEs. return ch == MathDsl::Deg // ° DEGREE SIGN || ch == UnicodeChars::MasculineOrdinalIndicator // º MASCULINE ORDINAL INDICATOR || ch == UnicodeChars::RingAbove // Ëš RING ABOVE || ch == UnicodeChars::RingOperator; // ∘ RING OPERATOR } bool isExponent(const QChar& ch, int base) { switch (base) { case 2: return ch == QLatin1Char('b') || ch == QLatin1Char('B'); case 8: return ch == QLatin1Char('o') || ch == QLatin1Char('O') || ch == QLatin1Char('C'); case 10: return ch == QLatin1Char('e') || ch == QLatin1Char('E'); case 16: return ch == QLatin1Char('h') || ch == QLatin1Char('H'); default: return false; } } const Quantity& Evaluator::checkOperatorResult(const Quantity& n) { switch (n.error()) { case Success: break; case NoOperand: if (!m_assignFunc) // The arguments are still NaN, so ignore this error. m_error = Evaluator::tr("cannot operate on a NaN"); break; case Underflow: m_error = Evaluator::tr("underflow - tiny result is out " "of SpeedCrunch's number range"); break; case Overflow: m_error = Evaluator::tr("overflow - huge result is out of " "SpeedCrunch's number range"); break; case ZeroDivide: m_error = Evaluator::tr("division by zero"); break; case OutOfLogicRange: if (!(m_assignFunc && !m_assignArg.isEmpty())) { m_error = Evaluator::tr("overflow - logic result exceeds " "maximum of 256 bits"); } break; case OutOfIntegerRange: if (!(m_assignFunc && !m_assignArg.isEmpty())) { m_error = Evaluator::tr("overflow - integer result exceeds " "maximum limit for integers"); } break; case TooExpensive: m_error = Evaluator::tr("too time consuming - " "computation was rejected"); break; case DimensionMismatch: // We cannot make any assumptions about the dimension of the arguments, // so ignore this error when assigning a function. if (!m_assignFunc) m_error = Evaluator::tr("dimension mismatch - quantities with " "different dimensions cannot be " "compared, added, etc."); break; case InvalidDimension: m_error = Evaluator::tr("invalid dimension - operation might " "require dimensionless arguments"); break; case NotImplemented: // Arguments are NaN placeholders while a function is being defined // (e.g. f(n) = n!), so the operation can't be judged yet. if (!(m_assignFunc && !m_assignArg.isEmpty())) m_error = Evaluator::tr("operation is not defined for these arguments"); break; case EvalUnstable: m_error = Evaluator::tr("Computation aborted - encountered " "numerical instability"); break; default:; } return n; } QString Evaluator::stringFromFunctionError(Function* function) { if (!function->error()) return QString(); QString result = QString::fromLatin1("%1: "); switch (function->error()) { case Success: break; case InvalidParamCount: result += Evaluator::tr("wrong number of arguments"); break; case NoOperand: result += Evaluator::tr("does not take NaN as an argument"); break; case Overflow: result += Evaluator::tr("overflow - huge result is out of " "SpeedCrunch's number range"); break; case Underflow: result += Evaluator::tr("underflow - tiny result is out of " "SpeedCrunch's number range"); break; case OutOfLogicRange: result += Evaluator::tr("overflow - logic result exceeds " "maximum of 256 bits"); break; case OutOfIntegerRange: result += Evaluator::tr("result out of range"); break; case ZeroDivide: result += Evaluator::tr("division by zero"); break; case EvalUnstable: result += Evaluator::tr("Computation aborted - " "encountered numerical instability"); break; case OutOfDomain: result += Evaluator::tr("undefined for argument domain"); break; case TooExpensive: result += Evaluator::tr("computation too expensive"); break; case InvalidDimension: result += Evaluator::tr("invalid dimension - function " "might require dimensionless arguments"); break; case DimensionMismatch: result += Evaluator::tr("dimension mismatch - quantities with " "different dimensions cannot be compared, " "added, etc."); break; case IONoBase: case BadLiteral: case InvalidPrecision: case InvalidParam: result += Evaluator::tr("internal error, please report a bug"); break; default: result += Evaluator::tr("error"); break; }; return result.arg(function->identifier()); } class TokenStack : public QVector { public: TokenStack(); bool isEmpty() const; unsigned itemCount() const; Token pop(); void push(const Token& token); const Token& top(); const Token& top(unsigned index); bool hasError() const { return !m_error.isEmpty(); } QString error() const { return m_error; } void reduce(int count, int minPrecedence = INVALID_PRECEDENCE); void reduce(int count, Token&& top, int minPrecedence = INVALID_PRECEDENCE); void reduce(QList tokens, Token&& top, int minPrecedence = INVALID_PRECEDENCE); private: void ensureSpace(); int topIndex; QString m_error; }; const Token Token::null; static Token::Operator matchOperator(const QString& text) { Token::Operator result = Token::Invalid; if (text.length() == 1) { QChar p = text.at(0); switch(p.unicode()) { case '+': result = Token::Addition; break; case MathDsl::SubOp.unicode(): case MathDsl::SubOpAl1.unicode(): result = Token::Subtraction; break; case MathDsl::MulCrossOp.unicode(): case MathDsl::MulDotOp.unicode(): case MathDsl::MulOpAl1.unicode(): result = Token::Multiplication; break; case UnicodeChars::DivisionSign.unicode(): case UnicodeChars::BigSolidus.unicode(): case '/': result = Token::Division; break; case MathDsl::PowOp.unicode(): result = Token::Exponentiation; break; case MathDsl::FunArgSep.unicode(): result = Token::ListSeparator; break; case MathDsl::GroupStart.unicode(): result = Token::AssociationStart; break; case MathDsl::GroupEnd.unicode(): result = Token::AssociationEnd; break; case MathDsl::UnitStart.unicode(): result = Token::AssociationStart; break; case MathDsl::UnitEnd.unicode(): result = Token::AssociationEnd; break; case MathDsl::ListStart.unicode(): result = Token::AssociationStart; break; case MathDsl::ListEnd.unicode(): result = Token::AssociationEnd; break; case MathDsl::FactorOp.unicode(): result = Token::Factorial; break; case MathDsl::PercentOp.unicode(): result = Token::Percent; break; case MathDsl::Equals.unicode(): result = Token::Assignment; break; case '\\': result = Token::IntegerDivision; break; case '~': result = Token::BitwiseLogicalNOT; break; case MathDsl::BitAndOp.unicode(): result = Token::BitwiseLogicalAND; break; case MathDsl::BitOrOp.unicode(): result = Token::BitwiseLogicalOR; break; case MathDsl::PhasorOp.unicode(): result = Token::Phasor; break; case MathDsl::TransOp.unicode(): result = Token::UnitConversion; break; default: result = Token::Invalid; } } else if (text.length() == 2) { if (text == "**") result = Token::Exponentiation; else if (text == "<<") result = Token::ArithmeticLeftShift; else if (text == ">>") result = Token::ArithmeticRightShift; else if (text == "->" || (text.at(0) == MathDsl::SubOp && text.at(1) == UnicodeChars::GreaterThanSign) || text.compare(MathDsl::TransOpAl1, Qt::CaseInsensitive) == 0) result = Token::UnitConversion; } return result; } // Helper function: give operator precedence e.g. "+" is 300 while "*" is 500. static int opPrecedence(Token::Operator op) { int prec; switch (op) { case Token::Factorial: case Token::Percent: prec = 800; break; case Token::Exponentiation: prec = 700; break; case Token::Function: // Not really operator but needed for managing shift/reduce conflicts. prec = 600; break; case Token::Multiplication: case Token::Division: case Token::Phasor: prec = 500; break; case Token::Modulo: case Token::IntegerDivision: prec = 600; break; case Token::Addition: case Token::Subtraction: prec = 300; break; case Token::ArithmeticLeftShift: case Token::ArithmeticRightShift: prec = 200; break; case Token::BitwiseLogicalNOT: prec = 150; break; case Token::BitwiseLogicalAND: prec = 100; break; case Token::BitwiseLogicalOR: prec = 50; break; case Token::UnitConversion: prec = 0; break; case Token::AssociationEnd: case Token::ListSeparator: prec = -100; break; case Token::AssociationStart: prec = -200; break; default: prec = -200; break; } return prec; } static int opcodePrecedence(Opcode::Type opcodeType) { switch (opcodeType) { case Opcode::Add: case Opcode::Sub: return opPrecedence(Token::Addition); case Opcode::Mul: case Opcode::Div: case Opcode::Phasor: return opPrecedence(Token::Multiplication); case Opcode::Unit: return opPrecedence(Token::Factorial) + 1; case Opcode::Pow: return opPrecedence(Token::Exponentiation); case Opcode::Fact: return opPrecedence(Token::Factorial); case Opcode::Percent: return opPrecedence(Token::Percent); case Opcode::Modulo: case Opcode::IntDiv: return opPrecedence(Token::Modulo); case Opcode::LSh: case Opcode::RSh: return opPrecedence(Token::ArithmeticLeftShift); case Opcode::BAnd: return opPrecedence(Token::BitwiseLogicalAND); case Opcode::BOr: return opPrecedence(Token::BitwiseLogicalOR); case Opcode::Conv: return opPrecedence(Token::UnitConversion); case Opcode::Neg: case Opcode::BNot: return opPrecedence(Token::Multiplication); default: return MAX_PRECEDENCE; } } static bool isRightAssociativeOpcode(Opcode::Type opcodeType) { return opcodeType == Opcode::Pow; } static QString opcodeToInfixSymbol(Opcode::Type opcodeType, bool implicitMultiplication = false) { switch (opcodeType) { case Opcode::Add: return "+"; case Opcode::Sub: return "-"; case Opcode::Mul: return implicitMultiplication ? QString(MathDsl::MulDotOp) : QString(MathDsl::MulCrossOp); case Opcode::Unit: return QString(); case Opcode::Div: return "/"; case Opcode::Pow: return "^"; case Opcode::Percent: return "%"; case Opcode::Modulo: return "mod"; case Opcode::IntDiv: return "\\"; case Opcode::LSh: return "<<"; case Opcode::RSh: return ">>"; case Opcode::BAnd: return "&"; case Opcode::BOr: return "|"; case Opcode::Phasor: return QString(MathDsl::PhasorOp); case Opcode::Conv: return QString(MathDsl::TransOp); default: return QString(); } } Token::Token(Type type, const QString& text, int pos, int size) { m_type = type; m_text = text; m_pos = pos; m_size = size; m_minPrecedence = MAX_PRECEDENCE; m_explicitUnitAttachment = false; } Token::Token(const Token& token) { m_type = token.m_type; m_text = token.m_text; m_pos = token.m_pos; m_size = token.m_size; m_minPrecedence = token.m_minPrecedence; m_explicitUnitAttachment = token.m_explicitUnitAttachment; } Token& Token::operator=(const Token& token) { m_type = token.m_type; m_text = token.m_text; m_pos = token.m_pos; m_size = token.m_size; m_minPrecedence = token.m_minPrecedence; m_explicitUnitAttachment = token.m_explicitUnitAttachment; return*this; } Quantity Token::asNumber() const { QString text = m_text; return isNumber() ? Quantity(CNumber((const char*)text.toLatin1())) : Quantity(0); } Token::Operator Token::asOperator() const { return isOperator() ? matchOperator(m_text) : Invalid; } QString Token::description() const { QString desc; switch (m_type) { case stxNumber: desc = "Number"; break; case stxIdentifier: desc = "Identifier"; break; case stxUnitIdentifier: desc = "Unit Identifier"; break; case stxOpenPar: case stxClosePar: case stxSep: case stxOperator: desc = "Operator"; break; default: desc = "Unknown"; break; } while (desc.length() < 10) desc.prepend(' '); QString header; header.append(QString::number(m_pos) + "," + QString::number(m_pos + m_size - 1)); header.append("," + (m_minPrecedence == MAX_PRECEDENCE ? "MAX" : QString::number(m_minPrecedence))); header.append(" "); while (header.length() < 10) header.append(' '); desc.prepend(header); desc.append(" : ").append(m_text); return desc; } static bool tokenPositionCompare(const Token& a, const Token& b) { return (a.pos() < b.pos()); } static bool tokenCanEndOperandForDisplaySpacing(const Token& token) { return token.isOperand() || token.asOperator() == Token::AssociationEnd || token.asOperator() == Token::Factorial || token.asOperator() == Token::Percent; } static bool tokenCanStartOperandForDisplaySpacing(const Token& token) { return token.isOperand() || token.asOperator() == Token::AssociationStart || token.asOperator() == Token::Addition || token.asOperator() == Token::Subtraction || token.asOperator() == Token::BitwiseLogicalNOT; } static bool isImaginaryUnitTokenForDisplay(const Token& token) { if (!token.isIdentifier()) return false; const QString text = token.text(); if (text == QLatin1String("i") || text == QLatin1String("j")) return true; const QChar configuredImaginaryUnit(Settings::instance()->imaginaryUnit); return text.size() == 1 && text.at(0) == configuredImaginaryUnit; } static bool startsWithImaginaryLiteralForDisplay(const Tokens& tokens, int startIndex) { if (startIndex < 0 || startIndex >= tokens.size()) return false; if (isImaginaryUnitTokenForDisplay(tokens.at(startIndex))) return true; if (startIndex + 2 >= tokens.size()) return false; const Token::Operator mulOp = tokens.at(startIndex + 1).asOperator(); return tokens.at(startIndex).isNumber() && mulOp == Token::Multiplication && isImaginaryUnitTokenForDisplay(tokens.at(startIndex + 2)); } static bool isStandaloneNumericLiteralOperandForDisplay(const Tokens& tokens, int startIndex, int endIndex) { if (startIndex < 0 || endIndex >= tokens.size() || startIndex > endIndex) return false; int start = startIndex; int end = endIndex; while (start <= end) { const Token::Operator op = tokens.at(start).asOperator(); if (op == Token::Addition || op == Token::Subtraction || op == Token::BitwiseLogicalNOT) { ++start; continue; } break; } while (start <= end) { const Token::Operator op = tokens.at(end).asOperator(); if (op == Token::Percent || op == Token::Factorial) { --end; continue; } break; } if (start > end) return false; if (tokens.at(end).text() == QString(MathDsl::UnitEnd)) { int depth = 0; int unitStart = -1; for (int i = end; i >= start; --i) { const QString text = tokens.at(i).text(); if (text == QString(MathDsl::UnitEnd)) { ++depth; continue; } if (text == QString(MathDsl::UnitStart)) { --depth; if (depth == 0) { unitStart = i; break; } } } if (unitStart < 0) return false; end = unitStart - 1; if (start > end) return false; } if (start == end && tokens.at(start).isNumber()) return true; if (tokens.at(start).asOperator() == Token::AssociationStart && tokens.at(end).asOperator() == Token::AssociationEnd) { int depth = 0; for (int i = start; i <= end; ++i) { const Token::Operator op = tokens.at(i).asOperator(); if (op == Token::AssociationStart) ++depth; else if (op == Token::AssociationEnd) --depth; if (depth == 0 && i < end) return false; } return isStandaloneNumericLiteralOperandForDisplay(tokens, start + 1, end - 1); } return false; } static bool isUnsignedIntegerDigitsText(const QString& text) { if (text.isEmpty()) return false; for (const QChar& ch : text) { if (!ch.isDigit()) return false; } return true; } static bool isIntegerNumericLiteralOperandForDisplay(const Tokens& tokens, int rangeStart, int rangeEnd) { if (!isStandaloneNumericLiteralOperandForDisplay(tokens, rangeStart, rangeEnd)) return false; if (rangeStart == rangeEnd && tokens.at(rangeStart).isNumber()) { QString text = tokens.at(rangeStart).text(); return normalizeUnsignedIntegerEquivalentDecimalText(text) || isUnsignedIntegerDigitsText(text); } if (tokens.at(rangeStart).asOperator() == Token::AssociationStart && tokens.at(rangeEnd).asOperator() == Token::AssociationEnd) { int innerStart = rangeStart + 1; int innerEnd = rangeEnd - 1; if (innerStart > innerEnd) return false; if (tokens.at(innerStart).asOperator() == Token::Addition || tokens.at(innerStart).asOperator() == Token::Subtraction) { ++innerStart; } if (innerStart != innerEnd || !tokens.at(innerStart).isNumber()) return false; QString text = tokens.at(innerStart).text(); return normalizeUnsignedIntegerEquivalentDecimalText(text) || isUnsignedIntegerDigitsText(text); } return false; } static bool isNumericPowerLiteralOperandForDisplay(const Tokens& tokens, int rangeStart, int rangeEnd) { if (rangeStart < 0 || rangeEnd >= tokens.size() || rangeStart > rangeEnd) return false; int start = rangeStart; int end = rangeEnd; if (tokens.at(start).asOperator() == Token::AssociationStart && tokens.at(end).asOperator() == Token::AssociationEnd) { int depth = 0; bool enclosesWholeRange = true; for (int i = start; i <= end; ++i) { const Token::Operator op = tokens.at(i).asOperator(); if (op == Token::AssociationStart) ++depth; else if (op == Token::AssociationEnd) --depth; if (depth == 0 && i < end) { enclosesWholeRange = false; break; } } if (enclosesWholeRange) return isNumericPowerLiteralOperandForDisplay(tokens, start + 1, end - 1); } int exponentOp = -1; int depth = 0; for (int i = start; i <= end; ++i) { const Token::Operator op = tokens.at(i).asOperator(); if (op == Token::AssociationStart) { ++depth; continue; } if (op == Token::AssociationEnd) { --depth; continue; } if (depth == 0 && op == Token::Exponentiation) { if (exponentOp >= 0) return false; exponentOp = i; } } if (exponentOp <= start || exponentOp >= end) return false; const bool baseIsNumericLiteral = isStandaloneNumericLiteralOperandForDisplay(tokens, start, exponentOp - 1) || isNumericPowerLiteralOperandForDisplay(tokens, start, exponentOp - 1); const bool exponentIsNumericLiteral = isStandaloneNumericLiteralOperandForDisplay(tokens, exponentOp + 1, end) || isNumericPowerLiteralOperandForDisplay(tokens, exponentOp + 1, end); return baseIsNumericLiteral && exponentIsNumericLiteral; } static bool isHardcodedNumericLiteralOperandForDisplay(const Tokens& tokens, int rangeStart, int rangeEnd) { return isStandaloneNumericLiteralOperandForDisplay(tokens, rangeStart, rangeEnd) || isNumericPowerLiteralOperandForDisplay(tokens, rangeStart, rangeEnd); } static bool isHardcodedNumericOperandOnLeftOfMultiplicationForDisplay(const Tokens& tokens, int mulIndex, bool includeNumericPowers) { if (mulIndex <= 0 || mulIndex >= tokens.size()) return false; int end = mulIndex - 1; int start = end; if (tokens.at(end).text() == QString(MathDsl::UnitEnd)) { int depth = 0; int unitStart = -1; for (int i = end; i >= 0; --i) { const QString text = tokens.at(i).text(); if (text == QString(MathDsl::UnitEnd)) { ++depth; continue; } if (text == QString(MathDsl::UnitStart)) { --depth; if (depth == 0) { unitStart = i; break; } } } if (unitStart < 1) return false; start = unitStart - 1; } if (tokens.at(start).asOperator() == Token::AssociationEnd) { int depth = 0; int groupStart = -1; for (int i = start; i >= 0; --i) { const Token::Operator op = tokens.at(i).asOperator(); if (op == Token::AssociationEnd) { ++depth; continue; } if (op == Token::AssociationStart) { --depth; if (depth == 0) { groupStart = i; break; } } } if (groupStart < 0) return false; // "(...)" immediately preceded by an identifier is a function call // operand (e.g. "sin(...)"), not a hardcoded numeric literal. if (groupStart > 0 && tokens.at(groupStart - 1).isIdentifier()) return false; start = groupStart; } if (start >= 2 && tokens.at(start - 1).asOperator() == Token::Exponentiation && tokens.at(start - 2).isNumber()) { QString baseText = tokens.at(start - 2).text(); normalizeUnsignedIntegerEquivalentDecimalText(baseText); const bool hasIntegerExponent = isIntegerNumericLiteralOperandForDisplay(tokens, start, end); const bool canTreatAsNumericPower = includeNumericPowers ? isHardcodedNumericLiteralOperandForDisplay(tokens, start, end) : hasIntegerExponent; if ((baseText == QLatin1String("10") && hasIntegerExponent) || (includeNumericPowers && canTreatAsNumericPower)) { start -= 2; } } if (start > 0) { const Token& previous = tokens.at(start - 1); const Token::Operator previousOp = previous.asOperator(); if (tokenCanEndOperandForDisplaySpacing(previous) || previousOp == Token::Exponentiation) { return false; } } return includeNumericPowers ? isHardcodedNumericLiteralOperandForDisplay(tokens, start, end) : isStandaloneNumericLiteralOperandForDisplay(tokens, start, end); } static bool isHardcodedNumericOperandOnRightOfMultiplicationForDisplay(const Tokens& tokens, int mulIndex, bool includeNumericPowers) { if (mulIndex < 0 || mulIndex >= tokens.size() - 1) return false; int start = mulIndex + 1; int end = start; const Token::Operator leadingOp = tokens.at(start).asOperator(); if (leadingOp == Token::Addition || leadingOp == Token::Subtraction || leadingOp == Token::BitwiseLogicalNOT) { ++end; if (end >= tokens.size()) return false; } if (tokens.at(end).asOperator() == Token::AssociationStart) { int depth = 0; int groupEnd = -1; for (int i = end; i < tokens.size(); ++i) { const Token::Operator op = tokens.at(i).asOperator(); if (op == Token::AssociationStart) { ++depth; continue; } if (op == Token::AssociationEnd) { --depth; if (depth == 0) { groupEnd = i; break; } } } if (groupEnd < 0) return false; end = groupEnd; } else if (tokens.at(end).isNumber()) { if (end + 1 < tokens.size() && tokens.at(end + 1).text() == QString(MathDsl::UnitStart)) { int depth = 0; int unitEnd = -1; for (int i = end + 1; i < tokens.size(); ++i) { const QString text = tokens.at(i).text(); if (text == QString(MathDsl::UnitStart)) { ++depth; continue; } if (text == QString(MathDsl::UnitEnd)) { --depth; if (depth == 0) { unitEnd = i; break; } } } if (unitEnd < 0) return false; end = unitEnd; } } while (end + 1 < tokens.size()) { const Token::Operator op = tokens.at(end + 1).asOperator(); if (op == Token::Percent || op == Token::Factorial) { ++end; continue; } break; } if (end + 1 < tokens.size() && tokens.at(end + 1).asOperator() == Token::Exponentiation) { if (start != end || !tokens.at(start).isNumber()) return false; const int exponentStart = end + 2; if (exponentStart >= tokens.size()) return false; int exponentEnd = exponentStart; if (tokens.at(exponentStart).asOperator() == Token::AssociationStart) { int depth = 0; int groupEnd = -1; for (int i = exponentStart; i < tokens.size(); ++i) { const Token::Operator op = tokens.at(i).asOperator(); if (op == Token::AssociationStart) { ++depth; continue; } if (op == Token::AssociationEnd) { --depth; if (depth == 0) { groupEnd = i; break; } } } if (groupEnd < 0) return false; exponentEnd = groupEnd; } const bool hasIntegerExponent = isIntegerNumericLiteralOperandForDisplay(tokens, exponentStart, exponentEnd); if (includeNumericPowers) return isHardcodedNumericLiteralOperandForDisplay(tokens, start, exponentEnd); QString baseText = tokens.at(start).text(); normalizeUnsignedIntegerEquivalentDecimalText(baseText); if (baseText != QLatin1String("10")) return false; return hasIntegerExponent; } return includeNumericPowers ? isHardcodedNumericLiteralOperandForDisplay(tokens, start, end) : isStandaloneNumericLiteralOperandForDisplay(tokens, start, end); } static bool isUnsignedDecimalIntegerText(const QString& text) { return RegExpPatterns::unsignedDecimalInteger().match(text).hasMatch(); } static bool isUnsignedDecimalNumberText(const QString& text) { return RegExpPatterns::unsignedDecimalNumber().match(text).hasMatch(); } static bool isSignedDecimalNumberText(const QString& text) { return RegExpPatterns::signedDecimalNumber().match(text).hasMatch(); } static bool isSafeForDoubleArithmetic(const QString& text) { if (!isSignedDecimalNumberText(text)) return false; int digitCount = 0; for (const QChar& ch : text) { if (ch.isDigit()) ++digitCount; } // Keep folding conservative to avoid precision regressions when using // temporary C++ doubles in the display simplifier. return digitCount <= 15; } static QString formatSimplifiedDecimal(double value) { const double rounded = std::round(value); if (std::abs(value - rounded) < 1e-12) return QString::number(static_cast(rounded)); QString text = QString::number(value, 'g', 15); if (text.contains(MathDsl::DotSep)) { while (text.endsWith(QLatin1Char('0'))) text.chop(1); if (text.endsWith(MathDsl::DotSep)) text.chop(1); } return text; } static bool normalizeUnsignedIntegerEquivalentDecimalText(QString& text) { const QRegularExpressionMatch match = RegExpPatterns::unsignedIntegerEquivalentDecimal().match(text); if (!match.hasMatch()) return false; const QString fractionalPart = match.captured(2); for (const QChar& ch : fractionalPart) { if (ch != QLatin1Char('0')) return false; } text = match.captured(1); return true; } static QString renderIntegerPowersAsSuperscriptsForDisplay( const QString& expression, bool collapseRightAssociativeIntegerPowerChains = false) { auto collapseRightAssociativeIntegerPowerChainsFn = [](QString text) { auto checkedPow = [](long long base, long long exponent, long long* out) { if (exponent < 0) return false; long long result = 1; for (long long i = 0; i < exponent; ++i) { if (base != 0 && result > std::numeric_limits::max() / base) return false; result *= base; if (result > 1000000) return false; } *out = result; return true; }; auto collapseIntegerExponentChainText = [&checkedPow](const QString& chain, long long* out) { QVector exponents; int pos = 0; while (pos < chain.size()) { bool negative = false; if (chain.at(pos) == MathDsl::SubOpAl1 || chain.at(pos) == MathDsl::SubOp) { negative = true; ++pos; } if (negative || pos >= chain.size() || !chain.at(pos).isDigit()) return false; long long value = 0; while (pos < chain.size() && chain.at(pos).isDigit()) { const int digit = chain.at(pos).digitValue(); if (value > 1000000) return false; value = value * 10 + digit; ++pos; } exponents.append(value); if (pos >= chain.size()) break; if (chain.at(pos) != MathDsl::PowOp) return false; ++pos; } if (exponents.size() < 2) return false; long long collapsed = exponents.last(); for (int idx = exponents.size() - 2; idx >= 0; --idx) { if (!checkedPow(exponents.at(idx), collapsed, &collapsed)) return false; } *out = collapsed; return true; }; auto parsePositiveIntegerToken = [](const QString& input, int start, long long* valueOut, int* endOut) { int pos = start; bool parenthesized = false; if (pos < input.size() && input.at(pos) == MathDsl::GroupStart) { parenthesized = true; ++pos; } if (pos >= input.size() || !input.at(pos).isDigit()) return false; long long value = 0; while (pos < input.size() && input.at(pos).isDigit()) { const int digit = input.at(pos).digitValue(); if (value > 1000000) return false; value = value * 10 + digit; ++pos; } if (parenthesized) { if (pos >= input.size() || input.at(pos) != MathDsl::GroupEnd) return false; ++pos; } *valueOut = value; *endOut = pos; return true; }; // Fold nested integer powers: (a^m)^n -> a^(m*n). while (true) { bool changed = false; for (int i = 1; i < text.size(); ++i) { if (text.at(i) != MathDsl::PowOp || text.at(i - 1) != MathDsl::GroupEnd) continue; long long outerExp = 0; int outerEnd = i + 1; if (!parsePositiveIntegerToken(text, i + 1, &outerExp, &outerEnd)) continue; int depth = 0; int open = -1; for (int j = i - 1; j >= 0; --j) { const QChar ch = text.at(j); if (ch == MathDsl::GroupEnd) ++depth; else if (ch == MathDsl::GroupStart) { --depth; if (depth == 0) { open = j; break; } } } if (open < 0) continue; const QString inner = text.mid(open + 1, i - open - 2); int innerDepth = 0; int innerPowPos = -1; for (int j = 0; j < inner.size(); ++j) { const QChar ch = inner.at(j); if (ch == MathDsl::GroupStart) ++innerDepth; else if (ch == MathDsl::GroupEnd) { if (innerDepth > 0) --innerDepth; } else if (ch == MathDsl::PowOp && innerDepth == 0) { innerPowPos = j; } } if (innerPowPos <= 0) continue; long long innerExp = 0; int innerExpEnd = innerPowPos + 1; if (!parsePositiveIntegerToken(inner, innerPowPos + 1, &innerExp, &innerExpEnd)) continue; if (innerExpEnd != inner.size()) continue; const QString innerBase = inner.left(innerPowPos); long long mergedExp = 0; if (innerExp != 0 && outerExp > 1000000 / innerExp) continue; mergedExp = innerExp * outerExp; if (mergedExp > 1000000) continue; text.replace(open, outerEnd - open, innerBase + MathDsl::PowOp + QString::number(mergedExp)); changed = true; break; } if (!changed) break; } auto parseIntegerExponentToken = [&text, &collapseIntegerExponentChainText](int start, long long* valueOut, int* endOut) { int pos = start; if (pos < text.size() && text.at(pos) == MathDsl::GroupStart) { int depth = 0; int close = -1; for (int i = pos; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd) { --depth; if (depth == 0) { close = i; break; } } } if (close < 0) return false; const QString inner = text.mid(pos + 1, close - pos - 1).trimmed(); long long collapsed = 0; if (!collapseIntegerExponentChainText(inner, &collapsed)) return false; *valueOut = collapsed; *endOut = close + 1; return true; } bool negative = false; if (pos < text.size() && (text.at(pos) == MathDsl::SubOpAl1 || text.at(pos) == MathDsl::SubOp)) { negative = true; ++pos; } if (pos >= text.size() || !text.at(pos).isDigit()) return false; long long value = 0; while (pos < text.size() && text.at(pos).isDigit()) { const int digit = text.at(pos).digitValue(); if (value > 1000000) // avoid overflow-heavy chains in display-only rewrite return false; value = value * 10 + digit; ++pos; } *valueOut = negative ? -value : value; *endOut = pos; return true; }; for (int i = 0; i < text.size(); ++i) { if (text.at(i) != MathDsl::PowOp) continue; QVector exponents; const bool startsWithParenthesizedExponentChain = (i + 1 < text.size() && text.at(i + 1) == MathDsl::GroupStart); int tokenPos = i + 1; while (tokenPos < text.size()) { long long value = 0; int tokenEnd = tokenPos; if (!parseIntegerExponentToken(tokenPos, &value, &tokenEnd)) break; exponents.append(value); tokenPos = tokenEnd; if (tokenPos >= text.size() || text.at(tokenPos) != MathDsl::PowOp) break; ++tokenPos; } if (exponents.isEmpty()) continue; if (exponents.size() < 2 && !startsWithParenthesizedExponentChain) continue; if (std::any_of(exponents.constBegin(), exponents.constEnd(), [](long long v) { return v < 0; })) { continue; } long long collapsedExponent = exponents.last(); bool ok = true; for (int idx = exponents.size() - 2; idx >= 0; --idx) { if (!checkedPow(exponents.at(idx), collapsedExponent, &collapsedExponent)) { ok = false; break; } } if (!ok) continue; text.replace(i + 1, tokenPos - (i + 1), QString::number(collapsedExponent)); } return text; }; QString normalizedExpression = expression; if (collapseRightAssociativeIntegerPowerChains) normalizedExpression = collapseRightAssociativeIntegerPowerChainsFn(expression); static const QRegularExpression powerRE( QStringLiteral(R"(\^(?:\(([−-]?)(\d+)\)|(\d+))(?![\p{L}\p{N}\.,_!]))")); QString rendered; rendered.reserve(normalizedExpression.size()); int lastPos = 0; auto it = powerRE.globalMatch(normalizedExpression); while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); rendered += normalizedExpression.mid(lastPos, match.capturedStart() - lastPos); const QString sign = match.captured(1); QString digits = match.captured(2); if (digits.isEmpty()) digits = match.captured(3); QString superscript; superscript.reserve(digits.size() + 1); if (!sign.isEmpty()) superscript += MathDsl::PowNeg; for (const QChar& digit : digits) superscript += MathDsl::asciiDigitToSuperscript(digit); rendered += superscript; lastPos = match.capturedEnd(); } rendered += normalizedExpression.mid(lastPos); auto isIdentifierChar = [](const QChar& ch) { return isIdentifierContinue(ch); }; auto isIdentifierStartChar = [](const QChar& ch) { return isIdentifierStart(ch); }; auto isSuperscriptPowerChar = [](const QChar& ch) { return MathDsl::isSuperscriptPowerChar(ch); }; // Convert function-call powers from "f(x)²" to "f²(x)". int i = 0; while (i < rendered.size()) { if (rendered.at(i) != MathDsl::GroupEnd) { ++i; continue; } int superscriptEnd = i + 1; while (superscriptEnd < rendered.size() && isSuperscriptPowerChar(rendered.at(superscriptEnd))) ++superscriptEnd; if (superscriptEnd == i + 1) { ++i; continue; } int depth = 0; int openParen = -1; for (int j = i; j >= 0; --j) { const QChar ch = rendered.at(j); if (ch == MathDsl::GroupEnd) { ++depth; } else if (ch == MathDsl::GroupStart) { --depth; if (depth == 0) { openParen = j; break; } } } if (openParen <= 0) { i = superscriptEnd; continue; } int nameStart = openParen - 1; while (nameStart >= 0 && isIdentifierChar(rendered.at(nameStart))) --nameStart; ++nameStart; if (nameStart >= openParen || !isIdentifierStartChar(rendered.at(nameStart))) { i = superscriptEnd; continue; } if (nameStart > 0 && isIdentifierChar(rendered.at(nameStart - 1))) { i = superscriptEnd; continue; } const QString funcName = rendered.mid(nameStart, openParen - nameStart); const QString callArgs = rendered.mid(openParen, i - openParen + 1); const QString superscript = rendered.mid(i + 1, superscriptEnd - (i + 1)); const QString replacement = funcName + superscript + callArgs; rendered.replace(nameStart, superscriptEnd - nameStart, replacement); i = nameStart + replacement.size(); } return rendered; } static bool isWrappedInOuterParentheses(const QString& text) { if (text.size() < 2 || text.front() != MathDsl::GroupStart || text.back() != MathDsl::GroupEnd) return false; int depth = 0; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd) { --depth; if (depth < 0) return false; if (depth == 0 && i != text.size() - 1) return false; } } return depth == 0; } static bool termNeedsGroupingForDisplay(const Tokens& tokens, int firstIndex, int lastIndex) { if (firstIndex < 0 || lastIndex >= tokens.size() || firstIndex >= lastIndex) return false; const int additivePrecedence = opPrecedence(Token::Addition); int depth = 0; for (int i = firstIndex; i <= lastIndex; ++i) { const Token& token = tokens.at(i); const Token::Operator op = token.asOperator(); if (op == Token::AssociationStart) { ++depth; continue; } if (op == Token::AssociationEnd) { if (depth > 0) --depth; continue; } if (depth != 0 || !token.isOperator()) continue; const bool hasLeftOperand = i > firstIndex && tokenCanEndOperandForDisplaySpacing(tokens.at(i - 1)); const bool hasRightOperand = i < lastIndex && tokenCanStartOperandForDisplaySpacing(tokens.at(i + 1)); if (!hasLeftOperand || !hasRightOperand) continue; if (opPrecedence(op) > additivePrecedence) { // Additive precedence already disambiguates top-level arithmetic // terms, so avoid injecting grouping parentheses for them. if (op == Token::Exponentiation || op == Token::Multiplication || op == Token::Division || op == Token::IntegerDivision || op == Token::Modulo) { continue; } return true; } } return false; } static QString groupHighPrecedenceAdditiveTermsForDisplay(const QString& expression, const Tokens& tokens) { if (tokens.isEmpty()) return expression; QVector topLevelBinaryAddSubTokenIndices; int depth = 0; for (int i = 0; i < tokens.size(); ++i) { const Token& token = tokens.at(i); const Token::Operator op = token.asOperator(); if (op == Token::AssociationStart) { ++depth; continue; } if (op == Token::AssociationEnd) { if (depth > 0) --depth; continue; } if (depth != 0 || (op != Token::Addition && op != Token::Subtraction)) continue; const bool hasLeftOperand = i > 0 && tokenCanEndOperandForDisplaySpacing(tokens.at(i - 1)); const bool hasRightOperand = i + 1 < tokens.size() && tokenCanStartOperandForDisplaySpacing(tokens.at(i + 1)); if (hasLeftOperand && hasRightOperand) topLevelBinaryAddSubTokenIndices.append(i); } if (topLevelBinaryAddSubTokenIndices.isEmpty()) return expression; auto tokenRangeText = [&expression, &tokens](int startIndex, int endIndex) { const int startPos = tokens.at(startIndex).pos(); const int endPos = tokens.at(endIndex).pos() + tokens.at(endIndex).size(); return expression.mid(startPos, endPos - startPos); }; QString grouped; grouped.reserve(expression.size() + topLevelBinaryAddSubTokenIndices.size() * 2); int termStartIndex = 0; for (int splitPos = 0; splitPos < topLevelBinaryAddSubTokenIndices.size(); ++splitPos) { const int operatorIndex = topLevelBinaryAddSubTokenIndices.at(splitPos); const int termEndIndex = operatorIndex - 1; if (termEndIndex >= termStartIndex) { QString termText = tokenRangeText(termStartIndex, termEndIndex); if (termNeedsGroupingForDisplay(tokens, termStartIndex, termEndIndex) && !isWrappedInOuterParentheses(termText)) { termText = QStringLiteral("(%1)").arg(termText); } grouped += termText; } grouped += tokenRangeText(operatorIndex, operatorIndex); termStartIndex = operatorIndex + 1; } if (termStartIndex < tokens.size()) { QString lastTermText = tokenRangeText(termStartIndex, tokens.size() - 1); if (termNeedsGroupingForDisplay(tokens, termStartIndex, tokens.size() - 1) && !isWrappedInOuterParentheses(lastTermText)) { lastTermText = QStringLiteral("(%1)").arg(lastTermText); } grouped += lastTermText; } return grouped; } static QString simplifyRepeatedMultiplicativeBasesForDisplay(const QString& expression, const Tokens& tokens); static bool approximateRationalFromDouble(double value, int maxDenominator, qint64* outNumerator, qint64* outDenominator); static bool parseSimplifiablePowerFactor(const QString& factorText, QString* baseOut, int* exponentOut) { static const QRegularExpression identifierRE( QStringLiteral(R"(^(?:[\p{L}_][\p{L}\p{N}_]*)$)")); static const QRegularExpression numberRE( QStringLiteral(R"(^(?:\d+(?:\.\d+)?)$)")); auto isFunctionCallBase = [](const QString& text) { const int firstParen = text.indexOf(MathDsl::GroupStart); if (firstParen <= 0 || !text.endsWith(MathDsl::GroupEnd)) return false; const QString functionName = text.left(firstParen); if (!identifierRE.match(functionName).hasMatch()) return false; int depth = 0; for (int i = firstParen; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd) { --depth; if (depth < 0) return false; if (depth == 0 && i != text.size() - 1) return false; } } return depth == 0; }; auto isSimplifiableBase = [&isFunctionCallBase](const QString& text) { return identifierRE.match(text).hasMatch() || numberRE.match(text).hasMatch() || isFunctionCallBase(text); }; const QString factor = factorText.trimmed(); QString base = factor; int exponent = 1; int depth = 0; int topLevelPowerPos = -1; for (int i = 0; i < factor.size(); ++i) { const QChar ch = factor.at(i); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; } else if (ch == MathDsl::PowOp && depth == 0) { topLevelPowerPos = i; break; } } if (topLevelPowerPos >= 0) { base = factor.left(topLevelPowerPos); QString exponentText = factor.mid(topLevelPowerPos + 1); if (base.isEmpty() || exponentText.isEmpty()) return false; if (exponentText.startsWith(MathDsl::GroupStart) && exponentText.endsWith(MathDsl::GroupEnd)) { exponentText = exponentText.mid(1, exponentText.size() - 2); } if (!normalizeUnsignedIntegerEquivalentDecimalText(exponentText) && !isUnsignedDecimalIntegerText(exponentText)) { return false; } bool ok = false; exponent = exponentText.toInt(&ok); if (!ok || exponent <= 0) return false; } base = base.trimmed(); if (!isSimplifiableBase(base)) return false; *baseOut = base; *exponentOut = exponent; return true; } static QString canonicalSimplifiableBaseKeyForDisplay(QString base) { base.replace(RegExpPatterns::piAliasWord(), QString::fromUtf8("Ï€")); base.replace(RegExpPatterns::eAliasWord(), QString::fromUtf8("ℯ")); return base; } static bool approximateRationalFromDouble(double value, int maxDenominator, qint64* outNumerator, qint64* outDenominator) { if (!outNumerator || !outDenominator || maxDenominator <= 0 || !std::isfinite(value)) return false; const double absValue = std::abs(value); qint64 n0 = 0, d0 = 1; qint64 n1 = 1, d1 = 0; double x = absValue; for (int iter = 0; iter < 64; ++iter) { const qint64 a = static_cast(std::floor(x)); const qint64 n2 = a * n1 + n0; const qint64 d2 = a * d1 + d0; if (d2 > maxDenominator || d2 <= 0) break; n0 = n1; d0 = d1; n1 = n2; d1 = d2; const double frac = x - static_cast(a); if (std::abs(frac) < 1e-15) break; x = 1.0 / frac; } if (d1 <= 0) return false; const qint64 signedNumerator = (value < 0.0) ? -n1 : n1; const double reconstructed = static_cast(signedNumerator) / static_cast(d1); if (std::abs(reconstructed - value) > 1e-12) return false; *outNumerator = signedNumerator; *outDenominator = d1; return true; } static QString simplifyRepeatedBasesInMultiplicativeTermForDisplay(const QString& termText) { if (termText.isEmpty()) return termText; QString workingTerm = termText; int negativeUnitFactorCount = 0; { static const QRegularExpression s_leadingNegativeUnitMultiplier( QStringLiteral(R"(^\s*[−-]1\s*(?:\*|·|×)\s*(.+)$)")); const QRegularExpressionMatch match = s_leadingNegativeUnitMultiplier.match(workingTerm); if (match.hasMatch()) { workingTerm = match.captured(1); ++negativeUnitFactorCount; } static const QRegularExpression s_trailingDivisionNegativeOne( QStringLiteral(R"(\s*(?:/|÷|⧸)\s*(?:[−-]1|\([−-]1\))\s*$)")); static const QRegularExpression s_trailingMultiplicationNegativeOne( QStringLiteral(R"(\s*(?:\*|·|×)\s*(?:[−-]1|\([−-]1\))\s*$)")); static const QRegularExpression s_trailingNeutralOne( QStringLiteral(R"(\s*(?:/|÷|⧸|\*|·|×)\s*(?:\+?1|\(\+?1\))\s*$)")); while (true) { QString updated = workingTerm; updated.replace(s_trailingDivisionNegativeOne, QString()); if (updated != workingTerm) { workingTerm = updated; ++negativeUnitFactorCount; continue; } updated = workingTerm; updated.replace(s_trailingMultiplicationNegativeOne, QString()); if (updated != workingTerm) { workingTerm = updated; ++negativeUnitFactorCount; continue; } updated = workingTerm; updated.replace(s_trailingNeutralOne, QString()); if (updated == workingTerm) break; workingTerm = updated; } } auto simplifyMultiplicationOnlySegment = [](const QString& segmentText) { if (segmentText.isEmpty()) return segmentText; QVector factors; QVector operators; int depth = 0; int partStart = 0; for (int i = 0; i < segmentText.size(); ++i) { const QChar ch = segmentText.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; continue; } if (depth == 0 && (ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp)) { factors.append(segmentText.mid(partStart, i - partStart)); operators.append(QString(ch)); partStart = i + 1; } } factors.append(segmentText.mid(partStart)); if (factors.size() < 2) return segmentText; QHash totalExponentsByBase; QHash representativeBaseByKey; for (int i = 0; i < factors.size(); ++i) { QString base; int exponent = 0; if (!parseSimplifiablePowerFactor(factors.at(i), &base, &exponent)) { continue; } const QString baseKey = canonicalSimplifiableBaseKeyForDisplay(base); if (!representativeBaseByKey.contains(baseKey)) representativeBaseByKey.insert(baseKey, base); totalExponentsByBase[baseKey] += exponent; } QString simplified; QSet emittedBaseKeys; bool hasOutput = false; int factorIndex = 0; while (factorIndex < factors.size()) { QString base; int exponent = 0; const bool isSimplifiableFactor = parseSimplifiablePowerFactor(factors.at(factorIndex), &base, &exponent); if (!isSimplifiableFactor) { if (hasOutput && factorIndex > 0) simplified += operators.at(factorIndex - 1); simplified += factors.at(factorIndex); hasOutput = true; ++factorIndex; continue; } const QString baseKey = canonicalSimplifiableBaseKeyForDisplay(base); if (emittedBaseKeys.contains(baseKey)) { ++factorIndex; continue; } emittedBaseKeys.insert(baseKey); if (hasOutput && factorIndex > 0) simplified += operators.at(factorIndex - 1); const int totalExponent = totalExponentsByBase.value(baseKey, 0); const QString representativeBase = representativeBaseByKey.value(baseKey, base); if (totalExponent > 1) { simplified += representativeBase; simplified += QStringLiteral("^%1").arg(totalExponent); } else { simplified += factors.at(factorIndex); } hasOutput = true; ++factorIndex; } QVector finalFactors; QVector finalOperators; int finalDepth = 0; int finalStart = 0; for (int i = 0; i < simplified.size(); ++i) { const QChar ch = simplified.at(i); if (ch == MathDsl::GroupStart) { ++finalDepth; continue; } if (ch == MathDsl::GroupEnd) { if (finalDepth > 0) --finalDepth; continue; } if (finalDepth == 0 && (ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp)) { finalFactors.append(simplified.mid(finalStart, i - finalStart)); finalOperators.append(QString(ch)); finalStart = i + 1; } } finalFactors.append(simplified.mid(finalStart)); int firstNumericIndex = -1; double numericProduct = 1.0; int numericCount = 0; bool hasSignedNumericFactor = false; auto isParenthesizedSignedDecimalFactor = [](const QString& factorText) { QString text = factorText.trimmed(); if (!(text.startsWith(MathDsl::GroupStart) && text.endsWith(MathDsl::GroupEnd))) return false; text = text.mid(1, text.size() - 2).trimmed(); return isSignedDecimalNumberText(text) && !isUnsignedDecimalNumberText(text); }; for (int i = 0; i < finalFactors.size(); ++i) { const QString factor = finalFactors.at(i); if (isSignedDecimalNumberText(factor) && !isUnsignedDecimalNumberText(factor)) hasSignedNumericFactor = true; if (isParenthesizedSignedDecimalFactor(factor)) hasSignedNumericFactor = true; if (!isUnsignedDecimalNumberText(finalFactors.at(i)) || !isSafeForDoubleArithmetic(finalFactors.at(i))) continue; if (firstNumericIndex < 0) firstNumericIndex = i; bool ok = false; const double value = finalFactors.at(i).toDouble(&ok); if (!ok) continue; numericProduct *= value; ++numericCount; } if (hasSignedNumericFactor) return simplified; if (numericCount > 1) { finalFactors[firstNumericIndex] = formatSimplifiedDecimal(numericProduct); for (int i = finalFactors.size() - 1; i >= 0; --i) { if (i == firstNumericIndex || !isUnsignedDecimalNumberText(finalFactors.at(i)) || !isSafeForDoubleArithmetic(finalFactors.at(i))) continue; finalFactors.removeAt(i); finalOperators.removeAt(i - 1); } QString rebuiltNumeric = finalFactors.at(0); for (int i = 1; i < finalFactors.size(); ++i) { rebuiltNumeric += finalOperators.at(i - 1); rebuiltNumeric += finalFactors.at(i); } return rebuiltNumeric; } return simplified; }; auto simplifyPostDivisionSegment = [&simplifyMultiplicationOnlySegment](const QString& segmentText) { if (segmentText.isEmpty()) return segmentText; QVector factors; QVector operators; int depth = 0; int partStart = 0; for (int i = 0; i < segmentText.size(); ++i) { const QChar ch = segmentText.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; continue; } if (depth == 0 && (ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp)) { factors.append(segmentText.mid(partStart, i - partStart)); operators.append(QString(ch)); partStart = i + 1; } } factors.append(segmentText.mid(partStart)); if (factors.size() <= 1) return segmentText; QString tail; tail += factors.at(1); for (int i = 2; i < factors.size(); ++i) { tail += operators.at(i - 1); tail += factors.at(i); } tail = simplifyMultiplicationOnlySegment(tail); QString rebuilt = factors.at(0); rebuilt += operators.at(0); rebuilt += tail; return rebuilt; }; QVector divisionSegments; QVector divisionOperators; int depth = 0; int segmentStart = 0; for (int i = 0; i < workingTerm.size(); ++i) { const QChar ch = workingTerm.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; continue; } if (depth == 0 && (ch == MathDsl::DivOp || ch == MathDsl::IntDivOp)) { divisionSegments.append(workingTerm.mid(segmentStart, i - segmentStart)); divisionOperators.append(QString(ch)); segmentStart = i + 1; } } divisionSegments.append(workingTerm.mid(segmentStart)); auto foldNumericDenominatorIntoPreviousSegment = [](QString* previousSegment, const QString& denominatorText) { if (!isUnsignedDecimalNumberText(denominatorText) || !isSafeForDoubleArithmetic(denominatorText)) return false; bool okDen = false; const double den = denominatorText.toDouble(&okDen); if (!okDen || den == 0.0) return false; QString prev = *previousSegment; QVector factors; QVector operators; int depth = 0; int partStart = 0; for (int i = 0; i < prev.size(); ++i) { const QChar ch = prev.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; continue; } if (depth == 0 && (ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp)) { factors.append(prev.mid(partStart, i - partStart)); operators.append(QString(ch)); partStart = i + 1; } } factors.append(prev.mid(partStart)); if (factors.size() <= 1) return false; for (int i = 1; i < factors.size(); ++i) { if (!isUnsignedDecimalNumberText(factors.at(i)) || !isSafeForDoubleArithmetic(factors.at(i))) continue; bool okNum = false; const double num = factors.at(i).toDouble(&okNum); if (!okNum) continue; factors[i] = formatSimplifiedDecimal(num / den); QString rebuilt = factors.at(0); for (int j = 1; j < factors.size(); ++j) { rebuilt += operators.at(j - 1); rebuilt += factors.at(j); } *previousSegment = rebuilt; return true; } return false; }; QString rebuilt; if (divisionOperators.isEmpty()) { QString simplified = simplifyMultiplicationOnlySegment(workingTerm); if ((negativeUnitFactorCount % 2) != 0 && !simplified.isEmpty()) { if (simplified == QLatin1String("1")) return QStringLiteral("-1"); return QStringLiteral("-") + simplified; } return simplified; } else { QVector simplifiedSegments; simplifiedSegments.reserve(divisionSegments.size()); for (int i = 0; i < divisionSegments.size(); ++i) { const bool followsDivisionOperator = i > 0 && (divisionOperators.at(i - 1) == QLatin1String("/") || divisionOperators.at(i - 1) == QLatin1String("\\")); simplifiedSegments.append(followsDivisionOperator ? simplifyPostDivisionSegment(divisionSegments.at(i)) : simplifyMultiplicationOnlySegment(divisionSegments.at(i))); } for (int i = 1; i < simplifiedSegments.size(); ++i) { if (divisionOperators.at(i - 1) != QLatin1String("/")) continue; if (i <= 1 || divisionOperators.at(i - 2) != QLatin1String("/")) continue; QString previous = simplifiedSegments.at(i - 1); if (!foldNumericDenominatorIntoPreviousSegment(&previous, simplifiedSegments.at(i))) continue; simplifiedSegments[i - 1] = previous; simplifiedSegments.removeAt(i); divisionOperators.removeAt(i - 1); --i; } for (int i = 0; i < simplifiedSegments.size(); ++i) { rebuilt += simplifiedSegments.at(i); if (i < divisionOperators.size()) rebuilt += divisionOperators.at(i); } } auto simplifyParenthesizedDenominators = [&simplifyMultiplicationOnlySegment](const QString& text) { QString out; out.reserve(text.size()); for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch != MathDsl::DivOp || i + 1 >= text.size() || text.at(i + 1) != MathDsl::GroupStart) { out += ch; continue; } int depth = 0; int closePos = -1; for (int j = i + 1; j < text.size(); ++j) { const QChar inner = text.at(j); if (inner == MathDsl::GroupStart) { ++depth; } else if (inner == MathDsl::GroupEnd) { --depth; if (depth == 0) { closePos = j; break; } } } if (closePos < 0) { out += ch; continue; } const QString inside = text.mid(i + 2, closePos - (i + 2)); const Tokens insideTokens = Evaluator::instance()->scan(inside); QString simplifiedInside = inside; if (!insideTokens.isEmpty()) simplifiedInside = simplifyRepeatedMultiplicativeBasesForDisplay(inside, insideTokens); else simplifiedInside = simplifyMultiplicationOnlySegment(inside); QString base; int exponent = 0; if (parseSimplifiablePowerFactor(simplifiedInside, &base, &exponent)) { out += MathDsl::DivOp; out += simplifiedInside; } else { out += MathDsl::DivOp; out += MathDsl::GroupStart; out += simplifiedInside; out += MathDsl::GroupEnd; } i = closePos; } return out; }; rebuilt = simplifyParenthesizedDenominators(rebuilt); auto simplifyAlgebraicMulDivChain = [&negativeUnitFactorCount, &workingTerm](const QString& text) { if (RegExpPatterns::simpleParenthesizedDenominatorQuotient().match(text).hasMatch()) return text; auto isFullyWrappedByOuterParens = [](const QString& expr) { if (expr.size() < 2 || expr.at(0) != MathDsl::GroupStart || expr.at(expr.size() - 1) != MathDsl::GroupEnd) return false; int depth = 0; for (int i = 0; i < expr.size(); ++i) { const QChar ch = expr.at(i); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd) --depth; if (depth == 0 && i < expr.size() - 1) return false; } return depth == 0; }; auto normalizeSimplifiableSignedFactor = [&isFullyWrappedByOuterParens](const QString& factor, QString* unsignedFactor, int* signOut) { QString normalized = factor.trimmed(); while (isFullyWrappedByOuterParens(normalized)) normalized = normalized.mid(1, normalized.size() - 2).trimmed(); int sign = 1; while (!normalized.isEmpty()) { const QChar ch = normalized.at(0); if (ch == MathDsl::AddOp) { normalized = normalized.mid(1).trimmed(); continue; } if (isMinus(ch)) { sign = -sign; normalized = normalized.mid(1).trimmed(); continue; } break; } while (isFullyWrappedByOuterParens(normalized)) normalized = normalized.mid(1, normalized.size() - 2).trimmed(); if (normalized.isEmpty()) return false; *unsignedFactor = normalized; *signOut = sign; return true; }; auto tryFoldParenthesizedNumericAddSubFactor = [](const QString& factor, QString* foldedUnsignedFactor) { QString normalized = factor.trimmed(); QString inner = normalized; if (normalized.startsWith(MathDsl::GroupStart) && normalized.endsWith(MathDsl::GroupEnd)) inner = normalized.mid(1, normalized.size() - 2).trimmed(); if (inner.isEmpty()) return false; const Tokens innerTokens = Evaluator::instance()->scan(inner); if (innerTokens.isEmpty()) return false; double total = 0.0; QString pendingOp = QStringLiteral("+"); bool expectValue = true; for (const Token& token : innerTokens) { if (expectValue) { if (!token.isNumber()) return false; const QString numberText = token.text().trimmed(); if (!isSignedDecimalNumberText(numberText) || !isSafeForDoubleArithmetic(numberText)) { return false; } bool ok = false; const double value = numberText.toDouble(&ok); if (!ok) return false; total += (pendingOp == QLatin1String("-")) ? -value : value; expectValue = false; continue; } const Token::Operator op = token.asOperator(); if (op != Token::Addition && op != Token::Subtraction) return false; pendingOp = token.text(); expectValue = true; } if (expectValue) return false; *foldedUnsignedFactor = formatSimplifiedDecimal(total); return true; }; auto splitTopLevelMulDivChain = [](const QString& expr, QVector* outFactors, QVector* outOperators) { outFactors->clear(); outOperators->clear(); int depth = 0; int partStart = 0; for (int i = 0; i < expr.size(); ++i) { const QChar ch = expr.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; continue; } if (depth == 0 && (ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp || ch == MathDsl::DivOp || ch == UnicodeChars::DivisionSign // ÷ || ch == UnicodeChars::BigSolidus // ⧸ || ch == UnicodeChars::DivisionSlash // ∕ || ch == MathDsl::IntDivOp)) { outFactors->append(expr.mid(partStart, i - partStart)); outOperators->append(QString(ch)); partStart = i + 1; } else if (depth == 0 && (ch == MathDsl::AddOp || ch == MathDsl::SubOpAl1 || ch == MathDsl::SubOp)) { return false; } } outFactors->append(expr.mid(partStart)); return outFactors->size() > 1; }; QVector factors; QVector operators; int depth = 0; int partStart = 0; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; continue; } if (depth == 0 && (ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp || ch == MathDsl::DivOp)) { factors.append(text.mid(partStart, i - partStart)); operators.append(QString(ch)); partStart = i + 1; } else if (depth == 0 && ch == MathDsl::IntDivOp) { return text; } } factors.append(text.mid(partStart)); if (factors.size() < 2) return text; QHash exponentByBase; QHash representativeBaseByKey; QVector baseOrder; double numericCoefficient = 1.0; int numericFactorCount = 0; bool hasAlgebraicReduction = text != workingTerm; const int previousNegativeFactorCount = negativeUnitFactorCount; bool hasNonNumericBase = false; bool hasOnlyUnitBases = true; auto combineMulDivOps = [](const QString& outerOp, const QString& innerOp) { auto isDivisionOp = [](const QString& opText) { return opText == QLatin1String("/") || opText == QLatin1String("\\") || opText == QString(UnicodeChars::DivisionSign) // ÷ || opText == QString(UnicodeChars::BigSolidus) // ⧸ || opText == QString(UnicodeChars::DivisionSlash); // ∕ }; const bool outerIsDiv = isDivisionOp(outerOp); const bool innerIsDiv = isDivisionOp(innerOp); if (outerIsDiv) return innerIsDiv ? QStringLiteral("*") : QStringLiteral("/"); return innerOp; }; auto isUnitOnlyBase = [](const QString& baseText) { const Tokens baseTokens = Evaluator::instance()->scan(baseText); if (!baseTokens.valid() || baseTokens.isEmpty()) return false; bool hasUnitIdentifier = false; for (const Token& token : baseTokens) { if (token.isUnitIdentifier()) { hasUnitIdentifier = true; continue; } if (token.isNumber()) continue; const Token::Operator op = token.asOperator(); if (op == Token::AssociationStart || op == Token::AssociationEnd || op == Token::Exponentiation || op == Token::Multiplication || op == Token::Division || op == Token::Addition || op == Token::Subtraction) { continue; } return false; } return hasUnitIdentifier; }; for (int i = 0; i < factors.size(); ++i) { QString unsignedFactor; int factorSign = 1; if (!normalizeSimplifiableSignedFactor(factors.at(i), &unsignedFactor, &factorSign)) return text; QString foldedNumericFactor; if (tryFoldParenthesizedNumericAddSubFactor(unsignedFactor, &foldedNumericFactor)) { hasAlgebraicReduction |= foldedNumericFactor != unsignedFactor; unsignedFactor = foldedNumericFactor; } if (factorSign < 0) ++negativeUnitFactorCount; const QString op = (i == 0) ? QStringLiteral("*") : operators.at(i - 1); QVector chainFactors; QVector chainOperators; if (!splitTopLevelMulDivChain(unsignedFactor, &chainFactors, &chainOperators)) { chainFactors = { unsignedFactor }; } for (int j = 0; j < chainFactors.size(); ++j) { QString chainFactor = chainFactors.at(j).trimmed(); QString foldedChainFactor; if (tryFoldParenthesizedNumericAddSubFactor(chainFactor, &foldedChainFactor)) { hasAlgebraicReduction |= foldedChainFactor != chainFactor; chainFactor = foldedChainFactor; } QString base; int exponent = 0; if (!parseSimplifiablePowerFactor(chainFactor, &base, &exponent)) return text; const QString innerOp = (j == 0) ? QStringLiteral("*") : chainOperators.at(j - 1); const QString effectiveOp = combineMulDivOps(op, innerOp); const int sign = (effectiveOp == QLatin1String("/")) ? -1 : 1; if (isUnsignedDecimalNumberText(base) && isSafeForDoubleArithmetic(base)) { bool ok = false; const double value = base.toDouble(&ok); if (!ok) return text; ++numericFactorCount; hasAlgebraicReduction |= numericFactorCount > 1 || value == 1.0 || exponent != 1; numericCoefficient *= std::pow(value, sign * exponent); } else if (!isUnsignedDecimalNumberText(base)) { const QString baseKey = canonicalSimplifiableBaseKeyForDisplay(base); if (!exponentByBase.contains(baseKey)) { baseOrder.append(baseKey); representativeBaseByKey.insert(baseKey, base); } else { hasAlgebraicReduction = true; } hasAlgebraicReduction |= exponent == 0; exponentByBase[baseKey] += sign * exponent; hasNonNumericBase = true; if (hasOnlyUnitBases && !isUnitOnlyBase(base)) hasOnlyUnitBases = false; } else { return text; } } } if (!hasNonNumericBase) return formatSimplifiedDecimal(numericCoefficient); // Moving a denominator into a leading coefficient does not simplify // anything. Keep the existing form unless factors actually reduce. if (!hasAlgebraicReduction) { negativeUnitFactorCount = previousNegativeFactorCount; return text; } QStringList positiveFactors; QStringList negativeFactors; for (const QString& baseKey : baseOrder) { const int exponent = exponentByBase.value(baseKey, 0); const QString base = representativeBaseByKey.value(baseKey, baseKey); if (exponent > 0) { positiveFactors.append(exponent == 1 ? base : QStringLiteral("%1^%2").arg(base).arg(exponent)); } else if (exponent < 0) { const int denExp = -exponent; negativeFactors.append(denExp == 1 ? base : QStringLiteral("%1^%2").arg(base).arg(denExp)); } } QString result; const bool coefficientIsOne = std::abs(numericCoefficient - 1.0) < 1e-12; const bool shouldShowUnitCoefficientOne = coefficientIsOne && hasOnlyUnitBases && (!positiveFactors.isEmpty() || !negativeFactors.isEmpty()); if (!coefficientIsOne || shouldShowUnitCoefficientOne || (positiveFactors.isEmpty() && !negativeFactors.isEmpty())) { QString coefficientText = formatSimplifiedDecimal(numericCoefficient); qint64 num = 0; qint64 den = 0; if (approximateRationalFromDouble(numericCoefficient, 1000000, &num, &den) && den != 1) { coefficientText = QStringLiteral("%1/%2").arg(num).arg(den); } result += coefficientText; } if (!positiveFactors.isEmpty()) { if (!result.isEmpty()) result += MathDsl::MulOpAl1; result += positiveFactors.join(QString(MathDsl::MulOpAl1)); } for (const QString& factor : negativeFactors) { if (result.isEmpty()) result = QStringLiteral("1"); result += MathDsl::DivOp; result += factor; } return result.isEmpty() ? text : result; }; QString simplified = simplifyAlgebraicMulDivChain(rebuilt); if ((negativeUnitFactorCount % 2) != 0 && !simplified.isEmpty()) { if (simplified == QLatin1String("1")) return QStringLiteral("-1"); return QStringLiteral("-") + simplified; } return simplified; } static QString simplifyRepeatedMultiplicativeBasesForDisplay(const QString& expression, const Tokens& tokens) { if (tokens.isEmpty()) return expression; QVector topLevelBinaryAddSubTokenIndices; int depth = 0; for (int i = 0; i < tokens.size(); ++i) { const Token& token = tokens.at(i); const Token::Operator op = token.asOperator(); if (op == Token::AssociationStart) { ++depth; continue; } if (op == Token::AssociationEnd) { if (depth > 0) --depth; continue; } if (depth != 0 || (op != Token::Addition && op != Token::Subtraction)) continue; const bool hasLeftOperand = i > 0 && tokenCanEndOperandForDisplaySpacing(tokens.at(i - 1)); const bool hasRightOperand = i + 1 < tokens.size() && tokenCanStartOperandForDisplaySpacing(tokens.at(i + 1)); if (hasLeftOperand && hasRightOperand) topLevelBinaryAddSubTokenIndices.append(i); } auto tokenRangeText = [&expression, &tokens](int startIndex, int endIndex) { const int startPos = tokens.at(startIndex).pos(); const int endPos = tokens.at(endIndex).pos() + tokens.at(endIndex).size(); return expression.mid(startPos, endPos - startPos); }; if (topLevelBinaryAddSubTokenIndices.isEmpty()) return simplifyRepeatedBasesInMultiplicativeTermForDisplay(expression); QVector simplifiedTerms; QVector additiveOperators; int termStartIndex = 0; for (int splitPos = 0; splitPos < topLevelBinaryAddSubTokenIndices.size(); ++splitPos) { const int operatorIndex = topLevelBinaryAddSubTokenIndices.at(splitPos); const int termEndIndex = operatorIndex - 1; if (termEndIndex >= termStartIndex) { const QString termText = tokenRangeText(termStartIndex, termEndIndex); simplifiedTerms.append(simplifyRepeatedBasesInMultiplicativeTermForDisplay(termText)); } additiveOperators.append(tokenRangeText(operatorIndex, operatorIndex)); termStartIndex = operatorIndex + 1; } if (termStartIndex < tokens.size()) { const QString lastTermText = tokenRangeText(termStartIndex, tokens.size() - 1); simplifiedTerms.append(simplifyRepeatedBasesInMultiplicativeTermForDisplay(lastTermText)); } const auto isMinusOperator = [](const QString& op) { return op.size() == 1 && isMinus(op.at(0)); }; const auto normalizeFoldableNumericTerm = [&isMinusOperator](const QString& termText, double* out) { QString term = termText.trimmed(); if (isSignedDecimalNumberText(term) && isSafeForDoubleArithmetic(term)) { bool ok = false; const double value = term.toDouble(&ok); if (ok) { *out = value; return true; } } if (!(term.startsWith(MathDsl::GroupStart) && term.endsWith(MathDsl::GroupEnd))) return false; const QString inner = term.mid(1, term.size() - 2).trimmed(); const Tokens innerTokens = Evaluator::instance()->scan(inner); if (innerTokens.isEmpty()) return false; double total = 0.0; QString pendingOp = QStringLiteral("+"); bool expectValue = true; for (const Token& token : innerTokens) { if (expectValue) { if (!token.isNumber()) return false; const QString numberText = token.text().trimmed(); if (!isSignedDecimalNumberText(numberText) || !isSafeForDoubleArithmetic(numberText)) { return false; } bool ok = false; const double value = numberText.toDouble(&ok); if (!ok) return false; total += isMinusOperator(pendingOp) ? -value : value; expectValue = false; continue; } const Token::Operator op = token.asOperator(); if (op != Token::Addition && op != Token::Subtraction) return false; pendingOp = token.text(); expectValue = true; } if (expectValue) return false; *out = total; return true; }; const bool hasPercentTerm = std::any_of( simplifiedTerms.constBegin(), simplifiedTerms.constEnd(), [](const QString& term) { return term.contains(MathDsl::PercentOp); }); if (hasPercentTerm) { if (simplifiedTerms.isEmpty()) return expression; QVector normalizedTerms = simplifiedTerms; for (int i = 0; i < normalizedTerms.size(); ++i) { double value = 0.0; QString term = normalizedTerms.at(i).trimmed(); if (term.contains(MathDsl::PercentOp)) continue; if (isWrappedInOuterParentheses(term)) { const QString inner = term.mid(1, term.size() - 2); const Tokens innerTokens = Evaluator::instance()->scan(inner); if (!innerTokens.isEmpty()) { const QString simplifiedInner = simplifyRepeatedMultiplicativeBasesForDisplay(inner, innerTokens); term = QStringLiteral("(%1)").arg(simplifiedInner); } } if (normalizeFoldableNumericTerm(term, &value)) term = formatSimplifiedDecimal(value); normalizedTerms[i] = term; } QVector foldedTerms; QVector foldedOperators; QString currentTerm = normalizedTerms.at(0).trimmed(); for (int i = 1; i < normalizedTerms.size(); ++i) { const QString op = additiveOperators.at(i - 1); const QString nextTerm = normalizedTerms.at(i).trimmed(); double currentValue = 0.0; double nextValue = 0.0; const bool canFoldCurrent = !currentTerm.contains(MathDsl::PercentOp) && normalizeFoldableNumericTerm(currentTerm, ¤tValue); const bool canFoldNext = !nextTerm.contains(MathDsl::PercentOp) && normalizeFoldableNumericTerm(nextTerm, &nextValue); if ((op == QLatin1String("+") || isMinusOperator(op)) && canFoldCurrent && canFoldNext) { const double result = currentValue + (isMinusOperator(op) ? -nextValue : nextValue); currentTerm = formatSimplifiedDecimal(result); continue; } foldedTerms.append(currentTerm); foldedOperators.append(op); currentTerm = nextTerm; } foldedTerms.append(currentTerm); QString simplifiedPercentAware; simplifiedPercentAware += foldedTerms.at(0); for (int i = 1; i < foldedTerms.size(); ++i) { simplifiedPercentAware += foldedOperators.at(i - 1); simplifiedPercentAware += foldedTerms.at(i); } return simplifiedPercentAware; } QVector constantValues; QVector constantSigns; QVector keptTerms; QVector keptOperators; for (int i = 0; i < simplifiedTerms.size(); ++i) { QString term = simplifiedTerms.at(i).trimmed(); const QString op = (i == 0) ? QStringLiteral("+") : additiveOperators.at(i - 1); if (isSignedDecimalNumberText(term) && isSafeForDoubleArithmetic(term)) { bool ok = false; const double value = term.toDouble(&ok); if (ok) { constantValues.append(value); constantSigns.append(op); continue; } } if (keptTerms.isEmpty()) { if (isMinusOperator(op)) keptTerms.append(QStringLiteral("-") + term); else keptTerms.append(term); } else { keptOperators.append(op); keptTerms.append(term); } } double foldedConstant = 0.0; for (int i = 0; i < constantValues.size(); ++i) { const QString op = constantSigns.at(i); foldedConstant += isMinusOperator(op) ? -constantValues.at(i) : constantValues.at(i); } if (!constantValues.isEmpty()) { if (keptTerms.isEmpty()) { keptTerms.append(formatSimplifiedDecimal(foldedConstant)); } else if (foldedConstant > 0.0) { keptOperators.append(QStringLiteral("+")); keptTerms.append(formatSimplifiedDecimal(foldedConstant)); } else if (foldedConstant < 0.0) { keptOperators.append(QStringLiteral("-")); keptTerms.append(formatSimplifiedDecimal(-foldedConstant)); } } if (!keptTerms.isEmpty()) { auto canonicalizeBuiltInUnitAliases = [](const QString& termText) { const Tokens termTokens = Evaluator::instance()->scan(termText); if (!termTokens.valid() || termTokens.isEmpty()) return termText; QString canonical = termText; int offset = 0; for (const Token& token : termTokens) { const bool isBuiltInUnitToken = token.isUnitIdentifier() || (token.isIdentifier() && s_isBuiltInUnitIdentifier(token.text())); if (!isBuiltInUnitToken) continue; const QString normalizedUnit = normalizeUnitName(token.text()); if (normalizedUnit.isEmpty() || normalizedUnit == token.text()) continue; const int start = token.pos() + offset; if (start < 0 || start + token.size() > canonical.size()) continue; canonical.replace(start, token.size(), normalizedUnit); offset += normalizedUnit.size() - token.size(); } // Normalize bracketed aliases too ("[rev]" vs "[revolution]") // so additive term merging can treat them as the same base. int searchPos = 0; while (true) { const QRegularExpressionMatch m = RegExpPatterns::bracketedSimpleUnitIdentifier().match(canonical, searchPos); if (!m.hasMatch()) break; const QString rawIdentifier = m.captured(1); if (!s_isBuiltInUnitIdentifier(rawIdentifier)) { searchPos = m.capturedEnd(); continue; } const QString normalizedUnit = normalizeUnitName(rawIdentifier); if (!normalizedUnit.isEmpty()) { const QString replacement = QStringLiteral("[%1]").arg(normalizedUnit); canonical.replace(m.capturedStart(), m.capturedLength(), replacement); searchPos = m.capturedStart() + replacement.size(); } else { searchPos = m.capturedEnd(); } } canonical.remove(QRegularExpression(QStringLiteral("\\s+"))); return canonical; }; QHash termCoefficients; QVector termOrder; QHash termDisplayByKey; auto splitLeadingNumericCoefficient = [](const QString& termText, QString* baseOut, double* coefficientOut) { const Tokens t = Evaluator::instance()->scan(termText); if (t.valid() && t.size() >= 3 && t.at(0).isNumber() && t.at(1).asOperator() == Token::Multiplication) { const QString coeffText = t.at(0).text().trimmed(); if (isSignedDecimalNumberText(coeffText) && isSafeForDoubleArithmetic(coeffText)) { bool ok = false; const double coefficient = coeffText.toDouble(&ok); if (ok) { const int baseStart = t.at(2).pos(); const int baseEnd = t.at(t.size() - 1).pos() + t.at(t.size() - 1).size(); if (baseStart >= 0 && baseEnd > baseStart && baseEnd <= termText.size()) { const QString base = termText.mid(baseStart, baseEnd - baseStart).trimmed(); if (!base.isEmpty()) { *baseOut = base; *coefficientOut = coefficient; return true; } } } } } const QString trimmed = termText.trimmed(); int i = 0; bool hasNegativePrefix = false; if (i < trimmed.size() && (trimmed.at(i) == MathDsl::AddOp || isMinus(trimmed.at(i)))) { hasNegativePrefix = isMinus(trimmed.at(i)); ++i; } int numberStart = i; bool seenDigit = false; bool seenDot = false; while (i < trimmed.size()) { const QChar ch = trimmed.at(i); if (ch.isDigit()) { seenDigit = true; ++i; continue; } if (!seenDot && ch == QLatin1Char('.')) { seenDot = true; ++i; continue; } break; } if (!seenDigit) return false; QString coeffText = trimmed.mid(numberStart, i - numberStart); if (hasNegativePrefix) coeffText.prepend(MathDsl::SubOpAl1); while (i < trimmed.size() && trimmed.at(i).isSpace()) ++i; if (i >= trimmed.size()) return false; const QChar op = trimmed.at(i); // Fallback path for formatted text where scanner token kinds can // vary; keep operator matching on MathDsl multiplication symbols. const bool isMulOp = op == MathDsl::MulOpAl1 || op == MathDsl::MulDotOp || op == MathDsl::MulCrossOp; if (!isMulOp) return false; ++i; while (i < trimmed.size() && trimmed.at(i).isSpace()) ++i; if (i >= trimmed.size()) return false; const QString base = trimmed.mid(i).trimmed(); if (base.isEmpty()) return false; if (!isSignedDecimalNumberText(coeffText) || !isSafeForDoubleArithmetic(coeffText)) return false; bool ok = false; const double coefficient = coeffText.toDouble(&ok); if (!ok) return false; *baseOut = base; *coefficientOut = coefficient; return true; }; for (int i = 0; i < keptTerms.size(); ++i) { QString term = keptTerms.at(i).trimmed(); QString op = (i == 0) ? QString(MathDsl::AddOp) : keptOperators.at(i - 1); if (!term.isEmpty()) { bool termNegative = false; int signPos = 0; while (signPos < term.size()) { const QChar signCh = term.at(signPos); if (signCh == MathDsl::AddOp) { ++signPos; continue; } if (signCh == MathDsl::SubOpAl1 || signCh == MathDsl::SubOp) { termNegative = !termNegative; ++signPos; continue; } break; } if (signPos > 0) { term = term.mid(signPos).trimmed(); if (termNegative) op = isMinusOperator(op) ? QString(MathDsl::AddOp) : QString(MathDsl::SubOpAl1); } } if (term.isEmpty()) continue; double numericFactor = 1.0; QString baseTerm = term; if (splitLeadingNumericCoefficient(term, &baseTerm, &numericFactor)) term = baseTerm; const double signedCoefficient = (isMinusOperator(op) ? -1.0 : 1.0) * numericFactor; const QString termKey = canonicalizeBuiltInUnitAliases(term); if (!termCoefficients.contains(termKey)) { termOrder.append(termKey); termDisplayByKey.insert(termKey, term); } termCoefficients[termKey] += signedCoefficient; } QVector mergedTerms; QVector mergedOperators; for (const QString& termKey : termOrder) { const double coefficient = termCoefficients.value(termKey, 0.0); if (std::abs(coefficient) < 1e-12) continue; const QString term = termDisplayByKey.value(termKey, termKey); const bool isNegative = coefficient < 0.0; const double magnitude = std::abs(coefficient); QString mergedTerm; if (std::abs(magnitude - 1.0) < 1e-12) { mergedTerm = term; } else { mergedTerm = formatSimplifiedDecimal(magnitude) + QString(MathDsl::MulDotOp) + term; } if (mergedTerms.isEmpty()) { mergedTerms.append(isNegative ? QString(MathDsl::SubOpAl1) + mergedTerm : mergedTerm); } else { mergedOperators.append(isNegative ? QString(MathDsl::SubOpAl1) : QString(MathDsl::AddOp)); mergedTerms.append(mergedTerm); } } if (!mergedTerms.isEmpty()) { keptTerms = mergedTerms; keptOperators = mergedOperators; } } QString simplified; if (!keptTerms.isEmpty()) { simplified += keptTerms.at(0); for (int i = 1; i < keptTerms.size(); ++i) { simplified += keptOperators.at(i - 1); simplified += keptTerms.at(i); } } return simplified.isEmpty() ? expression : simplified; } static QString formatInterpretedExpressionForDisplayImpl(const QString& expression, bool simplifyRepeatedMultiplicativeBases, const Evaluator* evaluator) { if (expression.isEmpty()) return expression; const int commentPos = findTopLevelCommentDelimiterPos(expression); const QString expressionPrefix = (commentPos >= 0) ? expression.left(commentPos).trimmed() : expression; QString commentSuffix; if (commentPos >= 0 && !simplifyRepeatedMultiplicativeBases) { const QString commentText = expression.mid(commentPos + 1).trimmed(); commentSuffix = QLatin1String(" ?"); if (!commentText.isEmpty()) commentSuffix += QLatin1String(" ") + commentText; } if (expressionPrefix.contains(MathDsl::ListStart)) { QString out; out.reserve(expressionPrefix.size() * 2); bool pendingSpace = false; for (int i = 0; i < expressionPrefix.size(); ++i) { const QChar ch = expressionPrefix.at(i); if (ch.isSpace()) { pendingSpace = true; continue; } if (ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp) { out = out.trimmed(); out += MathDsl::buildWrappedToken(MathDsl::MulCrossOp); pendingSpace = false; continue; } if (ch == MathDsl::AddOp || ((ch == MathDsl::SubOpAl1 || ch == MathDsl::SubOp) && i > 0)) { out = out.trimmed(); out += MathDsl::buildWrappedToken(ch == MathDsl::SubOp ? MathDsl::SubOpAl1 : ch); pendingSpace = false; continue; } if (ch == MathDsl::FunArgSep) { out = out.trimmed(); out += QStringLiteral("; "); pendingSpace = false; continue; } if (ch == MathDsl::UnitStart && !out.isEmpty() && !out.back().isSpace() && out.back() != MathDsl::ListStart && out.back() != MathDsl::GroupStart) { out += MathDsl::QuantSp; } if (pendingSpace && !out.isEmpty() && !out.back().isSpace() && out.back() != MathDsl::ListStart && ch != MathDsl::ListEnd) { out += QLatin1Char(' '); } out += ch; pendingSpace = false; } return out.trimmed() + commentSuffix; } const bool hasTrigFunction = RegExpPatterns::trigFunctionCall().match(expressionPrefix).hasMatch(); const bool allowAggressiveSimplification = simplifyRepeatedMultiplicativeBases // Keep unit-aware simplification conservative in general, but allow // trig-only expressions with explicit angle units (e.g. cos(pi[rad])) // to participate in symbolic folding. && ((!expressionPrefix.contains(MathDsl::UnitStart) && !expressionPrefix.contains(MathDsl::UnitEnd)) || hasTrigFunction); auto scanForDisplay = [](const QString& text) { // Interpreted expressions are internally dot-based. For comma-based // display styles, scanning with a strict single-radix setting can // misclassify '.' as grouping separator and corrupt token structure. // For display-only tokenization we temporarily enable "both radix // chars accepted" mode, scan, then restore the previous setting. // This keeps display formatting stable without changing evaluation // behavior or persisted style. Settings* settings = Settings::instance(); char previousRadix = 0; if (settings->isRadixCharacterBoth()) { previousRadix = MathDsl::MulOpAl1.toLatin1(); } else if (!settings->isRadixCharacterAuto()) { previousRadix = settings->radixCharacter(); } settings->setRadixCharacter(MathDsl::MulOpAl1.toLatin1()); const Tokens tokens = Evaluator::instance()->scan(text); settings->setRadixCharacter(previousRadix); return tokens; }; const Tokens scannedTokens = scanForDisplay(expressionPrefix); if (!scannedTokens.valid() || scannedTokens.isEmpty()) return expressionPrefix + commentSuffix; auto isKnownUnitIdentifier = [](const QString& tokenText) { Evaluator* evaluator = Evaluator::instance(); return s_isBuiltInUnitIdentifier(tokenText) || (evaluator && evaluator->hasUserUnit(tokenText)); }; bool hasUnitIdentifierToken = false; for (const Token& token : scannedTokens) { if (token.isUnitIdentifier() || (token.isIdentifier() && isKnownUnitIdentifier(token.text()))) { hasUnitIdentifierToken = true; break; } } const QString groupedExpression = groupHighPrecedenceAdditiveTermsForDisplay(expressionPrefix, scannedTokens); const Tokens groupedTokens = scanForDisplay(groupedExpression); if (!groupedTokens.valid() || groupedTokens.isEmpty()) return groupedExpression + commentSuffix; auto normalizeNeutralMultiplicativeOnes = [](const QString& text) { static const QRegularExpression s_trailingTimesOne( QStringLiteral(R"(\s*(?:\*|·|×)\s*1(?:[.,]0+)?\s*$)")); static const QRegularExpression s_leadingOneTimes( QStringLiteral(R"(^\s*1(?:[.,]0+)?\s*(?:\*|·|×)\s*)")); static const QRegularExpression s_trailingDivOne( QStringLiteral(R"(\s*(?:/|÷|⧸)\s*1(?:[.,]0+)?\s*$)")); QString normalized = text; bool changed = false; do { changed = false; QString updated = normalized; updated.replace(s_trailingTimesOne, QString()); if (updated != normalized) { normalized = updated; changed = true; } updated = normalized; updated.replace(s_leadingOneTimes, QString()); if (updated != normalized) { normalized = updated; changed = true; } updated = normalized; updated.replace(s_trailingDivOne, QString()); if (updated != normalized) { normalized = updated; changed = true; } } while (changed); auto isFullyWrappedByOuterParens = [](const QString& expr) { if (expr.size() < 2 || expr.at(0) != MathDsl::GroupStart || expr.at(expr.size() - 1) != MathDsl::GroupEnd) return false; int depth = 0; for (int i = 0; i < expr.size(); ++i) { const QChar ch = expr.at(i); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd) --depth; if (depth == 0 && i < expr.size() - 1) return false; } return depth == 0; }; while (isFullyWrappedByOuterParens(normalized)) normalized = normalized.mid(1, normalized.size() - 2).trimmed(); auto hasTopLevelLowPrecedenceOperator = [](const QString& expr) { int depth = 0; for (int i = 0; i < expr.size(); ++i) { const QChar ch = expr.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { if (depth > 0) --depth; continue; } if (depth != 0) continue; if (ch == MathDsl::AddOp || ch == MathDsl::BitAndOp || ch == MathDsl::BitOrOp || ch == MathDsl::FunArgSep || ch == MathDsl::Equals || ch == MathDsl::CommentSep || ch == MathDsl::LessThanOp || ch == MathDsl::GreaterThanOp) { return true; } if ((ch == MathDsl::SubOpAl1 || ch == MathDsl::SubOp) && i > 0) return true; } return false; }; auto isMulOp = [](QChar ch) { return ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp; }; auto unwrapEdgeParenthesizedMulDivFactor = [&](QString* expr) { QString t = expr->trimmed(); if (t.size() < 3) return false; // Unwrap "(factor) * rest" when factor has no top-level low-precedence ops. if (t.at(0) == MathDsl::GroupStart) { int depth = 0; int close = -1; for (int i = 0; i < t.size(); ++i) { const QChar ch = t.at(i); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd) { --depth; if (depth == 0) { close = i; break; } } } if (close > 0 && close < t.size() - 1) { int next = close + 1; while (next < t.size() && t.at(next).isSpace()) ++next; if (next < t.size() && isMulOp(t.at(next))) { const QString inner = t.mid(1, close - 1).trimmed(); const bool startsWithUnarySign = !inner.isEmpty() && (inner.at(0) == MathDsl::SubOpAl1 || inner.at(0) == MathDsl::SubOp || inner.at(0) == MathDsl::AddOp); if (!inner.isEmpty() && !startsWithUnarySign && !hasTopLevelLowPrecedenceOperator(inner)) { t = inner + t.mid(close + 1); *expr = t.trimmed(); return true; } } } } // Unwrap "left * (factor)" when factor has no top-level low-precedence ops. if (t.at(t.size() - 1) == MathDsl::GroupEnd) { int depth = 0; int open = -1; for (int i = t.size() - 1; i >= 0; --i) { const QChar ch = t.at(i); if (ch == MathDsl::GroupEnd) ++depth; else if (ch == MathDsl::GroupStart) { --depth; if (depth == 0) { open = i; break; } } } if (open > 0) { int prev = open - 1; while (prev >= 0 && t.at(prev).isSpace()) --prev; if (prev >= 0 && isMulOp(t.at(prev))) { const QString inner = t.mid(open + 1, t.size() - open - 2).trimmed(); const bool startsWithUnarySign = !inner.isEmpty() && (inner.at(0) == MathDsl::SubOpAl1 || inner.at(0) == MathDsl::SubOp || inner.at(0) == MathDsl::AddOp); if (!inner.isEmpty() && !startsWithUnarySign && !hasTopLevelLowPrecedenceOperator(inner)) { t = t.left(open) + inner; *expr = t.trimmed(); return true; } } } } return false; }; while (unwrapEdgeParenthesizedMulDivFactor(&normalized)) { // Keep unwrapping edge multiplicative wrappers until stable. } return normalized; }; QString displayExpression; if (allowAggressiveSimplification && (!hasUnitIdentifierToken || hasTrigFunction)) { displayExpression = simplifyRepeatedMultiplicativeBasesForDisplay(groupedExpression, groupedTokens); const QString normalized = normalizeNeutralMultiplicativeOnes(displayExpression); if (normalized != displayExpression) { const Tokens normalizedTokens = Evaluator::instance()->scan(normalized); displayExpression = normalizedTokens.isEmpty() ? normalized : simplifyRepeatedMultiplicativeBasesForDisplay(normalized, normalizedTokens); } } else { displayExpression = groupedExpression; } const Tokens tokens = scanForDisplay(displayExpression); if (!tokens.valid() || tokens.isEmpty()) return displayExpression + commentSuffix; bool hasUnitIdentifierTokenInDisplay = false; bool unitOnlyAddSubExpression = true; for (const Token& token : tokens) { if (token.isUnitIdentifier()) { hasUnitIdentifierTokenInDisplay = true; continue; } if (token.isIdentifier() && isKnownUnitIdentifier(token.text())) { hasUnitIdentifierTokenInDisplay = true; continue; } const Token::Operator op = token.asOperator(); if (op == Token::Addition || op == Token::Subtraction) continue; unitOnlyAddSubExpression = false; break; } unitOnlyAddSubExpression = unitOnlyAddSubExpression && hasUnitIdentifierTokenInDisplay; QString formatted; formatted.reserve(displayExpression.size() + tokens.size() * 2); auto parenthesisDepthBefore = [&tokens](int tokenIndex) { int depth = 0; for (int k = 0; k < tokenIndex; ++k) { const QString tokenText = tokens.at(k).text(); if (tokenText.size() != 1) continue; const QChar ch = tokenText.at(0); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd && depth > 0) { --depth; } } return depth; }; struct UnitBracketDisplayContext { bool compactDegreeSuffix = false; bool forceDegreeAlias = false; }; QVector unitBracketContextStack; auto currentUnitBracketContext = [&unitBracketContextStack]() -> UnitBracketDisplayContext* { return unitBracketContextStack.isEmpty() ? nullptr : &unitBracketContextStack.last(); }; auto isFunctionCallGroupEnd = [&tokens](int closeIndex) { if (closeIndex < 0 || closeIndex >= tokens.size()) return false; if (tokens.at(closeIndex).asOperator() != Token::AssociationEnd || tokens.at(closeIndex).text() != QLatin1String(")")) return false; int depth = 0; for (int i = closeIndex; i >= 0; --i) { const Token::Operator op = tokens.at(i).asOperator(); if (op == Token::AssociationEnd && tokens.at(i).text() == QLatin1String(")")) { ++depth; continue; } if (op == Token::AssociationStart && tokens.at(i).text() == QLatin1String("(")) { --depth; if (depth == 0) { return i > 0 && tokens.at(i - 1).isIdentifier(); } } } return false; }; auto normalizeCompoundDegreeUnitsInBracket = [](const QString& content) { if (content.isEmpty()) return content; QStringList factors; QStringList operators; QString current; int parenDepth = 0; auto flushCurrent = [&]() { factors.append(current.trimmed()); current.clear(); }; const auto isMultiplicationOp = [](const QChar& ch) { return ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp; }; for (int i = 0; i < content.size(); ++i) { const QChar ch = content.at(i); if (ch == MathDsl::GroupStart) { ++parenDepth; current += ch; continue; } if (ch == MathDsl::GroupEnd) { if (parenDepth > 0) --parenDepth; current += ch; continue; } if (parenDepth == 0 && (isMultiplicationOp(ch) || ch == MathDsl::DivOp)) { flushCurrent(); operators.append(QString(ch)); continue; } current += ch; } flushCurrent(); if (factors.size() <= 1) return content; const QString degreeAlias = Units::degreeAliasSymbol(); const QString degreeName = unitName(UnitId::Degree); const auto isDegreeFactor = [&](const QString& factor) { const QString t = factor.trimmed(); if (t.isEmpty()) return false; const QChar first = t.at(0); if (first == UnicodeChars::DegreeSign) return true; if (t.startsWith(degreeAlias)) { if (t.size() == degreeAlias.size()) return true; const QChar next = t.at(degreeAlias.size()); return !next.isLetter(); } if (t.startsWith(degreeName)) { if (t.size() == degreeName.size()) return true; const QChar next = t.at(degreeName.size()); return !next.isLetter(); } return false; }; const auto normalizeDegreeFactor = [&](const QString& factor) -> QString { const QString t = factor.trimmed(); if (t.isEmpty()) return t; if (t.at(0) == UnicodeChars::DegreeSign) { QString normalized = degreeAlias; normalized += t.mid(1); return normalized; } if (t.startsWith(degreeName)) { const int n = degreeName.size(); if (t.size() == n || !t.at(n).isLetter()) { QString normalized = degreeAlias; normalized += t.mid(n); return normalized; } } if (t.startsWith(degreeAlias)) return t; return t; }; bool hasDivision = false; for (const QString& opText : operators) { if (!opText.isEmpty() && opText.at(0) == MathDsl::DivOp) { hasDivision = true; break; } } bool changed = false; for (int i = 0; i < factors.size(); ++i) { if (isDegreeFactor(factors.at(i))) { const QString normalized = normalizeDegreeFactor(factors.at(i)); if (normalized != factors.at(i)) changed = true; factors[i] = normalized; } } if (!hasDivision) { QString degreeFactor; QStringList others; for (const QString& factor : factors) { if (degreeFactor.isEmpty() && isDegreeFactor(factor)) degreeFactor = normalizeDegreeFactor(factor); else others.append(factor.trimmed()); } if (!degreeFactor.isEmpty() && !others.isEmpty()) { changed = true; QString result = degreeFactor; const QString mulDotWrapped = QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp); for (const QString& factor : others) result += mulDotWrapped + factor; return result; } } if (!changed) return content; QString rebuilt; for (int i = 0; i < factors.size(); ++i) { if (i > 0 && i - 1 < operators.size()) rebuilt += operators.at(i - 1); rebuilt += factors.at(i).trimmed(); } return rebuilt; }; auto normalizeCompoundDegreeUnitsInDisplay = [&](QString text) { int i = 0; while (i < text.size()) { if (text.at(i) != MathDsl::UnitStart) { ++i; continue; } int depth = 1; int j = i + 1; for (; j < text.size(); ++j) { const QChar ch = text.at(j); if (ch == MathDsl::UnitStart) ++depth; else if (ch == MathDsl::UnitEnd) { --depth; if (depth == 0) break; } } if (j >= text.size()) break; const QString content = text.mid(i + 1, j - i - 1); QString normalized = normalizeCompoundDegreeUnitsInBracket(content); normalized = UnitDisplayFormat::normalizeUnitTextForDisplay(normalized); if (normalized != content) { text.replace(i + 1, j - i - 1, normalized); j = i + 1 + normalized.size(); } i = j + 1; } return text; }; for (int i = 0; i < tokens.size(); ++i) { const Token& token = tokens.at(i); const int parenthesisDepthBeforeToken = parenthesisDepthBefore(i); const Token::Operator op = token.asOperator(); const bool isSpacingOperator = op == Token::Addition || op == Token::Subtraction || op == Token::Multiplication || op == Token::Division || op == Token::Phasor || op == Token::IntegerDivision || op == Token::UnitConversion || op == Token::Assignment || op == Token::ArithmeticLeftShift || op == Token::ArithmeticRightShift; const QString operatorText = op == Token::Subtraction ? QString(MathDsl::SubOp) : token.text(); const bool shouldTreatIdentifierAsUnit = token.isIdentifier() && unitOnlyAddSubExpression && isKnownUnitIdentifier(operatorText) && !(evaluator ? evaluator : Evaluator::instance())->hasVariable(operatorText); const bool isUnitConversionTargetIdentifier = token.isIdentifier() && isKnownUnitIdentifier(operatorText) && i > 0 && tokens.at(i - 1).asOperator() == Token::UnitConversion; const bool isTemperatureConversionTargetIdentifier = isUnitConversionTargetIdentifier && Units::isAffineUnitName(operatorText); const bool isDisplayUnitToken = token.isUnitIdentifier() || shouldTreatIdentifierAsUnit; QString displayTokenText = isDisplayUnitToken ? UnitDisplayFormat::shortDisplayName(operatorText) : operatorText; if (isDisplayUnitToken) { const UnitId id = unitId(normalizeUnitName(operatorText)); if (id != UnitId::Unknown) { const QString symbol = unitSymbol(id); if (!symbol.isEmpty()) displayTokenText = symbol; } UnitBracketDisplayContext* unitContext = currentUnitBracketContext(); if (id == UnitId::Degree && unitContext && unitContext->forceDegreeAlias) { displayTokenText = Units::degreeAliasSymbol(); } } if (isTemperatureConversionTargetIdentifier) { const UnitId id = unitId(normalizeUnitName(operatorText)); QString symbol = UnitDisplayFormat::shortDisplayName(operatorText); if (id != UnitId::Unknown) { const QString candidate = unitSymbol(id); if (!candidate.isEmpty()) symbol = candidate; } displayTokenText = QStringLiteral("[%1]").arg(symbol); } const bool isInsideExplicitUnitBlock = i > 0 && tokens.at(i - 1).text().size() == 1 && tokens.at(i - 1).text().at(0) == MathDsl::UnitStart; if (isDisplayUnitToken && unitOnlyAddSubExpression && !isInsideExplicitUnitBlock) { displayTokenText = QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[%1]").arg(displayTokenText); } if (token.text().size() == 1 && token.text().at(0) == MathDsl::UnitStart) { const bool hasPreviousToken = i > 0; const Token previousToken = hasPreviousToken ? tokens.at(i - 1) : Token::null; const bool followsConversionArrow = hasPreviousToken && previousToken.asOperator() == Token::UnitConversion; const bool shouldAddValueUnitSpace = hasPreviousToken && (previousToken.isNumber() || previousToken.isIdentifier() || previousToken.isUnitIdentifier() || isFunctionCallGroupEnd(i - 1)); UnitBracketDisplayContext unitContext; int depth = 1; int closeIndex = -1; bool hasDivisionInside = false; for (int j = i + 1; j < tokens.size(); ++j) { const QString tokenText = tokens.at(j).text(); if (tokenText.size() == 1 && tokenText.at(0) == MathDsl::UnitStart) { ++depth; continue; } if (tokenText.size() == 1 && tokenText.at(0) == MathDsl::UnitEnd) { --depth; if (depth == 0) { closeIndex = j; break; } continue; } if (depth == 1 && tokens.at(j).asOperator() == Token::Division) hasDivisionInside = true; } const bool isAssignmentLeftSideUnitBlock = !hasPreviousToken && closeIndex >= 0 && closeIndex + 1 < tokens.size() && tokens.at(closeIndex + 1).asOperator() == Token::Assignment; const bool shouldInsertImplicitUnitOne = (!hasPreviousToken || previousToken.asOperator() == Token::Addition || previousToken.asOperator() == Token::Subtraction || previousToken.asOperator() == Token::Assignment || previousToken.asOperator() == Token::ListSeparator || previousToken.asOperator() == Token::AssociationStart) && !followsConversionArrow && !shouldAddValueUnitSpace && !isAssignmentLeftSideUnitBlock && i + 1 < tokens.size() && tokens.at(i + 1).isUnitIdentifier(); const bool isSimpleDegreeUnit = closeIndex == i + 2 && (tokens.at(i + 1).isUnitIdentifier() || (tokens.at(i + 1).isIdentifier() && isKnownUnitIdentifier(tokens.at(i + 1).text()))) && unitId(normalizeUnitName(tokens.at(i + 1).text())) == UnitId::Degree; unitContext.compactDegreeSuffix = isSimpleDegreeUnit && !followsConversionArrow && hasPreviousToken && previousToken.isNumber() && parenthesisDepthBeforeToken == 0; unitContext.forceDegreeAlias = hasDivisionInside; unitBracketContextStack.append(unitContext); if (shouldInsertImplicitUnitOne) { formatted += QStringLiteral("1"); formatted += MathDsl::QuantSp; } else if (shouldAddValueUnitSpace && !unitContext.compactDegreeSuffix) { formatted += MathDsl::QuantSp; } if (unitContext.compactDegreeSuffix) continue; } else if (token.text().size() == 1 && token.text().at(0) == MathDsl::UnitEnd) { UnitBracketDisplayContext unitContext; if (!unitBracketContextStack.isEmpty()) { unitContext = unitBracketContextStack.last(); unitBracketContextStack.removeLast(); } if (unitContext.compactDegreeSuffix) continue; } if (!isSpacingOperator) { formatted += displayTokenText; continue; } const bool hasLeftOperand = i > 0 && tokenCanEndOperandForDisplaySpacing(tokens.at(i - 1)); const bool hasRightOperand = i + 1 < tokens.size() && tokenCanStartOperandForDisplaySpacing(tokens.at(i + 1)); const bool isBinaryOperator = hasLeftOperand && hasRightOperand; if (!isBinaryOperator) { // Keep unary operators untouched (for example "−pi"). formatted += displayTokenText; continue; } if ((op == Token::Addition || op == Token::Subtraction) && startsWithImaginaryLiteralForDisplay(tokens, i + 1)) { // Keep "a+bj"/"a-bj" compact in complex-mode interpreted output. formatted += operatorText; continue; } if (op == Token::Multiplication && i > 0 && i + 1 < tokens.size() && tokens.at(i - 1).isNumber() && isImaginaryUnitTokenForDisplay(tokens.at(i + 1))) { // Render numeric imaginary literals as compact suffixes: "3j". continue; } if (op == Token::Addition) { formatted += MathDsl::AddWrap; formatted += MathDsl::AddOp; formatted += MathDsl::AddWrap; continue; } if (op == Token::Subtraction) { formatted += MathDsl::SubWrapSp; formatted += MathDsl::SubOp; formatted += MathDsl::SubWrapSp; continue; } if (op == Token::Division) { if (currentUnitBracketContext()) { formatted += MathDsl::DivOp; } else { formatted += MathDsl::DivWrap; formatted += MathDsl::DivOp; formatted += MathDsl::DivWrap; } continue; } if (op == Token::Multiplication) { const bool hasNumericLiteralLhs = isHardcodedNumericOperandOnLeftOfMultiplicationForDisplay( tokens, i, true); const bool hasNumericLiteralRhs = isHardcodedNumericOperandOnRightOfMultiplicationForDisplay( tokens, i, true); const QChar mulSign = (hasNumericLiteralLhs && hasNumericLiteralRhs) ? MathDsl::MulCrossOp : MathDsl::MulDotOp; const QChar mulSpace = mulSign == MathDsl::MulCrossOp ? MathDsl::MulCrossWrapSp : MathDsl::MulDotWrapSp; formatted += mulSpace; formatted += mulSign; formatted += mulSpace; continue; } formatted += MathDsl::AddWrap; formatted += displayTokenText; formatted += MathDsl::AddWrap; } formatted = normalizeCompoundDegreeUnitsInDisplay(formatted); formatted = renderIntegerPowersAsSuperscriptsForDisplay( formatted, allowAggressiveSimplification); formatted = normalizeCompoundDegreeUnitsInDisplay(formatted); return formatted + commentSuffix; } QString Evaluator::simplifyInterpretedExpression(const QString& expression) { if (expression.isEmpty()) return expression; const int commentPos = findTopLevelCommentDelimiterPos(expression); const QString expressionPrefix = (commentPos >= 0) ? expression.left(commentPos).trimmed() : expression; if (expressionPrefix.contains(MathDsl::UnitStart) || expressionPrefix.contains(MathDsl::UnitEnd)) { // Most unit-bearing interpreted expressions skip symbolic simplification // to avoid invalid rewrites across dimensions. Trig expressions are a // safe exception because explicit angle units are consumed by the trig // call and do not dimension the scalar result. const bool hasTrigFunction = RegExpPatterns::trigFunctionCall().match(expressionPrefix).hasMatch(); if (!hasTrigFunction) return expressionPrefix; } auto scanForDisplay = [](const QString& text) { // Same display-tokenization strategy as above: // force temporary dual-radix scan mode so internal dot-decimal // interpreted text is tokenized correctly under comma-style displays. Settings* settings = Settings::instance(); char previousRadix = 0; if (settings->isRadixCharacterBoth()) { previousRadix = MathDsl::MulOpAl1.toLatin1(); } else if (!settings->isRadixCharacterAuto()) { previousRadix = settings->radixCharacter(); } settings->setRadixCharacter(MathDsl::MulOpAl1.toLatin1()); const Tokens tokens = Evaluator::instance()->scan(text); settings->setRadixCharacter(previousRadix); return tokens; }; const Tokens scannedTokens = scanForDisplay(expressionPrefix); if (!scannedTokens.valid() || scannedTokens.isEmpty()) return expressionPrefix; const QString groupedExpression = groupHighPrecedenceAdditiveTermsForDisplay(expressionPrefix, scannedTokens); const Tokens groupedTokens = scanForDisplay(groupedExpression); if (!groupedTokens.valid() || groupedTokens.isEmpty()) return groupedExpression; QString simplifiedExpression = simplifyRepeatedMultiplicativeBasesForDisplay(groupedExpression, groupedTokens); // Normalize neutral multiplicative factors that can block symbolic // cancellations in the display simplifier (for example "(a/b)*1" -> "a/b"). static const QRegularExpression s_trailingTimesOne( QStringLiteral(R"(\s*(?:\*|·|×)\s*1(?:[.,]0+)?\s*$)")); static const QRegularExpression s_leadingOneTimes( QStringLiteral(R"(^\s*1(?:[.,]0+)?\s*(?:\*|·|×)\s*)")); static const QRegularExpression s_trailingDivOne( QStringLiteral(R"(\s*(?:/|÷|⧸)\s*1(?:[.,]0+)?\s*$)")); QString normalized = simplifiedExpression; bool changed = false; do { changed = false; QString updated = normalized; updated.replace(s_trailingTimesOne, QString()); if (updated != normalized) { normalized = updated; changed = true; } updated = normalized; updated.replace(s_leadingOneTimes, QString()); if (updated != normalized) { normalized = updated; changed = true; } updated = normalized; updated.replace(s_trailingDivOne, QString()); if (updated != normalized) { normalized = updated; changed = true; } } while (changed); if (normalized != simplifiedExpression) { const Tokens normalizedTokens = scanForDisplay(normalized); if (normalizedTokens.valid() && !normalizedTokens.isEmpty()) simplifiedExpression = simplifyRepeatedMultiplicativeBasesForDisplay(normalized, normalizedTokens); else simplifiedExpression = normalized; } return simplifiedExpression; } QString Evaluator::formatInterpretedExpressionForDisplay(const QString& expression) { return formatInterpretedExpressionForDisplayImpl(expression, false, nullptr); } QString Evaluator::formatInterpretedExpressionForDisplay(const QString& expression, const Evaluator* evaluator) { return formatInterpretedExpressionForDisplayImpl(expression, false, evaluator); } QString Evaluator::formatInterpretedExpressionSimplifiedForDisplay(const QString& expression) { return formatInterpretedExpressionForDisplayImpl(expression, true, nullptr); } QString Evaluator::formatInterpretedExpressionSimplifiedForDisplay(const QString& expression, const Evaluator* evaluator) { return formatInterpretedExpressionForDisplayImpl(expression, true, evaluator); } static QStringList splitTopLevelFunctionArguments(const QString& text) { QStringList arguments; int parenDepth = 0; int argumentStart = 0; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == '(') { ++parenDepth; } else if (ch == ')') { if (parenDepth > 0) --parenDepth; } else if (ch == ';' && parenDepth == 0) { arguments.append(text.mid(argumentStart, i - argumentStart).trimmed()); argumentStart = i + 1; } } arguments.append(text.mid(argumentStart).trimmed()); return arguments; } TokenStack::TokenStack() : QVector() { topIndex = 0; m_error = ""; ensureSpace(); } bool TokenStack::isEmpty() const { return topIndex == 0; } unsigned TokenStack::itemCount() const { return topIndex; } void TokenStack::push(const Token& token) { ensureSpace(); (*this)[topIndex++] = token; } Token TokenStack::pop() { if (topIndex > 0) return Token(at(--topIndex)); m_error = "token stack is empty (BUG)"; return Token(); } const Token& TokenStack::top() { return top(0); } const Token& TokenStack::top(unsigned index) { return (topIndex > (int)index) ? at(topIndex - index - 1) : Token::null; } void TokenStack::ensureSpace() { int length = size(); while (topIndex >= length) { length += 10; resize(length); } } /** Remove \a count tokens from the top of the stack, add a stxAbstract token * to the top and adjust its text position and minimum precedence. * * \param minPrecedence minimum precedence to set the top token, or * \c INVALID_PRECEDENCE if this method should use the minimum value from * the removed tokens. */ void TokenStack::reduce(int count, int minPrecedence) { // assert(itemCount() > count); QList tokens; for (int i = 0 ; i < count ; ++i) tokens.append(pop()); reduce(tokens, Token(Token::stxAbstract), minPrecedence); } /** Remove \a count tokens from the top of the stack, push \a top to the top * and adjust its text position and minimum precedence. * * \param minPrecedence minimum precedence to set the top token, or * \c INVALID_PRECEDENCE if this method should use the minimum value * from the removed tokens. */ void TokenStack::reduce(int count, Token&& top, int minPrecedence) { // assert(itemCount() >= count); QList tokens; for (int i = 0 ; i < count ; ++i) tokens.append(pop()); reduce(tokens, std::forward(top), minPrecedence); } /** Push \a top to the top and adjust its text position and minimum precedence * using \a tokens. * * \param minPrecedence minimum precedence to set the top token, or * \c INVALID_PRECEDENCE if this method should use the minimum value from the * removed tokens. */ void TokenStack::reduce(QList tokens, Token&& top, int minPrecedence) { #ifdef EVALUATOR_DEBUG { const auto& _tokens = tokens; qDebug() << "reduce(" << _tokens.size() << ", " << top.description() << ", " << minPrecedence << ")"; for (const auto& t : _tokens) qDebug() << t.description(); } #endif // EVALUATOR_DEBUG std::sort(tokens.begin(), tokens.end(), tokenPositionCompare); bool computeMinPrec = (minPrecedence == INVALID_PRECEDENCE); int min_prec = computeMinPrec ? MAX_PRECEDENCE : minPrecedence; int start = -1, end = -1; const auto& _tokens = tokens; for (auto& token : _tokens) { if (computeMinPrec) { Token::Operator op = token.asOperator(); if (op != Token::Invalid) { int prec = opPrecedence(op); if (prec < min_prec) min_prec = prec; } } if (token.pos() == -1 && token.size() == -1) continue; if (token.pos() == -1 || token.size() == -1) { #ifdef EVALUATOR_DEBUG qDebug() << "BUG: found token with either pos or size not set, " "but not both."; #endif // EVALUATOR_DEBUG continue; } if (start == -1) { start = token.pos(); } else { #ifdef EVALUATOR_DEBUG if (token.pos() != end) qDebug() << "BUG: tokens expressions are not successive."; #endif // EVALUATOR_DEBUG } end = token.pos() + token.size(); } if (start != -1) { top.setPos(start); top.setSize(end - start); } top.setMinPrecedence(min_prec); #ifdef EVALUATOR_DEBUG qDebug() << "=> " << top.description(); #endif // EVALUATOR_DEBUG push(top); } #ifdef EVALUATOR_DEBUG void Tokens::append(const Token& token) { qDebug() << QString("tokens.append: type=%1 text=%2") .arg(token.type()) .arg(token.text()); QVector::append(token); } #endif // EVALUATOR_DEBUG static bool isSubscriptDigit(QChar ch) { return ch.unicode() >= UnicodeChars::SubscriptZero.unicode() && ch.unicode() <= UnicodeChars::SubscriptNine.unicode(); } static QString superscriptDigitsToAscii(const QString& text) { QString converted; converted.reserve(text.size()); for (const QChar& ch : text) { if (ch == MathDsl::PowNeg) { converted.append(MathDsl::SubOp); continue; } if (ch == MathDsl::PowPos) { converted.append(MathDsl::AddOp); continue; } const QChar asciiDigit = MathDsl::superscriptDigitToAscii(ch); converted.append(asciiDigit.isNull() ? ch : asciiDigit); } return converted; } static bool isSubscriptLetter(QChar ch) { switch (ch.unicode()) { case UnicodeChars::LatinSubscriptSmallLetterA.unicode(): case UnicodeChars::LatinSubscriptSmallLetterE.unicode(): case UnicodeChars::LatinSubscriptSmallLetterO.unicode(): case UnicodeChars::LatinSubscriptSmallLetterX.unicode(): case UnicodeChars::LatinSubscriptSmallLetterSchwa.unicode(): case UnicodeChars::LatinSubscriptSmallLetterH.unicode(): case UnicodeChars::LatinSubscriptSmallLetterK.unicode(): case UnicodeChars::LatinSubscriptSmallLetterL.unicode(): case UnicodeChars::LatinSubscriptSmallLetterM.unicode(): case UnicodeChars::LatinSubscriptSmallLetterN.unicode(): case UnicodeChars::LatinSubscriptSmallLetterP.unicode(): case UnicodeChars::LatinSubscriptSmallLetterS.unicode(): case UnicodeChars::LatinSubscriptSmallLetterT.unicode(): case UnicodeChars::LatinSubscriptSmallLetterI.unicode(): case UnicodeChars::LatinSubscriptSmallLetterR.unicode(): case UnicodeChars::LatinSubscriptSmallLetterU.unicode(): case UnicodeChars::LatinSubscriptSmallLetterV.unicode(): case UnicodeChars::GreekSubscriptSmallLetterBeta.unicode(): case UnicodeChars::GreekSubscriptSmallLetterGamma.unicode(): case UnicodeChars::GreekSubscriptSmallLetterRho.unicode(): case UnicodeChars::GreekSubscriptSmallLetterPhi.unicode(): case UnicodeChars::GreekSubscriptSmallLetterChi.unicode(): return true; default: return false; } } // Helper function: return true for valid identifier start character. static bool isIdentifierStart(QChar ch) { return ch == UnicodeChars::LowLine || ch.unicode() == MathDsl::DollarSign.unicode() || ch.isLetter() || isSubscriptLetter(ch) || ch == UnicodeChars::Summation || ch == UnicodeChars::SquareRoot || ch == UnicodeChars::CubeRoot; } // Helper function: return true for valid identifier continuation character. static bool isIdentifierContinue(QChar ch) { return isIdentifierStart(ch) || ch.isDigit() || isSubscriptDigit(ch); } // Helper function: return true for valid radix characters. bool Evaluator::isRadixChar(const QChar& ch) { // Accept both '.' and ',' as potential radix markers at tokenization time. // Final decimal/grouping disambiguation is done later in fixNumberRadix(). if (ch.unicode() == MathDsl::DotSep.unicode() || ch.unicode() == MathDsl::CommaSep.unicode()) return true; if (Settings::instance()->isRadixCharacterBoth()) return ch.unicode() == MathDsl::DotSep.unicode() || ch.unicode() == MathDsl::CommaSep.unicode(); return ch.unicode() == Settings::instance()->radixCharacter(); } // Helper function: return true for valid thousand separator characters. bool Evaluator::isSeparatorChar(const QChar& ch) { // Never treat letters or digits from any script as grouping separators. // This avoids silently collapsing expressions like "12天2" into "122". if (ch.isLetterOrNumber()) return false; if (ch == UnicodeChars::Summation || ch == UnicodeChars::SquareRoot || ch == UnicodeChars::CubeRoot || ch == MathDsl::PhasorOp || isDegreeSign(ch)) return false; if (isRadixChar(ch)) return false; return RegExpPatterns::separatorToken().match(ch).hasMatch(); } bool Evaluator::isCommentOnlyExpression(const QString& expr) { for (QChar ch : expr) { if (!ch.isSpace()) return ch == MathDsl::CommentSep; } return false; } QString Evaluator::fixNumberRadix(const QString& number) { int dotCount = 0; int commaCount = 0; QChar lastRadixChar; // First pass: count dot/comma occurrences independently of the selected // radix setting. This keeps number parsing tolerant to copied values that // use a different but obvious decimal/grouping convention than the active // UI format (for example "1,56" while dot style is selected). for (int i = 0 ; i < number.size() ; ++i) { QChar c = number[i]; if (c == MathDsl::DotSep || c == MathDsl::CommaSep) { lastRadixChar = c; if (c == MathDsl::DotSep) ++dotCount; else ++commaCount; } } // Decide which radix characters to ignore based on their occurence count. bool ignoreDot = dotCount != 1; bool ignoreComma = commaCount != 1; if (!ignoreDot && !ignoreComma) { // If both radix characters are present once, // consider the last one as the radix point. ignoreDot = lastRadixChar != MathDsl::DotSep; ignoreComma = lastRadixChar != ','; } QChar radixChar; // Null character by default. if (!ignoreDot) radixChar = MathDsl::DotSep; else if (!ignoreComma) radixChar = ','; // Second pass: write the result. QString result = ""; for (int i = 0 ; i < number.size() ; ++i) { QChar c = number[i]; if (c == MathDsl::DotSep || c == MathDsl::CommaSep) { if (c == radixChar) result.append(MathDsl::DotSep); } else result.append(c); } return result; } HNumber getNumber(const QString& number) { if (number.isEmpty()) return HNumber(0); const QString sexagesimalStopChars = QStringLiteral("['\":") + MathDsl::ArcminOp + MathDsl::ArcsecOp + MathDsl::UnitEnd; int endPos = number.indexOf(QRegularExpression(sexagesimalStopChars)); // Stop at sexagesimal separators/markers. if (endPos == 0) return HNumber(0); if (endPos > 0) return HNumber(Evaluator::fixNumberRadix(number.left(endPos)).toStdString().c_str()); return HNumber(Evaluator::fixNumberRadix(number).toStdString().c_str()); } QString Evaluator::fixSexagesimal(const QString& number, QString& unit) { unit.clear(); QString bad, result = number; const QString minuteMarkClass = QStringLiteral("['") + MathDsl::ArcminOp + MathDsl::UnitEnd; const QString secondMarkClass = QStringLiteral("[\"") + MathDsl::ArcsecOp + MathDsl::UnitEnd; const auto isMinuteMark = [](QChar c) { return c == MathDsl::ArcminOpAl1 || c == MathDsl::ArcminOp; }; const auto isSecondMark = [](QChar c) { return c == MathDsl::ArcsecOpAl1 || c == MathDsl::ArcsecOp; }; bool arc = false; int colonCount = 0, degreeCount = 0, minuteCount = 0, secondCount = 0, digitCount = 0; for (int i = 0 ; i < number.size() ; ++i) { // check order and amount QChar c = number[i]; if (isDegreeSign(c)) { if (colonCount || minuteCount || secondCount) return bad; if (++degreeCount > 1) return bad; arc = true; } else if (c == ':') { if (minuteCount || degreeCount || secondCount) return bad; if (++colonCount > 2) return bad; } else if (isMinuteMark(c)) { if (secondCount) return bad; if (++minuteCount > 1) return bad; arc = true; } else if (isSecondMark(c)) { if (degreeCount && !minuteCount) return bad; if (++secondCount > 1) return bad; arc = true; } else if (c.isDigit()) ++digitCount; } if (colonCount || degreeCount || minuteCount || secondCount) { // sexagesimal value if (digitCount == 0) return bad; HNumber::Format fixed = HNumber::Format::Fixed(); HNumber mains(0), minutes(0), seconds(0), sign(1); int minPos = number.indexOf(arc ? QRegularExpression("[\\x{00B0}\\x{00BA}\\x{02DA}\\x{2218}]") : QRegularExpression(":")); if (minPos >= 0) { // degree sign or first colon -> minutes mains = getNumber(number.left(minPos)); // hours or degrees if (mains.isNegative()) sign = HNumber(-1); int secPos = number.indexOf(arc ? QRegularExpression(minuteMarkClass) : QRegularExpression(":"), minPos + 1); if (secPos >= 0) { // single quote or second colon -> seconds minutes = getNumber(number.mid(minPos + 1)); seconds = getNumber(number.mid(secPos + 1)); if (seconds.isZero()) { // postfix minutes result = HMath::format(mains * HNumber(60) + minutes * sign, fixed); unit = arc ? unitName(UnitId::Arcminute) : unitName(UnitId::Minute); } else { // minutes and seconds result = HMath::format(mains * HNumber(3600) + minutes * HNumber(60) * sign + seconds * sign, fixed); unit = arc ? unitName(UnitId::Arcsecond) : unitName(UnitId::Second); } } else { // just minutes minutes = getNumber(number.mid(minPos + 1)); result = HMath::format(mains * HNumber(60) + minutes * sign, fixed); unit = arc ? unitName(UnitId::Arcminute) : unitName(UnitId::Minute); } if (seconds.isZero() && minutes.isZero()) { // postfix mains result = HMath::format(mains, fixed); unit = arc ? unitName(UnitId::Degree) : unitName(UnitId::Hour); } } else if ( arc ) { int secPos = number.indexOf(QRegularExpression(minuteMarkClass)); if (secPos >= 0) { // single quote -> seconds minutes = getNumber(number.left(secPos)); if (minutes.isNegative()) sign = HNumber(-1); seconds = getNumber(number.mid(secPos + 1)); if (seconds.isZero()) { // postfix minutes result = HMath::format(minutes, fixed); unit = unitName(UnitId::Arcminute); } else { result = HMath::format(minutes * HNumber(60) + seconds * sign, fixed); unit = unitName(UnitId::Arcsecond); } } else { int unitPos = number.indexOf(QRegularExpression(secondMarkClass)); if (unitPos >= 0) { // postfix seconds seconds = getNumber(number.left(unitPos)); result = HMath::format(seconds, fixed); unit = unitName(UnitId::Arcsecond); } } } int unitPos = number.indexOf(QRegularExpression(secondMarkClass)); // check digits after seconds unit if (unitPos >= 0 && !getNumber(number.mid(unitPos + 1)).isZero()) return bad; if (!seconds.isZero() && (!minutes.isInteger() || !mains.isInteger())) return bad; if (!minutes.isZero() && !mains.isInteger()) return bad; const bool hasScientificExponent = number.contains(QLatin1Char('e'), Qt::CaseInsensitive); int dotNumber = number.lastIndexOf(QRegularExpression("[.,]")); if (dotNumber >= 0 && !hasScientificExponent) { // append decimals, remove possible postfix units int minuteUnitPos = number.indexOf(QRegularExpression(minuteMarkClass)); int secondUnitPos = number.indexOf(QRegularExpression(secondMarkClass)); int suffixPos = (secondUnitPos >= 0 && secondUnitPos < minuteUnitPos) ? secondUnitPos : minuteUnitPos; int dotResult = result.lastIndexOf(MathDsl::DotSep); if (dotResult >= 0) // replace decimals with original ones for accuracy result.resize(dotResult); result += number.mid(dotNumber, suffixPos < 0 ? -1 : suffixPos - dotNumber); } } else result = fixNumberRadix(result); return result; } Evaluator* Evaluator::instance() { if (!s_evaluatorInstance) { s_evaluatorInstance = new Evaluator; s_evaluatorInstance->initializeBuiltInVariables(); qAddPostRoutine(s_deleteEvaluator); } return s_evaluatorInstance; } QStringList Evaluator::builtInUnitIdentifiers() { QStringList identifiers = s_builtInUnitLookup().keys(); identifiers.sort(); return identifiers; } Evaluator::Evaluator() { reset(); } void Evaluator::initializeBuiltInVariables() { StartupDiagnostics::Scope timing("Initialize evaluator built-in variables"); setVariable(QLatin1String("e"), DMath::e(), Variable::BuiltIn); setVariable(QString::fromUtf8("ℯ"), DMath::e(), Variable::BuiltIn); setVariable(QLatin1String("pi"), DMath::pi(), Variable::BuiltIn); setVariable(QString::fromUtf8("Ï€"), DMath::pi(), Variable::BuiltIn); if (Settings::instance()->complexNumbers) { setVariable(QLatin1String("i"), DMath::i(), Variable::BuiltIn); setVariable(QLatin1String("j"), DMath::i(), Variable::BuiltIn); } else { if (hasVariable("i")) unsetVariable("i", ForceBuiltinVariableErasure(true)); if (hasVariable("j")) unsetVariable("j", ForceBuiltinVariableErasure(true)); } initializeAngleUnits(); } void Evaluator::initializeAngleUnits() { // Angle-dependent built-in unit values are resolved from the dedicated // unit lookup table (not from reserved variable names). s_builtInUnitLookup(); } void Evaluator::setExpression(const QString& expr) { m_expression = rewriteListBracesToInternalCalls(expr); m_dirty = true; m_valid = false; m_error = QString(); m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; m_allowGlobalUserDefinitionsOverride = false; } QString Evaluator::expression() const { return m_expression; } // Returns the validity. Note: empty expression is always invalid. bool Evaluator::isValid() { if (m_dirty) { Tokens tokens = scan(m_expression); if (!tokens.valid()) compile(tokens); else m_valid = false; } return m_valid; } void Evaluator::reset() { m_expression = QString(); m_dirty = true; m_valid = false; m_error = QString(); m_interpretedExpression = QString(); m_constants.clear(); m_constantTexts.clear(); m_codes.clear(); m_implicitMultiplicationOpcodeIndices.clear(); m_assignId = QString(); m_assignFunc = false; m_assignArg.clear(); m_assignVarDescription = QString(); m_assignUnitDescription = QString(); m_assignFuncExpr = QString(); m_assignUnitExpr = QString(); m_assignFuncDescription = QString(); m_assignUnit = false; m_functionsInUse.clear(); m_hasImplicitMultiplication = false; m_allowGlobalUserDefinitionsOverride = false; } QString Evaluator::error() const { return m_error; } QString Evaluator::interpretedExpression() const { return m_interpretedExpression; } bool Evaluator::hasImplicitMultiplication() const { return m_hasImplicitMultiplication; } // Returns list of token for the expression. // This triggers again the lexical analysis step. It is however preferable // (even when there's small performance penalty) because otherwise we need to // store parsed tokens all the time which serves no good purpose. Tokens Evaluator::tokens() const { return scan(m_expression); } bool isArcTime(QChar ch) { return (isDegreeSign(ch) || ch == '\'' || ch == '"' || ch == MathDsl::ArcminOp || ch == MathDsl::ArcsecOp || ch == ':'); } Tokens Evaluator::scan(const QString& expr) const { // Associate character codes with the highest number base // they might belong to. constexpr unsigned DIGIT_MAP_COUNT = 128; static unsigned char s_digitMap[DIGIT_MAP_COUNT] = { 0 }; if (s_digitMap[0] == 0) { // Initialize the digits map. std::fill_n(s_digitMap, DIGIT_MAP_COUNT, 255); for (int i = '0' ; i <= '9' ; ++i) s_digitMap[i] = i - '0' + 1; for (int i = 'a' ; i <= 'z' ; ++i) s_digitMap[i] = i - 'a' + 11; for (int i = 'A' ; i <= 'Z' ; ++i) s_digitMap[i] = i - 'A' + 11; } // Result. Tokens tokens; // Parsing state. enum { Init, Start, Finish, Bad, InNumberPrefix, InNumber, InExpIndicator, InExponentBase, InExponent, InIdentifier, InNumberEnd } state; // Initialize variables. state = Init; int i = 0; QString ex = UnicodeChars::normalizeUnitSymbolAliases(expr); // Accept editor-produced spacing in unit conversion aliases: // "− >" or "- >" should tokenize as "->". ex.replace( QRegularExpression(QStringLiteral("([\\-−])\\s+>")), QStringLiteral("->")); // Accept superscript shorthand aliases for unit symbols (m², mm³, etc.) // only inside explicit unit brackets. int superscriptUnitBracketDepth = 0; for (int p = 0; p < ex.size();) { const QChar current = ex.at(p); if (current == MathDsl::UnitStart) { ++superscriptUnitBracketDepth; ++p; continue; } if (current == MathDsl::UnitEnd) { if (superscriptUnitBracketDepth > 0) --superscriptUnitBracketDepth; ++p; continue; } if (superscriptUnitBracketDepth == 0 || !isIdentifierStart(current)) { ++p; continue; } int identEnd = p + 1; while (identEnd < ex.size() && isIdentifierContinue(ex.at(identEnd))) ++identEnd; int superscriptStart = identEnd; if (superscriptStart < ex.size() && MathDsl::isSuperscriptSign(ex.at(superscriptStart))) ++superscriptStart; int superscriptEnd = superscriptStart; while (superscriptEnd < ex.size() && MathDsl::isSuperscriptDigit(ex.at(superscriptEnd))) ++superscriptEnd; if (superscriptEnd == superscriptStart) { p = identEnd; continue; } const QString identifier = ex.mid(p, identEnd - p); const QString superscript = ex.mid(identEnd, superscriptEnd - identEnd); const QString replacement = identifier + MathDsl::PowOp + superscriptDigitsToAscii(superscript); ex.replace(p, superscriptEnd - p, replacement); p += replacement.size(); } QString tokenText, tokenUnit; int tokenStart = 0; // Includes leading spaces. Token::Type type; int numberBase = 10; int expBase = 0; int expStart = -1; // Index of the exponent part in the expression. QString expText; // Start of the exponent text matching /E[\+\-]*/ int unitBracketDepth = 0; // Force a terminator. ex.append(QChar()); #ifdef EVALUATOR_DEBUG qDebug() << "Scanning" << ex; #endif // EVALUATOR_DEBUG const auto isUnitArcSymbol = [](QChar c) { return c == MathDsl::ArcminOp || c == MathDsl::ArcsecOp || c == MathDsl::ArcminOpAl1 || c == MathDsl::ArcsecOpAl1; }; // Main loop. while (state != Bad && state != Finish && i < ex.length()) { QChar ch = ex.at(i); #ifdef EVALUATOR_DEBUG qDebug() << QString("state=%1 ch=%2 i=%3 tokenText=%4") .arg(state).arg(ch).arg(i).arg(tokenText); #endif // EVALUATOR_DEBUG switch (state) { case Init: tokenStart = i; tokenText = ""; tokenUnit = ""; state = Start; // State variables reset expStart = -1; expText = ""; numberBase = 10; expBase = 0; // C++17: [[fallthrough]]; // fall through case Start: // Skip any whitespaces. if (ch.isSpace()) ++i; else if (ch == MathDsl::CommentSep) // Comment. state = Finish; else if (ch.isDigit()) { // Check for number state = InNumberPrefix; } else if (ch == MathDsl::HexPrefixAl1) { // Simple hexadecimal notation tokenText.append(MathDsl::HexPrefix); numberBase = 16; state = InNumber; ++i; } else if (isRadixChar(ch)) { // Radix character? tokenText.append(ch); numberBase = 10; state = InNumber; ++i; } else if (unitBracketDepth == 0 && isDegreeSign(ch)) { // Outside explicit unit brackets, distinguish sexagesimal // degree starts from temperature/unit identifiers: // - "°34", "°'56" -> number // - "°C", "°F" -> identifier const QChar next = ex.at(i + 1); if (next.isLetter() || next == UnicodeChars::MicroSign || next == UnicodeChars::GreekCapitalOmega) { // Seed identifier token with the degree sign to avoid // stalling on the same character in InIdentifier state. tokenText.append(ex.at(i++)); state = InIdentifier; } else { state = InNumberPrefix; } } else if (unitBracketDepth == 0 && isArcTime(ch)) { // Sexagesimal/time notation can start with degree markers, // e.g. "°34" or "°'56". state = InNumberPrefix; } else if (ch == '~') { int tokenSize = ++i - tokenStart; tokens.append(Token(Token::stxOperator, "~", tokenStart, tokenSize)); state = Init; } else if (unitBracketDepth > 0 && isUnitArcSymbol(ch)) { // Inside explicit unit brackets, arcminute/arcsecond symbols // are unit identifiers, not sexagesimal separators. state = InIdentifier; } else if (isSeparatorChar(ch)) { // Leading separator, probably a number state = InNumberPrefix; } else if (ch.isNull()) // Terminator character. state = Finish; else if (isIdentifierStart(ch) || (unitBracketDepth > 0 && (isDegreeSign(ch) || isUnitArcSymbol(ch)))) // Identifier or alphanumeric operator state = InIdentifier; else { // Look for operator match. int op; QString s; s = QString(ch).append(ex.at(i+1)); op = matchOperator(s); // Check for one-char operator. if (op == Token::Invalid) { s = QString(ch); op = matchOperator(s); } // Any matched operator? if (op != Token::Invalid) { switch(op) { case Token::AssociationStart: type = Token::stxOpenPar; break; case Token::AssociationEnd: type = Token::stxClosePar; break; case Token::ListSeparator: type = Token::stxSep; break; default: type = Token::stxOperator; } int len = s.length(); i += len; int tokenSize = i - tokenStart; const QString opText = s.left(len); tokens.append(Token(type, opText, tokenStart, tokenSize)); if (opText == QString(MathDsl::UnitStart)) { ++unitBracketDepth; } else if (opText == QString(MathDsl::UnitEnd)) { if (unitBracketDepth == 0) { state = Bad; break; } --unitBracketDepth; } state = Init; } else state = Bad; } break; // Manage both identifier and alphanumeric operators. case InIdentifier: // Consume as long as alpha, dollar sign, underscore, or digit. if (isIdentifierContinue(ch) || (unitBracketDepth > 0 && (isDegreeSign(ch) || isUnitArcSymbol(ch)))) tokenText.append(ex.at(i++)); else { // We're done with identifier. QString identifier = tokenText; const bool isUnitContextIdentifier = unitBracketDepth > 0; if (isUnitContextIdentifier && identifier.startsWith(QLatin1Char('u')) && identifier.size() > 1) { QString microIdentifier(identifier); microIdentifier[0] = UnicodeChars::MicroSign; if (s_isBuiltInUnitIdentifier(microIdentifier)) identifier = microIdentifier; } int tokenSize = i - tokenStart; if (!isUnitContextIdentifier && matchOperator(identifier)) { tokens.append(Token(Token::stxOperator, identifier, tokenStart, tokenSize)); } else { const Token::Type identifierType = isUnitContextIdentifier ? Token::stxUnitIdentifier : Token::stxIdentifier; tokens.append(Token(identifierType, identifier, tokenStart, tokenSize)); } state = Init; } break; // Find out the number base. case InNumberPrefix: if (ch.isDigit()) { // Only consume the first digit and the second digit // if the first was 0. tokenText.append(ex.at(i++)); if (tokenText != "0") { numberBase = 10; state = InNumber; } } else if (isArcTime(ch)) { // Time/Degree notation numberBase = 10; tokenText.append(ex.at(i++)); state = InNumber; } else if (isExponent(ch, numberBase)) { if (tokenText.endsWith("0")) { // Maybe exponent (tokenText is "0" or "-0"). numberBase = 10; expText = ch.toUpper(); expStart = i; ++i; state = InExpIndicator; } else { // Only leading separators. state = Bad; } } else if (isRadixChar(ch)) { // Might be a radix point or a separator. // Collect it and decide later. tokenText.append(ch); numberBase = 10; state = InNumber; ++i; } else if (ch.toUpper() == 'X' && tokenText == "0") { // Hexadecimal number. numberBase = 16; tokenText.append('x'); ++i; state = InNumber; } else if (ch.toUpper() == 'B' && tokenText == "0") { // Binary number. numberBase = 2; tokenText.append('b'); ++i; state = InNumber; } else if (ch.toUpper() == 'O' && tokenText == "0") { // Octal number. numberBase = 8; tokenText.append('o'); ++i; state = InNumber; } else if (ch.toUpper() == 'D' && tokenText == "0") { // Decimal number (with prefix). numberBase = 10; tokenText.append('d'); ++i; state = InNumber; } else if (isSeparatorChar(ch)) { // Ignore thousand separators. ++i; } else if (tokenText.isEmpty() && (ch == '+' || isMinus(ch))) { // Allow expressions like "$-10" or "$+10". if (isMinus(ch)) tokenText.append(MathDsl::SubOpAl1); ++i; } else { if (tokenText.endsWith("0")) { // Done with integer number (tokenText is "0" or "-0"). numberBase = 10; state = InNumberEnd; } else { // Only leading separators. state = Bad; } } break; // Parse the number digits. case InNumber: { ushort c = ch.unicode(); bool isDigit = c < DIGIT_MAP_COUNT && (s_digitMap[c] <= numberBase); if (isDigit) { // Consume as long as it's a digit tokenText.append(ex.at(i++).toUpper()); } else if (isArcTime(ch)) { // Time/Degree notation tokenText.append(ex.at(i++)); } else if (isExponent(ch, numberBase)) { // Maybe exponent expText = ch.toUpper(); expStart = i; ++i; tokenText = fixNumberRadix(tokenText); if (!tokenText.isNull()) state = InExpIndicator; else state = Bad; } else if (isRadixChar(ch)) { // Might be a radix point or a separator. // Collect it and decide later. tokenText.append(ch); ++i; } else if (isSeparatorChar(ch)) { // Ignore thousand separators. ++i; } else { // We're done with number. if (numberBase == 10) tokenText = fixSexagesimal(tokenText, tokenUnit); else tokenText = fixNumberRadix(tokenText); if (!tokenText.isNull()) state = InNumberEnd; else state = Bad; } break; } // Validate exponent start. case InExpIndicator: { ushort c = ch.unicode(); bool isDigit = c < DIGIT_MAP_COUNT && (s_digitMap[c] <= numberBase); if (expBase == 0) { // Set the default exponent base (same as number) expBase = numberBase; } if (expText.length() == 1 && (ch == '+' || isMinus(ch))) { // Possible + or - right after E. expText.append(ch == MathDsl::SubOp ? MathDsl::SubOpAl1 : ch); ++i; } else if (isDigit) { if (ch == '0') { // Might be a base prefix expText.append(ch); ++i; state = InExponentBase; } else { // Parse the exponent absolute value. tokenText.append(expText); state = InExponent; } } else if (isSeparatorChar(ch)) { // Ignore thousand separators. ++i; } else { // Invalid thing here. Rollback: might be an identifier // used in implicit multiplication. i = expStart; state = InNumberEnd; } break; } // Detect exponent base. case InExponentBase: { int base = -1; switch (ch.toUpper().unicode()) { case 'B': base = 2; break; case 'O': base = 8; break; case 'D': base = 10; break; case 'X': base = 16; break; } if (base != -1) { // Specific exponent base found expBase = base; tokenText.append(expText); tokenText.append(ch.toLower()); ++i; } else { // No exponent base specified, use the default one tokenText.append(expText); } state = InExponent; break; } // Parse exponent. case InExponent: { ushort c = ch.unicode(); bool isDigit = c < DIGIT_MAP_COUNT && (s_digitMap[c] <= expBase); if (isDigit) { // Consume as long as it's a digit. tokenText.append(ex.at(i++)); } else if (isArcTime(ch)) { // Allow sexagesimal markers right after scientific notation, // e.g. "8.4381406e4\"" or "8.4381406e4″". tokenText.append(ex.at(i++)); state = InNumber; } else if (isSeparatorChar(ch)) { // Ignore thousand separators. ++i; } else { // We're done with floating-point number. state = InNumberEnd; }; break; } case InNumberEnd: { int tokenSize = i - tokenStart; if (!tokenUnit.isEmpty()) { // Keep the sexagesimal number and its generated unit together: // e.g. "1:30 / 4:00" should parse as // "90[minute] / 4[hour]", not "(90 minute / 4) hour". tokens.append(Token(Token::stxNumber, tokenText, tokenStart, tokenSize)); tokens.append(Token(Token::stxOpenPar, "[", tokenStart + tokenSize, 0)); tokens.append(Token(Token::stxUnitIdentifier, tokenUnit, tokenStart + tokenSize, 0)); tokens.append(Token(Token::stxClosePar, "]", tokenStart + tokenSize, 0)); } else { tokens.append(Token(Token::stxNumber, tokenText, tokenStart, tokenSize)); } // Make sure a number cannot be followed by another number. if (ch.isDigit() || isRadixChar(ch) || ch == MathDsl::HexPrefixAl1) state = Bad; else state = Init; break; } case Bad: tokens.setValid(false); break; default: break; }; } if (unitBracketDepth != 0) state = Bad; if (state == Bad) // Invalidating here too, because usually when we set state to Bad, // the case Bad won't be run. tokens.setValid(false); return tokens; } void Evaluator::compile(const Tokens& tokens) { #ifdef EVALUATOR_DEBUG QFile debugFile("eval.log"); if (!debugFile.open(QIODevice::WriteOnly)) qWarning() << "Could not open eval.log for writing:" << debugFile.errorString(); QTextStream dbg(&debugFile); #endif // Initialize variables. m_dirty = false; auto isGeneratedSexagesimalUnitToken = [](const Token& token) { if (token.type() != Token::stxUnitIdentifier || token.size() != 0) return false; const QString text = token.text(); return text == unitName(UnitId::Hour) || text == unitName(UnitId::Minute) || text == unitName(UnitId::Second) || text == unitName(UnitId::Degree) || text == unitName(UnitId::Arcminute) || text == unitName(UnitId::Arcsecond); }; bool hasGeneratedSexagesimalUnit = false; bool hasUnitConversionToken = false; bool hasPhasorToken = false; for (int idx = 0; idx < tokens.size(); ++idx) { if (isGeneratedSexagesimalUnitToken(tokens.at(idx))) { hasGeneratedSexagesimalUnit = true; } else if (tokens.at(idx).isOperator() && tokens.at(idx).asOperator() == Token::Phasor) { hasPhasorToken = true; } else if (tokens.at(idx).isOperator() && tokens.at(idx).asOperator() == Token::UnitConversion) { hasUnitConversionToken = true; } } m_valid = false; m_codes.clear(); m_implicitMultiplicationOpcodeIndices.clear(); m_constants.clear(); m_constantTexts.clear(); m_identifiers.clear(); m_error = QString(); m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; // Sanity check. if (tokens.count() == 0) return; TokenStack syntaxStack; QStack argStack; unsigned argCount = 1; for (int i = 0; i <= tokens.count() && !syntaxStack.hasError(); ++i) { // Helper token: Invalid is end-of-expression. auto token = (i < tokens.count()) ? tokens.at(i) : Token(Token::stxOperator); auto tokenType = token.type(); if (tokenType >= Token::stxOperator) tokenType = Token::stxOperator; #ifdef EVALUATOR_DEBUG dbg << "\nToken: " << token.description() << "\n"; #endif // Unknown token is invalid. if (tokenType == Token::stxUnknown) break; // Try to apply all parsing rules. #ifdef EVALUATOR_DEBUG dbg << "\tChecking rules..." << "\n"; #endif // Repeat until no more rule applies. bool argHandled = false; while (!syntaxStack.hasError()) { bool ruleFound = false; // Rule for function last argument: id (arg) -> arg. if (!ruleFound && syntaxStack.itemCount() >= 4) { Token par2 = syntaxStack.top(); Token arg = syntaxStack.top(1); Token par1 = syntaxStack.top(2); Token id = syntaxStack.top(3); if (par2.asOperator() == Token::AssociationEnd && arg.isOperand() && par1.asOperator() == Token::AssociationStart && par1.text() == QLatin1String("(") && par2.text() == QLatin1String(")") && id.isIdentifier()) { ruleFound = true; syntaxStack.reduce(4, MAX_PRECEDENCE); Opcode functionCall(Opcode::Function, argCount); if (s_isSummationFunctionIdentifier(id.text()) && argCount == 3) { const QString argText = m_expression.mid(arg.pos(), arg.size()); const QStringList argList = splitTopLevelFunctionArguments(argText); if (argList.count() == 3) functionCall.text = argList.at(2); } else if (s_isMolmassFunctionIdentifier(id.text()) && argCount == 1) { functionCall.text = m_expression.mid(arg.pos(), arg.size()); } else if (s_isMassFunctionIdentifier(id.text()) && argCount == 2) { const QString argText = m_expression.mid(arg.pos(), arg.size()); const QStringList argList = splitTopLevelFunctionArguments(argText); if (argList.count() == 2) functionCall.text = argList.at(1); } m_codes.append(functionCall); #ifdef EVALUATOR_DEBUG dbg << "\tRule for function last argument " << argCount << " \n"; #endif argCount = argStack.empty() ? 0 : argStack.pop(); } } // Are we entering a function? If token is operator, // and stack already has: id (arg. if (!ruleFound && !argHandled && tokenType == Token::stxOperator && syntaxStack.itemCount() >= 3) { Token arg = syntaxStack.top(); Token par = syntaxStack.top(1); Token id = syntaxStack.top(2); if (arg.isOperand() && par.asOperator() == Token::AssociationStart && par.text() == QLatin1String("(") && id.isIdentifier()) { ruleFound = true; argStack.push(argCount); #ifdef EVALUATOR_DEBUG dbg << "\tEntering new function, pushing argcount=" << argCount << " of parent function\n"; #endif argCount = 1; break; } } // Rule for list or matrix literal last element: {arg} -> arg. if (!ruleFound && syntaxStack.itemCount() >= 3) { Token right = syntaxStack.top(); Token arg = syntaxStack.top(1); Token left = syntaxStack.top(2); if (s_isClosingListBraceToken(right) && arg.isOperand() && s_isOpeningListBraceToken(left)) { ruleFound = true; syntaxStack.reduce(3, MAX_PRECEDENCE); m_codes.append(Opcode(Opcode::List, argCount)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for list literal with " << argCount << " elements\n"; #endif argCount = argStack.empty() ? 0 : argStack.pop(); } } // Are we entering a list literal? if (!ruleFound && !argHandled && tokenType == Token::stxOperator && syntaxStack.itemCount() >= 2) { Token arg = syntaxStack.top(); Token left = syntaxStack.top(1); if (arg.isOperand() && s_isOpeningListBraceToken(left)) { ruleFound = true; argStack.push(argCount); argCount = 1; break; } } // Rule for postfix operators: Y POSTFIX -> Y. // Condition: Y is not an operator, POSTFIX is a postfix op. // Since we evaluate from left to right, // we need not check precedence at this point. if (!ruleFound && syntaxStack.itemCount() >= 2) { Token postfix = syntaxStack.top(); Token y = syntaxStack.top(1); if (postfix.isOperator() && y.isOperand()) { switch (postfix.asOperator()) { case Token::Factorial: ruleFound = true; syntaxStack.reduce(2); m_codes.append(Opcode(Opcode::Fact)); break; case Token::Percent: ruleFound = true; syntaxStack.reduce(2); m_codes.append(Opcode(Opcode::Percent)); break; default:; } } #ifdef EVALUATOR_DEBUG if (ruleFound) { dbg << "\tRule for postfix operator " << postfix.text() << "\n"; } #endif } // Rule for explicit unit attachment: X [U] -> X. if (!ruleFound && syntaxStack.itemCount() >= 3) { Token right = syntaxStack.top(); Token left = syntaxStack.top(1); Token lhs = syntaxStack.top(2); if (lhs.isOperand() && s_isClosingUnitBracketToken(right) && s_isOpeningUnitBracketToken(left)) { ruleFound = true; lhs.setExplicitUnitAttachment(true); syntaxStack.reduce(3, std::move(lhs), MAX_PRECEDENCE); #ifdef EVALUATOR_DEBUG dbg << "\tRule for empty unit attachment X[] -> X\n"; #endif } } // Rule for explicit unit attachment: X [U] -> X. if (!ruleFound && syntaxStack.itemCount() >= 4) { Token right = syntaxStack.top(); Token unitExpr = syntaxStack.top(1); Token left = syntaxStack.top(2); Token lhs = syntaxStack.top(3); if (lhs.isOperand() && unitExpr.isOperand() && s_isClosingUnitBracketToken(right) && s_isOpeningUnitBracketToken(left)) { ruleFound = true; lhs.setExplicitUnitAttachment(true); syntaxStack.reduce(4, std::move(lhs), MAX_PRECEDENCE); m_codes.append(Opcode(Opcode::Unit)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for unit attachment X[U] -> X\n"; #endif } } // Rule for parenthesized explicit unit attachment: // X * ([U]) -> X. if (!ruleFound && syntaxStack.itemCount() >= 5) { Token rightPar = syntaxStack.top(); Token innerExpr = syntaxStack.top(1); Token leftPar = syntaxStack.top(2); Token op = syntaxStack.top(3); Token lhs = syntaxStack.top(4); if (lhs.isOperand() && innerExpr.isOperand() && op.asOperator() == Token::Multiplication && rightPar.asOperator() == Token::AssociationEnd && rightPar.text() == QLatin1String(")") && leftPar.asOperator() == Token::AssociationStart && leftPar.text() == QLatin1String("(")) { const QString innerSource = m_expression.mid(innerExpr.pos(), innerExpr.size()).trimmed(); if (innerSource.startsWith(MathDsl::UnitStart) && innerSource.endsWith(MathDsl::UnitEnd)) { ruleFound = true; lhs.setExplicitUnitAttachment(true); syntaxStack.reduce(5, std::move(lhs), MAX_PRECEDENCE); m_codes.append(Opcode(Opcode::Unit)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for parenthesized unit attachment X*([U]) -> X\n"; #endif } } } // Rule for parenthesis: (Y) -> Y. if (!ruleFound && syntaxStack.itemCount() >= 3) { Token right = syntaxStack.top(); Token y = syntaxStack.top(1); Token left = syntaxStack.top(2); if (y.isOperand() && right.asOperator() == Token::AssociationEnd && left.asOperator() == Token::AssociationStart && !s_isOpeningListBraceToken(left) && !s_isClosingListBraceToken(right)) { ruleFound = true; syntaxStack.reduce(3, MAX_PRECEDENCE); #ifdef EVALUATOR_DEBUG dbg << "\tRule for (Y) -> Y" << "\n"; #endif } } // Rule for simplified syntax for function, // e.g. "sin pi" or "cos 1.2". Conditions: // *precedence of function reduction >= precedence of next token. // *or next token is not an operator. if (!ruleFound && syntaxStack.itemCount() >= 2) { Token arg = syntaxStack.top(); Token id = syntaxStack.top(1); if (arg.isOperand() && isFunction(id) && (!token.isOperator() || opPrecedence(Token::Function) >= opPrecedence(token.asOperator()))) { ruleFound = true; m_codes.append(Opcode(Opcode::Function, 1)); syntaxStack.reduce(2); #ifdef EVALUATOR_DEBUG dbg << "\tRule for simplified function syntax; function " << id.text() << "\n"; #endif } } // Rule for unary operator in simplified function syntax. // This handles cases like "sin -90". if (!ruleFound && syntaxStack.itemCount() >= 3) { Token x = syntaxStack.top(); Token op = syntaxStack.top(1); Token id = syntaxStack.top(2); if (x.isOperand() && isFunction(id) && (op.asOperator() == Token::Addition || op.asOperator() == Token::Subtraction || op.asOperator() == Token::BitwiseLogicalNOT)) { ruleFound = true; syntaxStack.reduce(2); if (op.asOperator() == Token::Subtraction) m_codes.append(Opcode(Opcode::Neg)); else if (op.asOperator() == Token::BitwiseLogicalNOT) m_codes.append(Opcode(Opcode::BNot)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for unary operator in simplified " "function syntax; function " << id.text() << "\n"; #endif } } // Rule for function arguments. If token is ; or ): // id (arg1 ; arg2 -> id (arg. // Must come before binary op rule, special case of the latter. if (!ruleFound && syntaxStack.itemCount() >= 5 && token.isOperator() && (token.asOperator() == Token::AssociationEnd || token.asOperator() == Token::ListSeparator)) { Token arg2 = syntaxStack.top(); Token sep = syntaxStack.top(1); Token arg1 = syntaxStack.top(2); Token par = syntaxStack.top(3); Token id = syntaxStack.top(4); if (arg2.isOperand() && sep.asOperator() == Token::ListSeparator && arg1.isOperand() && par.asOperator() == Token::AssociationStart && par.text() == QLatin1String("(") && id.isIdentifier()) { ruleFound = true; argHandled = true; syntaxStack.reduce(3, MAX_PRECEDENCE); ++argCount; #ifdef EVALUATOR_DEBUG dbg << "\tRule for function argument " << argCount << " \n"; #endif } } // Rule for list literal elements. If token is ; or }: // {arg1 ; arg2 -> {arg. if (!ruleFound && syntaxStack.itemCount() >= 4 && token.isOperator() && (token.asOperator() == Token::AssociationEnd || token.asOperator() == Token::ListSeparator)) { Token arg2 = syntaxStack.top(); Token sep = syntaxStack.top(1); Token arg1 = syntaxStack.top(2); Token left = syntaxStack.top(3); if (arg2.isOperand() && sep.asOperator() == Token::ListSeparator && arg1.isOperand() && s_isOpeningListBraceToken(left)) { ruleFound = true; argHandled = true; syntaxStack.reduce(3, MAX_PRECEDENCE); ++argCount; #ifdef EVALUATOR_DEBUG dbg << "\tRule for list literal element " << argCount << "\n"; #endif } } // Rule for trailing function argument separator: // id (arg ; ) -> id (arg ) // id (arg ; -> id (arg (end-of-expression) // This keeps the already parsed argument list and discards // an empty trailing argument. if (!ruleFound && syntaxStack.itemCount() >= 4 && token.isOperator() && (token.asOperator() == Token::AssociationEnd || token.asOperator() == Token::Invalid)) { Token sep = syntaxStack.top(); Token arg = syntaxStack.top(1); Token par = syntaxStack.top(2); Token id = syntaxStack.top(3); if (sep.asOperator() == Token::ListSeparator && arg.isOperand() && par.asOperator() == Token::AssociationStart && par.text() == QLatin1String("(") && id.isIdentifier()) { ruleFound = true; argHandled = true; syntaxStack.reduce(2, std::move(arg), MAX_PRECEDENCE); #ifdef EVALUATOR_DEBUG dbg << "\tRule for trailing function argument separator\n"; #endif } } // Rule for function call with parentheses, // but without argument, e.g. "2*PI()". if (!ruleFound && syntaxStack.itemCount() >= 3) { Token par2 = syntaxStack.top(); Token par1 = syntaxStack.top(1); Token id = syntaxStack.top(2); if (par2.asOperator() == Token::AssociationEnd && par1.asOperator() == Token::AssociationStart && par1.text() == QLatin1String("(") && par2.text() == QLatin1String(")") && id.isIdentifier()) { ruleFound = true; syntaxStack.reduce(3, MAX_PRECEDENCE); m_codes.append(Opcode(Opcode::Function, 0)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for function call with parentheses, " "but without argument\n"; #endif } } // Rule for binary operator: A (op) B -> A. // Conditions: precedence of op >= precedence of token. // Action: push (op) to result e.g. // "A * B" becomes "A" if token is operator "+". // Exception: for caret (power operator), if op is another caret // then it doesn't apply, e.g. "2^3^2" is evaluated as "2^(3^2)". // Exception: doesn't apply if B is a function name (to manage // shift/reduce conflict with simplified function syntax // (issue #600). if (!ruleFound && syntaxStack.itemCount() >= 3) { Token b = syntaxStack.top(); Token op = syntaxStack.top(1); Token a = syntaxStack.top(2); const bool disallowPowerWithExplicitUnitAttachment = op.asOperator() == Token::Exponentiation && a.hasExplicitUnitAttachment(); if (disallowPowerWithExplicitUnitAttachment) { m_error = tr("syntax error"); m_valid = false; m_constants.clear(); m_constantTexts.clear(); m_codes.clear(); m_identifiers.clear(); m_implicitMultiplicationOpcodeIndices.clear(); m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; return; } const bool openingUnitBracketToken = token.isOperator() && s_isOpeningUnitBracketToken(token); const bool reducePowerBeforeUnitAttachment = openingUnitBracketToken && op.asOperator() == Token::Exponentiation; const bool forceReduceCompletedConversionBeforeAddSub = op.asOperator() == Token::UnitConversion && token.isOperator() && (token.asOperator() == Token::Addition || token.asOperator() == Token::Subtraction); if (a.isOperand() && b.isOperand() && op.isOperator() && ( // Normal operator. (token.isOperator() && (!openingUnitBracketToken || reducePowerBeforeUnitAttachment) && (forceReduceCompletedConversionBeforeAddSub || reducePowerBeforeUnitAttachment || opPrecedence(op.asOperator()) >= opPrecedence(token.asOperator())) #ifdef ALLOW_IMPLICIT_MULT && (token.asOperator() != Token::AssociationStart || opPrecedence(op.asOperator()) >= opPrecedence(Token::Multiplication)) #endif && !(b.isIdentifier() && token.asOperator() == Token::AssociationStart) && token.asOperator() != Token::Exponentiation) || ( // May represent implicit multiplication. token.isOperand() && opPrecedence(op.asOperator()) >= opPrecedence(Token::Multiplication))) && !(isFunction(b))) { ruleFound = true; switch (op.asOperator()) { // Simple binary operations. case Token::Addition: m_codes.append(Opcode::Add); break; case Token::Subtraction: m_codes.append(Opcode::Sub); break; case Token::Multiplication: m_codes.append(Opcode::Mul); break; case Token::Division: m_codes.append(Opcode::Div); break; case Token::Phasor: m_codes.append(Opcode::Phasor); break; case Token::Exponentiation: m_codes.append(Opcode::Pow); break; case Token::Modulo: m_codes.append(Opcode::Modulo); break; case Token::IntegerDivision: m_codes.append(Opcode::IntDiv); break; case Token::ArithmeticLeftShift: m_codes.append(Opcode::LSh); break; case Token::ArithmeticRightShift: m_codes.append(Opcode::RSh); break; case Token::BitwiseLogicalAND: m_codes.append(Opcode::BAnd); break; case Token::BitwiseLogicalOR: m_codes.append(Opcode::BOr); break; case Token::UnitConversion: { static const QRegularExpression unitNameNumberRE( "(^[0-9e\\+\\-\\.,]|[0-9e\\.,]$)", QRegularExpression::CaseInsensitiveOption ); QString unitName = m_expression.mid(b.pos(), b.size()).simplified(); // Make sure the whole unit name can be used // as a single operand in multiplications. if (b.minPrecedence() < opPrecedence(Token::Multiplication)) { unitName = "(" + unitName + ")"; } // Protect the unit name // if it starts or ends with a number. else { QRegularExpressionMatch match = unitNameNumberRE.match(unitName); if (match.hasMatch()) unitName = "(" + unitName + ")"; } m_codes.append(Opcode(Opcode::Conv, unitName)); break; } default: break; }; syntaxStack.reduce(3); #ifdef EVALUATOR_DEBUG dbg << "\tRule for binary operator" << "\n"; #endif } } #ifdef ALLOW_IMPLICIT_MULT // Rule for implicit multiplication. // Action: Treat as A * B. // Exception: doesn't apply if B is a function name // (to manage shift/reduce conflict with simplified // function syntax (fixes issue #600). if (!ruleFound && syntaxStack.itemCount() >= 2) { Token b = syntaxStack.top(); Token a = syntaxStack.top(1); if (a.isOperand() && b.isOperand() && token.asOperator() != Token::AssociationStart && ( // Token is normal operator. (token.isOperator() && !s_isOpeningUnitBracketToken(token) && opPrecedence(Token::Multiplication) >= opPrecedence(token.asOperator())) || token.isOperand()) // Implicit multiplication. && !isFunction(b)) { ruleFound = true; syntaxStack.reduce(2, opPrecedence(Token::Multiplication)); m_implicitMultiplicationOpcodeIndices.insert(m_codes.count()); m_codes.append(Opcode::Mul); #ifdef EVALUATOR_DEBUG dbg << "\tRule for implicit multiplication" << "\n"; #endif } } #endif // Rule for unary operator: (op1) (op2) X -> (op1) X. // Conditions: op2 is unary. // Current token has lower precedence than multiplication. if (!ruleFound && token.asOperator() != Token::AssociationStart && syntaxStack.itemCount() >= 3) { Token x = syntaxStack.top(); Token op2 = syntaxStack.top(1); Token op1 = syntaxStack.top(2); if (x.isOperand() && op1.isOperator() && (op2.asOperator() == Token::Addition || op2.asOperator() == Token::Subtraction || op2.asOperator() == Token::BitwiseLogicalNOT) && !(token.isOperand() && isFunction(x)) && (token.isOperand() || opPrecedence(token.asOperator()) <= opPrecedence(Token::Multiplication))) { ruleFound = true; if (op2.asOperator() == Token::Subtraction) m_codes.append(Opcode(Opcode::Neg)); else if (op2.asOperator() == Token::BitwiseLogicalNOT) m_codes.append(Opcode(Opcode::BNot)); syntaxStack.reduce(2); #ifdef EVALUATOR_DEBUG dbg << "\tRule for unary operator" << op2.text() << "\n"; #endif } } // Auxiliary rule for unary prefix operator: (op) X -> X. // Conditions: op is unary, op is first in syntax stack. // Action: create code for (op). Unary MINUS or PLUS are // treated with the precedence of multiplication. if (!ruleFound && token.asOperator() != Token::AssociationStart && syntaxStack.itemCount() == 2) { Token x = syntaxStack.top(); Token op = syntaxStack.top(1); if (x.isOperand() && (op.asOperator() == Token::Addition || op.asOperator() == Token::Subtraction || op.asOperator() == Token::BitwiseLogicalNOT) && !(token.isOperand() && isFunction(x)) && ((token.isOperator() && opPrecedence(token.asOperator()) <= opPrecedence(Token::Multiplication)) || token.isOperand())) { ruleFound = true; if (op.asOperator() == Token::Subtraction) m_codes.append(Opcode(Opcode::Neg)); else if (op.asOperator() == Token::BitwiseLogicalNOT) m_codes.append(Opcode(Opcode::BNot)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for unary operator (auxiliary)" << "\n"; #endif syntaxStack.reduce(2); } } if (!ruleFound) break; } // Can't apply rules anymore, push the token. syntaxStack.push(token); // For identifiers, generate code to load from references. if (tokenType == Token::stxIdentifier || tokenType == Token::stxUnitIdentifier) { m_identifiers.append(token.text()); const Opcode::Type refOpcodeType = tokenType == Token::stxUnitIdentifier ? Opcode::UnitRef : Opcode::Ref; m_codes.append(Opcode(refOpcodeType, m_identifiers.count() - 1)); #ifdef EVALUATOR_DEBUG dbg << "\tPush " << token.text() << " to identifier pools" << "\n"; #endif } // For constants, generate code to load from a constant. if (tokenType == Token::stxNumber) { m_constants.append(token.asNumber()); m_constantTexts.append(token.text()); m_codes.append(Opcode(Opcode::Load, m_constants.count() - 1)); #ifdef EVALUATOR_DEBUG dbg << "\tPush " << token.asNumber() << " to constant pools" << "\n"; #endif } } m_valid = false; if (syntaxStack.hasError()) m_error = syntaxStack.error(); // syntaxStack must left only one operand // and end-of-expression (i.e. Invalid). else if (syntaxStack.itemCount() == 2 && syntaxStack.top().isOperator() && syntaxStack.top().asOperator() == Token::Invalid && !syntaxStack.top(1).isOperator()) { m_valid = true; m_hasImplicitMultiplication = !m_implicitMultiplicationOpcodeIndices.isEmpty(); const bool preserveSourceSexagesimalDisplay = hasGeneratedSexagesimalUnit && !hasUnitConversionToken && !hasPhasorToken && m_implicitMultiplicationOpcodeIndices.isEmpty(); m_interpretedExpression = preserveSourceSexagesimalDisplay ? QString() : buildInterpretedExpressionFromOpcodes(); } #ifdef EVALUATOR_DEBUG dbg << "Dump: " << dump() << "\n"; debugFile.close(); #endif // Bad parsing? Clean-up everything. if (!m_valid) { m_constants.clear(); m_constantTexts.clear(); m_codes.clear(); m_identifiers.clear(); m_implicitMultiplicationOpcodeIndices.clear(); m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; } } QString Evaluator::buildInterpretedExpressionFromOpcodes() const { struct RenderNode { QString text; int precedence; Opcode::Type rootOpcode; bool isLiteralSymbol; bool isNumericOnly; bool isUnaryNegation; }; QVector stack; QHash refs; auto wrapInParentheses = [](const QString& text) { return QStringLiteral("(%1)").arg(text); }; auto makeUnaryNode = [&wrapInParentheses](const QString& symbol, const RenderNode& operand, int precedence) { QString operandText = operand.text; if (operand.precedence <= precedence) operandText = wrapInParentheses(operandText); return RenderNode{ symbol + operandText, precedence, Opcode::Nop, operand.isLiteralSymbol, operand.isNumericOnly, symbol == QLatin1String("-") }; }; auto makeBinaryNode = [&wrapInParentheses, this](const RenderNode& left, const RenderNode& right, Opcode::Type opcodeType, int opcodeIndex) { if (opcodeType == Opcode::Unit) { const int precedence = opcodePrecedence(opcodeType); QString leftText = left.text; if (left.precedence < precedence) leftText = wrapInParentheses(leftText); return RenderNode{ leftText + MathDsl::UnitStart + right.text + MathDsl::UnitEnd, precedence, opcodeType, left.isLiteralSymbol || right.isLiteralSymbol, left.isNumericOnly && right.isNumericOnly, false }; } Opcode::Type renderedOpcodeType = opcodeType; QString rightText = right.text; if (opcodeType == Opcode::Sub && right.isUnaryNegation) { // Prefer "a+b" over "a-(-b)" / "a--b" in interpreted output. renderedOpcodeType = Opcode::Add; if (rightText.startsWith(MathDsl::SubOpAl1)) rightText.remove(0, 1); } const int precedence = opcodePrecedence(renderedOpcodeType); const bool isRightAssociative = isRightAssociativeOpcode(opcodeType); const bool isImplicitMultiplication = opcodeType == Opcode::Mul && m_implicitMultiplicationOpcodeIndices.contains(opcodeIndex); QString leftText = left.text; if (left.precedence < precedence || (isRightAssociative && left.precedence == precedence)) { leftText = wrapInParentheses(leftText); } if (right.precedence < precedence || (!isRightAssociative && right.precedence == precedence)) { rightText = wrapInParentheses(rightText); } // In contextual percent expressions, make the additive base explicit: // render "1+99+10%" as "(1+99)+10%". if ((opcodeType == Opcode::Add || opcodeType == Opcode::Sub) && right.rootOpcode == Opcode::Percent && (left.rootOpcode == Opcode::Add || left.rootOpcode == Opcode::Sub) && !isWrappedInOuterParentheses(leftText)) { leftText = wrapInParentheses(leftText); } const bool leftIsAtomicNumericForGrouping = left.isNumericOnly && left.rootOpcode == Opcode::Nop && !left.isLiteralSymbol; const bool rightIsAtomicNumericForGrouping = right.isNumericOnly && right.rootOpcode == Opcode::Nop && !right.isLiteralSymbol; // Make "a / b c" style parses explicit as "(a / b) * c", except // for simple numeric factors where a flat mul/div chain is clearer. if (opcodeType == Opcode::Mul && isImplicitMultiplication && (left.rootOpcode == Opcode::Div || left.rootOpcode == Opcode::IntDiv || left.rootOpcode == Opcode::Modulo)) { const bool allowFlatChainForSimpleDivisorFactor = left.rootOpcode == Opcode::Div && rightIsAtomicNumericForGrouping; if (!allowFlatChainForSimpleDivisorFactor) leftText = wrapInParentheses(leftText); } if (opcodeType == Opcode::Mul && isImplicitMultiplication && (right.rootOpcode == Opcode::Div || right.rootOpcode == Opcode::IntDiv || right.rootOpcode == Opcode::Modulo)) { const bool allowFlatChainForSimpleDividendFactor = right.rootOpcode == Opcode::Div && leftIsAtomicNumericForGrouping; if (!allowFlatChainForSimpleDividendFactor) rightText = wrapInParentheses(rightText); } // For explicit multiplications, isolate most power terms to improve // readability in compound products (for example "1·(2^3)·3"), but // keep scientific-notation powers of ten flat ("x·10^n"). if (opcodeType == Opcode::Mul && !isImplicitMultiplication) { static const QRegularExpression s_scientificPowerOfTenRE( QStringLiteral(R"(^10\^(?:[−-]?\d+|\([−-]?\d+\))$)")); const bool keepLeftNumericPowerUnwrappedBeforeAtomicNumber = left.rootOpcode == Opcode::Pow && left.isNumericOnly && rightIsAtomicNumericForGrouping; if (left.rootOpcode == Opcode::Pow && !left.isLiteralSymbol && !keepLeftNumericPowerUnwrappedBeforeAtomicNumber && !s_scientificPowerOfTenRE.match(leftText).hasMatch() && !isWrappedInOuterParentheses(leftText)) { leftText = wrapInParentheses(leftText); } if (right.rootOpcode == Opcode::Pow && !right.isLiteralSymbol && !s_scientificPowerOfTenRE.match(rightText).hasMatch() && !isWrappedInOuterParentheses(rightText)) { rightText = wrapInParentheses(rightText); } } // Keep explicit grouping for factorial denominators // (for example "1/(2!)"). if (opcodeType == Opcode::Div && right.rootOpcode == Opcode::Fact && !isWrappedInOuterParentheses(rightText)) { rightText = wrapInParentheses(rightText); } // Keep non-integer numeric exponents explicit (for example // "2^(12.5)" instead of "2^12.5"). if (opcodeType == Opcode::Pow && !isWrappedInOuterParentheses(rightText)) { normalizeUnsignedIntegerEquivalentDecimalText(rightText); const bool isNonIntegerNumericExponent = right.isNumericOnly && right.rootOpcode == Opcode::Nop && !isUnsignedDecimalIntegerText(rightText); const bool isFactorialExponent = right.rootOpcode == Opcode::Fact; const bool isChainedExponent = right.rootOpcode == Opcode::Pow; if (isNonIntegerNumericExponent || isFactorialExponent || isChainedExponent) rightText = wrapInParentheses(rightText); } const bool leftIsAtomicNumeric = left.isNumericOnly && left.rootOpcode == Opcode::Nop && !left.isLiteralSymbol; const bool rightIsAtomicNumeric = right.isNumericOnly && right.rootOpcode == Opcode::Nop && !right.isLiteralSymbol; const bool isNumberTimesNumber = opcodeType == Opcode::Mul && leftIsAtomicNumeric && rightIsAtomicNumeric; static const QRegularExpression s_endsWithDigitRE(QStringLiteral(R"([0-9]$)")); static const QRegularExpression s_endsWithDigitOrSuperscriptRE( QStringLiteral(R"([0-9â�°Â¹Â²Â³â�´â�µâ�¶â�·â�¸â�¹]$)")); const bool isNumericBoundaryTimesNumber = opcodeType == Opcode::Mul && !isImplicitMultiplication && rightIsAtomicNumeric && (s_endsWithDigitRE.match(leftText).hasMatch() || s_endsWithDigitOrSuperscriptRE.match(leftText).hasMatch()); const bool isLiteralSymbolMultiplication = opcodeType == Opcode::Mul && !isNumberTimesNumber && !isNumericBoundaryTimesNumber; const QString infixSymbol = opcodeToInfixSymbol( renderedOpcodeType, isImplicitMultiplication || isLiteralSymbolMultiplication ); return RenderNode{ leftText + infixSymbol + rightText, precedence, renderedOpcodeType, left.isLiteralSymbol || right.isLiteralSymbol, left.isNumericOnly && right.isNumericOnly, false }; }; for (int opcodeIndex = 0; opcodeIndex < m_codes.count(); ++opcodeIndex) { const Opcode& opcode = m_codes.at(opcodeIndex); switch (opcode.type) { case Opcode::Nop: break; case Opcode::Load: { QString constantText = m_constantTexts.value(opcode.index); if (constantText.isEmpty()) { constantText = DMath::format(m_constants.value(opcode.index), Quantity::Format::Fixed()); } stack.append({ constantText, MAX_PRECEDENCE, Opcode::Nop, false, true, false }); break; } case Opcode::Ref: case Opcode::UnitRef: { const QString identifier = m_identifiers.value(opcode.index); const bool isUnitReference = opcode.type == Opcode::UnitRef; stack.append({ identifier, MAX_PRECEDENCE, Opcode::Nop, true, false, false }); if (isUnitReference) break; if (m_assignArg.contains(identifier) || hasVariable(identifier)) break; if (FunctionRepo::instance()->find(identifier) || hasUserFunction(identifier) || m_assignFunc) { refs.insert(stack.count(), identifier); } break; } case Opcode::Neg: case Opcode::BNot: { if (stack.isEmpty()) return QString(); const RenderNode operand = stack.takeLast(); if (opcode.type == Opcode::Neg && operand.isUnaryNegation) { QString text = operand.text; if (text.startsWith(MathDsl::SubOpAl1)) text.remove(0, 1); stack.append({ text, MAX_PRECEDENCE, Opcode::Nop, operand.isLiteralSymbol, operand.isNumericOnly, false }); break; } const QString symbol = opcode.type == Opcode::Neg ? "-" : "~"; stack.append(makeUnaryNode(symbol, operand, opcodePrecedence(opcode.type))); break; } case Opcode::Fact: case Opcode::Percent: { if (stack.isEmpty()) return QString(); const int precedence = opcodePrecedence(opcode.type); RenderNode operand = stack.takeLast(); if (operand.precedence < precedence) operand.text = wrapInParentheses(operand.text); const QString symbol = opcode.type == Opcode::Fact ? QStringLiteral("!") : QStringLiteral("%"); stack.append({ operand.text + symbol, precedence, opcode.type, operand.isLiteralSymbol, operand.isNumericOnly, false }); break; } case Opcode::Add: case Opcode::Sub: case Opcode::Mul: case Opcode::Div: case Opcode::Phasor: case Opcode::Pow: case Opcode::Modulo: case Opcode::IntDiv: case Opcode::LSh: case Opcode::RSh: case Opcode::BAnd: case Opcode::BOr: case Opcode::Conv: case Opcode::Unit: { if (stack.size() < 2) return QString(); const RenderNode right = stack.takeLast(); const RenderNode left = stack.takeLast(); stack.append(makeBinaryNode(left, right, opcode.type, opcodeIndex)); break; } case Opcode::Function: { const int argumentCount = static_cast(opcode.index); const int functionRefKey = stack.count() - argumentCount; QString functionName = refs.take(functionRefKey); if (functionName.isEmpty() && functionRefKey > 0 && functionRefKey <= stack.count()) { functionName = stack.at(functionRefKey - 1).text; } if (stack.count() < argumentCount + 1) return QString(); QStringList arguments; for (int i = 0; i < argumentCount; ++i) arguments.prepend(stack.takeLast().text); // Discard function reference placeholder. stack.takeLast(); if (functionName == QLatin1String("list")) { stack.append({ QString(MathDsl::ListStart) + arguments.join("; ") + QString(MathDsl::ListEnd), MAX_PRECEDENCE, Opcode::Nop, false, false, false }); break; } stack.append({ QStringLiteral("%1(%2)").arg( UnicodeChars::normalizeRootFunctionAliasesForDisplay(functionName), arguments.join("; ")), MAX_PRECEDENCE, Opcode::Nop, true, false, false }); break; } case Opcode::List: { const int elementCount = static_cast(opcode.index); if (stack.count() < elementCount) return QString(); QStringList elements; for (int i = 0; i < elementCount; ++i) elements.prepend(stack.takeLast().text); stack.append({ QStringLiteral("{%1}").arg(elements.join("; ")), MAX_PRECEDENCE, Opcode::Nop, false, false, false }); break; } } } if (stack.count() != 1) return QString(); return stack.constLast().text; } bool hasMixedStandaloneExplicitAngleTermAddSub(const Tokens& tokens) { if (tokens.isEmpty()) return false; auto isTopLevelAddSub = [](const Token& token) { const Token::Operator op = token.asOperator(); return op == Token::Addition || op == Token::Subtraction; }; int parenDepth = 0; int unitDepth = 0; QVector splitOps; for (int i = 0; i < tokens.size(); ++i) { const Token& token = tokens.at(i); const QString text = token.text(); if (text == QString(MathDsl::GroupStart)) { ++parenDepth; continue; } if (text == QString(MathDsl::GroupEnd)) { if (parenDepth > 0) --parenDepth; continue; } if (text == QString(MathDsl::UnitStart)) { ++unitDepth; continue; } if (text == QString(MathDsl::UnitEnd)) { if (unitDepth > 0) --unitDepth; continue; } if (parenDepth == 0 && unitDepth == 0 && isTopLevelAddSub(token)) splitOps.append(i); } if (splitOps.isEmpty()) return false; auto termHasFunctionCall = [&tokens](int start, int end) { for (int i = start; i < end; ++i) { if (!tokens.at(i).isIdentifier()) continue; if (i + 1 < end && tokens.at(i + 1).text() == QString(MathDsl::GroupStart)) return true; } return false; }; auto termHasExplicitAngleUnit = [&tokens](int start, int end) { for (int i = start; i < end; ++i) { if (!tokens.at(i).isUnitIdentifier()) continue; if (Units::isExplicitAngleUnitName(tokens.at(i).text())) return true; } return false; }; bool hasStandaloneExplicitAngleTerm = false; bool hasNonStandaloneExplicitAngleTerm = false; int termStart = 0; for (int part = 0; part <= splitOps.size(); ++part) { const int termEnd = (part < splitOps.size()) ? splitOps.at(part) : tokens.size(); if (termStart >= termEnd) { termStart = termEnd + 1; continue; } const bool hasAngleUnit = termHasExplicitAngleUnit(termStart, termEnd); const bool hasFunction = termHasFunctionCall(termStart, termEnd); if (hasAngleUnit && !hasFunction) hasStandaloneExplicitAngleTerm = true; else hasNonStandaloneExplicitAngleTerm = true; termStart = termEnd + 1; } return hasStandaloneExplicitAngleTerm && hasNonStandaloneExplicitAngleTerm; } static void replaceSuperscriptPowersWithCaretEquivalent(QString& expr); static void replacePowerOfTenScientificNotationWithDecimalExponent(QString& expr) { static const QRegularExpression pattern( QStringLiteral(R"((\d+(?:\.\d*)?|\.\d+)\s*[\*×]\s*10([â�°Â¹Â²Â³â�´â�µâ�¶â�·â�¸â�¹â�»â�º]+))")); int offset = 0; while (true) { const QRegularExpressionMatch match = pattern.match(expr, offset); if (!match.hasMatch()) break; const QString replacement = match.captured(1) + QLatin1Char('e') + superscriptDigitsToAscii(match.captured(2)); expr.replace(match.capturedStart(), match.capturedLength(), replacement); offset = match.capturedStart() + replacement.size(); } } Quantity Evaluator::evalNoAssign() { Quantity result; if (m_dirty) { // Reset. m_assignId = QString(); m_assignFunc = false; m_assignArg.clear(); m_assignVarDescription = QString(); m_assignUnitDescription = QString(); m_assignFuncExpr = QString(); m_assignUnitExpr = QString(); m_assignFuncDescription = QString(); m_assignUnit = false; m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; QString expressionToParse = m_expression; QString trailingComment; const int commentPos = m_expression.indexOf(MathDsl::CommentSep); if (commentPos >= 0) trailingComment = m_expression.mid(commentPos + 1).trimmed(); if (m_expression.contains(MathDsl::CommentSep)) { QString expressionWithoutDescription; QString description; if (splitUserFunctionDescription(m_expression, &expressionWithoutDescription, &description)) { expressionToParse = expressionWithoutDescription; m_assignFuncDescription = description; } else if (splitVariableDescription(m_expression, &expressionWithoutDescription, &description)) { expressionToParse = expressionWithoutDescription; m_assignVarDescription = description; } } // Fallback interpreted text (such as standalone angles) must not // include a comment that will be appended again below. if (commentPos >= 0) expressionToParse = expressionToParse.left(commentPos).trimmed(); replacePowerOfTenScientificNotationWithDecimalExponent(expressionToParse); replaceSuperscriptPowersWithCaretEquivalent(expressionToParse); Tokens tokens = scan(expressionToParse); // Invalid expression? if (!tokens.valid()) { m_error = tr("invalid expression"); m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; return Quantity(0); } if (tokens.count() == 0 && isCommentOnlyExpression(m_expression)) { m_valid = true; m_constants.clear(); m_constantTexts.clear(); m_codes.clear(); m_identifiers.clear(); m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; return CMath::nan(); } // User unit assignment? if (s_isUserUnitLhsTokens(tokens)) { m_assignId = tokens.at(1).text(); m_assignUnit = true; m_assignUnitExpr = expressionToParse.section("=", 1, 1).trimmed(); m_assignUnitDescription = m_assignVarDescription; for (int i = 0; i < 4; ++i) tokens.erase(tokens.begin()); } // Variable assignment? else if (tokens.count() > 2 && tokens.at(0).isIdentifier() && tokens.at(1).asOperator() == Token::Assignment) { m_assignId = tokens.at(0).text(); tokens.erase(tokens.begin()); tokens.erase(tokens.begin()); } else if (tokens.count() > 2 && tokens.at(0).isIdentifier() && tokens.at(1).asOperator() == Token::AssociationStart && tokens.at(1).text() == QLatin1String("(")) { // Check for function assignment. // Syntax: // ident opLeftPar (ident (opSemiColon ident)*)? opRightPar opEqual int t; if (tokens.count() > 4 && tokens.at(2).asOperator() == Token::AssociationEnd) { // Functions with no argument. t = 3; if (tokens.at(3).asOperator() == Token::Assignment) m_assignFunc = true; } else { for (t = 2; t + 1 < tokens.count(); t += 2) { if (!tokens.at(t).isIdentifier()) break; m_assignArg.append(tokens.at(t).text()); if (tokens.at(t+1).asOperator() == Token::AssociationEnd) { t += 2; if (t < tokens.count() && tokens.at(t).asOperator() == Token::Assignment) { m_assignFunc = true; } break; } else if (tokens.at(t + 1) .asOperator() != Token::ListSeparator) break; } } if (m_assignFunc) { m_assignId = tokens.at(0).text(); m_assignFuncExpr = expressionToParse.section("=", 1, 1).trimmed(); for (; t >= 0; --t) tokens.erase(tokens.begin()); } else m_assignArg.clear(); } if (hasMixedStandaloneExplicitAngleTermAddSub(tokens)) { m_error = tr("dimension mismatch - quantities with " "different dimensions cannot be compared, " "added, etc."); m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; return CNumber(0); } compile(tokens); if (!m_valid) { if (m_error.isEmpty()) m_error = tr("syntax error"); m_interpretedExpression = QString(); m_hasImplicitMultiplication = false; return CNumber(0); } if (m_interpretedExpression.isEmpty() && !tokens.isEmpty()) m_interpretedExpression = expressionToParse.trimmed(); if (!m_assignId.isEmpty() && !m_interpretedExpression.isEmpty()) { if (m_assignFunc) { const QString leftSide = QStringLiteral("%1(%2)").arg( m_assignId, m_assignArg.join(";") ); m_interpretedExpression = leftSide + QStringLiteral("=") + m_interpretedExpression; } else if (m_assignUnit) { QString interpretedRightSide = m_interpretedExpression; if (s_isBracketedExpression(m_assignUnitExpr) && !s_isBracketedExpression(interpretedRightSide)) { interpretedRightSide = QStringLiteral("[%1]").arg(interpretedRightSide.trimmed()); } m_interpretedExpression = QStringLiteral("[%1]=%2").arg(m_assignId, interpretedRightSide); } else { m_interpretedExpression = m_assignId + QStringLiteral("=") + m_interpretedExpression; } } if (!m_interpretedExpression.isEmpty() && !trailingComment.isEmpty()) m_interpretedExpression += QStringLiteral(" ? ") + trailingComment; } result = exec(m_codes, m_constants, m_identifiers); return result; } Quantity Evaluator::exec(const QVector& opcodes, const QVector& constants, const QStringList& identifiers) { struct StackEntry { Quantity value; bool isPercentValue; }; QStack stack; QHash refs; int index; Quantity val1, val2; bool val1IsPercent = false; bool rhsIsPercent = false; QVector args; QString fname; Function* function; const UserFunction* userFunction = nullptr; auto pushStackValue = [&stack](const Quantity& value, bool isPercentValue = false) { stack.push(StackEntry{value, isPercentValue}); }; auto popStackValue = [&stack](Quantity& value, bool* isPercentValue = nullptr) { const StackEntry entry = stack.pop(); value = entry.value; if (isPercentValue) *isPercentValue = entry.isPercentValue; }; auto hasPendingDeferredSummationContext = [&refs](int stackSize) { QHash::const_iterator it = refs.constBegin(); for (; it != refs.constEnd(); ++it) { if (it.key() <= stackSize && s_isSummationFunctionIdentifier(it.value())) { return true; } } return false; }; auto hasPendingDeferredMolmassContext = [&refs](int stackSize) { QHash::const_iterator it = refs.constBegin(); for (; it != refs.constEnd(); ++it) { if (it.key() <= stackSize && s_isMolmassFunctionIdentifier(it.value())) { return true; } } return false; }; auto hasPendingDeferredMassContext = [&refs](int stackSize) { QHash::const_iterator it = refs.constBegin(); for (; it != refs.constEnd(); ++it) { if (it.key() <= stackSize && s_isMassFunctionIdentifier(it.value())) { return true; } } return false; }; auto hasPendingDeferredOperandContext = [&hasPendingDeferredSummationContext, &hasPendingDeferredMolmassContext, &hasPendingDeferredMassContext](int stackSize) { return hasPendingDeferredSummationContext(stackSize) || hasPendingDeferredMolmassContext(stackSize) || hasPendingDeferredMassContext(stackSize); }; auto checkOperatorResultWithDeferredNoOperand = [this, &hasPendingDeferredOperandContext, &stack](const Quantity& result) { if (result.error() == NoOperand && hasPendingDeferredOperandContext(stack.count())) { return result; } return checkOperatorResult(result); }; for (int pc = 0; pc < opcodes.count(); ++pc) { const Opcode& opcode = opcodes.at(pc); index = opcode.index; switch (opcode.type) { // No operation. case Opcode::Nop: break; // Load a constant, push to stack. case Opcode::Load: val1 = constants.at(index); pushStackValue(val1); break; case Opcode::List: { if (stack.count() < index) { m_error = tr("invalid expression"); return CMath::nan(); } QVector elements; for (; index; --index) elements.prepend(stack.pop().value); val1 = Quantity::list(elements); val1 = checkOperatorResult(val1); pushStackValue(val1); break; } // Unary operation. case Opcode::Neg: if (stack.count() < 1) { m_error = tr("invalid expression"); return CMath::nan(); } val1IsPercent = false; popStackValue(val1, &val1IsPercent); val1 = checkOperatorResultWithDeferredNoOperand(-val1); pushStackValue(val1, val1IsPercent); break; case Opcode::BNot: if (stack.count() < 1) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); val1 = checkOperatorResultWithDeferredNoOperand(~val1); pushStackValue(val1); break; // Binary operation: take two values from stack, // do the operation, push the result to stack. case Opcode::Add: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } rhsIsPercent = false; popStackValue(val1, &rhsIsPercent); popStackValue(val2); if (rhsIsPercent) val1 = checkOperatorResultWithDeferredNoOperand(val2 * val1); val2 = checkOperatorResultWithDeferredNoOperand(val2 + val1); pushStackValue(val2); break; case Opcode::Sub: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } rhsIsPercent = false; popStackValue(val1, &rhsIsPercent); popStackValue(val2); if (rhsIsPercent) val1 = checkOperatorResultWithDeferredNoOperand(val2 * val1); val2 = checkOperatorResultWithDeferredNoOperand(val2 - val1); pushStackValue(val2); break; case Opcode::Mul: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); popStackValue(val2); val2 = checkOperatorResultWithDeferredNoOperand(val2 * val1); pushStackValue(val2); break; case Opcode::Unit: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); popStackValue(val2); { HNumber affineBaseValue; if (val2.isDimensionless() && val2.numericValue().isNearReal() && Units::tryConvertAffineToBase( val1.unitName(), val2.numericValue().real, &affineBaseValue)) { Quantity absolute = Quantity(affineBaseValue) * Units::kelvin(); absolute.setDisplayUnit(CNumber(1), val1.unitName()); val2 = checkOperatorResultWithDeferredNoOperand(absolute); } else { val2 = checkOperatorResultWithDeferredNoOperand(val2 * val1); } } pushStackValue(val2); break; case Opcode::Div: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); popStackValue(val2); val2 = checkOperatorResultWithDeferredNoOperand(val2 / val1); pushStackValue(val2); break; case Opcode::Phasor: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); popStackValue(val2); val2 = checkOperatorResultWithDeferredNoOperand( val2 * s_cisFromAngle(val1)); pushStackValue(val2); break; case Opcode::Pow: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); popStackValue(val2); val2 = checkOperatorResultWithDeferredNoOperand(DMath::raise(val2, val1)); pushStackValue(val2); break; case Opcode::Fact: if (stack.count() < 1) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); val1 = checkOperatorResultWithDeferredNoOperand(DMath::factorial(val1)); pushStackValue(val1); break; case Opcode::Percent: if (stack.count() < 1) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); val1 = checkOperatorResultWithDeferredNoOperand(val1 / Quantity(100)); pushStackValue(val1, true); break; case Opcode::Modulo: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); popStackValue(val2); val2 = checkOperatorResultWithDeferredNoOperand(val2 % val1); pushStackValue(val2); break; case Opcode::IntDiv: if (stack.count() < 2) { m_error = tr("invalid expression"); return CMath::nan(); } popStackValue(val1); popStackValue(val2); val2 = checkOperatorResultWithDeferredNoOperand(val2 / val1); pushStackValue(DMath::integer(val2)); break; case Opcode::LSh: if (stack.count() < 2) { m_error = tr("invalid expression"); return DMath::nan(); } popStackValue(val1); popStackValue(val2); val2 = val2 << val1; pushStackValue(val2); break; case Opcode::RSh: if (stack.count() < 2) { m_error = tr("invalid expression"); return DMath::nan(); } popStackValue(val1); popStackValue(val2); val2 = val2 >> val1; pushStackValue(val2); break; case Opcode::BAnd: if (stack.count() < 2) { m_error = tr("invalid expression"); return DMath::nan(); } popStackValue(val1); popStackValue(val2); val2 &= val1; pushStackValue(val2); break; case Opcode::BOr: if (stack.count() < 2) { m_error = tr("invalid expression"); return DMath::nan(); } popStackValue(val1); popStackValue(val2); val2 |= val1; pushStackValue(val2); break; case Opcode::Conv: { auto isFullyWrappedByOuterParens = [](const QString& expr) { if (expr.size() < 2 || expr.at(0) != MathDsl::GroupStart || expr.at(expr.size() - 1) != MathDsl::GroupEnd) return false; int depth = 0; for (int i = 0; i < expr.size(); ++i) { const QChar ch = expr.at(i); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd) --depth; if (depth == 0 && i < expr.size() - 1) return false; } return depth == 0; }; auto isFullyWrappedByOuterBrackets = [](const QString& expr) { if (expr.size() < 2 || expr.at(0) != MathDsl::UnitStart || expr.at(expr.size() - 1) != MathDsl::UnitEnd) return false; int depth = 0; for (int i = 0; i < expr.size(); ++i) { const QChar ch = expr.at(i); if (ch == MathDsl::UnitStart) ++depth; else if (ch == MathDsl::UnitEnd) --depth; if (depth == 0 && i < expr.size() - 1) return false; } return depth == 0; }; if (stack.count() < 2) { m_error = tr("invalid expression"); return HMath::nan(); } popStackValue(val1); popStackValue(val2); auto targetContainsUnitIdentifier = [this](const QString& targetText) { const Tokens targetTokens = scan(targetText); if (!targetTokens.valid()) return false; for (const Token& token : targetTokens) { if (token.isUnitIdentifier() || (token.isIdentifier() && tryGetAnyUnitQuantity(token.text(), nullptr))) { return true; } } return false; }; if (!targetContainsUnitIdentifier(opcode.text)) { m_error = tr("conversion target must be a unit"); return HMath::nan(); } if (val1.isZero()) { m_error = tr("unit must not be zero"); return HMath::nan(); } if (!val1.sameDimension(val2)) { m_error = tr("Conversion failed - dimension mismatch"); return HMath::nan(); } const bool targetIsAffineUnit = Units::isAffineUnitName(val1.unitName()); CNumber displayUnitValue = targetIsAffineUnit ? CNumber(1) : val1.numericValue(); QString displayUnitName = opcode.text.trimmed(); if (isFullyWrappedByOuterBrackets(displayUnitName)) displayUnitName = displayUnitName.mid(1, displayUnitName.size() - 2).trimmed(); if (displayUnitName.startsWith(QStringLiteral("((")) && isFullyWrappedByOuterParens(displayUnitName)) { const QString onceUnwrapped = displayUnitName.mid(1, displayUnitName.size() - 2).trimmed(); displayUnitName = onceUnwrapped; } if (isFullyWrappedByOuterParens(displayUnitName)) { const QString inner = displayUnitName.mid(1, displayUnitName.size() - 2).trimmed(); if (RegExpPatterns::simpleUnitIdentifier().match(inner).hasMatch()) displayUnitName = inner; } displayUnitName = UnicodeChars::normalizeUnitSymbolAliases(displayUnitName); const bool nestedConversionTarget = opcode.text.contains(QLatin1String("->")) || opcode.text.contains(MathDsl::TransOp); if (nestedConversionTarget) { Quantity canonicalTarget(val1); canonicalTarget.stripUnits(); if (!canonicalTarget.isDimensionless()) Units::findUnit(canonicalTarget); if (canonicalTarget.hasUnit()) { displayUnitValue = canonicalTarget.unit(); displayUnitName = canonicalTarget.unitName(); } } if (targetIsAffineUnit) { // Affine temperatures keep canonical symbol output (°C/°F) // even when the authored target uses an alternate alias. displayUnitName = val1.unitName(); } if (runtimeUnitNegativeExponentStyle() == Settings::UnitNegativeExponentSuperscript) displayUnitName = s_applySuperscriptStyleToExplicitUnitText(displayUnitName); else displayUnitName = s_renderUnitExponentsAsSuperscripts(displayUnitName); val2.setDisplayUnit(displayUnitValue, displayUnitName); pushStackValue(val2); break; } // Reference. case Opcode::Ref: fname = identifiers.at(index); if (m_assignArg.contains(fname)) { // Argument. pushStackValue(CMath::nan()); } else if (hasVariable(fname)) { // Variable. pushStackValue(getVariable(fname).value()); } else { // Function. function = FunctionRepo::instance()->find(fname); if (function) { pushStackValue(CMath::nan()); refs.insert(stack.count(), fname); } else if (m_assignFunc) { // Allow arbitrary identifiers // when declaring user functions. pushStackValue(CMath::nan()); refs.insert(stack.count(), fname); } else if (hasUserFunction(fname)) { pushStackValue(CMath::nan()); refs.insert(stack.count(), fname); } else if (fname.compare("n", Qt::CaseInsensitive) == 0 && hasPendingDeferredSummationContext(stack.count())) { pushStackValue(CMath::nan()); } else if (hasPendingDeferredMolmassContext(stack.count()) || hasPendingDeferredMassContext(stack.count())) { pushStackValue(CMath::nan()); } else { m_error = "" + fname + ": " + tr("unknown function or variable"); return CMath::nan(); } } break; case Opcode::UnitRef: fname = identifiers.at(index); if (m_assignArg.contains(fname)) { pushStackValue(CMath::nan()); break; } if (tryGetAnyUnitQuantity(fname, &val1)) { pushStackValue(val1); break; } m_error = "" + fname + ": " + tr("unknown unit"); return CMath::nan(); // Calling function. case Opcode::Function: fname = refs.take(stack.count() - index); // Identifiers followed by () must resolve to a callable. // Do not silently accept constants/variables as nullary calls. if (fname.isEmpty()) { m_error = tr("invalid expression"); return CMath::nan(); } function = FunctionRepo::instance()->find(fname); userFunction = nullptr; if (!function) { // Check if this is a valid user function call. userFunction = getUserFunction(fname); } if (!function && !userFunction && !m_assignFunc) { m_error = "" + fname + ": " + tr("unknown function or variable"); return CMath::nan(); } if (stack.count() < index) { m_error = tr("invalid expression"); return CMath::nan(); } args.clear(); for(; index; --index) args.insert(args.begin(), stack.pop().value); // Remove the NaN we put on the stack (needed to make the user // functions declaration work with arbitrary identifiers). stack.pop(); // Show function signature if user has given no argument (yet). if (userFunction) { if (!args.count() && userFunction->arguments().count() != 0) { m_error = QString::fromLatin1("%1(%2)").arg( userFunction->name(), userFunction->arguments().join(";") ); return CMath::nan(); } } if (m_assignFunc) { // Allow arbitrary identifiers for declaring user functions. pushStackValue(CMath::nan()); } else if (userFunction) { pushStackValue(execUserFunction(userFunction, args)); if (!m_error.isEmpty()) return CMath::nan(); } else if (s_isMolmassFunctionIdentifier(fname)) { if (args.count() != 1) { m_error = QString::fromLatin1("%1: ").arg(fname) + tr("wrong number of arguments"); return CMath::nan(); } Quantity molarMass; if (opcode.text.isEmpty() || !s_tryParseMolarMassFormula(opcode.text, &molarMass)) { m_error = QString::fromLatin1("%1: ").arg(fname) + tr("invalid expression"); return CMath::nan(); } pushStackValue(molarMass); } else if (s_isMassFunctionIdentifier(fname)) { if (args.count() != 2) { m_error = QString::fromLatin1("%1: ").arg(fname) + tr("wrong number of arguments"); return CMath::nan(); } Quantity molarMass; if (opcode.text.isEmpty() || !s_tryParseMolarMassFormula(opcode.text, &molarMass)) { m_error = QString::fromLatin1("%1: ").arg(fname) + tr("invalid expression"); return CMath::nan(); } Quantity amount = args.at(0); const Quantity oneMole = Units::mole(); if (amount.isDimensionless()) { amount *= oneMole; } else if (!amount.sameDimension(oneMole)) { m_error = QString::fromLatin1("%1: ").arg(fname) + tr("undefined for argument domain"); return CMath::nan(); } Quantity massResult = amount * molarMass; massResult.setDisplayUnit( Units::gram().numericValue(), QString(::unitSymbol(UnitId::Gram))); pushStackValue(massResult); } else if (s_isSummationFunctionIdentifier(fname)) { if (args.count() != 3) { m_error = QString::fromLatin1("%1: ").arg(fname) + tr("wrong number of arguments"); return CMath::nan(); } if (!args.at(0).isInteger() || !args.at(1).isInteger()) { m_error = QString::fromLatin1("%1: ").arg(fname) + tr("undefined for argument domain"); return CMath::nan(); } const bool hadN = hasVariable("n"); const Variable oldN = hadN ? getVariable("n") : Variable(QString(), Quantity(0)); auto restoreN = [this, hadN, oldN]() { if (hadN) { setVariable("n", oldN.value(), oldN.type(), oldN.description()); } else { unsetVariable("n"); } }; const Quantity start = args.at(0); const Quantity end = args.at(1); const Quantity step = (start <= end) ? Quantity(1) : Quantity(-1); const bool hasExpression = !opcode.text.isEmpty(); Quantity sigmaResult(0); for (Quantity n = start; step > 0 ? (n <= end) : (n >= end); n += step) { setVariable("n", n); Quantity term = args.at(2); if (hasExpression) { const bool savedDirty = m_dirty; const QString savedExpression = m_expression; const bool savedValid = m_valid; const QString savedInterpretedExpression = m_interpretedExpression; const QString savedAssignId = m_assignId; const bool savedAssignFunc = m_assignFunc; const QStringList savedAssignArg = m_assignArg; const QVector savedCodes = m_codes; const QVector savedConstants = m_constants; const QStringList savedIdentifiers = m_identifiers; const QString savedError = m_error; setExpression(opcode.text); term = evalNoAssign(); const QString termError = m_error; m_dirty = savedDirty; m_expression = savedExpression; m_valid = savedValid; m_interpretedExpression = savedInterpretedExpression; m_assignId = savedAssignId; m_assignFunc = savedAssignFunc; m_assignArg = savedAssignArg; m_codes = savedCodes; m_constants = savedConstants; m_identifiers = savedIdentifiers; m_error = savedError; if (!termError.isEmpty()) { restoreN(); m_error = QString::fromLatin1("%1: ").arg(fname) + termError; return CMath::nan(); } } sigmaResult += term; } restoreN(); pushStackValue(sigmaResult); } else { pushStackValue(function->exec(args)); if (function->error()) { if (!args.count() && function->error() == InvalidParamCount) { m_error = QString::fromLatin1("%1(%2)").arg( fname, function->usage() ); } else { m_error = stringFromFunctionError(function); } return CMath::nan(); } } break; default: break; } } // More than one value in stack? Unsuccessful execution. if (stack.count() != 1) { m_error = tr("invalid expression"); return CMath::nan(); } return stack.pop().value; } Quantity Evaluator::execUserFunction(const UserFunction* function, QVector& arguments) { // TODO: Replace user variables by user functions (with no argument)? if (arguments.count() != function->arguments().count()) { m_error = "" + function->name() + ": " + tr("wrong number of arguments"); return CMath::nan(); } if (m_functionsInUse.contains(function->name())) { m_error = "" + function->name() + ": " + tr("recursion not supported"); return CMath::nan(); } m_functionsInUse.insert(function->name()); QVector newOpcodes; auto newConstants = function->constants; // Copy. // Replace references to function arguments by constants. for (int i = 0; i < function->opcodes.count(); ++i) { Opcode opcode = function->opcodes.at(i); if (opcode.type == Opcode::Ref) { // Check if the identifier is an argument name. QString name = function->identifiers.at(opcode.index); int argIdx = function->arguments().indexOf(name); if (argIdx >= 0) { // Replace the reference by a constant value. opcode = Opcode(Opcode::Load, newConstants.count()); newConstants.append(arguments.at(argIdx)); } } newOpcodes.append(opcode); } auto result = exec(newOpcodes, newConstants, function->identifiers); if (!m_error.isEmpty()) { // Tell the user where the error happened. m_error = "" + function->name() + ": " + m_error; } m_functionsInUse.remove(function->name()); return result; } bool Evaluator::isUserFunctionAssign() const { return m_assignFunc; } bool Evaluator::isUserUnitAssign() const { return m_assignUnit; } bool Evaluator::isUserVariableAssign() const { return !m_assignId.isEmpty() && !m_assignFunc && !m_assignUnit; } bool Evaluator::isBuiltInVariable(const QString& id) const { // Defining variables with the same name as existing functions // is not supported for now. if (FunctionRepo::instance()->find(id)) return true; if (!m_symbols.variables().contains(id)) return false; return m_symbols.variables().get(id).type() == Variable::BuiltIn; } Quantity Evaluator::eval() { Quantity result = evalNoAssign(); // This sets m_assignId. if (!m_error.isEmpty()) return result; if (!m_assignUnit && isBuiltInVariable(m_assignId)) { m_error = tr("%1 is a reserved name, " "please choose another").arg(m_assignId); return CMath::nan(); } // Handle user variable or function assignment. if (!m_assignId.isEmpty()) { if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserVariable(m_assignId)) { m_error = tr("%1 is a global user definition and cannot be overridden in this session.") .arg(m_assignId); return CMath::nan(); } if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserFunction(m_assignId)) { m_error = tr("%1 is a global user definition and cannot be overridden in this session.") .arg(m_assignId); return CMath::nan(); } if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserUnit(m_assignId)) { m_error = tr("%1 is a global user definition and cannot be overridden in this session.") .arg(m_assignId); return CMath::nan(); } if (m_assignFunc) { if (hasVariable(m_assignId)) { m_error = tr("%1 is a variable name, please choose another " "or delete the variable").arg(m_assignId); return CMath::nan(); } // Check that each argument is unique and not a reserved identifier. for (int i = 0; i < m_assignArg.count() - 1; ++i) { const QString& argName = m_assignArg.at(i); if (m_assignArg.indexOf(argName, i + 1) != -1) { m_error = tr("argument %1 is used " "more than once").arg(argName); return CMath::nan(); } if (isBuiltInVariable(argName)) { m_error = tr("%1 is a reserved name, " "please choose another").arg(argName); return CMath::nan(); } } if (m_codes.isEmpty()) return CMath::nan(); UserFunction userFunction(m_assignId, m_assignArg, m_assignFuncExpr, m_assignFuncDescription); if (!m_interpretedExpression.isEmpty()) { const QString leftSide = QStringLiteral("%1(%2)=").arg( m_assignId, m_assignArg.join(";") ); QString interpretedBody = m_interpretedExpression; if (interpretedBody.startsWith(leftSide)) interpretedBody = interpretedBody.mid(leftSide.size()); else { const int assignmentPos = interpretedBody.indexOf(MathDsl::Equals); if (assignmentPos >= 0) interpretedBody = interpretedBody.mid(assignmentPos + 1); } const int commentPos = findTopLevelCommentDelimiterPos(interpretedBody); if (commentPos >= 0) interpretedBody = interpretedBody.left(commentPos).trimmed(); userFunction.setInterpretedExpression(interpretedBody); } userFunction.constants = m_constants; userFunction.identifiers = m_identifiers; userFunction.opcodes = m_codes; setUserFunction(userFunction); } else if (m_assignUnit) { if (s_isBuiltInUnitIdentifier(m_assignId)) { m_error = tr("%1 is a built-in unit name, please choose another") .arg(m_assignId); return CMath::nan(); } if (result.isZero()) { m_error = tr("unit must not be zero"); return CMath::nan(); } UserUnit userUnit(m_assignId, result, m_assignUnitExpr, m_interpretedExpression, m_assignUnitDescription); setUserUnit(userUnit); } else { if (hasUserFunction(m_assignId)) { m_error = tr("%1 is a user function name, please choose " "another or delete the function").arg(m_assignId); return CMath::nan(); } setVariable(m_assignId, result, Variable::UserDefined, m_assignVarDescription); } } return result; } Quantity Evaluator::evalUpdateAns() { auto result = eval(); if (m_error.isEmpty() && !m_assignFunc && !m_assignUnit && !isCommentOnlyExpression(m_expression)) setVariable(QLatin1String("ans"), result, Variable::BuiltIn); return result; } void Evaluator::setVariable(const QString& id, Quantity value, Variable::Type type, const QString& description, const QString& formattedValue) { Variable variable(id, value, type, description); if (type == Variable::UserDefined) { if (!formattedValue.isEmpty()) variable.setFormattedValue(formattedValue); else variable.setFormattedValue(NumberFormatter::format(value)); } m_symbols.variables().add(variable); } Variable Evaluator::getVariable(const QString& id) const { if (id.isEmpty()) return Variable(QLatin1String(""), Quantity(0)); return m_symbols.variables().get(id); } bool Evaluator::hasVariable(const QString& id) const { if (id.isEmpty()) return false; else return m_symbols.variables().contains(id); } void Evaluator::unsetVariable(const QString& id, ForceBuiltinVariableErasure force) { if (m_symbols.variables().isBuiltIn(id) && !force) return; if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserVariable(id)) return; m_symbols.variables().remove(id); } QList Evaluator::getVariables() const { return m_symbols.variables().toList(); } QList Evaluator::getUserDefinedVariables() const { auto result = getVariables(); auto iter = result.begin(); while (iter != result.end()) { if ((*iter).type() == Variable::BuiltIn) iter = result.erase(iter); else ++iter; } return result; } QList Evaluator::getUserDefinedVariablesPlusAns() const { auto result = getUserDefinedVariables(); auto ans = getVariable(QLatin1String("ans")); if (!ans.identifier().isEmpty()) result.append(ans); return result; } void Evaluator::unsetAllUserDefinedVariables() { const QList variables = m_symbols.variables().toList(); for (const Variable& variable : variables) { if (variable.type() == Variable::BuiltIn) continue; if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserVariable(variable.identifier())) continue; m_symbols.variables().remove(variable.identifier()); } } static void replaceSuperscriptPowersWithCaretEquivalent(QString& expr) { auto isIdentifierChar = [](const QChar& ch) { return isIdentifierContinue(ch); }; auto isIdentifierStartChar = [](const QChar& ch) { return isIdentifierStart(ch); }; auto isSuperscriptPowerChar = [](const QChar& ch) { return MathDsl::isSuperscriptPowerChar(ch); }; // Convert function-call powers from "f²(x)" to "f(x)²" so later conversion // can produce the parser-friendly "f(x)^2" form. int i = 0; while (i < expr.size()) { if (!isSuperscriptPowerChar(expr.at(i))) { ++i; continue; } int superscriptEnd = i + 1; while (superscriptEnd < expr.size() && isSuperscriptPowerChar(expr.at(superscriptEnd))) ++superscriptEnd; int nameStart = i - 1; while (nameStart >= 0 && isIdentifierChar(expr.at(nameStart))) --nameStart; ++nameStart; while (nameStart < i && !isIdentifierStartChar(expr.at(nameStart))) ++nameStart; if (nameStart >= i || !isIdentifierStartChar(expr.at(nameStart))) { i = superscriptEnd; continue; } int argsStart = superscriptEnd; while (argsStart < expr.size() && expr.at(argsStart).isSpace()) ++argsStart; if (argsStart >= expr.size() || expr.at(argsStart) != MathDsl::GroupStart) { i = superscriptEnd; continue; } int depth = 0; int argsEnd = -1; for (int j = argsStart; j < expr.size(); ++j) { const QChar ch = expr.at(j); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd) { --depth; if (depth == 0) { argsEnd = j; break; } } } if (argsEnd < 0) { i = superscriptEnd; continue; } const QString superscript = expr.mid(i, superscriptEnd - i); const QString callArgs = expr.mid(argsStart, argsEnd - argsStart + 1); int trailingPos = argsEnd + 1; while (trailingPos < expr.size() && expr.at(trailingPos).isSpace()) ++trailingPos; const bool followedByAnotherSuperscript = trailingPos < expr.size() && isSuperscriptPowerChar(expr.at(trailingPos)); if (followedByAnotherSuperscript) { const QString functionName = expr.mid(nameStart, i - nameStart); const QString replacement = QStringLiteral("(%1%2%3)") .arg(functionName, callArgs, superscript); expr.replace(nameStart, argsEnd - nameStart + 1, replacement); i = nameStart + replacement.size(); } else { const QString replacement = callArgs + superscript; expr.replace(i, argsEnd - i + 1, replacement); i += replacement.size(); } } static const QRegularExpression s_superscriptPowersRE( QStringLiteral("(") + QString(MathDsl::PowNeg) + QStringLiteral(")?[") + QString(MathDsl::Pow0) + QString(MathDsl::Pow1) + QString(MathDsl::Pow2) + QString(MathDsl::Pow3) + QString(MathDsl::Pow4) + QString(MathDsl::Pow5) + QString(MathDsl::Pow6) + QString(MathDsl::Pow7) + QString(MathDsl::Pow8) + QString(MathDsl::Pow9) + QStringLiteral("]+") ); int offset = 0; while (true) { QRegularExpressionMatch match = s_superscriptPowersRE.match(expr, offset); if (!match.hasMatch()) break; QString power = match.captured(); for (int pos = power.size() - 1; pos >= 0; --pos) { const QChar c = power.at(pos); if (c == MathDsl::PowNeg) { power.replace(pos, 1, MathDsl::SubOpAl1); continue; } const QChar asciiDigit = MathDsl::superscriptDigitToAscii(c); if (!asciiDigit.isNull()) power.replace(pos, 1, asciiDigit); } bool isNegative = match.capturedStart(1) != -1; if (isNegative) power = "^(" + power + ")"; else power = "^" + power; expr.replace(match.capturedStart(), match.capturedLength(), power); offset = match.capturedStart() + power.size(); } } QString Evaluator::expandSuperscriptPowers(const QString& expr) { const int commentPos = expr.indexOf(MathDsl::CommentSep); QString expression = commentPos >= 0 ? expr.left(commentPos) : expr; replaceSuperscriptPowersWithCaretEquivalent(expression); return commentPos >= 0 ? expression + expr.mid(commentPos) : expression; } static void normalizeFunctionCaretPowers(QString& expr) { auto isIdentifierChar = [](const QChar& ch) { return isIdentifierContinue(ch); }; auto isIdentifierStartChar = [](const QChar& ch) { return isIdentifierStart(ch); }; auto parseIntegerExponentToken = [](const QString& input, int start, int* endOut) { int pos = start; bool parenthesized = false; if (pos < input.size() && input.at(pos) == MathDsl::GroupStart) { parenthesized = true; ++pos; } if (pos < input.size() && (input.at(pos) == MathDsl::AddOp || input.at(pos) == MathDsl::SubOpAl1)) ++pos; const int digitsStart = pos; while (pos < input.size() && input.at(pos).isDigit()) ++pos; if (pos == digitsStart) return false; if (parenthesized) { if (pos >= input.size() || input.at(pos) != MathDsl::GroupEnd) return false; ++pos; } *endOut = pos; return true; }; int i = 0; while (i < expr.size()) { if (!isIdentifierStartChar(expr.at(i))) { ++i; continue; } int nameEnd = i + 1; while (nameEnd < expr.size() && isIdentifierChar(expr.at(nameEnd))) ++nameEnd; int afterName = nameEnd; while (afterName < expr.size() && expr.at(afterName).isSpace()) ++afterName; if (afterName >= expr.size() || expr.at(afterName) != MathDsl::PowOp) { i = nameEnd; continue; } int expStart = afterName + 1; while (expStart < expr.size() && expr.at(expStart).isSpace()) ++expStart; int expEnd = expStart; if (!parseIntegerExponentToken(expr, expStart, &expEnd)) { i = nameEnd; continue; } int argsStart = expEnd; while (argsStart < expr.size() && expr.at(argsStart).isSpace()) ++argsStart; if (argsStart >= expr.size() || expr.at(argsStart) != MathDsl::GroupStart) { i = nameEnd; continue; } int depth = 0; int argsEnd = -1; for (int j = argsStart; j < expr.size(); ++j) { const QChar ch = expr.at(j); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd) { --depth; if (depth == 0) { argsEnd = j; break; } } } if (argsEnd < 0) { i = nameEnd; continue; } const QString callArgs = expr.mid(argsStart, argsEnd - argsStart + 1); const QString exponentToken = expr.mid(expStart, expEnd - expStart); const QString replacement = callArgs + MathDsl::PowOp + exponentToken; expr.replace(afterName, argsEnd - afterName + 1, replacement); i = i + replacement.size(); } } QList Evaluator::getUserFunctions() const { return m_symbols.functions().toList(); } QList Evaluator::getUserUnits() const { return m_symbols.units().toList(); } void Evaluator::setUserFunction(const UserFunction& f) { m_symbols.functions().add(f); } void Evaluator::unsetUserFunction(const QString& fname) { if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserFunction(fname)) return; m_symbols.functions().remove(fname); } void Evaluator::unsetAllUserFunctions() { const QList functions = m_symbols.functions().toList(); for (const UserFunction& function : functions) { if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserFunction(function.name())) continue; m_symbols.functions().remove(function.name()); } } bool Evaluator::hasUserFunction(const QString& fname) const { return !fname.isEmpty() && m_symbols.functions().contains(fname); } const UserFunction* Evaluator::getUserFunction(const QString& fname) const { return m_symbols.functions().get(fname); } QStringList Evaluator::userUnitIdentifiers() const { QStringList identifiers; const auto units = m_symbols.units().toList(); for (const UserUnit& unit : units) identifiers.append(unit.name()); identifiers.sort(); return identifiers; } QStringList Evaluator::allUnitIdentifiers() const { QStringList identifiers = builtInUnitIdentifiers(); const QStringList userUnits = userUnitIdentifiers(); for (const QString& unit : userUnits) { if (!identifiers.contains(unit)) identifiers.append(unit); } identifiers.sort(); return identifiers; } void Evaluator::setUserUnit(const UserUnit& unit) { m_symbols.units().add(unit); } void Evaluator::unsetUserUnit(const QString& name) { if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserUnit(name)) return; m_symbols.units().remove(name); } void Evaluator::unsetAllUserUnits() { const QList units = m_symbols.units().toList(); for (const UserUnit& unit : units) { if (!m_allowGlobalUserDefinitionsOverride && GlobalSymbols::instance().isUserUnit(unit.name())) continue; m_symbols.units().remove(unit.name()); } } bool Evaluator::hasUserUnit(const QString& name) const { return !name.isEmpty() && m_symbols.units().contains(name); } void Evaluator::setAllowGlobalUserDefinitionsOverride(bool allow) { // See m_allowGlobalUserDefinitionsOverride in evaluator.h for intent. // Only the User Definitions import/apply path should enable this. m_allowGlobalUserDefinitionsOverride = allow; } void Evaluator::clearGlobalUserDefinitionRegistry() { GlobalSymbols::instance().clearUserDefinitionRegistry(); } void Evaluator::copySymbolContextFrom(const Evaluator& other) { m_symbols = other.m_symbols; } void Evaluator::registerGlobalUserVariable(const QString& id) { GlobalSymbols::instance().registerUserVariable(id); } void Evaluator::registerGlobalUserFunction(const QString& name) { GlobalSymbols::instance().registerUserFunction(name); } void Evaluator::registerGlobalUserUnit(const QString& name) { GlobalSymbols::instance().registerUserUnit(name); } bool Evaluator::isGlobalUserVariable(const QString& id) const { return GlobalSymbols::instance().isUserVariable(id); } bool Evaluator::isGlobalUserFunction(const QString& name) const { return GlobalSymbols::instance().isUserFunction(name); } bool Evaluator::isGlobalUserUnit(const QString& name) const { return GlobalSymbols::instance().isUserUnit(name); } const UserUnit* Evaluator::getUserUnit(const QString& name) const { return m_symbols.units().get(name); } bool Evaluator::tryGetAnyUnitQuantity(const QString& identifier, Quantity* valueOut) const { if (s_tryGetBuiltInUnitQuantity(identifier, valueOut)) return true; const UserUnit* unit = getUserUnit(identifier); if (!unit) return false; if (valueOut) *valueOut = unit->value(); return true; } QString Evaluator::autoFix(const QString& expr) { QString result; // Only expression text needs character cleanup. Preserve whitespace and // symbols inside comments just as they were entered. const int commentPos = expr.indexOf(MathDsl::CommentSep); const QString commentText = commentPos >= 0 ? expr.mid(commentPos + 1).trimmed() : QString(); const int expressionLength = commentPos >= 0 ? commentPos : expr.length(); // Strip off all funny characters. for (int c = 0; c < expressionLength; ++c) { const QChar ch = expr.at(c); if (ch.isSpace()) { result.append(QLatin1Char(' ')); continue; } if (ch >= QChar(32)) result.append(ch); } // No extra whitespaces at the beginning and at the end. result = result.trimmed(); // Strip trailing equal sign (=). while (result.endsWith("=")) result = result.left(result.length() - 1); auto closeUnmatchedListBraces = [&]() { QString closingStack; for (int i = 0; i < result.size(); ++i) { const QChar ch = result.at(i); if (ch == MathDsl::ListStart) { closingStack.append(MathDsl::ListEnd); continue; } if (ch != MathDsl::ListEnd || closingStack.isEmpty()) continue; closingStack.chop(1); } while (!closingStack.isEmpty()) { result.append(closingStack.at(closingStack.size() - 1)); closingStack.chop(1); } }; closeUnmatchedListBraces(); // Make committed evaluation consistent with live/selection previews by // swallowing safe trailing incomplete tokens (e.g. "1+2+"). QString withoutTrailingIncompleteToken; if (s_expressionWithoutIgnorableTrailingToken(result, &withoutTrailingIncompleteToken)) result = withoutTrailingIncompleteToken; normalizeFunctionCaretPowers(result); replaceSuperscriptPowersWithCaretEquivalent(result); // Treat an empty parenthesized exponent as a no-op, so expressions like // "3^()" keep evaluating as "3" instead of raising a syntax error. result.replace(QRegularExpression(QStringLiteral(R"(\^\s*\(\s*\))")), QString()); result = UnicodeChars::normalizeUnitSymbolAliases(result); result = UnicodeChars::normalizeRootFunctionAliasesForDisplay(result); // Normalize parenthesized unit attachment shorthand: // X([U]) -> X[U], including extra outer parentheses around [U]. auto canEndOperandBeforeParen = [](QChar ch) { return ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == MathDsl::GroupEnd || ch == MathDsl::UnitEnd || ch == MathDsl::UnitStart || ch == MathDsl::FactorOp || ch == MathDsl::PercentOp; }; auto isIdentifierChar = [](QChar ch) { return ch.isLetterOrNumber() || ch == QLatin1Char('_'); }; auto isBalancedBracketExpression = [](const QString& text) { if (text.isEmpty() || text.at(0) != MathDsl::UnitStart || text.at(text.size() - 1) != MathDsl::UnitEnd) return false; int depth = 0; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::UnitStart) { ++depth; } else if (ch == MathDsl::UnitEnd) { --depth; if (depth < 0) return false; } } return depth == 0; }; auto isWrappedByOuterParens = [](const QString& text) { if (text.size() < 2 || text.at(0) != MathDsl::GroupStart || text.at(text.size() - 1) != MathDsl::GroupEnd) return false; int depth = 0; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd) { --depth; if (depth == 0 && i != text.size() - 1) return false; if (depth < 0) return false; } } return depth == 0; }; auto normalizeParenthesizedUnitAttachment = [&]() { for (int i = 0; i < result.size(); ++i) { if (result.at(i) != MathDsl::GroupStart) continue; int prev = i - 1; while (prev >= 0 && result.at(prev).isSpace()) --prev; if (prev < 0 || !canEndOperandBeforeParen(result.at(prev))) continue; // Do not rewrite actual function-call parentheses, e.g. "sin([m])". if (isIdentifierChar(result.at(prev))) { int nameStart = prev; while (nameStart > 0 && isIdentifierChar(result.at(nameStart - 1))) --nameStart; const QString name = result.mid(nameStart, prev - nameStart + 1); if (FunctionRepo::instance()->find(name) || hasUserFunction(name)) continue; } int depth = 0; int closeParenPos = -1; for (int p = i; p < result.size(); ++p) { const QChar ch = result.at(p); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd) { --depth; if (depth == 0) { closeParenPos = p; break; } } } if (closeParenPos < 0) continue; QString inner = result.mid(i + 1, closeParenPos - i - 1).trimmed(); while (isWrappedByOuterParens(inner)) inner = inner.mid(1, inner.size() - 2).trimmed(); if (!isBalancedBracketExpression(inner)) continue; result.replace(i, closeParenPos - i + 1, inner); i += inner.size() - 1; } }; normalizeParenthesizedUnitAttachment(); // Normalize "X / N[U]" into "X / N·[U]" when X is not already a // unit-attached term in source text. This aligns editor-entered // "4/2[s]" with implicit-multiplication grouping while preserving // "6[W]/2[s]" as unit-division. auto normalizeDivisionByValueUnitAttachment = [&]() { QString rewritten; rewritten.reserve(result.size() + 8); int cursor = 0; while (cursor < result.size()) { if (result.at(cursor) != MathDsl::DivOp) { rewritten += result.at(cursor); ++cursor; continue; } int left = cursor - 1; while (left >= 0 && result.at(left).isSpace()) --left; if (left >= 0 && result.at(left) == MathDsl::UnitEnd) { rewritten += result.at(cursor); ++cursor; continue; } int rhs = cursor + 1; while (rhs < result.size() && result.at(rhs).isSpace()) ++rhs; if (rhs < result.size() && (MathDsl::isAdditionOperator(result.at(rhs)) || MathDsl::isSubtractionOperator(result.at(rhs)))) { ++rhs; } bool hasDigits = false; while (rhs < result.size() && result.at(rhs).isDigit()) { ++rhs; hasDigits = true; } if (rhs < result.size() && (result.at(rhs) == MathDsl::DotSep || result.at(rhs) == MathDsl::CommaSep)) { ++rhs; while (rhs < result.size() && result.at(rhs).isDigit()) { ++rhs; hasDigits = true; } } if (!hasDigits) { rewritten += result.at(cursor); ++cursor; continue; } int unitStart = rhs; while (unitStart < result.size() && result.at(unitStart).isSpace()) ++unitStart; if (unitStart >= result.size() || result.at(unitStart) != MathDsl::UnitStart) { rewritten += result.at(cursor); ++cursor; continue; } int depth = 0; int unitEnd = -1; for (int i = unitStart; i < result.size(); ++i) { const QChar ch = result.at(i); if (ch == MathDsl::UnitStart) { ++depth; } else if (ch == MathDsl::UnitEnd) { --depth; if (depth == 0) { unitEnd = i; break; } if (depth < 0) break; } } if (unitEnd < 0) { rewritten += result.at(cursor); ++cursor; continue; } rewritten += result.mid(cursor, unitStart - cursor); rewritten += MathDsl::MulDotOp; rewritten += result.mid(unitStart, unitEnd - unitStart + 1); cursor = unitEnd + 1; } result = rewritten; }; normalizeDivisionByValueUnitAttachment(); // Normalize symbolic multiplication to a compact "·" form. // Examples: // "2×pi" -> "2·pi" // "2 × pi pi" -> "2·pi·pi" { const QString dotOperator(MathDsl::MulDotOp); const Tokens tokens = Evaluator::scan(result); for (int i = tokens.count() - 2; i >= 1; --i) { const Token& op = tokens.at(i); if (op.asOperator() != Token::Multiplication) continue; const Token& left = tokens.at(i - 1); const Token& right = tokens.at(i + 1); const bool leftLooksMultiplicativeOperand = left.isIdentifier() || left.isUnitIdentifier() || left.isNumber() || left.asOperator() == Token::AssociationEnd || left.asOperator() == Token::Factorial || left.asOperator() == Token::Percent; const bool rightLooksMultiplicativeOperand = right.isIdentifier() || right.isUnitIdentifier() || right.isNumber() || right.asOperator() == Token::AssociationStart; if (!leftLooksMultiplicativeOperand || !rightLooksMultiplicativeOperand) continue; // Keep explicit multiplication sign for pure number×number. if (left.isNumber() && right.isNumber()) continue; result.replace(op.pos(), op.size(), dotOperator); } // Accept ASCII 'u' as a typing-friendly micro prefix for units: // normalize identifiers to 'µ*' only inside explicit unit brackets. for (int i = tokens.count() - 1; i >= 0; --i) { const Token& token = tokens.at(i); if (!token.isUnitIdentifier()) continue; const QString sourceText = result.mid(token.pos(), token.size()).trimmed(); if (!sourceText.startsWith(QLatin1Char('u')) || sourceText.size() <= 1) continue; const QString normalizedText = token.text(); if (!normalizedText.startsWith(UnicodeChars::MicroSign)) continue; if (!s_isBuiltInUnitIdentifier(normalizedText)) continue; result.replace(token.pos(), token.size(), normalizedText); } // Remove extra spaces around explicit dot multiplications. result.replace(QRegularExpression(QStringLiteral("\\s*%1\\s*").arg(dotOperator)), dotOperator); // Rewrite identifier adjacency to dot multiplication, except when // the left identifier is a known function (e.g. keep "sin pi"). static const QRegularExpression s_adjacentIdentifiersRE( QStringLiteral(R"(([A-Za-z_][A-Za-z_0-9]*)\s+([A-Za-z_][A-Za-z_0-9]*))") ); int offset = 0; while (true) { const QRegularExpressionMatch match = s_adjacentIdentifiersRE.match(result, offset); if (!match.hasMatch()) break; const QString left = match.captured(1); const QString right = match.captured(2); const bool keepAsUnitConversionAlias = left.compare(MathDsl::TransOpAl1, Qt::CaseInsensitive) == 0 || right.compare(MathDsl::TransOpAl1, Qt::CaseInsensitive) == 0; const bool keepAsFunctionCall = FunctionRepo::instance()->find(left) || hasUserFunction(left); if (keepAsUnitConversionAlias || keepAsFunctionCall) { offset = match.capturedStart(2); continue; } const int start = match.capturedStart(); result.replace(start, match.capturedLength(), left + dotOperator + right); offset = start + left.length() + 1 + right.length(); } } // Rewrite common shift-vs-add/sub ambiguity: // "a< "(a << b) + c" and "a>>b-c" -> "(a >> b) - c". // This targets simple three-operand forms only. while (true) { const Tokens tokens = Evaluator::scan(result); bool updated = false; for (int i = 1; i + 3 < tokens.count(); ++i) { const Token& left = tokens.at(i - 1); const Token& shift = tokens.at(i); const Token& right = tokens.at(i + 1); const Token& addSub = tokens.at(i + 2); const Token& tail = tokens.at(i + 3); const Token::Operator shiftOp = shift.asOperator(); if (shiftOp != Token::ArithmeticLeftShift && shiftOp != Token::ArithmeticRightShift) { continue; } if (!left.isOperand() || !right.isOperand() || !tail.isOperand()) continue; if (addSub.asOperator() != Token::Addition && addSub.asOperator() != Token::Subtraction) { continue; } const int startPos = left.pos(); const int endPos = tail.pos() + tail.size(); const QString leftText = result.mid(left.pos(), left.size()).trimmed(); const QString shiftText = shiftOp == Token::ArithmeticLeftShift ? QStringLiteral("<<") : QStringLiteral(">>"); const QString rightText = result.mid(right.pos(), right.size()).trimmed(); const QString addSubText = result.mid(addSub.pos(), addSub.size()).trimmed(); const QString tailText = result.mid(tail.pos(), tail.size()).trimmed(); const QString replacement = QStringLiteral("(%1 %2 %3) %4 %5") .arg(leftText, shiftText, rightText, addSubText, tailText); result.replace(startPos, endPos - startPos, replacement); updated = true; break; } if (!updated) break; } // Automagically close unmatched grouping delimiters. // // We do this for both parentheses and unit brackets to mirror the tolerant // typing behavior used elsewhere in the editor (e.g. "sin(1" -> "sin(1)", // "2[m3" -> "2[m3]"). The stack keeps expected closing delimiters in // nesting order, so mixed groups close correctly ("([..." -> "...])"). // The fix is only applied when scanning reaches the end of the expression, // avoiding synthetic closers when parsing already stopped earlier. Tokens tokens = Evaluator::scan(result); if (tokens.count()) { QString closingStack; for (int i = 0; i < tokens.count(); ++i) { if (tokens.at(i).asOperator() == Token::AssociationStart) { if (tokens.at(i).text() == QLatin1String("(")) closingStack.append(MathDsl::GroupEnd); else if (tokens.at(i).text() == QString(MathDsl::UnitStart)) closingStack.append(MathDsl::UnitEnd); else if (tokens.at(i).text() == QString(MathDsl::ListStart)) closingStack.append(MathDsl::ListEnd); continue; } if (tokens.at(i).asOperator() != Token::AssociationEnd) continue; if (closingStack.isEmpty()) continue; const QChar closing = tokens.at(i).text().isEmpty() ? QChar() : tokens.at(i).text().at(0); if (closingStack.at(closingStack.size() - 1) == closing) closingStack.chop(1); } // If the scanner stops in the middle, do not bother to apply fix. const Token& lastToken = tokens.at(tokens.count() - 1); if (lastToken.pos() + lastToken.size() >= result.length()) while (!closingStack.isEmpty()) { result.append(closingStack.at(closingStack.size() - 1)); closingStack.chop(1); } } normalizeParenthesizedUnitAttachment(); // Special treatment for simple function // e.g. "cos" is regarded as "cos(ans)". if (!result.isEmpty()) { Tokens functionTokens = Evaluator::scan(result); if (functionTokens.count() == 1 && functionTokens.at(0).isIdentifier() && FunctionRepo::instance()->find(functionTokens.at(0).text())) { result.append("(ans)"); } } if (commentPos >= 0) { result += QLatin1String(" ?"); if (!commentText.isEmpty()) result += QLatin1String(" ") + commentText; } return result; } QString Evaluator::dump() { QString result; int c; if (m_dirty) { Tokens tokens = scan(m_expression); compile(tokens); } result = QString("Expression: [%1]\n").arg(m_expression); result.append(" Constants:\n"); for (c = 0; c < m_constants.count(); ++c) { auto val = m_constants.at(c); result += QString(" #%1 = %2\n").arg(c).arg( DMath::format(val, Quantity::Format::Fixed()) ); } result.append("\n"); result.append(" Identifiers:\n"); for (c = 0; c < m_identifiers.count(); ++c) { result += QString(" #%1 = %2\n").arg(c).arg(m_identifiers.at(c)); } result.append("\n"); result.append(" Code:\n"); for (int i = 0; i < m_codes.count(); ++i) { QString code; switch (m_codes.at(i).type) { case Opcode::Load: code = QString("Load #%1").arg(m_codes.at(i).index); break; case Opcode::Ref: code = QString("Ref #%1").arg(m_codes.at(i).index); break; case Opcode::UnitRef: code = QString("UnitRef #%1").arg(m_codes.at(i).index); break; case Opcode::Function: code = QString("Function (%1)").arg(m_codes.at(i).index); break; case Opcode::List: code = QString("List (%1)").arg(m_codes.at(i).index); break; case Opcode::Add: code = "Add"; break; case Opcode::Sub: code = "Sub"; break; case Opcode::Mul: code = "Mul"; break; case Opcode::Unit: code = "Unit"; break; case Opcode::Div: code = "Div"; break; case Opcode::Phasor: code = "Phasor"; break; case Opcode::Neg: code = "Neg"; break; case Opcode::BNot: code = "BNot"; break; case Opcode::Pow: code = "Pow"; break; case Opcode::Fact: code = "Fact"; break; case Opcode::Percent: code = "Percent"; break; case Opcode::Modulo: code = "Modulo"; break; case Opcode::IntDiv: code = "IntDiv"; break; case Opcode::LSh: code = "LSh"; break; case Opcode::RSh: code = "RSh"; break; case Opcode::BAnd: code = "BAnd"; break; case Opcode::BOr: code = "BOr"; break; case Opcode::Conv: code = "Conv"; break; default: code = "Unknown"; break; } result.append(" ").append(code).append("\n"); } return result; } heldercorreia-speedcrunch-e7ca37f/src/core/evaluator.h000066400000000000000000000214321526573132500232310ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2013-2016, 2018, 2020, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_EVALUATOR_H #define CORE_EVALUATOR_H // Uncomment to trace scanning and parsing to the terminal and eval.log. // #define EVALUATOR_DEBUG #include "core/functions.h" #include "core/opcode.h" #include "core/symbolcontext.h" #include "core/variable.h" #include "core/userfunction.h" #include "core/userunit.h" #include "math/hmath.h" #include "math/cmath.h" #include "math/quantity.h" #include #include #include #include #include #include class Token { public: enum Operator { Invalid = 0, Addition, Subtraction, Multiplication, Division, IntegerDivision, Exponentiation, Super0, Super1, Super2, Super3, Super4, Super5, Super6, Super7, Super8, Super9, AssociationStart, AssociationEnd, ListSeparator, Factorial, Assignment, Modulo, Percent, ArithmeticLeftShift, ArithmeticRightShift, BitwiseLogicalNOT, BitwiseLogicalAND, BitwiseLogicalOR, Phasor, UnitConversion, Function // For managing shift/reduce conflicts. }; enum Type { stxUnknown, stxNumber, stxIdentifier, stxUnitIdentifier, stxAbstract, // isOperand stxOperator, stxOpenPar, stxClosePar, stxSep // isOperator }; static const Token null; Token(Type = stxUnknown, const QString& = QString(), int pos = -1, int size = -1); Token(const Token&); Quantity asNumber() const; Operator asOperator() const; QString description() const; bool isNumber() const { return m_type == stxNumber; } bool isOperator() const { return m_type >= stxOperator; } bool isIdentifier() const { return m_type == stxIdentifier; } bool isUnitIdentifier() const { return m_type == stxUnitIdentifier; } bool isAbstract() const { return m_type == stxAbstract; } bool isOperand() const { return isNumber() || isIdentifier() || isUnitIdentifier() || isAbstract(); } int pos() const { return m_pos; } void setPos(int pos) { m_pos = pos; } int size() const { return m_size; } void setSize(int size) { m_size = size; } QString text() const { return m_text; } Type type() const { return m_type; } int minPrecedence() const { return m_minPrecedence; } void setMinPrecedence(int value) { m_minPrecedence = value; } bool hasExplicitUnitAttachment() const { return m_explicitUnitAttachment; } void setExplicitUnitAttachment(bool value) { m_explicitUnitAttachment = value; } Token& operator=(const Token&); protected: // Start position of the text that token represents in the expression // (might include extra space characters). int m_pos; // Size of text that token represents in the expression // (might include extra space characters). int m_size; // Precedence of the operator with the lowest precedence contained // in this token. int m_minPrecedence; // Normalized version of that token text (only valid when the token // represents a single token). QString m_text; Type m_type; // True only for a value followed directly by a unit block. Grouping or // another completed operation makes its meaning as a power base explicit. bool m_explicitUnitAttachment; }; class Tokens : public QVector { public: Tokens() : QVector() , m_valid(true) { } bool valid() const { return m_valid; } void setValid(bool v) { m_valid = v; } #ifdef EVALUATOR_DEBUG void append(const Token&); #endif /* EVALUATOR_DEBUG */ protected: bool m_valid; }; class Evaluator : public QObject { Q_OBJECT using ForceBuiltinVariableErasure = bool; public: static Evaluator* instance(); Evaluator(); void reset(); static bool isSeparatorChar(const QChar&); static bool isRadixChar(const QChar&); static bool isCommentOnlyExpression(const QString&); static QString simplifyInterpretedExpression(const QString&); static QString formatInterpretedExpressionForDisplay(const QString&); static QString formatInterpretedExpressionForDisplay(const QString&, const Evaluator*); static QString formatInterpretedExpressionSimplifiedForDisplay(const QString&); static QString formatInterpretedExpressionSimplifiedForDisplay(const QString&, const Evaluator*); static QString fixNumberRadix(const QString&); static QString expandSuperscriptPowers(const QString&); static QString fixSexagesimal(const QString&, QString& unit); static QStringList builtInUnitIdentifiers(); QString autoFix(const QString&); QString dump(); QString error() const; QString interpretedExpression() const; Quantity eval(); Quantity evalNoAssign(); Quantity evalUpdateAns(); QString expression() const; bool hasImplicitMultiplication() const; bool isValid(); Tokens scan(const QString&) const; void setExpression(const QString&); Tokens tokens() const; bool isUserFunctionAssign() const; bool isUserUnitAssign() const; bool isUserVariableAssign() const; Variable getVariable(const QString&) const; QList getVariables() const; QList getUserDefinedVariables() const; QList getUserDefinedVariablesPlusAns() const; void setVariable(const QString&, Quantity, Variable::Type = Variable::UserDefined, const QString& = QString(), const QString& = QString()); void unsetVariable(const QString&, ForceBuiltinVariableErasure = false); void unsetAllUserDefinedVariables(); bool isBuiltInVariable(const QString&) const; bool hasVariable(const QString&) const; void initializeBuiltInVariables(); void initializeAngleUnits(); QList getUserFunctions() const; void setUserFunction(const UserFunction&); void unsetUserFunction(const QString&); void unsetAllUserFunctions(); bool hasUserFunction(const QString&) const; QList getUserUnits() const; QStringList userUnitIdentifiers() const; QStringList allUnitIdentifiers() const; void setUserUnit(const UserUnit&); void unsetUserUnit(const QString&); void unsetAllUserUnits(); bool hasUserUnit(const QString&) const; const UserUnit* getUserUnit(const QString&) const; void setAllowGlobalUserDefinitionsOverride(bool allow); void clearGlobalUserDefinitionRegistry(); void registerGlobalUserVariable(const QString& id); void registerGlobalUserFunction(const QString& name); void registerGlobalUserUnit(const QString& name); bool isGlobalUserVariable(const QString& id) const; bool isGlobalUserFunction(const QString& name) const; bool isGlobalUserUnit(const QString& name) const; SymbolContext& symbolContext() { return m_symbols; } const SymbolContext& symbolContext() const { return m_symbols; } void copySymbolContextFrom(const Evaluator& other); protected: void compile(const Tokens&); private: Q_DISABLE_COPY(Evaluator) bool m_dirty; QString m_error; QString m_expression; QString m_interpretedExpression; bool m_valid; QString m_assignId; bool m_assignFunc; QStringList m_assignArg; QString m_assignVarDescription; QString m_assignUnitDescription; QString m_assignFuncExpr; QString m_assignUnitExpr; QString m_assignFuncDescription; bool m_assignUnit; QVector m_codes; QVector m_constants; QStringList m_constantTexts; QStringList m_identifiers; QSet m_implicitMultiplicationOpcodeIndices; SymbolContext m_symbols; QSet m_functionsInUse; bool m_hasImplicitMultiplication; // Temporary gate used by the User Definitions dialog import/apply path. // When true, global definitions may replace previously-tagged global symbols. // Keep false for normal editor/session evaluation so globals stay immutable. bool m_allowGlobalUserDefinitionsOverride; const Quantity& checkOperatorResult(const Quantity&); static QString stringFromFunctionError(Function*); Quantity exec(const QVector& opcodes, const QVector& constants, const QStringList& identifiers); QString buildInterpretedExpressionFromOpcodes() const; Quantity execUserFunction(const UserFunction* function, QVector& arguments); const UserFunction* getUserFunction(const QString&) const; bool tryGetAnyUnitQuantity(const QString& identifier, Quantity* valueOut) const; bool isFunction(Token token) { return token.isIdentifier() && (FunctionRepo::instance()->find(token.text()) || hasUserFunction(token.text())); } }; #endif heldercorreia-speedcrunch-e7ca37f/src/core/functions.cpp000066400000000000000000002624401526573132500236000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006-2011, 2013-2019, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "core/functions.h" #include "core/mathdsl.h" #include "core/settings.h" #include "core/units.h" #include "core/unicodechars.h" #include "math/hmath.h" #include "math/cmath.h" #include "math/floatnum/floatconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static QString domainToDisplay(FunctionDomain domain) { switch (domain) { case FunctionDomain::Arithmetic: return FunctionRepo::tr("Arithmetic"); case FunctionDomain::Chemistry: return FunctionRepo::tr("Chemistry"); case FunctionDomain::Complex: return FunctionRepo::tr("Complex"); case FunctionDomain::Combinatorics: return FunctionRepo::tr("Combinatorics"); case FunctionDomain::Probability: return FunctionRepo::tr("Probability"); case FunctionDomain::Statistics: return FunctionRepo::tr("Statistics"); case FunctionDomain::Aggregation: return FunctionRepo::tr("Aggregation"); case FunctionDomain::Random: return FunctionRepo::tr("Random"); case FunctionDomain::BaseConversion: return FunctionRepo::tr("Base conversion"); case FunctionDomain::NumberFormatting: return FunctionRepo::tr("Number formatting"); case FunctionDomain::IntegerArithmetic: return FunctionRepo::tr("Integer arithmetic"); case FunctionDomain::SpecialFunctions: return FunctionRepo::tr("Special functions"); case FunctionDomain::ExponentialLogarithmic: return FunctionRepo::tr("Exponential & Logarithmic"); case FunctionDomain::AngleConversion: return FunctionRepo::tr("Angle conversion"); case FunctionDomain::Trigonometry: return FunctionRepo::tr("Trigonometry"); case FunctionDomain::Bitwise: return FunctionRepo::tr("Bitwise"); case FunctionDomain::FloatingPoint: return FunctionRepo::tr("Floating point"); case FunctionDomain::DateTime: return FunctionRepo::tr("Date & Time"); case FunctionDomain::LinearAlgebra: return FunctionRepo::tr("Linear algebra"); } return QString(); } #define FUNCTION_INSERT(DOMAIN, ID) insert(new Function(#ID, function_ ## ID, DOMAIN, this)) #define FUNCTION_USAGE(ID, USAGE) find(#ID)->setUsage(QString::fromLatin1(USAGE)); #define FUNCTION_USAGE_TR(ID, USAGE) find(#ID)->setUsage(USAGE); #define FUNCTION_NAME(ID, NAME) find(#ID)->setName(NAME) enum class StatisticalNormalization { Population, Sample }; enum class ScalarRoundingMode { HalfAwayFromZero, HalfEven, TowardZero, TowardPositiveInfinity, TowardNegativeInfinity }; #define ENSURE_MINIMUM_ARGUMENT_COUNT(i) \ if (args.count() < i) { \ f->setError(InvalidParamCount); \ return CMath::nan(InvalidParamCount); \ } #define ENSURE_ARGUMENT_COUNT(i) \ if (args.count() != (i)) { \ f->setError(InvalidParamCount); \ return CMath::nan(InvalidParamCount); \ } #define ENSURE_EITHER_ARGUMENT_COUNT(i, j) \ if (args.count() != (i) && args.count() != (j)) { \ f->setError(InvalidParamCount); \ return CMath::nan(InvalidParamCount); \ } #define ENSURE_SAME_DIMENSION() \ for(int i=0; isetError(OutOfDomain); \ return CMath::nan(); \ } #define ENSURE_REAL_ARGUMENTS() \ for (int i = 0; i < args.count(); i++) { \ ENSURE_REAL_ARGUMENT(i); \ } #define CONVERT_ARGUMENT_ANGLE(angle) \ { \ const bool convertedExplicitAngleUnit = Units::tryConvertExplicitAngleToRadians(&(angle)); \ if (!convertedExplicitAngleUnit && Settings::instance()->angleUnit == 'd') { \ if (angle.isReal()) \ angle = DMath::deg2rad(angle); \ else { \ f->setError(OutOfDomain); \ return DMath::nan(); \ } \ } \ else if (!convertedExplicitAngleUnit && Settings::instance()->angleUnit == 'g') { \ if (angle.isReal()) \ angle = DMath::gon2rad(angle); \ else { \ f->setError(OutOfDomain); \ return DMath::nan(); \ } \ } \ else if (!convertedExplicitAngleUnit && (Settings::instance()->angleUnit == 't' \ || Settings::instance()->angleUnit == 'v')) { \ if (angle.isReal()) \ angle *= Quantity(2) * DMath::pi(); \ else { \ f->setError(OutOfDomain); \ return DMath::nan(); \ } \ } \ } #define CONVERT_RESULT_ANGLE(result) \ if (Settings::instance()->angleUnit == 'd') \ result = DMath::rad2deg(result); \ else if (Settings::instance()->angleUnit == 'g') \ result = DMath::rad2gon(result); \ else if (Settings::instance()->angleUnit == 't' \ || Settings::instance()->angleUnit == 'v') \ result /= Quantity(2) * DMath::pi(); static FunctionRepo* s_FunctionRepoInstance = 0; static const int s_defaultRandomDigits = 16; // Internal sentinel used to request per-expression rational display in NumberFormatter. // This piggybacks on precision because Quantity::Format has no dedicated rational-override flag. static const int s_forcedRationalPrecision = -999; // FIXME: destructor seems not to be called static void s_deleteFunctions() { delete s_FunctionRepoInstance; } // Shared pseudo-random engine for random built-ins. static std::mt19937_64& s_randomEngine() { static std::mt19937_64 engine([] { const auto now = static_cast(QDateTime::currentMSecsSinceEpoch()); std::seed_seq seed{ static_cast(std::random_device{}()), static_cast(std::random_device{}()), static_cast(now & 0xFFFFFFFFULL), static_cast((now >> 32) & 0xFFFFFFFFULL) }; return std::mt19937_64(seed); }()); return engine; } static Quantity s_randomFraction(int digits) { std::uniform_int_distribution digitDistribution(0, 9); std::string literal = "0."; literal.reserve(2 + std::max(0, digits)); for (int i = 0; i < digits; ++i) { literal.push_back(static_cast('0' + digitDistribution(s_randomEngine()))); } return Quantity(HNumber(literal.c_str())); } static Quantity s_nonDecimalPad(Function* f, const Function::ArgumentList& args, Quantity::Format format) { ENSURE_EITHER_ARGUMENT_COUNT(1, 2); const Quantity value = args.at(0); if (!value.isInteger()) { f->setError(OutOfDomain); return DMath::nan(); } Quantity::Format padding = Quantity::Format::PadToByteBoundary(); if (args.count() == 2) { const Quantity bitsArg = args.at(1); if (!bitsArg.isInteger()) { f->setError(OutOfDomain); return DMath::nan(); } const int bits = bitsArg.numericValue().toInt(); if (bits <= 0) { f->setError(OutOfDomain); return DMath::nan(); } padding = Quantity::Format::PadBits(bits); } return Quantity(value).setFormat(format + padding + value.format()); } static bool s_tryExtractForcedExponent(const Quantity& value, int* out) { if (!value.isReal() || !value.isDimensionless()) return false; const HNumber numeric = value.numericValue().real; if (numeric.isZero()) { *out = 0; return true; } if (numeric.isPositive()) { const QString scientific = HMath::format( numeric, HNumber::Format::Scientific() + HNumber::Format::Decimal() + HNumber::Format::Precision(-1)); const int exponentPos = scientific.indexOf(QLatin1Char('e')); if (exponentPos > 0 && scientific.left(exponentPos) == QStringLiteral("1")) { bool ok = false; const int prefixExponent = scientific.mid(exponentPos + 1).toInt(&ok); if (ok && prefixExponent % 3 == 0) { *out = prefixExponent; return true; } } } if (!value.isInteger()) return false; const HNumber intMax(std::numeric_limits::max()); const HNumber intMin(std::numeric_limits::min()); if (numeric > intMax || numeric < intMin) return false; const int exponent = numeric.toInt(); if (exponent % 3 != 0) return false; *out = exponent; return true; } static Function::ArgumentList s_collectionElementsOrArgs(const Function::ArgumentList& args) { if (args.count() == 1 && args.at(0).isCollection()) return args.at(0).elements(); return args; } static bool s_ensureOneCollectionArg(Function* f, const Function::ArgumentList& args, Quantity* collection) { if (args.count() != 1 || !args.at(0).isCollection()) { f->setError(OutOfDomain); return false; } *collection = args.at(0); return true; } static bool s_ensureMatrixArg(Function* f, const Function::ArgumentList& args, Quantity* matrix) { if (!s_ensureOneCollectionArg(f, args, matrix) || !matrix->isMatrix()) { f->setError(OutOfDomain); return false; } return true; } static Quantity s_makeScalarList(const QVector& elements) { return Quantity::list(elements); } static Quantity s_makeMatrix(const QVector>& rows) { return Quantity::matrix(rows); } Quantity Function::exec(const Function::ArgumentList& args) { if (!m_ptr) return CMath::nan(); setError(Success); Quantity result = (*m_ptr)(this, args); if(result.error()) setError(result.error()); return result; } Quantity function_abs(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::abs(args.at(0)); } Quantity function_average(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ const Function::ArgumentList values = s_collectionElementsOrArgs(args); if (values.count() < 1 || (!args.at(0).isCollection() && values.count() < 2)) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } return std::accumulate(values.begin()+1, values.end(), *values.begin()) / Quantity(values.count()); } Quantity function_mean(Function* f, const Function::ArgumentList& args) { return function_average(f, args); } Quantity function_median(Function* f, const Function::ArgumentList& args); Quantity function_list(Function* f, const Function::ArgumentList& args) { ENSURE_MINIMUM_ARGUMENT_COUNT(1); Quantity result = Quantity::list(args); if (result.isNan()) { f->setError(result.error() == DimensionMismatch ? DimensionMismatch : OutOfDomain); return result; } return result; } Quantity function_absdev(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ const Function::ArgumentList values = s_collectionElementsOrArgs(args); if (values.count() < 1 || (!args.at(0).isCollection() && values.count() < 2)) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } Quantity mean = function_average(f, values); if (mean.isNan()) return mean; // pass the error along Quantity acc = 0; for (int i = 0; i < values.count(); ++i) acc += DMath::abs(values.at(i) - mean); return acc / Quantity(values.count()); } Quantity function_mad(Function* f, const Function::ArgumentList& args) { const Function::ArgumentList values = s_collectionElementsOrArgs(args); if (values.count() < 1 || (!args.at(0).isCollection() && values.count() < 2)) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } const Quantity median = function_median(f, values); if (median.isNan()) return median; Function::ArgumentList deviations; deviations.reserve(values.count()); for (const Quantity& value : values) deviations.append(DMath::abs(value - median)); return function_median(f, deviations); } Quantity function_int(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::integer(args[0]); } Quantity function_frac(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::frac(args[0]); } Quantity function_gcd(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); for (int i = 0; i < args.count(); ++i) if (!args[i].isInteger()) { f->setError(OutOfDomain); return DMath::nan(); } return std::accumulate(args.begin() + 1, args.end(), args.at(0), DMath::gcd); } Quantity function_lcm(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); for (int i = 0; i < args.count(); ++i) if (!args[i].isInteger()) { f->setError(OutOfDomain); return DMath::nan(); } return std::accumulate(args.begin() + 1, args.end(), args.at(0), DMath::lcm); } static Quantity s_roundScalar(Function* f, const Function::ArgumentList& args, ScalarRoundingMode mode) { const bool acceptsPrecision = mode == ScalarRoundingMode::HalfAwayFromZero || mode == ScalarRoundingMode::HalfEven || mode == ScalarRoundingMode::TowardZero; if (acceptsPrecision) { ENSURE_EITHER_ARGUMENT_COUNT(1, 2); } else { ENSURE_ARGUMENT_COUNT(1); } Quantity num = args.at(0); int prec = 0; if (args.count() == 2) { Quantity argprec = args.at(1); if (argprec != 0) { if (!argprec.isInteger()) { f->setError(OutOfDomain); return DMath::nan(); } prec = argprec.numericValue().toInt(); if (prec == 0) return num; // The second parameter exceeds the integer limits. if (argprec < 0) { Quantity result(0); result.copyDimension(num); if (num.hasUnit()) result.setDisplayUnit(num.unit(), num.unitName()); return result; } } } if (!num.isReal()) { f->setError(OutOfDomain); return DMath::nan(); } const CNumber unitValue = num.unit(); const CNumber scaledValue = num.hasUnit() ? num.numericValue() / unitValue : num.numericValue(); if (!scaledValue.isNearReal()) { f->setError(OutOfDomain); return DMath::nan(); } HNumber rounded; switch (mode) { case ScalarRoundingMode::HalfAwayFromZero: { const HNumber scale = HMath::raise(HNumber(10), prec); const HNumber scaled = scaledValue.real * scale; const HNumber absRounded = HMath::floor(HMath::abs(scaled) + HNumber("0.5")); rounded = (scaled.isNegative() ? -absRounded : absRounded) / scale; break; } case ScalarRoundingMode::HalfEven: rounded = HMath::round(scaledValue.real, prec); break; case ScalarRoundingMode::TowardZero: rounded = HMath::trunc(scaledValue.real, prec); break; case ScalarRoundingMode::TowardPositiveInfinity: rounded = HMath::ceil(scaledValue.real); break; case ScalarRoundingMode::TowardNegativeInfinity: default: rounded = HMath::floor(scaledValue.real); break; } Quantity result(num.hasUnit() ? CNumber(rounded) * unitValue : CNumber(rounded)); result.copyDimension(num); if (num.hasUnit()) result.setDisplayUnit(unitValue, num.unitName()); return result; } Quantity function_trunc(Function* f, const Function::ArgumentList& args) { return s_roundScalar(f, args, ScalarRoundingMode::TowardZero); } Quantity function_floor(Function* f, const Function::ArgumentList& args) { return s_roundScalar(f, args, ScalarRoundingMode::TowardNegativeInfinity); } Quantity function_ceil(Function* f, const Function::ArgumentList& args) { return s_roundScalar(f, args, ScalarRoundingMode::TowardPositiveInfinity); } Quantity function_round(Function* f, const Function::ArgumentList& args) { return s_roundScalar(f, args, ScalarRoundingMode::HalfAwayFromZero); } Quantity function_roundeven(Function* f, const Function::ArgumentList& args) { return s_roundScalar(f, args, ScalarRoundingMode::HalfEven); } Quantity function_sqrt(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::sqrt(args[0]); } static Quantity s_variance(Function* f, const Function::ArgumentList& args, StatisticalNormalization normalization) { const Function::ArgumentList values = s_collectionElementsOrArgs(args); const int divisor = normalization == StatisticalNormalization::Sample ? values.count() - 1 : values.count(); if (divisor <= 0) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } Quantity mean = function_average(f, values); if (mean.isNan()) return mean; Quantity acc(DMath::real(values[0] - mean)*DMath::real(values[0] - mean) + DMath::imag(values[0] - mean)*DMath::imag(values[0] - mean)); for (int i = 1; i < values.count(); ++i) { Quantity q(values[i] - mean); acc += DMath::real(q)*DMath::real(q) + DMath::imag(q)*DMath::imag(q); } return acc / Quantity(divisor); } Quantity function_varp(Function* f, const Function::ArgumentList& args) { return s_variance(f, args, StatisticalNormalization::Population); } Quantity function_vars(Function* f, const Function::ArgumentList& args) { return s_variance(f, args, StatisticalNormalization::Sample); } static Quantity s_stdev(Function* f, const Function::ArgumentList& args, StatisticalNormalization normalization) { /* TODO : complex mode switch for this function */ const Quantity variance = s_variance(f, args, normalization); return variance.isNan() ? variance : DMath::sqrt(variance); } Quantity function_stdevp(Function* f, const Function::ArgumentList& args) { return s_stdev(f, args, StatisticalNormalization::Population); } Quantity function_stdevs(Function* f, const Function::ArgumentList& args) { return s_stdev(f, args, StatisticalNormalization::Sample); } Quantity function_cbrt(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::cbrt(args[0]); } Quantity function_root(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(2); return DMath::root(args[0], args[1]); } Quantity function_exp(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::exp(args[0]); } Quantity function_ln(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::ln(args[0]); } Quantity function_lg(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::lg(args[0]); } Quantity function_lb(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::lb(args[0]); } Quantity function_log10(Function* f, const Function::ArgumentList& args) { return function_lg(f, args); } Quantity function_log2(Function* f, const Function::ArgumentList& args) { return function_lb(f, args); } Quantity function_log(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::log(args.at(0), args.at(1)); } Quantity function_real(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::real(args.at(0)); } Quantity function_numval(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); const Quantity value = args.at(0); if (!value.hasUnit()) return Quantity(value.numericValue()); if (value.unitName().isEmpty()) return Quantity(value.numericValue()); return Quantity(value.numericValue() / value.unit()); } Quantity function_imag(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::imag(args.at(0)); } Quantity function_conj(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::conj(args.at(0)); } Quantity function_phase(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = DMath::phase(args.at(0)); CONVERT_RESULT_ANGLE(angle); return angle; } Quantity function_sin(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); Quantity result = DMath::sin(angle); // Trig outputs are always pure scalars; explicit input-angle display units // (e.g. °/rad) must not leak into the function result. result.stripUnits(); return result; } Quantity function_cos(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); Quantity result = DMath::cos(angle); // Trig outputs are always pure scalars; explicit input-angle display units // (e.g. °/rad) must not leak into the function result. result.stripUnits(); return result; } Quantity function_cis(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); Quantity result = DMath::cos(angle) + (DMath::i() * DMath::sin(angle)); result.stripUnits(); return result; } Quantity function_tan(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); Quantity result = DMath::tan(angle); // Trig outputs are always pure scalars; explicit input-angle display units // (e.g. °/rad) must not leak into the function result. result.stripUnits(); return result; } Quantity function_cot(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); Quantity result = DMath::cot(angle); // Trig outputs are always pure scalars; explicit input-angle display units // (e.g. °/rad) must not leak into the function result. result.stripUnits(); return result; } Quantity function_sec(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); Quantity result = DMath::sec(angle); // Trig outputs are always pure scalars; explicit input-angle display units // (e.g. °/rad) must not leak into the function result. result.stripUnits(); return result; } Quantity function_csc(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); Quantity result = DMath::csc(angle); // Trig outputs are always pure scalars; explicit input-angle display units // (e.g. °/rad) must not leak into the function result. result.stripUnits(); return result; } Quantity function_arcsin(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity result; result = DMath::arcsin(args.at(0)); CONVERT_RESULT_ANGLE(result); return result; } Quantity function_arccos(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity result; result = DMath::arccos(args.at(0)); CONVERT_RESULT_ANGLE(result); return result; } Quantity function_arctan(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); Quantity result; result = DMath::arctan(args.at(0)); CONVERT_RESULT_ANGLE(result); return result; } Quantity function_arctan2(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(2); Quantity result; result = DMath::arctan2(args.at(0), args.at(1)); CONVERT_RESULT_ANGLE(result); return result; } Quantity function_sinh(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::sinh(args[0]); } Quantity function_cosh(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::cosh(args[0]); } Quantity function_tanh(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::tanh(args[0]); } Quantity function_arsinh(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::arsinh(args[0]); } Quantity function_arcosh(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::arcosh(args[0]); } Quantity function_artanh(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::artanh(args[0]); } Quantity function_erf(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::erf(args[0]); } Quantity function_erfc(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::erfc(args[0]); } Quantity function_gamma(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::gamma(args[0]); } Quantity function_lngamma(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); ENSURE_REAL_ARGUMENT(0); return DMath::lnGamma(args[0]); } Quantity function_rand(Function* f, const Function::ArgumentList& args) { ENSURE_EITHER_ARGUMENT_COUNT(0, 1); int digits = s_defaultRandomDigits; if (args.count() == 1) { if (args.at(0).isNan() && args.at(0).error() == NoOperand) { return s_randomFraction(digits); } if (!args.at(0).isInteger() || args.at(0) < Quantity(0)) { f->setError(OutOfDomain); return DMath::nan(OutOfDomain); } if (args.at(0) > Quantity(DECPRECISION)) { f->setError(InvalidPrecision); return DMath::nan(InvalidPrecision); } digits = args.at(0).numericValue().toInt(); } return s_randomFraction(digits); } Quantity function_randint(Function* f, const Function::ArgumentList& args) { ENSURE_EITHER_ARGUMENT_COUNT(1, 2); for (int i = 0; i < args.count(); ++i) { if (!args.at(i).isInteger()) { f->setError(OutOfDomain); return DMath::nan(OutOfDomain); } } Quantity lower = Quantity(0); Quantity upper = args.at(0); if (args.count() == 2) { lower = std::min(args.at(0), args.at(1)); upper = std::max(args.at(0), args.at(1)); } else if (upper < Quantity(0)) { lower = upper; upper = Quantity(0); } const Quantity span = (upper - lower) + Quantity(1); if (span.isNan()) { return span; } const Quantity offset = DMath::floor(s_randomFraction(DECPRECISION) * span); return lower + offset; } Quantity function_sgn(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::sgn(args[0]); } Quantity function_ncr(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::nCr(args.at(0), args.at(1)); } Quantity function_npr(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::nPr(args.at(0), args.at(1)); } Quantity function_degrees(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::rad2deg(args[0]); } Quantity function_radians(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::deg2rad(args[0]); } Quantity function_gradians(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return DMath::rad2gon(args[0]); } Quantity function_turns(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return args[0] / (Quantity(2) * DMath::pi()); } Quantity function_max(Function* f, const Function::ArgumentList& args) { const Function::ArgumentList values = s_collectionElementsOrArgs(args); if (values.count() < 1 || (!args.at(0).isCollection() && values.count() < 2)) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } for (const Quantity& value : values) { if (!value.isReal()) { f->setError(OutOfDomain); return CMath::nan(); } if (!value.sameDimension(values.at(0))) return DMath::nan(InvalidDimension); } return *std::max_element(values.begin(), values.end()); } Quantity function_median(Function* f, const Function::ArgumentList& args) { const Function::ArgumentList values = s_collectionElementsOrArgs(args); if (values.count() < 1 || (!args.at(0).isCollection() && values.count() < 2)) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } for (const Quantity& value : values) { if (!value.isReal()) { f->setError(OutOfDomain); return CMath::nan(); } if (!value.sameDimension(values.at(0))) return DMath::nan(InvalidDimension); } Function::ArgumentList sortedArgs = values; std::sort(sortedArgs.begin(), sortedArgs.end()); if ((values.count() & 1) == 1) return sortedArgs.at((values.count() - 1) / 2); const int centerLeft = values.count() / 2 - 1; return (sortedArgs.at(centerLeft) + sortedArgs.at(centerLeft + 1)) / Quantity(2); } Quantity function_min(Function* f, const Function::ArgumentList& args) { const Function::ArgumentList values = s_collectionElementsOrArgs(args); if (values.count() < 1 || (!args.at(0).isCollection() && values.count() < 2)) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } for (const Quantity& value : values) { if (!value.isReal()) { f->setError(OutOfDomain); return CMath::nan(); } if (!value.sameDimension(values.at(0))) return DMath::nan(InvalidDimension); } return *std::min_element(values.begin(), values.end()); } Quantity function_sum(Function* f, const Function::ArgumentList& args) { const Function::ArgumentList values = s_collectionElementsOrArgs(args); if (values.count() < 1 || (!args.at(0).isCollection() && values.count() < 2)) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } return std::accumulate(values.begin(), values.end(), Quantity(0)); } Quantity function_count(Function* f, const Function::ArgumentList& args) { if (args.count() == 1 && args.at(0).isCollection()) return Quantity(args.at(0).elementCount()); ENSURE_MINIMUM_ARGUMENT_COUNT(1); return Quantity(args.count()); } Quantity function_flatten(Function* f, const Function::ArgumentList& args) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix)) return CMath::nan(); return s_makeScalarList(matrix.elements()); } Quantity function_rows(Function* f, const Function::ArgumentList& args) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix)) return CMath::nan(); return Quantity(matrix.rows()); } Quantity function_cols(Function* f, const Function::ArgumentList& args) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix)) return CMath::nan(); return Quantity(matrix.columns()); } Quantity function_shape(Function* f, const Function::ArgumentList& args) { Quantity value; if (!s_ensureOneCollectionArg(f, args, &value)) return CMath::nan(); QVector dims; dims.append(Quantity(value.isList() ? value.columns() : value.rows())); if (value.isMatrix()) dims.append(Quantity(value.columns())); return s_makeScalarList(dims); } Quantity function_transpose(Function* f, const Function::ArgumentList& args) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix)) return CMath::nan(); QVector> rows; for (int c = 0; c < matrix.columns(); ++c) { QVector row; for (int r = 0; r < matrix.rows(); ++r) row.append(matrix.matrix().at(r).at(c)); rows.append(row); } return s_makeMatrix(rows); } Quantity function_dot(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(2); if (!args.at(0).isList() || !args.at(1).isList() || args.at(0).columns() != args.at(1).columns()) { f->setError(OutOfDomain); return CMath::nan(); } Quantity result(0); const QVector left = args.at(0).elements(); const QVector right = args.at(1).elements(); for (int i = 0; i < left.size(); ++i) result += left.at(i) * right.at(i); return result; } Quantity function_cross(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(2); if (!args.at(0).isList() || !args.at(1).isList() || args.at(0).columns() != 3 || args.at(1).columns() != 3) { f->setError(OutOfDomain); return CMath::nan(); } const QVector a = args.at(0).elements(); const QVector b = args.at(1).elements(); QVector result; result << (a.at(1) * b.at(2) - a.at(2) * b.at(1)); result << (a.at(2) * b.at(0) - a.at(0) * b.at(2)); result << (a.at(0) * b.at(1) - a.at(1) * b.at(0)); return s_makeScalarList(result); } Quantity function_norm(Function* f, const Function::ArgumentList& args) { Quantity value; if (!s_ensureOneCollectionArg(f, args, &value)) return CMath::nan(); Quantity sumSquares(0); for (const Quantity& element : value.elements()) sumSquares += element * element; return DMath::sqrt(sumSquares); } Quantity function_trace(Function* f, const Function::ArgumentList& args) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix) || matrix.rows() != matrix.columns()) { f->setError(OutOfDomain); return CMath::nan(); } Quantity result(0); const auto rows = matrix.matrix(); for (int i = 0; i < matrix.rows(); ++i) result += rows.at(i).at(i); return result; } Quantity function_det(Function* f, const Function::ArgumentList& args) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix) || matrix.rows() != matrix.columns()) { f->setError(OutOfDomain); return CMath::nan(); } QVector> a = matrix.matrix(); const int n = matrix.rows(); Quantity det(1); int sign = 1; for (int i = 0; i < n; ++i) { int pivot = i; while (pivot < n && a.at(pivot).at(i).isZero()) ++pivot; if (pivot == n) return Quantity(0); if (pivot != i) { std::swap(a[pivot], a[i]); sign = -sign; } const Quantity pivotValue = a.at(i).at(i); det *= pivotValue; for (int r = i + 1; r < n; ++r) { const Quantity factor = a.at(r).at(i) / pivotValue; for (int c = i; c < n; ++c) a[r][c] -= factor * a.at(i).at(c); } } return sign < 0 ? -det : det; } Quantity function_inv(Function* f, const Function::ArgumentList& args) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix) || matrix.rows() != matrix.columns()) { f->setError(OutOfDomain); return CMath::nan(); } QVector> a = matrix.matrix(); const int n = matrix.rows(); QVector> inv; for (int r = 0; r < n; ++r) { QVector row; for (int c = 0; c < n; ++c) row.append(Quantity(r == c ? 1 : 0)); inv.append(row); } for (int i = 0; i < n; ++i) { int pivot = i; while (pivot < n && a.at(pivot).at(i).isZero()) ++pivot; if (pivot == n) { f->setError(OutOfDomain); return CMath::nan(); } if (pivot != i) { std::swap(a[pivot], a[i]); std::swap(inv[pivot], inv[i]); } const Quantity pivotValue = a.at(i).at(i); for (int c = 0; c < n; ++c) { a[i][c] /= pivotValue; inv[i][c] /= pivotValue; } for (int r = 0; r < n; ++r) { if (r == i) continue; const Quantity factor = a.at(r).at(i); for (int c = 0; c < n; ++c) { a[r][c] -= factor * a.at(i).at(c); inv[r][c] -= factor * inv.at(i).at(c); } } } return s_makeMatrix(inv); } Quantity function_rank(Function* f, const Function::ArgumentList& args) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix)) return CMath::nan(); QVector> a = matrix.matrix(); int rank = 0; int row = 0; for (int col = 0; col < matrix.columns() && row < matrix.rows(); ++col) { int pivot = row; while (pivot < matrix.rows() && a.at(pivot).at(col).isZero()) ++pivot; if (pivot == matrix.rows()) continue; if (pivot != row) std::swap(a[pivot], a[row]); const Quantity pivotValue = a.at(row).at(col); for (int c = col; c < matrix.columns(); ++c) a[row][c] /= pivotValue; for (int r = 0; r < matrix.rows(); ++r) { if (r == row) continue; const Quantity factor = a.at(r).at(col); for (int c = col; c < matrix.columns(); ++c) a[r][c] -= factor * a.at(row).at(c); } ++rank; ++row; } return Quantity(rank); } static Quantity s_covarianceMatrix(Function* f, const Function::ArgumentList& args, bool normalize, StatisticalNormalization normalization) { Quantity matrix; if (!s_ensureMatrixArg(f, args, &matrix) || matrix.rows() < 2) { f->setError(OutOfDomain); return CMath::nan(); } const int divisor = normalization == StatisticalNormalization::Sample ? matrix.rows() - 1 : matrix.rows(); if (divisor <= 0) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } const auto data = matrix.matrix(); QVector means; for (int c = 0; c < matrix.columns(); ++c) { Quantity sum(0); for (int r = 0; r < matrix.rows(); ++r) sum += data.at(r).at(c); means.append(sum / Quantity(matrix.rows())); } QVector> covRows; for (int i = 0; i < matrix.columns(); ++i) { QVector row; for (int j = 0; j < matrix.columns(); ++j) { Quantity acc(0); for (int r = 0; r < matrix.rows(); ++r) acc += (data.at(r).at(i) - means.at(i)) * (data.at(r).at(j) - means.at(j)); row.append(acc / Quantity(divisor)); } covRows.append(row); } if (!normalize) return s_makeMatrix(covRows); QVector> corrRows; for (int i = 0; i < matrix.columns(); ++i) { QVector row; for (int j = 0; j < matrix.columns(); ++j) { const Quantity denom = DMath::sqrt(covRows.at(i).at(i) * covRows.at(j).at(j)); row.append(covRows.at(i).at(j) / denom); } corrRows.append(row); } return s_makeMatrix(corrRows); } Quantity function_covp(Function* f, const Function::ArgumentList& args) { return s_covarianceMatrix(f, args, false, StatisticalNormalization::Population); } Quantity function_covs(Function* f, const Function::ArgumentList& args) { return s_covarianceMatrix(f, args, false, StatisticalNormalization::Sample); } Quantity function_corrp(Function* f, const Function::ArgumentList& args) { return s_covarianceMatrix(f, args, true, StatisticalNormalization::Population); } Quantity function_corrs(Function* f, const Function::ArgumentList& args) { return s_covarianceMatrix(f, args, true, StatisticalNormalization::Sample); } Quantity function_summation(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(3); if (!args.at(0).isInteger() || !args.at(1).isInteger()) { f->setError(OutOfDomain); return DMath::nan(OutOfDomain); } const Quantity start = args.at(0); const Quantity end = args.at(1); const Quantity step = (start <= end) ? Quantity(1) : Quantity(-1); Quantity result(0); for (Quantity n = start; step > 0 ? (n <= end) : (n >= end); n += step) { result += args.at(2); } return result; } Quantity function_product(Function* f, const Function::ArgumentList& args) { ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(1), std::multiplies()); } Quantity function_geomean(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ const Function::ArgumentList values = s_collectionElementsOrArgs(args); if (values.count() < 1 || (!args.at(0).isCollection() && values.count() < 2)) { f->setError(InvalidParamCount); return CMath::nan(InvalidParamCount); } Quantity result = std::accumulate(values.begin(), values.end(), Quantity(1), std::multiplies()); if (result <= Quantity(0)) return DMath::nan(OutOfDomain); if (values.count() == 1) return result; if (values.count() == 2) return DMath::sqrt(result); return DMath::raise(result, Quantity(1)/Quantity(values.count())); } Quantity function_dec(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Decimal() + Quantity(args.at(0)).format()); } Quantity function_rat(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat( Quantity::Format::Decimal() + Quantity::Format::General() + Quantity::Format::Precision(s_forcedRationalPrecision) + Quantity(args.at(0)).format()); } Quantity function_hex(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Fixed() + Quantity::Format::Hexadecimal() + Quantity(args.at(0)).format()); } Quantity function_oct(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Fixed() + Quantity::Format::Octal() + Quantity(args.at(0)).format()); } Quantity function_bin(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Fixed() + Quantity::Format::Binary() + Quantity(args.at(0)).format()); } Quantity function_sci(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Scientific() + Quantity::Format::Decimal() + Quantity(args.at(0)).format()); } Quantity function_eng(Function* f, const Function::ArgumentList& args) { ENSURE_EITHER_ARGUMENT_COUNT(1, 2); Quantity::Format format = Quantity::Format::Engineering() + Quantity::Format::Decimal() + Quantity(args.at(0)).format(); if (args.count() == 2) { int forcedExponent = 0; if (!s_tryExtractForcedExponent(args.at(1), &forcedExponent)) { f->setError(OutOfDomain); return DMath::nan(); } format = format + Quantity::Format::ForcedExponent(forcedExponent); } return Quantity(args.at(0)).setFormat(format); } Quantity function_dms(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat( Quantity::Format::Sexagesimal() + Quantity::Format::Decimal() + Quantity(args.at(0)).format()); } Quantity function_binpad(Function* f, const Function::ArgumentList& args) { return s_nonDecimalPad(f, args, Quantity::Format::Fixed() + Quantity::Format::Binary()); } Quantity function_hexpad(Function* f, const Function::ArgumentList& args) { return s_nonDecimalPad(f, args, Quantity::Format::Fixed() + Quantity::Format::Hexadecimal()); } Quantity function_octpad(Function* f, const Function::ArgumentList& args) { return s_nonDecimalPad(f, args, Quantity::Format::Fixed() + Quantity::Format::Octal()); } Quantity function_rectform(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Cartesian() + Quantity(args.at(0)).format()); } Quantity function_trigform(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Trigonometric() + Quantity(args.at(0)).format()); } Quantity function_expform(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Polar() + Quantity(args.at(0)).format()); } Quantity function_cisform(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Cis() + Quantity(args.at(0)).format()); } Quantity function_phasorform(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::PolarAngle() + Quantity(args.at(0)).format()); } Quantity function_binompmf(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(3); return DMath::binomialPmf(args.at(0), args.at(1), args.at(2)); } Quantity function_binomcdf(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(3); return DMath::binomialCdf(args.at(0), args.at(1), args.at(2)); } Quantity function_binommean(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::binomialMean(args.at(0), args.at(1)); } Quantity function_binomvar(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::binomialVariance(args.at(0), args.at(1)); } Quantity function_hyperpmf(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(4); return DMath::hypergeometricPmf(args.at(0), args.at(1), args.at(2), args.at(3)); } Quantity function_hypercdf(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(4); return DMath::hypergeometricCdf(args.at(0), args.at(1), args.at(2), args.at(3)); } Quantity function_hypermean(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(3); return DMath::hypergeometricMean(args.at(0), args.at(1), args.at(2)); } Quantity function_hypervar(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(3); return DMath::hypergeometricVariance(args.at(0), args.at(1), args.at(2)); } Quantity function_poipmf(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::poissonPmf(args.at(0), args.at(1)); } Quantity function_poicdf(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::poissonCdf(args.at(0), args.at(1)); } Quantity function_poimean(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::poissonMean(args.at(0)); } Quantity function_poivar(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::poissonVariance(args.at(0)); } Quantity function_mask(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::mask(args.at(0), args.at(1)); } Quantity function_unmask(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::sgnext(args.at(0), args.at(1)); } Quantity function_not(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return ~args.at(0); } Quantity function_and(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(-1), std::mem_fn(&Quantity::operator&)); } Quantity function_or(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(0), std::mem_fn(&Quantity::operator|)); } Quantity function_xor(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(0), std::mem_fn(&Quantity::operator^)); } Quantity function_popcount(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); const Quantity value = args.at(0); Quantity result(0); for (int i = 0; i < LOGICRANGE; ++i) { const Quantity bit = value & (Quantity(1) << Quantity(i)); if (bit.isNan()) { return bit; } if (!bit.isZero()) { result += Quantity(1); } } return result; } Quantity function_shl(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::ashr(args.at(0), -args.at(1)); } Quantity function_shr(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::ashr(args.at(0), args.at(1)); } Quantity function_idiv(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::idiv(args.at(0), args.at(1)); } Quantity function_mod(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return args.at(0) % args.at(1); } Quantity function_emod(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); Quantity result = args.at(0) % args.at(1); if (result.isNan() || result.isZero()) { return result; } if (result.isNegative() != args.at(1).isNegative()) { result += args.at(1); } return result; } Quantity function_powmod(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(3); const Quantity base = args.at(0); const Quantity exponent = args.at(1); const Quantity modulo = args.at(2); if (!base.isInteger() || !exponent.isInteger() || !modulo.isInteger()) { f->setError(TypeMismatch); return DMath::nan(TypeMismatch); } if (modulo.isZero()) { f->setError(ZeroDivide); return DMath::nan(ZeroDivide); } if (exponent.isNegative()) { f->setError(OutOfDomain); return DMath::nan(OutOfDomain); } // Euclidean reduction helper: result has divisor sign (or is zero). auto emod = [&modulo](const Quantity& value) { Quantity result = value % modulo; if (result.isNan() || result.isZero()) { return result; } if (result.isNegative() != modulo.isNegative()) { result += modulo; } return result; }; Quantity e = exponent; Quantity factor = emod(base); Quantity result = emod(Quantity(1)); const Quantity zero(0); const Quantity two(2); while (e > zero) { if (!(e % two).isZero()) { result = emod(result * factor); } e = DMath::idiv(e, two); if (e > zero) { factor = emod(factor * factor); } } return result; } Quantity function_ieee754_decode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_EITHER_ARGUMENT_COUNT(3, 4); if (args.count() == 3) { return DMath::decodeIeee754(args.at(0), args.at(1), args.at(2)); } else { return DMath::decodeIeee754(args.at(0), args.at(1), args.at(2), args.at(3)); } } Quantity function_ieee754_encode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_EITHER_ARGUMENT_COUNT(3, 4); if (args.count() == 3) { return DMath::encodeIeee754(args.at(0), args.at(1), args.at(2)); } else { return DMath::encodeIeee754(args.at(0), args.at(1), args.at(2), args.at(3)); } } Quantity function_ieee754_half_decode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::decodeIeee754(args.at(0), 5, 10); } Quantity function_ieee754_half_encode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::encodeIeee754(args.at(0), 5, 10); } Quantity function_ieee754_single_decode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::decodeIeee754(args.at(0), 8, 23); } Quantity function_ieee754_single_encode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::encodeIeee754(args.at(0), 8, 23); } Quantity function_ieee754_double_decode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::decodeIeee754(args.at(0), 11, 52); } Quantity function_ieee754_double_encode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::encodeIeee754(args.at(0), 11, 52); } Quantity function_ieee754_quad_decode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::decodeIeee754(args.at(0), 15, 112); } Quantity function_ieee754_quad_encode(Function* f, const Function::ArgumentList& args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::encodeIeee754(args.at(0), 15, 112); } static Quantity s_ieee754_round(const Function::ArgumentList& args, int exponentBits, int significandBits) { const Quantity encoded = DMath::encodeIeee754(args.at(0), exponentBits, significandBits); return DMath::decodeIeee754(encoded, exponentBits, significandBits); } static Quantity s_ieee754_residual(const Function::ArgumentList& args, int exponentBits, int significandBits) { return args.at(0) - s_ieee754_round(args, exponentBits, significandBits); } Quantity function_ieee754_round_half(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return s_ieee754_round(args, 5, 10); } Quantity function_ieee754_round_float(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return s_ieee754_round(args, 8, 23); } Quantity function_ieee754_round_double(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return s_ieee754_round(args, 11, 52); } Quantity function_ieee754_round_quad(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return s_ieee754_round(args, 15, 112); } Quantity function_ieee754_half_residual(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return s_ieee754_residual(args, 5, 10); } Quantity function_ieee754_float_residual(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return s_ieee754_residual(args, 8, 23); } Quantity function_ieee754_double_residual(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return s_ieee754_residual(args, 11, 52); } Quantity function_ieee754_quad_residual(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); return s_ieee754_residual(args, 15, 112); } Quantity function_datetime(Function* f, const Function::ArgumentList& args) { ENSURE_EITHER_ARGUMENT_COUNT(1, 2); time_t timestamp = args.at(0).numericValue().toInt(); struct tm *time; char format[] = "%Y%m%d.%H%M%S"; char res[32]; if (args.count() == 2) { timestamp += (args.at(1).numericValue() * 3600).toInt(); time = std::gmtime(×tamp); } else { time = localtime(×tamp); } if (time == nullptr) { // Happen when specifying a negative timestamp on Windows f->setError(OutOfIntegerRange); return CMath::nan(OutOfIntegerRange); } strftime(res, sizeof(res), format, time); HNumber Temp(res); return Quantity(Temp).setFormat(Quantity::Format::Fixed() + Quantity::Format::Decimal() + Quantity::Format::Precision(6)); } Quantity function_epoch(Function* f, const Function::ArgumentList& args) { ENSURE_EITHER_ARGUMENT_COUNT(1, 2); ENSURE_REAL_ARGUMENT(0); if (args.count() == 2) ENSURE_REAL_ARGUMENT(1); const QString rawDateTime = HMath::format( args.at(0).numericValue().real, HNumber::Format::Fixed() + HNumber::Format::Point() + HNumber::Format::Precision(6)); const QStringList parts = rawDateTime.split(MathDsl::DotSep); if (parts.count() != 2 || parts.at(0).size() != 8 || parts.at(1).size() != 6) { f->setError(OutOfDomain); return DMath::nan(); } bool okYear = false, okMonth = false, okDay = false; bool okHour = false, okMinute = false, okSecond = false; const int year = parts.at(0).mid(0, 4).toInt(&okYear); const int month = parts.at(0).mid(4, 2).toInt(&okMonth); const int day = parts.at(0).mid(6, 2).toInt(&okDay); const int hour = parts.at(1).mid(0, 2).toInt(&okHour); const int minute = parts.at(1).mid(2, 2).toInt(&okMinute); const int second = parts.at(1).mid(4, 2).toInt(&okSecond); if (!okYear || !okMonth || !okDay || !okHour || !okMinute || !okSecond) { f->setError(OutOfDomain); return DMath::nan(); } const QDate date(year, month, day); const QTime time(hour, minute, second); if (!date.isValid() || !time.isValid()) { f->setError(OutOfDomain); return DMath::nan(); } QDateTime dateTime(date, time); if (args.count() == 2) { const int offsetSeconds = (args.at(1).numericValue() * 3600).toInt(); const QTimeZone zone(offsetSeconds); if (!zone.isValid()) { f->setError(OutOfDomain); return DMath::nan(); } dateTime = QDateTime(date, time, zone); } const qint64 epochSeconds = dateTime.toSecsSinceEpoch(); const QByteArray epochText = QByteArray::number(epochSeconds); return Quantity(HNumber(epochText.constData())); } Quantity function_molmass(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(1); f->setError(OutOfDomain); return DMath::nan(OutOfDomain); } Quantity function_mass(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(2); f->setError(OutOfDomain); return DMath::nan(OutOfDomain); } Quantity function_molarity(Function* f, const Function::ArgumentList& args) { ENSURE_ARGUMENT_COUNT(2); Quantity amount = args.at(0); Quantity volume = args.at(1); const Quantity oneMole = Units::mole(); const Quantity oneLitre = Units::litre(); if (amount.isDimensionless()) { amount *= oneMole; } else if (!amount.sameDimension(oneMole)) { f->setError(OutOfDomain); return DMath::nan(OutOfDomain); } if (volume.isDimensionless()) { volume *= oneLitre; } else if (!volume.sameDimension(oneLitre)) { f->setError(OutOfDomain); return DMath::nan(OutOfDomain); } Quantity concentration = amount / volume; const Quantity molPerLitre = oneMole / oneLitre; const QString molPerLitreSymbol = QString(::unitSymbol(UnitId::Mole)) + MathDsl::DivOp + QString(::unitSymbol(UnitId::Litre)); concentration.setDisplayUnit(molPerLitre.numericValue(), molPerLitreSymbol); return concentration; } void FunctionRepo::createFunctions() { // Aggregation. FUNCTION_INSERT(FunctionDomain::Aggregation, max); FUNCTION_INSERT(FunctionDomain::Aggregation, min); FUNCTION_INSERT(FunctionDomain::Aggregation, product); FUNCTION_INSERT(FunctionDomain::Aggregation, sum); FUNCTION_INSERT(FunctionDomain::Aggregation, summation); FUNCTION_INSERT(FunctionDomain::Aggregation, count); FUNCTION_INSERT(FunctionDomain::Aggregation, list); // Angle conversion. FUNCTION_INSERT(FunctionDomain::AngleConversion, degrees); FUNCTION_INSERT(FunctionDomain::AngleConversion, gradians); FUNCTION_INSERT(FunctionDomain::AngleConversion, radians); FUNCTION_INSERT(FunctionDomain::AngleConversion, turns); // Arithmetic. FUNCTION_INSERT(FunctionDomain::Arithmetic, abs); FUNCTION_INSERT(FunctionDomain::Arithmetic, cbrt); FUNCTION_INSERT(FunctionDomain::Arithmetic, ceil); FUNCTION_INSERT(FunctionDomain::Arithmetic, floor); FUNCTION_INSERT(FunctionDomain::Arithmetic, frac); FUNCTION_INSERT(FunctionDomain::Arithmetic, int); FUNCTION_INSERT(FunctionDomain::Arithmetic, round); FUNCTION_INSERT(FunctionDomain::Arithmetic, roundeven); FUNCTION_INSERT(FunctionDomain::Arithmetic, sgn); FUNCTION_INSERT(FunctionDomain::Arithmetic, root); FUNCTION_INSERT(FunctionDomain::Arithmetic, sqrt); FUNCTION_INSERT(FunctionDomain::Arithmetic, trunc); // Base conversion. FUNCTION_INSERT(FunctionDomain::BaseConversion, bin); FUNCTION_INSERT(FunctionDomain::BaseConversion, binpad); FUNCTION_INSERT(FunctionDomain::BaseConversion, dec); FUNCTION_INSERT(FunctionDomain::BaseConversion, hex); FUNCTION_INSERT(FunctionDomain::BaseConversion, hexpad); FUNCTION_INSERT(FunctionDomain::BaseConversion, oct); FUNCTION_INSERT(FunctionDomain::BaseConversion, octpad); // Bitwise. FUNCTION_INSERT(FunctionDomain::Bitwise, and); FUNCTION_INSERT(FunctionDomain::Bitwise, mask); FUNCTION_INSERT(FunctionDomain::Bitwise, not); FUNCTION_INSERT(FunctionDomain::Bitwise, or); FUNCTION_INSERT(FunctionDomain::Bitwise, popcount); FUNCTION_INSERT(FunctionDomain::Bitwise, shl); FUNCTION_INSERT(FunctionDomain::Bitwise, shr); FUNCTION_INSERT(FunctionDomain::Bitwise, unmask); FUNCTION_INSERT(FunctionDomain::Bitwise, xor); // Chemistry. FUNCTION_INSERT(FunctionDomain::Chemistry, mass); FUNCTION_INSERT(FunctionDomain::Chemistry, molarity); FUNCTION_INSERT(FunctionDomain::Chemistry, molmass); // Combinatorics. FUNCTION_INSERT(FunctionDomain::Combinatorics, ncr); FUNCTION_INSERT(FunctionDomain::Combinatorics, npr); // Complex. FUNCTION_INSERT(FunctionDomain::Complex, conj); FUNCTION_INSERT(FunctionDomain::Complex, imag); FUNCTION_INSERT(FunctionDomain::Complex, phase); FUNCTION_INSERT(FunctionDomain::Complex, real); FUNCTION_INSERT(FunctionDomain::Complex, rectform); FUNCTION_INSERT(FunctionDomain::Complex, trigform); FUNCTION_INSERT(FunctionDomain::Complex, expform); FUNCTION_INSERT(FunctionDomain::Complex, cisform); FUNCTION_INSERT(FunctionDomain::Complex, phasorform); // Date & Time. FUNCTION_INSERT(FunctionDomain::DateTime, datetime); FUNCTION_INSERT(FunctionDomain::DateTime, epoch); // Exponential & Logarithmic. FUNCTION_INSERT(FunctionDomain::ExponentialLogarithmic, exp); FUNCTION_INSERT(FunctionDomain::ExponentialLogarithmic, ln); FUNCTION_INSERT(FunctionDomain::ExponentialLogarithmic, log); FUNCTION_INSERT(FunctionDomain::ExponentialLogarithmic, log10); FUNCTION_INSERT(FunctionDomain::ExponentialLogarithmic, log2); // Floating point. FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_decode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_double_decode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_double_encode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_double_residual); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_encode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_float_residual); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_half_decode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_half_encode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_half_residual); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_quad_decode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_quad_encode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_quad_residual); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_round_double); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_round_float); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_round_half); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_round_quad); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_single_decode); FUNCTION_INSERT(FunctionDomain::FloatingPoint, ieee754_single_encode); // Integer arithmetic. FUNCTION_INSERT(FunctionDomain::IntegerArithmetic, emod); FUNCTION_INSERT(FunctionDomain::IntegerArithmetic, gcd); FUNCTION_INSERT(FunctionDomain::IntegerArithmetic, idiv); FUNCTION_INSERT(FunctionDomain::IntegerArithmetic, lcm); FUNCTION_INSERT(FunctionDomain::IntegerArithmetic, mod); FUNCTION_INSERT(FunctionDomain::IntegerArithmetic, powmod); // Number formatting. FUNCTION_INSERT(FunctionDomain::NumberFormatting, dms); FUNCTION_INSERT(FunctionDomain::NumberFormatting, eng); FUNCTION_INSERT(FunctionDomain::NumberFormatting, rat); FUNCTION_INSERT(FunctionDomain::NumberFormatting, sci); FUNCTION_INSERT(FunctionDomain::NumberFormatting, numval); // Probability. FUNCTION_INSERT(FunctionDomain::Probability, binomcdf); FUNCTION_INSERT(FunctionDomain::Probability, binommean); FUNCTION_INSERT(FunctionDomain::Probability, binompmf); FUNCTION_INSERT(FunctionDomain::Probability, binomvar); FUNCTION_INSERT(FunctionDomain::Probability, hypercdf); FUNCTION_INSERT(FunctionDomain::Probability, hypermean); FUNCTION_INSERT(FunctionDomain::Probability, hyperpmf); FUNCTION_INSERT(FunctionDomain::Probability, hypervar); FUNCTION_INSERT(FunctionDomain::Probability, poicdf); FUNCTION_INSERT(FunctionDomain::Probability, poimean); FUNCTION_INSERT(FunctionDomain::Probability, poipmf); FUNCTION_INSERT(FunctionDomain::Probability, poivar); // Random. FUNCTION_INSERT(FunctionDomain::Random, rand); FUNCTION_INSERT(FunctionDomain::Random, randint); // Special functions. FUNCTION_INSERT(FunctionDomain::SpecialFunctions, erf); FUNCTION_INSERT(FunctionDomain::SpecialFunctions, erfc); FUNCTION_INSERT(FunctionDomain::SpecialFunctions, gamma); FUNCTION_INSERT(FunctionDomain::SpecialFunctions, lngamma); // Statistics. FUNCTION_INSERT(FunctionDomain::Statistics, absdev); FUNCTION_INSERT(FunctionDomain::Statistics, average); FUNCTION_INSERT(FunctionDomain::Statistics, mean); FUNCTION_INSERT(FunctionDomain::Statistics, geomean); FUNCTION_INSERT(FunctionDomain::Statistics, mad); FUNCTION_INSERT(FunctionDomain::Statistics, median); FUNCTION_INSERT(FunctionDomain::Statistics, stdevp); FUNCTION_INSERT(FunctionDomain::Statistics, stdevs); FUNCTION_INSERT(FunctionDomain::Statistics, varp); FUNCTION_INSERT(FunctionDomain::Statistics, vars); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, cols); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, corrp); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, corrs); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, covp); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, covs); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, cross); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, det); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, dot); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, flatten); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, inv); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, norm); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, rank); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, rows); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, shape); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, trace); FUNCTION_INSERT(FunctionDomain::LinearAlgebra, transpose); // Trigonometry. FUNCTION_INSERT(FunctionDomain::Trigonometry, arccos); FUNCTION_INSERT(FunctionDomain::Trigonometry, arcosh); FUNCTION_INSERT(FunctionDomain::Trigonometry, arcsin); FUNCTION_INSERT(FunctionDomain::Trigonometry, arctan); FUNCTION_INSERT(FunctionDomain::Trigonometry, arctan2); FUNCTION_INSERT(FunctionDomain::Trigonometry, arsinh); FUNCTION_INSERT(FunctionDomain::Trigonometry, artanh); FUNCTION_INSERT(FunctionDomain::Trigonometry, cos); FUNCTION_INSERT(FunctionDomain::Trigonometry, cosh); FUNCTION_INSERT(FunctionDomain::Trigonometry, cis); FUNCTION_INSERT(FunctionDomain::Trigonometry, cot); FUNCTION_INSERT(FunctionDomain::Trigonometry, csc); FUNCTION_INSERT(FunctionDomain::Trigonometry, sec); FUNCTION_INSERT(FunctionDomain::Trigonometry, sin); FUNCTION_INSERT(FunctionDomain::Trigonometry, sinh); FUNCTION_INSERT(FunctionDomain::Trigonometry, tan); FUNCTION_INSERT(FunctionDomain::Trigonometry, tanh); // Symbol aliases. m_functions.insert(QString(UnicodeChars::Summation).toUpper(), find(QStringLiteral("summation"))); m_functions.insert(QString(UnicodeChars::SquareRoot).toUpper(), find(QStringLiteral("sqrt"))); m_functions.insert(QString(UnicodeChars::CubeRoot).toUpper(), find(QStringLiteral("cbrt"))); m_functions.insert(QStringLiteral("RATIO"), find(QStringLiteral("rat"))); m_functions.insert(QStringLiteral("RATIONAL"), find(QStringLiteral("rat"))); } FunctionRepo* FunctionRepo::instance() { if (!s_FunctionRepoInstance) { s_FunctionRepoInstance = new FunctionRepo; qAddPostRoutine(s_deleteFunctions); } return s_FunctionRepoInstance; } FunctionRepo::FunctionRepo() { StartupDiagnostics::Scope timing("Initialize built-in functions"); createFunctions(); setNonTranslatableFunctionUsages(); retranslateText(); } void FunctionRepo::insert(Function* function) { if (!function) return; function->setDomain(domainToDisplay(function->domainType())); m_functions.insert(function->identifier().toUpper(), function); } Function* FunctionRepo::find(const QString& identifier) const { if (identifier.isNull()) return 0; return m_functions.value(identifier.toUpper(), 0); } bool FunctionRepo::isIdentifierAliasOf(const QString& identifier, const QString& canonicalIdentifier) const { Function* canonical = find(canonicalIdentifier); if (!canonical) return false; return find(identifier) == canonical; } QString FunctionRepo::displayIdentifier(const QString& identifier) const { Function* function = find(identifier); if (!function) return identifier; const bool isAsciiWord = std::all_of(identifier.begin(), identifier.end(), [](QChar ch) { return (ch >= QLatin1Char('A') && ch <= QLatin1Char('Z')) || (ch >= QLatin1Char('a') && ch <= QLatin1Char('z')) || (ch >= QLatin1Char('0') && ch <= QLatin1Char('9')) || ch == QLatin1Char('_'); }); if (isAsciiWord) return function->identifier(); return identifier; } QStringList FunctionRepo::getIdentifiers() const { QStringList result = m_functions.keys(); std::transform(result.begin(), result.end(), result.begin(), [this](const QString& s) { return displayIdentifier(s); }); result.removeDuplicates(); return result; } const QStringList& FunctionRepo::domains() const { static QStringList result; result = QStringList() << domainToDisplay(FunctionDomain::Arithmetic) << domainToDisplay(FunctionDomain::Trigonometry) << domainToDisplay(FunctionDomain::ExponentialLogarithmic) << domainToDisplay(FunctionDomain::Aggregation) << domainToDisplay(FunctionDomain::Statistics) << domainToDisplay(FunctionDomain::LinearAlgebra) << domainToDisplay(FunctionDomain::Complex) << domainToDisplay(FunctionDomain::AngleConversion) << domainToDisplay(FunctionDomain::BaseConversion) << domainToDisplay(FunctionDomain::IntegerArithmetic) << domainToDisplay(FunctionDomain::NumberFormatting) << domainToDisplay(FunctionDomain::Random) << domainToDisplay(FunctionDomain::Probability) << domainToDisplay(FunctionDomain::Combinatorics) << domainToDisplay(FunctionDomain::DateTime) << domainToDisplay(FunctionDomain::Bitwise) << domainToDisplay(FunctionDomain::FloatingPoint) << domainToDisplay(FunctionDomain::SpecialFunctions) << domainToDisplay(FunctionDomain::Chemistry); return result; } void FunctionRepo::setNonTranslatableFunctionUsages() { FUNCTION_USAGE(abs, "x"); FUNCTION_USAGE(absdev, "x1; x2; ..."); FUNCTION_USAGE(list, "x1; x2; ..."); FUNCTION_USAGE(arccos, "x"); FUNCTION_USAGE(and, "x1; x2; ..."); FUNCTION_USAGE(arcosh, "x"); FUNCTION_USAGE(arsinh, "x"); FUNCTION_USAGE(artanh, "x"); FUNCTION_USAGE(arcsin, "x"); FUNCTION_USAGE(arctan, "x"); FUNCTION_USAGE(arctan2, "x; y"); FUNCTION_USAGE(average, "x1; x2; ..."); FUNCTION_USAGE(bin, "n"); FUNCTION_USAGE(binpad, "n [; bits]"); FUNCTION_USAGE(cbrt, "x"); FUNCTION_USAGE(ceil, "x"); FUNCTION_USAGE(cis, "x"); FUNCTION_USAGE(cisform, "x"); FUNCTION_USAGE(conj, "x"); FUNCTION_USAGE(cos, "x"); FUNCTION_USAGE(cosh, "x"); FUNCTION_USAGE(cols, "matrix"); FUNCTION_USAGE(corrp, "matrix"); FUNCTION_USAGE(corrs, "matrix"); FUNCTION_USAGE(count, "x1; x2; ..."); FUNCTION_USAGE(covp, "matrix"); FUNCTION_USAGE(covs, "matrix"); FUNCTION_USAGE(cross, "list; list"); FUNCTION_USAGE(cot, "x"); FUNCTION_USAGE(csc, "x"); FUNCTION_USAGE(dec, "x"); FUNCTION_USAGE(degrees, "x"); FUNCTION_USAGE(det, "matrix"); FUNCTION_USAGE(dms, "x"); FUNCTION_USAGE(dot, "list; list"); FUNCTION_USAGE(eng, "x [; exponent]"); FUNCTION_USAGE(erf, "x"); FUNCTION_USAGE(erfc, "x"); FUNCTION_USAGE(exp, "x"); FUNCTION_USAGE(expform, "x"); FUNCTION_USAGE(floor, "x"); FUNCTION_USAGE(flatten, "matrix"); FUNCTION_USAGE(frac, "x"); FUNCTION_USAGE(gamma, "x"); FUNCTION_USAGE(gcd, "n1; n2; ..."); FUNCTION_USAGE(lcm, "n1; n2; ..."); FUNCTION_USAGE(geomean, "x1; x2; ..."); FUNCTION_USAGE(gradians, "x"); FUNCTION_USAGE(hex, "n"); FUNCTION_USAGE(hexpad, "n [; bits]"); FUNCTION_USAGE(ieee754_half_decode, "x"); FUNCTION_USAGE(ieee754_half_encode, "x"); FUNCTION_USAGE(ieee754_single_decode, "x"); FUNCTION_USAGE(ieee754_single_encode, "x"); FUNCTION_USAGE(ieee754_double_decode, "x"); FUNCTION_USAGE(ieee754_double_encode, "x"); FUNCTION_USAGE(ieee754_quad_decode, "x"); FUNCTION_USAGE(ieee754_quad_encode, "x"); FUNCTION_USAGE(ieee754_round_half, "x"); FUNCTION_USAGE(ieee754_round_float, "x"); FUNCTION_USAGE(ieee754_round_double, "x"); FUNCTION_USAGE(ieee754_round_quad, "x"); FUNCTION_USAGE(ieee754_half_residual, "x"); FUNCTION_USAGE(ieee754_float_residual, "x"); FUNCTION_USAGE(ieee754_double_residual, "x"); FUNCTION_USAGE(ieee754_quad_residual, "x"); FUNCTION_USAGE(int, "x"); FUNCTION_USAGE(imag, "x"); FUNCTION_USAGE(inv, "matrix"); FUNCTION_USAGE(log2, "x"); FUNCTION_USAGE(log10, "x"); FUNCTION_USAGE(ln, "x"); FUNCTION_USAGE(lngamma, "x"); FUNCTION_USAGE(mad, "x1; x2; ..."); FUNCTION_USAGE(mass, "mol; formula"); FUNCTION_USAGE(molarity, "n; V"); FUNCTION_USAGE(molmass, "formula"); FUNCTION_USAGE(max, "x1; x2; ..."); FUNCTION_USAGE(median, "x1; x2; ..."); FUNCTION_USAGE(mean, "x1; x2; ..."); FUNCTION_USAGE(min, "x1; x2; ..."); FUNCTION_USAGE(numval, "x"); FUNCTION_USAGE(ncr, "x1; x2"); FUNCTION_USAGE(not, "n"); FUNCTION_USAGE(npr, "x1; x2"); FUNCTION_USAGE(oct, "n"); FUNCTION_USAGE(octpad, "n [; bits]"); FUNCTION_USAGE(norm, "list-or-matrix"); FUNCTION_USAGE(or, "x1; x2; ..."); FUNCTION_USAGE(popcount, "n"); FUNCTION_USAGE(product, "x1; x2; ..."); FUNCTION_USAGE(phase, "x"); FUNCTION_USAGE(phasorform, "x"); FUNCTION_USAGE(radians, "x"); FUNCTION_USAGE(rank, "matrix"); FUNCTION_USAGE(real, "x"); FUNCTION_USAGE(rat, "x"); FUNCTION_USAGE(rectform, "x"); FUNCTION_USAGE(root, "n; x"); FUNCTION_USAGE(sci, "x"); FUNCTION_USAGE(sec, "x)"); FUNCTION_USAGE(sgn, "x"); FUNCTION_USAGE(rows, "matrix"); FUNCTION_USAGE(shape, "list-or-matrix"); FUNCTION_USAGE(summation, "start; end; expression"); FUNCTION_USAGE(sin, "x"); FUNCTION_USAGE(sinh, "x"); FUNCTION_USAGE(sqrt, "x"); FUNCTION_USAGE(stdevp, "x1; x2; ..."); FUNCTION_USAGE(stdevs, "x1; x2; ..."); FUNCTION_USAGE(sum, "x1; x2; ..."); FUNCTION_USAGE(tan, "x"); FUNCTION_USAGE(trigform, "x"); FUNCTION_USAGE(turns, "x"); FUNCTION_USAGE(tanh, "x"); FUNCTION_USAGE(trunc, "x"); FUNCTION_USAGE(trace, "matrix"); FUNCTION_USAGE(transpose, "matrix"); FUNCTION_USAGE(varp, "x1; x2; ..."); FUNCTION_USAGE(vars, "x1; x2; ..."); FUNCTION_USAGE(xor, "x1; x2; ..."); } void FunctionRepo::setTranslatableFunctionUsages() { FUNCTION_USAGE_TR(binomcdf, tr("max; trials; probability")); FUNCTION_USAGE_TR(binommean, tr("trials; probability")); FUNCTION_USAGE_TR(binompmf, tr("hits; trials; probability")); FUNCTION_USAGE_TR(binomvar, tr("trials; probability")); FUNCTION_USAGE_TR(datetime, tr("unix_timestamp; x hours offset to GMT")); FUNCTION_USAGE_TR(epoch, tr("yyyymmdd.hhmmss; x hours offset to GMT")); FUNCTION_USAGE_TR(hypercdf, tr("max; total; hits; trials")); FUNCTION_USAGE_TR(hypermean, tr("total; hits; trials")); FUNCTION_USAGE_TR(hyperpmf, tr("count; total; hits; trials")); FUNCTION_USAGE_TR(hypervar, tr("total; hits; trials")); FUNCTION_USAGE_TR(idiv, tr("dividend; divisor")); FUNCTION_USAGE_TR(ieee754_decode, tr("x; exponent_bits; significand_bits [; exponent_bias]")); FUNCTION_USAGE_TR(ieee754_encode, tr("x; exponent_bits; significand_bits [; exponent_bias]")); FUNCTION_USAGE_TR(log, tr("base; x")); FUNCTION_USAGE_TR(rand, tr("[digits]")); FUNCTION_USAGE_TR(randint, tr("max [; min]")); FUNCTION_USAGE_TR(mask, "x; bits"); FUNCTION_USAGE_TR(mod, tr("value; modulo")); FUNCTION_USAGE_TR(emod, tr("value; modulo")); FUNCTION_USAGE_TR(powmod, tr("base; exponent; modulo")); FUNCTION_USAGE_TR(poicdf, tr("events; average_events")); FUNCTION_USAGE_TR(poimean, tr("average_events")); FUNCTION_USAGE_TR(poipmf, tr("events; average_events")); FUNCTION_USAGE_TR(poivar, tr("average_events")); FUNCTION_USAGE_TR(round, tr("x [; precision]")); FUNCTION_USAGE_TR(roundeven, tr("x [; precision]")); FUNCTION_USAGE_TR(shl, "x; bits"); FUNCTION_USAGE_TR(shr, "x; bits"); FUNCTION_USAGE_TR(unmask, "x; bits"); } void FunctionRepo::setFunctionNames() { FUNCTION_NAME(abs, tr("Absolute Value")); FUNCTION_NAME(absdev, tr("Absolute Deviation")); FUNCTION_NAME(list, tr("List Literal")); FUNCTION_NAME(arccos, tr("Arc Cosine")); FUNCTION_NAME(and, tr("Logical AND")); FUNCTION_NAME(arcosh, tr("Area Hyperbolic Cosine")); FUNCTION_NAME(arsinh, tr("Area Hyperbolic Sine")); FUNCTION_NAME(artanh, tr("Area Hyperbolic Tangent")); FUNCTION_NAME(arcsin, tr("Arc Sine")); FUNCTION_NAME(arctan, tr("Arc Tangent")); FUNCTION_NAME(arctan2, tr("Arc Tangent with two Arguments")); FUNCTION_NAME(average, tr("Average (Arithmetic Mean)")); FUNCTION_NAME(bin, tr("Convert to Binary Representation")); FUNCTION_NAME(binpad, tr("Convert to Padded Binary Representation")); FUNCTION_NAME(binomcdf, tr("Binomial Cumulative Distribution Function")); FUNCTION_NAME(binommean, tr("Binomial Distribution Mean")); FUNCTION_NAME(binompmf, tr("Binomial Probability Mass Function")); FUNCTION_NAME(binomvar, tr("Binomial Distribution Variance")); FUNCTION_NAME(cbrt, tr("Cube Root")); FUNCTION_NAME(ceil, tr("Round Toward +∞ (Ceiling)")); FUNCTION_NAME(cis, tr("Cosine plus Imaginary Sine")); FUNCTION_NAME(cisform, tr("Convert to Cis Complex Form")); FUNCTION_NAME(conj, tr("Complex Conjugate")); FUNCTION_NAME(cos, tr("Cosine")); FUNCTION_NAME(cosh, tr("Hyperbolic Cosine")); FUNCTION_NAME(cols, tr("Matrix Column Count")); FUNCTION_NAME(corrp, tr("Population Correlation Matrix (n)")); FUNCTION_NAME(corrs, tr("Sample Correlation Matrix (n-1)")); FUNCTION_NAME(count, tr("Count")); FUNCTION_NAME(covp, tr("Population Covariance Matrix (n)")); FUNCTION_NAME(covs, tr("Sample Covariance Matrix (n-1)")); FUNCTION_NAME(cross, tr("Cross Product")); FUNCTION_NAME(cot, tr("Cotangent")); FUNCTION_NAME(csc, tr("Cosecant")); FUNCTION_NAME(datetime, tr("Convert Unix timestamp to Date")); FUNCTION_NAME(epoch, tr("Convert Date to Unix timestamp")); FUNCTION_NAME(dec, tr("Convert to Decimal Representation")); FUNCTION_NAME(degrees, tr("Degrees of Arc")); FUNCTION_NAME(det, tr("Determinant")); FUNCTION_NAME(dms, tr("Convert to Sexagesimal Notation")); FUNCTION_NAME(dot, tr("Dot Product")); FUNCTION_NAME(eng, tr("Convert to Engineering Notation")); FUNCTION_NAME(erf, tr("Error Function")); FUNCTION_NAME(erfc, tr("Complementary Error Function")); FUNCTION_NAME(exp, tr("Exponential")); FUNCTION_NAME(expform, tr("Convert to Exponential Complex Form")); FUNCTION_NAME(floor, tr("Round Toward −∞ (Floor)")); FUNCTION_NAME(flatten, tr("Flatten Matrix")); FUNCTION_NAME(frac, tr("Fractional Part")); FUNCTION_NAME(gamma, tr("Extension of Factorials [= (x-1)!]")); FUNCTION_NAME(gcd, tr("Greatest Common Divisor")); FUNCTION_NAME(lcm, tr("Least Common Multiple")); FUNCTION_NAME(geomean, tr("Geometric Mean")); FUNCTION_NAME(gradians, tr("Gradians of arc")); FUNCTION_NAME(hex, tr("Convert to Hexadecimal Representation")); FUNCTION_NAME(hexpad, tr("Convert to Padded Hexadecimal Representation")); FUNCTION_NAME(hypercdf, tr("Hypergeometric Cumulative Distribution Function")); FUNCTION_NAME(hypermean, tr("Hypergeometric Distribution Mean")); FUNCTION_NAME(hyperpmf, tr("Hypergeometric Probability Mass Function")); FUNCTION_NAME(hypervar, tr("Hypergeometric Distribution Variance")); FUNCTION_NAME(idiv, tr("Integer Quotient")); FUNCTION_NAME(int, tr("Integer Part")); FUNCTION_NAME(imag, tr("Imaginary Part")); FUNCTION_NAME(inv, tr("Inverse Matrix")); FUNCTION_NAME(ieee754_decode, tr("Decode IEEE-754 Binary Value")); FUNCTION_NAME(ieee754_encode, tr("Encode IEEE-754 Binary Value")); FUNCTION_NAME(ieee754_half_decode, tr("Decode 16-bit Half-Precision Value")); FUNCTION_NAME(ieee754_half_encode, tr("Encode 16-bit Half-Precision Value")); FUNCTION_NAME(ieee754_single_decode, tr("Decode 32-bit Single-Precision Value")); FUNCTION_NAME(ieee754_single_encode, tr("Encode 32-bit Single-Precision Value")); FUNCTION_NAME(ieee754_double_decode, tr("Decode 64-bit Double-Precision Value")); FUNCTION_NAME(ieee754_double_encode, tr("Encode 64-bit Double-Precision Value")); FUNCTION_NAME(ieee754_quad_decode, tr("Decode 128-bit Quad-Precision Value")); FUNCTION_NAME(ieee754_quad_encode, tr("Encode 128-bit Quad-Precision Value")); FUNCTION_NAME(ieee754_round_half, tr("Round to 16-bit Half-Precision Value")); FUNCTION_NAME(ieee754_round_float, tr("Round to 32-bit Single-Precision Value")); FUNCTION_NAME(ieee754_round_double, tr("Round to 64-bit Double-Precision Value")); FUNCTION_NAME(ieee754_round_quad, tr("Round to 128-bit Quad-Precision Value")); FUNCTION_NAME(ieee754_half_residual, tr("Residual from 16-bit Half-Precision Rounding")); FUNCTION_NAME(ieee754_float_residual, tr("Residual from 32-bit Single-Precision Rounding")); FUNCTION_NAME(ieee754_double_residual, tr("Residual from 64-bit Double-Precision Rounding")); FUNCTION_NAME(ieee754_quad_residual, tr("Residual from 128-bit Quad-Precision Rounding")); FUNCTION_NAME(log2, tr("Binary Logarithm")); FUNCTION_NAME(log10, tr("Common Logarithm")); FUNCTION_NAME(ln, tr("Natural Logarithm")); FUNCTION_NAME(lngamma, "ln(abs(Gamma))"); FUNCTION_NAME(mass, tr("Substance Mass")); FUNCTION_NAME(molarity, tr("Molarity")); FUNCTION_NAME(molmass, tr("Molar Mass")); FUNCTION_NAME(log, tr("Logarithm to Arbitrary Base")); FUNCTION_NAME(mad, tr("Median Absolute Deviation")); FUNCTION_NAME(mask, tr("Mask to a bit size")); FUNCTION_NAME(max, tr("Maximum")); FUNCTION_NAME(median, tr("Median Value (50th Percentile)")); FUNCTION_NAME(mean, tr("Mean")); FUNCTION_NAME(min, tr("Minimum")); FUNCTION_NAME(numval, tr("Numerical Value of Quantity")); FUNCTION_NAME(rand, tr("Random Decimal Number")); FUNCTION_NAME(randint, tr("Random Integer Number")); FUNCTION_NAME(rat, tr("Convert to Rational Representation")); FUNCTION_NAME(mod, tr("Modulo")); FUNCTION_NAME(emod, tr("Euclidean Modulo")); FUNCTION_NAME(powmod, tr("Modular Exponentiation")); FUNCTION_NAME(ncr, tr("Combination (Binomial Coefficient)")); FUNCTION_NAME(not, tr("Logical NOT")); FUNCTION_NAME(npr, tr("Permutation (Arrangement)")); FUNCTION_NAME(oct, tr("Convert to Octal Representation")); FUNCTION_NAME(octpad, tr("Convert to Padded Octal Representation")); FUNCTION_NAME(norm, tr("Vector or Matrix Norm")); FUNCTION_NAME(or, tr("Logical OR")); FUNCTION_NAME(popcount, tr("Population Count (Hamming Weight)")); FUNCTION_NAME(phase, tr("Phase of Complex Number")); FUNCTION_NAME(poicdf, tr("Poissonian Cumulative Distribution Function")); FUNCTION_NAME(poimean, tr("Poissonian Distribution Mean")); FUNCTION_NAME(poipmf, tr("Poissonian Probability Mass Function")); FUNCTION_NAME(poivar, tr("Poissonian Distribution Variance")); FUNCTION_NAME(phasorform, tr("Convert to Phasor Complex Form")); FUNCTION_NAME(product, tr("Product")); FUNCTION_NAME(radians, tr("Radians")); FUNCTION_NAME(rank, tr("Matrix Rank")); FUNCTION_NAME(real, tr("Real Part")); FUNCTION_NAME(rectform, tr("Convert to Rectangular Complex Form")); FUNCTION_NAME(round, tr("Round Half Away from Zero")); FUNCTION_NAME(roundeven, tr("Round Half Even")); FUNCTION_NAME(root, tr("Nth Root")); FUNCTION_NAME(sci, tr("Convert to Scientific Notation")); FUNCTION_NAME(sec, tr("Secant")); FUNCTION_NAME(shl, tr("Arithmetic Shift Left")); FUNCTION_NAME(shr, tr("Arithmetic Shift Right")); FUNCTION_NAME(sgn, tr("Signum")); FUNCTION_NAME(rows, tr("Matrix Row Count")); FUNCTION_NAME(shape, tr("List or Matrix Shape")); FUNCTION_NAME(summation, tr("Summation")); FUNCTION_NAME(sin, tr("Sine")); FUNCTION_NAME(sinh, tr("Hyperbolic Sine")); FUNCTION_NAME(sqrt, tr("Square Root")); FUNCTION_NAME(stdevp, tr("Population Standard Deviation (n)")); FUNCTION_NAME(stdevs, tr("Sample Standard Deviation (n-1)")); FUNCTION_NAME(sum, tr("Sum")); FUNCTION_NAME(tan, tr("Tangent")); FUNCTION_NAME(trigform, tr("Convert to Trigonometric Complex Form")); FUNCTION_NAME(turns, tr("Turns")); FUNCTION_NAME(tanh, tr("Hyperbolic Tangent")); FUNCTION_NAME(trunc, tr("Round Toward Zero (Truncation)")); FUNCTION_NAME(trace, tr("Matrix Trace")); FUNCTION_NAME(transpose, tr("Transpose Matrix")); FUNCTION_NAME(unmask, tr("Sign-extend a value")); FUNCTION_NAME(varp, tr("Population Variance (n)")); FUNCTION_NAME(vars, tr("Sample Variance (n-1)")); FUNCTION_NAME(xor, tr("Logical XOR")); } void FunctionRepo::retranslateText() { setFunctionNames(); setTranslatableFunctionUsages(); } heldercorreia-speedcrunch-e7ca37f/src/core/functions.h000066400000000000000000000051621526573132500232410ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2009, 2013-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_FUNCTION_H #define CORE_FUNCTION_H #include "core/errors.h" #include "math/quantity.h" #include #include #include #include class Function; enum class FunctionDomain { Arithmetic, Chemistry, Complex, Combinatorics, Probability, Statistics, Aggregation, Random, BaseConversion, NumberFormatting, IntegerArithmetic, SpecialFunctions, ExponentialLogarithmic, AngleConversion, Trigonometry, Bitwise, FloatingPoint, DateTime, LinearAlgebra }; class Function : public QObject { Q_OBJECT public: typedef QVector ArgumentList; typedef Quantity (*FunctionImpl)(Function*, const ArgumentList&); Function(const QString& identifier, FunctionImpl ptr, FunctionDomain domainType, QObject* parent = 0) : QObject(parent) , m_identifier(identifier) , m_ptr(ptr) , m_domainType(domainType) { } const QString& identifier() const { return m_identifier; } const QString& name() const { return m_name; } const QString& usage() const { return m_usage; } FunctionDomain domainType() const { return m_domainType; } const QString& domain() const { return m_domain; } Error error() const { return m_error; } Quantity exec(const ArgumentList&); void setName(const QString& name) { m_name = name; } void setUsage(const QString& usage) { m_usage = usage; } void setDomain(const QString& domain) { m_domain = domain; } void setError(Error error) { m_error = error; } private: Q_DISABLE_COPY(Function) Function(); QString m_identifier; QString m_name; QString m_usage; Error m_error; FunctionImpl m_ptr; FunctionDomain m_domainType; QString m_domain; }; class FunctionRepo : public QObject { Q_OBJECT public: static FunctionRepo* instance(); void insert(Function*); QStringList getIdentifiers() const; Function* find(const QString& identifier) const; bool isIdentifierAliasOf(const QString& identifier, const QString& canonicalIdentifier) const; QString displayIdentifier(const QString& identifier) const; const QStringList& domains() const; public slots: void retranslateText(); private: Q_DISABLE_COPY(FunctionRepo) FunctionRepo(); void createFunctions(); void setFunctionNames(); void setNonTranslatableFunctionUsages(); void setTranslatableFunctionUsages(); QHash m_functions; }; #endif // CORE_FUNCTION_H heldercorreia-speedcrunch-e7ca37f/src/core/manualserver.cpp000066400000000000000000000072751526573132500242770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2016, 2021-2022, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/manualserver.h" #include "core/settings.h" #include #include #include #include #include #include #include #include #define FALLBACK_LANG "en_US" #define COPY_OVERWRITE(source, dest) \ if (QFile::exists(dest)) \ QFile::remove(dest); \ QFile::copy(source, dest); #define QHC_NAME(lang) ("manual-" + QString(lang) + ".qhc") #define QCH_NAME(lang) ("manual-" + QString(lang) + ".qch") #define QHC_RES_PATH(lang) (":/manual/" + QHC_NAME(lang)) #define QCH_RES_PATH(lang) (":/manual/" + QCH_NAME(lang)) ManualServer* ManualServer::s_instance = nullptr; QString ManualServer::deployDocs() { QString dest = Settings::getCachePath() + "/manual/"; QDir qdir; qdir.mkpath(dest); QString lang = Settings::instance()->language; m_deployedLanguage = lang; if (lang == "C") lang = QLocale().name(); if (!isSupportedLanguage(lang)) { // Extract the language from the locale and try to find a generic translation for it QStringList languages = QLocale((QLocale(lang).language())).uiLanguages(); lang = FALLBACK_LANG; for (int i = 0; i < languages.size(); ++i) { QString extra_lang = languages[i].replace('-', '_'); if (isSupportedLanguage(extra_lang)) { lang = extra_lang; break; } } } QFile::remove(dest + QHC_NAME(lang)); QFile::remove(dest + QCH_NAME(lang)); QFile::copy(QHC_RES_PATH(lang), dest + QHC_NAME(lang)); QFile::copy(QCH_RES_PATH(lang), dest + QCH_NAME(lang)); QFile qhc(dest + QHC_NAME(lang)); qhc.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner); QFile qch(dest + QCH_NAME(lang)); qch.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner); return dest + "manual-" + lang + ".qhc"; } bool ManualServer::isSupportedLanguage(const QString& lang) { return (QFile(QHC_RES_PATH(lang)).exists() && QFile(QCH_RES_PATH(lang)).exists()); } void ManualServer::setupHelpEngine() { QString collectionFile = deployDocs() ; m_helpEngine = new QHelpEngineCore(collectionFile, this); QStringList filters = m_helpEngine->customFilters(); if (!filters.isEmpty()) m_helpEngine->setCurrentFilter(filters.first()); } ManualServer *ManualServer::instance() { if (!s_instance) s_instance = new ManualServer(); return s_instance; } QUrl ManualServer::homePage() { ensureCorrectLanguage(); if (!m_helpEngine) return QUrl(); auto docs = m_helpEngine->documentsForKeyword("SpeedCrunch"); if (!docs.isEmpty()) { return docs[0].url; } return QUrl(); } QUrl ManualServer::urlForKeyword(const QString& keyword) { ensureCorrectLanguage(); if (!m_helpEngine) return QUrl(); auto constants = m_helpEngine->documentsForIdentifier(QString("constant.%1").arg(keyword)); if (!constants.isEmpty()) { return constants[0].url; } auto functions = m_helpEngine->documentsForIdentifier(QString("function.%1").arg(keyword)); if (!functions.isEmpty()) { return functions[0].url; } return QUrl(); } QByteArray ManualServer::fileData(const QUrl &url) { ensureCorrectLanguage(); return m_helpEngine->fileData(url); } void ManualServer::languageChanged() { setupHelpEngine(); } void ManualServer::ensureCorrectLanguage() { if (Settings::instance()->language != m_deployedLanguage) languageChanged(); } ManualServer::ManualServer() { m_helpEngine = nullptr; } heldercorreia-speedcrunch-e7ca37f/src/core/manualserver.h000066400000000000000000000015761526573132500237420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2016, 2022, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_MANUALSERVER_H #define CORE_MANUALSERVER_H #include #include class QHelpEngineCore; class QCloseEvent; class QUrl; class QString; class QByteArray; class ManualServer : public QObject { Q_OBJECT private: QString deployDocs(); void setupHelpEngine(); public: static ManualServer* instance(); QUrl homePage(); QUrl urlForKeyword(const QString& keyword); QByteArray fileData(const QUrl &url); bool isSupportedLanguage(const QString&); public slots: void ensureCorrectLanguage(); private: ManualServer(); Q_DISABLE_COPY(ManualServer) void languageChanged(); QHelpEngineCore *m_helpEngine; static ManualServer* s_instance; QString m_deployedLanguage; }; #endif // CORE_MANUALSERVER_H heldercorreia-speedcrunch-e7ca37f/src/core/mathdsl.cpp000066400000000000000000000055161526573132500232230ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/mathdsl.h" namespace MathDsl { bool isMultiplicationOperatorAlias(const QChar& ch, bool keepDotOperator) { switch (ch.unicode()) { case MathDsl::MulOpAl1.unicode(): case MathDsl::MulOpAl2.unicode(): case MathDsl::MulOpAl3.unicode(): case MathDsl::MulOpAl4.unicode(): case MathDsl::MulOpAl5.unicode(): case MathDsl::MulOpAl6.unicode(): case MathDsl::MulOpAl7.unicode(): return true; case MulDotOp.unicode(): return !keepDotOperator; default: return false; } } bool isDivisionOperatorAlias(const QChar& ch) { switch (ch.unicode()) { case UnicodeChars::DivisionSign.unicode(): return true; default: return isDivisionOperator(ch); } } bool isAdditionOperatorAlias(const QChar& ch) { return ch.unicode() == UnicodeChars::FullwidthPlusSign.unicode(); } bool isSubtractionOperatorAlias(const QChar& ch) { switch (ch.unicode()) { case UnicodeChars::MinusSign.unicode(): case UnicodeChars::HyphenMinus.unicode(): case UnicodeChars::Hyphen.unicode(): case UnicodeChars::NonBreakingHyphen.unicode(): case UnicodeChars::EnDash.unicode(): case UnicodeChars::EmDash.unicode(): case UnicodeChars::HorizontalBar.unicode(): case UnicodeChars::HyphenBullet.unicode(): case UnicodeChars::SmallHyphenMinus.unicode(): case UnicodeChars::FullwidthHyphenMinus.unicode(): return true; default: return false; } } bool isExpressionBoundaryOperatorOrSeparator(const QChar& ch) { return ch == AddOp || ch == SubOp || isMultiplicationOperator(ch) || isDivisionOperator(ch) || ch == PercentOp || ch == FactorOp || ch == PowOp || ch == BitAndOp || ch == BitOrOp || ch == PhasorOp || ch == Equals || ch == GreaterThanOp || ch == LessThanOp || ch == FunArgSep || ch == CommaSep; } bool isExpressionOperatorOrSeparator(const QChar& ch) { return isExpressionBoundaryOperatorOrSeparator(ch); } QString buildWrappedToken(const QChar& op, const QChar& wrap) { return buildWrappedToken(op, wrap, wrap); } QString buildWrappedToken(const QChar& op, const QChar& leftWrap, const QChar& rightWrap) { QString out; out.reserve(3); out += leftWrap; out += op; out += rightWrap; return out; } QString buildWrappedToken(const QString& op, const QChar& wrap) { return buildWrappedToken(op, wrap, wrap); } QString buildWrappedToken(const QString& op, const QChar& leftWrap, const QChar& rightWrap) { QString out; out.reserve(op.size() + 2); out += leftWrap; out += op; out += rightWrap; return out; } } // namespace MathDsl heldercorreia-speedcrunch-e7ca37f/src/core/mathdsl.h000066400000000000000000000156501526573132500226700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_MATHDSL_H #define CORE_MATHDSL_H #include "core/unicodechars.h" #include #include namespace MathDsl { // Display/operator symbol constants consumed by DisplayFormatUtils. // Spacing behavior is defined in gui/displayformatutils.h. inline constexpr QChar MulDotOp = UnicodeChars::MiddleDot; inline constexpr QChar MulCrossOp = UnicodeChars::MultiplicationSign; inline constexpr QChar MulOpAl1 = UnicodeChars::Asterisk; inline constexpr QChar MulOpAl2 = UnicodeChars::AsteriskOperator; inline constexpr QChar MulOpAl3 = UnicodeChars::BulletOperator; inline constexpr QChar MulOpAl4 = UnicodeChars::MultiplicationX; inline constexpr QChar MulOpAl5 = UnicodeChars::HeavyMultiplicationX; inline constexpr QChar MulOpAl6 = UnicodeChars::NAryTimesOperator; inline constexpr QChar MulOpAl7 = UnicodeChars::VectorOrCrossProduct; inline constexpr QChar DivOp = UnicodeChars::Solidus; inline constexpr QChar TransOp = UnicodeChars::RightwardsArrow; inline constexpr QChar PhasorOp = UnicodeChars::Angle; inline constexpr QChar PowOp = UnicodeChars::CircumflexAccent; inline constexpr QChar TimeSep = UnicodeChars::Colon; inline constexpr QChar FunArgSep = UnicodeChars::Semicolon; inline constexpr QChar AddOp = UnicodeChars::PlusSign; inline constexpr QChar Equals = UnicodeChars::EqualsSign; inline constexpr QChar SubOp = UnicodeChars::MinusSign; inline constexpr QChar SubOpAl1 = UnicodeChars::HyphenMinus; inline constexpr QChar PercentOp = UnicodeChars::PercentSign; inline constexpr QChar FactorOp = UnicodeChars::ExclamationMark; inline constexpr QChar CommentSep = UnicodeChars::QuestionMark; inline constexpr QChar DollarSign = UnicodeChars::DollarSign; inline constexpr QChar BitAndOp = UnicodeChars::Ampersand; inline constexpr QChar BitOrOp = UnicodeChars::VerticalLine; inline constexpr QChar LessThanOp = UnicodeChars::LessThanSign; inline constexpr QChar GreaterThanOp = UnicodeChars::GreaterThanSign; inline constexpr QChar Deg = UnicodeChars::DegreeSign; inline constexpr QChar CommaSep = UnicodeChars::Comma; inline constexpr QChar DotSep = UnicodeChars::FullStop; inline constexpr QChar ArcminOp = UnicodeChars::Prime; inline constexpr QChar ArcminOpAl1 = UnicodeChars::Apostrophe; inline constexpr QChar ArcsecOp = UnicodeChars::DoublePrime; inline constexpr QChar ArcsecOpAl1 = UnicodeChars::QuotationMark; inline constexpr QChar IntDivOp = UnicodeChars::ReverseSolidus; inline constexpr QChar SubWrapSp = UnicodeChars::Space; inline constexpr QChar AddWrap = UnicodeChars::Space; inline constexpr QChar DivWrap = UnicodeChars::Space; inline constexpr QChar MulDotWrapSp = UnicodeChars::Space; inline constexpr QChar MulCrossWrapSp = UnicodeChars::Space; inline constexpr QChar QuantSp = UnicodeChars::NoBreakSpace; inline constexpr QChar Dig0 = UnicodeChars::DigitZero; inline constexpr QChar Dig1 = UnicodeChars::DigitOne; inline constexpr QChar Dig2 = UnicodeChars::DigitTwo; inline constexpr QChar Dig3 = UnicodeChars::DigitThree; inline constexpr QChar Dig4 = UnicodeChars::DigitFour; inline constexpr QChar Dig5 = UnicodeChars::DigitFive; inline constexpr QChar Dig6 = UnicodeChars::DigitSix; inline constexpr QChar Dig7 = UnicodeChars::DigitSeven; inline constexpr QChar Dig8 = UnicodeChars::DigitEight; inline constexpr QChar Dig9 = UnicodeChars::DigitNine; inline constexpr QChar PowPos = UnicodeChars::SuperscriptPlus; inline constexpr QChar PowNeg = UnicodeChars::SuperscriptMinus; inline constexpr QChar Pow0 = UnicodeChars::SuperscriptZero; inline constexpr QChar Pow1 = UnicodeChars::SuperscriptOne; inline constexpr QChar Pow2 = UnicodeChars::SuperscriptTwo; inline constexpr QChar Pow3 = UnicodeChars::SuperscriptThree; inline constexpr QChar Pow4 = UnicodeChars::SuperscriptFour; inline constexpr QChar Pow5 = UnicodeChars::SuperscriptFive; inline constexpr QChar Pow6 = UnicodeChars::SuperscriptSix; inline constexpr QChar Pow7 = UnicodeChars::SuperscriptSeven; inline constexpr QChar Pow8 = UnicodeChars::SuperscriptEight; inline constexpr QChar Pow9 = UnicodeChars::SuperscriptNine; inline constexpr QChar GroupStart = UnicodeChars::LeftParenthesis; inline constexpr QChar GroupEnd = UnicodeChars::RightParenthesis; inline constexpr QChar UnitStart = UnicodeChars::LeftSquareBracket; inline constexpr QChar UnitEnd = UnicodeChars::RightSquareBracket; inline constexpr QChar ListStart = UnicodeChars::LeftCurlyBracket; inline constexpr QChar ListEnd = UnicodeChars::RightCurlyBracket; inline const QString HexPrefix = QStringLiteral("0x"); inline const QString BinPrefix = QStringLiteral("0b"); inline const QString OctPrefix = QStringLiteral("0o"); inline const QString ShiftLeftOp = QString(LessThanOp) + QString(LessThanOp); inline const QString ShiftRightOp = QString(GreaterThanOp) + QString(GreaterThanOp); inline constexpr QChar HexPrefixAl1 = UnicodeChars::NumberSign; inline const QString TransOpAl1 = QStringLiteral("in"); inline constexpr QChar Powers[] = { Pow0, Pow1, Pow2, Pow3, Pow4, Pow5, Pow6, Pow7, Pow8, Pow9 }; inline constexpr QChar Digits[] = { Dig0, Dig1, Dig2, Dig3, Dig4, Dig5, Dig6, Dig7, Dig8, Dig9 }; inline bool isAdditionOperator(const QChar& ch) { return ch == AddOp; } inline bool isSubtractionOperator(const QChar& ch) { return ch == SubOp || ch == SubOpAl1; } inline bool isMultiplicationOperator(const QChar& ch) { return ch == MulDotOp || ch == MulCrossOp; } inline bool isDivisionOperator(const QChar& ch) { return ch == DivOp; } bool isExpressionBoundaryOperatorOrSeparator(const QChar& ch); bool isExpressionOperatorOrSeparator(const QChar& ch); bool isMultiplicationOperatorAlias(const QChar& ch, bool keepDotOperator = false); bool isDivisionOperatorAlias(const QChar& ch); bool isAdditionOperatorAlias(const QChar& ch); bool isSubtractionOperatorAlias(const QChar& ch); QString buildWrappedToken(const QChar& op, const QChar& wrap = UnicodeChars::Space); QString buildWrappedToken(const QChar& op, const QChar& leftWrap, const QChar& rightWrap); QString buildWrappedToken(const QString& op, const QChar& wrap = UnicodeChars::Space); QString buildWrappedToken(const QString& op, const QChar& leftWrap, const QChar& rightWrap); inline bool isSuperscriptDigit(const QChar& ch) { for (int i = 0; i < 10; ++i) { if (ch == Powers[i]) return true; } return false; } inline bool isSuperscriptSign(const QChar& ch) { return ch == PowNeg || ch == PowPos; } inline bool isSuperscriptPowerChar(const QChar& ch) { return isSuperscriptDigit(ch) || isSuperscriptSign(ch); } inline QChar superscriptDigitToAscii(const QChar& ch) { for (int i = 0; i < 10; ++i) { if (ch == Powers[i]) return Digits[i]; } return QChar(); } inline QChar asciiDigitToSuperscript(const QChar& ch) { const ushort code = ch.unicode(); if (code < Dig0.unicode() || code > Dig9.unicode()) return QChar(); return Powers[code - Dig0.unicode()]; } } // namespace MathDsl #endif // CORE_MATHDSL_H heldercorreia-speedcrunch-e7ca37f/src/core/numberformatter.cpp000066400000000000000000000725261526573132500250100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2013, 2015-2018, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/numberformatter.h" #include "core/complexform.h" #include "core/regexpatterns.h" #include "core/unitdisplayformat.h" #include "core/settings.h" #include "core/symbolicnumberformat.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include "math/quantity.h" #include "math/rational.h" #include "core/units.h" #include static const QChar g_dotChar = MathDsl::MulDotOp; static const QChar g_minusChar = MathDsl::SubOp; namespace { constexpr int RationalFormatMaxDenominator = 1000000; // Internal sentinel set by rat()/ratio()/rational() via Quantity::Format::precision. // It forces rational display for a single result, with automatic decimal fallback. constexpr int ForcedRationalPrecision = -999; HNumber rationalFormatRelativeTolerance() { return HNumber("1e-60"); } bool isCloseTo(const HNumber& value, const HNumber& reference) { return SymbolicNumberFormat::isCloseToTrigSymbolicValue(value, reference); } void useUnprefixedSiUnitForScientificDisplay(Quantity* quantity) { if (!quantity || !quantity->hasUnit()) return; const auto baseIdForDisplayUnit = [](const QString& unitName) { const QString normalized = normalizeUnitName(unitName); const UnitId directId = unitId(normalized); if (directId != UnitId::Unknown) return directId; struct PrefixText { QString text; UnitPrefixSpec spec; }; QList prefixes; for (const UnitPrefixSpec& prefix : siPrefixes()) { prefixes.append(PrefixText{normalizeUnitName(prefix.symbol), prefix}); prefixes.append(PrefixText{normalizeUnitName(prefix.longName), prefix}); } std::sort(prefixes.begin(), prefixes.end(), [](const PrefixText& a, const PrefixText& b) { return a.text.size() > b.text.size(); }); for (const PrefixText& prefix : prefixes) { if (prefix.text.isEmpty() || !normalized.startsWith(prefix.text) || normalized.size() == prefix.text.size()) { continue; } const UnitId baseId = unitId(normalized.mid(prefix.text.size())); const int policy = unitPrefixPolicy(baseId); if ((policy & AllDecimalSiPrefixes) && unitPrefixPolicyAllows(policy, prefix.spec)) { return baseId; } } return UnitId::Unknown; }; const UnitId id = baseIdForDisplayUnit(quantity->unitName()); if (!(unitPrefixPolicy(id) & AllDecimalSiPrefixes)) return; const QString baseSymbol = unitSiPrefixBaseSymbol(id); const CNumber baseValue = unitSiPrefixBaseValue(id); if (baseSymbol.isEmpty() || !baseValue.isNearReal() || baseValue.real.isNearZero()) return; quantity->setDisplayUnit(baseValue, baseSymbol); } QString formatCommonTrigRadical(const HNumber& value) { const bool negative = value.isNegative(); const HNumber absValue = negative ? -value : value; const HNumber sqrt2 = HMath::sqrt(HNumber(2)); const HNumber sqrt3 = HMath::sqrt(HNumber(3)); QString symbol; if (isCloseTo(absValue, sqrt2 / HNumber(2))) symbol = SymbolicNumberFormat::formatFraction(QStringLiteral("sqrt(2)"), 2); else if (isCloseTo(absValue, sqrt3 / HNumber(2))) symbol = SymbolicNumberFormat::formatFraction(QStringLiteral("sqrt(3)"), 2); else if (isCloseTo(absValue, sqrt3 / HNumber(3))) symbol = SymbolicNumberFormat::formatFraction(QStringLiteral("sqrt(3)"), 3); else if (isCloseTo(absValue, HNumber(2) * sqrt3 / HNumber(3))) symbol = SymbolicNumberFormat::formatFraction(QStringLiteral("2 sqrt(3)"), 3); else if (isCloseTo(absValue, sqrt2)) symbol = QStringLiteral("sqrt(2)"); else if (isCloseTo(absValue, sqrt3)) symbol = QStringLiteral("sqrt(3)"); if (symbol.isEmpty()) return QString(); return negative ? QStringLiteral("-") + symbol : symbol; } QString formatCommonTrigFraction(const HNumber& value) { const bool negative = value.isNegative(); const HNumber absValue = negative ? -value : value; QString symbol; if (isCloseTo(absValue, HNumber(1) / HNumber(2))) symbol = SymbolicNumberFormat::formatFraction(QStringLiteral("1"), 2); if (symbol.isEmpty()) return QString(); return negative ? QStringLiteral("-") + symbol : symbol; } QString formatTrigSymbolicDisplay(const Quantity& q, const HNumber& value) { if (!q.isDimensionless() || !q.unitName().isEmpty()) return QString(); QString symbolic = SymbolicNumberFormat::formatPiMultiple(value); if (!symbolic.isEmpty()) return symbolic; symbolic = formatCommonTrigFraction(value); if (!symbolic.isEmpty()) return symbolic; return formatCommonTrigRadical(value); } QString formatRationalDisplay(Quantity q) { if (q.isNan()) return QString(); if (!q.hasUnit() && !q.isDimensionless()) { q.cleanDimension(); Units::findUnit(q); } CNumber number = q.numericValue(); number /= q.unit(); if (!number.isNearReal()) return QString(); QString symbolicTrig = formatTrigSymbolicDisplay(q, number.real); if (!symbolicTrig.isEmpty()) return symbolicTrig; Rational rational; if (!Rational::approximate(number.real, RationalFormatMaxDenominator, rationalFormatRelativeTolerance(), &rational)) { return QString(); } QString result; if (rational.denominator() == 1) { result = QString::number(rational.numerator()); } else { result = SymbolicNumberFormat::formatFraction(QString::number(rational.numerator()), rational.denominator()); } const QString unitName = q.unitName(); if (!unitName.isEmpty()) result += QStringLiteral("[%1]").arg(unitName); return result; } bool isValidDigitForBase(const QChar ch, int base) { if (base <= 10) return ch >= QLatin1Char('0') && ch < QLatin1Char('0' + base); if (ch >= QLatin1Char('0') && ch <= QLatin1Char('9')) return true; const QChar lower = ch.toLower(); return lower >= QLatin1Char('a') && lower < QLatin1Char('a' + (base - 10)); } bool isValidGroupedIntegerPart(const QString& part, QChar separator, int base, int groupSize) { const QStringList groups = part.split(separator, Qt::KeepEmptyParts); if (groups.isEmpty()) return false; for (int i = 0; i < groups.size(); ++i) { const QString& group = groups.at(i); if (group.isEmpty()) return false; const int expectedSize = (i == 0) ? -1 : groupSize; if (expectedSize > 0 && group.size() != expectedSize) return false; if (i == 0 && group.size() > groupSize) return false; for (const QChar ch : group) { if (!isValidDigitForBase(ch, base)) return false; } } return true; } bool canonicalizeLiteralMantissa(const QString& input, int base, int groupingSize, bool allowGroupingHeuristic, QString* output) { const int dotCount = input.count(MathDsl::DotSep); const int commaCount = input.count(MathDsl::CommaSep); if (dotCount == 0 && commaCount == 0) { if (input.isEmpty()) return false; for (const QChar ch : input) { if (!isValidDigitForBase(ch, base)) return false; } *output = input; return true; } QChar radixSep; QChar groupingSep; bool hasRadix = false; if (dotCount > 0 && commaCount > 0) { const int lastDot = input.lastIndexOf(MathDsl::DotSep); const int lastComma = input.lastIndexOf(MathDsl::CommaSep); hasRadix = true; radixSep = (lastDot > lastComma) ? MathDsl::DotSep : MathDsl::CommaSep; groupingSep = (radixSep == MathDsl::DotSep) ? MathDsl::CommaSep : MathDsl::DotSep; if (input.count(radixSep) > 1) return false; } else { const QChar sep = (dotCount > 0) ? MathDsl::DotSep : MathDsl::CommaSep; const int sepCount = input.count(sep); if (sepCount == 1) { const int sepPos = input.indexOf(sep); const QString left = input.left(sepPos); const QString right = input.mid(sepPos + 1); const Settings* settings = Settings::instance(); const QChar configuredDecimalSep(settings->decimalSeparator()); const bool separatorIsConfiguredDecimal = sep == configuredDecimalSep; const bool looksGroupedInteger = allowGroupingHeuristic && !separatorIsConfiguredDecimal && !left.isEmpty() && right.size() == groupingSize && std::all_of(left.cbegin(), left.cend(), [base](QChar ch) { return isValidDigitForBase(ch, base); }) && std::all_of(right.cbegin(), right.cend(), [base](QChar ch) { return isValidDigitForBase(ch, base); }); if (looksGroupedInteger) { hasRadix = false; groupingSep = sep; } else { hasRadix = true; radixSep = sep; } } else { hasRadix = false; groupingSep = sep; if (!isValidGroupedIntegerPart(input, groupingSep, base, groupingSize)) return false; } } if (!hasRadix) { QString integral = input; if (!groupingSep.isNull()) integral.remove(groupingSep); if (integral.isEmpty()) return false; for (const QChar ch : integral) { if (!isValidDigitForBase(ch, base)) return false; } *output = integral; return true; } const int radixPos = input.lastIndexOf(radixSep); if (radixPos <= 0 || radixPos >= input.size() - 1) return false; QString integral = input.left(radixPos); QString fractional = input.mid(radixPos + 1); if (integral.isEmpty() || fractional.isEmpty()) return false; if (!groupingSep.isNull()) { if (!isValidGroupedIntegerPart(integral, groupingSep, base, groupingSize)) return false; integral.remove(groupingSep); fractional.remove(groupingSep); } for (const QChar ch : integral) { if (!isValidDigitForBase(ch, base)) return false; } for (const QChar ch : fractional) { if (!isValidDigitForBase(ch, base)) return false; } *output = integral + MathDsl::DotSep + fractional; return true; } bool canonicalizeStandaloneNumericLiteral(const QString& input, QString* output) { QString trimmed = input.trimmed(); if (trimmed.isEmpty()) return false; QString sign; if (trimmed.startsWith(MathDsl::AddOp)) { trimmed.remove(0, 1); } else if (trimmed.startsWith(MathDsl::SubOpAl1) || trimmed.startsWith(g_minusChar)) { sign = QStringLiteral("-"); trimmed.remove(0, 1); } if (trimmed.isEmpty()) return false; QString mantissa = trimmed; QString exponent; int base = 10; int groupingSize = 3; bool allowGroupingHeuristic = true; QString prefix; if (trimmed.startsWith(MathDsl::HexPrefix, Qt::CaseInsensitive)) { base = 16; groupingSize = 4; allowGroupingHeuristic = false; prefix = trimmed.left(2); mantissa = trimmed.mid(2); } else if (trimmed.startsWith(MathDsl::OctPrefix, Qt::CaseInsensitive)) { base = 8; groupingSize = 3; allowGroupingHeuristic = false; prefix = trimmed.left(2); mantissa = trimmed.mid(2); } else if (trimmed.startsWith(MathDsl::BinPrefix, Qt::CaseInsensitive)) { base = 2; groupingSize = 4; allowGroupingHeuristic = false; prefix = trimmed.left(2); mantissa = trimmed.mid(2); } else { const int exponentPos = mantissa.indexOf(RegExpPatterns::decimalExponentSuffix()); if (exponentPos >= 0) { exponent = mantissa.mid(exponentPos); mantissa = mantissa.left(exponentPos); allowGroupingHeuristic = false; } } if (mantissa.isEmpty()) return false; QString canonicalMantissa; if (!canonicalizeLiteralMantissa(mantissa, base, groupingSize, allowGroupingHeuristic, &canonicalMantissa)) { return false; } QString canonical = sign + prefix + canonicalMantissa + exponent; if (base == 10) { const QByteArray bytes = canonical.toLatin1(); const char* rest = nullptr; const HNumber parsed = HMath::parse_str(bytes.constData(), &rest); if (parsed.isNan() || !rest || *rest != '\0') return false; } *output = canonical; return true; } } // namespace QString NumberFormatter::format(Quantity q) { return format(q, '\0'); } QString NumberFormatter::formatTrigSymbolic(Quantity q) { if (q.isNan()) return QString(); CNumber number = q.numericValue(); number /= q.unit(); if (!number.isNearReal()) return QString(); return formatTrigSymbolicDisplay(q, number.real); } QString NumberFormatter::format(Quantity q, char resultFormatOverride) { Settings* settings = Settings::instance(); return format(q, resultFormatOverride, settings->resultPrecision, settings->complexNumbers, settings->resultComplexForm); } QString NumberFormatter::format(Quantity q, char resultFormatOverride, int precisionOverride, bool useComplexNotation, char complexNotationOverride) { Settings* settings = Settings::instance(); CMath::setImaginaryUnitSymbol(settings->imaginaryUnit); CMath::setPolarAngleUnit(settings->angleUnit); const char activeResultFormat = resultFormatOverride == '\0' ? settings->resultFormat : resultFormatOverride; QString result; Quantity::Format format = q.format(); // Check per-expression rational-display override encoded in format precision. const bool forceRationalDisplay = format.precision == ForcedRationalPrecision; const bool hasExplicitFormatOverride = format.base != Quantity::Format::Base::Null || format.mode != Quantity::Format::Mode::Null; if (((!hasExplicitFormatOverride && activeResultFormat == 'r') || forceRationalDisplay) && format.base != Quantity::Format::Base::Binary && format.base != Quantity::Format::Base::Octal && format.base != Quantity::Format::Base::Hexadecimal && format.mode != Quantity::Format::Mode::Sexagesimal) { result = formatRationalDisplay(q); } if (format.base == Quantity::Format::Base::Null) { switch (activeResultFormat) { case 'b': format.base = Quantity::Format::Base::Binary; break; case 'o': format.base = Quantity::Format::Base::Octal; break; case 'h': format.base = Quantity::Format::Base::Hexadecimal; break; case 'n': case 'f': case 'e': case 'r': case 's': case 'g': default: format.base = Quantity::Format::Base::Decimal; break; } } if (format.mode == Quantity::Format::Mode::Null) { if (format.base == Quantity::Format::Base::Decimal) { switch (activeResultFormat) { case 'n': format.mode = Quantity::Format::Mode::Engineering; break; case 'f': format.mode = Quantity::Format::Mode::Fixed; break; case 'e': format.mode = Quantity::Format::Mode::Scientific; break; case 's': format.mode = Quantity::Format::Mode::Sexagesimal; break; case 'r': case 'g': default: format.mode = Quantity::Format::Mode::General; break; } } else { format.mode = Quantity::Format::Mode::Fixed; } } if (format.precision == Quantity::Format::PrecisionNull) format.precision = precisionOverride; format.removeTrailingZeroes = settings->removeTrailingZeroes; if (format.notation == Quantity::Format::Notation::Null) { if (useComplexNotation) { if (complexNotationOverride == ComplexForm::Rectangular) format.notation = Quantity::Format::Notation::Cartesian; else if (complexNotationOverride == ComplexForm::Exponential) format.notation = Quantity::Format::Notation::Polar; else if (complexNotationOverride == ComplexForm::Trigonometric) format.notation = Quantity::Format::Notation::Trigonometric; else if (complexNotationOverride == ComplexForm::Cis) format.notation = Quantity::Format::Notation::Cis; else if (complexNotationOverride == ComplexForm::Phasor) format.notation = Quantity::Format::Notation::PolarAngle; } } if (format.base == Quantity::Format::Base::Decimal && (format.mode == Quantity::Format::Mode::Scientific || activeResultFormat == 'e')) { if (!q.hasUnit() && !q.isDimensionless()) { q.cleanDimension(); Units::findUnit(q); } useUnprefixedSiUnitForScientificDisplay(&q); } const bool useSexagesimalOutput = format.base == Quantity::Format::Base::Decimal && format.mode == Quantity::Format::Mode::Sexagesimal; bool time = false, arc = q.isDimensionless(); if (useSexagesimalOutput && q.hasDimension()) { auto dimension = q.getDimensionByQuantity(); if (dimension.count() == 1 && dimension.firstKey() == UnitQuantity::Time) { auto iterator = dimension.begin(); if ( iterator->numerator() == 1 && iterator->denominator() == 1) { q.stripUnits(); q.clearDimension(); // remove unit, formatting itself is unit time = true; } } } if (arc && useSexagesimalOutput) { // convert to arcseconds // Sexagesimal angle formatting is unitless "D°M′S″" output. If the // value carries an explicit angle display unit (e.g. [rad]), drop it // before numeric formatting/parsing to avoid contaminating the // intermediate scalar with unit text. q.stripUnits(); if (settings->angleUnit == 'r') q /= Quantity(HMath::pi() / HNumber(180)); else if (settings->angleUnit == 'g') q /= Quantity(HNumber(200) / HNumber(180)); else if (settings->angleUnit == 't' || settings->angleUnit == 'v') q *= Quantity(360); q *= Quantity(3600); } bool negative = false; if (useSexagesimalOutput && q.isNegative()) { q *= Quantity(HNumber(-1)); negative = true; } if (result.isEmpty()) result = DMath::format(q, format); if (useSexagesimalOutput && (arc || time)) { // sexagesimal int dotPos = result.indexOf(MathDsl::DotSep); HNumber seconds(dotPos > 0 ? result.left(dotPos).toStdString().c_str() : result.toStdString().c_str()); HNumber mains = HMath::floor(seconds / HNumber(3600)); seconds -= (mains * HNumber(3600)); HNumber minutes = HMath::floor(seconds / HNumber(60)); seconds -= (minutes * HNumber(60)); HNumber::Format fixed = HNumber::Format::Fixed(); QString sexa = HMath::format(mains, fixed); sexa.append(time ? MathDsl::TimeSep : MathDsl::Deg).append(minutes < 10 ? "0" : "").append(HMath::format(minutes, fixed)); sexa.append(time ? MathDsl::TimeSep : MathDsl::ArcminOp).append(seconds < 10 ? "0" : "").append(HMath::format(seconds, fixed)); if (dotPos > 0) // append decimals sexa.append(result.mid(dotPos)); if (!time) sexa.append(MathDsl::ArcsecOp); result = sexa; } if (negative) result.insert(0, MathDsl::SubOpAl1); if (settings->decimalSeparator() == MathDsl::CommaSep.toLatin1()) result.replace(MathDsl::DotSep, MathDsl::CommaSep); if (q.hasUnit() || !q.isDimensionless()) { bool unitNormalized = false; const int openBracket = result.lastIndexOf(MathDsl::UnitStart); const int closeBracket = result.lastIndexOf(MathDsl::UnitEnd); if (openBracket >= 0 && closeBracket > openBracket && closeBracket == result.size() - 1) { const QString normalizedUnit = UnitDisplayFormat::normalizeUnitTextForDisplay( result.mid(openBracket + 1, closeBracket - openBracket - 1)); result = result.left(openBracket + 1) + normalizedUnit + MathDsl::UnitEnd; unitNormalized = true; } if (!unitNormalized) { const int firstSpace = result.indexOf(QLatin1Char(' ')); const int lastSpace = result.lastIndexOf(QLatin1Char(' ')); int splitSpace = firstSpace; if (firstSpace >= 0 && lastSpace > firstSpace) { const QString between = result.mid(firstSpace + 1, lastSpace - firstSpace - 1).trimmed(); const bool isScientificMantissaTail = (between.startsWith(MathDsl::MulCrossOp) || between.startsWith(MathDsl::MulOpAl1)) && between.contains(QStringLiteral("10")); if (isScientificMantissaTail) splitSpace = lastSpace; } if (splitSpace >= 0 && splitSpace + 1 < result.size()) { const QString normalizedUnit = UnitDisplayFormat::normalizeUnitTextForDisplay(result.mid(splitSpace + 1)); result = result.left(splitSpace) + MathDsl::UnitStart + normalizedUnit + MathDsl::UnitEnd; } } } result.replace(MathDsl::SubOpAl1, g_minusChar); // Replace all spaces between units with dot operator. int emptySpaces = 0; for (auto& ch : result) { if (ch.isSpace()) { ++emptySpaces; if (emptySpaces > 1) ch = g_dotChar; } else { emptySpaces = 0; } } return result; } QList NumberFormatter::digitGroupingPositions(int digitCount, int groupSize, bool fractional) { // Share the grouping boundaries between concrete result text and the // editor's painted separators so both follow the same Number Format. const Settings* settings = Settings::instance(); QList positions; if (!settings->isDigitGroupingEnabled() || groupSize <= 0 || (fractional && settings->digitGroupingIntegerPartOnly)) return positions; if (fractional) { for (int pos = groupSize; pos < digitCount; pos += groupSize) positions.append(pos); } else { const int leadingGroupSize = settings->isIndianDigitGrouping() && groupSize == 3 ? 2 : groupSize; for (int pos = digitCount - groupSize; pos > 0; pos -= leadingGroupSize) positions.prepend(pos); } return positions; } QString NumberFormatter::formatNumericLiteralForDisplay(const QString& input) { const Settings* settings = Settings::instance(); const QString separator = settings->digitGroupingSeparator(); const bool groupingEnabled = settings->isDigitGroupingEnabled() && !separator.isEmpty(); const QChar decimalSep = QChar(settings->decimalSeparator()); const QChar altDecimalSep = (decimalSep == MathDsl::DotSep) ? MathDsl::CommaSep : MathDsl::DotSep; auto groupPart = [&separator](const QString& digits, int groupSize, bool fromRight) { QString result; int start = 0; for (int pos : NumberFormatter::digitGroupingPositions(digits.size(), groupSize, !fromRight)) { result += digits.mid(start, pos - start) + separator; start = pos; } result += digits.mid(start); return result; }; QString output; int lastPos = 0; auto it = RegExpPatterns::numericToken().globalMatch(input); while (it.hasNext()) { const auto match = it.next(); output += input.mid(lastPos, match.capturedStart() - lastPos); QString token = match.captured(0); int prefixLength = 0; int groupSize = 3; if (token.startsWith(MathDsl::HexPrefix, Qt::CaseInsensitive)) { prefixLength = 2; groupSize = 4; } else if (token.startsWith(MathDsl::OctPrefix, Qt::CaseInsensitive)) { prefixLength = 2; groupSize = 3; } else if (token.startsWith(MathDsl::BinPrefix, Qt::CaseInsensitive)) { prefixLength = 2; groupSize = 4; } const QString prefix = token.left(prefixLength); QString body = token.mid(prefixLength); QString exponent; if (prefixLength == 0) { const int exponentPos = body.indexOf(RegExpPatterns::decimalExponentSuffix()); if (exponentPos >= 0) { exponent = body.mid(exponentPos); exponent[0] = QLatin1Char('e'); body = body.left(exponentPos); } } int radixPos = body.lastIndexOf(decimalSep); if (radixPos < 0) radixPos = body.lastIndexOf(altDecimalSep); auto stripGroupingChars = [&](const QString& part) { QString stripped; stripped.reserve(part.size()); for (const QChar c : part) { if (c.isDigit() || c.isLetter()) stripped.append(c); } return stripped; }; if (radixPos >= 0) { const QString integral = stripGroupingChars(body.left(radixPos)); const QString fractional = stripGroupingChars(body.mid(radixPos + 1)); QString groupedFractional = fractional; if (groupingEnabled && !settings->digitGroupingIntegerPartOnly) groupedFractional = groupPart(fractional, groupSize, false); token = prefix + (groupingEnabled ? groupPart(integral, groupSize, true) : integral) + decimalSep + groupedFractional + exponent; } else { const QString integral = stripGroupingChars(body); token = prefix + (groupingEnabled ? groupPart(integral, groupSize, true) : integral) + exponent; } output += token; lastPos = match.capturedEnd(); } output += input.mid(lastPos); return output; } QString NumberFormatter::rewriteScientificNotationForDisplay(const QString& input) { QString output; int lastPos = 0; auto it = RegExpPatterns::numericToken().globalMatch(input); while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); output += input.mid(lastPos, match.capturedStart() - lastPos); const QString token = match.captured(0); QString rewritten = token; if (!token.startsWith(MathDsl::HexPrefix, Qt::CaseInsensitive) && !token.startsWith(MathDsl::OctPrefix, Qt::CaseInsensitive) && !token.startsWith(MathDsl::BinPrefix, Qt::CaseInsensitive)) { const int exponentPos = token.indexOf(RegExpPatterns::decimalExponentSuffix()); if (exponentPos > 0) { const QString mantissa = token.left(exponentPos); QString exponent = token.mid(exponentPos + 1); bool negativeExponent = false; if (!exponent.isEmpty()) { if (exponent.at(0) == MathDsl::AddOp) { exponent.remove(0, 1); } else if (exponent.at(0) == MathDsl::SubOpAl1 || exponent.at(0) == UnicodeChars::MinusSign) { negativeExponent = true; exponent.remove(0, 1); } } QString superscript; if (negativeExponent) superscript += MathDsl::PowNeg; for (const QChar ch : exponent) { const QChar superscriptDigit = MathDsl::asciiDigitToSuperscript(ch); if (superscriptDigit.isNull()) { superscript.clear(); break; } superscript += superscriptDigit; } if (!superscript.isEmpty()) { rewritten = mantissa + QString(MathDsl::MulCrossWrapSp) + MathDsl::MulCrossOp + QString(MathDsl::MulCrossWrapSp) + QStringLiteral("10") + superscript; } } } output += rewritten; lastPos = match.capturedEnd(); } output += input.mid(lastPos); return output; } bool NumberFormatter::tryFormatStandaloneNumericLiteralForDisplay(const QString& input, QString* output) { if (!output) return false; QString canonical; if (!canonicalizeStandaloneNumericLiteral(input, &canonical)) return false; *output = formatNumericLiteralForDisplay(canonical); return true; } heldercorreia-speedcrunch-e7ca37f/src/core/numberformatter.h000066400000000000000000000021171526573132500244420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2013, 2015-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_NUMBERFORMATTER_H #define CORE_NUMBERFORMATTER_H #include "quantity.h" #include #include struct NumberFormatter { static QString format(HNumber &num) { return format(Quantity(num)); } static QString format(CNumber &num) { return format(Quantity(num)); } static QString format(Quantity); static QString format(Quantity, char resultFormatOverride); static QString format(Quantity, char resultFormatOverride, int precisionOverride, bool useComplexNotation, char complexNotationOverride); static QString formatTrigSymbolic(Quantity); static QString formatNumericLiteralForDisplay(const QString& input); static QList digitGroupingPositions(int digitCount, int groupSize, bool fractional); static QString rewriteScientificNotationForDisplay(const QString& input); static bool tryFormatStandaloneNumericLiteralForDisplay(const QString& input, QString* output); }; #endif heldercorreia-speedcrunch-e7ca37f/src/core/opcode.cpp000066400000000000000000000001711526573132500230300ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "opcode.h" heldercorreia-speedcrunch-e7ca37f/src/core/opcode.h000066400000000000000000000014421526573132500224770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_OPCODE_H #define CORE_OPCODE_H #include class Opcode { public: enum Type { Nop, Load, Ref, Function, List, Add, Sub, Neg, BNot, Mul, Div, Pow, Fact, Modulo, IntDiv, LSh, RSh, BAnd, BOr, Conv, Percent, Phasor, UnitRef, Unit }; Type type; unsigned index; // TODO: this is only needed for Conv Op. Maybe refactor this to a smarter place? // TODO: only keep a pointer to the string QString text; Opcode() : type(Nop), index(0) {} Opcode(Type t) : type(t), index(0) {} Opcode(Type t, QString txt) : type(t), index(0), text(txt) {} Opcode(Type t, unsigned i): type(t), index(i) {} }; #endif // CORE_OPCODE_H heldercorreia-speedcrunch-e7ca37f/src/core/pageserver.cpp000066400000000000000000000007421526573132500237260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014, 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/pageserver.h" QString PageServer::getPageContent(const QString& id) { PageMaker maker = m_toc.value(id); if (!maker) return QString(); m_currentPageID = id; return maker(); } QString PageServer::getCurrentPageContent() { if (m_currentPageID.isNull()) return QString(); return getPageContent(m_currentPageID); } heldercorreia-speedcrunch-e7ca37f/src/core/pageserver.h000066400000000000000000000013321526573132500233670ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014, 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_PAGESERVER_H #define CORE_PAGESERVER_H #include #include #include class PageServer : public QObject { Q_OBJECT public: explicit PageServer(QObject* parent = 0) : QObject(parent) { } QString getPageContent(const QString& id); QString getCurrentPageContent(); protected: typedef QString (*PageMaker)(); void addPage(const QString& id, PageMaker maker) { m_toc[id] = maker; } virtual void createPages() = 0; private: Q_DISABLE_COPY(PageServer) QHash m_toc; QString m_currentPageID; }; #endif // CORE_PAGESERVER_H heldercorreia-speedcrunch-e7ca37f/src/core/regexpatterns.h000066400000000000000000000266761526573132500241410ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_REGEXPATTERNS_H #define CORE_REGEXPATTERNS_H #include #include namespace RegExpPatterns { // Matches one standalone numeric token (decimal, hex, octal, or binary). // Example input/output: "x = 0xFF" -> match "0xFF"; "abc123def" -> no standalone match. inline const QRegularExpression& numericToken() { static const QRegularExpression pattern( QStringLiteral("(? match; "1 + 2" -> no match. inline const QRegularExpression& signedNumericLiteralWithSpaces() { static const QRegularExpression pattern( QStringLiteral("^\\s*[+\\-−]?\\s*(?:0[xX][0-9A-Fa-f]+(?:[\\.,][0-9A-Fa-f]+)?|0[oO][0-7]+(?:[\\.,][0-7]+)?|0[bB][01]+(?:[\\.,][01]+)?|\\d+(?:[\\.,]\\d+)?(?:[eE][+\\-−]?\\d+)?)\\s*$")); return pattern; } // Matches an exponent suffix at the end of a decimal literal. // Example input/output: "1.2e-3" -> match "e-3"; "1.2e" -> no match. inline const QRegularExpression& decimalExponentSuffix() { static const QRegularExpression pattern(QStringLiteral("[eE][+\\-−]?\\d+$")); return pattern; } // Matches radix separators accepted by parser helpers ('.' or ','). // Example input/output: "12,34" -> match ","; "1234" -> no match. inline const QRegularExpression& radixSeparator() { static const QRegularExpression pattern(QStringLiteral("[\\.,]")); return pattern; } // Matches any Unicode line-break character handled by the editor/parser. // Example input/output: "a\nb" -> match "\n"; "ab" -> no match. inline const QRegularExpression& lineBreak() { static const QRegularExpression pattern( QStringLiteral("[\\n\\r\\x{0085}\\x{2028}\\x{2029}]") ); return pattern; } // Matches a token separator (characters not allowed in expression tokens). // Example input/output: "a@b" -> match "@"; "a+b" -> no match. inline const QRegularExpression& separatorToken() { static const QRegularExpression pattern( // Match everything that is not alphanumeric or an expression operator. QStringLiteral(R"([^a-zA-Z0-9\+\-\−\*\×·÷\/⧸\^;\(\)\[\]%!=\\&\|<>\?#→\x0000])") ); return pattern; } // Matches a trigonometric function call start, case-insensitive. // Example input/output: "Sin (x)" -> match "Sin ("; "sinh(x)" -> no match. inline const QRegularExpression& trigFunctionCall() { static const QRegularExpression pattern( QStringLiteral(R"(\b(?:sin|cos|tan|cot|sec|csc|cis|arcsin|arccos|arctan|arctan2|radians|degrees|gradians)\s*\()"), QRegularExpression::CaseInsensitiveOption); return pattern; } // Matches a generic function-call start and captures function identifier. // Example input/output: "foo(x)" -> captures "foo"; "1+2" -> no match. inline const QRegularExpression& anyFunctionCall() { static const QRegularExpression pattern( QStringLiteral(R"(\b([\p{L}_][\p{L}\p{N}_]*)\s*\()")); return pattern; } // Matches standalone ASCII "pi" aliases for the Ï€ built-in constant. // Example input/output: "cos(pi)" -> match "pi"; "pixel" -> no match. inline const QRegularExpression& piAliasWord() { static const QRegularExpression pattern( QStringLiteral(R"((? match "e"; "exp" -> no match. inline const QRegularExpression& eAliasWord() { static const QRegularExpression pattern( QStringLiteral(R"((? true; "round" -> false. inline bool isTrigFunctionIdentifier(QStringView identifier) { return identifier.compare(QStringLiteral("sin"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("cos"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("tan"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("cot"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("sec"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("csc"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("cis"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("arcsin"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("arccos"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("arctan"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("arctan2"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("degrees"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("radians"), Qt::CaseInsensitive) == 0 || identifier.compare(QStringLiteral("gradians"), Qt::CaseInsensitive) == 0; } // Matches a full expression that is one plain function call. // Example input/output: " f(x+1) " -> match; "f(x)+g(x)" -> no match. inline const QRegularExpression& trivialSingleFunctionCall() { static const QRegularExpression pattern( // Keep this intentionally strict (ASCII identifier only) so we don't // hide meaningful simplifications like "f²(x)". QStringLiteral("^\\s*[+\\-−]?\\s*[A-Za-z_][A-Za-z0-9_]*\\s*\\(.*\\)\\s*$")); return pattern; } // Matches a full unsigned decimal integer. // Example input/output: "12345" -> match; "-123" -> no match. inline const QRegularExpression& unsignedDecimalInteger() { static const QRegularExpression pattern(QStringLiteral(R"(^\d+$)")); return pattern; } // Matches a full unsigned decimal number (integer or fixed-point). // Example input/output: "12.34" -> match; "+12.34" -> no match. inline const QRegularExpression& unsignedDecimalNumber() { static const QRegularExpression pattern(QStringLiteral(R"(^\d+(?:\.\d+)?$)")); return pattern; } // Matches a full signed decimal number. // Example input/output: "-12.34" -> match; "12e3" -> no match. inline const QRegularExpression& signedDecimalNumber() { static const QRegularExpression pattern(QStringLiteral(R"(^[+\-]?\d+(?:\.\d+)?$)")); return pattern; } // Matches decimals equivalent to integers, capturing whole and fractional parts. // Example input/output: "42.000" -> match groups ("42","000"); "42.01" -> match but not integer-equivalent by itself. inline const QRegularExpression& unsignedIntegerEquivalentDecimal() { static const QRegularExpression pattern(QStringLiteral(R"(^(\d+)\.(\d*)$)")); return pattern; } // Matches a simple unit identifier used by unit-token parsing. // Example input/output: "m2" -> match; "m/s" -> no match. inline const QRegularExpression& simpleUnitIdentifier() { static const QRegularExpression pattern( QStringLiteral("^[A-Za-z_µμΩ°º˚][A-Za-z0-9_µμΩ°º˚]*$")); return pattern; } // Matches a simple quotient whose denominator is a parenthesized expression. // Example input/output: "2/(m s^-1)" -> match; "2/m/s" -> no match. inline const QRegularExpression& simpleParenthesizedDenominatorQuotient() { static const QRegularExpression pattern( QStringLiteral(R"(^\s*[+\-−]?\d+(?:\.\d+)?\s*/\s*\([^()]+\)\s*$)")); return pattern; } // Matches one bracketed unit block like "[kg]" and captures inner text. // Example input/output: "1[kg]" -> match "[kg]" with group "kg". inline const QRegularExpression& unitBrackets() { static const QRegularExpression pattern( QStringLiteral(R"(\[([^\[\]]+)\])")); return pattern; } // Matches one bracketed simple unit identifier and captures the identifier. // Example input/output: "[rev]" -> match with group "rev"; "[kg·m]" -> no match. inline const QRegularExpression& bracketedSimpleUnitIdentifier() { static const QRegularExpression pattern( QStringLiteral(R"(\[\s*([A-Za-z_µμΩ°º˚][A-Za-z0-9_µμΩ°º˚]*)\s*\])")); return pattern; } // Matches bracketed compact-angle unit tokens and captures the inner token. // Example input/output: "1 [arcmin]" -> captures "arcmin"; "1 [′]" -> captures "′". inline const QRegularExpression& compactAngleTokenInBrackets() { static const QRegularExpression pattern( QStringLiteral("\\[\\s*([\\x{00B0}\\x{00BA}\\x{02DA}\\x{2032}\\x{2033}]|deg(?:ree)?|arcmin(?:ute)?|arcsec(?:ond)?)\\s*\\]"), QRegularExpression::CaseInsensitiveOption); return pattern; } // Matches a missing quantity-space before unit bracket. // Example input/output: "1[kg]" -> match "1[" with group "1". inline const QRegularExpression& missingQuantSpBeforeUnit() { static const QRegularExpression pattern( QStringLiteral(R"((\S)\[)")); return pattern; } // Matches value×[unit] style text to normalize as value [unit] in display. // Example input/output: "750 · [h]" -> groups ("0","[h]"); "a · [h]" -> no match. inline const QRegularExpression& valueTimesBracketedUnit() { static const QRegularExpression pattern( QStringLiteral(R"((\d)\s*[*·×]\s*(\[[^\[\]]+\]))")); return pattern; } // Matches text ending in power-of-ten scientific notation: // "*10^n", "× 10^n", or "× 10â�¿". // Example input/output: "1.2 × 10â�»Â³" -> match; "1.2e-3" -> no match. inline const QRegularExpression& trailingPowerOfTenScientificNotation() { static const QRegularExpression pattern( QStringLiteral(R"(.*(?:\*|×)\s*10(?:\^[−-]?\d+|[â�°Â¹Â²Â³â�´â�µâ�¶â�·â�¸â�¹â�»â�º]+)$)")); return pattern; } // Matches the standalone word "summation", case-insensitive. // Example input/output: "summation(k)" -> match; "presummation" -> no match. inline const QRegularExpression& summationWord() { static const QRegularExpression pattern( QStringLiteral(R"((? match; "asqrtb" -> no match. inline const QRegularExpression& sqrtWord() { static const QRegularExpression pattern( QStringLiteral(R"((? match; "mycbrtfn" -> no match. inline const QRegularExpression& cbrtWord() { static const QRegularExpression pattern( QStringLiteral(R"((? full match; "cos(1°)" -> no full match. inline const QRegularExpression& standaloneSexagesimalAngleLiteralAllowed() { static const QRegularExpression pattern( QStringLiteral("^[\\s\\p{Zs}+\\-−0-9\\.,°º˚'′\"″]+$")); return pattern; } // Matches a decimal digit anywhere in the input. // Example input/output: "°′″" -> no match; "1°" -> match. inline const QRegularExpression& anyDigit() { static const QRegularExpression pattern(QStringLiteral("\\d")); return pattern; } } // namespace RegExpPatterns #endif heldercorreia-speedcrunch-e7ca37f/src/core/session.cpp000066400000000000000000000472061526573132500232540ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "session.h" #include "sessionhistory.h" #include "variable.h" #include "evaluator.h" #include "settings.h" #include "sessionjsonkeys.h" #include #include #include #include #include namespace { EvaluationContext currentEvaluationContextFromSettings() { Settings* settings = Settings::instance(); EvaluationContext ctx; ctx.main.fmt = settings->resultFormat; ctx.main.prec = settings->resultPrecision; ctx.main.cplx = settings->resultComplexForm; if (settings->multipleResultLinesEnabled) { if (settings->secondaryResultEnabled) ctx.extras.append(ResultLineContext{settings->alternativeResultFormat, settings->secondaryResultPrecision, settings->secondaryResultComplexForm}); if (settings->tertiaryResultEnabled) ctx.extras.append(ResultLineContext{settings->tertiaryResultFormat, settings->tertiaryResultPrecision, settings->tertiaryResultComplexForm}); if (settings->quaternaryResultEnabled) ctx.extras.append(ResultLineContext{settings->quaternaryResultFormat, settings->quaternaryResultPrecision, settings->quaternaryResultComplexForm}); if (settings->quinaryResultEnabled) ctx.extras.append(ResultLineContext{settings->quinaryResultFormat, settings->quinaryResultPrecision, settings->quinaryResultComplexForm}); } ctx.complexOn = settings->complexNumbers; ctx.unit = settings->imaginaryUnit; ctx.angle = settings->angleUnit; ctx.unitExp = settings->unitNegativeExponentStyle; ctx.round = settings->resultRoundingMode; return ctx; } void applyEvaluationContextToSettings(const EvaluationContext& ctx) { Settings* settings = Settings::instance(); settings->resultFormat = ctx.main.fmt; settings->resultPrecision = ctx.main.prec; settings->resultComplexForm = ctx.main.cplx; settings->multipleResultLinesEnabled = !ctx.extras.isEmpty(); settings->secondaryResultEnabled = false; settings->tertiaryResultEnabled = false; settings->quaternaryResultEnabled = false; settings->quinaryResultEnabled = false; if (ctx.extras.size() > 0) { settings->secondaryResultEnabled = true; settings->alternativeResultFormat = ctx.extras.at(0).fmt; settings->secondaryResultPrecision = ctx.extras.at(0).prec; settings->secondaryResultComplexForm = ctx.extras.at(0).cplx; } if (ctx.extras.size() > 1) { settings->tertiaryResultEnabled = true; settings->tertiaryResultFormat = ctx.extras.at(1).fmt; settings->tertiaryResultPrecision = ctx.extras.at(1).prec; settings->tertiaryResultComplexForm = ctx.extras.at(1).cplx; } if (ctx.extras.size() > 2) { settings->quaternaryResultEnabled = true; settings->quaternaryResultFormat = ctx.extras.at(2).fmt; settings->quaternaryResultPrecision = ctx.extras.at(2).prec; settings->quaternaryResultComplexForm = ctx.extras.at(2).cplx; } if (ctx.extras.size() > 3) { settings->quinaryResultEnabled = true; settings->quinaryResultFormat = ctx.extras.at(3).fmt; settings->quinaryResultPrecision = ctx.extras.at(3).prec; settings->quinaryResultComplexForm = ctx.extras.at(3).cplx; } settings->complexNumbers = ctx.complexOn; settings->imaginaryUnit = (ctx.unit == 'j') ? 'j' : 'i'; settings->angleUnit = ctx.angle; settings->unitNegativeExponentStyle = isValidUnitNegativeExponentStyle(ctx.unitExp) ? ctx.unitExp : Settings::UnitNegativeExponentSuperscript; settings->resultRoundingMode = isValidResultRoundingMode(ctx.round) ? ctx.round : Settings::ResultRoundingHalfAwayFromZero; DMath::complexMode = settings->complexNumbers; CMath::setImaginaryUnitSymbol(settings->imaginaryUnit); setRuntimeUnitNegativeExponentStyle(settings->unitNegativeExponentStyle); setRuntimeResultRoundingMode(settings->resultRoundingMode); } } static void trimHistory(QList& history, int limit) { if (limit == 0 || history.size() <= limit) return; history.remove(0, history.size() - limit); } class SessionSerialization { public: static void serialize(const Session& session, QJsonObject& json); static int deserialize(Session& session, const QJsonObject& json, bool merge); private: static void recoverAns(Session& session); }; void SessionSerialization::serialize(const Session& session, QJsonObject& json) { const QString globalVariableTag = QObject::tr("Global User Variable"); const QString globalFunctionTag = QObject::tr("Global User Function"); const QString globalUnitTag = QObject::tr("Global User Unit"); json[QLatin1String(SessionJsonKeys::Schema)] = QLatin1String(SessionJsonKeys::SchemaDialect); json[QLatin1String(SessionJsonKeys::Id)] = QLatin1String(SessionJsonKeys::SchemaId); json[QLatin1String(SessionJsonKeys::Session)] = session.name().isEmpty() ? QLatin1String(SessionJsonKeys::SessionValueMain) : session.name(); json[QLatin1String(SessionJsonKeys::Limit)] = session.historyLimit(); QJsonArray hist_entries; for (int i = 0; i < session.historySize(); ++i) { QJsonObject curr_entry_obj; session.historyEntryAtRef(i).serialize(curr_entry_obj); hist_entries.append(curr_entry_obj); } json[QLatin1String(SessionJsonKeys::History)] = hist_entries; QJsonArray var_entries; const QList variables = session.variablesToList(); for (const Variable& variable : variables) { QJsonObject curr_entry_obj; if (variable.type() == Variable::BuiltIn && variable.identifier() != QLatin1String("ans")) continue; if (variable.description().contains(globalVariableTag)) continue; variable.serialize(curr_entry_obj); var_entries.append(curr_entry_obj); } json[QLatin1String(SessionJsonKeys::Variables)] = var_entries; QJsonArray func_entries; const QList functions = session.UserFunctionsToList(); for (const UserFunction& function : functions) { QJsonObject curr_entry_obj; if (function.description().contains(globalFunctionTag)) continue; function.serialize(curr_entry_obj); func_entries.append(curr_entry_obj); } json[QLatin1String(SessionJsonKeys::Functions)] = func_entries; QJsonArray unit_entries; const QList units = session.userUnitsToList(); for (const UserUnit& unit : units) { QJsonObject curr_entry_obj; if (unit.description().contains(globalUnitTag)) continue; unit.serialize(curr_entry_obj); unit_entries.append(curr_entry_obj); } json[QLatin1String(SessionJsonKeys::Units)] = unit_entries; QJsonArray globals; const QStringList definitions = Settings::instance()->startupUserDefinitions.split(QLatin1Char('\n')); for (const QString& line : definitions) { const QString trimmed = line.trimmed(); if (!trimmed.isEmpty()) globals.append(trimmed); } json[QLatin1String(SessionJsonKeys::Globals)] = globals; } int SessionSerialization::deserialize(Session& session, const QJsonObject& json, bool merge) { auto hasType = [&json](const char* key, bool (QJsonValue::*predicate)() const) { const QJsonValue value = json.value(QLatin1String(key)); return value.isUndefined() || (value.*predicate)(); }; auto arrayContainsOnlyObjects = [&json](const char* key) { const QJsonValue value = json.value(QLatin1String(key)); if (value.isUndefined()) return true; if (!value.isArray()) return false; const QJsonArray array = value.toArray(); for (const QJsonValue& entry : array) { if (!entry.isObject()) return false; } return true; }; if (json.isEmpty()) return false; const QJsonValue schema = json.value(QLatin1String(SessionJsonKeys::Schema)); if (!schema.isString() || schema.toString() != QLatin1String(SessionJsonKeys::SchemaDialect)) return false; const QJsonValue id = json.value(QLatin1String(SessionJsonKeys::Id)); if (!id.isString() || id.toString() != QLatin1String(SessionJsonKeys::SchemaId)) return false; if (json.contains(QLatin1String("scheme"))) return false; if (!hasType(SessionJsonKeys::Session, &QJsonValue::isString) || !hasType(SessionJsonKeys::Limit, &QJsonValue::isDouble) || !hasType(SessionJsonKeys::History, &QJsonValue::isArray) || !hasType(SessionJsonKeys::Variables, &QJsonValue::isArray) || !hasType(SessionJsonKeys::Functions, &QJsonValue::isArray) || !hasType(SessionJsonKeys::Units, &QJsonValue::isArray) || !hasType(SessionJsonKeys::Globals, &QJsonValue::isArray) || !arrayContainsOnlyObjects(SessionJsonKeys::History) || !arrayContainsOnlyObjects(SessionJsonKeys::Variables) || !arrayContainsOnlyObjects(SessionJsonKeys::Functions) || !arrayContainsOnlyObjects(SessionJsonKeys::Units)) { return false; } if (!merge) { session.clearHistory(); session.clearVariables(); session.clearUserFunctions(); session.clearUserUnits(); session.setEditorText(QString()); } if (!merge) session.setName(json[QLatin1String(SessionJsonKeys::Session)].toString()); if (json.contains(QLatin1String(SessionJsonKeys::Limit))) session.setHistoryLimit(json[QLatin1String(SessionJsonKeys::Limit)].toInt(1000)); session.evaluator()->initializeBuiltInVariables(); QJsonArray hist_obj = json[QLatin1String(SessionJsonKeys::History)].toArray(); int n = hist_obj.size(); const int limit = session.historyLimit(); const int firstHistoryIndex = limit > 0 ? std::max(0, n - limit) : 0; for (int i = firstHistoryIndex; i < n; ++i) session.addHistoryEntry(HistoryEntry(hist_obj[i].toObject())); QJsonArray var_obj = json[QLatin1String(SessionJsonKeys::Variables)].toArray(); n = var_obj.size(); for (int i = 0; i < n; ++i) { QJsonObject var = var_obj[i].toObject(); Variable variable; variable.deSerialize(var); session.addVariable(variable); } QJsonArray func_obj = json[QLatin1String(SessionJsonKeys::Functions)].toArray(); n = func_obj.size(); for (int i = 0; i < n; ++i) { UserFunction func(func_obj[i].toObject()); session.addUserFunction(func); } if (json.contains(QLatin1String(SessionJsonKeys::Units))) { QJsonArray unit_obj = json[QLatin1String(SessionJsonKeys::Units)].toArray(); const int unitCount = unit_obj.size(); for (int i = 0; i < unitCount; ++i) { UserUnit unit(unit_obj[i].toObject()); session.addUserUnit(unit); } } if (!merge && json.contains(QLatin1String(SessionJsonKeys::Globals))) { const QJsonArray globalsObj = json[QLatin1String(SessionJsonKeys::Globals)].toArray(); QStringList lines; lines.reserve(globalsObj.size()); for (const QJsonValue& value : globalsObj) { if (value.isString() && !value.toString().trimmed().isEmpty()) lines.append(value.toString().trimmed()); } if (!lines.isEmpty() && Settings::instance()->startupUserDefinitions.trimmed().isEmpty()) Settings::instance()->startupUserDefinitions = lines.join(QLatin1Char('\n')); } recoverAns(session); return true; } void SessionSerialization::recoverAns(Session& session) { const EvaluationContext originalContext = currentEvaluationContextFromSettings(); const bool hasAns = session.hasVariable("ans"); const bool hasContextHistory = session.historySize() > 0 && session.historyEntryAtRef(0).hasContext(); const bool needsAnsRecovery = hasContextHistory || !hasAns || session.getVariable("ans").value().isNan(); if (!needsAnsRecovery) return; Quantity recoveredValue = CMath::nan(); for (int i = session.historySize() - 1; i >= 0; --i) { const Quantity value = session.historyEntryAtRef(i).result(); if (!value.isNan()) { recoveredValue = value; break; } } if (recoveredValue.isNan() && hasContextHistory) { Evaluator* evaluator = session.evaluator(); for (int i = 0; i < session.historySize(); ++i) { const HistoryEntry entry = session.historyEntryAtRef(i); applyEvaluationContextToSettings(entry.contextRef()); evaluator->setExpression(evaluator->autoFix(entry.expr())); const Quantity value = evaluator->evalUpdateAns(); if (evaluator->error().isEmpty() && !value.isNan()) recoveredValue = value; } applyEvaluationContextToSettings(originalContext); } if (!recoveredValue.isNan()) session.addVariable(Variable("ans", recoveredValue, Variable::BuiltIn)); } Session::Session() : m_evaluator(new Evaluator) , m_name(QLatin1String(SessionJsonKeys::SessionValueMain)) { bindEvaluator(); } Session::Session(QJsonObject& json) : Session() { deSerialize(json, false); } Session::Session(const Session& other) : m_history(other.m_history) , m_historyHead(other.m_historyHead) , m_evaluator(new Evaluator) , m_name(other.m_name) , m_editorText(other.m_editorText) , m_private(other.m_private) , m_historyLimit(other.m_historyLimit) { bindEvaluator(); m_evaluator->copySymbolContextFrom(*other.m_evaluator); } Session& Session::operator=(const Session& other) { if (this == &other) return *this; m_history = other.m_history; m_historyHead = other.m_historyHead; m_name = other.m_name; m_editorText = other.m_editorText; m_private = other.m_private; m_historyLimit = other.m_historyLimit; bindEvaluator(); m_evaluator->copySymbolContextFrom(*other.m_evaluator); return *this; } Session::~Session() = default; void Session::bindEvaluator() { if (!m_evaluator) m_evaluator.reset(new Evaluator); m_evaluator->initializeBuiltInVariables(); } int Session::physicalHistoryIndex(int logicalIndex) const { const int size = m_history.size(); if (size == 0) return -1; return (m_historyHead + logicalIndex) % size; } void Session::normalizeHistoryOrder() { if (m_historyHead == 0 || m_history.isEmpty()) return; History normalized; normalized.reserve(m_history.size()); for (int i = 0; i < m_history.size(); ++i) normalized.append(m_history.at(physicalHistoryIndex(i))); m_history.swap(normalized); m_historyHead = 0; } void Session::serialize(QJsonObject &json) const { SessionSerialization::serialize(*this, json); } int Session::deSerialize(const QJsonObject &json, bool merge=false) { StartupDiagnostics::Scope timing("Deserialize session"); return SessionSerialization::deserialize(*this, json, merge); } void Session::setName(const QString& name) { const QString trimmed = name.trimmed(); m_name = trimmed.isEmpty() ? QLatin1String(SessionJsonKeys::SessionValueMain) : trimmed; } void Session::setHistoryLimit(int limit) { m_historyLimit = std::max(0, limit); applyHistoryLimit(); } void Session::addVariable(const Variable &var) { evaluator()->symbolContext().variables().add(var); } bool Session::hasVariable(const QString &id) const { return evaluator()->symbolContext().variables().contains(id); } void Session::removeVariable(const QString &id) { evaluator()->symbolContext().variables().remove(id); } void Session::clearVariables() { evaluator()->symbolContext().variables().clear(); } Variable Session::getVariable(const QString &id) const { return evaluator()->symbolContext().variables().get(id); } QList Session::variablesToList() const { return evaluator()->symbolContext().variables().toList(); } bool Session::isBuiltInVariable(const QString & id) const { // Defining variables with the same name as existing functions is not supported for now. if(FunctionRepo::instance()->find(id)) return true; if(!hasVariable(id)) return false; return getVariable(id).type() == Variable::BuiltIn; } void Session::addHistoryEntry(const HistoryEntry &entry) { const int limit = historyLimit(); if (limit > 0) { if (m_history.size() < limit) { m_history.append(entry); } else if (limit > 0) { m_history[m_historyHead] = entry; m_historyHead = (m_historyHead + 1) % limit; } return; } m_history.append(entry); } bool Session::nextHistoryEntryReachesLimit() const { const int limit = historyLimit(); return limit > 0 && m_history.size() == limit - 1; } void Session::insertHistoryEntry(const int index, const HistoryEntry &entry) { normalizeHistoryOrder(); m_history.insert(index, entry); trimHistory(m_history, historyLimit()); } void Session::removeHistoryEntryAt(const int index) { normalizeHistoryOrder(); m_history.removeAt(index); } const HistoryEntry& Session::historyEntryAtRef(const int index) const { return m_history.at(physicalHistoryIndex(index)); } HistoryEntry Session::historyEntryAt(const int index) const { return historyEntryAtRef(index); } QList Session::historyToList() const { if (m_historyHead == 0) return m_history; QList ordered; ordered.reserve(m_history.size()); for (int i = 0; i < m_history.size(); ++i) ordered.append(historyEntryAtRef(i)); return ordered; } void Session::applyHistoryLimit() { normalizeHistoryOrder(); trimHistory(m_history, historyLimit()); } void Session::clearHistory() { m_history.clear(); m_historyHead = 0; } void Session::addUserFunction(const UserFunction &func) { if(func.opcodes.isEmpty()) { // We need to compile the function, so pretend the user typed it. QString expression = func.name() + "(" + func.arguments().join(";") + ")=" + func.expression(); if (!func.description().isEmpty()) expression += " ? " + func.description(); evaluator()->setExpression(expression); evaluator()->eval(); } else { evaluator()->symbolContext().functions().add(func); } } void Session::removeUserFunction(const QString &str) { evaluator()->symbolContext().functions().remove(str); } void Session::clearUserFunctions() { evaluator()->symbolContext().functions().clear(); } bool Session::hasUserFunction(const QString &str) const { return evaluator()->symbolContext().functions().contains(str); } QList Session::UserFunctionsToList() const { return evaluator()->symbolContext().functions().toList(); } const UserFunction * Session::getUserFunction(const QString &fname) const { return evaluator()->symbolContext().functions().get(fname); } void Session::addUserUnit(const UserUnit& unit) { const QString name = unit.name(); if (name.isEmpty()) return; evaluator()->symbolContext().units().add(unit); } void Session::removeUserUnit(const QString& name) { evaluator()->symbolContext().units().remove(name); } void Session::clearUserUnits() { evaluator()->symbolContext().units().clear(); } bool Session::hasUserUnit(const QString& name) const { return evaluator()->symbolContext().units().contains(name); } QList Session::userUnitsToList() const { return evaluator()->symbolContext().units().toList(); } const UserUnit* Session::getUserUnit(const QString& name) const { return evaluator()->symbolContext().units().get(name); } heldercorreia-speedcrunch-e7ca37f/src/core/session.h000066400000000000000000000061151526573132500227130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_SESSION_H #define CORE_SESSION_H #include "hmath.h" #include "sessionhistory.h" #include "variable.h" #include "userfunction.h" #include "userunit.h" #include #include #include #include class Evaluator; class Session { private: typedef QList History ; History m_history; int m_historyHead = 0; // Logical index 0 maps to physical m_historyHead. std::unique_ptr m_evaluator; QString m_name; QString m_editorText; bool m_private = false; int m_historyLimit = 1000; // 0: unlimited. int physicalHistoryIndex(int logicalIndex) const; void normalizeHistoryOrder(); void bindEvaluator(); public: Session(); Session(QJsonObject & json); Session(const Session& other); Session& operator=(const Session& other); ~Session(); Evaluator* evaluator() { return m_evaluator.get(); } const Evaluator* evaluator() const { return m_evaluator.get(); } void load(); void save(); void serialize(QJsonObject &json) const; int deSerialize(const QJsonObject & json, bool merge); QString name() const { return m_name; } void setName(const QString& name); bool isPrivate() const { return m_private; } void setPrivate(bool value) { m_private = value; } QString editorText() const { return m_editorText; } void setEditorText(const QString& text) { m_editorText = text; } int historyLimit() const { return m_historyLimit; } void setHistoryLimit(int limit); void addVariable(const Variable & var); bool hasVariable(const QString & id) const; void removeVariable(const QString & id); void clearVariables(); Variable getVariable(const QString & id) const; QList variablesToList() const; bool isBuiltInVariable(const QString &id) const; void addHistoryEntry(const HistoryEntry & entry); bool nextHistoryEntryReachesLimit() const; void insertHistoryEntry(const int index, const HistoryEntry & entry); void removeHistoryEntryAt(const int index); int historySize() const { return m_history.size(); } bool historyIsEmpty() const { return m_history.isEmpty(); } const HistoryEntry& historyEntryAtRef(const int index) const; HistoryEntry historyEntryAt(const int index) const; QList historyToList() const; void applyHistoryLimit(); void clearHistory(); void addUserFunction(const UserFunction & func); void removeUserFunction(const QString & str); void clearUserFunctions(); bool hasUserFunction(const QString & str) const; QList UserFunctionsToList() const; const UserFunction * getUserFunction(const QString & fname) const; void addUserUnit(const UserUnit& unit); void removeUserUnit(const QString& name); void clearUserUnits(); bool hasUserUnit(const QString& name) const; QList userUnitsToList() const; const UserUnit* getUserUnit(const QString& name) const; }; #endif // CORE_SESSION_H heldercorreia-speedcrunch-e7ca37f/src/core/sessionhistory.cpp000066400000000000000000000247171526573132500247000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "sessionhistory.h" #include "core/complexform.h" #include "core/settings.h" #include "core/sessionjsonkeys.h" #include "math/cmath.h" #include namespace { EvaluationContext contextFromCurrentSettings() { Settings* settings = Settings::instance(); EvaluationContext ctx; ctx.main.fmt = settings->resultFormat; ctx.main.prec = settings->resultPrecision; ctx.main.cplx = settings->resultComplexForm; if (settings->multipleResultLinesEnabled) { if (settings->secondaryResultEnabled) ctx.extras.append(ResultLineContext{settings->alternativeResultFormat, settings->secondaryResultPrecision, settings->secondaryResultComplexForm}); if (settings->tertiaryResultEnabled) ctx.extras.append(ResultLineContext{settings->tertiaryResultFormat, settings->tertiaryResultPrecision, settings->tertiaryResultComplexForm}); if (settings->quaternaryResultEnabled) ctx.extras.append(ResultLineContext{settings->quaternaryResultFormat, settings->quaternaryResultPrecision, settings->quaternaryResultComplexForm}); if (settings->quinaryResultEnabled) ctx.extras.append(ResultLineContext{settings->quinaryResultFormat, settings->quinaryResultPrecision, settings->quinaryResultComplexForm}); } ctx.complexOn = settings->complexNumbers; ctx.unit = settings->imaginaryUnit; ctx.angle = settings->angleUnit; ctx.unitExp = settings->unitNegativeExponentStyle; ctx.round = settings->resultRoundingMode; return ctx; } QJsonObject serializeResultLineContext(const ResultLineContext& line) { QJsonObject json; json[QLatin1String(SessionJsonKeys::EvaluationContext::Line::Notation)] = QString(QChar(line.fmt)); json[QLatin1String(SessionJsonKeys::EvaluationContext::Line::Precision)] = line.prec; json[QLatin1String(SessionJsonKeys::EvaluationContext::Line::ComplexFormat)] = ComplexForm::toString(line.cplx); return json; } ResultLineContext deserializeResultLineContext(const QJsonObject& json) { ResultLineContext line; const QString fmt = json[QLatin1String(SessionJsonKeys::EvaluationContext::Line::Notation)].toString(); if (fmt.size() == 1) line.fmt = fmt.at(0).toLatin1(); line.prec = json[QLatin1String(SessionJsonKeys::EvaluationContext::Line::Precision)].toInt(-1); line.cplx = ComplexForm::fromString( json[QLatin1String(SessionJsonKeys::EvaluationContext::Line::ComplexFormat)].toString()); return line; } qint64 currentEditTimestampMs() { return QDateTime::currentMSecsSinceEpoch(); } } void EvaluationContext::serialize(QJsonObject& json) const { QJsonObject lines; lines[QLatin1String(SessionJsonKeys::EvaluationContext::MainLine)] = serializeResultLineContext(main); QJsonArray extrasArray; for (const ResultLineContext& line : extras) extrasArray.append(serializeResultLineContext(line)); lines[QLatin1String(SessionJsonKeys::EvaluationContext::ExtraLines)] = extrasArray; json[QLatin1String(SessionJsonKeys::EvaluationContext::Lines)] = lines; if (!complexOn) json[QLatin1String(SessionJsonKeys::EvaluationContext::Complex)] = QLatin1String(SessionJsonKeys::EvaluationContext::ComplexValues::Off); else json[QLatin1String(SessionJsonKeys::EvaluationContext::Complex)] = (unit == 'j') ? QLatin1String(SessionJsonKeys::EvaluationContext::ComplexValues::J) : QLatin1String(SessionJsonKeys::EvaluationContext::ComplexValues::I); json[QLatin1String(SessionJsonKeys::EvaluationContext::Angle)] = QString(QChar(angle)); json[QLatin1String(SessionJsonKeys::EvaluationContext::UnitExponentStyle)] = QString(QChar(unitExp)); json[QLatin1String(SessionJsonKeys::EvaluationContext::Rounding)] = QString(QChar(round)); } void EvaluationContext::deSerialize(const QJsonObject& json) { *this = EvaluationContext(); const QJsonObject lines = json[QLatin1String(SessionJsonKeys::EvaluationContext::Lines)].toObject(); if (lines.contains(QLatin1String(SessionJsonKeys::EvaluationContext::MainLine))) main = deserializeResultLineContext(lines[QLatin1String(SessionJsonKeys::EvaluationContext::MainLine)].toObject()); const QJsonArray extrasArray = lines[QLatin1String(SessionJsonKeys::EvaluationContext::ExtraLines)].toArray(); for (const QJsonValue& value : extrasArray) { if (value.isObject()) extras.append(deserializeResultLineContext(value.toObject())); } while (extras.size() > 4) extras.removeLast(); const QString complexText = json[QLatin1String(SessionJsonKeys::EvaluationContext::Complex)].toString(); if (complexText == QLatin1String(SessionJsonKeys::EvaluationContext::ComplexValues::J)) { complexOn = true; unit = 'j'; } else if (complexText == QLatin1String(SessionJsonKeys::EvaluationContext::ComplexValues::I)) { complexOn = true; unit = 'i'; } else { complexOn = false; unit = 'i'; } const QString angleText = json[QLatin1String(SessionJsonKeys::EvaluationContext::Angle)].toString(); if (angleText.size() == 1) angle = angleText.at(0).toLatin1(); const QString unitExpText = json[QLatin1String(SessionJsonKeys::EvaluationContext::UnitExponentStyle)].toString(); if (unitExpText.size() == 1) unitExp = unitExpText.at(0).toLatin1(); if (!isValidUnitNegativeExponentStyle(unitExp)) unitExp = Settings::UnitNegativeExponentSuperscript; const QString roundText = json[QLatin1String(SessionJsonKeys::EvaluationContext::Rounding)].toString(); if (roundText.size() == 1) round = roundText.at(0).toLatin1(); if (!isValidResultRoundingMode(round)) round = Settings::ResultRoundingHalfAwayFromZero; } HistoryEntry::HistoryEntry(const QJsonObject & json) { deSerialize(json); } HistoryEntry::HistoryEntry(const QString & expr, const Quantity & num) : m_expr(expr), m_result(num), m_ctx(contextFromCurrentSettings()), m_hasCtx(true), m_editTimestamp(currentEditTimestampMs()) { } HistoryEntry::HistoryEntry(const QString & expr, const Quantity & num, const QString& interpretedExpr) : m_expr(expr), m_interpretedExpr(interpretedExpr), m_result(num), m_ctx(contextFromCurrentSettings()), m_hasCtx(true), m_editTimestamp(currentEditTimestampMs()) { } HistoryEntry::HistoryEntry(const QString & expr, const EvaluationContext& ctx) : m_expr(expr), m_result(0), m_ctx(ctx), m_hasCtx(true), m_editTimestamp(currentEditTimestampMs()) { } HistoryEntry::HistoryEntry(const QString & expr, const Quantity & num, const QString& interpretedExpr, const EvaluationContext& ctx) : m_expr(expr), m_interpretedExpr(interpretedExpr), m_result(num), m_ctx(ctx), m_hasCtx(true), m_editTimestamp(currentEditTimestampMs()) { } QString HistoryEntry::expr() const { return m_expr; } Quantity HistoryEntry::result() const { return m_result; } QString HistoryEntry::interpretedExpr() const { return m_interpretedExpr; } void HistoryEntry::setExpr(const QString & e) { m_expr = e; m_editTimestamp = currentEditTimestampMs(); } void HistoryEntry::setInterpretedExpr(const QString& e) { m_interpretedExpr = e; } void HistoryEntry::setResult(const Quantity & n) { m_result = n; } void HistoryEntry::setContext(const EvaluationContext& ctx) { m_ctx = ctx; m_editTimestamp = currentEditTimestampMs(); } void HistoryEntry::setRenderedLines(const QStringList& lines) { m_renderedLines = lines; } void HistoryEntry::setEditTimestamp(qint64 timestamp) { m_editTimestamp = timestamp; } void HistoryEntry::serialize(QJsonObject & json) const { json[QLatin1String(SessionJsonKeys::HistoryEntry::Expression)] = m_expr; json[QLatin1String(SessionJsonKeys::HistoryEntry::InterpretedExpression)] = m_interpretedExpr; QJsonObject result; m_result.serialize(result); json[QLatin1String(SessionJsonKeys::HistoryEntry::Result)] = result; QJsonObject ctx; m_ctx.serialize(ctx); json[QLatin1String(SessionJsonKeys::HistoryEntry::Context)] = ctx; json[QLatin1String(SessionJsonKeys::HistoryEntry::EditTimestamp)] = m_editTimestamp; if (!m_renderedLines.isEmpty()) { QJsonArray renderedLines; for (const QString& line : m_renderedLines) renderedLines.append(line); json[QLatin1String(SessionJsonKeys::HistoryEntry::PrintedLines)] = renderedLines; } } void HistoryEntry::deSerialize(const QJsonObject & json) { *this = HistoryEntry(); m_result = CMath::nan(); if (json.contains(QLatin1String(SessionJsonKeys::HistoryEntry::Expression))) m_expr = json[QLatin1String(SessionJsonKeys::HistoryEntry::Expression)].toString(); if (json.contains(QLatin1String(SessionJsonKeys::HistoryEntry::InterpretedExpression))) m_interpretedExpr = json[QLatin1String(SessionJsonKeys::HistoryEntry::InterpretedExpression)].toString(); if (json.contains(QLatin1String(SessionJsonKeys::HistoryEntry::Result)) && json[QLatin1String(SessionJsonKeys::HistoryEntry::Result)].isObject()) m_result = Quantity::deSerialize(json[QLatin1String(SessionJsonKeys::HistoryEntry::Result)].toObject()); if (json.contains(QLatin1String(SessionJsonKeys::HistoryEntry::Context))) { m_ctx.deSerialize(json[QLatin1String(SessionJsonKeys::HistoryEntry::Context)].toObject()); m_hasCtx = true; } if (json.contains(QLatin1String(SessionJsonKeys::HistoryEntry::EditTimestamp))) m_editTimestamp = json[QLatin1String(SessionJsonKeys::HistoryEntry::EditTimestamp)].toVariant().toLongLong(); else m_editTimestamp = currentEditTimestampMs(); if (json.contains(QLatin1String(SessionJsonKeys::HistoryEntry::PrintedLines))) { const QJsonArray renderedLines = json[QLatin1String(SessionJsonKeys::HistoryEntry::PrintedLines)].toArray(); for (const QJsonValue& value : renderedLines) { if (value.isString()) m_renderedLines.append(value.toString()); } } } EvaluationContext HistoryEntry::context() const { return m_ctx; } const EvaluationContext& HistoryEntry::contextRef() const { return m_ctx; } bool HistoryEntry::hasContext() const { return m_hasCtx; } QStringList HistoryEntry::renderedLines() const { return m_renderedLines; } bool HistoryEntry::hasRenderedLines() const { return !m_renderedLines.isEmpty(); } qint64 HistoryEntry::editTimestamp() const { return m_editTimestamp; } heldercorreia-speedcrunch-e7ca37f/src/core/sessionhistory.h000066400000000000000000000047531526573132500243430ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_SESSIONHISTORY_H #define CORE_SESSIONHISTORY_H #include #include #include #include #include #include #include "core/complexform.h" #include "math/quantity.h" struct ResultLineContext { char fmt = 'g'; int prec = -1; char cplx = ComplexForm::Default; }; struct EvaluationContext { ResultLineContext main; QVector extras; bool complexOn = false; char unit = 'i'; char angle = 'r'; char unitExp = 's'; char round = 'a'; void serialize(QJsonObject& json) const; void deSerialize(const QJsonObject& json); }; class HistoryEntry { private: QString m_expr; QString m_interpretedExpr; Quantity m_result; EvaluationContext m_ctx; bool m_hasCtx = false; QStringList m_renderedLines; qint64 m_editTimestamp = 0; public: HistoryEntry() : m_expr(""), m_result(0) {} HistoryEntry(const QJsonObject & json); HistoryEntry(const QString & expr, const Quantity & num); HistoryEntry(const QString & expr, const Quantity & num, const QString& interpretedExpr); HistoryEntry(const QString & expr, const EvaluationContext& ctx); HistoryEntry(const QString & expr, const Quantity & num, const QString& interpretedExpr, const EvaluationContext& ctx); HistoryEntry(const HistoryEntry & other) : m_expr(other.m_expr), m_interpretedExpr(other.m_interpretedExpr), m_result(other.m_result), m_ctx(other.m_ctx), m_hasCtx(other.m_hasCtx), m_renderedLines(other.m_renderedLines), m_editTimestamp(other.m_editTimestamp) {} HistoryEntry& operator=(const HistoryEntry& other) = default; void setExpr(const QString & e); void setInterpretedExpr(const QString& e); void setResult(const Quantity & n); void setContext(const EvaluationContext& ctx); void setRenderedLines(const QStringList& lines); void setEditTimestamp(qint64 timestamp); QString expr() const; QString interpretedExpr() const; Quantity result() const; EvaluationContext context() const; const EvaluationContext& contextRef() const; bool hasContext() const; QStringList renderedLines() const; bool hasRenderedLines() const; qint64 editTimestamp() const; void serialize(QJsonObject & json) const; void deSerialize(const QJsonObject & json); }; #endif // CORE_SESSIONHISTORY_H heldercorreia-speedcrunch-e7ca37f/src/core/sessionjsonkeys.h000066400000000000000000000204131526573132500244760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later /* { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/session-v1.schema.json", "title": "SpeedCrunch Session", "type": "object", "required": ["$schema", "$id", "session", "limit", "history", "variables", "functions", "units", "globals"], "additionalProperties": false, "properties": { "$schema": { "const": "https://json-schema.org/draft/2020-12/schema", "description": "JSON Schema dialect identifier" }, "$id": { "const": "https://speedcrunch.org/schemas/session-v1.schema.json", "description": "Session schema identifier" }, "session": { "type": "string", "minLength": 1 }, "limit": { "type": "integer", "minimum": 0, "description": "Maximum stored history entries for this session; 0 means unlimited." }, "history": { "type": "array", "items": { "$ref": "#/$defs/historyEntry" } }, "variables": { "type": "array", "items": { "$ref": "#/$defs/variable" } }, "functions": { "type": "array", "items": { "$ref": "#/$defs/userFunction" } }, "units": { "type": "array", "items": { "$ref": "#/$defs/userUnit" } }, "globals": { "type": "array", "items": { "type": "string" } } }, "$defs": { "historyEntry": { "type": "object", "required": ["xpr", "itp", "rst", "ctx", "edt"], "additionalProperties": false, "properties": { "xpr": { "type": "string" }, "itp": { "type": "string" }, "rst": { "$ref": "#/$defs/quantity" }, "ctx": { "$ref": "#/$defs/evaluationContext" }, "edt": { "type": "integer" }, "prt": { "type": "array", "items": { "type": "string" } } } }, "evaluationContext": { "type": "object", "required": ["lns", "cpx", "ang", "uxp", "rnd"], "additionalProperties": false, "properties": { "lns": { "type": "object", "required": ["main", "ext"], "additionalProperties": false, "properties": { "main": { "$ref": "#/$defs/resultLineContext" }, "ext": { "type": "array", "maxItems": 4, "items": { "$ref": "#/$defs/resultLineContext" } } } }, "cpx": { "type": "string", "enum": ["off", "i", "j"] }, "ang": { "type": "string", "minLength": 1, "maxLength": 1 }, "uxp": { "type": "string", "minLength": 1, "maxLength": 1 }, "rnd": { "type": "string", "minLength": 1, "maxLength": 1 } } }, "resultLineContext": { "type": "object", "required": ["ntn", "prc", "cpx"], "additionalProperties": false, "properties": { "ntn": { "type": "string", "minLength": 1, "maxLength": 1 }, "prc": { "type": "integer" }, "cpx": { "type": "string", "minLength": 1, "maxLength": 1 } } }, "variable": { "type": "object", "required": ["id", "qty"], "additionalProperties": false, "properties": { "id": { "type": "string" }, "qty": { "$ref": "#/$defs/quantity" }, "dsc": { "type": "string" } } }, "userFunction": { "type": "object", "required": ["id", "args", "xpr"], "additionalProperties": false, "properties": { "id": { "type": "string" }, "args": { "type": "array", "items": { "type": "string" } }, "xpr": { "type": "string" }, "itp": { "type": "string" }, "dsc": { "type": "string" }, "opcodes": { "type": "array", "items": { "$ref": "#/$defs/opcode" } }, "constants": { "type": "array", "items": { "$ref": "#/$defs/cNumber" } }, "identifiers": { "type": "array", "items": { "type": "string" } } } }, "opcode": { "type": "object", "required": ["t", "i"], "additionalProperties": false, "properties": { "t": { "type": "integer" }, "i": { "type": "integer" }, "text": { "type": "string" } } }, "userUnit": { "type": "object", "required": ["id", "qty"], "additionalProperties": false, "properties": { "id": { "type": "string" }, "qty": { "$ref": "#/$defs/quantity" }, "xpr": { "type": "string" }, "itp": { "type": "string" }, "dsc": { "type": "string" } } }, "quantity": { "type": "object", "required": ["val"], "additionalProperties": true, "properties": { "val": { "type": "string" }, "dim": { "type": "object", "additionalProperties": { "type": "string" } }, "unit": { "type": "object", "additionalProperties": true }, "unit_name": { "type": "string" }, "format": { "type": "object", "additionalProperties": true } } }, "cNumber": { "type": "object", "required": ["value"], "additionalProperties": true, "properties": { "value": { "type": "string" } } } } } */ #ifndef CORE_SESSIONJSONKEYS_H #define CORE_SESSIONJSONKEYS_H namespace SessionJsonKeys { inline constexpr const char* Schema = "$schema"; inline constexpr const char* SchemaDialect = "https://json-schema.org/draft/2020-12/schema"; inline constexpr const char* Id = "$id"; inline constexpr const char* SchemaId = "https://speedcrunch.org/schemas/session-v1.schema.json"; inline constexpr const char* Session = "session"; inline constexpr const char* SessionValueMain = "main"; inline constexpr const char* Limit = "limit"; inline constexpr const char* History = "history"; inline constexpr const char* Variables = "variables"; inline constexpr const char* Functions = "functions"; inline constexpr const char* Units = "units"; inline constexpr const char* Globals = "globals"; namespace Common { inline constexpr const char* Id = "id"; inline constexpr const char* Description = "dsc"; inline constexpr const char* Expression = "xpr"; inline constexpr const char* InterpretedExpression = "itp"; } namespace HistoryEntry { inline constexpr const char* Expression = "xpr"; inline constexpr const char* InterpretedExpression = "itp"; inline constexpr const char* Result = "rst"; inline constexpr const char* Context = "ctx"; inline constexpr const char* EditTimestamp = "edt"; inline constexpr const char* PrintedLines = "prt"; } namespace EvaluationContext { inline constexpr const char* Lines = "lns"; inline constexpr const char* MainLine = "main"; inline constexpr const char* ExtraLines = "ext"; inline constexpr const char* Complex = "cpx"; inline constexpr const char* Angle = "ang"; inline constexpr const char* UnitExponentStyle = "uxp"; inline constexpr const char* Rounding = "rnd"; namespace Line { inline constexpr const char* Notation = "ntn"; inline constexpr const char* Precision = "prc"; inline constexpr const char* ComplexFormat = "cpx"; } namespace ComplexValues { inline constexpr const char* Off = "off"; inline constexpr const char* I = "i"; inline constexpr const char* J = "j"; } } namespace Variable { inline constexpr const char* Id = "id"; inline constexpr const char* Quantity = "qty"; inline constexpr const char* Description = "dsc"; inline constexpr const char* FormattedValue = "fmt"; } namespace Function { inline constexpr const char* Id = "id"; inline constexpr const char* Arguments = "args"; inline constexpr const char* Expression = "xpr"; inline constexpr const char* InterpretedExpression = "itp"; inline constexpr const char* Description = "dsc"; inline constexpr const char* Opcodes = "opcodes"; inline constexpr const char* Constants = "constants"; inline constexpr const char* Identifiers = "identifiers"; namespace Opcode { inline constexpr const char* Type = "t"; inline constexpr const char* Index = "i"; inline constexpr const char* Text = "text"; } } } #endif // CORE_SESSIONJSONKEYS_H heldercorreia-speedcrunch-e7ca37f/src/core/settings.cpp000066400000000000000000001413701526573132500234260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2013-2016, 2018, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "core/settings.h" #include "core/complexform.h" #include "math/floatnum/floatconfig.h" #include "core/mathdsl.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN # define WIN32_LEAN_AND_MEAN # ifndef NOMINMAX # define NOMINMAX # endif # include # include #endif // The current config revision. Based on the application version number // ('1200' corresponds to 0.12.0, '10300' would be 1.3.0 etc.). When making // a backwards-incompatible change to the config format, bump this number to // the next release (if not already happened), then update the migration code // in createQSettings. Don't bump the config version unnecessarily for // releases that don't contain incompatible changes. static const int ConfigVersion = 1200; static const char* DefaultColorScheme = "Duskfox"; namespace { static const int MinCustomKeypadDimension = 1; static const int MaxCustomKeypadDimension = 20; bool isValidCustomAction(int action) { return action >= static_cast(Settings::CustomKeypadActionInsertText) && action <= static_cast(Settings::CustomKeypadActionEvaluateExpression); } QJsonObject serializeCustomKeypad(const Settings::CustomKeypad& keypad) { QJsonObject json; json.insert(QStringLiteral("rows"), keypad.rows); json.insert(QStringLiteral("columns"), keypad.columns); QJsonArray buttonsJson; for (const auto& button : keypad.buttons) { QJsonObject item; item.insert(QStringLiteral("row"), button.row); item.insert(QStringLiteral("column"), button.column); item.insert(QStringLiteral("label"), button.label); item.insert(QStringLiteral("text"), button.text); item.insert(QStringLiteral("action"), static_cast(button.action)); buttonsJson.push_back(item); } json.insert(QStringLiteral("buttons"), buttonsJson); return json; } bool deserializeCustomKeypad(const QJsonObject& json, Settings::CustomKeypad* keypad) { if (!keypad || !json.contains(QStringLiteral("rows")) || !json.contains(QStringLiteral("columns"))) return false; const int rows = json.value(QStringLiteral("rows")).toInt(0); const int columns = json.value(QStringLiteral("columns")).toInt(0); if (rows < MinCustomKeypadDimension || rows > MaxCustomKeypadDimension || columns < MinCustomKeypadDimension || columns > MaxCustomKeypadDimension) { return false; } Settings::CustomKeypad parsed; parsed.rows = rows; parsed.columns = columns; const QJsonArray buttonsJson = json.value(QStringLiteral("buttons")).toArray(); for (const auto& buttonValue : buttonsJson) { if (!buttonValue.isObject()) continue; const QJsonObject buttonJson = buttonValue.toObject(); const int row = buttonJson.value(QStringLiteral("row")).toInt(-1); const int column = buttonJson.value(QStringLiteral("column")).toInt(-1); const int action = buttonJson.value(QStringLiteral("action")).toInt( static_cast(Settings::CustomKeypadActionInsertText)); if (row < 0 || row >= rows || column < 0 || column >= columns || !isValidCustomAction(action)) continue; Settings::CustomKeypadButton button; button.row = row; button.column = column; button.label = buttonJson.value(QStringLiteral("label")).toString(); button.text = buttonJson.value(QStringLiteral("text")).toString(); button.action = static_cast(action); parsed.buttons.append(button); } *keypad = parsed; return true; } bool shouldUseNonAtomicSettingsSync(const QString& fileName) { const QFileInfo fileInfo(fileName); if (!fileInfo.exists()) return false; // Renaming a temporary file over a linked target breaks the link. if (fileInfo.isSymLink()) return true; std::error_code error; const auto linkCount = std::filesystem::hard_link_count( std::filesystem::path(fileName.toStdU16String()), error); return !error && linkCount > 1; } #if defined(SPEEDCRUNCH_PORTABLE) && !defined(SPEEDCRUNCH_UI_TEST) QString portableStoragePath() { QDir directory(QApplication::applicationDirPath()); #ifdef Q_OS_MACOS // Keep writable data outside the signed application bundle. QDir bundle(directory); if (bundle.dirName() == QLatin1String("MacOS") && bundle.cdUp() && bundle.dirName() == QLatin1String("Contents") && bundle.cdUp() && bundle.dirName().endsWith(QLatin1String(".app"), Qt::CaseInsensitive)) { directory = bundle; directory.cdUp(); } return directory.filePath(QStringLiteral("SpeedCrunch-data")); #else return directory.absolutePath(); #endif } #endif } // namespace #ifdef SPEEDCRUNCH_UI_TEST static QString uiTestStoragePath(const QString& directory) { const QString root = QString::fromUtf8(qgetenv("SPEEDCRUNCH_UI_TEST_STORAGE")); if (root.isEmpty()) qFatal("UI tests must initialize UiTestFixture before accessing settings."); return QDir(root).filePath(directory); } #endif QString Settings::getConfigPath() { #ifdef SPEEDCRUNCH_UI_TEST return uiTestStoragePath(QStringLiteral("config")); #elif defined(SPEEDCRUNCH_PORTABLE) return portableStoragePath(); #elif defined(Q_OS_WIN) // On Windows, use AppData/Roaming/SpeedCrunch, the same path as getDataPath. return getDataPath(); #else // Everywhere else, use `QStandardPaths::ConfigLocation`/SpeedCrunch: // * OSX: ~/Library/Preferences/SpeedCrunch // * Linux: ~/.config/SpeedCrunch return QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), QCoreApplication::applicationName()); #endif } QString Settings::getDataPath() { #ifdef SPEEDCRUNCH_UI_TEST return uiTestStoragePath(QStringLiteral("data")); #elif defined(SPEEDCRUNCH_PORTABLE) return portableStoragePath(); #elif QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); #elif defined(Q_OS_WIN) // We can't use AppDataLocation, so we simply use the Win32 API to emulate it. WCHAR w32path[MAX_PATH]; HRESULT result = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, w32path); Q_ASSERT(SUCCEEDED(result)); QString path = QString::fromWCharArray(w32path); QString orgName = QCoreApplication::organizationName(); QString appName = QCoreApplication::applicationName(); if (!orgName.isEmpty()) { path.append('\\'); path.append(orgName); } if (!appName.isEmpty()) { path.append('\\'); path.append(appName); } return QDir::fromNativeSeparators(path); #else // Any non-Windows with Qt < 5.4. Since DataLocation and AppDataLocation are // equivalent outside of Windows, that should be fine. return QStandardPaths::writableLocation(QStandardPaths::DataLocation); #endif } QString Settings::getCachePath() { #ifdef SPEEDCRUNCH_UI_TEST return uiTestStoragePath(QStringLiteral("cache")); #elif defined(SPEEDCRUNCH_PORTABLE) return portableStoragePath(); #else return QStandardPaths::writableLocation(QStandardPaths::CacheLocation); #endif } bool Settings::preparePortableStorage(QString* errorMessage) { #if defined(SPEEDCRUNCH_PORTABLE) && defined(Q_OS_MACOS) && !defined(SPEEDCRUNCH_UI_TEST) const QString path = portableStoragePath(); if (!QDir().mkpath(path)) { *errorMessage = QObject::tr("Could not create %1.").arg(path); return false; } QTemporaryFile probe(QDir(path).filePath(QStringLiteral(".write-check-XXXXXX"))); if (!probe.open() || probe.write("1", 1) != 1 || !probe.flush()) { *errorMessage = probe.errorString(); return false; } #else Q_UNUSED(errorMessage); #endif return true; } static Settings* s_settingsInstance = 0; static char s_radixCharacter = 0; static void s_deleteSettings() { delete s_settingsInstance; } static QSettings* createQSettings(const QString& key); Settings* Settings::instance() { if (!s_settingsInstance) { s_settingsInstance = new Settings; s_settingsInstance->load(); qAddPostRoutine(s_deleteSettings); } return s_settingsInstance; } Settings::CustomKeypad Settings::defaultCustomKeypad() { Settings::CustomKeypad custom; custom.rows = 4; custom.columns = 5; static const struct { int row; int column; QString label; QString text; Settings::CustomKeypadButtonAction action; } defaults[] = { {0, 0, QStringLiteral("7"), QStringLiteral("7"), Settings::CustomKeypadActionInsertText}, {0, 1, QStringLiteral("8"), QStringLiteral("8"), Settings::CustomKeypadActionInsertText}, {0, 2, QStringLiteral("9"), QStringLiteral("9"), Settings::CustomKeypadActionInsertText}, {0, 3, QStringLiteral("÷"), QStringLiteral("÷"), Settings::CustomKeypadActionInsertText}, {0, 4, QStringLiteral("⌧"), QString(), Settings::CustomKeypadActionClearExpression}, {1, 0, QStringLiteral("4"), QStringLiteral("4"), Settings::CustomKeypadActionInsertText}, {1, 1, QStringLiteral("5"), QStringLiteral("5"), Settings::CustomKeypadActionInsertText}, {1, 2, QStringLiteral("6"), QStringLiteral("6"), Settings::CustomKeypadActionInsertText}, {1, 3, QString(MathDsl::MulCrossOp), QString(MathDsl::MulCrossOp), Settings::CustomKeypadActionInsertText}, {1, 4, QStringLiteral("⌫"), QString(), Settings::CustomKeypadActionBackspace}, {2, 0, QStringLiteral("1"), QStringLiteral("1"), Settings::CustomKeypadActionInsertText}, {2, 1, QStringLiteral("2"), QStringLiteral("2"), Settings::CustomKeypadActionInsertText}, {2, 2, QStringLiteral("3"), QStringLiteral("3"), Settings::CustomKeypadActionInsertText}, {2, 3, QStringLiteral("−"), QStringLiteral("−"), Settings::CustomKeypadActionInsertText}, {2, 4, QStringLiteral("("), QStringLiteral("("), Settings::CustomKeypadActionInsertText}, {3, 0, QStringLiteral("0"), QStringLiteral("0"), Settings::CustomKeypadActionInsertText}, {3, 1, QStringLiteral("."), QStringLiteral("."), Settings::CustomKeypadActionInsertText}, {3, 2, QStringLiteral("="), QString(), Settings::CustomKeypadActionEvaluateExpression}, {3, 3, QStringLiteral("+"), QStringLiteral("+"), Settings::CustomKeypadActionInsertText}, {3, 4, QStringLiteral(")"), QStringLiteral(")"), Settings::CustomKeypadActionInsertText} }; const int count = int(sizeof defaults / sizeof defaults[0]); for (int i = 0; i < count; ++i) { Settings::CustomKeypadButton button; button.row = defaults[i].row; button.column = defaults[i].column; button.label = defaults[i].label; button.text = defaults[i].text; button.action = defaults[i].action; custom.buttons.append(button); } return custom; } Settings::Settings() { inputDigitGrouping = true; cursorBlinking = true; escapeClearsEditor = false; digitGroupingIntegerPartOnly = true; numberFormatStyle = NumberFormatNoGroupingDot; hasNumberFormatStyleSetting = false; simplifyResultExpressions = true; complexNumbers = true; imaginaryUnit = 'i'; autoCompletionAcceptWithEnter = false; autoCompletionBuiltInFunctions = true; autoCompletionBuiltInVariables = true; autoCompletionLongFormUnits = true; autoCompletionUserFunctions = true; autoCompletionUserVariables = true; secondaryResultPrecision = -1; resultRoundingMode = ResultRoundingHalfAwayFromZero; removeTrailingZeroes = false; unitNegativeExponentStyle = UnitNegativeExponentSuperscript; tertiaryResultPrecision = -1; quaternaryResultPrecision = -1; quinaryResultPrecision = -1; secondaryResultEnabled = false; tertiaryResultEnabled = false; quaternaryResultEnabled = false; quinaryResultEnabled = false; multipleResultLinesEnabled = false; secondaryComplexNumbers = true; resultComplexForm = ComplexForm::Default; secondaryResultComplexForm = ComplexForm::Default; tertiaryComplexNumbers = true; tertiaryResultComplexForm = ComplexForm::Default; quaternaryComplexNumbers = true; quaternaryResultComplexForm = ComplexForm::Default; quinaryComplexNumbers = true; quinaryResultComplexForm = ComplexForm::Default; setRuntimeUnitNegativeExponentStyle(unitNegativeExponentStyle); setRuntimeResultRoundingMode(resultRoundingMode); } void Settings::load() { StartupDiagnostics::Scope timing("Read and migrate settings"); const char* KEY = "SpeedCrunch"; QSettings* settings = createQSettings(KEY); if (!settings) return; QString key = QString::fromLatin1(KEY) + QLatin1String("/General/"); // Angle mode special case. QString angleUnitStr; angleUnitStr = settings->value(key + QLatin1String("AngleMode"), "r").toString(); if (angleUnitStr != QLatin1String("r") && angleUnitStr != QLatin1String("d") && angleUnitStr != QLatin1String("g") && angleUnitStr != QLatin1String("t") && angleUnitStr != QLatin1String("v")) angleUnit = 'r'; else angleUnit = angleUnitStr.at(0).toLatin1(); // Radix character special case. QString radixCharStr; radixCharStr = settings->value(key + QLatin1String("RadixCharacter"), "*").toString(); setRadixCharacter(radixCharStr.at(0).toLatin1()); autoAns = settings->value(key + QLatin1String("AutoAns"), false).toBool(); autoCalc = settings->value(key + QLatin1String("AutoCalc"), true).toBool(); autoCompletion = settings->value(key + QLatin1String("AutoCompletion"), true).toBool(); autoCompletionAcceptWithEnter = settings->value( key + QLatin1String("AutoCompletionAcceptWithEnter"), false).toBool(); autoCompletionBuiltInFunctions = settings->value( key + QLatin1String("AutoCompletionBuiltInFunctions"), true).toBool(); autoCompletionBuiltInVariables = settings->value( key + QLatin1String("AutoCompletionBuiltInVariables"), autoCompletionBuiltInFunctions).toBool(); const QString autoCompletionLongFormUnitsKey = key + QLatin1String("AutoCompletionLongFormUnits"); autoCompletionLongFormUnits = settings->value( autoCompletionLongFormUnitsKey, true).toBool(); autoCompletionUserFunctions = settings->value( key + QLatin1String("AutoCompletionUserFunctions"), true).toBool(); autoCompletionUserVariables = settings->value( key + QLatin1String("AutoCompletionUserVariables"), true).toBool(); const QString upDownArrowBehaviorKey = key + QLatin1String("UpDownArrowBehavior"); if (settings->contains(upDownArrowBehaviorKey)) { upDownArrowBehavior = static_cast( settings->value(upDownArrowBehaviorKey).toInt()); } else { // Backward compatibility with old boolean key. const bool historyNavigationWithUpDown = settings->value( key + QLatin1String("HistoryNavigationWithUpDown"), true).toBool(); upDownArrowBehavior = historyNavigationWithUpDown ? UpDownArrowBehaviorAlways : UpDownArrowBehaviorNever; } if (upDownArrowBehavior != UpDownArrowBehaviorNever && upDownArrowBehavior != UpDownArrowBehaviorAlways && upDownArrowBehavior != UpDownArrowBehaviorSingleLineOnly) { upDownArrowBehavior = UpDownArrowBehaviorAlways; } leaveLastExpression = settings->value(key + QLatin1String("LeaveLastExpression"), false).toBool(); language = settings->value(key + QLatin1String("Language"), "C").toString(); syntaxHighlighting = settings->value(key + QLatin1String("SyntaxHighlighting"), true).toBool(); automaticInputAdjustments = settings->value( key + QLatin1String("AutomaticInputAdjustments"), true).toBool(); inputDigitGrouping = settings->value(key + QLatin1String("InputDigitGrouping"), true).toBool(); cursorBlinking = settings->value(key + QLatin1String("CursorBlinking"), true).toBool(); escapeClearsEditor = settings->value(key + QLatin1String("EscapeClearsEditor"), false).toBool(); hoverHighlightResults = settings->value(key + QLatin1String("HoverHighlightResults"), true).toBool(); autoResultToClipboard = settings->value(key + QLatin1String("AutoResultToClipboard"), false).toBool(); simplifyResultExpressions = settings->value(key + QLatin1String("SimplifyResultExpressions"), true).toBool(); windowPositionSave = settings->value(key + QLatin1String("WindowPositionSave"), true).toBool(); openPrivateTabOnStartup = settings->value(key + QLatin1String("OpenPrivateTabOnStartup"), false).toBool(); complexNumbers = true; QString imaginaryUnitStr = settings->value(key + QLatin1String("ImaginaryUnit"), 'i').toString(); if (imaginaryUnitStr != QLatin1String("i") && imaginaryUnitStr != QLatin1String("j")) imaginaryUnit = 'i'; else imaginaryUnit = imaginaryUnitStr.at(0).toLatin1(); digitGrouping = settings->value(key + QLatin1String("DigitGrouping"), 0).toInt(); digitGrouping = std::min(3, std::max(0, digitGrouping)); digitGroupingIntegerPartOnly = settings->value( key + QLatin1String("DigitGroupingIntegerPartOnly"), true).toBool(); const int numberFormatStyleValue = settings->value( key + QLatin1String("NumberFormatStyle"), -1).toInt(); hasNumberFormatStyleSetting = settings->contains(key + QLatin1String("NumberFormatStyle")); if (numberFormatStyleValue >= static_cast(NumberFormatSystem) && numberFormatStyleValue <= static_cast(NumberFormatIndianCommaDot)) { numberFormatStyle = static_cast(numberFormatStyleValue); } else { // Deterministic default when style is not set. numberFormatStyle = NumberFormatNoGroupingDot; } if (numberFormatStyle == NumberFormatSystem) numberFormatStyle = NumberFormatNoGroupingDot; applyNumberFormatStyle(); key = KEY + QLatin1String("/Format/"); // Format special case. QString format = settings->value(key + QLatin1String("MainType"), 'g').toString(); if (format != "g" && format != "f" && format != "e" && format != "n" && format != "r" && format != "h" && format != "o" && format != "b" && format != "s") resultFormat = 'f'; else resultFormat = format.at(0).toLatin1(); QString alternativeFormat = settings->value(key + QLatin1String("SecondaryType"), "").toString(); if (alternativeFormat.isEmpty()) alternativeResultFormat = '\0'; else if (alternativeFormat != "g" && alternativeFormat != "f" && alternativeFormat != "e" && alternativeFormat != "r" && alternativeFormat != "n" && alternativeFormat != "h" && alternativeFormat != "o" && alternativeFormat != "b" && alternativeFormat != "s") alternativeResultFormat = '\0'; else alternativeResultFormat = alternativeFormat.at(0).toLatin1(); secondaryResultEnabled = settings->value( key + QLatin1String("SecondaryEnabled"), alternativeResultFormat != '\0').toBool(); QString tertiaryFormat = settings->value(key + QLatin1String("TertiaryType"), "").toString(); if (tertiaryFormat.isEmpty()) tertiaryResultFormat = '\0'; else if (tertiaryFormat != "g" && tertiaryFormat != "f" && tertiaryFormat != "e" && tertiaryFormat != "r" && tertiaryFormat != "n" && tertiaryFormat != "h" && tertiaryFormat != "o" && tertiaryFormat != "b" && tertiaryFormat != "s") tertiaryResultFormat = '\0'; else tertiaryResultFormat = tertiaryFormat.at(0).toLatin1(); tertiaryResultEnabled = settings->value( key + QLatin1String("TertiaryEnabled"), tertiaryResultFormat != '\0').toBool(); QString quaternaryFormat = settings->value(key + QLatin1String("QuaternaryType"), "").toString(); if (quaternaryFormat.isEmpty()) quaternaryResultFormat = '\0'; else if (quaternaryFormat != "g" && quaternaryFormat != "f" && quaternaryFormat != "e" && quaternaryFormat != "r" && quaternaryFormat != "n" && quaternaryFormat != "h" && quaternaryFormat != "o" && quaternaryFormat != "b" && quaternaryFormat != "s") quaternaryResultFormat = '\0'; else quaternaryResultFormat = quaternaryFormat.at(0).toLatin1(); quaternaryResultEnabled = settings->value( key + QLatin1String("QuaternaryEnabled"), quaternaryResultFormat != '\0').toBool(); QString quinaryFormat = settings->value(key + QLatin1String("QuinaryType"), "").toString(); if (quinaryFormat.isEmpty()) quinaryResultFormat = '\0'; else if (quinaryFormat != "g" && quinaryFormat != "f" && quinaryFormat != "e" && quinaryFormat != "r" && quinaryFormat != "n" && quinaryFormat != "h" && quinaryFormat != "o" && quinaryFormat != "b" && quinaryFormat != "s") quinaryResultFormat = '\0'; else quinaryResultFormat = quinaryFormat.at(0).toLatin1(); quinaryResultEnabled = settings->value( key + QLatin1String("QuinaryEnabled"), quinaryResultFormat != '\0').toBool(); multipleResultLinesEnabled = settings->value( key + QLatin1String("MultipleLinesEnabled"), false).toBool(); // Complex format special case. resultComplexForm = ComplexForm::fromString( settings->value(key + QLatin1String("MainComplexForm"), ComplexForm::toString(ComplexForm::Default)).toString()); removeTrailingZeroes = settings->value(key + QLatin1String("RemoveTrailingZeroes"), false).toBool(); resultPrecision = settings->value(key + QLatin1String("MainPrecision"), -1).toInt(); if (!settings->contains(key + QLatin1String("MainPrecision"))) { // Backward compatibility with legacy key. resultPrecision = settings->value(key + QLatin1String("Precision"), -1).toInt(); } const QString roundingModeKey = key + QLatin1String("ResultRoundingMode"); if (settings->contains(roundingModeKey)) { const QVariant value = settings->value(roundingModeKey); const QString text = value.toString(); if (text.size() == 1 && isValidResultRoundingMode(text.at(0).toLatin1())) { resultRoundingMode = text.at(0).toLatin1(); } else { resultRoundingMode = ResultRoundingHalfAwayFromZero; } } else { resultRoundingMode = ResultRoundingHalfAwayFromZero; } if (!isValidResultRoundingMode(resultRoundingMode)) { resultRoundingMode = ResultRoundingHalfAwayFromZero; } setRuntimeResultRoundingMode(resultRoundingMode); secondaryResultPrecision = settings->value(key + QLatin1String("SecondaryPrecision"), -1).toInt(); const QVariant unitExpValue = settings->value(key + QLatin1String("UnitNegativeExponentStyle"), QString(QChar(static_cast(UnitNegativeExponentSuperscript)))); const QString unitExpText = unitExpValue.toString(); if (unitExpText.size() == 1 && isValidUnitNegativeExponentStyle(unitExpText.at(0).toLatin1())) { unitNegativeExponentStyle = unitExpText.at(0).toLatin1(); } else { unitNegativeExponentStyle = UnitNegativeExponentSuperscript; } if (!isValidUnitNegativeExponentStyle(unitNegativeExponentStyle)) { unitNegativeExponentStyle = UnitNegativeExponentSuperscript; } setRuntimeUnitNegativeExponentStyle(unitNegativeExponentStyle); tertiaryResultPrecision = settings->value(key + QLatin1String("TertiaryPrecision"), -1).toInt(); quaternaryResultPrecision = settings->value(key + QLatin1String("QuaternaryPrecision"), -1).toInt(); quinaryResultPrecision = settings->value(key + QLatin1String("QuinaryPrecision"), -1).toInt(); secondaryComplexNumbers = true; tertiaryComplexNumbers = true; quaternaryComplexNumbers = true; quinaryComplexNumbers = true; secondaryResultComplexForm = ComplexForm::fromString( settings->value(key + QLatin1String("SecondaryComplexForm"), ComplexForm::toString(ComplexForm::Default)).toString()); tertiaryResultComplexForm = ComplexForm::fromString( settings->value(key + QLatin1String("TertiaryComplexForm"), ComplexForm::toString(ComplexForm::Default)).toString()); quaternaryResultComplexForm = ComplexForm::fromString( settings->value(key + QLatin1String("QuaternaryComplexForm"), ComplexForm::toString(ComplexForm::Default)).toString()); quinaryResultComplexForm = ComplexForm::fromString( settings->value(key + QLatin1String("QuinaryComplexForm"), ComplexForm::toString(ComplexForm::Default)).toString()); if (resultPrecision > DECPRECISION) resultPrecision = DECPRECISION; if (secondaryResultPrecision > DECPRECISION) secondaryResultPrecision = DECPRECISION; if (tertiaryResultPrecision > DECPRECISION) tertiaryResultPrecision = DECPRECISION; if (quaternaryResultPrecision > DECPRECISION) quaternaryResultPrecision = DECPRECISION; if (quinaryResultPrecision > DECPRECISION) quinaryResultPrecision = DECPRECISION; key = KEY + QLatin1String("/Layout/"); customKeypad = defaultCustomKeypad(); windowOnfullScreen = settings->value(key + QLatin1String("WindowOnFullScreen"), false).toBool(); historyDockVisible = settings->value(key + QLatin1String("HistoryDockVisible"), false).toBool(); int keypadModeValue = static_cast(KeypadModeBasicWide); if (settings->contains(key + QLatin1String("KeypadMode"))) { keypadModeValue = settings->value(key + QLatin1String("KeypadMode")).toInt(); } else if (settings->contains(key + QLatin1String("KeypadVisible"))) { // Legacy compatibility for pre-keypad-mode settings. keypadModeValue = settings->value(key + QLatin1String("KeypadVisible"), false).toBool() ? static_cast(KeypadModeScientificWide) : static_cast(KeypadModeDisabled); } if (keypadModeValue >= static_cast(KeypadModeDisabled) && keypadModeValue <= static_cast(KeypadModeCustom)) { keypadMode = static_cast(keypadModeValue); } else { keypadMode = KeypadModeBasicWide; } if (keypadMode == KeypadModeBasicNarrow) keypadMode = KeypadModeBasicWide; keypadVisible = (keypadMode == KeypadModeBasicWide || keypadMode == KeypadModeScientificWide || keypadMode == KeypadModeScientificNarrow || keypadMode == KeypadModeCustom); keypadZoomPercent = settings->value(key + QLatin1String("KeypadZoomPercent"), 100).toInt(); if (keypadZoomPercent != 50 && keypadZoomPercent != 100 && keypadZoomPercent != 150 && keypadZoomPercent != 200) keypadZoomPercent = 100; const QString customKeypadJson = settings->value(key + QLatin1String("CustomKeypad"), QString()).toString(); if (!customKeypadJson.isEmpty()) { const QJsonDocument doc = QJsonDocument::fromJson(customKeypadJson.toUtf8()); if (doc.isObject()) deserializeCustomKeypad(doc.object(), &customKeypad); } statusBarVisible = settings->value(key + QLatin1String("StatusBarVisible"), false).toBool(); menuBarVisible = settings->value(key + QLatin1String("MenuBarVisible"), true).toBool(); functionsDockVisible = settings->value(key + QLatin1String("FunctionsDockVisible"), false).toBool(); variablesDockVisible = settings->value(key + QLatin1String("VariablesDockVisible"), false).toBool(); userFunctionsDockVisible = settings->value(key + QLatin1String("UserFunctionsDockVisible"), false).toBool(); userUnitsDockVisible = settings->value(key + QLatin1String("UserUnitsDockVisible"), false).toBool(); formulaBookDockVisible = settings->value(key + QLatin1String("FormulaBookDockVisible"), false).toBool(); constantsDockVisible = settings->value(key + QLatin1String("ConstantsDockVisible"), false).toBool(); windowAlwaysOnTop = settings->value(key + QLatin1String("WindowAlwaysOnTop"), false).toBool(); bitfieldVisible = settings->value(key + QLatin1String("BitfieldVisible"), false).toBool(); constantsDockDomain = settings->value(key + QLatin1String("ConstantsDockDomain"), QString()).toString(); constantsDockSubdomain = settings->value(key + QLatin1String("ConstantsDockSubdomain"), QString()).toString(); constantsDockSearchText = settings->value(key + QLatin1String("ConstantsDockSearchText"), QString()).toString(); functionsDockDomain = settings->value(key + QLatin1String("FunctionsDockDomain"), QString()).toString(); functionsDockSearchText = settings->value(key + QLatin1String("FunctionsDockSearchText"), QString()).toString(); userFunctionsDockSearchText = settings->value(key + QLatin1String("UserFunctionsDockSearchText"), QString()).toString(); userUnitsDockSearchText = settings->value(key + QLatin1String("UserUnitsDockSearchText"), QString()).toString(); variablesDockSearchText = settings->value(key + QLatin1String("VariablesDockSearchText"), QString()).toString(); formulaBookActivePage = settings->value(key + QLatin1String("FormulaBookActivePage"), QStringLiteral("index")).toString(); dockColumnOrdersJson = settings->value(key + QLatin1String("DockColumnOrders"), QString()).toString(); windowState = settings->value(key + QLatin1String("State")).toByteArray(); windowGeometry = settings->value(key + QLatin1String("WindowGeometry")).toByteArray(); manualWindowGeometry = settings->value(key + QLatin1String("ManualWindowGeometry")).toByteArray(); sessionLayoutJson = settings->value(key + QLatin1String("SessionLayoutJson"), QString()).toString(); key = KEY + QLatin1String("/Display/"); displayFont = settings->value(key + QLatin1String("DisplayFont"), QFont().toString()).toString(); colorScheme = settings->value(key + QLatin1String("ColorSchemeName"), DefaultColorScheme).toString(); menuAppearance = settings->value(key + QLatin1String("MenuAppearance"), MenuAppearanceSpeedCrunch).toInt() == MenuAppearanceSystem ? MenuAppearanceSystem : MenuAppearanceSpeedCrunch; dockAppearance = settings->value(key + QLatin1String("DockAppearance"), DockAppearanceSpeedCrunch).toInt() == DockAppearanceSystem ? DockAppearanceSystem : DockAppearanceSpeedCrunch; statusBarAppearance = settings->value(key + QLatin1String("StatusBarAppearance"), StatusBarAppearanceSpeedCrunch).toInt() == StatusBarAppearanceSystem ? StatusBarAppearanceSystem : StatusBarAppearanceSpeedCrunch; editorDisplayStyle = settings->value(key + QLatin1String("EditorDisplayStyle"), EditorDisplayModern).toInt() == EditorDisplayClassic ? EditorDisplayClassic : EditorDisplayModern; keypadAppearance = settings->value(key + QLatin1String("KeypadAppearance"), KeypadAppearanceModern).toInt() == KeypadAppearanceClassic ? KeypadAppearanceClassic : KeypadAppearanceModern; customColorSchemeJson = settings->value(key + QLatin1String("CustomColorSchemeJson"), QString()).toString(); delete settings; } void Settings::save() { const QString KEY = QString::fromLatin1("SpeedCrunch"); QSettings* settings = createQSettings(KEY); if (!settings) return; QString key = KEY + QLatin1String("/General/"); settings->setValue(key + QLatin1String("LeaveLastExpression"), leaveLastExpression); settings->setValue(key + QLatin1String("AutoCompletion"), autoCompletion); settings->setValue(key + QLatin1String("AutoCompletionAcceptWithEnter"), autoCompletionAcceptWithEnter); settings->setValue(key + QLatin1String("AutoCompletionBuiltInFunctions"), autoCompletionBuiltInFunctions); settings->setValue(key + QLatin1String("AutoCompletionBuiltInVariables"), autoCompletionBuiltInVariables); settings->setValue(key + QLatin1String("AutoCompletionLongFormUnits"), autoCompletionLongFormUnits); settings->setValue(key + QLatin1String("AutoCompletionUserFunctions"), autoCompletionUserFunctions); settings->setValue(key + QLatin1String("AutoCompletionUserVariables"), autoCompletionUserVariables); settings->setValue(key + QLatin1String("AutoAns"), autoAns); settings->setValue(key + QLatin1String("AutoCalc"), autoCalc); settings->setValue( key + QLatin1String("UpDownArrowBehavior"), static_cast(upDownArrowBehavior)); settings->setValue(key + QLatin1String("SyntaxHighlighting"), syntaxHighlighting); settings->setValue(key + QLatin1String("AutomaticInputAdjustments"), automaticInputAdjustments); settings->setValue(key + QLatin1String("InputDigitGrouping"), inputDigitGrouping); settings->setValue(key + QLatin1String("CursorBlinking"), cursorBlinking); settings->setValue(key + QLatin1String("EscapeClearsEditor"), escapeClearsEditor); settings->setValue(key + QLatin1String("HoverHighlightResults"), hoverHighlightResults); settings->setValue(key + QLatin1String("DigitGrouping"), digitGrouping); settings->setValue(key + QLatin1String("DigitGroupingIntegerPartOnly"), digitGroupingIntegerPartOnly); settings->setValue(key + QLatin1String("NumberFormatStyle"), static_cast(numberFormatStyle)); settings->setValue(key + QLatin1String("AutoResultToClipboard"), autoResultToClipboard); settings->setValue(key + QLatin1String("SimplifyResultExpressions"), simplifyResultExpressions); settings->setValue(key + QLatin1String("Language"), language); settings->setValue(key + QLatin1String("WindowPositionSave"), windowPositionSave); settings->setValue(key + QLatin1String("OpenPrivateTabOnStartup"), openPrivateTabOnStartup); settings->setValue(key + QLatin1String("ComplexNumbers"), true); settings->setValue(key + QLatin1String("ImaginaryUnit"), QString(QChar(imaginaryUnit))); settings->setValue(key + QLatin1String("AngleMode"), QString(QChar(angleUnit))); key = KEY + QLatin1String("/Format/"); settings->setValue(key + QLatin1String("MainType"), QString(QChar(resultFormat))); settings->setValue(key + QLatin1String("SecondaryType"), alternativeResultFormat == '\0' ? QString() : QString(QChar(alternativeResultFormat))); settings->setValue(key + QLatin1String("TertiaryType"), tertiaryResultFormat == '\0' ? QString() : QString(QChar(tertiaryResultFormat))); settings->setValue(key + QLatin1String("QuaternaryType"), quaternaryResultFormat == '\0' ? QString() : QString(QChar(quaternaryResultFormat))); settings->setValue(key + QLatin1String("QuinaryType"), quinaryResultFormat == '\0' ? QString() : QString(QChar(quinaryResultFormat))); settings->setValue(key + QLatin1String("SecondaryEnabled"), secondaryResultEnabled); settings->setValue(key + QLatin1String("TertiaryEnabled"), tertiaryResultEnabled); settings->setValue(key + QLatin1String("QuaternaryEnabled"), quaternaryResultEnabled); settings->setValue(key + QLatin1String("QuinaryEnabled"), quinaryResultEnabled); settings->setValue(key + QLatin1String("MultipleLinesEnabled"), multipleResultLinesEnabled); settings->setValue(key + QLatin1String("MainComplexForm"), ComplexForm::toString(resultComplexForm)); settings->setValue(key + QLatin1String("MainPrecision"), resultPrecision); settings->setValue(key + QLatin1String("RemoveTrailingZeroes"), removeTrailingZeroes); settings->setValue(key + QLatin1String("ResultRoundingMode"), QString(QChar(resultRoundingMode))); settings->setValue(key + QLatin1String("UnitNegativeExponentStyle"), QString(QChar(unitNegativeExponentStyle))); settings->setValue(key + QLatin1String("SecondaryPrecision"), secondaryResultPrecision); settings->setValue(key + QLatin1String("TertiaryPrecision"), tertiaryResultPrecision); settings->setValue(key + QLatin1String("QuaternaryPrecision"), quaternaryResultPrecision); settings->setValue(key + QLatin1String("QuinaryPrecision"), quinaryResultPrecision); settings->setValue(key + QLatin1String("SecondaryComplexEnabled"), true); settings->setValue(key + QLatin1String("SecondaryComplexForm"), ComplexForm::toString(secondaryResultComplexForm)); settings->setValue(key + QLatin1String("TertiaryComplexEnabled"), true); settings->setValue(key + QLatin1String("TertiaryComplexForm"), ComplexForm::toString(tertiaryResultComplexForm)); settings->setValue(key + QLatin1String("QuaternaryComplexEnabled"), true); settings->setValue(key + QLatin1String("QuaternaryComplexForm"), ComplexForm::toString(quaternaryResultComplexForm)); settings->setValue(key + QLatin1String("QuinaryComplexEnabled"), true); settings->setValue(key + QLatin1String("QuinaryComplexForm"), ComplexForm::toString(quinaryResultComplexForm)); key = KEY + QLatin1String("/Layout/"); settings->setValue(key + QLatin1String("FormulaBookDockVisible"), formulaBookDockVisible); settings->setValue(key + QLatin1String("ConstantsDockVisible"), constantsDockVisible); settings->setValue(key + QLatin1String("FunctionsDockVisible"), functionsDockVisible); settings->setValue(key + QLatin1String("HistoryDockVisible"), historyDockVisible); settings->setValue(key + QLatin1String("KeypadMode"), static_cast(keypadMode)); settings->setValue(key + QLatin1String("WindowOnFullScreen"), windowOnfullScreen); settings->setValue(key + QLatin1String("KeypadVisible"), keypadMode == KeypadModeBasicWide || keypadMode == KeypadModeScientificWide || keypadMode == KeypadModeScientificNarrow || keypadMode == KeypadModeCustom); settings->setValue(key + QLatin1String("KeypadZoomPercent"), keypadZoomPercent); settings->setValue(key + QLatin1String("CustomKeypad"), QString::fromUtf8(QJsonDocument(serializeCustomKeypad(customKeypad)).toJson(QJsonDocument::Compact))); settings->setValue(key + QLatin1String("StatusBarVisible"), statusBarVisible); settings->setValue(key + QLatin1String("MenuBarVisible"), menuBarVisible); settings->setValue(key + QLatin1String("VariablesDockVisible"), variablesDockVisible); settings->setValue(key + QLatin1String("UserFunctionsDockVisible"), userFunctionsDockVisible); settings->setValue(key + QLatin1String("UserUnitsDockVisible"), userUnitsDockVisible); settings->setValue(key + QLatin1String("WindowAlwaysOnTop"), windowAlwaysOnTop); settings->setValue(key + QLatin1String("State"), windowState); settings->setValue(key + QLatin1String("WindowGeometry"), windowGeometry); settings->setValue(key + QLatin1String("ManualWindowGeometry"), manualWindowGeometry); settings->setValue(key + QLatin1String("SessionLayoutJson"), sessionLayoutJson); settings->setValue(key + QLatin1String("BitfieldVisible"), bitfieldVisible); settings->setValue(key + QLatin1String("ConstantsDockDomain"), constantsDockDomain); settings->setValue(key + QLatin1String("ConstantsDockSubdomain"), constantsDockSubdomain); settings->setValue(key + QLatin1String("ConstantsDockSearchText"), constantsDockSearchText); settings->setValue(key + QLatin1String("FunctionsDockDomain"), functionsDockDomain); settings->setValue(key + QLatin1String("FunctionsDockSearchText"), functionsDockSearchText); settings->setValue(key + QLatin1String("UserFunctionsDockSearchText"), userFunctionsDockSearchText); settings->setValue(key + QLatin1String("UserUnitsDockSearchText"), userUnitsDockSearchText); settings->setValue(key + QLatin1String("VariablesDockSearchText"), variablesDockSearchText); settings->setValue(key + QLatin1String("FormulaBookActivePage"), formulaBookActivePage); settings->setValue(key + QLatin1String("DockColumnOrders"), dockColumnOrdersJson); key = KEY + QLatin1String("/Display/"); settings->setValue(key + QLatin1String("DisplayFont"), displayFont); settings->setValue(key + QLatin1String("ColorSchemeName"), colorScheme); settings->setValue(key + QLatin1String("MenuAppearance"), static_cast(menuAppearance)); settings->setValue(key + QLatin1String("DockAppearance"), static_cast(dockAppearance)); settings->setValue(key + QLatin1String("StatusBarAppearance"), static_cast(statusBarAppearance)); settings->setValue(key + QLatin1String("EditorDisplayStyle"), static_cast(editorDisplayStyle)); settings->setValue(key + QLatin1String("KeypadAppearance"), static_cast(keypadAppearance)); settings->setValue(key + QLatin1String("CustomColorSchemeJson"), customColorSchemeJson); delete settings; } bool Settings::resetToDefaults() { QSettings* settings = createQSettings(QStringLiteral("SpeedCrunch")); if (!settings) return false; // The open sessions are work in progress, so keep their layout while // removing preferences, including keys left behind by older versions. settings->remove(QStringLiteral("SpeedCrunch")); settings->setValue(QStringLiteral("SpeedCrunch/Layout/SessionLayoutJson"), sessionLayoutJson); settings->sync(); const bool success = settings->status() == QSettings::NoError; delete settings; if (!success) return false; // Use the same defaults as a fresh installation instead of keeping a // second list here. Save the number format to avoid a first-run prompt. load(); hasNumberFormatStyleSetting = true; save(); return true; } void Settings::saveSessionLayoutJson() { const QString KEY = QString::fromLatin1("SpeedCrunch"); QSettings* settings = createQSettings(KEY); if (!settings) return; settings->setValue(KEY + QLatin1String("/Layout/SessionLayoutJson"), sessionLayoutJson); delete settings; } char Settings::radixCharacter() const { if (isRadixCharacterAuto() || isRadixCharacterBoth()) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // In Qt 6, decimalPoint returns a QString QChar decimalPoint = QLocale().decimalPoint().at(0); #else // In Qt 5, decimalPoint returns a QChar QChar decimalPoint = QLocale().decimalPoint(); #endif return decimalPoint.toLatin1(); } return s_radixCharacter; } char Settings::decimalSeparator() const { switch (numberFormatStyle) { case NumberFormatNoGroupingComma: case NumberFormatThreeDigitDotComma: case NumberFormatThreeDigitSpaceComma: case NumberFormatSIComma: case NumberFormatThreeDigitUnderscoreComma: case NumberFormatThreeDigitDotCommaFraction: case NumberFormatThreeDigitUnderscoreCommaFraction: return MathDsl::CommaSep.toLatin1(); case NumberFormatSIDot: case NumberFormatNoGroupingDot: case NumberFormatThreeDigitCommaDot: case NumberFormatThreeDigitCommaDotFraction: case NumberFormatThreeDigitSpaceDot: case NumberFormatThreeDigitUnderscoreDot: case NumberFormatThreeDigitUnderscoreDotFraction: case NumberFormatIndianCommaDot: default: return MathDsl::DotSep.toLatin1(); } } bool Settings::isRadixCharacterAuto() const { return s_radixCharacter == 0; } bool Settings::isRadixCharacterBoth() const { return s_radixCharacter == MathDsl::MulOpAl1.toLatin1(); } void Settings::setRadixCharacter(char c) { s_radixCharacter = (c != MathDsl::CommaSep.toLatin1() && c != MathDsl::DotSep.toLatin1() && c != MathDsl::MulOpAl1.toLatin1()) ? 0 : c; } void Settings::applyNumberFormatStyle() { switch (numberFormatStyle) { case NumberFormatNoGroupingDot: case NumberFormatSIDot: case NumberFormatThreeDigitCommaDot: case NumberFormatThreeDigitCommaDotFraction: case NumberFormatThreeDigitSpaceDot: case NumberFormatThreeDigitUnderscoreDot: case NumberFormatThreeDigitUnderscoreDotFraction: case NumberFormatIndianCommaDot: setRadixCharacter(MathDsl::DotSep.toLatin1()); break; case NumberFormatNoGroupingComma: case NumberFormatSIComma: case NumberFormatThreeDigitDotComma: case NumberFormatThreeDigitDotCommaFraction: case NumberFormatThreeDigitSpaceComma: case NumberFormatThreeDigitUnderscoreComma: case NumberFormatThreeDigitUnderscoreCommaFraction: setRadixCharacter(MathDsl::CommaSep.toLatin1()); break; case NumberFormatSystem: default: setRadixCharacter(MathDsl::DotSep.toLatin1()); break; } // Legacy syntax-highlighter spacing should stay disabled; grouping is now // represented explicitly by concrete separators in formatted text. digitGrouping = 0; switch (numberFormatStyle) { case NumberFormatSIDot: case NumberFormatSIComma: case NumberFormatThreeDigitCommaDotFraction: case NumberFormatThreeDigitDotCommaFraction: case NumberFormatThreeDigitUnderscoreDotFraction: case NumberFormatThreeDigitUnderscoreCommaFraction: digitGroupingIntegerPartOnly = false; break; default: digitGroupingIntegerPartOnly = true; break; } } bool Settings::isDigitGroupingEnabled() const { return numberFormatStyle != NumberFormatNoGroupingDot && numberFormatStyle != NumberFormatNoGroupingComma; } bool Settings::isIndianDigitGrouping() const { return numberFormatStyle == NumberFormatIndianCommaDot; } QString Settings::digitGroupingSeparator() const { if (!isDigitGroupingEnabled()) return QString(); switch (numberFormatStyle) { case NumberFormatSIDot: case NumberFormatSIComma: case NumberFormatThreeDigitSpaceDot: case NumberFormatThreeDigitSpaceComma: return QStringLiteral(" "); case NumberFormatThreeDigitCommaDot: case NumberFormatThreeDigitCommaDotFraction: case NumberFormatIndianCommaDot: return QStringLiteral(","); case NumberFormatThreeDigitDotComma: case NumberFormatThreeDigitDotCommaFraction: return QStringLiteral("."); case NumberFormatThreeDigitUnderscoreDot: case NumberFormatThreeDigitUnderscoreDotFraction: case NumberFormatThreeDigitUnderscoreComma: case NumberFormatThreeDigitUnderscoreCommaFraction: return QStringLiteral("_"); default: return QString(); } } // Settings migration from legacy (0.11 and before) to 0.12 (ConfigVersion 1200). static void migrateSettings_legacyTo1200(QSettings* settings, const QString& KEY) { #ifdef SPEEDCRUNCH_PORTABLE // This is the same as the new path, but let's cut down QSettings* legacy = new QSettings(Settings::getConfigPath() + "/" + KEY + ".ini", QSettings::IniFormat); #else QSettings* legacy = new QSettings(QSettings::NativeFormat, QSettings::UserScope, KEY, KEY); #endif QString legacyFile = legacy->fileName(); if (legacyFile != settings->fileName()) { // If the file names are different, we assume the legacy settings were in a // different location (most were, but e.g. not on the portable version) so we // copy everything over, then delete the old settings. On Windows, the file // name may also be a registry path, but the same reasoning applies. for (auto& key : legacy->allKeys()) settings->setValue(key, legacy->value(key)); #ifdef Q_OS_WIN // On Windows, check if the legacy settings were in the registry; if so, just clear() // them. if (legacy->format() == QSettings::NativeFormat) { legacy->clear(); delete legacy; } else { delete legacy; QFile::remove(legacyFile); } #else // On other platforms, delete the legacy settings file. delete legacy; QFile::remove(legacyFile); #endif } else { // If both settings objects point to the same location, removing the old stuff // may well break the new settings. delete legacy; } // ColorScheme -> ColorSchemeName QString colorSchemeName; switch (settings->value("SpeedCrunch/Display/ColorScheme", -1).toInt()) { case 0: colorSchemeName = "Terminal"; break; case 1: colorSchemeName = "Standard"; break; case 2: colorSchemeName = "Sublime"; break; default: colorSchemeName = DefaultColorScheme; break; } settings->setValue("SpeedCrunch/Display/ColorSchemeName", colorSchemeName); settings->remove("SpeedCrunch/Display/ColorScheme"); // DigitGrouping (bool) -> DigitGrouping (int) bool groupDigits = settings->value("SpeedCrunch/General/DigitGrouping", false).toBool(); settings->setValue("SpeedCrunch/General/DigitGrouping", groupDigits ? 1 : 0); } QSettings* createQSettings(const QString& KEY) { QSettings* settings = new QSettings(Settings::getConfigPath() + "/" + KEY + ".ini", QSettings::IniFormat); settings->setAtomicSyncRequired(!shouldUseNonAtomicSettingsSync(settings->fileName())); int ver = settings->value("ConfigVersion", 0).toInt(); switch (ver) { case 0: migrateSettings_legacyTo1200(settings, KEY); break; } settings->setValue("ConfigVersion", ConfigVersion); return settings; } heldercorreia-speedcrunch-e7ca37f/src/core/settings.h000066400000000000000000000225251526573132500230730ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_SETTINGS_H #define CORE_SETTINGS_H #include #include #include #include #include "core/complexform.h" #include "math/floatnum/floatconvert.h" class Settings { public: enum UpDownArrowBehavior { UpDownArrowBehaviorNever = 0, UpDownArrowBehaviorAlways = 1, UpDownArrowBehaviorSingleLineOnly = 2 }; enum KeypadMode { KeypadModeDisabled = 0, KeypadModeBasicWide = 1, KeypadModeBasicNarrow = 2, KeypadModeScientificWide = 3, KeypadModeScientificNarrow = 4, KeypadModeCustom = 5 }; enum CustomKeypadButtonAction { CustomKeypadActionInsertText = 0, CustomKeypadActionBackspace = 1, CustomKeypadActionClearExpression = 2, CustomKeypadActionEvaluateExpression = 3 }; enum MenuAppearance { MenuAppearanceSystem = 0, MenuAppearanceSpeedCrunch = 1 }; enum DockAppearance { DockAppearanceSystem = 0, DockAppearanceSpeedCrunch = 1 }; enum StatusBarAppearance { StatusBarAppearanceSystem = 0, StatusBarAppearanceSpeedCrunch = 1 }; enum EditorDisplayStyle { EditorDisplayModern = 0, EditorDisplayClassic = 1 }; enum KeypadAppearance { KeypadAppearanceModern = 0, KeypadAppearanceClassic = 1 }; enum NumberFormatStyle { NumberFormatSystem = 0, // Legacy value kept for migration compatibility. NumberFormatNoGroupingDot = 1, NumberFormatNoGroupingComma = 2, NumberFormatSIDot = 3, NumberFormatSIComma = 4, NumberFormatThreeDigitCommaDot = 5, NumberFormatThreeDigitCommaDotFraction = 6, NumberFormatThreeDigitDotComma = 7, NumberFormatThreeDigitDotCommaFraction = 8, NumberFormatThreeDigitSpaceDot = 9, NumberFormatThreeDigitSpaceComma = 10, NumberFormatThreeDigitUnderscoreDot = 11, NumberFormatThreeDigitUnderscoreDotFraction = 12, NumberFormatThreeDigitUnderscoreComma = 13, NumberFormatThreeDigitUnderscoreCommaFraction = 14, NumberFormatIndianCommaDot = 15 }; enum UnitNegativeExponentStyle : char { UnitNegativeExponentSuperscript = 's', UnitNegativeExponentFraction = 'f' }; enum ResultRoundingMode : char { ResultRoundingHalfAwayFromZero = 'a', ResultRoundingHalfEven = 'e', ResultRoundingTowardZero = 'z', ResultRoundingTowardPositiveInfinity = 'p', ResultRoundingTowardNegativeInfinity = 'm' }; struct CustomKeypadButton { int row; int column; QString label; QString text; CustomKeypadButtonAction action; }; struct CustomKeypad { int rows; int columns; QList buttons; }; static Settings* instance(); static QString getConfigPath(); static QString getDataPath(); static QString getCachePath(); static bool preparePortableStorage(QString* errorMessage); static CustomKeypad defaultCustomKeypad(); void load(); void save(); bool resetToDefaults(); void saveSessionLayoutJson(); char radixCharacter() const; // 0 or '*': Automatic. void setRadixCharacter(char c = 0); bool isRadixCharacterAuto() const; bool isRadixCharacterBoth() const; bool isDigitGroupingEnabled() const; bool isIndianDigitGrouping() const; QString digitGroupingSeparator() const; char decimalSeparator() const; void applyNumberFormatStyle(); bool complexNumbers; char imaginaryUnit; // 'i' or 'j'. char angleUnit; // 'r': radian; 'd': degree; 'g': gradian; 't': turn; 'v': revolution. // 'g': general; 'f': fixed; 'n': engineering; 'e': scientific; 'r': rational; // 'b': binary; 'o': octal; 'h': hexadecimal; 's': sexagesimal. char resultFormat; // Main notation. char alternativeResultFormat; // Secondary notation; '\0': disabled. char tertiaryResultFormat; // Tertiary notation; '\0': disabled. char quaternaryResultFormat; // Extra line #3 notation; '\0': disabled. char quinaryResultFormat; // Extra line #4 notation; '\0': disabled. bool secondaryResultEnabled; bool tertiaryResultEnabled; bool quaternaryResultEnabled; bool quinaryResultEnabled; bool multipleResultLinesEnabled; // UI toggle: show/use extra result lines. int resultPrecision; // Main precision. See HMath documentation. bool removeTrailingZeroes; char resultRoundingMode; char unitNegativeExponentStyle; int secondaryResultPrecision; // Secondary precision. int tertiaryResultPrecision; // Tertiary precision. int quaternaryResultPrecision; // Extra line #3 precision. int quinaryResultPrecision; // Extra line #4 precision. char resultComplexForm; // Global complex form: 'r' rectangular; 'e' exponential; 't' trigonometric; 'c' cis; 'p' phasor. bool secondaryComplexNumbers; char secondaryResultComplexForm; // Secondary complex form. bool tertiaryComplexNumbers; char tertiaryResultComplexForm; // Tertiary complex form. bool quaternaryComplexNumbers; char quaternaryResultComplexForm; // Extra line #3 complex form. bool quinaryComplexNumbers; char quinaryResultComplexForm; // Extra line #4 complex form. bool autoAns; bool autoCalc; bool autoCompletion; bool autoCompletionAcceptWithEnter; bool autoCompletionBuiltInFunctions; bool autoCompletionBuiltInVariables; bool autoCompletionLongFormUnits; bool autoCompletionUserFunctions; bool autoCompletionUserVariables; UpDownArrowBehavior upDownArrowBehavior; int digitGrouping; bool digitGroupingIntegerPartOnly; NumberFormatStyle numberFormatStyle; bool hasNumberFormatStyleSetting; bool leaveLastExpression; bool syntaxHighlighting; bool automaticInputAdjustments; bool inputDigitGrouping; bool cursorBlinking; bool escapeClearsEditor; bool hoverHighlightResults; bool windowAlwaysOnTop; bool autoResultToClipboard; bool simplifyResultExpressions; bool windowPositionSave; bool openPrivateTabOnStartup; QString startupUserDefinitions; bool constantsDockVisible; bool functionsDockVisible; bool historyDockVisible; bool keypadVisible; KeypadMode keypadMode; int keypadZoomPercent; CustomKeypad customKeypad; bool formulaBookDockVisible; bool statusBarVisible; bool menuBarVisible; bool variablesDockVisible; bool userFunctionsDockVisible; bool userUnitsDockVisible; bool windowOnfullScreen; bool bitfieldVisible; QString constantsDockDomain; QString constantsDockSubdomain; QString constantsDockSearchText; QString functionsDockDomain; QString functionsDockSearchText; QString userFunctionsDockSearchText; QString userUnitsDockSearchText; QString variablesDockSearchText; QString formulaBookActivePage; QString dockColumnOrdersJson; QString colorScheme; MenuAppearance menuAppearance; DockAppearance dockAppearance; StatusBarAppearance statusBarAppearance; EditorDisplayStyle editorDisplayStyle; KeypadAppearance keypadAppearance; QString customColorSchemeJson; QString displayFont; QString sessionLayoutJson; QString language; QByteArray windowState; QByteArray windowGeometry; QByteArray manualWindowGeometry; private: Settings(); Q_DISABLE_COPY(Settings) }; inline char g_runtimeUnitNegativeExponentStyle = Settings::UnitNegativeExponentSuperscript; inline char g_runtimeResultRoundingMode = Settings::ResultRoundingHalfAwayFromZero; inline bool isValidUnitNegativeExponentStyle(char style) { if (style != Settings::UnitNegativeExponentSuperscript && style != Settings::UnitNegativeExponentFraction) { return false; } return true; } inline void setRuntimeUnitNegativeExponentStyle(char style) { if (!isValidUnitNegativeExponentStyle(style)) return; g_runtimeUnitNegativeExponentStyle = style; } inline char runtimeUnitNegativeExponentStyle() { return g_runtimeUnitNegativeExponentStyle; } inline bool isValidResultRoundingMode(char mode) { if (mode != Settings::ResultRoundingHalfAwayFromZero && mode != Settings::ResultRoundingHalfEven && mode != Settings::ResultRoundingTowardZero && mode != Settings::ResultRoundingTowardPositiveInfinity && mode != Settings::ResultRoundingTowardNegativeInfinity) { return false; } return true; } inline void setRuntimeResultRoundingMode(char mode) { if (!isValidResultRoundingMode(mode)) return; g_runtimeResultRoundingMode = mode; io_rounding_mode ioMode = IO_ROUND_HALF_AWAY_FROM_ZERO; if (mode == Settings::ResultRoundingHalfEven) ioMode = IO_ROUND_HALF_EVEN; else if (mode == Settings::ResultRoundingTowardZero) ioMode = IO_ROUND_TOWARD_ZERO; else if (mode == Settings::ResultRoundingTowardPositiveInfinity) ioMode = IO_ROUND_TOWARD_PLUS_INFINITY; else if (mode == Settings::ResultRoundingTowardNegativeInfinity) ioMode = IO_ROUND_TOWARD_MINUS_INFINITY; float_set_output_rounding_mode(ioMode); } inline char runtimeResultRoundingMode() { return g_runtimeResultRoundingMode; } #endif heldercorreia-speedcrunch-e7ca37f/src/core/startupdiagnostics.h000066400000000000000000000337251526573132500251710ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_STARTUPDIAGNOSTICS_H #define CORE_STARTUPDIAGNOSTICS_H #include #include #include #include #include #include #include #include #include #include #include #include // Only startup is measured. Fixed phase names keep the report free of user data. // Repeated phases are aggregated so restoring many sessions uses bounded memory. namespace StartupDiagnostics { struct Phase { QString name; bool worker = false; qint64 firstStartNs = 0; qint64 totalNs = 0; qint64 longestNs = 0; int calls = 0; int running = 0; }; struct AppearanceCall { QString name; QString context; int widgetId = 0; int parentCall = 0; qint64 startNs = 0; qint64 durationNs = 0; // -1 means no comparison, 0 means first call, 1 changed, 2 unchanged. int inputs = -1; QString inputChanges; bool finished = false; }; struct AppearanceAssignment { int call = 0; int widgetId = 0; bool palette = false; int changed = 0; int unchanged = 0; int skipped = 0; }; struct Snapshot { QVector phases; QVector appearanceCalls; QVector appearanceAssignments; int omittedAppearanceRecords = 0; qint64 elapsedNs = 0; qint64 firstPaintNs = -1; bool started = false; bool complete = false; }; #ifdef SPEEDCRUNCH_ENABLE_STARTUP_DIAGNOSTICS inline constexpr bool isEnabled() { return true; } namespace Detail { struct State { QMutex mutex; QElapsedTimer clock; QVector phases; QVector appearanceCalls; QVector appearanceAssignments; QVector> widgets; QHash widgetIds; QHash previousInputs; QHash assignmentIndices; int omittedAppearanceRecords = 0; std::atomic_bool recording{false}; quint64 generation = 0; int openScopes = 0; qint64 firstPaintNs = -1; qint64 finishedNs = 0; }; inline State& state() { static State value; return value; } inline thread_local QString appearanceContext; inline thread_local int appearanceCall = -1; inline int widgetId(State& state, const QObject* widget) { if (!widget) return 0; const int previous = state.widgetIds.value(widget, 0); // A deleted widget's address can be reused during pane restoration. if (previous > 0 && state.widgets.at(previous - 1) == widget) return previous; if (state.widgets.size() >= 2048) return -1; state.widgets.append(QPointer(widget)); const int id = state.widgets.size(); state.widgetIds.insert(widget, id); return id; } } inline void begin() { auto& state = Detail::state(); QMutexLocker lock(&state.mutex); ++state.generation; state.phases.clear(); state.appearanceCalls.clear(); state.appearanceAssignments.clear(); state.widgets.clear(); state.widgetIds.clear(); state.previousInputs.clear(); state.assignmentIndices.clear(); state.omittedAppearanceRecords = 0; Detail::appearanceContext.clear(); Detail::appearanceCall = -1; state.openScopes = 0; state.firstPaintNs = -1; state.finishedNs = 0; state.clock.start(); state.recording.store(true); } inline bool isRecording() { return Detail::state().recording.load(); } inline int appearanceObjectId(const QObject* object) { if (!isRecording()) return -1; auto& state = Detail::state(); QMutexLocker lock(&state.mutex); return Detail::widgetId(state, object); } class Scope { public: explicit Scope(const char* name) { start(name); } ~Scope() { finish(); } Scope(const Scope&) = delete; Scope& operator=(const Scope&) = delete; void next(const char* name) { finish(); start(name); } void finish() { if (m_index < 0) return; auto& state = Detail::state(); QMutexLocker lock(&state.mutex); if (m_generation == state.generation) { const qint64 elapsed = state.clock.nsecsElapsed() - m_startNs; auto& phase = state.phases[m_index]; phase.totalNs += elapsed; phase.longestNs = qMax(phase.longestNs, elapsed); ++phase.calls; --phase.running; --state.openScopes; } m_index = -1; } private: void start(const char* name) { auto& state = Detail::state(); if (!state.recording.load()) return; QMutexLocker lock(&state.mutex); if (!state.recording.load()) return; m_generation = state.generation; m_startNs = state.clock.nsecsElapsed(); const bool worker = QCoreApplication::instance() && QThread::currentThread() != QCoreApplication::instance()->thread(); const QString label = QString::fromLatin1(name); for (int i = 0; i < state.phases.size(); ++i) { if (state.phases[i].name == label && state.phases[i].worker == worker) { m_index = i; break; } } if (m_index < 0) { m_index = state.phases.size(); state.phases.append(Phase{label, worker, m_startNs}); } ++state.phases[m_index].running; ++state.openScopes; } quint64 m_generation = 0; qint64 m_startNs = 0; int m_index = -1; }; // Context names are fixed at call sites. No user text goes into the report. class AppearanceContext { public: explicit AppearanceContext(const char* name) : m_previous(Detail::appearanceContext), m_active(isRecording()) { if (m_active) { Detail::appearanceContext = m_previous.isEmpty() ? QString::fromLatin1(name) : m_previous + QStringLiteral(" / ") + QString::fromLatin1(name); } } ~AppearanceContext() { if (m_active) Detail::appearanceContext = m_previous; } AppearanceContext(const AppearanceContext&) = delete; AppearanceContext& operator=(const AppearanceContext&) = delete; private: QString m_previous; bool m_active; }; class AppearanceScope { public: AppearanceScope(const char* name, QObject* widget = nullptr, const QByteArray& inputs = {}) : m_timing(name), m_previous(Detail::appearanceCall) { auto& state = Detail::state(); if (!isRecording()) return; QMutexLocker lock(&state.mutex); m_generation = state.generation; if (state.appearanceCalls.size() >= 512) { ++state.omittedAppearanceRecords; Detail::appearanceCall = -1; m_active = true; return; } const int id = Detail::widgetId(state, widget); AppearanceCall call; call.name = QString::fromLatin1(name); call.context = Detail::appearanceContext.isEmpty() ? QStringLiteral("Other startup callbacks") : Detail::appearanceContext; call.widgetId = id; call.parentCall = m_previous + 1; call.startNs = state.clock.nsecsElapsed(); if (!inputs.isEmpty() && id >= 0) { const QString key = call.name + QString::number(id); const auto previous = state.previousInputs.constFind(key); call.inputs = previous == state.previousInputs.constEnd() ? 0 : (*previous == inputs ? 2 : 1); state.previousInputs.insert(key, inputs); } m_index = state.appearanceCalls.size(); state.appearanceCalls.append(call); Detail::appearanceCall = m_index; m_active = true; } template , int> = 0> AppearanceScope(const char* name, QObject* widget, Factory&& inputs) : AppearanceScope(name, widget, isRecording() ? inputs() : QByteArray()) {} ~AppearanceScope() { if (!m_active) return; Detail::appearanceCall = m_previous; auto& state = Detail::state(); QMutexLocker lock(&state.mutex); if (m_index >= 0 && m_generation == state.generation) { auto& call = state.appearanceCalls[m_index]; call.durationNs = state.clock.nsecsElapsed() - call.startNs; call.finished = true; } } AppearanceScope(const AppearanceScope&) = delete; AppearanceScope& operator=(const AppearanceScope&) = delete; void observeInputs(const char* category, const QByteArray& inputs) { if (m_index < 0 || inputs.isEmpty()) return; auto& state = Detail::state(); QMutexLocker lock(&state.mutex); if (m_generation != state.generation) return; auto& call = state.appearanceCalls[m_index]; if (call.widgetId < 0) return; const QString label = QString::fromLatin1(category); const QString key = call.name + QString::number(call.widgetId) + label; const auto previous = state.previousInputs.constFind(key); const QString change = previous == state.previousInputs.constEnd() ? QStringLiteral("first") : (*previous == inputs ? QStringLiteral("unchanged") : QStringLiteral("changed")); state.previousInputs.insert(key, inputs); if (!call.inputChanges.isEmpty()) call.inputChanges += QLatin1Char(' '); call.inputChanges += label + QLatin1Char('=') + change; } template , int> = 0> void observeInputs(const char* category, Factory&& inputs) { if (m_index >= 0) observeInputs(category, inputs()); } private: Scope m_timing; int m_previous; int m_index = -1; quint64 m_generation = 0; bool m_active = false; }; inline void appearanceAssignment(QObject* widget, bool palette, bool changed, bool skipped) { if (!isRecording() || Detail::appearanceCall < 0) return; auto& state = Detail::state(); QMutexLocker lock(&state.mutex); const int id = Detail::widgetId(state, widget); const int call = Detail::appearanceCall + 1; if (id < 0) { ++state.omittedAppearanceRecords; return; } const quint64 key = (quint64(call) << 32) | (quint64(id) << 1) | quint64(palette); int index = state.assignmentIndices.value(key, -1); if (index < 0) { if (state.appearanceAssignments.size() >= 2048) { ++state.omittedAppearanceRecords; return; } index = state.appearanceAssignments.size(); state.appearanceAssignments.append(AppearanceAssignment{call, id, palette}); state.assignmentIndices.insert(key, index); } auto& assignment = state.appearanceAssignments[index]; if (skipped) ++assignment.skipped; else if (changed) ++assignment.changed; else ++assignment.unchanged; } // A shared scope spans a worker and its queued UI callback, including queue wait. inline std::shared_ptr task(const char* name) { return isRecording() ? std::make_shared(name) : nullptr; } inline void firstPaintFinished() { auto& state = Detail::state(); QMutexLocker lock(&state.mutex); if (!state.recording.load() || state.firstPaintNs >= 0) return; state.firstPaintNs = state.clock.nsecsElapsed(); } // The dispatcher reaches this point after handling paints and queued callbacks. inline void finishWhenIdle() { auto& state = Detail::state(); QMutexLocker lock(&state.mutex); if (!state.recording.load() || state.firstPaintNs < 0 || state.openScopes != 0) return; state.finishedNs = state.clock.nsecsElapsed(); state.recording.store(false); } inline Snapshot snapshot() { auto& state = Detail::state(); QMutexLocker lock(&state.mutex); Snapshot result; result.started = state.clock.isValid(); if (!result.started) return result; result.phases = state.phases; result.appearanceCalls = state.appearanceCalls; result.appearanceAssignments = state.appearanceAssignments; result.omittedAppearanceRecords = state.omittedAppearanceRecords; result.complete = !state.recording.load(); result.elapsedNs = result.complete ? state.finishedNs : state.clock.nsecsElapsed(); result.firstPaintNs = state.firstPaintNs; return result; } #else inline constexpr bool isEnabled() { return false; } inline constexpr bool isRecording() { return false; } inline void begin() {} inline int appearanceObjectId(const QObject*) { return -1; } class Scope { public: explicit Scope(const char*) {} Scope(const Scope&) = delete; Scope& operator=(const Scope&) = delete; void next(const char*) {} void finish() {} }; class AppearanceContext { public: explicit AppearanceContext(const char*) {} AppearanceContext(const AppearanceContext&) = delete; AppearanceContext& operator=(const AppearanceContext&) = delete; }; class AppearanceScope { public: explicit AppearanceScope(const char*, QObject* = nullptr, const QByteArray& = {}) {} template , int> = 0> AppearanceScope(const char*, QObject*, Factory&&) {} AppearanceScope(const AppearanceScope&) = delete; AppearanceScope& operator=(const AppearanceScope&) = delete; void observeInputs(const char*, const QByteArray&) {} template , int> = 0> void observeInputs(const char*, Factory&&) {} }; inline void appearanceAssignment(QObject*, bool, bool, bool) {} inline std::shared_ptr task(const char*) { return {}; } inline void firstPaintFinished() {} inline void finishWhenIdle() {} inline Snapshot snapshot() { return {}; } #endif } #endif heldercorreia-speedcrunch-e7ca37f/src/core/symbolcontext.h000066400000000000000000000111341526573132500241370ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_SYMBOLCONTEXT_H #define CORE_SYMBOLCONTEXT_H #include "core/userfunction.h" #include "core/userunit.h" #include "core/variable.h" #include #include #include #include #include class GlobalSymbols { public: static GlobalSymbols& instance() { static GlobalSymbols symbols; return symbols; } void clearUserDefinitionRegistry() { m_userVariables.clear(); m_userFunctions.clear(); m_userUnits.clear(); } void registerUserVariable(const QString& id) { m_userVariables.insert(id); } void registerUserFunction(const QString& name) { m_userFunctions.insert(name); } void registerUserUnit(const QString& name) { m_userUnits.insert(name); } bool isUserVariable(const QString& id) const { return m_userVariables.contains(id); } bool isUserFunction(const QString& name) const { return m_userFunctions.contains(name); } bool isUserUnit(const QString& name) const { return m_userUnits.contains(name); } private: GlobalSymbols() = default; Q_DISABLE_COPY(GlobalSymbols) QSet m_userVariables; QSet m_userFunctions; QSet m_userUnits; }; class SessionVariableRepository { public: void add(const Variable& variable) { m_variables[variable.identifier()] = variable; } bool contains(const QString& id) const { return m_variables.contains(id); } void remove(const QString& id) { m_variables.remove(id); } void clear() { m_variables.clear(); } Variable get(const QString& id) const { return m_variables.value(id); } QList toList() const { QList variables = m_variables.values(); std::sort(variables.begin(), variables.end(), [](const Variable& lhs, const Variable& rhs) { return lhs.identifier().compare(rhs.identifier(), Qt::CaseInsensitive) < 0; }); return variables; } bool isBuiltIn(const QString& id) const { return m_variables.contains(id) && m_variables.value(id).type() == Variable::BuiltIn; } private: QHash m_variables; }; class SessionFunctionRepository { public: void add(const UserFunction& function) { m_functions[function.name()] = function; } bool contains(const QString& name) const { return m_functions.contains(name); } void remove(const QString& name) { m_functions.remove(name); } void clear() { m_functions.clear(); } QList toList() const { QList functions = m_functions.values(); std::sort(functions.begin(), functions.end(), [](const UserFunction& lhs, const UserFunction& rhs) { return lhs.name().compare(rhs.name(), Qt::CaseInsensitive) < 0; }); return functions; } const UserFunction* get(const QString& name) const { auto it = m_functions.constFind(name); return it == m_functions.constEnd() ? nullptr : &it.value(); } private: QHash m_functions; }; class SessionUnitRepository { public: void add(const UserUnit& unit) { m_units[unit.name()] = unit; } bool contains(const QString& name) const { return m_units.contains(name); } void remove(const QString& name) { m_units.remove(name); } void clear() { m_units.clear(); } QList toList() const { QList units = m_units.values(); std::sort(units.begin(), units.end(), [](const UserUnit& lhs, const UserUnit& rhs) { return lhs.name().compare(rhs.name(), Qt::CaseInsensitive) < 0; }); return units; } const UserUnit* get(const QString& name) const { auto it = m_units.constFind(name); return it == m_units.constEnd() ? nullptr : &it.value(); } private: QHash m_units; }; class SymbolContext { public: SessionVariableRepository& variables() { return m_variables; } const SessionVariableRepository& variables() const { return m_variables; } SessionFunctionRepository& functions() { return m_functions; } const SessionFunctionRepository& functions() const { return m_functions; } SessionUnitRepository& units() { return m_units; } const SessionUnitRepository& units() const { return m_units; } GlobalSymbols& globals() { return GlobalSymbols::instance(); } const GlobalSymbols& globals() const { return GlobalSymbols::instance(); } private: SessionVariableRepository m_variables; SessionFunctionRepository m_functions; SessionUnitRepository m_units; }; #endif heldercorreia-speedcrunch-e7ca37f/src/core/symbolicnumberformat.h000066400000000000000000000053031526573132500254710ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_SYMBOLICNUMBERFORMAT_H #define CORE_SYMBOLICNUMBERFORMAT_H #include "core/mathdsl.h" #include "math/hmath.h" #include "math/rational.h" #include #include namespace SymbolicNumberFormat { inline HNumber trigSymbolicRelativeTolerance() { return HNumber("1e-30"); } inline bool isCloseToTrigSymbolicValue(const HNumber& value, const HNumber& reference) { const HNumber diff = HMath::abs(value - reference); const HNumber scale = HMath::max(HMath::abs(value), HMath::abs(reference)); const HNumber one(1); return diff <= trigSymbolicRelativeTolerance() * (scale < one ? one : scale); } inline QString formatFraction(const QString& numerator, int denominator) { const QString operatorSpace(MathDsl::DivWrap); return numerator + operatorSpace + MathDsl::DivOp + operatorSpace + QString::number(denominator); } inline QString formatPiMultiple(const HNumber& value) { constexpr int maxDenominator = 12; const HNumber pi = HMath::pi(); if (HMath::abs(value) > HNumber(2) * pi) return QString(); Rational ratio; if (!Rational::approximate(value / pi, maxDenominator, trigSymbolicRelativeTolerance(), &ratio)) { return QString(); } const int numerator = ratio.numerator(); const int denominator = ratio.denominator(); if (numerator == 0) return QString(); if (qAbs(numerator) > maxDenominator) return QString(); if (denominator != 1 && denominator != 2 && denominator != 3 && denominator != 4 && denominator != 6 && denominator != 8 && denominator != 12) { return QString(); } const HNumber expected = pi * HNumber(numerator) / HNumber(denominator); if (!isCloseToTrigSymbolicValue(value, expected)) return QString(); const QString mulSpace(MathDsl::MulDotWrapSp); if (denominator == 1) { if (numerator == 1) return QStringLiteral("pi"); if (numerator == -1) return QStringLiteral("-pi"); return QString::number(numerator) + mulSpace + MathDsl::MulDotOp + mulSpace + QStringLiteral("pi"); } QString numeratorText; if (numerator == 1) numeratorText = QStringLiteral("pi"); else if (numerator == -1) numeratorText = QStringLiteral("-pi"); else numeratorText = QString::number(numerator) + mulSpace + MathDsl::MulDotOp + mulSpace + QStringLiteral("pi"); return formatFraction(numeratorText, denominator); } } #endif // CORE_SYMBOLICNUMBERFORMAT_H heldercorreia-speedcrunch-e7ca37f/src/core/unicodechars.h000066400000000000000000000273151526573132500237040ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_UNICODECHARS_H #define CORE_UNICODECHARS_H #include "core/regexpatterns.h" #include #include namespace UnicodeChars { inline constexpr QChar Space(0x0020); // ' ' inline constexpr QChar DigitZero(0x0030); // '0' inline constexpr QChar DigitOne(0x0031); // '1' inline constexpr QChar DigitTwo(0x0032); // '2' inline constexpr QChar DigitThree(0x0033); // '3' inline constexpr QChar DigitFour(0x0034); // '4' inline constexpr QChar DigitFive(0x0035); // '5' inline constexpr QChar DigitSix(0x0036); // '6' inline constexpr QChar DigitSeven(0x0037); // '7' inline constexpr QChar DigitEight(0x0038); // '8' inline constexpr QChar DigitNine(0x0039); // '9' inline constexpr QChar LeftToRightMark(0x200E); // LRM inline constexpr QChar NoBreakSpace(0x00A0); // ' ' inline constexpr QChar MediumMathematicalSpace(0x205F); // 'â�Ÿ' inline constexpr QChar NarrowNoBreakSpace(0x202F); // ' ' inline constexpr QChar LeftParenthesis(0x0028); // '(' inline constexpr QChar RightParenthesis(0x0029); // ')' inline constexpr QChar LeftSquareBracket(0x005B); // '[' inline constexpr QChar RightSquareBracket(0x005D); // ']' inline constexpr QChar LeftCurlyBracket(0x007B); // '{' inline constexpr QChar RightCurlyBracket(0x007D); // '}' inline constexpr QChar PlusSign(0x002B); // '+' inline constexpr QChar FullwidthPlusSign(0xFF0B); // '+' inline constexpr QChar Colon(0x003A); // ':' inline constexpr QChar Semicolon(0x003B); // ';' inline constexpr QChar EqualsSign(0x003D); // '=' inline constexpr QChar LessThanSign(0x003C); // '<' inline constexpr QChar GreaterThanSign(0x003E); // '>' inline constexpr QChar Ampersand(0x0026); // '&' inline constexpr QChar VerticalLine(0x007C); // '|' inline constexpr QChar Comma(0x002C); // ',' inline constexpr QChar FullStop(0x002E); // '.' inline constexpr QChar Tilde(0x007E); // '~' inline constexpr QChar Apostrophe(0x0027); // ''' inline constexpr QChar NumberSign(0x0023); // '#' inline constexpr QChar DollarSign(0x0024); // '$' inline constexpr QChar ExclamationMark(0x0021); // '!' inline constexpr QChar PercentSign(0x0025); // '%' inline constexpr QChar QuestionMark(0x003F); // '?' inline constexpr QChar CircumflexAccent(0x005E); // '^' inline constexpr QChar ModifierLetterCircumflexAccent(0x02C6); // 'ˆ' inline constexpr QChar Caret(0x2038); // '‸' inline constexpr QChar FullwidthCircumflexAccent(0xFF3E); // 'ï¼¾' inline constexpr QChar Solidus(0x002F); // '/' inline constexpr QChar ReverseSolidus(0x005C); // '\' inline constexpr QChar HyphenMinus(0x002D); // '-' inline constexpr QChar Hyphen(0x2010); // 'â€�' inline constexpr QChar NonBreakingHyphen(0x2011); // '‑' inline constexpr QChar EnDash(0x2013); // '–' inline constexpr QChar EmDash(0x2014); // '—' inline constexpr QChar HorizontalBar(0x2015); // '―' inline constexpr QChar HyphenBullet(0x2043); // 'â�ƒ' inline constexpr QChar SmallHyphenMinus(0xFE63); // 'ï¹£' inline constexpr QChar FullwidthHyphenMinus(0xFF0D); // 'ï¼�' inline constexpr QChar MultiplicationSign(0x00D7); // '×' inline constexpr QChar MinusSign(0x2212); // '−' inline constexpr QChar DotOperator(0x22C5); // 'â‹…' inline constexpr QChar Asterisk(0x002A); // '*' inline constexpr QChar LowLine(0x005F); // '_' inline constexpr QChar QuotationMark(0x0022); // '"' inline constexpr QChar LatinSmallLetterI(0x0069); // 'i' inline constexpr QChar LatinSmallLetterP(0x0070); // 'p' inline constexpr QChar MiddleDot(0x00B7); // '·' inline constexpr QChar AsteriskOperator(0x2217); // '∗' inline constexpr QChar BulletOperator(0x2219); // '∙' inline constexpr QChar MultiplicationX(0x2715); // '✕' inline constexpr QChar HeavyMultiplicationX(0x2716); // '✖' inline constexpr QChar NAryTimesOperator(0x2A09); // '⨉' inline constexpr QChar VectorOrCrossProduct(0x2A2F); // '⨯' inline constexpr QChar GreekCapitalOmega(0x03A9); // 'Ω' inline constexpr QChar OhmSign(0x2126); // 'Ω' inline constexpr QChar MicroSign(0x00B5); // 'µ' inline constexpr QChar GreekSmallLetterMu(0x03BC); // 'μ' inline constexpr QChar Pi(0x03C0); // 'Ï€' inline constexpr QChar Summation(0x2211); // '∑' inline constexpr QChar Angle(0x2220); // '∠' inline constexpr QChar SquareRoot(0x221A); // '√' inline constexpr QChar CubeRoot(0x221B); // '∛' inline constexpr QChar RightwardsArrow(0x2192); // '→' inline constexpr QChar Prime(0x2032); // '′' inline constexpr QChar DoublePrime(0x2033); // '″' inline constexpr QChar DegreeSign(0x00B0); // '°' inline constexpr QChar FeminineOrdinalIndicator(0x00AA); // 'ª' inline constexpr QChar MasculineOrdinalIndicator(0x00BA); // 'º' inline constexpr QChar RingAbove(0x02DA); // 'Ëš' inline constexpr QChar RingOperator(0x2218); // '∘' inline constexpr QChar DivisionSign(0x00F7); // '÷' inline constexpr QChar DivisionSlash(0x2215); // '∕' inline constexpr QChar BigSolidus(0x29F8); // '⧸' inline constexpr QChar SuperscriptPlus(0x207A); // 'â�º' inline constexpr QChar SuperscriptMinus(0x207B); // 'â�»' inline constexpr QChar SuperscriptZero(0x2070); // 'â�°' inline constexpr QChar SuperscriptOne(0x00B9); // '¹' inline constexpr QChar SuperscriptTwo(0x00B2); // '²' inline constexpr QChar SuperscriptThree(0x00B3); // '³' inline constexpr QChar SuperscriptFour(0x2074); // 'â�´' inline constexpr QChar SuperscriptFive(0x2075); // 'â�µ' inline constexpr QChar SuperscriptSix(0x2076); // 'â�¶' inline constexpr QChar SuperscriptSeven(0x2077); // 'â�·' inline constexpr QChar SuperscriptEight(0x2078); // 'â�¸' inline constexpr QChar SuperscriptNine(0x2079); // 'â�¹' inline constexpr QChar SubscriptZero(0x2080); // 'â‚€' inline constexpr QChar SubscriptOne(0x2081); // 'â‚�' inline constexpr QChar SubscriptTwo(0x2082); // 'â‚‚' inline constexpr QChar SubscriptThree(0x2083); // '₃' inline constexpr QChar SubscriptFour(0x2084); // 'â‚„' inline constexpr QChar SubscriptFive(0x2085); // 'â‚…' inline constexpr QChar SubscriptSix(0x2086); // '₆' inline constexpr QChar SubscriptSeven(0x2087); // '₇' inline constexpr QChar SubscriptEight(0x2088); // '₈' inline constexpr QChar SubscriptNine(0x2089); // '₉' inline constexpr QChar LatinSubscriptSmallLetterA(0x2090); // 'â‚�' inline constexpr QChar LatinSubscriptSmallLetterE(0x2091); // 'â‚‘' inline constexpr QChar LatinSubscriptSmallLetterO(0x2092); // 'â‚’' inline constexpr QChar LatinSubscriptSmallLetterX(0x2093); // 'â‚“' inline constexpr QChar LatinSubscriptSmallLetterSchwa(0x2094); // 'â‚”' inline constexpr QChar LatinSubscriptSmallLetterH(0x2095); // 'â‚•' inline constexpr QChar LatinSubscriptSmallLetterK(0x2096); // 'â‚–' inline constexpr QChar LatinSubscriptSmallLetterL(0x2097); // 'â‚—' inline constexpr QChar LatinSubscriptSmallLetterM(0x2098); // 'ₘ' inline constexpr QChar LatinSubscriptSmallLetterN(0x2099); // 'â‚™' inline constexpr QChar LatinSubscriptSmallLetterP(0x209A); // 'ₚ' inline constexpr QChar LatinSubscriptSmallLetterS(0x209B); // 'â‚›' inline constexpr QChar LatinSubscriptSmallLetterT(0x209C); // 'ₜ' inline constexpr QChar LatinSubscriptSmallLetterI(0x1D62); // 'áµ¢' inline constexpr QChar LatinSubscriptSmallLetterR(0x1D63); // 'áµ£' inline constexpr QChar LatinSubscriptSmallLetterU(0x1D64); // 'ᵤ' inline constexpr QChar LatinSubscriptSmallLetterV(0x1D65); // 'áµ¥' inline constexpr QChar GreekSubscriptSmallLetterBeta(0x1D66); // 'ᵦ' inline constexpr QChar GreekSubscriptSmallLetterGamma(0x1D67); // 'áµ§' inline constexpr QChar GreekSubscriptSmallLetterRho(0x1D68); // 'ᵨ' inline constexpr QChar GreekSubscriptSmallLetterPhi(0x1D69); // 'ᵩ' inline constexpr QChar GreekSubscriptSmallLetterChi(0x1D6A); // 'ᵪ' // These pi variants are non-BMP Unicode code points (> U+FFFF), so they // cannot be represented as a single QChar (UTF-16 code unit). We keep them // as char32_t and feed them to QString::fromUcs4 when normalizing aliases. inline constexpr char32_t MathematicalBoldSmallPiCodePoint = 0x1D6D1; inline constexpr char32_t MathematicalItalicSmallPiCodePoint = 0x1D70B; inline constexpr char32_t MathematicalSansSerifBoldSmallPiCodePoint = 0x1D745; inline constexpr char32_t MathematicalSansSerifBoldItalicSmallPiCodePoint = 0x1D7B9; // Returns true if `ch` is a superscript decimal digit (0-9). // Example input/output: '²' -> true, '2' -> false. inline bool isSuperscriptDigit(QChar ch) { return ch == SuperscriptOne || ch == SuperscriptTwo || ch == SuperscriptThree || (ch.unicode() >= SuperscriptZero.unicode() && ch.unicode() <= SuperscriptNine.unicode()); } // Returns true if `ch` is a superscript sign used in exponents. // Example input/output: 'â�»' -> true, '-' -> false. inline bool isSuperscriptSign(QChar ch) { return ch == SuperscriptMinus || ch == SuperscriptPlus; } // Returns true when `ch` is accepted inside a simple unit identifier. // Example input/output: 'Ω' -> true, '/' -> false. inline bool isUnitIdentifierChar(QChar ch) { return ch.isLetterOrNumber() || ch == LowLine || ch == MicroSign || ch == GreekCapitalOmega || ch == DegreeSign || ch == MasculineOrdinalIndicator || ch == RingAbove; } // Replaces mathematical styled pi symbols with plain 'Ï€'. // Example input/output: "ð�›‘ + Ï€" -> "Ï€ + Ï€". inline QString normalizePiAliasesToPi(QString text) { const QString piSymbol(Pi); text.replace(QString::fromUcs4(&MathematicalBoldSmallPiCodePoint, 1), piSymbol); text.replace(QString::fromUcs4(&MathematicalItalicSmallPiCodePoint, 1), piSymbol); text.replace(QString::fromUcs4(&MathematicalSansSerifBoldSmallPiCodePoint, 1), piSymbol); text.replace(QString::fromUcs4(&MathematicalSansSerifBoldItalicSmallPiCodePoint, 1), piSymbol); return text; } // Normalizes unit-symbol aliases to canonical forms. // Example input/output: // "Ω(U+2126) μ(U+03BC) º(U+00BA) Ëš(U+02DA)" -> "Ω(U+03A9) µ(U+00B5) °(U+00B0) °(U+00B0)". inline QString normalizeUnitSymbolAliases(QString text) { text.replace(OhmSign, GreekCapitalOmega); text.replace(GreekSmallLetterMu, MicroSign); text.replace(MasculineOrdinalIndicator, DegreeSign); text.replace(RingAbove, DegreeSign); return text; } // Normalizes ASCII sexagesimal marks to Unicode prime symbols. // Example input/output: "12'34\"" -> "12′34″". inline QString normalizeSexagesimalSymbolAliases(QString text) { text.replace(Apostrophe, Prime); text.replace(QuotationMark, DoublePrime); return text; } // Normalizes pi text for display while preserving identifiers (e.g. "pixel"). // Example input/output: "2*pi + ð�›‘ + pixel" -> "2*Ï€ + Ï€ + pixel". inline QString normalizePiForDisplay(QString text) { text = normalizePiAliasesToPi(text); auto isIdentifierChar = [](QChar ch) { return ch.isLetter() || ch.isDigit() || ch == LowLine; }; for (int i = 0; i + 1 < text.size();) { if (text.at(i) == LatinSmallLetterP && text.at(i + 1) == LatinSmallLetterI) { const bool hasLeft = i > 0; const bool hasRight = i + 2 < text.size(); const bool leftIsIdentifier = hasLeft && isIdentifierChar(text.at(i - 1)); const bool rightIsIdentifier = hasRight && isIdentifierChar(text.at(i + 2)); if (!leftIsIdentifier && !rightIsIdentifier) { text.replace(i, 2, QString(Pi)); ++i; continue; } } ++i; } return text; } // Rewrites root/summation function words to display symbols. // Example input/output: "sqrt(x)+cbrt(y)+summation(k)" -> "√(x)+∛(y)+∑(k)". inline QString normalizeRootFunctionAliasesForDisplay(QString text) { text.replace(RegExpPatterns::summationWord(), QString(Summation)); text.replace(RegExpPatterns::sqrtWord(), QString(SquareRoot)); text.replace(RegExpPatterns::cbrtWord(), QString(CubeRoot)); return text; } } // namespace UnicodeChars #endif heldercorreia-speedcrunch-e7ca37f/src/core/unitdisplayformat.cpp000066400000000000000000000262531526573132500253460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/unitdisplayformat.h" #include "core/mathdsl.h" #include "core/unicodechars.h" #include "core/units.h" #include #include namespace UnitDisplayFormat { namespace { // Returns the index where a trailing superscript exponent suffix starts. // Supports ¹²³ and U+2070..U+2079 digits plus superscript plus/minus. int superscriptSuffixStart(const QString& text) { int suffixStart = text.size(); while (suffixStart > 0) { const QChar ch = text.at(suffixStart - 1); if (!UnicodeChars::isSuperscriptDigit(ch) && !UnicodeChars::isSuperscriptSign(ch)) break; --suffixStart; } return suffixStart; } // Builds an identifier->symbol cache from unit metadata, used to collapse // long names (and aliases) to short display symbols. const QHash& shortNamesByIdentifier() { static const QHash shortNames = [] { QHash map; const auto& values = Units::builtInUnitValues(); for (auto it = values.constBegin(); it != values.constEnd(); ++it) { const QString& identifier = it.key(); UnitId id = unitId(normalizeUnitName(identifier)); if (id == UnitId::Unknown) continue; const QString symbol = unitSymbol(id); if (!symbol.isEmpty()) map.insert(identifier, symbol); } return map; }(); return shortNames; } QString compositeAngleAlias(UnitId id) { if (id == UnitId::Degree) return Units::degreeAliasSymbol(); if (id == UnitId::Arcminute) return Units::arcminuteAliasSymbol(); if (id == UnitId::Arcsecond) return Units::arcsecondAliasSymbol(); return QString(); } UnitId unitIdForDisplayTokenBase(const QString& tokenBase) { const UnitId id = unitId(normalizeUnitName(tokenBase)); if (id != UnitId::Unknown) return id; if (tokenBase == unitSymbol(UnitId::Degree)) return UnitId::Degree; if (tokenBase == unitSymbol(UnitId::Arcminute)) return UnitId::Arcminute; if (tokenBase == unitSymbol(UnitId::Arcsecond)) return UnitId::Arcsecond; return UnitId::Unknown; } bool isDisplayUnitTokenChar(QChar ch) { return UnicodeChars::isUnitIdentifierChar(ch) || ch == UnicodeChars::Prime || ch == UnicodeChars::DoublePrime || UnicodeChars::isSuperscriptDigit(ch) || UnicodeChars::isSuperscriptSign(ch); } QString superscriptFromPositiveExponent(int exponent) { if (exponent <= 1) return QString(); QString superscript; const QString digits = QString::number(exponent); superscript.reserve(digits.size()); for (const QChar& digit : digits) superscript.append(MathDsl::asciiDigitToSuperscript(digit)); return superscript; } int parseTokenExponent(const QString& token, int* baseEnd, bool* ok) { *ok = false; *baseEnd = token.size(); if (token.isEmpty()) return 0; const int suffixStart = superscriptSuffixStart(token); if (suffixStart >= token.size()) return 1; bool negative = false; int pos = suffixStart; if (token.at(pos) == MathDsl::PowNeg || token.at(pos) == MathDsl::PowPos) { negative = token.at(pos) == MathDsl::PowNeg; ++pos; } if (pos >= token.size()) return 0; QString asciiDigits; asciiDigits.reserve(token.size() - pos); for (; pos < token.size(); ++pos) { const QChar asciiDigit = MathDsl::superscriptDigitToAscii(token.at(pos)); if (asciiDigit.isNull()) return 0; asciiDigits.append(asciiDigit); } bool intOk = false; const int exponent = asciiDigits.toInt(&intOk); if (!intOk) return 0; *ok = true; *baseEnd = suffixStart; return negative ? -exponent : exponent; } QString simplifyCompositeUnitText(const QString& text) { if (text.isEmpty() || text.contains(MathDsl::GroupStart) || text.contains(MathDsl::GroupEnd)) { return text; } struct UnitFactor { QString base; int exponent = 0; }; QVector factors; QHash factorIndexByBase; bool hasRepeatedBase = false; auto appendFactor = [&](const QString& token, bool inDenominator) { if (token.isEmpty()) return; int baseEnd = token.size(); bool hasExplicitExponent = false; int exponent = parseTokenExponent(token, &baseEnd, &hasExplicitExponent); if (!hasExplicitExponent) exponent = 1; const QString base = token.left(baseEnd); if (base.isEmpty()) return; if (inDenominator) exponent = -exponent; if (!factorIndexByBase.contains(base)) { UnitFactor factor; factor.base = base; factor.exponent = exponent; factors.append(factor); factorIndexByBase.insert(base, factors.size() - 1); return; } hasRepeatedBase = true; UnitFactor& existing = factors[factorIndexByBase.value(base)]; existing.exponent += exponent; }; QString currentToken; bool denominatorForNextToken = false; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); const bool isSpaceSep = ch.isSpace(); const bool isMul = ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp; const bool isDiv = ch == MathDsl::DivOp; if (!isSpaceSep && !isMul && !isDiv) { currentToken.append(ch); continue; } appendFactor(currentToken.trimmed(), denominatorForNextToken); currentToken.clear(); // '/' only affects the immediately following factor; multiplication // separators start a new factor in numerator context. denominatorForNextToken = isDiv; } appendFactor(currentToken.trimmed(), denominatorForNextToken); if (!hasRepeatedBase) return text; QStringList numerators; QStringList denominators; numerators.reserve(factors.size()); denominators.reserve(factors.size()); for (const UnitFactor& factor : factors) { if (factor.exponent == 0) continue; if (factor.exponent > 0) { numerators.append(factor.base + superscriptFromPositiveExponent(factor.exponent)); } else { denominators.append(factor.base + superscriptFromPositiveExponent(-factor.exponent)); } } if (numerators.isEmpty() && denominators.isEmpty()) return QStringLiteral("1"); const QString mulOp = QString(MathDsl::MulDotOp); if (denominators.isEmpty()) return numerators.join(mulOp); QString result = numerators.isEmpty() ? QStringLiteral("1") : numerators.join(mulOp); if (denominators.size() == 1) { result += QString(MathDsl::DivOp) + denominators.first(); } else { result += QString(MathDsl::DivOp) + QString(MathDsl::GroupStart) + denominators.join(mulOp) + QString(MathDsl::GroupEnd); } return result; } } // namespace // Collapses a unit token to a compact display form: // canonical symbol when known, preserving superscript exponent suffixes. // Examples: // - "metre" -> "m" // - "kilometre" -> "km" // - "quebibyte" -> "QiB" // - "metreâ�»Â²" -> "mâ�»Â²" QString shortDisplayName(const QString& name) { const QString trimmed = name.trimmed(); if (trimmed.isEmpty()) return trimmed; const int suffixStart = superscriptSuffixStart(trimmed); const QString baseName = trimmed.left(suffixStart); const QString exponentSuffix = trimmed.mid(suffixStart); const auto& shortNames = shortNamesByIdentifier(); if (shortNames.contains(baseName)) return shortNames.value(baseName) + exponentSuffix; for (const PrefixId id : siPrefixIds()) { const QString prefixLong = prefixName(id); if (!baseName.startsWith(prefixLong)) continue; const QString base = baseName.mid(prefixLong.size()); if (shortNames.contains(base)) return prefixSymbol(id) + shortNames.value(base) + exponentSuffix; } for (const PrefixId id : binaryPrefixIds()) { const QString prefixLong = prefixName(id); if (!baseName.startsWith(prefixLong)) continue; const QString base = baseName.mid(prefixLong.size()); if (shortNames.contains(base)) return prefixSymbol(id) + shortNames.value(base) + exponentSuffix; } return trimmed; } // Normalizes a full unit-expression string for display by tokenizing around // separators/operators and applying token-level formatting. // Examples: // - "metre secondâ�»Â¹" -> "m sâ�»Â¹" // - "joule/(mole kelvin)" -> "J/(mol K)" // - "kilogram·metre/second²" -> "kg·m/s²" QString normalizeUnitTextForDisplay(const QString& text) { if (text.isEmpty()) return text; const bool hasCompositeUnitOperators = text.contains(MathDsl::MulOpAl1) || text.contains(MathDsl::MulDotOp) || text.contains(MathDsl::MulCrossOp) || text.contains(MathDsl::DivOp); QString displayInput = text; if (hasCompositeUnitOperators) { displayInput.replace(UnicodeChars::DegreeSign, Units::degreeAliasSymbol()); displayInput.replace(UnicodeChars::Prime, Units::arcminuteAliasSymbol()); displayInput.replace(UnicodeChars::DoublePrime, Units::arcsecondAliasSymbol()); } QString normalized; normalized.reserve(displayInput.size()); for (int i = 0; i < displayInput.size();) { const QChar ch = displayInput.at(i); if (!isDisplayUnitTokenChar(ch)) { normalized.append(ch); ++i; continue; } int j = i + 1; while (j < displayInput.size() && isDisplayUnitTokenChar(displayInput.at(j))) ++j; const QString token = displayInput.mid(i, j - i); const int tokenSuffixStart = superscriptSuffixStart(token); const QString tokenBase = token.left(tokenSuffixStart); const bool hasExponentSuffix = tokenSuffixStart < token.size(); QString displayToken = shortDisplayName(token); const UnitId tokenId = unitIdForDisplayTokenBase(tokenBase); const QString preferredAlias = compositeAngleAlias(tokenId); const bool shouldPreferAlias = !preferredAlias.isEmpty() && (hasCompositeUnitOperators || hasExponentSuffix); if (shouldPreferAlias) { QString suffix; const QString tokenSymbol = unitSymbol(tokenId); if (!displayToken.isEmpty() && displayToken.startsWith(tokenSymbol)) { suffix = displayToken.mid(tokenSymbol.size()); } else if (displayToken.startsWith(preferredAlias)) { suffix = displayToken.mid(preferredAlias.size()); } displayToken = preferredAlias + suffix; } normalized.append(displayToken); i = j; } if (hasCompositeUnitOperators) return simplifyCompositeUnitText(normalized); return normalized; } } // namespace UnitDisplayFormat heldercorreia-speedcrunch-e7ca37f/src/core/unitdisplayformat.h000066400000000000000000000005351526573132500250060ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef UNITDISPLAYFORMAT_H #define UNITDISPLAYFORMAT_H #include namespace UnitDisplayFormat { QString shortDisplayName(const QString& name); QString normalizeUnitTextForDisplay(const QString& text); } #endif // UNITDISPLAYFORMAT_H heldercorreia-speedcrunch-e7ca37f/src/core/units.cpp000066400000000000000000004204361526573132500227330ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "core/units.h" #include "core/unicodechars.h" #include "core/settings.h" #include "math/hmath.h" #include "core/mathdsl.h" #include "math/quantity.h" #include "math/rational.h" #include #include #include #include #include #include #include /* - Source #1: The International System of Units - 9th edition (2019) Bureau International des Poids et Mesures Published in May 2019 - Revised in August 2025 https://doi.org/10.59161/AUEZ1291 - Source #2: SI Reference Point Bureau International des Poids et Mesures https://si-digital-framework.org/SI/units - Source #3: The Unified Code for Units of Measure Regenstrief Institute, Inc. and the UCUM Organization Version: 2.2 | Revision: N/A | Date: 2024-06-17 https://ucum.org/ucum - Source #4: https://www.nist.gov/system/files/documents/2025/12/30/appc-26-HB44-20251222.pdf - Source #5: https://qudt.org/vocab/unit/ */ namespace UnitText { inline constexpr QStringView NewtonMetre{u"newton metre", 12}; inline constexpr QStringView WattSecond{u"watt second", 11}; inline constexpr QStringView VoltSquaredAmpere{u"volt² ampere", 12}; inline constexpr QStringView JoulePerSquareMetre{u"joule / metre²", 14}; inline constexpr QStringView JoulePerCubicMetre{u"joule / metre³", 14}; } // namespace UnitText namespace UnitName { inline const QString Acre = QStringLiteral("acre"); inline const QString Ampere = QStringLiteral("ampere"); inline const QString Angstrom = QStringLiteral("angstrom"); inline const QString Arcminute = QStringLiteral("arcminute"); inline const QString Arcsecond = QStringLiteral("arcsecond"); inline const QString Milliarcsecond = QStringLiteral("milliarcsecond"); inline const QString Microarcsecond = QStringLiteral("microarcsecond"); inline const QString AstronomicalUnit = QStringLiteral("astronomical_unit"); inline const QString Atmosphere = QStringLiteral("atmosphere"); inline const QString AtomicMassUnit = QStringLiteral("atomic_mass_unit"); inline const QString Bar = QStringLiteral("bar"); inline const QString Becquerel = QStringLiteral("becquerel"); inline const QString Bit = QStringLiteral("bit"); inline const QString BritishThermalUnit = QStringLiteral("british_thermal_unit"); inline const QString Byte = QStringLiteral("byte"); inline const QString Calorie = QStringLiteral("calorie"); inline const QString Candela = QStringLiteral("candela"); inline const QString Carat = QStringLiteral("carat"); inline const QString Coulomb = QStringLiteral("coulomb"); inline const QString CubicMetre = QStringLiteral("cubic_metre"); inline const QString CubicMillimetre = QStringLiteral("cubic_millimetre"); inline const QString CubicCentimetre = QStringLiteral("cubic_centimetre"); inline const QString CubicDecimetre = QStringLiteral("cubic_decimetre"); inline const QString CubicKilometre = QStringLiteral("cubic_kilometre"); inline const QString SquareMillimetre = QStringLiteral("square_millimetre"); inline const QString SquareKilometre = QStringLiteral("square_kilometre"); inline const QString Cup = QStringLiteral("cup"); inline const QString CupImp = QStringLiteral("cup_imp"); inline const QString CupJp = QStringLiteral("cup_jp"); inline const QString CupUs = QStringLiteral("cup_us"); inline const QString Dalton = QStringLiteral("dalton"); inline const QString Day = QStringLiteral("day"); inline const QString Degree = QStringLiteral("degree"); inline const QString DegreeCelsius = QStringLiteral("degree_celsius"); inline const QString DegreeFahrenheit = QStringLiteral("degree_fahrenheit"); inline const QString Electronvolt = QStringLiteral("electronvolt"); inline const QString Farad = QStringLiteral("farad"); inline const QString Fathom = QStringLiteral("fathom"); inline const QString FluidOunceImp = QStringLiteral("fluid_ounce_imp"); inline const QString FluidOunceUs = QStringLiteral("fluid_ounce_us"); inline const QString FluidDramImp = QStringLiteral("fluid_dram_imp"); inline const QString FluidDramUs = QStringLiteral("fluid_dram_us"); inline const QString Foot = QStringLiteral("foot"); inline const QString SquareFoot = QStringLiteral("square_foot"); inline const QString CubicFoot = QStringLiteral("cubic_foot"); inline const QString Furlong = QStringLiteral("furlong"); inline const QString GallonImp = QStringLiteral("gallon_imp"); inline const QString GallonUs = QStringLiteral("gallon_us"); inline const QString GillImp = QStringLiteral("gill_imp"); inline const QString GillUs = QStringLiteral("gill_us"); inline const QString Gradian = QStringLiteral("gradian"); inline const QString Grain = QStringLiteral("grain"); inline const QString Gram = QStringLiteral("gram"); inline const QString Gray = QStringLiteral("gray"); inline const QString Hartley = QStringLiteral("hartley"); inline const QString HartreeEnergyUnit = QStringLiteral("hartree_energy_unit"); inline const QString Hectare = QStringLiteral("hectare"); inline const QString Henry = QStringLiteral("henry"); inline const QString Hertz = QStringLiteral("hertz"); inline const QString Horsepower = QStringLiteral("horsepower"); inline const QString Hour = QStringLiteral("hour"); inline const QString Inch = QStringLiteral("inch"); inline const QString SquareInch = QStringLiteral("square_inch"); inline const QString CubicInch = QStringLiteral("cubic_inch"); inline const QString Joule = QStringLiteral("joule"); inline const QString Karat = QStringLiteral("karat"); inline const QString Katal = QStringLiteral("katal"); inline const QString Kelvin = QStringLiteral("kelvin"); inline const QString Kilogram = QStringLiteral("kilogram"); inline const QString Knot = QStringLiteral("knot"); inline const QString Lightminute = QStringLiteral("lightminute"); inline const QString Lightsecond = QStringLiteral("lightsecond"); inline const QString Lightyear = QStringLiteral("lightyear"); inline const QString Litre = QStringLiteral("litre"); inline const QString LongTon = QStringLiteral("long_ton"); inline const QString Lumen = QStringLiteral("lumen"); inline const QString Lux = QStringLiteral("lux"); inline const QString Metre = QStringLiteral("metre"); inline const QString Mile = QStringLiteral("mile"); inline const QString SquareMile = QStringLiteral("square_mile"); inline const QString CubicMile = QStringLiteral("cubic_mile"); inline const QString MilePerHour = QStringLiteral("mile_per_hour"); inline const QString KilometrePerHour = QStringLiteral("kilometre_per_hour"); inline const QString Minute = QStringLiteral("minute"); inline const QString Mole = QStringLiteral("mole"); inline const QString Nat = QStringLiteral("nat"); inline const QString NauticalMile = QStringLiteral("nautical_mile"); inline const QString Newton = QStringLiteral("newton"); inline const QString Ohm = QStringLiteral("ohm"); inline const QString Ounce = QStringLiteral("ounce"); inline const QString Parsec = QStringLiteral("parsec"); inline const QString Pascal = QStringLiteral("pascal"); inline const QString PintImp = QStringLiteral("pint_imp"); inline const QString PintUs = QStringLiteral("pint_us"); inline const QString Pound = QStringLiteral("pound"); inline const QString PoundsPerSqinch = QStringLiteral("pounds_per_sqinch"); inline const QString QuartImp = QStringLiteral("quart_imp"); inline const QString QuartUs = QStringLiteral("quart_us"); inline const QString BarrelOil = QStringLiteral("barrel_oil"); inline const QString BarrelBeerUs = QStringLiteral("barrel_beer_us"); inline const QString Radian = QStringLiteral("radian"); inline const QString Rod = QStringLiteral("rod"); inline const QString SquareYard = QStringLiteral("square_yard"); inline const QString CubicYard = QStringLiteral("cubic_yard"); inline const QString Second = QStringLiteral("second"); inline const QString ShortTon = QStringLiteral("short_ton"); inline const QString Stone = QStringLiteral("stone"); inline const QString Siemens = QStringLiteral("siemens"); inline const QString Sievert = QStringLiteral("sievert"); inline const QString SquareMetre = QStringLiteral("square_metre"); inline const QString Steradian = QStringLiteral("steradian"); inline const QString Tablespoon = QStringLiteral("tablespoon"); inline const QString TablespoonAu = QStringLiteral("tablespoon_au"); inline const QString TablespoonImp = QStringLiteral("tablespoon_imp"); inline const QString TablespoonUs = QStringLiteral("tablespoon_us"); inline const QString DessertSpoon = QStringLiteral("dessert_spoon"); inline const QString Teaspoon = QStringLiteral("teaspoon"); inline const QString TeaspoonImp = QStringLiteral("teaspoon_imp"); inline const QString TeaspoonUs = QStringLiteral("teaspoon_us"); inline const QString Tesla = QStringLiteral("tesla"); inline const QString Tonne = QStringLiteral("tonne"); inline const QString Torr = QStringLiteral("torr"); inline const QString Turn = QStringLiteral("turn"); inline const QString Revolution = QStringLiteral("revolution"); inline const QString RevolutionPerMinute = QStringLiteral("revolution_per_minute"); inline const QString Volt = QStringLiteral("volt"); inline const QString Watt = QStringLiteral("watt"); inline const QString KilowattHour = QStringLiteral("kilowatt_hour"); inline const QString MillimetreOfMercury = QStringLiteral("millimetre_of_mercury"); inline const QString Quad = QStringLiteral("quad"); inline const QString Weber = QStringLiteral("weber"); inline const QString Week = QStringLiteral("week"); inline const QString Yard = QStringLiteral("yard"); inline const QString CenturyJulian = QStringLiteral("century_julian"); inline const QString YearJulian = QStringLiteral("year_julian"); inline const QString YearSidereal = QStringLiteral("year_sidereal"); inline const QString YearTropical = QStringLiteral("year_tropical"); } // namespace UnitName namespace UnitSymbol { inline const QString Acre = QStringLiteral("ac"); inline const QString Ampere = QStringLiteral("A"); inline const QString Angstrom = QStringLiteral("Ã…"); inline const QString Arcminute = QStringLiteral("′"); inline const QString Arcsecond = QStringLiteral("″"); inline const QString Milliarcsecond = QStringLiteral("mas"); inline const QString Microarcsecond = QStringLiteral("µas"); inline const QString AstronomicalUnit = QStringLiteral("au"); inline const QString Atmosphere = QStringLiteral("atm"); inline const QString AtomicMassUnit = QStringLiteral("u"); inline const QString Bar = QStringLiteral("bar"); inline const QString Becquerel = QStringLiteral("Bq"); inline const QString Bit = QStringLiteral("b"); inline const QString BritishThermalUnit = QStringLiteral("Btu"); inline const QString Byte = QStringLiteral("B"); inline const QString Calorie = QStringLiteral("cal"); inline const QString Candela = QStringLiteral("cd"); inline const QString Carat = QStringLiteral("ct"); inline const QString Coulomb = QStringLiteral("C"); inline const QString CubicMetre = QStringLiteral("m³"); inline const QString CubicMillimetre = QStringLiteral("mm³"); inline const QString CubicCentimetre = QStringLiteral("cm³"); inline const QString CubicDecimetre = QStringLiteral("dm³"); inline const QString CubicKilometre = QStringLiteral("km³"); inline const QString SquareMillimetre = QStringLiteral("mm²"); inline const QString SquareKilometre = QStringLiteral("km²"); inline const QString Cup = QStringLiteral("cup"); inline const QString CupImp = QStringLiteral("cup_imp"); inline const QString CupJp = QStringLiteral("cup_jp"); inline const QString CupUs = QStringLiteral("cup_us"); inline const QString Dalton = QStringLiteral("Da"); inline const QString Day = QStringLiteral("d"); inline const QString Degree = QStringLiteral("°"); inline const QString DegreeCelsius = QStringLiteral("°C"); inline const QString DegreeFahrenheit = QStringLiteral("°F"); inline const QString Electronvolt = QStringLiteral("eV"); inline const QString Farad = QStringLiteral("F"); inline const QString Fathom = QStringLiteral("fathom"); // Source #5 inline const QString FluidOunceImp = QStringLiteral("floz_imp"); inline const QString FluidOunceUs = QStringLiteral("floz_us"); inline const QString FluidDramImp = QStringLiteral("fldr_imp"); inline const QString FluidDramUs = QStringLiteral("fldr_us"); inline const QString Foot = QStringLiteral("ft"); inline const QString SquareFoot = QStringLiteral("ft²"); inline const QString CubicFoot = QStringLiteral("ft³"); inline const QString Furlong = QStringLiteral("fur"); // Source #4 inline const QString GallonImp = QStringLiteral("gal_imp"); inline const QString GallonUs = QStringLiteral("gal_us"); inline const QString GillImp = QStringLiteral("gill_imp"); inline const QString GillUs = QStringLiteral("gill_us"); inline const QString Gradian = QStringLiteral("gon"); inline const QString Grain = QStringLiteral("gr"); inline const QString Gram = QStringLiteral("g"); inline const QString Gray = QStringLiteral("Gy"); inline const QString Hartley = QStringLiteral("Hart"); inline const QString HartreeEnergyUnit = QStringLiteral("Eh"); inline const QString Hectare = QStringLiteral("ha"); inline const QString Henry = QStringLiteral("H"); inline const QString Hertz = QStringLiteral("Hz"); inline const QString Horsepower = QStringLiteral("hp"); inline const QString Hour = QStringLiteral("h"); inline const QString Inch = MathDsl::TransOpAl1; inline const QString SquareInch = QStringLiteral("in²"); inline const QString CubicInch = QStringLiteral("in³"); inline const QString Joule = QStringLiteral("J"); inline const QString Karat = QStringLiteral("Kt"); inline const QString Katal = QStringLiteral("kat"); inline const QString Kelvin = QStringLiteral("K"); inline const QString Kilogram = QStringLiteral("kg"); inline const QString Knot = QStringLiteral("kn"); inline const QString Lightminute = QStringLiteral("lmin"); inline const QString Lightsecond = QStringLiteral("ls"); inline const QString Lightyear = QStringLiteral("ly"); inline const QString Litre = QStringLiteral("L"); inline const QString LongTon = QStringLiteral("long_ton"); inline const QString Lumen = QStringLiteral("lm"); inline const QString Lux = QStringLiteral("lx"); inline const QString Metre = QStringLiteral("m"); inline const QString Mile = QStringLiteral("mi"); inline const QString SquareMile = QStringLiteral("mi²"); inline const QString CubicMile = QStringLiteral("mi³"); inline const QString MilePerHour = QStringLiteral("mph"); inline const QString KilometrePerHour = QStringLiteral("kph"); inline const QString Minute = QStringLiteral("min"); inline const QString Mole = QStringLiteral("mol"); inline const QString Nat = QStringLiteral("nat"); inline const QString NauticalMile = QStringLiteral("nmi"); inline const QString Newton = QStringLiteral("N"); inline const QString Ohm = QStringLiteral("Ω"); inline const QString Ounce = QStringLiteral("oz"); inline const QString Parsec = QStringLiteral("pc"); inline const QString Pascal = QStringLiteral("Pa"); inline const QString PintImp = QStringLiteral("pt_imp"); inline const QString PintUs = QStringLiteral("pt_us"); inline const QString Pound = QStringLiteral("lb"); inline const QString PoundsPerSqinch = QStringLiteral("psi"); inline const QString QuartImp = QStringLiteral("qt_imp"); inline const QString QuartUs = QStringLiteral("qt_us"); inline const QString BarrelOil = QStringLiteral("bbl_oil"); inline const QString BarrelBeerUs = QStringLiteral("bbl_beer"); inline const QString Radian = QStringLiteral("rad"); inline const QString Rod = QStringLiteral("rd"); // Source #4 inline const QString SquareYard = QStringLiteral("yd²"); inline const QString CubicYard = QStringLiteral("yd³"); inline const QString Second = QStringLiteral("s"); inline const QString ShortTon = QStringLiteral("tn"); // Source #4 inline const QString Stone = QStringLiteral("st"); inline const QString Siemens = QStringLiteral("S"); inline const QString Sievert = QStringLiteral("Sv"); inline const QString SquareMetre = QStringLiteral("m²"); inline const QString Steradian = QStringLiteral("sr"); inline const QString Tablespoon = QStringLiteral("tbsp"); inline const QString TablespoonAu = QStringLiteral("tbsp_au"); inline const QString TablespoonImp = QStringLiteral("tbsp_imp"); inline const QString TablespoonUs = QStringLiteral("tbsp_us"); inline const QString DessertSpoon = QStringLiteral("dsp"); inline const QString Teaspoon = QStringLiteral("tsp"); inline const QString TeaspoonImp = QStringLiteral("tsp_imp"); inline const QString TeaspoonUs = QStringLiteral("tsp_us"); inline const QString Tesla = QStringLiteral("T"); inline const QString Tonne = QStringLiteral("t"); inline const QString Torr = QStringLiteral("Torr"); inline const QString Turn = QStringLiteral("tr"); inline const QString Revolution = QStringLiteral("rev"); inline const QString RevolutionPerMinute = QStringLiteral("rpm"); inline const QString Volt = QStringLiteral("V"); inline const QString Watt = QStringLiteral("W"); inline const QString KilowattHour = QStringLiteral("kWh"); inline const QString MillimetreOfMercury = QStringLiteral("mmHg"); inline const QString Quad = QStringLiteral("quad"); inline const QString Weber = QStringLiteral("Wb"); inline const QString Week = QStringLiteral("wk"); inline const QString Yard = QStringLiteral("yd"); inline const QString CenturyJulian = QStringLiteral("cy_jul"); inline const QString YearJulian = QStringLiteral("a_jul"); inline const QString YearSidereal = QStringLiteral("a_sid"); inline const QString YearTropical = QStringLiteral("a_trop"); } // namespace UnitSymbol namespace UnitAltSymbol { inline const QString Arcminute = QStringLiteral("arcmin"); inline const QString Arcsecond = QStringLiteral("arcsec"); inline const QString Degree1 = QStringLiteral("deg"); inline const QString Degree2 = QStringLiteral("Ëš"); inline const QString DegreeCelsius1 = QStringLiteral("ºC"); inline const QString DegreeCelsius2 = QStringLiteral("oC"); inline const QString DegreeCelsius3 = QStringLiteral("degC"); inline const QString DegreeCelsius4 = QStringLiteral("Cel"); inline const QString DegreeCelsius5 = QStringLiteral("ËšC"); inline const QString DegreeFahrenheit1 = QStringLiteral("ºF"); inline const QString DegreeFahrenheit2 = QStringLiteral("oF"); inline const QString DegreeFahrenheit3 = QStringLiteral("degF"); inline const QString DegreeFahrenheit4 = QStringLiteral("Fah"); inline const QString DegreeFahrenheit5 = QStringLiteral("ËšF"); inline const QString MicroarcsecondAscii = QStringLiteral("uas"); inline const QString CubicCentimetre = QStringLiteral("cc"); inline const QString Litre = QStringLiteral("l"); inline const QString Turn = QStringLiteral("pla"); } // namespace UnitAltSymbol struct UnitRegistry; namespace { char s_runtimeAngleModeForUnits = 'r'; QString composeAnglePerSecondUnitName(const QString& angleUnitName) { const QString secondName = unitName(UnitId::Second); if (runtimeUnitNegativeExponentStyle() == Settings::UnitNegativeExponentSuperscript) { return angleUnitName + QLatin1Char(' ') + secondName + QString(MathDsl::PowNeg) + QString(MathDsl::Pow1); } return angleUnitName + QStringLiteral(" / ") + secondName; } QString toSuperscriptExponent(int exponent) { QString result; if (exponent < 0) result += MathDsl::PowNeg; for (const QChar& digit : QString::number(qAbs(exponent))) result += MathDsl::asciiDigitToSuperscript(digit); return result; } int parseTrailingExponent(const QString& factor, int* exponentStart, bool* ok) { *ok = false; *exponentStart = factor.size(); if (factor.isEmpty()) return 0; int suffixStart = factor.size(); while (suffixStart > 0) { const QChar ch = factor.at(suffixStart - 1); if (!MathDsl::isSuperscriptDigit(ch) && !MathDsl::isSuperscriptSign(ch)) break; --suffixStart; } if (suffixStart < factor.size()) { bool negative = false; int pos = suffixStart; if (factor.at(pos) == MathDsl::PowNeg || factor.at(pos) == MathDsl::PowPos) { negative = factor.at(pos) == MathDsl::PowNeg; ++pos; } if (pos >= factor.size()) return 0; QString asciiDigits; for (; pos < factor.size(); ++pos) { const QChar ascii = MathDsl::superscriptDigitToAscii(factor.at(pos)); if (ascii.isNull()) return 0; asciiDigits += ascii; } bool intOk = false; const int value = asciiDigits.toInt(&intOk); if (!intOk) return 0; *ok = true; *exponentStart = suffixStart; return negative ? -value : value; } const int caret = factor.lastIndexOf(MathDsl::PowOp); if (caret >= 0 && caret + 1 < factor.size()) { const QString expText = factor.mid(caret + 1).trimmed(); bool intOk = false; const int value = expText.toInt(&intOk); if (intOk) { *ok = true; *exponentStart = caret; return value; } } return 0; } QString negateUnitFactorExponent(const QString& factor) { const QString trimmed = factor.trimmed(); if (trimmed.isEmpty()) return trimmed; int exponentStart = trimmed.size(); bool hasExponent = false; const int exponent = parseTrailingExponent(trimmed, &exponentStart, &hasExponent); if (hasExponent) return trimmed.left(exponentStart) + toSuperscriptExponent(-exponent); return trimmed + toSuperscriptExponent(-1); } QString applySuperscriptStyleToUnitName(QString unitName) { if (!unitName.contains(MathDsl::DivOp)) return unitName; QStringList parts = unitName.split(MathDsl::DivOp); if (parts.isEmpty()) return unitName; QString normalized = parts.takeFirst().trimmed(); for (QString denominator : parts) { denominator = denominator.trimmed(); if (denominator.startsWith(MathDsl::GroupStart) && denominator.endsWith(MathDsl::GroupEnd) && denominator.size() > 2) { denominator = denominator.mid(1, denominator.size() - 2).trimmed(); } const QStringList factors = denominator.split( QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts); for (const QString& rawFactor : factors) { const QString negated = negateUnitFactorExponent(rawFactor); if (negated.isEmpty()) continue; if (!normalized.isEmpty()) normalized += QLatin1Char(' '); normalized += negated; } } return normalized; } const UnitRegistry& s_unitRegistry(); enum class UnitFamily { SiBase, SiDerived, SiAccepted, Other }; struct UnitAliasSpec { UnitId id; QString longName; QString localized; Quantity value; QString shortName; QString alternateShortName; int prefixPolicy; }; struct AffineDefinition { // Affine conversion handlers only transform numeric offsets/scales. // Unit dimensions for identifiers still come from UnitSpec::linearValue // (e.g. degree_celsius/degree_fahrenheit use Units::kelvin). HNumber (*toBase)(const HNumber&) = nullptr; HNumber (*fromBase)(const HNumber&) = nullptr; }; struct UnitSpec { QString name; const char* localized = ""; QString symbol; QList aliases; UnitFamily family; QList quantities; int prefixPolicy; const Quantity (*linearValue)(); AffineDefinition affine = {}; }; using PrefixSpec = UnitPrefixSpec; } // namespace HNumber s_celsiusToKelvin(const HNumber& c); HNumber s_kelvinToCelsius(const HNumber& k); HNumber s_fahrenheitToKelvin(const HNumber& f); HNumber s_kelvinToFahrenheit(const HNumber& k); const Quantity s_hartreeEnergyUnit(); const QHash& s_unitSpecs() { // Single source of truth for built-in units. // See Sources at top of this file. static const QHash specs = { // SI base units {UnitId::Second, UnitSpec{UnitName::Second, QT_TRANSLATE_NOOP("Editor", "second"), UnitSymbol::Second, {}, UnitFamily::SiBase, {UnitQuantity::Time}, EngineeringSiPrefixes, &Units::second}}, {UnitId::Metre, UnitSpec{UnitName::Metre, QT_TRANSLATE_NOOP("Editor", "metre"), UnitSymbol::Metre, {}, UnitFamily::SiBase, {UnitQuantity::Length}, EngineeringSiPrefixes | SmallSiPrefixes, &Units::metre}}, {UnitId::Kilogram, UnitSpec{UnitName::Kilogram, QT_TRANSLATE_NOOP("Editor", "kilogram"), UnitSymbol::Kilogram, {}, UnitFamily::SiBase, {UnitQuantity::Mass}, NoPrefixes, &Units::kilogram}}, {UnitId::Ampere, UnitSpec{UnitName::Ampere, "Ampere", UnitSymbol::Ampere, {}, UnitFamily::SiBase, {UnitQuantity::ElectricCurrent}, EngineeringSiPrefixes, &Units::ampere}}, {UnitId::Kelvin, UnitSpec{UnitName::Kelvin, "Kelvin", UnitSymbol::Kelvin, {}, UnitFamily::SiBase, {UnitQuantity::ThermodynamicTemperature}, EngineeringSiPrefixes, &Units::kelvin}}, {UnitId::Mole, UnitSpec{UnitName::Mole, QT_TRANSLATE_NOOP("Editor", "mole"), UnitSymbol::Mole, {}, UnitFamily::SiBase, {UnitQuantity::AmountOfSubstance}, EngineeringSiPrefixes, &Units::mole}}, {UnitId::Candela, UnitSpec{UnitName::Candela, "candela", UnitSymbol::Candela, {}, UnitFamily::SiBase, {UnitQuantity::LuminousIntensity}, EngineeringSiPrefixes, &Units::candela}}, // SI derived units {UnitId::Radian, UnitSpec{UnitName::Radian, QT_TRANSLATE_NOOP("Editor", "radian"), UnitSymbol::Radian, {}, UnitFamily::SiDerived, {UnitQuantity::PlaneAngle}, EngineeringSiPrefixes, &Units::radian}}, {UnitId::Steradian, UnitSpec{UnitName::Steradian, QT_TRANSLATE_NOOP("Editor", "steradian"), UnitSymbol::Steradian, {}, UnitFamily::SiDerived, {UnitQuantity::SolidAngle}, EngineeringSiPrefixes, &Units::steradian}}, {UnitId::Hertz, UnitSpec{UnitName::Hertz, "Hertz", UnitSymbol::Hertz, {}, UnitFamily::SiDerived, {UnitQuantity::Frequency}, EngineeringSiPrefixes, &Units::hertz}}, {UnitId::Newton, UnitSpec{UnitName::Newton, "Newton", UnitSymbol::Newton, {}, UnitFamily::SiDerived, {UnitQuantity::Force}, EngineeringSiPrefixes | SmallPositiveSiPrefixes, &Units::newton}}, {UnitId::Pascal, UnitSpec{UnitName::Pascal, "Pascal", UnitSymbol::Pascal, {}, UnitFamily::SiDerived, {UnitQuantity::Pressure, UnitQuantity::Stress}, EngineeringSiPrefixes | SmallPositiveSiPrefixes, &Units::pascal}}, {UnitId::Joule, UnitSpec{UnitName::Joule, "Joule", UnitSymbol::Joule, {}, UnitFamily::SiDerived, {UnitQuantity::Energy, UnitQuantity::Work, UnitQuantity::AmountOfHeat}, EngineeringSiPrefixes, &Units::joule}}, {UnitId::Watt, UnitSpec{UnitName::Watt, "Watt", UnitSymbol::Watt, {}, UnitFamily::SiDerived, {UnitQuantity::Power, UnitQuantity::RadiantFlux}, EngineeringSiPrefixes, &Units::watt}}, {UnitId::Coulomb, UnitSpec{UnitName::Coulomb, "Coulomb", UnitSymbol::Coulomb, {}, UnitFamily::SiDerived, {UnitQuantity::ElectricCharge}, EngineeringSiPrefixes, &Units::coulomb}}, {UnitId::Volt, UnitSpec{UnitName::Volt, "Volt", UnitSymbol::Volt, {}, UnitFamily::SiDerived, {UnitQuantity::ElectricPotentialDifference}, EngineeringSiPrefixes, &Units::volt}}, {UnitId::Farad, UnitSpec{UnitName::Farad, "Farad", UnitSymbol::Farad, {}, UnitFamily::SiDerived, {UnitQuantity::Capacitance}, EngineeringSiPrefixes, &Units::farad}}, {UnitId::Ohm, UnitSpec{UnitName::Ohm, "Ohm", UnitSymbol::Ohm, {}, UnitFamily::SiDerived, {UnitQuantity::ElectricResistance}, EngineeringSiPrefixes, &Units::ohm}}, {UnitId::Siemens, UnitSpec{UnitName::Siemens, "Siemens", UnitSymbol::Siemens, {}, UnitFamily::SiDerived, {UnitQuantity::ElectricConductance}, EngineeringSiPrefixes, &Units::siemens}}, {UnitId::Weber, UnitSpec{UnitName::Weber, "Weber", UnitSymbol::Weber, {}, UnitFamily::SiDerived, {UnitQuantity::MagneticFlux}, EngineeringSiPrefixes, &Units::weber}}, {UnitId::Tesla, UnitSpec{UnitName::Tesla, "Tesla", UnitSymbol::Tesla, {}, UnitFamily::SiDerived, {UnitQuantity::MagneticFluxDensity}, EngineeringSiPrefixes, &Units::tesla}}, {UnitId::Henry, UnitSpec{UnitName::Henry, "Henry", UnitSymbol::Henry, {}, UnitFamily::SiDerived, {UnitQuantity::Inductance}, EngineeringSiPrefixes, &Units::henry}}, {UnitId::DegreeCelsius, UnitSpec{UnitName::DegreeCelsius, QT_TRANSLATE_NOOP("Editor", "degree Celsius"), UnitSymbol::DegreeCelsius, {UnitAltSymbol::DegreeCelsius1, UnitAltSymbol::DegreeCelsius2, UnitAltSymbol::DegreeCelsius3, UnitAltSymbol::DegreeCelsius4, UnitAltSymbol::DegreeCelsius5}, UnitFamily::SiAccepted, {UnitQuantity::CelsiusTemperature}, NoPrefixes, &Units::kelvin, {&s_celsiusToKelvin, &s_kelvinToCelsius}}}, {UnitId::Lumen, UnitSpec{UnitName::Lumen, "lumen", UnitSymbol::Lumen, {}, UnitFamily::SiDerived, {UnitQuantity::LuminousFlux}, EngineeringSiPrefixes, &Units::lumen}}, {UnitId::Lux, UnitSpec{UnitName::Lux, "lux", UnitSymbol::Lux, {}, UnitFamily::SiDerived, {UnitQuantity::Illuminance}, EngineeringSiPrefixes, &Units::lux}}, {UnitId::Becquerel, UnitSpec{UnitName::Becquerel, "Becquerel", UnitSymbol::Becquerel, {}, UnitFamily::SiDerived, {UnitQuantity::ActivityReferredToARadionuclide}, EngineeringSiPrefixes, &Units::becquerel}}, {UnitId::Gray, UnitSpec{UnitName::Gray, "Gray", UnitSymbol::Gray, {}, UnitFamily::SiDerived, {UnitQuantity::AbsorbedDose, UnitQuantity::Kerma}, EngineeringSiPrefixes, &Units::gray}}, {UnitId::Sievert, UnitSpec{UnitName::Sievert, "sievert", UnitSymbol::Sievert, {}, UnitFamily::SiDerived, {UnitQuantity::DoseEquivalent}, EngineeringSiPrefixes, &Units::sievert}}, {UnitId::Katal, UnitSpec{UnitName::Katal, "katal", UnitSymbol::Katal, {}, UnitFamily::SiDerived, {UnitQuantity::CatalyticActivity}, EngineeringSiPrefixes, &Units::katal}}, {UnitId::CubicMetre, UnitSpec{UnitName::CubicMetre, QT_TRANSLATE_NOOP("Editor", "cubic metre"), UnitSymbol::CubicMetre, {}, UnitFamily::SiDerived, {UnitQuantity::Volume}, EngineeringSiPrefixes | SmallNegativeSiPrefixes, &Units::cubic_metre}}, {UnitId::CubicMillimetre, UnitSpec{UnitName::CubicMillimetre, QT_TRANSLATE_NOOP("Editor", "cubic millimetre"), UnitSymbol::CubicMillimetre, {}, UnitFamily::SiDerived, {UnitQuantity::Volume}, NoPrefixes, &Units::cubic_millimetre}}, {UnitId::CubicCentimetre, UnitSpec{UnitName::CubicCentimetre, QT_TRANSLATE_NOOP("Editor", "cubic centimetre"), UnitSymbol::CubicCentimetre, {UnitAltSymbol::CubicCentimetre}, UnitFamily::SiDerived, {UnitQuantity::Volume}, NoPrefixes, &Units::cubic_centimetre}}, {UnitId::CubicDecimetre, UnitSpec{UnitName::CubicDecimetre, QT_TRANSLATE_NOOP("Editor", "cubic decimetre"), UnitSymbol::CubicDecimetre, {}, UnitFamily::SiDerived, {UnitQuantity::Volume}, NoPrefixes, &Units::cubic_decimetre}}, {UnitId::CubicKilometre, UnitSpec{UnitName::CubicKilometre, QT_TRANSLATE_NOOP("Editor", "cubic kilometre"), UnitSymbol::CubicKilometre, {}, UnitFamily::SiDerived, {UnitQuantity::Volume}, NoPrefixes, &Units::cubic_kilometre}}, {UnitId::SquareMillimetre, UnitSpec{UnitName::SquareMillimetre, QT_TRANSLATE_NOOP("Editor", "square millimetre"), UnitSymbol::SquareMillimetre, {}, UnitFamily::SiDerived, {UnitQuantity::Area}, NoPrefixes, &Units::square_millimetre}}, {UnitId::SquareKilometre, UnitSpec{UnitName::SquareKilometre, QT_TRANSLATE_NOOP("Editor", "square kilometre"), UnitSymbol::SquareKilometre, {}, UnitFamily::SiDerived, {UnitQuantity::Area}, NoPrefixes, &Units::square_kilometre}}, {UnitId::SquareMetre, UnitSpec{UnitName::SquareMetre, QT_TRANSLATE_NOOP("Editor", "square metre"), UnitSymbol::SquareMetre, {}, UnitFamily::SiDerived, {UnitQuantity::Area}, EngineeringSiPrefixes | SmallNegativeSiPrefixes, &Units::square_metre}}, // SI-accepted units {UnitId::Minute, UnitSpec{UnitName::Minute, QT_TRANSLATE_NOOP("Editor", "minute"), UnitSymbol::Minute, {}, UnitFamily::SiAccepted, {UnitQuantity::Time}, NoPrefixes, &Units::minute}}, {UnitId::Hour, UnitSpec{UnitName::Hour, QT_TRANSLATE_NOOP("Editor", "hour"), UnitSymbol::Hour, {}, UnitFamily::SiAccepted, {UnitQuantity::Time}, NoPrefixes, &Units::hour}}, {UnitId::Day, UnitSpec{UnitName::Day, QT_TRANSLATE_NOOP("Editor", "day"), UnitSymbol::Day, {}, UnitFamily::SiAccepted, {UnitQuantity::Time}, NoPrefixes, &Units::day}}, {UnitId::AstronomicalUnit, UnitSpec{UnitName::AstronomicalUnit, QT_TRANSLATE_NOOP("Editor", "astronomical unit"), UnitSymbol::AstronomicalUnit, {}, UnitFamily::SiAccepted, {UnitQuantity::Length}, NoPrefixes, &Units::astronomical_unit}}, {UnitId::Degree, UnitSpec{UnitName::Degree, QT_TRANSLATE_NOOP("Editor", "degree"), UnitSymbol::Degree, {UnitAltSymbol::Degree1, UnitAltSymbol::Degree2}, UnitFamily::SiAccepted, {UnitQuantity::PlaneAngle}, NoPrefixes, &Units::degree}}, {UnitId::Arcminute, UnitSpec{UnitName::Arcminute, QT_TRANSLATE_NOOP("Editor", "arcminute"), UnitSymbol::Arcminute, {UnitAltSymbol::Arcminute}, UnitFamily::SiAccepted, {UnitQuantity::PlaneAngle}, NoPrefixes, &Units::arcminute}}, {UnitId::Arcsecond, UnitSpec{UnitName::Arcsecond, QT_TRANSLATE_NOOP("Editor", "arcsecond"), UnitSymbol::Arcsecond, {UnitAltSymbol::Arcsecond}, UnitFamily::SiAccepted, {UnitQuantity::PlaneAngle}, NoPrefixes, &Units::arcsecond}}, {UnitId::Milliarcsecond, UnitSpec{UnitName::Milliarcsecond, QT_TRANSLATE_NOOP("Editor", "milliarcsecond"), UnitSymbol::Milliarcsecond, {}, UnitFamily::SiAccepted, {UnitQuantity::PlaneAngle}, NoPrefixes, &Units::milliarcsecond}}, {UnitId::Microarcsecond, UnitSpec{UnitName::Microarcsecond, QT_TRANSLATE_NOOP("Editor", "microarcsecond"), UnitSymbol::Microarcsecond, {UnitAltSymbol::MicroarcsecondAscii}, UnitFamily::SiAccepted, {UnitQuantity::PlaneAngle}, NoPrefixes, &Units::microarcsecond}}, {UnitId::Hectare, UnitSpec{UnitName::Hectare, QT_TRANSLATE_NOOP("Editor", "hectare"), UnitSymbol::Hectare, {}, UnitFamily::SiAccepted, {UnitQuantity::Area}, NoPrefixes, &Units::hectare}}, {UnitId::Litre, UnitSpec{UnitName::Litre, QT_TRANSLATE_NOOP("Editor", "litre"), UnitSymbol::Litre, {UnitAltSymbol::Litre}, UnitFamily::SiAccepted, {UnitQuantity::Volume}, EngineeringSiPrefixes | SmallSiPrefixes, &Units::litre}}, {UnitId::Tonne, UnitSpec{UnitName::Tonne, QT_TRANSLATE_NOOP("Editor", "tonne"), UnitSymbol::Tonne, {}, UnitFamily::SiAccepted, {UnitQuantity::Mass}, NoPrefixes, &Units::tonne}}, {UnitId::Dalton, UnitSpec{UnitName::Dalton, QT_TRANSLATE_NOOP("Editor", "Dalton"), UnitSymbol::Dalton, {}, UnitFamily::SiAccepted, {UnitQuantity::Mass}, NoPrefixes, &Units::atomic_mass_unit}}, {UnitId::Electronvolt, UnitSpec{UnitName::Electronvolt, QT_TRANSLATE_NOOP("Editor", "electronvolt"), UnitSymbol::Electronvolt, {}, UnitFamily::SiAccepted, {UnitQuantity::Energy}, EngineeringSiPrefixes, &Units::electronvolt}}, {UnitId::Acre, UnitSpec{UnitName::Acre, "acre", UnitSymbol::Acre, {}, UnitFamily::Other, {UnitQuantity::Area}, NoPrefixes, &Units::acre}}, {UnitId::Angstrom, UnitSpec{UnitName::Angstrom, QT_TRANSLATE_NOOP("Editor", "Angstrom"), UnitSymbol::Angstrom, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::angstrom}}, {UnitId::Atmosphere, UnitSpec{UnitName::Atmosphere, QT_TRANSLATE_NOOP("Editor", "atmosphere"), UnitSymbol::Atmosphere, {}, UnitFamily::Other, {UnitQuantity::Pressure}, NoPrefixes, &Units::atmosphere}}, {UnitId::AtomicMassUnit, UnitSpec{UnitName::AtomicMassUnit, QT_TRANSLATE_NOOP("Editor", "atomic mass unit"), UnitSymbol::AtomicMassUnit, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::atomic_mass_unit}}, {UnitId::Bar, UnitSpec{UnitName::Bar, "bar", UnitSymbol::Bar, {}, UnitFamily::Other, {UnitQuantity::Pressure}, EngineeringSiPrefixes, &Units::bar}}, {UnitId::Bit, UnitSpec{UnitName::Bit, "bit", UnitSymbol::Bit, {}, UnitFamily::Other, {UnitQuantity::Information}, PositiveEngineeringSiPrefixes | BinaryIecPrefixes, &Units::bit}}, {UnitId::BritishThermalUnit, UnitSpec{UnitName::BritishThermalUnit, QT_TRANSLATE_NOOP("Editor", "British thermal unit"), UnitSymbol::BritishThermalUnit, {}, UnitFamily::Other, {UnitQuantity::AmountOfHeat}, NoPrefixes, &Units::british_thermal_unit}}, {UnitId::Byte, UnitSpec{UnitName::Byte, "byte", UnitSymbol::Byte, {}, UnitFamily::Other, {UnitQuantity::Information}, PositiveEngineeringSiPrefixes | BinaryIecPrefixes, &Units::byte}}, {UnitId::Calorie, UnitSpec{UnitName::Calorie, QT_TRANSLATE_NOOP("Editor", "calorie"), UnitSymbol::Calorie, {}, UnitFamily::Other, {UnitQuantity::AmountOfHeat}, NoPrefixes, &Units::calorie}}, {UnitId::Carat, UnitSpec{UnitName::Carat, QT_TRANSLATE_NOOP("Editor", "carat"), UnitSymbol::Carat, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::carat}}, {UnitId::Cup, UnitSpec{UnitName::Cup, QT_TRANSLATE_NOOP("Editor", "cup"), UnitSymbol::Cup, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::cup}}, {UnitId::CupImp, UnitSpec{UnitName::CupImp, QT_TRANSLATE_NOOP("Editor", "cup (Imperial)"), UnitSymbol::CupImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::cup_imp}}, {UnitId::CupJp, UnitSpec{UnitName::CupJp, QT_TRANSLATE_NOOP("Editor", "cup (Japanese)"), UnitSymbol::CupJp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::cup_jp}}, {UnitId::CupUs, UnitSpec{UnitName::CupUs, QT_TRANSLATE_NOOP("Editor", "cup (US)"), UnitSymbol::CupUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::cup_us}}, {UnitId::DegreeFahrenheit, UnitSpec{UnitName::DegreeFahrenheit, QT_TRANSLATE_NOOP("Editor", "degree Fahrenheit"), UnitSymbol::DegreeFahrenheit, {UnitAltSymbol::DegreeFahrenheit1, UnitAltSymbol::DegreeFahrenheit2, UnitAltSymbol::DegreeFahrenheit3, UnitAltSymbol::DegreeFahrenheit4, UnitAltSymbol::DegreeFahrenheit5}, UnitFamily::Other, {UnitQuantity::CelsiusTemperature}, NoPrefixes, &Units::kelvin, {&s_fahrenheitToKelvin, &s_kelvinToFahrenheit}}}, {UnitId::Fathom, UnitSpec{UnitName::Fathom, QT_TRANSLATE_NOOP("Editor", "fathom"), UnitSymbol::Fathom, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::fathom}}, {UnitId::FluidOunceImp, UnitSpec{UnitName::FluidOunceImp, QT_TRANSLATE_NOOP("Editor", "fluid ounce (Imperial)"), UnitSymbol::FluidOunceImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::fluid_ounce_imp}}, {UnitId::FluidOunceUs, UnitSpec{UnitName::FluidOunceUs, QT_TRANSLATE_NOOP("Editor", "fluid ounce (US)"), UnitSymbol::FluidOunceUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::fluid_ounce_us}}, {UnitId::FluidDramImp, UnitSpec{UnitName::FluidDramImp, QT_TRANSLATE_NOOP("Editor", "fluid dram (Imperial)"), UnitSymbol::FluidDramImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::fluid_dram_imp}}, {UnitId::FluidDramUs, UnitSpec{UnitName::FluidDramUs, QT_TRANSLATE_NOOP("Editor", "fluid dram (US)"), UnitSymbol::FluidDramUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::fluid_dram_us}}, {UnitId::Foot, UnitSpec{UnitName::Foot, QT_TRANSLATE_NOOP("Editor", "foot"), UnitSymbol::Foot, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::foot}}, {UnitId::SquareFoot, UnitSpec{UnitName::SquareFoot, QT_TRANSLATE_NOOP("Editor", "square foot"), UnitSymbol::SquareFoot, {}, UnitFamily::Other, {UnitQuantity::Area}, NoPrefixes, &Units::square_foot}}, {UnitId::CubicFoot, UnitSpec{UnitName::CubicFoot, QT_TRANSLATE_NOOP("Editor", "cubic foot"), UnitSymbol::CubicFoot, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::cubic_foot}}, {UnitId::Furlong, UnitSpec{UnitName::Furlong, "furlong", UnitSymbol::Furlong, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::furlong}}, {UnitId::GallonImp, UnitSpec{UnitName::GallonImp, QT_TRANSLATE_NOOP("Editor", "gallon (Imperial)"), UnitSymbol::GallonImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::gallon_imp}}, {UnitId::GallonUs, UnitSpec{UnitName::GallonUs, QT_TRANSLATE_NOOP("Editor", "gallon (US)"), UnitSymbol::GallonUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::gallon_us}}, {UnitId::GillImp, UnitSpec{UnitName::GillImp, QT_TRANSLATE_NOOP("Editor", "gill (Imperial)"), UnitSymbol::GillImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::gill_imp}}, {UnitId::GillUs, UnitSpec{UnitName::GillUs, QT_TRANSLATE_NOOP("Editor", "gill (US)"), UnitSymbol::GillUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::gill_us}}, {UnitId::Gradian, UnitSpec{UnitName::Gradian, QT_TRANSLATE_NOOP("Editor", "gradian"), UnitSymbol::Gradian, {}, UnitFamily::Other, {UnitQuantity::PlaneAngle}, NoPrefixes, &Units::gradian}}, {UnitId::Grain, UnitSpec{UnitName::Grain, QT_TRANSLATE_NOOP("Editor", "grain"), UnitSymbol::Grain, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::grain}}, {UnitId::Gram, UnitSpec{UnitName::Gram, QT_TRANSLATE_NOOP("Editor", "gram"), UnitSymbol::Gram, {}, UnitFamily::Other, {UnitQuantity::Mass}, EngineeringSiPrefixes | SmallSiPrefixes, &Units::gram}}, {UnitId::Hartley, UnitSpec{UnitName::Hartley, QT_TRANSLATE_NOOP("Editor", "Hartley"), UnitSymbol::Hartley, {}, UnitFamily::Other, {UnitQuantity::Information}, NoPrefixes, &Units::hartley}}, {UnitId::HartreeEnergyUnit, UnitSpec{UnitName::HartreeEnergyUnit, QT_TRANSLATE_NOOP("Editor", "Hartree energy unit"), UnitSymbol::HartreeEnergyUnit, {}, UnitFamily::Other, {UnitQuantity::Energy}, NoPrefixes, &s_hartreeEnergyUnit}}, {UnitId::Horsepower, UnitSpec{UnitName::Horsepower, QT_TRANSLATE_NOOP("Editor", "horsepower"), UnitSymbol::Horsepower, {}, UnitFamily::Other, {UnitQuantity::Power}, NoPrefixes, &Units::horsepower}}, {UnitId::Inch, UnitSpec{UnitName::Inch, QT_TRANSLATE_NOOP("Editor", "inch"), UnitSymbol::Inch, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::inch}}, {UnitId::SquareInch, UnitSpec{UnitName::SquareInch, QT_TRANSLATE_NOOP("Editor", "square inch"), UnitSymbol::SquareInch, {}, UnitFamily::Other, {UnitQuantity::Area}, NoPrefixes, &Units::square_inch}}, {UnitId::CubicInch, UnitSpec{UnitName::CubicInch, QT_TRANSLATE_NOOP("Editor", "cubic inch"), UnitSymbol::CubicInch, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::cubic_inch}}, {UnitId::Karat, UnitSpec{UnitName::Karat, QT_TRANSLATE_NOOP("Editor", "karat"), UnitSymbol::Karat, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::karat}}, {UnitId::Knot, UnitSpec{UnitName::Knot, QT_TRANSLATE_NOOP("Editor", "knot"), UnitSymbol::Knot, {}, UnitFamily::Other, {UnitQuantity::Speed, UnitQuantity::Velocity}, NoPrefixes, &Units::knot}}, {UnitId::Lightminute, UnitSpec{UnitName::Lightminute, QT_TRANSLATE_NOOP("Editor", "lightminute"), UnitSymbol::Lightminute, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::lightminute}}, {UnitId::Lightsecond, UnitSpec{UnitName::Lightsecond, QT_TRANSLATE_NOOP("Editor", "lightsecond"), UnitSymbol::Lightsecond, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::lightsecond}}, {UnitId::Lightyear, UnitSpec{UnitName::Lightyear, QT_TRANSLATE_NOOP("Editor", "lightyear"), UnitSymbol::Lightyear, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::lightyear}}, {UnitId::LongTon, UnitSpec{UnitName::LongTon, QT_TRANSLATE_NOOP("Editor", "long ton"), UnitSymbol::LongTon, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::long_ton}}, {UnitId::Mile, UnitSpec{UnitName::Mile, QT_TRANSLATE_NOOP("Editor", "mile"), UnitSymbol::Mile, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::mile}}, {UnitId::SquareMile, UnitSpec{UnitName::SquareMile, QT_TRANSLATE_NOOP("Editor", "square mile"), UnitSymbol::SquareMile, {}, UnitFamily::Other, {UnitQuantity::Area}, NoPrefixes, &Units::square_mile}}, {UnitId::CubicMile, UnitSpec{UnitName::CubicMile, QT_TRANSLATE_NOOP("Editor", "cubic mile"), UnitSymbol::CubicMile, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::cubic_mile}}, {UnitId::MilePerHour, UnitSpec{UnitName::MilePerHour, QT_TRANSLATE_NOOP("Editor", "mile per hour"), UnitSymbol::MilePerHour, {}, UnitFamily::Other, {UnitQuantity::Speed, UnitQuantity::Velocity}, NoPrefixes, &Units::mile_per_hour}}, {UnitId::KilometrePerHour, UnitSpec{UnitName::KilometrePerHour, QT_TRANSLATE_NOOP("Editor", "kilometre per hour"), UnitSymbol::KilometrePerHour, {}, UnitFamily::Other, {UnitQuantity::Speed, UnitQuantity::Velocity}, NoPrefixes, &Units::kilometre_per_hour}}, {UnitId::Nat, UnitSpec{UnitName::Nat, "nat", UnitSymbol::Nat, {}, UnitFamily::Other, {UnitQuantity::Information}, NoPrefixes, &Units::nat}}, {UnitId::NauticalMile, UnitSpec{UnitName::NauticalMile, QT_TRANSLATE_NOOP("Editor", "nautical mile"), UnitSymbol::NauticalMile, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::nautical_mile}}, {UnitId::Ounce, UnitSpec{UnitName::Ounce, QT_TRANSLATE_NOOP("Editor", "ounce"), UnitSymbol::Ounce, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::ounce}}, {UnitId::Parsec, UnitSpec{UnitName::Parsec, QT_TRANSLATE_NOOP("Editor", "parsec"), UnitSymbol::Parsec, {}, UnitFamily::Other, {UnitQuantity::Length}, PositiveEngineeringSiPrefixes, &Units::parsec}}, {UnitId::PintImp, UnitSpec{UnitName::PintImp, QT_TRANSLATE_NOOP("Editor", "pint (Imperial)"), UnitSymbol::PintImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::pint_imp}}, {UnitId::PintUs, UnitSpec{UnitName::PintUs, QT_TRANSLATE_NOOP("Editor", "pint (US)"), UnitSymbol::PintUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::pint_us}}, {UnitId::Pound, UnitSpec{UnitName::Pound, QT_TRANSLATE_NOOP("Editor", "pound"), UnitSymbol::Pound, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::pound}}, {UnitId::PoundsPerSqinch, UnitSpec{UnitName::PoundsPerSqinch, QT_TRANSLATE_NOOP("Editor", "pounds per square inch"), UnitSymbol::PoundsPerSqinch, {}, UnitFamily::Other, {UnitQuantity::Pressure}, NoPrefixes, &Units::pounds_per_sqinch}}, {UnitId::QuartImp, UnitSpec{UnitName::QuartImp, QT_TRANSLATE_NOOP("Editor", "quart (Imperial)"), UnitSymbol::QuartImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::quart_imp}}, {UnitId::QuartUs, UnitSpec{UnitName::QuartUs, QT_TRANSLATE_NOOP("Editor", "quart (US)"), UnitSymbol::QuartUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::quart_us}}, {UnitId::BarrelOil, UnitSpec{UnitName::BarrelOil, QT_TRANSLATE_NOOP("Editor", "oil barrel"), UnitSymbol::BarrelOil, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::barrel_oil}}, {UnitId::BarrelBeerUs, UnitSpec{UnitName::BarrelBeerUs, QT_TRANSLATE_NOOP("Editor", "beer barrel (US)"), UnitSymbol::BarrelBeerUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::barrel_beer_us}}, {UnitId::Rod, UnitSpec{UnitName::Rod, "rod", UnitSymbol::Rod, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::rod}}, {UnitId::SquareYard, UnitSpec{UnitName::SquareYard, QT_TRANSLATE_NOOP("Editor", "square yard"), UnitSymbol::SquareYard, {}, UnitFamily::Other, {UnitQuantity::Area}, NoPrefixes, &Units::square_yard}}, {UnitId::CubicYard, UnitSpec{UnitName::CubicYard, QT_TRANSLATE_NOOP("Editor", "cubic yard"), UnitSymbol::CubicYard, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::cubic_yard}}, {UnitId::ShortTon, UnitSpec{UnitName::ShortTon, QT_TRANSLATE_NOOP("Editor", "short ton"), UnitSymbol::ShortTon, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::short_ton}}, {UnitId::Stone, UnitSpec{UnitName::Stone, "stone", UnitSymbol::Stone, {}, UnitFamily::Other, {UnitQuantity::Mass}, NoPrefixes, &Units::stone}}, {UnitId::Tablespoon, UnitSpec{UnitName::Tablespoon, QT_TRANSLATE_NOOP("Editor", "tablespoon"), UnitSymbol::Tablespoon, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::tablespoon}}, {UnitId::TablespoonAu, UnitSpec{UnitName::TablespoonAu, QT_TRANSLATE_NOOP("Editor", "tablespoon (Australian)"), UnitSymbol::TablespoonAu, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::tablespoon_au}}, {UnitId::TablespoonImp, UnitSpec{UnitName::TablespoonImp, QT_TRANSLATE_NOOP("Editor", "tablespoon (Imperial)"), UnitSymbol::TablespoonImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::tablespoon_imp}}, {UnitId::TablespoonUs, UnitSpec{UnitName::TablespoonUs, QT_TRANSLATE_NOOP("Editor", "tablespoon (US)"), UnitSymbol::TablespoonUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::tablespoon_us}}, {UnitId::DessertSpoon, UnitSpec{UnitName::DessertSpoon, QT_TRANSLATE_NOOP("Editor", "dessert spoon"), UnitSymbol::DessertSpoon, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::dessert_spoon}}, {UnitId::Teaspoon, UnitSpec{UnitName::Teaspoon, QT_TRANSLATE_NOOP("Editor", "teaspoon"), UnitSymbol::Teaspoon, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::teaspoon}}, {UnitId::TeaspoonImp, UnitSpec{UnitName::TeaspoonImp, QT_TRANSLATE_NOOP("Editor", "teaspoon (Imperial)"), UnitSymbol::TeaspoonImp, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::teaspoon_imp}}, {UnitId::TeaspoonUs, UnitSpec{UnitName::TeaspoonUs, QT_TRANSLATE_NOOP("Editor", "teaspoon (US)"), UnitSymbol::TeaspoonUs, {}, UnitFamily::Other, {UnitQuantity::Volume}, NoPrefixes, &Units::teaspoon_us}}, {UnitId::Torr, UnitSpec{UnitName::Torr, "Torr", UnitSymbol::Torr, {}, UnitFamily::Other, {UnitQuantity::Pressure}, NoPrefixes, &Units::torr}}, {UnitId::Turn, UnitSpec{UnitName::Turn, QT_TRANSLATE_NOOP("Editor", "turn"), UnitSymbol::Turn, {UnitAltSymbol::Turn}, UnitFamily::Other, {UnitQuantity::PlaneAngle}, NoPrefixes, &Units::turn}}, {UnitId::Revolution, UnitSpec{UnitName::Revolution, QT_TRANSLATE_NOOP("Editor", "revolution"), UnitSymbol::Revolution, {}, UnitFamily::Other, {UnitQuantity::PlaneAngle}, NoPrefixes, &Units::revolution}}, {UnitId::RevolutionPerMinute, UnitSpec{UnitName::RevolutionPerMinute, QT_TRANSLATE_NOOP("Editor", "revolution per minute"), UnitSymbol::RevolutionPerMinute, {}, UnitFamily::Other, {UnitQuantity::Frequency}, NoPrefixes, &Units::revolution_per_minute}}, {UnitId::Week, UnitSpec{UnitName::Week, QT_TRANSLATE_NOOP("Editor", "week"), UnitSymbol::Week, {}, UnitFamily::Other, {UnitQuantity::Time}, NoPrefixes, &Units::week}}, {UnitId::KilowattHour, UnitSpec{UnitName::KilowattHour, QT_TRANSLATE_NOOP("Editor", "kilowatt hour"), UnitSymbol::KilowattHour, {}, UnitFamily::Other, {UnitQuantity::Energy, UnitQuantity::Work, UnitQuantity::AmountOfHeat}, NoPrefixes, &Units::kilowatt_hour}}, {UnitId::MillimetreOfMercury, UnitSpec{UnitName::MillimetreOfMercury, QT_TRANSLATE_NOOP("Editor", "millimetre of mercury"), UnitSymbol::MillimetreOfMercury, {}, UnitFamily::Other, {UnitQuantity::Pressure}, NoPrefixes, &Units::millimetre_of_mercury}}, {UnitId::Quad, UnitSpec{UnitName::Quad, "quad", UnitSymbol::Quad, {}, UnitFamily::Other, {UnitQuantity::AmountOfHeat}, NoPrefixes, &Units::quad}}, {UnitId::Yard, UnitSpec{UnitName::Yard, QT_TRANSLATE_NOOP("Editor", "yard"), UnitSymbol::Yard, {}, UnitFamily::Other, {UnitQuantity::Length}, NoPrefixes, &Units::yard}}, {UnitId::CenturyJulian, UnitSpec{UnitName::CenturyJulian, QT_TRANSLATE_NOOP("Editor", "Julian century"), UnitSymbol::CenturyJulian, {}, UnitFamily::Other, {UnitQuantity::Time}, NoPrefixes, &Units::julian_century}}, {UnitId::YearJulian, UnitSpec{UnitName::YearJulian, QT_TRANSLATE_NOOP("Editor", "Julian year"), UnitSymbol::YearJulian, {}, UnitFamily::Other, {UnitQuantity::Time}, NoPrefixes, &Units::julian_year}}, {UnitId::YearSidereal, UnitSpec{UnitName::YearSidereal, QT_TRANSLATE_NOOP("Editor", "sidereal year"), UnitSymbol::YearSidereal, {}, UnitFamily::Other, {UnitQuantity::Time}, NoPrefixes, &Units::sidereal_year}}, {UnitId::YearTropical, UnitSpec{UnitName::YearTropical, QT_TRANSLATE_NOOP("Editor", "tropical year"), UnitSymbol::YearTropical, {}, UnitFamily::Other, {UnitQuantity::Time}, NoPrefixes, &Units::tropical_year}}, }; return specs; } // Stable textual keys for base dimensions used in expression rendering/parsing. // Canonical base-unit names are derived from unit specs (see helpers below). struct DimensionKeyEntry { UnitQuantity quantity; QString dimensionKey; }; const std::array& s_dimensionKeyEntries() { // Keep these keys stable: they are consumed by // unitQuantityDimensionKey()/unitQuantityFromDimensionKey(). static const std::array entries = {{ {UnitQuantity::Mass, QStringLiteral("mass")}, {UnitQuantity::Length, QStringLiteral("length")}, {UnitQuantity::Time, QStringLiteral("time")}, {UnitQuantity::ElectricCurrent, QStringLiteral("electric current")}, {UnitQuantity::ThermodynamicTemperature, QStringLiteral("temperature")}, {UnitQuantity::AmountOfSubstance, QStringLiteral("amount")}, {UnitQuantity::LuminousIntensity, QStringLiteral("luminous intensity")}, {UnitQuantity::Information, QStringLiteral("information")} }}; return entries; } #define SI_PREFIX_TABLE(X) \ X(Quecto, quecto, "quecto", "q", -30) \ X(Ronto, ronto, "ronto", "r", -27) \ X(Yocto, yocto, "yocto", "y", -24) \ X(Zepto, zepto, "zepto", "z", -21) \ X(Atto, atto, "atto", "a", -18) \ X(Femto, femto, "femto", "f", -15) \ X(Pico, pico, "pico", "p", -12) \ X(Nano, nano, "nano", "n", -9) \ X(Micro, micro, "micro", QString(UnicodeChars::MicroSign), -6) \ X(Milli, milli, "milli", "m", -3) \ X(Centi, centi, "centi", "c", -2) \ X(Deci, deci, "deci", "d", -1) \ X(Deca, deca, "deca", "da", 1) \ X(Hecto, hecto, "hecto", "h", 2) \ X(Kilo, kilo, "kilo", "k", 3) \ X(Mega, mega, "mega", "M", 6) \ X(Giga, giga, "giga", "G", 9) \ X(Tera, tera, "tera", "T", 12) \ X(Peta, peta, "peta", "P", 15) \ X(Exa, exa, "exa", "E", 18) \ X(Zetta, zetta, "zetta", "Z", 21) \ X(Yotta, yotta, "yotta", "Y", 24) \ X(Ronna, ronna, "ronna", "R", 27) \ X(Quetta, quetta, "quetta", "Q", 30) #define BINARY_PREFIX_TABLE(X) \ X(Kibi, kibi, "kibi", "Ki", 10) \ X(Mebi, mebi, "mebi", "Mi", 20) \ X(Gibi, gibi, "gibi", "Gi", 30) \ X(Tebi, tebi, "tebi", "Ti", 40) \ X(Pebi, pebi, "pebi", "Pi", 50) \ X(Exbi, exbi, "exbi", "Ei", 60) \ X(Zebi, zebi, "zebi", "Zi", 70) \ X(Yobi, yobi, "yobi", "Yi", 80) \ X(Robi, robi, "robi", "Ri", 90) \ X(Quebi, quebi, "quebi", "Qi", 100) struct UnitRegistry { /* - valuesByIdentifier: Flat identifier->value map consumed by evaluator/unit lookup clients via Units::builtInUnitValues() and Units::builtInUnitLookup(). - displaySymbolsByIdentifier: Maps canonical/alias identifiers to preferred short display symbols (e.g. "ohm" -> "Ω"), consumed by unit display-format helpers. - prefixedIdentifiers: Generated decimal/binary prefix identifiers whose authored token is itself the preferred display spelling. - affineByIdentifier: Affine conversion metadata for identifiers like degree_celsius and degree_fahrenheit, used by affine conversion helpers. - canonicalMatchLookup: Dimension-to-canonical-unit map used by Units::findUnit() to select preferred display units for computed dimensions. */ QHash valuesByIdentifier; QHash idsByIdentifier; QHash localizedByIdentifier; QHash displaySymbolsByIdentifier; QSet prefixedIdentifiers; QHash affineByIdentifier; QHash, Unit> canonicalMatchLookup; }; // Returns the stable textual key for a base dimension quantity. // Used by formatting/parsing fallback paths for unnamed dimensions. QString unitQuantityDimensionKey(UnitQuantity quantity) { for (const DimensionKeyEntry& entry : s_dimensionKeyEntries()) { if (entry.quantity == quantity) return entry.dimensionKey; } return QString(); } // Parses a textual base-dimension key back into UnitQuantity. // Returns false for unknown keys or null output pointers. bool unitQuantityFromDimensionKey(const QString& key, UnitQuantity* out) { if (!out) return false; for (const DimensionKeyEntry& entry : s_dimensionKeyEntries()) { if (key == entry.dimensionKey) { *out = entry.quantity; return true; } } return false; } // Normalizes user-provided unit text for identifier lookups: // trims, removes outer parentheses, and lowercases. QString normalizeUnitName(const QString& name) { QString normalized = name.trimmed(); if (normalized.startsWith(MathDsl::GroupStart) && normalized.endsWith(MathDsl::GroupEnd) && normalized.size() > 2) normalized = normalized.mid(1, normalized.size() - 2).trimmed(); return normalized.toLower(); } // Marks units that should be preferred as canonical display names // when rendering matched dimensions. bool isPreferredCanonicalDisplayUnit(UnitId id) { switch (id) { case UnitId::Newton: case UnitId::Joule: case UnitId::Watt: case UnitId::Pascal: case UnitId::Coulomb: case UnitId::Volt: case UnitId::Ohm: case UnitId::Siemens: case UnitId::Farad: case UnitId::Weber: case UnitId::Tesla: case UnitId::Henry: case UnitId::Hertz: case UnitId::Becquerel: case UnitId::Gray: case UnitId::Sievert: case UnitId::Katal: case UnitId::Lumen: case UnitId::Lux: return true; default: return false; } } // Returns predefined phrase fragments used when composing display text. QStringView unitPhrase(UnitPhraseId key) { switch (key) { case UnitPhraseId::NewtonMetre: return UnitText::NewtonMetre; case UnitPhraseId::WattSecond: return UnitText::WattSecond; case UnitPhraseId::VoltSquaredAmpere: return UnitText::VoltSquaredAmpere; case UnitPhraseId::JoulePerSquareMetre: return UnitText::JoulePerSquareMetre; case UnitPhraseId::JoulePerCubicMetre: return UnitText::JoulePerCubicMetre; default: return QStringView(); } } HNumber s_celsiusToKelvin(const HNumber& c) { return c + HNumber("273.15"); } HNumber s_kelvinToCelsius(const HNumber& k) { return k - HNumber("273.15"); } HNumber s_fahrenheitToKelvin(const HNumber& f) { return (f + HNumber("459.67")) * HNumber("5") / HNumber("9"); } HNumber s_kelvinToFahrenheit(const HNumber& k) { return k * HNumber("9") / HNumber("5") - HNumber("459.67"); } Quantity s_powerOfTen(int exponent) { HNumber result(1); const HNumber ten(10); if (exponent >= 0) { for (int i = 0; i < exponent; ++i) result *= ten; } else { for (int i = 0; i < -exponent; ++i) result /= ten; } return Quantity(result); } Quantity s_powerOfTwo(int exponent) { HNumber result(1); const HNumber two(2); for (int i = 0; i < exponent; ++i) result *= two; return Quantity(result); } const Quantity s_hartreeEnergyUnit() { Quantity hartreeEnergy = HNumber("4.3597447222060e-18") * Units::joule(); hartreeEnergy.setDisplayUnit(Units::joule().numericValue(), unitName(UnitId::Joule)); return hartreeEnergy; } const QList& s_unitSpecOrder() { static const QList order = [] { QList ids = s_unitSpecs().keys(); std::sort(ids.begin(), ids.end(), [](UnitId a, UnitId b) { return static_cast(a) < static_cast(b); }); return ids; }(); return order; } QString s_baseUnitCanonicalNameForQuantity(UnitQuantity quantity) { // Single source of truth: // infer canonical base-unit names from SI base rows in unit specs. const QHash& specs = s_unitSpecs(); for (const UnitId id : s_unitSpecOrder()) { const UnitSpec& spec = specs.value(id); if (spec.family != UnitFamily::SiBase || spec.quantities.isEmpty()) continue; if (spec.quantities.first() == quantity) return spec.name; } return QString(); } const QList& s_baseDimensionOutputOrder() { // Preferred base-dimension print order for fallback decomposition. static const QList order = { UnitQuantity::Mass, UnitQuantity::Length, UnitQuantity::Time, UnitQuantity::ElectricCurrent, UnitQuantity::ThermodynamicTemperature, UnitQuantity::AmountOfSubstance, UnitQuantity::LuminousIntensity, UnitQuantity::Information }; return order; } int s_baseDimensionOutputOrderIndex(UnitQuantity quantity) { // Order index space starts at 2 because compact sorting reserves: // 0 => coulomb, 1 => joule. const int index = s_baseDimensionOutputOrder().indexOf(quantity); return index < 0 ? 100 : (2 + index); } struct ReadableUnitScore { int bucket = 3; HNumber value = HNumber(0); }; ReadableUnitScore readableUnitScore(const HNumber& baseValue, const CNumber& unit) { const auto abs = [](const HNumber& value) { return value < HNumber(0) ? -value : value; }; ReadableUnitScore score; if (!unit.isNearReal() || unit.real.isNearZero()) return score; score.value = abs(baseValue / unit.real); if (score.value >= HNumber(1) && score.value < HNumber(1000)) { score.bucket = 0; } else if (score.value >= HNumber(1000)) { score.bucket = 1; } else { score.bucket = 2; } return score; } bool isBetterReadableUnitScore(const ReadableUnitScore& a, const ReadableUnitScore& b) { if (a.bucket != b.bucket) return a.bucket < b.bucket; if (a.bucket == 0) return a.value < b.value; if (a.bucket == 1) return a.value < b.value; if (a.bucket == 2) return a.value > b.value; return false; } const QList& s_siPrefixes() { static const QList prefixes = { #define SI_PREFIX_SPEC(id, func, name, symbol, exponent) \ {PrefixId::id, name, symbol, exponent, s_powerOfTen(exponent)}, SI_PREFIX_TABLE(SI_PREFIX_SPEC) #undef SI_PREFIX_SPEC }; return prefixes; } const QList& s_binaryPrefixes() { static const QList prefixes = { #define BINARY_PREFIX_SPEC(id, func, name, symbol, exponent) \ {PrefixId::id, name, symbol, exponent, s_powerOfTwo(exponent)}, BINARY_PREFIX_TABLE(BINARY_PREFIX_SPEC) #undef BINARY_PREFIX_SPEC }; return prefixes; } const QList& siPrefixes() { return s_siPrefixes(); } const QList& binaryIecPrefixes() { return s_binaryPrefixes(); } int unitPrefixPolicy(UnitId id) { const auto it = s_unitSpecs().constFind(id); if (it == s_unitSpecs().constEnd()) return NoPrefixes; return it.value().prefixPolicy; } bool unitPrefixPolicyAllows(int policy, const UnitPrefixSpec& prefix, bool binaryPrefix) { if (binaryPrefix) return policy & BinaryIecPrefixes; if (prefix.power == 0) return false; const bool engineering = prefix.power % 3 == 0; if (prefix.power < 0) return policy & (engineering ? NegativeEngineeringSiPrefixes : SmallNegativeSiPrefixes); return policy & (engineering ? PositiveEngineeringSiPrefixes : SmallPositiveSiPrefixes); } QString unitSiPrefixBaseSymbol(UnitId id) { const UnitId baseId = id == UnitId::Kilogram ? UnitId::Gram : id; const auto it = s_unitSpecs().constFind(baseId); if (it == s_unitSpecs().constEnd() || it.value().prefixPolicy == NoPrefixes) return QString(); return it.value().symbol; } CNumber unitSiPrefixBaseValue(UnitId id) { const UnitId baseId = id == UnitId::Kilogram ? UnitId::Gram : id; const auto it = s_unitSpecs().constFind(baseId); if (it == s_unitSpecs().constEnd() || !it.value().linearValue) return CNumber(0); return it.value().linearValue().numericValue(); } bool shouldAddSiPrefixedShortAlias(const QString& prefixSymbol, const QString& unitShortName) { Q_UNUSED(prefixSymbol) Q_UNUSED(unitShortName) return true; } enum class AngleUnitKind { None, Radian, Degree, Gradian, Turn, Arcminute, Arcsecond, Milliarcsecond, Microarcsecond }; // Normalizes explicit angle unit tokens, including masculine ordinal aliasing. QString normalizeAngleUnitName(const QString& unitName) { QString normalized = unitName.trimmed().toLower(); normalized.replace(UnicodeChars::MasculineOrdinalIndicator, UnicodeChars::DegreeSign); // º -> ° return normalized; } AngleUnitKind angleUnitKindFromName(const QString& name) { const QString normalized = normalizeAngleUnitName(name); if (normalized == unitName(UnitId::Radian) || normalized == UnitSymbol::Radian) return AngleUnitKind::Radian; if (normalized == unitName(UnitId::Degree) || normalized == UnitAltSymbol::Degree1 || normalized == UnitSymbol::Degree) return AngleUnitKind::Degree; if (normalized == UnitName::Gradian || normalized == UnitSymbol::Gradian) return AngleUnitKind::Gradian; if (normalized == UnitName::Turn || normalized == UnitSymbol::Turn || normalized == UnitName::Revolution || normalized == UnitSymbol::Revolution) return AngleUnitKind::Turn; if (normalized == unitName(UnitId::Arcminute) || normalized == UnitAltSymbol::Arcminute || normalized == UnitSymbol::Arcminute) return AngleUnitKind::Arcminute; if (normalized == unitName(UnitId::Arcsecond) || normalized == UnitAltSymbol::Arcsecond || normalized == UnitSymbol::Arcsecond) return AngleUnitKind::Arcsecond; if (normalized == unitName(UnitId::Milliarcsecond) || normalized == UnitSymbol::Milliarcsecond) return AngleUnitKind::Milliarcsecond; if (normalized == unitName(UnitId::Microarcsecond) || normalized == UnitSymbol::Microarcsecond || normalized == UnitAltSymbol::MicroarcsecondAscii) return AngleUnitKind::Microarcsecond; return AngleUnitKind::None; } Quantity angleUnitValueForMode(AngleUnitKind angleUnit, char angleMode) { Quantity modeReference = Units::radian(); if (angleMode == 'd') modeReference = Units::degree(); else if (angleMode == 'g') modeReference = Units::gradian(); else if (angleMode == 't' || angleMode == 'v') modeReference = Units::turn(); if (angleUnit == AngleUnitKind::Radian) { Quantity rad = Units::radian() / modeReference; rad.setDisplayUnit(Quantity(1).numericValue(), Units::angleModeUnitSymbol(angleMode)); return rad; } if (angleUnit == AngleUnitKind::Degree) { Quantity degree = Units::degree() / modeReference; degree.setDisplayUnit(Quantity(1).numericValue(), Units::angleModeUnitSymbol(angleMode)); return degree; } if (angleUnit == AngleUnitKind::Gradian) { Quantity gradian = Units::gradian() / modeReference; gradian.setDisplayUnit(Quantity(1).numericValue(), Units::angleModeUnitSymbol(angleMode)); return gradian; } if (angleUnit == AngleUnitKind::Turn) { Quantity turn = Units::turn() / modeReference; turn.setDisplayUnit(Quantity(1).numericValue(), Units::angleModeUnitSymbol(angleMode)); return turn; } if (angleUnit == AngleUnitKind::Arcminute) { Quantity arcminute = Units::arcminute() / modeReference; arcminute.setDisplayUnit(Quantity(1).numericValue(), Units::angleModeUnitSymbol(angleMode)); return arcminute; } if (angleUnit == AngleUnitKind::Arcsecond) { Quantity arcsecond = Units::arcsecond() / modeReference; arcsecond.setDisplayUnit(Quantity(1).numericValue(), Units::angleModeUnitSymbol(angleMode)); return arcsecond; } if (angleUnit == AngleUnitKind::Milliarcsecond) { Quantity milliarcsecond = Units::milliarcsecond() / modeReference; milliarcsecond.setDisplayUnit(Quantity(1).numericValue(), Units::angleModeUnitSymbol(angleMode)); return milliarcsecond; } if (angleUnit == AngleUnitKind::Microarcsecond) { Quantity microarcsecond = Units::microarcsecond() / modeReference; microarcsecond.setDisplayUnit(Quantity(1).numericValue(), Units::angleModeUnitSymbol(angleMode)); return microarcsecond; } return Quantity(0); } bool tryGetPrefixedExplicitAngleUnitValueForMode(const QString& identifier, char angleMode, Quantity* out) { if (!out) return false; const QString normalized = UnicodeChars::normalizeUnitSymbolAliases(identifier.trimmed()); if (normalized.isEmpty()) return false; const auto tryMatchPrefix = [&](const QString& prefixText, const Quantity& prefixValue, Qt::CaseSensitivity caseSensitivity) { if (!normalized.startsWith(prefixText, caseSensitivity)) return false; const QString base = normalized.mid(prefixText.size()); const AngleUnitKind baseUnitKind = angleUnitKindFromName(base); if (baseUnitKind == AngleUnitKind::None) return false; *out = prefixValue * angleUnitValueForMode(baseUnitKind, angleMode); return true; }; for (const PrefixSpec& prefix : s_siPrefixes()) { if (tryMatchPrefix(prefix.longName, prefix.value, Qt::CaseInsensitive)) return true; if (tryMatchPrefix(prefix.symbol, prefix.value, Qt::CaseSensitive)) return true; if (prefix.id == PrefixId::Micro && tryMatchPrefix(QStringLiteral("u"), prefix.value, Qt::CaseSensitive)) { return true; } } return false; } QString unitName(UnitId id) { return s_unitSpecs().value(id).name; } const char* unitLocalizedName(UnitId id) { const auto it = s_unitSpecs().constFind(id); if (it == s_unitSpecs().constEnd()) return ""; return it.value().localized ? it.value().localized : ""; } QString unitLocalizedIdentifierName(const QString& identifier) { const auto it = s_unitRegistry().localizedByIdentifier.constFind(identifier); if (it != s_unitRegistry().localizedByIdentifier.constEnd()) return it.value(); const UnitId id = unitId(normalizeUnitName(identifier)); return id == UnitId::Unknown ? QString() : QString::fromUtf8(unitLocalizedName(id)); } bool isUnitLocalizedNameTranslatable(const QString& localizedName) { static const QSet untranslatableNames = { QStringLiteral("acre"), QStringLiteral("Ampere"), QStringLiteral("Becquerel"), QStringLiteral("bit"), QStringLiteral("candela"), QStringLiteral("Coulomb"), QStringLiteral("Farad"), QStringLiteral("Gray"), QStringLiteral("Henry"), QStringLiteral("Hertz"), QStringLiteral("Joule"), QStringLiteral("katal"), QStringLiteral("Kelvin"), QStringLiteral("lumen"), QStringLiteral("lux"), QStringLiteral("nat"), QStringLiteral("Newton"), QStringLiteral("Ohm"), QStringLiteral("Pascal"), QStringLiteral("quad"), QStringLiteral("Siemens"), QStringLiteral("sievert"), QStringLiteral("stone"), QStringLiteral("Tesla"), QStringLiteral("Torr"), QStringLiteral("Volt"), QStringLiteral("Watt"), QStringLiteral("Weber"), }; return !untranslatableNames.contains(localizedName); } QString unitSymbol(UnitId id) { return s_unitSpecs().value(id).symbol; } QString Units::angleModeUnitSymbol(char angleMode) { if (angleMode == 'd') return UnitSymbol::Degree; if (angleMode == 'g') return UnitSymbol::Gradian; if (angleMode == 't') return UnitSymbol::Turn; if (angleMode == 'v') return UnitSymbol::Revolution; return UnitSymbol::Radian; } QString Units::degreeAliasSymbol() { return UnitAltSymbol::Degree1; } QString Units::arcminuteAliasSymbol() { return UnitAltSymbol::Arcminute; } QString Units::arcsecondAliasSymbol() { return UnitAltSymbol::Arcsecond; } QStringList Units::affineUnitAliases(UnitId id) { switch (id) { case UnitId::DegreeCelsius: return { UnitAltSymbol::DegreeCelsius1, UnitAltSymbol::DegreeCelsius2, UnitAltSymbol::DegreeCelsius3, UnitAltSymbol::DegreeCelsius4, UnitAltSymbol::DegreeCelsius5 }; case UnitId::DegreeFahrenheit: return { UnitAltSymbol::DegreeFahrenheit1, UnitAltSymbol::DegreeFahrenheit2, UnitAltSymbol::DegreeFahrenheit3, UnitAltSymbol::DegreeFahrenheit4, UnitAltSymbol::DegreeFahrenheit5 }; default: return {}; } } QString prefixName(PrefixId id) { for (const PrefixSpec& prefix : s_siPrefixes()) { if (prefix.id == id) return prefix.longName; } for (const PrefixSpec& prefix : s_binaryPrefixes()) { if (prefix.id == id) return prefix.longName; } return QString(); } QString prefixSymbol(PrefixId id) { for (const PrefixSpec& prefix : s_siPrefixes()) { if (prefix.id == id) return prefix.symbol; } for (const PrefixSpec& prefix : s_binaryPrefixes()) { if (prefix.id == id) return prefix.symbol; } return QString(); } PrefixId prefixId(const QString& normalizedName) { const QString key = normalizedName.trimmed(); for (const PrefixSpec& prefix : s_siPrefixes()) { if (key == prefix.longName || key == prefix.symbol) return prefix.id; } for (const PrefixSpec& prefix : s_binaryPrefixes()) { if (key == prefix.longName || key == prefix.symbol) return prefix.id; } return PrefixId::Unknown; } const QList& siPrefixIds() { static const QList ids = [] { QList list; for (const PrefixSpec& prefix : s_siPrefixes()) list.append(prefix.id); return list; }(); return ids; } const QList& binaryPrefixIds() { static const QList ids = [] { QList list; for (const PrefixSpec& prefix : s_binaryPrefixes()) list.append(prefix.id); return list; }(); return ids; } Quantity unitValue(UnitId id) { const auto it = s_unitSpecs().constFind(id); if (it == s_unitSpecs().constEnd()) return Quantity(1); const UnitSpec& spec = it.value(); return spec.linearValue ? spec.linearValue() : Quantity(1); } /* Resolve a normalized unit identifier (canonical name or supported alias) to its UnitId. Expected input: - already normalized text (for example via normalizeUnitName()). - case-insensitive handling is achieved by normalization before calling. Optimization: - Uses a function-local static QHash built once on first call, then reused for all subsequent lookups. - Canonical names/symbols/aliases are inferred from unit specs (single source of truth). */ UnitId unitId(const QString& name) { static const QHash byName = [] { QHash map; QHash normalizedSymbolUseCount; const QHash& specs = s_unitSpecs(); for (const UnitId id : s_unitSpecOrder()) { const UnitSpec& spec = specs.value(id); if (!spec.symbol.isEmpty()) { const QString normalizedSymbol = normalizeUnitName(spec.symbol); normalizedSymbolUseCount.insert( normalizedSymbol, normalizedSymbolUseCount.value(normalizedSymbol, 0) + 1); } } const auto insertIfMissing = [&](const QString& key, UnitId id) { if (key.isEmpty() || map.contains(key)) return; map.insert(key, id); }; for (const UnitId id : s_unitSpecOrder()) { const UnitSpec& spec = specs.value(id); insertIfMissing(normalizeUnitName(spec.name), id); if (!spec.symbol.isEmpty()) { const QString normalizedSymbol = normalizeUnitName(spec.symbol); if (normalizedSymbolUseCount.value(normalizedSymbol) == 1) insertIfMissing(normalizedSymbol, id); } for (const QString& alias : spec.aliases) { if (alias.isEmpty()) continue; insertIfMissing(normalizeUnitName(alias), id); } } return map; }(); return byName.value(name, UnitId::Unknown); } template const Quantity s_cachedUnit(QMap& cache, const QString& name, Builder&& builder) { auto it = cache.constFind(name); if (it == cache.cend()) it = cache.insert(name, builder()); return it.value(); } // Builds a base-unit quantity from the spec dimension list of a canonical name. Quantity s_baseUnitFromDefinitions(const QString& canonicalName) { const QHash& specs = s_unitSpecs(); for (const UnitId id : s_unitSpecOrder()) { const UnitSpec& spec = specs.value(id); if (spec.name != canonicalName) continue; if (spec.quantities.isEmpty()) break; Quantity value(1); value.modifyDimension(spec.quantities.first(), 1); return value; } return Quantity(1); } template Quantity s_unitValueFromDefinitions(const QString& canonicalName, const Quantity (*selfGetter)(), FallbackBuilder&& fallbackBuilder) { // Uses declarative spec linear value when available; otherwise keeps // the fallback builder expression for compatibility. const QHash& specs = s_unitSpecs(); for (const UnitId id : s_unitSpecOrder()) { const UnitSpec& spec = specs.value(id); if (spec.name != canonicalName) continue; if (spec.linearValue && spec.linearValue != selfGetter) return spec.linearValue(); break; } Quantity fallbackValue = fallbackBuilder(); // Joule is defined from N*m. Without this explicit override, the fallback // display token propagates as "newton metre", which then leaks into heat // units derived from joule (for example Btu). Keep joule's canonical name // so conversions like Btu -> J and Btu -> joule render as energy units. if (canonicalName == UnitName::Joule) fallbackValue.setDisplayUnit(fallbackValue.numericValue(), canonicalName); return fallbackValue; } #define DEFINE_DERIVED_UNIT(name, value) \ const Quantity Units::name() \ { \ const QString unitKey = QStringLiteral(#name); \ return s_cachedUnit(m_cache, unitKey, [unitKey]() { \ return s_unitValueFromDefinitions(unitKey, &Units::name, []() { \ return Quantity(value); \ }); \ }); \ } #define DEFINE_BASE_UNIT(name) \ const Quantity Units::name() \ { \ const QString unitKey = QStringLiteral(#name); \ return s_cachedUnit(m_cache, unitKey, [unitKey]() { return s_baseUnitFromDefinitions(unitKey); }); \ } QHash, Unit> Units::m_matchLookup; QMap Units::m_cache; // Adds a normalized quantity->name mapping into the canonical match table. void Units::pushUnit(Quantity q, QString name) { q.cleanDimension(); Unit u(name, q); m_matchLookup.insert(q.getDimensionByQuantity(), u); } // Initialize the lookup table for automatic matching. void Units::initTable() { StartupDiagnostics::Scope timing("Initialize unit lookup tables"); // Base canonicalization map derived from unit specs. // Entries in this map are preferred renderings for matching dimensions. m_matchLookup = s_unitRegistry().canonicalMatchLookup; // Additional preferred canonical renderings for composite dimensions that // are not represented by a single unit spec row. // // Important: these entries DO NOT mark dimensions as "never simplify". // They do the opposite: when a dimension matches, formatting prefers the // named/compound form below. Ambiguity exceptions are handled separately by // denyAutoCanonicalization() in findUnit(). const auto addCanonical = [&](Quantity q, const QString& name) { q.cleanDimension(); m_matchLookup.insert(q.getDimensionByQuantity(), Unit(name, q)); }; addCanonical(Units::volt()*Units::volt()*Units::ampere(), "volt² ampere"); addCanonical(Units::volt()*Units::volt() / Units::ampere(), "volt² ampereâ�»Â¹"); addCanonical(Units::ohm()*Units::metre(), "ohm metre"); addCanonical(Units::siemens() / Units::metre(), "siemens metreâ�»Â¹"); addCanonical(Units::siemens() / Units::metre() / Units::mole(), "siemens metreâ�»Â¹ moleâ�»Â¹"); addCanonical(Units::coulomb() / Units::cubic_metre(), "coulomb metreâ�»Â³"); addCanonical(Units::coulomb() / Units::square_metre(), "coulomb metreâ�»Â²"); addCanonical(Units::coulomb() / Units::kilogram(), "coulomb kilogramâ�»Â¹"); addCanonical(Units::farad() / Units::metre(), "farad metreâ�»Â¹"); addCanonical(Units::henry() / Units::metre(), "henry metreâ�»Â¹"); addCanonical(Quantity(1) / Units::metre() / Units::tesla(), "metreâ�»Â¹ teslaâ�»Â¹"); addCanonical(Units::joule() / Units::kilogram() / Units::kelvin(), "joule kilogramâ�»Â¹ kelvinâ�»Â¹"); addCanonical(Units::joule() / Units::mole() / Units::kelvin(), "joule moleâ�»Â¹ kelvinâ�»Â¹"); addCanonical(Units::mole() / Units::second() / Units::cubic_metre(), "mole secondâ�»Â¹ metreâ�»Â³"); addCanonical(Units::newton() / Units::metre(), "newton metreâ�»Â¹"); addCanonical(Units::pascal() * Units::second(), "pascal second"); addCanonical(Units::volt() / Units::metre(), "volt metreâ�»Â¹"); addCanonical(Units::watt() / Units::metre() / Units::kelvin(), "watt metreâ�»Â¹ kelvinâ�»Â¹"); addCanonical(Units::watt() / Units::square_metre(), "watt/metre²"); addCanonical(Units::joule() / Units::kelvin(), "joule/kelvin"); addCanonical(Units::joule() / Units::kilogram(), "joule/kilogram"); addCanonical(Units::kilogram()*Units::square_metre()*Units::volt() / (Units::second()*Units::second()*Units::second()*Units::second()), "kilogram metre² volt secondâ�»â�´"); } // Resolves and formats the best unit display for a quantity dimension: // prefers canonical named units, otherwise renders composed factors. void Units::findUnit(Quantity& q) { struct ExplicitAngleFactorInfo { bool hasFactor = false; Rational exponent = Rational(0); AngleUnitKind preferredKind = AngleUnitKind::None; }; const auto explicitAngleFactorInfo = [](const QString& text) { ExplicitAngleFactorInfo info; if (text.isEmpty()) return info; int sign = 1; QString token; auto flushToken = [&]() { if (token.isEmpty()) return; QString factor = token.trimmed(); token.clear(); if (factor.isEmpty()) return; int exponentStart = factor.size(); bool hasExponent = false; int exponent = parseTrailingExponent(factor, &exponentStart, &hasExponent); QString base = factor.left(exponentStart).trimmed(); while (!base.isEmpty() && (UnicodeChars::isSuperscriptDigit(base.at(base.size() - 1)) || UnicodeChars::isSuperscriptSign(base.at(base.size() - 1)))) { base.chop(1); } if (base.isEmpty()) return; const AngleUnitKind kind = angleUnitKindFromName(base); if (kind == AngleUnitKind::None) return; info.hasFactor = true; if (info.preferredKind == AngleUnitKind::None) info.preferredKind = kind; if (!hasExponent) exponent = 1; info.exponent += Rational(sign * exponent); }; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); const bool isUnitChar = UnicodeChars::isUnitIdentifierChar(ch) || UnicodeChars::isSuperscriptDigit(ch) || UnicodeChars::isSuperscriptSign(ch); if (isUnitChar) { token += ch; continue; } flushToken(); if (ch == MathDsl::DivOp) sign = -1; } flushToken(); return info; }; const QString originalUnitName = q.unitName(); QString unit_name = ""; CNumber unit(1); q.cleanDimension(); if (m_matchLookup.isEmpty()) initTable(); const QMap dim = q.getDimensionByQuantity(); const ExplicitAngleFactorInfo angleInfo = explicitAngleFactorInfo(originalUnitName); const bool preserveExplicitAngleFactor = !originalUnitName.isEmpty() && !q.isDimensionless() && angleInfo.hasFactor && !angleInfo.exponent.isZero(); // Policy: only auto-canonicalize dimensions that map to a single, // overwhelmingly standard named unit without major semantic collision. // Example: N·m is intentionally kept explicit in multiplication code // (see Quantity::operator*) and only becomes J on explicit conversion. // These denylist entries intentionally keep expressions expanded to // avoid silently choosing one meaning among multiple valid ones. const auto denyAutoCanonicalization = [&](const QString& candidateName, const QMap& candidateDim) { auto makeDim = [](std::initializer_list> items) { QMap d; for (const auto& item : items) d.insert(item.first, Rational(item.second)); return d; }; static const QMap perSecondDim = makeDim({{UnitQuantity::Time, -1}}); static const QMap specificEnergyDim = makeDim({{UnitQuantity::Length, 2}, {UnitQuantity::Time, -2}}); const QString name = candidateName.toLower(); if ((name == unitName(UnitId::Hertz) || name == unitName(UnitId::Becquerel)) && candidateDim == perSecondDim) { return true; } if ((name == unitName(UnitId::Gray) || name == unitName(UnitId::Sievert)) && candidateDim == specificEnergyDim) { return true; } return false; }; const auto isSpeedDimension = [](const QMap& dimension) { return dimension.size() == 2 && dimension.value(UnitQuantity::Length) == Rational(1) && dimension.value(UnitQuantity::Time) == Rational(-1); }; const auto tryNamedSpeedDisplayUnit = [&](QString* displayUnitName, CNumber* displayUnitValue) { static const QList candidates = { UnitId::MilePerHour, UnitId::KilometrePerHour, UnitId::Knot }; for (const UnitId id : candidates) { const QString name = unitName(id); const Quantity value = unitValue(id); if (value.numericValue() != q.numericValue()) continue; if (displayUnitName) *displayUnitName = name; if (displayUnitValue) *displayUnitValue = value.numericValue(); return true; } return false; }; const auto tryReadablePrefixedDisplayUnit = [&]() { if (!q.numericValue().isNearReal()) return false; if (dim.isEmpty()) return false; struct Candidate { QString name; CNumber value; ReadableUnitScore score; }; const HNumber baseValue = q.numericValue().real; const QHash& specs = s_unitSpecs(); bool canonicalAlreadyReadable = false; Candidate best; const auto considerCandidate = [&](const QString& name, const Quantity& value) { if (name.isEmpty()) return; Quantity candidate(value); candidate.cleanDimension(); const QMap candidateDim = candidate.getDimensionByQuantity(); if (candidateDim != dim || denyAutoCanonicalization(name, candidateDim)) return; const ReadableUnitScore candidateScore = readableUnitScore( baseValue, candidate.numericValue()); if (candidateScore.bucket != 0) return; if (best.name.isEmpty() || isBetterReadableUnitScore(candidateScore, best.score)) best = Candidate{name, candidate.numericValue(), candidateScore}; }; for (const UnitId id : s_unitSpecOrder()) { const UnitSpec& spec = specs.value(id); if (spec.prefixPolicy == NoPrefixes || !spec.linearValue || spec.affine.toBase) continue; Quantity baseUnitValue = spec.linearValue(); baseUnitValue.cleanDimension(); const QMap candidateDim = baseUnitValue.getDimensionByQuantity(); if (candidateDim != dim || denyAutoCanonicalization(spec.name, candidateDim)) continue; if ((spec.family == UnitFamily::SiBase || spec.family == UnitFamily::SiDerived) && readableUnitScore(baseValue, baseUnitValue.numericValue()).bucket == 0) { canonicalAlreadyReadable = true; } if (spec.family != UnitFamily::SiBase && spec.family != UnitFamily::SiDerived) considerCandidate(spec.symbol.isEmpty() ? spec.name : spec.symbol, baseUnitValue); // Area and volume have explicit prefixed units, but generating // prefixes from m²/m³ changes powers by the exponent and produces // surprising display choices for ordinary square/cubic units. if (id == UnitId::SquareMetre || id == UnitId::CubicMetre || id == UnitId::Kilogram) continue; for (const PrefixSpec& prefix : s_siPrefixes()) { if (prefix.power % 3 != 0) continue; if (id == UnitId::Second && prefix.power > 0) continue; if (!unitPrefixPolicyAllows(spec.prefixPolicy, prefix)) continue; if (spec.symbol.isEmpty() || !shouldAddSiPrefixedShortAlias(prefix.symbol, spec.symbol)) { continue; } considerCandidate(prefix.symbol + spec.symbol, prefix.value * baseUnitValue); } } if (canonicalAlreadyReadable || best.name.isEmpty()) return false; q.setDisplayUnit(best.value, best.name); return true; }; if (isSpeedDimension(dim)) { QString speedUnitName; CNumber speedUnitValue; if (tryNamedSpeedDisplayUnit(&speedUnitName, &speedUnitValue)) { q.setDisplayUnit(speedUnitValue, speedUnitName); return; } if (!originalUnitName.isEmpty() && originalUnitName.contains(MathDsl::DivOp)) { q.setDisplayUnit(q.numericValue(), originalUnitName); return; } } if (tryReadablePrefixedDisplayUnit()) return; if (dim.size() == 1 && dim.value(UnitQuantity::Mass) == Rational(1) && q.hasUnit() && q.numericValue().isNearReal() && q.unit().isNearReal()) { HNumber kilogramValue = q.numericValue().real; if (kilogramValue < HNumber(0)) kilogramValue = -kilogramValue; if (kilogramValue >= HNumber(1) && kilogramValue < HNumber(1000)) { q.setDisplayUnit(CNumber(1), unitName(UnitId::Kilogram)); return; } } if (m_matchLookup.contains(dim) && !preserveExplicitAngleFactor) { Unit temp(m_matchLookup[dim]); if (runtimeUnitNegativeExponentStyle() == Settings::UnitNegativeExponentSuperscript) temp.name = applySuperscriptStyleToUnitName(temp.name); // For denylisted dimensions, keep base/compound form instead of forcing // a potentially ambiguous derived-unit name. if (!denyAutoCanonicalization(temp.name, dim)) q.setDisplayUnit(temp.value.numericValue(), temp.name); } else { const auto superscriptFromExponent = [](const Rational& value) { QString exponent = value.toString(); if (exponent.contains('/')) exponent = QString(MathDsl::PowOp) + QString(MathDsl::GroupStart) + exponent + MathDsl::GroupEnd; else if (exponent == "1") exponent = ""; else exponent = QString(MathDsl::PowOp) + exponent; if (exponent.startsWith(MathDsl::PowOp) && !exponent.contains(MathDsl::GroupStart)) { QString superscript; superscript.reserve(exponent.size()); for (int i = 1; i < exponent.size(); ++i) { const QChar ch = exponent.at(i); if (ch == MathDsl::SubOpAl1) { superscript += MathDsl::PowNeg; } else if (ch == QLatin1Char('+')) { superscript += MathDsl::PowPos; } else if (ch >= MathDsl::Dig0 && ch <= MathDsl::Dig9) { superscript += MathDsl::asciiDigitToSuperscript(ch); } else { return exponent; } } if (!superscript.isEmpty()) return superscript; } return exponent; }; struct UnitFactor { QString name; Rational exponent; }; QList factors; const auto appendFactor = [&](const QString& name, const Rational& exponent) { factors.append(UnitFactor{name, exponent}); }; if (preserveExplicitAngleFactor) { const auto compositeAngleDisplayName = [](AngleUnitKind kind) { if (kind == AngleUnitKind::Radian) return unitName(UnitId::Radian); if (kind == AngleUnitKind::Gradian) return UnitSymbol::Gradian; if (kind == AngleUnitKind::Turn) return UnitSymbol::Turn; return UnitAltSymbol::Degree1; }; appendFactor(compositeAngleDisplayName(angleInfo.preferredKind), angleInfo.exponent); const Quantity explicitAngleScale = angleUnitValueForMode( angleInfo.preferredKind == AngleUnitKind::None ? AngleUnitKind::Degree : angleInfo.preferredKind, s_runtimeAngleModeForUnits); const QByteArray exponentText = angleInfo.exponent.toString().toLatin1(); unit *= HMath::raise(explicitAngleScale.numericValue().real, HNumber(exponentText.constData())); } // Prefer recognizable derived SI units before base-unit fallback. QMap remaining = q.getDimensionByQuantity(); static const QList derivedCandidates = { Unit(unitName(UnitId::Tesla), unitValue(UnitId::Tesla)), Unit(unitName(UnitId::Weber), unitValue(UnitId::Weber)), Unit(unitName(UnitId::Henry), unitValue(UnitId::Henry)), Unit(unitName(UnitId::Farad), unitValue(UnitId::Farad)), Unit(unitName(UnitId::Ohm), unitValue(UnitId::Ohm)), Unit(unitName(UnitId::Siemens), unitValue(UnitId::Siemens)), Unit(unitName(UnitId::Volt), unitValue(UnitId::Volt)), Unit(unitName(UnitId::Coulomb), unitValue(UnitId::Coulomb)), Unit(unitName(UnitId::Joule), unitValue(UnitId::Joule)), Unit(unitName(UnitId::Newton), unitValue(UnitId::Newton)), Unit(unitName(UnitId::Pascal), unitValue(UnitId::Pascal)), Unit(unitName(UnitId::Watt), unitValue(UnitId::Watt)), Unit(unitName(UnitId::Hertz), unitValue(UnitId::Hertz)), Unit(unitName(UnitId::Becquerel), unitValue(UnitId::Becquerel)), Unit(unitName(UnitId::Gray), unitValue(UnitId::Gray)), Unit(unitName(UnitId::Sievert), unitValue(UnitId::Sievert)), Unit(unitName(UnitId::Katal), unitValue(UnitId::Katal)), Unit(unitName(UnitId::Lumen), unitValue(UnitId::Lumen)), Unit(unitName(UnitId::Lux), unitValue(UnitId::Lux)), Unit(unitName(UnitId::Steradian), unitValue(UnitId::Steradian)) }; const QString lumenName = unitName(UnitId::Lumen); bool progress = true; while (progress) { progress = false; for (const Unit& candidate : derivedCandidates) { Quantity qc(candidate.value); qc.cleanDimension(); const auto cdim = qc.getDimensionByQuantity(); if (cdim.isEmpty() || (cdim.size() < 2 && candidate.name != lumenName)) continue; bool firstRatio = true; Rational ratio; bool fits = true; for (auto it = cdim.constBegin(); it != cdim.constEnd(); ++it) { if (!remaining.contains(it.key())) { fits = false; break; } const Rational rv = remaining.value(it.key()); const Rational cv = it.value(); Rational r(rv.numerator() * cv.denominator(), rv.denominator() * cv.numerator()); if (firstRatio) { ratio = r; firstRatio = false; } else if (r != ratio) { fits = false; break; } } if (!fits || firstRatio || ratio.isZero() || ratio.denominator() != 1) continue; const Rational ratioInt(ratio.numerator(), 1); for (auto it = cdim.constBegin(); it != cdim.constEnd(); ++it) { const UnitQuantity key = it.key(); remaining[key] -= ratioInt * it.value(); if (remaining[key].isZero()) remaining.remove(key); } if (!denyAutoCanonicalization(candidate.name, qc.getDimensionByQuantity())) appendFactor(candidate.name, ratioInt); else { // Keep base-unit expansion for denied automatic canonicalizations. // Revert the tentative reduction and continue searching. for (auto it = cdim.constBegin(); it != cdim.constEnd(); ++it) { const UnitQuantity key = it.key(); remaining[key] += ratioInt * it.value(); if (remaining[key].isZero()) remaining.remove(key); } continue; } progress = true; break; } } auto appendDimension = [&](UnitQuantity key, const Rational& value) { const QString baseUnitName = s_baseUnitCanonicalNameForQuantity(key); if (!baseUnitName.isEmpty()) appendFactor(baseUnitName, value); else { const QString dimensionKey = unitQuantityDimensionKey(key); appendFactor(!dimensionKey.isEmpty() ? dimensionKey : QStringLiteral("dimension"), value); } }; // Keep auto-generated base-unit products in canonical output order: // kilogram, metre, second, ampere, kelvin, mole, candela, information. // (Angle units such as radian/steradian are represented explicitly when used.) QSet handledDimensions; for (const UnitQuantity key : s_baseDimensionOutputOrder()) { if (!remaining.contains(key)) continue; appendDimension(key, remaining.value(key)); handledDimensions.insert(key); } for (auto i = remaining.constBegin(); i != remaining.constEnd(); ++i) { if (!handledDimensions.contains(i.key())) appendDimension(i.key(), i.value()); } // Readability optimization for mixed electro-mechanical dimensions: // when both electrical current and mass are present, prefer a compact // representation in terms of C and J (plus minimal base leftovers) // when that is clearly shorter than base-heavy decomposition. const auto exponentComplexity = [](const Rational& exponent) { const int n = qAbs(exponent.numerator()); const int d = exponent.denominator(); return d == 1 ? n : (n + d); }; const auto factorPenalty = [exponentComplexity](const UnitFactor& factor) { const UnitId factorId = unitId(normalizeUnitName(factor.name)); const auto specIt = s_unitSpecs().constFind(factorId); const bool isBase = specIt != s_unitSpecs().constEnd() && specIt.value().family == UnitFamily::SiBase; const int unitWeight = isBase ? 6 : 2; return unitWeight * exponentComplexity(factor.exponent); }; const auto scoreFactors = [&](const QList& candidateFactors) { int score = 0; for (const UnitFactor& factor : candidateFactors) score += factorPenalty(factor); score += candidateFactors.size() * 2; return score; }; const Rational zero(0); const Rational two(2); const Rational currentExp = dim.value(UnitQuantity::ElectricCurrent, zero); const Rational massExp = dim.value(UnitQuantity::Mass, zero); if (!currentExp.isZero() && !massExp.isZero() && currentExp.denominator() == 1 && massExp.denominator() == 1) { const Rational lengthExp = dim.value(UnitQuantity::Length, zero); const Rational timeExp = dim.value(UnitQuantity::Time, zero); if (lengthExp.denominator() == 1 && timeExp.denominator() == 1) { QList compactFactors; compactFactors.reserve(factors.size()); compactFactors.append(UnitFactor{unitName(UnitId::Coulomb), currentExp}); compactFactors.append(UnitFactor{unitName(UnitId::Joule), massExp}); const Rational residualLength = lengthExp - (two * massExp); const Rational residualTime = timeExp - currentExp + (two * massExp); if (!residualLength.isZero()) compactFactors.append(UnitFactor{unitName(UnitId::Metre), residualLength}); if (!residualTime.isZero()) compactFactors.append(UnitFactor{unitName(UnitId::Second), residualTime}); for (auto it = dim.constBegin(); it != dim.constEnd(); ++it) { const UnitQuantity key = it.key(); const bool isCoreCompactDimension = key == UnitQuantity::ElectricCurrent || key == UnitQuantity::Mass || key == UnitQuantity::Length || key == UnitQuantity::Time; if (isCoreCompactDimension) continue; if (!it.value().isZero()) { const QString baseUnitName = s_baseUnitCanonicalNameForQuantity(key); const QString dimensionKey = unitQuantityDimensionKey(key); const QString factorName = !baseUnitName.isEmpty() ? baseUnitName : (!dimensionKey.isEmpty() ? dimensionKey : QStringLiteral("dimension")); compactFactors.append(UnitFactor{factorName, it.value()}); } } // Keep deterministic order: C, J, then leftovers in canonical // base-dimension order and finally unknown dimensions. const auto orderIndex = [](const QString& name) { if (name == unitName(UnitId::Coulomb)) return 0; if (name == unitName(UnitId::Joule)) return 1; const auto& order = s_baseDimensionOutputOrder(); for (const UnitQuantity quantity : order) { if (name == s_baseUnitCanonicalNameForQuantity(quantity)) return s_baseDimensionOutputOrderIndex(quantity); } return 100; }; std::sort(compactFactors.begin(), compactFactors.end(), [&](const UnitFactor& a, const UnitFactor& b) { const int ao = orderIndex(a.name); const int bo = orderIndex(b.name); if (ao != bo) return ao < bo; return a.name < b.name; }); if (scoreFactors(compactFactors) < scoreFactors(factors)) factors = compactFactors; } } if (runtimeUnitNegativeExponentStyle() == Settings::UnitNegativeExponentSuperscript) { QStringList terms; for (const UnitFactor& factor : factors) terms << (factor.name + superscriptFromExponent(factor.exponent)); unit_name = MathDsl::QuantSp + terms.join(QString(MathDsl::MulDotOp)); } else { QStringList numeratorTerms; QStringList denominatorTerms; for (const UnitFactor& factor : factors) { if (factor.exponent > zero) { numeratorTerms << (factor.name + superscriptFromExponent(factor.exponent)); } else if (factor.exponent < zero) { const Rational absExponent(-factor.exponent.numerator(), factor.exponent.denominator()); denominatorTerms << (factor.name + superscriptFromExponent(absExponent)); } } const QString numeratorText = numeratorTerms.join(QString(MathDsl::MulDotOp)); const QString denominatorText = denominatorTerms.join(QString(MathDsl::MulDotOp)); if (!numeratorTerms.isEmpty() && !denominatorTerms.isEmpty()) { unit_name = MathDsl::QuantSp + numeratorText + MathDsl::DivOp; if (denominatorTerms.size() > 1) unit_name += MathDsl::GroupStart + denominatorText + MathDsl::GroupEnd; else unit_name += denominatorText; } else if (!numeratorTerms.isEmpty()) { unit_name = MathDsl::QuantSp + numeratorText; } else if (!denominatorTerms.isEmpty()) { // Keep inverse-only units in exponent form (sâ�»Â¹, mâ�»Â¹â‹…sâ�»Â², ...). QStringList inverseTerms; for (const UnitFactor& factor : factors) { if (factor.exponent < zero) inverseTerms << (factor.name + superscriptFromExponent(factor.exponent)); } unit_name = MathDsl::QuantSp + inverseTerms.join(QString(MathDsl::MulDotOp)); } } q.setDisplayUnit(unit, unit_name.trimmed()); } } namespace { // Builds runtime lookup registries from declarative unit specs: // identifiers, display symbols, affine converters and canonical matches. static UnitRegistry s_buildUnitRegistry() { StartupDiagnostics::Scope timing("Build built-in unit registry"); UnitRegistry registry; QList unitAliasSpecs; const auto addUnique = [&](const QString& name, const Quantity& value, const QString& localizedName = QString(), UnitId id = UnitId::Unknown, bool prefixedIdentifier = false) { if (name.isEmpty() || registry.valuesByIdentifier.contains(name)) return; registry.valuesByIdentifier.insert(name, value); if (id != UnitId::Unknown) registry.idsByIdentifier.insert(name, id); if (!localizedName.isEmpty()) registry.localizedByIdentifier.insert(name, localizedName); if (prefixedIdentifier) registry.prefixedIdentifiers.insert(name); }; const auto localizedFromSpec = [](const UnitSpec& spec) { return spec.localized ? QString::fromUtf8(spec.localized) : QString(); }; const auto prefixedLocalizedName = [](const QString& prefix, const QString& base) -> QString { if (prefix.isEmpty() || base.isEmpty()) return QString(); QString loweredBase = base; loweredBase[0] = loweredBase.at(0).toLower(); return prefix + loweredBase; }; const QHash& specs = s_unitSpecs(); for (const UnitId id : s_unitSpecOrder()) { const UnitSpec& spec = specs.value(id); // Spec -> runtime registry: // canonical name/symbol/aliases are all registered from this single source. const Quantity value = spec.linearValue ? spec.linearValue() : Quantity(1); const QString localized = localizedFromSpec(spec); addUnique(spec.name, value, localized, id); const QString symbol = spec.symbol; if (!symbol.isEmpty()) { addUnique(symbol, value, localized, id); registry.displaySymbolsByIdentifier.insert(spec.name, symbol); registry.displaySymbolsByIdentifier.insert(symbol, symbol); } for (const QString& alias : spec.aliases) { if (alias.isEmpty()) continue; addUnique(alias, value, localized, id); if (!symbol.isEmpty()) registry.displaySymbolsByIdentifier.insert(alias, symbol); } // Prefix generation currently consumes one alternate short alias // (the first alias entry), in addition to the canonical symbol. const QString primaryAlias = spec.aliases.isEmpty() ? QString() : spec.aliases.first(); unitAliasSpecs.append({ id, spec.name, localized, value, symbol, primaryAlias, spec.prefixPolicy }); if (spec.affine.toBase && spec.affine.fromBase) { registry.affineByIdentifier.insert(spec.name, spec.affine); if (!symbol.isEmpty()) registry.affineByIdentifier.insert(symbol, spec.affine); for (const QString& alias : spec.aliases) { if (alias.isEmpty()) continue; registry.affineByIdentifier.insert(alias, spec.affine); } continue; } // Build canonical dimension->unit lookup from declarative spec. // Keep only unambiguous SI base/derived rows and preserve first-in wins. if ((spec.family == UnitFamily::SiBase || spec.family == UnitFamily::SiDerived) && !spec.quantities.contains(UnitQuantity::Unspecified) && spec.quantities.size() == 1) { const UnitQuantity quantity = spec.quantities.first(); // Keep ambiguous or purely notational units out of auto-canonicalization. if (quantity == UnitQuantity::PlaneAngle || quantity == UnitQuantity::SolidAngle || quantity == UnitQuantity::Frequency || quantity == UnitQuantity::Area || quantity == UnitQuantity::ActivityReferredToARadionuclide || quantity == UnitQuantity::AbsorbedDose || quantity == UnitQuantity::DoseEquivalent || quantity == UnitQuantity::Information) { continue; } Quantity canonicalValue = value; canonicalValue.cleanDimension(); const QMap dim = canonicalValue.getDimensionByQuantity(); if (!dim.isEmpty() && !registry.canonicalMatchLookup.contains(dim)) { registry.canonicalMatchLookup.insert( dim, Unit(spec.name, canonicalValue)); } } } // Automatic SI-prefixed aliases for every prefixable unit. // Example: kilo + m² => km², kilo + m³ => km³. // This is spec-driven via UnitAliasSpec built above from unit specs. for (const PrefixSpec& prefix : s_siPrefixes()) { for (const UnitAliasSpec& unit : unitAliasSpecs) { if (!unitPrefixPolicyAllows(unit.prefixPolicy, prefix)) continue; if (unit.id == UnitId::SquareMetre || unit.id == UnitId::CubicMetre) continue; const Quantity prefixedValue = prefix.value * unit.value; const QString localized = prefixedLocalizedName(prefix.longName, unit.localized); const bool keepPrefixedDisplay = prefix.power > 0 && prefix.power < 3; // Long form: kilo + metre => kilometre addUnique(prefix.longName + unit.longName, prefixedValue, localized, unit.id, keepPrefixedDisplay); if (!unit.shortName.isEmpty() && shouldAddSiPrefixedShortAlias(prefix.symbol, unit.shortName)) // Symbol form: k + m => km; k + m² => km²; k + m³ => km³ addUnique(prefix.symbol + unit.shortName, prefixedValue, localized, unit.id, keepPrefixedDisplay); if (!unit.alternateShortName.isEmpty() && shouldAddSiPrefixedShortAlias(prefix.symbol, unit.alternateShortName)) addUnique(prefix.symbol + unit.alternateShortName, prefixedValue, localized, unit.id, keepPrefixedDisplay); } } // Automatic binary-prefixed aliases are generated from unit specs. // Standalone binary prefixes (kibi/mebi/...) are not registered as units. for (const PrefixSpec& prefix : s_binaryPrefixes()) { for (const UnitAliasSpec& unit : unitAliasSpecs) { if (!unitPrefixPolicyAllows(unit.prefixPolicy, prefix, true)) continue; const Quantity prefixedValue = prefix.value * unit.value; const QString localized = prefixedLocalizedName(prefix.longName, unit.localized); addUnique(prefix.longName + unit.longName, prefixedValue, localized, unit.id); if (!unit.shortName.isEmpty()) addUnique(prefix.symbol + unit.shortName, prefixedValue, localized, unit.id); } } return registry; } const UnitRegistry& s_unitRegistry() { static const UnitRegistry registry = s_buildUnitRegistry(); return registry; } } // namespace // Returns built-in unit identifiers mapped to their base quantity values. const QHash& Units::builtInUnitValues() { return s_unitRegistry().valuesByIdentifier; } QHash Units::builtInUnitLookup(char angleMode) { s_runtimeAngleModeForUnits = angleMode; QHash lookup; const UnitRegistry& registry = s_unitRegistry(); const auto& unitValues = registry.valuesByIdentifier; lookup.reserve(unitValues.size()); for (auto it = unitValues.constBegin(); it != unitValues.constEnd(); ++it) { const QString& identifier = it.key(); const Quantity& value = it.value(); Quantity unitValue = value; const auto idIt = registry.idsByIdentifier.constFind(identifier); const UnitId id = idIt != registry.idsByIdentifier.constEnd() ? idIt.value() : unitId(normalizeUnitName(identifier)); const bool isCanonicalIdentifier = id != UnitId::Unknown && identifier == unitName(id); const bool isInformationUnit = unitValue.getDimensionByQuantity().contains(UnitQuantity::Information); const auto specIt = s_unitSpecs().constFind(id); const bool isNonSiIdentifier = specIt != s_unitSpecs().constEnd() && specIt.value().family != UnitFamily::SiBase && specIt.value().family != UnitFamily::SiDerived && id != UnitId::Second && id != UnitId::Minute && id != UnitId::Hour && id != UnitId::Day && id != UnitId::Week; const bool keepDisplayUnit = (id == UnitId::Steradian) || registry.prefixedIdentifiers.contains(identifier) || ((id == UnitId::Hertz || id == UnitId::Becquerel || id == UnitId::Gray || id == UnitId::Sievert || id == UnitId::Pascal || id == UnitId::Newton || id == UnitId::Metre) && isCanonicalIdentifier) || isInformationUnit || isNonSiIdentifier; if (keepDisplayUnit) unitValue.setDisplayUnit(value.numericValue(), identifier); lookup.insert(identifier, unitValue); } const auto insertDisplayed = [&](const QString& key, const Quantity& value, const QString& displayName) { Quantity q(value); q.setDisplayUnit(value.numericValue(), displayName); lookup.insert(key, q); }; // Force display-name preservation for short symbols/aliases that are // intentionally user-facing spellings. Without this, some lookups keep // value equivalence but lose the authored display token. insertDisplayed(UnitSymbol::Joule, unitValue(UnitId::Joule), unitName(UnitId::Joule)); insertDisplayed(UnitSymbol::Watt, unitValue(UnitId::Watt), unitName(UnitId::Watt)); insertDisplayed(UnitSymbol::Volt, unitValue(UnitId::Volt), unitName(UnitId::Volt)); insertDisplayed(UnitSymbol::Farad, unitValue(UnitId::Farad), unitName(UnitId::Farad)); insertDisplayed(UnitSymbol::Henry, unitValue(UnitId::Henry), unitName(UnitId::Henry)); insertDisplayed(UnitSymbol::Tesla, unitValue(UnitId::Tesla), unitName(UnitId::Tesla)); insertDisplayed(UnitSymbol::Newton, unitValue(UnitId::Newton), unitName(UnitId::Newton)); insertDisplayed(UnitSymbol::Pascal, unitValue(UnitId::Pascal), unitName(UnitId::Pascal)); insertDisplayed(UnitName::Ohm, unitValue(UnitId::Ohm), unitName(UnitId::Ohm)); insertDisplayed(UnitSymbol::Ohm, unitValue(UnitId::Ohm), unitName(UnitId::Ohm)); insertDisplayed(UnitSymbol::Second, unitValue(UnitId::Second), unitName(UnitId::Second)); insertDisplayed(UnitSymbol::Hour, unitValue(UnitId::Hour), UnitSymbol::Hour); const auto insertAffineDisplayAliases = [&](UnitId id) { const auto specIt = s_unitSpecs().constFind(id); if (specIt == s_unitSpecs().constEnd()) return; const UnitSpec& spec = specIt.value(); if (!(spec.affine.toBase && spec.affine.fromBase)) return; insertDisplayed(spec.name, unitValue(UnitId::Kelvin), spec.name); if (!spec.symbol.isEmpty()) insertDisplayed(spec.symbol, Units::kelvin(), spec.symbol); for (const QString& alias : spec.aliases) { if (alias.isEmpty()) continue; insertDisplayed(alias, Units::kelvin(), spec.symbol.isEmpty() ? spec.name : spec.symbol); } }; insertAffineDisplayAliases(UnitId::DegreeCelsius); insertAffineDisplayAliases(UnitId::DegreeFahrenheit); { Quantity hz = unitValue(UnitId::Hertz); hz.setDisplayUnit(unitValue(UnitId::Hertz).numericValue(), unitName(UnitId::Hertz)); lookup.insert(UnitSymbol::Hertz, hz); } { Quantity bq = unitValue(UnitId::Becquerel); bq.setDisplayUnit(unitValue(UnitId::Becquerel).numericValue(), unitName(UnitId::Becquerel)); lookup.insert(UnitSymbol::Becquerel, bq); } lookup.insert(unitName(UnitId::Radian), angleUnitValueForMode(AngleUnitKind::Radian, angleMode)); lookup.insert(UnitSymbol::Radian, angleUnitValueForMode(AngleUnitKind::Radian, angleMode)); lookup.insert(unitName(UnitId::Degree), angleUnitValueForMode(AngleUnitKind::Degree, angleMode)); lookup.insert(UnitAltSymbol::Degree1, angleUnitValueForMode(AngleUnitKind::Degree, angleMode)); lookup.insert(UnitSymbol::Degree, angleUnitValueForMode(AngleUnitKind::Degree, angleMode)); lookup.insert(UnitName::Gradian, angleUnitValueForMode(AngleUnitKind::Gradian, angleMode)); lookup.insert(UnitSymbol::Gradian, angleUnitValueForMode(AngleUnitKind::Gradian, angleMode)); lookup.insert(UnitName::Turn, angleUnitValueForMode(AngleUnitKind::Turn, angleMode)); lookup.insert(UnitSymbol::Turn, angleUnitValueForMode(AngleUnitKind::Turn, angleMode)); lookup.insert(UnitName::Revolution, angleUnitValueForMode(AngleUnitKind::Turn, angleMode)); lookup.insert(UnitSymbol::Revolution, angleUnitValueForMode(AngleUnitKind::Turn, angleMode)); { Quantity rpm = angleUnitValueForMode(AngleUnitKind::Turn, angleMode) / Units::minute(); const QString rpmDisplayName = composeAnglePerSecondUnitName(Units::angleModeUnitSymbol(angleMode)); rpm.setDisplayUnit(rpm.unit(), rpmDisplayName); lookup.insert(unitName(UnitId::RevolutionPerMinute), rpm); lookup.insert(UnitSymbol::RevolutionPerMinute, rpm); } lookup.insert(unitName(UnitId::Arcminute), angleUnitValueForMode(AngleUnitKind::Arcminute, angleMode)); lookup.insert(unitName(UnitId::Arcsecond), angleUnitValueForMode(AngleUnitKind::Arcsecond, angleMode)); lookup.insert(unitName(UnitId::Milliarcsecond), angleUnitValueForMode(AngleUnitKind::Milliarcsecond, angleMode)); lookup.insert(unitName(UnitId::Microarcsecond), angleUnitValueForMode(AngleUnitKind::Microarcsecond, angleMode)); lookup.insert(UnitAltSymbol::Arcminute, angleUnitValueForMode(AngleUnitKind::Arcminute, angleMode)); lookup.insert(UnitAltSymbol::Arcsecond, angleUnitValueForMode(AngleUnitKind::Arcsecond, angleMode)); lookup.insert(UnitSymbol::Arcminute, angleUnitValueForMode(AngleUnitKind::Arcminute, angleMode)); lookup.insert(UnitSymbol::Arcsecond, angleUnitValueForMode(AngleUnitKind::Arcsecond, angleMode)); lookup.insert(UnitSymbol::Milliarcsecond, angleUnitValueForMode(AngleUnitKind::Milliarcsecond, angleMode)); lookup.insert(UnitSymbol::Microarcsecond, angleUnitValueForMode(AngleUnitKind::Microarcsecond, angleMode)); lookup.insert(UnitAltSymbol::MicroarcsecondAscii, angleUnitValueForMode(AngleUnitKind::Microarcsecond, angleMode)); for (auto it = lookup.begin(); it != lookup.end(); ++it) { Quantity prefixedAngleValue; if (tryGetPrefixedExplicitAngleUnitValueForMode(it.key(), angleMode, &prefixedAngleValue)) it.value() = prefixedAngleValue; } return lookup; } bool Units::isExplicitAngleUnitName(const QString& unitName) { return angleUnitKindFromName(unitName) != AngleUnitKind::None; } bool Units::isAffineUnitName(const QString& unitName) { return s_unitRegistry().affineByIdentifier.contains( UnicodeChars::normalizeUnitSymbolAliases(unitName.trimmed())); } bool Units::tryConvertAffineToBase(const QString& unitName, const HNumber& value, HNumber* baseValueOut) { if (!baseValueOut) return false; const QString normalized = UnicodeChars::normalizeUnitSymbolAliases(unitName.trimmed()); const auto it = s_unitRegistry().affineByIdentifier.constFind(normalized); if (it == s_unitRegistry().affineByIdentifier.constEnd() || !it.value().toBase) return false; *baseValueOut = it.value().toBase(value); return true; } bool Units::tryConvertAffineFromBase(const QString& unitName, const HNumber& baseValue, HNumber* valueOut) { if (!valueOut) return false; const QString normalized = UnicodeChars::normalizeUnitSymbolAliases(unitName.trimmed()); const auto it = s_unitRegistry().affineByIdentifier.constFind(normalized); if (it == s_unitRegistry().affineByIdentifier.constEnd() || !it.value().fromBase) return false; *valueOut = it.value().fromBase(baseValue); return true; } // Converts explicit-angle quantities to radians in-place and strips units. bool Units::tryConvertExplicitAngleToRadians(Quantity* angle) { if (!angle || !angle->hasUnit()) return false; const AngleUnitKind unitKind = angleUnitKindFromName(angle->unitName()); if (unitKind == AngleUnitKind::None) return false; if (unitKind == AngleUnitKind::Degree) *angle = DMath::deg2rad(*angle); else if (unitKind == AngleUnitKind::Gradian) *angle = DMath::gon2rad(*angle); else if (unitKind == AngleUnitKind::Turn) *angle *= Quantity(2) * DMath::pi(); else if (unitKind == AngleUnitKind::Arcminute) *angle = DMath::deg2rad(*angle / Quantity(60)); else if (unitKind == AngleUnitKind::Arcsecond) *angle = DMath::deg2rad(*angle / Quantity(3600)); else if (unitKind == AngleUnitKind::Milliarcsecond) *angle = DMath::deg2rad(*angle / Quantity(3600000)); else if (unitKind == AngleUnitKind::Microarcsecond) *angle = DMath::deg2rad(*angle / HNumber("3600000000")); angle->stripUnits(); return true; } DEFINE_BASE_UNIT(metre) DEFINE_BASE_UNIT(second) DEFINE_BASE_UNIT(kilogram) DEFINE_BASE_UNIT(ampere) DEFINE_BASE_UNIT(mole) DEFINE_BASE_UNIT(kelvin) DEFINE_BASE_UNIT(candela) DEFINE_BASE_UNIT(byte) // Internal primitive for the information dimension (not an SI base unit). DEFINE_DERIVED_UNIT(newton, Units::metre() * Units::kilogram() / (Units::second()*Units::second())) DEFINE_DERIVED_UNIT(hertz, Quantity(1) / Units::second()) DEFINE_DERIVED_UNIT(radian, Quantity(1)) DEFINE_DERIVED_UNIT(degree, HMath::pi() * Units::radian() / HNumber(180)) DEFINE_DERIVED_UNIT(gradian, HMath::pi() / HNumber(200)) DEFINE_DERIVED_UNIT(turn, HNumber(2) * HMath::pi() * Units::radian()) DEFINE_DERIVED_UNIT(revolution, HNumber(2) * HMath::pi() * Units::radian()) DEFINE_DERIVED_UNIT(arcminute, Units::degree() / HNumber(60)) DEFINE_DERIVED_UNIT(arcsecond, Units::arcminute() / HNumber(60)) DEFINE_DERIVED_UNIT(milliarcsecond, Units::milli() * Units::arcsecond()) DEFINE_DERIVED_UNIT(microarcsecond, Units::micro() * Units::arcsecond()) DEFINE_DERIVED_UNIT(pascal, Units::newton() / Units::square_metre()) DEFINE_DERIVED_UNIT(joule, Units::newton() * Units::metre()) DEFINE_DERIVED_UNIT(watt, Units::joule() / Units::second()) DEFINE_DERIVED_UNIT(coulomb, Units::ampere() * Units::second()) DEFINE_DERIVED_UNIT(volt, Units::watt() / Units::ampere()) DEFINE_DERIVED_UNIT(farad, Units::coulomb() / Units::volt()) DEFINE_DERIVED_UNIT(ohm, Units::volt() / Units::ampere()) DEFINE_DERIVED_UNIT(siemens, Units::ampere() / Units::volt()) DEFINE_DERIVED_UNIT(weber, Units::volt() * Units::second()) DEFINE_DERIVED_UNIT(tesla, Units::weber() / Units::square_metre()) DEFINE_DERIVED_UNIT(henry, Units::weber() / Units::ampere()) DEFINE_DERIVED_UNIT(becquerel, Quantity(1) / Units::second()) DEFINE_DERIVED_UNIT(gray, Units::joule() / Units::kilogram()) DEFINE_DERIVED_UNIT(sievert, Units::joule() / Units::kilogram()) DEFINE_DERIVED_UNIT(katal, Units::mole() / Units::second()) DEFINE_DERIVED_UNIT(steradian, Quantity(1)) DEFINE_DERIVED_UNIT(lumen, Units::candela()*Units::steradian()) DEFINE_DERIVED_UNIT(lux, Units::lumen()/Units::square_metre()) DEFINE_DERIVED_UNIT(electronvolt, HNumber("1.602176634e-19") * Units::joule()) DEFINE_DERIVED_UNIT(tonne, Units::mega() * Units::gram()) DEFINE_DERIVED_UNIT(gram, Units::milli() * Units::kilogram()) DEFINE_DERIVED_UNIT(pound, HNumber("0.45359237") * Units::kilogram()) // International avoirdupois. DEFINE_DERIVED_UNIT(stone, HNumber(14) * Units::pound()) DEFINE_DERIVED_UNIT(ounce, Units::pound() / HNumber(16)) DEFINE_DERIVED_UNIT(grain, Units::pound() / HNumber(7000)) DEFINE_DERIVED_UNIT(short_ton, HNumber(2000) * Units::pound()) DEFINE_DERIVED_UNIT(long_ton, HNumber(2240) * Units::pound()) DEFINE_DERIVED_UNIT(atomic_mass_unit, HNumber("1.66053906892e-27") * Units::kilogram()) // CODATA 2022: https://physics.nist.gov/cgi-bin/cuu/Value?ukg DEFINE_DERIVED_UNIT(carat, HNumber(200) * Units::milli()*Units::gram()) // Do not confuse with karat below. DEFINE_DERIVED_UNIT(angstrom, HNumber("1e-10") * Units::metre() ) DEFINE_DERIVED_UNIT(astronomical_unit, HNumber("149597870700") * Units::metre()) // IAU 2012 Resolution B2. DEFINE_DERIVED_UNIT(lightyear, Units::speed_of_light() * Units::julian_year()) DEFINE_DERIVED_UNIT(lightminute, Units::speed_of_light() * Units::minute()) DEFINE_DERIVED_UNIT(lightsecond, Units::speed_of_light() * Units::second()) DEFINE_DERIVED_UNIT(parsec, HNumber(648000)/HMath::pi() * Units::astronomical_unit()) // IAU 2015 Resolution B2. DEFINE_DERIVED_UNIT(inch, HNumber("0.0254") * Units::metre()) // International inch. DEFINE_DERIVED_UNIT(square_inch, Units::inch() * Units::inch()) DEFINE_DERIVED_UNIT(cubic_inch, Units::inch() * Units::inch() * Units::inch()) DEFINE_DERIVED_UNIT(foot, HNumber(12) * Units::inch()) DEFINE_DERIVED_UNIT(square_foot, Units::foot() * Units::foot()) DEFINE_DERIVED_UNIT(cubic_foot, Units::foot() * Units::foot() * Units::foot()) DEFINE_DERIVED_UNIT(yard, HNumber(36) * Units::inch()) DEFINE_DERIVED_UNIT(square_yard, Units::yard() * Units::yard()) DEFINE_DERIVED_UNIT(cubic_yard, Units::yard() * Units::yard() * Units::yard()) DEFINE_DERIVED_UNIT(mile, HNumber(1760) * Units::yard()) DEFINE_DERIVED_UNIT(square_mile, Units::mile() * Units::mile()) DEFINE_DERIVED_UNIT(cubic_mile, Units::mile() * Units::mile() * Units::mile()) DEFINE_DERIVED_UNIT(rod, HNumber("5.5") * Units::yard()) DEFINE_DERIVED_UNIT(furlong, HNumber(40) * Units::rod()) DEFINE_DERIVED_UNIT(fathom, HNumber(6) * Units::foot()) DEFINE_DERIVED_UNIT(nautical_mile, HNumber("1852") * Units::metre()) // UCUM: [nmi_i] DEFINE_DERIVED_UNIT(square_metre, Units::metre() * Units::metre()) DEFINE_DERIVED_UNIT(hectare, HNumber(10000) * Units::square_metre()) DEFINE_DERIVED_UNIT(acre, Units::mile() * Units::mile() / HNumber(640)) DEFINE_DERIVED_UNIT(cubic_metre, Units::square_metre() * Units::metre()) DEFINE_DERIVED_UNIT(cubic_millimetre, Units::milli() * Units::milli() * Units::milli() * Units::cubic_metre()) DEFINE_DERIVED_UNIT(cubic_centimetre, Units::centi() * Units::centi() * Units::centi() * Units::cubic_metre()) DEFINE_DERIVED_UNIT(cubic_decimetre, Units::deci() * Units::deci() * Units::deci() * Units::cubic_metre()) DEFINE_DERIVED_UNIT(cubic_kilometre, Units::kilo() * Units::kilo() * Units::kilo() * Units::cubic_metre()) DEFINE_DERIVED_UNIT(square_millimetre, Units::milli() * Units::milli() * Units::square_metre()) DEFINE_DERIVED_UNIT(square_kilometre, Units::kilo() * Units::kilo() * Units::square_metre()) DEFINE_DERIVED_UNIT(litre, Units::milli() * Units::cubic_metre()) DEFINE_DERIVED_UNIT(gallon_us, HNumber("3.785411784") * Units::litre()) DEFINE_DERIVED_UNIT(gallon_imp, HNumber("4.54609") * Units::litre()) DEFINE_DERIVED_UNIT(quart_us, Units::gallon_us() / HNumber(4)) DEFINE_DERIVED_UNIT(quart_imp, Units::gallon_imp() / HNumber(4)) DEFINE_DERIVED_UNIT(pint_us, Units::gallon_us() / HNumber(8)) DEFINE_DERIVED_UNIT(pint_imp, Units::gallon_imp() / HNumber(8)) DEFINE_DERIVED_UNIT(gill_us, Units::pint_us() / HNumber(4)) DEFINE_DERIVED_UNIT(gill_imp, Units::pint_imp() / HNumber(4)) DEFINE_DERIVED_UNIT(fluid_ounce_us, Units::gallon_us() / HNumber(128)) DEFINE_DERIVED_UNIT(fluid_ounce_imp, Units::gallon_imp() / HNumber(160)) DEFINE_DERIVED_UNIT(fluid_dram_us, Units::fluid_ounce_us() / HNumber(8)) DEFINE_DERIVED_UNIT(fluid_dram_imp, Units::fluid_ounce_imp() / HNumber(8)) DEFINE_DERIVED_UNIT(barrel_oil, HNumber(42) * Units::gallon_us()) DEFINE_DERIVED_UNIT(barrel_beer_us, HNumber("31.5") * Units::gallon_us()) DEFINE_DERIVED_UNIT(teaspoon, HNumber(5) * Units::milli()*Units::litre()) DEFINE_DERIVED_UNIT(teaspoon_imp, Units::gallon_imp() / HNumber(768)) DEFINE_DERIVED_UNIT(teaspoon_us, Units::gallon_us() / HNumber(768)) DEFINE_DERIVED_UNIT(dessert_spoon, HNumber(10) * Units::milli()*Units::litre()) DEFINE_DERIVED_UNIT(tablespoon, HNumber(15) * Units::milli()*Units::litre()) DEFINE_DERIVED_UNIT(tablespoon_au, HNumber("0.02") * Units::litre()) DEFINE_DERIVED_UNIT(tablespoon_imp, Units::gallon_imp() / HNumber(256)) DEFINE_DERIVED_UNIT(tablespoon_us, Units::gallon_us() / HNumber(256)) DEFINE_DERIVED_UNIT(cup, HNumber(240) * Units::milli()*Units::litre()) DEFINE_DERIVED_UNIT(cup_imp, Units::gallon_imp() / HNumber(16)) DEFINE_DERIVED_UNIT(cup_jp, HNumber("0.2") * Units::litre()) DEFINE_DERIVED_UNIT(cup_us, Units::gallon_us() / HNumber(16)) DEFINE_DERIVED_UNIT(minute, HNumber(60) * Units::second()) DEFINE_DERIVED_UNIT(hour, HNumber(60) * Units::minute()) DEFINE_DERIVED_UNIT(day, HNumber(24) * Units::hour()) DEFINE_DERIVED_UNIT(week, HNumber(7) * Units::day()) DEFINE_DERIVED_UNIT(julian_year, HNumber("365.25") * Units::day()) DEFINE_DERIVED_UNIT(julian_century, HNumber(100) * Units::julian_year()) DEFINE_DERIVED_UNIT(tropical_year, HNumber("365.242190402") * Units::day()) // Approx.: changes over time due to Earth's precession. DEFINE_DERIVED_UNIT(sidereal_year, HNumber("365.256363004") * Units::day()) // http://hpiers.obspm.fr/eop-pc/models/constants.html DEFINE_DERIVED_UNIT(karat, Rational(1,24).toHNumber()) // Do not confuse with carat above. DEFINE_DERIVED_UNIT(bar, HNumber("1e5") * Units::pascal()) DEFINE_DERIVED_UNIT(atmosphere, HNumber("1.01325") * Units::bar()) DEFINE_DERIVED_UNIT(torr, Units::atmosphere() / HNumber(760)) DEFINE_DERIVED_UNIT(pounds_per_sqinch, Units::pound() * Units::gravity() / (Units::inch()*Units::inch())) DEFINE_DERIVED_UNIT(calorie, HNumber("4.184") * Units::joule()) // International Table calorie. DEFINE_DERIVED_UNIT(british_thermal_unit, HNumber("1055.05585262") * Units::joule()) // International standard ISO 31-4 DEFINE_DERIVED_UNIT(quad, Units::peta() * Units::british_thermal_unit()) DEFINE_DERIVED_UNIT(nat, Units::bit() / HMath::ln(2)) DEFINE_DERIVED_UNIT(hartley, HMath::ln(10) * Units::nat()) DEFINE_DERIVED_UNIT(bit, Units::byte() / HNumber(8)) DEFINE_DERIVED_UNIT(gravity, HNumber("9.80665") * Units::newton() / Units::kilogram()) // 3rd CGPM (1901, CR 70). DEFINE_DERIVED_UNIT(speed_of_light, HNumber(299792458) * Units::metre() / Units::second()) DEFINE_DERIVED_UNIT(speed_of_sound_STP, HNumber(331) * Units::metre()/Units::second()) DEFINE_DERIVED_UNIT(knot, Units::nautical_mile()/Units::hour()) DEFINE_DERIVED_UNIT(mile_per_hour, HNumber("1609.344") * Units::metre() / Units::hour()) DEFINE_DERIVED_UNIT(kilometre_per_hour, Units::kilo() * Units::metre() / Units::hour()) DEFINE_DERIVED_UNIT(revolution_per_minute, Units::revolution() / Units::minute()) DEFINE_DERIVED_UNIT(horsepower, HNumber(550) * Units::foot() * Units::pound() * Units::gravity() / Units::second()) // Imperial horsepower. DEFINE_DERIVED_UNIT(kilowatt_hour, Units::kilo() * Units::watt() * Units::hour()) DEFINE_DERIVED_UNIT(millimetre_of_mercury, HNumber("133.322387415") * Units::pascal()) #define SI_PREFIX_CACHE(id, func, name, symbol, exponent) \ DEFINE_DERIVED_UNIT(func, s_powerOfTen(exponent)) SI_PREFIX_TABLE(SI_PREFIX_CACHE) #undef SI_PREFIX_CACHE #define BINARY_PREFIX_CACHE(id, func, name, symbol, exponent) \ DEFINE_DERIVED_UNIT(func, s_powerOfTwo(exponent)) BINARY_PREFIX_TABLE(BINARY_PREFIX_CACHE) #undef BINARY_PREFIX_CACHE #undef SI_PREFIX_TABLE #undef BINARY_PREFIX_TABLE heldercorreia-speedcrunch-e7ca37f/src/core/units.h000066400000000000000000000343231526573132500223740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef UNITS_H #define UNITS_H #include #include #include #include "math/quantity.h" #include "math/rational.h" class QString; class QStringView; class Rational; enum class UnitQuantity { Unspecified, Length, Time, Mass, ElectricCurrent, ThermodynamicTemperature, AmountOfSubstance, LuminousIntensity, Information, PlaneAngle, SolidAngle, Frequency, Force, Pressure, Stress, Energy, Work, AmountOfHeat, Power, RadiantFlux, ElectricCharge, ElectricPotentialDifference, Capacitance, ElectricResistance, ElectricConductance, MagneticFlux, MagneticFluxDensity, Inductance, CelsiusTemperature, LuminousFlux, Illuminance, ActivityReferredToARadionuclide, AbsorbedDose, Kerma, DoseEquivalent, CatalyticActivity, Area, Volume, Speed, Velocity, DimensionlessRatio }; enum class UnitId { Unknown, Second, Metre, Kilogram, Ampere, Kelvin, Mole, Candela, Radian, Steradian, Hertz, Newton, Pascal, Joule, Watt, Coulomb, Volt, Farad, Ohm, Siemens, Weber, Tesla, Henry, DegreeCelsius, Lumen, Lux, Becquerel, Gray, Sievert, Katal, CubicMetre, CubicMillimetre, CubicCentimetre, CubicDecimetre, CubicKilometre, SquareMillimetre, SquareKilometre, SquareMetre, Minute, Hour, Day, AstronomicalUnit, Degree, Arcminute, Arcsecond, Milliarcsecond, Microarcsecond, Hectare, Litre, Tonne, Dalton, Electronvolt, Acre, Angstrom, Atmosphere, AtomicMassUnit, Bar, Bit, BritishThermalUnit, Byte, Calorie, Carat, Cup, CupImp, CupJp, CupUs, DegreeFahrenheit, ElementaryCharge, Fathom, FluidOunceImp, FluidOunceUs, FluidDramImp, FluidDramUs, Foot, SquareFoot, CubicFoot, Furlong, GallonImp, GallonUs, GillImp, GillUs, Gradian, Grain, Gram, Hartley, HartreeEnergyUnit, Horsepower, Inch, SquareInch, CubicInch, Karat, Knot, Lightminute, Lightsecond, Lightyear, LongTon, Mile, SquareMile, CubicMile, MilePerHour, KilometrePerHour, Nat, NauticalMile, Ounce, Parsec, PartsPerBillion, PartsPerMillion, PintImp, PintUs, Pound, PoundsPerSqinch, QuartImp, QuartUs, BarrelOil, BarrelBeerUs, Rod, SquareYard, CubicYard, ShortTon, Stone, Tablespoon, TablespoonAu, TablespoonImp, TablespoonUs, DessertSpoon, Teaspoon, TeaspoonImp, TeaspoonUs, Torr, Turn, Revolution, RevolutionPerMinute, Week, KilowattHour, MillimetreOfMercury, Quad, Yard, CenturyJulian, YearJulian, YearSidereal, YearTropical }; enum class UnitPhraseId { NewtonMetre, WattSecond, VoltSquaredAmpere, JoulePerSquareMetre, JoulePerCubicMetre }; enum class PrefixId { Quecto, Ronto, Yocto, Zepto, Atto, Femto, Pico, Nano, Micro, Milli, Centi, Deci, Deca, Hecto, Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta, Ronna, Quetta, Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi, Robi, Quebi, Unknown }; using UnitDimension = QMap; QString unitQuantityDimensionKey(UnitQuantity quantity); bool unitQuantityFromDimensionKey(const QString& key, UnitQuantity* out); QString normalizeUnitName(const QString& name); UnitId unitId(const QString& normalizedName); QString unitName(UnitId id); const char* unitLocalizedName(UnitId id); QString unitLocalizedIdentifierName(const QString& identifier); bool isUnitLocalizedNameTranslatable(const QString& localizedName); QString unitSymbol(UnitId id); bool isPreferredCanonicalDisplayUnit(UnitId id); QStringView unitPhrase(UnitPhraseId key); PrefixId prefixId(const QString& normalizedName); QString prefixName(PrefixId id); QString prefixSymbol(PrefixId id); const QList& siPrefixIds(); const QList& binaryPrefixIds(); enum UnitPrefixPolicy { NoPrefixes = 0, // Decimal SI prefixes, powers of 1000. NegativeEngineeringSiPrefixes = 1 << 0, // m, µ, n, p, ... PositiveEngineeringSiPrefixes = 1 << 1, // k, M, G, T, ... // Decimal SI prefixes, non-engineering powers of 10. SmallNegativeSiPrefixes = 1 << 2, // d, c SmallPositiveSiPrefixes = 1 << 3, // da, h // IEC binary prefixes. BinaryIecPrefixes = 1 << 4 // Ki, Mi, Gi, Ti, ... }; constexpr int EngineeringSiPrefixes = NegativeEngineeringSiPrefixes | PositiveEngineeringSiPrefixes; constexpr int SmallSiPrefixes = SmallNegativeSiPrefixes | SmallPositiveSiPrefixes; constexpr int AllDecimalSiPrefixes = EngineeringSiPrefixes | SmallSiPrefixes; constexpr int AllPrefixes = AllDecimalSiPrefixes | BinaryIecPrefixes; struct UnitPrefixSpec { PrefixId id; QString longName; QString symbol; int power; Quantity value; }; const QList& siPrefixes(); const QList& binaryIecPrefixes(); int unitPrefixPolicy(UnitId id); bool unitPrefixPolicyAllows(int policy, const UnitPrefixSpec& prefix, bool binaryPrefix = false); QString unitSiPrefixBaseSymbol(UnitId id); CNumber unitSiPrefixBaseValue(UnitId id); struct Unit { QString name; Quantity value; Unit(QString name, Quantity value) : name(name) , value(value) { } Unit() : name("") , value(1) { } }; class Units { public: static QString angleModeUnitSymbol(char angleMode); static QString degreeAliasSymbol(); static QString arcminuteAliasSymbol(); static QString arcsecondAliasSymbol(); static QStringList affineUnitAliases(UnitId id); static void findUnit(Quantity& q); static const QHash& builtInUnitValues(); static QHash builtInUnitLookup(char angleMode); static bool isAffineUnitName(const QString& unitName); static bool tryConvertAffineToBase(const QString& unitName, const HNumber& value, HNumber* baseValueOut); static bool tryConvertAffineFromBase(const QString& unitName, const HNumber& baseValue, HNumber* valueOut); static bool isExplicitAngleUnitName(const QString& unitName); static bool tryConvertExplicitAngleToRadians(Quantity* angle); // Base SI units. static const Quantity metre(); static const Quantity second(); static const Quantity kilogram(); static const Quantity ampere(); static const Quantity mole(); static const Quantity kelvin(); static const Quantity candela(); // Base non-SI units. static const Quantity bit(); // SI prefixes. static const Quantity quecto(); static const Quantity ronto(); static const Quantity yocto(); static const Quantity zepto(); static const Quantity atto(); static const Quantity femto(); static const Quantity pico(); static const Quantity nano(); static const Quantity micro(); static const Quantity milli(); static const Quantity centi(); static const Quantity deci(); static const Quantity deca(); static const Quantity hecto(); static const Quantity kilo(); static const Quantity mega(); static const Quantity giga(); static const Quantity tera(); static const Quantity peta(); static const Quantity exa(); static const Quantity zetta(); static const Quantity yotta(); static const Quantity ronna(); static const Quantity quetta(); // Binary prefixes. static const Quantity kibi(); static const Quantity mebi(); static const Quantity gibi(); static const Quantity tebi(); static const Quantity pebi(); static const Quantity exbi(); static const Quantity zebi(); static const Quantity yobi(); static const Quantity robi(); static const Quantity quebi(); // Derived SI units. static const Quantity square_metre(); static const Quantity cubic_metre(); static const Quantity cubic_millimetre(); static const Quantity cubic_centimetre(); static const Quantity cubic_decimetre(); static const Quantity cubic_kilometre(); static const Quantity square_millimetre(); static const Quantity square_kilometre(); static const Quantity newton(); static const Quantity hertz(); static const Quantity radian(); static const Quantity degree(); static const Quantity gradian(); static const Quantity turn(); static const Quantity revolution(); static const Quantity arcminute(); static const Quantity arcsecond(); static const Quantity milliarcsecond(); static const Quantity microarcsecond(); static const Quantity steradian(); static const Quantity pascal(); static const Quantity joule(); static const Quantity watt(); static const Quantity coulomb(); static const Quantity volt(); static const Quantity farad(); static const Quantity ohm(); static const Quantity siemens(); static const Quantity weber(); static const Quantity tesla(); static const Quantity henry(); static const Quantity lumen(); static const Quantity lux(); static const Quantity becquerel(); static const Quantity gray(); static const Quantity sievert(); static const Quantity katal(); // Derived from SI units. // Mass. static const Quantity tonne(); static const Quantity short_ton(); static const Quantity long_ton(); static const Quantity pound(); static const Quantity ounce(); static const Quantity grain(); static const Quantity gram(); static const Quantity atomic_mass_unit(); static const Quantity carat(); // Distance/length. static const Quantity micron(); static const Quantity angstrom(); static const Quantity astronomical_unit(); static const Quantity lightyear(); static const Quantity lightsecond(); static const Quantity lightminute(); static const Quantity parsec(); // US measures. static const Quantity inch(); static const Quantity square_inch(); static const Quantity foot(); static const Quantity square_foot(); static const Quantity yard(); static const Quantity square_yard(); static const Quantity cubic_yard(); static const Quantity mile(); static const Quantity square_mile(); static const Quantity cubic_mile(); static const Quantity rod(); static const Quantity furlong(); // Nautical (US). static const Quantity fathom(); static const Quantity nautical_mile(); static const Quantity cable(); // Area. static const Quantity are(); static const Quantity hectare(); static const Quantity decare(); static const Quantity acre(); // Volume. static const Quantity gallon_us(); static const Quantity gallon_imp(); static const Quantity quart_us(); static const Quantity quart_imp(); static const Quantity pint_us(); static const Quantity pint_imp(); static const Quantity fluid_ounce_us(); static const Quantity fluid_ounce_imp(); static const Quantity fluid_dram_us(); static const Quantity fluid_dram_imp(); static const Quantity gill_us(); static const Quantity gill_imp(); static const Quantity barrel_oil(); static const Quantity barrel_beer_us(); static const Quantity cubic_inch(); static const Quantity cubic_foot(); static const Quantity litre(); // Time. static const Quantity minute(); static const Quantity hour(); static const Quantity day(); static const Quantity week(); static const Quantity century(); static const Quantity julian_century(); static const Quantity julian_year(); static const Quantity tropical_year(); static const Quantity sidereal_year(); // Concentration. static const Quantity percent(); static const Quantity ppm(); static const Quantity ppb(); static const Quantity karat(); // Pressure. static const Quantity bar(); static const Quantity atmosphere(); static const Quantity torr(); static const Quantity pounds_per_sqinch(); // Energy. static const Quantity electronvolt(); static const Quantity calorie(); static const Quantity british_thermal_unit(); // Information. static const Quantity nat(); static const Quantity hartley(); static const Quantity byte(); // Cooking. // Note: these again differ from US to UK, Australia, Japan, ... // Since for cooking generally not that high a precision is // required, let's just stick with the so called 'legal' variant. static const Quantity tablespoon(); static const Quantity tablespoon_au(); static const Quantity tablespoon_imp(); static const Quantity tablespoon_us(); static const Quantity teaspoon(); static const Quantity teaspoon_imp(); static const Quantity teaspoon_us(); static const Quantity cup(); static const Quantity cup_imp(); static const Quantity cup_jp(); static const Quantity cup_us(); // Various others. static const Quantity gravity(); static const Quantity speed_of_light(); static const Quantity elementary_charge(); static const Quantity speed_of_sound_STP(); static const Quantity knot(); static const Quantity mile_per_hour(); static const Quantity kilometre_per_hour(); static const Quantity revolution_per_minute(); static const Quantity horsepower(); static const Quantity kilowatt_hour(); static const Quantity millimetre_of_mercury(); static const Quantity stone(); static const Quantity dessert_spoon(); static const Quantity quad(); private: static void pushUnit(Quantity q, QString name); static void clearCache() { m_cache.clear(); } static QHash, Unit> m_matchLookup; static QMap m_cache; static void initTable(); }; #endif // UNITS_H heldercorreia-speedcrunch-e7ca37f/src/core/userdefinitions.cpp000066400000000000000000000047051526573132500250000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "core/userdefinitions.h" #include "core/settings.h" #include #include #include #include #include #include namespace { QString startupDefinitionsPath() { return Settings::getDataPath() + QStringLiteral("/definitions.json"); } } void UserDefinitions::loadInto(Settings* settings) { StartupDiagnostics::Scope timing("Load global definitions"); if (!settings) return; settings->startupUserDefinitions.clear(); QFile file(startupDefinitionsPath()); if (!file.exists() || !file.open(QIODevice::ReadOnly)) return; QJsonParseError parseError; const QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &parseError); if (parseError.error != QJsonParseError::NoError || !doc.isObject()) return; const QJsonObject json = doc.object(); QStringList definitionLines; const QJsonValue startupDefinitionsValue = json.value( QLatin1String(UserDefinitions::kStartupDefinitionsJsonKey)); if (startupDefinitionsValue.isArray()) { const QJsonArray definitionsArray = startupDefinitionsValue.toArray(); for (const QJsonValue& value : definitionsArray) { if (value.isString()) definitionLines.append(value.toString()); } } else if (startupDefinitionsValue.isString()) { // Accept legacy string format if present. definitionLines = startupDefinitionsValue.toString().split(QLatin1Char('\n')); } settings->startupUserDefinitions = definitionLines.join(QLatin1Char('\n')); } void UserDefinitions::saveFrom(const Settings* settings) { if (!settings) return; const QString path = startupDefinitionsPath(); QDir().mkpath(QFileInfo(path).absolutePath()); QFile file(path); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return; QJsonObject json; QJsonArray definitionsArray; const QStringList definitionLines = settings->startupUserDefinitions.split(QLatin1Char('\n')); for (const QString& line : definitionLines) { if (!line.trimmed().isEmpty()) definitionsArray.append(line); } json[QLatin1String(UserDefinitions::kStartupDefinitionsJsonKey)] = definitionsArray; file.write(QJsonDocument(json).toJson(QJsonDocument::Indented)); } heldercorreia-speedcrunch-e7ca37f/src/core/userdefinitions.h000066400000000000000000000014261526573132500244420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_USERDEFINITIONS_H #define CORE_USERDEFINITIONS_H /* { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/user-definitions.json", "title": "SpeedCrunch User Definitions", "type": "object", "required": ["startupDefinitions"], "additionalProperties": false, "properties": { "startupDefinitions": { "type": "array", "items": { "type": "string" } } } } */ class Settings; namespace UserDefinitions { inline constexpr const char* kStartupDefinitionsJsonKey = "startupDefinitions"; void loadInto(Settings* settings); void saveFrom(const Settings* settings); } #endif // CORE_USERDEFINITIONS_H heldercorreia-speedcrunch-e7ca37f/src/core/userfunction.cpp000066400000000000000000000127311526573132500243100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/userfunction.h" #include "core/evaluator.h" #include "core/opcode.h" #include "core/sessionjsonkeys.h" #include //#define SAVE_COMPILED_FORM UserFunction::UserFunction(const QJsonObject &json) : UserFunction() { if (json.contains(QLatin1String(SessionJsonKeys::Function::Id))) m_name = json[QLatin1String(SessionJsonKeys::Function::Id)].toString(); if (json.contains(QLatin1String(SessionJsonKeys::Function::Arguments))) { const QJsonArray args_json = json[QLatin1String(SessionJsonKeys::Function::Arguments)].toArray(); int n = json[QLatin1String(SessionJsonKeys::Function::Arguments)].toArray().size(); for(int i=0; i( codes_json[i].toObject()[QLatin1String(SessionJsonKeys::Function::Opcode::Type)].toInt()), codes_json[i].toObject()[QLatin1String(SessionJsonKeys::Function::Opcode::Index)].toInt()); if(codes_json[i].toObject().contains(QLatin1String(SessionJsonKeys::Function::Opcode::Text))) opcode.text = codes_json[i].toObject()[QLatin1String(SessionJsonKeys::Function::Opcode::Text)].toString(); opcodes.append(opcode); } const QJsonArray & const_json = json[QLatin1String(SessionJsonKeys::Function::Constants)].toArray(); for(int i=0; i #include #include #include "core/opcode.h" #include "math/quantity.h" class UserFunction { private: QString m_name; QStringList m_arguments; QString m_expression; QString m_interpretedExpression; QString m_description; public: QVector constants; QStringList identifiers; QVector opcodes; UserFunction(QString name, QStringList arguments, QString expression, QString description = QString(), QString interpretedExpression = QString()) : m_name(name) , m_arguments(arguments) , m_expression(expression) , m_interpretedExpression(interpretedExpression) , m_description(description) {} UserFunction() {} UserFunction(const QJsonObject & json); QString name() const; QStringList arguments() const; QString expression() const; QString interpretedExpression() const; QString description() const; void setName(const QString & str); void setArguments(const QStringList & args); void setExpression(const QString & expr); void setInterpretedExpression(const QString& expr); void setDescription(const QString & expr); void serialize(QJsonObject & json) const; void deSerialize(const QJsonObject & json); }; #endif // CORE_USERFUNCTION_H heldercorreia-speedcrunch-e7ca37f/src/core/userunit.cpp000066400000000000000000000022501526573132500234350ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/userunit.h" UserUnit::UserUnit(const QJsonObject& json) { deSerialize(json); } void UserUnit::serialize(QJsonObject& json) const { json[QStringLiteral("id")] = m_name; QJsonObject valueJson; m_value.serialize(valueJson); json[QStringLiteral("qty")] = valueJson; if (!m_expression.isEmpty()) json[QStringLiteral("xpr")] = m_expression; if (!m_interpretedExpression.isEmpty()) json[QStringLiteral("itp")] = m_interpretedExpression; if (!m_description.isEmpty()) json[QStringLiteral("dsc")] = m_description; } void UserUnit::deSerialize(const QJsonObject& json) { m_name = json[QStringLiteral("id")].toString(); if (json.contains(QStringLiteral("qty")) && json[QStringLiteral("qty")].isObject()) m_value = Quantity::deSerialize(json[QStringLiteral("qty")].toObject()); else m_value = Quantity(1); m_expression = json[QStringLiteral("xpr")].toString(); m_interpretedExpression = json[QStringLiteral("itp")].toString(); m_description = json[QStringLiteral("dsc")].toString(); } heldercorreia-speedcrunch-e7ca37f/src/core/userunit.h000066400000000000000000000031471526573132500231100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_USERUNIT_H #define CORE_USERUNIT_H #include "math/quantity.h" #include #include class UserUnit { public: UserUnit() {} UserUnit(const QString& name, const Quantity& value, const QString& expression = QString(), const QString& interpretedExpression = QString(), const QString& description = QString()) : m_name(name) , m_value(value) , m_expression(expression) , m_interpretedExpression(interpretedExpression) , m_description(description) { } UserUnit(const QJsonObject& json); QString name() const { return m_name; } Quantity value() const { return m_value; } QString expression() const { return m_expression; } QString interpretedExpression() const { return m_interpretedExpression; } QString description() const { return m_description; } void setName(const QString& value) { m_name = value; } void setValue(const Quantity& value) { m_value = value; } void setExpression(const QString& value) { m_expression = value; } void setInterpretedExpression(const QString& value) { m_interpretedExpression = value; } void setDescription(const QString& value) { m_description = value; } void serialize(QJsonObject& json) const; void deSerialize(const QJsonObject& json); private: QString m_name; Quantity m_value; QString m_expression; QString m_interpretedExpression; QString m_description; }; #endif // CORE_USERUNIT_H heldercorreia-speedcrunch-e7ca37f/src/core/variable.cpp000066400000000000000000000025541526573132500233530ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "variable.h" #include "sessionjsonkeys.h" Variable::Variable(const QJsonObject &json) { deSerialize(json); } void Variable::serialize(QJsonObject &json) const { json[QLatin1String(SessionJsonKeys::Variable::Id)] = m_identifier; QJsonObject value; m_value.serialize(value); json[QLatin1String(SessionJsonKeys::Variable::Quantity)] = value; if (!m_description.isEmpty()) json[QLatin1String(SessionJsonKeys::Variable::Description)] = m_description; if (!m_formattedValue.isEmpty()) json[QLatin1String(SessionJsonKeys::Variable::FormattedValue)] = m_formattedValue; } void Variable::deSerialize(const QJsonObject &json) { if (json.contains(QLatin1String(SessionJsonKeys::Variable::Id))) m_identifier = json[QLatin1String(SessionJsonKeys::Variable::Id)].toString(); m_type = (m_identifier == QStringLiteral("ans")) ? BuiltIn : UserDefined; if (json.contains(QLatin1String(SessionJsonKeys::Variable::Quantity))) m_value = Quantity(json[QLatin1String(SessionJsonKeys::Variable::Quantity)].toObject()); m_description = json[QLatin1String(SessionJsonKeys::Variable::Description)].toString(); m_formattedValue = json[QLatin1String(SessionJsonKeys::Variable::FormattedValue)].toString(); } heldercorreia-speedcrunch-e7ca37f/src/core/variable.h000066400000000000000000000035641526573132500230220ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef CORE_VARIABLE_H #define CORE_VARIABLE_H #include #include #include #include "math/quantity.h" class Variable { public: enum Type { BuiltIn, UserDefined }; private: QString m_identifier; Quantity m_value; Type m_type; QString m_description; QString m_formattedValue; public: Variable() : m_identifier(""), m_value(0), m_type(UserDefined), m_description("") {} Variable(const QJsonObject & json); Variable(const QString & id, const Quantity & val, Type t = UserDefined, const QString& description = QString()) : m_identifier(id), m_value(val), m_type(t), m_description(description) {} Variable(const Variable & other) : m_identifier(other.m_identifier), m_value(other.m_value), m_type(other.m_type), m_description(other.m_description), m_formattedValue(other.m_formattedValue) {} Variable& operator=(const Variable&) = default; Quantity value() const {return m_value;} QString identifier() const {return m_identifier;} Type type() const {return m_type;} QString description() const {return m_description;} QString formattedValue() const { return m_formattedValue; } void setValue(const Quantity & val) {m_value = val;} void set_identifier(const QString & str) {m_identifier = str;} void set_type(const Type t) {m_type = t;} void setDescription(const QString& description) {m_description = description;} void setFormattedValue(const QString& formattedValue) { m_formattedValue = formattedValue; } void serialize(QJsonObject & json) const; void deSerialize(const QJsonObject & json); bool operator==(const Variable& other) const { return m_identifier == other.m_identifier; } }; #endif // CORE_VARIABLE_H heldercorreia-speedcrunch-e7ca37f/src/gui/000077500000000000000000000000001526573132500207105ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/gui/aboutbox.cpp000066400000000000000000000124541526573132500232450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006, 2008-2010, 2013-2019, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/aboutbox.h" #include #include #include #include #include #include #define THANKS(name) #name"
    " AboutBox::AboutBox(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) { setObjectName("AboutBox"); setWindowTitle(tr("About SpeedCrunch")); QString msg = "
    "; msg += "
    "; msg += "SpeedCrunch " SPEEDCRUNCH_VERSION; #ifdef SPEEDCRUNCH_PORTABLE msg += " Portable"; #endif msg += "
    "; const QString osName = QSysInfo::prettyProductName() .remove(QLatin1Char('(')).remove(QLatin1Char(')')); msg += osName.toHtmlEscaped() + "
    "; msg += "Qt " + QLatin1String(QT_VERSION_STR) + "
    "; const QString authors = "

    %1
    %2"; msg += authors.arg(tr("Main author | Logo | Maintainer"), "Helder Correia"); msg += "

    " + QString("%1
    ").arg(tr("Core developers")); msg += THANKS(Felix Krull) THANKS(Hadrien Theveneau) THANKS(Pol Welter) THANKS(Teyut) ; msg += authors.arg(tr("Original author"), "Ariya Hidayat"); msg += authors.arg(tr("Math engine"), "Wolf Lammen"); msg += "

    " + QString("%1
    ").arg(tr("Thanks")); msg += THANKS(Alan Birtles) THANKS(Alan Davies) THANKS(Alejandro Villarreal) THANKS(Alessandro Portale) THANKS(Alexey Gorishny) THANKS(Alexey Kouznetsov) THANKS(Anders Lund) THANKS(Andreas Scherer) THANKS(Antonio Mannella) THANKS(Artem Golovinsky) THANKS(Aurélien Gâteau) THANKS(Bart Martens) THANKS(Benjamin Robin) THANKS(Bernhard Schiffner) THANKS(Brian Hale) THANKS(Christian Ehrlich) THANKS(Damir Perisa) THANKS(Daniel Schäufele) THANKS(@ddidderr) THANKS(Derek O'Connor) THANKS(D.J.L. Sales) THANKS(Enrico Rós) THANKS(Eugeniu Plamadeala) THANKS(F Chris Carrera) THANKS(Francesco di Cugno) THANKS(Francis Tseng) THANKS(@FrankMountainFace) THANKS(Gary Cramblitt) THANKS(Henrik Nordstrom) THANKS(Henrique Pinto) THANKS(James Yuzwalk) THANKS(Jean-Michel Frouin) THANKS(Jean-Remy Falleri) THANKS(@jetp250) THANKS(Johan Thelin) THANKS(Johannes Lange) THANKS(Jonathan Avraham) THANKS(Jonathan Riddell) THANKS(Lars Ivar Igesund) THANKS(l.inc) THANKS(Luigi Toscano) THANKS(Maciek Borowka) THANKS(Marco Wegner) THANKS(@Matth7878) THANKS(Matthew J Smith) THANKS(Matthias Prager) THANKS(Melchior Franz) THANKS(Michael Pyne) THANKS(Mikko Syrjä) THANKS(Mohamed Eldesoky) THANKS(Nelson Almeida) THANKS(@nfshr) THANKS(Nikolay Zlatev) THANKS(Noah Davis) THANKS(Oliver Gubler) THANKS(@pandora1986) THANKS(Pedro Montes Alcalde) THANKS(Petri Damstén) THANKS(Philippe Fremy) THANKS(Pieter Pareit) THANKS(@playerofgames) THANKS(@rafa4mat) THANKS(Rafael Fraga) THANKS(@RedNova84) THANKS(Roberto Alsina) THANKS(Rodrigo Pedra) THANKS(Roger Sachan) THANKS(Roland 'liquidat' Wolters) THANKS(@Sacryn) THANKS(Sarah Hobbs) THANKS(Sébastien Szymanski) THANKS(Stephan Binner) THANKS(Steven Honeyman) THANKS(Theodore R. Smith) THANKS(Thomas Luebking) THANKS(Thomas Nagy) THANKS(@tosione) THANKS(Vibet Alexis) THANKS(Vitaly Zaitsev) THANKS(Vladimir Pouzanov) THANKS(Wictor Lund) THANKS(Witold Wysota) THANKS(1100101) ; msg += "

    "; msg += "

    "; msg += tr("Copyright (C) 2004-2026 The SpeedCrunch developers"); msg += "

    "; msg += "

    "; msg += tr("This program is free software; you can redistribute it and/or " "modify it under the terms of the GNU General Public License " "as published by the Free Software Foundation; either version 2 " "of the License, or (at your option) any later version"); msg += "

    "; msg += "

    "; msg += tr("This program is distributed in the hope that it will be useful, " "but WITHOUT ANY WARRANTY; without even the implied warranty of " "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " "GNU General Public License for more details."); msg += "

    "; msg += "
    "; QTextEdit* textEdit = new QTextEdit(this); textEdit->setReadOnly(true); textEdit->setText(msg); QPushButton* closeButton = new QPushButton(this); closeButton->setText(tr("Close")); connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(close())); QGridLayout* mainLayout = new QGridLayout(this); mainLayout->addWidget(textEdit, 0, 0, 1, 2); mainLayout->addWidget(closeButton, 1, 1, 1, 1); mainLayout->setColumnStretch(0, 1); setWindowTitle(tr("About SpeedCrunch")); } heldercorreia-speedcrunch-e7ca37f/src/gui/aboutbox.h000066400000000000000000000006131526573132500227040ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2013-2014, 2021, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_ABOUTBOX_H #define GUI_ABOUTBOX_H #include class AboutBox : public QDialog { Q_OBJECT public: explicit AboutBox(QWidget *parent = 0, Qt::WindowFlags f = QFlag(0)); private: Q_DISABLE_COPY(AboutBox) }; #endif // GUI_ABOUTBOX_H heldercorreia-speedcrunch-e7ca37f/src/gui/bitfieldwidget.cpp000066400000000000000000000725701526573132500244150ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014-2017, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "bitfieldwidget.h" #include "core/mathdsl.h" #include "core/settings.h" #include "gui/menustyleutils.h" #include "gui/startupappearance.h" #include "gui/tooltipstyleutils.h" #include "gui/uiconfig.h" #include "math/quantity.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { QString bitFieldButtonStyleSheet(const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& pressedBackground, const QColor& pressedForeground) { return QStringLiteral( "QPushButton {" " border: none;" " border-radius: 5px;" " padding: 2px;" " background-color: %1;" " color: %2;" "}" "QPushButton:hover {" " border: none;" " background-color: %3;" " color: %4;" "}" "QPushButton:pressed {" " border: none;" " background-color: %5;" " color: %6;" "}") .arg(background.name(), foreground.name(), hoverBackground.name(), hoverForeground.name(), pressedBackground.name(), pressedForeground.name()); } } // namespace BitWidget::BitWidget(int bitPosition, QWidget* parent) : QLabel(parent), m_state(false) { HNumber number(HMath::raise(HNumber(2), bitPosition)); m_toolTipText = QString("2%1 = %2") .arg(bitPosition) .arg(HMath::format(number, Quantity::Format::Decimal())); setText(QString("%1").arg(bitPosition)); setObjectName("BitWidget"); setCursor(Qt::PointingHandCursor); setMouseTracking(true); setAttribute(Qt::WA_Hover, true); updateStyle(StyleUpdateReason::Theme); } void BitWidget::setState(bool state) { if (state != m_state) { m_state = state; setProperty("bitState", m_state); updateStyle(StyleUpdateReason::Interaction); update(); } } void BitWidget::updateStyle(StyleUpdateReason reason) { const QPalette palette = m_themeBackground.isValid() ? this->palette() : MenuStyle::systemPalette(this); const QColor background = m_themeBackground.isValid() ? m_themeBackground : palette.color(QPalette::Window); const QColor foreground = m_themeForeground.isValid() ? m_themeForeground : palette.color(QPalette::WindowText); const QColor hoverBackground = m_themeHoverBackground.isValid() ? m_themeHoverBackground : palette.color(QPalette::Button); const QColor hoverForeground = m_themeHoverForeground.isValid() ? m_themeHoverForeground : palette.color(QPalette::ButtonText); const QColor selectedBackground = m_themeSelectedBackground.isValid() ? m_themeSelectedBackground : palette.color(QPalette::Highlight); const QColor selectedForeground = m_themeSelectedForeground.isValid() ? m_themeSelectedForeground : palette.color(QPalette::HighlightedText); setProperty("bitState", m_state); setProperty("bitPressed", m_pressed); const QString style = QString("QLabel { background-color: %1; color: %2; }" "QLabel[bitState=\"true\"], QLabel[bitPressed=\"true\"] {" " background-color: %5; color: %6;" "}" "QLabel:hover { background-color: %3; color: %4; }" // Keep selected/pressed bits visually selected when they also match :hover. "QLabel[bitState=\"true\"]:hover, QLabel[bitPressed=\"true\"]:hover {" " background-color: %5; color: %6;" "}") .arg(background.name(), foreground.name(), hoverBackground.name(), hoverForeground.name(), selectedBackground.name(), selectedForeground.name()); if (styleSheet() != style) { StartupDiagnostics::setAppearanceStyleSheet(this, style); } else { StartupDiagnostics::appearanceAssignment(this, false, false, true); if (reason == StyleUpdateReason::Interaction) { // Property selectors must still update when a bit is selected or pressed. this->style()->unpolish(this); this->style()->polish(this); update(); } } } void BitWidget::setThemeColors(const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& selectedBackground, const QColor& selectedForeground) { if (background.isValid() && m_themeBackground == background && m_themeForeground == foreground && m_themeHoverBackground == hoverBackground && m_themeHoverForeground == hoverForeground && m_themeSelectedBackground == selectedBackground && m_themeSelectedForeground == selectedForeground) { return; } m_themeBackground = background; m_themeForeground = foreground; m_themeHoverBackground = hoverBackground; m_themeHoverForeground = hoverForeground; m_themeSelectedBackground = selectedBackground; m_themeSelectedForeground = selectedForeground; updateStyle(StyleUpdateReason::Theme); } void BitWidget::setToolTipThemeColors(const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius) { m_summaryPopupBackgroundColor = background; m_summaryPopupForegroundColor = foreground; m_summaryPopupOutlineColor = outline; m_summaryPopupCornerRadius = qMax(0, cornerRadius); applySummaryPopupTheme(); } void BitWidget::enterEvent(QEnterEvent* event) { QLabel::enterEvent(event); showSummaryPopup(event->globalPosition().toPoint()); } void BitWidget::leaveEvent(QEvent* event) { QLabel::leaveEvent(event); hideSummaryPopup(); } void BitWidget::mouseMoveEvent(QMouseEvent* event) { QLabel::mouseMoveEvent(event); showSummaryPopup(event->globalPosition().toPoint()); } void BitWidget::mousePressEvent(QMouseEvent*) { hideSummaryPopup(); m_pressed = true; updateStyle(StyleUpdateReason::Interaction); } void BitWidget::mouseReleaseEvent(QMouseEvent*) { m_pressed = false; setState(!m_state); emit stateChanged(m_state); } void BitWidget::applySummaryPopupTheme() { ToolTipStyleUtils::applyPopupTheme( m_summaryPopup, m_summaryPopupLabel, this, {m_summaryPopupBackgroundColor, m_summaryPopupForegroundColor, m_summaryPopupOutlineColor, m_summaryPopupCornerRadius}); } void BitWidget::ensureSummaryPopup() { if (m_summaryPopup != nullptr) return; m_summaryPopup = ToolTipStyleUtils::createPopup(this, QStringLiteral("bitSummaryPopup"), QStringLiteral("bitSummaryPopupLabel"), Qt::RichText, &m_summaryPopupLabel); applySummaryPopupTheme(); } void BitWidget::hideSummaryPopup() { if (m_summaryPopup != nullptr) m_summaryPopup->hide(); } void BitWidget::showSummaryPopup(const QPoint& globalPos) { if (m_toolTipText.isEmpty()) return; ensureSummaryPopup(); ToolTipStyleUtils::showPopup(m_summaryPopup, m_summaryPopupLabel, m_toolTipText, this, globalPos, m_summaryPopupCornerRadius); } void BitWidget::updateSummaryPopupMask() { if (m_summaryPopup == nullptr) return; ToolTipStyleUtils::applyRoundedPopupMask(m_summaryPopup, qMax(0, m_summaryPopupCornerRadius)); } BitFieldWidget::BitFieldWidget(QWidget* parent) : QWidget(parent) { setObjectName(QStringLiteral("BitFieldWidget")); setAutoFillBackground(true); setLayoutDirection(Qt::LeftToRight); refreshTheme(); m_bitWidgets.reserve(NumberOfBits); for (int i = 0; i < NumberOfBits; ++i) { BitWidget* bitWidget = new BitWidget(i, this); connect(bitWidget, SIGNAL(stateChanged(bool)), this, SLOT(onBitChanged())); m_bitWidgets.append(bitWidget); } m_byteLayouts.reserve(NumberOfBits / 8); for (int i = 0; i < NumberOfBits; i += 8) { QHBoxLayout* byteLayout(new QHBoxLayout); byteLayout->setSpacing(5); // Each byte is drawn over 3 UI elements (1 for each nibble and 1 for space) for (int nibble = 1 ; nibble >= 0 ; --nibble) { // Draw each nibble (4-bits) in a single box QHBoxLayout* nibbleLayout(new QHBoxLayout); // Disable items spacing so that it looks like a table nibbleLayout->setSpacing(0); for (int j = 3; j >= 0; --j) { const int bitIndex = i + (nibble * 4) + j; nibbleLayout->addWidget(m_bitWidgets.at(bitIndex)); } // Change the name of first bits so that the proper style is applied nibbleLayout->itemAt(0)->widget()->setObjectName("FirstBitWidget"); byteLayout->addLayout(nibbleLayout, Qt::AlignCenter); } // Draw the space between each byte QLabel* byteSpaceLabel = new QLabel; byteLayout->addWidget(byteSpaceLabel); m_byteLayouts.append(byteLayout); } m_resetButton = new QPushButton("0"); setupButton(m_resetButton); connect(m_resetButton, SIGNAL(clicked()), this, SLOT(resetBits())); m_invertButton = new QPushButton("~"); setupButton(m_invertButton); connect(m_invertButton, SIGNAL(clicked()), this, SLOT(invertBits())); m_shiftLeftButton = new QPushButton("<<"); setupButton(m_shiftLeftButton); connect(m_shiftLeftButton, SIGNAL(clicked()), this, SLOT(shiftBitsLeft())); m_shiftRightButton = new QPushButton(">>"); setupButton(m_shiftRightButton); connect(m_shiftRightButton, SIGNAL(clicked()), this, SLOT(shiftBitsRight())); m_buttonsLayout = new QGridLayout; m_buttonsLayout->addWidget(m_resetButton, 0, 0); m_buttonsLayout->addWidget(m_invertButton, 0, 1); m_buttonsLayout->addWidget(m_shiftLeftButton, 1, 0); m_buttonsLayout->addWidget(m_shiftRightButton, 1, 1); m_fieldLayout = new QGridLayout; m_mainLayout = new QHBoxLayout(this); m_mainLayout->addStretch(); m_mainLayout->addLayout(m_fieldLayout); m_mainLayout->addLayout(m_buttonsLayout); m_mainLayout->addStretch(); this->updateFieldLayout(); // The following needs to be done AFTER the widgets have been added to BitFieldWidget // as the style sheet will not be applied otherwise this->updateSize(); // Update the field layout again, because the widgets size has changed now this->updateFieldLayout(); } void BitFieldWidget::refreshTheme() { // Build the CSS border color using 50% opacity (same result as previous method with painting). const QPalette palette = m_themeBackground.isValid() ? this->palette() : MenuStyle::systemPalette(this); const QColor background = m_themeBackground.isValid() ? m_themeBackground : palette.color(QPalette::Window); const QColor foreground = m_themeForeground.isValid() ? m_themeForeground : palette.color(QPalette::WindowText); const QColor hoverBackground = m_themeHoverBackground.isValid() ? m_themeHoverBackground : palette.color(QPalette::Button); const QColor hoverForeground = m_themeHoverForeground.isValid() ? m_themeHoverForeground : palette.color(QPalette::ButtonText); const QColor pressedBackground = m_themePressedBackground.isValid() ? m_themePressedBackground : palette.color(QPalette::Highlight); const QColor pressedForeground = m_themePressedForeground.isValid() ? m_themePressedForeground : palette.color(QPalette::HighlightedText); const QColor buttonBackground = m_themeButtonBackground.isValid() ? m_themeButtonBackground : background; const QColor buttonForeground = m_themeButtonForeground.isValid() ? m_themeButtonForeground : foreground; const QColor buttonHoverBackground = m_themeButtonHoverBackground.isValid() ? m_themeButtonHoverBackground : hoverBackground; const QColor buttonHoverForeground = m_themeButtonHoverForeground.isValid() ? m_themeButtonHoverForeground : hoverForeground; const QColor buttonPressedBackground = m_themeButtonPressedBackground.isValid() ? m_themeButtonPressedBackground : pressedBackground; const QColor buttonPressedForeground = m_themeButtonPressedForeground.isValid() ? m_themeButtonPressedForeground : pressedForeground; const QColor borderColor = foreground; const QString cssBorderColor = QString("rgba(%1, %2, %3, %4)") .arg(borderColor.red()) .arg(borderColor.green()) .arg(borderColor.blue()) .arg(0.5); const QString style = QString("QWidget#BitFieldWidget {" " background-color: %1; color: %2;" "}" "QLabel#BitWidget, QLabel#FirstBitWidget {" " qproperty-alignment: 'AlignHCenter | AlignVCenter';" " border-top: 1px solid %3;" " border-bottom: 1px solid %3;" " border-right: 1px solid %3;" " padding: 1px;" " background-color : %1; color : %2;" "}" "QLabel#FirstBitWidget {" " border-left: 1px solid %3;" "}") .arg(background.name(), foreground.name(), cssBorderColor); if (styleSheet() != style) setStyleSheet(style); // Paint the container too, otherwise the parent window shows through. setAttribute(Qt::WA_StyledBackground, true); const QString buttonStyle = bitFieldButtonStyleSheet(buttonBackground, buttonForeground, buttonHoverBackground, buttonHoverForeground, buttonPressedBackground, buttonPressedForeground); for (QPushButton* button : {m_resetButton, m_invertButton, m_shiftLeftButton, m_shiftRightButton}) { if (button == nullptr) continue; if (Settings::instance()->dockAppearance == Settings::DockAppearanceSystem) { if (!button->styleSheet().isEmpty()) button->setStyleSheet(QString()); button->setPalette(MenuStyle::systemPalette(button)); continue; } QPalette buttonPalette = button->palette(); buttonPalette.setColor(QPalette::Button, buttonBackground); buttonPalette.setColor(QPalette::ButtonText, buttonForeground); buttonPalette.setColor(QPalette::Highlight, buttonHoverBackground); buttonPalette.setColor(QPalette::HighlightedText, buttonHoverForeground); button->setPalette(buttonPalette); if (button->styleSheet() != buttonStyle) button->setStyleSheet(buttonStyle); } const QColor selectedBackground = m_themeSelectedBackground.isValid() ? m_themeSelectedBackground : pressedBackground; const QColor selectedForeground = m_themeSelectedForeground.isValid() ? m_themeSelectedForeground : pressedForeground; for (BitWidget* bitWidget : m_bitWidgets) bitWidget->setThemeColors(background, foreground, hoverBackground, hoverForeground, selectedBackground, selectedForeground); for (BitWidget* bitWidget : m_bitWidgets) bitWidget->setToolTipThemeColors(m_summaryPopupBackgroundColor, m_summaryPopupForegroundColor, m_summaryPopupOutlineColor, m_summaryPopupCornerRadius); applyButtonSummaryPopupTheme(); } void BitFieldWidget::setThemeColors(const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& pressedBackground, const QColor& pressedForeground, const QColor& selectedBackground, const QColor& selectedForeground, const QColor& buttonBackground, const QColor& buttonForeground, const QColor& buttonHoverBackground, const QColor& buttonHoverForeground, const QColor& buttonPressedBackground, const QColor& buttonPressedForeground) { m_themeBackground = background; m_themeForeground = foreground; m_themeHoverBackground = hoverBackground; m_themeHoverForeground = hoverForeground; m_themePressedBackground = pressedBackground; m_themePressedForeground = pressedForeground; m_themeSelectedBackground = selectedBackground; m_themeSelectedForeground = selectedForeground; m_themeButtonBackground = buttonBackground; m_themeButtonForeground = buttonForeground; m_themeButtonHoverBackground = buttonHoverBackground; m_themeButtonHoverForeground = buttonHoverForeground; m_themeButtonPressedBackground = buttonPressedBackground; m_themeButtonPressedForeground = buttonPressedForeground; refreshTheme(); } void BitFieldWidget::setToolTipThemeColors(const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius) { m_summaryPopupBackgroundColor = background; m_summaryPopupForegroundColor = foreground; m_summaryPopupOutlineColor = outline; m_summaryPopupCornerRadius = qMax(0, cornerRadius); for (BitWidget* bitWidget : m_bitWidgets) bitWidget->setToolTipThemeColors(m_summaryPopupBackgroundColor, m_summaryPopupForegroundColor, m_summaryPopupOutlineColor, m_summaryPopupCornerRadius); applyButtonSummaryPopupTheme(); } QSize BitFieldWidget::minimumSizeHint() const { QSize hint = QWidget::minimumSizeHint(); const int byteHeight = m_byteLayouts.isEmpty() ? 0 : m_byteLayouts.first()->sizeHint().height(); const int controlsHeight = m_buttonsLayout ? m_buttonsLayout->sizeHint().height() : 0; const QMargins margins = contentsMargins() + m_mainLayout->contentsMargins(); hint.setHeight(qMax(byteHeight, controlsHeight) + margins.top() + margins.bottom()); return hint; } /** Update the bitfield layout based on the size of BitFieldWidget and its children. * This method should be called during initialization (but only after all the BitFieldWidget * members have been set) and every time the size of BitFieldWidget is changed. */ void BitFieldWidget::updateFieldLayout() { // Empty current field layout while (m_fieldLayout->count() > 0) { m_fieldLayout->removeItem(m_fieldLayout->itemAt(0)); } // Compute how much horizontal space we have to draw the bitfield int widgetWidth = this->size().width(); int buttonsWidth = m_buttonsLayout->sizeHint().width(); int byteWidgetWidth = m_byteLayouts.at(0)->sizeHint().width(); auto contentMargins = this->contentsMargins() + m_mainLayout->contentsMargins(); int spacesWidth = contentMargins.left() + contentMargins.right() + m_mainLayout->spacing() * 3; int availableWidth = widgetWidth - (buttonsWidth + spacesWidth); // Find out how much bytes per row can be shown within availableWidth int bytesPerRow = 1; if (byteWidgetWidth > 0 && byteWidgetWidth <= availableWidth) { // Make it a power of 2 so that only 8/16/32/64 bits per row are possible bytesPerRow = pow(2, floor(log2(availableWidth / byteWidgetWidth))); } // Populate the field layout int maxRows = NumberOfBits / (8 * bytesPerRow); for (int col = 0 ; col < bytesPerRow ; ++col) { const int colOffset = (bytesPerRow - col - 1); for (int row = 0 ; row < maxRows ; ++row) { int byteIndex = (maxRows - row - 1) * bytesPerRow + colOffset; auto* byteLayout = m_byteLayouts.at(byteIndex); m_fieldLayout->addLayout(byteLayout, row, col); } } // Update the minimum widget size so that its width can be reduced by the user if (byteWidgetWidth + buttonsWidth > 0) this->setMinimumWidth(byteWidgetWidth + buttonsWidth + spacesWidth); } /** Update the size of each BitWidget so that it is the same, as well as the size of the buttons. * This method should be called during initialization, and every time the UI font is changed. */ void BitFieldWidget::updateSize() { // Compute bit widgets max size and apply it to all bit widgets QSize maxSize(0, 0); for (auto& bitWidget : m_bitWidgets) { auto widgetSize = bitWidget->sizeHint(); if (maxSize.width() < widgetSize.width()) maxSize.setWidth(widgetSize.width()); if (maxSize.height() < widgetSize.height()) maxSize.setHeight(widgetSize.height()); } // Make the box be a square if (maxSize.width() < maxSize.height()) maxSize.setWidth(maxSize.height()); else maxSize.setHeight(maxSize.width()); // Apply maxSize to all bit widgets for (auto& widget : m_bitWidgets) widget->setFixedSize(maxSize); // TODO: find some more justifiable size calculation. int buttonHeight = maxSize.height() * 4 / 3; int buttonWidth = buttonHeight * 2; m_resetButton->setFixedSize(buttonWidth, buttonHeight); m_invertButton->setFixedSize(buttonWidth, buttonHeight); m_shiftLeftButton->setFixedSize(buttonWidth, buttonHeight); m_shiftRightButton->setFixedSize(buttonWidth, buttonHeight); } void BitFieldWidget::wheelEvent(QWheelEvent* we) { if (we->angleDelta().y() > 0) shiftBitsLeft(); else shiftBitsRight(); } void BitFieldWidget::resizeEvent(QResizeEvent*) { this->updateFieldLayout(); } bool BitFieldWidget::eventFilter(QObject* watched, QEvent* event) { const QString summaryText = buttonSummaryText(watched); if (!summaryText.isEmpty()) { QWidget* button = qobject_cast(watched); switch (event->type()) { case QEvent::Enter: if (button != nullptr) showButtonSummaryPopup(summaryText, button, button->mapToGlobal(button->rect().center())); break; case QEvent::MouseMove: { QMouseEvent* mouseEvent = static_cast(event); showButtonSummaryPopup(summaryText, button, mouseEvent->globalPosition().toPoint()); break; } case QEvent::HoverMove: { QHoverEvent* hoverEvent = static_cast(event); if (button != nullptr) showButtonSummaryPopup(summaryText, button, button->mapToGlobal(hoverEvent->position().toPoint())); break; } case QEvent::Hide: case QEvent::KeyPress: case QEvent::Leave: case QEvent::MouseButtonPress: case QEvent::Wheel: hideButtonSummaryPopup(); break; default: break; } } return QWidget::eventFilter(watched, event); } void BitFieldWidget::setupButton(QPushButton* button) { button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); button->setCursor(Qt::PointingHandCursor); button->setMouseTracking(true); button->setAttribute(Qt::WA_Hover, true); button->setToolTip(QString()); button->installEventFilter(this); } QString BitFieldWidget::buttonSummaryText(const QObject* watched) const { if (watched == m_resetButton) return tr("Reset bits to zero"); if (watched == m_invertButton) return tr("Invert bits"); if (watched == m_shiftLeftButton) return tr("Shift bits left"); if (watched == m_shiftRightButton) return tr("Shift bits right"); return QString(); } void BitFieldWidget::applyButtonSummaryPopupTheme() { ToolTipStyleUtils::applyPopupTheme( m_buttonSummaryPopup, m_buttonSummaryPopupLabel, this, {m_summaryPopupBackgroundColor, m_summaryPopupForegroundColor, m_summaryPopupOutlineColor, m_summaryPopupCornerRadius}); } void BitFieldWidget::ensureButtonSummaryPopup() { if (m_buttonSummaryPopup != nullptr) return; m_buttonSummaryPopup = ToolTipStyleUtils::createPopup( this, QStringLiteral("bitfieldButtonSummaryPopup"), QStringLiteral("bitfieldButtonSummaryPopupLabel"), Qt::PlainText, &m_buttonSummaryPopupLabel); applyButtonSummaryPopupTheme(); } void BitFieldWidget::hideButtonSummaryPopup() { if (m_buttonSummaryPopup != nullptr) m_buttonSummaryPopup->hide(); } void BitFieldWidget::showButtonSummaryPopup(const QString& text, QWidget* anchor, const QPoint& globalPos) { if (text.isEmpty() || anchor == nullptr) return; ensureButtonSummaryPopup(); ToolTipStyleUtils::showPopup(m_buttonSummaryPopup, m_buttonSummaryPopupLabel, text, anchor, globalPos, m_summaryPopupCornerRadius); } void BitFieldWidget::updateButtonSummaryPopupMask() { if (m_buttonSummaryPopup == nullptr) return; ToolTipStyleUtils::applyRoundedPopupMask(m_buttonSummaryPopup, qMax(0, m_summaryPopupCornerRadius)); } void BitFieldWidget::updateBits(const Quantity& number) { // Create a binary copy of number // (simply converting it to binary will not work if its base is defined) Quantity binNumber(number); binNumber.setFormat(Quantity::Format::Fixed() + Quantity::Format::Binary() + Quantity(number).format()); QString binaryNumberString = DMath::format(binNumber); QListIterator bitsIterator(m_bitWidgets); if (number.isZero() || !number.isInteger()) binaryNumberString.clear(); else if (number.isNegative()) binaryNumberString.remove(0, 3); // Remove '-0b'. else binaryNumberString.remove(0, 2); // Remove '0b'. auto iterator = binaryNumberString.end(); while (bitsIterator.hasNext()) { if (iterator != binaryNumberString.begin()) { --iterator; bitsIterator.next()->setState(*iterator == '1'); } else bitsIterator.next()->setState(false); } } void BitFieldWidget::onBitChanged() { QListIterator bitsIterator(m_bitWidgets); QString expression; while (bitsIterator.hasNext()) expression.prepend(bitsIterator.next()->state() ? "1" : "0"); QRegularExpression leadingZerosPattern(QString("^0{,%1}").arg(NumberOfBits - 1)); expression.remove(leadingZerosPattern); expression.prepend(MathDsl::BinPrefix); emit bitsChanged(expression); } void BitFieldWidget::invertBits() { foreach (BitWidget* w, m_bitWidgets) w->setState(!w->state()); onBitChanged(); } void BitFieldWidget::clear() { for (auto& w : m_bitWidgets) w->setState(false); } void BitFieldWidget::resetBits() { clear(); onBitChanged(); } void BitFieldWidget::shiftBitsLeft() { auto it = m_bitWidgets.constEnd(); auto itBegin = m_bitWidgets.constBegin(); --it; while (it != itBegin) { (*it)->setState((*(it-1))->state()); --it; } (*itBegin)->setState(false); onBitChanged(); } void BitFieldWidget::shiftBitsRight() { auto it = m_bitWidgets.constBegin(); auto itEnd = m_bitWidgets.constEnd(); --itEnd; while (it != itEnd) { (*it)->setState((*(it+1))->state()); it++; } (*itEnd)->setState(false); onBitChanged(); } heldercorreia-speedcrunch-e7ca37f/src/gui/bitfieldwidget.h000066400000000000000000000132341526573132500240520ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef BITFIELDWIDGET_H #define BITFIELDWIDGET_H #include #include #include class Quantity; class QEnterEvent; class QFrame; class QPushButton; class QGridLayout; class QHBoxLayout; class BitWidget : public QLabel { Q_OBJECT public: explicit BitWidget(int apos, QWidget* parent = 0); bool state() const { return m_state; } void setState(bool state); void setThemeColors(const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& selectedBackground, const QColor& selectedForeground); void setToolTipThemeColors(const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius); signals: void stateChanged(bool); protected: void enterEvent(QEnterEvent*) override; void leaveEvent(QEvent*) override; void mouseMoveEvent(QMouseEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseReleaseEvent(QMouseEvent*) override; private: enum class StyleUpdateReason { Theme, Interaction }; void applySummaryPopupTheme(); void ensureSummaryPopup(); void hideSummaryPopup(); void showSummaryPopup(const QPoint& globalPos); void updateSummaryPopupMask(); void updateStyle(StyleUpdateReason reason); enum { // TODO: have this scale with screen DPI SizePixels = 20, }; Q_DISABLE_COPY(BitWidget) bool m_state; bool m_pressed = false; QString m_toolTipText; QFrame* m_summaryPopup = nullptr; QLabel* m_summaryPopupLabel = nullptr; QColor m_summaryPopupBackgroundColor; QColor m_summaryPopupForegroundColor; QColor m_summaryPopupOutlineColor; int m_summaryPopupCornerRadius = 0; QColor m_themeBackground; QColor m_themeForeground; QColor m_themeHoverBackground; QColor m_themeHoverForeground; QColor m_themeSelectedBackground; QColor m_themeSelectedForeground; }; class BitFieldWidget : public QWidget { Q_OBJECT public: explicit BitFieldWidget(QWidget* parent = 0); QSize minimumSizeHint() const override; signals: void bitsChanged(const QString&); protected: bool eventFilter(QObject* watched, QEvent* event) override; void wheelEvent(QWheelEvent*) override; void resizeEvent(QResizeEvent*) override; public slots: void clear(); void updateBits(const Quantity&); void updateSize(); void updateFieldLayout(); void setThemeColors(const QColor& background, const QColor& foreground, const QColor& hoverBackground = QColor(), const QColor& hoverForeground = QColor(), const QColor& pressedBackground = QColor(), const QColor& pressedForeground = QColor(), const QColor& selectedBackground = QColor(), const QColor& selectedForeground = QColor(), const QColor& buttonBackground = QColor(), const QColor& buttonForeground = QColor(), const QColor& buttonHoverBackground = QColor(), const QColor& buttonHoverForeground = QColor(), const QColor& buttonPressedBackground = QColor(), const QColor& buttonPressedForeground = QColor()); void setToolTipThemeColors(const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius); void refreshTheme(); private slots: void onBitChanged(); void invertBits(); void shiftBitsLeft(); void shiftBitsRight(); void resetBits(); private: void applyButtonSummaryPopupTheme(); QString buttonSummaryText(const QObject* watched) const; void ensureButtonSummaryPopup(); void hideButtonSummaryPopup(); void setupButton(QPushButton* button); void showButtonSummaryPopup(const QString& text, QWidget* anchor, const QPoint& globalPos); void updateButtonSummaryPopupMask(); enum { NumberOfBits = 64 }; Q_DISABLE_COPY(BitFieldWidget) QList m_bitWidgets; QList m_byteLayouts; QGridLayout* m_fieldLayout; QGridLayout* m_buttonsLayout; QHBoxLayout* m_mainLayout; QPushButton* m_resetButton = nullptr; QPushButton* m_invertButton = nullptr; QPushButton* m_shiftLeftButton = nullptr; QPushButton* m_shiftRightButton = nullptr; QFrame* m_buttonSummaryPopup = nullptr; QLabel* m_buttonSummaryPopupLabel = nullptr; QColor m_themeBackground; QColor m_themeForeground; QColor m_themeHoverBackground; QColor m_themeHoverForeground; QColor m_themePressedBackground; QColor m_themePressedForeground; QColor m_themeSelectedBackground; QColor m_themeSelectedForeground; QColor m_themeButtonBackground; QColor m_themeButtonForeground; QColor m_themeButtonHoverBackground; QColor m_themeButtonHoverForeground; QColor m_themeButtonPressedBackground; QColor m_themeButtonPressedForeground; QColor m_summaryPopupBackgroundColor; QColor m_summaryPopupForegroundColor; QColor m_summaryPopupOutlineColor; int m_summaryPopupCornerRadius = 0; }; #endif // BITFIELDWIDGET_H heldercorreia-speedcrunch-e7ca37f/src/gui/bookdock.cpp000066400000000000000000000204001526573132500232030ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2008-2015, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/bookdock.h" #include "core/book.h" #include "core/evaluator.h" #include "core/settings.h" #include "core/mathdsl.h" #include "gui/editorutils.h" #include "gui/menustyleutils.h" #include "gui/oklchutils.h" #include #include #include #include #include #include #include namespace { QString toSuperscriptDigits(const QString& text) { QString out; out.reserve(text.size()); for (const QChar ch : text) { const QChar superscript = MathDsl::asciiDigitToSuperscript(ch); out += superscript.isNull() ? ch : superscript; } return out; } QString formatFormulaForEditorInsertion(const QString& text) { QString formatted = text; // Convert exponent forms such as ^2 or ^(12) to superscripts. static const QRegularExpression s_powerPattern( QStringLiteral(R"(\^(?:\(([0-9]+)\)|([0-9]+)))")); int offset = 0; auto it = s_powerPattern.globalMatch(formatted); while (it.hasNext()) { const auto match = it.next(); const QString exponentDigits = match.captured(1).isEmpty() ? match.captured(2) : match.captured(1); const QString superscript = toSuperscriptDigits(exponentDigits); const int start = match.capturedStart(0) + offset; const int length = match.capturedLength(0); formatted.replace(start, length, superscript); offset += superscript.size() - length; } // Use regular spaces around the main binary operators. const QString ms(MathDsl::AddWrap); const QString replacement = ms + QStringLiteral("\\1") + ms; static const QRegularExpression s_binaryOps( QStringLiteral(R"(\s*([=+\-−·×/*])\s*)")); formatted.replace(s_binaryOps, replacement); return formatted; } } // namespace void TextBrowser::changeEvent(QEvent* event) { QTextBrowser::changeEvent(event); if (event->type() == QEvent::PaletteChange || event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::StyleChange) { emit paletteStyleChanged(); } } BookDock::BookDock(QWidget* parent) : DockWidget(parent) , m_book(new Book(this)) { QWidget* widget = new QWidget(this); QVBoxLayout* bookLayout = new QVBoxLayout; bookLayout->setContentsMargins(0, 0, 0, 0); bookLayout->setSpacing(0); m_browser = new TextBrowser(this); m_browser->setFrameShape(QFrame::NoFrame); m_browser->setLineWrapMode(QTextEdit::NoWrap); m_browser->setOpenLinks(false); m_browser->setOpenExternalLinks(false); m_browser->setAutoFillBackground(true); updatePaletteStyle(); connect(m_browser, SIGNAL(anchorClicked(const QUrl&)), SLOT(handleAnchorClick(const QUrl&))); connect(m_browser, SIGNAL(paletteStyleChanged()), SLOT(schedulePaletteStyleRefresh())); bookLayout->addWidget(m_browser); widget->setLayout(bookLayout); setWidget(widget); retranslateText(); openPage(QUrl("index")); } void BookDock::setContentSurfaceColors(const QColor& background, const QColor& foreground) { if (m_contentBackground == background && m_contentForeground == foreground) return; m_contentBackground = background; m_contentForeground = foreground; schedulePaletteStyleRefresh(); } void BookDock::handleAnchorClick(const QUrl& url) { if (url.toString().startsWith("formula:")) { #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) QString expression = url.toString(QUrl::DecodeReserved).mid(8); #else QString expression = url.toString().mid(8); #endif expression = EditorUtils::normalizeExpressionOperatorsForEditorInput(expression); Evaluator* evaluator = Evaluator::instance(); evaluator->setExpression(expression); if (evaluator->isValid()) { const QString interpreted = evaluator->interpretedExpression(); if (!interpreted.isEmpty()) expression = Evaluator::formatInterpretedExpressionForDisplay(interpreted, evaluator); } expression.replace(MathDsl::MulCrossOp, MathDsl::MulDotOp); expression = formatFormulaForEditorInsertion(expression); emit expressionSelected(expression); } else openPage(url); } void BookDock::openPage(const QUrl& url) { const QString page = url.toString().isEmpty() ? QStringLiteral("index") : url.toString(); const QString content = m_book->getPageContent(page); if (!content.isNull()) { m_pageContent = content; refreshCurrentPage(); } m_currentPage = page; } void BookDock::retranslateText() { setWindowTitle(tr("Formula Book")); const QString content = m_book->getCurrentPageContent(); if (!content.isNull()) { m_pageContent = content; refreshCurrentPage(); } } void BookDock::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { retranslateText(); } else if (event->type() == QEvent::PaletteChange || event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::StyleChange) { schedulePaletteStyleRefresh(); } else { QDockWidget::changeEvent(event); } } QString BookDock::currentPage() const { return m_currentPage.isEmpty() ? QStringLiteral("index") : m_currentPage; } void BookDock::schedulePaletteStyleRefresh() { if (m_refreshingPaletteStyle || m_paletteStyleRefreshPending) return; // Parent polishing sends several palette and style events in one pass. // Render the current page once after those changes settle. m_paletteStyleRefreshPending = true; QTimer::singleShot(0, this, [this]() { m_paletteStyleRefreshPending = false; refreshCurrentPage(); }); } void BookDock::refreshCurrentPage() { if (m_refreshingPaletteStyle) return; QScopedValueRollback refreshing(m_refreshingPaletteStyle, true); updatePaletteStyle(); if (m_pageContent.isNull()) return; const QString styledContent = applyPaletteStyle(m_pageContent); if (styledContent == m_styledContent) return; m_styledContent = styledContent; m_browser->setHtml(styledContent); } QString BookDock::applyPaletteStyle(const QString& content) const { const QPalette palette = m_browser->palette(); const QColor background = palette.color(QPalette::Base); const QColor foreground = palette.color(QPalette::Text); const bool system = Settings::instance()->dockAppearance == Settings::DockAppearanceSystem; const QColor formulaLink = system ? palette.color(QPalette::Link) : aaForegroundForBackground(background, palette.color(QPalette::Link)); const QColor sectionLink = system ? formulaLink : generateSecondaryLinkFromBackground(background, formulaLink); const QString sectionLinkName = sectionLink.isValid() ? sectionLink.name() : foreground.name(); QString styledContent = content; styledContent.replace(QStringLiteral("background-color: #ffffff;"), QStringLiteral("background-color: %1;").arg(background.name())); styledContent.replace(QStringLiteral("color: #000000;"), QStringLiteral("color: %1;").arg(foreground.name())); styledContent.replace(QStringLiteral("color: #555;"), QStringLiteral("color: %1;").arg(sectionLinkName)); styledContent.replace(QStringLiteral("color: SteelBlue;"), QStringLiteral("color: %1;").arg(formulaLink.name())); return styledContent; } void BookDock::updatePaletteStyle() { QPalette palette = Settings::instance()->dockAppearance == Settings::DockAppearanceSystem ? MenuStyle::systemPalette(m_browser) : this->palette(); palette.setColor(QPalette::Base, m_contentBackground.isValid() ? m_contentBackground : palette.color(QPalette::Window)); palette.setColor(QPalette::Text, m_contentForeground.isValid() ? m_contentForeground : palette.color(QPalette::WindowText)); m_browser->setPalette(palette); m_browser->viewport()->setPalette(palette); } heldercorreia-speedcrunch-e7ca37f/src/gui/bookdock.h000066400000000000000000000027531526573132500226630ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2008-2010, 2013-2014, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_BOOKDOCK_H #define GUI_BOOKDOCK_H #include "core/book.h" #include "gui/dockwidget.h" #include #include class QUrl; class TextBrowser : public QTextBrowser { Q_OBJECT public: TextBrowser(QWidget* parent) : QTextBrowser(parent) { } signals: void paletteStyleChanged(); public slots: void setSource(const QUrl&) { } protected: void changeEvent(QEvent*) override; }; class BookDock : public DockWidget { Q_OBJECT public: BookDock(QWidget* parent = 0); void setContentSurfaceColors(const QColor& background, const QColor& foreground); signals: void expressionSelected(const QString&); public slots: void openPage(const QUrl&); void retranslateText(); QString currentPage() const; protected: void changeEvent(QEvent*) override; private slots: void handleAnchorClick(const QUrl&); void schedulePaletteStyleRefresh(); void refreshCurrentPage(); private: QString applyPaletteStyle(const QString& content) const; void updatePaletteStyle(); Q_DISABLE_COPY(BookDock) Book* m_book; TextBrowser* m_browser; QString m_currentPage; QString m_pageContent; QString m_styledContent; QColor m_contentBackground; QColor m_contentForeground; bool m_refreshingPaletteStyle = false; bool m_paletteStyleRefreshPending = false; }; #endif // GUI_BOOKDOCK_H heldercorreia-speedcrunch-e7ca37f/src/gui/constantbrowserutils.h000066400000000000000000000037151526573132500254050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_CONSTANTBROWSERUTILS_H #define GUI_CONSTANTBROWSERUTILS_H #include "core/constants.h" #include "core/mathdsl.h" #include "core/unicodechars.h" #include namespace ConstantBrowserUtils { inline QString unit(const Constant& constant) { QString result = constant.unit; result.replace(UnicodeChars::MiddleDot, MathDsl::MulDotOp); return result; } inline QString expression(const Constant& constant) { if (constant.domainType == ConstantDomain::Mathematics && constant.unit.isEmpty()) { if (constant.value == QStringLiteral("3.14159265358979323846264338327950288419716939937511")) return QString(UnicodeChars::Pi); if (constant.value == QStringLiteral("2.71828182845904523536028747135266249775724709369996")) return QStringLiteral("e"); } return constant.unit.isEmpty() ? constant.value : QStringLiteral("%1%2[%3]").arg(constant.value, QString(MathDsl::QuantSp), unit(constant)); } inline bool matches(const Constant& constant, const QString& term, const QString& domain = {}, const QString& subdomain = {}) { return (domain.isEmpty() || constant.domain == domain) && (subdomain.isEmpty() || constant.subdomain == subdomain) && (constant.name.contains(term, Qt::CaseInsensitive) || unit(constant).contains(term, Qt::CaseInsensitive)); } inline void moveSelection(QTreeWidget* list, int key) { const int count = list->topLevelItemCount(); if (count == 0) return; const int current = list->indexOfTopLevelItem(list->currentItem()); const int next = current < 0 ? (key == Qt::Key_Up ? count - 1 : 0) : qBound(0, current + (key == Qt::Key_Up ? -1 : 1), count - 1); list->setCurrentItem(list->topLevelItem(next)); list->scrollToItem(list->currentItem()); } } // namespace ConstantBrowserUtils #endif heldercorreia-speedcrunch-e7ca37f/src/gui/constantswidget.cpp000066400000000000000000000615161526573132500246450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2011, 2014, 2016, 2021, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/constantswidget.h" #include "gui/constantbrowserutils.h" #include "core/constants.h" #include "core/settings.h" #include "core/startupdiagnostics.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include "gui/dockliststyle.h" #include "gui/themedlineedit.h" #include "gui/tooltipstyleutils.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static QString displayValue(const Constant& constant) { if (constant.domainType != ConstantDomain::Mathematics) return constant.value; const int dotPos = constant.value.indexOf(MathDsl::DotSep); if (dotPos < 0) return constant.value; return constant.value.left(qMin(constant.value.length(), dotPos + 16)); } static bool hasLineBreak(const QString& text) { return text.contains(QLatin1Char('\n')) || text.contains(QLatin1Char('\r')) || text.contains(QChar::LineSeparator) || text.contains(QChar::ParagraphSeparator); } ConstantsWidget::ConstantsWidget(QWidget* parent, const InitialState& state) : QWidget(parent) { constexpr int kControlRowHorizontalPadding = 8; m_domainLabel = new QLabel(this); m_domain = new QComboBox(this); m_domain->setEditable(false); m_domain->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); m_subdomainLabel = new QLabel(this); m_subdomain = new QComboBox(this); m_subdomain->setEditable(false); m_subdomain->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); connect(m_domain, SIGNAL(activated(int)), SLOT(handleDomainChanged())); connect(m_subdomain, SIGNAL(activated(int)), SLOT(filter())); m_domainBox = new QWidget(this); m_domainLayout = new QGridLayout; m_domainBox->setLayout(m_domainLayout); m_domainLayout->setContentsMargins(kControlRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding, kControlRowHorizontalPadding, 0); m_domainLayout->setSpacing(6); m_label = new QLabel(this); m_filter = new ThemedLineEdit(this); m_filter->setMinimumWidth(fontMetrics().horizontalAdvance('X') * 10); m_filter->setClearButtonEnabled(true); connect(m_filter, SIGNAL(textChanged(const QString &)), SLOT(triggerFilter())); QWidget* searchBox = new QWidget(this); QHBoxLayout* searchLayout = new QHBoxLayout; searchBox->setLayout(searchLayout); searchLayout->setSpacing(6); searchLayout->addWidget(m_label); searchLayout->addWidget(m_filter); searchLayout->setContentsMargins(kControlRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding, kControlRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding); m_list = new QTreeWidget(this); m_list->setAutoScroll(true); m_list->setSizeAdjustPolicy(QAbstractScrollArea::AdjustIgnored); m_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_list->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_list->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_list->setColumnCount(3); m_list->setRootIsDecorated(false); m_list->setMouseTracking(true); m_list->viewport()->setMouseTracking(true); m_list->viewport()->setAttribute(Qt::WA_Hover, true); m_list->setEditTriggers(QTreeWidget::NoEditTriggers); m_list->setSelectionBehavior(QTreeWidget::SelectRows); m_list->header()->setStretchLastSection(false); DockListStyle::apply(m_list); m_list->installEventFilter(this); m_list->viewport()->installEventFilter(this); connect(m_list->verticalScrollBar(), &QScrollBar::valueChanged, this, &ConstantsWidget::hideSummaryPopup); connect(m_list->horizontalScrollBar(), &QScrollBar::valueChanged, this, &ConstantsWidget::hideSummaryPopup); connect(m_list, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(handleItem(QTreeWidgetItem*))); QShortcut* returnShortcut = new QShortcut(QKeySequence(Qt::Key_Return), this); returnShortcut->setContext(Qt::WidgetWithChildrenShortcut); const auto activateCurrent = [this]() { if (m_filterTimer->isActive()) filter(); if (QTreeWidgetItem* current = m_list->currentItem()) handleItem(current); }; connect(returnShortcut, &QShortcut::activated, this, activateCurrent); QShortcut* enterShortcut = new QShortcut(QKeySequence(Qt::Key_Enter), this); enterShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(enterShortcut, &QShortcut::activated, this, activateCurrent); QVBoxLayout* layout = new QVBoxLayout; setLayout(layout); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(m_domainBox); layout->addWidget(searchBox); layout->addWidget(m_list); m_filterTimer = new QTimer(this); m_filterTimer->setInterval(500); m_filterTimer->setSingleShot(true); connect(m_filterTimer, SIGNAL(timeout()), SLOT(filter())); m_noMatchLabel = new QLabel(this); m_noMatchLabel->setAlignment(Qt::AlignCenter); m_noMatchLabel->adjustSize(); m_noMatchLabel->hide(); translateControls(ListUpdate::DeferPopulation); updateDomainLayout(); QWidget::setTabOrder(m_filter, m_list); setFocusProxy(m_filter); restoreState(state.domain, state.subdomain, state.searchText); m_filter->installEventFilter(this); } ConstantsWidget::~ConstantsWidget() { m_filterTimer->stop(); hideSummaryPopup(); } QSize ConstantsWidget::minimumSizeHint() const { QSize hint = QWidget::minimumSizeHint(); hint.setWidth(UiConfig::ConstantsDockMinimumWidth); return hint; } QString ConstantsWidget::selectedDomain() const { return m_domain->currentText(); } QString ConstantsWidget::selectedSubdomain() const { return m_subdomain->currentText(); } QString ConstantsWidget::searchText() const { return m_filter->text(); } void ConstantsWidget::restoreState(const QString& domain, const QString& subdomain, const QString& searchText) { StartupDiagnostics::AppearanceContext context("Restore constants dock filters"); const QSignalBlocker searchBlocker(m_filter); if (!searchText.isNull()) m_filter->setText(searchText); if (!domain.isEmpty()) { const int domainIndex = m_domain->findText(domain); if (domainIndex >= 0) m_domain->setCurrentIndex(domainIndex); } refreshSubdomains(); if (!subdomain.isEmpty()) { const int subdomainIndex = m_subdomain->findText(subdomain); if (subdomainIndex >= 0) m_subdomain->setCurrentIndex(subdomainIndex); } filter(); } void ConstantsWidget::setSummaryPopupThemeColors(const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius) { m_summaryPopupBackgroundColor = background; m_summaryPopupForegroundColor = foreground; m_summaryPopupOutlineColor = outline; m_summaryPopupCornerRadius = qMax(0, cornerRadius); applySummaryPopupTheme(); } void ConstantsWidget::handleRadixCharacterChange() { StartupDiagnostics::AppearanceContext context("Constants dock radix change"); updateList(); } void ConstantsWidget::retranslateText() { translateControls(ListUpdate::Populate); } void ConstantsWidget::translateControls(ListUpdate mode) { m_domainLabel->setText(tr("Domain")); m_subdomainLabel->setText(tr("Subdomain")); m_label->setText(tr("Search")); m_noMatchLabel->setText(tr("No match found")); QStringList titles; const QString name = tr("Name"); const QString value = tr("Value"); const QString unit = tr("Unit"); if (layoutDirection() == Qt::LeftToRight) titles << name << value << unit; else titles << name << unit << value; m_list->setHeaderLabels(titles); updateDomainLabelAlignment(); refreshList(mode); } void ConstantsWidget::filter() { const QList &clist = Constants::instance()->list(); const char radixChar = Settings::instance()->radixCharacter(); const QString term = m_filter->text(); m_filterTimer->stop(); const QString chosenDomain = m_domain->currentText(); const QString chosenSubdomain = m_subdomain->currentText(); const QString all = tr("All"); const bool rightToLeft = layoutDirection() == Qt::RightToLeft; // Compare the translated content itself, including fallback translations. QStringList inputs {all, chosenDomain, chosenSubdomain, term, QString(QChar::fromLatin1(radixChar)), QString::number(layoutDirection())}; inputs.reserve(inputs.size() + clist.size() * 6); for (const Constant& constant : clist) { inputs << constant.name << constant.domain << constant.subdomain << constant.value << constant.unit << QString::number(int(constant.domainType)); } const bool unchanged = inputs == m_populatedInputs; StartupDiagnostics::AppearanceScope timing(unchanged ? "Skip unchanged constants dock list" : "Populate constants dock list", this); if (unchanged) return; setUpdatesEnabled(false); hideSummaryPopup(); { StartupDiagnostics::AppearanceScope phase("Clear constants dock rows", this); m_list->clear(); } struct PreparedRow { const Constant* constant; QStringList text; }; QList rows; bool uniformRowHeights = true; { StartupDiagnostics::AppearanceScope phase("Filter and format constants dock rows", this); rows.reserve(clist.size()); for (const Constant& constant : clist) { if (!ConstantBrowserUtils::matches(constant, term, chosenDomain == all ? QString() : chosenDomain, chosenSubdomain == all ? QString() : chosenSubdomain)) { continue; } const QString value = displayValue(constant); const QString radCh = (radixChar != MathDsl::DotSep) ? QString(value).replace(MathDsl::DotSep, radixChar) : value; const QString normalizedUnit = ConstantBrowserUtils::unit(constant); QStringList str {constant.name}; if (rightToLeft) str << normalizedUnit + UnicodeChars::LeftToRightMark << radCh; else str << radCh << normalizedUnit; // Keep variable heights if a translation introduces multiple lines. if (uniformRowHeights) uniformRowHeights = std::none_of(str.cbegin(), str.cend(), hasLineBreak); rows.append({&constant, std::move(str)}); } } { StartupDiagnostics::AppearanceScope phase("Create constants dock rows and tooltips", this); // Single-line rows share a font and have no icons or per-item size hints. // Reuse their height during layout without changing content-based widths. m_list->setUniformRowHeights(uniformRowHeights); for (const auto& row : rows) { const Constant& constant = *row.constant; QTreeWidgetItem* item = new QTreeWidgetItem(m_list, row.text); item->setData(0, Qt::UserRole, ConstantBrowserUtils::expression(constant)); QString tip; tip += QString(UnicodeChars::LeftToRightMark); tip += QString("%1
    %2") .arg(constant.name, constant.value); tip += QString(UnicodeChars::LeftToRightMark); if (!constant.unit.isEmpty()) tip.append(" ").append(QString(constant.unit).replace( UnicodeChars::MiddleDot, MathDsl::MulDotOp)); if (radixChar != MathDsl::DotSep) tip.replace(MathDsl::DotSep, radixChar); tip += QString(UnicodeChars::LeftToRightMark); item->setToolTip(0, tip); item->setToolTip(1, tip); item->setToolTip(2, tip); if (rightToLeft) { item->setTextAlignment(1, Qt::AlignRight); item->setTextAlignment(2, Qt::AlignLeft); } else { item->setTextAlignment(1, Qt::AlignLeft); item->setTextAlignment(2, Qt::AlignLeft); } } } const bool hasMatches = m_list->topLevelItemCount() > 0; m_columnsNeedResize = true; if (m_list->isVisible()) resizeColumnsToContents(); if (hasMatches) { m_noMatchLabel->hide(); StartupDiagnostics::AppearanceScope phase("Sort constants dock rows", this); m_list->sortItems(0, Qt::AscendingOrder); m_list->setCurrentItem(m_list->topLevelItem(0)); } else { updateEmptyHeaderStretch(); scheduleEmptyHeaderStretch(); DockListStyle::showCenteredNoMatchLabel(m_list, m_noMatchLabel); } m_populatedInputs = std::move(inputs); setUpdatesEnabled(true); } void ConstantsWidget::handleItem(QTreeWidgetItem* item) { emit constantSelected(item->data(0, Qt::UserRole).toString()); } void ConstantsWidget::triggerFilter() { m_filterTimer->stop(); m_filterTimer->start(); } void ConstantsWidget::updateList() { refreshList(ListUpdate::Populate); } void ConstantsWidget::refreshList(ListUpdate mode) { const int chosenDomainIndex = m_domain->currentIndex(); const QString chosenDomain = m_domain->currentText(); const int chosenSubdomainIndex = m_subdomain->currentIndex(); const QString chosenSubdomain = m_subdomain->currentText(); m_domain->clear(); Constants::instance()->retranslateText(); m_domain->addItems(Constants::instance()->domains()); m_domain->insertItem(0, tr("All")); int domainIndex = m_domain->findText(chosenDomain); if (domainIndex < 0 && chosenDomainIndex >= 0 && chosenDomainIndex < m_domain->count()) { domainIndex = chosenDomainIndex; } if (domainIndex < 0) { const QString defaultDomain = Constants::instance()->domains().value(0); domainIndex = m_domain->findText(defaultDomain); } if (domainIndex < 0) domainIndex = 0; m_domain->setCurrentIndex(domainIndex); refreshSubdomains(); int subdomainIndex = m_subdomain->findText(chosenSubdomain); if (subdomainIndex < 0 && chosenSubdomainIndex >= 0 && chosenSubdomainIndex < m_subdomain->count()) { subdomainIndex = chosenSubdomainIndex; } if (subdomainIndex >= 0) m_subdomain->setCurrentIndex(subdomainIndex); if (mode == ListUpdate::Populate) filter(); } void ConstantsWidget::handleDomainChanged() { StartupDiagnostics::AppearanceContext context("Constants dock domain change"); refreshSubdomains(); filter(); } void ConstantsWidget::refreshSubdomains() { m_subdomain->clear(); const QString chosenDomain = m_domain->currentText(); if (chosenDomain == tr("All")) { m_subdomain->insertItem(0, tr("All")); m_subdomain->setCurrentIndex(0); m_subdomainLabel->setVisible(true); m_subdomain->setVisible(true); updateDomainLayout(); return; } const QStringList subdomains = Constants::instance()->subdomains(chosenDomain); m_subdomain->addItems(subdomains); m_subdomain->insertItem(0, tr("All")); m_subdomain->setCurrentIndex(0); const bool hasConfiguredSubdomains = !subdomains.isEmpty(); m_subdomainLabel->setVisible(hasConfiguredSubdomains); m_subdomain->setVisible(hasConfiguredSubdomains); updateDomainLayout(); } void ConstantsWidget::changeEvent(QEvent* e) { if (e->type() == QEvent::LanguageChange) { StartupDiagnostics::AppearanceContext context("Constants dock LanguageChange"); retranslateText(); } else { QWidget::changeEvent(e); if (e->type() == QEvent::LayoutDirectionChange) retranslateText(); if (e->type() == QEvent::FontChange) QTimer::singleShot(0, this, [this]() { updateDomainLayout(); }); } } bool ConstantsWidget::eventFilter(QObject* watched, QEvent* event) { if (watched == m_filter && event->type() == QEvent::KeyPress) { const int key = static_cast(event)->key(); if (key == Qt::Key_Up || key == Qt::Key_Down) { if (m_filterTimer->isActive()) filter(); ConstantBrowserUtils::moveSelection(m_list, key); return true; } } if (watched == m_list && event->type() == QEvent::Show && m_columnsNeedResize) resizeColumnsToContents(); if (watched == m_list || watched == m_list->viewport()) { switch (event->type()) { case QEvent::ToolTip: { QHelpEvent* helpEvent = static_cast(event); const QPoint viewportPos = watched == m_list->viewport() ? helpEvent->pos() : m_list->viewport()->mapFrom(m_list, helpEvent->pos()); updateSummaryPopupForViewportPosition(viewportPos, helpEvent->globalPos()); return true; } case QEvent::MouseMove: { QMouseEvent* mouseEvent = static_cast(event); const QPoint viewportPos = watched == m_list->viewport() ? mouseEvent->pos() : m_list->viewport()->mapFrom(m_list, mouseEvent->pos()); updateSummaryPopupForViewportPosition(viewportPos, mouseEvent->globalPosition().toPoint()); break; } case QEvent::HoverMove: { QHoverEvent* hoverEvent = static_cast(event); const QPoint viewportPos = watched == m_list->viewport() ? hoverEvent->position().toPoint() : m_list->viewport()->mapFrom(m_list, hoverEvent->position().toPoint()); updateSummaryPopupForViewportPosition(viewportPos, m_list->viewport()->mapToGlobal(viewportPos)); break; } case QEvent::Hide: case QEvent::KeyPress: case QEvent::Leave: case QEvent::MouseButtonDblClick: case QEvent::MouseButtonPress: case QEvent::Resize: case QEvent::Wheel: hideSummaryPopup(); break; default: break; } } return QWidget::eventFilter(watched, event); } void ConstantsWidget::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); updateDomainLayout(); updateEmptyHeaderStretch(); scheduleEmptyHeaderStretch(); } void ConstantsWidget::ensureSummaryPopup() { if (m_summaryPopup != nullptr) return; m_summaryPopup = ToolTipStyleUtils::createPopup( this, QStringLiteral("constantsSummaryPopup"), QStringLiteral("constantsSummaryPopupLabel"), Qt::RichText, &m_summaryPopupLabel); applySummaryPopupTheme(); } void ConstantsWidget::applySummaryPopupTheme() { ToolTipStyleUtils::applyPopupTheme( m_summaryPopup, m_summaryPopupLabel, this, {m_summaryPopupBackgroundColor, m_summaryPopupForegroundColor, m_summaryPopupOutlineColor, m_summaryPopupCornerRadius}); } void ConstantsWidget::hideSummaryPopup() { if (m_summaryPopup != nullptr) m_summaryPopup->hide(); } void ConstantsWidget::showSummaryPopup(QTreeWidgetItem* item, int column, const QPoint& globalPos) { if (item == nullptr) return; const QString tip = item->toolTip(column).isEmpty() ? item->toolTip(0) : item->toolTip(column); if (tip.isEmpty()) { hideSummaryPopup(); return; } ensureSummaryPopup(); ToolTipStyleUtils::showPopup(m_summaryPopup, m_summaryPopupLabel, tip, m_list, globalPos, m_summaryPopupCornerRadius); } void ConstantsWidget::updateSummaryPopupForViewportPosition(const QPoint& viewportPos, const QPoint& globalPos) { // QTreeView can return the first row for positions above the viewport. if (!m_list->viewport()->rect().contains(viewportPos)) { hideSummaryPopup(); return; } const QModelIndex index = m_list->indexAt(viewportPos); QTreeWidgetItem* item = index.isValid() ? m_list->itemAt(viewportPos) : nullptr; if (item == nullptr) { hideSummaryPopup(); return; } showSummaryPopup(item, index.column(), globalPos); } void ConstantsWidget::updateSummaryPopupMask() { if (m_summaryPopup == nullptr) return; ToolTipStyleUtils::applyRoundedPopupMask(m_summaryPopup, qMax(0, m_summaryPopupCornerRadius)); } void ConstantsWidget::scheduleEmptyHeaderStretch() { if (m_emptyHeaderStretchQueued || m_list == nullptr || m_list->topLevelItemCount() > 0) { return; } m_emptyHeaderStretchQueued = true; QTimer::singleShot(0, this, [this]() { m_emptyHeaderStretchQueued = false; updateEmptyHeaderStretch(); }); } void ConstantsWidget::updateEmptyHeaderStretch() { if (m_list == nullptr || m_list->topLevelItemCount() > 0) return; QHeaderView* header = m_list->header(); if (header == nullptr || header->count() < 3) return; const int fixedWidth = header->sectionSize(0) + header->sectionSize(1); const int targetWidth = qMax(header->width(), m_list->viewport()->width()); if (targetWidth <= fixedWidth) return; header->resizeSection(2, qMax(header->sectionSizeHint(2), targetWidth - fixedWidth)); } void ConstantsWidget::resizeColumnsToContents() { StartupDiagnostics::AppearanceScope phase("Size constants dock columns", this); m_columnsNeedResize = false; m_list->header()->setStretchLastSection(false); m_list->header()->setSectionResizeMode(2, QHeaderView::Interactive); for (int column = 0; column < m_list->columnCount(); ++column) m_list->resizeColumnToContents(column); updateEmptyHeaderStretch(); } void ConstantsWidget::updateDomainLayout() { const int minInlineWidthByControls = m_domainLabel->sizeHint().width() + m_domain->minimumSizeHint().width() + m_subdomainLabel->sizeHint().width() + m_subdomain->minimumSizeHint().width() + (m_domainLayout->spacing() * 3); // Side docks are often still wide enough to satisfy minimum hints while visually cramped. // Use both control hints and a practical width cap so right/left panes stack reliably. const int practicalInlineWidth = 560; const int availableWidth = m_domainBox->width() > 0 ? m_domainBox->width() : width(); const bool compact = availableWidth < std::max(minInlineWidthByControls, practicalInlineWidth); m_domainLayout->setColumnStretch(3, compact || m_subdomain->isHidden() ? 0 : 1); if (m_domainLayoutInitialized && compact == m_isCompactDomainLayout) { updateDomainLabelAlignment(); return; } m_domainLayoutInitialized = true; m_isCompactDomainLayout = compact; while (QLayoutItem* item = m_domainLayout->takeAt(0)) delete item; m_domainLayout->setColumnStretch(1, 1); m_domainLayout->addWidget(m_domainLabel, 0, 0); m_domainLayout->addWidget(m_domain, 0, 1); m_domainLayout->addWidget(m_subdomainLabel, compact ? 1 : 0, compact ? 0 : 2); m_domainLayout->addWidget(m_subdomain, compact ? 1 : 0, compact ? 1 : 3); updateDomainLabelAlignment(); } void ConstantsWidget::updateDomainLabelAlignment() { if (m_isCompactDomainLayout) { const int labelWidth = std::max({m_domainLabel->sizeHint().width(), m_subdomainLabel->sizeHint().width(), m_label->sizeHint().width()}); m_domainLabel->setFixedWidth(labelWidth); m_subdomainLabel->setFixedWidth(labelWidth); m_label->setFixedWidth(labelWidth); } else { const int labelWidth = std::max(m_domainLabel->sizeHint().width(), m_label->sizeHint().width()); m_domainLabel->setFixedWidth(labelWidth); m_label->setFixedWidth(labelWidth); m_subdomainLabel->setMinimumWidth(0); m_subdomainLabel->setMaximumWidth(QWIDGETSIZE_MAX); } } heldercorreia-speedcrunch-e7ca37f/src/gui/constantswidget.h000066400000000000000000000062101526573132500243000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2011, 2013-2014, 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_CONSTANTSWIDGET_H #define GUI_CONSTANTSWIDGET_H #include #include #include class QSize; class QComboBox; class QEvent; class QFrame; class QGridLayout; class QLabel; class QLineEdit; class QPoint; class QResizeEvent; class QTimer; class QTreeWidget; class QTreeWidgetItem; class ConstantsWidget : public QWidget { Q_OBJECT public: struct InitialState { QString domain; QString subdomain; QString searchText; }; explicit ConstantsWidget(QWidget* parent = nullptr, const InitialState& state = {}); ~ConstantsWidget(); QSize minimumSizeHint() const override; QString selectedDomain() const; QString selectedSubdomain() const; QString searchText() const; void restoreState(const QString& domain, const QString& subdomain, const QString& searchText); void setSummaryPopupThemeColors(const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius); signals: void constantSelected(const QString&); public slots: void handleRadixCharacterChange(); protected slots: void filter(); void handleDomainChanged(); void handleItem(QTreeWidgetItem*); void refreshSubdomains(); void retranslateText(); void triggerFilter(); void updateList(); protected: void changeEvent(QEvent*) override; bool eventFilter(QObject* watched, QEvent* event) override; void resizeEvent(QResizeEvent* event) override; private: enum class ListUpdate { DeferPopulation, Populate }; void translateControls(ListUpdate mode); void refreshList(ListUpdate mode); void applySummaryPopupTheme(); void ensureSummaryPopup(); void hideSummaryPopup(); void scheduleEmptyHeaderStretch(); void showSummaryPopup(QTreeWidgetItem* item, int column, const QPoint& globalPos); void updateSummaryPopupForViewportPosition(const QPoint& viewportPos, const QPoint& globalPos); void updateSummaryPopupMask(); void updateEmptyHeaderStretch(); void resizeColumnsToContents(); void updateDomainLayout(); void updateDomainLabelAlignment(); Q_DISABLE_COPY(ConstantsWidget) QComboBox* m_domain; QLabel* m_domainLabel; QComboBox* m_subdomain; QLabel* m_subdomainLabel; QLineEdit* m_filter; QTimer* m_filterTimer; QLabel* m_label; QTreeWidget* m_list; QLabel* m_noMatchLabel; QWidget* m_domainBox; QGridLayout* m_domainLayout; QFrame* m_summaryPopup = nullptr; QLabel* m_summaryPopupLabel = nullptr; QColor m_summaryPopupBackgroundColor; QColor m_summaryPopupForegroundColor; QColor m_summaryPopupOutlineColor; int m_summaryPopupCornerRadius = 0; bool m_isCompactDomainLayout = false; bool m_domainLayoutInitialized = false; bool m_emptyHeaderStretchQueued = false; bool m_columnsNeedResize = false; QStringList m_populatedInputs; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/customkeypaddialog.cpp000066400000000000000000000270501526573132500253100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/customkeypaddialog.h" #include "gui/keypad.h" #include #include #include #include #include #include #include #include #include #include #include namespace { const int ColumnIndexRow = 0; const int ColumnIndexColumn = 1; const int ColumnIndexLabel = 2; const int ColumnIndexAction = 3; const int ColumnIndexText = 4; const int TableColumns = 5; QString actionText(Settings::CustomKeypadButtonAction action) { switch (action) { case Settings::CustomKeypadActionBackspace: return QObject::tr("Backspace"); case Settings::CustomKeypadActionClearExpression: return QObject::tr("Clear expression"); case Settings::CustomKeypadActionEvaluateExpression: return QObject::tr("Evaluate expression"); case Settings::CustomKeypadActionInsertText: default: return QObject::tr("Insert text"); } } Settings::CustomKeypad presetKeypad(int layout) { Settings::CustomKeypad keypad; Keypad::LayoutMode layoutMode = Keypad::LayoutModeBasicWide; if (layout == 1) layoutMode = Keypad::LayoutModeScientificWide; else if (layout == 2) layoutMode = Keypad::LayoutModeScientificNarrow; const QList presetButtons = Keypad::presetCustomButtons( layoutMode, Settings::instance()->radixCharacter(), &keypad.rows, &keypad.columns); for (const auto& presetButton : presetButtons) { Settings::CustomKeypadButton button; button.row = presetButton.row; button.column = presetButton.column; button.label = presetButton.label; button.text = presetButton.text; button.action = static_cast(presetButton.action); keypad.buttons.append(button); } return keypad; } } CustomKeypadDialog::CustomKeypadDialog(const Settings::CustomKeypad& keypad, QWidget* parent) : QDialog(parent) , m_rowsSpin(new QSpinBox(this)) , m_columnsSpin(new QSpinBox(this)) , m_table(new QTableWidget(this)) , m_currentRows(1) , m_currentColumns(1) { setWindowTitle(tr("Custom Keypad")); resize(860, 520); m_rowsSpin->setRange(1, 20); m_columnsSpin->setRange(1, 20); const int initialRows = qBound(1, keypad.rows, 20); const int initialColumns = qBound(1, keypad.columns, 20); m_currentRows = initialRows; m_currentColumns = initialColumns; m_rowsSpin->setValue(initialRows); m_columnsSpin->setValue(initialColumns); m_cells = QList(initialRows * initialColumns); for (const auto& button : keypad.buttons) { if (button.row < 0 || button.row >= initialRows || button.column < 0 || button.column >= initialColumns) continue; const int index = cellIndex(button.row, button.column); m_cells[index].label = button.label; m_cells[index].text = button.text; m_cells[index].action = button.action; } QGridLayout* topControlsLayout = new QGridLayout; topControlsLayout->addWidget(new QLabel(tr("Rows:"), this), 0, 0); topControlsLayout->addWidget(m_rowsSpin, 0, 1); topControlsLayout->addWidget(new QLabel(tr("Columns:"), this), 0, 2); topControlsLayout->addWidget(m_columnsSpin, 0, 3); topControlsLayout->addWidget(new QLabel(tr("Copy preset:"), this), 0, 4); QComboBox* presetCombo = new QComboBox(this); presetCombo->addItem(tr("Basic"), PresetLayoutBasicWide); presetCombo->addItem(tr("Scientific (wide)"), PresetLayoutScientificWide); presetCombo->addItem(tr("Scientific (narrow)"), PresetLayoutScientificNarrow); topControlsLayout->addWidget(presetCombo, 0, 5); auto* presetApplyButton = new QPushButton(tr("Apply"), this); topControlsLayout->addWidget(presetApplyButton, 0, 6); topControlsLayout->setColumnStretch(7, 1); m_table->setColumnCount(TableColumns); m_table->setAlternatingRowColors(true); m_table->setSelectionBehavior(QAbstractItemView::SelectRows); m_table->setSelectionMode(QAbstractItemView::SingleSelection); m_table->verticalHeader()->setVisible(false); m_table->horizontalHeader()->setStretchLastSection(true); QStringList labels; labels << tr("Row") << tr("Column") << tr("Label") << tr("Behavior") << tr("Text"); m_table->setHorizontalHeaderLabels(labels); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(m_rowsSpin, qOverload(&QSpinBox::valueChanged), this, [this](int value) { rebuildCellStorage(value, m_columnsSpin->value()); }); connect(m_columnsSpin, qOverload(&QSpinBox::valueChanged), this, [this](int value) { rebuildCellStorage(m_rowsSpin->value(), value); }); connect(presetApplyButton, &QPushButton::clicked, this, [this, presetCombo]() { applyPresetLayout(static_cast(presetCombo->currentData().toInt())); }); QVBoxLayout* rootLayout = new QVBoxLayout(this); rootLayout->addLayout(topControlsLayout); rootLayout->addWidget(m_table); rootLayout->addWidget(buttons); buildTableFromCells(); } Settings::CustomKeypad CustomKeypadDialog::customKeypad() const { Settings::CustomKeypad keypad; keypad.rows = m_rowsSpin->value(); keypad.columns = m_columnsSpin->value(); const QList cells = readCellsFromTable(); for (int row = 0; row < keypad.rows; ++row) { for (int column = 0; column < keypad.columns; ++column) { const Cell& cell = cells.at(cellIndex(row, column)); if (cell.label.isEmpty() && cell.text.isEmpty() && cell.action == Settings::CustomKeypadActionInsertText) continue; Settings::CustomKeypadButton button; button.row = row; button.column = column; button.label = cell.label; button.text = cell.text; button.action = cell.action; keypad.buttons.append(button); } } return keypad; } int CustomKeypadDialog::cellIndex(int row, int column) const { return row * m_currentColumns + column; } void CustomKeypadDialog::buildTableFromCells() { const int rows = m_rowsSpin->value(); const int columns = m_columnsSpin->value(); const int entries = rows * columns; m_table->setRowCount(entries); for (int row = 0; row < rows; ++row) { for (int column = 0; column < columns; ++column) { const int index = row * columns + column; const Cell& cell = m_cells.at(index); auto* rowItem = new QTableWidgetItem(QString::number(row + 1)); rowItem->setFlags(rowItem->flags() & ~Qt::ItemIsEditable); m_table->setItem(index, ColumnIndexRow, rowItem); auto* columnItem = new QTableWidgetItem(QString::number(column + 1)); columnItem->setFlags(columnItem->flags() & ~Qt::ItemIsEditable); m_table->setItem(index, ColumnIndexColumn, columnItem); m_table->setItem(index, ColumnIndexLabel, new QTableWidgetItem(cell.label)); QComboBox* actionCombo = new QComboBox(m_table); actionCombo->addItem(actionText(Settings::CustomKeypadActionInsertText), Settings::CustomKeypadActionInsertText); actionCombo->addItem(actionText(Settings::CustomKeypadActionBackspace), Settings::CustomKeypadActionBackspace); actionCombo->addItem(actionText(Settings::CustomKeypadActionClearExpression), Settings::CustomKeypadActionClearExpression); actionCombo->addItem(actionText(Settings::CustomKeypadActionEvaluateExpression), Settings::CustomKeypadActionEvaluateExpression); const int comboIndex = actionCombo->findData(cell.action); actionCombo->setCurrentIndex(comboIndex >= 0 ? comboIndex : 0); m_table->setCellWidget(index, ColumnIndexAction, actionCombo); auto* textItem = new QTableWidgetItem(cell.text); if (cell.action != Settings::CustomKeypadActionInsertText) textItem->setFlags(textItem->flags() & ~Qt::ItemIsEditable); m_table->setItem(index, ColumnIndexText, textItem); connect(actionCombo, qOverload(&QComboBox::currentIndexChanged), this, [this, index, actionCombo]() { QTableWidgetItem* textItem = m_table->item(index, ColumnIndexText); if (!textItem) return; const auto action = static_cast(actionCombo->currentData().toInt()); Qt::ItemFlags flags = textItem->flags(); if (action == Settings::CustomKeypadActionInsertText) flags |= Qt::ItemIsEditable; else flags &= ~Qt::ItemIsEditable; textItem->setFlags(flags); }); } } m_table->resizeColumnsToContents(); } void CustomKeypadDialog::rebuildCellStorage(int rows, int columns) { const QList oldCells = readCellsFromTable(); const int oldRows = m_currentRows; const int oldColumns = m_currentColumns; QList newCells(rows * columns); const int copyRows = qMin(rows, oldRows); const int copyColumns = qMin(columns, oldColumns); for (int row = 0; row < copyRows; ++row) { for (int column = 0; column < copyColumns; ++column) newCells[row * columns + column] = oldCells.at(row * oldColumns + column); } m_cells = newCells; m_currentRows = rows; m_currentColumns = columns; buildTableFromCells(); } void CustomKeypadDialog::applyPresetLayout(CustomKeypadDialog::PresetLayout presetLayout) { const Settings::CustomKeypad preset = presetKeypad(static_cast(presetLayout)); { const QSignalBlocker rowBlocker(m_rowsSpin); const QSignalBlocker columnBlocker(m_columnsSpin); m_rowsSpin->setValue(preset.rows); m_columnsSpin->setValue(preset.columns); } m_currentRows = preset.rows; m_currentColumns = preset.columns; m_cells = QList(preset.rows * preset.columns); for (const auto& button : preset.buttons) { if (button.row < 0 || button.row >= preset.rows || button.column < 0 || button.column >= preset.columns) continue; const int index = cellIndex(button.row, button.column); m_cells[index].label = button.label; m_cells[index].text = button.text; m_cells[index].action = button.action; } buildTableFromCells(); } QList CustomKeypadDialog::readCellsFromTable() const { const int rows = m_rowsSpin->value(); const int columns = m_columnsSpin->value(); const int entries = rows * columns; QList cells(entries); for (int index = 0; index < entries; ++index) { const auto* labelItem = m_table->item(index, ColumnIndexLabel); const auto* textItem = m_table->item(index, ColumnIndexText); const auto* actionCombo = qobject_cast(m_table->cellWidget(index, ColumnIndexAction)); cells[index].label = labelItem ? labelItem->text() : QString(); cells[index].text = textItem ? textItem->text() : QString(); cells[index].action = actionCombo ? static_cast(actionCombo->currentData().toInt()) : Settings::CustomKeypadActionInsertText; } return cells; } heldercorreia-speedcrunch-e7ca37f/src/gui/customkeypaddialog.h000066400000000000000000000022121526573132500247460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_CUSTOMKEYPADDIALOG_H #define GUI_CUSTOMKEYPADDIALOG_H #include "core/settings.h" #include #include class QSpinBox; class QTableWidget; class CustomKeypadDialog : public QDialog { Q_OBJECT public: explicit CustomKeypadDialog(const Settings::CustomKeypad& keypad, QWidget* parent = nullptr); Settings::CustomKeypad customKeypad() const; private: enum PresetLayout { PresetLayoutBasicWide = 0, PresetLayoutScientificWide = 1, PresetLayoutScientificNarrow = 2 }; struct Cell { QString label; QString text; Settings::CustomKeypadButtonAction action; }; int cellIndex(int row, int column) const; void buildTableFromCells(); void rebuildCellStorage(int rows, int columns); void applyPresetLayout(PresetLayout presetLayout); QList readCellsFromTable() const; QSpinBox* m_rowsSpin; QSpinBox* m_columnsSpin; QTableWidget* m_table; QList m_cells; int m_currentRows; int m_currentColumns; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/diagnosticapplication.h000066400000000000000000000030561526573132500254350ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_DIAGNOSTICAPPLICATION_H #define GUI_DIAGNOSTICAPPLICATION_H #include "core/startupdiagnostics.h" #include "gui/mainwindow.h" #include #include #include #include #include class RecordingDiagnosticApplication : public QApplication { public: RecordingDiagnosticApplication(int& argc, char** argv) : QApplication(argc, argv) { connect(QAbstractEventDispatcher::instance(), &QAbstractEventDispatcher::aboutToBlock, this, []() { StartupDiagnostics::finishWhenIdle(); }); } bool notify(QObject* receiver, QEvent* event) override { if (event->type() != QEvent::Paint || !StartupDiagnostics::isRecording()) return QApplication::notify(receiver, event); StartupDiagnostics::Scope timing("Paint startup widgets"); const bool result = QApplication::notify(receiver, event); QWidget* widget = qobject_cast(receiver); if (!m_firstPaintQueued && widget && widget->isVisible() && qobject_cast(widget->window())) { m_firstPaintQueued = true; QTimer::singleShot(0, this, []() { StartupDiagnostics::firstPaintFinished(); }); } return result; } private: bool m_firstPaintQueued = false; }; using DiagnosticApplication = std::conditional_t; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/diagnosticsdialog.cpp000066400000000000000000000324611526573132500251110ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/diagnosticsdialog.h" #include "core/settings.h" #include "core/startupdiagnostics.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #endif #ifdef Q_OS_MACOS #include #endif #ifdef Q_OS_WIN #include #include #endif namespace { QString milliseconds(qint64 ns) { return QString::number(ns / 1000000.0, 'f', 3); } QString mib(quint64 bytes) { return QString::number(bytes / (1024.0 * 1024.0), 'f', 1); } QString processStatistics() { QString result; QTextStream out(&result); #ifdef Q_OS_UNIX struct rusage usage = {}; if (getrusage(RUSAGE_SELF, &usage) == 0) { const auto seconds = [](const timeval& time) { return time.tv_sec + time.tv_usec / 1000000.0; }; out << "Process CPU time since launch (user / system): " << QString::number(seconds(usage.ru_utime), 'f', 3) << " / " << QString::number(seconds(usage.ru_stime), 'f', 3) << " s\n"; #if defined(Q_OS_MACOS) out << "Peak resident memory: " << mib(usage.ru_maxrss) << " MiB\n"; #elif defined(Q_OS_LINUX) out << "Peak resident memory: " << mib(quint64(usage.ru_maxrss) * 1024) << " MiB\n"; #endif } #endif #ifdef Q_OS_MACOS mach_task_basic_info_data_t info = {}; mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT; if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, reinterpret_cast(&info), &count) == KERN_SUCCESS) out << "Current resident memory: " << mib(info.resident_size) << " MiB\n"; #elif defined(Q_OS_LINUX) QFile status(QStringLiteral("/proc/self/status")); if (status.open(QIODevice::ReadOnly)) { const QList lines = status.readAll().split('\n'); for (const QByteArray& line : lines) { if (line.startsWith("VmRSS:")) { bool ok = false; const quint64 kib = line.mid(6).simplified().split(' ').value(0).toULongLong(&ok); if (ok) out << "Current resident memory: " << mib(kib * 1024) << " MiB\n"; } } } #elif defined(Q_OS_WIN) PROCESS_MEMORY_COUNTERS info = {}; if (K32GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info))) { out << "Current resident memory: " << mib(info.WorkingSetSize) << " MiB\n" << "Peak resident memory: " << mib(info.PeakWorkingSetSize) << " MiB\n"; } FILETIME created, exited, kernel, user; if (GetProcessTimes(GetCurrentProcess(), &created, &exited, &kernel, &user)) { const auto seconds = [](const FILETIME& time) { ULARGE_INTEGER value; value.LowPart = time.dwLowDateTime; value.HighPart = time.dwHighDateTime; return value.QuadPart / 10000000.0; }; out << "Process CPU time since launch (user / system): " << QString::number(seconds(user), 'f', 3) << " / " << QString::number(seconds(kernel), 'f', 3) << " s\n"; } #endif if (result.isEmpty()) out << "Process memory and CPU time: unavailable on this platform\n"; return result; } } QString appDiagnosticsReport(const QString& workload) { const Settings* settings = Settings::instance(); QString report; QTextStream out(&report); out << "SpeedCrunch " SPEEDCRUNCH_VERSION; #ifdef SPEEDCRUNCH_PORTABLE out << " Portable\nPortable: yes\n"; #else out << "\nPortable: no\n"; #endif out << "OS: " << QSysInfo::prettyProductName() << '\n' << "OS version: " << QSysInfo::productVersion() << '\n' << "Kernel: " << QSysInfo::kernelType() << ' ' << QSysInfo::kernelVersion() << '\n' << "Architecture (build / CPU): " << QSysInfo::buildCpuArchitecture() << " / " << QSysInfo::currentCpuArchitecture() << '\n' << "Build ABI: " << QSysInfo::buildAbi() << '\n' << "Qt (runtime / build): " << qVersion() << " / " QT_VERSION_STR << '\n'; #ifdef QT_DEBUG out << "Build: Debug\n"; #else out << "Build: Release\n"; #endif out << "App language: "; if (settings->language == QLatin1String("C")) out << "System (" << QLocale().name() << ")\n"; else out << settings->language << '\n'; QString translation = qApp->property("speedcrunchTranslationLanguage").toString(); if (translation.isEmpty()) translation = QStringLiteral("unavailable"); const QStyle* platformStyle = qApp->style(); while (const auto* proxy = qobject_cast(platformStyle)) platformStyle = proxy->baseStyle(); out << "System language: " << QLocale::system().name() << '\n' << "System UI languages: " << QLocale::system().uiLanguages().join(", ") << '\n' << "Loaded translation: " << translation << '\n' << "Qt platform: " << QGuiApplication::platformName() << '\n' << "Widget style: " << (platformStyle->objectName().isEmpty() ? QString::fromLatin1(platformStyle->metaObject()->className()) : platformStyle->objectName()) << '\n' << "CPU threads available: " << QThread::idealThreadCount() << '\n'; int screenIndex = 0; for (const QScreen* screen : QGuiApplication::screens()) { const QSize size = screen->size(); out << "Screen " << ++screenIndex << ": " << size.width() << 'x' << size.height() << ", scale " << screen->devicePixelRatio() << ", logical DPI " << screen->logicalDotsPerInch() << ", refresh " << screen->refreshRate() << " Hz\n"; } out << '\n' << processStatistics() << '\n' << workload; int definitionLines = 0; for (const QString& line : settings->startupUserDefinitions.split('\n')) { if (!line.trimmed().isEmpty()) ++definitionLines; } out << "Theme: " << (settings->colorScheme == QLatin1String("Custom") ? QStringLiteral("Custom") : settings->colorScheme) << '\n' << "Editor appearance: " << (settings->editorDisplayStyle == Settings::EditorDisplayClassic ? "Classic" : "Modern") << '\n' << "Dock appearance: " << (settings->dockAppearance == Settings::DockAppearanceSystem ? "System" : "SpeedCrunch Theme") << '\n' << "Menu appearance: " << (settings->menuAppearance == Settings::MenuAppearanceSystem ? "System" : "SpeedCrunch Theme") << '\n' << "Status bar appearance: " << (settings->statusBarAppearance == Settings::StatusBarAppearanceSystem ? "System" : "SpeedCrunch Theme") << '\n' << "Automatic calculation: " << (settings->autoCalc ? "on" : "off") << '\n' << "Syntax highlighting: " << (settings->syntaxHighlighting ? "on" : "off") << '\n' << "Automatic completion: " << (settings->autoCompletion ? "on" : "off") << '\n' << "Complex numbers: " << (settings->complexNumbers ? "on" : "off") << '\n' << "Result precision setting: " << settings->resultPrecision << '\n' << "Extra result lines: " << (settings->multipleResultLinesEnabled ? "on" : "off") << '\n' << "Global definition lines: " << definitionLines << '\n' << "Saved window layout size: " << settings->sessionLayoutJson.toUtf8().size() << " bytes\n" << "Keypad mode / zoom: " << int(settings->keypadMode) << " / " << settings->keypadZoomPercent << "%\n"; #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS out << "Update checks: enabled\n"; #else out << "Update checks: disabled\n"; #endif const auto startup = StartupDiagnostics::snapshot(); out << "\nStartup timings\n"; if (!StartupDiagnostics::isEnabled()) { out << "Startup recording disabled in this build.\n"; return report; } if (!startup.started) { out << "Unavailable (startup recording did not run).\n"; return report; } out << "Status: " << (startup.complete ? "complete" : "in progress") << '\n' << "Elapsed from main(): " << milliseconds(startup.elapsedNs) << " ms\n"; if (startup.firstPaintNs >= 0) out << "First window paint and event processing: " << milliseconds(startup.firstPaintNs) << " ms from main()\n"; out << "Durations are wall-clock times. Nested phases and worker tasks overlap.\n" << "Totals include repeated calls. Do not add them to estimate startup time.\n" << "Async totals include time waiting for the UI thread.\n" << "Start ms | Total ms | Max ms | Calls | Thread | Phase\n"; for (const auto& phase : startup.phases) { out << milliseconds(phase.firstStartNs) << " | " << milliseconds(phase.totalNs) << " | " << milliseconds(phase.longestNs) << " | " << phase.calls << " | " << (phase.worker ? "worker" : "main") << " | " << phase.name; if (phase.running) out << " (" << phase.running << " running)"; out << '\n'; } if (!startup.appearanceCalls.isEmpty()) { out << "\nStartup appearance calls\n" << "Widget IDs are temporary numeric IDs, not names or addresses.\n" << "Style installation uses the application object as its target.\n" << "Widget 0 means no target. Widget -1 means the identity limit is reached.\n" << "Input comparisons refer to the preceding call of the same kind and target.\n" << "Document comparisons use revision and size, without reading calculation text.\n" << "Document revisions can also change when formatting changes.\n" << "Settings comparisons cover highlighting, grouping, radix, editor style and font.\n" << "Evaluator comparisons check identity, not changes to its symbols.\n" << "Unchanged inputs alone do not establish that a call is safe to skip.\n" << "Call | Parent | Start ms | Duration ms | Widget | Context | Operation | Inputs\n"; int callNumber = 0; for (const auto& call : startup.appearanceCalls) { out << ++callNumber << " | " << call.parentCall << " | " << milliseconds(call.startNs) << " | " << milliseconds(call.durationNs) << " | " << call.widgetId << " | " << call.context << " | " << call.name; if (!call.finished) out << " (running)"; out << " | "; if (call.inputs >= 0) { out << "inputs=" << (call.inputs == 0 ? "first" : call.inputs == 1 ? "changed" : "unchanged"); } if (!call.inputChanges.isEmpty()) { if (call.inputs >= 0) out << ' '; out << call.inputChanges; } out << '\n'; } out << "\nStartup appearance assignments\n" << "Counts cover instrumented setters inside recorded appearance calls.\n" << "Assignments belong to the innermost call.\n" << "Changed and unchanged compare requested values before invoking the setter.\n" << "Skipped counts guards that avoid identical palette or stylesheet assignments.\n" << "Native palettes can be skipped when no style polish is needed.\n" << "Call | Widget | Assignment | Changed | Unchanged | Skipped\n"; for (const auto& assignment : startup.appearanceAssignments) { out << assignment.call << " | " << assignment.widgetId << " | " << (assignment.palette ? "palette" : "stylesheet") << " | " << assignment.changed << " | " << assignment.unchanged << " | " << assignment.skipped << '\n'; } out << "Appearance recording limits: 512 calls, 2048 identities, 2048 assignment rows.\n" << "Omitted appearance records: " << startup.omittedAppearanceRecords << '\n'; } out << "\nTimings start at main() and exclude process loading before main().\n" << "Measurements stay in memory and are discarded when the app exits.\n"; return report; } DiagnosticsDialog::DiagnosticsDialog(const QString& report, QWidget* parent) : QDialog(parent) { setObjectName(QStringLiteral("AppDiagnosticsDialog")); setWindowTitle(tr("App Diagnostics")); resize(760, 560); auto* text = new QPlainTextEdit(this); text->setObjectName(QStringLiteral("DiagnosticsText")); text->setReadOnly(true); text->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); text->setLineWrapMode(QPlainTextEdit::NoWrap); text->setPlainText(report); auto* buttons = new QDialogButtonBox(QDialogButtonBox::Close, this); auto* copy = buttons->addButton(tr("Copy to Clipboard"), QDialogButtonBox::ActionRole); copy->setObjectName(QStringLiteral("CopyDiagnostics")); connect(copy, &QPushButton::clicked, this, [text]() { QApplication::clipboard()->setText(text->toPlainText()); }); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); auto* layout = new QVBoxLayout(this); layout->addWidget(text); layout->addWidget(buttons); } heldercorreia-speedcrunch-e7ca37f/src/gui/diagnosticsdialog.h000066400000000000000000000006171526573132500245540ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_DIAGNOSTICSDIALOG_H #define GUI_DIAGNOSTICSDIALOG_H #include QString appDiagnosticsReport(const QString& workload); class DiagnosticsDialog : public QDialog { Q_OBJECT public: explicit DiagnosticsDialog(const QString& report, QWidget* parent = nullptr); }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/displayformatutils.cpp000066400000000000000000000332411526573132500253560ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/displayformatutils.h" #include "core/evaluator.h" #include "core/numberformatter.h" #include "core/regexpatterns.h" #include "core/unicodechars.h" #include "core/mathdsl.h" namespace DisplayFormatUtils { namespace { struct ArrowRange { int pos = -1; int size = 0; }; ArrowRange findConversionArrow(const QString& text) { const int unicodeArrowPos = text.indexOf(MathDsl::TransOp); if (unicodeArrowPos >= 0) return {unicodeArrowPos, 1}; const int asciiArrowPos = text.indexOf(QStringLiteral("->")); if (asciiArrowPos >= 0) return {asciiArrowPos, 2}; return {}; } bool sourceHasBracketedConversionTarget(const QString& sourceExpression) { if (sourceExpression.isEmpty()) return false; const ArrowRange arrow = findConversionArrow(sourceExpression); if (arrow.pos < 0) return false; int sourceTargetStart = arrow.pos + arrow.size; while (sourceTargetStart < sourceExpression.size() && sourceExpression.at(sourceTargetStart).isSpace()) { ++sourceTargetStart; } return sourceTargetStart < sourceExpression.size() && sourceExpression.at(sourceTargetStart) == MathDsl::UnitStart; } bool tokenCanEndOperandForSpacing(const Token& token) { return token.isOperand() || token.asOperator() == Token::AssociationEnd || token.asOperator() == Token::Factorial || token.asOperator() == Token::Percent; } bool tokenCanStartOperandForSpacing(const Token& token) { return token.isOperand() || token.asOperator() == Token::AssociationStart || token.asOperator() == Token::Addition || token.asOperator() == Token::Subtraction || token.asOperator() == Token::BitwiseLogicalNOT; } QString spacingForBinaryOperator(const Token& token, const QString& operatorText) { const Token::Operator op = token.asOperator(); switch (op) { case Token::Addition: return MathDsl::buildWrappedToken(MathDsl::AddOp, MathDsl::AddWrap); case Token::Subtraction: return MathDsl::buildWrappedToken(MathDsl::SubOp, MathDsl::SubWrapSp); case Token::Division: return MathDsl::buildWrappedToken(MathDsl::DivOp, MathDsl::DivWrap); case Token::Multiplication: { const bool useCrossSign = operatorText == QString(MathDsl::MulCrossOp) || operatorText == QStringLiteral("*"); const QChar sign = useCrossSign ? MathDsl::MulCrossOp : MathDsl::MulDotOp; const QChar space = useCrossSign ? MathDsl::MulCrossWrapSp : MathDsl::MulDotWrapSp; return MathDsl::buildWrappedToken(sign, space); } default: return token.text(); } } QString signForUnitOperator(const Token& token, const QString& operatorText) { const Token::Operator op = token.asOperator(); switch (op) { case Token::Addition: return QString(MathDsl::AddOp); case Token::Subtraction: return QString(MathDsl::SubOp); case Token::Division: return QString(MathDsl::DivOp); case Token::Multiplication: return operatorText == QString(MathDsl::MulCrossOp) ? QString(MathDsl::MulCrossOp) : QString(MathDsl::MulDotOp); default: return token.text(); } } QString compactCompositeUnitSpacing(QString text) { static const QRegularExpression compactUnitOps( QStringLiteral(R"(\s*([·×/])\s*)")); int pos = 0; while (true) { const int open = text.indexOf(MathDsl::UnitStart, pos); if (open < 0) break; const int close = text.indexOf(MathDsl::UnitEnd, open + 1); if (close < 0) break; QString segment = text.mid(open + 1, close - open - 1); segment.replace(compactUnitOps, QStringLiteral("\\1")); text.replace(open + 1, close - open - 1, segment); pos = open + segment.size() + 2; } const int arrow = text.indexOf(MathDsl::TransOp); if (arrow >= 0) { int rhsStart = arrow + 1; while (rhsStart < text.size() && text.at(rhsStart).isSpace()) ++rhsStart; int rhsEnd = text.indexOf(MathDsl::CommentSep, rhsStart); if (rhsEnd < 0) rhsEnd = text.size(); if (rhsStart < rhsEnd) { QString rhs = text.mid(rhsStart, rhsEnd - rhsStart); rhs.replace(compactUnitOps, QStringLiteral("\\1")); text.replace(rhsStart, rhsEnd - rhsStart, rhs); } } return text; } QString collapseValueUnitMultiplicationSpacing(QString text) { return text.replace( RegExpPatterns::valueTimesBracketedUnit(), QStringLiteral("\\1") + QString(MathDsl::QuantSp) + QStringLiteral("\\2")); } bool endsWithNumericLiteral(QStringView text) { int end = text.size() - 1; while (end >= 0 && text.at(end).isSpace()) --end; if (end < 0) return false; int start = end; while (start >= 0) { const QChar ch = text.at(start); if (ch.isLetterOrNumber() || ch == MathDsl::DotSep || ch == MathDsl::CommaSep || ch == MathDsl::AddOp || MathDsl::isSubtractionOperator(ch)) { --start; continue; } break; } const QString candidate = text.mid(start + 1, end - start).toString(); return RegExpPatterns::signedNumericLiteralWithSpaces().match(candidate).hasMatch(); } } // namespace QString applyOperatorSpacingForDisplay(const QString& input) { const Tokens tokens = Evaluator::instance()->scan(input); if (!tokens.valid() || tokens.isEmpty()) return input; QString output; output.reserve(input.size() + 16); int lastPos = 0; int unitBracketDepth = 0; for (int i = 0; i < tokens.size(); ++i) { const Token& token = tokens.at(i); if (token.pos() < lastPos || token.pos() < 0 || token.size() < 0 || token.pos() + token.size() > input.size()) { return input; } const QString originalTokenText = input.mid(token.pos(), token.size()); output += input.mid(lastPos, token.pos() - lastPos); lastPos = token.pos() + token.size(); const Token::Operator op = token.asOperator(); if (op == Token::AssociationStart && originalTokenText == QLatin1String("[")) { ++unitBracketDepth; output += originalTokenText; continue; } if (op == Token::AssociationEnd && originalTokenText == QLatin1String("]")) { if (unitBracketDepth > 0) --unitBracketDepth; output += originalTokenText; continue; } const bool isSpacingOperator = op == Token::Addition || op == Token::Subtraction || op == Token::Multiplication || op == Token::Division; const bool hasLeftOperand = i > 0 && tokenCanEndOperandForSpacing(tokens.at(i - 1)); const bool hasRightOperand = i + 1 < tokens.size() && tokenCanStartOperandForSpacing(tokens.at(i + 1)); const bool isBinaryOperator = hasLeftOperand && hasRightOperand; int rhsPos = lastPos; while (rhsPos < input.size() && input.at(rhsPos).isSpace()) ++rhsPos; const bool isValueUnitAttachment = op == Token::Multiplication && rhsPos < input.size() && input.at(rhsPos) == MathDsl::UnitStart; const bool isUnitCompositeOperator = (op == Token::Multiplication || op == Token::Division) && i > 0 && i + 1 < tokens.size() && tokens.at(i - 1).isUnitIdentifier() && tokens.at(i + 1).isUnitIdentifier(); if (!isSpacingOperator || !isBinaryOperator) { output += originalTokenText; continue; } while (!output.isEmpty() && output.back().isSpace()) output.chop(1); if (isValueUnitAttachment) { output += MathDsl::QuantSp; lastPos = rhsPos; continue; } output += (unitBracketDepth > 0 || isUnitCompositeOperator) ? signForUnitOperator(token, originalTokenText) : spacingForBinaryOperator(token, originalTokenText); while (lastPos < input.size() && input.at(lastPos).isSpace()) ++lastPos; } output += input.mid(lastPos); auto isUnitOp = [](QChar ch) { return MathDsl::isMultiplicationOperator(ch) || MathDsl::isDivisionOperator(ch); }; auto isUnitLike = [](QChar ch) { return ch.isLetter() || ch == QLatin1Char('_') || ch == UnicodeChars::MicroSign || ch == UnicodeChars::GreekCapitalOmega || ch == UnicodeChars::DegreeSign // ° || ch == MathDsl::PowNeg // � || MathDsl::isSuperscriptDigit(ch) || ch == MathDsl::GroupStart || ch == MathDsl::GroupEnd || ch == MathDsl::UnitStart || ch == MathDsl::UnitEnd; }; int i = 0; while (i < output.size()) { if (!isUnitOp(output.at(i))) { ++i; continue; } int left = i - 1; while (left >= 0 && output.at(left).isSpace()) --left; int right = i + 1; while (right < output.size() && output.at(right).isSpace()) ++right; if (left < 0 || right >= output.size() || !isUnitLike(output.at(left)) || !isUnitLike(output.at(right))) { ++i; continue; } int removeStart = left + 1; int removeCount = i - removeStart; if (removeCount > 0) { output.remove(removeStart, removeCount); i = removeStart; } const int opPos = i; int next = opPos + 1; while (next < output.size() && output.at(next).isSpace()) ++next; const int rightSpaces = next - (opPos + 1); if (rightSpaces > 0) output.remove(opPos + 1, rightSpaces); ++i; } return output; } QString applyValueUnitSpacingForDisplay(const QString& input) { QString output; output.reserve(input.size() + 8); for (const QChar ch : input) { if (ch == MathDsl::UnitStart && !output.isEmpty()) { if (output.back().isSpace()) { if (endsWithNumericLiteral(QStringView(output))) { int i = output.size() - 1; while (i >= 0 && output.at(i).isSpace()) --i; output.truncate(i + 1); output += MathDsl::QuantSp; } } else if (endsWithNumericLiteral(QStringView(output))) { output += MathDsl::QuantSp; } } output += ch; } return output; } QString applyDigitGroupingForDisplay(const QString& input) { // Even when grouping is disabled we still pass numeric tokens through // NumberFormatter::formatNumericLiteralForDisplay(), because that helper // also normalizes decimal separator display according to the selected // number-format style (for example dot-internal -> comma-display). // Grouping can be a no-op there while decimal-separator conversion still // needs to happen. QString output; int lastPos = 0; auto it = RegExpPatterns::numericToken().globalMatch(input); while (it.hasNext()) { const auto match = it.next(); output += input.mid(lastPos, match.capturedStart() - lastPos); output += NumberFormatter::formatNumericLiteralForDisplay(match.captured(0)); lastPos = match.capturedEnd(); } output += input.mid(lastPos); output = UnicodeChars::normalizePiForDisplay(output); output = UnicodeChars::normalizeRootFunctionAliasesForDisplay(output); output = applyOperatorSpacingForDisplay(output); output = compactCompositeUnitSpacing(output); output = collapseValueUnitMultiplicationSpacing(output); return applyValueUnitSpacingForDisplay(output); } QString preserveConversionTargetBracketsForDisplay(const QString& displayedInterpreted, const QString& sourceExpression) { if (displayedInterpreted.isEmpty()) return displayedInterpreted; const bool hasSourceBracketedTarget = sourceHasBracketedConversionTarget(sourceExpression); const ArrowRange arrow = findConversionArrow(displayedInterpreted); if (arrow.pos < 0) return displayedInterpreted; int targetStart = arrow.pos + arrow.size; while (targetStart < displayedInterpreted.size() && displayedInterpreted.at(targetStart).isSpace()) ++targetStart; if (targetStart >= displayedInterpreted.size()) return displayedInterpreted; if (displayedInterpreted.at(targetStart) == MathDsl::UnitStart) return displayedInterpreted; bool shouldWrapTarget = hasSourceBracketedTarget; if (!shouldWrapTarget) { const QString lhs = displayedInterpreted.left(arrow.pos); const bool hasBracketedSourceUnit = lhs.contains(MathDsl::UnitStart) && lhs.contains(MathDsl::UnitEnd); shouldWrapTarget = hasBracketedSourceUnit; } if (!shouldWrapTarget) return displayedInterpreted; int targetEnd = displayedInterpreted.indexOf(QStringLiteral(" ?"), targetStart); if (targetEnd < 0) targetEnd = displayedInterpreted.size(); const QString target = displayedInterpreted.mid(targetStart, targetEnd - targetStart).trimmed(); if (target.isEmpty()) return displayedInterpreted; return displayedInterpreted.left(targetStart) + MathDsl::UnitStart + target + MathDsl::UnitEnd + displayedInterpreted.mid(targetEnd); } } // namespace DisplayFormatUtils heldercorreia-speedcrunch-e7ca37f/src/gui/displayformatutils.h000066400000000000000000000032031526573132500250160ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef DISPLAYFORMATUTILS_H #define DISPLAYFORMATUTILS_H #include namespace DisplayFormatUtils { /* Display spacing rules (single source of truth) ---------------------------------------------- Operator sign constants come from MathDsl. 1) Arithmetic expression operators - use MathDsl::AddWrap around AdditionSign - use MathDsl::SubtractionSpace around SubtractionSign - use MathDsl::DivWrap around DivisionSign - use MathDsl::MulDotWrapSp around MulDotSign - use MathDsl::MulCrossWrapSp around MulCrossSign Examples: - 2 + 3 + 4 - 2 − 3 − 4 - 2 / 3 / 4 - 2 · cos(45) · sin(90) - 2 × 3 × 4 2) Number + unit pair - Between numeric value and unit bracket use MathDsl::QuantSp. - Example: 2 [kg] 3) Composite units - Inside unit expressions there are no surrounding spaces around unit multiplication/division operators, regardless of operator sign. - Example: [kg·m/s²] 4) Conversion target display - Preserve explicit source RHS unit brackets for display, e.g. `3 [m] -> [km]` displays as `3 [m] → [km]`. */ QString applyDigitGroupingForDisplay(const QString& input); QString applyOperatorSpacingForDisplay(const QString& input); QString applyValueUnitSpacingForDisplay(const QString& input); QString preserveConversionTargetBracketsForDisplay(const QString& displayedInterpreted, const QString& sourceExpression); } #endif // DISPLAYFORMATUTILS_H heldercorreia-speedcrunch-e7ca37f/src/gui/dockcomboboxchevron.cpp000066400000000000000000000362551526573132500254650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/dockcomboboxchevron.h" #include "core/settings.h" #include "gui/menustyleutils.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { constexpr int kChevronAnimationMs = 150; constexpr float kChevronOpacity = 0.76f; // Qt's menu delegate paints through the combo's style, which also carries // the closed control's stylesheet. Paint popup items with the system style. class SystemPopupDelegate : public QStyledItemDelegate { public: SystemPopupDelegate(QComboBox* combo, QAbstractItemView* view) : QStyledItemDelegate(view), m_combo(combo) {} void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { QStyleOptionViewItem item(option); initStyleOption(&item, index); if (!usesMenuItems()) { QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &item, painter, option.widget); return; } const QStyleOptionMenuItem menu = menuOption(item, index); painter->fillRect(menu.rect, menu.palette.window()); QApplication::style()->drawControl(QStyle::CE_MenuItem, &menu, painter, option.widget); } QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override { if (!usesMenuItems()) return QStyledItemDelegate::sizeHint(option, index); QStyleOptionViewItem item(option); initStyleOption(&item, index); const QStyleOptionMenuItem menu = menuOption(item, index); return QApplication::style()->sizeFromContents(QStyle::CT_MenuItem, &menu, menu.rect.size(), option.widget); } private: bool usesMenuItems() const { QStyleOptionComboBox option; option.initFrom(m_combo); option.editable = m_combo->isEditable(); return QApplication::style()->styleHint(QStyle::SH_ComboBox_Popup, &option, m_combo); } QStyleOptionMenuItem menuOption(const QStyleOptionViewItem& item, const QModelIndex& index) const { QStyleOptionMenuItem menu; menu.rect = menu.menuRect = item.rect; menu.direction = item.direction; menu.palette = item.palette; menu.state = item.state & (QStyle::State_Active | QStyle::State_Enabled | QStyle::State_Selected); if (!(index.flags() & Qt::ItemIsEnabled)) menu.state &= ~QStyle::State_Enabled; menu.palette.setCurrentColorGroup(!(menu.state & QStyle::State_Enabled) ? QPalette::Disabled : (menu.state & QStyle::State_Active) ? QPalette::Active : QPalette::Inactive); menu.font = item.font; menu.fontMetrics = item.fontMetrics; menu.text = item.text; menu.text.replace(QLatin1Char('&'), QStringLiteral("&&")); menu.icon = item.icon; menu.maxIconWidth = item.decorationSize.width() + 4; menu.menuItemType = QStyleOptionMenuItem::Normal; menu.checkType = QStyleOptionMenuItem::NonExclusive; menu.checked = m_combo->currentIndex() == index.row(); return menu; } QComboBox* m_combo; }; void removeFrame(QWidget* widget) { QFrame* frame = qobject_cast(widget); if (frame == nullptr) return; frame->setFrameShape(QFrame::NoFrame); frame->setLineWidth(0); frame->setMidLineWidth(0); } void applyRoundedMask(QWidget* widget) { if (widget == nullptr || widget->size().isEmpty()) return; QBitmap mask(widget->size()); mask.fill(Qt::color0); QPainter painter(&mask); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); painter.setBrush(Qt::color1); painter.drawRoundedRect(QRectF(mask.rect()).adjusted(0, 0, -1, -1), UiConfig::CompletionPopupCornerRadius, UiConfig::CompletionPopupCornerRadius); widget->setMask(mask); } } // namespace DockComboBoxChevron::DockComboBoxChevron(QComboBox* comboBox) : QWidget(comboBox) , m_comboBox(comboBox) , m_animation(new QVariantAnimation(this)) , m_nativeButtonStyle(comboBox->styleSheet()) { setObjectName(QStringLiteral("speedcrunchDockComboBoxChevron")); setAttribute(Qt::WA_TransparentForMouseEvents); setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_TranslucentBackground); setAutoFillBackground(false); setFocusPolicy(Qt::NoFocus); m_animation->setDuration(kChevronAnimationMs); m_animation->setEasingCurve(QEasingCurve::OutCubic); connect(m_animation, &QVariantAnimation::valueChanged, this, [this](const QVariant& value) { m_rotation = value.toReal(); update(); }); connect(comboBox, QOverload::of(&QComboBox::activated), this, [this]() { setPopupOpen(false); }); comboBox->installEventFilter(this); installPopupEventFilters(); reposition(); show(); } void DockComboBoxChevron::apply(QComboBox* comboBox, const QColor& textColor, const QColor& outlineColor, const PopupTheme& popupTheme) { if (comboBox == nullptr) return; DockComboBoxChevron* chevron = nullptr; if (QWidget* existing = comboBox->findChild( QStringLiteral("speedcrunchDockComboBoxChevron"), Qt::FindDirectChildrenOnly)) { chevron = dynamic_cast(existing); } if (chevron == nullptr) chevron = new DockComboBoxChevron(comboBox); comboBox->setProperty("speedcrunchDockComboBox", true); chevron->m_popupTheme = popupTheme; chevron->setColors(textColor, outlineColor); chevron->refresh(); } void DockComboBoxChevron::refreshPopupAppearance(QComboBox* comboBox) { if (comboBox == nullptr) return; if (auto* chevron = dynamic_cast(comboBox->findChild( QStringLiteral("speedcrunchDockComboBoxChevron"), Qt::FindDirectChildrenOnly))) chevron->refresh(); } void DockComboBoxChevron::applySystemAppearance(QComboBox* comboBox) { apply(comboBox, QColor(), QColor(), PopupTheme()); } void DockComboBoxChevron::setColors(QColor chevronColor, const QColor& outlineColor) { chevronColor.setAlphaF(kChevronOpacity); if (m_chevronColor == chevronColor && m_outlineColor == outlineColor) return; m_chevronColor = chevronColor; m_outlineColor = outlineColor; update(); } void DockComboBoxChevron::refresh() { installPopupEventFilters(); reposition(); setPopupOpen(m_view != nullptr && m_view->isVisible()); raise(); setVisible(Settings::instance()->dockAppearance != Settings::DockAppearanceSystem); } bool DockComboBoxChevron::eventFilter(QObject* watched, QEvent* event) { if (m_stylingPopup) return false; if (watched == m_comboBox) { switch (event->type()) { case QEvent::Move: case QEvent::Resize: case QEvent::Show: case QEvent::StyleChange: reposition(); stylePopupChrome(); break; case QEvent::Hide: setPopupOpen(false); break; case QEvent::KeyPress: case QEvent::MouseButtonPress: installPopupEventFilters(); break; default: break; } } else if (watched == m_view || watched == m_popupWindow) { if (event->type() == QEvent::Show) { stylePopupChrome(); setPopupOpen(true); } else if (event->type() == QEvent::Hide) { setPopupOpen(false); } else if (event->type() == QEvent::Resize) { stylePopupChrome(); } } return QWidget::eventFilter(watched, event); } void DockComboBoxChevron::paintEvent(QPaintEvent*) { if (!m_chevronColor.isValid()) return; const qreal dpr = devicePixelRatioF(); const auto aligned = [dpr](qreal value) { return qRound(value * dpr) / dpr; }; QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.translate(QPointF(aligned(width() / 2.0), aligned(height() / 2.0))); painter.rotate(m_rotation); QPainterPath path; path.moveTo(QPointF(-5.0, -3.0)); path.lineTo(QPointF(0.0, 3.0)); path.lineTo(QPointF(5.0, -3.0)); QPen pen(m_chevronColor, 1.65, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); painter.setPen(pen); painter.setBrush(Qt::NoBrush); painter.drawPath(path); } void DockComboBoxChevron::installPopupEventFilters() { if (m_comboBox == nullptr) return; QAbstractItemView* view = m_comboBox->view(); if (m_view != view) { if (m_view != nullptr) m_view->removeEventFilter(this); m_view = view; if (m_view != nullptr) { m_themedDelegate = m_view->itemDelegate(); m_systemDelegate = new SystemPopupDelegate(m_comboBox, m_view); m_nativeView.capture(m_view); m_nativeViewport.capture(m_view->viewport()); m_view->installEventFilter(this); } } QWidget* popupWindow = m_view != nullptr ? m_view->window() : nullptr; if (popupWindow == m_comboBox->window()) popupWindow = nullptr; if (m_popupWindow != popupWindow) { if (m_popupWindow != nullptr) m_popupWindow->removeEventFilter(this); m_popupWindow = popupWindow; if (m_popupWindow != nullptr) { m_nativePopup.capture(m_popupWindow); m_popupWindow->installEventFilter(this); } } stylePopupChrome(); } QWidget* DockComboBoxChevron::popupChromeWidget() const { if (m_popupWindow != nullptr) return m_popupWindow; return m_view; } void DockComboBoxChevron::reposition() { if (m_comboBox == nullptr) return; setGeometry(qMax(0, m_comboBox->width() - IndicatorWidth), 0, IndicatorWidth, m_comboBox->height()); } void DockComboBoxChevron::stylePopupChrome() { const bool systemDock = Settings::instance()->dockAppearance == Settings::DockAppearanceSystem; if (m_view == nullptr || m_stylingPopup || (!systemDock && m_popupTheme.viewStyle.isEmpty())) return; QScopedValueRollback guard(m_stylingPopup, true); const bool system = systemDock || Settings::instance()->menuAppearance == Settings::MenuAppearanceSystem; if (!system && m_view->itemDelegate() == m_systemDelegate && m_themedDelegate) m_view->setItemDelegate(m_themedDelegate); const QString comboStyle = systemDock ? m_nativeButtonStyle : m_popupTheme.buttonStyle + (system ? QString() : QStringLiteral( "QComboBox QAbstractItemView { background-color: %1; color: %2; border: 0; outline: 0; }") .arg(m_popupTheme.palette.color(QPalette::Base).name(), m_popupTheme.palette.color(QPalette::Text).name())); if (m_comboBox->styleSheet() != comboStyle) { // Popup rules also repolish the button. Keep its dock colors intact. const QPalette buttonPalette = m_comboBox->palette(); m_comboBox->setStyleSheet(comboStyle); m_comboBox->setPalette(buttonPalette); } setVisible(!systemDock); if (system) { if (m_view->itemDelegate() != m_systemDelegate) { m_themedDelegate = m_view->itemDelegate(); m_view->setItemDelegate(m_systemDelegate); } const QPalette palette = MenuStyle::systemComboPopupPalette(m_comboBox); m_nativeView.restore(m_view, palette); m_nativeViewport.restore(m_view->viewport(), palette); if (m_popupWindow != nullptr) m_nativePopup.restore(m_popupWindow, palette); for (QScrollBar* bar : {m_view->verticalScrollBar(), m_view->horizontalScrollBar()}) { if (!bar->styleSheet().isEmpty()) bar->setStyleSheet(QString()); bar->setPalette(MenuStyle::systemPalette(bar)); } return; } const QString viewStyle = m_popupTheme.viewStyle + m_popupTheme.scrollBarStyle; if (m_view->styleSheet() != viewStyle) m_view->setStyleSheet(viewStyle); m_view->setPalette(m_popupTheme.palette); m_view->viewport()->setPalette(m_popupTheme.palette); for (QScrollBar* bar : {m_view->verticalScrollBar(), m_view->horizontalScrollBar()}) { if (bar->styleSheet() != m_popupTheme.scrollBarStyle) bar->setStyleSheet(m_popupTheme.scrollBarStyle); bar->setPalette(m_popupTheme.palette); } removeFrame(m_view); m_view->setAutoFillBackground(false); m_view->viewport()->setAutoFillBackground(false); m_view->viewport()->setAttribute(Qt::WA_StyledBackground, true); QWidget* popupChrome = popupChromeWidget(); if (popupChrome == nullptr) return; removeFrame(popupChrome); popupChrome->setAutoFillBackground(false); popupChrome->setAttribute(Qt::WA_StyledBackground, true); if (popupChrome != m_view) { popupChrome->setObjectName(QStringLiteral("speedcrunchDockComboBoxPopupChrome")); const QString style = QStringLiteral( "QWidget#speedcrunchDockComboBoxPopupChrome," "QFrame#speedcrunchDockComboBoxPopupChrome {" " background: transparent; border: 0;" "}"); if (popupChrome->styleSheet() != style) popupChrome->setStyleSheet(style); } applyRoundedMask(popupChrome); } void DockComboBoxChevron::NativeSurface::capture(QWidget* widget) { if (auto* frame = qobject_cast(widget)) { shape = frame->frameShape(); shadow = frame->frameShadow(); lineWidth = frame->lineWidth(); midLineWidth = frame->midLineWidth(); } autoFill = widget->autoFillBackground(); styledBackground = widget->testAttribute(Qt::WA_StyledBackground); mask = widget->mask(); styleSheet = widget->styleSheet(); } void DockComboBoxChevron::NativeSurface::restore(QWidget* widget, const QPalette& palette) const { if (widget->styleSheet() != styleSheet) widget->setStyleSheet(styleSheet); if (auto* frame = qobject_cast(widget)) { frame->setFrameShape(shape); frame->setFrameShadow(shadow); frame->setLineWidth(lineWidth); frame->setMidLineWidth(midLineWidth); } widget->setPalette(palette); widget->setAutoFillBackground(autoFill); widget->setAttribute(Qt::WA_StyledBackground, styledBackground); if (mask.isEmpty()) widget->clearMask(); else widget->setMask(mask); } void DockComboBoxChevron::setPopupOpen(bool open) { if (open) stylePopupChrome(); if (m_popupOpen == open && m_animation->state() != QAbstractAnimation::Running) return; m_popupOpen = open; m_animation->stop(); m_animation->setStartValue(m_rotation); m_animation->setEndValue(open ? 180.0 : 0.0); m_animation->start(); } heldercorreia-speedcrunch-e7ca37f/src/gui/dockcomboboxchevron.h000066400000000000000000000045341526573132500251250ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_DOCKCOMBOBOXCHEVRON_H #define GUI_DOCKCOMBOBOXCHEVRON_H #include #include #include #include #include #include class QAbstractItemView; class QAbstractItemDelegate; class QComboBox; class QEvent; class QPaintEvent; class QVariantAnimation; class DockComboBoxChevron : public QWidget { public: struct PopupTheme { QString buttonStyle; QString viewStyle; QString scrollBarStyle; QPalette palette; }; static constexpr int IndicatorWidth = 28; explicit DockComboBoxChevron(QComboBox* comboBox); static void apply(QComboBox* comboBox, const QColor& textColor, const QColor& outlineColor, const PopupTheme& popupTheme); static void refreshPopupAppearance(QComboBox* comboBox); static void applySystemAppearance(QComboBox* comboBox); void setColors(QColor chevronColor, const QColor& outlineColor); void refresh(); protected: bool eventFilter(QObject* watched, QEvent* event) override; void paintEvent(QPaintEvent* event) override; private: struct NativeSurface { QFrame::Shape shape = QFrame::NoFrame; QFrame::Shadow shadow = QFrame::Plain; int lineWidth = 0; int midLineWidth = 0; bool autoFill = false; bool styledBackground = false; QRegion mask; QString styleSheet; void capture(QWidget* widget); void restore(QWidget* widget, const QPalette& palette) const; }; void installPopupEventFilters(); QWidget* popupChromeWidget() const; void reposition(); void stylePopupChrome(); void setPopupOpen(bool open); QPointer m_comboBox; QPointer m_view; QPointer m_popupWindow; QPointer m_themedDelegate; QPointer m_systemDelegate; QVariantAnimation* m_animation; QColor m_chevronColor; QColor m_outlineColor; PopupTheme m_popupTheme; QString m_nativeButtonStyle; NativeSurface m_nativeView; NativeSurface m_nativeViewport; NativeSurface m_nativePopup; bool m_stylingPopup = false; qreal m_rotation = 0.0; bool m_popupOpen = false; }; #endif // GUI_DOCKCOMBOBOXCHEVRON_H heldercorreia-speedcrunch-e7ca37f/src/gui/dockliststyle.cpp000066400000000000000000000247131526573132500243200ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/dockliststyle.h" #include "core/settings.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { QColor hoverColorForView(const QAbstractItemView* view) { const QColor themedHover = view->property("dockListHoverBackground").value(); if (themedHover.isValid()) return themedHover; const QPalette palette = view->palette(); const QColor base = palette.color(QPalette::Base); QColor hover = palette.color(QPalette::Highlight); if (hover == base) hover = base.lightness() < 128 ? base.lighter(135) : base.darker(108); return hover; } QColor hoverTextColorForView(const QAbstractItemView* view) { const QColor themedText = view->property("dockListHoverForeground").value(); if (themedText.isValid()) return themedText; const QPalette palette = view->palette(); const QColor text = palette.color(QPalette::HighlightedText); return text.isValid() ? text : palette.color(QPalette::Text); } QColor selectedColorForView(const QAbstractItemView* view) { const QColor themedSelection = view->property( view->hasFocus() ? "dockListActiveSelectionBackground" : "dockListInactiveSelectionBackground").value(); if (themedSelection.isValid()) return themedSelection; return view->palette().color(QPalette::Highlight); } QColor selectedTextColorForView(const QAbstractItemView* view) { const QColor themedText = view->property( view->hasFocus() ? "dockListActiveSelectionForeground" : "dockListInactiveSelectionForeground").value(); if (themedText.isValid()) return themedText; return view->palette().color(QPalette::HighlightedText); } bool columnIsHidden(const QAbstractItemView* view, int column) { const QTreeView* treeView = qobject_cast(view); return treeView != nullptr && treeView->isColumnHidden(column); } QVector visibleColumnsForIndex(const QAbstractItemView* view, const QModelIndex& index) { QVector columns; const QAbstractItemModel* model = view->model(); if (model == nullptr) return columns; const int columnCount = model->columnCount(index.parent()); const QTreeView* treeView = qobject_cast(view); const QHeaderView* header = treeView != nullptr ? treeView->header() : nullptr; if (header != nullptr && header->count() == columnCount) { for (int visualIndex = 0; visualIndex < header->count(); ++visualIndex) { const int column = header->logicalIndex(visualIndex); if (!columnIsHidden(view, column)) columns.append(column); } return columns; } for (int column = 0; column < columnCount; ++column) { if (!columnIsHidden(view, column)) columns.append(column); } return columns; } QRect rowRectForIndex(const QAbstractItemView* view, const QModelIndex& index) { QRect rowRect; for (const int column : visibleColumnsForIndex(view, index)) { const QRect cellRect = view->visualRect(index.sibling(index.row(), column)); if (!cellRect.isEmpty()) rowRect = rowRect.united(cellRect); } if (rowRect.isEmpty()) rowRect = view->visualRect(index); return rowRect; } bool isFirstVisibleColumnForIndex(const QAbstractItemView* view, const QModelIndex& index) { const QVector columns = visibleColumnsForIndex(view, index); if (columns.isEmpty()) return index.column() == 0; return index.column() == columns.first(); } void fillRoundedRow(QPainter* painter, const QRect& rowRect, const QColor& color) { if (rowRect.isEmpty()) return; painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(Qt::NoPen); painter->setBrush(color); painter->drawRoundedRect(QRectF(rowRect).adjusted(1.0, 1.0, -1.0, -1.0), UiConfig::DockHoveredItemCornerRadius, UiConfig::DockHoveredItemCornerRadius); painter->restore(); } class DockListItemDelegate : public QStyledItemDelegate { public: explicit DockListItemDelegate(QAbstractItemView* view) : QStyledItemDelegate(view) , m_view(view) { } void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { if (Settings::instance()->dockAppearance == Settings::DockAppearanceSystem) { QStyledItemDelegate::paint(painter, option, index); return; } QStyleOptionViewItem opt(option); initStyleOption(&opt, index); const bool selected = opt.state & QStyle::State_Selected; if (selected) { painter->save(); painter->fillRect(opt.rect, selectedColorForView(m_view)); painter->restore(); opt.palette.setColor(QPalette::Text, selectedTextColorForView(m_view)); opt.palette.setColor(QPalette::WindowText, selectedTextColorForView(m_view)); opt.palette.setColor(QPalette::HighlightedText, selectedTextColorForView(m_view)); opt.backgroundBrush = Qt::NoBrush; // The selected fill is painted above; suppress style hover/focus backgrounds. opt.state &= ~(QStyle::State_Selected | QStyle::State_MouseOver | QStyle::State_HasFocus); } else if (index.row() == m_view->property("dockListHoveredRow").toInt()) { if (isFirstVisibleColumnForIndex(m_view, index)) fillRoundedRow(painter, rowRectForIndex(m_view, index), hoverColorForView(m_view)); opt.palette.setColor(QPalette::Text, hoverTextColorForView(m_view)); opt.palette.setColor(QPalette::WindowText, hoverTextColorForView(m_view)); opt.backgroundBrush = Qt::NoBrush; opt.state &= ~QStyle::State_MouseOver; } QStyledItemDelegate::paint(painter, opt, index); } private: QAbstractItemView* m_view; }; class DockListCursorFilter : public QObject { public: explicit DockListCursorFilter(QAbstractItemView* view) : QObject(view) , m_view(view) { } protected: bool eventFilter(QObject* watched, QEvent* event) override { if (watched == m_view) { if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) m_view->viewport()->update(); return QObject::eventFilter(watched, event); } if (watched != m_view->viewport()) return QObject::eventFilter(watched, event); if (event->type() == QEvent::MouseMove) { const QMouseEvent* mouseEvent = static_cast(event); updateHoveredIndex(m_view->indexAt(mouseEvent->pos())); } else if (event->type() == QEvent::HoverMove) { const QHoverEvent* hoverEvent = static_cast(event); updateHoveredIndex(m_view->indexAt(hoverEvent->position().toPoint())); } else if (event->type() == QEvent::Leave || event->type() == QEvent::HoverLeave) { updateHoveredIndex(QModelIndex()); m_view->viewport()->setCursor(Qt::ArrowCursor); } else if (event->type() == QEvent::Resize) { const QList labels = m_view->viewport()->findChildren( QString(), Qt::FindDirectChildrenOnly); for (QLabel* label : labels) { if (label->property("dockListNoMatchLabel").toBool() && label->isVisible()) label->setGeometry(m_view->viewport()->rect()); } } return QObject::eventFilter(watched, event); } private: void updateHoveredIndex(const QModelIndex& hoveredIndex) { const int previousHoveredRow = m_view->property("dockListHoveredRow").toInt(); const int hoveredRow = hoveredIndex.isValid() ? hoveredIndex.row() : -1; if (hoveredRow != previousHoveredRow) { m_view->setProperty("dockListHoveredRow", hoveredRow); updateRow(previousHoveredRow); updateRow(hoveredRow); } m_view->viewport()->setCursor( hoveredIndex.isValid() ? Qt::PointingHandCursor : Qt::ArrowCursor); } void updateRow(int row) { if (row < 0 || !m_view->model()) return; const QModelIndex rowIndex = m_view->model()->index(row, 0, m_view->rootIndex()); const QRect rowRect = rowRectForIndex(m_view, rowIndex); if (!rowRect.isEmpty()) m_view->viewport()->update(rowRect.adjusted(-2, -2, 2, 2)); } QAbstractItemView* m_view; }; } // namespace namespace DockListStyle { void apply(QAbstractItemView* view) { // The dock already provides a boundary around its content. view->setFrameShape(QFrame::NoFrame); view->setAlternatingRowColors(false); view->setMouseTracking(true); view->viewport()->setMouseTracking(true); view->viewport()->setAttribute(Qt::WA_Hover, true); view->viewport()->setCursor(Qt::ArrowCursor); view->setProperty("dockListHoveredRow", -1); view->setItemDelegate(new DockListItemDelegate(view)); DockListCursorFilter* cursorFilter = new DockListCursorFilter(view); view->installEventFilter(cursorFilter); view->viewport()->installEventFilter(cursorFilter); } void showCenteredNoMatchLabel(QAbstractItemView* view, QLabel* label) { if (label->parentWidget() != view->viewport()) label->setParent(view->viewport()); const QColor foreground = view->palette().color(QPalette::Text); QPalette palette = label->palette(); palette.setColor(QPalette::WindowText, foreground); palette.setColor(QPalette::Text, foreground); label->setPalette(palette); label->setStyleSheet(QStringLiteral("QLabel { background: transparent; color: %1; }") .arg(foreground.name())); label->setProperty("dockListNoMatchLabel", true); label->setAttribute(Qt::WA_TransparentForMouseEvents); label->setGeometry(view->viewport()->rect()); label->show(); label->raise(); } } // namespace DockListStyle heldercorreia-speedcrunch-e7ca37f/src/gui/dockliststyle.h000066400000000000000000000006121526573132500237550ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_DOCKLISTSTYLE_H #define GUI_DOCKLISTSTYLE_H class QAbstractItemView; class QLabel; namespace DockListStyle { void apply(QAbstractItemView* view); void showCenteredNoMatchLabel(QAbstractItemView* view, QLabel* label); } // namespace DockListStyle #endif // GUI_DOCKLISTSTYLE_H heldercorreia-speedcrunch-e7ca37f/src/gui/dockwidget.h000066400000000000000000000045101526573132500232050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_DOCKWIDGET_H #define GUI_DOCKWIDGET_H #include #include #include #include #include #include class DockWidget : public QDockWidget { public: using QDockWidget::QDockWidget; protected: bool event(QEvent* event) override { if ((event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) && isFloating() && titleBarWidget() == nullptr && usesWaylandWindowMoves()) { auto* mouseEvent = static_cast(event); QStyleOptionDockWidget option; initStyleOption(&option); const QPoint pos = mouseEvent->position().toPoint(); bool onButton = false; for (const auto* button : findChildren( QString(), Qt::FindDirectChildrenOnly)) { if (button->isVisible() && button->geometry().contains(pos)) { onButton = true; break; } } if (mouseEvent->button() == Qt::LeftButton && option.rect.contains(pos) && !onButton) { if (event->type() == QEvent::MouseButtonDblClick) { if (features().testFlag(DockWidgetFloatable)) setFloating(false); mouseEvent->accept(); return true; } // Wayland owns window positions. Ask the compositor to move // the dock while this press still supplies a valid input serial. startWindowMove(); // Even a rejected move must not enter Qt's dock drag path, // which tries an unsupported mouse grab and QWidget::move(). mouseEvent->accept(); return true; } } return QDockWidget::event(event); } virtual bool usesWaylandWindowMoves() const { return QGuiApplication::platformName().startsWith(QLatin1String("wayland")); } virtual void startWindowMove() { if (QWindow* handle = windowHandle()) handle->startSystemMove(); } }; #endif // GUI_DOCKWIDGET_H heldercorreia-speedcrunch-e7ca37f/src/gui/editor.cpp000066400000000000000000006064631526573132500227210ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2012-2019, 2021, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/editor.h" #include "gui/constantbrowserutils.h" #include "gui/dockliststyle.h" #include "gui/themedlineedit.h" #include "gui/lineeditstyleutils.h" #include "gui/startupappearance.h" #include "gui/displayformatutils.h" #include "gui/editorutils.h" #include "gui/functiontooltiputils.h" #include "gui/oklchutils.h" #include "gui/resultlineformatutils.h" #include "gui/syntaxhighlighter.h" #include "gui/tooltipstyleutils.h" #include "gui/uiconfig.h" #include "core/constants.h" #include "core/evaluator.h" #include "core/functions.h" #include "core/numberformatter.h" #include "core/regexpatterns.h" #include "core/settings.h" #include "core/unitdisplayformat.h" #include "core/session.h" #include "core/unicodechars.h" #include "core/units.h" #include "core/mathdsl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include constexpr int kEditorOuterLeft = UiConfig::ModernEditorHorizontalMargin; constexpr int kEditorOuterTop = UiConfig::ModernEditorTopMargin; constexpr int kEditorOuterRight = UiConfig::ModernEditorHorizontalMargin; constexpr int kEditorOuterBottom = UiConfig::ModernEditorBottomMargin; constexpr int kEditorHorizontalPadding = UiConfig::ModernEditorHorizontalPadding; constexpr int kEditorVerticalPadding = UiConfig::ModernEditorVerticalPadding; constexpr int kEditorRadius = UiConfig::ModernEditorCornerRadius; constexpr int kEditorCursorWidth = 2; constexpr int kEditorDocumentMargin = 2; constexpr int kClassicEditorHorizontalPadding = UiConfig::ClassicTextInset - kEditorDocumentMargin; static QPointer s_completionMouseSelectionOwner; static bool usesWaylandCompletionPositioner() { // Qt's xdg-shell anchor overrides are available starting with Qt 6.6. return QGuiApplication::platformName().startsWith(QLatin1String("wayland")) && QVersionNumber::fromString(QString::fromLatin1(qVersion())) >= QVersionNumber(6, 6); } template class CompletionPopup : public Widget { public: explicit CompletionPopup(QWidget* parent = nullptr) : Widget(parent) {} void setPlacementAnchor(const QRect& anchor, const QSize& requestedSize, int cornerRadius) { // Older xdg-shell versions cannot reposition a mapped popup. Remap it // when its anchor or requested size changes so every supported Qt and // compositor uses the new positioner. if (usesWaylandCompletionPositioner() && this->isVisible() && (anchor != m_anchor || requestedSize != m_requestedSize)) { this->hide(); } m_anchor = anchor; m_requestedSize = requestedSize; m_cornerRadius = cornerRadius; configurePositioner(); } protected: void showEvent(QShowEvent* event) override { // show() creates the QWindow before this event and maps it afterwards. // Configure the first native surface here without forcing winId(). configurePositioner(); Widget::showEvent(event); } void resizeEvent(QResizeEvent* event) override { Widget::resizeEvent(event); ToolTipStyleUtils::applyRoundedPopupMask(this, m_cornerRadius); } private: void configurePositioner() { if (QWindow* window = this->windowHandle()) { // Qt's Wayland backend consumes these overrides; other platforms // ignore them. Keep the anchor in the transient parent's coordinates. window->setProperty("_q_waylandPopupAnchorRect", m_anchor); window->setProperty("_q_waylandPopupAnchor", QVariant::fromValue(Qt::Edges(Qt::BottomEdge | Qt::LeftEdge))); window->setProperty("_q_waylandPopupGravity", QVariant::fromValue(Qt::Edges(Qt::BottomEdge | Qt::RightEdge))); // xdg_positioner: slide_x = 1, flip_y = 8, resize_y = 32. // Vertical sliding would move the popup across the editor. Flipping // around its full height keeps the popup wholly below or above it. window->setProperty("_q_waylandPopupConstraintAdjustment", uint(1 | 8 | 32)); } } QRect m_anchor; QSize m_requestedSize; int m_cornerRadius = 0; }; static void updateCompletionTransientParent(QWidget* popup, Editor* editor) { // Let show() create the native popup normally. Calling winId() here sets // WA_NativeWindow and forces the editor's viewport/scrollbars into native // sibling windows, disrupting their backing-store composition on Wayland. // Existing popups still need their transient parent refreshed after a pane // moves between windows. if (QWindow* window = popup->windowHandle()) { QWindow* parent = editor->window()->windowHandle(); if (window->transientParent() != parent) { popup->hide(); window->setTransientParent(parent); } } } static QRect completionPopupGeometry(Editor* editor, const QTextCursor& cursor, const QSize& size) { // cursorRect includes wrapping, scrolling, text direction and text margins; // measuring the whole text prefix does not describe its visible position. const int x = editor->viewport()->mapToGlobal(editor->cursorRect(cursor).topLeft()).x(); const QRect editorRect(editor->mapToGlobal(QPoint(0, 0)), editor->size()); QRect bounds = editor->screen()->availableGeometry(); if (usesWaylandCompletionPositioner()) { // Global top-level positions on Wayland are guesses. Request placement // below the editor and let xdg-shell flip it using the real screen space. return EditorUtils::completionPopupCompositorGeometry( EditorUtils::completionPopupAnchorRect(editorRect, x), size, bounds.size()); } if (QGuiApplication::platformName().startsWith(QLatin1String("wayland")) && editor->window() != editor) { // Wayland reports no reliable global position for the containing window. // Keep the popup inside its client area, whose coordinates are known, // so the compositor does not slide a screen-constrained popup over input. QWidget* window = editor->window(); bounds = QRect(window->mapToGlobal(QPoint(0, 0)), window->size()); } return EditorUtils::completionPopupGeometry(editorRect, x, size, bounds); } template static void prepareCompletionPopup(Widget* popup, Editor* editor, const QTextCursor& cursor, const QSize& size, int cornerRadius) { updateCompletionTransientParent(popup, editor); QWidget* parent = editor->window(); const QRect editorRect(editor->mapTo(parent, QPoint(0, 0)), editor->size()); const int anchorX = editor->viewport()->mapTo(parent, editor->cursorRect(cursor).topLeft()).x(); static_cast*>(popup)->setPlacementAnchor( EditorUtils::completionPopupAnchorRect(editorRect, anchorX), size, cornerRadius); } static int editorVerticalDecorationHeight() { if (Settings::instance()->editorDisplayStyle == Settings::EditorDisplayClassic) return 2 * (kEditorDocumentMargin + UiConfig::ClassicEditorVerticalPadding) + UiConfig::OutlineStrokeWidth; return kEditorOuterTop + kEditorOuterBottom + 2 * kEditorVerticalPadding + 2 * kEditorDocumentMargin + 2 * UiConfig::OutlineStrokeWidth; } static int editorLineHeight(const QFont& font) { // QPlainTextEdit advances each line by a whole-pixel height. Integer font // metrics can round down and leave too little space below the text. return int(std::ceil(QFontMetricsF(font).height())); } static QColor editorFillColorForThemeBackground(const QColor& background) { const int factor = 115; return background.lightnessF() < 0.5 ? background.lighter(factor) : background.darker(factor); } static void moveCursorToEnd(Editor* editor) { QTextCursor cursor = editor->textCursor(); cursor.movePosition(QTextCursor::EndOfBlock); editor->setTextCursor(cursor); } static bool isOperatorOnlyIncompleteInput(const QString& expression) { const QString trimmed = expression.trimmed(); if (trimmed.isEmpty()) return false; bool sawOperator = false; for (int i = 0; i < trimmed.size(); ++i) { const QChar ch = trimmed.at(i); if (ch.isSpace()) continue; if (ch == MathDsl::AddOp || MathDsl::isSubtractionOperatorAlias(ch)) { sawOperator = true; continue; } return false; } return sawOperator; } class EditorCompletionPopup : public CompletionPopup { public: explicit EditorCompletionPopup(QWidget* parent = nullptr) : CompletionPopup(parent) { viewport()->installEventFilter(this); } protected: bool event(QEvent* event) override { if (event->type() == QEvent::Wheel) { scrollByWheelEvent(static_cast(event)); return true; } return QTreeWidget::event(event); } bool eventFilter(QObject* object, QEvent* event) override { if (object == viewport() && event->type() == QEvent::Wheel) { scrollByWheelEvent(static_cast(event)); return true; } return QTreeWidget::eventFilter(object, event); } void wheelEvent(QWheelEvent* event) override { scrollByWheelEvent(event); } bool viewportEvent(QEvent* event) override { if (event->type() == QEvent::Wheel) { scrollByWheelEvent(static_cast(event)); return true; } return QTreeWidget::viewportEvent(event); } private: void scrollByWheelEvent(QWheelEvent* event) { const int delta = event->angleDelta().y() != 0 ? event->angleDelta().y() : event->pixelDelta().y(); if (delta == 0) { event->ignore(); return; } QScrollBar* scrollBar = verticalScrollBar(); scrollBar->setValue(scrollBar->value() - delta / 8); event->accept(); } }; static QString normalizeExpressionTypedInEditor(QString text) { return EditorUtils::normalizeExpressionOperatorsForEditorInput(text); } static bool isInsideUnmatchedSquareBracketContext(const QString& text, int cursorPosition) { int squareBracketDepth = 0; const int safeCursorPosition = qBound(0, cursorPosition, text.size()); for (int i = 0; i < safeCursorPosition; ++i) { const QChar ch = text.at(i); if (ch == MathDsl::UnitStart) { ++squareBracketDepth; continue; } if (ch == MathDsl::UnitEnd && squareBracketDepth > 0) --squareBracketDepth; } return squareBracketDepth > 0; } static bool isTypedMultiplicationCharacter(const QChar& ch) { return MathDsl::isMultiplicationOperator(ch) || MathDsl::isMultiplicationOperatorAlias(ch, true); } static bool isGroupedSpacedOperator(QChar leftSpace, QChar sign, QChar rightSpace) { const auto matches = [leftSpace, sign, rightSpace](QChar expectedSpace, QChar expectedSign) { return leftSpace == expectedSpace && sign == expectedSign && rightSpace == expectedSpace; }; return matches(MathDsl::MulDotWrapSp, MathDsl::MulDotOp) || matches(MathDsl::MulCrossWrapSp, MathDsl::MulCrossOp) || matches(MathDsl::AddWrap, MathDsl::AddOp) || matches(MathDsl::SubWrapSp, MathDsl::SubOp) || matches(MathDsl::DivWrap, MathDsl::DivOp) || matches(QLatin1Char(' '), MathDsl::Equals) || matches(MathDsl::SubWrapSp, MathDsl::TransOp) || matches(QLatin1Char(' '), MathDsl::CommentSep); } static QString wrappedShiftLeftToken() { return MathDsl::buildWrappedToken(MathDsl::ShiftLeftOp); } static QString wrappedShiftRightToken() { return MathDsl::buildWrappedToken(MathDsl::ShiftRightOp); } static bool isAfterGroupedSpacedOperator(const QString& text, int cursorPosition) { if (cursorPosition > text.size()) return false; const QString shiftLeft = wrappedShiftLeftToken(); const QString shiftRight = wrappedShiftRightToken(); if (cursorPosition >= shiftLeft.size() && text.mid(cursorPosition - shiftLeft.size(), shiftLeft.size()) == shiftLeft) { return true; } if (cursorPosition >= shiftRight.size() && text.mid(cursorPosition - shiftRight.size(), shiftRight.size()) == shiftRight) { return true; } if (cursorPosition < 3) return false; const QChar leftSpace = text.at(cursorPosition - 3); const QChar sign = text.at(cursorPosition - 2); const QChar rightSpace = text.at(cursorPosition - 1); // Keep display-formatted binary operators atomic for Backspace when the // cursor is exactly after "". return isGroupedSpacedOperator(leftSpace, sign, rightSpace); } static bool isBeforeGroupedSpacedOperator(const QString& text, int cursorPosition) { if (cursorPosition < 0 || cursorPosition > text.size()) return false; const QString shiftLeft = wrappedShiftLeftToken(); const QString shiftRight = wrappedShiftRightToken(); if (cursorPosition + shiftLeft.size() <= text.size() && text.mid(cursorPosition, shiftLeft.size()) == shiftLeft) { return true; } if (cursorPosition + shiftRight.size() <= text.size() && text.mid(cursorPosition, shiftRight.size()) == shiftRight) { return true; } if (cursorPosition + 3 > text.size()) return false; const QChar leftSpace = text.at(cursorPosition); const QChar sign = text.at(cursorPosition + 1); const QChar rightSpace = text.at(cursorPosition + 2); return isGroupedSpacedOperator(leftSpace, sign, rightSpace); } static int groupedSpacedOperatorStartAround(const QString& text, int cursorPosition) { // Detect whether the cursor is currently at/inside a grouped // "" triplet and return its first index. // We probe up to two chars to the left so positions on the sign or // right-space are still recognized as belonging to the same group. if (isBeforeGroupedSpacedOperator(text, cursorPosition)) return cursorPosition; if (cursorPosition > 0 && isBeforeGroupedSpacedOperator(text, cursorPosition - 1)) return cursorPosition - 1; if (cursorPosition > 1 && isBeforeGroupedSpacedOperator(text, cursorPosition - 2)) return cursorPosition - 2; if (cursorPosition > 2 && isBeforeGroupedSpacedOperator(text, cursorPosition - 3)) return cursorPosition - 3; return -1; } static bool isLeadingQuestionCommentToken(const QString& text) { return text.size() >= 2 && text.at(0) == MathDsl::CommentSep && text.at(1) == QLatin1Char(' '); } static int groupedTokenLengthBefore(const QString& text, int cursorPosition) { const QString shiftLeft = wrappedShiftLeftToken(); const QString shiftRight = wrappedShiftRightToken(); if (cursorPosition >= shiftLeft.size() && cursorPosition <= text.size() && text.mid(cursorPosition - shiftLeft.size(), shiftLeft.size()) == shiftLeft) { return shiftLeft.size(); } if (cursorPosition >= shiftRight.size() && cursorPosition <= text.size() && text.mid(cursorPosition - shiftRight.size(), shiftRight.size()) == shiftRight) { return shiftRight.size(); } if (isAfterGroupedSpacedOperator(text, cursorPosition)) return 3; if (cursorPosition >= 2 && cursorPosition <= text.size() && cursorPosition - 2 == 0 && isLeadingQuestionCommentToken(text)) { return 2; } return 0; } static int groupedTokenLengthAfter(const QString& text, int cursorPosition) { const QString shiftLeft = wrappedShiftLeftToken(); const QString shiftRight = wrappedShiftRightToken(); if (cursorPosition >= 0 && cursorPosition + shiftLeft.size() <= text.size() && text.mid(cursorPosition, shiftLeft.size()) == shiftLeft) { return shiftLeft.size(); } if (cursorPosition >= 0 && cursorPosition + shiftRight.size() <= text.size() && text.mid(cursorPosition, shiftRight.size()) == shiftRight) { return shiftRight.size(); } if (isBeforeGroupedSpacedOperator(text, cursorPosition)) return 3; if (cursorPosition == 0 && isLeadingQuestionCommentToken(text)) return 2; return 0; } static int groupedTokenStartAround(const QString& text, int cursorPosition, int* tokenLength) { const QString shiftLeft = wrappedShiftLeftToken(); const QString shiftRight = wrappedShiftRightToken(); for (int delta = 0; delta <= 3; ++delta) { const int start = cursorPosition - delta; if (start < 0) continue; if (start + shiftLeft.size() <= text.size() && text.mid(start, shiftLeft.size()) == shiftLeft) { if (tokenLength) *tokenLength = shiftLeft.size(); return start; } if (start + shiftRight.size() <= text.size() && text.mid(start, shiftRight.size()) == shiftRight) { if (tokenLength) *tokenLength = shiftRight.size(); return start; } } const int tripletStart = groupedSpacedOperatorStartAround(text, cursorPosition); if (tripletStart >= 0) { if (tokenLength) *tokenLength = 3; return tripletStart; } if (isLeadingQuestionCommentToken(text) && cursorPosition >= 0 && cursorPosition <= 2) { if (tokenLength) *tokenLength = 2; return 0; } return -1; } static bool isRightOfOpeningSquareBracketWithOnlySpaces(const QString& text, int cursorPosition) { int i = qBound(0, cursorPosition, text.size()) - 1; while (i >= 0 && text.at(i).isSpace()) --i; return i >= 0 && text.at(i) == MathDsl::UnitStart; } static bool isCurrentUnitContextEmptyOrOnlySpaces(const QString& text, int cursorPosition) { const int safeCursor = qBound(0, cursorPosition, text.size()); int depth = 0; int openPos = -1; for (int i = 0; i < safeCursor; ++i) { const QChar ch = text.at(i); if (ch == MathDsl::UnitStart) { ++depth; openPos = i; } else if (ch == MathDsl::UnitEnd && depth > 0) { --depth; if (depth == 0) openPos = -1; } } if (depth <= 0 || openPos < 0) return false; for (int i = openPos + 1; i < safeCursor; ++i) { if (!text.at(i).isSpace()) return false; } return true; } static bool hasOnlySpacesToRight(const QString& text, int cursorPosition) { const int safeCursor = qBound(0, cursorPosition, text.size()); for (int i = safeCursor; i < text.size(); ++i) { if (!text.at(i).isSpace()) return false; } return true; } static bool isAnyOperatorKey(int key) { return key == Qt::Key_Plus || key == Qt::Key_Minus || key == Qt::Key_Asterisk || key == Qt::Key_Slash || key == Qt::Key_division || key == Qt::Key_Percent || key == Qt::Key_AsciiCircum || key == Qt::Key_Ampersand || key == Qt::Key_Bar || key == Qt::Key_Equal || key == Qt::Key_Less || key == Qt::Key_Greater; } static bool isAnyMultiplicationOperator(const QChar& ch) { return ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp || MathDsl::isMultiplicationOperatorAlias(ch, true); } static bool isAnyAdditionOperator(const QChar& ch) { // Treat both normalized '+' and accepted plus aliases as one operator // class for insertion guards (prevents consecutive plus insertion). return ch == MathDsl::AddOp || MathDsl::isAdditionOperatorAlias(ch); } static QChar normalizedTypedCharFromEvent(const QKeyEvent* event, const QString& normalizedEventText) { // Editing keys can carry text (e.g. Backspace's U+0008), but must not // enter the character-insertion rules. Unknown keys may carry symbols // from keyboard layouts, so keep accepting their printable payloads. if ((event->key() >= Qt::Key_Escape && event->key() != Qt::Key_unknown) || (!event->text().isEmpty() && !event->text().at(0).isPrint())) { return QChar(); } if (normalizedEventText.size() == 1) return normalizedEventText.at(0); if (event->text().size() == 1) { const QChar raw = event->text().at(0); if (MathDsl::isAdditionOperatorAlias(raw)) return MathDsl::AddOp; if (MathDsl::isSubtractionOperatorAlias(raw)) return MathDsl::SubOp; if (MathDsl::isDivisionOperatorAlias(raw)) return MathDsl::DivOp; if (MathDsl::isMultiplicationOperatorAlias(raw, true)) return raw == MathDsl::MulDotOp ? MathDsl::MulDotOp : MathDsl::MulCrossOp; return raw; } switch (event->key()) { case Qt::Key_Plus: return MathDsl::AddOp; case Qt::Key_Equal: return MathDsl::Equals; case Qt::Key_Minus: return MathDsl::SubOp; case Qt::Key_Slash: return MathDsl::DivOp; case Qt::Key_Asterisk: return MathDsl::MulCrossOp; case Qt::Key_AsciiCircum: return MathDsl::PowOp; case Qt::Key_ParenLeft: return MathDsl::GroupStart; default: return QChar(); } } static void replacePreviousOperatorAtCursorWithCaret(Editor* editor) { QTextCursor cursor = editor->textCursor(); const QString text = editor->text(); const int pos = cursor.position(); if (pos <= 0) return; int signPos = pos - 1; while (signPos >= 0 && text.at(signPos).isSpace()) --signPos; if (signPos < 0 || !isAnyMultiplicationOperator(text.at(signPos))) return; int start = signPos; int end = signPos + 1; if (signPos > 0 && text.at(signPos - 1).isSpace()) start = signPos - 1; if (signPos + 1 < pos && text.at(signPos + 1).isSpace()) end = signPos + 2; cursor.setPosition(start); cursor.setPosition(end, QTextCursor::KeepAnchor); cursor.removeSelectedText(); cursor.insertText(QString::fromUtf8("^")); editor->setTextCursor(cursor); } static void replacePreviousSubtractionAtCursorWithUnitConversion(Editor* editor) { QTextCursor cursor = editor->textCursor(); const QString text = editor->text(); const int pos = cursor.position(); if (pos <= 0) return; int signPos = pos - 1; while (signPos >= 0 && text.at(signPos).isSpace()) --signPos; if (signPos < 0 || !MathDsl::isSubtractionOperatorAlias(text.at(signPos))) return; int start = signPos; int end = signPos + 1; if (signPos > 0 && text.at(signPos - 1).isSpace()) start = signPos - 1; if (signPos + 1 < pos && text.at(signPos + 1).isSpace()) end = signPos + 2; cursor.setPosition(start); cursor.setPosition(end, QTextCursor::KeepAnchor); cursor.removeSelectedText(); const QString insertion = MathDsl::buildWrappedToken(MathDsl::TransOp, MathDsl::SubWrapSp) + QStringLiteral("[]"); cursor.insertText(insertion); cursor.setPosition(start + insertion.size() - 1); editor->setTextCursor(cursor); } static bool canEndUnitConversionLeftOperand(const QChar& ch) { return ch.isLetterOrNumber() || ch == MathDsl::GroupEnd || ch == MathDsl::UnitEnd || ch == MathDsl::Deg || ch == UnicodeChars::MasculineOrdinalIndicator || ch == UnicodeChars::Prime || ch == UnicodeChars::DoublePrime; } static bool isBlockingBinaryOperator(const QChar& ch) { return isAnyAdditionOperator(ch) || MathDsl::isSubtractionOperatorAlias(ch) || MathDsl::isDivisionOperatorAlias(ch) || isAnyMultiplicationOperator(ch) || ch == MathDsl::PowOp || ch == MathDsl::PercentOp || ch == MathDsl::BitAndOp || ch == MathDsl::BitOrOp || ch == MathDsl::Equals || ch == MathDsl::LessThanOp || ch == MathDsl::GreaterThanOp; } static void insertUnitConversionAtCursorWithUnitPlaceholder(Editor* editor) { QTextCursor cursor = editor->textCursor(); const int start = cursor.position(); QString insertion = MathDsl::buildWrappedToken(MathDsl::TransOp, MathDsl::SubWrapSp) + QStringLiteral("[]"); if (start > 0 && editor->text().at(start - 1).isSpace() && insertion.at(0).isSpace()) insertion.remove(0, 1); cursor.insertText(insertion); cursor.setPosition(start + insertion.size() - 1); editor->setTextCursor(cursor); } static bool textContainsOnlyAdditionAliases(const QString& text) { if (text.isEmpty()) return false; for (const QChar ch : text) { if (!MathDsl::isAdditionOperatorAlias(ch)) return false; } return true; } static bool isCaretOperatorAlias(const QChar& ch) { // Caret may arrive as ASCII '^' or as layout/IME-specific variants // (for example PT dead-key composition). Keep them equivalent here. switch (ch.unicode()) { case MathDsl::PowOp.unicode(): case UnicodeChars::ModifierLetterCircumflexAccent.unicode(): case UnicodeChars::Caret.unicode(): case UnicodeChars::FullwidthCircumflexAccent.unicode(): return true; default: return false; } } static bool textContainsOnlyCaretOperators(const QString& text) { if (text.isEmpty()) return false; for (const QChar ch : text) { if (!isCaretOperatorAlias(ch)) return false; } return true; } static bool textContainsOnlyDivisionAliases(const QString& text) { if (text.isEmpty()) return false; for (const QChar ch : text) { if (!MathDsl::isDivisionOperatorAlias(ch)) return false; } return true; } static bool textContainsOnlySubtractionAliases(const QString& text) { const QString trimmed = text.trimmed(); if (trimmed.isEmpty()) return false; for (const QChar ch : trimmed) { if (!MathDsl::isSubtractionOperatorAlias(ch)) return false; } return true; } static bool isDeadKey(int key) { return key >= Qt::Key_Dead_Grave && key <= Qt::Key_Dead_Small_Schwa; } static QChar previousNonSpaceChar(const QString& text, int cursorPosition) { int i = qBound(0, cursorPosition, text.size()) - 1; while (i >= 0 && text.at(i).isSpace()) --i; return i >= 0 ? text.at(i) : QChar(); } static int previousNonSpaceIndex(const QString& text, int cursorPosition) { int i = qBound(0, cursorPosition, text.size()) - 1; while (i >= 0 && text.at(i).isSpace()) --i; return i; } static bool isExponentTailBeforeIndex(const QString& text, int index) { if (index < 0 || index >= text.size()) return false; const QChar ch = text.at(index); if (MathDsl::isSuperscriptPowerChar(ch)) return true; if (!ch.isDigit()) return false; int start = index; while (start >= 0 && text.at(start).isDigit()) --start; const int beforeDigits = previousNonSpaceIndex(text, start + 1); if (beforeDigits < 0) return false; const QChar before = text.at(beforeDigits); return isCaretOperatorAlias(before) || before == MathDsl::PowNeg; } static bool isValidUnitExponentBase(const QChar& ch) { return ch.isLetterOrNumber() || ch == MathDsl::GroupEnd || ch == MathDsl::UnitEnd; } static bool isInsideCommentFromQuestionMark(const QString& text, int cursorPosition) { const int safeCursorPosition = qBound(0, cursorPosition, text.size()); for (int i = safeCursorPosition - 1; i >= 0; --i) { const QChar ch = text.at(i); if (ch == MathDsl::CommentSep) return true; if (ch == QLatin1Char('\n') || ch == QLatin1Char('\r')) return false; } return false; } static bool hasOnlyWhitespaceToLeft(const QString& text, int cursorPosition) { const int safeCursorPosition = qBound(0, cursorPosition, text.size()); for (int i = 0; i < safeCursorPosition; ++i) { if (!text.at(i).isSpace()) return false; } return true; } static bool hasAnyNonWhitespace(const QString& text) { for (const QChar ch : text) { if (!ch.isSpace()) return true; } return false; } static bool isCurrencySymbolChar(const QChar& ch) { return ch.category() == QChar::Symbol_Currency; } static bool isUnitIdentifierCharInEditor(const QChar& ch) { return ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == UnicodeChars::MicroSign || ch == UnicodeChars::GreekSmallLetterMu || ch == UnicodeChars::GreekCapitalOmega || ch == UnicodeChars::OhmSign || ch == MathDsl::Deg || ch == UnicodeChars::MasculineOrdinalIndicator || ch == MathDsl::ArcminOp || ch == MathDsl::ArcsecOp || ch == MathDsl::ArcminOpAl1 || ch == MathDsl::ArcsecOpAl1; } static bool isAllowedUnitBracketChar(const QChar& ch) { return isUnitIdentifierCharInEditor(ch) || ch == MathDsl::GroupStart || ch == MathDsl::GroupEnd || ch == MathDsl::UnitEnd || ch == MathDsl::PowOp || MathDsl::isDivisionOperator(ch) || MathDsl::isMultiplicationOperator(ch); } static QString superscriptFromAsciiExponent(const QString& asciiExponent) { QString superscript; superscript.reserve(asciiExponent.size()); for (const QChar ch : asciiExponent) { if (ch == MathDsl::AddOp) { superscript += MathDsl::PowPos; continue; } if (MathDsl::isSubtractionOperatorAlias(ch)) { superscript += MathDsl::PowNeg; continue; } const QChar superscriptDigit = MathDsl::asciiDigitToSuperscript(ch); if (superscriptDigit.isNull()) return QString(); superscript += superscriptDigit; } return superscript; } static bool rewriteTrailingAsciiUnitExponentToSuperscript(Editor* editor, const QString& suffix) { QTextCursor cursor = editor->textCursor(); const QString current = editor->text(); const int cursorPos = cursor.position(); int pos = qBound(0, cursorPos, current.size()) - 1; while (pos >= 0 && current.at(pos).isSpace()) --pos; if (pos < 0 || !current.at(pos).isDigit()) return false; int exponentStart = pos; while (exponentStart >= 0 && current.at(exponentStart).isDigit()) --exponentStart; ++exponentStart; int caretPos = exponentStart - 1; if (caretPos >= 1 && MathDsl::isSubtractionOperatorAlias(current.at(caretPos)) && current.at(caretPos - 1) == MathDsl::PowOp) { --caretPos; } if (caretPos < 0 || current.at(caretPos) != MathDsl::PowOp) return false; const QString asciiExponent = current.mid(caretPos + 1, pos - caretPos); const QString superscript = superscriptFromAsciiExponent(asciiExponent); if (superscript.isEmpty()) return false; cursor.setPosition(caretPos); cursor.setPosition(pos + 1, QTextCursor::KeepAnchor); cursor.insertText(superscript + suffix); editor->setTextCursor(cursor); return true; } static bool appendSuffixAfterTrailingSuperscriptExponent(Editor* editor, const QString& suffix, const QString& numericBaseSuffix = QString()) { QTextCursor cursor = editor->textCursor(); const QString current = editor->text(); const int cursorPos = cursor.position(); int pos = qBound(0, cursorPos, current.size()) - 1; while (pos >= 0 && current.at(pos).isSpace()) --pos; if (pos < 0 || !MathDsl::isSuperscriptPowerChar(current.at(pos))) return false; const int exponentEnd = pos; while (pos >= 0 && MathDsl::isSuperscriptPowerChar(current.at(pos))) --pos; if (pos < 0) return false; const QChar base = current.at(pos); if (!base.isLetterOrNumber() && base != MathDsl::GroupEnd && base != MathDsl::UnitEnd) return false; const int insertPos = exponentEnd + 1; cursor.setPosition(insertPos); // Keep numeric-exponent products visually distinct: use the caller-provided // numeric suffix (typically " × ") when the exponent base is numeric. const QString chosenSuffix = (!numericBaseSuffix.isEmpty() && base.isDigit()) ? numericBaseSuffix : suffix; cursor.insertText(chosenSuffix); editor->setTextCursor(cursor); return true; } static bool rewriteTrailingSuperscriptExponentToParenthesizedAscii(Editor* editor, const QString& suffix) { QTextCursor cursor = editor->textCursor(); const QString current = editor->text(); const int cursorPos = cursor.position(); int pos = qBound(0, cursorPos, current.size()) - 1; while (pos >= 0 && current.at(pos).isSpace()) --pos; if (pos < 0 || !MathDsl::isSuperscriptPowerChar(current.at(pos))) return false; const int exponentEnd = pos; while (pos >= 0 && MathDsl::isSuperscriptPowerChar(current.at(pos))) --pos; if (pos < 0) return false; const QChar base = current.at(pos); if (!base.isLetterOrNumber() && base != MathDsl::GroupEnd && base != MathDsl::UnitEnd) return false; const int exponentStart = pos + 1; QString asciiExponent; asciiExponent.reserve(exponentEnd - exponentStart + 1); for (int i = exponentStart; i <= exponentEnd; ++i) { const QChar ch = current.at(i); if (MathDsl::isSuperscriptDigit(ch)) { const QChar asciiDigit = MathDsl::superscriptDigitToAscii(ch); if (asciiDigit.isNull()) return false; asciiExponent += asciiDigit; continue; } if (ch == MathDsl::PowNeg) { asciiExponent += MathDsl::SubOpAl1; continue; } if (ch == MathDsl::PowPos) { asciiExponent += MathDsl::AddOp; continue; } return false; } if (asciiExponent.isEmpty()) return false; const QString replacement = QStringLiteral("^(%1%2)").arg(asciiExponent, suffix); cursor.setPosition(exponentStart); cursor.setPosition(exponentEnd + 1, QTextCursor::KeepAnchor); cursor.insertText(replacement); cursor.setPosition(exponentStart + replacement.size() - 1); editor->setTextCursor(cursor); return true; } static QString renderUnitAsciiExponentsAsSuperscripts(const QString& unitText) { static const QRegularExpression exponentPattern( QStringLiteral(R"(\^(?:\(([−-]?)(\d+)\)|([−-]?)(\d+)))")); QString output; output.reserve(unitText.size()); int lastPos = 0; auto it = exponentPattern.globalMatch(unitText); while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); output += unitText.mid(lastPos, match.capturedStart() - lastPos); QString sign = match.captured(1); QString digits = match.captured(2); if (digits.isEmpty()) { sign = match.captured(3); digits = match.captured(4); } if (!sign.isEmpty() && sign != QLatin1String("-") && sign != QString(MathDsl::SubOp)) { output += match.captured(0); } else { if (!sign.isEmpty()) output += MathDsl::PowNeg; for (const QChar ch : digits) { const QChar superscript = MathDsl::asciiDigitToSuperscript(ch); output += superscript.isNull() ? ch : superscript; } } lastPos = match.capturedEnd(); } output += unitText.mid(lastPos); return output; } static QString normalizeTypedTextForSquareBracketContext(const QString& surroundingText, int cursorPosition, QString text) { QString normalized; normalized.reserve(text.size()); const auto previousNonSpaceBefore = [](const QString& source, int fromExclusive) { int i = qBound(0, fromExclusive, source.size()) - 1; while (i >= 0 && source.at(i).isSpace()) --i; return i >= 0 ? source.at(i) : QChar(); }; const int cursor = qBound(0, cursorPosition, surroundingText.size()); QChar previous = previousNonSpaceBefore(surroundingText, cursor); int previousIndex = cursor - 1; while (previousIndex >= 0 && surroundingText.at(previousIndex).isSpace()) --previousIndex; QChar previousPrevious = previousNonSpaceBefore(surroundingText, previousIndex); int previousPreviousIndex = previousIndex - 1; while (previousPreviousIndex >= 0 && surroundingText.at(previousPreviousIndex).isSpace()) --previousPreviousIndex; QChar previousThird = previousNonSpaceBefore(surroundingText, previousPreviousIndex); const auto initialParenthesizedExponentDepth = [&]() { int depth = 0; const int end = qBound(0, cursorPosition, surroundingText.size()); for (int idx = 0; idx < end; ++idx) { const QChar current = surroundingText.at(idx); if (current == MathDsl::GroupStart) { const QChar beforeOpen = previousNonSpaceBefore(surroundingText, idx); if (beforeOpen == MathDsl::PowOp) { ++depth; } else if (depth > 0) { ++depth; } } else if (current == MathDsl::GroupEnd && depth > 0) { --depth; } } return depth; }; int parenthesizedExponentDepth = initialParenthesizedExponentDepth(); for (int i = 0; i < text.size(); ++i) { QChar ch = text.at(i); if (MathDsl::isAdditionOperatorAlias(ch)) { return QString(); } if (MathDsl::isDivisionOperatorAlias(ch)) ch = MathDsl::DivOp; // Keep unit-symbol aliases normalized as users type inside []. if (ch == UnicodeChars::OhmSign) ch = UnicodeChars::GreekCapitalOmega; else if (ch == UnicodeChars::GreekSmallLetterMu) ch = UnicodeChars::MicroSign; else if (ch == UnicodeChars::MasculineOrdinalIndicator) ch = MathDsl::Deg; else if (ch == MathDsl::ArcminOpAl1) ch = MathDsl::ArcminOp; else if (ch == MathDsl::ArcsecOpAl1) ch = MathDsl::ArcsecOp; if (MathDsl::isSubtractionOperatorAlias(ch)) { const bool afterExponentStart = previous == MathDsl::PowOp || previous == MathDsl::PowNeg || (previous == MathDsl::GroupStart && previousPrevious == MathDsl::PowOp); if (!afterExponentStart) return QString(); ch = MathDsl::SubOp; } if (isUnitIdentifierCharInEditor(ch) && !ch.isDigit()) { if (ch == QLatin1Char('e') || ch == QLatin1Char('E')) { const bool inExponentTypingPosition = previous == MathDsl::PowOp || parenthesizedExponentDepth > 0 || previousPrevious == MathDsl::PowOp; if (inExponentTypingPosition) return QString(); } const bool rightAfterExponentStart = previous == MathDsl::PowOp || (previous == MathDsl::GroupStart && previousPrevious == MathDsl::PowOp); if (rightAfterExponentStart) return QString(); } if (previous == MathDsl::DivOp) { if (parenthesizedExponentDepth > 0) { const bool isValidExponentDenominatorDigit = ch.isDigit(); if (!isValidExponentDenominatorDigit) return QString(); } else { const bool isValidUnitDenominator = (isUnitIdentifierCharInEditor(ch) && !ch.isDigit()) || ch == MathDsl::GroupStart; if (!isValidUnitDenominator) return QString(); } } if (ch == MathDsl::DotSep || ch == MathDsl::CommaSep) { if (parenthesizedExponentDepth <= 0 || !previous.isDigit()) return QString(); int idx = normalized.size() - 1; while (idx >= 0 && normalized.at(idx).isDigit()) --idx; if (idx >= 0 && normalized.at(idx) == MathDsl::DotSep) return QString(); ch = MathDsl::DotSep; } if (MathDsl::isDivisionOperator(ch)) { if (MathDsl::isDivisionOperator(previous)) return QString(); if (MathDsl::isMultiplicationOperator(previous)) { return QString(); } const bool afterExponentStart = previous == MathDsl::PowOp || previous == MathDsl::PowNeg || (previous == MathDsl::GroupStart && previousPrevious == MathDsl::PowOp); const bool afterSignedExponentStart = MathDsl::isSubtractionOperatorAlias(previous) && (previousPrevious == MathDsl::PowOp || (previousPrevious == MathDsl::GroupStart && previousThird == MathDsl::PowOp)); if (afterExponentStart || afterSignedExponentStart) return QString(); } if (ch == MathDsl::PowOp) { const bool validExponentBase = previous.isLetterOrNumber() || previous == MathDsl::GroupEnd || previous == MathDsl::UnitEnd; if (!validExponentBase) return QString(); } if (ch == QLatin1Char(' ')) { if (previous.isNull() || previous == MathDsl::PowOp || previous == MathDsl::GroupStart || MathDsl::isMultiplicationOperator(previous)) { return QString(); } ch = MathDsl::MulDotOp; } else if (MathDsl::isMultiplicationOperatorAlias(ch, true)) { if (!MathDsl::isMultiplicationOperator(ch)) ch = MathDsl::MulCrossOp; } if (!isAllowedUnitBracketChar(ch) && ch != MathDsl::SubOp) return QString(); normalized += ch; if (!ch.isSpace()) { if (ch == MathDsl::GroupStart) { if (previous == MathDsl::PowOp) ++parenthesizedExponentDepth; else if (parenthesizedExponentDepth > 0) ++parenthesizedExponentDepth; } else if (ch == MathDsl::GroupEnd && parenthesizedExponentDepth > 0) { --parenthesizedExponentDepth; } previousThird = previousPrevious; previousPrevious = previous; previous = ch; } } return normalized; } static Tokens scanForCompletionContext(Evaluator* evaluator, const QString& text, bool squareBracketContext) { const auto normalizeSuperscriptPowers = [&](QString source) { for (int i = 0; i < source.size(); ++i) { if (!MathDsl::isSuperscriptPowerChar(source.at(i))) continue; int j = i; while (j < source.size() && MathDsl::isSuperscriptPowerChar(source.at(j))) ++j; QString power; power.reserve(j - i + 3); bool negative = false; for (int k = i; k < j; ++k) { const QChar ch = source.at(k); if (MathDsl::isSuperscriptDigit(ch)) { const QChar asciiDigit = MathDsl::superscriptDigitToAscii(ch); if (!asciiDigit.isNull()) power += asciiDigit; continue; } if (ch == MathDsl::PowNeg) { if (power.isEmpty()) { negative = true; continue; } power += MathDsl::SubOpAl1; continue; } if (ch == MathDsl::PowPos) { if (power.isEmpty()) continue; power += MathDsl::AddOp; } } if (power.isEmpty()) continue; if (negative) power = QString(MathDsl::PowOp) + MathDsl::GroupStart + MathDsl::SubOpAl1 + power + MathDsl::GroupEnd; else power.prepend(MathDsl::PowOp); source.replace(i, j - i, power); i += power.size() - 1; } return source; }; Tokens tokens = evaluator->scan(text); if (tokens.valid()) return tokens; const QString normalized = normalizeSuperscriptPowers(text); if (normalized != text) tokens = evaluator->scan(normalized); if (tokens.valid()) return tokens; if (squareBracketContext) { tokens = evaluator->scan(text + MathDsl::UnitEnd); if (!tokens.valid() && normalized != text) tokens = evaluator->scan(normalized + MathDsl::UnitEnd); } return tokens; } static int trailingIdentifierStart(const QString& text, int endPosition) { const int safeEnd = qBound(0, endPosition, text.size()); if (safeEnd <= 0) return -1; auto isIdentifierStartChar = [](const QChar& ch) { return isUnitIdentifierCharInEditor(ch) && !ch.isDigit() && !MathDsl::isSuperscriptPowerChar(ch); }; auto isIdentifierContinueChar = [](const QChar& ch) { return isUnitIdentifierCharInEditor(ch) && !MathDsl::isSuperscriptPowerChar(ch); }; int start = safeEnd; while (start > 0 && isIdentifierContinueChar(text.at(start - 1))) --start; while (start < safeEnd && !isIdentifierStartChar(text.at(start))) ++start; if (start == safeEnd) return -1; return start; } static QString formattedLiveResultWithAlternatives(const Quantity& quantity, const QString& expression, const QString& interpretedExpression, const QString& sourceExpression = QString(), const Evaluator* evaluator = nullptr) { const QString source = sourceExpression.isEmpty() ? expression : sourceExpression; const QStringList lines = ResultLineFormatUtils::formatResultLinesForDisplay( source, interpretedExpression, quantity, false, true, evaluator, true); QStringList escapedLines; for (const QString& line : lines) escapedLines.append(line.toHtmlEscaped()); return escapedLines.join(QStringLiteral("
    ")); } Editor::Editor(QWidget* parent) : QPlainTextEdit(parent) { m_ownedSession.reset(new Session); m_session = m_ownedSession.get(); m_evaluator = m_session->evaluator(); m_currentHistoryIndex = 0; m_isAutoCompletionEnabled = true; m_completion = new EditorCompletion(this); m_constantCompletion = 0; m_completionTimer = new QTimer(this); m_isAutoCalcEnabled = true; m_highlighter = new SyntaxHighlighter(this, true); updateMatchedParenthesisColors(); m_matchingTimer = new QTimer(this); m_cursorBlinkTimer = new QTimer(this); m_cursorBlinkingEnabled = Settings::instance()->cursorBlinking; m_customCursorVisible = true; m_historyArrowNavigationEnabled = true; setViewportMargins(0, 0, 0, 0); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); setTabChangesFocus(true); setLineWrapMode(QPlainTextEdit::WidgetWidth); setWordWrapMode(QTextOption::WrapAnywhere); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setCursorWidth(kEditorCursorWidth); setAttribute(Qt::WA_StyledBackground, true); viewport()->setObjectName(QStringLiteral("editorViewport")); viewport()->setAutoFillBackground(false); document()->setDocumentMargin(kEditorDocumentMargin); m_cursorBlinkTimer->setSingleShot(false); connect(m_cursorBlinkTimer, &QTimer::timeout, this, [this]() { m_themedCursorVisible = !m_themedCursorVisible; viewport()->update(themedCursorRect()); }); connect(m_completion, &EditorCompletion::selectedCompletion, this, &Editor::autoComplete); connect(m_completionTimer, SIGNAL(timeout()), SLOT(triggerAutoComplete())); connect(m_matchingTimer, SIGNAL(timeout()), SLOT(doMatchingPar())); connect(this, &Editor::selectionChanged, this, &Editor::checkSelectionAutoCalc); connect(this, &Editor::textChanged, this, [this]() { m_currentAutoCalcDismissed = false; }); connect(this, &Editor::textChanged, this, &Editor::checkAutoCalc); connect(this, &Editor::textChanged, this, &Editor::checkAutoComplete); connect(this, &Editor::textChanged, this, &Editor::checkMatching); connect(this, &Editor::textChanged, this, &Editor::showThemedCursorAndRestartBlink); connect(this, &Editor::cursorPositionChanged, this, &Editor::updateHeightAndEnsureCursorVisible); connect(this, &Editor::cursorPositionChanged, this, &Editor::showThemedCursorAndRestartBlink); connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this, [this](const QSizeF&) { updateHeightAndEnsureCursorVisible(); }); adjustSize(); updateHeightAndEnsureCursorVisible(); } Editor::~Editor() = default; void Editor::setSession(Session* session) { if (session == nullptr) { if (!m_ownedSession) m_ownedSession.reset(new Session); session = m_ownedSession.get(); } m_session = session; m_evaluator = m_session->evaluator(); { // Rebinding the highlighter changes formatting, not the expression. const QSignalBlocker blocker(this); m_highlighter->setEvaluator(m_evaluator); } updateHistory(); } void Editor::refreshAutoCalc() { if (m_isAutoCalcEnabled) { if (!textCursor().selectedText().isEmpty()) checkSelectionAutoCalc(); else checkAutoCalc(); } } QString Editor::text() const { return toPlainText(); } void Editor::dismissCurrentAutoCalc() { m_currentAutoCalcDismissed = true; } void Editor::setText(const QString& text) { setPlainText(Settings::instance()->automaticInputAdjustments ? normalizeExpressionTypedInEditor(text) : text); updateHeightAndEnsureCursorVisible(); } QString Editor::historyExpressionForInput(const QString& text) { if (Settings::instance()->automaticInputAdjustments) return text; // Older entries can contain adjustments made before the option was disabled. const int commentPos = text.indexOf(MathDsl::CommentSep); const QString expression = Evaluator::expandSuperscriptPowers( commentPos >= 0 ? text.left(commentPos) : text); QString raw; raw.reserve(expression.size()); for (QChar ch : expression) { if (MathDsl::isMultiplicationOperator(ch) || MathDsl::isMultiplicationOperatorAlias(ch)) raw += MathDsl::MulOpAl1; else if (MathDsl::isDivisionOperatorAlias(ch) || ch == UnicodeChars::BigSolidus) raw += MathDsl::DivOp; else if (MathDsl::isSubtractionOperatorAlias(ch)) raw += MathDsl::SubOpAl1; else if (ch == MathDsl::TransOp) raw += QStringLiteral("->"); else raw += ch; } return commentPos >= 0 ? raw + text.mid(commentPos) : raw; } void Editor::insert(const QString& text) { // Inserted fragments may belong to an existing comment even without a '?'. // Use the start of a selection, since the selected delimiter may be removed. if (!Settings::instance()->automaticInputAdjustments || isInsideCommentFromQuestionMark(this->text(), textCursor().selectionStart())) { insertPlainText(text); updateHeightAndEnsureCursorVisible(); return; } QString normalized = normalizeExpressionTypedInEditor(text); const QString normalizedTrimmed = normalized.trimmed(); const int pos = textCursor().position(); const QString surroundingText = this->text(); const bool squareBracketContext = isInsideUnmatchedSquareBracketContext( surroundingText, pos); if (squareBracketContext) { normalized = normalizeTypedTextForSquareBracketContext( surroundingText, pos, normalized); if (normalized.isEmpty()) return; } // Reject repeated exponent operators when the nearest left non-space is // already a caret operator, regardless of how caret is encoded. if (textContainsOnlyCaretOperators(normalized) || textContainsOnlyCaretOperators(normalizedTrimmed)) { const QChar prev = previousNonSpaceChar(this->text(), pos); if (isCaretOperatorAlias(prev)) return; } if (textContainsOnlyAdditionAliases(normalized) || textContainsOnlyAdditionAliases(normalizedTrimmed)) { const QChar prev = previousNonSpaceChar(this->text(), pos); const bool prevIsBlockingOperator = isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || prev == MathDsl::PowOp; if (prevIsBlockingOperator) return; normalized = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( this->text(), pos, QString(MathDsl::AddOp)); } insertPlainText(normalized); updateHeightAndEnsureCursorVisible(); } void Editor::doBackspace() { QTextCursor cursor = textCursor(); const int groupedLength = Settings::instance()->automaticInputAdjustments && !cursor.hasSelection() ? groupedTokenLengthBefore(toPlainText(), cursor.position()) : 0; if (groupedLength > 0) { cursor.setPosition(cursor.position() - groupedLength, QTextCursor::KeepAnchor); cursor.removeSelectedText(); setTextCursor(cursor); return; } cursor.deletePreviousChar(); setTextCursor(cursor); } void Editor::doDelete() { QTextCursor cursor = textCursor(); const int groupedLength = Settings::instance()->automaticInputAdjustments && !cursor.hasSelection() ? groupedTokenLengthAfter(toPlainText(), cursor.position()) : 0; if (groupedLength > 0) { cursor.setPosition(cursor.position() + groupedLength, QTextCursor::KeepAnchor); cursor.removeSelectedText(); setTextCursor(cursor); return; } cursor.deleteChar(); setTextCursor(cursor); } char Editor::radixChar() const { return Settings::instance()->radixCharacter(); } int Editor::cursorPosition() const { return textCursor().position(); } void Editor::setCursorPosition(int position) { QTextCursor cursor = textCursor(); cursor.setPosition(position); setTextCursor(cursor); } void Editor::doSetTextCursor(const QTextCursor& cursor) { // An edit block delays Qt's layout update. Automatic rewrites can move // past the old line ends before it finishes, so refresh the block before // Qt tries to scroll the new cursor into view. if (m_inputEditInProgress) cursor.block().clearLayout(); QPlainTextEdit::doSetTextCursor(cursor); } QSize Editor::sizeHint() const { ensurePolished(); const QFontMetrics metrics = fontMetrics(); const int width = metrics.horizontalAdvance('x') * 10; const int height = editorLineHeight(font()) + editorVerticalDecorationHeight(); return QSize(width, height); } void Editor::clearHistory() { m_history.clear(); m_currentHistoryIndex = 0; } bool Editor::isAutoCompletionEnabled() const { return m_isAutoCompletionEnabled; } void Editor::setAutoCompletionEnabled(bool enable) { m_isAutoCompletionEnabled = enable; } bool Editor::isAutoCalcEnabled() const { return m_isAutoCalcEnabled; } void Editor::setAutoCalcEnabled(bool enable) { m_isAutoCalcEnabled = enable; } void Editor::setCustomCursorVisible(bool visible) { setCursorWidth(visible ? kEditorCursorWidth : 0); if (m_customCursorVisible == visible) return; m_customCursorVisible = visible; if (visible) showThemedCursorAndRestartBlink(); else hideThemedCursorAndStopBlink(); viewport()->update(); } void Editor::setCursorBlinkingEnabled(bool enabled) { if (m_cursorBlinkingEnabled == enabled) return; m_cursorBlinkingEnabled = enabled; if (hasFocus() || m_completion->isVisible()) showThemedCursorAndRestartBlink(); else hideThemedCursorAndStopBlink(); } void Editor::showThemedCursorAndRestartBlink() { m_themedCursorVisible = true; if (shouldPaintThemedCursor() && m_cursorBlinkingEnabled) { const int cursorFlashTime = QApplication::cursorFlashTime(); const int blinkInterval = cursorFlashTime > 0 ? qMax(1, cursorFlashTime / 2) : 500; m_cursorBlinkTimer->start(blinkInterval); } else { m_cursorBlinkTimer->stop(); } viewport()->update(themedCursorRect()); } void Editor::hideThemedCursorAndStopBlink() { m_cursorBlinkTimer->stop(); m_themedCursorVisible = false; viewport()->update(themedCursorRect()); } bool Editor::shouldPaintThemedCursor() const { return m_customCursorVisible && m_themePrimaryColor.isValid(); } QRect Editor::themedCursorRect() const { const QRect nativeRect = cursorRect(); if (!nativeRect.isValid() || nativeRect.height() <= 0) return QRect(); return QRect(nativeRect.x() + (nativeRect.width() - kEditorCursorWidth) / 2, nativeRect.y(), kEditorCursorWidth, nativeRect.height()); } void Editor::setHistoryArrowNavigationEnabled(bool enabled) { m_historyArrowNavigationEnabled = enabled; } void Editor::checkAutoComplete() { // A dismissal only suppresses completion until the next text edit, even // when later edits restore the same text and cursor position. m_suppressedCompletionText.clear(); m_suppressedCompletionPosition = -1; if (!m_isAutoCompletionEnabled) return; m_completionTimer->stop(); m_completionTimer->setSingleShot(true); m_completionTimer->start(); } void Editor::checkMatching() { if (!Settings::instance()->syntaxHighlighting) return; m_matchingTimer->stop(); m_matchingTimer->setSingleShot(true); m_matchingTimer->start(); } void Editor::checkAutoCalc() { if (m_mouseSelectionInProgress) return; if (m_currentAutoCalcDismissed) return; if (m_isAutoCalcEnabled) autoCalc(); } void Editor::doMatchingPar() { // Clear previous. setExtraSelections(QList()); if (!Settings::instance()->syntaxHighlighting) return; doMatchingLeft(); doMatchingRight(); } void Editor::checkSelectionAutoCalc() { if (m_mouseSelectionInProgress) return; if (m_isAutoCalcEnabled) autoCalcSelection(); } void Editor::doMatchingLeft() { const int currentPosition = textCursor().position(); if (currentPosition <= 0) return; const QString currentText = text(); const int closePos = currentPosition - 1; if (closePos < 0 || closePos >= currentText.size()) return; const auto isOpen = [](QChar ch) { return ch == MathDsl::GroupStart || ch == MathDsl::UnitStart || ch == MathDsl::ListStart; }; const auto isClose = [](QChar ch) { return ch == MathDsl::GroupEnd || ch == MathDsl::UnitEnd || ch == MathDsl::ListEnd; }; const auto matchingOpen = [](QChar ch) { if (ch == MathDsl::GroupEnd) return MathDsl::GroupStart; if (ch == MathDsl::UnitEnd) return MathDsl::UnitStart; if (ch == MathDsl::ListEnd) return MathDsl::ListStart; return QChar(); }; const QChar closing = currentText.at(closePos); if (!isClose(closing)) return; QVector expectedOpenStack; expectedOpenStack.append(matchingOpen(closing)); int matchPos = -1; for (int i = closePos - 1; i >= 0; --i) { const QChar ch = currentText.at(i); if (isClose(ch)) { expectedOpenStack.append(matchingOpen(ch)); continue; } if (!isOpen(ch)) continue; if (expectedOpenStack.isEmpty()) break; if (ch == expectedOpenStack.last()) { expectedOpenStack.removeLast(); if (expectedOpenStack.isEmpty()) { matchPos = i; break; } } else { break; } } if (matchPos < 0) return; QTextEdit::ExtraSelection hilite1; hilite1.cursor = textCursor(); hilite1.cursor.setPosition(matchPos); hilite1.cursor.setPosition(matchPos + 1, QTextCursor::KeepAnchor); hilite1.format = matchedParenthesisFormat(); QTextEdit::ExtraSelection hilite2; hilite2.cursor = textCursor(); hilite2.cursor.setPosition(closePos); hilite2.cursor.setPosition(closePos + 1, QTextCursor::KeepAnchor); hilite2.format = hilite1.format; QList extras; extras << hilite1; extras << hilite2; setExtraSelections(extras); } void Editor::doMatchingRight() { const int currentPosition = textCursor().position(); const QString currentText = text(); if (currentPosition < 0 || currentPosition >= currentText.size()) return; const auto isOpen = [](QChar ch) { return ch == MathDsl::GroupStart || ch == MathDsl::UnitStart || ch == MathDsl::ListStart; }; const auto isClose = [](QChar ch) { return ch == MathDsl::GroupEnd || ch == MathDsl::UnitEnd || ch == MathDsl::ListEnd; }; const auto matchingClose = [](QChar ch) { if (ch == MathDsl::GroupStart) return MathDsl::GroupEnd; if (ch == MathDsl::UnitStart) return MathDsl::UnitEnd; if (ch == MathDsl::ListStart) return MathDsl::ListEnd; return QChar(); }; const int openPos = currentPosition; const QChar opening = currentText.at(openPos); if (!isOpen(opening)) return; QVector expectedCloseStack; expectedCloseStack.append(matchingClose(opening)); int matchPos = -1; for (int i = openPos + 1; i < currentText.size(); ++i) { const QChar ch = currentText.at(i); if (isOpen(ch)) { expectedCloseStack.append(matchingClose(ch)); continue; } if (!isClose(ch)) continue; if (expectedCloseStack.isEmpty()) break; if (ch == expectedCloseStack.last()) { expectedCloseStack.removeLast(); if (expectedCloseStack.isEmpty()) { matchPos = i; break; } } else { break; } } if (matchPos < 0) return; QTextEdit::ExtraSelection hilite1; hilite1.cursor = textCursor(); hilite1.cursor.setPosition(matchPos); hilite1.cursor.setPosition(matchPos + 1, QTextCursor::KeepAnchor); hilite1.format = matchedParenthesisFormat(); QTextEdit::ExtraSelection hilite2; hilite2.cursor = textCursor(); hilite2.cursor.setPosition(openPos); hilite2.cursor.setPosition(openPos + 1, QTextCursor::KeepAnchor); hilite2.format = hilite1.format; QList extras; extras << hilite1; extras << hilite2; setExtraSelections(extras); } // Matches a list of built-in functions, units and variables to a fragment. QStringList Editor::matchFragment(const QString& id, bool unitContext) const { const Settings* settings = Settings::instance(); QStringList choices; if (!unitContext && settings->autoCompletionBuiltInFunctions) { const auto fnames = FunctionRepo::instance()->getIdentifiers(); for (int i = 0; i < fnames.count(); ++i) { if (fnames.at(i).startsWith(id, Qt::CaseSensitive)) { QString str = fnames.at(i); Function* f = FunctionRepo::instance()->find(str); if (f) str.append(':').append(f->name()); choices.append(str); } } choices.sort(); } if (unitContext) { const auto unitNameMatchesFragment = [&id](const QString& unitName) -> bool { if (unitName.startsWith(id, Qt::CaseSensitive)) return true; // Treat ASCII 'u' as a typing-friendly alias for leading micro sign. if (id.isEmpty() || id.at(0) != QLatin1Char('u') || !unitName.startsWith(UnicodeChars::MicroSign)) return false; return unitName.mid(1).startsWith(id.mid(1), Qt::CaseSensitive); }; QStringList unitChoices; QSet seenUnitNames; const QStringList allUnits = m_evaluator->allUnitIdentifiers(); for (const QString& unitName : allUnits) { if (!unitNameMatchesFragment(unitName)) continue; // Keep parsing support for ASCII microarcsecond alias, but avoid // showing it in completion where the preferred symbol is "µas". if (unitName == QStringLiteral("uas")) continue; if (seenUnitNames.contains(unitName)) continue; seenUnitNames.insert(unitName); QString unitDescription = tr("Unit"); if (const UserUnit* userUnit = m_evaluator->getUserUnit(unitName)) { const QString userDescription = userUnit->description().trimmed(); unitDescription = userDescription.isEmpty() ? tr("User unit") : userDescription; } else { const QString localizedName = unitLocalizedIdentifierName(unitName); if (!localizedName.isEmpty()) { unitDescription = isUnitLocalizedNameTranslatable(localizedName) ? tr(localizedName.toUtf8().constData()) : localizedName; } } unitChoices.append(unitName + QStringLiteral(":") + unitDescription); } unitChoices.sort(); choices += unitChoices; } // Find matches in variable names. QStringList variableChoices; QSet seenVariableCompletionIds; QList variables = m_evaluator->getVariables(); for (int i = 0; i < variables.count(); ++i) { const Variable variable = variables.at(i); const bool isBuiltIn = variable.type() == Variable::BuiltIn; const bool includeVariable = !unitContext && ((isBuiltIn && settings->autoCompletionBuiltInVariables) || (!isBuiltIn && settings->autoCompletionUserVariables)); if (!includeVariable) continue; if (variable.identifier().startsWith(id, Qt::CaseSensitive)) { const QString completionIdentifier = variable.identifier(); if (seenVariableCompletionIds.contains(completionIdentifier)) continue; seenVariableCompletionIds.insert(completionIdentifier); QString variableDescription; if (m_evaluator->isGlobalUserVariable(completionIdentifier)) variableDescription = NumberFormatter::format(variable.value()); else variableDescription = variable.description().trimmed().isEmpty() ? NumberFormatter::format(variable.value()) : variable.description().trimmed(); variableChoices.append(QString("%1:%2").arg( completionIdentifier, variableDescription)); } } variableChoices.sort(); choices += variableChoices; if (!unitContext && settings->autoCompletionUserFunctions) { QStringList ufchoices; auto userFunctions = m_evaluator->getUserFunctions(); for (int i = 0; i < userFunctions.count(); ++i) { if (userFunctions.at(i).name().startsWith(id, Qt::CaseSensitive)) { const QString description = userFunctions.at(i).description().trimmed().isEmpty() ? tr("User function") : userFunctions.at(i).description().trimmed(); ufchoices.append(QString("%1:%2").arg( userFunctions.at(i).name(), description)); } } ufchoices.sort(); choices += ufchoices; } return choices; } QString Editor::getKeyword() const { // Tokenize the expression. const int currentPosition = textCursor().position(); const bool unitContextAtCursor = isInsideUnmatchedSquareBracketContext(text(), currentPosition); const Tokens tokens = scanForCompletionContext( m_evaluator, text(), unitContextAtCursor); // Find the token at the cursor. for (int i = tokens.size() - 1; i >= 0; --i) { const auto& token = tokens[i]; if (token.pos() > currentPosition) continue; if (token.isIdentifier() || token.isUnitIdentifier()) { const QString tokenText = token.text(); const auto matches = matchFragment(tokenText, unitContextAtCursor); // Prefer an exact identifier match under cursor; prefix matches // are only a fallback for partial identifiers. for (const auto& match : matches) { const QString identifier = match.split(":").first(); if (identifier.compare(tokenText, Qt::CaseSensitive) == 0) return identifier; } if (!matches.empty()) return matches.first().split(":").first(); } // Try further to the left. continue; } return ""; } void Editor::triggerAutoComplete() { if (m_shouldBlockAutoCompletionOnce) { m_shouldBlockAutoCompletionOnce = false; return; } if (!m_isAutoCompletionEnabled) return; QWidget* focusWidget = QApplication::focusWidget(); if (!hasFocus() && !m_completion->isVisible() && focusWidget != nullptr && focusWidget != this && focusWidget != viewport()) return; const int currentPosition = textCursor().position(); if (m_suppressedCompletionPosition == currentPosition && m_suppressedCompletionText == text()) { return; } // Tokenize the expression (this is very fast). auto subtext = text().left(currentPosition); const bool unitContext = isInsideUnmatchedSquareBracketContext(text(), currentPosition); const auto tokens = scanForCompletionContext(m_evaluator, subtext, unitContext); if (!tokens.valid() || tokens.count() < 1) return; Token lastToken; bool foundIdentifierToken = false; for (int i = tokens.count() - 1; i >= 0; --i) { const Token candidate = tokens.at(i); if (!candidate.isIdentifier() && !candidate.isUnitIdentifier()) continue; if (!candidate.size()) continue; if (candidate.pos() > subtext.length()) continue; lastToken = candidate; foundIdentifierToken = true; break; } if (!foundIdentifierToken) return; const int rawIdStart = trailingIdentifierStart(subtext, subtext.length()); const QString id = rawIdStart >= 0 ? subtext.mid(rawIdStart) : lastToken.text(); if (id.length() < 1) return; // No space after identifier. const int rawIdEnd = rawIdStart >= 0 ? subtext.length() : (lastToken.pos() + lastToken.size()); if (rawIdEnd < subtext.length()) return; QStringList choices(matchFragment(id, unitContext)); // If we are assigning a user function, find matches in its arguments names // and replace variables names that collide. if (m_evaluator->isUserFunctionAssign()) { for (int i=2; ishowCompletion(choices); } void Editor::autoComplete(const QString& item) { if (!m_isAutoCompletionEnabled || item.isEmpty()) return; // Accepting a completion edits text (and often inserts "()" for functions), // which emits textChanged and would immediately reopen completion. m_shouldBlockAutoCompletionOnce = true; const int currentPosition = textCursor().position(); const bool unitContext = isInsideUnmatchedSquareBracketContext(text(), currentPosition); const auto subtext = text().left(currentPosition); const auto tokens = scanForCompletionContext(m_evaluator, subtext, unitContext); if (!tokens.valid() || tokens.count() < 1) return; Token lastToken; bool foundIdentifierToken = false; for (int i = tokens.count() - 1; i >= 0; --i) { const Token candidate = tokens.at(i); if (!candidate.isIdentifier() && !candidate.isUnitIdentifier()) continue; if (!candidate.size()) continue; if (candidate.pos() > subtext.length()) continue; lastToken = candidate; foundIdentifierToken = true; break; } if (!foundIdentifierToken) return; const auto str = item.split(':'); // Add leading space characters if any. auto newTokenText = str.at(0); if (unitContext) { newTokenText = UnicodeChars::normalizeUnitSymbolAliases(newTokenText); const QString preferredShortUnitText = UnitDisplayFormat::shortDisplayName(newTokenText); if (preferredShortUnitText != newTokenText) { // Some short unit symbols are not accepted by unit-context typing // normalization. Fall back to the long identifier so completion // still inserts a valid unit token instead of becoming a no-op. const QString normalizedShortUnitText = normalizeTypedTextForSquareBracketContext( text(), currentPosition, preferredShortUnitText); if (!normalizedShortUnitText.isEmpty()) newTokenText = preferredShortUnitText; } else { newTokenText = preferredShortUnitText; } const UnitId completedUnitId = unitId(normalizeUnitName(UnicodeChars::normalizeUnitSymbolAliases(newTokenText))); if (completedUnitId != UnitId::Unknown) { const QString symbol = unitSymbol(completedUnitId); if (!symbol.isEmpty()) newTokenText = symbol; } } if (newTokenText == QLatin1String("pi")) newTokenText = QString(UnicodeChars::Pi); const int rawIdStart = trailingIdentifierStart(subtext, subtext.length()); const int replaceStart = rawIdStart >= 0 ? rawIdStart : lastToken.pos(); const int replaceSize = rawIdStart >= 0 ? (subtext.length() - rawIdStart) : lastToken.size(); const int leadingSpaces = rawIdStart >= 0 ? 0 : (lastToken.size() - lastToken.text().length()); if (leadingSpaces > 0) newTokenText = newTokenText.rightJustified( leadingSpaces + newTokenText.length(), ' '); blockSignals(true); QTextCursor cursor = textCursor(); cursor.setPosition(replaceStart); cursor.setPosition(replaceStart + replaceSize, QTextCursor::KeepAnchor); setTextCursor(cursor); QPlainTextEdit::insertPlainText(newTokenText); blockSignals(false); cursor = textCursor(); bool hasParensAlready = cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); if (hasParensAlready) { auto nextChar = cursor.selectedText(); hasParensAlready = (nextChar == QString(MathDsl::GroupStart)); } bool isFunction = !unitContext && (FunctionRepo::instance()->find(str.at(0)) || m_evaluator->hasUserFunction(str.at(0))); bool shouldAutoInsertParens = isFunction && !hasParensAlready; if (shouldAutoInsertParens) { insert(QString(MathDsl::GroupStart) + MathDsl::GroupEnd); cursor = textCursor(); cursor.movePosition(QTextCursor::PreviousCharacter); setTextCursor(cursor); } checkAutoCalc(); } void Editor::insertFromMimeData(const QMimeData* source) { if (!source->text().contains(RegExpPatterns::lineBreak()) && isInsideCommentFromQuestionMark(text(), textCursor().selectionStart())) { insert(source->text()); return; } const QStringList expressions = EditorUtils::parsePastedExpressionsImpl( source->text(), [](const QString& text) { return text; }); if (expressions.isEmpty()) return; auto normalizedPastedExpression = [this](const QString& expression) { if (!Settings::instance()->automaticInputAdjustments || isInsideCommentFromQuestionMark(text(), textCursor().selectionStart())) return expression; QString formattedNumericLiteral; if (NumberFormatter::tryFormatStandaloneNumericLiteralForDisplay(expression, &formattedNumericLiteral)) return normalizeExpressionTypedInEditor(formattedNumericLiteral); return expression; }; if (expressions.size() == 1) { // Insert text manually to make sure expression does not contain new line characters insert(normalizedPastedExpression(expressions.at(0))); return; } emit bulkEvaluationStarted(); for (int i = 0; i < expressions.size(); ++i) { insert(normalizedPastedExpression(expressions.at(i))); evaluate(); } emit bulkEvaluationFinished(); } void Editor::autoCalc() { if (!m_isAutoCalcEnabled) return; const auto str = m_evaluator->autoFix(text()); if (str.isEmpty()) return; // Same reason as above, do not update "ans". m_evaluator->setExpression(str); auto quantity = m_evaluator->evalNoAssign(); if (m_evaluator->error().isEmpty()) { QString interpretedExpr = m_evaluator->interpretedExpression(); if (quantity.isNan() && (m_evaluator->isUserFunctionAssign() || Evaluator::isCommentOnlyExpression(str))) { // Result is not available for user function assignment and // comment-only expressions. emit autoCalcDisabled(); } else { const auto formatted = formattedLiveResultWithAlternatives( quantity, str, interpretedExpr, text(), m_evaluator); auto message = tr("Current result:
    %1").arg(formatted); emit autoCalcMessageAvailable(message); emit autoCalcQuantityAvailable(quantity); } } else { if (isOperatorOnlyIncompleteInput(str)) { emit autoCalcDisabled(); return; } const QString usageTooltip = FunctionTooltipUtils::activeFunctionUsageTooltip( m_evaluator, text(), textCursor().position() ); if (usageTooltip.isEmpty()) { QString baseExpression; if (EditorUtils::expressionWithoutIgnorableTrailingToken(str, &baseExpression)) { m_evaluator->setExpression(baseExpression); auto baseQuantity = m_evaluator->evalNoAssign(); if (m_evaluator->error().isEmpty()) { const QString interpretedExpr = m_evaluator->interpretedExpression(); if (baseQuantity.isNan() && (m_evaluator->isUserFunctionAssign() || Evaluator::isCommentOnlyExpression(baseExpression))) { emit autoCalcDisabled(); } else { const auto formatted = formattedLiveResultWithAlternatives( baseQuantity, baseExpression, interpretedExpr, text(), m_evaluator); auto message = tr("Current result:
    %1").arg(formatted); emit autoCalcMessageAvailable(message); emit autoCalcQuantityAvailable(baseQuantity); } return; } } } emit autoCalcMessageAvailable( usageTooltip.isEmpty() ? m_evaluator->error() : usageTooltip ); } } void Editor::increaseFontPointSize() { QFont newFont = font(); const int newSize = newFont.pointSize() + 1; if (newSize > 96) return; newFont.setPointSize(newSize); setFont(newFont); } void Editor::decreaseFontPointSize() { QFont newFont = font(); const int newSize = newFont.pointSize() - 1; if (newSize < 8) return; newFont.setPointSize(newSize); setFont(newFont); } void Editor::autoCalcSelection(const QString& custom) { if (!m_isAutoCalcEnabled) return; const QString rawSelection = custom.isNull() ? textCursor().selectedText() : custom; if (rawSelection.contains(RegExpPatterns::lineBreak())) { emit autoCalcDisabled(); return; } auto str = rawSelection; str = m_evaluator->autoFix(str); if (str.isEmpty()) { emit autoCalcDisabled(); return; } // Same reason as above, do not update "ans". m_evaluator->setExpression(str); auto quantity = m_evaluator->evalNoAssign(); if (m_evaluator->error().isEmpty()) { const QString interpretedExpr = m_evaluator->interpretedExpression(); if (quantity.isNan() && (m_evaluator->isUserFunctionAssign() || Evaluator::isCommentOnlyExpression(str))) { // Result is not available for user function assignment and // comment-only expressions. auto message = tr("Selection result: n/a"); emit autoCalcMessageAvailable(message); } else { const auto formatted = formattedLiveResultWithAlternatives( quantity, str, interpretedExpr, rawSelection, m_evaluator); auto message = tr("Selection result:
    %1").arg(formatted); emit autoCalcMessageAvailable(message); emit autoCalcQuantityAvailable(quantity); } } else { if (isOperatorOnlyIncompleteInput(str)) { emit autoCalcDisabled(); return; } QString baseExpression; if (EditorUtils::expressionWithoutIgnorableTrailingToken(str, &baseExpression)) { m_evaluator->setExpression(baseExpression); const auto baseQuantity = m_evaluator->evalNoAssign(); if (m_evaluator->error().isEmpty()) { const QString interpretedExpr = m_evaluator->interpretedExpression(); if (baseQuantity.isNan() && (m_evaluator->isUserFunctionAssign() || Evaluator::isCommentOnlyExpression(baseExpression))) { auto message = tr("Selection result: n/a"); emit autoCalcMessageAvailable(message); } else { const auto formatted = formattedLiveResultWithAlternatives( baseQuantity, baseExpression, interpretedExpr, rawSelection, m_evaluator); auto message = tr("Selection result:
    %1").arg(formatted); emit autoCalcMessageAvailable(message); emit autoCalcQuantityAvailable(baseQuantity); } return; } } auto message = tr("Selection result: %1").arg(m_evaluator->error()); emit autoCalcMessageAvailable(message); } } void Editor::insertConstant(const QString& constant) { auto formattedConstant = constant; if (radixChar() == MathDsl::CommaSep) formattedConstant.replace(MathDsl::DotSep, MathDsl::CommaSep); formattedConstant = DisplayFormatUtils::applyValueUnitSpacingForDisplay(formattedConstant); if (!constant.isNull()) insert(formattedConstant); if (m_constantCompletion) { disconnect(m_constantCompletion); m_constantCompletion->deleteLater(); m_constantCompletion = 0; } } void Editor::cancelConstantCompletion() { if (m_constantCompletion) { disconnect(m_constantCompletion); m_constantCompletion->deleteLater(); m_constantCompletion = 0; } } void Editor::evaluate() { triggerEnter(); } static void paintInputDigitSeparators(QPainter& painter, const QTextBlock& block, const QPointF& offset, const QAbstractTextDocumentLayout::PaintContext& context) { // The layout has already drawn the unchanged document text. Add the glyphs // described by SyntaxHighlighter's format properties. A space needs only // the reserved gap, while commas, dots and underscores need a painted glyph. // The grouping glyph belongs to the preceding digit for selection colors. // It is never a separate character that the cursor or Backspace can visit. const QTextLayout* layout = block.layout(); for (const auto& range : layout->formats()) { const bool replacement = range.format.hasProperty(SyntaxHighlighter::InputRadixReplacement); const QString separator = range.format.stringProperty(replacement ? SyntaxHighlighter::InputRadixReplacement : SyntaxHighlighter::InputDigitSeparator); if (separator.isEmpty() || separator == QLatin1String(" ")) continue; for (int pos = range.start; pos < range.start + range.length; ++pos) { const QTextLine line = layout->lineForTextPosition(pos); if (!line.isValid()) continue; QFont font = range.format.font().resolve(layout->font()); font.setLetterSpacing(QFont::AbsoluteSpacing, 0); QColor color = range.format.foreground().color(); QBrush background = block.blockFormat().background(); if (background == Qt::NoBrush) background = context.palette.base(); for (const auto& selection : context.selections) { const int absolutePos = block.position() + pos; if (absolutePos >= selection.cursor.selectionStart() && absolutePos < selection.cursor.selectionEnd()) { if (selection.format.foreground() != Qt::NoBrush) color = selection.format.foreground().color(); if (selection.format.background() != Qt::NoBrush) background = selection.format.background(); } } painter.save(); painter.setFont(font); painter.setPen(color); const qreal x = replacement ? line.cursorToX(pos) : line.cursorToX(pos + 1) - range.format.fontLetterSpacing(); if (replacement) { // Cover the original decimal glyph, including its selection // background, then draw the selected one in the same place. // This changes the view without rewriting the document. painter.fillRect(QRectF(offset + QPointF(x, line.y()), QSizeF(line.cursorToX(pos + 1) - x, line.height())), background); } painter.drawText(offset + QPointF(x, line.y() + line.ascent()), separator); painter.restore(); } } } void Editor::paintEvent(QPaintEvent* event) { if (m_customCursorVisible && !m_themePrimaryColor.isValid()) { QPlainTextEdit::paintEvent(event); if (!Settings::instance()->inputDigitGrouping) return; QPainter painter(viewport()); painter.setClipRegion(event->region()); QPointF offset = contentOffset(); const auto context = getPaintContext(); for (QTextBlock block = firstVisibleBlock(); block.isValid(); block = block.next()) { paintInputDigitSeparators(painter, block, offset, context); offset.ry() += blockBoundingRect(block).height(); if (offset.y() > viewport()->height()) break; } return; } // Paint the text layouts directly so Qt never draws its native cursor. // A zero cursor width is insufficient: QTextLayout can still draw a // cosmetic hairline at fractional display scales (and bidi cursor marks). // Its independent blink and raster inversion then add extra cursor states. QPainter painter(viewport()); painter.setClipRegion(event->region()); QPointF offset = contentOffset(); painter.setBrushOrigin(offset); const auto context = getPaintContext(); painter.setPen(context.palette.text().color()); QRect clip = event->rect(); const qreal maximumWidth = qMax(qreal(viewport()->width()), document()->documentLayout()->documentSize().width()); if (document()->isEmpty() && !placeholderText().isEmpty() && !textCursor().hasSelection() && textCursor().block().layout()->preeditAreaText().isEmpty()) { painter.save(); painter.setPen(context.palette.placeholderText().color()); const int margin = int(document()->documentMargin()); painter.drawText(viewport()->rect().adjusted(margin, margin, 0, 0), Qt::AlignTop | Qt::TextWordWrap, placeholderText()); painter.restore(); } // Keep full-width selections out of the document's right margin, as in // QPlainTextEdit's normal paint path. const int rightEdge = int(offset.x() + maximumWidth - document()->documentMargin()) + cursorWidth(); clip.setRight(qMin(clip.right(), rightEdge)); painter.setClipRect(clip, Qt::IntersectClip); QTextBlock block = firstVisibleBlock(); for (; block.isValid(); block = block.next()) { const QRectF bounds = blockBoundingRect(block).translated(offset); if (block.isVisible() && bounds.bottom() >= clip.top() && bounds.top() <= clip.bottom()) { const QBrush background = block.blockFormat().background(); if (background != Qt::NoBrush) { QRectF backgroundRect = bounds; backgroundRect.setWidth(maximumWidth); painter.fillRect(backgroundRect, background); } QList selections; QTextLayout* layout = block.layout(); for (const auto& selection : context.selections) { const int start = selection.cursor.selectionStart() - block.position(); const int end = selection.cursor.selectionEnd() - block.position(); QTextLayout::FormatRange range; range.format = selection.format; if (start < block.length() && end > 0 && end > start) { range.start = start; range.length = end - start; } else if (!selection.cursor.hasSelection() && selection.format.boolProperty(QTextFormat::FullWidthSelection) && block.contains(selection.cursor.position())) { const QTextLine line = layout->lineForTextPosition(start); range.start = line.textStart(); range.length = line.textLength(); if (range.start + range.length == block.length() - 1) ++range.length; } else { continue; } selections.append(range); } layout->draw(&painter, offset, selections, clip); paintInputDigitSeparators(painter, block, offset, context); } offset.ry() += bounds.height(); if (offset.y() > viewport()->height()) { block = block.next(); break; } } if (backgroundVisible() && !block.isValid() && offset.y() <= clip.bottom() && (centerOnScroll() || verticalScrollBar()->maximum() == verticalScrollBar()->minimum())) { painter.fillRect(QRect(QPoint(clip.left(), int(offset.y())), clip.bottomRight()), palette().window()); } const bool paintThemedCursor = shouldPaintThemedCursor(); const QRect themedCursor = paintThemedCursor ? themedCursorRect() : QRect(); if (!paintThemedCursor || !m_themedCursorVisible || !themedCursor.isValid()) return; painter.setClipRegion(event->region()); painter.setPen(Qt::NoPen); painter.fillRect(themedCursor, m_themePrimaryColor); } void Editor::historyBack() { if (!m_history.count()) return; if (!m_currentHistoryIndex) return; m_shouldBlockAutoCompletionOnce = true; if (m_currentHistoryIndex == m_history.count()) m_savedCurrentEditor = toPlainText(); --m_currentHistoryIndex; setText(historyExpressionForInput(m_history.at(m_currentHistoryIndex).expr())); moveCursorToEnd(this); ensureCursorVisible(); } Editor* Editor::completionMouseSelectionOwner() { return s_completionMouseSelectionOwner; } void Editor::historyForward() { if (!m_history.count()) return; if (m_currentHistoryIndex == m_history.count()) return; m_shouldBlockAutoCompletionOnce = true; m_currentHistoryIndex++; if (m_currentHistoryIndex == m_history.count()) setText(m_savedCurrentEditor); else setText(historyExpressionForInput(m_history.at(m_currentHistoryIndex).expr())); moveCursorToEnd(this); ensureCursorVisible(); } void Editor::triggerEnter() { m_completionTimer->stop(); m_matchingTimer->stop(); m_currentHistoryIndex = m_history.count(); emit returnPressed(); } void Editor::changeEvent(QEvent* event) { QPlainTextEdit::changeEvent(event); if (event->type() == QEvent::FontChange) { m_highlighter->rehighlight(); updateHeightAndEnsureCursorVisible(); } } bool Editor::event(QEvent* event) { if (event->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Tab && m_completion->handleEditorKeyPress(keyEvent)) return true; } return QPlainTextEdit::event(event); } void Editor::resizeEvent(QResizeEvent* event) { QPlainTextEdit::resizeEvent(event); updateHeightAndEnsureCursorVisible(); } void Editor::focusInEvent(QFocusEvent* event) { QPlainTextEdit::focusInEvent(event); showThemedCursorAndRestartBlink(); } void Editor::focusOutEvent(QFocusEvent* event) { QPlainTextEdit::focusOutEvent(event); if (m_completion->isVisible()) showThemedCursorAndRestartBlink(); else hideThemedCursorAndStopBlink(); } void Editor::inputMethodEvent(QInputMethodEvent* event) { if (!Settings::instance()->automaticInputAdjustments) { QPlainTextEdit::inputMethodEvent(event); return; } const int replacementPosition = event->replacementLength() > 0 ? textCursor().position() + event->replacementStart() : textCursor().selectionStart(); if (isInsideCommentFromQuestionMark(text(), replacementPosition)) { QPlainTextEdit::inputMethodEvent(event); return; } // Composed input can also rewrite existing text, such as an exponent. // Keep that rewrite in the same undo step as the committed characters. const bool hasCommittedEdit = !event->commitString().isEmpty() || event->replacementLength() > 0; const QScopedValueRollback inputEdit(m_inputEditInProgress, hasCommittedEdit); QTextCursor editCursor = textCursor(); if (hasCommittedEdit) editCursor.beginEditBlock(); const auto finishEdit = qScopeGuard([&]() { if (hasCommittedEdit) editCursor.endEditBlock(); }); const QString normalizedCommit = normalizeExpressionTypedInEditor(event->commitString()); const QString normalizedPreedit = normalizeExpressionTypedInEditor(event->preeditString()); const int cursorPosition = textCursor().position(); const bool squareBracketContext = isInsideUnmatchedSquareBracketContext( text(), cursorPosition); const QChar prev = previousNonSpaceChar(text(), cursorPosition); const bool autoAnsEnabled = Settings::instance()->autoAns; const bool atExpressionStart = !textCursor().hasSelection() && hasOnlyWhitespaceToLeft(text(), cursorPosition); if (atExpressionStart) { // Mirror keyPressEvent start-of-expression filtering for IME/dead-key // commits and preedit text; otherwise composed symbols can still appear. if (!normalizedCommit.isEmpty()) { const bool allAllowed = std::all_of( normalizedCommit.cbegin(), normalizedCommit.cend(), [autoAnsEnabled](const QChar& ch) { return EditorUtils::isAllowedLeadingCharAtExpressionStart(ch, autoAnsEnabled); }); if (!allAllowed) { event->accept(); return; } } if (normalizedCommit.isEmpty() && !normalizedPreedit.isEmpty()) { const bool allAllowedPreedit = std::all_of( normalizedPreedit.cbegin(), normalizedPreedit.cend(), [autoAnsEnabled](const QChar& ch) { return EditorUtils::isAllowedLeadingCharAtExpressionStart(ch, autoAnsEnabled); }); if (!allAllowedPreedit) { QInputMethodEvent clearEvent; QPlainTextEdit::inputMethodEvent(&clearEvent); event->accept(); return; } } } if (event->commitString().isEmpty() && textContainsOnlyCaretOperators(normalizedPreedit)) { if (isCaretOperatorAlias(prev)) { // Block dead-key/preedit caret echoes after an existing caret. // Send an empty IME update so any pending preedit is cleared. QInputMethodEvent clearEvent; QPlainTextEdit::inputMethodEvent(&clearEvent); event->accept(); return; } // On layouts that use dead-caret preedit (e.g. PT), remember this // so the next committed digit/minus can be converted to superscript // even if preedit is not carried over to the commit event. if (squareBracketContext) { const bool validExponentBase = prev.isLetterOrNumber() || prev == MathDsl::GroupEnd || prev == MathDsl::UnitEnd; m_pendingDeadCaretPreedit = validExponentBase; } else { m_pendingDeadCaretPreedit = true; } event->accept(); return; } if (textContainsOnlyCaretOperators(normalizedCommit)) { if (squareBracketContext && !isValidUnitExponentBase(prev)) { event->accept(); return; } const bool prevIsBlockingOperator = isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev); if (prevIsBlockingOperator) { event->accept(); return; } if (isCaretOperatorAlias(prev) || MathDsl::isSuperscriptPowerChar(prev)) { event->accept(); return; } } if (normalizedCommit.size() == 1 && !textCursor().hasSelection() && !(QApplication::keyboardModifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) { const QChar typed = normalizedCommit.at(0); const bool isTypedDigit = typed.isDigit(); const bool isTypedMinus = MathDsl::isSubtractionOperatorAlias(typed) || typed == MathDsl::PowNeg; if (isTypedDigit || isTypedMinus) { const int cursorPos = textCursor().position(); const int prevIndex = previousNonSpaceIndex(text(), cursorPos); const QChar prevChar = prevIndex >= 0 ? text().at(prevIndex) : QChar(); const int baseIndex = previousNonSpaceIndex(text(), prevIndex); const QChar baseBeforeCaret = baseIndex >= 0 ? text().at(baseIndex) : QChar(); const bool preeditCarriesCaret = textContainsOnlyCaretOperators(normalizedPreedit); const bool afterCaretRaw = isCaretOperatorAlias(prevChar); const bool afterCaretFromIme = preeditCarriesCaret || m_pendingDeadCaretPreedit; const bool afterCaret = afterCaretRaw || afterCaretFromIme; const bool continuingSuperscript = prevChar == MathDsl::PowNeg || MathDsl::isSuperscriptDigit(prevChar); const bool chainedAfterSuperscriptBase = afterCaretRaw && MathDsl::isSuperscriptPowerChar(baseBeforeCaret); if (squareBracketContext && afterCaretFromIme && !afterCaretRaw) { const bool validExponentBase = prevChar.isLetterOrNumber() || prevChar == MathDsl::GroupEnd || prevChar == MathDsl::UnitEnd; if (!validExponentBase) { event->accept(); return; } } const bool invalidSuperscriptMinus = isTypedMinus && (!afterCaret || chainedAfterSuperscriptBase || continuingSuperscript); if ((afterCaret || continuingSuperscript) && invalidSuperscriptMinus) { // Do not let raw IME minus/superscript-minus commit leak through // while inside an existing superscript exponent chain. event->accept(); return; } if ((afterCaret || continuingSuperscript) && !invalidSuperscriptMinus) { const QChar superscript = isTypedDigit ? MathDsl::asciiDigitToSuperscript(typed) : MathDsl::PowNeg; if (!superscript.isNull()) { QTextCursor cursor = textCursor(); if (isCaretOperatorAlias(prevChar)) { cursor.setPosition(prevIndex); cursor.setPosition(prevIndex + 1, QTextCursor::KeepAnchor); cursor.insertText(QString(superscript)); } else { cursor.insertText(QString(superscript)); } setTextCursor(cursor); m_pendingDeadCaretPreedit = false; event->accept(); return; } } } } if (!normalizedCommit.isEmpty()) m_pendingDeadCaretPreedit = false; if (textContainsOnlyAdditionAliases(normalizedCommit)) { if (squareBracketContext) { event->accept(); return; } const bool prevIsBlockingOperator = isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || prev == MathDsl::PowOp; if (prevIsBlockingOperator) { event->accept(); return; } const QString singlePlusAdjusted = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( text(), cursorPosition, QString(MathDsl::AddOp)); if (singlePlusAdjusted.isEmpty()) { event->accept(); return; } QInputMethodEvent normalizedEvent(event->preeditString(), event->attributes()); normalizedEvent.setCommitString(singlePlusAdjusted, event->replacementStart(), event->replacementLength()); QPlainTextEdit::inputMethodEvent(&normalizedEvent); return; } if (normalizedCommit.size() == 1 && MathDsl::isSubtractionOperatorAlias(normalizedCommit.at(0)) && !squareBracketContext) { if (!Settings::instance()->autoAns && textContainsOnlySubtractionAliases(text())) { event->accept(); return; } const bool prevIsBlockingOperator = isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || prev == MathDsl::PowOp; if (prevIsBlockingOperator) { event->accept(); return; } } if (squareBracketContext && !normalizedCommit.isEmpty()) { const QString adjusted = normalizeTypedTextForSquareBracketContext( text(), cursorPosition, normalizedCommit); if (adjusted.isEmpty()) { event->accept(); return; } if (adjusted != event->commitString()) { QInputMethodEvent normalizedEvent(event->preeditString(), event->attributes()); normalizedEvent.setCommitString(adjusted, event->replacementStart(), event->replacementLength()); QPlainTextEdit::inputMethodEvent(&normalizedEvent); return; } } if (normalizedCommit == event->commitString()) { QPlainTextEdit::inputMethodEvent(event); return; } QInputMethodEvent normalizedEvent(event->preeditString(), event->attributes()); normalizedEvent.setCommitString(normalizedCommit, event->replacementStart(), event->replacementLength()); QPlainTextEdit::inputMethodEvent(&normalizedEvent); } void Editor::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { m_mouseSelectionInProgress = true; m_currentAutoCalcDismissed = true; } QPlainTextEdit::mousePressEvent(event); } void Editor::mouseReleaseEvent(QMouseEvent* event) { QPlainTextEdit::mouseReleaseEvent(event); if (event->button() != Qt::LeftButton) return; m_mouseSelectionInProgress = false; if (textCursor().hasSelection()) checkSelectionAutoCalc(); } void Editor::keyPressEvent(QKeyEvent* event) { if (m_completion->isVisible()) m_completionTimer->stop(); if (m_completion->handleEditorKeyPress(event)) return; // Opening a picker must not start an empty document edit block. Finishing // that block emits textChanged and the active pane then takes focus back. if (event->key() == Qt::Key_Space && event->modifiers() == Qt::ControlModifier && !m_constantCompletion) { m_completionTimer->stop(); m_constantCompletion = new ConstantCompletion(this); m_constantCompletion->setThemeColors(m_completionBackgroundColor, m_completionForegroundColor, m_completionScrollbarThumbColor, m_completionScrollbarThumbForegroundColor, m_completionSelectedRowColor, m_completionSelectedRowForegroundColor, m_completionOutlineColor, m_completionCornerRadius, m_completionSearchButtonFill, m_completionSearchButtonCross); connect(m_constantCompletion, SIGNAL(selectedCompletion(const QString&)), SLOT(insertConstant(const QString&))); connect(m_constantCompletion, &ConstantCompletion::canceledCompletion, this, &Editor::cancelConstantCompletion); connect(m_constantCompletion, &ConstantCompletion::visibilityChanged, this, &Editor::constantSearchVisibilityChanged); m_constantCompletion->showCompletion(); event->accept(); return; } // Shortcut text can contain control characters or printable letters. // Let Qt perform the edit before any expression insertion rules run. if (event->matches(QKeySequence::Undo) || event->matches(QKeySequence::Redo) || event->matches(QKeySequence::Cut) || event->matches(QKeySequence::Paste)) { QPlainTextEdit::keyPressEvent(event); return; } if (event->matches(QKeySequence::Copy)) { emit copySequencePressed(); event->accept(); return; } if (event->matches(QKeySequence::SelectAll)) { QPlainTextEdit::keyPressEvent(event); if (textCursor().hasSelection()) checkSelectionAutoCalc(); else checkAutoCalc(); event->accept(); return; } const bool hasPrintableTextPayload = !event->text().isEmpty() && (event->key() < Qt::Key_Escape || event->key() == Qt::Key_unknown) && std::all_of(event->text().cbegin(), event->text().cend(), [](const QChar& ch) { return ch.isPrint(); }); // Keep a typed key and its automatic rewrites together, while preventing // consecutive digits from merging into one undo step. const QScopedValueRollback inputEdit(m_inputEditInProgress, hasPrintableTextPayload); QTextCursor editCursor = textCursor(); if (hasPrintableTextPayload) editCursor.beginEditBlock(); const auto finishEdit = qScopeGuard([&]() { if (hasPrintableTextPayload) editCursor.endEditBlock(); }); int key = event->key(); switch (key) { case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Down: case Qt::Key_Home: case Qt::Key_End: m_currentAutoCalcDismissed = true; break; default: break; } switch (key) { case Qt::Key_Tab: // setTabChangesFocus() still allows entering a Tab character when // there's no other widgets to change focus to. To avoid that, // explicitly consume any Tabs that make it here. event->accept(); return; case Qt::Key_Enter: case Qt::Key_Return: triggerEnter(); event->accept(); return; case Qt::Key_Escape: m_currentAutoCalcDismissed = true; emit escapePressed(); event->accept(); return; case Qt::Key_Up: if (!m_historyArrowNavigationEnabled) { QPlainTextEdit::keyPressEvent(event); event->accept(); return; } if (event->modifiers() & Qt::ShiftModifier) emit shiftUpPressed(); else if (Settings::instance()->upDownArrowBehavior == Settings::UpDownArrowBehaviorAlways || (Settings::instance()->upDownArrowBehavior == Settings::UpDownArrowBehaviorSingleLineOnly && height() <= sizeHint().height())) historyBack(); else QPlainTextEdit::keyPressEvent(event); event->accept(); return; case Qt::Key_Down: if (!m_historyArrowNavigationEnabled) { QPlainTextEdit::keyPressEvent(event); event->accept(); return; } if (event->modifiers() & Qt::ShiftModifier) emit shiftDownPressed(); else if (Settings::instance()->upDownArrowBehavior == Settings::UpDownArrowBehaviorAlways || (Settings::instance()->upDownArrowBehavior == Settings::UpDownArrowBehaviorSingleLineOnly && height() <= sizeHint().height())) historyForward(); else QPlainTextEdit::keyPressEvent(event); event->accept(); return; case Qt::Key_PageUp: if (event->modifiers() & Qt::ShiftModifier) emit shiftPageUpPressed(); else if (event->modifiers() & Qt::ControlModifier) emit controlPageUpPressed(); else emit pageUpPressed(); event->accept(); return; case Qt::Key_PageDown: if (event->modifiers() & Qt::ShiftModifier) emit shiftPageDownPressed(); else if (event->modifiers() & Qt::ControlModifier) emit controlPageDownPressed(); else emit pageDownPressed(); event->accept(); return; default: break; } if (!Settings::instance()->automaticInputAdjustments) { // Keep calculator commands above, but let Qt edit every character as // ordinary text, including operators and incomplete expressions. QPlainTextEdit::keyPressEvent(event); return; } const int cursorPosition = textCursor().position(); if (isInsideCommentFromQuestionMark(text(), textCursor().selectionStart()) && !(event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) && hasPrintableTextPayload) { QPlainTextEdit::keyPressEvent(event); return; } const bool squareBracketContext = isInsideUnmatchedSquareBracketContext( text(), cursorPosition); const bool rightOfOpeningSquareBracket = squareBracketContext && isRightOfOpeningSquareBracketWithOnlySpaces(text(), cursorPosition); const bool emptyOrOnlySpacesUnitContext = squareBracketContext && isCurrentUnitContextEmptyOrOnlySpaces(text(), cursorPosition); if (squareBracketContext && isDeadKey(key) && key != Qt::Key_Dead_Circumflex && key != Qt::Key_Dead_Acute && key != Qt::Key_Dead_Diaeresis) { event->accept(); return; } const auto implicitMulPrefixForTypedChar = [this](QChar typedChar) { const QString typedText(typedChar); const QString adjusted = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( text(), textCursor().position(), typedText); if (adjusted.size() > typedText.size() && adjusted.endsWith(typedText)) return adjusted.left(adjusted.size() - typedText.size()); return QString(); }; const QString normalizedEventText = hasPrintableTextPayload ? normalizeExpressionTypedInEditor(event->text()) : QString(); const auto isOperatorLikeSingleCharInput = [](const QString& input) { if (input.size() != 1) return false; const QChar ch = input.at(0); return EditorUtils::isAnyOperator(ch) || MathDsl::isAdditionOperatorAlias(ch) || MathDsl::isSubtractionOperatorAlias(ch) || MathDsl::isDivisionOperatorAlias(ch) || MathDsl::isMultiplicationOperatorAlias(ch, true); }; if (emptyOrOnlySpacesUnitContext && !(event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) && (key == Qt::Key_Space || isAnyOperatorKey(key) || isOperatorLikeSingleCharInput(event->text()) || isOperatorLikeSingleCharInput(normalizedEventText))) { event->accept(); return; } if (!textCursor().hasSelection() && (hasPrintableTextPayload || isDeadKey(key)) && hasOnlyWhitespaceToLeft(text(), cursorPosition)) { const bool autoAnsEnabledForStart = Settings::instance()->autoAns; // When "Auto-insert ans..." is off, treat expression start as a strict // allowlist gate. This blocks layout-specific AltGr/dead-key symbols // from bypassing leading-operator restrictions. // // When it is on, apply the same gate but allow +/*//^ starters too so // main-window auto-ans rewrite can still trigger. const QString typedCandidate = !normalizedEventText.isEmpty() ? normalizedEventText : event->text(); if (!typedCandidate.isEmpty()) { const bool allAllowed = std::all_of( typedCandidate.cbegin(), typedCandidate.cend(), [autoAnsEnabledForStart](const QChar& ch) { return ch.isSpace() || ch == MathDsl::DotSep || ch == MathDsl::CommaSep || EditorUtils::isAllowedLeadingCharAtExpressionStart(ch, autoAnsEnabledForStart); }); if (!allAllowed) { event->accept(); return; } } else if (isDeadKey(key) && key != Qt::Key_Dead_Tilde && (key != Qt::Key_Dead_Circumflex || !autoAnsEnabledForStart)) { event->accept(); return; } } const auto tryHandleSuperscriptExponentTyping = [&]() -> bool { if ((event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) || textCursor().hasSelection() || normalizedEventText.size() != 1) { return false; } const QChar typed = normalizedEventText.at(0); const bool isTypedDigit = typed.isDigit(); const bool isTypedMinus = MathDsl::isSubtractionOperatorAlias(typed) || typed == MathDsl::PowNeg; if (!isTypedDigit && !isTypedMinus) return false; const int cursorPos = textCursor().position(); const int prevIndex = previousNonSpaceIndex(text(), cursorPos); if (prevIndex < 0) return false; const QChar prev = text().at(prevIndex); const int baseIndex = previousNonSpaceIndex(text(), prevIndex); const QChar baseBeforeCaret = baseIndex >= 0 ? text().at(baseIndex) : QChar(); const bool afterCaret = isCaretOperatorAlias(prev); const bool continuingSuperscript = prev == MathDsl::PowNeg || MathDsl::isSuperscriptDigit(prev); const bool chainedAfterSuperscriptBase = afterCaret && MathDsl::isSuperscriptPowerChar(baseBeforeCaret); if (!afterCaret && !continuingSuperscript) return false; if (isTypedMinus && (!afterCaret || chainedAfterSuperscriptBase || continuingSuperscript)) return false; const QChar superscript = isTypedDigit ? MathDsl::asciiDigitToSuperscript(typed) : MathDsl::PowNeg; if (superscript.isNull()) return false; QTextCursor cursor = textCursor(); if (afterCaret) { cursor.setPosition(prevIndex); cursor.setPosition(prevIndex + 1, QTextCursor::KeepAnchor); cursor.insertText(QString(superscript)); } else { cursor.insertText(QString(superscript)); } setTextCursor(cursor); event->accept(); return true; }; if (tryHandleSuperscriptExponentTyping()) return; const auto tryHandleTypedGroupStart = [&]() -> bool { if (textCursor().hasSelection()) return false; QTextCursor cursor = textCursor(); const int position = cursor.position(); const bool shouldAutoInsertGroupEnd = hasOnlySpacesToRight(text(), position); const QString insertedGroupStart = QString(MathDsl::GroupStart); const QString insertedGroupPair = QString(MathDsl::GroupStart) + QString(MathDsl::GroupEnd); cursor.insertText(shouldAutoInsertGroupEnd ? insertedGroupPair : insertedGroupStart); cursor.setPosition(position + 1); setTextCursor(cursor); event->accept(); return true; }; if (key == Qt::Key_Dead_Circumflex) { // PT and similar layouts emit a dead-circumflex key before commit. // Consume it when a caret is already on the left to avoid a second // pending caret from composition. const QChar prev = previousNonSpaceChar(text(), cursorPosition); if (squareBracketContext && !isValidUnitExponentBase(prev)) { event->accept(); return; } if (isCaretOperatorAlias(prev)) { event->accept(); return; } const bool prevIsBlockingOperator = isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev); if (prevIsBlockingOperator) { event->accept(); return; } insert(QStringLiteral("^")); event->accept(); return; } const bool isTypedTilde = key == Qt::Key_Dead_Tilde || key == Qt::Key_AsciiTilde || event->text() == QLatin1String("~") || normalizedEventText == QLatin1String("~"); if (isTypedTilde) { if (squareBracketContext) { event->accept(); return; } const QChar prev = previousNonSpaceChar(text(), cursorPosition); const bool prevAllowsUnaryTilde = prev.isNull() || prev == MathDsl::GroupStart || prev == MathDsl::UnitStart || isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || isCaretOperatorAlias(prev); if (prevAllowsUnaryTilde) { insert(QStringLiteral("~")); } event->accept(); return; } if (textContainsOnlyAdditionAliases(event->text()) || textContainsOnlyAdditionAliases(normalizedEventText)) { if (squareBracketContext) { event->accept(); return; } const QChar prev = previousNonSpaceChar(text(), cursorPosition); const bool prevIsBlockingOperator = isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || prev == MathDsl::PowOp; if (prevIsBlockingOperator) { event->accept(); return; } const QString singlePlusAdjusted = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( text(), textCursor().position(), QString(MathDsl::AddOp)); if (!singlePlusAdjusted.isEmpty()) insert(singlePlusAdjusted); event->accept(); return; } // Use the layout's text payload before falling back to the logical key. // Shift+Key_Equal can produce '=' on Portuguese keyboards, not just '+'. const bool isTypedPlus = normalizedTypedCharFromEvent(event, normalizedEventText) == MathDsl::AddOp; if (isTypedPlus) { if (squareBracketContext) { event->accept(); return; } const QChar prev = previousNonSpaceChar(text(), cursorPosition); if (isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || prev == MathDsl::PowOp) { event->accept(); return; } } const bool isTypedCaret = key == Qt::Key_AsciiCircum || textContainsOnlyCaretOperators(event->text()) || textContainsOnlyCaretOperators(normalizedEventText); if (isTypedCaret) { const QChar prev = previousNonSpaceChar(text(), cursorPosition); if (squareBracketContext && !isValidUnitExponentBase(prev)) { event->accept(); return; } const bool prevIsBlockingOperator = isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev); if (prevIsBlockingOperator) { event->accept(); return; } if (isCaretOperatorAlias(prev) || MathDsl::isSuperscriptPowerChar(prev)) { event->accept(); return; } } if (squareBracketContext && (textContainsOnlyDivisionAliases(event->text()) || textContainsOnlyDivisionAliases(normalizedEventText))) { rewriteTrailingAsciiUnitExponentToSuperscript(this, QString()); const int cursorPos = textCursor().position(); const QChar previous = previousNonSpaceChar(text(), cursorPos); if (MathDsl::isDivisionOperatorAlias(previous)) { int previousIndex = qBound(0, cursorPos, text().size()) - 1; while (previousIndex >= 0 && text().at(previousIndex).isSpace()) --previousIndex; if (previousIndex >= 1 && text().at(previousIndex - 1) == MathDsl::PowOp) { auto cursor = textCursor(); cursor.setPosition(previousIndex + 1); cursor.deletePreviousChar(); setTextCursor(cursor); event->accept(); return; } } const QString adjusted = normalizeTypedTextForSquareBracketContext( text(), textCursor().position(), QString(MathDsl::DivOp)); if (!adjusted.isEmpty()) insert(adjusted); event->accept(); return; } if (squareBracketContext && (event->text() == QLatin1String("]") || key == Qt::Key_BracketRight) && !textCursor().hasSelection()) { const QString currentText = text(); const int cursorPos = textCursor().position(); const int openPos = currentText.lastIndexOf(MathDsl::UnitStart, cursorPos - 1); if (openPos >= 0) { QTextCursor cursor = textCursor(); const QString unitBody = currentText.mid(openPos + 1, cursorPos - (openPos + 1)); const QString normalizedBody = renderUnitAsciiExponentsAsSuperscripts(unitBody); cursor.setPosition(openPos + 1); cursor.setPosition(cursorPos, QTextCursor::KeepAnchor); cursor.insertText(normalizedBody); cursor.insertText(QStringLiteral("]")); setTextCursor(cursor); event->accept(); return; } } if (squareBracketContext && !normalizedEventText.isEmpty() && std::all_of(normalizedEventText.cbegin(), normalizedEventText.cend(), isTypedMultiplicationCharacter)) { rewriteTrailingAsciiUnitExponentToSuperscript(this, QString()); } const bool isTypedGroupStart = key == Qt::Key_ParenLeft || event->text() == QLatin1String("(") || normalizedEventText == QLatin1String("("); if (isTypedGroupStart && tryHandleTypedGroupStart()) return; const bool isTypedRadixSeparator = key == Qt::Key_Period || key == Qt::Key_Comma || event->text() == QLatin1String(".") || event->text() == QLatin1String(",") || normalizedEventText == QLatin1String(".") || normalizedEventText == QLatin1String(","); if (isTypedRadixSeparator) { if (!(event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) { const QString radix = QString(QChar(this->radixChar())); if (rewriteTrailingSuperscriptExponentToParenthesizedAscii(this, radix)) { event->accept(); return; } const QChar prev = previousNonSpaceChar(text(), textCursor().position()); if (prev == QChar(this->radixChar()) || prev == MathDsl::DotSep || prev == MathDsl::CommaSep) { event->accept(); return; } const bool startsNewDecimalAfterOperator = prev.isNull() || prev == MathDsl::AddOp || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isMultiplicationOperator(prev) || MathDsl::isMultiplicationOperatorAlias(prev, true) || MathDsl::isDivisionOperator(prev) || MathDsl::isDivisionOperatorAlias(prev) || prev == MathDsl::PercentOp || prev == MathDsl::PowOp || prev == MathDsl::BitAndOp || prev == MathDsl::BitOrOp || prev == MathDsl::Equals || prev == MathDsl::LessThanOp || prev == MathDsl::GreaterThanOp; if (startsNewDecimalAfterOperator) { insert(QStringLiteral("0") + radix); event->accept(); return; } if (prev == MathDsl::GroupEnd || prev == MathDsl::UnitEnd || prev.isLetter()) { QString prefix = MathDsl::buildWrappedToken(MathDsl::MulCrossOp, MathDsl::MulCrossWrapSp); const int pos = textCursor().position(); if (pos > 0 && text().at(pos - 1).isSpace() && !prefix.isEmpty() && prefix.at(0).isSpace()) prefix.remove(0, 1); insert(prefix + QStringLiteral("0") + radix); event->accept(); return; } if (!prev.isDigit()) { event->accept(); return; } } if (event->modifiers() == Qt::KeypadModifier) { insert(QChar(this->radixChar())); event->accept(); return; } } const QChar typedForRules = normalizedTypedCharFromEvent(event, normalizedEventText); if (key != Qt::Key_Enter && key != Qt::Key_Return && !(event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) && !textCursor().hasSelection() && !typedForRules.isNull()) { const QChar prev = previousNonSpaceChar(text(), cursorPosition); const auto isGroupStartLetterDigitOrCurrency = [](const QChar& ch) { return ch == MathDsl::GroupStart || ch == MathDsl::ListStart || ch.isLetter() || ch.isDigit() || isCurrencySymbolChar(ch); }; if (typedForRules == MathDsl::GreaterThanOp && MathDsl::isSubtractionOperatorAlias(prev)) { replacePreviousSubtractionAtCursorWithUnitConversion(this); event->accept(); return; } if (typedForRules == MathDsl::SubOp && MathDsl::isSubtractionOperatorAlias(prev)) { const int prevIndex = previousNonSpaceIndex(text(), cursorPosition); const int beforePrevIndex = previousNonSpaceIndex(text(), prevIndex); if (beforePrevIndex < 0 || !canEndUnitConversionLeftOperand(text().at(beforePrevIndex))) { event->accept(); return; } replacePreviousSubtractionAtCursorWithUnitConversion(this); event->accept(); return; } if (typedForRules == MathDsl::TransOp && !squareBracketContext) { insertUnitConversionAtCursorWithUnitPlaceholder(this); event->accept(); return; } if (typedForRules == MathDsl::LessThanOp || typedForRules == MathDsl::GreaterThanOp) { const int pos = textCursor().position(); const QString wrappedShift = typedForRules == MathDsl::LessThanOp ? wrappedShiftLeftToken() : wrappedShiftRightToken(); if (pos >= wrappedShift.size() && text().mid(pos - wrappedShift.size(), wrappedShift.size()) == wrappedShift) { event->accept(); return; } if (isBlockingBinaryOperator(prev)) { event->accept(); return; } } if (MathDsl::isSubtractionOperatorAlias(prev) || isAnyAdditionOperator(prev) || MathDsl::isDivisionOperatorAlias(prev)) { const bool isRadixSeparator = typedForRules == MathDsl::DotSep || typedForRules == MathDsl::CommaSep; const bool isUnitConversionTail = MathDsl::isSubtractionOperatorAlias(prev) && typedForRules == MathDsl::GreaterThanOp; if (!isGroupStartLetterDigitOrCurrency(typedForRules) && !isRadixSeparator && !isUnitConversionTail) { event->accept(); return; } } else if (isCaretOperatorAlias(prev)) { if (!(MathDsl::isSubtractionOperatorAlias(typedForRules) || typedForRules == MathDsl::GroupStart || typedForRules == MathDsl::ListStart || typedForRules.isLetter() || typedForRules.isDigit() || isCurrencySymbolChar(typedForRules))) { event->accept(); return; } } else if (isAnyMultiplicationOperator(prev)) { if (typedForRules == MathDsl::GroupStart || typedForRules == MathDsl::ListStart || typedForRules.isLetter() || isCurrencySymbolChar(typedForRules) || (typedForRules.isDigit() && !squareBracketContext)) { // Allowed as-is. } else if (isAnyMultiplicationOperator(typedForRules)) { const int prevIndex = previousNonSpaceIndex(text(), cursorPosition); const int beforePrevIndex = previousNonSpaceIndex(text(), prevIndex); if (beforePrevIndex >= 0 && isExponentTailBeforeIndex(text(), beforePrevIndex)) { event->accept(); return; } replacePreviousOperatorAtCursorWithCaret(this); event->accept(); return; } else { event->accept(); return; } } } if (rightOfOpeningSquareBracket && (isAnyOperatorKey(key) || (event->text().size() == 1 && EditorUtils::isAnyOperator(event->text().at(0))) || (normalizedEventText.size() == 1 && EditorUtils::isAnyOperator(normalizedEventText.at(0))))) { event->accept(); return; } if ((event->text() == QLatin1String("[") || key == Qt::Key_BracketLeft) && !textCursor().hasSelection()) { if (squareBracketContext) { event->accept(); return; } const QChar previous = previousNonSpaceChar(text(), textCursor().position()); if (previous == MathDsl::UnitEnd) { event->accept(); return; } QTextCursor cursor = textCursor(); const int position = cursor.position(); const bool shouldAutoInsertUnitEnd = hasOnlySpacesToRight(text(), position); const bool shouldInsertValueUnitSpace = previous == MathDsl::GroupEnd || !implicitMulPrefixForTypedChar(MathDsl::UnitStart).isEmpty(); const QString prefix = shouldInsertValueUnitSpace ? QString(MathDsl::QuantSp) : QString(); if (shouldInsertValueUnitSpace) { int left = position; while (left > 0 && text().at(left - 1).isSpace()) --left; if (left < position) { cursor.setPosition(left); cursor.setPosition(position, QTextCursor::KeepAnchor); cursor.removeSelectedText(); } } const int insertionPosition = cursor.position(); QString insertedUnit = prefix + MathDsl::UnitStart; if (shouldAutoInsertUnitEnd) insertedUnit += MathDsl::UnitEnd; cursor.insertText(insertedUnit); cursor.setPosition(insertionPosition + prefix.size() + 1); setTextCursor(cursor); event->accept(); return; } switch (key) { case Qt::Key_Left: case Qt::Key_Right: { const bool isModifiedNavigation = event->modifiers() & (Qt::AltModifier | Qt::ControlModifier | Qt::MetaModifier); const bool keepAnchor = event->modifiers() & Qt::ShiftModifier; QTextCursor cursor = textCursor(); if (!isModifiedNavigation && (keepAnchor || !cursor.hasSelection())) { // Plain left/right movement should keep grouped spaced // operators atomic, so single-step arrows do not stop // inside "". const int position = cursor.position(); int newPosition = -1; if (key == Qt::Key_Left) { const int groupedLength = groupedTokenLengthBefore(text(), position); if (groupedLength > 0) newPosition = position - groupedLength; else { const int groupedLengthAtNext = groupedTokenLengthBefore(text(), position + 1); if (groupedLengthAtNext > 0) newPosition = position - (groupedLengthAtNext - 1); } } else if (key == Qt::Key_Right) { const int groupedLength = groupedTokenLengthAfter(text(), position); if (groupedLength > 0) newPosition = position + groupedLength; else if (position > 0) { const int groupedLengthAtPrev = groupedTokenLengthAfter(text(), position - 1); if (groupedLengthAtPrev > 0) newPosition = position + (groupedLengthAtPrev - 1); } } if (newPosition >= 0) { cursor.setPosition(newPosition, keepAnchor ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); setTextCursor(cursor); checkMatching(); if (textCursor().hasSelection()) checkSelectionAutoCalc(); event->accept(); return; } } const int oldPosition = textCursor().position(); QPlainTextEdit::keyPressEvent(event); cursor = textCursor(); int newPosition = cursor.position(); if (isModifiedNavigation && newPosition == oldPosition) { // Some platforms/layouts may not move with Alt/Ctrl/Meta+arrows. // Still keep grouped spaced operators atomic when the cursor is // immediately before/after one. if (key == Qt::Key_Left) { const int groupedLength = groupedTokenLengthBefore(text(), oldPosition); if (groupedLength > 0) newPosition = oldPosition - groupedLength; } else if (key == Qt::Key_Right) { const int groupedLength = groupedTokenLengthAfter(text(), oldPosition); if (groupedLength > 0) newPosition = oldPosition + groupedLength; } if (newPosition != oldPosition) { cursor.setPosition(newPosition, keepAnchor ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); setTextCursor(cursor); checkMatching(); if (textCursor().hasSelection()) checkSelectionAutoCalc(); event->accept(); return; } } if (isModifiedNavigation && newPosition != oldPosition) { // Alt/Ctrl/Meta navigation uses native Qt word movement first. // Then, if that move lands at/inside a grouped spaced operator, // snap to the nearest valid side of the triplet to keep it // atomic without changing normal word-jump semantics. int groupLength = 0; const int groupStart = groupedTokenStartAround(text(), newPosition, &groupLength); if (groupStart >= 0) { if (key == Qt::Key_Right && newPosition > oldPosition) { // Use strict-side comparison so repeated Alt+Right does // not get stuck at the same boundary. newPosition = (oldPosition < groupStart) ? groupStart : groupStart + groupLength; } else if (key == Qt::Key_Left && newPosition < oldPosition) { // Use strict-side comparison so repeated Alt+Left keeps // progressing past grouped operators. newPosition = (oldPosition > groupStart + groupLength) ? groupStart + groupLength : groupStart; } } if (newPosition != cursor.position()) { cursor.setPosition(newPosition, keepAnchor ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); setTextCursor(cursor); } } } checkMatching(); if (textCursor().hasSelection()) checkSelectionAutoCalc(); event->accept(); return; case Qt::Key_Home: case Qt::Key_End: QPlainTextEdit::keyPressEvent(event); checkMatching(); if (textCursor().hasSelection()) checkSelectionAutoCalc(); event->accept(); return; case Qt::Key_Backspace: if (event->matches(QKeySequence::DeleteStartOfWord)) { // Preserve word-delete shortcuts (platform-dependent Alt/Ctrl+BS), // but still treat grouped spaced operators as a single unit. if (!textCursor().hasSelection() && isAfterGroupedSpacedOperator(text(), textCursor().position())) { doBackspace(); event->accept(); return; } QPlainTextEdit::keyPressEvent(event); event->accept(); return; } doBackspace(); event->accept(); return; case Qt::Key_Delete: if (event->matches(QKeySequence::DeleteEndOfWord)) { // Preserve word-delete shortcuts (platform-dependent Alt/Ctrl+Del), // but still treat grouped spaced operators as a single unit. if (!textCursor().hasSelection() && isBeforeGroupedSpacedOperator(text(), textCursor().position())) { doDelete(); event->accept(); return; } QPlainTextEdit::keyPressEvent(event); event->accept(); return; } doDelete(); event->accept(); return; case Qt::Key_Space: if (event->modifiers() == Qt::NoModifier) { const int pos = textCursor().position(); if (pos > 0 && text().at(pos - 1).isSpace()) { event->accept(); return; } } if (event->modifiers() == Qt::NoModifier && squareBracketContext) { if (appendSuffixAfterTrailingSuperscriptExponent(this, QString(MathDsl::MulDotOp))) { event->accept(); return; } if (rewriteTrailingAsciiUnitExponentToSuperscript(this, QString(MathDsl::MulDotOp))) { event->accept(); return; } } if (event->modifiers() == Qt::NoModifier && squareBracketContext) { const QString adjusted = normalizeTypedTextForSquareBracketContext( text(), textCursor().position(), QStringLiteral(" ")); if (!adjusted.isEmpty()) insert(adjusted); event->accept(); return; } break; case Qt::Key_Asterisk: { if (squareBracketContext) { rewriteTrailingAsciiUnitExponentToSuperscript(this, QString()); auto position = textCursor().position(); const QChar prev = previousNonSpaceChar(text(), position); if (MathDsl::isSuperscriptPowerChar(prev)) { insert(QString(MathDsl::MulDotOp)); event->accept(); return; } const int opIndex = previousNonSpaceIndex(text(), position); const QChar op = opIndex >= 0 ? text().at(opIndex) : QChar(); if (op == MathDsl::MulOpAl1 || op == MathDsl::MulCrossOp || op == MathDsl::MulDotOp) { const int beforeOpIndex = previousNonSpaceIndex(text(), opIndex); if (beforeOpIndex >= 0 && isExponentTailBeforeIndex(text(), beforeOpIndex)) { // Do not allow "**" to become "^" after superscript exponents. event->accept(); return; } auto cursor = textCursor(); cursor.removeSelectedText(); cursor.deletePreviousChar(); insert(QString::fromUtf8("^")); } else { insert(QString(MathDsl::MulDotOp)); } event->accept(); return; } auto position = textCursor().position(); const int opIndex = previousNonSpaceIndex(text(), position); const QChar op = opIndex >= 0 ? text().at(opIndex) : QChar(); if (op == MathDsl::MulOpAl1 || op == MathDsl::MulCrossOp || op == MathDsl::MulDotOp) { const int beforeOpIndex = previousNonSpaceIndex(text(), opIndex); if (beforeOpIndex >= 0 && isExponentTailBeforeIndex(text(), beforeOpIndex)) { event->accept(); return; } } if (op == MathDsl::MulOpAl1 || op == MathDsl::MulCrossOp) { const int beforeOpIndex = previousNonSpaceIndex(text(), opIndex); if (beforeOpIndex >= 0 && MathDsl::isSuperscriptPowerChar(text().at(beforeOpIndex))) { event->accept(); return; } // Replace ×* by ^ operator auto cursor = textCursor(); cursor.removeSelectedText(); // just in case some text is selected cursor.deletePreviousChar(); insert(QString::fromUtf8("^")); } else { insert(EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( text(), textCursor().position(), QString(MathDsl::MulCrossOp))); } event->accept(); return; } case Qt::Key_Plus: case Qt::Key_Equal: if (key == Qt::Key_Equal && !isTypedPlus) { const QChar prev = previousNonSpaceChar(text(), textCursor().position()); if (isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || prev == MathDsl::PowOp || prev == MathDsl::Equals) { event->accept(); return; } insert(EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( text(), textCursor().position(), QString(MathDsl::Equals))); event->accept(); return; } { const QChar prev = previousNonSpaceChar(text(), textCursor().position()); if (isAnyAdditionOperator(prev) || MathDsl::isSubtractionOperatorAlias(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || prev == MathDsl::PowOp) { event->accept(); return; } insert(EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( text(), textCursor().position(), QString(MathDsl::AddOp))); event->accept(); return; } case Qt::Key_Minus: if (squareBracketContext) { const QString adjusted = normalizeTypedTextForSquareBracketContext( text(), textCursor().position(), QString(MathDsl::SubOp)); if (!adjusted.isEmpty()) insert(adjusted); event->accept(); return; } if (!Settings::instance()->autoAns && textContainsOnlySubtractionAliases(text())) { event->accept(); return; } { const QChar prev = previousNonSpaceChar(text(), textCursor().position()); if (MathDsl::isSubtractionOperatorAlias(prev) || isAnyAdditionOperator(prev) || MathDsl::isDivisionOperatorAlias(prev) || isAnyMultiplicationOperator(prev) || prev == MathDsl::PowOp) { event->accept(); return; } } insert(EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( text(), textCursor().position(), QString(MathDsl::SubOp))); event->accept(); return; case Qt::Key_Slash: if (squareBracketContext) { const QString adjusted = normalizeTypedTextForSquareBracketContext( text(), textCursor().position(), QString(MathDsl::DivOp)); if (!adjusted.isEmpty()) insert(adjusted); event->accept(); return; } break; case Qt::Key_At: insert(QString(MathDsl::Deg)); // U+00B0 ° DEGREE SIGN event->accept(); return; case Qt::Key_ParenLeft: break; default:; } QString normalizedText = normalizedEventText; if (!(event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) && normalizedText == QLatin1String("?") && !isInsideCommentFromQuestionMark(text(), textCursor().position())) { const int cursorPos = textCursor().position(); const int prevIndex = cursorPos - 1; const bool needsLeftSpace = hasAnyNonWhitespace(text()) && prevIndex >= 0 && !text().at(prevIndex).isSpace(); const bool needsRightSpace = cursorPos >= text().size() || !text().at(cursorPos).isSpace(); normalizedText = QString(); if (needsLeftSpace) normalizedText += QLatin1Char(' '); normalizedText += MathDsl::CommentSep; if (needsRightSpace) normalizedText += QLatin1Char(' '); } const QString implicitMulAdjustedText = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( text(), textCursor().position(), normalizedText); const QString contextAdjustedText = squareBracketContext ? normalizeTypedTextForSquareBracketContext(text(), textCursor().position(), implicitMulAdjustedText) : implicitMulAdjustedText; if (squareBracketContext && contextAdjustedText != implicitMulAdjustedText) { if (!contextAdjustedText.isEmpty()) insert(contextAdjustedText); event->accept(); return; } if (!contextAdjustedText.isEmpty() && contextAdjustedText != event->text()) { insert(contextAdjustedText); event->accept(); return; } // For printable text input, always go through Editor::insert() so all // normalization and operator guards are consistently applied. if (!normalizedText.isEmpty()) { insert(contextAdjustedText.isEmpty() ? normalizedText : contextAdjustedText); event->accept(); return; } QPlainTextEdit::keyPressEvent(event); } void Editor::scrollContentsBy(int dx, int dy) { if (dy && !m_canScrollWrappedText) { verticalScrollBar()->setValue(verticalScrollBar()->minimum()); return; } QPlainTextEdit::scrollContentsBy(dx, dy); } void Editor::updateHeightForWrappedText() { int visualLineCount = 0; qreal blockTop = 0; qreal textHeight = 0; for (QTextBlock block = document()->begin(); block.isValid(); block = block.next()) { // Highlighting can invalidate wrapping before Qt lays the block out again. // Resolve it before counting lines so the editor does not briefly shrink. const QRectF bounds = blockBoundingRect(block); const QTextLayout* layout = block.layout(); if (layout) { for (int i = 0; i < layout->lineCount() && visualLineCount + i < 5; ++i) { const QTextLine line = layout->lineAt(i); textHeight = qMax(textHeight, blockTop + line.y() + line.height()); } } visualLineCount += layout ? std::max(1, layout->lineCount()) : 1; blockTop += bounds.height(); } // Use Qt's laid-out span, including leading and font fallback. Multiplying // font metrics by the line count can leave extra space or clip the text. if (textHeight <= 0) textHeight = editorLineHeight(font()); m_canScrollWrappedText = visualLineCount > 5; setFixedHeight(int(std::ceil(textHeight)) + editorVerticalDecorationHeight()); if (!m_canScrollWrappedText) verticalScrollBar()->setValue(verticalScrollBar()->minimum()); } void Editor::updateHeightAndEnsureCursorVisible() { if (m_updatingWrappedTextHeight) return; const QScopedValueRollback updatingHeight(m_updatingWrappedTextHeight, true); updateHeightForWrappedText(); if (m_canScrollWrappedText) ensureCursorVisible(); } void Editor::wheelEvent(QWheelEvent* event) { if (m_completion->handleEditorWheelEvent(event)) return; if (event->angleDelta().y() > 0) historyBack(); else if (event->angleDelta().y() < 0) historyForward(); event->accept(); } void Editor::refreshInputMode() { // A dead caret from the previous mode must not affect the next edit. m_pendingDeadCaretPreedit = false; rehighlight(); } void Editor::rehighlight() { StartupDiagnostics::AppearanceScope timing("Refresh editor highlighting and appearance", this); if (StartupDiagnostics::isRecording()) { const QByteArray theme = m_themePreviewColorScheme.has_value() ? StartupDiagnostics::themeInputs(*m_themePreviewColorScheme) : StartupDiagnostics::configuredThemeInputs(); StartupDiagnostics::observeHighlightInputs(timing, this, theme, {m_themeSurfaceColor, m_themeOuterSurfaceColor, m_themePrimaryColor, m_usePrimaryOutline}, m_evaluator); } // Qt can emit textChanged while applying styles and highlighting. // A theme refresh must not act like an edit or clear a result selection. const QSignalBlocker blocker(this); if (m_themePreviewColorScheme.has_value()) m_highlighter->setColorScheme( ColorScheme::fromJsonObject(m_themePreviewColorScheme->toJsonObject())); else m_highlighter->updateColorScheme(); updateMatchedParenthesisColors(); updateAppearance(); { StartupDiagnostics::AppearanceScope highlightTiming("Highlight editor document", this); m_highlighter->rehighlight(); } updateHeightAndEnsureCursorVisible(); } void Editor::updateAppearance() { StartupDiagnostics::AppearanceScope timing("Refresh editor appearance", this); // Style changes must preserve the expression and any result selection. const QSignalBlocker blocker(this); const QColor themeBackground = m_highlighter->colorForRole(ColorScheme::Background); const QColor generatedPrimary = generatePrimaryFromBackground(themeBackground); // Editors can rehighlight before MainWindow injects the resolved theme // primary. Use the same generated primary fallback here so the editor's // default text styling never depends on a color-scheme accent role. const QColor primaryColor = m_themePrimaryColor.isValid() ? m_themePrimaryColor : (generatedPrimary.isValid() ? generatedPrimary : QApplication::palette().color(QPalette::Text)); const bool classic = Settings::instance()->editorDisplayStyle == Settings::EditorDisplayClassic; const QColor modernColor = m_themeSurfaceColor.isValid() ? m_themeSurfaceColor : editorFillColorForThemeBackground(themeBackground); const QColor outerColor = m_themeOuterSurfaceColor.isValid() ? m_themeOuterSurfaceColor : (classic ? themeBackground : modernColor); const QColor color = modernColor; const QString colorName = color.name(); const QString primaryColorName = primaryColor.name(); const QString borderColorName = m_usePrimaryOutline ? primaryColorName : (classic ? modernColor.name() : QStringLiteral("transparent")); QPalette pal = palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { pal.setColor(group, QPalette::Base, color); pal.setColor(group, QPalette::Window, classic ? color : outerColor); pal.setColor(group, QPalette::Text, primaryColor); } StartupDiagnostics::setAppearancePalette(this, pal); setAutoFillBackground(false); setAttribute(Qt::WA_StyledBackground, true); QPalette viewportPalette = viewport()->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { viewportPalette.setColor(group, QPalette::Base, color); viewportPalette.setColor(group, QPalette::Window, color); viewportPalette.setColor(group, QPalette::Text, primaryColor); } StartupDiagnostics::setAppearancePalette(viewport(), viewportPalette); viewport()->setAutoFillBackground(false); viewport()->setAttribute(Qt::WA_StyledBackground, true); if (classic) { const int separatorWidth = m_usePrimaryOutline ? UiConfig::OutlineStrokeWidth : UiConfig::ClassicUnfocusedSeparatorWidth; // Keep the text in place when the focus line changes thickness. const int topPadding = UiConfig::ClassicEditorVerticalPadding + UiConfig::OutlineStrokeWidth - separatorWidth; StartupDiagnostics::setAppearanceStyleSheet(this, QStringLiteral(R"( QPlainTextEdit { background-color: %1; color: %2; border: 0; border-top: %4px solid %3; border-radius: 0; margin: 0; padding: %7px %5px %6px; } )").arg(colorName, primaryColorName, borderColorName) .arg(separatorWidth) .arg(kClassicEditorHorizontalPadding) .arg(UiConfig::ClassicEditorVerticalPadding) .arg(topPadding)); } else { StartupDiagnostics::setAppearanceStyleSheet(this, QStringLiteral(R"( QPlainTextEdit { background-color: %1; color: %2; border: %11px solid %3; border-radius: %4px; margin: %5px %6px %7px %8px; padding: %9px %10px; } )").arg(colorName, primaryColorName, borderColorName) .arg(kEditorRadius) .arg(kEditorOuterTop) .arg(kEditorOuterRight) .arg(kEditorOuterBottom) .arg(kEditorOuterLeft) .arg(kEditorVerticalPadding) .arg(kEditorHorizontalPadding) .arg(UiConfig::OutlineStrokeWidth)); } StartupDiagnostics::setAppearancePalette(this, pal); document()->setDocumentMargin(kEditorDocumentMargin); // Qt parents the right-click menu to the viewport. Keep transparency // scoped to the viewport so system menus can paint their own background. StartupDiagnostics::setAppearanceStyleSheet(viewport(), QStringLiteral("QWidget#editorViewport { background: transparent; }")); StartupDiagnostics::setAppearancePalette(viewport(), viewportPalette); clearMask(); } void Editor::setThemeSurfaceColor(const QColor& color, const QColor& outerColor) { m_themeSurfaceColor = color; m_themeOuterSurfaceColor = outerColor; } void Editor::updateMatchedParenthesisColors() { const QColor background = m_highlighter->colorForRole(ColorScheme::Parens); if (background == m_matchedParenthesisBackgroundColor && m_matchedParenthesisForegroundColor.isValid()) { return; } m_matchedParenthesisBackgroundColor = background; m_matchedParenthesisForegroundColor = aaForegroundForBackground(background); } QTextCharFormat Editor::matchedParenthesisFormat() const { QTextCharFormat format; format.setBackground(m_matchedParenthesisBackgroundColor); format.setForeground(m_matchedParenthesisForegroundColor); return format; } void Editor::setThemePrimaryColor(const QColor& color, bool usePrimaryOutline) { // Pane activation runs while typing. Keep unchanged themes from rebuilding // the editor's styles and text layout on every character. const bool themeChanged = m_themePrimaryColor != color || m_usePrimaryOutline != usePrimaryOutline // Qt can reset the viewport palette when polishing a parent widget. || viewport()->palette().color(QPalette::Base) != palette().color(QPalette::Base); m_themePrimaryColor = color; m_usePrimaryOutline = usePrimaryOutline; if (themeChanged) { updateAppearance(); updateHeightAndEnsureCursorVisible(); } if (shouldPaintThemedCursor()) showThemedCursorAndRestartBlink(); else hideThemedCursorAndStopBlink(); } bool Editor::isConstantSearchVisible() const { return m_constantCompletion && m_constantCompletion->isVisible(); } void Editor::setThemeCompletionColors(const QColor& background, const QColor& foreground, const QColor& scrollbarThumb, const QColor& scrollbarThumbForeground, const QColor& selectedRow, const QColor& selectedRowForeground, const QColor& outline, int cornerRadius, const QColor& searchButtonFill, const QColor& searchButtonCross) { m_completionBackgroundColor = background; m_completionForegroundColor = foreground; m_completionScrollbarThumbColor = scrollbarThumb; m_completionScrollbarThumbForegroundColor = scrollbarThumbForeground; m_completionSelectedRowColor = selectedRow; m_completionSelectedRowForegroundColor = selectedRowForeground; m_completionOutlineColor = outline; m_completionCornerRadius = cornerRadius; m_completionSearchButtonFill = searchButtonFill; m_completionSearchButtonCross = searchButtonCross; m_completion->setThemeColors(background, foreground, scrollbarThumb, scrollbarThumbForeground, selectedRow, selectedRowForeground, outline, cornerRadius); if (m_constantCompletion) { m_constantCompletion->setThemeColors(background, foreground, scrollbarThumb, scrollbarThumbForeground, selectedRow, selectedRowForeground, outline, cornerRadius, searchButtonFill, searchButtonCross); } } void Editor::setThemePreviewColorScheme(const ColorScheme& scheme) { m_themePreviewColorScheme = ColorScheme::fromJsonObject(scheme.toJsonObject()); rehighlight(); } void Editor::updateHistory() { const Session* session = m_session; if (session == nullptr) return; const int sessionHistoryCount = session->historySize(); // Fast path for appending one new history entry. if (sessionHistoryCount == m_history.count() + 1) { m_history.append(session->historyEntryAtRef(sessionHistoryCount - 1)); m_currentHistoryIndex = m_history.count(); return; } // Fast path for history cap behavior: oldest entry dropped, newest appended. if (sessionHistoryCount == m_history.count() && sessionHistoryCount > 0) { const int count = sessionHistoryCount; if (count == 1) { m_history[0] = session->historyEntryAtRef(count - 1); m_currentHistoryIndex = m_history.count(); return; } if (m_history.count() > 1 && session->historyEntryAtRef(0).expr() == m_history.at(1).expr()) { m_history.removeFirst(); m_history.append(session->historyEntryAtRef(count - 1)); m_currentHistoryIndex = m_history.count(); return; } } m_history.clear(); m_history.reserve(sessionHistoryCount); for (int i = 0; i < sessionHistoryCount; ++i) m_history.append(session->historyEntryAtRef(i)); m_currentHistoryIndex = m_history.count(); } void Editor::stopAutoCalc() { emit autoCalcDisabled(); } void Editor::stopAutoComplete() { m_completionTimer->stop(); m_completion->selectItem(QString()); m_completion->doneCompletion(); setFocus(); } void Editor::wrapSelection() { auto cursor = textCursor(); if (cursor.hasSelection()) { const int selectionStart = cursor.selectionStart(); const int selectionEnd = cursor.selectionEnd(); cursor.setPosition(selectionStart); cursor.insertText(QString(MathDsl::GroupStart)); cursor.setPosition(selectionEnd + 1); cursor.insertText(QString(MathDsl::GroupEnd)); } else { cursor.movePosition(QTextCursor::Start); cursor.insertText(QString(MathDsl::GroupStart)); cursor.movePosition(QTextCursor::End); cursor.insertText(QString(MathDsl::GroupEnd)); } setTextCursor(cursor); } EditorCompletion::EditorCompletion(Editor* editor) : QObject(editor) { m_editor = editor; m_popup = new EditorCompletionPopup(); m_popup->setObjectName(QStringLiteral("editorCompletionPopup")); m_popup->setFrameShape(QFrame::NoFrame); m_popup->setColumnCount(3); m_popup->setRootIsDecorated(false); m_popup->header()->hide(); m_popup->header()->setStretchLastSection(false); m_popup->setEditTriggers(QTreeWidget::NoEditTriggers); m_popup->setSelectionBehavior(QTreeWidget::SelectRows); m_popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_popup->setMouseTracking(true); m_popup->installEventFilter(this); m_popup->viewport()->installEventFilter(this); qApp->installEventFilter(this); m_popup->hide(); // ToolTip creates a positioned, non-grabbing xdg_popup on Wayland. Tool // creates an xdg_toplevel whose position is controlled by the compositor. // Keyboard input stays with the editor; our event filter handles clicks. m_popup->setParent(editor, Qt::ToolTip | Qt::FramelessWindowHint); m_popup->setAutoFillBackground(true); m_popup->setAttribute(Qt::WA_TranslucentBackground, false); m_popup->setAttribute(Qt::WA_ShowWithoutActivating, true); m_popup->setAttribute(Qt::WA_NoMouseReplay, true); m_popup->setFocusPolicy(Qt::NoFocus); m_popup->setFrameStyle(QFrame::NoFrame); } EditorCompletion::~EditorCompletion() { qApp->removeEventFilter(this); // The editor owns the popup through Qt parent-child deletion. } void EditorCompletion::setThemeColors(const QColor& background, const QColor& foreground, const QColor& scrollbarThumb, const QColor& scrollbarThumbForeground, const QColor& selectedRow, const QColor& selectedRowForeground, const QColor& outline, int cornerRadius) { m_backgroundColor = background; m_foregroundColor = foreground; m_scrollbarThumbColor = scrollbarThumb; m_scrollbarThumbForegroundColor = scrollbarThumbForeground; m_selectedRowColor = selectedRow; m_selectedRowForegroundColor = selectedRowForeground; m_outlineColor = outline; m_cornerRadius = cornerRadius; applyThemeColors(); } void EditorCompletion::applyThemeColors() { ToolTipStyleUtils::applyTreePopupTheme( m_popup, {m_backgroundColor, m_foregroundColor, m_scrollbarThumbColor, m_scrollbarThumbForegroundColor, m_selectedRowColor, m_selectedRowForegroundColor, m_outlineColor, m_cornerRadius}); } void EditorCompletion::restoreEditorFocus() { m_editor->window()->activateWindow(); m_editor->setFocus(Qt::OtherFocusReason); QTimer::singleShot(0, m_editor, [editor = m_editor]() { editor->window()->activateWindow(); editor->setFocus(Qt::OtherFocusReason); editor->viewport()->setFocus(Qt::OtherFocusReason); }); } bool EditorCompletion::eventFilter(QObject* object, QEvent* event) { if (m_popup->isVisible() && event->type() == QEvent::Wheel) { QWheelEvent* wheelEvent = static_cast(event); const bool wheelInsidePopup = object == m_popup || object == m_popup->viewport() || (object != nullptr && m_popup->isAncestorOf(qobject_cast(object))) || m_popup->rect().contains(m_popup->mapFromGlobal(wheelEvent->globalPosition().toPoint())); if (wheelInsidePopup) { const int delta = wheelEvent->angleDelta().y() != 0 ? wheelEvent->angleDelta().y() : wheelEvent->pixelDelta().y(); if (delta != 0) { QScrollBar* scrollBar = m_popup->verticalScrollBar(); scrollBar->setValue(scrollBar->value() - delta / 8); return true; } } } if (m_popup->isVisible() && event->type() == QEvent::MouseButtonPress) { const QPoint globalPosition = static_cast(event)->globalPosition().toPoint(); if (!m_popup->rect().contains(m_popup->mapFromGlobal(globalPosition))) { m_editor->m_completionTimer->stop(); m_editor->m_suppressedCompletionText = m_editor->text(); m_editor->m_suppressedCompletionPosition = m_editor->textCursor().position(); m_popup->hide(); if (!m_editor->hasFocus()) m_editor->hideThemedCursorAndStopBlink(); return false; } } if (object != m_popup && object != m_popup->viewport()) return false; if (object == m_popup && event->type() == QEvent::Hide) { m_editor->m_completionTimer->stop(); m_editor->m_suppressedCompletionText = m_editor->text(); m_editor->m_suppressedCompletionPosition = m_editor->textCursor().position(); if (!m_editor->hasFocus()) m_editor->hideThemedCursorAndStopBlink(); return false; } if (event->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast(event); if (handleCompletionKey(keyEvent)) return true; QApplication::sendEvent(m_editor, keyEvent); return true; } if (event->type() == QEvent::MouseButtonRelease && object == m_popup->viewport()) { QMouseEvent* mouseEvent = static_cast(event); if (QTreeWidgetItem* item = m_popup->itemAt(mouseEvent->position().toPoint())) { s_completionMouseSelectionOwner = m_editor; QTimer::singleShot(250, m_editor, [editor = m_editor]() { if (s_completionMouseSelectionOwner == editor) s_completionMouseSelectionOwner = nullptr; }); m_popup->setCurrentItem(item); doneCompletion(); return true; } } return false; } bool EditorCompletion::isVisible() const { return m_popup->isVisible(); } bool EditorCompletion::handleEditorKeyPress(QKeyEvent* event) { if (!isVisible()) return false; const int key = event->key(); if (key == Qt::Key_Escape || key == Qt::Key_Enter || key == Qt::Key_Return || key == Qt::Key_Tab || key == Qt::Key_Up || key == Qt::Key_Down || key == Qt::Key_Home || key == Qt::Key_End || key == Qt::Key_PageUp || key == Qt::Key_PageDown) { return handleCompletionKey(event); } m_popup->hide(); return false; } bool EditorCompletion::handleEditorWheelEvent(QWheelEvent* event) { if (!m_popup->isVisible()) return false; const int delta = event->angleDelta().y() != 0 ? event->angleDelta().y() : event->pixelDelta().y(); if (delta == 0) return false; QScrollBar* scrollBar = m_popup->verticalScrollBar(); scrollBar->setValue(scrollBar->value() - delta / 8); event->accept(); return true; } bool EditorCompletion::handleCompletionKey(QKeyEvent* event) { m_editor->m_completionTimer->stop(); const int key = event->key(); switch (key) { case Qt::Key_Enter: case Qt::Key_Return: if (m_popupInteracted || Settings::instance()->autoCompletionAcceptWithEnter) { doneCompletion(); return true; } m_popup->hide(); m_editor->setFocus(); QMetaObject::invokeMethod(m_editor, "triggerEnter", Qt::DirectConnection); return true; case Qt::Key_Tab: doneCompletion(); return true; case Qt::Key_Escape: m_editor->m_suppressedCompletionText = m_editor->text(); m_editor->m_suppressedCompletionPosition = m_editor->textCursor().position(); m_popup->hide(); restoreEditorFocus(); return true; case Qt::Key_Up: case Qt::Key_Down: case Qt::Key_Home: case Qt::Key_End: case Qt::Key_PageUp: case Qt::Key_PageDown: m_popupInteracted = true; if (m_popup->topLevelItemCount() > 0) { const int currentRow = qMax(0, m_popup->indexOfTopLevelItem(m_popup->currentItem())); const int pageStep = qMax(1, m_popup->height() / qMax(1, m_popup->sizeHintForRow(0))); int targetRow = currentRow; if (key == Qt::Key_Up) targetRow = currentRow - 1; else if (key == Qt::Key_Down) targetRow = currentRow + 1; else if (key == Qt::Key_Home) targetRow = 0; else if (key == Qt::Key_End) targetRow = m_popup->topLevelItemCount() - 1; else if (key == Qt::Key_PageUp) targetRow = currentRow - pageStep; else if (key == Qt::Key_PageDown) targetRow = currentRow + pageStep; targetRow = qBound(0, targetRow, m_popup->topLevelItemCount() - 1); m_popup->setCurrentItem(m_popup->topLevelItem(targetRow)); m_popup->scrollToItem(m_popup->currentItem()); } return true; default: m_editor->m_suppressedCompletionText = m_editor->text(); m_editor->m_suppressedCompletionPosition = m_editor->textCursor().position(); m_popup->hide(); m_editor->setFocus(); return false; } } void EditorCompletion::doneCompletion() { m_popup->hide(); QTreeWidgetItem* item = m_popup->currentItem(); emit selectedCompletion(item ? item->text(1) : QString()); restoreEditorFocus(); } void EditorCompletion::showCompletion(const QStringList& choices) { if (!choices.count()) return; m_popupInteracted = false; applyThemeColors(); m_popup->setUpdatesEnabled(false); m_popup->clear(); // Performance: compute these once per popup render (not per row) because // unit completion can contain many entries and this function runs often. Evaluator* evaluator = m_editor->evaluator(); const QList builtInUnitKeys = Units::builtInUnitLookup(Settings::instance()->angleUnit).keys(); const QSet builtInUnits( builtInUnitKeys.constBegin(), builtInUnitKeys.constEnd()); const bool unitContextAtCursor = isInsideUnmatchedSquareBracketContext( m_editor->text(), m_editor->textCursor().position()); for (int i = 0; i < choices.count(); ++i) { const auto pair = choices.at(i).split(':'); if (pair.count() < 2) continue; const auto identifier = pair.at(0); const auto description = pair.mid(1).join(":"); QString typeSymbol = QString::fromUtf8("👤 ð�‘¥"); if (FunctionRepo::instance()->find(identifier)) { typeSymbol = QString::fromUtf8("📚 Æ’"); // Reuse local evaluator pointer to avoid repeated singleton lookups // on every completion row. } else if (evaluator->hasUserFunction(identifier)) { typeSymbol = QString::fromUtf8("👤 Æ’"); } else if (!unitContextAtCursor && evaluator->hasVariable(identifier)) { const auto variable = evaluator->getVariable(identifier); if (variable.type() == Variable::BuiltIn) typeSymbol = QString::fromUtf8("ðŸ“� ð�‘˜"); } else if (evaluator->hasUserUnit(identifier)) { typeSymbol = QString::fromUtf8("👤 ð�’–"); // O(1) membership check against precomputed built-in unit identifiers. } else if (builtInUnits.contains(identifier)) { typeSymbol = QString::fromUtf8("📚 ð�’–"); } QStringList columns; columns << typeSymbol << identifier << description; QTreeWidgetItem* item = new QTreeWidgetItem(m_popup, columns); if (item && m_editor->layoutDirection() == Qt::RightToLeft) item->setTextAlignment(1, Qt::AlignRight); item->setTextAlignment(0, Qt::AlignCenter); } m_popup->sortItems(2, Qt::AscendingOrder); m_popup->sortItems(1, Qt::AscendingOrder); m_popup->setCurrentItem(m_popup->topLevelItem(0)); // Size of the pop-up. m_popup->resizeColumnToContents(0); m_popup->setColumnWidth(0, m_popup->columnWidth(0) + 18); m_popup->resizeColumnToContents(1); m_popup->setColumnWidth(1, m_popup->columnWidth(1) + 25); m_popup->resizeColumnToContents(2); m_popup->setColumnWidth(2, m_popup->columnWidth(2) + 25); const int maxVisibleItems = 8; const int height = m_popup->sizeHintForRow(0) * qMin(maxVisibleItems, choices.count()) + 3; const int width = m_popup->columnWidth(0) + m_popup->columnWidth(1) + m_popup->columnWidth(2) + 1; auto cursor = m_editor->textCursor(); cursor.movePosition(QTextCursor::StartOfWord); prepareCompletionPopup(m_popup, m_editor, cursor, QSize(width, height), m_cornerRadius); const QRect geometry = completionPopupGeometry(m_editor, cursor, QSize(width, height)); m_popup->setUpdatesEnabled(true); if (!geometry.isValid()) { m_popup->hide(); return; } m_popup->setGeometry(geometry); ToolTipStyleUtils::applyRoundedPopupMask(m_popup, m_cornerRadius); m_popup->verticalScrollBar()->setValue(m_popup->verticalScrollBar()->minimum()); m_popup->show(); m_editor->setFocus(); } void EditorCompletion::selectItem(const QString& item) { if (item.isNull()) { m_popup->setCurrentItem(0); return; } auto targets = m_popup->findItems(item, Qt::MatchExactly, 1); if (targets.count() > 0) m_popup->setCurrentItem(targets.at(0)); } namespace { constexpr int constantUnitRole = Qt::UserRole + 1; class ConstantCompletionDelegate : public QStyledItemDelegate { public: ConstantCompletionDelegate(SyntaxHighlighter* highlighter, QObject* parent) : QStyledItemDelegate(parent), m_highlighter(highlighter) { Q_ASSERT(m_highlighter); } void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { QStyleOptionViewItem item(option); initStyleOption(&item, index); const QString name = item.text; item.text.clear(); const QStyle* style = item.widget ? item.widget->style() : QApplication::style(); style->drawControl(QStyle::CE_ItemViewItem, &item, painter, item.widget); const QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &item, item.widget); if (textRect.isEmpty()) return; const QPalette::ColorGroup group = !(item.state & QStyle::State_Enabled) ? QPalette::Disabled : (item.state & QStyle::State_Active) ? QPalette::Active : QPalette::Inactive; const bool selected = item.state & QStyle::State_Selected; const QColor foreground = item.palette.color(group, selected ? QPalette::HighlightedText : QPalette::Text); const QColor unitColor = m_highlighter->colorForRole(ColorScheme::Unit); QFont unitFont(item.font); if (unitFont.pointSizeF() > 0) unitFont.setPointSizeF(unitFont.pointSizeF() * 0.93); else if (unitFont.pixelSize() > 0) unitFont.setPixelSize(qMax(1, qRound(unitFont.pixelSize() * 0.93))); const QFontMetrics unitMetrics(unitFont); const QString rawUnit = index.data(constantUnitRole).toString(); const QString unit = unitMetrics.elidedText(rawUnit, Qt::ElideRight, textRect.width() / 2); const QString gap = unit.isEmpty() ? QString() : QStringLiteral(" "); const int unitWidth = unitMetrics.horizontalAdvance(unit) + item.fontMetrics.horizontalAdvance(gap); const QString displayName = item.fontMetrics.elidedText(name, Qt::ElideRight, qMax(0, textRect.width() - unitWidth)); // Isolate the unit so mixed-direction names do not reorder its symbols. const QString text = unit.isEmpty() ? displayName : displayName + gap + QChar(0x2066) + unit + QChar(0x2069); if (text.isEmpty()) return; QTextLayout layout(text, item.font); QTextOption textOption; textOption.setTextDirection(item.direction); textOption.setAlignment(QStyle::visualAlignment(item.direction, Qt::AlignLeft)); textOption.setWrapMode(QTextOption::NoWrap); layout.setTextOption(textOption); QTextLayout::FormatRange unitFormat; unitFormat.start = displayName.size() + gap.size(); unitFormat.length = text.size() - unitFormat.start; unitFormat.format.setFont(unitFont); unitFormat.format.setForeground(unitColor); layout.setFormats({unitFormat}); layout.beginLayout(); QTextLine line = layout.createLine(); line.setLineWidth(textRect.width()); layout.endLayout(); painter->save(); painter->setClipRect(textRect, Qt::IntersectClip); painter->setPen(foreground); layout.draw(painter, QPointF(textRect.left(), textRect.top() + (textRect.height() - line.height()) / 2)); painter->restore(); } private: SyntaxHighlighter* m_highlighter; }; } // namespace ConstantCompletion::ConstantCompletion(Editor* editor) : QObject(editor) , m_editor(editor) { m_popup = new CompletionPopup; m_popup->setObjectName(QStringLiteral("constantCompletionPopup")); m_popup->setParent(editor, Qt::Popup | Qt::FramelessWindowHint); m_popup->setAttribute(Qt::WA_NoMouseReplay, true); m_popup->setFrameStyle(QFrame::NoFrame); m_popup->setAutoFillBackground(true); m_search = new ThemedLineEdit(m_popup); m_search->setObjectName(QStringLiteral("constantCompletionSearch")); m_search->setPlaceholderText(tr("Search constants")); m_search->setAccessibleName(tr("Search constants")); m_search->setClearButtonEnabled(true); m_popup->setFocusProxy(m_search); m_constantWidget = new QTreeWidget(m_popup); m_constantWidget->setObjectName(QStringLiteral("constantCompletionConstantsPopup")); m_constantWidget->setFrameShape(QFrame::NoFrame); m_constantWidget->setColumnCount(1); m_constantWidget->header()->hide(); m_constantWidget->setItemDelegate(new ConstantCompletionDelegate(editor->findChild(), m_constantWidget)); m_constantWidget->setRootIsDecorated(false); m_constantWidget->setEditTriggers(QTreeWidget::NoEditTriggers); m_constantWidget->setSelectionBehavior(QTreeWidget::SelectRows); m_constantWidget->setSelectionMode(QTreeWidget::SingleSelection); m_constantWidget->setMouseTracking(true); m_constantWidget->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_noMatchLabel = new QLabel(tr("No match found"), m_popup); m_noMatchLabel->setAlignment(Qt::AlignCenter); m_noMatchLabel->hide(); auto* layout = new QVBoxLayout(m_popup); layout->setContentsMargins(8, 8, 8, 8); layout->setSpacing(6); layout->addWidget(m_search); layout->addWidget(m_constantWidget, 1); QWidget::setTabOrder(m_search, m_constantWidget); connect(m_search, &QLineEdit::textChanged, this, &ConstantCompletion::filter); connect(m_constantWidget, &QTreeWidget::itemClicked, this, &ConstantCompletion::doneCompletion); filter(); const int rowHeight = qMax(m_constantWidget->sizeHintForRow(0), m_constantWidget->fontMetrics().height()); m_popupSize = QSize(qMax(480, m_search->fontMetrics().horizontalAdvance(QLatin1Char('M')) * 48), rowHeight * 7 + m_search->sizeHint().height() + 22); // Let the compositor shorten the list on small outputs. layout->setSizeConstraint(QLayout::SetNoConstraint); m_constantWidget->setMinimumSize(0, 0); m_popup->resize(m_popupSize); m_search->installEventFilter(this); m_constantWidget->installEventFilter(this); m_constantWidget->viewport()->installEventFilter(this); m_popup->installEventFilter(this); } ConstantCompletion::~ConstantCompletion() { m_popup->removeEventFilter(this); delete m_popup; } bool ConstantCompletion::isVisible() const { return m_popup->isVisible(); } void ConstantCompletion::setThemeColors(const QColor& background, const QColor& foreground, const QColor& scrollbarThumb, const QColor& scrollbarThumbForeground, const QColor& selectedRow, const QColor& selectedRowForeground, const QColor& outline, int cornerRadius, const QColor& searchButtonFill, const QColor& searchButtonCross) { m_backgroundColor = background; m_foregroundColor = foreground; m_scrollbarThumbColor = scrollbarThumb; m_scrollbarThumbForegroundColor = scrollbarThumbForeground; m_selectedRowColor = selectedRow; m_selectedRowForegroundColor = selectedRowForeground; m_outlineColor = outline; m_cornerRadius = cornerRadius; m_searchButtonFill = searchButtonFill.isValid() ? searchButtonFill : foreground; m_searchButtonCross = searchButtonCross.isValid() ? searchButtonCross : background; applyThemeColors(); } void ConstantCompletion::applyThemeColors() { if (!m_backgroundColor.isValid() || !m_foregroundColor.isValid()) return; QPalette palette = m_popup->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { palette.setColor(group, QPalette::Window, m_backgroundColor); palette.setColor(group, QPalette::WindowText, m_foregroundColor); palette.setColor(group, QPalette::Base, m_backgroundColor); palette.setColor(group, QPalette::Text, m_foregroundColor); palette.setColor(group, QPalette::PlaceholderText, m_foregroundColor); palette.setColor(group, QPalette::Button, m_backgroundColor); palette.setColor(group, QPalette::ButtonText, m_foregroundColor); palette.setColor(group, QPalette::Highlight, m_selectedRowColor); palette.setColor(group, QPalette::HighlightedText, m_selectedRowForegroundColor); } m_popup->setPalette(palette); m_search->setPalette(palette); m_popup->setStyleSheet(QStringLiteral( "QFrame#constantCompletionPopup { background: %1; border: %2px solid %3; border-radius: %4px; }") .arg(m_backgroundColor.name()).arg(UiConfig::PopupOutlineStrokeWidth) .arg(m_outlineColor.name()).arg(m_cornerRadius)); static_cast(m_search)->setCursorColor(m_searchButtonFill); const int focusInset = UiConfig::OutlineStrokeWidth - 1; m_search->setStyleSheet(QStringLiteral( "QLineEdit { background: %1; color: %2; border: 1px solid %3;" " border-radius: %4px; padding: 4px 6px; selection-background-color: %5; selection-color: %6; }" "QLineEdit:focus { border: %7px solid %8; padding: %9px %10px; }") .arg(m_backgroundColor.name(), m_foregroundColor.name(), m_outlineColor.name()) .arg(UiConfig::ControlCornerRadius) .arg(m_selectedRowColor.name(), m_selectedRowForegroundColor.name()) .arg(UiConfig::OutlineStrokeWidth).arg(m_searchButtonFill.name()) .arg(4 - focusInset).arg(6 - focusInset)); updateSearchClearButton(m_search->hasFocus()); ToolTipStyleUtils::applyTreePopupTheme(m_constantWidget, {m_backgroundColor, m_foregroundColor, m_scrollbarThumbColor, m_scrollbarThumbForegroundColor, m_selectedRowColor, m_selectedRowForegroundColor, m_outlineColor, m_cornerRadius}); m_constantWidget->setStyleSheet(m_constantWidget->styleSheet() + QStringLiteral( "QTreeWidget { border: 0; border-radius: 0; }" "QTreeWidget::item { padding: 5px 6px; border-radius: 3px; }")); } void ConstantCompletion::updateSearchClearButton(bool focused) { if (!m_backgroundColor.isValid() || !m_foregroundColor.isValid()) return; LineEditStyleUtils::applyClearButtonColors(m_search, focused ? m_searchButtonFill : m_backgroundColor, focused ? m_searchButtonCross : m_foregroundColor); } void ConstantCompletion::filter() { m_constantWidget->clear(); const auto& constants = Constants::instance()->list(); for (const Constant& constant : constants) { if (!ConstantBrowserUtils::matches(constant, m_search->text())) continue; auto* item = new QTreeWidgetItem(m_constantWidget, {constant.name}); const QString unit = ConstantBrowserUtils::unit(constant); item->setData(0, constantUnitRole, unit); item->setData(0, Qt::AccessibleTextRole, unit.isEmpty() ? constant.name : constant.name + QLatin1Char(' ') + unit); item->setData(0, Qt::UserRole, ConstantBrowserUtils::expression(constant)); const QString tip = constant.name + QLatin1Char('\n') + constant.value + (unit.isEmpty() ? QString() : QLatin1Char(' ') + unit); item->setToolTip(0, tip); } m_constantWidget->sortItems(0, Qt::AscendingOrder); m_constantWidget->setCurrentItem(m_constantWidget->topLevelItem(0)); m_noMatchLabel->hide(); if (m_constantWidget->topLevelItemCount() == 0) DockListStyle::showCenteredNoMatchLabel(m_constantWidget, m_noMatchLabel); } void ConstantCompletion::restoreEditorFocus() { m_editor->window()->activateWindow(); m_editor->setFocus(Qt::OtherFocusReason); QTimer::singleShot(0, m_editor, [editor = m_editor]() { editor->window()->activateWindow(); editor->setFocus(Qt::OtherFocusReason); editor->viewport()->setFocus(Qt::OtherFocusReason); }); } bool ConstantCompletion::eventFilter(QObject* object, QEvent* event) { if (object == m_constantWidget->viewport() && event->type() == QEvent::Resize && m_constantWidget->topLevelItemCount() == 0) { DockListStyle::showCenteredNoMatchLabel(m_constantWidget, m_noMatchLabel); } if (object == m_popup) { if (event->type() == QEvent::Show || event->type() == QEvent::Hide) emit visibilityChanged(); if (event->type() == QEvent::Hide && !m_finishing) emit canceledCompletion(); return false; } if (object == m_search && (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut)) { updateSearchClearButton(event->type() == QEvent::FocusIn); } if (event->type() != QEvent::KeyPress) return false; auto* keyEvent = static_cast(event); const int key = keyEvent->key(); if (key == Qt::Key_Escape) { m_popup->hide(); restoreEditorFocus(); return true; } if (key == Qt::Key_Return || key == Qt::Key_Enter || (key == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier)) { doneCompletion(); return true; } if (object == m_search && (key == Qt::Key_Up || key == Qt::Key_Down)) { ConstantBrowserUtils::moveSelection(m_constantWidget, key); return true; } const bool editsSearch = (!keyEvent->text().isEmpty() && keyEvent->text().front().isPrint()) || key == Qt::Key_Backspace || key == Qt::Key_Delete; if (object == m_constantWidget && editsSearch && !(keyEvent->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) { m_search->setFocus(); QApplication::sendEvent(m_search, event); return true; } return false; } void ConstantCompletion::doneCompletion() { const auto* item = m_constantWidget->currentItem(); if (!item || m_finishing) return; const QString expression = item->data(0, Qt::UserRole).toString(); m_finishing = true; s_completionMouseSelectionOwner = m_editor; QTimer::singleShot(250, m_editor, [editor = m_editor]() { if (s_completionMouseSelectionOwner == editor) s_completionMouseSelectionOwner = nullptr; }); m_popup->hide(); emit selectedCompletion(expression); restoreEditorFocus(); } void ConstantCompletion::showCompletion() { m_finishing = false; applyThemeColors(); m_popup->ensurePolished(); const int rowHeight = qMax(m_constantWidget->sizeHintForRow(0), m_constantWidget->fontMetrics().height()); m_popupSize.setHeight(rowHeight * 7 + m_search->sizeHint().height() + 22); prepareCompletionPopup(m_popup, m_editor, m_editor->textCursor(), m_popupSize, m_cornerRadius); const QRect geometry = completionPopupGeometry(m_editor, m_editor->textCursor(), m_popupSize); if (!geometry.isValid()) { emit canceledCompletion(); return; } m_popup->setGeometry(geometry); ToolTipStyleUtils::applyRoundedPopupMask(m_popup, m_cornerRadius); m_popup->show(); m_search->setFocus(Qt::PopupFocusReason); } heldercorreia-speedcrunch-e7ca37f/src/gui/editor.h000066400000000000000000000237061526573132500223570ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2013-2017, 2019-2020, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_EDITOR_H #define GUI_EDITOR_H #include "core/colorscheme.h" #include "core/sessionhistory.h" #include #include #include #include #include struct Constant; class ConstantCompletion; class EditorCompletion; class Evaluator; class Session; class CNumber; class SyntaxHighlighter; class QEvent; class QFocusEvent; class QInputMethodEvent; class QKeyEvent; class QLabel; class QLineEdit; class QMimeData; class QMouseEvent; class QTimer; class QTreeWidget; class QWheelEvent; class QWidget; class QResizeEvent; class Editor : public QPlainTextEdit { Q_OBJECT public: explicit Editor(QWidget* parent = nullptr); ~Editor() override; bool isAutoCalcEnabled() const; bool isAutoCompletionEnabled() const; bool isConstantSearchVisible() const; bool isCursorBlinkingEnabled() const { return m_cursorBlinkingEnabled; } Evaluator* evaluator() const { return m_evaluator; } static Editor* completionMouseSelectionOwner(); static QString historyExpressionForInput(const QString&); void clearHistory(); QColor cursorColor() const { return m_themePrimaryColor; } int cursorPosition() const; void dismissCurrentAutoCalc(); void doBackspace(); void doDelete(); char radixChar() const; void setAutoCalcEnabled(bool); void setAutoCompletionEnabled(bool); void setCustomCursorVisible(bool visible); void setCursorBlinkingEnabled(bool enabled); void setThemePrimaryColor(const QColor& color, bool usePrimaryOutline); void setThemePreviewColorScheme(const ColorScheme& scheme); void setThemeCompletionColors(const QColor& background, const QColor& foreground, const QColor& scrollbarThumb, const QColor& scrollbarThumbForeground, const QColor& selectedRow, const QColor& selectedRowForeground, const QColor& outline, int cornerRadius, const QColor& searchButtonFill = QColor(), const QColor& searchButtonCross = QColor()); void setThemeSurfaceColor(const QColor& color, const QColor& outerColor = QColor()); void setSession(Session* session); void setHistoryArrowNavigationEnabled(bool enabled); void setCursorPosition(int pos); void setText(const QString&); void stopAutoCalc(); void stopAutoComplete(); void wrapSelection(); QString text() const; QStringList matchFragment(const QString&, bool unitContext = false) const; QString getKeyword() const; signals: void autoCalcMessageAvailable(const QString&); void autoCalcQuantityAvailable(const Quantity&); void autoCalcDisabled(); void controlPageDownPressed(); void controlPageUpPressed(); void copySequencePressed(); void pageDownPressed(); void pageUpPressed(); void returnPressed(); void escapePressed(); void shiftDownPressed(); void shiftUpPressed(); void shiftPageDownPressed(); void shiftPageUpPressed(); void bulkEvaluationStarted(); void bulkEvaluationFinished(); void constantSearchVisibilityChanged(); public slots: void autoCalcSelection(const QString& custom = QString()); void cancelConstantCompletion(); void evaluate(); void decreaseFontPointSize(); void increaseFontPointSize(); void insert(const QString&); void insertConstant(const QString&); void rehighlight(); void updateHistory(); void refreshAutoCalc(); void refreshInputMode(); protected slots: void insertFromMimeData(const QMimeData*) override; void autoCalc(); void autoComplete(const QString&); void checkAutoCalc(); void checkAutoComplete(); void checkMatching(); void checkSelectionAutoCalc(); void doMatchingLeft(); void doMatchingPar(); void doMatchingRight(); void historyBack(); void historyForward(); void triggerAutoComplete(); void triggerEnter(); protected: void changeEvent(QEvent*) override; bool event(QEvent*) override; void focusInEvent(QFocusEvent*) override; void focusOutEvent(QFocusEvent*) override; void inputMethodEvent(QInputMethodEvent*) override; void keyPressEvent(QKeyEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseReleaseEvent(QMouseEvent*) override; void paintEvent(QPaintEvent*) override; void resizeEvent(QResizeEvent*) override; void scrollContentsBy(int, int) override; void doSetTextCursor(const QTextCursor&) override; QSize sizeHint() const override; void wheelEvent(QWheelEvent*) override; private: Q_DISABLE_COPY(Editor) friend class EditorCompletion; bool m_isAutoCalcEnabled; bool m_inputEditInProgress = false; bool m_shouldBlockAutoCompletionOnce = false; bool m_isAutoCompletionEnabled; EditorCompletion* m_completion; QTimer* m_completionTimer; QString m_suppressedCompletionText; int m_suppressedCompletionPosition = -1; ConstantCompletion* m_constantCompletion; Evaluator* m_evaluator; SyntaxHighlighter* m_highlighter; QList m_history; QString m_savedCurrentEditor; int m_currentHistoryIndex; QTimer* m_matchingTimer; QTimer* m_cursorBlinkTimer; bool m_cursorBlinkingEnabled; bool m_customCursorVisible; bool m_themedCursorVisible = false; bool m_historyArrowNavigationEnabled; bool m_canScrollWrappedText = false; bool m_updatingWrappedTextHeight = false; bool m_mouseSelectionInProgress = false; bool m_currentAutoCalcDismissed = false; bool m_pendingDeadCaretPreedit = false; QColor m_themeSurfaceColor; QColor m_themeOuterSurfaceColor; QColor m_themePrimaryColor; QColor m_matchedParenthesisBackgroundColor; QColor m_matchedParenthesisForegroundColor; QColor m_completionBackgroundColor; QColor m_completionForegroundColor; QColor m_completionScrollbarThumbColor; QColor m_completionScrollbarThumbForegroundColor; QColor m_completionSelectedRowColor; QColor m_completionSelectedRowForegroundColor; QColor m_completionOutlineColor; QColor m_completionSearchButtonFill; QColor m_completionSearchButtonCross; int m_completionCornerRadius = 0; std::optional m_themePreviewColorScheme; bool m_usePrimaryOutline = false; std::unique_ptr m_ownedSession; Session* m_session; void updateHeightForWrappedText(); void updateAppearance(); void updateHeightAndEnsureCursorVisible(); void showThemedCursorAndRestartBlink(); void hideThemedCursorAndStopBlink(); void updateMatchedParenthesisColors(); QTextCharFormat matchedParenthesisFormat() const; bool shouldPaintThemedCursor() const; QRect themedCursorRect() const; }; class EditorCompletion : public QObject { Q_OBJECT public: EditorCompletion(Editor*); ~EditorCompletion(); bool eventFilter(QObject*, QEvent*); bool isVisible() const; bool handleEditorKeyPress(QKeyEvent* event); bool handleEditorWheelEvent(QWheelEvent* event); void setThemeColors(const QColor& background, const QColor& foreground, const QColor& scrollbarThumb, const QColor& scrollbarThumbForeground, const QColor& selectedRow, const QColor& selectedRowForeground, const QColor& outline, int cornerRadius); void showCompletion(const QStringList&); signals: void selectedCompletion(const QString&); public slots: void doneCompletion(); void selectItem(const QString&); private: Q_DISABLE_COPY(EditorCompletion) Editor* m_editor; QTreeWidget* m_popup; bool m_popupInteracted = false; QColor m_backgroundColor; QColor m_foregroundColor; QColor m_scrollbarThumbColor; QColor m_scrollbarThumbForegroundColor; QColor m_selectedRowColor; QColor m_selectedRowForegroundColor; QColor m_outlineColor; int m_cornerRadius = 0; bool handleCompletionKey(QKeyEvent* event); void applyThemeColors(); void restoreEditorFocus(); }; class ConstantCompletion : public QObject { Q_OBJECT public: ConstantCompletion(Editor*); ~ConstantCompletion(); bool eventFilter(QObject*, QEvent*); void setThemeColors(const QColor& background, const QColor& foreground, const QColor& scrollbarThumb, const QColor& scrollbarThumbForeground, const QColor& selectedRow, const QColor& selectedRowForeground, const QColor& outline, int cornerRadius, const QColor& searchButtonFill = QColor(), const QColor& searchButtonCross = QColor()); void showCompletion(); bool isVisible() const; signals: void canceledCompletion(); void selectedCompletion(const QString&); void visibilityChanged(); public slots: void doneCompletion(); private: Q_DISABLE_COPY(ConstantCompletion) Editor* m_editor; QLineEdit* m_search; QTreeWidget* m_constantWidget; QLabel* m_noMatchLabel; QFrame* m_popup; QSize m_popupSize; bool m_finishing = false; QColor m_backgroundColor; QColor m_foregroundColor; QColor m_scrollbarThumbColor; QColor m_scrollbarThumbForegroundColor; QColor m_selectedRowColor; QColor m_selectedRowForegroundColor; QColor m_outlineColor; QColor m_searchButtonFill; QColor m_searchButtonCross; int m_cornerRadius = 0; void applyThemeColors(); void updateSearchClearButton(bool focused); void filter(); void restoreEditorFocus(); }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/editorutils.h000066400000000000000000000511111526573132500234270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later // This file is part of the SpeedCrunch project // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. #ifndef GUI_EDITORUTILS_H #define GUI_EDITORUTILS_H #include "core/unicodechars.h" #include "core/mathdsl.h" #include #include #include namespace EditorUtils { inline QRect completionPopupAnchorRect(const QRect& editor, int anchorX) { return QRect(qBound(editor.left(), anchorX, editor.right()), editor.top(), 1, editor.height()); } inline QRect completionPopupCompositorGeometry(const QRect& anchor, const QSize& requestedSize, const QSize& availableSize) { // Without a global window position, limit unusually tall lists to a height // that fits on at least one side of an on-screen editor. The compositor // determines which side has room and may constrain the size further. const int height = qMin(requestedSize.height(), qMax(0, (availableSize.height() - anchor.height()) / 2)); if (height <= 0) return QRect(); return QRect(QPoint(anchor.left(), anchor.bottom() + 1), QSize(qMin(requestedSize.width(), availableSize.width()), height)); } inline QRect completionPopupGeometry(const QRect& editor, int anchorX, const QSize& requestedSize, const QRect& bounds) { const int below = qMax(0, bounds.bottom() - editor.bottom()); const int above = qMax(0, editor.top() - bounds.top()); const bool useBelow = requestedSize.height() <= below || (requestedSize.height() > above && below >= above); const int height = qMin(requestedSize.height(), useBelow ? below : above); if (height <= 0) return QRect(); const int x = qBound(bounds.left(), anchorX, qMax(bounds.left(), bounds.right() + 1 - requestedSize.width())); const int y = useBelow ? editor.bottom() + 1 : editor.top() - height; return QRect(QPoint(x, y), QSize(requestedSize.width(), height)); } enum AutoAnsRewriteMode { AutoAnsNoRewrite = 0, AutoAnsPrependAns = 1, AutoAnsAppendAns = 2 }; inline QString normalizeMultiplicationOperators(QString text, bool keepDotOperator = false) { for (QChar& ch : text) { if (MathDsl::isMultiplicationOperatorAlias(ch, keepDotOperator)) ch = MathDsl::MulCrossOp; } return text; } inline QString normalizeDivisionOperators(QString text) { for (QChar& ch : text) { if (MathDsl::isDivisionOperatorAlias(ch)) ch = UnicodeChars::BigSolidus; // ⧸ BIG SOLIDUS } return text; } inline QString normalizeDivisionOperatorsForEditorInput(QString text) { for (QChar& ch : text) { if (MathDsl::isDivisionOperatorAlias(ch) || ch == UnicodeChars::BigSolidus) ch = MathDsl::DivOp; // / SOLIDUS } return text; } inline QString normalizeAdditionOperators(QString text) { for (QChar& ch : text) { if (MathDsl::isAdditionOperatorAlias(ch)) ch = MathDsl::AddOp; // + PLUS SIGN } return text; } inline QString normalizeSubtractionOperators(QString text) { for (QChar& ch : text) { if (MathDsl::isSubtractionOperatorAlias(ch)) ch = UnicodeChars::MinusSign; } return text; } inline QString normalizeExpressionOperators(QString text) { const int commentPos = text.indexOf(MathDsl::CommentSep); if (commentPos >= 0) return normalizeExpressionOperators(text.left(commentPos)) + text.mid(commentPos); text = UnicodeChars::normalizeUnitSymbolAliases(text); text = UnicodeChars::normalizeSexagesimalSymbolAliases(text); text = normalizeMultiplicationOperators(text); text = normalizeDivisionOperators(text); text = normalizeAdditionOperators(text); text = normalizeSubtractionOperators(text); return text; } inline QString normalizeExpressionOperatorsForEditorInput(QString text) { const int commentPos = text.indexOf(MathDsl::CommentSep); if (commentPos >= 0) return normalizeExpressionOperatorsForEditorInput(text.left(commentPos)) + text.mid(commentPos); text = UnicodeChars::normalizeUnitSymbolAliases(text); text = UnicodeChars::normalizeSexagesimalSymbolAliases(text); text = UnicodeChars::normalizePiAliasesToPi(text); text = UnicodeChars::normalizeRootFunctionAliasesForDisplay(text); text = normalizeMultiplicationOperators(text, true); text = normalizeDivisionOperatorsForEditorInput(text); text = normalizeAdditionOperators(text); text = normalizeSubtractionOperators(text); return text; } inline bool shouldIgnoreTypedSpaceAfterDigit(const QString& text, int cursorPosition) { if (cursorPosition <= 0 || cursorPosition > text.size()) return false; int i = cursorPosition - 1; while (i >= 0 && text.at(i).isSpace()) --i; if (i < 0) return false; const QChar prevNonSpace = text.at(i); return prevNonSpace.isDigit() || prevNonSpace.isLetter() || MathDsl::isSuperscriptDigit(prevNonSpace) || prevNonSpace == MathDsl::GroupEnd || prevNonSpace == MathDsl::UnitEnd; } inline QString adjustedTypedTextForImplicitMultiplicationAfterDigit( const QString& text, int cursorPosition, const QString& typedText) { if (typedText.size() != 1) return typedText; if (cursorPosition <= 0 || cursorPosition > text.size()) return typedText; const QChar typed = typedText.at(0); const auto isScientificExponentSignContext = [&]() { int i = cursorPosition - 1; while (i >= 0 && text.at(i).isSpace()) --i; if (i < 0) return false; const QChar marker = text.at(i); if (marker != QLatin1Char('e') && marker != QLatin1Char('E')) return false; --i; if (i < 0) return false; bool sawDigit = false; while (i >= 0) { const QChar ch = text.at(i); if (ch.isDigit()) { sawDigit = true; --i; continue; } if (ch == MathDsl::DotSep || ch == MathDsl::CommaSep) { --i; continue; } if (MathDsl::isSubtractionOperatorAlias(ch) || MathDsl::isAdditionOperatorAlias(ch)) { const int boundaryIndex = i - 1; if (boundaryIndex < 0) return sawDigit; const QChar boundary = text.at(boundaryIndex); return sawDigit && (boundary.isSpace() || MathDsl::isExpressionBoundaryOperatorOrSeparator(boundary) || boundary == MathDsl::GroupStart || boundary == MathDsl::UnitStart); } return sawDigit && (ch.isSpace() || MathDsl::isExpressionBoundaryOperatorOrSeparator(ch) || ch == MathDsl::GroupStart || ch == MathDsl::UnitStart); } return sawDigit; }; const auto isSingleZeroTermToLeft = [&]() { int i = cursorPosition - 1; while (i >= 0 && text.at(i).isSpace()) --i; if (i < 0 || text.at(i) != MathDsl::Dig0) return false; --i; while (i >= 0 && text.at(i).isSpace()) --i; if (i < 0) return true; const QChar left = text.at(i); return MathDsl::isExpressionBoundaryOperatorOrSeparator(left) || left == MathDsl::GroupStart || left == MathDsl::UnitStart; }; QString operatorPrefix; const auto leftNonSpaceSupportsOperatorInsertion = [&]() { int i = cursorPosition - 1; while (i >= 0 && text.at(i).isSpace()) --i; if (i < 0) return false; const QChar prevNonSpace = text.at(i); return prevNonSpace.isDigit() || prevNonSpace.isLetter() || MathDsl::isSuperscriptDigit(prevNonSpace) || prevNonSpace == MathDsl::GroupEnd || prevNonSpace == MathDsl::UnitEnd; }; if (typed.isLetter()) { if (typed == QLatin1Char('e') || typed == QLatin1Char('E')) return typedText; if (typed == QLatin1Char('i') || typed == QLatin1Char('I')) { int i = cursorPosition - 1; while (i >= 0 && text.at(i).isSpace()) --i; if (i < 0) return typedText; const QChar prevNonSpace = text.at(i); const bool shouldExpandToIn = prevNonSpace.isDigit() || MathDsl::isSuperscriptDigit(prevNonSpace) || prevNonSpace == MathDsl::GroupEnd || prevNonSpace == MathDsl::UnitEnd; if (!shouldExpandToIn) return typedText; return (i == cursorPosition - 1) ? (QStringLiteral(" ") + typedText) : typedText; } if ((typed == QLatin1Char('b') || typed == QLatin1Char('B') || typed == QLatin1Char('o') || typed == QLatin1Char('O') || typed == QLatin1Char('x') || typed == QLatin1Char('X')) && isSingleZeroTermToLeft()) { return typedText; } return typedText; } else if (typed == MathDsl::GroupStart || typed == MathDsl::UnitStart) { int i = cursorPosition - 1; while (i >= 0 && text.at(i).isSpace()) --i; if (i < 0) return typedText; const QChar prevNonSpace = text.at(i); if (!prevNonSpace.isDigit() && !MathDsl::isSuperscriptDigit(prevNonSpace) && !prevNonSpace.isLetter()) { return typedText; } } else if (typed == MathDsl::AddOp || MathDsl::isAdditionOperatorAlias(typed)) { if (!leftNonSpaceSupportsOperatorInsertion()) return typedText; operatorPrefix = MathDsl::buildWrappedToken(MathDsl::AddOp, MathDsl::AddWrap); } else if (MathDsl::isSubtractionOperatorAlias(typed)) { if (isScientificExponentSignContext()) return typedText; if (!leftNonSpaceSupportsOperatorInsertion()) return typedText; operatorPrefix = MathDsl::buildWrappedToken(MathDsl::SubOp, MathDsl::SubWrapSp); } else if (typed == MathDsl::DivOp || MathDsl::isDivisionOperatorAlias(typed)) { if (!leftNonSpaceSupportsOperatorInsertion()) return typedText; operatorPrefix = MathDsl::buildWrappedToken(MathDsl::DivOp, MathDsl::DivWrap); } else if (typed == MathDsl::PhasorOp) { if (!leftNonSpaceSupportsOperatorInsertion()) return typedText; operatorPrefix = MathDsl::buildWrappedToken(MathDsl::PhasorOp, MathDsl::AddWrap); } else if (MathDsl::isMultiplicationOperator(typed) || MathDsl::isMultiplicationOperatorAlias(typed, true)) { if (!leftNonSpaceSupportsOperatorInsertion()) return typedText; const bool useDotSign = typed == MathDsl::MulDotOp; const QChar sign = useDotSign ? MathDsl::MulDotOp : MathDsl::MulCrossOp; const QChar space = useDotSign ? MathDsl::MulDotWrapSp : MathDsl::MulCrossWrapSp; operatorPrefix = MathDsl::buildWrappedToken(sign, space); } else if (typed == MathDsl::Equals) { if (!leftNonSpaceSupportsOperatorInsertion()) return typedText; operatorPrefix = MathDsl::buildWrappedToken(MathDsl::Equals, UnicodeChars::Space); } else if (typed == MathDsl::LessThanOp) { if (!leftNonSpaceSupportsOperatorInsertion()) return typedText; operatorPrefix = MathDsl::buildWrappedToken(MathDsl::ShiftLeftOp); } else if (typed == MathDsl::GreaterThanOp) { if (!leftNonSpaceSupportsOperatorInsertion()) return typedText; operatorPrefix = MathDsl::buildWrappedToken(MathDsl::ShiftRightOp); } else { return typedText; } if (!operatorPrefix.isEmpty()) { // Avoid producing double spaces when the cursor is already after a // space and we are about to insert a grouped " " sequence. if (cursorPosition > 0 && text.at(cursorPosition - 1).isSpace() && operatorPrefix.size() >= 3 && operatorPrefix.at(0).isSpace()) { return operatorPrefix.mid(1); } return operatorPrefix; } if (typed == MathDsl::GroupStart) { int i = cursorPosition - 1; while (i >= 0 && text.at(i).isSpace()) --i; if (i >= 0) { const QChar prevNonSpace = text.at(i); bool numericLeftTerm = prevNonSpace.isDigit() && !MathDsl::isSuperscriptDigit(prevNonSpace); if (!numericLeftTerm && MathDsl::isSuperscriptDigit(prevNonSpace)) { int baseIndex = i; while (baseIndex >= 0 && MathDsl::isSuperscriptPowerChar(text.at(baseIndex))) --baseIndex; numericLeftTerm = baseIndex >= 0 && text.at(baseIndex).isDigit(); } if (numericLeftTerm) { return MathDsl::buildWrappedToken(MathDsl::MulCrossOp, MathDsl::MulCrossWrapSp) + typedText; } } } return MathDsl::buildWrappedToken(MathDsl::MulDotOp, MathDsl::MulDotWrapSp) + typedText; } inline bool isAnyOperator(const QChar& ch) { return ch == MathDsl::AddOp || ch == MathDsl::SubOpAl1 || ch == MathDsl::MulOpAl1 || ch == QLatin1Char('/') || ch == MathDsl::PhasorOp || ch == MathDsl::PercentOp || ch == MathDsl::PowOp || ch == MathDsl::BitAndOp || ch == MathDsl::BitOrOp || ch == MathDsl::Equals || ch == MathDsl::LessThanOp || ch == MathDsl::GreaterThanOp || MathDsl::isAdditionOperatorAlias(ch) || MathDsl::isSubtractionOperatorAlias(ch) || MathDsl::isDivisionOperatorAlias(ch) || MathDsl::isMultiplicationOperatorAlias(ch, true); } inline bool endsWithIncompleteExpressionToken(const QString& text) { const QString trimmed = text.trimmed(); if (trimmed.isEmpty()) return false; const QChar last = trimmed.at(trimmed.size() - 1); return last == MathDsl::GroupStart || MathDsl::isExpressionBoundaryOperatorOrSeparator(last); } inline bool expressionWithoutIgnorableTrailingToken(const QString& text, QString* out) { if (!out) return false; const QString trimmed = text.trimmed(); if (trimmed.isEmpty()) return false; int i = trimmed.size() - 1; const QChar last = trimmed.at(i); const bool isPlusMinusTail = (last == MathDsl::AddOp || MathDsl::isSubtractionOperatorAlias(last)); const bool isMultiplicationTail = (MathDsl::isMultiplicationOperator(last) || MathDsl::isMultiplicationOperatorAlias(last, true)); const bool isPhasorTail = last == MathDsl::PhasorOp; if (last != MathDsl::GroupStart && !isPlusMinusTail && !isMultiplicationTail && !isPhasorTail && last != MathDsl::FunArgSep && last != QLatin1Char('/') && last != MathDsl::PowOp && last != MathDsl::IntDivOp) return false; // Allow safe trailing suffixes: // - one or more '+' // - one or more '−' // - one or more '(' // - one or more '\' // - one '/' only if (last == QLatin1Char('/')) { --i; if (i >= 0 && trimmed.at(i) == QLatin1Char('/')) return false; } else if (last == MathDsl::PowOp) { --i; if (i >= 0 && trimmed.at(i) == MathDsl::PowOp) return false; } else if (isPlusMinusTail) { while (i >= 0 && (trimmed.at(i) == MathDsl::AddOp || MathDsl::isSubtractionOperatorAlias(trimmed.at(i)))) --i; } else if (isMultiplicationTail) { --i; if (i >= 0) { const QChar prev = trimmed.at(i); const bool prevIsMultiplication = (MathDsl::isMultiplicationOperator(prev) || MathDsl::isMultiplicationOperatorAlias(prev, true)); if (prevIsMultiplication) { --i; if (i >= 0) { const QChar prevPrev = trimmed.at(i); const bool prevPrevIsMultiplication = (MathDsl::isMultiplicationOperator(prevPrev) || MathDsl::isMultiplicationOperatorAlias(prevPrev, true)); if (prevPrevIsMultiplication) return false; } } } } else { while (i >= 0 && trimmed.at(i) == last) --i; } const QString prefix = trimmed.left(i + 1).trimmed(); if (prefix.isEmpty()) return false; const QChar prefixLast = prefix.at(prefix.size() - 1); if (prefixLast == MathDsl::GroupStart || MathDsl::isExpressionBoundaryOperatorOrSeparator(prefixLast) || prefixLast == MathDsl::IntDivOp) return false; *out = prefix; return true; } template inline QStringList parsePastedExpressionsImpl(const QString& text, NormalizeExpression normalizeExpression) { QStringList expressions; const QStringList candidates = text.split('\n', Qt::KeepEmptyParts, Qt::CaseSensitive); expressions.reserve(candidates.size()); for (const auto& candidate : candidates) { const auto expression = normalizeExpression(candidate.trimmed()); if (!expression.isEmpty()) expressions.append(expression); } return expressions; } inline QStringList parsePastedExpressions(const QString& text) { return parsePastedExpressionsImpl(text, normalizeExpressionOperators); } inline QStringList parsePastedExpressionsForEditorInput(const QString& text) { return parsePastedExpressionsImpl(text, normalizeExpressionOperatorsForEditorInput); } inline AutoAnsRewriteMode autoAnsRewriteModeForLeadingOperator(const QString& operatorText) { if (operatorText.size() != 1) return AutoAnsNoRewrite; const QChar op = normalizeExpressionOperatorsForEditorInput(operatorText).at(0); if (op == QLatin1Char('~')) return AutoAnsAppendAns; if (op == MathDsl::AddOp || MathDsl::isSubtractionOperatorAlias(op) || MathDsl::isMultiplicationOperator(op) || MathDsl::isDivisionOperator(op) || op == MathDsl::PowOp || op == MathDsl::FactorOp) { return AutoAnsPrependAns; } return AutoAnsNoRewrite; } inline QString applyAutoAnsRewrite(const QString& expression, AutoAnsRewriteMode mode) { if (mode == AutoAnsAppendAns) return expression + QStringLiteral("ans"); if (mode == AutoAnsPrependAns) return QStringLiteral("ans") + expression; return expression; } inline bool isAllowedLeadingCharAtExpressionStart(const QChar& ch, bool autoAnsEnabled) { if (ch.isDigit()) return true; if (ch == UnicodeChars::LowLine || ch == MathDsl::DollarSign || ch == UnicodeChars::Summation || ch == UnicodeChars::SquareRoot || ch == UnicodeChars::CubeRoot) { return true; } if (ch.isLetter()) { // Exclude ordinal indicators that behave like symbols on PT/US layouts // and are not intended to be valid leading tokens. if (ch == UnicodeChars::FeminineOrdinalIndicator || ch == UnicodeChars::MasculineOrdinalIndicator) return false; return true; } if (ch.category() == QChar::Symbol_Currency) return true; if (MathDsl::isSubtractionOperatorAlias(ch)) return true; if (ch == QLatin1Char('~') || ch == MathDsl::GroupStart || ch == MathDsl::ListStart || ch == MathDsl::UnitStart || ch == MathDsl::HexPrefixAl1 || ch == MathDsl::CommentSep) { return true; } if (!autoAnsEnabled) return false; // When auto-ans is enabled, allow leading operator starts that can be // rewritten as "ans ..." or "~ans". return ch == MathDsl::AddOp || MathDsl::isDivisionOperator(ch) || MathDsl::isMultiplicationOperator(ch) || ch == MathDsl::FactorOp || MathDsl::isAdditionOperatorAlias(ch) || MathDsl::isDivisionOperatorAlias(ch) || MathDsl::isMultiplicationOperatorAlias(ch, true) || ch == MathDsl::PowOp; } } #endif heldercorreia-speedcrunch-e7ca37f/src/gui/functionswidget.cpp000066400000000000000000000241021526573132500246270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2011, 2013-2014, 2016, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/functionswidget.h" #include "core/functions.h" #include "core/settings.h" #include "core/startupdiagnostics.h" #include "gui/dockliststyle.h" #include "gui/themedlineedit.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include FunctionsWidget::FunctionsWidget(QWidget* parent, const InitialState& state) : QWidget(parent) , m_filterTimer(new QTimer(this)) , m_domain(new QComboBox(this)) , m_domainLabel(new QLabel(this)) , m_functions(new QTreeWidget(this)) , m_noMatchLabel(new QLabel(m_functions)) , m_searchFilter(new ThemedLineEdit(this)) , m_searchLabel(new QLabel(this)) { constexpr int kControlRowHorizontalPadding = 8; m_filterTimer->setInterval(500); m_filterTimer->setSingleShot(true); m_functions->setAutoScroll(true); m_functions->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_functions->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_functions->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_functions->setColumnCount(2); m_functions->setRootIsDecorated(false); m_functions->setEditTriggers(QTreeWidget::NoEditTriggers); m_functions->setSelectionBehavior(QTreeWidget::SelectRows); DockListStyle::apply(m_functions); m_noMatchLabel->setAlignment(Qt::AlignCenter); m_noMatchLabel->adjustSize(); m_noMatchLabel->hide(); m_searchFilter->setClearButtonEnabled(true); m_domain->setEditable(false); m_domain->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); QWidget* domainBox = new QWidget(this); QHBoxLayout* domainLayout = new QHBoxLayout; domainLayout->addWidget(m_domainLabel); domainLayout->addWidget(m_domain); domainLayout->setSpacing(6); domainLayout->setContentsMargins(kControlRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding, kControlRowHorizontalPadding, 0); domainBox->setLayout(domainLayout); QWidget* searchBox = new QWidget(this); QHBoxLayout* searchLayout = new QHBoxLayout; searchLayout->addWidget(m_searchLabel); searchLayout->addWidget(m_searchFilter); searchLayout->setSpacing(6); searchLayout->setContentsMargins(kControlRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding, kControlRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding); searchBox->setLayout(searchLayout); QVBoxLayout* layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(domainBox); layout->addWidget(searchBox); layout->addWidget(m_functions); setLayout(layout); QWidget::setTabOrder(m_searchFilter, m_functions); setFocusProxy(m_searchFilter); translateControls(ListUpdate::DeferPopulation); connect(m_filterTimer, SIGNAL(timeout()), SLOT(updateList())); connect(m_domain, SIGNAL(activated(int)), SLOT(updateList())); connect(m_functions, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(handleItemActivated(QTreeWidgetItem*, int))); connect(m_searchFilter, SIGNAL(textChanged(const QString &)), SLOT(triggerFilter())); QShortcut* returnShortcut = new QShortcut(QKeySequence(Qt::Key_Return), this); returnShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(returnShortcut, &QShortcut::activated, this, [this]() { if (const QTreeWidgetItem* current = m_functions->currentItem()) emit functionSelected(current->text(0)); }); QShortcut* enterShortcut = new QShortcut(QKeySequence(Qt::Key_Enter), this); enterShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(enterShortcut, &QShortcut::activated, this, [this]() { if (const QTreeWidgetItem* current = m_functions->currentItem()) emit functionSelected(current->text(0)); }); restoreState(state.domain, state.searchText); } FunctionsWidget::~FunctionsWidget() { m_filterTimer->stop(); } void FunctionsWidget::updateList() { m_filterTimer->stop(); QString term = m_searchFilter->text(); const QString selectedDomain = m_domain->currentText(); QStringList functionNames = FunctionRepo::instance()->getIdentifiers(); FunctionRepo::instance()->retranslateText(); QStringList inputs {tr("All"), selectedDomain, term, QString::number(layoutDirection())}; inputs.reserve(inputs.size() + functionNames.size() * 3); for (const QString& identifier : functionNames) { if (const Function* function = FunctionRepo::instance()->find(identifier)) inputs << identifier << function->name() << function->domain(); } const bool unchanged = inputs == m_populatedInputs; StartupDiagnostics::AppearanceScope timing(unchanged ? "Skip unchanged functions dock list" : "Populate functions dock list", this); if (unchanged) return; setUpdatesEnabled(false); m_functions->clear(); for (int k = 0; k < functionNames.count(); ++k) { const QString identifier = functionNames.at(k); Function* f = FunctionRepo::instance()->find(identifier); if (!f) continue; QStringList str; str << identifier << f->name(); const bool domainMatches = selectedDomain == tr("All") || f->domain() == selectedDomain; if (term.isEmpty() || str.at(0).contains(term, Qt::CaseInsensitive) || str.at(1).contains(term, Qt::CaseInsensitive)) { if (domainMatches) { QTreeWidgetItem* item = new QTreeWidgetItem(m_functions, str); if (layoutDirection() == Qt::LeftToRight) { item->setTextAlignment(0, Qt::AlignLeft); item->setTextAlignment(1, Qt::AlignLeft); } else { item->setTextAlignment(0, Qt::AlignRight); item->setTextAlignment(1, Qt::AlignLeft); } } } } m_functions->resizeColumnToContents(0); m_functions->resizeColumnToContents(1); if (m_functions->topLevelItemCount() > 0) { m_noMatchLabel->hide(); m_functions->sortItems(0, Qt::AscendingOrder); } else { DockListStyle::showCenteredNoMatchLabel(m_functions, m_noMatchLabel); } m_populatedInputs = std::move(inputs); setUpdatesEnabled(true); } void FunctionsWidget::retranslateText() { translateControls(ListUpdate::Populate); } void FunctionsWidget::translateControls(ListUpdate mode) { FunctionRepo::instance()->retranslateText(); QStringList titles; const QString identifier = tr("Identifier"); const QString name = tr("Name"); titles << identifier << name; m_functions->setHeaderLabels(titles); m_searchLabel->setText(tr("Search")); m_domainLabel->setText(tr("Domain")); updateControlLabelWidths(); const QString selectedDomain = m_domain->currentText(); const int selectedDomainIndex = m_domain->currentIndex(); m_domain->clear(); m_domain->addItem(tr("All")); m_domain->addItems(FunctionRepo::instance()->domains()); int selectedIndex = m_domain->findText(selectedDomain); if (selectedIndex < 0 && selectedDomainIndex >= 0 && selectedDomainIndex < m_domain->count()) selectedIndex = selectedDomainIndex; m_domain->setCurrentIndex(selectedIndex >= 0 ? selectedIndex : 0); m_noMatchLabel->setText(tr("No match found")); if (mode == ListUpdate::Populate) updateList(); } QList FunctionsWidget::selectedItems() const { return m_functions->selectedItems(); } const QTreeWidgetItem* FunctionsWidget::currentItem() const { return m_functions->currentItem(); } QString FunctionsWidget::searchText() const { return m_searchFilter->text(); } void FunctionsWidget::setSearchText(const QString& text) { m_searchFilter->setText(text); } QString FunctionsWidget::selectedDomain() const { return m_domain->currentText(); } void FunctionsWidget::restoreState(const QString& domain, const QString& searchText) { StartupDiagnostics::AppearanceContext context("Restore functions dock filters"); const QSignalBlocker searchBlocker(m_searchFilter); const int index = m_domain->findText(domain); if (index >= 0) m_domain->setCurrentIndex(index); if (!searchText.isNull()) m_searchFilter->setText(searchText); updateList(); } void FunctionsWidget::setSelectedDomain(const QString& domain) { StartupDiagnostics::AppearanceContext context("Functions dock domain change"); const int index = m_domain->findText(domain); if (index >= 0) { m_domain->setCurrentIndex(index); updateList(); } } void FunctionsWidget::handleItemActivated(QTreeWidgetItem* item, int /*column*/) { emit functionSelected(item->text(0)); } void FunctionsWidget::clearSelection(QTreeWidgetItem*) { m_functions->clearSelection(); } void FunctionsWidget::triggerFilter() { m_filterTimer->stop(); m_filterTimer->start(); } void FunctionsWidget::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { StartupDiagnostics::AppearanceContext context("Functions dock LanguageChange"); retranslateText(); } else { QWidget::changeEvent(event); if (event->type() == QEvent::LayoutDirectionChange) retranslateText(); if (event->type() == QEvent::FontChange) QTimer::singleShot(0, this, [this]() { updateControlLabelWidths(); }); } } void FunctionsWidget::updateControlLabelWidths() { const int labelWidth = std::max(m_domainLabel->sizeHint().width(), m_searchLabel->sizeHint().width()); m_domainLabel->setFixedWidth(labelWidth); m_searchLabel->setFixedWidth(labelWidth); } heldercorreia-speedcrunch-e7ca37f/src/gui/functionswidget.h000066400000000000000000000032671526573132500243050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2011, 2013-2014, 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_FUNCTIONSWIDGET_H #define GUI_FUNCTIONSWIDGET_H #include #include #include class QEvent; class QComboBox; class QLabel; class QLineEdit; class QTreeWidget; class QTreeWidgetItem; class FunctionsWidget : public QWidget { Q_OBJECT public: struct InitialState { QString domain; QString searchText; }; explicit FunctionsWidget(QWidget* parent = nullptr, const InitialState& state = {}); ~FunctionsWidget(); const QTreeWidgetItem* currentItem() const; QList selectedItems() const; QString searchText() const; void setSearchText(const QString& text); QString selectedDomain() const; void setSelectedDomain(const QString& domain); void restoreState(const QString& domain, const QString& searchText); signals: void functionSelected(const QString&); protected slots: void handleItemActivated(QTreeWidgetItem*, int); virtual void changeEvent(QEvent*); void clearSelection(QTreeWidgetItem*); void updateList(); void retranslateText(); void triggerFilter(); private: Q_DISABLE_COPY(FunctionsWidget) enum class ListUpdate { DeferPopulation, Populate }; void translateControls(ListUpdate mode); void updateControlLabelWidths(); QTimer* m_filterTimer; QComboBox* m_domain; QLabel* m_domainLabel; QTreeWidget* m_functions; bool m_insertAllItems; QLabel* m_noMatchLabel; QLineEdit* m_searchFilter; QLabel* m_searchLabel; QStringList m_populatedInputs; }; #endif // GUI_FUNCTIONSWIDGET_H heldercorreia-speedcrunch-e7ca37f/src/gui/functiontooltiputils.cpp000066400000000000000000000214051526573132500257370ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/functiontooltiputils.h" #include "core/evaluator.h" #include "core/functions.h" #include "core/mathdsl.h" #include "core/unicodechars.h" #include "core/userfunction.h" #include namespace { struct ActiveFunctionCallContext { QString functionName; int argumentIndex; }; static bool trailingFunctionIdentifierAtCursor(const Evaluator* evaluator, const QString& expression, int cursorPosition, QString* functionName) { if (!functionName) return false; const int safeCursorPosition = qBound(0, cursorPosition, expression.length()); const QString prefix = expression.left(safeCursorPosition); const Tokens tokens = evaluator->scan(prefix); if (!tokens.valid() || tokens.isEmpty()) return false; const Token last = tokens.last(); if (!last.isIdentifier()) return false; const int tokenEnd = last.pos() + last.size(); if (tokenEnd != prefix.length()) return false; *functionName = last.text(); return true; } static bool openFunctionCallPrefixAtCursor(const QString& expression, int cursorPosition, QString* functionName) { if (!functionName) return false; const int safeCursorPosition = qBound(0, cursorPosition, expression.length()); const QString prefix = expression.left(safeCursorPosition); static const QRegularExpression s_openCallAtCursor( QStringLiteral(R"(([A-Za-z_][A-Za-z_0-9]*)\s*\(\s*$)")); const QRegularExpressionMatch match = s_openCallAtCursor.match(prefix); if (!match.hasMatch()) return false; *functionName = match.captured(1); return true; } static bool emptyFunctionCallAroundCursor(const QString& expression, int cursorPosition, QString* functionName) { if (!functionName) return false; const int safeCursorPosition = qBound(0, cursorPosition, expression.length()); int openPos = -1; int closePos = -1; for (int i = 0; i < expression.size(); ++i) { if (expression.at(i) != MathDsl::GroupStart) continue; int depth = 1; for (int j = i + 1; j < expression.size(); ++j) { if (expression.at(j) == MathDsl::GroupStart) ++depth; else if (expression.at(j) == MathDsl::GroupEnd) --depth; if (depth == 0) { const bool cursorInside = safeCursorPosition >= i + 1 && safeCursorPosition <= j + 1; if (cursorInside) { openPos = i; closePos = j; } i = j; break; } } } if (openPos < 0 || closePos < 0) return false; const QString inside = expression.mid(openPos + 1, closePos - openPos - 1).trimmed(); if (!inside.isEmpty()) return false; int nameEnd = openPos - 1; while (nameEnd >= 0 && expression.at(nameEnd).isSpace()) --nameEnd; if (nameEnd < 0) return false; int nameStart = nameEnd; while (nameStart >= 0 && (expression.at(nameStart).isLetterOrNumber() || expression.at(nameStart) == UnicodeChars::LowLine)) { --nameStart; } ++nameStart; if (nameStart > nameEnd) return false; *functionName = expression.mid(nameStart, nameEnd - nameStart + 1); return true; } bool activeFunctionCallContext(const Evaluator* evaluator, const QString& expression, int cursorPosition, ActiveFunctionCallContext* context) { if (!context) return false; const int safeCursorPosition = qBound(0, cursorPosition, expression.length()); const Tokens tokens = evaluator->scan(expression.left(safeCursorPosition)); if (!tokens.valid() || tokens.isEmpty()) return false; struct Scope { QString functionName; int argumentIndex; }; QVector scopes; Token previous = Token::null; bool hasPrevious = false; for (int i = 0; i < tokens.count(); ++i) { const Token token = tokens.at(i); const Token::Operator op = token.asOperator(); if (op == Token::AssociationStart && token.text() == QLatin1String("(")) { Scope scope; scope.argumentIndex = 0; if (hasPrevious && previous.isIdentifier()) scope.functionName = previous.text(); scopes.append(scope); } else if (op == Token::AssociationEnd && token.text() == QLatin1String(")")) { if (!scopes.isEmpty()) scopes.removeLast(); } else if (op == Token::ListSeparator) { if (!scopes.isEmpty() && !scopes.last().functionName.isEmpty()) ++scopes.last().argumentIndex; } previous = token; hasPrevious = true; } for (int i = scopes.count() - 1; i >= 0; --i) { if (!scopes.at(i).functionName.isEmpty()) { context->functionName = scopes.at(i).functionName; context->argumentIndex = scopes.at(i).argumentIndex; return true; } } return false; } QString formatFunctionUsageTooltip(const QString& functionName, const QStringList& parameters, int argumentIndex, bool escapeParameters) { QStringList displayParameters; displayParameters.reserve(parameters.count()); for (int i = 0; i < parameters.count(); ++i) { QString parameter = escapeParameters ? parameters.at(i).toHtmlEscaped() : parameters.at(i); if (i == argumentIndex) { int leading = 0; while (leading < parameter.size() && parameter.at(leading).isSpace()) ++leading; int trailing = 0; while (trailing < parameter.size() - leading && parameter.at(parameter.size() - 1 - trailing).isSpace()) { ++trailing; } const QString prefix = parameter.left(leading); const QString core = parameter.mid( leading, parameter.size() - leading - trailing); const QString suffix = parameter.right(trailing); parameter = prefix + QStringLiteral("%1").arg(core) + suffix; } displayParameters.append(parameter); } const QString escapedFunctionName = functionName.toHtmlEscaped(); return QStringLiteral("%1(%2)") .arg(escapedFunctionName, displayParameters.join(";")); } } // namespace namespace FunctionTooltipUtils { QString activeFunctionUsageTooltip(const Evaluator* evaluator, const QString& expression, int cursorPosition) { ActiveFunctionCallContext context; if (!activeFunctionCallContext(evaluator, expression, cursorPosition, &context)) { // Fallback for manual typing: show usage when cursor is just after a // recognized function identifier, even before typing '('. QString trailingFunctionName; if (!emptyFunctionCallAroundCursor(expression, cursorPosition, &trailingFunctionName) && !openFunctionCallPrefixAtCursor(expression, cursorPosition, &trailingFunctionName) && !trailingFunctionIdentifierAtCursor( evaluator, expression, cursorPosition, &trailingFunctionName)) { return QString(); } context.functionName = trailingFunctionName; context.argumentIndex = 0; } if (Function* function = FunctionRepo::instance()->find(context.functionName)) { const QString usage = function->usage(); if (usage.isEmpty()) return QStringLiteral("%1()").arg(context.functionName.toHtmlEscaped()); return formatFunctionUsageTooltip( context.functionName, usage.split(';'), context.argumentIndex, false ); } const auto userFunctions = evaluator->getUserFunctions(); for (const UserFunction& userFunction : userFunctions) { if (userFunction.name().compare(context.functionName, Qt::CaseInsensitive) != 0) continue; return formatFunctionUsageTooltip( userFunction.name(), userFunction.arguments(), context.argumentIndex, true ); } return QString(); } } // namespace FunctionTooltipUtils heldercorreia-speedcrunch-e7ca37f/src/gui/functiontooltiputils.h000066400000000000000000000006651526573132500254110ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_FUNCTIONTOOLTIPUTILS_H #define GUI_FUNCTIONTOOLTIPUTILS_H #include class Evaluator; namespace FunctionTooltipUtils { QString activeFunctionUsageTooltip(const Evaluator* evaluator, const QString& expression, int cursorPosition); } #endif heldercorreia-speedcrunch-e7ca37f/src/gui/genericdock.h000066400000000000000000000026641526573132500233460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_GENERICDOCK_H #define GUI_GENERICDOCK_H #include "gui/dockwidget.h" #include #include template class GenericDock : public DockWidget { // Can't have Q_OBJECT in templates. That means no signals, slots, or properties in this class. public: template explicit GenericDock(const char* i18nContext, const char* name, QWidget* parent = nullptr, Args&&... args) : DockWidget(parent), m_name(name), m_i18nContext(i18nContext), m_widget(new Widget(this, std::forward(args)...)) { setWidget(m_widget); setMinimumWidth(200); retranslateText(); } void retranslateText() { setWindowTitle(QCoreApplication::translate(m_i18nContext, m_name)); } Widget* widget() const { return m_widget; } void setWidget(Widget* widget) { QDockWidget::setWidget(widget); m_widget = widget; setFocusProxy(widget); } protected: void changeEvent(QEvent* e) override { if (e->type() == QEvent::LanguageChange) retranslateText(); else QDockWidget::changeEvent(e); } private: const char* m_name; const char* m_i18nContext; Widget* m_widget; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/gtkmenupalette.h000066400000000000000000000022361526573132500241150ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef SPEEDCRUNCH_GTKMENUPALETTE_H #define SPEEDCRUNCH_GTKMENUPALETTE_H #include #include namespace GtkMenuPalette { // GTK and Cairo are optional runtime libraries. Keep their public ABI here // so the GNOME menu colors do not add a build dependency on other platforms. struct Rgba { double red, green, blue, alpha; }; struct Api { void* (*popoverNew)(void*); void* (*modelButtonNew)(); void (*add)(void*, void*); void* (*context)(void*); void (*setState)(void*, unsigned); void (*color)(void*, unsigned, Rgba*); void (*background)(void*, void*, double, double, double, double); void (*destroyWidget)(void*); void* (*refSink)(void*); void (*unref)(void*); void* (*surfaceForData)(unsigned char*, int, int, int, int); void* (*createPainter)(void*); void (*destroyPainter)(void*); void (*flushSurface)(void*); void (*destroySurface)(void*); }; QPalette read(const Api& api, const QPalette& fallback); std::optional systemPalette(const QPalette& fallback); void invalidate(); } #endif heldercorreia-speedcrunch-e7ca37f/src/gui/historywidget.cpp000066400000000000000000000127131526573132500243250ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2011, 2014-2016, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/historywidget.h" #include "core/sessionhistory.h" #include "core/numberformatter.h" #include "core/session.h" #include "gui/dockliststyle.h" #include #include #include #include #include #include #include namespace { QString groupedExpressionForHistory(const QString& input) { return NumberFormatter::formatNumericLiteralForDisplay(input); } } HistoryWidget::HistoryWidget(QWidget *parent) : QWidget(parent) , m_list(new QListWidget(this)) , m_session(nullptr) { m_list->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_list->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_list->setUniformItemSizes(true); DockListStyle::apply(m_list); m_list->setContextMenuPolicy(Qt::CustomContextMenu); QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(m_list); setLayout(layout); connect(m_list, SIGNAL(itemActivated(QListWidgetItem *)), SLOT(handleItem(QListWidgetItem *))); connect(m_list, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(handleContextMenuRequested(const QPoint &))); QShortcut* returnShortcut = new QShortcut(QKeySequence(Qt::Key_Return), this); returnShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(returnShortcut, &QShortcut::activated, this, [this]() { if (QListWidgetItem* current = m_list->currentItem()) handleItem(current); }); QShortcut* enterShortcut = new QShortcut(QKeySequence(Qt::Key_Enter), this); enterShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(enterShortcut, &QShortcut::activated, this, [this]() { if (QListWidgetItem* current = m_list->currentItem()) handleItem(current); }); updateHistory(); } void HistoryWidget::updateHistory() { const int historySize = m_session != nullptr ? m_session->historySize() : 0; if (historySize == 0) { m_list->clear(); m_list->clearSelection(); return; } if (historySize == m_list->count() + 1) { appendHistoryItem(historySize - 1); m_list->scrollToBottom(); return; } if (historySize == m_list->count()) { const int count = historySize; if (count == 1) { const QString expression = m_session->historyEntryAtRef(0).expr(); QListWidgetItem* item = m_list->item(0); if (item != nullptr && item->data(Qt::UserRole).toString() != expression) { item->setText(groupedExpressionForHistory(expression)); item->setData(Qt::UserRole, expression); } m_list->scrollToBottom(); return; } QListWidgetItem* secondItem = m_list->item(1); if (secondItem != nullptr && secondItem->data(Qt::UserRole).toString() == m_session->historyEntryAtRef(0).expr()) { delete m_list->takeItem(0); appendHistoryItem(historySize - 1); m_list->scrollToBottom(); return; } } rebuildHistory(); } void HistoryWidget::appendHistoryItem(int index) { if (m_session == nullptr || index < 0 || index >= m_session->historySize()) return; const QString expression = m_session->historyEntryAtRef(index).expr(); QListWidgetItem* item = new QListWidgetItem(groupedExpressionForHistory(expression)); item->setData(Qt::UserRole, expression); m_list->addItem(item); } void HistoryWidget::rebuildHistory() { const int historySize = m_session != nullptr ? m_session->historySize() : 0; m_list->setUpdatesEnabled(false); m_list->clear(); m_list->clearSelection(); for (int i = 0; i < historySize; ++i) appendHistoryItem(i); m_list->setUpdatesEnabled(true); m_list->scrollToBottom(); } void HistoryWidget::setSession(const Session* session) { if (m_session == session) return; m_session = session; m_list->clear(); m_list->clearSelection(); updateHistory(); } void HistoryWidget::handleItem(QListWidgetItem *item) { m_list->clearSelection(); emit expressionSelected(item->data(Qt::UserRole).toString()); } void HistoryWidget::handleContextMenuRequested(const QPoint &position) { const int historyIndex = m_list->indexAt(position).row(); if (historyIndex < 0) return; QMenu menu(m_list); QAction *removeAboveAction = menu.addAction(tr("Remove All Calculations Above")); connect(removeAboveAction, &QAction::triggered, this, [this, historyIndex]() { emit removeHistoryEntriesAboveRequested(historyIndex); }); QAction *removeAction = menu.addAction(tr("Remove This Calculation")); connect(removeAction, &QAction::triggered, this, [this, historyIndex]() { emit removeHistoryEntryRequested(historyIndex); }); QAction *removeBelowAction = menu.addAction(tr("Remove All Calculations Below")); connect(removeBelowAction, &QAction::triggered, this, [this, historyIndex]() { emit removeHistoryEntriesBelowRequested(historyIndex); }); menu.exec(m_list->viewport()->mapToGlobal(position)); } void HistoryWidget::changeEvent(QEvent *e) { if (e->type() == QEvent::LanguageChange) setLayoutDirection(Qt::LeftToRight); else QWidget::changeEvent(e); } heldercorreia-speedcrunch-e7ca37f/src/gui/historywidget.h000066400000000000000000000020271526573132500237670ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2011, 2013-2015, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_HISTORYWIDGET_H #define GUI_HISTORYWIDGET_H #include class QListWidget; class QListWidgetItem; class HistoryEntry; class QPoint; class Session; class HistoryWidget : public QWidget { Q_OBJECT public: explicit HistoryWidget(QWidget *parent = 0); void setSession(const Session* session); public slots: void updateHistory(); signals: void expressionSelected(const QString &); void removeHistoryEntryRequested(int index); void removeHistoryEntriesAboveRequested(int index); void removeHistoryEntriesBelowRequested(int index); protected slots: void handleItem(QListWidgetItem *); void handleContextMenuRequested(const QPoint &position); protected: void changeEvent(QEvent *); private: Q_DISABLE_COPY(HistoryWidget) void appendHistoryItem(int index); void rebuildHistory(); QListWidget *m_list; const Session* m_session; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/keypad.cpp000066400000000000000000001331011526573132500226700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014, 2017, 2021, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/keypad.h" #include "core/settings.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include "gui/oklchutils.h" #include "gui/tooltipstyleutils.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x040400 && defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) #include #endif const Keypad::KeyDescription Keypad::keyDescriptions[] = { {QString::fromLatin1("0"), Key0, true, 3, 0}, {QString::fromLatin1("1"), Key1, true, 2, 0}, {QString::fromLatin1("2"), Key2, true, 2, 1}, {QString::fromLatin1("3"), Key3, true, 2, 2}, {QString::fromLatin1("4"), Key4, true, 1, 0}, {QString::fromLatin1("5"), Key5, true, 1, 1}, {QString::fromLatin1("6"), Key6, true, 1, 2}, {QString::fromLatin1("7"), Key7, true, 0, 0}, {QString::fromLatin1("8"), Key8, true, 0, 1}, {QString::fromLatin1("9"), Key9, true, 0, 2}, {QString::fromLatin1(","), KeyRadixChar, true, 3, 1}, {QString::fromUtf8("="), KeyEquals, true, 3, 2}, {QString::fromUtf8("÷"), KeyDivide, true, 0, 3}, {QString(MathDsl::MulCrossOp), KeyTimes, true, 1, 3}, {QString(UnicodeChars::MinusSign), KeyMinus, true, 2, 3}, {QString::fromUtf8("+"), KeyPlus, true, 3, 3}, {QString::fromLatin1("arccos"), KeyAcos, false, 2, 7}, {QString::fromLatin1("ans"), KeyAns, false, 1, 9}, {QString::fromLatin1("arcsin"), KeyAsin, false, 2, 5}, {QString::fromLatin1("arctan"), KeyAtan, false, 3, 5}, {QString::fromUtf8("⌧"), KeyClear, false, 0, 8}, {QString::fromLatin1("cos"), KeyCos, false, 2, 6}, {QString::fromLatin1("E"), KeyEE, false, 0, 6}, {QString::fromLatin1("exp"), KeyExp, false, 0, 7}, {QString::fromLatin1("!"), KeyFactorial, false, 3, 9}, {QString::fromLatin1("ln"), KeyLn, false, 1, 6}, {QString::fromLatin1("("), KeyLeftPar, false, 2, 8}, {QString::fromUtf8("⌫"), KeyBackspace, false, 0, 9}, {QString::fromLatin1("%"), KeyPercent, false, 3, 8}, {QString::fromUtf8("xʸ"), KeyRaise, false, 1, 4}, {QString::fromLatin1(")"), KeyRightPar, false, 2, 9}, {QString::fromLatin1("sin"), KeySin, false, 2, 4}, {QString::fromLatin1("tan"), KeyTan, false, 3, 4}, {QString::fromLatin1(";"), KeyArgumentSeparator, false, 3, 7}, {QString::fromUtf8("x²"), KeySquare, false, 0, 5}, {QString::fromUtf8("â�¿âˆš"), KeyRoot, false, 1, 5}, {QString::fromLatin1("log10"), KeyLog10, false, 1, 7}, {QString::fromLatin1("mod"), KeyMod, false, 3, 6}, {QString::fromUtf8("Ï€"), KeyPi, false, 1, 8}, {QString::fromUtf8("√"), KeySqrt, false, 0, 4} }; namespace { struct LayoutEntry { Keypad::Button button; int row; int column; }; const LayoutEntry s_basicWideLayout[] = { {Keypad::Key7, 0, 0}, {Keypad::Key8, 0, 1}, {Keypad::Key9, 0, 2}, {Keypad::KeyDivide, 0, 3}, {Keypad::KeyBackspace, 0, 4}, {Keypad::Key4, 1, 0}, {Keypad::Key5, 1, 1}, {Keypad::Key6, 1, 2}, {Keypad::KeyTimes, 1, 3}, {Keypad::KeyLeftPar, 1, 4}, {Keypad::Key1, 2, 0}, {Keypad::Key2, 2, 1}, {Keypad::Key3, 2, 2}, {Keypad::KeyMinus, 2, 3}, {Keypad::KeyRightPar, 2, 4}, {Keypad::Key0, 3, 0}, {Keypad::KeyRadixChar, 3, 1}, {Keypad::KeyEquals, 3, 2}, {Keypad::KeyPlus, 3, 3}, {Keypad::KeyPercent, 3, 4} }; const LayoutEntry s_scientificWideLayout[] = { {Keypad::Key7, 0, 0}, {Keypad::Key8, 0, 1}, {Keypad::Key9, 0, 2}, {Keypad::KeyDivide, 0, 3}, {Keypad::KeySqrt, 0, 4}, {Keypad::KeySquare, 0, 5}, {Keypad::KeyEE, 0, 6}, {Keypad::KeyExp, 0, 7}, {Keypad::KeyClear, 0, 8}, {Keypad::KeyBackspace, 0, 9}, {Keypad::Key4, 1, 0}, {Keypad::Key5, 1, 1}, {Keypad::Key6, 1, 2}, {Keypad::KeyTimes, 1, 3}, {Keypad::KeyRaise, 1, 4}, {Keypad::KeyRoot, 1, 5}, {Keypad::KeyLn, 1, 6}, {Keypad::KeyLog10, 1, 7}, {Keypad::KeyPi, 1, 8}, {Keypad::KeyAns, 1, 9}, {Keypad::Key1, 2, 0}, {Keypad::Key2, 2, 1}, {Keypad::Key3, 2, 2}, {Keypad::KeyMinus, 2, 3}, {Keypad::KeySin, 2, 4}, {Keypad::KeyAsin, 2, 5}, {Keypad::KeyCos, 2, 6}, {Keypad::KeyAcos, 2, 7}, {Keypad::KeyLeftPar, 2, 8}, {Keypad::KeyRightPar, 2, 9}, {Keypad::Key0, 3, 0}, {Keypad::KeyRadixChar, 3, 1}, {Keypad::KeyEquals, 3, 2}, {Keypad::KeyPlus, 3, 3}, {Keypad::KeyTan, 3, 4}, {Keypad::KeyAtan, 3, 5}, {Keypad::KeyMod, 3, 6}, {Keypad::KeyArgumentSeparator, 3, 7}, {Keypad::KeyPercent, 3, 8}, {Keypad::KeyFactorial, 3, 9} }; const LayoutEntry s_scientificNarrowLayout[] = { {Keypad::Key7, 0, 0}, {Keypad::Key8, 0, 1}, {Keypad::Key9, 0, 2}, {Keypad::KeyDivide, 0, 3}, {Keypad::KeyClear, 0, 4}, {Keypad::Key4, 1, 0}, {Keypad::Key5, 1, 1}, {Keypad::Key6, 1, 2}, {Keypad::KeyTimes, 1, 3}, {Keypad::KeyBackspace, 1, 4}, {Keypad::Key1, 2, 0}, {Keypad::Key2, 2, 1}, {Keypad::Key3, 2, 2}, {Keypad::KeyMinus, 2, 3}, {Keypad::KeyLeftPar, 2, 4}, {Keypad::Key0, 3, 0}, {Keypad::KeyRadixChar, 3, 1}, {Keypad::KeyEquals, 3, 2}, {Keypad::KeyPlus, 3, 3}, {Keypad::KeyRightPar, 3, 4}, {Keypad::KeySqrt, 4, 0}, {Keypad::KeySquare, 4, 1}, {Keypad::KeyEE, 4, 2}, {Keypad::KeyExp, 4, 3}, {Keypad::KeyPi, 4, 4}, {Keypad::KeyRaise, 5, 0}, {Keypad::KeyRoot, 5, 1}, {Keypad::KeyLn, 5, 2}, {Keypad::KeyLog10, 5, 3}, {Keypad::KeyAns, 5, 4}, {Keypad::KeySin, 6, 0}, {Keypad::KeyAsin, 6, 1}, {Keypad::KeyCos, 6, 2}, {Keypad::KeyAcos, 6, 3}, {Keypad::KeyMod, 6, 4}, {Keypad::KeyTan, 7, 0}, {Keypad::KeyAtan, 7, 1}, {Keypad::KeyPercent, 7, 2}, {Keypad::KeyFactorial, 7, 3}, {Keypad::KeyArgumentSeparator, 7, 4} }; void layoutEntries(Keypad::LayoutMode layoutMode, const LayoutEntry** entries, int* count) { *entries = nullptr; *count = 0; if (layoutMode == Keypad::LayoutModeScientificWide) { *entries = s_scientificWideLayout; *count = int(sizeof s_scientificWideLayout / sizeof s_scientificWideLayout[0]); } else if (layoutMode == Keypad::LayoutModeScientificNarrow) { *entries = s_scientificNarrowLayout; *count = int(sizeof s_scientificNarrowLayout / sizeof s_scientificNarrowLayout[0]); } else if (layoutMode == Keypad::LayoutModeBasicWide) { *entries = s_basicWideLayout; *count = int(sizeof s_basicWideLayout / sizeof s_basicWideLayout[0]); } } QString customButtonInsertText(Keypad::Button button, QChar radixCharacter) { switch (button) { case Keypad::Key0: return QString::fromLatin1("0"); case Keypad::Key1: return QString::fromLatin1("1"); case Keypad::Key2: return QString::fromLatin1("2"); case Keypad::Key3: return QString::fromLatin1("3"); case Keypad::Key4: return QString::fromLatin1("4"); case Keypad::Key5: return QString::fromLatin1("5"); case Keypad::Key6: return QString::fromLatin1("6"); case Keypad::Key7: return QString::fromLatin1("7"); case Keypad::Key8: return QString::fromLatin1("8"); case Keypad::Key9: return QString::fromLatin1("9"); case Keypad::KeyPlus: return QString::fromLatin1("+"); case Keypad::KeyMinus: return QString::fromUtf8("−"); case Keypad::KeyTimes: return QString(MathDsl::MulCrossOp); case Keypad::KeyDivide: return QString::fromUtf8("÷"); case Keypad::KeyEE: return QString::fromLatin1("e"); case Keypad::KeyLeftPar: return QString::fromLatin1("("); case Keypad::KeyRightPar: return QString::fromLatin1(")"); case Keypad::KeyRaise: return QString::fromLatin1("^"); case Keypad::KeyPercent: return QString::fromLatin1("%"); case Keypad::KeyFactorial: return QString::fromLatin1("!"); case Keypad::KeySquare: return QString::fromLatin1("^2"); case Keypad::KeyArgumentSeparator: return QString::fromLatin1(";"); case Keypad::KeyPi: return QString::fromLatin1("pi"); case Keypad::KeyAns: return QString::fromLatin1("ans"); case Keypad::KeySqrt: return QString::fromLatin1("sqrt("); case Keypad::KeyRoot: return QString::fromLatin1("root("); case Keypad::KeyLog10: return QString::fromLatin1("log10("); case Keypad::KeyMod: return QString::fromLatin1("mod("); case Keypad::KeyLn: return QString::fromLatin1("ln("); case Keypad::KeyExp: return QString::fromLatin1("exp("); case Keypad::KeySin: return QString::fromLatin1("sin("); case Keypad::KeyCos: return QString::fromLatin1("cos("); case Keypad::KeyTan: return QString::fromLatin1("tan("); case Keypad::KeyAcos: return QString::fromLatin1("arccos("); case Keypad::KeyAtan: return QString::fromLatin1("arctan("); case Keypad::KeyAsin: return QString::fromLatin1("arcsin("); case Keypad::KeyRadixChar: return QString(radixCharacter); default: break; } return QString(); } QString customButtonLabel(Keypad::Button button, QChar radixCharacter) { switch (button) { case Keypad::Key0: return QString::fromLatin1("0"); case Keypad::Key1: return QString::fromLatin1("1"); case Keypad::Key2: return QString::fromLatin1("2"); case Keypad::Key3: return QString::fromLatin1("3"); case Keypad::Key4: return QString::fromLatin1("4"); case Keypad::Key5: return QString::fromLatin1("5"); case Keypad::Key6: return QString::fromLatin1("6"); case Keypad::Key7: return QString::fromLatin1("7"); case Keypad::Key8: return QString::fromLatin1("8"); case Keypad::Key9: return QString::fromLatin1("9"); case Keypad::KeyEquals: return QString::fromLatin1("="); case Keypad::KeyPlus: return QString::fromLatin1("+"); case Keypad::KeyMinus: return QString::fromUtf8("−"); case Keypad::KeyTimes: return QString(MathDsl::MulCrossOp); case Keypad::KeyDivide: return QString::fromUtf8("÷"); case Keypad::KeyRadixChar: return QString(radixCharacter); case Keypad::KeyClear: return QString::fromUtf8("⌧"); case Keypad::KeyEE: return QString::fromLatin1("E"); case Keypad::KeyLeftPar: return QString::fromLatin1("("); case Keypad::KeyRightPar: return QString::fromLatin1(")"); case Keypad::KeyRaise: return QString::fromUtf8("xʸ"); case Keypad::KeySqrt: return QString::fromUtf8("√"); case Keypad::KeyRoot: return QString::fromUtf8("â�¿âˆš"); case Keypad::KeyLog10: return QString::fromLatin1("log10"); case Keypad::KeyMod: return QString::fromLatin1("mod"); case Keypad::KeyBackspace: return QString::fromUtf8("⌫"); case Keypad::KeyPercent: return QString::fromLatin1("%"); case Keypad::KeyFactorial: return QString::fromLatin1("!"); case Keypad::KeyPi: return QString::fromUtf8("Ï€"); case Keypad::KeyAns: return QString::fromLatin1("ans"); case Keypad::KeySquare: return QString::fromUtf8("x²"); case Keypad::KeyArgumentSeparator: return QString::fromLatin1(";"); case Keypad::KeyExp: return QString::fromLatin1("exp"); case Keypad::KeyLn: return QString::fromLatin1("ln"); case Keypad::KeySin: return QString::fromLatin1("sin"); case Keypad::KeyAsin: return QString::fromLatin1("arcsin"); case Keypad::KeyCos: return QString::fromLatin1("cos"); case Keypad::KeyAcos: return QString::fromLatin1("arccos"); case Keypad::KeyTan: return QString::fromLatin1("tan"); case Keypad::KeyAtan: return QString::fromLatin1("arctan"); default: break; } return QString(); } int customButtonAction(Keypad::Button button) { switch (button) { case Keypad::KeyBackspace: return Settings::CustomKeypadActionBackspace; case Keypad::KeyClear: return Settings::CustomKeypadActionClearExpression; case Keypad::KeyEquals: return Settings::CustomKeypadActionEvaluateExpression; default: break; } return Settings::CustomKeypadActionInsertText; } QHash createLayoutMap(Keypad::LayoutMode layoutMode) { QHash map; const LayoutEntry* entries = nullptr; int count = 0; layoutEntries(layoutMode, &entries, &count); for (int i = 0; i < count; ++i) map.insert(entries[i].button, QPoint(entries[i].column, entries[i].row)); return map; } QFont scaledFont(const QFont& base, int scalePercent) { const qreal scale = qreal(scalePercent) / 100.0; QFont font(base); if (font.pointSizeF() > 0.0) { font.setPointSizeF(font.pointSizeF() * scale); } else if (font.pixelSize() > 0) { font.setPixelSize(qMax(1, qRound(font.pixelSize() * scale))); } return font; } enum class KeypadButtonVisualRole { Normal, Numeric, ArithmeticOperator, Evaluate }; struct KeypadButtonColors { QColor background; QColor foreground; QColor hoverBackground; QColor hoverForeground; QColor pressedBackground; QColor pressedForeground; }; bool isArithmeticOperatorButton(Keypad::Button button) { switch (button) { case Keypad::KeyPlus: case Keypad::KeyMinus: case Keypad::KeyTimes: case Keypad::KeyDivide: return true; default: return false; } } bool isNumericButton(Keypad::Button button) { switch (button) { case Keypad::Key0: case Keypad::Key1: case Keypad::Key2: case Keypad::Key3: case Keypad::Key4: case Keypad::Key5: case Keypad::Key6: case Keypad::Key7: case Keypad::Key8: case Keypad::Key9: case Keypad::KeyRadixChar: return true; default: return false; } } KeypadButtonVisualRole visualRoleForButton(Keypad::Button button) { if (button == Keypad::KeyEquals) return KeypadButtonVisualRole::Evaluate; if (isArithmeticOperatorButton(button)) return KeypadButtonVisualRole::ArithmeticOperator; if (isNumericButton(button)) return KeypadButtonVisualRole::Numeric; return KeypadButtonVisualRole::Normal; } bool isArithmeticOperatorText(const QString& text) { const QString trimmed = text.trimmed(); if (trimmed.size() != 1) return false; const QChar ch = trimmed.at(0); return MathDsl::isAdditionOperator(ch) || MathDsl::isAdditionOperatorAlias(ch) || MathDsl::isSubtractionOperator(ch) || MathDsl::isSubtractionOperatorAlias(ch) || MathDsl::isMultiplicationOperator(ch) || MathDsl::isMultiplicationOperatorAlias(ch) || MathDsl::isDivisionOperator(ch) || MathDsl::isDivisionOperatorAlias(ch); } bool isNumericButtonText(const QString& text) { const QString trimmed = text.trimmed(); if (trimmed.size() != 1) return false; const QChar ch = trimmed.at(0); return ch.isDigit() || ch == MathDsl::DotSep || ch == MathDsl::CommaSep; } KeypadButtonVisualRole visualRoleForCustomButton( const Keypad::CustomButtonDescription& button) { if (button.action == Settings::CustomKeypadActionEvaluateExpression) return KeypadButtonVisualRole::Evaluate; if (button.action == Settings::CustomKeypadActionInsertText && isArithmeticOperatorText(button.text)) { return KeypadButtonVisualRole::ArithmeticOperator; } if (button.action == Settings::CustomKeypadActionInsertText && isNumericButtonText(button.text)) { return KeypadButtonVisualRole::Numeric; } return KeypadButtonVisualRole::Normal; } int primaryHueChromaPercentForRole(KeypadButtonVisualRole role) { switch (role) { case KeypadButtonVisualRole::Evaluate: return UiConfig::KeypadEvaluatePrimaryHueChromaPercent; case KeypadButtonVisualRole::ArithmeticOperator: return UiConfig::KeypadOperatorPrimaryHueChromaPercent; case KeypadButtonVisualRole::Numeric: return UiConfig::KeypadDigitPrimaryHueChromaPercent; case KeypadButtonVisualRole::Normal: break; } return 0; } QColor oklchWithLightnessOffset(const QColor& color, double offset) { if (!color.isValid()) return color; Oklch oklch = qColorToOklch(color); oklch.l = qBound(0.0, oklch.l + offset, 1.0); const QColor adjusted = oklchToValidSrgbQColor(oklch); return adjusted.isValid() ? adjusted : color; } QColor keypadGradientTopColor(const QColor& background) { return oklchWithLightnessOffset(background, UiConfig::KeypadButtonGradientLightnessDelta); } QColor keypadGradientBottomColor(const QColor& background) { return oklchWithLightnessOffset(background, -UiConfig::KeypadButtonGradientLightnessDelta); } QColor keypadPrimaryStateBackground(const QColor& primary, const QColor& stateBackground, const QColor& normalBackground) { if (!primary.isValid() || !stateBackground.isValid() || !normalBackground.isValid()) return primary.isValid() ? primary : stateBackground; Oklch accent = qColorToOklch(primary); const Oklch state = qColorToOklch(stateBackground); const Oklch normal = qColorToOklch(normalBackground); const double offset = state.l - normal.l; if (qAbs(offset) < 1e-9) return primary; accent.l = qBound(0.0, accent.l + offset, 1.0); const QColor color = oklchToValidSrgbQColor(accent); return color.isValid() ? color : primary; } QColor keypadPrimaryHueFillBackground(const QColor& primary, const QColor& stateBackground, const QColor& normalBackground, int primaryPercent) { if (!primary.isValid() || !stateBackground.isValid() || !normalBackground.isValid()) return stateBackground; const double primaryRatio = double(qBound(0, primaryPercent, 100)) / 100.0; if (primaryRatio <= 0.0) return stateBackground; const QColor primaryStateBackground = keypadPrimaryStateBackground(primary, stateBackground, normalBackground); if (primaryRatio >= 1.0) return primaryStateBackground; const Oklch stateOklch = qColorToOklch(stateBackground); const Oklch primaryStateOklch = qColorToOklch(primaryStateBackground); // The percent is a blend toward the full primary state, not just a chroma // multiplier. That makes 100 match the primary accent exactly while lower // role percentages still read as quieter primary-hue fills. Oklch fill { stateOklch.l + (primaryStateOklch.l - stateOklch.l) * primaryRatio, stateOklch.c + (primaryStateOklch.c - stateOklch.c) * primaryRatio, primaryStateOklch.h, stateOklch.alpha }; const QColor color = oklchToValidSrgbQColor(fill); return color.isValid() ? color : stateBackground; } KeypadButtonColors keypadButtonColorsForRole(const KeypadButtonColors& normalColors, const QColor& primaryBackground, KeypadButtonVisualRole role) { if (!primaryBackground.isValid() || role == KeypadButtonVisualRole::Normal) return normalColors; const auto withForegrounds = [](const QColor& background, const QColor& hoverBackground, const QColor& pressedBackground) { return KeypadButtonColors { background, aaForegroundForBackground(background), hoverBackground, aaForegroundForBackground(hoverBackground), pressedBackground, aaForegroundForBackground(pressedBackground) }; }; const int primaryPercent = primaryHueChromaPercentForRole(role); const QColor background = keypadPrimaryHueFillBackground( primaryBackground, normalColors.background, normalColors.background, primaryPercent); const QColor hoverBackground = keypadPrimaryHueFillBackground( primaryBackground, normalColors.hoverBackground, normalColors.background, primaryPercent); const QColor pressedBackground = keypadPrimaryHueFillBackground( primaryBackground, normalColors.pressedBackground, normalColors.background, primaryPercent); return withForegrounds(background, hoverBackground, pressedBackground); } QPalette keypadButtonPalette(const QPalette& source, const QColor& background, const QColor& foreground) { QPalette palette = source; for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { palette.setColor(group, QPalette::Button, background); palette.setColor(group, QPalette::ButtonText, foreground); palette.setColor(group, QPalette::Window, background); palette.setColor(group, QPalette::WindowText, foreground); } return palette; } QString keypadButtonStyleSheet(const QPalette& palette, const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& pressedBackground, const QColor& pressedForeground, bool classic); void applyKeypadButtonStyle(QPushButton* button, const QPalette& sourcePalette, const KeypadButtonColors& colors, bool classic) { if (button == nullptr) return; // Qt repolishes a widget when its stylesheet changes, and that can reset // palette roles exposed through QPalette. Apply the stylesheet first, then // restore the semantic button/text colors so runtime theme changes keep the // same inspectable palette roles as startup theme application. button->setStyleSheet(keypadButtonStyleSheet(sourcePalette, colors.background, colors.foreground, colors.hoverBackground, colors.hoverForeground, colors.pressedBackground, colors.pressedForeground, classic)); button->setPalette(keypadButtonPalette(sourcePalette, colors.background, colors.foreground)); } QString keypadButtonBackgroundStyle(const QColor& background) { return QString::fromLatin1( " background-color: %1;" " background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," " stop: 0 %2, stop: 1 %3);") .arg(background.name(), keypadGradientTopColor(background).name(), keypadGradientBottomColor(background).name()); } QString keypadButtonStyleSheet(const QPalette& palette, const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& pressedBackground, const QColor& pressedForeground, bool classic); QString keypadButtonStyleSheet(const QPalette& palette, bool classic = false) { return keypadButtonStyleSheet(palette, palette.color(QPalette::Button), palette.color(QPalette::ButtonText), palette.color(QPalette::Highlight), palette.color(QPalette::HighlightedText), palette.color(QPalette::Mid), palette.color(QPalette::ButtonText), classic); } QString keypadButtonStyleSheet(const QPalette& palette, const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& pressedBackground, const QColor& pressedForeground, bool classic) { Q_UNUSED(palette); const QString margin = QString::number(classic ? UiConfig::ClassicKeypadButtonMargin : UiConfig::KeypadButtonMargin); const QString cornerRadius = QString::number(classic ? UiConfig::ClassicKeypadButtonCornerRadius : UiConfig::KeypadButtonCornerRadius); const QString padding = QString::number(classic ? UiConfig::ClassicKeypadButtonPadding : UiConfig::KeypadButtonPadding); return QString::fromLatin1( "QPushButton {" " border: none;" " border-radius: %2px;" " margin: %1px;" " padding: %3px;" "%4" " color: %5;" "}" "QPushButton:hover {" " border: none;" "%6" " color: %7;" "}" "QPushButton:pressed {" " border: none;" "%8" " color: %9;" "}") .arg(margin, cornerRadius, padding, keypadButtonBackgroundStyle(background), foreground.name(), keypadButtonBackgroundStyle(hoverBackground), hoverForeground.name(), keypadButtonBackgroundStyle(pressedBackground), pressedForeground.name()); } QSize compactButtonSize(const QList& buttons) { QSize textSize; for (QPushButton* button : buttons) { button->ensurePolished(); const QFontMetrics metrics = button->fontMetrics(); textSize = textSize.expandedTo(QSize(metrics.horizontalAdvance(button->text()), metrics.lineSpacing())); } const int inset = 2 * (UiConfig::ClassicKeypadButtonMargin + UiConfig::ClassicKeypadButtonPadding); const int height = textSize.height() + inset; // Keep short labels rectangular too, using the old keypad's proportions. return QSize(qMax(textSize.width() + inset + 6, height * 162 / 100), height); } } // namespace Keypad::Keypad(LayoutMode layoutMode, QWidget* parent, int scalePercent) : QWidget(parent) , m_layoutMode(layoutMode) , m_isCustom(false) , m_scalePercent(scalePercent) { createButtons(); sizeButtons(); layoutButtons(); setButtonTooltips(); disableButtonFocus(); setLayoutDirection(Qt::LeftToRight); } Keypad::Keypad(const QList& customButtons, QWidget* parent, int scalePercent) : QWidget(parent) , m_layoutMode(LayoutModeScientificWide) , m_isCustom(true) , m_scalePercent(scalePercent) , m_customButtons(customButtons) { createCustomButtons(); sizeCustomButtons(); layoutCustomButtons(); disableButtonFocus(); setLayoutDirection(Qt::LeftToRight); } void Keypad::setAppearance(Appearance appearance) { if (m_appearance == appearance) return; m_appearance = appearance; updateButtonStyleSheets(); const int margin = appearance == Classic ? UiConfig::ClassicKeypadButtonMargin : UiConfig::KeypadButtonMargin; layout()->setContentsMargins(margin, margin, margin, margin); if (m_isCustom) sizeCustomButtons(); else sizeButtons(); updateGeometry(); } QList Keypad::presetCustomButtons(LayoutMode layoutMode, QChar radixCharacter, int* rows, int* columns) { QList buttons; const LayoutEntry* entries = nullptr; int count = 0; layoutEntries(layoutMode, &entries, &count); if (!entries || count <= 0) { if (rows) *rows = 1; if (columns) *columns = 1; return buttons; } int maxRow = 0; int maxColumn = 0; for (int i = 0; i < count; ++i) { maxRow = qMax(maxRow, entries[i].row); maxColumn = qMax(maxColumn, entries[i].column); const QString label = customButtonLabel(entries[i].button, radixCharacter); if (label.isEmpty()) continue; CustomButtonDescription button; button.row = entries[i].row; button.column = entries[i].column; button.label = label; button.action = customButtonAction(entries[i].button); button.text = (button.action == Settings::CustomKeypadActionInsertText) ? customButtonInsertText(entries[i].button, radixCharacter) : QString(); buttons.append(button); } if (rows) *rows = maxRow + 1; if (columns) *columns = maxColumn + 1; return buttons; } void Keypad::handleRadixCharacterChange() { if (m_isCustom) return; key(KeyRadixChar)->setText(QString(QChar(Settings::instance()->radixCharacter()))); } void Keypad::retranslateText() { if (m_isCustom) return; setButtonTooltips(); handleRadixCharacterChange(); } QPushButton* Keypad::key(Button button) const { Q_ASSERT(keys.contains(button)); return keys.value(button).first; } void Keypad::createButtons() { keys.clear(); QFont boldFont; boldFont.setBold(true); QFont emphasizedBoldFont = boldFont; emphasizedBoldFont.setPointSize(emphasizedBoldFont.pointSize() + 3); boldFont = scaledFont(boldFont, m_scalePercent); emphasizedBoldFont = scaledFont(emphasizedBoldFont, m_scalePercent); static const int keyDescriptionsCount = int(sizeof keyDescriptions / sizeof keyDescriptions[0]); for (int i = 0; i < keyDescriptionsCount; ++i) { const KeyDescription* description = keyDescriptions + i; QPushButton* key = new QPushButton(description->label, this); key->setCursor(Qt::PointingHandCursor); key->setMouseTracking(true); key->setAttribute(Qt::WA_Hover, true); key->setStyleSheet(keypadButtonStyleSheet(palette())); key->setFont(description->boldFont ? emphasizedBoldFont : boldFont); key->installEventFilter(this); const QPair hashValue(key, description); keys.insert(description->button, hashValue); QObject::connect(key, &QPushButton::clicked, this, [this, description]() { emit buttonPressed(description->button); }); } handleRadixCharacterChange(); } void Keypad::disableButtonFocus() { QHashIterator > i(keys); while (i.hasNext()) { i.next(); i.value().first->setFocusPolicy(Qt::NoFocus); } for (auto* button : m_customWidgets) button->setFocusPolicy(Qt::NoFocus); } void Keypad::layoutButtons() { if (m_isCustom) return; int layoutSpacing = 0; #if QT_VERSION >= 0x040400 && defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) // Workaround for a layouting bug in QMacStyle, Qt 4.4.0. Buttons would overlap. if (qobject_cast(p->style())) layoutSpacing = -1; #endif QGridLayout* layout = new QGridLayout(this); layout->setContentsMargins(UiConfig::KeypadButtonMargin, UiConfig::KeypadButtonMargin, UiConfig::KeypadButtonMargin, UiConfig::KeypadButtonMargin); layout->setSpacing(layoutSpacing); // Hide everything first; only buttons added to the active layout are shown. QHashIterator > hideIter(keys); while (hideIter.hasNext()) { hideIter.next(); hideIter.value().first->hide(); } const QHash positions = createLayoutMap(m_layoutMode); QHashIterator > i(keys); while (i.hasNext()) { i.next(); if (!positions.contains(i.key())) continue; QWidget* widget = i.value().first; const QPoint pos = positions.value(i.key()); layout->addWidget(widget, pos.y(), pos.x()); widget->show(); } } void Keypad::createCustomButtons() { QFont boldFont; boldFont.setBold(true); boldFont = scaledFont(boldFont, m_scalePercent); for (const auto& description : m_customButtons) { QPushButton* key = new QPushButton(description.label, this); key->setCursor(Qt::PointingHandCursor); key->setFont(boldFont); key->setStyleSheet(keypadButtonStyleSheet(palette())); QObject::connect(key, &QPushButton::clicked, this, [this, description]() { emit customButtonPressed(description.action, description.text); }); m_customWidgets.append(key); } } void Keypad::layoutCustomButtons() { if (!m_isCustom) return; int layoutSpacing = 0; QGridLayout* layout = new QGridLayout(this); layout->setContentsMargins(UiConfig::KeypadButtonMargin, UiConfig::KeypadButtonMargin, UiConfig::KeypadButtonMargin, UiConfig::KeypadButtonMargin); layout->setSpacing(layoutSpacing); const int count = qMin(m_customButtons.size(), m_customWidgets.size()); for (int i = 0; i < count; ++i) layout->addWidget(m_customWidgets.at(i), m_customButtons.at(i).row, m_customButtons.at(i).column); } void Keypad::updateButtonStyleSheets() { const bool hasThemeButtonColors = m_buttonBackground.isValid(); const KeypadButtonColors normalColors { m_buttonBackground, m_buttonForeground, m_buttonHoverBackground, m_buttonHoverForeground, m_buttonPressedBackground, m_buttonPressedForeground }; const bool classic = m_appearance == Classic; const QString fallbackStyleSheet = keypadButtonStyleSheet(palette(), classic); QHashIterator > i(keys); while (i.hasNext()) { i.next(); QPushButton* button = i.value().first; if (hasThemeButtonColors) { const KeypadButtonColors colors = keypadButtonColorsForRole( normalColors, m_primaryBackground, visualRoleForButton(i.key())); applyKeypadButtonStyle(button, palette(), colors, classic); } else { button->setStyleSheet(fallbackStyleSheet); } } for (int index = 0; index < m_customWidgets.size(); ++index) { QPushButton* button = m_customWidgets.at(index); if (hasThemeButtonColors) { const KeypadButtonVisualRole role = index < m_customButtons.size() ? visualRoleForCustomButton(m_customButtons.at(index)) : KeypadButtonVisualRole::Normal; const KeypadButtonColors colors = keypadButtonColorsForRole( normalColors, m_primaryBackground, role); applyKeypadButtonStyle(button, palette(), colors, classic); } else { button->setStyleSheet(fallbackStyleSheet); } } } void Keypad::setThemeButtonColors(const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& pressedBackground, const QColor& pressedForeground, const QColor& primaryBackground) { m_buttonBackground = background; m_buttonForeground = foreground; m_buttonHoverBackground = hoverBackground; m_buttonHoverForeground = hoverForeground; m_buttonPressedBackground = pressedBackground; m_buttonPressedForeground = pressedForeground; m_primaryBackground = primaryBackground; updateButtonStyleSheets(); // Runtime theme changes can still have queued Qt palette/style polish work // from parent widgets after this call returns. Reapply once at the end of // the event turn so keyed buttons keep their role-specific fills instead // of being flattened back to the inherited QPushButton palette. QTimer::singleShot(0, this, [this]() { updateButtonStyleSheets(); }); } void Keypad::setToolTipThemeColors(const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius) { m_summaryPopupBackgroundColor = background; m_summaryPopupForegroundColor = foreground; m_summaryPopupOutlineColor = outline; m_summaryPopupCornerRadius = qMax(0, cornerRadius); applySummaryPopupTheme(); } void Keypad::setButtonTooltip(Button button, const QString& text) { QPushButton* buttonWidget = key(button); m_buttonToolTipTexts.insert(buttonWidget, text); buttonWidget->setToolTip(QString()); } void Keypad::setButtonTooltips() { if (m_isCustom) return; setButtonTooltip(KeyAcos, Keypad::tr("Inverse cosine")); setButtonTooltip(KeyAns, Keypad::tr("The last result")); setButtonTooltip(KeyAsin, Keypad::tr("Inverse sine")); setButtonTooltip(KeyAtan, Keypad::tr("Inverse tangent")); setButtonTooltip(KeyEquals, Keypad::tr("Evaluate expression")); setButtonTooltip(KeyDivide, Keypad::tr("Division")); setButtonTooltip(KeyTimes, Keypad::tr("Multiplication")); setButtonTooltip(KeyMinus, Keypad::tr("Subtraction")); setButtonTooltip(KeyPlus, Keypad::tr("Addition")); setButtonTooltip(KeyClear, Keypad::tr("Clear expression")); setButtonTooltip(KeyCos, Keypad::tr("Cosine")); setButtonTooltip(KeyBackspace, Keypad::tr("Backspace")); setButtonTooltip(KeyEE, Keypad::tr("Scientific notation")); setButtonTooltip(KeyExp, Keypad::tr("Exponential")); setButtonTooltip(KeyFactorial, Keypad::tr("Factorial")); setButtonTooltip(KeyLn, Keypad::tr("Natural logarithm")); setButtonTooltip(KeyLeftPar, Keypad::tr("Left parenthesis")); setButtonTooltip(KeyRoot, Keypad::tr("Nth root")); setButtonTooltip(KeyLog10, Keypad::tr("Common logarithm")); setButtonTooltip(KeyMod, Keypad::tr("Modulo")); setButtonTooltip(KeyPercent, Keypad::tr("Contextual percentage")); setButtonTooltip(KeyRaise, Keypad::tr("Power")); setButtonTooltip(KeyRightPar, Keypad::tr("Right parenthesis")); setButtonTooltip(KeySin, Keypad::tr("Sine")); setButtonTooltip(KeySqrt, Keypad::tr("Square root")); setButtonTooltip(KeyTan, Keypad::tr("Tangent")); setButtonTooltip(KeyPi, Keypad::tr("Pi")); setButtonTooltip(KeyRadixChar, Keypad::tr("Decimal separator")); setButtonTooltip(KeyArgumentSeparator, Keypad::tr("Argument separator")); setButtonTooltip(KeySquare, Keypad::tr("Square")); } bool Keypad::eventFilter(QObject* watched, QEvent* event) { const QString summaryText = tooltipTextForObject(watched); if (!summaryText.isEmpty()) { QWidget* button = qobject_cast(watched); switch (event->type()) { case QEvent::Enter: if (button != nullptr) showSummaryPopup(summaryText, button, button->mapToGlobal(button->rect().center())); break; case QEvent::MouseMove: { QMouseEvent* mouseEvent = static_cast(event); showSummaryPopup(summaryText, button, mouseEvent->globalPosition().toPoint()); break; } case QEvent::HoverMove: { QHoverEvent* hoverEvent = static_cast(event); if (button != nullptr) showSummaryPopup(summaryText, button, button->mapToGlobal(hoverEvent->position().toPoint())); break; } case QEvent::ToolTip: { QHelpEvent* helpEvent = static_cast(event); showSummaryPopup(summaryText, button, helpEvent->globalPos()); return true; } case QEvent::Hide: case QEvent::KeyPress: case QEvent::Leave: case QEvent::MouseButtonPress: case QEvent::Wheel: hideSummaryPopup(); break; default: break; } } return QWidget::eventFilter(watched, event); } QString Keypad::tooltipTextForObject(const QObject* watched) const { QPushButton* button = qobject_cast(const_cast(watched)); if (button == nullptr) return QString(); return m_buttonToolTipTexts.value(button); } void Keypad::applySummaryPopupTheme() { ToolTipStyleUtils::applyPopupTheme( m_summaryPopup, m_summaryPopupLabel, this, {m_summaryPopupBackgroundColor, m_summaryPopupForegroundColor, m_summaryPopupOutlineColor, m_summaryPopupCornerRadius}); } void Keypad::ensureSummaryPopup() { if (m_summaryPopup != nullptr) return; m_summaryPopup = ToolTipStyleUtils::createPopup(this, QStringLiteral("keypadSummaryPopup"), QStringLiteral("keypadSummaryPopupLabel"), Qt::PlainText, &m_summaryPopupLabel); applySummaryPopupTheme(); } void Keypad::hideSummaryPopup() { if (m_summaryPopup != nullptr) m_summaryPopup->hide(); } void Keypad::showSummaryPopup(const QString& text, QWidget* anchor, const QPoint& globalPos) { if (text.isEmpty() || anchor == nullptr) return; ensureSummaryPopup(); ToolTipStyleUtils::showPopup(m_summaryPopup, m_summaryPopupLabel, text, anchor, globalPos, m_summaryPopupCornerRadius); } void Keypad::updateSummaryPopupMask() { if (m_summaryPopup == nullptr) return; ToolTipStyleUtils::applyRoundedPopupMask(m_summaryPopup, qMax(0, m_summaryPopupCornerRadius)); } void Keypad::sizeButtons() { if (m_isCustom) return; if (m_appearance == Classic) { QList buttons; const auto positions = createLayoutMap(m_layoutMode); for (auto i = keys.cbegin(); i != keys.cend(); ++i) { if (positions.contains(i.key())) buttons.append(i.value().first); } const QSize size = compactButtonSize(buttons); for (QPushButton* button : buttons) button->setFixedSize(size); return; } // Resolve the stylesheet font before measuring. Otherwise an initial keypad // and one rebuilt under an already polished window can use different metrics. key(Key0)->ensurePolished(); key(KeyAcos)->ensurePolished(); // The same font in all buttons, so just pick one. QFontMetrics fm = key(Key0)->fontMetrics(); int maxWidth = fm.horizontalAdvance(key(KeyAcos)->text()); const int textHeight = qMax(fm.lineSpacing(), 14); QStyle::ContentsType type = QStyle::CT_ToolButton; QStyleOptionButton option; const QWidget* exampleWidget = key(KeyAcos); option.initFrom(exampleWidget); QSize minSize = QSize(maxWidth, textHeight); QSize size = exampleWidget->style()->sizeFromContents(type, &option, minSize, exampleWidget); #ifdef Q_WS_X11 // We would like to use the button size as indicated by the widget style, but in some cases, // e.g. KDE's Plastik or Oxygen, another few pixels (typically 5) are added as the content // margin, thereby making the button incredibly wider than necessary. Workaround: take only // the hinted height, adjust the width ourselves (with our own margin). maxWidth += 6; int hh = size.height(); size = QSize(qMax(hh, maxWidth), hh); #endif const int side = qMax(size.width(), size.height()); size = QSize(side, side); // limit the size of the buttons QHashIterator > i(keys); while (i.hasNext()) { i.next(); i.value().first->setFixedSize(size); } } void Keypad::sizeCustomButtons() { if (!m_isCustom || m_customWidgets.isEmpty()) return; if (m_appearance == Classic) { const QSize size = compactButtonSize(m_customWidgets); for (QPushButton* button : m_customWidgets) button->setFixedSize(size); return; } m_customWidgets.first()->ensurePolished(); // Match preset keypad sizing baseline exactly (bold, larger numeric key font). QFont boldFont = m_customWidgets.first()->font(); boldFont.setBold(true); boldFont.setPointSize(boldFont.pointSize() + 3); boldFont = scaledFont(boldFont, m_scalePercent); const QFontMetrics fm(boldFont); const int maxWidth = fm.horizontalAdvance(QStringLiteral("arccos")); const int textHeight = qMax(fm.lineSpacing(), 14); QStyle::ContentsType type = QStyle::CT_ToolButton; QStyleOptionButton option; const QWidget* exampleWidget = m_customWidgets.first(); option.initFrom(exampleWidget); QSize minSize = QSize(maxWidth, textHeight); QSize size = exampleWidget->style()->sizeFromContents(type, &option, minSize, exampleWidget); #ifdef Q_WS_X11 maxWidth += 6; int hh = size.height(); size = QSize(qMax(hh, maxWidth), hh); #endif const int side = qMax(size.width(), size.height()); size = QSize(side, side); for (auto* button : m_customWidgets) button->setFixedSize(size); } void Keypad::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) retranslateText(); const bool paletteChanged = event->type() == QEvent::PaletteChange || event->type() == QEvent::ApplicationPaletteChange; QWidget::changeEvent(event); if (paletteChanged) updateButtonStyleSheets(); } heldercorreia-speedcrunch-e7ca37f/src/gui/keypad.h000066400000000000000000000104641526573132500223430ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_KEYPAD_H #define GUI_KEYPAD_H #include #include #include #include class QPushButton; class QFrame; class QLabel; class Keypad : public QWidget { Q_OBJECT public: enum Appearance { Modern, Classic }; enum LayoutMode { LayoutModeScientificWide = 0, LayoutModeBasicWide = 1, LayoutModeScientificNarrow = 2 }; enum Button { Key0, Key1, Key2, Key3, Key4, Key5, Key6, Key7, Key8, Key9, KeyEquals, KeyPlus, KeyMinus, KeyTimes, KeyDivide, KeyRadixChar, KeyClear, KeyEE, KeyLeftPar, KeyRightPar, KeyRaise, KeySqrt, KeyRoot, KeyLog10, KeyMod, KeyBackspace, KeyPercent, KeyFactorial, KeyPi, KeyAns, KeySquare, KeyArgumentSeparator, KeyExp, KeyLn, KeySin, KeyAsin, KeyCos, KeyAcos, KeyTan, KeyAtan }; struct CustomButtonDescription { QString label; QString text; int action; int row; int column; }; static QList presetCustomButtons(LayoutMode layoutMode, QChar radixCharacter, int* rows = nullptr, int* columns = nullptr); explicit Keypad(LayoutMode layoutMode = LayoutModeScientificWide, QWidget* parent = 0, int scalePercent = 100); explicit Keypad(const QList& customButtons, QWidget* parent = 0, int scalePercent = 100); void setAppearance(Appearance appearance); void setThemeButtonColors(const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground, const QColor& pressedBackground, const QColor& pressedForeground, const QColor& primaryBackground); void setToolTipThemeColors(const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius); signals: void buttonPressed(Keypad::Button) const; void customButtonPressed(int action, const QString& text) const; public slots: void handleRadixCharacterChange(); void retranslateText(); protected: bool eventFilter(QObject* watched, QEvent* event) override; void changeEvent(QEvent*) override; private: Q_DISABLE_COPY(Keypad) void applySummaryPopupTheme(); void ensureSummaryPopup(); void hideSummaryPopup(); QPushButton* key(Button button) const; void createButtons(); void disableButtonFocus(); void layoutButtons(); void createCustomButtons(); void layoutCustomButtons(); void updateButtonStyleSheets(); void setButtonTooltip(Button button, const QString& text); void setButtonTooltips(); void showSummaryPopup(const QString& text, QWidget* anchor, const QPoint& globalPos); void sizeButtons(); void sizeCustomButtons(); QString tooltipTextForObject(const QObject* watched) const; void updateSummaryPopupMask(); static const struct KeyDescription { QString label; Button button; bool boldFont; int gridRow; int gridColumn; } keyDescriptions[]; LayoutMode m_layoutMode; bool m_isCustom; int m_scalePercent; Appearance m_appearance = Modern; QColor m_buttonBackground; QColor m_buttonForeground; QColor m_buttonHoverBackground; QColor m_buttonHoverForeground; QColor m_buttonPressedBackground; QColor m_buttonPressedForeground; QColor m_primaryBackground; QColor m_summaryPopupBackgroundColor; QColor m_summaryPopupForegroundColor; QColor m_summaryPopupOutlineColor; int m_summaryPopupCornerRadius = 0; QFrame* m_summaryPopup = nullptr; QLabel* m_summaryPopupLabel = nullptr; QHash > keys; QHash m_buttonToolTipTexts; QList m_customButtons; QList m_customWidgets; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/lineeditstyleutils.h000066400000000000000000000032511526573132500250210ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_LINEEDITSTYLEUTILS_H #define GUI_LINEEDITSTYLEUTILS_H #include #include #include #include #include namespace LineEditStyleUtils { inline void applyClearButtonColors(QLineEdit* searchBox, const QColor& fill, const QColor& cross) { if (searchBox == nullptr) return; const auto pixmapForScale = [&fill, &cross](qreal scale) { constexpr int logicalSize = 16; QPixmap pixmap(qRound(logicalSize * scale), qRound(logicalSize * scale)); pixmap.setDevicePixelRatio(scale); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(Qt::NoPen); painter.setBrush(fill); painter.drawEllipse(QRectF(1.5, 1.5, 13.0, 13.0)); painter.setPen(QPen(cross, 1.45, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter.drawLine(QPointF(5.25, 5.25), QPointF(10.75, 10.75)); painter.drawLine(QPointF(10.75, 5.25), QPointF(5.25, 10.75)); return pixmap; }; QIcon icon; icon.addPixmap(pixmapForScale(1.0)); icon.addPixmap(pixmapForScale(2.0)); icon.addPixmap(pixmapForScale(3.0)); for (QAction* action : searchBox->actions()) action->setIcon(icon); for (QToolButton* button : searchBox->findChildren()) { if (QAction* action = button->defaultAction()) action->setIcon(icon); button->setIcon(icon); button->setIconSize(QSize(16, 16)); } } } // namespace LineEditStyleUtils #endif heldercorreia-speedcrunch-e7ca37f/src/gui/mainwindow.cpp000066400000000000000000024026231526573132500236010ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2020, 2022, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/mainwindow.h" #include "gui/diagnosticsdialog.h" #include "core/startupdiagnostics.h" #include "gui/startupappearance.h" #include "gui/menustyleutils.h" #include "core/complexform.h" #include "core/constants.h" #include "core/evaluator.h" #include "core/functions.h" #include "core/numberformatter.h" #include "core/regexpatterns.h" #include "core/settings.h" #include "core/session.h" #include "core/sessionjsonkeys.h" #include "core/userdefinitions.h" #include "core/unicodechars.h" #include "core/variable.h" #include "core/sessionhistory.h" #include "core/userfunction.h" #include "gui/aboutbox.h" #include "gui/bitfieldwidget.h" #include "gui/bookdock.h" #include "gui/genericdock.h" #include "gui/constantswidget.h" #include "gui/customkeypaddialog.h" #include "gui/dockcomboboxchevron.h" #include "gui/editorutils.h" #include "gui/functionswidget.h" #include "gui/historywidget.h" #include "gui/userfunctionlistwidget.h" #include "gui/userunitlistwidget.h" #include "gui/variablelistwidget.h" #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS #include "gui/versioncheck.h" #endif #include "gui/editor.h" #include "gui/historywidget.h" #include "gui/manualwindow.h" #include "gui/numberformatdialog.h" #include "gui/notationandprecisiondialog.h" #include "gui/oklchutils.h" #include "gui/splittertreeutils.h" #include "core/manualserver.h" #include "gui/resultdisplay.h" #include "gui/resultlineformatutils.h" #include "gui/syntaxhighlighter.h" #include "gui/themedlineedit.h" #include "gui/lineeditstyleutils.h" #include "gui/tooltipstyleutils.h" #include "gui/uiconfig.h" #include "math/cmath.h" #include "math/floatnum/floatconfig.h" #include "core/mathdsl.h" #include "core/units.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN32 #include "windows.h" #include #endif // Q_OS_WIN32 namespace { constexpr const char* kFeedbackUrl = "https://www.speedcrunch.org/issues.html"; constexpr const char* kCommunityUrl = "https://speedcrunch.org/community.html"; constexpr const char* kSourceUrl = "https://www.speedcrunch.org/source.html"; constexpr const char* kDonateUrl = "https://www.speedcrunch.org/donate.html"; QString sessionsPath() { return QDir(Settings::getDataPath()).filePath(QStringLiteral("sessions")); } bool ensureSessionsPath() { QDir dir; return dir.mkpath(sessionsPath()); } bool directoryIsEmpty(const QString& path) { const QDir dir(path); return !dir.exists() || dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty(); } QString normalizedSessionName(QString name) { name = name.trimmed(); return name.isEmpty() ? QLatin1String(SessionJsonKeys::SessionValueMain) : name; } bool hasCurrentSessionSchema(const QByteArray& data) { const QJsonDocument doc = QJsonDocument::fromJson(data); if (!doc.isObject()) return false; const QJsonObject object = doc.object(); if (object.contains(QLatin1String("scheme"))) return false; const QJsonValue schema = object.value(QLatin1String(SessionJsonKeys::Schema)); const QJsonValue id = object.value(QLatin1String(SessionJsonKeys::Id)); return schema.isString() && schema.toString() == QLatin1String(SessionJsonKeys::SchemaDialect) && id.isString() && id.toString() == QLatin1String(SessionJsonKeys::SchemaId); } bool readValidSessionJson(const QString& filePath, QJsonObject* json) { QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) return false; const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); if (!doc.isObject()) return false; const QJsonObject object = doc.object(); if (object.contains(QLatin1String("scheme"))) return false; const QJsonValue schema = object.value(QLatin1String(SessionJsonKeys::Schema)); if (!schema.isString() || schema.toString() != QLatin1String(SessionJsonKeys::SchemaDialect)) return false; const QJsonValue id = object.value(QLatin1String(SessionJsonKeys::Id)); if (!id.isString() || id.toString() != QLatin1String(SessionJsonKeys::SchemaId)) return false; const QString name = object.value(QLatin1String(SessionJsonKeys::Session)).toString().trimmed(); if (name.isEmpty()) return false; if (json != nullptr) *json = object; return true; } QString sessionFilePath(const QString& sessionName); QString firstAvailableUntitledSessionName(const QHash& sessions); void migrateLegacyHistoryIfNeeded() { const QDir dataDir(Settings::getDataPath()); const QString legacyPath = dataDir.filePath(QStringLiteral("history.json")); QFile legacyFile(legacyPath); if (!legacyFile.exists()) return; const QString sessionDirPath = sessionsPath(); const QFileInfo sessionDirInfo(sessionDirPath); const bool shouldMigrate = !sessionDirInfo.exists() || (sessionDirInfo.isDir() && directoryIsEmpty(sessionDirPath)); if (!shouldMigrate) return; if (!legacyFile.open(QIODevice::ReadOnly)) return; const QByteArray data = legacyFile.readAll(); legacyFile.close(); if (!hasCurrentSessionSchema(data)) return; if (!ensureSessionsPath()) return; QJsonObject sessionJson = QJsonDocument::fromJson(data).object(); const QHash loadedSessions; const QString sessionName = firstAvailableUntitledSessionName(loadedSessions); sessionJson[QLatin1String(SessionJsonKeys::Session)] = sessionName; const QByteArray migratedData = QJsonDocument(sessionJson).toJson(QJsonDocument::Compact); QFile migratedSession(sessionFilePath(sessionName)); if (!migratedSession.open(QIODevice::WriteOnly)) return; if (migratedSession.write(migratedData) != migratedData.size()) return; migratedSession.close(); legacyFile.remove(); } QString sessionFileBaseName(QString sessionName) { sessionName = normalizedSessionName(sessionName); QString safeName; safeName.reserve(sessionName.size()); for (const QChar ch : sessionName) { if (ch.isLetterOrNumber() || ch == QLatin1Char('-') || ch == QLatin1Char('_') || ch == QLatin1Char(' ')) safeName.append(ch); else safeName.append(QLatin1Char('_')); } const QString trimmedSafeName = safeName.trimmed(); return trimmedSafeName.isEmpty() ? QLatin1String(SessionJsonKeys::SessionValueMain) : trimmedSafeName; } QString sessionFilePath(const QString& sessionName) { ensureSessionsPath(); return QDir(sessionsPath()).filePath(sessionFileBaseName(sessionName) + QLatin1String(".json")); } QMutex& asyncSessionIoMutex() { static QMutex mutex; return mutex; } QHash& asyncSessionSaveGenerations() { static QHash generations; return generations; } QList& asyncSessionIoThreads() { static QList threads; return threads; } struct SessionLoadSpec { QString name; QString filePath; QJsonObject tab; }; bool g_restoringExtraWindows = false; bool g_multiWindowSpawnDone = false; constexpr int DockLayoutStateVersion = 1; QStringList allDockNames() { return {QStringLiteral("BookDock"), QStringLiteral("ConstantsDock"), QStringLiteral("FunctionsDock"), QStringLiteral("HistoryDock"), QStringLiteral("VariablesDock"), QStringLiteral("UserFunctionsDock"), QStringLiteral("UserUnitsDock"), QStringLiteral("BitfieldDock")}; } QStringList legacyOpenDockNames(const QByteArray& state, bool* valid) { StartupDiagnostics::Scope timing("Read legacy dock layout visibility"); // Let Qt read its own layout format using empty docks, without building // formula pages, lists, search controls, or other application dock contents. QMainWindow probe; probe.setAttribute(Qt::WA_DontShowOnScreen); QList docks; for (const QString& name : allDockNames()) { auto* dock = new QDockWidget(&probe); dock->setObjectName(name); dock->setAttribute(Qt::WA_DontShowOnScreen); probe.addDockWidget(Qt::RightDockWidgetArea, dock); dock->hide(); docks.append(dock); } *valid = probe.restoreState(state, DockLayoutStateVersion); QStringList names; if (*valid) { for (QDockWidget* dock : docks) { if (!dock->isHidden()) names.append(dock->objectName()); } } return names; } bool asyncSessionSaveIsCurrent(const QString& filePath, quint64 generation) { QMutexLocker locker(&asyncSessionIoMutex()); return asyncSessionSaveGenerations().value(filePath) == generation; } void unregisterAsyncSessionIoThread(QThread* thread) { QMutexLocker locker(&asyncSessionIoMutex()); asyncSessionIoThreads().removeAll(thread); } bool writeSessionJsonToFile(const QJsonObject& json, const QString& filePath, quint64 generation = 0) { const QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact); if (generation != 0 && !asyncSessionSaveIsCurrent(filePath, generation)) return false; QSaveFile file(filePath); if (!file.open(QIODevice::WriteOnly)) return false; if (file.write(data) != data.size()) return false; return file.commit(); } void saveSessionAsync(const Session& session, const QString& filePath) { if (session.isPrivate()) return; ensureSessionsPath(); QJsonObject json; session.serialize(json); quint64 generation = 0; { QMutexLocker locker(&asyncSessionIoMutex()); generation = asyncSessionSaveGenerations().value(filePath) + 1; asyncSessionSaveGenerations().insert(filePath, generation); } QThread* thread = QThread::create([json, filePath, generation]() { if (!asyncSessionSaveIsCurrent(filePath, generation)) return; writeSessionJsonToFile(json, filePath, generation); }); { QMutexLocker locker(&asyncSessionIoMutex()); asyncSessionIoThreads().append(thread); } QObject::connect(thread, &QThread::finished, thread, [thread]() { unregisterAsyncSessionIoThread(thread); thread->deleteLater(); }); thread->start(); } void waitForAsyncSessionIo() { while (true) { QList threads; { QMutexLocker locker(&asyncSessionIoMutex()); threads = asyncSessionIoThreads(); } if (threads.isEmpty()) return; for (QThread* thread : threads) { if (thread != nullptr) { thread->wait(); unregisterAsyncSessionIoThread(thread); } } } } bool loadedSessionNameExists(const QHash& sessions, const QString& name) { for (const QString& existingName : sessions.keys()) { if (existingName.compare(name, Qt::CaseInsensitive) == 0) return true; } return false; } QString firstAvailableUntitledSessionName(const QHash& sessions) { for (int number = 1; number < (std::numeric_limits::max)(); ++number) { const QString name = QStringLiteral("Untitled-%1").arg(number); if (!loadedSessionNameExists(sessions, name) && !QFileInfo::exists(sessionFilePath(name))) return name; } return QStringLiteral("Untitled"); } QIcon privateSessionIcon(const QColor& color) { QPixmap pixmap(32, 32); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(QPen(color, 2.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter.setBrush(Qt::NoBrush); QPainterPath shield; shield.moveTo(16, 3); shield.lineTo(27, 7); shield.lineTo(26, 17); shield.cubicTo(25, 23, 20, 27, 16, 29); shield.cubicTo(12, 27, 7, 23, 6, 17); shield.lineTo(5, 7); shield.closeSubpath(); painter.drawPath(shield); return QIcon(pixmap); } QJsonObject persistentSessionLayout(QJsonObject node, const QSet& privateNames) { if (node.contains(QStringLiteral("tabs"))) { QJsonArray tabs; for (const QJsonValue& value : node.value(QStringLiteral("tabs")).toArray()) { const QString name = value.toObject().value(QStringLiteral("name")).toString(); if (!privateNames.contains(name)) tabs.append(value); } node.insert(QStringLiteral("tabs"), tabs); if (privateNames.contains(node.value(QStringLiteral("active")).toString())) node.insert(QStringLiteral("active"), tabs.isEmpty() ? QString() : tabs.first().toObject().value(QStringLiteral("name")).toString()); if (tabs.isEmpty()) return QJsonObject(); } if (node.contains(QStringLiteral("children"))) { QJsonArray children; QJsonArray sizes; const QJsonArray oldChildren = node.value(QStringLiteral("children")).toArray(); const QJsonArray oldSizes = node.value(QStringLiteral("sizes")).toArray(); for (int i = 0; i < oldChildren.size(); ++i) { const QJsonObject child = persistentSessionLayout(oldChildren.at(i).toObject(), privateNames); if (!child.isEmpty()) { children.append(child); sizes.append(i < oldSizes.size() ? oldSizes.at(i) : QJsonValue(1)); } } if (children.isEmpty()) return QJsonObject(); node.insert(QStringLiteral("children"), children); node.insert(QStringLiteral("sizes"), sizes); } return node; } QString firstAvailableImportedSessionName(const QString& preferredName, const QHash& sessions) { const QString baseName = normalizedSessionName(preferredName); const auto isAvailable = [&sessions](const QString& name) { return !loadedSessionNameExists(sessions, name) && !QFileInfo::exists(sessionFilePath(name)); }; if (isAvailable(baseName)) return baseName; for (int number = 2; number < (std::numeric_limits::max)(); ++number) { const QString candidate = QStringLiteral("%1 (%2)").arg(baseName).arg(number); if (isAvailable(candidate)) return candidate; } return firstAvailableUntitledSessionName(sessions); } int untitledSessionNumber(const QString& name) { static const QString prefix = QStringLiteral("Untitled-"); if (!name.startsWith(prefix, Qt::CaseInsensitive)) return -1; bool ok = false; const int number = name.mid(prefix.size()).toInt(&ok); return ok && number > 0 ? number : -1; } bool isReusableUntitledSession(const Session* session) { if (session == nullptr || session->isPrivate() || !session->historyIsEmpty()) return false; const Evaluator* evaluator = session->evaluator(); const QList variables = session->variablesToList(); for (const Variable& variable : variables) { if (variable.type() != Variable::BuiltIn && !(evaluator && evaluator->isGlobalUserVariable(variable.identifier()))) return false; } const QList functions = session->UserFunctionsToList(); for (const UserFunction& function : functions) { if (!(evaluator && evaluator->isGlobalUserFunction(function.name()))) return false; } const QList units = session->userUnitsToList(); for (const UserUnit& unit : units) { if (!(evaluator && evaluator->isGlobalUserUnit(unit.name()))) return false; } return true; } bool sessionHasPersistableContent(const Session* session) { if (session == nullptr) return false; if (!session->historyIsEmpty()) return true; const Evaluator* evaluator = session->evaluator(); const QList variables = session->variablesToList(); for (const Variable& variable : variables) { if (variable.type() != Variable::BuiltIn && !(evaluator && evaluator->isGlobalUserVariable(variable.identifier()))) { return true; } } const QList functions = session->UserFunctionsToList(); for (const UserFunction& function : functions) { if (!(evaluator && evaluator->isGlobalUserFunction(function.name()))) return true; } const QList units = session->userUnitsToList(); for (const UserUnit& unit : units) { if (!(evaluator && evaluator->isGlobalUserUnit(unit.name()))) return true; } return false; } bool shouldDeleteSessionFileOnClose(const QString& sessionName, const Session* session) { return untitledSessionNumber(sessionName) > 0 && isReusableUntitledSession(session); } QJsonObject editorState(Editor* editor) { QJsonObject state; if (editor == nullptr) return state; state.insert(QStringLiteral("text"), editor->text()); state.insert(QStringLiteral("cursor"), editor->cursorPosition()); return state; } void restoreEditorState(Editor* editor, const QJsonObject& state, const QString& fallbackText) { if (editor == nullptr) return; const QString text = state.value(QStringLiteral("text")).toString(fallbackText); const int cursor = state.contains(QStringLiteral("cursor")) ? state.value(QStringLiteral("cursor")).toInt(text.size()) : text.size(); { const QSignalBlocker blocker(editor); editor->setText(text); editor->setCursorPosition(qBound(0, cursor, text.size())); } if (!text.trimmed().isEmpty()) editor->refreshAutoCalc(); } QJsonObject sessionLayoutEntry(const QString& name, const QPair& viewportAnchor, int scrollValue, const QJsonObject& editor, bool includeEditor) { QJsonObject entry; entry.insert(QStringLiteral("name"), name); entry.insert(QStringLiteral("file"), QString(sessionFileBaseName(name) + QLatin1String(".json"))); if (viewportAnchor.first >= 0 || scrollValue >= 0) { QJsonObject scroll; if (viewportAnchor.first >= 0) { scroll.insert(QStringLiteral("block"), viewportAnchor.first); scroll.insert(QStringLiteral("offset"), viewportAnchor.second); } if (scrollValue >= 0) scroll.insert(QStringLiteral("value"), scrollValue); entry.insert(QStringLiteral("scroll"), scroll); } if (includeEditor) entry.insert(QStringLiteral("editor"), editor); return entry; } EvaluationContext currentEvaluationContext(const Settings* settings) { EvaluationContext ctx; ctx.main.fmt = settings->resultFormat; ctx.main.prec = settings->resultPrecision; ctx.main.cplx = settings->resultComplexForm; if (settings->multipleResultLinesEnabled) { if (settings->secondaryResultEnabled) ctx.extras.append(ResultLineContext{settings->alternativeResultFormat, settings->secondaryResultPrecision, settings->secondaryResultComplexForm}); if (settings->tertiaryResultEnabled) ctx.extras.append(ResultLineContext{settings->tertiaryResultFormat, settings->tertiaryResultPrecision, settings->tertiaryResultComplexForm}); if (settings->quaternaryResultEnabled) ctx.extras.append(ResultLineContext{settings->quaternaryResultFormat, settings->quaternaryResultPrecision, settings->quaternaryResultComplexForm}); if (settings->quinaryResultEnabled) ctx.extras.append(ResultLineContext{settings->quinaryResultFormat, settings->quinaryResultPrecision, settings->quinaryResultComplexForm}); } ctx.complexOn = settings->complexNumbers; ctx.unit = settings->imaginaryUnit; ctx.angle = settings->angleUnit; ctx.unitExp = settings->unitNegativeExponentStyle; ctx.round = settings->resultRoundingMode; return ctx; } void applyEvaluationContext(Settings* settings, const EvaluationContext& ctx) { settings->resultFormat = ctx.main.fmt; settings->resultPrecision = ctx.main.prec; settings->resultComplexForm = ctx.main.cplx; settings->multipleResultLinesEnabled = !ctx.extras.isEmpty(); settings->secondaryResultEnabled = false; settings->tertiaryResultEnabled = false; settings->quaternaryResultEnabled = false; settings->quinaryResultEnabled = false; auto applyExtra = [settings](int index, const ResultLineContext& line) { if (index == 0) { settings->secondaryResultEnabled = true; settings->alternativeResultFormat = line.fmt; settings->secondaryResultPrecision = line.prec; settings->secondaryResultComplexForm = line.cplx; } else if (index == 1) { settings->tertiaryResultEnabled = true; settings->tertiaryResultFormat = line.fmt; settings->tertiaryResultPrecision = line.prec; settings->tertiaryResultComplexForm = line.cplx; } else if (index == 2) { settings->quaternaryResultEnabled = true; settings->quaternaryResultFormat = line.fmt; settings->quaternaryResultPrecision = line.prec; settings->quaternaryResultComplexForm = line.cplx; } else if (index == 3) { settings->quinaryResultEnabled = true; settings->quinaryResultFormat = line.fmt; settings->quinaryResultPrecision = line.prec; settings->quinaryResultComplexForm = line.cplx; } }; for (int i = 0; i < ctx.extras.size() && i < 4; ++i) applyExtra(i, ctx.extras.at(i)); settings->complexNumbers = ctx.complexOn; settings->imaginaryUnit = (ctx.unit == 'j') ? 'j' : 'i'; settings->angleUnit = ctx.angle; settings->unitNegativeExponentStyle = isValidUnitNegativeExponentStyle(ctx.unitExp) ? ctx.unitExp : Settings::UnitNegativeExponentSuperscript; settings->resultRoundingMode = isValidResultRoundingMode(ctx.round) ? ctx.round : Settings::ResultRoundingHalfAwayFromZero; DMath::complexMode = settings->complexNumbers; CMath::setImaginaryUnitSymbol(settings->imaginaryUnit); setRuntimeUnitNegativeExponentStyle(settings->unitNegativeExponentStyle); setRuntimeResultRoundingMode(settings->resultRoundingMode); } QStringList renderedLinesForHistoryEntry(const HistoryEntry& entry, Settings* settings, const Evaluator* evaluator) { const EvaluationContext previousContext = currentEvaluationContext(settings); applyEvaluationContext(settings, entry.contextRef()); QStringList lines; lines.append(ResultLineFormatUtils::formattedExpressionLineForDisplay( entry.expr(), entry.interpretedExpr(), evaluator)); if (!entry.result().isNan()) { lines.append(ResultLineFormatUtils::formatResultLinesForDisplay( entry.expr(), entry.interpretedExpr(), entry.result(), false, true, evaluator)); } applyEvaluationContext(settings, previousContext); return lines; } } QTranslator* MainWindow::createTranslator(const QString& langCode) { QTranslator* translator = new QTranslator; QLocale locale(langCode == "C" ? QLocale().name() : langCode); if(!translator->load(locale, QString(":/locale/"))) { // There are regional Portuguese translations only for Brazil and Portugal. // Unsupported Portuguese variants (e.g. pt_AO) should fall back to pt_PT. if (locale.language() == QLocale::Portuguese) { const QLocale::Territory territory = locale.territory(); if (territory != QLocale::Brazil && territory != QLocale::Portugal) { if (translator->load(QLocale(QLocale::Portuguese, QLocale::Portugal), QString(":/locale/"))) return translator; } } // Strip the country and try to find a generic translation for this language locale = QLocale(locale.language()); if (!translator->load(locale, QString(":/locale/"))) { // Handle the case where the translation file cannot be loaded // For example, log an error, use a default language, etc. } } return translator; } static bool isVisibleKeypadMode(Settings::KeypadMode mode) { return mode == Settings::KeypadModeBasicWide || mode == Settings::KeypadModeScientificWide || mode == Settings::KeypadModeScientificNarrow || mode == Settings::KeypadModeCustom; } static bool isWaylandPlatform() { const auto platform = QGuiApplication::platformName(); const bool isWayland = (platform == "wayland"); return isWayland; } QString colorSchemeRoleLabel(ColorScheme::Role role) { switch (role) { case ColorScheme::Number: return QStringLiteral("number"); case ColorScheme::Parens: return QStringLiteral("parens"); case ColorScheme::List: return QStringLiteral("list"); case ColorScheme::Unit: return QStringLiteral("unit"); case ColorScheme::Result: return QStringLiteral("result"); case ColorScheme::Comment: return QStringLiteral("comment"); case ColorScheme::Function: return QStringLiteral("function"); case ColorScheme::Operator: return QStringLiteral("operator"); case ColorScheme::Variable: return QStringLiteral("variable"); case ColorScheme::Separator: return QStringLiteral("separator"); case ColorScheme::Background: return QStringLiteral("background"); case ColorScheme::Primary: return QStringLiteral("primary"); } return QString(); } void updateColorButtonStyle(QPushButton* button, const QColor& color) { if (!button || !color.isValid()) return; const QColor textColor = aaForegroundForBackground(color); button->setText(color.name()); button->setMinimumWidth(button->fontMetrics().horizontalAdvance(QStringLiteral("#000000")) + 22); button->setStyleSheet(QStringLiteral(R"( QPushButton { background-color: %1; color: %2; border: 1px solid %2; border-radius: 3px; padding: 2px 8px; } )").arg(color.name(), textColor.name())); } enum class ColorSchemeFilter { Dark, Light }; bool colorSchemeMatchesFilter(const ColorScheme& scheme, ColorSchemeFilter filter) { const QColor background = scheme.colorForRole(ColorScheme::Background); const ThemePolarity polarity = themePolarityForBackground(background); return filter == ColorSchemeFilter::Dark ? polarity == ThemePolarity::Dark : polarity == ThemePolarity::Light; } ColorScheme activeColorScheme(const Settings* settings) { if (settings && settings->colorScheme == QLatin1String("Custom")) { const QJsonDocument doc = QJsonDocument::fromJson(settings->customColorSchemeJson.toUtf8()); const ColorScheme custom(doc); if (custom.isValid()) return custom; } const ColorScheme named = ColorScheme::loadByName(settings ? settings->colorScheme : QString()); if (named.isValid()) return named; return ColorScheme::loadByName(QStringLiteral("Terminal")); } QString colorSchemeDisplayName(const QString& schemeName, const ColorScheme& scheme) { const QString displayName = scheme.displayName(); return displayName.isEmpty() ? schemeName : displayName; } QString colorSchemeDisplayName(const QString& schemeName) { return colorSchemeDisplayName(schemeName, ColorScheme::loadByName(schemeName)); } struct ThemeSurfaceColors { QColor background; QColor foreground; }; struct ThemeScrollBarColors { QColor track; QColor thumb; QColor hoverThumb; QColor pressedThumb; }; constexpr int kThemeGeneratedShadeCount = UiConfig::Shade600 + 1; constexpr int kDockComboPopupHorizontalPadding = 8; constexpr int kDockComboPopupVerticalPadding = 6; struct GeneratedThemeSurfaces { QColor base; ThemeSurfaceColors primary; ThemePolarity polarity; QVector backgrounds; QVector foregrounds; // 100: outer window chrome, including tab-row empty space and dock padding. ThemeSurfaceColors window; // 200: result display and active session surface. This is the background // role from the selected SpeedCrunch theme. ThemeSurfaceColors result; // 300: expression editor, dock list/table content, bitfield bit cells, // hovered dock header buttons, and normal keypad buttons. The editor no // longer has an independent theme role; it is derived from the // result-display background by moving one OKLCH shade step away from the // base surface. ThemeSurfaceColors editorAndLists; // 400: dock title bars, dock/list/table headers, combo popup fill, // list/table hovered items, active dock tabs, selected session tabs, // popup/input borders, normal bitfield buttons, hovered keypad buttons, // and hovered bitfield bit cells. ThemeSurfaceColors headersAndBorders; // 500: input controls, search boxes, combo boxes, hovered session tabs, // hovered bitfield buttons, and pressed keypad buttons. ThemeSurfaceColors inputs; // 600: inactive tabs, session tab close-button hover fills, and pressed // bitfield buttons. ThemeSurfaceColors hoverAndInactiveTabs; }; GeneratedThemeSurfaces generatedSurfaceColorsForScheme(const ColorScheme& scheme) { const QColor base = scheme.isValid() ? scheme.colorForRole(ColorScheme::Background) : QApplication::palette().color(QPalette::Base); const QColor configuredPrimary = scheme.isValid() && scheme.hasColorForRole(ColorScheme::Primary) ? scheme.colorForRole(ColorScheme::Primary) : QColor(); const QColor fallbackText = QApplication::palette().color(QPalette::Text); // Only these colors affect generated surfaces. Keep one entry per thread // so repeated widget refreshes share the shades without growing the cache. struct SurfaceCache { QColor base; QColor primary; QColor fallbackText; GeneratedThemeSurfaces surfaces; bool valid = false; }; static thread_local SurfaceCache cache; const bool unchanged = cache.valid && cache.base == base && cache.primary == configuredPrimary && cache.fallbackText == fallbackText; StartupDiagnostics::AppearanceScope timing(unchanged ? "Reuse theme surface colors" : "Generate theme surface colors", nullptr, [&]() { return StartupDiagnostics::appearanceInputs({base, configuredPrimary, fallbackText}); }); if (unchanged) return cache.surfaces; const QColor generatedPrimary = configuredPrimary.isValid() ? QColor() : generatePrimaryFromBackground(base); const QColor primary = configuredPrimary.isValid() ? configuredPrimary : (generatedPrimary.isValid() ? generatedPrimary : fallbackText); const ThemePolarity polarity = themePolarityForBackground(base); const QVector shades = generateOklchShades(base, kThemeGeneratedShadeCount, polarity); const QVector foregrounds = aaForegroundsForBackgrounds(shades); const QColor fallbackForeground = aaForegroundForBackground(base); const auto surface = [&](int index) { return ThemeSurfaceColors { shades.value(index, base), foregrounds.value(index, fallbackForeground) }; }; const GeneratedThemeSurfaces surfaces { base, ThemeSurfaceColors { primary, aaForegroundForBackground(primary) }, polarity, shades, foregrounds, surface(UiConfig::WindowBackgroundShade), surface(UiConfig::ResultDisplayShade), surface(UiConfig::DockBackgroundShade), surface(UiConfig::DockHeaderShade), surface(UiConfig::DockUnfocusedSelectedItemShade), surface(UiConfig::Shade600) }; cache = {base, configuredPrimary, fallbackText, surfaces, true}; return surfaces; } GeneratedThemeSurfaces generatedSurfaceColors(const Settings* settings) { return generatedSurfaceColorsForScheme(activeColorScheme(settings)); } QPalette paletteForThemeSurface(const QPalette& inherited, const ThemeSurfaceColors& surface) { QPalette palette = inherited; for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { palette.setColor(group, QPalette::Window, surface.background); palette.setColor(group, QPalette::WindowText, surface.foreground); palette.setColor(group, QPalette::Base, surface.background); palette.setColor(group, QPalette::Text, surface.foreground); palette.setColor(group, QPalette::Button, surface.background); palette.setColor(group, QPalette::ButtonText, surface.foreground); } return palette; } ThemeSurfaceColors themeSurfaceForShadeIndex(const GeneratedThemeSurfaces& surfaces, int shadeIndex) { const QColor fallbackBackground = surfaces.base.isValid() ? surfaces.base : QApplication::palette().color(QPalette::Base); const QColor fallbackForeground = aaForegroundForBackground(fallbackBackground); return { surfaces.backgrounds.value(shadeIndex, fallbackBackground), surfaces.foregrounds.value(shadeIndex, fallbackForeground) }; } bool setStyleSheetIfChanged(QWidget* widget, const QString& styleSheet) { // Even an identical stylesheet makes Qt repolish the widget's children. if (widget->styleSheet() == styleSheet) { StartupDiagnostics::appearanceAssignment(widget, false, false, true); return false; } StartupDiagnostics::setAppearanceStyleSheet(widget, styleSheet); return true; } void setDockPaletteIfChanged(QWidget* widget, const QPalette& palette) { const QPalette current = widget->palette(); // Matching colors must also keep the same explicit palette roles. if (widget->testAttribute(Qt::WA_SetPalette) && current == palette && current.resolveMask() == palette.resolveMask()) { StartupDiagnostics::appearanceAssignment(widget, true, false, true); return; } StartupDiagnostics::setAppearancePalette(widget, palette); } void applyStatusBarAppearance(QStatusBar* bar, const GeneratedThemeSurfaces& surfaces) { if (bar == nullptr) return; if (!bar->property("speedcrunchNativeStatusBarStyledBackground").isValid()) { bar->setProperty("speedcrunchNativeStatusBarStyledBackground", bar->testAttribute(Qt::WA_StyledBackground)); } if (Settings::instance()->statusBarAppearance == Settings::StatusBarAppearanceSystem) { setStyleSheetIfChanged(bar, QString()); QList widgets = bar->findChildren(); widgets.prepend(bar); for (QWidget* widget : widgets) { widget->style()->unpolish(widget); StartupDiagnostics::setAppearancePalette(widget, MenuStyle::systemPalette(widget)); widget->style()->polish(widget); widget->updateGeometry(); widget->update(); } // Fill styles that leave the status bar transparent so the window's // SpeedCrunch theme cannot show through the system surface. bar->setAutoFillBackground(true); bar->setAttribute(Qt::WA_StyledBackground, bar->property("speedcrunchNativeStatusBarStyledBackground").toBool()); return; } const ThemeSurfaceColors surface = themeSurfaceForShadeIndex(surfaces, UiConfig::StatusBarBackgroundShade); StartupDiagnostics::setAppearancePalette(bar, paletteForThemeSurface(bar->palette(), surface)); bar->setAutoFillBackground(true); bar->setAttribute(Qt::WA_StyledBackground, true); setStyleSheetIfChanged(bar, QStringLiteral( "QStatusBar { background-color: %1; color: %2; }" "QStatusBar::item { border: none; }" "QStatusBar QLabel { background: transparent; color: %2; }" "QStatusBar QPushButton {" " background: transparent; color: %2; border: none;" " margin: 0px; padding: 0px 4px;" "}" "QStatusBar QPushButton:hover {" " background: transparent; color: %2;" "}" "QStatusBar QPushButton:pressed {" " background: transparent; color: %2;" "}") .arg(surface.background.name(), surface.foreground.name())); for (QWidget* child : bar->findChildren()) StartupDiagnostics::setAppearancePalette(child, paletteForThemeSurface(child->palette(), surface)); } ThemeScrollBarColors scrollBarColorsForSurfaceIndex(const GeneratedThemeSurfaces& surfaces, int surfaceIndex) { const auto colorAt = [&surfaces](int index) { return surfaces.backgrounds.value(qBound(0, index, surfaces.backgrounds.size() - 1)); }; return { colorAt(surfaceIndex), colorAt(surfaceIndex + 1), colorAt(surfaceIndex + 2), colorAt(surfaceIndex + 3) }; } constexpr auto DockSeparatorNormalColorProperty = "speedcrunchDockSeparatorNormalColor"; constexpr auto DockSeparatorActiveColorProperty = "speedcrunchDockSeparatorActiveColor"; constexpr auto DockSeparatorBackgroundColorProperty = "speedcrunchDockSeparatorBackgroundColor"; constexpr auto DockSeparatorStrokeWidthProperty = "speedcrunchDockSeparatorStrokeWidth"; constexpr auto DockChromeStyleInstalledProperty = "speedcrunchDockChromeStyleInstalled"; QVariant dockSeparatorPropertyForWidget(const QWidget* widget, const char* propertyName) { for (const QWidget* current = widget; current != nullptr; current = current->parentWidget()) { const QVariant value = current->property(propertyName); if (value.isValid()) return value; } return QVariant(); } QRect dockSeparatorStrokeRect(const QRect& separatorRect, int strokeWidth) { QRect strokeRect = separatorRect; if (strokeRect.width() > strokeRect.height()) { const int height = qMax(1, strokeWidth); strokeRect.setTop(strokeRect.center().y() - (height - 1) / 2); strokeRect.setHeight(height); } else { const int width = qMax(1, strokeWidth); strokeRect.setLeft(strokeRect.center().x() - (width - 1) / 2); strokeRect.setWidth(width); } return strokeRect; } class DockChromeStyle : public QProxyStyle { public: using QProxyStyle::QProxyStyle; QRect subElementRect(SubElement element, const QStyleOption* option, const QWidget* widget = nullptr) const override { QRect rect = QProxyStyle::subElementRect(element, option, widget); if (element != SE_DockWidgetCloseButton && element != SE_DockWidgetFloatButton) return rect; const auto* dock = qobject_cast(widget); const auto* dockOption = qstyleoption_cast(option); if (dock == nullptr || dockOption == nullptr || rect.isEmpty()) return rect; const auto* button = dock->findChild( element == SE_DockWidgetCloseButton ? QStringLiteral("qt_dockwidget_closebutton") : QStringLiteral("qt_dockwidget_floatbutton"), Qt::FindDirectChildrenOnly); if (button == nullptr || !button->property("speedcrunchDockHeaderButton").toBool()) return rect; // Native styles center their own button extent. QWidget's fixed size // can then change that extent without adjusting the origin. Center the // actual themed button in the title area before Qt applies its geometry. const QRect titleRect = dockOption->rect; if (dockOption->verticalTitleBar) { rect.setLeft(titleRect.left() + (titleRect.width() - button->width()) / 2); rect.setWidth(button->width()); } else { rect.setTop(titleRect.top() + (titleRect.height() - button->height()) / 2); rect.setHeight(button->height()); } return rect; } void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override { if (element != PE_IndicatorDockWidgetResizeHandle || option == nullptr || widget == nullptr) { QProxyStyle::drawPrimitive(element, option, painter, widget); return; } const QColor normalColor = dockSeparatorPropertyForWidget(widget, DockSeparatorNormalColorProperty).value(); const QColor activeColor = dockSeparatorPropertyForWidget(widget, DockSeparatorActiveColorProperty).value(); if (!normalColor.isValid() || !activeColor.isValid()) { QProxyStyle::drawPrimitive(element, option, painter, widget); return; } const QColor backgroundColor = dockSeparatorPropertyForWidget(widget, DockSeparatorBackgroundColorProperty).value(); if (backgroundColor.isValid()) painter->fillRect(option->rect, backgroundColor); const QVariant strokeWidth = dockSeparatorPropertyForWidget(widget, DockSeparatorStrokeWidthProperty); const QRect strokeRect = dockSeparatorStrokeRect(option->rect, strokeWidth.isValid() ? strokeWidth.toInt() : UiConfig::DockSplitterStrokeWidth); const QPoint cursorPosition = widget->mapFromGlobal(QCursor::pos()); const bool cursorOverStroke = strokeRect.contains(cursorPosition); const bool active = option->state.testFlag(State_MouseOver) || option->state.testFlag(State_Sunken) || cursorOverStroke; painter->fillRect(strokeRect, active ? activeColor : normalColor); } }; void ensureDockChromeStyleInstalled() { if (QApplication::style()->property(DockChromeStyleInstalledProperty).toBool()) return; StartupDiagnostics::AppearanceScope timing("Install dock chrome style", qApp); timing.observeInputs("installed", []() { return StartupDiagnostics::appearanceInputs({ QApplication::style()->property(DockChromeStyleInstalledProperty).toBool()}); }); QStyle* style = new DockChromeStyle(QApplication::style()); style->setProperty(DockChromeStyleInstalledProperty, true); QApplication::setStyle(style); } QString splitterStyleSheet(const QColor& normal, const QColor& active) { return QStringLiteral( "QSplitter::handle { background-color: %1; }" "QSplitter::handle:hover, QSplitter::handle:pressed { background-color: %2; }") .arg(normal.name(), active.name()); } QString splitterHandleStyleSheet(const QColor& normal, const QColor& active) { return QStringLiteral( "QSplitterHandle { background-color: %1; }" "QSplitterHandle:hover, QSplitterHandle:pressed { background-color: %2; }") .arg(normal.name(), active.name()); } QString scrollBarStyleSheet(const ThemeScrollBarColors& colors) { return QStringLiteral( "QScrollBar:vertical {" " background: %1; border: 0; margin: 0; width: 10px;" "}" "QScrollBar:horizontal {" " background: %1; border: 0; margin: 0; height: 10px;" "}" "QScrollBar::handle:vertical, QScrollBar::handle:horizontal {" " background: %2; border: 0; border-radius: 4px; min-height: 20px; min-width: 20px;" "}" "QScrollBar::handle:vertical:hover, QScrollBar::handle:horizontal:hover {" " background: %3;" "}" "QScrollBar::handle:vertical:pressed, QScrollBar::handle:horizontal:pressed {" " background: %4;" "}" "QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical," "QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {" " background: %1; border: 0; width: 0; height: 0;" "}" "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical," "QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {" " background: %1;" "}") .arg(colors.track.name(), colors.thumb.name(), colors.hoverThumb.name(), colors.pressedThumb.name()); } void saveNativeDockSurface(QWidget* widget); void restoreNativeDockSurface(QWidget* widget, bool forceNativePolish = true); void applyScrollCornerColorToScrollArea(QAbstractScrollArea* area, const QColor& color) { if (area == nullptr || !color.isValid()) return; QWidget* corner = area->cornerWidget(); if (corner == nullptr) { corner = new QWidget(area); area->setCornerWidget(corner); } saveNativeDockSurface(corner); QPalette palette = corner->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { palette.setColor(group, QPalette::Window, color); palette.setColor(group, QPalette::Base, color); palette.setColor(group, QPalette::Button, color); } StartupDiagnostics::setAppearancePalette(corner, palette); corner->setAutoFillBackground(true); corner->setAttribute(Qt::WA_StyledBackground, true); setStyleSheetIfChanged(corner, QStringLiteral("QWidget { background-color: %1; border: 0; }") .arg(color.name())); } class MenuPrecisionSpinBox : public QSpinBox { public: using QSpinBox::QSpinBox; void setSystemAppearance() { m_arrowColor = QColor(); setStyleSheet(QString()); StartupDiagnostics::setAppearancePalette(this, MenuStyle::systemPalette(this)); if (QLineEdit* editor = lineEdit()) { setStyleSheetIfChanged(editor, QString()); StartupDiagnostics::setAppearancePalette(editor, MenuStyle::systemPalette(editor)); } update(); } void setThemeSurface(const ThemeSurfaceColors& surface) { m_arrowColor = surface.foreground; StartupDiagnostics::setAppearancePalette(this, paletteForThemeSurface(palette(), surface)); setStyleSheet(QStringLiteral( "QSpinBox {" " background-color: %1; color: %2; border: none; border-radius: 7px;" " padding: 1px 18px 1px 6px;" " selection-background-color: %2; selection-color: %1;" "}" "QSpinBox::up-button, QSpinBox::down-button {" " subcontrol-origin: border; width: 18px;" " background: transparent; border: none;" "}" "QSpinBox::up-button { subcontrol-position: top right; }" "QSpinBox::down-button { subcontrol-position: bottom right; }" "QSpinBox::up-arrow, QSpinBox::down-arrow {" " image: none; width: 0; height: 0;" "}") .arg(surface.background.name(), surface.foreground.name())); if (QLineEdit* editor = lineEdit()) { StartupDiagnostics::setAppearancePalette(editor, paletteForThemeSurface(editor->palette(), surface)); setStyleSheetIfChanged(editor, QStringLiteral( "QLineEdit { background: transparent; color: %1; border: none; }") .arg(surface.foreground.name())); } } protected: void paintEvent(QPaintEvent* event) override { QSpinBox::paintEvent(event); if (!m_arrowColor.isValid()) return; QStyleOptionSpinBox option; initStyleOption(&option); QColor arrowColor = m_arrowColor; if (!isEnabled()) arrowColor.setAlphaF(0.55f); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(QPen(arrowColor, 2.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter.setBrush(Qt::NoBrush); const auto drawArrow = [this, &option, &painter](QStyle::SubControl control, bool up) { const QRect rect = style()->subControlRect(QStyle::CC_SpinBox, &option, control, this); const QPointF center = QRectF(rect).center(); QPainterPath path; path.moveTo(center.x() - 3.5, center.y() + (up ? 1.5 : -1.5)); path.lineTo(center.x(), center.y() + (up ? -1.5 : 1.5)); path.lineTo(center.x() + 3.5, center.y() + (up ? 1.5 : -1.5)); painter.drawPath(path); }; drawArrow(QStyle::SC_SpinBoxUp, true); drawArrow(QStyle::SC_SpinBoxDown, false); } private: QColor m_arrowColor; }; void applyScrollBarColorsToScrollArea(QAbstractScrollArea* area, const ThemeScrollBarColors& colors) { if (area == nullptr) return; const QString styleSheet = scrollBarStyleSheet(colors); if (QScrollBar* bar = area->verticalScrollBar()) setStyleSheetIfChanged(bar, styleSheet); if (QScrollBar* bar = area->horizontalScrollBar()) setStyleSheetIfChanged(bar, styleSheet); applyScrollCornerColorToScrollArea(area, colors.track); } QIcon dockTitleButtonIcon(bool isCloseButton, const QColor& fill, const QColor& foreground) { const auto pixmapForScale = [isCloseButton, &fill, &foreground](qreal scale) { constexpr int logicalSize = 18; const int physicalSize = qRound(logicalSize * scale); QPixmap pixmap(physicalSize, physicalSize); pixmap.setDevicePixelRatio(scale); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(Qt::NoPen); painter.setBrush(fill); painter.drawEllipse(QRectF(0.5, 0.5, 17.0, 17.0)); painter.setBrush(Qt::NoBrush); painter.setPen(QPen(foreground, 1.35, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); if (isCloseButton) { painter.drawLine(QPointF(6.5, 6.5), QPointF(11.5, 11.5)); painter.drawLine(QPointF(11.5, 6.5), QPointF(6.5, 11.5)); } else { painter.drawRect(QRectF(6.5, 6.5, 5.0, 5.0)); } return pixmap; }; QIcon icon; icon.addPixmap(pixmapForScale(1.0)); icon.addPixmap(pixmapForScale(2.0)); icon.addPixmap(pixmapForScale(3.0)); return icon; } void applyDockTitleButtonIcon(QAbstractButton* button, bool hovered) { if (button == nullptr) return; const bool closeButton = button->property("speedcrunchDockHeaderCloseButton").toBool(); const QColor fill = button->property(hovered ? "speedcrunchDockHeaderButtonHoverFill" : "speedcrunchDockHeaderButtonFill").value(); const QColor foreground = button->property(hovered ? "speedcrunchDockHeaderButtonHoverForeground" : "speedcrunchDockHeaderButtonForeground").value(); button->setIcon(dockTitleButtonIcon(closeButton, fill, foreground)); } void applyDockSearchClearButtonIcon(QLineEdit* searchBox, const GeneratedThemeSurfaces& surfaces, bool focused) { if (searchBox == nullptr) return; const ThemeSurfaceColors clearButtonSurface = focused ? surfaces.primary : themeSurfaceForShadeIndex(surfaces, UiConfig::DockTextInputOutlineShade); LineEditStyleUtils::applyClearButtonColors(searchBox, clearButtonSurface.background, clearButtonSurface.foreground); } void applyDockSearchClearButtonIcon(QLineEdit* searchBox, const GeneratedThemeSurfaces& surfaces) { applyDockSearchClearButtonIcon(searchBox, surfaces, searchBox != nullptr && searchBox->hasFocus()); } void applySurfaceToLabel(QLabel* label, const ThemeSurfaceColors& surface) { if (label == nullptr) return; setDockPaletteIfChanged(label, paletteForThemeSurface(label->palette(), surface)); setStyleSheetIfChanged(label, QStringLiteral( "QLabel { background-color: %1; color: %2; }") .arg(surface.background.name(), surface.foreground.name())); } void applyNoMatchLabelSurface(QAbstractItemView* view, const ThemeSurfaceColors& surface) { if (view == nullptr || view->viewport() == nullptr) return; for (QLabel* label : view->viewport()->findChildren(QString(), Qt::FindDirectChildrenOnly)) { if (!label->property("dockListNoMatchLabel").toBool()) continue; setDockPaletteIfChanged(label, paletteForThemeSurface(label->palette(), surface)); setStyleSheetIfChanged(label, QStringLiteral("QLabel { background: transparent; color: %1; }") .arg(surface.foreground.name())); } } bool isStructuralDockBackgroundWidget(QWidget* widget) { if (widget == nullptr || widget->window()->windowType() == Qt::Popup) return false; if (qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget)) { return false; } if (qobject_cast(widget->parentWidget())) return false; return true; } void applySurfaceToStructuralDockWidget(QWidget* widget, const ThemeSurfaceColors& surface) { if (!isStructuralDockBackgroundWidget(widget)) return; setDockPaletteIfChanged(widget, paletteForThemeSurface(widget->palette(), surface)); widget->setAutoFillBackground(true); widget->setAttribute(Qt::WA_StyledBackground, true); // Dock containers share their stylesheet with child menus. Limit these // colors to the structural surfaces so the menu setting controls popups. widget->setProperty("speedcrunchDockSurface", true); setStyleSheetIfChanged(widget, QStringLiteral( "QWidget[speedcrunchDockSurface=\"true\"] { background-color: %1; color: %2; }") .arg(surface.background.name(), surface.foreground.name())); } void applySurfaceToContainingRow(QWidget* root, QWidget* item, const ThemeSurfaceColors& surface) { if (root == nullptr || item == nullptr) return; QList candidates = root->findChildren(); candidates.prepend(root); for (QWidget* candidate : candidates) { QLayout* layout = candidate->layout(); if (layout == nullptr || layout->indexOf(item) < 0) continue; applySurfaceToStructuralDockWidget(candidate, surface); for (int index = 0; index < layout->count(); ++index) { applySurfaceToLabel(qobject_cast(layout->itemAt(index)->widget()), surface); } return; } } bool isComboBoxPopupView(const QAbstractItemView* view, const QList& comboBoxes) { for (const QComboBox* comboBox : comboBoxes) { if (comboBox->view() == view || comboBox->isAncestorOf(view)) return true; } return false; } void updateDockSystemTabCursor(QTabBar* tabBar, const QPoint& pos) { if (tabBar == nullptr) return; tabBar->setCursor(tabBar->tabAt(pos) >= 0 ? Qt::PointingHandCursor : Qt::ArrowCursor); } void applyDockChromeAppearance(MainWindow* owner, QDockWidget* dock, const GeneratedThemeSurfaces& surfaces, bool forceNativePolish) { if (dock == nullptr) return; StartupDiagnostics::AppearanceScope timing("Apply dock chrome appearance", dock); StartupDiagnostics::observeAppearanceSettings(timing); saveNativeDockSurface(dock); QList titleButtons; for (QAbstractButton* button : dock->findChildren( QString(), Qt::FindDirectChildrenOnly)) { if (button->objectName() != QLatin1String("qt_dockwidget_closebutton") && button->objectName() != QLatin1String("qt_dockwidget_floatbutton")) continue; saveNativeDockSurface(button); if (!button->property("speedcrunchNativeDockHeaderButton").isValid()) { const QVariantList state {button->minimumSize(), button->maximumSize(), button->iconSize(), QVariant::fromValue(button->cursor()), button->hasMouseTracking(), button->testAttribute(Qt::WA_Hover)}; button->setProperty("speedcrunchNativeDockHeaderButton", state); } titleButtons.append(button); } if (Settings::instance()->dockAppearance == Settings::DockAppearanceSystem) { for (QAbstractButton* button : titleButtons) { button->setProperty("speedcrunchDockHeaderButton", false); if (owner != nullptr) button->removeEventFilter(owner); restoreNativeDockSurface(button, forceNativePolish); const QVariantList state = button->property("speedcrunchNativeDockHeaderButton").toList(); button->setMinimumSize(state.at(0).toSize()); button->setMaximumSize(state.at(1).toSize()); button->setIconSize(state.at(2).toSize()); button->setCursor(state.at(3).value()); button->setMouseTracking(state.at(4).toBool()); button->setAttribute(Qt::WA_Hover, state.at(5).toBool()); } restoreNativeDockSurface(dock, forceNativePolish); // Some system styles leave the title background transparent. Fill the // dock with its system palette so the main window theme cannot show through. dock->setAutoFillBackground(true); // Let Qt refresh native title icons and layout for the current dock state. QEvent styleChange(QEvent::StyleChange); QCoreApplication::sendEvent(dock, &styleChange); dock->updateGeometry(); dock->update(); return; } const ThemeSurfaceColors titleButton = themeSurfaceForShadeIndex(surfaces, UiConfig::DockHeaderButtonFillShade); const ThemeSurfaceColors titleButtonHover = themeSurfaceForShadeIndex(surfaces, UiConfig::DockHeaderButtonHoverFillShade); setDockPaletteIfChanged(dock, paletteForThemeSurface(dock->palette(), surfaces.headersAndBorders)); const bool styleChanged = setStyleSheetIfChanged(dock, QStringLiteral( "QDockWidget {" " color: %2;" "}" "QDockWidget::title {" " background-color: %1; color: %2; padding: 5px 4px;" "}" "QDockWidget::close-button, QDockWidget::float-button {" " background-color: transparent; border: none; padding: 0px;" " width: 18px; height: 18px;" "}" "QAbstractButton#qt_dockwidget_closebutton," "QAbstractButton#qt_dockwidget_floatbutton {" " background-color: %3; color: %4;" " border: none; border-radius: 9px; padding: 0px;" " min-width: 18px; max-width: 18px;" " min-height: 18px; max-height: 18px;" "}" "QAbstractButton#qt_dockwidget_closebutton:hover," "QAbstractButton#qt_dockwidget_floatbutton:hover {" " background-color: %5; color: %6;" "}") .arg(surfaces.headersAndBorders.background.name(), surfaces.headersAndBorders.foreground.name(), titleButton.background.name(), titleButton.foreground.name(), titleButtonHover.background.name(), titleButtonHover.foreground.name())); if (styleChanged) { dock->style()->unpolish(dock); dock->style()->polish(dock); dock->setWindowTitle(dock->windowTitle()); dock->update(); } for (QAbstractButton* button : titleButtons) { const bool closeButton = button->objectName() == QLatin1String("qt_dockwidget_closebutton"); button->setProperty("speedcrunchDockHeaderButton", true); button->setProperty("speedcrunchDockHeaderCloseButton", closeButton); button->setProperty("speedcrunchDockHeaderButtonFill", titleButton.background); button->setProperty("speedcrunchDockHeaderButtonForeground", titleButton.foreground); button->setProperty("speedcrunchDockHeaderButtonHoverFill", titleButtonHover.background); button->setProperty("speedcrunchDockHeaderButtonHoverForeground", titleButtonHover.foreground); if (owner != nullptr) button->installEventFilter(owner); button->setCursor(Qt::PointingHandCursor); button->setMouseTracking(true); button->setAttribute(Qt::WA_Hover, true); button->setFixedSize(QSize(18, 18)); button->setIconSize(QSize(18, 18)); setStyleSheetIfChanged(button, QStringLiteral( "QAbstractButton {" " background-color: %1; color: %2;" " border: none; border-radius: 9px; padding: 0px;" " min-width: 18px; max-width: 18px;" " min-height: 18px; max-height: 18px;" "}" "QAbstractButton:hover {" " background-color: %3; color: %4;" "}").arg(titleButton.background.name(), titleButton.foreground.name(), titleButtonHover.background.name(), titleButtonHover.foreground.name())); setDockPaletteIfChanged(button, paletteForThemeSurface(button->palette(), titleButton)); applyDockTitleButtonIcon(button, button->underMouse()); } } void saveNativeDockSurface(QWidget* widget) { // Keep frame and background settings before the first theme application. if (widget->property("speedcrunchNativeDockSurface").isValid()) return; QVariantList state {widget->styleSheet(), widget->autoFillBackground(), widget->testAttribute(Qt::WA_StyledBackground)}; if (QFrame* frame = qobject_cast(widget)) { state << int(frame->frameShape()) << int(frame->frameShadow()) << frame->lineWidth() << frame->midLineWidth(); } widget->setProperty("speedcrunchNativeDockSurface", state); if (QAbstractButton* button = qobject_cast(widget)) button->setProperty("speedcrunchNativeDockIcon", button->icon()); if (QLineEdit* edit = qobject_cast(widget)) { for (QAction* action : edit->actions()) action->setProperty("speedcrunchNativeDockIcon", action->icon()); } } void restoreNativeDockSurface(QWidget* widget, bool forceNativePolish) { const QVariantList state = widget->property("speedcrunchNativeDockSurface").toList(); if (state.size() < 3) return; const QString styleSheet = widget->property("dockListNoMatchLabel").toBool() ? QStringLiteral("QLabel { background: transparent; }") : state.at(0).toString(); const bool styleSheetChanged = setStyleSheetIfChanged(widget, styleSheet); bool needsPolish = forceNativePolish || styleSheetChanged; if (!needsPolish) { const QPointer lastPolishedStyle = widget->property("speedcrunchNativeDockPolishedStyle").value>(); const QVariant sourcePalette = widget->property("speedcrunchNativeDockSourcePalette"); const QVariant restoredPalette = widget->property("speedcrunchNativeDockRestoredPalette"); // Stylesheets can alter native palette roles during polish. needsPolish = lastPolishedStyle != widget->style() || !sourcePalette.isValid() || !restoredPalette.isValid() || sourcePalette.value() != MenuStyle::systemPalette(widget) || widget->palette() != restoredPalette.value(); } if (needsPolish) { StartupDiagnostics::Scope timing("Restore native dock style"); widget->style()->unpolish(widget); const QPalette nativePalette = MenuStyle::systemPalette(widget); StartupDiagnostics::setAppearancePalette(widget, nativePalette); widget->style()->polish(widget); widget->setProperty("speedcrunchNativeDockSourcePalette", nativePalette); } else { StartupDiagnostics::appearanceAssignment(widget, true, false, true); } widget->setAutoFillBackground(state.at(1).toBool()); widget->setAttribute(Qt::WA_StyledBackground, state.at(2).toBool()); if (QFrame* frame = qobject_cast(widget)) { if (state.size() == 7) { frame->setFrameShape(static_cast(state.at(3).toInt())); frame->setFrameShadow(static_cast(state.at(4).toInt())); frame->setLineWidth(state.at(5).toInt()); frame->setMidLineWidth(state.at(6).toInt()); } } if (QAbstractButton* button = qobject_cast(widget)) button->setIcon(button->property("speedcrunchNativeDockIcon").value()); for (const char* property : {"dockListHoverBackground", "dockListHoverForeground", "dockListActiveSelectionBackground", "dockListActiveSelectionForeground", "dockListInactiveSelectionBackground", "dockListInactiveSelectionForeground"}) widget->setProperty(property, QVariant()); if (ThemedLineEdit* edit = dynamic_cast(widget)) edit->setCursorColor(QColor()); if (QLineEdit* edit = qobject_cast(widget)) { for (QAction* action : edit->actions()) action->setIcon(action->property("speedcrunchNativeDockIcon").value()); } if (needsPolish) { widget->setProperty("speedcrunchNativeDockPolishedStyle", QVariant::fromValue(QPointer(widget->style()))); widget->setProperty("speedcrunchNativeDockRestoredPalette", widget->palette()); } widget->update(); } void alignDockSearchRow(QWidget* content) { QLineEdit* search = content->findChild(); if (!search || !search->parentWidget()->layout()) return; const auto combos = content->findChildren(); if (combos.isEmpty()) return; int bottomInset = 0; for (QComboBox* combo : combos) { QStyleOptionComboBox option; option.initFrom(combo); option.rect = QRect(QPoint(), combo->sizeHint()); const QRect itemRect = combo->style()->subElementRect(QStyle::SE_ComboBoxLayoutItem, &option, combo); if (!itemRect.isEmpty()) bottomInset = qMax(bottomInset, option.rect.bottom() - itemRect.bottom()); } // Native dropdowns reserve space below their painted bounds in the row above. QLayout* layout = search->parentWidget()->layout(); QMargins margins = layout->contentsMargins(); margins.setTop(qMax(0, UiConfig::DockSearchRowVerticalPadding - bottomInset)); layout->setContentsMargins(margins); } void applyDockContentAppearance(MainWindow* owner, QDockWidget* dock, const GeneratedThemeSurfaces& surfaces, const QList& widgets, bool forceNativePolish) { StartupDiagnostics::AppearanceScope timing("Apply dock content appearance", dock); StartupDiagnostics::observeAppearanceSettings(timing); QWidget* dockContent = dock->widget(); if (dockContent == nullptr) return; if (Settings::instance()->dockAppearance == Settings::DockAppearanceSystem) { for (QWidget* widget : widgets) { if (!qobject_cast(widget)) restoreNativeDockSurface(widget, forceNativePolish); } dockContent->setAutoFillBackground(true); if (BookDock* book = qobject_cast(dock)) { const QPalette palette = MenuStyle::systemPalette(book->findChild()); book->setContentSurfaceColors(palette.color(QPalette::Base), palette.color(QPalette::Text)); } if (BitFieldWidget* bitField = qobject_cast(dockContent)) { bitField->setThemeColors(QColor(), QColor()); const QPalette palette = MenuStyle::systemPalette(bitField); bitField->setToolTipThemeColors(palette.color(QPalette::ToolTipBase), palette.color(QPalette::ToolTipText), palette.color(QPalette::Mid), 0); } if (ConstantsWidget* constants = qobject_cast(dockContent)) { const QPalette palette = MenuStyle::systemPalette(constants); constants->setSummaryPopupThemeColors(palette.color(QPalette::ToolTipBase), palette.color(QPalette::ToolTipText), palette.color(QPalette::Mid), 0); } for (QComboBox* combo : dockContent->findChildren()) DockComboBoxChevron::applySystemAppearance(combo); alignDockSearchRow(dockContent); return; } const ThemeSurfaceColors dockBackground = themeSurfaceForShadeIndex(surfaces, UiConfig::DockBackgroundShade); const ThemeSurfaceColors dockHeader = themeSurfaceForShadeIndex(surfaces, UiConfig::DockHeaderShade); const ThemeSurfaceColors dockHoveredItem = themeSurfaceForShadeIndex(surfaces, UiConfig::DockHoveredItemShade); const int dockComboPopupShade = qMin(UiConfig::DockBackgroundShade + 1, UiConfig::Shade600); const ThemeSurfaceColors dockComboPopup = themeSurfaceForShadeIndex(surfaces, dockComboPopupShade); const ThemeSurfaceColors dockTextInput = themeSurfaceForShadeIndex(surfaces, UiConfig::DockTextInputShade); const ThemeSurfaceColors dockTextInputOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::DockTextInputOutlineShade); const ThemeSurfaceColors dockUnfocusedSelection = themeSurfaceForShadeIndex(surfaces, UiConfig::DockUnfocusedSelectedItemShade); BitFieldWidget* bitField = qobject_cast(dockContent); const QList comboBoxes = dockContent->findChildren(); const ThemeSurfaceColors& dockSurface = dockBackground; setDockPaletteIfChanged(dockContent, paletteForThemeSurface(dockContent->palette(), dockSurface)); dockContent->setAutoFillBackground(true); applySurfaceToStructuralDockWidget(dockContent, dockSurface); for (QWidget* child : dockContent->findChildren()) applySurfaceToStructuralDockWidget(child, dockSurface); if (bitField != nullptr) { const ThemeSurfaceColors bitfieldHover = themeSurfaceForShadeIndex(surfaces, UiConfig::BitfieldBitHoverShade); const ThemeSurfaceColors bitfieldButton = themeSurfaceForShadeIndex(surfaces, UiConfig::BitfieldButtonFillShade); const ThemeSurfaceColors bitfieldButtonHover = themeSurfaceForShadeIndex(surfaces, UiConfig::BitfieldButtonHoverFillShade); const ThemeSurfaceColors bitfieldButtonPressed = themeSurfaceForShadeIndex(surfaces, UiConfig::BitfieldButtonPressedFillShade); const ThemeSurfaceColors bitfieldToolTip = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupBackgroundShade); const ThemeSurfaceColors bitfieldToolTipOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupOutlineShade); bitField->setToolTipThemeColors(bitfieldToolTip.background, bitfieldToolTip.foreground, bitfieldToolTipOutline.background, UiConfig::CompletionPopupCornerRadius); bitField->setThemeColors(dockBackground.background, dockBackground.foreground, bitfieldHover.background, bitfieldHover.foreground, dockUnfocusedSelection.background, dockUnfocusedSelection.foreground, surfaces.primary.background, surfaces.primary.foreground, bitfieldButton.background, bitfieldButton.foreground, bitfieldButtonHover.background, bitfieldButtonHover.foreground, bitfieldButtonPressed.background, bitfieldButtonPressed.foreground); } const ThemeScrollBarColors listScrollBars = scrollBarColorsForSurfaceIndex(surfaces, UiConfig::DockBackgroundShade); const ThemeScrollBarColors comboPopupScrollBars = scrollBarColorsForSurfaceIndex(surfaces, dockComboPopupShade); if (BookDock* bookDock = qobject_cast(dock)) { bookDock->setContentSurfaceColors(dockBackground.background, dockBackground.foreground); } if (ConstantsWidget* constantsWidget = qobject_cast(dockContent)) { const ThemeSurfaceColors completionPopup = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupBackgroundShade); const ThemeSurfaceColors completionOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupOutlineShade); constantsWidget->setSummaryPopupThemeColors(completionPopup.background, completionPopup.foreground, completionOutline.background, UiConfig::CompletionPopupCornerRadius); } for (QAbstractScrollArea* scrollArea : dockContent->findChildren()) { if (qobject_cast(scrollArea)) continue; applyScrollBarColorsToScrollArea(scrollArea, listScrollBars); } for (QComboBox* comboBox : comboBoxes) { applySurfaceToContainingRow(dockContent, comboBox, dockSurface); setDockPaletteIfChanged(comboBox, paletteForThemeSurface(comboBox->palette(), dockTextInput)); DockComboBoxChevron::PopupTheme popupTheme; popupTheme.buttonStyle = QStringLiteral( "QComboBox {" " background-color: %1; color: %2;" " border: 1px solid %3; border-radius: %6px; padding: 4px %4px 4px 8px;" "}" "QComboBox::drop-down {" " subcontrol-origin: border; subcontrol-position: top right;" " width: %5px; border: none; background: transparent;" "}" "QComboBox::down-arrow {" " image: none; width: 0px; height: 0px;" "}") .arg(dockTextInput.background.name(), dockTextInput.foreground.name(), dockTextInputOutline.background.name()) .arg(DockComboBoxChevron::IndicatorWidth + 4) .arg(DockComboBoxChevron::IndicatorWidth) .arg(UiConfig::ControlCornerRadius); if (QAbstractItemView* popupView = comboBox->view()) { QPalette popupPalette = paletteForThemeSurface(MenuStyle::systemPalette(popupView), dockComboPopup); popupPalette.setColor(QPalette::Highlight, dockHoveredItem.background); popupPalette.setColor(QPalette::HighlightedText, dockHoveredItem.foreground); popupTheme.viewStyle = QStringLiteral( "QAbstractItemView {" " background-color: %1; color: %2;" " border: 0; border-radius: %7px; outline: 0;" " padding: %3px %4px;" "}" "QAbstractItemView::item {" " border: 0; border-radius: %8px;" "}" "QAbstractItemView::item:hover {" " background-color: %5; color: %6;" " border-radius: %8px;" "}") .arg(dockComboPopup.background.name(), dockComboPopup.foreground.name()) .arg(kDockComboPopupVerticalPadding) .arg(kDockComboPopupHorizontalPadding) .arg(dockHoveredItem.background.name(), dockHoveredItem.foreground.name()) .arg(UiConfig::CompletionPopupCornerRadius) .arg(UiConfig::DockHoveredItemCornerRadius); popupTheme.palette = popupPalette; popupTheme.scrollBarStyle = scrollBarStyleSheet(comboPopupScrollBars); DockComboBoxChevron::apply(comboBox, dockTextInput.foreground, dockTextInputOutline.background, popupTheme); } } for (QLineEdit* searchBox : dockContent->findChildren()) { applySurfaceToContainingRow(dockContent, searchBox, dockSurface); searchBox->setProperty("speedcrunchDockTextInput", true); if (owner != nullptr) searchBox->installEventFilter(owner); setDockPaletteIfChanged(searchBox, paletteForThemeSurface(searchBox->palette(), dockTextInput)); if (ThemedLineEdit* themedSearchBox = dynamic_cast(searchBox)) themedSearchBox->setCursorColor(surfaces.primary.background); setStyleSheetIfChanged(searchBox, QStringLiteral( "QLineEdit {" " background-color: %1; color: %2;" " border: %5px solid %3; border-radius: %7px; padding: 4px 8px;" "}" "QLineEdit:focus {" " border: %6px solid %4;" "}") .arg(dockTextInput.background.name(), dockTextInput.foreground.name(), dockTextInputOutline.background.name(), surfaces.primary.background.name()) .arg(UiConfig::DockTextInputUnfocusedOutlineStrokeWidth) .arg(UiConfig::OutlineStrokeWidth) .arg(UiConfig::ControlCornerRadius)); applyDockSearchClearButtonIcon(searchBox, surfaces); } for (QAbstractItemView* view : dockContent->findChildren()) { if (qobject_cast(view) || isComboBoxPopupView(view, comboBoxes)) continue; view->setFrameShape(QFrame::NoFrame); QPalette palette = paletteForThemeSurface(view->palette(), dockBackground); palette.setColor(QPalette::Active, QPalette::Highlight, surfaces.primary.background); palette.setColor(QPalette::Active, QPalette::HighlightedText, surfaces.primary.foreground); palette.setColor(QPalette::Inactive, QPalette::Highlight, dockUnfocusedSelection.background); palette.setColor(QPalette::Inactive, QPalette::HighlightedText, dockUnfocusedSelection.foreground); palette.setColor(QPalette::Disabled, QPalette::Highlight, dockUnfocusedSelection.background); palette.setColor(QPalette::Disabled, QPalette::HighlightedText, dockUnfocusedSelection.foreground); view->setProperty("dockListHoverBackground", dockHoveredItem.background); view->setProperty("dockListHoverForeground", dockHoveredItem.foreground); view->setProperty("dockListActiveSelectionBackground", surfaces.primary.background); view->setProperty("dockListActiveSelectionForeground", surfaces.primary.foreground); view->setProperty("dockListInactiveSelectionBackground", dockUnfocusedSelection.background); view->setProperty("dockListInactiveSelectionForeground", dockUnfocusedSelection.foreground); setStyleSheetIfChanged(view, QStringLiteral( "QAbstractItemView {" " background-color: %1; color: %2;" " border: 0;" " padding: %3px;" "}") .arg(dockBackground.background.name(), dockBackground.foreground.name()) .arg(UiConfig::DockListPadding) + scrollBarStyleSheet(listScrollBars)); setDockPaletteIfChanged(view, palette); setDockPaletteIfChanged(view->viewport(), palette); applyScrollBarColorsToScrollArea(view, listScrollBars); applyNoMatchLabelSurface(view, dockBackground); } for (QHeaderView* header : dockContent->findChildren()) { const QPointer measuredModel = header->property("speedcrunchNativeHeaderModel").value>(); if (measuredModel != header->model()) { header->setProperty("speedcrunchNativeHeaderMetrics", QVariant()); QAbstractItemModel* model = header->model(); if (model != nullptr) { const auto invalidateMetrics = [header, model]() { if (header->model() == model) header->setProperty("speedcrunchNativeHeaderMetrics", QVariant()); }; QObject::connect(model, &QAbstractItemModel::headerDataChanged, header, [header, invalidateMetrics](Qt::Orientation orientation, int, int) { if (orientation == header->orientation()) invalidateMetrics(); }); QObject::connect(model, &QAbstractItemModel::modelReset, header, invalidateMetrics); } header->setProperty("speedcrunchNativeHeaderModel", QVariant::fromValue(QPointer(model))); } const auto metricInputs = [header]() { return QVariantList {header->font(), MenuStyle::systemPalette(header), header->logicalDpiX(), header->logicalDpiY(), int(header->layoutDirection()), header->count()}; }; const QVariantList metrics = header->property("speedcrunchNativeHeaderMetrics").toList(); const QPointer measuredStyle = header->property("speedcrunchNativeHeaderStyle").value>(); const bool reuseMetrics = !forceNativePolish && metrics.size() == 2 && measuredStyle == header->style() && header->property("speedcrunchNativeHeaderInputs").toList() == metricInputs() && header->property("speedcrunchThemedHeaderStyleSheet").toString() == header->styleSheet(); int headerMargin; int headerContentHeight; if (reuseMetrics) { StartupDiagnostics::Scope headerMetricsTiming("Reuse native dock header metrics"); headerMargin = metrics.at(0).toInt(); headerContentHeight = metrics.at(1).toInt(); } else { StartupDiagnostics::Scope headerMetricsTiming("Measure native dock header metrics"); restoreNativeDockSurface(header); QStyleOptionHeader option; option.initFrom(header); headerMargin = qMax(0, header->style()->pixelMetric(QStyle::PM_HeaderMargin, &option, header)); // Keep the native height, including the two themed border strokes. headerContentHeight = qMax(0, header->sizeHint().height() - 2); } setDockPaletteIfChanged(header, paletteForThemeSurface(header->palette(), dockBackground)); setStyleSheetIfChanged(header, QStringLiteral( "QHeaderView { background-color: %1; color: %2; border: 0; padding: 0; }" "QHeaderView::section {" " background-color: %1; color: %2;" " border: 0;" " border-top: 1px solid %3;" " border-right: 1px solid %3;" " border-bottom: 1px solid %3;" " padding: 0px %4px;" " height: %5px;" "}" "QHeaderView::section:first {" " border-left: 0;" "}" "QHeaderView::section:last {" " border-right: 0;" "}") .arg(dockBackground.background.name(), dockBackground.foreground.name(), dockHeader.background.name()) .arg(headerMargin) .arg(headerContentHeight)); if (!reuseMetrics) { header->setProperty("speedcrunchNativeHeaderMetrics", QVariantList {headerMargin, headerContentHeight}); header->setProperty("speedcrunchNativeHeaderStyle", QVariant::fromValue(QPointer(header->style()))); header->setProperty("speedcrunchNativeHeaderInputs", metricInputs()); header->setProperty("speedcrunchThemedHeaderStyleSheet", header->styleSheet()); } } alignDockSearchRow(dockContent); } void applyDockAppearance(MainWindow* owner, QDockWidget* dock, const GeneratedThemeSurfaces& surfaces, bool forceNativePolish = true) { if (dock == nullptr) return; StartupDiagnostics::AppearanceScope timing("Apply dock appearance", dock); QList widgets; if (QWidget* content = dock->widget()) { widgets = content->findChildren(); widgets.prepend(content); // Capture native state before the parent's stylesheet can polish children. for (QWidget* widget : widgets) { if (!qobject_cast(widget)) saveNativeDockSurface(widget); } } // Set the parent style first so it does not repolish freshly styled contents. applyDockChromeAppearance(owner, dock, surfaces, forceNativePolish); applyDockContentAppearance(owner, dock, surfaces, widgets, forceNativePolish); } void applyThemeBackgroundRoleToWidget(QWidget* widget, const QColor& background) { if (widget == nullptr) return; QPalette pal = widget->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { pal.setColor(group, QPalette::Window, background); pal.setColor(group, QPalette::Base, background); pal.setColor(group, QPalette::Button, background); } StartupDiagnostics::setAppearancePalette(widget, pal); widget->setAutoFillBackground(true); widget->setAttribute(Qt::WA_StyledBackground, true); if (!qobject_cast(widget)) { // Keep the surface color local. An unqualified stylesheet also paints // child menus, even when they have a complete system palette. widget->setProperty("speedcrunchThemeSurfaceBackground", true); setStyleSheetIfChanged(widget, QStringLiteral( "QWidget[speedcrunchThemeSurfaceBackground=\"true\"] { background-color: %1; }") .arg(background.name())); } } void applyWindowThemeBackground(QWidget* window, const ThemeSurfaceColors& surface) { StartupDiagnostics::setAppearancePalette(window, paletteForThemeSurface(window->palette(), surface)); window->setAutoFillBackground(true); window->setAttribute(Qt::WA_StyledBackground, true); setStyleSheetIfChanged(window, QStringLiteral("QMainWindow { background-color: %1; }") .arg(surface.background.name())); } void applyDockTabBarBackgroundToWidget(QWidget* widget, const ThemeSurfaceColors& surface) { if (widget == nullptr) return; widget->setProperty("speedcrunchDockTabBackground", true); StartupDiagnostics::setAppearancePalette(widget, paletteForThemeSurface(widget->palette(), surface)); widget->setAutoFillBackground(true); widget->setAttribute(Qt::WA_StyledBackground, true); setStyleSheetIfChanged(widget, QStringLiteral( "QWidget[speedcrunchDockTabBackground=\"true\"] {" " background-color: %1; border: 0;" "}") .arg(surface.background.name())); } QString oklchThemeReportPath() { return QDir(QDir::tempPath()).absoluteFilePath( QStringLiteral("speedcrunch-oklch-theme-report.html")); } // Theme application can run multiple times while startup restores widgets, but // later user theme changes still need a fresh diagnostics report. Keying by the // generated colors suppresses duplicate writes without turning the report into a // process-wide one-shot. QString oklchThemeReportKey(const GeneratedThemeSurfaces& surfaces) { QStringList colors; colors.reserve(surfaces.backgrounds.size() + surfaces.foregrounds.size() + 2); colors.append(surfaces.base.name(QColor::HexArgb)); colors.append(QString::number(static_cast(surfaces.polarity))); for (const QColor& color : surfaces.backgrounds) colors.append(color.name(QColor::HexArgb)); for (const QColor& color : surfaces.foregrounds) colors.append(color.name(QColor::HexArgb)); return colors.join(QLatin1Char('|')); } QString& lastOklchThemeReportKey() { static QString key; return key; } QString debugColorName(const QColor& color) { return color.isValid() ? color.name(QColor::HexRgb).toUpper() : QStringLiteral("(invalid)"); } QString paletteColorName(const QWidget* widget, QPalette::ColorRole role) { return widget ? debugColorName(widget->palette().color(role)) : QStringLiteral("(missing)"); } QString grabbedCenterColorName(QWidget* widget) { if (widget == nullptr || widget->size().isEmpty() || !widget->isVisible()) return QStringLiteral("(unavailable)"); const QPixmap pixmap = widget->grab(); const QImage image = pixmap.toImage(); if (image.isNull() || image.width() <= 0 || image.height() <= 0) return QStringLiteral("(unavailable)"); return debugColorName(image.pixelColor(image.width() / 2, image.height() / 2)); } QString htmlTableCell(const QString& value) { return QStringLiteral("%1").arg(value.toHtmlEscaped()); } void appendDiagnosticRow(QTextStream& out, const QString& widget, const QString& expected, const QString& palette, const QString& viewportPalette, const QString& grab, const QString& styleSheet) { out << "" << widget.toHtmlEscaped() << "" << htmlTableCell(expected) << htmlTableCell(palette) << htmlTableCell(viewportPalette) << htmlTableCell(grab) << htmlTableCell(styleSheet) << "\n"; } QString shortStyleSheet(const QWidget* widget) { if (widget == nullptr) return QStringLiteral("(missing)"); QString styleSheet = widget->styleSheet().simplified(); constexpr int kMaximumStyleSheetLength = 120; if (styleSheet.size() > kMaximumStyleSheetLength) styleSheet = styleSheet.left(kMaximumStyleSheetLength) + QStringLiteral("..."); return styleSheet.isEmpty() ? QStringLiteral("(empty)") : styleSheet; } static void typeTextThroughEditorInputRules(Editor* editor, const QString& text) { if (!editor || text.isEmpty()) return; const auto keyForChar = [](QChar ch) -> int { switch (ch.unicode()) { case MathDsl::DotSep.unicode(): return Qt::Key_Period; case MathDsl::CommaSep.unicode(): return Qt::Key_Comma; case MathDsl::AddOp.unicode(): return Qt::Key_Plus; case MathDsl::SubOpAl1.unicode(): return Qt::Key_Minus; case MathDsl::DivOp.unicode(): return Qt::Key_Slash; case MathDsl::MulOpAl1.unicode(): return Qt::Key_Asterisk; case MathDsl::PowOp.unicode(): return Qt::Key_AsciiCircum; case MathDsl::GroupStart.unicode(): return Qt::Key_ParenLeft; case MathDsl::GroupEnd.unicode(): return Qt::Key_ParenRight; case MathDsl::PercentOp.unicode(): return Qt::Key_Percent; case MathDsl::FactorOp.unicode(): return Qt::Key_Exclam; default: break; } if (ch.isDigit()) return Qt::Key_0 + (ch.unicode() - MathDsl::Dig0.unicode()); return Qt::Key_unknown; }; for (const QChar ch : text) { const int key = keyForChar(ch); QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier, QString(ch)); QApplication::sendEvent(editor, &keyEvent); } } namespace { struct AssignmentTarget { QString identifier; bool isFunction = false; bool isUnit = false; bool valid = false; }; int& activeSessionTabDragCount() { static int count = 0; return count; } QPointer& primaryMainWindow() { static QPointer window; return window; } QList>& allMainWindows() { static QList> windows; return windows; } QHash>& windowIds() { static QHash> ids; return ids; } QPointer& globallyActiveDisplay() { static QPointer display; return display; } QPointer& globallyActiveEditor() { static QPointer editor; return editor; } bool& activeEditorDisplayPaneActivationInProgress() { static bool inProgress = false; return inProgress; } int& dockTextInputFocusTransferDepth() { static int depth = 0; return depth; } bool dockTextInputFocusTransferInProgress() { return dockTextInputFocusTransferDepth() > 0; } QPointer& pendingDockTextInputFocusTarget() { static QPointer target; return target; } int& pendingDockTextInputFocusTargetGeneration() { static int generation = 0; return generation; } int setPendingDockTextInputFocusTarget(QWidget* target) { pendingDockTextInputFocusTarget() = target; return ++pendingDockTextInputFocusTargetGeneration(); } QPointer& pendingDockFocusTarget() { static QPointer target; return target; } int& pendingDockFocusTargetGeneration() { static int generation = 0; return generation; } int setPendingDockFocusTarget(QWidget* target) { pendingDockFocusTarget() = target; return ++pendingDockFocusTargetGeneration(); } QPointer& pendingSessionTabActivationDisplay() { static QPointer display; return display; } QPointer& pendingSessionTabActivationEditor() { static QPointer editor; return editor; } QPointer& pendingWindowActivationEditor() { static QPointer editor; return editor; } QPointer& editorBeforeWindowDeactivate() { static QPointer editor; return editor; } QPointer& focusWidgetBeforeWindowDeactivate() { static QPointer widget; return widget; } QPointer& lastFocusWidgetInActiveWindow() { static QPointer widget; return widget; } QPointer& pendingWindowActivationFocusWidget() { static QPointer widget; return widget; } int& windowActivationRestoreGeneration() { static int generation = 0; return generation; } void cancelWindowActivationRestore() { pendingWindowActivationEditor() = nullptr; pendingWindowActivationFocusWidget() = nullptr; ++windowActivationRestoreGeneration(); } MainWindow* activeMainWindowForMenuAction(MainWindow* fallback) { const auto windowForWidget = [](QWidget* widget) -> MainWindow* { if (widget == nullptr) return nullptr; if (auto* window = qobject_cast(widget->window())) return window; // Floating docks are windows too, but retain their MainWindow parent. for (QWidget* ancestor = widget; ancestor != nullptr; ancestor = ancestor->parentWidget()) { if (auto* dock = qobject_cast(ancestor)) { for (QWidget* owner = dock->parentWidget(); owner != nullptr; owner = owner->parentWidget()) { if (auto* window = qobject_cast(owner)) return window; } } } return nullptr; }; MainWindow* targetWindow = windowForWidget(QApplication::activeWindow()); if (targetWindow == nullptr) targetWindow = windowForWidget(QApplication::focusWidget()); if (targetWindow == nullptr) targetWindow = windowForWidget(lastFocusWidgetInActiveWindow()); return targetWindow != nullptr ? targetWindow : fallback; } class DockTextInputFocusTransferGuard { public: DockTextInputFocusTransferGuard() { ++dockTextInputFocusTransferDepth(); } ~DockTextInputFocusTransferGuard() { --dockTextInputFocusTransferDepth(); } }; bool& appShutdownInProgress() { static bool shuttingDown = false; return shuttingDown; } bool applicationShutdownInProgress() { // MainWindow close events can be triggered by more than one shutdown path: // the primary window, QApplication::quit(), and the single-instance startup // handshake in main.cpp. Keep this helper in sync with main.cpp's dynamic // property so child windows can tell a real app shutdown from an ordinary // child-window close. return appShutdownInProgress() || (qApp && qApp->property("speedcrunchShutdownInProgress").toBool()); } QList>& panesPendingSessionTabDragDeletion() { static QList> panes; return panes; } void flushPanesPendingSessionTabDragDeletion() { if (activeSessionTabDragCount() > 0) return; QList> panes = panesPendingSessionTabDragDeletion(); panesPendingSessionTabDragDeletion().clear(); for (const QPointer& pane : panes) { if (pane != nullptr) pane->deleteLater(); } } void deletePaneAfterSessionTabDrag(QWidget* pane) { if (pane == nullptr) return; pane->hide(); pane->setParent(nullptr); if (activeSessionTabDragCount() > 0) { panesPendingSessionTabDragDeletion().append(QPointer(pane)); return; } pane->deleteLater(); } class SessionTabDragGuard { public: SessionTabDragGuard() { ++activeSessionTabDragCount(); } ~SessionTabDragGuard() { --activeSessionTabDragCount(); flushPanesPendingSessionTabDragDeletion(); } }; class SessionTabBar : public QTabBar { public: explicit SessionTabBar(QWidget* parent = nullptr) : QTabBar(parent) { setAcceptDrops(true); setDrawBase(false); setElideMode(Qt::ElideRight); setExpanding(true); setMouseTracking(true); setMovable(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); setUsesScrollButtons(false); setContextMenuPolicy(Qt::DefaultContextMenu); applyStyle(QColor()); } static QColor secondarySurfaceColor(const QColor& surface) { return surface.lightnessF() < 0.5 ? surface.lighter(118) : surface.darker(108); } void applyStyle(const QColor& selectedText, const QColor& selectedSurface = QColor(), const QColor& hoverText = QColor(), const QColor& hoverSurface = QColor(), const QColor& stripSurface = QColor(), const QColor& inactiveText = QColor(), const QColor& closeButtonHoverText = QColor(), const QColor& closeButtonHoverSurface = QColor(), const QColor& toolTipBackground = QColor(), const QColor& toolTipForeground = QColor(), const QColor& toolTipOutline = QColor(), int toolTipCornerRadius = 0) { const QColor fg = selectedText.isValid() ? selectedText : palette().color(QPalette::WindowText); const QPalette pal = palette(); const QColor selected = selectedSurface.isValid() ? selectedSurface : pal.color(QPalette::Window); const QColor hovered = hoverSurface.isValid() ? hoverSurface : secondarySurfaceColor(selected); const QColor strip = stripSurface.isValid() ? stripSurface : selected; const QColor text = inactiveText.isValid() ? inactiveText : pal.color(QPalette::WindowText); const QColor hoveredText = hoverText.isValid() ? hoverText : text; const QColor closeButtonHovered = closeButtonHoverSurface.isValid() ? closeButtonHoverSurface : hovered; const QColor closeButtonHoveredText = closeButtonHoverText.isValid() ? closeButtonHoverText : hoveredText; m_tabStripColor = strip; m_inactiveTabColor = strip; m_hoveredTabColor = hovered; m_selectedTabColor = selected; m_tabTextColor = text; m_hoveredTextColor = hoveredText; m_selectedTextColor = fg; m_closeButtonHoverColor = closeButtonHovered; m_closeButtonHoverTextColor = closeButtonHoveredText; m_toolTipBackgroundColor = toolTipBackground; m_toolTipForegroundColor = toolTipForeground; m_toolTipOutlineColor = toolTipOutline; m_toolTipCornerRadius = qMax(0, toolTipCornerRadius); applyToolTipTheme(); setStyleSheet(QStringLiteral(R"( QToolButton { background: transparent; border: none; padding: 0px; margin: 0px; } QToolButton:hover, QToolButton:pressed { background: transparent; border: none; } )")); if (QWidget* row = parentWidget()) { QPalette rowPalette = row->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { rowPalette.setColor(group, QPalette::Window, m_tabStripColor); rowPalette.setColor(group, QPalette::Base, m_tabStripColor); } row->setPalette(rowPalette); row->setAutoFillBackground(true); row->setAttribute(Qt::WA_StyledBackground, true); row->setStyleSheet(QStringLiteral("background-color: %1;") .arg(m_tabStripColor.name())); } QPalette tabPalette = palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { tabPalette.setColor(group, QPalette::Window, m_tabStripColor); tabPalette.setColor(group, QPalette::Base, m_tabStripColor); } setPalette(tabPalette); setAutoFillBackground(true); updateGeometry(); update(); } std::function tabContextMenuRequested; std::function sessionTabDropped; std::function sourceMainWindow; std::function sessionTabDetached; std::function tabCloseRequested; std::function tabActivated; void setActivePaneSelectedTabIndicatorColor(const QColor& color) { const QColor activeColor = color.isValid() ? color : QColor(); if (m_activePaneSelectedTabIndicatorColor == activeColor) return; m_activePaneSelectedTabIndicatorColor = activeColor; refreshCloseButtons(); update(); } void refreshCloseButtons() { bool visibilityChanged = false; for (int i = 0; i < count(); ++i) { const bool showButton = !m_visualDragActive && (i == currentIndex() || i == m_hoveredTabIndex); QWidget* existingButton = tabButton(i, QTabBar::RightSide); QToolButton* closeButton = qobject_cast(existingButton); if (closeButton == nullptr) { closeButton = new QToolButton(this); closeButton->setAutoRaise(false); closeButton->setCursor(Qt::PointingHandCursor); closeButton->setFocusPolicy(Qt::NoFocus); closeButton->setObjectName(QStringLiteral("SessionTabCloseButton")); closeButton->setMouseTracking(true); closeButton->setAttribute(Qt::WA_Hover, true); closeButton->setText(QStringLiteral("×")); closeButton->setStyleSheet(QStringLiteral(R"( QToolButton { background: transparent; border: none; margin: 3px 3px 3px 0px; padding: 0px; min-width: 18px; max-width: 18px; min-height: 18px; max-height: 18px; border-radius: 9px; font-weight: 400; text-align: center; } QToolButton:hover { background: rgba(127, 127, 127, 80); } QToolButton:pressed { background: rgba(127, 127, 127, 192); } )")); closeButton->setToolTip(QString()); closeButton->installEventFilter(this); QFont closeFont = closeButton->font(); closeFont.setBold(false); closeFont.setPixelSize(qMax(11, fontMetrics().height() - 5)); closeButton->setFont(closeFont); const int buttonExtent = qMax(16, fontMetrics().height() + 1); closeButton->setFixedSize(buttonExtent, buttonExtent); setTabButton(i, QTabBar::RightSide, closeButton); connect(closeButton, &QToolButton::clicked, this, [this, closeButton]() { int tabIndex = -1; for (int i = 0; i < count(); ++i) { if (tabButton(i, QTabBar::RightSide) == closeButton) { tabIndex = i; break; } } if (tabIndex >= 0 && tabCloseRequested) tabCloseRequested(tabText(tabIndex)); }); } const bool selected = i == currentIndex(); const bool hovered = i == m_hoveredTabIndex; const QColor normalText = selected ? m_selectedTextColor : (hovered ? m_hoveredTextColor : m_tabTextColor); const QColor hoveredText = m_closeButtonHoverTextColor.isValid() ? m_closeButtonHoverTextColor : normalText; closeButton->setStyleSheet(QStringLiteral(R"( QToolButton { background: transparent; color: %1; border: none; margin: 3px 3px 3px 0px; padding: 0px; min-width: 18px; max-width: 18px; min-height: 18px; max-height: 18px; border-radius: 9px; font-weight: 400; text-align: center; } QToolButton:hover { background: %2; color: %3; } QToolButton:pressed { background: %2; color: %3; } )") .arg(normalText.name(), m_closeButtonHoverColor.name(), hoveredText.name())); visibilityChanged = visibilityChanged || closeButton->isVisible() != showButton; closeButton->setVisible(showButton); } if (visibilityChanged) update(); } protected: void contextMenuEvent(QContextMenuEvent* event) override { const int index = tabAt(event->pos()); if (index >= 0) { setCurrentIndex(index); if (tabContextMenuRequested) tabContextMenuRequested(tabText(index), event->globalPos()); event->accept(); return; } QTabBar::contextMenuEvent(event); } void mousePressEvent(QMouseEvent* event) override { hideTabToolTip(); if (event->button() == Qt::LeftButton) { m_dragTabIndex = tabAt(event->pos()); m_dragSessionName = m_dragTabIndex >= 0 ? tabText(m_dragTabIndex) : QString(); m_dragTabPressOffsetX = m_dragTabIndex >= 0 ? event->pos().x() - tabRect(m_dragTabIndex).left() : 0; } const QString pressedSession = m_dragSessionName; if (event->button() == Qt::LeftButton && !pressedSession.isEmpty()) { if (currentIndex() != m_dragTabIndex) setCurrentIndex(m_dragTabIndex); else if (tabActivated) tabActivated(pressedSession); refreshCloseButtons(); event->accept(); return; } QTabBar::mousePressEvent(event); refreshCloseButtons(); } void mouseMoveEvent(QMouseEvent* event) override { updateHoveredTab(event->pos()); showTabToolTip(event->pos(), event->globalPosition().toPoint()); const bool hasPressedTab = (event->buttons() & Qt::LeftButton) && m_dragTabIndex >= 0; if (!hasPressedTab) { QTabBar::mouseMoveEvent(event); refreshCloseButtons(); return; } if (!shouldStartCrossBarDrag(event->pos(), event->globalPosition().toPoint())) { updateDraggedTabVisual(event->pos()); event->accept(); refreshCloseButtons(); return; } m_visualDragActive = false; m_visualTargetIndex = -1; refreshCloseButtons(); repaint(); QMimeData* mime = new QMimeData(); QJsonObject payload; payload.insert(QStringLiteral("session"), m_dragSessionName); if (sourceMainWindow) { if (MainWindow* window = sourceMainWindow()) payload.insert(QStringLiteral("windowId"), window->objectName()); } mime->setData(QStringLiteral("application/x-speedcrunch-session-tab"), QJsonDocument(payload).toJson(QJsonDocument::Compact)); QDrag* drag = new QDrag(this); drag->setMimeData(mime); const int currentDragIndex = qMax(0, indexOfDragSession()); drag->setPixmap(grab(tabRect(currentDragIndex))); const QPoint clampedPos = clampTabDragPos(event->pos()); drag->setHotSpot(clampedPos - tabRect(currentDragIndex).topLeft()); QPointer self(this); SessionTabDragGuard dragGuard; const Qt::DropAction dropAction = drag->exec(Qt::MoveAction); if (self == nullptr) return; if (dropAction != Qt::MoveAction && sessionTabDetached && !m_dragSessionName.isEmpty()) sessionTabDetached(m_dragSessionName, QCursor::pos()); m_dragTabIndex = -1; m_dragSessionName.clear(); m_dropIndicatorIndex = -1; update(); } void mouseReleaseEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton && m_visualDragActive) { commitVisualTabDrag(); m_dragTabIndex = -1; m_dragSessionName.clear(); m_visualDragActive = false; m_visualTargetIndex = -1; refreshCloseButtons(); update(); event->accept(); return; } QTabBar::mouseReleaseEvent(event); if (event->button() == Qt::LeftButton) { m_dragTabIndex = -1; m_dragSessionName.clear(); m_visualDragActive = false; m_visualTargetIndex = -1; refreshCloseButtons(); update(); } } void dragEnterEvent(QDragEnterEvent* event) override { if (event->mimeData()->hasFormat(QStringLiteral("application/x-speedcrunch-session-tab"))) { updateDropIndicator(event->position().toPoint()); event->acceptProposedAction(); } } void dragMoveEvent(QDragMoveEvent* event) override { if (event->mimeData()->hasFormat(QStringLiteral("application/x-speedcrunch-session-tab"))) { updateDropIndicator(event->position().toPoint()); event->acceptProposedAction(); } } void dragLeaveEvent(QDragLeaveEvent* event) override { m_dropIndicatorIndex = -1; update(); QTabBar::dragLeaveEvent(event); } void dropEvent(QDropEvent* event) override { const QMimeData* mime = event->mimeData(); if (!mime->hasFormat(QStringLiteral("application/x-speedcrunch-session-tab"))) return; QString sessionName; const QByteArray payload = mime->data(QStringLiteral("application/x-speedcrunch-session-tab")); const QJsonDocument payloadDoc = QJsonDocument::fromJson(payload); if (payloadDoc.isObject()) sessionName = payloadDoc.object().value(QStringLiteral("session")).toString(); if (sessionName.isEmpty()) sessionName = QString::fromUtf8(payload); SessionTabBar* sourceTabBar = dynamic_cast(event->source()); int targetIndex = tabAt(event->position().toPoint()); if (targetIndex < 0) targetIndex = count(); if (sessionTabDropped) sessionTabDropped(sourceTabBar, sessionName, targetIndex); m_dropIndicatorIndex = -1; update(); event->acceptProposedAction(); } void leaveEvent(QEvent* event) override { m_hoveredTabIndex = -1; hideTabToolTip(); setCursor(Qt::ArrowCursor); refreshCloseButtons(); update(); QTabBar::leaveEvent(event); } bool event(QEvent* event) override { if (event->type() == QEvent::HoverMove) { QHoverEvent* hoverEvent = static_cast(event); const QPoint pos = hoverEvent->position().toPoint(); updateHoveredTab(pos); showTabToolTip(pos, mapToGlobal(pos)); } else if (event->type() == QEvent::ToolTip) { QHelpEvent* helpEvent = static_cast(event); showTabToolTip(helpEvent->pos(), helpEvent->globalPos()); return true; } return QTabBar::event(event); } void paintEvent(QPaintEvent* event) override { QPainter tabPainter(this); tabPainter.setRenderHint(QPainter::Antialiasing, true); tabPainter.fillRect(event->rect(), m_tabStripColor); const int visualDragIndex = m_visualDragActive ? indexOfDragSession() : -1; const int draggedWidth = visualDragIndex >= 0 ? tabRect(visualDragIndex).width() : 0; QVector paintedRects(count()); for (int i = 0; i < count(); ++i) { if (i == visualDragIndex) continue; QRect rect = tabRect(i); if (m_visualDragActive && m_visualTargetIndex >= 0) { if (m_visualTargetIndex > visualDragIndex && i > visualDragIndex && i <= m_visualTargetIndex) rect.translate(-draggedWidth, 0); else if (m_visualTargetIndex < visualDragIndex && i >= m_visualTargetIndex && i < visualDragIndex) rect.translate(draggedWidth, 0); } paintedRects[i] = rect; paintTab(&tabPainter, i, rect, false); } for (int i = 0; i + 1 < count(); ++i) { if (i == visualDragIndex || i + 1 == visualDragIndex) continue; if (i == currentIndex() || i + 1 == currentIndex()) continue; if (i == m_hoveredTabIndex || i + 1 == m_hoveredTabIndex) continue; if (paintedRects[i].isEmpty() || paintedRects[i + 1].isEmpty()) continue; const int x = (paintedRects[i].right() + paintedRects[i + 1].left()) / 2; const int top = pillRect(paintedRects[i]).top() + 5; const int bottom = pillRect(paintedRects[i]).bottom() - 5; tabPainter.setPen(QPen(m_hoveredTabColor, 1)); tabPainter.drawLine(QPoint(x, top), QPoint(x, bottom)); } if (visualDragIndex >= 0) { QRect draggedRect = tabRect(visualDragIndex); draggedRect.moveLeft(qRound(m_visualDragLeft)); paintTab(&tabPainter, visualDragIndex, draggedRect, true); } if (m_dropIndicatorIndex < 0) return; int x = width() - 1; if (m_dropIndicatorIndex < count()) x = tabRect(m_dropIndicatorIndex).left(); else if (count() > 0) x = tabRect(count() - 1).right() + 1; QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(QPen(palette().highlight().color(), 2)); painter.drawLine(QPoint(x, 4), QPoint(x, height() - 4)); } QSize tabSizeHint(int index) const override { const int closeExtent = qMax(16, fontMetrics().height() + 1); const int closeWidth = closeExtent + 8; const int width = fontMetrics().horizontalAdvance(tabText(index)) + UiConfig::SessionTabHorizontalPadding + closeWidth + (tabIcon(index).isNull() ? 0 : 22); const int height = qMax(30, fontMetrics().height() + 12); return QSize(width, height); } private: bool eventFilter(QObject* watched, QEvent* event) override { QWidget* watchedWidget = qobject_cast(watched); if (watchedWidget != nullptr && watchedWidget->objectName() == QLatin1String("SessionTabCloseButton")) { switch (event->type()) { case QEvent::Enter: case QEvent::HoverEnter: case QEvent::MouseMove: case QEvent::HoverMove: showCloseButtonToolTip(QCursor::pos()); break; case QEvent::Leave: case QEvent::HoverLeave: hideTabToolTip(); break; case QEvent::ToolTip: { const QHelpEvent* helpEvent = static_cast(event); showCloseButtonToolTip(helpEvent->globalPos()); return true; } default: break; } } return QTabBar::eventFilter(watched, event); } void applyToolTipTheme() { ToolTipStyleUtils::applyPopupTheme( m_toolTipPopup, m_toolTipPopupLabel, this, {m_toolTipBackgroundColor, m_toolTipForegroundColor, m_toolTipOutlineColor, m_toolTipCornerRadius}); } void ensureToolTipPopup() { if (m_toolTipPopup != nullptr) return; m_toolTipPopup = ToolTipStyleUtils::createPopup( this, QStringLiteral("sessionTabToolTipPopup"), QStringLiteral("sessionTabToolTipPopupLabel"), Qt::PlainText, &m_toolTipPopupLabel, true); applyToolTipTheme(); } void hideTabToolTip() { if (m_toolTipPopup != nullptr) m_toolTipPopup->hide(); } void showTabToolTip(const QPoint& pos, const QPoint& globalPos) { const int index = tabAt(pos); if (index < 0) { hideTabToolTip(); return; } QWidget* closeButton = tabButton(index, QTabBar::RightSide); if (closeButton != nullptr && closeButton->rect().contains(closeButton->mapFromGlobal(globalPos))) { hideTabToolTip(); return; } const QString text = tabToolTip(index).isEmpty() ? tabText(index) : tabToolTip(index); if (tabIcon(index).isNull() && fontMetrics().horizontalAdvance(text) <= tabTextRect(index, tabRect(index)).width()) { hideTabToolTip(); return; } ensureToolTipPopup(); ToolTipStyleUtils::showPopup(m_toolTipPopup, m_toolTipPopupLabel, text, this, globalPos, m_toolTipCornerRadius); } void showCloseButtonToolTip(const QPoint& globalPos) { ensureToolTipPopup(); ToolTipStyleUtils::showPopup(m_toolTipPopup, m_toolTipPopupLabel, MainWindow::tr("Close Session"), this, globalPos, m_toolTipCornerRadius); } QRect tabTextRect(int index, const QRect& rect) const { const int rightButtonWidth = tabButton(index, QTabBar::RightSide) != nullptr && tabButton(index, QTabBar::RightSide)->isVisible() ? tabButton(index, QTabBar::RightSide)->width() + 6 : 0; return pillRect(rect).adjusted(12 + (tabIcon(index).isNull() ? 0 : 22), 0, -12 - rightButtonWidth, 0); } void updateHoveredTab(const QPoint& pos) { const int hoveredTabIndex = tabAt(pos); if (m_hoveredTabIndex != hoveredTabIndex) { m_hoveredTabIndex = hoveredTabIndex; refreshCloseButtons(); update(); } setCursor(hoveredTabIndex >= 0 ? Qt::PointingHandCursor : Qt::ArrowCursor); } QRect pillRect(const QRect& tabRect) const { return tabRect.adjusted(2, 3, -2, 0); } QPainterPath topRoundedTabPath(const QRect& rect) const { const QRectF tab(rect); const qreal radius = qMin(qreal(UiConfig::ControlCornerRadius), qMin(tab.width() / 2.0, tab.height() / 2.0)); QPainterPath path; path.moveTo(tab.left(), tab.bottom()); path.lineTo(tab.left(), tab.top() + radius); path.quadTo(tab.left(), tab.top(), tab.left() + radius, tab.top()); path.lineTo(tab.right() - radius, tab.top()); path.quadTo(tab.right(), tab.top(), tab.right(), tab.top() + radius); path.lineTo(tab.right(), tab.bottom()); path.closeSubpath(); return path; } void paintTab(QPainter* painter, int index, const QRect& rect, bool dragged) const { if (index < 0 || index >= count() || rect.isEmpty()) return; const bool selected = index == currentIndex(); const bool hovered = index == m_hoveredTabIndex && !m_visualDragActive; const QRect pill = pillRect(rect); if (selected || hovered || dragged) { const QColor fill = selected ? m_selectedTabColor : (hovered || dragged ? m_hoveredTabColor : m_inactiveTabColor); painter->setPen(Qt::NoPen); painter->setBrush(fill); painter->drawPath(topRoundedTabPath(pill)); } if (selected && m_activePaneSelectedTabIndicatorColor.isValid()) { const int strokeWidth = UiConfig::ActiveSessionTabIndicatorStrokeWidth; const qreal y = pill.bottom() - (strokeWidth - 1) / 2.0; painter->setPen(QPen(m_activePaneSelectedTabIndicatorColor, strokeWidth, Qt::SolidLine, Qt::SquareCap)); painter->setBrush(Qt::NoBrush); painter->drawLine(QPointF(pill.left(), y), QPointF(pill.right(), y)); } const QRect textRect = tabTextRect(index, rect); if (!tabIcon(index).isNull()) { const QRect iconRect(textRect.left() - 22, textRect.center().y() - 8, 16, 16); tabIcon(index).paint(painter, iconRect); } painter->setPen(selected ? m_selectedTextColor : (hovered ? m_hoveredTextColor : m_tabTextColor)); painter->setFont(font()); painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, fontMetrics().elidedText(tabText(index), elideMode(), textRect.width())); } void updateDropIndicator(const QPoint& pos) { int index = tabAt(clampDropPos(pos)); if (index < 0) { if (count() > 0 && pos.x() < tabRect(0).left()) index = 0; else index = count(); } if (index < 0) index = count(); else if (clampDropPos(pos).x() > tabRect(index).center().x()) ++index; if (m_dropIndicatorIndex != index) { m_dropIndicatorIndex = index; update(); } } bool shouldStartCrossBarDrag(const QPoint& pos, const QPoint& globalPos) const { if (count() == 0) return true; const int detachDistance = QApplication::startDragDistance(); if (pos.y() < -detachDistance || pos.y() >= height() + detachDistance) return true; QWidget* topLevel = window(); return topLevel != nullptr && !topLevel->frameGeometry().contains(globalPos); } QPoint clampTabDragPos(const QPoint& pos) const { if (count() == 0) return pos; return QPoint(qBound(tabRect(0).left(), pos.x(), tabRect(count() - 1).right()), qBound(0, pos.y(), height() - 1)); } QPoint clampDropPos(const QPoint& pos) const { if (count() == 0) return pos; return QPoint(qBound(tabRect(0).left(), pos.x(), tabRect(count() - 1).right()), qBound(0, pos.y(), height() - 1)); } int visualTargetIndexForDrag(qreal visualLeft, int draggedWidth) const { const int sourceIndex = indexOfDragSession(); if (sourceIndex < 0 || sourceIndex >= count()) return -1; int targetIndex = sourceIndex; if (visualLeft < tabRect(sourceIndex).left()) { while (targetIndex > 0 && visualLeft < tabRect(targetIndex - 1).center().x()) --targetIndex; } else { const qreal visualRight = visualLeft + draggedWidth; while (targetIndex + 1 < count() && visualRight > tabRect(targetIndex + 1).center().x()) ++targetIndex; } return qBound(0, targetIndex, count() - 1); } void updateDraggedTabVisual(const QPoint& pos) { const int index = indexOfDragSession(); if (index < 0 || index >= count()) return; const int leftLimit = count() > 0 ? tabRect(0).left() : 0; const int rightLimit = count() > 0 ? tabRect(count() - 1).right() - tabRect(index).width() + 1 : width(); const int clampedRightLimit = qMax(leftLimit, rightLimit); m_visualDragActive = true; m_visualDragLeft = qBound(leftLimit, pos.x() - m_dragTabPressOffsetX, clampedRightLimit); m_visualTargetIndex = visualTargetIndexForDrag(m_visualDragLeft, tabRect(index).width()); update(); } void commitVisualTabDrag() { int index = indexOfDragSession(); if (index < 0 || index >= count()) return; if (m_visualTargetIndex < 0 || m_visualTargetIndex == index) return; moveTab(index, m_visualTargetIndex); m_dragTabIndex = m_visualTargetIndex; setCurrentIndex(m_visualTargetIndex); } int m_dragTabPressOffsetX = 0; int m_dragTabIndex = -1; int m_hoveredTabIndex = -1; int m_dropIndicatorIndex = -1; bool m_visualDragActive = false; qreal m_visualDragLeft = 0.0; int m_visualTargetIndex = -1; QColor m_tabStripColor; QColor m_inactiveTabColor; QColor m_hoveredTabColor; QColor m_selectedTabColor; QColor m_activePaneSelectedTabIndicatorColor; QColor m_tabTextColor; QColor m_hoveredTextColor; QColor m_selectedTextColor; QColor m_closeButtonHoverColor; QColor m_closeButtonHoverTextColor; QColor m_toolTipBackgroundColor; QColor m_toolTipForegroundColor; QColor m_toolTipOutlineColor; int m_toolTipCornerRadius = 0; QFrame* m_toolTipPopup = nullptr; QLabel* m_toolTipPopupLabel = nullptr; QString m_dragSessionName; int indexOfDragSession() const { for (int i = 0; i < count(); ++i) { if (tabText(i) == m_dragSessionName) return i; } return m_dragTabIndex; } }; enum class PaneDropZone { Center, Top, Bottom, Left, Right }; class SessionPane : public QWidget { public: explicit SessionPane(QWidget* parent = nullptr) : QWidget(parent) { setObjectName(QStringLiteral("SessionPane")); setAcceptDrops(true); m_overlay = new QWidget(this); m_overlay->setAttribute(Qt::WA_TransparentForMouseEvents); m_overlay->setStyleSheet(QStringLiteral("background: rgba(0, 0, 0, 80);")); m_overlay->hide(); } std::function sessionTabDroppedOnPane; std::function shouldShowOverlayForDrag; std::function paneActivated; void setOverlayAreaWidget(QWidget* widget) { m_overlayAreaWidget = widget; } PaneDropZone dropZoneForPanePosition(const QPoint& panePos) const { return dropZoneForPosition(panePos); } void watchDropTarget(QWidget* widget) { if (widget == nullptr) return; widget->installEventFilter(this); widget->setAcceptDrops(true); } protected: void mousePressEvent(QMouseEvent* event) override { if (paneActivated) paneActivated(); QWidget::mousePressEvent(event); } void dragEnterEvent(QDragEnterEvent* event) override { if (acceptSessionTabDrag(event)) return; QWidget::dragEnterEvent(event); } void dragMoveEvent(QDragMoveEvent* event) override { if (acceptSessionTabDrag(event, event->position().toPoint())) return; QWidget::dragMoveEvent(event); } void dropEvent(QDropEvent* event) override { if (handleSessionTabDrop(event, event->position().toPoint())) return; QWidget::dropEvent(event); } void dragLeaveEvent(QDragLeaveEvent* event) override { hideOverlay(); QWidget::dragLeaveEvent(event); } void resizeEvent(QResizeEvent* event) override { if (m_overlay != nullptr) m_overlay->setGeometry(overlayRect(PaneDropZone::Center)); QWidget::resizeEvent(event); } bool eventFilter(QObject* watched, QEvent* event) override { QWidget* watchedWidget = qobject_cast(watched); if (watchedWidget == nullptr) return QWidget::eventFilter(watched, event); if (event->type() == QEvent::DragEnter) { QDragEnterEvent* dragEvent = static_cast(event); return acceptSessionTabDrag(dragEvent); } if (event->type() == QEvent::DragMove) { QDragMoveEvent* dragEvent = static_cast(event); return acceptSessionTabDrag(dragEvent, watchedWidget->mapTo(this, dragEvent->position().toPoint())); } if (event->type() == QEvent::Drop) { QDropEvent* dropEvent = static_cast(event); return handleSessionTabDrop(dropEvent, watchedWidget->mapTo(this, dropEvent->position().toPoint())); } if (event->type() == QEvent::DragLeave) { hideOverlay(); return false; } if (event->type() == QEvent::MouseButtonPress) { if (paneActivated) paneActivated(); return false; } return QWidget::eventFilter(watched, event); } private: bool acceptSessionTabDrag(QDragMoveEvent* event, const QPoint& panePos = QPoint()) { if (!event->mimeData()->hasFormat(QStringLiteral("application/x-speedcrunch-session-tab"))) return false; SessionTabBar* sourceTabBar = dynamic_cast(event->source()); if (shouldShowOverlayForDrag && !shouldShowOverlayForDrag(sourceTabBar)) { hideOverlay(); event->acceptProposedAction(); return true; } updateOverlay(panePos.isNull() ? event->position().toPoint() : panePos); event->acceptProposedAction(); return true; } bool handleSessionTabDrop(QDropEvent* event, const QPoint& panePos) { const QMimeData* mime = event->mimeData(); if (!mime->hasFormat(QStringLiteral("application/x-speedcrunch-session-tab"))) return false; QString sessionName; const QByteArray payload = mime->data(QStringLiteral("application/x-speedcrunch-session-tab")); const QJsonDocument payloadDoc = QJsonDocument::fromJson(payload); if (payloadDoc.isObject()) sessionName = payloadDoc.object().value(QStringLiteral("session")).toString(); if (sessionName.isEmpty()) sessionName = QString::fromUtf8(payload); SessionTabBar* sourceTabBar = dynamic_cast(event->source()); if (sourceTabBar == nullptr || sessionName.isEmpty()) return false; hideOverlay(); if (sessionTabDroppedOnPane) sessionTabDroppedOnPane(sourceTabBar, sessionName, panePos); event->acceptProposedAction(); return true; } void updateOverlay(const QPoint& panePos) { if (m_overlay == nullptr) return; m_overlay->setGeometry(overlayRect(dropZoneForPosition(panePos))); m_overlay->raise(); m_overlay->show(); } void hideOverlay() { if (m_overlay != nullptr) m_overlay->hide(); } PaneDropZone dropZoneForPosition(const QPoint& panePos) const { const QPointF pos(panePos); const QRect rect = overlayBounds(); const QPointF center(rect.center()); const QPointF top(rect.left() + rect.width() / 2.0, rect.top()); const QPointF bottom(rect.left() + rect.width() / 2.0, rect.bottom()); const QPointF left(rect.left(), rect.top() + rect.height() / 2.0); const QPointF right(rect.right(), rect.top() + rect.height() / 2.0); const auto distanceSquared = [&pos](const QPointF& point) { const QPointF delta = pos - point; return delta.x() * delta.x() + delta.y() * delta.y(); }; PaneDropZone zone = PaneDropZone::Center; qreal bestDistance = distanceSquared(center); const auto consider = [&bestDistance, &zone, &distanceSquared](PaneDropZone candidate, const QPointF& point) { const qreal distance = distanceSquared(point); if (distance < bestDistance) { bestDistance = distance; zone = candidate; } }; consider(PaneDropZone::Top, top); consider(PaneDropZone::Bottom, bottom); consider(PaneDropZone::Left, left); consider(PaneDropZone::Right, right); return zone; } QRect overlayRect(PaneDropZone zone) const { const QRect rect = overlayBounds(); switch (zone) { case PaneDropZone::Center: return rect; case PaneDropZone::Top: return QRect(rect.left(), rect.top(), rect.width(), rect.height() / 2); case PaneDropZone::Bottom: return QRect(rect.left(), rect.top() + rect.height() / 2, rect.width(), rect.height() - rect.height() / 2); case PaneDropZone::Left: return QRect(rect.left(), rect.top(), rect.width() / 2, rect.height()); case PaneDropZone::Right: return QRect(rect.left() + rect.width() / 2, rect.top(), rect.width() - rect.width() / 2, rect.height()); } return rect; } QRect overlayBounds() const { if (m_overlayAreaWidget == nullptr) return this->rect(); const QPoint topLeft = m_overlayAreaWidget->mapTo(this, QPoint(0, 0)); return QRect(topLeft, m_overlayAreaWidget->size()); } QWidget* m_overlay = nullptr; QWidget* m_overlayAreaWidget = nullptr; }; QWidget* paneWidgetForDisplay(ResultDisplay* display) { QWidget* widget = display; while (widget != nullptr && !qobject_cast(widget->parentWidget())) widget = widget->parentWidget(); return widget; } bool splitAssignmentDescriptionForImport(const QString& expression, QString* expressionWithoutDescription, QString* description = nullptr) { const int equalsPos = expression.indexOf(MathDsl::Equals); if (equalsPos < 0) return false; int depth = 0; const int n = expression.size(); for (int i = equalsPos + 1; i < n; ++i) { const QChar ch = expression.at(i); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd && depth > 0) { --depth; } else if (ch == MathDsl::CommentSep && depth == 0) { *expressionWithoutDescription = expression.left(i).trimmed(); if (description) *description = expression.mid(i + 1).trimmed(); return true; } } return false; } AssignmentTarget assignmentTargetFromExpression(Evaluator* evaluator, const QString& expression) { AssignmentTarget target; if (!evaluator) return target; QString expressionToParse = expression; splitAssignmentDescriptionForImport(expression, &expressionToParse); Tokens tokens = evaluator->scan(expressionToParse); if (!tokens.valid()) return target; if (tokens.count() > 2 && tokens.at(0).isIdentifier() && tokens.at(1).asOperator() == Token::Assignment) { target.identifier = tokens.at(0).text(); target.valid = true; return target; } if (tokens.count() > 4 && tokens.at(0).asOperator() == Token::AssociationStart && tokens.at(0).text() == QString(MathDsl::UnitStart) && tokens.at(1).isUnitIdentifier() && tokens.at(2).asOperator() == Token::AssociationEnd && tokens.at(2).text() == QString(MathDsl::UnitEnd) && tokens.at(3).asOperator() == Token::Assignment) { target.identifier = tokens.at(1).text(); target.isUnit = true; target.valid = true; return target; } if (tokens.count() > 2 && tokens.at(0).isIdentifier() && tokens.at(1).asOperator() == Token::AssociationStart && tokens.at(1).text() == QLatin1String("(")) { bool assignFunc = false; int t = 0; if (tokens.count() > 4 && tokens.at(2).asOperator() == Token::AssociationEnd && tokens.at(2).text() == QLatin1String(")")) { t = 3; if (tokens.at(3).asOperator() == Token::Assignment) assignFunc = true; } else { for (t = 2; t + 1 < tokens.count(); t += 2) { if (!tokens.at(t).isIdentifier()) break; if (tokens.at(t + 1).asOperator() == Token::AssociationEnd && tokens.at(t + 1).text() == QLatin1String(")")) { t += 2; if (t < tokens.count() && tokens.at(t).asOperator() == Token::Assignment) { assignFunc = true; } break; } else if (tokens.at(t + 1).asOperator() != Token::ListSeparator) { break; } } } if (assignFunc) { target.identifier = tokens.at(0).text(); target.isFunction = true; target.valid = true; } } return target; } bool findUserFunctionByName(const QList& functions, const QString& name, UserFunction* function) { for (const UserFunction& candidate : functions) { if (candidate.name() == name) { if (function) *function = candidate; return true; } } return false; } QString normalizedDisplaySelectionForEvaluation(QString selected) { selected.replace(QChar::ParagraphSeparator, QLatin1Char('\n')); const QStringList rawLines = selected.split(QLatin1Char('\n'), Qt::SkipEmptyParts); QStringList candidateLines; candidateLines.reserve(rawLines.size()); for (const QString& rawLine : rawLines) { const QString line = rawLine.trimmed(); if (line.isEmpty()) continue; if (line.startsWith(QLatin1String("="))) continue; candidateLines.append(line); } if (!candidateLines.isEmpty()) return candidateLines.join(QLatin1Char(' ')); for (const QString& rawLine : rawLines) { QString line = rawLine.trimmed(); if (line.startsWith(QLatin1String("="))) line = line.mid(1).trimmed(); if (!line.isEmpty()) return line; } return selected.trimmed(); } } // namespace void MainWindow::createUi() { createActions(); createActionGroups(); createActionShortcuts(); createMenus(); createFixedWidgets(); createFixedConnections(); setWindowTitle("SpeedCrunch"); setWindowIcon(QPixmap(":/speedcrunch.png")); m_copyWidget = m_widgets.editor; syncEditMenuActionState(); syncSessionMenuActionState(); } void MainWindow::createActions() { StartupDiagnostics::Scope timing("Create actions"); m_actions.sessionExportHtml = new QAction(this); m_actions.sessionExportJson = new QAction(this); m_actions.sessionExportPlainText = new QAction(this); m_actions.sessionImport = new QAction(this); m_actions.sessionImportUserDefinitions = new QAction(this); m_actions.sessionNewTab = new QAction(this); m_actions.sessionNewPrivate = new QAction(this); m_actions.sessionConvertPrivacy = new QAction(this); m_actions.sessionNewWindow = new QAction(this); m_actions.sessionOpen = new QAction(this); m_actions.sessionRename = new QAction(this); m_actions.sessionClone = new QAction(this); m_actions.sessionClose = new QAction(this); m_actions.sessionReopen = new QAction(this); m_actions.sessionOpenSessionsFolder = new QAction(this); m_actions.sessionQuit = new QAction(this); m_actions.editUndo = new QAction(this); m_actions.editRedo = new QAction(this); m_actions.editCut = new QAction(this); m_actions.editClearExpression = new QAction(this); m_actions.editClearHistory = new QAction(this); m_actions.editCopyLastResult = new QAction(this); m_actions.editCopy = new QAction(this); m_actions.editPaste = new QAction(this); m_actions.editSelectExpression = new QAction(this); m_actions.editWrapSelection = new QAction(this); m_actions.viewConstants = new QAction(this); m_actions.viewFullScreenMode = new QAction(this); m_actions.viewFunctions = new QAction(this); m_actions.viewHistory = new QAction(this); m_actions.viewKeypadDisabled = new QAction(this); m_actions.viewKeypadBasicWide = new QAction(this); m_actions.viewKeypadScientificWide = new QAction(this); m_actions.viewKeypadScientificNarrow = new QAction(this); m_actions.viewKeypadCustom = new QAction(this); m_actions.viewKeypadZoom50 = new QAction(this); m_actions.viewKeypadZoom100 = new QAction(this); m_actions.viewKeypadZoom150 = new QAction(this); m_actions.viewKeypadZoom200 = new QAction(this); m_actions.viewFormulaBook = new QAction(this); m_actions.viewStatusBar = new QAction(this); m_actions.viewMenuBar = new QAction(this); m_actions.viewVariables = new QAction(this); m_actions.viewBitfield = new QAction(this); m_actions.viewSplitLeft = new QAction(this); m_actions.viewSplitRight = new QAction(this); m_actions.viewSplitUp = new QAction(this); m_actions.viewSplitDown = new QAction(this); m_actions.viewClosePane = new QAction(this); m_actions.viewUserFunctions = new QAction(this); m_actions.viewUserUnits = new QAction(this); m_actions.settingsAngleUnitDegree = new QAction(this); m_actions.settingsAngleUnitRadian = new QAction(this); m_actions.settingsAngleUnitGradian = new QAction(this); m_actions.settingsAngleUnitTurn = new QAction(this); m_actions.settingsAngleUnitRevolution = new QAction(this); m_actions.settingsBehaviorAlwaysOnTop = new QAction(this); m_actions.settingsOpenPrivateTabOnStartup = new QAction(this); m_actions.settingsBehaviorAutoAns = new QAction(this); m_actions.settingsBehaviorAutoCompletion = new QAction(this); m_actions.settingsBehaviorAutoCompletionAcceptWithEnter = new QAction(this); m_actions.settingsBehaviorAutoCompletionAcceptWithEnter->setObjectName(QStringLiteral("AutoCompletionAcceptWithEnterAction")); m_actions.settingsBehaviorAutoCompletionBuiltInFunctions = new QAction(this); m_actions.settingsBehaviorAutoCompletionBuiltInVariables = new QAction(this); m_actions.settingsBehaviorAutoCompletionLongFormUnits = new QAction(this); m_actions.settingsBehaviorAutoCompletionUserFunctions = new QAction(this); m_actions.settingsBehaviorAutoCompletionUserVariables = new QAction(this); m_actions.settingsBehaviorLeaveLastExpression = new QAction(this); m_actions.settingsBehaviorNumberFormat = new QAction(this); m_actions.settingsResetAll = new QAction(this); m_actions.settingsResetAll->setObjectName(QStringLiteral("ResetAllSettingsAction")); m_actions.settingsBehaviorResultSlots = new QAction(this); m_actions.settingsBehaviorUpDownArrowNever = new QAction(this); m_actions.settingsBehaviorUpDownArrowAlways = new QAction(this); m_actions.settingsBehaviorUpDownArrowSingleLineOnly = new QAction(this); m_actions.settingsBehaviorPartialResults = new QAction(this); m_actions.settingsBehaviorSaveWindowPositionOnExit = new QAction(this); m_actions.settingsBehaviorSyntaxHighlighting = new QAction(this); m_actions.settingsEditingInputDigitGrouping = new QAction(this); m_actions.settingsEditingAutomaticInputAdjustments = new QAction(this); m_actions.settingsEditingAutomaticInputAdjustments->setObjectName(QStringLiteral("AutomaticInputAdjustmentsAction")); m_actions.settingsEditingInputDigitGrouping->setObjectName(QStringLiteral("InputDigitGroupingAction")); m_actions.settingsEditingCursorBlinking = new QAction(this); m_actions.settingsEditingCursorBlinking->setObjectName(QStringLiteral("CursorBlinkingAction")); m_actions.settingsEditingEscapeClearsEditor = new QAction(this); m_actions.settingsEditingEscapeClearsEditor->setObjectName(QStringLiteral("EscapeClearsEditorAction")); m_actions.settingsBehaviorHoverHighlightResults = new QAction(this); m_actions.settingsBehaviorDigitGroupingNone = new QAction(this); m_actions.settingsBehaviorDigitGroupingOneSpace = new QAction(this); m_actions.settingsBehaviorDigitGroupingTwoSpaces = new QAction(this); m_actions.settingsBehaviorDigitGroupingThreeSpaces = new QAction(this); m_actions.settingsBehaviorDigitGroupingIntegerPartOnly = new QAction(this); m_actions.settingsBehaviorAutoResultToClipboard = new QAction(this); m_actions.settingsBehaviorSimplifyResultExpressions = new QAction(this); m_actions.settingsBehaviorHistorySizeLimit = new QAction(this); m_actions.settingsDisplayFont = new QAction(this); m_actions.settingsDisplayColorSchemeCustom = new QAction(this); m_actions.settingsMenuAppearanceSystem = new QAction(this); m_actions.settingsMenuAppearanceSpeedCrunch = new QAction(this); m_actions.settingsMenuAppearanceSystem->setCheckable(true); m_actions.settingsMenuAppearanceSystem->setData(Settings::MenuAppearanceSystem); m_actions.settingsMenuAppearanceSpeedCrunch->setCheckable(true); m_actions.settingsMenuAppearanceSpeedCrunch->setData(Settings::MenuAppearanceSpeedCrunch); m_actions.settingsDockAppearanceSystem = new QAction(this); m_actions.settingsDockAppearanceSpeedCrunch = new QAction(this); m_actions.settingsDockAppearanceSystem->setCheckable(true); m_actions.settingsDockAppearanceSystem->setData(Settings::DockAppearanceSystem); m_actions.settingsDockAppearanceSpeedCrunch->setCheckable(true); m_actions.settingsDockAppearanceSpeedCrunch->setData(Settings::DockAppearanceSpeedCrunch); m_actions.settingsStatusBarAppearanceSystem = new QAction(this); m_actions.settingsStatusBarAppearanceSpeedCrunch = new QAction(this); m_actions.settingsStatusBarAppearanceSystem->setCheckable(true); m_actions.settingsStatusBarAppearanceSystem->setData(Settings::StatusBarAppearanceSystem); m_actions.settingsStatusBarAppearanceSpeedCrunch->setCheckable(true); m_actions.settingsStatusBarAppearanceSpeedCrunch->setData(Settings::StatusBarAppearanceSpeedCrunch); m_actions.settingsKeypadAppearanceClassic = new QAction(this); m_actions.settingsKeypadAppearanceClassic->setCheckable(true); m_actions.settingsKeypadAppearanceClassic->setData(Settings::KeypadAppearanceClassic); m_actions.settingsKeypadAppearanceModern = new QAction(this); m_actions.settingsKeypadAppearanceModern->setCheckable(true); m_actions.settingsKeypadAppearanceModern->setData(Settings::KeypadAppearanceModern); m_actions.settingsEditorDisplayClassic = new QAction(this); m_actions.settingsEditorDisplayClassic->setCheckable(true); m_actions.settingsEditorDisplayClassic->setData(Settings::EditorDisplayClassic); m_actions.settingsEditorDisplayModern = new QAction(this); m_actions.settingsEditorDisplayModern->setCheckable(true); m_actions.settingsEditorDisplayModern->setData(Settings::EditorDisplayModern); m_actions.settingsLanguage = new QAction(this); m_actions.settingsRadixCharComma = new QAction(this); m_actions.settingsRadixCharDefault = new QAction(this); m_actions.settingsRadixCharDot = new QAction(this); m_actions.settingsRadixCharBoth = new QAction(this); m_actions.settingsResultFormat0Digits = new QAction(this); m_actions.settingsResultFormat15Digits = new QAction(this); m_actions.settingsResultFormat2Digits = new QAction(this); m_actions.settingsResultFormat3Digits = new QAction(this); m_actions.settingsResultFormat50Digits = new QAction(this); m_actions.settingsResultFormat8Digits = new QAction(this); m_actions.settingsResultFormatCustomDigits = new QAction(this); m_actions.settingsResultRoundingHalfAwayFromZero = new QAction(this); m_actions.settingsResultRoundingHalfEven = new QAction(this); m_actions.settingsResultRoundingTowardZero = new QAction(this); m_actions.settingsResultRoundingTowardPositiveInfinity = new QAction(this); m_actions.settingsResultRoundingTowardNegativeInfinity = new QAction(this); m_actions.settingsResultFormatAutoPrecision = new QAction(this); m_actions.settingsResultFormatBinary = new QAction(this); m_actions.settingsResultFormatEngineering = new QAction(this); m_actions.settingsRemoveTrailingZeroes = new QAction(this); m_actions.settingsRemoveTrailingZeroes->setObjectName(QStringLiteral("RemoveTrailingZeroesAction")); m_actions.settingsRemoveTrailingZeroes->setCheckable(true); m_actions.settingsResultFormatFixed = new QAction(this); m_actions.settingsResultFormatGeneral = new QAction(this); m_actions.settingsResultFormatHexadecimal = new QAction(this); m_actions.settingsResultFormatOctal = new QAction(this); m_actions.settingsResultFormatRational = new QAction(this); m_actions.settingsResultFormatScientific = new QAction(this); m_actions.settingsResultFormatCartesian= new QAction(this); m_actions.settingsResultFormatPolar = new QAction(this); m_actions.settingsResultFormatTrigonometric = new QAction(this); m_actions.settingsResultFormatCis = new QAction(this); m_actions.settingsResultFormatPolarAngle = new QAction(this); m_actions.settingsImaginaryUnitI = new QAction(this); m_actions.settingsImaginaryUnitJ = new QAction(this); m_actions.settingsResultFormatSexagesimal = new QAction(this); m_actions.settingsUnitNegativeExponentSuperscript = new QAction(this); m_actions.settingsUnitNegativeExponentFraction = new QAction(this); m_actions.helpManual = new QAction(this); #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS m_actions.helpUpdates = new QAction(this); #endif m_actions.helpFeedback = new QAction(this); m_actions.helpCommunity = new QAction(this); m_actions.helpSource = new QAction(this); m_actions.helpDonate = new QAction(this); m_actions.helpAbout = new QAction(this); m_actions.helpDiagnostics = new QAction(this); m_actions.helpDiagnostics->setObjectName(QStringLiteral("AppDiagnosticsAction")); m_actions.helpDiagnostics->setMenuRole(QAction::NoRole); m_actions.contextHelp = new QAction(this); m_actions.settingsAngleUnitDegree->setCheckable(true); m_actions.settingsAngleUnitRadian->setCheckable(true); m_actions.settingsAngleUnitGradian->setCheckable(true); m_actions.settingsAngleUnitTurn->setCheckable(true); m_actions.settingsAngleUnitRevolution->setCheckable(true); m_actions.settingsBehaviorAlwaysOnTop->setCheckable(true); m_actions.settingsOpenPrivateTabOnStartup->setCheckable(true); m_actions.settingsBehaviorAutoAns->setCheckable(true); m_actions.settingsBehaviorAutoCompletion->setCheckable(true); m_actions.settingsBehaviorAutoCompletionAcceptWithEnter->setCheckable(true); m_actions.settingsBehaviorAutoCompletionBuiltInFunctions->setCheckable(true); m_actions.settingsBehaviorAutoCompletionBuiltInVariables->setCheckable(true); m_actions.settingsBehaviorAutoCompletionLongFormUnits->setCheckable(true); m_actions.settingsBehaviorAutoCompletionUserFunctions->setCheckable(true); m_actions.settingsBehaviorAutoCompletionUserVariables->setCheckable(true); m_actions.settingsBehaviorLeaveLastExpression->setCheckable(true); m_actions.settingsBehaviorUpDownArrowNever->setCheckable(true); m_actions.settingsBehaviorUpDownArrowNever->setData(Settings::UpDownArrowBehaviorNever); m_actions.settingsBehaviorUpDownArrowAlways->setCheckable(true); m_actions.settingsBehaviorUpDownArrowAlways->setData(Settings::UpDownArrowBehaviorAlways); m_actions.settingsBehaviorUpDownArrowSingleLineOnly->setCheckable(true); m_actions.settingsBehaviorUpDownArrowSingleLineOnly->setData(Settings::UpDownArrowBehaviorSingleLineOnly); m_actions.settingsBehaviorPartialResults->setCheckable(true); m_actions.settingsBehaviorSaveWindowPositionOnExit->setCheckable(true); m_actions.settingsBehaviorSyntaxHighlighting->setCheckable(true); m_actions.settingsEditingInputDigitGrouping->setCheckable(true); m_actions.settingsEditingAutomaticInputAdjustments->setCheckable(true); m_actions.settingsEditingCursorBlinking->setCheckable(true); m_actions.settingsEditingEscapeClearsEditor->setCheckable(true); m_actions.settingsBehaviorHoverHighlightResults->setCheckable(true); m_actions.settingsBehaviorDigitGroupingNone->setCheckable(true); m_actions.settingsBehaviorDigitGroupingNone->setData(0); m_actions.settingsBehaviorDigitGroupingOneSpace->setCheckable(true); m_actions.settingsBehaviorDigitGroupingOneSpace->setData(1); m_actions.settingsBehaviorDigitGroupingTwoSpaces->setCheckable(true); m_actions.settingsBehaviorDigitGroupingTwoSpaces->setData(2); m_actions.settingsBehaviorDigitGroupingThreeSpaces->setCheckable(true); m_actions.settingsBehaviorDigitGroupingThreeSpaces->setData(3); m_actions.settingsBehaviorDigitGroupingIntegerPartOnly->setCheckable(true); m_actions.settingsBehaviorAutoResultToClipboard->setCheckable(true); m_actions.settingsBehaviorSimplifyResultExpressions->setCheckable(true); m_actions.settingsRadixCharComma->setCheckable(true); m_actions.settingsRadixCharDefault->setCheckable(true); m_actions.settingsRadixCharDot->setCheckable(true); m_actions.settingsRadixCharBoth->setCheckable(true); m_actions.settingsResultFormat0Digits->setCheckable(true); m_actions.settingsResultFormat15Digits->setCheckable(true); m_actions.settingsResultFormat2Digits->setCheckable(true); m_actions.settingsResultFormat3Digits->setCheckable(true); m_actions.settingsResultFormat50Digits->setCheckable(true); m_actions.settingsResultFormat8Digits->setCheckable(true); m_actions.settingsResultFormatCustomDigits->setCheckable(true); m_actions.settingsResultRoundingHalfAwayFromZero->setCheckable(true); m_actions.settingsResultRoundingHalfAwayFromZero->setData(Settings::ResultRoundingHalfAwayFromZero); m_actions.settingsResultRoundingHalfEven->setCheckable(true); m_actions.settingsResultRoundingHalfEven->setData(Settings::ResultRoundingHalfEven); m_actions.settingsResultRoundingTowardZero->setCheckable(true); m_actions.settingsResultRoundingTowardZero->setData(Settings::ResultRoundingTowardZero); m_actions.settingsResultRoundingTowardPositiveInfinity->setCheckable(true); m_actions.settingsResultRoundingTowardPositiveInfinity->setData(Settings::ResultRoundingTowardPositiveInfinity); m_actions.settingsResultRoundingTowardNegativeInfinity->setCheckable(true); m_actions.settingsResultRoundingTowardNegativeInfinity->setData(Settings::ResultRoundingTowardNegativeInfinity); m_actions.settingsResultFormatAutoPrecision->setCheckable(true); m_actions.settingsResultFormatBinary->setCheckable(true); m_actions.settingsResultFormatCartesian->setCheckable(true); m_actions.settingsResultFormatEngineering->setCheckable(true); m_actions.settingsResultFormatFixed->setCheckable(true); m_actions.settingsResultFormatGeneral->setCheckable(true); m_actions.settingsResultFormatHexadecimal->setCheckable(true); m_actions.settingsResultFormatOctal->setCheckable(true); m_actions.settingsResultFormatPolar->setCheckable(true); m_actions.settingsResultFormatTrigonometric->setCheckable(true); m_actions.settingsResultFormatCis->setCheckable(true); m_actions.settingsResultFormatPolarAngle->setCheckable(true); m_actions.settingsImaginaryUnitI->setCheckable(true); m_actions.settingsImaginaryUnitJ->setCheckable(true); m_actions.settingsResultFormatRational->setCheckable(true); m_actions.settingsResultFormatScientific->setCheckable(true); m_actions.settingsResultFormatSexagesimal->setCheckable(true); m_actions.settingsUnitNegativeExponentSuperscript->setCheckable(true); m_actions.settingsUnitNegativeExponentSuperscript->setData( static_cast(Settings::UnitNegativeExponentSuperscript)); m_actions.settingsUnitNegativeExponentFraction->setCheckable(true); m_actions.settingsUnitNegativeExponentFraction->setData( static_cast(Settings::UnitNegativeExponentFraction)); m_actions.viewConstants->setCheckable(true); m_actions.viewFullScreenMode->setCheckable(true); m_actions.viewFunctions->setCheckable(true); m_actions.viewHistory->setCheckable(true); m_actions.viewKeypadDisabled->setCheckable(true); m_actions.viewKeypadDisabled->setData(Settings::KeypadModeDisabled); m_actions.viewKeypadBasicWide->setCheckable(true); m_actions.viewKeypadBasicWide->setData(Settings::KeypadModeBasicWide); m_actions.viewKeypadScientificWide->setCheckable(true); m_actions.viewKeypadScientificWide->setData(Settings::KeypadModeScientificWide); m_actions.viewKeypadScientificNarrow->setCheckable(true); m_actions.viewKeypadScientificNarrow->setData(Settings::KeypadModeScientificNarrow); m_actions.viewKeypadCustom->setCheckable(true); m_actions.viewKeypadCustom->setData(Settings::KeypadModeCustom); m_actions.viewKeypadZoom50->setCheckable(true); m_actions.viewKeypadZoom50->setData(50); m_actions.viewKeypadZoom100->setCheckable(true); m_actions.viewKeypadZoom100->setData(100); m_actions.viewKeypadZoom150->setCheckable(true); m_actions.viewKeypadZoom150->setData(150); m_actions.viewKeypadZoom200->setCheckable(true); m_actions.viewKeypadZoom200->setData(200); m_actions.viewFormulaBook->setCheckable(true); m_actions.viewStatusBar->setCheckable(true); m_actions.viewMenuBar->setCheckable(true); m_actions.viewVariables->setCheckable(true); m_actions.viewBitfield->setCheckable(true); m_actions.viewUserFunctions->setCheckable(true); m_actions.viewUserUnits->setCheckable(true); const auto schemes = ColorScheme::enumerate(); // TODO: use qAsConst(). for (auto& colorScheme : schemes) { auto action = new QAction(this); action->setCheckable(true); action->setText(colorSchemeDisplayName(colorScheme)); action->setData(colorScheme); m_actions.settingsDisplayColorSchemes.append(action); } } void MainWindow::retranslateText() { StartupDiagnostics::Scope timing("Load translations and translate UI"); QTranslator* tr = 0; tr = createTranslator(m_settings->language); if (tr) { if (m_translator) { qApp->removeTranslator(m_translator); m_translator->deleteLater(); } qApp->installTranslator(tr); m_translator = tr; const QString translationLanguage = tr->language().isEmpty() ? QFileInfo(tr->filePath()).completeBaseName() : tr->language(); qApp->setProperty("speedcrunchTranslationLanguage", tr->isEmpty() ? QStringLiteral("English (fallback)") : translationLanguage); } else { qApp->removeTranslator(m_translator); m_translator = 0; } setMenusText(); setActionsText(); for (const QPointer& ptr : allMainWindows()) { if (MainWindow* window = ptr.data()) window->setStatusBarText(); } setWidgetsDirection(); } void MainWindow::setStatusBarText() { if (m_status.angleUnit) { m_status.angleUnitLabel->setText(MainWindow::tr("Angle Mode:")); m_status.resultFormatLabel->setText(MainWindow::tr("Notation:")); m_status.resultPrecisionLabel->setText(MainWindow::tr("Precision:")); m_status.angleUnit->setText(statusBarAngleUnitValue()); m_status.resultFormat->setText(statusBarResultFormatValue()); m_status.resultPrecision->setText(statusBarResultPrecisionValue()); updateStatusBarSectionVisibility(); } } void MainWindow::updateStatusBarSectionVisibility() { if (!m_status.angleUnit) return; QStatusBar* bar = statusBar(); const int availableWidth = bar->contentsRect().width(); const int spacing = qMax(0, bar->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing, nullptr, bar)); struct Section { QWidget* widget; QWidget* separatorBefore; bool enabled; }; const Section sections[] = { { m_status.resultFormatSection, nullptr, true }, { m_status.resultPrecisionSection, m_status.resultPrecisionSeparator, true }, { m_status.angleUnitSection, m_status.angleUnitSeparator, true } }; int usedWidth = 0; bool hasVisibleSection = false; for (const Section& section : sections) { if (!section.enabled) { section.widget->setVisible(false); if (section.separatorBefore != nullptr) section.separatorBefore->setVisible(false); continue; } const int sectionWidth = section.widget->sizeHint().width(); const int separatorWidth = hasVisibleSection && section.separatorBefore != nullptr ? section.separatorBefore->sizeHint().width() : 0; const int gap = hasVisibleSection ? spacing + (section.separatorBefore != nullptr ? separatorWidth + spacing : 0) : 0; if (usedWidth + gap + sectionWidth <= availableWidth) { if (section.separatorBefore != nullptr) section.separatorBefore->setVisible(hasVisibleSection); section.widget->setVisible(true); usedWidth += gap + sectionWidth; hasVisibleSection = true; } else { if (section.separatorBefore != nullptr) section.separatorBefore->setVisible(false); section.widget->setVisible(false); } } } void MainWindow::updateColorSchemeActionState() { const auto schemes = m_actions.settingsDisplayColorSchemes; bool colorSchemeMatched = false; for (auto& action : schemes) { const bool matches = m_settings->colorScheme == action->data().toString(); action->setChecked(matches); colorSchemeMatched = colorSchemeMatched || matches; } m_actions.settingsDisplayColorSchemeCustom->setChecked(!colorSchemeMatched && m_settings->colorScheme == QLatin1String("Custom")); } void MainWindow::setMenuAppearance(QAction* action) { if (action == nullptr) return; m_settings->menuAppearance = action->data().toInt() == Settings::MenuAppearanceSpeedCrunch ? Settings::MenuAppearanceSpeedCrunch : Settings::MenuAppearanceSystem; MenuStyle::refresh(); for (const QPointer& window : allMainWindows()) { if (!window) continue; window->m_actions.settingsMenuAppearanceSystem->setChecked( m_settings->menuAppearance == Settings::MenuAppearanceSystem); window->m_actions.settingsMenuAppearanceSpeedCrunch->setChecked( m_settings->menuAppearance == Settings::MenuAppearanceSpeedCrunch); emit window->menuAppearanceChanged(); } } void MainWindow::setDockAppearance(QAction* action) { if (action == nullptr) return; m_settings->dockAppearance = action->data().toInt() == Settings::DockAppearanceSystem ? Settings::DockAppearanceSystem : Settings::DockAppearanceSpeedCrunch; const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); for (const QPointer& window : allMainWindows()) { if (!window) continue; window->m_actions.settingsDockAppearanceSystem->setChecked( m_settings->dockAppearance == Settings::DockAppearanceSystem); window->m_actions.settingsDockAppearanceSpeedCrunch->setChecked( m_settings->dockAppearance == Settings::DockAppearanceSpeedCrunch); for (QDockWidget* dock : window->m_allDocks) { applyDockAppearance(window, dock, surfaces); } window->applyDockTabBarAppearance(); window->updateSplitterStyleSheet(); window->update(); } } void MainWindow::setStatusBarAppearance(QAction* action) { if (action == nullptr) return; m_settings->statusBarAppearance = action->data().toInt() == Settings::StatusBarAppearanceSystem ? Settings::StatusBarAppearanceSystem : Settings::StatusBarAppearanceSpeedCrunch; const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); for (const QPointer& window : allMainWindows()) { if (!window) continue; window->m_actions.settingsStatusBarAppearanceSystem->setChecked( m_settings->statusBarAppearance == Settings::StatusBarAppearanceSystem); window->m_actions.settingsStatusBarAppearanceSpeedCrunch->setChecked( m_settings->statusBarAppearance == Settings::StatusBarAppearanceSpeedCrunch); applyStatusBarAppearance(window->findChild(QString(), Qt::FindDirectChildrenOnly), surfaces); window->updateStatusBarSectionVisibility(); } } void MainWindow::setKeypadAppearance(QAction* action) { if (action == nullptr) return; m_settings->keypadAppearance = action->data().toInt() == Settings::KeypadAppearanceClassic ? Settings::KeypadAppearanceClassic : Settings::KeypadAppearanceModern; for (const QPointer& window : allMainWindows()) { if (window) window->applyKeypadAppearance(); } } void MainWindow::applyKeypadAppearance() { StartupDiagnostics::Scope timing("Apply keypad appearance"); const bool classic = m_settings->keypadAppearance == Settings::KeypadAppearanceClassic; m_actions.settingsKeypadAppearanceClassic->setChecked(classic); m_actions.settingsKeypadAppearanceModern->setChecked(!classic); if (m_widgets.keypad) m_widgets.keypad->setAppearance(classic ? Keypad::Classic : Keypad::Modern); } void MainWindow::setEditorDisplayStyle(QAction* action) { if (action == nullptr) return; m_settings->editorDisplayStyle = action->data().toInt() == Settings::EditorDisplayClassic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; for (const QPointer& window : allMainWindows()) { if (window) window->applyEditorDisplayStyle(); } updatePaneEditorCursorVisibility(); } void MainWindow::applyEditorDisplayStyle() { StartupDiagnostics::Scope timing("Apply editor and display appearance"); m_actions.settingsEditorDisplayClassic->setChecked( m_settings->editorDisplayStyle == Settings::EditorDisplayClassic); m_actions.settingsEditorDisplayModern->setChecked( m_settings->editorDisplayStyle == Settings::EditorDisplayModern); for (ResultDisplay* display : splitPaneDisplays()) display->applyEditorDisplayStyle(); for (Editor* editor : splitPaneEditors()) editor->rehighlight(); updateSplitterStyleSheet(); if (m_widgets.state != nullptr && m_widgets.state->isVisible()) { // The new editor height takes effect when Qt lays out the pane. QTimer::singleShot(0, this, [this]() { if (m_widgets.state->isVisible()) showStateLabel(m_widgets.state->text()); }); } } QString MainWindow::statusBarAngleUnitValue() const { return (m_status.selectedAngleUnit == 'r' ? MainWindow::tr("Radian") : (m_status.selectedAngleUnit == 'g') ? MainWindow::tr("Gradian") : (m_status.selectedAngleUnit == 't') ? MainWindow::tr("Turn") : (m_status.selectedAngleUnit == 'v') ? MainWindow::tr("Revolution") : MainWindow::tr("Degree")); } QString MainWindow::statusBarResultFormatValue() const { switch (m_status.selectedResultFormat) { case 'b': return MainWindow::tr("Binary"); case 'o': return MainWindow::tr("Octal"); case 'h': return MainWindow::tr("Hexadecimal"); case 's': return MainWindow::tr("Sexagesimal"); case 'f': return MainWindow::tr("Fixed-point decimal"); case 'n': return MainWindow::tr("Engineering decimal"); case 'e': return MainWindow::tr("Scientific decimal"); case 'r': return MainWindow::tr("Rational"); case 'g': return MainWindow::tr("Automatic decimal"); default : return QString(); } } QString MainWindow::statusBarResultPrecisionValue() const { if (m_status.selectedResultPrecision < 0) return MainWindow::tr("Automatic"); return QString::number(m_status.selectedResultPrecision); } void MainWindow::setActionsText() { m_actions.sessionExportHtml->setText(QStringLiteral("&HTML")); m_actions.sessionExportJson->setText(QStringLiteral("JSON")); m_actions.sessionExportPlainText->setText(MainWindow::tr("Plain &text")); m_actions.sessionImport->setText(MainWindow::tr("&Import...")); m_actions.sessionImportUserDefinitions->setText(MainWindow::tr("User &Definitions...")); m_actions.sessionNewTab->setText(MainWindow::tr("New &Tab")); m_actions.sessionNewPrivate->setText(MainWindow::tr("New &Private Tab")); m_actions.sessionConvertPrivacy->setText(m_session && m_session->isPrivate() ? tr("Keep") : tr("Make Private...")); m_actions.sessionNewWindow->setText(MainWindow::tr("New &Window")); m_actions.sessionOpen->setText(MainWindow::tr("&Open...")); m_actions.sessionRename->setText(MainWindow::tr("&Rename...")); m_actions.sessionClone->setText(tr("Clo&ne...")); m_actions.sessionClose->setText(tr("&Close Tab")); m_actions.sessionReopen->setText(tr("Reopen Clo&sed Tab")); m_actions.sessionOpenSessionsFolder->setText(MainWindow::tr("Open Sessions &Folder")); m_actions.sessionQuit->setText(MainWindow::tr("&Quit")); m_actions.editClearExpression->setText(MainWindow::tr("Clear E&xpression")); m_actions.editUndo->setText(tr("&Undo")); m_actions.editRedo->setText(tr("&Redo")); m_actions.editCut->setText(tr("Cu&t")); m_actions.editClearHistory->setText(MainWindow::tr("Clear &History")); m_actions.editCopyLastResult->setText(MainWindow::tr("Copy &Last Result")); m_actions.editCopy->setText(MainWindow::tr("&Copy")); m_actions.editPaste->setText(MainWindow::tr("&Paste")); m_actions.editSelectExpression->setText(MainWindow::tr("&Select Expression")); m_actions.editWrapSelection->setText(MainWindow::tr("&Wrap in Parentheses")); m_actions.viewConstants->setText(MainWindow::tr("&Constants")); m_actions.viewFullScreenMode->setText(MainWindow::tr("Full Scr&een Mode")); m_actions.viewFunctions->setText(MainWindow::tr("&Functions")); m_actions.viewHistory->setText(MainWindow::tr("&History")); updateKeypadDisabledActionText(); m_actions.viewKeypadBasicWide->setText(MainWindow::tr("&Basic")); m_actions.viewKeypadScientificWide->setText(MainWindow::tr("&Scientific (wide)")); m_actions.viewKeypadScientificNarrow->setText(MainWindow::tr("Scientific (narrow)")); m_actions.viewKeypadCustom->setText(MainWindow::tr("&Custom...")); m_actions.viewKeypadZoom50->setText(QStringLiteral("50%")); m_actions.viewKeypadZoom100->setText(QStringLiteral("100%")); m_actions.viewKeypadZoom150->setText(QStringLiteral("150%")); m_actions.viewKeypadZoom200->setText(QStringLiteral("200%")); m_actions.viewFormulaBook->setText(MainWindow::tr("Formula &Book")); m_actions.viewStatusBar->setText(MainWindow::tr("&Status Bar")); m_actions.viewMenuBar->setText(MainWindow::tr("Main &Menu")); m_actions.viewVariables->setText(MainWindow::tr("User &Variables")); m_actions.viewBitfield->setText(MainWindow::tr("Bitfield")); m_actions.viewSplitLeft->setText(tr("&Left")); m_actions.viewSplitRight->setText(tr("&Right")); m_actions.viewSplitUp->setText(tr("&Up")); m_actions.viewSplitDown->setText(tr("&Down")); m_actions.viewClosePane->setText(tr("Close Pa&ne")); m_actions.viewUserFunctions->setText(MainWindow::tr("Use&r Functions")); m_actions.viewUserUnits->setText(MainWindow::tr("User &Units")); m_actions.settingsAngleUnitDegree->setText(MainWindow::tr("&Degree")); m_actions.settingsAngleUnitRadian->setText(MainWindow::tr("&Radian")); m_actions.settingsAngleUnitGradian->setText(MainWindow::tr("&Gradian")); m_actions.settingsAngleUnitTurn->setText(MainWindow::tr("&Turn")); m_actions.settingsAngleUnitRevolution->setText(MainWindow::tr("Re&volution")); m_actions.settingsBehaviorAlwaysOnTop->setText(MainWindow::tr("Always on &Top")); m_actions.settingsBehaviorAutoAns->setText(MainWindow::tr("Auto-Insert a&ns")); m_actions.settingsBehaviorAutoAns->setToolTip(MainWindow::tr("If a new expression starts with +, -, *, or /, SpeedCrunch inserts \"ans\" first.")); m_actions.settingsBehaviorAutoAns->setStatusTip(MainWindow::tr("If a new expression starts with +, -, *, or /, SpeedCrunch inserts \"ans\" first.")); m_actions.settingsBehaviorAutoCompletion->setText(MainWindow::tr("Automatic &Completion")); m_actions.settingsBehaviorAutoCompletionAcceptWithEnter->setText(tr("&Accept with Enter")); m_actions.settingsBehaviorAutoCompletionAcceptWithEnter->setToolTip(tr("Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys.")); m_actions.settingsBehaviorAutoCompletionAcceptWithEnter->setStatusTip(m_actions.settingsBehaviorAutoCompletionAcceptWithEnter->toolTip()); m_actions.settingsBehaviorAutoCompletionBuiltInFunctions->setText(MainWindow::tr("&Built-in Functions")); m_actions.settingsBehaviorAutoCompletionBuiltInVariables->setText(MainWindow::tr("Built-in &Variables")); m_actions.settingsBehaviorAutoCompletionLongFormUnits->setText(MainWindow::tr("&Units")); m_actions.settingsBehaviorAutoCompletionUserFunctions->setText(MainWindow::tr("User &Functions")); m_actions.settingsBehaviorAutoCompletionUserVariables->setText(MainWindow::tr("User Va&riables")); m_actions.settingsBehaviorPartialResults->setText(MainWindow::tr("Show Live Result &Preview")); m_actions.settingsBehaviorSaveWindowPositionOnExit->setText(MainWindow::tr("Save &Window Position on Exit")); m_actions.settingsOpenPrivateTabOnStartup->setText(tr("Open a Private Tab on Startup")); m_actions.settingsOpenPrivateTabOnStartup->setToolTip(tr("Open and focus a new private tab whenever SpeedCrunch starts.")); m_actions.settingsOpenPrivateTabOnStartup->setStatusTip(m_actions.settingsOpenPrivateTabOnStartup->toolTip()); m_actions.settingsBehaviorSyntaxHighlighting->setText(MainWindow::tr("Syntax &Highlighting")); m_actions.settingsEditingInputDigitGrouping->setText(MainWindow::tr("Group Digits in &Input")); m_actions.settingsEditingAutomaticInputAdjustments->setText(MainWindow::tr("Automatic Input &Adjustments")); m_actions.settingsEditingAutomaticInputAdjustments->setToolTip(MainWindow::tr("Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters.")); m_actions.settingsEditingInputDigitGrouping->setToolTip(MainWindow::tr("Group input digits using the selected number format.")); m_actions.settingsEditingCursorBlinking->setText(MainWindow::tr("&Blinking Cursor")); m_actions.settingsEditingCursorBlinking->setToolTip(MainWindow::tr("Blink the cursor in the expression editor.")); m_actions.settingsEditingEscapeClearsEditor->setText(MainWindow::tr("&Escape Clears Editor")); m_actions.settingsEditingEscapeClearsEditor->setToolTip(MainWindow::tr("Clear the focused expression editor with Escape after dismissing any popup or preview.")); m_actions.settingsBehaviorHoverHighlightResults->setText(MainWindow::tr("Hover Highlighting")); m_actions.settingsBehaviorDigitGroupingNone->setText(MainWindow::tr("Disabled")); m_actions.settingsBehaviorDigitGroupingOneSpace->setText(MainWindow::tr("Small Space")); m_actions.settingsBehaviorDigitGroupingTwoSpaces->setText(MainWindow::tr("Medium Space")); m_actions.settingsBehaviorDigitGroupingThreeSpaces->setText(MainWindow::tr("Large Space")); m_actions.settingsBehaviorDigitGroupingIntegerPartOnly->setText(MainWindow::tr("Group Integer Part Only")); m_actions.settingsBehaviorLeaveLastExpression->setText(MainWindow::tr("Keep Expression After Evaluation")); m_actions.settingsBehaviorNumberFormat->setText(MainWindow::tr("Number Format...")); m_actions.settingsBehaviorResultSlots->setText(MainWindow::tr("Notation && Precision...")); m_actions.settingsBehaviorLeaveLastExpression->setToolTip(MainWindow::tr("After pressing Enter, keep the entered expression selected in the editor.")); m_actions.settingsBehaviorLeaveLastExpression->setStatusTip(MainWindow::tr("After pressing Enter, keep the entered expression selected in the editor.")); m_actions.settingsBehaviorUpDownArrowNever->setText(MainWindow::tr("Never")); m_actions.settingsBehaviorUpDownArrowAlways->setText(MainWindow::tr("Always")); m_actions.settingsBehaviorUpDownArrowSingleLineOnly->setText(MainWindow::tr("Only for Single-Line Expressions")); m_actions.settingsBehaviorAutoResultToClipboard->setText(MainWindow::tr("Copy New Results Automatically")); m_actions.settingsBehaviorSimplifyResultExpressions->setText(MainWindow::tr("Simplify Displayed Expressions")); m_actions.settingsBehaviorHistorySizeLimit->setText(MainWindow::tr("History Size &Limit...")); m_actions.settingsRadixCharComma->setText(MainWindow::tr("&Comma")); m_actions.settingsRadixCharDefault->setText(MainWindow::tr("&System Default")); m_actions.settingsRadixCharDot->setText(MainWindow::tr("&Dot")); m_actions.settingsRadixCharBoth->setText(MainWindow::tr("Dot &And Comma")); m_actions.settingsResultFormat0Digits->setText(MainWindow::tr("&0 Digits")); m_actions.settingsResultFormat15Digits->setText(MainWindow::tr("&15 Digits")); m_actions.settingsResultFormat2Digits->setText(MainWindow::tr("&2 Digits")); m_actions.settingsResultFormat3Digits->setText(MainWindow::tr("&3 Digits")); m_actions.settingsResultFormat50Digits->setText(MainWindow::tr("&50 Digits")); m_actions.settingsResultFormat8Digits->setText(MainWindow::tr("&8 Digits")); m_actions.settingsResultFormatCustomDigits->setText(MainWindow::tr("&Custom...")); m_actions.settingsRemoveTrailingZeroes->setText(MainWindow::tr("Remove Trailing &Zeroes")); m_actions.settingsResultRoundingHalfAwayFromZero->setText( MainWindow::tr("Nearest, Half &Away (round)")); m_actions.settingsResultRoundingHalfEven->setText( MainWindow::tr("Nearest, Half &Even (roundeven)")); m_actions.settingsResultRoundingTowardZero->setText(MainWindow::tr("Toward &Zero (trunc)")); m_actions.settingsResultRoundingTowardPositiveInfinity->setText( MainWindow::tr("Toward +∞ (&ceil)")); m_actions.settingsResultRoundingTowardNegativeInfinity->setText( MainWindow::tr("Toward −∞ (&floor)")); m_actions.settingsResultFormatAutoPrecision->setText(MainWindow::tr("&Automatic")); m_actions.settingsResultFormatGeneral->setText(MainWindow::tr("&Automatic")); m_actions.settingsResultFormatFixed->setText(MainWindow::tr("&Fixed-Point")); m_actions.settingsResultFormatEngineering->setText(MainWindow::tr("&Engineering")); m_actions.settingsResultFormatScientific->setText(MainWindow::tr("&Scientific")); m_actions.settingsResultFormatRational->setText(MainWindow::tr("&Rational")); m_actions.settingsResultFormatBinary->setText(MainWindow::tr("&Binary")); m_actions.settingsResultFormatOctal->setText(MainWindow::tr("&Octal")); m_actions.settingsResultFormatHexadecimal->setText(MainWindow::tr("&Hexadecimal")); m_actions.settingsResultFormatSexagesimal->setText(MainWindow::tr("&Sexagesimal")); m_actions.settingsUnitNegativeExponentSuperscript->setText( MainWindow::tr("&Exponential (m·sâ�»Â¹)")); m_actions.settingsUnitNegativeExponentFraction->setText( MainWindow::tr("&Fractional (m/s)")); m_actions.settingsResultFormatCartesian->setText(MainWindow::tr("&Rectangular (a + bi)")); m_actions.settingsResultFormatPolar->setText(MainWindow::tr("Exponential (reâ�±á¶¿)")); m_actions.settingsResultFormatTrigonometric->setText( MainWindow::tr("Trigonometric (r(cos θ + i·sin θ))")); m_actions.settingsResultFormatCis->setText(QStringLiteral("Cis (r·cis(θ))")); m_actions.settingsResultFormatPolarAngle->setText(MainWindow::tr("Phasor (r∠θ)")); m_actions.settingsImaginaryUnitI->setText(QStringLiteral("&i")); m_actions.settingsImaginaryUnitJ->setText(QStringLiteral("&j")); m_actions.settingsDisplayFont->setText(MainWindow::tr("&Font...")); m_actions.settingsResetAll->setText(MainWindow::tr("Reset All Settings...")); m_actions.settingsDisplayColorSchemeCustom->setText(MainWindow::tr("&Theme...")); m_actions.settingsMenuAppearanceSystem->setText(MainWindow::tr("&System")); m_actions.settingsMenuAppearanceSpeedCrunch->setText(MainWindow::tr("SpeedCrunch &Theme")); m_actions.settingsDockAppearanceSystem->setText(MainWindow::tr("&System")); m_actions.settingsDockAppearanceSpeedCrunch->setText(MainWindow::tr("SpeedCrunch &Theme")); m_actions.settingsStatusBarAppearanceSystem->setText(MainWindow::tr("&System")); m_actions.settingsStatusBarAppearanceSpeedCrunch->setText(MainWindow::tr("SpeedCrunch &Theme")); m_actions.settingsKeypadAppearanceClassic->setText(MainWindow::tr("&Classic")); m_actions.settingsKeypadAppearanceModern->setText(MainWindow::tr("&Modern")); m_actions.settingsEditorDisplayClassic->setText(MainWindow::tr("&Classic")); m_actions.settingsEditorDisplayModern->setText(MainWindow::tr("&Modern")); m_actions.settingsLanguage->setText(MainWindow::tr("&Language...")); m_actions.helpManual->setText(MainWindow::tr("User &Manual")); m_actions.contextHelp->setText(MainWindow::tr("Context Help")); #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS m_actions.helpUpdates->setText(MainWindow::tr("Check for &Updates")); #endif m_actions.helpFeedback->setText(MainWindow::tr("Issues and &Feedback")); m_actions.helpCommunity->setText(MainWindow::tr("Community")); m_actions.helpSource->setText(MainWindow::tr("Source Code")); m_actions.helpDonate->setText(MainWindow::tr("&Donate")); m_actions.helpAbout->setText(MainWindow::tr("&About SpeedCrunch")); m_actions.helpDiagnostics->setText(MainWindow::tr("App Diag&nostics")); } void MainWindow::createActionGroups() { StartupDiagnostics::Scope timing("Create action groups"); m_actionGroups.resultFormat = new QActionGroup(this); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatBinary); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatGeneral); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatFixed); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatEngineering); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatScientific); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatRational); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatOctal); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatHexadecimal); m_actionGroups.resultFormat->addAction(m_actions.settingsResultFormatSexagesimal); m_actionGroups.complexFormat = new QActionGroup(this); m_actionGroups.complexFormat->addAction(m_actions.settingsResultFormatCartesian); m_actionGroups.complexFormat->addAction(m_actions.settingsResultFormatPolar); m_actionGroups.complexFormat->addAction(m_actions.settingsResultFormatTrigonometric); m_actionGroups.complexFormat->addAction(m_actions.settingsResultFormatCis); m_actionGroups.complexFormat->addAction(m_actions.settingsResultFormatPolarAngle); m_actionGroups.imaginaryUnit = new QActionGroup(this); m_actionGroups.imaginaryUnit->addAction(m_actions.settingsImaginaryUnitI); m_actionGroups.imaginaryUnit->addAction(m_actions.settingsImaginaryUnitJ); m_actionGroups.radixChar = new QActionGroup(this); m_actionGroups.radixChar->addAction(m_actions.settingsRadixCharDefault); m_actionGroups.radixChar->addAction(m_actions.settingsRadixCharDot); m_actionGroups.radixChar->addAction(m_actions.settingsRadixCharComma); m_actionGroups.radixChar->addAction(m_actions.settingsRadixCharBoth); m_actionGroups.digits = new QActionGroup(this); m_actionGroups.digits->addAction(m_actions.settingsResultFormatAutoPrecision); m_actionGroups.digits->addAction(m_actions.settingsResultFormat0Digits); m_actionGroups.digits->addAction(m_actions.settingsResultFormat2Digits); m_actionGroups.digits->addAction(m_actions.settingsResultFormat3Digits); m_actionGroups.digits->addAction(m_actions.settingsResultFormat8Digits); m_actionGroups.digits->addAction(m_actions.settingsResultFormat15Digits); m_actionGroups.digits->addAction(m_actions.settingsResultFormat50Digits); m_actionGroups.digits->addAction(m_actions.settingsResultFormatCustomDigits); m_actionGroups.resultRoundingMode = new QActionGroup(this); m_actionGroups.resultRoundingMode->addAction(m_actions.settingsResultRoundingHalfAwayFromZero); m_actionGroups.resultRoundingMode->addAction(m_actions.settingsResultRoundingHalfEven); m_actionGroups.resultRoundingMode->addAction(m_actions.settingsResultRoundingTowardZero); m_actionGroups.resultRoundingMode->addAction(m_actions.settingsResultRoundingTowardPositiveInfinity); m_actionGroups.resultRoundingMode->addAction(m_actions.settingsResultRoundingTowardNegativeInfinity); m_actionGroups.angle = new QActionGroup(this); m_actionGroups.angle->addAction(m_actions.settingsAngleUnitDegree); m_actionGroups.angle->addAction(m_actions.settingsAngleUnitRadian); m_actionGroups.angle->addAction(m_actions.settingsAngleUnitGradian); m_actionGroups.angle->addAction(m_actions.settingsAngleUnitTurn); m_actionGroups.angle->addAction(m_actions.settingsAngleUnitRevolution); m_actionGroups.colorScheme = new QActionGroup(this); m_actionGroups.menuAppearance = new QActionGroup(this); m_actionGroups.menuAppearance->addAction(m_actions.settingsMenuAppearanceSystem); m_actionGroups.menuAppearance->addAction(m_actions.settingsMenuAppearanceSpeedCrunch); m_actionGroups.dockAppearance = new QActionGroup(this); m_actionGroups.dockAppearance->addAction(m_actions.settingsDockAppearanceSystem); m_actionGroups.dockAppearance->addAction(m_actions.settingsDockAppearanceSpeedCrunch); m_actionGroups.statusBarAppearance = new QActionGroup(this); m_actionGroups.statusBarAppearance->addAction(m_actions.settingsStatusBarAppearanceSystem); m_actionGroups.statusBarAppearance->addAction(m_actions.settingsStatusBarAppearanceSpeedCrunch); m_actionGroups.keypadAppearance = new QActionGroup(this); m_actionGroups.keypadAppearance->addAction(m_actions.settingsKeypadAppearanceClassic); m_actionGroups.keypadAppearance->addAction(m_actions.settingsKeypadAppearanceModern); m_actionGroups.editorDisplayStyle = new QActionGroup(this); m_actionGroups.editorDisplayStyle->addAction(m_actions.settingsEditorDisplayClassic); m_actionGroups.editorDisplayStyle->addAction(m_actions.settingsEditorDisplayModern); const auto schemes = m_actions.settingsDisplayColorSchemes; for (auto& action : schemes) m_actionGroups.colorScheme->addAction(action); m_actionGroups.digitGrouping = new QActionGroup(this); m_actionGroups.digitGrouping->addAction(m_actions.settingsBehaviorDigitGroupingNone); m_actionGroups.digitGrouping->addAction(m_actions.settingsBehaviorDigitGroupingOneSpace); m_actionGroups.digitGrouping->addAction(m_actions.settingsBehaviorDigitGroupingTwoSpaces); m_actionGroups.digitGrouping->addAction(m_actions.settingsBehaviorDigitGroupingThreeSpaces); m_actionGroups.upDownArrowBehavior = new QActionGroup(this); m_actionGroups.upDownArrowBehavior->addAction(m_actions.settingsBehaviorUpDownArrowNever); m_actionGroups.upDownArrowBehavior->addAction(m_actions.settingsBehaviorUpDownArrowAlways); m_actionGroups.upDownArrowBehavior->addAction(m_actions.settingsBehaviorUpDownArrowSingleLineOnly); m_actionGroups.keypad = new QActionGroup(this); m_actionGroups.keypad->addAction(m_actions.viewKeypadDisabled); m_actionGroups.keypad->addAction(m_actions.viewKeypadBasicWide); m_actionGroups.keypad->addAction(m_actions.viewKeypadScientificWide); m_actionGroups.keypad->addAction(m_actions.viewKeypadScientificNarrow); m_actionGroups.keypad->addAction(m_actions.viewKeypadCustom); m_actionGroups.keypadZoom = new QActionGroup(this); m_actionGroups.keypadZoom->addAction(m_actions.viewKeypadZoom50); m_actionGroups.keypadZoom->addAction(m_actions.viewKeypadZoom100); m_actionGroups.keypadZoom->addAction(m_actions.viewKeypadZoom150); m_actionGroups.keypadZoom->addAction(m_actions.viewKeypadZoom200); m_actionGroups.unitNegativeExponentStyle = new QActionGroup(this); m_actionGroups.unitNegativeExponentStyle->addAction( m_actions.settingsUnitNegativeExponentSuperscript); m_actionGroups.unitNegativeExponentStyle->addAction( m_actions.settingsUnitNegativeExponentFraction); } void MainWindow::createActionShortcuts() { StartupDiagnostics::Scope timing("Create shortcuts"); QList newTabBindings = QKeySequence::keyBindings(QKeySequence::AddTab); for (const QKeySequence& binding : QKeySequence::keyBindings(QKeySequence::New)) { if (!newTabBindings.contains(binding)) newTabBindings.append(binding); } m_actions.sessionNewTab->setShortcuts(newTabBindings); m_actions.sessionOpen->setShortcuts(QKeySequence::Open); m_actions.sessionClose->setShortcuts(QKeySequence::Close); m_actions.sessionReopen->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_T); m_actions.editUndo->setShortcuts(QKeySequence::Undo); m_actions.editRedo->setShortcuts(QKeySequence::Redo); m_actions.editCut->setShortcuts(QKeySequence::Cut); m_actions.sessionNewPrivate->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_N); // Let this QAction own Quit; a separate standard-key QShortcut would // duplicate Ctrl+Q on Linux and make the shortcut ambiguous. m_actions.sessionQuit->setShortcut(Qt::CTRL | Qt::Key_Q); m_actions.editCopyLastResult->setShortcut(Qt::CTRL | Qt::Key_R); m_actions.editCopy->setShortcut(Qt::CTRL | Qt::Key_C); m_actions.editPaste->setShortcut(Qt::CTRL | Qt::Key_V); m_actions.editSelectExpression->setShortcut(Qt::CTRL | Qt::Key_A); m_actions.editWrapSelection->setShortcuts({ QKeySequence(Qt::CTRL | Qt::Key_ParenLeft), QKeySequence(Qt::CTRL | Qt::Key_ParenRight) }); m_actions.viewBitfield->setShortcut(Qt::CTRL | Qt::Key_8); m_actions.viewConstants->setShortcut(Qt::CTRL | Qt::Key_2); m_actions.viewFullScreenMode->setShortcut(Qt::Key_F11); m_actions.viewFunctions->setShortcut(Qt::CTRL | Qt::Key_3); m_actions.viewHistory->setShortcut(Qt::CTRL | Qt::Key_7); m_actions.viewFormulaBook->setShortcut(Qt::CTRL | Qt::Key_1); m_actions.viewStatusBar->setShortcut(Qt::CTRL | Qt::Key_B); m_actions.viewVariables->setShortcut(Qt::CTRL | Qt::Key_4); m_actions.viewUserFunctions->setShortcut(Qt::CTRL | Qt::Key_5); m_actions.viewUserUnits->setShortcut(Qt::CTRL | Qt::Key_6); m_actions.settingsResultFormatGeneral->setShortcut(Qt::Key_F2); m_actions.settingsResultFormatFixed->setShortcut(Qt::Key_F3); m_actions.settingsResultFormatEngineering->setShortcut(Qt::Key_F4); m_actions.settingsResultFormatScientific->setShortcut(Qt::Key_F5); m_actions.settingsResultFormatOctal->setShortcut(Qt::Key_F7); m_actions.settingsResultFormatHexadecimal->setShortcut(Qt::Key_F8); m_actions.settingsResultFormatSexagesimal->setShortcut(Qt::Key_F9); m_actions.settingsResultFormatBinary->setShortcut(Qt::Key_F10); m_actions.contextHelp->setShortcut(Qt::Key_F1); // The notation menus are standalone popups, so register their shortcuts // with the window even when those menus and the status bar are hidden. addActions({m_actions.settingsResultFormatGeneral, m_actions.settingsResultFormatFixed, m_actions.settingsResultFormatEngineering, m_actions.settingsResultFormatScientific, m_actions.settingsResultFormatOctal, m_actions.settingsResultFormatHexadecimal, m_actions.settingsResultFormatSexagesimal, m_actions.settingsResultFormatBinary}); } void MainWindow::createMenus() { StartupDiagnostics::Scope timing("Create menus"); QMenuBar* bar; { StartupDiagnostics::Scope menuBarTiming("Create menu bar"); bar = menuBar(); } StartupDiagnostics::Scope contents("Populate application menus"); m_menus.session = new QMenu("", this); bar->addMenu(m_menus.session); m_menus.session->addAction(m_actions.sessionNewTab); m_menus.session->addAction(m_actions.sessionNewPrivate); m_menus.session->addAction(m_actions.sessionNewWindow); m_menus.session->addSeparator(); m_menus.session->addAction(m_actions.sessionOpen); m_menus.session->addAction(m_actions.sessionRename); m_menus.session->addAction(m_actions.sessionClone); m_menus.session->addAction(m_actions.sessionConvertPrivacy); m_menus.session->addSeparator(); m_menus.session->addAction(m_actions.sessionImport); m_menus.sessionExport = m_menus.session->addMenu(""); m_menus.sessionExport->addAction(m_actions.sessionExportJson); m_menus.sessionExport->addAction(m_actions.sessionExportPlainText); m_menus.sessionExport->addAction(m_actions.sessionExportHtml); m_menus.session->addAction(m_actions.sessionOpenSessionsFolder); m_menus.session->addSeparator(); m_menus.session->addAction(m_actions.settingsBehaviorHistorySizeLimit); m_menus.session->addSeparator(); m_menus.session->addAction(m_actions.sessionClose); m_menus.session->addAction(m_actions.sessionReopen); m_menus.session->addSeparator(); m_menus.session->addAction(m_actions.sessionQuit); connect(m_menus.session, &QMenu::aboutToShow, this, [this]() { syncSessionMenuActionState(); }); m_menus.edit = new QMenu("", this); bar->addMenu(m_menus.edit); m_menus.edit->addAction(m_actions.editUndo); m_menus.edit->addAction(m_actions.editRedo); m_menus.edit->addSeparator(); m_menus.edit->addAction(m_actions.editCut); m_menus.edit->addAction(m_actions.editCopy); m_menus.edit->addAction(m_actions.editPaste); m_menus.edit->addAction(m_actions.editCopyLastResult); m_menus.edit->addSeparator(); m_menus.edit->addAction(m_actions.editSelectExpression); m_menus.edit->addAction(m_actions.editWrapSelection); m_menus.edit->addAction(m_actions.editClearExpression); m_menus.edit->addSeparator(); m_menus.edit->addAction(m_actions.editClearHistory); connect(m_menus.edit, &QMenu::aboutToShow, this, &MainWindow::syncEditMenuActionState); m_menus.view = new QMenu("", this); bar->addMenu(m_menus.view); m_menus.keypad = m_menus.view->addMenu(""); m_menus.keypad->addAction(m_actions.viewKeypadDisabled); m_menus.keypad->addAction(m_actions.viewKeypadBasicWide); m_menus.keypad->addAction(m_actions.viewKeypadScientificWide); m_menus.keypad->addAction(m_actions.viewKeypadScientificNarrow); m_menus.keypad->addAction(m_actions.viewKeypadCustom); m_menus.view->addAction(m_actions.viewStatusBar); m_menus.view->addSeparator(); m_menus.view->addAction(m_actions.viewFormulaBook); m_menus.view->addAction(m_actions.viewConstants); m_menus.view->addAction(m_actions.viewFunctions); m_menus.view->addSeparator(); m_menus.view->addAction(m_actions.viewVariables); m_menus.view->addAction(m_actions.viewUserFunctions); m_menus.view->addAction(m_actions.viewUserUnits); m_menus.view->addSeparator(); m_menus.view->addAction(m_actions.viewHistory); m_menus.view->addAction(m_actions.viewBitfield); m_menus.view->addSeparator(); m_menus.split = m_menus.view->addMenu(""); m_menus.split->addAction(m_actions.viewSplitLeft); m_menus.split->addAction(m_actions.viewSplitRight); m_menus.split->addAction(m_actions.viewSplitUp); m_menus.split->addAction(m_actions.viewSplitDown); m_menus.view->addAction(m_actions.viewClosePane); #if !defined(Q_OS_MACOS) m_menus.view->addSeparator(); m_menus.view->addAction(m_actions.viewMenuBar); m_menus.view->addAction(m_actions.viewFullScreenMode); #endif m_menus.settings = new QMenu("", this); bar->addMenu(m_menus.settings); m_menus.settings->addAction(m_actions.settingsBehaviorNumberFormat); m_menus.settings->addAction(m_actions.settingsLanguage); m_menus.settings->addSeparator(); m_menus.display = m_menus.settings->addMenu(""); m_menus.display->addAction(m_actions.settingsDisplayColorSchemeCustom); m_menus.display->addSeparator(); m_menus.menuAppearance = m_menus.display->addMenu(""); m_menus.menuAppearance->setObjectName(QStringLiteral("MenuAppearanceMenu")); m_menus.menuAppearance->addAction(m_actions.settingsMenuAppearanceSystem); m_menus.menuAppearance->addAction(m_actions.settingsMenuAppearanceSpeedCrunch); m_menus.dockAppearance = m_menus.display->addMenu(""); m_menus.dockAppearance->setObjectName(QStringLiteral("DockAppearanceMenu")); m_menus.dockAppearance->addAction(m_actions.settingsDockAppearanceSystem); m_menus.dockAppearance->addAction(m_actions.settingsDockAppearanceSpeedCrunch); m_menus.editorDisplayStyle = m_menus.display->addMenu(""); m_menus.editorDisplayStyle->setObjectName(QStringLiteral("EditorDisplayStyleMenu")); m_menus.editorDisplayStyle->addAction(m_actions.settingsEditorDisplayClassic); m_menus.editorDisplayStyle->addAction(m_actions.settingsEditorDisplayModern); m_menus.editorDisplayStyle->addSeparator(); m_menus.editorDisplayStyle->addAction(m_actions.settingsDisplayFont); m_menus.keypadAppearance = m_menus.display->addMenu(""); m_menus.keypadAppearance->setObjectName(QStringLiteral("KeypadAppearanceMenu")); m_menus.keypadAppearance->addAction(m_actions.settingsKeypadAppearanceClassic); m_menus.keypadAppearance->addAction(m_actions.settingsKeypadAppearanceModern); m_menus.keypadAppearance->addSeparator(); m_menus.keypadZoom = m_menus.keypadAppearance->addMenu(""); m_menus.keypadZoom->addAction(m_actions.viewKeypadZoom50); m_menus.keypadZoom->addAction(m_actions.viewKeypadZoom100); m_menus.keypadZoom->addAction(m_actions.viewKeypadZoom150); m_menus.keypadZoom->addAction(m_actions.viewKeypadZoom200); m_menus.statusBarAppearance = m_menus.display->addMenu(""); m_menus.statusBarAppearance->setObjectName(QStringLiteral("StatusBarAppearanceMenu")); m_menus.statusBarAppearance->addAction(m_actions.settingsStatusBarAppearanceSystem); m_menus.statusBarAppearance->addAction(m_actions.settingsStatusBarAppearanceSpeedCrunch); m_menus.display->addSeparator(); m_menus.display->addAction(m_actions.settingsBehaviorSyntaxHighlighting); m_menus.display->addAction(m_actions.settingsBehaviorHoverHighlightResults); m_menus.editing = m_menus.settings->addMenu(""); m_menus.editing->addAction(m_actions.settingsEditingAutomaticInputAdjustments); m_menus.editing->addAction(m_actions.settingsBehaviorAutoAns); m_menus.editing->addAction(m_actions.settingsEditingInputDigitGrouping); m_menus.editing->addAction(m_actions.settingsEditingCursorBlinking); m_menus.editing->addAction(m_actions.settingsEditingEscapeClearsEditor); m_menus.editing->addAction(m_actions.settingsBehaviorLeaveLastExpression); m_menus.editing->setToolTipsVisible(true); m_menus.editing->addSeparator(); m_menus.autoCompletion = m_menus.editing->addMenu(""); m_menus.autoCompletion->setToolTipsVisible(true); m_menus.autoCompletion->addAction(m_actions.settingsBehaviorAutoCompletionAcceptWithEnter); m_menus.autoCompletion->addSeparator(); m_menus.autoCompletion->addAction(m_actions.settingsBehaviorAutoCompletionBuiltInFunctions); m_menus.autoCompletion->addAction(m_actions.settingsBehaviorAutoCompletionBuiltInVariables); m_menus.autoCompletion->addAction(m_actions.settingsBehaviorAutoCompletionLongFormUnits); m_menus.autoCompletion->addAction(m_actions.settingsBehaviorAutoCompletionUserFunctions); m_menus.autoCompletion->addAction(m_actions.settingsBehaviorAutoCompletionUserVariables); m_menus.upDownArrowBehavior = m_menus.editing->addMenu(""); m_menus.upDownArrowBehavior->addAction(m_actions.settingsBehaviorUpDownArrowNever); m_menus.upDownArrowBehavior->addAction(m_actions.settingsBehaviorUpDownArrowAlways); m_menus.upDownArrowBehavior->addAction(m_actions.settingsBehaviorUpDownArrowSingleLineOnly); m_menus.results = m_menus.settings->addMenu(""); m_menus.results->addAction(m_actions.settingsBehaviorResultSlots); m_menus.results->addAction(m_actions.settingsRemoveTrailingZeroes); m_menus.results->addSeparator(); m_menus.resultRoundingMode = m_menus.results->addMenu(""); m_menus.resultRoundingMode->addAction(m_actions.settingsResultRoundingHalfAwayFromZero); m_menus.resultRoundingMode->addAction(m_actions.settingsResultRoundingHalfEven); m_menus.resultRoundingMode->addAction(m_actions.settingsResultRoundingTowardZero); m_menus.resultRoundingMode->addAction(m_actions.settingsResultRoundingTowardPositiveInfinity); m_menus.resultRoundingMode->addAction(m_actions.settingsResultRoundingTowardNegativeInfinity); m_menus.complexForm = m_menus.results->addMenu(""); m_menus.complexForm->addAction(m_actions.settingsResultFormatCartesian); m_menus.complexForm->addAction(m_actions.settingsResultFormatPolar); m_menus.complexForm->addAction(m_actions.settingsResultFormatTrigonometric); m_menus.complexForm->addAction(m_actions.settingsResultFormatCis); m_menus.complexForm->addAction(m_actions.settingsResultFormatPolarAngle); m_menus.imaginaryUnit = m_menus.results->addMenu(""); m_menus.imaginaryUnit->addAction(m_actions.settingsImaginaryUnitI); m_menus.imaginaryUnit->addAction(m_actions.settingsImaginaryUnitJ); m_menus.unitNegativeExponentStyle = m_menus.results->addMenu(""); m_menus.unitNegativeExponentStyle->addAction( m_actions.settingsUnitNegativeExponentSuperscript); m_menus.unitNegativeExponentStyle->addAction( m_actions.settingsUnitNegativeExponentFraction); m_menus.results->addSeparator(); // Deprecated direct menus kept as internal context menus only; users should // configure these via "Notation & Precision...". m_menus.resultFormat = new QMenu("", this); m_menus.decimal = m_menus.resultFormat->addMenu(""); m_menus.decimal->addAction(m_actions.settingsResultFormatGeneral); m_menus.decimal->addAction(m_actions.settingsResultFormatFixed); m_menus.decimal->addAction(m_actions.settingsResultFormatEngineering); m_menus.decimal->addAction(m_actions.settingsResultFormatScientific); m_menus.resultFormat->addAction(m_actions.settingsResultFormatRational); m_menus.resultFormat->addAction(m_actions.settingsResultFormatBinary); m_menus.resultFormat->addAction(m_actions.settingsResultFormatOctal); m_menus.resultFormat->addAction(m_actions.settingsResultFormatHexadecimal); m_menus.resultFormat->addAction(m_actions.settingsResultFormatSexagesimal); m_menus.precision = new QMenu("", this); m_menus.precision->addAction(m_actions.settingsResultFormatAutoPrecision); m_menus.precision->addAction(m_actions.settingsResultFormat0Digits); m_menus.precision->addAction(m_actions.settingsResultFormat2Digits); m_menus.precision->addAction(m_actions.settingsResultFormat3Digits); m_menus.precision->addAction(m_actions.settingsResultFormat8Digits); m_menus.precision->addAction(m_actions.settingsResultFormat15Digits); m_menus.precision->addAction(m_actions.settingsResultFormat50Digits); m_menus.precision->addSeparator(); m_menus.precision->addAction(m_actions.settingsResultFormatCustomDigits); m_menus.results->addAction(m_actions.settingsBehaviorPartialResults); m_menus.results->addAction(m_actions.settingsBehaviorSimplifyResultExpressions); m_menus.results->addAction(m_actions.settingsBehaviorAutoResultToClipboard); m_menus.angleUnit = m_menus.settings->addMenu(""); m_menus.angleUnit->addAction(m_actions.settingsAngleUnitDegree); m_menus.angleUnit->addAction(m_actions.settingsAngleUnitRadian); m_menus.angleUnit->addAction(m_actions.settingsAngleUnitGradian); m_menus.angleUnit->addAction(m_actions.settingsAngleUnitTurn); m_menus.angleUnit->addAction(m_actions.settingsAngleUnitRevolution); m_menus.window = m_menus.settings->addMenu(""); m_menus.window->addAction(m_actions.settingsOpenPrivateTabOnStartup); m_menus.window->addAction(m_actions.settingsBehaviorSaveWindowPositionOnExit); if (!isWaylandPlatform()) m_menus.window->addAction(m_actions.settingsBehaviorAlwaysOnTop); m_menus.settings->addSeparator(); m_menus.settings->addAction(m_actions.sessionImportUserDefinitions); m_menus.settings->addSeparator(); m_menus.settings->addAction(m_actions.settingsResetAll); m_menus.help = new QMenu("", this); bar->addMenu(m_menus.help); m_menus.help->addAction(m_actions.helpManual); m_menus.help->addAction(m_actions.contextHelp); m_menus.help->addSeparator(); m_menus.help->addAction(m_actions.helpCommunity); m_menus.help->addAction(m_actions.helpFeedback); m_menus.help->addAction(m_actions.helpSource); m_menus.help->addAction(m_actions.helpDonate); m_menus.help->addSeparator(); #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS m_menus.help->addAction(m_actions.helpUpdates); #endif m_menus.help->addAction(m_actions.helpDiagnostics); m_menus.help->addAction(m_actions.helpAbout); addActions(bar->actions()); } void MainWindow::setMenusText() { m_menus.session->setTitle(MainWindow::tr("&Session")); m_menus.sessionExport->setTitle(MainWindow::tr("&Export")); m_menus.edit->setTitle(MainWindow::tr("&Edit")); m_menus.view->setTitle(MainWindow::tr("&View")); m_menus.keypad->setTitle(MainWindow::tr("&Keypad")); m_menus.split->setTitle(tr("S&plit")); m_menus.keypadZoom->setTitle(MainWindow::tr("&Zoom")); m_menus.settings->setTitle(MainWindow::tr("Se&ttings")); m_menus.results->setTitle(MainWindow::tr("&Results")); m_menus.unitNegativeExponentStyle->setTitle(MainWindow::tr("Unit Notation")); m_menus.resultRoundingMode->setTitle(MainWindow::tr("Rounding Mode")); m_menus.resultFormat->setTitle(MainWindow::tr("&Notation")); m_menus.decimal->setTitle(MainWindow::tr("&Decimal")); m_menus.precision->setTitle(MainWindow::tr("&Precision")); m_menus.angleUnit->setTitle(MainWindow::tr("Angle &Mode")); m_menus.complexForm->setTitle(MainWindow::tr("&Complex Form")); m_menus.imaginaryUnit->setTitle(MainWindow::tr("&Imaginary Unit")); m_menus.window->setTitle(MainWindow::tr("&Window")); m_menus.editing->setTitle(MainWindow::tr("&Editing")); m_menus.autoCompletion->setTitle(MainWindow::tr("A&utocomplete")); m_menus.upDownArrowBehavior->setTitle(MainWindow::tr("Up/Down Arrow History")); m_menus.display->setTitle(MainWindow::tr("&Appearance")); m_menus.menuAppearance->setTitle(MainWindow::tr("&Menus")); m_menus.dockAppearance->setTitle(MainWindow::tr("&Docks")); m_menus.statusBarAppearance->setTitle(MainWindow::tr("&Status Bar")); m_menus.keypadAppearance->setTitle(MainWindow::tr("&Keypad")); m_menus.editorDisplayStyle->setTitle(MainWindow::tr("&Input and Results")); m_menus.help->setTitle(MainWindow::tr("&Help")); } void MainWindow::updateKeypadDisabledActionText() { if (m_actions.viewKeypadDisabled->isChecked()) m_actions.viewKeypadDisabled->setText(MainWindow::tr("&Disabled")); else m_actions.viewKeypadDisabled->setText(MainWindow::tr("&Disable")); } void MainWindow::updateKeypadModeActionState() { const QSignalBlocker keypadBlocker(m_actionGroups.keypad); switch (m_keypadMode) { case Settings::KeypadModeBasicWide: m_actions.viewKeypadBasicWide->setChecked(true); break; case Settings::KeypadModeScientificWide: m_actions.viewKeypadScientificWide->setChecked(true); break; case Settings::KeypadModeScientificNarrow: m_actions.viewKeypadScientificNarrow->setChecked(true); break; case Settings::KeypadModeCustom: m_actions.viewKeypadCustom->setChecked(true); break; case Settings::KeypadModeDisabled: default: m_actions.viewKeypadDisabled->setChecked(true); break; } } void MainWindow::createStatusBar() { StartupDiagnostics::Scope timing("Create status bar"); QStatusBar* bar = statusBar(); if (m_status.angleUnitSection != nullptr) { applyStatusBarAppearance(bar, generatedSurfaceColors(m_settings)); bar->show(); setStatusBarText(); updateStatusBarSectionVisibility(); return; } m_status.angleUnitSection = new QWidget(bar); m_status.resultFormatSection = new QWidget(bar); m_status.resultPrecisionSection = new QWidget(bar); m_status.angleUnitLabel = new QLabel(m_status.angleUnitSection); m_status.resultFormatLabel = new QLabel(m_status.resultFormatSection); m_status.resultPrecisionLabel = new QLabel(m_status.resultPrecisionSection); m_status.resultPrecisionSeparator = new QLabel(QStringLiteral("|"), bar); m_status.angleUnitSeparator = new QLabel(QStringLiteral("|"), bar); m_status.angleUnit = new QPushButton(bar); m_status.resultFormat = new QPushButton(bar); m_status.resultPrecision = new QPushButton(bar); m_status.angleUnit->setParent(m_status.angleUnitSection); m_status.resultFormat->setParent(m_status.resultFormatSection); m_status.resultPrecision->setParent(m_status.resultPrecisionSection); QHBoxLayout* angleLayout = new QHBoxLayout(m_status.angleUnitSection); QHBoxLayout* formatLayout = new QHBoxLayout(m_status.resultFormatSection); QHBoxLayout* precisionLayout = new QHBoxLayout(m_status.resultPrecisionSection); angleLayout->setContentsMargins(0, 0, 0, 0); formatLayout->setContentsMargins(0, 0, 0, 0); precisionLayout->setContentsMargins(0, 0, 0, 0); angleLayout->setSpacing(2); formatLayout->setSpacing(2); precisionLayout->setSpacing(2); angleLayout->addWidget(m_status.angleUnitLabel); angleLayout->addWidget(m_status.angleUnit); formatLayout->addWidget(m_status.resultFormatLabel); formatLayout->addWidget(m_status.resultFormat); precisionLayout->addWidget(m_status.resultPrecisionLabel); precisionLayout->addWidget(m_status.resultPrecision); QFont boldFont = m_status.angleUnitLabel->font(); boldFont.setBold(true); m_status.angleUnitLabel->setFont(boldFont); m_status.resultFormatLabel->setFont(boldFont); m_status.resultPrecisionLabel->setFont(boldFont); m_status.resultPrecisionSeparator->setContentsMargins(2, 0, 2, 0); m_status.angleUnitSeparator->setContentsMargins(2, 0, 2, 0); m_status.angleUnitLabel->setCursor(Qt::PointingHandCursor); m_status.resultFormatLabel->setCursor(Qt::PointingHandCursor); m_status.resultPrecisionLabel->setCursor(Qt::PointingHandCursor); m_status.angleUnitLabel->installEventFilter(this); m_status.resultFormatLabel->installEventFilter(this); m_status.resultPrecisionLabel->installEventFilter(this); m_status.angleUnit->setCursor(Qt::PointingHandCursor); m_status.resultFormat->setCursor(Qt::PointingHandCursor); m_status.resultPrecision->setCursor(Qt::PointingHandCursor); m_status.angleUnit->setFocusPolicy(Qt::NoFocus); m_status.resultFormat->setFocusPolicy(Qt::NoFocus); m_status.resultPrecision->setFocusPolicy(Qt::NoFocus); m_status.angleUnit->setFlat(true); m_status.resultFormat->setFlat(true); m_status.resultPrecision->setFlat(true); m_status.angleUnit->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_status.angleUnit, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(showAngleModeContextMenu(const QPoint&))); m_status.resultFormat->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_status.resultFormat, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(showResultFormatContextMenu(const QPoint&))); m_status.resultPrecision->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_status.resultPrecision, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(showPrecisionContextMenu(const QPoint&))); connect(m_status.angleUnit, &QPushButton::clicked, this, [this]() { showAngleModeContextMenu(QPoint(0, m_status.angleUnit->height())); }); connect(m_status.resultFormat, &QPushButton::clicked, this, [this]() { showResultFormatContextMenu(QPoint(0, m_status.resultFormat->height())); }); connect(m_status.resultPrecision, &QPushButton::clicked, this, [this]() { showPrecisionContextMenu(QPoint(0, m_status.resultPrecision->height())); }); bar->addWidget(m_status.resultFormatSection); bar->addWidget(m_status.resultPrecisionSeparator); bar->addWidget(m_status.resultPrecisionSection); bar->addWidget(m_status.angleUnitSeparator); bar->addWidget(m_status.angleUnitSection); applyStatusBarAppearance(bar, generatedSurfaceColors(m_settings)); bar->show(); setStatusBarText(); // When the status bar is recreated via View > Status Bar, geometry might not // be updated yet and width can be 0, which hides all sections. Recompute // once the event loop lays out the status bar. QTimer::singleShot(0, this, [this]() { updateStatusBarSectionVisibility(); }); } void MainWindow::createFixedWidgets() { StartupDiagnostics::Scope timing("Create editor and result display"); m_widgets.root = new QWidget(this); setCentralWidget(m_widgets.root); m_layouts.root = new QVBoxLayout(m_widgets.root); m_layouts.root->setSpacing(0); m_layouts.root->setContentsMargins(0, 0, 0, 0); m_widgets.splitContainer = new QSplitter(Qt::Horizontal, m_widgets.root); m_widgets.splitContainer->setObjectName(QStringLiteral("MainSplitContainer")); m_widgets.splitContainer->setChildrenCollapsible(false); m_widgets.splitContainer->setHandleWidth(UiConfig::SessionPaneSplitterWidth); applyThemeBackgroundRoleToWidget(m_widgets.splitContainer, generatedSurfaceColors(m_settings).window.background); updateSplitterStyleSheet(); m_layouts.root->addWidget(m_widgets.splitContainer, 1); { StartupDiagnostics::Scope displayTiming("Construct initial result display"); m_widgets.display = new ResultDisplay(); m_widgets.display->setFrameStyle(QFrame::NoFrame); } { StartupDiagnostics::Scope editorTiming("Construct initial expression editor"); m_widgets.editor = new Editor(); m_widgets.editor->setFrameStyle(QFrame::NoFrame); m_widgets.editor->installEventFilter(this); m_widgets.editor->viewport()->installEventFilter(this); } { StartupDiagnostics::Scope paneTiming("Create and bind initial session pane"); m_widgets.splitContainer->addWidget(createEditorDisplayPane(m_widgets.display, m_widgets.editor)); m_paneSessionNames.insert(m_widgets.display, m_session ? m_session->name() : QString()); m_paneSessionTabs.insert(m_widgets.display, QStringList(m_session ? m_session->name() : QString())); m_widgets.display->setSession(m_session); m_widgets.editor->setSession(m_session); } m_widgets.state = new QLabel(this); m_widgets.state->setObjectName(QStringLiteral("EditorStatePopup")); m_widgets.state->setPalette(QToolTip::palette()); m_widgets.state->setAutoFillBackground(true); m_widgets.state->setFrameShape(QFrame::NoFrame); m_widgets.state->installEventFilter(this); m_widgets.stateCloseButton = new QPushButton(QStringLiteral("×"), m_widgets.state); m_widgets.stateCloseButton->setFocusPolicy(Qt::NoFocus); m_widgets.stateCloseButton->setFlat(true); m_widgets.stateCloseButton->setToolTip(tr("Close preview")); m_widgets.stateCloseButton->setStyleSheet(QStringLiteral(R"( QPushButton { border: none; background: transparent; padding: 0; margin: 0; outline: none; } QPushButton:hover { background: transparent; } QPushButton:pressed { background: transparent; } )")); connect(m_widgets.stateCloseButton, &QPushButton::clicked, this, &MainWindow::hideStateLabel); m_widgets.state->hide(); } QWidget* MainWindow::createEditorDisplayPane(ResultDisplay* display, Editor* editor) { connect(editor, &Editor::constantSearchVisibilityChanged, this, &MainWindow::updatePaneEditorCursorVisibility); const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); SessionPane* pane = new SessionPane(m_widgets.splitContainer); applyThemeBackgroundRoleToWidget(pane, surfaces.result.background); QVBoxLayout* layout = new QVBoxLayout(pane); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); SessionTabBar* tabBar = new SessionTabBar(pane); tabBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); QWidget* tabBarRow = new QWidget(pane); QHBoxLayout* tabBarRowLayout = new QHBoxLayout(tabBarRow); tabBarRowLayout->setSpacing(0); tabBarRowLayout->setContentsMargins(0, 0, 0, 0); tabBarRowLayout->addWidget(tabBar); tabBarRowLayout->addStretch(1); QStackedWidget* stack = new QStackedWidget(pane); applyThemeBackgroundRoleToWidget(stack, surfaces.result.background); QWidget* page = new QWidget(stack); applyThemeBackgroundRoleToWidget(page, surfaces.result.background); display->setThemeSurfaceColor(surfaces.result.background); const ThemeSurfaceColors resultToolTip = themeSurfaceForShadeIndex(surfaces, UiConfig::ResultTooltipBackgroundShade); const ThemeSurfaceColors resultToolTipOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::ResultTooltipOutlineShade); display->setThemeToolTipColors(resultToolTip.background, resultToolTip.foreground, resultToolTipOutline.background); display->setThemeInteractionColors(surfaces.editorAndLists.background, surfaces.primary.background, surfaces.headersAndBorders.background, surfaces.headersAndBorders.foreground, surfaces.inputs.background, surfaces.inputs.foreground); display->rehighlight(); editor->setThemeSurfaceColor(surfaces.editorAndLists.background, surfaces.result.background); const ThemeSurfaceColors completionPopup = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupBackgroundShade); const ThemeSurfaceColors completionScrollbarThumb = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupScrollbarThumbShade); const ThemeSurfaceColors completionSelectedRow = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupSelectedRowShade); const ThemeSurfaceColors completionOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupOutlineShade); editor->setThemeCompletionColors(completionPopup.background, completionPopup.foreground, completionScrollbarThumb.background, completionScrollbarThumb.foreground, completionSelectedRow.background, completionSelectedRow.foreground, completionOutline.background, UiConfig::CompletionPopupCornerRadius, surfaces.primary.background, surfaces.primary.foreground); editor->rehighlight(); QVBoxLayout* pageLayout = new QVBoxLayout(page); pageLayout->setSpacing(0); pageLayout->setContentsMargins(0, 0, 0, 0); pageLayout->addWidget(display); pageLayout->addWidget(editor); stack->addWidget(page); layout->addWidget(tabBarRow); layout->addWidget(stack, 1); m_paneTabBars.insert(display, tabBar); m_tabBarDisplays.insert(tabBar, display); connect(tabBar, &QTabBar::currentChanged, this, [this, tabBar, display, editor](int index) { if (index < 0) return; pendingSessionTabActivationDisplay() = display; pendingSessionTabActivationEditor() = editor; setActiveEditorDisplayPane(display, editor, true); switchPaneToSession(display, tabBar->tabText(index)); QPointer pendingDisplay(display); QPointer pendingEditor(editor); QTimer::singleShot(0, this, [pendingDisplay, pendingEditor]() { if (pendingSessionTabActivationDisplay() == pendingDisplay && pendingSessionTabActivationEditor() == pendingEditor) { pendingSessionTabActivationDisplay() = nullptr; pendingSessionTabActivationEditor() = nullptr; } }); tabBar->refreshCloseButtons(); }); tabBar->tabActivated = [this, display, editor](const QString& sessionName) { pendingSessionTabActivationDisplay() = display; pendingSessionTabActivationEditor() = editor; setActiveEditorDisplayPane(display, editor, true); switchPaneToSession(display, sessionName); QPointer pendingDisplay(display); QPointer pendingEditor(editor); QTimer::singleShot(0, this, [pendingDisplay, pendingEditor]() { if (pendingSessionTabActivationDisplay() == pendingDisplay && pendingSessionTabActivationEditor() == pendingEditor) { pendingSessionTabActivationDisplay() = nullptr; pendingSessionTabActivationEditor() = nullptr; } }); }; connect(tabBar, &QTabBar::tabMoved, this, [this, tabBar, display](int, int) { QStringList names; for (int i = 0; i < tabBar->count(); ++i) names.append(tabBar->tabText(i)); m_paneSessionTabs.insert(display, names); saveSessionLayout(false); }); connect(tabBar, &QTabBar::tabBarDoubleClicked, this, [this, tabBar, display, editor](int index) { if (index < 0 || index >= tabBar->count()) return; setActiveEditorDisplayPane(display, editor); switchPaneToSession(display, tabBar->tabText(index)); showRenameSessionDialog(); }); tabBar->tabContextMenuRequested = [this, display, editor](const QString& sessionName, const QPoint& globalPos) { switchPaneToSession(display, sessionName); QMenu menu(this); QAction* renameSessionAction = menu.addAction(tr("Rename...")); QAction* duplicateSessionAction = menu.addAction(tr("Clone...")); QAction* convertPrivacyAction = menu.addAction(m_session->isPrivate() ? tr("Keep") : tr("Make Private...")); QAction* closeSessionAction = menu.addAction(tr("Close Tab")); menu.addSeparator(); QAction* newSessionAction = menu.addAction(tr("New Tab")); QAction* newPrivateAction = menu.addAction(tr("New Private Tab")); QAction* openSessionAction = menu.addAction(tr("Open...")); QAction* reopenSessionAction = menu.addAction(tr("Reopen Closed Tab")); reopenSessionAction->setEnabled(!m_closedSessionTabs.isEmpty()); menu.addSeparator(); menu.addAction(m_actions.sessionImport); QMenu* exportMenu = menu.addMenu(m_menus.sessionExport->title()); exportMenu->addAction(m_actions.sessionExportJson); exportMenu->addAction(m_actions.sessionExportPlainText); exportMenu->addAction(m_actions.sessionExportHtml); menu.addSeparator(); QMenu* splitMenu = menu.addMenu(tr("Split")); QAction* splitLeftAction = splitMenu->addAction(tr("Left")); QAction* splitRightAction = splitMenu->addAction(tr("Right")); QAction* splitUpAction = splitMenu->addAction(tr("Up")); QAction* splitDownAction = splitMenu->addAction(tr("Down")); QAction* closePaneAction = menu.addAction(tr("Close Pane")); menu.addSeparator(); QAction* clearSessionAction = menu.addAction(tr("Clear")); QAction* deleteSessionAction = menu.addAction(tr("Delete")); MenuStyle::apply(&menu); QAction* selectedAction = menu.exec(globalPos); if (selectedAction == nullptr) return; setActiveEditorDisplayPane(display, editor); if (selectedAction == newSessionAction) showNewSessionDialog(); else if (selectedAction == newPrivateAction) showNewPrivateSession(); else if (selectedAction == convertPrivacyAction) convertSessionPrivacy(); else if (selectedAction == openSessionAction) showOpenSessionDialog(); else if (selectedAction == reopenSessionAction) restoreClosedSessionTab(); else if (selectedAction == duplicateSessionAction) showDuplicateSessionDialog(); else if (selectedAction == splitLeftAction) splitActivePaneLeft(); else if (selectedAction == splitRightAction) splitActivePaneRight(); else if (selectedAction == splitUpAction) splitActivePaneUp(); else if (selectedAction == splitDownAction) splitActivePaneDown(); else if (selectedAction == renameSessionAction) showRenameSessionDialog(); else if (selectedAction == clearSessionAction) clearSession(); else if (selectedAction == closeSessionAction) closeCurrentSession(); else if (selectedAction == closePaneAction) closeCurrentPane(); else if (selectedAction == deleteSessionAction) deleteCurrentSession(); }; tabBar->sessionTabDropped = [this, tabBar](SessionTabBar* sourceTabBar, const QString& sessionName, int targetIndex) { moveSessionTab(sourceTabBar, tabBar, sessionName, targetIndex); }; tabBar->sourceMainWindow = [this]() { return this; }; tabBar->sessionTabDetached = [this, tabBar](const QString& sessionName, const QPoint& globalPos) { if (sessionName.isEmpty()) return; ResultDisplay* sourceDisplay = tabBarDisplay(tabBar); if (sourceDisplay == nullptr) return; if (!paneSessionNames(sourceDisplay).contains(sessionName, Qt::CaseInsensitive)) return; const QString previousLayoutJson = m_settings->sessionLayoutJson; m_settings->sessionLayoutJson.clear(); MainWindow* detachedWindow = new MainWindow(false); m_settings->sessionLayoutJson = previousLayoutJson; detachedWindow->show(); detachedWindow->move(globalPos - QPoint(detachedWindow->width() / 4, 18)); Session* sourceSession = m_loadedSessions.value(sessionName, nullptr); if (sourceSession == nullptr) return; const QStringList detachedNames = detachedWindow->m_loadedSessions.keys(); for (const QString& name : detachedNames) { Session* sessionToDelete = detachedWindow->m_loadedSessions.take(name); detachedWindow->m_sessionViewportAnchors.remove(name); detachedWindow->m_sessionScrollValues.remove(name); if (sessionToDelete == detachedWindow->m_session) detachedWindow->m_session = nullptr; if (sessionToDelete != nullptr) delete sessionToDelete; } Session* movedSession = new Session(*sourceSession); movedSession->setName(sessionName); detachedWindow->m_loadedSessions.insert(sessionName, movedSession); detachedWindow->applyUserDefinitions(); detachedWindow->m_paneSessionTabs.insert(detachedWindow->m_widgets.display, QStringList(sessionName)); detachedWindow->m_paneSessionNames.insert(detachedWindow->m_widgets.display, sessionName); detachedWindow->m_widgets.display->setSession(movedSession); detachedWindow->activateSession(movedSession); detachedWindow->updatePaneLoadedSessionCounts(); detachedWindow->updatePaneTabBars(); removeSessionTabFromPane(sourceDisplay, sessionName, true); const auto referencedByRemainingPanes = [this](const QString& name) { for (ResultDisplay* display : splitPaneDisplays()) { if (paneSessionNames(display).contains(name, Qt::CaseInsensitive)) return true; } return false; }; if (!referencedByRemainingPanes(sessionName)) { Session* sessionToDelete = m_loadedSessions.take(sessionName); m_sessionViewportAnchors.remove(sessionName); m_sessionScrollValues.remove(sessionName); if (sessionToDelete != nullptr && sessionToDelete != m_session) delete sessionToDelete; } updatePaneLoadedSessionCounts(); updatePaneTabBars(); detachedWindow->saveSessionLayout(false); saveSessionLayout(false); }; tabBar->tabCloseRequested = [this, display](const QString& sessionName) { switchPaneToSession(display, sessionName); closeCurrentSession(); }; pane->sessionTabDroppedOnPane = [this, display](SessionTabBar* sourceTabBar, const QString& sessionName, const QPoint& panePos) { moveSessionTabToPane(sourceTabBar, display, sessionName, panePos); }; pane->shouldShowOverlayForDrag = [this, display](SessionTabBar* sourceTabBar) { ResultDisplay* sourceDisplay = tabBarDisplay(sourceTabBar); if (sourceDisplay == nullptr || sourceDisplay != display) return true; return paneSessionNames(sourceDisplay).size() > 1; }; pane->paneActivated = [this, display, editor]() { setActiveEditorDisplayPane(display, editor); }; pane->watchDropTarget(stack); pane->setOverlayAreaWidget(stack); pane->watchDropTarget(page); pane->watchDropTarget(display); pane->watchDropTarget(display->viewport()); pane->watchDropTarget(editor); pane->watchDropTarget(editor->viewport()); return pane; } void MainWindow::setActiveEditorDisplayPane(ResultDisplay* display, Editor* editor, bool forceEditorFocus) { if (display == nullptr || editor == nullptr) return; if (forceEditorFocus) { cancelWindowActivationRestore(); setPendingDockTextInputFocusTarget(nullptr); } const bool dockWidgetHasFocus = !forceEditorFocus && pendingDockFocusTarget() != nullptr; const bool dockTextInputHasFocus = !forceEditorFocus && (isDockTextInput(QApplication::focusWidget()) || pendingDockTextInputFocusTarget() != nullptr); if (dockWidgetHasFocus || dockTextInputHasFocus) { globallyActiveDisplay() = nullptr; globallyActiveEditor() = nullptr; return; } else { globallyActiveDisplay() = display; globallyActiveEditor() = editor; } if (activeEditorDisplayPaneActivationInProgress()) return; activeEditorDisplayPaneActivationInProgress() = true; struct ActivationGuard { ~ActivationGuard() { activeEditorDisplayPaneActivationInProgress() = false; } } activationGuard; if (m_widgets.display != display || m_widgets.editor != editor) { const QString sessionName = m_paneSessionNames.value(display); Session* paneSession = m_loadedSessions.value(sessionName, nullptr); const bool switchingSession = paneSession != nullptr && paneSession != m_session; const bool previousSessionIsLoaded = m_session != nullptr && m_loadedSessions.values().contains(m_session); if (previousSessionIsLoaded) { if (m_sessionSavePending) flushPendingSessionSave(); captureEditorTextInCurrentSession(); if (m_widgets.display != nullptr && m_paneSessionNames.value(m_widgets.display) == m_session->name()) { m_sessionViewportAnchors.insert(m_session->name(), m_widgets.display->viewportTopAnchor()); QScrollBar* bar = m_widgets.display->verticalScrollBar(); const int scrollValue = bar->value() == bar->maximum() ? (std::numeric_limits::max)() : bar->value(); m_sessionScrollValues.insert(m_session->name(), scrollValue); } } else { captureEditorTextInCurrentSession(); } if (switchingSession) m_session = nullptr; m_widgets.display = display; m_widgets.editor = editor; // Selection signals can set the copy source before activating a pane. // Keep that source when it belongs to the pane being activated. if (m_copyWidget != display && m_copyWidget != editor) m_copyWidget = editor; if (paneSession != nullptr && paneSession != m_session) activateSession(paneSession); } if (!dockWidgetHasFocus && !dockTextInputHasFocus && QApplication::activePopupWidget() == nullptr) { editor->setFocus(Qt::OtherFocusReason); QPointer editorGuard(editor); QTimer::singleShot(0, editor, [editorGuard]() { if (editorGuard != nullptr && globallyActiveEditor() == editorGuard && pendingDockFocusTarget() == nullptr && pendingDockTextInputFocusTarget() == nullptr && QApplication::activePopupWidget() == nullptr) { editorGuard->setFocus(Qt::OtherFocusReason); } }); } updatePaneEditorCursorVisibility(); updateActiveSessionPaneTabColor(); syncEditMenuActionState(); if (!dockWidgetHasFocus && !dockTextInputHasFocus && m_widgets.state != nullptr && m_widgets.state->isVisible()) showStateLabel(m_widgets.state->text()); } bool MainWindow::isDockTextInput(QWidget* widget) const { QLineEdit* lineEdit = qobject_cast(widget); if (lineEdit == nullptr) return false; if (lineEdit->property("speedcrunchDockTextInput").toBool()) return true; for (QObject* ancestor = widget; ancestor != nullptr; ancestor = ancestor->parent()) { QDockWidget* dock = qobject_cast(ancestor); if (dock != nullptr && m_allDocks.contains(dock)) return true; } for (QDockWidget* dock : m_allDocks) { if (dock != nullptr && dock->findChildren().contains(lineEdit)) return true; } return false; } bool MainWindow::isDockWidgetDescendant(QWidget* widget) const { return dockWidgetForDescendant(widget) != nullptr; } QDockWidget* MainWindow::dockWidgetForDescendant(QWidget* widget) const { if (widget == nullptr) return nullptr; for (QObject* ancestor = widget; ancestor != nullptr; ancestor = ancestor->parent()) { QDockWidget* dock = qobject_cast(ancestor); if (dock != nullptr && m_allDocks.contains(dock)) return dock; } return nullptr; } QAbstractItemView* MainWindow::dockItemViewFocusTarget(QWidget* widget) const { if (widget == nullptr) return nullptr; const auto usableDockView = [this](QAbstractItemView* view) -> QAbstractItemView* { if (view == nullptr) return nullptr; if (!isDockWidgetDescendant(view)) return nullptr; if (view->model() == nullptr || view->model()->rowCount() <= 0) return nullptr; return view; }; for (QWidget* candidate = widget; candidate != nullptr; candidate = candidate->parentWidget()) { if (QAbstractItemView* view = usableDockView(qobject_cast(candidate))) return view; } const QPoint globalPos = QCursor::pos(); for (QDockWidget* dock : m_allDocks) { if (dock == nullptr || !dock->isVisible()) continue; if (!dock->rect().contains(dock->mapFromGlobal(globalPos))) continue; for (QAbstractItemView* view : dock->findChildren()) { if (!view->isVisible()) continue; if (!view->rect().contains(view->mapFromGlobal(globalPos))) continue; if (QAbstractItemView* usableView = usableDockView(view)) return usableView; } } return nullptr; } QList MainWindow::focusCycleTargets() const { QList targets; QSet seen; const auto addTarget = [&targets, &seen, this](QWidget* widget) { if (widget == nullptr || seen.contains(widget)) return; if (!widget->isEnabled() || !widget->isVisibleTo(const_cast(this))) return; if (widget->focusPolicy() == Qt::NoFocus) return; targets.append(widget); seen.insert(widget); }; for (Editor* editor : splitPaneEditors()) addTarget(editor); for (QDockWidget* dock : m_allDocks) { if (dock == nullptr || !dock->isEnabled() || !dock->isVisibleTo(const_cast(this))) continue; QWidget* dockWidget = dock->widget(); if (dockWidget == nullptr || !dockWidget->isEnabled() || !dockWidget->isVisibleTo(const_cast(this))) continue; const QList textInputs = dockWidget->findChildren(); for (QLineEdit* textInput : textInputs) addTarget(textInput); const QList itemViews = dockWidget->findChildren(); for (QAbstractItemView* itemView : itemViews) addTarget(itemView); } return targets; } bool MainWindow::focusWidgetMatchesCycleTarget(QWidget* focusWidget, QWidget* target) const { if (focusWidget == nullptr || target == nullptr) return false; if (focusWidget == target) return true; if (target->isAncestorOf(focusWidget)) return true; if (QAbstractItemView* itemView = qobject_cast(target)) { QWidget* viewport = itemView->viewport(); return focusWidget == viewport || (viewport != nullptr && viewport->isAncestorOf(focusWidget)); } return false; } void MainWindow::cycleFocusRegion(int direction) { const QList targets = focusCycleTargets(); if (targets.size() <= 1) return; // F6 expresses a newer focus choice than the delayed replay scheduled by // window activation. Do not let that replay pull focus back to the editor. cancelWindowActivationRestore(); QWidget* focused = QApplication::focusWidget(); if (focused == nullptr || (focused->window() != this && !isDockWidgetDescendant(focused))) focused = focusWidget(); int currentIndex = -1; for (int i = 0; i < targets.size(); ++i) { if (focusWidgetMatchesCycleTarget(focused, targets.at(i))) { currentIndex = i; break; } } const int targetIndex = currentIndex < 0 ? (direction >= 0 ? 0 : targets.size() - 1) : (currentIndex + direction + targets.size()) % targets.size(); QWidget* target = targets.at(targetIndex); setPendingDockFocusTarget(nullptr); setPendingDockTextInputFocusTarget(nullptr); if (isDockWidgetDescendant(target)) { const int focusGeneration = setPendingDockFocusTarget(target); int textInputGeneration = pendingDockTextInputFocusTargetGeneration(); if (isDockTextInput(target)) textInputGeneration = setPendingDockTextInputFocusTarget(target); deactivateActiveEditorForTextInputFocus(); hideStateLabel(); QPointer focusTarget(target); QTimer::singleShot(100, target, [focusTarget, focusGeneration, textInputGeneration]() { if (pendingDockFocusTargetGeneration() == focusGeneration && pendingDockFocusTarget() == focusTarget) { setPendingDockFocusTarget(nullptr); } if (pendingDockTextInputFocusTargetGeneration() == textInputGeneration && pendingDockTextInputFocusTarget() == focusTarget) { setPendingDockTextInputFocusTarget(nullptr); } }); } // Floating docks are separate top-level windows; activate the destination // before asking one of its children to take focus. if (!target->window()->isActiveWindow()) target->window()->activateWindow(); target->setFocus(Qt::ShortcutFocusReason); } void MainWindow::cycleFocusForward() { cycleFocusRegion(1); } void MainWindow::cycleFocusBackward() { cycleFocusRegion(-1); } void MainWindow::deactivateActiveEditorForTextInputFocus() { // Dock search fields and other dock text inputs are peers of the expression // editor. The focus event is already moving to the dock input here, so this // clears only the app-level active-editor state and repaint flags. Calling // clearFocus() on the previous editor during the transfer can make Qt fall // back to that editor, which would leave two text inputs competing for the // primary outline. QPointer previousActiveEditor = globallyActiveEditor(); if (previousActiveEditor == nullptr) previousActiveEditor = m_widgets.editor; if (previousActiveEditor == nullptr && globallyActiveDisplay() == nullptr) return; DockTextInputFocusTransferGuard focusTransferGuard; globallyActiveEditor() = nullptr; globallyActiveDisplay() = nullptr; if (previousActiveEditor != nullptr) { previousActiveEditor->setCustomCursorVisible(false); previousActiveEditor->setThemePrimaryColor( generatedSurfaceColors(m_settings).primary.background, false); } } void MainWindow::handleApplicationFocusChanged(QWidget* previous, QWidget* focused) { if (!allMainWindows().contains(QPointer(this))) return; if (focused != nullptr) { if (focused->window() == this || isDockWidgetDescendant(focused)) lastFocusWidgetInActiveWindow() = focused; } else if (previous != nullptr && (previous->window() == this || isDockWidgetDescendant(previous))) { lastFocusWidgetInActiveWindow() = previous; } syncEditMenuActionState(); syncSessionMenuActionState(); if (!isDockTextInput(focused)) return; const int textInputGeneration = setPendingDockTextInputFocusTarget(focused); QPointer textInput(focused); QTimer::singleShot(100, focused, [textInput, textInputGeneration]() { if (pendingDockTextInputFocusTargetGeneration() == textInputGeneration && pendingDockTextInputFocusTarget() == textInput) { setPendingDockTextInputFocusTarget(nullptr); } }); deactivateActiveEditorForTextInputFocus(); } void MainWindow::configureEditorDisplayPane(ResultDisplay* display, Editor* editor) { if (display == nullptr || editor == nullptr) return; editor->installEventFilter(this); editor->viewport()->installEventFilter(this); connect(editor, &Editor::textChanged, this, [this, display, editor]() { // Programmatic text changes in an inactive pane must not make that pane // active. Real editor input activates the pane through the mouse/key/input // event path before the text changes. if (editor == m_widgets.editor || editor->hasFocus() || editor->viewport()->hasFocus()) { setActiveEditorDisplayPane(display, editor); } }); connect(editor, &Editor::returnPressed, this, [this, display, editor]() { setActiveEditorDisplayPane(display, editor); evaluateEditorExpression(); }); connect(editor, &Editor::bulkEvaluationStarted, this, &MainWindow::handleBulkEvaluationStarted); connect(editor, &Editor::bulkEvaluationFinished, this, &MainWindow::handleBulkEvaluationFinished); connect(editor, &Editor::escapePressed, this, [this, display, editor]() { setActiveEditorDisplayPane(display, editor); handleEditorEscapePressed(); }); connect(editor, &Editor::selectionChanged, this, [this, display, editor]() { setActiveEditorDisplayPane(display, editor); handleEditorSelectionChange(); }); connect(editor, &Editor::autoCalcDisabled, this, [this, editor]() { if (editor == m_widgets.editor) hideStateLabel(); }); connect(editor, &Editor::autoCalcMessageAvailable, this, &MainWindow::handleAutoCalcMessageAvailable); connect(editor, &Editor::autoCalcQuantityAvailable, this, &MainWindow::handleAutoCalcQuantityAvailable); connect(editor, &Editor::shiftDownPressed, this, &MainWindow::decreaseDisplayFontPointSize); connect(editor, &Editor::shiftUpPressed, this, &MainWindow::increaseDisplayFontPointSize); connect(editor, &Editor::controlPageUpPressed, display, &ResultDisplay::scrollToTop); connect(editor, &Editor::controlPageDownPressed, display, &ResultDisplay::scrollToBottom); connect(editor, &Editor::shiftPageUpPressed, display, &ResultDisplay::scrollLineUp); connect(editor, &Editor::shiftPageDownPressed, display, &ResultDisplay::scrollLineDown); connect(editor, &Editor::pageUpPressed, display, &ResultDisplay::scrollPageUp); connect(editor, &Editor::pageDownPressed, display, &ResultDisplay::scrollPageDown); connect(editor, &Editor::textChanged, this, [this, editor]() { if (editor == m_widgets.editor || editor->hasFocus() || editor->viewport()->hasFocus()) { handleEditorTextChange(); } }); connect(editor, &Editor::copyAvailable, this, &MainWindow::handleCopyAvailable); connect(editor, &Editor::undoAvailable, this, &MainWindow::syncEditMenuActionState); connect(editor, &Editor::redoAvailable, this, &MainWindow::syncEditMenuActionState); connect(editor, &Editor::copySequencePressed, this, &MainWindow::copy); connect(this, &MainWindow::historyChanged, editor, &Editor::updateHistory); connect(display, &ResultDisplay::clicked, this, [this, display, editor]() { setActiveEditorDisplayPane(display, editor, true); hideStateLabel(); }); connect(display, &ResultDisplay::copyAvailable, this, &MainWindow::handleCopyAvailable); connect(display, &ResultDisplay::expressionSelected, this, [this, display, editor](const QString& text) { setActiveEditorDisplayPane(display, editor, true); insertHistoryExpressionIntoEditor(text); }); connect(display, &ResultDisplay::editHistoryEntryRequested, this, &MainWindow::startHistoryEntryEdit); connect(display, &ResultDisplay::editHistoryEntryContextRequested, this, &MainWindow::editHistoryEntryContext); connect(display, &ResultDisplay::cancelHistoryEditRequested, this, &MainWindow::cancelHistoryEntryEdit); connect(display, &ResultDisplay::removeHistoryEntryRequested, this, &MainWindow::removeHistoryEntryAt); connect(display, &ResultDisplay::removeHistoryEntriesAboveRequested, this, &MainWindow::removeHistoryEntriesAbove); connect(display, &ResultDisplay::removeHistoryEntriesBelowRequested, this, &MainWindow::removeHistoryEntriesBelow); connect(display, &ResultDisplay::newSessionRequested, this, &MainWindow::showNewSessionDialog); connect(display, &ResultDisplay::newPrivateSessionRequested, this, &MainWindow::showNewPrivateSession); connect(display, &ResultDisplay::convertSessionPrivacyRequested, this, &MainWindow::convertSessionPrivacy); connect(display, &ResultDisplay::openSessionRequested, this, &MainWindow::showOpenSessionDialog); connect(display, &ResultDisplay::importSessionRequested, this, &MainWindow::showSessionImportDialog); connect(display, &ResultDisplay::exportSessionJsonRequested, this, &MainWindow::exportJson); connect(display, &ResultDisplay::exportSessionPlainTextRequested, this, &MainWindow::exportPlainText); connect(display, &ResultDisplay::exportSessionHtmlRequested, this, &MainWindow::exportHtml); connect(display, &ResultDisplay::duplicateSessionRequested, this, &MainWindow::showDuplicateSessionDialog); connect(display, &ResultDisplay::splitLeftRequested, this, &MainWindow::splitActivePaneLeft); connect(display, &ResultDisplay::splitRightRequested, this, &MainWindow::splitActivePaneRight); connect(display, &ResultDisplay::splitUpRequested, this, &MainWindow::splitActivePaneUp); connect(display, &ResultDisplay::splitDownRequested, this, &MainWindow::splitActivePaneDown); connect(display, &ResultDisplay::renameSessionRequested, this, &MainWindow::showRenameSessionDialog); connect(display, &ResultDisplay::clearSessionRequested, this, &MainWindow::clearSession); connect(display, &ResultDisplay::closeSessionRequested, this, &MainWindow::closeCurrentSession); connect(display, &ResultDisplay::closePaneRequested, this, &MainWindow::closeCurrentPane); connect(display, &ResultDisplay::deleteSessionRequested, this, &MainWindow::deleteCurrentSession); connect(display, &ResultDisplay::loadedSessionsMenuRequested, this, &MainWindow::showLoadedSessionsMenu); connect(display, &ResultDisplay::selectionChanged, this, [this, display, editor]() { setActiveEditorDisplayPane(display, editor, true); handleDisplaySelectionChange(); }); connect(display, &ResultDisplay::shiftWheelUp, this, &MainWindow::increaseDisplayFontPointSize); connect(display, &ResultDisplay::shiftWheelDown, this, &MainWindow::decreaseDisplayFontPointSize); connect(display, &ResultDisplay::controlWheelUp, this, &MainWindow::increaseDisplayFontPointSize); connect(display, &ResultDisplay::controlWheelDown, this, &MainWindow::decreaseDisplayFontPointSize); connect(display, &ResultDisplay::shiftControlWheelDown, this, &MainWindow::decreaseOpacity); connect(display, &ResultDisplay::shiftControlWheelUp, this, &MainWindow::increaseOpacity); connect(this, &MainWindow::historyChanged, display, &ResultDisplay::refresh); connect(this, &MainWindow::radixCharacterChanged, display, &ResultDisplay::refresh); connect(this, &MainWindow::radixCharacterChanged, editor, &Editor::refreshAutoCalc); connect(this, &MainWindow::angleUnitChanged, editor, &Editor::refreshAutoCalc); connect(this, &MainWindow::complexNumbersChanged, display, &ResultDisplay::refreshLastHistoryEntry); connect(this, &MainWindow::complexNumbersChanged, editor, &Editor::refreshAutoCalc); connect(this, &MainWindow::resultFormatChanged, display, &ResultDisplay::refreshLastHistoryEntry); connect(this, &MainWindow::resultFormatChanged, editor, &Editor::refreshAutoCalc); connect(this, &MainWindow::resultPrecisionChanged, display, &ResultDisplay::refreshLastHistoryEntry); connect(this, &MainWindow::resultPrecisionChanged, editor, &Editor::refreshAutoCalc); connect(this, &MainWindow::resultRoundingModeChanged, display, &ResultDisplay::refreshLastHistoryEntry); connect(this, &MainWindow::resultRoundingModeChanged, editor, &Editor::refreshAutoCalc); connect(this, &MainWindow::colorSchemeChanged, display, &ResultDisplay::rehighlight); connect(this, &MainWindow::colorSchemeChanged, editor, &Editor::rehighlight); connect(this, &MainWindow::syntaxHighlightingChanged, display, &ResultDisplay::rehighlight); connect(this, &MainWindow::syntaxHighlightingChanged, editor, &Editor::rehighlight); } void MainWindow::splitActivePane(Qt::Orientation orientation, bool insertAfter) { if (m_widgets.splitContainer == nullptr || m_widgets.display == nullptr || m_widgets.editor == nullptr) return; QWidget* activePane = paneWidgetForDisplay(m_widgets.display); QSplitter* parentSplitter = qobject_cast(activePane ? activePane->parentWidget() : nullptr); if (parentSplitter == nullptr) return; const int activeIndex = parentSplitter->indexOf(activePane); if (activeIndex < 0) return; const QList parentSizesBefore = parentSplitter->sizes(); const int activeSize = activeIndex < parentSizesBefore.size() ? parentSizesBefore.at(activeIndex) : qMax(1, orientation == Qt::Horizontal ? activePane->width() : activePane->height()); ResultDisplay* display = new ResultDisplay(); display->setFrameStyle(QFrame::NoFrame); display->setFont(m_widgets.display->font()); display->setHoverHighlightEnabled(m_settings->hoverHighlightResults); display->setLoadedSessionCount(1); display->rehighlight(); Editor* editor = new Editor(); editor->setFrameStyle(QFrame::NoFrame); editor->setFont(m_widgets.editor->font()); editor->setAutoCalcEnabled(m_settings->autoCalc); editor->setAutoCompletionEnabled(m_settings->autoCompletion); editor->rehighlight(); Session* newSession = createUntitledSession(false); editor->setText(QString()); editor->setCursorPosition(editor->text().size()); QWidget* pane = createEditorDisplayPane(display, editor); configureEditorDisplayPane(display, editor); QSplitter* targetSplitter = parentSplitter; if (parentSplitter->orientation() != orientation) { QSplitter* nestedSplitter = new QSplitter(orientation); nestedSplitter->setChildrenCollapsible(false); nestedSplitter->setHandleWidth(UiConfig::SessionPaneSplitterWidth); nestedSplitter->setStyleSheet(m_widgets.splitContainer->styleSheet()); activePane->setParent(nullptr); parentSplitter->insertWidget(activeIndex, nestedSplitter); if (insertAfter) { nestedSplitter->addWidget(activePane); nestedSplitter->addWidget(pane); } else { nestedSplitter->addWidget(pane); nestedSplitter->addWidget(activePane); } targetSplitter = nestedSplitter; if (parentSizesBefore.size() == parentSplitter->count()) parentSplitter->setSizes(parentSizesBefore); } else { const int insertIndex = insertAfter ? activeIndex + 1 : activeIndex; parentSplitter->insertWidget(insertIndex, pane); } if (newSession != nullptr) m_paneSessionNames.insert(display, newSession->name()); if (newSession != nullptr) m_paneSessionTabs.insert(display, QStringList(newSession->name())); display->setSession(newSession); if (newSession != nullptr) editor->setSession(newSession); const int firstHalf = qMax(1, activeSize / 2); const int secondHalf = qMax(1, activeSize - firstHalf); if (targetSplitter == parentSplitter) { QList sizes = parentSizesBefore; if (activeIndex < sizes.size()) { sizes[activeIndex] = insertAfter ? firstHalf : secondHalf; sizes.insert(insertAfter ? activeIndex + 1 : activeIndex, insertAfter ? secondHalf : firstHalf); if (sizes.size() == targetSplitter->count()) targetSplitter->setSizes(sizes); } } else { targetSplitter->setSizes(insertAfter ? QList({ firstHalf, secondHalf }) : QList({ firstHalf, secondHalf })); } display->refresh(); editor->updateHistory(); editor->refreshAutoCalc(); updateSplitterStyleSheet(); updatePaneLoadedSessionCounts(); cancelWindowActivationRestore(); setActiveEditorDisplayPane(display, editor); saveSessionLayout(); } void MainWindow::splitActivePaneLeft() { splitActivePane(Qt::Horizontal, false); } void MainWindow::splitActivePaneRight() { splitActivePane(Qt::Horizontal, true); } void MainWindow::splitActivePaneUp() { splitActivePane(Qt::Vertical, false); } void MainWindow::splitActivePaneDown() { splitActivePane(Qt::Vertical, true); } void MainWindow::activateNextChild() { if (m_widgets.display == nullptr) return; QTabBar* currentTabBar = displayTabBar(m_widgets.display); if (currentTabBar != nullptr && currentTabBar->count() > 0) { const int currentIndex = currentTabBar->currentIndex(); if (currentIndex >= 0 && currentIndex + 1 < currentTabBar->count()) { currentTabBar->setCurrentIndex(currentIndex + 1); return; } } const QList displays = splitPaneDisplays(); const int currentPaneIndex = displays.indexOf(m_widgets.display); if (currentPaneIndex < 0 || currentPaneIndex + 1 >= displays.size()) return; ResultDisplay* nextDisplay = displays.at(currentPaneIndex + 1); QWidget* page = nextDisplay->parentWidget(); Editor* nextEditor = page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (nextEditor == nullptr) return; setActiveEditorDisplayPane(nextDisplay, nextEditor); const QString sessionName = m_paneSessionNames.value(nextDisplay); if (!sessionName.isEmpty()) switchPaneToSession(nextDisplay, sessionName); } void MainWindow::activatePreviousChild() { if (m_widgets.display == nullptr) return; QTabBar* currentTabBar = displayTabBar(m_widgets.display); if (currentTabBar != nullptr && currentTabBar->count() > 0) { const int currentIndex = currentTabBar->currentIndex(); if (currentIndex > 0) { currentTabBar->setCurrentIndex(currentIndex - 1); return; } } const QList displays = splitPaneDisplays(); const int currentPaneIndex = displays.indexOf(m_widgets.display); if (currentPaneIndex <= 0) return; ResultDisplay* previousDisplay = displays.at(currentPaneIndex - 1); QWidget* page = previousDisplay->parentWidget(); Editor* previousEditor = page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (previousEditor == nullptr) return; setActiveEditorDisplayPane(previousDisplay, previousEditor); const QString sessionName = m_paneSessionNames.value(previousDisplay); if (!sessionName.isEmpty()) switchPaneToSession(previousDisplay, sessionName); } QString MainWindow::firstAvailableUntitledSessionNameAcrossWindows(const MainWindow* ignoredWindow) const { QHash sessions; for (const QPointer& ptr : allMainWindows()) { MainWindow* window = ptr.data(); if (window == nullptr || window == ignoredWindow) continue; for (auto it = window->m_loadedSessions.constBegin(); it != window->m_loadedSessions.constEnd(); ++it) sessions.insert(it.key(), it.value()); } return firstAvailableUntitledSessionName(sessions); } void MainWindow::copyWindowLayoutFrom(const MainWindow* source) { if (source == nullptr) return; restoreDockColumnOrders(source->dockColumnOrders()); restoreDockLayout(source->saveState(DockLayoutStateVersion), source->openDockNames()); const auto dockIsVisible = [](QDockWidget* dock) { return dock != nullptr && !dock->isHidden(); }; const auto statusBarIsVisible = [](const MainWindow* window) { const QStatusBar* statusBar = window != nullptr ? window->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; return statusBar != nullptr && statusBar->isVisible(); }; const bool statusBarVisible = statusBarIsVisible(source); if (statusBarIsVisible(this) != statusBarVisible) setStatusBarVisible(statusBarVisible); m_actions.viewStatusBar->setChecked(statusBarVisible); m_status.selectedAngleUnit = source->m_status.selectedAngleUnit; m_status.selectedResultFormat = source->m_status.selectedResultFormat; m_status.selectedResultPrecision = source->m_status.selectedResultPrecision; setStatusBarText(); const bool formulaBookVisible = dockIsVisible(source->m_docks.book); if (dockIsVisible(m_docks.book) != formulaBookVisible) setFormulaBookDockVisible(formulaBookVisible, false); m_actions.viewFormulaBook->setChecked(formulaBookVisible); const bool constantsVisible = dockIsVisible(source->m_docks.constants); if (dockIsVisible(m_docks.constants) != constantsVisible) setConstantsDockVisible(constantsVisible, false); m_actions.viewConstants->setChecked(constantsVisible); const bool functionsVisible = dockIsVisible(source->m_docks.functions); if (dockIsVisible(m_docks.functions) != functionsVisible) setFunctionsDockVisible(functionsVisible, false); m_actions.viewFunctions->setChecked(functionsVisible); const bool historyVisible = dockIsVisible(source->m_docks.history); if (dockIsVisible(m_docks.history) != historyVisible) setHistoryDockVisible(historyVisible, false); m_actions.viewHistory->setChecked(historyVisible); const bool variablesVisible = dockIsVisible(source->m_docks.variables); if (dockIsVisible(m_docks.variables) != variablesVisible) setVariablesDockVisible(variablesVisible, false); m_actions.viewVariables->setChecked(variablesVisible); const bool userFunctionsVisible = dockIsVisible(source->m_docks.userFunctions); if (dockIsVisible(m_docks.userFunctions) != userFunctionsVisible) setUserFunctionsDockVisible(userFunctionsVisible, false); m_actions.viewUserFunctions->setChecked(userFunctionsVisible); const bool userUnitsVisible = dockIsVisible(source->m_docks.userUnits); if (dockIsVisible(m_docks.userUnits) != userUnitsVisible) setUserUnitsDockVisible(userUnitsVisible, false); m_actions.viewUserUnits->setChecked(userUnitsVisible); const bool bitfieldVisible = dockIsVisible(source->m_docks.bitField); if (dockIsVisible(m_docks.bitField) != bitfieldVisible) setBitfieldVisible(bitfieldVisible); m_actions.viewBitfield->setChecked(bitfieldVisible); const bool keypadVisible = source->m_widgets.keypad != nullptr; restoreWindowKeypadLayout(keypadVisible, static_cast(source->m_keypadMode)); restoreWindowKeypadZoom(source->m_keypadZoomPercent); applyThemeSurfacePalette(); refreshPaneThemes(); } Session* MainWindow::createUntitledSession(bool activateCreatedSession) { Session* recycledSession = nullptr; int recycledNumber = (std::numeric_limits::max)(); for (auto it = m_loadedSessions.constBegin(); it != m_loadedSessions.constEnd(); ++it) { const QString name = it.key(); const int number = untitledSessionNumber(name); if (number <= 0 || number >= recycledNumber) continue; if (!isReusableUntitledSession(it.value())) continue; bool alreadyAttachedToPane = false; for (auto paneIt = m_paneSessionTabs.constBegin(); paneIt != m_paneSessionTabs.constEnd(); ++paneIt) { if (paneIt.value().contains(name, Qt::CaseInsensitive)) { alreadyAttachedToPane = true; break; } } if (alreadyAttachedToPane) continue; recycledSession = it.value(); recycledNumber = number; } if (recycledSession != nullptr) { applyUserDefinitions(); if (activateCreatedSession) activateSession(recycledSession); return recycledSession; } const QString name = firstAvailableUntitledSessionName(m_loadedSessions); Session* session = new Session(); session->setName(name); m_loadedSessions.insert(name, session); updatePaneLoadedSessionCounts(); applyUserDefinitions(); if (activateCreatedSession) activateSession(session); return session; } QList MainWindow::splitPaneDisplays() const { QList displays; if (m_widgets.splitContainer == nullptr) return displays; const auto collectDisplays = [&displays](QWidget* widget, const auto& collectDisplaysRef) -> void { if (widget == nullptr) return; if (ResultDisplay* display = qobject_cast(widget)) { displays.append(display); return; } if (QSplitter* splitter = qobject_cast(widget)) { for (int i = 0; i < splitter->count(); ++i) collectDisplaysRef(splitter->widget(i), collectDisplaysRef); return; } const QList childDisplays = widget->findChildren(); for (ResultDisplay* display : childDisplays) displays.append(display); }; collectDisplays(m_widgets.splitContainer, collectDisplays); return displays; } QList MainWindow::splitPaneEditors() const { QList editors; for (ResultDisplay* display : splitPaneDisplays()) { QWidget* pane = display->parentWidget(); if (Editor* editor = pane ? pane->findChild() : nullptr) editors.append(editor); } return editors; } QStringList MainWindow::paneSessionNames(ResultDisplay* display) const { QStringList names = m_paneSessionTabs.value(display); if (names.isEmpty()) { const QString activeName = m_paneSessionNames.value(display); if (!activeName.isEmpty()) names.append(activeName); } return names; } void MainWindow::addSessionToActivePane(const QString& name) { if (m_widgets.display == nullptr || name.isEmpty()) return; QStringList names = paneSessionNames(m_widgets.display); const bool tabAdded = !names.contains(name, Qt::CaseInsensitive); const bool activeChanged = m_paneSessionNames.value(m_widgets.display).compare(name, Qt::CaseInsensitive) != 0; if (tabAdded) names.append(name); if (!tabAdded && !activeChanged) return; m_paneSessionTabs.insert(m_widgets.display, names); m_paneSessionNames.insert(m_widgets.display, name); updatePaneLoadedSessionCounts(); } ResultDisplay* MainWindow::tabBarDisplay(QTabBar* tabBar) const { return m_tabBarDisplays.value(tabBar, nullptr); } QTabBar* MainWindow::displayTabBar(ResultDisplay* display) const { return m_paneTabBars.value(display, nullptr); } void MainWindow::switchPaneToSession(ResultDisplay* display, const QString& name) { if (m_shutdownStateSaved) return; if (display == nullptr || name.isEmpty()) return; if (!m_paneTabBars.contains(display)) return; Session* session = m_loadedSessions.value(name, nullptr); if (session == nullptr) return; QWidget* page = display->parentWidget(); Editor* editor = page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (editor == nullptr) return; const QString currentName = m_paneSessionNames.value(display); if (!currentName.isEmpty() && currentName.compare(name, Qt::CaseInsensitive) != 0) { if (Session* currentSession = m_loadedSessions.value(currentName, nullptr)) currentSession->setEditorText(editor->text()); } const bool paneAlreadyShowsSession = display->session() == session && m_paneSessionNames.value(display).compare(name, Qt::CaseInsensitive) == 0; setActiveEditorDisplayPane(display, editor); activateSession(session); if (!paneAlreadyShowsSession) { editor->setText(session->editorText()); editor->setCursorPosition(editor->text().size()); } if (!paneAlreadyShowsSession) updatePaneTabBars(); } bool MainWindow::focusOpenSession(const QString& name) { if (name.isEmpty()) return false; QList> candidateWindows; candidateWindows.append(QPointer(this)); for (const QPointer& window : allMainWindows()) { if (window != nullptr && window != this) candidateWindows.append(window); } for (const QPointer& window : candidateWindows) { if (window == nullptr) continue; for (ResultDisplay* display : window->splitPaneDisplays()) { if (!window->paneSessionNames(display).contains(name, Qt::CaseInsensitive)) continue; QWidget* page = display->parentWidget(); Editor* editor = page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (editor == nullptr) continue; window->setActiveEditorDisplayPane(display, editor); window->switchPaneToSession(display, name); if (window->isMinimized()) window->showNormal(); window->raise(); window->activateWindow(); return true; } } return false; } void MainWindow::moveSessionTab(QTabBar* sourceTabBar, QTabBar* targetTabBar, const QString& name, int targetIndex) { if (m_shutdownStateSaved) return; ResultDisplay* sourceDisplay = tabBarDisplay(sourceTabBar); ResultDisplay* targetDisplay = tabBarDisplay(targetTabBar); if (targetDisplay == nullptr || name.isEmpty()) return; MainWindow* sourceWindow = this; if (sourceDisplay == nullptr && sourceTabBar != nullptr) sourceWindow = qobject_cast(sourceTabBar->window()); if (sourceDisplay == nullptr && sourceWindow != nullptr) sourceDisplay = sourceWindow->tabBarDisplay(sourceTabBar); if (sourceDisplay == nullptr || sourceWindow == nullptr) return; const bool crossWindowMove = sourceWindow != this; if (!crossWindowMove && !m_loadedSessions.contains(name)) return; if (crossWindowMove && !sourceWindow->m_loadedSessions.contains(name)) return; QStringList sourceNames = crossWindowMove ? sourceWindow->paneSessionNames(sourceDisplay) : paneSessionNames(sourceDisplay); if (!sourceNames.contains(name, Qt::CaseInsensitive)) return; QStringList targetNames = paneSessionNames(targetDisplay); if (crossWindowMove) { Session* sourceSession = sourceWindow->m_loadedSessions.value(name, nullptr); if (sourceSession == nullptr) return; Session* movedSession = new Session(*sourceSession); movedSession->setName(name); m_loadedSessions.insert(name, movedSession); applyUserDefinitions(); if (!targetNames.contains(name, Qt::CaseInsensitive)) targetNames.insert(qBound(0, targetIndex, targetNames.size()), name); m_paneSessionTabs.insert(targetDisplay, targetNames); m_paneSessionNames.insert(targetDisplay, name); switchPaneToSession(targetDisplay, name); sourceWindow->removeSessionTabFromPane(sourceDisplay, name, true); const auto referencedByRemainingPanes = [sourceWindow](const QString& sessionName) { for (ResultDisplay* display : sourceWindow->splitPaneDisplays()) { if (sourceWindow->paneSessionNames(display).contains(sessionName, Qt::CaseInsensitive)) return true; } return false; }; if (!referencedByRemainingPanes(name)) { Session* removedSession = sourceWindow->m_loadedSessions.take(name); sourceWindow->m_sessionViewportAnchors.remove(name); sourceWindow->m_sessionScrollValues.remove(name); if (removedSession != nullptr && removedSession != sourceWindow->m_session) delete removedSession; } sourceWindow->updatePaneLoadedSessionCounts(); sourceWindow->updatePaneTabBars(); sourceWindow->saveSessionLayout(false); updatePaneLoadedSessionCounts(); updatePaneTabBars(); saveSessionLayout(false); return; } if (sourceDisplay == targetDisplay) { const int sourceIndex = sourceNames.indexOf(name); sourceNames.removeAll(name); if (sourceIndex >= 0 && sourceIndex < targetIndex) --targetIndex; sourceNames.insert(qBound(0, targetIndex, sourceNames.size()), name); m_paneSessionTabs.insert(sourceDisplay, sourceNames); updatePaneTabBars(); saveSessionLayout(false); return; } sourceNames.removeAll(name); if (!targetNames.contains(name, Qt::CaseInsensitive)) targetNames.insert(qBound(0, targetIndex, targetNames.size()), name); if (sourceNames.isEmpty()) { if (splitPaneDisplays().size() > 1) { m_paneSessionTabs.insert(targetDisplay, targetNames); m_paneSessionNames.insert(targetDisplay, name); removePaneForDisplay(sourceDisplay); switchPaneToSession(targetDisplay, name); updatePaneLoadedSessionCounts(); updatePaneTabBars(); saveSessionLayout(false); return; } Session* replacement = createUntitledSession(false); if (replacement != nullptr) sourceNames.append(replacement->name()); } m_paneSessionTabs.insert(sourceDisplay, sourceNames); if (m_paneSessionNames.value(sourceDisplay).compare(name, Qt::CaseInsensitive) == 0) { m_paneSessionNames.insert(sourceDisplay, sourceNames.first()); if (Session* sourceSession = m_loadedSessions.value(sourceNames.first(), nullptr)) { sourceDisplay->setSession(sourceSession); sourceDisplay->refresh(); QWidget* page = sourceDisplay->parentWidget(); if (Editor* sourceEditor = page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr) { sourceEditor->setSession(sourceSession); sourceEditor->setText(sourceSession->editorText()); sourceEditor->setCursorPosition(sourceEditor->text().size()); sourceEditor->updateHistory(); sourceEditor->refreshAutoCalc(); } } } m_paneSessionTabs.insert(targetDisplay, targetNames); m_paneSessionNames.insert(targetDisplay, name); switchPaneToSession(targetDisplay, name); updatePaneLoadedSessionCounts(); updatePaneTabBars(); saveSessionLayout(false); } void MainWindow::rememberClosedSessionTab(ResultDisplay* display, const QString& name) { if (display == nullptr || name.isEmpty()) return; Session* session = m_loadedSessions.value(name, nullptr); if (session == nullptr || session->isPrivate()) return; if (display == m_widgets.display && session == m_session) captureEditorTextInCurrentSession(); ClosedSessionTab closedTab; closedTab.name = name; session->serialize(closedTab.sessionJson); closedTab.editorText = session->editorText(); closedTab.display = display; closedTab.tabIndex = paneSessionNames(display).indexOf(name); m_closedSessionTabs.append(closedTab); syncSessionMenuActionState(); } void MainWindow::restoreClosedSessionTab() { if (qApp->activeModalWidget() != nullptr || qApp->activePopupWidget() != nullptr) return; if (m_closedSessionTabs.isEmpty()) return; ClosedSessionTab closedTab = m_closedSessionTabs.last(); ResultDisplay* targetDisplay = nullptr; const QList displays = splitPaneDisplays(); if (closedTab.display != nullptr && displays.contains(closedTab.display) && displayTabBar(closedTab.display) != nullptr) { targetDisplay = closedTab.display; } else if (m_widgets.display != nullptr && displays.contains(m_widgets.display) && displayTabBar(m_widgets.display) != nullptr) { targetDisplay = m_widgets.display; } if (targetDisplay == nullptr) return; m_closedSessionTabs.removeLast(); syncSessionMenuActionState(); Session* session = m_loadedSessions.value(closedTab.name, nullptr); if (session == nullptr) { session = new Session(); if (!session->deSerialize(closedTab.sessionJson, false)) { delete session; return; } session->setName(closedTab.name); session->setEditorText(closedTab.editorText); m_loadedSessions.insert(closedTab.name, session); applyUserDefinitions(); } else { session->setEditorText(closedTab.editorText); } QStringList targetNames = paneSessionNames(targetDisplay); if (targetNames.contains(closedTab.name, Qt::CaseInsensitive)) { switchPaneToSession(targetDisplay, closedTab.name); return; } const int insertIndex = qBound(0, closedTab.tabIndex, targetNames.size()); targetNames.insert(insertIndex, closedTab.name); m_paneSessionTabs.insert(targetDisplay, targetNames); switchPaneToSession(targetDisplay, closedTab.name); updatePaneLoadedSessionCounts(); updatePaneTabBars(); saveSessionLayout(false); } void MainWindow::removeSessionTabFromPane(ResultDisplay* display, const QString& name, bool closePaneIfEmpty) { if (display == nullptr || name.isEmpty()) return; QStringList names = paneSessionNames(display); if (!names.contains(name, Qt::CaseInsensitive)) return; names.removeAll(name); if (names.isEmpty()) { if (closePaneIfEmpty) { removePaneForDisplay(display); return; } Session* replacement = createUntitledSession(false); if (replacement != nullptr) names.append(replacement->name()); } m_paneSessionTabs.insert(display, names); if (m_paneSessionNames.value(display).compare(name, Qt::CaseInsensitive) == 0) { m_paneSessionNames.insert(display, names.first()); if (Session* session = m_loadedSessions.value(names.first(), nullptr)) { QWidget* page = display->parentWidget(); if (Editor* editor = page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr) { // Removing a tab can switch the visible pane to another // session without changing keyboard focus. If this is the // active pane, update MainWindow::m_session too; otherwise the // window-level symbol docks keep reading the removed session // until the pane receives a click/focus event. if (display == m_widgets.display && editor == m_widgets.editor) { activateSession(session); } else { display->setSession(session); display->refresh(); editor->setText(session->editorText()); editor->setCursorPosition(editor->text().size()); editor->updateHistory(); editor->refreshAutoCalc(); } } } } } void MainWindow::removePaneForDisplay(ResultDisplay* display) { QWidget* pane = paneWidgetForDisplay(display); if (display == nullptr || pane == nullptr) return; const QList displays = splitPaneDisplays(); if (displays.size() <= 1) return; ResultDisplay* nextDisplay = nullptr; const int displayIndex = displays.indexOf(display); if (displayIndex >= 0 && displayIndex + 1 < displays.size()) nextDisplay = displays.at(displayIndex + 1); else if (displayIndex > 0) nextDisplay = displays.at(displayIndex - 1); else { for (ResultDisplay* candidate : displays) { if (candidate != display) { nextDisplay = candidate; break; } } } if (nextDisplay == nullptr) return; Editor* nextEditor = nextDisplay->parentWidget() ? nextDisplay->parentWidget()->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (nextEditor == nullptr) return; QTabBar* tabBar = displayTabBar(display); m_paneSessionNames.remove(display); m_paneSessionTabs.remove(display); m_paneTabBars.remove(display); if (tabBar != nullptr) m_tabBarDisplays.remove(tabBar); if (m_widgets.display == display) { m_widgets.display = nextDisplay; m_widgets.editor = nextEditor; m_copyWidget = nextEditor; if (Session* nextSession = m_loadedSessions.value(m_paneSessionNames.value(nextDisplay), nullptr)) activateSession(nextSession); } // Tab drags run a nested event loop. Defer physical pane destruction until // the drag unwinds so source/target widgets cannot disappear mid-event. deletePaneAfterSessionTabDrag(pane); normalizeSplitContainerTree(); } void MainWindow::moveSessionTabToPane(QTabBar* sourceTabBar, ResultDisplay* targetDisplay, const QString& name, const QPoint& panePos) { if (sourceTabBar == nullptr || targetDisplay == nullptr || name.isEmpty()) return; MainWindow* sourceWindow = qobject_cast(sourceTabBar->window()); ResultDisplay* sourceDisplay = tabBarDisplay(sourceTabBar); if (sourceDisplay == nullptr && sourceWindow != nullptr) sourceDisplay = sourceWindow->tabBarDisplay(sourceTabBar); if (sourceDisplay == nullptr || sourceWindow == nullptr) return; QWidget* targetPane = paneWidgetForDisplay(targetDisplay); if (targetPane == nullptr) return; PaneDropZone zone = PaneDropZone::Center; if (SessionPane* sessionPane = dynamic_cast(targetPane)) zone = sessionPane->dropZoneForPanePosition(panePos); const bool crossWindowMove = (sourceWindow != this); if (crossWindowMove) { QTabBar* targetTabBar = displayTabBar(targetDisplay); if (targetTabBar == nullptr) return; const int insertIndex = paneSessionNames(targetDisplay).size(); moveSessionTab(sourceTabBar, targetTabBar, name, insertIndex); if (zone == PaneDropZone::Center) return; QTabBar* localTargetTabBar = displayTabBar(targetDisplay); ResultDisplay* localSourceDisplay = localTargetTabBar ? tabBarDisplay(localTargetTabBar) : nullptr; if (localTargetTabBar == nullptr || localSourceDisplay == nullptr) return; switch (zone) { case PaneDropZone::Top: splitPaneWithSession(localTargetTabBar, targetDisplay, name, Qt::Vertical, false); return; case PaneDropZone::Bottom: splitPaneWithSession(localTargetTabBar, targetDisplay, name, Qt::Vertical, true); return; case PaneDropZone::Left: splitPaneWithSession(localTargetTabBar, targetDisplay, name, Qt::Horizontal, false); return; case PaneDropZone::Right: splitPaneWithSession(localTargetTabBar, targetDisplay, name, Qt::Horizontal, true); return; case PaneDropZone::Center: return; } } switch (zone) { case PaneDropZone::Center: if (sourceDisplay == targetDisplay) return; if (sourceWindow != this) { if (QTabBar* targetTabBar = displayTabBar(targetDisplay)) moveSessionTab(sourceTabBar, targetTabBar, name, paneSessionNames(targetDisplay).size()); return; } { QStringList targetNames = paneSessionNames(targetDisplay); if (!targetNames.contains(name, Qt::CaseInsensitive)) targetNames.append(name); m_paneSessionTabs.insert(targetDisplay, targetNames); m_paneSessionNames.insert(targetDisplay, name); removeSessionTabFromPane(sourceDisplay, name, true); switchPaneToSession(targetDisplay, name); updatePaneLoadedSessionCounts(); saveSessionLayout(false); } break; case PaneDropZone::Top: splitPaneWithSession(sourceTabBar, targetDisplay, name, Qt::Vertical, false); break; case PaneDropZone::Bottom: splitPaneWithSession(sourceTabBar, targetDisplay, name, Qt::Vertical, true); break; case PaneDropZone::Left: splitPaneWithSession(sourceTabBar, targetDisplay, name, Qt::Horizontal, false); break; case PaneDropZone::Right: splitPaneWithSession(sourceTabBar, targetDisplay, name, Qt::Horizontal, true); break; } } void MainWindow::splitPaneWithSession(QTabBar* sourceTabBar, ResultDisplay* targetDisplay, const QString& name, Qt::Orientation orientation, bool insertAfter) { ResultDisplay* sourceDisplay = tabBarDisplay(sourceTabBar); Session* session = m_loadedSessions.value(name, nullptr); if (sourceDisplay == nullptr || targetDisplay == nullptr || session == nullptr) return; QStringList sourceNames = paneSessionNames(sourceDisplay); if (!sourceNames.contains(name, Qt::CaseInsensitive)) return; QWidget* activePane = paneWidgetForDisplay(targetDisplay); QSplitter* parentSplitter = qobject_cast(activePane ? activePane->parentWidget() : nullptr); if (parentSplitter == nullptr) return; Editor* targetEditor = targetDisplay->parentWidget() ? targetDisplay->parentWidget()->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (targetEditor == nullptr) return; const int activeIndex = parentSplitter->indexOf(activePane); if (activeIndex < 0) return; const QList parentSizesBefore = parentSplitter->sizes(); const int activeSize = activeIndex < parentSizesBefore.size() ? parentSizesBefore.at(activeIndex) : qMax(1, orientation == Qt::Horizontal ? activePane->width() : activePane->height()); ResultDisplay* display = new ResultDisplay(); display->setFrameStyle(QFrame::NoFrame); display->setFont(targetDisplay->font()); display->setHoverHighlightEnabled(m_settings->hoverHighlightResults); display->setLoadedSessionCount(1); display->rehighlight(); Editor* editor = new Editor(); editor->setFrameStyle(QFrame::NoFrame); editor->setFont(targetEditor->font()); editor->setAutoCalcEnabled(m_settings->autoCalc); editor->setAutoCompletionEnabled(m_settings->autoCompletion); editor->setText(session->editorText()); editor->setCursorPosition(editor->text().size()); editor->rehighlight(); QWidget* pane = createEditorDisplayPane(display, editor); configureEditorDisplayPane(display, editor); QSplitter* targetSplitter = parentSplitter; if (parentSplitter->orientation() != orientation) { QSplitter* nestedSplitter = new QSplitter(orientation); nestedSplitter->setChildrenCollapsible(false); nestedSplitter->setHandleWidth(UiConfig::SessionPaneSplitterWidth); nestedSplitter->setStyleSheet(m_widgets.splitContainer->styleSheet()); activePane->setParent(nullptr); parentSplitter->insertWidget(activeIndex, nestedSplitter); if (insertAfter) { nestedSplitter->addWidget(activePane); nestedSplitter->addWidget(pane); } else { nestedSplitter->addWidget(pane); nestedSplitter->addWidget(activePane); } targetSplitter = nestedSplitter; if (parentSizesBefore.size() == parentSplitter->count()) parentSplitter->setSizes(parentSizesBefore); } else { const int insertIndex = insertAfter ? activeIndex + 1 : activeIndex; parentSplitter->insertWidget(insertIndex, pane); } m_paneSessionNames.insert(display, name); m_paneSessionTabs.insert(display, QStringList(name)); display->setSession(session); editor->setSession(session); const int firstHalf = qMax(1, activeSize / 2); const int secondHalf = qMax(1, activeSize - firstHalf); if (targetSplitter == parentSplitter) { QList sizes = parentSizesBefore; if (activeIndex < sizes.size()) { sizes[activeIndex] = insertAfter ? firstHalf : secondHalf; sizes.insert(insertAfter ? activeIndex + 1 : activeIndex, insertAfter ? secondHalf : firstHalf); if (sizes.size() == targetSplitter->count()) targetSplitter->setSizes(sizes); } } else { targetSplitter->setSizes(QList({ firstHalf, secondHalf })); } display->refresh(); editor->updateHistory(); editor->refreshAutoCalc(); removeSessionTabFromPane(sourceDisplay, name, true); updateSplitterStyleSheet(); updatePaneLoadedSessionCounts(); setActiveEditorDisplayPane(display, editor); updatePaneTabBars(); saveSessionLayout(false); } void MainWindow::updatePaneLoadedSessionCounts() { const bool multiplePanes = splitPaneDisplays().size() > 1; for (ResultDisplay* display : splitPaneDisplays()) { display->setLoadedSessionCount(paneSessionNames(display).size()); display->setCloseSessionEnabled(multiplePanes || paneSessionNames(display).size() > 1); } updatePaneTabBars(); updatePaneEditorCursorVisibility(); } void MainWindow::updatePaneEditorCursorVisibility() { const QPointer activeDisplay = globallyActiveDisplay(); const QPointer activeEditor = globallyActiveEditor(); const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); const int windowCount = std::count_if(allMainWindows().cbegin(), allMainWindows().cend(), [](const QPointer& window) { return !window.isNull(); }); QSet updatedWindows; for (const QPointer& ptr : allMainWindows()) { MainWindow* window = ptr.data(); if (window == nullptr || updatedWindows.contains(window)) continue; updatedWindows.insert(window); const QList displays = window->splitPaneDisplays(); const bool showActiveOutline = m_settings->editorDisplayStyle != Settings::EditorDisplayClassic || windowCount != 1 || displays.size() != 1; QSet updatedEditors; for (ResultDisplay* display : displays) { QWidget* page = display->parentWidget(); Editor* editor = page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; const bool active = activeDisplay != nullptr && activeEditor != nullptr && display == activeDisplay && editor == activeEditor; if (editor != nullptr) { updatedEditors.insert(editor); const bool editorFocused = active && !editor->isConstantSearchVisible(); editor->setCustomCursorVisible(editorFocused); editor->setThemePrimaryColor(surfaces.primary.background, editorFocused && showActiveOutline); } } for (Editor* editor : window->splitPaneEditors()) { if (editor == nullptr || updatedEditors.contains(editor)) continue; editor->setCustomCursorVisible(false); editor->setThemePrimaryColor(surfaces.primary.background, false); } window->updateActiveSessionPaneTabColor(); } } void MainWindow::updateActiveSessionPaneTabColor() { const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); const QList displays = splitPaneDisplays(); for (ResultDisplay* display : displays) { QTabBar* tabBar = displayTabBar(display); SessionTabBar* sessionTabBar = dynamic_cast(tabBar); if (sessionTabBar == nullptr) continue; sessionTabBar->setActivePaneSelectedTabIndicatorColor(QColor()); } ResultDisplay* activeDisplay = globallyActiveDisplay(); if (activeDisplay == nullptr || activeDisplay->window() != this) { if (QApplication::activeWindow() != this) return; activeDisplay = m_widgets.display; } SessionTabBar* activeTabBar = dynamic_cast(displayTabBar(activeDisplay)); if (activeTabBar != nullptr) activeTabBar->setActivePaneSelectedTabIndicatorColor(surfaces.primary.background); } void MainWindow::updatePaneTabBars() { const QList displays = splitPaneDisplays(); const bool singlePaneSingleTab = displays.size() == 1 && paneSessionNames(displays.first()).size() == 1; const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); const ThemeSurfaceColors selectedSessionTab = themeSurfaceForShadeIndex(surfaces, UiConfig::SelectedSessionTabFillShade); const ThemeSurfaceColors hoveredSessionTab = themeSurfaceForShadeIndex(surfaces, UiConfig::HoveredSessionTabFillShade); const ThemeSurfaceColors closeButtonHover = themeSurfaceForShadeIndex(surfaces, UiConfig::SessionTabCloseButtonHoverFillShade); const ThemeSurfaceColors toolTip = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupBackgroundShade); const ThemeSurfaceColors toolTipOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupOutlineShade); for (ResultDisplay* display : displays) { QTabBar* tabBar = displayTabBar(display); if (tabBar == nullptr) continue; static_cast(tabBar)->applyStyle( selectedSessionTab.foreground, selectedSessionTab.background, hoveredSessionTab.foreground, hoveredSessionTab.background, surfaces.window.background, surfaces.window.foreground, closeButtonHover.foreground, closeButtonHover.background, toolTip.background, toolTip.foreground, toolTipOutline.background, UiConfig::CompletionPopupCornerRadius); const QSignalBlocker blocker(tabBar); const QStringList names = paneSessionNames(display); bool tabsAlreadyMatch = tabBar->count() == names.size(); for (int i = 0; tabsAlreadyMatch && i < names.size(); ++i) tabsAlreadyMatch = tabBar->tabText(i) == names.at(i); if (!tabsAlreadyMatch) { while (tabBar->count() > 0) tabBar->removeTab(0); for (const QString& name : names) tabBar->addTab(name); } for (int i = 0; i < names.size(); ++i) { const Session* session = m_loadedSessions.value(names.at(i)); const bool isPrivate = session && session->isPrivate(); tabBar->setTabIcon(i, isPrivate ? privateSessionIcon(selectedSessionTab.foreground) : QIcon()); tabBar->setTabToolTip(i, isPrivate ? tr("%1\nPrivate session: contents are discarded when closed.\n" "Choose Session > Keep to turn it into a regular session." ).arg(names.at(i)) : QString()); } const int activeIndex = names.indexOf(m_paneSessionNames.value(display)); tabBar->setCurrentIndex(activeIndex >= 0 ? activeIndex : 0); // tabBar->setUsesScrollButtons(names.size() > 4); tabBar->setVisible(!singlePaneSingleTab); static_cast(tabBar)->refreshCloseButtons(); } updateSessionWindowTitle(); updateActiveSessionPaneTabColor(); } void MainWindow::updateSessionWindowTitle() { syncSessionMenuActionState(); if (m_session && m_session->isPrivate()) { setWindowTitle(tr("SpeedCrunch - %1 [Private]").arg(m_session->name())); return; } const QList displays = splitPaneDisplays(); if (displays.size() == 1) { const QStringList names = paneSessionNames(displays.first()); if (names.size() == 1) { setWindowTitle(QStringLiteral("SpeedCrunch - %1").arg(names.first())); return; } } setWindowTitle(QStringLiteral("SpeedCrunch")); } void MainWindow::normalizeSplitContainerTree() { normalizeSplitterTree(m_widgets.splitContainer); } void MainWindow::updateSplitterStyleSheet() { StartupDiagnostics::AppearanceScope timing("Style session splitters", this); if (m_widgets.splitContainer == nullptr) return; const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); const bool classic = m_settings->editorDisplayStyle == Settings::EditorDisplayClassic; const QColor handle = themeSurfaceForShadeIndex( surfaces, classic ? UiConfig::ClassicVerticalPaneDividerShade : UiConfig::SplitterShade).background; const QColor hoveredHandle = UiConfig::SplitterHoverUsesPrimary ? surfaces.primary.background : themeSurfaceForShadeIndex(surfaces, UiConfig::SplitterHoverShade).background; const bool systemDocks = m_settings->dockAppearance == Settings::DockAppearanceSystem; const QPalette systemPalette = MenuStyle::systemPalette(this); setProperty(DockSeparatorNormalColorProperty, systemDocks ? systemPalette.color(QPalette::Mid) : handle); setProperty(DockSeparatorActiveColorProperty, systemDocks ? systemPalette.color(QPalette::Highlight) : hoveredHandle); setProperty(DockSeparatorBackgroundColorProperty, systemDocks ? systemPalette.color(QPalette::Window) : QColor()); setProperty(DockSeparatorStrokeWidthProperty, systemDocks ? UiConfig::SystemDockSplitterStrokeWidth : UiConfig::DockSplitterStrokeWidth); const QColor classicPaneDivider = themeSurfaceForShadeIndex( surfaces, UiConfig::ClassicVerticalPaneDividerShade).background; const QString styleSheet = splitterStyleSheet(handle, hoveredHandle); const QString classicVerticalStyleSheet = splitterStyleSheet(classicPaneDivider, hoveredHandle); const auto applyStyle = [classic, &styleSheet, &classicVerticalStyleSheet]( QSplitter* splitter, const auto& applyStyleRef) -> void { if (splitter == nullptr) return; setStyleSheetIfChanged(splitter, classic && splitter->orientation() == Qt::Horizontal ? classicVerticalStyleSheet : styleSheet); for (int i = 0; i < splitter->count(); ++i) { if (QSplitter* childSplitter = qobject_cast(splitter->widget(i))) applyStyleRef(childSplitter, applyStyleRef); } }; applyStyle(m_widgets.splitContainer, applyStyle); for (QSplitterHandle* splitterHandle : findChildren()) { splitterHandle->installEventFilter(this); const bool classicVerticalDivider = classic && splitterHandle->orientation() == Qt::Horizontal && m_widgets.splitContainer->isAncestorOf(splitterHandle); setStyleSheetIfChanged(splitterHandle, splitterHandleStyleSheet( classicVerticalDivider ? classicPaneDivider : handle, hoveredHandle)); splitterHandle->update(); } } void MainWindow::refreshPaneThemes() { // Settings actions can emit several appearance signals during startup. // The constructor applies the final pane theme once those settings settle. if (m_initializingUi) return; StartupDiagnostics::AppearanceScope timing("Apply pane themes", this); timing.observeInputs("theme", StartupDiagnostics::configuredThemeInputs()); StartupDiagnostics::observeAppearanceSettings(timing); if (StartupDiagnostics::isRecording()) { QVariantList panes; for (ResultDisplay* display : splitPaneDisplays()) panes.append(StartupDiagnostics::appearanceObjectId(display)); for (Editor* editor : splitPaneEditors()) panes.append(StartupDiagnostics::appearanceObjectId(editor)); timing.observeInputs("panes", StartupDiagnostics::appearanceInputs(panes)); } const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); applyThemeBackgroundRoleToWidget(m_widgets.splitContainer, surfaces.window.background); const ThemeSurfaceColors resultToolTip = themeSurfaceForShadeIndex(surfaces, UiConfig::ResultTooltipBackgroundShade); const ThemeSurfaceColors resultToolTipOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::ResultTooltipOutlineShade); for (ResultDisplay* display : splitPaneDisplays()) { display->setThemeSurfaceColor(surfaces.result.background); display->setThemeToolTipColors(resultToolTip.background, resultToolTip.foreground, resultToolTipOutline.background); display->setThemeInteractionColors(surfaces.editorAndLists.background, surfaces.primary.background, surfaces.headersAndBorders.background, surfaces.headersAndBorders.foreground, surfaces.inputs.background, surfaces.inputs.foreground); display->rehighlight(); QWidget* page = display->parentWidget(); applyThemeBackgroundRoleToWidget(page, surfaces.result.background); applyThemeBackgroundRoleToWidget(page ? page->parentWidget() : nullptr, surfaces.result.background); applyThemeBackgroundRoleToWidget(paneWidgetForDisplay(display), surfaces.result.background); } for (Editor* editor : splitPaneEditors()) { editor->setThemeSurfaceColor(surfaces.editorAndLists.background, surfaces.result.background); const ThemeSurfaceColors completionPopup = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupBackgroundShade); const ThemeSurfaceColors completionScrollbarThumb = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupScrollbarThumbShade); const ThemeSurfaceColors completionSelectedRow = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupSelectedRowShade); const ThemeSurfaceColors completionOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupOutlineShade); editor->setThemeCompletionColors(completionPopup.background, completionPopup.foreground, completionScrollbarThumb.background, completionScrollbarThumb.foreground, completionSelectedRow.background, completionSelectedRow.foreground, completionOutline.background, UiConfig::CompletionPopupCornerRadius, surfaces.primary.background, surfaces.primary.foreground); editor->rehighlight(); } updatePaneEditorCursorVisibility(); updatePaneTabBars(); updateSplitterStyleSheet(); } void MainWindow::applyDockTabBarAppearance() { StartupDiagnostics::AppearanceScope timing("Apply dock tab bar appearance", this); const GeneratedThemeSurfaces tabSurfaces = generatedSurfaceColors(m_settings); for (QTabBar* tabBar : findChildren()) { if (m_tabBarDisplays.contains(tabBar)) continue; saveNativeDockSurface(tabBar); if (!tabBar->property("speedcrunchNativeDockTabBar").isValid()) { const QVariantList state {tabBar->drawBase(), QVariant::fromValue(tabBar->cursor()), tabBar->hasMouseTracking(), tabBar->testAttribute(Qt::WA_Hover)}; tabBar->setProperty("speedcrunchNativeDockTabBar", state); } QWidget* tabBarParent = tabBar->parentWidget(); const bool separateParent = tabBarParent != nullptr && tabBarParent != this && !qobject_cast(tabBarParent); if (separateParent) saveNativeDockSurface(tabBarParent); if (m_settings->dockAppearance == Settings::DockAppearanceSystem) { tabBar->setProperty("speedcrunchDockSystemTabBar", false); tabBar->removeEventFilter(this); restoreNativeDockSurface(tabBar); const QVariantList state = tabBar->property("speedcrunchNativeDockTabBar").toList(); tabBar->setDrawBase(state.at(0).toBool()); tabBar->setCursor(state.at(1).value()); tabBar->setMouseTracking(state.at(2).toBool()); tabBar->setAttribute(Qt::WA_Hover, state.at(3).toBool()); // Fill unused space with system colors instead of the main window theme. tabBar->setAutoFillBackground(true); if (separateParent) { restoreNativeDockSurface(tabBarParent); tabBarParent->setAutoFillBackground(true); } continue; } if (separateParent) { applyDockTabBarBackgroundToWidget(tabBarParent, tabSurfaces.window); } const QPalette tabBarPalette = paletteForThemeSurface(tabBar->palette(), tabSurfaces.headersAndBorders); if (!tabBar->property("speedcrunchDockSystemTabBar").toBool()) { tabBar->setProperty("speedcrunchDockSystemTabBar", true); tabBar->setMouseTracking(true); tabBar->setAttribute(Qt::WA_Hover, true); tabBar->installEventFilter(this); } updateDockSystemTabCursor(tabBar, tabBar->mapFromGlobal(QCursor::pos())); tabBar->setDrawBase(false); StartupDiagnostics::setAppearancePalette(tabBar, tabBarPalette); setStyleSheetIfChanged(tabBar, QStringLiteral( "QTabBar { background-color: %1; }" "QTabBar::tab {" " background-color: transparent; color: %2;" " padding: 5px 14px; margin: 2px 1px;" "}" "QTabBar::tab:!selected:hover {" " background-color: %3; color: %4;" " border-radius: 10px;" "}" "QTabBar::tab:selected {" " background-color: %5; color: %6;" " border-radius: 10px;" "}") .arg(tabSurfaces.window.background.name(), tabSurfaces.window.foreground.name(), tabSurfaces.result.background.name(), tabSurfaces.result.foreground.name(), tabSurfaces.headersAndBorders.background.name(), tabSurfaces.headersAndBorders.foreground.name())); StartupDiagnostics::setAppearancePalette(tabBar, tabBarPalette); } } void MainWindow::applyThemeSurfacePalette() { StartupDiagnostics::AppearanceScope timing("Apply window theme palette", this); timing.observeInputs("theme", StartupDiagnostics::configuredThemeInputs()); StartupDiagnostics::observeAppearanceSettings(timing); const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); if (UiConfig::OklchThemeDebugReportEnabled) { const QString reportKey = oklchThemeReportKey(surfaces); if (reportKey != lastOklchThemeReportKey()) { const QString reportPath = writeOklchGenerationHtmlReport(surfaces.base, 1, surfaces.backgrounds.size() - 2, surfaces.polarity, defaultOklchShadeDistanceFactor(), false, surfaces.backgrounds, surfaces.foregrounds, UiConfig::GeneratedTextMinimumContrast); if (!reportPath.isEmpty()) { lastOklchThemeReportKey() = reportKey; QTextStream stream(stderr); stream << "OKLCH HTML report: " << reportPath << Qt::endl; scheduleThemeRuntimeDiagnosticsReport(); } } } const ThemeSurfaceColors& surface = surfaces.window; applyWindowThemeBackground(this, surface); MenuStyle::refresh(); if (m_widgets.root) applyThemeBackgroundRoleToWidget(m_widgets.root, surface.background); applyKeypadThemeSurfacePalette(); applyStatusBarAppearance(findChild(QString(), Qt::FindDirectChildrenOnly), surfaces); for (QDockWidget* dock : m_allDocks) { if (dock == nullptr) continue; applyDockAppearance(this, dock, surfaces); } applyDockTabBarAppearance(); // The direct pass has already polished the controls for the current style. m_dockNativePolishPending = false; scheduleDockAppearanceRefresh(); } void MainWindow::restoreWindowThemeBackgrounds() { StartupDiagnostics::AppearanceScope timing("Restore window theme backgrounds", this); timing.observeInputs("theme", StartupDiagnostics::configuredThemeInputs()); StartupDiagnostics::observeAppearanceSettings(timing); const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); // Native polishing can change inherited palettes after the window is shown. applyWindowThemeBackground(this, surfaces.window); MenuStyle::refresh(); applyThemeBackgroundRoleToWidget(m_widgets.root, surfaces.window.background); // Keep the deferred dock pass after native layout and palette updates settle. scheduleDockAppearanceRefresh(); } void MainWindow::scheduleDockAppearanceRefresh(bool forceNativePolish) { if (m_initializingUi) return; m_dockNativePolishPending = m_dockNativePolishPending || forceNativePolish; if (m_dockAppearanceRefreshPending) return; m_dockAppearanceRefreshPending = true; QTimer::singleShot(0, this, [this]() { StartupDiagnostics::AppearanceContext context("Deferred dock refresh"); StartupDiagnostics::AppearanceScope timing("Refresh deferred dock appearance", this); timing.observeInputs("theme", StartupDiagnostics::configuredThemeInputs()); StartupDiagnostics::observeAppearanceSettings(timing); const bool forceNativePolish = m_dockNativePolishPending; m_dockNativePolishPending = false; const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); MenuStyle::refresh(); const QList docks = m_allDocks; for (QDockWidget* dock : docks) { applyDockAppearance(this, dock, surfaces, forceNativePolish); } applyDockTabBarAppearance(); updateSplitterStyleSheet(); m_dockAppearanceRefreshPending = false; if (m_dockNativePolishPending) scheduleDockAppearanceRefresh(true); }); } void MainWindow::applyKeypadThemeSurfacePalette() { StartupDiagnostics::AppearanceScope timing("Apply keypad theme palette", m_widgets.keypad); if (!m_widgets.keypad) return; const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); const ThemeSurfaceColors keypadBackground = themeSurfaceForShadeIndex(surfaces, UiConfig::KeypadBackgroundShade); const QPalette keypadPalette = paletteForThemeSurface(palette(), keypadBackground); const ThemeSurfaceColors keypadButton = themeSurfaceForShadeIndex(surfaces, UiConfig::KeypadButtonShade); const ThemeSurfaceColors keypadButtonHover = themeSurfaceForShadeIndex(surfaces, UiConfig::KeypadButtonHoverShade); const ThemeSurfaceColors keypadButtonPressed = themeSurfaceForShadeIndex(surfaces, UiConfig::KeypadButtonPressedShade); const ThemeSurfaceColors keypadToolTip = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupBackgroundShade); const ThemeSurfaceColors keypadToolTipOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::CompletionPopupOutlineShade); applyThemeBackgroundRoleToWidget(m_widgets.keypadContainer, keypadBackground.background); StartupDiagnostics::setAppearancePalette(m_widgets.keypad, keypadPalette); m_widgets.keypad->setAutoFillBackground(true); const QPointer keypad = m_widgets.keypad; QTimer::singleShot(0, this, [keypad, keypadPalette]() { if (!keypad) return; StartupDiagnostics::AppearanceContext context("Deferred keypad refresh"); StartupDiagnostics::AppearanceScope timing("Refresh deferred keypad palette", keypad); StartupDiagnostics::setAppearancePalette(keypad, keypadPalette); keypad->setAutoFillBackground(true); QEvent paletteChange(QEvent::PaletteChange); QApplication::sendEvent(keypad, &paletteChange); }); m_widgets.keypad->setToolTipThemeColors(keypadToolTip.background, keypadToolTip.foreground, keypadToolTipOutline.background, UiConfig::CompletionPopupCornerRadius); m_widgets.keypad->setThemeButtonColors(keypadButton.background, keypadButton.foreground, keypadButtonHover.background, keypadButtonHover.foreground, keypadButtonPressed.background, keypadButtonPressed.foreground, surfaces.primary.background); QEvent paletteChange(QEvent::PaletteChange); QApplication::sendEvent(m_widgets.keypad, &paletteChange); } void MainWindow::scheduleThemeRuntimeDiagnosticsReport() { writeThemeRuntimeDiagnosticsReport(); QPointer guard(this); QTimer::singleShot(150, this, [guard]() { if (guard) guard->writeThemeRuntimeDiagnosticsReport(); }); } void MainWindow::writeThemeRuntimeDiagnosticsReport() { const QString path = oklchThemeReportPath(); QFile file(path); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QString html = QString::fromUtf8(file.readAll()); file.close(); if (html.isEmpty()) return; const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); QString section; QTextStream out(§ion); out << "\n\n" << "
    \n" << "

    Runtime widget samples

    \n" << "

    Generated after the " << "live window has restored its saved layout and the Qt event loop has " << "repainted. These values are read from widget palettes, style sheets, " << "and widget grabs inside the running application.

    \n" << "

    Executable: " << QCoreApplication::applicationFilePath().toHtmlEscaped() << "

    \n" << "

    Expected shades: "; for (int i = 0; i < surfaces.backgrounds.size(); ++i) { if (i > 0) out << " "; out << "" << i << "=" << debugColorName(surfaces.backgrounds.at(i)) << ""; } out << "

    \n" << "
    " << "" << "" << "" << "" << "" << "" << "" << "" << "\n"; appendDiagnosticRow(out, QStringLiteral("MainWindow"), debugColorName(surfaces.window.background), paletteColorName(this, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(this), shortStyleSheet(this)); appendDiagnosticRow(out, QStringLiteral("MainSplitContainer"), debugColorName(surfaces.window.background), paletteColorName(m_widgets.splitContainer, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(m_widgets.splitContainer), shortStyleSheet(m_widgets.splitContainer)); int displayIndex = 0; for (ResultDisplay* display : splitPaneDisplays()) { ++displayIndex; QWidget* page = display ? display->parentWidget() : nullptr; QWidget* stack = page ? page->parentWidget() : nullptr; QWidget* pane = display ? paneWidgetForDisplay(display) : nullptr; appendDiagnosticRow(out, QStringLiteral("ResultDisplay %1").arg(displayIndex), debugColorName(surfaces.result.background), paletteColorName(display, QPalette::Base), paletteColorName(display ? display->viewport() : nullptr, QPalette::Base), grabbedCenterColorName(display ? display->viewport() : nullptr), shortStyleSheet(display)); appendDiagnosticRow(out, QStringLiteral("ResultDisplay %1 viewport").arg(displayIndex), debugColorName(surfaces.result.background), paletteColorName(display ? display->viewport() : nullptr, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(display ? display->viewport() : nullptr), shortStyleSheet(display ? display->viewport() : nullptr)); appendDiagnosticRow(out, QStringLiteral("ResultDisplay %1 page").arg(displayIndex), debugColorName(surfaces.result.background), paletteColorName(page, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(page), shortStyleSheet(page)); appendDiagnosticRow(out, QStringLiteral("ResultDisplay %1 stack").arg(displayIndex), debugColorName(surfaces.result.background), paletteColorName(stack, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(stack), shortStyleSheet(stack)); appendDiagnosticRow(out, QStringLiteral("ResultDisplay %1 pane").arg(displayIndex), debugColorName(surfaces.result.background), paletteColorName(pane, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(pane), shortStyleSheet(pane)); } int editorIndex = 0; for (Editor* editor : splitPaneEditors()) { ++editorIndex; appendDiagnosticRow(out, QStringLiteral("Editor %1").arg(editorIndex), debugColorName(surfaces.editorAndLists.background), paletteColorName(editor, QPalette::Base), paletteColorName(editor ? editor->viewport() : nullptr, QPalette::Base), grabbedCenterColorName(editor), shortStyleSheet(editor)); } const ThemeSurfaceColors keypadBackground = themeSurfaceForShadeIndex(surfaces, UiConfig::KeypadBackgroundShade); appendDiagnosticRow(out, QStringLiteral("Keypad"), debugColorName(keypadBackground.background), paletteColorName(m_widgets.keypad, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(m_widgets.keypad), shortStyleSheet(m_widgets.keypad)); appendDiagnosticRow(out, QStringLiteral("Bitfield"), debugColorName(surfaces.editorAndLists.background), paletteColorName(m_widgets.bitField, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(m_widgets.bitField), shortStyleSheet(m_widgets.bitField)); if (QStatusBar* bar = findChild(QString(), Qt::FindDirectChildrenOnly)) { const ThemeSurfaceColors statusBarSurface = themeSurfaceForShadeIndex(surfaces, UiConfig::StatusBarBackgroundShade); appendDiagnosticRow(out, QStringLiteral("StatusBar"), debugColorName(statusBarSurface.background), paletteColorName(bar, QPalette::Window), QStringLiteral("(n/a)"), grabbedCenterColorName(bar), shortStyleSheet(bar)); } out << "
    WidgetExpectedPaletteViewport paletteGrab centerStyle sheet
    \n" << "
    \n" << "\n"; const QString startMarker = QStringLiteral(""); const QString endMarker = QStringLiteral(""); const int start = html.indexOf(startMarker); const int end = start >= 0 ? html.indexOf(endMarker, start) : -1; if (start >= 0 && end >= 0) html.remove(start, end + endMarker.size() - start); const int insertAt = html.lastIndexOf(QStringLiteral("")); if (insertAt >= 0) html.insert(insertAt, section); else html.append(section); if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) return; file.write(html.toUtf8()); file.close(); } void MainWindow::captureVisibleSessionViewports() { for (ResultDisplay* display : splitPaneDisplays()) { if (display == nullptr) continue; QString sessionName = m_paneSessionNames.value(display); if (sessionName.isEmpty() && display->session() != nullptr) sessionName = display->session()->name(); if (sessionName.isEmpty()) continue; m_sessionViewportAnchors.insert(sessionName, display->viewportTopAnchor()); QScrollBar* bar = display->verticalScrollBar(); const int scrollValue = bar->value() == bar->maximum() ? (std::numeric_limits::max)() : bar->value(); m_sessionScrollValues.insert(sessionName, scrollValue); } } void MainWindow::restoreVisibleSessionViewports() { StartupDiagnostics::Scope timing("Restore visible history viewports"); for (ResultDisplay* display : splitPaneDisplays()) { if (display == nullptr) continue; QString sessionName = m_paneSessionNames.value(display); if (sessionName.isEmpty() && display->session() != nullptr) sessionName = display->session()->name(); if (sessionName.isEmpty()) continue; const QPair anchor = m_sessionViewportAnchors.value(sessionName, qMakePair(-1, 0)); const int scrollValue = m_sessionScrollValues.value(sessionName, -1); if (anchor.first >= 0) display->restoreViewportTopAnchor(anchor); if (scrollValue >= 0) display->restoreScrollValue(scrollValue); } } void MainWindow::createBitField() { StartupDiagnostics::Scope timing("Create bitfield dock"); if (m_docks.bitField) { m_docks.bitField->show(); m_docks.bitField->raise(); m_settings->bitfieldVisible = true; return; } m_docks.bitField = new GenericDock("MainWindow", QT_TR_NOOP("Bitfield"), this); m_docks.bitField->setObjectName("BitfieldDock"); m_docks.bitField->installEventFilter(this); m_docks.bitField->setAllowedAreas(Qt::AllDockWidgetAreas); m_widgets.bitField = m_docks.bitField->widget(); addTabifiedDock(m_docks.bitField, false, Qt::BottomDockWidgetArea); m_widgets.display->verticalScrollBar()->setValue(m_widgets.display->verticalScrollBar()->maximum()); connect(m_widgets.bitField, SIGNAL(bitsChanged(const QString&)), SLOT(handleBitsChanged(const QString&))); m_settings->bitfieldVisible = true; } void MainWindow::createKeypad() { StartupDiagnostics::Scope timing("Create keypad"); if (m_widgets.keypad) return; m_widgets.keypadContainer = new QWidget(m_widgets.root); if (m_keypadMode == Settings::KeypadModeCustom) { QList customButtons; for (const auto& button : m_settings->customKeypad.buttons) { if (button.row < 0 || button.row >= m_settings->customKeypad.rows || button.column < 0 || button.column >= m_settings->customKeypad.columns) { continue; } Keypad::CustomButtonDescription description; description.label = button.label; description.text = button.text; description.action = static_cast(button.action); description.row = button.row; description.column = button.column; customButtons.append(description); } m_widgets.keypad = new Keypad(customButtons, m_widgets.keypadContainer, m_keypadZoomPercent); connect(m_widgets.keypad, &Keypad::customButtonPressed, this, &MainWindow::handleCustomKeypadButtonPress); } else { Keypad::LayoutMode layoutMode = Keypad::LayoutModeScientificWide; if (m_keypadMode == Settings::KeypadModeBasicWide) layoutMode = Keypad::LayoutModeBasicWide; else if (m_keypadMode == Settings::KeypadModeScientificNarrow) layoutMode = Keypad::LayoutModeScientificNarrow; m_widgets.keypad = new Keypad(layoutMode, m_widgets.keypadContainer, m_keypadZoomPercent); connect(m_widgets.keypad, SIGNAL(buttonPressed(Keypad::Button)), SLOT(handleKeypadButtonPress(Keypad::Button))); connect(this, SIGNAL(radixCharacterChanged()), m_widgets.keypad, SLOT(handleRadixCharacterChange())); } m_widgets.keypad->setFocusPolicy(Qt::NoFocus); applyKeypadAppearance(); m_widgets.keypad->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_widgets.keypad, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(showKeypadContextMenu(const QPoint&))); m_layouts.keypad = new QHBoxLayout(m_widgets.keypadContainer); m_layouts.keypad->setContentsMargins(0, 0, 0, 0); m_layouts.keypad->addStretch(); m_layouts.keypad->addWidget(m_widgets.keypad); m_layouts.keypad->addStretch(); m_widgets.keypad->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_layouts.root->addWidget(m_widgets.keypadContainer, 0); m_widgets.keypadContainer->show(); m_widgets.keypad->show(); applyKeypadThemeSurfacePalette(); } void MainWindow::createBookDock(bool) { StartupDiagnostics::Scope timing("Create formula book dock"); if (m_docks.book) { m_docks.book->show(); m_docks.book->raise(); m_settings->formulaBookDockVisible = true; return; } m_docks.book = new BookDock(this); m_docks.book->setObjectName("BookDock"); m_docks.book->installEventFilter(this); m_docks.book->setAllowedAreas(Qt::AllDockWidgetAreas); connect(m_docks.book, SIGNAL(expressionSelected(const QString&)), SLOT(insertTextIntoEditor(const QString&))); // No focus for this dock. addTabifiedDock(m_docks.book, false); if (!m_settings->formulaBookActivePage.isEmpty()) m_docks.book->openPage(QUrl(m_settings->formulaBookActivePage)); m_settings->formulaBookDockVisible = true; } void MainWindow::createConstantsDock(bool takeFocus) { StartupDiagnostics::Scope timing("Create constants dock"); if (m_docks.constants) { m_docks.constants->show(); m_docks.constants->raise(); if (takeFocus) m_docks.constants->setFocus(); m_settings->constantsDockVisible = true; return; } const ConstantsWidget::InitialState state {m_settings->constantsDockDomain, m_settings->constantsDockSubdomain, m_settings->constantsDockSearchText}; m_docks.constants = new GenericDock("MainWindow", QT_TR_NOOP("Constants"), this, state); m_docks.constants->setObjectName("ConstantsDock"); m_docks.constants->setMinimumWidth(UiConfig::ConstantsDockMinimumWidth); m_docks.constants->installEventFilter(this); m_docks.constants->setAllowedAreas(Qt::AllDockWidgetAreas); connect(m_docks.constants->widget(), &ConstantsWidget::constantSelected, this, &MainWindow::insertConstantIntoEditor); connect(this, &MainWindow::radixCharacterChanged, m_docks.constants->widget(), &ConstantsWidget::handleRadixCharacterChange); addTabifiedDock(m_docks.constants, takeFocus); m_settings->constantsDockVisible = true; } void MainWindow::createFunctionsDock(bool takeFocus) { StartupDiagnostics::Scope timing("Create functions dock"); if (m_docks.functions) { m_docks.functions->show(); m_docks.functions->raise(); if (takeFocus) m_docks.functions->setFocus(); m_settings->functionsDockVisible = true; return; } const FunctionsWidget::InitialState state {m_settings->functionsDockDomain, m_settings->functionsDockSearchText}; m_docks.functions = new GenericDock("MainWindow", QT_TR_NOOP("Functions"), this, state); m_docks.functions->setObjectName("FunctionsDock"); m_docks.functions->installEventFilter(this); m_docks.functions->setAllowedAreas(Qt::AllDockWidgetAreas); connect(m_docks.functions->widget(), &FunctionsWidget::functionSelected, this, &MainWindow::insertFunctionIntoEditor); addTabifiedDock(m_docks.functions, takeFocus); m_settings->functionsDockVisible = true; } void MainWindow::createHistoryDock(bool) { StartupDiagnostics::Scope timing("Create history dock"); if (m_docks.history) { m_docks.history->show(); m_docks.history->raise(); m_settings->historyDockVisible = true; return; } m_docks.history = new GenericDock("MainWindow", QT_TR_NOOP("History"), this); m_docks.history->setObjectName("HistoryDock"); m_docks.history->installEventFilter(this); m_docks.history->setAllowedAreas(Qt::AllDockWidgetAreas); connect(m_docks.history->widget(), &HistoryWidget::expressionSelected, this, &MainWindow::insertHistoryExpressionIntoEditor); connect(m_docks.history->widget(), &HistoryWidget::removeHistoryEntryRequested, this, &MainWindow::removeHistoryEntryAt); connect(m_docks.history->widget(), &HistoryWidget::removeHistoryEntriesAboveRequested, this, &MainWindow::removeHistoryEntriesAbove); connect(m_docks.history->widget(), &HistoryWidget::removeHistoryEntriesBelowRequested, this, &MainWindow::removeHistoryEntriesBelow); connect(this, &MainWindow::historyChanged, m_docks.history->widget(), &HistoryWidget::updateHistory); m_docks.history->widget()->setSession(m_session); // No focus for this dock. addTabifiedDock(m_docks.history, false); m_settings->historyDockVisible = true; } void MainWindow::createVariablesDock(bool takeFocus) { StartupDiagnostics::Scope timing("Create variables dock"); if (m_docks.variables) { m_docks.variables->show(); m_docks.variables->raise(); if (takeFocus) m_docks.variables->setFocus(); m_settings->variablesDockVisible = true; return; } m_docks.variables = new GenericDock("MainWindow", QT_TR_NOOP("User Variables"), this); m_docks.variables->setObjectName("VariablesDock"); m_docks.variables->installEventFilter(this); m_docks.variables->setAllowedAreas(Qt::AllDockWidgetAreas); connect(m_docks.variables->widget(), &VariableListWidget::variableSelected, this, &MainWindow::insertVariableIntoEditor); connect(m_docks.variables->widget(), &VariableListWidget::variableEdited, this, &MainWindow::insertTextIntoEditor); m_docks.variables->widget()->setEvaluator(m_evaluator); const auto updateVariables = [this]() { if (m_docks.variables) m_docks.variables->widget()->updateList(); }; connect(this, &MainWindow::radixCharacterChanged, this, updateVariables); connect(this, &MainWindow::variablesChanged, this, updateVariables); connect(m_docks.variables, &QDockWidget::visibilityChanged, this, [updateVariables](bool visible) { if (visible) updateVariables(); }); addTabifiedDock(m_docks.variables, takeFocus); m_docks.variables->widget()->setSearchText(m_settings->variablesDockSearchText); m_settings->variablesDockVisible = true; } void MainWindow::createUserFunctionsDock(bool takeFocus) { StartupDiagnostics::Scope timing("Create user functions dock"); if (m_docks.userFunctions) { m_docks.userFunctions->show(); m_docks.userFunctions->raise(); if (takeFocus) m_docks.userFunctions->setFocus(); m_settings->userFunctionsDockVisible = true; return; } m_docks.userFunctions = new GenericDock("MainWindow", QT_TR_NOOP("User Functions"), this); m_docks.userFunctions->setObjectName("UserFunctionsDock"); m_docks.userFunctions->installEventFilter(this); m_docks.userFunctions->setAllowedAreas(Qt::AllDockWidgetAreas); connect(m_docks.userFunctions->widget(), &UserFunctionListWidget::userFunctionSelected, this, &MainWindow::insertUserFunctionIntoEditor); connect(m_docks.userFunctions->widget(), &UserFunctionListWidget::userFunctionEdited, this, &MainWindow::insertUserFunctionIntoEditor); m_docks.userFunctions->widget()->setEvaluator(m_evaluator); const auto updateFunctions = [this]() { if (m_docks.userFunctions) m_docks.userFunctions->widget()->updateList(); }; connect(this, &MainWindow::radixCharacterChanged, this, updateFunctions); connect(this, &MainWindow::functionsChanged, this, updateFunctions); connect(m_docks.userFunctions, &QDockWidget::visibilityChanged, this, [updateFunctions](bool visible) { if (visible) updateFunctions(); }); addTabifiedDock(m_docks.userFunctions, takeFocus); m_docks.userFunctions->widget()->setSearchText(m_settings->userFunctionsDockSearchText); m_settings->userFunctionsDockVisible = true; } void MainWindow::createUserUnitsDock(bool takeFocus) { StartupDiagnostics::Scope timing("Create user units dock"); if (m_docks.userUnits) { m_docks.userUnits->show(); m_docks.userUnits->raise(); if (takeFocus) m_docks.userUnits->setFocus(); m_settings->userUnitsDockVisible = true; return; } m_docks.userUnits = new GenericDock("MainWindow", QT_TR_NOOP("User Units"), this); m_docks.userUnits->setObjectName("UserUnitsDock"); m_docks.userUnits->installEventFilter(this); m_docks.userUnits->setAllowedAreas(Qt::AllDockWidgetAreas); connect(m_docks.userUnits->widget(), &UserUnitListWidget::userUnitSelected, this, &MainWindow::insertUserUnitIntoEditor); connect(m_docks.userUnits->widget(), &UserUnitListWidget::userUnitEdited, this, &MainWindow::insertTextIntoEditor); m_docks.userUnits->widget()->setEvaluator(m_evaluator); const auto updateUnits = [this]() { if (m_docks.userUnits) m_docks.userUnits->widget()->updateList(); }; connect(this, &MainWindow::radixCharacterChanged, this, updateUnits); connect(this, &MainWindow::unitsChanged, this, updateUnits); connect(m_docks.userUnits, &QDockWidget::visibilityChanged, this, [updateUnits](bool visible) { if (visible) updateUnits(); }); addTabifiedDock(m_docks.userUnits, takeFocus); m_docks.userUnits->widget()->setSearchText(m_settings->userUnitsDockSearchText); m_settings->userUnitsDockVisible = true; } void MainWindow::addTabifiedDock(QDockWidget* newDock, bool takeFocus, Qt::DockWidgetArea area) { connect(newDock, &QDockWidget::visibilityChanged, this, &MainWindow::handleDockWidgetVisibilityChanged); connect(newDock, &QDockWidget::topLevelChanged, newDock, [newDock]() { // Qt replaces title button icons when changing between floating and // docked. Restore our themed icons after that reset, before any hover. for (QAbstractButton* button : newDock->findChildren( QString(), Qt::FindDirectChildrenOnly)) { if (button->property("speedcrunchDockHeaderButton").toBool()) applyDockTitleButtonIcon(button, button->underMouse()); } }); const bool restored = m_hasRestoredDockLayout && restoreDockWidget(newDock); if (!restored) { addDockWidget(area, newDock); for (QDockWidget* dock : m_allDocks) { // Keep floating panels independent when opening another dock. if (!dock->isFloating() && dockWidgetArea(dock) == area) tabifyDockWidget(dock, newDock); } } m_allDocks.append(newDock); restoreDockColumnOrder(newDock); newDock->show(); newDock->raise(); // Startup styles the restored docks together once their layout is ready. if (!m_initializingUi) { const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); applyDockAppearance(this, newDock, surfaces); applyDockTabBarAppearance(); updateSplitterStyleSheet(); scheduleDockAppearanceRefresh(); } if (takeFocus) newDock->setFocus(); } void MainWindow::deleteDock(QDockWidget* dock) { // QMainWindow retains internal layout items for dock restoration and tab // groups. Keep an attached dock alive and hidden instead of destroying it // from its Close event while Qt may still be traversing that layout. dock->hide(); } void MainWindow::createFixedConnections() { StartupDiagnostics::Scope timing("Connect UI signals"); ResultDisplay* initialDisplay = m_widgets.display; Editor* initialEditor = m_widgets.editor; connect(initialEditor, &Editor::textChanged, this, [this, initialDisplay, initialEditor]() { if (initialEditor == m_widgets.editor || initialEditor->hasFocus() || initialEditor->viewport()->hasFocus()) { setActiveEditorDisplayPane(initialDisplay, initialEditor); } }); connect(initialEditor, &Editor::selectionChanged, this, [this, initialDisplay, initialEditor]() { setActiveEditorDisplayPane(initialDisplay, initialEditor); }); connect(initialDisplay, &ResultDisplay::clicked, this, [this, initialDisplay, initialEditor]() { setActiveEditorDisplayPane(initialDisplay, initialEditor, true); }); connect(initialDisplay, &ResultDisplay::selectionChanged, this, [this, initialDisplay, initialEditor]() { setActiveEditorDisplayPane(initialDisplay, initialEditor, true); }); connect(this, &MainWindow::colorSchemeChanged, this, &MainWindow::updateSplitterStyleSheet); connect(this, &MainWindow::colorSchemeChanged, this, &MainWindow::applyThemeSurfacePalette); connect(this, &MainWindow::colorSchemeChanged, this, &MainWindow::refreshPaneThemes); connect(m_actionGroups.menuAppearance, &QActionGroup::triggered, this, &MainWindow::setMenuAppearance); connect(m_actionGroups.dockAppearance, &QActionGroup::triggered, this, &MainWindow::setDockAppearance); connect(m_actionGroups.statusBarAppearance, &QActionGroup::triggered, this, &MainWindow::setStatusBarAppearance); connect(m_actionGroups.keypadAppearance, &QActionGroup::triggered, this, &MainWindow::setKeypadAppearance); connect(m_actionGroups.editorDisplayStyle, &QActionGroup::triggered, this, &MainWindow::setEditorDisplayStyle); connect(this, &MainWindow::syntaxHighlightingChanged, this, &MainWindow::refreshPaneThemes); connect(m_actions.sessionExportJson, SIGNAL(triggered()), SLOT(exportJson())); connect(m_actions.sessionExportHtml, SIGNAL(triggered()), SLOT(exportHtml())); connect(m_actions.sessionExportPlainText, SIGNAL(triggered()), SLOT(exportPlainText())); connect(m_actions.sessionImport, SIGNAL(triggered()), SLOT(showSessionImportDialog())); connect(m_actions.sessionImportUserDefinitions, &QAction::triggered, this, &MainWindow::showUserDefinitionsImportDialog); connect(m_actions.sessionNewTab, &QAction::triggered, this, [this]() { // On macOS the native menu bar can dispatch a menu action owned by a // window that is no longer frontmost. The target has to come from the // current Qt active window first, not from this QAction's owner. MainWindow* targetWindow = qobject_cast(QApplication::activeWindow()); if (targetWindow == nullptr) { if (QWidget* focusWidget = QApplication::focusWidget()) targetWindow = qobject_cast(focusWidget->window()); } // Focus bookkeeping can lag behind title-bar activation. These fallbacks // keep keyboard/menu activation working while avoiding stale global // editor state until every foreground-window source has been tried. if (targetWindow == nullptr) { if (QWidget* focusWidget = lastFocusWidgetInActiveWindow()) targetWindow = qobject_cast(focusWidget->window()); } if (targetWindow == nullptr) { if (QWidget* focusWidget = pendingWindowActivationFocusWidget()) targetWindow = qobject_cast(focusWidget->window()); } if (targetWindow == nullptr) { if (Editor* activeEditor = pendingWindowActivationEditor()) targetWindow = qobject_cast(activeEditor->window()); } if (targetWindow == nullptr) { if (Editor* activeEditor = globallyActiveEditor()) targetWindow = qobject_cast(activeEditor->window()); } if (targetWindow == nullptr) { if (ResultDisplay* activeDisplay = globallyActiveDisplay()) targetWindow = qobject_cast(activeDisplay->window()); } if (targetWindow == nullptr) targetWindow = this; QPointer guardedWindow(targetWindow); QTimer::singleShot(0, targetWindow, [guardedWindow]() { if (guardedWindow != nullptr) guardedWindow->showNewSessionDialog(); }); }); connect(m_actions.sessionNewWindow, SIGNAL(triggered()), SLOT(showNewSessionWindow())); connect(m_actions.sessionNewPrivate, &QAction::triggered, this, [this]() { activeMainWindowForMenuAction(this)->showNewPrivateSession(); }); connect(m_actions.sessionConvertPrivacy, &QAction::triggered, this, [this]() { activeMainWindowForMenuAction(this)->convertSessionPrivacy(); }); const auto connectWindowAction = [this](QAction* action, void (MainWindow::*operation)()) { connect(action, &QAction::triggered, this, [this, operation]() { (activeMainWindowForMenuAction(this)->*operation)(); }); }; connectWindowAction(m_actions.sessionOpen, &MainWindow::showOpenSessionDialog); connectWindowAction(m_actions.sessionRename, &MainWindow::showRenameSessionDialog); connectWindowAction(m_actions.sessionClone, &MainWindow::showDuplicateSessionDialog); connectWindowAction(m_actions.sessionClose, &MainWindow::closeCurrentSession); connect(m_actions.sessionReopen, &QAction::triggered, this, [this]() { MainWindow* target = activeMainWindowForMenuAction(this); QTimer::singleShot(0, target, &MainWindow::restoreClosedSessionTab); }); connect(m_actions.sessionOpenSessionsFolder, SIGNAL(triggered()), SLOT(openSessionsFolder())); connect(m_actions.sessionQuit, &QAction::triggered, qApp, &QCoreApplication::quit); connectWindowAction(m_actions.editClearExpression, &MainWindow::clearEditorAndBitfield); connectWindowAction(m_actions.editClearHistory, &MainWindow::clearHistory); connectWindowAction(m_actions.editCopyLastResult, &MainWindow::copyResultToClipboard); connectWindowAction(m_actions.editCopy, &MainWindow::copy); connectWindowAction(m_actions.editSelectExpression, &MainWindow::selectEditorExpression); connectWindowAction(m_actions.editWrapSelection, &MainWindow::wrapSelection); const auto connectEditorAction = [this](QAction* action, void (QPlainTextEdit::*operation)()) { connect(action, &QAction::triggered, this, [this, operation]() { MainWindow* target = activeMainWindowForMenuAction(this); if (target->m_widgets.editor != nullptr) (target->m_widgets.editor->*operation)(); target->syncEditMenuActionState(); }); }; connectEditorAction(m_actions.editUndo, &QPlainTextEdit::undo); connectEditorAction(m_actions.editRedo, &QPlainTextEdit::redo); connectEditorAction(m_actions.editCut, &QPlainTextEdit::cut); connectEditorAction(m_actions.editPaste, &QPlainTextEdit::paste); connectWindowAction(m_actions.viewSplitLeft, &MainWindow::splitActivePaneLeft); connectWindowAction(m_actions.viewSplitRight, &MainWindow::splitActivePaneRight); connectWindowAction(m_actions.viewSplitUp, &MainWindow::splitActivePaneUp); connectWindowAction(m_actions.viewSplitDown, &MainWindow::splitActivePaneDown); connectWindowAction(m_actions.viewClosePane, &MainWindow::closeCurrentPane); connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &MainWindow::syncEditMenuActionState); const auto connectViewToggleToActiveWindow = [this](QAction* action, auto apply) { connect(action, &QAction::triggered, this, [this, apply](bool checked) { MainWindow* targetWindow = activeMainWindowForMenuAction(this); apply(targetWindow, checked); targetWindow->syncViewMenuActionState(); }); }; connectViewToggleToActiveWindow( m_actions.viewFullScreenMode, [](MainWindow* window, bool enabled) { window->setFullScreenEnabled(enabled); }); connect(m_actionGroups.keypad, &QActionGroup::triggered, this, [this](QAction* action) { MainWindow* targetWindow = activeMainWindowForMenuAction(this); targetWindow->setKeypadMode(action); targetWindow->syncViewMenuActionState(); }); connect(m_actions.viewKeypadDisabled, &QAction::toggled, this, [this](bool) { updateKeypadDisabledActionText(); }); connect(m_actionGroups.keypadZoom, &QActionGroup::triggered, this, [this](QAction* action) { MainWindow* targetWindow = activeMainWindowForMenuAction(this); targetWindow->setKeypadZoom(action); targetWindow->syncViewMenuActionState(); }); connectViewToggleToActiveWindow( m_actions.viewStatusBar, [](MainWindow* window, bool visible) { window->setStatusBarVisible(visible); }); #if !defined(Q_OS_MACOS) connectViewToggleToActiveWindow( m_actions.viewMenuBar, [](MainWindow* window, bool visible) { window->setMenuBarVisible(visible); }); #endif connectViewToggleToActiveWindow( m_actions.viewBitfield, [](MainWindow* window, bool visible) { window->setBitfieldVisible(visible); }); connectViewToggleToActiveWindow( m_actions.viewConstants, [](MainWindow* window, bool visible) { window->setConstantsDockVisible(visible); }); connectViewToggleToActiveWindow( m_actions.viewFunctions, [](MainWindow* window, bool visible) { window->setFunctionsDockVisible(visible); }); connectViewToggleToActiveWindow( m_actions.viewHistory, [](MainWindow* window, bool visible) { window->setHistoryDockVisible(visible); }); connectViewToggleToActiveWindow( m_actions.viewFormulaBook, [](MainWindow* window, bool visible) { window->setFormulaBookDockVisible(visible); }); connectViewToggleToActiveWindow( m_actions.viewVariables, [](MainWindow* window, bool visible) { window->setVariablesDockVisible(visible); }); connectViewToggleToActiveWindow( m_actions.viewUserFunctions, [](MainWindow* window, bool visible) { window->setUserFunctionsDockVisible(visible); }); connectViewToggleToActiveWindow( m_actions.viewUserUnits, [](MainWindow* window, bool visible) { window->setUserUnitsDockVisible(visible); }); connect(m_menus.view, &QMenu::aboutToShow, this, [this]() { activeMainWindowForMenuAction(this)->syncViewMenuActionState(); }); const auto connectToActiveWindow = [this](QAction* action, void (MainWindow::*handler)()) { connect(action, &QAction::triggered, this, [this, handler]() { MainWindow* targetWindow = activeMainWindowForMenuAction(this); (targetWindow->*handler)(); }); }; connectToActiveWindow(m_actions.settingsAngleUnitDegree, &MainWindow::setAngleModeDegree); connectToActiveWindow(m_actions.settingsAngleUnitRadian, &MainWindow::setAngleModeRadian); connectToActiveWindow(m_actions.settingsAngleUnitGradian, &MainWindow::setAngleModeGradian); connectToActiveWindow(m_actions.settingsAngleUnitTurn, &MainWindow::setAngleModeTurn); connectToActiveWindow(m_actions.settingsAngleUnitRevolution, &MainWindow::setAngleModeRevolution); if (!isWaylandPlatform()) connect(m_actions.settingsBehaviorAlwaysOnTop, SIGNAL(toggled(bool)), SLOT(setAlwaysOnTopEnabled(bool))); connect(m_actions.settingsBehaviorAutoCompletion, SIGNAL(toggled(bool)), SLOT(setAutoCompletionEnabled(bool))); connect(m_actions.settingsBehaviorAutoCompletionAcceptWithEnter, &QAction::toggled, this, &MainWindow::setAutoCompletionAcceptWithEnterEnabled); connect(m_actions.settingsBehaviorAutoCompletionBuiltInFunctions, SIGNAL(toggled(bool)), SLOT(setAutoCompletionBuiltInFunctionsEnabled(bool))); connect(m_actions.settingsBehaviorAutoCompletionBuiltInVariables, SIGNAL(toggled(bool)), SLOT(setAutoCompletionBuiltInVariablesEnabled(bool))); connect(m_actions.settingsBehaviorAutoCompletionLongFormUnits, SIGNAL(toggled(bool)), SLOT(setAutoCompletionLongFormUnitsEnabled(bool))); connect(m_actions.settingsBehaviorAutoCompletionUserFunctions, SIGNAL(toggled(bool)), SLOT(setAutoCompletionUserFunctionsEnabled(bool))); connect(m_actions.settingsBehaviorAutoCompletionUserVariables, SIGNAL(toggled(bool)), SLOT(setAutoCompletionUserVariablesEnabled(bool))); connect(m_actions.settingsBehaviorAutoAns, SIGNAL(toggled(bool)), SLOT(setAutoAnsEnabled(bool))); connect(m_actions.settingsBehaviorPartialResults, SIGNAL(toggled(bool)), SLOT(setAutoCalcEnabled(bool))); connect(m_actions.settingsBehaviorHistorySizeLimit, SIGNAL(triggered()), SLOT(setHistorySizeLimit())); connect(m_actions.settingsBehaviorSaveWindowPositionOnExit, SIGNAL(toggled(bool)), SLOT(setWindowPositionSaveEnabled(bool))); connect(m_actions.settingsOpenPrivateTabOnStartup, &QAction::toggled, this, &MainWindow::setOpenPrivateTabOnStartupEnabled); connect(m_actions.settingsBehaviorSyntaxHighlighting, SIGNAL(toggled(bool)), SLOT(setSyntaxHighlightingEnabled(bool))); connect(m_actions.settingsEditingInputDigitGrouping, &QAction::toggled, this, &MainWindow::setInputDigitGroupingEnabled); connect(m_actions.settingsEditingAutomaticInputAdjustments, &QAction::toggled, this, &MainWindow::setAutomaticInputAdjustmentsEnabled); connect(m_actions.settingsEditingCursorBlinking, &QAction::toggled, this, &MainWindow::setCursorBlinkingEnabled); connect(m_actions.settingsEditingEscapeClearsEditor, &QAction::toggled, this, &MainWindow::setEscapeClearsEditorEnabled); connect(m_actions.settingsBehaviorHoverHighlightResults, SIGNAL(toggled(bool)), SLOT(setHoverHighlightResultsEnabled(bool))); connect(m_actionGroups.digitGrouping, SIGNAL(triggered(QAction*)), SLOT(setDigitGrouping(QAction*))); connect(m_actions.settingsBehaviorDigitGroupingIntegerPartOnly, SIGNAL(toggled(bool)), SLOT(setDigitGroupingIntegerPartOnlyEnabled(bool))); connect(m_actions.settingsBehaviorLeaveLastExpression, SIGNAL(toggled(bool)), SLOT(setLeaveLastExpressionEnabled(bool))); connect(m_actions.settingsBehaviorNumberFormat, SIGNAL(triggered()), SLOT(showNumberFormatDialog())); connectToActiveWindow(m_actions.settingsBehaviorResultSlots, &MainWindow::showResultSlotsDialog); connect(m_actionGroups.upDownArrowBehavior, SIGNAL(triggered(QAction*)), SLOT(setUpDownArrowBehavior(QAction*))); connect(m_actions.settingsBehaviorAutoResultToClipboard, SIGNAL(toggled(bool)), SLOT(setAutoResultToClipboardEnabled(bool))); connect(m_actions.settingsBehaviorSimplifyResultExpressions, SIGNAL(toggled(bool)), SLOT(setSimplifyResultExpressionsEnabled(bool))); connect(m_actions.settingsRadixCharComma, SIGNAL(triggered()), SLOT(setRadixCharacterComma())); connect(m_actions.settingsRadixCharDefault, SIGNAL(triggered()), SLOT(setRadixCharacterAutomatic())); connect(m_actions.settingsRadixCharDot, SIGNAL(triggered()), SLOT(setRadixCharacterDot())); connect(m_actions.settingsRadixCharBoth, SIGNAL(triggered()), SLOT(setRadixCharacterBoth())); connect(m_actions.settingsResultFormat0Digits, &QAction::triggered, this, [this]() { activeMainWindowForMenuAction(this)->setResultPrecision(0); }); connectToActiveWindow(m_actions.settingsResultFormat15Digits, &MainWindow::setResultPrecision15Digits); connectToActiveWindow(m_actions.settingsResultFormat2Digits, &MainWindow::setResultPrecision2Digits); connectToActiveWindow(m_actions.settingsResultFormat3Digits, &MainWindow::setResultPrecision3Digits); connectToActiveWindow(m_actions.settingsResultFormat50Digits, &MainWindow::setResultPrecision50Digits); connectToActiveWindow(m_actions.settingsResultFormat8Digits, &MainWindow::setResultPrecision8Digits); connectToActiveWindow(m_actions.settingsResultFormatCustomDigits, &MainWindow::setResultPrecisionCustom); connectToActiveWindow(m_actions.settingsResultFormatAutoPrecision, &MainWindow::setResultPrecisionAutomatic); connectToActiveWindow(m_actions.settingsResultFormatBinary, &MainWindow::setResultFormatBinary); connect(m_actions.settingsResultFormatCartesian, SIGNAL(triggered()), SLOT(setResultFormatCartesian())); connectToActiveWindow(m_actions.settingsResultFormatEngineering, &MainWindow::setResultFormatEngineering); connectToActiveWindow(m_actions.settingsResultFormatFixed, &MainWindow::setResultFormatFixed); connectToActiveWindow(m_actions.settingsResultFormatGeneral, &MainWindow::setResultFormatGeneral); connectToActiveWindow(m_actions.settingsResultFormatHexadecimal, &MainWindow::setResultFormatHexadecimal); connect(m_actions.settingsImaginaryUnitI, SIGNAL(triggered()), SLOT(setImaginaryUnitI())); connect(m_actions.settingsImaginaryUnitJ, SIGNAL(triggered()), SLOT(setImaginaryUnitJ())); connectToActiveWindow(m_actions.settingsResultFormatOctal, &MainWindow::setResultFormatOctal); connect(m_actions.settingsResultFormatPolar, SIGNAL(triggered()), SLOT(setResultFormatPolar())); connect(m_actions.settingsResultFormatTrigonometric, SIGNAL(triggered()), SLOT(setResultFormatTrigonometric())); connect(m_actions.settingsResultFormatCis, SIGNAL(triggered()), SLOT(setResultFormatCis())); connect(m_actions.settingsResultFormatPolarAngle, SIGNAL(triggered()), SLOT(setResultFormatPolarAngle())); connectToActiveWindow(m_actions.settingsResultFormatRational, &MainWindow::setResultFormatRational); connectToActiveWindow(m_actions.settingsResultFormatSexagesimal, &MainWindow::setResultFormatSexagesimal); connectToActiveWindow(m_actions.settingsResultFormatScientific, &MainWindow::setResultFormatScientific); connect(m_actionGroups.unitNegativeExponentStyle, SIGNAL(triggered(QAction*)), SLOT(setUnitNegativeExponentStyle(QAction*))); connect(m_actionGroups.resultRoundingMode, SIGNAL(triggered(QAction*)), SLOT(setResultRoundingMode(QAction*))); connect(m_actions.settingsRemoveTrailingZeroes, &QAction::toggled, this, &MainWindow::setRemoveTrailingZeroesEnabled); connect(m_actions.settingsLanguage, SIGNAL(triggered()), SLOT(showLanguageChooserDialog())); connectToActiveWindow(m_actions.settingsResetAll, &MainWindow::resetAllSettings); connect(m_actions.helpManual, SIGNAL(triggered()), SLOT(showManualWindow())); connect(m_actions.contextHelp, SIGNAL(triggered()), SLOT(showContextHelp())); #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS connect(m_actions.helpUpdates, SIGNAL(triggered()), SLOT(checkForUpdates())); #endif connect(m_actions.helpFeedback, SIGNAL(triggered()), SLOT(openFeedbackURL())); connect(m_actions.helpCommunity, SIGNAL(triggered()), SLOT(openCommunityURL())); connect(m_actions.helpSource, SIGNAL(triggered()), SLOT(openSourceURL())); connect(m_actions.helpDonate, SIGNAL(triggered()), SLOT(openDonateURL())); connect(m_actions.helpAbout, SIGNAL(triggered()), SLOT(showAboutDialog())); connect(m_actions.helpDiagnostics, &QAction::triggered, this, &MainWindow::showDiagnosticsDialog); connect(m_widgets.editor, &Editor::autoCalcDisabled, this, [this]() { if (sender() == m_widgets.editor) hideStateLabel(); }); connect(m_widgets.editor, SIGNAL(autoCalcMessageAvailable(const QString&)), SLOT(handleAutoCalcMessageAvailable(const QString&))); connect(m_widgets.editor, SIGNAL(autoCalcQuantityAvailable(const Quantity&)), SLOT(handleAutoCalcQuantityAvailable(const Quantity&))); connect(m_widgets.editor, SIGNAL(returnPressed()), SLOT(evaluateEditorExpression())); connect(m_widgets.editor, SIGNAL(escapePressed()), SLOT(handleEditorEscapePressed())); connect(m_widgets.editor, SIGNAL(shiftDownPressed()), SLOT(decreaseDisplayFontPointSize())); connect(m_widgets.editor, SIGNAL(shiftUpPressed()), SLOT(increaseDisplayFontPointSize())); connect(m_widgets.editor, SIGNAL(controlPageUpPressed()), m_widgets.display, SLOT(scrollToTop())); connect(m_widgets.editor, SIGNAL(controlPageDownPressed()), m_widgets.display, SLOT(scrollToBottom())); connect(m_widgets.editor, SIGNAL(shiftPageUpPressed()), m_widgets.display, SLOT(scrollLineUp())); connect(m_widgets.editor, SIGNAL(shiftPageDownPressed()), m_widgets.display, SLOT(scrollLineDown())); connect(m_widgets.editor, SIGNAL(pageUpPressed()), m_widgets.display, SLOT(scrollPageUp())); connect(m_widgets.editor, SIGNAL(pageDownPressed()), m_widgets.display, SLOT(scrollPageDown())); connect(initialEditor, &Editor::textChanged, this, [this, initialEditor]() { if (initialEditor == m_widgets.editor || initialEditor->hasFocus() || initialEditor->viewport()->hasFocus()) { handleEditorTextChange(); } }); connect(m_widgets.editor, SIGNAL(copyAvailable(bool)), SLOT(handleCopyAvailable(bool))); connect(initialEditor, &Editor::undoAvailable, this, &MainWindow::syncEditMenuActionState); connect(initialEditor, &Editor::redoAvailable, this, &MainWindow::syncEditMenuActionState); connect(m_widgets.editor, SIGNAL(copySequencePressed()), SLOT(copy())); connect(m_widgets.editor, SIGNAL(selectionChanged()), SLOT(handleEditorSelectionChange())); connect(this, SIGNAL(historyChanged()), m_widgets.editor, SLOT(updateHistory())); connect(m_widgets.display, SIGNAL(copyAvailable(bool)), SLOT(handleCopyAvailable(bool))); connect(m_widgets.display, SIGNAL(clicked()), SLOT(hideStateLabel())); connect(m_widgets.display, SIGNAL(expressionSelected(const QString&)), SLOT(insertHistoryExpressionIntoEditor(const QString&))); connect(m_widgets.display, SIGNAL(editHistoryEntryRequested(int)), SLOT(startHistoryEntryEdit(int))); connect(m_widgets.display, SIGNAL(editHistoryEntryContextRequested(int)), SLOT(editHistoryEntryContext(int))); connect(m_widgets.display, SIGNAL(cancelHistoryEditRequested()), SLOT(cancelHistoryEntryEdit())); connect(m_widgets.display, SIGNAL(removeHistoryEntryRequested(int)), SLOT(removeHistoryEntryAt(int))); connect(m_widgets.display, SIGNAL(removeHistoryEntriesAboveRequested(int)), SLOT(removeHistoryEntriesAbove(int))); connect(m_widgets.display, SIGNAL(removeHistoryEntriesBelowRequested(int)), SLOT(removeHistoryEntriesBelow(int))); connect(m_widgets.display, SIGNAL(newSessionRequested()), SLOT(showNewSessionDialog())); connect(m_widgets.display, &ResultDisplay::newPrivateSessionRequested, this, &MainWindow::showNewPrivateSession); connect(m_widgets.display, &ResultDisplay::convertSessionPrivacyRequested, this, &MainWindow::convertSessionPrivacy); connect(m_widgets.display, SIGNAL(openSessionRequested()), SLOT(showOpenSessionDialog())); connect(m_widgets.display, SIGNAL(importSessionRequested()), SLOT(showSessionImportDialog())); connect(m_widgets.display, SIGNAL(exportSessionJsonRequested()), SLOT(exportJson())); connect(m_widgets.display, SIGNAL(exportSessionPlainTextRequested()), SLOT(exportPlainText())); connect(m_widgets.display, SIGNAL(exportSessionHtmlRequested()), SLOT(exportHtml())); connect(m_widgets.display, SIGNAL(duplicateSessionRequested()), SLOT(showDuplicateSessionDialog())); connect(m_widgets.display, SIGNAL(splitLeftRequested()), SLOT(splitActivePaneLeft())); connect(m_widgets.display, SIGNAL(splitRightRequested()), SLOT(splitActivePaneRight())); connect(m_widgets.display, SIGNAL(splitUpRequested()), SLOT(splitActivePaneUp())); connect(m_widgets.display, SIGNAL(splitDownRequested()), SLOT(splitActivePaneDown())); connect(m_widgets.display, SIGNAL(renameSessionRequested()), SLOT(showRenameSessionDialog())); connect(m_widgets.display, SIGNAL(clearSessionRequested()), SLOT(clearSession())); connect(m_widgets.display, SIGNAL(closeSessionRequested()), SLOT(closeCurrentSession())); connect(m_widgets.display, SIGNAL(closePaneRequested()), SLOT(closeCurrentPane())); connect(m_widgets.display, SIGNAL(deleteSessionRequested()), SLOT(deleteCurrentSession())); connect(m_widgets.display, SIGNAL(loadedSessionsMenuRequested(const QPoint&)), SLOT(showLoadedSessionsMenu(const QPoint&))); connect(m_widgets.display, SIGNAL(selectionChanged()), SLOT(handleDisplaySelectionChange())); connect(m_widgets.display, SIGNAL(shiftWheelUp()), SLOT(increaseDisplayFontPointSize())); connect(m_widgets.display, SIGNAL(shiftWheelDown()), SLOT(decreaseDisplayFontPointSize())); connect(m_widgets.display, SIGNAL(controlWheelUp()), SLOT(increaseDisplayFontPointSize())); connect(m_widgets.display, SIGNAL(controlWheelDown()), SLOT(decreaseDisplayFontPointSize())); connect(m_widgets.display, SIGNAL(shiftControlWheelDown()), SLOT(decreaseOpacity())); connect(m_widgets.display, SIGNAL(shiftControlWheelUp()), SLOT(increaseOpacity())); connect(this, SIGNAL(historyChanged()), m_widgets.display, SLOT(refresh())); connect(this, SIGNAL(radixCharacterChanged()), m_widgets.display, SLOT(refresh())); connect(this, SIGNAL(radixCharacterChanged()), m_widgets.editor, SLOT(refreshAutoCalc())); connect(this, SIGNAL(angleUnitChanged()), m_widgets.editor, SLOT(refreshAutoCalc())); connect(this, SIGNAL(complexNumbersChanged()), m_widgets.display, SLOT(refreshLastHistoryEntry())); connect(this, SIGNAL(complexNumbersChanged()), m_widgets.editor, SLOT(refreshAutoCalc())); connect(this, SIGNAL(resultFormatChanged()), m_widgets.display, SLOT(refreshLastHistoryEntry())); connect(this, SIGNAL(resultFormatChanged()), m_widgets.editor, SLOT(refreshAutoCalc())); connect(this, SIGNAL(resultPrecisionChanged()), m_widgets.display, SLOT(refreshLastHistoryEntry())); connect(this, SIGNAL(resultPrecisionChanged()), m_widgets.editor, SLOT(refreshAutoCalc())); connect(this, SIGNAL(resultRoundingModeChanged()), m_widgets.display, SLOT(refreshLastHistoryEntry())); connect(this, SIGNAL(resultRoundingModeChanged()), m_widgets.editor, SLOT(refreshAutoCalc())); connect(this, SIGNAL(colorSchemeChanged()), m_widgets.display, SLOT(rehighlight())); connect(this, SIGNAL(colorSchemeChanged()), m_widgets.editor, SLOT(rehighlight())); connect(this, SIGNAL(syntaxHighlightingChanged()), m_widgets.display, SLOT(rehighlight())); connect(this, SIGNAL(syntaxHighlightingChanged()), m_widgets.editor, SLOT(rehighlight())); connect(m_actions.settingsDisplayFont, SIGNAL(triggered()), SLOT(showFontDialog())); connect(m_actions.settingsDisplayColorSchemeCustom, SIGNAL(triggered()), SLOT(showCustomThemeDialog())); connect(this, SIGNAL(languageChanged()), SLOT(retranslateText())); const auto bindApplicationShortcut = [this](const QKeySequence& sequence, const std::function& handler) { QShortcut* shortcut = new QShortcut(sequence, this); shortcut->setContext(Qt::ApplicationShortcut); connect(shortcut, &QShortcut::activated, this, handler); }; #if defined(Q_OS_MACOS) bindApplicationShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Right), [this]() { activateNextChild(); }); bindApplicationShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Left), [this]() { activatePreviousChild(); }); #else bindApplicationShortcut(QKeySequence(Qt::CTRL | Qt::Key_PageDown), [this]() { activateNextChild(); }); bindApplicationShortcut(QKeySequence(Qt::CTRL | Qt::Key_PageUp), [this]() { activatePreviousChild(); }); #endif QShortcut* cycleFocusForwardShortcut = new QShortcut(QKeySequence(Qt::Key_F6), this); // Each window owns its focus cycle. Application-wide bindings conflict // when more than one main window is visible. cycleFocusForwardShortcut->setContext(Qt::WindowShortcut); connect(cycleFocusForwardShortcut, &QShortcut::activated, this, &MainWindow::cycleFocusForward); QShortcut* cycleFocusBackwardShortcut = new QShortcut(QKeySequence(Qt::SHIFT | Qt::Key_F6), this); cycleFocusBackwardShortcut->setContext(Qt::WindowShortcut); connect(cycleFocusBackwardShortcut, &QShortcut::activated, this, &MainWindow::cycleFocusBackward); QShortcut* splitRightShortcut = new QShortcut(QKeySequence(QStringLiteral("Ctrl+\\")), this); connect(splitRightShortcut, &QShortcut::activated, this, &MainWindow::splitActivePaneRight); QShortcut* splitDownShortcut = new QShortcut(QKeySequence(QStringLiteral("Ctrl+Shift+\\")), this); connect(splitDownShortcut, &QShortcut::activated, this, &MainWindow::splitActivePaneDown); } void MainWindow::applySettings(bool initializing) { StartupDiagnostics::AppearanceContext context("Apply startup settings"); StartupDiagnostics::Scope timing("Apply appearance and language"); applyKeypadAppearance(); m_actions.settingsDockAppearanceSystem->setChecked( m_settings->dockAppearance == Settings::DockAppearanceSystem); m_actions.settingsDockAppearanceSpeedCrunch->setChecked( m_settings->dockAppearance == Settings::DockAppearanceSpeedCrunch); m_actions.settingsStatusBarAppearanceSystem->setChecked( m_settings->statusBarAppearance == Settings::StatusBarAppearanceSystem); m_actions.settingsStatusBarAppearanceSpeedCrunch->setChecked( m_settings->statusBarAppearance == Settings::StatusBarAppearanceSpeedCrunch); applyEditorDisplayStyle(); m_actions.settingsMenuAppearanceSystem->setChecked( m_settings->menuAppearance == Settings::MenuAppearanceSystem); m_actions.settingsMenuAppearanceSpeedCrunch->setChecked( m_settings->menuAppearance == Settings::MenuAppearanceSpeedCrunch); emit languageChanged(); m_status.selectedAngleUnit = m_settings->angleUnit; m_status.selectedResultFormat = m_settings->resultFormat; m_status.selectedResultPrecision = m_settings->resultPrecision; // Saved workspaces choose their own docks before session files are read. // Other windows use the configured defaults without constructing closed panels. if (!initializing) applyOpenDocks(configuredOpenDockNames()); else if (!m_restorePreviousSessionOnStartup) restoreWindowLayoutState(m_settings->windowState); timing.next("Configure keypad, status bar and menu bar"); updateKeypadModeActionState(); switch (m_keypadZoomPercent) { case 50: m_actions.viewKeypadZoom50->setChecked(true); break; case 150: m_actions.viewKeypadZoom150->setChecked(true); break; case 200: m_actions.viewKeypadZoom200->setChecked(true); break; case 100: default: m_actions.viewKeypadZoom100->setChecked(true); break; } setKeypadVisible(isVisibleKeypadMode(m_keypadMode)); m_menus.keypadZoom->setEnabled(isVisibleKeypadMode(m_keypadMode)); setStatusBarVisible(m_settings->statusBarVisible); m_actions.viewStatusBar->setChecked(m_settings->statusBarVisible); #if !defined(Q_OS_MACOS) setMenuBarVisible(m_settings->menuBarVisible); m_actions.viewMenuBar->setChecked(m_settings->menuBarVisible); #endif timing.next("Restore window geometry and dock layout"); const bool hasSavedWindowLayout = !m_settings->sessionLayoutJson.isEmpty(); if (hasSavedWindowLayout || !restoreGeometry(m_settings->windowGeometry)) { int defaultWidth = 640; if (m_widgets.keypad) defaultWidth = m_widgets.keypad->sizeHint().width(); resize(defaultWidth, 480); QRect screenGeometry = QGuiApplication::primaryScreen()->availableGeometry(); move(screenGeometry.center() - rect().center()); } m_actions.viewFullScreenMode->setChecked(m_settings->windowOnfullScreen); if (!isWaylandPlatform()) m_actions.settingsBehaviorAlwaysOnTop->setChecked(m_settings->windowAlwaysOnTop); if (m_settings->angleUnit == 'r') m_actions.settingsAngleUnitRadian->setChecked(true); else if (m_settings->angleUnit == 'd') m_actions.settingsAngleUnitDegree->setChecked(true); else if (m_settings->angleUnit == 'g') m_actions.settingsAngleUnitGradian->setChecked(true); else if (m_settings->angleUnit == 't') m_actions.settingsAngleUnitTurn->setChecked(true); else if (m_settings->angleUnit == 'v') m_actions.settingsAngleUnitRevolution->setChecked(true); timing.next("Load global definitions and schedule session restore"); if (initializing) { UserDefinitions::loadInto(m_settings); if (m_restorePreviousSessionOnStartup) restoreSession(); applyUserDefinitions(); } timing.next("Apply calculation, editing and display preferences"); m_actions.settingsBehaviorLeaveLastExpression->setChecked(m_settings->leaveLastExpression); switch (m_settings->upDownArrowBehavior) { case Settings::UpDownArrowBehaviorNever: m_actions.settingsBehaviorUpDownArrowNever->setChecked(true); break; case Settings::UpDownArrowBehaviorSingleLineOnly: m_actions.settingsBehaviorUpDownArrowSingleLineOnly->setChecked(true); break; case Settings::UpDownArrowBehaviorAlways: default: m_actions.settingsBehaviorUpDownArrowAlways->setChecked(true); break; } m_actions.settingsBehaviorSaveWindowPositionOnExit->setChecked(m_settings->windowPositionSave); m_actions.settingsOpenPrivateTabOnStartup->setChecked(m_settings->openPrivateTabOnStartup); checkInitialResultFormat(); checkInitialResultPrecision(); checkInitialComplexFormat(); checkInitialImaginaryUnit(); m_actions.settingsRemoveTrailingZeroes->setChecked(m_settings->removeTrailingZeroes); switch (m_settings->resultRoundingMode) { case Settings::ResultRoundingHalfEven: m_actions.settingsResultRoundingHalfEven->setChecked(true); break; case Settings::ResultRoundingTowardZero: m_actions.settingsResultRoundingTowardZero->setChecked(true); break; case Settings::ResultRoundingTowardPositiveInfinity: m_actions.settingsResultRoundingTowardPositiveInfinity->setChecked(true); break; case Settings::ResultRoundingTowardNegativeInfinity: m_actions.settingsResultRoundingTowardNegativeInfinity->setChecked(true); break; case Settings::ResultRoundingHalfAwayFromZero: default: m_actions.settingsResultRoundingHalfAwayFromZero->setChecked(true); break; } setRuntimeResultRoundingMode(m_settings->resultRoundingMode); if (m_settings->unitNegativeExponentStyle == Settings::UnitNegativeExponentFraction) m_actions.settingsUnitNegativeExponentFraction->setChecked(true); else m_actions.settingsUnitNegativeExponentSuperscript->setChecked(true); setRuntimeUnitNegativeExponentStyle(m_settings->unitNegativeExponentStyle); if (m_settings->autoAns) m_actions.settingsBehaviorAutoAns->setChecked(true); else setAutoAnsEnabled(false); if (m_settings->autoCalc) m_actions.settingsBehaviorPartialResults->setChecked(true); else setAutoCalcEnabled(false); if (m_settings->autoCompletion) m_actions.settingsBehaviorAutoCompletion->setChecked(true); else setAutoCompletionEnabled(false); setAutoCompletionAcceptWithEnterEnabled(m_settings->autoCompletionAcceptWithEnter); m_actions.settingsBehaviorAutoCompletionBuiltInFunctions->setChecked( m_settings->autoCompletionBuiltInFunctions); m_actions.settingsBehaviorAutoCompletionBuiltInVariables->setChecked( m_settings->autoCompletionBuiltInVariables); m_actions.settingsBehaviorAutoCompletionLongFormUnits->setChecked( m_settings->autoCompletionLongFormUnits); m_actions.settingsBehaviorAutoCompletionUserFunctions->setChecked( m_settings->autoCompletionUserFunctions); m_actions.settingsBehaviorAutoCompletionUserVariables->setChecked( m_settings->autoCompletionUserVariables); if (m_settings->syntaxHighlighting) m_actions.settingsBehaviorSyntaxHighlighting->setChecked(true); else setSyntaxHighlightingEnabled(false); m_actions.settingsEditingInputDigitGrouping->setChecked(m_settings->inputDigitGrouping); setAutomaticInputAdjustmentsEnabled(m_settings->automaticInputAdjustments); setCursorBlinkingEnabled(m_settings->cursorBlinking); setEscapeClearsEditorEnabled(m_settings->escapeClearsEditor); if (m_settings->hoverHighlightResults) m_actions.settingsBehaviorHoverHighlightResults->setChecked(true); else setHoverHighlightResultsEnabled(false); if (m_settings->autoResultToClipboard) m_actions.settingsBehaviorAutoResultToClipboard->setChecked(true); else setAutoResultToClipboardEnabled(false); if (m_settings->simplifyResultExpressions) m_actions.settingsBehaviorSimplifyResultExpressions->setChecked(true); else setSimplifyResultExpressionsEnabled(false); QFont font; font.fromString(m_settings->displayFont); for (ResultDisplay* display : splitPaneDisplays()) display->setFont(font); for (Editor* editor : splitPaneEditors()) editor->setFont(font); if (initializing && m_widgets.display != nullptr) m_widgets.display->verticalScrollBar()->setValue(m_widgets.display->verticalScrollBar()->maximum()); updateColorSchemeActionState(); updateSplitterStyleSheet(); } void MainWindow::resetAllSettings() { QMessageBox confirmation(this); confirmation.setIcon(QMessageBox::Question); confirmation.setWindowTitle(tr("Reset All Settings")); confirmation.setText(tr("Reset all settings to their default values?")); confirmation.setInformativeText(tr("This includes appearance, editing, result formats, and window preferences. " "Your calculations, open sessions, and user definitions will be kept.")); confirmation.setStandardButtons(QMessageBox::Yes | QMessageBox::No); confirmation.setDefaultButton(QMessageBox::No); confirmation.setEscapeButton(QMessageBox::No); if (confirmation.exec() != QMessageBox::Yes) return; saveSessionLayout(false); if (!m_settings->resetToDefaults()) { QMessageBox::warning(this, tr("Reset All Settings"), tr("The settings file could not be written.")); return; } DMath::complexMode = m_settings->complexNumbers; CMath::setImaginaryUnitSymbol(m_settings->imaginaryUnit); MenuStyle::refresh(); // Keep QActionGroup's exclusive checks working while suppressing window // notifications that would reformat existing calculation history. std::vector> windowBlockers; for (const QPointer& window : allMainWindows()) { if (window) windowBlockers.push_back(std::make_unique(window.data())); } for (const QPointer& window : allMainWindows()) { if (!window) continue; std::vector> blockers; window->restoreDockColumnOrders(QJsonObject()); QDockWidget* previousDock = nullptr; for (QDockWidget* dock : window->m_allDocks) { blockers.push_back(std::make_unique(dock)); window->removeDockWidget(dock); const bool bitfield = dock == window->m_docks.bitField; window->addDockWidget(bitfield ? Qt::BottomDockWidgetArea : Qt::RightDockWidgetArea, dock); dock->setFloating(false); if (!bitfield) { if (previousDock) window->tabifyDockWidget(previousDock, dock); previousDock = dock; } } window->deleteKeypad(); window->m_hasRestoredDockLayout = false; window->m_keypadMode = m_settings->keypadMode; window->m_keypadZoomPercent = m_settings->keypadZoomPercent; window->applySettings(false); if (!isWaylandPlatform()) window->setAlwaysOnTopEnabled(m_settings->windowAlwaysOnTop); window->setFullScreenEnabled(m_settings->windowOnfullScreen); if (window->m_docks.constants) { for (QComboBox* combo : window->m_docks.constants->widget()->findChildren()) combo->setCurrentIndex(0); window->m_docks.constants->widget()->restoreState(QString(), QString(), QStringLiteral("")); } if (window->m_docks.functions) { for (QComboBox* combo : window->m_docks.functions->widget()->findChildren()) combo->setCurrentIndex(0); window->m_docks.functions->widget()->setSearchText(QString()); } if (window->m_docks.variables) window->m_docks.variables->widget()->setSearchText(QString()); if (window->m_docks.userFunctions) window->m_docks.userFunctions->widget()->setSearchText(QString()); if (window->m_docks.userUnits) window->m_docks.userUnits->widget()->setSearchText(QString()); if (window->m_docks.book) window->m_docks.book->openPage(QUrl(m_settings->formulaBookActivePage)); if (window->m_widgets.manual) window->m_widgets.manual->resize(640, 480); for (ResultDisplay* display : window->splitPaneDisplays()) display->setHoverHighlightEnabled(m_settings->hoverHighlightResults); for (Editor* editor : window->splitPaneEditors()) { editor->setAutoCalcEnabled(m_settings->autoCalc); editor->setAutoCompletionEnabled(m_settings->autoCompletion); editor->refreshAutoCalc(); } window->setStatusBarText(); window->syncStatusBarSelectionMenuActionState(); } windowBlockers.clear(); for (const QPointer& window : allMainWindows()) { if (!window) continue; emit window->languageChanged(); emit window->colorSchemeChanged(); emit window->menuAppearanceChanged(); } saveSessionLayout(false); m_settings->save(); } void MainWindow::showManualWindow() { if (m_widgets.manual) { m_widgets.manual->raise(); m_widgets.manual->activateWindow(); return; } m_widgets.manual = new ManualWindow(); if (!m_widgets.manual->restoreGeometry(m_settings->manualWindowGeometry)) m_widgets.manual->resize(640, 480); m_widgets.manual->show(); connect(m_widgets.manual, SIGNAL(windowClosed()), SLOT(handleManualClosed())); } void MainWindow::showContextHelp() { QString kw = ""; if(m_widgets.editor->hasFocus()) { kw = m_widgets.editor->getKeyword(); if (kw != "") { auto url = m_manualServer->urlForKeyword(kw); if (url.isValid()) { showManualWindow(); m_widgets.manual->openPage(url); } } } } void MainWindow::checkInitialResultFormat() { switch (m_settings->resultFormat) { case 'g': m_actions.settingsResultFormatGeneral->setChecked(true); break; case 'n': m_actions.settingsResultFormatEngineering->setChecked(true); break; case 'e': m_actions.settingsResultFormatScientific->setChecked(true); break; case 'r': m_actions.settingsResultFormatRational->setChecked(true); break; case 'h': m_actions.settingsResultFormatHexadecimal->setChecked(true); break; case 'o': m_actions.settingsResultFormatOctal->setChecked(true); break; case 'b': m_actions.settingsResultFormatBinary->setChecked(true); break; case 's': m_actions.settingsResultFormatSexagesimal->setChecked(true); break; default : m_actions.settingsResultFormatFixed->setChecked(true); } } void MainWindow::checkInitialComplexFormat() { m_settings->complexNumbers = true; m_settings->secondaryComplexNumbers = true; m_settings->tertiaryComplexNumbers = true; m_settings->quaternaryComplexNumbers = true; m_settings->quinaryComplexNumbers = true; DMath::complexMode = true; if (m_settings->resultComplexForm == ComplexForm::Exponential) m_actions.settingsResultFormatPolar->setChecked(true); else if (m_settings->resultComplexForm == ComplexForm::Trigonometric) m_actions.settingsResultFormatTrigonometric->setChecked(true); else if (m_settings->resultComplexForm == ComplexForm::Cis) m_actions.settingsResultFormatCis->setChecked(true); else if (m_settings->resultComplexForm == ComplexForm::Phasor) m_actions.settingsResultFormatPolarAngle->setChecked(true); else m_actions.settingsResultFormatCartesian->setChecked(true); } void MainWindow::checkInitialImaginaryUnit() { if (m_settings->imaginaryUnit == 'j') m_actions.settingsImaginaryUnitJ->setChecked(true); else m_actions.settingsImaginaryUnitI->setChecked(true); } void MainWindow::checkInitialResultPrecision() { switch (m_settings->resultPrecision) { case 0: m_actions.settingsResultFormat0Digits->setChecked(true); break; case 2: m_actions.settingsResultFormat2Digits->setChecked(true); break; case 3: m_actions.settingsResultFormat3Digits->setChecked(true); break; case 8: m_actions.settingsResultFormat8Digits->setChecked(true); break; case 15: m_actions.settingsResultFormat15Digits->setChecked(true); break; case 50: m_actions.settingsResultFormat50Digits->setChecked(true); break; case -1: m_actions.settingsResultFormatAutoPrecision->setChecked(true); break; default: m_actions.settingsResultFormatCustomDigits->setChecked(true); break; } } void MainWindow::checkInitialDigitGrouping() { switch (m_settings->digitGrouping) { case 1: m_actions.settingsBehaviorDigitGroupingOneSpace->setChecked(true); break; case 2: m_actions.settingsBehaviorDigitGroupingTwoSpaces->setChecked(true); break; case 3: m_actions.settingsBehaviorDigitGroupingThreeSpaces->setChecked(true); break; default: case 0: m_actions.settingsBehaviorDigitGroupingNone->setChecked(true); break; } } void MainWindow::saveSettings() { if (m_docks.constants) { m_settings->constantsDockDomain = m_docks.constants->widget()->selectedDomain(); m_settings->constantsDockSubdomain = m_docks.constants->widget()->selectedSubdomain(); m_settings->constantsDockSearchText = m_docks.constants->widget()->searchText(); } if (m_docks.functions) { m_settings->functionsDockDomain = m_docks.functions->widget()->selectedDomain(); m_settings->functionsDockSearchText = m_docks.functions->widget()->searchText(); } if (m_docks.userFunctions) m_settings->userFunctionsDockSearchText = m_docks.userFunctions->widget()->searchText(); if (m_docks.userUnits) m_settings->userUnitsDockSearchText = m_docks.userUnits->widget()->searchText(); if (m_docks.variables) m_settings->variablesDockSearchText = m_docks.variables->widget()->searchText(); if (m_docks.book) m_settings->formulaBookActivePage = m_docks.book->currentPage(); // These values seed a window only when no session-layout record exists. // Use the active window rather than assigning ownership to the first one. MainWindow* defaultWindow = activeMainWindowForMenuAction(this); m_settings->windowGeometry = m_settings->windowPositionSave ? defaultWindow->saveGeometry() : QByteArray(); m_settings->windowState = defaultWindow->saveState(DockLayoutStateVersion); m_settings->dockColumnOrdersJson = QString::fromUtf8( QJsonDocument(defaultWindow->dockColumnOrders()).toJson(QJsonDocument::Compact)); const QStringList openDocks = defaultWindow->openDockNames(); m_settings->formulaBookDockVisible = openDocks.contains(QStringLiteral("BookDock")); m_settings->constantsDockVisible = openDocks.contains(QStringLiteral("ConstantsDock")); m_settings->functionsDockVisible = openDocks.contains(QStringLiteral("FunctionsDock")); m_settings->historyDockVisible = openDocks.contains(QStringLiteral("HistoryDock")); m_settings->variablesDockVisible = openDocks.contains(QStringLiteral("VariablesDock")); m_settings->userFunctionsDockVisible = openDocks.contains(QStringLiteral("UserFunctionsDock")); m_settings->userUnitsDockVisible = openDocks.contains(QStringLiteral("UserUnitsDock")); m_settings->bitfieldVisible = openDocks.contains(QStringLiteral("BitfieldDock")); m_settings->keypadMode = defaultWindow->m_keypadMode; m_settings->keypadVisible = defaultWindow->m_widgets.keypad != nullptr; m_settings->keypadZoomPercent = defaultWindow->m_keypadZoomPercent; if (m_widgets.manual) m_settings->manualWindowGeometry = m_settings->windowPositionSave ? m_widgets.manual->saveGeometry() : QByteArray(); if (m_widgets.display != nullptr) m_settings->displayFont = m_widgets.display->font().toString(); m_settings->save(); } void MainWindow::saveSession(QString & fname) { captureEditorTextInCurrentSession(); QJsonObject json; m_session->serialize(json); writeSessionJsonToFile(json, fname); } void MainWindow::saveSessionLayout(bool captureCurrentViewport, bool captureEditorState) { const bool includeEditorState = captureEditorState || m_shutdownStateSaved || applicationShutdownInProgress(); const auto editorForDisplay = [](ResultDisplay* display) -> Editor* { QWidget* page = display ? display->parentWidget() : nullptr; return page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; }; if (captureCurrentViewport) { QSet capturedWindows; for (const QPointer& ptr : allMainWindows()) { MainWindow* window = ptr.data(); if (window == nullptr || capturedWindows.contains(window)) continue; capturedWindows.insert(window); window->captureVisibleSessionViewports(); } } QStringList sessionNames; for (ResultDisplay* display : splitPaneDisplays()) { const QStringList names = paneSessionNames(display); for (const QString& name : names) { if (!name.isEmpty() && !sessionNames.contains(name, Qt::CaseInsensitive)) sessionNames.append(name); } } if (sessionNames.isEmpty()) sessionNames = m_loadedSessions.keys(); sessionNames.sort(Qt::CaseInsensitive); QJsonArray tabs; const QString activePaneSessionName = m_widgets.display != nullptr ? m_paneSessionNames.value(m_widgets.display) : QString(); const QJsonObject activeEditorState = includeEditorState ? editorState(editorForDisplay(m_widgets.display)) : QJsonObject(); for (const QString& name : sessionNames) tabs.append(sessionLayoutEntry(name, m_sessionViewportAnchors.value(name, qMakePair(-1, 0)), m_sessionScrollValues.value(name, -1), activeEditorState, includeEditorState && name.compare(activePaneSessionName, Qt::CaseInsensitive) == 0)); const auto layoutNodeForWidget = [this, includeEditorState, &editorForDisplay](QWidget* widget, const auto& layoutNodeForWidgetRef) -> QJsonObject { QJsonObject node; if (widget == nullptr) return node; if (QSplitter* splitter = qobject_cast(widget)) { QJsonArray children; for (int i = 0; i < splitter->count(); ++i) { const QJsonObject child = layoutNodeForWidgetRef(splitter->widget(i), layoutNodeForWidgetRef); if (!child.isEmpty()) children.append(child); } QJsonArray sizes; for (int size : splitter->sizes()) sizes.append(size); node.insert(QStringLiteral("type"), QStringLiteral("split")); node.insert(QStringLiteral("orientation"), splitter->orientation() == Qt::Horizontal ? QStringLiteral("horizontal") : QStringLiteral("vertical")); node.insert(QStringLiteral("sizes"), sizes); node.insert(QStringLiteral("children"), children); return node; } ResultDisplay* display = widget->findChild(); if (display == nullptr) return node; const QString paneSessionName = m_paneSessionNames.value(display); QJsonArray paneTabs; const QStringList paneNames = paneSessionNames(display); const QJsonObject paneEditorState = includeEditorState ? editorState(editorForDisplay(display)) : QJsonObject(); for (const QString& name : paneNames) { paneTabs.append(sessionLayoutEntry(name, m_sessionViewportAnchors.value(name, qMakePair(-1, 0)), m_sessionScrollValues.value(name, -1), paneEditorState, includeEditorState && name.compare(paneSessionName, Qt::CaseInsensitive) == 0)); } node.insert(QStringLiteral("type"), QStringLiteral("pane")); node.insert(QStringLiteral("active"), paneSessionName); node.insert(QStringLiteral("tabs"), paneTabs); return node; }; QJsonObject root; const QList displays = splitPaneDisplays(); if (m_widgets.splitContainer != nullptr && displays.size() > 1) { root = layoutNodeForWidget(m_widgets.splitContainer, layoutNodeForWidget); root.insert(QStringLiteral("active"), m_session ? m_session->name() : QString()); root.insert(QStringLiteral("tabs"), tabs); } else { root.insert(QStringLiteral("type"), QStringLiteral("tabs")); root.insert(QStringLiteral("active"), m_session ? m_session->name() : QString()); root.insert(QStringLiteral("tabs"), tabs); } QJsonArray windows; int windowIndex = 0; QSet uniqueWindows; for (const QPointer& ptr : allMainWindows()) { MainWindow* windowObject = ptr.data(); if (windowObject == nullptr || windowObject->m_session == nullptr) continue; if (uniqueWindows.contains(windowObject)) continue; uniqueWindows.insert(windowObject); QJsonArray windowTabs; QStringList names; for (ResultDisplay* display : windowObject->splitPaneDisplays()) { for (const QString& name : windowObject->paneSessionNames(display)) { if (!name.isEmpty() && !names.contains(name, Qt::CaseInsensitive)) names.append(name); } } if (names.isEmpty()) names = windowObject->m_loadedSessions.keys(); names.sort(Qt::CaseInsensitive); const QString windowActivePaneSessionName = windowObject->m_widgets.display != nullptr ? windowObject->m_paneSessionNames.value(windowObject->m_widgets.display) : QString(); const QJsonObject windowActiveEditorState = includeEditorState ? editorState(editorForDisplay(windowObject->m_widgets.display)) : QJsonObject(); for (const QString& name : names) { windowTabs.append(sessionLayoutEntry(name, windowObject->m_sessionViewportAnchors.value(name, qMakePair(-1, 0)), windowObject->m_sessionScrollValues.value(name, -1), windowActiveEditorState, includeEditorState && name.compare(windowActivePaneSessionName, Qt::CaseInsensitive) == 0)); } const auto nodeForWidget = [windowObject, includeEditorState, &editorForDisplay](QWidget* widget, const auto& selfRef) -> QJsonObject { QJsonObject node; if (widget == nullptr) return node; if (QSplitter* splitter = qobject_cast(widget)) { QJsonArray children; for (int i = 0; i < splitter->count(); ++i) { const QJsonObject child = selfRef(splitter->widget(i), selfRef); if (!child.isEmpty()) children.append(child); } QJsonArray sizes; for (int size : splitter->sizes()) sizes.append(size); node.insert(QStringLiteral("type"), QStringLiteral("split")); node.insert(QStringLiteral("orientation"), splitter->orientation() == Qt::Horizontal ? QStringLiteral("horizontal") : QStringLiteral("vertical")); node.insert(QStringLiteral("sizes"), sizes); node.insert(QStringLiteral("children"), children); return node; } ResultDisplay* display = widget->findChild(); if (display == nullptr) return node; node.insert(QStringLiteral("type"), QStringLiteral("pane")); const QString paneSessionName = windowObject->m_paneSessionNames.value(display); node.insert(QStringLiteral("active"), paneSessionName); QJsonArray paneTabs; const QJsonObject paneEditorState = includeEditorState ? editorState(editorForDisplay(display)) : QJsonObject(); for (const QString& name : windowObject->paneSessionNames(display)) { paneTabs.append(sessionLayoutEntry(name, windowObject->m_sessionViewportAnchors.value(name, qMakePair(-1, 0)), windowObject->m_sessionScrollValues.value(name, -1), paneEditorState, includeEditorState && name.compare(paneSessionName, Qt::CaseInsensitive) == 0)); } node.insert(QStringLiteral("tabs"), paneTabs); return node; }; QJsonObject windowRoot; const QList windowDisplays = windowObject->splitPaneDisplays(); if (windowObject->m_widgets.splitContainer != nullptr && windowDisplays.size() > 1) { windowRoot = nodeForWidget(windowObject->m_widgets.splitContainer, nodeForWidget); windowRoot.insert(QStringLiteral("active"), windowObject->m_session ? windowObject->m_session->name() : QString()); windowRoot.insert(QStringLiteral("tabs"), windowTabs); } else { windowRoot.insert(QStringLiteral("type"), QStringLiteral("tabs")); windowRoot.insert(QStringLiteral("active"), windowObject->m_session ? windowObject->m_session->name() : QString()); windowRoot.insert(QStringLiteral("tabs"), windowTabs); } QJsonObject window; const QString id = QStringLiteral("window-%1").arg(windowIndex++); window.insert(QStringLiteral("id"), id); window.insert(QStringLiteral("active"), windowObject == this); window.insert(QStringLiteral("root"), windowRoot); const QStatusBar* windowStatusBar = windowObject->findChild(QString(), Qt::FindDirectChildrenOnly); // isVisible() also becomes false when the top-level window is hidden // during shutdown. isHidden() records only the status bar's own choice. window.insert(QStringLiteral("statusBarVisible"), windowStatusBar != nullptr && !windowStatusBar->isHidden()); window.insert(QStringLiteral("statusBarAngleUnit"), QString(QChar::fromLatin1(windowObject->m_status.selectedAngleUnit))); window.insert(QStringLiteral("statusBarResultFormat"), QString(QChar::fromLatin1(windowObject->m_status.selectedResultFormat))); window.insert(QStringLiteral("statusBarResultPrecision"), windowObject->m_status.selectedResultPrecision); window.insert(QStringLiteral("bitfieldVisible"), windowObject->m_docks.bitField != nullptr && !windowObject->m_docks.bitField->isHidden()); window.insert(QStringLiteral("openDocks"), QJsonArray::fromStringList(windowObject->openDockNames())); window.insert(QStringLiteral("dockColumnOrders"), windowObject->dockColumnOrders()); const bool keypadVisible = windowObject->m_widgets.keypad != nullptr; window.insert(QStringLiteral("keypadVisible"), keypadVisible); if (keypadVisible) window.insert(QStringLiteral("keypadMode"), static_cast(windowObject->m_keypadMode)); window.insert(QStringLiteral("keypadZoomPercent"), windowObject->m_keypadZoomPercent); window.insert(QStringLiteral("windowState"), QString::fromLatin1(windowObject->saveState(DockLayoutStateVersion).toBase64())); if (windowObject->m_settings->windowPositionSave) window.insert(QStringLiteral("geometry"), QString::fromLatin1(windowObject->saveGeometry().toBase64())); windows.append(window); } QJsonObject layout; layout.insert(QStringLiteral("scheme"), 1); layout.insert(QStringLiteral("kind"), QStringLiteral("session-layout")); layout.insert(QStringLiteral("activeWindow"), QStringLiteral("window-0")); QSet privateNames; for (const QPointer& window : allMainWindows()) { if (window) { for (Session* session : window->m_loadedSessions) { if (session->isPrivate()) privateNames.insert(session->name()); } } } QJsonArray persistentWindows; for (const QJsonValue& value : windows) { QJsonObject window = value.toObject(); const QJsonObject persistentRoot = persistentSessionLayout(window.value(QStringLiteral("root")).toObject(), privateNames); if (!persistentRoot.isEmpty()) { window.insert(QStringLiteral("root"), persistentRoot); persistentWindows.append(window); } } if (!persistentWindows.isEmpty()) layout.insert(QStringLiteral("activeWindow"), persistentWindows.first().toObject().value(QStringLiteral("id"))); layout.insert(QStringLiteral("windows"), persistentWindows); m_settings->sessionLayoutJson = QString::fromUtf8( QJsonDocument(layout).toJson(QJsonDocument::Compact)); m_settings->saveSessionLayoutJson(); } void MainWindow::openImportedSession(Session* session) { if (session == nullptr) return; if (m_sessionSavePending) flushPendingSessionSave(); const QString name = firstAvailableImportedSessionName(session->name(), m_loadedSessions); session->setName(name); m_loadedSessions.insert(name, session); updatePaneLoadedSessionCounts(); applyUserDefinitions(); activateSession(session); QString importedSessionPath = sessionFilePath(name); saveSession(importedSessionPath); saveSessionLayout(false); } void MainWindow::activateSession(Session* session) { StartupDiagnostics::AppearanceContext context("Activate session"); if (session == nullptr) return; const bool previousSessionIsLoaded = m_session != nullptr && m_loadedSessions.values().contains(m_session); if (previousSessionIsLoaded && m_session != session) { if (m_sessionSavePending) flushPendingSessionSave(); captureEditorTextInCurrentSession(); if (m_widgets.display != nullptr && m_paneSessionNames.value(m_widgets.display) == m_session->name()) { m_sessionViewportAnchors.insert(m_session->name(), m_widgets.display->viewportTopAnchor()); QScrollBar* bar = m_widgets.display->verticalScrollBar(); const int scrollValue = bar->value() == bar->maximum() ? (std::numeric_limits::max)() : bar->value(); m_sessionScrollValues.insert(m_session->name(), scrollValue); } } const bool displayAlreadyShowsSession = m_widgets.display != nullptr && m_widgets.display->session() == session; m_session = session; m_evaluator = m_session->evaluator(); m_evaluator->initializeBuiltInVariables(); if (m_widgets.display != nullptr) m_widgets.display->setSession(m_session); if (m_widgets.editor != nullptr) m_widgets.editor->setSession(m_session); if (m_docks.history) m_docks.history->widget()->setSession(m_session); if (m_docks.variables) m_docks.variables->widget()->setEvaluator(m_evaluator); if (m_docks.userFunctions) m_docks.userFunctions->widget()->setEvaluator(m_evaluator); if (m_docks.userUnits) m_docks.userUnits->widget()->setEvaluator(m_evaluator); if (m_widgets.display != nullptr) addSessionToActivePane(m_session->name()); m_pendingHistoryEditIndex = -1; if (m_widgets.display != nullptr) m_widgets.display->setEditingHistoryIndex(-1); if (m_widgets.editor != nullptr) m_widgets.editor->setHistoryArrowNavigationEnabled(true); if (!displayAlreadyShowsSession) restoreEditorTextFromCurrentSession(); if (m_widgets.editor != nullptr) m_widgets.editor->updateHistory(); if (m_widgets.display != nullptr && !displayAlreadyShowsSession) m_widgets.display->refresh(); if (m_docks.history) m_docks.history->widget()->updateHistory(); emit variablesChanged(); emit functionsChanged(); emit unitsChanged(); QTimer::singleShot(0, this, [this]() { emit variablesChanged(); emit functionsChanged(); emit unitsChanged(); }); if (m_widgets.display == nullptr) { m_conditions.autoAns = !m_session->historyIsEmpty(); updatePaneEditorCursorVisibility(); return; } m_widgets.display->viewport()->update(); if (!displayAlreadyShowsSession) { const QPair anchor = m_sessionViewportAnchors.value(m_session->name(), qMakePair(-1, 0)); const int scrollValue = m_sessionScrollValues.value(m_session->name(), -1); if (anchor.first >= 0) { m_widgets.display->restoreViewportTopAnchor(anchor); QTimer::singleShot(0, this, [this, anchor]() { m_widgets.display->restoreViewportTopAnchor(anchor); }); } if (scrollValue >= 0) { m_widgets.display->restoreScrollValue(scrollValue); QTimer::singleShot(0, this, [this, scrollValue]() { m_widgets.display->restoreScrollValue(scrollValue); }); } } m_conditions.autoAns = !m_session->historyIsEmpty(); updatePaneEditorCursorVisibility(); } void MainWindow::captureEditorTextInCurrentSession() { if (m_widgets.editor == nullptr) return; Session* session = nullptr; if (m_widgets.display != nullptr) { const QString paneSessionName = m_paneSessionNames.value(m_widgets.display); session = m_loadedSessions.value(paneSessionName, nullptr); } if (session == nullptr) session = m_session; if (session == nullptr) return; session->setEditorText(m_widgets.editor->text()); } void MainWindow::restoreEditorTextFromCurrentSession() { if (m_session == nullptr || m_widgets.editor == nullptr) return; m_widgets.editor->setText(m_session->editorText()); m_widgets.editor->setCursorPosition(m_widgets.editor->text().size()); if (m_widgets.editor->text().trimmed().isEmpty() && m_widgets.bitField) m_widgets.bitField->clear(); else m_widgets.editor->refreshAutoCalc(); QTimer::singleShot(0, this, [this]() { if (m_widgets.editor) m_widgets.editor->refreshAutoCalc(); }); m_widgets.editor->setFocus(); } void MainWindow::initializeApplicationStyle() { StartupDiagnostics::AppearanceContext context("Initialize application style"); // Set the application style before any main-window widgets are created. ensureDockChromeStyleInstalled(); } MainWindow::MainWindow(bool restorePreviousSession) : QMainWindow() , m_restorePreviousSessionOnStartup(restorePreviousSession) { StartupDiagnostics::AppearanceContext context("Initial window construction"); StartupDiagnostics::Scope windowTiming("Construct main window (total)"); StartupDiagnostics::Scope timing("Register window"); qApp->setQuitOnLastWindowClosed(false); applyDockCornerLayout(); setAttribute(Qt::WA_Hover, true); setMouseTracking(true); if (primaryMainWindow().isNull()) primaryMainWindow() = this; allMainWindows().append(QPointer(this)); if (objectName().isEmpty()) setObjectName(QStringLiteral("window-%1").arg(QUuid::createUuid().toString(QUuid::WithoutBraces))); windowIds().insert(objectName(), QPointer(this)); timing.next("Create initial session and evaluator"); m_session = new Session(); m_session->setName(firstAvailableUntitledSessionName(m_loadedSessions)); m_loadedSessions.insert(m_session->name(), m_session); timing.next("Load constants repository"); m_constants = Constants::instance(); m_evaluator = m_session->evaluator(); timing.next("Load functions repository"); m_functions = FunctionRepo::instance(); m_evaluator->initializeBuiltInVariables(); timing.next("Initialize window state and menu style"); m_translator = 0; m_settings = Settings::instance(); m_dockColumnOrders = QJsonDocument::fromJson(m_settings->dockColumnOrdersJson.toUtf8()).object(); m_startupPrivateTabPending = restorePreviousSession && this == primaryMainWindow() && !g_restoringExtraWindows && m_settings->openPrivateTabOnStartup; if (g_restoringExtraWindows && primaryMainWindow() && primaryMainWindow()->m_startupPrivateTabPending) { setAttribute(Qt::WA_ShowWithoutActivating); } MenuStyle::install(); m_keypadMode = m_settings->keypadMode; m_keypadZoomPercent = m_settings->keypadZoomPercent; DMath::complexMode = m_settings->complexNumbers; CMath::setImaginaryUnitSymbol(m_settings->imaginaryUnit); m_widgets.manual = 0; m_widgets.keypad = 0; m_widgets.bitField = nullptr; m_widgets.keypadContainer = 0; m_conditions.autoAns = false; m_docks.book = 0; m_docks.history = 0; m_docks.constants = 0; m_docks.functions = 0; m_docks.variables = 0; m_docks.userFunctions = 0; m_docks.userUnits = 0; m_docks.bitField = 0; m_status.angleUnit = 0; m_status.angleUnitSection = 0; m_status.angleUnitLabel = 0; m_status.resultFormat = 0; m_status.resultFormatSection = 0; m_status.resultFormatLabel = 0; m_status.resultPrecisionSeparator = 0; m_status.resultPrecision = 0; m_status.resultPrecisionSection = 0; m_status.resultPrecisionLabel = 0; m_status.angleUnitSeparator = 0; m_copyWidget = 0; m_pendingHistoryEditIndex = -1; m_shutdownStateSaved = false; #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS m_versionCheck = 0; #endif m_deferredSessionSaveTimer = new QTimer(this); m_deferredSessionSaveTimer->setSingleShot(true); m_deferredSessionSaveTimer->setInterval(200); m_sessionSavePending = false; m_bulkEvaluationInProgress = false; m_bulkHistoryChanged = false; m_bulkVariablesChanged = false; m_bulkFunctionsChanged = false; m_bulkUnitsChanged = false; connect(m_deferredSessionSaveTimer, &QTimer::timeout, this, &MainWindow::flushPendingSessionSave); connect(qApp, &QApplication::focusChanged, this, &MainWindow::handleApplicationFocusChanged); qApp->installEventFilter(this); timing.next("Create main UI (total)"); createUi(); timing.next("Apply startup settings (total)"); applySettings(); timing.next("Finalize theme and editor focus"); StartupDiagnostics::AppearanceContext finalThemeContext("Finalize window theme"); m_initializingUi = false; applyThemeSurfacePalette(); refreshPaneThemes(); // Keep direct window construction working without the startup initializer. ensureDockChromeStyleInstalled(); updatePaneLoadedSessionCounts(); // Set the initial focus after parenting the editor and restoring the docks. m_widgets.editor->setFocus(Qt::OtherFocusReason); if (!m_settings->hasNumberFormatStyleSetting) QTimer::singleShot(0, this, SLOT(showNumberFormatDialog())); #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS timing.next("Initialize update checker"); m_versionCheck = new VersionCheck(this, this); m_versionCheck->checkForUpdateAfterFirstPaint(); #endif timing.next("Initialize manual server"); m_manualServer = ManualServer::instance(); connect(this, SIGNAL(languageChanged()), m_manualServer, SLOT(ensureCorrectLanguage())); } MainWindow::~MainWindow() { // QWidget's destructor can change focus and hide docks before QObject // disconnects us. Stop these callbacks while MainWindow is still alive. disconnect(qApp, &QApplication::focusChanged, this, &MainWindow::handleApplicationFocusChanged); for (QDockWidget* dock : std::as_const(m_allDocks)) disconnect(dock, nullptr, this, nullptr); qApp->removeEventFilter(this); windowIds().remove(objectName()); allMainWindows().removeAll(QPointer(this)); if (!applicationShutdownInProgress()) updatePaneEditorCursorVisibility(); if (m_docks.book) deleteBookDock(); if (m_docks.constants) deleteConstantsDock(); if (m_docks.variables) deleteVariablesDock(); if (m_docks.userFunctions) deleteUserFunctionsDock(); if (m_docks.userUnits) deleteUserUnitsDock(); if (m_docks.functions) deleteFunctionsDock(); if (m_docks.history) deleteHistoryDock(); qDeleteAll(m_loadedSessions); m_session = nullptr; } void MainWindow::showAboutDialog() { AboutBox dialog(this); dialog.resize(480, 640); dialog.exec(); } void MainWindow::showDiagnosticsDialog() { int windows = 0; int panes = 0; int sessions = 0; qint64 historyEntries = 0; qint64 variables = 0; qint64 functions = 0; qint64 units = 0; for (const auto& pointer : allMainWindows()) { if (MainWindow* window = pointer.data()) { ++windows; panes += window->splitPaneDisplays().size(); sessions += window->m_loadedSessions.size(); for (const Session* session : window->m_loadedSessions) { historyEntries += session->historySize(); variables += session->variablesToList().size(); functions += session->UserFunctionsToList().size(); units += session->userUnitsToList().size(); } } } const QString workload = QStringLiteral( "Open windows: %1\nVisible session panes: %2\nLoaded sessions: %3\n" "Loaded history entries: %4\nVariables: %5\nUser functions: %6\nUser units: %7\n") .arg(windows).arg(panes).arg(sessions).arg(historyEntries) .arg(variables).arg(functions).arg(units); DiagnosticsDialog dialog(appDiagnosticsReport(workload), this); dialog.exec(); } void MainWindow::clearHistory() { if (m_session->historyIsEmpty()) return; QMessageBox confirmation(this); confirmation.setIcon(QMessageBox::Question); confirmation.setWindowTitle(tr("Clear History")); confirmation.setText(tr("Are you sure you want to clear the calculation history?")); confirmation.setStandardButtons(QMessageBox::Yes | QMessageBox::No); confirmation.setDefaultButton(QMessageBox::No); confirmation.setEscapeButton(QMessageBox::No); QShortcut clearHistoryEscape(QKeySequence(Qt::Key_Escape), &confirmation); connect(&clearHistoryEscape, &QShortcut::activated, &confirmation, &QMessageBox::reject); if (confirmation.exec() != QMessageBox::Yes) return; m_session->clearHistory(); m_pendingHistoryEditIndex = -1; m_widgets.display->setEditingHistoryIndex(-1); m_widgets.editor->setHistoryArrowNavigationEnabled(true); clearEditorAndBitfield(); emit historyChanged(); m_conditions.autoAns = false; } void MainWindow::clearSession() { if (m_session->historyIsEmpty() && m_session->variablesToList().isEmpty() && m_session->UserFunctionsToList().isEmpty() && m_session->userUnitsToList().isEmpty() && m_widgets.editor->text().isEmpty()) { return; } QMessageBox confirmation(this); confirmation.setIcon(QMessageBox::Question); confirmation.setWindowTitle(tr("Clear Session")); confirmation.setText(tr("Clear this session's calculations, unfinished expression, variables, functions, and units?")); confirmation.setInformativeText(tr("Global user definitions are kept.")); confirmation.setStandardButtons(QMessageBox::Yes | QMessageBox::No); confirmation.setDefaultButton(QMessageBox::No); confirmation.setEscapeButton(QMessageBox::No); QShortcut clearSessionEscape(QKeySequence(Qt::Key_Escape), &confirmation); connect(&clearSessionEscape, &QShortcut::activated, &confirmation, &QMessageBox::reject); if (confirmation.exec() != QMessageBox::Yes) return; m_session->clearHistory(); m_session->clearVariables(); m_session->clearUserFunctions(); m_session->clearUserUnits(); m_pendingHistoryEditIndex = -1; m_widgets.display->setEditingHistoryIndex(-1); m_widgets.editor->setHistoryArrowNavigationEnabled(true); clearEditorAndBitfield(); m_evaluator->initializeBuiltInVariables(); applyUserDefinitions(); emit historyChanged(); emit variablesChanged(); emit functionsChanged(); emit unitsChanged(); m_conditions.autoAns = false; saveSessionToDefaultPath(); } void MainWindow::showNewSessionDialog() { createUntitledSession(); saveSessionLayout(false); } QString MainWindow::firstAvailableSessionNameAcrossWindows(bool privateSession) const { QHash sessions; for (const QPointer& window : allMainWindows()) { if (window) { for (auto it = window->m_loadedSessions.constBegin(); it != window->m_loadedSessions.constEnd(); ++it) sessions.insert(it.key(), it.value()); } } if (!privateSession) return firstAvailableUntitledSessionName(sessions); for (int number = 1; number < (std::numeric_limits::max)(); ++number) { const QString name = QStringLiteral("Private-%1").arg(number); if (!loadedSessionNameExists(sessions, name) && !QFileInfo::exists(sessionFilePath(name))) return name; } return firstAvailableImportedSessionName(QStringLiteral("Private"), sessions); } void MainWindow::showNewPrivateSession() { Session* session = new Session(); session->setPrivate(true); session->setName(firstAvailableSessionNameAcrossWindows(true)); m_loadedSessions.insert(session->name(), session); applyUserDefinitions(); activateSession(session); // Startup must keep the saved workspace intact while other windows restore. if (!m_startupPrivateTabPending) saveSessionLayout(false); } void MainWindow::finishStartupSessionRestore(bool restoredSession) { StartupDiagnostics::Scope timing("Finalize startup session and focus"); if (m_startupPrivateTabPending) { const bool emptyUntitledSession = untitledSessionNumber(m_session->name()) > 0 && !sessionHasPersistableContent(m_session) && m_widgets.editor->text().trimmed().isEmpty(); if (restoredSession && !emptyUntitledSession) { showNewPrivateSession(); } else { // Reuse a blank tab instead of opening an extra empty ordinary session. m_session->setPrivate(true); renameLoadedSession(m_session, firstAvailableSessionNameAcrossWindows(true)); applyUserDefinitions(); } m_startupPrivateTabPending = false; if (isVisible()) { raise(); activateWindow(); } } // Startup always ends in the active editor, even if a dock input took focus // while the saved window layout was being restored. if (isActiveWindow()) setActiveEditorDisplayPane(m_widgets.display, m_widgets.editor, true); else m_widgets.editor->setFocus(Qt::OtherFocusReason); } void MainWindow::renameLoadedSession(Session* session, const QString& name) { const QString originalName = session->name(); session->setName(name); for (const QPointer& window : allMainWindows()) { if (!window) continue; // Old reopen snapshots must not bring back the session's saved identity. for (int i = window->m_closedSessionTabs.size() - 1; i >= 0; --i) { if (window->m_closedSessionTabs.at(i).name == originalName) window->m_closedSessionTabs.removeAt(i); } if (window->m_loadedSessions.value(originalName) != session) continue; window->m_loadedSessions.remove(originalName); window->m_loadedSessions.insert(name, session); if (window->m_sessionViewportAnchors.contains(originalName)) window->m_sessionViewportAnchors.insert(name, window->m_sessionViewportAnchors.take(originalName)); if (window->m_sessionScrollValues.contains(originalName)) window->m_sessionScrollValues.insert(name, window->m_sessionScrollValues.take(originalName)); for (QString& paneName : window->m_paneSessionNames) { if (paneName == originalName) paneName = name; } for (QStringList& names : window->m_paneSessionTabs) { for (QString& paneName : names) { if (paneName == originalName) paneName = name; } } window->updatePaneTabBars(); } } void MainWindow::convertSessionPrivacy() { if (m_session == nullptr) return; Session* session = m_session; const bool makePrivate = !session->isPrivate(); if (makePrivate) { QMessageBox confirmation(QMessageBox::Warning, tr("Make Session Private"), tr("The saved session %1 will be deleted. Its contents will stay open in a private session " "and will be discarded when that session is closed or SpeedCrunch exits.") .arg(session->name()), QMessageBox::Yes | QMessageBox::Cancel, this); confirmation.setDefaultButton(QMessageBox::Cancel); confirmation.setEscapeButton(QMessageBox::Cancel); confirmation.button(QMessageBox::Yes)->setText(tr("Make Private")); if (confirmation.exec() != QMessageBox::Yes) return; } captureEditorTextInCurrentSession(); // A delayed or running save must not recreate the file after conversion. m_deferredSessionSaveTimer->stop(); m_sessionSavePending = false; waitForAsyncSessionIo(); const QString name = firstAvailableSessionNameAcrossWindows(makePrivate); if (makePrivate) { const QString path = sessionFilePath(session->name()); if (QFileInfo::exists(path) && !QFile::remove(path)) { QMessageBox::warning(this, tr("Make Session Private"), tr("Could not delete the saved session %1.").arg(path)); saveSessionToDefaultPath(); return; } } else { QJsonObject json; session->serialize(json); json.insert(QLatin1String(SessionJsonKeys::Session), name); if (!writeSessionJsonToFile(json, sessionFilePath(name))) { QMessageBox::warning(this, tr("Keep Session"), tr("Could not save the session. It remains private.")); return; } } session->setPrivate(makePrivate); renameLoadedSession(session, name); saveSessionLayout(true, !makePrivate); } void MainWindow::discardUnusedPrivateSessions() { for (auto it = m_loadedSessions.begin(); it != m_loadedSessions.end();) { Session* session = it.value(); bool attached = session == m_session; for (const QStringList& names : m_paneSessionTabs) attached = attached || names.contains(it.key()); if (session->isPrivate() && !attached) { m_sessionViewportAnchors.remove(it.key()); m_sessionScrollValues.remove(it.key()); it = m_loadedSessions.erase(it); delete session; } else { ++it; } } } void MainWindow::showNewSessionWindow() { if (m_shutdownStateSaved) return; MainWindow* window = new MainWindow(false); window->setAttribute(Qt::WA_DeleteOnClose, true); Session* session = window->m_session; if (session != nullptr) { const QString name = firstAvailableUntitledSessionNameAcrossWindows(window); if (session->name().compare(name, Qt::CaseInsensitive) != 0) { window->m_loadedSessions.remove(session->name()); session->setName(name); window->m_loadedSessions.insert(name, session); } session->setEditorText(QString()); window->m_sessionViewportAnchors.clear(); window->m_sessionScrollValues.clear(); if (window->m_widgets.display != nullptr) { window->m_paneSessionNames.clear(); window->m_paneSessionTabs.clear(); window->m_paneSessionNames.insert(window->m_widgets.display, name); window->m_paneSessionTabs.insert(window->m_widgets.display, QStringList(name)); window->m_widgets.display->setSession(session); window->m_widgets.display->refresh(); } if (window->m_widgets.editor != nullptr) { window->m_widgets.editor->setSession(session); window->m_widgets.editor->setText(QString()); window->m_widgets.editor->setCursorPosition(0); window->m_widgets.editor->updateHistory(); window->m_widgets.editor->refreshAutoCalc(); } window->m_conditions.autoAns = false; window->updatePaneLoadedSessionCounts(); } window->copyWindowLayoutFrom(this); window->resize(size()); QRect availableGeometry; if (QScreen* targetScreen = QGuiApplication::screenAt(frameGeometry().center())) availableGeometry = targetScreen->availableGeometry(); else if (QGuiApplication::primaryScreen() != nullptr) availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); QPoint targetPos = frameGeometry().topLeft() + QPoint(32, 32); if (!availableGeometry.isEmpty() && !availableGeometry.contains(QRect(targetPos, window->size()))) { targetPos = availableGeometry.center() - QRect(QPoint(0, 0), window->size()).center(); } window->move(targetPos); window->show(); window->raise(); window->activateWindow(); window->saveSessionLayout(false); } void MainWindow::showOpenSessionDialog() { migrateLegacyHistoryIfNeeded(); ensureSessionsPath(); struct SessionFileEntry { QString name; QString path; QJsonObject json; }; QList entries; const QDir dir(sessionsPath()); const QFileInfoList files = dir.entryInfoList(QStringList(QStringLiteral("*.json")), QDir::Files | QDir::Readable, QDir::Name | QDir::IgnoreCase); for (const QFileInfo& fileInfo : files) { QJsonObject json; if (!readValidSessionJson(fileInfo.absoluteFilePath(), &json)) continue; SessionFileEntry entry; entry.name = normalizedSessionName(json.value(QLatin1String(SessionJsonKeys::Session)).toString()); entry.path = fileInfo.absoluteFilePath(); entry.json = json; entries.append(entry); } QDialog dialog(this); dialog.setWindowTitle(tr("Open Session")); QVBoxLayout* layout = new QVBoxLayout(&dialog); QListWidget* list = new QListWidget(&dialog); for (int i = 0; i < entries.size(); ++i) { QListWidgetItem* item = new QListWidgetItem(entries.at(i).name, list); item->setData(Qt::UserRole, i); if (m_session != nullptr && entries.at(i).name == m_session->name()) item->setSelected(true); } layout->addWidget(list); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Open | QDialogButtonBox::Cancel, &dialog); QPushButton* openButton = buttons->button(QDialogButtonBox::Open); openButton->setEnabled(list->currentItem() != nullptr); layout->addWidget(buttons); connect(list, &QListWidget::currentItemChanged, &dialog, [openButton](QListWidgetItem* current) { openButton->setEnabled(current != nullptr); }); connect(list, &QListWidget::itemDoubleClicked, &dialog, [&dialog](QListWidgetItem*) { dialog.accept(); }); connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); if (list->count() > 0 && list->currentItem() == nullptr) list->setCurrentRow(0); list->setFocus(); if (dialog.exec() != QDialog::Accepted || list->currentItem() == nullptr) return; const int entryIndex = list->currentItem()->data(Qt::UserRole).toInt(); if (entryIndex < 0 || entryIndex >= entries.size()) return; const SessionFileEntry entry = entries.at(entryIndex); if (focusOpenSession(entry.name)) { saveSessionLayout(false); return; } Session* selectedSession = m_loadedSessions.value(entry.name, nullptr); bool reloadedSession = false; if (selectedSession == nullptr) { selectedSession = new Session(); selectedSession->deSerialize(entry.json, false); selectedSession->setName(entry.name); m_loadedSessions.insert(entry.name, selectedSession); updatePaneLoadedSessionCounts(); reloadedSession = true; } else if (selectedSession == m_session) { selectedSession->deSerialize(entry.json, false); selectedSession->setName(entry.name); reloadedSession = true; } // Deserializing a saved session replaces its symbol tables. Startup global // definitions are applied after normal restore, so manual open/reload has // to do the same or an empty session appears to have no global symbols. if (reloadedSession) applyUserDefinitions(); if (selectedSession != m_session) saveSessionToDefaultPath(); activateSession(selectedSession); saveSessionLayout(false); } void MainWindow::showDuplicateSessionDialog() { if (m_session == nullptr) return; captureEditorTextInCurrentSession(); const QString originalName = normalizedSessionName(m_session->name()); while (true) { bool accepted = false; const QString enteredName = QInputDialog::getText( this, tr("Clone Session"), tr("Session name:"), QLineEdit::Normal, m_session->isPrivate() ? firstAvailableSessionNameAcrossWindows(true) : originalName + QStringLiteral(" (copy)"), &accepted).trimmed(); if (!accepted) return; const QString name = normalizedSessionName(enteredName); if (loadedSessionNameExists(m_loadedSessions, name) || QFileInfo::exists(sessionFilePath(name))) { QMessageBox::warning(this, tr("Clone Session"), tr("A session named %1 already exists.").arg(name)); continue; } QJsonObject duplicateJson; m_session->serialize(duplicateJson); duplicateJson.insert(QLatin1String(SessionJsonKeys::Session), name); const QString duplicatePath = sessionFilePath(name); if (m_session->isPrivate()) { Session* duplicate = new Session(*m_session); duplicate->setName(name); m_loadedSessions.insert(name, duplicate); activateSession(duplicate); saveSessionLayout(false); return; } QFile duplicateFile(duplicatePath); if (!duplicateFile.open(QIODevice::WriteOnly)) { QMessageBox::warning(this, tr("Clone Session"), tr("Could not create session file %1.").arg(duplicatePath)); continue; } const QByteArray sessionData = QJsonDocument(duplicateJson).toJson(QJsonDocument::Compact); if (duplicateFile.write(sessionData) != sessionData.size()) { duplicateFile.close(); QFile::remove(duplicatePath); QMessageBox::warning(this, tr("Clone Session"), tr("Could not write session file %1.").arg(duplicatePath)); continue; } duplicateFile.close(); Session* duplicateSession = new Session(); duplicateSession->deSerialize(duplicateJson, false); duplicateSession->setName(name); duplicateSession->setEditorText(m_session->editorText()); m_loadedSessions.insert(name, duplicateSession); updatePaneLoadedSessionCounts(); activateSession(duplicateSession); m_conditions.autoAns = !duplicateSession->historyIsEmpty(); saveSessionLayout(false); return; } } void MainWindow::showRenameSessionDialog() { if (m_session == nullptr) return; const QString originalName = m_session->name(); while (true) { bool accepted = false; const QString enteredName = QInputDialog::getText( this, tr("Rename Session"), tr("Session name:"), QLineEdit::Normal, originalName, &accepted).trimmed(); if (!accepted) return; const QString name = normalizedSessionName(enteredName); if (name == originalName) return; bool exists = QFileInfo::exists(sessionFilePath(name)); for (const QPointer& window : allMainWindows()) { if (window) exists = exists || loadedSessionNameExists(window->m_loadedSessions, name); } if (exists) { QMessageBox::warning(this, tr("Rename Session"), tr("A session named %1 already exists.").arg(name)); continue; } captureEditorTextInCurrentSession(); if (!m_session->isPrivate()) { m_deferredSessionSaveTimer->stop(); m_sessionSavePending = false; waitForAsyncSessionIo(); QJsonObject json; m_session->serialize(json); json.insert(QLatin1String(SessionJsonKeys::Session), name); const QString path = sessionFilePath(name); if (!writeSessionJsonToFile(json, path)) { QMessageBox::warning(this, tr("Rename Session"), tr("Could not save session file %1.").arg(path)); continue; } const QString originalPath = sessionFilePath(originalName); if (QFileInfo::exists(originalPath) && !QFile::remove(originalPath)) { QFile::remove(path); QMessageBox::warning(this, tr("Rename Session"), tr("Could not delete session file %1.").arg(originalPath)); continue; } } renameLoadedSession(m_session, name); saveSessionLayout(); return; } } void MainWindow::closeCurrentSession() { if (m_session == nullptr) return; QStringList names = paneSessionNames(m_widgets.display); if (names.size() <= 1) { if (splitPaneDisplays().size() <= 1) { const QString closingName = m_session->name(); rememberClosedSessionTab(m_widgets.display, closingName); if (shouldDeleteSessionFileOnClose(closingName, m_session)) QFile::remove(sessionFilePath(closingName)); else if (sessionHasPersistableContent(m_session)) saveSessionToDefaultPath(); // A child window exists only to host its current session set. When // the last tab closes there, close the child window instead of // creating a replacement untitled session as the primary window // does. if (this != primaryMainWindow()) { close(); return; } Session* replacementSession = createUntitledSession(true); QStringList paneNames = paneSessionNames(m_widgets.display); paneNames.removeAll(closingName); if (replacementSession != nullptr && !paneNames.contains(replacementSession->name(), Qt::CaseInsensitive)) paneNames.append(replacementSession->name()); m_paneSessionTabs.insert(m_widgets.display, paneNames); m_paneSessionNames.insert(m_widgets.display, replacementSession ? replacementSession->name() : QString()); Session* closingSession = m_loadedSessions.take(closingName); m_sessionViewportAnchors.remove(closingName); m_sessionScrollValues.remove(closingName); delete closingSession; updatePaneLoadedSessionCounts(); saveSessionLayout(false); return; } QWidget* pane = paneWidgetForDisplay(m_widgets.display); QSplitter* parentSplitter = qobject_cast(pane ? pane->parentWidget() : nullptr); if (parentSplitter == nullptr) return; const int closingPaneIndex = parentSplitter->indexOf(pane); const int nextPaneIndex = closingPaneIndex + 1 < parentSplitter->count() ? closingPaneIndex + 1 : qMax(0, closingPaneIndex - 1); QWidget* nextPane = parentSplitter->widget(nextPaneIndex); ResultDisplay* nextDisplay = nextPane ? nextPane->findChild() : nullptr; Editor* nextEditor = nextPane ? nextPane->findChild() : nullptr; if (nextDisplay == nullptr || nextEditor == nullptr || pane == nextPane) return; const QString closingName = m_session->name(); rememberClosedSessionTab(m_widgets.display, closingName); captureEditorTextInCurrentSession(); QTabBar* closingTabBar = displayTabBar(m_widgets.display); m_paneSessionNames.remove(m_widgets.display); m_paneSessionTabs.remove(m_widgets.display); m_paneTabBars.remove(m_widgets.display); if (closingTabBar != nullptr) m_tabBarDisplays.remove(closingTabBar); m_widgets.display = nextDisplay; m_widgets.editor = nextEditor; m_copyWidget = nextEditor; deletePaneAfterSessionTabDrag(pane); normalizeSplitContainerTree(); updatePaneLoadedSessionCounts(); Session* nextSession = m_loadedSessions.value(m_paneSessionNames.value(nextDisplay), nullptr); if (nextSession != nullptr) activateSession(nextSession); discardUnusedPrivateSessions(); saveSessionLayout(false); return; } const QString closingName = m_session->name(); rememberClosedSessionTab(m_widgets.display, closingName); if (shouldDeleteSessionFileOnClose(closingName, m_session)) QFile::remove(sessionFilePath(closingName)); else if (sessionHasPersistableContent(m_session)) saveSessionToDefaultPath(); names.sort(Qt::CaseInsensitive); const int closingIndex = names.indexOf(closingName); const int nextIndex = closingIndex >= 0 && closingIndex + 1 < names.size() ? closingIndex + 1 : qMax(0, closingIndex - 1); const QString nextName = names.value(nextIndex); Session* nextSession = m_loadedSessions.value(nextName, nullptr); if (nextSession == nullptr || nextSession == m_session) return; QStringList paneNames = paneSessionNames(m_widgets.display); paneNames.removeAll(closingName); m_paneSessionTabs.insert(m_widgets.display, paneNames); activateSession(nextSession); discardUnusedPrivateSessions(); updatePaneLoadedSessionCounts(); saveSessionLayout(false); } void MainWindow::closeCurrentPane() { if (m_widgets.display == nullptr || m_widgets.editor == nullptr || m_session == nullptr) return; captureEditorTextInCurrentSession(); ResultDisplay* closingDisplay = m_widgets.display; QWidget* closingPane = paneWidgetForDisplay(closingDisplay); if (closingPane == nullptr) return; QStringList closingNames = paneSessionNames(closingDisplay); if (closingNames.isEmpty() && m_session != nullptr) closingNames.append(m_session->name()); const auto saveLoadedSession = [this](const QString& name) { Session* session = m_loadedSessions.value(name, nullptr); if (session == nullptr || session->isPrivate()) return; if (shouldDeleteSessionFileOnClose(name, session)) { QFile::remove(sessionFilePath(name)); return; } if (!sessionHasPersistableContent(session)) return; QJsonObject json; session->serialize(json); QFile file(sessionFilePath(name)); if (file.open(QIODevice::WriteOnly)) file.write(QJsonDocument(json).toJson(QJsonDocument::Compact)); }; for (const QString& name : closingNames) saveLoadedSession(name); const QList displaysBeforeClose = splitPaneDisplays(); if (displaysBeforeClose.size() <= 1) { Session* replacementSession = createUntitledSession(true); const QString replacementName = replacementSession ? replacementSession->name() : QString(); m_paneSessionTabs.insert(closingDisplay, replacementName.isEmpty() ? QStringList() : QStringList(replacementName)); m_paneSessionNames.insert(closingDisplay, replacementName); for (const QString& name : closingNames) { if (name == replacementName) continue; Session* session = m_loadedSessions.take(name); m_sessionViewportAnchors.remove(name); m_sessionScrollValues.remove(name); delete session; } if (replacementSession != nullptr) activateSession(replacementSession); updatePaneLoadedSessionCounts(); saveSessionLayout(false); return; } const int closingDisplayIndex = displaysBeforeClose.indexOf(closingDisplay); ResultDisplay* nextDisplay = nullptr; if (closingDisplayIndex >= 0 && closingDisplayIndex + 1 < displaysBeforeClose.size()) nextDisplay = displaysBeforeClose.at(closingDisplayIndex + 1); else if (closingDisplayIndex > 0) nextDisplay = displaysBeforeClose.at(closingDisplayIndex - 1); else { for (ResultDisplay* display : displaysBeforeClose) { if (display != closingDisplay) { nextDisplay = display; break; } } } if (nextDisplay == nullptr) return; Editor* nextEditor = nextDisplay->parentWidget() ? nextDisplay->parentWidget()->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; Session* nextSession = m_loadedSessions.value(m_paneSessionNames.value(nextDisplay), nullptr); if (nextEditor == nullptr || nextSession == nullptr) return; m_paneSessionNames.remove(closingDisplay); m_paneSessionTabs.remove(closingDisplay); QTabBar* closingTabBar = displayTabBar(closingDisplay); m_paneTabBars.remove(closingDisplay); if (closingTabBar != nullptr) m_tabBarDisplays.remove(closingTabBar); m_widgets.display = nextDisplay; m_widgets.editor = nextEditor; m_copyWidget = nextEditor; deletePaneAfterSessionTabDrag(closingPane); normalizeSplitContainerTree(); const auto referencedByRemainingPanes = [this](const QString& name) { for (ResultDisplay* display : splitPaneDisplays()) { const QStringList names = paneSessionNames(display); if (names.contains(name, Qt::CaseInsensitive)) return true; } return false; }; activateSession(nextSession); for (const QString& name : closingNames) { if (referencedByRemainingPanes(name)) continue; Session* session = m_loadedSessions.take(name); m_sessionViewportAnchors.remove(name); m_sessionScrollValues.remove(name); if (session != m_session) delete session; } updatePaneLoadedSessionCounts(); updatePaneEditorCursorVisibility(); saveSessionLayout(false); } void MainWindow::deleteCurrentSession() { if (m_session == nullptr) return; QMessageBox confirmation(this); confirmation.setIcon(QMessageBox::Question); confirmation.setWindowTitle(tr("Delete Session")); confirmation.setText(tr("Are you sure you want to delete this session?")); confirmation.setStandardButtons(QMessageBox::Yes | QMessageBox::No); confirmation.setDefaultButton(QMessageBox::No); confirmation.setEscapeButton(QMessageBox::No); QShortcut deleteSessionEscape(QKeySequence(Qt::Key_Escape), &confirmation); connect(&deleteSessionEscape, &QShortcut::activated, &confirmation, &QMessageBox::reject); if (confirmation.exec() != QMessageBox::Yes) return; const QString deletingName = m_session->name(); const QString deletingPath = sessionFilePath(deletingName); Session* deletingSession = m_session; m_loadedSessions.remove(deletingName); m_sessionViewportAnchors.remove(deletingName); m_sessionScrollValues.remove(deletingName); m_session = nullptr; m_evaluator = nullptr; if (QFileInfo::exists(deletingPath)) QFile::remove(deletingPath); Session* nextSession = nullptr; bool createdReplacementSession = false; if (m_loadedSessions.isEmpty()) { const QString name = firstAvailableUntitledSessionName(m_loadedSessions); nextSession = new Session(); nextSession->setName(name); m_loadedSessions.insert(name, nextSession); createdReplacementSession = true; } else { QStringList names = m_loadedSessions.keys(); names.sort(Qt::CaseInsensitive); nextSession = m_loadedSessions.value(names.first(), nullptr); } updatePaneLoadedSessionCounts(); activateSession(nextSession); for (auto it = m_paneSessionNames.begin(); it != m_paneSessionNames.end(); ++it) { if (it.value() == deletingName) it.value() = nextSession->name(); } for (auto it = m_paneSessionTabs.begin(); it != m_paneSessionTabs.end(); ++it) { QStringList names = it.value(); names.removeAll(deletingName); if (names.isEmpty() && nextSession != nullptr) names.append(nextSession->name()); it.value() = names; } if (createdReplacementSession) applyUserDefinitions(); delete deletingSession; m_conditions.autoAns = false; saveSessionLayout(false); } void MainWindow::showLoadedSessionsMenu(const QPoint& globalPos) { const QStringList paneNames = paneSessionNames(m_widgets.display); if (paneNames.isEmpty()) return; QMenu menu(this); QStringList names = paneNames; names.sort(Qt::CaseInsensitive); for (const QString& name : names) { QAction* action = menu.addAction(name); action->setCheckable(true); action->setChecked(m_session != nullptr && name == m_session->name()); action->setData(name); } MenuStyle::apply(&menu); QAction* selectedAction = menu.exec(globalPos); if (selectedAction == nullptr) return; const QString name = selectedAction->data().toString(); Session* selectedSession = m_loadedSessions.value(name, nullptr); if (selectedSession == nullptr || selectedSession == m_session) return; saveSessionToDefaultPath(); activateSession(selectedSession); saveSessionLayout(false); } void MainWindow::clearEditor() { m_widgets.editor->clear(); if (m_widgets.bitField) m_widgets.bitField->clear(); m_widgets.editor->setFocus(); } void MainWindow::clearEditorAndBitfield() { clearEditor(); } void MainWindow::copyResultToClipboard() { QClipboard* cb = QApplication::clipboard(); Quantity q = m_evaluator->getVariable(QLatin1String("ans")).value(); QString strToCopy(NumberFormatter::format(q)); strToCopy.replace(UnicodeChars::MinusSign, MathDsl::SubOpAl1); cb->setText(strToCopy, QClipboard::Clipboard); } void MainWindow::decreaseOpacity() { if (windowOpacity() > 0.4) setWindowOpacity(windowOpacity() - 0.1); } void MainWindow::increaseOpacity() { if (windowOpacity() < 1.0) setWindowOpacity(windowOpacity() + 0.1); } void MainWindow::deleteVariables() { m_session->clearVariables(); if (m_docks.variables) m_docks.variables->widget()->updateList(); } void MainWindow::deleteUserFunctions() { m_session->clearUserFunctions(); if (m_docks.userFunctions) m_docks.userFunctions->widget()->updateList(); } void MainWindow::setResultPrecision2Digits() { setResultPrecision(2); } void MainWindow::setResultPrecision3Digits() { setResultPrecision(3); } void MainWindow::setResultPrecision8Digits() { setResultPrecision(8); } void MainWindow::setResultPrecision15Digits() { setResultPrecision(15); } void MainWindow::setResultPrecision50Digits() { setResultPrecision(50); } void MainWindow::setResultPrecisionAutomatic() { setResultPrecision(-1); } void MainWindow::setResultPrecisionCustom() { bool ok = false; const int current = (m_settings->resultPrecision >= 0) ? m_settings->resultPrecision : 8; const int precision = QInputDialog::getInt(this, tr("Custom Precision"), tr("Fractional digits:"), current, 0, 50, 1, &ok); if (ok) setResultPrecision(precision); checkInitialResultPrecision(); } void MainWindow::showCustomThemeDialog() { QDialog dialog(this); dialog.setObjectName(QStringLiteral("ThemeDialog")); dialog.setWindowTitle(tr("Theme")); QVBoxLayout* layout = new QVBoxLayout(&dialog); QWidget* themeWidget = new QWidget(&dialog); QHBoxLayout* themeLayout = new QHBoxLayout(themeWidget); themeLayout->setContentsMargins(0, 0, 0, 0); themeLayout->setSpacing(10); QGroupBox* lightThemesGroup = new QGroupBox(tr("Light Themes"), themeWidget); QVBoxLayout* lightThemesLayout = new QVBoxLayout(lightThemesGroup); QListWidget* lightThemeList = new QListWidget(lightThemesGroup); lightThemeList->setObjectName(QStringLiteral("LightThemeList")); lightThemesLayout->addWidget(lightThemeList); themeLayout->addWidget(lightThemesGroup); QGroupBox* darkThemesGroup = new QGroupBox(tr("Dark Themes"), themeWidget); QVBoxLayout* darkThemesLayout = new QVBoxLayout(darkThemesGroup); QListWidget* darkThemeList = new QListWidget(darkThemesGroup); darkThemeList->setObjectName(QStringLiteral("DarkThemeList")); darkThemesLayout->addWidget(darkThemeList); themeLayout->addWidget(darkThemesGroup); layout->addWidget(themeWidget); QGroupBox* previewGroup = new QGroupBox(tr("Preview"), &dialog); QVBoxLayout* previewGroupLayout = new QVBoxLayout(previewGroup); QWidget* previewWidget = new QWidget(previewGroup); previewWidget->setObjectName(QStringLiteral("ThemePreview")); QVBoxLayout* previewLayout = new QVBoxLayout(previewWidget); previewLayout->setContentsMargins(0, 0, 0, 0); previewLayout->setSpacing(0); QWidget* mainPreviewWidget = new QWidget(previewWidget); QHBoxLayout* mainPreviewLayout = new QHBoxLayout(mainPreviewWidget); mainPreviewLayout->setContentsMargins(0, 0, 0, 0); mainPreviewLayout->setSpacing(0); QPlainTextEdit* preview = new QPlainTextEdit(mainPreviewWidget); preview->setReadOnly(true); preview->setFrameShape(QFrame::NoFrame); preview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); preview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); preview->setPlainText( QStringLiteral("cos(2 · π + (3 / 2) · π)\n" "= 0.98512127610111389784\n" "\n" "average({1;2;3;4;5}) ? Calculate the average of the list\n" "= 3\n" "\n" "distance = 42 [km] + 195 [m] → [km] ? Marathon distance\n" "= 42.195 km" ) ); auto previewHighlighter = new SyntaxHighlighter(preview); QWidget* previewScrollbarTrack = new QWidget(mainPreviewWidget); const int previewScrollbarWidth = m_widgets.display ? m_widgets.display->verticalScrollBar()->sizeHint().width() : previewScrollbarTrack->style()->pixelMetric(QStyle::PM_ScrollBarExtent); previewScrollbarTrack->setFixedWidth(previewScrollbarWidth); QVBoxLayout* previewScrollbarLayout = new QVBoxLayout(previewScrollbarTrack); previewScrollbarLayout->setContentsMargins(0, 0, 0, 0); previewScrollbarLayout->setSpacing(0); QWidget* previewScrollbar = new QWidget(previewScrollbarTrack); previewScrollbar->setFixedHeight(28); previewScrollbarLayout->addWidget(previewScrollbar); previewScrollbarLayout->addStretch(); mainPreviewLayout->addWidget(preview); mainPreviewLayout->addWidget(previewScrollbarTrack); previewLayout->addWidget(mainPreviewWidget); Editor* editorPreview = new Editor(previewWidget); editorPreview->setReadOnly(true); editorPreview->setFrameShape(QFrame::NoFrame); editorPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); editorPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); editorPreview->setText(QStringLiteral("sqrt(144) + sin(π / 2)")); editorPreview->setCustomCursorVisible(true); const int editorPreviewHeight = m_widgets.editor ? m_widgets.editor->height() : editorPreview->fontMetrics().lineSpacing() + 46; editorPreview->setFixedHeight(editorPreviewHeight); previewLayout->addWidget(editorPreview); previewGroupLayout->addWidget(previewWidget); layout->addWidget(previewGroup); QGroupBox* rolesGroup = new QGroupBox(tr("Colors"), &dialog); QGridLayout* roleLayout = new QGridLayout(rolesGroup); roleLayout->setHorizontalSpacing(10); roleLayout->setVerticalSpacing(6); layout->addWidget(rolesGroup); QWidget* rolesWidget = rolesGroup; QStringList schemeNames = ColorScheme::enumerate(); QString selectedSchemeName = m_settings->colorScheme == QLatin1String("Custom") ? QString() : m_settings->colorScheme; bool isCustomScheme = selectedSchemeName.isEmpty(); auto currentScheme = ColorScheme::loadByName(m_settings->colorScheme); if (!currentScheme.isValid()) { const QJsonDocument customDoc = QJsonDocument::fromJson(m_settings->customColorSchemeJson.toUtf8()); currentScheme = ColorScheme(customDoc); } if (!currentScheme.isValid()) currentScheme = ColorScheme::loadByName(QStringLiteral("Terminal")); if (!currentScheme.isValid()) currentScheme = ColorScheme(QJsonDocument(QJsonObject())); QMap colorsByRole; const auto roleEntries = ColorScheme::roleNames(); bool primaryColorExplicit = false; QMap roleButtons; QPushButton* okButton = nullptr; const auto applyColorsToControls = [&colorsByRole, &roleButtons, roleEntries]() { for (const auto& roleEntry : roleEntries) updateColorButtonStyle(roleButtons.value(roleEntry.second), colorsByRole.value(roleEntry.second)); }; const auto setColorsFromScheme = [&colorsByRole, &primaryColorExplicit, roleEntries](const ColorScheme& scheme) { for (const auto& roleEntry : roleEntries) colorsByRole[roleEntry.second] = scheme.colorForRole(roleEntry.second); primaryColorExplicit = scheme.hasColorForRole(ColorScheme::Primary); if (!primaryColorExplicit) { const QColor background = colorsByRole.value(ColorScheme::Background); const QColor generatedPrimary = generatePrimaryFromBackground(background); if (generatedPrimary.isValid()) colorsByRole[ColorScheme::Primary] = generatedPrimary; } }; setColorsFromScheme(currentScheme); const auto colorSchemeJsonObject = [&colorsByRole, &primaryColorExplicit, roleEntries]() { QJsonObject object; object.insert(QStringLiteral("$schema"), QString::fromLatin1(ColorScheme::SchemaDraft)); object.insert(QStringLiteral("$id"), QString::fromLatin1(ColorScheme::SchemaId)); for (const auto& roleEntry : roleEntries) { if (roleEntry.second == ColorScheme::Primary && !primaryColorExplicit) continue; object.insert(roleEntry.first, colorsByRole.value(roleEntry.second).name()); } return object; }; const auto applyPreview = [&colorSchemeJsonObject, preview, previewHighlighter, previewWidget, previewScrollbarTrack, previewScrollbar, editorPreview]() { const QJsonObject object = colorSchemeJsonObject(); const ColorScheme scheme = ColorScheme::fromJsonObject(object); const GeneratedThemeSurfaces surfaces = generatedSurfaceColorsForScheme(scheme); previewWidget->setAutoFillBackground(true); previewWidget->setAttribute(Qt::WA_StyledBackground, true); previewWidget->setStyleSheet(QStringLiteral("QWidget#ThemePreview { background-color: %1; }") .arg(surfaces.result.background.name())); previewHighlighter->setColorScheme(ColorScheme::fromJsonObject(scheme.toJsonObject())); const QPalette resultPalette = paletteForThemeSurface(preview->palette(), surfaces.result); preview->setPalette(resultPalette); preview->viewport()->setPalette(resultPalette); preview->setStyleSheet(QStringLiteral("QPlainTextEdit { background-color: %1; color: %2; }") .arg(surfaces.result.background.name(), surfaces.result.foreground.name())); previewHighlighter->rehighlight(); const ThemeScrollBarColors resultScrollBars = scrollBarColorsForSurfaceIndex(surfaces, 1); previewScrollbarTrack->setStyleSheet(QStringLiteral("background-color: %1;") .arg(resultScrollBars.track.name())); previewScrollbar->setStyleSheet(QStringLiteral("background-color: %1; border-radius: 4px;") .arg(resultScrollBars.thumb.name())); editorPreview->setThemeSurfaceColor(surfaces.editorAndLists.background, surfaces.result.background); editorPreview->setThemePreviewColorScheme(scheme); editorPreview->setThemePrimaryColor(surfaces.primary.background, true); editorPreview->setCustomCursorVisible(true); editorPreview->rehighlight(); }; const auto updateThemeListHeight = [](QListWidget* list) { const int visibleRows = qMin(list->count(), 7); const int rowHeight = list->sizeHintForRow(0) > 0 ? list->sizeHintForRow(0) : list->fontMetrics().height() + 6; list->setMaximumHeight(rowHeight * visibleRows + list->frameWidth() * 2); }; const auto restoreThemeListScroll = [&dialog](QListWidget* list, int scrollValue) { if (list == nullptr || list->verticalScrollBar() == nullptr) return; list->verticalScrollBar()->setValue(scrollValue); QPointer guardedList(list); QTimer::singleShot(0, &dialog, [guardedList, scrollValue]() { if (guardedList != nullptr && guardedList->verticalScrollBar() != nullptr) guardedList->verticalScrollBar()->setValue(scrollValue); }); }; QHash pressedThemeListScrollValues; const auto rememberThemeListScroll = [&](QListWidget* list) { if (list != nullptr && list->verticalScrollBar() != nullptr) pressedThemeListScrollValues.insert(list, list->verticalScrollBar()->value()); }; const auto restorePressedThemeListScroll = [&](QListWidget* list) { if (!pressedThemeListScrollValues.contains(list)) return; restoreThemeListScroll(list, pressedThemeListScrollValues.take(list)); }; const auto clearThemeListSelection = [&](QListWidget* list) { if (list == nullptr) return; const int scrollValue = list->verticalScrollBar() ? list->verticalScrollBar()->value() : 0; const QSignalBlocker blocker(list); list->clearSelection(); restoreThemeListScroll(list, scrollValue); }; connect(lightThemeList, &QListWidget::itemPressed, &dialog, [&, lightThemeList](QListWidgetItem*) { rememberThemeListScroll(lightThemeList); }); connect(darkThemeList, &QListWidget::itemPressed, &dialog, [&, darkThemeList](QListWidgetItem*) { rememberThemeListScroll(darkThemeList); }); connect(lightThemeList, &QListWidget::itemClicked, &dialog, [&, lightThemeList](QListWidgetItem*) { restorePressedThemeListScroll(lightThemeList); }); connect(darkThemeList, &QListWidget::itemClicked, &dialog, [&, darkThemeList](QListWidgetItem*) { restorePressedThemeListScroll(darkThemeList); }); const auto populateThemeList = [&](QListWidget* list, ColorSchemeFilter filter) { const QSignalBlocker blocker(list); list->clear(); for (const auto& schemeName : schemeNames) { const ColorScheme scheme = ColorScheme::loadByName(schemeName); if (!scheme.isValid() || !colorSchemeMatchesFilter(scheme, filter)) continue; auto item = new QListWidgetItem(colorSchemeDisplayName(schemeName, scheme), list); item->setData(Qt::UserRole, schemeName); } updateThemeListHeight(list); }; const auto showSelectedTheme = [&](QListWidget* list) { if (selectedSchemeName.isEmpty()) return false; for (int row = 0; row < list->count(); ++row) { QListWidgetItem* item = list->item(row); if (item->data(Qt::UserRole).toString() != selectedSchemeName) continue; const QSignalBlocker blocker(list); list->setCurrentItem(item); item->setSelected(true); list->setFocus(Qt::OtherFocusReason); return true; } return false; }; const auto populateThemeLists = [&]() { schemeNames = ColorScheme::enumerate(); populateThemeList(lightThemeList, ColorSchemeFilter::Light); populateThemeList(darkThemeList, ColorSchemeFilter::Dark); if (showSelectedTheme(lightThemeList)) darkThemeList->clearSelection(); else if (showSelectedTheme(darkThemeList)) lightThemeList->clearSelection(); }; int roleIndex = 0; constexpr int roleRowsPerColumn = 4; for (const auto& roleEntry : roleEntries) { const ColorScheme::Role role = roleEntry.second; QLabel* roleLabel = new QLabel(colorSchemeRoleLabel(role), rolesWidget); QPushButton* colorButton = new QPushButton(rolesWidget); colorButton->setObjectName(QStringLiteral("ThemeColorButton_%1").arg(roleEntry.first)); updateColorButtonStyle(colorButton, colorsByRole.value(role)); roleButtons.insert(role, colorButton); const int row = roleIndex % roleRowsPerColumn; const int column = (roleIndex / roleRowsPerColumn) * 2; roleLayout->addWidget(colorButton, row, column); roleLayout->addWidget(roleLabel, row, column + 1); connect(colorButton, &QPushButton::clicked, &dialog, [&, role]() { const QColor initial = colorsByRole.value(role); const QColor chosen = QColorDialog::getColor(initial, &dialog, tr("Select color for %1").arg(colorSchemeRoleLabel(role))); if (!chosen.isValid()) return; colorsByRole[role] = chosen; if (role == ColorScheme::Primary) primaryColorExplicit = true; if (role == ColorScheme::Background && !primaryColorExplicit) { const QColor generatedPrimary = generatePrimaryFromBackground(chosen); if (generatedPrimary.isValid()) { colorsByRole[ColorScheme::Primary] = generatedPrimary; updateColorButtonStyle(roleButtons.value(ColorScheme::Primary), generatedPrimary); } } selectedSchemeName.clear(); isCustomScheme = true; lightThemeList->clearSelection(); darkThemeList->clearSelection(); updateColorButtonStyle(roleButtons.value(role), chosen); if (okButton != nullptr) okButton->setEnabled(false); applyPreview(); }); ++roleIndex; } applyPreview(); populateThemeLists(); const auto handleThemeSelection = [&](QListWidget* currentList, QListWidget* otherList, QListWidgetItem* current) { if (!current) return; clearThemeListSelection(otherList); const QString schemeName = current->data(Qt::UserRole).toString(); const ColorScheme scheme = ColorScheme::loadByName(schemeName); if (!scheme.isValid()) return; selectedSchemeName = schemeName; isCustomScheme = false; setColorsFromScheme(scheme); applyColorsToControls(); if (okButton != nullptr) okButton->setEnabled(true); applyPreview(); restorePressedThemeListScroll(currentList); }; // Clearing a selection leaves the current item in place, so selecting that // same theme again must update the preview even when the current item stays. connect(lightThemeList, &QListWidget::itemSelectionChanged, &dialog, [&]() { handleThemeSelection(lightThemeList, darkThemeList, lightThemeList->selectedItems().value(0)); }); connect(darkThemeList, &QListWidget::itemSelectionChanged, &dialog, [&]() { handleThemeSelection(darkThemeList, lightThemeList, darkThemeList->selectedItems().value(0)); }); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dialog); okButton = buttons->button(QDialogButtonBox::Ok); QPushButton* importButton = buttons->addButton(tr("Import..."), QDialogButtonBox::ActionRole); QPushButton* exportButton = buttons->addButton(tr("Export..."), QDialogButtonBox::ActionRole); layout->addWidget(buttons); connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); const auto applyCurrentTheme = [&]() { if (isCustomScheme || selectedSchemeName.isEmpty()) { const QJsonObject object = colorSchemeJsonObject(); m_settings->customColorSchemeJson = QString::fromUtf8(QJsonDocument(object).toJson(QJsonDocument::Compact)); m_settings->colorScheme = QStringLiteral("Custom"); } else { m_settings->colorScheme = selectedSchemeName; } for (const QPointer& ptr : allMainWindows()) { if (MainWindow* window = ptr.data()) { window->updateColorSchemeActionState(); emit window->colorSchemeChanged(); } } }; const auto writableColorSchemesPath = [&]() { const auto colorSchemePaths = ColorScheme::fileSystemSearchPaths(); const QString path = colorSchemePaths.isEmpty() ? QString() : colorSchemePaths.constFirst(); if (!path.isEmpty()) QDir().mkpath(path); return path; }; connect(importButton, &QPushButton::clicked, this, [&, roleEntries]() { const QString filePath = QFileDialog::getOpenFileName( this, tr("Import Theme"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), tr("Theme file (*.json);;All files (*)")); if (filePath.isEmpty()) return; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::critical(this, tr("Error"), tr("Can't read from file %1").arg(filePath)); return; } const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); const ColorScheme importedScheme(doc); if (!importedScheme.isValid()) { QMessageBox::critical(this, tr("Error"), tr("Invalid theme file.")); return; } const QFileInfo importFileInfo(filePath); const QString themeName = importFileInfo.completeBaseName(); if (ColorScheme::isBuiltInName(themeName)) { QMessageBox::critical( this, tr("Error"), tr("Can't import theme \"%1\" because it conflicts with a built-in theme.").arg(themeName)); return; } const QString colorSchemesPath = writableColorSchemesPath(); if (colorSchemesPath.isEmpty()) { QMessageBox::critical(this, tr("Error"), tr("Can't find a writable theme folder.")); return; } const QString destinationPath = QDir(colorSchemesPath).filePath(themeName + QLatin1String(".json")); if (QFileInfo::exists(destinationPath)) { const QMessageBox::StandardButton answer = QMessageBox::question( this, tr("Overwrite Theme"), tr("A custom theme named \"%1\" already exists. Do you want to overwrite it?").arg(themeName), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (answer != QMessageBox::Yes) return; const QFileInfo destinationFileInfo(destinationPath); if (destinationFileInfo.absoluteFilePath() != importFileInfo.absoluteFilePath() && !QFile::remove(destinationPath)) { QMessageBox::critical(this, tr("Error"), tr("Can't overwrite theme file %1").arg(destinationPath)); return; } } if (QFileInfo(destinationPath).absoluteFilePath() != importFileInfo.absoluteFilePath() && !QFile::copy(filePath, destinationPath)) { QMessageBox::critical(this, tr("Error"), tr("Can't copy theme file to %1").arg(destinationPath)); return; } for (const auto& roleEntry : roleEntries) { const QColor color = importedScheme.colorForRole(roleEntry.second); colorsByRole[roleEntry.second] = color; } for (const auto& roleEntry : roleEntries) updateColorButtonStyle(roleButtons.value(roleEntry.second), colorsByRole.value(roleEntry.second)); selectedSchemeName = themeName; isCustomScheme = false; if (okButton != nullptr) okButton->setEnabled(true); populateThemeLists(); applyPreview(); }); connect(exportButton, &QPushButton::clicked, this, [&, roleEntries]() { QString colorSchemesPath; if (!selectedSchemeName.isEmpty()) { const QString selectedSchemePath = ColorScheme::filePathForName(selectedSchemeName); if (!selectedSchemePath.startsWith(QLatin1Char(':'))) { const QFileInfo selectedSchemeInfo(selectedSchemePath); if (selectedSchemeInfo.exists()) colorSchemesPath = selectedSchemeInfo.absolutePath(); } } const auto colorSchemePaths = ColorScheme::fileSystemSearchPaths(); if (colorSchemesPath.isEmpty()) { for (const auto& path : colorSchemePaths) { if (QDir(path).exists()) { colorSchemesPath = path; break; } } } if (colorSchemesPath.isEmpty() && !colorSchemePaths.isEmpty()) colorSchemesPath = colorSchemePaths.constFirst(); if (!colorSchemesPath.isEmpty()) QDir().mkpath(colorSchemesPath); QString filePath = QFileDialog::getSaveFileName( this, tr("Export Theme"), colorSchemesPath, tr("Theme file (*.json);;All files (*)")); if (filePath.isEmpty()) return; if (!filePath.endsWith(QLatin1String(".json"), Qt::CaseInsensitive)) filePath += QLatin1String(".json"); const QFileInfo exportFileInfo(filePath); if (ColorScheme::isBuiltInName(exportFileInfo.completeBaseName())) { QMessageBox::critical( this, tr("Error"), tr("Can't export theme as \"%1\" because it conflicts with a built-in theme.").arg(exportFileInfo.completeBaseName())); return; } QFile file(filePath); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QMessageBox::critical(this, tr("Error"), tr("Can't write to file %1").arg(filePath)); return; } const QJsonObject object = colorSchemeJsonObject(); file.write(QJsonDocument(object).toJson(QJsonDocument::Indented)); file.close(); const ColorScheme exportedScheme = ColorScheme::loadFromFile(filePath); if (exportedScheme.isValid()) { selectedSchemeName = exportFileInfo.completeBaseName(); isCustomScheme = false; populateThemeLists(); } }); dialog.setFixedSize(dialog.sizeHint().expandedTo(QSize(720, 560))); if (dialog.exec() != QDialog::Accepted) { m_actions.settingsDisplayColorSchemeCustom->setChecked(m_settings->colorScheme == QLatin1String("Custom")); return; } applyCurrentTheme(); } void MainWindow::selectEditorExpression() { activateWindow(); m_widgets.editor->selectAll(); m_widgets.editor->setFocus(); } void MainWindow::hideStateLabel() { if (m_widgets.state->isVisible() && m_widgets.state->text().contains(QStringLiteral("Current result:"))) { m_currentResultPreviewDismissed = true; if (m_widgets.editor != nullptr) m_widgets.editor->dismissCurrentAutoCalc(); } m_widgets.state->hide(); } void MainWindow::hideCurrentResultPreview() { if (m_widgets.state == nullptr || !m_widgets.state->isVisible() || !m_widgets.state->text().contains(QStringLiteral("Current result:"))) { return; } hideStateLabel(); } void MainWindow::handleEditorEscapePressed() { if (m_widgets.state->isVisible()) { hideStateLabel(); return; } cancelHistoryEntryEdit(); if (m_settings->escapeClearsEditor && (m_widgets.editor->hasFocus() || m_widgets.editor->viewport()->hasFocus())) { clearEditor(); } } void MainWindow::wrapSelection() { m_widgets.editor->wrapSelection(); } void MainWindow::exportJson() { if (m_session == nullptr) return; const QString filters = tr("JSON file (*.json);;Any file (*.*)"); const QString sessionBaseName = sessionFileBaseName(m_session->name()); const QString defaultFileName = sessionBaseName + QLatin1String(".json"); QFileDialog dialog(this, tr("Export session as JSON"), QDir::homePath(), filters); dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setDefaultSuffix(QStringLiteral("json")); dialog.selectFile(defaultFileName); QTimer::singleShot(0, &dialog, [sessionBaseName, &dialog]() { if (QLineEdit* fileNameEdit = dialog.findChild()) fileNameEdit->setSelection(0, sessionBaseName.size()); }); if (dialog.exec() != QDialog::Accepted) return; const QStringList selectedFiles = dialog.selectedFiles(); if (selectedFiles.isEmpty()) return; QString fname = selectedFiles.constFirst(); if (fname.isEmpty()) return; QFile file(fname); if (!file.open(QIODevice::WriteOnly)) { QMessageBox::critical(this, tr("Error"), tr("Can't write to file %1").arg(fname)); return; } QJsonObject json; captureEditorTextInCurrentSession(); m_session->serialize(json); QJsonDocument doc(json); file.write(doc.toJson()); file.close(); } void MainWindow::showSessionImportDialog() { const QString filters = tr("JSON file (*.json);;Any file (*.*)"); QFileDialog dialog(this, tr("Import Session"), QDir::homePath(), filters); dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setFileMode(QFileDialog::ExistingFile); dialog.setDefaultSuffix(QStringLiteral("json")); if (dialog.exec() != QDialog::Accepted) return; const QStringList selectedFiles = dialog.selectedFiles(); if (selectedFiles.isEmpty()) return; const QString fname = selectedFiles.constFirst(); if (fname.isEmpty()) return; QFile file(fname); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::critical(this, tr("Import Session"), tr("Can't read from file %1").arg(fname)); return; } QJsonParseError parseError; const QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &parseError); if (parseError.error != QJsonParseError::NoError) { QMessageBox::critical(this, tr("Import Session"), tr("The selected file is not valid JSON: %1").arg(parseError.errorString())); return; } if (!doc.isObject()) { QMessageBox::critical(this, tr("Import Session"), tr("The selected file is not a SpeedCrunch session JSON file.")); return; } const QJsonObject json = doc.object(); if (json.contains(QLatin1String("scheme"))) { QMessageBox::critical(this, tr("Import Session"), tr("This file uses an obsolete SpeedCrunch session format and cannot be imported.")); return; } const QJsonValue schema = json.value(QLatin1String(SessionJsonKeys::Schema)); if (!schema.isString()) { QMessageBox::critical(this, tr("Import Session"), tr("The selected JSON file is missing the required $schema field.")); return; } if (schema.toString() != QLatin1String(SessionJsonKeys::SchemaDialect)) { QMessageBox::critical(this, tr("Import Session"), tr("The selected JSON file uses an unsupported JSON schema: %1").arg(schema.toString())); return; } const QJsonValue schemaId = json.value(QLatin1String(SessionJsonKeys::Id)); if (!schemaId.isString()) { QMessageBox::critical(this, tr("Import Session"), tr("The selected JSON file is missing the SpeedCrunch session schema identifier ($id).")); return; } if (schemaId.toString() != QLatin1String(SessionJsonKeys::SchemaId)) { QMessageBox::critical(this, tr("Import Session"), tr("The selected JSON file uses an unsupported SpeedCrunch session format: %1").arg(schemaId.toString())); return; } const QJsonValue sessionName = json.value(QLatin1String(SessionJsonKeys::Session)); if (!sessionName.isString()) { QMessageBox::critical(this, tr("Import Session"), tr("The selected JSON file is missing the required session name.")); return; } if (sessionName.toString().trimmed().isEmpty()) { QMessageBox::critical(this, tr("Import Session"), tr("The selected JSON file has an empty session name.")); return; } std::unique_ptr importedSession(new Session()); if (!importedSession->deSerialize(json, false)) { QMessageBox::critical(this, tr("Import Session"), tr("The selected JSON file has invalid or incomplete SpeedCrunch session data.")); return; } openImportedSession(importedSession.release()); } void MainWindow::openSessionsFolder() { if (!ensureSessionsPath()) { QMessageBox::critical(this, tr("Open Sessions Folder"), tr("Could not create the sessions folder: %1").arg(sessionsPath())); return; } const QUrl sessionsFolderUrl = QUrl::fromLocalFile(sessionsPath()); if (!QDesktopServices::openUrl(sessionsFolderUrl)) { QMessageBox::critical(this, tr("Open Sessions Folder"), tr("Could not open the sessions folder: %1").arg(sessionsPath())); } } void MainWindow::importUserDefinitionsFromText(const QString& text, bool overwriteExisting, int* importedVariables, int* importedFunctions, int* importedUnits, int* ignoredLines, QList* ignoredLineNumbers, bool dryRun) { const QString globalVariableTag = tr("Global User Variable"); const QString globalFunctionTag = tr("Global User Function"); const QString globalUnitTag = tr("Global User Unit"); int localImportedVariables = 0; int localImportedFunctions = 0; int localImportedUnits = 0; int localIgnoredLines = 0; QList localIgnoredLineNumbers; Session sessionBackup; bool autoAnsBackup = false; if (dryRun && m_session) { sessionBackup = *m_session; autoAnsBackup = m_conditions.autoAns; } m_evaluator->setAllowGlobalUserDefinitionsOverride(true); const auto hasGlobalTag = [](const QString& description, const QString& tag) { return description.contains(tag); }; const QList existingVariables = m_evaluator->getUserDefinedVariables(); for (const Variable& variable : existingVariables) { if (hasGlobalTag(variable.description(), globalVariableTag)) m_evaluator->unsetVariable(variable.identifier()); } const QList existingFunctions = m_evaluator->getUserFunctions(); for (const UserFunction& function : existingFunctions) { if (hasGlobalTag(function.description(), globalFunctionTag)) m_evaluator->unsetUserFunction(function.name()); } const QList existingUnits = m_evaluator->getUserUnits(); for (const UserUnit& unit : existingUnits) { if (hasGlobalTag(unit.description(), globalUnitTag)) m_evaluator->unsetUserUnit(unit.name()); } m_evaluator->clearGlobalUserDefinitionRegistry(); QString inputText = text; QTextStream stream(&inputText, QIODevice::ReadOnly); int lineNumber = 0; while (!stream.atEnd()) { const QString rawLine = stream.readLine(); ++lineNumber; const QString normalizedExpression = EditorUtils::normalizeExpressionOperators(rawLine).trimmed(); if (normalizedExpression.isEmpty()) continue; const QString expression = m_evaluator->autoFix(normalizedExpression); if (expression.isEmpty() || Evaluator::isCommentOnlyExpression(expression)) continue; QString expressionWithoutDescription = expression; QString explicitDescription; splitAssignmentDescriptionForImport( expression, &expressionWithoutDescription, &explicitDescription); const AssignmentTarget target = assignmentTargetFromExpression(m_evaluator, expression); if (!target.valid) { ++localIgnoredLines; localIgnoredLineNumbers.append(lineNumber); continue; } const bool hasExistingVariable = m_evaluator->hasVariable(target.identifier); const bool hasExistingUserVariable = hasExistingVariable && !m_evaluator->isBuiltInVariable(target.identifier); const bool hasExistingUserFunction = m_evaluator->hasUserFunction(target.identifier); bool hasExistingUserUnit = m_evaluator->hasUserUnit(target.identifier); if (hasExistingUserUnit) { const UserUnit* existingUnit = m_evaluator->getUserUnit(target.identifier); if (!existingUnit || existingUnit->value().isZero()) { m_evaluator->unsetUserUnit(target.identifier); hasExistingUserUnit = false; } } if (!overwriteExisting && (hasExistingVariable || hasExistingUserFunction || hasExistingUserUnit)) { ++localIgnoredLines; localIgnoredLineNumbers.append(lineNumber); continue; } Variable previousVariable; UserFunction previousFunction; UserUnit previousUnit; bool hasPreviousUserFunction = false; if (hasExistingUserVariable) previousVariable = m_evaluator->getVariable(target.identifier); if (hasExistingUserFunction) hasPreviousUserFunction = findUserFunctionByName( m_evaluator->getUserFunctions(), target.identifier, &previousFunction); if (hasExistingUserUnit && m_evaluator->getUserUnit(target.identifier)) previousUnit = *m_evaluator->getUserUnit(target.identifier); if (overwriteExisting) { if (target.isFunction && hasExistingUserVariable) { m_evaluator->unsetVariable(target.identifier); } if (target.isFunction && hasExistingUserFunction) { m_evaluator->unsetUserFunction(target.identifier); } else if (!target.isFunction && !target.isUnit && hasExistingUserFunction) { m_evaluator->unsetUserFunction(target.identifier); } else if (!target.isFunction && !target.isUnit && hasExistingUserVariable) { m_evaluator->unsetVariable(target.identifier); } else if (target.isUnit) { if (hasExistingUserVariable) m_evaluator->unsetVariable(target.identifier); if (hasExistingUserFunction) m_evaluator->unsetUserFunction(target.identifier); if (hasExistingUserUnit) m_evaluator->unsetUserUnit(target.identifier); } } m_evaluator->setExpression(expressionWithoutDescription); m_evaluator->eval(); bool importSucceeded = false; if (m_evaluator->error().isEmpty()) { if (target.isFunction) { importSucceeded = m_evaluator->hasUserFunction(target.identifier); } else if (target.isUnit) { importSucceeded = m_evaluator->hasUserUnit(target.identifier); } else if (m_evaluator->hasVariable(target.identifier) && !m_evaluator->isBuiltInVariable(target.identifier)) { const Variable importedVariable = m_evaluator->getVariable(target.identifier); importSucceeded = !importedVariable.value().isNan(); } } if (!importSucceeded) { if (target.isFunction) { if (m_evaluator->hasUserFunction(target.identifier)) m_evaluator->unsetUserFunction(target.identifier); } else if (target.isUnit) { if (m_evaluator->hasUserUnit(target.identifier)) m_evaluator->unsetUserUnit(target.identifier); } else if (m_evaluator->hasVariable(target.identifier) && !m_evaluator->isBuiltInVariable(target.identifier)) { m_evaluator->unsetVariable(target.identifier); } if (hasExistingUserVariable) { m_evaluator->setVariable( previousVariable.identifier(), previousVariable.value(), previousVariable.type(), previousVariable.description(), previousVariable.formattedValue()); } if (hasPreviousUserFunction) m_evaluator->setUserFunction(previousFunction); if (hasExistingUserUnit) m_evaluator->setUserUnit(previousUnit); ++localIgnoredLines; localIgnoredLineNumbers.append(lineNumber); continue; } if (target.isFunction) { UserFunction taggedFunction; if (findUserFunctionByName(m_evaluator->getUserFunctions(), target.identifier, &taggedFunction)) { QString description = explicitDescription; if (description.isEmpty()) description = taggedFunction.description(); if (!description.contains(globalFunctionTag)) description = description.isEmpty() ? globalFunctionTag : description + QStringLiteral(" · ") + globalFunctionTag; if (taggedFunction.description() != description) taggedFunction.setDescription(description); m_evaluator->setUserFunction(taggedFunction); m_evaluator->registerGlobalUserFunction(target.identifier); } } else if (target.isUnit) { const UserUnit* existingUnit = m_evaluator->getUserUnit(target.identifier); if (existingUnit) { UserUnit taggedUnit = *existingUnit; QString description = explicitDescription; if (description.isEmpty()) description = taggedUnit.description(); if (!description.contains(globalUnitTag)) description = description.isEmpty() ? globalUnitTag : description + QStringLiteral(" · ") + globalUnitTag; if (taggedUnit.description() != description) taggedUnit.setDescription(description); m_evaluator->setUserUnit(taggedUnit); m_evaluator->registerGlobalUserUnit(target.identifier); } } else if (m_evaluator->hasVariable(target.identifier) && !m_evaluator->isBuiltInVariable(target.identifier)) { const Variable importedVariable = m_evaluator->getVariable(target.identifier); QString description = explicitDescription; if (description.isEmpty()) description = importedVariable.description(); if (!description.contains(globalVariableTag)) { description = description.isEmpty() ? globalVariableTag : description + QStringLiteral(" · ") + globalVariableTag; } m_evaluator->setVariable( importedVariable.identifier(), importedVariable.value(), importedVariable.type(), description, importedVariable.formattedValue()); m_evaluator->registerGlobalUserVariable(target.identifier); } if (target.isFunction) ++localImportedFunctions; else if (target.isUnit) ++localImportedUnits; else ++localImportedVariables; } if (!dryRun && (localImportedVariables > 0 || localImportedFunctions > 0 || localImportedUnits > 0)) { emit variablesChanged(); emit functionsChanged(); emit unitsChanged(); } if (dryRun && m_session) { *m_session = sessionBackup; m_conditions.autoAns = autoAnsBackup; } m_evaluator->setAllowGlobalUserDefinitionsOverride(false); if (importedVariables) *importedVariables = localImportedVariables; if (importedFunctions) *importedFunctions = localImportedFunctions; if (importedUnits) *importedUnits = localImportedUnits; if (ignoredLines) *ignoredLines = localIgnoredLines; if (ignoredLineNumbers) *ignoredLineNumbers = localIgnoredLineNumbers; } void MainWindow::applyUserDefinitions(int* importedVariables, int* importedFunctions, int* importedUnits, int* ignoredLines, QList* ignoredLineNumbers) { StartupDiagnostics::Scope timing("Apply global definitions"); const QString definitionsText = m_settings->startupUserDefinitions.trimmed(); const int previousImportedVariables = importedVariables ? *importedVariables : 0; const int previousImportedFunctions = importedFunctions ? *importedFunctions : 0; const int previousImportedUnits = importedUnits ? *importedUnits : 0; const int previousIgnoredLines = ignoredLines ? *ignoredLines : 0; int totalImportedVariables = 0; int totalImportedFunctions = 0; int totalImportedUnits = 0; int maxIgnoredLines = 0; QSet uniqueIgnoredLineNumbers; Session* previousSession = m_session; const bool previousAutoAns = m_conditions.autoAns; const QList sessions = m_loadedSessions.values(); for (Session* session : sessions) { if (session == nullptr) continue; m_session = session; m_evaluator = m_session->evaluator(); m_evaluator->initializeBuiltInVariables(); int sessionImportedVariables = 0; int sessionImportedFunctions = 0; int sessionImportedUnits = 0; int sessionIgnoredLines = 0; QList sessionIgnoredLineNumbers; importUserDefinitionsFromText( definitionsText, true, &sessionImportedVariables, &sessionImportedFunctions, &sessionImportedUnits, &sessionIgnoredLines, &sessionIgnoredLineNumbers, false); totalImportedVariables += sessionImportedVariables; totalImportedFunctions += sessionImportedFunctions; totalImportedUnits += sessionImportedUnits; maxIgnoredLines = qMax(maxIgnoredLines, sessionIgnoredLines); for (int lineNumber : sessionIgnoredLineNumbers) uniqueIgnoredLineNumbers.insert(lineNumber); } m_session = previousSession; m_evaluator = m_session ? m_session->evaluator() : nullptr; if (m_session != nullptr) m_evaluator->initializeBuiltInVariables(); m_conditions.autoAns = previousAutoAns; if (m_widgets.display != nullptr && m_session != nullptr) m_widgets.display->setSession(m_session); if (m_widgets.editor != nullptr && m_evaluator != nullptr) m_widgets.editor->setSession(m_session); if (importedVariables) *importedVariables = previousImportedVariables + totalImportedVariables; if (importedFunctions) *importedFunctions = previousImportedFunctions + totalImportedFunctions; if (importedUnits) *importedUnits = previousImportedUnits + totalImportedUnits; if (ignoredLines) *ignoredLines = previousIgnoredLines + maxIgnoredLines; if (ignoredLineNumbers) { QList sortedIgnoredLineNumbers = uniqueIgnoredLineNumbers.values(); std::sort(sortedIgnoredLineNumbers.begin(), sortedIgnoredLineNumbers.end()); for (int lineNumber : sortedIgnoredLineNumbers) { if (!ignoredLineNumbers->contains(lineNumber)) ignoredLineNumbers->append(lineNumber); } } emit variablesChanged(); emit functionsChanged(); emit unitsChanged(); } void MainWindow::showUserDefinitionsImportDialog() { QDialog dialog(this); dialog.setObjectName(QStringLiteral("UserDefinitionsDialog")); dialog.setWindowTitle(tr("User Definitions")); dialog.setMinimumSize(640, 420); QVBoxLayout* layout = new QVBoxLayout(&dialog); QLabel* info = new QLabel( tr("These definitions are global and are loaded into every session.\n" "They are immutable for sessions and override same-name definitions from the session editor.\n" "Enter one definition per line."), &dialog); info->setWordWrap(true); layout->addWidget(info); QPlainTextEdit* textEdit = new QPlainTextEdit(&dialog); textEdit->setObjectName(QStringLiteral("UserDefinitionsEditor")); textEdit->setPlainText(m_settings->startupUserDefinitions); textEdit->setPlaceholderText(tr("Examples:\n" "my_rate=1.25\n" "f(x)=x^2+1\n" "[cm_s]=[centimetre/second]")); SyntaxHighlighter* startupDefinitionsHighlighter = new SyntaxHighlighter(textEdit); const auto updateDefinitionsTheme = [textEdit, startupDefinitionsHighlighter]() { startupDefinitionsHighlighter->update(); QPalette palette = textEdit->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { palette.setColor(group, QPalette::PlaceholderText, aaForegroundForBackground(palette.color(group, QPalette::Base))); } textEdit->setPalette(palette); textEdit->viewport()->setPalette(palette); }; updateDefinitionsTheme(); connect(this, &MainWindow::colorSchemeChanged, &dialog, updateDefinitionsTheme); connect(this, &MainWindow::syntaxHighlightingChanged, &dialog, [startupDefinitionsHighlighter]() { startupDefinitionsHighlighter->rehighlight(); }); QPlainTextEdit* lineNumbers = new QPlainTextEdit(&dialog); lineNumbers->setObjectName(QStringLiteral("UserDefinitionsLineNumbers")); lineNumbers->setReadOnly(true); lineNumbers->setFrameStyle(QFrame::NoFrame); lineNumbers->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); lineNumbers->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); lineNumbers->setWordWrapMode(QTextOption::NoWrap); lineNumbers->setTextInteractionFlags(Qt::NoTextInteraction); lineNumbers->setStyleSheet(QStringLiteral( "QPlainTextEdit { background: palette(alternate-base); color: palette(mid); }")); lineNumbers->setFixedWidth(36); lineNumbers->setFont(textEdit->font()); QWidget* editorRow = new QWidget(&dialog); QHBoxLayout* editorRowLayout = new QHBoxLayout(editorRow); editorRowLayout->setContentsMargins(0, 0, 0, 0); editorRowLayout->setSpacing(0); editorRowLayout->addWidget(lineNumbers); editorRowLayout->addWidget(textEdit); layout->addWidget(editorRow); const auto updateLineNumbers = [textEdit, lineNumbers]() { QStringList lines; lines.reserve(textEdit->blockCount()); for (int i = 1; i <= textEdit->blockCount(); ++i) lines.append(QString::number(i)); lineNumbers->setPlainText(lines.join(QLatin1Char('\n'))); lineNumbers->verticalScrollBar()->setValue(textEdit->verticalScrollBar()->value()); }; connect(textEdit, &QPlainTextEdit::textChanged, &dialog, updateLineNumbers); connect(textEdit->verticalScrollBar(), &QScrollBar::valueChanged, &dialog, [textEdit, lineNumbers](int) { lineNumbers->verticalScrollBar()->setValue(textEdit->verticalScrollBar()->value()); }); updateLineNumbers(); QDialogButtonBox* buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); QPushButton* applyNowButton = buttons->addButton(tr("Apply"), QDialogButtonBox::ActionRole); QPushButton* validateButton = buttons->addButton(tr("Validate"), QDialogButtonBox::ActionRole); layout->addWidget(buttons); connect(buttons, &QDialogButtonBox::accepted, &dialog, [this, textEdit, &dialog]() { m_settings->startupUserDefinitions = textEdit->toPlainText(); applyUserDefinitions(); dialog.accept(); }); connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); connect(validateButton, &QPushButton::clicked, this, [this, textEdit]() { int importedVariables = 0; int importedFunctions = 0; int importedUnits = 0; int ignoredLines = 0; QList ignoredLineNumbers; importUserDefinitionsFromText( textEdit->toPlainText(), true, &importedVariables, &importedFunctions, &importedUnits, &ignoredLines, &ignoredLineNumbers, true); QString ignoredLineNumbersText; if (!ignoredLineNumbers.isEmpty()) { QStringList values; values.reserve(ignoredLineNumbers.size()); for (int line : ignoredLineNumbers) values.append(QString::number(line)); ignoredLineNumbersText = values.join(QStringLiteral(", ")); } QMessageBox::information( this, tr("Test Results"), tr("Imported variables: %1\nImported functions: %2\nImported units: %3\nLine numbers with errors: %4") .arg(importedVariables) .arg(importedFunctions) .arg(importedUnits) .arg(ignoredLineNumbersText.isEmpty() ? tr("none") : ignoredLineNumbersText)); }); connect(applyNowButton, &QPushButton::clicked, this, [this, textEdit]() { int importedVariables = 0; int importedFunctions = 0; int importedUnits = 0; int ignoredLines = 0; QList ignoredLineNumbers; m_settings->startupUserDefinitions = textEdit->toPlainText(); applyUserDefinitions( &importedVariables, &importedFunctions, &importedUnits, &ignoredLines, &ignoredLineNumbers); QString ignoredLineNumbersText; if (!ignoredLineNumbers.isEmpty()) { QStringList values; values.reserve(ignoredLineNumbers.size()); for (int line : ignoredLineNumbers) values.append(QString::number(line)); ignoredLineNumbersText = values.join(QStringLiteral(", ")); } QMessageBox::information( this, tr("Apply Results"), tr("Imported variables: %1\nImported functions: %2\nImported units: %3\nLine numbers with errors: %4") .arg(importedVariables) .arg(importedFunctions) .arg(importedUnits) .arg(ignoredLineNumbersText.isEmpty() ? tr("none") : ignoredLineNumbersText)); }); if (dialog.exec() != QDialog::Accepted) return; m_settings->startupUserDefinitions = textEdit->toPlainText(); UserDefinitions::saveFrom(m_settings); showStateLabel(tr("User definitions saved.")); } void MainWindow::setAlwaysOnTopEnabled(bool b) { m_settings->windowAlwaysOnTop = b; // move() uses the outer frame position, not the global client-area origin. const QPoint cur = pos(); if (b) setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); else setWindowFlags(windowFlags() & (~ Qt::WindowStaysOnTopHint)); move(cur); show(); } void MainWindow::setAutoAnsEnabled(bool b) { m_settings->autoAns = b; } void MainWindow::setAutoCalcEnabled(bool b) { m_settings->autoCalc = b; if (m_widgets.editor != nullptr) m_widgets.editor->setAutoCalcEnabled(b); } void MainWindow::setHistorySizeLimit() { bool ok = false; const int current = m_session->historyLimit(); const int value = QInputDialog::getInt( this, tr("History Size Limit"), tr("Maximum number of history entries for this session (0 = unlimited):"), current, 0, 1000000, 100, &ok); if (!ok || value == current) return; m_session->setHistoryLimit(value); m_conditions.autoAns = !m_session->historyIsEmpty(); emit historyChanged(); saveSessionToDefaultPath(); } void MainWindow::setLeaveLastExpressionEnabled(bool b) { m_settings->leaveLastExpression = b; } void MainWindow::setUpDownArrowBehavior(QAction* action) { if (!action) return; m_settings->upDownArrowBehavior = static_cast(action->data().toInt()); } void MainWindow::setWindowPositionSaveEnabled(bool b) { m_settings->windowPositionSave = b; } void MainWindow::setOpenPrivateTabOnStartupEnabled(bool enabled) { if (m_settings->openPrivateTabOnStartup == enabled) return; m_settings->openPrivateTabOnStartup = enabled; for (const QPointer& window : allMainWindows()) { if (!window) continue; const QSignalBlocker blocker(window->m_actions.settingsOpenPrivateTabOnStartup); window->m_actions.settingsOpenPrivateTabOnStartup->setChecked(enabled); } m_settings->save(); } void MainWindow::setAutoCompletionEnabled(bool b) { m_settings->autoCompletion = b; if (m_widgets.editor != nullptr) m_widgets.editor->setAutoCompletionEnabled(b); } void MainWindow::setAutoCompletionAcceptWithEnterEnabled(bool enabled) { m_settings->autoCompletionAcceptWithEnter = enabled; QList> windows = allMainWindows(); if (!windows.contains(QPointer(this))) windows.append(QPointer(this)); for (const QPointer& window : windows) { if (!window) continue; const QSignalBlocker blocker(window->m_actions.settingsBehaviorAutoCompletionAcceptWithEnter); window->m_actions.settingsBehaviorAutoCompletionAcceptWithEnter->setChecked(enabled); } } void MainWindow::setAutoCompletionBuiltInFunctionsEnabled(bool b) { m_settings->autoCompletionBuiltInFunctions = b; } void MainWindow::setAutoCompletionBuiltInVariablesEnabled(bool b) { m_settings->autoCompletionBuiltInVariables = b; } void MainWindow::setAutoCompletionLongFormUnitsEnabled(bool b) { m_settings->autoCompletionLongFormUnits = b; } void MainWindow::setAutoCompletionUserFunctionsEnabled(bool b) { m_settings->autoCompletionUserFunctions = b; } void MainWindow::setAutoCompletionUserVariablesEnabled(bool b) { m_settings->autoCompletionUserVariables = b; } void MainWindow::setBitfieldVisible(bool b) { if (b) createBitField(); else deleteBitField(); } void MainWindow::setSyntaxHighlightingEnabled(bool b) { m_settings->syntaxHighlighting = b; emit syntaxHighlightingChanged(); } void MainWindow::setAutomaticInputAdjustmentsEnabled(bool enabled) { m_settings->automaticInputAdjustments = enabled; QList> windows = allMainWindows(); if (!windows.contains(QPointer(this))) windows.append(QPointer(this)); for (const QPointer& window : windows) { if (!window) continue; const QSignalBlocker blocker(window->m_actions.settingsEditingAutomaticInputAdjustments); window->m_actions.settingsEditingAutomaticInputAdjustments->setChecked(enabled); for (Editor* editor : window->findChildren()) editor->refreshInputMode(); } } void MainWindow::setInputDigitGroupingEnabled(bool enabled) { m_settings->inputDigitGrouping = enabled; QList> windows = allMainWindows(); if (!windows.contains(QPointer(this))) windows.append(QPointer(this)); for (const QPointer& window : windows) { if (!window) continue; const QSignalBlocker blocker(window->m_actions.settingsEditingInputDigitGrouping); window->m_actions.settingsEditingInputDigitGrouping->setChecked(enabled); emit window->syntaxHighlightingChanged(); } } void MainWindow::setCursorBlinkingEnabled(bool enabled) { m_settings->cursorBlinking = enabled; QList> windows = allMainWindows(); if (!windows.contains(QPointer(this))) windows.append(QPointer(this)); for (const QPointer& window : windows) { if (!window) continue; const QSignalBlocker blocker(window->m_actions.settingsEditingCursorBlinking); window->m_actions.settingsEditingCursorBlinking->setChecked(enabled); for (Editor* editor : window->findChildren()) editor->setCursorBlinkingEnabled(enabled); } } void MainWindow::setEscapeClearsEditorEnabled(bool enabled) { m_settings->escapeClearsEditor = enabled; QList> windows = allMainWindows(); if (!windows.contains(QPointer(this))) windows.append(QPointer(this)); for (const QPointer& window : windows) { if (!window) continue; const QSignalBlocker blocker(window->m_actions.settingsEditingEscapeClearsEditor); window->m_actions.settingsEditingEscapeClearsEditor->setChecked(enabled); } } void MainWindow::setDigitGrouping(QAction *action) { m_settings->digitGrouping = action->data().toInt(); emit historyChanged(); if (m_widgets.editor != nullptr) m_widgets.editor->refreshAutoCalc(); emit syntaxHighlightingChanged(); } void MainWindow::setDigitGroupingIntegerPartOnlyEnabled(bool b) { m_settings->digitGroupingIntegerPartOnly = b; emit historyChanged(); if (m_widgets.editor != nullptr) m_widgets.editor->refreshAutoCalc(); emit syntaxHighlightingChanged(); } void MainWindow::setAutoResultToClipboardEnabled(bool b) { m_settings->autoResultToClipboard = b; } void MainWindow::setSimplifyResultExpressionsEnabled(bool b) { m_settings->simplifyResultExpressions = b; emit historyChanged(); if (m_widgets.editor != nullptr) m_widgets.editor->refreshAutoCalc(); } void MainWindow::setHoverHighlightResultsEnabled(bool b) { m_settings->hoverHighlightResults = b; for (ResultDisplay* display : splitPaneDisplays()) display->setHoverHighlightEnabled(b); } void MainWindow::setAngleModeDegree() { if (m_settings->angleUnit == 'd' && m_status.selectedAngleUnit == 'd') return; m_settings->angleUnit = 'd'; m_status.selectedAngleUnit = 'd'; setStatusBarText(); syncStatusBarSelectionMenuActionState(); m_evaluator->initializeAngleUnits(); emit angleUnitChanged(); } void MainWindow::setAngleModeRadian() { if (m_settings->angleUnit == 'r' && m_status.selectedAngleUnit == 'r') return; m_settings->angleUnit = 'r'; m_status.selectedAngleUnit = 'r'; setStatusBarText(); syncStatusBarSelectionMenuActionState(); m_evaluator->initializeAngleUnits(); emit angleUnitChanged(); } void MainWindow::setAngleModeGradian() { if (m_settings->angleUnit == 'g' && m_status.selectedAngleUnit == 'g') return; m_settings->angleUnit = 'g'; m_status.selectedAngleUnit = 'g'; setStatusBarText(); syncStatusBarSelectionMenuActionState(); m_evaluator->initializeAngleUnits(); emit angleUnitChanged(); } void MainWindow::setAngleModeTurn() { if (m_settings->angleUnit == 't' && m_status.selectedAngleUnit == 't') return; m_settings->angleUnit = 't'; m_status.selectedAngleUnit = 't'; setStatusBarText(); syncStatusBarSelectionMenuActionState(); m_evaluator->initializeAngleUnits(); emit angleUnitChanged(); } void MainWindow::setAngleModeRevolution() { if (m_settings->angleUnit == 'v' && m_status.selectedAngleUnit == 'v') return; m_settings->angleUnit = 'v'; m_status.selectedAngleUnit = 'v'; setStatusBarText(); syncStatusBarSelectionMenuActionState(); m_evaluator->initializeAngleUnits(); emit angleUnitChanged(); } inline static QString documentsLocation() { return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); } void MainWindow::exportHtml() { if (m_session == nullptr) return; const QString sessionBaseName = sessionFileBaseName(m_session->name()); QFileDialog dialog(this, tr("Export session as HTML"), documentsLocation(), tr("HTML file (*.html)")); dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setDefaultSuffix(QStringLiteral("html")); dialog.selectFile(sessionBaseName + QLatin1String(".html")); QTimer::singleShot(0, &dialog, [sessionBaseName, &dialog]() { if (QLineEdit* fileNameEdit = dialog.findChild()) fileNameEdit->setSelection(0, sessionBaseName.size()); }); if (dialog.exec() != QDialog::Accepted) return; const QStringList selectedFiles = dialog.selectedFiles(); if (selectedFiles.isEmpty()) return; const QString fname = selectedFiles.constFirst(); if (fname.isEmpty()) return; QFile file(fname); if (!file.open(QIODevice::WriteOnly)) { QMessageBox::critical(this, tr("Error"), tr("Can't write to file %1").arg(fname)); return; } QTextStream stream(& file); stream << m_widgets.display->exportHtml(); file.close(); } void MainWindow::exportPlainText() { if (m_session == nullptr) return; const QString sessionBaseName = sessionFileBaseName(m_session->name()); QFileDialog dialog(this, tr("Export session as plain text"), documentsLocation(), tr("Text file (*.txt);;Any file (*.*)")); dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setDefaultSuffix(QStringLiteral("txt")); dialog.selectFile(sessionBaseName + QLatin1String(".txt")); QTimer::singleShot(0, &dialog, [sessionBaseName, &dialog]() { if (QLineEdit* fileNameEdit = dialog.findChild()) fileNameEdit->setSelection(0, sessionBaseName.size()); }); if (dialog.exec() != QDialog::Accepted) return; const QStringList selectedFiles = dialog.selectedFiles(); if (selectedFiles.isEmpty()) return; const QString fname = selectedFiles.constFirst(); if (fname.isEmpty()) return; QFile file(fname); if (!file.open(QIODevice::WriteOnly)) { QMessageBox::critical(this, tr("Error"), tr("Can't write to file %1").arg(fname)); return; } QByteArray text; QTextStream stream(&text, QIODevice::WriteOnly | QIODevice::Text); stream << m_widgets.display->document()->toPlainText(); stream.flush(); file.write(text); file.close(); } void MainWindow::setWidgetsDirection() { QLocale::Language lang = QLocale().language(); bool rtlSystem = (lang == QLocale::Hebrew || lang == QLocale::Arabic || lang == QLocale::Persian); QString code = m_settings->language; bool rtlCustom = (code.contains("he") || code.contains("ar") || code.contains("fa")); if ((m_settings->language == "C" && rtlSystem) || rtlCustom) qApp->setLayoutDirection(Qt::RightToLeft); else qApp->setLayoutDirection(Qt::LeftToRight); } void MainWindow::showFontDialog() { QFontDialog::FontDialogOptions options; #if defined(Q_OS_MACOS) // QTBUG-151608: macOS 27 breaks the native font panel's OK/Cancel buttons. // Revisit this workaround when https://bugreports.qt.io/browse/QTBUG-151608 is fixed upstream. if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 27)) { options |= QFontDialog::DontUseNativeDialog; } #endif bool ok; QFont f = QFontDialog::getFont(&ok, m_widgets.display->font(), this, tr("Editor and Results Font"), options); if (!ok) return; setDisplayFont(f); } void MainWindow::setDisplayFont(const QFont& font) { // New windows read the shared preference. Existing tabs share the editor // and result display in their pane, so updating every pane covers them too. m_settings->displayFont = font.toString(); for (const QPointer& window : allMainWindows()) { if (!window) continue; for (ResultDisplay* display : window->splitPaneDisplays()) display->setFont(font); for (Editor* editor : window->splitPaneEditors()) editor->setFont(font); if (window->m_widgets.state != nullptr && window->m_widgets.state->isVisible()) window->showStateLabel(window->m_widgets.state->text()); } } void MainWindow::setStatusBarVisible(bool b) { b ? createStatusBar() : deleteStatusBar(); } void MainWindow::syncEditMenuActionState() { MainWindow* target = activeMainWindowForMenuAction(this); // Focus can change while a window's child widgets are being destroyed. if (!allMainWindows().contains(QPointer(target))) return; Editor* editor = target->m_widgets.editor; if (editor == nullptr) return; const bool dockInput = target->isDockTextInput(QApplication::focusWidget()); const bool editing = !editor->isReadOnly() && !dockInput; const bool canCopy = target->m_copyWidget != nullptr && target->m_copyWidget->textCursor().hasSelection() && !dockInput; const QMimeData* clipboardData = QApplication::clipboard()->mimeData(); const bool canPaste = editing && clipboardData != nullptr && clipboardData->hasText(); for (const QPointer& window : allMainWindows()) { if (window == nullptr || window->m_widgets.editor == nullptr) continue; window->m_actions.editUndo->setEnabled(editing && editor->document()->isUndoAvailable()); window->m_actions.editRedo->setEnabled(editing && editor->document()->isRedoAvailable()); window->m_actions.editCut->setEnabled(editing && editor->textCursor().hasSelection()); window->m_actions.editCopy->setEnabled(canCopy); window->m_actions.editPaste->setEnabled(canPaste); } } void MainWindow::syncSessionMenuActionState() { MainWindow* target = activeMainWindowForMenuAction(this); if (!allMainWindows().contains(QPointer(target))) return; const bool canClose = target->m_session != nullptr; const bool canReopen = !target->m_closedSessionTabs.isEmpty(); const QString privacyLabel = canClose && target->m_session->isPrivate() ? tr("Keep") : tr("Make Private..."); for (const QPointer& window : allMainWindows()) { if (window == nullptr || window->m_actions.sessionClose == nullptr) continue; window->m_actions.sessionClose->setEnabled(canClose); window->m_actions.sessionReopen->setEnabled(canReopen); window->m_actions.sessionConvertPrivacy->setText(privacyLabel); } } void MainWindow::syncViewMenuActionState() { QStatusBar* existingStatusBar = findChild(QString(), Qt::FindDirectChildrenOnly); const bool statusBarVisible = existingStatusBar != nullptr && !existingStatusBar->isHidden(); const auto dockIsVisible = [](const QDockWidget* dock) { return dock != nullptr && !dock->isHidden(); }; const bool formulaBookVisible = dockIsVisible(m_docks.book); const bool constantsVisible = dockIsVisible(m_docks.constants); const bool functionsVisible = dockIsVisible(m_docks.functions); const bool historyVisible = dockIsVisible(m_docks.history); const bool variablesVisible = dockIsVisible(m_docks.variables); const bool userFunctionsVisible = dockIsVisible(m_docks.userFunctions); const bool userUnitsVisible = dockIsVisible(m_docks.userUnits); const bool bitfieldVisible = dockIsVisible(m_docks.bitField); const Settings::KeypadMode keypadMode = m_widgets.keypad != nullptr ? m_keypadMode : Settings::KeypadModeDisabled; const int keypadZoomPercent = m_keypadZoomPercent; const bool keypadZoomEnabled = keypadMode != Settings::KeypadModeDisabled; const bool menuBarVisible = menuBar() != nullptr && !menuBar()->isHidden(); const bool fullScreenEnabled = isFullScreen(); // Qt can reuse any window's QAction for the native application menu. Mirror // the active window's complete View state into every action copy while // leaving the inactive windows' widgets untouched. for (const QPointer& ptr : allMainWindows()) { MainWindow* window = ptr.data(); if (window == nullptr) continue; const auto setChecked = [](QAction* action, bool checked) { if (action == nullptr) return; action->setChecked(checked); }; setChecked(window->m_actions.viewFormulaBook, formulaBookVisible); setChecked(window->m_actions.viewConstants, constantsVisible); setChecked(window->m_actions.viewFunctions, functionsVisible); setChecked(window->m_actions.viewHistory, historyVisible); setChecked(window->m_actions.viewVariables, variablesVisible); setChecked(window->m_actions.viewUserFunctions, userFunctionsVisible); setChecked(window->m_actions.viewUserUnits, userUnitsVisible); setChecked(window->m_actions.viewBitfield, bitfieldVisible); setChecked(window->m_actions.viewStatusBar, statusBarVisible); setChecked(window->m_actions.viewMenuBar, menuBarVisible); setChecked(window->m_actions.viewFullScreenMode, fullScreenEnabled); window->m_menus.keypadZoom->setEnabled(keypadZoomEnabled); switch (keypadMode) { case Settings::KeypadModeBasicWide: setChecked(window->m_actions.viewKeypadBasicWide, true); break; case Settings::KeypadModeScientificWide: setChecked(window->m_actions.viewKeypadScientificWide, true); break; case Settings::KeypadModeScientificNarrow: setChecked(window->m_actions.viewKeypadScientificNarrow, true); break; case Settings::KeypadModeCustom: setChecked(window->m_actions.viewKeypadCustom, true); break; case Settings::KeypadModeDisabled: default: setChecked(window->m_actions.viewKeypadDisabled, true); break; } switch (keypadZoomPercent) { case 50: setChecked(window->m_actions.viewKeypadZoom50, true); break; case 150: setChecked(window->m_actions.viewKeypadZoom150, true); break; case 200: setChecked(window->m_actions.viewKeypadZoom200, true); break; case 100: default: setChecked(window->m_actions.viewKeypadZoom100, true); break; } window->updateKeypadDisabledActionText(); } } void MainWindow::setStatusBarSelectionActionState(char angleUnit, char resultFormat, int resultPrecision) { switch (angleUnit) { case 'r': m_actions.settingsAngleUnitRadian->setChecked(true); break; case 'g': m_actions.settingsAngleUnitGradian->setChecked(true); break; case 't': m_actions.settingsAngleUnitTurn->setChecked(true); break; case 'v': m_actions.settingsAngleUnitRevolution->setChecked(true); break; default: m_actions.settingsAngleUnitDegree->setChecked(true); break; } switch (resultFormat) { case 'g': m_actions.settingsResultFormatGeneral->setChecked(true); break; case 'n': m_actions.settingsResultFormatEngineering->setChecked(true); break; case 'e': m_actions.settingsResultFormatScientific->setChecked(true); break; case 'r': m_actions.settingsResultFormatRational->setChecked(true); break; case 'h': m_actions.settingsResultFormatHexadecimal->setChecked(true); break; case 'o': m_actions.settingsResultFormatOctal->setChecked(true); break; case 'b': m_actions.settingsResultFormatBinary->setChecked(true); break; case 's': m_actions.settingsResultFormatSexagesimal->setChecked(true); break; default: m_actions.settingsResultFormatFixed->setChecked(true); break; } switch (resultPrecision) { case 0: m_actions.settingsResultFormat0Digits->setChecked(true); break; case 2: m_actions.settingsResultFormat2Digits->setChecked(true); break; case 3: m_actions.settingsResultFormat3Digits->setChecked(true); break; case 8: m_actions.settingsResultFormat8Digits->setChecked(true); break; case 15: m_actions.settingsResultFormat15Digits->setChecked(true); break; case 50: m_actions.settingsResultFormat50Digits->setChecked(true); break; case -1: m_actions.settingsResultFormatAutoPrecision->setChecked(true); break; default: m_actions.settingsResultFormatCustomDigits->setChecked(true); break; } } void MainWindow::syncStatusBarSelectionMenuActionState() { for (const QPointer& ptr : allMainWindows()) { MainWindow* window = ptr.data(); if (window == nullptr) continue; window->setStatusBarSelectionActionState(m_status.selectedAngleUnit, m_status.selectedResultFormat, m_status.selectedResultPrecision); } } void MainWindow::applyStatusBarSelectionState() { // Evaluators still consume the shared Settings values. Window activation // projects this window's durable selection into that shared runtime without // overwriting the selections retained by inactive windows. const bool angleChanged = m_settings->angleUnit != m_status.selectedAngleUnit; const bool formatChanged = m_settings->resultFormat != m_status.selectedResultFormat; const bool precisionChanged = m_settings->resultPrecision != m_status.selectedResultPrecision; m_settings->angleUnit = m_status.selectedAngleUnit; m_settings->resultFormat = m_status.selectedResultFormat; m_settings->resultPrecision = m_status.selectedResultPrecision; syncStatusBarSelectionMenuActionState(); if (angleChanged) { m_evaluator->initializeAngleUnits(); emit angleUnitChanged(); } if (formatChanged) emit resultFormatChanged(); if (precisionChanged) emit resultPrecisionChanged(); } void MainWindow::setMenuBarVisible(bool b) { menuBar()->setVisible(b); m_settings->menuBarVisible = b; } void MainWindow::showStateLabel(const QString& msg) { if (msg.contains(QStringLiteral("Current result:"))) m_lastCurrentResultPreviewMessage = msg; const GeneratedThemeSurfaces surfaces = generatedSurfaceColors(m_settings); const ThemeSurfaceColors tooltipSurface = themeSurfaceForShadeIndex(surfaces, UiConfig::ResultTooltipBackgroundShade); const ThemeSurfaceColors tooltipOutline = themeSurfaceForShadeIndex(surfaces, UiConfig::ResultTooltipOutlineShade); m_widgets.state->setStyleSheet(ToolTipStyleUtils::labelToolTipStyleSheet( QStringLiteral("QLabel"), tooltipSurface.background, tooltipSurface.foreground, tooltipOutline.background, UiConfig::ResultTooltipCornerRadius)); m_widgets.stateCloseButton->setStyleSheet(QStringLiteral(R"( QPushButton { border: none; background: transparent; color: %1; padding: 0; margin: 0; outline: none; } QPushButton:hover { background: transparent; color: %1; } QPushButton:pressed { background: transparent; color: %1; } )").arg(tooltipSurface.foreground.name())); Editor* positionEditor = m_widgets.editor; if (positionEditor == nullptr || positionEditor->window() != this) positionEditor = globallyActiveEditor(); const int closeButtonSize = qMax(14, positionEditor->fontMetrics().height() - 2); const int closeButtonRightPadding = 2; const int closeButtonTopPadding = 1; const int closeButtonReservedWidth = closeButtonSize + closeButtonRightPadding + 2; m_widgets.state->setContentsMargins(6, 3, closeButtonReservedWidth, 3); m_widgets.state->setFont(positionEditor->font()); m_widgets.state->setText(msg); m_widgets.stateCloseButton->setFixedSize(closeButtonSize, closeButtonSize); m_widgets.state->adjustSize(); m_widgets.stateCloseButton->move( m_widgets.state->width() - closeButtonSize - closeButtonRightPadding, closeButtonTopPadding); m_widgets.stateCloseButton->show(); m_widgets.stateCloseButton->raise(); m_widgets.state->show(); m_widgets.state->raise(); const int height = m_widgets.state->height(); const int horizontalMargin = m_settings->editorDisplayStyle == Settings::EditorDisplayClassic ? UiConfig::ClassicTextInset : UiConfig::ResultTooltipStartMargin; QPoint pos = mapFromGlobal( positionEditor->mapToGlobal(QPoint(horizontalMargin, -height))); m_widgets.state->move(pos); } void MainWindow::handleAutoCalcMessageAvailable(const QString& message) { if (pendingDockFocusTarget() != nullptr) return; if (Editor* editor = qobject_cast(sender()); editor != nullptr && editor != m_widgets.editor) return; if (message.contains(QStringLiteral("Current result:")) && !m_widgets.state->isVisible() && message == m_lastCurrentResultPreviewMessage) { return; } if (m_currentResultPreviewDismissed && message.contains(QStringLiteral("Current result:"))) return; showStateLabel(message); } void MainWindow::handleAutoCalcQuantityAvailable(const Quantity& quantity) { if (Editor* editor = qobject_cast(sender()); editor != nullptr && editor != m_widgets.editor) return; if (m_widgets.bitField && m_docks.bitField && !m_docks.bitField->isHidden()) m_widgets.bitField->updateBits(quantity); } void MainWindow::setFullScreenEnabled(bool b) { m_settings->windowOnfullScreen = b; b ? showFullScreen() : showNormal(); } bool MainWindow::event(QEvent* e) { if (e != nullptr && m_settings != nullptr && m_settings->statusBarAppearance == Settings::StatusBarAppearanceSystem && (e->type() == QEvent::ApplicationPaletteChange || e->type() == QEvent::ThemeChange || e->type() == QEvent::StyleChange) && !property("speedcrunchStatusBarRefreshPending").toBool()) { setProperty("speedcrunchStatusBarRefreshPending", true); QTimer::singleShot(0, this, [this]() { applyStatusBarAppearance(findChild(QString(), Qt::FindDirectChildrenOnly), generatedSurfaceColors(m_settings)); updateStatusBarSectionVisibility(); setProperty("speedcrunchStatusBarRefreshPending", false); }); } if (e != nullptr && !m_allDocks.isEmpty() && m_settings->dockAppearance == Settings::DockAppearanceSystem && (e->type() == QEvent::ApplicationPaletteChange || e->type() == QEvent::ThemeChange || e->type() == QEvent::StyleChange)) { scheduleDockAppearanceRefresh(true); } if (e != nullptr) { const bool updateDockSeparators = e->type() == QEvent::Enter || e->type() == QEvent::Leave || e->type() == QEvent::HoverEnter || e->type() == QEvent::HoverMove || e->type() == QEvent::HoverLeave || e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove; if (updateDockSeparators && !m_allDocks.isEmpty()) update(); const bool splitCursor = cursor().shape() == Qt::SplitHCursor || cursor().shape() == Qt::SplitVCursor; if (splitCursor && e->type() == QEvent::MouseButtonPress) { const QMouseEvent* mouseEvent = static_cast(e); if (mouseEvent->button() == Qt::LeftButton) hideCurrentResultPreview(); } else if (splitCursor && e->type() == QEvent::MouseMove) { const QMouseEvent* mouseEvent = static_cast(e); if (mouseEvent->buttons() & Qt::LeftButton) hideCurrentResultPreview(); } } if (e != nullptr && (e->type() == QEvent::KeyPress || e->type() == QEvent::ShortcutOverride)) { QKeyEvent* keyEvent = static_cast(e); const Qt::KeyboardModifiers shortcutModifiers = keyEvent->modifiers() & ~(Qt::KeypadModifier); if (e->type() == QEvent::KeyPress && keyEvent->key() == Qt::Key_F6 && (shortcutModifiers == Qt::NoModifier || shortcutModifiers == Qt::ShiftModifier) && qApp->activeModalWidget() == nullptr && qApp->activePopupWidget() == nullptr) { if (shortcutModifiers == Qt::ShiftModifier) cycleFocusBackward(); else cycleFocusForward(); keyEvent->accept(); return true; } if (keyEvent->key() == Qt::Key_Escape && m_widgets.state != nullptr && m_widgets.state->isVisible() && m_widgets.state->text().contains(QStringLiteral("Current result:"))) { m_currentResultPreviewDismissed = true; if (m_widgets.editor != nullptr) m_widgets.editor->dismissCurrentAutoCalc(); } } if (e != nullptr && e->type() == QEvent::WindowDeactivate) { QWidget* focusWidget = lastFocusWidgetInActiveWindow(); if (focusWidget == nullptr) focusWidget = QApplication::focusWidget(); focusWidgetBeforeWindowDeactivate() = focusWidget != nullptr && focusWidget->window() == this ? focusWidget : m_widgets.editor; editorBeforeWindowDeactivate() = m_widgets.editor; } if (e != nullptr && e->type() == QEvent::WindowActivate) { // Restore the exact widget that had focus before the app lost focus. // On macOS the toolkit may later replay passive editor FocusIn events // in widget order, and the replay can otherwise promote the last pane. QPointer focusWidget(focusWidgetBeforeWindowDeactivate()); if (focusWidget != nullptr && focusWidget->window() != this) focusWidget = nullptr; QPointer activeEditor(qobject_cast(focusWidget.data())); if (activeEditor == nullptr && focusWidget != nullptr) activeEditor = qobject_cast(focusWidget->parentWidget()); if (activeEditor != nullptr && activeEditor->window() != this) activeEditor = nullptr; if (activeEditor == nullptr) { QPointer previousEditor(editorBeforeWindowDeactivate()); if (previousEditor != nullptr && previousEditor->window() == this) activeEditor = previousEditor; } if (activeEditor == nullptr) activeEditor = m_widgets.editor; focusWidgetBeforeWindowDeactivate() = nullptr; editorBeforeWindowDeactivate() = nullptr; pendingWindowActivationEditor() = activeEditor; pendingWindowActivationFocusWidget() = focusWidget; const int restoreGeneration = ++windowActivationRestoreGeneration(); const auto restoreWindowFocus = [this, activeEditor, focusWidget, restoreGeneration]() { if (activeEditor == nullptr || windowActivationRestoreGeneration() != restoreGeneration || QApplication::activePopupWidget() != nullptr) return; QWidget* pane = activeEditor->parentWidget(); ResultDisplay* display = pane ? pane->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (display != nullptr) setActiveEditorDisplayPane(display, activeEditor); if (focusWidget != nullptr && focusWidget->window() == this && windowActivationRestoreGeneration() == restoreGeneration) { focusWidget->setFocus(Qt::ActiveWindowFocusReason); } }; QTimer::singleShot(0, this, restoreWindowFocus); QTimer::singleShot(50, this, restoreWindowFocus); QTimer::singleShot(150, this, restoreWindowFocus); // Some platforms deliver a delayed focus replay after the activation // event has returned. Keep one late restore before clearing the guard. QTimer::singleShot(300, this, restoreWindowFocus); QTimer::singleShot(350, this, [activeEditor, focusWidget, restoreGeneration]() { if (windowActivationRestoreGeneration() == restoreGeneration && pendingWindowActivationEditor() == activeEditor && pendingWindowActivationFocusWidget() == focusWidget) { pendingWindowActivationEditor() = nullptr; pendingWindowActivationFocusWidget() = nullptr; } }); const QString activeName = m_paneSessionNames.value(m_widgets.display); if (!activeName.isEmpty()) { if (Session* activeSession = m_loadedSessions.value(activeName, nullptr)) activateSession(activeSession); } else if (m_session != nullptr) { m_evaluator = m_session->evaluator(); m_evaluator->initializeBuiltInVariables(); } applyStatusBarSelectionState(); syncViewMenuActionState(); } return QMainWindow::event(e); } bool MainWindow::eventFilter(QObject* o, QEvent* e) { if (o == qApp && e != nullptr && e->type() == QEvent::Quit && primaryMainWindow() == this) { // QApplication closes top-level windows in an unspecified order. // Save all windows before floating docks receive Close and hide. qApp->setProperty("speedcrunchShutdownInProgress", true); persistSessionAndSettingsForShutdown(); } if (e != nullptr && e->type() == QEvent::KeyPress) { if (QWidget* widget = qobject_cast(o); widget != nullptr && (widget->window() == this || isDockWidgetDescendant(widget))) { QKeyEvent* keyEvent = static_cast(e); const Qt::KeyboardModifiers shortcutModifiers = keyEvent->modifiers() & ~(Qt::KeypadModifier); if (keyEvent->key() == Qt::Key_F6 && (shortcutModifiers == Qt::NoModifier || shortcutModifiers == Qt::ShiftModifier) && qApp->activeModalWidget() == nullptr && qApp->activePopupWidget() == nullptr) { if (shortcutModifiers == Qt::ShiftModifier) cycleFocusBackward(); else cycleFocusForward(); keyEvent->accept(); return true; } } } if (qobject_cast(o) != nullptr) { if (e->type() == QEvent::MouseButtonPress) { const QMouseEvent* mouseEvent = static_cast(e); if (mouseEvent->button() == Qt::LeftButton) hideCurrentResultPreview(); } else if (e->type() == QEvent::MouseMove) { const QMouseEvent* mouseEvent = static_cast(e); if (mouseEvent->buttons() & Qt::LeftButton) hideCurrentResultPreview(); } return QMainWindow::eventFilter(o, e); } if (QAbstractButton* button = qobject_cast(o); button != nullptr && button->property("speedcrunchDockHeaderButton").toBool()) { if (e->type() == QEvent::Paint) { // Qt's dock title button ignores QAbstractButton::iconSize() and // shrinks icons to 5/8 of PM_SmallIconSize on framed styles (Windows). // Paint our themed icon directly at its intended logical size. QPainter painter(button); const QSize size = button->iconSize().boundedTo(button->size()); const QRect iconRect(QPoint((button->width() - size.width()) / 2, (button->height() - size.height()) / 2), size); button->icon().paint(&painter, iconRect, Qt::AlignCenter, button->isEnabled() ? QIcon::Normal : QIcon::Disabled); return true; } else if (e->type() == QEvent::Enter || e->type() == QEvent::HoverEnter || e->type() == QEvent::MouseMove) { applyDockTitleButtonIcon(button, true); } else if (e->type() == QEvent::Leave) { applyDockTitleButtonIcon(button, false); } return QMainWindow::eventFilter(o, e); } if (QTabBar* tabBar = qobject_cast(o); tabBar != nullptr && tabBar->property("speedcrunchDockSystemTabBar").toBool()) { if (e->type() == QEvent::Enter) { QEnterEvent* enterEvent = static_cast(e); updateDockSystemTabCursor(tabBar, enterEvent->position().toPoint()); } else if (e->type() == QEvent::HoverEnter || e->type() == QEvent::HoverMove) { QHoverEvent* hoverEvent = static_cast(e); updateDockSystemTabCursor(tabBar, hoverEvent->position().toPoint()); } else if (e->type() == QEvent::MouseMove) { QMouseEvent* mouseEvent = static_cast(e); updateDockSystemTabCursor(tabBar, mouseEvent->pos()); } else if (e->type() == QEvent::Leave) { tabBar->setCursor(Qt::ArrowCursor); } return QMainWindow::eventFilter(o, e); } if (QWidget* widget = qobject_cast(o); isDockTextInput(widget)) { if (e->type() == QEvent::MouseButtonPress) { const int textInputGeneration = setPendingDockTextInputFocusTarget(widget); widget->setFocus(Qt::MouseFocusReason); deactivateActiveEditorForTextInputFocus(); QPointer textInput(widget); QTimer::singleShot(0, widget, [textInput, textInputGeneration]() { if (textInput != nullptr && pendingDockTextInputFocusTargetGeneration() == textInputGeneration && pendingDockTextInputFocusTarget() == textInput) textInput->setFocus(Qt::MouseFocusReason); }); QTimer::singleShot(100, widget, [textInput, textInputGeneration]() { if (pendingDockTextInputFocusTargetGeneration() == textInputGeneration && pendingDockTextInputFocusTarget() == textInput) { setPendingDockTextInputFocusTarget(nullptr); } }); } else if (e->type() == QEvent::FocusIn) { deactivateActiveEditorForTextInputFocus(); if (QLineEdit* lineEdit = qobject_cast(widget); lineEdit && m_settings->dockAppearance == Settings::DockAppearanceSpeedCrunch) applyDockSearchClearButtonIcon(lineEdit, generatedSurfaceColors(m_settings), true); } else if (e->type() == QEvent::FocusOut) { if (QLineEdit* lineEdit = qobject_cast(widget); lineEdit && m_settings->dockAppearance == Settings::DockAppearanceSpeedCrunch) applyDockSearchClearButtonIcon(lineEdit, generatedSurfaceColors(m_settings), false); } return QMainWindow::eventFilter(o, e); } if (e->type() == QEvent::MouseButtonPress) { if (QWidget* widget = qobject_cast(o)) { QDockWidget* dock = dockWidgetForDescendant(widget); if (dock != nullptr) { QWidget* focusTarget = dock; if (QAbstractItemView* view = dockItemViewFocusTarget(widget)) { view->setFocusPolicy(Qt::StrongFocus); focusTarget = view; } else { dock->setFocusPolicy(Qt::StrongFocus); } const int focusGeneration = setPendingDockFocusTarget(focusTarget); deactivateActiveEditorForTextInputFocus(); hideStateLabel(); setPendingDockTextInputFocusTarget(nullptr); const QColor inactivePrimary = generatedSurfaceColors(m_settings).primary.background; for (Editor* paneEditor : splitPaneEditors()) { if (paneEditor == nullptr) continue; paneEditor->clearFocus(); paneEditor->setCustomCursorVisible(false); paneEditor->setThemePrimaryColor(inactivePrimary, false); } focusTarget->setFocus(Qt::MouseFocusReason); QPointer focusTargetGuard(focusTarget); const auto restoreDockFocus = [focusTargetGuard, focusGeneration]() { if (focusTargetGuard != nullptr && pendingDockFocusTargetGeneration() == focusGeneration && pendingDockFocusTarget() == focusTargetGuard) focusTargetGuard->setFocus(Qt::MouseFocusReason); }; QTimer::singleShot(0, focusTarget, restoreDockFocus); QTimer::singleShot(50, focusTarget, restoreDockFocus); QTimer::singleShot(250, focusTarget, [focusTargetGuard, focusGeneration]() { if (pendingDockFocusTargetGeneration() == focusGeneration && pendingDockFocusTarget() == focusTargetGuard) { setPendingDockFocusTarget(nullptr); } }); } } } Editor* filteredEditor = qobject_cast(o); if (filteredEditor == nullptr) { if (QWidget* widget = qobject_cast(o)) filteredEditor = qobject_cast(widget->parentWidget()); } if (Editor* editor = filteredEditor) { // Every main window filters application-wide events. Input in another // window must not replace this window's active editor/display pointers. if (editor->window() != this) return QMainWindow::eventFilter(o, e); // Recalling wrapped input can move the editor after its result appears. // Keep the preview above the editor as the pane layout catches up. if (o == editor && editor == m_widgets.editor && (e->type() == QEvent::Move || e->type() == QEvent::Resize) && m_widgets.state != nullptr && m_widgets.state->isVisible()) { showStateLabel(m_widgets.state->text()); } if (e->type() == QEvent::FocusIn && pendingDockFocusTarget() != nullptr) { // A dock click is explicit focus intent. Handle it before editor // completion focus recovery, otherwise a pending completion owner can // pull focus back to an editor and make dock selection use stale pane // state. QPointer focusTarget(pendingDockFocusTarget()); editor->clearFocus(); QTimer::singleShot(0, focusTarget, [focusTarget]() { if (focusTarget != nullptr) focusTarget->setFocus(Qt::MouseFocusReason); }); return true; } if (e->type() == QEvent::FocusIn && pendingDockTextInputFocusTarget() != nullptr) { QPointer textInput(pendingDockTextInputFocusTarget()); QTimer::singleShot(0, textInput, [textInput]() { if (textInput != nullptr) textInput->setFocus(Qt::MouseFocusReason); }); return true; } if (Editor* completionOwner = Editor::completionMouseSelectionOwner()) { if (editor != completionOwner && (e->type() == QEvent::FocusIn || e->type() == QEvent::MouseButtonPress)) { QPointer owner(completionOwner); QTimer::singleShot(0, completionOwner, [owner]() { if (owner != nullptr) { owner->window()->activateWindow(); owner->setFocus(Qt::OtherFocusReason); owner->viewport()->setFocus(Qt::OtherFocusReason); } }); return true; } } if (dockTextInputFocusTransferInProgress() && e->type() == QEvent::FocusIn) return QMainWindow::eventFilter(o, e); if (e->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast(e); if (keyEvent->key() == Qt::Key_Escape && m_widgets.state->isVisible() && m_widgets.state->text().contains(QStringLiteral("Current result:"))) { m_currentResultPreviewDismissed = true; editor->dismissCurrentAutoCalc(); } } // A bare FocusIn is not pane-selection intent. Window activation can // replay FocusIn through every editor viewport in layout order, which // used to make the last pane active after each app switch. Only input // events that originate from the editor path below may select a pane. if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::KeyPress || e->type() == QEvent::InputMethod) { if (pendingWindowActivationEditor() != nullptr && (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::KeyPress)) { cancelWindowActivationRestore(); } if (pendingWindowActivationEditor() != nullptr && editor != pendingWindowActivationEditor()) { // Input method events can still arrive while the activation // restore is settling. Until mouse/key intent cancels the // guard above, keep the previously active editor selected. QPointer activeEditor(pendingWindowActivationEditor()); QPointer window(this); QTimer::singleShot(0, this, [window, activeEditor]() { if (activeEditor != nullptr && window != nullptr && pendingWindowActivationEditor() == activeEditor) { QWidget* pane = activeEditor->parentWidget(); ResultDisplay* display = pane ? pane->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (display != nullptr) window->setActiveEditorDisplayPane(display, activeEditor); } }); return true; } if (pendingSessionTabActivationEditor() != nullptr && editor != pendingSessionTabActivationEditor()) { QPointer targetEditor(pendingSessionTabActivationEditor()); QTimer::singleShot(0, targetEditor, [targetEditor]() { if (targetEditor != nullptr) targetEditor->setFocus(Qt::MouseFocusReason); }); return true; } QWidget* pane = editor->parentWidget(); ResultDisplay* display = pane ? pane->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; if (display != nullptr) setActiveEditorDisplayPane(display, editor); } return QMainWindow::eventFilter(o, e); } if (o == m_widgets.state && e->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast(e); if (mouseEvent->button() == Qt::LeftButton) { hideStateLabel(); return true; } } if (o == m_status.angleUnitLabel || o == m_status.resultFormatLabel || o == m_status.resultPrecisionLabel) { if (e->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast(e); if (mouseEvent->button() == Qt::LeftButton) { const QPoint popupPoint(0, static_cast(o)->height()); if (o == m_status.angleUnitLabel) showAngleModeContextMenu(m_status.angleUnit->mapFromGlobal(static_cast(o)->mapToGlobal(popupPoint))); else if (o == m_status.resultPrecisionLabel) showPrecisionContextMenu(m_status.resultPrecision->mapFromGlobal(static_cast(o)->mapToGlobal(popupPoint))); else showResultFormatContextMenu(m_status.resultFormat->mapFromGlobal(static_cast(o)->mapToGlobal(popupPoint))); return true; } if (mouseEvent->button() == Qt::RightButton) { const QPoint globalPoint = static_cast(o)->mapToGlobal(mouseEvent->pos()); if (o == m_status.angleUnitLabel) showAngleModeContextMenu(m_status.angleUnit->mapFromGlobal(globalPoint)); else if (o == m_status.resultPrecisionLabel) showPrecisionContextMenu(m_status.resultPrecision->mapFromGlobal(globalPoint)); else showResultFormatContextMenu(m_status.resultFormat->mapFromGlobal(globalPoint)); return true; } } if (e->type() == QEvent::ContextMenu) { QContextMenuEvent* contextMenuEvent = static_cast(e); const QPoint globalPoint = contextMenuEvent->globalPos(); if (o == m_status.angleUnitLabel) showAngleModeContextMenu(m_status.angleUnit->mapFromGlobal(globalPoint)); else if (o == m_status.resultPrecisionLabel) showPrecisionContextMenu(m_status.resultPrecision->mapFromGlobal(globalPoint)); else showResultFormatContextMenu(m_status.resultFormat->mapFromGlobal(globalPoint)); return true; } } if (o == m_docks.book) { if (e->type() == QEvent::Close) { deleteBookDock(); return true; } return false; } if (o == m_docks.bitField) { if (e->type() == QEvent::Close) { deleteBitField(); return true; } return false; } if (o == m_docks.constants) { if (e->type() == QEvent::Close) { deleteConstantsDock(); return true; } return false; } if (o == m_docks.functions) { if (e->type() == QEvent::Close) { deleteFunctionsDock(); return true; } return false; } if (o == m_docks.history) { if (e->type() == QEvent::Close) { deleteHistoryDock(); return true; } return false; } if (o == m_docks.variables) { if (e->type() == QEvent::Close) { deleteVariablesDock(); return true; } return false; } if (o == m_docks.userFunctions) { if (e->type() == QEvent::Close) { deleteUserFunctionsDock(); return true; } return false; } if (o == m_docks.userUnits) { if (e->type() == QEvent::Close) { deleteUserUnitsDock(); return true; } return false; } return QMainWindow::eventFilter(o, e); } void MainWindow::deleteKeypad(bool deferredDeletion) { if (!m_widgets.keypad) return; disconnect(m_widgets.keypad); if (deferredDeletion) m_widgets.keypad->deleteLater(); else delete m_widgets.keypad; m_widgets.keypad = 0; if (m_widgets.keypadContainer) { m_layouts.root->removeWidget(m_widgets.keypadContainer); if (deferredDeletion) m_widgets.keypadContainer->deleteLater(); else delete m_widgets.keypadContainer; m_widgets.keypadContainer = 0; } else { m_layouts.root->removeItem(m_layouts.keypad); if (deferredDeletion) m_layouts.keypad->deleteLater(); else delete m_layouts.keypad; } m_layouts.keypad = 0; } void MainWindow::deleteStatusBar() { QStatusBar* existingStatusBar = findChild(QString(), Qt::FindDirectChildrenOnly); if (existingStatusBar != nullptr) existingStatusBar->hide(); if (m_status.angleUnitSection) m_status.angleUnitSection->deleteLater(); m_status.angleUnit = 0; m_status.angleUnitSection = 0; m_status.angleUnitLabel = 0; if (m_status.resultFormatSection) m_status.resultFormatSection->deleteLater(); m_status.resultFormat = 0; m_status.resultFormatSection = 0; m_status.resultFormatLabel = 0; if (m_status.resultPrecisionSeparator) m_status.resultPrecisionSeparator->deleteLater(); m_status.resultPrecisionSeparator = 0; if (m_status.resultPrecisionSection) m_status.resultPrecisionSection->deleteLater(); m_status.resultPrecision = 0; m_status.resultPrecisionSection = 0; m_status.resultPrecisionLabel = 0; if (m_status.angleUnitSeparator) m_status.angleUnitSeparator->deleteLater(); m_status.angleUnitSeparator = 0; if (existingStatusBar != nullptr) setStatusBar(0); } void MainWindow::deleteBitField() { if (!m_docks.bitField) return; deleteDock(m_docks.bitField); m_actions.viewBitfield->setChecked(false); m_settings->bitfieldVisible = false; } void MainWindow::deleteBookDock() { if (!m_docks.book) return; deleteDock(m_docks.book); m_actions.viewFormulaBook->setChecked(false); m_settings->formulaBookDockVisible = false; } void MainWindow::deleteConstantsDock() { if (!m_docks.constants) return; deleteDock(m_docks.constants); m_actions.viewConstants->setChecked(false); m_settings->constantsDockVisible = false; } void MainWindow::deleteFunctionsDock() { if (!m_docks.functions) return; deleteDock(m_docks.functions); m_actions.viewFunctions->setChecked(false); m_settings->functionsDockVisible = false; } void MainWindow::deleteHistoryDock() { if (!m_docks.history) return; deleteDock(m_docks.history); m_actions.viewHistory->setChecked(false); m_settings->historyDockVisible = false; } void MainWindow::deleteVariablesDock() { if (!m_docks.variables) return; deleteDock(m_docks.variables); m_actions.viewVariables->setChecked(false); m_settings->variablesDockVisible = false; } void MainWindow::deleteUserFunctionsDock() { if (!m_docks.userFunctions) return; deleteDock(m_docks.userFunctions); m_actions.viewUserFunctions->setChecked(false); m_settings->userFunctionsDockVisible = false; } void MainWindow::deleteUserUnitsDock() { if (!m_docks.userUnits) return; deleteDock(m_docks.userUnits); m_actions.viewUserUnits->setChecked(false); m_settings->userUnitsDockVisible = false; } void MainWindow::setFunctionsDockVisible(bool b, bool takeFocus) { if (b) createFunctionsDock(takeFocus); else deleteFunctionsDock(); } void MainWindow::setFormulaBookDockVisible(bool b, bool takeFocus) { if (b) createBookDock(takeFocus); else deleteBookDock(); } void MainWindow::setConstantsDockVisible(bool b, bool takeFocus) { if (b) createConstantsDock(takeFocus); else deleteConstantsDock(); } void MainWindow::setHistoryDockVisible(bool b, bool takeFocus) { if (b) createHistoryDock(takeFocus); else deleteHistoryDock(); } void MainWindow::setVariablesDockVisible(bool b, bool takeFocus) { if (b) createVariablesDock(takeFocus); else deleteVariablesDock(); } void MainWindow::setUserFunctionsDockVisible(bool b, bool takeFocus) { if (b) createUserFunctionsDock(takeFocus); else deleteUserFunctionsDock(); } void MainWindow::setUserUnitsDockVisible(bool b, bool takeFocus) { if (b) createUserUnitsDock(takeFocus); else deleteUserUnitsDock(); } void MainWindow::setKeypadVisible(bool b) { if (b && !m_widgets.keypad) createKeypad(); else if (!b && m_widgets.keypad) deleteKeypad(); } void MainWindow::setKeypadMode(QAction* action) { if (!action) return; const Settings::KeypadMode mode = static_cast(action->data().toInt()); const bool isCustomMode = (mode == Settings::KeypadModeCustom); if (isCustomMode && !configureCustomKeypad()) { updateKeypadModeActionState(); return; } if (m_keypadMode == mode && !isCustomMode) return; const bool wasVisible = isVisibleKeypadMode(m_keypadMode); const bool nowVisible = isVisibleKeypadMode(mode); m_keypadMode = mode; m_settings->keypadMode = mode; updateKeypadModeActionState(); if (wasVisible && nowVisible) { deleteKeypad(); createKeypad(); return; } setKeypadVisible(nowVisible); } void MainWindow::setKeypadZoom(QAction* action) { if (!action) return; const int zoomPercent = action->data().toInt(); if (zoomPercent != 50 && zoomPercent != 100 && zoomPercent != 150 && zoomPercent != 200) return; if (m_keypadZoomPercent == zoomPercent) return; m_keypadZoomPercent = zoomPercent; m_settings->keypadZoomPercent = zoomPercent; if (m_widgets.keypad) { deleteKeypad(); createKeypad(); } } bool MainWindow::configureCustomKeypad() { CustomKeypadDialog dialog(m_settings->customKeypad, this); if (dialog.exec() != QDialog::Accepted) return false; m_settings->customKeypad = dialog.customKeypad(); return true; } void MainWindow::setResultFormatBinary() { setResultFormat('b'); setStatusBarText(); } void MainWindow::setResultFormatCartesian() { if (m_settings->resultComplexForm == ComplexForm::Rectangular) return; m_settings->complexNumbers = true; m_settings->secondaryComplexNumbers = true; m_settings->tertiaryComplexNumbers = true; m_settings->quaternaryComplexNumbers = true; m_settings->quinaryComplexNumbers = true; m_settings->resultComplexForm = ComplexForm::Rectangular; m_settings->secondaryResultComplexForm = ComplexForm::Rectangular; m_settings->tertiaryResultComplexForm = ComplexForm::Rectangular; m_settings->quaternaryResultComplexForm = ComplexForm::Rectangular; m_settings->quinaryResultComplexForm = ComplexForm::Rectangular; DMath::complexMode = true; setStatusBarText(); emit resultFormatChanged(); } void MainWindow::setResultFormatEngineering() { setResultFormat('n'); setStatusBarText(); } void MainWindow::setResultFormatFixed() { setResultFormat('f'); setStatusBarText(); } void MainWindow::setResultFormatGeneral() { setResultFormat('g'); setStatusBarText(); } void MainWindow::setResultFormatHexadecimal() { setResultFormat('h'); setStatusBarText(); } void MainWindow::setImaginaryUnitI() { if (m_settings->imaginaryUnit == 'i') return; m_settings->complexNumbers = true; DMath::complexMode = true; m_settings->imaginaryUnit = 'i'; CMath::setImaginaryUnitSymbol(QLatin1Char('i')); m_evaluator->initializeBuiltInVariables(); setStatusBarText(); emit complexNumbersChanged(); emit resultFormatChanged(); } void MainWindow::setImaginaryUnitJ() { if (m_settings->imaginaryUnit == 'j') return; m_settings->complexNumbers = true; DMath::complexMode = true; m_settings->imaginaryUnit = 'j'; CMath::setImaginaryUnitSymbol(QLatin1Char('j')); m_evaluator->initializeBuiltInVariables(); setStatusBarText(); emit complexNumbersChanged(); emit resultFormatChanged(); } void MainWindow::setResultFormatOctal() { setResultFormat('o'); setStatusBarText(); } void MainWindow::setResultFormatPolar() { if (m_settings->resultComplexForm == ComplexForm::Exponential) return; m_settings->complexNumbers = true; m_settings->secondaryComplexNumbers = true; m_settings->tertiaryComplexNumbers = true; m_settings->quaternaryComplexNumbers = true; m_settings->quinaryComplexNumbers = true; m_settings->resultComplexForm = ComplexForm::Exponential; m_settings->secondaryResultComplexForm = ComplexForm::Exponential; m_settings->tertiaryResultComplexForm = ComplexForm::Exponential; m_settings->quaternaryResultComplexForm = ComplexForm::Exponential; m_settings->quinaryResultComplexForm = ComplexForm::Exponential; DMath::complexMode = true; setStatusBarText(); emit resultFormatChanged(); } void MainWindow::setResultFormatTrigonometric() { if (m_settings->resultComplexForm == ComplexForm::Trigonometric) return; m_settings->complexNumbers = true; m_settings->secondaryComplexNumbers = true; m_settings->tertiaryComplexNumbers = true; m_settings->quaternaryComplexNumbers = true; m_settings->quinaryComplexNumbers = true; m_settings->resultComplexForm = ComplexForm::Trigonometric; m_settings->secondaryResultComplexForm = ComplexForm::Trigonometric; m_settings->tertiaryResultComplexForm = ComplexForm::Trigonometric; m_settings->quaternaryResultComplexForm = ComplexForm::Trigonometric; m_settings->quinaryResultComplexForm = ComplexForm::Trigonometric; DMath::complexMode = true; setStatusBarText(); emit resultFormatChanged(); } void MainWindow::setResultFormatCis() { if (m_settings->resultComplexForm == ComplexForm::Cis) return; m_settings->complexNumbers = true; m_settings->secondaryComplexNumbers = true; m_settings->tertiaryComplexNumbers = true; m_settings->quaternaryComplexNumbers = true; m_settings->quinaryComplexNumbers = true; m_settings->resultComplexForm = ComplexForm::Cis; m_settings->secondaryResultComplexForm = ComplexForm::Cis; m_settings->tertiaryResultComplexForm = ComplexForm::Cis; m_settings->quaternaryResultComplexForm = ComplexForm::Cis; m_settings->quinaryResultComplexForm = ComplexForm::Cis; DMath::complexMode = true; setStatusBarText(); emit resultFormatChanged(); } void MainWindow::setResultFormatPolarAngle() { if (m_settings->resultComplexForm == ComplexForm::Phasor) return; m_settings->complexNumbers = true; m_settings->secondaryComplexNumbers = true; m_settings->tertiaryComplexNumbers = true; m_settings->quaternaryComplexNumbers = true; m_settings->quinaryComplexNumbers = true; m_settings->resultComplexForm = ComplexForm::Phasor; m_settings->secondaryResultComplexForm = ComplexForm::Phasor; m_settings->tertiaryResultComplexForm = ComplexForm::Phasor; m_settings->quaternaryResultComplexForm = ComplexForm::Phasor; m_settings->quinaryResultComplexForm = ComplexForm::Phasor; DMath::complexMode = true; setStatusBarText(); emit resultFormatChanged(); } void MainWindow::showAngleModeContextMenu(const QPoint& point) { m_menus.angleUnit->popup(m_status.angleUnit->mapToGlobal(point)); } void MainWindow::setResultFormatScientific() { setResultFormat('e'); setStatusBarText(); } void MainWindow::setResultFormatRational() { setResultFormat('r'); setStatusBarText(); } void MainWindow::setResultFormatSexagesimal() { setResultFormat('s'); setStatusBarText(); } void MainWindow::insertConstantIntoEditor(const QString& c) { if (c.isEmpty()) return; // Insertion takes precedence over focus recovery from the dock click. setPendingDockFocusTarget(nullptr); setPendingDockTextInputFocusTarget(nullptr); QString s = c; s.replace(MathDsl::DotSep, m_settings->radixCharacter()); insertTextIntoEditor(s); } void MainWindow::insertHistoryExpressionIntoEditor(const QString& text) { const QString prefix = m_widgets.editor->text().left(m_widgets.editor->textCursor().selectionStart()); insertTextIntoEditor(prefix.contains(MathDsl::CommentSep) ? text : Editor::historyExpressionForInput(text)); } void MainWindow::insertTextIntoEditor(const QString& s) { if (s.isEmpty()) return; const QString prefix = m_widgets.editor->text().left(m_widgets.editor->textCursor().selectionStart()); const QString normalized = !m_settings->automaticInputAdjustments || prefix.contains(MathDsl::CommentSep) ? s : EditorUtils::normalizeExpressionOperatorsForEditorInput(s); const bool atExpressionStart = [&]() { const QString text = m_widgets.editor->text(); int i = m_widgets.editor->textCursor().position() - 1; while (i >= 0 && text.at(i).isSpace()) --i; return i < 0; }(); if (m_settings->automaticInputAdjustments && atExpressionStart && !normalized.isEmpty()) { int firstNonSpace = 0; while (firstNonSpace < normalized.size() && normalized.at(firstNonSpace).isSpace()) ++firstNonSpace; if (firstNonSpace < normalized.size()) { const QChar leadingChar = normalized.at(firstNonSpace); if (!EditorUtils::isAllowedLeadingCharAtExpressionStart(leadingChar, m_settings->autoAns)) return; } } bool shouldAutoComplete = m_widgets.editor->isAutoCompletionEnabled(); m_widgets.editor->setAutoCompletionEnabled(false); m_widgets.editor->insert(normalized); m_widgets.editor->setAutoCompletionEnabled(shouldAutoComplete); if (!isActiveWindow()) activateWindow(); m_widgets.editor->setFocus(); } void MainWindow::insertFunctionIntoEditor(const QString& f) { if (f.isEmpty()) return; const QString functionCall = f + QStringLiteral("()"); const bool keepAsciiFunctionName = (f.compare(QStringLiteral("sqrt"), Qt::CaseInsensitive) == 0 || f.compare(QStringLiteral("cbrt"), Qt::CaseInsensitive) == 0 || f.compare(QStringLiteral("summation"), Qt::CaseInsensitive) == 0); if (keepAsciiFunctionName) { bool shouldAutoComplete = m_widgets.editor->isAutoCompletionEnabled(); m_widgets.editor->setAutoCompletionEnabled(false); m_widgets.editor->insertPlainText(functionCall); m_widgets.editor->setAutoCompletionEnabled(shouldAutoComplete); if (!isActiveWindow()) activateWindow(); m_widgets.editor->setFocus(); } else { insertTextIntoEditor(functionCall); } QTextCursor cursor = m_widgets.editor->textCursor(); cursor.movePosition(QTextCursor::PreviousCharacter); m_widgets.editor->setTextCursor(cursor); } void MainWindow::handleKeypadButtonPress(Keypad::Button b) { const auto typeWithRules = [this](const QString& s) { typeTextThroughEditorInputRules(m_widgets.editor, s); if (!isActiveWindow()) activateWindow(); m_widgets.editor->setFocus(); }; switch (b) { case Keypad::Key0: typeWithRules("0"); break; case Keypad::Key1: typeWithRules("1"); break; case Keypad::Key2: typeWithRules("2"); break; case Keypad::Key3: typeWithRules("3"); break; case Keypad::Key4: typeWithRules("4"); break; case Keypad::Key5: typeWithRules("5"); break; case Keypad::Key6: typeWithRules("6"); break; case Keypad::Key7: typeWithRules("7"); break; case Keypad::Key8: typeWithRules("8"); break; case Keypad::Key9: typeWithRules("9"); break; case Keypad::KeyPlus: typeWithRules("+"); break; case Keypad::KeyMinus: typeWithRules("−"); break; case Keypad::KeyTimes: typeWithRules(QString(MathDsl::MulCrossOp)); break; case Keypad::KeyDivide: typeWithRules("÷"); break; case Keypad::KeyEE: insertTextIntoEditor("e"); break; case Keypad::KeyLeftPar: typeWithRules("("); break; case Keypad::KeyRightPar: typeWithRules(")"); break; case Keypad::KeyRaise: typeWithRules("^"); break; case Keypad::KeyBackspace: { m_widgets.editor->doBackspace(); if (!isActiveWindow()) activateWindow(); m_widgets.editor->setFocus(); break; } case Keypad::KeyPercent: typeWithRules("%"); break; case Keypad::KeyFactorial: typeWithRules("!"); break; case Keypad::KeySquare: typeWithRules("^2"); break; case Keypad::KeyArgumentSeparator: typeWithRules(";"); break; case Keypad::KeyPi: insertTextIntoEditor("pi"); break; case Keypad::KeyAns: insertTextIntoEditor("ans"); break; case Keypad::KeySqrt: insertTextIntoEditor("sqrt("); break; case Keypad::KeyRoot: insertTextIntoEditor("root("); break; case Keypad::KeyLog10: insertTextIntoEditor("log10("); break; case Keypad::KeyMod: insertTextIntoEditor("mod("); break; case Keypad::KeyLn: insertTextIntoEditor("ln("); break; case Keypad::KeyExp:insertTextIntoEditor("exp("); break; case Keypad::KeySin: insertTextIntoEditor("sin("); break; case Keypad::KeyCos: insertTextIntoEditor("cos("); break; case Keypad::KeyTan: insertTextIntoEditor("tan("); break; case Keypad::KeyAcos: insertTextIntoEditor("arccos("); break; case Keypad::KeyAtan: insertTextIntoEditor("arctan("); break; case Keypad::KeyAsin: insertTextIntoEditor("arcsin("); break; case Keypad::KeyRadixChar: typeWithRules(QString(m_settings->radixCharacter())); break; case Keypad::KeyClear: clearEditor(); break; case Keypad::KeyEquals: evaluateEditorExpression(); break; default: break; } } void MainWindow::handleCustomKeypadButtonPress(int action, const QString& text) { const auto typeWithRules = [this](const QString& s) { typeTextThroughEditorInputRules(m_widgets.editor, s); if (!isActiveWindow()) activateWindow(); m_widgets.editor->setFocus(); }; switch (static_cast(action)) { case Settings::CustomKeypadActionInsertText: typeWithRules(text); break; case Settings::CustomKeypadActionBackspace: { m_widgets.editor->doBackspace(); if (!isActiveWindow()) activateWindow(); m_widgets.editor->setFocus(); break; } case Settings::CustomKeypadActionClearExpression: clearEditor(); break; case Settings::CustomKeypadActionEvaluateExpression: evaluateEditorExpression(); break; default: break; } } #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS void MainWindow::checkForUpdates() { if (!m_versionCheck) return; m_versionCheck->checkForUpdateNow(); } #endif void MainWindow::openFeedbackURL() { QDesktopServices::openUrl(QUrl(QString::fromLatin1(kFeedbackUrl))); } void MainWindow::openSourceURL() { QDesktopServices::openUrl(QUrl(QString::fromLatin1(kSourceUrl))); } void MainWindow::openCommunityURL() { QDesktopServices::openUrl(QUrl(QString::fromLatin1(kCommunityUrl))); } void MainWindow::openDonateURL() { QDesktopServices::openUrl(QUrl(QString::fromLatin1(kDonateUrl))); } void MainWindow::copy() { m_copyWidget->copy(); } void MainWindow::restoreSession(bool restoreHistory) { StartupDiagnostics::Scope timing("Migrate history and schedule session restore"); migrateLegacyHistoryIfNeeded(); ensureSessionsPath(); if (restoreSessionLayout(restoreHistory)) return; restoreWindowLayoutState(m_settings->windowState); const QString name = m_session->name(); const QString filePath = sessionFilePath(name); QPointer windowGuard(this); const auto startupTask = StartupDiagnostics::task("Restore single session (async total)"); QThread* thread = QThread::create([windowGuard, filePath, name, restoreHistory, startupTask]() { StartupDiagnostics::Scope timing("Read single session JSON"); QJsonObject json; const bool ok = readValidSessionJson(filePath, &json); if (ok && !restoreHistory) json.remove(QLatin1String(SessionJsonKeys::History)); if (!windowGuard) return; timing.finish(); QMetaObject::invokeMethod(windowGuard.data(), [windowGuard, ok, json, name, restoreHistory, startupTask]() mutable { StartupDiagnostics::Scope timing("Apply restored single session"); if (!windowGuard) return; if (!ok) { windowGuard->finishStartupSessionRestore(false); return; } Session* loadedSession = new Session(); loadedSession->deSerialize(json, false); loadedSession->setName(name); MainWindow* window = windowGuard.data(); Session* oldSession = window->m_session; window->m_loadedSessions.remove(oldSession ? oldSession->name() : QString()); window->m_loadedSessions.insert(name, loadedSession); window->activateSession(loadedSession); if (oldSession != nullptr) delete oldSession; // The initial session receives globals before this async load finishes. window->applyUserDefinitions(); emit window->historyChanged(); emit window->variablesChanged(); emit window->functionsChanged(); emit window->unitsChanged(); window->restoreEditorTextFromCurrentSession(); window->m_conditions.autoAns = restoreHistory && !loadedSession->historyIsEmpty(); window->finishStartupSessionRestore(true); }, Qt::QueuedConnection); }); { QMutexLocker locker(&asyncSessionIoMutex()); asyncSessionIoThreads().append(thread); } QObject::connect(thread, &QThread::finished, thread, [thread]() { unregisterAsyncSessionIoThread(thread); thread->deleteLater(); }); thread->start(); } bool MainWindow::restoreSessionLayout(bool restoreHistory) { StartupDiagnostics::Scope timing("Parse saved window layout"); if (m_settings->sessionLayoutJson.isEmpty()) return false; const QJsonDocument layoutDoc = QJsonDocument::fromJson(m_settings->sessionLayoutJson.toUtf8()); if (!layoutDoc.isObject()) return false; const QJsonObject layout = layoutDoc.object(); if (layout.value(QStringLiteral("scheme")).toInt() != 1 || layout.value(QStringLiteral("kind")).toString() != QLatin1String("session-layout")) { return false; } const QJsonArray windows = layout.value(QStringLiteral("windows")).toArray(); if (windows.isEmpty()) return false; const QString activeWindowId = layout.value(QStringLiteral("activeWindow")).toString(); QJsonObject window; for (const QJsonValue& value : windows) { if (!value.isObject()) continue; const QJsonObject candidate = value.toObject(); if ((!activeWindowId.isEmpty() && candidate.value(QStringLiteral("id")).toString() == activeWindowId) || (activeWindowId.isEmpty() && candidate.value(QStringLiteral("active")).toBool())) { window = candidate; break; } } if (window.isEmpty() && windows.first().isObject()) window = windows.first().toObject(); if (window.isEmpty()) return false; const QJsonObject root = window.value(QStringLiteral("root")).toObject(); const QString rootType = root.value(QStringLiteral("type")).toString(); if (rootType != QLatin1String("tabs") && rootType != QLatin1String("split")) return false; QJsonArray tabs = rootType == QLatin1String("tabs") ? root.value(QStringLiteral("tabs")).toArray() : QJsonArray(); const auto appendPaneTabs = [&tabs](const QJsonObject& node, const auto& appendPaneTabsRef) -> void { const QString type = node.value(QStringLiteral("type")).toString(); if (type == QLatin1String("pane")) { const QJsonArray paneTabs = node.value(QStringLiteral("tabs")).toArray(); for (const QJsonValue& tabValue : paneTabs) tabs.append(tabValue); return; } if (type != QLatin1String("split")) return; const QJsonArray children = node.value(QStringLiteral("children")).toArray(); for (const QJsonValue& childValue : children) { if (childValue.isObject()) appendPaneTabsRef(childValue.toObject(), appendPaneTabsRef); } }; if (rootType == QLatin1String("split")) appendPaneTabs(root, appendPaneTabs); if (tabs.isEmpty()) return false; // Window-local chrome is independent of session-file I/O. Restore it now // so every window, including the first, has its final UI before it is shown. restoreWindowUiState(window); QString activeSessionName = normalizedSessionName(root.value(QStringLiteral("active")).toString()); QList sessionLoadSpecs; QStringList loadNames; for (const QJsonValue& value : tabs) { if (!value.isObject()) continue; const QJsonObject tab = value.toObject(); const QString name = normalizedSessionName(tab.value(QStringLiteral("name")).toString()); if (loadNames.contains(name, Qt::CaseInsensitive)) continue; loadNames.append(name); QString fileName = tab.value(QStringLiteral("file")).toString(); if (fileName.isEmpty()) fileName = sessionFileBaseName(name) + QLatin1String(".json"); const QString filePath = QDir(sessionsPath()).filePath(fileName); sessionLoadSpecs.append(SessionLoadSpec{ name, filePath, tab }); } if (sessionLoadSpecs.isEmpty()) return false; QPointer windowGuard(this); const auto startupTask = StartupDiagnostics::task("Restore window sessions (async total)"); QThread* thread = QThread::create([windowGuard, sessionLoadSpecs, activeSessionName, layout, window, root, tabs, restoreHistory, startupTask]() { StartupDiagnostics::Scope timing("Read saved session files (worker total)"); QHash sessionJsons; QHash> viewportAnchors; QHash scrollValues; for (const SessionLoadSpec& spec : sessionLoadSpecs) { StartupDiagnostics::Scope fileTiming("Read and parse session JSON"); QJsonObject sessionJson; if (!readValidSessionJson(spec.filePath, &sessionJson)) continue; if (!restoreHistory) sessionJson.remove(QLatin1String(SessionJsonKeys::History)); sessionJson.insert(QLatin1String(SessionJsonKeys::Session), spec.name); sessionJsons.insert(spec.name, sessionJson); const QJsonObject scroll = spec.tab.value(QStringLiteral("scroll")).toObject(); const int block = scroll.value(QStringLiteral("block")).toInt(-1); const int offset = scroll.value(QStringLiteral("offset")).toInt(0); const int scrollValue = scroll.value(QStringLiteral("value")).toInt(-1); if (block >= 0) viewportAnchors.insert(spec.name, qMakePair(block, offset)); if (scrollValue >= 0) scrollValues.insert(spec.name, scrollValue); } if (!windowGuard) return; timing.finish(); QMetaObject::invokeMethod(windowGuard.data(), [windowGuard, layout, window, root, tabs, activeSessionName, restoreHistory, sessionJsons, viewportAnchors, scrollValues, startupTask]() mutable { StartupDiagnostics::Scope timing("Apply restored window sessions (total)"); if (!windowGuard) return; windowGuard->finishRestoreSessionLayout(layout, window, root, tabs, activeSessionName, restoreHistory, sessionJsons, viewportAnchors, scrollValues); }, Qt::QueuedConnection); }); { QMutexLocker locker(&asyncSessionIoMutex()); asyncSessionIoThreads().append(thread); } QObject::connect(thread, &QThread::finished, thread, [thread]() { unregisterAsyncSessionIoThread(thread); thread->deleteLater(); }); thread->start(); return true; } void MainWindow::finishRestoreSessionLayout(const QJsonObject& layout, const QJsonObject& window, const QJsonObject& root, const QJsonArray& tabs, const QString& activeSessionName, bool restoreHistory, QHash sessionJsons, QHash> viewportAnchors, QHash scrollValues) { StartupDiagnostics::AppearanceContext context("Restore session panes"); StartupDiagnostics::Scope timing("Deserialize saved sessions (total)"); const QJsonArray windows = layout.value(QStringLiteral("windows")).toArray(); const QString rootType = root.value(QStringLiteral("type")).toString(); if (sessionJsons.isEmpty()) { finishStartupSessionRestore(false); return; } QHash restoredSessions; for (auto it = sessionJsons.constBegin(); it != sessionJsons.constEnd(); ++it) { Session* session = new Session(); session->deSerialize(it.value(), false); session->setName(it.key()); restoredSessions.insert(it.key(), session); } timing.next("Rebuild session panes and tabs"); m_sessionViewportAnchors = viewportAnchors; m_sessionScrollValues = scrollValues; QString activeSessionNameToRestore = activeSessionName; Session* activeSession = restoredSessions.value(activeSessionNameToRestore, nullptr); if (activeSession == nullptr) { activeSessionNameToRestore = restoredSessions.keys().constFirst(); activeSession = restoredSessions.value(activeSessionNameToRestore); } const QFont displayFont = m_widgets.display->font(); const QFont editorFont = m_widgets.editor->font(); QWidget* initialPane = paneWidgetForDisplay(m_widgets.display); std::unique_ptr reusablePane( m_widgets.splitContainer->count() == 1 && initialPane == m_widgets.splitContainer->widget(0) ? initialPane : nullptr); ResultDisplay* initialDisplay = reusablePane ? m_widgets.display : nullptr; Editor* initialEditor = reusablePane ? m_widgets.editor : nullptr; QTabBar* initialTabBar = m_paneTabBars.value(initialDisplay, nullptr); if (initialEditor != nullptr) { initialEditor->stopAutoCalc(); initialEditor->stopAutoComplete(); } const QList oldSessions = m_loadedSessions.values(); m_loadedSessions = restoredSessions; m_session = nullptr; m_evaluator = nullptr; m_widgets.display = nullptr; m_widgets.editor = nullptr; m_copyWidget = nullptr; while (m_widgets.splitContainer != nullptr && m_widgets.splitContainer->count() > 0) { QWidget* child = m_widgets.splitContainer->widget(0); child->setParent(nullptr); if (child != reusablePane.get()) delete child; } m_paneSessionNames.clear(); m_paneSessionTabs.clear(); m_paneTabBars.clear(); m_tabBarDisplays.clear(); ResultDisplay* activeDisplay = nullptr; Editor* activeEditor = nullptr; ResultDisplay* firstDisplay = nullptr; Editor* firstEditor = nullptr; const auto paneNamesFromNode = [](const QJsonObject& node) -> QStringList { QStringList names; const QJsonArray paneTabs = node.value(QStringLiteral("tabs")).toArray(); for (const QJsonValue& tabValue : paneTabs) { if (!tabValue.isObject()) continue; const QString name = normalizedSessionName(tabValue.toObject().value(QStringLiteral("name")).toString()); if (!name.isEmpty() && !names.contains(name, Qt::CaseInsensitive)) names.append(name); } const QString activeName = normalizedSessionName(node.value(QStringLiteral("active")).toString()); if (!activeName.isEmpty() && !names.contains(activeName, Qt::CaseInsensitive)) names.prepend(activeName); return names; }; const auto firstLoadedName = [this](const QStringList& names) -> QString { for (const QString& name : names) { if (m_loadedSessions.contains(name)) return name; } return QString(); }; const auto editorStateFromNode = [](const QJsonObject& node, const QString& activeName) -> QJsonObject { const QJsonArray paneTabs = node.value(QStringLiteral("tabs")).toArray(); for (const QJsonValue& tabValue : paneTabs) { if (!tabValue.isObject()) continue; const QJsonObject tab = tabValue.toObject(); const QString tabName = normalizedSessionName(tab.value(QStringLiteral("name")).toString()); if (tabName.compare(activeName, Qt::CaseInsensitive) == 0) return tab.value(QStringLiteral("editor")).toObject(); } return QJsonObject(); }; const auto createPane = [this, &displayFont, &editorFont, &activeSessionNameToRestore, &paneNamesFromNode, &activeDisplay, &activeEditor, &firstDisplay, &firstEditor, &reusablePane, initialDisplay, initialEditor, initialTabBar, &firstLoadedName, &editorStateFromNode](const QJsonObject& node) -> QWidget* { const QStringList names = paneNamesFromNode(node); QStringList loadedNames; for (const QString& name : names) { if (m_loadedSessions.contains(name) && !loadedNames.contains(name, Qt::CaseInsensitive)) loadedNames.append(name); } if (loadedNames.isEmpty()) return nullptr; QString activeName = normalizedSessionName(node.value(QStringLiteral("active")).toString()); if (!m_loadedSessions.contains(activeName)) activeName = firstLoadedName(loadedNames); if (activeName.isEmpty()) return nullptr; if (!loadedNames.contains(activeName, Qt::CaseInsensitive)) loadedNames.prepend(activeName); ResultDisplay* display = nullptr; Editor* editor = nullptr; QWidget* pane = nullptr; if (reusablePane) { StartupDiagnostics::Scope reuseTiming("Reuse initial session pane"); pane = reusablePane.release(); display = initialDisplay; editor = initialEditor; // Keep the existing signal connections and the configured controls. m_paneTabBars.insert(display, initialTabBar); m_tabBarDisplays.insert(initialTabBar, display); } else { display = new ResultDisplay(); display->setFrameStyle(QFrame::NoFrame); display->setFont(displayFont); display->setHoverHighlightEnabled(m_settings->hoverHighlightResults); display->setLoadedSessionCount(1); display->rehighlight(); editor = new Editor(); editor->setFrameStyle(QFrame::NoFrame); editor->setFont(editorFont); editor->setAutoCalcEnabled(m_settings->autoCalc); editor->setAutoCompletionEnabled(m_settings->autoCompletion); editor->rehighlight(); pane = createEditorDisplayPane(display, editor); configureEditorDisplayPane(display, editor); } m_paneSessionNames.insert(display, activeName); m_paneSessionTabs.insert(display, loadedNames); Session* paneSession = m_loadedSessions.value(activeName, nullptr); const QSignalBlocker displaySignals(display); const QSignalBlocker editorSignals(editor); // The final historyChanged signal renders after settings and themes are ready. display->setSession(paneSession, false); if (paneSession != nullptr) editor->setSession(paneSession); restoreEditorState(editor, editorStateFromNode(node, activeName), paneSession != nullptr ? paneSession->editorText() : QString()); if (firstDisplay == nullptr) { firstDisplay = display; firstEditor = editor; } if (activeName == activeSessionNameToRestore) { activeDisplay = display; activeEditor = editor; } return pane; }; const auto restoreSplitterSizes = [](QSplitter* splitter, const QJsonObject& node) { QJsonArray splitSizes = node.value(QStringLiteral("sizes")).toArray(); if (splitSizes.isEmpty()) return; QList sizes; for (const QJsonValue& value : splitSizes) sizes.append(value.toInt()); if (sizes.size() == splitter->count()) splitter->setSizes(sizes); }; const auto restoreNode = [this, &createPane, &restoreSplitterSizes](const QJsonObject& node, const auto& restoreNodeRef) -> QWidget* { const QString type = node.value(QStringLiteral("type")).toString(); if (type == QLatin1String("pane")) return createPane(node); QSplitter* splitter = new QSplitter( node.value(QStringLiteral("orientation")).toString() == QLatin1String("vertical") ? Qt::Vertical : Qt::Horizontal); splitter->setChildrenCollapsible(false); splitter->setHandleWidth(UiConfig::SessionPaneSplitterWidth); splitter->setStyleSheet(m_widgets.splitContainer->styleSheet()); const QJsonArray children = node.value(QStringLiteral("children")).toArray(); for (const QJsonValue& childValue : children) { if (!childValue.isObject()) continue; QWidget* child = restoreNodeRef(childValue.toObject(), restoreNodeRef); if (child != nullptr) splitter->addWidget(child); } restoreSplitterSizes(splitter, node); return splitter; }; if (rootType == QLatin1String("split")) { m_widgets.splitContainer->setOrientation( root.value(QStringLiteral("orientation")).toString() == QLatin1String("vertical") ? Qt::Vertical : Qt::Horizontal); const QJsonArray children = root.value(QStringLiteral("children")).toArray(); for (const QJsonValue& childValue : children) { if (!childValue.isObject()) continue; QWidget* child = restoreNode(childValue.toObject(), restoreNode); if (child != nullptr) m_widgets.splitContainer->addWidget(child); } restoreSplitterSizes(m_widgets.splitContainer, root); } if (m_widgets.splitContainer->count() == 0 || firstDisplay == nullptr) { while (m_widgets.splitContainer->count() > 0) { QWidget* child = m_widgets.splitContainer->widget(0); child->setParent(nullptr); delete child; } m_paneSessionNames.clear(); m_paneSessionTabs.clear(); m_paneTabBars.clear(); m_tabBarDisplays.clear(); activeDisplay = nullptr; activeEditor = nullptr; firstDisplay = nullptr; firstEditor = nullptr; QJsonObject pane; pane.insert(QStringLiteral("type"), QStringLiteral("pane")); pane.insert(QStringLiteral("active"), activeSessionNameToRestore); pane.insert(QStringLiteral("tabs"), tabs); m_widgets.splitContainer->addWidget(createPane(pane)); } m_widgets.display = activeDisplay ? activeDisplay : firstDisplay; m_widgets.editor = activeEditor ? activeEditor : firstEditor; m_copyWidget = m_widgets.editor; updatePaneLoadedSessionCounts(); m_session = nullptr; activateSession(activeSession); // Apply globals to every restored tab after replacing the initial sessions. applyUserDefinitions(); // Rebind retained widgets and docks before releasing the initial session. const QList retainedSessions = restoredSessions.values(); for (Session* oldSession : oldSessions) { if (!retainedSessions.contains(oldSession)) delete oldSession; } m_conditions.autoAns = restoreHistory && !m_session->historyIsEmpty(); updatePaneEditorCursorVisibility(); timing.next("Restore per-window settings and theme"); // Pane rebuilding keeps the docks and keypad restored before session loading. // Reapply selections and geometry after the central layout changes. restoreWindowUiState(window, false); // Existing controls keep their theme. Refresh the new panes below. restoreWindowThemeBackgrounds(); refreshPaneThemes(); emit historyChanged(); emit variablesChanged(); emit functionsChanged(); emit unitsChanged(); restoreVisibleSessionViewports(); const auto viewportTask = StartupDiagnostics::task("Deferred history viewport restoration"); QTimer::singleShot(0, this, [this, viewportTask]() { restoreVisibleSessionViewports(); }); timing.next("Restore additional windows"); if (this == primaryMainWindow() && !g_restoringExtraWindows && !g_multiWindowSpawnDone && windows.size() > 1) { g_multiWindowSpawnDone = true; g_restoringExtraWindows = true; for (int i = 0; i < windows.size(); ++i) { const QJsonValue value = windows.at(i); if (!value.isObject()) continue; const QJsonObject candidate = value.toObject(); if (candidate.value(QStringLiteral("id")).toString() == window.value(QStringLiteral("id")).toString()) continue; QJsonObject singleLayout = layout; singleLayout.insert(QStringLiteral("windows"), QJsonArray({ candidate })); singleLayout.insert(QStringLiteral("activeWindow"), candidate.value(QStringLiteral("id")).toString()); const QString previousLayoutJson = m_settings->sessionLayoutJson; m_settings->sessionLayoutJson = QString::fromUtf8(QJsonDocument(singleLayout).toJson(QJsonDocument::Compact)); MainWindow* extraWindow = new MainWindow(); m_settings->sessionLayoutJson = previousLayoutJson; const QString geometryBase64 = candidate.value(QStringLiteral("geometry")).toString(); extraWindow->showRestoredWindow( QByteArray::fromBase64(geometryBase64.toLatin1())); } g_restoringExtraWindows = false; } finishStartupSessionRestore(true); } void MainWindow::restoreWindowUiState(const QJsonObject& window, bool restoreLayout) { StartupDiagnostics::AppearanceScope timing(restoreLayout ? "Restore window UI state" : "Restore window selections and geometry", this); const QString restoredAngleUnit = window.value(QStringLiteral("statusBarAngleUnit")).toString(); if (restoredAngleUnit.size() == 1 && QByteArray("drgtv").contains(restoredAngleUnit.at(0).toLatin1())) { m_status.selectedAngleUnit = restoredAngleUnit.at(0).toLatin1(); } const QString restoredResultFormat = window.value(QStringLiteral("statusBarResultFormat")).toString(); if (restoredResultFormat.size() == 1 && QByteArray("gnerhobsf").contains(restoredResultFormat.at(0).toLatin1())) { m_status.selectedResultFormat = restoredResultFormat.at(0).toLatin1(); } if (window.contains(QStringLiteral("statusBarResultPrecision"))) { const int restoredPrecision = window.value(QStringLiteral("statusBarResultPrecision")).toInt(-1); if (restoredPrecision >= -1 && restoredPrecision <= 50) m_status.selectedResultPrecision = restoredPrecision; } if (restoreLayout && window.contains(QStringLiteral("statusBarVisible"))) setStatusBarVisible(window.value(QStringLiteral("statusBarVisible")).toBool(true)); else setStatusBarText(); if (QApplication::activeWindow() == this) applyStatusBarSelectionState(); if (restoreLayout) { if (window.value(QStringLiteral("dockColumnOrders")).isObject()) restoreDockColumnOrders(window.value(QStringLiteral("dockColumnOrders")).toObject()); const QString windowStateBase64 = window.value(QStringLiteral("windowState")).toString(); const QByteArray state = windowStateBase64.isEmpty() ? m_settings->windowState : QByteArray::fromBase64(windowStateBase64.toLatin1()); if (window.value(QStringLiteral("openDocks")).isArray()) { QStringList names; for (const QJsonValue& value : window.value(QStringLiteral("openDocks")).toArray()) { if (value.isString()) names.append(value.toString()); } restoreDockLayout(state, names); } else { restoreWindowLayoutState(state); } if (!window.contains(QStringLiteral("openDocks")) && window.contains(QStringLiteral("bitfieldVisible"))) setBitfieldVisible(window.value(QStringLiteral("bitfieldVisible")).toBool(false)); if (window.contains(QStringLiteral("keypadVisible"))) { restoreWindowKeypadLayout( window.value(QStringLiteral("keypadVisible")).toBool(false), window.value(QStringLiteral("keypadMode")).toInt(static_cast(m_keypadMode))); } if (window.contains(QStringLiteral("keypadZoomPercent"))) { restoreWindowKeypadZoom( window.value(QStringLiteral("keypadZoomPercent")).toInt(m_keypadZoomPercent)); } } const QString geometryBase64 = window.value(QStringLiteral("geometry")).toString(); if (!geometryBase64.isEmpty()) restoreWindowGeometry(QByteArray::fromBase64(geometryBase64.toLatin1())); } void MainWindow::restoreWindowGeometry(const QByteArray& geometry) { if (geometry.isEmpty()) return; restoreGeometry(geometry); // Restoring window controls and rebuilding session panes can change size // constraints on later event-loop turns. Reapply the saved geometry once // those layout passes have completed. QTimer::singleShot(0, this, [this, geometry]() { restoreGeometry(geometry); QTimer::singleShot(0, this, [this, geometry]() { restoreGeometry(geometry); }); }); } void MainWindow::showRestoredWindow(const QByteArray& geometry) { // Keep restored secondary windows hidden until their controls and central // layout have settled, so the first visible frame uses the saved layout. QTimer::singleShot(0, this, [this, geometry]() { QTimer::singleShot(0, this, [this, geometry]() { if (!geometry.isEmpty()) restoreGeometry(geometry); const bool preserveStartupFocus = testAttribute(Qt::WA_ShowWithoutActivating); show(); setAttribute(Qt::WA_ShowWithoutActivating, false); if (preserveStartupFocus && primaryMainWindow()) { MainWindow* startupWindow = primaryMainWindow(); QTimer::singleShot(0, startupWindow, [startupWindow]() { if (!startupWindow->m_session || !startupWindow->m_session->isPrivate()) return; startupWindow->raise(); startupWindow->activateWindow(); startupWindow->m_widgets.editor->setFocus(); }); } }); }); } void MainWindow::applyDockCornerLayout() { setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); } QJsonObject MainWindow::dockColumnOrders() const { // Keep unopened docks too. Their widgets may not exist yet on this launch. QJsonObject orders = m_dockColumnOrders; for (QDockWidget* dock : m_allDocks) { const QTreeWidget* table = dock->findChild(); if (!table) continue; const QHeaderView* header = table->header(); QJsonArray order; for (int visual = 0; visual < header->count(); ++visual) order.append(header->logicalIndex(visual)); orders.insert(dock->objectName(), order); } return orders; } void MainWindow::restoreDockColumnOrders(const QJsonObject& orders) { m_dockColumnOrders = orders; for (QDockWidget* dock : m_allDocks) restoreDockColumnOrder(dock); } void MainWindow::restoreDockColumnOrder(QDockWidget* dock) { QTreeWidget* table = dock->findChild(); if (!table) return; QHeaderView* header = table->header(); const QJsonArray order = m_dockColumnOrders.value(dock->objectName()).toArray(); QSet columns; bool valid = order.size() == header->count(); for (const QJsonValue& value : order) { const int column = value.toInt(-1); if (column < 0 || column >= header->count() || columns.contains(column)) { valid = false; break; } columns.insert(column); } // Ignore stale or malformed orders instead of applying a partial layout. for (int visual = 0; visual < header->count(); ++visual) { const int logical = valid ? order.at(visual).toInt() : visual; header->moveSection(header->visualIndex(logical), visual); } } void MainWindow::restoreWindowLayoutState(const QByteArray& state) { bool valid = false; const QStringList names = state.isEmpty() ? QStringList() : legacyOpenDockNames(state, &valid); restoreDockLayout(state, valid ? names : configuredOpenDockNames()); } QStringList MainWindow::openDockNames() const { QStringList names; for (const QDockWidget* dock : m_allDocks) { // A panel behind another tab is open even when it is not exposed. if (!dock->isHidden()) names.append(dock->objectName()); } return names; } QStringList MainWindow::configuredOpenDockNames() const { const bool enabled[] = {m_settings->formulaBookDockVisible, m_settings->constantsDockVisible, m_settings->functionsDockVisible, m_settings->historyDockVisible, m_settings->variablesDockVisible, m_settings->userFunctionsDockVisible, m_settings->userUnitsDockVisible, m_settings->bitfieldVisible}; QStringList names; const QStringList available = allDockNames(); for (int i = 0; i < available.size(); ++i) { if (enabled[i]) names.append(available.at(i)); } return names; } void MainWindow::applyOpenDocks(const QStringList& names) { StartupDiagnostics::Scope timing("Create and configure open docks (total)"); setFormulaBookDockVisible(names.contains(QStringLiteral("BookDock")), false); setConstantsDockVisible(names.contains(QStringLiteral("ConstantsDock")), false); setFunctionsDockVisible(names.contains(QStringLiteral("FunctionsDock")), false); setHistoryDockVisible(names.contains(QStringLiteral("HistoryDock")), false); setVariablesDockVisible(names.contains(QStringLiteral("VariablesDock")), false); setUserFunctionsDockVisible(names.contains(QStringLiteral("UserFunctionsDock")), false); setUserUnitsDockVisible(names.contains(QStringLiteral("UserUnitsDock")), false); setBitfieldVisible(names.contains(QStringLiteral("BitfieldDock"))); syncViewMenuActionState(); } void MainWindow::restoreDockLayout(const QByteArray& state, const QStringList& names) { m_hasRestoredDockLayout = restoreState(state, DockLayoutStateVersion); applyOpenDocks(names); // Reapply the final sizes and selected tabs after adding the required docks. if (m_hasRestoredDockLayout) restoreState(state, DockLayoutStateVersion); for (QDockWidget* dock : m_allDocks) { if (!names.contains(dock->objectName())) dock->hide(); } // Saved layouts include corner ownership. Keep side docks at full height // even when restoring a layout saved with top or bottom corners. applyDockCornerLayout(); syncViewMenuActionState(); if (m_initializingUi && state.isEmpty() && m_docks.constants != nullptr) { QPointer constantsDock(m_docks.constants); QTimer::singleShot(0, this, [this, constantsDock]() { if (constantsDock && !constantsDock->isHidden()) resizeDocks({constantsDock}, {UiConfig::ConstantsDockDefaultWidth}, Qt::Horizontal); }); } } void MainWindow::restoreWindowKeypadLayout(bool visible, int modeValue) { if (modeValue < static_cast(Settings::KeypadModeDisabled) || modeValue > static_cast(Settings::KeypadModeCustom)) { modeValue = static_cast(m_keypadMode); } Settings::KeypadMode mode = static_cast(modeValue); if (mode == Settings::KeypadModeBasicNarrow) mode = Settings::KeypadModeBasicWide; if (!visible || !isVisibleKeypadMode(mode)) mode = Settings::KeypadModeDisabled; if (m_keypadMode != mode && m_widgets.keypad != nullptr) deleteKeypad(isVisible()); m_keypadMode = mode; setKeypadVisible(isVisibleKeypadMode(mode)); updateKeypadModeActionState(); } void MainWindow::restoreWindowKeypadZoom(int zoomPercent) { if (zoomPercent != 50 && zoomPercent != 100 && zoomPercent != 150 && zoomPercent != 200) return; if (m_keypadZoomPercent == zoomPercent) return; m_keypadZoomPercent = zoomPercent; if (m_widgets.keypad != nullptr) { deleteKeypad(isVisible()); createKeypad(); } } void MainWindow::evaluateEditorExpression() { const bool startedFromHistoryEdit = (m_pendingHistoryEditIndex >= 0); const QString enteredExpr = m_widgets.editor->text(); QString expr = m_evaluator->autoFix(enteredExpr); const bool isCommentOnly = Evaluator::isCommentOnlyExpression(expr); if (expr.isEmpty()) return; if (m_pendingHistoryEditIndex >= 0) { const int previousDisplayScrollValue = m_widgets.display->verticalScrollBar()->value(); const auto restoreDisplayScroll = [this, previousDisplayScrollValue]() { QScrollBar* bar = m_widgets.display->verticalScrollBar(); const int clamped = qBound(bar->minimum(), previousDisplayScrollValue, bar->maximum()); bar->setValue(clamped); QTimer::singleShot(0, this, [this, previousDisplayScrollValue]() { QScrollBar* deferredBar = m_widgets.display->verticalScrollBar(); const int deferredClamped = qBound(deferredBar->minimum(), previousDisplayScrollValue, deferredBar->maximum()); deferredBar->setValue(deferredClamped); }); }; const int historySize = m_session->historySize(); if (m_pendingHistoryEditIndex >= historySize) { m_pendingHistoryEditIndex = -1; m_widgets.display->setEditingHistoryIndex(-1); m_widgets.editor->setHistoryArrowNavigationEnabled(true); m_widgets.editor->clear(); restoreDisplayScroll(); } else { const QList previousEntries = historyEntries(); QList updatedEntries = previousEntries; HistoryEntry updatedEntry = updatedEntries.at(m_pendingHistoryEditIndex); updatedEntry.setExpr(enteredExpr); updatedEntries[m_pendingHistoryEditIndex] = updatedEntry; int errorIndex = -1; QString errorText; if (!rebuildSessionFromEntries(updatedEntries, m_pendingHistoryEditIndex, &errorIndex, &errorText)) { m_widgets.display->setEditingHistoryIndex(m_pendingHistoryEditIndex); restoreDisplayScroll(); showStateLabel(tr("Could not recalculate from calculation %1: %2").arg(errorIndex + 1).arg(errorText)); return; } m_pendingHistoryEditIndex = -1; m_widgets.display->setEditingHistoryIndex(-1); m_widgets.editor->setHistoryArrowNavigationEnabled(true); emit historyChanged(); emit variablesChanged(); emit functionsChanged(); emit unitsChanged(); restoreDisplayScroll(); m_widgets.editor->clear(); m_widgets.editor->stopAutoCalc(); m_widgets.editor->stopAutoComplete(); saveSessionToDefaultPath(); return; } } const EvaluationContext evalContext = currentEvaluationContext(m_settings); m_evaluator->setExpression(expr); Quantity result = m_evaluator->evalUpdateAns(); if (!m_evaluator->error().isEmpty()) { showStateLabel(m_evaluator->error()); return; } if (m_evaluator->isUserFunctionAssign()) { result = CMath::nan(); if (m_bulkEvaluationInProgress) m_bulkFunctionsChanged = true; else emit functionsChanged(); } else if (m_evaluator->isUserUnitAssign()) { result = CMath::nan(); if (m_bulkEvaluationInProgress) m_bulkUnitsChanged = true; else emit unitsChanged(); } else if (result.isNan() && !isCommentOnly) return; const QString interpretedExpr = m_evaluator->interpretedExpression(); const bool warnHistoryLimitReached = m_session->nextHistoryEntryReachesLimit(); HistoryEntry historyEntry(enteredExpr, result, interpretedExpr, evalContext); historyEntry.setRenderedLines(renderedLinesForHistoryEntry(historyEntry, m_settings, m_evaluator)); m_session->addHistoryEntry(historyEntry); const bool userVariableAssign = m_evaluator->isUserVariableAssign(); if (m_bulkEvaluationInProgress) m_bulkHistoryChanged = true; else emit historyChanged(); if (!startedFromHistoryEdit) m_widgets.display->verticalScrollBar()->setValue(m_widgets.display->verticalScrollBar()->maximum()); if (userVariableAssign) { if (m_bulkEvaluationInProgress) m_bulkVariablesChanged = true; else emit variablesChanged(); } if (m_evaluator->isUserUnitAssign()) { if (m_bulkEvaluationInProgress) m_bulkUnitsChanged = true; else emit unitsChanged(); } if (m_widgets.bitField && m_docks.bitField && !m_docks.bitField->isHidden()) m_widgets.bitField->updateBits(result); if (m_settings->autoResultToClipboard) copyResultToClipboard(); if (m_settings->leaveLastExpression) m_widgets.editor->selectAll(); else m_widgets.editor->clear(); m_widgets.editor->stopAutoCalc(); m_widgets.editor->stopAutoComplete(); if (!result.isNan()) m_conditions.autoAns = true; if (warnHistoryLimitReached) { QTimer::singleShot(0, this, [this]() { QMessageBox::information( this, tr("History Size Limit Reached"), tr("This calculation fills the last available history slot. " "Future calculations will remove the oldest calculation from history. " "You can increase the limit from Session > History Size Limit.")); }); } if (m_bulkEvaluationInProgress) m_sessionSavePending = true; else saveSessionToDefaultPath(); } void MainWindow::startHistoryEntryEdit(int index) { const int historySize = m_session->historySize(); if (index < 0 || index >= historySize) return; m_pendingHistoryEditIndex = index; m_widgets.display->setEditingHistoryIndex(index); m_widgets.editor->setHistoryArrowNavigationEnabled(false); m_widgets.editor->setText(Editor::historyExpressionForInput(m_session->historyEntryAt(index).expr())); m_widgets.editor->setFocus(); m_widgets.editor->setCursorPosition(m_widgets.editor->text().size()); showStateLabel(tr("Editing calculation. Press Esc twice to cancel.")); } void MainWindow::handleBulkEvaluationStarted() { m_bulkEvaluationInProgress = true; m_bulkHistoryChanged = false; m_bulkVariablesChanged = false; m_bulkFunctionsChanged = false; m_bulkUnitsChanged = false; } void MainWindow::handleBulkEvaluationFinished() { m_bulkEvaluationInProgress = false; if (m_bulkHistoryChanged) emit historyChanged(); if (m_bulkVariablesChanged) emit variablesChanged(); if (m_bulkFunctionsChanged) emit functionsChanged(); if (m_bulkUnitsChanged) emit unitsChanged(); if (m_bulkHistoryChanged && m_widgets.display) m_widgets.display->verticalScrollBar()->setValue(m_widgets.display->verticalScrollBar()->maximum()); if (m_bulkHistoryChanged || m_bulkVariablesChanged || m_bulkFunctionsChanged || m_bulkUnitsChanged || m_sessionSavePending) saveSessionToDefaultPath(); } void MainWindow::editHistoryEntryContext(int index) { const int historySize = m_session->historySize(); if (index < 0 || index >= historySize) return; HistoryEntry entry = m_session->historyEntryAt(index); EvaluationContext ctx = entry.context(); ResultSlotsDialog dialog(tr("Calculation Settings"), ctx, this); if (dialog.exec() != QDialog::Accepted) return; ctx = dialog.evaluationContext(ctx); const int previousDisplayScrollValue = m_widgets.display->verticalScrollBar()->value(); const QList previousEntries = historyEntries(); QList updatedEntries = previousEntries; HistoryEntry updatedEntry = updatedEntries.at(index); updatedEntry.setContext(ctx); updatedEntries[index] = updatedEntry; int errorIndex = -1; QString errorText; if (!rebuildSessionFromEntries(updatedEntries, index, &errorIndex, &errorText)) { QScrollBar* bar = m_widgets.display->verticalScrollBar(); bar->setValue(qBound(bar->minimum(), previousDisplayScrollValue, bar->maximum())); showStateLabel(tr("Could not recalculate from calculation %1: %2").arg(errorIndex + 1).arg(errorText)); return; } emit historyChanged(); emit variablesChanged(); emit functionsChanged(); emit unitsChanged(); QScrollBar* bar = m_widgets.display->verticalScrollBar(); const int clamped = qBound(bar->minimum(), previousDisplayScrollValue, bar->maximum()); bar->setValue(clamped); QTimer::singleShot(0, this, [this, previousDisplayScrollValue]() { QScrollBar* deferredBar = m_widgets.display->verticalScrollBar(); const int deferredClamped = qBound(deferredBar->minimum(), previousDisplayScrollValue, deferredBar->maximum()); deferredBar->setValue(deferredClamped); }); saveSessionToDefaultPath(); } void MainWindow::cancelHistoryEntryEdit() { if (m_pendingHistoryEditIndex < 0) return; const int previousDisplayScrollValue = m_widgets.display->verticalScrollBar()->value(); m_pendingHistoryEditIndex = -1; m_widgets.display->setEditingHistoryIndex(-1); m_widgets.editor->setHistoryArrowNavigationEnabled(true); m_widgets.display->verticalScrollBar()->setValue(previousDisplayScrollValue); m_widgets.editor->clear(); hideStateLabel(); } QList MainWindow::historyEntries() const { QList entries; const int historySize = m_session->historySize(); entries.reserve(historySize); for (int i = 0; i < historySize; ++i) entries.append(m_session->historyEntryAtRef(i)); return entries; } bool MainWindow::rebuildSessionFromEntries(const QList& entries, int startIndex, int* errorIndex, QString* errorText) { if (errorIndex) *errorIndex = -1; if (errorText) *errorText = QString(); if (startIndex < 0 || startIndex > entries.size()) { if (errorText) *errorText = tr("Invalid recalculation start index"); return false; } const Session previousSessionState = *m_session; const bool previousAutoAns = m_conditions.autoAns; if (startIndex == 0) { bool hasBaselineAns = false; Quantity baselineAnsValue = CMath::nan(); const bool hadPreviousAns = m_evaluator->hasVariable(QStringLiteral("ans")); if (hadPreviousAns) { const Variable previousAnsVariable = m_evaluator->getVariable(QStringLiteral("ans")); baselineAnsValue = previousAnsVariable.value(); hasBaselineAns = !baselineAnsValue.isNan(); } if (!hasBaselineAns) { for (int i = previousSessionState.historySize() - 1; i >= 0; --i) { const Quantity candidate = previousSessionState.historyEntryAtRef(i).result(); if (!candidate.isNan()) { baselineAnsValue = candidate; hasBaselineAns = true; break; } } } m_session->clearHistory(); m_session->clearVariables(); m_session->clearUserFunctions(); m_evaluator->initializeBuiltInVariables(); if (hasBaselineAns) { m_evaluator->setVariable( QStringLiteral("ans"), baselineAnsValue, Variable::BuiltIn); } m_conditions.autoAns = false; } else { while (m_session->historySize() > startIndex) m_session->removeHistoryEntryAt(m_session->historySize() - 1); } const EvaluationContext originalContext = currentEvaluationContext(m_settings); for (int i = startIndex; i < entries.size(); ++i) { const HistoryEntry entry = entries.at(i); const QString currentExpr = entry.expr(); applyEvaluationContext(m_settings, entry.contextRef()); const QString evalExpr = m_evaluator->autoFix(currentExpr); const bool isCommentOnly = Evaluator::isCommentOnlyExpression(evalExpr); m_evaluator->setExpression(evalExpr); Quantity result = m_evaluator->evalUpdateAns(); if (!m_evaluator->error().isEmpty()) { if (errorIndex) *errorIndex = i; if (errorText) *errorText = m_evaluator->error(); applyEvaluationContext(m_settings, originalContext); *m_session = previousSessionState; m_conditions.autoAns = previousAutoAns; return false; } if (m_evaluator->isUserFunctionAssign()) result = CMath::nan(); else if (result.isNan() && !isCommentOnly) continue; const QString interpretedExpr = m_evaluator->interpretedExpression(); HistoryEntry rebuiltEntry(currentExpr, result, interpretedExpr, entry.contextRef()); rebuiltEntry.setEditTimestamp(entry.editTimestamp()); rebuiltEntry.setRenderedLines(renderedLinesForHistoryEntry(rebuiltEntry, m_settings, m_evaluator)); m_session->addHistoryEntry(rebuiltEntry); } applyEvaluationContext(m_settings, originalContext); const bool hasAns = m_evaluator->hasVariable(QStringLiteral("ans")); m_conditions.autoAns = hasAns && !m_evaluator->getVariable(QStringLiteral("ans")).value().isNan(); return true; } void MainWindow::removeHistoryEntryAt(int index) { const int historySize = m_session->historySize(); if (index < 0 || index >= historySize) return; m_session->removeHistoryEntryAt(index); if (m_pendingHistoryEditIndex == index) m_pendingHistoryEditIndex = -1; else if (m_pendingHistoryEditIndex > index) --m_pendingHistoryEditIndex; m_widgets.display->setEditingHistoryIndex(m_pendingHistoryEditIndex); m_widgets.editor->setHistoryArrowNavigationEnabled(m_pendingHistoryEditIndex < 0); m_conditions.autoAns = !m_session->historyIsEmpty(); emit historyChanged(); saveSessionToDefaultPath(); } void MainWindow::removeHistoryEntriesAbove(int index) { const int historySize = m_session->historySize(); if (historySize == 0 || index <= 0 || index >= historySize) return; for (int i = 0; i < index; ++i) m_session->removeHistoryEntryAt(0); if (m_pendingHistoryEditIndex >= 0) { if (m_pendingHistoryEditIndex < index) m_pendingHistoryEditIndex = -1; else m_pendingHistoryEditIndex -= index; } m_widgets.display->setEditingHistoryIndex(m_pendingHistoryEditIndex); m_widgets.editor->setHistoryArrowNavigationEnabled(m_pendingHistoryEditIndex < 0); m_conditions.autoAns = !m_session->historyIsEmpty(); emit historyChanged(); saveSessionToDefaultPath(); } void MainWindow::removeHistoryEntriesBelow(int index) { const int historySize = m_session->historySize(); if (historySize == 0 || index < 0 || index >= historySize - 1) return; for (int i = historySize - 1; i > index; --i) m_session->removeHistoryEntryAt(i); if (m_pendingHistoryEditIndex > index) m_pendingHistoryEditIndex = -1; m_widgets.display->setEditingHistoryIndex(m_pendingHistoryEditIndex); m_widgets.editor->setHistoryArrowNavigationEnabled(m_pendingHistoryEditIndex < 0); m_conditions.autoAns = !m_session->historyIsEmpty(); emit historyChanged(); saveSessionToDefaultPath(); } void MainWindow::clearTextEditSelection(QPlainTextEdit* edit) { QTextCursor cursor = edit->textCursor(); if (cursor.hasSelection()) { cursor.clearSelection(); edit->setTextCursor(cursor); } } void MainWindow::handleManualClosed() { disconnect(m_widgets.manual); m_settings->manualWindowGeometry = m_settings->windowPositionSave ? m_widgets.manual->saveGeometry() : QByteArray(); m_widgets.manual->deleteLater(); m_widgets.manual = 0; } void MainWindow::handleDisplaySelectionChange() { const QTextCursor displayCursor = m_widgets.display->textCursor(); if (displayCursor.hasSelection()) { clearTextEditSelection(m_widgets.editor); const QString rawSelected = displayCursor.selectedText(); if (rawSelected.contains(RegExpPatterns::lineBreak())) { m_widgets.editor->autoCalcSelection(rawSelected); return; } const QString selected = normalizedDisplaySelectionForEvaluation(rawSelected); m_widgets.editor->autoCalcSelection(selected); return; } hideStateLabel(); } void MainWindow::handleEditorSelectionChange() { if (m_widgets.editor->textCursor().hasSelection()) { clearTextEditSelection(m_widgets.display); return; } if (m_widgets.editor->text().trimmed().isEmpty()) hideStateLabel(); } void MainWindow::handleCopyAvailable(bool copyAvailable) { QPlainTextEdit* const textEdit = static_cast(sender()); if (copyAvailable && textEdit) m_copyWidget = textEdit; syncEditMenuActionState(); } void MainWindow::handleBitsChanged(const QString& str) { Quantity num(CNumber(str.toLatin1().data())); auto result = DMath::format(num, Quantity::Format::Fixed() + Quantity::Format::Hexadecimal()); insertTextIntoEditor(result); showStateLabel(QString("Current value: %1").arg(NumberFormatter::format(num))); auto cursor = m_widgets.editor->textCursor(); if (cursor.hasSelection()) cursor.removeSelectedText(); cursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, result.length()); cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, result.length()); m_widgets.editor->setTextCursor(cursor); } void MainWindow::handleEditorTextChange() { m_currentResultPreviewDismissed = false; captureEditorTextInCurrentSession(); m_widgets.display->clearHoverFeedback(); clearTextEditSelection(m_widgets.display); if (m_widgets.editor->text().trimmed().isEmpty()) { hideStateLabel(); if (m_widgets.bitField) m_widgets.bitField->clear(); return; } if (m_conditions.autoAns && m_settings->autoAns) { QString expr = m_evaluator->autoFix(m_widgets.editor->text()); if (expr.isEmpty()) return; Tokens tokens = m_evaluator->scan(expr); if (tokens.count() == 1) { const auto mode = EditorUtils::autoAnsRewriteModeForLeadingOperator(tokens.at(0).text()); if (mode != EditorUtils::AutoAnsNoRewrite) { m_conditions.autoAns = false; expr = EditorUtils::applyAutoAnsRewrite(expr, mode); m_widgets.editor->setText(expr); m_widgets.editor->setCursorPosition(expr.length()); } } } } void MainWindow::handleDockWidgetVisibilityChanged(bool visible) { QDockWidget* dock = qobject_cast(sender()); if (!dock) return; // Pass the focus back to the editor if the dock that is being hidden has the focus. QWidget* focusWidget = dock->focusWidget(); if (focusWidget && !visible && focusWidget->hasFocus()) m_widgets.editor->setFocus(); if (activeMainWindowForMenuAction(nullptr) == this) syncViewMenuActionState(); if (m_dockVisibilityRefreshPending) return; m_dockVisibilityRefreshPending = true; QTimer::singleShot(0, this, [this]() { // Changes during the refresh can schedule another pass. m_dockVisibilityRefreshPending = false; StartupDiagnostics::AppearanceContext context("Deferred dock visibility refresh"); StartupDiagnostics::AppearanceScope timing("Refresh deferred dock visibility appearance", this); updateSplitterStyleSheet(); applyDockTabBarAppearance(); }); } void MainWindow::insertVariableIntoEditor(const QString& v) { insertTextIntoEditor(v); } void MainWindow::insertUserFunctionIntoEditor(const QString& v) { insertTextIntoEditor(v); } void MainWindow::insertUserUnitIntoEditor(const QString& v) { insertTextIntoEditor(v); } void MainWindow::setRadixCharacterAutomatic() { setRadixCharacter(0); } void MainWindow::setRadixCharacterDot() { setRadixCharacter(MathDsl::DotSep.toLatin1()); } void MainWindow::setRadixCharacterComma() { setRadixCharacter(MathDsl::CommaSep.toLatin1()); } void MainWindow::setRadixCharacterBoth() { setRadixCharacter(MathDsl::MulOpAl1.toLatin1()); } void MainWindow::closeEvent(QCloseEvent* e) { if (primaryMainWindow() == this) { const bool shutdownAlreadyInProgress = applicationShutdownInProgress(); if (!shutdownAlreadyInProgress) { // Mark shutdown before saving/restoring layouts so child close events // caused by QApplication::quit() do not rewrite the multi-window layout // as if each child had been closed manually. qApp->setProperty("speedcrunchShutdownInProgress", true); appShutdownInProgress() = true; } persistSessionAndSettingsForShutdown(); if (!shutdownAlreadyInProgress) qApp->quit(); } else { if (!applicationShutdownInProgress()) { allMainWindows().removeAll(QPointer(this)); updatePaneEditorCursorVisibility(); saveSessionLayout(false); } } e->accept(); } void MainWindow::resizeEvent(QResizeEvent* event) { QMainWindow::resizeEvent(event); updateStatusBarSectionVisibility(); if (m_widgets.state->isVisible()) showStateLabel(m_widgets.state->text()); } void MainWindow::persistSessionAndSettingsForShutdown() { if (m_shutdownStateSaved) return; m_shutdownStateSaved = true; if (m_sessionSavePending) flushPendingSessionSave(); if (m_widgets.manual) m_settings->manualWindowGeometry = m_settings->windowPositionSave ? m_widgets.manual->saveGeometry() : QByteArray(); ensureSessionsPath(); QSet savedSessions; // Shutdown has to persist every restored window, not just the primary one. // Saving by Session* avoids duplicate writes when a session is referenced // by more than one pane or window during layout transitions. for (const QPointer& ptr : allMainWindows()) { MainWindow* window = ptr.data(); if (window == nullptr) continue; window->captureEditorTextInCurrentSession(); for (auto it = window->m_loadedSessions.constBegin(); it != window->m_loadedSessions.constEnd(); ++it) { Session* session = it.value(); if (session == nullptr || savedSessions.contains(session)) continue; savedSessions.insert(session); saveSessionAsync(*session, sessionFilePath(it.key())); } } waitForAsyncSessionIo(); saveSessionLayout(); saveSettings(); } void MainWindow::saveSessionToDefaultPath() { if (m_session == nullptr || m_session->isPrivate()) return; m_sessionSavePending = true; m_deferredSessionSaveTimer->start(); } void MainWindow::flushPendingSessionSave() { if (!m_sessionSavePending) return; m_sessionSavePending = false; if (m_session == nullptr || m_session->isPrivate()) return; ensureSessionsPath(); captureEditorTextInCurrentSession(); const QString sessionName = m_session->name().isEmpty() ? QLatin1String(SessionJsonKeys::SessionValueMain) : m_session->name(); QString dataPath = sessionFilePath(sessionName); saveSessionAsync(*m_session, dataPath); } void MainWindow::setResultPrecision(int p) { if (m_settings->resultPrecision == p && m_status.selectedResultPrecision == p) return; m_settings->resultPrecision = p; m_status.selectedResultPrecision = p; setStatusBarText(); syncStatusBarSelectionMenuActionState(); emit resultPrecisionChanged(); } void MainWindow::setResultFormat(char c) { if (m_settings->resultFormat == c && m_status.selectedResultFormat == c) return; m_settings->resultFormat = c; m_status.selectedResultFormat = c; setStatusBarText(); syncStatusBarSelectionMenuActionState(); emit resultFormatChanged(); } void MainWindow::setUnitNegativeExponentStyle(QAction* action) { const Settings::UnitNegativeExponentStyle style = static_cast(action->data().toInt()); if (style != Settings::UnitNegativeExponentSuperscript && style != Settings::UnitNegativeExponentFraction) { return; } if (m_settings->unitNegativeExponentStyle == style) return; m_settings->unitNegativeExponentStyle = style; setRuntimeUnitNegativeExponentStyle(style); // Unit exponent style changes should affect only future evaluations and // live editor previews, not previously displayed history entries. m_widgets.editor->refreshAutoCalc(); } void MainWindow::setRemoveTrailingZeroesEnabled(bool enabled) { m_settings->removeTrailingZeroes = enabled; QList> windows = allMainWindows(); if (!windows.contains(QPointer(this))) windows.append(QPointer(this)); for (const QPointer& window : windows) { if (!window) continue; const QSignalBlocker blocker(window->m_actions.settingsRemoveTrailingZeroes); window->m_actions.settingsRemoveTrailingZeroes->setChecked(enabled); for (Editor* editor : window->findChildren()) editor->refreshAutoCalc(); } } void MainWindow::setResultRoundingMode(QAction* action) { const Settings::ResultRoundingMode mode = static_cast(action->data().toInt()); if (mode != Settings::ResultRoundingHalfAwayFromZero && mode != Settings::ResultRoundingHalfEven && mode != Settings::ResultRoundingTowardZero && mode != Settings::ResultRoundingTowardPositiveInfinity && mode != Settings::ResultRoundingTowardNegativeInfinity) { return; } if (m_settings->resultRoundingMode == mode) return; m_settings->resultRoundingMode = mode; setRuntimeResultRoundingMode(mode); emit resultRoundingModeChanged(); } void MainWindow::setRadixCharacter(char c) { m_settings->setRadixCharacter(c); emit radixCharacterChanged(); } void MainWindow::showNumberFormatDialog() { NumberFormatDialog dialog(this); dialog.setSelection(m_settings->numberFormatStyle); if (dialog.exec() != QDialog::Accepted) return; const Settings::NumberFormatStyle selectedStyle = dialog.selectedStyle(); if (m_settings->numberFormatStyle == selectedStyle) return; m_settings->numberFormatStyle = selectedStyle; m_settings->applyNumberFormatStyle(); // Number format changes from this dialog should not rewrite previous // history entries in Result Display. Only refresh live editor previews. for (const QPointer& window : allMainWindows()) { if (!window) continue; emit window->syntaxHighlightingChanged(); for (Editor* editor : window->findChildren()) editor->refreshAutoCalc(); } } void MainWindow::showResultSlotsDialog() { ResultSlotsDialog dialog(this); connect(&dialog, &ResultSlotsDialog::settingsApplied, this, [this]() { DMath::complexMode = m_settings->complexNumbers; if (m_settings->complexNumbers) m_evaluator->initializeBuiltInVariables(); m_status.selectedResultFormat = m_settings->resultFormat; m_status.selectedResultPrecision = m_settings->resultPrecision; setStatusBarText(); syncStatusBarSelectionMenuActionState(); for (const QPointer& ptr : allMainWindows()) { MainWindow* window = ptr.data(); if (window == nullptr) continue; for (Editor* editor : window->splitPaneEditors()) editor->refreshAutoCalc(); } }); dialog.exec(); } void MainWindow::increaseDisplayFontPointSize() { if (m_widgets.display == nullptr) return; m_widgets.display->increaseFontPointSize(); setDisplayFont(m_widgets.display->font()); } void MainWindow::decreaseDisplayFontPointSize() { if (m_widgets.display == nullptr) return; m_widgets.display->decreaseFontPointSize(); setDisplayFont(m_widgets.display->font()); } void MainWindow::showLanguageChooserDialog() { QMap map; // List all available translations from the resource files QDir localeDir(":/locale/", "*.qm"); QFileInfoList localeList = localeDir.entryInfoList(); for (int i = 0; i < localeList.size(); ++i) { QFileInfo fileInfo = localeList.at(i); QString localeName = fileInfo.baseName(); QString langName = QLocale(localeName).nativeLanguageName(); // Kludges for region-specific translations if(localeName == "es") langName = QString::fromUtf8("Español (Latinoamérica)"); if(localeName == "es_ES") langName = QString::fromUtf8("Español (España)"); if(localeName == "pt_BR") langName = QString::fromUtf8("Português (Brasil)"); if(localeName == "pt_PT") langName = QString::fromUtf8("Português (Portugal)"); // The first letter is not always capitalized so force it langName[0] = langName[0].toUpper(); map.insert(langName, localeName); } const auto values = map.values(); int current = values.indexOf(m_settings->language) + 1; QString defaultKey = tr("System Default"); QStringList keys(QStringList() << defaultKey << map.keys()); bool ok; QString langName = QInputDialog::getItem(this, tr("Language"), tr("Select the language:"), keys, current, false, &ok); if (ok && !langName.isEmpty()) { QString value = (langName == defaultKey) ? QLatin1String("C") : map.value(langName); if (m_settings->language != value) { m_settings->language = value; emit languageChanged(); } } } void MainWindow::showResultFormatContextMenu(const QPoint& point) { m_menus.resultFormat->popup(m_status.resultFormat->mapToGlobal(point)); } void MainWindow::showPrecisionContextMenu(const QPoint& point) { QMenu menu(this); QActionGroup modeGroup(&menu); modeGroup.setExclusive(true); QAction* automaticAction = menu.addAction(MainWindow::tr("Automatic")); automaticAction->setCheckable(true); automaticAction->setChecked(m_settings->resultPrecision < 0); modeGroup.addAction(automaticAction); connect(automaticAction, &QAction::triggered, this, [this]() { setResultPrecision(-1); }); QAction* customAction = menu.addAction(MainWindow::tr("Custom")); customAction->setCheckable(true); customAction->setChecked(m_settings->resultPrecision >= 0); modeGroup.addAction(customAction); menu.addSeparator(); QWidget* precisionEditor = new QWidget(&menu); QHBoxLayout* precisionLayout = new QHBoxLayout(precisionEditor); precisionLayout->setContentsMargins(8, 4, 8, 4); precisionLayout->setSpacing(6); QLabel* precisionLabel = new QLabel(MainWindow::tr("Decimal places:"), precisionEditor); MenuPrecisionSpinBox* precisionSpin = new MenuPrecisionSpinBox(precisionEditor); precisionSpin->setRange(0, 50); precisionSpin->setValue(m_settings->resultPrecision < 0 ? 8 : m_settings->resultPrecision); precisionSpin->setEnabled(m_settings->resultPrecision >= 0); connect(precisionSpin, QOverload::of(&QSpinBox::valueChanged), this, [this](int value) { setResultPrecision(value); }); connect(precisionSpin, QOverload::of(&QSpinBox::valueChanged), customAction, [customAction](int) { customAction->setChecked(true); }); connect(customAction, &QAction::triggered, this, [this, precisionSpin]() { setResultPrecision(precisionSpin->value()); }); connect(automaticAction, &QAction::toggled, precisionSpin, [precisionSpin](bool automatic) { precisionSpin->setEnabled(!automatic); }); precisionLayout->addWidget(precisionLabel); precisionLayout->addWidget(precisionSpin); QWidgetAction* editorAction = new QWidgetAction(&menu); editorAction->setDefaultWidget(precisionEditor); menu.addAction(editorAction); const auto updateAppearance = [this, &menu, precisionEditor, precisionLabel, precisionSpin]() { MenuStyle::apply(&menu); precisionEditor->setPalette(menu.palette()); precisionLabel->setPalette(menu.palette()); if (m_settings->menuAppearance == Settings::MenuAppearanceSpeedCrunch) precisionSpin->setThemeSurface(generatedSurfaceColors(m_settings).inputs); else precisionSpin->setSystemAppearance(); }; connect(this, &MainWindow::menuAppearanceChanged, &menu, updateAppearance); connect(this, &MainWindow::colorSchemeChanged, &menu, updateAppearance); updateAppearance(); menu.exec(m_status.resultPrecision->mapToGlobal(point)); } void MainWindow::showKeypadContextMenu(const QPoint& point) { if (!m_widgets.keypad) return; QMenu menu(this); menu.addActions(m_menus.keypad->actions()); menu.addSeparator(); menu.addMenu(m_menus.keypadZoom); MenuStyle::apply(&menu); menu.exec(m_widgets.keypad->mapToGlobal(point)); } heldercorreia-speedcrunch-e7ca37f/src/gui/mainwindow.h000066400000000000000000000714441526573132500232470ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2012-2018, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_MAINWINDOW_H #define GUI_MAINWINDOW_H #include "core/settings.h" #include "gui/keypad.h" #include "math/quantity.h" #include #include #include #include #include #include #include class AutoHideLabel; class BitFieldWidget; template class GenericDock; class BookDock; class Constants; class ConstantsWidget; class Editor; class Evaluator; class HistoryEntry; class UserFunction; class FunctionRepo; class FunctionsWidget; class HistoryWidget; class ManualWindow; class ManualServer; class ResultDisplay; class Session; class UserFunctionListWidget; class UserUnitListWidget; class Variable; class VariableListWidget; #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS class VersionCheck; #endif class QAbstractItemView; class QActionGroup; class QDockWidget; class QHBoxLayout; class QLabel; class QPlainTextEdit; class QPushButton; class QResizeEvent; class QSplitter; class QTabBar; class QTimer; class QTranslator; class QVBoxLayout; class MainWindow : public QMainWindow { Q_OBJECT public: static void initializeApplicationStyle(); explicit MainWindow(bool restorePreviousSession = true); ~MainWindow(); void persistSessionAndSettingsForShutdown(); signals: void angleUnitChanged(); void complexNumbersChanged(); void colorSchemeChanged(); void menuAppearanceChanged(); void languageChanged(); void radixCharacterChanged(); void resultFormatChanged(); void resultPrecisionChanged(); void resultRoundingModeChanged(); void syntaxHighlightingChanged(); void historyChanged(); void variablesChanged(); void functionsChanged(); void unitsChanged(); public slots: void copy(); private slots: void clearEditor(); void clearEditorAndBitfield(); void clearHistory(); void clearSession(); void resetAllSettings(); void copyResultToClipboard(); void decreaseDisplayFontPointSize(); void decreaseOpacity(); void deleteVariables(); void deleteUserFunctions(); void evaluateEditorExpression(); void handleBulkEvaluationStarted(); void handleBulkEvaluationFinished(); void handleApplicationFocusChanged(QWidget* previous, QWidget* focused); void cancelHistoryEntryEdit(); void exportJson(); void exportHtml(); void exportPlainText(); void handleAutoCalcMessageAvailable(const QString&); void handleAutoCalcQuantityAvailable(const Quantity&); void handleCopyAvailable(bool copyAvailable); void handleBitsChanged(const QString&); void handleKeypadButtonPress(Keypad::Button); void handleEditorTextChange(); void handleEditorEscapePressed(); void showNewSessionDialog(); void showNewPrivateSession(); void convertSessionPrivacy(); void showNewSessionWindow(); void showOpenSessionDialog(); void showDuplicateSessionDialog(); void showRenameSessionDialog(); void closeCurrentSession(); void restoreClosedSessionTab(); void restoreWindowGeometry(const QByteArray& geometry); void restoreWindowLayoutState(const QByteArray& state); void restoreWindowKeypadLayout(bool visible, int mode); void restoreWindowKeypadZoom(int zoomPercent); void restoreWindowUiState(const QJsonObject& window, bool restoreLayout = true); void showRestoredWindow(const QByteArray& geometry); void cycleFocusForward(); void cycleFocusBackward(); void closeCurrentPane(); void deleteCurrentSession(); void splitActivePaneLeft(); void splitActivePaneRight(); void splitActivePaneUp(); void splitActivePaneDown(); void activateNextChild(); void activatePreviousChild(); void showLoadedSessionsMenu(const QPoint& globalPos); void handleCustomKeypadButtonPress(int action, const QString& text); void handleDisplaySelectionChange(); void handleEditorSelectionChange(); void handleManualClosed(); void handleDockWidgetVisibilityChanged(bool visible); void hideStateLabel(); void increaseDisplayFontPointSize(); void increaseOpacity(); void insertConstantIntoEditor(const QString&); void insertFunctionIntoEditor(const QString&); void insertTextIntoEditor(const QString&); void insertHistoryExpressionIntoEditor(const QString&); void insertVariableIntoEditor(const QString&); void insertUserFunctionIntoEditor(const QString&); void insertUserUnitIntoEditor(const QString&); #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS void checkForUpdates(); #endif void openFeedbackURL(); void openCommunityURL(); void openSourceURL(); void openDonateURL(); void retranslateText(); void selectEditorExpression(); void setAlwaysOnTopEnabled(bool); void setAngleModeDegree(); void setAngleModeRadian(); void setAngleModeGradian(); void setAngleModeTurn(); void setAngleModeRevolution(); void setAutoAnsEnabled(bool); void setAutoCalcEnabled(bool); void setAutoCompletionEnabled(bool); void setAutoCompletionAcceptWithEnterEnabled(bool); void setAutoCompletionBuiltInFunctionsEnabled(bool); void setAutoCompletionBuiltInVariablesEnabled(bool); void setAutoCompletionLongFormUnitsEnabled(bool); void setAutoCompletionUserFunctionsEnabled(bool); void setAutoCompletionUserVariablesEnabled(bool); void setBitfieldVisible(bool); void setHistorySizeLimit(); void setConstantsDockVisible(bool, bool takeFocus = true); void setFormulaBookDockVisible(bool, bool takeFocus = true); void setFullScreenEnabled(bool); void setFunctionsDockVisible(bool, bool takeFocus = true); void setHistoryDockVisible(bool, bool takeFocus = true); void setKeypadMode(QAction*); void setMenuAppearance(QAction*); void setDockAppearance(QAction*); void setStatusBarAppearance(QAction*); void setKeypadAppearance(QAction*); void applyKeypadAppearance(); void setEditorDisplayStyle(QAction*); void setKeypadZoom(QAction*); void setKeypadVisible(bool); void setLeaveLastExpressionEnabled(bool); void setUpDownArrowBehavior(QAction*); void setRadixCharacterAutomatic(); void setRadixCharacter(char); void setRadixCharacterComma(); void setRadixCharacterDot(); void setRadixCharacterBoth(); void setResultFormatBinary(); void setResultFormatCartesian(); void setResultFormat(char); void setResultFormatEngineering(); void setResultFormatFixed(); void setResultFormatGeneral(); void setResultFormatHexadecimal(); void setImaginaryUnitI(); void setImaginaryUnitJ(); void setResultFormatOctal(); void setResultFormatPolar(); void setResultFormatTrigonometric(); void setResultFormatCis(); void setResultFormatPolarAngle(); void setResultFormatRational(); void setResultFormatScientific(); void setResultFormatSexagesimal(); void setUnitNegativeExponentStyle(QAction*); void setResultPrecision15Digits(); void setResultPrecision2Digits(); void setResultPrecision3Digits(); void setResultPrecision50Digits(); void setResultPrecision8Digits(); void setResultPrecisionAutomatic(); void setResultPrecisionCustom(); void setResultPrecision(int); void setResultRoundingMode(QAction*); void setRemoveTrailingZeroesEnabled(bool); void setMenuBarVisible(bool); void setStatusBarVisible(bool); void setSyntaxHighlightingEnabled(bool); void setInputDigitGroupingEnabled(bool); void setAutomaticInputAdjustmentsEnabled(bool); void setCursorBlinkingEnabled(bool); void setEscapeClearsEditorEnabled(bool); void setDigitGrouping(QAction*); void setDigitGroupingIntegerPartOnlyEnabled(bool); void setAutoResultToClipboardEnabled(bool); void setSimplifyResultExpressionsEnabled(bool); void setHoverHighlightResultsEnabled(bool); void setVariablesDockVisible(bool, bool takeFocus = true); void setUserFunctionsDockVisible(bool, bool takeFocus = true); void setUserUnitsDockVisible(bool, bool takeFocus = true); void setWindowPositionSaveEnabled(bool); void setOpenPrivateTabOnStartupEnabled(bool); void setWidgetsDirection(); void showAboutDialog(); void showDiagnosticsDialog(); void showStateLabel(const QString&); void showFontDialog(); void showLanguageChooserDialog(); void showManualWindow(); void showNumberFormatDialog(); void showResultSlotsDialog(); void showCustomThemeDialog(); void showContextHelp(); void showAngleModeContextMenu(const QPoint&); void showPrecisionContextMenu(const QPoint&); void showKeypadContextMenu(const QPoint&); void showResultFormatContextMenu(const QPoint&); void showSessionImportDialog(); void showUserDefinitionsImportDialog(); void openSessionsFolder(); void wrapSelection(); void startHistoryEntryEdit(int index); void editHistoryEntryContext(int index); void removeHistoryEntryAt(int index); void removeHistoryEntriesAbove(int index); void removeHistoryEntriesBelow(int index); protected: bool event(QEvent*) override; void closeEvent(QCloseEvent*) override; void resizeEvent(QResizeEvent*) override; bool eventFilter(QObject*, QEvent*) override; private: Q_DISABLE_COPY(MainWindow) void clearTextEditSelection(QPlainTextEdit*); void hideCurrentResultPreview(); void addTabifiedDock(QDockWidget*, bool takeFocus, Qt::DockWidgetArea = Qt::RightDockWidgetArea); void applyDockCornerLayout(); void deleteDock(QDockWidget*); void createUi(); void createActions(); void createActionGroups(); void createActionShortcuts(); void createMenus(); void createStatusBar(); void createFixedWidgets(); void createKeypad(); void createBitField(); void createBookDock(bool takeFocus = true); void createConstantsDock(bool takeFocus = true); void createFunctionsDock(bool takeFocus = true); void createHistoryDock(bool takeFocus = true); void createVariablesDock(bool takeFocus = true); void createUserFunctionsDock(bool takeFocus = true); void createUserUnitsDock(bool takeFocus = true); void createFixedConnections(); void applySettings(bool initializing = true); void setDisplayFont(const QFont& font); void applyEditorDisplayStyle(); void checkInitialResultFormat(); void checkInitialComplexFormat(); void checkInitialImaginaryUnit(); void checkInitialResultPrecision(); void checkInitialLanguage(); void checkInitialDigitGrouping(); void restoreSession(bool restoreHistory = true); bool restoreSessionLayout(bool restoreHistory); void deleteKeypad(bool deferredDeletion = true); void deleteStatusBar(); void deleteBitField(); void deleteBookDock(); void deleteConstantsDock(); void deleteFunctionsDock(); void deleteHistoryDock(); void deleteVariablesDock(); void deleteUserFunctionsDock(); void deleteUserUnitsDock(); void saveSettings(); void saveSessionToDefaultPath(); void saveSession(QString &fname); void finishRestoreSessionLayout(const QJsonObject& layout, const QJsonObject& window, const QJsonObject& root, const QJsonArray& tabs, const QString& activeSessionName, bool restoreHistory, QHash sessionJsons, QHash> viewportAnchors, QHash scrollValues); void openImportedSession(Session* session); void activateSession(Session* session); void captureEditorTextInCurrentSession(); void restoreEditorTextFromCurrentSession(); QWidget* createEditorDisplayPane(ResultDisplay* display, Editor* editor); void configureEditorDisplayPane(ResultDisplay* display, Editor* editor); void setActiveEditorDisplayPane(ResultDisplay* display, Editor* editor, bool forceEditorFocus = false); QAbstractItemView* dockItemViewFocusTarget(QWidget* widget) const; QDockWidget* dockWidgetForDescendant(QWidget* widget) const; bool isDockWidgetDescendant(QWidget* widget) const; bool isDockTextInput(QWidget* widget) const; void deactivateActiveEditorForTextInputFocus(); QList focusCycleTargets() const; bool focusWidgetMatchesCycleTarget(QWidget* focusWidget, QWidget* target) const; void cycleFocusRegion(int direction); void splitActivePane(Qt::Orientation orientation, bool insertAfter); Session* createUntitledSession(bool activateCreatedSession = true); QString firstAvailableSessionNameAcrossWindows(bool privateSession) const; void renameLoadedSession(Session* session, const QString& name); void discardUnusedPrivateSessions(); void finishStartupSessionRestore(bool restoredSession); QString firstAvailableUntitledSessionNameAcrossWindows(const MainWindow* ignoredWindow = nullptr) const; void copyWindowLayoutFrom(const MainWindow* source); QList splitPaneDisplays() const; QList splitPaneEditors() const; QStringList paneSessionNames(ResultDisplay* display) const; void addSessionToActivePane(const QString& name); void updatePaneLoadedSessionCounts(); void updatePaneEditorCursorVisibility(); void updateActiveSessionPaneTabColor(); void updatePaneTabBars(); void updateSessionWindowTitle(); ResultDisplay* tabBarDisplay(QTabBar* tabBar) const; QTabBar* displayTabBar(ResultDisplay* display) const; void switchPaneToSession(ResultDisplay* display, const QString& name); bool focusOpenSession(const QString& name); void moveSessionTab(QTabBar* sourceTabBar, QTabBar* targetTabBar, const QString& name, int targetIndex); void moveSessionTabToPane(QTabBar* sourceTabBar, ResultDisplay* targetDisplay, const QString& name, const QPoint& panePos); void splitPaneWithSession(QTabBar* sourceTabBar, ResultDisplay* targetDisplay, const QString& name, Qt::Orientation orientation, bool insertAfter); void rememberClosedSessionTab(ResultDisplay* display, const QString& name); void removeSessionTabFromPane(ResultDisplay* display, const QString& name, bool closePaneIfEmpty); void removePaneForDisplay(ResultDisplay* display); void normalizeSplitContainerTree(); void applyThemeSurfacePalette(); void restoreWindowThemeBackgrounds(); void scheduleDockAppearanceRefresh(bool forceNativePolish = false); void applyDockTabBarAppearance(); QStringList openDockNames() const; QStringList configuredOpenDockNames() const; void applyOpenDocks(const QStringList& names); void restoreDockLayout(const QByteArray& state, const QStringList& names); QJsonObject dockColumnOrders() const; void restoreDockColumnOrders(const QJsonObject& orders); void restoreDockColumnOrder(QDockWidget* dock); void applyKeypadThemeSurfacePalette(); void scheduleThemeRuntimeDiagnosticsReport(); void writeThemeRuntimeDiagnosticsReport(); void updateSplitterStyleSheet(); void refreshPaneThemes(); void captureVisibleSessionViewports(); void restoreVisibleSessionViewports(); void saveSessionLayout(bool captureCurrentViewport = true, bool captureEditorState = false); void flushPendingSessionSave(); bool configureCustomKeypad(); void updateKeypadModeActionState(); void setActionsText(); void updateKeypadDisabledActionText(); void setMenusText(); void setStatusBarText(); void applyStatusBarSelectionState(); void setStatusBarSelectionActionState(char angleUnit, char resultFormat, int resultPrecision); void syncStatusBarSelectionMenuActionState(); void syncViewMenuActionState(); void syncEditMenuActionState(); void syncSessionMenuActionState(); void updateStatusBarSectionVisibility(); void updateColorSchemeActionState(); QString statusBarAngleUnitValue() const; QString statusBarResultPrecisionValue() const; QString statusBarResultFormatValue() const; void applyUserDefinitions(int* importedVariables = nullptr, int* importedFunctions = nullptr, int* importedUnits = nullptr, int* ignoredLines = nullptr, QList* ignoredLineNumbers = nullptr); void importUserDefinitionsFromText(const QString& text, bool overwriteExisting, int* importedVariables = nullptr, int* importedFunctions = nullptr, int* importedUnits = nullptr, int* ignoredLines = nullptr, QList* ignoredLineNumbers = nullptr, bool dryRun = false); bool rebuildSessionFromEntries(const QList& entries, int startIndex = 0, int* errorIndex = nullptr, QString* errorText = nullptr); QList historyEntries() const; static QTranslator* createTranslator(const QString& langCode); struct { QAction* sessionOpen; QAction* sessionRename; QAction* sessionClone; QAction* sessionClose; QAction* sessionReopen; QAction* sessionNewTab; QAction* sessionNewPrivate; QAction* sessionConvertPrivacy; QAction* sessionNewWindow; QAction* sessionOpenSessionsFolder; QAction* sessionImport; QAction* sessionImportUserDefinitions; QAction* sessionExportJson; QAction* sessionExportHtml; QAction* sessionExportPlainText; QAction* sessionQuit; QAction* editUndo; QAction* editRedo; QAction* editCut; QAction* editCopy; QAction* editCopyLastResult; QAction* editPaste; QAction* editSelectExpression; QAction* editInsertFunction; QAction* editInsertVariable; QAction* editDeleteVariable; QAction* editInsertUserFunction; QAction* editDeleteUserFunction; QAction* editClearExpression; QAction* editClearHistory; QAction* editWrapSelection; QAction* viewKeypadDisabled; QAction* viewKeypadBasicWide; QAction* viewKeypadScientificWide; QAction* viewKeypadScientificNarrow; QAction* viewKeypadCustom; QAction* viewKeypadZoom50; QAction* viewKeypadZoom100; QAction* viewKeypadZoom150; QAction* viewKeypadZoom200; QAction* viewFormulaBook; QAction* viewConstants; QAction* viewFunctions; QAction* viewVariables; QAction* viewUserFunctions; QAction* viewUserUnits; QAction* viewHistory; QAction* viewStatusBar; QAction* viewMenuBar; QAction* viewFullScreenMode; QAction* viewBitfield; QAction* viewSplitLeft; QAction* viewSplitRight; QAction* viewSplitUp; QAction* viewSplitDown; QAction* viewClosePane; QAction* settingsResultFormatGeneral; QAction* settingsResultFormatFixed; QAction* settingsResultFormatEngineering; QAction* settingsResultFormatScientific; QAction* settingsResultFormatRational; QAction* settingsResultFormatAutoPrecision; QAction* settingsResultFormat0Digits; QAction* settingsResultFormat2Digits; QAction* settingsResultFormat3Digits; QAction* settingsResultFormat8Digits; QAction* settingsResultFormat15Digits; QAction* settingsResultFormat50Digits; QAction* settingsResultFormatCustomDigits; QAction* settingsResultRoundingHalfAwayFromZero; QAction* settingsRemoveTrailingZeroes; QAction* settingsResultRoundingHalfEven; QAction* settingsResultRoundingTowardZero; QAction* settingsResultRoundingTowardPositiveInfinity; QAction* settingsResultRoundingTowardNegativeInfinity; QAction* settingsResultFormatBinary; QAction* settingsResultFormatOctal; QAction* settingsResultFormatCartesian; QAction* settingsResultFormatPolar; QAction* settingsResultFormatTrigonometric; QAction* settingsResultFormatCis; QAction* settingsResultFormatPolarAngle; QAction* settingsImaginaryUnitI; QAction* settingsImaginaryUnitJ; QAction* settingsResultFormatHexadecimal; QAction* settingsResultFormatSexagesimal; QAction* settingsUnitNegativeExponentSuperscript; QAction* settingsUnitNegativeExponentFraction; QAction* settingsAngleUnitRadian; QAction* settingsAngleUnitDegree; QAction* settingsAngleUnitGradian; QAction* settingsAngleUnitTurn; QAction* settingsAngleUnitRevolution; QAction* settingsBehaviorSaveWindowPositionOnExit; QAction* settingsBehaviorPartialResults; QAction* settingsBehaviorAutoCompletion; QAction* settingsBehaviorAutoCompletionAcceptWithEnter; QAction* settingsBehaviorAutoCompletionBuiltInFunctions; QAction* settingsBehaviorAutoCompletionBuiltInVariables; QAction* settingsBehaviorAutoCompletionLongFormUnits; QAction* settingsBehaviorAutoCompletionUserFunctions; QAction* settingsBehaviorAutoCompletionUserVariables; QAction* settingsBehaviorSyntaxHighlighting; QAction* settingsEditingInputDigitGrouping; QAction* settingsEditingAutomaticInputAdjustments; QAction* settingsEditingCursorBlinking; QAction* settingsEditingEscapeClearsEditor; QAction* settingsBehaviorHoverHighlightResults; QAction* settingsBehaviorDigitGroupingNone; QAction* settingsBehaviorDigitGroupingOneSpace; QAction* settingsBehaviorDigitGroupingTwoSpaces; QAction* settingsBehaviorDigitGroupingThreeSpaces; QAction* settingsBehaviorDigitGroupingIntegerPartOnly; QAction* settingsBehaviorAutoAns; QAction* settingsBehaviorLeaveLastExpression; QAction* settingsBehaviorNumberFormat; QAction* settingsResetAll; QAction* settingsBehaviorResultSlots; QAction* settingsBehaviorUpDownArrowNever; QAction* settingsBehaviorUpDownArrowAlways; QAction* settingsBehaviorUpDownArrowSingleLineOnly; QAction* settingsBehaviorAlwaysOnTop; QAction* settingsOpenPrivateTabOnStartup; QAction* settingsBehaviorAutoResultToClipboard; QAction* settingsBehaviorSimplifyResultExpressions; QAction* settingsBehaviorHistorySizeLimit; QAction* settingsRadixCharBoth; QAction* settingsDisplayZoomIn; QAction* settingsDisplayZoomOut; QAction* settingsDisplayFont; QAction* settingsDisplayColorSchemeCustom; QAction* settingsMenuAppearanceSystem; QAction* settingsMenuAppearanceSpeedCrunch; QAction* settingsDockAppearanceSystem; QAction* settingsDockAppearanceSpeedCrunch; QAction* settingsStatusBarAppearanceSystem; QAction* settingsStatusBarAppearanceSpeedCrunch; QAction* settingsKeypadAppearanceClassic; QAction* settingsKeypadAppearanceModern; QAction* settingsEditorDisplayClassic; QAction* settingsEditorDisplayModern; QVector settingsDisplayColorSchemes; QAction* settingsRadixCharDefault; QAction* settingsRadixCharDot; QAction* settingsRadixCharComma; QAction* settingsLanguage; QAction* helpManual; #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS QAction* helpUpdates; #endif QAction* helpFeedback; QAction* helpCommunity; QAction* helpSource; QAction* helpDonate; QAction* helpAbout; QAction* helpDiagnostics; QAction* contextHelp; } m_actions{}; struct { QActionGroup* angle; QActionGroup* colorScheme; QActionGroup* menuAppearance; QActionGroup* dockAppearance; QActionGroup* statusBarAppearance; QActionGroup* keypadAppearance; QActionGroup* editorDisplayStyle; QActionGroup* digits; QActionGroup* resultRoundingMode; QActionGroup* resultFormat; QActionGroup* complexFormat; QActionGroup* imaginaryUnit; QActionGroup* radixChar; QActionGroup* digitGrouping; QActionGroup* upDownArrowBehavior; QActionGroup* keypad; QActionGroup* keypadZoom; QActionGroup* unitNegativeExponentStyle; } m_actionGroups; struct { QMenu* angleUnit; QMenu* complexForm; QMenu* imaginaryUnit; QMenu* editing; QMenu* autoCompletion; QMenu* colorScheme; QMenu* decimal; QMenu* digitGrouping; QMenu* display; QMenu* menuAppearance; QMenu* dockAppearance; QMenu* statusBarAppearance; QMenu* keypadAppearance; QMenu* editorDisplayStyle; QMenu* edit; QMenu* results; QMenu* unitNegativeExponentStyle; QMenu* resultRoundingMode; QMenu* resultFormat; QMenu* inputFormat; QMenu* help; QMenu* precision; QMenu* radixChar; QMenu* upDownArrowBehavior; QMenu* session; QMenu* sessionExport; QMenu* settings; QMenu* view; QMenu* split; QMenu* keypad; QMenu* keypadZoom; QMenu* window; } m_menus; struct { QVBoxLayout* root; QHBoxLayout* keypad; } m_layouts; struct { QLabel* state; QPushButton* stateCloseButton; ResultDisplay* display; Editor* editor; QSplitter* splitContainer = nullptr; Keypad* keypad = nullptr; QWidget* keypadContainer = nullptr; QWidget* root; ManualWindow* manual = nullptr; BitFieldWidget* bitField = nullptr; } m_widgets{}; struct { BookDock* book; GenericDock* constants; GenericDock* functions; GenericDock* history; GenericDock* variables; GenericDock* userFunctions; GenericDock* userUnits; GenericDock* bitField; } m_docks; QList m_allDocks; QJsonObject m_dockColumnOrders; bool m_initializingUi = true; bool m_hasRestoredDockLayout = false; bool m_dockAppearanceRefreshPending = false; bool m_dockNativePolishPending = false; bool m_dockVisibilityRefreshPending = false; QHash m_paneSessionNames; QHash m_paneSessionTabs; QHash m_paneTabBars; QHash m_tabBarDisplays; struct ClosedSessionTab { QString name; QJsonObject sessionJson; QString editorText; QPointer display; int tabIndex = -1; }; QList m_closedSessionTabs; struct { bool autoAns; } m_conditions; struct { QWidget* angleUnitSection; QLabel* angleUnitLabel; QPushButton* angleUnit; QWidget* resultFormatSection; QLabel* resultFormatLabel; QPushButton* resultFormat; QLabel* resultPrecisionSeparator; QWidget* resultPrecisionSection; QLabel* resultPrecisionLabel; QPushButton* resultPrecision; QLabel* angleUnitSeparator; // Settings holds the active evaluator state; these values are the // independent, persistent selection owned by this window. char selectedAngleUnit = 'd'; char selectedResultFormat = 'g'; int selectedResultPrecision = -1; } m_status; Constants* m_constants; Evaluator* m_evaluator; FunctionRepo* m_functions; Settings* m_settings = nullptr; Settings::KeypadMode m_keypadMode; int m_keypadZoomPercent; Session* m_session; QHash m_loadedSessions; QHash> m_sessionViewportAnchors; QHash m_sessionScrollValues; QTranslator* m_translator; QPlainTextEdit* m_copyWidget = nullptr; ManualServer* m_manualServer; #ifdef SPEEDCRUNCH_ENABLE_UPDATE_CHECKS VersionCheck* m_versionCheck; #endif int m_pendingHistoryEditIndex; bool m_shutdownStateSaved; bool m_restorePreviousSessionOnStartup; bool m_startupPrivateTabPending = false; QTimer* m_deferredSessionSaveTimer; bool m_sessionSavePending; bool m_bulkEvaluationInProgress; bool m_bulkHistoryChanged; bool m_bulkVariablesChanged; bool m_bulkFunctionsChanged; bool m_bulkUnitsChanged; bool m_currentResultPreviewDismissed = false; QString m_lastCurrentResultPreviewMessage; }; #endif // GUI_MAINWINDOW_H heldercorreia-speedcrunch-e7ca37f/src/gui/manualwindow.cpp000066400000000000000000000111671526573132500241270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014, 2016, 2022, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/manualwindow.h" #include "core/settings.h" #include "core/manualserver.h" #include #include #include #include #include ManualWindow::ManualWindow(QWidget* parent) : QTextBrowser(parent), m_scrollUpdated(false) { setWindowFlags(Qt::Window); setWindowIcon(QPixmap(":/speedcrunch.png")); setStyleSheet(QStringLiteral("QTextBrowser { background-color: #FFFFFF; }")); QFont f("Helvetica", 10, QFont::Normal); f.setStyleHint(QFont::SansSerif); #ifdef Q_OS_MACOS // CoreText font smoothing makes regular text look heavier on the manual's // white background. Use grayscale antialiasing without changing the weight. f.setStyleStrategy(QFont::NoSubpixelAntialias); #endif setFont(f); //Disable automatic opening of links. We handle them ourselves. this->setOpenLinks(false); connect(this, SIGNAL(anchorClicked(const QUrl&)), SLOT(handleAnchorClick(const QUrl&))); connect(this, SIGNAL(sourceChanged(const QUrl&)), SLOT(handleSourceChanged(const QUrl&))); m_server = ManualServer::instance(); auto homePage = m_server->homePage(); if (homePage.isValid()) { openPage(homePage); } retranslateText(); } void ManualWindow::openPage(const QUrl& url) { setSource(url); } void ManualWindow::retranslateText() { QString docTitle = documentTitle(); if (docTitle.isEmpty()) setWindowTitle(tr("SpeedCrunch Manual")); else setWindowTitle(tr("%1 - SpeedCrunch Manual").arg(docTitle)); } void ManualWindow::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { m_server->ensureCorrectLanguage(); this->reload(); retranslateText(); } else QTextBrowser::changeEvent(event); } void ManualWindow::keyPressEvent(QKeyEvent *ev) { if(ev->key() == Qt::Key_Escape) { ev->accept(); this->close(); } else if(ev->key() == Qt::Key_Back || ev->key() == Qt::Key_Backspace) { ev->accept(); this->backward(); } else if(ev->key() == Qt::Key_Forward) { ev->accept(); this->forward(); } else if(ev->key() == Qt::Key_Home) { ev->accept(); this->home(); } else QTextBrowser::keyPressEvent(ev); } void ManualWindow::mouseReleaseEvent(QMouseEvent* ev) { if (ev->button() == Qt::BackButton) { ev->accept(); backward(); } else if (ev->button() == Qt::ForwardButton) { ev->accept(); forward(); } else QTextBrowser::mouseReleaseEvent(ev); } void ManualWindow::closeEvent(QCloseEvent* event) { emit windowClosed(); QTextBrowser::closeEvent(event); } void ManualWindow::paintEvent(QPaintEvent* e) { /* So the issue and reasoning here is: * - When opening the manual window via the context help feature *and it was maximized before*, * it doesn't correctly scroll to the right anchor on the page. * - QTextBrowser keeps its scrolling offset in pixels; when the widget is resized, the text on * the page is laid out again and the pixel offset of anchors may change. This means when * resizing the widget, the formerly-scrolled-to anchor may not be at the top anymore. * - For maximized windows, the page is loaded first, -- including scrolling the widget to the * anchor -- then there's a resizeEvent that sets the actual, maximized window size. This throws * off the page position. * - We work around this here by updating the scroll position on the very first paintEvent, which * happens after the window's maximized state has finally properly registered; late enough to fix * the scrolling. * * Yes, it's rather hackish. */ if (!m_scrollUpdated && source().isValid()) { scrollToAnchor(source().fragment()); m_scrollUpdated = true; } QTextBrowser::paintEvent(e); } void ManualWindow::handleAnchorClick(const QUrl &url) { if (url.scheme() == "qthelp") openPage(url); else QDesktopServices::openUrl(url); } void ManualWindow::handleSourceChanged(const QUrl&) { // This updates the window title with the new document title. retranslateText(); } QVariant ManualWindow::loadResource(int type, const QUrl &name) { QByteArray ba; if (type < 4 && name.scheme()=="qthelp") { QUrl url(name); if (name.isRelative()) url = source().resolved(name); ba = m_server->fileData(url); } return ba; } heldercorreia-speedcrunch-e7ca37f/src/gui/manualwindow.h000066400000000000000000000017531526573132500235740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014, 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_MANUALWINDOW_H #define GUI_MANUALWINDOW_H #include class QCloseEvent; class QEvent; class QUrl; class ManualServer; class ManualWindow : public QTextBrowser { Q_OBJECT public: ManualWindow(QWidget* parent = 0); signals: void windowClosed(); public slots: void openPage(const QUrl&); void retranslateText(); protected: virtual void changeEvent(QEvent*); virtual void keyPressEvent(QKeyEvent * ev); virtual void mouseReleaseEvent(QMouseEvent* ev); virtual void closeEvent(QCloseEvent*); virtual void paintEvent(QPaintEvent* e); private slots: void handleAnchorClick(const QUrl&url); void handleSourceChanged(const QUrl& url); private: Q_DISABLE_COPY(ManualWindow) QVariant loadResource(int type, const QUrl &name); ManualServer *m_server; bool m_scrollUpdated; }; #endif // GUI_MANUALWINDOW_H heldercorreia-speedcrunch-e7ca37f/src/gui/menustyleutils.cpp000066400000000000000000000707001526573132500245260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/menustyleutils.h" #include "core/startupdiagnostics.h" #include "core/colorscheme.h" #include "core/settings.h" #include "gui/dockcomboboxchevron.h" #include "gui/gtkmenupalette.h" #include "gui/oklchutils.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace GtkMenuPalette { namespace { constexpr unsigned Hover = 1 << 1; // GTK_STATE_FLAG_PRELIGHT constexpr unsigned Disabled = 1 << 3; // GTK_STATE_FLAG_INSENSITIVE constexpr unsigned Backdrop = 1 << 6; // GTK_STATE_FLAG_BACKDROP QColor over(const QColor& foreground, const QColor& background) { const qreal alpha = foreground.alphaF(); return QColor::fromRgbF(foreground.redF() * alpha + background.redF() * (1 - alpha), foreground.greenF() * alpha + background.greenF() * (1 - alpha), foreground.blueF() * alpha + background.blueF() * (1 - alpha)); } struct CachedPalette { QPalette source; std::optional colors; bool loaded = false; }; CachedPalette cachedPalette; bool usesGtkColors() { if (QSysInfo::kernelType() != QLatin1String("linux")) return false; const QString platform = QApplication::platformName(); if (platform != QLatin1String("xcb") && !platform.startsWith(QLatin1String("wayland"))) return false; const QByteArray theme = qgetenv("QT_QPA_PLATFORMTHEME").toLower(); if (!theme.isEmpty() && theme != "gtk3" && theme != "gnome") return false; if (theme.isEmpty() && !qgetenv("XDG_CURRENT_DESKTOP").toLower().split(':').contains("gnome")) return false; QStyle* style = QApplication::style(); while (auto* proxy = qobject_cast(style)) style = proxy->baseStyle(); // Dedicated styles such as Breeze and Adwaita already draw their own menus. return style->objectName().compare(QLatin1String("fusion"), Qt::CaseInsensitive) == 0; } const Api* gtkApi() { static QLibrary library(QStringLiteral("libgtk-3.so.0")); static Api api{}; static bool resolved = false; if (!resolved) { resolved = true; library.setLoadHints(QLibrary::PreventUnloadHint); if (!library.load()) return nullptr; #define RESOLVE(member, symbol) \ api.member = reinterpret_cast(library.resolve(symbol)); RESOLVE(popoverNew, "gtk_popover_new") RESOLVE(modelButtonNew, "gtk_model_button_new") RESOLVE(add, "gtk_container_add") RESOLVE(context, "gtk_widget_get_style_context") RESOLVE(setState, "gtk_style_context_set_state") RESOLVE(color, "gtk_style_context_get_color") RESOLVE(background, "gtk_render_background") RESOLVE(destroyWidget, "gtk_widget_destroy") RESOLVE(refSink, "g_object_ref_sink") RESOLVE(unref, "g_object_unref") RESOLVE(surfaceForData, "cairo_image_surface_create_for_data") RESOLVE(createPainter, "cairo_create") RESOLVE(destroyPainter, "cairo_destroy") RESOLVE(flushSurface, "cairo_surface_flush") RESOLVE(destroySurface, "cairo_surface_destroy") #undef RESOLVE } const auto display = reinterpret_cast(library.resolve("gdk_display_get_default")); if (!display || !api.popoverNew || !api.modelButtonNew || !api.add || !api.context || !api.setState || !api.color || !api.background || !api.destroyWidget || !api.refSink || !api.unref || !api.surfaceForData || !api.createPainter || !api.destroyPainter || !api.flushSurface || !api.destroySurface) return nullptr; if (!display()) { // The GTK platform plugin may be absent even on GNOME. Match Qt's // backend and preserve its Xlib handler when initializing GTK ourselves. const auto initialize = reinterpret_cast(library.resolve("gtk_init_check")); const auto disableLocale = reinterpret_cast(library.resolve("gtk_disable_setlocale")); const auto backends = reinterpret_cast(library.resolve("gdk_set_allowed_backends")); if (!initialize || !disableLocale || !backends) return nullptr; using ErrorHandler = int (*)(void*, void*); const auto setErrorHandler = reinterpret_cast(library.resolve("XSetErrorHandler")); const ErrorHandler handler = setErrorHandler ? setErrorHandler(nullptr) : nullptr; disableLocale(); backends(QApplication::platformName().startsWith(QLatin1String("wayland")) ? "wayland,x11" : "x11,wayland"); const bool initialized = initialize(nullptr, nullptr); if (setErrorHandler) setErrorHandler(handler); if (!initialized) return nullptr; } static bool watchingTheme = false; if (!watchingTheme) { const auto settings = reinterpret_cast(library.resolve("gtk_settings_get_default")); using Callback = void (*)(); using DestroyNotify = void (*)(void*, void*); const auto connectSignal = reinterpret_cast(library.resolve("g_signal_connect_data")); if (settings && connectSignal) { const auto changed = +[](void*, void*, void*) { if (qApp) QTimer::singleShot(0, qApp, []() { MenuStyle::refresh(); }); }; connectSignal(settings(), "notify::gtk-theme-name", reinterpret_cast(changed), nullptr, nullptr, 0); connectSignal(settings(), "notify::gtk-application-prefer-dark-theme", reinterpret_cast(changed), nullptr, nullptr, 0); watchingTheme = true; } } return &api; } } QPalette read(const Api& api, const QPalette& fallback) { QPalette palette = fallback; // Modern GNOME menus use popover model buttons. Legacy GtkMenu items // still use the list accent in Yaru, which differs from popup hover. void* menu = api.popoverNew(nullptr); api.refSink(menu); void* item = api.modelButtonNew(); api.add(menu, item); void* menuContext = api.context(menu); void* itemContext = api.context(item); const auto background = [&api](void* context, unsigned state, const QColor& base) { QImage image(64, 64, QImage::Format_ARGB32_Premultiplied); image.fill(base); // Cairo's ARGB32 format has the same native byte order as QImage's. void* surface = api.surfaceForData(image.bits(), 0, image.width(), image.height(), image.bytesPerLine()); void* painter = api.createPainter(surface); api.setState(context, state); api.background(context, painter, 0, 0, image.width(), image.height()); api.destroyPainter(painter); api.flushSurface(surface); const QColor result = image.pixelColor(32, 32); api.destroySurface(surface); return result; }; const auto foreground = [&api](void* context, unsigned state, const QColor& base) { Rgba color{}; api.color(context, state, &color); return over(QColor::fromRgbF(color.red, color.green, color.blue, color.alpha), base); }; for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { const unsigned state = group == QPalette::Inactive ? Backdrop : group == QPalette::Disabled ? Disabled : 0; const QColor fill = background(menuContext, state, fallback.color(group, QPalette::Window)); api.setState(itemContext, state); const QColor text = foreground(itemContext, state, fill); const QColor selected = background(itemContext, state | Hover, fill); const QColor selectedText = foreground(itemContext, state | Hover, selected); for (const QPalette::ColorRole role : {QPalette::Window, QPalette::Base, QPalette::Button}) palette.setColor(group, role, fill); for (const QPalette::ColorRole role : {QPalette::WindowText, QPalette::Text, QPalette::ButtonText}) palette.setColor(group, role, text); palette.setColor(group, QPalette::Highlight, selected); palette.setColor(group, QPalette::HighlightedText, selectedText); } api.destroyWidget(menu); api.unref(menu); return palette; } std::optional systemPalette(const QPalette& fallback) { if (!usesGtkColors()) return std::nullopt; CachedPalette& cached = cachedPalette; if (!cached.loaded || cached.source != fallback) { cached.source = fallback; cached.colors.reset(); cached.loaded = true; if (const Api* api = gtkApi()) cached.colors = read(*api, fallback); } return cached.colors; } void invalidate() { cachedPalette.loaded = false; } } namespace { constexpr auto ThemeColorsProperty = "speedcrunchMenuThemeColors"; constexpr auto ThemeSchemeProperty = "speedcrunchMenuThemeScheme"; constexpr auto NativeBarBackgroundProperty = "speedcrunchNativeMenuBarStyledBackground"; constexpr auto SystemPaletteSourceProperty = "speedcrunchSystemMenuPaletteSource"; constexpr auto SystemPaletteProperty = "speedcrunchSystemMenuPalette"; QString themeKey() { const Settings* settings = Settings::instance(); return settings->colorScheme + QLatin1Char('|') + settings->customColorSchemeJson; } struct MenuColors { QColor background; QColor foreground; QColor selectedBackground; QColor selectedForeground; }; struct CachedThemeColors { QString key; QColor fallbackBackground; MenuColors menu; MenuColors bar; bool valid = false; }; CachedThemeColors cachedThemeColors; class MenuIconEngine : public QIconEngine { public: MenuIconEngine(const QIcon& source, const QPalette& palette) : m_source(source), m_palette(palette) {} QIconEngine* clone() const override { return new MenuIconEngine(m_source, m_palette); } bool isNull() override { return m_source.isNull(); } QString iconName() override { return m_source.name(); } QSize actualSize(const QSize& size, QIcon::Mode mode, QIcon::State state) override { return m_source.actualSize(size, mode, state); } QList availableSizes(QIcon::Mode mode, QIcon::State state) override { return m_source.availableSizes(mode, state); } QPixmap pixmap(const QSize& size, QIcon::Mode mode, QIcon::State state) override { return scaledPixmap(size, mode, state, 1.0); } QPixmap scaledPixmap(const QSize& size, QIcon::Mode mode, QIcon::State state, qreal scale) override { QPixmap result = m_source.pixmap(size, scale, mode, state); if (result.isNull()) return result; const QPalette::ColorGroup group = mode == QIcon::Disabled ? QPalette::Disabled : QPalette::Active; const QPalette::ColorRole role = mode == QIcon::Active || mode == QIcon::Selected ? QPalette::HighlightedText : QPalette::WindowText; QColor foreground = m_palette.color(group, role); if (mode == QIcon::Disabled && foreground == m_palette.color(QPalette::Active, QPalette::WindowText)) { const auto maximumAlpha = [](const QPixmap& pixmap) { const QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); int maximum = 0; for (int y = 0; y < image.height(); ++y) { const auto* row = reinterpret_cast(image.constScanLine(y)); for (int x = 0; x < image.width(); ++x) { maximum = qMax(maximum, qAlpha(row[x])); if (maximum == 255) return maximum; } } return maximum; }; const QPixmap enabled = m_source.pixmap(size, scale, QIcon::Normal, state); // Recoloring removes gray disabled tints from opaque glyphs. // Fade those, but preserve opacity supplied by the source icon. if (maximumAlpha(result) >= maximumAlpha(enabled)) foreground.setAlphaF(foreground.alphaF() * 0.5); } QPainter painter(&result); painter.setCompositionMode(QPainter::CompositionMode_SourceIn); painter.fillRect(QRectF(QPointF(), result.deviceIndependentSize()), foreground); return result; } void paint(QPainter* painter, const QRect& rect, QIcon::Mode mode, QIcon::State state) override { const QPixmap image = scaledPixmap(rect.size(), mode, state, painter->device()->devicePixelRatioF()); const QRectF target(QRectF(rect).center() - QPointF(image.deviceIndependentSize().width() / 2, image.deviceIndependentSize().height() / 2), image.deviceIndependentSize()); painter->drawPixmap(target, image, QRectF(image.rect())); } private: QIcon m_source; QPalette m_palette; }; void updateMenuIcons(QMenu* menu, const QPalette* palette) { if (menu == nullptr) return; for (QAction* action : menu->actions()) { constexpr auto SourceProperty = "speedcrunchMenuIconSource"; constexpr auto ThemedKeyProperty = "speedcrunchMenuIconKey"; constexpr auto PaletteProperty = "speedcrunchMenuIconPalette"; const QIcon current = action->icon(); const bool hasSource = action->property(SourceProperty).isValid(); const bool usesThemedIcon = hasSource && current.cacheKey() == action->property(ThemedKeyProperty).toLongLong(); const QIcon source = usesThemedIcon ? action->property(SourceProperty).value() : current; if (palette != nullptr && !source.isNull()) { if (usesThemedIcon && action->property(PaletteProperty).value() == *palette) continue; // Platform icons can ignore the menu's palette. Keep the original // so System appearance can restore it. const QIcon themed = MenuStyle::themedIcon(source, *palette); action->setProperty(SourceProperty, source); action->setProperty(ThemedKeyProperty, themed.cacheKey()); action->setProperty(PaletteProperty, *palette); action->setIcon(themed); } else if (hasSource) { action->setProperty(SourceProperty, QVariant()); action->setProperty(ThemedKeyProperty, QVariant()); action->setProperty(PaletteProperty, QVariant()); if (usesThemedIcon) action->setIcon(source); } } } MenuColors themeColors(const QWidget* widget) { const QVariantList saved = widget->property(ThemeColorsProperty).toList(); const QString key = themeKey(); if (saved.size() == 4 && widget->property(ThemeSchemeProperty).toString() == key) { return {saved.at(0).value(), saved.at(1).value(), saved.at(2).value(), saved.at(3).value()}; } const QColor fallback = QApplication::palette().color(QPalette::Base); CachedThemeColors& cached = cachedThemeColors; const bool isBar = qobject_cast(widget) != nullptr; if (cached.valid && cached.key == key && cached.fallbackBackground == fallback) { StartupDiagnostics::Scope timing("Reuse menu theme colors"); return isBar ? cached.bar : cached.menu; } StartupDiagnostics::Scope timing("Generate menu theme colors"); const Settings* settings = Settings::instance(); ColorScheme scheme = settings->colorScheme == QLatin1String("Custom") ? ColorScheme(QJsonDocument::fromJson(settings->customColorSchemeJson.toUtf8())) : ColorScheme::loadByName(settings->colorScheme); if (!scheme.isValid()) scheme = ColorScheme::loadByName(QStringLiteral("Terminal")); const QColor base = scheme.isValid() ? scheme.colorForRole(ColorScheme::Background) : fallback; const QVector shades = generateOklchShades(base, 6, themePolarityForBackground(base)); const QColor selected = shades.at(UiConfig::DockUnfocusedSelectedItemShade); const QColor selectedText = aaForegroundForBackground(selected); const auto colors = [&](int shade) { const QColor background = shades.at(shade); return MenuColors{background, aaForegroundForBackground(background), selected, selectedText}; }; cached.key = key; cached.fallbackBackground = fallback; cached.menu = colors(UiConfig::DockHeaderShade); cached.bar = colors(UiConfig::WindowBackgroundShade); cached.valid = true; return isBar ? cached.bar : cached.menu; } QPalette fullyResolvedPalette(QPalette palette) { // Resolve every role explicitly so a themed parent cannot supply menu // text, selection, or disabled colors through palette inheritance. for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (int role = 0; role < QPalette::NColorRoles; ++role) { const auto colorRole = static_cast(role); if (colorRole != QPalette::NoRole) palette.setBrush(group, colorRole, palette.brush(group, colorRole)); } } return palette; } QPalette fullyResolvedSystemPalette(const QWidget* widget) { QPalette palette = QApplication::palette(widget); if (qobject_cast(widget)) { if (const auto gtk = GtkMenuPalette::systemPalette(palette)) palette = *gtk; } return fullyResolvedPalette(palette); } class MenuAppearanceFilter : public QObject { public: explicit MenuAppearanceFilter(QObject* parent) : QObject(parent) {} void apply(QWidget* widget) { if (m_updating || widget == nullptr) return; QScopedValueRollback guard(m_updating, true); applyWidget(widget); for (QMenu* child : widget->findChildren()) applyWidget(child); } void refresh() { if (m_updating) return; QScopedValueRollback guard(m_updating, true); for (QWidget* widget : QApplication::allWidgets()) applyWidget(widget); } void scheduleRefresh() { if (m_refreshPending) return; m_refreshPending = true; QTimer::singleShot(0, this, [this]() { m_refreshPending = false; refresh(); }); } protected: bool eventFilter(QObject* watched, QEvent* event) override { if (m_updating) return false; if ((watched == qApp && event->type() == QEvent::ApplicationPaletteChange) || event->type() == QEvent::ThemeChange) { // Let the platform finish updating its palette before refreshing // menus, including menus that are already open. GtkMenuPalette::invalidate(); scheduleRefresh(); } if (event->type() == QEvent::Polish || event->type() == QEvent::Show || event->type() == QEvent::ActionAdded || event->type() == QEvent::ActionChanged || event->type() == QEvent::ApplicationPaletteChange || event->type() == QEvent::PaletteChange || event->type() == QEvent::StyleChange) { QWidget* widget = qobject_cast(watched); if ((qobject_cast(widget) || qobject_cast(widget) || (qobject_cast(widget) && widget->property("speedcrunchDockComboBox").toBool())) && (event->type() == QEvent::Polish || event->type() == QEvent::Show || widget->testAttribute(Qt::WA_WState_Polished))) { if (event->type() == QEvent::StyleChange) widget->setProperty(SystemPaletteSourceProperty, QVariant()); apply(widget); if (event->type() == QEvent::StyleChange || event->type() == QEvent::Polish) scheduleRefresh(); } } return false; } private: void applyWidget(QWidget* widget) { if (auto* combo = qobject_cast(widget)) { if (combo->property("speedcrunchDockComboBox").toBool()) DockComboBoxChevron::refreshPopupAppearance(combo); return; } auto* bar = qobject_cast(widget); if (bar == nullptr && !qobject_cast(widget)) return; StartupDiagnostics::Scope timing("Apply menu appearance"); if (Settings::instance()->menuAppearance == Settings::MenuAppearanceSystem || (bar != nullptr && bar->isNativeMenuBar())) { const bool hadTheme = !widget->styleSheet().isEmpty(); if (hadTheme) widget->setStyleSheet(QString()); const QPalette source = fullyResolvedSystemPalette(widget); if (hadTheme || !widget->property(SystemPaletteSourceProperty).isValid() || widget->property(SystemPaletteSourceProperty).value() != source) { // Clear Qt's saved stylesheet palette before letting the desktop // style restore its own menu colors, including header text. widget->style()->unpolish(widget); widget->setPalette(source); widget->style()->polish(widget); widget->setProperty(SystemPaletteSourceProperty, source); widget->setProperty(SystemPaletteProperty, fullyResolvedPalette(widget->palette())); } const QPalette palette = widget->property(SystemPaletteProperty).value(); if (widget->palette() != palette || widget->palette().resolveMask() != palette.resolveMask()) widget->setPalette(palette); // Some desktop styles leave the bar transparent and rely on its // parent to paint the background. Use the system brush here too. if (bar != nullptr && !bar->isNativeMenuBar()) { // Removing a stylesheet does not restore this painting flag. // Otherwise desktop styles can still paint a themed surface. if (bar->property(NativeBarBackgroundProperty).isValid()) bar->setAttribute(Qt::WA_StyledBackground, bar->property(NativeBarBackgroundProperty).toBool()); bar->setAutoFillBackground(true); bar->update(); } if (auto* menu = qobject_cast(widget)) { updateMenuIcons(menu, nullptr); for (QAction* action : menu->actions()) { auto* widgetAction = qobject_cast(action); QWidget* content = widgetAction != nullptr ? widgetAction->defaultWidget() : nullptr; if (content == nullptr) continue; content->setPalette(palette); for (QWidget* control : content->findChildren()) { control->setPalette(qobject_cast(control) ? palette : fullyResolvedSystemPalette(control)); } } } return; } const MenuColors colors = themeColors(widget); widget->setProperty(SystemPaletteSourceProperty, QVariant()); if (bar != nullptr && !bar->property(NativeBarBackgroundProperty).isValid()) bar->setProperty(NativeBarBackgroundProperty, bar->testAttribute(Qt::WA_StyledBackground)); QPalette palette = fullyResolvedSystemPalette(widget); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (const QPalette::ColorRole role : {QPalette::Window, QPalette::Base, QPalette::Button}) palette.setColor(group, role, colors.background); for (const QPalette::ColorRole role : {QPalette::WindowText, QPalette::Text, QPalette::ButtonText}) palette.setColor(group, role, colors.foreground); palette.setColor(group, QPalette::Highlight, colors.selectedBackground); palette.setColor(group, QPalette::HighlightedText, colors.selectedForeground); } QString style = (bar != nullptr ? QStringLiteral( "QMenuBar { background-color: %1; color: %2; border: none; }" "QMenuBar::item { background: transparent; color: %2; }" "QMenuBar::item:selected { background-color: %3; color: %4; }" "QMenuBar::item:pressed { background-color: %3; color: %4; }") : QStringLiteral( "QMenu { background-color: %1; color: %2;" " border: 1px solid %3; border-radius: %5px; }" "QMenu::item:selected { background-color: %3; color: %4; }")) .arg(colors.background.name(), colors.foreground.name(), colors.selectedBackground.name(), colors.selectedForeground.name()); if (bar == nullptr) { style = style.arg(UiConfig::ControlCornerRadius); QColor disabledForeground = colors.foreground; disabledForeground.setAlphaF(disabledForeground.alphaF() * 0.5); style += QStringLiteral("QMenu::item:disabled { color: %1; }") .arg(disabledForeground.name(QColor::HexArgb)); } if (widget->styleSheet() != style) widget->setStyleSheet(style); if (widget->palette() != palette) widget->setPalette(palette); updateMenuIcons(qobject_cast(widget), &palette); } bool m_updating = false; bool m_refreshPending = false; }; QPointer& appearanceFilter() { static QPointer filter; return filter; } } void MenuStyle::install() { if (appearanceFilter() || qApp == nullptr) return; appearanceFilter() = new MenuAppearanceFilter(qApp); qApp->installEventFilter(appearanceFilter()); } void MenuStyle::refresh() { // A theme file can change without changing its saved name. cachedThemeColors.valid = false; GtkMenuPalette::invalidate(); install(); if (appearanceFilter()) { appearanceFilter()->refresh(); // Finish after native style handlers and popup dismissal as well. appearanceFilter()->scheduleRefresh(); } } void MenuStyle::apply(QWidget* widget) { install(); if (appearanceFilter()) appearanceFilter()->apply(widget); } QIcon MenuStyle::themedIcon(const QIcon& source, const QPalette& palette) { return source.isNull() ? QIcon() : QIcon(new MenuIconEngine(source, palette)); } QPalette MenuStyle::systemPalette(const QWidget* widget) { return fullyResolvedSystemPalette(widget); } QPalette MenuStyle::systemComboPopupPalette(const QComboBox* combo) { QStyleOptionComboBox option; option.initFrom(combo); option.editable = combo->isEditable(); const bool menu = QApplication::style()->styleHint(QStyle::SH_ComboBox_Popup, &option, combo); // macOS gives menus and lists different selection colors. A menu-style // dropdown must use the menu palette even though its view is a QListView. QPalette palette = menu ? QApplication::palette("QMenu") : QApplication::palette(combo->view()); if (menu) { if (const auto gtk = GtkMenuPalette::systemPalette(palette)) palette = *gtk; } return fullyResolvedPalette(palette); } void MenuStyle::setThemeColors(QMenu* menu, const QColor& background, const QColor& foreground, const QColor& selectedBackground, const QColor& selectedForeground) { if (menu == nullptr) return; const QVariantList colors {background, foreground, selectedBackground, selectedForeground}; const QString key = themeKey(); const auto save = [&colors, &key](QMenu* target) { target->setProperty(ThemeColorsProperty, colors); target->setProperty(ThemeSchemeProperty, key); }; save(menu); for (QMenu* child : menu->findChildren()) save(child); apply(menu); } heldercorreia-speedcrunch-e7ca37f/src/gui/menustyleutils.h000066400000000000000000000013021526573132500241630ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef SPEEDCRUNCH_MENUSTYLEUTILS_H #define SPEEDCRUNCH_MENUSTYLEUTILS_H #include class QMenu; class QIcon; class QComboBox; class QPalette; class QWidget; namespace MenuStyle { void install(); void refresh(); void apply(QWidget* widget); QIcon themedIcon(const QIcon& source, const QPalette& palette); QPalette systemPalette(const QWidget* widget); QPalette systemComboPopupPalette(const QComboBox* combo); void setThemeColors(QMenu* menu, const QColor& background, const QColor& foreground, const QColor& selectedBackground, const QColor& selectedForeground); } #endif heldercorreia-speedcrunch-e7ca37f/src/gui/notationandprecisiondialog.cpp000066400000000000000000000250171526573132500270330ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/notationandprecisiondialog.h" #include "core/settings.h" #include #include #include #include #include #include #include #include #include #include namespace { char notationFromComboData(const QVariant& data) { const QString value = data.toString(); return value.isEmpty() ? '\0' : value.at(0).toLatin1(); } QLabel* createHeaderLabel(const QString& text, QWidget* parent) { QLabel* label = new QLabel(text, parent); QFont font = label->font(); font.setBold(true); label->setFont(font); return label; } QComboBox* createNotationCombo(QWidget* parent) { QComboBox* combo = new QComboBox(parent); combo->setSizeAdjustPolicy(QComboBox::AdjustToContents); combo->addItem(QObject::tr("Automatic decimal"), QStringLiteral("g")); combo->addItem(QObject::tr("Fixed-point decimal"), QStringLiteral("f")); combo->addItem(QObject::tr("Engineering decimal"), QStringLiteral("n")); combo->addItem(QObject::tr("Scientific decimal"), QStringLiteral("e")); combo->insertSeparator(combo->count()); combo->addItem(QObject::tr("Rational"), QStringLiteral("r")); combo->addItem(QObject::tr("Binary"), QStringLiteral("b")); combo->addItem(QObject::tr("Octal"), QStringLiteral("o")); combo->addItem(QObject::tr("Hexadecimal"), QStringLiteral("h")); combo->addItem(QObject::tr("Sexagesimal"), QStringLiteral("s")); return combo; } } ResultSlotsDialog::ResultSlotsDialog(QWidget* parent) : QDialog(parent) , m_table(new QWidget(this)) { buildDialog(tr("Notation & Precision")); loadFromSettings(); loadRowsToUi(); finalizeSize(); } ResultSlotsDialog::ResultSlotsDialog(const QString& title, const EvaluationContext& context, QWidget* parent) : QDialog(parent) , m_table(new QWidget(this)) , m_applyToSettings(false) { buildDialog(title); loadFromEvaluationContext(context); loadRowsToUi(); finalizeSize(); } void ResultSlotsDialog::buildDialog(const QString& title) { setWindowTitle(title); QVBoxLayout* root = new QVBoxLayout(this); createTable(); root->addWidget(m_table); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); root->addWidget(buttons); connect(buttons, &QDialogButtonBox::accepted, this, [this]() { saveRowsToSlots(); if (m_applyToSettings) { applyToSettings(); emit settingsApplied(); } accept(); }); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); } void ResultSlotsDialog::finalizeSize() { m_table->setFixedSize(m_table->sizeHint()); setFixedSize(sizeHint()); } void ResultSlotsDialog::createTable() { QGridLayout* grid = new QGridLayout(m_table); grid->setColumnStretch(0, 0); grid->setColumnStretch(1, 0); grid->setColumnStretch(2, 0); grid->setColumnStretch(3, 0); grid->setHorizontalSpacing(12); grid->setVerticalSpacing(6); grid->addWidget(createHeaderLabel(tr("Result Line"), m_table), 0, 0); grid->addWidget(createHeaderLabel(tr("Enabled"), m_table), 0, 1); grid->addWidget(createHeaderLabel(tr("Notation"), m_table), 0, 2); grid->addWidget(createHeaderLabel(tr("Decimal Places"), m_table), 0, 3); const QStringList rowNames = { tr("Main Line"), tr("Extra Line #1"), tr("Extra Line #2"), tr("Extra Line #3"), tr("Extra Line #4") }; for (int row = 0; row < 5; ++row) { const int gridRow = row + 1; grid->addWidget(new QLabel(rowNames.at(row), m_table), gridRow, 0); RowWidgets widgets; widgets.enabled = new QCheckBox(m_table); widgets.enabled->setChecked(row == 0); widgets.enabled->setEnabled(row != 0); grid->addWidget(widgets.enabled, gridRow, 1, Qt::AlignCenter); widgets.notation = createNotationCombo(m_table); grid->addWidget(widgets.notation, gridRow, 2); QWidget* precisionWidget = new QWidget(m_table); QHBoxLayout* precisionLayout = new QHBoxLayout(precisionWidget); precisionLayout->setContentsMargins(0, 0, 0, 0); widgets.autoPrecision = new QCheckBox(tr("Auto"), precisionWidget); widgets.precision = new QSpinBox(precisionWidget); widgets.precision->setRange(0, 50); precisionLayout->addWidget(widgets.autoPrecision); precisionLayout->addWidget(widgets.precision); grid->addWidget(precisionWidget, gridRow, 3); m_rows[row] = widgets; connect(widgets.enabled, &QCheckBox::toggled, this, [this, row](bool enabled) { setRowControlsEnabled(row, enabled); }); connect(widgets.autoPrecision, &QCheckBox::toggled, this, [this, row](bool automatic) { m_rows[row].precision->setEnabled(m_rows[row].enabled->isChecked() && !automatic); }); } } void ResultSlotsDialog::loadFromSettings() { Settings* settings = Settings::instance(); m_slots[0].notation = settings->resultFormat; m_slots[0].precision = settings->resultPrecision; m_slots[0].complexForm = settings->resultComplexForm; m_slots[0].enabled = true; m_slots[1].notation = settings->alternativeResultFormat; m_slots[1].precision = settings->secondaryResultPrecision; m_slots[1].complexForm = settings->secondaryResultComplexForm; m_slots[1].enabled = settings->secondaryResultEnabled; m_slots[2].notation = settings->tertiaryResultFormat; m_slots[2].precision = settings->tertiaryResultPrecision; m_slots[2].complexForm = settings->tertiaryResultComplexForm; m_slots[2].enabled = settings->tertiaryResultEnabled; m_slots[3].notation = settings->quaternaryResultFormat; m_slots[3].precision = settings->quaternaryResultPrecision; m_slots[3].complexForm = settings->quaternaryResultComplexForm; m_slots[3].enabled = settings->quaternaryResultEnabled; m_slots[4].notation = settings->quinaryResultFormat; m_slots[4].precision = settings->quinaryResultPrecision; m_slots[4].complexForm = settings->quinaryResultComplexForm; m_slots[4].enabled = settings->quinaryResultEnabled; } void ResultSlotsDialog::loadFromEvaluationContext(const EvaluationContext& context) { m_slots[0].notation = context.main.fmt; m_slots[0].precision = context.main.prec; m_slots[0].complexForm = context.main.cplx; m_slots[0].enabled = true; for (int i = 1; i < 5; ++i) { m_slots[i] = SlotSettings(); m_slots[i].enabled = (i - 1) < context.extras.size(); if (m_slots[i].enabled) { const ResultLineContext& line = context.extras.at(i - 1); m_slots[i].notation = line.fmt; m_slots[i].precision = line.prec; m_slots[i].complexForm = line.cplx; } } } void ResultSlotsDialog::loadRowsToUi() { for (int row = 0; row < 5; ++row) { const SlotSettings& source = m_slots[row]; RowWidgets& widgets = m_rows[row]; widgets.enabled->setChecked(row == 0 ? true : source.enabled); const int notationIndex = widgets.notation->findData(QString(QChar(source.notation))); widgets.notation->setCurrentIndex(notationIndex >= 0 ? notationIndex : widgets.notation->findData(QStringLiteral("g"))); widgets.autoPrecision->setChecked(source.precision < 0); widgets.precision->setValue(source.precision < 0 ? 8 : source.precision); setRowControlsEnabled(row, widgets.enabled->isChecked()); } } void ResultSlotsDialog::saveRowsToSlots() { for (int row = 0; row < 5; ++row) { const RowWidgets& widgets = m_rows[row]; SlotSettings& target = m_slots[row]; target.enabled = (row == 0) ? true : widgets.enabled->isChecked(); target.notation = notationFromComboData(widgets.notation->currentData()); target.precision = widgets.autoPrecision->isChecked() ? -1 : widgets.precision->value(); } } void ResultSlotsDialog::applyToSettings() { Settings* settings = Settings::instance(); settings->multipleResultLinesEnabled = m_slots[1].enabled || m_slots[2].enabled || m_slots[3].enabled || m_slots[4].enabled; settings->complexNumbers = true; settings->resultFormat = m_slots[0].notation; settings->resultPrecision = m_slots[0].precision; settings->resultComplexForm = m_slots[0].complexForm; settings->alternativeResultFormat = m_slots[1].notation; settings->secondaryResultEnabled = m_slots[1].enabled; settings->secondaryResultPrecision = m_slots[1].precision; settings->secondaryComplexNumbers = true; settings->secondaryResultComplexForm = m_slots[1].complexForm; settings->tertiaryResultFormat = m_slots[2].notation; settings->tertiaryResultEnabled = m_slots[2].enabled; settings->tertiaryResultPrecision = m_slots[2].precision; settings->tertiaryComplexNumbers = true; settings->tertiaryResultComplexForm = m_slots[2].complexForm; settings->quaternaryResultFormat = m_slots[3].notation; settings->quaternaryResultEnabled = m_slots[3].enabled; settings->quaternaryResultPrecision = m_slots[3].precision; settings->quaternaryComplexNumbers = true; settings->quaternaryResultComplexForm = m_slots[3].complexForm; settings->quinaryResultFormat = m_slots[4].notation; settings->quinaryResultEnabled = m_slots[4].enabled; settings->quinaryResultPrecision = m_slots[4].precision; settings->quinaryComplexNumbers = true; settings->quinaryResultComplexForm = m_slots[4].complexForm; } EvaluationContext ResultSlotsDialog::evaluationContext(const EvaluationContext& baseContext) const { EvaluationContext context = baseContext; context.main.fmt = m_slots[0].notation; context.main.prec = m_slots[0].precision; context.main.cplx = m_slots[0].complexForm; context.complexOn = true; context.extras.clear(); for (int i = 1; i < 5; ++i) { if (!m_slots[i].enabled) continue; ResultLineContext line; line.fmt = m_slots[i].notation; line.prec = m_slots[i].precision; line.cplx = m_slots[i].complexForm; context.extras.append(line); } return context; } void ResultSlotsDialog::setRowControlsEnabled(int row, bool enabled) { RowWidgets& widgets = m_rows[row]; widgets.notation->setEnabled(enabled); widgets.autoPrecision->setEnabled(enabled); widgets.precision->setEnabled(enabled && !widgets.autoPrecision->isChecked()); } heldercorreia-speedcrunch-e7ca37f/src/gui/notationandprecisiondialog.h000066400000000000000000000027741526573132500265050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_RESULTSLOTSDIALOG_H #define GUI_RESULTSLOTSDIALOG_H #include "core/sessionhistory.h" #include #include class QCheckBox; class QComboBox; class QSpinBox; class QWidget; class ResultSlotsDialog : public QDialog { Q_OBJECT public: explicit ResultSlotsDialog(QWidget* parent = nullptr); ResultSlotsDialog(const QString& title, const EvaluationContext& context, QWidget* parent = nullptr); EvaluationContext evaluationContext(const EvaluationContext& baseContext) const; signals: void settingsApplied(); private: struct SlotSettings { char notation = '\0'; int precision = -1; char complexForm = ComplexForm::Default; bool enabled = true; }; struct RowWidgets { QCheckBox* enabled = nullptr; QComboBox* notation = nullptr; QCheckBox* autoPrecision = nullptr; QSpinBox* precision = nullptr; }; void buildDialog(const QString& title); void finalizeSize(); void createTable(); void loadFromSettings(); void loadFromEvaluationContext(const EvaluationContext& context); void loadRowsToUi(); void saveRowsToSlots(); void applyToSettings(); void setRowControlsEnabled(int row, bool enabled); QWidget* m_table; bool m_applyToSettings = true; std::array m_slots; std::array m_rows; }; #endif // GUI_RESULTSLOTSDIALOG_H heldercorreia-speedcrunch-e7ca37f/src/gui/numberformatdialog.cpp000066400000000000000000000065761526573132500253130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/numberformatdialog.h" #include #include #include #include #include NumberFormatDialog::NumberFormatDialog(QWidget* parent) : QDialog(parent) , m_styles(new QComboBox(this)) { setWindowTitle(tr("Number Format")); QVBoxLayout* layout = new QVBoxLayout(this); QLabel* intro = new QLabel( tr("Select the number format for results and input digit grouping.

    Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.
    "), this); intro->setWordWrap(true); layout->addWidget(intro); layout->setSizeConstraint(QLayout::SetFixedSize); auto addStyle = [this](Settings::NumberFormatStyle style, const QString& example) { m_styleItems.append(style); m_styles->addItem(example); }; addStyle(Settings::NumberFormatNoGroupingDot, QStringLiteral("1234567.12345")); addStyle(Settings::NumberFormatNoGroupingComma, QStringLiteral("1234567,12345")); addStyle(Settings::NumberFormatThreeDigitCommaDot, QStringLiteral("1,234,567.12345")); addStyle(Settings::NumberFormatThreeDigitDotComma, QStringLiteral("1.234.567,12345")); addStyle(Settings::NumberFormatThreeDigitSpaceDot, QStringLiteral("1 234 567.12345")); addStyle(Settings::NumberFormatThreeDigitSpaceComma, QStringLiteral("1 234 567,12345")); addStyle(Settings::NumberFormatSIDot, QStringLiteral("1 234 567.123 45")); addStyle(Settings::NumberFormatSIComma, QStringLiteral("1 234 567,123 45")); addStyle(Settings::NumberFormatThreeDigitCommaDotFraction, QStringLiteral("1,234,567.123,45")); addStyle(Settings::NumberFormatThreeDigitDotCommaFraction, QStringLiteral("1.234.567,123.45")); addStyle(Settings::NumberFormatThreeDigitUnderscoreDot, QStringLiteral("1_234_567.12345")); addStyle(Settings::NumberFormatThreeDigitUnderscoreComma, QStringLiteral("1_234_567,12345")); addStyle(Settings::NumberFormatThreeDigitUnderscoreDotFraction, QStringLiteral("1_234_567.123_45")); addStyle(Settings::NumberFormatThreeDigitUnderscoreCommaFraction, QStringLiteral("1_234_567,123_45")); addStyle(Settings::NumberFormatIndianCommaDot, QStringLiteral("12,34,567.12345")); layout->addWidget(m_styles); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); layout->addWidget(buttons); connect(m_styles, QOverload::of(&QComboBox::currentIndexChanged), this, [this](int index) { if (index >= 0 && index < m_styleItems.size()) emit selectionChanged(m_styleItems.at(index)); }); } void NumberFormatDialog::setSelection(Settings::NumberFormatStyle style) { const int index = m_styleItems.indexOf(style); if (index >= 0) m_styles->setCurrentIndex(index); else m_styles->setCurrentIndex(0); } Settings::NumberFormatStyle NumberFormatDialog::selectedStyle() const { const int index = m_styles->currentIndex(); if (index < 0 || index >= m_styleItems.size()) return Settings::NumberFormatNoGroupingDot; return m_styleItems.at(index); } heldercorreia-speedcrunch-e7ca37f/src/gui/numberformatdialog.h000066400000000000000000000012671526573132500247500ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_NUMBERFORMATDIALOG_H #define GUI_NUMBERFORMATDIALOG_H #include "core/settings.h" #include #include class QComboBox; class NumberFormatDialog : public QDialog { Q_OBJECT public: explicit NumberFormatDialog(QWidget* parent = nullptr); void setSelection(Settings::NumberFormatStyle style); Settings::NumberFormatStyle selectedStyle() const; signals: void selectionChanged(Settings::NumberFormatStyle style); private: QComboBox* m_styles; QVector m_styleItems; }; #endif // GUI_NUMBERFORMATDIALOG_H heldercorreia-speedcrunch-e7ca37f/src/gui/oklchutils.cpp000066400000000000000000001203641526573132500236030ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/oklchutils.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include namespace { // Pi is used only for OKLCH hue conversion between degrees and radians. Keeping // it local avoids pulling in non-standard constants from . constexpr double kPi = 3.14159265358979323846; // OKLCH hue wraps around a 360-degree circle. The normalization helper uses // this value to preserve hue continuity after modulo arithmetic. constexpr double kDegreesInCircle = 360.0; // WCAG thresholds used by the diagnostic report. constexpr double kAaMinimumContrast = 4.5; constexpr double kAaaMinimumContrast = 7.0; // Default percentage of the available lightness range used by shade generation. // For dark themes, right-side shades move this fraction toward white; for light // themes, right-side shades move this fraction toward black. constexpr double kDefaultShadeDistanceFactor = 0.090; // Default hue used when the background is too close to neutral to provide a // stable hue. 250 degrees is a blue-violet accent: familiar for focus/selection // affordances, but far enough from red/green/yellow semantic colors. constexpr double kDefaultPrimaryFallbackHueDegrees = 250.0; // Primary accents are generated from the background in OKLCH, because OKLCH // separates perceptual lightness, chroma, and hue more predictably than // HSL/HSV. In HSL/HSV, equal numeric lightness or saturation changes can look // very different across hues; OKLCH lets the theme code target readable // accents with deterministic lightness and chroma adjustments. constexpr double kNeutralBackgroundChromaThreshold = 0.02; constexpr double kPrimaryMinimumContrast = 3.0; constexpr double kPrimaryPreferredContrast = 4.5; constexpr double kDarkPrimaryLightness = 0.74; constexpr double kLightPrimaryLightness = 0.52; constexpr double kDarkPrimaryMaximumLightness = 0.86; constexpr double kLightPrimaryMinimumLightness = 0.36; constexpr double kSecondaryLinkMinimumHueDistance = 55.0; constexpr double kSecondaryLinkMinimumChroma = 0.025; constexpr double kSecondaryLinkMaximumChroma = 0.080; constexpr double kSecondaryLinkChromaStep = 0.005; // Chroma retention applied per shade step away from the base shade. This keeps // generated palettes from becoming over-saturated as lightness moves toward the // extremes while preserving hue as much as sRGB allows. constexpr double kDefaultShadeChromaDecay = 0.95; // The window shade sits on the opposite side of the base from the main generated // ramp. It gets an explicit chroma reduction so it stays visually quieter than // the result-display/base surface. constexpr double kWindowShadeChromaMultiplier = 0.50; // Tints below this OKLCH chroma are treated as visually neutral and skipped, so // foreground selection falls back to the black/white contrast path. constexpr double kMinimumVisibleTintChroma = 0.015; // Tiny tolerance for floating-point noise when checking whether linear sRGB // values are inside gamut before binary-search chroma fitting. constexpr double kGamutEpsilon = 1e-7; // Number of binary-search rounds used for chroma fitting and tinted foreground // lightness adjustment. Thirty-two rounds is deterministic and more precise // than QColor's 8-bit output can represent. constexpr int kBinarySearchIterations = 32; // Bjorn Ottosson's OKLab matrix from linear sRGB to LMS cone responses. constexpr double kLinearSrgbToLms[3][3] = { {0.4122214708, 0.5363325363, 0.0514459929}, {0.2119034982, 0.6806995451, 0.1073969566}, {0.0883024619, 0.2817188376, 0.6299787005} }; // Bjorn Ottosson's OKLab matrix from cube-root LMS to OKLab coordinates. constexpr double kLmsToOklab[3][3] = { {0.2104542553, 0.7936177850, -0.0040720468}, {1.9779984951, -2.4285922050, 0.4505937099}, {0.0259040371, 0.7827717662, -0.8086757660} }; // Inverse OKLab matrix from OKLab coordinates back to cube-root LMS. constexpr double kOklabToLms[3][3] = { {1.0, 0.3963377774, 0.2158037573}, {1.0, -0.1055613458, -0.0638541728}, {1.0, -0.0894841775, -1.2914855480} }; // Final inverse OKLab matrix from cubed LMS responses back to linear sRGB. constexpr double kLmsToLinearSrgb[3][3] = { {4.0767416621, -3.3077115913, 0.2309699292}, {-1.2684380046, 2.6097574011, -0.3413193965}, {-0.0041960863, -0.7034186147, 1.7076147010} }; struct LinearSrgb { double r; double g; double b; }; struct Oklab { double l; double a; double b; double alpha; }; double clamp(double value, double minimum, double maximum) { return std::max(minimum, std::min(maximum, value)); } double normalizedHue(double hue) { double result = std::fmod(hue, kDegreesInCircle); if (result < 0.0) result += kDegreesInCircle; return result; } Oklch sanitizedOklch(const Oklch& color) { return { clamp(color.l, 0.0, 1.0), std::max(0.0, color.c), normalizedHue(color.h), clamp(color.alpha, 0.0, 1.0) }; } double srgbToLinear(double channel) { return channel <= 0.04045 ? channel / 12.92 : std::pow((channel + 0.055) / 1.055, 2.4); } double linearToSrgb(double channel) { return channel <= 0.0031308 ? 12.92 * channel : 1.055 * std::pow(channel, 1.0 / 2.4) - 0.055; } Oklab oklchToOklab(const Oklch& color) { const double radians = color.h * kPi / 180.0; return { color.l, color.c * std::cos(radians), color.c * std::sin(radians), color.alpha }; } LinearSrgb oklabToLinearSrgb(const Oklab& color) { const double lRoot = kOklabToLms[0][0] * color.l + kOklabToLms[0][1] * color.a + kOklabToLms[0][2] * color.b; const double mRoot = kOklabToLms[1][0] * color.l + kOklabToLms[1][1] * color.a + kOklabToLms[1][2] * color.b; const double sRoot = kOklabToLms[2][0] * color.l + kOklabToLms[2][1] * color.a + kOklabToLms[2][2] * color.b; const double l = lRoot * lRoot * lRoot; const double m = mRoot * mRoot * mRoot; const double s = sRoot * sRoot * sRoot; return { kLmsToLinearSrgb[0][0] * l + kLmsToLinearSrgb[0][1] * m + kLmsToLinearSrgb[0][2] * s, kLmsToLinearSrgb[1][0] * l + kLmsToLinearSrgb[1][1] * m + kLmsToLinearSrgb[1][2] * s, kLmsToLinearSrgb[2][0] * l + kLmsToLinearSrgb[2][1] * m + kLmsToLinearSrgb[2][2] * s }; } LinearSrgb oklchToLinearSrgb(const Oklch& color) { return oklabToLinearSrgb(oklchToOklab(color)); } bool isLinearSrgbInGamut(const LinearSrgb& color) { return color.r >= -kGamutEpsilon && color.r <= 1.0 + kGamutEpsilon && color.g >= -kGamutEpsilon && color.g <= 1.0 + kGamutEpsilon && color.b >= -kGamutEpsilon && color.b <= 1.0 + kGamutEpsilon; } QColor colorFromLinearSrgb(const LinearSrgb& color, double alpha) { return QColor::fromRgbF( clamp(linearToSrgb(clamp(color.r, 0.0, 1.0)), 0.0, 1.0), clamp(linearToSrgb(clamp(color.g, 0.0, 1.0)), 0.0, 1.0), clamp(linearToSrgb(clamp(color.b, 0.0, 1.0)), 0.0, 1.0), clamp(alpha, 0.0, 1.0)); } Oklch fitOklchToSrgb(const Oklch& source) { Oklch candidate = sanitizedOklch(source); if (isLinearSrgbInGamut(oklchToLinearSrgb(candidate))) return candidate; double lowerChroma = 0.0; double upperChroma = candidate.c; for (int i = 0; i < kBinarySearchIterations; ++i) { const double chroma = (lowerChroma + upperChroma) / 2.0; Oklch attempt = candidate; attempt.c = chroma; if (isLinearSrgbInGamut(oklchToLinearSrgb(attempt))) lowerChroma = chroma; else upperChroma = chroma; } candidate.c = lowerChroma; return candidate; } double relativeLuminance(const QColor& color) { const QColor rgb = color.toRgb(); return 0.2126 * srgbToLinear(rgb.redF()) + 0.7152 * srgbToLinear(rgb.greenF()) + 0.0722 * srgbToLinear(rgb.blueF()); } double contrastRatio(const QColor& first, const QColor& second) { const double firstLuminance = relativeLuminance(first); const double secondLuminance = relativeLuminance(second); const double lighter = std::max(firstLuminance, secondLuminance); const double darker = std::min(firstLuminance, secondLuminance); return (lighter + 0.05) / (darker + 0.05); } QColor eightBitColor(const QColor& color) { return QColor(color.red(), color.green(), color.blue(), color.alpha()); } bool meetsTextContrast(const QColor& foreground, const QColor& background, double minimumContrast) { // Stylesheets use eight-bit hex colors. Check both rendering paths. return contrastRatio(foreground, background) >= minimumContrast && contrastRatio(foreground, eightBitColor(background)) >= minimumContrast; } QColor bestBlackOrWhiteForeground(const QColor& background) { const QColor black(Qt::black); const QColor white(Qt::white); return contrastRatio(background, black) >= contrastRatio(background, white) ? black : white; } QColor primaryColorFromOklch(const Oklch& color) { const Oklch fitted = fitOklchToSrgb(color); return colorFromLinearSrgb(oklchToLinearSrgb(fitted), fitted.alpha); } QColor contrastFallbackPrimary(const QColor& background) { const QColor fallback = bestBlackOrWhiteForeground(background); if (fallback == QColor(Qt::white)) return QColor(QStringLiteral("#f5f5f5")); if (fallback == QColor(Qt::black)) return QColor(QStringLiteral("#111111")); return fallback; } double hueDistance(double first, double second) { const double difference = std::abs(normalizedHue(first) - normalizedHue(second)); return std::min(difference, kDegreesInCircle - difference); } bool isDistinctHue(double hue, const std::optional& avoidedHue) { return !avoidedHue.has_value() || hueDistance(hue, avoidedHue.value()) >= kSecondaryLinkMinimumHueDistance; } void appendDistinctHueCandidate(QVector& hues, double hue, const std::optional& avoidedHue) { const double normalized = normalizedHue(hue); if (!isDistinctHue(normalized, avoidedHue)) return; const auto existing = std::find_if(hues.cbegin(), hues.cend(), [normalized](double candidate) { return hueDistance(candidate, normalized) < 0.5; }); if (existing == hues.cend()) hues.append(normalized); } QVector secondaryLinkHueCandidates(double preferredHue, const std::optional& avoidedHue) { QVector hues; appendDistinctHueCandidate(hues, preferredHue, avoidedHue); if (avoidedHue.has_value()) { const double avoided = avoidedHue.value(); appendDistinctHueCandidate(hues, avoided + kSecondaryLinkMinimumHueDistance, avoidedHue); appendDistinctHueCandidate(hues, avoided - kSecondaryLinkMinimumHueDistance, avoidedHue); for (double offset = 75.0; offset <= 180.0; offset += 15.0) { appendDistinctHueCandidate(hues, avoided + offset, avoidedHue); appendDistinctHueCandidate(hues, avoided - offset, avoidedHue); } } for (double hue = 0.0; hue < kDegreesInCircle; hue += 15.0) appendDistinctHueCandidate(hues, hue, avoidedHue); std::sort(hues.begin(), hues.end(), [preferredHue](double first, double second) { return hueDistance(first, preferredHue) < hueDistance(second, preferredHue); }); return hues; } QColor readableLinkCandidate(const QColor& background, double hue, double chroma, double minimumContrast) { const Oklch backgroundOklch = qColorToOklch(background); const bool dark = themePolarityForBackground(background) == ThemePolarity::Dark; double failingLightness = backgroundOklch.l; double passingLightness = dark ? 1.0 : 0.0; auto candidateForLightness = [hue, chroma](double lightness) { return eightBitColor(oklchToValidSrgbQColor({lightness, chroma, hue, 1.0})); }; if (!meetsTextContrast(candidateForLightness(passingLightness), background, minimumContrast)) return QColor(); QColor passingCandidate = candidateForLightness(passingLightness); for (int i = 0; i < kBinarySearchIterations; ++i) { const double attemptLightness = (failingLightness + passingLightness) / 2.0; const QColor attempt = candidateForLightness(attemptLightness); if (meetsTextContrast(attempt, background, minimumContrast)) { passingLightness = attemptLightness; passingCandidate = attempt; } else { failingLightness = attemptLightness; } } return passingCandidate; } double shadeLightnessForIndex(double baseLightness, int index, ThemePolarity polarity, double distanceFactor) { const double factor = clamp(distanceFactor, 0.0, 1.0); if (index <= 0) { return polarity == ThemePolarity::Dark ? baseLightness * (1.0 - factor) : baseLightness + ((1.0 - baseLightness) * factor); } if (index == 1) return baseLightness; const double percentage = clamp(factor * (index - 1), 0.0, 1.0); return polarity == ThemePolarity::Dark ? baseLightness + ((1.0 - baseLightness) * percentage) : baseLightness * (1.0 - percentage); } double shadeChromaMultiplierForIndex(int index) { if (index <= 0) return kWindowShadeChromaMultiplier; if (index == 1) return 1.0; return std::pow(kDefaultShadeChromaDecay, index - 1); } QString debugColorHex(const QColor& color) { if (!color.isValid()) return QStringLiteral(""); const QColor::NameFormat format = color.alpha() == 255 ? QColor::HexRgb : QColor::HexArgb; return color.name(format).toUpper(); } QString htmlColorDetails(const QColor& color) { if (!color.isValid()) return QStringLiteral("<invalid>"); const Oklch converted = qColorToOklch(color); return QStringLiteral( "%1rgb(%2 %3 %4)oklch(%5 %6 %7)") .arg(debugColorHex(color).toHtmlEscaped()) .arg(color.red()) .arg(color.green()) .arg(color.blue()) .arg(converted.l, 0, 'f', 3) .arg(converted.c, 0, 'f', 3) .arg(converted.h, 0, 'f', 1); } QString htmlStatusLine(const QString& label, bool passed) { return QStringLiteral("

    %1%2: %3

    ") .arg(passed ? QStringLiteral("✔") : QStringLiteral("✖"), label, passed ? QStringLiteral("PASS") : QStringLiteral("FAIL")); } bool retainsVisibleTint(const Oklch& fitted, const Oklch& original) { return original.c >= kMinimumVisibleTintChroma && fitted.c >= kMinimumVisibleTintChroma; } QColor tintedAaForegroundForBackground(const QColor& background, const QColor& preferredTint, double minimumContrast) { if (!background.isValid() || !preferredTint.isValid()) return QColor(); const Oklch originalTint = qColorToOklch(preferredTint); if (originalTint.c < kMinimumVisibleTintChroma) return QColor(); const auto meetsContrast = [&](const QColor& foreground) { return meetsTextContrast(foreground, background, minimumContrast); }; const auto foregroundForTint = [](const Oklch& tint) { const QColor color = colorFromLinearSrgb(oklchToLinearSrgb(tint), tint.alpha); return eightBitColor(color); }; Oklch fittedTint = fitOklchToSrgb(originalTint); QColor candidate = foregroundForTint(fittedTint); if (retainsVisibleTint(fittedTint, originalTint) && meetsContrast(candidate)) { return candidate; } const double targetLightness = bestBlackOrWhiteForeground(background) == QColor(Qt::white) ? 1.0 : 0.0; double failingLightness = originalTint.l; double passingLightness = targetLightness; QColor passingCandidate; Oklch passingTint = originalTint; for (int i = 0; i < kBinarySearchIterations; ++i) { Oklch attempt = originalTint; attempt.l = (failingLightness + passingLightness) / 2.0; const Oklch fitted = fitOklchToSrgb(attempt); const QColor foreground = foregroundForTint(fitted); if (meetsContrast(foreground)) { passingLightness = attempt.l; passingTint = fitted; passingCandidate = foreground; } else { failingLightness = attempt.l; } } if (passingCandidate.isValid() && retainsVisibleTint(passingTint, originalTint)) return passingCandidate; return QColor(); } } // namespace Oklch qColorToOklch(const QColor& color) { if (!color.isValid()) return {0.0, 0.0, 0.0, 0.0}; const QColor rgb = color.toRgb(); const double r = srgbToLinear(rgb.redF()); const double g = srgbToLinear(rgb.greenF()); const double b = srgbToLinear(rgb.blueF()); const double l = std::cbrt( kLinearSrgbToLms[0][0] * r + kLinearSrgbToLms[0][1] * g + kLinearSrgbToLms[0][2] * b); const double m = std::cbrt( kLinearSrgbToLms[1][0] * r + kLinearSrgbToLms[1][1] * g + kLinearSrgbToLms[1][2] * b); const double s = std::cbrt( kLinearSrgbToLms[2][0] * r + kLinearSrgbToLms[2][1] * g + kLinearSrgbToLms[2][2] * b); const double oklabL = kLmsToOklab[0][0] * l + kLmsToOklab[0][1] * m + kLmsToOklab[0][2] * s; const double oklabA = kLmsToOklab[1][0] * l + kLmsToOklab[1][1] * m + kLmsToOklab[1][2] * s; const double oklabB = kLmsToOklab[2][0] * l + kLmsToOklab[2][1] * m + kLmsToOklab[2][2] * s; const double chroma = std::hypot(oklabA, oklabB); const double hue = chroma < 1e-12 ? 0.0 : normalizedHue(std::atan2(oklabB, oklabA) * 180.0 / kPi); return {oklabL, chroma, hue, rgb.alphaF()}; } QColor oklchToQColor(const Oklch& color) { const Oklch sanitized = sanitizedOklch(color); return colorFromLinearSrgb(oklchToLinearSrgb(sanitized), sanitized.alpha); } QColor oklchToValidSrgbQColor(const Oklch& color) { const Oklch fitted = fitOklchToSrgb(color); return colorFromLinearSrgb(oklchToLinearSrgb(fitted), fitted.alpha); } ThemePolarity themePolarityForBackground(const QColor& background) { // Theme polarity follows OKLCH lightness, not sRGB channel averages, so the // generated surfaces and accents use the same perceptual light/dark split. return qColorToOklch(background).l < 0.50 ? ThemePolarity::Dark : ThemePolarity::Light; } QColor generatePrimaryFromBackground(const QColor& background, std::optional fallbackHueDegrees) { if (!background.isValid()) return QColor(); const Oklch backgroundOklch = qColorToOklch(background); const ThemePolarity polarity = themePolarityForBackground(background); const bool dark = polarity == ThemePolarity::Dark; // Hue is preserved for chromatic backgrounds so the generated accent feels // related to the chosen theme instead of introducing an unrelated brand // color. Near-neutral backgrounds have an unstable OKLCH hue, so they use a // configurable fallback hue before applying the same chroma/lightness rules. const double hue = backgroundOklch.c < kNeutralBackgroundChromaThreshold ? normalizedHue(fallbackHueDegrees.value_or(kDefaultPrimaryFallbackHueDegrees)) : backgroundOklch.h; // Accent colors deliberately use more chroma than the background so focus, // selection, and checked-state affordances read as active controls rather // than as another quiet surface. Dark and light themes need different fixed // lightness targets: dark themes require a lighter accent, while light // themes require a darker one. Oklch primary { dark ? kDarkPrimaryLightness : kLightPrimaryLightness, dark ? clamp(std::max(backgroundOklch.c * 2.5, 0.10), 0.10, 0.18) : clamp(std::max(backgroundOklch.c * 2.0, 0.09), 0.09, 0.16), hue, 1.0 }; // sRGB cannot represent every OKLCH coordinate. Gamut fitting preserves hue // and lightness and reduces chroma, because hue carries theme identity and // lightness carries contrast; reducing chroma is the least disruptive way to // keep the color displayable. QColor candidate = primaryColorFromOklch(primary); if (contrastRatio(candidate, background) >= kPrimaryPreferredContrast) return candidate; const double lightnessLimit = dark ? kDarkPrimaryMaximumLightness : kLightPrimaryMinimumLightness; Oklch limitPrimary = primary; limitPrimary.l = lightnessLimit; QColor limitCandidate = primaryColorFromOklch(limitPrimary); const double targetContrast = contrastRatio(limitCandidate, background) >= kPrimaryPreferredContrast ? kPrimaryPreferredContrast : kPrimaryMinimumContrast; if (contrastRatio(limitCandidate, background) >= targetContrast) { // Move lightness only as far as needed to reach the target contrast. // This keeps the generated primary recognizably tied to the fixed // accent target while still satisfying readability requirements. double failingLightness = primary.l; double passingLightness = lightnessLimit; QColor passingCandidate = limitCandidate; for (int i = 0; i < kBinarySearchIterations; ++i) { Oklch attempt = primary; attempt.l = (failingLightness + passingLightness) / 2.0; const QColor attemptColor = primaryColorFromOklch(attempt); if (contrastRatio(attemptColor, background) >= targetContrast) { passingLightness = attempt.l; passingCandidate = attemptColor; } else { failingLightness = attempt.l; } } return passingCandidate; } primary.l = lightnessLimit; QColor bestCandidate = limitCandidate; double bestContrast = contrastRatio(bestCandidate, background); for (int i = 0; i < 8; ++i) { primary.c *= 0.85; candidate = primaryColorFromOklch(primary); const double contrast = contrastRatio(candidate, background); if (contrast > bestContrast) { bestContrast = contrast; bestCandidate = candidate; } if (contrast >= kPrimaryMinimumContrast) return candidate; } if (bestContrast >= kPrimaryMinimumContrast) return bestCandidate; // This is intentionally last-resort: black/white-like colors are less // expressive as accents, but a readable primary is preferable to preserving // chroma when an extreme input color defeats the bounded OKLCH adjustment. return contrastFallbackPrimary(background); } QColor generateSecondaryLinkFromBackground(const QColor& background, const QColor& primaryLink, double minimumContrast) { if (!background.isValid()) return QColor(); const Oklch backgroundOklch = qColorToOklch(background); const Oklch primaryLinkOklch = qColorToOklch(primaryLink); const std::optional avoidedHue = primaryLink.isValid() && primaryLinkOklch.c >= kMinimumVisibleTintChroma ? std::optional(primaryLinkOklch.h) : std::nullopt; const double preferredHue = backgroundOklch.c < kNeutralBackgroundChromaThreshold ? avoidedHue.value_or(kDefaultPrimaryFallbackHueDegrees) : backgroundOklch.h; const QVector hues = secondaryLinkHueCandidates(preferredHue, avoidedHue); QColor bestCandidate; double bestScore = std::numeric_limits::max(); for (double chroma = kSecondaryLinkMinimumChroma; chroma <= kSecondaryLinkMaximumChroma + 0.0001; chroma += kSecondaryLinkChromaStep) { for (const double hue : hues) { const QColor candidate = readableLinkCandidate( background, hue, chroma, minimumContrast); if (!candidate.isValid()) continue; const Oklch candidateOklch = qColorToOklch(candidate); if (candidateOklch.c < kMinimumVisibleTintChroma) continue; if (avoidedHue.has_value() && !isDistinctHue(candidateOklch.h, avoidedHue)) { continue; } // Rank by requested chroma so eight-bit rounding cannot outweigh // the theme's hue preference among equally muted candidates. const double score = chroma * 1000.0 + hueDistance(candidateOklch.h, preferredHue) / kDegreesInCircle + std::abs(candidateOklch.l - backgroundOklch.l) * 0.01; if (score < bestScore) { bestScore = score; bestCandidate = candidate; } } if (bestCandidate.isValid()) return bestCandidate; } return aaForegroundForBackground(background, minimumContrast); } double defaultOklchShadeDistanceFactor() { return kDefaultShadeDistanceFactor; } QVector generateOklchShades(const QColor& base, int count, ThemePolarity polarity) { return generateOklchShades(base, count, polarity, kDefaultShadeDistanceFactor); } QVector generateOklchShades(const QColor& base, int count, ThemePolarity polarity, double distanceFactor) { QVector shades; if (count <= 0) return shades; shades.reserve(count); const Oklch anchor = qColorToOklch(base); if (count == 1) { shades.append(oklchToValidSrgbQColor(anchor)); return shades; } for (int i = 0; i < count; ++i) { Oklch shade = anchor; shade.l = clamp(shadeLightnessForIndex(anchor.l, i, polarity, distanceFactor), 0.0, 1.0); shade.c = anchor.c * shadeChromaMultiplierForIndex(i); shades.append(oklchToValidSrgbQColor(shade)); } return shades; } QColor aaForegroundForBackground(const QColor& background, double minimumContrast) { return aaForegroundForBackground(background, background, minimumContrast); } QColor aaForegroundForBackground(const QColor& background, const QColor& preferredTint, double minimumContrast) { const QColor tinted = tintedAaForegroundForBackground( background, preferredTint, minimumContrast); if (tinted.isValid()) return tinted; return bestBlackOrWhiteForeground(background); } QVector aaForegroundsForBackgrounds(const QVector& backgrounds, double minimumContrast) { QVector foregrounds; foregrounds.reserve(backgrounds.size()); for (const QColor& background : backgrounds) foregrounds.append(aaForegroundForBackground(background, minimumContrast)); return foregrounds; } QVector aaForegroundsForBackgrounds(const QVector& backgrounds, const QColor& preferredTint, double minimumContrast) { QVector foregrounds; foregrounds.reserve(backgrounds.size()); for (const QColor& background : backgrounds) { foregrounds.append( aaForegroundForBackground(background, preferredTint, minimumContrast)); } return foregrounds; } QString writeOklchGenerationHtmlReport(const QColor& base, int leftShadeCount, int rightShadeCount, ThemePolarity polarity, double distanceFactor, bool requireAllWcag, const QVector& backgrounds, const QVector& foregrounds, double minimumContrast) { if (!UiConfig::OklchThemeDebugReportEnabled) return QString(); const QString reportPath = QDir(QDir::tempPath()).absoluteFilePath( QStringLiteral("speedcrunch-oklch-theme-report.html")); QFile file(reportPath); if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) return QString(); const QString polarityName = polarity == ThemePolarity::Dark ? QStringLiteral("DARK") : QStringLiteral("LIGHT"); const QString executablePath = QCoreApplication::applicationFilePath(); QTextStream out(&file); out << R"HTML( OKLCH Shade Stripes

    Color scale tool

    OKLCH shade stripes

    Move each shade by a percentage of the remaining OKLCH lightness range while preserving hue and decaying chroma away from the anchor.

    Generated by: )HTML" << executablePath.toHtmlEscaped() << R"HTML(

    )HTML"; out << " \n" << " \n" << " \n" << R"HTML(
    )HTML" << " \n" << R"HTML(
    )HTML" << " \n" << R"HTML(
    Theme polarity \n" << R"HTML( \n" << R"HTML(
    )HTML" << " \n" << R"HTML(
    \n" << " Targets " << (requireAllWcag ? "AAA" : "AA") << " text contrast; shade colors stay fixed.\n" << R"HTML(

    Generated stripes

    )HTML" << backgrounds.size() << " " << (backgrounds.size() == 1 ? "stripe" : "stripes") << " | " << polarityName << " | factor " << QString::number(distanceFactor, 'f', 2) << " | " << (requireAllWcag ? "AAA REQUIRED" : "AA REQUIRED") << R"HTML(

    )HTML"; for (int index = 0; index < backgrounds.size(); ++index) { const QColor background = backgrounds.at(index); const QColor foreground = foregrounds.value(index); const double contrast = foreground.isValid() ? contrastRatio(background, foreground) : 0.0; const bool isBase = index == leftShadeCount; out << "
    \n" << "

    " << (index + 1) * 100 << "

    " << (isBase ? "

    Base

    " : "") << "
    \n" << "
    \n" << "

    " << htmlColorDetails(background) << "

    \n" << "

    Foreground: " << debugColorHex(foreground).toHtmlEscaped() << "

    \n" << "
    \n" << "

    WCAG: " << QString::number(contrast, 'f', 2) << ":1

    \n" << " " << htmlStatusLine(QStringLiteral("AA"), contrast >= kAaMinimumContrast) << "\n" << " " << htmlStatusLine(QStringLiteral("AALarge"), contrast >= 3.0) << "\n" << " " << htmlStatusLine(QStringLiteral("AAA"), contrast >= kAaaMinimumContrast) << "\n" << " " << htmlStatusLine(QStringLiteral("AAALarge"), contrast >= kAaMinimumContrast) << "\n" << "
    \n" << "
    \n" << "
    \n"; } out << R"HTML(
    )HTML"; file.close(); return reportPath; } heldercorreia-speedcrunch-e7ca37f/src/gui/oklchutils.h000066400000000000000000000052431526573132500232460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef OKLCHUTILS_H #define OKLCHUTILS_H #include "gui/uiconfig.h" #include #include #include #include enum class ThemePolarity { Light, Dark }; struct Oklch { double l; double c; double h; double alpha; }; Oklch qColorToOklch(const QColor& color); QColor oklchToQColor(const Oklch& color); QColor oklchToValidSrgbQColor(const Oklch& color); ThemePolarity themePolarityForBackground(const QColor& background); QColor generatePrimaryFromBackground( const QColor& background, std::optional fallbackHueDegrees = std::nullopt); QColor generateSecondaryLinkFromBackground(const QColor& background, const QColor& primaryLink, double minimumContrast = UiConfig::GeneratedTextMinimumContrast); double defaultOklchShadeDistanceFactor(); QVector generateOklchShades(const QColor& base, int count, ThemePolarity polarity); QVector generateOklchShades(const QColor& base, int count, ThemePolarity polarity, double distanceFactor); QColor aaForegroundForBackground(const QColor& background, double minimumContrast = UiConfig::GeneratedTextMinimumContrast); QColor aaForegroundForBackground(const QColor& background, const QColor& preferredTint, double minimumContrast = UiConfig::GeneratedTextMinimumContrast); QVector aaForegroundsForBackgrounds( const QVector& backgrounds, double minimumContrast = UiConfig::GeneratedTextMinimumContrast); QVector aaForegroundsForBackgrounds( const QVector& backgrounds, const QColor& preferredTint, double minimumContrast = UiConfig::GeneratedTextMinimumContrast); QString writeOklchGenerationHtmlReport(const QColor& base, int leftShadeCount, int rightShadeCount, ThemePolarity polarity, double distanceFactor, bool requireAllWcag, const QVector& backgrounds, const QVector& foregrounds, double minimumContrast = 7.0); #endif // OKLCHUTILS_H heldercorreia-speedcrunch-e7ca37f/src/gui/resultdisplay.cpp000066400000000000000000002544611526573132500243340ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2011, 2013-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/startupdiagnostics.h" #include "gui/resultdisplay.h" #include "gui/startupappearance.h" #include "gui/menustyleutils.h" #include "gui/displayformatutils.h" #include "gui/resultlineformatutils.h" #include "gui/oklchutils.h" #include "core/functions.h" #include "core/numberformatter.h" #include "core/regexpatterns.h" #include "core/settings.h" #include "core/units.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include "gui/simplifiedexpressionutils.h" #include "gui/syntaxhighlighter.h" #include "gui/tooltipstyleutils.h" #include "gui/uiconfig.h" #include "math/cmath.h" #include "math/floatnum/floatconfig.h" #include "core/evaluator.h" #include "core/session.h" #include "core/sessionhistory.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { constexpr int kResultDisplayHorizontalPadding = UiConfig::ModernEditorHorizontalMargin; constexpr int kResultDisplayFadeHeight = 28; struct ResultDisplayScrollBarColors { QColor track; QColor thumb; QColor hoverThumb; QColor pressedThumb; }; struct ScrollToBottomButtonColors { QColor background; QColor foreground; QColor hoverBackground; QColor hoverForeground; QColor outline; }; QPointF badgeCenter(const QRect& rect) { return QPointF(rect.x() + rect.width() * 0.5, rect.y() + rect.height() * 0.5); } QColor hoverColorForBackground(const QColor& background) { const bool isLightBackground = background.lightnessF() >= 0.5; const QColor target = isLightBackground ? QColor(Qt::black) : QColor(Qt::white); const qreal blendFactor = 0.12; // subtle, but always visible even on pure black/white backgrounds auto mixChannel = [blendFactor](int from, int to) { return qBound(0, static_cast(from + (to - from) * blendFactor), 255); }; return QColor(mixChannel(background.red(), target.red()), mixChannel(background.green(), target.green()), mixChannel(background.blue(), target.blue())); } QVector resultDisplayShadesFromBackground(const QColor& background) { const QColor base = background.isValid() ? background : QApplication::palette().color(QPalette::Base); return generateOklchShades(base, UiConfig::Shade500 + 1, themePolarityForBackground(base)); } QColor shadeOrFallback(const QVector& shades, int index, const QColor& fallback) { return shades.value(index, fallback); } ResultDisplayScrollBarColors scrollBarColorsForResultBackground(const QColor& background) { const QVector shades = resultDisplayShadesFromBackground(background); // Result-display scrollbar colors are generated from the result background // itself: the track stays on the result surface, while the thumb advances // through the same OKLCH shade steps used elsewhere for normal, hovered, // and pressed scrollbar states. This keeps scrollbars independent from any // obsolete color-scheme role while preserving the existing shade semantics. const QColor track = shadeOrFallback(shades, UiConfig::ResultDisplayShade, background); const QColor thumb = shadeOrFallback(shades, UiConfig::ResultDisplayScrollbarShade, track); const QColor hoverThumb = shadeOrFallback(shades, UiConfig::ResultDisplayScrollbarHoverShade, thumb); const QColor pressedThumb = shadeOrFallback(shades, UiConfig::ResultDisplayScrollbarPressedShade, hoverThumb); return { track, thumb, hoverThumb, pressedThumb }; } ScrollToBottomButtonColors scrollToBottomButtonColorsForResultBackground(const QColor& background) { const QVector shades = resultDisplayShadesFromBackground(background); const QColor normalBackground = shadeOrFallback(shades, UiConfig::ScrollToBottomButtonBackgroundShade, background); const QColor hoverBackground = shadeOrFallback(shades, UiConfig::ScrollToBottomButtonHoverBackgroundShade, normalBackground); const QColor outline = shadeOrFallback(shades, UiConfig::ScrollToBottomButtonOutlineShade, hoverBackground); return { normalBackground, aaForegroundForBackground(normalBackground), hoverBackground, aaForegroundForBackground(hoverBackground), outline }; } QIcon downArrowIcon(const QColor& color) { QPixmap pixmap(16, 16); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(Qt::NoPen); painter.setBrush(color); painter.drawPolygon(QPolygonF{ QPointF(3.5, 5.5), QPointF(12.5, 5.5), QPointF(8.0, 11.0) }); return QIcon(pixmap); } void applyContextMenuTheme(QMenu* menu, const QColor& background, const QColor& foreground, const QColor& hoverBackground, const QColor& hoverForeground) { const QColor effectiveHoverBackground = hoverBackground.isValid() ? hoverBackground : background; const QColor effectiveHoverForeground = hoverForeground.isValid() ? hoverForeground : foreground; if (background.isValid() && foreground.isValid()) MenuStyle::setThemeColors(menu, background, foreground, effectiveHoverBackground, effectiveHoverForeground); else MenuStyle::apply(menu); } int maxRenderedHistoryEntries(const Session* session) { static const int kDefaultMaxRenderedHistoryEntries = 800; const int configuredLimit = session != nullptr ? session->historyLimit() : 0; if (configuredLimit > 0) return qMin(configuredLimit, kDefaultMaxRenderedHistoryEntries); return kDefaultMaxRenderedHistoryEntries; } int firstDisplayedHistoryIndexForCount(int historyCount, const Session* session) { return qMax(0, historyCount - maxRenderedHistoryEntries(session)); } void cloneMenuActions(const QMenu* sourceMenu, QMenu* targetMenu) { const QList sourceActions = sourceMenu->actions(); for (QAction* sourceAction : sourceActions) { if (sourceAction->isSeparator()) { targetMenu->addSeparator(); continue; } QMenu* sourceSubmenu = sourceAction->menu(); if (sourceSubmenu != 0) { QMenu* clonedSubmenu = targetMenu->addMenu(sourceSubmenu->title()); clonedSubmenu->setEnabled(sourceAction->isEnabled()); cloneMenuActions(sourceSubmenu, clonedSubmenu); continue; } targetMenu->addAction(sourceAction); } } QString formatResultForClipboard(const Quantity& value) { QString textToCopy = NumberFormatter::format(value); textToCopy.replace( RegExpPatterns::missingQuantSpBeforeUnit(), QStringLiteral("\\1") + QString(MathDsl::QuantSp) + QString(MathDsl::UnitStart)); textToCopy.replace(UnicodeChars::MinusSign, MathDsl::SubOpAl1); return textToCopy; } QStringList formatResultLines(const HistoryEntry& entry, const Evaluator* evaluator) { Settings* settings = Settings::instance(); const bool oldComplexNumbers = settings->complexNumbers; const char oldImaginaryUnit = settings->imaginaryUnit; const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; const char oldResultComplexForm = settings->resultComplexForm; const char oldUnitExp = settings->unitNegativeExponentStyle; const char oldRound = settings->resultRoundingMode; const bool oldMultiple = settings->multipleResultLinesEnabled; const bool oldSecondaryEnabled = settings->secondaryResultEnabled; const bool oldTertiaryEnabled = settings->tertiaryResultEnabled; const bool oldQuaternaryEnabled = settings->quaternaryResultEnabled; const bool oldQuinaryEnabled = settings->quinaryResultEnabled; const char oldSecondaryFormat = settings->alternativeResultFormat; const char oldTertiaryFormat = settings->tertiaryResultFormat; const char oldQuaternaryFormat = settings->quaternaryResultFormat; const char oldQuinaryFormat = settings->quinaryResultFormat; const int oldSecondaryPrecision = settings->secondaryResultPrecision; const int oldTertiaryPrecision = settings->tertiaryResultPrecision; const int oldQuaternaryPrecision = settings->quaternaryResultPrecision; const int oldQuinaryPrecision = settings->quinaryResultPrecision; const char oldSecondaryComplex = settings->secondaryResultComplexForm; const char oldTertiaryComplex = settings->tertiaryResultComplexForm; const char oldQuaternaryComplex = settings->quaternaryResultComplexForm; const char oldQuinaryComplex = settings->quinaryResultComplexForm; const EvaluationContext& ctx = entry.contextRef(); settings->complexNumbers = ctx.complexOn; settings->imaginaryUnit = (ctx.unit == 'j') ? 'j' : 'i'; settings->angleUnit = ctx.angle; settings->resultFormat = ctx.main.fmt; settings->resultPrecision = ctx.main.prec; settings->resultComplexForm = ctx.main.cplx; settings->unitNegativeExponentStyle = isValidUnitNegativeExponentStyle(ctx.unitExp) ? ctx.unitExp : Settings::UnitNegativeExponentSuperscript; settings->resultRoundingMode = isValidResultRoundingMode(ctx.round) ? ctx.round : Settings::ResultRoundingHalfAwayFromZero; setRuntimeUnitNegativeExponentStyle(settings->unitNegativeExponentStyle); setRuntimeResultRoundingMode(settings->resultRoundingMode); settings->multipleResultLinesEnabled = !ctx.extras.isEmpty(); settings->secondaryResultEnabled = false; settings->tertiaryResultEnabled = false; settings->quaternaryResultEnabled = false; settings->quinaryResultEnabled = false; if (ctx.extras.size() > 0) { settings->secondaryResultEnabled = true; settings->alternativeResultFormat = ctx.extras.at(0).fmt; settings->secondaryResultPrecision = ctx.extras.at(0).prec; settings->secondaryResultComplexForm = ctx.extras.at(0).cplx; } if (ctx.extras.size() > 1) { settings->tertiaryResultEnabled = true; settings->tertiaryResultFormat = ctx.extras.at(1).fmt; settings->tertiaryResultPrecision = ctx.extras.at(1).prec; settings->tertiaryResultComplexForm = ctx.extras.at(1).cplx; } if (ctx.extras.size() > 2) { settings->quaternaryResultEnabled = true; settings->quaternaryResultFormat = ctx.extras.at(2).fmt; settings->quaternaryResultPrecision = ctx.extras.at(2).prec; settings->quaternaryResultComplexForm = ctx.extras.at(2).cplx; } if (ctx.extras.size() > 3) { settings->quinaryResultEnabled = true; settings->quinaryResultFormat = ctx.extras.at(3).fmt; settings->quinaryResultPrecision = ctx.extras.at(3).prec; settings->quinaryResultComplexForm = ctx.extras.at(3).cplx; } const QStringList lines = ResultLineFormatUtils::formatResultLinesForDisplay( entry.expr(), entry.interpretedExpr(), entry.result(), false, true, evaluator); settings->complexNumbers = oldComplexNumbers; settings->imaginaryUnit = oldImaginaryUnit; settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; settings->resultComplexForm = oldResultComplexForm; settings->unitNegativeExponentStyle = oldUnitExp; settings->resultRoundingMode = oldRound; settings->multipleResultLinesEnabled = oldMultiple; settings->secondaryResultEnabled = oldSecondaryEnabled; settings->tertiaryResultEnabled = oldTertiaryEnabled; settings->quaternaryResultEnabled = oldQuaternaryEnabled; settings->quinaryResultEnabled = oldQuinaryEnabled; settings->alternativeResultFormat = oldSecondaryFormat; settings->tertiaryResultFormat = oldTertiaryFormat; settings->quaternaryResultFormat = oldQuaternaryFormat; settings->quinaryResultFormat = oldQuinaryFormat; settings->secondaryResultPrecision = oldSecondaryPrecision; settings->tertiaryResultPrecision = oldTertiaryPrecision; settings->quaternaryResultPrecision = oldQuaternaryPrecision; settings->quinaryResultPrecision = oldQuinaryPrecision; settings->secondaryResultComplexForm = oldSecondaryComplex; settings->tertiaryResultComplexForm = oldTertiaryComplex; settings->quaternaryResultComplexForm = oldQuaternaryComplex; settings->quinaryResultComplexForm = oldQuinaryComplex; setRuntimeUnitNegativeExponentStyle(settings->unitNegativeExponentStyle); setRuntimeResultRoundingMode(settings->resultRoundingMode); return lines; } QString formattedExpressionForDisplay(const HistoryEntry& entry, const Evaluator* evaluator) { return ResultLineFormatUtils::formattedExpressionLineForDisplay( entry.expr(), entry.interpretedExpr(), evaluator); } QString simplifiedExpressionLineForDisplay(const HistoryEntry& entry, const Evaluator* evaluator) { const QString simplifiedLine = ResultLineFormatUtils::simplifiedExpressionLineForDisplay( entry.interpretedExpr(), entry.expr(), Settings::instance()->simplifyResultExpressions, evaluator); return simplifiedLine.isEmpty() ? QString() : QStringLiteral("= ") + simplifiedLine; } bool isSimplifiedExpressionRenderLine(const QStringList& renderedLines, int lineIndex, const QString& simplifiedLine) { if (lineIndex <= 0 || lineIndex >= renderedLines.size()) return false; const QString line = renderedLines.at(lineIndex); if (!line.startsWith(QLatin1String("= "))) return false; return !simplifiedLine.isEmpty() && line == simplifiedLine; } QStringList renderedHistoryLinesForDisplay(const HistoryEntry& entry, const Evaluator* evaluator) { if (entry.hasRenderedLines()) return entry.renderedLines(); QStringList lines; lines.append(formattedExpressionForDisplay(entry, evaluator)); if (!entry.result().isNan()) lines.append(formatResultLines(entry, evaluator)); return lines; } QString formattedExpressionForDisplay(const QString& expression, const QString& interpretedExpression, const Evaluator* evaluator) { return ResultLineFormatUtils::formattedExpressionLineForDisplay( expression, interpretedExpression, evaluator); } const Session* displaySession(const ResultDisplay* display) { return display != nullptr ? display->session() : nullptr; } } ResultDisplay::ResultDisplay(QWidget* parent) : QPlainTextEdit(parent) , m_highlighter(new SyntaxHighlighter(this)) , m_scrolledLines(0) , m_scrollDirection(0) , m_isScrollingPageOnly(false) , m_hoverHighlightEnabled(true) , m_scrollBarHovered(false) , m_historyBlockIndexCacheDirty(true) , m_hoveredHistoryIndex(-1) , m_editingHistoryIndex(-1) , m_count(0) , m_firstDisplayedHistoryIndex(0) , m_loadedSessionCount(1) , m_closeSessionEnabled(false) , m_session(nullptr) , m_themeSurfaceColor() , m_toolTipBackgroundColor() , m_toolTipForegroundColor() , m_toolTipOutlineColor() , m_hoverActionPopup(nullptr) , m_hoverActionPopupLabel(nullptr) , m_hoverHighlightColor() , m_primaryColor() , m_contextMenuBackgroundColor() , m_contextMenuForegroundColor() , m_contextMenuHoverBackgroundColor() , m_contextMenuHoverForegroundColor() , m_hoveredActionBadge(NoActionBadge) , m_scrollToBottomButtonHovered(false) , m_scrollToBottomButton(new QToolButton(this)) { StartupDiagnostics::Scope timing("Initialize result display controls"); applyEditorDisplayStyle(); MenuStyle::install(); setBackgroundRole(QPalette::Base); setLayoutDirection(Qt::LeftToRight); setMinimumWidth(150); setReadOnly(true); setFocusPolicy(Qt::NoFocus); setWordWrapMode(QTextOption::WrapAnywhere); setMouseTracking(true); QScrollBar* bar = verticalScrollBar(); bar->setAttribute(Qt::WA_Hover, true); bar->setMouseTracking(true); bar->installEventFilter(this); connect(bar, &QScrollBar::valueChanged, this, [this]() { updateScrollToBottomButtonVisibility(); viewport()->update(); }); connect(bar, &QScrollBar::rangeChanged, this, [this]() { repositionScrollToBottomButton(); updateScrollToBottomButtonVisibility(); viewport()->update(); }); m_scrollToBottomButton->setFocusPolicy(Qt::NoFocus); m_scrollToBottomButton->setObjectName(QStringLiteral("ScrollToBottomButton")); m_scrollToBottomButton->setCursor(Qt::PointingHandCursor); m_scrollToBottomButton->setToolTip(QString()); m_scrollToBottomButton->setIconSize(QSize(16, 16)); m_scrollToBottomButton->setFixedSize(30, 30); m_scrollToBottomButton->setAttribute(Qt::WA_Hover, true); m_scrollToBottomButton->setMouseTracking(true); m_scrollToBottomButton->installEventFilter(this); updateScrollToBottomButtonStyle(); connect(m_scrollToBottomButton, &QToolButton::clicked, this, &ResultDisplay::scrollToBottom); m_scrollToBottomButton->hide(); repositionScrollToBottomButton(); } bool ResultDisplay::eventFilter(QObject* watched, QEvent* event) { if (watched == verticalScrollBar()) { if (event->type() == QEvent::Enter || event->type() == QEvent::HoverEnter) { if (!m_scrollBarHovered) { m_scrollBarHovered = true; updateScrollBarStyleSheet(); } } else if (event->type() == QEvent::Leave || event->type() == QEvent::HoverLeave) { if (m_scrollBarHovered) { m_scrollBarHovered = false; updateScrollBarStyleSheet(); } } } else if (watched == m_scrollToBottomButton) { if (event->type() == QEvent::Enter || event->type() == QEvent::HoverEnter) { if (!m_scrollToBottomButtonHovered) { m_scrollToBottomButtonHovered = true; updateScrollToBottomButtonStyle(); } showHoverActionPopup(tr("Scroll to bottom"), m_scrollToBottomButton, m_scrollToBottomButton->mapToGlobal( m_scrollToBottomButton->rect().center())); } else if (event->type() == QEvent::MouseMove) { QMouseEvent* mouseEvent = static_cast(event); showHoverActionPopup(tr("Scroll to bottom"), m_scrollToBottomButton, mouseEvent->globalPosition().toPoint()); } else if (event->type() == QEvent::HoverMove) { showHoverActionPopup(tr("Scroll to bottom"), m_scrollToBottomButton, m_scrollToBottomButton->mapToGlobal( static_cast(event)->position().toPoint())); } else if (event->type() == QEvent::Leave || event->type() == QEvent::HoverLeave) { if (m_scrollToBottomButtonHovered) { m_scrollToBottomButtonHovered = false; updateScrollToBottomButtonStyle(); } hideHoverActionPopup(); } else if (event->type() == QEvent::Hide || event->type() == QEvent::MouseButtonPress || event->type() == QEvent::Wheel) { hideHoverActionPopup(); } } return QPlainTextEdit::eventFilter(watched, event); } void ResultDisplay::setHoverHighlightEnabled(bool enabled) { if (m_hoverHighlightEnabled == enabled) return; m_hoverHighlightEnabled = enabled; if (!m_hoverHighlightEnabled) m_hoveredHistoryIndex = -1; updateHoverHighlightSelection(); } void ResultDisplay::setEditingHistoryIndex(int index) { if (m_editingHistoryIndex == index) return; const int previousEditingHistoryIndex = m_editingHistoryIndex; m_editingHistoryIndex = index; if (m_editingHistoryIndex >= 0 && m_hoveredHistoryIndex >= 0) { const int previousHoveredHistoryIndex = m_hoveredHistoryIndex; m_hoveredHistoryIndex = -1; updateHoverHighlightSelection(); viewport()->update(hoverActionRectForHistoryIndex(previousHoveredHistoryIndex)); } if (m_editingHistoryIndex >= 0) viewport()->unsetCursor(); updateHoverHighlightSelection(); if (previousEditingHistoryIndex >= 0) viewport()->update(viewport()->rect()); if (m_editingHistoryIndex >= 0) viewport()->update(viewport()->rect()); } void ResultDisplay::setLoadedSessionCount(int count) { const int normalizedCount = qMax(1, count); if (m_loadedSessionCount == normalizedCount) return; m_loadedSessionCount = normalizedCount; viewport()->update(); } void ResultDisplay::setCloseSessionEnabled(bool enabled) { if (m_closeSessionEnabled == enabled) return; m_closeSessionEnabled = enabled; viewport()->update(); } void ResultDisplay::setSession(const Session* session, bool renderHistory) { if (m_session == session) return; m_session = session; m_highlighter->setEvaluator(m_session ? m_session->evaluator() : nullptr); clear(); if (renderHistory) refresh(); viewport()->update(); } void ResultDisplay::append(const QString& expression, Quantity& value, const QString& interpretedExpression) { ++m_count; const Evaluator* evaluator = m_session ? m_session->evaluator() : nullptr; appendPlainText(formattedExpressionForDisplay(expression, interpretedExpression, evaluator)); if (!value.isNan()) { const Settings* settings = Settings::instance(); EvaluationContext ctx; ctx.main.fmt = settings->resultFormat; ctx.main.prec = settings->resultPrecision; ctx.main.cplx = settings->resultComplexForm; ctx.complexOn = settings->complexNumbers; ctx.unit = settings->imaginaryUnit; ctx.angle = settings->angleUnit; ctx.unitExp = settings->unitNegativeExponentStyle; ctx.round = settings->resultRoundingMode; const HistoryEntry entry(expression, value, interpretedExpression, ctx); const QStringList resultLines = formatResultLines(entry, evaluator); const QString simplifiedLine = simplifiedExpressionLineForDisplay(entry, evaluator); const QStringList renderedLines = QStringList({ formattedExpressionForDisplay(entry, evaluator) }) + resultLines; for (int i = 0; i < resultLines.size(); ++i) { const QString& line = resultLines.at(i); appendPlainText(line); if (isSimplifiedExpressionRenderLine(renderedLines, i + 1, simplifiedLine)) markSimplifiedExpressionBlock(document()->lastBlock().blockNumber()); } } appendPlainText(QLatin1String("")); markHistoryBlockIndexCacheDirty(); } int ResultDisplay::count() const { return m_count; } QPair ResultDisplay::viewportTopAnchor() const { const QTextBlock block = firstVisibleBlock(); if (!block.isValid()) return qMakePair(-1, 0); const QRectF blockRect = blockBoundingGeometry(block).translated(contentOffset()); const int offsetInBlock = qMax(0, qRound(-blockRect.top())); return qMakePair(block.blockNumber(), offsetInBlock); } void ResultDisplay::restoreViewportTopAnchor(const QPair& anchor) { if (anchor.first < 0 || document()->blockCount() <= 0) return; const int blockNumber = qBound(0, anchor.first, document()->blockCount() - 1); const QTextBlock block = document()->findBlockByNumber(blockNumber); if (!block.isValid()) return; QScrollBar* bar = verticalScrollBar(); const int targetValue = qRound(blockBoundingGeometry(block).top()) + anchor.second; bar->setValue(qBound(bar->minimum(), targetValue, bar->maximum())); } void ResultDisplay::restoreScrollValue(int value) { QScrollBar* bar = verticalScrollBar(); const int targetValue = value == std::numeric_limits::max() ? bar->maximum() : qBound(bar->minimum(), value, bar->maximum()); bar->setValue(targetValue); updateScrollToBottomButtonVisibility(); } QString ResultDisplay::exportHtml() const { QString str; m_highlighter->asHtml(str); return str; } void ResultDisplay::rehighlight() { StartupDiagnostics::AppearanceScope timing("Refresh result highlighting and appearance", this); if (StartupDiagnostics::isRecording()) { StartupDiagnostics::observeHighlightInputs(timing, this, StartupDiagnostics::configuredThemeInputs(), {m_themeSurfaceColor}, m_session ? m_session->evaluator() : Evaluator::instance()); } m_highlighter->update(); const QColor backgroundColor = themeSurfaceBackground(); QPalette palette = this->palette(); palette.setColor(QPalette::Active, QPalette::Base, backgroundColor); palette.setColor(QPalette::Inactive, QPalette::Base, backgroundColor); palette.setColor(QPalette::Disabled, QPalette::Base, backgroundColor); palette.setColor(QPalette::Active, QPalette::Window, backgroundColor); palette.setColor(QPalette::Inactive, QPalette::Window, backgroundColor); palette.setColor(QPalette::Disabled, QPalette::Window, backgroundColor); StartupDiagnostics::setAppearancePalette(this, palette); setAutoFillBackground(true); setAttribute(Qt::WA_StyledBackground, true); QPalette viewportPalette = viewport()->palette(); viewportPalette.setColor(QPalette::Active, QPalette::Base, backgroundColor); viewportPalette.setColor(QPalette::Inactive, QPalette::Base, backgroundColor); viewportPalette.setColor(QPalette::Disabled, QPalette::Base, backgroundColor); viewportPalette.setColor(QPalette::Active, QPalette::Window, backgroundColor); viewportPalette.setColor(QPalette::Inactive, QPalette::Window, backgroundColor); viewportPalette.setColor(QPalette::Disabled, QPalette::Window, backgroundColor); StartupDiagnostics::setAppearancePalette(viewport(), viewportPalette); viewport()->setAutoFillBackground(true); viewport()->setAttribute(Qt::WA_StyledBackground, true); updateSurfaceStyleSheet(); updateScrollBarStyleSheet(); } void ResultDisplay::applyEditorDisplayStyle() { const int inset = Settings::instance()->editorDisplayStyle == Settings::EditorDisplayClassic ? UiConfig::ClassicTextInset : kResultDisplayHorizontalPadding; const int padding = qMax(0, inset - qRound(document()->documentMargin())); setViewportMargins(padding, 0, padding, 0); repositionScrollToBottomButton(); } void ResultDisplay::setThemeSurfaceColor(const QColor& color) { m_themeSurfaceColor = color; updateSurfaceStyleSheet(); updateScrollToBottomButtonStyle(); updateScrollBarStyleSheet(); } void ResultDisplay::setThemeToolTipColors(const QColor& background, const QColor& foreground, const QColor& outline) { m_toolTipBackgroundColor = background; m_toolTipForegroundColor = foreground; m_toolTipOutlineColor = outline; applyHoverActionPopupTheme(); } void ResultDisplay::updateSurfaceStyleSheet() { const QString background = themeSurfaceBackground().name(); StartupDiagnostics::setAppearanceStyleSheet(this, QStringLiteral("QPlainTextEdit { background-color: %1; }") .arg(background)); StartupDiagnostics::setAppearanceStyleSheet(viewport(), QStringLiteral("QWidget { background-color: %1; }") .arg(background)); } void ResultDisplay::setThemeInteractionColors(const QColor& hoverBackground, const QColor& primaryColor, const QColor& menuBackground, const QColor& menuForeground, const QColor& menuHoverBackground, const QColor& menuHoverForeground) { m_hoverHighlightColor = hoverBackground; m_primaryColor = primaryColor; m_contextMenuBackgroundColor = menuBackground; m_contextMenuForegroundColor = menuForeground; m_contextMenuHoverBackgroundColor = menuHoverBackground; m_contextMenuHoverForegroundColor = menuHoverForeground; updateHoverHighlightSelection(); } void ResultDisplay::clear() { m_count = 0; m_firstDisplayedHistoryIndex = 0; setPlainText(QLatin1String("")); markHistoryBlockIndexCacheDirty(); clearHoverFeedback(); updateScrollToBottomButtonVisibility(); } void ResultDisplay::clearHoverFeedback() { const int previousHoveredHistoryIndex = m_hoveredHistoryIndex; m_hoveredHistoryIndex = -1; setHoveredActionBadge(NoActionBadge); setHoverActionToolTip(QString()); updateHoverHighlightSelection(); if (previousHoveredHistoryIndex >= 0) viewport()->update(hoverActionRectForHistoryIndex(previousHoveredHistoryIndex)); } QRect ResultDisplay::actionBadgeRect(HoveredActionBadge badge) const { if (badge == CancelActionBadge) return cancelGlyphBadgeRectForEditingIndex(); if (m_hoveredHistoryIndex < 0) return QRect(); switch (badge) { case CopyActionBadge: return copyGlyphBadgeRectForHistoryIndex(m_hoveredHistoryIndex); case EditActionBadge: return editGlyphBadgeRectForHistoryIndex(m_hoveredHistoryIndex); case SettingsActionBadge: return settingsGlyphBadgeRectForHistoryIndex(m_hoveredHistoryIndex); case RemoveActionBadge: return removeGlyphBadgeRectForHistoryIndex(m_hoveredHistoryIndex); default: return QRect(); } } ResultDisplay::HoveredActionBadge ResultDisplay::actionBadgeAtPosition(int historyIndex, const QPoint& pos) const { if (historyIndex < 0) return NoActionBadge; if (copyGlyphBadgeRectForHistoryIndex(historyIndex).contains(pos)) return CopyActionBadge; if (editGlyphBadgeRectForHistoryIndex(historyIndex).contains(pos)) return EditActionBadge; if (settingsGlyphBadgeRectForHistoryIndex(historyIndex).contains(pos)) return SettingsActionBadge; if (removeGlyphBadgeRectForHistoryIndex(historyIndex).contains(pos)) return RemoveActionBadge; return NoActionBadge; } int ResultDisplay::historyIndexForActionBadgeAtPosition(const QPoint& pos) const { ensureHistoryBlockIndexCache(); const int historyCount = m_firstDisplayedHistoryIndex + m_historyBlockRanges.size(); for (int historyIndex = m_firstDisplayedHistoryIndex; historyIndex < historyCount; ++historyIndex) { if (actionBadgeAtPosition(historyIndex, pos) != NoActionBadge) return historyIndex; } return -1; } void ResultDisplay::setHoveredActionBadge(HoveredActionBadge badge) { if (m_hoveredActionBadge == badge) return; const QRect previousRect = actionBadgeRect(m_hoveredActionBadge); m_hoveredActionBadge = badge; const QRect currentRect = actionBadgeRect(m_hoveredActionBadge); if (previousRect.isValid()) viewport()->update(previousRect.adjusted(-1, -1, 1, 1)); if (currentRect.isValid()) viewport()->update(currentRect.adjusted(-1, -1, 1, 1)); } void ResultDisplay::setHoverActionToolTip(const QString& text) { if (text.isEmpty()) hideHoverActionPopup(); else showHoverActionPopup(text); } void ResultDisplay::applyHoverActionPopupTheme() { ToolTipStyleUtils::applyPopupTheme( m_hoverActionPopup, m_hoverActionPopupLabel, this, {m_toolTipBackgroundColor, m_toolTipForegroundColor, m_toolTipOutlineColor, UiConfig::ResultTooltipCornerRadius}); } void ResultDisplay::ensureHoverActionPopup() { if (m_hoverActionPopup != nullptr) return; m_hoverActionPopup = ToolTipStyleUtils::createPopup(this, QStringLiteral("resultActionPopup"), QStringLiteral("resultActionPopupLabel"), Qt::RichText, &m_hoverActionPopupLabel, true); applyHoverActionPopupTheme(); } void ResultDisplay::hideHoverActionPopup() { if (m_hoverActionPopup != nullptr) m_hoverActionPopup->hide(); } void ResultDisplay::showHoverActionPopup(const QString& text) { showHoverActionPopup(text, viewport(), QCursor::pos()); } void ResultDisplay::showHoverActionPopup(const QString& text, QWidget* anchor, const QPoint& globalPos) { ensureHoverActionPopup(); ToolTipStyleUtils::showPopup(m_hoverActionPopup, m_hoverActionPopupLabel, text, anchor, globalPos, UiConfig::ResultTooltipCornerRadius); } void ResultDisplay::updateHoverActionPopupMask() { if (m_hoverActionPopup == nullptr) return; ToolTipStyleUtils::applyRoundedPopupMask(m_hoverActionPopup, qMax(0, UiConfig::ResultTooltipCornerRadius)); } QColor ResultDisplay::hoverActionBadgeFillColor() const { const QColor hoverColor = m_hoverHighlightColor.isValid() ? m_hoverHighlightColor : hoverColorForBackground(themeSurfaceBackground()); return aaForegroundForBackground(hoverColor, 7.0); } QColor ResultDisplay::hoverActionIconColor(HoveredActionBadge badge) const { if (badge == m_hoveredActionBadge && m_primaryColor.isValid()) return m_primaryColor; return m_hoverHighlightColor.isValid() ? m_hoverHighlightColor : hoverColorForBackground(themeSurfaceBackground()); } void ResultDisplay::refresh() { StartupDiagnostics::AppearanceScope timing("Render session history", this); const Session* session = displaySession(this); if (session == nullptr) { clear(); return; } const int historyCount = session->historySize(); const int previousScrollValue = verticalScrollBar()->value(); const int firstDisplayedHistoryIndex = firstDisplayedHistoryIndexForCount(historyCount, session); const auto appendRenderedHistoryEntry = [this, session](int historyIndex) { const HistoryEntry& lastEntry = session->historyEntryAtRef(historyIndex); const Evaluator* evaluator = session->evaluator(); const QStringList renderedLines = renderedHistoryLinesForDisplay(lastEntry, evaluator); const QString simplifiedLine = simplifiedExpressionLineForDisplay(lastEntry, evaluator); for (int i = 0; i < renderedLines.size(); ++i) { const QString& line = renderedLines.at(i); appendPlainText(line); if (isSimplifiedExpressionRenderLine(renderedLines, i, simplifiedLine)) markSimplifiedExpressionBlock(document()->lastBlock().blockNumber()); } appendPlainText(QLatin1String("")); }; // Fast path for the common "new evaluation added one history entry" case. if (historyCount == m_count + 1 && historyCount > 0 && firstDisplayedHistoryIndex == m_firstDisplayedHistoryIndex) { clearHoverFeedback(); appendRenderedHistoryEntry(historyCount - 1); m_count = historyCount; m_firstDisplayedHistoryIndex = firstDisplayedHistoryIndex; markHistoryBlockIndexCacheDirty(); updateHoverHighlightSelection(); updateScrollToBottomButtonVisibility(); return; } const auto secondDisplayedHistoryBlock = [this]() { QTextBlock block = document()->firstBlock(); while (block.isValid()) { if (block.text().isEmpty()) return block.next(); block = block.next(); } return QTextBlock(); }; const auto removeFirstDisplayedHistoryEntry = [this, &secondDisplayedHistoryBlock]() { QTextBlock firstBlock = document()->firstBlock(); if (!firstBlock.isValid()) return false; QTextBlock nextEntryBlock = secondDisplayedHistoryBlock(); QTextCursor cursor(document()); cursor.setPosition(firstBlock.position()); if (nextEntryBlock.isValid()) cursor.setPosition(nextEntryBlock.position(), QTextCursor::KeepAnchor); else cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); cursor.removeSelectedText(); return true; }; const bool appendedPastRenderedWindow = historyCount == m_count + 1 && firstDisplayedHistoryIndex == m_firstDisplayedHistoryIndex + 1; const bool historyLimitReplacedOldestEntry = historyCount == m_count && historyCount > 0 && firstDisplayedHistoryIndex == m_firstDisplayedHistoryIndex; if (appendedPastRenderedWindow || historyLimitReplacedOldestEntry) { const bool singleRenderedEntry = document()->firstBlock().isValid() && !secondDisplayedHistoryBlock().isValid(); const HistoryEntry& firstEntry = session->historyEntryAtRef(firstDisplayedHistoryIndex); const QString expectedFirstLine = formattedExpressionForDisplay(firstEntry, session->evaluator()); const QString currentFirstLine = document()->firstBlock().isValid() ? document()->firstBlock().text() : QString(); const QTextBlock secondBlock = secondDisplayedHistoryBlock(); const bool canRollRenderedWindow = currentFirstLine != expectedFirstLine && (singleRenderedEntry || (secondBlock.isValid() && secondBlock.text() == expectedFirstLine)); if (canRollRenderedWindow) { clearHoverFeedback(); removeFirstDisplayedHistoryEntry(); appendRenderedHistoryEntry(historyCount - 1); m_count = historyCount; m_firstDisplayedHistoryIndex = firstDisplayedHistoryIndex; markHistoryBlockIndexCacheDirty(); updateHoverHighlightSelection(); updateScrollToBottomButtonVisibility(); return; } } clearHoverFeedback(); m_count = historyCount; m_firstDisplayedHistoryIndex = firstDisplayedHistoryIndex; QStringList allLines; allLines.reserve(qMax(1, (m_count - m_firstDisplayedHistoryIndex) * 3)); for (int i = m_firstDisplayedHistoryIndex; i < m_count; ++i) { const HistoryEntry& historyEntry = session->historyEntryAtRef(i); allLines.append(renderedHistoryLinesForDisplay(historyEntry, session->evaluator())); allLines.append(QLatin1String("")); } setPlainText(allLines.join(QLatin1String("\n"))); markSimplifiedExpressionBlocks(); verticalScrollBar()->setValue(previousScrollValue); markHistoryBlockIndexCacheDirty(); updateHoverHighlightSelection(); updateScrollToBottomButtonVisibility(); } void ResultDisplay::refreshLastHistoryEntry() { const Session* session = displaySession(this); if (session == nullptr) { clear(); return; } const int historyCount = session->historySize(); const int firstDisplayedHistoryIndex = firstDisplayedHistoryIndexForCount(historyCount, session); if (historyCount == 0) { clear(); return; } if (m_count != historyCount || m_firstDisplayedHistoryIndex != firstDisplayedHistoryIndex || blockCount() <= 0) { refresh(); return; } QTextBlock endBlock = document()->lastBlock(); while (endBlock.isValid() && endBlock.text().isEmpty() && endBlock.previous().isValid()) endBlock = endBlock.previous(); if (!endBlock.isValid()) { refresh(); return; } QTextBlock startBlock = endBlock; while (startBlock.previous().isValid() && !startBlock.previous().text().isEmpty()) startBlock = startBlock.previous(); const HistoryEntry& lastEntry = session->historyEntryAtRef(historyCount - 1); QStringList updatedLines = renderedHistoryLinesForDisplay(lastEntry, session->evaluator()); updatedLines.append(QLatin1String("")); clearHoverFeedback(); QTextCursor cursor(document()); cursor.setPosition(startBlock.position()); cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); cursor.insertText(updatedLines.join(QLatin1String("\n"))); markSimplifiedExpressionBlocks(); markHistoryBlockIndexCacheDirty(); updateHoverHighlightSelection(); updateScrollToBottomButtonVisibility(); } void ResultDisplay::scrollLines(int numberOfLines) { QScrollBar* bar = verticalScrollBar(); bar->setValue(bar->value() + numberOfLines); } void ResultDisplay::scrollLineUp() { if (m_scrollDirection != 0) { stopActiveScrollingAnimation(); return; } scrollLines(-1); } void ResultDisplay::scrollLineDown() { if (m_scrollDirection != 0) { stopActiveScrollingAnimation(); return; } scrollLines(1); } void ResultDisplay::scrollToDirection(int direction) { m_scrolledLines = 0; bool mustStartTimer = (m_scrollDirection == 0); m_scrollDirection = direction; if (mustStartTimer) m_scrollTimer.start(16, this); } void ResultDisplay::scrollPageUp() { if (verticalScrollBar()->value() == 0) return; m_isScrollingPageOnly = true; scrollToDirection(-1); } void ResultDisplay::scrollPageDown() { if (verticalScrollBar()->value() == verticalScrollBar()->maximum()) return; m_isScrollingPageOnly = true; scrollToDirection(1); } void ResultDisplay::scrollToTop() { if (verticalScrollBar()->value() == 0) return; m_isScrollingPageOnly = false; scrollToDirection(-1); } void ResultDisplay::scrollToBottom() { if (verticalScrollBar()->value() == verticalScrollBar()->maximum()) return; m_isScrollingPageOnly = false; scrollToDirection(1); } void ResultDisplay::increaseFontPointSize() { QFont newFont = font(); const int newSize = newFont.pointSize() + 1; if (newSize > 96) return; newFont.setPointSize(newSize); setFont(newFont); } void ResultDisplay::decreaseFontPointSize() { QFont newFont = font(); const int newSize = newFont.pointSize() - 1; if (newSize < 8) return; newFont.setPointSize(newSize); setFont(newFont); } void ResultDisplay::mouseDoubleClickEvent(QMouseEvent* event) { QTextCursor cursor = textCursor(); cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); setTextCursor(cursor); const int selectedHistoryIndex = historyIndexAtPosition(event->pos()); const Session* selectedSession = displaySession(this); int expressionBlock = -1; int lastBlock = -1; if (selectedSession != nullptr && selectedHistoryIndex >= 0 && selectedHistoryIndex < selectedSession->historySize() && blockRangeForHistoryIndex(selectedHistoryIndex, expressionBlock, lastBlock) && cursor.blockNumber() == expressionBlock) { // Reuse the source expression, including any literal comment text. emit expressionSelected(selectedSession->historyEntryAtRef(selectedHistoryIndex).expr()); return; } QString text = cursor.selectedText(); QString resultMarker = QLatin1String("= "); if (text.startsWith(resultMarker)) { // Display lines strip unit brackets for readability, but editor input // requires canonical expression syntax ("value[unit]") with QuantSp. // For result lines (all blocks after the expression block in the same // history entry), rehydrate from the underlying Quantity instead of // copying the visually simplified text. const int historyIndex = historyIndexAtPosition(event->pos()); if (historyIndex >= 0) { int startBlock = -1; int endBlock = -1; if (blockRangeForHistoryIndex(historyIndex, startBlock, endBlock) && cursor.blockNumber() > startBlock) { const Session* session = displaySession(this); if (session != nullptr && historyIndex < session->historySize()) { const Quantity value = session->historyEntryAtRef(historyIndex).result(); if (!value.isNan()) { QString clipboardText = formatResultForClipboard(value); const QString displayedResultLine = text.mid(resultMarker.size()); if (!clipboardText.contains(MathDsl::UnitStart) && !clipboardText.endsWith(MathDsl::Deg) && !clipboardText.endsWith(UnicodeChars::Prime) && !clipboardText.endsWith(UnicodeChars::DoublePrime)) { if (displayedResultLine.endsWith(MathDsl::Deg)) clipboardText += MathDsl::Deg; else if (displayedResultLine.endsWith(UnicodeChars::Prime)) clipboardText += UnicodeChars::Prime; else if (displayedResultLine.endsWith(UnicodeChars::DoublePrime)) clipboardText += UnicodeChars::DoublePrime; } emit expressionSelected(clipboardText); return; } } } } text.remove(resultMarker); } emit expressionSelected(text); } void ResultDisplay::mousePressEvent(QMouseEvent* event) { emit clicked(); if (m_editingHistoryIndex >= 0) { const QRect cancelRect = cancelGlyphBadgeRectForEditingIndex(); if (event->button() == Qt::LeftButton && cancelRect.isValid() && cancelRect.contains(event->pos())) { emit cancelHistoryEditRequested(); event->accept(); return; } QPlainTextEdit::mousePressEvent(event); return; } if (event->button() == Qt::LeftButton && m_hoverHighlightEnabled) { const int actionHistoryIndex = m_hoveredHistoryIndex >= 0 && actionBadgeAtPosition(m_hoveredHistoryIndex, event->pos()) != NoActionBadge ? m_hoveredHistoryIndex : historyIndexForActionBadgeAtPosition(event->pos()); const HoveredActionBadge actionBadge = actionBadgeAtPosition(actionHistoryIndex, event->pos()); if (actionBadge == CopyActionBadge) { const Session* session = displaySession(this); if (session != nullptr && actionHistoryIndex >= 0 && actionHistoryIndex < session->historySize()) { const Quantity value = session->historyEntryAtRef(actionHistoryIndex).result(); if (!value.isNan()) QApplication::clipboard()->setText(formatResultForClipboard(value), QClipboard::Clipboard); } event->accept(); return; } if (actionBadge == EditActionBadge) { emit editHistoryEntryRequested(actionHistoryIndex); event->accept(); return; } if (actionBadge == SettingsActionBadge) { emit editHistoryEntryContextRequested(actionHistoryIndex); event->accept(); return; } if (actionBadge == RemoveActionBadge) { emit removeHistoryEntryRequested(actionHistoryIndex); event->accept(); return; } } QPlainTextEdit::mousePressEvent(event); } QMenu* ResultDisplay::createContextMenu(const QPoint& pos) { QMenu* menu = new QMenu(this); QMenu* copyMenu = menu->addMenu(tr("Copy")); QAction* copySelectionAction = copyMenu->addAction( tr("Selection") + QLatin1Char('\t') + QKeySequence(QKeySequence::Copy).toString(QKeySequence::NativeText)); copySelectionAction->setEnabled(textCursor().hasSelection()); copyMenu->setEnabled(copySelectionAction->isEnabled()); connect(copySelectionAction, &QAction::triggered, this, &ResultDisplay::copy); QAction* selectAllAction = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-select-all")), tr("Select All") + QLatin1Char('\t') + QKeySequence(QKeySequence::SelectAll).toString(QKeySequence::NativeText)); selectAllAction->setEnabled(!document()->isEmpty()); connect(selectAllAction, &QAction::triggered, this, &ResultDisplay::selectAll); const int historyIndex = historyIndexAtPosition(pos); if (historyIndex >= 0) { const Session* session = displaySession(this); if (session == nullptr) return menu; copyMenu->setEnabled(true); copyMenu->addSeparator(); QAction* copyExpressionAction = copyMenu->addAction(tr("Expression")); connect(copyExpressionAction, &QAction::triggered, this, [session, historyIndex]() { if (historyIndex < 0 || historyIndex >= session->historySize()) return; QApplication::clipboard()->setText(session->historyEntryAtRef(historyIndex).expr(), QClipboard::Clipboard); }); QAction* copyResultAction = copyMenu->addAction(tr("Result")); const bool canCopyResult = historyIndex >= 0 && historyIndex < session->historySize() && !session->historyEntryAtRef(historyIndex).result().isNan(); copyResultAction->setEnabled(canCopyResult); connect(copyResultAction, &QAction::triggered, this, [session, historyIndex]() { if (historyIndex < 0 || historyIndex >= session->historySize()) return; const Quantity value = session->historyEntryAtRef(historyIndex).result(); if (value.isNan()) return; QApplication::clipboard()->setText(formatResultForClipboard(value), QClipboard::Clipboard); }); QAction* copyCalculationAction = copyMenu->addAction(tr("Calculation")); int startBlock = -1; int endBlock = -1; QString calculationText; if (blockRangeForHistoryIndex(historyIndex, startBlock, endBlock)) { // Use the displayed lines so saved formatting and simplifications // are copied exactly as shown, without the blank separator line. QTextCursor calculationCursor(document()); calculationCursor.setPosition(document()->findBlockByNumber(startBlock).position()); const QTextBlock lastBlock = document()->findBlockByNumber(endBlock); calculationCursor.setPosition(lastBlock.position() + lastBlock.length() - 1, QTextCursor::KeepAnchor); calculationText = QTextDocumentFragment(calculationCursor).toPlainText(); } copyCalculationAction->setEnabled(!calculationText.isEmpty()); connect(copyCalculationAction, &QAction::triggered, this, [calculationText]() { QApplication::clipboard()->setText(calculationText, QClipboard::Clipboard); }); QAction* copySingleLineAction = copyMenu->addAction(tr("Calculation as Single Line")); copySingleLineAction->setEnabled(!calculationText.isEmpty()); connect(copySingleLineAction, &QAction::triggered, this, [calculationText]() { QString singleLineText = calculationText; singleLineText.replace(QLatin1Char('\n'), QLatin1Char(' ')); QApplication::clipboard()->setText(singleLineText, QClipboard::Clipboard); }); menu->addSeparator(); QAction* editAction = menu->addAction(tr("Edit Expression")); connect(editAction, &QAction::triggered, this, [this, historyIndex]() { emit editHistoryEntryRequested(historyIndex); }); QAction* editSettingsAction = menu->addAction(tr("Change Settings")); connect(editSettingsAction, &QAction::triggered, this, [this, historyIndex]() { emit editHistoryEntryContextRequested(historyIndex); }); QMenu* removeMenu = menu->addMenu(tr("Remove")); QAction* removeAction = removeMenu->addAction(tr("This Calculation")); connect(removeAction, &QAction::triggered, this, [this, historyIndex]() { emit removeHistoryEntryRequested(historyIndex); }); QAction* removeAboveAction = removeMenu->addAction(tr("All Calculations Above")); connect(removeAboveAction, &QAction::triggered, this, [this, historyIndex]() { emit removeHistoryEntriesAboveRequested(historyIndex); }); QAction* removeBelowAction = removeMenu->addAction(tr("All Calculations Below")); connect(removeBelowAction, &QAction::triggered, this, [this, historyIndex]() { emit removeHistoryEntriesBelowRequested(historyIndex); }); } menu->addSeparator(); QAction* newSessionAction = menu->addAction(tr("New Tab")); connect(newSessionAction, &QAction::triggered, this, [this]() { emit newSessionRequested(); }); QAction* privateSessionAction = menu->addAction(tr("New Private Tab")); connect(privateSessionAction, &QAction::triggered, this, &ResultDisplay::newPrivateSessionRequested); QMenu* sessionMenu = menu->addMenu(tr("Session")); QAction* openSessionAction = sessionMenu->addAction(tr("Open...")); connect(openSessionAction, &QAction::triggered, this, [this]() { emit openSessionRequested(); }); QAction* importSessionAction = sessionMenu->addAction(tr("&Import...")); connect(importSessionAction, &QAction::triggered, this, [this]() { emit importSessionRequested(); }); QMenu* exportSessionMenu = sessionMenu->addMenu(tr("&Export")); QAction* exportJsonAction = exportSessionMenu->addAction(QStringLiteral("JSON")); connect(exportJsonAction, &QAction::triggered, this, [this]() { emit exportSessionJsonRequested(); }); QAction* exportPlainTextAction = exportSessionMenu->addAction(tr("Plain &text")); connect(exportPlainTextAction, &QAction::triggered, this, [this]() { emit exportSessionPlainTextRequested(); }); QAction* exportHtmlAction = exportSessionMenu->addAction(QStringLiteral("&HTML")); connect(exportHtmlAction, &QAction::triggered, this, [this]() { emit exportSessionHtmlRequested(); }); sessionMenu->addSeparator(); QAction* duplicateSessionAction = sessionMenu->addAction(tr("Clone...")); connect(duplicateSessionAction, &QAction::triggered, this, [this]() { emit duplicateSessionRequested(); }); QAction* renameSessionAction = sessionMenu->addAction(tr("Rename...")); QAction* convertPrivacyAction = sessionMenu->addAction(m_session && m_session->isPrivate() ? tr("Keep") : tr("Make Private...")); connect(convertPrivacyAction, &QAction::triggered, this, &ResultDisplay::convertSessionPrivacyRequested); connect(renameSessionAction, &QAction::triggered, this, [this]() { emit renameSessionRequested(); }); sessionMenu->addSeparator(); QAction* clearSessionAction = sessionMenu->addAction(tr("Clear")); connect(clearSessionAction, &QAction::triggered, this, [this]() { emit clearSessionRequested(); }); QAction* deleteSessionAction = sessionMenu->addAction(tr("Delete")); connect(deleteSessionAction, &QAction::triggered, this, [this]() { emit deleteSessionRequested(); }); sessionMenu->addSeparator(); QAction* closeSessionAction = sessionMenu->addAction(tr("Close")); connect(closeSessionAction, &QAction::triggered, this, [this]() { emit closeSessionRequested(); }); menu->addSeparator(); QMenu* splitMenu = menu->addMenu(tr("Split")); QAction* splitLeftAction = splitMenu->addAction(tr("Left")); connect(splitLeftAction, &QAction::triggered, this, [this]() { emit splitLeftRequested(); }); QAction* splitRightAction = splitMenu->addAction(tr("Right")); connect(splitRightAction, &QAction::triggered, this, [this]() { emit splitRightRequested(); }); QAction* splitUpAction = splitMenu->addAction(tr("Up")); connect(splitUpAction, &QAction::triggered, this, [this]() { emit splitUpRequested(); }); QAction* splitDownAction = splitMenu->addAction(tr("Down")); connect(splitDownAction, &QAction::triggered, this, [this]() { emit splitDownRequested(); }); QAction* closePaneAction = menu->addAction(tr("Close Pane")); connect(closePaneAction, &QAction::triggered, this, [this]() { emit closePaneRequested(); }); QMainWindow* mainWindow = qobject_cast(window()); if (mainWindow != 0 && mainWindow->menuBar() != 0 && !mainWindow->menuBar()->isVisible()) { menu->addSeparator(); QMenu* mainMenu = menu->addMenu(tr("Main Menu")); const QList topLevelActions = mainWindow->menuBar()->actions(); for (QAction* topLevelAction : topLevelActions) { if (topLevelAction->isSeparator()) { mainMenu->addSeparator(); continue; } QMenu* sourceSubmenu = topLevelAction->menu(); if (sourceSubmenu != 0) { QMenu* clonedTopLevelSubmenu = mainMenu->addMenu(sourceSubmenu->title()); clonedTopLevelSubmenu->setEnabled(topLevelAction->isEnabled()); cloneMenuActions(sourceSubmenu, clonedTopLevelSubmenu); } } } applyContextMenuTheme(menu, m_contextMenuBackgroundColor, m_contextMenuForegroundColor, m_contextMenuHoverBackgroundColor, m_contextMenuHoverForegroundColor); return menu; } void ResultDisplay::contextMenuEvent(QContextMenuEvent* event) { QMenu* menu = createContextMenu(event->pos()); menu->exec(event->globalPos()); delete menu; } void ResultDisplay::leaveEvent(QEvent* event) { QPlainTextEdit::leaveEvent(event); viewport()->unsetCursor(); setHoveredActionBadge(NoActionBadge); setHoverActionToolTip(QString()); if (m_hoveredHistoryIndex >= 0) { const int previousHoveredHistoryIndex = m_hoveredHistoryIndex; m_hoveredHistoryIndex = -1; updateHoverHighlightSelection(); viewport()->update(hoverActionRectForHistoryIndex(previousHoveredHistoryIndex)); } } void ResultDisplay::timerEvent(QTimerEvent* event) { if (event->timerId() != m_scrollTimer.timerId()) { QWidget::timerEvent(event); return; } if (m_isScrollingPageOnly) pageScrollEvent(); else fullContentScrollEvent(); } void ResultDisplay::pageScrollEvent() { if (m_scrolledLines >= linesPerPage()) { stopActiveScrollingAnimation(); return; } scrollLines(m_scrollDirection * 2); m_scrolledLines += 2; } void ResultDisplay::fullContentScrollEvent() { QScrollBar* bar = verticalScrollBar(); int value = bar->value(); bool shouldStop = (m_scrollDirection == -1 && value <= 0) || (m_scrollDirection == 1 && value >= bar->maximum()); if (shouldStop && m_scrollDirection != 0) { stopActiveScrollingAnimation(); return; } scrollLines(m_scrollDirection * 10); } void ResultDisplay::wheelEvent(QWheelEvent* event) { if (event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) { if (event->angleDelta().y() > 0) emit shiftControlWheelUp(); else emit shiftControlWheelDown(); } else if (event->modifiers() == Qt::ShiftModifier) { if (event->angleDelta().y() > 0) emit shiftWheelUp(); else emit shiftWheelDown(); } else if (event->modifiers() == Qt::ControlModifier) { if (event->angleDelta().y() > 0) emit controlWheelUp(); else emit controlWheelDown(); } else { QPlainTextEdit::wheelEvent(event); return; } event->accept(); } void ResultDisplay::mouseMoveEvent(QMouseEvent* event) { QPlainTextEdit::mouseMoveEvent(event); if (event->buttons() & Qt::LeftButton) { setHoverActionToolTip(QString()); viewport()->unsetCursor(); setHoveredActionBadge(NoActionBadge); return; } if (m_editingHistoryIndex >= 0) { const QRect cancelRect = cancelGlyphBadgeRectForEditingIndex(); const bool overCancelGlyph = cancelRect.isValid() && cancelRect.contains(event->pos()); setHoveredActionBadge(overCancelGlyph ? CancelActionBadge : NoActionBadge); setHoverActionToolTip(overCancelGlyph ? tr("Cancel editing") : QString()); if (overCancelGlyph) viewport()->setCursor(Qt::PointingHandCursor); else viewport()->unsetCursor(); return; } if (!m_hoverHighlightEnabled) { if (m_hoveredHistoryIndex >= 0) { const int previousHoveredHistoryIndex = m_hoveredHistoryIndex; m_hoveredHistoryIndex = -1; setHoveredActionBadge(NoActionBadge); updateHoverHighlightSelection(); viewport()->update(hoverActionRectForHistoryIndex(previousHoveredHistoryIndex)); } setHoverActionToolTip(QString()); viewport()->unsetCursor(); return; } int hoveredHistoryIndex = historyIndexAtPosition(event->pos()); if (hoveredHistoryIndex < 0) hoveredHistoryIndex = historyIndexForActionBadgeAtPosition(event->pos()); if (hoveredHistoryIndex >= 0 && (historyBlockOverlapsSessionBadge(hoveredHistoryIndex) || historyBlockOverlapsScrollToBottomButton(hoveredHistoryIndex))) { hoveredHistoryIndex = -1; } if (hoveredHistoryIndex != m_hoveredHistoryIndex) { const int previousHoveredHistoryIndex = m_hoveredHistoryIndex; m_hoveredHistoryIndex = hoveredHistoryIndex; updateHoverHighlightSelection(); if (previousHoveredHistoryIndex >= 0) viewport()->update(hoverActionRectForHistoryIndex(previousHoveredHistoryIndex)); if (m_hoveredHistoryIndex >= 0) viewport()->update(hoverActionRectForHistoryIndex(m_hoveredHistoryIndex)); } const HoveredActionBadge actionBadge = actionBadgeAtPosition(m_hoveredHistoryIndex, event->pos()); const bool overActionGlyph = actionBadge != NoActionBadge; setHoveredActionBadge(actionBadge); if (overActionGlyph) viewport()->setCursor(Qt::PointingHandCursor); else viewport()->unsetCursor(); setHoverActionToolTip(actionBadge == CopyActionBadge ? tr("Copy result") : actionBadge == EditActionBadge ? tr("Edit expression") : actionBadge == SettingsActionBadge ? tr("Change settings") : actionBadge == RemoveActionBadge ? tr("Remove calculation") : QString()); } void ResultDisplay::paintEvent(QPaintEvent* event) { QPlainTextEdit::paintEvent(event); QPainter painter(viewport()); drawScrollEdgeGradients(&painter); if (m_editingHistoryIndex >= 0) { const QRect cancelRect = cancelGlyphBadgeRectForEditingIndex(); if (!cancelRect.isValid()) return; const QColor badgeFill = hoverActionBadgeFillColor(); const QColor iconColor = hoverActionIconColor(CancelActionBadge); painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(Qt::NoPen); painter.setBrush(badgeFill); painter.drawEllipse(cancelRect); painter.setPen(QPen(iconColor, 1.8, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); const QPointF center = badgeCenter(cancelRect); const qreal side = cancelRect.width() * 0.22; painter.drawRect(QRectF(center.x() - side, center.y() - side, side * 2.0, side * 2.0)); return; } if (!m_hoverHighlightEnabled || m_hoveredHistoryIndex < 0) return; const QRect copyRect = copyGlyphBadgeRectForHistoryIndex(m_hoveredHistoryIndex); const QRect removeRect = removeGlyphBadgeRectForHistoryIndex(m_hoveredHistoryIndex); const QRect editRect = editGlyphBadgeRectForHistoryIndex(m_hoveredHistoryIndex); const QRect settingsRect = settingsGlyphBadgeRectForHistoryIndex(m_hoveredHistoryIndex); if (!copyRect.isValid() || !removeRect.isValid() || !editRect.isValid() || !settingsRect.isValid()) return; painter.setRenderHint(QPainter::Antialiasing, true); const QColor badgeFill = hoverActionBadgeFillColor(); painter.setPen(Qt::NoPen); painter.setBrush(badgeFill); painter.drawEllipse(copyRect); painter.setPen(QPen(hoverActionIconColor(CopyActionBadge), 1.3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); const QPointF copyCenter = badgeCenter(copyRect); const qreal pageSize = copyRect.width() * 0.33; const QRectF backPage(copyCenter.x() - pageSize * 0.72, copyCenter.y() - pageSize * 0.72, pageSize, pageSize); const QRectF frontPage(copyCenter.x() - pageSize * 0.28, copyCenter.y() - pageSize * 0.28, pageSize, pageSize); const qreal radius = qMax(0.8, copyRect.width() * 0.07); painter.drawRoundedRect(backPage, radius, radius); painter.drawRoundedRect(frontPage, radius, radius); painter.setPen(Qt::NoPen); painter.setBrush(badgeFill); painter.drawEllipse(editRect); painter.setPen(QPen(hoverActionIconColor(EditActionBadge), 1.6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); const QPointF editCenter = badgeCenter(editRect); const qreal editHalf = editRect.width() * 0.20; painter.drawLine(QPointF(editCenter.x() - editHalf, editCenter.y() + editHalf), QPointF(editCenter.x() + editHalf, editCenter.y() - editHalf)); painter.setPen(QPen(hoverActionIconColor(EditActionBadge), 1.1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter.drawLine(QPointF(editCenter.x() + editHalf * 0.62, editCenter.y() - editHalf * 0.62), QPointF(editCenter.x() + editHalf * 1.08, editCenter.y() - editHalf * 1.08)); painter.setPen(Qt::NoPen); painter.setBrush(badgeFill); painter.drawEllipse(settingsRect); painter.setPen(QPen(hoverActionIconColor(SettingsActionBadge), 1.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); const QPointF settingsCenter = badgeCenter(settingsRect); const qreal gear = settingsRect.width() * 0.16; painter.drawEllipse(QRectF(settingsCenter.x() - gear, settingsCenter.y() - gear, gear * 2.0, gear * 2.0)); painter.drawLine(QPointF(settingsCenter.x() - gear * 1.9, settingsCenter.y()), QPointF(settingsCenter.x() - gear * 1.2, settingsCenter.y())); painter.drawLine(QPointF(settingsCenter.x() + gear * 1.2, settingsCenter.y()), QPointF(settingsCenter.x() + gear * 1.9, settingsCenter.y())); painter.drawLine(QPointF(settingsCenter.x(), settingsCenter.y() - gear * 1.9), QPointF(settingsCenter.x(), settingsCenter.y() - gear * 1.2)); painter.drawLine(QPointF(settingsCenter.x(), settingsCenter.y() + gear * 1.2), QPointF(settingsCenter.x(), settingsCenter.y() + gear * 1.9)); painter.setPen(Qt::NoPen); painter.setBrush(badgeFill); painter.drawEllipse(removeRect); painter.setPen(QPen(hoverActionIconColor(RemoveActionBadge), 1.8, Qt::SolidLine, Qt::RoundCap)); const QPointF center = badgeCenter(removeRect); const qreal half = removeRect.width() * 0.22; painter.drawLine(QPointF(center.x() - half, center.y() - half), QPointF(center.x() + half, center.y() + half)); painter.drawLine(QPointF(center.x() - half, center.y() + half), QPointF(center.x() + half, center.y() - half)); } void ResultDisplay::resizeEvent(QResizeEvent* event) { QPlainTextEdit::resizeEvent(event); repositionScrollToBottomButton(); } void ResultDisplay::scrollContentsBy(int dx, int dy) { QPlainTextEdit::scrollContentsBy(dx, dy); updateScrollToBottomButtonVisibility(); viewport()->update(); } void ResultDisplay::stopActiveScrollingAnimation() { m_scrollTimer.stop(); m_scrolledLines = 0; m_scrollDirection = 0; updateScrollToBottomButtonVisibility(); } int ResultDisplay::scrollEdgeFadeHeightForCurrentFont() const { const int defaultLineHeight = QFontMetrics(QApplication::font()).height(); const int currentLineHeight = fontMetrics().height(); if (defaultLineHeight <= 0 || currentLineHeight <= 0) return kResultDisplayFadeHeight; const qreal scale = static_cast(currentLineHeight) / static_cast(defaultLineHeight); return qMax(1, qRound(kResultDisplayFadeHeight * scale)); } void ResultDisplay::drawScrollEdgeGradients(QPainter* painter) { if (painter == nullptr) return; QScrollBar* bar = verticalScrollBar(); if (bar == nullptr || bar->maximum() <= bar->minimum()) return; const QRect rect = viewport()->rect(); const int fadeHeight = qMin(scrollEdgeFadeHeightForCurrentFont(), rect.height() / 2); if (fadeHeight <= 0) return; QColor solid = themeSurfaceBackground(); QColor transparent = solid; solid.setAlpha(255); transparent.setAlpha(0); painter->save(); painter->setPen(Qt::NoPen); if (bar->value() > bar->minimum()) { const QRect topRect(rect.left(), rect.top(), rect.width(), fadeHeight); QLinearGradient topGradient(topRect.topLeft(), topRect.bottomLeft()); topGradient.setColorAt(0.0, solid); topGradient.setColorAt(1.0, transparent); painter->fillRect(topRect, topGradient); } if (bar->value() < bar->maximum()) { const QRect bottomRect(rect.left(), rect.bottom() - fadeHeight + 1, rect.width(), fadeHeight); QLinearGradient bottomGradient(bottomRect.topLeft(), bottomRect.bottomLeft()); bottomGradient.setColorAt(0.0, transparent); bottomGradient.setColorAt(1.0, solid); painter->fillRect(bottomRect, bottomGradient); } painter->restore(); } void ResultDisplay::repositionScrollToBottomButton() { if (!m_scrollToBottomButton) return; const int rightMargin = kResultDisplayHorizontalPadding; const int bottomMargin = 10; const QRect contentRect = contentsRect(); const int x = contentRect.left() + qMax(0, contentRect.width() - m_scrollToBottomButton->width() - rightMargin); const int y = contentRect.top() + qMax(0, contentRect.height() - m_scrollToBottomButton->height() - bottomMargin); m_scrollToBottomButton->move(x, y); m_scrollToBottomButton->raise(); } void ResultDisplay::updateScrollToBottomButtonVisibility() { if (!m_scrollToBottomButton) return; QScrollBar* bar = verticalScrollBar(); const bool hasScrollableContent = bar->maximum() > bar->minimum(); const bool nearBottom = bar->value() >= bar->maximum(); m_scrollToBottomButton->setVisible(hasScrollableContent && !nearBottom); } void ResultDisplay::updateScrollToBottomButtonStyle() { if (!m_scrollToBottomButton) return; const ScrollToBottomButtonColors colors = scrollToBottomButtonColorsForResultBackground(themeSurfaceBackground()); const QColor foreground = m_scrollToBottomButtonHovered ? colors.hoverForeground : colors.foreground; m_scrollToBottomButton->setIcon(downArrowIcon(foreground)); m_scrollToBottomButton->setStyleSheet(QStringLiteral( "QToolButton {" " border: %4px solid %3;" " border-radius: 15px;" " background: %1;" "}" "QToolButton:hover {" " background: %2;" "}") .arg(colors.background.name(), colors.hoverBackground.name(), colors.outline.name()) .arg(UiConfig::OutlineStrokeWidth)); } void ResultDisplay::updateScrollBarStyleSheet() { static const int kBaseScrollBarWidthAt96Dpi = 5; static const qreal kReferenceDpi = 96.0; const int baseScrollBarWidth = qMax( 1, qRound(kBaseScrollBarWidthAt96Dpi * (logicalDpiX() / kReferenceDpi))); const int scrollBarWidth = baseScrollBarWidth * 2; const int handleHorizontalMargin = m_scrollBarHovered ? 0 : baseScrollBarWidth / 2; const ResultDisplayScrollBarColors colors = scrollBarColorsForResultBackground(themeSurfaceBackground()); StartupDiagnostics::setAppearanceStyleSheet(verticalScrollBar(), QString( "QScrollBar:vertical {" " border: 0;" " margin: 0 0 0 0;" " background: %1;" " width: %3px;" "}" "QScrollBar::handle:vertical {" " background: %2;" " margin: 0 %4px 0 %4px;" "}" "QScrollBar::handle:vertical:hover {" " background: %5;" "}" "QScrollBar::handle:vertical:pressed {" " background: %6;" "}" "QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {" " border: 0;" " width: 0;" " height: 0;" " background: %1;" "}" "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {" " background: %1;" "}" ).arg(colors.track.name(), colors.thumb.name()) .arg(scrollBarWidth) .arg(handleHorizontalMargin) .arg(colors.hoverThumb.name(), colors.pressedThumb.name())); } int ResultDisplay::historyIndexAtPosition(const QPoint& pos) const { const QTextCursor cursor = cursorForPosition(pos); const int blockNumber = cursor.blockNumber(); if (blockNumber < 0) return -1; ensureHistoryBlockIndexCache(); if (blockNumber >= m_blockToHistoryIndex.size()) return -1; const int historyIndex = m_blockToHistoryIndex.at(blockNumber); const int localHistoryIndex = historyIndex - m_firstDisplayedHistoryIndex; if (localHistoryIndex < 0 || localHistoryIndex >= m_historyBlockRanges.size()) return -1; const QPair range = m_historyBlockRanges.at(localHistoryIndex); // Separator blank lines are intentionally mapped in the cache; keep them // non-interactive while still allowing genuine blank lines inside entries. if (blockNumber < range.first || blockNumber > range.second) return -1; return historyIndex; } bool ResultDisplay::blockRangeForHistoryIndex(int historyIndex, int& startBlock, int& endBlock) const { startBlock = -1; endBlock = -1; const int localHistoryIndex = historyIndex - m_firstDisplayedHistoryIndex; if (localHistoryIndex < 0) return false; ensureHistoryBlockIndexCache(); if (localHistoryIndex >= m_historyBlockRanges.size()) return false; const QPair range = m_historyBlockRanges.at(localHistoryIndex); startBlock = range.first; endBlock = range.second; return startBlock >= 0 && endBlock >= startBlock; } QRect ResultDisplay::removeGlyphRectForHistoryIndex(int historyIndex) const { int startBlock = -1; int endBlock = -1; if (!blockRangeForHistoryIndex(historyIndex, startBlock, endBlock)) return QRect(); QTextBlock start = document()->findBlockByNumber(startBlock); QTextBlock end = document()->findBlockByNumber(endBlock); if (!start.isValid() || !end.isValid()) return QRect(); const QRectF startRect = blockBoundingGeometry(start).translated(contentOffset()); const QRectF endRect = blockBoundingGeometry(end).translated(contentOffset()); const int top = qRound(startRect.top()); const int bottom = qRound(endRect.bottom()); if (bottom <= top) return QRect(); const int side = qMax(12, fontMetrics().height()); const int spacing = 4; const int rightPadding = 6; const int left = viewport()->width() - side - rightPadding; const int minLeft = side + spacing; if (left < minLeft) return QRect(); return QRect(left, top, side, bottom - top); } QRect ResultDisplay::removeGlyphBadgeRectForHistoryIndex(int historyIndex) const { const QRect removeLaneRect = removeGlyphRectForHistoryIndex(historyIndex); if (!removeLaneRect.isValid()) return QRect(); const int diameter = qMin(removeLaneRect.width(), qMax(12, fontMetrics().height() - 2)); const int left = removeLaneRect.left() + (removeLaneRect.width() - diameter) / 2; const int top = removeLaneRect.top() + (removeLaneRect.height() - diameter) / 2; return QRect(left, top, diameter, diameter); } QRect ResultDisplay::editGlyphRectForHistoryIndex(int historyIndex) const { const QRect removeRect = removeGlyphRectForHistoryIndex(historyIndex); if (!removeRect.isValid()) return QRect(); const int spacing = 4; const int left = removeRect.left() - removeRect.width() - spacing; if (left < 0) return QRect(); return QRect(left, removeRect.top(), removeRect.width(), removeRect.height()); } QRect ResultDisplay::editGlyphBadgeRectForHistoryIndex(int historyIndex) const { const QRect editLaneRect = editGlyphRectForHistoryIndex(historyIndex); if (!editLaneRect.isValid()) return QRect(); const int diameter = qMin(editLaneRect.width(), qMax(12, fontMetrics().height() - 2)); const int left = editLaneRect.left() + (editLaneRect.width() - diameter) / 2; const int top = editLaneRect.top() + (editLaneRect.height() - diameter) / 2; return QRect(left, top, diameter, diameter); } QRect ResultDisplay::copyGlyphRectForHistoryIndex(int historyIndex) const { const QRect settingsRect = settingsGlyphRectForHistoryIndex(historyIndex); if (!settingsRect.isValid()) return QRect(); const int spacing = 4; const int left = settingsRect.left() - settingsRect.width() - spacing; if (left < 0) return QRect(); return QRect(left, settingsRect.top(), settingsRect.width(), settingsRect.height()); } QRect ResultDisplay::copyGlyphBadgeRectForHistoryIndex(int historyIndex) const { const QRect copyLaneRect = copyGlyphRectForHistoryIndex(historyIndex); if (!copyLaneRect.isValid()) return QRect(); const int diameter = qMin(copyLaneRect.width(), qMax(12, fontMetrics().height() - 2)); const int left = copyLaneRect.left() + (copyLaneRect.width() - diameter) / 2; const int top = copyLaneRect.top() + (copyLaneRect.height() - diameter) / 2; return QRect(left, top, diameter, diameter); } QRect ResultDisplay::settingsGlyphRectForHistoryIndex(int historyIndex) const { const QRect editRect = editGlyphRectForHistoryIndex(historyIndex); if (!editRect.isValid()) return QRect(); const int spacing = 4; const int left = editRect.left() - editRect.width() - spacing; if (left < 0) return QRect(); return QRect(left, editRect.top(), editRect.width(), editRect.height()); } QRect ResultDisplay::settingsGlyphBadgeRectForHistoryIndex(int historyIndex) const { const QRect settingsLaneRect = settingsGlyphRectForHistoryIndex(historyIndex); if (!settingsLaneRect.isValid()) return QRect(); const int diameter = qMin(settingsLaneRect.width(), qMax(12, fontMetrics().height() - 2)); const int left = settingsLaneRect.left() + (settingsLaneRect.width() - diameter) / 2; const int top = settingsLaneRect.top() + (settingsLaneRect.height() - diameter) / 2; return QRect(left, top, diameter, diameter); } QRect ResultDisplay::hoverActionRectForHistoryIndex(int historyIndex) const { return copyGlyphRectForHistoryIndex(historyIndex) .united(settingsGlyphRectForHistoryIndex(historyIndex)) .united(editGlyphRectForHistoryIndex(historyIndex)) .united(removeGlyphRectForHistoryIndex(historyIndex)); } QRect ResultDisplay::cancelGlyphBadgeRectForEditingIndex() const { if (m_editingHistoryIndex < 0) return QRect(); return removeGlyphBadgeRectForHistoryIndex(m_editingHistoryIndex); } bool ResultDisplay::historyBlockOverlapsSessionBadge(int historyIndex) const { int startBlock = -1; int endBlock = -1; if (!blockRangeForHistoryIndex(historyIndex, startBlock, endBlock)) return false; return false; } bool ResultDisplay::historyBlockOverlapsScrollToBottomButton(int historyIndex) const { if (m_scrollToBottomButton == nullptr || !m_scrollToBottomButton->isVisible()) return false; int startBlock = -1; int endBlock = -1; if (!blockRangeForHistoryIndex(historyIndex, startBlock, endBlock)) return false; const QTextBlock start = document()->findBlockByNumber(startBlock); const QTextBlock end = document()->findBlockByNumber(endBlock); if (!start.isValid() || !end.isValid()) return false; const QRectF startRect = blockBoundingGeometry(start).translated(contentOffset()); const QRectF endRect = blockBoundingGeometry(end).translated(contentOffset()); const QRect historyRect(0, qRound(startRect.top()), viewport()->width(), qMax(1, qRound(endRect.bottom() - startRect.top()))); const QRect buttonRect(viewport()->mapFrom(this, m_scrollToBottomButton->pos()), m_scrollToBottomButton->size()); return historyRect.intersects(buttonRect); } void ResultDisplay::updateHoverHighlightSelection() { QList selections; if (m_hoveredHistoryIndex < 0 && m_editingHistoryIndex < 0) { setExtraSelections(selections); return; } const QColor hoverColor = m_hoverHighlightColor.isValid() ? m_hoverHighlightColor : hoverColorForBackground(themeSurfaceBackground()); auto appendSelectionForHistoryIndex = [this, &selections, &hoverColor](int historyIndex) { int startBlock = -1; int endBlock = -1; if (!blockRangeForHistoryIndex(historyIndex, startBlock, endBlock)) return; for (int blockNumber = startBlock; blockNumber <= endBlock; ++blockNumber) { QTextBlock block = document()->findBlockByNumber(blockNumber); if (!block.isValid()) continue; QTextLayout* layout = block.layout(); if (layout == nullptr) continue; const int lineCount = layout->lineCount(); if (lineCount <= 0) continue; const int blockPosition = block.position(); for (int lineIndex = 0; lineIndex < lineCount; ++lineIndex) { const QTextLine line = layout->lineAt(lineIndex); QTextEdit::ExtraSelection selection; selection.cursor = QTextCursor(document()); selection.cursor.setPosition(blockPosition + line.textStart()); selection.format.setProperty(QTextFormat::FullWidthSelection, true); selection.format.setBackground(hoverColor); selections.append(selection); } } }; if (m_hoverHighlightEnabled && m_hoveredHistoryIndex >= 0) appendSelectionForHistoryIndex(m_hoveredHistoryIndex); if (m_editingHistoryIndex >= 0 && (!m_hoverHighlightEnabled || m_editingHistoryIndex != m_hoveredHistoryIndex)) appendSelectionForHistoryIndex(m_editingHistoryIndex); setExtraSelections(selections); } QColor ResultDisplay::themeSurfaceBackground() const { return m_themeSurfaceColor.isValid() ? m_themeSurfaceColor : m_highlighter->colorForRole(ColorScheme::Background); } void ResultDisplay::markHistoryBlockIndexCacheDirty() { m_historyBlockIndexCacheDirty = true; } void ResultDisplay::markSimplifiedExpressionBlock(int blockNumber) { QTextBlock block = document()->findBlockByNumber(blockNumber); if (!block.isValid()) return; auto blockData = new SyntaxHighlightBlockData; blockData->highlightResultExpressionSyntax = true; block.setUserData(blockData); m_highlighter->rehighlightBlock(block); } void ResultDisplay::markSimplifiedExpressionBlocks() { const Session* session = displaySession(this); if (session == nullptr) return; const int historySize = session->historySize(); const int firstDisplayedHistoryIndex = firstDisplayedHistoryIndexForCount(historySize, session); QTextBlock block = document()->firstBlock(); for (int i = firstDisplayedHistoryIndex; i < historySize && block.isValid(); ++i) { const HistoryEntry& entry = session->historyEntryAtRef(i); const QStringList renderedLines = renderedHistoryLinesForDisplay(entry, session->evaluator()); const QString simplifiedLine = simplifiedExpressionLineForDisplay(entry, session->evaluator()); int lineIndex = 0; while (block.isValid()) { const QString blockText = block.text(); if (isSimplifiedExpressionRenderLine(renderedLines, lineIndex, simplifiedLine)) markSimplifiedExpressionBlock(block.blockNumber()); block = block.next(); ++lineIndex; if (blockText.isEmpty()) break; } } } void ResultDisplay::ensureHistoryBlockIndexCache() const { if (!m_historyBlockIndexCacheDirty) return; m_blockToHistoryIndex.clear(); m_historyBlockRanges.clear(); const Session* session = displaySession(this); if (session == nullptr) return; const int historySize = session->historySize(); const int firstDisplayedHistoryIndex = firstDisplayedHistoryIndexForCount(historySize, session); const int displayedHistoryCount = historySize - firstDisplayedHistoryIndex; m_historyBlockRanges.reserve(qMax(0, displayedHistoryCount)); QTextBlock block = document()->firstBlock(); for (int i = firstDisplayedHistoryIndex; i < historySize; ++i) { const int startBlock = block.isValid() ? block.blockNumber() : -1; int endBlock = -1; // Reconstruct ranges from the currently displayed text blocks so hover // hit-testing always matches what is visible, even after format mode // changes that intentionally do not rewrite history lines. while (block.isValid()) { const int blockNumber = block.blockNumber(); if (block.text().isEmpty()) { // Preserve existing behavior: separator blocks map to this // history entry, but are excluded from highlight ranges. m_blockToHistoryIndex.append(i); block = block.next(); break; } m_blockToHistoryIndex.append(i); endBlock = blockNumber; block = block.next(); } m_historyBlockRanges.append(qMakePair(startBlock, endBlock)); } // Keep the cache shape aligned with the rendered document even if there // are stale trailing blocks. while (block.isValid()) { m_blockToHistoryIndex.append(historySize > 0 ? historySize - 1 : -1); block = block.next(); } m_historyBlockIndexCacheDirty = false; } heldercorreia-speedcrunch-e7ca37f/src/gui/resultdisplay.h000066400000000000000000000204451526573132500237720ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2011, 2013-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_RESULTDISPLAY_H #define GUI_RESULTDISPLAY_H #include #include #include #include #include class Quantity; class SyntaxHighlighter; class HistoryEntry; class Session; class QContextMenuEvent; class QMenu; class QPainter; class QPoint; class QMouseEvent; class QEvent; class QFrame; class QLabel; class QPaintEvent; class QRect; class QResizeEvent; class QToolButton; class ResultDisplay : public QPlainTextEdit { Q_OBJECT public: explicit ResultDisplay(QWidget* parent = 0); void append(const QString& expr, Quantity& value, const QString& interpretedExpression = QString()); void appendHistory(const QStringList& expressions, const QStringList& results); int count() const; bool isEmpty() const { return m_count==0; } QString exportHtml() const; void setHoverHighlightEnabled(bool enabled); void setEditingHistoryIndex(int index); void setLoadedSessionCount(int count); void setCloseSessionEnabled(bool enabled); // With deferred rendering, call refresh() before restoring the viewport. void setSession(const Session* session, bool renderHistory = true); void setThemeSurfaceColor(const QColor& color); void applyEditorDisplayStyle(); void setThemeToolTipColors(const QColor& background, const QColor& foreground, const QColor& outline); void setThemeInteractionColors(const QColor& hoverBackground, const QColor& primaryColor, const QColor& menuBackground, const QColor& menuForeground, const QColor& menuHoverBackground, const QColor& menuHoverForeground); const Session* session() const { return m_session; } bool closeSessionEnabled() const { return m_closeSessionEnabled; } int loadedSessionCount() const { return m_loadedSessionCount; } QPair viewportTopAnchor() const; void restoreViewportTopAnchor(const QPair& anchor); void restoreScrollValue(int value); signals: void clicked(); void shiftWheelDown(); void shiftWheelUp(); void shiftControlWheelDown(); void shiftControlWheelUp(); void controlWheelDown(); void controlWheelUp(); void expressionSelected(const QString&); void editHistoryEntryRequested(int index); void editHistoryEntryContextRequested(int index); void cancelHistoryEditRequested(); void removeHistoryEntryRequested(int index); void removeHistoryEntriesAboveRequested(int index); void removeHistoryEntriesBelowRequested(int index); void newSessionRequested(); void newPrivateSessionRequested(); void convertSessionPrivacyRequested(); void openSessionRequested(); void importSessionRequested(); void exportSessionJsonRequested(); void exportSessionPlainTextRequested(); void exportSessionHtmlRequested(); void duplicateSessionRequested(); void splitLeftRequested(); void splitRightRequested(); void splitUpRequested(); void splitDownRequested(); void renameSessionRequested(); void clearSessionRequested(); void closeSessionRequested(); void closePaneRequested(); void deleteSessionRequested(); void loadedSessionsMenuRequested(const QPoint& globalPos); public slots: void clear(); void clearHoverFeedback(); void decreaseFontPointSize(); void increaseFontPointSize(); void rehighlight(); void refresh(); void refreshLastHistoryEntry(); void scrollLines(int); void scrollLineUp(); void scrollLineDown(); void scrollPageUp(); void scrollPageDown(); void scrollToBottom(); void scrollToTop(); protected: virtual void contextMenuEvent(QContextMenuEvent*); virtual bool eventFilter(QObject* watched, QEvent* event); virtual void leaveEvent(QEvent*); virtual void mouseDoubleClickEvent(QMouseEvent*); virtual void mousePressEvent(QMouseEvent*); virtual void mouseMoveEvent(QMouseEvent*); virtual void paintEvent(QPaintEvent*); virtual void resizeEvent(QResizeEvent*); virtual void scrollContentsBy(int dx, int dy); virtual void wheelEvent(QWheelEvent*); virtual void timerEvent(QTimerEvent*); void fullContentScrollEvent(); float linesPerPage() const { return static_cast(viewport()->height()) / fontMetrics().height(); } void pageScrollEvent(); void scrollToDirection(int); void stopActiveScrollingAnimation(); int scrollEdgeFadeHeightForCurrentFont() const; QMenu* createContextMenu(const QPoint& pos); void drawScrollEdgeGradients(QPainter* painter); void repositionScrollToBottomButton(); void updateScrollToBottomButtonVisibility(); void updateSurfaceStyleSheet(); void updateScrollToBottomButtonStyle(); void updateScrollBarStyleSheet(); int historyIndexAtPosition(const QPoint& pos) const; bool blockRangeForHistoryIndex(int historyIndex, int& startBlock, int& endBlock) const; QRect removeGlyphRectForHistoryIndex(int historyIndex) const; QRect removeGlyphBadgeRectForHistoryIndex(int historyIndex) const; QRect editGlyphRectForHistoryIndex(int historyIndex) const; QRect editGlyphBadgeRectForHistoryIndex(int historyIndex) const; QRect settingsGlyphRectForHistoryIndex(int historyIndex) const; QRect settingsGlyphBadgeRectForHistoryIndex(int historyIndex) const; QRect copyGlyphRectForHistoryIndex(int historyIndex) const; QRect copyGlyphBadgeRectForHistoryIndex(int historyIndex) const; QRect hoverActionRectForHistoryIndex(int historyIndex) const; QRect cancelGlyphBadgeRectForEditingIndex() const; bool historyBlockOverlapsSessionBadge(int historyIndex) const; bool historyBlockOverlapsScrollToBottomButton(int historyIndex) const; void updateHoverHighlightSelection(); QColor themeSurfaceBackground() const; void markHistoryBlockIndexCacheDirty(); void markSimplifiedExpressionBlock(int blockNumber); void markSimplifiedExpressionBlocks(); void ensureHistoryBlockIndexCache() const; private: Q_DISABLE_COPY(ResultDisplay) enum HoveredActionBadge { NoActionBadge, CopyActionBadge, EditActionBadge, SettingsActionBadge, RemoveActionBadge, CancelActionBadge }; QRect actionBadgeRect(HoveredActionBadge badge) const; HoveredActionBadge actionBadgeAtPosition(int historyIndex, const QPoint& pos) const; int historyIndexForActionBadgeAtPosition(const QPoint& pos) const; void setHoveredActionBadge(HoveredActionBadge badge); void setHoverActionToolTip(const QString& text); void applyHoverActionPopupTheme(); void ensureHoverActionPopup(); void hideHoverActionPopup(); void showHoverActionPopup(const QString& text); void showHoverActionPopup(const QString& text, QWidget* anchor, const QPoint& globalPos); void updateHoverActionPopupMask(); QColor hoverActionBadgeFillColor() const; QColor hoverActionIconColor(HoveredActionBadge badge) const; SyntaxHighlighter* m_highlighter; QBasicTimer m_scrollTimer; int m_scrolledLines; int m_scrollDirection; bool m_isScrollingPageOnly; bool m_hoverHighlightEnabled; bool m_scrollBarHovered; mutable bool m_historyBlockIndexCacheDirty; mutable QVector m_blockToHistoryIndex; mutable QVector> m_historyBlockRanges; int m_hoveredHistoryIndex; int m_editingHistoryIndex; int m_count; int m_firstDisplayedHistoryIndex; int m_loadedSessionCount; bool m_closeSessionEnabled; const Session* m_session; QColor m_themeSurfaceColor; QColor m_toolTipBackgroundColor; QColor m_toolTipForegroundColor; QColor m_toolTipOutlineColor; QFrame* m_hoverActionPopup; QLabel* m_hoverActionPopupLabel; QColor m_hoverHighlightColor; QColor m_primaryColor; QColor m_contextMenuBackgroundColor; QColor m_contextMenuForegroundColor; QColor m_contextMenuHoverBackgroundColor; QColor m_contextMenuHoverForegroundColor; HoveredActionBadge m_hoveredActionBadge; bool m_scrollToBottomButtonHovered; QToolButton* m_scrollToBottomButton; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/resultlineformatutils.h000066400000000000000000001656321526573132500255560ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_RESULTLINEFORMATUTILS_H #define GUI_RESULTLINEFORMATUTILS_H #include "core/evaluator.h" #include "core/mathdsl.h" #include "core/numberformatter.h" #include "core/regexpatterns.h" #include "core/settings.h" #include "core/unitdisplayformat.h" #include "core/unicodechars.h" #include "core/units.h" #include "gui/displayformatutils.h" #include "gui/simplifiedexpressionutils.h" #include "math/rational.h" #include #include #include #include #include #include namespace ResultLineFormatUtils { inline QString normalizeBracketedUnitTextForDisplay(const QString& text) { QString output; output.reserve(text.size()); int cursor = 0; QRegularExpressionMatchIterator matches = RegExpPatterns::unitBrackets().globalMatch(text); while (matches.hasNext()) { const QRegularExpressionMatch match = matches.next(); const int start = match.capturedStart(); const int end = match.capturedEnd(); output += text.mid(cursor, start - cursor); output += MathDsl::UnitStart; output += UnitDisplayFormat::normalizeUnitTextForDisplay(match.captured(1)); output += MathDsl::UnitEnd; cursor = end; } output += text.mid(cursor); return output; } inline QString collapseValueUnitMultiplicationForDisplay(QString text) { return text.replace( RegExpPatterns::valueTimesBracketedUnit(), QStringLiteral("\\1") + QString(MathDsl::QuantSp) + QStringLiteral("\\2")); } inline QString preserveExplicitBracketedSimpleUnitsFromSource(QString displayed, const QString& sourceExpression) { QRegularExpressionMatchIterator it = RegExpPatterns::bracketedSimpleUnitIdentifier().globalMatch(sourceExpression); QSet sourceSimpleUnits; while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); sourceSimpleUnits.insert(match.captured(1)); } if (sourceSimpleUnits.isEmpty()) return displayed; for (const QString& unitToken : sourceSimpleUnits) { const QString escapedToken = QRegularExpression::escape(unitToken); const QRegularExpression valueTimesUnit( QStringLiteral(R"((\d(?:[\d\.,]*)?)\s*[*·×]\s*(%1)(?![\p{L}\p{N}_]))") .arg(escapedToken)); displayed.replace( valueTimesUnit, QStringLiteral("\\1") + QString(MathDsl::QuantSp) + QStringLiteral("[") + unitToken + QStringLiteral("]")); } return displayed; } inline QString preserveExplicitParenthesizedUnitDenominatorFromSource( QString displayed, const QString& sourceExpression) { auto countExplicitGroupedUnitDenominators = [](const QString& text) { int count = 0; for (int i = 0; i < text.size(); ++i) { if (text.at(i) != MathDsl::DivOp) continue; int pos = i + 1; while (pos < text.size() && text.at(pos).isSpace()) ++pos; if (pos >= text.size() || text.at(pos) != MathDsl::GroupStart) continue; int depth = 0; int closePos = -1; for (int j = pos; j < text.size(); ++j) { const QChar ch = text.at(j); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd) { --depth; if (depth == 0) { closePos = j; break; } if (depth < 0) break; } } if (closePos < 0) continue; const QString grouped = text.mid(pos + 1, closePos - pos - 1); if (grouped.contains(MathDsl::UnitStart) && grouped.contains(MathDsl::UnitEnd)) ++count; i = closePos; } return count; }; int sourceParenthesizedDenominatorCount = countExplicitGroupedUnitDenominators(sourceExpression); if (sourceParenthesizedDenominatorCount == 0) return displayed; int preservedCount = 0; for (int i = 0; i < displayed.size() && preservedCount < sourceParenthesizedDenominatorCount; ++i) { if (displayed.at(i) != MathDsl::DivOp) continue; int numStart = i + 1; while (numStart < displayed.size() && displayed.at(numStart).isSpace()) ++numStart; if (numStart >= displayed.size()) continue; if (displayed.at(numStart) == MathDsl::GroupStart) continue; int unitOpen = displayed.indexOf(MathDsl::UnitStart, numStart); int unitClose = (unitOpen >= 0) ? displayed.indexOf(MathDsl::UnitEnd, unitOpen + 1) : -1; if (unitOpen < 0 || unitClose < 0) continue; bool hasInnerDivOrAddSub = false; for (int j = numStart; j < unitOpen; ++j) { const QChar ch = displayed.at(j); if (ch == MathDsl::DivOp || MathDsl::isAdditionOperator(ch) || MathDsl::isSubtractionOperator(ch)) { hasInnerDivOrAddSub = true; break; } } if (hasInnerDivOrAddSub) continue; displayed.insert(unitClose + 1, MathDsl::GroupEnd); displayed.insert(numStart, MathDsl::GroupStart); ++preservedCount; } return displayed; } inline QString preserveExplicitParenthesizedQuotientBeforeUnitFromSource( QString displayed, const QString& sourceExpression) { auto countSourceGroupedQuotientsWithUnit = [](const QString& text) { int count = 0; for (int i = 0; i < text.size(); ++i) { if (text.at(i) != MathDsl::GroupStart) continue; int depth = 0; int close = -1; for (int j = i; j < text.size(); ++j) { const QChar ch = text.at(j); if (ch == MathDsl::GroupStart) { ++depth; } else if (ch == MathDsl::GroupEnd) { --depth; if (depth == 0) { close = j; break; } } } if (close < 0) continue; int next = close + 1; while (next < text.size() && text.at(next).isSpace()) ++next; if (next < text.size() && text.at(next) == MathDsl::UnitStart && text.mid(i + 1, close - i - 1).contains(MathDsl::DivOp)) { ++count; } i = close; } return count; }; auto isNumericChar = [](QChar ch) { return ch.isDigit() || ch == MathDsl::DotSep || ch == MathDsl::CommaSep; }; int preserveCount = countSourceGroupedQuotientsWithUnit(sourceExpression); if (preserveCount == 0) return displayed; for (int i = 0; i < displayed.size() && preserveCount > 0; ++i) { if (displayed.at(i) != MathDsl::UnitStart) continue; int rightEnd = i - 1; while (rightEnd >= 0 && displayed.at(rightEnd).isSpace()) --rightEnd; if (rightEnd < 0) continue; if (!isNumericChar(displayed.at(rightEnd))) continue; int rightStart = rightEnd; while (rightStart >= 0 && isNumericChar(displayed.at(rightStart))) --rightStart; ++rightStart; int slashPos = rightStart - 1; while (slashPos >= 0 && displayed.at(slashPos).isSpace()) --slashPos; if (slashPos < 0 || displayed.at(slashPos) != MathDsl::DivOp) continue; int leftEnd = slashPos - 1; while (leftEnd >= 0 && displayed.at(leftEnd).isSpace()) --leftEnd; if (leftEnd < 0 || !isNumericChar(displayed.at(leftEnd))) continue; int leftStart = leftEnd; while (leftStart >= 0 && isNumericChar(displayed.at(leftStart))) --leftStart; ++leftStart; int beforeLeft = leftStart - 1; while (beforeLeft >= 0 && displayed.at(beforeLeft).isSpace()) --beforeLeft; if (beforeLeft >= 0 && displayed.at(beforeLeft) == MathDsl::GroupStart) continue; displayed.insert(i, MathDsl::GroupEnd); displayed.insert(leftStart, MathDsl::GroupStart); ++i; --preserveCount; } return displayed; } inline QString collapseBracketedCompactAngleSuffixes(QString text) { auto compactSuffixForToken = [](const QString& token) { const QString normalized = normalizeUnitName( UnicodeChars::normalizeUnitSymbolAliases(token.trimmed())); const UnitId id = unitId(normalized); if (id == UnitId::Degree) { return UnicodeChars::DegreeSign; } if (id == UnitId::Arcminute) { return UnicodeChars::Prime; } if (id == UnitId::Arcsecond) { return UnicodeChars::DoublePrime; } return QChar(); }; auto isCompactionSpace = [](QChar ch) { return ch.isSpace() || ch == MathDsl::QuantSp || ch == UnicodeChars::NoBreakSpace; }; auto isCompactionLeftAnchor = [](QChar ch) { return ch.isLetterOrNumber() || ch == MathDsl::GroupEnd || ch == MathDsl::UnitEnd || ch == MathDsl::PercentOp || ch == UnicodeChars::DegreeSign || ch == UnicodeChars::Prime || ch == UnicodeChars::DoublePrime; }; auto isInsideTrigCallArgument = [&](int index) { QVector parenStack; parenStack.reserve(8); for (int i = 0; i < index && i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::GroupStart) { parenStack.append(i); } else if (ch == MathDsl::GroupEnd) { if (!parenStack.isEmpty()) parenStack.removeLast(); } } if (parenStack.isEmpty()) return false; const int openParenPos = parenStack.last(); int nameEnd = openParenPos - 1; while (nameEnd >= 0 && text.at(nameEnd).isSpace()) --nameEnd; if (nameEnd < 0) return false; int nameStart = nameEnd; while (nameStart >= 0) { const QChar ch = text.at(nameStart); if (ch.isLetterOrNumber() || ch == UnicodeChars::LowLine) { --nameStart; continue; } break; } ++nameStart; if (nameStart > nameEnd) return false; return RegExpPatterns::isTrigFunctionIdentifier( QStringView(text).mid(nameStart, nameEnd - nameStart + 1)); }; QString output; output.reserve(text.size()); int cursor = 0; QRegularExpressionMatchIterator it = RegExpPatterns::compactAngleTokenInBrackets().globalMatch(text); while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); const int tokenStart = match.capturedStart(); const int tokenEnd = match.capturedEnd(); int left = tokenStart - 1; while (left >= cursor && isCompactionSpace(text.at(left))) --left; int right = tokenEnd; while (right < text.size() && isCompactionSpace(text.at(right))) ++right; if (left < cursor || !isCompactionLeftAnchor(text.at(left))) { output += text.mid(cursor, tokenEnd - cursor); cursor = tokenEnd; continue; } output += text.mid(cursor, left - cursor + 1); const QChar suffix = compactSuffixForToken(match.captured(1)); if (suffix.isNull()) { output += match.captured(0); } else { if (suffix == UnicodeChars::DegreeSign && !isInsideTrigCallArgument(tokenStart)) { output += match.captured(0); cursor = tokenEnd; continue; } const QChar leftChar = text.at(left); const bool alreadyHasSameSuffix = leftChar == suffix || (suffix == UnicodeChars::DegreeSign && (leftChar == UnicodeChars::MasculineOrdinalIndicator || leftChar == UnicodeChars::RingAbove)); if (!alreadyHasSameSuffix) output += suffix; } cursor = tokenEnd; } output += text.mid(cursor); return output; } inline bool containsExplicitBracketedAngleUnit(const QString& expression) { QRegularExpressionMatchIterator matches = RegExpPatterns::unitBrackets().globalMatch(expression); while (matches.hasNext()) { const QRegularExpressionMatch match = matches.next(); if (Units::isExplicitAngleUnitName(match.captured(1))) return true; } return false; } inline bool containsExplicitSexagesimalAngleMarkers(const QString& expression) { for (const QChar ch : expression) { if (ch == UnicodeChars::DegreeSign || ch == UnicodeChars::MasculineOrdinalIndicator || ch == UnicodeChars::RingOperator || ch == UnicodeChars::Prime || ch == UnicodeChars::DoublePrime || ch == UnicodeChars::Apostrophe || ch == UnicodeChars::QuotationMark) { return true; } } return false; } inline bool isStandaloneSexagesimalAngleLiteral(const QString& expression) { if (!RegExpPatterns::standaloneSexagesimalAngleLiteralAllowed().match(expression).hasMatch()) return false; if (!RegExpPatterns::anyDigit().match(expression).hasMatch()) return false; return containsExplicitSexagesimalAngleMarkers(expression); } inline QString foldRepeatedAdditiveTermsForDisplay(const QString& text) { if (text.isEmpty()) return text; const Tokens tokens = Evaluator::instance()->scan(text); if (!tokens.valid() || tokens.isEmpty()) return text; QVector splitOps; int depth = 0; for (int i = 0; i < tokens.size(); ++i) { const Token::Operator op = tokens.at(i).asOperator(); if (op == Token::AssociationStart) { ++depth; continue; } if (op == Token::AssociationEnd) { if (depth > 0) --depth; continue; } if (depth == 0 && (op == Token::Addition || op == Token::Subtraction)) splitOps.append(i); } if (splitOps.isEmpty()) return text; auto tokenRangeText = [&text, &tokens](int startIndex, int endIndex) { const int startPos = tokens.at(startIndex).pos(); const int endPos = tokens.at(endIndex).pos() + tokens.at(endIndex).size(); return text.mid(startPos, endPos - startPos); }; auto isMinusChar = [](const QChar& ch) { return ch == MathDsl::SubOp || ch == MathDsl::SubOpAl1; }; auto formatCoeff = [](double value) { return QString::number(value, 'g', 15); }; auto normalizeKey = [](QString s) { s.remove(QRegularExpression(QStringLiteral("\\s+"))); return s; }; auto isNumericPowerLiteralRange = [](const Tokens& parsed, int start, int end, const auto& self) -> bool { if (start < 0 || end >= parsed.size() || start > end) return false; // Strip unary prefix. while (start <= end) { const Token::Operator op = parsed.at(start).asOperator(); if (op == Token::Addition || op == Token::Subtraction || op == Token::BitwiseLogicalNOT) { ++start; continue; } break; } // Strip postfix operators. while (start <= end) { const Token::Operator op = parsed.at(end).asOperator(); if (op == Token::Percent || op == Token::Factorial) { --end; continue; } break; } if (start > end) return false; // Single numeric token (covers rendered superscript numbers too). if (start == end && parsed.at(start).isNumber()) return true; // Unwrap one full parenthesized layer. if (parsed.at(start).asOperator() == Token::AssociationStart && parsed.at(end).asOperator() == Token::AssociationEnd) { int depth = 0; bool enclosesWholeRange = true; for (int i = start; i <= end; ++i) { const Token::Operator op = parsed.at(i).asOperator(); if (op == Token::AssociationStart) ++depth; else if (op == Token::AssociationEnd) --depth; if (depth == 0 && i < end) { enclosesWholeRange = false; break; } } if (enclosesWholeRange) return self(parsed, start + 1, end - 1, self); } // Accept numeric powers recursively: a^b where both sides are numeric literals/powers. int exponentOp = -1; int depth = 0; for (int i = start; i <= end; ++i) { const Token::Operator op = parsed.at(i).asOperator(); if (op == Token::AssociationStart) { ++depth; continue; } if (op == Token::AssociationEnd) { --depth; continue; } if (depth == 0 && op == Token::Exponentiation) { if (exponentOp >= 0) return false; exponentOp = i; } } if (exponentOp <= start || exponentOp >= end) return false; return self(parsed, start, exponentOp - 1, self) && self(parsed, exponentOp + 1, end, self); }; auto isNumericLiteralOrPowerLiteral = [&isNumericPowerLiteralRange](const QString& factorText) { auto isWholeWrappedByParentheses = [](const QString& text) { if (text.size() < 2 || text.at(0) != MathDsl::GroupStart || text.at(text.size() - 1) != MathDsl::GroupEnd) return false; int depth = 0; for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd) --depth; if (depth == 0 && i < text.size() - 1) return false; } return depth == 0; }; auto isDisplayedNumericPowerLiteralText = [&isWholeWrappedByParentheses](QString text) { text = text.trimmed(); while (isWholeWrappedByParentheses(text)) text = text.mid(1, text.size() - 2).trimmed(); if (text.isEmpty()) return false; bool hasDigit = false; for (const QChar& ch : text) { if (ch.isDigit()) { hasDigit = true; continue; } if (MathDsl::isSuperscriptPowerChar(ch)) continue; if (ch == MathDsl::PowOp || ch == MathDsl::AddOp || ch == MathDsl::SubOp || ch == MathDsl::SubOpAl1 || ch == QLatin1Char('.') || ch == QLatin1Char(',')) { continue; } return false; } return hasDigit; }; if (isDisplayedNumericPowerLiteralText(factorText)) return true; const Tokens parsed = Evaluator::instance()->scan(factorText); if (!parsed.valid() || parsed.isEmpty()) return false; return isNumericPowerLiteralRange(parsed, 0, parsed.size() - 1, isNumericPowerLiteralRange); }; QHash coeffByKey; QHash displayByKey; QVector keyOrder; int termStart = 0; for (int part = 0; part <= splitOps.size(); ++part) { const int opIndex = (part < splitOps.size()) ? splitOps.at(part) : -1; const int termEnd = (opIndex >= 0) ? (opIndex - 1) : (tokens.size() - 1); if (termEnd < termStart) { termStart = opIndex + 1; continue; } const QString opText = (part == 0) ? QString(MathDsl::AddOp) : tokenRangeText(splitOps.at(part - 1), splitOps.at(part - 1)); QString termText = tokenRangeText(termStart, termEnd).trimmed(); termStart = opIndex + 1; if (termText.isEmpty()) continue; bool negFromTerm = false; while (!termText.isEmpty() && (termText.at(0) == MathDsl::AddOp || isMinusChar(termText.at(0)))) { if (isMinusChar(termText.at(0))) negFromTerm = !negFromTerm; termText.remove(0, 1); termText = termText.trimmed(); } if (termText.isEmpty()) continue; bool ok = false; double numericFactor = 1.0; QString base = termText; const Tokens termTokens = Evaluator::instance()->scan(termText); if (termTokens.valid() && termTokens.size() >= 3 && termTokens.at(0).isNumber() && termTokens.at(1).asOperator() == Token::Multiplication) { numericFactor = termTokens.at(0).text().toDouble(&ok); if (ok && numericFactor != 0.0) { const int baseStart = termTokens.at(2).pos(); const int baseEnd = termTokens.at(termTokens.size() - 1).pos() + termTokens.at(termTokens.size() - 1).size(); if (baseStart >= 0 && baseEnd > baseStart && baseEnd <= termText.size()) base = termText.mid(baseStart, baseEnd - baseStart).trimmed(); } else { ok = false; } } else { ok = true; } if (!ok || base.isEmpty()) continue; const bool minusOp = (opText.size() == 1 && isMinusChar(opText.at(0))); const double signedFactor = (minusOp ? -1.0 : 1.0) * (negFromTerm ? -numericFactor : numericFactor); const QString key = normalizeKey(base); if (!coeffByKey.contains(key)) { keyOrder.append(key); displayByKey.insert(key, base); } coeffByKey[key] += signedFactor; } QString rebuilt; for (const QString& key : keyOrder) { const double coeff = coeffByKey.value(key, 0.0); if (std::abs(coeff) < 1e-12) continue; const QString base = displayByKey.value(key, key); const bool negative = coeff < 0.0; const double magnitude = std::abs(coeff); QString term = base; if (std::abs(magnitude - 1.0) >= 1e-12) { const QChar mulOp = isNumericLiteralOrPowerLiteral(base) ? MathDsl::MulCrossOp : MathDsl::MulDotOp; const QChar mulWrap = (mulOp == MathDsl::MulCrossOp) ? MathDsl::MulCrossWrapSp : MathDsl::MulDotWrapSp; // Keep coefficient*term rendering on the same DSL-wrapped spacing // path used by display formatting, so mixed-alias inputs do not // regress to compact "4·x" while other paths show "4 · x". term = formatCoeff(magnitude) + MathDsl::buildWrappedToken(mulOp, mulWrap) + base; } if (rebuilt.isEmpty()) { rebuilt = negative ? (QString(MathDsl::SubOpAl1) + term) : term; } else { rebuilt += negative ? QString(MathDsl::SubOpAl1) : QString(MathDsl::AddOp); rebuilt += term; } } return rebuilt.isEmpty() ? text : rebuilt; } inline QString simplifiedExpressionLineForDisplay(const QString& commentedInterpretedExpression, const QString& commentedSourceExpression, bool simplifyResultExpressions, const Evaluator* evaluator = nullptr) { if (!simplifyResultExpressions) return QString(); const QString interpretedExpression = commentedInterpretedExpression.section(MathDsl::CommentSep, 0, 0); const QString sourceExpression = commentedSourceExpression.section(MathDsl::CommentSep, 0, 0); auto splitConversionSides = [](const QString& expression, QString* leftOut, QString* rightOut) -> bool { const QString asciiArrow = QString(MathDsl::SubOpAl1) + QString(MathDsl::GreaterThanOp); int splitPos = expression.lastIndexOf(MathDsl::TransOp); int splitWidth = 1; if (splitPos < 0) { splitPos = expression.lastIndexOf(asciiArrow); splitWidth = asciiArrow.size(); } if (splitPos < 0) return false; if (leftOut) *leftOut = expression.left(splitPos).trimmed(); if (rightOut) *rightOut = expression.mid(splitPos + splitWidth).trimmed(); return true; }; QString sourceLeft; QString sourceRight; const bool sourceHasConversionTarget = splitConversionSides(sourceExpression, &sourceLeft, &sourceRight); QString expressionForSimplification = interpretedExpression; if (sourceHasConversionTarget) { QString interpretedLeft; QString interpretedRight; if (splitConversionSides(interpretedExpression, &interpretedLeft, &interpretedRight) && !interpretedLeft.isEmpty()) { expressionForSimplification = interpretedLeft; } else if (!sourceLeft.isEmpty()) { expressionForSimplification = sourceLeft; } else if (!sourceRight.isEmpty()) { expressionForSimplification = sourceRight; } } if (expressionForSimplification.isEmpty()) { if (!sourceLeft.isEmpty()) expressionForSimplification = sourceLeft; else if (!sourceRight.isEmpty()) expressionForSimplification = sourceRight; const bool sourceHasExplicitAngles = containsExplicitBracketedAngleUnit(sourceExpression) || containsExplicitSexagesimalAngleMarkers(sourceExpression); if (sourceHasExplicitAngles) expressionForSimplification = sourceExpression; } if (expressionForSimplification.isEmpty()) return QString(); QString interpretedDisplay = DisplayFormatUtils::applyDigitGroupingForDisplay( Evaluator::formatInterpretedExpressionForDisplay(expressionForSimplification, evaluator)); QString simplifiedDisplay = DisplayFormatUtils::applyDigitGroupingForDisplay( Evaluator::formatInterpretedExpressionSimplifiedForDisplay(expressionForSimplification, evaluator)); if (!sourceExpression.isEmpty()) { interpretedDisplay = DisplayFormatUtils::preserveConversionTargetBracketsForDisplay( interpretedDisplay, sourceExpression); simplifiedDisplay = DisplayFormatUtils::preserveConversionTargetBracketsForDisplay( simplifiedDisplay, sourceExpression); } interpretedDisplay = normalizeBracketedUnitTextForDisplay(interpretedDisplay); simplifiedDisplay = normalizeBracketedUnitTextForDisplay(simplifiedDisplay); interpretedDisplay = collapseValueUnitMultiplicationForDisplay(interpretedDisplay); simplifiedDisplay = collapseValueUnitMultiplicationForDisplay(simplifiedDisplay); interpretedDisplay = collapseBracketedCompactAngleSuffixes(interpretedDisplay); simplifiedDisplay = collapseBracketedCompactAngleSuffixes(simplifiedDisplay); if (simplifiedDisplay.isEmpty() || simplifiedDisplay == interpretedDisplay || simplifiedDisplay == SimplifiedExpressionUtils::expressionWithoutTopLevelComment( interpretedDisplay)) { return QString(); } if (SimplifiedExpressionUtils::shouldSuppressSimplifiedExpressionLine( interpretedDisplay, simplifiedDisplay)) return QString(); return foldRepeatedAdditiveTermsForDisplay(simplifiedDisplay); } inline bool splitConversionExpressionForDisplay(const QString& expression, QString* leftOut, QString* rightOut) { const int asciiArrowPos = expression.lastIndexOf(QString(MathDsl::SubOpAl1) + MathDsl::GreaterThanOp); const int unicodeArrowPos = expression.lastIndexOf(MathDsl::TransOp); int textualInPos = -1; QRegularExpressionMatchIterator inMatches = QRegularExpression(QStringLiteral("\\bin\\b"), QRegularExpression::CaseInsensitiveOption).globalMatch(expression); while (inMatches.hasNext()) textualInPos = inMatches.next().capturedStart(); int arrowPos = -1; int arrowWidth = 0; if (asciiArrowPos >= 0 && asciiArrowPos >= unicodeArrowPos && asciiArrowPos >= textualInPos) { arrowPos = asciiArrowPos; arrowWidth = 2; } else if (unicodeArrowPos >= 0 && unicodeArrowPos >= textualInPos) { arrowPos = unicodeArrowPos; arrowWidth = 1; } else if (textualInPos >= 0) { arrowPos = textualInPos; arrowWidth = 2; } if (arrowPos < 0) return false; if (leftOut) *leftOut = expression.left(arrowPos).trimmed(); if (rightOut) *rightOut = expression.mid(arrowPos + arrowWidth).trimmed(); return true; } inline QString conversionTargetSuffixForDisplay(const QString& expression) { QString target; if (!splitConversionExpressionForDisplay(expression, nullptr, &target)) return QString(); if (target.isEmpty()) return QString(); return QStringLiteral(" \u2192 ") + target; } inline QString formattedExpressionLineForDisplay(const QString& sourceExpression, const QString& interpretedExpression, const Evaluator* evaluator = nullptr) { // Keep prose outside every expression-formatting pass, including unit and // conversion formatting that runs after the evaluator restores the comment. const int sourceCommentPos = sourceExpression.indexOf(MathDsl::CommentSep); const int interpretedCommentPos = interpretedExpression.indexOf(MathDsl::CommentSep); const QString& expression = sourceCommentPos >= 0 ? sourceExpression : interpretedExpression; const int commentPos = sourceCommentPos >= 0 ? sourceCommentPos : interpretedCommentPos; if (commentPos >= 0) { const QString comment = expression.mid(commentPos + 1).trimmed(); const QString displayed = formattedExpressionLineForDisplay( sourceCommentPos >= 0 ? sourceExpression.left(sourceCommentPos).trimmed() : sourceExpression, interpretedCommentPos >= 0 ? interpretedExpression.left(interpretedCommentPos).trimmed() : interpretedExpression, evaluator); return displayed + (displayed.isEmpty() ? QStringLiteral("?") : QStringLiteral(" ?")) + (comment.isEmpty() ? QString() : QStringLiteral(" ") + comment); } const QString sourceConversionTargetSuffix = conversionTargetSuffixForDisplay(sourceExpression); if (!sourceConversionTargetSuffix.isEmpty()) { QString sourceLeft; splitConversionExpressionForDisplay(sourceExpression, &sourceLeft, nullptr); const bool preserveConvertedStandaloneSexagesimalAngle = isStandaloneSexagesimalAngleLiteral(sourceLeft) && !sourceLeft.contains(MathDsl::UnitStart) && !sourceLeft.contains(MathDsl::UnitEnd); if (preserveConvertedStandaloneSexagesimalAngle) { return DisplayFormatUtils::applyDigitGroupingForDisplay( UnicodeChars::normalizePiForDisplay(sourceLeft)) + sourceConversionTargetSuffix; } } const bool preserveStandaloneSexagesimalAngle = isStandaloneSexagesimalAngleLiteral(sourceExpression) && !sourceExpression.contains(MathDsl::UnitStart) && !sourceExpression.contains(MathDsl::UnitEnd) && !sourceExpression.contains(QString(MathDsl::SubOpAl1) + MathDsl::GreaterThanOp) && !sourceExpression.contains(MathDsl::TransOp); if (preserveStandaloneSexagesimalAngle) { return DisplayFormatUtils::applyDigitGroupingForDisplay( UnicodeChars::normalizePiForDisplay(sourceExpression.trimmed())); } const QString interpretedSource = interpretedExpression.isEmpty() ? sourceExpression : interpretedExpression; const QString displayed = DisplayFormatUtils::applyDigitGroupingForDisplay( UnicodeChars::normalizePiForDisplay( Evaluator::formatInterpretedExpressionForDisplay(interpretedSource, evaluator))); return collapseBracketedCompactAngleSuffixes( collapseValueUnitMultiplicationForDisplay( preserveExplicitParenthesizedUnitDenominatorFromSource( preserveExplicitParenthesizedQuotientBeforeUnitFromSource( preserveExplicitBracketedSimpleUnitsFromSource( normalizeBracketedUnitTextForDisplay( DisplayFormatUtils::preserveConversionTargetBracketsForDisplay( displayed, sourceExpression)), sourceExpression), sourceExpression), sourceExpression))); } inline QString trimTrailingFractionZeros(QString text) { static const QRegularExpression trailingZerosAfterNonZero( QStringLiteral("([\\.,]\\d*?[1-9])0+$")); static const QRegularExpression onlyZeroFraction( QStringLiteral("[\\.,]0+$")); text.replace(trailingZerosAfterNonZero, QStringLiteral("\\1")); text.replace(onlyZeroFraction, QString()); return text; } inline QString stripDisplayedUnitBrackets(QString text) { const int openBracket = text.lastIndexOf(MathDsl::UnitStart); const int closeBracket = text.lastIndexOf(MathDsl::UnitEnd); if (openBracket >= 0 && closeBracket > openBracket && closeBracket == text.size() - 1) { const QString normalizedUnit = UnitDisplayFormat::normalizeUnitTextForDisplay( text.mid(openBracket + 1, closeBracket - openBracket - 1)); text = text.left(openBracket) + normalizedUnit; } else { text.replace(RegExpPatterns::unitBrackets(), QStringLiteral("\\1")); } auto endsWithPowerOfTenScientificNotation = [](const QString& prefix) { const QString trimmed = prefix.trimmed(); return RegExpPatterns::trailingPowerOfTenScientificNotation().match(trimmed).hasMatch(); }; auto collapseTrailingCompactSuffix = [&text, &endsWithPowerOfTenScientificNotation](const QChar suffix) { const QString quantSpVariant = QString(MathDsl::QuantSp) + suffix; const QString asciiSpVariant = QStringLiteral(" ") + suffix; const QString compactVariant = QString(suffix); if (text.endsWith(quantSpVariant)) { if (endsWithPowerOfTenScientificNotation( text.left(text.size() - quantSpVariant.size()))) { return; } text.chop(quantSpVariant.size()); text += suffix; } else if (text.endsWith(asciiSpVariant)) { if (endsWithPowerOfTenScientificNotation( text.left(text.size() - asciiSpVariant.size()))) { return; } text.chop(asciiSpVariant.size()); text += suffix; } else if (text.endsWith(compactVariant)) { if (endsWithPowerOfTenScientificNotation( text.left(text.size() - compactVariant.size()))) { text.insert(text.size() - compactVariant.size(), MathDsl::QuantSp); } } }; collapseTrailingCompactSuffix(UnicodeChars::DegreeSign); collapseTrailingCompactSuffix(UnicodeChars::Prime); collapseTrailingCompactSuffix(UnicodeChars::DoublePrime); return text; } inline bool isPureTimeQuantity(const Quantity& value) { if (!value.hasDimension()) return false; const auto dimension = value.getDimensionByQuantity(); if (dimension.count() != 1 || !dimension.contains(UnitQuantity::Time)) return false; const auto it = dimension.constFind(UnitQuantity::Time); return it != dimension.constEnd() && it->numerator() == 1 && it->denominator() == 1; } inline bool hasCompoundSexagesimalFields(const QString& expression) { const QString trimmed = expression.trimmed(); const QList degreeMarkers = { UnicodeChars::DegreeSign, UnicodeChars::MasculineOrdinalIndicator, UnicodeChars::RingOperator }; for (const QChar marker : degreeMarkers) { const int markerPos = trimmed.indexOf(marker); if (markerPos >= 0) return !trimmed.mid(markerPos + 1).trimmed().isEmpty(); } int minuteSecondMarkerCount = 0; const QList minuteSecondMarkers = { UnicodeChars::Prime, UnicodeChars::DoublePrime, UnicodeChars::Apostrophe, UnicodeChars::QuotationMark }; for (const QChar ch : trimmed) { if (minuteSecondMarkers.contains(ch)) ++minuteSecondMarkerCount; } return minuteSecondMarkerCount > 1; } inline bool shouldPreserveDetailedStandaloneSexagesimalAngle( const QString& sourceExpression, const Quantity& value, const Settings* settings) { return value.isDimensionless() && settings->angleUnit == 'd' && isStandaloneSexagesimalAngleLiteral(sourceExpression) && hasCompoundSexagesimalFields(sourceExpression) && !sourceExpression.contains(QString(MathDsl::SubOpAl1) + MathDsl::GreaterThanOp) && !sourceExpression.contains(MathDsl::TransOp); } inline bool expressionUsesTrigFunction(const QString& sourceExpression, const QString& interpretedExpression, const Evaluator* evaluator = nullptr) { const QString source = interpretedExpression.isEmpty() ? sourceExpression : interpretedExpression; if (RegExpPatterns::trigFunctionCall().match(source).hasMatch()) return true; const QList userFunctions = (evaluator ? evaluator : Evaluator::instance())->getUserFunctions(); if (userFunctions.isEmpty()) return false; QHash bodiesByName; for (const UserFunction& function : userFunctions) { QString body = function.interpretedExpression().trimmed(); if (body.isEmpty()) body = function.expression().trimmed(); if (!body.isEmpty()) bodiesByName.insert(function.name(), body); } if (bodiesByName.isEmpty()) return false; const QRegularExpression& anyFunctionCall = RegExpPatterns::anyFunctionCall(); auto callsUserFunctionByName = [&bodiesByName, &anyFunctionCall](const QString& text) { QRegularExpressionMatchIterator it = anyFunctionCall.globalMatch(text); while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); if (bodiesByName.contains(match.captured(1))) return true; } return false; }; if (!callsUserFunctionByName(source)) return false; QHash memo; QSet visiting; std::function userFunctionUsesTrig = [&](const QString& functionName) -> bool { const auto memoIt = memo.constFind(functionName); if (memoIt != memo.constEnd()) return memoIt.value(); if (visiting.contains(functionName)) return false; const QString body = bodiesByName.value(functionName); if (body.isEmpty()) return false; visiting.insert(functionName); bool usesTrig = RegExpPatterns::trigFunctionCall().match(body).hasMatch(); if (!usesTrig) { QRegularExpressionMatchIterator it = anyFunctionCall.globalMatch(body); while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); const QString callee = match.captured(1); if (bodiesByName.contains(callee) && userFunctionUsesTrig(callee)) { usesTrig = true; break; } } } visiting.remove(functionName); memo.insert(functionName, usesTrig); return usesTrig; }; QRegularExpressionMatchIterator sourceCalls = anyFunctionCall.globalMatch(source); while (sourceCalls.hasNext()) { const QRegularExpressionMatch match = sourceCalls.next(); const QString called = match.captured(1); if (bodiesByName.contains(called) && userFunctionUsesTrig(called)) return true; } return false; } inline bool expressionUsesPhasorOperator(const QString& sourceExpression, const QString& interpretedExpression) { return sourceExpression.contains(MathDsl::PhasorOp) || interpretedExpression.contains(MathDsl::PhasorOp); } inline bool shouldShowAdditionalRationalForTrig(const Settings* settings, const QString& sourceExpression, const QString& interpretedExpression, const Quantity& value, const Evaluator* evaluator = nullptr) { const bool hasRationalAlready = settings->resultFormat == 'r' || (settings->multipleResultLinesEnabled && settings->secondaryResultEnabled && settings->alternativeResultFormat == 'r') || (settings->multipleResultLinesEnabled && settings->tertiaryResultEnabled && settings->tertiaryResultFormat == 'r') || (settings->multipleResultLinesEnabled && settings->quaternaryResultEnabled && settings->quaternaryResultFormat == 'r') || (settings->multipleResultLinesEnabled && settings->quinaryResultEnabled && settings->quinaryResultFormat == 'r'); if (hasRationalAlready) return false; if (!expressionUsesTrigFunction(sourceExpression, interpretedExpression, evaluator)) return false; return !NumberFormatter::formatTrigSymbolic(value).isEmpty(); } inline QString conversionTargetText(const QString& expression) { const int asciiArrowPos = expression.lastIndexOf(QString(MathDsl::SubOpAl1) + MathDsl::GreaterThanOp); const int unicodeArrowPos = expression.lastIndexOf(MathDsl::TransOp); int arrowPos = -1; int arrowWidth = 0; if (asciiArrowPos >= 0 && asciiArrowPos >= unicodeArrowPos) { arrowPos = asciiArrowPos; arrowWidth = 2; } else if (unicodeArrowPos >= 0) { arrowPos = unicodeArrowPos; arrowWidth = 1; } if (arrowPos < 0) return QString(); return expression.mid(arrowPos + arrowWidth).trimmed(); } inline bool isRadianUnitText(QString text) { text = text.trimmed(); if (text.startsWith(MathDsl::UnitStart) && text.endsWith(MathDsl::UnitEnd) && text.size() > 2) text = text.mid(1, text.size() - 2).trimmed(); text = normalizeUnitName(UnicodeChars::normalizeUnitSymbolAliases(text)); return unitId(text) == UnitId::Radian; } inline bool isRadianResultContext(const Settings* settings, const QString& sourceExpression, const QString& interpretedExpression) { if (settings->angleUnit == 'r') return true; const QString sourceTarget = conversionTargetText(sourceExpression); if (!sourceTarget.isEmpty() && isRadianUnitText(sourceTarget)) return true; const QString interpretedTarget = conversionTargetText(interpretedExpression); return !interpretedTarget.isEmpty() && isRadianUnitText(interpretedTarget); } inline bool expressionUsesTrigOrExplicitAngleInput(const QString& sourceExpression, const QString& interpretedExpression, const Evaluator* evaluator = nullptr) { if (expressionUsesTrigFunction(sourceExpression, interpretedExpression, evaluator)) return true; return containsExplicitBracketedAngleUnit(sourceExpression) || containsExplicitBracketedAngleUnit(interpretedExpression) || containsExplicitSexagesimalAngleMarkers(sourceExpression) || containsExplicitSexagesimalAngleMarkers(interpretedExpression); } inline bool tryExtractRealRadiansFromResult(const Quantity& value, HNumber* radiansOut) { if (!radiansOut || value.isNan()) return false; Quantity scalar = value; if (scalar.hasUnit()) { CNumber displayNumber = scalar.numericValue(); displayNumber /= scalar.unit(); if (!displayNumber.isNearReal()) return false; Quantity normalized(displayNumber.real); normalized.setDisplayUnit(CNumber(1), scalar.unitName()); if (!Units::tryConvertExplicitAngleToRadians(&normalized)) return false; scalar = normalized; } if (!scalar.isDimensionless()) return false; const CNumber numeric = scalar.numericValue(); if (!numeric.isNearReal()) return false; *radiansOut = numeric.real; return true; } inline QString formatPiMultipleForRadians(const HNumber& radians) { static const HNumber tolerance("1e-20"); static const int maxDenominator = 3600; Rational ratio; if (!Rational::approximate(radians / HMath::pi(), maxDenominator, tolerance, &ratio)) return QString(); const int numerator = ratio.numerator(); const int denominator = ratio.denominator(); if (numerator == 0 || denominator <= 0) return QString(); const HNumber expected = HMath::pi() * HNumber(numerator) / HNumber(denominator); const HNumber diff = HMath::abs(radians - expected); const HNumber scale = HMath::max(HMath::max(HMath::abs(radians), HMath::abs(expected)), HNumber(1)); if (diff > tolerance * scale) return QString(); const QString division = QString(MathDsl::DivWrap) + QString(MathDsl::DivOp) + QString(MathDsl::DivWrap); const QString multiplication = QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp); const QString pi = QString(UnicodeChars::Pi); const QString sign = (numerator < 0) ? QString(MathDsl::SubOp) : QString(); const int absNumerator = qAbs(numerator); if (denominator == 1) { if (absNumerator == 1) return sign + pi; return sign + QString::number(absNumerator) + multiplication + pi; } if (absNumerator == 1) return sign + pi + division + QString::number(denominator); return sign + QString::number(absNumerator) + division + QString::number(denominator) + multiplication + pi; } inline QString formatPiRadianResultLineIfNeeded(const Settings* settings, const QString& sourceExpression, const QString& interpretedExpression, const Quantity& value, const Evaluator* evaluator = nullptr) { if (expressionUsesPhasorOperator(sourceExpression, interpretedExpression)) return QString(); if (!expressionUsesTrigOrExplicitAngleInput(sourceExpression, interpretedExpression, evaluator)) return QString(); if (!isRadianResultContext(settings, sourceExpression, interpretedExpression)) return QString(); HNumber radians; if (!tryExtractRealRadiansFromResult(value, &radians)) return QString(); const QString piMultiple = formatPiMultipleForRadians(radians); if (piMultiple.isEmpty()) return QString(); return DisplayFormatUtils::applyDigitGroupingForDisplay( piMultiple + QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r')); } inline QString normalizeResultLineForComparison(QString text) { text.replace(MathDsl::QuantSp, QLatin1Char(' ')); text.replace(UnicodeChars::NoBreakSpace, QLatin1Char(' ')); text.replace(MathDsl::SubOp, MathDsl::SubOpAl1); return text; } inline QString appendAngleModeSuffixIfNeeded(const QString& formattedText, const QString& sourceExpression, const QString& interpretedExpression, const Quantity& value, char resultFormat, const Settings* settings, const Evaluator* evaluator = nullptr) { if (resultFormat == 's') return formattedText; if (!value.isDimensionless()) return formattedText; if (formattedText.contains(MathDsl::UnitStart) || formattedText.contains(MathDsl::UnitEnd)) return formattedText; if (expressionUsesTrigFunction(sourceExpression, interpretedExpression, evaluator)) return formattedText; if (expressionUsesPhasorOperator(sourceExpression, interpretedExpression)) return formattedText; const bool hasExplicitBracketedAngleUnit = containsExplicitBracketedAngleUnit(sourceExpression) || containsExplicitBracketedAngleUnit(interpretedExpression); const bool hasExplicitSexagesimalAngleMarkers = containsExplicitSexagesimalAngleMarkers(sourceExpression) || containsExplicitSexagesimalAngleMarkers(interpretedExpression); if (!hasExplicitBracketedAngleUnit && !hasExplicitSexagesimalAngleMarkers) return formattedText; auto endsWithUnitToken = [&formattedText](const QString& token) { return formattedText.endsWith(token) || formattedText.endsWith(QString(MathDsl::QuantSp) + token) || formattedText.endsWith(QStringLiteral(" ") + token); }; if (endsWithUnitToken(Units::angleModeUnitSymbol('r')) || endsWithUnitToken(Units::angleModeUnitSymbol('d')) || endsWithUnitToken(Units::angleModeUnitSymbol('g')) || endsWithUnitToken(Units::angleModeUnitSymbol('t')) || endsWithUnitToken(Units::angleModeUnitSymbol('v')) || formattedText.endsWith(UnicodeChars::Prime) || formattedText.endsWith(UnicodeChars::DoublePrime)) { return formattedText; } const QString symbol = Units::angleModeUnitSymbol(settings->angleUnit); const bool hasPowerOfTenScientificSuffix = RegExpPatterns::trailingPowerOfTenScientificNotation().match( formattedText.trimmed()).hasMatch(); if (settings->angleUnit == 'd' && !hasPowerOfTenScientificSuffix) return formattedText + symbol; return formattedText + QString(MathDsl::QuantSp) + symbol; } inline QString formatNumericResultLine(const Quantity& value, const QString& sourceExpression, const QString& interpretedExpression, char resultFormat, int precision, bool complexNumbers, char complexFormat, bool stripUnitBrackets, const Settings* settings, const Evaluator* evaluator = nullptr) { if (!expressionUsesTrigFunction(sourceExpression, interpretedExpression, evaluator) && shouldPreserveDetailedStandaloneSexagesimalAngle( sourceExpression, value, settings)) { resultFormat = 's'; } Quantity formattedValue = value; if (resultFormat == 's' && isPureTimeQuantity(formattedValue)) formattedValue.stripUnits(); QString formattedText = DisplayFormatUtils::applyDigitGroupingForDisplay( NumberFormatter::format(formattedValue, resultFormat, precision, complexNumbers, complexFormat)); formattedText = NumberFormatter::rewriteScientificNotationForDisplay(formattedText); formattedText.replace(QString::fromUtf8(" × 10�"), QString()); formattedText = appendAngleModeSuffixIfNeeded( formattedText, sourceExpression, interpretedExpression, value, resultFormat, settings, evaluator); return stripUnitBrackets ? stripDisplayedUnitBrackets(formattedText) : formattedText; } inline QStringList formatResultLinesForDisplay(const QString& commentedSourceExpression, const QString& commentedInterpretedExpression, const Quantity& value, bool includeExpressionLine, bool stripUnitBracketsInNumericLines, const Evaluator* evaluator = nullptr, bool resultOnly = false) { const Settings* settings = Settings::instance(); const QString resultPrefix = resultOnly ? QString() : QStringLiteral("= "); QStringList lines; auto appendUniqueLine = [&lines](const QString& line) { if (!line.isEmpty() && !lines.contains(line)) lines.append(line); }; if (includeExpressionLine && !resultOnly) appendUniqueLine(formattedExpressionLineForDisplay( commentedSourceExpression, commentedInterpretedExpression, evaluator)); // Comments belong on the expression line, but must not supply angle, // conversion, or function hints for any result line. const QString sourceExpression = commentedSourceExpression.section(MathDsl::CommentSep, 0, 0); const QString interpretedExpression = commentedInterpretedExpression.section(MathDsl::CommentSep, 0, 0); if (!resultOnly) { const QString simplifiedLine = simplifiedExpressionLineForDisplay( interpretedExpression, sourceExpression, settings->simplifyResultExpressions, evaluator); if (!simplifiedLine.isEmpty()) appendUniqueLine(QStringLiteral("= ") + simplifiedLine); } if (settings->simplifyResultExpressions && isPureTimeQuantity(value) && (SimplifiedExpressionUtils::isStandaloneSexagesimalTimeLiteral(sourceExpression) || SimplifiedExpressionUtils::containsSexagesimalTimeLiteral(sourceExpression))) { Quantity sexagesimalValue(value); sexagesimalValue.stripUnits(); const QString normalizedSexagesimal = DisplayFormatUtils::applyDigitGroupingForDisplay( trimTrailingFractionZeros( NumberFormatter::format(sexagesimalValue, 's', settings->resultPrecision, settings->complexNumbers, settings->resultComplexForm))); appendUniqueLine(resultPrefix + normalizedSexagesimal + conversionTargetSuffixForDisplay(sourceExpression)); } appendUniqueLine(resultPrefix + formatNumericResultLine( value, sourceExpression, interpretedExpression, settings->resultFormat, settings->resultPrecision, settings->complexNumbers, settings->resultComplexForm, stripUnitBracketsInNumericLines, settings, evaluator)); if (settings->multipleResultLinesEnabled && settings->secondaryResultEnabled && settings->alternativeResultFormat != '\0') { appendUniqueLine(resultPrefix + formatNumericResultLine( value, sourceExpression, interpretedExpression, settings->alternativeResultFormat, settings->secondaryResultPrecision, settings->complexNumbers && settings->secondaryComplexNumbers, settings->secondaryResultComplexForm, stripUnitBracketsInNumericLines, settings, evaluator)); } if (settings->multipleResultLinesEnabled && settings->tertiaryResultEnabled && settings->tertiaryResultFormat != '\0') { appendUniqueLine(resultPrefix + formatNumericResultLine( value, sourceExpression, interpretedExpression, settings->tertiaryResultFormat, settings->tertiaryResultPrecision, settings->complexNumbers && settings->tertiaryComplexNumbers, settings->tertiaryResultComplexForm, stripUnitBracketsInNumericLines, settings, evaluator)); } if (settings->multipleResultLinesEnabled && settings->quaternaryResultEnabled && settings->quaternaryResultFormat != '\0') { appendUniqueLine(resultPrefix + formatNumericResultLine( value, sourceExpression, interpretedExpression, settings->quaternaryResultFormat, settings->quaternaryResultPrecision, settings->complexNumbers && settings->quaternaryComplexNumbers, settings->quaternaryResultComplexForm, stripUnitBracketsInNumericLines, settings, evaluator)); } if (settings->multipleResultLinesEnabled && settings->quinaryResultEnabled && settings->quinaryResultFormat != '\0') { appendUniqueLine(resultPrefix + formatNumericResultLine( value, sourceExpression, interpretedExpression, settings->quinaryResultFormat, settings->quinaryResultPrecision, settings->complexNumbers && settings->quinaryComplexNumbers, settings->quinaryResultComplexForm, stripUnitBracketsInNumericLines, settings, evaluator)); } const QString piRadianResultLine = formatPiRadianResultLineIfNeeded( settings, sourceExpression, interpretedExpression, value, evaluator); if (!piRadianResultLine.isEmpty()) appendUniqueLine(resultPrefix + piRadianResultLine); if (shouldShowAdditionalRationalForTrig( settings, sourceExpression, interpretedExpression, value, evaluator)) { const QString trigSymbolicLine = DisplayFormatUtils::applyDigitGroupingForDisplay( NumberFormatter::formatTrigSymbolic(value)); const QString trigSymbolicNormalizedPi = UnicodeChars::normalizePiForDisplay(trigSymbolicLine); if (trigSymbolicNormalizedPi.contains(UnicodeChars::Pi)) return lines; const QString piRadianFromTrigLine = trigSymbolicLine + QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r'); if (piRadianResultLine.isEmpty() || normalizeResultLineForComparison(piRadianResultLine) != normalizeResultLineForComparison(piRadianFromTrigLine)) { appendUniqueLine(resultPrefix + trigSymbolicLine); } } return lines; } } // namespace ResultLineFormatUtils #endif heldercorreia-speedcrunch-e7ca37f/src/gui/simplifiedexpressionutils.h000066400000000000000000000207241526573132500264140ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_SIMPLIFIEDEXPRESSIONUTILS_H #define GUI_SIMPLIFIEDEXPRESSIONUTILS_H #include "core/regexpatterns.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include #include namespace SimplifiedExpressionUtils { inline bool isNumericSimplifiedExpression(const QString& expression) { return RegExpPatterns::signedNumericLiteralWithSpaces().match(expression).hasMatch(); } inline bool isPlainNumericArithmeticExpression(const QString& expression) { static const QRegularExpression pattern( QStringLiteral("^[\\s\\p{Zs}]*[0-9\\.,\\s\\p{Zs}+\\-−*/%()^×÷·�¹²³��������]+[\\s\\p{Zs}]*$")); return pattern.match(expression).hasMatch(); } inline bool isStandaloneSexagesimalTimeLiteral(const QString& expression) { static const QRegularExpression allowedPattern( QStringLiteral("^[\\s\\p{Zs}+\\-−0-9\\.,:]+$")); if (!allowedPattern.match(expression).hasMatch()) return false; const QString compact = expression.simplified().remove(UnicodeChars::Space); const int colonCount = compact.count(QLatin1Char(':')); if (colonCount < 1 || colonCount > 2) return false; if (!compact.contains(QRegularExpression(QStringLiteral("\\d")))) return false; const QString withoutSign = (compact.startsWith(QLatin1Char('+')) || compact.startsWith(MathDsl::SubOpAl1) || compact.startsWith(QChar(UnicodeChars::MinusSign))) ? compact.mid(1) : compact; if (withoutSign.isEmpty() || withoutSign == QLatin1String(":") || withoutSign == QLatin1String("::")) return false; if (withoutSign.contains(QLatin1String(":::"))) return false; return true; } inline bool containsSexagesimalTimeLiteral(const QString& expression) { // Detect colon-based sexagesimal tokens inside larger expressions // (e.g. "23:50:40 + 5:20:50"), while avoiding obvious identifier/decimal // neighbors that are not time literals. static const QRegularExpression tokenPattern( QStringLiteral(R"((?:^|[^0-9A-Za-z_\.])(?:[+\-−]?\d*:\d*(?::\d*)?)(?:$|[^0-9A-Za-z_\.]))")); if (!tokenPattern.match(expression).hasMatch()) return false; static const QRegularExpression hasDigitPattern(QStringLiteral("\\d")); return hasDigitPattern.match(expression).hasMatch(); } inline QString normalizedTokenForCommutativeComparison(const QString& token) { QString normalized = token; normalized.remove(QRegularExpression(QStringLiteral("[\\s\\p{Zs}]"))); return normalized; } inline QString expressionWithoutTopLevelComment(const QString& expression) { int depth = 0; for (int i = 0; i < expression.size(); ++i) { const QChar ch = expression.at(i); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd && depth > 0) --depth; else if (ch == MathDsl::CommentSep && depth == 0) return expression.left(i).trimmed(); } return expression.trimmed(); } inline bool splitSingleTopLevelBinary(const QString& expression, QChar op, QString* leftOut, QString* rightOut) { int depth = 0; int splitPos = -1; int splitCount = 0; for (int i = 0; i < expression.size(); ++i) { const QChar ch = expression.at(i); if (ch == MathDsl::GroupStart) ++depth; else if (ch == MathDsl::GroupEnd) --depth; else if (depth == 0 && ch == op) { // Keep only a single top-level operator (e.g. a+b, not a+b+c). splitPos = i; ++splitCount; if (splitCount > 1) return false; } } if (splitCount != 1 || splitPos <= 0 || splitPos >= expression.size() - 1) return false; const QString left = expression.left(splitPos).trimmed(); const QString right = expression.mid(splitPos + 1).trimmed(); if (left.isEmpty() || right.isEmpty()) return false; *leftOut = left; *rightOut = right; return true; } inline bool isCommutativeTopLevelSwap(const QString& interpretedDisplay, const QString& simplifiedDisplay) { const QChar commutativeOps[] = { MathDsl::AddOp, MathDsl::MulOpAl1, QChar(MathDsl::MulCrossOp), QChar(MathDsl::MulDotOp) }; for (const QChar op : commutativeOps) { QString leftA, rightA, leftB, rightB; if (!splitSingleTopLevelBinary(interpretedDisplay, op, &leftA, &rightA)) continue; if (!splitSingleTopLevelBinary(simplifiedDisplay, op, &leftB, &rightB)) continue; if (normalizedTokenForCommutativeComparison(leftA) == normalizedTokenForCommutativeComparison(rightB) && normalizedTokenForCommutativeComparison(rightA) == normalizedTokenForCommutativeComparison(leftB)) { return true; } } return false; } inline bool parseTopLevelAdditiveTerms(const QString& expression, QStringList* signedTermsOut) { signedTermsOut->clear(); int depth = 0; int tokenStart = 0; int currentSign = +1; bool sawTopLevelAdditiveOperator = false; while (tokenStart < expression.size() && expression.at(tokenStart).isSpace()) ++tokenStart; if (tokenStart < expression.size()) { const QChar first = expression.at(tokenStart); if (MathDsl::isAdditionOperator(first)) { ++tokenStart; } else if (MathDsl::isSubtractionOperator(first)) { currentSign = -1; ++tokenStart; } } auto appendTerm = [&](int endPos) { const QString term = expression.mid(tokenStart, endPos - tokenStart).trimmed(); if (term.isEmpty()) return false; const QString normalized = normalizedTokenForCommutativeComparison(term); if (normalized.isEmpty()) return false; signedTermsOut->append((currentSign < 0 ? QStringLiteral("-") : QStringLiteral("+")) + normalized); return true; }; for (int i = tokenStart; i < expression.size(); ++i) { const QChar ch = expression.at(i); if (ch == MathDsl::GroupStart) { ++depth; continue; } if (ch == MathDsl::GroupEnd) { --depth; continue; } if (depth != 0 || (!MathDsl::isAdditionOperator(ch) && !MathDsl::isSubtractionOperator(ch))) continue; const QString candidate = expression.mid(tokenStart, i - tokenStart).trimmed(); if (candidate.isEmpty()) { if (MathDsl::isSubtractionOperator(ch)) currentSign = -currentSign; tokenStart = i + 1; continue; } if (!appendTerm(i)) return false; sawTopLevelAdditiveOperator = true; currentSign = MathDsl::isSubtractionOperator(ch) ? -1 : +1; tokenStart = i + 1; } if (!appendTerm(expression.size())) return false; return sawTopLevelAdditiveOperator && signedTermsOut->size() > 1; } inline bool isTopLevelAdditiveTermReorder(const QString& interpretedDisplay, const QString& simplifiedDisplay) { QStringList interpretedTerms; QStringList simplifiedTerms; if (!parseTopLevelAdditiveTerms(interpretedDisplay, &interpretedTerms)) return false; if (!parseTopLevelAdditiveTerms(simplifiedDisplay, &simplifiedTerms)) return false; interpretedTerms.sort(); simplifiedTerms.sort(); return interpretedTerms == simplifiedTerms; } inline bool shouldSuppressSimplifiedExpressionLine(const QString& interpretedDisplay, const QString& simplifiedDisplay) { const QString interpretedExpression = expressionWithoutTopLevelComment(interpretedDisplay); const QString simplifiedExpression = expressionWithoutTopLevelComment(simplifiedDisplay); return isCommutativeTopLevelSwap(interpretedExpression, simplifiedExpression) || isTopLevelAdditiveTermReorder(interpretedExpression, simplifiedExpression) || (isPlainNumericArithmeticExpression(interpretedExpression) && (isPlainNumericArithmeticExpression(simplifiedExpression) || isNumericSimplifiedExpression(simplifiedExpression))); } } // namespace SimplifiedExpressionUtils #endif // GUI_SIMPLIFIEDEXPRESSIONUTILS_H heldercorreia-speedcrunch-e7ca37f/src/gui/splittertreeutils.cpp000066400000000000000000000045311526573132500252260ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/splittertreeutils.h" #include #include void normalizeSplitterTree(QSplitter* rootSplitter) { if (rootSplitter == nullptr) return; const auto normalize = [](QSplitter* splitter, const auto& normalizeRef) -> void { if (splitter == nullptr) return; for (int i = splitter->count() - 1; i >= 0; --i) { if (QSplitter* childSplitter = qobject_cast(splitter->widget(i))) normalizeRef(childSplitter, normalizeRef); } for (int i = splitter->count() - 1; i >= 0; --i) { QSplitter* childSplitter = qobject_cast(splitter->widget(i)); if (childSplitter == nullptr) continue; if (childSplitter->count() == 0) { childSplitter->setParent(nullptr); childSplitter->deleteLater(); continue; } if (childSplitter->count() == 1) { QWidget* onlyChild = childSplitter->widget(0); if (onlyChild != nullptr) { onlyChild->setParent(nullptr); splitter->insertWidget(i, onlyChild); } childSplitter->setParent(nullptr); childSplitter->deleteLater(); } } }; normalize(rootSplitter, normalize); while (rootSplitter->count() == 1) { QSplitter* onlyChildSplitter = qobject_cast(rootSplitter->widget(0)); if (onlyChildSplitter == nullptr) break; const Qt::Orientation orientation = onlyChildSplitter->orientation(); const QList childSizes = onlyChildSplitter->sizes(); QList children; while (onlyChildSplitter->count() > 0) { QWidget* child = onlyChildSplitter->widget(0); child->setParent(nullptr); children.append(child); } rootSplitter->setOrientation(orientation); for (QWidget* child : children) rootSplitter->addWidget(child); if (childSizes.size() == rootSplitter->count()) rootSplitter->setSizes(childSizes); onlyChildSplitter->setParent(nullptr); onlyChildSplitter->deleteLater(); } } heldercorreia-speedcrunch-e7ca37f/src/gui/splittertreeutils.h000066400000000000000000000003651526573132500246740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_SPLITTERTREEUTILS_H #define GUI_SPLITTERTREEUTILS_H class QSplitter; void normalizeSplitterTree(QSplitter* rootSplitter); #endif heldercorreia-speedcrunch-e7ca37f/src/gui/startupappearance.h000066400000000000000000000072721526573132500246130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_STARTUPAPPEARANCE_H #define GUI_STARTUPAPPEARANCE_H #include "core/startupdiagnostics.h" #include "core/colorscheme.h" #include "core/settings.h" #include #include #include #include #include #include namespace StartupDiagnostics { inline QByteArray appearanceInputs(const QVariantList& values) { if (!isRecording()) return {}; QByteArray bytes; QDataStream stream(&bytes, QIODevice::WriteOnly); stream << values; return QCryptographicHash::hash(bytes, QCryptographicHash::Sha256); } inline QByteArray themeInputs(const ColorScheme& scheme) { if (!isRecording()) return {}; QVariantList values {scheme.isValid()}; for (const auto& role : ColorScheme::roleNames()) { values.append(scheme.hasColorForRole(role.second)); values.append(scheme.colorForRole(role.second)); } // Invalid schemes and missing accents can use application palette colors. if (!scheme.isValid() || !scheme.hasColorForRole(ColorScheme::Primary)) { values.append(QApplication::palette().color(QPalette::Base)); values.append(QApplication::palette().color(QPalette::Text)); } return appearanceInputs(values); } inline QByteArray configuredThemeInputs() { if (!isRecording()) return {}; const Settings* settings = Settings::instance(); return appearanceInputs({settings->colorScheme, settings->colorScheme == QLatin1String("Custom") ? settings->customColorSchemeJson : QString()}); } inline void observeHighlightInputs(AppearanceScope& scope, QPlainTextEdit* widget, const QByteArray& theme, const QVariantList& surfaces, const QObject* evaluator) { if (!isRecording()) return; scope.observeInputs("document", appearanceInputs({widget->document()->revision(), widget->document()->characterCount(), widget->document()->blockCount()})); scope.observeInputs("theme", appearanceInputs({theme, QVariant(surfaces)})); const Settings* settings = Settings::instance(); scope.observeInputs("settings", appearanceInputs({settings->syntaxHighlighting, settings->digitGrouping, settings->digitGroupingIntegerPartOnly, settings->inputDigitGrouping, settings->digitGroupingSeparator(), int(settings->radixCharacter()), int(settings->editorDisplayStyle), widget->font()})); // Identity says which evaluator is attached, not whether its symbols change. const int evaluatorId = appearanceObjectId(evaluator); if (evaluatorId >= 0) scope.observeInputs("evaluator", appearanceInputs({evaluatorId})); } inline void observeAppearanceSettings(AppearanceScope& scope) { if (!isRecording()) return; const Settings* settings = Settings::instance(); scope.observeInputs("appearance", appearanceInputs({int(settings->menuAppearance), int(settings->dockAppearance), int(settings->statusBarAppearance), int(settings->keypadAppearance), int(settings->editorDisplayStyle)})); } // Keep the existing setter calls, including identical assignments. inline void setAppearancePalette(QWidget* widget, const QPalette& palette) { if (isRecording()) appearanceAssignment(widget, true, widget->palette() != palette, false); widget->setPalette(palette); } inline void setAppearanceStyleSheet(QWidget* widget, const QString& styleSheet) { if (isRecording()) appearanceAssignment(widget, false, widget->styleSheet() != styleSheet, false); widget->setStyleSheet(styleSheet); } } #endif heldercorreia-speedcrunch-e7ca37f/src/gui/startupfontpreparation.h000066400000000000000000000025561526573132500257270ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_STARTUPFONTPREPARATION_H #define GUI_STARTUPFONTPREPARATION_H #include "core/startupdiagnostics.h" #include #include #include #include class StartupFontPreparation { public: StartupFontPreparation() { if (QGuiApplication::platformName() != QLatin1String("cocoa")) return; // The first text widget otherwise loads the font database on the UI // thread. QFontDatabase is thread-safe, so overlap that work with native // menu and window construction after QApplication has initialized. const auto task = StartupDiagnostics::task("Prepare font database (async total)"); m_thread.reset(QThread::create([task]() { { StartupDiagnostics::Scope timing("Prepare font database"); QFontDatabase::families(); } if (task) task->finish(); })); m_thread->start(); } ~StartupFontPreparation() { wait(); } void wait() { if (!m_thread) return; StartupDiagnostics::Scope timing("Wait for font preparation"); m_thread->wait(); m_thread.reset(); } private: std::unique_ptr m_thread; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/syntaxhighlighter.cpp000066400000000000000000000725271526573132500251760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2010, 2013-2016, 2018, 2021, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/syntaxhighlighter.h" #include "gui/startupappearance.h" #include "core/evaluator.h" #include "core/functions.h" #include "core/mathdsl.h" #include "core/numberformatter.h" #include "core/settings.h" #include #include #include #include static const constexpr auto DefaultColorSchemeName = "Terminal"; static QString textNormalizedForHighlighting(QString text) { static const QHash superscriptToAscii { {MathDsl::PowNeg, MathDsl::SubOpAl1}, // � SUPERSCRIPT MINUS. {MathDsl::Pow0, QLatin1Char('0')}, // � {MathDsl::Pow1, QLatin1Char('1')}, // ¹ {MathDsl::Pow2, QLatin1Char('2')}, // ² {MathDsl::Pow3, QLatin1Char('3')}, // ³ {MathDsl::Pow4, QLatin1Char('4')}, // � {MathDsl::Pow5, QLatin1Char('5')}, // � {MathDsl::Pow6, QLatin1Char('6')}, // � {MathDsl::Pow7, QLatin1Char('7')}, // � {MathDsl::Pow8, QLatin1Char('8')}, // � {MathDsl::Pow9, QLatin1Char('9')}, // � }; for (QChar& ch : text) { const QChar replacement = superscriptToAscii.value(ch, QChar::Null); if (!replacement.isNull()) ch = replacement; } return text; } static bool isSuperscriptExponentChar(QChar ch) { return ch == MathDsl::PowNeg || MathDsl::isSuperscriptDigit(ch); } static bool hasSuperscriptExponent(const QString& tokenText) { for (const QChar ch : tokenText) { if (isSuperscriptExponentChar(ch)) return true; } return false; } static QString stripTrailingAsciiDigits(QString text) { while (!text.isEmpty() && text.at(text.size() - 1).isDigit()) text.chop(1); return text; } SyntaxHighlighter::SyntaxHighlighter(QPlainTextEdit* edit, bool inputEditor) : QSyntaxHighlighter(edit) , m_evaluator(Evaluator::instance()) , m_inputEditor(inputEditor) { StartupDiagnostics::Scope timing("Initialize syntax highlighter"); setDocument(edit->document()); update(); } const Evaluator* SyntaxHighlighter::evaluator() const { return m_evaluator ? m_evaluator : Evaluator::instance(); } void SyntaxHighlighter::setEvaluator(const Evaluator* evaluator) { StartupDiagnostics::AppearanceScope timing("Bind syntax highlighter evaluator", parent()); m_evaluator = evaluator ? evaluator : Evaluator::instance(); { StartupDiagnostics::AppearanceScope highlightTiming( m_inputEditor ? "Highlight editor document" : "Highlight result document", parent()); rehighlight(); } } void SyntaxHighlighter::setColorScheme(ColorScheme&& colorScheme) { m_colorScheme = colorScheme; } void SyntaxHighlighter::highlightBlock(const QString& text) { highlightSyntaxBlock(text); if (m_inputEditor && Settings::instance()->inputDigitGrouping) groupInputDigits(text); } void SyntaxHighlighter::groupInputDigits(const QString& text) { // Keep the user's expression intact. For example, typing "1000" leaves // four characters in the document even when it appears as "1,000". // QSyntaxHighlighter formats belong to the text layout, not to an edit of // the document, so grouping creates no cursor stops or undo commands. // Copying, saving and evaluation still use the original expression. const Settings* settings = Settings::instance(); const QString separator = settings->digitGroupingSeparator(); const QFontMetricsF metrics(document()->defaultFont()); const auto groupPart = [this, &separator, &metrics](int start, int end, int groupSize, bool fractional) { for (int boundary : NumberFormatter::digitGroupingPositions(end - start, groupSize, fractional)) { // Reserve the separator's width after the preceding digit. Qt uses // this width for wrapping and cursor placement. Store the glyph as // a format property so Editor can paint it inside that gap. const int pos = start + boundary - 1; QTextCharFormat fmt = format(pos); fmt.setFontLetterSpacingType(QFont::AbsoluteSpacing); fmt.setFontLetterSpacing(metrics.horizontalAdvance(separator)); fmt.setProperty(InputDigitSeparator, separator); setFormat(pos, 1, fmt); } }; const Tokens tokens = evaluator()->scan(textNormalizedForHighlighting(text)); for (const Token& token : tokens) { if (token.type() != Token::stxNumber) continue; int start = token.pos(); const int limit = qMin(text.size(), start + token.size()); if (start < 0 || start >= limit) continue; while (start < limit && text.at(start).isSpace()) ++start; int base = 10; if (start < limit && text.at(start) == MathDsl::HexPrefixAl1) { base = 16; ++start; } else if (start + 1 < limit && text.at(start) == QLatin1Char('0')) { const QChar prefix = text.at(start + 1).toLower(); if (prefix == QLatin1Char('x')) base = 16; else if (prefix == QLatin1Char('b')) base = 2; else if (prefix == QLatin1Char('o')) base = 8; if (base != 10 || prefix == QLatin1Char('d')) start += 2; } const auto isDigit = [base](QChar ch) { ch = ch.toLower(); const int digit = ch >= QLatin1Char('0') && ch <= QLatin1Char('9') ? ch.unicode() - '0' : ch >= QLatin1Char('a') && ch <= QLatin1Char('f') ? ch.unicode() - 'a' + 10 : -1; return digit >= 0 && digit < base; }; int end = start; while (end < limit && isDigit(text.at(end))) ++end; // Leave manually spaced groups alone rather than adding separators twice. int next = end; while (next < limit && (text.at(next).isSpace() || text.at(next) == QLatin1Char('_'))) ++next; if (next > end && next < limit && isDigit(text.at(next))) continue; const int groupSize = base == 2 || base == 16 ? 4 : 3; if (end < limit && QString(text.at(end)) == separator) { // A pasted number may already contain the selected grouping marks. // Do not mistake those marks for an alternate decimal separator. const QString tail = text.mid(end + 1, limit - end - 1).trimmed(); bool groupedTail = tail.size() == groupSize && end - start <= groupSize; for (QChar ch : tail) groupedTail = groupedTail && isDigit(ch); if (groupedTail || tail.contains(QChar(settings->decimalSeparator())) || tail.contains(separator)) continue; } groupPart(start, end, groupSize, false); if (end < limit && Evaluator::isRadixChar(text.at(end))) { if (text.at(end) != QChar(settings->decimalSeparator())) { // Decimal separator changes are also visual. Editor paints the // selected separator over this character, leaving the typed // separator in the source expression and on the clipboard. QTextCharFormat fmt = format(end); fmt.setProperty(InputRadixReplacement, QString(QChar(settings->decimalSeparator()))); setFormat(end, 1, fmt); } const int fractionalStart = end + 1; int fractionalEnd = fractionalStart; while (fractionalEnd < limit && isDigit(text.at(fractionalEnd))) ++fractionalEnd; groupPart(fractionalStart, fractionalEnd, groupSize, true); } } } void SyntaxHighlighter::highlightSyntaxBlock(const QString& text) { // Default color for the text setFormat(0, text.length(), colorForRole(ColorScheme::Number)); if (!Settings::instance()->syntaxHighlighting) return; const SyntaxHighlightBlockData* blockData = dynamic_cast(currentBlockUserData()); if (text.startsWith(MathDsl::Equals)) { setFormat(0, 1, colorForRole(ColorScheme::Operator)); const int expressionOffset = text.size() > 1 && text.at(1) == UnicodeChars::Space ? 2 : 1; const QString expressionText = text.mid(expressionOffset); const bool highlightResultExpressionSyntax = blockData && blockData->highlightResultExpressionSyntax; if (!highlightResultExpressionSyntax) { setFormat(1, text.length(), colorForRole(ColorScheme::Result)); if (Settings::instance()->digitGrouping > 0) { // Use token-based grouping for result lines as well, so // integer-only grouping works when lexer splits around radix chars. const Tokens tokens = evaluator()->scan(text); for (int i = 0; i < tokens.count(); ++i) { const Token& token = tokens.at(i); if (token.type() != Token::stxNumber) continue; if (Settings::instance()->digitGroupingIntegerPartOnly && i > 0 && !tokens.at(i - 1).text().isEmpty() && (tokens.at(i - 1).type() == Token::stxSep || tokens.at(i - 1).type() == Token::stxOperator) && Evaluator::isRadixChar(tokens.at(i - 1).text().at(0).unicode())) { continue; } groupDigits(text, token.pos(), token.size()); } } return; } setFormat(expressionOffset, text.length() - expressionOffset, colorForRole(ColorScheme::Number)); int questionMarkIndex = expressionText.indexOf(MathDsl::CommentSep); if (questionMarkIndex != -1) setFormat(expressionOffset + questionMarkIndex, expressionText.length() - questionMarkIndex, colorForRole(ColorScheme::Comment)); const QString normalizedExpressionText = textNormalizedForHighlighting(expressionText); Tokens tokens = evaluator()->scan(normalizedExpressionText); int unitBracketDepth = 0; for (int i = 0; i < tokens.count(); ++i) { const Token& token = tokens.at(i); const QString tokenText = token.text().toLower(); QStringList functionNames = FunctionRepo::instance()->getIdentifiers(); QColor color; const bool insideUnitBrackets = unitBracketDepth > 0; switch (token.type()) { case Token::stxNumber: case Token::stxUnknown: color = colorForRole(insideUnitBrackets ? ColorScheme::Unit : ColorScheme::Number); break; case Token::stxOperator: color = colorForRole(insideUnitBrackets ? ColorScheme::Unit : ColorScheme::Operator); break; case Token::stxSep: color = colorForRole(insideUnitBrackets ? ColorScheme::Unit : ColorScheme::Separator); break; case Token::stxOpenPar: case Token::stxClosePar: color = colorForRole(ColorScheme::Parens); if (token.text() == QString(MathDsl::UnitStart) || token.text() == QString(MathDsl::UnitEnd)) color = colorForRole(ColorScheme::Unit); break; case Token::stxIdentifier: color = colorForRole(ColorScheme::Variable); if (evaluator()->hasUserFunction(token.text()) || functionNames.contains(tokenText, Qt::CaseInsensitive)) color = colorForRole(ColorScheme::Function); else if (i + 1 < tokens.count() && tokens.at(i + 1).type() == Token::stxOpenPar && token.pos() >= 0 && token.pos() + token.size() <= expressionText.size()) { const QString originalTokenText = expressionText.mid(token.pos(), token.size()); if (hasSuperscriptExponent(originalTokenText)) { const QString baseName = stripTrailingAsciiDigits(token.text()); if (evaluator()->hasUserFunction(baseName) || functionNames.contains(baseName.toLower(), Qt::CaseInsensitive)) { color = colorForRole(ColorScheme::Function); } } } break; case Token::stxUnitIdentifier: color = colorForRole(ColorScheme::Unit); break; default: break; } if (color.isValid()) setFormat(expressionOffset + token.pos(), token.size(), color); if ((token.type() == Token::stxIdentifier || token.type() == Token::stxUnitIdentifier) && token.pos() >= 0 && token.pos() + token.size() <= expressionText.size()) { const QString originalTokenText = expressionText.mid(token.pos(), token.size()); for (int j = 0; j < originalTokenText.size(); ++j) { if (isSuperscriptExponentChar(originalTokenText.at(j))) setFormat(expressionOffset + token.pos() + j, 1, token.type() == Token::stxUnitIdentifier ? colorForRole(ColorScheme::Unit) : colorForRole(ColorScheme::Number)); } } if (token.text() == QString(MathDsl::UnitStart)) ++unitBracketDepth; else if (token.text() == QString(MathDsl::UnitEnd)) unitBracketDepth = qMax(0, unitBracketDepth - 1); } return; } int questionMarkIndex = text.indexOf(MathDsl::CommentSep); if (questionMarkIndex != -1) setFormat(questionMarkIndex, text.length(), colorForRole(ColorScheme::Comment)); const QString normalizedText = textNormalizedForHighlighting(text); Tokens tokens = evaluator()->scan(normalizedText); int unitBracketDepth = 0; for (int i = 0; i < tokens.count(); ++i) { const Token& token = tokens.at(i); const QString tokenText = token.text().toLower(); QStringList functionNames = FunctionRepo::instance()->getIdentifiers(); QColor color; const bool insideUnitBrackets = unitBracketDepth > 0; switch (token.type()) { case Token::stxNumber: case Token::stxUnknown: color = colorForRole(ColorScheme::Number); if (insideUnitBrackets) color = colorForRole(ColorScheme::Unit); // TODO: color thousand separators differently? It might help troubleshooting issues break; case Token::stxOperator: color = colorForRole(ColorScheme::Operator); if (insideUnitBrackets) color = colorForRole(ColorScheme::Unit); break; case Token::stxSep: color = colorForRole(ColorScheme::Separator); if (insideUnitBrackets) color = colorForRole(ColorScheme::Unit); break; case Token::stxOpenPar: case Token::stxClosePar: color = colorForRole(ColorScheme::Parens); if (token.text() == QString(MathDsl::UnitStart) || token.text() == QString(MathDsl::UnitEnd)) color = colorForRole(ColorScheme::Unit); break; case Token::stxIdentifier: color = colorForRole(ColorScheme::Variable); if (evaluator()->hasUserFunction(token.text()) || functionNames.contains(tokenText, Qt::CaseInsensitive)) color = colorForRole(ColorScheme::Function); else if (i + 1 < tokens.count() && tokens.at(i + 1).type() == Token::stxOpenPar && token.pos() >= 0 && token.pos() + token.size() <= text.size()) { const QString originalTokenText = text.mid(token.pos(), token.size()); if (hasSuperscriptExponent(originalTokenText)) { const QString baseName = stripTrailingAsciiDigits(token.text()); if (evaluator()->hasUserFunction(baseName) || functionNames.contains(baseName.toLower(), Qt::CaseInsensitive)) { color = colorForRole(ColorScheme::Function); } } } break; case Token::stxUnitIdentifier: color = colorForRole(ColorScheme::Unit); break; default: break; }; setFormat(token.pos(), token.size(), color); if ((token.type() == Token::stxIdentifier || token.type() == Token::stxUnitIdentifier) && token.pos() >= 0 && token.pos() + token.size() <= text.size()) { const QString originalTokenText = text.mid(token.pos(), token.size()); for (int j = 0; j < originalTokenText.size(); ++j) { if (isSuperscriptExponentChar(originalTokenText.at(j))) setFormat(token.pos() + j, 1, token.type() == Token::stxUnitIdentifier ? colorForRole(ColorScheme::Unit) : colorForRole(ColorScheme::Number)); } } if (token.type() == Token::stxOpenPar && token.text() == QString(MathDsl::UnitStart)) ++unitBracketDepth; else if (token.type() == Token::stxClosePar && token.text() == QString(MathDsl::UnitEnd)) unitBracketDepth = qMax(0, unitBracketDepth - 1); if (token.type() == Token::stxNumber && Settings::instance()->digitGrouping > 0) { // If the lexer split a decimal number around the radix character, // avoid grouping the fractional token when integer-only grouping is enabled. if (Settings::instance()->digitGroupingIntegerPartOnly && i > 0 && !tokens.at(i - 1).text().isEmpty() && (tokens.at(i - 1).type() == Token::stxSep || tokens.at(i - 1).type() == Token::stxOperator) && Evaluator::isRadixChar(tokens.at(i - 1).text().at(0).unicode())) { continue; } groupDigits(text, token.pos(), token.size()); } } for (int i = 0; i < text.size(); ++i) { const QChar ch = text.at(i); if (ch == MathDsl::ListStart || ch == MathDsl::ListEnd) setFormat(i, 1, colorForRole(ColorScheme::List)); } } void SyntaxHighlighter::update() { StartupDiagnostics::AppearanceScope timing("Update syntax highlighter", parent()); updateColorScheme(); QColor backgroundColor = colorForRole(ColorScheme::Background); QWidget* parentWidget = static_cast(parent()); QPalette pal = parentWidget->palette(); pal.setColor(QPalette::Active, QPalette::Base, backgroundColor); pal.setColor(QPalette::Inactive, QPalette::Base, backgroundColor); StartupDiagnostics::setAppearancePalette(parentWidget, pal); { StartupDiagnostics::AppearanceScope highlightTiming( m_inputEditor ? "Highlight editor document" : "Highlight result document", parent()); rehighlight(); } } void SyntaxHighlighter::updateColorScheme() { const Settings* settings = Settings::instance(); const QString name = settings->colorScheme; if (name == QLatin1String("Custom")) { const QJsonDocument customDoc = QJsonDocument::fromJson(settings->customColorSchemeJson.toUtf8()); ColorScheme customScheme(customDoc); if (customScheme.isValid()) setColorScheme(std::move(customScheme)); else setColorScheme(ColorScheme::loadByName(DefaultColorSchemeName)); } else { setColorScheme(ColorScheme::loadByName(name)); } } void SyntaxHighlighter::formatDigitsGroup(const QString& text, int start, int end, bool invert, int size) { Q_ASSERT(start <= end); Q_ASSERT(size > 0); qreal spacing = 100; // Size of the space between groups (100 means no space). spacing += 40 * Settings::instance()->digitGrouping; int inc = !invert ? -1 : 1; if(!invert) { int tmp = start; start = end - 1; end = tmp - 1; // Skip the first digit so that we add the spacing to the first digit of the next group. while (start != end && Evaluator::isSeparatorChar(text[start].unicode())) --start; if (start == end) return; // Bug ? --start; } for (int count = 0 ; start != end ; start += inc) { // When there are separators in the number, we must not count them as part of the group. if (!Evaluator::isSeparatorChar(text[start].unicode())) { ++count; if (count == size) { // Only change the letter spacing from the format and keep the other properties. QTextCharFormat fmt = format(start); fmt.setFontLetterSpacing(spacing); setFormat(start, 1, fmt); count = 0; // Reset // TODO: if the next character is a separator, do not add spacing? } } } } void SyntaxHighlighter::groupDigits(const QString& text, int pos, int length) { // Used to find out which characters belong to which radixes. static int charType[128] = { 0 }; static const int BIN_CHAR = (1 << 0); static const int OCT_CHAR = (1 << 1); static const int DEC_CHAR = (1 << 2); static const int HEX_CHAR = (1 << 3); if (charType[int('0')] == 0) { // Initialize the table on first call (not thread-safe!). charType[int('0')] = HEX_CHAR | DEC_CHAR | OCT_CHAR | BIN_CHAR; charType[int('1')] = HEX_CHAR | DEC_CHAR | OCT_CHAR | BIN_CHAR; charType[int('2')] = HEX_CHAR | DEC_CHAR | OCT_CHAR; charType[int('3')] = HEX_CHAR | DEC_CHAR | OCT_CHAR; charType[int('4')] = HEX_CHAR | DEC_CHAR | OCT_CHAR; charType[int('5')] = HEX_CHAR | DEC_CHAR | OCT_CHAR; charType[int('6')] = HEX_CHAR | DEC_CHAR | OCT_CHAR; charType[int('7')] = HEX_CHAR | DEC_CHAR | OCT_CHAR; charType[int('8')] = HEX_CHAR | DEC_CHAR; charType[int('9')] = HEX_CHAR | DEC_CHAR; charType[int('a')] = HEX_CHAR; charType[int('b')] = HEX_CHAR; charType[int('c')] = HEX_CHAR; charType[int('d')] = HEX_CHAR; charType[int('e')] = HEX_CHAR; charType[int('f')] = HEX_CHAR; charType[int('A')] = HEX_CHAR; charType[int('B')] = HEX_CHAR; charType[int('C')] = HEX_CHAR; charType[int('D')] = HEX_CHAR; charType[int('E')] = HEX_CHAR; charType[int('F')] = HEX_CHAR; } int s = -1; // Index of the first digit (most significant). int radixPos = -1; // Index of radix char for the current number, if any. bool invertGroup = false; // If true, group digits from the most significant digit. int groupSize = 3; // Number of digits to group (depends on the radix). int allowedChars = DEC_CHAR; // Allowed characters for the radix of the current number being parsed. int endPos = pos + length; if (endPos > text.length()) endPos = text.length(); for (int i = pos; i < endPos; ++i) { ushort c = text[i].unicode(); bool isDigit = c < 128 && (charType[c] & allowedChars); if (s >= 0) { if (!isDigit) { bool endOfNumber = true; if (Evaluator::isRadixChar(c) && i < endPos - 1) { // Radix characters keep integer and fractional digits in the same number. ushort nextC = text[i + 1].unicode(); if (nextC < 128 && (charType[nextC] & allowedChars)) endOfNumber = false; } // If this is a separator and next character is a digit or a separator, // the next character is part of the same number expression if (Evaluator::isSeparatorChar(c) && i= 0 && Settings::instance()->digitGroupingIntegerPartOnly) formatDigitsGroup(text, s, radixPos, false, groupSize); else formatDigitsGroup(text, s, i, invertGroup, groupSize); s = -1; // Reset. radixPos = -1; // Reset. } } } else { if (isDigit) { // Start of number found. s = i; radixPos = -1; } } if (!isDigit) { if (Evaluator::isRadixChar(c)) { if (Settings::instance()->digitGroupingIntegerPartOnly) radixPos = i; else invertGroup = true; // Invert the grouping for the fractional part. } else if (!Evaluator::isSeparatorChar(c)){ // Look for a radix prefix. invertGroup = false; radixPos = -1; if (i > 0 && text[i - 1] == '0') { if (c == 'x') { groupSize = 4; allowedChars = HEX_CHAR; } else if (c == 'o') { groupSize = 3; allowedChars = OCT_CHAR; } else if (c == 'b') { groupSize = 4; allowedChars = BIN_CHAR; } else { groupSize = 3; allowedChars = DEC_CHAR; } } else { groupSize = 3; allowedChars = DEC_CHAR; } } } } // Group the last digits if the string finishes with the number. if (s >= 0) { if (radixPos >= 0 && Settings::instance()->digitGroupingIntegerPartOnly) formatDigitsGroup(text, s, radixPos, false, groupSize); else formatDigitsGroup(text, s, endPos, invertGroup, groupSize); } } // Original code snippet from StackOverflow. // http://stackoverflow.com/questions/15280452/how-can-i-get-highlighted-text-from-a-qsyntaxhighlighter-into-an-html-string void SyntaxHighlighter::asHtml(QString& html) { // Create a new document from all the selected text document. QTextCursor cursor(document()); cursor.select(QTextCursor::Document); QTextDocument* tempDocument(new QTextDocument); Q_ASSERT(tempDocument); QTextCursor tempCursor(tempDocument); tempCursor.insertFragment(cursor.selection()); tempCursor.select(QTextCursor::Document); // Set the default foreground for the inserted characters. QTextCharFormat textfmt = tempCursor.charFormat(); textfmt.setForeground(Qt::gray); tempCursor.setCharFormat(textfmt); // Apply the additional formats set by the syntax highlighter const QTextBlock firstBlock = document()->findBlock(cursor.selectionStart()); const QTextBlock endBlock = document()->findBlock(cursor.selectionEnd()).next(); const int selectionStart = cursor.selectionStart(); const int endOfDocument = tempDocument->characterCount() - 1; for(QTextBlock current = firstBlock; current.isValid() && current != endBlock; current = current.next()) { const QTextLayout* layout(current.layout()); foreach(const QTextLayout::FormatRange &range, layout->formats()) { const int start = current.position() + range.start - selectionStart; const int end = start + range.length; if(end <= 0 || start >= endOfDocument) continue; tempCursor.setPosition(qMax(start, 0)); tempCursor.setPosition(qMin(end, endOfDocument), QTextCursor::KeepAnchor); tempCursor.setCharFormat(range.format); } } // Reset the user states since they are not interesting for(QTextBlock block = tempDocument->begin(); block.isValid(); block = block.next()) block.setUserState(-1); // Make sure the text appears pre-formatted, and set the background we want. tempCursor.select(QTextCursor::Document); QTextBlockFormat blockFormat = tempCursor.blockFormat(); blockFormat.setNonBreakableLines(true); blockFormat.setBackground(colorForRole(ColorScheme::Background)); tempCursor.setBlockFormat(blockFormat); // Finally retreive the syntax higlighted and formatted html. html = tempCursor.selection().toHtml(); delete tempDocument; // Inject CSS, so to avoid a white margin html.replace("", QString(" ") .arg(colorForRole(ColorScheme::Background).name())); } heldercorreia-speedcrunch-e7ca37f/src/gui/syntaxhighlighter.h000066400000000000000000000034741526573132500246360ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2010, 2013-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_SYNTAXHIGHLIGHTER_H #define GUI_SYNTAXHIGHLIGHTER_H #include "core/colorscheme.h" #include #include class QPlainTextEdit; class Evaluator; class SyntaxHighlightBlockData : public QTextBlockUserData { public: bool highlightResultExpressionSyntax = false; }; class SyntaxHighlighter : public QSyntaxHighlighter { Q_OBJECT public: // Layout metadata read by Editor's paint code. These properties describe // visible separators without inserting or replacing document characters. static constexpr int InputDigitSeparator = QTextFormat::UserProperty; static constexpr int InputRadixReplacement = QTextFormat::UserProperty + 1; explicit SyntaxHighlighter(QPlainTextEdit*, bool inputEditor = false); void setColorScheme(ColorScheme&&); void setEvaluator(const Evaluator* evaluator); QColor colorForRole(ColorScheme::Role role) const { return m_colorScheme.colorForRole(role); } void update(); // Load colors without changing the widget palette or document formatting. void updateColorScheme(); virtual void highlightBlock(const QString&); void asHtml(QString& html); private: Q_DISABLE_COPY(SyntaxHighlighter) SyntaxHighlighter(); SyntaxHighlighter(QObject*); SyntaxHighlighter(QTextDocument*); void groupDigits(const QString& text, int pos, int length); void highlightSyntaxBlock(const QString& text); void groupInputDigits(const QString& text); void formatDigitsGroup(const QString& text, int start, int end, bool invert, int size); const Evaluator* evaluator() const; ColorScheme m_colorScheme; const Evaluator* m_evaluator; const bool m_inputEditor; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/themedlineedit.cpp000066400000000000000000000075511526573132500244100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/themedlineedit.h" #include #include #include #include #include #include #include #include #include namespace { const char* kHideNativeCursorProperty = "speedcrunchHideNativeTextCursor"; constexpr int kThemedCursorWidth = 2; constexpr int kThemedCursorXOffset = 1; class ThemedLineEditStyle : public QProxyStyle { public: int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override { if (metric == QStyle::PM_TextCursorWidth && dynamic_cast(widget) != nullptr && widget->property(kHideNativeCursorProperty).toBool()) { return 0; } return QProxyStyle::pixelMetric(metric, option, widget); } }; } ThemedLineEdit::ThemedLineEdit(QWidget* parent) : QLineEdit(parent) , m_cursorStyle(new ThemedLineEditStyle) , m_cursorBlinkTimer(new QTimer(this)) { m_cursorStyle->setParent(this); m_cursorBlinkTimer->setSingleShot(false); connect(m_cursorBlinkTimer, &QTimer::timeout, this, [this]() { m_cursorVisible = !m_cursorVisible; update(themedCursorRect()); }); connect(this, &QLineEdit::cursorPositionChanged, this, [this]() { showCursorAndRestartBlink(); }); connect(this, &QLineEdit::textEdited, this, [this]() { showCursorAndRestartBlink(); }); } void ThemedLineEdit::setCursorColor(const QColor& color) { if (m_cursorColor == color) return; m_cursorColor = color; setStyle(color.isValid() ? m_cursorStyle : nullptr); update(); } void ThemedLineEdit::focusInEvent(QFocusEvent* event) { QLineEdit::focusInEvent(event); showCursorAndRestartBlink(); } void ThemedLineEdit::focusOutEvent(QFocusEvent* event) { hideCursorAndStopBlink(); QLineEdit::focusOutEvent(event); } void ThemedLineEdit::paintEvent(QPaintEvent* event) { if (!m_cursorColor.isValid()) { QLineEdit::paintEvent(event); return; } setProperty(kHideNativeCursorProperty, true); QLineEdit::paintEvent(event); setProperty(kHideNativeCursorProperty, QVariant()); if (!hasFocus() || !m_cursorVisible || !m_cursorColor.isValid()) return; const QRect cursorRect = themedCursorRect(); QPainter painter(this); painter.setPen(Qt::NoPen); painter.fillRect(cursorRect, m_cursorColor); } void ThemedLineEdit::showCursorAndRestartBlink() { m_cursorVisible = true; if (hasFocus()) { const int cursorFlashTime = QApplication::cursorFlashTime(); const int blinkInterval = cursorFlashTime > 0 ? qMax(1, cursorFlashTime / 2) : 500; m_cursorBlinkTimer->start(blinkInterval); } update(); } void ThemedLineEdit::hideCursorAndStopBlink() { m_cursorBlinkTimer->stop(); m_cursorVisible = false; update(themedCursorRect()); } QRect ThemedLineEdit::themedCursorRect() const { const QRect nativeRect = inputMethodQuery(Qt::ImCursorRectangle).toRect(); if (nativeRect.isValid() && nativeRect.height() > 0) { return QRect(nativeRect.x() + (nativeRect.width() - kThemedCursorWidth) / 2 + kThemedCursorXOffset, nativeRect.y(), kThemedCursorWidth, nativeRect.height()); } QStyleOptionFrame option; initStyleOption(&option); const QRect contentRect = style()->subElementRect(QStyle::SE_LineEditContents, &option, this); const int height = qMax(1, contentRect.height() - 4); return QRect(contentRect.left(), contentRect.top() + (contentRect.height() - height) / 2, kThemedCursorWidth, height); } heldercorreia-speedcrunch-e7ca37f/src/gui/themedlineedit.h000066400000000000000000000015761526573132500240560ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_THEMEDLINEEDIT_H #define GUI_THEMEDLINEEDIT_H #include #include class QFocusEvent; class QPaintEvent; class QStyle; class QTimer; class ThemedLineEdit : public QLineEdit { public: explicit ThemedLineEdit(QWidget* parent = nullptr); QColor cursorColor() const { return m_cursorColor; } void setCursorColor(const QColor& color); protected: void focusInEvent(QFocusEvent* event) override; void focusOutEvent(QFocusEvent* event) override; void paintEvent(QPaintEvent* event) override; private: void showCursorAndRestartBlink(); void hideCursorAndStopBlink(); QRect themedCursorRect() const; QColor m_cursorColor; QStyle* m_cursorStyle; QTimer* m_cursorBlinkTimer; bool m_cursorVisible = false; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/tooltipstyleutils.cpp000066400000000000000000000236661526573132500252650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/tooltipstyleutils.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include namespace ToolTipStyleUtils { void applyRoundedPopupMask(QWidget* popup, int cornerRadius) { if (popup == nullptr) return; if (cornerRadius > 0) { QBitmap mask(popup->size()); mask.fill(Qt::color0); QPainter painter(&mask); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); painter.setBrush(Qt::color1); painter.drawRoundedRect(QRectF(mask.rect()).adjusted(0, 0, -1, -1), cornerRadius, cornerRadius); popup->setMask(mask); } else { popup->clearMask(); } } QPoint constrainedPopupPosition(QWidget* anchor, const QPoint& globalPos, const QSize& popupSize) { constexpr int kPopupOffsetX = 12; constexpr int kPopupOffsetY = 18; QPoint pos = globalPos + QPoint(kPopupOffsetX, kPopupOffsetY); QScreen* screen = anchor != nullptr ? anchor->screen() : QGuiApplication::primaryScreen(); if (screen == nullptr) return pos; const QRect available = screen->availableGeometry(); if (pos.x() + popupSize.width() > available.right()) pos.setX(globalPos.x() - popupSize.width() - kPopupOffsetX); if (pos.y() + popupSize.height() > available.bottom()) pos.setY(globalPos.y() - popupSize.height() - kPopupOffsetY); pos.setX(qBound(available.left(), pos.x(), qMax(available.left(), available.right() - popupSize.width()))); pos.setY(qBound(available.top(), pos.y(), qMax(available.top(), available.bottom() - popupSize.height()))); return pos; } QFrame* createPopup(QWidget* parent, const QString& popupObjectName, const QString& labelObjectName, Qt::TextFormat textFormat, QLabel** label, bool transparentForMouseEvents, const QMargins& contentsMargins) { QFrame* popup = new QFrame(parent, Qt::ToolTip | Qt::FramelessWindowHint); popup->setObjectName(popupObjectName); popup->setAutoFillBackground(true); popup->setAttribute(Qt::WA_ShowWithoutActivating, true); popup->setAttribute(Qt::WA_StyledBackground, true); popup->setAttribute(Qt::WA_TransparentForMouseEvents, transparentForMouseEvents); popup->setFocusPolicy(Qt::NoFocus); popup->setFrameStyle(QFrame::NoFrame); QVBoxLayout* layout = new QVBoxLayout(popup); layout->setContentsMargins(contentsMargins); layout->setSpacing(0); QLabel* popupLabel = new QLabel(popup); popupLabel->setObjectName(labelObjectName); popupLabel->setTextFormat(textFormat); popupLabel->setTextInteractionFlags(Qt::NoTextInteraction); popupLabel->setAttribute(Qt::WA_TransparentForMouseEvents); layout->addWidget(popupLabel); if (label != nullptr) *label = popupLabel; return popup; } void applyPopupTheme(QFrame* popup, QLabel* label, QWidget* paletteSource, const PopupTheme& theme) { if (popup == nullptr || label == nullptr) return; const QPalette sourcePalette = paletteSource != nullptr ? paletteSource->palette() : popup->palette(); const QColor background = theme.background.isValid() ? theme.background : sourcePalette.color(QPalette::ToolTipBase); const QColor foreground = theme.foreground.isValid() ? theme.foreground : sourcePalette.color(QPalette::ToolTipText); const QColor outline = theme.outline.isValid() ? theme.outline : background; const int cornerRadius = qMax(0, theme.cornerRadius); QPalette popupPalette = popup->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { popupPalette.setColor(group, QPalette::Window, background); popupPalette.setColor(group, QPalette::WindowText, foreground); } popup->setPalette(popupPalette); QPalette labelPalette = label->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { labelPalette.setColor(group, QPalette::WindowText, foreground); labelPalette.setColor(group, QPalette::Text, foreground); } label->setPalette(labelPalette); popup->setStyleSheet(QStringLiteral( "QFrame#%1 {" " background: %3; color: %4;" " border: %6px solid %5;" " border-radius: %7px;" "}" "QLabel#%2 {" " background: transparent; color: %4;" "}") .arg(popup->objectName(), label->objectName(), background.name(), foreground.name(), outline.name()) .arg(UiConfig::PopupOutlineStrokeWidth) .arg(cornerRadius)); applyRoundedPopupMask(popup, cornerRadius); } void applyTreePopupTheme(QTreeWidget* popup, const TreePopupTheme& theme) { if (popup == nullptr || !theme.background.isValid() || !theme.foreground.isValid()) return; const QColor scrollbarThumb = theme.scrollbarThumb.isValid() ? theme.scrollbarThumb : theme.background; const QColor scrollbarThumbForeground = theme.scrollbarThumbForeground.isValid() ? theme.scrollbarThumbForeground : theme.foreground; const QColor selectedRow = theme.selectedRow.isValid() ? theme.selectedRow : scrollbarThumb; const QColor selectedRowForeground = theme.selectedRowForeground.isValid() ? theme.selectedRowForeground : scrollbarThumbForeground; const QColor outline = theme.outline.isValid() ? theme.outline : theme.background; const int cornerRadius = qMax(0, theme.cornerRadius); QPalette palette = popup->palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { palette.setColor(group, QPalette::Base, theme.background); palette.setColor(group, QPalette::Window, theme.background); palette.setColor(group, QPalette::Text, theme.foreground); palette.setColor(group, QPalette::WindowText, theme.foreground); palette.setColor(group, QPalette::Highlight, selectedRow); palette.setColor(group, QPalette::HighlightedText, selectedRowForeground); } popup->setPalette(palette); popup->viewport()->setPalette(palette); popup->viewport()->setAutoFillBackground(true); popup->setCursor(Qt::PointingHandCursor); popup->viewport()->setCursor(Qt::PointingHandCursor); popup->setStyleSheet(QStringLiteral( "QTreeWidget {" " background: %1; color: %2;" " selection-background-color: %3; selection-color: %4;" " border: %8px solid %6;" " border-radius: %7px;" "}" "QTreeWidget::item:selected {" " background: %3; color: %4;" "}" "QScrollBar:vertical {" " background: %1; border: 0; margin: 0; width: 10px;" "}" "QScrollBar:horizontal {" " background: %1; border: 0; margin: 0; height: 10px;" "}" "QScrollBar::handle:vertical {" " background: %5; border: 0; border-radius: 4px; min-height: 20px;" "}" "QScrollBar::handle:horizontal {" " background: %5; border: 0; border-radius: 4px; min-width: 20px;" "}" "QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical," "QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {" " background: %1; border: 0; width: 0; height: 0;" "}" "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical," "QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {" " background: %1;" "}") .arg(theme.background.name(), theme.foreground.name(), selectedRow.name(), selectedRowForeground.name(), scrollbarThumb.name(), outline.name()) .arg(cornerRadius) .arg(UiConfig::PopupOutlineStrokeWidth)); } QString labelToolTipStyleSheet(const QString& selector, const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius) { return QStringLiteral( "%1 {" " background-color: %2;" " color: %3;" " border: %6px solid %4;" " border-radius: %5px;" "}") .arg(selector, background.name(), foreground.name(), outline.name()) .arg(qMax(0, cornerRadius)) .arg(UiConfig::PopupOutlineStrokeWidth); } void showPopup(QFrame* popup, QLabel* label, const QString& text, QWidget* anchor, const QPoint& globalPos, int cornerRadius) { if (popup == nullptr || label == nullptr || text.isEmpty() || anchor == nullptr) return; label->setText(text); popup->adjustSize(); popup->resize(popup->sizeHint()); applyRoundedPopupMask(popup, qMax(0, cornerRadius)); popup->move(constrainedPopupPosition(anchor, globalPos, popup->size())); popup->show(); } } heldercorreia-speedcrunch-e7ca37f/src/gui/tooltipstyleutils.h000066400000000000000000000037621526573132500247250ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_TOOLTIPSTYLEUTILS_H #define GUI_TOOLTIPSTYLEUTILS_H #include #include #include #include #include class QLabel; class QFrame; class QSize; class QTreeWidget; class QWidget; namespace ToolTipStyleUtils { struct PopupTheme { QColor background; QColor foreground; QColor outline; int cornerRadius = 0; }; struct TreePopupTheme { QColor background; QColor foreground; QColor scrollbarThumb; QColor scrollbarThumbForeground; QColor selectedRow; QColor selectedRowForeground; QColor outline; int cornerRadius = 0; }; void applyRoundedPopupMask(QWidget* popup, int cornerRadius); void applyPopupTheme(QFrame* popup, QLabel* label, QWidget* paletteSource, const PopupTheme& theme); void applyTreePopupTheme(QTreeWidget* popup, const TreePopupTheme& theme); QPoint constrainedPopupPosition(QWidget* anchor, const QPoint& globalPos, const QSize& popupSize); QFrame* createPopup(QWidget* parent, const QString& popupObjectName, const QString& labelObjectName, Qt::TextFormat textFormat, QLabel** label, bool transparentForMouseEvents = false, const QMargins& contentsMargins = QMargins(6, 4, 6, 4)); QString labelToolTipStyleSheet(const QString& selector, const QColor& background, const QColor& foreground, const QColor& outline, int cornerRadius); void showPopup(QFrame* popup, QLabel* label, const QString& text, QWidget* anchor, const QPoint& globalPos, int cornerRadius); } #endif heldercorreia-speedcrunch-e7ca37f/src/gui/uiconfig.h000066400000000000000000000115701526573132500226700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_UICONFIG_H #define GUI_UICONFIG_H namespace UiConfig { constexpr int SessionPaneSplitterWidth = 1; constexpr int DockSplitterStrokeWidth = 2; constexpr int SystemDockSplitterStrokeWidth = 1; constexpr int OutlineStrokeWidth = 2; constexpr int ControlCornerRadius = 8; constexpr int ModernEditorHorizontalMargin = 8; constexpr int ModernEditorTopMargin = 4; constexpr int ModernEditorBottomMargin = 8; constexpr int ModernEditorHorizontalPadding = 6; constexpr int ModernEditorVerticalPadding = 6; constexpr int ModernEditorCornerRadius = ControlCornerRadius; constexpr int ClassicTextInset = 8; constexpr int ClassicEditorVerticalPadding = 4; constexpr int ClassicUnfocusedSeparatorWidth = 1; constexpr int PopupOutlineStrokeWidth = 1; constexpr int ActiveSessionTabIndicatorStrokeWidth = 2; constexpr int SessionTabHorizontalPadding = 36; constexpr int KeypadButtonMargin = 3; constexpr int KeypadButtonPadding = 3; constexpr int KeypadButtonCornerRadius = ControlCornerRadius; constexpr int ClassicKeypadButtonMargin = 1; constexpr int ClassicKeypadButtonPadding = 1; constexpr int ClassicKeypadButtonCornerRadius = 3; // 0 keeps keyed buttons on the normal button surface; 100 gives them the full // primary fill. Intermediate values blend in OKLCH while using the primary hue. constexpr int KeypadDigitPrimaryHueChromaPercent = 25; constexpr int KeypadOperatorPrimaryHueChromaPercent = 50; constexpr int KeypadEvaluatePrimaryHueChromaPercent = 90; constexpr double KeypadButtonGradientLightnessDelta = 0.035; // Keep generated text comfortably readable on tinted surfaces. If a surface // cannot reach this ratio, use whichever contrasts better, black or white. constexpr double GeneratedTextMinimumContrast = 10.0; // Enables the temporary OKLCH HTML diagnostics report in the system temp // directory. Keep disabled for normal builds; it is only useful while tuning // generated theme surfaces. constexpr bool OklchThemeDebugReportEnabled = false; // Theme surfaces are generated as six OKLCH shades from the result-display // background. Keep visual-role-to-shade choices here so small UI tuning does // not require hunting through individual widgets. constexpr int Shade100 = 0; constexpr int Shade200 = 1; constexpr int Shade300 = 2; constexpr int Shade400 = 3; constexpr int Shade500 = 4; constexpr int Shade600 = 5; constexpr int WindowBackgroundShade = Shade100; constexpr int ResultDisplayShade = Shade200; constexpr int SplitterShade = Shade300; constexpr int ClassicVerticalPaneDividerShade = Shade400; constexpr bool SplitterHoverUsesPrimary = true; constexpr int SplitterHoverShade = Shade400; constexpr int ScrollToBottomButtonBackgroundShade = Shade300; constexpr int ScrollToBottomButtonHoverBackgroundShade = Shade400; constexpr int ScrollToBottomButtonOutlineShade = Shade400; constexpr int ResultTooltipBackgroundShade = Shade400; constexpr int ResultTooltipOutlineShade = Shade500; constexpr int ResultTooltipCornerRadius = ControlCornerRadius; constexpr int ResultTooltipStartMargin = ModernEditorHorizontalMargin; constexpr int CompletionPopupBackgroundShade = Shade400; constexpr int CompletionPopupScrollbarThumbShade = Shade500; constexpr int CompletionPopupSelectedRowShade = Shade500; constexpr int CompletionPopupOutlineShade = Shade600; constexpr int CompletionPopupCornerRadius = ControlCornerRadius; constexpr int ResultDisplayScrollbarShade = Shade300; constexpr int ResultDisplayScrollbarHoverShade = Shade400; constexpr int ResultDisplayScrollbarPressedShade = Shade500; constexpr int SelectedSessionTabFillShade = Shade400; constexpr int HoveredSessionTabFillShade = Shade300; constexpr int SessionTabCloseButtonHoverFillShade = Shade600; constexpr int DockBackgroundShade = Shade300; constexpr int DockHeaderShade = Shade400; constexpr int DockHeaderButtonFillShade = Shade200; constexpr int DockHeaderButtonHoverFillShade = Shade300; constexpr int ConstantsDockMinimumWidth = 120; constexpr int ConstantsDockDefaultWidth = 320; constexpr int DockTextInputShade = Shade300; constexpr int DockTextInputOutlineShade = Shade400; constexpr int DockTextInputUnfocusedOutlineStrokeWidth = 1; constexpr int DockSearchRowVerticalPadding = 6; constexpr int DockListPadding = 0; constexpr int DockHoveredItemShade = Shade500; constexpr int DockHoveredItemCornerRadius = 6; constexpr int DockUnfocusedSelectedItemShade = Shade500; constexpr int KeypadBackgroundShade = Shade200; constexpr int KeypadButtonShade = Shade300; constexpr int KeypadButtonHoverShade = Shade400; constexpr int KeypadButtonPressedShade = Shade500; constexpr int StatusBarBackgroundShade = Shade100; constexpr int BitfieldBitHoverShade = Shade400; constexpr int BitfieldButtonFillShade = Shade400; constexpr int BitfieldButtonHoverFillShade = Shade500; constexpr int BitfieldButtonPressedFillShade = Shade600; } // namespace UiConfig #endif // GUI_UICONFIG_H heldercorreia-speedcrunch-e7ca37f/src/gui/userfunctionlistwidget.cpp000066400000000000000000000223701526573132500262440ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014-2016, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/userfunctionlistwidget.h" #include "core/evaluator.h" #include "gui/displayformatutils.h" #include "gui/dockliststyle.h" #include "gui/themedlineedit.h" #include "gui/uiconfig.h" #include "core/settings.h" #include "core/unicodechars.h" #include #include #include #include #include #include #include #include #include #include UserFunctionListWidget::UserFunctionListWidget(QWidget* parent) : QWidget(parent) , m_filterTimer(new QTimer(this)) , m_userFunctions(new QTreeWidget(this)) , m_noMatchLabel(new QLabel(m_userFunctions)) , m_searchFilter(new ThemedLineEdit(this)) , m_searchLabel(new QLabel(this)) , m_evaluator(Evaluator::instance()) , m_pendingRefresh(false) { constexpr int kSearchRowHorizontalPadding = 8; m_filterTimer->setInterval(500); m_filterTimer->setSingleShot(true); m_userFunctions->setAutoScroll(true); m_userFunctions->setColumnCount(3); m_userFunctions->setEditTriggers(QTreeWidget::NoEditTriggers); m_userFunctions->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_userFunctions->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_userFunctions->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_userFunctions->setRootIsDecorated(false); m_userFunctions->setSelectionBehavior(QTreeWidget::SelectRows); DockListStyle::apply(m_userFunctions); m_noMatchLabel->setAlignment(Qt::AlignCenter); m_noMatchLabel->adjustSize(); m_noMatchLabel->hide(); m_searchFilter->setClearButtonEnabled(true); QWidget* searchBox = new QWidget(this); QHBoxLayout* searchLayout = new QHBoxLayout; searchLayout->addWidget(m_searchLabel); searchLayout->addWidget(m_searchFilter); searchLayout->setContentsMargins(kSearchRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding, kSearchRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding); searchBox->setLayout(searchLayout); QVBoxLayout* layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(searchBox); layout->addWidget(m_userFunctions); setLayout(layout); QMenu* contextMenu = new QMenu(m_userFunctions); m_insertAction = new QAction("", contextMenu); m_editAction = new QAction("", contextMenu); m_deleteAction = new QAction("", contextMenu); m_deleteAllAction = new QAction("", contextMenu); m_userFunctions->setContextMenuPolicy(Qt::ActionsContextMenu); m_userFunctions->addAction(m_insertAction); m_userFunctions->addAction(m_editAction); m_userFunctions->addAction(m_deleteAction); m_userFunctions->addAction(m_deleteAllAction); QWidget::setTabOrder(m_searchFilter, m_userFunctions); setFocusProxy(m_searchFilter); retranslateText(); connect(m_filterTimer, SIGNAL(timeout()), SLOT(updateList())); connect(m_searchFilter, SIGNAL(textChanged(const QString&)), SLOT(triggerFilter())); connect(m_userFunctions, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(activateItem())); connect(m_insertAction, SIGNAL(triggered()), SLOT(activateItem())); connect(m_editAction, SIGNAL(triggered()), SLOT(editItem())); connect(m_deleteAction, SIGNAL(triggered()), SLOT(deleteItem())); connect(m_deleteAllAction, SIGNAL(triggered()), SLOT(deleteAllItems())); QShortcut* returnShortcut = new QShortcut(QKeySequence(Qt::Key_Return), this); returnShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(returnShortcut, &QShortcut::activated, this, [this]() { activateItem(); }); QShortcut* enterShortcut = new QShortcut(QKeySequence(Qt::Key_Enter), this); enterShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(enterShortcut, &QShortcut::activated, this, [this]() { activateItem(); }); updateList(); } UserFunctionListWidget::~UserFunctionListWidget() { m_filterTimer->stop(); } void UserFunctionListWidget::updateList() { if (!isVisible()) { m_pendingRefresh = true; return; } setUpdatesEnabled(false); m_filterTimer->stop(); m_userFunctions->clear(); QString term = m_searchFilter->text(); QList userFunctions = m_evaluator->getUserFunctions(); for (int i = 0; i < userFunctions.count(); ++i) { QString fname = userFunctions.at(i).name() + "(" + userFunctions.at(i).arguments().join(";") + ")"; QStringList namesAndValues; namesAndValues << fname << userFunctions.at(i).expression() << userFunctions.at(i).description(); if (term.isEmpty() || namesAndValues.at(0).contains(term, Qt::CaseInsensitive) || namesAndValues.at(1).contains(term, Qt::CaseInsensitive) || namesAndValues.at(2).contains(term, Qt::CaseInsensitive)) { const UserFunction& userFunction = userFunctions.at(i); const QString rawExpression = userFunction.expression(); const QString sourceExpression = userFunction.interpretedExpression().isEmpty() ? rawExpression : userFunction.interpretedExpression(); const QString formattedExpression = DisplayFormatUtils::applyDigitGroupingForDisplay( UnicodeChars::normalizePiForDisplay( Evaluator::formatInterpretedExpressionForDisplay(sourceExpression, m_evaluator))); namesAndValues[1] = formattedExpression; QTreeWidgetItem* item = new QTreeWidgetItem(m_userFunctions, namesAndValues); item->setData(1, Qt::UserRole, rawExpression); item->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter); item->setTextAlignment(1, Qt::AlignLeft | Qt::AlignVCenter); item->setTextAlignment(2, Qt::AlignLeft | Qt::AlignVCenter); } } m_userFunctions->resizeColumnToContents(0); m_userFunctions->resizeColumnToContents(1); m_userFunctions->resizeColumnToContents(2); if (m_userFunctions->topLevelItemCount() > 0) { m_noMatchLabel->hide(); m_userFunctions->sortItems(0, Qt::AscendingOrder); } else { DockListStyle::showCenteredNoMatchLabel(m_userFunctions, m_noMatchLabel); } setUpdatesEnabled(true); m_pendingRefresh = false; } void UserFunctionListWidget::retranslateText() { QStringList titles; titles << tr("Name") << tr("Value") << tr("Description"); m_userFunctions->setHeaderLabels(titles); m_searchLabel->setText(tr("Search")); m_noMatchLabel->setText(tr("No match found")); m_insertAction->setText(tr("Insert")); m_editAction->setText(tr("Edit")); m_deleteAction->setText(tr("Delete")); m_deleteAllAction->setText(tr("Delete All")); QTimer::singleShot(0, this, SLOT(updateList())); } QTreeWidgetItem* UserFunctionListWidget::currentItem() const { return m_userFunctions->currentItem(); } QString UserFunctionListWidget::getUserFunctionName(const QTreeWidgetItem *item) { return item->text(0).section("(", 0, 0); } QString UserFunctionListWidget::searchText() const { return m_searchFilter->text(); } void UserFunctionListWidget::setEvaluator(Evaluator* evaluator) { m_evaluator = evaluator ? evaluator : Evaluator::instance(); } void UserFunctionListWidget::setSearchText(const QString& text) { m_searchFilter->setText(text); } void UserFunctionListWidget::activateItem() { if (!currentItem() || m_userFunctions->selectedItems().isEmpty()) return; emit userFunctionSelected(currentItem()->text(0)); } void UserFunctionListWidget::editItem() { if (!currentItem() || m_userFunctions->selectedItems().isEmpty()) return; const QString rawExpression = currentItem()->data(1, Qt::UserRole).toString(); QString editedExpression = currentItem()->text(0) + " = " + rawExpression; const QString description = currentItem()->text(2).trimmed(); if (!description.isEmpty()) editedExpression += " ? " + description; emit userFunctionEdited(editedExpression); } void UserFunctionListWidget::deleteItem() { if (!currentItem() || m_userFunctions->selectedItems().isEmpty()) return; m_evaluator->unsetUserFunction(getUserFunctionName(currentItem())); updateList(); } void UserFunctionListWidget::deleteAllItems() { m_evaluator->unsetAllUserFunctions(); updateList(); } void UserFunctionListWidget::triggerFilter() { m_filterTimer->stop(); m_filterTimer->start(); } void UserFunctionListWidget::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { setLayoutDirection(Qt::LeftToRight); retranslateText(); return; } QWidget::changeEvent(event); } void UserFunctionListWidget::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Delete) deleteItem(); else if (event->key() == Qt::Key_E) editItem(); else { QWidget::keyPressEvent(event); return; } event->accept(); } void UserFunctionListWidget::showEvent(QShowEvent* event) { QWidget::showEvent(event); if (m_pendingRefresh) updateList(); } heldercorreia-speedcrunch-e7ca37f/src/gui/userfunctionlistwidget.h000066400000000000000000000031001526573132500256770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2014, 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_USERFUNCTIONLISTWIDGET_H #define GUI_USERFUNCTIONLISTWIDGET_H #include #include class QEvent; class QKeyEvent; class QLabel; class QLineEdit; class QShowEvent; class QTimer; class QTreeWidget; class QTreeWidgetItem; class Evaluator; class UserFunctionListWidget : public QWidget { Q_OBJECT public: explicit UserFunctionListWidget(QWidget* parent = 0); ~UserFunctionListWidget(); QTreeWidgetItem* currentItem() const; QString getUserFunctionName(const QTreeWidgetItem *); QString searchText() const; void setEvaluator(Evaluator* evaluator); void setSearchText(const QString& text); signals: void userFunctionSelected(const QString&); void userFunctionEdited(const QString&); public slots: void updateList(); void retranslateText(); protected slots: void activateItem(); void editItem(); void deleteItem(); void deleteAllItems(); void triggerFilter(); protected: void changeEvent(QEvent*) override; void keyPressEvent(QKeyEvent*) override; void showEvent(QShowEvent*) override; private: Q_DISABLE_COPY(UserFunctionListWidget) QTimer* m_filterTimer; QTreeWidget* m_userFunctions; QAction* m_insertAction; QAction* m_editAction; QAction* m_deleteAction; QAction* m_deleteAllAction; QLabel* m_noMatchLabel; QLineEdit* m_searchFilter; QLabel* m_searchLabel; Evaluator* m_evaluator; bool m_pendingRefresh; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/userunitlistwidget.cpp000066400000000000000000000217501526573132500253770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/userunitlistwidget.h" #include "core/evaluator.h" #include "core/mathdsl.h" #include "core/numberformatter.h" #include "gui/dockliststyle.h" #include "gui/themedlineedit.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include #include UserUnitListWidget::UserUnitListWidget(QWidget* parent) : QWidget(parent) , m_filterTimer(new QTimer(this)) , m_userUnits(new QTreeWidget(this)) , m_noMatchLabel(new QLabel(m_userUnits)) , m_searchFilter(new ThemedLineEdit(this)) , m_searchLabel(new QLabel(this)) , m_evaluator(Evaluator::instance()) , m_pendingRefresh(false) { constexpr int kSearchRowHorizontalPadding = 8; m_filterTimer->setInterval(500); m_filterTimer->setSingleShot(true); m_userUnits->setAutoScroll(true); m_userUnits->setColumnCount(3); m_userUnits->setEditTriggers(QTreeWidget::NoEditTriggers); m_userUnits->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_userUnits->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_userUnits->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_userUnits->setRootIsDecorated(false); m_userUnits->setSelectionBehavior(QTreeWidget::SelectRows); DockListStyle::apply(m_userUnits); m_noMatchLabel->setAlignment(Qt::AlignCenter); m_noMatchLabel->adjustSize(); m_noMatchLabel->hide(); m_searchFilter->setClearButtonEnabled(true); QWidget* searchBox = new QWidget(this); QHBoxLayout* searchLayout = new QHBoxLayout; searchLayout->addWidget(m_searchLabel); searchLayout->addWidget(m_searchFilter); searchLayout->setContentsMargins(kSearchRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding, kSearchRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding); searchBox->setLayout(searchLayout); QVBoxLayout* layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(searchBox); layout->addWidget(m_userUnits); setLayout(layout); QMenu* contextMenu = new QMenu(m_userUnits); m_insertAction = new QAction("", contextMenu); m_editAction = new QAction("", contextMenu); m_deleteAction = new QAction("", contextMenu); m_deleteAllAction = new QAction("", contextMenu); m_userUnits->setContextMenuPolicy(Qt::ActionsContextMenu); m_userUnits->addAction(m_insertAction); m_userUnits->addAction(m_editAction); m_userUnits->addAction(m_deleteAction); m_userUnits->addAction(m_deleteAllAction); QWidget::setTabOrder(m_searchFilter, m_userUnits); setFocusProxy(m_searchFilter); retranslateText(); connect(m_filterTimer, SIGNAL(timeout()), SLOT(updateList())); connect(m_searchFilter, SIGNAL(textChanged(const QString&)), SLOT(triggerFilter())); connect(m_userUnits, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(activateItem())); connect(m_insertAction, SIGNAL(triggered()), SLOT(activateItem())); connect(m_editAction, SIGNAL(triggered()), SLOT(editItem())); connect(m_deleteAction, SIGNAL(triggered()), SLOT(deleteItem())); connect(m_deleteAllAction, SIGNAL(triggered()), SLOT(deleteAllItems())); QShortcut* returnShortcut = new QShortcut(QKeySequence(Qt::Key_Return), this); returnShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(returnShortcut, &QShortcut::activated, this, [this]() { activateItem(); }); QShortcut* enterShortcut = new QShortcut(QKeySequence(Qt::Key_Enter), this); enterShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(enterShortcut, &QShortcut::activated, this, [this]() { activateItem(); }); updateList(); } UserUnitListWidget::~UserUnitListWidget() { m_filterTimer->stop(); } void UserUnitListWidget::updateList() { if (!isVisible()) { m_pendingRefresh = true; return; } setUpdatesEnabled(false); m_filterTimer->stop(); m_userUnits->clear(); const QString term = m_searchFilter->text(); const QList userUnits = m_evaluator->getUserUnits(); for (int i = 0; i < userUnits.count(); ++i) { const UserUnit& userUnit = userUnits.at(i); QString displayExpression = userUnit.interpretedExpression().isEmpty() ? userUnit.expression() : userUnit.interpretedExpression(); const int commentPos = displayExpression.indexOf(MathDsl::CommentSep); if (commentPos >= 0) displayExpression = displayExpression.left(commentPos).trimmed(); // Keep only the right-hand-side expression in the Value column: // turn "[unit] = expr" (or legacy "1 [unit] = expr") into "expr". displayExpression.remove( QRegularExpression(QStringLiteral(R"(^\s*(?:1\s+)?\[[^\]]+\]\s*=\s*)"))); QStringList row; row << userUnit.name() << (displayExpression.isEmpty() ? NumberFormatter::format(userUnit.value()) : displayExpression) << userUnit.description(); if (term.isEmpty() || row.at(0).contains(term, Qt::CaseInsensitive) || row.at(1).contains(term, Qt::CaseInsensitive) || row.at(2).contains(term, Qt::CaseInsensitive)) { QTreeWidgetItem* item = new QTreeWidgetItem(m_userUnits, row); item->setData(1, Qt::UserRole, userUnit.expression()); item->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter); item->setTextAlignment(1, Qt::AlignLeft | Qt::AlignVCenter); item->setTextAlignment(2, Qt::AlignLeft | Qt::AlignVCenter); } } m_userUnits->resizeColumnToContents(0); m_userUnits->resizeColumnToContents(1); m_userUnits->resizeColumnToContents(2); if (m_userUnits->topLevelItemCount() > 0) { m_noMatchLabel->hide(); m_userUnits->sortItems(0, Qt::AscendingOrder); } else { DockListStyle::showCenteredNoMatchLabel(m_userUnits, m_noMatchLabel); } setUpdatesEnabled(true); m_pendingRefresh = false; } void UserUnitListWidget::retranslateText() { QStringList titles; titles << tr("Name") << tr("Value") << tr("Description"); m_userUnits->setHeaderLabels(titles); m_searchLabel->setText(tr("Search")); m_noMatchLabel->setText(tr("No match found")); m_insertAction->setText(tr("Insert")); m_editAction->setText(tr("Edit")); m_deleteAction->setText(tr("Delete")); m_deleteAllAction->setText(tr("Delete All")); QTimer::singleShot(0, this, SLOT(updateList())); } QTreeWidgetItem* UserUnitListWidget::currentItem() const { return m_userUnits->currentItem(); } QString UserUnitListWidget::getUserUnitName(const QTreeWidgetItem* item) { return item->text(0); } QString UserUnitListWidget::searchText() const { return m_searchFilter->text(); } void UserUnitListWidget::setEvaluator(Evaluator* evaluator) { m_evaluator = evaluator ? evaluator : Evaluator::instance(); } void UserUnitListWidget::setSearchText(const QString& text) { m_searchFilter->setText(text); } void UserUnitListWidget::activateItem() { if (!currentItem() || m_userUnits->selectedItems().isEmpty()) return; emit userUnitSelected(QStringLiteral("[%1]").arg(currentItem()->text(0))); } void UserUnitListWidget::editItem() { if (!currentItem() || m_userUnits->selectedItems().isEmpty()) return; const QString expression = currentItem()->data(1, Qt::UserRole).toString(); QString editedExpression = QStringLiteral("[%1] = %2").arg(currentItem()->text(0), expression); const QString description = currentItem()->text(2).trimmed(); if (!description.isEmpty()) editedExpression += QStringLiteral(" ? ") + description; emit userUnitEdited(editedExpression); } void UserUnitListWidget::deleteItem() { if (!currentItem() || m_userUnits->selectedItems().isEmpty()) return; m_evaluator->unsetUserUnit(getUserUnitName(currentItem())); updateList(); } void UserUnitListWidget::deleteAllItems() { m_evaluator->unsetAllUserUnits(); updateList(); } void UserUnitListWidget::triggerFilter() { m_filterTimer->stop(); m_filterTimer->start(); } void UserUnitListWidget::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { setLayoutDirection(Qt::LeftToRight); retranslateText(); return; } QWidget::changeEvent(event); } void UserUnitListWidget::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Delete) deleteItem(); else if (event->key() == Qt::Key_E) editItem(); else { QWidget::keyPressEvent(event); return; } event->accept(); } void UserUnitListWidget::showEvent(QShowEvent* event) { QWidget::showEvent(event); if (m_pendingRefresh) updateList(); } heldercorreia-speedcrunch-e7ca37f/src/gui/userunitlistwidget.h000066400000000000000000000027631526573132500250470ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_USERUNITLISTWIDGET_H #define GUI_USERUNITLISTWIDGET_H #include class QEvent; class QKeyEvent; class QLabel; class QLineEdit; class QShowEvent; class QTimer; class QTreeWidget; class QTreeWidgetItem; class Evaluator; class UserUnitListWidget : public QWidget { Q_OBJECT public: explicit UserUnitListWidget(QWidget* parent = 0); ~UserUnitListWidget(); QTreeWidgetItem* currentItem() const; QString getUserUnitName(const QTreeWidgetItem*); QString searchText() const; void setEvaluator(Evaluator* evaluator); void setSearchText(const QString& text); signals: void userUnitSelected(const QString&); void userUnitEdited(const QString&); public slots: void updateList(); void retranslateText(); protected slots: void activateItem(); void editItem(); void deleteItem(); void deleteAllItems(); void triggerFilter(); protected: void changeEvent(QEvent*) override; void keyPressEvent(QKeyEvent*) override; void showEvent(QShowEvent*) override; private: Q_DISABLE_COPY(UserUnitListWidget) QTimer* m_filterTimer; QTreeWidget* m_userUnits; QAction* m_insertAction; QAction* m_editAction; QAction* m_deleteAction; QAction* m_deleteAllAction; QLabel* m_noMatchLabel; QLineEdit* m_searchFilter; QLabel* m_searchLabel; Evaluator* m_evaluator; bool m_pendingRefresh; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/variablelistwidget.cpp000066400000000000000000000225611526573132500253070ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009-2011, 2013-2016, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/variablelistwidget.h" #include "core/evaluator.h" #include "core/settings.h" #include "core/numberformatter.h" #include "gui/dockliststyle.h" #include "gui/themedlineedit.h" #include "gui/uiconfig.h" #include #include #include #include #include #include #include #include #include #include #include static QString formatValue(const Quantity &value); static QString formatValue(const Variable& variable); VariableListWidget::VariableListWidget(QWidget* parent) : QWidget(parent) , m_filterTimer(new QTimer(this)) , m_variables(new QTreeWidget(this)) , m_noMatchLabel(new QLabel(m_variables)) , m_searchFilter(new ThemedLineEdit(this)) , m_searchLabel(new QLabel(this)) , m_evaluator(Evaluator::instance()) , m_pendingRefresh(false) { constexpr int kSearchRowHorizontalPadding = 8; m_filterTimer->setInterval(500); m_filterTimer->setSingleShot(true); m_variables->setAutoScroll(true); m_variables->setColumnCount(3); m_variables->setEditTriggers(QTreeWidget::NoEditTriggers); m_variables->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_variables->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); m_variables->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_variables->setRootIsDecorated(false); m_variables->setSelectionBehavior(QTreeWidget::SelectRows); DockListStyle::apply(m_variables); m_noMatchLabel->setAlignment(Qt::AlignCenter); m_noMatchLabel->adjustSize(); m_noMatchLabel->hide(); m_searchFilter->setClearButtonEnabled(true); QWidget* searchBox = new QWidget(this); QHBoxLayout* searchLayout = new QHBoxLayout; searchLayout->addWidget(m_searchLabel); searchLayout->addWidget(m_searchFilter); searchLayout->setContentsMargins(kSearchRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding, kSearchRowHorizontalPadding, UiConfig::DockSearchRowVerticalPadding); searchBox->setLayout(searchLayout); QVBoxLayout* layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(searchBox); layout->addWidget(m_variables); setLayout(layout); QMenu* contextMenu = new QMenu(m_variables); m_insertAction = new QAction("", contextMenu); m_editAction = new QAction("", contextMenu); m_deleteAction = new QAction("", contextMenu); m_deleteAllAction = new QAction("", contextMenu); m_variables->setContextMenuPolicy(Qt::ActionsContextMenu); m_variables->addAction(m_insertAction); m_variables->addAction(m_editAction); m_variables->addAction(m_deleteAction); m_variables->addAction(m_deleteAllAction); QWidget::setTabOrder(m_searchFilter, m_variables); setFocusProxy(m_searchFilter); retranslateText(); connect(m_filterTimer, SIGNAL(timeout()), SLOT(updateList())); connect(m_searchFilter, SIGNAL(textChanged(const QString&)), SLOT(triggerFilter())); connect(m_variables, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(activateItem())); connect(m_insertAction, SIGNAL(triggered()), SLOT(activateItem())); connect(m_editAction, SIGNAL(triggered()), SLOT(editItem())); connect(m_deleteAction, SIGNAL(triggered()), SLOT(deleteItem())); connect(m_deleteAllAction, SIGNAL(triggered()), SLOT(deleteAllItems())); QShortcut* returnShortcut = new QShortcut(QKeySequence(Qt::Key_Return), this); returnShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(returnShortcut, &QShortcut::activated, this, [this]() { activateItem(); }); QShortcut* enterShortcut = new QShortcut(QKeySequence(Qt::Key_Enter), this); enterShortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(enterShortcut, &QShortcut::activated, this, [this]() { activateItem(); }); updateList(); } VariableListWidget::~VariableListWidget() { m_filterTimer->stop(); } void VariableListWidget::updateList() { if (!isVisible()) { m_pendingRefresh = true; return; } setUpdatesEnabled(false); m_filterTimer->stop(); const QString term = m_searchFilter->text(); const QList variables = m_evaluator->getUserDefinedVariables(); QHash itemsByName; itemsByName.reserve(m_variables->topLevelItemCount()); for (int i = 0; i < m_variables->topLevelItemCount(); ++i) { QTreeWidgetItem* item = m_variables->topLevelItem(i); itemsByName.insert(item->text(0), item); } QSet visibleNames; visibleNames.reserve(variables.count()); for (int i = 0; i < variables.count(); ++i) { const QString varName = variables.at(i).identifier(); QStringList namesAndValues; namesAndValues << varName << formatValue(variables.at(i)) << variables.at(i).description(); if (term.isEmpty() || namesAndValues.at(0).contains(term, Qt::CaseInsensitive) || namesAndValues.at(1).contains(term, Qt::CaseInsensitive) || namesAndValues.at(2).contains(term, Qt::CaseInsensitive)) { visibleNames.insert(varName); QTreeWidgetItem* item = itemsByName.value(varName, nullptr); if (!item) item = new QTreeWidgetItem(m_variables); item->setText(0, namesAndValues.at(0)); item->setText(1, namesAndValues.at(1)); item->setText(2, namesAndValues.at(2)); item->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter); item->setTextAlignment(1, Qt::AlignLeft | Qt::AlignVCenter); item->setTextAlignment(2, Qt::AlignLeft | Qt::AlignVCenter); } } for (int i = m_variables->topLevelItemCount() - 1; i >= 0; --i) { QTreeWidgetItem* item = m_variables->topLevelItem(i); if (!visibleNames.contains(item->text(0))) delete m_variables->takeTopLevelItem(i); } m_variables->resizeColumnToContents(0); m_variables->resizeColumnToContents(1); m_variables->resizeColumnToContents(2); if (m_variables->topLevelItemCount() > 0) { m_noMatchLabel->hide(); m_variables->sortItems(0, Qt::AscendingOrder); } else { DockListStyle::showCenteredNoMatchLabel(m_variables, m_noMatchLabel); } setUpdatesEnabled(true); m_pendingRefresh = false; } void VariableListWidget::retranslateText() { QStringList titles; titles << tr("Name") << tr("Value") << tr("Description"); m_variables->setHeaderLabels(titles); m_searchLabel->setText(tr("Search")); m_noMatchLabel->setText(tr("No match found")); m_insertAction->setText(tr("Insert")); m_editAction->setText(tr("Edit")); m_deleteAction->setText(tr("Delete")); m_deleteAllAction->setText(tr("Delete All")); QTimer::singleShot(0, this, SLOT(updateList())); } QTreeWidgetItem* VariableListWidget::currentItem() const { return m_variables->currentItem(); } QString VariableListWidget::searchText() const { return m_searchFilter->text(); } void VariableListWidget::setEvaluator(Evaluator* evaluator) { m_evaluator = evaluator ? evaluator : Evaluator::instance(); } void VariableListWidget::setSearchText(const QString& text) { m_searchFilter->setText(text); } void VariableListWidget::activateItem() { if (!currentItem() || m_variables->selectedItems().isEmpty()) return; emit variableSelected(currentItem()->text(0)); } void VariableListWidget::deleteItem() { if (!currentItem() || m_variables->selectedItems().isEmpty()) return; m_evaluator->unsetVariable(currentItem()->text(0)); updateList(); } void VariableListWidget::editItem() { if (!currentItem() || m_variables->selectedItems().isEmpty()) return; QString editedExpression = currentItem()->text(0) + " = " + currentItem()->text(1); const QString description = currentItem()->text(2).trimmed(); if (!description.isEmpty()) editedExpression += " ? " + description; emit variableEdited(editedExpression); } void VariableListWidget::deleteAllItems() { m_evaluator->unsetAllUserDefinedVariables(); updateList(); } void VariableListWidget::triggerFilter() { m_filterTimer->stop(); m_filterTimer->start(); } void VariableListWidget::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { setLayoutDirection(Qt::LeftToRight); retranslateText(); return; } QWidget::changeEvent(event); } void VariableListWidget::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Delete) { deleteItem(); event->accept(); return; } else if (event->key() == Qt::Key_E) { editItem(); event->accept(); return; } QWidget::keyPressEvent(event); } void VariableListWidget::showEvent(QShowEvent* event) { QWidget::showEvent(event); if (m_pendingRefresh) updateList(); } static QString formatValue(const Quantity& value) { return NumberFormatter::format(value); } static QString formatValue(const Variable& variable) { if (!variable.formattedValue().isEmpty()) return variable.formattedValue(); return formatValue(variable.value()); } heldercorreia-speedcrunch-e7ca37f/src/gui/variablelistwidget.h000066400000000000000000000027661526573132500247610ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009, 2011, 2013-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_VARIABLELISTWIDGET_H #define GUI_VARIABLELISTWIDGET_H #include #include class QEvent; class QKeyEvent; class QLabel; class QLineEdit; class QShowEvent; class QTimer; class QTreeWidget; class QTreeWidgetItem; class Evaluator; class Variable; class VariableListWidget : public QWidget { Q_OBJECT public: explicit VariableListWidget(QWidget* parent = 0); ~VariableListWidget(); QTreeWidgetItem* currentItem() const; QString searchText() const; void setEvaluator(Evaluator* evaluator); void setSearchText(const QString& text); signals: void variableSelected(const QString&); void variableEdited(const QString&); public slots: void updateList(); void retranslateText(); protected slots: void activateItem(); void editItem(); void deleteItem(); void deleteAllItems(); void triggerFilter(); protected: void changeEvent(QEvent*) override; void keyPressEvent(QKeyEvent*) override; void showEvent(QShowEvent*) override; private: Q_DISABLE_COPY(VariableListWidget) QTimer* m_filterTimer; QTreeWidget* m_variables; QAction* m_insertAction; QAction* m_editAction; QAction* m_deleteAction; QAction* m_deleteAllAction; QLabel* m_noMatchLabel; QLineEdit* m_searchFilter; QLabel* m_searchLabel; Evaluator* m_evaluator; bool m_pendingRefresh; }; #endif heldercorreia-speedcrunch-e7ca37f/src/gui/versioncheck.cpp000066400000000000000000000537021526573132500241060ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/versioncheck.h" #include "core/startupdiagnostics.h" #include "core/settings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { static const char WEBSITE_URL[] = "https://speedcrunch.org"; static const char VERSION_URL[] = "https://speedcrunch.org/version"; static const char LAST_CHECK_KEY[] = "updates/lastVersionCheckUtcMsecs"; static const char LAST_FETCHED_VERSION_KEY[] = "updates/lastFetchedVersion"; static const char LAST_NOTIFIED_VERSION_KEY[] = "updates/lastNotifiedVersion"; const qint64 CHECK_INTERVAL_MSECS = 24LL * 60LL * 60LL * 1000LL; constexpr qint64 MAX_VERSION_RESPONSE_BYTES = 1024; constexpr int VERSION_REQUEST_TIMEOUT_MSECS = 5000; Q_LOGGING_CATEGORY(lcVersionCheck, "speedcrunch.updatecheck") struct VersionResponse { QByteArray payload; QDeadlineTimer deadline{VERSION_REQUEST_TIMEOUT_MSECS, Qt::PreciseTimer}; bool tooLarge = false; bool timedOut = false; void readAvailable(QNetworkReply* reply) { if (tooLarge || reply->bytesAvailable() == 0) return; const qint64 remaining = MAX_VERSION_RESPONSE_BYTES - payload.size(); // Read one extra byte to detect overflow even without Content-Length. const QByteArray chunk = reply->read(remaining + 1); if (chunk.size() > remaining) { tooLarge = true; payload.clear(); return; } payload.append(chunk); } }; bool compareVersions(const QString& left, const QString& right, int* result); bool tryParseVersion(const QString& version, QVector* components); QMutex& updateScheduleMutex() { static QMutex mutex; return mutex; } QSettings updateCheckSettings() { #ifdef SPEEDCRUNCH_PORTABLE return QSettings(QDir(Settings::getConfigPath()).filePath(QStringLiteral("updates.ini")), QSettings::IniFormat); #else return QSettings(); #endif } static QDebug versionCheckDebug() { return QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, lcVersionCheck().categoryName()).debug(); } void deleteStoppedThread(QThread* thread) { // finished() precedes deferred deletion and thread-local cleanup. Deleting // a thread still in that stage can make its destructor wait indefinitely. if (thread->wait(0)) { delete thread; return; } QTimer::singleShot(10, thread, [thread]() { deleteStoppedThread(thread); }); } } class VersionCheckWorker : public QObject { Q_OBJECT public: void startRequest(VersionCheck::CheckTrigger trigger) { if (QThread::currentThread()->isInterruptionRequested()) return; { // Claim the automatic attempt before another window checks the schedule. QMutexLocker lock(&updateScheduleMutex()); if (trigger == VersionCheck::CheckTriggerAutomatic && !isCheckDue()) { versionCheckDebug() << "Update check skipped: next check not due yet."; emit requestSkipped(); return; } markCheckAttempted(); } if (QThread::currentThread()->isInterruptionRequested()) return; versionCheckDebug() << "Starting update check request to" << QString::fromLatin1(VERSION_URL) << "; trigger =" << (trigger == VersionCheck::CheckTriggerManual ? "manual" : "automatic"); if (!m_manager) { StartupDiagnostics::Scope timing("Initialize update network manager"); m_manager = new QNetworkAccessManager(this); } if (QThread::currentThread()->isInterruptionRequested()) return; QNetworkRequest request(QUrl(QString::fromLatin1(VERSION_URL))); request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); request.setTransferTimeout(VERSION_REQUEST_TIMEOUT_MSECS); const auto response = std::make_shared(); QNetworkReply* reply; { StartupDiagnostics::Scope timing("Dispatch update network request"); reply = m_manager->get(request); } reply->setReadBufferSize(MAX_VERSION_RESPONSE_BYTES + 1); auto* timeout = new QTimer(reply); timeout->setSingleShot(true); timeout->setTimerType(Qt::PreciseTimer); connect(reply, &QNetworkReply::finished, this, [this, reply, trigger, response, timeout]() { timeout->stop(); response->timedOut = response->timedOut || response->deadline.hasExpired(); response->readAvailable(reply); const auto error = response->tooLarge ? QNetworkReply::UnknownContentError : response->timedOut ? QNetworkReply::TimeoutError : reply->error(); const int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); const QString errorString = response->tooLarge ? QStringLiteral("Update response exceeds the 1024-byte limit.") : response->timedOut ? QStringLiteral("Update request exceeds the five-second deadline.") : reply->errorString(); reply->deleteLater(); QString latestVersion; int comparison = 0; bool comparable = false; bool notify = false; if (error == QNetworkReply::NoError) { latestVersion = QString::fromUtf8(response->payload).trimmed().section('\n', 0, 0).trimmed(); comparable = compareVersions(latestVersion, QString::fromLatin1(SPEEDCRUNCH_VERSION), &comparison); storeFetchedVersion(latestVersion); if (comparable && comparison > 0) notify = trigger == VersionCheck::CheckTriggerManual || shouldNotifyForVersion(latestVersion); } emit requestFinished(error, latestVersion, httpStatus, errorString, comparable, comparison, notify); }); connect(timeout, &QTimer::timeout, this, [reply, response]() { response->timedOut = true; response->payload.clear(); reply->abort(); }); connect(reply, &QNetworkReply::readyRead, this, [reply, response]() { response->readAvailable(reply); if (response->tooLarge) reply->abort(); }); connect(reply, &QNetworkReply::metaDataChanged, this, [reply, response]() { if (!response->tooLarge && reply->header(QNetworkRequest::ContentLengthHeader).toLongLong() > MAX_VERSION_RESPONSE_BYTES) { response->tooLarge = true; response->payload.clear(); reply->abort(); } }); // Keep one deadline across redirects and incoming data. timeout->start(response->deadline.remainingTime()); } void markVersionNotified(const QString& version); signals: void requestDispatched(); void requestSkipped(); void requestFinished(QNetworkReply::NetworkError error, const QString& latestVersion, int httpStatus, const QString& errorString, bool comparable, int comparison, bool shouldNotify); private: void markCheckAttempted(); bool isCheckDue() const; void storeFetchedVersion(const QString& version); bool shouldNotifyForVersion(const QString& version) const; QNetworkAccessManager* m_manager = nullptr; }; VersionCheck::VersionCheck(QWidget* parentWindow, QObject* parent) : QObject(parent), m_parentWindow(parentWindow) { } VersionCheck::~VersionCheck() { if (m_networkThread) { QThread* thread = m_networkThread; thread->requestInterruption(); // Finish notification writes already queued before stopping the worker. QMetaObject::invokeMethod(m_networkWorker, [thread]() { thread->quit(); }, Qt::QueuedConnection); } } void VersionCheck::checkForUpdateAfterFirstPaint() { if (qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK") || m_automaticCheckScheduled || !m_parentWindow) return; m_automaticCheckScheduled = true; qApp->installEventFilter(this); } bool VersionCheck::eventFilter(QObject* watched, QEvent* event) { if (event->type() == QEvent::Paint) { QWidget* widget = qobject_cast(watched); if (widget && widget->isVisible() && widget->window() == m_parentWindow) { qApp->removeEventFilter(this); const auto startupTask = StartupDiagnostics::task("Deferred automatic update check (async total)"); // Let the paint finish and its diagnostics callback run before dispatch. QTimer::singleShot(0, this, [this, startupTask]() { QTimer::singleShot(0, this, [this, startupTask]() { StartupDiagnostics::Scope timing("Queue automatic update check"); checkForUpdateIfDue(); }); }); } } return QObject::eventFilter(watched, event); } void VersionCheck::checkForUpdateIfDue() { if (qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK")) return; if (m_requestPending) { versionCheckDebug() << "Update check skipped: request already in progress."; return; } startRequest(CheckTriggerAutomatic); } void VersionCheck::checkForUpdateNow() { if (m_requestPending) { versionCheckDebug() << "Manual update check requested while another request is running."; showVerificationFailedDialog(m_parentWindow); return; } startRequest(CheckTriggerManual); } void VersionCheck::handleReplyFinished(QNetworkReply::NetworkError error, const QString& latestVersion, int httpStatus, const QString& errorString, bool comparable, int comparison, bool shouldNotify) { m_requestPending = false; versionCheckDebug() << "Update check response received." << "HTTP status:" << httpStatus; const bool ok = (error == QNetworkReply::NoError); if (!ok) { versionCheckDebug() << "Update check failed:" << errorString; if (m_trigger == CheckTriggerManual) { if (isConnectivityError(error)) showNoConnectivityDialog(m_parentWindow); else showVerificationFailedDialog(m_parentWindow); } return; } const QString currentVersion = QString::fromLatin1(SPEEDCRUNCH_VERSION); versionCheckDebug() << "Parsed versions:" << "remote =" << latestVersion << ", local =" << currentVersion << ", comparable =" << comparable << ", compare result =" << comparison; if (!comparable) { versionCheckDebug() << "Could not compare versions."; if (m_trigger == CheckTriggerManual) showVerificationFailedDialog(m_parentWindow); } else if (comparison > 0) { if (shouldNotify) { versionCheckDebug() << "Newer version found; showing update dialog."; showUpdateDialog(m_parentWindow, latestVersion, m_trigger == CheckTriggerAutomatic ? m_networkWorker : nullptr); } else { versionCheckDebug() << "Newer version found, but user was already notified for this version."; } } else { versionCheckDebug() << "No newer version available."; if (m_trigger == CheckTriggerManual) showUpToDateDialog(m_parentWindow, currentVersion); } } namespace { bool compareVersions(const QString& left, const QString& right, int* result) { if (!result) return false; *result = 0; QVector leftComponents; QVector rightComponents; if (!tryParseVersion(left, &leftComponents) || !tryParseVersion(right, &rightComponents)) return false; const int count = qMax(leftComponents.size(), rightComponents.size()); for (int i = 0; i < count; ++i) { const qulonglong leftPart = (i < leftComponents.size()) ? leftComponents.at(i) : 0; const qulonglong rightPart = (i < rightComponents.size()) ? rightComponents.at(i) : 0; if (leftPart < rightPart) *result = -1; if (leftPart > rightPart) *result = 1; if (*result != 0) return true; } return true; } bool tryParseVersion(const QString& version, QVector* components) { if (!components) return false; components->clear(); const QString trimmed = version.trimmed(); if (trimmed.isEmpty()) return false; const QStringList parts = trimmed.split('.', Qt::KeepEmptyParts); for (const QString& part : parts) { if (part.isEmpty()) return false; for (const QChar ch : part) { if (!ch.isDigit()) return false; } bool ok = false; const qulonglong value = part.toULongLong(&ok); if (!ok) return false; components->append(value); } return !components->isEmpty(); } } void VersionCheck::showUpdateDialog(QWidget* parent, const QString& latestVersion, VersionCheckWorker* notificationWorker) { versionCheckDebug() << "Displaying update dialog for version" << latestVersion; QDialog dialog(parent); dialog.setWindowTitle(QObject::tr("Update Available")); QVBoxLayout* layout = new QVBoxLayout(&dialog); QLabel* text = new QLabel( QObject::tr("A newer version (%1) is available.
    Visit website to download.") .arg(latestVersion, QString::fromLatin1(WEBSITE_URL)), &dialog); text->setTextFormat(Qt::RichText); text->setTextInteractionFlags(Qt::TextBrowserInteraction); text->setOpenExternalLinks(false); QObject::connect(text, &QLabel::linkActivated, &dialog, [](const QString& url) { QDesktopServices::openUrl(QUrl(url)); }); layout->addWidget(text); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, &dialog); QObject::connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); layout->addWidget(buttons); if (notificationWorker) { QObject::connect(&dialog, &QDialog::finished, notificationWorker, [notificationWorker, latestVersion]() { notificationWorker->markVersionNotified(latestVersion); }, Qt::QueuedConnection); } dialog.exec(); } void VersionCheck::showUpToDateDialog(QWidget* parent, const QString& currentVersion) { QDialog dialog(parent); dialog.setWindowTitle(QObject::tr("Check for Updates")); QVBoxLayout* layout = new QVBoxLayout(&dialog); QLabel* text = new QLabel( QObject::tr("SpeedCrunch %1 is up to date.").arg(currentVersion), &dialog); text->setWordWrap(true); layout->addWidget(text); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, &dialog); QObject::connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); layout->addWidget(buttons); dialog.exec(); } void VersionCheck::showNoConnectivityDialog(QWidget* parent) { QDialog dialog(parent); dialog.setWindowTitle(QObject::tr("Check for Updates")); QVBoxLayout* layout = new QVBoxLayout(&dialog); QLabel* text = new QLabel( QObject::tr("No connectivity. Please check your internet connection and try again."), &dialog); text->setWordWrap(true); layout->addWidget(text); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, &dialog); QObject::connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); layout->addWidget(buttons); dialog.exec(); } void VersionCheck::showVerificationFailedDialog(QWidget* parent) { QDialog dialog(parent); dialog.setWindowTitle(QObject::tr("Check for Updates")); QVBoxLayout* layout = new QVBoxLayout(&dialog); QLabel* text = new QLabel( QObject::tr("Could not verify the latest available version."), &dialog); text->setWordWrap(true); layout->addWidget(text); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, &dialog); QObject::connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); layout->addWidget(buttons); dialog.exec(); } bool VersionCheck::isConnectivityError(QNetworkReply::NetworkError error) { return error == QNetworkReply::ConnectionRefusedError || error == QNetworkReply::RemoteHostClosedError || error == QNetworkReply::HostNotFoundError || error == QNetworkReply::TimeoutError || error == QNetworkReply::OperationCanceledError || error == QNetworkReply::SslHandshakeFailedError || error == QNetworkReply::TemporaryNetworkFailureError || error == QNetworkReply::NetworkSessionFailedError || error == QNetworkReply::BackgroundRequestNotAllowedError || error == QNetworkReply::TooManyRedirectsError || error == QNetworkReply::InsecureRedirectError || error == QNetworkReply::ProxyConnectionRefusedError || error == QNetworkReply::ProxyConnectionClosedError || error == QNetworkReply::ProxyNotFoundError || error == QNetworkReply::ProxyTimeoutError || error == QNetworkReply::ProxyAuthenticationRequiredError || error == QNetworkReply::UnknownNetworkError || error == QNetworkReply::UnknownProxyError; } void VersionCheckWorker::markCheckAttempted() { StartupDiagnostics::Scope timing("Save update check timestamp"); QSettings settings = updateCheckSettings(); const qint64 now = QDateTime::currentMSecsSinceEpoch(); settings.setValue(QString::fromLatin1(LAST_CHECK_KEY), now); versionCheckDebug() << "Recorded update check timestamp (UTC msecs):" << now; } bool VersionCheckWorker::isCheckDue() const { StartupDiagnostics::Scope timing("Check update schedule"); QSettings settings = updateCheckSettings(); const qint64 lastCheck = settings.value(QString::fromLatin1(LAST_CHECK_KEY), 0).toLongLong(); if (lastCheck <= 0) { versionCheckDebug() << "No previous update check timestamp found; check is due."; return true; } const qint64 elapsed = QDateTime::currentMSecsSinceEpoch() - lastCheck; const bool due = elapsed >= CHECK_INTERVAL_MSECS; versionCheckDebug() << "Last update check elapsed msecs:" << elapsed << "; interval msecs:" << CHECK_INTERVAL_MSECS << "; due =" << due; return due; } void VersionCheck::startRequest(CheckTrigger trigger) { m_trigger = trigger; m_requestPending = true; versionCheckDebug() << "Queuing update check; trigger =" << (trigger == CheckTriggerManual ? "manual" : "automatic"); const auto startupTask = StartupDiagnostics::task("Update schedule and request setup (async total)"); if (!m_networkWorker) { // Neither object belongs to the window. They survive until cleanup ends. QThread* thread = new QThread; m_networkThread = thread; m_networkWorker = new VersionCheckWorker; m_networkWorker->moveToThread(thread); connect(thread, &QThread::finished, m_networkWorker, &QObject::deleteLater); connect(thread, &QThread::finished, thread, [thread]() { deleteStoppedThread(thread); }, Qt::QueuedConnection); connect(m_networkWorker, &VersionCheckWorker::requestFinished, this, &VersionCheck::handleReplyFinished, Qt::QueuedConnection); connect(m_networkWorker, &VersionCheckWorker::requestSkipped, this, [this]() { m_requestPending = false; }, Qt::QueuedConnection); // Wake diagnostics after setup without retaining a pointer to the window. connect(m_networkWorker, &VersionCheckWorker::requestDispatched, qApp, []() {}, Qt::QueuedConnection); thread->start(); } VersionCheckWorker* worker = m_networkWorker; QMetaObject::invokeMethod(worker, [worker, startupTask, trigger]() { worker->startRequest(trigger); if (startupTask) startupTask->finish(); emit worker->requestDispatched(); }, Qt::QueuedConnection); } void VersionCheckWorker::storeFetchedVersion(const QString& version) { QSettings settings = updateCheckSettings(); settings.setValue(QString::fromLatin1(LAST_FETCHED_VERSION_KEY), version); versionCheckDebug() << "Recorded latest fetched version:" << version; } bool VersionCheckWorker::shouldNotifyForVersion(const QString& version) const { QSettings settings = updateCheckSettings(); const QString lastNotified = settings.value(QString::fromLatin1(LAST_NOTIFIED_VERSION_KEY)).toString().trimmed(); if (lastNotified.isEmpty()) return true; int comparison = 0; const bool comparable = compareVersions(version, lastNotified, &comparison); if (!comparable) { versionCheckDebug() << "Could not compare against last notified version; notifying by default." << "remote =" << version << ", lastNotified =" << lastNotified; return true; } return comparison > 0; } void VersionCheckWorker::markVersionNotified(const QString& version) { QSettings settings = updateCheckSettings(); settings.setValue(QString::fromLatin1(LAST_NOTIFIED_VERSION_KEY), version); versionCheckDebug() << "Recorded notified version:" << version; } #include "versioncheck.moc" heldercorreia-speedcrunch-e7ca37f/src/gui/versioncheck.h000066400000000000000000000033161526573132500235470ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef GUI_VERSIONCHECK_H #define GUI_VERSIONCHECK_H #include #include #include #include #include class QWidget; class VersionCheckWorker; class VersionCheck : public QObject { Q_OBJECT public: enum CheckTrigger { CheckTriggerAutomatic, CheckTriggerManual }; explicit VersionCheck(QWidget* parentWindow, QObject* parent = 0); ~VersionCheck() override; void checkForUpdateAfterFirstPaint(); void checkForUpdateIfDue(); void checkForUpdateNow(); protected: bool eventFilter(QObject* watched, QEvent* event) override; private: void handleReplyFinished(QNetworkReply::NetworkError error, const QString& latestVersion, int httpStatus, const QString& errorString, bool comparable, int comparison, bool shouldNotify); static void showUpdateDialog(QWidget* parent, const QString& latestVersion, VersionCheckWorker* notificationWorker); static void showUpToDateDialog(QWidget* parent, const QString& currentVersion); static void showNoConnectivityDialog(QWidget* parent); static void showVerificationFailedDialog(QWidget* parent); static bool isConnectivityError(QNetworkReply::NetworkError error); void startRequest(CheckTrigger trigger); QPointer m_parentWindow; QPointer m_networkThread; VersionCheckWorker* m_networkWorker = nullptr; bool m_requestPending = false; CheckTrigger m_trigger = CheckTriggerAutomatic; bool m_automaticCheckScheduled = false; }; #endif heldercorreia-speedcrunch-e7ca37f/src/main.cpp000066400000000000000000000306701526573132500215620ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2013-2014, 2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/mainwindow.h" #include "gui/diagnosticapplication.h" #include "gui/startupfontpreparation.h" #include "core/settings.h" #include "core/startupdiagnostics.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN #include #endif #ifdef Q_OS_UNIX #include #include #include #include #endif namespace { // Dynamic property name mirrored by MainWindow. It lets the GUI layer observe // shutdown state even when quit starts from the application/singleton layer. constexpr const char* kShutdownInProgressProperty = "speedcrunchShutdownInProgress"; QString singletonServerName() { const QString scope = QCoreApplication::applicationFilePath() + QLatin1Char('|') + Settings::getConfigPath(); const QByteArray hash = QCryptographicHash::hash(scope.toUtf8(), QCryptographicHash::Sha1).toHex(); return QStringLiteral("speedcrunch-single-instance-%1").arg(QString::fromLatin1(hash.left(24))); } void activateMainWindow(MainWindow* window) { if (!window) return; if (window->windowState() & Qt::WindowMinimized) window->setWindowState(window->windowState() & ~Qt::WindowMinimized); window->show(); window->raise(); window->activateWindow(); } bool notifyRunningInstance(const QString& serverName) { QLocalSocket socket; socket.connectToServer(serverName, QIODevice::ReadWrite); if (!socket.waitForConnected(250)) return false; socket.write("activate\n"); if (!socket.waitForBytesWritten(250)) return false; if (!socket.waitForReadyRead(750)) return false; // Treat the instance as running only after it explicitly accepts the // activation. If it is already shutting down, the new process should take // over instead of exiting and leaving the user with no restored windows. const QByteArray response = socket.readAll().trimmed(); socket.disconnectFromServer(); return response == QByteArrayLiteral("accepted"); } bool startSingletonServer(QLocalServer* server, const QString& serverName, bool* alreadyRunning) { if (alreadyRunning) *alreadyRunning = false; if (server->listen(serverName)) return true; if (server->serverError() == QAbstractSocket::AddressInUseError) { if (notifyRunningInstance(serverName)) { if (alreadyRunning) *alreadyRunning = true; return false; } QLocalServer::removeServer(serverName); if (server->listen(serverName)) return true; } qWarning() << "Could not initialize singleton server:" << server->errorString(); return false; } MainWindow* g_mainWindow = 0; std::atomic_bool g_eventLoopRunning(false); std::atomic_bool g_shutdownInProgress(false); bool shutdownInProgress() { const QCoreApplication* application = QCoreApplication::instance(); // Keep both an atomic flag and the QApplication property: signal handlers // and singleton callbacks use the atomic, while MainWindow close handling // reads the property. return g_shutdownInProgress.load() || (application && application->property(kShutdownInProgressProperty).toBool()); } class ShutdownEventFilter : public QObject { public: using QObject::QObject; protected: bool eventFilter(QObject* watched, QEvent* event) override { Q_UNUSED(watched); if (event != nullptr && event->type() == QEvent::Quit) { // Mark shutdown as early as possible. aboutToQuit can be too late // for nested close events that decide whether to save child-window // layout changes. g_shutdownInProgress.store(true); if (QCoreApplication::instance()) QCoreApplication::instance()->setProperty(kShutdownInProgressProperty, true); } return false; } }; void persistAndQuit() { // Console/signal shutdown paths bypass the normal window-close entry point, // so they must publish shutdown state before asking MainWindow to persist. g_shutdownInProgress.store(true); if (QCoreApplication::instance()) QCoreApplication::instance()->setProperty(kShutdownInProgressProperty, true); if (g_mainWindow) g_mainWindow->persistSessionAndSettingsForShutdown(); if (QCoreApplication::instance()) QCoreApplication::quit(); } void requestGracefulShutdown(Qt::ConnectionType connectionType = Qt::QueuedConnection) { QCoreApplication* application = QCoreApplication::instance(); if (!application) return; if (QThread::currentThread() == application->thread()) { persistAndQuit(); return; } QMetaObject::invokeMethod(application, []() { persistAndQuit(); }, connectionType); } #ifdef Q_OS_UNIX int g_unixSignalFds[2] = { -1, -1 }; void handleUnixSignal(int signalNumber) { const char signalCode = static_cast(signalNumber); const ssize_t written = ::write(g_unixSignalFds[0], &signalCode, sizeof(signalCode)); Q_UNUSED(written); } bool installUnixSignalHandler(int signalNumber) { struct sigaction action = {}; action.sa_handler = handleUnixSignal; sigemptyset(&action.sa_mask); action.sa_flags = 0; return ::sigaction(signalNumber, &action, 0) == 0; } bool setupUnixTerminationSignalHandlers() { if (::socketpair(AF_UNIX, SOCK_STREAM, 0, g_unixSignalFds) != 0) return false; const bool ok = installUnixSignalHandler(SIGTERM) && installUnixSignalHandler(SIGINT) && installUnixSignalHandler(SIGHUP); if (!ok) { ::close(g_unixSignalFds[0]); ::close(g_unixSignalFds[1]); g_unixSignalFds[0] = -1; g_unixSignalFds[1] = -1; } return ok; } #endif #ifdef Q_OS_WIN BOOL WINAPI handleWindowsConsoleControl(DWORD controlType) { switch (controlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: requestGracefulShutdown(g_eventLoopRunning.load() ? Qt::BlockingQueuedConnection : Qt::QueuedConnection); return TRUE; default: return FALSE; } } #endif } int main(int argc, char* argv[]) { StartupDiagnostics::begin(); StartupDiagnostics::Scope timing("Configure surface format"); QSurfaceFormat surfaceFormat = QSurfaceFormat::defaultFormat(); surfaceFormat.setColorSpace(QColorSpace::SRgb); QSurfaceFormat::setDefaultFormat(surfaceFormat); timing.next("Initialize QApplication and platform plugin"); DiagnosticApplication application(argc, argv); timing.next("Configure application identity"); ShutdownEventFilter shutdownEventFilter(&application); application.installEventFilter(&shutdownEventFilter); QCoreApplication::setApplicationName("SpeedCrunch"); QCoreApplication::setOrganizationDomain("speedcrunch.org"); QGuiApplication::setDesktopFileName("org.speedcrunch.SpeedCrunch"); QString storageError; if (!Settings::preparePortableStorage(&storageError)) { // Let macOS finish launching before opening a native modal alert. QTimer::singleShot(0, &application, [&]() { QMessageBox message(QMessageBox::Critical, QObject::tr("Portable Data Folder Unavailable"), QObject::tr("SpeedCrunch cannot prepare its portable data folder:\n%1\n\n%2\n\n" "Use Finder to move SpeedCrunch.app and any SpeedCrunch-data folder " "to a writable location, then open the app again.") .arg(Settings::getConfigPath(), storageError)); message.setTextFormat(Qt::PlainText); message.exec(); application.exit(1); }); return application.exec(); } timing.next("Load application settings (total)"); Settings::instance(); timing.next("Install shutdown handlers"); QLocalServer singletonServer; bool pendingActivation = false; QObject::connect(&application, &QCoreApplication::aboutToQuit, &application, [&]() { // Stop accepting single-instance activations during teardown. A second // launch that races with quit should create the replacement instance, // not send activation to a process that is already saving and exiting. g_shutdownInProgress.store(true); application.setProperty(kShutdownInProgressProperty, true); singletonServer.close(); if (g_mainWindow) g_mainWindow->persistSessionAndSettingsForShutdown(); #ifdef Q_OS_UNIX if (g_unixSignalFds[0] != -1) { ::close(g_unixSignalFds[0]); g_unixSignalFds[0] = -1; } if (g_unixSignalFds[1] != -1) { ::close(g_unixSignalFds[1]); g_unixSignalFds[1] = -1; } #endif }); #ifdef Q_OS_UNIX QSocketNotifier* unixSignalNotifier = 0; if (setupUnixTerminationSignalHandlers()) { unixSignalNotifier = new QSocketNotifier(g_unixSignalFds[1], QSocketNotifier::Read, &application); QObject::connect(unixSignalNotifier, &QSocketNotifier::activated, &application, [&]() { char signalCode = 0; const ssize_t bytesRead = ::read(g_unixSignalFds[1], &signalCode, sizeof(signalCode)); if (bytesRead > 0) requestGracefulShutdown(Qt::QueuedConnection); }); } else { qWarning() << "Could not install Unix termination signal handlers."; } #endif #ifdef Q_OS_WIN if (!SetConsoleCtrlHandler(handleWindowsConsoleControl, TRUE)) qWarning() << "Could not install Windows console termination handler."; #endif timing.next("Check and register single instance"); const QString serverName = singletonServerName(); if (notifyRunningInstance(serverName)) return 0; bool alreadyRunning = false; if (startSingletonServer(&singletonServer, serverName, &alreadyRunning)) { QObject::connect(&singletonServer, &QLocalServer::newConnection, &application, [&]() { bool acceptedActivation = false; while (singletonServer.hasPendingConnections()) { QLocalSocket* socket = singletonServer.nextPendingConnection(); if (!socket) continue; if (shutdownInProgress()) { // Refuse activation during shutdown so the launching // process removes the stale server and performs a full // restore of all saved windows. socket->write("shutting-down\n"); socket->waitForBytesWritten(250); socket->close(); socket->deleteLater(); continue; } socket->write("accepted\n"); socket->waitForBytesWritten(250); socket->close(); socket->deleteLater(); acceptedActivation = true; } // If all pending sockets were refused because shutdown is in // progress, do not raise a window that is about to disappear. if (!acceptedActivation) return; if (g_mainWindow) activateMainWindow(g_mainWindow); else pendingActivation = true; }); } else if (alreadyRunning) { return 0; } timing.next("Initialize application widget style"); MainWindow::initializeApplicationStyle(); StartupFontPreparation fontPreparation; timing.next("Initialize main window (total)"); MainWindow window; fontPreparation.wait(); g_mainWindow = &window; timing.next("Show main window"); window.show(); if (pendingActivation) activateMainWindow(g_mainWindow); QObject::connect(&application, &QGuiApplication::lastWindowClosed, &application, [&]() { if (!shutdownInProgress()) application.quit(); }); timing.finish(); g_eventLoopRunning.store(true); const int result = application.exec(); g_eventLoopRunning.store(false); g_mainWindow = 0; return result; } heldercorreia-speedcrunch-e7ca37f/src/math/000077500000000000000000000000001526573132500210555ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/math/cmath.cpp000066400000000000000000000631431526573132500226640ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2018, 2020, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "cmath.h" #include "core/anglemode.h" #include "core/symbolicnumberformat.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include "cnumberparser.h" #include "floatnum/floatconvert.h" #include "hmath.h" #include #include #include #include namespace { QChar s_imaginaryUnitSymbol = QLatin1Char('j'); char s_polarAngleUnit = 'r'; QString formatRadianPhase(const HNumber& phase, const CNumber::Format& format, bool allowSymbolicPiMultiples) { if (allowSymbolicPiMultiples) { const QString symbolic = SymbolicNumberFormat::formatPiMultiple(phase); if (!symbolic.isEmpty()) return symbolic; } return HMath::format(phase, format); } QString formatAngleModePhase(HNumber phase, const CNumber::Format& format) { const char angleMode = CMath::polarAngleUnit(); if (angleMode == AngleMode::Radian) return formatRadianPhase(phase, format, true); if (angleMode == AngleMode::Degree) phase = CMath::rad2deg(phase).real; else if (angleMode == AngleMode::Gradian) phase = CMath::rad2gon(phase).real; else if (angleMode == AngleMode::Turn || angleMode == AngleMode::Revolution) phase /= HNumber(2) * HMath::pi(); return HMath::format(phase, format); } QString parenthesizePhasorPhaseIfNeeded(const QString& phase) { if (phase.contains(MathDsl::DivOp) || phase.contains(MathDsl::MulDotOp)) return QStringLiteral("(%1)").arg(phase); return phase; } } void CMath::setImaginaryUnitSymbol(QChar symbol) { const QChar lower = symbol.toLower(); s_imaginaryUnitSymbol = (lower == QLatin1Char('j')) ? QLatin1Char('j') : QLatin1Char('i'); } QChar CMath::imaginaryUnitSymbol() { return s_imaginaryUnitSymbol; } void CMath::setPolarAngleUnit(char angleUnit) { s_polarAngleUnit = AngleMode::isValid(angleUnit) && angleUnit != AngleMode::Radian ? angleUnit : AngleMode::Radian; } char CMath::polarAngleUnit() { return s_polarAngleUnit; } /** * Creates a new complex number. */ CNumber::CNumber() : real(0) , imag(0) {} /** * Creates a new complex number from one real number */ CNumber::CNumber(const HNumber& hn) : real(hn), imag(0) { } /** * Creates a new complex number from the real and imaginary parts */ CNumber::CNumber(const HNumber& x, const HNumber& y) : real(x) , imag(y) { } /** * Copies from another complex number. */ CNumber::CNumber(const CNumber& cn) : real(cn.real) , imag(cn.imag) { } /** * Creates a new number from an integer value. */ CNumber::CNumber(int i) : real(i) , imag(0) { } /** * Creates a new number from a string. */ CNumber::CNumber(const char* str) { CNumberParser parser(str); parser.parse(this); // FIXME: Exception management. } CNumber::CNumber(const QJsonObject& json) { *this = deSerialize(json); } /** * Returns true if this number is Not a Number (NaN). */ bool CNumber::isNan() const { return real.isNan() || imag.isNan(); } /** * Returns true if this number is zero. */ bool CNumber::isZero() const { return real.isZero() && imag.isZero(); } /** * Returns true if this number is a positive REAL */ bool CNumber::isPositive() const { return real.isPositive() && imag.isZero(); } /** * Returns true if this number is a negative REAL */ bool CNumber::isNegative() const { return real.isNegative() && imag.isZero(); } /** * Returns true if this number is integer and REAL */ bool CNumber::isInteger() const { return real.isInteger() && imag.isZero(); } /** * Returns true if this number is a Gaussian integer */ bool CNumber::isGaussian() const { return real.isInteger() && imag.isInteger(); } /** * Returns true if this number is a real number */ bool CNumber::isReal() const { return imag.isZero(); } /** * Returns true if this number is approximately a real number */ bool CNumber::isNearReal() const { return imag.isNearZero(); } void CNumber::serialize(QJsonObject& json) const { json["value"] = CMath::format(*this, CNumber::Format::Fixed() + CNumber::Format::Precision(DECPRECISION)); } CNumber CNumber::deSerialize(const QJsonObject& json) { CNumber result; if (json.contains("value")) { QString str = json["value"].toString(); str.replace(",", "."); result = CNumber(str.toLatin1().constData()); } return result; } /** * Returns a NaN (Not a Number) with error set to * passed parameter. */ CNumber CMath::nan(Error error) { // We must always ensure that both numbers have the same NaN error. CNumber result; result.real = HMath::nan(error); result.imag = HMath::nan(error); return result; } /** * Returns the error code kept with a NaN. */ Error CNumber::error() const { // real and imag have always the same NaN error. return real.error(); } /** * Assigns from another complex number. */ CNumber& CNumber::operator=(const CNumber& cn) { real = cn.real; imag = cn.imag; return *this; } /** * Adds another complex number. */ CNumber CNumber::operator+(const CNumber& num) const { CNumber result; result.real = real + num.real; result.imag = imag + num.imag; return result; } /** * Adds another complex number. */ CNumber& CNumber::operator+=(const CNumber& num) { return operator=(*this + num); } /** * Subtract from another complex number. */ CNumber operator-(const CNumber& n1, const CNumber& n2) { CNumber result; result.real = n1.real - n2.real; result.imag = n1.imag - n2.imag; return result; } /** * Subtract from another complex number. */ CNumber& CNumber::operator-=(const CNumber& num) { return operator=(*this - num); } /** * Multiplies with another complex number. */ CNumber CNumber::operator*(const CNumber& num) const { CNumber result; result.real = real*num.real - imag*num.imag; result.imag = imag*num.real + real*num.imag; return result; } /** * Multiplies with another REAL number. */ CNumber CNumber::operator*(const HNumber& num) const { CNumber result; result.real = real*num; result.imag = imag*num; return result; } /** * Multiplies with another number. */ CNumber& CNumber::operator*=(const CNumber& num) { return operator=(*this * num); } /** * Divides with another complex number. */ CNumber CNumber::operator/(const CNumber& num) const { if (num.isZero()) return CMath::nan(ZeroDivide); else { CNumber result; HNumber divider = num.real*num.real + num.imag*num.imag; result.real = (real*num.real + imag*num.imag) / divider; result.imag = (imag*num.real - real*num.imag) / divider; return result; } } /** * Divides with another REAL number. */ CNumber CNumber::operator/(const HNumber& num) const { if (num.isZero()) return CMath::nan(ZeroDivide); else return CNumber(real / num, imag / num) ; } /** * Divides with another number. */ CNumber& CNumber::operator/=(const CNumber& num) { return operator=(*this / num); } /** * Returns -1, 0, 1 if n1 is less than, equal to, or more than n2. * Only valid for real numbers, since complex ones are not an ordered field. */ int CNumber::compare(const CNumber& other) const { if (isReal() && other.isReal()) return real.compare(other.real); else return false; // FIXME: Return something better. } /** * Returns true if l is greater than r. */ bool operator>(const CNumber& l, const CNumber& r) { return l.compare(r) > 0; } /** * Returns true if l is less than r. */ bool operator<(const CNumber& l, const CNumber& r) { return l.compare(r) < 0; } /** * Returns true if l is greater than or equal to r. */ bool operator>=(const CNumber& l, const CNumber& r) { return l.compare(r) >= 0; } /** * Returns true if l is less than or equal to r. */ bool operator<=(const CNumber& l, const CNumber& r) { return l.compare(r) <= 0; } /** * Returns true if l is equal to r. */ bool operator==(const CNumber& l, const CNumber& r) { return l.compare(r) == 0; } /** * Returns true if l is not equal to r. */ bool operator!=(const CNumber& l, const CNumber& r) { return l.compare(r) != 0; } /** * Changes the sign. */ CNumber operator-(const CNumber& x) { return CNumber(-x.real, -x.imag); } CNumber::Format::Format() : HNumber::Format() , notation(Format::Notation::Null) { } CNumber::Format::Format(const Format& other) : HNumber::Format(static_cast(other)) , notation(other.notation) { } CNumber::Format::Format(const HNumber::Format& other) : HNumber::Format(other) , notation(Notation::Null) { } CNumber::Format CNumber::Format::operator+(const CNumber::Format& other) const { Format result(HNumber::Format::operator+(static_cast(other))); result.notation = (this->notation != Notation::Null) ? this->notation : other.notation; return result; } CNumber::Format CNumber::Format::Polar() { Format result; result.notation = Format::Notation::Polar; return result; } CNumber::Format CNumber::Format::Trigonometric() { Format result; result.notation = Format::Notation::Trigonometric; return result; } CNumber::Format CNumber::Format::Cis() { Format result; result.notation = Format::Notation::Cis; return result; } CNumber::Format CNumber::Format::PolarAngle() { Format result; result.notation = Format::Notation::PolarAngle; return result; } CNumber::Format CNumber::Format::Cartesian() { Format result; result.notation = Format::Notation::Cartesian; return result; } /** * Returns the constant e (Euler's number). */ CNumber CMath::e() { return CNumber(HMath::e()); } /** * Returns the constant pi. */ CNumber CMath::pi() { return CNumber(HMath::pi()); } /** * Returns the constant phi (golden number). */ CNumber CMath::phi() { return CNumber(HMath::phi()); } /** * Returns the constant i. */ CNumber CMath::i() { return CNumber(0, 1); } // TODO: Improve complex number formatting. /** * Formats the given number as string. */ QString CMath::format(const CNumber& cn, CNumber::Format format) { if (cn.isNan()) return "NaN"; else if (cn.imag.isNearZero()) // Number is real. return HMath::format(cn.real, format); if (format.notation == CNumber::Format::Notation::Polar) { QString strRadius = HMath::format(CMath::abs(cn).real, format); HNumber phase = CMath::phase(cn).real; if (phase.isZero()) return strRadius; const bool allowSymbolicPiMultiples = CMath::polarAngleUnit() == AngleMode::Radian; QString strPhase = formatRadianPhase(phase, format, allowSymbolicPiMultiples); const QString imagUnit(CMath::imaginaryUnitSymbol()); const QString operatorSpace(MathDsl::MulDotWrapSp); const QString dotOperator(MathDsl::MulDotOp); return QStringLiteral("%1%2%3%2exp(%4%2%3%2%5)") .arg(strRadius, operatorSpace, dotOperator, imagUnit, strPhase); } else if (format.notation == CNumber::Format::Notation::Trigonometric) { QString strRadius = HMath::format(CMath::abs(cn).real, format); HNumber phase = CMath::phase(cn).real; if (phase.isZero()) return strRadius; QString strPhase = formatAngleModePhase(phase, format); const QString imagUnit(CMath::imaginaryUnitSymbol()); const QString operatorSpace(MathDsl::MulDotWrapSp); const QString dotOperator(MathDsl::MulDotOp); return QStringLiteral("%1%2%3%2(cos(%4) + %5%2%3%2sin(%4))") .arg(strRadius, operatorSpace, dotOperator, strPhase, imagUnit); } else if (format.notation == CNumber::Format::Notation::Cis) { QString strRadius = HMath::format(CMath::abs(cn).real, format); HNumber phase = CMath::phase(cn).real; if (phase.isZero()) return strRadius; QString strPhase = formatAngleModePhase(phase, format); const QString operatorSpace(MathDsl::MulDotWrapSp); const QString dotOperator(MathDsl::MulDotOp); return QStringLiteral("%1%2%3%2cis(%4)") .arg(strRadius, operatorSpace, dotOperator, strPhase); } else if (format.notation == CNumber::Format::Notation::PolarAngle) { QString strRadius = HMath::format(CMath::abs(cn).real, format); HNumber phase = CMath::phase(cn).real; if (phase.isZero()) return strRadius; QString strPhase = parenthesizePhasorPhaseIfNeeded(formatAngleModePhase(phase, format)); const QString operatorSpace(MathDsl::AddWrap); return QStringLiteral("%1%2∠%2%3").arg(strRadius, operatorSpace, strPhase); } else { QString real_part = cn.real.isZero()? "" : HMath::format(cn.real, format); QString imag_part = ""; QString separator = ""; QString postfix = QString(CMath::imaginaryUnitSymbol()); if (cn.imag.isPositive()) { separator = cn.real.isZero() ? "": "+"; imag_part = HMath::format(cn.imag, format); } else { separator = "-"; imag_part = HMath::format(-cn.imag, format); } return real_part + separator + imag_part + postfix; } } /** * Returns the norm of n. */ CNumber CMath::abs(const CNumber& n) { return HMath::sqrt(n.real * n.real + n.imag * n.imag); } /* * Returns the complex conjugate of n */ CNumber CMath::conj(const CNumber& n) { return CNumber(n.real, -n.imag); } /** * Returns the square root of n. */ CNumber CMath::sqrt(const CNumber& n) { CNumber result; HNumber s = (n.imag.isPositive() || n.imag.isZero()) ? 1 : -1; // cf https://en.wikipedia.org/wiki/Square_root#Square_roots_of_negative_and_complex_numbers. result.real = HMath::sqrt((abs(n).real + n.real) / 2); result.imag = s * HMath::sqrt((abs(n).real - n.real) / 2); return result; } /** * Raises n1 to an integer n. */ CNumber CMath::raise(const CNumber& n1, int n) { return CMath::exp(CMath::ln(n1) * n); } /** * Raises n1 to n2. */ CNumber CMath::raise(const CNumber& n1, const CNumber& n2) { if (n1.isZero() && (n2.real > 0)) return CNumber(0); return CMath::exp(CMath::ln(n1) * n2); } /** * Returns e raised to x. */ CNumber CMath::exp(const CNumber& x) { HNumber abs = HMath::exp(x.real); return CNumber(abs*HMath::cos(x.imag), abs*HMath::sin(x.imag)); } /** * Returns the complex natural logarithm of x. */ CNumber CMath::ln(const CNumber& x) { CNumber result; // If real number if (x.imag.isZero()) { // If zero number, out of domain if (x.real.isZero()) return CMath::nan(OutOfDomain); // Here, non-zero number // Real part result.real = HMath::ln(HMath::abs(x.real)); // If NaN, ensures NaN and same error in both imag and real parts if (result.real.isNan()) { result.imag = result.real; return result; } // Imag part according to sign of real part result.imag = x.real.isPositive() ? 0 : HMath::pi(); } // Else, complex number else { HNumber abs = CMath::abs(x).real; result.real = HMath::ln(abs); // Principal Value logarithm // https://en.wikipedia.org/wiki/Complex_logarithm#Definition_of_principal_value auto imag = HMath::arccos(x.real / abs); result.imag = (x.imag.isPositive() || x.imag.isZero()) ? imag : -imag; } return result; } /** * Returns the common logarithm of x. */ CNumber CMath::lg(const CNumber& x) { return CMath::ln(x) / HMath::ln(10); } /** * Returns the binary logarithm of x. */ CNumber CMath::lb(const CNumber& x) { return CMath::ln(x) / HMath::ln(2); } /** * Returns the logarithm of x to base. * If x is non positive, returns NaN. */ CNumber CMath::log(const CNumber& base, const CNumber& x) { return CMath::ln(x) / CMath::ln(base); } /** * Returns the complex sine of x. Note that x must be in radians. */ CNumber CMath::sin(const CNumber& x) { // cf. https://en.wikipedia.org/wiki/Sine#Sine_with_a_complex_argument. return CNumber(HMath::sin(x.real) * HMath::cosh(x.imag), HMath::cos(x.real) * HMath::sinh(x.imag)); } /** * Returns the cosine of x. Note that x must be in radians. */ CNumber CMath::cos(const CNumber& x) { // Expanded using Wolfram Mathematica 9.0. return CNumber(HMath::cos(x.real) * HMath::cosh(x.imag), -HMath::sin(x.real) * HMath::sinh(x.imag)); } /** * Returns the tangent of x. Note that x must be in radians. */ CNumber CMath::tan(const CNumber& x) { return CMath::sin(x) / CMath::cos(x); } /** * Returns the hyperbolic sine of x. */ CNumber CMath::sinh(const CNumber& x) { return (exp(x) - exp(-x)) / HNumber(2); } /** * Returns the hyperbolic cosine of x. */ CNumber CMath::cosh(const CNumber& x) { return (exp(x) + exp(-x)) / HNumber(2); } /** * Returns the hyperbolic tangent of x. */ CNumber CMath::tanh(const CNumber& x) { if (x.isReal()) return CNumber(HMath::tanh(x.real)); return sinh(x) / cosh(x); } /** * Returns the cotangent of x. Note that x must be in radians. */ CNumber CMath::cot(const CNumber& x) { return cos(x) / sin(x); } /** * Returns the secant of x. Note that x must be in radians. */ CNumber CMath::sec(const CNumber& x) { return CNumber(1) / cos(x); } /** * Returns the cosecant of x. Note that x must be in radians. */ CNumber CMath::csc(const CNumber& x) { return CNumber(1) / sin(x); } /** * Returns the area hyperbolic sine of x. */ CNumber CMath::arsinh(const CNumber& x) { return CMath::ln(x + CMath::sqrt(x * x + CNumber(1))); } /** * Returns the area hyperbolic cosine of x. */ CNumber CMath::arcosh(const CNumber& x) { return CMath::ln(x + CMath::sqrt(x + CNumber(1)) * CMath::sqrt(x - CNumber(1))); } /** * Returns the area hyperbolic tangent of x. */ CNumber CMath::artanh(const CNumber& x) { return (CNumber("0.5") * CMath::ln(CNumber(1) + x)) - (CNumber("0.5") * CMath::ln(CNumber(1) - x)); } /** * Returns the phase of x. */ CNumber CMath::phase(const CNumber& x) { return HMath::arctan2(x.real, x.imag); } /** * Returns the arc tangent of x. */ CNumber CMath::arctan(const CNumber& x) { CNumber result = CMath::i() * (CMath::ln(CNumber(1) - CMath::i() * x) - CMath::ln(CNumber(1) + CMath::i() * x)) / 2; if (result.isNearReal()) { result.imag = 0; } return result; } /** * Returns the arc sine of x. */ CNumber CMath::arcsin(const CNumber& x) { CNumber result = -CMath::i() * CMath::ln(CMath::i() * x + sqrt(CNumber(1) - x * x)); if (result.isNearReal()) { result.imag = 0; } return result; } /** * Returns the arc cosine of x. */ CNumber CMath::arccos(const CNumber& x) { CNumber result = -CMath::i() * CMath::ln(x + sqrt(x * x - CNumber(1))); if (result.isNearReal()) { result.imag = 0; } return result; } /** * Converts an angle from radians to degrees. * Also accepts complex arguments. */ CNumber CMath::rad2deg(const CNumber& x) { return CNumber(HMath::rad2deg(x.real), HMath::rad2deg(x.imag)); } /** * Converts an angle from degrees to radians. * Also accepts complex arguments. */ CNumber CMath::deg2rad(const CNumber& x) { return CNumber(HMath::deg2rad(x.real), HMath::deg2rad(x.imag)); } /** * Converts an angle from radians to gons. * Also accepts complex arguments. */ CNumber CMath::rad2gon(const CNumber& x) { return CNumber(HMath::rad2gon(x.real), HMath::rad2gon(x.imag)); } /** * Converts an angle from gons to radians. * Also accepts complex arguments. */ CNumber CMath::gon2rad(const CNumber& x) { return CNumber(HMath::gon2rad(x.real), HMath::gon2rad(x.imag)); } // Wrappers towards functions defined only on real numbers // ======================================================= // NaN is treated like real numbers for the purposes of wrappers. #define ENSURE_REAL(number, error) \ if((number).isNan() || !(number).isNearReal()) \ return CMath::nan(error); #define REAL_WRAPPER_CNUMBER_1(fct, error) \ CNumber CNumber::fct() const \ { \ ENSURE_REAL(*this, error); \ return CNumber(this->real.fct()); \ } #define REAL_WRAPPER_CNUMBER_2(fct, error) \ CNumber CNumber::fct(const CNumber& x) const \ { \ ENSURE_REAL(*this, error); \ ENSURE_REAL(x, error); \ return CNumber(this->real.fct(x.real)); \ } #define REAL_WRAPPER_CNUMBER_3(fct, error) \ CNumber& CNumber::fct(const CNumber& x) \ { \ if(!this->isReal()) { \ *this = CMath::nan(error); \ return *this; \ } \ if (!x.isReal()) { \ *this = CMath::nan(error); \ return *this; \ } \ this->real.fct(x.real); \ return *this; \ } #define REAL_WRAPPER_CNUMBER_4(fct, error) \ int CNumber::fct() const \ { \ if (!this->isNearReal()) \ return 0; /* FIXME: Better fail value. */ \ return this->real.fct(); \ } #define REAL_WRAPPER_CMATH_NUM(fct, error) \ CNumber CMath::fct(const CNumber& x) \ { \ ENSURE_REAL(x, error); \ return CNumber(HMath::fct(x.real)); \ } #define REAL_WRAPPER_CMATH_NUM_NUM(fct, error) \ CNumber CMath::fct(const CNumber& x1, const CNumber& x2) \ { \ ENSURE_REAL(x1, error); \ ENSURE_REAL(x2, error); \ return CNumber(HMath::fct(x1.real, x2.real)); \ } #define REAL_WRAPPER_CMATH_NUM_INT(fct, error) \ CNumber CMath::fct(const CNumber& x1, int n) \ { \ ENSURE_REAL(x1, error); \ return CNumber(HMath::fct(x1.real, n)); \ } #define REAL_WRAPPER_CMATH_NUM_NUM_NUM(fct, error) \ CNumber CMath::fct(const CNumber& x1, const CNumber& x2, const CNumber& x3) \ { \ ENSURE_REAL(x1, error); \ ENSURE_REAL(x2, error); \ ENSURE_REAL(x3, error); \ return CNumber(HMath::fct(x1.real, x2.real, x3.real)); \ } #define REAL_WRAPPER_CMATH_NUM_NUM_NUM_NUM(fct, error) \ CNumber CMath::fct(const CNumber& x1, const CNumber& x2, const CNumber& x3, const CNumber& x4) \ { \ ENSURE_REAL(x1, error); \ ENSURE_REAL(x2, error); \ ENSURE_REAL(x3, error); \ ENSURE_REAL(x4, error); \ return CNumber(HMath::fct(x1.real, x2.real, x3.real, x4.real)); \ } // CNumber REAL_WRAPPER_CNUMBER_4(toInt, OutOfDomain) REAL_WRAPPER_CNUMBER_2(operator%, OutOfDomain) REAL_WRAPPER_CNUMBER_2(operator&, OutOfLogicRange) REAL_WRAPPER_CNUMBER_3(operator&=, OutOfLogicRange) REAL_WRAPPER_CNUMBER_2(operator|, OutOfLogicRange) REAL_WRAPPER_CNUMBER_3(operator|=, OutOfLogicRange) REAL_WRAPPER_CNUMBER_2(operator^, OutOfLogicRange) REAL_WRAPPER_CNUMBER_3(operator^=, OutOfLogicRange) REAL_WRAPPER_CNUMBER_1(operator~, OutOfLogicRange) REAL_WRAPPER_CNUMBER_2(operator>>, OutOfLogicRange) REAL_WRAPPER_CNUMBER_2(operator<<, OutOfLogicRange) // CMath GENERAL MATH REAL_WRAPPER_CMATH_NUM(integer, OutOfDomain) REAL_WRAPPER_CMATH_NUM(frac, OutOfDomain) REAL_WRAPPER_CMATH_NUM(floor, OutOfDomain) REAL_WRAPPER_CMATH_NUM(ceil, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(gcd, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(lcm, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(idiv, OutOfDomain) REAL_WRAPPER_CMATH_NUM_INT(round, OutOfDomain) REAL_WRAPPER_CMATH_NUM_INT(trunc, OutOfDomain) REAL_WRAPPER_CMATH_NUM(cbrt, OutOfDomain) REAL_WRAPPER_CMATH_NUM(sgn, OutOfDomain) // CMath EXPONENTIAL FUNCTION AND RELATED REAL_WRAPPER_CMATH_NUM_NUM(arctan2, OutOfDomain) // CMath TRIGONOMETRY /* All trigonometry functions accept complex numbers */ // CMath HIGHER MATH FUNCTIONS REAL_WRAPPER_CMATH_NUM_NUM(factorial, NotImplemented) REAL_WRAPPER_CMATH_NUM(erf, OutOfDomain) REAL_WRAPPER_CMATH_NUM(erfc, OutOfDomain) REAL_WRAPPER_CMATH_NUM(gamma, NotImplemented) REAL_WRAPPER_CMATH_NUM(lnGamma, NotImplemented) // CMath PROBABILITY REAL_WRAPPER_CMATH_NUM_NUM(nCr, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(nPr, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM(binomialPmf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM(binomialCdf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(binomialMean, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(binomialVariance, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM_NUM(hypergeometricPmf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM_NUM(hypergeometricCdf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM(hypergeometricMean, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM(hypergeometricVariance, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(poissonPmf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(poissonCdf, OutOfDomain) REAL_WRAPPER_CMATH_NUM(poissonMean, OutOfDomain) REAL_WRAPPER_CMATH_NUM(poissonVariance, OutOfDomain) // CMath LOGIC REAL_WRAPPER_CMATH_NUM_NUM(mask, OutOfLogicRange) REAL_WRAPPER_CMATH_NUM_NUM(sgnext, OutOfLogicRange) REAL_WRAPPER_CMATH_NUM_NUM(ashr, OutOfLogicRange) // CMath IEEE-754 CONVERSION REAL_WRAPPER_CMATH_NUM_NUM_NUM(decodeIeee754, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM_NUM(decodeIeee754, OutOfDomain) CNumber CMath::encodeIeee754(const CNumber& val, const CNumber& exp_bits, const CNumber& significand_bits, const CNumber& exp_bias) { ENSURE_REAL(exp_bits, OutOfDomain); ENSURE_REAL(significand_bits, OutOfDomain); ENSURE_REAL(exp_bias, OutOfDomain); if (!val.isNan() && !val.isNearReal()) return CMath::nan(OutOfDomain); return CNumber(HMath::encodeIeee754(val.real, exp_bits.real, significand_bits.real, exp_bias.real)); } CNumber CMath::encodeIeee754(const CNumber& val, const CNumber& exp_bits, const CNumber& significand_bits) { ENSURE_REAL(exp_bits, OutOfDomain); ENSURE_REAL(significand_bits, OutOfDomain); if (!val.isNan() && !val.isNearReal()) return CMath::nan(OutOfDomain); return CNumber(HMath::encodeIeee754(val.real, exp_bits.real, significand_bits.real)); } heldercorreia-speedcrunch-e7ca37f/src/math/cmath.h000066400000000000000000000174461526573132500223360ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2018, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef MATH_CMATH_H #define MATH_CMATH_H #include "hmath.h" #include "rational.h" #include #include class CMath; class CNumber { friend class CMath; friend CNumber operator-(const CNumber&); friend CNumber operator-(const CNumber&, const CNumber&); friend bool operator>(const CNumber&, const CNumber&); friend bool operator<(const CNumber&, const CNumber&); friend bool operator>=(const CNumber&, const CNumber&); friend bool operator<=(const CNumber&, const CNumber&); friend bool operator==(const CNumber&, const CNumber&); friend bool operator!=(const CNumber&, const CNumber&); public: CNumber(); CNumber(const HNumber&); CNumber(const HNumber&, const HNumber&); CNumber(const CNumber&); CNumber(int); CNumber(const char*); CNumber(const QJsonObject&); ~CNumber() { } bool isNan() const; bool isZero() const; bool isPositive() const; bool isNegative() const; bool isInteger() const; bool isGaussian() const; bool isReal() const; bool isNearReal() const; void serialize(QJsonObject&) const; static CNumber deSerialize(const QJsonObject&); int toInt() const; // Removed, too problematic for complex numbers. Error error() const; CNumber& operator=(const CNumber&); CNumber operator+(const CNumber&) const; CNumber& operator+=(const CNumber&); CNumber& operator-=(const CNumber&); CNumber operator*(const CNumber&) const; CNumber operator*(const HNumber&) const; CNumber operator*(int x) { return operator * (HNumber(x)); } // Overload ambiguity resolution. CNumber& operator*=(const CNumber&); CNumber operator/(const CNumber&) const; CNumber operator/(const HNumber&) const; CNumber operator/(int x) { return operator / (HNumber(x)); } // Overload ambiguity resolution. CNumber& operator/=(const CNumber&); CNumber operator%(const CNumber&) const; CNumber operator&(const CNumber&) const; CNumber& operator&=(const CNumber&); CNumber operator|(const CNumber&) const; CNumber& operator|=(const CNumber&); CNumber operator^(const CNumber&) const; CNumber& operator^=(const CNumber&); CNumber operator~() const; CNumber operator>>(const CNumber&) const; CNumber operator<<(const CNumber&) const; private: int compare(const CNumber&) const; public: HNumber real; HNumber imag; // FIXME: Better access control to real and imag. // Invariants: // - real and imag are neither or both NaN. // - real and imag have the same NaN error. struct Format : public HNumber::Format { enum class Notation {Null, Cartesian, Polar, Trigonometric, Cis, PolarAngle}; Notation notation; Format(); Format(const Format&); Format(const HNumber::Format&); Format operator+(const Format&) const; static Format Polar(); static Format Trigonometric(); static Format Cis(); static Format PolarAngle(); static Format Cartesian(); }; }; class CMath { public: static void setImaginaryUnitSymbol(QChar symbol); static QChar imaginaryUnitSymbol(); static void setPolarAngleUnit(char angleUnit); static char polarAngleUnit(); // FORMAT static QString format(const CNumber&, CNumber::Format = CNumber::Format()); // CONSTANTS static CNumber e(); static CNumber phi(); static CNumber pi(); static CNumber nan(Error error = Success); static CNumber i(); // GENERAL MATH static CNumber rad2deg(const CNumber&); static CNumber deg2rad(const CNumber&); static CNumber rad2gon(const CNumber&); static CNumber gon2rad(const CNumber&); static CNumber abs(const CNumber&); static CNumber integer(const CNumber&); static CNumber frac(const CNumber&); static CNumber floor(const CNumber&); static CNumber ceil(const CNumber&); static CNumber gcd(const CNumber&, const CNumber&); static CNumber lcm(const CNumber&, const CNumber&); static CNumber idiv(const CNumber&, const CNumber&); static CNumber round(const CNumber&, int prec = 0); static CNumber trunc(const CNumber&, int prec = 0); static CNumber sqrt(const CNumber&); static CNumber cbrt(const CNumber&); static CNumber raise(const CNumber&, int); static CNumber raise(const CNumber&, const CNumber&); static CNumber sgn(const CNumber&); // EXPONENTIAL FUNCTION AND RELATED static CNumber exp(const CNumber&); static CNumber ln(const CNumber&); static CNumber lg(const CNumber&); static CNumber lb(const CNumber&); static CNumber log(const CNumber& base, const CNumber& x); static CNumber sinh(const CNumber&); static CNumber cosh(const CNumber&); static CNumber tanh(const CNumber&); static CNumber arsinh(const CNumber&); static CNumber arcosh(const CNumber&); static CNumber artanh(const CNumber&); // COMPLEX SPECIFIC static CNumber real(const CNumber& x) {return x.real;} static CNumber imag(const CNumber& x) {return x.imag;} static CNumber conj(const CNumber& x); static CNumber phase(const CNumber&); // TRIGONOMETRY static CNumber sin(const CNumber&); static CNumber cos(const CNumber&); static CNumber tan(const CNumber&); static CNumber cot(const CNumber&); static CNumber sec(const CNumber&); static CNumber csc(const CNumber&); static CNumber arcsin(const CNumber&); static CNumber arccos(const CNumber&); static CNumber arctan(const CNumber&); static CNumber arctan2(const CNumber&, const CNumber&); // HIGHER MATH FUNCTIONS static CNumber factorial(const CNumber&, const CNumber& base = CNumber(1)); static CNumber gamma(const CNumber&); static CNumber lnGamma(const CNumber&); static CNumber erf(const CNumber&); static CNumber erfc(const CNumber&); // PROBABILITY static CNumber nCr(const CNumber&, const CNumber&); static CNumber nPr(const CNumber&, const CNumber&); static CNumber binomialPmf(const CNumber& k, const CNumber& n, const CNumber& p); static CNumber binomialCdf(const CNumber& k, const CNumber& n, const CNumber& p); static CNumber binomialMean(const CNumber& n, const CNumber& p); static CNumber binomialVariance(const CNumber& n, const CNumber& p); static CNumber hypergeometricPmf(const CNumber& k, const CNumber& N, const CNumber& M, const CNumber& n); static CNumber hypergeometricCdf(const CNumber& k, const CNumber& N, const CNumber& M, const CNumber& n); static CNumber hypergeometricMean(const CNumber& N, const CNumber& M, const CNumber& n); static CNumber hypergeometricVariance(const CNumber& N, const CNumber& M, const CNumber& n); static CNumber poissonPmf(const CNumber& k, const CNumber& l); static CNumber poissonCdf(const CNumber& k, const CNumber& l); static CNumber poissonMean(const CNumber& l); static CNumber poissonVariance(const CNumber& l); // LOGIC static CNumber mask(const CNumber&, const CNumber& bits); static CNumber sgnext(const CNumber&, const CNumber& bits); static CNumber ashr(const CNumber&, const CNumber& bits); // IEEE-754 CONVERSION static CNumber decodeIeee754(const CNumber&, const CNumber& exp_bits, const CNumber& significand_bits); static CNumber decodeIeee754(const CNumber&, const CNumber& exp_bits, const CNumber& significand_bits, const CNumber& exp_bias); static CNumber encodeIeee754(const CNumber&, const CNumber& exp_bits, const CNumber& significand_bits); static CNumber encodeIeee754(const CNumber&, const CNumber& exp_bits, const CNumber& significand_bits, const CNumber& exp_bias); }; std::ostream& operator<<(std::ostream&, const CNumber&); #endif // CMATH_CMATH_H heldercorreia-speedcrunch-e7ca37f/src/math/cnumberparser.cpp000066400000000000000000000061371526573132500244400ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later // This complex number parser currently recognizes the following forms : // // a // a+ib // a+jb // a+bi // a+bj // ib // jb // bi // bj // // The grammar describing one complex number is: // // complex_number -> part suite // suite -> [] // suite -> + part suite // // part -> prefixed_part // part -> postfixed_part // // part_prefixed -> i base_number // part_prefixed -> j base_number // // part_postfixed -> base_number postfix // // postfix -> i // postfix -> j // postfix -> [] #include "cnumberparser.h" using namespace CNumberParserExceptions; CNumberParser::CNumberParser(const char * _str) : str(_str) { } /* Parses a complex number using a recursive-desent approach. * * If successfull, stores the result into *Number. * * See header file for details. */ void CNumberParser::parse (CNumber * Number) { /* Parsing */ CNumber a = part(); CNumber b = suite(); /* Processing */ *Number = a + b; } /* Null string or empty string. strlen(NULL) is undefined. */ static char _isempty(const char* p){ return p == NULL || *p == '\0'; } /* Parsing functions. * * Each of the following function parses one producion of the grammar */ CNumber CNumberParser::part () { if (_isempty(str)) { return CMath::nan(); } else if (strncmp(str, "NaN", 3) == 0) { return CMath::nan(); } else if (*str == 'i' || *str == 'j') { return part_prefixed(); } else if (isdigit (*str) || *str == '-' || *str == '+' || *str == '.') { /* Example cases : 1.0 -1.0 +1.0 .5 */ return part_postfixed(); } else { return CMath::nan(); } } CNumber CNumberParser::suite () { if (_isempty(str)) { return CNumber(0); } else if (*str == '+') { accept(); CNumber a = part(); CNumber b = suite(); return a + b; } else if (*str == '-') { accept(); CNumber a = part(); CNumber b = suite(); return (-a) + b; } else { return CNumber(0); } } CNumber CNumberParser::part_prefixed () { if (*str == 'i' || *str == 'j') { /* Parsing */ accept(); HNumber y = base_number(); /* Processing */ HNumber x = HNumber(0); CNumber res = CNumber(x, y); return res; } else { throw UnexpectedSymbol(*str); } } HNumber CNumberParser::base_number () { /* FIXME ! Error checking ! */ HNumber x = HMath::parse_str(str, &str); return x; } CNumber CNumberParser::part_postfixed () { /* Parsing */ HNumber x = base_number(); postfix_t p = postfix(); /* Processing */ if (p == REAL) /* If real part of a complex number */ return CNumber(x, 0); else if (p == IMAG) /* If imaginary part */ return CNumber(0, x); else { /* Should never happen */ throw LogicError(); } } CNumberParser::postfix_t CNumberParser::postfix () { if (*str == 'i' || *str == 'j') { accept(); return IMAG; } else { return REAL; } } heldercorreia-speedcrunch-e7ca37f/src/math/cnumberparser.h000066400000000000000000000033611526573132500241010ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later // This complex number parser currently recognizes the following forms : // // a // a+ib // a+jb // a+bi // a+bj // ib // jb // bi // bj // // The grammar describing one complex number is: // // complex_number -> part suite // suite -> [] // suite -> + part suite // // part -> prefixed_part // part -> postfixed_part // // part_prefixed -> i base_number // part_prefixed -> j base_number // // part_postfixed -> base_number postfix // // postfix -> i // postfix -> j // postfix -> [] #ifndef CNUMBER_PARSER_HXX #define CNUMBER_PARSER_HXX #include #include #include #include "hmath.h" #include "cmath.h" class CNumberParser { private: const char * str; /* Remaining of the string to parse */ /* Parsing functions. */ void accept () {str++;} /* Each of the following function parses one producion of the grammar. */ CNumber part (); CNumber suite (); CNumber part_prefixed (); HNumber base_number (); CNumber part_postfixed (); typedef enum {IMAG, REAL} postfix_t; postfix_t postfix (); public: CNumberParser (const char * _str); void parse (CNumber * number); }; namespace CNumberParserExceptions { class Exception : public std::exception {}; class UnexpectedSymbol : public Exception { private: char symbol; public: char get_symbol () {return symbol;} UnexpectedSymbol (char _symbol) : symbol(_symbol) {} /* FIXME ! Error message ! */ }; class LogicError : public Exception {}; class UnexpectedEnd : public Exception {}; } #endif // CNUMBER_PARSER_HXX heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/000077500000000000000000000000001526573132500227025ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/README.md000066400000000000000000000053701526573132500241660ustar00rootroot00000000000000# Floatnum Module This entire module was originally written by Wolf Lammen (`ookami1 gmx de`) from 2007-2009. Only occasional maintenance and extension changes have been performed by other authors since then. ## Purpose `floatnum` is SpeedCrunch's decimal floating-point backend for high-precision and numerically stable evaluation. The code in this directory provides: - core number representation and primitive operations - conversion and I/O helpers for decimal formats - series/infrastructure helpers reused by multiple functions - elementary and higher math functions implemented on top of the same engine ## File Roles ### Core and shared infrastructure - `floatconfig.h`: compile-time configuration limits, constants, and feature toggles. - `floatlong.h`, `floatlong.c`: fixed-width helper utilities used by low-level routines. - `floatio.h`, `floatio.c`: digit-sequence and textual I/O support. - `floatnum.h`, `floatnum.c`: central decimal floating-point type and primitive arithmetic/state handling. - `floatconst.h`, `floatconst.c`: reusable mathematical constants and coefficient tables. - `floatcommon.h`, `floatcommon.c`: common utility routines shared by most math operations. - `floatconvert.h`, `floatconvert.c`: radix/format conversion routines between numeric forms. ### Series and building-block algorithms - `floatseries.h`, `floatseries.c`: reusable series expansions used by transcendental functions. - `floatipower.h`, `floatipower.c`: integer-power helpers. ### Function families - `floatexp.h`, `floatexp.c`: exponential and related functions. - `floatlog.h`, `floatlog.c`: logarithmic functions. - `floattrig.h`, `floattrig.c`: trigonometric functions. - `floatpower.h`, `floatpower.c`: generic power functions built from lower-level components. - `floatgamma.h`, `floatgamma.c`: Gamma-related computations. - `floaterf.h`, `floaterf.c`: error function and normal-distribution related integrals. - `floatlogic.h`, `floatlogic.c`: logical/integer-like operations for `floatnum` values. - `floathmath.h`, `floathmath.c`: high-level facade that combines multiple families. - `floatincgamma.h`, `floatincgamma.c`: incomplete-gamma-related operations built on higher-level math. ## Practical Structure - Base layer: `floatconfig`, `floatio`, `floatlong`, `floatnum` - Shared math substrate: `floatconst`, `floatcommon`, `floatconvert`, `floatseries`, `floatipower` - Specialized families: `floatexp`, `floatlog`, `floattrig`, `floatpower`, `floatgamma`, `floaterf`, `floatlogic` - Orchestration/top-level composition: `floathmath`, then `floatincgamma` ## Tests This module has a dedicated test target, `testfloatnum`, focused on validating the `floatnum` engine and related math routines. - Test source: [`src/tests/testfloatnum.c`](../tests/testfloatnum.c) heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatcommon.c000066400000000000000000000221561526573132500253720ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2009, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatcommon.h" #include "floatconst.h" #include "floatlong.h" #include #include #define MSB (1u << (sizeof(unsigned)*8 - 1)) #define LOGMSB ((301*(sizeof(unsigned)*8-1))/1000) static char _chckparam1( cfloatnum x, int digits, int limit, int specialval) { if (float_isnan(x)) { float_seterror(NoOperand); return 0; } if ((digits <= 0 || digits > limit) && digits != specialval) { float_seterror(InvalidPrecision); return 0; } return 1; } static char _chckparam( floatnum x, int digits, int limit, int specialval) { if (!_chckparam1(x, digits, limit, specialval)) return _setnan(x); return 1; } char chckmathparam( floatnum x, int digits) { return _chckparam(x, digits, MATHPRECISION, 1); } int logexp( cfloatnum x) { int expx, result; expx = float_getexponent(x); if (expx < 0) expx = -expx; result = -1; while (expx != 0) { expx <<= 1; ++result; } return result; } void float_setasciiz( floatnum x, const char* asciiz) { float_setscientific(x, asciiz, NULLTERMINATED); } char float_divi( floatnum quotient, cfloatnum dividend, int divisor, int digits) { floatstruct tmp; char result; int expx; if (!_chckparam1(dividend, digits, maxdigits, INTQUOT)) return _setnan(quotient); if (digits != INTQUOT && (divisor == 1 || divisor == -1)) return float_muli(quotient, dividend, divisor, digits); if (divisor == 10 || divisor == -10) { expx = float_getexponent(dividend)-1; if (expx < -float_getrange() - 1) return _seterror(quotient, Underflow); } float_create(&tmp); float_setinteger(&tmp, divisor); result = float_div(quotient, dividend, &tmp, digits); float_free(&tmp); return result; } char float_addi( floatnum sum, cfloatnum summand1, int summand2, int digits) { floatstruct tmp; char result; if (!_chckparam1(summand1, digits, maxdigits, EXACT)) return _setnan(sum); if (summand2 == 0) return float_copy(sum, summand1, digits); float_create(&tmp); float_setinteger(&tmp, summand2); result = float_add(sum, summand1, &tmp, digits); float_free(&tmp); return result; } char float_muli( floatnum product, cfloatnum factor1, int factor2, int digits) { floatstruct tmp; char result; int expx; if (!_chckparam1(factor1, digits, maxdigits, EXACT)) return _setnan(product); switch(factor2) { case 0: return _setzero(product); case 1: case -1: case 10: case -10: expx = float_getexponent(factor1); if (factor2 != 1 && factor2 != -1 && ++expx > float_getrange()) return _seterror(product, Overflow); result = float_copy(product, factor1, digits); if (factor2 < 0) float_neg(product); float_setexponent(product, expx); return result; case 2: case -2: result = float_add(product, factor1, factor1, digits); if (factor2 < 0) float_neg(product); return result; } float_create(&tmp); float_setinteger(&tmp, factor2); result = float_mul(product, factor1, &tmp, digits); float_free(&tmp); return result; } int leadingdigits( cfloatnum x, int digits) { int i; unsigned tmp, ovfl; char buf[LOGMSB+1]; const unsigned msb = MSB; if (digits <= 0 || digits > (int)LOGMSB+1 || float_isnan(x) || float_iszero(x)) return 0; memset(buf, '0', digits); float_getsignificand(buf, digits, x); tmp = 0; for(i = 0; i < digits; ++i) { ovfl = 10; if (_longmul(&tmp, &ovfl)) { ovfl = buf[i] - '0'; _longadd(&tmp, &ovfl); } if (ovfl != 0) return 0; } if (float_getsign(x) < 0) { if (tmp > msb) return 0; if (tmp == msb) return (int)tmp; return -(int)tmp; } if (tmp >= msb) return 0; return (int)tmp; } int float_abscmp( floatnum x, floatnum y) { signed char sx, sy; int result; sx = float_getsign(x); sy = float_getsign(y); float_abs(x); float_abs(y); result = float_cmp(x, y); float_setsign(x, sx); float_setsign(y, sy); return result; } int float_relcmp( floatnum x, floatnum y, int digits) { /* do not simply use float_sub, because of overflow/underflow */ floatstruct tmp; int result; int expx, expy, expdiff; result = float_cmp(x, y); if (result == 0 || float_getlength(x) == 0 || float_getlength(y) == 0 || float_getsign(x) != float_getsign(y)) return result; expx = float_getexponent(x); expy = float_getexponent(y); expdiff = expx - expy; if (expdiff >= 2 || expdiff < -2) return result; float_create(&tmp); if (result > 0) float_setexponent(x, 0); float_setexponent(y, expy - expx); float_sub(&tmp, x, y, 2); if ((result * float_getsign(x)) > 0) float_div(&tmp, &tmp, x, 2); else float_div(&tmp, &tmp, y, 2); if (float_getexponent(&tmp) < -digits) result = 0; float_setexponent(x, expx); float_setexponent(y, expy); float_free(&tmp); return result; } char float_reciprocal( floatnum x, int digits) { return float_div(x, &c1, x, digits); } char float_isinteger( cfloatnum x) { return !float_isnan(x) && float_getlength(x) <= float_getexponent(x) + 1; } int float_asinteger( cfloatnum x) { return leadingdigits(x, float_getexponent(x)+1); } void float_checkedround( floatnum x, int digits) { float_checkedroundmode(x, digits, TONEAREST); } void float_checkedroundmode( floatnum x, int digits, roundmode mode) { floatstruct tmp; int saveerr; saveerr = float_geterror(); float_create(&tmp); if (float_round(&tmp, x, digits, mode)) float_move(x, &tmp); float_free(&tmp); float_geterror(); float_seterror(saveerr); } void float_addexp( floatnum x, int smd) { float_setexponent(x, float_getexponent(x) + smd); } char float_isodd( floatnum x) { return (float_getdigit(x, float_getexponent(x)) & 1) != 0; } char float_roundtoint( floatnum x, roundmode mode) { signed char value = 0; signed char sign; char digit; if (float_isnan(x)) return float_int(x); /* sets float_error */ if (float_getexponent(x) >= 0) return float_round(x, x, float_getexponent(x) + 1, mode); sign = float_getsign(x); switch (mode) { case TONEAREST: /* For |x| < 0.1, x is always closer to 0 than to +/-1. */ if (float_getexponent(x) < -1) value = 0; else { digit = float_getdigit(x, 0); if (digit < 5 || (digit == 5 && float_getlength(x) == 1)) value = 0; else value = sign; } break; case TOINFINITY: value = sign; break; case TOPLUSINFINITY: value = sign > 0? 1 : 0; break; case TOMINUSINFINITY: value = sign > 0? 0 : -1; break; case TOZERO: value = 0; break; } switch (value) { case 0: float_setzero(x); break; case 1: float_copy(x, &c1, EXACT); break; case -1: float_copy(x, &cMinus1, EXACT); break; } return 1; } static float _ipwr(float x, int exp){ int e = exp < 0? -exp : exp; double pwr = x; if ((e & 1) == 0) x = 1; while (e >>= 1){ pwr *= pwr; if ((exp & 1) != 0) x = (float)(x * pwr); } return exp < 0? 1/x : x; } /* returns x as a float. Only the first 6 digits contribute to the result. The exponent has to be in the valid range of a float */ float float_asfloat(cfloatnum x){ return (float)(leadingdigits(x, 6)/100000.0 * _ipwr(10, float_getexponent(x))); } void float_setfloat(floatnum dest, float x){ int exp = (int)aprxlog10(x); // use two assignments to avoid overflow x *= _ipwr(10, -exp); x *= 100000000; float_setinteger(dest, (int)x); float_addexp(dest, exp - 8); } /* Somehow math.h cannot always be included with the full set of ISO C99 math functions enabled. So use the approximations below. These functions are used to get first guess start values for iterative algorithms, or to estimate round off errors, or to find the approximative size of a summand. They need not be accurate to more than, say, 0.1% */ float aprxsqrt(float x){ int exp, i; float x2 = (float)(2 * frexp(x, &exp) - 1); float result = (float)((0.5 - 0.125 * x2) * x2 + 1); x2 += 1; for (i = 0; ++i <= 2;) result = (float)(0.5 * (result + x2 / result)); if ((exp & 1) == 0) result = (float)(result * M_SQRT2); return result * _ipwr(2, (exp - 1) >> 1); } float aprxln(float x){ /* The evaluation of approxlog(x) is based on an approximation suggested by Abramowitz, Stegun, Handbook of mathematical functions. The returned logarithm is valid to 5 (decimal) digits after the decimal point. */ int exp; x = 2 * frexpf((float)fabs(x), &exp) - 1; return (float)(((((0.03215845 * x - 0.13606275) * x + 0.28947478) * x - 0.49190896) * x + 0.99949556) * x + (exp - 1) * M_LN2); } float aprxlog2(float x){ return (float)(aprxln(x) * M_LOG2E); } float aprxlog10(float x){ return (float)(aprxln(x) * M_LOG10E); } float aprxlog10fn(cfloatnum x){ return float_getexponent(x) + aprxlog10((float)leadingdigits(x, 5)) - 4; } float aprxlngamma(float x){ return (float)((x-0.5) * aprxln(x) - x + 0.9189385332f); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatcommon.h000066400000000000000000000075341526573132500254020ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2009, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATCOMMON_H # define FLOATCOMMON_H #include "floatnum.h" /* Load the system constants before supplying fallbacks. MSVC defines them outside math.h's include guard when _USE_MATH_DEFINES is enabled. */ #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES #endif #include #ifndef M_PI #define M_PI 3.14159265358979323846 // Pi #endif #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 // Square root of 2 #endif #ifndef M_LN2 #define M_LN2 0.69314718055994530942 // Natural log of 2 #endif #ifndef M_LN10 #define M_LN10 2.30258509299404568402 // Natural logarithm of 10 #endif #ifndef M_LOG2E #define M_LOG2E 1.44269504088896340736 // Log base 2 of e #endif #ifndef M_LOG10E #define M_LOG10E 0.43429448190325182765 // Log base 10 of e #endif #ifdef __cplusplus extern "C" { #endif /* helper, checks parameters. Sets float_error to NaNOperand or InvalidPrecision and sets to NaN, if the parameters do not meet the requirements of routines for higher mathematical functions, and returns 0 in this case */ char chckmathparam(floatnum x, int digits); /* helper, determines, how many decimal digits the exponent of has. If the exponent is 0, -1 is returned */ int logexp(cfloatnum x); /* helper, returns the first decimal digits and the sign of a significand, encoded in an integer. */ int leadingdigits(cfloatnum x, int digits); /* convenience wrapper for float_setscientific, setting the last parameter to NULLTERMINATED */ void float_setasciiz(floatnum x, const char* asciiz); /* convenience wrapper for float_add, adds a signed integer to and places the result in */ char float_addi(floatnum sum, cfloatnum summand1, int summand2, int digits); /* convenience wrapper for float_mul, multiplies a signed integer with and places the result in */ char float_muli(floatnum product, cfloatnum factor1, int factor2, int digits); /* convenience wrapper for float_div, divides by a signed integer and places the result in */ char float_divi(floatnum quotient, cfloatnum dividend, int divisor, int digits); /* convenience wrapper for float_cmp: compares the absolute value of both operands */ int float_abscmp(floatnum x, floatnum y); /* convenience wrapper for float_div, returns 1/ */ char float_reciprocal(floatnum x, int digits); /* compares two numbers in a normal fashion, but returns equal, if their relative difference is less than 1e-, i.e. |(x-y)/max(x,y)| < 1e- */ int float_relcmp(floatnum x, floatnum y, int digits); /* returns whether x is an integer */ char float_isinteger(cfloatnum x); /* returns the integer part of x as integer. If x exceeds the integer range, 0 is returned */ int float_asinteger(cfloatnum x); /* rounds x in TONEAREST mode. If x overflows, the rounding is reverted. Does not report errors */ void float_checkedround(floatnum x, int digits); void float_checkedroundmode(floatnum x, int digits, roundmode mode); /* a fast way to multiply with a power of ten, does not set float_error on overflow or NaN, returns silently NaN instead*/ void float_addexp(floatnum x, int smd); /* returns 0, if the integer part of x is even */ char float_isodd(floatnum x); /* an extension of float_int: you can choose the round mode errors: FLOAT_NANOPERAND FLOAT_OVERFLOW (if EXP_MAX is really small) */ char float_roundtoint(floatnum x, roundmode mode); float float_asfloat(cfloatnum x); void float_setfloat(floatnum dest, float x); float aprxsqrt(float x); float aprxln(float x); float aprxlog10(float x); float aprxlog2(float x); float aprxlngamma(float x); float aprxlog10fn(cfloatnum x); #ifdef __cplusplus } #endif #endif /* FLOATCOMMON_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatconfig.h000066400000000000000000000137631526573132500253600ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later /* this file contains the basic settings, that control the overall behaviour of floatnum and derivates. Uncomment or set any of the following defines according to your needs. */ #ifndef _FLOATCONFIG_H #define _FLOATCONFIG_H /* FLOATDEBUG introduces some extensions to floatnum, so you can easily follow operations of floatnum in a debugger like ddd. Uncomment this, if you develop code based on floatnum, and if you want to look into floatnum variables during a debugger session. */ // #define FLOATDEBUG /* enables a pre-defined set of macros so that a regression test suite of floatnum can be executed. These settings are such that corner cases can easily be triggered. The settings are not useful in a real application of floatnum. Uncomment this if you want to run the standard regression test suite of floatnum */ // #define _FLOATNUMTEST /* floatnum uses bc's bc_num format to store and operate on data. Since bc_num is an arbitrary precision format, operands may grow to extreme sizes, where complex operations take considerable time to execute, up to an hour or more. floatconfig defines a guard value to avoid extreme long operands. Any request to produce a result of more than MAXDIGITS digits is considered an error and yields a NaN result. When setting this value, bear in mind, this is a global value that effects internal operations as well as 'user' requests. When using the routines for transcendent mathematical functions, you should allow extra 14 digits, so that operations like float_exp do not fail when they compute something near maximum precision. */ #define MAXDIGITS 250 /* the number of bits into which an exponent of a floatnum is encoded. In order to avoid integer overflow, this should be at least two bits less than the bits in the integer type chosen for the exponent. The default is two bit less than the size of an int */ // #define BITS_IN_EXP 30 /* floatnum puts an upper limit on the base 10 exponent of its numbers that is based on the size of an integer, but even for 16 bit integers this limit is as big as 4095. Real applications usually do not need such big numbers. If you want to limit the range of possible numbers, set this value accordingly. An operation result exceeding this limit is converted into a NaN, and an overflow/underflow is reported. The default is the maximum positive value that can be encoded in BITS_IN_EXP bits. If you change EXPMAX, you might want to reduce BITS_IN_EXP as well. */ /* #define EXPMAX 5000 */ /* The precision of basic operations like + or * is limited by MAXDIGITS. In addition, some higher mathematical functions involve constants, that, of course, are stored to a limited precision only. This puts another bound on floatnum, described by the value MATHPRECISION. Since procedures for higher mathematical functions employ basic operations to determine their result, MATHPRECISION is <= MAXDIGITS. The current math library version of floatnum limits higher mathematical functions to 100 digits precision. One can say, MATHPRECISION describes the granularity of the number space, because higher functions do not (reliably) produce different results for values closer to each other than this granularity. You may re-define granularity by setting DECPRECISION. This will never bypass MATHPRECISION, being always the limit for the math library, but basic operations may benefit from finer granularity, up to the overall limit MAXDIGITS. If you lower granularity, that saves some memory and evaluation time in a few places. Granularity means that integers with more than DECPRECISION digits might not be saved without loss of digits. So DECPRECISION defines the integer range of floatnum. Because base convertion and logic operations are integer based, both are limited by DECPRECISION as well. By default, DECPRECISION is set to MATHPRECISION */ #define DECPRECISION 78 /* The integer domain of logical functions is a true subset of the integer range, because, according to their nature, they operate modulo a power of two, so the limit on their input is best chosen to be a power of 2. If you do not declare a limit here, an appropriate value is derived from DECPRECISION. If you change this value, make sure 2^LOGICRANGE is less than 10^DECPRECISION */ #define LOGICRANGE 256 /*************************************************************************** END OF USER SETABLE DEFINES ***************************************************************************/ /* the limit of the math library */ #define MATHPRECISION 100 #if defined(_FLOATNUMTEST) # undef MAXDIGITS # undef MATHPRECISION # undef DECPRECISION # undef LOGICRANGE # define MAXDIGITS 130 # define MATHPRECISION 130 # define LOGICRANGE 96 #endif #define MAXBITS_IN_EXP (sizeof(int)*8-2) #define MAXEXP ((1 << MAXBITS_IN_EXP) - 1) #ifndef BITS_IN_EXP /* we need 2 extra bits during conversion, so that the exponent does not overflow while computing a base 2 expression */ # define BITS_IN_EXP MAXBITS_IN_EXP #endif /* necessary width of an integer to hold all possible exponents after a conversion to another base */ #define BITS_IN_HEXEXP BITS_IN_EXP #define BITS_IN_OCTEXP (BITS_IN_EXP + 1) #define BITS_IN_BINEXP (BITS_IN_EXP + 2) #ifndef MAXDIGITS # define MAXDIGITS 500 #endif /* MAXDIGITS */ #ifndef EXPMAX # define EXPMAX ((1 << (BITS_IN_EXP-1)) - 1) #endif /* EXPMAX */ #define EXPMIN (-EXPMAX - 1) #define EXPZERO ((int)(((unsigned int)-1) << (sizeof(int)*8-1))) #define EXPNAN ((int)(~EXPZERO)) #ifndef DECPRECISION #define DECPRECISION MATHPRECISION #endif #define BINPRECISION ((33219*DECPRECISION)/10000 + 1) #define OCTPRECISION ((11073*DECPRECISION)/10000 + 1) #define HEXPRECISION ((8305*DECPRECISION)/10000 + 1) #ifndef LOGICRANGE # define LOGICRANGE (16*((BINPRECISION-2)/16)) #endif #endif /* _FLOATCONFIG_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatconst.c000066400000000000000000000254521526573132500252320ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatconst.h" static char sExp[] = "2.7182818284""5904523536""0287471352""6624977572""4709369995" "9574966967""6277240766""3035354759""4571382178""5251664274" "2746639193""2003059921""8174135966""2904357290""0334295260" "5956307381""3232862794""3490763233""8298807531""9525101901" "1573834187"; static char sLn2[] = "0.6931471805""5994530941""7232121458""1765680755""0013436025" "5254120680""0094933936""2196969471""5605863326""9964186875" "4200148102""0570685734"; static char sLn3[] = "1.0986122886""6810969139""5245236922""5257046474""9055782274" "9451734694""3336374942""9321860896""6873615754""8137320887" "8797002906""5957865742"; static char sLn7[] = "1.9459101490""5531330510""5352743443""1797296370""8472958186" "1188459390""1499375798""6275206926""7787658498""5878715269" "9306169420""5851140912"; static char sLn10[] = "2.3025850929""9404568401""7991454684""3642076011""0148862877" "2976033327""9009675726""0967735248""0235997205""0895982983" "4196778404""2286248633"; static char sPhi[] = "1.6180339887""4989484820""4586834365""6381177203""0917980576" "2862135448""6227052604""6281890244""9707207204""1893911374" "8475408807""5386891752""1266338622""2353693179""3180060766" "7263544333""8908659593""9582905638""3226613199""2829026788" "0675208766"; static char sPi[] = "3.1415926535""8979323846""2643383279""5028841971""6939937510" "5820974944""5923078164""0628620899""8628034825""3421170679" "8214808651""3282306647""0938446095""5058223172""5359408128" "4811174502""8410270193""8521105559""6446229489""5493038196" "4428810976"; static char sPiDiv2[] = "1.5707963267""9489661923""1321691639""7514420985""8469968755" "2910487472""2961539082""0314310449""9314017412""6710585339" "9107404325""6641153324"; static char sPiDiv4[] = "0.7853981633""9744830961""5660845819""8757210492""9234984377" "6455243736""1480769541""0157155224""9657008706""3355292669" "9553702162""8320576662"; static char s2Pi[] = "6.2831853071""7958647692""5286766559""0057683943""3879875021" "1641949889""1846156328""1257241799""7256069650""6842341359" "6429617302""6564613294"; static char s1DivPi[] = "0.3183098861""8379067153""7767526745""0287240689""1929148091" "2897495334""6881177935""9526845307""0180227605""5325061719" "1214568545""3515916074"; static char sLnSqrt2PiMinusHalf[] = "0.4189385332""0467274178""0329736405""6176398613""9747363778" "3412817151""5404827656""9592726039""7694743298""6359541976" "2200564662""4634337446"; static char sSqrtPi[] = "1.7724538509""0551602729""8167483341""1451827975""4945612238" "7128213807""7898529112""8459103218""1374950656""7385446654" "1622682362""4282570666"; static char s1DivSqrtPi[] = "0.5641895835""4775628694""8079451560""7725858440""5062932899" "8856844085""7217106424""6844149341""4486743660""2021073634" "4302834790""6361707352"; static char s2DivSqrtPi[] = "1.1283791670""9551257389""6158903121""5451716881""0125865799" "7713688171""4434212849""3688298682""8973487320""4042147268" "8605669581""2723414703"; static char* sBernoulli[] = { "1", "6", "1", "-30", "1", "42", "1", "-30", "5", "66", "691", "-2730", "7", "6", "3617", "-510", "43867", "798", "174611", "-330", "854513", "138", "236364091", "-2730", "8553103", "6", "23749461029", "-870", "8615841276005", "14322", "7709321041217", "-510", "2577687858367", "6", "26315271553053477373", "-1919190", "2929993913841559", "6", "261082718496449122051", "-13530", "1520097643918070802691", "1806", "27833269579301024235023", "-690", "596451111593912163277961", "282", "5609403368997817686249127547", "-46410", "495057205241079648212477525", "66", "801165718135489957347924991853", "-1590", "29149963634884862421418123812691", "798", "2479392929313226753685415739663229", "-870", "84483613348880041862046775994036021", "354", "1215233140483755572040304994079820246041491", "-56786730", "12300585434086858541953039857403386151", "6", "106783830147866529886385444979142647942017", "-510", "1472600022126335654051619428551932342241899101", "64722", "78773130858718728141909149208474606244347001", "-30", "1505381347333367003803076567377857208511438160235", "4686", "5827954961669944110438277244641067365282488301844260429", "-140100870", "34152417289221168014330073731472635186688307783087", "6", "24655088825935372707687196040585199904365267828865801", "-30", "414846365575400828295179035549542073492199375372400483487", "3318", "4603784299479457646935574969019046849794257872751288919656867", "-230010", "1677014149185145836823154509786269900207736027570253414881613", "498", "2024576195935290360231131160111731009989917391198090877281083932477", "-3404310", "660714619417678653573847847426261496277830686653388931761996983", "6", "1311426488674017507995511424019311843345750275572028644296919890574047", "-61410", "1179057279021082799884123351249215083775254949669647116231545215727922535", "272118", "1295585948207537527989427828538576749659341483719435143023316326829946247", "-1410", "1220813806579744469607301679413201203958508415202696621436215105284649447", "6", "-4.70038339580357310785752555350060606545967373697590579151397635641e73", "1", "1.13180434454842492706751862577339342678903659547507479181789935417e76", "1", "-2.83822495706937069592641563364817647382846809280128821282285317145e78", "1", "7.40642489796788506297508271409209841768797317880887066731161003487e80", "1", "-2.00964548027566044834656196727153631868672708225328766243461301989e83", "1", "5.66571700508059414457193460305193569614194682875104206213875644522e85", "1", "-1.65845111541362169158237133743199123014949626147254647274024668156e88", "1", "5.03688599504923774192894219151801548124423742649032141415256513225e90", "1", "-1.58614682376581863693634015729664387827409784127789638804728645143e93", "1", "5.17567436175456269840732406825071225612408492359305508590621669403e95", "1", "-1.74889218402171173396900258776181591451414761618265448726273472159e98", "1", "6.11605199949521852558245252642641677807677268467832007168432401127e100", "1", "-2.2122776912707834942288323456712932445573185054987780150566552693e103", "1", "8.27227767987709698542210624599845957312046505184335662838488529886e105", "1", "-3.19589251114157095835916343691808148735262766710991122731845042431e108", "1", "1.27500822233877929823100243029266798669571917963897732951605857354e111", "1", "-5.25009230867741338994028246245651754469198940377552432607801345222e113", "1", "2.2301817894241625209869298198838728143738272150875878542490550781e116", "1", "-9.76845219309552044386335133989802393011669026749856789710001706619e118", "1", "4.40983619784529542722726228748131691918757542655281147353197591401e121", "1", "-2.05085708864640888397293377275830154864565966904008359530873982755e124", "1" }; floatstruct cBernoulliNum[68]; floatstruct cBernoulliDen[68]; floatstruct c1; floatstruct c2; floatstruct c3; floatstruct c12; floatstruct c16; floatstruct cExp; floatstruct cMinus1; floatstruct cMinus20; floatstruct c1Div2; floatstruct cLn2; floatstruct cLn3; floatstruct cLn7; floatstruct cLn10; floatstruct cPhi; floatstruct cPi; floatstruct cPiDiv2; floatstruct cPiDiv4; floatstruct c2Pi; floatstruct c1DivPi; floatstruct cSqrtPi; floatstruct cLnSqrt2PiMinusHalf; floatstruct c1DivSqrtPi; floatstruct c2DivSqrtPi; floatstruct cMinus0_4; floatstruct cUnsignedBound; int erfcdigits = 0; floatstruct erfccoeff[MAXERFCIDX]; floatstruct erfcalpha; floatstruct erfcalphasqr; floatstruct erfct2; floatstruct erfct3; void floatmath_init(void) { int i, save; floatnum_init(); save = float_setprecision(MAXDIGITS); float_create(&c1); float_setinteger(&c1, 1); float_create(&c2); float_setinteger(&c2, 2); float_create(&c3); float_setinteger(&c3, 3); float_create(&c12); float_setinteger(&c12, 12); float_create(&c16); float_setinteger(&c16, 16); float_create(&cMinus1); float_setinteger(&cMinus1, -1); float_create(&cMinus20); float_setinteger(&cMinus20, -20); float_create(&c1Div2); float_setscientific(&c1Div2, ".5", NULLTERMINATED); float_create(&cExp); float_setscientific(&cExp, sExp, NULLTERMINATED); float_create(&cLn2); float_setscientific(&cLn2, sLn2, NULLTERMINATED); float_create(&cLn3); float_setscientific(&cLn3, sLn3, NULLTERMINATED); float_create(&cLn7); float_setscientific(&cLn7, sLn7, NULLTERMINATED); float_create(&cLn10); float_setscientific(&cLn10, sLn10, NULLTERMINATED); float_create(&cPhi); float_setscientific(&cPhi, sPhi, NULLTERMINATED); float_create(&cPi); float_setscientific(&cPi, sPi, NULLTERMINATED); float_create(&cPiDiv2); float_setscientific(&cPiDiv2, sPiDiv2, NULLTERMINATED); float_create(&cPiDiv4); float_setscientific(&cPiDiv4, sPiDiv4, NULLTERMINATED); float_create(&c2Pi); float_setscientific(&c2Pi, s2Pi, NULLTERMINATED); float_create(&c1DivPi); float_setscientific(&c1DivPi, s1DivPi, NULLTERMINATED); float_create(&cSqrtPi); float_setscientific(&cSqrtPi, sSqrtPi, NULLTERMINATED); float_create(&cLnSqrt2PiMinusHalf); float_setscientific(&cLnSqrt2PiMinusHalf, sLnSqrt2PiMinusHalf, NULLTERMINATED); float_create(&c1DivSqrtPi); float_setscientific(&c1DivSqrtPi, s1DivSqrtPi, NULLTERMINATED); float_create(&c2DivSqrtPi); float_setscientific(&c2DivSqrtPi, s2DivSqrtPi, NULLTERMINATED); float_create(&cMinus0_4); float_setscientific(&cMinus0_4, "-.4", NULLTERMINATED); for (i = -1; ++i < MAXBERNOULLIIDX;) { float_create(&cBernoulliNum[i]); float_create(&cBernoulliDen[i]); float_setscientific(&cBernoulliNum[i], sBernoulli[2*i], NULLTERMINATED); float_setscientific(&cBernoulliDen[i], sBernoulli[2*i+1], NULLTERMINATED); } float_create(&cUnsignedBound); float_copy(&cUnsignedBound, &c1, EXACT); for (i = -1; ++i < 2*(int)sizeof(unsigned);) float_mul(&cUnsignedBound, &c16, &cUnsignedBound, EXACT); for (i = -1; ++i < MAXERFCIDX;) float_create(&erfccoeff[i]); float_create(&erfcalpha); float_create(&erfcalphasqr); float_create(&erfct2); float_create(&erfct3); float_setprecision(save); } void floatmath_exit(void) { int i; float_free(&c1); float_free(&c2); float_free(&c3); float_free(&c12); float_free(&c16); float_free(&cMinus1); float_free(&cMinus20); float_free(&c1Div2); float_free(&cExp); float_free(&cLn2); float_free(&cLn3); float_free(&cLn7); float_free(&cLn10); float_free(&cPhi); float_free(&cPi); float_free(&cPiDiv2); float_free(&cPiDiv4); float_free(&c2Pi); float_free(&c1DivPi); float_free(&cSqrtPi); float_free(&cLnSqrt2PiMinusHalf); float_free(&c1DivSqrtPi); float_free(&c2DivSqrtPi); float_free(&cMinus0_4); for (i = -1; ++i < MAXBERNOULLIIDX;) { float_free(&cBernoulliNum[i]); float_free(&cBernoulliDen[i]); } float_free(&cUnsignedBound); for (i = -1; ++i < MAXERFCIDX;) float_free(&erfccoeff[i]); float_free(&erfcalpha); float_free(&erfcalphasqr); float_free(&erfct2); float_free(&erfct3); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatconst.h000066400000000000000000000024201526573132500252250ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2009, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATCONST_H #define FLOATCONST_H #include "floatnum.h" #define MAXBERNOULLIIDX 68 #define MAXERFCIDX 80 #ifdef __cplusplus extern "C" { #endif extern floatstruct c1; extern floatstruct c2; extern floatstruct c3; extern floatstruct c12; extern floatstruct cExp; extern floatstruct cMinus1; extern floatstruct cMinus20; extern floatstruct c1Div2; extern floatstruct cLn2; extern floatstruct cLn3; extern floatstruct cLn7; extern floatstruct cLn10; extern floatstruct cPhi; extern floatstruct cPi; extern floatstruct cPiDiv2; extern floatstruct cPiDiv4; extern floatstruct c2Pi; extern floatstruct c1DivPi; extern floatstruct cSqrtPi; extern floatstruct c1DivSqrtPi; extern floatstruct cLnSqrt2PiMinusHalf; extern floatstruct c2DivSqrtPi; extern floatstruct cMinus0_4; extern floatstruct cBernoulliNum[68]; extern floatstruct cBernoulliDen[68]; extern floatstruct cUnsignedBound; extern int erfcdigits; extern floatstruct erfccoeff[MAXERFCIDX]; extern floatstruct erfcalpha; extern floatstruct erfcalphasqr; extern floatstruct erfct2; extern floatstruct erfct3; void floatmath_init(void); void floatmath_exit(void); #ifdef __cplusplus } #endif #endif /* FLOATCONST_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatconvert.c000066400000000000000000000400161526573132500255550ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2009, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatconvert.h" #include "floatcommon.h" #include "floatconst.h" #include "floatipower.h" #include typedef struct{ t_number_desc n; t_longint l; floatnum f; int bitlength; int trailing0; int lgbase; }t_ext_number; typedef t_ext_number* p_ext_number; static io_rounding_mode s_output_rounding_mode = IO_ROUND_HALF_AWAY_FROM_ZERO; void float_set_output_rounding_mode( io_rounding_mode mode) { if (mode == IO_ROUND_HALF_EVEN || mode == IO_ROUND_HALF_AWAY_FROM_ZERO || mode == IO_ROUND_TOWARD_ZERO || mode == IO_ROUND_TOWARD_PLUS_INFINITY || mode == IO_ROUND_TOWARD_MINUS_INFINITY) s_output_rounding_mode = mode; } io_rounding_mode float_get_output_rounding_mode(void) { return s_output_rounding_mode; } static char _isexacthalf( cfloatnum x, int digits) { int i; int len = float_getlength(x); if (digits < 0 || digits >= len) return FALSE; if (float_getdigit(x, digits) != 5) return FALSE; for (i = digits + 1; i < len; ++i) { if (float_getdigit(x, i) != 0) return FALSE; } return TRUE; } static roundmode _outputroundmode( cfloatnum x, int digits, signed char sign) { if (s_output_rounding_mode == IO_ROUND_TOWARD_ZERO) return TOZERO; if (s_output_rounding_mode == IO_ROUND_TOWARD_PLUS_INFINITY) return sign < 0 ? TOMINUSINFINITY : TOPLUSINFINITY; if (s_output_rounding_mode == IO_ROUND_TOWARD_MINUS_INFINITY) return sign < 0 ? TOPLUSINFINITY : TOMINUSINFINITY; if (s_output_rounding_mode == IO_ROUND_HALF_AWAY_FROM_ZERO && _isexacthalf(x, digits)) return TOINFINITY; return TONEAREST; } /************************ conversion to/from longint *******************/ static unsigned _digitblock( floatnum f, int ofs, int count) { unsigned result; result = 0; for (; --count >= 0;) result = 10 * result + float_getdigit(f, ofs++); return result; } Error _floatnum2longint( t_longint* longint, floatnum f) { int digits; int i; unsigned factor; longint->length = 0; digits = float_getexponent(f) + 1; i = digits % 9; _longintadd(longint, _digitblock(f, 0, i)); factor = 1000000000; while (i < digits) { if (_longintmul(longint, factor) || _longintadd(longint, _digitblock(f, i, 9))) return IOConversionOverflow; i += 9; } /* extra element for floatlong operations */ *(longint->value+longint->length) = 0; return Success; } static void _setunsigned( floatnum f, unsigned value) { float_setinteger(f, value); if ((int)value < 0) float_add(f, f, &cUnsignedBound, EXACT); } void _longint2floatnum( floatnum f, t_longint* longint) { floatstruct tmp; int idx; float_setzero(f); if(longint->length == 0) return; float_create(&tmp); idx = longint->length - 1; for (; idx >= 0; --idx) { _setunsigned(&tmp, longint->value[idx]); float_mul(f, f, &cUnsignedBound, EXACT); float_add(f, f, &tmp, EXACT); } float_free(&tmp); } /************************** io routines **************************/ static int _max( int a, int b) { return a > b? a : b; } static char _validmode( char mode) { return mode >= IO_MODE_SCIENTIFIC && mode <= IO_MODE_COMPLEMENT; } static int lgbase( signed char base) { switch(base) { case 2: return 1; case 8: return 3; case 16: return 4; } return 0; } static char _getfnintdigit( int ofs, p_seq_desc n) { if (ofs <= n->digits) return float_getdigit((floatnum)(n->param), ofs); return 0; } static char _getfnfracdigit( int ofs, p_seq_desc n) { floatnum x; int exp; x = (floatnum)(n->param); exp = float_getexponent(x); if (ofs >= 0) return float_getdigit(x, ofs + exp + 1); return 0; } static void _setfndesc( p_number_desc n, floatnum x) { int digits; n->intpart.seq.base = 10; digits = _max(float_getexponent(x) + 1, 0); n->intpart.seq.digits = digits; n->intpart.seq.trailing0 = _max(digits - float_getlength(x), 0); n->intpart.seq.param = x; n->intpart.getdigit = _getfnintdigit; n->fracpart.seq.base = 10; n->fracpart.seq.leadingSignDigits = _max(-float_getexponent(x) - 1, 0); n->fracpart.seq.digits = float_getlength(x) - digits + n->fracpart.seq.leadingSignDigits; n->fracpart.seq.param = x; n->fracpart.getdigit = _getfnfracdigit; } static Error _pack2longint( t_longint* l, p_ext_seq_desc n) { int bitofs; int ofs; int logbase; logbase = lgbase((signed char)n->seq.base); ofs = n->seq.leadingSignDigits; if (_significantdigits(&n->seq) == 0) /* can be true in complement case: 0xFF00 */ --ofs; bitofs = (n->seq.digits - ofs) * logbase; if (!_longintsetsize(l, bitofs)) return IOBufferOverflow; for (; bitofs > 0;) { bitofs -= logbase; _orsubstr(l->value, bitofs, n->getdigit(ofs++, &n->seq)); } return Success; } static char _getlongintdigit( int ofs, p_seq_desc n) { if (ofs < 0 || ofs >= n->digits) return 0; return (char)(_bitsubstr(((t_longint*)(n->param))->value, (n->digits - ofs - 1) * lgbase((signed char)n->base)) & (n->base - 1)); } static char _getlongintofsdigit( int ofs, p_seq_desc n) { p_number_desc nmb; int digits; nmb = (p_number_desc)(n->param); digits = n->digits; if (ofs < 0 || ofs >= digits) return 0; digits += nmb->fracpart.seq.digits; return (char)(_bitsubstr(((t_longint*)(nmb->fracpart.seq.param))->value, (digits - ofs - 1) * lgbase((signed char)n->base)) & (n->base - 1)); } static void _setlongintdesc( p_ext_seq_desc n, t_longint* l, signed char base) { int lg; n->seq.base = base; lg = lgbase(base); n->seq.digits = (_bitlength(l) + lg - 1) / lg; n->seq.leadingSignDigits = 0; n->seq.trailing0 = _lastnonzerobit(l) / lg; n->seq.param = l; n->getdigit = _getlongintdigit; } static Error _packdec2int( floatnum x, p_ext_seq_desc n) { int ofs; int exp; int bufsz; int i; char buf[DECPRECISION]; float_setnan(x); ofs = n->seq.leadingSignDigits; exp = n->seq.trailing0; bufsz = n->seq.digits - ofs - exp; if (bufsz > DECPRECISION) return IOBufferOverflow; if (bufsz == 0) float_setzero(x); else for (i = -1; ++i < bufsz;) buf[i] = n->getdigit(ofs++, &n->seq) + '0'; float_setsignificand(x, NULL, buf, bufsz); float_setexponent(x, exp + bufsz - 1); return Success; } static Error _packbin2int( floatnum x, p_ext_seq_desc n) { t_longint l; Error result; float_setnan(x); if ((result = _pack2longint(&l, n)) != Success) return result; _longint2floatnum(x, &l); return Success; } static Error _pack2int( floatnum x, p_ext_seq_desc n) { switch(n->seq.base) { case IO_BASE_NAN: float_setnan(x); break; case IO_BASE_ZERO: float_setzero(x); break; case 10: return _packdec2int(x, n); default: return _packbin2int(x, n); } return Success; } static Error _pack2frac( floatnum x, p_ext_seq_desc n, int digits) { floatstruct tmp; int exp; Error result; n->seq.digits -= n->seq.trailing0; n->seq.trailing0 = 0; switch(n->seq.base) { case IO_BASE_NAN: float_setnan(x); break; case IO_BASE_ZERO: float_setzero(x); break; default: if ((result = _pack2int(x, n)) != Success) return result; float_create(&tmp); float_setinteger(&tmp, n->seq.base); _raiseposi(&tmp, &exp, n->seq.digits, digits+2); float_div(x, x, &tmp, digits + 2); float_setexponent(x, float_getexponent(x) - exp); float_free(&tmp); } n->seq.digits += n->seq.trailing0; return Success; } Error pack2floatnum( floatnum x, p_number_desc n) { floatstruct tmp; int digits; int saveerr; int saverange; Error result; signed char base; if ((result = _pack2int(x, &n->intpart)) != Success) return result; if (float_isnan(x)) return Success; saveerr = float_geterror(); saverange = float_setrange(MAXEXP); float_create(&tmp); float_move(&tmp, x); float_setzero(x); digits = DECPRECISION - float_getexponent(&tmp); if (digits <= 0 || (result = _pack2frac(x, &n->fracpart, digits)) == Success) float_add(x, x, &tmp, DECPRECISION); if (result != Success) return result; if ((!float_getlength(x)) == 0) /* no zero, no NaN? */ { base = n->prefix.base; float_setinteger(&tmp, base); if (n->exp >= 0) { _raiseposi_(&tmp, n->exp, DECPRECISION + 2); float_mul(x, x, &tmp, DECPRECISION + 2); } else { _raiseposi_(&tmp, -n->exp, DECPRECISION + 2); float_div(x, x, &tmp, DECPRECISION + 2); } } float_free(&tmp); float_setsign(x, n->prefix.sign == IO_SIGN_COMPLEMENT? -1 : n->prefix.sign); float_geterror(); float_seterror(saveerr); float_setrange(saverange); if (!float_isvalidexp(float_getexponent(x))) float_setnan(x); return float_isnan(x)? IOExpOverflow : Success; } static Error _outscidec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { float_checkedroundmode(x, scale + 1, _outputroundmode(x, scale + 1, n->prefix.sign)); n->exp = float_getexponent(x); float_setexponent(x, 0); _setfndesc(n, x); return desc2str(tokens, n, scale); } static int _checkbounds( floatnum x, int digits, signed char base) { if (float_getexponent(x) < 0) { float_muli(x, x, base, digits); return -1; } else if (float_asinteger(x) >= base) { float_divi(x, x, base, digits); return 1; } return 0; } static void _scale2int( floatnum x, int scale, signed char base, signed char sign) { floatstruct pwr; int pwrexp; (void)scale; if (scale != 0) { float_create(&pwr); float_setinteger(&pwr, base); _raiseposi(&pwr, &pwrexp, scale, DECPRECISION+4); float_mul(x, x, &pwr, DECPRECISION+4); float_addexp(x, pwrexp); float_free(&pwr); } float_round(x, x, float_getexponent(x) + 1, _outputroundmode(x, float_getexponent(x) + 1, sign)); } static Error _fixp2longint( p_number_desc n, t_longint* l, floatnum x, int scale) { Error result; _scale2int(x, scale, n->prefix.base, n->prefix.sign); result = _floatnum2longint(l, x); if (result != Success) return result; _setlongintdesc(&n->fracpart, l, n->prefix.base); return Success; } static int _extractexp( floatnum x, int scale, signed char base) { floatstruct pwr; floatstruct fbase; int decprec; int pwrexp; int exp; int logbase; (void)scale; logbase = lgbase(base); decprec = DECPRECISION + 3; exp = (int)(aprxlog10fn(x) * 3.321928095f); if (float_getexponent(x) < 0) exp -= 3; exp /= logbase; if (exp != 0) { float_create(&fbase); float_setinteger(&fbase, base); float_create(&pwr); float_copy(&pwr, &fbase, EXACT); _raiseposi(&pwr, &pwrexp, exp < 0? -exp : exp, decprec); if (float_getexponent(x) < 0) { float_addexp(x, pwrexp); float_mul(x, x, &pwr, decprec); } else { float_addexp(x, -pwrexp); float_div(x, x, &pwr, decprec); } float_free(&pwr); float_free(&fbase); } exp += _checkbounds(x, decprec, base); return exp; } static void _setscale( p_number_desc n, t_longint* l, int scale) { (void)l; n->intpart.seq.leadingSignDigits = 0; n->intpart.seq.trailing0 = n->fracpart.seq.trailing0 - scale; if (n->intpart.seq.trailing0 < 0) n->intpart.seq.trailing0 = 0; n->intpart.seq.base = n->fracpart.seq.base; n->intpart.seq.digits = n->fracpart.seq.digits - scale; n->intpart.getdigit = _getlongintofsdigit; n->intpart.seq.param = n; n->fracpart.seq.digits = scale; if (n->fracpart.seq.trailing0 >= scale) { n->fracpart.seq.base = IO_BASE_ZERO; n->fracpart.seq.trailing0 = scale; } } static Error _outscihex( p_otokens tokens, floatnum x, p_number_desc n, int scale) { t_longint l; Error result; n->exp = _extractexp(x, scale, n->prefix.base); result = _fixp2longint(n, &l, x, scale); if (result != Success) return result; /* rounding in _fixp2longint may have increased the exponent */ n->exp += n->fracpart.seq.digits - 1 - scale; _setscale(n, &l, n->fracpart.seq.digits - 1); return desc2str(tokens, n, scale); } static char _isvalidbase( signed char base) { return base == 10 || lgbase(base) != 0; } static Error _outsci( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base == 10) return _outscidec(tokens, x, n, scale); return _outscihex(tokens, x, n, scale); } static Error _outfixpdec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { int digits; digits = float_getexponent(x) + scale + 1; if (digits <= 0) { /* In fixed mode, values below the selected decimal place round to zero. */ float_setzero(x); n->prefix.sign = IO_SIGN_NONE; _setfndesc(n, x); return desc2str(tokens, n, scale); } if (float_round(x, x, digits, _outputroundmode(x, digits, n->prefix.sign)) != TRUE) /* float_round() can err if the number contains too many digits */ return float_geterror(); _setfndesc(n, x); return desc2str(tokens, n, scale); } static Error _outfixphex( p_otokens tokens, floatnum x, p_number_desc n, int scale) { t_longint l; Error result; float_copy(x, x, DECPRECISION+1); result = _fixp2longint(n, &l, x, scale); if (result != Success) return result; if (l.length == 0) { result = float_geterror(); return result != Success ? result : IOConversionUnderflow; } _setscale(n, &l, scale); return desc2str(tokens, n, scale); } static Error _outfixp( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base == 10) return _outfixpdec(tokens, x, n, scale); return _outfixphex(tokens, x, n, scale); } static Error _outengdec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { int shift; float_checkedroundmode(x, scale + 1, _outputroundmode(x, scale + 1, n->prefix.sign)); n->exp = float_getexponent(x); if (n->exp < 0) shift = 2 - (-n->exp-1) % 3; else shift = n->exp % 3; float_setexponent(x, shift); n->exp -= shift; _setfndesc(n, x); return desc2str(tokens, n, scale - shift); } static Error _outeng( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base != 10 || scale < 2) return InvalidParam; return _outengdec(tokens, x, n, scale); } static Error _outcompl( p_otokens tokens, floatnum x, p_number_desc n, int scale) { (void)scale; if (!float_isinteger(x)) return IOInvalidComplement; if (n->prefix.sign == IO_SIGN_MINUS) n->prefix.sign = IO_SIGN_COMPLEMENT; else n->prefix.sign = IO_SIGN_NONE; return _outfixphex(tokens, x, n, 0); } static void _emptybuffer( p_buffer token) { if (token->sz > 0) *(token->buf) = '\0'; else token->buf = NULL; } static void _emptytokens( p_otokens tokens) { _emptybuffer(&tokens->intpart); _emptybuffer(&tokens->fracpart); tokens->sign = IO_SIGN_NONE; tokens->base = IO_BASE_NAN; tokens->exp = 0; } Error float_out( p_otokens tokens, floatnum x, int scale, signed char base, char outmode) { t_number_desc n; _emptytokens(tokens); /* do some sanity checks first */ if (!_validmode(outmode) || scale < 0 || !_isvalidbase(base)) return InvalidParam; _clearnumber(&n); if (float_iszero(x)) n.prefix.base = IO_BASE_ZERO; else if (!float_isnan(x)) n.prefix.base = base; if (!_isvalidbase(n.prefix.base)) /* NaN and 0 are handled here */ return desc2str(tokens, &n, 0); n.prefix.sign = float_getsign(x); float_abs(x); switch (outmode) { case IO_MODE_FIXPOINT: return _outfixp(tokens, x, &n, scale); case IO_MODE_ENG: return _outeng(tokens, x, &n, scale); case IO_MODE_COMPLEMENT: return _outcompl(tokens, x, &n, 0); default: return _outsci(tokens, x, &n, scale); } } Error float_in( floatnum x, p_itokens tokens) { t_number_desc n; Error result; if ((result = str2desc(&n, tokens)) == Success) result = pack2floatnum(x, &n); if (result != Success) { _seterror(x, BadLiteral); float_setnan(x); } return result; } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatconvert.h000066400000000000000000000041651526573132500255670ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATCONVERT_H # define FLOATCONVERT_H #include "floatnum.h" #include "floatlong.h" #ifdef __cplusplus extern "C" { #endif #define IO_MODE_SCIENTIFIC 0 #define IO_MODE_FIXPOINT 1 #define IO_MODE_ENG 2 #define IO_MODE_COMPLEMENT 3 typedef enum { IO_ROUND_HALF_EVEN = 0, IO_ROUND_HALF_AWAY_FROM_ZERO = 1, IO_ROUND_TOWARD_ZERO = 2, IO_ROUND_TOWARD_PLUS_INFINITY = 3, IO_ROUND_TOWARD_MINUS_INFINITY = 4 } io_rounding_mode; /* converts the integer part of f to a binary coded bigint. Returns IOConversionOverflow, if the bigint overflows */ Error _floatnum2longint(t_longint* longint, floatnum f); /* converts a binary coded bigint into a floatnum */ void _longint2floatnum(floatnum f, t_longint* longint); /* the output process destroys x 'digits' are the number of digits after the dot. Regardless of the value of 'digits', a conversion is always done to DECPRECISION places Before reducing to 'digits' places the (converted) value is rounded. Trailing zeros are padded, if necessary, to fill to the right size. Errors: InvalidParam (if any of the parameters makes no sense like digits <= 0, or a not supported base) IOBufferOverflow (if the caller does not provide enough buffer in tokens) IOConversionOverflow (request requires too much buffer space for radix conversion) IOConversionUnderflow (request would produce leading zeros only) IOInvalidComplement (two's complement cannot be generated) */ Error float_out(p_otokens tokens, floatnum x, int digits, signed char base, char outmode); void float_set_output_rounding_mode(io_rounding_mode mode); io_rounding_mode float_get_output_rounding_mode(void); /* returns Success or one of the IO... codes Errors: BadLiteral, set in addition to the returned result */ Error float_in(floatnum x, p_itokens tokens); #ifdef __cplusplus } #endif #endif /* FLOATCONVERT_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floaterf.c000066400000000000000000000237161526573132500246610ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2009 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floaterf.h" #include "floatconst.h" #include "floatcommon.h" #include "floatexp.h" #include /* The Taylor expansion of sqrt(pi)*erf(x)/2 around x = 0. converges only for small |x| < 1 sufficiently. erf(x) = SUM[i>=0] (x^(2*i+1)/(i! * (2*i+1))) relative error for 100-digit evaluation: < 3e-100 */ char erfseries(floatnum x, int digits) { floatstruct xsqr, smd, pwr; int i, workprec, expx; expx = float_getexponent(x); workprec = digits + 2*expx + 2; if (workprec <= 0 || float_iszero(x)) /* for tiny arguments approx. == x */ return 1; float_create(&xsqr); float_create(&smd); float_create(&pwr); float_mul(&xsqr, x, x, workprec + 1); workprec = digits + float_getexponent(&xsqr) + 1; float_copy(&pwr, x, workprec + 1); i = 1; while (workprec > 0) { float_mul(&pwr, &pwr, &xsqr, workprec + 1); float_divi(&pwr, &pwr, -i, workprec + 1); float_divi(&smd, &pwr, 2 * i++ + 1, workprec); float_add(x, x, &smd, digits + 3); workprec = digits + float_getexponent(&smd) + expx + 2; } float_free(&pwr); float_free(&smd); float_free(&xsqr); return 1; } /* the asymptotic expansion of erfc, the bigger x is, the better. returns sum( (2*i+1)! /i! / x^(2*i) Relative error for x >= 16 and 100-digit evaluation is less than 9e-100 */ char erfcasymptotic(floatnum x, int digits) { floatstruct smd, fct; int i, workprec, newprec; float_create(&smd); float_create(&fct); workprec = digits - 2 * float_getexponent(x) + 1; if (workprec <= 0) { float_copy(x, &c1, EXACT); return 1; } float_mul(&fct, x, x, digits + 1); float_div(&fct, &c1Div2, &fct, digits); float_neg(&fct); float_copy(&smd, &c1, EXACT); float_setzero(x); newprec = digits; workprec = newprec; i = 1; while (newprec > 0 && newprec <= workprec) { workprec = newprec; float_add(x, x, &smd, digits + 4); float_muli(&smd, &smd, i, workprec + 1); float_mul(&smd, &smd, &fct, workprec + 2); newprec = digits + float_getexponent(&smd) + 1; i += 2; } float_free(&fct); float_free(&smd); return newprec <= workprec; } /* this algorithm is based on a paper from Crandall, who in turn attributes to Chiarella and Reichel. Found this in a paper from Borwein, Bailey and Girgensohn, and added minor improvements such as the adaptive working precision. There is a restriction with this algorithm not mentioned in the paper: x must not be too large, because the correcting term 2/(1-exp(2*pi*x/alpha)) becomes dominant and renders the result incorrect for large x. Fortunately, the valid range seems to overlap with the range of the asymptotic formula. Picks a fixed alpha suitable for the desired precision and evaluates the sum f(t, alpha) = Sum[k>0](exp(-k*k*alpha*alpha)/(k*k*alpha*alpha + t) f(t, alpha) is used in the evaluation of erfc(sqrt(t)) alpha is dependent on the desired precision; For a precision of p places, alpha should be < pi/sqrt(p*ln 10). Unfortunately, the smaller alpha is, the worse is the convergence rate, so alpha is usually approximately its upper limit. relative error for 100-digit evaluation < 5e-100 */ char erfcsum(floatnum x, /* should be the square of the parameter to erfc */ int digits) { int i; int workprec = 0; floatstruct sum, smd; floatnum Ei; if (digits > erfcdigits) { /* cannot re-use last evaluation's intermediate results */ for (i = MAXERFCIDX; --i >= 0;) /* clear all exp(-k*k*alpha*alpha) to indicate their absence */ float_free(&erfccoeff[i]); /* current precision */ erfcdigits = digits; /* create new alpha appropriate for the desired precision This alpha need not be high precision, any alpha near the one evaluated here would do */ float_setfloat(&erfcalpha, (float)(M_PI / aprxsqrt((float)((digits + 4) * M_LN10)))); float_round(&erfcalpha, &erfcalpha, 3, TONEAREST); float_mul(&erfcalphasqr, &erfcalpha, &erfcalpha, EXACT); /* the exp(-k*k*alpha*alpha) are later evaluated iteratively. Initiate the iteration here */ float_copy(&erfct2, &erfcalphasqr, EXACT); float_neg(&erfct2); _exp(&erfct2, digits + 3); /* exp(-alpha*alpha) */ float_copy(erfccoeff, &erfct2, EXACT); /* start value */ float_mul(&erfct3, &erfct2, &erfct2, digits + 3); /* exp(-2*alpha*alpha) */ } float_create(&sum); float_create(&smd); float_setzero(&sum); for (i = 0; ++i < MAXERFCIDX;) { Ei = &erfccoeff[i-1]; if (float_isnan(Ei)) { /* if exp(-i*i*alpha*alpha) is not available, evaluate it from the coefficient of the last summand */ float_mul(&erfct2, &erfct2, &erfct3, workprec + 3); float_mul(Ei, &erfct2, &erfccoeff[i-2], workprec + 3); } /* Ei finally decays rapidly. save some time by adjusting the working precision */ workprec = digits + float_getexponent(Ei) + 1; if (workprec <= 0) break; /* evaluate the summand exp(-i*i*alpha*alpha)/(i*i*alpha*alpha+x) */ float_muli(&smd, &erfcalphasqr, i*i, workprec); float_add(&smd, x, &smd, workprec + 2); float_div(&smd, Ei, &smd, workprec + 1); /* add summand to the series */ float_add(&sum, &sum, &smd, digits + 3); } float_move(x, &sum); float_free(&smd); return 1; } /* checks the quality of the asymptotic series for erfc. If the ratio of two subsequent summands from the series (the convergence rate) should not fall below `ratio' for a desired result precision (represented by digits), the number of summands n must not be greater than n <= (`digits'*ln 10 + 0.5 * ln 2)/(1 - ln `ratio') and the parameter x has to fullfil x >= sqrt(n/`ratio') `ratio' must be a value < 1, If you pick a value close to 1, you finally have to add quite a lot of summands from the series (in low precision), that affect a few digits at the low end of the result only. On the other hand, choosing a good convergence rate pushes the validity range of the series towards larger x. Here, the convergence rate is chosen to be 0.5, meaning that the addition of a summand from the series at least halfs the magnitude of the tail of the series. The evaluation is carried out in low precision using interger arithmetic rather than floating point data. For a 100 digit result the lower boundary of the range of the asymptotic series (truncated when the convergence rate falls below 0.5) is x > approx. 16.5. The above formulas estimate the limit x slightly too small, especially when `digits' is small. So, to compensate for that, r should be at least <= 0.92 */ static char _asymptotic_good( floatnum x, int digits) { /* all constants scaled by 10000 */ /* 1/ratio */ #define RATIO 20000 /* (1 - ln ratio) */ #define C_RATIO 16931 /* ln 10 */ #define LN10 23026 /* 0.5*ln 2 */ #define LN2DIV2 3466 int n, ix; if (!float_isvalidexp(float_getexponent(x) + 2) || (digits == 1 && float_cmp(x, &c2) >= 0)) return 1; /* 10000 * n/ratio */ n = RATIO*((digits * LN10 + LN2DIV2) / C_RATIO); float_addexp(x, 2); ix = float_asinteger(x); float_addexp(x, -2); return ix == 0 || ix >= 0x10000 || ix * ix >= n; } static int _logexpxsqr(int exp) { if (exp < 0) exp = 0; if (exp >= 0x1000) exp = 0x1000; return ((exp * exp * 73) >> 5); } char _erf( floatnum x, int digits) { int workprec; signed char sign; sign = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) > 0) { workprec = digits - _logexpxsqr(float_getexponent(x)); if (workprec < 0 || !_erfc(x, workprec)) float_setzero(x); float_sub(x, &c1, x, digits + 1); } else { erfnear0(x, digits); float_mul(x, x, &c2DivSqrtPi, digits + 2); } float_setsign(x, sign); return 1; } char _erfc( floatnum x, int digits) { floatstruct tmp, t2, t3; int expx, prec; char result; if (float_cmp(x, &c1Div2) <= 0) { /* use erfc(x) = 1 - erf(x) for small or negative x */ prec = digits; /* default for negative x, result is approx. 1 */ expx = float_getexponent(x); if (expx < 0) { /* |x| < 1, but not 0 */ prec = expx + digits + 2; if (prec <= 0) { float_copy(x, &c1, EXACT); return 1; } } _erf(x, prec); float_sub(x, &c1, x, digits + 1); return 1; } float_create(&tmp); if (_asymptotic_good(x, digits)) { if (float_mul(&tmp, x, x, digits + 5) && _exp(&tmp, digits + 3) && float_mul(&tmp, &tmp, x, digits + 3) && float_div(&tmp, &c1DivSqrtPi, &tmp, digits + 3)) { if (!erfcbigx(x, digits)) result = _seterror(x, EvalUnstable); else result = float_mul(x, x, &tmp, digits + 4); } else result = _seterror(x, Underflow); } else { result = 1; float_create(&t2); float_create(&t3); float_mul(&t2, x, x, digits + 2); float_copy(&tmp, &t2, EXACT); erfcsum(&tmp, digits); float_add(&tmp, &tmp, &tmp, digits + 1); float_copy(&t3, &t2, EXACT); float_reciprocal(&t2, digits + 1); float_add(&tmp, &tmp, &t2, digits + 2); float_neg(&t3); _exp(&t3, digits + 2); float_mul(&t3, &t3, &tmp, digits + 2); float_mul(&tmp, &erfcalpha, x, digits + 2); float_mul(&t3, &tmp, &t3, digits + 3); float_mul(&t3, &c1DivPi, &t3, digits + 2); /* quick estimate to find the right working precision */ float_div(&tmp, x, &erfcalpha, 4); float_mul(&tmp, &tmp, &c2Pi, 4); float_div(&tmp, &tmp, &cLn10, 4); prec = digits - float_getexponent(&t3) - float_asinteger(&tmp) + 1; /* add correction term */ if (prec > 0) { float_div(&tmp, x, &erfcalpha, prec + 3); float_mul(&tmp, &tmp, &c2Pi, prec + 4); _exp(&tmp, prec); float_sub(&tmp, &c1, &tmp, prec); float_div(&tmp, &c2, &tmp, prec); float_add(&t3, &t3, &tmp, digits + 1); } float_free(&t2); float_move(x, &t3); } float_free(&tmp); return result; } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floaterf.h000066400000000000000000000006251526573132500246600ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATERF_H #define FLOATERF_H #include "math/floatnum/floatseries.h" #ifdef __cplusplus extern "C" { #endif #define erfnear0 erfseries #define erfcbigx erfcasymptotic char _erf(floatnum x, int digits); char _erfc(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /* FLOATERF_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatexp.c000066400000000000000000000177201526573132500246770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatconst.h" #include "floatcommon.h" #include "floatseries.h" #include "floatexp.h" /* uses the addition theorem cosh(2x)-1 == 2*(cosh x - 1)*(cosh x + 1) to reduce the argument to the range |x| < 0.01. Starting with x == 1, you need 7 reduction steps to achieve the desired magnitude. The relative error is < 8e-100 for a 100 digit result. The return value is 0, if the result underflows. |x| < 1, otherwise the final process, where the reductions are unwinded, becomes too unstable */ char _coshminus1lt1( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return 1; float_abs(x); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(x, x, &c1Div2, digits+1); ++reductions; } if (!coshminus1near0(x, digits) && reductions == 0) return !float_iszero(x); float_create(&tmp); for(; reductions-- > 0;) { float_mul(&tmp, x, x, digits); float_add(x, x, x, digits+2); float_add(x, x, &tmp, digits+2); float_add(x, x, x, digits+2); } float_free(&tmp); return 1; } /* sinh x == sqrt((cosh x - 1) * (cosh x + 1)) */ static void _sinhfromcoshminus1( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, x, &c2, digits); float_mul(x, &tmp, x, digits+1); float_sqrt(x, digits+1); float_free(&tmp); } /* sinh x for |x| < 1. Derived from cosh x - 1. The relative error is < 8e-100 for a 100 digit result */ void _sinhlt1( floatnum x, int digits) { signed char sgn; if (float_getexponent(x) < -digits) /* for very small x: sinh(x) approx. == x. */ return; sgn = float_getsign(x); _coshminus1lt1(x, digits); _sinhfromcoshminus1(x, digits); float_setsign(x, sgn); } /* evaluates exp(x) - 1. This value can be obtained by exp(x) - 1 == sinh(x) + cosh(x) - 1 relative error < 8e-100 for a 100 digit result */ void _expminus1lt1( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (float_getexponent(x) < -digits || float_iszero(x)) /* for very small x: exp(x)-1 approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _coshminus1lt1(x, digits); float_copy(&tmp, x, EXACT); _sinhfromcoshminus1(x, digits); float_setsign(x, sgn); float_add(x, x, &tmp, digits+1); float_free(&tmp); } /* exp(x) for 0 <= x < ln 10 relative error < 5e-100 */ void _expltln10( floatnum x, int digits) { int expx; int factor; char sgnf; expx = float_getexponent(x); factor = 1; if (expx >= -1) { sgnf = (char)leadingdigits(x, 2 + expx); if (sgnf > 4) { if (sgnf < 9) { factor = 2; float_sub(x, x, &cLn2, digits+1); } else if (sgnf < 14) { factor = 3; float_sub(x, x, &cLn3, digits+1); } else if (sgnf < 21) { factor = 7; float_sub(x, x, &cLn7, digits+1); } else { factor = 10; float_sub(x, x, &cLn10, digits+1); } } } _expminus1lt1(x, digits); float_add(x, x, &c1, digits+1); if (factor != 1) float_muli(x, x, factor, digits+1); } /* exp(x) for all x. Underflow or overflow is indicated by the return value (0, if error) relative error for 100 digit results is 5e-100 */ char _exp( floatnum x, int digits) { floatstruct exp, tmp; int expx, extra; char ok; if (float_iszero(x)) { float_copy(x, &c1, EXACT); return 1; } expx = float_getexponent(x); if (expx >= (int)(BITS_IN_EXP >> 1)) /* obvious overflow or underflow */ return 0; float_create(&exp); float_create(&tmp); float_setzero(&exp); if (expx >= 0) { float_div(&exp, x, &cLn10, expx+1); float_int(&exp); extra = float_getexponent(&exp)+1; float_mul(&tmp, &exp, &cLn10, digits+extra); float_sub(x, x, &tmp, digits+extra); if (float_cmp(x, &cLn10) >= 0) { float_add(&exp, &exp, &c1, EXACT); float_sub(x, x, &cLn10, digits); } } if (float_getsign(x) < 0) { float_sub(&exp, &exp, &c1, EXACT); float_add(x, x, &cLn10, digits); } /* when we get here 0 <= x < ln 10 */ _expltln10(x, digits); /* just in case rounding leads to a value >= 10 */ expx = float_getexponent(x); if (expx != 0) float_addi(&exp, &exp, expx, EXACT); ok = 1; if (!float_iszero(&exp)) { expx = float_asinteger(&exp); ok = expx != 0; float_setexponent(x, expx); } float_free(&exp); float_free(&tmp); return ok && !float_isnan(x); } static char _0_5exp( floatnum x, int digits) { float_sub(x, x, &cLn2, digits + (3*logexp(x)/10)+1); return _exp(x, digits); } /* exp(x)-1 for all x. Overflow is indicated by the return value (0, if error) relative error for 100 digit results is 8e-100 */ char _expminus1( floatnum x, int digits) { int expr; if (float_abscmp(x, &c1Div2) < 0) { _expminus1lt1(x, digits); return 1; } if (float_getsign(x) < 0) { expr = (2*float_getexponent(x)/5); if (expr >= digits) float_setinteger(x, -1); else { _exp(x, digits-expr); float_sub(x, x, &c1, digits); } return 1; } if (!_exp(x, digits)) return 0; float_sub(x, x, &c1, digits); return 1; } static void _addreciproc( floatnum x, int digits, signed char sgn) { floatstruct tmp; int expx; expx = float_getexponent(x); if (2*expx < digits) { float_create(&tmp); float_muli(&tmp, x, 4, digits-2*expx); float_reciprocal(&tmp, digits-2*expx); float_setsign(&tmp, sgn); float_add(x, x, &tmp, digits+1); float_free(&tmp); } } /* cosh(x)-1 for all x. Underflow or overflow is indicated by the return value (0, if error) relative error for 100 digit results is 6e-100 */ char _coshminus1( floatnum x, int digits) { if (float_getexponent(x) < 0 || float_iszero(x)) return _coshminus1lt1(x, digits); if(!_0_5exp(x, digits)) return 0; _addreciproc(x, digits, 1); float_sub(x, x, &c1, digits); return 1; } /* sinh(x) for all x. Overflow is indicated by the return value (0, if error) relative error for 100 digit results is < 8e-100 */ char _sinh( floatnum x, int digits) { if (float_getexponent(x) < 0 || float_iszero(x)) _sinhlt1(x, digits); else { if(!_0_5exp(x, digits)) return 0; _addreciproc(x, digits, -1); } return 1; } /* tanh(x) for |x| <= 0.5. relative error for 100 digit results is < 7e-100 */ void _tanhlt0_5( floatnum x, int digits) { floatstruct tmp; signed char sgn; float_create(&tmp); sgn = float_getsign(x); float_abs(x); float_add(x, x, x, digits+1); _expminus1lt1(x, digits); float_add(&tmp, x, &c2, digits); float_div(x, x, &tmp, digits); float_setsign(x, sgn); float_free(&tmp); } /* tanh(x)-1 for x > 0. relative error for 100 digit results is < 9e-100 */ char _tanhminus1gt0( floatnum x, int digits) { if (float_add(x, x, x, digits+1) && _0_5exp(x, digits)) { float_add(x, x, &c1Div2, digits+1); float_reciprocal(x, digits+1); float_setsign(x, -1); return 1; } return 0; } void _tanhgt0_5( floatnum x, int digits) { floatstruct limit; int expx; /* 1 - tanh(x) < 2*exp(-2*x). For x >= 2*digits and digits >= 1, this is less than half an ulp below 1 at the requested precision. Compare before forming 2*x or exp(2*x), which may exceed the range. */ float_create(&limit); float_setinteger(&limit, 2*digits); if (float_cmp(x, &limit) >= 0) float_copy(x, &c1, EXACT); else { expx = float_getexponent(x); _tanhminus1gt0(x, digits - 5*expx); float_add(x, x, &c1, digits); } float_free(&limit); } char _power10( floatnum x, int digits) { int exp; if (float_isinteger(x)) { exp = float_asinteger(x); if (exp == 0 && !float_iszero(x)) return 0; float_copy(x, &c1, EXACT); float_setexponent(x, exp); return !float_isnan(x); } return float_mul(x, x, &cLn10, digits+2) && _exp(x, digits); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatexp.h000066400000000000000000000013621526573132500246770ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATEXP_H # define FLOATEXP_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _coshminus1lt1(floatnum x, int digits); void _sinhlt1(floatnum x, int digits); void _expminus1lt1(floatnum x, int digits); void _expltln10(floatnum x, int digits); char _exp(floatnum x, int digits); char _expminus1(floatnum x, int digits); char _coshminus1(floatnum x, int digits); void _tanhlt0_5(floatnum x, int digits); char _tanhminus1gt0(floatnum x, int digits); char _sinh(floatnum x, int digits); void _tanhgt0_5(floatnum x, int digits); char _power10(floatnum exponent, int digits); #ifdef __cplusplus } #endif #endif /* FLOATEXP_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatgamma.c000066400000000000000000000253051526573132500251630ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatgamma.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" #include "floattrig.h" /* asymptotic series of the Binet function for x >= 77 and a 100 digit computation, the relative error is < 9e-100. the series converges, if x and digits comply to 100 >= digits >= 2 x >= sqrt((digits*ln 10 + 0.5*ln 2)/1.0033). As a special case, for digits == 1, convergence is guaranteed, if x >= 1.8. */ char binetasymptotic(floatnum x, int digits) { floatstruct recsqr; floatstruct sum; floatstruct smd; floatstruct pwr; int i, workprec; if (float_getexponent(x) >= digits) { /* if x is very big, ln(gamma(x)) is dominated by x*ln x and the Binet function does not contribute anything substantial to the final result */ float_setzero(x); return 1; } float_create(&recsqr); float_create(&sum); float_create(&smd); float_create(&pwr); float_copy(&pwr, &c1, EXACT); float_setzero(&sum); float_div(&smd, &c1, &c12, digits+1); workprec = digits - 2*float_getexponent(x)+3; i = 1; if (workprec > 0) { float_mul(&recsqr, x, x, workprec); float_reciprocal(&recsqr, workprec); while (float_getexponent(&smd) > -digits-1 && ++i <= MAXBERNOULLIIDX) { workprec = digits + float_getexponent(&smd) + 3; float_add(&sum, &sum, &smd, digits+1); float_mul(&pwr, &recsqr, &pwr, workprec); float_muli(&smd, &cBernoulliDen[i-1], 2*i*(2*i-1), workprec); float_div(&smd, &pwr, &smd, workprec); float_mul(&smd, &smd, &cBernoulliNum[i-1], workprec); } } else /* sum reduces to the first summand*/ float_move(&sum, &smd); if (i > MAXBERNOULLIIDX) /* x was not big enough for the asymptotic series to converge sufficiently */ float_setnan(x); else float_div(x, &sum, x, digits); float_free(&pwr); float_free(&smd); float_free(&sum); float_free(&recsqr); return i <= MAXBERNOULLIIDX; } /* returns the number of summands needed in the asymptotic series to guarantee precision. Each extra summand yields roughly extra 1.8 digits. This is derived under the assumption, that the costs of an extra factor in the rising pochhammer symbol are about the same than those of an extra summand in the series */ static int _findorder( int digits) { return (5*digits + 5)/9; } /* returns how big x has to be to let the asymptotic series converge to at least precision. Derived from an estimation of the Bernouilli number inserted in the formula of a summand. */ static int _minx( int digits) { return (4657*_findorder(digits)-2750)/5000; } /* returns how much x has to be increased to let the asymptotic series converge to places */ static int _ofs( floatnum x, int digits) { int result; if (float_getexponent(x) >= 8) return 0; result = _minx(digits) - float_asinteger(x); return result <= 0? 0 : result; } /* evaluates the rising pochhammer symbol x*(x+1)*...*(x+n-1) (n >= 0) by multiplying. This can be expensive when n is large, so better restrict n to something sane like n <= 100. su stands for "small" and "unsigned" n */ static char _pochhammer_su( floatnum x, int n, int digits) { floatstruct factor; char result; /* the rising pochhammer symbol is computed recursively, observing that pochhammer(x, n) == pochhammer(x, p) * pochhammer(x+p, n-p). p is choosen as floor(n/2), so both factors are somehow "balanced". This pays off, if x has just a few digits, since only some late multiplications are full scale then and Karatsuba boosting yields best results, because both factors are always almost the same size. */ result = 1; switch (n) { case 0: float_copy(x, &c1, EXACT); case 1: break; default: float_create(&factor); float_addi(&factor, x, n >> 1, digits+2); result = _pochhammer_su(x, n >> 1, digits) && _pochhammer_su(&factor, n - (n >> 1), digits) && float_mul(x, x, &factor, digits+2); float_free(&factor); } return result; } /* evaluates ln(Gamma(x)) for all those x big enough to let the asymptotic series converge directly. Returns 0, if the result overflows relative error for a 100 gigit calculation < 5e-100 */ static char _lngammabigx( floatnum x, int digits) { floatstruct tmp1, tmp2; char result; result = 0; float_create(&tmp1); float_create(&tmp2); /* compute (ln x-1) * (x-0.5) - 0.5 + ln(sqrt(2*pi)) */ float_copy(&tmp2, x, digits+1); _ln(&tmp2, digits+1); float_sub(&tmp2, &tmp2, &c1, digits+2); float_sub(&tmp1, x, &c1Div2, digits+2); if (float_mul(&tmp1, &tmp1, &tmp2, digits+2)) { /* no overflow */ binetasymptotic(x, digits); float_add(x, &tmp1, x, digits+3); float_add(x, x, &cLnSqrt2PiMinusHalf, digits+3); result = 1; } float_free(&tmp2); float_free(&tmp1); return result; } static char _lngamma_prim_xgt0( floatnum x, floatnum revfactor, int digits) { int ofs; ofs = _ofs(x, digits); float_copy(revfactor, x, digits+1); _pochhammer_su(revfactor, ofs, digits); float_addi(x, x, ofs, digits+2); return _lngammabigx(x, digits); } static char _lngamma_prim( floatnum x, floatnum revfactor, int* infinity, int digits) { floatstruct tmp; char result; char odd; *infinity = 0; if (float_getsign(x) > 0) return _lngamma_prim_xgt0(x, revfactor, digits); float_copy(revfactor, x, digits + 2); float_sub(x, &c1, x, digits+2); float_create(&tmp); result = _lngamma_prim_xgt0(x, &tmp, digits); if (result) { float_neg(x); odd = float_isodd(revfactor); _sinpix(revfactor, digits); if (float_iszero(revfactor)) { *infinity = 1; float_setinteger(revfactor, odd? -1 : 1); } else float_mul(&tmp, &tmp, &cPi, digits+2); float_div(revfactor, revfactor, &tmp, digits+2); } float_free(&tmp); return result; } char _lngamma( floatnum x, int digits) { floatstruct factor; int infinity; char result; if (float_cmp(x, &c1) == 0 || float_cmp(x, &c2) == 0) return _setzero(x); float_create(&factor); result = _lngamma_prim(x, &factor, &infinity, digits) && infinity == 0; if (result) { float_abs(&factor); _ln(&factor, digits + 1); result = float_sub(x, x, &factor, digits+1); } float_free(&factor); if (infinity != 0) return _seterror(x, ZeroDivide); if (!result) float_setnan(x); return result; } char _gammagtminus20( floatnum x, int digits) { floatstruct factor; int ofs; char result; float_create(&factor); ofs = _ofs(x, digits+1); float_copy(&factor, x, digits+1); _pochhammer_su(&factor, ofs, digits); float_addi(x, x, ofs, digits+2); result = _lngammabigx(x, digits) && _exp(x, digits) && float_div(x, x, &factor, digits+1); float_free(&factor); if (!result) float_setnan(x); return result; } char _gamma( floatnum x, int digits) { floatstruct tmp; int infinity; char result; if (float_cmp(&cMinus20, x) > 0) { float_create(&tmp); result = _lngamma_prim(x, &tmp, &infinity, digits) && infinity == 0 && _exp(x, digits) && float_div(x, x, &tmp, digits + 1); float_free(&tmp); if (infinity != 0) return _seterror(x, ZeroDivide); if (!result) float_setnan(x); return result; } return _gammagtminus20(x, digits); } char _gammaint( floatnum integer, int digits) { int ofs; if (float_getexponent(integer) >=2) return _gammagtminus20(integer, digits); ofs = float_asinteger(integer); float_copy(integer, &c1, EXACT); return _pochhammer_su(integer, ofs-1, digits); } char _gamma0_5( floatnum x, int digits) { floatstruct tmp; int ofs; if (float_getexponent(x) >= 2) return _gamma(x, digits); float_create(&tmp); float_sub(&tmp, x, &c1Div2, EXACT); ofs = float_asinteger(&tmp); float_free(&tmp); if (ofs >= 0) { float_copy(x, &c1Div2, EXACT); if(!_pochhammer_su(x, ofs, digits)) return 0; return float_mul(x, x, &cSqrtPi, digits); } if(!_pochhammer_su(x, -ofs, digits)) return 0; return float_div(x, &cSqrtPi, x, digits); } static char _pochhammer_si( floatnum x, int n, int digits) { /* this extends the rising Pochhammer symbol to negative integer offsets following the formula pochhammer(x,n-1) = pochhammer(x,n)/(x-n+1) */ if (n >= 0) return _pochhammer_su(x, n, digits); return float_addi(x, x, n, digits) && _pochhammer_su(x, -n, digits) && float_reciprocal(x, digits); } static char _pochhammer_g( floatnum x, cfloatnum n, int digits) { /* this generalizes the rising Pochhammer symbol using the formula pochhammer(x,n) = Gamma(x+1)/Gamma(x-n+1) */ floatstruct tmp, factor1, factor2; int inf1, inf2; char result; float_create(&tmp); float_create(&factor1); float_create(&factor2); inf2 = 0; float_add(&tmp, x, n, digits+1); result = _lngamma_prim(x, &factor1, &inf1, digits) && _lngamma_prim(&tmp, &factor2, &inf2, digits) && (inf2 -= inf1) <= 0; if (inf2 > 0) float_seterror(ZeroDivide); if (result && inf2 < 0) float_setzero(x); if (result && inf2 == 0) result = float_div(&factor1, &factor1, &factor2, digits+1) && float_sub(x, &tmp, x, digits+1) && _exp(x, digits) && float_mul(x, x, &factor1, digits+1); float_free(&tmp); float_free(&factor2); float_free(&factor1); if (!result) float_setnan(x); return result; } static char _pochhammer_i( floatnum x, cfloatnum n, int digits) { /* do not use the expensive Gamma function when a few multiplications do the same */ /* pre: n is an integer */ int ni; signed char result; if (float_iszero(n)) return float_copy(x, &c1, EXACT); if (float_isinteger(x)) { result = -1; float_neg((floatnum)n); if (float_getsign(x) <= 0 && float_cmp(x, n) > 0) /* x and x+n have opposite signs, meaning 0 is among the factors */ result = _setzero(x); else if (float_getsign(x) > 0 && float_cmp(x, n) <= 0) /* x and x+n have opposite signs, meaning at one point you have to divide by 0 */ result = _seterror(x, ZeroDivide); float_neg((floatnum)n); if (result >= 0) return result; } if (float_getexponent(x) < EXPMAX/100) { ni = float_asinteger(n); if (ni != 0 && ni < 50 && ni > -50) return _pochhammer_si(x, ni, digits+2); } return _pochhammer_g(x, n, digits); } char _pochhammer( floatnum x, cfloatnum n, int digits) { if (float_isinteger(n)) return _pochhammer_i(x, n, digits); return _pochhammer_g(x, n, digits); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatgamma.h000066400000000000000000000007411526573132500251650ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATGAMMA_H # define FLOATGAMMA_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _lngamma(floatnum x, int digits); char _gamma(floatnum x, int digits); char _gammaint(floatnum integer, int digits); char _gamma0_5(floatnum x, int digits); char _pochhammer(floatnum x, cfloatnum n, int digits); #ifdef __cplusplus } #endif #endif /* FLOATGAMMA_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floathmath.c000066400000000000000000000264631526573132500252100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floathmath.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" #include "floattrig.h" #include "floatpower.h" #include "floatipower.h" #include "floatgamma.h" #include "floaterf.h" #include "floatlogic.h" static char _cvtlogic( t_longint* lx, cfloatnum x) { if (float_isnan(x)) { float_seterror(NoOperand); return 0; } if (_floatnum2logic(lx, x)) return 1; float_seterror(OutOfLogicRange); return 0; } char float_lnxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) < 0 && float_getexponent(x) >= 0) return _seterror(x, OutOfDomain); _lnxplus1(x, digits); return 1; } char float_ln(floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); _ln(x, digits); return 1; } char float_artanh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= 0) return _seterror(x, OutOfDomain); _artanh(x, digits); return 1; } char float_artanhxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) >= 0 || float_abscmp(x, &c2) >= 0) return _seterror(x, OutOfDomain); if (float_cmp(x, &c1Div2) < 0) { float_neg(x); _artanh1minusx(x, digits); } else { float_sub(x, &c1, x, digits+1); _artanh(x, digits); } return 1; } char float_arsinh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; _arsinh(x, digits); return 1; } char float_arcoshxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) < 0) return _seterror(x, OutOfDomain); _arcoshxplus1(x, digits); return 1; } char float_arcosh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; float_sub(x, x, &c1, digits+1); return float_arcoshxplus1(x, digits); } char float_lg( floatnum x, int digits) { floatstruct tmp; int expx; if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); float_create(&tmp); expx = float_getexponent(x); float_setexponent(x, 0); _ln(x, digits); float_div(x, x, &cLn10, digits); float_setinteger(&tmp, expx); float_add(x, x, &tmp, digits); float_free(&tmp); return 1; } char float_lb( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); _ln(x, digits); float_div(x, x, &cLn2, digits); return 1; } char float_exp( floatnum x, int digits) { signed char sgn; if (!chckmathparam(x, digits)) return 0; sgn = float_getsign(x); if (_exp(x, digits)) return 1; if (sgn < 0) return _seterror(x, Underflow); return _seterror(x, Overflow); } char float_expminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (_expminus1(x, digits)) return 1; return _seterror(x, Overflow); } char float_cosh( floatnum x, int digits) { int expx; if (!chckmathparam(x, digits)) return 0; expx = float_getexponent(x); if (2*expx+2 <= -digits || !_coshminus1(x, digits+2*expx)) { if (expx > 0) return _seterror(x, Overflow); float_setzero(x); } return float_add(x, x, &c1, digits); } char float_coshminus1( floatnum x, int digits) { int expx; if (!chckmathparam(x, digits)) return 0; expx = float_getexponent(x); if (_coshminus1(x, digits)) return 1; if (expx < 0) return _seterror(x, Underflow); return _seterror(x, Overflow); } char float_sinh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (_sinh(x, digits)) return 1; return _seterror(x, Overflow); } char float_tanh( floatnum x, int digits) { signed char sgn; if (!chckmathparam(x, digits)) return 0; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) >= 0) _tanhgt0_5(x, digits); else _tanhlt0_5(x, digits); float_setsign(x, sgn); return 1; } char float_tanhminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_cmp(x, &c1Div2) >= 0) return _tanhminus1gt0(x, digits)? 1 : _seterror(x, Underflow); if (!float_iszero(x)) { if (float_abscmp(x, &c1Div2) <= 0) _tanhlt0_5(x, digits); else { float_setsign(x, 1); _tanhgt0_5(x, digits); float_setsign(x, -1); } } return float_sub(x, x, &c1, digits); } char float_arctan( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; _arctan(x, digits); return 1; } char float_arcsin( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_abscmp(x, &c1) > 0) return _seterror(x, OutOfDomain); _arcsin(x, digits); return 1; } char float_arccos( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_abscmp(x, &c1) > 0) return _seterror(x, OutOfDomain); _arccos(x, digits); return 1; } char float_arccosxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) > 0 || float_abscmp(x, &c2) > 0) return _seterror(x, OutOfDomain); _arccosxplus1(x, digits); return 1; } char float_cos( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits)) return _seterror(x, EvalUnstable); _cos(x, digits); return 1; } char float_cosminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (!_trigreduce(x, digits)) return _seterror(x, EvalUnstable); return _cosminus1(x, digits)? 1 : _seterror(x, Underflow); } char float_sin( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits)) return _seterror(x, EvalUnstable); _sin(x, digits); return 1; } char float_tan( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; return float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits) || !_tan(x, digits)? _seterror(x, EvalUnstable) : 1; } char float_raisei( floatnum power, cfloatnum base, int exponent, int digits) { if (digits <= 0 || digits > maxdigits) return _seterror(power, InvalidPrecision); if (float_isnan(base)) return _seterror(power, NoOperand); if (float_iszero(base)) { if (exponent == 0) return _seterror(power, OutOfDomain); if (exponent < 0) return _seterror(power, ZeroDivide); return _setzero(power); } digits += 14; if (digits > maxdigits) digits = maxdigits; float_copy(power, base, digits); if (!_raisei(power, exponent, digits) || !float_isvalidexp(float_getexponent(power))) { if (float_getexponent(base) < 0) return _seterror(power, Underflow); return _seterror(power, Overflow); } return 1; } char float_raise( floatnum power, cfloatnum base, cfloatnum exponent, int digits) { signed char sgn; if (float_isnan(exponent) || float_isnan(base)) return _seterror(power, NoOperand); if (digits <= 0 || digits > MATHPRECISION) return _seterror(power, InvalidPrecision); if (float_iszero(base)) { switch(float_getsign(exponent)) { case 0: return _seterror(power, OutOfDomain); case -1: return _seterror(power, ZeroDivide); } return _setzero(power); } sgn = float_getsign(base); if (sgn < 0) { if (!float_isinteger(exponent)) return _seterror(power, OutOfDomain); if ((float_getdigit(exponent, float_getexponent(exponent)) & 1) == 0) sgn = 1; } float_copy(power, base, digits+1); float_abs(power); if (!_raise(power, exponent, digits)) { float_seterror(Overflow); if (float_getexponent(base) * float_getsign(exponent) < 0) float_seterror(Underflow); return _setnan(power); } float_setsign(power, sgn); return 1; } char float_power10( floatnum x, int digits) { signed char sign; if (!chckmathparam(x, digits)) return 0; sign = float_getsign(x); if (_power10(x, digits)) return 1; return sign > 0? _seterror(x, Overflow) : _seterror(x, Underflow); } char float_gamma( floatnum x, int digits) { signed char sign; char result; if (!chckmathparam(x, digits)) return 0; sign = float_getsign(x); if (float_isinteger(x)) { if (sign <= 0) return _seterror(x, ZeroDivide); result = _gammaint(x, digits); } else if (float_getlength(x) - float_getexponent(x) == 2 && float_getdigit(x, float_getlength(x) - 1) == 5) result = _gamma0_5(x, digits); else result = _gamma(x, digits); if (!result) { if (sign < 0) float_seterror(Underflow); else float_seterror(Overflow); float_setnan(x); } return result; } char float_lngamma( floatnum x, int digits) { if (!x) return _seterror(x, OutOfDomain); return chckmathparam(x, digits) && _lngamma(x, digits)? 1 : _setnan(x); } char float_factorial( floatnum x, int digits) { if (!float_isnan(x)) float_add(x, x, &c1, digits); return float_gamma(x, digits); } char float_pochhammer( floatnum x, cfloatnum delta, int digits) { if (!chckmathparam(x, digits)) return 0; return float_isnan(delta)? _seterror(x, NoOperand) : _pochhammer(x, delta, digits); } char float_erf(floatnum x, int digits) { return chckmathparam(x, digits)? _erf(x, digits) : 0; } char float_erfc(floatnum x, int digits) { return chckmathparam(x, digits)? _erfc(x, digits) : 0; } char float_not( floatnum x) { t_longint lx; if(!_cvtlogic(&lx, x)) return _setnan(x); _not(&lx); _logic2floatnum(x, &lx); return 1; } char float_and( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _and(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char float_or( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _or(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char float_xor( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _xor(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char _doshift( floatnum dest, cfloatnum x, cfloatnum shift, char right) { int ishift; t_longint lx; if (float_isnan(shift)) return _seterror(dest, NoOperand); if (!float_isinteger(shift)) return _seterror(dest, OutOfDomain); if(!_cvtlogic(&lx, x)) return 0; if (float_iszero(shift)) { float_copy(dest, x, EXACT); return 1; } ishift = float_asinteger(shift); if (ishift == 0) ishift = (3*LOGICRANGE) * float_getsign(shift); if (!right) ishift = -ishift; if (ishift > 0) _shr(&lx, ishift); else _shl(&lx, -ishift); _logic2floatnum(dest, &lx); return 1; } char float_shr( floatnum dest, cfloatnum x, cfloatnum shift) { return _doshift(dest, x, shift, 1); } char float_shl( floatnum dest, cfloatnum x, cfloatnum shift) { return _doshift(dest, x, shift, 0); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floathmath.h000066400000000000000000000312551526573132500252100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008, 2014, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATHMATH_H #define FLOATHMATH_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif /* evaluates ln(1+x) for x > -1. This function is especially useful for small x, where its computation is more precise than that of float_ln. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_lnxplus1(floatnum x, int digits); /* evaluates ln x (the logarithm to base e) for x > 0. Near x == 0, this function yields better results than float_lnxplus1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_ln(floatnum x, int digits); /* evaluates lg x (the logarithm to base 10) for x > 0. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_lg(floatnum x, int digits); /* evaluates lb x (the logarithm to base 2) for x > 0. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_lb(floatnum x, int digits); /* evaluates arsinh x, the inverse function of sinh. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arsinh(floatnum x, int digits); /* evaluates arcosh x, the inverse function of cosh, for x >= 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_arcosh(floatnum x, int digits); /* evaluates artanh x, the inverse function of tanh, for |x| < 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_artanh(floatnum x, int digits); /* evaluates artanh (1+x), for -2 < x <= 0. This function is especially useful, if you want to compute values near the pole at x == 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_artanhxplus1(floatnum x, int digits); /* evaluates arcosh (1+x), for x >= 0. This function is especially useful, if you want to compute values near the singularity of arcosh at x == 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_arcoshxplus1(floatnum x, int digits); /* evaluates exp(x) In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_exp(floatnum x, int digits); /* evaluates exp(x)-1. Use this in the neighbourhood of x == 0. In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_expminus1(floatnum x, int digits); /* evaluates cosh(x). In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cosh(floatnum x, int digits); /* evaluates cosh(x) - 1. Yields better results in the neighbourhood of x == 0 than float_cosh. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_coshminus1(floatnum x, int digits); /* evaluates sinh(x). In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_sinh(floatnum x, int digits); /* evaluates tanh(x). In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tanh(floatnum x, int digits); /* evaluates tanh(x)-1. Yields better results for large x > 0, when tanh x approx.== 1, than float_tanh. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tanhminus1(floatnum x, int digits); /* evaluates 10^x. No optimization is applied for integer exponents. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_power10(floatnum x, int digits); /* evaluates arctan x, yielding a result -pi/2 < result < pi/2. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arctan(floatnum x, int digits); /* evaluates arcsin x for -1 <= x <= 1, yielding a result -pi/2 <= result <= pi/2. In case of an error, x is set to NaN and 0 is returned. Errors: OutOfDomain NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arcsin(floatnum x, int digits); /* evaluates arccos x for -1 <= x <= 1, yielding a result 0 <= result <= pi. In case of an error, x is set to NaN and 0 is returned. Errors: OutOfDomain NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arccos(floatnum x, int digits); /* evaluates arccos (1+x) for -2 <= x <= 0, yielding a result 0 <= result <= pi. This function is more precise in the neighbourhood of x == 0 than float_arccos. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arccosxplus1(floatnum x, int digits); /* evaluates tan x. For extreme large x, the periodicity of tan is not recognized any more, and a FLOAT_UNSTABLE error is reported. The same holds, if x is too near to a pole of tan, more precise, if |x-0.5*n*pi| < 1e- for some n. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tan(floatnum x, int digits); /* evaluates sin x. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_sin(floatnum x, int digits); /* evaluates cos x. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cos(floatnum x, int digits); /* evaluates cos x - 1. In the neighbourhood of x==0, when cos x approx.== 1, this function yields better results than float_cos. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: Undeflow EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cosminus1(floatnum x, int digits); /* evaluates base^exponent In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow OutOfDomain (base <= 0 and most exponents) ZeroDivide ( base == 0 and exponent negative) NaNOperand InvalidPrecision (digits > maxprecision-14) */ char float_raisei(floatnum power, cfloatnum base, int exponent, int digits); /* evaluates base^exponent In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow OutOfDomain (base <= 0 and most exponents) ZeroDivide (base == 0 and exponent negative) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_raise(floatnum power, cfloatnum base, cfloatnum exponent, int digits); /* evaluates Gamma(x) = (x-1)! In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow ZeroDivide (for integers <= 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_gamma(floatnum x, int digits); /* evaluates ln(Gamma(x)) = ln((x-1)!) In case of an error, x is set to NaN and 0 is returned. Errors: Overflow OutOfDomain (for x <= 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_lngamma(floatnum x, int digits); /* evaluates x! In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow ZeroDivide (for integers < 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_factorial(floatnum x, int digits); /* evaluates gamma(x+delta)/gamma(x). If delta is a positive integer, this is the Pochhammer symbol x*(x+1)*...*(x+delta-1). The poles of the gamma function are handled appropriately. Errors: Underflow Overflow ZeroDivide (not annihilated pole in the nominator) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_pochhammer(floatnum x, cfloatnum delta, int digits); /* evaluates erf(x). NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_erf(floatnum x, int digits); /* evaluates erfc(x). Underflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_erfc(floatnum x, int digits); /* cuts off the fraction part of and complements the bits in the 2's complement representation of then. The corresponding integer of the result is stored back in . In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_not(floatnum x); /* uses the integer parts of and and builds their 2's complement representation. The resulting strings are and-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_and(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer parts of x and y and builds their 2's complement representation. The resulting strings are or-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_or(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer parts of and and builds their 2's complement representation. The resulting strings are xor-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_xor(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer part of and builds its 2's complement representation as LOGICRANGE bits. The resulting bitstring is then shifted y times to the left. Shifted out bits are dropped, to the right 0 bits are fed in. The corresponding integer of the resulting bitstring is stored in . has to be an integer or an error is reported. If it is negative, this operation turns into a shift right. In case of an error, is set to NaN and 0 is returned. Errors: OutOfDomain (y not an integer) OutOfLogicRange NaNOperand */ char float_shl(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer part of and builds its 2's complement representation as LOGICRANGE bits. The resulting bitstring is then shifted y times to the right. Shifted out bits are dropped, to the left the sign bit is duplicated. The corresponding integer of the resulting bitstring is stored in . has to be an integer or an error is reported. If it is negative, this operation turns into a shift left. In case of an error, is set to NaN and 0 is returned. Errors: OutOfDomain (y not an integer) OutOfLogicRange NaNOperand */ char float_shr(floatnum dest, cfloatnum x, cfloatnum y); #ifdef __cplusplus } #endif #endif /* FLOATLOG_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatincgamma.c000066400000000000000000000135451526573132500256600ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2009 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatincgamma.h" #include "floatconst.h" #include "floatcommon.h" #include "floathmath.h" /* many ideas are from a paper of Serge Winitzki, "Computing the incomplete Gamma function to arbitrary precision" */ /* The critical line of the lower incomplete gamma function lowgamma(a, z) is composed of all non-positive real 'a' along with z == 0. It cannot be continued on this line. Near this line lowgamma behaves approximately as 1. z^a/a, a not close to a negative integer 2. (z^a/a) + (-1)^k*z^h/h/k!, where -k is a negative integer very close to a and h = a + k very small If h << z the second summand in 2. becomes dominant, otherwise z^a/a is a rough estimate of lowgamma(a, z), diverging for fixed non-positive 'a* and z -> 0. Since z^a is true complex for real z < 0, lowgamma cannot be continued in the real number domain accross the critical line, except for 'a' a negative integer. reglowgammanearpole computes f(x, k, h) = x^(k-h) * [lowgamma(-k+h, x) - (-1)^k * x^h / h / k!] where k is an integer >= 0. It should only be used for |h| <= 0.5 and |x| not much bigger than 2. f is useful for computing both the lower and upper incomplete gamma function for values a, x close to the critical line. The term (-1)^k * x^h/(k!*h) subtracts the pole Gamma(-k), and, in addition, lowgamma(a, x) is regularized by the factor x^(k-h), in order to eliminate the singularity introduced by the factor z^a/a. f is real-valued even for negative x, where lowgamma is true complex. f is not continuous at a = (-2k-1)/2, k integer > 0, where the subtracted pole changes */ static void reglowgammanearpole(floatnum x, int k, cfloatnum h, int digits){ floatstruct tmp; float_create(&tmp); if (float_iszero(x) || float_getexponent(x) < -digits-3){ // tiny x, return the first element of the series: k > 0? 1/(h-k) : -x/(1+h) if (k > 0){ float_addi(x, h, -k, digits+2); float_reciprocal(x, digits+1); } else{ float_sub(&tmp, &cMinus1, h, digits+2); float_div(x, x, &tmp, digits+1); } } else{ // evaluate the series int workprec = digits+5; int i = 0; int expx = float_getexponent(x); floatstruct summand; floatstruct sum; float_create(&summand); float_create(&sum); float_copy(&tmp, &c1, EXACT); float_setzero(&sum); while (workprec > 0){ if (i != k){ float_addi(&summand, h, i-k, workprec); float_div(&summand, &tmp, &summand, workprec); float_add(&sum, &sum, &summand, digits+5); } workprec = digits - float_getexponent(&sum) + float_getexponent(&summand) + expx+5; if (workprec > 0){ float_mul(&tmp, &tmp, x, workprec); float_divi(&tmp, &tmp, -++i, workprec); } } float_move(x, &sum); // frees sum as a side-effect // float_free(&sum); float_free(&summand); } float_free(&tmp); } /* computes x^a (withExp = 0) or exp(-x)*x^a (withExp = 1) x^a[*exp(-x)] is the regulizing factor of the lower incomplete gamma function */ static char regulizingfactor(floatnum x, cfloatnum a, int digits, char withExp){ char result; floatstruct tmp; float_create(&tmp); result = float_raise(&tmp, x, a, digits); if (result && withExp){ float_neg(x); result = float_exp(x, digits) && float_mul(&tmp, &tmp, x, digits); } float_move(x, &tmp); // frees tmp as a side-effect // float_free(&tmp); return result; } /* adds (-1)^k * x^h / (h * k!) to lowgamma, accounting for the pole of the gamma function, h!= 0 */ static char addgammapole(floatnum lowgamma, cfloatnum x, int k, cfloatnum h, int digits){ // estimate the size of this summand, often it will not contribute // to the result char result = 1; float fh = float_getexponent(h) >= -37? float_asfloat(h) : 0; float xx; float fexp = aprxlog10fn(x); fexp *= fh; fexp -= aprxlog10fn(h); xx = aprxlngamma((float)(k+1)); xx *= 0.434294481903f; fexp += xx; fexp +=1; /* float fexp = (aprxlog2fn(x)*fh - aprxlog2fn(h)) * 0.301029995663981f - aprxlngamma(k+1) * 0.434294481903f + 1;*/ if (fexp > EXPMIN){ int exp = (int)fexp; int explowgamma = float_getexponent(lowgamma); int workprec = digits + 3; if (exp < explowgamma-3) workprec = digits - explowgamma - exp -3; if (workprec > 0){ floatstruct pwr; floatstruct fct; float_create(&pwr); float_create(&fct); float_setinteger(&fct, k); result = float_raise(&pwr, x, h, workprec) && float_factorial(&fct, workprec) && float_div(&pwr, &pwr, &fct, workprec) && float_div(&pwr, &pwr, h, workprec); if ((k & 1) != 0) float_neg(&pwr); result = result && float_add(lowgamma, lowgamma, &pwr, digits+2); float_free(&fct); float_free(&pwr); } } return result; } /* for 0.5 > a and ln Gamma(-a) / ln 10 < 2 * digits */ static char lowgammanearpole(floatnum x, cfloatnum a, int digits){ int k = float_getexponent(a); char result; floatstruct h; floatstruct lowgamma; floatstruct factor; float_create(&h); float_create(&lowgamma); float_create(&factor); float_sub(&h, a, &c1Div2, k < -1? 2 : k+3); k = -float_asinteger(&h); float_addi(&h, a, k, digits+2); float_copy(&lowgamma, x, digits+2); float_copy(&factor, x, digits+3); reglowgammanearpole(&lowgamma, k, &h, digits); result = regulizingfactor(&factor, a, digits, 0) && float_mul(&lowgamma, &lowgamma, &factor, digits+2) && addgammapole(&lowgamma, x, k, &h, digits); float_move(x, &lowgamma); // frees lowgamma float_free(&lowgamma); float_free(&h); return result; } void testincgamma(floatnum x, cfloatnum a, int digits){ lowgammanearpole(x, a, digits); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatincgamma.h000066400000000000000000000005111526573132500256520ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATINCGAMMA_H # define FLOATINCGAMMA_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif void testincgamma(floatnum x, cfloatnum a, int digits); #ifdef __cplusplus } #endif #endif /* FLOATINCGAMMA_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatio.c000066400000000000000000000530101526573132500245020ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatio.h" #include "floatlong.h" #include typedef enum { NmbNormal, NmbSpecial, NmbBufferOverflow } NmbType; /* Besides the regular bases 2, 8, 10 and 16, there are three others (IO_BASE_DEFAULT, IO_BASE_NAN and IO_BASE_ZERO) used internally to mark special situations. They are called pseudo-bases, because you cannot use them as parameter to floatnum functions */ static char _isspecial( signed char base) { switch (base) { case IO_BASE_NAN: case IO_BASE_ZERO: case IO_BASE_DEFAULT: return 1; } return 0; } /*-------------- ASCII based functions -------------*/ static char emptystr = '\0'; /* sort of alias for (strlen == 0). I don't have access to a POSIX manual, so I don't know how strlen reacts on NULL.*/ static char _isempty( const char* p) { return p == NULL || *p == '\0'; } /* copies the null-terminated ASCIIZ string src into the buffer dest. If the buffer is too small to hold src, 0 is returned */ static char _setstr( p_buffer dest, const char* src) { if (dest->sz > 0) { if (src == NULL) *(dest->buf) = '\0'; else if (dest->sz < (int)strlen(src) + 1) return 0; else strcpy(dest->buf, src); } return 1; } /* looks, whether dest begins with the substring in pattern */ static int _match( const char* dest, const char* pattern) { int lg; if (_isempty(dest) || _isempty(pattern)) return 0; lg = (int)strlen(pattern); return strncmp(dest, pattern, lg) == 0? lg : 0; } /* converts an ASCII encoded hexagesimal digit a corresponding value < 16 */ char _ascii2digit( char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return (c - 'A') + 10; if (c >= 'a' && c <= 'f') return (c - 'a') + 10; return NO_DIGIT; } static char hexdigits[] = "0123456789ABCDEF"; /* converts a value 0 <=x < 16 into a hexdigit */ char _digit2ascii( int value) { return hexdigits[value]; } /* advances the pointer buf until it points to the first character not being a valid digit of base base. The return pointer is the initial value of buf, or NULL if no digit was found */ static const char* _scandigits( const char** buf, char base) { const char* p; const char* result; result = *buf; p = result - 1; while (_ascii2digit(*++p) < base); *buf = p; return p == result? NULL : result; } /*-------------------- t_seq_desc ---------------*/ /* returns the offset6 of the last significant digit */ static int _ofslastnz( p_seq_desc n) { return n->digits - n->trailing0 - 1; } /* number of significant digits in a number sequence */ int _significantdigits( p_seq_desc n) { return n->digits - n->leadingSignDigits - n->trailing0; } /* number of digits without leading zeros in a sequence. If the sequence describes an integer, these are the digits of this integer */ static int _intdigits( p_seq_desc n) { return n->digits - n->leadingSignDigits; } /* has a sequence significant digits? */ static char _iszero( p_seq_desc n) { return _significantdigits(n) == 0; } /* returns a digit from an ASCIIZ string containing digits only */ static char _getseqdigit( int ofs, p_seq_desc n) { if (ofs < 0 || ofs > _ofslastnz(n)) return 0; return _ascii2digit(*((char*)(n->param) + ofs)); } /* returns a digit from an ASCIIZ string containing digits only, but complements them */ static char _getcmpldigit( int ofs, p_seq_desc n) { int lastnz; char c; lastnz = _ofslastnz(n); if (ofs > lastnz) return 0; c = (char)(n->base - _getseqdigit(ofs, n) - (ofs == lastnz? 0 : 1)); return c == n->base? 1 : c; } /* initializes a structure used for copying digit sequences */ static void _clearint( p_ext_seq_desc n) { n->seq.leadingSignDigits = 0; n->seq.digits = 0; n->seq.trailing0 = 0; n->seq.base = IO_BASE_ZERO; n->seq.param = NULL; n->getdigit = _getseqdigit; } /*---------------------- t_[io]token ------------------*/ /* initializes a structure used for describing a floating point number */ void _clearnumber( p_number_desc n) { n->prefix.sign = IO_SIGN_NONE; n->prefix.base = IO_BASE_NAN; _clearint(&n->intpart); _clearint(&n->fracpart); n->exp = 0; } /* creates a sequence descriptor from an ASCII digit sequence, not necessarily terminated by \0. After maxdigits digits, all following digits are assumed to be zero, regardless of their true value. */ static void _str2seq( p_ext_seq_desc n, const char* digits, int maxdigits, signed char base, char complement) { /* pre: n has to be initialized to describe a zero */ const char* p; const char* pz; char leadingdigit; unsigned char c; leadingdigit = 0; if (complement) { leadingdigit = base - 1; n->getdigit = _getcmpldigit; } p = digits; /* skip sign digits (usually 0, in complement mode F, 7 or 1 */ for (; _ascii2digit(*p) == leadingdigit; ++p); n->seq.leadingSignDigits = (int)(p - digits); /* pz is pointer to first trailing zero */ pz = p; for (; (c = _ascii2digit(*(p++))) < base;) { if (--maxdigits >= 0 && c != 0) pz = p; } n->seq.trailing0 = (int)(p - pz - 1); n->seq.digits = (int)(p - digits - 1); n->seq.param = (void*)digits; if (complement || _significantdigits(&n->seq) != 0) n->seq.base = base; } /* copy count digits (leading zeros included) from the digit sequence described by n to an ASCII buffer */ static Error _seq2str( p_buffer dest, int count, p_ext_seq_desc n) { int ofs; char* buf; ofs = 0; if (count >= dest->sz) return IOBufferOverflow; buf = dest->buf; for (; ofs < count; ++ofs) *(buf++) = _digit2ascii(n->getdigit(ofs, &n->seq)); *(buf) = '\0'; return Success; } /* copy all digits (leading zeros included) from the digit sequence described by n to an ASCII buffer, but complement the sequence before writing to the buffer */ static Error _cmplseq2str( p_buffer dest, p_ext_seq_desc n) { int bound; int ofs; int lastnz; char* buf; char c; buf = dest->buf; bound = _intdigits(&n->seq); if (bound + 1 > dest->sz) return IOBufferOverflow; lastnz = _ofslastnz(&n->seq); for (ofs = -1; ++ofs < lastnz;) { c = (char)(n->seq.base - n->getdigit(ofs, &n->seq) - 1); *(buf++) = _digit2ascii(c); } c = n->getdigit(ofs, &n->seq); if (c != 1 || _significantdigits(&n->seq) != 1) *(buf++) = _digit2ascii(n->seq.base - c); else { --bound; --ofs; } for (; ++ofs < bound;) *(buf++) = _digit2ascii(0); *(buf) = '\0'; return Success; } /* create a descriptor from a sequence of digits, assuming the sequence is an integer */ static Error str2int( p_ext_seq_desc n, const char* value, p_prefix prefix, int maxdigits) { char complement; if (prefix->base == IO_BASE_NAN) return IONoBase; complement = prefix->sign == IO_SIGN_COMPLEMENT; if (complement) { n->getdigit = _getcmpldigit; /* necessary, because when value is empty, base = IO_BASE_ZERO */ n->seq.base = prefix->base; } if (value) _str2seq(n, value, maxdigits, prefix->base, complement); return Success; } /* if base describes a special value (0 or NaN), the normal conversion routines fail. This routine creates special output values for these bases, and return nmbBufferOverflow: if the buffer is too small nmbSpecial: if it created output nmbNormal: if base stands for a usual number that the normal routines should deal with */ static NmbType _special2str( p_otokens tokens, signed char base) { const char* p; switch (base) { case IO_BASE_ZERO: p = "0"; break; case IO_BASE_NAN: p = "NaN"; break; default: return NmbNormal; } return _setstr(&tokens->intpart, p)? NmbSpecial : NmbBufferOverflow; } /* create an ASCIIZ sequence of the integer part, set sign and base. */ static Error int2str( p_otokens tokens, p_number_desc n, char complement) { tokens->sign = n->prefix.sign; tokens->base = n->prefix.base; switch (_special2str(tokens, n->prefix.base)) { case NmbSpecial: return Success; case NmbBufferOverflow: return IOBufferOverflow; default: break; /* NmbNormal */ } /* no special encodings */ if (complement) return _cmplseq2str(&tokens->intpart, &n->intpart); return _seq2str(&tokens->intpart, _intdigits(&n->intpart.seq), &n->intpart); } /* do some sanity checks, create descriptors of integer and fraction part in tokens, set sign and base */ static Error str2fixp( p_number_desc n, p_itokens tokens) { Error result; int maxdigits; maxdigits = tokens->maxdigits; n->prefix.base = tokens->base; n->prefix.sign = tokens->sign; if (tokens->sign == IO_SIGN_COMPLEMENT && (!_isempty(tokens->fracpart) || tokens->exp)) return IOInvalidComplement; result = str2int(&n->intpart, tokens->intpart, &n->prefix, maxdigits); if (_isspecial(n->prefix.base)) return result; if (!_isempty(tokens->fracpart)) _str2seq(&n->fracpart, tokens->fracpart, maxdigits - _intdigits(&n->intpart.seq), n->prefix.base, 0); if (n->prefix.sign != IO_SIGN_COMPLEMENT && n->intpart.seq.digits + n->fracpart.seq.digits == 0) return IONoSignificand; if (n->prefix.sign != IO_SIGN_COMPLEMENT && _iszero(&n->intpart.seq) && _iszero(&n->fracpart.seq)) n->prefix.base = IO_BASE_ZERO; return Success; } /* convert integer and fraction part into ASCIIZ sequences */ static Error fixp2str( p_otokens tokens, p_number_desc n, int scale) { Error result; result = int2str(tokens, n, n->prefix.sign == IO_SIGN_COMPLEMENT); if (result != Success || _isspecial(n->prefix.base)) return result; return _seq2str(&tokens->fracpart, scale, &n->fracpart); } /* create a descriptor from the digit sequence of the exponent */ static Error _exp2desc( p_number_desc n, p_itokens tokens) { if (tokens->expsign != IO_SIGN_NONE || tokens->exp) { unsigned upperLimit; signed char sign; switch (tokens->base) { case 2 : upperLimit = BITS_IN_BINEXP - 1; break; case 8 : upperLimit = BITS_IN_OCTEXP - 1; break; case 16: upperLimit = BITS_IN_HEXEXP - 1; break; default: upperLimit = BITS_IN_EXP - 1; break; } upperLimit = (1 << (upperLimit)) - 1; sign = tokens->expsign; switch (sign) { case IO_SIGN_COMPLEMENT: return IOBadExp; case IO_SIGN_NONE: sign = IO_SIGN_PLUS; break; case IO_SIGN_MINUS: ++upperLimit; break; default:; } if (tokens->exp > upperLimit) return IOExpOverflow; if (sign < 0) n->exp = -(int)(tokens->exp); else n->exp = tokens->exp; } return Success; } /* create a descriptor from the floating point number given in tokens */ Error str2desc( p_number_desc n, p_itokens tokens) { Error result; _clearnumber(n); result = str2fixp(n, tokens); if (result == Success) result = _exp2desc(n, tokens); if (result != Success) n->prefix.base = IO_BASE_NAN; return result; } Error desc2str( p_otokens tokens, p_number_desc n, int scale) { Error result; result = fixp2str(tokens, n, scale); if (result != Success || _isspecial(n->prefix.base)) return result; tokens->exp = n->exp; return Success; } Error exp2str( p_buffer dest, int exp, char base) { char tmp[BITS_IN_EXP + 3]; int idx = 0; int di = 0; if (exp < 0) exp = -exp; while (exp != 0) { tmp[idx++] = hexdigits[exp % base]; exp /= base; } if (idx == 0) tmp[idx++] = hexdigits[0]; if (dest->sz <= idx) return IOBufferOverflow; for (; --idx >= 0;) dest->buf[di++] = tmp[idx]; dest->buf[di] = 0; return Success; } /* ***************** additional stuff, just to get started *************/ static t_ioparams stdioparams[4] = { {10, 10, '.', "0d", "eE(", " )", "", DECPRECISION}, {16, 10, '.', "0x", "hH(", " )", "sF", HEXPRECISION}, {2, 10, '.', "0b", "bB(", " )", "s1", BINPRECISION}, {8, 10, '.', "0o", "oOC(", " )", "s7", OCTPRECISION} }; enum {idzero, idx10, idx16, idx2, idx8, idxcount}; static t_ioparams ioparams[idxcount] = { {IO_BASE_ZERO, IO_BASE_ZERO, '\0', "", "", "", "", 0x7FFFFFFF}, {IO_BASE_DEFAULT, IO_BASE_DEFAULT, '\0', "", "", "", "", 0}, {IO_BASE_DEFAULT, IO_BASE_DEFAULT, '\0', "", "", "", "", 0}, {IO_BASE_DEFAULT, IO_BASE_DEFAULT, '\0', "", "", "", "", 0}, {IO_BASE_DEFAULT, IO_BASE_DEFAULT, '\0', "", "", "", "", 0} }; static p_ioparams _defaultbase = NULL; static char _isvalidioparams( p_ioparams param) { return param != NULL && param->base != IO_BASE_DEFAULT; } static void _invalidateioparams( p_ioparams param) { if (param) param->base = IO_BASE_DEFAULT; } p_ioparams _base2ioparams( signed char base) { int idx; switch (base) { case 10: idx = idx10; break; case 16: idx = idx16; break; case 2: idx = idx2; break; case 8: idx = idx8; break; case IO_BASE_ZERO: idx = idzero; break; default: return NULL; } return &ioparams[idx]; } char setioparams( p_ioparams params) { p_ioparams dest; if (!_isvalidioparams(params)) return 0; dest = _base2ioparams(params->base); if (dest == NULL) return 0; *dest = *params; return 1; } char delioparams( signed char base) { p_ioparams dest; dest = _base2ioparams(base); _invalidateioparams(dest); return dest != NULL; } p_ioparams getioparams( signed char base) { p_ioparams result; if (base == IO_BASE_DEFAULT) return _defaultbase; result = _base2ioparams(base); return _isvalidioparams(result)? result : NULL; } static signed char _getdefaultbase(void) { p_ioparams param; param = getioparams(IO_BASE_DEFAULT); return param == NULL? IO_BASE_DEFAULT : param->base; } signed char setdefaultbase( signed char base) { char result; result = _getdefaultbase(); _defaultbase = _base2ioparams(base); return result; } void float_stdconvert(void) { int i; for (i = 0; i < 4; ++i) setioparams(&stdioparams[i]); setdefaultbase(10); } const char* basePrefix(char base) { return getioparams(base)->basetag; } static signed char _parsesign( const char** buf) { signed char result; result = IO_SIGN_NONE; if (!_isempty(*buf)) switch (**buf) { case '-': result = IO_SIGN_MINUS; break; case '+': result = IO_SIGN_PLUS; } if (result != IO_SIGN_NONE) (*buf)++; return result; } static signed char _parsebase( const char** buf, char defaultbase) { signed char base; int lg, i; lg = 0; base = IO_BASE_DEFAULT; if (!_isempty(*buf)) for (i = 0; i < idxcount; ++i) { lg = _match(*buf, ioparams[i].basetag); if (lg > 0) { base = ioparams[i].base; break; } } *buf += lg; return base == IO_BASE_DEFAULT? defaultbase : base; } static char _parsecmpl( const char** buf, char base) { int lg; p_ioparams param; param = getioparams(base); lg = 0; if (_isvalidioparams(param)) lg = _match(*buf, param->cmpltag); *buf += lg; return lg > 0; } Error parse( p_itokens tokens, const char** buffer) { p_ioparams params; const char* p; char* expchar; signed char base; int idx; char dot; char* expbegin; char* expend; tokens->fracpart = NULL; tokens->exp = 0; tokens->expsign = IO_SIGN_NONE; tokens->maxdigits = 0; dot = '.'; expbegin = "("; expend = ")"; p = *buffer; tokens->sign = _parsesign(&p); base = _parsebase(&p, _getdefaultbase()); params = getioparams(base); if (params != NULL) { dot = params->dot; if (params->expbegin != NULL) expbegin = params->expbegin; if (params->expend != NULL) expend = params->expend; tokens->maxdigits = params->maxdigits; } else base = 10; tokens->base = base; if (tokens->maxdigits <= 0) tokens->maxdigits = DECPRECISION; if (_parsecmpl(&p, tokens->base)) { if (tokens->sign != IO_SIGN_NONE) return IOInvalidComplement; tokens->sign = IO_SIGN_COMPLEMENT; } tokens->intpart = _scandigits(&p, base); if (*p == dot) { ++p; tokens->fracpart = _scandigits(&p, base); } if (!tokens->intpart && !tokens->fracpart && tokens->sign != IO_SIGN_COMPLEMENT) return IONoSignificand; expchar = strchr(expbegin, *p); if (!_isempty(expchar)) { const char* expptr; int i; int e = 0; signed char expbase; ++p; idx = (int)(expchar - expbegin); tokens->expsign = _parsesign(&p); expbase = _parsebase(&p, base); expptr = _scandigits(&p, expbase); if (!expptr || (*(expend + idx) != ' ' && *(expend + idx) != *p)) return IOBadExp; for (i = 0; i < p-expptr; ++i) { if (!_checkmul(&e, expbase) || !_checkadd(&e, _ascii2digit(*(expptr+i)))) return IOExpOverflow; } tokens->exp = e; } *buffer = p; return Success; } static char _decodesign( signed char s) { switch (s) { case IO_SIGN_PLUS: return '+'; case IO_SIGN_MINUS: return '-'; } return '\0'; } static char* _decodebase( signed char base) { p_ioparams param; param = getioparams(base); if (!_isvalidioparams(param) || _isempty(param->basetag)) return &emptystr; return param->basetag; } static char* _decodecomplement( signed char sign, signed char base) { p_ioparams param; param = getioparams(base); if (sign != IO_SIGN_COMPLEMENT || !_isvalidioparams(param) || _isempty(param->cmpltag)) return &emptystr; return param->cmpltag; } static void _cattoken( char* buf, char* token, char enable) { if (enable && !_isempty(token)) strcat(buf, token); } int cattokens( char* buf, int bufsz, p_otokens tokens, signed char expbase, unsigned flags) { int sz; int fraclg; p_ioparams params; char* expbegin; char* expend; char* cmpltag; char* basetag; char* expbasetag; signed char base; char dot; char cbuf[2]; char printsign; char printbasetag; char printcmpl; char printleading0; char printdot; char printexp; char printexpsign = 0; char printexpbase = 0; char printexpbegin; char printexpend; char exp[BITS_IN_BINEXP+2]; t_buffer expBuf; expBuf.sz = sizeof(exp); expBuf.buf = exp; cbuf[1] = '\0'; fraclg = 0; if (!_isempty(tokens->fracpart.buf)) { fraclg = (int)(strlen(tokens->fracpart.buf) - 1); if ((flags & IO_FLAG_SUPPRESS_TRL_ZERO) != 0) while (fraclg >= 0 && tokens->fracpart.buf[fraclg] == '0') --fraclg; ++fraclg; } params = getioparams(IO_BASE_DEFAULT); base = tokens->base; printbasetag = !_isspecial(base) && (flags & IO_FLAG_SUPPRESS_BASETAG) == 0 && (params == NULL || params->base != base); params = getioparams(base); basetag = _decodebase(base); cmpltag = _decodecomplement(tokens->sign, base); expbasetag = NULL; if (base == IO_BASE_DEFAULT) flags |= IO_FLAG_SUPPRESS_DOT | IO_FLAG_SUPPRESS_LDG_ZERO; if ((flags & IO_FLAG_SHOW_BASE) != 0) printbasetag = 1; printcmpl = tokens->sign == IO_SIGN_COMPLEMENT && (flags & IO_FLAG_SUPPRESS_CMPL) == 0; printsign = !printcmpl && tokens->sign != IO_SIGN_NONE && (tokens->sign != IO_SIGN_PLUS || (flags & IO_FLAG_SUPPRESS_PLUS) == 0); printleading0 = _isempty(tokens->intpart.buf) && (flags & IO_FLAG_SUPPRESS_LDG_ZERO) == 0; printdot = fraclg > 0 || (flags & IO_FLAG_SUPPRESS_DOT) == 0; printexp = base != IO_BASE_NAN && base != IO_BASE_ZERO && ((flags & IO_FLAG_SUPPRESS_EXPZERO) == 0 || tokens->exp != 0); if (printexp) { if (expbase < 2) expbase = params->expbase; expbasetag = _decodebase(expbase); printexpsign = tokens->exp < 0 || (flags & IO_FLAG_SUPPRESS_EXPPLUS) == 0; printexpbase = expbasetag != NULL && (flags & IO_FLAG_SUPPRESS_EXPBASE) == 0 && (_isempty(basetag) || strcmp(basetag, expbasetag) != 0); if ((flags & IO_FLAG_SHOW_EXPBASE) != 0) printexpbase = 1; } dot = '.'; expbegin = "("; expend = ")"; if (params != NULL) { dot = params->dot; expbegin = params->expbegin; expend = params->expend; } printexpbegin = *expbegin != '\0'; printexpend = *expend != '\0' && *expend != ' '; sz = 1; if (printsign) sz += 1; if (printbasetag) sz = (int)(sz + strlen(basetag)); if (printcmpl) sz = (int)(sz + strlen(cmpltag)); if (printleading0) ++sz; if (!_isempty(tokens->intpart.buf)) sz = (int)(sz + strlen(tokens->intpart.buf)); if (printdot) sz += 1; sz += fraclg; if (printexp) { exp2str(&expBuf, tokens->exp, expbase); if (printexpbegin) ++sz; if (printexpsign) sz += 1; if (printexpbase) sz = (int)(sz + strlen(expbasetag)); sz = (int)(sz + strlen(expBuf.buf)); if (printexpend) ++sz; } if (sz <= bufsz) { *buf = '\0'; cbuf[0] = _decodesign(tokens->sign); _cattoken(buf, cbuf, printsign); _cattoken(buf, basetag, printbasetag); _cattoken(buf, cmpltag, printcmpl); _cattoken(buf, "0", printleading0); _cattoken(buf, tokens->intpart.buf, 1); cbuf[0] = dot; _cattoken(buf, cbuf, printdot); if (fraclg > 0) strncat(buf, tokens->fracpart.buf, fraclg); if (printexp) { cbuf[0] = *expbegin; _cattoken(buf, cbuf, printexpbegin); cbuf[0] = _decodesign(tokens->exp < 0? -1:1); _cattoken(buf, cbuf, printexpsign); _cattoken(buf, expbasetag, printexpbase); strcat(buf, expBuf.buf); cbuf[0] = *expend; _cattoken(buf, cbuf, printexpend); } } return sz; } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatio.h000066400000000000000000000114201526573132500245060ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include #ifndef FLOATIO_H # define FLOATIO_H #define NO_DIGIT 0x7F #define IO_BASE_ZERO 1 #define IO_BASE_NAN 0 #define IO_BASE_DEFAULT (-1) #define IO_SIGN_PLUS 1 #define IO_SIGN_NONE 0 #define IO_SIGN_MINUS (-1) #define IO_SIGN_COMPLEMENT (-2) #define IO_FLAG_SUPPRESS_PLUS 0x001 #define IO_FLAG_SUPPRESS_BASETAG 0x002 #define IO_FLAG_SUPPRESS_CMPL 0x004 #define IO_FLAG_SUPPRESS_LDG_ZERO 0x008 #define IO_FLAG_SUPPRESS_TRL_ZERO 0x010 #define IO_FLAG_SUPPRESS_DOT 0x020 #define IO_FLAG_SUPPRESS_EXPPLUS 0x040 #define IO_FLAG_SUPPRESS_EXPBASE 0x080 #define IO_FLAG_SUPPRESS_EXPZERO 0x100 #define IO_FLAG_SHOW_BASE 0x200 #define IO_FLAG_SHOW_EXPBASE 0x400 #ifdef __cplusplus extern "C"{ #endif typedef struct{ int sz; char* buf; }t_buffer; typedef t_buffer* p_buffer; /* t_seq_desc describes the format of a sequence of digits. leadingSignDigits are the count of leading zeros (or for two's complement, F's, 7's or 1's), trailing0 are the number of zeros at the end of the sequence and digits are the total count of digits in the sequence. If a sequence contains only zeros, in some contexts, they are counted as sign digits, in others they are trailing zeros. base is the number base the sequence is coded in (one of 2, 8, 10 or 16) and is reserved for callback. */ typedef struct{ int leadingSignDigits; int trailing0; int digits; int base; void* param; } t_seq_desc; typedef t_seq_desc* p_seq_desc; /* the number of digits not being a leading sign digit or a trailing zero */ int _significantdigits(p_seq_desc n); /* sequences of digits can be encoded in various ways (ASCII, bc_num style, packed and so on). In order to access a single digit, a getter has to be supplied for each encoding. This is the common interface of these getters. ofs is the index of the digit in the sequence, the first (most significant) having an index 0. The getter should return a sign digit (mostly 0) for negative indices and 0 for indices greator or equal to the length of the sequence. Instances of t_getdigit usually access the param field of n to find the data structure where the digits are encoded in */ typedef char (*t_getdigit)(int ofs, p_seq_desc param); /* list of tokens that are created in an output process. Instead of returning a single ASCII string, all parts of a number are kept in separate places, so a post-processor can reorder or beautify them */ typedef struct{ signed char sign; signed char base; t_buffer intpart; t_buffer fracpart; int exp; } t_otokens; typedef t_otokens* p_otokens; /* list of tokens that are sources in an input process. Instead of using a single ASCII string, all parts of a number are kept in separate places, stripped off all grammar related information. The tokens need not be 0 terminated, as long as the token is delimited by something not mistaken as a part of it. */ typedef struct{ signed char sign; signed char base; const char* intpart; const char* fracpart; signed char expsign; unsigned exp; unsigned maxdigits; } t_itokens; typedef t_itokens* p_itokens; typedef struct{ t_seq_desc seq; t_getdigit getdigit; } t_ext_seq_desc; typedef t_ext_seq_desc* p_ext_seq_desc; typedef struct{ signed char sign; signed char base; } t_prefix; typedef t_prefix* p_prefix; typedef struct{ t_prefix prefix; t_ext_seq_desc intpart; t_ext_seq_desc fracpart; int exp; } t_number_desc; typedef t_number_desc* p_number_desc; void _clearnumber(p_number_desc n); Error str2desc(p_number_desc n, p_itokens tokens); Error desc2str(p_otokens tokens, p_number_desc n, int scale); Error exp2str(p_buffer dest, int exp, char base); /*------------ additional stuff ------------------*/ /* t_ioparams is a data structure that contains all necessary information to convert an ASCII character encoded number into a t_token and vice versa. Most information is grammar related like dot, basetag and so on. Others like maxdigits describe general limits of floatnums. */ typedef struct{ signed char base; signed char expbase; char dot; char* basetag; char* expbegin; char* expend; char* cmpltag; unsigned maxdigits; } t_ioparams; typedef t_ioparams* p_ioparams; const char* basePrefix(char base); Error parse(p_itokens tokens, const char** buf); int cattokens(char* buf, int bufsz, p_otokens tokens, signed char expbase, unsigned flags); void float_stdconvert(void); char setioparams(p_ioparams params); char delioparams(signed char base); p_ioparams getioparams(signed char base); signed char setdefaultbase(signed char base); #ifdef __cplusplus } #endif #endif /* FLOATIO_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatipower.c000066400000000000000000000044621526573132500254070ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatipower.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlong.h" /* for radix conversion, we need to get a result, even though it might slightly overflow or underflow. That is why we keep the exponent separate. For limited exponents (< 1024) the relative error for a 100 digit calculation is < 1e-99 x != 0 */ char _raiseposi( floatnum x, int* expx, unsigned exponent, int digits) { int exppwr, extra; floatstruct pwr; float_create(&pwr); float_move(&pwr, x); exppwr = float_getexponent(&pwr); float_setexponent(&pwr, 0); if ((exponent & 1) != 0) { float_copy(x, &pwr, digits+1); *expx = exppwr; } else { float_copy(x, &c1, EXACT); *expx = 0; } extra = _findfirstbit(exponent)/3+1; while((exponent >>= 1) != 0) { float_mul(&pwr, &pwr, &pwr, digits+extra); if (!_checkadd(&exppwr, exppwr)) break; exppwr += float_getexponent(&pwr); float_setexponent(&pwr, 0); if((exponent & 1) != 0) { float_mul(x, x, &pwr, digits+extra); *expx += exppwr + float_getexponent(x); float_setexponent(x, 0); } } float_free(&pwr); return exponent == 0; } char _raiseposi_( floatnum x, unsigned exponent, int digits) { int exp; char result; result = _raiseposi(x, &exp, exponent, digits); float_setexponent(x, exp); return result; } /* raises a non-zero x to the exponent-th power */ char _raisei( floatnum x, int exponent, int digits) { int expx; signed char sgn; char negexp; switch (exponent) { case 0: float_copy(x, &c1, EXACT); /* fall through */ case 1: return 1; } if (float_getlength(x) == 1 && float_getdigit(x, 0) == 1) { /* power of ten */ if (!_checkmul(&exponent, float_getexponent(x)) || exponent < EXPMIN || exponent > EXPMAX) return 0; sgn = float_getsign(x) < 0? -(exponent & 1) : 1; float_setexponent(x, exponent); float_setsign(x, sgn); return 1; } negexp = exponent < 0; if (negexp) exponent = -exponent; if (!_raiseposi(x, &expx, exponent, digits) || expx < EXPMIN || expx > EXPMAX) return 0; float_setexponent(x, expx); return negexp? float_reciprocal(x, digits) : 1; } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatipower.h000066400000000000000000000007031526573132500254060ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATIPOWER_H # define FLOATIPOWER_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _raiseposi_(floatnum x, unsigned exponent, int digits); char _raiseposi(floatnum x, int* expx, unsigned exponent, int digits); char _raisei(floatnum x, int exponent, int digits); #ifdef __cplusplus } #endif #endif /* FLOATIPOWER_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatlog.c000066400000000000000000000264461526573132500246710ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatlog.h" #include "floatconst.h" #include "floatcommon.h" #include "floatseries.h" typedef struct { char c2; char c3; char c5; char c7; char c10; } _lincomb; static _lincomb _lincombtbl[] = { {0,3,3,2,5},{12,4,0,2,7},{4,0,0,0,1},{0,2,2,1,3},{13,3,0,1,6}, /* -.40 */ {7,5,0,2,6},{10,1,0,2,5},{4,3,0,3,5},{1,6,0,0,3},{4,2,0,0,2}, /* -.35 */ {0,4,2,1,4},{1,0,0,1,1},{0,9,0,1,5},{3,5,0,1,4},{6,1,0,1,3}, /* -.30 */ {0,3,0,2,3},{8,6,0,1,6},{11,2,0,1,5},{0,6,2,1,5},{22,1,0,0,7}, /* -.25 */ {9,5,0,0,5},{0,0,2,2,3},{0,5,1,0,3},{2,1,0,0,1},{0,3,4,1,5}, /* -.20 */ {0,1,8,0,6},{0,3,3,3,6},{5,6,0,2,6},{8,2,0,2,5},{0,13,0,1,7}, /* -.15 */ {12,3,0,0,5},{0,7,1,0,4},{0,2,1,4,5},{0,7,0,2,5},{3,3,0,2,4}, /* -.10 */ {20,0,0,0,6},{7,4,0,0,4},{10,0,0,0,3},{8,4,0,2,6},{0,0,0,0,0}, /* -.05 */ {0,0,0,0,0},{0,9,1,0,5},{13,5,0,2,8},{9,3,0,1,5},{0,7,4,1,7}, /* 0.00 */ {10,3,0,3,7},{0,1,5,0,4},{0,12,2,1,8},{10,2,0,0,4},{8,6,0,2,7},/* 0.05 */ {8,1,0,6,8},{7,0,0,1,3},{5,4,0,3,6},{22,1,0,1,8},{2,7,0,0,4}, /* 0.10 */ {2,2,0,4,5},{0,0,2,3,4},{0,5,1,1,4},{0,3,5,0,5},{14,6,0,1,8}, /* 0.15 */ {10,4,0,0,5},{3,1,0,3,4},{4,6,0,1,5},{0,4,0,0,2},{14,0,0,2,6}, /* 0.20 */ {0,13,1,0,7},{8,2,0,3,6},{4,0,0,2,3},{2,4,0,4,6},{0,2,2,3,5}, /* 0.25 */ {0,0,6,2,6},{0,5,5,0,6},{23,2,0,0,8},{0,1,2,0,2},{17,4,0,1,8}, /* 0.30 */ {0,10,3,0,7},{11,6,0,2,8},{4,3,0,5,7},{14,2,0,2,7},{10,0,0,1,4},/* 0.35 */ {8,4,0,3,7},{1,1,0,6,6},{11,0,0,3,6},{12,5,0,1,7},{2,1,0,8,8}, /* 0.40 */ {15,1,0,1,6},{0,7,5,0,7},{6,2,0,6,8},{2,0,0,5,5},{1,14,0,1,8}, /* 0.45 */ {0,12,3,0,8},{20,2,0,1,8},{0,8,0,0,4},{14,4,0,2,8},{3,4,0,0,3},/* 0.50 */ {0,1,4,3,6},{6,0,0,0,2},{4,4,0,2,5},{0,2,0,1,2},{8,0,1,2,5}, /* 0.55 */ {8,5,0,0,5},{15,3,0,1,7},{0,9,5,0,8},{0,0,3,2,4},{0,5,2,0,4}, /* 0.60 */ {5,3,0,1,4},{0,0,2,4,5},{13,6,0,0,7},{3,2,0,7,8},{16,2,0,0,6}, /* 0.65 */ {0,1,9,0,7},{3,6,0,0,4},{10,4,0,1,6},{0,0,0,8,7},{13,0,0,1,5}, /* 0.70 */ {0,6,7,0,8},{0,4,0,1,3},{0,2,4,0,4},{3,0,0,1,2},{15,5,0,1,8}, /* 0.75 */ {8,2,0,4,7},{2,9,0,1,6},{4,0,0,3,4},{2,4,0,5,7},{12,3,0,2,7}, /* 0.80 */ {1,3,0,0,2},{0,0,6,3,7},{6,5,0,3,7},{16,4,0,0,7},{0,3,9,0,8}, /* 0.85 */ {0,1,2,1,3},{10,6,0,1,7},{0,2,0,8,8},{0,10,3,1,8},{0,1,1,3,4}, /* 0.90 */ {9,0,0,0,3},{4,3,0,6,8},{0,4,4,0,5},{8,9,0,0,7},{10,0,0,2,5} /* 0.95 */ }; /* artanh x and ln(x+1) are closely related. Evaluate the logarithm using the artanh series, which converges twice as fast as the logarithm series. With 100 digits, if -0.0198 <= x <= 0.02, the relative error is less than 5.0e-100, or at most 1 unit in the 100th place */ void _lnxplus1near0( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, &c2, x, digits); float_div(x, x, &tmp, digits); artanhnear0(x, digits); float_add(x, x, x, EXACT); float_free(&tmp); } /* helpers */ static void _addcoef( floatnum x, int coef, floatnum cnst, int digits) { floatstruct tmp; if (coef != 0) { float_create(&tmp); float_muli(&tmp, cnst, coef, digits); float_add(x, x, &tmp, digits); float_free(&tmp); } } static int _factor( int idx) { int factor; int i; factor = 1; for (i = _lincombtbl[idx].c2; --i >= 0;) factor *= 2; for (i = _lincombtbl[idx].c3; --i >= 0;) factor *= 3; for (i = _lincombtbl[idx].c5; --i >= 0;) factor *= 5; for (i = _lincombtbl[idx].c7; --i >= 0;) factor *= 7; return factor; } static void _lnguess( floatnum dest, int digits, int idx) { _addcoef(dest, _lincombtbl[idx].c2-_lincombtbl[idx].c5, &cLn2, digits); _addcoef(dest, _lincombtbl[idx].c3, &cLn3, digits); _addcoef(dest, _lincombtbl[idx].c7, &cLn7, digits); _addcoef(dest, _lincombtbl[idx].c5-_lincombtbl[idx].c10, &cLn10, digits); } /* reduces x using a special factor whose prime factors are 2, 3, 5 and 7 only. x is multiplied by this factor, yielding a value near a power of ten. Then x is divided by this power of ten. The logarithm of this factor is returned in lnguess. Valid for -0.4 <= x < 1. Relative error < 5e-100 for 100 digit result. This algorithm reduces x to a value < 0.01, which is appropriately small for submitting to a series evaluation */ void _lnreduce( floatnum x, floatnum lnguess, int digits) { floatstruct tmp1, tmp2; int idx; int expx; signed char pos; float_setzero(lnguess); expx = float_getexponent(x); if (expx < -2) return; float_create(&tmp1); float_create(&tmp2); idx = leadingdigits(x, 3 + expx) + 39; if (idx < 0) idx = 0; pos = idx >= 40? 1 : 0; idx += pos; float_setinteger(&tmp1, _factor(idx)); float_setexponent(&tmp1, -pos); float_sub(&tmp1, &tmp1, &c1, EXACT); float_mul(&tmp2, x, &tmp1, digits); float_add(&tmp1, &tmp1, &tmp2, digits+1); float_add(x, x, &tmp1, digits); _lnguess(lnguess, digits+4, idx); float_free(&tmp1); float_free(&tmp2); return; } /* for -0.4 <= x < 1.0 */ void _lnxplus1lt1( floatnum x, int digits) { floatstruct lnfactor; float_create(&lnfactor); _lnreduce(x, &lnfactor, digits); _lnxplus1near0(x, digits); float_sub(x, x, &lnfactor, digits+1); float_free(&lnfactor); } /* the general purpose routine evaluating ln(x) for all positive arguments. It uses multiplication and division to reduce the argument to a value near 1. The factors are always small, so these operations do not take much time. -- One often sees an argument reduction by taking the square root several times in succession. But the square root is slow in number.c, so we avoid it best. -- Super-fast algorithm like the AGM based ones, do not pay off for limited lengths because of the same reason: They require taking square roots several times. A test showed, a hundred digits calculation using AGM is 8 times slower than the algorithm here. For extreme precision, of course, AGM will be superior. The relative error seems to be less than 7e-101 for 100-digits computations */ void _ln( floatnum x, int digits) { floatstruct tmp; int coef10; char coef3; char dgt; float_create(&tmp); coef10 = float_getexponent(x); /* reducing the significand to 0.6 <= x < 2 by simple multiplication */ dgt = (char)leadingdigits(x, 1); coef3 = 0; if (dgt == 1) float_setexponent(x, 0); else { ++coef10; float_setexponent(x, - 1); coef3 = (dgt < 6); if (coef3) float_mul(x, x, &c3, digits+1); } float_sub(x, x, &c1, digits+1); _lnxplus1lt1(x, digits); if (coef10 != 0) { float_muli(&tmp, &cLn10, coef10, digits+1); float_add(x, x, &tmp, digits+1); } if (coef3) float_sub(x, x, &cLn3, digits); float_free(&tmp); } void _lnxplus1( floatnum x, int digits) { if (float_cmp(x, &cMinus0_4) >= 0 && float_cmp(x, &c1) < 0) _lnxplus1lt1(x, digits); else { float_add(x, x, &c1, digits+1); _ln(x, digits); } } /* The artanh function has a pole at x == 1. For values close to 1 the general purpose evaluation is too unstable. We use a dedicated algorithm here to get around the problems. Avoid using this function for values of x > 0.5, _artanh is the better choice then. Values near the other pole of artanh at -1 can be derived from this function using artanh(-1+x) = -artanh(1-x). For x < 0.5 and a 100-digit computation, the maximum relative error is in the order of 1e-99 */ void _artanh1minusx( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_sub(&tmp, &c2, x, digits); float_div(x, &tmp, x, digits); _ln(x, digits); float_mul(x, x, &c1Div2, digits); float_free(&tmp); } /* designed for |x| <= 0.5. The evaluation is not symmetric with respect to 0, i.e. it might be -artanh x != artanh -x. The difference is in the order of the last digit, of course. Evaluation of positive values yield a slightly better relative error than that of negative values. The maximum relative error is the maximum of that of artanhnear0 and 1e-99 */ void _artanhlt0_5( floatnum x, int digits) { floatstruct tmp; if (float_getexponent(x) < -2 || float_iszero(x)) artanhnear0(x, digits); else { float_create(&tmp); float_sub(&tmp, &c1, x, digits+1); float_add(x, x, x, digits); float_div(x, x, &tmp, digits); _lnxplus1(x, digits); float_mul(x, x, &c1Div2, digits); float_free(&tmp); } } /* the general purpose routine for evaluating artanh. The evaluation is symmetric with respect to 0, i.e. it is always -artanh(x) == artanh -x. Valid for |x| < 1, but unstable for |x| approx. == 1 */ void _artanh( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) <= 0) _artanhlt0_5(x, digits); else { float_sub(x, &c1, x, digits+1); _artanh1minusx(x, digits); } float_setsign(x, sgn); } /* evaluates ln(2*x), the asymptotic function of arsinh and arcosh for large x */ static void _ln2x( floatnum x, int digits) { _ln(x, digits); float_add(x, &cLn2, x, digits); } /* valid for all x. The relative error is less than 1e-99. The evaluation is symmetric with respect to 0: arsinh -x == - arsinh x */ void _arsinh( floatnum x, int digits) { floatstruct tmp; int expxsqr; signed char sgn; expxsqr = 2*float_getexponent(x)+2; /* for extreme small x, sqrt(1+x*x) is approx == 1 + x*x/2 - x^4/8, so arsinh x == ln(1 + x + x*x/2 - x^4/8 +...) approx == x - x*x*x/6 + ... If we approximate arsinh x by x, the relative error is roughly |x*x/6|. This is less than acceptable 10^(-), if log(x*x) < - */ if (expxsqr < -digits || float_iszero(x)) return; float_create(&tmp); /* arsinh -x = -arsinh x, so we can derive the arsinh for negative arguments from that of positive arguments */ sgn = float_getsign(x); float_abs(x); if (expxsqr-2 > digits) /* for very large x, use the asymptotic formula ln(2*x) */ _ln2x(x, digits); else { float_mul(&tmp, x, x, digits + (expxsqr>=0? 0 : expxsqr)); float_add(&tmp, &tmp, &c1, digits+1); float_sqrt(&tmp, digits); if (float_getexponent(x) < 0) { /* for small x, use arsinh x == artanh (x/sqrt(1+x*x)). Stable for x < 1, but not for large x*/ float_div(x, x, &tmp, digits); _artanh(x, digits+1); } else { /* arsinh x = ln(x+sqrt(1+x*x)), stable for x >= 1, but not for small x */ float_add(x, x, &tmp, digits); _ln(x, digits); } } float_setsign(x, sgn); float_free(&tmp); } /* arcosh(x+1), x >= 0, is the stable variant of arcosh(x), x >= 1. The relative error is less than 1e-99. */ void _arcoshxplus1( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); if (2*float_getexponent(x) > digits) { /* for very large x, use the asymptotic formula ln(2*(x+1)) */ float_add(x, x, &c1, digits+1); _ln2x(x, digits); } else { /* arcosh(x+1) = ln(1+(x+sqrt(x*(x+2)))), stable for all positive x, except for extreme large x, where x*(x+2) might overflow */ /* get sinh(arcosh (1+x)) = sqrt(x*(x+2)) */ float_add(&tmp, x, &c2, digits); float_mul(&tmp, x, &tmp, digits); float_sqrt(&tmp, digits); float_add(x, x, &tmp, digits); _lnxplus1(x, digits); } float_free(&tmp); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatlog.h000066400000000000000000000012561526573132500246660ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATLOG_H # define FLOATLOG_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif void _lnxplus1near0(floatnum x, int digits); void _lnreduce(floatnum x, floatnum lnguess, int digits); void _lnxplus1lt1(floatnum x, int digits); void _ln(floatnum x, int digits); void _lnxplus1(floatnum x, int digits); void _artanh1minusx(floatnum x, int digits); void _artanhlt0_5(floatnum x, int digits); void _artanh(floatnum x, int digits); void _arsinh(floatnum x, int digits); void _arcoshxplus1(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /* FLOATLOG_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatlogic.c000066400000000000000000000076471526573132500252070ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatlogic.h" #include "floatconst.h" #define MAXIDX ((LOGICRANGE-1) / BITS_IN_UNSIGNED) #define SIGNBIT (LOGICRANGE - 1 - MAXIDX * BITS_IN_UNSIGNED) static void _zeroextend( t_longint* longint) { int idx; idx = longint->length - 1; for (; ++idx <= (int)MAXIDX;) longint->value[idx] = 0; } signed char _signof( t_longint* longint) { return (longint->value[MAXIDX] & (1 << SIGNBIT)) != 0? -1:1; } static char _signextend( t_longint* longint) { unsigned mask; signed char sign; sign = _signof(longint); // Make sure to perform bitwise operations on an unsigned type. mask = (~0u) << SIGNBIT; if (sign < 0) longint->value[MAXIDX] |= mask; else longint->value[MAXIDX] &= ~mask; return sign; } static void _neg( t_longint* longint) { int idx = -1; const int maxidx = MAXIDX; while (++idx <= maxidx && longint->value[idx] == 0); if (idx <= maxidx) longint->value[idx] = 0u - longint->value[idx]; while (++idx <= maxidx) longint->value[idx] = ~longint->value[idx]; } char _floatnum2logic( t_longint* longint, cfloatnum x) { floatstruct tmp; int digits; digits = float_getexponent(x)+1; if (float_iszero(x) || digits <= 0) { longint->length = 1; longint->value[0] = 0; } else { if (digits > MATHPRECISION) return 0; float_create(&tmp); /* floatnum2longint rounds, we have to truncate first */ float_copy(&tmp, x, digits); if (float_getsign(x) < 0) float_add(&tmp, &tmp, &c1, EXACT); _floatnum2longint(longint, &tmp); float_free(&tmp); if (_bitlength(longint) > LOGICRANGE) return 0; } _zeroextend(longint); if (float_getsign(x) < 0) _not(longint); return 1; } void _logic2floatnum( floatnum f, t_longint* longint) { int idx; signed char sign; sign = _signextend(longint); if (sign < 0) _neg(longint); idx = MAXIDX; while (idx >= 0 && longint->value[idx] == 0) --idx; if (idx < 0) longint->length = 0; else longint->length = idx + 1; _longint2floatnum(f, longint); float_setsign(f, sign); } void _not( t_longint* longint) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) longint->value[idx] = ~(longint->value[idx]); } void _and( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] & x2->value[idx]; } void _or( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] | x2->value[idx]; } void _xor( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] ^ x2->value[idx]; } void _shr( t_longint* x, unsigned shift) { int idx; const unsigned sign = _signof(x) < 0? ~0 : 0; const int moves = shift/BITS_IN_UNSIGNED; const int maxidx = MAXIDX; if (moves > 0) { shift -= moves * BITS_IN_UNSIGNED; for (idx = moves-1; ++idx <= maxidx;) x->value[idx-moves] = x->value[idx]; idx = MAXIDX - moves + 1; if (idx < 0) idx = 0; for (; idx <= maxidx; ++idx) x->value[idx] = sign; } if (shift > 0) { for (idx = -1; ++idx < maxidx;) x->value[idx] = _longshr(x->value[idx], x->value[idx+1], (char)shift); x->value[MAXIDX] = _longshr(x->value[MAXIDX], sign, (char)shift); } } void _shl( t_longint* x, unsigned shift) { int moves, idx; moves = shift/BITS_IN_UNSIGNED; if (moves > 0) { shift -= moves * BITS_IN_UNSIGNED; for (idx = MAXIDX; idx >= moves; --idx) x->value[idx] = x->value[idx-moves]; if (moves > (int)MAXIDX) moves = MAXIDX+1; for (idx = -1; ++idx < moves;) x->value[idx] = 0; } if (shift > 0) { for (idx = MAXIDX; idx > 0; --idx) x->value[idx] = _longshl(x->value[idx-1], x->value[idx], (char)shift); x->value[0] <<= shift; } } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatlogic.h000066400000000000000000000012031526573132500251720ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATLOGIC_H # define FLOATLOGIC_H #include "floatconvert.h" #ifdef __cplusplus extern "C" { #endif char _canconvert(cfloatnum x); char _floatnum2logic(t_longint* longint, cfloatnum x); void _logic2floatnum(floatnum f, t_longint* longint); void _not(t_longint* longint); void _and(t_longint* x1, t_longint* x2); void _or(t_longint* x1, t_longint* x2); void _xor(t_longint* x1, t_longint* x2); void _shr(t_longint* x, unsigned shift); void _shl(t_longint* x, unsigned shift); #ifdef __cplusplus } #endif #endif /* FLOATLOGIC_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatlong.c000066400000000000000000000121441526573132500250350ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatlong.h" #define HALFSIZE (sizeof(unsigned) * 4) #define LOWMASK ((1u << HALFSIZE) - 1u) #define MSB (1u << (2*HALFSIZE-1)) /*************** functions handling a single unsigned ********************/ int _findfirstbit( unsigned value) { int result; result = -1; while (value != 0) { value >>= 1; ++result; } return result; } /* pre: value != 0 */ static int _revfindfirstbit( unsigned value) { int result; result = 0; while ((value & 1) == 0) { value >>= 1; ++result; } return result; } /******************* double unsigned functions ********************/ static void _longsplit( unsigned value, unsigned* low, unsigned* high) { *high = value >> HALFSIZE; *low = value & LOWMASK; } static unsigned _longcat( unsigned low, unsigned high) { return (high << HALFSIZE) + low; } char _longadd( unsigned* s1, unsigned* s2) { unsigned s1h, s1l, s2h, s2l; _longsplit(*s1, &s1l, &s1h); _longsplit(*s2, &s2l, &s2h); s1l += s2l; _longsplit(s1l, &s1l, &s2l); s1h += s2h + s2l; _longsplit(s1h, &s1h, s2); *s1 = _longcat(s1l, s1h); return *s2 == 0; } char _longmul( unsigned* f1, unsigned* f2) { unsigned f1h, f1l, f2h, f2l; _longsplit(*f1, &f1l, &f1h); _longsplit(*f2, &f2l, &f2h); *f1 = f1l * f2l; *f2 = f1h * f2h; f1l *= f2h; f2l *= f1h; _longadd(&f1l, &f2l); _longsplit(f1l, &f1l, &f1h); f1l <<= HALFSIZE; _longadd(f1, &f1l); *f2 += f1l + (f2l << HALFSIZE) + f1h; return *f2 == 0; } unsigned _longshr( unsigned low, unsigned high, char shift) { if (shift == 0) return low; return (low >> shift) | (high << ((2*HALFSIZE)-shift)); } unsigned _longshl( unsigned low, unsigned high, char shift) { if (shift == 0) return high; return (low >> ((2*HALFSIZE)-shift)) | (high << shift); } /***************** unsigned array functions *****************/ unsigned _longarrayadd( unsigned* uarray, int lg, unsigned incr) { for(; lg-- > 0 && incr != 0;) _longadd(uarray++, &incr); return incr; } unsigned _longarraymul( unsigned* uarray, int lg, unsigned factor) { unsigned ovfl, carry; carry = 0; ovfl = 0; for (; lg-- > 0;) { carry += ovfl; ovfl = factor; _longmul(uarray, &ovfl); _longadd(uarray++, &carry); } return carry + ovfl; } unsigned _bitsubstr( unsigned* uarray, int ofs) { int idx; if (ofs <= 0) return *uarray << -ofs; idx = ofs / BITS_IN_UNSIGNED; return _longshr(*(uarray+idx), *(uarray+idx+1), (char)(ofs - idx * BITS_IN_UNSIGNED)); } void _orsubstr( unsigned* uarray, int bitofs, unsigned value) { int idx; int ofs; idx = bitofs / BITS_IN_UNSIGNED; ofs = bitofs - idx * BITS_IN_UNSIGNED; if (ofs == 0) *(uarray + idx) |= value; else { *(uarray + idx) |= value << ofs; *(uarray + idx + 1) |= value >> (BITS_IN_UNSIGNED - ofs); } } /**************** longint functions ****************/ char _isfull( t_longint* l) { return l->length >= (int)UARRAYLG - 1; } unsigned _bitlength( t_longint* l) { if (l->length == 0) return 0; return (l->length - 1) * BITS_IN_UNSIGNED + _findfirstbit(l->value[l->length-1]) + 1; } unsigned _lastnonzerobit( t_longint* l) { int i; if (l->length == 0) return ~0u; i = -1; for (; ++i < l->length && l->value[i] == 0;); return i * BITS_IN_UNSIGNED + _revfindfirstbit(l->value[i]); } unsigned _longintadd( t_longint* l, unsigned summand) { unsigned ovfl; ovfl = _longarrayadd(l->value, l->length, summand); if (ovfl != 0 && !_isfull(l)) { l->value[l->length] = ovfl; ++l->length; ovfl = 0; } return ovfl; } unsigned _longintmul( t_longint* l, unsigned factor) { unsigned ovfl; ovfl = _longarraymul(l->value, l->length, factor); if (ovfl != 0 && !_isfull(l)) { l->value[l->length] = ovfl; ++l->length; ovfl = 0; } return ovfl; } char _longintsetsize( t_longint* l, unsigned bitlength) { int i; if (bitlength == 0) l->length = 0; else l->length = (bitlength - 1) / BITS_IN_UNSIGNED + 1; if (l->length >= (int)UARRAYLG) return 0; for(i = l->length; i >= 0; --i) l->value[i] = 0; return 1; } /**************** overflow checking integer functions *************/ char _checkadd( int* s1, int s2) { unsigned u1, u2; if ((*s1 < 0) ^ (s2 < 0)) { /* you can always add summands of opposite sign */ *s1 += s2; return 1; } if (s2 < 0) { u1 = -*s1; u2 = -s2; _longadd(&u1, &u2); *s1 = -(int)u1; return u2 == 0 && *s1 < 0; } u1 = *s1; u2 = s2; _longadd(&u1, &u2); *s1 = u1; return *s1 >= 0; } char _checkmul( int* f1, int f2) { unsigned x1, x2; signed char sgn = 1; const unsigned msb = MSB; if (*f1 >= 0) x1 = *f1; else { sgn = -1; x1 = -*f1; } if (f2 >= 0) x2 = f2; else { sgn = -sgn; x2 = -f2; } _longmul(&x1, &x2); if (sgn < 0) { *f1 = -(int)x1; return (x2 == 0 && x1 <= msb); } *f1 = (int)x1; return (x2 == 0 && x1 < msb); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatlong.h000066400000000000000000000025411526573132500250420ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATLONG_H # define FLOATLONG_H #include "floatconfig.h" #ifdef __cplusplus extern "C" { #endif #define BITS_IN_UNSIGNED (sizeof(unsigned)*8) /* one unsigned extra, so that _bitsubstr() does not access parts outside of t_uarray */ #define UARRAYLG ((8305*(MATHPRECISION+5) + 1)/20000/sizeof(unsigned) + 2) typedef unsigned t_uarray[UARRAYLG]; typedef struct{ int length; t_uarray value; } t_longint; int _findfirstbit(unsigned value); char _longadd(unsigned* s1, unsigned* s2); char _longmul(unsigned* f1, unsigned* f2); char _checkadd(int* s1, int s2); char _checkmul(int* f1, int f2); unsigned _longshr(unsigned low, unsigned high, char shift); unsigned _longshl(unsigned low, unsigned high, char shift); unsigned _longarrayadd(unsigned* uarray, int lg, unsigned incr); unsigned _longarraymul(unsigned* uarray, int lg, unsigned factor); void _orsubstr(unsigned* uarray, int bitofs, unsigned value); unsigned _bitsubstr(unsigned* uarray, int ofs); unsigned _bitlength(t_longint* l); unsigned _lastnonzerobit(t_longint* l); char _longintsetsize(t_longint* l, unsigned bitlength); unsigned _longintadd(t_longint* l, unsigned summand); unsigned _longintmul(t_longint* l, unsigned factor); #ifdef __cplusplus } #endif #endif /* FLOATLONG_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatnum.c000066400000000000000000001161471526573132500247050ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later /* a floating point engine based on bc's decimal fix point arithmetic. The speed is not overwhelming, but sufficient for calculators with limited demands. As bc's number.c is a portable engine, this should be portable as well. */ #include "floatnum.h" #include "floatlong.h" #include #include #define NOSPECIALVALUE 1 int maxdigits = MAXDIGITS; Error float_error; int expmax = EXPMAX; int expmin = EXPMIN; /* general helper routines */ static int _max(int x, int y) { return x > y? x : y; } static int _min(int x, int y) { return x < y? x : y; } /* the return value points to the first character different from accept. */ const char* _memskip( const char* buf, const char* end, char accept) { for(--buf; ++buf != end && *buf == accept;); return buf; } /* scans a value in a bc-num (or part of it) for the first occurence of a digit *different* from . The scan is limited to bytes. Returns the offset of the matching byte, or , if none was found */ static int _scan_digit( const char*p, int count, char digit) { const char* ps; ps = p; for (; count-- > 0 && *p == digit; ++p); return (int)(p - ps); } /* bc_num primitives */ #define _scaleof(f) (f->significand->n_scale) #define _lenof(f) (f->significand->n_len) #define _valueof(f) (f->significand->n_value) #define _digit(f, offset) (*(_valueof(f) + offset)) #define _setscale(f, value) (_scaleof(f) = value) /* converts floatnum's sign encodings (+1, -1) to bc_num sign encoding (PLUS, MINUS) */ static void _setsign( floatnum f, signed char value) { f->significand->n_sign = value < 0? MINUS : PLUS; #ifdef FLOATDEBUG f->value[0] = value < 0? '-' : '+'; #endif } /* modifies a bc_num significand such that the last (existing) digits of its value are not visible to bc_num operations any more. A negative reverts this operation (unhide). pre: <= n_scale*/ static void _hidelast( floatnum f, int count) { f->significand->n_scale -= count; } /* modifies a bc_num significand such that the first (existing) digits of its value are not visible to bc_num operations any more. A negative reverts this operation (unhide). pre: <= n_scale*/ static void _hidefirst( floatnum f, int count) { f->significand->n_value += count; f->significand->n_scale -= count; } /* Usually, significands are normalized, which means they fulfill 1 <= x < 10. This operation moves the decimal point places to the right, effectively multiplying the significand by a power of 10. A negative reverts such an operation. pre: < n_scale */ static void _movepoint( floatnum f, int digits) { f->significand->n_len += digits; f->significand->n_scale -= digits; } /* floatstruct primitives */ /* a quick check for NaN and 0 */ static char _is_special( cfloatnum f) { return f->significand == NULL; } /* creates a shallow working copy of in , using b as a container for the significand. On return, is equal in value to . may then be modified freely in the course of an operation, without effecting source, *except* that the digits in *(dest->significand->n_value) have to be retained (or restored). must *never* be the destination of a float_xxx operation, in particiular, it must not be freed. Neither must b be modified (or freed) in a bc_num operation */ static void _copyfn( floatnum dest, cfloatnum source, bc_num b) { *dest = *source; if (!_is_special(source)) { *b = *(source->significand); b->n_ptr = 0; dest->significand = b; } } /* If you want to execute a bc_num operation to a limited scale, it is a waste of computation time to pass operands with a longer scale, because bc lets the operand's scale override your limit. This function hides superfluous digits from bc, returning the original scale for restoring purposes */ static int _limit_scale( floatnum f, int newscale) { int oldscale; oldscale = _scaleof(f); _setscale(f, _min(oldscale, newscale)); return oldscale; } /*============================ floatnum routines ===================*/ int float_getrange(void) { return expmax; } int float_getprecision(void) { return maxdigits; } int float_setrange( int maxexp) { int result; result = expmax; expmax = _max(_min(maxexp, MAXEXP), 1); expmin = -expmax - 1; return result; } int float_setprecision( int digits) { int result; result = maxdigits; maxdigits = _max(_min(digits, MAXDIGITS), 1); return result; } /* checking the limits on exponents */ char float_isvalidexp( int exp) { return exp >= expmin && exp <= expmax; } /* clears the error state as well */ Error float_geterror(void) { Error tmp; tmp = float_error; float_error = Success; return tmp; } /* the first error blocks all others as it may be the source of a cascade of dependent errors */ void float_seterror( Error code) { if (float_error == Success) float_error = code; } void floatnum_init(void) { bc_init_numbers(); float_geterror(); } void float_create( floatnum f) { f->significand = NULL; f->exponent = EXPNAN; #ifdef FLOATDEBUG memcpy(f->value, "NaN", 4); #endif } void float_setnan ( floatnum f) { bc_free_num(&(f->significand)); float_create(f); } char _setnan( floatnum result) { float_setnan(result); return FALSE; } char _seterror( floatnum result, Error code) { float_seterror(code); return _setnan(result); } void float_setzero ( floatnum f) { bc_free_num(&(f->significand)); f->exponent = EXPZERO; #ifdef FLOATDEBUG f->value[0] ='0'; f->value[1] = 0; #endif } char _setzero( floatnum result) { float_setzero(result); return TRUE; } char float_isnan( cfloatnum f) { return _is_special(f) && f->exponent != EXPZERO; } char float_iszero( cfloatnum f) { return _is_special(f) && f->exponent == EXPZERO; } int float_getlength( cfloatnum f) { return _is_special(f)? 0 : _scaleof(f) + 1; } char float_getdigit( cfloatnum f, int ofs) { if (ofs >= float_getlength(f) || ofs < 0) return 0; return _digit(f, ofs); } /* checks whether f is a NaN and sets the float_error variable accordingly. Used in parameter checks when float_xxx calls are executed. FALSE is returned if a NaN is encountered. */ char _checknan( cfloatnum f) { if (!float_isnan(f)) return TRUE; float_seterror(NoOperand); return FALSE; } /* checks whether is positive and sets the float_error variable accordingly. Used in parameter checks when float_xxx calls are executed. Some operations accept a special value like EXACT, that has to pass this check, even though its numerical encoding violates the boundaries. If a function does not accept a special value, use NOSPECIALVALUE as a parameter for . TRUE is returned if the check is passed. The check for the limit MAXDIGITS is not executed here, because some intermediate operations have to succeed on more than MAXDIGITS digits */ static char _checkdigits( int digits, int specialval) { if ((digits > 0 && digits <= maxdigits) || digits == specialval) return TRUE; float_seterror(InvalidPrecision); return FALSE; } /* backward-scans the significand in . Returns the number of digits equal to beginning with the +1-th digit of f->significand->n_value. */ static int _bscandigit( cfloatnum f, int scale, char digit) { char* p; char* ps; ps = _valueof(f); for (p = ps + scale + 1; p-- != ps && *p == digit;); return (int)(scale - (p - ps)); } /* scans two significands for the first occurence of a pair of differnt digits. Returns the number of equal digits at the beginning */ static int _scan_equal( floatnum v1, floatnum v2) { int count, i; char* p1; char* p2; count = _min(_scaleof(v1), _scaleof(v2)); p1 = _valueof(v1); p2 = _valueof(v2); i = 0; for (; *(p1++) == *(p2++) && ++i <= count;); return i; } /* scans two significands until it finds a digit different from 0 in the first significand, or a digit different from 9 in the second operand. The scan is limited by compares and starts with the *second* digit in the significands. Returns the number of found (0,9) pairs. */ static int _scan_09pairs( floatnum f1, floatnum f2, int count) { char* p; char* p1; char* p2; p1 = _valueof(f1) + 1; p2 = _valueof(f2) + 1; p = p1; for (; count-- > 0 && *p1 == 0 && *(p2++) == 9; ++p1); return (int)(p1 - p); } signed char float_getsign( cfloatnum f) { if(_is_special(f)) return 0; return f->significand->n_sign == PLUS? 1 : -1; } void float_setsign( floatnum f, signed char s) { if (s == 1 || s == -1) { if(!_is_special(f)) _setsign(f, s); } else if (s != 0) float_setnan(f); } char float_neg( floatnum f) { float_setsign(f, -float_getsign(f)); return _checknan(f); } char float_abs( floatnum f) { if(float_getsign(f) == -1) float_neg(f); return _checknan(f); } signed char float_cmp( cfloatnum val1, cfloatnum val2) { signed char sgn1; if (!_checknan(val1) || !_checknan(val2)) return UNORDERED; sgn1 = float_getsign(val1); if (float_getsign(val2) != sgn1) { if (sgn1 != 0) return sgn1; return -float_getsign(val2); } if (val1->exponent > val2->exponent) return sgn1; if (val1->exponent < val2->exponent) return -sgn1; if (_is_special(val1)) return 0; return (signed char)bc_compare(val1->significand, val2->significand); } /* normalizing process: hides leading zeros in a significand and corrects the exponent accordingly */ static void _corr_lead_zero( floatnum f) { int count; count = _scan_digit(_valueof(f), float_getlength(f), 0); _hidefirst(f, count); f->exponent-=count; } /* normalizing process: if the significand is > 10 in magnitude, this function corrects this */ static void _corr_overflow( floatnum f) { int shift; shift = _lenof(f) - 1; _movepoint(f, -shift); f->exponent += shift; } /* cuts off trailing zeros at the end of a significand */ static void _corr_trailing_zeros( floatnum f) { _hidelast(f, _bscandigit(f, _scaleof(f), 0)); } static char hexdigits[] = "0123456789ABCDEF"; int float_getsignificand( char* buf, int bufsz, cfloatnum f) { int idx, lg; if (bufsz <= 0) return 0; if (float_isnan(f)) { *buf = 'N'; return 1; } if (float_iszero(f)) { *buf = '0'; return 1; } idx = -1; lg = _min(bufsz, float_getlength(f)); for(; ++idx < lg;) *(buf++) = hexdigits[(int)float_getdigit(f, idx)]; return lg; } int float_getexponent( cfloatnum f) { if (_is_special(f)) return 0; return f->exponent; } int float_getscientific( char* buf, int bufsz, cfloatnum f) { char b[42]; /* supports exponents encoded in up to 128 bits */ int sgnlg, explg, mlg; /* handle special cases */ if(float_isnan(f)) { if (bufsz < 4) return -1; memcpy(buf, "NaN\0", 4); return 3; } if(float_iszero(f)) { if (bufsz < 2) return -1; *buf = '0'; *(buf+1) = '\0'; return 1; } /* set one byte aside for sign? */ sgnlg = 0; if(float_getsign(f) < 0) sgnlg = 1; /* convert the exponent */ sprintf(b, "%d", float_getexponent(f)); explg = (int)strlen(b); /* 3 extra bytes for dot, exp char and terminating \0 */ bufsz -= explg + sgnlg + 3; /* rest is for significand */ if (bufsz <= 0) /* buffer too small */ return-1; if(sgnlg > 0) *(buf++) = '-'; /* get the digit sequence of the significand, trailing zeros cut off */ mlg = float_getsignificand(++buf, bufsz, f) - 1; /* move the first digit one byte to the front and fill the gap with a dot */ *(buf-1) = *buf; *(buf++) = '.'; /* append the exponent */ *(buf+mlg) = 'e'; memcpy(buf+mlg+1, b, explg); /* the trailing \0 */ *(buf+mlg+explg+1) = '\0'; return sgnlg + mlg + explg + 3; } #ifdef FLOATDEBUG void _setvalue_(floatnum f) { f->value[float_getsignificand(f->value+2, sizeof(f->value)-3, f)+2] = 0; f->value[1] = f->value[2]; f->value[2] = '.'; f->value[0] = float_getsign(f) < 0? '-' : '+'; } #endif int float_setsignificand( floatnum f, int* leadingzeros, const char* buf, int bufsz) { const char* p; const char* dot; const char* last; const char* b; char* bcp; int zeros; int lg; char c; float_setnan(f); if (bufsz == NULLTERMINATED) bufsz = (int)strlen(buf); /* initialize the output parameters for all early out branches */ if (leadingzeros != NULL) *leadingzeros = 0; if (bufsz <= 0) return -1; dot = memchr(buf, '.', bufsz); /* do not accept more than 1 dots */ if (dot != NULL && memchr(dot + 1, '.', bufsz - (dot - buf)) != NULL) return -1; last = buf + bufsz; /* points behind the input buffer */ /* skip all leading zeros */ b = _memskip(buf, last, '0'); /* is the first non-zero character found a dot? */ if (b == dot) /* then skip all zeros following the dot */ b = _memskip(b+1, last, '0'); /* the 'leading zeros' */ zeros = (int)(b - buf - (dot == NULL || dot >= b? 0:1)); /* only zeros found? */ if (b == last) { /* indicate no dot, no leading zeros, because this does not matter in case of zero */ if (bufsz > (dot == NULL? 0:1)) float_setzero(f); /* do not accept a dot without any zero */ return -1; } /* size of the rest buffer without leading zeros */ bufsz = (int)(bufsz - (b - buf)); /* does the rest buffer contain a dot? */ lg = dot >= b && dot - b < maxdigits? 1 : 0; /* points behind the last significant digit */ p = b + _min(maxdigits + lg, bufsz); /* digits, limited by MAXDIGITS */ lg = _min(maxdigits, bufsz - lg); /* reduce lg by the number of trailing zeros */ for (; *--p == '0'; --lg); if (*(p--) == '.') for (; *(p--) == '0'; --lg); /* get a bc_num of sufficient size */ f->significand = bc_new_num(1, lg - 1); if (f->significand == NULL) return -1; /* exponent is forced to 0 */ f->exponent = 0; /* copy lg digits into bc_num buffer, scan the rest for invalid characters */ bcp = _valueof(f); for(; --bufsz >= 0;) { c = *(b++); if (c != '.') /* ignore a dot */ { if (c < '0' || c > '9') { /* invalid character */ float_setnan(f); return -1; } if (--lg >= 0) *(bcp++) = c - '0'; } } if (leadingzeros != NULL) *leadingzeros = zeros; #ifdef FLOATDEBUG _setvalue_(f); #endif return dot == NULL? -1 : (int)(dot - buf); } void float_setexponent( floatnum f, int exponent) { if (!_is_special(f)) { if (!float_isvalidexp(exponent)) float_setnan(f); else f->exponent = exponent; } } void float_setscientific( floatnum f, const char* buf, int bufsz) { int exppos; int zeros; int dotpos; unsigned exp, ovfl; signed char expsign, msign; const char* expptr; const char* last; char c; float_setnan(f); if (bufsz == NULLTERMINATED) bufsz = (int)strlen(buf); /* find the offset of the exponent character, or -1, if not found */ for(exppos = bufsz; --exppos >= 0;) if ((c = *(buf+exppos)) == 'E' || c == 'e') break; /* marks the end of the exponent string */ last = buf + bufsz; /* pre-set exponent to +0, which is the right value, if there is no exponent. */ exp = 0; expsign = 1; ovfl = 0; if (exppos >= 0) { /* points behind the exponent character */ expptr = buf + (exppos + 1); if (expptr == last) /* do not accept an exponent char without an integer */ return; /* get the exponent sign */ switch(*expptr) { case '-': expsign = -1; // C++17: [[fallthrough]]; // fall through case '+': ++expptr; } if (expptr == last) /* do not accept a sign without a digit following */ return; /* encode the sequence of digits into an unsignedeger */ for (;expptr != last ;) { if (*expptr < '0' || *expptr > '9') /* invalid char encountered */ return; ovfl = 10; if (_longmul(&exp, &ovfl)) { ovfl = *(expptr++) - '0'; _longadd(&exp, &ovfl); } if (ovfl != 0 || exp > EXPMAX+1) { /* do not return immediately, because the significand can be zero */ ovfl = 1; break; } } /* move the last pointer to the exponent char.*/ last = buf + exppos; } /* last points behind the significand part. exp is at most -EXPMIN */ /* get the sign of the significand */ msign = 1; if (buf != last) switch(*buf) { case '-': msign = -1; /* fall through */ case '+': ++buf; } /* let setsignificand convert the sequence of digits into a significand. If a dot is found, its position is given in dotpos, -1 otherwise. zeros are the count of leading '0' digits before the first non_zero digit. */ dotpos = float_setsignificand(f, &zeros, buf, (int)(last-buf)); if (_is_special(f)) /* setsignificand either found a zero or encountered invalid characters */ return; /* if we did not find a dot, we assume an integer, and put the dot after last digit */ if (dotpos == -1) dotpos = (int)(last - buf); /* leading zeros shift the dot to the left. dotpos is now the exponent that results from the position of the dot in the significand. */ dotpos -= zeros+1; /* combine the dot position with the explicit exponent */ if (ovfl != 0 || !_checkadd(&dotpos, expsign * (int)exp)) /* exponent overflow */ float_setnan(f); float_setexponent(f, dotpos); float_setsign(f, msign); } /* normalizes a significand such that 1 <= x < 10. If the exponent overflows during this operation this is notified. */ static char _normalize( floatnum f) { _corr_lead_zero(f); if (f->significand != NULL && _lenof(f) > 1) _corr_overflow(f); if (f->significand != NULL) _corr_trailing_zeros(f); if (f->significand != NULL && !float_isvalidexp(f->exponent)) { float_seterror(Underflow); if (f->exponent > 0) float_seterror(Overflow); float_setnan(f); } #ifdef FLOATDEBUG if (f->significand != NULL) _setvalue_(f); #endif return f->significand != NULL; } void float_setinteger(floatnum dest, int value) { char buf[BITS_IN_UNSIGNED/3 + 3]; sprintf(buf, "%d", value); float_setscientific(dest, buf, NULLTERMINATED); } void float_move( floatnum dest, floatnum source) { if (dest != source) { float_setnan(dest); *dest = *source; float_create(source); } } /* creates a copy of and assigns it to . The significand is guaranteed to have +1 digits. The significand is truncated, or padded with zeros to the right, to achieve the desired length. may assume the special value EXACT, in which case a true copy is generated. This function allows an in-place copy (dest == source). */ static void _scaled_clone( floatnum dest, cfloatnum source, int scale) { /* dest == source allowed! */ bc_num mant; unsigned exp; signed char sign; mant = NULL; if(scale == EXACT) scale = _scaleof(source); if (dest == source && scale <= _scaleof(source)) { _setscale(dest, scale); return; } mant = bc_new_num(1, scale); scale = _min(scale, _scaleof(source)); memcpy(mant->n_value, _valueof(source), scale+1); sign = float_getsign(source); exp = source->exponent; float_setnan(dest); dest->exponent = exp; dest->significand = mant; #ifdef FLOATDEBUG _setvalue_(dest); #endif float_setsign(dest, sign); } char float_copy( floatnum dest, cfloatnum source, int digits) { int scale, save; if (digits == EXACT) digits = _max(1, float_getlength(source)); if (!_checkdigits(digits, NOSPECIALVALUE)) return _seterror(dest, InvalidPrecision); if (_is_special(source)) { if (dest != source) float_free(dest); *dest = *source; } else { // invariant: source has to be restored, if it is != dest scale = _min(digits - 1, _scaleof(source)); save = _limit_scale((floatnum)source, scale); _corr_trailing_zeros((floatnum)source); _scaled_clone(dest, source, EXACT); if (dest != source) _setscale(source, save); } return TRUE; } /* rounding a value towards zero */ static void _trunc( floatnum dest, cfloatnum x, int scale) { scale -= _bscandigit(x, scale, 0); _scaled_clone(dest, x, scale); #ifdef FLOATDEBUG _setvalue_(dest); #endif } /* rounding a value towards infinity */ static char _roundup( floatnum dest, cfloatnum x, int scale) { scale -= _bscandigit(x, scale, 9); _scaled_clone(dest, x, _max(0, scale)); if (scale < 0) { *_valueof(dest) = 1; if (!float_isvalidexp(++dest->exponent)) return FALSE; } else { ++*(_valueof(dest) + scale); } #ifdef FLOATDEBUG _setvalue_(dest); #endif return TRUE; } char float_round( floatnum dest, cfloatnum src, int digits, roundmode mode) { int scalediff, scale; char digit; signed char sign, updown; if (mode > TOMINUSINFINITY) return _seterror(dest, InvalidParam); if (!_checkdigits(digits, NOSPECIALVALUE)) return _setnan(dest); if (float_isnan(src)) return _seterror(dest, NoOperand); updown = 0; scale = digits - 1; if (float_getlength(src) > digits) { sign = float_getsign(src); switch(mode) { case TONEAREST: scalediff = _scaleof(src) - scale; if (scalediff > 0) { digit = _digit(src, digits); if (digit < 5 || (digit == 5 && scalediff == 1 && (_digit(src, scale) & 1) == 0)) updown = -1; else updown = 1; } break; case TOZERO: updown = -1; break; case TOINFINITY: updown = 1; break; case TOPLUSINFINITY: updown = sign; break; case TOMINUSINFINITY: updown = -sign; break; } } switch (updown) { case 1: if (!_roundup(dest, src, scale)) return _seterror(dest, Overflow); break; case 0: float_copy(dest, src, digits); break; case -1: _trunc(dest, src, scale); break; } return TRUE; } char float_int( floatnum f) { if (!_checknan(f)) return FALSE; if (f->exponent < 0) float_setzero(f); else if (!float_iszero(f)) float_round(f, f, f->exponent+1, TOZERO); return TRUE; } char float_frac( floatnum f) { if (!_checknan(f) || float_iszero(f) || f->exponent < 0) return !float_isnan(f); if (_scaleof(f) <= f->exponent) float_setzero(f); else { int leadingzeros = 0; _hidefirst(f, f->exponent + 1); leadingzeros = _scan_digit(_valueof(f), float_getlength(f), 0); _hidefirst(f, leadingzeros); f->exponent = -leadingzeros - 1; #ifdef FLOATDEBUG _setvalue_(f); #endif } return TRUE; } /* the general purpose add/subtract routine that deals with the ordinary case. */ static char _addsub_normal( floatnum dest, floatnum summand1, floatnum summand2, int digits) { floatstruct tmp; int expdiff; int scale; int fulllength; int extradigit; /* the operands are ordered by their exponent */ expdiff = (unsigned)(summand1->exponent - summand2->exponent); /* the full length of the sum (without carry) */ fulllength = _max(expdiff + _scaleof(summand2), _scaleof(summand1)) + 1; extradigit = 0; if (digits == EXACT || digits > fulllength) digits = fulllength; else { if (float_getsign(summand1) + float_getsign(summand2) == 0) extradigit = 1; /* a true subtraction needs no space for a carry */ if (expdiff > digits + extradigit) /* second operand underflows due to exponent diff */ return float_copy(dest, summand1, digits+extradigit); } if (digits > maxdigits) return _seterror(dest, InvalidPrecision); /* we cannot add the operands directly because of possibly different exponents. So we assume the second operand "to be OK" and shift the decimal point of the first appropriately to the right. There is a cheap way to do this: increment len by expdiff and decrement scale by the same amount. But: Check the operand is long enough to do this. */ float_create(&tmp); if (_scaleof(summand1) < expdiff) { _scaled_clone(&tmp, summand1, expdiff); summand1 = &tmp; } scale = digits + extradigit - (int)expdiff - 1; _movepoint(summand1, expdiff); /* truncate overly long operands */ _limit_scale(summand1, scale); _limit_scale(summand2, scale); /* add */ dest->exponent = summand2->exponent; bc_add(summand1->significand, summand2->significand, &(dest->significand), scale); float_free(&tmp); return _normalize(dest); } static char _sub_checkborrow( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* the operands have opposite signs, the same exponent, but their first digit of the significand differ. The operands are ordered by this digit. */ char result; int borrow; int scale1, scale2; char save = 0; char* v1 = NULL; char* v2 = NULL; /* Cancellation occurs, when the operands are of type p.000...yyy - q.999...xxx, p-q == 1, because a borrow propagates from the difference ..0yyy.. - ..9xxx.., leaving zeros in the first part. We check for this here. */ borrow = 0; if (_digit(summand1, 0) - _digit(summand2, 0) == 1) { scale1 = _scaleof(summand1); scale2 = _scaleof(summand2); if (scale1 == 0) /* the special case of a one-digit first operand p. - q.999..xxx */ borrow = _scan_digit(_valueof(summand2) + 1, scale2, 9); else if (scale2 > 0) /* count the 0 - 9 pairs after the first digit, the area where a borrow can propagate */ borrow = _scan_09pairs(summand1, summand2, _min(scale1, scale2)); /* In case of a one-digit second operand (p.yyy.. - q. == 1.yyy..), nothing is cancelled out. Borrow is already set to 0, and this is the correct value for this case, so nothing has to be done here */ if (borrow > 0) { /* we have cancellation here. We skip all digits, that cancel out due to a propagating borrow. These include the first digit and all following (0,9) digit pairs, except the last one. The last pair may be subject to cancellation or not, we do not care, because the following digit pair either yields a non-zero difference, or creates no borrow. Our standard adder is good enough to deal with such a limited cancelling effect. We will replace the last (0,9) digit pair with a (9,8) pair. This prevents the creation of a borrow, and yet, will yield the correct result */ /* hide all digits until the last found 0 - 9 pair */ summand2->exponent -= borrow; summand1->exponent -= borrow; /* in case of a one-digit significand, there is nothing to hide */ if (scale1 > 0) _hidefirst(summand1, borrow); _hidefirst(summand2, borrow); /* we replace the last found 0 - 9 pair by a 9 - 8 pair, avoiding a carry, yet yielding the correct result */ save = *(v1 = _valueof(summand1)); *v1 = 9; *(v2 = _valueof(summand2)) = 8; } } result = _addsub_normal(dest, summand1, summand2, digits); /* restore the modified digits */ if (borrow > 0) { if (summand1 != dest && v1 != NULL) *v1 = save; if (summand2 != dest && v1 != NULL) *v2 = 9; } return result; } static char _sub_expdiff0( floatnum dest, floatnum summand1, floatnum summand2, int digits) { int eq; int result; /* the operands are ordered by their significand length, and have the same exponent, and different sign */ /* One type of cancellation is when both significands set out with the same digits. Since these digits cancel out during subtraction, we look out for the first pair of different digits. eq receives the number of equal digits, which may be 0 */ eq = _scan_equal(summand1, summand2); if (float_getlength(summand2) == eq) { /* the complete second operand is cancelled out */ if (float_getlength(summand1) == eq) /* op1 == -op2 */ return _setzero(dest); /* If xxx.. denotes the second operand, the (longer) first one is of form xxx..yyy.., since it has the same digits in the beginning. During subtraction the xxx... part is cancelled out, and this leaves yyy... as the subtraction result. By copying the yyy... to the result, we can shortcut the subtraction. But before doing so, we have to check yyy... for leading zeros, because the cancellation continues in this case. */ eq += _scan_digit(_valueof(summand1) + eq, float_getlength(summand1) - eq, 0); _hidefirst(summand1, eq); result = float_copy(dest, summand1, digits); dest->exponent -= eq; return result != 0 && _normalize(dest); } /* hide the identical digits, and do the subtraction without them. */ summand1->exponent -= eq; summand2->exponent -= eq; _hidefirst(summand1, eq); _hidefirst(summand2, eq); /* order the operands by their first digit */ if (_digit(summand1, 0) >= _digit(summand2, 0)) return _sub_checkborrow(dest, summand1, summand2, digits); return _sub_checkborrow(dest, summand2, summand1, digits); } static char _sub_expdiff1( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* Cancellation occurs when subtracting 0.9xxx from 1.0yyy */ char result; char singledigit; char* v1; char* v2; /* the operands have different sign, are ordered by their exponent, and the difference of the exponents is 1 */ /* 1.0yyy may be given as a single digit 1 or as a string of digits starting with 1.0 */ singledigit = _scaleof(summand1) == 0; if (_digit(summand1, 0) != 1 || _digit(summand2, 0) != 9 || (!singledigit && _digit(summand1, 1) != 0)) return _addsub_normal(dest, summand1, summand2, digits); /* we have cancellation here. We transform this case into that of equal exponents. */ /* we align both operands by hiding the first digit (1) of the greater operand. This leaves .0yyy which matches the second operand .9xxx. Unfortunately, if the first operand has only one digit, we cannot hide it, so we have to work around this then. */ if (!singledigit) _hidefirst(summand1, 1); /* we change the leading digits into a '9' and a '8' resp. So we finally subtract .8xxx from .9yyy, yielding the correct result. */ v1 = _valueof(summand1); v2 = _valueof(summand2); *v1 = 9; *v2 = 8; summand1->exponent--; result = _sub_checkborrow(dest, summand1, summand2, digits); /* restore the original digits */ if (summand1 != dest) *v1 = singledigit? 1 : 0; if (summand2 != dest) *v2 = 9; return result; } static char _sub_ordered( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* we have to check for cancellation when subtracting. Cancellation occurs when the operands are almost equal in magnitude. E.g. in 1.234 - 1.226 = 0.008, the result is on quite a different scale than the operands. Actually, this is a big problem, because it means that the (true) subtraction is numerically not stable. There is no way to get around this; you always have to take this into account, when subtracting. We make the best out of it, and check for cancellation in advance, so the result is at least valid to all digits, if the operands are known to be exact. Cancellation occurs only, if the difference between the exponents is 1 at most. We prepare the critical cases in specialized routines, and let the standard routine do the rest. */ /* the operands are ordered by their exponent */ unsigned expdiff; expdiff = (unsigned)(summand1->exponent - summand2->exponent); switch (expdiff) { case 0: /* order the operands by their length of the significands */ if (float_getlength(summand1) >= float_getlength(summand2)) return _sub_expdiff0(dest, summand1, summand2, digits); return _sub_expdiff0(dest, summand2, summand1, digits); case 1: return _sub_expdiff1(dest, summand1, summand2, digits); } return _addsub_normal(dest, summand1, summand2, digits); } static char _addsub_ordered( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* operands are ordered by their exponent */ /* handle a bunch of special cases */ if (!_checkdigits(digits, EXACT) || !_checknan(summand1)) return _setnan(dest); if (float_iszero(summand2)) return float_copy(dest, summand1, digits); /* separate true addition from true subtraction */ if (float_getsign(summand1) == float_getsign(summand2)) return _addsub_normal(dest, summand1, summand2, digits); return _sub_ordered(dest, summand1, summand2, digits); } char float_add( floatnum dest, cfloatnum summand1, cfloatnum summand2, int digits) { bc_struct bc1, bc2; floatstruct tmp1, tmp2; floatnum s1, s2; /* the adder may occasionally adjust operands to his needs. Hence we work on temporary structures */ s1 = dest; s2 = dest; if (dest != summand1) { _copyfn(&tmp1, summand1, &bc1); s1 = &tmp1; } if (dest != summand2) { _copyfn(&tmp2, summand2, &bc2); s2 = &tmp2; } /* order the operands by their exponent. This should bring a NaN always to the front, and keeps zeros after any other number. */ if (s1->exponent >= s2->exponent) return _addsub_ordered(dest, s1, s2, digits); return _addsub_ordered(dest, s2, s1, digits); } char float_sub( floatnum dest, cfloatnum minuend, cfloatnum subtrahend, int scale) { char result; if (minuend == subtrahend) { /* changing the sign of one operand would change that of the other as well. So this is a special case */ if(!_checknan(minuend)) return FALSE; _setzero(dest); } /* do not use float_neg, because it may change float_error */ float_setsign((floatnum)subtrahend, -float_getsign(subtrahend)); result = float_add(dest, minuend, subtrahend, scale); if (dest != subtrahend) float_setsign((floatnum)subtrahend, -float_getsign(subtrahend)); return result; } char float_mul( floatnum dest, cfloatnum factor1, cfloatnum factor2, int digits) { char result; int fullscale; int savescale1, savescale2; int scale; /* handle a bunch of special cases */ if (!_checkdigits(digits, EXACT) || !_checknan(factor1) || !_checknan(factor2)) /* invalid scale value or NaN operand */ return _setnan(dest); if (float_iszero(factor1) || float_iszero(factor2)) return _setzero(dest); scale = digits - 1; fullscale = _scaleof(factor1) + _scaleof(factor2); if (digits == EXACT || scale > fullscale) scale = fullscale; if (scale >= maxdigits) /* scale too large */ return _seterror(dest, InvalidPrecision); /* limit the scale of the operands to sane sizes */ savescale1 = _limit_scale((floatnum)factor1, scale); savescale2 = _limit_scale((floatnum)factor2, scale); /* multiply */ dest->exponent = factor1->exponent + factor2->exponent; bc_multiply(factor1->significand, factor2->significand, &(dest->significand), scale); result = _normalize(dest); /* reverse order is necessary in case factor1 == factor2 */ if (dest != factor2) _setscale(factor2, savescale2); if (dest != factor1) _setscale(factor1, savescale1); return result; } char float_div( floatnum dest, cfloatnum dividend, cfloatnum divisor, int digits) { char result; int savescale1, savescale2; int exp; /* handle a bunch of special cases */ if (!_checkdigits(digits, INTQUOT) || !_checknan(dividend) || !_checknan(divisor)) return _setnan(dest); if (float_iszero(divisor)) return _seterror(dest, ZeroDivide); if (float_iszero(dividend)) /* 0/x == 0 */ return _setzero(dest); exp = dividend->exponent - divisor->exponent; /* check for integer quotient */ if(digits == INTQUOT) { if (exp < 0) return _setzero(dest); digits = exp; } /* scale OK? */ if(digits > maxdigits) return _seterror(dest, InvalidPrecision); /* limit the scale of the operands to sane sizes */ savescale1 = _limit_scale((floatnum)dividend, digits); savescale2 = _limit_scale((floatnum)divisor, digits); /* divide */ result = TRUE; dest->exponent = exp; bc_divide(dividend->significand, divisor->significand, &(dest->significand), digits); if (bc_is_zero(dest->significand)) float_setzero(dest); else result = _normalize(dest); /* reverse order is necessary in case divisor == dividend */ if (dest != divisor) _setscale(divisor, savescale2); if (dest != dividend) _setscale(dividend, savescale1); return result; } char float_divmod( floatnum quotient, floatnum remainder, cfloatnum dividend, cfloatnum divisor, int digits) { int exp, exp1; if (!_checkdigits(digits, INTQUOT) || !_checknan(dividend) || !_checknan(divisor) || quotient == remainder || float_iszero(divisor) || float_getlength(divisor) > maxdigits) { if (quotient == remainder) float_seterror(InvalidParam); if (float_getlength(divisor) > maxdigits) float_seterror(TooExpensive); if (float_iszero(divisor)) float_seterror(ZeroDivide); float_setnan(quotient); return _setnan(remainder); } if (float_iszero(dividend)) { float_setzero(quotient); return _setzero(remainder); } exp1 = dividend->exponent; exp = exp1 - divisor->exponent; if(digits-- == INTQUOT) { if (exp < 0) { if (float_copy(remainder, dividend, EXACT)) return _setzero(quotient); return _setnan(quotient); } digits = exp; } if (digits > maxdigits) { float_setnan(quotient); return _seterror(remainder, TooExpensive); } /* divide */ quotient->exponent = exp; remainder->exponent = exp1; bc_divmod(dividend->significand, divisor->significand, &(quotient->significand), &(remainder->significand), digits); /* if something goes wrong (one of the results overflows or underflows), always set both quotient and remainder to NaN */ if (bc_is_zero(remainder->significand)) float_setzero(remainder); else if (!_normalize(remainder)) return _setnan(quotient); if (bc_is_zero(quotient->significand)) float_setzero(quotient); else if (!_normalize(quotient)) return _setnan(remainder); return TRUE; } char float_sqrt(floatnum value, int digits) { if (!_checkdigits(digits, NOSPECIALVALUE) || !_checknan(value)) return _setnan(value); switch (float_getsign(value)) { case -1: return _seterror(value, OutOfDomain); case 0: return TRUE; } if ((value->exponent & 1) != 0) { if (float_getlength(value) == 1) _scaled_clone(value, value, 1); _movepoint(value, 1); } bc_sqrt(&value->significand, digits - 1); #ifdef FLOATDEBUG _setvalue_(value); #endif if (value->exponent >= 0) value->exponent >>= 1; else value->exponent = -((1-value->exponent) >> 1); return TRUE; } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatnum.h000066400000000000000000000417451526573132500247130ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATNUM_H # define FLOATNUM_H #include "number.h" #include "floatconfig.h" #include "floatio.h" #define NULLTERMINATED (-20) #define UNORDERED (-2) #define EXACT (-101) #define INTQUOT (-102) #define float_free(f) float_setnan(f) #ifdef __cplusplus extern "C" { #endif extern int maxdigits; typedef struct { bc_num significand; int exponent; #ifdef FLOATDEBUG char value[110]; #endif /* FLOATDEBUG */ } floatstruct; typedef floatstruct* floatnum; typedef const floatstruct* cfloatnum; typedef enum {TONEAREST, TOZERO, TOINFINITY, TOPLUSINFINITY, TOMINUSINFINITY} roundmode; /* initializes this module. Has to be called prior to the first use of any of the following functions */ void floatnum_init(void); /* sets the error to `code' unless it is already set */ void float_seterror(Error code); /* gets the last error and clears the error afterwards */ Error float_geterror(void); /* returns the current overflow limit. It is the maximum possible exponent. The smallest exponent is -`return value' - 1. This function never reports an error */ int float_getrange(void); /* sets the overflow/underflow limit. Subsequent arithmetic results with exponents between `maxexp' >= exponent >= -`maxexp'-1 are considered valid, all others trigger overflow/underflow errors. `maxexp' cannot be greater than MAXEXP and not less than 1. Exceeding arguments are replaced by the respective limit. The return value is the old overflow limit. This function affects future results only. Current stored values are not subject to overflow/underflow checking, even when they are used as parameters to an operation. This function never reports an error */ int float_setrange(int maxexp); /* returns the current precision limit. Arithmetic results may be cut off after this number of decimal digits */ int float_getprecision(void); /* sets the current maximum precision (in decimal digits) that is used by basic arithmetic operations. The precision is at least 1 and at most MAXDIGITS. An exceeding argument is replaced by the respective limit. Setting a new precision affects future operations only; currently set variables are kept unmodified. The return value is the old precision limit. This function never reports an error */ int float_setprecision(int digits); /* checks whether the submitted exponent is within the current overflow and underflow limits. This function never reports an error */ char float_isvalidexp(int exp); /* initializes a new floatnum to NaN. Call this before the first use of a floatnum variable. The destructing function is float_setnan or its alias, float_free. This function never reports an error. */ void float_create(floatnum f); /* finalizes a variable. To avoid memory leaks, call this before a floatnum is freed. A special value (NaN = not a number) is loaded into `f', so any subsequent arithmetic operation on this variable will fail. However, a variable such finalized can still be re-used without prior initialization, by making it the destination of an operation. If you wish to deliberately "empty" a variable, without detroying it, call this function. An alias "float_free" to this function is defined that you may use anywhere as a replacement for float_setnan. This function never reports an error. */ void float_setnan(floatnum f); /* returns the base 10 exponent of the value in `f'. If `f' is zero or NaN, the returned exponent is 0. This function never reports an error. */ int float_getexponent(cfloatnum f); /* fills the buffer `buf' of size `bufsz' with an ASCII string representing the significand of `f'. No zeros are padded to the right to fill the buffer in case of a short significand. If `bufsz' <= 0, the function returns immediately with result 0. If the significand does not fit completely into the buffer, the output is stopped when the last buffer byte is written to. A non-zero significand yields a sequence of digits, without a decimal point; zero yields "0" and NaN "N". On truncation, no trailing zeros are removed. Exponent and sign are ignored, and no decimal point is written. No '\0' character is appended to the right. The return value are the number of characters written to the buffer. This function never reports an error. */ int float_getsignificand(char* buf, int bufsz, cfloatnum f); /* returns the number of digits in the significand, or 0 for NaN and zero. This function never reports an error. */ int float_getlength(cfloatnum f); /* returns 1, if `f' is positive, -1, if `f' is negative, and 0 if `f' is zero or NaN. This function never reports an error. */ signed char float_getsign(cfloatnum f); /* writes the value stored in `f' as an ASCIIZ string into a buffer of size `bufsz'. If the buffer is too small to hold the full value, the significand is truncated appropriately. If the buffer is too small to even store the most significant digit of the significand besides exponent and sign, nothing is stored at all, and -1 is returned. Else, the length of the output, but without the trailing \0 character, is returned. The output format is the usual scientific format. On truncation, no trailing zeros are removed from the output of the significand. Examples of an output: value output ----- ------ NaN NaN\0 0 0\0 1 1.e0\0 1.2 1.2e0\0 0.5 5.e-1\0 -1 -1.e0\0 1.009 1.00e0\0 (truncated to 3 digits) 10^10 1.e10\0 This function does not touch the adjacent bytes of the final output. If no reasonable output is possible, the complete buffer is left unchanged, not even the final \0 character is written. This function never reports an error. */ int float_getscientific(char* buf, int bufsz, cfloatnum f); /* gets the `ofs'-th digit from the decimal representation of the significand of `f'. If `ofs' is negative or greater equal to the length of the significand, 0 is returned. The return value is between 0 and 9 (not the ASCII representation of these digits (0x30 - 0x39)). This function never returns an error */ char float_getdigit(cfloatnum f, int ofs); /* sets the significand according to the the ASCII text in buffer buf of size `bufsz'. The buffer must contain digits '0' -'9' only, with one possible exception: A single decimal point ('.') may be placed anywhere in the buffer. It is skipped while encoding the significand. The function searches the buffer for the first non-zero digit, and starts the encoding from there. `f' is set to NaN, if the buffer fails to fulfill the above conditions. If the resulting significand exceeds digits, it is truncated. The exponent of `f' is set to 0, so the result is always NaN, 0 or a number between 1 and 9.99... If you want to set both the significand and the exponent of f, set the significand first. If `leadingzeros' is not NULL, and the result in `f' is neither zero nor NaN, the number of leading (and skipped) zeros are stored here. In case of NaN or zero, this value is 0. All trailing zeros in the significand of `f' are removed. The result is the position of the decimal point in `buf', or -1 if either none was found, or if it is not relevant (NaN or 0.0). This function never reports an error. */ int float_setsignificand(floatnum f, int* leadingzeros, const char* buf, int bufsz); /* sets the base 10 exponent of f to exponent. The significand is only changed when this operation fails. Integers greater than EXPMAX or smaller than EXPMIN are not accepted as exponent and let the operation fail, setting `f' to NaN. You cannot change the exponent of 0 or NaN, this is ignored. If you want to set both the significand and the exponent of `f', set the significand first. This function never reports an error. */ void float_setexponent(floatnum f, int exponent); /* converts an ASCII string of length `bufsz' in `buf' to `f'. `bufsz' may assume the special value NULLTERMINATED, in which case the first found \0 character terminates the input. The input format is [+|-][digit...][.[digit...][(e|E)[+|-]digit...]] At least one digit of the significand has to be present. Any non-valid input is converted into a NaN. This function never reports an error. */ void float_setscientific(floatnum f, const char* buf, int bufsz); /* if `s' is 1 or -1, the sign of `f' is set accordingly. Has no effect, if `f' == NaN or zero, or `s' == 0. `f' is set to NaN, if |s| > 1. This function never reports an error. */ void float_setsign(floatnum f, signed char s); /* sets dest to the value in `value'. This function never reports an error. */ void float_setinteger(floatnum dest, int value); /* sets a variable to the numerical value zero. This function never reports an error. */ void float_setzero (floatnum f); /* returns 1, if f contains the special NaN value, 0 otherwise. This function never reports an error. */ char float_isnan(cfloatnum f); /* returns 1, if f contains the value zero, 0 otherwise. This function never reports an error. */ char float_iszero(cfloatnum f); /* copies source to dest, limiting the significand to at most `digits' digits. The parameter `digits' may assume the value EXACT, in which case a full copy is made. If source and dest coincide, float_copy tries to re-use the significand. This prevents unnecessary copying. If a copy has to be made, the allocated space is just big enough to hold the significand, so no memory is wasted. A return value of 0 indicates an error. errors: InvalidPrecision, if `digits', or the length of the copy, exceeds `maxdigits' */ char float_copy(floatnum dest, cfloatnum source, int digits); /* transfers the contents of source to dest. source is assigned NaN afterwards. In contrast to float_copy, float_move does not create a copy of the significand (which employs memory allocation and copying), but transfers simply the data from the source to the destination. This function has been designed to implement, for example, swapping of variables in a fast way. If dest == source, nothing happens. This function never reports an error */ void float_move(floatnum dest, floatnum source); /* changes the value of `f' to -`f'. Has no effect on zero or NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_neg(floatnum f); /* changes the sign of `f', if `f' is negative. Has no effect on a NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_abs(floatnum f); /* compares two values and returns +1 if val1 > val2, 0 if val1 == val2 and -1 if val1 < val2. This function is not intended to be used with NaN's. If you pass it as an argument, UNORDERED is returned to indicate an error. errors: NaNOperand */ signed char float_cmp(cfloatnum val1, cfloatnum val2); /* rounds `f' to `digits' digits according to the submitted mode. If `digits' <= 0 or mode is not recognized, `f' is changed into a NaN. The same holds should the rounding operation overflow. mode == TONEAREST: checks whether the first cut off digit is a '5' or greater. In this case, the absolute value of the significand is rounded up, otherwise rounded down. If the part cut off is a single digit '5', the significand is rounded such that its last digit is even. mode == TOZERO: cuts off all digits after the `digits'th digit. This mode never overflows. mode = TOINFINITY: rounds positive numbers up, negative numbers down (towards greater magnitude). mode == TOPLUSINFINITY: always rounds up. So, negative values are effectively truncated. mode == TOMINUSINFINITY: always rounds down. So, negative values usually increase in magnitude. A return value of 0 indicates an error. errors: NaNOperand InvalidParam InvalidPrecision Overflow */ char float_round(floatnum dest, cfloatnum src, int digits, roundmode mode); /* cuts off the fractional part of `f'. The result is always less or equal in magnitude to the passed argument. A NaN yields a NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_int(floatnum f); /* cuts off the integer part of `f'. If the result is not equal to 0, it has the same sign as the argument. NaN yields NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_frac(floatnum f); /* adds the values in `summand1' and `summand2' and stores the result in `dest'. `dest' may coincide with either summand (or even both). The result is evaluated to `digits' or `digits'+1 digits. If `digits' is EXACT, the sum is evaluated to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting digits exceed `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_add(floatnum dest, cfloatnum summand1, cfloatnum summand2, int digits); /* subtracts `subtrahend' from `minuend' and stores the result in `dest'. `dest' may coincide with either operand (or even both). The result is evaluated to `digits' or `digits'+1 digits. If `digits' is EXACT, the difference is evaluated to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting digits exceed `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_sub(floatnum dest, cfloatnum minuend, cfloatnum subtrahend, int digits); /* multiplies both factors and stores the result in `dest'. `dest' may coincide with either factor (or even both). The result is evaluated to `digits' or `digits'+1 digits, or, if `digits' == EXACT, to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting scale exceeds `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_mul(floatnum dest, cfloatnum factor1, cfloatnum factor2, int digits); /* divides `dividend' by `divisor' and stores the result in `dest'. `dest' may coincide with either operand (or even both). The result is evaluated to `digits' or `digits'+1 digits, or, if `digits' == INTQUOT, to the size of the integer part of the quotient. EXACT is not allowed, even in cases where the dividend is divisible by the divisor. NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - the divisor is zero; - `digits' is invalid, or the effective scale exceeds `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow ZeroDivide */ char float_div(floatnum dest, cfloatnum dividend, cfloatnum divisor, int digits); /* evaluates the quotient, using `digits' steps of the schoolbook division algorithm. The quotient, thus, has `digits' or `digits'-1 digits, and is always truncated towards zero. The remainder fulfills the equation: remainder = dividend - quotient * divisor. `digits' may assume the special value INTQUOT, in which case the integer part of the quotient is calculated. This function is an exact operation anyway, so EXACT is not allowed here. `digits' is subject to the `maxdigits' limit. `remainder' and `quotient' have to be different variables, but apart from this, there are no other restrictions on the passed variables. If this function fails, both result variables are set to NaN. A return value of 0 indicates an error. errors: NaNOperand InvalidParam InvalidPrecision TooExpensive Overflow Underflow ZeroDivide */ char float_divmod(floatnum quotient, floatnum remainder, cfloatnum dividend, cfloatnum divisor, int digits); /* computes the sqare root of `value' to `digits' or `digits'+1 digits. `digits' == EXACT is not allowed, even if the argument is a square. NaN is returned, if - the operand is NaN, - `digits' exceeds `maxdigits' - the operand is negative. A return value 0 indicates an error. errors: NaNOperand InvalidPrecision OutOfDomain */ char float_sqrt(floatnum value, int digits); /* a few convenience functions used everywhere */ char _setnan(floatnum result); char _seterror(floatnum result, Error code); char _checknan(cfloatnum f); char _setzero(floatnum x); #ifdef __cplusplus } #endif #endif /* FLOATNUM_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatpower.c000066400000000000000000000014521526573132500252320ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatpower.h" #include "floatipower.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" char _raise( floatnum x, cfloatnum exponent, int digits) { int iexp; int extra; extra = float_getexponent(exponent); if (digits + extra > maxdigits) extra = maxdigits - digits; if (float_isinteger(exponent)) { iexp = leadingdigits(exponent, float_getexponent(exponent) + 1); if (float_iszero(exponent) || iexp != 0) return _raisei(x, iexp, digits+extra); } if (digits + extra > MATHPRECISION) extra = MATHPRECISION - digits; _ln(x, digits+extra); if (!float_mul(x, x, exponent, digits+extra)) return 0; return _exp(x, digits); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatpower.h000066400000000000000000000005011526573132500252310ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATPOWER_H # define FLOATPOWER_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _raise(floatnum x, cfloatnum exponent, int digits); #ifdef __cplusplus } #endif #endif /* FLOATPOWER_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatseries.c000066400000000000000000000103771526573132500253760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floatseries.h" #include "floatconst.h" #include "floatcommon.h" #include "floatexp.h" /* Though all these serieses can be used with arguments |x| < 1 or even more, the computation time increases rapidly with x. Tests show, that for 100 digit results, it is best to limit x to |x| < 0.01..0.02, and use reduction formulas for greater x */ /* the Taylor series of arctan/arctanh x at x == 0. For small |x| < 0.01 this series converges very fast, yielding 4 or more digits of the result with every summand. The working precision is adjusted, so that the relative error for 100-digit arguments is around 5.0e-100. This means, the error is 1 in the 100-th place (or less) */ void arctanseries( floatnum x, int digits, char alternating) { int expx; int expsqrx; int pwrsz; int addsz; int i; floatstruct xsqr; floatstruct pwr; floatstruct smd; floatstruct sum; /* upper limit of log(x) and log(result) */ expx = float_getexponent(x)+1; /* the summands of the series from the second on are bounded by x^(2*i-1)/3. So the summation yields a result bounded by (x^3/(1-x*x))/3. For x < sqrt(1/3) approx.= 0.5, this is less than 0.5*x^3. We need to sum up only, if the first places of the result (roughly x) are touched. Ignoring the effect of a possile carry, this is only the case, if x*x >= 2*10^(-digits) > 10^(-digits) Example: for x = 9e-51, a 100-digits result covers the decimal places from 1e-51 to 1e-150. x^3/3 is roughly 3e-151, and so is the sum of the series. So we can ignore the sum, but we couldn't for x = 9e-50 */ if (float_iszero(x) || 2*expx < -digits) /* for very tiny arguments arctan/arctanh x is approx.== x */ return; float_create(&xsqr); float_create(&pwr); float_create(&smd); float_create(&sum); /* we adapt the working precision to the decreasing summands, saving time when multiplying. Unfortunately, there is no error bound given for the operations of bc_num. Tests show, that the last digit in an incomplete multiplication is usually not correct up to 5 ULP's. */ pwrsz = digits + 2*expx + 1; /* the precision of the addition must not decrease, of course */ addsz = pwrsz; i = 3; float_mul(&xsqr, x, x, pwrsz); float_setsign(&xsqr, alternating? -1 : 1); expsqrx = float_getexponent(&xsqr); float_copy(&pwr, x, pwrsz); float_setzero(&sum); for(; pwrsz > 0; ) { /* x^i */ float_mul(&pwr, &pwr, &xsqr, pwrsz+1); /* x^i/i */ float_divi(&smd, &pwr, i, pwrsz); /* The addition virtually does not introduce errors */ float_add(&sum, &sum, &smd, addsz); /* reduce the working precision according to the decreasing powers */ pwrsz = digits - expx + float_getexponent(&smd) + expsqrx + 3; i += 2; } /* add the first summand */ float_add(x, x, &sum, digits+1); float_free(&xsqr); float_free(&pwr); float_free(&smd); float_free(&sum); } /* series expansion of cos/cosh - 1 used for small x, |x| <= 0.01. The function returns 0, if an underflow occurs. The relative error seems to be less than 5e-100 for a 100-digit calculation with |x| < 0.01 */ char cosminus1series( floatnum x, int digits, char alternating) { floatstruct sum, smd; int expsqrx, pwrsz, addsz, i; expsqrx = 2 * float_getexponent(x); float_setexponent(x, 0); float_mul(x, x, x, digits+1); float_mul(x, x, &c1Div2, digits+1); float_setsign(x, alternating? -1 : 1); expsqrx += float_getexponent(x); if (float_iszero(x) || expsqrx < EXPMIN) { /* underflow */ float_setzero(x); return expsqrx == 0; } float_setexponent(x, expsqrx); pwrsz = digits + expsqrx + 2; if (pwrsz <= 0) /* for very small x, cos/cosh(x) - 1 = (-/+)0.5*x*x */ return 1; addsz = pwrsz; float_create(&sum); float_create(&smd); float_copy(&smd, x, pwrsz); float_setzero(&sum); i = 2; while (pwrsz > 0) { float_mul(&smd, &smd, x, pwrsz+1); float_divi(&smd, &smd, i*(2*i-1), pwrsz); float_add(&sum, &sum, &smd, addsz); ++i; pwrsz = digits + float_getexponent(&smd); } float_add(x, x, &sum, digits+1); float_free(&sum); float_free(&smd); return 1; } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floatseries.h000066400000000000000000000011761526573132500254000ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATSERIES_H # define FLOATSERIES_H #include "floatnum.h" #define artanhnear0(x, digits) arctanseries(x, digits, 0) #define arctannear0(x, digits) arctanseries(x, digits, 1) #define coshminus1near0(x, digits) cosminus1series(x, digits, 0) #define cosminus1near0(x, digits) cosminus1series(x, digits, 1) #ifdef __cplusplus extern "C" { #endif void arctanseries(floatnum x, int digits, char alternating); char cosminus1series(floatnum x, int digits, char alternating); #ifdef __cplusplus } #endif #endif /* FLOATSERIES_H */ heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floattrig.c000066400000000000000000000175561526573132500250570ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2008 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "floattrig.h" #include "floatseries.h" #include "floatconst.h" #include "floatcommon.h" /* evaluates arctan x for |x| <= 1 relative error for a 100 digit result is 6e-100 */ void _arctanlt1( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return; float_create(&tmp); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(&tmp, x, x, digits); float_add(&tmp, &tmp, &c1, digits+2); float_sqrt(&tmp, digits); float_add(&tmp, &tmp, &c1, digits+1); float_div(x, x, &tmp, digits); ++reductions; } arctannear0(x, digits); for (;reductions-- > 0;) float_add(x, x, x, digits+1); float_free(&tmp); } /* evaluates arctan x for all x. The result is in the range -pi/2 < result < pi/2 relative error for a 100 digit result is 9e-100 */ void _arctan( floatnum x, int digits) { signed char sgn; if (float_abscmp(x, &c1) > 0) { sgn = float_getsign(x); float_abs(x); float_reciprocal(x, digits); _arctanlt1(x, digits); float_sub(x, &cPiDiv2, x, digits+1); float_setsign(x, sgn); } else _arctanlt1(x, digits); } /* evaluates arccos(1+x) for -0.5 <= x <= 0 arccos(1+x) = arctan(sqrt(-x*(2+x))/(1+x)) the relative error of a 100 digit result is < 5e-100 */ void _arccosxplus1lt0_5( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_setsign(x, 1); float_sqrt(x, digits); float_sub(&tmp, &tmp, &c1, digits); float_div(x, x, &tmp, digits+1); _arctan(x, digits); float_free(&tmp); } /* evaluates arcsin x for -0.5 <= x <= 0.5 arcsin x = arctan(x/sqrt(1-x*x)) the relative error of a 100 digit result is < 5e-100 */ void _arcsinlt0_5( floatnum x, int digits) { floatstruct tmp; if (2*float_getexponent(x) < -digits) return; float_create(&tmp); float_mul(&tmp, x, x, digits); float_sub(&tmp, &c1, &tmp, digits); float_sqrt(&tmp, digits); float_div(x, x, &tmp, digits+1); _arctanlt1(x, digits); float_free(&tmp); } /* evaluates arccos x for -1 <= x <= 1. The result is in the range 0 <= result <= pi. The relative error for a 100 digit result is < 5e-100 */ void _arccos( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) > 0) { float_sub(x, x, &c1, digits+1); _arccosxplus1lt0_5(x, digits); } else { _arcsinlt0_5(x, digits); float_sub(x, &cPiDiv2, x, digits+1); } if (sgn < 0) float_sub(x, &cPi, x, digits+1); } /* evaluates arccos (1+x) for -2 <= x <= 0. The result is in the range 0 <= x <= pi */ void _arccosxplus1( floatnum x, int digits) { if (float_abscmp(x, &c1Div2) <= 0) _arccosxplus1lt0_5(x, digits); else { float_add(x, x, &c1, digits); _arccos(x, digits); } } /* evaluates arcsin x for -1 <= x <= 1. The result is in the range -pi/2 <= result <= pi/2 The relative error for a 100 digit result is < 8e-100 */ void _arcsin( floatnum x, int digits) { signed char sgn; if (float_abscmp(x, &c1Div2) <= 0) _arcsinlt0_5(x, digits); else { sgn = float_getsign(x); float_abs(x); _arccos(x, digits); float_sub(x, &cPiDiv2, x, digits); float_setsign(x, sgn); } } /* evaluates cos x - 1 for x < |pi/4| relative error for 100 digit results is < 5e-100 */ char _cosminus1ltPiDiv4( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return 1; float_abs(x); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(x, x, &c1Div2, digits+1); ++reductions; } if (!cosminus1near0(x, digits) && reductions == 0) return !float_iszero(x); float_create(&tmp); for(; reductions-- > 0;) { float_mul(&tmp, x, x, digits); float_add(x, x, x, digits+2); float_add(x, x, &tmp, digits+2); float_add(x, x, x, digits+2); } float_free(&tmp); return 1; } /* evaluate sin x for |x| <= pi/4, using |sin x| = sqrt((1-cos x)*(2 + cos x-1)) relative error for 100 digit results is < 6e-100*/ void _sinltPiDiv4( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (2*float_getexponent(x)+2 < -digits) /* for small x: sin x approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _cosminus1ltPiDiv4(x, digits); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_abs(x); float_sqrt(x, digits); float_setsign(x, sgn); float_free(&tmp); } /* evaluates tan x for |x| <= pi/4. The relative error for a 100 digit result is < 6e-100 */ void _tanltPiDiv4( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (2*float_getexponent(x)+2 < -digits) /* for small x: tan x approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _cosminus1ltPiDiv4(x, digits); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_abs(x); float_sqrt(x, digits); float_sub(&tmp, &tmp, &c1, digits); float_div(x, x, &tmp, digits+1); float_setsign(x, sgn); float_free(&tmp); } /* evaluates cos x for |x| <= pi */ void _cos( floatnum x, int digits) { signed char sgn; float_abs(x); sgn = 1; if (float_cmp(x, &cPiDiv2) > 0) { sgn = -1; float_sub(x, &cPi, x, digits+1); } if (float_cmp(x, &cPiDiv4) <= 0) { if (2*float_getexponent(x)+2 < - digits) float_setzero(x); else _cosminus1ltPiDiv4(x, digits); float_add(x, x, &c1, digits); } else { float_sub(x, &cPiDiv2, x, digits+1); _sinltPiDiv4(x, digits); } float_setsign(x, sgn); } /* evaluates cos x - 1 for |x| <= pi. This function may underflow, which is indicated by the return value 0 */ char _cosminus1( floatnum x, int digits) { float_abs(x); if (float_cmp(x, &cPiDiv4) <= 0) return _cosminus1ltPiDiv4(x, digits); _cos(x, digits); float_sub(x, x, &c1, digits); return 1; } /* evaluates sin x for |x| <= pi. */ void _sin( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &cPiDiv2) > 0) float_sub(x, &cPi, x, digits+1); if (float_cmp(x, &cPiDiv4) <= 0) _sinltPiDiv4(x, digits); else { float_sub(x, &cPiDiv2, x, digits+1); if (2*float_getexponent(x)+2 < - digits) float_setzero(x); else _cosminus1ltPiDiv4(x, digits); float_add(x, x, &c1, digits); } float_setsign(x, sgn); } /* evaluates tan x for |x| <= pi. A return value of 0 indicates that x = +/- pi/2 within small tolerances, so that tan x cannot be reliable computed */ char _tan( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &cPiDiv2) > 0) { float_sub(x, &cPi, x, digits+1); sgn = -sgn; } if (float_cmp(x, &cPiDiv4) <= 0) _tanltPiDiv4(x, digits); else { float_sub(x, &cPiDiv2, x, digits+1); if (float_iszero(x) || float_getexponent(x) < -digits) return 0; _tanltPiDiv4(x, digits); float_reciprocal(x, digits); } float_setsign(x, sgn); return 1; } char _trigreduce( floatnum x, int digits) { floatstruct tmp; int expx, save; signed char sgn; char odd; if (float_abscmp(x, &cPi) <= 0) return 1; expx = float_getexponent(x); if (expx > float_getlength(&cPi) - digits) return 0; save = float_setprecision(MAXDIGITS); float_create(&tmp); sgn = float_getsign(x); float_abs(x); float_divmod(&tmp, x, x, &cPi, INTQUOT); float_setprecision(save); odd = float_isodd(&tmp); if (odd) float_sub(x, x, &cPi, digits+1); if (sgn < 0) float_neg(x); float_free(&tmp); return 1; } void _sinpix( floatnum x, int digits) { char odd; odd = float_isodd(x); float_frac(x); float_mul(x, &cPi, x, digits+1); _sin(x, digits); if (odd) float_neg(x); } heldercorreia-speedcrunch-e7ca37f/src/math/floatnum/floattrig.h000066400000000000000000000016211526573132500250460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef FLOATTRIG_H # define FLOATTRIG_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif void _arctanlt1(floatnum x, int digits); void _arctan(floatnum x, int digits); void _arccosxplus1lt0_5(floatnum x, int digits); void _arcsinlt0_5(floatnum x, int digits); void _arccos(floatnum x, int digits); void _arccosxplus1(floatnum x, int digits); void _arcsin(floatnum x, int digits); char _cosminus1ltPiDiv4(floatnum x, int digits); void _sinltPiDiv4(floatnum x, int digits); void _tanltPiDiv4(floatnum x, int digits); void _cos(floatnum x, int digits); void _sin(floatnum x, int digits); char _tan(floatnum x, int digits); char _cosminus1(floatnum x, int digits); char _trigreduce(floatnum x, int digits); void _sinpix(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /* FLOATTRIG_H */ heldercorreia-speedcrunch-e7ca37f/src/math/hmath.cpp000066400000000000000000001613541526573132500226740ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2009, 2011, 2013-2016, 2018, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "hmath.h" #include "core/startupdiagnostics.h" #include "floatnum/floatcommon.h" #include "floatnum/floatconst.h" #include "floatnum/floatconvert.h" #include "floatnum/floathmath.h" #include "rational.h" #include "core/mathdsl.h" #include #include #include #include #include #include #include #define RATIONAL_TOL HNumber("1e-20") //TODO make this configurable #define HMATH_WORKING_PREC (DECPRECISION + 3) #define HMATH_EVAL_PREC (HMATH_WORKING_PREC + 2) // If cancellation leaves only a handful of digits, treat the residual as noise. #define HMATH_CANCELLATION_GUARD_DIGITS 8 //TODO should go into a separate format file // default scale for fall back in formatting #define HMATH_MAX_SHOWN 20 #define HMATH_BIN_MAX_SHOWN ((33219*HMATH_MAX_SHOWN)/10000 + 1) #define HMATH_OCT_MAX_SHOWN ((11073*HMATH_MAX_SHOWN)/10000 + 1) #define HMATH_HEX_MAX_SHOWN ((8305*HMATH_MAX_SHOWN)/10000 + 1) /*------------------------ Helper routines -------------------------*/ static void checkfullcancellation(cfloatnum op1, cfloatnum op2, floatnum r) { if (float_getlength(op1) != 0 && float_getlength(op2) != 0 && float_getlength(r) != 0) { // NaN or zero not involved in computation. int expr = float_getexponent(r); if (float_getexponent(op1) - expr >= HMATH_WORKING_PREC - HMATH_CANCELLATION_GUARD_DIGITS || float_getexponent(op2) - expr >= HMATH_WORKING_PREC - HMATH_CANCELLATION_GUARD_DIGITS) float_setzero(r); } } static char checkAdd(floatnum dest, cfloatnum s1, cfloatnum s2, int digits) { if (float_add(dest, s1, s2, digits) && float_getsign(s1) + float_getsign(s2) == 0) checkfullcancellation(s1, s2, dest); return float_isnan(dest); } static char checkSub(floatnum dest, cfloatnum s1, cfloatnum s2, int digits) { if (float_sub(dest, s1, s2, digits) && float_getsign(s1) - float_getsign(s2) == 0) checkfullcancellation(s1, s2, dest); return float_isnan(dest); } static void h_init() { static bool h_initialized = false; if (!h_initialized) { StartupDiagnostics::Scope timing("Initialize math engine"); h_initialized = true; //TODO related to formats, get rid of it. float_stdconvert(); } } static void checkpoleorzero(floatnum result, floatnum x) { if (float_getlength(result) == 0 || float_getlength(x) == 0) return; int expx = float_getexponent(x)-HMATH_WORKING_PREC+1; int expr = float_getexponent(result); if (expr <= expx) float_setzero(result); else if (expr >= -expx) { float_setnan(result); float_seterror(EvalUnstable); } } static char roundResult(floatnum x) { if (float_isnan(x)) // Avoids setting float_error. return 0; return float_round(x, x, HMATH_WORKING_PREC, TONEAREST); } /*--------------------------- HNumberPrivate --------------------*/ class HNumberPrivate { public: HNumberPrivate(); ~HNumberPrivate(); //TODO make this a variant floatstruct fnum; Error error; }; HNumberPrivate::HNumberPrivate() : error(Success) { h_init(); float_create(&fnum); } HNumberPrivate::~HNumberPrivate() { float_free(&fnum); } typedef char (*Float1ArgND)(floatnum x); typedef char (*Float1Arg)(floatnum x, int digits); typedef char (*Float2ArgsND)(floatnum result, cfloatnum p1, cfloatnum p2); typedef char (*Float2Args)(floatnum result, cfloatnum p1, cfloatnum p2, int digits); static Error checkNaNParam(const HNumberPrivate& v1, const HNumberPrivate* v2 = 0) { if (!float_isnan(&v1.fnum) && (!v2 || !float_isnan(&v2->fnum))) return Success; Error error = v1.error; if (error == Success && v2) error = v2->error; return error == 0? NoOperand : error; } void roundSetError(HNumberPrivate* dest) { dest->error = float_geterror(); floatnum dfnum = &dest->fnum; if (dest->error != Success) float_setnan(dfnum); if (!float_isnan(dfnum)) float_round(dfnum, dfnum, HMATH_WORKING_PREC, TONEAREST); } void call2Args(HNumberPrivate* dest, HNumberPrivate* n1, HNumberPrivate* n2, Float2Args func) { dest->error = checkNaNParam(*n1, n2); if (dest->error == Success) { floatnum dfnum = &dest->fnum; func(dfnum, &n1->fnum, &n2->fnum, HMATH_EVAL_PREC); roundSetError(dest); } } void call2ArgsND(HNumberPrivate* dest, HNumberPrivate* n1, HNumberPrivate* n2, Float2ArgsND func) { dest->error = checkNaNParam(*n1, n2); if (dest->error == Success) { floatnum dfnum = &dest->fnum; func(dfnum, &n1->fnum, &n2->fnum); roundSetError(dest); } } void call1Arg(HNumberPrivate* dest, HNumberPrivate* n, Float1Arg func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); func(dfnum, HMATH_EVAL_PREC); roundSetError(dest); } } void call1ArgPoleCheck(HNumberPrivate* dest, HNumberPrivate* n, Float1Arg func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); if (func(dfnum, HMATH_EVAL_PREC)) checkpoleorzero(dfnum, &n->fnum); roundSetError(dest); } } void call1ArgND(HNumberPrivate* dest, HNumberPrivate* n, Float1ArgND func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); func(dfnum); roundSetError(dest); } } static char modwrap(floatnum result, cfloatnum p1, cfloatnum p2, int /*digits*/) { floatstruct tmp; float_create(&tmp); char ok = float_divmod(&tmp, result, p1, p2, INTQUOT); float_free(&tmp); return ok; } char idivwrap(floatnum result, cfloatnum p1, cfloatnum p2) { floatstruct tmp; int save = float_setprecision(DECPRECISION); float_create(&tmp); char ok = float_divmod(result, &tmp, p1, p2, INTQUOT); float_free(&tmp); float_setprecision(save); return ok; } /*-------------------------- HNumber -------------------*/ /** * Creates a new number. */ HNumber::HNumber() : d(new HNumberPrivate) { } /** * Copies from another number. */ HNumber::HNumber(const HNumber& hn) : d(new HNumberPrivate) { operator=(hn); } /** * Creates a new number from an integer value. */ HNumber::HNumber(int i) : d(new HNumberPrivate) { float_setinteger(&d->fnum, i); } /** * Creates a new number from a string. */ HNumber::HNumber(const char* str) : d(new HNumberPrivate) { t_itokens tokens; if ((d->error = parse(&tokens, &str)) == Success && *str == 0) d->error = float_in(&d->fnum, &tokens); float_geterror(); } HNumber::HNumber(const QJsonObject& json) : d(new HNumberPrivate) { *this = deSerialize(json); } /** * Destroys this number. */ HNumber::~HNumber() { delete d; } /** * Returns the error code kept with a NaN. */ Error HNumber::error() const { return d->error; } /** * Returns true if this number is Not a Number (NaN). */ bool HNumber::isNan() const { return float_isnan(&d->fnum) != 0; } /** * Returns true if this number is zero. */ bool HNumber::isZero() const { return float_iszero(&d->fnum) != 0; } /** * Returns true if this number is more than zero. */ bool HNumber::isPositive() const { return float_getsign(&d->fnum) > 0; } /** * Returns true if this number is less than zero. */ bool HNumber::isNegative() const { return float_getsign(&d->fnum) < 0; } /** * Returns true if this number is integer. */ bool HNumber::isInteger() const { return float_isinteger(&d->fnum) != 0; } void HNumber::serialize(QJsonObject& json) const { json["value"] = HMath::format(*this, Format::Fixed() + Format::Precision(DECPRECISION)); } HNumber HNumber::deSerialize(const QJsonObject& json) { HNumber result; if (json.contains("value")) { QString str = json["value"].toString(); str.replace(",", "."); result = HNumber(str.toLatin1().constData()); } return result; } /** * Returns the number as an int. * It is meant to convert small (integer) numbers only and no * checking is done whatsoever. */ int HNumber::toInt() const { return float_asinteger(&d->fnum); } /** * Assigns from another number. */ HNumber& HNumber::operator=(const HNumber& hn) { d->error = hn.error(); float_copy(&d->fnum, &hn.d->fnum, EXACT); return *this; } /** * Adds another number. */ HNumber HNumber::operator+(const HNumber& num) const { if (this->isZero()) return num; if (num.isZero()) return *this; HNumber result; call2Args(result.d, d, num.d, checkAdd); return result; } /** * Adds another number. */ HNumber& HNumber::operator+=(const HNumber& num) { return operator=(*this + num); } /** * Subtract from another number. */ HNumber operator-(const HNumber& n1, const HNumber& n2) { HNumber result; call2Args(result.d, n1.d, n2.d, checkSub); return result; } /** * Subtract from another number. */ HNumber& HNumber::operator-=(const HNumber& num) { return operator=(*this - num); } /** * Multiplies with another number. */ HNumber HNumber::operator*(const HNumber& num) const { HNumber result; call2Args(result.d, d, num.d, float_mul); return result; } /** * Multiplies with another number. */ HNumber& HNumber::operator*=(const HNumber& num) { return operator=(*this * num); } /** * Divides with another number. */ HNumber HNumber::operator/(const HNumber& num) const { HNumber result; call2Args(result.d, d, num.d, float_div); return result; } /** * Divides with another number. */ HNumber& HNumber::operator/=(const HNumber& num) { return operator=(*this / num); } /** * Modulo (rest of integer division) */ HNumber HNumber::operator%(const HNumber& num) const { HNumber result; call2Args(result.d, d, num.d, modwrap); return result; } /** * Returns -1, 0, 1 if *this is less than, equal to, or more than other. */ int HNumber::compare(const HNumber& other) const { int result = float_relcmp(&d->fnum, &other.d->fnum, HMATH_EVAL_PREC-1); float_geterror(); // clears error, if one operand was a NaN return result; } /** * Returns true if l is greater than r. */ bool operator>(const HNumber& l, const HNumber& r) { return l.compare(r) > 0; } /** * Returns true if l is less than r. */ bool operator<(const HNumber& l, const HNumber& r) { return l.compare(r) < 0; } /** * Returns true if l is greater than or equal to r. */ bool operator>=(const HNumber& l, const HNumber& r) { return l.compare(r) >= 0; } /** * Returns true if l is less than or equal to r. */ bool operator<=(const HNumber& l, const HNumber& r) { return l.compare(r) <= 0; } /** * Returns true if l is equal to r. */ bool operator==(const HNumber& l, const HNumber& r) { return l.compare(r) == 0; } /** * Returns true if l is not equal to r. */ bool operator!=(const HNumber& l, const HNumber& r) { return l.compare(r) != 0; } /** * Bitwise ANDs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator&(const HNumber& num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_and); return result; } /** * Bitwise ANDs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber& HNumber::operator&=(const HNumber& num) { return operator=(*this & num); } /** * Bitwise ORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator|(const HNumber& num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_or); return result; } /** * Bitwise ORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber& HNumber::operator|=(const HNumber& num) { return operator=(*this | num); } /** * Bitwise XORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator^(const HNumber& num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_xor); return result; } /** * Bitwise XORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber& HNumber::operator^=(const HNumber& num) { return operator=(*this ^ num); } /** * Bitwise NOTs the integral part *this. * Yields NaN, if *this exeeds the logic range */ HNumber HNumber::operator~() const { HNumber result; call1ArgND(result.d, d, float_not); return result; } /** * Changes the sign. */ HNumber operator-(const HNumber& x) { HNumber result; call1ArgND(result.d, x.d, float_neg); return result; } /** * Shifts the integral part of <*this> to the left by * the parameters value's bits. Zeros are shifted in * to the right, shifted out bits are dropped. * Yields NaN, if the operand exeeds the logic range, * or the shift count is not a non-negative integer. */ HNumber HNumber::operator<<(const HNumber& num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_shl); return result; } /** * Shifts the integral part of <*this> to the right by * the parameters value's bits. The most significand * bit is duplicated to the left, shifted out bits are dropped * (signed or arithmethic shift right). * Yields NaN, if the operand exeeds the logic range, * or the shift count is not a non-negative integer. */ HNumber HNumber::operator>>(const HNumber& num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_shr); return result; } HNumber::Format::Format() : base(Base::Null) , radixChar(RadixChar::Null) , mode(Mode::Null) , precision(PrecisionNull) , paddedBits(0) , forcedExponent(ForcedExponentNull) { } HNumber::Format::Format(const HNumber::Format& other) : base(other.base) , radixChar(other.radixChar) , mode(other.mode) , precision(other.precision) , removeTrailingZeroes(other.removeTrailingZeroes) , paddedBits(other.paddedBits) , forcedExponent(other.forcedExponent) { } HNumber::Format HNumber::Format::operator+(const HNumber::Format& other) const { Format result; result.base = (this->base != Base::Null) ? this->base : other.base; result.radixChar = (this->radixChar != RadixChar::Null) ? this->radixChar : other.radixChar; result.mode = (this->mode != Mode::Null) ? this->mode : other.mode; result.precision = (this->precision != PrecisionNull) ? this->precision : other.precision; result.removeTrailingZeroes = this->removeTrailingZeroes || other.removeTrailingZeroes; result.paddedBits = this->paddedBits != 0 ? this->paddedBits : other.paddedBits; result.forcedExponent = this->forcedExponent != ForcedExponentNull ? this->forcedExponent : other.forcedExponent; return result; } HNumber::Format HNumber::Format::Binary() { Format result; result.base = Base::Binary; return result; } HNumber::Format HNumber::Format::Octal() { Format result; result.base = Base::Octal; return result; } HNumber::Format HNumber::Format::Decimal() { Format result; result.base = Base::Decimal; return result; } HNumber::Format HNumber::Format::Hexadecimal() { Format result; result.base = Base::Hexadecimal; return result; } HNumber::Format HNumber::Format::Precision(int prec) { Format result; result.precision = prec; return result; } HNumber::Format HNumber::Format::Point() { Format result; result.radixChar = RadixChar::Point; return result; } HNumber::Format HNumber::Format::Comma() { Format result; result.radixChar = RadixChar::Comma; return result; } HNumber::Format HNumber::Format::General() { Format result; result.mode = Mode::General; return result; } HNumber::Format HNumber::Format::Fixed() { Format result; result.mode = Mode::Fixed; return result; } HNumber::Format HNumber::Format::Scientific() { Format result; result.mode = Mode::Scientific; return result; } HNumber::Format HNumber::Format::Engineering() { Format result; result.mode = Mode::Engineering; return result; } HNumber::Format HNumber::Format::ForcedExponent(int exponent) { Format result; result.forcedExponent = exponent; return result; } HNumber::Format HNumber::Format::Sexagesimal() { Format result; result.mode = Mode::Sexagesimal; return result; } HNumber::Format HNumber::Format::PadBits(int bits) { Format result; result.paddedBits = bits; return result; } HNumber::Format HNumber::Format::PadToByteBoundary() { Format result; result.paddedBits = PaddedBitsAutoByte; return result; } namespace { QString applyIntegerPadding(const QString& input, int base, int paddedBits) { if (paddedBits == 0) return input; int bitsPerDigit = 0; QString prefix; switch (base) { case 2: bitsPerDigit = 1; prefix = MathDsl::BinPrefix; break; case 8: bitsPerDigit = 3; prefix = MathDsl::OctPrefix; break; case 16: bitsPerDigit = 4; prefix = MathDsl::HexPrefix; break; default: return input; } int pos = 0; QString result(input); if (result.startsWith(QLatin1Char('-')) || result.startsWith(QLatin1Char('+'))) ++pos; if (!result.mid(pos).startsWith(prefix, Qt::CaseInsensitive)) return input; pos += prefix.size(); const int dotPos = result.indexOf(QLatin1Char('.'), pos); const int intEnd = dotPos >= 0 ? dotPos : result.size(); const int intDigits = intEnd - pos; if (intDigits <= 0) return input; const int currentBits = intDigits * bitsPerDigit; int targetBits = paddedBits; if (paddedBits == HNumber::Format::PaddedBitsAutoByte) targetBits = ((currentBits + 7) / 8) * 8; if (targetBits <= currentBits) return input; const int targetDigits = (targetBits + bitsPerDigit - 1) / bitsPerDigit; result.insert(pos, QString(targetDigits - intDigits, QLatin1Char('0'))); return result; } char* _doFormat(cfloatnum x, signed char base, signed char expbase, char outmode, int prec, unsigned flags) { t_otokens tokens; char intbuf[BINPRECISION+1]; char fracbuf[BINPRECISION+1]; int sz = 0; char* str = nullptr; switch (base) { case 2: sz = BINPRECISION+1; break; case 8: sz = OCTPRECISION+1; break; case 10: sz = DECPRECISION+1; break; case 16: sz = HEXPRECISION+1; break; } tokens.intpart.sz = sz; tokens.intpart.buf = intbuf; tokens.fracpart.sz = sz; tokens.fracpart.buf = fracbuf; floatstruct tmp; float_create(&tmp); float_copy(&tmp, x, DECPRECISION + 2); if (float_out(&tokens, &tmp, prec, base, outmode) == Success) { sz = cattokens(nullptr, -1, &tokens, expbase, flags); str = (char*)malloc(sz); cattokens(str, sz, &tokens, expbase, flags); } float_free(&tmp); return str; } /** * Formats the given number as string, using specified decimal digits. * Note that the returned string must be freed. */ char* formatFixed(cfloatnum x, int prec, int base, bool removeTrailingZeroes) { unsigned flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_EXPZERO; if (removeTrailingZeroes) flags |= IO_FLAG_SUPPRESS_TRL_ZERO; if (base != 10) flags += IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE; if (prec < 0) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; prec = HMATH_MAX_SHOWN; } char* result = _doFormat(x, base, base, IO_MODE_FIXPOINT, prec, flags); return result ? result : _doFormat(x, base, base, IO_MODE_SCIENTIFIC, HMATH_MAX_SHOWN, flags); } /** * Formats the given number as string, in scientific format. * Note that the returned string must be freed. */ char* formatScientific(cfloatnum x, int prec, int base, bool removeTrailingZeroes) { unsigned flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_EXPPLUS; if (removeTrailingZeroes) flags |= IO_FLAG_SUPPRESS_TRL_ZERO; if (base != 10) flags += IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE; if (prec < 0) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; prec = HMATH_MAX_SHOWN; } return _doFormat(x, base, base, IO_MODE_SCIENTIFIC, prec, flags); } /** * Formats the given number as string, in engineering notation. * Note that the returned string must be freed. */ char* formatEngineering(cfloatnum x, int prec, int base, bool removeTrailingZeroes) { unsigned flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_EXPPLUS; if (removeTrailingZeroes) flags |= IO_FLAG_SUPPRESS_TRL_ZERO | IO_FLAG_SUPPRESS_DOT; if (base != 10) flags += IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE; if (prec <= 1) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO + IO_FLAG_SUPPRESS_DOT; prec = HMATH_MAX_SHOWN; } return _doFormat(x, base, base, IO_MODE_ENG, prec, flags); } /** * Formats the given number as string, using specified decimal digits. * Note that the returned string must be freed. */ char* formatGeneral(cfloatnum x, int prec, int base, bool removeTrailingZeroes) { // find the exponent and the factor int expd = float_getexponent(x); char* str; if (expd > 14) str = formatScientific(x, prec, base, removeTrailingZeroes); else if (expd < -9) str = formatScientific(x, prec, base, removeTrailingZeroes); else if ((expd < 0) && (prec >= 0) && (expd < -prec)) str = formatScientific(x, prec, base, removeTrailingZeroes); else str = formatFixed(x, prec, base, removeTrailingZeroes); return str; } } /* unnamed namespace */ /** * Formats the given number as string, using specified decimal digits. */ QString HMath::format(const HNumber& hn, HNumber::Format format) { if (format.mode == HNumber::Format::Mode::Engineering && format.base != HNumber::Format::Base::Binary && format.base != HNumber::Format::Base::Octal && format.base != HNumber::Format::Base::Hexadecimal && format.forcedExponent != HNumber::Format::ForcedExponentNull) { const int forcedExponent = format.forcedExponent; const HNumber scale = HMath::raise(HNumber(10), forcedExponent); const HNumber mantissa = hn / scale; HNumber::Format mantissaFormat(format); mantissaFormat.mode = HNumber::Format::Mode::Fixed; mantissaFormat.base = HNumber::Format::Base::Decimal; mantissaFormat.forcedExponent = HNumber::Format::ForcedExponentNull; QString result = HMath::format(mantissa, mantissaFormat); if (forcedExponent != 0) result += QStringLiteral("e%1").arg(forcedExponent); return result; } char* rs = 0; if (format.precision < 0) // This includes PrecisionNull format.precision = -1; int base; switch (format.base) { case HNumber::Format::Base::Binary: base = 2; break; case HNumber::Format::Base::Octal: base = 8; break; case HNumber::Format::Base::Hexadecimal: base = 16; break; case HNumber::Format::Base::Decimal: case HNumber::Format::Base::Null: default: base = 10; break; } switch (format.mode) { case HNumber::Format::Mode::Fixed: rs = formatFixed(&hn.d->fnum, format.precision, base, format.removeTrailingZeroes); break; case HNumber::Format::Mode::Scientific: rs = formatScientific(&hn.d->fnum, format.precision, base, format.removeTrailingZeroes); break; case HNumber::Format::Mode::Engineering: rs = formatEngineering(&hn.d->fnum, format.precision, base, format.removeTrailingZeroes); break; case HNumber::Format::Mode::Sexagesimal: rs = formatFixed(&hn.d->fnum, format.precision, base, format.removeTrailingZeroes); break; case HNumber::Format::Mode::General: default: rs = formatGeneral(&hn.d->fnum, format.precision, base, format.removeTrailingZeroes); } QString result(rs); free(rs); return applyIntegerPadding(result, base, format.paddedBits); } /** * Converts radians to degrees. */ HNumber HMath::rad2deg(const HNumber& angle) { return angle * (HNumber(180) / HMath::pi()); } /** * Converts degrees to radians. */ HNumber HMath::deg2rad(const HNumber& angle) { return angle * (HMath::pi() / HNumber(180)); } /** * Converts radians to gons. */ HNumber HMath::rad2gon(const HNumber& angle) { return angle * (HNumber(200) / HMath::pi()); } /** * Converts gons to radians. */ HNumber HMath::gon2rad(const HNumber& angle) { return angle * (HMath::pi() / HNumber(200)); } /** * Returns the constant e (Euler's number). */ HNumber HMath::e() { HNumber value; float_copy(&value.d->fnum, &cExp, HMATH_EVAL_PREC); return value; } /** * Returns the constant Pi. */ HNumber HMath::pi() { HNumber value; float_copy(&value.d->fnum, &cPi, HMATH_EVAL_PREC); return value; } /** * Returns the constant Phi (golden number). */ HNumber HMath::phi() { HNumber value; float_copy(&value.d->fnum, &cPhi, HMATH_EVAL_PREC); return value; } /** * Returns a NaN (Not a Number) with error set to * passed parameter. */ HNumber HMath::nan(Error error) { HNumber result; result.d->error = error; return result; } /** * Returns the maximum of two numbers. */ HNumber HMath::max(const HNumber& n1, const HNumber& n2) { switch (float_cmp(&n1.d->fnum, &n2.d->fnum)) { case 0: case 1: return n1; case -1: return n2; default: return HMath::nan(checkNaNParam(*n1.d, n2.d)); } } /** * Returns the minimum of two numbers. */ HNumber HMath::min(const HNumber& n1, const HNumber& n2) { switch (float_cmp(&n1.d->fnum, &n2.d->fnum)) { case 0: case 1: return n2; case -1: return n1; default: return HMath::nan(checkNaNParam(*n1.d, n2.d)); } } /** * Returns the absolute value of n. */ HNumber HMath::abs(const HNumber& n) { HNumber result; call1ArgND(result.d, n.d, float_abs); return result; } /** * Rounds n to the specified decimal digits. */ HNumber HMath::round(const HNumber& n, int prec) { if (n.isNan()) return HMath::nan(checkNaNParam(*n.d)); HNumber result(n); floatnum rnum = &result.d->fnum; int exp = float_getexponent(rnum); // Avoid exponent overflow later. if (prec > HMATH_WORKING_PREC && exp > 0) prec = HMATH_WORKING_PREC; if (prec < 0 && -exp-1 > prec) float_setzero(rnum); else if (exp + prec < HMATH_WORKING_PREC) { float_addexp(rnum, prec); float_roundtoint(rnum, TONEAREST); float_addexp(rnum, -prec); } return result; } /** * Truncates n to the specified decimal digits. */ HNumber HMath::trunc(const HNumber& n, int prec) { if (n.isNan()) return HMath::nan(checkNaNParam(*n.d)); HNumber result(n); floatnum rnum = &result.d->fnum; int exp = float_getexponent(rnum); // Avoid exponent overflow later on. if (prec > HMATH_WORKING_PREC && exp > 0) prec = HMATH_WORKING_PREC; if (prec < 0 && -exp-1 > prec) float_setzero(rnum); else if (exp + prec < HMATH_WORKING_PREC) { float_addexp(rnum, prec); float_roundtoint(rnum, TOZERO); float_addexp(rnum, -prec); } return result; } /** * Returns the integer part of n. */ HNumber HMath::integer(const HNumber& n) { HNumber result; call1ArgND(result.d, n.d, float_int); return result; } /** * Returns the fraction part of n. */ HNumber HMath::frac(const HNumber& n) { HNumber result; call1ArgND(result.d, n.d, float_frac); return result; } #define CHECK_NAN \ if (n.isNan()) \ return HMath::nan(checkNaNParam(*n.d)); #define RETURN_IF_NEAR_INT \ HNumber nearest_int(n); \ float_roundtoint(&nearest_int.d->fnum, TONEAREST); \ /* Note: float_relcmp doesn't work here, because it's doesn't check the relative */ \ /* tolerance if exponents are not the same. */ \ /* FIXME: Put this value as parameter. */ \ /* Kudos to the guy who can figure out why we need such a small tolerance here. */ \ /* 1e-70 does not work, but 1e-10000 does. */ \ if (HMath::abs(n - nearest_int) < HNumber("1e-100") * HMath::abs(n + nearest_int)) /* FIXME: Make configurable. */ \ return nearest_int; \ /** * Returns the floor of n. */ HNumber HMath::floor(const HNumber& n) { CHECK_NAN; RETURN_IF_NEAR_INT; // Actual rounding, if needed. HNumber r(n); float_roundtoint(&r.d->fnum, TOMINUSINFINITY); return r; } /** * Returns the ceiling of n. */ HNumber HMath::ceil(const HNumber& n) { CHECK_NAN; RETURN_IF_NEAR_INT; // Actual rounding, if needed. HNumber r(n); float_roundtoint(&r.d->fnum, TOPLUSINFINITY); return r; } /** * Returns the greatest common divisor of n1 and n2. */ HNumber HMath::gcd(const HNumber& n1, const HNumber& n2) { if (!n1.isInteger() || !n2.isInteger()) { Error error = checkNaNParam(*n1.d, n2.d); if (error != Success) return HMath::nan(error); return HMath::nan(TypeMismatch); } HNumber a = abs(n1); HNumber b = abs(n2); if (a == 0) return b; if (b == 0) return a; // Run Euclidean algorithm. while (true) { a = a % b; if (a == 0) return b; b = b % a; if (b == 0) return a; } } /** * Returns the least common multiple of n1 and n2. */ HNumber HMath::lcm(const HNumber& n1, const HNumber& n2) { if (!n1.isInteger() || !n2.isInteger()) { Error error = checkNaNParam(*n1.d, n2.d); if (error != Success) return HMath::nan(error); return HMath::nan(TypeMismatch); } HNumber a = abs(n1); HNumber b = abs(n2); if (a == 0 || b == 0) return HNumber(0); return abs((a / gcd(a, b)) * b); } /** * Performs an integer divide. */ HNumber HMath::idiv(const HNumber& dividend, const HNumber& divisor) { HNumber result; call2ArgsND(result.d, dividend.d, divisor.d, idivwrap); if (result.error() == TooExpensive) result.d->error = Overflow; return result; } /** * Returns the square root of n. If n is negative, returns NaN. */ HNumber HMath::sqrt(const HNumber& n) { HNumber result; call1Arg(result.d, n.d, float_sqrt); return result; } /** * Returns the cube root of n. */ HNumber HMath::cbrt(const HNumber& n) { if (n.isNan()) return HMath::nan(checkNaNParam(*n.d)); if (n.isZero()) return n; HNumber r; floatnum rnum = &r.d->fnum; // iterations to approximate result // X[i+1] = (2/3)X[i] + n / (3 * X[i]^2)) // initial guess = sqrt(n) // r = X[i], q = X[i+1], a = n floatstruct a, q; float_create(&a); float_create(&q); float_copy(&a, &n.d->fnum, HMATH_EVAL_PREC); signed char sign = float_getsign(&a); float_abs(&a); int expn = float_getexponent(&a); float_setexponent(&a, expn % 3); expn /= 3; int digits = 0; float_copy(&q, &a, 2); float_sqrt(&q, 2); while (digits < HMATH_EVAL_PREC/2 + 3) { digits = 4 * digits + 2; if (digits > HMATH_EVAL_PREC+2) digits = HMATH_EVAL_PREC+2; float_move(rnum, &q); float_mul(&q, rnum, rnum, digits); float_div(&q, &a, &q, digits); float_add(&q, &q, rnum, digits); float_add(&q, &q, rnum, digits); float_div(&q, &q, &c3, digits); float_sub(rnum, rnum, &q, 3); if (!float_iszero(rnum)) digits = float_getexponent(&q) - float_getexponent(rnum); } float_move(rnum, &q); float_free(&q); float_free(&a); float_setsign(rnum, sign); float_addexp(rnum, expn); roundResult(&r.d->fnum); return r; } /** * Raises n1 to an integer n. */ HNumber HMath::raise(const HNumber& n1, int n) { HNumber r; float_raisei(&r.d->fnum, &n1.d->fnum, n, HMATH_EVAL_PREC); roundSetError(r.d); return r; } /** * Raises n1 to n2. */ HNumber HMath::raise(const HNumber& n1, const HNumber& n2) { HNumber result; HNumber temp = n1; Rational exp; bool result_negative = false; if (n1.isNegative() && !n2.isInteger()){ //Try to convert n2 to a Rational. If n2 is not rational, return NaN. // For negative bases only allow odd denominators. exp = Rational(n2); if (abs(exp.toHNumber() - n2) >= RATIONAL_TOL || (n1.isNegative() && exp.denominator()%2 == 0)) return HMath::nan(OutOfDomain); temp = -temp; result_negative = (exp.numerator() % 2 != 0); } call2Args(result.d, temp.d, n2.d, float_raise); result *= result_negative ? -1 : 1; return result; } /** * Returns e raised to x. */ HNumber HMath::exp(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_exp); return result; }; /** * Returns the natural logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::ln(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_ln); return result; } /** * Returns the common logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::lg(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_lg); return result; } /** * Returns the binary logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::lb(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_lb); return result; } /** * Returns the logarithm of x to base. * If x is non positive, returns NaN. */ HNumber HMath::log(const HNumber& base, const HNumber& x) { return lg(x) / lg(base); } /** * Returns the sine of x. Note that x must be in radians. */ HNumber HMath::sin(const HNumber& x) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_sin); return result; } /** * Returns the cosine of x. Note that x must be in radians. */ HNumber HMath::cos(const HNumber& x) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_cos); return result; } /** * Returns the tangent of x. Note that x must be in radians. */ HNumber HMath::tan(const HNumber& x) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_tan); return result; } /** * Returns the cotangent of x. Note that x must be in radians. */ HNumber HMath::cot(const HNumber& x) { return cos(x) / sin(x); } /** * Returns the secant of x. Note that x must be in radians. */ HNumber HMath::sec(const HNumber& x) { return HNumber(1) / cos(x); } /** * Returns the cosecant of x. Note that x must be in radians. */ HNumber HMath::csc(const HNumber& x) { return HNumber(1) / sin(x); } /** * Returns the arc tangent of x. */ HNumber HMath::arctan(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_arctan); return result; } /** * Returns the angle formed by the vector (x, y) and the x-axis. */ HNumber HMath::arctan2(const HNumber& x, const HNumber& y) { if (y.isZero()) { if (x.isNegative()) return HMath::pi(); if (x.isZero()) return HMath::nan(OutOfDomain); return HNumber(0); } else { HNumber phi = HMath::arctan(HMath::abs(y / x)); if (x.isNegative()) return (HMath::pi() - phi) * HMath::sgn(y); if (x.isZero()) return HMath::pi()/HNumber(2)*HMath::sgn(y); return phi * HMath::sgn(y); } } /** * Returns the arc sine of x. */ HNumber HMath::arcsin(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_arcsin); return result; }; /** * Returns the arc cosine of x. */ HNumber HMath::arccos(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_arccos); return result; }; /** * Returns the hyperbolic sine of x. */ HNumber HMath::sinh(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_sinh); return result; } /** * Returns the hyperbolic cosine of x. */ HNumber HMath::cosh(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_cosh); return result; } /** * Returns the hyperbolic tangent of x. */ HNumber HMath::tanh(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_tanh); return result; } /** * Returns the area hyperbolic sine of x. */ HNumber HMath::arsinh(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_arsinh); return result; } /** * Returns the area hyperbolic cosine of x. */ HNumber HMath::arcosh(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_arcosh); return result; } /** * Returns the area hyperbolic tangent of x. */ HNumber HMath::artanh(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_artanh); return result; } /** * Returns the Gamma function. */ HNumber HMath::gamma(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_gamma); return result; } /** * Returns ln(abs(Gamma(x))). */ HNumber HMath::lnGamma(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_lngamma); return result; } /** * Returns signum x. */ HNumber HMath::sgn(const HNumber& x) { if (x.isNan()) return HMath::nan(checkNaNParam(*x.d)); return float_getsign(&x.d->fnum); } /** * Returns the binomial coefficient of n and r. * Is any of n and r negative or a non-integer, * 1/(n+1)*B(r+1, n-r+1)) is returned, where * B(x,y) is the complete Beta function */ HNumber HMath::nCr(const HNumber& n, const HNumber& r) { Error error = checkNaNParam(*n.d, r.d); if (error != Success) return HMath::nan(error); if (r.isInteger() && r < 0) return HNumber(0); // use symmetry nCr(n, r) == nCr(n, n-r) to find r1 such // 2*r1 <= n and nCr(n, r) == nCr(n, r1) HNumber r1 = (r + r > n) ? n - r : r; HNumber r2 = n - r1; if (r1 >= 0) { if (n.isInteger() && r1.isInteger() && n <= 1000 && r1 <= 50) return factorial(n, r2+1) / factorial(r1, 1); HNumber result(n); floatnum rnum = &result.d->fnum; floatstruct fn, fr; float_create(&fn); float_create(&fr); float_copy(&fr, &r1.d->fnum, HMATH_EVAL_PREC); float_copy(&fn, rnum, EXACT); float_sub(rnum, rnum, &fr, HMATH_EVAL_PREC) && float_add(&fn, &fn, &c1, HMATH_EVAL_PREC) && float_add(&fr, &fr, &c1, HMATH_EVAL_PREC) && float_add(rnum, rnum, &c1, HMATH_EVAL_PREC) && float_lngamma(&fn, HMATH_EVAL_PREC) && float_lngamma(&fr, HMATH_EVAL_PREC) && float_lngamma(rnum, HMATH_EVAL_PREC) && float_add(rnum, rnum, &fr, HMATH_EVAL_PREC) && float_sub(rnum, &fn, rnum, HMATH_EVAL_PREC) && float_exp(rnum, HMATH_EVAL_PREC); float_free(&fn); float_free(&fr); roundSetError(result.d); return result; } if (r2 >= 0 || !r2.isInteger()) return factorial(n, r1+1)/factorial(r2, 1); return 0; } /** * Returns the permutation of n elements chosen r elements. */ HNumber HMath::nPr(const HNumber& n, const HNumber& r) { return factorial(n, (n-r+1)); } /** * Returns the falling Pochhammer symbol x*(x-1)*..*base. * For base == 1, this is the usual factorial x!, what this * function is named after. * This function has been extended using the Gamma function, * so that actually Gamma(x+1)/Gamma(base) is computed, a * value that equals the falling Pochhammer symbol, when * x - base is an integer, but allows other differences as well. */ HNumber HMath::factorial(const HNumber& x, const HNumber& base) { floatstruct tmp; if (float_cmp(&c1, &base.d->fnum) == 0) { HNumber result; call1Arg(result.d, x.d, float_factorial); return result; } float_create(&tmp); HNumber r(base); float_sub(&tmp, &x.d->fnum, &base.d->fnum, HMATH_EVAL_PREC) && float_add(&tmp, &tmp, &c1, HMATH_EVAL_PREC) && float_pochhammer(&r.d->fnum, &tmp, HMATH_EVAL_PREC); roundSetError(r.d); float_free(&tmp); return r; } static bool checkpn(const HNumber& p, const HNumber& n) { return n.isInteger() && !n.isNegative() && !p.isNan() && !p.isNegative() && p <= 1; } /** * Calculates the binomial discrete distribution probability mass function: * \f[X{\sim}B(n,p)\f] * \f[\Pr(X=k|n,p)={n\choose k}p^{k}(1-p)^{n-k}\f] * * \param[in] k the number of probed exact successes * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the probability of exactly \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialPmf(const HNumber& k, const HNumber& n, const HNumber& p) { if (!k.isInteger() || !checkpn(p, n)) return HMath::nan(InvalidParam); HNumber result = nCr(n, k); if (result.isZero()) return result; // special case: powers of zero, 0^0 == 1 in this context if (p.isInteger()) return (int)(p.isZero()? k.isZero() : n == k); return result * raise(p, k) * raise(HNumber(1) - p, n - k); } /** * Calculates the binomial cumulative distribution function: * \f[X{\sim}B(n,p)\f] * \f[\Pr(X \leq k|n,p)=\sum_{i=0}^{k}{n\choose i}p^{i}(1-p)^{n-i}\f] * * \param[in] k the maximum number of probed successes * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the probability of up to \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialCdf(const HNumber& k, const HNumber& n, const HNumber& p) { // FIXME: Use the regularized incomplete Beta function to avoid the potentially very expensive loop. if (!k.isInteger() || n.isNan()) return HMath::nan(); // Initiates summation, checks arguments as well. HNumber summand = binomialPmf(0, n, p); if (summand.isNan()) return summand; HNumber one(1); // Some early out results. if (k.isNegative()) return 0; if (k >= n) return one; HNumber pcompl = one - p; if (p.isInteger()) return pcompl; // use reflexion formula to limit summation if (k + k > n && k + one >= p * (n + one)) return one - binomialCdf(n - k - one, n, pcompl); // loop adding binomialPdf HNumber result(summand); for (HNumber i(0); i < k;) { summand *= p * (n-i); i += one; summand /= pcompl * i; result += summand; } return result; } /** * Calculates the expected value of a binomially distributed random variable: * \f[X{\sim}B(n,p)\f] * \f[E(X)=np\f] * * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialMean(const HNumber& n, const HNumber& p) { if (!checkpn(p, n)) return HMath::nan(); return n * p; } /** * Calculates the variance of a binomially distributed random variable: * \f[X{\sim}B(n,p)\f] * \f[Var(X)=np(1-p)\f] * * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the variance of the variable, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialVariance(const HNumber& n, const HNumber& p) { return binomialMean(n, p) * (HNumber(1) - p); } static bool checkNMn(const HNumber& N, const HNumber& M, const HNumber& n) { return N.isInteger() && !N.isNegative() && M.isInteger() && !M.isNegative() && n.isInteger() && !n.isNegative() && HMath::max(M, n) <= N; } /** * Calculates the hypergeometric discrete distribution probability mass * function: * \f[X{\sim}H(N,M,n)\f] * \f[\Pr(X=k|N,M,n)=\frac{{M\choose k}{N-M\choose n-k}}{{N\choose n}}\f] * * \param[in] k the number of probed exact successes * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the probability of exactly \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::hypergeometricPmf(const HNumber& k, const HNumber& N, const HNumber& M, const HNumber& n) { if (!k.isInteger() || !checkNMn(N, M, n)) return HMath::nan(); return HMath::nCr(M, k) * HMath::nCr(N - M, n - k) / HMath::nCr(N, n); } /** * Calculates the hypergeometric cumulative distribution function: * \f[X{\sim}H(N,M,n)\f] * \f[\Pr(X\leq k|N,M,n)= * \sum_{i=0}^{k}\frac{{M\choose k}{N-M\choose n-k}}{{N\choose n}}\f] * * \param[in] k the maximum number of probed successes * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the probability of up to \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::hypergeometricCdf(const HNumber& k, const HNumber& N, const HNumber& M, const HNumber& n) { // Lowest index of non-zero summand in loop. HNumber c = M + n - N; HNumber i = max(c, 0); // First summand in loop, do the parameter checking here. HNumber summand = HMath::hypergeometricPmf(i, N, M, n); if (!k.isInteger() || summand.isNan()) return HMath::nan(); // Some early out results. HNumber one(1); if (k >= M || k >= n) return one; if (i > k) return 0; // Use reflexion formula to limit summations. Numerically unstable where the result is near 0, disable for now. // if (k + k > n) // return one - hypergeometricCdf(n - k - 1, N, N - M, n); HNumber result = summand; for (; i < k;) { summand *= (M - i) * (n - i); i += one; summand /= i * (i - c); result += summand; } return result; } /** * Calculates the expected value of a hypergeometrically distributed random * variable: * \f[X{\sim}H(N,M,n)\f] * \f[E(X)=n\frac{M}{N}\f] * * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameter. */ HNumber HMath::hypergeometricMean(const HNumber& N, const HNumber& M, const HNumber& n) { if (!checkNMn(N, M, n)) return HMath::nan(); return n * M / N; } /** * * Calculates the variance of a hypergeometrically distributed random variable: * \f[X{\sim}H(N,M,n)\f] * \f[Var(X)=\frac{n\frac{M}{N}(1-\frac{M}{N})(N-n)}{N-1}\f] * * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the variance of the variable, otherwise \p NaN if the function is * not defined for the specified parameter. */ HNumber HMath::hypergeometricVariance(const HNumber& N, const HNumber& M, const HNumber& n) { return (hypergeometricMean(N, M, n) * (HNumber(1) - M / N) * (N - n)) / (N - HNumber(1)); } /** * * Calculates the poissonian discrete distribution probability mass function: * \f[X{\sim}P(\lambda)\f] * \f[\Pr(X=k|\lambda)=\frac{e^{-\lambda}\lambda^k}{k!}\f] * * \param[in] k the number of event occurrences * \param[in] l the expected number of occurrences that occur in an interval * * \return the probability of exactly \p k event occurrences, otherwise \p NaN * if the function is not defined for the specified parameters. */ HNumber HMath::poissonPmf(const HNumber& k, const HNumber& l) { if (!k.isInteger() || l.isNan() || l.isNegative()) return HMath::nan(); if (k.isNegative()) return 0; if (l.isZero()) return int(k.isZero()); return exp(-l) * raise(l, k) / factorial(k); } /** * Calculates the poissonian cumulative distribution function: * \f[X{\sim}P(\lambda)\f] * \f[\Pr(X\leq k|\lambda)=\sum_{i=0}^{k}\frac{e^{-\lambda}\lambda^k}{k!}\f] * * \param[in] k the maximum number of event occurrences * \param[in] l the expected number of occurrences that occur in an interval * * \return the probability of up to \p k event occurrences, otherwise \p NaN * if the function is not defined for the specified parameters. */ HNumber HMath::poissonCdf(const HNumber& k, const HNumber& l) { // FIXME: Use the incomplete gamma function to avoid a potentially expensive loop. if (!k.isInteger() || l.isNan() || l.isNegative()) return HMath::nan(); if (k.isNegative()) return 0; HNumber one(1); if (l.isZero()) return one; HNumber summand = one; HNumber result = one; for (HNumber i = one; i <= k; i += one) { summand *= l / i; result += summand; } result = exp(-l) * result; return result; } /** * Calculates the expected value of a Poisson distributed random variable: * \f[X{\sim}P(\lambda)\f] * \f[E(X)=\lambda\f] * * \param[in] l the expected number of occurrences that occur in an interval * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameter. */ HNumber HMath::poissonMean(const HNumber& l) { if (l.isNan() || l.isNegative()) return HMath::nan(); return l; } /** * Calculates the variance of a Poisson distributed random variable: * \f[X{\sim}P(\lambda)\f] * \f[Var(X)=\lambda\f] * * \param[in] l the expected number of occurrences that occur in an interval * * \return the variance of the variable, otherwise \p NaN if the function is * not defined for the specified parameter. */ HNumber HMath::poissonVariance(const HNumber& l) { return poissonMean(l); } /** * Returns the erf function (related to normal distribution). */ HNumber HMath::erf(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_erf); return result; } /** * Returns the complementary erf function (related to normal distribution). */ HNumber HMath::erfc(const HNumber& x) { HNumber result; call1Arg(result.d, x.d, float_erfc); return result; } /** * Restricts a logic value to a given bit size. */ HNumber HMath::mask(const HNumber& val, const HNumber& bits) { if (val.isNan() || bits == 0 || bits >= LOGICRANGE || !bits.isInteger()) return HMath::nan(); return val & ~(HNumber(-1) << HNumber(bits)); } /** * sign-extends an unsigned value */ HNumber HMath::sgnext(const HNumber& val, const HNumber& bits) { if (val.isNan() || bits == 0 || bits >= LOGICRANGE || !bits.isInteger()) return HMath::nan(); HNumber ofs = HNumber(LOGICRANGE) - bits; return (val << ofs) >> ofs; } /** * For bits >= 0 does an arithmetic shift right, for bits < 0 a shift left. */ HNumber HMath::ashr(const HNumber& val, const HNumber& bits) { if (val.isNan() || bits <= -LOGICRANGE || bits >= LOGICRANGE || !bits.isInteger()) return HMath::nan(); if (bits >= 0) return val >> bits; return val << -bits; } /** * Decode an IEEE-754 bit pattern with the default exponent bias */ HNumber HMath::decodeIeee754(const HNumber& val, const HNumber& exp_bits, const HNumber& significand_bits) { return HMath::decodeIeee754(val, exp_bits, significand_bits, HMath::raise(2, exp_bits - 1) - 1); } /** * Decode an IEEE-754 bit pattern with the given parameters */ HNumber HMath::decodeIeee754(const HNumber& val, const HNumber& exp_bits, const HNumber& significand_bits, const HNumber& exp_bias) { if (val.isNan() || exp_bits <= 0 || exp_bits >= LOGICRANGE || !exp_bits.isInteger() || significand_bits <= 0 || significand_bits >= LOGICRANGE || !significand_bits.isInteger() || !exp_bias.isInteger()) return HMath::nan(); HNumber sign(HMath::mask(val >> (exp_bits + significand_bits), 1).isZero() ? 1 : -1); HNumber exp = HMath::mask(val >> significand_bits, exp_bits); // <=> '0.' b_x b_x-1 b_x-2 ... b_0 HNumber significand = HMath::mask(val, significand_bits) * HMath::raise(2, -significand_bits); if (exp.isZero()) { // Exponent 0, subnormal value or zero. return sign * significand * HMath::raise(2, exp - exp_bias + 1); } if (exp - HMath::raise(2, exp_bits) == -1) { // Exponent all 1... if (significand.isZero()) // ...and signficand 0, infinity. // TODO: Represent infinity as something other than NaN? return HNumber(); // ...and significand not 0, NaN. return HMath::nan(); } return sign * (significand + 1) * HMath::raise(2, exp - exp_bias); // Normalised value. } /** * Encode a value in a IEEE-754 binary representation with the default exponent bias */ HNumber HMath::encodeIeee754(const HNumber& val, const HNumber& exp_bits, const HNumber& significand_bits) { return HMath::encodeIeee754(val, exp_bits, significand_bits, HMath::raise(2, exp_bits - 1) - 1); } /** * Encode a value in a IEEE-754 binary representation */ HNumber HMath::encodeIeee754(const HNumber& val, const HNumber& exp_bits, const HNumber& significand_bits, const HNumber& exp_bias) { if (exp_bits <= 0 || exp_bits >= LOGICRANGE || !exp_bits.isInteger() || significand_bits <= 0 || significand_bits >= LOGICRANGE || !significand_bits.isInteger() || !exp_bias.isInteger()) return HMath::nan(); HNumber sign_bit; HNumber significand; HNumber exponent; HNumber min_exp(1 - exp_bias); HNumber max_exp(HMath::raise(2, exp_bits) - 2 - exp_bias); if (val.isNan()) { // Encode a NaN. sign_bit = 0; significand = HMath::raise(2, significand_bits) - 1; exponent = HMath::raise(2, exp_bits) - 1; } else if (val.isZero()) { // Encode a basic 0. sign_bit = 0; significand = 0; exponent = 0; } else { // Regular input value. sign_bit = val.isNegative() ? 1 : 0; // Determine exponent. HNumber search_min = min_exp; HNumber search_max = max_exp; exponent = HMath::ceil((search_max - search_min) / 2) + search_min; significand = HMath::abs(val) * HMath::raise(2, -exponent); do { if (significand >= 1 && significand < 2) { // Integer part is 1, stop here. break; } else if (significand >= 2) { // Increase exponent. search_min = exponent + 1; } else if (significand < 1) { // Decrease exponent. search_max = exponent - 1; } exponent = HMath::ceil((search_max - search_min) / 2) + search_min; significand = HMath::abs(val) * HMath::raise(2, -exponent); } while (exponent != min_exp && exponent != max_exp); HNumber rounded = HMath::round(significand * HMath::raise(2, significand_bits)); HNumber intpart = HMath::integer(rounded * HMath::raise(2, -significand_bits)); significand = HMath::mask(rounded, significand_bits); if (intpart.isZero()) { // Subnormal value. exponent = 0; } else if (intpart > 1) { // Round-to-nearest carry into the implicit leading bit. exponent = exponent + 1; significand = 0; // Infinity only if the rounded exponent overflows the representable range. if (exponent > max_exp) exponent = HMath::raise(2, exp_bits) - 1; else exponent = exponent + exp_bias; } else { // Normalised value. exponent = exponent + exp_bias; } } HNumber result = sign_bit << (exp_bits + significand_bits) | exponent << (significand_bits) | significand; return result; } std::ostream& operator<<(std::ostream& s, const HNumber& n) { QString str = HMath::format(n); s << str.toLatin1().constData(); return s; } struct MathInit { MathInit(){ floatmath_init(); } }; MathInit mathinit; /** * Parses a string containing a real number. * * Parameters : * str_in : pointer towards the string to parse * str_out : pointer towards a pointer towards the remaining of the string after parsing */ HNumber HMath::parse_str(const char* str_in, const char** str_out) { // FIXME: Duplicate code. // FIXME: Error management. const char* str = str_in; t_itokens tokens; HNumber x; delete x.d; x.d = new HNumberPrivate; if ((x.d->error = parse(&tokens, &str)) == Success) x.d->error = float_in(&x.d->fnum, &tokens); float_geterror(); /* Store remaining of the string */ if (str_out) *str_out = str; return x; } bool HNumber::isNearZero() const { return float_iszero(&(d->fnum)) || float_getexponent(&(d->fnum)) <= -80; } heldercorreia-speedcrunch-e7ca37f/src/math/hmath.h000066400000000000000000000201531526573132500223300ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2007-2010, 2015-2016, 2018, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef MATH_HMATH_H #define MATH_HMATH_H #include "core/errors.h" #include #include #include class HMath; class HNumberPrivate; class CNumber; class CMath; class Rational; class HNumber { friend class HMath; friend class CNumber; friend class CMath; friend HNumber operator-(const HNumber&); friend HNumber operator-(const HNumber&, const HNumber&); friend bool operator>(const HNumber&, const HNumber&); friend bool operator<(const HNumber&, const HNumber&); friend bool operator>=(const HNumber&, const HNumber&); friend bool operator<=(const HNumber&, const HNumber&); friend bool operator==(const HNumber&, const HNumber&); friend bool operator!=(const HNumber&, const HNumber&); public: HNumber(); HNumber(const HNumber&); HNumber(int); HNumber(const char*); HNumber(const QJsonObject&); ~HNumber(); bool isNan() const; bool isZero() const; bool isNearZero() const; bool isPositive() const; bool isNegative() const; bool isInteger() const; void serialize(QJsonObject&) const; static HNumber deSerialize(const QJsonObject&); int toInt() const; Error error() const; HNumber& operator=(const HNumber&); HNumber operator+(const HNumber&) const; HNumber& operator+=(const HNumber&); HNumber& operator-=(const HNumber&); HNumber operator*(const HNumber&) const; HNumber& operator*=(const HNumber&); HNumber operator/(const HNumber&) const; HNumber& operator/=(const HNumber&); HNumber operator%(const HNumber&) const; HNumber operator&(const HNumber&) const; HNumber& operator&=(const HNumber&); HNumber operator|(const HNumber&) const; HNumber& operator|=(const HNumber&); HNumber operator^(const HNumber&) const; HNumber& operator^=(const HNumber&); HNumber operator~() const; HNumber operator>>(const HNumber&) const; HNumber operator<<(const HNumber&) const; private: HNumberPrivate* d; int compare(const HNumber&) const; public: struct Format { enum class Base {Null, Binary, Decimal, Octal, Hexadecimal}; enum class RadixChar {Null, Point, Comma}; enum class Mode {Null, General, Fixed, Scientific, Engineering, Sexagesimal}; Base base; RadixChar radixChar; Mode mode; int precision; // -1 means 'auto' // Display-only choice, applied after rounding to the requested precision. bool removeTrailingZeroes = false; // 0 disables integer-part padding. Positive values pad to at least this many bits. // -1 pads to the next multiple of 8 bits. int paddedBits; // Keeps exponent selection automatic when set to ForcedExponentNull. int forcedExponent; static const int PrecisionNull = -1000; static const int PaddedBitsAutoByte = -1; static const int ForcedExponentNull = -2147483647 - 1; Format(); Format(const Format&); Format operator+(const Format&) const; static Format Binary(); static Format Octal(); static Format Decimal(); static Format Hexadecimal(); static Format Precision(int); static Format Point(); static Format Comma(); static Format General(); static Format Fixed(); static Format Scientific(); static Format Engineering(); static Format ForcedExponent(int exponent); static Format Sexagesimal(); static Format PadBits(int bits); static Format PadToByteBoundary(); }; }; class HMath { public: // FORMAT static QString format(const HNumber&, HNumber::Format = HNumber::Format()); // PARSING static HNumber parse_str(const char*, const char** out); // CONSTANTS static HNumber e(); static HNumber phi(); static HNumber pi(); static HNumber nan(Error = Success); // GENERAL MATH static HNumber rad2deg(const HNumber&); static HNumber deg2rad(const HNumber&); static HNumber rad2gon(const HNumber&); static HNumber gon2rad(const HNumber&); static HNumber max(const HNumber&, const HNumber&); static HNumber min(const HNumber&, const HNumber&); static HNumber abs(const HNumber&); static HNumber integer(const HNumber&); static HNumber frac(const HNumber&); static HNumber floor(const HNumber&); static HNumber ceil(const HNumber&); static HNumber gcd(const HNumber&, const HNumber&); static HNumber lcm(const HNumber&, const HNumber&); static HNumber idiv(const HNumber&, const HNumber&); static HNumber round(const HNumber&, int prec = 0); static HNumber trunc(const HNumber&, int prec = 0); static HNumber sqrt(const HNumber&); static HNumber cbrt(const HNumber&); static HNumber raise(const HNumber&, int); static HNumber raise(const HNumber&, const HNumber&); static HNumber sgn(const HNumber&); // EXPONENTIAL FUNCTION AND RELATED static HNumber exp(const HNumber&); static HNumber ln(const HNumber&); static HNumber lg(const HNumber&); static HNumber lb(const HNumber&); static HNumber log(const HNumber& base, const HNumber& x); static HNumber sinh(const HNumber&); static HNumber cosh(const HNumber&); static HNumber tanh(const HNumber&); static HNumber arsinh(const HNumber&); static HNumber arcosh(const HNumber&); static HNumber artanh(const HNumber&); // TRIGONOMETRY static HNumber sin(const HNumber&); static HNumber cos(const HNumber&); static HNumber tan(const HNumber&); static HNumber cot(const HNumber&); static HNumber sec(const HNumber&); static HNumber csc(const HNumber&); static HNumber arcsin(const HNumber&); static HNumber arccos(const HNumber&); static HNumber arctan(const HNumber&); static HNumber arctan2(const HNumber&, const HNumber&); // HIGHER MATH FUNCTIONS static HNumber factorial(const HNumber&, const HNumber& base = HNumber(1)); static HNumber gamma(const HNumber&); static HNumber lnGamma(const HNumber&); static HNumber erf(const HNumber&); static HNumber erfc(const HNumber&); // PROBABILITY static HNumber nCr(const HNumber& n, const HNumber& k); static HNumber nPr(const HNumber& n, const HNumber& r); static HNumber binomialPmf(const HNumber& k, const HNumber& n, const HNumber& p); static HNumber binomialCdf(const HNumber& k, const HNumber& n, const HNumber& p); static HNumber binomialMean(const HNumber& n, const HNumber& p); static HNumber binomialVariance(const HNumber& n, const HNumber& p); static HNumber hypergeometricPmf(const HNumber& k, const HNumber& N, const HNumber& M, const HNumber& n); static HNumber hypergeometricCdf(const HNumber& k, const HNumber& N, const HNumber& M, const HNumber& n); static HNumber hypergeometricMean(const HNumber& N, const HNumber& M, const HNumber& n); static HNumber hypergeometricVariance(const HNumber& N, const HNumber& M, const HNumber& n); static HNumber poissonPmf(const HNumber& k, const HNumber& l); static HNumber poissonCdf(const HNumber& k, const HNumber& l); static HNumber poissonMean(const HNumber& l); static HNumber poissonVariance(const HNumber& l); // LOGIC static HNumber mask(const HNumber&, const HNumber& bits); static HNumber sgnext(const HNumber&, const HNumber& bits); static HNumber ashr(const HNumber&, const HNumber& bits); // IEEE-754 CONVERSION static HNumber decodeIeee754(const HNumber&, const HNumber& exp_bits, const HNumber& significand_bits); static HNumber decodeIeee754(const HNumber&, const HNumber& exp_bits, const HNumber& significand_bits, const HNumber& exp_bias); static HNumber encodeIeee754(const HNumber&, const HNumber& exp_bits, const HNumber& significand_bits); static HNumber encodeIeee754(const HNumber&, const HNumber& exp_bits, const HNumber& significand_bits, const HNumber& exp_bias); }; std::ostream& operator<<(std::ostream&, const HNumber&); #endif // MATH_HMATH_H heldercorreia-speedcrunch-e7ca37f/src/math/number.c000066400000000000000000001215361526573132500225210ustar00rootroot00000000000000/* number.c: Implements arbitrary precision numbers. */ /* Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: philnelson@acm.org us-mail: Philip A. Nelson Computer Science Department, 9062 Western Washington University Bellingham, WA 98226-9062 !!!This is a patched file, the original file from bc 1.06 contains bugs in (a) bc_divide and (b) bc_int2num. A patch is applied here by Wolf Lammen, Oertzweg 45, 22307 Hamburg email ookami1 gmx de One patched line fixes a nasty bug, where a division by 1 may fail occasionly when an operand is overwritten by the result. The other one lets a conversion of an integer succeed, even if the most negative integer is passed as argument *************************************************************************/ #include "number.h" #include #include #include #include #include /* Prototypes needed for external utility routines. */ #define bc_rt_warn rt_warn #define bc_rt_error rt_error #define bc_out_of_memory out_of_memory _PROTOTYPE(void rt_warn, (char *mesg ,...)); _PROTOTYPE(void rt_error, (char *mesg ,...)); _PROTOTYPE(void out_of_memory, (void)); void out_of_memory(void){ return; } void rt_warn(char *mesg ,...){ (void)mesg; return; } void rt_error(char *mesg ,...){ (void)mesg; return; } /* Storage used for special numbers. */ bc_num _zero_; bc_num _one_; bc_num _two_; static bc_num _bc_Free_list = NULL; /* new_num allocates a number and sets fields to known values. */ bc_num bc_new_num (int length, int scale) { bc_num temp; if (_bc_Free_list != NULL) { temp = _bc_Free_list; _bc_Free_list = temp->n_next; } else { temp = (bc_num) malloc (sizeof(bc_struct)); if (temp == NULL) bc_out_of_memory (); } temp->n_sign = PLUS; temp->n_len = length; temp->n_scale = scale; temp->n_refs = 1; temp->n_ptr = (char *) malloc (length+scale+1); if (temp->n_ptr == NULL) bc_out_of_memory(); temp->n_value = temp->n_ptr; memset (temp->n_ptr, 0, length+scale); return temp; } /* "Frees" a bc_num NUM. Actually decreases reference count and only frees the storage if reference count is zero. */ void bc_free_num (bc_num *num) { if (*num == NULL) return; (*num)->n_refs--; if ((*num)->n_refs == 0) { if ((*num)->n_ptr) free ((*num)->n_ptr); (*num)->n_next = _bc_Free_list; _bc_Free_list = *num; } *num = NULL; } /* Intitialize the number package! */ void bc_init_numbers (void) { _zero_ = bc_new_num (1,0); _one_ = bc_new_num (1,0); _one_->n_value[0] = 1; _two_ = bc_new_num (1,0); _two_->n_value[0] = 2; } /* Make a copy of a number! Just increments the reference count! */ bc_num bc_copy_num (bc_num num) { num->n_refs++; return num; } /* Initialize a number NUM by making it a copy of zero. */ void bc_init_num (bc_num *num) { *num = bc_copy_num (_zero_); } /* For many things, we may have leading zeros in a number NUM. _bc_rm_leading_zeros just moves the data "value" pointer to the correct place and adjusts the length. */ static void _bc_rm_leading_zeros (bc_num num) { /* We can move n_value to point to the first non zero digit! */ while (*num->n_value == 0 && num->n_len > 1) { num->n_value++; num->n_len--; } } /* Compare two bc numbers. Return value is 0 if equal, -1 if N1 is less than N2 and +1 if N1 is greater than N2. If USE_SIGN is false, just compare the magnitudes. */ static int _bc_do_compare (bc_num n1, bc_num n2, int use_sign, int ignore_last) { char *n1ptr, *n2ptr; int count; /* First, compare signs. */ if (use_sign && n1->n_sign != n2->n_sign) { if (n1->n_sign == PLUS) return (1); /* Positive N1 > Negative N2 */ else return (-1); /* Negative N1 < Positive N1 */ } /* Now compare the magnitude. */ if (n1->n_len != n2->n_len) { if (n1->n_len > n2->n_len) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } else { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } /* If we get here, they have the same number of integer digits. check the integer part and the equal length part of the fraction. */ count = n1->n_len + MIN (n1->n_scale, n2->n_scale); n1ptr = n1->n_value; n2ptr = n2->n_value; while ((count > 0) && (*n1ptr == *n2ptr)) { n1ptr++; n2ptr++; count--; } if (ignore_last && count == 1 && n1->n_scale == n2->n_scale) return (0); if (count != 0) { if (*n1ptr > *n2ptr) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } else { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } /* They are equal up to the last part of the equal part of the fraction. */ if (n1->n_scale != n2->n_scale) { if (n1->n_scale > n2->n_scale) { for (count = n1->n_scale-n2->n_scale; count>0; count--) if (*n1ptr++ != 0) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } } else { for (count = n2->n_scale-n1->n_scale; count>0; count--) if (*n2ptr++ != 0) { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } } /* They must be equal! */ return (0); } /* This is the "user callable" routine to compare numbers N1 and N2. */ int bc_compare (bc_num n1, bc_num n2) { return _bc_do_compare (n1, n2, TRUE, FALSE); } /* In some places we need to check if the number is negative. */ char bc_is_neg (bc_num num) { return num->n_sign == MINUS; } /* In some places we need to check if the number NUM is zero. */ char bc_is_zero (bc_num num) { int count; char *nptr; /* Quick check. */ if (num == _zero_) return TRUE; /* Initialize */ count = num->n_len + num->n_scale; nptr = num->n_value; /* The check */ while ((count > 0) && (*nptr++ == 0)) count--; if (count != 0) return FALSE; else return TRUE; } /* In some places we need to check if the number NUM is almost zero. Specifically, all but the last digit is 0 and the last digit is 1. Last digit is defined by scale. */ char bc_is_near_zero (bc_num num, int scale) { int count; char *nptr; /* Error checking */ if (scale > num->n_scale) scale = num->n_scale; /* Initialize */ count = num->n_len + scale; nptr = num->n_value; /* The check */ while ((count > 0) && (*nptr++ == 0)) count--; if (count != 0 && (count != 1 || *--nptr != 1)) return FALSE; else return TRUE; } /* Perform addition: N1 is added to N2 and the value is returned. The signs of N1 and N2 are ignored. SCALE_MIN is to set the minimum scale of the result. */ static bc_num _bc_do_add (bc_num n1, bc_num n2, int scale_min) { bc_num sum; int sum_scale, sum_digits; char *n1ptr, *n2ptr, *sumptr; int carry, n1bytes, n2bytes; int count; /* Prepare sum. */ sum_scale = MAX (n1->n_scale, n2->n_scale); sum_digits = MAX (n1->n_len, n2->n_len) + 1; sum = bc_new_num (sum_digits, MAX(sum_scale, scale_min)); /* Zero extra digits made by scale_min. */ if (scale_min > sum_scale) { sumptr = (char *) (sum->n_value + sum_scale + sum_digits); for (count = scale_min - sum_scale; count > 0; count--) *sumptr++ = 0; } /* Start with the fraction part. Initialize the pointers. */ n1bytes = n1->n_scale; n2bytes = n2->n_scale; n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1); n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1); sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1); /* Add the fraction part. First copy the longer fraction.*/ if (n1bytes != n2bytes) { if (n1bytes > n2bytes) while (n1bytes>n2bytes) { *sumptr-- = *n1ptr--; n1bytes--;} else while (n2bytes>n1bytes) { *sumptr-- = *n2ptr--; n2bytes--;} } /* Now add the remaining fraction part and equal size integer parts. */ n1bytes += n1->n_len; n2bytes += n2->n_len; carry = 0; while ((n1bytes > 0) && (n2bytes > 0)) { *sumptr = (char)(*n1ptr-- + *n2ptr-- + carry); if (*sumptr > (BASE-1)) { carry = 1; *sumptr -= BASE; } else carry = 0; sumptr--; n1bytes--; n2bytes--; } /* Now add carry the longer integer part. */ if (n1bytes == 0) { n1bytes = n2bytes; n1ptr = n2ptr; } while (n1bytes-- > 0) { *sumptr = (char)(*n1ptr-- + carry); if (*sumptr > (BASE-1)) { carry = 1; *sumptr -= BASE; } else carry = 0; sumptr--; } /* Set final carry. */ if (carry == 1) *sumptr += 1; /* Adjust sum and return. */ _bc_rm_leading_zeros (sum); return sum; } /* Perform subtraction: N2 is subtracted from N1 and the value is returned. The signs of N1 and N2 are ignored. Also, N1 is assumed to be larger than N2. SCALE_MIN is the minimum scale of the result. */ static bc_num _bc_do_sub (bc_num n1, bc_num n2, int scale_min) { bc_num diff; int diff_scale, diff_len; int min_scale, min_len; char *n1ptr, *n2ptr, *diffptr; int borrow, count, val; /* Allocate temporary storage. */ diff_len = MAX (n1->n_len, n2->n_len); diff_scale = MAX (n1->n_scale, n2->n_scale); min_len = MIN (n1->n_len, n2->n_len); min_scale = MIN (n1->n_scale, n2->n_scale); diff = bc_new_num (diff_len, MAX(diff_scale, scale_min)); /* Zero extra digits made by scale_min. */ if (scale_min > diff_scale) { diffptr = (char *) (diff->n_value + diff_len + diff_scale); for (count = scale_min - diff_scale; count > 0; count--) *diffptr++ = 0; } /* Initialize the subtract. */ n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1); n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1); diffptr = (char *) (diff->n_value + diff_len + diff_scale -1); /* Subtract the numbers. */ borrow = 0; /* Take care of the longer scaled number. */ if (n1->n_scale != min_scale) { /* n1 has the longer scale */ for (count = n1->n_scale - min_scale; count > 0; count--) *diffptr-- = *n1ptr--; } else { /* n2 has the longer scale */ for (count = n2->n_scale - min_scale; count > 0; count--) { val = - *n2ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = (char)val; } } /* Now do the equal length scale and integer parts. */ for (count = 0; count < min_len + min_scale; count++) { val = *n1ptr-- - *n2ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = (char)val; } /* If n1 has more digits then n2, we now do that subtract. */ if (diff_len != min_len) { for (count = diff_len - min_len; count > 0; count--) { val = *n1ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = (char)val; } } /* Clean up and return. */ _bc_rm_leading_zeros (diff); return diff; } /* Here is the full subtract routine that takes care of negative numbers. N2 is subtracted from N1 and the result placed in RESULT. SCALE_MIN is the minimum scale for the result. */ void bc_sub (bc_num n1, bc_num n2, bc_num *result, int scale_min) { bc_num diff = NULL; int cmp_res; int res_scale; if (n1->n_sign != n2->n_sign) { diff = _bc_do_add (n1, n2, scale_min); diff->n_sign = n1->n_sign; } else { /* subtraction must be done. */ /* Compare magnitudes. */ cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); switch (cmp_res) { case -1: /* n1 is less than n2, subtract n1 from n2. */ diff = _bc_do_sub (n2, n1, scale_min); diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS); break; case 0: /* They are equal! return zero! */ res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); diff = bc_new_num (1, res_scale); memset (diff->n_value, 0, res_scale+1); break; case 1: /* n2 is less than n1, subtract n2 from n1. */ diff = _bc_do_sub (n1, n2, scale_min); diff->n_sign = n1->n_sign; break; } } /* Clean up and return. */ bc_free_num (result); *result = diff; } /* Here is the full add routine that takes care of negative numbers. N1 is added to N2 and the result placed into RESULT. SCALE_MIN is the minimum scale for the result. */ void bc_add (bc_num n1, bc_num n2, bc_num *result, int scale_min) { bc_num sum = NULL; int cmp_res; int res_scale; if (n1->n_sign == n2->n_sign) { sum = _bc_do_add (n1, n2, scale_min); sum->n_sign = n1->n_sign; } else { /* subtraction must be done. */ cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); /* Compare magnitudes. */ switch (cmp_res) { case -1: /* n1 is less than n2, subtract n1 from n2. */ sum = _bc_do_sub (n2, n1, scale_min); sum->n_sign = n2->n_sign; break; case 0: /* They are equal! return zero with the correct scale! */ res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); sum = bc_new_num (1, res_scale); memset (sum->n_value, 0, res_scale+1); break; case 1: /* n2 is less than n1, subtract n2 from n1. */ sum = _bc_do_sub (n1, n2, scale_min); sum->n_sign = n1->n_sign; } } /* Clean up and return. */ bc_free_num (result); *result = sum; } /* Recursive vs non-recursive multiply crossover ranges. */ #if defined(MULDIGITS) #include "muldigits.h" #else #define MUL_BASE_DIGITS 80 #endif int mul_base_digits = MUL_BASE_DIGITS; #define MUL_SMALL_DIGITS mul_base_digits/4 /* Multiply utility routines */ static bc_num new_sub_num (int length, int scale, char *value) { bc_num temp; if (_bc_Free_list != NULL) { temp = _bc_Free_list; _bc_Free_list = temp->n_next; } else { temp = (bc_num) malloc (sizeof(bc_struct)); if (temp == NULL) bc_out_of_memory (); } temp->n_sign = PLUS; temp->n_len = length; temp->n_scale = scale; temp->n_refs = 1; temp->n_ptr = NULL; temp->n_value = value; return temp; } static void _bc_simp_mul (bc_num n1, int n1len, bc_num n2, int n2len, bc_num *prod, int full_scale) { char *n1ptr, *n2ptr, *pvptr; char *n1end, *n2end; /* To the end of n1 and n2. */ int indx, sum; const int prodlen = n1len + n2len + 1; (void)full_scale; *prod = bc_new_num (prodlen, 0); n1end = (char *) (n1->n_value + n1len - 1); n2end = (char *) (n2->n_value + n2len - 1); pvptr = (char *) ((*prod)->n_value + prodlen - 1); sum = 0; /* Here is the loop... */ for (indx = 0; indx < prodlen-1; indx++) { n1ptr = (char *) (n1end - MAX(0, indx-n2len+1)); n2ptr = (char *) (n2end - MIN(indx, n2len-1)); while ((n1ptr >= n1->n_value) && (n2ptr <= n2end)) sum += *n1ptr-- * *n2ptr++; *pvptr-- = sum % BASE; sum = sum / BASE; } *pvptr = (char)sum; } /* A special adder/subtractor for the recursive divide and conquer multiply algorithm. Note: if sub is called, accum must be larger that what is being subtracted. Also, accum and val must have n_scale = 0. (e.g. they must look like integers. *) */ static void _bc_shift_addsub (bc_num accum, bc_num val, int shift, int sub) { signed char *accp, *valp; int count, carry; count = val->n_len; if (val->n_value[0] == 0) count--; assert (accum->n_len+accum->n_scale >= shift+count); /* Set up pointers and others */ accp = (signed char *)(accum->n_value + accum->n_len + accum->n_scale - shift - 1); valp = (signed char *)(val->n_value + val->n_len - 1); carry = 0; if (sub) { /* Subtraction, carry is really borrow. */ while (count--) { *accp = (signed char)(*accp - (*valp-- + carry)); if (*accp < 0) { carry = 1; *accp-- += BASE; } else { carry = 0; accp--; } } while (carry) { *accp = (signed char)(*accp - carry); if (*accp < 0) *accp-- += BASE; else carry = 0; } } else { /* Addition */ while (count--) { *accp = (signed char)(*accp + (*valp-- + carry)); if (*accp > (BASE-1)) { carry = 1; *accp-- -= BASE; } else { carry = 0; accp--; } } while (carry) { *accp = (signed char)(*accp + carry); if (*accp > (BASE-1)) *accp-- -= BASE; else carry = 0; } } } /* Recursive divide and conquer multiply algorithm. Based on Let u = u0 + u1*(b^n) Let v = v0 + v1*(b^n) Then uv = (B^2n+B^n)*u1*v1 + B^n*(u1-u0)*(v0-v1) + (B^n+1)*u0*v0 B is the base of storage, number of digits in u1,u0 close to equal. */ static void _bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod, int full_scale) { bc_num u0, u1, v0, v1; /*int u0len, v0len;*/ bc_num m1, m2, m3, d1, d2; int n, prodlen, m1zero; int d1len, d2len; /* Base case? */ if ((ulen+vlen) < mul_base_digits || ulen < MUL_SMALL_DIGITS || vlen < MUL_SMALL_DIGITS ) { _bc_simp_mul (u, ulen, v, vlen, prod, full_scale); return; } /* Calculate n -- the u and v split point in digits. */ n = (MAX(ulen, vlen)+1) / 2; /* Split u and v. */ if (ulen < n) { u1 = bc_copy_num (_zero_); u0 = new_sub_num (ulen,0, u->n_value); } else { u1 = new_sub_num (ulen-n, 0, u->n_value); u0 = new_sub_num (n, 0, u->n_value+ulen-n); } if (vlen < n) { v1 = bc_copy_num (_zero_); v0 = new_sub_num (vlen,0, v->n_value); } else { v1 = new_sub_num (vlen-n, 0, v->n_value); v0 = new_sub_num (n, 0, v->n_value+vlen-n); } _bc_rm_leading_zeros (u1); _bc_rm_leading_zeros (u0); /*u0len = u0->n_len;*/ _bc_rm_leading_zeros (v1); _bc_rm_leading_zeros (v0); /*v0len = v0->n_len;*/ m1zero = bc_is_zero(u1) || bc_is_zero(v1); /* Calculate sub results ... */ bc_init_num(&d1); bc_init_num(&d2); bc_sub (u1, u0, &d1, 0); d1len = d1->n_len; bc_sub (v0, v1, &d2, 0); d2len = d2->n_len; /* Do recursive multiplies and shifted adds. */ if (m1zero) m1 = bc_copy_num (_zero_); else _bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1, 0); if (bc_is_zero(d1) || bc_is_zero(d2)) m2 = bc_copy_num (_zero_); else _bc_rec_mul (d1, d1len, d2, d2len, &m2, 0); if (bc_is_zero(u0) || bc_is_zero(v0)) m3 = bc_copy_num (_zero_); else _bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3, 0); /* Initialize product */ prodlen = ulen+vlen+1; *prod = bc_new_num(prodlen, 0); if (!m1zero) { _bc_shift_addsub (*prod, m1, 2*n, 0); _bc_shift_addsub (*prod, m1, n, 0); } _bc_shift_addsub (*prod, m3, n, 0); _bc_shift_addsub (*prod, m3, 0, 0); _bc_shift_addsub (*prod, m2, n, d1->n_sign != d2->n_sign); /* Now clean up! */ bc_free_num (&u1); bc_free_num (&u0); bc_free_num (&v1); bc_free_num (&m1); bc_free_num (&v0); bc_free_num (&m2); bc_free_num (&m3); bc_free_num (&d1); bc_free_num (&d2); } /* The multiply routine. N2 times N1 is put int PROD with the scale of the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)). */ void bc_multiply (bc_num n1, bc_num n2, bc_num *prod, int scale) { bc_num pval; int len1, len2; int full_scale, prod_scale; /* Initialize things. */ len1 = n1->n_len + n1->n_scale; len2 = n2->n_len + n2->n_scale; full_scale = n1->n_scale + n2->n_scale; prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale))); /* Do the multiply */ _bc_rec_mul (n1, len1, n2, len2, &pval, full_scale); /* Assign to prod and clean up the number. */ pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); pval->n_value = pval->n_ptr; pval->n_len = len2 + len1 + 1 - full_scale; pval->n_scale = prod_scale; _bc_rm_leading_zeros (pval); if (bc_is_zero (pval)) pval->n_sign = PLUS; bc_free_num (prod); *prod = pval; } /* Some utility routines for the divide: First a one digit multiply. NUM (with SIZE digits) is multiplied by DIGIT and the result is placed into RESULT. It is written so that NUM and RESULT can be the same pointers. */ static void _one_mult (unsigned char *num, int size, int digit, unsigned char *result) { int carry, value; unsigned char *nptr, *rptr; if (digit == 0) memset (result, 0, size); else { if (digit == 1) memcpy (result, num, size); else { /* Initialize */ nptr = (unsigned char *) (num+size-1); rptr = (unsigned char *) (result+size-1); carry = 0; while (size-- > 0) { value = *nptr-- * digit + carry; *rptr-- = value % BASE; carry = value / BASE; } if (carry != 0) *rptr = (unsigned char)carry; } } } /* The full division routine. This computes N1 / N2. It returns 0 if the division is ok and the result is in QUOT. The number of digits after the decimal point is SCALE. It returns -1 if division by zero is tried. The algorithm is found in Knuth Vol 2. p237. */ int bc_divide (bc_num n1, bc_num n2, bc_num *quot, int scale) { bc_num qval; unsigned char *num1, *num2; unsigned char *ptr1, *ptr2, *n2ptr, *qptr; int scale1, val; unsigned int len1, len2, scale2, qdigits, extra, count; unsigned int qdig, qguess, borrow, carry; unsigned char *mval; char zero; unsigned int norm; /* Test for divide by zero. */ if (bc_is_zero (n2)) return -1; /* Test for divide by 1. If it is we must truncate. */ if (n2->n_scale == 0) { if (n2->n_len == 1 && *n2->n_value == 1) { qval = bc_new_num (n1->n_len, scale); qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS); memset (&qval->n_value[n1->n_len],0,scale); memcpy (qval->n_value, n1->n_value, n1->n_len + MIN(n1->n_scale,scale)); bc_free_num (quot); *quot = qval; return 0; /* bug fix Wolf Lammen */ } } /* Set up the divide. Move the decimal point on n1 by n2's scale. Remember, zeros on the end of num2 are wasted effort for dividing. */ scale2 = n2->n_scale; n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1; while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--; len1 = n1->n_len + scale2; scale1 = n1->n_scale - scale2; if (scale1 < scale) extra = scale - scale1; else extra = 0; num1 = (unsigned char *) malloc (n1->n_len+n1->n_scale+extra+2); if (num1 == NULL) bc_out_of_memory(); memset (num1, 0, n1->n_len+n1->n_scale+extra+2); memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale); len2 = n2->n_len + scale2; num2 = (unsigned char *) malloc (len2+1); if (num2 == NULL) bc_out_of_memory(); memcpy (num2, n2->n_value, len2); *(num2+len2) = 0; n2ptr = num2; while (*n2ptr == 0) { n2ptr++; len2--; } /* Calculate the number of quotient digits. */ if (len2 > len1+scale) { qdigits = scale+1; zero = TRUE; } else { zero = FALSE; if (len2>len1) qdigits = scale+1; /* One for the zero integer part. */ else qdigits = len1-len2+scale+1; } /* Allocate and zero the storage for the quotient. */ qval = bc_new_num (qdigits-scale,scale); memset (qval->n_value, 0, qdigits); /* Allocate storage for the temporary storage mval. */ mval = (unsigned char *) malloc (len2+1); if (mval == NULL) bc_out_of_memory (); /* Now for the full divide algorithm. */ if (!zero) { /* Normalize */ norm = 10 / ((int)*n2ptr + 1); if (norm != 1) { _one_mult (num1, len1+scale1+extra+1, norm, num1); _one_mult (n2ptr, len2, norm, n2ptr); } /* Initialize divide loop. */ qdig = 0; if (len2 > len1) qptr = (unsigned char *) qval->n_value+len2-len1; else qptr = (unsigned char *) qval->n_value; /* Loop */ while (qdig <= len1+scale-len2) { /* Calculate the quotient digit guess. */ if (*n2ptr == num1[qdig]) qguess = 9; else qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr; /* Test qguess. */ if (n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]) { qguess--; /* And again. */ if (n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]) qguess--; } /* Multiply and subtract. */ borrow = 0; if (qguess != 0) { *mval = 0; _one_mult (n2ptr, len2, qguess, mval+1); ptr1 = (unsigned char *) num1+qdig+len2; ptr2 = (unsigned char *) mval+len2; for (count = 0; count < len2+1; count++) { val = (int) *ptr1 - (int) *ptr2-- - borrow; if (val < 0) { val += 10; borrow = 1; } else borrow = 0; *ptr1-- = (unsigned char)val; } } /* Test for negative result. */ if (borrow == 1) { qguess--; ptr1 = (unsigned char *) num1+qdig+len2; ptr2 = (unsigned char *) n2ptr+len2-1; carry = 0; for (count = 0; count < len2; count++) { val = (int) *ptr1 + (int) *ptr2-- + carry; if (val > 9) { val -= 10; carry = 1; } else carry = 0; *ptr1-- = (unsigned char)val; } if (carry == 1) *ptr1 = (*ptr1 + 1) % 10; } /* We now know the quotient digit. */ *qptr++ = (unsigned char)qguess; qdig++; } } /* Clean up and return the number. */ qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); if (bc_is_zero (qval)) qval->n_sign = PLUS; _bc_rm_leading_zeros (qval); bc_free_num (quot); *quot = qval; /* Clean up temporary storage. */ free (mval); free (num1); free (num2); return 0; /* Everything is OK. */ } /* Division *and* modulo for numbers. This computes both NUM1 / NUM2 and NUM1 % NUM2 and puts the results in QUOT and REM, except that if QUOT is NULL then that store will be omitted. */ int bc_divmod (bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, int scale) { bc_num quotient = NULL; bc_num temp; int rscale; /* Check for correct numbers. */ if (bc_is_zero (num2)) return -1; /* Calculate final scale. */ rscale = MAX (num1->n_scale, num2->n_scale+scale); bc_init_num(&temp); /* Calculate it. */ bc_divide (num1, num2, &temp, scale); if (quot) quotient = bc_copy_num (temp); bc_multiply (temp, num2, &temp, rscale); bc_sub (num1, temp, rem, rscale); bc_free_num (&temp); if (quot) { bc_free_num (quot); *quot = quotient; } return 0; /* Everything is OK. */ } /* Modulo for numbers. This computes NUM1 % NUM2 and puts the result in RESULT. */ int bc_modulo (bc_num num1, bc_num num2, bc_num *result, int scale) { return bc_divmod (num1, num2, NULL, result, scale); } /* Raise BASE to the EXPO power, reduced modulo MOD. The result is placed in RESULT. If a EXPO is not an integer, only the integer part is used. */ int bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) { bc_num power, exponent, parity, temp; int rscale; /* Check for correct numbers. */ if (bc_is_zero(mod)) return -1; if (bc_is_neg(expo)) return -1; /* Set initial values. */ power = bc_copy_num (base); exponent = bc_copy_num (expo); temp = bc_copy_num (_one_); bc_init_num(&parity); /* Check the base for scale digits. */ if (base->n_scale != 0) bc_rt_warn ("non-zero scale in base"); /* Check the exponent for scale digits. */ if (exponent->n_scale != 0) { bc_rt_warn ("non-zero scale in exponent"); bc_divide (exponent, _one_, &exponent, 0); /*truncate */ } /* Check the modulus for scale digits. */ if (mod->n_scale != 0) bc_rt_warn ("non-zero scale in modulus"); /* Do the calculation. */ rscale = MAX(scale, base->n_scale); while ( !bc_is_zero(exponent) ) { (void) bc_divmod (exponent, _two_, &exponent, &parity, 0); if ( !bc_is_zero(parity) ) { bc_multiply (temp, power, &temp, rscale); (void) bc_modulo (temp, mod, &temp, scale); } bc_multiply (power, power, &power, rscale); (void) bc_modulo (power, mod, &power, scale); } /* Assign the value. */ bc_free_num (&power); bc_free_num (&exponent); bc_free_num (result); *result = temp; return 0; /* Everything is OK. */ } /* Raise NUM1 to the NUM2 power. The result is placed in RESULT. Maximum exponent is LONG_MAX. If a NUM2 is not an integer, only the integer part is used. */ void bc_raise (bc_num num1, bc_num num2, bc_num *result, int scale) { bc_num temp, power; long exponent; int rscale; int pwrscale; int calcscale; char neg; /* Check the exponent for scale digits and convert to a long. */ if (num2->n_scale != 0) bc_rt_warn ("non-zero scale in exponent"); exponent = bc_num2long (num2); if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0)) bc_rt_error ("exponent too large in raise"); /* Special case if exponent is a zero. */ if (exponent == 0) { bc_free_num (result); *result = bc_copy_num (_one_); return; } /* Other initializations. */ if (exponent < 0) { neg = TRUE; exponent = -exponent; rscale = scale; } else { neg = FALSE; rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale)); } /* Set initial value of temp. */ power = bc_copy_num (num1); pwrscale = num1->n_scale; while ((exponent & 1) == 0) { pwrscale = 2*pwrscale; bc_multiply (power, power, &power, pwrscale); exponent = exponent >> 1; } temp = bc_copy_num (power); calcscale = pwrscale; exponent = exponent >> 1; /* Do the calculation. */ while (exponent > 0) { pwrscale = 2*pwrscale; bc_multiply (power, power, &power, pwrscale); if ((exponent & 1) == 1) { calcscale = pwrscale + calcscale; bc_multiply (temp, power, &temp, calcscale); } exponent = exponent >> 1; } /* Assign the value. */ if (neg) { bc_divide (_one_, temp, result, rscale); bc_free_num (&temp); } else { bc_free_num (result); *result = temp; if ((*result)->n_scale > rscale) (*result)->n_scale = rscale; } bc_free_num (&power); } /* Take the square root NUM and return it in NUM with SCALE digits after the decimal place. */ int bc_sqrt (bc_num *num, int scale) { int rscale, cmp_res, done; int cscale; bc_num guess, guess1, point5, diff; /* Initial checks. */ cmp_res = bc_compare (*num, _zero_); if (cmp_res < 0) return 0; /* error */ else { if (cmp_res == 0) { bc_free_num (num); *num = bc_copy_num (_zero_); return 1; } } cmp_res = bc_compare (*num, _one_); if (cmp_res == 0) { bc_free_num (num); *num = bc_copy_num (_one_); return 1; } /* Initialize the variables. */ rscale = MAX (scale, (*num)->n_scale); bc_init_num(&guess); bc_init_num(&guess1); bc_init_num(&diff); point5 = bc_new_num (1,1); point5->n_value[1] = 5; /* Calculate the initial guess. */ if (cmp_res < 0) { /* The number is between 0 and 1. Guess should start at 1. */ guess = bc_copy_num (_one_); cscale = (*num)->n_scale; } else { /* The number is greater than 1. Guess should start at 10^(exp/2). */ bc_int2num (&guess,10); bc_int2num (&guess1,(*num)->n_len); bc_multiply (guess1, point5, &guess1, 0); guess1->n_scale = 0; bc_raise (guess, guess1, &guess, 0); bc_free_num (&guess1); cscale = 3; } /* Find the square root using Newton's algorithm. */ done = FALSE; while (!done) { bc_free_num (&guess1); guess1 = bc_copy_num (guess); bc_divide (*num, guess, &guess, cscale); bc_add (guess, guess1, &guess, 0); bc_multiply (guess, point5, &guess, cscale); bc_sub (guess, guess1, &diff, cscale+1); if (bc_is_near_zero (diff, cscale)) { if (cscale < rscale+1) cscale = MIN (cscale*3, rscale+1); else done = TRUE; } } /* Assign the number and clean up. */ bc_free_num (num); bc_divide (guess,_one_,num,rscale); bc_free_num (&guess); bc_free_num (&guess1); bc_free_num (&point5); bc_free_num (&diff); return 1; } /* The following routines provide output for bcd numbers package using the rules of POSIX bc for output. */ /* This structure is used for saving digits in the conversion process. */ typedef struct stk_rec { long digit; struct stk_rec *next; } stk_rec; /* The reference string for digits. */ static char ref_str[] = "0123456789ABCDEF"; /* A special output routine for "multi-character digits." Exactly SIZE characters must be output for the value VAL. If SPACE is non-zero, we must output one space before the number. OUT_CHAR is the actual routine for writing the characters. */ void bc_out_long (long val, int size, int space, void (*out_char)(int)) { char digits[40]; int len, ix; if (space) (*out_char) (' '); sprintf (digits, "%ld", val); len = (int)strlen (digits); while (size > len) { (*out_char) ('0'); size--; } for (ix=0; ix < len; ix++) (*out_char) (digits[ix]); } /* Output of a bcd number. NUM is written in base O_BASE using OUT_CHAR as the routine to do the actual output of the characters. */ void bc_out_num (bc_num num, int o_base, void (*out_char)(int), int leading_zero) { char *nptr; int index, fdigit, pre_space; stk_rec *digits, *temp; bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit; /* The negative sign if needed. */ if (num->n_sign == MINUS) (*out_char) ('-'); /* Output the number. */ if (bc_is_zero (num)) (*out_char) ('0'); else if (o_base == 10) { /* The number is in base 10, do it the fast way. */ nptr = num->n_value; if (num->n_len > 1 || *nptr != 0) for (index=num->n_len; index>0; index--) (*out_char) (BCD_CHAR(*nptr++)); else nptr++; if (leading_zero && bc_is_zero (num)) (*out_char) ('0'); /* Now the fraction. */ if (num->n_scale > 0) { (*out_char) ('.'); for (index=0; indexn_scale; index++) (*out_char) (BCD_CHAR(*nptr++)); } } else { /* special case ... */ if (leading_zero && bc_is_zero (num)) (*out_char) ('0'); /* The number is some other base. */ digits = NULL; bc_init_num (&int_part); bc_divide (num, _one_, &int_part, 0); bc_init_num (&frac_part); bc_init_num (&cur_dig); bc_init_num (&base); bc_sub (num, int_part, &frac_part, 0); /* Make the INT_PART and FRAC_PART positive. */ int_part->n_sign = PLUS; frac_part->n_sign = PLUS; bc_int2num (&base, o_base); bc_init_num (&max_o_digit); bc_int2num (&max_o_digit, o_base-1); /* Get the digits of the integer part and push them on a stack. */ while (!bc_is_zero (int_part)) { bc_modulo (int_part, base, &cur_dig, 0); temp = (stk_rec *) malloc (sizeof(stk_rec)); if (temp == NULL) bc_out_of_memory(); temp->digit = bc_num2long (cur_dig); temp->next = digits; digits = temp; bc_divide (int_part, base, &int_part, 0); } /* Print the digits on the stack. */ if (digits != NULL) { /* Output the digits. */ while (digits != NULL) { temp = digits; digits = digits->next; if (o_base <= 16) (*out_char) (ref_str[ (int) temp->digit]); else bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char); free (temp); } } /* Get and print the digits of the fraction part. */ if (num->n_scale > 0) { (*out_char) ('.'); pre_space = 0; t_num = bc_copy_num (_one_); while (t_num->n_len <= num->n_scale) { bc_multiply (frac_part, base, &frac_part, num->n_scale); fdigit = bc_num2long (frac_part); bc_int2num (&int_part, fdigit); bc_sub (frac_part, int_part, &frac_part, 0); if (o_base <= 16) (*out_char) (ref_str[fdigit]); else { bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char); pre_space = 1; } bc_multiply (t_num, base, &t_num, 0); } bc_free_num (&t_num); } /* Clean up. */ bc_free_num (&int_part); bc_free_num (&frac_part); bc_free_num (&base); bc_free_num (&cur_dig); bc_free_num (&max_o_digit); } } /* Convert a number NUM to a long. The function returns only the integer part of the number. For numbers that are too large to represent as a long, this function returns a zero. This can be detected by checking the NUM for zero after having a zero returned. */ long bc_num2long (bc_num num) { long val; char *nptr; int index; /* Extract the int value, ignore the fraction. */ val = 0; nptr = num->n_value; for (index=num->n_len; (index>0) && (val<=(LONG_MAX/BASE)); index--) val = val*BASE + *nptr++; /* Check for overflow. If overflow, return zero. */ if (index>0) val = 0; if (val < 0) val = 0; /* Return the value. */ if (num->n_sign == PLUS) return (val); else return (-val); } /* Convert an integer VAL to a bc number NUM. */ void bc_int2num (bc_num *num, int val) { char buffer[30]; char *bptr, *vptr; int ix = 1; char neg = 0; /* Sign. */ if (val < 0) { neg = 1; val = -val; } /* Get things going. */ bptr = buffer; *bptr++ = (unsigned)val % BASE; /* type cast to unsigned, bug fix Wolf Lammen */ val = (unsigned)val / BASE; /* type cast to unsigned, bug fix Wolf Lammen */ /* Extract remaining digits. */ while (val != 0) { *bptr++ = val % BASE; val = val / BASE; ix++; /* Count the digits. */ } /* Make the number. */ bc_free_num (num); *num = bc_new_num (ix, 0); if (neg) (*num)->n_sign = MINUS; /* Assign the digits. */ vptr = (*num)->n_value; while (ix-- > 0) *vptr++ = *--bptr; } /* Convert a numbers to a string. Base 10 only.*/ char *bc_num2str (bc_num num) { char *str, *sptr; char *nptr; int index, signch; /* Allocate the string memory. */ signch = ( num->n_sign == PLUS ? 0 : 1 ); /* Number of sign chars. */ if (num->n_scale > 0) str = (char *) malloc (num->n_len + num->n_scale + 2 + signch); else str = (char *) malloc (num->n_len + 1 + signch); if (str == NULL) bc_out_of_memory(); /* The negative sign if needed. */ sptr = str; if (signch) *sptr++ = '-'; /* Load the whole number. */ nptr = num->n_value; for (index=num->n_len; index>0; index--) *sptr++ = BCD_CHAR(*nptr++); /* Now the fraction. */ if (num->n_scale > 0) { *sptr++ = '.'; for (index=0; indexn_scale; index++) *sptr++ = BCD_CHAR(*nptr++); } /* Terminate the string and return it! */ *sptr = '\0'; return (str); } /* Convert strings to bc numbers. Base 10 only.*/ void bc_str2num (bc_num *num, char *str, int scale) { int digits, strscale; char *ptr, *nptr; char zero_int; /* Prepare num. */ bc_free_num (num); /* Check for valid number and count digits. */ ptr = str; digits = 0; strscale = 0; zero_int = FALSE; if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */ while (*ptr == '0') ptr++; /* Skip leading zeros. */ while (isdigit((int)*ptr)) ptr++, digits++; /* digits */ if (*ptr == '.') ptr++; /* decimal point */ while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */ if ((*ptr != '\0') || (digits+strscale == 0)) { *num = bc_copy_num (_zero_); return; } /* Adjust numbers and allocate storage and initialize fields. */ strscale = MIN(strscale, scale); if (digits == 0) { zero_int = TRUE; digits = 1; } *num = bc_new_num (digits, strscale); /* Build the whole number. */ ptr = str; if (*ptr == '-') { (*num)->n_sign = MINUS; ptr++; } else { (*num)->n_sign = PLUS; if (*ptr == '+') ptr++; } while (*ptr == '0') ptr++; /* Skip leading zeros. */ nptr = (*num)->n_value; if (zero_int) { *nptr++ = 0; digits = 0; } for (;digits > 0; digits--) *nptr++ = CH_VAL(*ptr++); /* Build the fractional part. */ if (strscale > 0) { ptr++; /* skip the decimal point! */ for (;strscale > 0; strscale--) *nptr++ = CH_VAL(*ptr++); } } /* pn prints the number NUM in base 10. */ static void out_char (int c) { putchar(c); } void pn (bc_num num) { bc_out_num (num, 10, out_char, 0); out_char ('\n'); } /* pv prints a character array as if it was a string of bcd digits. */ void pv (char *name, unsigned char *num, int len) { int i; printf ("%s=", name); for (i=0; i #ifdef __cplusplus extern "C" { #endif #undef _PROTOTYPE #ifndef NUMBER__STDC__ #define NUMBER__STDC__ #endif typedef enum {PLUS, MINUS} sign; typedef struct bc_struct *bc_num; typedef struct bc_struct { sign n_sign; int n_len; /* The number of digits before the decimal point. */ int n_scale; /* The number of digits after the decimal point. */ int n_refs; /* The number of pointers to this number. */ bc_num n_next; /* Linked list for available list. */ char *n_ptr; /* The pointer to the actual storage. If NULL, n_value points to the inside of another number (bc_multiply...) and should not be "freed." */ char *n_value; /* The number. Not zero char terminated. May not point to the same place as n_ptr as in the case of leading zeros generated. */ } bc_struct; /* The base used in storing the numbers in n_value above. Currently this MUST be 10. */ #define BASE 10 /* Some useful macros and constants. */ #define CH_VAL(c) (c - '0') #define CH_HEX(c) ((c < ':') ? ( c - '0') : (c < 'G') ? ( c - 'A' + 10) : ( c - 'a' + 10)) #define BCD_CHAR(d) (d + '0') #ifdef MIN #undef MIN #undef MAX #endif #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)>(b)?(b):(a)) #define ODD(a) ((a)&1) #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef LONG_MAX #define LONG_MAX 0x7ffffff #endif /* Global numbers. */ extern bc_num _zero_; extern bc_num _one_; extern bc_num _two_; /* Function Prototypes */ /* Define the _PROTOTYPE macro if it is needed. */ #ifndef _PROTOTYPE #ifdef NUMBER__STDC__ #define _PROTOTYPE(func, args) func args #else #define _PROTOTYPE(func, args) func() #endif #endif _PROTOTYPE(void bc_init_numbers, (void)); _PROTOTYPE(bc_num bc_new_num, (int length, int scale)); _PROTOTYPE(void bc_free_num, (bc_num *num)); _PROTOTYPE(bc_num bc_copy_num, (bc_num num)); _PROTOTYPE(void bc_init_num, (bc_num *num)); _PROTOTYPE(void bc_str2num, (bc_num *num, char *str, int scale)); _PROTOTYPE(char *bc_num2str, (bc_num num)); _PROTOTYPE(void bc_int2num, (bc_num *num, int val)); _PROTOTYPE(long bc_num2long, (bc_num num)); _PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2)); _PROTOTYPE(char bc_is_zero, (bc_num num)); _PROTOTYPE(char bc_is_near_zero, (bc_num num, int scale)); _PROTOTYPE(char bc_is_neg, (bc_num num)); _PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result, int scale_min)); _PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result, int scale_min)); _PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale)); _PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale)); _PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result, int scale)); _PROTOTYPE(int bc_divmod, (bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, int scale)); _PROTOTYPE(int bc_raisemod, (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)); _PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result, int scale)); _PROTOTYPE(int bc_sqrt, (bc_num *num, int scale)); _PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int), int leading_zero)); #ifdef __cplusplus } #endif #endif heldercorreia-speedcrunch-e7ca37f/src/math/quantity.cpp000066400000000000000000003070421526573132500234450ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2016-2018, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "quantity.h" #include "core/complexform.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include "core/settings.h" #include "rational.h" #include "core/units.h" #include #include #include #include #define RATIONAL_TOL HNumber("1e-20") #define ENSURE_DIMENSIONLESS(x) \ if (!(x).isDimensionless()) \ return DMath::nan(InvalidDimension); #define ENSURE_SAME_DIMENSION(x, y) \ if ((!(x).sameDimension(y))) \ return DMath::nan(DimensionMismatch); namespace { enum class SemanticUnitKind { None, Frequency, Activity, AbsorbedDose, EquivalentDose }; enum class InformationUnitFamily { None, Bit, Byte }; SemanticUnitKind semanticUnitKind(const QString& unitName) { switch (unitId(normalizeUnitName(unitName))) { case UnitId::Hertz: return SemanticUnitKind::Frequency; case UnitId::Becquerel: return SemanticUnitKind::Activity; case UnitId::Gray: return SemanticUnitKind::AbsorbedDose; case UnitId::Sievert: return SemanticUnitKind::EquivalentDose; default: return SemanticUnitKind::None; } } InformationUnitFamily informationUnitFamily(const QString& unitName) { QString n = unitName.trimmed(); if (n.startsWith(MathDsl::GroupStart) && n.endsWith(MathDsl::GroupEnd) && n.size() > 2) n = n.mid(1, n.size() - 2).trimmed(); if (n.isEmpty()) return InformationUnitFamily::None; if (n.endsWith(QLatin1String("byte"), Qt::CaseInsensitive) || n.endsWith(QLatin1Char('B'))) return InformationUnitFamily::Byte; if (n.endsWith(QLatin1String("bit"), Qt::CaseInsensitive) || n.endsWith(QLatin1Char('b'))) return InformationUnitFamily::Bit; return InformationUnitFamily::None; } bool isSteradianUnitName(const QString& unitName) { return unitId(normalizeUnitName(unitName)) == UnitId::Steradian; } bool tryBestSiPrefixForScaledDisplayUnit(const Quantity& source, const Quantity& result, CNumber* unit, QString* unitName) { if (!source.hasUnit() || !result.numericValue().isNearReal() || !source.unit().isNearReal() || source.unit().real.isNearZero()) { return false; } if (Units::isExplicitAngleUnitName(source.unitName())) return false; const UnitId id = unitId(normalizeUnitName(source.unitName())); const int policy = unitPrefixPolicy(id); if (!(policy & AllDecimalSiPrefixes)) return false; const auto abs = [](const HNumber& value) { return value < HNumber(0) ? -value : value; }; struct Score { int bucket = 3; HNumber value = HNumber(0); }; const auto scoreForUnit = [&](const CNumber& displayUnit) { Score score; if (!displayUnit.isNearReal() || displayUnit.real.isNearZero()) return score; score.value = abs(result.numericValue().real / displayUnit.real); if (score.value >= HNumber(1) && score.value < HNumber(1000)) { score.bucket = 0; } else if (score.value >= HNumber(1000)) { score.bucket = 1; } else { score.bucket = 2; } return score; }; const auto better = [](const Score& a, const Score& b) { if (a.bucket != b.bucket) return a.bucket < b.bucket; if (a.bucket == 0 || a.bucket == 1) return a.value < b.value; if (a.bucket == 2) return a.value > b.value; return false; }; const Score sourceScore = scoreForUnit(source.unit()); if (sourceScore.bucket == 0) return false; if (id == UnitId::Metre && sourceScore.bucket == 2 && sourceScore.value >= HNumber("0.001")) return false; const QString symbol = unitSiPrefixBaseSymbol(id); if (symbol.isEmpty()) return false; const CNumber baseUnit = unitSiPrefixBaseValue(id); if (!baseUnit.isNearReal() || baseUnit.real.isNearZero()) return false; Score bestScore; CNumber bestUnit; QString bestName; for (const UnitPrefixSpec& prefix : siPrefixes()) { if (prefix.power % 3 != 0) continue; if (id == UnitId::Second && prefix.power > 0) continue; if (!unitPrefixPolicyAllows(policy, prefix)) continue; const CNumber candidateUnit = baseUnit * prefix.value.numericValue(); const Score candidateScore = scoreForUnit(candidateUnit); if (candidateScore.bucket != 0) continue; if (bestName.isEmpty() || better(candidateScore, bestScore)) { bestScore = candidateScore; bestUnit = candidateUnit; bestName = prefix.symbol + symbol; } } if (bestName.isEmpty()) return false; if (unit) *unit = bestUnit; if (unitName) *unitName = bestName; return true; } enum class AffineTemperatureScale { None, Celsius, Fahrenheit }; AffineTemperatureScale affineTemperatureScaleFromDisplayUnitName(const QString& unitName) { QString normalized = UnicodeChars::normalizeUnitSymbolAliases(unitName).trimmed(); if (normalized.isEmpty()) return AffineTemperatureScale::None; auto matchesUnitAndAliases = [&](UnitId id) { if (normalized == ::unitSymbol(id) || normalized == ::unitName(id)) return true; const QStringList aliases = Units::affineUnitAliases(id); for (const QString& alias : aliases) { if (normalized == UnicodeChars::normalizeUnitSymbolAliases(alias).trimmed()) return true; } return false; }; if (matchesUnitAndAliases(UnitId::DegreeCelsius)) { return AffineTemperatureScale::Celsius; } if (matchesUnitAndAliases(UnitId::DegreeFahrenheit)) { return AffineTemperatureScale::Fahrenheit; } return AffineTemperatureScale::None; } bool tryAffineScaleByRealScalar(const Quantity& affineQuantity, const HNumber& scalar, CNumber* scaledBaseValueOut) { if (!scaledBaseValueOut || !affineQuantity.hasUnit() || !affineQuantity.numericValue().isNearReal()) { return false; } const AffineTemperatureScale scale = affineTemperatureScaleFromDisplayUnitName(affineQuantity.unitName()); if (scale == AffineTemperatureScale::None) return false; static const HNumber kelvinOffset("273.15"); static const HNumber five(5); static const HNumber nine(9); static const HNumber thirtyTwo(32); HNumber affineValue; if (scale == AffineTemperatureScale::Celsius) { affineValue = affineQuantity.numericValue().real - kelvinOffset; } else { affineValue = (affineQuantity.numericValue().real - kelvinOffset) * (nine / five) + thirtyTwo; } const HNumber scaledAffineValue = affineValue * scalar; HNumber scaledBaseValue; if (scale == AffineTemperatureScale::Celsius) { scaledBaseValue = scaledAffineValue + kelvinOffset; } else { scaledBaseValue = ((scaledAffineValue - thirtyTwo) * (five / nine)) + kelvinOffset; } *scaledBaseValueOut = CNumber(scaledBaseValue); return true; } bool tryAffineValueFromBase(const Quantity& affineQuantity, HNumber* affineValueOut, AffineTemperatureScale* scaleOut = nullptr) { if (!affineValueOut || !affineQuantity.hasUnit() || !affineQuantity.numericValue().isNearReal()) { return false; } const AffineTemperatureScale scale = affineTemperatureScaleFromDisplayUnitName(affineQuantity.unitName()); if (scale == AffineTemperatureScale::None) return false; static const HNumber kelvinOffset("273.15"); static const HNumber five(5); static const HNumber nine(9); static const HNumber thirtyTwo(32); if (scale == AffineTemperatureScale::Celsius) { *affineValueOut = affineQuantity.numericValue().real - kelvinOffset; } else { *affineValueOut = (affineQuantity.numericValue().real - kelvinOffset) * (nine / five) + thirtyTwo; } if (scaleOut) *scaleOut = scale; return true; } bool tryAffineBaseFromValue(const HNumber& affineValue, const AffineTemperatureScale scale, HNumber* baseValueOut) { if (!baseValueOut || scale == AffineTemperatureScale::None) return false; static const HNumber kelvinOffset("273.15"); static const HNumber five(5); static const HNumber nine(9); static const HNumber thirtyTwo(32); if (scale == AffineTemperatureScale::Celsius) { *baseValueOut = affineValue + kelvinOffset; } else { *baseValueOut = ((affineValue - thirtyTwo) * (five / nine)) + kelvinOffset; } return true; } bool isExactDimension(const Quantity& q, const QMap& expected) { return q.getDimensionByQuantity() == expected; } bool parseUnitFactorAndExponent(const QString& token, QString* baseOut, int* exponentOut) { if (!baseOut || !exponentOut) return false; QString t = token.trimmed(); if (t.isEmpty()) return false; int exponent = 1; int suffixStart = t.size(); while (suffixStart > 0) { const QChar ch = t.at(suffixStart - 1); if (!UnicodeChars::isSuperscriptDigit(ch) && !UnicodeChars::isSuperscriptSign(ch)) { break; } --suffixStart; } if (suffixStart < t.size()) { bool negative = false; int pos = suffixStart; if (t.at(pos) == MathDsl::PowNeg || t.at(pos) == MathDsl::PowPos) { negative = t.at(pos) == MathDsl::PowNeg; ++pos; } if (pos >= t.size()) return false; QString digits; for (; pos < t.size(); ++pos) { const QChar ascii = MathDsl::superscriptDigitToAscii(t.at(pos)); if (ascii.isNull()) return false; digits += ascii; } bool ok = false; int value = digits.toInt(&ok); if (!ok) return false; exponent = negative ? -value : value; t = t.left(suffixStart).trimmed(); } else { const int caret = t.lastIndexOf(MathDsl::PowOp); if (caret >= 0 && caret + 1 < t.size()) { bool ok = false; const int value = t.mid(caret + 1).trimmed().toInt(&ok); if (!ok) return false; exponent = value; t = t.left(caret).trimmed(); } } if (t.isEmpty()) return false; *baseOut = t; *exponentOut = exponent; return true; } QString formatUnitFactorWithExponent(const QString& base, int exponent) { if (exponent == 1) return base; QString suffix; if (exponent < 0) suffix += MathDsl::PowNeg; const QString digits = QString::number(qAbs(exponent)); for (const QChar ch : digits) suffix += MathDsl::asciiDigitToSuperscript(ch); return base + suffix; } bool unitTextContainsExplicitAngleFactor(const QString& unitText) { if (unitText.isEmpty()) return false; QString token; auto flushTokenIsAngle = [&]() { if (token.isEmpty()) return false; QString base; int exponent = 0; const QString raw = token; token.clear(); if (!parseUnitFactorAndExponent(raw, &base, &exponent)) return false; return Units::isExplicitAngleUnitName(base); }; for (int i = 0; i < unitText.size(); ++i) { const QChar ch = unitText.at(i); const bool isUnitChar = UnicodeChars::isUnitIdentifierChar(ch) || UnicodeChars::isSuperscriptDigit(ch) || UnicodeChars::isSuperscriptSign(ch) || ch == MathDsl::PowOp; if (isUnitChar) { token += ch; continue; } if (flushTokenIsAngle()) return true; } return flushTokenIsAngle(); } QString simplifyExplicitAngleCompositeDisplayUnits(const QString& unitName) { QString normalized = unitName.trimmed(); if (normalized.isEmpty()) return normalized; if (!unitTextContainsExplicitAngleFactor(normalized)) return normalized; if (normalized.contains(MathDsl::DivOp) || normalized.contains(MathDsl::AddOp) || normalized.contains(MathDsl::SubOpAl1) || normalized.contains(MathDsl::GroupStart) || normalized.contains(MathDsl::GroupEnd)) { return normalized; } struct Factor { QString base; int exponent = 1; }; QList factors; QString token; auto flushToken = [&]() -> bool { if (token.isEmpty()) return true; QString base; int exponent = 0; const QString raw = token; token.clear(); if (!parseUnitFactorAndExponent(raw, &base, &exponent)) return false; factors.append(Factor{base, exponent}); return true; }; const auto isMulSeparator = [](const QChar ch) { return ch.isSpace() || ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp; }; for (int i = 0; i < normalized.size(); ++i) { const QChar ch = normalized.at(i); if (isMulSeparator(ch)) { if (!flushToken()) return unitName; continue; } token += ch; } if (!flushToken()) return unitName; if (factors.size() < 2) return normalized; const QString kgName = ::unitName(UnitId::Kilogram); const QString kgSymbol = ::unitSymbol(UnitId::Kilogram); const QString mName = ::unitName(UnitId::Metre); const QString mSymbol = ::unitSymbol(UnitId::Metre); const QString sName = ::unitName(UnitId::Second); const QString sSymbol = ::unitSymbol(UnitId::Second); const QString jSymbol = ::unitSymbol(UnitId::Joule); const QString metreName = ::unitName(UnitId::Metre); for (int i = 0; i < factors.size(); ++i) { if (factors[i].base == ::unitName(UnitId::SquareMetre)) { factors[i].base = metreName; factors[i].exponent *= 2; } else if (factors[i].base == ::unitName(UnitId::CubicMetre)) { factors[i].base = metreName; factors[i].exponent *= 3; } } int kgIndex = -1; int mIndex = -1; int sIndex = -1; for (int i = 0; i < factors.size(); ++i) { const QString b = factors.at(i).base; if (kgIndex < 0 && (b == kgName || b == kgSymbol)) kgIndex = i; else if (mIndex < 0 && (b == mName || b == mSymbol)) mIndex = i; else if (sIndex < 0 && (b == sName || b == sSymbol)) sIndex = i; } if (kgIndex < 0 || mIndex < 0 || sIndex < 0) { return normalized; } if (factors[kgIndex].exponent <= 0 || factors[mIndex].exponent < 2) { return normalized; } const int jExp = qMin(factors[kgIndex].exponent, factors[mIndex].exponent / 2); if (jExp <= 0) return normalized; factors[kgIndex].exponent -= jExp; factors[mIndex].exponent -= 2 * jExp; factors[sIndex].exponent += 2 * jExp; int jIndex = -1; for (int i = 0; i < factors.size(); ++i) { if (factors.at(i).base == jSymbol) { jIndex = i; break; } } if (jIndex >= 0) { factors[jIndex].exponent += jExp; } else { factors.insert(kgIndex, Factor{jSymbol, jExp}); } QStringList rendered; for (const Factor& factor : factors) { if (factor.exponent == 0) continue; rendered << formatUnitFactorWithExponent(factor.base, factor.exponent); } if (rendered.isEmpty()) return normalized; return rendered.join(QString(MathDsl::MulDotOp)); } QString simplifyRepeatedCompositeDisplayUnitFactors(const QString& unitName) { QString normalized = unitName.trimmed(); if (normalized.isEmpty()) return normalized; if (normalized.contains(MathDsl::DivOp) || normalized.contains(MathDsl::AddOp) || normalized.contains(MathDsl::SubOpAl1) || normalized.contains(MathDsl::GroupStart) || normalized.contains(MathDsl::GroupEnd)) { return normalized; } QMap exponentsByBase; QStringList order; QString token; const auto isMulSeparator = [](const QChar ch) { return ch.isSpace() || ch == MathDsl::MulOpAl1 || ch == MathDsl::MulDotOp || ch == MathDsl::MulCrossOp; }; auto flushToken = [&]() -> bool { const QString raw = token.trimmed(); token.clear(); if (raw.isEmpty()) return true; QString base; int exponent = 0; if (!parseUnitFactorAndExponent(raw, &base, &exponent)) return false; if (!exponentsByBase.contains(base)) order.append(base); exponentsByBase[base] += exponent; return true; }; for (int i = 0; i < normalized.size(); ++i) { const QChar ch = normalized.at(i); if (isMulSeparator(ch)) { if (!flushToken()) return unitName; continue; } token += ch; } if (!flushToken()) return unitName; QStringList rendered; for (const QString& base : order) { const int exponent = exponentsByBase.value(base); if (exponent == 0) continue; rendered << formatUnitFactorWithExponent(base, exponent); } if (rendered.isEmpty()) return normalized; return rendered.join(QString(MathDsl::MulDotOp)); } QString normalizeDisplayUnitNameForOutput(const QString& unitName) { QString normalized = unitName.trimmed(); if (normalized.isEmpty()) return normalized; if (unitId(normalized) == UnitId::Degree) { return QString(UnicodeChars::DegreeSign); } const bool isCompositeUnit = normalized.contains(MathDsl::MulOpAl1) || normalized.contains(MathDsl::MulDotOp) || normalized.contains(MathDsl::MulCrossOp) || normalized.contains(MathDsl::DivOp); if (isCompositeUnit && (normalized.contains(UnicodeChars::DegreeSign) || normalized.contains(UnicodeChars::MasculineOrdinalIndicator))) { normalized.replace(UnicodeChars::MasculineOrdinalIndicator, UnicodeChars::DegreeSign); normalized.replace(QString(UnicodeChars::DegreeSign), Units::degreeAliasSymbol()); } normalized = simplifyExplicitAngleCompositeDisplayUnits(normalized); // Keep explicit conversion-expression targets unchanged; they are meant // to mirror user-entered structure (operators and grouping). if (normalized.contains(MathDsl::MulOpAl1) || normalized.contains(MathDsl::MulDotOp) || normalized.contains(MathDsl::MulCrossOp) || normalized.contains(MathDsl::DivOp) || normalized.contains(MathDsl::AddOp) || normalized.contains(MathDsl::SubOpAl1) || normalized.contains(MathDsl::GroupStart) || normalized.contains(MathDsl::GroupEnd) || normalized.contains(QLatin1String("->")) || normalized.contains(MathDsl::TransOp)) { return normalized; } normalized.replace(QRegularExpression(QStringLiteral("\\s+")), QString(MathDsl::MulDotOp)); return normalized; } QString composeProductUnitName(const QString& left, const QString& right) { const QString l = left.trimmed(); const QString r = right.trimmed(); if (l.isEmpty()) return r; if (r.isEmpty()) return l; return l + QLatin1Char(' ') + r; } bool needsGroupingInQuotient(const QString& unitName) { const QString n = unitName.trimmed(); return n.contains(QLatin1Char(' ')) || n.contains(MathDsl::MulOpAl1) || n.contains(MathDsl::MulDotOp) || n.contains(MathDsl::MulCrossOp) || n.contains(QLatin1Char('/')); } QString composeQuotientUnitName(const QString& numerator, const QString& denominator) { const QString n = numerator.trimmed(); QString d = denominator.trimmed(); if (n.isEmpty()) return d; if (d.isEmpty()) return n; if (needsGroupingInQuotient(d)) d = QString(MathDsl::GroupStart) + d + QString(MathDsl::GroupEnd); return n + QStringLiteral(" / ") + d; } QString composeAnglePerSecondUnitName(const QString& angleUnitName) { const QString secondName = ::unitName(UnitId::Second); if (runtimeUnitNegativeExponentStyle() == Settings::UnitNegativeExponentSuperscript) { return composeProductUnitName( angleUnitName, secondName + QString(MathDsl::PowNeg) + QString(MathDsl::Pow1)); } return composeQuotientUnitName(angleUnitName, secondName); } bool isSpeedDimension(const QMap& dimension) { return dimension.size() == 2 && dimension.value(UnitQuantity::Length) == Rational(1) && dimension.value(UnitQuantity::Time) == Rational(-1); } bool tryNamedSpeedDisplayUnit(const CNumber& displayUnitValue, QString* displayUnitName, CNumber* normalizedDisplayUnitValue) { static const QList candidates = { UnitId::MilePerHour, UnitId::KilometrePerHour, UnitId::Knot }; const auto& units = Units::builtInUnitValues(); for (const UnitId id : candidates) { const QString name = unitName(id); const Quantity value = units.value(name); if (value.numericValue() != displayUnitValue) continue; if (displayUnitName) *displayUnitName = name; if (normalizedDisplayUnitValue) *normalizedDisplayUnitValue = value.numericValue(); return true; } return false; } bool tryReadableDisplayUnitForLinearSum(const Quantity& left, const Quantity& right, const Quantity& result, CNumber* unit, QString* unitName) { if (!result.numericValue().isNearReal()) return false; if (result.isDimensionless()) return false; if (result.sameDimension(Units::kilogram())) { const auto abs = [](const HNumber& value) { return value < HNumber(0) ? -value : value; }; const HNumber kilogramValue = abs(result.numericValue().real); if (kilogramValue >= HNumber(1) && kilogramValue < HNumber(1000)) { if (unit) *unit = CNumber(1); if (unitName) *unitName = ::unitName(UnitId::Kilogram); return true; } } if (result.sameDimension(Units::second())) { if (left.format().mode == HNumber::Format::Mode::Sexagesimal || right.format().mode == HNumber::Format::Mode::Sexagesimal) { return false; } if (!left.hasUnit() && !right.hasUnit()) return false; HNumber seconds = result.numericValue().real; if (seconds < HNumber(0)) seconds = -seconds; if (seconds >= HNumber("3600")) { if (unit) *unit = Units::hour().numericValue(); if (unitName) *unitName = unitSymbol(UnitId::Hour); return true; } if (seconds >= HNumber("60")) { if (unit) *unit = Units::minute().numericValue(); if (unitName) *unitName = ::unitName(UnitId::Minute); return true; } } const auto displayCandidate = [](const Quantity& source) { Quantity candidate(source); if (!candidate.hasUnit()) { candidate.stripUnits(); Units::findUnit(candidate); } return candidate; }; const Quantity leftCandidate = displayCandidate(left); const Quantity rightCandidate = displayCandidate(right); if (!leftCandidate.hasUnit() || !rightCandidate.hasUnit()) return false; HNumber affineValue; if (tryAffineValueFromBase(leftCandidate, &affineValue) || tryAffineValueFromBase(rightCandidate, &affineValue)) { return false; } if (informationUnitFamily(leftCandidate.unitName()) != InformationUnitFamily::None || informationUnitFamily(rightCandidate.unitName()) != InformationUnitFamily::None) { return false; } const auto abs = [](const HNumber& value) { return value < HNumber(0) ? -value : value; }; const auto score = [&](const Quantity& candidate) { struct Score { int bucket = 3; HNumber value = HNumber(0); }; Score s; if (!candidate.unit().isNearReal() || candidate.unit().real.isNearZero()) return s; s.value = abs(result.numericValue().real / candidate.unit().real); if (s.value >= HNumber(1) && s.value < HNumber(1000)) { s.bucket = 0; } else if (s.value >= HNumber(1000)) { s.bucket = 1; } else { s.bucket = 2; } return s; }; const auto better = [](const auto& a, const auto& b) { if (a.bucket != b.bucket) return a.bucket < b.bucket; if (a.bucket == 0) return a.value < b.value; if (a.bucket == 1) return a.value < b.value; if (a.bucket == 2) return a.value > b.value; return false; }; Quantity canonical(result); canonical.stripUnits(); Units::findUnit(canonical); const Quantity* chosen = &leftCandidate; auto chosenScore = score(*chosen); const auto rightScore = score(rightCandidate); if (better(rightScore, chosenScore)) { chosen = &rightCandidate; chosenScore = rightScore; } if (canonical.hasUnit()) { const auto canonicalScore = score(canonical); if (better(canonicalScore, chosenScore)) chosen = &canonical; } if (unit) *unit = chosen->unit(); if (unitName) *unitName = chosen->unitName(); return true; } QMap dimensionCandela() { QMap dim; dim.insert(UnitQuantity::LuminousIntensity, Rational(1)); return dim; } QMap dimensionMetre() { QMap dim; dim.insert(UnitQuantity::Length, Rational(1)); return dim; } QMap dimensionSecond() { QMap dim; dim.insert(UnitQuantity::Time, Rational(1)); return dim; } QMap dimensionAmpere() { QMap dim; dim.insert(UnitQuantity::ElectricCurrent, Rational(1)); return dim; } QMap dimensionCubicMetre() { QMap dim; dim.insert(UnitQuantity::Length, Rational(3)); return dim; } QMap dimensionSquareMetre() { QMap dim; dim.insert(UnitQuantity::Length, Rational(2)); return dim; } QMap dimensionPascal() { QMap dim; dim.insert(UnitQuantity::Mass, Rational(1)); dim.insert(UnitQuantity::Length, Rational(-1)); dim.insert(UnitQuantity::Time, Rational(-2)); return dim; } QMap dimensionNewton() { QMap dim; dim.insert(UnitQuantity::Mass, Rational(1)); dim.insert(UnitQuantity::Length, Rational(1)); dim.insert(UnitQuantity::Time, Rational(-2)); return dim; } QMap dimensionJoule() { QMap dim; dim.insert(UnitQuantity::Mass, Rational(1)); dim.insert(UnitQuantity::Length, Rational(2)); dim.insert(UnitQuantity::Time, Rational(-2)); return dim; } QMap dimensionWatt() { QMap dim; dim.insert(UnitQuantity::Mass, Rational(1)); dim.insert(UnitQuantity::Length, Rational(2)); dim.insert(UnitQuantity::Time, Rational(-3)); return dim; } QMap dimensionVolt() { QMap dim; dim.insert(UnitQuantity::Mass, Rational(1)); dim.insert(UnitQuantity::Length, Rational(2)); dim.insert(UnitQuantity::Time, Rational(-3)); dim.insert(UnitQuantity::ElectricCurrent, Rational(-1)); return dim; } QMap dimensionFarad() { QMap dim; dim.insert(UnitQuantity::Mass, Rational(-1)); dim.insert(UnitQuantity::Length, Rational(-2)); dim.insert(UnitQuantity::Time, Rational(4)); dim.insert(UnitQuantity::ElectricCurrent, Rational(2)); return dim; } QMap dimensionTesla() { QMap dim; dim.insert(UnitQuantity::Mass, Rational(1)); dim.insert(UnitQuantity::Time, Rational(-2)); dim.insert(UnitQuantity::ElectricCurrent, Rational(-1)); return dim; } } Quantity operator-(const Quantity& q) { if (q.isCollection()) { QVector> rows = q.matrix(); for (QVector& row : rows) { for (Quantity& element : row) element = -element; } return q.isList() ? Quantity::list(rows.value(0)) : Quantity::matrix(rows); } Quantity res(q); res.m_numericValue = -res.m_numericValue; return res; } Quantity operator-(const Quantity& a, const Quantity& b) { if (a.isCollection() || b.isCollection()) return a + (-b); Quantity res(a); res.m_format = Quantity::Format(); if (!a.sameDimension(b)) return DMath::nan(DimensionMismatch); const SemanticUnitKind k1 = semanticUnitKind(a.unitName()); const SemanticUnitKind k2 = semanticUnitKind(b.unitName()); if (k1 != SemanticUnitKind::None && k2 != SemanticUnitKind::None && k1 != k2) { return DMath::nan(DimensionMismatch); } HNumber lhsAffine; HNumber rhsAffine; AffineTemperatureScale lhsScale = AffineTemperatureScale::None; AffineTemperatureScale rhsScale = AffineTemperatureScale::None; const bool lhsIsAffine = tryAffineValueFromBase(a, &lhsAffine, &lhsScale); const bool rhsIsAffine = tryAffineValueFromBase(b, &rhsAffine, &rhsScale); if (lhsIsAffine && rhsIsAffine && lhsScale == rhsScale) { HNumber baseDiff; if (tryAffineBaseFromValue(lhsAffine - rhsAffine, lhsScale, &baseDiff)) res.m_numericValue = CNumber(baseDiff); else res.m_numericValue -= b.m_numericValue; } else { res.m_numericValue -= b.m_numericValue; } res.cleanDimension(); CNumber readableUnit; QString readableUnitName; if (tryReadableDisplayUnitForLinearSum(a, b, res, &readableUnit, &readableUnitName)) res.setDisplayUnit(readableUnit, readableUnitName); return res; } bool operator>(const Quantity& l, const Quantity& r) { if (l.sameDimension(r)) return l.m_numericValue > r.m_numericValue; return false; } bool operator<(const Quantity& l, const Quantity& r) { if (l.sameDimension(r)) return l.m_numericValue < r.m_numericValue; return false; } bool operator>=(const Quantity& l, const Quantity& r) { if (l.sameDimension(r)) return l.m_numericValue >= r.m_numericValue; return false; } bool operator<=(const Quantity& l, const Quantity& r) { if (l.sameDimension(r)) return l.m_numericValue <= r.m_numericValue; return false; } bool operator==(const Quantity& l, const Quantity& r) { if (l.isCollection() || r.isCollection()) return l.m_matrix == r.m_matrix; if (l.sameDimension(r)) return l.m_numericValue == r.m_numericValue; return false; } // Returns TRUE upon dimension mismatch. bool operator!=(const Quantity& l, const Quantity& r) { if (l.sameDimension(r)) return l.m_numericValue != r.m_numericValue; return true; } Quantity operator*(const HNumber& l, const Quantity& r) { return r * l; } Quantity operator*(const CNumber& l, const Quantity& r) { return r * l; } Quantity operator/(const HNumber& l, const Quantity& r) { return Quantity(l) / r; } Quantity operator/(const CNumber& l, const Quantity& r) { return Quantity(l) / r; } Quantity::Quantity() : m_numericValue(0) , m_unit(nullptr) , m_unitName("") , m_collectionIsMatrix(false) { } Quantity::Quantity(const Quantity& other) : m_numericValue(other.m_numericValue) , m_dimension(other.m_dimension) , m_unit(nullptr) , m_unitName(other.m_unitName) , m_format(other.m_format) , m_matrix(other.m_matrix) , m_collectionIsMatrix(other.m_collectionIsMatrix) { if (other.hasUnit()) this->m_unit = new CNumber(other.unit()); cleanDimension(); } Quantity::Quantity(int i) : Quantity(CNumber(i)) { } Quantity::Quantity(const QJsonObject& json) : Quantity() { *this = deSerialize(json); } Quantity::Quantity(const HNumber& h) : Quantity(CNumber(h)) { } Quantity::Quantity(const CNumber& c) : Quantity() { this->m_numericValue = c; } Quantity::~Quantity() { delete m_unit; } bool Quantity::isNan() const { if (isCollection()) { for (const QVector& row : m_matrix) for (const Quantity& element : row) if (element.isNan()) return true; return false; } return m_numericValue.isNan(); } bool Quantity::isZero() const { if (isCollection()) return false; return m_numericValue.isZero(); } bool Quantity::isReal() const { if (isCollection()) { for (const QVector& row : m_matrix) for (const Quantity& element : row) if (!element.isReal()) return false; return true; } return m_numericValue.isReal(); } bool Quantity::isPositive() const { if (isCollection()) return false; return m_numericValue.isPositive(); } bool Quantity::isNegative() const { if (isCollection()) return false; return m_numericValue.isNegative(); } bool Quantity::isInteger() const { if (isCollection()) return false; return (!this->hasDimension() && !this->hasUnit()) && m_numericValue.isInteger(); } bool Quantity::isCollection() const { return !m_matrix.isEmpty(); } bool Quantity::isList() const { return isCollection() && !m_collectionIsMatrix; } bool Quantity::isMatrix() const { return isCollection() && m_collectionIsMatrix; } int Quantity::rows() const { return isCollection() ? m_matrix.size() : 0; } int Quantity::columns() const { return isCollection() && !m_matrix.isEmpty() ? m_matrix.at(0).size() : 0; } int Quantity::elementCount() const { return rows() * columns(); } QVector Quantity::elements() const { QVector result; for (const QVector& row : m_matrix) result += row; return result; } QVector> Quantity::matrix() const { return m_matrix; } Quantity Quantity::list(const QVector& elements) { for (const Quantity& element : elements) { if (element.isMatrix()) return DMath::nan(OutOfDomain); if (!element.isCollection() && (element.hasUnit() || element.hasDimension())) return DMath::nan(InvalidDimension); } bool allRows = !elements.isEmpty(); for (const Quantity& element : elements) allRows = allRows && element.isList(); if (allRows) { QVector> rows; int columns = -1; for (const Quantity& element : elements) { const QVector row = element.elements(); if (columns < 0) columns = row.size(); if (row.size() != columns) return DMath::nan(DimensionMismatch); rows.append(row); } return Quantity::matrix(rows); } for (const Quantity& element : elements) { if (element.isCollection()) return DMath::nan(OutOfDomain); } Quantity result; result.m_matrix.append(elements); result.m_collectionIsMatrix = false; result.m_numericValue = CMath::nan(OutOfDomain); return result; } Quantity Quantity::matrix(const QVector>& rows) { if (rows.isEmpty()) return DMath::nan(OutOfDomain); const int columns = rows.at(0).size(); if (columns == 0) return DMath::nan(OutOfDomain); for (const QVector& row : rows) { if (row.size() != columns) return DMath::nan(DimensionMismatch); for (const Quantity& element : row) { if (element.isCollection()) return DMath::nan(OutOfDomain); } } Quantity result; result.m_matrix = rows; result.m_collectionIsMatrix = true; result.m_numericValue = CMath::nan(OutOfDomain); return result; } bool Quantity::hasUnit() const { if (isCollection()) return false; return this->m_unit != NULL; } CNumber Quantity::unit() const { if (this->hasUnit()) return CNumber(*(this->m_unit)); return CNumber(1); } QString Quantity::unitName() const { if (this->hasUnit()) return m_unitName; return ""; } CNumber Quantity::numericValue() const { if (isCollection()) return CMath::nan(OutOfDomain); return m_numericValue; } Quantity& Quantity::setDisplayUnit(const CNumber unit, const QString& name) { if (unit.isNan()) *this = DMath::nan(InvalidDimension); else { stripUnits(); m_unit = new CNumber(unit); m_unitName = name; } return *this; } Quantity& Quantity::setFormat(Format c) { m_format = c; return *this; } void Quantity::stripUnits() { delete m_unit; m_unit = nullptr; m_unitName = ""; } bool Quantity::hasDimension() const { if (isCollection()) return false; return !this->m_dimension.empty(); } /* * Unlike hasDimension(), this does a clean up first, i.e. it * checks for redundant exponents. */ bool Quantity::isDimensionless() const { if (isCollection()) return true; Quantity temp(*this); temp.cleanDimension(); return temp.m_dimension.empty(); } QMap Quantity::getDimension() const { Quantity temp(*this); temp.cleanDimension(); QMap result; for (auto it = temp.m_dimension.constBegin(); it != temp.m_dimension.constEnd(); ++it) { const QString key = unitQuantityDimensionKey(it.key()); if (key.isEmpty()) continue; result.insert(key, it.value()); } return result; } QMap Quantity::getDimensionByQuantity() const { Quantity temp(*this); temp.cleanDimension(); return temp.m_dimension; } void Quantity::modifyDimension(const QString& key, const Rational& exponent) { UnitQuantity quantity = UnitQuantity::Unspecified; if (!unitQuantityFromDimensionKey(key, &quantity)) return; modifyDimension(quantity, exponent); } void Quantity::modifyDimension(UnitQuantity key, const Rational& exponent) { if (exponent.isZero()) m_dimension.remove(key); else m_dimension.insert(key, exponent); } void Quantity::copyDimension(const Quantity& other) { clearDimension(); this->m_dimension = other.m_dimension; } void Quantity::clearDimension() { this->m_dimension.clear(); } // Note: Does NOT clean the dimension vector first. // The calling function must do so on its own. bool Quantity::sameDimension(const Quantity& other) const { return this->m_dimension == other.m_dimension; } void Quantity::cleanDimension() { auto i = m_dimension.begin(); while (i != m_dimension.end()) { if (i.value().isZero()) i = m_dimension.erase(i); else ++i; } } void Quantity::serialize(QJsonObject& json) const { if (isCollection()) { QJsonArray rows; for (const QVector& row : m_matrix) { QJsonArray values; for (const Quantity& element : row) { QJsonObject elementJson; element.serialize(elementJson); values.append(elementJson); } rows.append(values); } json["matrix"] = rows; json["matrix_kind"] = isMatrix() ? QStringLiteral("matrix") : QStringLiteral("list"); return; } json["val"] = CMath::format( m_numericValue, CNumber::Format::Fixed() + CNumber::Format::Precision(DECPRECISION)); if (hasDimension()) { QJsonObject dim_json; auto i = m_dimension.constBegin(); while (i != m_dimension.constEnd()) { const auto& exp = i.value(); const QString key = unitQuantityDimensionKey(i.key()); if (!key.isEmpty()) dim_json[key] = exp.toString(); ++i; } json["dim"] = dim_json; } if (hasUnit()) { QJsonObject unit_json; m_unit->serialize(unit_json); json["unit"] = unit_json; json["unit_name"] = m_unitName; } if (!m_format.isNull()) { QJsonObject format_json; m_format.serialize(format_json); json["format"] = format_json; } } Quantity Quantity::deSerialize(const QJsonObject& json) { Quantity result; if (json.contains("matrix")) { QVector> rows; const QJsonArray rowsJson = json["matrix"].toArray(); for (const QJsonValue& rowValue : rowsJson) { QVector row; const QJsonArray rowJson = rowValue.toArray(); for (const QJsonValue& value : rowJson) row.append(Quantity::deSerialize(value.toObject())); rows.append(row); } if (json["matrix_kind"].toString() != QStringLiteral("matrix")) return Quantity::list(rows.at(0)); return Quantity::matrix(rows); } if (json.contains("val")) { QString str = json["val"].toString(); str.replace(",", "."); result.m_numericValue = CNumber(str.toLatin1().constData()); } result.stripUnits(); if (json.contains("unit")) { QJsonObject unit_json = json["unit"].toObject(); result.m_unit = new CNumber(unit_json); } if (json.contains("unit_name")) result.m_unitName = json["unit_name"].toString(); if (json.contains("dim")) { QJsonObject dim_json = json["dim"].toObject(); for (int i = 0; i < dim_json.count(); ++i) { auto key = dim_json.keys().at(i); Rational val(dim_json[key].toString()); UnitQuantity quantity = UnitQuantity::Unspecified; if (unitQuantityFromDimensionKey(key, &quantity)) result.modifyDimension(quantity, val); } } if (json.contains("format")) { QJsonObject format_json = json["format"].toObject(); result.m_format = Quantity::Format::deSerialize(format_json); } return result; } Error Quantity::error() const { if (isCollection()) { for (const QVector& row : m_matrix) { for (const Quantity& element : row) { if (element.error() != Success) return element.error(); } } return Success; } return m_numericValue.error(); } Quantity& Quantity::operator=(const Quantity& other) { m_numericValue = other.m_numericValue; m_dimension = other.m_dimension; m_format = other.m_format; m_matrix = other.m_matrix; m_collectionIsMatrix = other.m_collectionIsMatrix; stripUnits(); if(other.hasUnit()) { m_unit = new CNumber(*other.m_unit); m_unitName = other.m_unitName; } cleanDimension(); return *this; } Quantity Quantity::operator+(const Quantity& other) const { if (isCollection() || other.isCollection()) { if ((!isCollection() && (hasUnit() || hasDimension())) || (!other.isCollection() && (other.hasUnit() || other.hasDimension()))) return DMath::nan(InvalidDimension); if (!isCollection() || !other.isCollection()) return DMath::nan(NotImplemented); if (rows() != other.rows() || columns() != other.columns()) return DMath::nan(DimensionMismatch); QVector> resultRows; for (int r = 0; r < m_matrix.size(); ++r) { QVector row; for (int c = 0; c < m_matrix.at(r).size(); ++c) row.append(m_matrix.at(r).at(c) + other.m_matrix.at(r).at(c)); resultRows.append(row); } return resultRows.size() == 1 ? Quantity::list(resultRows.at(0)) : Quantity::matrix(resultRows); } if (!this->sameDimension(other)) return DMath::nan(DimensionMismatch); const InformationUnitFamily info1 = informationUnitFamily(this->unitName()); const InformationUnitFamily info2 = informationUnitFamily(other.unitName()); if (info1 != InformationUnitFamily::None && info2 != InformationUnitFamily::None && info1 != info2) { // Do not mix byte-family and bit-family implicitly. return DMath::nan(DimensionMismatch); } const SemanticUnitKind k1 = semanticUnitKind(this->unitName()); const SemanticUnitKind k2 = semanticUnitKind(other.unitName()); if (k1 != SemanticUnitKind::None && k2 != SemanticUnitKind::None && k1 != k2) { return DMath::nan(DimensionMismatch); } Quantity result(*this); result.m_format = Quantity::Format(); HNumber lhsAffine; HNumber rhsAffine; AffineTemperatureScale lhsScale = AffineTemperatureScale::None; AffineTemperatureScale rhsScale = AffineTemperatureScale::None; const bool lhsIsAffine = tryAffineValueFromBase(*this, &lhsAffine, &lhsScale); const bool rhsIsAffine = tryAffineValueFromBase(other, &rhsAffine, &rhsScale); if (lhsIsAffine && rhsIsAffine && lhsScale == rhsScale) { HNumber baseSum; if (tryAffineBaseFromValue(lhsAffine + rhsAffine, lhsScale, &baseSum)) result.m_numericValue = CNumber(baseSum); else result.m_numericValue += other.m_numericValue; } else { result.m_numericValue += other.m_numericValue; } if (info1 != InformationUnitFamily::None && info1 == info2 && this->hasUnit() && other.hasUnit()) { // For storage-style math keep the coarsest explicit unit from operands. if (this->unit().real >= other.unit().real) result.setDisplayUnit(this->unit(), this->unitName()); else result.setDisplayUnit(other.unit(), other.unitName()); } else { result.cleanDimension(); CNumber readableUnit; QString readableUnitName; if (tryReadableDisplayUnitForLinearSum(*this, other, result, &readableUnit, &readableUnitName)) result.setDisplayUnit(readableUnit, readableUnitName); } return result; } Quantity& Quantity::operator+=(const Quantity& other) { if (!this->sameDimension(other)) *this = DMath::nan(DimensionMismatch); else { const InformationUnitFamily info1 = informationUnitFamily(this->unitName()); const InformationUnitFamily info2 = informationUnitFamily(other.unitName()); if (info1 != InformationUnitFamily::None && info2 != InformationUnitFamily::None && info1 != info2) { *this = DMath::nan(DimensionMismatch); return *this; } const SemanticUnitKind k1 = semanticUnitKind(this->unitName()); const SemanticUnitKind k2 = semanticUnitKind(other.unitName()); if (k1 != SemanticUnitKind::None && k2 != SemanticUnitKind::None && k1 != k2) { *this = DMath::nan(DimensionMismatch); return *this; } HNumber lhsAffine; HNumber rhsAffine; AffineTemperatureScale lhsScale = AffineTemperatureScale::None; AffineTemperatureScale rhsScale = AffineTemperatureScale::None; const bool lhsIsAffine = tryAffineValueFromBase(*this, &lhsAffine, &lhsScale); const bool rhsIsAffine = tryAffineValueFromBase(other, &rhsAffine, &rhsScale); if (lhsIsAffine && rhsIsAffine && lhsScale == rhsScale) { HNumber baseSum; if (tryAffineBaseFromValue(lhsAffine + rhsAffine, lhsScale, &baseSum)) this->m_numericValue = CNumber(baseSum); else this->m_numericValue += other.m_numericValue; } else { this->m_numericValue += other.m_numericValue; } if (info1 != InformationUnitFamily::None && info1 == info2 && this->hasUnit() && other.hasUnit()) { if (this->unit().real < other.unit().real) this->setDisplayUnit(other.unit(), other.unitName()); } else { this->cleanDimension(); CNumber readableUnit; QString readableUnitName; if (tryReadableDisplayUnitForLinearSum(*this, other, *this, &readableUnit, &readableUnitName)) this->setDisplayUnit(readableUnit, readableUnitName); } } return *this; } Quantity& Quantity::operator-=(const Quantity& other) { return operator=(*this - other); } Quantity Quantity::operator*(const Quantity& other) const { if (isCollection() || other.isCollection()) { if ((!isCollection() && (hasUnit() || hasDimension())) || (!other.isCollection() && (other.hasUnit() || other.hasDimension()))) return DMath::nan(InvalidDimension); if (isCollection() && other.isCollection() && (isMatrix() || other.isMatrix())) { const int lhsRows = isList() ? 1 : rows(); const int lhsColumns = columns(); const bool rhsListAsColumn = other.isList() && lhsColumns == other.columns(); const int rhsRows = other.isList() ? (rhsListAsColumn ? other.columns() : 1) : other.rows(); const int rhsColumns = other.isList() ? (rhsListAsColumn ? 1 : other.columns()) : other.columns(); if (lhsColumns != rhsRows) return DMath::nan(DimensionMismatch); QVector> resultRows; for (int r = 0; r < lhsRows; ++r) { QVector row; for (int c = 0; c < rhsColumns; ++c) { Quantity sum(0); for (int k = 0; k < lhsColumns; ++k) { const Quantity& left = isList() ? m_matrix.at(0).at(k) : m_matrix.at(r).at(k); const Quantity& right = other.isList() ? other.m_matrix.at(0).at(rhsListAsColumn ? k : c) : other.m_matrix.at(k).at(c); sum += left * right; } row.append(sum); } resultRows.append(row); } if (resultRows.size() == 1) { if (resultRows.at(0).size() == 1) return resultRows.at(0).at(0); return Quantity::list(resultRows.at(0)); } return Quantity::matrix(resultRows); } const bool lhsCollection = isCollection(); const bool rhsCollection = other.isCollection(); if (lhsCollection && rhsCollection) return DMath::nan(NotImplemented); const QVector> source = lhsCollection ? m_matrix : other.m_matrix; QVector> resultRows; for (int r = 0; r < source.size(); ++r) { QVector row; for (int c = 0; c < source.at(r).size(); ++c) { const Quantity& left = lhsCollection ? m_matrix.at(r).at(c) : *this; const Quantity& right = rhsCollection ? other.m_matrix.at(r).at(c) : other; row.append(left * right); } resultRows.append(row); } return resultRows.size() == 1 ? Quantity::list(resultRows.at(0)) : Quantity::matrix(resultRows); } Quantity result(*this); if (this->isDimensionless() && this->numericValue().isNearReal() && other.hasUnit() && affineTemperatureScaleFromDisplayUnitName(other.unitName()) != AffineTemperatureScale::None) { CNumber scaledBaseValue; if (tryAffineScaleByRealScalar(other, this->numericValue().real, &scaledBaseValue)) { result = other; result.m_numericValue = scaledBaseValue; return result; } } else if (other.isDimensionless() && other.numericValue().isNearReal() && this->hasUnit() && affineTemperatureScaleFromDisplayUnitName(this->unitName()) != AffineTemperatureScale::None) { CNumber scaledBaseValue; if (tryAffineScaleByRealScalar(*this, other.numericValue().real, &scaledBaseValue)) { result = *this; result.m_numericValue = scaledBaseValue; return result; } } result.m_numericValue *= other.m_numericValue; const bool lhsExplicitAngleUnit = this->hasUnit() && Units::isExplicitAngleUnitName(this->unitName()); const bool rhsExplicitAngleUnit = other.hasUnit() && Units::isExplicitAngleUnitName(other.unitName()); const bool lhsExplicitAngleDimensionless = lhsExplicitAngleUnit && this->isDimensionless(); const bool rhsExplicitAngleDimensionless = rhsExplicitAngleUnit && other.isDimensionless(); const auto isPureInverseTimeQuantity = [](const Quantity& quantity) { QMap dimension = quantity.getDimensionByQuantity(); return dimension.size() == 1 && dimension.contains(UnitQuantity::Time) && dimension.value(UnitQuantity::Time) == Rational(-1); }; const auto copyDisplayUnit = [&](const Quantity& source) { result.stripUnits(); result.m_unit = new CNumber(source.unit()); result.m_unitName = source.unitName(); }; const auto chooseBestPrefixForScaledDisplayUnit = [&](const Quantity& source) { CNumber readableUnit; QString readableUnitName; if (tryBestSiPrefixForScaledDisplayUnit(source, result, &readableUnit, &readableUnitName)) result.setDisplayUnit(readableUnit, readableUnitName); }; const auto unitTextContainsExplicitAngleFactor = [](const QString& unitText) { if (unitText.isEmpty()) return false; QString token; auto flushTokenIsAngle = [&]() { if (token.isEmpty()) return false; QString base = token.trimmed(); token.clear(); while (!base.isEmpty() && (UnicodeChars::isSuperscriptDigit(base.at(base.size() - 1)) || UnicodeChars::isSuperscriptSign(base.at(base.size() - 1)))) { base.chop(1); } return !base.isEmpty() && Units::isExplicitAngleUnitName(base); }; for (int i = 0; i < unitText.size(); ++i) { const QChar ch = unitText.at(i); const bool isUnitChar = UnicodeChars::isUnitIdentifierChar(ch) || UnicodeChars::isSuperscriptDigit(ch) || UnicodeChars::isSuperscriptSign(ch); if (isUnitChar) { token += ch; continue; } if (flushTokenIsAngle()) return true; } return flushTokenIsAngle(); }; if (!other.isDimensionless()) { result.stripUnits(); auto i = other.m_dimension.constBegin(); while (i != other.m_dimension.constEnd()) { const auto& exp = i.value(); const auto& name = i.key(); if (!result.m_dimension.contains(name)) result.m_dimension[name] = Rational(0); result.m_dimension[name] += exp; ++i; } result.cleanDimension(); // Preserve preferred display unit when multiplying a dimensionless // value by a quantity with an explicit display unit. if (this->isDimensionless() && other.hasUnit() && !lhsExplicitAngleUnit) { result.m_unit = new CNumber(*other.m_unit); result.m_unitName = other.m_unitName; chooseBestPrefixForScaledDisplayUnit(other); } } if (!result.hasUnit()) { const QString n1 = normalizeUnitName(this->unitName()); const QString n2 = normalizeUnitName(other.unitName()); const UnitId u1 = unitId(n1); const UnitId u2 = unitId(n2); const bool hasExplicitAngleFactorOperand = unitTextContainsExplicitAngleFactor(this->unitName()) || unitTextContainsExplicitAngleFactor(other.unitName()); const bool isNewtonMetrePair = (u1 == UnitId::Newton && u2 == UnitId::Metre) || (u1 == UnitId::Metre && u2 == UnitId::Newton) || (isExactDimension(*this, dimensionNewton()) && isExactDimension(other, dimensionMetre())) || (isExactDimension(*this, dimensionMetre()) && isExactDimension(other, dimensionNewton())); if (!hasExplicitAngleFactorOperand && isNewtonMetrePair) { // Keep N·m explicit by default because it is semantically ambiguous: // energy is expressed in J, while torque is commonly expressed as N·m. // Users can still request an explicit conversion target ("-> joule"). result.setDisplayUnit(this->unit() * other.unit(), QString(unitPhrase(UnitPhraseId::NewtonMetre))); } else if (!hasExplicitAngleFactorOperand && ((u1 == UnitId::Pascal && isExactDimension(other, dimensionCubicMetre())) || (u2 == UnitId::Pascal && isExactDimension(*this, dimensionCubicMetre())))) { result.setDisplayUnit(this->unit() * other.unit(), QString(::unitName(UnitId::Joule))); } else if (!hasExplicitAngleFactorOperand && ((u1 == UnitId::Watt && u2 == UnitId::Second) || (u2 == UnitId::Watt && u1 == UnitId::Second) || (isExactDimension(*this, dimensionWatt()) && isExactDimension(other, dimensionSecond()) && !other.hasUnit()) || (isExactDimension(*this, dimensionSecond()) && isExactDimension(other, dimensionWatt()) && !this->hasUnit()))) { // Keep W·s explicit by default: although dimensionally equal to J, // it often conveys time-integration context (power over time). // Auto-collapsing to J can hide that intent unless user requests // an explicit conversion ("-> joule"). result.setDisplayUnit(this->unit() * other.unit(), QString(unitPhrase(UnitPhraseId::WattSecond))); } else if (!hasExplicitAngleFactorOperand && ((u1 == UnitId::Coulomb && u2 == UnitId::Volt) || (u2 == UnitId::Coulomb && u1 == UnitId::Volt))) { result.setDisplayUnit(this->unit() * other.unit(), QString(::unitName(UnitId::Joule))); } else if (!hasExplicitAngleFactorOperand && ((isExactDimension(*this, dimensionVolt()) && isExactDimension(other, dimensionSecond())) || (isExactDimension(other, dimensionVolt()) && isExactDimension(*this, dimensionSecond())))) { result.setDisplayUnit(this->unit() * other.unit(), QString(::unitName(UnitId::Weber))); } else if (!hasExplicitAngleFactorOperand && ((isExactDimension(*this, dimensionVolt()) && isExactDimension(other, dimensionAmpere())) || (isExactDimension(other, dimensionVolt()) && isExactDimension(*this, dimensionAmpere())))) { result.setDisplayUnit(this->unit() * other.unit(), QString(::unitName(UnitId::Watt))); } else if (!hasExplicitAngleFactorOperand && ((isExactDimension(*this, dimensionWatt()) && isExactDimension(other, dimensionVolt())) || (isExactDimension(other, dimensionWatt()) && isExactDimension(*this, dimensionVolt())))) { result.setDisplayUnit(this->unit() * other.unit(), QString(unitPhrase(UnitPhraseId::VoltSquaredAmpere))); } else if (!hasExplicitAngleFactorOperand && ((isExactDimension(*this, dimensionFarad()) && isExactDimension(other, dimensionVolt())) || (isExactDimension(other, dimensionFarad()) && isExactDimension(*this, dimensionVolt())))) { result.setDisplayUnit(this->unit() * other.unit(), QString(::unitName(UnitId::Coulomb))); } else if (!hasExplicitAngleFactorOperand && ((isExactDimension(*this, dimensionTesla()) && isExactDimension(other, dimensionSquareMetre())) || (isExactDimension(other, dimensionTesla()) && isExactDimension(*this, dimensionSquareMetre())))) { result.setDisplayUnit(this->unit() * other.unit(), QString(::unitName(UnitId::Weber))); } else if (!hasExplicitAngleFactorOperand && ((isExactDimension(*this, dimensionPascal()) && isExactDimension(other, dimensionSquareMetre())) || (isExactDimension(other, dimensionPascal()) && isExactDimension(*this, dimensionSquareMetre())))) { result.setDisplayUnit(this->unit() * other.unit(), QString(::unitName(UnitId::Newton))); } else if (((this->hasUnit() && Units::isExplicitAngleUnitName(this->unitName()) && isPureInverseTimeQuantity(other)) || (other.hasUnit() && Units::isExplicitAngleUnitName(other.unitName()) && isPureInverseTimeQuantity(*this)))) { const QString angleUnitName = this->hasUnit() && Units::isExplicitAngleUnitName(this->unitName()) ? this->unitName() : other.unitName(); result.setDisplayUnit(this->unit() * other.unit(), composeAnglePerSecondUnitName(angleUnitName)); } else if (this->hasUnit() && other.hasUnit() && !result.isDimensionless() && !(isExactDimension(*this, dimensionMetre()) && isExactDimension(other, dimensionMetre()))) { result.setDisplayUnit(this->unit() * other.unit(), composeProductUnitName(this->unitName(), other.unitName())); } else if (!hasExplicitAngleFactorOperand && ((isSteradianUnitName(n1) && isExactDimension(other, dimensionCandela())) || (isSteradianUnitName(n2) && isExactDimension(*this, dimensionCandela())))) { // This mapping is unambiguous in this context: cd·sr is luminous flux. result.setDisplayUnit(this->unit() * other.unit(), QString(::unitName(UnitId::Lumen))); } } if (!result.hasUnit()) { if (this->isDimensionless() && other.hasUnit()) { copyDisplayUnit(other); chooseBestPrefixForScaledDisplayUnit(other); } else if (other.isDimensionless() && this->hasUnit()) { copyDisplayUnit(*this); chooseBestPrefixForScaledDisplayUnit(*this); } } if (lhsExplicitAngleDimensionless && !other.isDimensionless()) { QString otherUnitName = other.unitName(); if (otherUnitName.isEmpty()) { Quantity canonical(other); canonical.cleanDimension(); Units::findUnit(canonical); otherUnitName = canonical.unitName(); } const QString displayName = isPureInverseTimeQuantity(other) ? composeAnglePerSecondUnitName(this->unitName()) : composeProductUnitName(this->unitName(), otherUnitName); result.setDisplayUnit(this->unit() * other.unit(), displayName); } else if (rhsExplicitAngleDimensionless && !this->isDimensionless()) { QString thisUnitName = this->unitName(); if (thisUnitName.isEmpty()) { Quantity canonical(*this); canonical.cleanDimension(); Units::findUnit(canonical); thisUnitName = canonical.unitName(); } const QString displayName = isPureInverseTimeQuantity(*this) ? composeAnglePerSecondUnitName(other.unitName()) : composeProductUnitName(other.unitName(), thisUnitName); result.setDisplayUnit(this->unit() * other.unit(), displayName); } if (!result.hasUnit() && !result.isDimensionless()) { if (this->hasUnit() && !other.hasUnit() && !other.isDimensionless() && unitTextContainsExplicitAngleFactor(this->unitName())) { Quantity canonical(other); canonical.cleanDimension(); Units::findUnit(canonical); if (canonical.hasUnit()) { result.setDisplayUnit(this->unit() * other.unit(), composeProductUnitName(this->unitName(), canonical.unitName())); } } else if (other.hasUnit() && !this->hasUnit() && !this->isDimensionless() && unitTextContainsExplicitAngleFactor(other.unitName())) { Quantity canonical(*this); canonical.cleanDimension(); Units::findUnit(canonical); if (canonical.hasUnit()) { result.setDisplayUnit(this->unit() * other.unit(), composeProductUnitName(other.unitName(), canonical.unitName())); } } } if (result.hasUnit()) { const QString factorSimplified = simplifyRepeatedCompositeDisplayUnitFactors(result.unitName()); if (factorSimplified != result.unitName()) result.setDisplayUnit(result.unit(), factorSimplified); const QString simplified = simplifyExplicitAngleCompositeDisplayUnits(result.unitName()); if (simplified != result.unitName()) result.setDisplayUnit(result.unit(), simplified); } return result; } Quantity Quantity::operator*(const CNumber& other) const { Quantity result(*this); result.m_numericValue *= other; return result; } Quantity Quantity::operator*(const HNumber& other) const { return operator*(CNumber(other)); } Quantity &Quantity::operator*=(const Quantity& other) { return operator=(*this * other); } Quantity Quantity::operator/(const Quantity& other) const { if (isCollection() || other.isCollection()) { if ((!isCollection() && (hasUnit() || hasDimension())) || (!other.isCollection() && (other.hasUnit() || other.hasDimension()))) return DMath::nan(InvalidDimension); if (other.isCollection() && !isCollection()) return DMath::nan(NotImplemented); if (isCollection() && other.isCollection()) return DMath::nan(NotImplemented); QVector> resultRows; for (int r = 0; r < m_matrix.size(); ++r) { QVector row; for (int c = 0; c < m_matrix.at(r).size(); ++c) { const Quantity& divisor = other.isCollection() ? other.m_matrix.at(r).at(c) : other; row.append(m_matrix.at(r).at(c) / divisor); } resultRows.append(row); } return resultRows.size() == 1 ? Quantity::list(resultRows.at(0)) : Quantity::matrix(resultRows); } Quantity result(*this); if (other.isDimensionless() && other.numericValue().isNearReal() && this->hasUnit() && affineTemperatureScaleFromDisplayUnitName(this->unitName()) != AffineTemperatureScale::None) { CNumber scaledBaseValue; if (tryAffineScaleByRealScalar(*this, HNumber(1) / other.numericValue().real, &scaledBaseValue)) { result = *this; result.m_numericValue = scaledBaseValue; return result; } } result.m_numericValue /= other.m_numericValue; const auto isPureTimeQuantity = [](const Quantity& quantity) { QMap dimension = quantity.getDimensionByQuantity(); return dimension.size() == 1 && dimension.contains(UnitQuantity::Time) && dimension.value(UnitQuantity::Time) == Rational(1); }; const auto copyDisplayUnit = [&](const Quantity& source) { result.stripUnits(); result.m_unit = new CNumber(source.unit()); result.m_unitName = source.unitName(); }; const auto unitTextContainsExplicitAngleFactor = [](const QString& unitText) { if (unitText.isEmpty()) return false; QString token; auto flushTokenIsAngle = [&]() { if (token.isEmpty()) return false; QString base = token.trimmed(); token.clear(); while (!base.isEmpty() && (UnicodeChars::isSuperscriptDigit(base.at(base.size() - 1)) || UnicodeChars::isSuperscriptSign(base.at(base.size() - 1)))) { base.chop(1); } return !base.isEmpty() && Units::isExplicitAngleUnitName(base); }; for (int i = 0; i < unitText.size(); ++i) { const QChar ch = unitText.at(i); const bool isUnitChar = UnicodeChars::isUnitIdentifierChar(ch) || UnicodeChars::isSuperscriptDigit(ch) || UnicodeChars::isSuperscriptSign(ch); if (isUnitChar) { token += ch; continue; } if (flushTokenIsAngle()) return true; } return flushTokenIsAngle(); }; const auto firstExplicitAngleFactorToken = [](const QString& unitText) -> QString { if (unitText.isEmpty()) return QString(); QString token; const QString degreeName = ::unitName(UnitId::Degree); const QString degreeAlias = Units::degreeAliasSymbol(); auto normalizeAngleToken = [&](const QString& rawToken) -> QString { QString normalized = rawToken.trimmed(); if (normalized.isEmpty()) return normalized; int suffixStart = normalized.size(); while (suffixStart > 0) { const QChar ch = normalized.at(suffixStart - 1); if (!UnicodeChars::isSuperscriptDigit(ch) && !UnicodeChars::isSuperscriptSign(ch)) { break; } --suffixStart; } QString base = normalized.left(suffixStart).trimmed(); const QString exponentSuffix = normalized.mid(suffixStart); while (!base.isEmpty() && (UnicodeChars::isSuperscriptDigit(base.at(base.size() - 1)) || UnicodeChars::isSuperscriptSign(base.at(base.size() - 1)))) { base.chop(1); } if (!Units::isExplicitAngleUnitName(base)) return QString(); if (base.startsWith(UnicodeChars::DegreeSign)) return degreeAlias + base.mid(1) + exponentSuffix; if (base.startsWith(degreeName)) { const int n = degreeName.size(); if (base.size() == n || !base.at(n).isLetter()) return degreeAlias + base.mid(n) + exponentSuffix; } if (base.startsWith(degreeAlias)) return base + exponentSuffix; return base + exponentSuffix; }; auto flushToken = [&]() { if (token.isEmpty()) return QString(); QString raw = token; token.clear(); return normalizeAngleToken(raw); }; for (int i = 0; i < unitText.size(); ++i) { const QChar ch = unitText.at(i); const bool isUnitChar = UnicodeChars::isUnitIdentifierChar(ch) || UnicodeChars::isSuperscriptDigit(ch) || UnicodeChars::isSuperscriptSign(ch); if (isUnitChar) { token += ch; continue; } const QString factor = flushToken(); if (!factor.isEmpty()) return factor; } return flushToken(); }; if (!other.isDimensionless()) { result.stripUnits(); auto i = other.m_dimension.constBegin(); while (i != other.m_dimension.constEnd()) { const auto& exp = i.value(); const auto& name = i.key(); if (!result.m_dimension.contains(name)) result.m_dimension[name] = Rational(0); result.m_dimension[name] -= exp; ++i; } result.cleanDimension(); const QString n1 = normalizeUnitName(this->unitName()); const UnitId u1 = unitId(n1); // Keep user-intended energy-per-geometry forms in their original domain // unless conversion is explicitly requested, to avoid context loss: // J/m² (energy/area) vs N/m (force/length), and // J/m³ (energy density) vs Pa (pressure). // These unprefixed SI labels need an SI scale. Keeping the operands' // scale would hide their conversion factor from the displayed value. if (((this->hasUnit() && u1 == UnitId::Joule) || isExactDimension(*this, dimensionJoule())) && isExactDimension(other, dimensionSquareMetre())) { result.setDisplayUnit(CNumber(1), QString(unitPhrase(UnitPhraseId::JoulePerSquareMetre))); return result; } if (((this->hasUnit() && u1 == UnitId::Joule) || isExactDimension(*this, dimensionJoule())) && isExactDimension(other, dimensionCubicMetre())) { result.setDisplayUnit(CNumber(1), QString(unitPhrase(UnitPhraseId::JoulePerCubicMetre))); return result; } if (isExactDimension(*this, dimensionJoule()) && isExactDimension(other, dimensionSecond())) { result.setDisplayUnit(this->unit() / other.unit(), QString(::unitName(UnitId::Watt))); return result; } // Preserve explicit angle-unit intent for angular-rate expressions, // even when the denominator unit has no own display token (e.g. minute). if (this->hasUnit() && Units::isExplicitAngleUnitName(this->unitName()) && isPureTimeQuantity(other)) { result.setDisplayUnit(this->unit() / other.unit(), composeAnglePerSecondUnitName(this->unitName())); return result; } if (this->hasUnit() && other.hasUnit() && !result.isDimensionless()) { Quantity canonical(result); canonical.cleanDimension(); Units::findUnit(canonical); const bool hasExplicitAngleFactorOperand = unitTextContainsExplicitAngleFactor(this->unitName()) || unitTextContainsExplicitAngleFactor(other.unitName()); if (hasExplicitAngleFactorOperand) { QString angleFactorToken = firstExplicitAngleFactorToken(this->unitName()); if (angleFactorToken.isEmpty()) angleFactorToken = firstExplicitAngleFactorToken(other.unitName()); QString canonicalName = canonical.unitName(); QString displayName; if (canonicalName.isEmpty()) { displayName = angleFactorToken; } else if (unitTextContainsExplicitAngleFactor(canonicalName)) { displayName = canonicalName; } else if (!angleFactorToken.isEmpty()) { displayName = composeProductUnitName(angleFactorToken, canonicalName); } else { displayName = canonicalName; } if (!displayName.isEmpty()) { const CNumber displayUnitValue = canonical.hasUnit() ? canonical.unit() : (this->unit() / other.unit()); result.setDisplayUnit(displayUnitValue, displayName); return result; } } const UnitId canonicalId = unitId(normalizeUnitName(canonical.unitName())); if (isPreferredCanonicalDisplayUnit(canonicalId)) { result.setDisplayUnit(canonical.unit(), canonical.unitName()); } else if (isSpeedDimension(result.getDimensionByQuantity())) { QString speedUnitName; CNumber speedUnitValue; if (tryNamedSpeedDisplayUnit(this->unit() / other.unit(), &speedUnitName, &speedUnitValue)) { result.setDisplayUnit(speedUnitValue, speedUnitName); } else { result.setDisplayUnit(this->unit() / other.unit(), composeQuotientUnitName(this->unitName(), other.unitName())); } } else { result.setDisplayUnit(this->unit() / other.unit(), composeQuotientUnitName(this->unitName(), other.unitName())); } return result; } if (!result.hasUnit() && !result.isDimensionless() && this->hasUnit() && !other.hasUnit() && unitTextContainsExplicitAngleFactor(this->unitName())) { Quantity canonicalResult(result); canonicalResult.cleanDimension(); Units::findUnit(canonicalResult); QString angleFactorToken = firstExplicitAngleFactorToken(this->unitName()); QString canonicalName = canonicalResult.unitName(); QString displayName; if (canonicalName.isEmpty()) { displayName = angleFactorToken; } else if (unitTextContainsExplicitAngleFactor(canonicalName)) { displayName = canonicalName; } else if (!angleFactorToken.isEmpty()) { displayName = composeProductUnitName(angleFactorToken, canonicalName); } else { displayName = canonicalName; } if (!displayName.isEmpty()) { const CNumber displayUnitValue = canonicalResult.hasUnit() ? canonicalResult.unit() : (this->unit() / other.unit()); result.setDisplayUnit(displayUnitValue, displayName); return result; } } } else if (this->hasUnit()) { const bool divisorHasExplicitAngleUnit = other.hasUnit() && Units::isExplicitAngleUnitName(other.unitName()); if (divisorHasExplicitAngleUnit) { result.setDisplayUnit(this->unit() / other.unit(), composeQuotientUnitName(this->unitName(), other.unitName())); } else { copyDisplayUnit(*this); } } else if (other.hasUnit() && Units::isExplicitAngleUnitName(other.unitName()) && !result.isDimensionless()) { Quantity canonicalNumerator(*this); canonicalNumerator.cleanDimension(); Units::findUnit(canonicalNumerator); if (canonicalNumerator.hasUnit()) { result.setDisplayUnit(canonicalNumerator.unit() / other.unit(), composeQuotientUnitName(canonicalNumerator.unitName(), other.unitName())); } } if (result.hasUnit()) { const QString simplified = simplifyExplicitAngleCompositeDisplayUnits(result.unitName()); if (simplified != result.unitName()) result.setDisplayUnit(result.unit(), simplified); } return result; } Quantity Quantity::operator/(const HNumber& other) const { return operator/(CNumber(other)); } Quantity Quantity::operator/(const CNumber& other) const { Quantity result(*this); result.m_numericValue /= other; result.cleanDimension(); return result; } Quantity &Quantity::operator/=(const Quantity& other) { return operator=(*this/other); } Quantity Quantity::operator%(const Quantity& other) const { Quantity result(*this); result.m_numericValue = result.m_numericValue % other.m_numericValue; return result; } Quantity Quantity::operator&(const Quantity& other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue &= other.m_numericValue; return result; } Quantity &Quantity::operator&=(const Quantity& other) { return operator=(*this & other); } Quantity Quantity::operator|(const Quantity& other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue |= other.m_numericValue; return result; } Quantity &Quantity::operator|=(const Quantity& other) { return operator=(*this | other); } Quantity Quantity::operator^(const Quantity& other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue ^= other.m_numericValue; return result; } Quantity &Quantity::operator^=(const Quantity& other) { return operator=(*this ^ other); } Quantity Quantity::operator~() const { ENSURE_DIMENSIONLESS(*this); Quantity result(*this); result.m_numericValue= ~result.m_numericValue; return result; } Quantity Quantity::operator>>(const Quantity& other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue = result.m_numericValue >> other.m_numericValue; return result; } Quantity Quantity::operator<<(const Quantity& other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue = result.m_numericValue << other.m_numericValue; return result; } Quantity::Format::Format() : CNumber::Format() { } Quantity::Format::Format(const CNumber::Format& other) : CNumber::Format(other) { } Quantity::Format::Format(const HNumber::Format& other) : CNumber::Format(other) { } Quantity::Format Quantity::Format::operator+(const Quantity::Format& other) const { return Quantity::Format(CNumber::Format::operator+(static_cast(other))); } void Quantity::Format::serialize(QJsonObject& json) const { switch (mode) { case Mode::General: json["mode"] = QStringLiteral("General"); break; case Mode::Fixed: json["mode"] = QStringLiteral("Fixed"); break; case Mode::Scientific: json["mode"] = QStringLiteral("Scientific"); break; case Mode::Engineering: json["mode"] = QStringLiteral("Engineering"); break; case Mode::Sexagesimal: json["mode"] = QStringLiteral("Sexagesimal"); break; case Mode::Null: break; } switch (base) { case Base::Binary: json["base"] = QStringLiteral("Binary"); break; case Base::Octal: json["base"] = QStringLiteral("Octal"); break; case Base::Hexadecimal: json["base"] = QStringLiteral("Hexadecimal"); break; case Base::Decimal: json["base"] = QStringLiteral("Decimal"); break; case Base::Null: break; } switch (notation) { case Notation::Cartesian: json["form"] = ComplexForm::toString(ComplexForm::Rectangular); break; case Notation::Polar: json["form"] = ComplexForm::toString(ComplexForm::Exponential); break; case Notation::Trigonometric: json["form"] = ComplexForm::toString(ComplexForm::Trigonometric); break; case Notation::Cis: json["form"] = ComplexForm::toString(ComplexForm::Cis); break; case Notation::PolarAngle: json["form"] = ComplexForm::toString(ComplexForm::Phasor); break; case Notation::Null: default: break; } if (precision != PrecisionNull) json["precision"] = precision; if (paddedBits != 0) json["padded_bits"] = paddedBits; if (forcedExponent != ForcedExponentNull) json["forced_exponent"] = forcedExponent; } Quantity::Format Quantity::Format::deSerialize(const QJsonObject& json) { Format result; if (json.contains("mode")) { auto strMode = json["mode"].toString(); if (strMode == "General") result.mode = Mode::General; else if (strMode == "Fixed") result.mode = Mode::Fixed; else if (strMode == "Scientific") result.mode = Mode::Scientific; else if (strMode == "Engineering") result.mode = Mode::Engineering; else if (strMode == "Sexagesimal") result.mode = Mode::Sexagesimal; else result.mode = Mode::Null; } else result.mode = Mode::Null; if (json.contains("base")) { auto strBase = json["base"].toString(); if (strBase == "Binary") result.base = Base::Binary; else if (strBase == "Octal") result.base = Base::Octal; else if (strBase == "Decimal") result.base = Base::Decimal; else if (strBase == "Hexadecimal") result.base = Base::Hexadecimal; else result.base = Base::Null; } else result.base = Base::Null; if (json.contains("form")) { const char form = ComplexForm::fromString(json["form"].toString(), '\0'); if (form == ComplexForm::Rectangular) result.notation = Notation::Cartesian; else if (form == ComplexForm::Exponential) result.notation = Notation::Polar; else if (form == ComplexForm::Trigonometric) result.notation = Notation::Trigonometric; else if (form == ComplexForm::Cis) result.notation = Notation::Cis; else if (form == ComplexForm::Phasor) result.notation = Notation::PolarAngle; else result.notation = Notation::Null; } else result.notation = Notation::Null; result.precision = json.contains("precision") ? json["precision"].toInt() : PrecisionNull; result.paddedBits = json.contains("padded_bits") ? json["padded_bits"].toInt() : 0; result.forcedExponent = json.contains("forced_exponent") ? json["forced_exponent"].toInt() : ForcedExponentNull; return result; } bool Quantity::Format::isNull() const { return (mode == Mode::Null && base == Base::Null && precision == PrecisionNull && notation == Notation::Null && paddedBits == 0 && forcedExponent == ForcedExponentNull); } // DMath // ===== bool DMath::complexMode = true; #define COMPLEX_WRAP_1(fct, arg) \ (DMath::complexMode ? CMath::fct(arg) : CNumber(HMath::fct(arg.real))) #define COMPLEX_WRAP_2(fct, arg1, arg2) \ (DMath::complexMode ? CMath::fct(arg1, arg2) : CNumber(HMath::fct(arg1.real, arg2.real))) #define COMPLEX_WRAP_3(fct, arg1, arg2, arg3) \ (DMath::complexMode ? CMath::fct(arg1, arg2, arg3) : CNumber(HMath::fct(arg1.real, arg2.real, arg3.real))) #define COMPLEX_WRAP_4(fct, arg1, arg2, arg3, arg4) \ (DMath::complexMode ? CMath::fct(arg1, arg2, arg3, arg4) \ : CNumber(HMath::fct(arg1.real, arg2.real, arg3.real, arg4.real))) // Wrappers for functions that are only defined for dimensionless arguments // Mo argument. #define WRAPPER_DMATH_0(fct) \ Quantity DMath::fct() \ { \ return Quantity(CMath::fct()); \ } \ // One argument. #define WRAPPER_DMATH_1(fct) \ Quantity DMath::fct(const Quantity& arg1) \ { \ ENSURE_DIMENSIONLESS(arg1); \ return Quantity(COMPLEX_WRAP_1(fct, arg1.m_numericValue)); \ } // Two arguments. #define WRAPPER_DMATH_2(fct) \ Quantity DMath::fct(const Quantity& arg1, const Quantity& arg2) \ { \ ENSURE_DIMENSIONLESS(arg1); \ ENSURE_DIMENSIONLESS(arg2); \ return Quantity(COMPLEX_WRAP_2(fct, arg1.m_numericValue, arg2.m_numericValue)); \ } // Three arguments. #define WRAPPER_DMATH_3(fct) \ Quantity DMath::fct(const Quantity& arg1, const Quantity& arg2, const Quantity& arg3) \ { \ ENSURE_DIMENSIONLESS(arg1); \ ENSURE_DIMENSIONLESS(arg2); \ ENSURE_DIMENSIONLESS(arg3); \ return Quantity(COMPLEX_WRAP_3(fct, arg1.m_numericValue, arg2.m_numericValue, arg3.m_numericValue)); \ } // Four arguments. #define WRAPPER_DMATH_4(fct) \ Quantity DMath::fct(const Quantity& arg1, const Quantity& arg2, const Quantity& arg3, const Quantity& arg4) \ { \ ENSURE_DIMENSIONLESS(arg1); \ ENSURE_DIMENSIONLESS(arg2); \ ENSURE_DIMENSIONLESS(arg3); \ ENSURE_DIMENSIONLESS(arg4); \ return Quantity(COMPLEX_WRAP_4(fct, arg1.m_numericValue, arg2.m_numericValue, arg3.m_numericValue, \ arg4.m_numericValue)); \ } WRAPPER_DMATH_0(e) WRAPPER_DMATH_0(pi) WRAPPER_DMATH_0(phi) WRAPPER_DMATH_0(i) Quantity DMath::nan(Error error) { return Quantity(CMath::nan(error)); } WRAPPER_DMATH_1(rad2deg) WRAPPER_DMATH_1(deg2rad) WRAPPER_DMATH_1(rad2gon) WRAPPER_DMATH_1(gon2rad) WRAPPER_DMATH_1(integer) WRAPPER_DMATH_1(frac) WRAPPER_DMATH_1(floor) WRAPPER_DMATH_1(ceil) WRAPPER_DMATH_1(exp) WRAPPER_DMATH_1(ln) WRAPPER_DMATH_1(lg) WRAPPER_DMATH_1(lb) WRAPPER_DMATH_2(log) WRAPPER_DMATH_1(sinh) WRAPPER_DMATH_1(cosh) WRAPPER_DMATH_1(tanh) WRAPPER_DMATH_1(arsinh) WRAPPER_DMATH_1(arcosh) WRAPPER_DMATH_1(artanh) WRAPPER_DMATH_1(sin) WRAPPER_DMATH_1(cos) WRAPPER_DMATH_1(tan) WRAPPER_DMATH_1(cot) WRAPPER_DMATH_1(sec) WRAPPER_DMATH_1(csc) WRAPPER_DMATH_1(arcsin) WRAPPER_DMATH_1(arccos) WRAPPER_DMATH_1(arctan) WRAPPER_DMATH_2(arctan2) WRAPPER_DMATH_2(factorial) WRAPPER_DMATH_1(gamma) WRAPPER_DMATH_1(lnGamma) WRAPPER_DMATH_1(erf) WRAPPER_DMATH_1(erfc) WRAPPER_DMATH_2(gcd) WRAPPER_DMATH_2(lcm) WRAPPER_DMATH_2(idiv) Quantity DMath::round(const Quantity& n, int prec) { ENSURE_DIMENSIONLESS(n); return DMath::complexMode ? CMath::round(n.numericValue(), prec) : CNumber(HMath::round(n.numericValue().real, prec)); } Quantity DMath::trunc(const Quantity& n, int prec) { ENSURE_DIMENSIONLESS(n); return DMath::complexMode ? CMath::trunc(n.numericValue(), prec) : CNumber(HMath::trunc(n.numericValue().real, prec)); } WRAPPER_DMATH_2(nCr) WRAPPER_DMATH_2(nPr) WRAPPER_DMATH_3(binomialPmf) WRAPPER_DMATH_3(binomialCdf) WRAPPER_DMATH_2(binomialMean) WRAPPER_DMATH_2(binomialVariance) WRAPPER_DMATH_4(hypergeometricPmf) WRAPPER_DMATH_4(hypergeometricCdf) WRAPPER_DMATH_3(hypergeometricMean) WRAPPER_DMATH_3(hypergeometricVariance) WRAPPER_DMATH_2(poissonPmf) WRAPPER_DMATH_2(poissonCdf) WRAPPER_DMATH_1(poissonMean) WRAPPER_DMATH_1(poissonVariance) WRAPPER_DMATH_2(mask) WRAPPER_DMATH_2(sgnext) WRAPPER_DMATH_2(ashr) WRAPPER_DMATH_3(decodeIeee754) WRAPPER_DMATH_4(decodeIeee754) QString DMath::format(Quantity q, Quantity::Format format) { if (q.isCollection()) { const QString listStart(MathDsl::ListStart); const QString listEnd(MathDsl::ListEnd); QStringList rowTexts; for (const QVector& row : q.matrix()) { QStringList elementTexts; for (const Quantity& element : row) elementTexts << DMath::format(element, format); rowTexts << (listStart + elementTexts.join(QStringLiteral("; ")) + listEnd); } if (q.isList()) return rowTexts.value(0); return listStart + rowTexts.join(QStringLiteral("; ")) + listEnd; } format = q.format() + format; // Left hand side operator takes priority. // Handle units. if (!q.hasUnit() && !q.isDimensionless()) { q.cleanDimension(); Units::findUnit(q); } const QString normalizedUnitName = normalizeDisplayUnitNameForOutput(q.unitName()); const bool hasUnitSuffix = !normalizedUnitName.isEmpty(); const bool compactDegreeSuffix = normalizedUnitName == QString(UnicodeChars::DegreeSign); const QString unit_name = hasUnitSuffix ? (compactDegreeSuffix ? normalizedUnitName : (QStringLiteral(" ") + normalizedUnitName)) : QString(); CNumber unit = q.unit(); CNumber number = q.m_numericValue; number /= unit; if (number.isNearReal()) { HNumber affineValue; if (Units::tryConvertAffineFromBase(q.unitName(), number.real, &affineValue)) number.real = affineValue; } QString result = CMath::format(number, format); if (!number.real.isZero() && !number.imag.isZero() && hasUnitSuffix) result = "(" + result + ")"; if (hasUnitSuffix) result.append(unit_name); return result; } Quantity DMath::real(const Quantity& x) { Quantity result(x); result.m_numericValue = result.m_numericValue.real; return result; } Quantity DMath::imag(const Quantity& x) { Quantity result(x); result.m_numericValue = result.m_numericValue.imag; return result; } Quantity DMath::conj(const Quantity& n) { Quantity result = Quantity(n); // If in Real mode, just strip the imaginary part. result.m_numericValue = complexMode ? CMath::conj(result.m_numericValue) : CMath::real(result.m_numericValue); return result; } Quantity DMath::abs(const Quantity& n) { Quantity result(n); result.m_numericValue = COMPLEX_WRAP_1(abs, n.m_numericValue); return result; } Quantity DMath::phase(const Quantity& n) { return CMath::phase(n.numericValue()); } Quantity DMath::sqrt(const Quantity& n) { Quantity result(COMPLEX_WRAP_1(sqrt, n.m_numericValue)); auto i = n.m_dimension.constBegin(); while (i != n.m_dimension.constEnd()) { auto& exp = i.value(); auto& name = i.key(); result.modifyDimension(name, exp * Rational(1,2)); ++i; } return result; } Quantity DMath::cbrt(const Quantity& n) { Quantity result(COMPLEX_WRAP_1(cbrt, n.m_numericValue)); auto i = n.m_dimension.constBegin(); while (i != n.m_dimension.constEnd()) { auto& exp = i.value(); auto& name = i.key(); result.modifyDimension(name, exp * Rational(1,3)); ++i; } return result; } Quantity DMath::root(const Quantity& n, const Quantity& x) { ENSURE_DIMENSIONLESS(n); if (x.isCollection() || n.isCollection() || !n.isInteger() || !n.isPositive()) return nan(OutOfDomain); const HNumber index = n.numericValue().real; if (!x.isDimensionless() && index > HNumber(std::numeric_limits::max())) return nan(OutOfDomain); if (index == HNumber(1)) return x; if (index == HNumber(2)) return sqrt(x); if (index == HNumber(3) && x.isReal()) return cbrt(x); const HNumber exponent = HNumber(1) / index; const CNumber value = x.numericValue(); CNumber numericRoot; if (value.isReal() && (!value.isNegative() || (index % HNumber(2)) == HNumber(1))) { // Use the magnitude so odd roots stay real even in complex mode. const HNumber magnitude = HMath::raise(HMath::abs(value.real), exponent); numericRoot = value.isNegative() ? -magnitude : magnitude; } else { if (!complexMode) return nan(OutOfDomain); numericRoot = CMath::raise(value, CNumber(exponent)); } Quantity result(numericRoot); if (!x.isDimensionless()) { const Rational dimensionExponent(1, index.toInt()); for (auto i = x.m_dimension.constBegin(); i != x.m_dimension.constEnd(); ++i) result.modifyDimension(i.key(), i.value() * dimensionExponent); } return result; } Quantity DMath::raise(const Quantity& n1, int n) { Quantity result; result.m_numericValue = complexMode ? CMath::raise(n1.m_numericValue, n) : CNumber(HMath::raise(n1.m_numericValue.real, n)); auto i = n1.m_dimension.constBegin(); while (i != n1.m_dimension.constEnd()) { auto& exp = i.value(); auto& name = i.key(); result.modifyDimension(name, exp * n); ++i; } if (n1.hasUnit() && n != 0) { result.setDisplayUnit(CMath::raise(n1.unit(), n), formatUnitFactorWithExponent(n1.unitName(), n)); } return result; } Quantity DMath::raise(const Quantity& n1, const Quantity& n2) { if (!n2.isDimensionless() || (!n1.isDimensionless() && !n2.isReal() && complexMode)) return DMath::nan(InvalidDimension); // First get the new numeric value. Quantity result(COMPLEX_WRAP_2(raise, n1.m_numericValue, n2.m_numericValue)); if (n1.isDimensionless()) { Rational exponent(n2.m_numericValue.real); if (n1.hasUnit() && abs(exponent.toHNumber() - n2.m_numericValue.real) < RATIONAL_TOL && exponent.denominator() == 1 && exponent.numerator() != 0) { const int integerExponent = exponent.numerator(); result.setDisplayUnit(CMath::raise(n1.unit(), integerExponent), formatUnitFactorWithExponent(n1.unitName(), integerExponent)); } return result; } // We can now assume that n1 has a dimension, but n2 is real. // Compute the new dimension: try to convert n2 to a Rational. If n2 is not // rational, return NaN. // For negative bases only allow odd denominators. Rational exponent(n2.m_numericValue.real); if (abs(exponent.toHNumber() - n2.m_numericValue.real) >= RATIONAL_TOL || (n1.isNegative() && exponent.denominator() % 2 == 0)) return DMath::nan(OutOfDomain); // Compute new dimension. auto i = n1.m_dimension.constBegin(); while (i != n1.m_dimension.constEnd()) { result.modifyDimension(i.key(), i.value()*exponent); ++i; } return result; } Quantity DMath::sgn(const Quantity& x) { return Quantity(CMath::sgn(x.m_numericValue)); } Quantity DMath::encodeIeee754(const Quantity& val, const Quantity& exp_bits, const Quantity& significand_bits) { ENSURE_DIMENSIONLESS(val); ENSURE_DIMENSIONLESS(exp_bits); ENSURE_DIMENSIONLESS(significand_bits); Quantity result(CMath::encodeIeee754(val.numericValue(), exp_bits.numericValue(), significand_bits.numericValue())); result.m_format = result.m_format + Quantity::Format::Fixed() + Quantity::Format::Hexadecimal(); return result; } Quantity DMath::encodeIeee754(const Quantity& val, const Quantity& exp_bits, const Quantity& significand_bits, const Quantity& exp_bias) { ENSURE_DIMENSIONLESS(val); ENSURE_DIMENSIONLESS(exp_bits); ENSURE_DIMENSIONLESS(significand_bits); ENSURE_DIMENSIONLESS(exp_bias); Quantity result(CMath::encodeIeee754(val.numericValue(), exp_bits.numericValue(), significand_bits.numericValue(), exp_bias.numericValue())); result.m_format = result.m_format + Quantity::Format::Fixed() + Quantity::Format::Hexadecimal(); return result; } heldercorreia-speedcrunch-e7ca37f/src/math/quantity.h000066400000000000000000000216321526573132500231100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2016-2018, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef QUANTITY_H #define QUANTITY_H #include "cmath.h" #include "hmath.h" #include "core/errors.h" #include #include class CNumber; class HNumber; class QJsonObject; class QString; class Rational; enum class UnitQuantity; class DMath; class Quantity; Quantity operator*(const HNumber&, const Quantity&); Quantity operator*(const CNumber&, const Quantity&); Quantity operator/(const HNumber&, const Quantity&); Quantity operator/(const CNumber&, const Quantity&); class Quantity { friend class DMath; friend Quantity operator-(const Quantity&); friend Quantity operator-(const Quantity&, const Quantity&); friend bool operator>(const Quantity&, const Quantity&); friend bool operator<(const Quantity&, const Quantity&); friend bool operator>=(const Quantity&, const Quantity&); friend bool operator<=(const Quantity&, const Quantity&); friend bool operator==(const Quantity&, const Quantity&); friend bool operator!=(const Quantity&, const Quantity&); public: Quantity(); Quantity(const Quantity&); Quantity(int); Quantity(const QJsonObject&); Quantity(const HNumber&); Quantity(const CNumber&); ~Quantity(); bool isNan() const; bool isZero() const; bool isReal() const; bool isPositive() const; bool isNegative() const; bool isInteger() const; bool isCollection() const; bool isList() const; bool isMatrix() const; int rows() const; int columns() const; int elementCount() const; QVector elements() const; QVector> matrix() const; static Quantity list(const QVector& elements); static Quantity matrix(const QVector>& rows); bool hasUnit() const; CNumber unit() const; QString unitName() const; CNumber numericValue() const; Quantity& setDisplayUnit(const CNumber unit, const QString& name); void stripUnits(); bool hasDimension() const; bool isDimensionless() const; QMap getDimension() const; QMap getDimensionByQuantity() const; void modifyDimension(const QString& key, const Rational& exponent); void modifyDimension(UnitQuantity key, const Rational& exponent); void copyDimension(const Quantity&); void clearDimension(); bool sameDimension(const Quantity& other) const; void cleanDimension(); void serialize(QJsonObject&) const; static Quantity deSerialize(const QJsonObject&); Error error() const; Quantity& operator=(const Quantity&); Quantity operator+(const Quantity&) const; Quantity& operator+=(const Quantity&); Quantity& operator-=(const Quantity&); Quantity operator*(const Quantity&) const; Quantity operator*(const CNumber&) const; Quantity operator*(const HNumber&) const; Quantity& operator*=(const Quantity&); Quantity operator/(const Quantity&) const; Quantity operator/(const HNumber&) const; Quantity operator/(const CNumber&) const; Quantity& operator/=(const Quantity&); Quantity operator%(const Quantity&) const; Quantity operator&(const Quantity&) const; Quantity& operator&=(const Quantity&); Quantity operator|(const Quantity&) const; Quantity& operator|=(const Quantity&); Quantity operator^(const Quantity&) const; Quantity& operator^=(const Quantity&); Quantity operator~() const; Quantity operator>>(const Quantity&) const; Quantity operator<<(const Quantity&) const; class Format : public CNumber::Format { public: Format(); Format(const CNumber::Format&); Format(const HNumber::Format&); Format operator+(const Format&) const; void serialize(QJsonObject&) const; static Format deSerialize(const QJsonObject&); bool isNull() const; }; Format format() const { return m_format; } Quantity& setFormat(Format); private: CNumber m_numericValue; QMap m_dimension; CNumber* m_unit; QString m_unitName; Format m_format; QVector> m_matrix; bool m_collectionIsMatrix; }; /* * Math functions for quantities with dimensions */ class DMath { public: static bool complexMode; static QString format(const Quantity, Quantity::Format = Quantity::Format()); // CONSTANTS static Quantity e(); static Quantity phi(); static Quantity pi(); static Quantity nan(Error = Success); static Quantity i(); // GENERAL MATH static Quantity rad2deg(const Quantity&); static Quantity deg2rad(const Quantity&); static Quantity rad2gon(const Quantity&); static Quantity gon2rad(const Quantity&); static Quantity abs(const Quantity&); static Quantity integer(const Quantity&); static Quantity frac(const Quantity&); static Quantity floor(const Quantity&); static Quantity ceil(const Quantity&); static Quantity gcd(const Quantity&, const Quantity&); static Quantity lcm(const Quantity&, const Quantity&); static Quantity idiv(const Quantity&, const Quantity&); static Quantity round(const Quantity&, int prec = 0); static Quantity trunc(const Quantity&, int prec = 0); static Quantity sqrt(const Quantity&); static Quantity cbrt(const Quantity&); static Quantity root(const Quantity& n, const Quantity& x); static Quantity raise(const Quantity&, int); static Quantity raise(const Quantity&, const Quantity&); static Quantity sgn(const Quantity&); // EXPONENTIAL FUNCTION AND RELATED static Quantity exp(const Quantity&); static Quantity ln(const Quantity&); static Quantity lg(const Quantity&); static Quantity lb(const Quantity&); static Quantity log(const Quantity& base, const Quantity&); static Quantity sinh(const Quantity&); static Quantity cosh(const Quantity&); static Quantity tanh(const Quantity&); static Quantity arsinh(const Quantity&); static Quantity arcosh(const Quantity&); static Quantity artanh(const Quantity&); // COMPLEX static Quantity real(const Quantity&); static Quantity imag(const Quantity&); static Quantity conj(const Quantity&); static Quantity phase(const Quantity&); // TRIGONOMETRY static Quantity sin(const Quantity&); static Quantity cos(const Quantity&); static Quantity tan(const Quantity&); static Quantity cot(const Quantity&); static Quantity sec(const Quantity&); static Quantity csc(const Quantity&); static Quantity arcsin(const Quantity&); static Quantity arccos(const Quantity&); static Quantity arctan(const Quantity&); static Quantity arctan2(const Quantity&, const Quantity & y); // HIGHER MATH FUNCTIONS static Quantity factorial(const Quantity& x, const Quantity& base = CNumber(1)); static Quantity gamma(const Quantity&); static Quantity lnGamma(const Quantity&); static Quantity erf(const Quantity&); static Quantity erfc(const Quantity&); // PROBABILITY static Quantity nCr(const Quantity& n, const Quantity& k); static Quantity nPr(const Quantity& n, const Quantity& r); static Quantity binomialPmf(const Quantity& k, const Quantity& n, const Quantity& p); static Quantity binomialCdf(const Quantity& k, const Quantity& n, const Quantity& p); static Quantity binomialMean(const Quantity& n, const Quantity& p); static Quantity binomialVariance(const Quantity& n, const Quantity& p); static Quantity hypergeometricPmf(const Quantity& k, const Quantity& N, const Quantity& M, const Quantity& n); static Quantity hypergeometricCdf(const Quantity& k, const Quantity& N, const Quantity& M, const Quantity& n); static Quantity hypergeometricMean(const Quantity& N, const Quantity& M, const Quantity& n); static Quantity hypergeometricVariance(const Quantity& N, const Quantity& M, const Quantity& n); static Quantity poissonPmf(const Quantity& k, const Quantity& l); static Quantity poissonCdf(const Quantity& k, const Quantity& l); static Quantity poissonMean(const Quantity& l); static Quantity poissonVariance(const Quantity& l); // LOGIC static Quantity mask (const Quantity&, const Quantity& bits); static Quantity sgnext (const Quantity&, const Quantity& bits); static Quantity ashr(const Quantity&, const Quantity& bits); // IEEE-754 CONVERSION static Quantity decodeIeee754(const Quantity&, const Quantity& exp_bits, const Quantity& significand_bits); static Quantity decodeIeee754(const Quantity&, const Quantity& exp_bits, const Quantity& significand_bits, const Quantity& exp_bias); static Quantity encodeIeee754(const Quantity&, const Quantity& exp_bits, const Quantity& significand_bits); static Quantity encodeIeee754(const Quantity&, const Quantity& exp_bits, const Quantity& significand_bits, const Quantity& exp_bias); }; #endif // QUANTITY_H heldercorreia-speedcrunch-e7ca37f/src/math/rational.cpp000066400000000000000000000172661526573132500234060ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2016, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "rational.h" #include "math/hmath.h" #include "numberformatter.h" #include #include #include #include #include void Rational::normalize() { if(m_denom==0) { m_valid = false; return; } if(m_num==0) { m_denom=1; return; } int g = gcd(abs(m_num), abs(m_denom)); m_num /= g; m_denom /= g; if(m_denom<0) { m_num = -m_num; m_denom = -m_denom; } } int Rational::compare(const Rational &other) const { return m_num*other.m_denom - m_denom*other.m_num; } bool Rational::approximate(const HNumber& num, int maxDenominator, const HNumber& relativeTolerance, Rational* out) { if (out == nullptr || maxDenominator < 1 || relativeTolerance <= HNumber(0) || num.isNan()) return false; if (num.isZero()) { *out = Rational(0, 1); return true; } const HNumber nearIntTol("1e-18"); const HNumber absNum = HMath::abs(num); auto withinTolerance = [&](const Rational& candidate) { const HNumber diff = HMath::abs(candidate.toHNumber() - num); const HNumber scale = HMath::abs(num); if (scale.isZero()) return diff <= relativeTolerance; return diff <= relativeTolerance * scale; }; long long pPrevPrev = 0; long long qPrevPrev = 1; long long pPrev = 1; long long qPrev = 0; HNumber val(absNum); while (true) { HNumber aNum = HMath::floor(val); HNumber frac = val - aNum; // Guard against rounding noise near integer boundaries. if (HMath::abs(HNumber(1) - frac) < nearIntTol) { aNum += 1; frac = 0; } if (aNum > HNumber(INT_MAX)) break; const long long a = static_cast(aNum.toInt()); if ((a != 0 && pPrev > (std::numeric_limits::max() - pPrevPrev) / a) || (a != 0 && qPrev > (std::numeric_limits::max() - qPrevPrev) / a)) { break; } const long long p = pPrevPrev + a * pPrev; const long long q = qPrevPrev + a * qPrev; if (q > maxDenominator) break; if (p > INT_MAX) break; Rational candidate(static_cast(p), static_cast(q)); if (num.isNegative()) candidate = Rational(-candidate.numerator(), candidate.denominator()); if (withinTolerance(candidate)) { *out = candidate; return true; } if (HMath::abs(frac) < nearIntTol) break; pPrevPrev = pPrev; qPrevPrev = qPrev; pPrev = p; qPrev = q; val = HNumber(1) / frac; } return false; } /* * Find a rational approximation to num using a continued fraction scheme. * Code adapted from the 'Fraction' module for the PYTHON programming language, * authored by Sjoerd Mullender and Jeffrey Yasskin. */ Rational::Rational(const HNumber &num) : m_num(1), m_denom(1), m_valid(1) { const HNumber nearIntTol("1e-18"); if(num.isZero()) { m_num = 0; return; } if(HMath::abs(num)>HNumber(INT_MAX) || HMath::abs(num)MAXD) break; unsigned long long temp1=p0, temp2=p1, temp3=q1; p0 = temp2; q0 = temp3; p1 = temp1 + a*temp2; q1 = q2; if(HMath::abs(frac) < nearIntTol) break; val = HNumber(1)/frac; if(val>HNumber(MAXD)) break; } Rational bound(p1, q1); if(num<0) { bound.m_num *= -1; } *this = bound; } Rational::Rational(const double &num): m_num(1), m_denom(1), m_valid(1) { if (num==0) { m_num = 0; return; } if (std::abs(num)>INT_MAX || std::abs(1./num)>INT_MAX) { m_valid = false; return; } const long long MAXD = INT_MAX/2; // maximal denominator long long p0=0, q0=1, p1=1, q1=0; double val = fabs(num); while(true) { unsigned long long a = static_cast(floor(val)); unsigned long long q2 = q0 + a*q1; if(q2>MAXD) break; unsigned long long temp1=p0, temp2=p1, temp3=q1; p0 = temp2; q0 = temp3; p1 = temp1 + a*temp2; q1 = q2; if(val==a) break; val = 1/(val-a); } Rational bound(p1, q1); if(num<0) bound.m_num *= -1; *this = bound; } Rational::Rational(const QString &str) : m_num(0), m_denom(1), m_valid(true) { if(str=="") { m_valid=false; return; } QStringList l = str.split("/"); if(l.size()==1) { bool ok; m_num = l.at(0).toInt(&ok); if(!ok) { m_valid=false; return; } } else if(l.size()==2) { bool ok; m_num = l.at(0).toInt(&ok); if(!ok) { m_valid=false; return; } m_denom = l.at(1).toInt(&ok); if(!ok) { m_valid=false; return; } } } Rational Rational::operator*(const Rational &other) const { return Rational(this->m_num * other.m_num, this->m_denom * other.m_denom); } Rational Rational::operator/(const Rational &other) const { if(other.isZero()) return Rational(1,0); // Rational(1,0) will set m_valid=false return Rational(this->m_num / other.m_num, this->m_denom / other.m_denom); } Rational Rational::operator+(const Rational &other) const { return Rational(this->m_num*other.m_denom + this->m_denom*other.m_num, this->m_denom*other.m_denom); } Rational Rational::operator-(const Rational &other) const { return Rational(this->m_num*other.m_denom - this->m_denom*other.m_num, this->m_denom*other.m_denom); } /*Rational &Rational::operator=(const Rational &other) { m_num = other.m_num; m_denom = other.m_denom; m_valid = other.m_valid; return *this; }*/ Rational &Rational::operator+=(const Rational &other) { return operator=(*this + other); } Rational &Rational::operator-=(const Rational &other) { return operator=(*this - other); } Rational &Rational::operator*=(const Rational &other) { return operator=(*this * other); } Rational &Rational::operator/=(const Rational &other) { return operator=(*this / other); } bool Rational::operator<(const Rational &other) const { return compare(other)<0; } bool Rational::operator==(const Rational &other) const { return compare(other) == 0; } bool Rational::operator>(const Rational &other) const { return compare(other)>0; } bool Rational::isZero() const { return m_num==0; } bool Rational::isValid() const { return m_valid; } QString Rational::toString() const { if(m_denom==1) return QString::fromLatin1("%1").arg(m_num); return QString::fromLatin1("%1/%2").arg(m_num).arg(m_denom); } HNumber Rational::toHNumber() const { HNumber num(m_num); HNumber denom(m_denom); return num/denom; } double Rational::toDouble() const { return double(m_num)/m_denom; } heldercorreia-speedcrunch-e7ca37f/src/math/rational.h000066400000000000000000000037451526573132500230500ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015, 2024, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef RATIONAL_H #define RATIONAL_H #include class HNumber; class QString; class Rational { int m_num; int m_denom; bool m_valid; inline int gcd(int a, int b) const {return (b==0) ? a : gcd(b, a%b);} void normalize(); int compare(const Rational & other) const; public: Rational() : m_num(0), m_denom(1), m_valid(true) {} Rational(const HNumber &num); Rational(const double &num); Rational(const QString & str); static bool approximate(const HNumber& num, int maxDenominator, const HNumber& relativeTolerance, Rational* out); Rational(const int a, const int b) : m_num(a), m_denom(b), m_valid(true) {normalize();} Rational(const Rational& other) = default; int numerator() const {return m_num;} int denominator() const {return m_denom;} Rational& operator=(const Rational& other) = default; Rational& operator=(Rational&& other) noexcept = default; Rational operator*(const Rational & other) const; Rational operator/(const Rational & other) const; Rational operator+(const Rational & other) const; Rational operator-(const Rational & other) const; Rational &operator+=(const Rational & other); Rational &operator-=(const Rational & other); Rational &operator*=(const Rational & other); Rational &operator/=(const Rational & other); bool operator<(const Rational & other) const; bool operator==(const Rational & other) const; bool operator!=(const Rational & other) const {return !operator==(other);} bool operator>(const Rational & other) const; bool isZero() const; bool isValid() const; QString toString() const; HNumber toHNumber( )const; double toDouble() const; }; inline size_t qHash(const Rational& value, size_t seed = 0) noexcept { return qHashMulti(seed, value.numerator(), value.denominator()); } #endif // RATIONAL_H heldercorreia-speedcrunch-e7ca37f/src/resources/000077500000000000000000000000001526573132500221365ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/000077500000000000000000000000001526573132500247015ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Black on White.json000066400000000000000000000010341526573132500302440ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Black on White", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#000000", "unit": "#000000", "number": "#000000", "parens": "#000000", "result": "#000000", "comment": "#000000", "function": "#000000", "operator": "#000000", "variable": "#000000", "separator": "#000000", "background": "#FFFFFF" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Breeze Dark.json000066400000000000000000000010311526573132500276450ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Breeze Dark", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#EFF0F1", "unit": "#FFA069", "number": "#F67400", "parens": "#EFF0F1", "result": "#11D116", "comment": "#BDC3C7", "function": "#27AE60", "operator": "#EFF0F1", "variable": "#1D99F3", "separator": "#EFF0F1", "background": "#292C2F" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Breeze.json000066400000000000000000000010241526573132500270050ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Breeze", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#8F4001", "unit": "#8F4001", "number": "#F67400", "parens": "#232629", "result": "#11D116", "comment": "#BDC3C7", "function": "#27AE60", "operator": "#232629", "variable": "#2980B9", "separator": "#232629", "background": "#FCFCFC" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Carbonfox.json000066400000000000000000000010271526573132500275150ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Carbonfox", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#f2f4f8", "unit": "#b6b8bb", "number": "#08bdba", "parens": "#A1A1A1", "result": "#25be6a", "comment": "#78a9ff", "function": "#33b1ff", "operator": "#3ddbd9", "variable": "#be95ff", "separator": "#A1A1A1", "background": "#161616" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Catppuccin Latte.json000066400000000000000000000010361526573132500307170ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Catppuccin Latte", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#8F3300", "unit": "#8F3300", "number": "#fe640b", "parens": "#4c4f69", "result": "#40a02b", "comment": "#9ca0b0", "function": "#1e66f5", "operator": "#04a5e5", "variable": "#d20f39", "separator": "#4E5063", "background": "#eff1f5" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Catppuccin Macchiato.json000066400000000000000000000010421526573132500315330ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Catppuccin Macchiato", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#f5a97f", "unit": "#f5a97f", "number": "#f5a97f", "parens": "#cad3f5", "result": "#a6da95", "comment": "#6e738d", "function": "#8aadf4", "operator": "#91d7e3", "variable": "#ed8796", "separator": "#ABB2CE", "background": "#24273a" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Dawnfox.json000066400000000000000000000010251526573132500272000ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Dawnfox", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#544F73", "unit": "#544E78", "number": "#ea9d34", "parens": "#544B89", "result": "#618774", "comment": "#907aa9", "function": "#56949f", "operator": "#d7827e", "variable": "#286983", "separator": "#4D5555", "background": "#faf4ed" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Dayfox.json000066400000000000000000000010241526573132500270230ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Dayfox", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#3d2b5a", "unit": "#643f61", "number": "#ac5402", "parens": "#534c45", "result": "#396847", "comment": "#4863b6", "function": "#287980", "operator": "#955f61", "variable": "#6e33ce", "separator": "#525252", "background": "#f6f2ee" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Dracula.json000066400000000000000000000010251526573132500271450ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Dracula", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#8be9fd", "unit": "#C8A6FD", "number": "#ffb86c", "parens": "#f8f8f2", "result": "#50fa7b", "comment": "#6272a4", "function": "#50fa7b", "operator": "#8be9fd", "variable": "#f8f8f2", "separator": "#FE94CE", "background": "#282a36" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Duskfox.json000066400000000000000000000010251526573132500272150ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Duskfox", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e0def4", "unit": "#cdcbe0", "number": "#f6c177", "parens": "#AAA9DA", "result": "#a3be8c", "comment": "#c4a7e7", "function": "#9ccfd8", "operator": "#ea9a97", "variable": "#569fba", "separator": "#B2A9C8", "background": "#232136" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/GitHub Dark.json000066400000000000000000000010311526573132500276130ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "GitHub Dark", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#C9D1D9", "unit": "#C9D1D9", "number": "#C9D1D9", "parens": "#9DA6B0", "result": "#79C0FF", "comment": "#8B949E", "function": "#FFA657", "operator": "#A5D6FF", "variable": "#D2A8FF", "separator": "#D79396", "background": "#161B22" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/GitHub Light.json000066400000000000000000000010321526573132500300020ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "GitHub Light", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#24292E", "unit": "#24292E", "number": "#24292E", "parens": "#54575B", "result": "#005CC5", "comment": "#6A737D", "function": "#6F42C1", "operator": "#D73A49", "variable": "#005CC5", "separator": "#54575B", "background": "#FAFBFC" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Gruvbox Dark.json000066400000000000000000000010321526573132500300660ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Gruvbox Dark", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#EBDBB2", "unit": "#D5C4A1", "number": "#FABD2F", "parens": "#B4A895", "result": "#B8BB26", "comment": "#928374", "function": "#8EC07C", "operator": "#FE8019", "variable": "#D3869B", "separator": "#ABA9A8", "background": "#1D2021" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Gruvbox Light.json000066400000000000000000000010331526573132500302550ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Gruvbox Light", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#3C3836", "unit": "#504945", "number": "#B57614", "parens": "#5C5147", "result": "#79740E", "comment": "#928374", "function": "#427B58", "operator": "#AF3A03", "variable": "#8F3F71", "separator": "#5F5139", "background": "#F9F5D7" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Monokai.json000066400000000000000000000010251526573132500271670ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Monokai", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#C0A3FE", "unit": "#C0A3FE", "number": "#ae81ff", "parens": "#f8f8f2", "result": "#66d9ef", "comment": "#75715e", "function": "#a6e22e", "operator": "#f92672", "variable": "#fd971f", "separator": "#e6db74", "background": "#272822" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Nightfox.json000066400000000000000000000010261526573132500273610ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Nightfox", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#cdcecf", "unit": "#aeafb0", "number": "#dbc074", "parens": "#ACADAD", "result": "#81b29a", "comment": "#6085b6", "function": "#63cdcf", "operator": "#f4a261", "variable": "#9d79d6", "separator": "#99AECB", "background": "#192330" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Nord Dark.json000066400000000000000000000010271526573132500273400ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Nord Dark", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#d8dee9", "unit": "#A0CAC9", "number": "#eceff4", "parens": "#92CBDB", "result": "#81a1c1", "comment": "#d08770", "function": "#bf616a", "operator": "#ebcb8b", "variable": "#a3be8c", "separator": "#D8B9D2", "background": "#2e3440" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Nord Light.json000066400000000000000000000010301526573132500275200ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Nord Light", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#475064", "unit": "#4F5050", "number": "#5e81ac", "parens": "#434c5e", "result": "#4c566a", "comment": "#d08770", "function": "#bf616a", "operator": "#b48ead", "variable": "#a3be8c", "separator": "#2e3440", "background": "#eceff4" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Nordfox.json000066400000000000000000000010251526573132500272110ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Nordfox", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#cdcecf", "unit": "#C0C2C6", "number": "#ebcb8b", "parens": "#B0C3EA", "result": "#a3be8c", "comment": "#668aab", "function": "#88c0d0", "operator": "#c9826b", "variable": "#b48ead", "separator": "#B1C4DA", "background": "#2e3440" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/One Dark.json000066400000000000000000000010261526573132500271560ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "One Dark", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#f0f0f0", "unit": "#f0f0f0", "number": "#e5c07b", "parens": "#B1B8C5", "result": "#98c379", "comment": "#5c6370", "function": "#61afef", "operator": "#abb2bf", "variable": "#e06c75", "separator": "#E3AD7A", "background": "#282c34" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Rose Pine Dawn.json000066400000000000000000000010351526573132500302310ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Rosé Pine Dawn", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#544F73", "unit": "#54506D", "number": "#d7827e", "parens": "#853B52", "result": "#ea9d34", "comment": "#907aa9", "function": "#56949f", "operator": "#286983", "variable": "#575279", "separator": "#54506D", "background": "#faf4ed" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Rose Pine Moon.json000066400000000000000000000010351526573132500302500ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Rosé Pine Moon", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e0def4", "unit": "#AEABC3", "number": "#ea9a97", "parens": "#FE8AA8", "result": "#f6c177", "comment": "#c4a7e7", "function": "#9ccfd8", "operator": "#3e8fb0", "variable": "#e0def4", "separator": "#AEABC3", "background": "#232136" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Solarized Dark.json000066400000000000000000000010341526573132500303700ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Solarized Dark", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#B2C1C3", "unit": "#B2C1C3", "number": "#839496", "parens": "#FDF6E3", "result": "#FDF6E3", "comment": "#586E75", "function": "#268BD2", "operator": "#B58900", "variable": "#859900", "separator": "#E2B959", "background": "#073642" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Solarized Light.json000066400000000000000000000010351526573132500305570ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Solarized Light", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#4A565B", "unit": "#4A565B", "number": "#657B83", "parens": "#002B36", "result": "#073642", "comment": "#93A1A1", "function": "#268BD2", "operator": "#B58900", "variable": "#859900", "separator": "#6B5005", "background": "#FDF6E3" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Sonokai Andromeda.json000066400000000000000000000010371526573132500310530ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Sonokai Andromeda", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e1e3e4", "unit": "#AFB1B8", "number": "#edc763", "parens": "#AFB1B8", "result": "#9ed06c", "comment": "#7e8294", "function": "#6dcae8", "operator": "#f89860", "variable": "#bb97ee", "separator": "#ADB1BD", "background": "#252630" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Sonokai Atlantis.json000066400000000000000000000010361526573132500307370ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Sonokai Atlantis", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e1e3e4", "unit": "#A9B2C2", "number": "#eacb64", "parens": "#A9B2C3", "result": "#9dd274", "comment": "#828a9a", "function": "#72cce8", "operator": "#f69c5e", "variable": "#ba9cf3", "separator": "#A9B2C5", "background": "#24272e" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Sonokai Default.json000066400000000000000000000010351526573132500305430ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Sonokai Default", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e2e2e3", "unit": "#ABADB4", "number": "#e7c664", "parens": "#A6AEBE", "result": "#9ed072", "comment": "#7f8490", "function": "#76cce0", "operator": "#f39660", "variable": "#b39df3", "separator": "#A9ADB9", "background": "#222327" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Sonokai Espresso.json000066400000000000000000000010361526573132500307630ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Sonokai Espresso", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e4e3e1", "unit": "#AEABA9", "number": "#f0c66f", "parens": "#AEABA9", "result": "#a6cd77", "comment": "#90817b", "function": "#81d0c9", "operator": "#f08d71", "variable": "#9fa0e1", "separator": "#AEABA9", "background": "#242120" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Sonokai Maia.json000066400000000000000000000010321526573132500300230ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Sonokai Maia", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e1e2e3", "unit": "#AEB2B5", "number": "#e3d367", "parens": "#AEB2B5", "result": "#9cd57b", "comment": "#82878b", "function": "#78cee9", "operator": "#f3a96a", "variable": "#baa0f8", "separator": "#A9B3BA", "background": "#21282c" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Sonokai Shusia.json000066400000000000000000000010341526573132500304120ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Sonokai Shusia", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e3e1e4", "unit": "#AAA9AD", "number": "#e5c463", "parens": "#ABA8B3", "result": "#9ecd6f", "comment": "#848089", "function": "#7accd7", "operator": "#ef9062", "variable": "#ab9df2", "separator": "#AAA9AD", "background": "#211f21" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Standard.json000066400000000000000000000010261526573132500273330ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Standard", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#282828", "unit": "#282828", "number": "#282828", "parens": "#834C01", "result": "#0064C8", "comment": "#707070", "function": "#4A9A07", "operator": "#969696", "variable": "#EF2928", "separator": "#64507B", "background": "#FFFFFF" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Sublime.json000066400000000000000000000010251526573132500271720ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Sublime", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#CFA6C3", "unit": "#CFA6C3", "number": "#AD779E", "parens": "#ADB5A1", "result": "#C5DA6B", "comment": "#75715E", "function": "#D5266A", "operator": "#F2F8D6", "variable": "#40B5EE", "separator": "#C5DA6B", "background": "#272822" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Terafox.json000066400000000000000000000010251526573132500272020ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Terafox", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#e6eaea", "unit": "#cbd9d8", "number": "#fda47f", "parens": "#AAADB2", "result": "#7aa4a1", "comment": "#5a93aa", "function": "#a1cdd8", "operator": "#ff8349", "variable": "#ad5c7c", "separator": "#96B2B2", "background": "#152528" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Terminal.json000066400000000000000000000010261526573132500273460ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Terminal", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#bbbbbb", "unit": "#bbbbbb", "number": "#FFFFFF", "parens": "#C395BE", "result": "#689FCF", "comment": "#894b7a", "function": "#EF2928", "operator": "#C4A000", "variable": "#4A9A07", "separator": "#C395BE", "background": "#300A24" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Tokyo Day.json000066400000000000000000000010271526573132500273770ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Tokyo Day", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#1D429D", "unit": "#38457D", "number": "#8C6C3E", "parens": "#464855", "result": "#587539", "comment": "#A1A6C5", "function": "#007197", "operator": "#B15C00", "variable": "#9854F1", "separator": "#454857", "background": "#E1E2E7" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Tokyo Night.json000066400000000000000000000010311526573132500277260ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Tokyo Night", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#C0CAF5", "unit": "#A9B1D6", "number": "#E0AF68", "parens": "#AAB1CA", "result": "#9ECE6A", "comment": "#565F89", "function": "#7DCFFF", "operator": "#FF9E64", "variable": "#BB9AF7", "separator": "#AAB1CB", "background": "#252634" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Tomorrow Night Blue.json000066400000000000000000000010411526573132500313220ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Tomorrow Night Blue", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#FFC58F", "unit": "#FFC58F", "number": "#FFC58F", "parens": "#FFFFFF", "result": "#D1F1A9", "comment": "#7285B7", "function": "#BBDAFF", "operator": "#99FFFF", "variable": "#FF9DA4", "separator": "#7EB2F7", "background": "#002451" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Tomorrow Night Bright.json000066400000000000000000000010431526573132500316540ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Tomorrow Night Bright", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#E78C45", "unit": "#E78C45", "number": "#E78C45", "parens": "#EAEAEA", "result": "#B9CA4A", "comment": "#969896", "function": "#7AA6DA", "operator": "#70C0B1", "variable": "#D54E53", "separator": "#959595", "background": "#000000" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Tomorrow Night Eighties.json000066400000000000000000000010451526573132500322000ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Tomorrow Night Eighties", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#FEA372", "unit": "#FEA372", "number": "#F99157", "parens": "#CCCCCC", "result": "#99CC99", "comment": "#999999", "function": "#6699CC", "operator": "#66CCCC", "variable": "#F2777A", "separator": "#B9B9B9", "background": "#2D2D2D" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Tomorrow Night.json000066400000000000000000000010341526573132500304540ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Tomorrow Night", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#E29864", "unit": "#E29864", "number": "#DE935F", "parens": "#C5C8C6", "result": "#B5BD68", "comment": "#969896", "function": "#81A2BE", "operator": "#8ABEB7", "variable": "#CC6666", "separator": "#A5A9AF", "background": "#1D1F21" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/Tomorrow.json000066400000000000000000000010261526573132500274230ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "Tomorrow", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#8B4701", "unit": "#8B4701", "number": "#F5871F", "parens": "#4D4D4C", "result": "#718C00", "comment": "#8E908C", "function": "#4271AE", "operator": "#3E999F", "variable": "#C82829", "separator": "#595959", "background": "#FFFFFF" } heldercorreia-speedcrunch-e7ca37f/src/resources/color-schemes/White on Black.json000066400000000000000000000010341526573132500302440ustar00rootroot00000000000000{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://speedcrunch.org/schemas/theme-v1.schema.json", "name": "White on Black", "author": "SpeedCrunch", "homepage": "http://speedcrunch.org", "version": "1", "list": "#FFFFFF", "unit": "#FFFFFF", "number": "#FFFFFF", "parens": "#FFFFFF", "result": "#FFFFFF", "comment": "#FFFFFF", "function": "#FFFFFF", "operator": "#FFFFFF", "variable": "#FFFFFF", "separator": "#FFFFFF", "background": "#000000" } heldercorreia-speedcrunch-e7ca37f/src/resources/locale/000077500000000000000000000000001526573132500233755ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/resources/locale/ar.ts000066400000000000000000011026061526573132500243550ustar00rootroot00000000000000 AboutBox About SpeedCrunch حول SpeedCrunch Core developers المطورون الأساسيون Original author المؤل� الأصلي Close إغلاق Math engine محرك الرياضيات Main author | Logo | Maintainer المؤل� الرئيسي | الشعار | المشر� Thanks شكراً Copyright (C) 2004-2026 The SpeedCrunch developers حقوق النشر (C) 2004-2026 مطورو SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version هذا البرنامج برنامج حر؛ يمكنك إعادة توزيعه و/أو تعديله بموجب شروط رخصة GNU العمومية العامة كما نشرتها مؤسسة البرمجيات الحرة؛ إما الإصدار 2 من الرخصة أو (حسب اختيارك) أي إصدار لاحق This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. يوزع هذا البرنامج على أمل أن يكون م�يدًا، ولكن دون أي ضمان؛ حتى دون الضمان الضمني لقابلية التسويق أو الملاءمة لغرض معين. راجع رخصة GNU العمومية العامة لمزيد من الت�اصيل. BitFieldWidget Reset bits to zero إعادة تعيين البتات إلى الص�ر Invert bits عكس البتات Shift bits left إزاحة البتات إلى اليسار Shift bits right إزاحة البتات إلى اليمين Book Index ال�هرس Algebra الجبر Quadratic Equation معادلة تربيعية Logarithmic Base Conversion تحويل أساس اللوغاريتم Geometry الهندسة Circle دائرة Sector قطاع Sphere كرة Cube مكعب Cone مخروط Cylinder أسطوانة Electronics الإلكترونيات Ohm's Law قانون أوم (Ω) Power القدرة الكهربائية Reactance الم�اعلة Resonance الرنين Radio Frequency تردد الراديو Antennas الهوائيات Characteristic Impedance (coax) المعاوقة المميزة (كابل محوري) Velocity of Propagation (coax) سرعة الانتشار (كابل محوري) Standing Wave Ratio & Return Loss نسبة الموجة الدائمة و�قدان العودة Free Space Wavelength الطول الموجي �ي ال�ضاء الحر resistance المقاومة voltage الجهد الكهربائي current التيار الكهربائي power القدرة الكهربائية inductive reactance م�اعلة حثية capacitive reactance م�اعلة تكاث�ية inductance المحاثة capacitance السعة frequency التردد resonance frequency التردد الرنيني area مساحة perimeter المحيط diameter الق�طْر radius نص� القطر volume الحجم surface area مساحة السطح height الارت�اع slant height طول راسم المخروط face diagonal قطر الوجه space diagonal القطر ال�راغي edge length طول الحا�ة arc length طول القوس central angle (degrees) الزاوية المركزية (بالدرجات) input power قدرة الدخل reflected power القدرة المنعكسة transmitted power القدرة الم�رسلة return loss �قدان العودة dielectric constant ثابت العزل الكهربائي outer conductor's inner diameter القطر الداخلي للموصل الخارجي inner conductor's outer diameter القطر الخارجي للموصل الداخلي speed of light سرعة الضوء reflection coefficient معامل الانعكاس standing wave ratio نسبة الموجة الدائمة normalized impedance المعاوقة المقيسة frequency (Hz) التردد (Hz) BookDock Formula Book كتاب المعادلات ConstantCompletion Search constants البحث عن الثوابت No match found لم ي�عثر على تطابق Constants Mathematics الرياضيات Physics (CODATA 2022) ال�يزياء (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) الكيمياء (IUPAC - CIAAW 2021) Uncategorized غير مصن� Universal عالمي Physicochemical �يزيائي كيميائي Atomic & Nuclear — General الذرية والنووية — عام Atomic & Nuclear — Electroweak الذرية والنووية — الكهروضعي�ة Atomic & Nuclear — Electron الذرية والنووية — الإلكترون Atomic & Nuclear — Muon الذرية والنووية — الميون Atomic & Nuclear — Tau الذرية والنووية — التاو Atomic & Nuclear — Proton الذرية والنووية — البروتون Atomic & Nuclear — Neutron الذرية والنووية — النيوترون Atomic & Nuclear — Deuteron الذرية والنووية — الديوترون Atomic & Nuclear — Triton الذرية والنووية — التريتون Atomic & Nuclear — Helion الذرية والنووية — الهيليون Atomic & Nuclear — Alpha particle الذرية والنووية — جسيم أل�ا Atomic & Nuclear — Atomic units الذرية والنووية — الوحدات الذرية Atomic & Nuclear — Energy conversion relationships الذرية والنووية — علاقات تحويل الطاقة Atomic & Nuclear — X-ray units الذرية والنووية — وحدات الأشعة السينية Atomic & Nuclear — Magnetic shielding corrections الذرية والنووية — تصحيحات الحجب المغناطيسي Masses الكتل Lifetimes الأعمار Molar Masses الكتل المولية Electronegativity السالبية الكهربائية Ionization Energy طاقة التأين Nominal Constants (IAU 2015) الثوابت الاسمية (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) أ�ضل التقديرات الحالية (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) المعاوقة المميزة لل�راغ (Z₀) reduced Planck constant (�) ثابت بلانك المختزل (�) vacuum electric permittivity (ϵ₀) السماحية الكهربائية لل�راغ (ϵ₀) Newtonian constant of gravitation (G) ثابت الجذب العام النيوتني (G) vacuum magnetic permeability (μ₀) الن�اذية المغناطيسية لل�راغ (μ₀) Planck constant (h) ثابت بلانك (h) speed of light in vacuum (c) سرعة الضوء �ي ال�راغ (c) standard acceleration of gravity (gₙ) التسارع القياسي للجاذبية (gₙ) Newtonian constant of gravitation over h-bar c ثابت الجذب العام النيوتني على � c Planck length بلانك الطول Planck constant in eV/Hz (h) ثابت بلانك بوحدة eV/Hz (h) Planck mass بلانك الكتلة Planck mass energy equivalent in GeV بلانك مكا�ئ طاقة الكتلة بوحدة GeV Planck temperature بلانك درجة الحرارة Planck time بلانك الزمن reduced Planck constant in eV·s (�) المختزل ثابت بلانك بوحدة eV·s (�) reduced Planck constant times c in MeV·fm المختزل ثابت بلانك مضروبًا �ي c بوحدة MeV·fm Bohr magneton مغنطون بور conductance quantum (G₀) كمية الموصلية (G₀) Coulomb constant (kₑ) ثابت كولوم (kₑ) elementary charge (e) الشحنة الأولية (e) elementary charge over h-bar الشحنة الأولية over h-bar conventional value of Josephson constant القيمة التقليدية لـ ثابت جوز�سون Josephson constant ثابت جوز�سون conventional value of ampere-90 القيمة التقليدية لـ ampere-90 conventional value of coulomb-90 القيمة التقليدية لـ coulomb-90 conventional value of farad-90 القيمة التقليدية لـ farad-90 conventional value of henry-90 القيمة التقليدية لـ henry-90 conventional value of ohm-90 القيمة التقليدية لـ ohm-90 conventional value of volt-90 القيمة التقليدية لـ volt-90 conventional value of watt-90 القيمة التقليدية لـ watt-90 magnetic flux quantum (Φ₀) كمية ال�يض المغناطيسي (Φ₀) nuclear magneton المغنطون النووي inverse of conductance quantum معكوس كمية الموصلية conventional value of von Klitzing constant القيمة التقليدية لـ ثابت �ون كليتزينغ von Klitzing constant ثابت �ون كليتزينغ atomic unit of magnetic dipole moment الوحدة الذرية لـ عزم ثنائي القطب المغناطيسي atomic unit of magnetic flux density الوحدة الذرية لـ كثا�ة ال�يض المغناطيسي Bohr magneton in eV/T مغنطون بور in eV/T Bohr magneton in Hz/T مغنطون بور in Hz/T Bohr magneton in inverse meter per tesla مغنطون بور in متر عكسي لكل تسلا Bohr magneton in K/T مغنطون بور in K/T nuclear magneton in eV/T المغنطون النووي in eV/T nuclear magneton in inverse meter per tesla المغنطون النووي in متر عكسي لكل تسلا nuclear magneton in K/T المغنطون النووي in K/T nuclear magneton in MHz/T المغنطون النووي in MHz/T Bohr radius (a₀) نص� قطر بور (a₀) fine-structure constant (α) ثابت البنية الدقيقة (α) Hartree energy (Eₕ) طاقة هارتري (Eₕ) Hartree energy in eV طاقة هارتري in eV quantum of circulation كمية الدوران quantum of circulation times 2 كمية الدوران times 2 Rydberg constant (R∞) ثابت ريدبرغ (R∞) atomic mass unit-hartree relationship وحدة الكتلة الذرية-hartree علاقة atomic mass unit-hertz relationship وحدة الكتلة الذرية-هرتز علاقة atomic mass unit-inverse meter relationship وحدة الكتلة الذرية-متر عكسي علاقة atomic mass unit-joule relationship وحدة الكتلة الذرية-جول علاقة atomic mass unit-kelvin relationship وحدة الكتلة الذرية-كل�ن علاقة atomic mass unit-kilogram relationship وحدة الكتلة الذرية-كيلوغرام علاقة atomic unit of 1st hyperpolarizability الوحدة الذرية لـ 1st hyperpolarizability atomic unit of 2nd hyperpolarizability الوحدة الذرية لـ 2nd hyperpolarizability atomic unit of charge (e) الوحدة الذرية لـ charge (e) atomic unit of charge density الوحدة الذرية لـ كثا�ة الشحنة atomic unit of current الوحدة الذرية لـ التيار atomic unit of electric dipole moment الوحدة الذرية لـ عزم ثنائي القطب الكهربائي atomic unit of electric field الوحدة الذرية لـ المجال الكهربائي atomic unit of electric field gradient الوحدة الذرية لـ تدرج المجال الكهربائي atomic unit of electric polarizability الوحدة الذرية لـ الاستقطابية الكهربائية atomic unit of electric potential الوحدة الذرية لـ الجهد الكهربائي atomic unit of electric quadrupole moment الوحدة الذرية لـ عزم رباعي القطب الكهربائي atomic unit of action الوحدة الذرية لـ ال�عل atomic unit of energy الوحدة الذرية لـ الطاقة atomic unit of force الوحدة الذرية لـ القوة atomic unit of length الوحدة الذرية لـ الطول hertz-atomic mass unit relationship هرتز-وحدة الكتلة الذرية علاقة hertz-electron volt relationship هرتز-إلكترون �ولت علاقة hertz-hartree relationship هرتز-hartree علاقة hertz-inverse meter relationship هرتز-متر عكسي علاقة hertz-joule relationship هرتز-جول علاقة hertz-kelvin relationship هرتز-كل�ن علاقة hertz-kilogram relationship هرتز-كيلوغرام علاقة hyperfine transition frequency of Cs-133 تردد الانتقال �ائق الدقة of Cs-133 inverse fine-structure constant (α�¹) inverse ثابت البنية الدقيقة (α�¹) inverse meter-atomic mass unit relationship متر عكسي-وحدة الكتلة الذرية علاقة inverse meter-electron volt relationship متر عكسي-إلكترون �ولت علاقة inverse meter-hartree relationship متر عكسي-hartree علاقة inverse meter-hertz relationship متر عكسي-هرتز علاقة inverse meter-joule relationship متر عكسي-جول علاقة inverse meter-kelvin relationship متر عكسي-كل�ن علاقة inverse meter-kilogram relationship متر عكسي-كيلوغرام علاقة joule-atomic mass unit relationship جول-وحدة الكتلة الذرية علاقة joule-electron volt relationship جول-إلكترون �ولت علاقة joule-hertz relationship جول-هرتز علاقة joule-hartree relationship جول-hartree علاقة joule-inverse meter relationship جول-متر عكسي علاقة joule-kelvin relationship جول-كل�ن علاقة joule-kilogram relationship جول-كيلوغرام علاقة kelvin-atomic mass unit relationship كل�ن-وحدة الكتلة الذرية علاقة kelvin-electron volt relationship كل�ن-إلكترون �ولت علاقة kelvin-hertz relationship كل�ن-هرتز علاقة kelvin-hartree relationship كل�ن-hartree علاقة kelvin-inverse meter relationship كل�ن-متر عكسي علاقة kelvin-joule relationship كل�ن-جول علاقة kelvin-kilogram relationship كل�ن-كيلوغرام علاقة kilogram-atomic mass unit relationship كيلوغرام-وحدة الكتلة الذرية علاقة kilogram-electron volt relationship كيلوغرام-إلكترون �ولت علاقة kilogram-hertz relationship كيلوغرام-هرتز علاقة kilogram-hartree relationship كيلوغرام-hartree علاقة kilogram-inverse meter relationship كيلوغرام-متر عكسي علاقة kilogram-joule relationship كيلوغرام-جول علاقة kilogram-kelvin relationship كيلوغرام-كل�ن علاقة lattice parameter of silicon (a) معامل الشبكة of silicon (a) luminous efficacy الك�اءة الضوئية natural unit of energy الوحدة الطبيعية لـ الطاقة natural unit of energy in MeV الوحدة الطبيعية لـ الطاقة in MeV natural unit of action (�) الوحدة الطبيعية لـ ال�عل (�) natural unit of action in eV·s الوحدة الطبيعية لـ ال�عل بوحدة eV·s natural unit of length الوحدة الطبيعية لـ الطول natural unit of mass الوحدة الطبيعية لـ الكتلة natural unit of momentum الوحدة الطبيعية لـ momentum natural unit of momentum in MeV/c الوحدة الطبيعية لـ momentum in MeV/c natural unit of time الوحدة الطبيعية لـ الزمن natural unit of velocity الوحدة الطبيعية لـ السرعة Rydberg constant times c in Hz ثابت ريدبرغ مضروبًا �ي c in Hz Rydberg constant times hc in eV ثابت ريدبرغ times hc in eV Rydberg constant times hc in J ثابت ريدبرغ times hc in J Fermi coupling constant ثابت اقتران �يرمي weak mixing angle زاوية الخلط الضعي� W to Z mass ratio W to Z نسبة الكتلة Thomson cross section (σₑ) مقطع طومسون العرضي (σₑ) electron mass (mₑ) إلكترون الكتلة (mₑ) electron mass in u إلكترون الكتلة in u electron mass energy equivalent (mₑ·c²) إلكترون مكا�ئ طاقة الكتلة (mₑ·c²) electron mass energy equivalent in MeV إلكترون مكا�ئ طاقة الكتلة in MeV reduced Compton wavelength المختزل طول موجة كومبتون classical electron radius (rₑ) classical إلكترون نص� القطر (rₑ) electron charge to mass quotient إلكترون نسبة الشحنة إلى الكتلة electron-deuteron magnetic moment ratio إلكترون-ديوترون نسبة العزم المغناطيسي electron-deuteron mass ratio إلكترون-ديوترون نسبة الكتلة electron g factor (gₑ) إلكترون عامل g (gₑ) electron gyromagnetic ratio (γₑ) إلكترون النسبة الجيرومغناطيسية (γₑ) electron gyromagnetic ratio in MHz/T إلكترون النسبة الجيرومغناطيسية in MHz/T electron-helion mass ratio إلكترون-هيليون نسبة الكتلة electron magnetic moment (μₑ) إلكترون العزم المغناطيسي (μₑ) electron magnetic moment anomaly (aₑ) إلكترون العزم المغناطيسي anomaly (aₑ) electron magnetic moment to Bohr magneton ratio إلكترون العزم المغناطيسي to مغنطون بور ratio electron magnetic moment to nuclear magneton ratio إلكترون العزم المغناطيسي to المغنطون النووي ratio electron molar mass (Mₑ) إلكترون الكتلة المولية (Mₑ) electron-muon magnetic moment ratio إلكترون-ميون نسبة العزم المغناطيسي electron-muon mass ratio إلكترون-ميون نسبة الكتلة electron-neutron magnetic moment ratio إلكترون-نيوترون نسبة العزم المغناطيسي electron-neutron mass ratio إلكترون-نيوترون نسبة الكتلة electron-proton magnetic moment ratio إلكترون-بروتون نسبة العزم المغناطيسي electron-proton mass ratio إلكترون-بروتون نسبة الكتلة electron relative atomic mass (Ar(e)) إلكترون الكتلة الذرية النسبية (Ar(e)) electron-tau mass ratio إلكترون-تاو نسبة الكتلة electron to alpha particle mass ratio إلكترون to جسيم أل�ا نسبة الكتلة electron to shielded helion magnetic moment ratio إلكترون to محجوب هيليون نسبة العزم المغناطيسي electron to shielded proton magnetic moment ratio إلكترون to محجوب بروتون نسبة العزم المغناطيسي electron-triton mass ratio إلكترون-تريتون نسبة الكتلة electron volt-atomic mass unit relationship إلكترون �ولت-وحدة الكتلة الذرية علاقة electron volt-hartree relationship إلكترون �ولت-hartree علاقة electron volt-hertz relationship إلكترون �ولت-هرتز علاقة electron volt-inverse meter relationship إلكترون �ولت-متر عكسي علاقة electron volt-joule relationship إلكترون �ولت-جول علاقة electron volt-kelvin relationship إلكترون �ولت-كل�ن علاقة electron volt-kilogram relationship إلكترون �ولت-كيلوغرام علاقة hartree-atomic mass unit relationship hartree-وحدة الكتلة الذرية علاقة hartree-electron volt relationship hartree-إلكترون �ولت علاقة muon Compton wavelength ميون طول موجة كومبتون muon-electron mass ratio ميون-إلكترون نسبة الكتلة muon g factor ميون عامل g muon magnetic moment ميون العزم المغناطيسي muon magnetic moment anomaly ميون العزم المغناطيسي anomaly muon magnetic moment to Bohr magneton ratio ميون العزم المغناطيسي to مغنطون بور ratio muon magnetic moment to nuclear magneton ratio ميون العزم المغناطيسي to المغنطون النووي ratio muon mass ميون الكتلة muon mass energy equivalent ميون مكا�ئ طاقة الكتلة muon mass energy equivalent in MeV ميون مكا�ئ طاقة الكتلة in MeV muon mass in u ميون الكتلة in u muon molar mass ميون الكتلة المولية muon-neutron mass ratio ميون-نيوترون نسبة الكتلة muon-proton magnetic moment ratio ميون-بروتون نسبة العزم المغناطيسي muon-proton mass ratio ميون-بروتون نسبة الكتلة muon-tau mass ratio ميون-تاو نسبة الكتلة reduced muon Compton wavelength المختزل ميون طول موجة كومبتون reduced tau Compton wavelength المختزل تاو طول موجة كومبتون tau Compton wavelength تاو طول موجة كومبتون tau-electron mass ratio تاو-إلكترون نسبة الكتلة tau mass تاو الكتلة tau mass energy equivalent تاو مكا�ئ طاقة الكتلة tau mass in u تاو الكتلة in u tau molar mass تاو الكتلة المولية tau-muon mass ratio تاو-ميون نسبة الكتلة tau-neutron mass ratio تاو-نيوترون نسبة الكتلة tau-proton mass ratio تاو-بروتون نسبة الكتلة proton charge to mass quotient بروتون نسبة الشحنة إلى الكتلة proton Compton wavelength بروتون طول موجة كومبتون proton-electron mass ratio بروتون-إلكترون نسبة الكتلة proton g factor (gₚ) بروتون عامل g (gₚ) proton gyromagnetic ratio (γₚ) بروتون النسبة الجيرومغناطيسية (γₚ) proton gyromagnetic ratio in MHz/T بروتون النسبة الجيرومغناطيسية in MHz/T proton magnetic moment (μₚ) بروتون العزم المغناطيسي (μₚ) proton magnetic moment to Bohr magneton ratio بروتون العزم المغناطيسي to مغنطون بور ratio proton magnetic moment to nuclear magneton ratio بروتون العزم المغناطيسي to المغنطون النووي ratio proton magnetic shielding correction بروتون magnetic الحجب تصحيح proton mass (mₚ) بروتون الكتلة (mₚ) proton mass energy equivalent بروتون مكا�ئ طاقة الكتلة proton mass energy equivalent in MeV بروتون مكا�ئ طاقة الكتلة in MeV proton mass in u بروتون الكتلة in u proton molar mass (Mₚ) بروتون الكتلة المولية (Mₚ) proton-muon mass ratio بروتون-ميون نسبة الكتلة proton-neutron magnetic moment ratio بروتون-نيوترون نسبة العزم المغناطيسي proton-neutron mass ratio بروتون-نيوترون نسبة الكتلة proton relative atomic mass (Ar(p)) بروتون الكتلة الذرية النسبية (Ar(p)) proton rms charge radius بروتون نص� قطر الشحنة الجذري المتوسط proton-tau mass ratio بروتون-تاو نسبة الكتلة reduced proton Compton wavelength المختزل بروتون طول موجة كومبتون shielded proton gyromagnetic ratio محجوب بروتون النسبة الجيرومغناطيسية shielded proton gyromagnetic ratio in MHz/T محجوب بروتون النسبة الجيرومغناطيسية in MHz/T shielded proton magnetic moment محجوب بروتون العزم المغناطيسي shielded proton magnetic moment to Bohr magneton ratio محجوب بروتون العزم المغناطيسي to مغنطون بور ratio shielded proton magnetic moment to nuclear magneton ratio محجوب بروتون العزم المغناطيسي to المغنطون النووي ratio neutron Compton wavelength نيوترون طول موجة كومبتون neutron-electron magnetic moment ratio نيوترون-إلكترون نسبة العزم المغناطيسي neutron-electron mass ratio نيوترون-إلكترون نسبة الكتلة neutron g factor (gₙ) نيوترون عامل g (gₙ) neutron gyromagnetic ratio (γₙ) نيوترون النسبة الجيرومغناطيسية (γₙ) neutron gyromagnetic ratio in MHz/T نيوترون النسبة الجيرومغناطيسية in MHz/T neutron magnetic moment (μₙ) نيوترون العزم المغناطيسي (μₙ) neutron magnetic moment to Bohr magneton ratio نيوترون العزم المغناطيسي to مغنطون بور ratio neutron magnetic moment to nuclear magneton ratio نيوترون العزم المغناطيسي to المغنطون النووي ratio neutron mass (mₙ) نيوترون الكتلة (mₙ) neutron mass energy equivalent نيوترون مكا�ئ طاقة الكتلة neutron mass energy equivalent in MeV نيوترون مكا�ئ طاقة الكتلة in MeV neutron mass in u نيوترون الكتلة in u neutron molar mass (Mₙ) نيوترون الكتلة المولية (Mₙ) neutron-muon mass ratio نيوترون-ميون نسبة الكتلة neutron-proton magnetic moment ratio نيوترون-بروتون نسبة العزم المغناطيسي neutron-proton mass difference نيوترون-بروتون الكتلة �رق neutron-proton mass difference energy equivalent نيوترون-بروتون الكتلة �رق الطاقة equivalent neutron-proton mass difference energy equivalent in MeV نيوترون-بروتون الكتلة �رق الطاقة equivalent in MeV neutron-proton mass difference in u نيوترون-بروتون الكتلة �رق in u neutron-proton mass ratio نيوترون-بروتون نسبة الكتلة neutron relative atomic mass (Ar(n)) نيوترون الكتلة الذرية النسبية (Ar(n)) neutron-tau mass ratio نيوترون-تاو نسبة الكتلة neutron to shielded proton magnetic moment ratio نيوترون to محجوب بروتون نسبة العزم المغناطيسي reduced neutron Compton wavelength المختزل نيوترون طول موجة كومبتون deuteron-electron magnetic moment ratio ديوترون-إلكترون نسبة العزم المغناطيسي deuteron-electron mass ratio ديوترون-إلكترون نسبة الكتلة deuteron g factor ديوترون عامل g deuteron magnetic moment ديوترون العزم المغناطيسي deuteron magnetic moment to Bohr magneton ratio ديوترون العزم المغناطيسي to مغنطون بور ratio deuteron magnetic moment to nuclear magneton ratio ديوترون العزم المغناطيسي to المغنطون النووي ratio deuteron mass ديوترون الكتلة deuteron mass energy equivalent ديوترون مكا�ئ طاقة الكتلة deuteron mass energy equivalent in MeV ديوترون مكا�ئ طاقة الكتلة in MeV deuteron mass in u ديوترون الكتلة in u deuteron molar mass ديوترون الكتلة المولية deuteron-neutron magnetic moment ratio ديوترون-نيوترون نسبة العزم المغناطيسي deuteron-proton magnetic moment ratio ديوترون-بروتون نسبة العزم المغناطيسي deuteron-proton mass ratio ديوترون-بروتون نسبة الكتلة deuteron relative atomic mass (Ar(d)) ديوترون الكتلة الذرية النسبية (Ar(d)) deuteron rms charge radius ديوترون نص� قطر الشحنة الجذري المتوسط triton-electron mass ratio تريتون-إلكترون نسبة الكتلة triton g factor (gₜ) تريتون عامل g (gₜ) triton magnetic moment (μₜ) تريتون العزم المغناطيسي (μₜ) triton magnetic moment to Bohr magneton ratio تريتون العزم المغناطيسي to مغنطون بور ratio triton magnetic moment to nuclear magneton ratio تريتون العزم المغناطيسي to المغنطون النووي ratio triton mass (mₜ) تريتون الكتلة (mₜ) triton mass energy equivalent تريتون مكا�ئ طاقة الكتلة triton mass energy equivalent in MeV تريتون مكا�ئ طاقة الكتلة in MeV triton mass in u تريتون الكتلة in u triton molar mass (Mₜ) تريتون الكتلة المولية (Mₜ) triton-proton mass ratio تريتون-بروتون نسبة الكتلة triton relative atomic mass (Ar(t)) تريتون الكتلة الذرية النسبية (Ar(t)) triton to proton magnetic moment ratio تريتون to بروتون نسبة العزم المغناطيسي helion-electron mass ratio هيليون-إلكترون نسبة الكتلة helion g factor (gₕ) هيليون عامل g (gₕ) helion magnetic moment (μₕ) هيليون العزم المغناطيسي (μₕ) helion magnetic moment to Bohr magneton ratio هيليون العزم المغناطيسي to مغنطون بور ratio helion magnetic moment to nuclear magneton ratio هيليون العزم المغناطيسي to المغنطون النووي ratio helion mass (mₕ) هيليون الكتلة (mₕ) helion mass energy equivalent هيليون مكا�ئ طاقة الكتلة helion mass energy equivalent in MeV هيليون مكا�ئ طاقة الكتلة in MeV helion mass in u هيليون الكتلة in u helion molar mass (Mₕ) هيليون الكتلة المولية (Mₕ) helion-proton mass ratio هيليون-بروتون نسبة الكتلة helion relative atomic mass (Ar(h)) هيليون الكتلة الذرية النسبية (Ar(h)) helion shielding shift هيليون الحجب shift shielded helion gyromagnetic ratio محجوب هيليون النسبة الجيرومغناطيسية shielded helion gyromagnetic ratio in MHz/T محجوب هيليون النسبة الجيرومغناطيسية in MHz/T shielded helion magnetic moment محجوب هيليون العزم المغناطيسي shielded helion magnetic moment to Bohr magneton ratio محجوب هيليون العزم المغناطيسي to مغنطون بور ratio shielded helion magnetic moment to nuclear magneton ratio محجوب هيليون العزم المغناطيسي to المغنطون النووي ratio shielded helion to proton magnetic moment ratio محجوب هيليون to بروتون نسبة العزم المغناطيسي shielded helion to shielded proton magnetic moment ratio محجوب هيليون to محجوب بروتون نسبة العزم المغناطيسي alpha particle mass جسيم أل�ا الكتلة alpha particle mass in u جسيم أل�ا الكتلة in u alpha particle mass energy equivalent جسيم أل�ا مكا�ئ طاقة الكتلة alpha particle mass energy equivalent in MeV جسيم أل�ا مكا�ئ طاقة الكتلة in MeV alpha particle-electron mass ratio جسيم أل�ا-إلكترون نسبة الكتلة alpha particle-proton mass ratio جسيم أل�ا-بروتون نسبة الكتلة alpha particle rms charge radius جسيم أل�ا نص� قطر الشحنة الجذري المتوسط alpha particle molar mass جسيم أل�ا الكتلة المولية alpha particle relative atomic mass (Ar(α)) جسيم أل�ا الكتلة الذرية النسبية (Ar(α)) atomic mass constant (mᵤ) atomic الكتلة ثابت (mᵤ) Avogadro constant ثابت أ�وغادرو Boltzmann constant (k) ثابت بولتزمان (k) Boltzmann constant in eV/K ثابت بولتزمان in eV/K Boltzmann constant in Hz/K ثابت بولتزمان in Hz/K Boltzmann constant in inverse meter per kelvin ثابت بولتزمان in متر عكسي per كل�ن electron volt (eV) إلكترون �ولت (eV) Faraday constant (F) ثابت �اراداي (F) first radiation constant (c�) first ثابت الإشعاع (c�) first radiation constant for spectral radiance first ثابت الإشعاع for spectral radiance molar gas constant (R) ثابت الغاز المولي (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) ثابت لوشميت (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) ثابت لوشميت (n₀, 273.15 K, 101.325 kPa) molar Planck constant molar ثابت بلانك second radiation constant (c₂) second ثابت الإشعاع (c₂) Stefan-Boltzmann constant (σ) ثابت ستي�ان-بولتزمان (σ) lattice spacing of ideal Si (d₂₂₀) تباعد الشبكة للسيليكون المثالي (d₂₂₀) atomic mass constant energy equivalent atomic الكتلة ثابت الطاقة equivalent atomic mass constant energy equivalent in MeV atomic الكتلة ثابت الطاقة equivalent in MeV atomic mass unit-electron volt relationship وحدة الكتلة الذرية-إلكترون �ولت علاقة molar mass constant (Mᵤ) الكتلة المولية ثابت (Mᵤ) molar mass of carbon-12 الكتلة المولية of carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) الحجم المولي للغاز المثالي (273.15 K، 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) الحجم المولي للغاز المثالي (273.15 K، 101.325 kPa) molar volume of silicon الحجم المولي للسيليكون Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode ثابت (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode ثابت (1 K, 101.325 kPa) Wien frequency displacement law constant Wien frequency displacement law ثابت Wien wavelength displacement law constant Wien wavelength displacement law ثابت standard atmosphere (atm) الغلا� الجوي القياسي (atm) standard-state pressure (p°) standard-state الضغط (p°) Angstrom star (Å*) أنغستروم نجمي (Å*) Copper x unit وحدة x للنحاس Molybdenum x unit وحدة x للموليبدينوم atomic unit of magnetizability الوحدة الذرية لـ magnetizability atomic unit of mass (mₑ) الوحدة الذرية لـ الكتلة (mₑ) atomic unit of momentum الوحدة الذرية لـ momentum atomic unit of permittivity الوحدة الذرية لـ permittivity atomic unit of time الوحدة الذرية لـ الزمن atomic unit of velocity الوحدة الذرية لـ السرعة hartree-hertz relationship hartree-هرتز علاقة hartree-inverse meter relationship hartree-متر عكسي علاقة hartree-joule relationship hartree-جول علاقة hartree-kelvin relationship hartree-كل�ن علاقة hartree-kilogram relationship hartree-كيلوغرام علاقة shielding difference of d and p in HD الحجب �رق of d and p in HD shielding difference of t and p in HT الحجب �رق of t and p in HT pi (π) باي (π) Euler's number (e) عدد أويلر (e) golden ratio (φ) النسبة الذهبية (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni ثابت (γ) nominal solar radius الشمسي الاسمي نص� القطر nominal solar total irradiance الشمسي الاسمي total irradiance nominal solar luminosity الشمسي الاسمي اللمعان nominal solar effective temperature الشمسي الاسمي درجة الحرارة ال�عالة nominal solar mass parameter الشمسي الاسمي معامل الكتلة nominal terrestrial equatorial radius الأرضي الاسمي الاستوائي نص� القطر nominal terrestrial polar radius الأرضي الاسمي القطبي نص� القطر nominal terrestrial mass parameter الأرضي الاسمي معامل الكتلة nominal jovian equatorial radius المشتري الاسمي الاستوائي نص� القطر nominal jovian polar radius المشتري الاسمي القطبي نص� القطر nominal jovian mass parameter المشتري الاسمي معامل الكتلة average value of one minus the rate of TCG relative to TCB القيمة المتوسطة لواحد ناقص معدل TCG بالنسبة إلى TCB solar mass parameter (TCB-compatible) solar معامل الكتلة (TCB-compatible) solar mass parameter (TDB-compatible) solar معامل الكتلة (TDB-compatible) equatorial radius of the Earth (TT-compatible) الاستوائي نص� القطر of the الأرض (TT-compatible) dynamical form factor of the Earth dynamical form factor of the الأرض time rate of change in the dynamical form factor of the Earth الزمن rate of change in the dynamical form factor of the الأرض geocentric gravitational constant (TCB-compatible) geocentric gravitational ثابت (TCB-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational ثابت (TT-compatible) geocentric gravitational constant (TDB-compatible) geocentric gravitational ثابت (TDB-compatible) potential of the geoid جهد الجيويد nominal mean angular velocity of the Earth (TT-compatible) nominal mean angular السرعة of the الأرض (TT-compatible) ratio mass of the Moon to the Earth نسبة كتلة the القمر to the الأرض ratio of the mass of the Sun to Mercury نسبة كتلة the الشمس to عطارد ratio of the mass of the Sun to Venus نسبة كتلة the الشمس to الزهرة ratio of the mass of the Sun to Mars نسبة كتلة the الشمس to المريخ ratio of the mass of the Sun to Jupiter نسبة كتلة the الشمس to المشتري ratio of the mass of the Sun to Saturn نسبة كتلة the الشمس to زحل ratio of the mass of the Sun to Uranus نسبة كتلة the الشمس to أورانوس ratio of the mass of the Sun to Neptune نسبة كتلة the الشمس to نبتون ratio of the mass of the Sun to (134340) Pluto نسبة كتلة the الشمس to (134340) Pluto ratio of the mass of the Sun to (136199) Eris نسبة كتلة the الشمس to (136199) Eris ratio of the mass of (1) Ceres to the Sun نسبة كتلة (1) Ceres to the الشمس ratio of the mass of (2) Pallas to the Sun نسبة كتلة (2) Pallas to the الشمس ratio of the mass of (4) Vesta to the Sun نسبة كتلة (4) Vesta to the الشمس mean obliquity of the ecliptic at J2000.0 متوسط ميل دائرة البروج at J2000.0 Electromagnetic الكهرومغناطيسية Compton wavelength طول موجى كومبتون Astronomy علم ال�لك ConstantsWidget Domain المجال Subdomain المجال ال�رعي No match found لا تطابق موجود Name الاسم Value القيمة Unit الوحدة Search بحث All الكل CustomKeypadDialog Custom Keypad لوحة م�اتيح مخصصة Rows: الص�و�: Columns: الأعمدة: Copy preset: نسخ الإعداد المسبق: Basic أساسي Scientific (wide) علمي (عريض) Scientific (narrow) علمي (ضيق) Apply تطبيق Row ص� Column عمود Label التسمية Behavior السلوك Text النص DiagnosticsDialog App Diagnostics تشخيص التطبيق Copy to Clipboard نسخ إلى الحا�ظة Editor Unit الوحدة User unit وحدة المستخدم User function دالة مستخدم Argument وسيط Current result:<br/>%1 النتيجة الحالية:<br/>%1 Selection result:<br/>%1 نتيجة التحديد:<br/>%1 Selection result: n/a نتيجة التحديد: غير متو�ر Selection result: %1 نتيجة التحديد: %1 second ثانية metre متر kilogram كيلوغرام mole مول radian راديان steradian ستيراديان degree Celsius درجة مئوية cubic metre متر مكعب cubic millimetre مليمتر مكعب cubic centimetre سنتيمتر مكعب cubic decimetre ديسيمتر مكعب cubic kilometre كيلومتر مكعب square millimetre مليمتر مربع square kilometre كيلومتر مربع square metre متر مربع minute دقيقة hour ساعة day يوم astronomical unit وحدة �لكية degree درجة arcminute دقيقة قوسية arcsecond ثانية قوسية milliarcsecond ملي ثانية قوسية microarcsecond ميكروثانية قوسية hectare هكتار litre لتر tonne طن Dalton دالتون electronvolt إلكترون �ولت Angstrom أنغستروم atmosphere غلا� جوي atomic mass unit وحدة الكتلة الذرية British thermal unit وحدة حرارية بريطانية calorie سعرة حرارية carat قيراط cup كوب cup (Imperial) كوب (إمبراطوري) cup (Japanese) كوب (ياباني) cup (US) كوب (أمريكي) degree Fahrenheit درجة �هرنهايت fathom قامة fluid ounce (Imperial) أونصة سائلة (إمبراطورية) fluid ounce (US) أونصة سائلة (أمريكية) fluid dram (Imperial) درام سائل (إمبراطوري) fluid dram (US) درام سائل (أمريكي) foot قدم square foot مربع foot cubic foot مكعب foot gallon (Imperial) غالون (إمبراطوري) gallon (US) غالون (أمريكي) gill (Imperial) جيل (إمبراطوري) gill (US) جيل (أمريكي) gradian غراديان grain حبة gram غرام Hartley هارتلي Hartree energy unit طاقة هارتري unit horsepower حصان بخاري inch بوصة square inch مربع inch cubic inch مكعب inch karat قيراط knot عقدة lightminute دقيقة ضوئية lightsecond ثانية ضوئية lightyear سنة ضوئية long ton طن طويل mile ميل square mile مربع mile cubic mile مكعب mile mile per hour ميل �ي الساعة kilometre per hour كيلومتر �ي الساعة nautical mile ميل بحري ounce أونصة parsec �رسخ �لكي pint (Imperial) باينت (إمبراطوري) pint (US) باينت (أمريكي) pound رطل pounds per square inch pounds per مربع inch quart (Imperial) كوارت (إمبراطوري) quart (US) كوارت (أمريكي) oil barrel برميل ن�ط beer barrel (US) برميل بيرة (أمريكي) square yard مربع yard cubic yard مكعب yard short ton طن قصير tablespoon ملعقة طعام tablespoon (Australian) ملعقة طعام (أسترالية) tablespoon (Imperial) ملعقة طعام (إمبراطورية) tablespoon (US) ملعقة طعام (أمريكية) dessert spoon ملعقة حلوى teaspoon ملعقة شاي teaspoon (Imperial) ملعقة شاي (إمبراطورية) teaspoon (US) ملعقة شاي (أمريكية) turn دورة revolution دورة revolution per minute دورة �ي الدقيقة week أسبوع kilowatt hour كيلوواط ساعة millimetre of mercury مليمتر زئبق yard ياردة Julian century قرن يولياني Julian year سنة يوليانية sidereal year سنة نجمية tropical year سنة مدارية Evaluator invalid expression صيغة غير صحيحة division by zero قسمة على الص�ر too time consuming - computation was rejected تم ر�ض العملية الحسابية - تستغرق وقت طويلاً dimension mismatch - quantities with different dimensions cannot be compared, added, etc. عدم تطابق الأبعاد - لا يمكن مقارنة الكميات ذات الأبعاد المختل�ة أو جمعها، إلخ. invalid dimension - operation might require dimensionless arguments ب�عد غير صحيح. العملية ربما تطلب متغيرات بلا ب�عد Computation aborted - encountered numerical instability أ�لغي الحساب - حدث عدم استقرار عددي invalid dimension - function might require dimensionless arguments ب�عد غير صحيح. الدالة ربما تطلب متغيرات بلا ب�عد error خطأ unit must not be zero الوحدة يجب ألا تكون ص�ر Conversion failed - dimension mismatch �شل التحويل - عدم تطابق الأبعاد unknown function or variable دالة أو متغير غير معرو� recursion not supported الاستدعاء الذاتي غير مدعوم cannot operate on a NaN لا يمكن إجراء العملية على قيمة NaN underflow - tiny result is out of SpeedCrunch's number range تجاوز س�لي - النتيجة الصغيرة جدًا خارج نطاق أعداد SpeedCrunch overflow - huge result is out of SpeedCrunch's number range تجاوز - النتيجة الكبيرة جدًا خارج نطاق أعداد SpeedCrunch overflow - logic result exceeds maximum of 256 bits تجاوز - نتيجة العملية المنطقية تتجاوز الحد الأقصى البالغ 256 بت overflow - integer result exceeds maximum limit for integers تجاوز - نتيجة العدد الصحيح تتجاوز الحد الأقصى للأعداد الصحيحة operation is not defined for these arguments العملية غير معرّ�ة لهذه الوسائط wrong number of arguments عدد الوسائط غير صحيح does not take NaN as an argument لا يقبل NaN كوسيط result out of range النتيجة خارج النطاق undefined for argument domain غير معرّ� �ي مجال الوسيط computation too expensive الحساب مكل� جدًا internal error, please report a bug خطأ داخلي، يرجى الإبلاغ عن علة syntax error خطأ �ي الصياغة conversion target must be a unit يجب أن يكون هد� التحويل وحدة unknown unit وحدة غير معرو�ة %1 is a reserved name, please choose another %1 اسم محجوز، يرجى اختيار اسم آخر %1 is a global user definition and cannot be overridden in this session. %1 هو تعري� مستخدم عام ولا يمكن تجاوزه �ي هذه الجلسة. %1 is a variable name, please choose another or delete the variable %1 اسم متغير، يرجى اختيار اسم آخر أو حذ� المتغير argument %1 is used more than once الوسيط %1 مستخدم أكثر من مرة %1 is a built-in unit name, please choose another %1 اسم وحدة مدمجة، يرجى اختيار اسم آخر %1 is a user function name, please choose another or delete the function %1 اسم دالة مستخدم، يرجى اختيار اسم آخر أو حذ� الدالة FunctionRepo max; trials; probability الحد الأقصى; التجارب; الاحتمال trials; probability التجارب; الاحتمال hits; trials; probability النجاحات; التجارب; الاحتمال max; total; hits; trials الحد الأقصى; الإجمالي; النجاحات; التجارب total; hits; trials الإجمالي; النجاحات; التجارب count; total; hits; trials العدد; الإجمالي; النجاحات; التجارب dividend; divisor المقسوم; المقسوم عليه x; exponent_bits; significand_bits [; exponent_bias] x; بتات الأس; بتات الجزء المعنوي [; انحياز الأس] base; x الأساس; x value; modulo القيمة; المقياس base; exponent; modulo الأساس; الأس; المقياس events; average_events الأحداث; متوسط الأحداث average_events متوسط الأحداث x [; precision] x [; الدقة] Absolute Value القيمة المطلقة Absolute Deviation الانحرا� المطلق Arc Cosine قوس جيب التمام Logical AND و منطقي Area Hyperbolic Cosine جيب التمام الزائدي العكسي Area Hyperbolic Sine الجيب الزائدي العكسي Area Hyperbolic Tangent الظل الزائدي العكسي Arc Sine قوس الجيب Arc Tangent قوس الظل Arc Tangent with two Arguments قوس الظل بوسيطين Average (Arithmetic Mean) المتوسط (الوسط الحسابي) Binomial Cumulative Distribution Function دالة التوزيع التراكمي ذي الحدين Binomial Distribution Mean متوسط التوزيع ذي الحدين Binomial Probability Mass Function دالة الكتلة الاحتمالية للتوزيع ذي الحدين Binomial Distribution Variance تباين التوزيع ذي الحدين Cube Root الجذر المكعب Complex Conjugate المرا�ق المركب Cosine جتا Hyperbolic Cosine جيب التمام الزائدي Cotangent ظل التمام Cosecant قاطع التمام Convert Unix timestamp to Date تحويل طابع Unix الزمني إلى تاريخ Degrees of Arc درجات قوسية Error Function دالة خاطئة Complementary Error Function دالة الخطأ التكميلية Exponential أسي Fractional Part الجزء الكسري Extension of Factorials [= (x-1)!] امتداد المضروب [= (x-1)!] Greatest Common Divisor القاسم المشترك الأكبر Geometric Mean متوسط هندسي Gradians of arc غراديانات قوسية Hypergeometric Cumulative Distribution Function دالة التوزيع التراكمي �وق الهندسي Hypergeometric Distribution Mean متوسط التوزيع �وق الهندسي Hypergeometric Probability Mass Function دالة الكتلة الاحتمالية للتوزيع �وق الهندسي Hypergeometric Distribution Variance تباين التوزيع �وق الهندسي Integer Quotient خارج القسمة الصحيح Integer Part جزء صحيح Imaginary Part جزء تخيلي Decode IEEE-754 Binary Value �ك ترميز قيمة IEEE-754 ثنائية Encode IEEE-754 Binary Value ترميز قيمة IEEE-754 ثنائية Decode 16-bit Half-Precision Value �ك ترميز قيمة نص� الدقة 16-بت Encode 16-bit Half-Precision Value ترميز قيمة نص� الدقة 16-بت Decode 32-bit Single-Precision Value �ك ترميز قيمة أحادية الدقة 32-بت Encode 32-bit Single-Precision Value ترميز قيمة أحادية الدقة 32-بت Decode 64-bit Double-Precision Value �ك ترميز قيمة مزدوجة الدقة 64-بت Encode 64-bit Double-Precision Value ترميز قيمة مزدوجة الدقة 64-بت Decode 128-bit Quad-Precision Value �ك ترميز قيمة رباعية الدقة 128-بت Encode 128-bit Quad-Precision Value ترميز قيمة رباعية الدقة 128-بت Binary Logarithm لوغاريتم ثنائي Common Logarithm لوغاريتم عشري Natural Logarithm لوغاريتم طبيعي Logarithm to Arbitrary Base لوغاريتم لأساس اختياري Mask to a bit size قصر القيمة على حجم بتات Maximum الحد الاقصى Median Value (50th Percentile) الوسيط (المئين الخمسون) Minimum الحد الأدنى Modulo باقي القسمة Euclidean Modulo باقي القسمة الإقليدي Modular Exponentiation الأس النمطي Combination (Binomial Coefficient) التوا�يق (معامل ثنائي الحدين) Logical NOT ن�ي منطقي Permutation (Arrangement) التباديل (الترتيب) Convert to Binary Representation تحويل إلى تمثيل ثنائي Arithmetic الحساب Chemistry الكيمياء Complex الأعداد المركبة Combinatorics التوا�يق Probability الاحتمالات Statistics الإحصاء Aggregation التجميع Random عشوائي Base conversion تحويل الأساس Number formatting تنسيق الأعداد Integer arithmetic حساب الأعداد الصحيحة Special functions دوال خاصة Exponential & Logarithmic الأسي واللوغاريتمي Angle conversion تحويل الزوايا Trigonometry علم المثلثات Bitwise عمليات البت Floating point ال�اصلة العائمة Date & Time التاريخ والوقت Linear algebra الجبر الخطي unix_timestamp; x hours offset to GMT طابع Unix الزمني; إزاحة x ساعة عن GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; إزاحة x ساعة عن GMT [digits] [الأرقام] max [; min] الحد الأقصى [; الحد الأدنى] List Literal قائمة حر�ية Convert to Padded Binary Representation تحويل إلى تمثيل ثنائي مبطن Round Toward +∞ (Ceiling) تقريب باتجاه +∞ (السق�) Cosine plus Imaginary Sine جيب التمام زائد جيب تمام تخيلي Convert to Cis Complex Form تحويل إلى الصيغة المركبة cis Matrix Column Count عدد أعمدة المص�و�ة Population Correlation Matrix (n) مجتمع ارتباط مص�و�ة (n) Sample Correlation Matrix (n-1) عينة ارتباط مص�و�ة (n-1) Count العدد Population Covariance Matrix (n) مجتمع تغاير مص�و�ة (n) Sample Covariance Matrix (n-1) عينة تغاير مص�و�ة (n-1) Cross Product جداء اتجاهي Convert Date to Unix timestamp تحويل التاريخ إلى طابع Unix الزمني Convert to Decimal Representation تحويل إلى تمثيل عشري Determinant المحدد Convert to Sexagesimal Notation تحويل إلى تدوين ستيني Dot Product جداء نقطي Convert to Engineering Notation تحويل إلى تدوين هندسي Convert to Exponential Complex Form تحويل إلى الصيغة المركبة الأسية Round Toward −∞ (Floor) تقريب باتجاه −∞ (الأرضية) Flatten Matrix تسطيح مص�و�ة Least Common Multiple المضاع� المشترك الأصغر Convert to Hexadecimal Representation تحويل إلى تمثيل ست عشري Convert to Padded Hexadecimal Representation تحويل إلى تمثيل ست عشري مبطن Inverse Matrix معكوس مص�و�ة Round to 16-bit Half-Precision Value تقريب إلى قيمة نص� الدقة 16-بت Round to 32-bit Single-Precision Value تقريب إلى قيمة أحادية الدقة 32-بت Round to 64-bit Double-Precision Value تقريب إلى قيمة مزدوجة الدقة 64-بت Round to 128-bit Quad-Precision Value تقريب إلى قيمة رباعية الدقة 128-بت Residual from 16-bit Half-Precision Rounding الباقي من تقريب نص� الدقة 16-بت Residual from 32-bit Single-Precision Rounding الباقي من تقريب أحادي الدقة 32-بت Residual from 64-bit Double-Precision Rounding الباقي من تقريب مزدوج الدقة 64-بت Residual from 128-bit Quad-Precision Rounding الباقي من تقريب رباعي الدقة 128-بت Substance Mass كتلة المادة Molarity المولارية Molar Mass الكتلة المولية Median Absolute Deviation الانحرا� المطلق الوسيط Mean المتوسط Numerical Value of Quantity القيمة العددية للكمية Random Decimal Number عدد عشري عشوائي Random Integer Number عدد صحيح عشوائي Convert to Rational Representation تحويل إلى تمثيل نسبي Convert to Octal Representation تحويل إلى تمثيل ثماني Convert to Padded Octal Representation تحويل إلى تمثيل ثماني مبطن Vector or Matrix Norm معيار متجه أو مص�و�ة Logical OR أو منطقي Population Count (Hamming Weight) عدد البتات المضبوطة (وزن هامنغ) Phase of Complex Number طور العدد المركب Poissonian Cumulative Distribution Function دالة التوزيع التراكمي لبواسون Poissonian Distribution Mean متوسط توزيع بواسون Poissonian Probability Mass Function دالة الكتلة الاحتمالية لتوزيع بواسون Poissonian Distribution Variance تباين توزيع بواسون Convert to Phasor Complex Form تحويل إلى الصيغة المركبة ال�يزورية Convert to Rectangular Complex Form تحويل إلى الصيغة المركبة المستطيلة Round Half Away from Zero تقريب النص� بعيدًا عن الص�ر Round Half Even تقريب النص� إلى الزوجي Nth Root الجذر النوني Convert to Scientific Notation تحويل إلى تدوين علمي Matrix Row Count عدد ص�و� المص�و�ة List or Matrix Shape شكل القائمة أو المص�و�ة Summation المجموع Population Standard Deviation (n) الانحرا� المعياري للمجتمع (n) Sample Standard Deviation (n-1) الانحرا� المعياري للعينة (n-1) Round Toward Zero (Truncation) تقريب باتجاه الص�ر (اقتطاع) Matrix Trace أثر المص�و�ة Transpose Matrix نقل المص�و�ة Population Variance (n) تباين المجتمع (n) Sample Variance (n-1) تباين العينة (n-1) Product حاصل الضرب Radians راديانات Matrix Rank رتبة المص�و�ة Real Part الجزء الحقيقي Secant القاطع Arithmetic Shift Left إزاحة حسابية لليسار Arithmetic Shift Right إزاحة حسابية لليمين Signum دالة الإشارة Sine جا Hyperbolic Sine الجيب الزائدي Square Root جذر مربع Sum جمع Tangent الظل Convert to Trigonometric Complex Form تحويل إلى الصيغة المركبة المثلثية Turns دورات Hyperbolic Tangent الظل الزائدي Sign-extend a value تمديد إشارة قيمة Logical XOR أو حصري منطقي FunctionsWidget Domain المجال All الكل Name الاسم Search بحث No match found لم نعثر على مطابق Identifier معر� HistoryWidget Remove All Calculations Above إزالة كل الحسابات أعلاه Remove This Calculation إزالة هذه العملية الحسابية Remove All Calculations Below إزالة كل الحسابات أدناه Keypad Inverse cosine معكوس الجتا The last result آخر نتيجة Inverse sine معكوس الجا Inverse tangent معكوس الظل Evaluate expression حساب التعبير Division القسمة Multiplication الضرب Subtraction الطرح Addition الجمع Clear expression مسح العبارة Cosine جتا Backspace مسا�ة للخل� Scientific notation ترميز علمي Exponential أسي Factorial المضروب Natural logarithm لوغاريتم طبيعي Left parenthesis قوس أيسر Nth root الجذر النوني Argument separator �اصل الوسائط Square التربيع Common logarithm اللوغاريتم العشري Modulo باقي القسمة Contextual percentage النسبة المئوية السياقية Power الأس Right parenthesis قوس أيمن Sine جا Square root الجذر التربيعي Tangent الظل Pi باي Decimal separator �اصل عشري MainWindow Radian راديان Degree درجة Gradian غراديان Binary عدد ثنائي القيمة Octal الثماني Hexadecimal السادس عشري Sexagesimal ستيني Engineering decimal الهندسة العشرية Scientific decimal العدد العشري العلمي &Import... استيراد... &Quit إنهاء Clear E&xpression مسح التعبير Clear &History مسح السجل &Copy نسخ &Paste لصق &Select Expression تحديد التعبير &Constants الثوابت &Functions الدوال &History السجل &Status Bar شريط الحالة Bitfield حقل البتات Use&r Functions دوال المستخدم &Degree درجة &Radian راديان &Gradian غراديان Re&volution &دوران Auto-Insert a&ns إدراج a&ns تلقائيًا Automatic &Completion الإكمال الأتوماتيكي &Built-in Functions &الدوال المدمجة Built-in &Variables ا&لمتغيرات المدمجة User &Functions &دوال المستخدم User Va&riables &متغيرات المستخدم Open a Private Tab on Startup �تح لسان خاص عند بدء التشغيل Open and focus a new private tab whenever SpeedCrunch starts. �تح لسان خاص جديد والتركيز عليه كلما بدأ SpeedCrunch. Syntax &Highlighting تمييز الصياغة Group Digits in &Input ت&جميع أرقام الإدخال Automatic Input &Adjustments &تعديلات الإدخال التلقائية Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. ضبط المعاملات والمسا�ات والأقواس والأسس تلقائيًا، وقصر الإدخال على المحار� الصالحة. Group input digits using the selected number format. تجميع أرقام الإدخال و�ق تنسيق الأعداد المحدد. &Blinking Cursor &مؤشر وامض Blink the cursor in the expression editor. جعل المؤشر يومض �ي محرر التعابير. &Escape Clears Editor &Escape يمسح المحرر Clear the focused expression editor with Escape after dismissing any popup or preview. مسح محرر التعابير النشط بم�تاح Escape بعد إغلاق أي نا�ذة منبثقة أو معاينة. Keep Expression After Evaluation الاحت�اظ بالتعبير بعد الحساب Copy New Results Automatically نسخ النتائج الجديدة تلقائيًا &Comma �اصلة &System Default النظام الاعتيادي &Dot نقطة Dot &And Comma نقطة و�اصلة Toward +∞ (&ceil) نحو +∞ (&ceil) Toward −∞ (&floor) نحو −∞ (&floor) &Binary عدد ثنائي القيمة &Engineering هندسي &Hexadecimal السادس عشري &Octal ثماني &Scientific علمي User &Manual دليل المستخدم Issues and &Feedback &المشكلات والملاحظات &Donate تبرع &About SpeedCrunch &حول SpeedCrunch App Diag&nostics &تشخيص التطبيق S&plit &تقسيم Angle &Mode &نمط الزوايا &Complex Form &الصيغة المركبة New Tab تبويب جديد Constants ثوابت Functions دوال History سجل User Functions دوال المستخدم &Font... الخط... &Language... اللغة... &Session الجلسة &Edit تحرير &View عرض Se&ttings الإعدادات &Decimal عشري &Keypad لوحة الم�اتيح الرقمية Always on &Top دائمًا �ي الأعلى Disabled معطل Small Space مسا�ة قصيرة Medium Space مسا�ة متوسطة Large Space مسا�ة كبيرة &0 Digits 0 أرقام &15 Digits 15 رقمًا &2 Digits رقمان &3 Digits 3 أرقام &50 Digits 50 رقمًا &8 Digits 8 أرقام &Sexagesimal ستيني Reset All Settings... إعادة ضبط جميع الإعدادات... &System &النظام SpeedCrunch &Theme &سمة SpeedCrunch &Classic &كلاسيكي &Modern &حديث Context Help تعليمات السياق &Help مساعدة Error خطأ Can't read from file %1 لا يمكن القراءة من المل� %1 Import Session استيراد الجلسة Close Session إغلاق الجلسة Angle Mode: وضع الزاوية: Notation: التدوين: Precision: الدقة: Turn دورة Revolution دوران Fixed-point decimal عدد عشري ثابت ال�اصلة Rational نسبي Automatic decimal عدد عشري تلقائي Automatic تلقائي User &Definitions... تعري�ات المستخدم... New &Tab تبويب &جديد New &Private Tab &لسان خاص جديد Keep احت�اظ Make Private... جعلها خاصة... New &Window &نا�ذة جديدة &Open... &�تح... &Rename... &إعادة تسمية... Clo&ne... &استنساخ... &Close Tab إ&غلاق اللسان Reopen Clo&sed Tab إ&عادة �تح اللسان المغلق Open Sessions &Folder �تح &مجلد الجلسات &Undo &تراجع &Redo &إعادة Cu&t &قص Copy &Last Result &نسخ آخر نتيجة &Wrap in Parentheses إ&حاطة بأقواس Full Scr&een Mode &نمط ملء الشاشة &Basic أساسي &Scientific (wide) علمي (عريض) Scientific (narrow) علمي (ضيق) &Custom... مخصص... Main &Menu القائمة الرئيسية User &Variables متغيرات المستخدم &Left &يسار &Right ي&مين &Up &أعلى &Down أ&س�ل Close Pa&ne &إغلاق الجزء User &Units وحدات المستخدم &Turn دورة If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. إذا بدأ تعبير جديد بـ + أو - أو * أو /، يدرج SpeedCrunch "ans" أولًا. &Accept with Enter ال&قبول باستخدام Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. اقبل اقتراح الإكمال التلقائي الحالي باستخدام Enter دون تحديده أولًا بم�اتيح الأسهم. &Units الوحدات Show Live Result &Preview إظهار معاينة النتيجة المباشرة Save &Window Position on Exit ح�ظ موضع النا�ذة عند الخروج Hover Highlighting تمييز التحويم Group Integer Part Only تجميع الجزء الصحيح �قط Number Format... تنسيق الأرقام... Notation && Precision... التدوين والدقة... After pressing Enter, keep the entered expression selected in the editor. بعد الضغط على Enter، أبق التعبير المدخل محددًا �ي المحرر. Never أبدًا Always دائمًا Only for Single-Line Expressions �قط للتعبيرات ذات السطر الواحد Simplify Displayed Expressions تبسيط التعبيرات المعروضة History Size &Limit... حد حجم السجل... Remove Trailing &Zeroes &إزالة الأص�ار اللاحقة Nearest, Half &Away (round) الأقرب، النص� بعيدًا (round) Nearest, Half &Even (roundeven) الأقرب، النص� إلى الزوجي (roundeven) Toward &Zero (trunc) نحو الص�ر (trunc) &Fixed-Point ثابت ال�اصلة &Rational نسبي &Exponential (m·s�¹) أسي (m·s�¹) &Fractional (m/s) كسري (m/s) &Rectangular (a + bi) مستطيل (a + bi) Exponential (re�ᶿ) أسي (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) مثلثي (r(cos θ + i·sin θ)) Phasor (r∠θ) �يزوري (r∠θ) &Theme... السمة... Check for &Updates التحقق من وجود تحديثات Source Code الشي�رة المصدرية &Zoom التكبير &Results النتائج Unit Notation تدوين الوحدات Rounding Mode وضع التقريب &Notation التدوين &Imaginary Unit الوحدة التخيلية &Window النا�ذة &Editing التحرير A&utocomplete الإكمال التلقائي Up/Down Arrow History سجل السهمين للأعلى/للأس�ل &Appearance المظهر &Menus &القوائم &Docks ا&للوحات القابلة للإرساء &Input and Results ال&إدخال والنتائج &Disabled معطل &Disable تعطيل Close preview إغلاق المعاينة Rename... إعادة تسمية... Clone... استنساخ... Close Tab إغلاق اللسان New Private Tab لسان خاص جديد Open... �تح... Reopen Closed Tab إعادة �تح اللسان المغلق Split تقسيم Left يسار Right يمين Up أعلى Down أس�ل Clear مسح Delete حذ� %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 جلسة خاصة: ي�تخلّص من محتوياتها عند إغلاقها. اختر الجلسة > احت�اظ لتحويلها إلى جلسة عادية. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [خاصة] Reset All Settings إعادة ضبط جميع الإعدادات Reset all settings to their default values? إعادة ضبط جميع الإعدادات إلى قيمها الا�تراضية؟ This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. يشمل ذلك المظهر والتحرير وتنسيقات النتائج وت�ضيلات النوا�ذ. سي�حت�ظ بحساباتك والجلسات الم�توحة وتعري�ات المستخدم. The settings file could not be written. تعذرت كتابة مل� الإعدادات. Clear this session's calculations, unfinished expression, variables, functions, and units? مسح حسابات هذه الجلسة والتعبير غير المكتمل والمتغيرات والدوال والوحدات؟ Global user definitions are kept. ي�حت�ظ بتعري�ات المستخدم العامة. Make Session Private جعل الجلسة خاصة The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. ست�حذ� الجلسة المح�وظة %1. ستبقى محتوياتها م�توحة �ي جلسة خاصة وسي�تخلّص منها عند إغلاق تلك الجلسة أو الخروج من SpeedCrunch. Make Private جعلها خاصة Could not delete the saved session %1. تعذر حذ� الجلسة المح�وظة %1. Keep Session الاحت�اظ بالجلسة Could not save the session. It remains private. تعذر ح�ظ الجلسة. ستبقى خاصة. Clone Session استنساخ الجلسة Could not save session file %1. تعذر ح�ظ مل� الجلسة %1. Could not delete session file %1. تعذر حذ� مل� الجلسة %1. JSON file (*.json);;Any file (*.*) مل� JSON (*.json);;أي مل� (*.*) Export session as JSON تصدير الجلسة كمل� JSON The selected file is not valid JSON: %1 المل� المحدد ليس JSON صالحًا: %1 The selected file is not a SpeedCrunch session JSON file. المل� المحدد ليس مل� جلسة SpeedCrunch بصيغة JSON. This file uses an obsolete SpeedCrunch session format and cannot be imported. يستخدم هذا المل� تنسيق جلسة SpeedCrunch قديمًا ولا يمكن استيراده. The selected JSON file is missing the required $schema field. مل� JSON المحدد ي�تقد حقل $schema المطلوب. The selected JSON file uses an unsupported JSON schema: %1 يستخدم مل� JSON المحدد مخطط JSON غير مدعوم: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). مل� JSON المحدد ي�تقد معر� مخطط جلسة SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 يستخدم مل� JSON المحدد تنسيق جلسة SpeedCrunch غير مدعوم: %1 The selected JSON file is missing the required session name. مل� JSON المحدد ي�تقد اسم الجلسة المطلوب. The selected JSON file has an empty session name. يحتوي مل� JSON المحدد على اسم جلسة �ارغ. The selected JSON file has invalid or incomplete SpeedCrunch session data. يحتوي مل� JSON المحدد على بيانات جلسة SpeedCrunch غير صالحة أو غير مكتملة. Open Sessions Folder �تح مجلد الجلسات Could not create the sessions folder: %1 تعذر إنشاء مجلد الجلسات: %1 Could not open the sessions folder: %1 تعذر �تح مجلد الجلسات: %1 Editor and Results Font خط المحرر والنتائج Open Session �تح جلسة Community المجتمع Rename Session إعادة تسمية الجلسة Clear Session مسح الجلسة Delete Session حذ� الجلسة Close Pane إغلاق الجزء User Variables متغيرات المستخدم User Units وحدات المستخدم Clear History مسح السجل Are you sure you want to clear the calculation history? هل تريد بالتأكيد مسح سجل الحسابات؟ Session name: اسم الجلسة: A session named %1 already exists. توجد جلسة بالاسم %1 بال�عل. Could not create session file %1. تعذر إنشاء مل� الجلسة %1. Could not write session file %1. تعذر كتابة مل� الجلسة %1. Are you sure you want to delete this session? هل تريد بالتأكيد حذ� هذه الجلسة؟ Custom Precision دقة مخصصة Fractional digits: الخانات الكسرية: Theme السمة Light Themes سمات �اتحة Dark Themes سمات داكنة Preview معاينة Colors الألوان Select color for %1 اختر لون %1 Import... استيراد... Export... تصدير... Import Theme استيراد سمة Theme file (*.json);;All files (*) مل� سمة (*.json);;كل المل�ات (*) Invalid theme file. مل� السمة غير صالح. Can't import theme "%1" because it conflicts with a built-in theme. لا يمكن استيراد السمة "%1" لأنها تتعارض مع سمة مدمجة. Can't find a writable theme folder. تعذر العثور على مجلد سمات قابل للكتابة. Overwrite Theme استبدال السمة A custom theme named "%1" already exists. Do you want to overwrite it? توجد سمة مخصصة بالاسم "%1" بال�عل. هل تريد استبدالها؟ Can't overwrite theme file %1 لا يمكن استبدال مل� السمة %1 Can't copy theme file to %1 لا يمكن نسخ مل� السمة إلى %1 Export Theme تصدير السمة Can't export theme as "%1" because it conflicts with a built-in theme. لا يمكن تصدير السمة باسم "%1" لأنها تتعارض مع سمة مدمجة. Can't write to file %1 لا يمكن الكتابة إلى المل� %1 Global User Variable متغير مستخدم عام Global User Function دالة مستخدم عامة Global User Unit وحدة مستخدم عامة User Definitions تعري�ات المستخدم These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. هذه التعري�ات عامة ويتم تحميلها �ي كل جلسة. لا يمكن تعديلها من داخل الجلسات، وهي تتجاوز التعري�ات التي تحمل الاسم ن�سه �ي محرر الجلسة. أدخل تعري�ًا واحدًا �ي كل سطر. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] أمثلة: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply تطبيق Validate التحقق Test Results نتائج الاختبار Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 المتغيرات المستوردة: %1 الدوال المستوردة: %2 الوحدات المستوردة: %3 أرقام الأسطر التي تحتوي على أخطاء: %4 none لا يوجد Apply Results نتائج التطبيق User definitions saved. تم ح�ظ تعري�ات المستخدم. History Size Limit حد حجم السجل Maximum number of history entries for this session (0 = unlimited): الحد الأقصى لعدد إدخالات السجل لهذه الجلسة (0 = غير محدود): Text file (*.txt);;Any file (*.*) مل� نصي (*.txt);;أي مل� (*.*) Could not recalculate from calculation %1: %2 تعذرت إعادة الحساب من العملية %1: %2 History Size Limit Reached تم بلوغ حد حجم السجل This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. يشغل هذا الحساب آخر خانة متاحة �ي السجل. ستزيل الحسابات اللاحقة أقدم حساب من السجل. يمكنك زيادة الحد من الجلسة > حد حجم السجل. Editing calculation. Press Esc twice to cancel. يجري تحرير الحساب. اضغط Esc مرتين للإلغاء. Calculation Settings إعدادات الحساب Invalid recalculation start index �هرس بدء إعادة الحساب غير صالح System Default الا�تراضي للنظام Language اللغة Select the language: اختر اللغة: Custom مخصص Decimal places: المنازل العشرية: &Automatic تلقائي &Precision الدقة Plain &text نص عادي Formula &Book كتاب المعادلات &Export تصدير Export session as HTML تصدير الجلسة كمل� HTML HTML file (*.html) مل� HTML (*.html) Export session as plain text تصدير الجلسة كنص عادي ManualWindow SpeedCrunch Manual دليل SpeedCrunch %1 - SpeedCrunch Manual %1 - دليل SpeedCrunch NumberFormatDialog Number Format تنسيق الأرقام <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>حدد تنسيق الأعداد للنتائج وتجميع أرقام الإدخال.</b><br/><br/>ملاحظة: ت�قبل التنسيقات الواضحة للأعداد المدخلة حتى إن اختل�ت عن تنسيق العرض المحدد.<br/> QObject Global User Variable متغير مستخدم عام Global User Function دالة مستخدم عامة Global User Unit وحدة مستخدم عامة Backspace مسا�ة للخل� Clear expression مسح التعبير Evaluate expression حساب التعبير Insert text إدراج نص Automatic decimal عدد عشري تلقائي Fixed-point decimal عدد عشري ثابت ال�اصلة Engineering decimal عدد عشري هندسي Scientific decimal عدد عشري علمي Rational نسبي Binary ثنائي Octal ثماني Hexadecimal ست عشري Sexagesimal ستيني Update Available تحديث متاح A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> يتو�ر إصدار أحدث (%1).<br/><a href="%2">زر الموقع للتنزيل.</a> Check for Updates التحقق من وجود تحديثات SpeedCrunch %1 is up to date. SpeedCrunch %1 محدّث. No connectivity. Please check your internet connection and try again. لا يوجد اتصال. تحقق من اتصال الإنترنت وحاول مرة أخرى. Could not verify the latest available version. تعذر التحقق من أحدث إصدار متاح. ResultDisplay Scroll to bottom التمرير إلى الأس�ل Edit Expression تحرير التعبير Change Settings تغيير الإعدادات New Tab تبويب جديد &Import... ا&ستيراد... &Export &تصدير Plain &text نص &عادي Copy نسخ Selection التحديد Select All تحديد الكل Expression التعبير Result النتيجة Calculation الحساب Calculation as Single Line الحساب �ي سطر واحد Remove إزالة This Calculation هذا الحساب All Calculations Above كل الحسابات أعلاه All Calculations Below كل الحسابات أدناه New Private Tab لسان خاص جديد Session الجلسة Open... �تح... Clone... استنساخ... Rename... إعادة تسمية... Keep احت�اظ Make Private... جعلها خاصة... Clear مسح Delete حذ� Close إغلاق Split تقسيم Left يسار Right يمين Up أعلى Down أس�ل Close Pane إغلاق الجزء Main Menu القائمة الرئيسية Cancel editing إلغاء التحرير Copy result نسخ النتيجة Edit expression تحرير التعبير Change settings تغيير الإعدادات Remove calculation إزالة الحساب ResultSlotsDialog Notation & Precision التدوين والدقة Result Line سطر النتيجة Enabled م�عل Notation التدوين Decimal Places المنازل العشرية Main Line السطر الرئيسي Extra Line #1 السطر الإضا�ي رقم 1 Extra Line #2 السطر الإضا�ي رقم 2 Extra Line #3 السطر الإضا�ي رقم 3 Extra Line #4 السطر الإضا�ي رقم 4 Auto تلقائي UserFunctionListWidget Name الاسم Value القيمة Description الوص� Search بحث No match found لم نعثر على مطابق Insert أدخل Edit تعديل Delete حذ� Delete All حذ� الكل UserUnitListWidget Name الاسم Value القيمة Description الوص� Search بحث No match found لم نعثر على مطابق Insert إدراج Edit تحرير Delete حذ� Delete All حذ� الكل VariableListWidget Name الاسم Value القيمة Description الوص� Search بحث No match found لم نعثر على مطابق Insert أدخل Edit تحرير Delete حذ� Delete All حذ� الكل heldercorreia-speedcrunch-e7ca37f/src/resources/locale/bg.ts000066400000000000000000011445731526573132500243540ustar00rootroot00000000000000 AboutBox About SpeedCrunch Отно�но SpeedCrunch Core developers Главни разработчици Original author �втор Close Затвори Math engine Математиче�ки модул Main author | Logo | Maintainer О�новен автор | Лого | Поддръжка Thanks Благодарно�ти Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Разработчиците на SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Тази програма е �вободен �офтуер; можете да � разпро�тран�вате и/или промен�те �ъгла�но у�лови�та на GNU General Public License, публикуван от Free Software Foundation; вер�и� 2 на лиценза или (по ваш избор) ко�то и да е по-нова вер�и�. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Тази програма �е разпро�тран�ва � надеждата, че ще бъде полезна, но БЕЗ �ИК�КВ� Г�Р��ЦИЯ; дори без подразбиращата �е гаранци� за ТЪРГОВСК� ПРИГОД�ОСТ или ПРИГОД�ОСТ З� ОПРЕДЕЛЕ�� ЦЕЛ. Вижте GNU General Public License за повече подробно�ти. BitFieldWidget Reset bits to zero �улиране на битовете Invert bits Обръщане на битовете Shift bits left Преме�тване на битовете нал�во Shift bits right Преме�тване на битовете над��но Book Index Съдържание Algebra �лгебра Quadratic Equation Квадратно уравнение Logarithmic Base Conversion См�на на о�новата на логаритъм Geometry Геометри� Circle Окръжно�т Sector Сектор Sphere Сфера Cube Куб Cone Кону� Cylinder Цилиндър Electronics Електроника Ohm's Law Закон на Ом Power Мощно�т Reactance Реактан� Resonance Резонан� Radio Frequency Радио че�тота Antennas �нтени Characteristic Impedance (coax) Характери�тично �ъпротивление (коак�иал) Velocity of Propagation (coax) Скоро�т на разпро�транение (коак�иал) Standing Wave Ratio & Return Loss Коефициент на �то�щата вълна и възвратни загуби Free Space Wavelength Дължина на вълната в �вободното про�тран�тво resistance �ъпротивление voltage напрежение current ток power мощно�т inductive reactance индуктивно �ъпротивление capacitive reactance капацитивно �ъпротивление inductance индуктивно�т capacitance капацитет frequency че�тота resonance frequency резонан�на че�тота area площ perimeter обиколка diameter диаметър radius радиу� volume обем surface area площ на повърхнина height ви�очина slant height наклонена ви�очина face diagonal Диагонал на �тена space diagonal Теле�ен диагонал edge length дължина на ръб arc length дължина на крива central angle (degrees) Централен ъгъл (в граду�и) input power входна мощно�т reflected power отразена мощно�т transmitted power предадена мощно�т return loss възвратни загуби dielectric constant диелектриче�ка кон�танта outer conductor's inner diameter вътрешен диаметър на външни� проводник inner conductor's outer diameter външен диаметър на вътрешни� проводник speed of light �коро�тта на �ветлината reflection coefficient коефициент на отражение standing wave ratio коефициент на �то�щата вълна normalized impedance нормализиран импедан� frequency (Hz) че�тота (Hz) BookDock Formula Book Спи�ък � формули ConstantCompletion Search constants Тър�ене на кон�танти No match found ��ма �ъвпадени� Constants Mathematics Математика Physics (CODATA 2022) Физика (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Хими� (IUPAC - CIAAW 2021) Uncategorized Без категори� Universal Универ�ално Physicochemical Физикохимично Atomic & Nuclear — General �томни и �дрени — общи Atomic & Nuclear — Electroweak �томни и �дрени — електро�лаби Atomic & Nuclear — Electron �томни и �дрени — електрон Atomic & Nuclear — Muon �томни и �дрени — мюон Atomic & Nuclear — Tau �томни и �дрени — тау Atomic & Nuclear — Proton �томни и �дрени — протон Atomic & Nuclear — Neutron �томни и �дрени — неутрон Atomic & Nuclear — Deuteron �томни и �дрени — деутерон Atomic & Nuclear — Triton �томни и �дрени — тритон Atomic & Nuclear — Helion �томни и �дрени — хелион Atomic & Nuclear — Alpha particle �томни и �дрени — алфа ча�тица Atomic & Nuclear — Atomic units �томни и �дрени — атомни единици Atomic & Nuclear — Energy conversion relationships �томни и �дрени — зави�имо�ти за преобразуване на енерги� Atomic & Nuclear — X-ray units �томни и �дрени — рентгенови единици Atomic & Nuclear — Magnetic shielding corrections �томни и �дрени — корекции за магнитно екраниране Masses Ма�и Lifetimes Времена на живот Molar Masses Моларни ма�и Electronegativity Електроотрицателно�т Ionization Energy Енерги� на йонизаци� Nominal Constants (IAU 2015) �оминални кон�танти (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Текущи най-добри оценки (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) характери�тичен импедан� на вакуума (Z₀) reduced Planck constant (�) редуцирана кон�танта на Планк (�) vacuum electric permittivity (ϵ₀) електрична проницаемо�т на вакуума (ϵ₀) Newtonian constant of gravitation (G) �ютонова гравитационна кон�танта (G) vacuum magnetic permeability (μ₀) магнитна проницаемо�т на вакуума (μ₀) Planck constant (h) кон�танта на Планк (h) speed of light in vacuum (c) �коро�т на �ветлината във вакуум (c) standard acceleration of gravity (gₙ) �тандартно земно у�корение (gₙ) Newtonian constant of gravitation over h-bar c �ютонова гравитационна кон�танта върху �c Planck length дължина на Планк Planck constant in eV/Hz (h) кон�танта на Планк в eV/Hz (h) Planck mass ма�а на Планк Planck mass energy equivalent in GeV енергиен еквивалент на ма�ата на Планк в GeV Planck temperature температура на Планк Planck time време на Планк reduced Planck constant in eV·s (�) редуцирана кон�танта на Планк в eV·s (�) reduced Planck constant times c in MeV·fm редуцирана кон�танта на Планк, умножена по c, в MeV·fm Bohr magneton магнетон на Бор conductance quantum (G₀) квант на проводимо�тта (G₀) Coulomb constant (kₑ) кон�танта на Кулон (kₑ) elementary charge (e) елементарен зар�д (e) elementary charge over h-bar елементарен зар�д върху � conventional value of Josephson constant конвенционална �тойно�т на кон�тантата на Джоузеф�ън Josephson constant кон�танта на Джоузеф�ън conventional value of ampere-90 конвенционална �тойно�т на ампер-90 conventional value of coulomb-90 конвенционална �тойно�т на кулон-90 conventional value of farad-90 конвенционална �тойно�т на фарад-90 conventional value of henry-90 конвенционална �тойно�т на хенри-90 conventional value of ohm-90 конвенционална �тойно�т на ом-90 conventional value of volt-90 конвенционална �тойно�т на волт-90 conventional value of watt-90 конвенционална �тойно�т на ват-90 magnetic flux quantum (Φ₀) квант на магнитни� поток (Φ₀) nuclear magneton �дрен магнетон inverse of conductance quantum обратна �тойно�т на кванта на проводимо�тта conventional value of von Klitzing constant конвенционална �тойно�т на кон�тантата на фон Клитцинг von Klitzing constant кон�танта на фон Клитцинг atomic unit of magnetic dipole moment атомна единица за магнитен диполен момент atomic unit of magnetic flux density атомна единица за магнитна индукци� Bohr magneton in eV/T магнетон на Бор в eV/T Bohr magneton in Hz/T магнетон на Бор в Hz/T Bohr magneton in inverse meter per tesla магнетон на Бор в обратни метри на те�ла Bohr magneton in K/T магнетон на Бор в K/T nuclear magneton in eV/T �дрен магнетон в eV/T nuclear magneton in inverse meter per tesla �дрен магнетон в обратни метри на те�ла nuclear magneton in K/T �дрен магнетон в K/T nuclear magneton in MHz/T �дрен магнетон в MHz/T Bohr radius (a₀) радиу� на Бор (a₀) fine-structure constant (α) кон�танта на фината �труктура (α) Hartree energy (Eₕ) енерги� на Хартри (Eₕ) Hartree energy in eV енерги� на Хартри в eV quantum of circulation квант на циркулаци�та quantum of circulation times 2 квант на циркулаци�та по 2 Rydberg constant (R∞) кон�танта на Ридберг (R∞) atomic mass unit-hartree relationship атомна единица за ма�а-hartree зави�имо�т atomic mass unit-hertz relationship атомна единица за ма�а-херц зави�имо�т atomic mass unit-inverse meter relationship атомна единица за ма�а-обратен метър зави�имо�т atomic mass unit-joule relationship атомна единица за ма�а-джаул зави�имо�т atomic mass unit-kelvin relationship атомна единица за ма�а-келвин зави�имо�т atomic mass unit-kilogram relationship атомна единица за ма�а-килограм зави�имо�т atomic unit of 1st hyperpolarizability атомна единица за хиперпол�ризуемо�т от 1-ви ред atomic unit of 2nd hyperpolarizability атомна единица за хиперпол�ризуемо�т от 2-ри ред atomic unit of charge (e) атомна единица за зар�д (e) atomic unit of charge density атомна единица за плътно�т на зар�да atomic unit of current атомна единица за ток atomic unit of electric dipole moment атомна единица за електричен диполен момент atomic unit of electric field атомна единица за електрично поле atomic unit of electric field gradient атомна единица за градиент на електричното поле atomic unit of electric polarizability атомна единица за електрична пол�ризуемо�т atomic unit of electric potential атомна единица за електричен потенциал atomic unit of electric quadrupole moment атомна единица за електричен квадруполен момент atomic unit of action атомна единица за дей�твие atomic unit of energy атомна единица за енерги� atomic unit of force атомна единица за �ила atomic unit of length атомна единица за дължина hertz-atomic mass unit relationship херц-атомна единица за ма�а зави�имо�т hertz-electron volt relationship херц-електронволт зави�имо�т hertz-hartree relationship херц-hartree зави�имо�т hertz-inverse meter relationship херц-обратен метър зави�имо�т hertz-joule relationship херц-джаул зави�имо�т hertz-kelvin relationship херц-келвин зави�имо�т hertz-kilogram relationship херц-килограм зави�имо�т hyperfine transition frequency of Cs-133 че�тота на �връхфин преход на Cs-133 inverse fine-structure constant (α�¹) обратна �тойно�т на кон�тантата на фината �труктура (α�¹) inverse meter-atomic mass unit relationship обратен метър-атомна единица за ма�а зави�имо�т inverse meter-electron volt relationship обратен метър-електронволт зави�имо�т inverse meter-hartree relationship обратен метър-hartree зави�имо�т inverse meter-hertz relationship обратен метър-херц зави�имо�т inverse meter-joule relationship обратен метър-джаул зави�имо�т inverse meter-kelvin relationship обратен метър-келвин зави�имо�т inverse meter-kilogram relationship обратен метър-килограм зави�имо�т joule-atomic mass unit relationship джаул-атомна единица за ма�а зави�имо�т joule-electron volt relationship джаул-електронволт зави�имо�т joule-hertz relationship джаул-херц зави�имо�т joule-hartree relationship джаул-hartree зави�имо�т joule-inverse meter relationship джаул-обратен метър зави�имо�т joule-kelvin relationship джаул-келвин зави�имо�т joule-kilogram relationship джаул-килограм зави�имо�т kelvin-atomic mass unit relationship келвин-атомна единица за ма�а зави�имо�т kelvin-electron volt relationship келвин-електронволт зави�имо�т kelvin-hertz relationship келвин-херц зави�имо�т kelvin-hartree relationship келвин-hartree зави�имо�т kelvin-inverse meter relationship келвин-обратен метър зави�имо�т kelvin-joule relationship келвин-джаул зави�имо�т kelvin-kilogram relationship келвин-килограм зави�имо�т kilogram-atomic mass unit relationship килограм-атомна единица за ма�а зави�имо�т kilogram-electron volt relationship килограм-електронволт зави�имо�т kilogram-hertz relationship килограм-херц зави�имо�т kilogram-hartree relationship килограм-hartree зави�имо�т kilogram-inverse meter relationship килограм-обратен метър зави�имо�т kilogram-joule relationship килограм-джаул зави�имо�т kilogram-kelvin relationship килограм-келвин зави�имо�т lattice parameter of silicon (a) параметър на решетката на �илици� (a) luminous efficacy �ветлинна ефективно�т natural unit of energy е�те�твена единица за енерги� natural unit of energy in MeV е�те�твена единица за енерги� в MeV natural unit of action (�) е�те�твена единица за дей�твие (�) natural unit of action in eV·s е�те�твена единица за дей�твие в eV·s natural unit of length е�те�твена единица за дължина natural unit of mass е�те�твена единица за ма�а natural unit of momentum е�те�твена единица за импул� natural unit of momentum in MeV/c е�те�твена единица за импул� в MeV/c natural unit of time е�те�твена единица за време natural unit of velocity е�те�твена единица за �коро�т Rydberg constant times c in Hz кон�танта на Ридберг по c в Hz Rydberg constant times hc in eV кон�танта на Ридберг, умножена по hc, в eV Rydberg constant times hc in J кон�танта на Ридберг по hc в J Fermi coupling constant кон�танта на �вързване на Ферми weak mixing angle ъгъл на �лабо �ме�ване W to Z mass ratio отношение на ма�ите W към Z Thomson cross section (σₑ) �ечение на Том�ън (σₑ) electron mass (mₑ) електрон ма�а (mₑ) electron mass in u електрон ма�а в u electron mass energy equivalent (mₑ·c²) електрон енергиен еквивалент на ма�ата (mₑ·c²) electron mass energy equivalent in MeV електрон енергиен еквивалент на ма�ата в MeV reduced Compton wavelength редуцирана комптънова дължина на вълната classical electron radius (rₑ) кла�иче�ки радиу� на електрона (rₑ) electron charge to mass quotient електрон отношение зар�д към ма�а electron-deuteron magnetic moment ratio отношение на магнитните моменти на електрона и деутерона electron-deuteron mass ratio електрон-деутерон отношение на ма�ите electron g factor (gₑ) електрон g-фактор (gₑ) electron gyromagnetic ratio (γₑ) електрон жиромагнитно отношение (γₑ) electron gyromagnetic ratio in MHz/T електрон жиромагнитно отношение в MHz/T electron-helion mass ratio електрон-хелион отношение на ма�ите electron magnetic moment (μₑ) електрон магнитен момент (μₑ) electron magnetic moment anomaly (aₑ) електрон аномали� на магнитни� момент (aₑ) electron magnetic moment to Bohr magneton ratio отношение на магнитни� момент на електрона към магнетона на Бор electron magnetic moment to nuclear magneton ratio отношение на магнитни� момент на електрона към �дрени� магнетон electron molar mass (Mₑ) електрон моларна ма�а (Mₑ) electron-muon magnetic moment ratio отношение на магнитните моменти на електрона и мюона electron-muon mass ratio електрон-мюон отношение на ма�ите electron-neutron magnetic moment ratio отношение на магнитните моменти на електрона и неутрона electron-neutron mass ratio електрон-неутрон отношение на ма�ите electron-proton magnetic moment ratio отношение на магнитните моменти на електрона и протона electron-proton mass ratio електрон-протон отношение на ма�ите electron relative atomic mass (Ar(e)) електрон отно�ителна атомна ма�а (Ar(e)) electron-tau mass ratio електрон-тау отношение на ма�ите electron to alpha particle mass ratio отношение на ма�ата на електрона към ма�ата на алфа ча�тицата electron to shielded helion magnetic moment ratio отношение на магнитни� момент на електрона към този на екранирани� хелион electron to shielded proton magnetic moment ratio отношение на магнитни� момент на електрона към този на екранирани� протон electron-triton mass ratio електрон-тритон отношение на ма�ите electron volt-atomic mass unit relationship електронволт-атомна единица за ма�а зави�имо�т electron volt-hartree relationship електронволт-hartree зави�имо�т electron volt-hertz relationship електронволт-херц зави�имо�т electron volt-inverse meter relationship електронволт-обратен метър зави�имо�т electron volt-joule relationship електронволт-джаул зави�имо�т electron volt-kelvin relationship електронволт-келвин зави�имо�т electron volt-kilogram relationship електронволт-килограм зави�имо�т hartree-atomic mass unit relationship hartree-атомна единица за ма�а зави�имо�т hartree-electron volt relationship hartree-електронволт зави�имо�т muon Compton wavelength мюон дължина на вълната на Комптън muon-electron mass ratio мюон-електрон отношение на ма�ите muon g factor мюон g-фактор muon magnetic moment мюон магнитен момент muon magnetic moment anomaly мюон аномали� на магнитни� момент muon magnetic moment to Bohr magneton ratio отношение на магнитни� момент на мюона към магнетона на Бор muon magnetic moment to nuclear magneton ratio отношение на магнитни� момент на мюона към �дрени� магнетон muon mass мюон ма�а muon mass energy equivalent мюон енергиен еквивалент на ма�ата muon mass energy equivalent in MeV мюон енергиен еквивалент на ма�ата в MeV muon mass in u мюон ма�а в u muon molar mass мюон моларна ма�а muon-neutron mass ratio мюон-неутрон отношение на ма�ите muon-proton magnetic moment ratio отношение на магнитните моменти на мюона и протона muon-proton mass ratio мюон-протон отношение на ма�ите muon-tau mass ratio мюон-тау отношение на ма�ите reduced muon Compton wavelength редуцирана комптънова дължина на вълната на мюона reduced tau Compton wavelength редуцирана комптънова дължина на вълната на тау tau Compton wavelength тау дължина на вълната на Комптън tau-electron mass ratio тау-електрон отношение на ма�ите tau mass тау ма�а tau mass energy equivalent тау енергиен еквивалент на ма�ата tau mass in u тау ма�а в u tau molar mass тау моларна ма�а tau-muon mass ratio тау-мюон отношение на ма�ите tau-neutron mass ratio тау-неутрон отношение на ма�ите tau-proton mass ratio тау-протон отношение на ма�ите proton charge to mass quotient протон отношение зар�д към ма�а proton Compton wavelength протон дължина на вълната на Комптън proton-electron mass ratio протон-електрон отношение на ма�ите proton g factor (gₚ) протон g-фактор (gₚ) proton gyromagnetic ratio (γₚ) протон жиромагнитно отношение (γₚ) proton gyromagnetic ratio in MHz/T протон жиромагнитно отношение в MHz/T proton magnetic moment (μₚ) протон магнитен момент (μₚ) proton magnetic moment to Bohr magneton ratio отношение на магнитни� момент на протона към магнетона на Бор proton magnetic moment to nuclear magneton ratio отношение на магнитни� момент на протона към �дрени� магнетон proton magnetic shielding correction протон корекци� за магнитно екраниране proton mass (mₚ) протон ма�а (mₚ) proton mass energy equivalent протон енергиен еквивалент на ма�ата proton mass energy equivalent in MeV протон енергиен еквивалент на ма�ата в MeV proton mass in u протон ма�а в u proton molar mass (Mₚ) протон моларна ма�а (Mₚ) proton-muon mass ratio протон-мюон отношение на ма�ите proton-neutron magnetic moment ratio отношение на магнитните моменти на протона и неутрона proton-neutron mass ratio протон-неутрон отношение на ма�ите proton relative atomic mass (Ar(p)) протон отно�ителна атомна ма�а (Ar(p)) proton rms charge radius протон �редноквадратичен радиу� на зар�да proton-tau mass ratio протон-тау отношение на ма�ите reduced proton Compton wavelength редуцирана комптънова дължина на вълната на протона shielded proton gyromagnetic ratio екраниран протон жиромагнитно отношение shielded proton gyromagnetic ratio in MHz/T екраниран протон жиромагнитно отношение в MHz/T shielded proton magnetic moment екраниран протон магнитен момент shielded proton magnetic moment to Bohr magneton ratio отношение на магнитни� момент на екранирани� протон към магнетона на Бор shielded proton magnetic moment to nuclear magneton ratio отношение на магнитни� момент на екранирани� протон към �дрени� магнетон neutron Compton wavelength неутрон дължина на вълната на Комптън neutron-electron magnetic moment ratio отношение на магнитните моменти на неутрона и електрона neutron-electron mass ratio неутрон-електрон отношение на ма�ите neutron g factor (gₙ) неутрон g-фактор (gₙ) neutron gyromagnetic ratio (γₙ) неутрон жиромагнитно отношение (γₙ) neutron gyromagnetic ratio in MHz/T неутрон жиромагнитно отношение в MHz/T neutron magnetic moment (μₙ) неутрон магнитен момент (μₙ) neutron magnetic moment to Bohr magneton ratio отношение на магнитни� момент на неутрона към магнетона на Бор neutron magnetic moment to nuclear magneton ratio отношение на магнитни� момент на неутрона към �дрени� магнетон neutron mass (mₙ) неутрон ма�а (mₙ) neutron mass energy equivalent неутрон енергиен еквивалент на ма�ата neutron mass energy equivalent in MeV неутрон енергиен еквивалент на ма�ата в MeV neutron mass in u неутрон ма�а в u neutron molar mass (Mₙ) неутрон моларна ма�а (Mₙ) neutron-muon mass ratio неутрон-мюон отношение на ма�ите neutron-proton magnetic moment ratio отношение на магнитните моменти на неутрона и протона neutron-proton mass difference неутрон-протон разлика в ма�ите neutron-proton mass difference energy equivalent неутрон-протон разлика в ма�ите енергиен еквивалент neutron-proton mass difference energy equivalent in MeV неутрон-протон разлика в ма�ите енергиен еквивалент в MeV neutron-proton mass difference in u неутрон-протон разлика в ма�ите в u neutron-proton mass ratio неутрон-протон отношение на ма�ите neutron relative atomic mass (Ar(n)) неутрон отно�ителна атомна ма�а (Ar(n)) neutron-tau mass ratio неутрон-тау отношение на ма�ите neutron to shielded proton magnetic moment ratio отношение на магнитни� момент на неутрона към този на екранирани� протон reduced neutron Compton wavelength редуцирана комптънова дължина на вълната на неутрона deuteron-electron magnetic moment ratio отношение на магнитните моменти на деутерона и електрона deuteron-electron mass ratio деутерон-електрон отношение на ма�ите deuteron g factor деутерон g-фактор deuteron magnetic moment деутерон магнитен момент deuteron magnetic moment to Bohr magneton ratio отношение на магнитни� момент на деутерона към магнетона на Бор deuteron magnetic moment to nuclear magneton ratio отношение на магнитни� момент на деутерона към �дрени� магнетон deuteron mass деутерон ма�а deuteron mass energy equivalent деутерон енергиен еквивалент на ма�ата deuteron mass energy equivalent in MeV деутерон енергиен еквивалент на ма�ата в MeV deuteron mass in u деутерон ма�а в u deuteron molar mass деутерон моларна ма�а deuteron-neutron magnetic moment ratio отношение на магнитните моменти на деутерона и неутрона deuteron-proton magnetic moment ratio отношение на магнитните моменти на деутерона и протона deuteron-proton mass ratio деутерон-протон отношение на ма�ите deuteron relative atomic mass (Ar(d)) деутерон отно�ителна атомна ма�а (Ar(d)) deuteron rms charge radius деутерон �редноквадратичен радиу� на зар�да triton-electron mass ratio тритон-електрон отношение на ма�ите triton g factor (gₜ) тритон g-фактор (gₜ) triton magnetic moment (μₜ) тритон магнитен момент (μₜ) triton magnetic moment to Bohr magneton ratio отношение на магнитни� момент на тритона към магнетона на Бор triton magnetic moment to nuclear magneton ratio отношение на магнитни� момент на тритона към �дрени� магнетон triton mass (mₜ) тритон ма�а (mₜ) triton mass energy equivalent тритон енергиен еквивалент на ма�ата triton mass energy equivalent in MeV тритон енергиен еквивалент на ма�ата в MeV triton mass in u тритон ма�а в u triton molar mass (Mₜ) тритон моларна ма�а (Mₜ) triton-proton mass ratio тритон-протон отношение на ма�ите triton relative atomic mass (Ar(t)) тритон отно�ителна атомна ма�а (Ar(t)) triton to proton magnetic moment ratio отношение на магнитни� момент на тритона към този на протона helion-electron mass ratio хелион-електрон отношение на ма�ите helion g factor (gₕ) хелион g-фактор (gₕ) helion magnetic moment (μₕ) хелион магнитен момент (μₕ) helion magnetic moment to Bohr magneton ratio отношение на магнитни� момент на хелиона към магнетона на Бор helion magnetic moment to nuclear magneton ratio отношение на магнитни� момент на хелиона към �дрени� магнетон helion mass (mₕ) хелион ма�а (mₕ) helion mass energy equivalent хелион енергиен еквивалент на ма�ата helion mass energy equivalent in MeV хелион енергиен еквивалент на ма�ата в MeV helion mass in u хелион ма�а в u helion molar mass (Mₕ) хелион моларна ма�а (Mₕ) helion-proton mass ratio хелион-протон отношение на ма�ите helion relative atomic mass (Ar(h)) хелион отно�ителна атомна ма�а (Ar(h)) helion shielding shift хелион отме�тване от екраниране shielded helion gyromagnetic ratio екраниран хелион жиромагнитно отношение shielded helion gyromagnetic ratio in MHz/T екраниран хелион жиромагнитно отношение в MHz/T shielded helion magnetic moment екраниран хелион магнитен момент shielded helion magnetic moment to Bohr magneton ratio отношение на магнитни� момент на екранирани� хелион към магнетона на Бор shielded helion magnetic moment to nuclear magneton ratio отношение на магнитни� момент на екранирани� хелион към �дрени� магнетон shielded helion to proton magnetic moment ratio отношение на магнитни� момент на екранирани� хелион към този на протона shielded helion to shielded proton magnetic moment ratio отношение на магнитни� момент на екранирани� хелион към този на екранирани� протон alpha particle mass алфа ча�тица ма�а alpha particle mass in u алфа ча�тица ма�а в u alpha particle mass energy equivalent алфа ча�тица енергиен еквивалент на ма�ата alpha particle mass energy equivalent in MeV алфа ча�тица енергиен еквивалент на ма�ата в MeV alpha particle-electron mass ratio алфа ча�тица-електрон отношение на ма�ите alpha particle-proton mass ratio алфа ча�тица-протон отношение на ма�ите alpha particle rms charge radius алфа ча�тица �редноквадратичен радиу� на зар�да alpha particle molar mass алфа ча�тица моларна ма�а alpha particle relative atomic mass (Ar(α)) алфа ча�тица отно�ителна атомна ма�а (Ar(α)) atomic mass constant (mᵤ) атомна кон�танта за ма�а (mᵤ) Avogadro constant кон�танта на �вогадро Boltzmann constant (k) кон�танта на Болцман (k) Boltzmann constant in eV/K кон�танта на Болцман в eV/K Boltzmann constant in Hz/K кон�танта на Болцман in Hz/K Boltzmann constant in inverse meter per kelvin кон�танта на Болцман in обратен метър на келвин electron volt (eV) електронволт (eV) Faraday constant (F) кон�танта на Фарадей (F) first radiation constant (c�) първа радиационна кон�танта (c�) first radiation constant for spectral radiance първа радиационна кон�танта for spectral radiance molar gas constant (R) моларна газова кон�танта (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) кон�танта на Лошмид (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) кон�танта на Лошмид (n₀, 273.15 K, 101.325 kPa) molar Planck constant molar кон�танта на Планк second radiation constant (c₂) втора радиационна кон�танта (c₂) Stefan-Boltzmann constant (σ) Stefan-кон�танта на Болцман (σ) lattice spacing of ideal Si (d₂₂₀) междурешетъчно раз�то�ние на идеален Si (d₂₂₀) atomic mass constant energy equivalent атомна кон�танта за ма�а енергиен еквивалент atomic mass constant energy equivalent in MeV атомна кон�танта за ма�а енергиен еквивалент в MeV atomic mass unit-electron volt relationship атомна единица за ма�а-електронволт зави�имо�т molar mass constant (Mᵤ) моларна ма�а constant (Mᵤ) molar mass of carbon-12 моларна ма�а на въглерод-12 molar volume of ideal gas (273.15 K, 100 kPa) моларен обем на идеален газ (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) моларен обем на идеален газ (273.15 K, 101.325 kPa) molar volume of silicon моларен обем на �илици� Sackur-Tetrode constant (1 K, 100 kPa) кон�танта на Сакур-Тетроде (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) кон�танта на Сакур-Тетроде (1 K, 101.325 kPa) Wien frequency displacement law constant кон�танта на закона на Вин за че�тотно отме�тване Wien wavelength displacement law constant кон�танта на закона на Вин за дължина на вълната standard atmosphere (atm) �тандартна атмо�фера (atm) standard-state pressure (p°) �тандартно нал�гане (p°) Angstrom star (Å*) анг�трьом-звезда (Å*) Copper x unit медна x-единица Molybdenum x unit молибденова x-единица atomic unit of magnetizability атомна единица за магнитизуемо�т atomic unit of mass (mₑ) атомна единица за ма�а (mₑ) atomic unit of momentum атомна единица за импул� atomic unit of permittivity атомна единица за електрична проницаемо�т atomic unit of time атомна единица за време atomic unit of velocity атомна единица за �коро�т hartree-hertz relationship hartree-херц зави�имо�т hartree-inverse meter relationship hartree-обратен метър зави�имо�т hartree-joule relationship hartree-джаул зави�имо�т hartree-kelvin relationship hartree-келвин зави�имо�т hartree-kilogram relationship hartree-килограм зави�имо�т shielding difference of d and p in HD разлика в екранирането на d и p в HD shielding difference of t and p in HT разлика в екранирането на t и p в HT pi (π) пи (π) Euler's number (e) чи�ло на Ойлер (e) golden ratio (φ) златно �ечение (φ) Euler-Mascheroni constant (γ) кон�танта на Ойлер-Ма�керони (γ) nominal solar radius номинален �лънчев радиу� nominal solar total irradiance номинално пълно �лънчево облъчване nominal solar luminosity номинална �лънчева �ветимо�т nominal solar effective temperature номинална ефективна температура на Слънцето nominal solar mass parameter номинален �лънчев ма�ов параметър nominal terrestrial equatorial radius номинален земен екваториален радиу� nominal terrestrial polar radius номинален земен пол�рен радиу� nominal terrestrial mass parameter номинален земен ма�ов параметър nominal jovian equatorial radius номинален юпитеров екваториален радиу� nominal jovian polar radius номинален юпитеров пол�рен радиу� nominal jovian mass parameter номинален юпитеров ма�ов параметър average value of one minus the rate of TCG relative to TCB �редна �тойно�т на едно мину� �коро�тта на TCG �пр�мо TCB solar mass parameter (TCB-compatible) �лънчев ма�ов параметър (�ъвме�тим � TCB) solar mass parameter (TDB-compatible) �лънчев ма�ов параметър (�ъвме�тим � TDB) equatorial radius of the Earth (TT-compatible) екваториален радиу� на Зем�та (�ъвме�тим � TT) dynamical form factor of the Earth динамичен форм-фактор на Зем�та time rate of change in the dynamical form factor of the Earth �коро�т на изменение на динамични� форм-фактор на Зем�та geocentric gravitational constant (TCB-compatible) геоцентрична гравитационна кон�танта (�ъвме�тима � TCB) geocentric gravitational constant (TT-compatible) геоцентрична гравитационна кон�танта (�ъвме�тима � TT) geocentric gravitational constant (TDB-compatible) геоцентрична гравитационна кон�танта (�ъвме�тима � TDB) potential of the geoid потенциал на геоида nominal mean angular velocity of the Earth (TT-compatible) номинална �редна ъглова �коро�т на Зем�та (�ъвме�тима � TT) ratio mass of the Moon to the Earth отношение на ма�ата на Луната към ма�ата на Зем�та ratio of the mass of the Sun to Mercury отношение на ма�ата на Слънцето към ма�ата на Меркурий ratio of the mass of the Sun to Venus отношение на ма�ата на Слънцето към ма�ата на Венера ratio of the mass of the Sun to Mars отношение на ма�ата на Слънцето към ма�ата на Мар� ratio of the mass of the Sun to Jupiter отношение на ма�ата на Слънцето към ма�ата на Юпитер ratio of the mass of the Sun to Saturn отношение на ма�ата на Слънцето към ма�ата на Сатурн ratio of the mass of the Sun to Uranus отношение на ма�ата на Слънцето към ма�ата на Уран ratio of the mass of the Sun to Neptune отношение на ма�ата на Слънцето към ма�ата на �ептун ratio of the mass of the Sun to (134340) Pluto отношение на ма�ата на Слънцето към ма�ата на (134340) Плутон ratio of the mass of the Sun to (136199) Eris отношение на ма�ата на Слънцето към ма�ата на (136199) Ерида ratio of the mass of (1) Ceres to the Sun отношение на ма�ата на (1) Церера към ма�ата на Слънцето ratio of the mass of (2) Pallas to the Sun отношение на ма�ата на (2) Пала� към ма�ата на Слънцето ratio of the mass of (4) Vesta to the Sun отношение на ма�ата на (4) Ве�та към ма�ата на Слънцето mean obliquity of the ecliptic at J2000.0 �реден наклон на еклиптиката при J2000.0 Electromagnetic Електромагнитно Compton wavelength комптънова дължина на вълната Astronomy ��трономи� ConstantsWidget Domain Обла�т Subdomain Подобла�т No match found ��ма �ъвпадени� Name �аименование Value Стойно�т Unit Мерна единица Search Тър�и All В�ички CustomKeypadDialog Custom Keypad Потребител�ка клавиатура Rows: Редове: Columns: Колони: Copy preset: Копиране на шаблон: Basic О�новна Scientific (wide) �аучна (широка) Scientific (narrow) �аучна (т��на) Apply Прилагане Row Ред Column Колона Label Етикет Behavior Поведение Text Тек�т DiagnosticsDialog App Diagnostics Диагно�тика на приложението Copy to Clipboard Копиране в клипборда Editor Unit Мерна единица User unit Потребител�ка единица User function Ръчно-дефинирана функци� Argument �ргумент Current result:<br/>%1 Текущ резултат:<br/>%1 Selection result:<br/>%1 Резултат от избраното:<br/>%1 Selection result: n/a Резултат от избраното: н�ма Selection result: %1 Резултат от избраното: %1 second �екунда metre метър kilogram килограм mole мол radian радиан steradian �терадиан degree Celsius граду� Целзий cubic metre кубичен метър cubic millimetre кубичен милиметър cubic centimetre кубичен �антиметър cubic decimetre кубичен дециметър cubic kilometre кубичен километър square millimetre квадратен милиметър square kilometre квадратен километър square metre квадратен метър minute минута hour ча� day ден astronomical unit а�трономиче�ка единица degree граду� arcminute ъглова минута arcsecond ъглова �екунда milliarcsecond милиъглова �екунда microarcsecond микроъглова �екунда hectare хектар litre литър tonne тон Dalton далтон electronvolt електронволт Angstrom анг�трьом atmosphere атмо�фера atomic mass unit атомна единица за ма�а British thermal unit британ�ка термична единица calorie калори� carat карат cup чаша cup (Imperial) чаша (импер�ка) cup (Japanese) чаша (�пон�ка) cup (US) чаша (С�Щ) degree Fahrenheit граду� Фаренхайт fathom фатъм fluid ounce (Imperial) течна унци� (импер�ка) fluid ounce (US) течна унци� (С�Щ) fluid dram (Imperial) течен драм (импер�ки) fluid dram (US) течен драм (С�Щ) foot фут square foot квадратен фут cubic foot кубичен фут gallon (Imperial) галон (импер�ки) gallon (US) галон (С�Щ) gill (Imperial) гил (импер�ки) gill (US) гил (С�Щ) gradian град grain грейн gram грам Hartley хартли Hartree energy unit единица енерги� на Хартри horsepower кон�ка �ила inch инч square inch квадратен инч cubic inch кубичен инч karat карат knot възел lightminute �ветлинна минута lightsecond �ветлинна �екунда lightyear �ветлинна година long ton дълъг тон mile мил� square mile квадратна мил� cubic mile кубична мил� mile per hour мил� в ча� kilometre per hour километър в ча� nautical mile мор�ка мил� ounce унци� parsec пар�ек pint (Imperial) пинта (импер�ка) pint (US) пинта (С�Щ) pound паунд pounds per square inch паундове на квадратен инч quart (Imperial) кварта (импер�ка) quart (US) кварта (С�Щ) oil barrel петролен барел beer barrel (US) бирен барел (С�Щ) square yard квадратен �рд cubic yard кубичен �рд short ton къ� тон tablespoon �упена лъжица tablespoon (Australian) �упена лъжица (ав�тралий�ка) tablespoon (Imperial) �упена лъжица (импер�ка) tablespoon (US) �упена лъжица (С�Щ) dessert spoon де�ертна лъжица teaspoon чаена лъжица teaspoon (Imperial) чаена лъжица (импер�ка) teaspoon (US) чаена лъжица (С�Щ) turn оборот revolution завъртане revolution per minute обороти в минута week �едмица kilowatt hour киловатча� millimetre of mercury милиметър живачен �тълб yard �рд Julian century юлиан�ки век Julian year юлиан�ка година sidereal year звездна година tropical year тропична година Evaluator invalid expression �еправилен израз division by zero деление на нула too time consuming - computation was rejected отнема прекалено много време - изчи�лението е отхвърлено dimension mismatch - quantities with different dimensions cannot be compared, added, etc. не�ъответ�твие в мерните единици – количе�тва � различни величини не могат да �е �равн�ват, �ъбират и т.н. invalid dimension - operation might require dimensionless arguments грешна мерна единица – операци�та може би изи�ква безразмерен аргумент Computation aborted - encountered numerical instability Изчи�лението прекратено - открита е чи�лена не�табилно�т invalid dimension - function might require dimensionless arguments грешна мерна единица – функци�та изи�ква безразмерен аргумент error грешка unit must not be zero мерната единица не тр�бва да е нула Conversion failed - dimension mismatch Преобразуването неу�пешно – не�ъвме�тими мерни единици unknown function or variable непозната функци� или променлива recursion not supported не �е поддържа рекур�и� cannot operate on a NaN не �е поддържат операции върху нечи�лени �тойно�ти underflow - tiny result is out of SpeedCrunch's number range извън долната граница – твърде малък резултат извън диапазона на SpeedCrunch overflow - huge result is out of SpeedCrunch's number range извън горната граница – твърде гол�м резултат извън диапазона на SpeedCrunch overflow - logic result exceeds maximum of 256 bits извън горната граница – логиче�ка �тойно�т надхвърл� мак�имума от 256 бита overflow - integer result exceeds maximum limit for integers извън горната граница – целочи�лена �тойно�т надхвърл� мак�имални�т лимит за цели чи�ла operation is not defined for these arguments операци�та не е дефинирана за тези аргументи wrong number of arguments грешен брой аргументи does not take NaN as an argument нечи�лени �тойно�ти не �е приемат за аргументи result out of range резултат извън диапазона undefined for argument domain недефиниран обхват на аргумент computation too expensive твърде трудно за пре�м�тане internal error, please report a bug вътрешна грешка, мол� докладвайте syntax error �интактична грешка conversion target must be a unit целта за преобразуване тр�бва да бъде мерна единица unknown unit неизве�тна единица %1 is a reserved name, please choose another %1 е запазено, мол� изберете друго наименование %1 is a global user definition and cannot be overridden in this session. %1 е глобална потребител�ка дефиници� и не може да бъде презапи�ана в тази �е�и�. %1 is a variable name, please choose another or delete the variable %1 е име на променлива, мол� по�очете друго наименование или изтрийте променливата argument %1 is used more than once %1 �е използва повече от веднъж като аргумент %1 is a built-in unit name, please choose another %1 е име на вградена мерна единица, мол� изберете друго %1 is a user function name, please choose another or delete the function %1 е ръчно-дефинирана функци�, мол� по�очете друго наименование или изтрийте функци�та FunctionRepo max; trials; probability мак�имум; опити; веро�тно�т trials; probability опити; веро�тно�т hits; trials; probability удари; опити; веро�тно�т max; total; hits; trials мак�имум; общо; удари, опити total; hits; trials общо; удари; опити count; total; hits; trials брой; общо; удари; опити dividend; divisor делимо; делител x; exponent_bits; significand_bits [; exponent_bias] x; битове_ек�понента; битове_манти�а [; отме�тване_ек�понента] base; x о�нова; x value; modulo �тойно�т; модул base; exponent; modulo о�нова; ек�понента; модул events; average_events �ъбити�; �редно_�ъбити� average_events �редно_�ъбити� x [; precision] x [; точно�т] Absolute Value �б�олютна �тойно�т Absolute Deviation �б�олютно отклонение Arc Cosine �рку�ко�ину� Logical AND Логиче�ко И Area Hyperbolic Cosine �ркко�ину� хиперболичен Area Hyperbolic Sine �рк�ину� хиперболичен Area Hyperbolic Tangent �рктанген� хиперболичен Arc Sine �рку��ину� Arc Tangent �рку�танген� Arc Tangent with two Arguments �рку�танген� � два аргумента Average (Arithmetic Mean) О�редн�ване (Средно аритметично) Binomial Cumulative Distribution Function Биномиална кумулативна функци� на разпределение Binomial Distribution Mean Средна �тойно�т на биномиално разпределение Binomial Probability Mass Function Биномиална функци� на веро�тно�тната ма�а Binomial Distribution Variance Ди�пер�и� на биномиално разпределение Cube Root Кубичен корен Complex Conjugate Комплек�но �прегнато Cosine Ко�ину� Hyperbolic Cosine Хиперболичен Ко�ину� Cotangent Котанген� Cosecant Ко�екант Convert Unix timestamp to Date Преобразуване на Unix времеви отпечатък в дата Degrees of Arc Граду�и на арка Error Function Функци� на грешката Complementary Error Function Допълнителна функци� на грешката Exponential Ек�поненциал Fractional Part Дробна ча�т Extension of Factorials [= (x-1)!] Разширение на факториелите [= (x-1)!] Greatest Common Divisor �ай-гол�м общ делител Geometric Mean Геометрична �редна Gradians of arc Гради на арка Hypergeometric Cumulative Distribution Function Хипергеометрична кумулативна функци� на разпределение Hypergeometric Distribution Mean Средна �тойно�т на хипергеометрично разпределение Hypergeometric Probability Mass Function Хипергеометрична функци� на веро�тно�тната ма�а Hypergeometric Distribution Variance Ди�пер�и� на хипергеометрично разпределение Integer Quotient Целочи�лено ча�тно Integer Part Ц�ла ча�т Imaginary Part Имагинерна ча�т Decode IEEE-754 Binary Value Декодиране на IEEE-754 двоична �тойно�т Encode IEEE-754 Binary Value Кодиране на IEEE-754 двоична �тойно�т Decode 16-bit Half-Precision Value Декодиране на 16-битова половин точно�т Encode 16-bit Half-Precision Value Кодиране на 16-битова половин точно�т Decode 32-bit Single-Precision Value Декодиране на 32-битова единична точно�т Encode 32-bit Single-Precision Value Кодиране на 32-битова единична точно�т Decode 64-bit Double-Precision Value Декодиране на 64-битова двойна точно�т Encode 64-bit Double-Precision Value Кодиране на 64-битова двойна точно�т Decode 128-bit Quad-Precision Value Декодиране на 128-битова четворна точно�т Encode 128-bit Quad-Precision Value Кодиране на 128-битова четворна точно�т Binary Logarithm Двоичен логаритъм Common Logarithm Де�етичен логаритъм Natural Logarithm Е�те�твен логаритъм Logarithm to Arbitrary Base Логаритъм � о�нова Mask to a bit size Ма�киране до битова ширина Maximum Мак�имум Median Value (50th Percentile) Медиана (50-и пер�ентил) Minimum Минимум Modulo О�татък Euclidean Modulo Евклидов модул Modular Exponentiation Модулно �тепенуване Combination (Binomial Coefficient) Комбинаци� (биномиален коефициент) Logical NOT Логиче�ко �Е Permutation (Arrangement) Пермутаци� (Подреждане) Convert to Binary Representation Преобразуване в двоично пред�тав�не Arithmetic �ритметика Chemistry Хими� Complex Комплек�ни чи�ла Combinatorics Комбинаторика Probability Веро�тно�ти Statistics Стати�тика Aggregation �грегиране Random Случайни Base conversion Преобразуване на о�нова Number formatting Форматиране на чи�ла Integer arithmetic Целочи�лена аритметика Special functions Специални функции Exponential & Logarithmic Ек�поненциални и логаритмични Angle conversion Преобразуване на ъгли Trigonometry Тригонометри� Bitwise Побитови Floating point Плаваща запета� Date & Time Дата и ча� Linear algebra Линейна алгебра unix_timestamp; x hours offset to GMT unix_timestamp; отме�тване x ча�а �пр�мо GMT yyyymmdd.hhmmss; x hours offset to GMT ггггммдд.ччмм��; отме�тване x ча�а �пр�мо GMT [digits] [цифри] max [; min] мак�. [; мин.] List Literal Спи�ъчен литерал Convert to Padded Binary Representation Преобразуване към допълнено двоично пред�тав�не Round Toward +∞ (Ceiling) Закръгл�ване към +∞ (таван) Cosine plus Imaginary Sine Ко�ину� плю� имагинерен �ину� Convert to Cis Complex Form Преобразуване към комплек�на форма cis Matrix Column Count Брой колони на матрица Population Correlation Matrix (n) Корелационна матрица на �ъвкупно�т (n) Sample Correlation Matrix (n-1) Корелационна матрица на извадка (n-1) Count Брой Population Covariance Matrix (n) Ковариационна матрица на �ъвкупно�т (n) Sample Covariance Matrix (n-1) Ковариационна матрица на извадка (n-1) Cross Product Векторно произведение Convert Date to Unix timestamp Преобразуване на дата към Unix времеви печат Convert to Decimal Representation Преобразуване в де�етично пред�тав�не Determinant Детерминанта Convert to Sexagesimal Notation Преобразуване към шей�етична нотаци� Dot Product Скаларно произведение Convert to Engineering Notation Преобразуване към инженерна нотаци� Convert to Exponential Complex Form Преобразуване към ек�поненциална комплек�на форма Round Toward −∞ (Floor) Закръгл�ване към −∞ (под) Flatten Matrix Спле�кване на матрица Least Common Multiple �ай-малко общо кратно Convert to Hexadecimal Representation Преобразуване в ше�тнаде�етично пред�тав�не Convert to Padded Hexadecimal Representation Преобразуване в допълнено ше�тнаде�етично пред�тав�не Inverse Matrix Обратна матрица Round to 16-bit Half-Precision Value Закръгл�ване до 16-битова �тойно�т � половин точно�т Round to 32-bit Single-Precision Value Закръгл�ване до 32-битова �тойно�т � единична точно�т Round to 64-bit Double-Precision Value Закръгл�ване до 64-битова �тойно�т � двойна точно�т Round to 128-bit Quad-Precision Value Закръгл�ване до 128-битова �тойно�т � четворна точно�т Residual from 16-bit Half-Precision Rounding О�татък от 16-битово закръгл�ване � половин точно�т Residual from 32-bit Single-Precision Rounding О�татък от 32-битово закръгл�ване � единична точно�т Residual from 64-bit Double-Precision Rounding О�татък от 64-битово закръгл�ване � двойна точно�т Residual from 128-bit Quad-Precision Rounding О�татък от 128-битово закръгл�ване � четворна точно�т Substance Mass Ма�а на веще�твото Molarity Моларно�т Molar Mass Моларна ма�а Median Absolute Deviation Медианно аб�олютно отклонение Mean Средна �тойно�т Numerical Value of Quantity Чи�лена �тойно�т на величина Random Decimal Number Случайно де�етично чи�ло Random Integer Number Случайно ц�ло чи�ло Convert to Rational Representation Преобразуване към рационално пред�тав�не Convert to Octal Representation Преобразуване в о�мично пред�тав�не Convert to Padded Octal Representation Преобразуване в допълнено о�мично пред�тав�не Vector or Matrix Norm �орма на вектор или матрица Logical OR Логиче�ко ИЛИ Population Count (Hamming Weight) Брой единични битове (тегло на Хаминг) Phase of Complex Number Фаза на комплек�но чи�ло Poissonian Cumulative Distribution Function Поа�онова кумулативна функци� на разпределение Poissonian Distribution Mean Средна �тойно�т на Поа�оново разпределение Poissonian Probability Mass Function Поа�онова функци� на веро�тно�тната ма�а Poissonian Distribution Variance Ди�пер�и� на Поа�оново разпределение Convert to Phasor Complex Form Преобразуване във фазорна комплек�на форма Convert to Rectangular Complex Form Преобразуване към правоъгълна комплек�на форма Round Half Away from Zero Закръгл�ване на половината от нулата Round Half Even Закръгл�ване на половината към четно Nth Root Корен от n-та �тепен Convert to Scientific Notation Преобразуване към научна нотаци� Matrix Row Count Брой редове на матрица List or Matrix Shape Форма на �пи�ък или матрица Summation Сумиране Population Standard Deviation (n) Стандартно отклонение на �ъвкупно�т (n) Sample Standard Deviation (n-1) Стандартно отклонение на извадка (n-1) Round Toward Zero (Truncation) Закръгл�ване към нула (отр�зване) Matrix Trace Следа на матрица Transpose Matrix Тран�пониране на матрица Population Variance (n) Ди�пер�и� на �ъвкупно�т (n) Sample Variance (n-1) Ди�пер�и� на извадка (n-1) Product Произведение Radians Радиани Matrix Rank Ранг на матрица Real Part Реална ча�т Secant Секант Arithmetic Shift Left �ритметично изме�тване нал�во Arithmetic Shift Right �ритметично изме�тване над��но Signum Сигнум Sine Сину� Hyperbolic Sine Хиперболичен �ину� Square Root Корен квадратен Sum Сума Tangent Танген� Convert to Trigonometric Complex Form Преобразуване в тригонометрична комплек�на форма Turns Обороти Hyperbolic Tangent Хиперболичен танген� Sign-extend a value Разшир�ване на знак на �тойно�т Logical XOR Логиче�ко изключващо ИЛИ FunctionsWidget Domain Обла�т All В�ички Name �аименование Search Тър�ене No match found ��ма �ъвпадени� Identifier Идентификатор HistoryWidget Remove All Calculations Above Премахване на в�ички изчи�лени� по-горе Remove This Calculation Премахни това изчи�ление Remove All Calculations Below Премахване на в�ички изчи�лени� по-долу Keypad Inverse cosine Обратен ко�ину� The last result По�ледни�т резултат Inverse sine Обратен �ину� Inverse tangent Обратен танген� Evaluate expression Изчи�л�ване на израз Division Деление Multiplication Умножение Subtraction Изваждане Addition Събиране Clear expression Изтрий израза Cosine Ко�ину� Backspace Backspace Scientific notation �аучен формат Exponential Ек�поненциално Factorial Факториел Natural logarithm Е�те�твен логаритъм Left parenthesis Л�ва �коба Nth root Корен от n-та �тепен Argument separator Разделител на аргументи Square Квадрат Common logarithm Де�етичен логаритъм Modulo О�татък Contextual percentage Контек�тен процент Power Степенуване Right parenthesis Д��на �коба Sine Сину� Square root Корен квадратен Tangent Танген� Pi Пи Decimal separator Де�етичен разделител MainWindow Radian Радиан Degree Граду� Gradian Град Binary Двоичен Octal О�мична Hexadecimal Ше�тнаде�етична Sexagesimal Шей�етична Engineering decimal Инженерна де�етична Scientific decimal �аучна де�етична &Import... &Импортиране... &Quit &Излизане Clear E&xpression Изчи�ти &израза Clear &History Изчи�ти &И�тори�та &Copy &Копиране &Paste &По�тав�не &Select Expression &Избери израз &Constants &Кон�танти &Functions &Функции &History &И�тори� &Status Bar &Стату� лента Bitfield Битово поле Use&r Functions &Ръчно-дефинирани функции &Degree &Граду�и &Radian &Радиани &Gradian &Гради Re&volution &Завъртане Auto-Insert a&ns �втоматично вмъкване на a&ns Automatic &Completion �втоматично &завършване &Built-in Functions &Вградени функции Built-in &Variables В&градени променливи User &Functions &Ръчно-дефинирани функции User Va&riables &Потребител�ки променливи Open a Private Tab on Startup Отвар�не на ча�тен раздел при �тартиране Open and focus a new private tab whenever SpeedCrunch starts. Отвар�не и фоку�иране на нов ча�тен раздел при в��ко �тартиране на SpeedCrunch. Syntax &Highlighting &Оцвет�ване на изразите Group Digits in &Input &Групиране на цифрите при въвеждане Automatic Input &Adjustments &�втоматични корекции на входа Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. �втоматично коригиране на операторите, интервалите, �кобите и �тепените и ограничаване на входа до валидни знаци. Group input digits using the selected number format. Групиране на въведените цифри �поред избрани� чи�лов формат. &Blinking Cursor &Мигащ кур�ор Blink the cursor in the expression editor. Мигане на кур�ора в редактора на изрази. &Escape Clears Editor &Escape изчи�тва редактора Clear the focused expression editor with Escape after dismissing any popup or preview. Изчи�тване на активни� редактор на изрази � Escape �лед затвар�не на из�качащите прозорци или визуализации. Keep Expression After Evaluation Запазване на израза �лед изчи�л�ване Copy New Results Automatically �втоматично копиране на новите резултати &Comma &Де�етична Запета� &System Default &Си�темно подразбиране &Dot &Де�етична точка Dot &And Comma Точка &и запета� Toward +∞ (&ceil) Към +∞ (&ceil) Toward −∞ (&floor) Към −∞ (&floor) &Binary &Бинарна &Engineering &Инженерен &Hexadecimal &Ше�тнаде�етична &Octal &О�мична &Scientific &�аучен User &Manual �аръчник Issues and &Feedback &Проблеми и отзиви &Donate &Дари &About SpeedCrunch О&тно�но SpeedCrunch App Diag&nostics Д&иагно�тика на приложението S&plit Р&аздел�не Angle &Mode &Ъглов режим &Complex Form &Комплек�на форма New Tab �ов раздел Constants Кон�танти Functions Функции History И�тори� User Functions Ръчно-дефинирани функции &Font... &Шрифт &Language... &Език... &Session &Се�и� &Edit &Редактиране &View &Изглед Se&ttings &Свой�тва &Decimal &Де�етичен &Keypad &Цифрова клавиатура Always on &Top Винаги най-отгоре Disabled Изключен Small Space Малко раз�то�ние Medium Space Средно раз�то�ние Large Space Гол�мо раз�то�ние &0 Digits &0 Цифри &15 Digits &15 Цифри &2 Digits &2 Цифри &3 Digits &3 Цифри &50 Digits &50 Цифри &8 Digits &8 Цифри &Sexagesimal &Шей�етична Reset All Settings... �улиране на в�ички на�тройки... &System &Си�тема SpeedCrunch &Theme &Тема на SpeedCrunch &Classic &Кла�иче�ки &Modern М&одерен Context Help Контек�тна помощ &Help &Помощ Error Грешка Can't read from file %1 �е може �е прочете от файл %1 Import Session Импортирай �е�и� Close Session Затвар�не на �е�и� Angle Mode: Ъглов режим: Notation: �отаци�: Precision: Точно�т: Turn Оборот Revolution Завъртане Fixed-point decimal Де�етичен � фик�ирана запета� Rational Рационален Automatic decimal �втоматичен де�етичен Automatic �втоматично User &Definitions... Потребител�ки &дефиниции... New &Tab �ов &раздел New &Private Tab &�ов ча�тен раздел Keep Запазване Make Private... Преобразуване в ча�тна... New &Window �ов &прозорец &Open... &Отвар�не... &Rename... Преи&менуване... Clo&ne... &Клониране... &Close Tab &Затвар�не на раздела Reopen Clo&sed Tab По&вторно отвар�не на затворени� раздел Open Sessions &Folder Отвар�не на &папка �ъ� �е�ии &Undo &Отм�на &Redo &Въз�танов�ване Cu&t И&зр�зване Copy &Last Result Копи&ране на по�ледни� резултат &Wrap in Parentheses О&граждане �ъ� �коби Full Scr&een Mode Ре&жим на ц�л екран &Basic &О�новна &Scientific (wide) &�аучна (широка) Scientific (narrow) �аучна (т��на) &Custom... &Потребител�ки... Main &Menu Главно &меню User &Variables Потребител�ки &променливи &Left &�ал�во &Right �&ад��но &Up �а&горе &Down �а&долу Close Pa&ne &Затвар�не на панела User &Units Потребител�ки &единици &Turn &Оборот If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. �ко нов израз започва � +, -, * или /, SpeedCrunch първо вмъква "ans". &Accept with Enter Пр&иемане � Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Приемане на текущото предложение за автоматично довършване � Enter, без предварително избиране � клавишите �ъ� �трелки. &Units &Единици Show Live Result &Preview Показване на &предварителен преглед на резултата Save &Window Position on Exit Запазване на позици�та на &прозореца при изход Hover Highlighting Откро�ване при по�очване Group Integer Part Only Групиране �амо на ц�лата ча�т Number Format... Формат на чи�лата... Notation && Precision... �отаци� и точно�т... After pressing Enter, keep the entered expression selected in the editor. След нати�кане на Enter въведени�т израз о�тава избран в редактора. Never �икога Always Винаги Only for Single-Line Expressions Само за едноредови изрази Simplify Displayed Expressions Опро�т�ване на показваните изрази History Size &Limit... &Ограничение на размера на и�тори�та... Remove Trailing &Zeroes П&ремахване на крайните нули Nearest, Half &Away (round) �ай-близко, половината &навън (round) Nearest, Half &Even (roundeven) �ай-близко, половината &четно (roundeven) Toward &Zero (trunc) Към &нула (trunc) &Fixed-Point &Фик�ирана запета� &Rational &Рационален &Exponential (m·s�¹) &Ек�поненциална (m·s�¹) &Fractional (m/s) &Дробна (m/s) &Rectangular (a + bi) &Правоъгълна (a + bi) Exponential (re�ᶿ) Ек�поненциална (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Тригонометрична (r(cos θ + i·sin θ)) Phasor (r∠θ) Фазорна (r∠θ) &Theme... &Тема... Check for &Updates Проверка за &обновлени� Source Code Изходен код &Zoom &Мащаб &Results &Резултати Unit Notation �отаци� на единиците Rounding Mode Режим на закръгл�ване &Notation &�отаци� &Imaginary Unit &Имагинерна единица &Window &Прозорец &Editing &Редактиране A&utocomplete A&втодовършване Up/Down Arrow History И�тори� �ъ� �трелки нагоре/надолу &Appearance &Външен вид &Menus &Менюта &Docks &Прикрепващи �е панели &Input and Results &Вход и резултати &Disabled &Изключено &Disable &Изключване Close preview Затвар�не на прегледа Rename... Преименуване... Clone... Клониране... Close Tab Затвар�не на раздела New Private Tab �ов ча�тен раздел Open... Отвар�не... Reopen Closed Tab Повторно отвар�не на затворени� раздел Split Раздел�не Left �ал�во Right �ад��но Up �агоре Down �адолу Clear Изчи�тване Delete Изтриване %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Ча�тна �е�и�: �ъдържанието �е изхвърл� при затвар�не. Изберете Се�и� > Запазване, за да � превърнете в обикновена �е�и�. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Ча�тна] Reset All Settings �улиране на в�ички на�тройки Reset all settings to their default values? Да �е въз�танов�т ли �тандартните �тойно�ти на в�ички на�тройки? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Това включва външни� вид, редактирането, форматите на резултатите и предпочитани�та за прозорците. Изчи�лени�та, отворените �е�ии и потребител�ките дефиниции ще бъдат запазени. The settings file could not be written. Файлът � на�тройките не може да бъде запи�ан. Clear this session's calculations, unfinished expression, variables, functions, and units? Да �е изчи�т�т ли изчи�лени�та, недовършени�т израз, променливите, функциите и единиците в тази �е�и�? Global user definitions are kept. Глобалните потребител�ки дефиниции �е запазват. Make Session Private Преобразуване на �е�и�та в ча�тна The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Запазената �е�и� %1 ще бъде изтрита. Съдържанието � ще о�тане отворено в ча�тна �е�и� и ще бъде изхвърлено при затвар�не на �е�и�та или изход от SpeedCrunch. Make Private Преобразуване в ча�тна Could not delete the saved session %1. Запазената �е�и� %1 не може да бъде изтрита. Keep Session Запазване на �е�и�та Could not save the session. It remains private. Се�и�та не може да бъде запазена. Т� о�тава ча�тна. Clone Session Клониране на �е�и�та Could not save session file %1. Файлът на �е�и�та %1 не може да бъде запи�ан. Could not delete session file %1. Файлът на �е�и�та %1 не може да бъде изтрит. JSON file (*.json);;Any file (*.*) JSON файл (*.json);;В�еки файл (*.*) Export session as JSON Ек�портиране на �е�и�та като JSON The selected file is not valid JSON: %1 Избрани�т файл не е валиден JSON: %1 The selected file is not a SpeedCrunch session JSON file. Избрани�т файл не е JSON файл на �е�и� на SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Този файл използва о�тар�л формат на �е�и� на SpeedCrunch и не може да бъде импортиран. The selected JSON file is missing the required $schema field. В избрани� JSON файл лип�ва задължителното поле $schema. The selected JSON file uses an unsupported JSON schema: %1 Избрани�т JSON файл използва неподдържана JSON �хема: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). В избрани� JSON файл лип�ва идентификаторът на �хемата на �е�и�та на SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Избрани�т JSON файл използва неподдържан формат на �е�и� на SpeedCrunch: %1 The selected JSON file is missing the required session name. В избрани� JSON файл лип�ва задължителното име на �е�и�та. The selected JSON file has an empty session name. Избрани�т JSON файл има празно име на �е�и�. The selected JSON file has invalid or incomplete SpeedCrunch session data. Избрани�т JSON файл �ъдържа невалидни или непълни данни за �е�и� на SpeedCrunch. Open Sessions Folder Отвар�не на папката �ъ� �е�ии Could not create the sessions folder: %1 Папката �ъ� �е�ии не можа да бъде �ъздадена: %1 Could not open the sessions folder: %1 Папката �ъ� �е�ии не можа да бъде отворена: %1 Editor and Results Font Шрифт на редактора и резултатите Open Session Отвар�не на �е�и� Community Общно�т Rename Session Преименуване на �е�и� Clear Session Изчи�тване на �е�и� Delete Session Изтриване на �е�и� Close Pane Затвар�не на панела User Variables Потребител�ки променливи User Units Потребител�ки единици Clear History Изчи�тване на и�тори�та Are you sure you want to clear the calculation history? Сигурни ли �те, че и�кате да изчи�тите и�тори�та на изчи�лени�та? Session name: Име на �е�и�та: A session named %1 already exists. Вече �ъще�твува �е�и� � име %1. Could not create session file %1. �е може да �е �ъздаде файлът на �е�и�та %1. Could not write session file %1. �е може да �е запише файлът на �е�и�та %1. Are you sure you want to delete this session? Сигурни ли �те, че и�кате да изтриете тази �е�и�? Custom Precision Потребител�ка точно�т Fractional digits: Дробни цифри: Theme Тема Light Themes Светли теми Dark Themes Тъмни теми Preview Преглед Colors Цветове Select color for %1 Избор на цв�т за %1 Import... Импортиране... Export... Ек�портиране... Import Theme Импортиране на тема Theme file (*.json);;All files (*) Файл на тема (*.json);;В�ички файлове (*) Invalid theme file. �евалиден файл на тема. Can't import theme "%1" because it conflicts with a built-in theme. Темата "%1" не може да �е импортира, защото е в конфликт � вградена тема. Can't find a writable theme folder. �е може да �е намери папка за теми � право на запи�. Overwrite Theme Презапи�ване на тема A custom theme named "%1" already exists. Do you want to overwrite it? Вече �ъще�твува потребител�ка тема � име "%1". И�кате ли да � презапишете? Can't overwrite theme file %1 Файлът на темата %1 не може да �е презапише Can't copy theme file to %1 Файлът на темата не може да �е копира в %1 Export Theme Ек�портиране на тема Can't export theme as "%1" because it conflicts with a built-in theme. Темата не може да �е ек�портира като "%1", защото е в конфликт � вградена тема. Can't write to file %1 �е може да �е запише във файл %1 Global User Variable Глобална потребител�ка променлива Global User Function Глобална потребител�ка функци� Global User Unit Глобална потребител�ка единица User Definitions Потребител�ки дефиниции These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Тези дефиниции �а глобални и �е зареждат във в��ка �е�и�. Те не могат да �е промен�т в �е�иите и имат предим�тво пред дефинициите �ъ� �ъщото име от редактора на �е�и�та. Въвеждайте по една дефиници� на ред. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Примери: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Прилагане Validate Проверка Test Results Резултати от проверката Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Импортирани променливи: %1 Импортирани функции: %2 Импортирани единици: %3 �омера на редовете � грешки: %4 none н�ма Apply Results Резултати от прилагането User definitions saved. Потребител�ките дефиниции �а запазени. History Size Limit Ограничение на размера на и�тори�та Maximum number of history entries for this session (0 = unlimited): Мак�имален брой запи�и в и�тори�та за тази �е�и� (0 = без ограничение): Text file (*.txt);;Any file (*.*) Тек�тов файл (*.txt);;В�еки файл (*.*) Could not recalculate from calculation %1: %2 �е може да �е преизчи�ли от изчи�ление %1: %2 History Size Limit Reached До�тигнато е ограничението на размера на и�тори�та This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Това изчи�ление запълва по�ледното �вободно м��то в и�тори�та. Следващите изчи�лени� ще премахват най-�тарото изчи�ление от и�тори�та. Можете да увеличите ограничението от Се�и� > Ограничение на размера на и�тори�та. Editing calculation. Press Esc twice to cancel. Редактиране на изчи�ление. �ати�нете Esc два пъти за отказ. Calculation Settings �а�тройки на изчи�лението Invalid recalculation start index �евалиден начален индек� за преизчи�л�ване System Default Си�темно по подразбиране Language Език Select the language: Избери език: Custom Потребител�ки Decimal places: Де�етични знаци: &Automatic &�втоматично &Precision &Точно�т Plain &text Обикновен &тек�т Formula &Book Книга � &формули &Export &Ек�портиране Export session as HTML Ек�портиране на �е�и�та като HTML HTML file (*.html) HTML файл (*.html) Export session as plain text Ек�портиране на �е�и�та като обикновен тек�т ManualWindow SpeedCrunch Manual SpeedCrunch наръчник %1 - SpeedCrunch Manual %1 - SpeedCrunch наръчник NumberFormatDialog Number Format Формат на чи�лата <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Изберете чи�лови� формат за резултатите и групирането на въведените цифри.</b><br/><br/>Забележка: при въвеждане на чи�ла �е приемат недву�ми�лени формати, дори когато �е различават от избрани� формат за показване.<br/> QObject Global User Variable Глобална потребител�ка променлива Global User Function Глобална потребител�ка функци� Global User Unit Глобална потребител�ка единица Backspace Backspace Clear expression Изтрий израза Evaluate expression Изчи�л�ване на израз Insert text Вмъкване на тек�т Automatic decimal �втоматичен де�етичен Fixed-point decimal Де�етичен � фик�ирана запета� Engineering decimal Инженерна де�етична Scientific decimal �аучна де�етична Rational Рационален Binary Двоичен Octal О�мична Hexadecimal Ше�тнаде�етична Sexagesimal Шей�етична Update Available �алично е обновление A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> �алична е по-нова вер�и� (%1).<br/><a href="%2">По�етете �айта за изтегл�не.</a> Check for Updates Проверка за обновлени� SpeedCrunch %1 is up to date. SpeedCrunch %1 е актуален. No connectivity. Please check your internet connection and try again. ��ма връзка. Проверете интернет връзката �и и опитайте отново. Could not verify the latest available version. �е може да �е провери по�ледната налична вер�и�. ResultDisplay Scroll to bottom Превъртане до кра� Edit Expression Редактиране на израза Change Settings Пром�на на на�тройките New Tab �ов раздел &Import... &Импортиране... &Export &Ек�портиране Plain &text Обикновен &тек�т Copy Копиране Selection Избраното Select All Избиране на в�ичко Expression Израз Result Резултат Calculation Изчи�ление Calculation as Single Line Изчи�ление на един ред Remove Премахване This Calculation Това изчи�ление All Calculations Above В�ички изчи�лени� отгоре All Calculations Below В�ички изчи�лени� отдолу New Private Tab �ов ча�тен раздел Session Се�и� Open... Отвар�не... Clone... Клониране... Rename... Преименуване... Keep Запазване Make Private... Преобразуване в ча�тна... Clear Изчи�тване Delete Изтриване Close Затвори Split Раздел�не Left �ал�во Right �ад��но Up �агоре Down �адолу Close Pane Затвар�не на панела Main Menu Главно меню Cancel editing Отказ от редактирането Copy result Копиране на резултата Edit expression Редактиране на израза Change settings Пром�на на на�тройките Remove calculation Премахване на изчи�лението ResultSlotsDialog Notation & Precision �отаци� и точно�т Result Line Ред за резултат Enabled Включено Notation �отаци� Decimal Places Де�етични знаци Main Line О�новен ред Extra Line #1 Допълнителен ред #1 Extra Line #2 Допълнителен ред #2 Extra Line #3 Допълнителен ред #3 Extra Line #4 Допълнителен ред #4 Auto �втоматично UserFunctionListWidget Name �аименование Value Стойно�т Description Опи�ание Search Тър�ене No match found �е �а намерени резултати Insert Вмъкване Edit Редактиране Delete Изтриване Delete All Изтрий в�ички UserUnitListWidget Name �аименование Value Стойно�т Description Опи�ание Search Тър�ене No match found ��ма намерено �ъвпадение Insert Вмъкване Edit Редактиране Delete Изтриване Delete All Изтрий в�ички VariableListWidget Name �аименование Value Стойно�т Description Опи�ание Search Тър�ене No match found ��ма намерени Insert Вмъкване Edit Редактиране Delete Изтриване Delete All Изтрий в�ички heldercorreia-speedcrunch-e7ca37f/src/resources/locale/bn.ts000066400000000000000000011631631526573132500243570ustar00rootroot00000000000000 AboutBox About SpeedCrunch স�পিডক�রাঞ�চ সম�পর�কে Main author | Logo | Maintainer প�রধান লেখক | লোগো | রক�ষণাবেক�ষণকারী Core developers মূল ডেভেলপাররা Original author মূল লেখক Math engine গণিত ইঞ�জিন Thanks ধন�যবাদ Copyright (C) 2004-2026 The SpeedCrunch developers কপিরাইট (C) 2004-2026 স�পিডক�রাঞ�চ ডেভেলপাররা This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version �ই প�রোগ�রামটি ম�ক�ত সফটওয়�যার; আপনি ফ�রি সফটওয়�যার ফাউন�ডেশন কর�তৃক প�রকাশিত GNU General Public License-�র শর�তাবলীর অধীনে �টি প�নর�বিতরণ �বং/অথবা পরিবর�তন করতে পারেন; লাইসেন�সের সংস�করণ 2 অথবা (আপনার পছন�দে) যেকোনো পরবর�তী সংস�করণ। This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. �ই প�রোগ�রামটি উপকারী হবে �ই আশায় বিতরণ করা হয়, কিন�ত� কোনো প�রকার ওয়ারেন�টি ছাড়াই; �মনকি বাণিজ�যযোগ�যতা বা নির�দিষ�ট উদ�দেশ�যে উপযোগিতার অন�তর�নিহিত ওয়ারেন�টিও নয়। আরও বিস�তারিতের জন�য GNU General Public License দেখ�ন। Close বন�ধ কর�ন BitFieldWidget Reset bits to zero বিটগ�লো শূন�যে রিসেট কর�ন Invert bits বিটগ�লো উল�টে দিন Shift bits left বিটগ�লো বামে সরান Shift bits right বিটগ�লো ডানে সরান Book Index সূচি Algebra বীজগণিত Quadratic Equation দ�বিঘাত সমীকরণ Logarithmic Base Conversion লগারিদমিক ভিত�তি রূপান�তর Geometry জ�যামিতি Circle বৃত�ত Sector সেক�টর Sphere গোলক Cube ঘনক Cone শঙ�ক� Cylinder সিলিন�ডার Electronics ইলেকট�রনিক�স Ohm's Law ওহমের সূত�র Power ক�ষমতা Reactance রিঅ�যাক�ট�যান�স Resonance রেজোন�যান�স Radio Frequency রেডিও ফ�রিকোয়েন�সি Antennas অ�যান�টেনা Characteristic Impedance (coax) চরিত�রগত ইম�পিড�যান�স (কোঅ�যাক�স) Velocity of Propagation (coax) প�রসারণের বেগ (কোঅ�যাক�স) Standing Wave Ratio & Return Loss স�ট�যান�ডিং ওয়েভ রেশিও ও রিটার�ন লস Free Space Wavelength ম�ক�ত স�থানের তরঙ�গদৈর�ঘ�য resistance প�রতিরোধ voltage ভোল�টেজ current কারেন�ট power ক�ষমতা inductive reactance ইন�ডাক�টিভ রিঅ�যাক�ট�যান�স capacitive reactance ক�যাপাসিটিভ রিঅ�যাক�ট�যান�স inductance ইন�ডাক�ট�যান�স capacitance ক�যাপাসিট�যান�স frequency ফ�রিকোয়েন�সি resonance frequency রেজোন�যান�স ফ�রিকোয়েন�সি area ক�ষেত�রফল perimeter পরিসীমা diameter ব�যাস radius ব�যাসার�ধ volume আয়তন surface area পৃষ�ঠতল ক�ষেত�রফল height উচ�চতা slant height তির�যক উচ�চতা face diagonal তল কর�ণ space diagonal স�থানিক কর�ণ edge length ধারের দৈর�ঘ�য arc length চাপ দৈর�ঘ�য central angle (degrees) কেন�দ�রীয় কোণ (ডিগ�রি) dielectric constant ডাইইলেকট�রিক ধ�র�বক outer conductor's inner diameter বাহ�যিক পরিবাহকের অভ�যন�তরীণ ব�যাস inner conductor's outer diameter অভ�যন�তরীণ পরিবাহকের বাহ�যিক ব�যাস speed of light আলোর বেগ input power ইনপ�ট ক�ষমতা reflected power প�রতিফলিত ক�ষমতা transmitted power সঞ�চারিত ক�ষমতা return loss রিটার�ন লস reflection coefficient প�রতিফলন সহগ standing wave ratio স�ট�যান�ডিং ওয়েভ রেশিও normalized impedance স�বাভাবিকীকৃত ইম�পিড�যান�স frequency (Hz) ফ�রিকোয়েন�সি (Hz) BookDock Formula Book সূত�র বই ConstantCompletion Search constants ধ�র�বক খ��জ�ন No match found কোনও মিল পাওয়া যায়নি Constants Mathematics গণিত Physics (CODATA 2022) পদার�থবিজ�ঞান (CODATA ২০২২) Chemistry (IUPAC - CIAAW 2021) রসায়ন (IUPAC - CIAAW ২০২১) Uncategorized শ�রেণিবিহীন Universal সার�বজনীন Physicochemical ভৌত-রাসায়নিক Atomic & Nuclear — General পরমাণ� ও নিউক�লীয় — সাধারণ Atomic & Nuclear — Electroweak পরমাণ� ও নিউক�লীয় — ইলেক�ট�রোউইক Atomic & Nuclear — Electron পরমাণ� ও নিউক�লীয় — ইলেকট�রন Atomic & Nuclear — Muon পরমাণ� ও নিউক�লীয় — মিউয়ন Atomic & Nuclear — Tau পরমাণ� ও নিউক�লীয় — টাউ Atomic & Nuclear — Proton পরমাণ� ও নিউক�লীয় — প�রোটন Atomic & Nuclear — Neutron পরমাণ� ও নিউক�লীয় — নিউট�রন Atomic & Nuclear — Deuteron পরমাণ� ও নিউক�লীয় — ডিউটেরন Atomic & Nuclear — Triton পরমাণ� ও নিউক�লীয় — ট�রাইটন Atomic & Nuclear — Helion পরমাণ� ও নিউক�লীয় — হেলিয়ন Atomic & Nuclear — Alpha particle পরমাণ� ও নিউক�লীয় — আলফা কণা Atomic & Nuclear — Atomic units পরমাণ� ও নিউক�লীয় — পারমাণবিক �কক Atomic & Nuclear — Energy conversion relationships পরমাণ� ও নিউক�লীয় — শক�তি রূপান�তর সম�পর�ক Atomic & Nuclear — X-ray units পরমাণ� ও নিউক�লীয় — �ক�স-রে �কক Atomic & Nuclear — Magnetic shielding corrections পরমাণ� ও নিউক�লীয় — চৌম�বক শিল�ডিং সংশোধন Masses ভরসমূহ Lifetimes আয়�ষ�কালসমূহ Molar Masses মোলার ভরসমূহ Electronegativity তড়িৎঋণাত�মকতা Ionization Energy আয়নায়ন শক�তি Nominal Constants (IAU 2015) নামমাত�র ধ�র�বকসমূহ (IAU ২০১৫) Current Best Estimates (IAU NSFA 2026-04) বর�তমান সেরা অন�মানসমূহ (IAU NSFA ২০২৬-০৪) characteristic impedance of vacuum (Z₀) characteristic impedance of শূন�যস�থান (Z₀) reduced Planck constant (�) হ�রাসপ�রাপ�ত প�ল�যাঙ�ক ধ�র�বক (�) vacuum electric permittivity (ϵ₀) শূন�যস�থান তড়িৎ পারমিটিভিটি (ϵ₀) Newtonian constant of gravitation (G) নিউটনীয় ধ�র�বক of মহাকর�ষ (G) vacuum magnetic permeability (μ₀) শূন�যস�থান magnetic পারমিয়াবিলিটি (μ₀) Planck constant (h) প�ল�যাঙ�ক ধ�র�বক (h) speed of light in vacuum (c) speed of আলো in শূন�যস�থান (c) standard acceleration of gravity (gₙ) মাধ�যাকর�ষণের মানক ত�বরণ (gₙ) Newtonian constant of gravitation over h-bar c নিউটনীয় ধ�র�বক of মহাকর�ষ over h-bar c Planck length প�ল�যাঙ�ক দৈর�ঘ�য Planck constant in eV/Hz (h) প�ল�যাঙ�ক ধ�র�বক in eV/Hz (h) Planck mass প�ল�যাঙ�ক ভর Planck mass energy equivalent in GeV প�ল�যাঙ�ক ভর শক�তি সমত�ল�য in GeV Planck temperature প�ল�যাঙ�ক তাপমাত�রা Planck time প�ল�যাঙ�ক সময় reduced Planck constant in eV·s (�) হ�রাসপ�রাপ�ত প�ল�যাঙ�ক ধ�র�বক in eV·s (�) reduced Planck constant times c in MeV·fm হ�রাসপ�রাপ�ত প�ল�যাঙ�ক ধ�র�বক গ�ণ c, MeV·fm-� Bohr magneton বোর magneton conductance quantum (G₀) পরিবাহিতা কোয়ান�টাম (G₀) Coulomb constant (kₑ) ক�লম�ব ধ�র�বক (kₑ) elementary charge (e) elementary আধান (e) elementary charge over h-bar elementary আধান over h-bar conventional value of Josephson constant conventional value of জোসেফসন ধ�র�বক Josephson constant জোসেফসন ধ�র�বক conventional value of ampere-90 অ�যাম�পিয়ার-90-�র প�রচলিত মান conventional value of coulomb-90 ক�লম�ব-90-�র প�রচলিত মান conventional value of farad-90 ফ�যারাড-90-�র প�রচলিত মান conventional value of henry-90 হেনরি-90-�র প�রচলিত মান conventional value of ohm-90 ওহম-90-�র প�রচলিত মান conventional value of volt-90 ভোল�ট-90-�র প�রচলিত মান conventional value of watt-90 ওয়াট-90-�র প�রচলিত মান magnetic flux quantum (Φ₀) magnetic flux কোয়ান�টাম (Φ₀) nuclear magneton নিউক�লীয় ম�যাগনেটন inverse of conductance quantum বিপরীত of পরিবাহিতা কোয়ান�টাম conventional value of von Klitzing constant conventional value of von Klitzing ধ�র�বক von Klitzing constant von Klitzing ধ�র�বক atomic unit of magnetic dipole moment পারমাণবিক �কক of magnetic dipole moment atomic unit of magnetic flux density পারমাণবিক �কক of magnetic flux ঘনত�ব Bohr magneton in eV/T বোর magneton in eV/T Bohr magneton in Hz/T বোর magneton in Hz/T Bohr magneton in inverse meter per tesla বোর magneton in বিপরীত meter per tesla Bohr magneton in K/T বোর magneton in K/T nuclear magneton in eV/T নিউক�লীয় ম�যাগনেটন eV/T-� nuclear magneton in inverse meter per tesla nuclear magneton in বিপরীত meter per tesla nuclear magneton in K/T নিউক�লীয় ম�যাগনেটন K/T-� nuclear magneton in MHz/T নিউক�লীয় ম�যাগনেটন MHz/T-� Bohr radius (a₀) বোর ব�যাসার�ধ (a₀) fine-structure constant (α) fine-structure ধ�র�বক (α) Hartree energy (Eₕ) হার�ট�রি শক�তি (Eₕ) Hartree energy in eV হার�ট�রি শক�তি in eV quantum of circulation পরিসঞ�চালনের কোয়ান�টাম quantum of circulation times 2 পরিসঞ�চালনের কোয়ান�টাম গ�ণ 2 Rydberg constant (R∞) রিডবার�গ ধ�র�বক (R∞) atomic mass unit-hartree relationship পারমাণবিক ভর �কক-hartree সম�পর�ক atomic mass unit-hertz relationship পারমাণবিক ভর �কক-hertz সম�পর�ক atomic mass unit-inverse meter relationship পারমাণবিক ভর �কক-বিপরীত meter সম�পর�ক atomic mass unit-joule relationship পারমাণবিক ভর �কক-joule সম�পর�ক atomic mass unit-kelvin relationship পারমাণবিক ভর �কক-kelvin সম�পর�ক atomic mass unit-kilogram relationship পারমাণবিক ভর �কক-kilogram সম�পর�ক atomic unit of 1st hyperpolarizability পারমাণবিক �কক of 1st hyperpolarizability atomic unit of 2nd hyperpolarizability পারমাণবিক �কক of 2nd hyperpolarizability atomic unit of charge (e) পারমাণবিক �কক of আধান (e) atomic unit of charge density পারমাণবিক �কক of আধান ঘনত�ব atomic unit of current পারমাণবিক �কক of current atomic unit of electric dipole moment পারমাণবিক �কক of তড়িৎ dipole moment atomic unit of electric field পারমাণবিক �কক of তড়িৎ field atomic unit of electric field gradient পারমাণবিক �কক of তড়িৎ field gradient atomic unit of electric polarizability পারমাণবিক �কক of তড়িৎ polarizability atomic unit of electric potential পারমাণবিক �কক of তড়িৎ বিভব atomic unit of electric quadrupole moment পারমাণবিক �কক of তড়িৎ quadrupole moment atomic unit of action পারমাণবিক �কক of ক�রিয়া atomic unit of energy পারমাণবিক �কক of শক�তি atomic unit of force পারমাণবিক �কক of বল atomic unit of length পারমাণবিক �কক of দৈর�ঘ�য hertz-atomic mass unit relationship hertz-পারমাণবিক ভর �কক সম�পর�ক hertz-electron volt relationship hertz-ইলেকট�রন volt সম�পর�ক hertz-hartree relationship hertz-hartree সম�পর�ক hertz-inverse meter relationship hertz-বিপরীত meter সম�পর�ক hertz-joule relationship hertz-joule সম�পর�ক hertz-kelvin relationship hertz-kelvin সম�পর�ক hertz-kilogram relationship hertz-kilogram সম�পর�ক hyperfine transition frequency of Cs-133 hyperfine transition কম�পাঙ�ক of Cs-133 inverse fine-structure constant (α�¹) বিপরীত fine-structure ধ�র�বক (α�¹) inverse meter-atomic mass unit relationship বিপরীত meter-পারমাণবিক ভর �কক সম�পর�ক inverse meter-electron volt relationship বিপরীত meter-ইলেকট�রন volt সম�পর�ক inverse meter-hartree relationship বিপরীত meter-hartree সম�পর�ক inverse meter-hertz relationship বিপরীত meter-hertz সম�পর�ক inverse meter-joule relationship বিপরীত meter-joule সম�পর�ক inverse meter-kelvin relationship বিপরীত meter-kelvin সম�পর�ক inverse meter-kilogram relationship বিপরীত meter-kilogram সম�পর�ক joule-atomic mass unit relationship joule-পারমাণবিক ভর �কক সম�পর�ক joule-electron volt relationship joule-ইলেকট�রন volt সম�পর�ক joule-hertz relationship joule-hertz সম�পর�ক joule-hartree relationship joule-hartree সম�পর�ক joule-inverse meter relationship joule-বিপরীত meter সম�পর�ক joule-kelvin relationship joule-kelvin সম�পর�ক joule-kilogram relationship joule-kilogram সম�পর�ক kelvin-atomic mass unit relationship kelvin-পারমাণবিক ভর �কক সম�পর�ক kelvin-electron volt relationship kelvin-ইলেকট�রন volt সম�পর�ক kelvin-hertz relationship kelvin-hertz সম�পর�ক kelvin-hartree relationship kelvin-hartree সম�পর�ক kelvin-inverse meter relationship kelvin-বিপরীত meter সম�পর�ক kelvin-joule relationship kelvin-joule সম�পর�ক kelvin-kilogram relationship kelvin-kilogram সম�পর�ক kilogram-atomic mass unit relationship kilogram-পারমাণবিক ভর �কক সম�পর�ক kilogram-electron volt relationship kilogram-ইলেকট�রন volt সম�পর�ক kilogram-hertz relationship kilogram-hertz সম�পর�ক kilogram-hartree relationship kilogram-hartree সম�পর�ক kilogram-inverse meter relationship kilogram-বিপরীত meter সম�পর�ক kilogram-joule relationship kilogram-joule সম�পর�ক kilogram-kelvin relationship kilogram-kelvin সম�পর�ক lattice parameter of silicon (a) সিলিকনের জালক পরামিতি (a) luminous efficacy আলোক কার�যকারিতা natural unit of energy প�রাকৃতিক �কক of শক�তি natural unit of energy in MeV প�রাকৃতিক �কক of শক�তি in MeV natural unit of action (�) প�রাকৃতিক �কক of ক�রিয়া (�) natural unit of action in eV·s প�রাকৃতিক �কক of ক�রিয়া in eV·s natural unit of length প�রাকৃতিক �কক of দৈর�ঘ�য natural unit of mass প�রাকৃতিক �কক of ভর natural unit of momentum প�রাকৃতিক �কক of ভরবেগ natural unit of momentum in MeV/c প�রাকৃতিক �কক of ভরবেগ in MeV/c natural unit of time প�রাকৃতিক �কক of সময় natural unit of velocity প�রাকৃতিক �কক of বেগ Rydberg constant times c in Hz রিডবার�গ ধ�র�বক গ�ণ c, Hz-� Rydberg constant times hc in eV রিডবার�গ ধ�র�বক গ�ণ hc, eV-� Rydberg constant times hc in J রিডবার�গ ধ�র�বক গ�ণ hc, J-� Fermi coupling constant Fermi coupling ধ�র�বক weak mixing angle দ�র�বল মিশ�রণ কোণ W to Z mass ratio W to Z ভর অন�পাত Thomson cross section (σₑ) থমসন cross section (σₑ) electron mass (mₑ) ইলেকট�রন ভর (mₑ) electron mass in u ইলেকট�রন ভর in u electron mass energy equivalent (mₑ·c²) ইলেকট�রন ভর শক�তি সমত�ল�য (mₑ·c²) electron mass energy equivalent in MeV ইলেকট�রন ভর শক�তি সমত�ল�য in MeV reduced Compton wavelength হ�রাসপ�রাপ�ত কম�পটন তরঙ�গদৈর�ঘ�য classical electron radius (rₑ) classical ইলেকট�রন ব�যাসার�ধ (rₑ) electron charge to mass quotient ইলেকট�রন আধান to ভর quotient electron-deuteron magnetic moment ratio ইলেকট�রন-ডিউটেরন চৌম�বক ম�হূর�ত অন�পাত electron-deuteron mass ratio ইলেকট�রন-ডিউটেরন ভর অন�পাত electron g factor (gₑ) ইলেকট�রন g factor (gₑ) electron gyromagnetic ratio (γₑ) ইলেকট�রন gyromagnetic অন�পাত (γₑ) electron gyromagnetic ratio in MHz/T ইলেকট�রন gyromagnetic অন�পাত in MHz/T electron-helion mass ratio ইলেকট�রন-হেলিয়ন ভর অন�পাত electron magnetic moment (μₑ) ইলেকট�রন চৌম�বক ম�হূর�ত (μₑ) electron magnetic moment anomaly (aₑ) ইলেকট�রন চৌম�বক ম�হূর�ত anomaly (aₑ) electron magnetic moment to Bohr magneton ratio ইলেকট�রন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত electron magnetic moment to nuclear magneton ratio ইলেকট�রন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত electron molar mass (Mₑ) ইলেকট�রন মোলার ভর (Mₑ) electron-muon magnetic moment ratio ইলেকট�রন-মিউয়ন চৌম�বক ম�হূর�ত অন�পাত electron-muon mass ratio ইলেকট�রন-মিউয়ন ভর অন�পাত electron-neutron magnetic moment ratio ইলেকট�রন-নিউট�রন চৌম�বক ম�হূর�ত অন�পাত electron-neutron mass ratio ইলেকট�রন-নিউট�রন ভর অন�পাত electron-proton magnetic moment ratio ইলেকট�রন-প�রোটন চৌম�বক ম�হূর�ত অন�পাত electron-proton mass ratio ইলেকট�রন-প�রোটন ভর অন�পাত electron relative atomic mass (Ar(e)) ইলেকট�রন আপেক�ষিক পারমাণবিক ভর (Ar(e)) electron-tau mass ratio ইলেকট�রন-টাউ ভর অন�পাত electron to alpha particle mass ratio ইলেকট�রন to আলফা কণা ভর অন�পাত electron to shielded helion magnetic moment ratio ইলেকট�রন to শিল�ডেড হেলিয়ন চৌম�বক ম�হূর�ত অন�পাত electron to shielded proton magnetic moment ratio ইলেকট�রন to শিল�ডেড প�রোটন চৌম�বক ম�হূর�ত অন�পাত electron-triton mass ratio ইলেকট�রন-ট�রাইটন ভর অন�পাত electron volt-atomic mass unit relationship ইলেকট�রন volt-পারমাণবিক ভর �কক সম�পর�ক electron volt-hartree relationship ইলেকট�রন volt-hartree সম�পর�ক electron volt-hertz relationship ইলেকট�রন volt-hertz সম�পর�ক electron volt-inverse meter relationship ইলেকট�রন volt-বিপরীত meter সম�পর�ক electron volt-joule relationship ইলেকট�রন volt-joule সম�পর�ক electron volt-kelvin relationship ইলেকট�রন volt-kelvin সম�পর�ক electron volt-kilogram relationship ইলেকট�রন volt-kilogram সম�পর�ক hartree-atomic mass unit relationship hartree-পারমাণবিক ভর �কক সম�পর�ক hartree-electron volt relationship hartree-ইলেকট�রন volt সম�পর�ক muon Compton wavelength মিউয়ন কম�পটন তরঙ�গদৈর�ঘ�য muon-electron mass ratio মিউয়ন-ইলেকট�রন ভর অন�পাত muon g factor মিউয়ন g factor muon magnetic moment মিউয়ন চৌম�বক ম�হূর�ত muon magnetic moment anomaly মিউয়ন চৌম�বক ম�হূর�ত anomaly muon magnetic moment to Bohr magneton ratio মিউয়ন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত muon magnetic moment to nuclear magneton ratio মিউয়ন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত muon mass মিউয়ন ভর muon mass energy equivalent মিউয়ন ভর শক�তি সমত�ল�য muon mass energy equivalent in MeV মিউয়ন ভর শক�তি সমত�ল�য in MeV muon mass in u মিউয়ন ভর in u muon molar mass মিউয়ন মোলার ভর muon-neutron mass ratio মিউয়ন-নিউট�রন ভর অন�পাত muon-proton magnetic moment ratio মিউয়ন-প�রোটন চৌম�বক ম�হূর�ত অন�পাত muon-proton mass ratio মিউয়ন-প�রোটন ভর অন�পাত muon-tau mass ratio মিউয়ন-টাউ ভর অন�পাত reduced muon Compton wavelength হ�রাসপ�রাপ�ত মিউয়ন কম�পটন তরঙ�গদৈর�ঘ�য reduced tau Compton wavelength হ�রাসপ�রাপ�ত টাউ কম�পটন তরঙ�গদৈর�ঘ�য tau Compton wavelength টাউ কম�পটন তরঙ�গদৈর�ঘ�য tau-electron mass ratio টাউ-ইলেকট�রন ভর অন�পাত tau mass টাউ ভর tau mass energy equivalent টাউ ভর শক�তি সমত�ল�য tau mass in u টাউ ভর in u tau molar mass টাউ মোলার ভর tau-muon mass ratio টাউ-মিউয়ন ভর অন�পাত tau-neutron mass ratio টাউ-নিউট�রন ভর অন�পাত tau-proton mass ratio টাউ-প�রোটন ভর অন�পাত proton charge to mass quotient প�রোটন আধান to ভর quotient proton Compton wavelength প�রোটন কম�পটন তরঙ�গদৈর�ঘ�য proton-electron mass ratio প�রোটন-ইলেকট�রন ভর অন�পাত proton g factor (gₚ) প�রোটন g factor (gₚ) proton gyromagnetic ratio (γₚ) প�রোটন gyromagnetic অন�পাত (γₚ) proton gyromagnetic ratio in MHz/T প�রোটন gyromagnetic অন�পাত in MHz/T proton magnetic moment (μₚ) প�রোটন চৌম�বক ম�হূর�ত (μₚ) proton magnetic moment to Bohr magneton ratio প�রোটন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত proton magnetic moment to nuclear magneton ratio প�রোটন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত proton magnetic shielding correction প�রোটন magnetic shielding correction proton mass (mₚ) প�রোটন ভর (mₚ) proton mass energy equivalent প�রোটন ভর শক�তি সমত�ল�য proton mass energy equivalent in MeV প�রোটন ভর শক�তি সমত�ল�য in MeV proton mass in u প�রোটন ভর in u proton molar mass (Mₚ) প�রোটন মোলার ভর (Mₚ) proton-muon mass ratio প�রোটন-মিউয়ন ভর অন�পাত proton-neutron magnetic moment ratio প�রোটন-নিউট�রন চৌম�বক ম�হূর�ত অন�পাত proton-neutron mass ratio প�রোটন-নিউট�রন ভর অন�পাত proton relative atomic mass (Ar(p)) প�রোটন আপেক�ষিক পারমাণবিক ভর (Ar(p)) proton rms charge radius প�রোটন rms আধান ব�যাসার�ধ proton-tau mass ratio প�রোটন-টাউ ভর অন�পাত reduced proton Compton wavelength হ�রাসপ�রাপ�ত প�রোটন কম�পটন তরঙ�গদৈর�ঘ�য shielded proton gyromagnetic ratio শিল�ডেড প�রোটন gyromagnetic অন�পাত shielded proton gyromagnetic ratio in MHz/T শিল�ডেড প�রোটন gyromagnetic অন�পাত in MHz/T shielded proton magnetic moment শিল�ডেড প�রোটন চৌম�বক ম�হূর�ত shielded proton magnetic moment to Bohr magneton ratio শিল�ডেড প�রোটন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত shielded proton magnetic moment to nuclear magneton ratio শিল�ডেড প�রোটন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত neutron Compton wavelength নিউট�রন কম�পটন তরঙ�গদৈর�ঘ�য neutron-electron magnetic moment ratio নিউট�রন-ইলেকট�রন চৌম�বক ম�হূর�ত অন�পাত neutron-electron mass ratio নিউট�রন-ইলেকট�রন ভর অন�পাত neutron g factor (gₙ) নিউট�রন g factor (gₙ) neutron gyromagnetic ratio (γₙ) নিউট�রন gyromagnetic অন�পাত (γₙ) neutron gyromagnetic ratio in MHz/T নিউট�রন gyromagnetic অন�পাত in MHz/T neutron magnetic moment (μₙ) নিউট�রন চৌম�বক ম�হূর�ত (μₙ) neutron magnetic moment to Bohr magneton ratio নিউট�রন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত neutron magnetic moment to nuclear magneton ratio নিউট�রন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত neutron mass (mₙ) নিউট�রন ভর (mₙ) neutron mass energy equivalent নিউট�রন ভর শক�তি সমত�ল�য neutron mass energy equivalent in MeV নিউট�রন ভর শক�তি সমত�ল�য in MeV neutron mass in u নিউট�রন ভর in u neutron molar mass (Mₙ) নিউট�রন মোলার ভর (Mₙ) neutron-muon mass ratio নিউট�রন-মিউয়ন ভর অন�পাত neutron-proton magnetic moment ratio নিউট�রন-প�রোটন চৌম�বক ম�হূর�ত অন�পাত neutron-proton mass difference নিউট�রন-প�রোটন ভর difference neutron-proton mass difference energy equivalent নিউট�রন-প�রোটন ভর difference শক�তি সমত�ল�য neutron-proton mass difference energy equivalent in MeV নিউট�রন-প�রোটন ভর difference শক�তি সমত�ল�য in MeV neutron-proton mass difference in u নিউট�রন-প�রোটন ভর difference in u neutron-proton mass ratio নিউট�রন-প�রোটন ভর অন�পাত neutron relative atomic mass (Ar(n)) নিউট�রন আপেক�ষিক পারমাণবিক ভর (Ar(n)) neutron-tau mass ratio নিউট�রন-টাউ ভর অন�পাত neutron to shielded proton magnetic moment ratio নিউট�রন to শিল�ডেড প�রোটন চৌম�বক ম�হূর�ত অন�পাত reduced neutron Compton wavelength হ�রাসপ�রাপ�ত নিউট�রন কম�পটন তরঙ�গদৈর�ঘ�য deuteron-electron magnetic moment ratio ডিউটেরন-ইলেকট�রন চৌম�বক ম�হূর�ত অন�পাত deuteron-electron mass ratio ডিউটেরন-ইলেকট�রন ভর অন�পাত deuteron g factor ডিউটেরন g factor deuteron magnetic moment ডিউটেরন চৌম�বক ম�হূর�ত deuteron magnetic moment to Bohr magneton ratio ডিউটেরন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত deuteron magnetic moment to nuclear magneton ratio ডিউটেরন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত deuteron mass ডিউটেরন ভর deuteron mass energy equivalent ডিউটেরন ভর শক�তি সমত�ল�য deuteron mass energy equivalent in MeV ডিউটেরন ভর শক�তি সমত�ল�য in MeV deuteron mass in u ডিউটেরন ভর in u deuteron molar mass ডিউটেরন মোলার ভর deuteron-neutron magnetic moment ratio ডিউটেরন-নিউট�রন চৌম�বক ম�হূর�ত অন�পাত deuteron-proton magnetic moment ratio ডিউটেরন-প�রোটন চৌম�বক ম�হূর�ত অন�পাত deuteron-proton mass ratio ডিউটেরন-প�রোটন ভর অন�পাত deuteron relative atomic mass (Ar(d)) ডিউটেরন আপেক�ষিক পারমাণবিক ভর (Ar(d)) deuteron rms charge radius ডিউটেরন rms আধান ব�যাসার�ধ triton-electron mass ratio ট�রাইটন-ইলেকট�রন ভর অন�পাত triton g factor (gₜ) ট�রাইটন g factor (gₜ) triton magnetic moment (μₜ) ট�রাইটন চৌম�বক ম�হূর�ত (μₜ) triton magnetic moment to Bohr magneton ratio ট�রাইটন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত triton magnetic moment to nuclear magneton ratio ট�রাইটন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত triton mass (mₜ) ট�রাইটন ভর (mₜ) triton mass energy equivalent ট�রাইটন ভর শক�তি সমত�ল�য triton mass energy equivalent in MeV ট�রাইটন ভর শক�তি সমত�ল�য in MeV triton mass in u ট�রাইটন ভর in u triton molar mass (Mₜ) ট�রাইটন মোলার ভর (Mₜ) triton-proton mass ratio ট�রাইটন-প�রোটন ভর অন�পাত triton relative atomic mass (Ar(t)) ট�রাইটন আপেক�ষিক পারমাণবিক ভর (Ar(t)) triton to proton magnetic moment ratio ট�রাইটন to প�রোটন চৌম�বক ম�হূর�ত অন�পাত helion-electron mass ratio হেলিয়ন-ইলেকট�রন ভর অন�পাত helion g factor (gₕ) হেলিয়ন g factor (gₕ) helion magnetic moment (μₕ) হেলিয়ন চৌম�বক ম�হূর�ত (μₕ) helion magnetic moment to Bohr magneton ratio হেলিয়ন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত helion magnetic moment to nuclear magneton ratio হেলিয়ন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত helion mass (mₕ) হেলিয়ন ভর (mₕ) helion mass energy equivalent হেলিয়ন ভর শক�তি সমত�ল�য helion mass energy equivalent in MeV হেলিয়ন ভর শক�তি সমত�ল�য in MeV helion mass in u হেলিয়ন ভর in u helion molar mass (Mₕ) হেলিয়ন মোলার ভর (Mₕ) helion-proton mass ratio হেলিয়ন-প�রোটন ভর অন�পাত helion relative atomic mass (Ar(h)) হেলিয়ন আপেক�ষিক পারমাণবিক ভর (Ar(h)) helion shielding shift হেলিয়ন shielding shift shielded helion gyromagnetic ratio শিল�ডেড হেলিয়ন gyromagnetic অন�পাত shielded helion gyromagnetic ratio in MHz/T শিল�ডেড হেলিয়ন gyromagnetic অন�পাত in MHz/T shielded helion magnetic moment শিল�ডেড হেলিয়ন চৌম�বক ম�হূর�ত shielded helion magnetic moment to Bohr magneton ratio শিল�ডেড হেলিয়ন চৌম�বক ম�হূর�ত to বোর magneton অন�পাত shielded helion magnetic moment to nuclear magneton ratio শিল�ডেড হেলিয়ন চৌম�বক ম�হূর�ত to nuclear magneton অন�পাত shielded helion to proton magnetic moment ratio শিল�ডেড হেলিয়ন to প�রোটন চৌম�বক ম�হূর�ত অন�পাত shielded helion to shielded proton magnetic moment ratio শিল�ডেড হেলিয়ন to শিল�ডেড প�রোটন চৌম�বক ম�হূর�ত অন�পাত alpha particle mass আলফা কণা ভর alpha particle mass in u আলফা কণা ভর in u alpha particle mass energy equivalent আলফা কণা ভর শক�তি সমত�ল�য alpha particle mass energy equivalent in MeV আলফা কণা ভর শক�তি সমত�ল�য in MeV alpha particle-electron mass ratio আলফা কণা-ইলেকট�রন ভর অন�পাত alpha particle-proton mass ratio আলফা কণা-প�রোটন ভর অন�পাত alpha particle rms charge radius আলফা কণা rms আধান ব�যাসার�ধ alpha particle molar mass আলফা কণা মোলার ভর alpha particle relative atomic mass (Ar(α)) আলফা কণা আপেক�ষিক পারমাণবিক ভর (Ar(α)) atomic mass constant (mᵤ) পারমাণবিক ভর ধ�র�বক (mᵤ) Avogadro constant অ�যাভোগাড�রো ধ�র�বক Boltzmann constant (k) বোল�টসম�যান ধ�র�বক (k) Boltzmann constant in eV/K বোল�টসম�যান ধ�র�বক in eV/K Boltzmann constant in Hz/K বোল�টসম�যান ধ�র�বক in Hz/K Boltzmann constant in inverse meter per kelvin বোল�টসম�যান ধ�র�বক in বিপরীত meter per kelvin electron volt (eV) ইলেকট�রন volt (eV) Faraday constant (F) ফ�যারাডে ধ�র�বক (F) first radiation constant (c�) first radiation ধ�র�বক (c�) first radiation constant for spectral radiance first radiation ধ�র�বক for spectral radiance molar gas constant (R) মোলার gas ধ�র�বক (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidt ধ�র�বক (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Loschmidt ধ�র�বক (n₀, 273.15 K, 101.325 kPa) molar Planck constant মোলার প�ল�যাঙ�ক ধ�র�বক second radiation constant (c₂) second radiation ধ�র�বক (c₂) Stefan-Boltzmann constant (σ) Stefan-বোল�টসম�যান ধ�র�বক (σ) lattice spacing of ideal Si (d₂₂₀) আদর�শ Si-�র জালক ব�যবধান (d₂₂₀) atomic mass constant energy equivalent পারমাণবিক ভর ধ�র�বক শক�তি সমত�ল�য atomic mass constant energy equivalent in MeV পারমাণবিক ভর ধ�র�বক শক�তি সমত�ল�য in MeV atomic mass unit-electron volt relationship পারমাণবিক ভর �কক-ইলেকট�রন volt সম�পর�ক molar mass constant (Mᵤ) মোলার ভর ধ�র�বক (Mᵤ) molar mass of carbon-12 মোলার ভর of carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) মোলার আয়তন of ideal gas (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) মোলার আয়তন of ideal gas (273.15 K, 101.325 kPa) molar volume of silicon মোলার আয়তন of silicon Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode ধ�র�বক (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode ধ�র�বক (1 K, 101.325 kPa) Wien frequency displacement law constant Wien কম�পাঙ�ক displacement law ধ�র�বক Wien wavelength displacement law constant Wien তরঙ�গদৈর�ঘ�য displacement law ধ�র�বক standard atmosphere (atm) মানক atmosphere (atm) standard-state pressure (p°) মানক-state চাপ (p°) Angstrom star (Å*) অ�যাংস�ট�রম স�টার (Å*) Copper x unit Copper x �কক Molybdenum x unit Molybdenum x �কক atomic unit of magnetizability পারমাণবিক �কক of magnetizability atomic unit of mass (mₑ) পারমাণবিক �কক of ভর (mₑ) atomic unit of momentum পারমাণবিক �কক of ভরবেগ atomic unit of permittivity পারমাণবিক �কক of পারমিটিভিটি atomic unit of time পারমাণবিক �কক of সময় atomic unit of velocity পারমাণবিক �কক of বেগ hartree-hertz relationship hartree-hertz সম�পর�ক hartree-inverse meter relationship hartree-বিপরীত meter সম�পর�ক hartree-joule relationship hartree-joule সম�পর�ক hartree-kelvin relationship hartree-kelvin সম�পর�ক hartree-kilogram relationship hartree-kilogram সম�পর�ক shielding difference of d and p in HD HD-তে d ও p-�র শিল�ডিং পার�থক�য shielding difference of t and p in HT HT-তে t ও p-�র শিল�ডিং পার�থক�য pi (π) পাই (π) Euler's number (e) অয়লার's number (e) golden ratio (φ) golden অন�পাত (φ) Euler-Mascheroni constant (γ) অয়লার-Mascheroni ধ�র�বক (γ) nominal solar radius নামমাত�র solar ব�যাসার�ধ nominal solar total irradiance নামমাত�র solar total irradiance nominal solar luminosity নামমাত�র solar luminosity nominal solar effective temperature নামমাত�র solar effective তাপমাত�রা nominal solar mass parameter নামমাত�র solar ভর parameter nominal terrestrial equatorial radius নামমাত�র terrestrial equatorial ব�যাসার�ধ nominal terrestrial polar radius নামমাত�র terrestrial polar ব�যাসার�ধ nominal terrestrial mass parameter নামমাত�র terrestrial ভর parameter nominal jovian equatorial radius নামমাত�র jovian equatorial ব�যাসার�ধ nominal jovian polar radius নামমাত�র jovian polar ব�যাসার�ধ nominal jovian mass parameter নামমাত�র jovian ভর parameter average value of one minus the rate of TCG relative to TCB TCB-�র সাপেক�ষে TCG-�র হারের �ক-বিয়োগের গড় মান solar mass parameter (TCB-compatible) solar ভর parameter (TCB-compatible) solar mass parameter (TDB-compatible) solar ভর parameter (TDB-compatible) equatorial radius of the Earth (TT-compatible) equatorial ব�যাসার�ধ of the Earth (TT-compatible) dynamical form factor of the Earth পৃথিবীর গতীয় রূপ গ�ণক time rate of change in the dynamical form factor of the Earth সময় rate of change in the dynamical form factor of the Earth geocentric gravitational constant (TCB-compatible) ভূকেন�দ�রিক মহাকর�ষীয় ধ�র�বক (TCB-compatible) geocentric gravitational constant (TT-compatible) ভূকেন�দ�রিক মহাকর�ষীয় ধ�র�বক (TT-compatible) geocentric gravitational constant (TDB-compatible) ভূকেন�দ�রিক মহাকর�ষীয় ধ�র�বক (TDB-compatible) potential of the geoid বিভব of the geoid nominal mean angular velocity of the Earth (TT-compatible) নামমাত�র গড় angular বেগ of the Earth (TT-compatible) ratio mass of the Moon to the Earth অন�পাত ভর of the Moon to the Earth ratio of the mass of the Sun to Mercury অন�পাত of the ভর of the Sun to Mercury ratio of the mass of the Sun to Venus অন�পাত of the ভর of the Sun to Venus ratio of the mass of the Sun to Mars অন�পাত of the ভর of the Sun to Mars ratio of the mass of the Sun to Jupiter সূর�যের ভর ও বৃহস�পতির ভরের অন�পাত ratio of the mass of the Sun to Saturn অন�পাত of the ভর of the Sun to Saturn ratio of the mass of the Sun to Uranus অন�পাত of the ভর of the Sun to Uranus ratio of the mass of the Sun to Neptune অন�পাত of the ভর of the Sun to Neptune ratio of the mass of the Sun to (134340) Pluto অন�পাত of the ভর of the Sun to (134340) Pluto ratio of the mass of the Sun to (136199) Eris অন�পাত of the ভর of the Sun to (136199) Eris ratio of the mass of (1) Ceres to the Sun অন�পাত of the ভর of (1) Ceres to the Sun ratio of the mass of (2) Pallas to the Sun অন�পাত of the ভর of (2) Pallas to the Sun ratio of the mass of (4) Vesta to the Sun অন�পাত of the ভর of (4) Vesta to the Sun mean obliquity of the ecliptic at J2000.0 গড় obliquity of the ecliptic at J2000.0 Electromagnetic তড়িৎচৌম�বক Compton wavelength কম�পটন তরঙ�গদৈর�ঘ�য Astronomy জ�যোতির�বিজ�ঞান ConstantsWidget Domain ক�ষেত�র Subdomain উপক�ষেত�র Search অন�সন�ধান No match found কোনও মিল পাওয়া যায়নি Name নাম Value মান Unit �কক All সব CustomKeypadDialog Custom Keypad কাস�টম কীপ�যাড Rows: সারি: Columns: কলাম: Copy preset: প�রিসেট কপি কর�ন: Basic মৌলিক Scientific (wide) বৈজ�ঞানিক (প�রশস�ত) Scientific (narrow) বৈজ�ঞানিক (সংকীর�ণ) Apply প�রয়োগ Row সারি Column কলাম Label লেবেল Behavior আচরণ Text পাঠ�য DiagnosticsDialog App Diagnostics অ�যাপের রোগনির�ণয় Copy to Clipboard ক�লিপবোর�ডে অন�লিপি Editor Unit �কক User unit ব�যবহারকারী �কক User function ব�যবহারকারী ফাংশন Argument আর�গ�মেন�ট Current result:<br/>%1 বর�তমান ফলাফল:<br/>%1 Selection result:<br/>%1 নির�বাচনের ফলাফল:<br/>%1 Selection result: n/a নির�বাচিত ফলাফল: প�রযোজ�য নয় Selection result: %1 নির�বাচিত ফলাফল: %1 second সেকেন�ড metre মিটার kilogram কিলোগ�রাম mole মোল radian রেডিয়ান steradian স�টেরেডিয়ান degree Celsius ডিগ�রি সেলসিয়াস cubic metre ঘন মিটার cubic millimetre ঘন মিলিমিটার cubic centimetre ঘন সেন�টিমিটার cubic decimetre ঘন ডেসিমিটার cubic kilometre ঘন কিলোমিটার square millimetre বর�গ মিলিমিটার square kilometre বর�গ কিলোমিটার square metre বর�গ মিটার minute মিনিট hour ঘণ�টা day দিন astronomical unit জ�যোতির�বৈজ�ঞানিক �কক degree ডিগ�রি arcminute আর�কমিনিট arcsecond আর�কসেকেন�ড milliarcsecond মিলিআর�কসেকেন�ড microarcsecond মাইক�রোআর�কসেকেন�ড hectare হেক�টর litre লিটার tonne টন Dalton ডাল�টন electronvolt ইলেকট�রনভোল�ট Angstrom অ�যাংস�ট�রম atmosphere বায়�মণ�ডল atomic mass unit পারমাণবিক ভর �কক British thermal unit ব�রিটিশ তাপীয় �কক calorie ক�যালরি carat ক�যারেট cup কাপ cup (Imperial) কাপ (ইম�পেরিয়াল) cup (Japanese) কাপ (জাপানি) cup (US) কাপ (মার�কিন) degree Fahrenheit ডিগ�রি ফারেনহাইট fathom ফ�যাদম fluid ounce (Imperial) তরল আউন�স (ইম�পেরিয়াল) fluid ounce (US) তরল আউন�স (মার�কিন) fluid dram (Imperial) তরল ড�রাম (ইম�পেরিয়াল) fluid dram (US) তরল ড�রাম (মার�কিন) foot ফ�ট square foot বর�গ ফ�ট cubic foot ঘন ফ�ট gallon (Imperial) গ�যালন (ইম�পেরিয়াল) gallon (US) গ�যালন (মার�কিন) gill (Imperial) গিল (ইম�পেরিয়াল) gill (US) গিল (মার�কিন) gradian গ�রেডিয়ান grain গ�রেইন gram গ�রাম Hartley হার�টলি Hartree energy unit হার�ট�রি শক�তি �কক horsepower অশ�বশক�তি inch ইঞ�চি square inch বর�গ ইঞ�চি cubic inch ঘন ইঞ�চি karat ক�যারাট knot নট lightminute আলোক-মিনিট lightsecond আলোক-সেকেন�ড lightyear আলোকবর�ষ long ton লং টন mile মাইল square mile বর�গ মাইল cubic mile ঘন মাইল mile per hour মাইল প�রতি ঘণ�টা kilometre per hour কিলোমিটার প�রতি ঘণ�টা nautical mile সাম�দ�রিক মাইল ounce আউন�স parsec পারসেক pint (Imperial) পাইন�ট (ইম�পেরিয়াল) pint (US) পাইন�ট (মার�কিন) pound পাউন�ড pounds per square inch প�রতি বর�গ ইঞ�চিতে পাউন�ড quart (Imperial) কোয়ার�ট (ইম�পেরিয়াল) quart (US) কোয়ার�ট (মার�কিন) oil barrel তেল ব�যারেল beer barrel (US) বিয়ার ব�যারেল (মার�কিন) square yard বর�গ গজ cubic yard ঘন গজ short ton শর�ট টন tablespoon টেবিল চামচ tablespoon (Australian) টেবিল চামচ (অস�ট�রেলীয়) tablespoon (Imperial) টেবিল চামচ (ইম�পেরিয়াল) tablespoon (US) টেবিল চামচ (মার�কিন) dessert spoon ডেজার�ট চামচ teaspoon চা চামচ teaspoon (Imperial) চা চামচ (ইম�পেরিয়াল) teaspoon (US) চা চামচ (মার�কিন) turn টার�ন revolution আবর�তন revolution per minute প�রতি মিনিটে আবর�তন week সপ�তাহ kilowatt hour কিলোওয়াট ঘণ�টা millimetre of mercury পারদের মিলিমিটার yard গজ Julian century জ�লীয় শতাব�দী Julian year জ�লীয় বছর sidereal year নাক�ষত�রিক বছর tropical year ক�রান�তীয় বছর Evaluator cannot operate on a NaN NaN-�র উপর ক�রিয়া চালানো যায় না underflow - tiny result is out of SpeedCrunch's number range আন�ডারফ�লো - অত�যন�ত ছোট ফলাফল SpeedCrunch-�র সংখ�যার পরিসরের বাইরে overflow - huge result is out of SpeedCrunch's number range ওভারফ�লো - অত�যন�ত বড় ফলাফল SpeedCrunch-�র সংখ�যার পরিসরের বাইরে division by zero শূন�য দ�বারা ভাগ overflow - logic result exceeds maximum of 256 bits ওভারফ�লো - লজিক ফলাফল 256 বিটের সর�বোচ�চ সীমা ছাড়িয়েছে overflow - integer result exceeds maximum limit for integers ওভারফ�লো - পূর�ণসংখ�যার ফলাফল পূর�ণসংখ�যার সর�বোচ�চ সীমা ছাড়িয়েছে too time consuming - computation was rejected অতিরিক�ত সময়সাপেক�ষ - গণনা বাতিল করা হয়েছে dimension mismatch - quantities with different dimensions cannot be compared, added, etc. মাত�রা অসামঞ�জস�য - ভিন�ন মাত�রার রাশি ত�লনা, যোগ ইত�যাদি করা যায় না। invalid dimension - operation might require dimensionless arguments অবৈধ মাত�রা - �ই ক�রিয়ায় মাত�রাহীন আর�গ�মেন�ট লাগতে পারে operation is not defined for these arguments �ই আর�গ�মেন�টগ�লির জন�য অপারেশন সংজ�ঞায়িত নয় Computation aborted - encountered numerical instability গণনা বাতিল - সংখ�যাগত অস�থিতিশীলতা পাওয়া গেছে wrong number of arguments আর�গ�মেন�টের সংখ�যা ভ�ল does not take NaN as an argument NaN-কে আর�গ�মেন�ট হিসেবে নেয় না result out of range ফলাফল পরিসরের বাইরে undefined for argument domain �ই আর�গ�মেন�ট ডোমেইনের জন�য সংজ�ঞায়িত নয় computation too expensive গণনা অতিরিক�ত ব�যয়বহ�ল invalid dimension - function might require dimensionless arguments অবৈধ মাত�রা - ফাংশনে মাত�রাহীন আর�গ�মেন�ট লাগতে পারে internal error, please report a bug অভ�যন�তরীণ ত�র�টি, অন�গ�রহ করে বাগ রিপোর�ট কর�ন error ত�র�টি invalid expression অবৈধ অভিব�যক�তি syntax error সিনট�যাক�স ত�র�টি conversion target must be a unit রূপান�তরের লক�ষ�য অবশ�যই �কটি �কক হতে হবে unit must not be zero �কক শূন�য হতে পারবে না Conversion failed - dimension mismatch রূপান�তর ব�যর�থ - মাত�রা অসামঞ�জস�য unknown function or variable অজানা ফাংশন বা ভেরিয়েবল unknown unit অজানা �কক recursion not supported রিকারশন সমর�থিত নয় %1 is a reserved name, please choose another %1 �কটি সংরক�ষিত নাম, অন�গ�রহ করে অন�যটি বেছে নিন %1 is a global user definition and cannot be overridden in this session. %1 �কটি বৈশ�বিক ব�যবহারকারী সংজ�ঞা �বং �ই সেশনে ওভাররাইড করা যাবে না। %1 is a variable name, please choose another or delete the variable %1 �কটি ভেরিয়েবলের নাম, অন�গ�রহ করে অন�যটি বেছে নিন অথবা ভেরিয়েবলটি ম�ছে দিন argument %1 is used more than once আর�গ�মেন�ট %1 �কাধিকবার ব�যবহার করা হয়েছে %1 is a built-in unit name, please choose another %1 �কটি অন�তর�নির�মিত �ককের নাম, অন�গ�রহ করে অন�যটি বেছে নিন %1 is a user function name, please choose another or delete the function %1 �কটি ব�যবহারকারী ফাংশনের নাম, অন�গ�রহ করে অন�যটি বেছে নিন অথবা ফাংশনটি ম�ছে দিন FunctionRepo max; trials; probability সর�বোচ�চ; ট�রায়াল; সম�ভাব�যতা trials; probability ট�রায়াল; সম�ভাব�যতা hits; trials; probability হিট; ট�রায়াল; সম�ভাব�যতা unix_timestamp; x hours offset to GMT unix_timestamp; GMT থেকে x ঘণ�টার অফসেট max; total; hits; trials সর�বোচ�চ; মোট; হিট; ট�রায়াল total; hits; trials মোট; হিট; ট�রায়াল count; total; hits; trials গণনা; মোট; হিট; ট�রায়াল dividend; divisor ভাজ�য; ভাজক x; exponent_bits; significand_bits [; exponent_bias] x; সূচক_বিট; তাৎপর�যাংশ_বিট [; সূচক_বায়াস] base; x ভিত�তি; x value; modulo মান; মড�লো base; exponent; modulo ভিত�তি; সূচক; মড�লো events; average_events ঘটনা; গড়_ঘটনা average_events গড়_ঘটনা x [; precision] x [; নির�ভ�লতা] Absolute Value পরম মান Absolute Deviation পরম বিচ�য�তি Arc Cosine আর�ক কোসাইন Logical AND লজিক�যাল AND Area Hyperbolic Cosine �रिया হাইপারবোলিক কোসাইন Area Hyperbolic Sine �रिया হাইপারবোলিক সাইন Area Hyperbolic Tangent �रिया হাইপারবোলিক ট�যানজেন�ট Arc Sine আর�ক সাইন Arc Tangent আর�ক ট�যানজেন�ট Arc Tangent with two Arguments দ�টি আর�গ�মেন�টসহ আর�ক ট�যানজেন�ট Average (Arithmetic Mean) গড় (পাটিগণিতিক মধ�যমান) Convert to Binary Representation বাইনারি রূপে রূপান�তর Binomial Cumulative Distribution Function দ�বিপদী সঞ�চিত বণ�টন ফাংশন Binomial Distribution Mean দ�বিপদী বণ�টনের গড় Binomial Probability Mass Function দ�বিপদী সম�ভাব�যতা ভর ফাংশন Binomial Distribution Variance দ�বিপদী বণ�টনের বিচরণ Cube Root ঘনমূল Complex Conjugate জটিল সহয�গ�ম Cosine কোসাইন Hyperbolic Cosine হাইপারবোলিক কোসাইন Cotangent কোট�যানজেন�ট Cosecant কোসেক�যান�ট Convert Unix timestamp to Date Unix timestamp থেকে তারিখে রূপান�তর Convert to Decimal Representation দশমিক রূপে রূপান�তর Degrees of Arc আর�কের ডিগ�রি Error Function ত�র�টি ফাংশন Complementary Error Function পরিপূরক ত�র�টি ফাংশন Exponential সূচকীয় Arithmetic পাটিগণিত Chemistry রসায়ন Complex জটিল Combinatorics সমাবেশতত�ত�ব Probability সম�ভাবনা Statistics পরিসংখ�যান Aggregation সমষ�টিকরণ Random র�যান�ডম Base conversion ভিত�তি রূপান�তর Number formatting সংখ�যা বিন�যাস Integer arithmetic পূর�ণসংখ�যা পাটিগণিত Special functions বিশেষ ফাংশন Exponential & Logarithmic সূচকীয় ও লগারিদমিক Angle conversion কোণ রূপান�তর Trigonometry ত�রিকোণমিতি Bitwise বিটভিত�তিক Floating point ফ�লোটিং পয়েন�ট Date & Time তারিখ ও সময় Linear algebra রৈখিক বীজগণিত yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; GMT থেকে x ঘণ�টা অফসেট [digits] [অঙ�ক] max [; min] সর�বোচ�চ [; সর�বনিম�ন] List Literal তালিকা লিটারাল Convert to Padded Binary Representation শূন�য-পূরণ করা বাইনারি রূপে রূপান�তর Round Toward +∞ (Ceiling) +∞-�র দিকে রাউন�ড (সিলিং) Cosine plus Imaginary Sine কোসাইন যোগ কাল�পনিক সাইন Convert to Cis Complex Form �তে রূপান�তর কর�ন: Cis জটিল রূপ Matrix Column Count ম�যাট�রিক�সের কলাম সংখ�যা Population Correlation Matrix (n) জনসংখ�যা সহসম�পর�ক ম�যাট�রিক�স (n) Sample Correlation Matrix (n-1) নম�না সহসম�পর�ক ম�যাট�রিক�স (n-1) Count গণনা Population Covariance Matrix (n) জনসংখ�যা সহভেদাঙ�ক ম�যাট�রিক�স (n) Sample Covariance Matrix (n-1) নম�না সহভেদাঙ�ক ম�যাট�রিক�স (n-1) Cross Product ক�রস গ�ণন Convert Date to Unix timestamp তারিখকে Unix টাইমস�ট�যাম�পে রূপান�তর Determinant নির�ণায়ক Convert to Sexagesimal Notation ষাটভিত�তিক নোটেশনে রূপান�তর Dot Product ডট গ�ণন Convert to Engineering Notation ইঞ�জিনিয়ারিং নোটেশনে রূপান�তর Convert to Exponential Complex Form সূচকীয় জটিল রূপে রূপান�তর Round Toward −∞ (Floor) −∞-�র দিকে রাউন�ড (ফ�লোর) Flatten Matrix ম�যাট�রিক�স সমতল কর�ন Fractional Part ভগ�নাংশ অংশ Extension of Factorials [= (x-1)!] ফ�যাক�টোরিয়ালের সম�প�রসারণ [= (x-1)!] Greatest Common Divisor সর�বাধিক সাধারণ গ�ণনীয়ক Least Common Multiple লঘিষ�ঠ সাধারণ গ�ণিতক Geometric Mean জ�যামিতিক গড় Gradians of arc আর�কের গ�রেডিয়ান Convert to Hexadecimal Representation হেক�সাডেসিমাল রূপে রূপান�তর Convert to Padded Hexadecimal Representation শূন�য-পূরণ করা হেক�সাডেসিমাল রূপে রূপান�তর Hypergeometric Cumulative Distribution Function হাইপারজ�যামিতিক সঞ�চিত বণ�টন ফাংশন Hypergeometric Distribution Mean হাইপারজ�যামিতিক বণ�টনের গড় Hypergeometric Probability Mass Function হাইপারজ�যামিতিক সম�ভাব�যতা ভর ফাংশন Hypergeometric Distribution Variance হাইপারজ�যামিতিক বণ�টনের বিচরণ Integer Quotient পূর�ণসংখ�যা ভাগফল Integer Part পূর�ণসংখ�যা অংশ Imaginary Part কাল�পনিক অংশ Inverse Matrix বিপরীত ম�যাট�রিক�স Decode IEEE-754 Binary Value IEEE-754 বাইনারি মান ডিকোড Encode IEEE-754 Binary Value IEEE-754 বাইনারি মান �নকোড Decode 16-bit Half-Precision Value 16-বিট হাফ-প�রিসিশন মান ডিকোড Encode 16-bit Half-Precision Value 16-বিট হাফ-প�রিসিশন মান �নকোড Decode 32-bit Single-Precision Value 32-বিট সিঙ�গেল-প�রিসিশন মান ডিকোড Encode 32-bit Single-Precision Value 32-বিট সিঙ�গেল-প�রিসিশন মান �নকোড Decode 64-bit Double-Precision Value 64-বিট ডাবল-প�রিসিশন মান ডিকোড Encode 64-bit Double-Precision Value 64-বিট ডাবল-প�রিসিশন মান �নকোড Decode 128-bit Quad-Precision Value 128-বিট কোয়াড-প�রিসিশন মান ডিকোড Encode 128-bit Quad-Precision Value 128-বিট কোয়াড-প�রিসিশন মান �নকোড Round to 16-bit Half-Precision Value 16-বিট হাফ-প�রিসিশন মানে রাউন�ড Round to 32-bit Single-Precision Value 32-বিট সিঙ�গেল-প�রিসিশন মানে রাউন�ড Round to 64-bit Double-Precision Value 64-বিট ডাবল-প�রিসিশন মানে রাউন�ড Round to 128-bit Quad-Precision Value 128-বিট কোয়াড-প�রিসিশন মানে রাউন�ড Residual from 16-bit Half-Precision Rounding 16-বিট হাফ-প�রিসিশন রাউন�ডিং থেকে অবশিষ�ট Residual from 32-bit Single-Precision Rounding 32-বিট সিঙ�গেল-প�রিসিশন রাউন�ডিং থেকে অবশিষ�ট Residual from 64-bit Double-Precision Rounding 64-বিট ডাবল-প�রিসিশন রাউন�ডিং থেকে অবশিষ�ট Residual from 128-bit Quad-Precision Rounding 128-বিট কোয়াড-প�রিসিশন রাউন�ডিং থেকে অবশিষ�ট Binary Logarithm বাইনারি লগারিদম Common Logarithm সাধারণ লগারিদম Natural Logarithm প�রাকৃতিক লগারিদম Substance Mass পদার�থের ভর Molarity মোলারতা Molar Mass মোলার ভর Logarithm to Arbitrary Base ইচ�ছেমতো ভিত�তিতে লগারিদম Median Absolute Deviation মধ�যক পরম বিচ�য�তি Mask to a bit size নির�দিষ�ট বিট-আকারে মাস�ক Maximum সর�বাধিক Median Value (50th Percentile) মধ�যক মান (50তম পার�সেন�টাইল) Mean গড় Minimum সর�বনিম�ন Numerical Value of Quantity রাশির সাংখ�যিক মান Random Decimal Number র�যান�ডম দশমিক সংখ�যা Random Integer Number র�যান�ডম পূর�ণসংখ�যা Convert to Rational Representation মূলদ রূপে রূপান�তর Modulo মড�লো Euclidean Modulo ইউক�লিডীয় মড�লো Modular Exponentiation মড�লার সূচকীয় Combination (Binomial Coefficient) সমাবেশ (দ�বিপদী সহগ) Logical NOT লজিক�যাল NOT Permutation (Arrangement) বিন�যাস (সজ�জা) Convert to Octal Representation অক�টাল রূপে রূপান�তর Convert to Padded Octal Representation শূন�য-পূরণ করা অক�টাল রূপে রূপান�তর Vector or Matrix Norm ভেক�টর বা ম�যাট�রিক�স নর�ম Logical OR লজিক�যাল OR Population Count (Hamming Weight) বিট গণনা (হ�যামিং ওজন) Phase of Complex Number জটিল সংখ�যার ফেজ Poissonian Cumulative Distribution Function পয়সন সঞ�চিত বণ�টন ফাংশন Poissonian Distribution Mean পয়সন বণ�টনের গড় Poissonian Probability Mass Function পয়সন সম�ভাব�যতা ভর ফাংশন Poissonian Distribution Variance পয়সন বণ�টনের বিচরণ Convert to Phasor Complex Form ফেজর জটিল রূপে রূপান�তর Convert to Rectangular Complex Form আয়তাকার জটিল রূপে রূপান�তর Round Half Away from Zero শূন�য থেকে দূরে অর�ধেক রাউন�ড Round Half Even অর�ধেক জোড় রাউন�ড Nth Root n-তম মূল Convert to Scientific Notation বৈজ�ঞানিক নোটেশনে রূপান�তর Matrix Row Count ম�যাট�রিক�সের সারি সংখ�যা List or Matrix Shape তালিকা বা ম�যাট�রিক�সের আকার Summation সমষ�টি Population Standard Deviation (n) জনসংখ�যার মানক বিচ�য�তি (n) Sample Standard Deviation (n-1) নম�নার মানক বিচ�য�তি (n-1) Round Toward Zero (Truncation) শূন�যের দিকে রাউন�ড (ট�রাঙ�কেশন) Matrix Trace ম�যাট�রিক�স ট�রেস Transpose Matrix ম�যাট�রিক�স ট�রান�সপোজ Population Variance (n) জনসংখ�যা ভ�যারিয়েন�স (n) Sample Variance (n-1) নম�না ভ�যারিয়েন�স (n-1) Product গ�ণফল Radians রেডিয়ান Matrix Rank ম�যাট�রিক�স র�যাঙ�ক Real Part বাস�তব অংশ Secant সেক�যান�ট Arithmetic Shift Left অ�যারিথমেটিক বাম শিফট Arithmetic Shift Right অ�যারিথমেটিক ডান শিফট Signum সাইনাম Sine সাইন Hyperbolic Sine হাইপারবোলিক সাইন Square Root বর�গমূল Sum যোগফল Tangent ট�যানজেন�ট Convert to Trigonometric Complex Form ত�রিকোণমিতিক জটিল রূপে রূপান�তর Turns টার�ন Hyperbolic Tangent হাইপারবোলিক ট�যানজেন�ট Sign-extend a value �কটি মানে চিহ�ন-প�রসারণ Logical XOR লজিক�যাল XOR FunctionsWidget Domain ক�ষেত�র All সব Identifier সনাক�তকারী Name নাম Search অন�সন�ধান No match found কোনও মিল পাওয়া যায়নি HistoryWidget Remove All Calculations Above উপরের সব গণনা সরান Remove This Calculation �ই গণনাটি সরান Remove All Calculations Below নিচের সব গণনা সরান Keypad Inverse cosine বিপরীত কোসাইন The last result সর�বশেষ ফলাফল Inverse sine বিপরীত সাইন Inverse tangent বিপরীত ট�যানজেন�ট Evaluate expression �ক�সপ�রেশন মূল�যায়ন কর�ন Division ভাগ Multiplication গ�ণ Subtraction বিয়োগ Addition যোগ Clear expression অভিব�যক�তি পরিষ�কার কর�ন Cosine কোসাইন Backspace ব�যাকস�পেস Scientific notation বৈজ�ঞানিক সংকেত Exponential সূচকীয় Factorial ফ�যাক�টোরিয়াল Natural logarithm প�রাকৃতিক লগারিদম Left parenthesis বাম বন�ধনী Nth root n-তম মূল Argument separator আর�গ�মেন�ট বিভাজক Square বর�গ Common logarithm সাধারণ লগারিদম Modulo মড�লো Contextual percentage প�রাসঙ�গিক শতাংশ Power ঘাত Right parenthesis ডান বন�ধনী Sine সাইন Square root বর�গমূল Tangent ট�যানজেন�ট Pi পাই Decimal separator দশমিক বিভাজক MainWindow Radian রেডিয়ান Gradian গ�রেডিয়ান Degree ডিগ�রি Binary বাইনারি Octal অক�টাল Hexadecimal হেক�সাডেসিমাল Sexagesimal সেক�সাজেসিমাল Engineering decimal ইঞ�জিনিয়ারিং দশমিক Scientific decimal বৈজ�ঞানিক দশমিক Plain &text সাধারণ &পাঠ�য &Import... &আমদানি... &Quit &প�রস�থান Clear E&xpression অ&ভিব�যক�তি পরিষ�কার কর�ন Clear &History &ইতিহাস পরিষ�কার কর�ন &Copy &কপি &Paste &পেস�ট &Select Expression &অভিব�যক�তি নির�বাচন কর�ন &Constants &ধ�র�বকসমূহ &Functions &ফাংশনসমূহ &History &ইতিহাস &Keypad &কীপ�যাড Formula &Book সূত�র &বই New &Private Tab &নত�ন ব�যক�তিগত ট�যাব Keep রাখ�ন Make Private... ব�যক�তিগত কর�ন... &Rename... না&ম বদলান... Clo&ne... প�র&তিলিপি তৈরি... &Close Tab ট�&যাব বন�ধ কর�ন Reopen Clo&sed Tab &বন�ধ ট�যাব আবার খ�ল�ন &Undo পূ&র�বাবস�থায় ফেরান &Redo &আবার কর�ন Cu&t কা&ট�ন Copy &Last Result &শেষ ফলাফল অন�লিপি কর�ন &Wrap in Parentheses &বন�ধনীতে আবদ�ধ কর�ন Full Scr&een Mode পূর�&ণ পর�দা মোড &Status Bar &স�ট�যাটাস বার Bitfield বিটফিল�ড &Left &বামে &Right &ডানে &Up &উপরে &Down &নিচে Close Pa&ne &প�যান বন�ধ কর�ন Use&r Functions ব�যবহা&রকারী ফাংশন &Degree &ডিগ�রি &Radian &রেডিয়ান &Gradian &গ�রেডিয়ান Re&volution &আবর�তন Always on &Top সবসময় &উপরে Auto-Insert a&ns স�বয়ংক�রিয়ভাবে a&ns ঢোকান Automatic &Completion স�বয়ংক�রিয় &সম�পূর�ণতা &Built-in Functions &অন�তর�নির�মিত ফাংশন Built-in &Variables অ&ন�তর�নির�মিত চলক User &Functions &ব�যবহারকারী ফাংশনসমূহ User Va&riables ব�&যবহারকারী চলক Open a Private Tab on Startup শ�র�তে ব�যক�তিগত ট�যাব খ�ল�ন Open and focus a new private tab whenever SpeedCrunch starts. SpeedCrunch প�রতিবার চাল� হলে নত�ন ব�যক�তিগত ট�যাব খ�ল�ন �বং তাতে ফোকাস কর�ন। Syntax &Highlighting সিনট�যাক�স &হাইলাইটিং Group Digits in &Input &ইনপ�টের অঙ�ক গ�চ�ছবদ�ধ কর�ন Automatic Input &Adjustments &স�বয়ংক�রিয় ইনপ�ট সমন�বয় Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. অপারেটর, ফা�ক, বন�ধনী ও ঘাত স�বয়ংক�রিয়ভাবে সমন�বয় কর�ন �বং কেবল বৈধ অক�ষর ইনপ�ট করতে দিন। Group input digits using the selected number format. নির�বাচিত সংখ�যা বিন�যাস অন�যায়ী ইনপ�টের অঙ�ক গ�চ�ছবদ�ধ কর�ন। &Blinking Cursor &�লকানো কার�সর Blink the cursor in the expression editor. রাশির সম�পাদকে কার�সর �লকাতে দিন। &Escape Clears Editor &Escape সম�পাদক খালি করে Clear the focused expression editor with Escape after dismissing any popup or preview. পপআপ বা পূর�বরূপ বন�ধ করার পর Escape দিয়ে ফোকাস করা রাশির সম�পাদক খালি কর�ন। Disabled নিষ�ক�রিয় Small Space ছোট ফা�ক Medium Space মা�ারি ফা�ক Large Space বড় ফা�ক Keep Expression After Evaluation হিসাবের পর রাশি রাখ�ন Copy New Results Automatically নত�ন ফলাফল স�বয়ংক�রিয়ভাবে অন�লিপি কর�ন &Comma &কমা &System Default &সিস�টেম ডিফল�ট &Dot &ডট Dot &And Comma ডট &�বং কমা &0 Digits &0 অঙ�ক &15 Digits &15 অঙ�ক &2 Digits &2 অঙ�ক &3 Digits &3 অঙ�ক &50 Digits &50 অঙ�ক &8 Digits &8 অঙ�ক Toward +∞ (&ceil) +∞-�র দিকে (&ceil) Toward −∞ (&floor) −∞-�র দিকে (&floor) &Automatic &স�বয়ংক�রিয় &Engineering &ইঞ�জিনিয়ারিং &Scientific &বৈজ�ঞানিক &Binary &বাইনারি &Octal &অক�টাল &Hexadecimal &হেক�সাডেসিমাল &Sexagesimal &সেক�সাজেসিমাল &Font... &ফন�ট... Reset All Settings... সব সেটিং প�নরায় নির�ধারণ... &System &সিস�টেম SpeedCrunch &Theme &SpeedCrunch থিম &Classic &ধ�র�পদি &Modern &আধ�নিক &Language... &ভাষা... User &Manual ব�যবহারকারী &ম�যান�য়াল Context Help প�রসঙ�গভিত�তিক সাহায�য Issues and &Feedback &সমস�যা ও মতামত &Donate &অন�দান দিন Editor and Results Font সম�পাদক ও ফলাফলের ফন�ট &Session &সেশন &Export &রপ�তানি &Edit &সম�পাদনা &View &দেখ�ন S&plit &ভাগ কর�ন Se&ttings সে&টিংস &Decimal &দশমিক &Precision &নির�ভ�লতা Angle &Mode &কোণ মোড &Complex Form &জটিল সংখ�যার রূপ &Help &সহায়তা New Tab নত�ন ট�যাব Constants ধ�র�বকসমূহ Functions ফাংশনসমূহ History ইতিহাস User Functions ব�যবহারকারী ফাংশনসমূহ Error ত�র�টি Can't read from file %1 ফাইল %1 থেকে পড়া যাচ�ছে না Can't write to file %1 ফাইল %1-� লেখা যাচ�ছে না Import Session সেশন আমদানি কর�ন Close Session সেশন বন�ধ কর�ন Angle Mode: কোণ মোড: Notation: নোটেশন: Precision: নির�ভ�লতা: Turn টার�ন Revolution আবর�তন Fixed-point decimal স�থির-বিন�দ� দশমিক Rational মূলদ Automatic decimal স�বয়ংক�রিয় দশমিক Automatic স�বয়ংক�রিয় User &Definitions... ব�যবহারকারী &সংজ�ঞা... New &Tab নত�ন &ট�যাব New &Window নত�ন &উইন�ডো &Open... &খ�ল�ন... Open Sessions &Folder সেশন &ফোল�ডার খ�ল�ন &Basic &মৌলিক &Scientific (wide) &বৈজ�ঞানিক (প�রশস�ত) Scientific (narrow) বৈজ�ঞানিক (সংকীর�ণ) &Custom... &কাস�টম... Main &Menu প�রধান &মেন� User &Variables ব�যবহারকারী &চলক User &Units ব�যবহারকারী &�কক &Turn &টার�ন If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. নত�ন �ক�সপ�রেশন +, -, *, বা / দিয়ে শ�র� হলে, SpeedCrunch প�রথমে "ans" ঢোকায়। &Accept with Enter &Enter দিয়ে গ�রহণ কর�ন Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. প�রথমে তীরচিহ�নের কীগ�লি দিয়ে নির�বাচন না করেই Enter দিয়ে স�বয়ংক�রিয় পূরণের বর�তমান প�রস�তাবটি গ�রহণ কর�ন। &Units &�কক Show Live Result &Preview লাইভ ফলাফলের &পূর�বরূপ দেখান Save &Window Position on Exit প�রস�থানকালে &উইন�ডোর অবস�থান সংরক�ষণ কর�ন Hover Highlighting হোভার হাইলাইটিং Group Integer Part Only শ�ধ� পূর�ণসংখ�যা অংশ গ�র�প কর�ন Number Format... সংখ�যা বিন�যাস... Notation && Precision... নোটেশন && নির�ভ�লতা... After pressing Enter, keep the entered expression selected in the editor. Enter চাপার পর প�রবেশ করানো �ক�সপ�রেশনটি �ডিটরে নির�বাচিত রাখ�ন। Never কখনও নয় Always সবসময় Only for Single-Line Expressions শ�ধ� �ক-লাইন �ক�সপ�রেশনের জন�য Simplify Displayed Expressions প�রদর�শিত �ক�সপ�রেশন সরলীকরণ কর�ন History Size &Limit... ইতিহাস আকারের &সীমা... Remove Trailing &Zeroes &শেষের শূন�য সরান Nearest, Half &Away (round) নিকটতম, অর�ধেক &দূরে (round) Nearest, Half &Even (roundeven) নিকটতম, অর�ধেক &জোড় (roundeven) Toward &Zero (trunc) &শূন�যের দিকে (trunc) &Fixed-Point &স�থির-বিন�দ� &Rational &মূলদ &Exponential (m·s�¹) &সূচকীয় (m·s�¹) &Fractional (m/s) &ভগ�নাংশীয় (m/s) &Rectangular (a + bi) &আয়তাকার (a + bi) Exponential (re�ᶿ) সূচকীয় (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) ত�রিকোণমিতিক (r(cos θ + i·sin θ)) Phasor (r∠θ) ফেজর (r∠θ) &Theme... &থিম... Check for &Updates &আপডেট পরীক�ষা কর�ন Source Code সোর�স কোড &Zoom &জ�ম &Results &ফলাফল Unit Notation �কক নোটেশন Rounding Mode রাউন�ডিং মোড &Notation &নোটেশন &Imaginary Unit &কাল�পনিক �কক &Window &উইন�ডো &Editing &সম�পাদনা A&utocomplete স�বয়ংসম�পূ&রণ Up/Down Arrow History উপর/নিচ তীর ইতিহাস &Appearance &চেহারা &Menus &মেন� &Docks &ডকযোগ�য প�যানেল &Input and Results &ইনপ�ট ও ফলাফল &Disabled &নিষ�ক�রিয় &Disable &নিষ�ক�রিয় কর�ন Close preview প�রিভিউ বন�ধ কর�ন Rename... নাম বদলান... Clone... প�রতিলিপি তৈরি... Close Tab ট�যাব বন�ধ কর�ন New Private Tab নত�ন ব�যক�তিগত ট�যাব Open... খ�ল�ন... Reopen Closed Tab বন�ধ ট�যাব আবার খ�ল�ন Split ভাগ কর�ন Left বামে Right ডানে Up উপরে Down নিচে Clear খালি কর�ন Delete ম�ছ�ন %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 ব�যক�তিগত সেশন: বন�ধ করলে �র বিষয়বস�ত� ফেলে দেওয়া হয়। সাধারণ সেশনে রূপান�তর করতে সেশন > রাখ�ন বেছে নিন। SpeedCrunch - %1 [Private] SpeedCrunch - %1 [ব�যক�তিগত] Reset All Settings সব সেটিং প�নরায় নির�ধারণ Reset all settings to their default values? সব সেটিং কি পূর�বনির�ধারিত মানে ফিরিয়ে আনবেন? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. �র মধ�যে চেহারা, সম�পাদনা, ফলাফলের বিন�যাস ও উইন�ডোর পছন�দ অন�তর�ভ�ক�ত। আপনার হিসাব, খোলা সেশন ও ব�যবহারকারীর সংজ�ঞাগ�লি রাখা হবে। The settings file could not be written. সেটিংস ফাইল লেখা যায়নি। Clear this session's calculations, unfinished expression, variables, functions, and units? �ই সেশনের হিসাব, অসমাপ�ত রাশি, চলক, ফাংশন ও �কক ম�ছে ফেলবেন? Global user definitions are kept. সার�বিক ব�যবহারকারীর সংজ�ঞাগ�লি রাখা হয়। Make Session Private সেশন ব�যক�তিগত কর�ন The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. সংরক�ষিত সেশন %1 ম�ছে ফেলা হবে। �র বিষয়বস�ত� ব�যক�তিগত সেশনে খোলা থাকবে �বং সেই সেশন বন�ধ করলে বা SpeedCrunch থেকে বের হলে ফেলে দেওয়া হবে। Make Private ব�যক�তিগত কর�ন Could not delete the saved session %1. সংরক�ষিত সেশন %1 ম�ছে ফেলা যায়নি। Keep Session সেশন রাখ�ন Could not save the session. It remains private. সেশন সংরক�ষণ করা যায়নি। �টি ব�যক�তিগতই রয়ে গেছে। Clone Session সেশনের প�রতিলিপি তৈরি Could not save session file %1. সেশন ফাইল %1 সংরক�ষণ করা যায়নি। Could not delete session file %1. সেশন ফাইল %1 ম�ছে ফেলা যায়নি। JSON file (*.json);;Any file (*.*) JSON ফাইল (*.json);;যেকোনো ফাইল (*.*) Export session as JSON সেশন JSON হিসেবে রপ�তানি কর�ন The selected file is not valid JSON: %1 নির�বাচিত ফাইলটি বৈধ JSON নয়: %1 The selected file is not a SpeedCrunch session JSON file. নির�বাচিত ফাইলটি SpeedCrunch সেশনের JSON ফাইল নয়। This file uses an obsolete SpeedCrunch session format and cannot be imported. �ই ফাইলটি প�রোনো SpeedCrunch সেশন ফরম�যাট ব�যবহার করে �বং আমদানি করা যাবে না। The selected JSON file is missing the required $schema field. নির�বাচিত JSON ফাইলে প�রয়োজনীয় $schema ক�ষেত�র নেই। The selected JSON file uses an unsupported JSON schema: %1 নির�বাচিত JSON ফাইলটি অসমর�থিত JSON স�কিমা ব�যবহার করে: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). নির�বাচিত JSON ফাইলে SpeedCrunch সেশন স�কিমা শনাক�তকারী ($id) নেই। The selected JSON file uses an unsupported SpeedCrunch session format: %1 নির�বাচিত JSON ফাইলটি অসমর�থিত SpeedCrunch সেশন ফরম�যাট ব�যবহার করে: %1 The selected JSON file is missing the required session name. নির�বাচিত JSON ফাইলে প�রয়োজনীয় সেশনের নাম নেই। The selected JSON file has an empty session name. নির�বাচিত JSON ফাইলে সেশনের নাম খালি। The selected JSON file has invalid or incomplete SpeedCrunch session data. নির�বাচিত JSON ফাইলে অবৈধ বা অসম�পূর�ণ SpeedCrunch সেশন ডেটা আছে। Open Sessions Folder সেশন ফোল�ডার খ�ল�ন Could not create the sessions folder: %1 সেশন ফোল�ডার তৈরি করা যায়নি: %1 Could not open the sessions folder: %1 সেশন ফোল�ডার খোলা যায়নি: %1 Open Session সেশন খ�ল�ন Community সম�প�রদায় Rename Session সেশনের নাম বদলান Clear Session সেশন পরিষ�কার কর�ন Delete Session সেশন ম�ছ�ন Close Pane প�যান বন�ধ কর�ন &About SpeedCrunch স�&পিডক�রাঞ�চ সম�পর�কে App Diag&nostics অ�&যাপের রোগনির�ণয় User Variables ব�যবহারকারী চলক User Units ব�যবহারকারী �কক Clear History ইতিহাস পরিষ�কার কর�ন Are you sure you want to clear the calculation history? আপনি কি গণনার ইতিহাস পরিষ�কার করতে নিশ�চিত? Session name: সেশনের নাম: A session named %1 already exists. %1 নামের �কটি সেশন ইতিমধ�যেই আছে। Could not create session file %1. সেশন ফাইল %1 তৈরি করা যায়নি। Could not write session file %1. সেশন ফাইল %1 লেখা যায়নি। Are you sure you want to delete this session? আপনি কি �ই সেশন ম�ছতে নিশ�চিত? Custom Precision কাস�টম নির�ভ�লতা Fractional digits: ভগ�নাংশ অঙ�ক: Theme থিম Light Themes হালকা থিম Dark Themes গাঢ় থিম Preview প�রিভিউ Colors রং Select color for %1 %1-�র জন�য রং নির�বাচন কর�ন Import... আমদানি... Export... রপ�তানি... Import Theme থিম আমদানি Theme file (*.json);;All files (*) থিম ফাইল (*.json);;সব ফাইল (*) Invalid theme file. অবৈধ থিম ফাইল। Can't import theme "%1" because it conflicts with a built-in theme. থিম "%1" আমদানি করা যায়নি, কারণ �টি অন�তর�নির�মিত থিমের সাথে সংঘর�ষ করে। Can't find a writable theme folder. লেখারযোগ�য থিম ফোল�ডার খ��জে পাওয়া যায়নি। Overwrite Theme থিম ওভাররাইট কর�ন A custom theme named "%1" already exists. Do you want to overwrite it? "%1" নামের �কটি কাস�টম থিম ইতিমধ�যেই আছে। �টি ওভাররাইট করবেন? Can't overwrite theme file %1 থিম ফাইল %1 ওভাররাইট করা যায়নি Can't copy theme file to %1 থিম ফাইল %1-� কপি করা যায়নি Export Theme থিম রপ�তানি Can't export theme as "%1" because it conflicts with a built-in theme. থিম "%1" হিসেবে রপ�তানি করা যায়নি, কারণ �টি অন�তর�নির�মিত থিমের সাথে সংঘর�ষ করে। Global User Variable বৈশ�বিক ব�যবহারকারী চলক Global User Function বৈশ�বিক ব�যবহারকারী ফাংশন Global User Unit বৈশ�বিক ব�যবহারকারী �কক User Definitions ব�যবহারকারীর সংজ�ঞা These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. �ই সংজ�ঞাগ�লি বৈশ�বিক �বং প�রতিটি সেশনে লোড করা হয়। সেশন থেকে �গ�লি পরিবর�তন করা যায় না �বং সেশন সম�পাদকের �কই নামের সংজ�ঞার চেয়ে �গ�লি অগ�রাধিকার পায়। প�রতি লাইনে �কটি সংজ�ঞা লিখ�ন। Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] উদাহরণ: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply প�রয়োগ Validate যাচাই কর�ন Test Results পরীক�ষার ফলাফল Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 আমদানি করা চলক: %1 আমদানি করা ফাংশন: %2 আমদানি করা �কক: %3 ত�র�টিয�ক�ত লাইনের নম�বর: %4 none কোনোটি নেই Apply Results প�রয়োগের ফলাফল User definitions saved. ব�যবহারকারীর সংজ�ঞা সংরক�ষিত হয়েছে। History Size Limit ইতিহাস আকারের সীমা Maximum number of history entries for this session (0 = unlimited): �ই সেশনের জন�য ইতিহাস �ন�ট�রির সর�বোচ�চ সংখ�যা (0 = অসীম): Export session as HTML সেশন HTML হিসেবে রপ�তানি কর�ন HTML file (*.html) HTML ফাইল (*.html) Export session as plain text সেশন সাধারণ পাঠ�য হিসেবে রপ�তানি কর�ন Text file (*.txt);;Any file (*.*) পাঠ�য ফাইল (*.txt);;যেকোনো ফাইল (*.*) Could not recalculate from calculation %1: %2 গণনা %1 থেকে প�নর�গণনা করা যায়নি: %2 History Size Limit Reached ইতিহাস আকারের সীমা পৌ�ছেছে This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. �ই গণনাটি ইতিহাসের শেষ উপলব�ধ স�থান পূরণ করছে। ভবিষ�যতের গণনাগ�লি ইতিহাস থেকে সবচেয়ে প�রোনো গণনা সরিয়ে দেবে। সেশন > ইতিহাস আকারের সীমা থেকে সীমাটি বাড়াতে পারেন। Editing calculation. Press Esc twice to cancel. গণনা সম�পাদনা হচ�ছে। বাতিল করতে Esc দ�বার চাপ�ন। Calculation Settings গণনা সেটিংস Invalid recalculation start index অবৈধ প�নর�গণনা শ�র� সূচক System Default সিস�টেম ডিফল�ট Language ভাষা Select the language: ভাষা নির�বাচন কর�ন: Custom কাস�টম Decimal places: দশমিক স�থান: ManualWindow SpeedCrunch Manual SpeedCrunch ম�যান�য়াল %1 - SpeedCrunch Manual %1 - SpeedCrunch ম�যান�য়াল NumberFormatDialog Number Format সংখ�যা বিন�যাস <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>ফলাফল ও ইনপ�টের অঙ�ক গ�চ�ছবদ�ধ করার সংখ�যা বিন�যাস বেছে নিন।</b><br/><br/>দ�রষ�টব�য: ইনপ�ট সংখ�যার দ�ব�যর�থহীন বিন�যাস নির�বাচিত প�রদর�শন বিন�যাস থেকে ভিন�ন হলেও গ�রহণ করা হয়।<br/> QObject Global User Variable বৈশ�বিক ব�যবহারকারী চলক Global User Function বৈশ�বিক ব�যবহারকারী ফাংশন Global User Unit বৈশ�বিক ব�যবহারকারী �কক Backspace ব�যাকস�পেস Clear expression �ক�সপ�রেশন পরিষ�কার কর�ন Evaluate expression �ক�সপ�রেশন মূল�যায়ন কর�ন Insert text পাঠ�য সন�নিবেশ কর�ন Automatic decimal স�বয়ংক�রিয় দশমিক Fixed-point decimal স�থির-বিন�দ� দশমিক Engineering decimal প�রকৌশল দশমিক Scientific decimal বৈজ�ঞানিক দশমিক Rational মূলদ Binary বাইনারি Octal অক�টাল Hexadecimal হেক�সাডেসিমাল Sexagesimal ষাটভিত�তিক Update Available আপডেট উপলব�ধ A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> নত�ন সংস�করণ (%1) উপলব�ধ।<br/><a href="%2">ডাউনলোড করতে ওয়েবসাইটে যান।</a> Check for Updates আপডেট পরীক�ষা SpeedCrunch %1 is up to date. SpeedCrunch %1 হালনাগাদ আছে। No connectivity. Please check your internet connection and try again. সংযোগ নেই। অন�গ�রহ করে ইন�টারনেট সংযোগ পরীক�ষা করে আবার চেষ�টা কর�ন। Could not verify the latest available version. সর�বশেষ উপলব�ধ সংস�করণ যাচাই করা যায়নি। ResultDisplay Scroll to bottom নিচে স�ক�রল কর�ন Edit Expression �ক�সপ�রেশন সম�পাদনা কর�ন Change Settings সেটিংস পরিবর�তন কর�ন New Tab নত�ন ট�যাব &Import... &আমদানি... &Export &রপ�তানি Plain &text সাধারণ &পাঠ�য Copy কপি Selection নির�বাচিত অংশ Select All সব নির�বাচন কর�ন Expression রাশি Result ফলাফল Calculation হিসাব Calculation as Single Line �ক লাইনে হিসাব Remove সরান This Calculation �ই হিসাব All Calculations Above উপরের সব হিসাব All Calculations Below নিচের সব হিসাব New Private Tab নত�ন ব�যক�তিগত ট�যাব Session সেশন Open... খ�ল�ন... Clone... প�রতিলিপি তৈরি... Rename... নাম বদলান... Keep রাখ�ন Make Private... ব�যক�তিগত কর�ন... Clear খালি কর�ন Delete ম�ছ�ন Close বন�ধ কর�ন Split ভাগ কর�ন Left বামে Right ডানে Up উপরে Down নিচে Close Pane প�যান বন�ধ কর�ন Main Menu প�রধান মেন� Cancel editing সম�পাদনা বাতিল Copy result ফলাফল কপি কর�ন Edit expression �ক�সপ�রেশন সম�পাদনা কর�ন Change settings সেটিংস পরিবর�তন কর�ন Remove calculation গণনা সরান ResultSlotsDialog Notation & Precision নোটেশন ও নির�ভ�লতা Result Line ফলাফল লাইন Enabled সক�রিয় Notation নোটেশন Decimal Places দশমিক স�থান Main Line প�রধান লাইন Extra Line #1 অতিরিক�ত লাইন #১ Extra Line #2 অতিরিক�ত লাইন #২ Extra Line #3 অতিরিক�ত লাইন #৩ Extra Line #4 অতিরিক�ত লাইন #৪ Auto স�বয়ংক�রিয় UserFunctionListWidget Name নাম Value মান Description বিবরণ Search অন�সন�ধান No match found কোনও মিল পাওয়া যায়নি Insert সন�নিবেশ কর�ন Edit সম�পাদনা Delete ম�ছ�ন Delete All সব ম�ছ�ন UserUnitListWidget Name নাম Value মান Description বিবরণ Search অন�সন�ধান No match found কোনও মিল পাওয়া যায়নি Insert সন�নিবেশ Edit সম�পাদনা Delete ম�ছ�ন Delete All সব ম�ছ�ন VariableListWidget Name নাম Value মান Description বিবরণ Search অন�সন�ধান No match found কোনও মিল পাওয়া যায়নি Insert সন�নিবেশ কর�ন Edit সম�পাদনা Delete ম�ছ�ন Delete All সব ম�ছ�ন heldercorreia-speedcrunch-e7ca37f/src/resources/locale/ca.ts000066400000000000000000010561451526573132500243440ustar00rootroot00000000000000 AboutBox About SpeedCrunch Quant a SpeedCrunch Core developers Desenvolupadors principals Original author Autor original Close Tanca Math engine Motor matemàtic Main author | Logo | Maintainer Autor principal | Logotip | Mantenidor Thanks Agraïments Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Els desenvolupadors de SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Aquest programa és programari lliure; podeu redistribuir-lo i/o modificar-lo sota els termes de la Llicència Pública General de GNU publicada per la Free Software Foundation; ja sigui la versió 2 de la Llicència o, si ho preferiu, qualsevol versió posterior This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Aquest programa es distribueix amb l'esperança que sigui útil, però SENSE CAP GARANTIA; ni tan sols la garantia implícita de COMERCIABILITAT o ADEQUACIÓ A UN PROPÒSIT PARTICULAR. Consulteu la Llicència Pública General de GNU per a més detalls. BitFieldWidget Reset bits to zero Restableix els bits a zero Invert bits Inverteix els bits Shift bits left Desplaça els bits a l'esquerra Shift bits right Desplaça els bits a la dreta Book Index �ndex Algebra Àlgebra Quadratic Equation Equació quadràtica Logarithmic Base Conversion Conversió de base logarítmica Geometry Geometria Circle Cercle Sector Sector Sphere Esfera Cube Cub Cone Con Cylinder Cilindre Electronics Electrònica Ohm's Law Llei d'Ohm Power Potència Reactance Reactància Resonance Ressonància Radio Frequency Radiofreqüència Antennas Antenes Characteristic Impedance (coax) Impedància característica (coax) Velocity of Propagation (coax) Velocitat de propagació (coax) Standing Wave Ratio & Return Loss Relació d'ona estacionària i pèrdua de retorn Free Space Wavelength Longitud d'ona en l'espai lliure resistance resistència voltage voltatge current corrent power potència inductive reactance reactància inductiva capacitive reactance reactància capacitiva inductance inductància capacitance capacitància frequency freqüència resonance frequency freqüència de ressonància area àrea perimeter perímetre diameter diàmetre radius radi volume volum surface area àrea de la superfície height altura slant height apotema lateral face diagonal diagonal de la cara space diagonal diagonal espacial edge length longitud de l'aresta arc length longitud d'arc central angle (degrees) angle central (graus) input power potència d'entrada reflected power potència reflectida transmitted power potència transmesa return loss pèrdua de retorn dielectric constant constant dielèctrica outer conductor's inner diameter diàmetre interior del conductor exterior inner conductor's outer diameter diàmetre exterior del conductor interior speed of light velocitat de la llum reflection coefficient coeficient de reflexió standing wave ratio relació d'ona estacionària normalized impedance impedància normalitzada frequency (Hz) freqüència (Hz) BookDock Formula Book Llibre de fórmules ConstantCompletion Search constants Cerca constants No match found No s'han trobat coincidències Constants Mathematics Matemàtiques Physics (CODATA 2022) Física (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Química (IUPAC - CIAAW 2021) Uncategorized Sense categoria Universal Universal Physicochemical Fisicoquímica Atomic & Nuclear — General Atòmica i nuclear — General Atomic & Nuclear — Electroweak Atòmica i nuclear — Electrofeble Atomic & Nuclear — Electron Atòmica i nuclear — Electró Atomic & Nuclear — Muon Atòmica i nuclear — Muó Atomic & Nuclear — Tau Atòmica i nuclear — Tau Atomic & Nuclear — Proton Atòmica i nuclear — Protó Atomic & Nuclear — Neutron Atòmica i nuclear — Neutró Atomic & Nuclear — Deuteron Atòmica i nuclear — Deuteró Atomic & Nuclear — Triton Atòmica i nuclear — Tritó Atomic & Nuclear — Helion Atòmica i nuclear — Helió Atomic & Nuclear — Alpha particle Atòmica i nuclear — Partícula alfa Atomic & Nuclear — Atomic units Atòmica i nuclear — Unitats atòmiques Atomic & Nuclear — Energy conversion relationships Atòmica i nuclear — Relacions de conversió d'energia Atomic & Nuclear — X-ray units Atòmica i nuclear — Unitats de raigs X Atomic & Nuclear — Magnetic shielding corrections Atòmica i nuclear — Correccions d'apantallament magnètic Masses Masses Lifetimes Temps de vida Molar Masses Masses molars Electronegativity Electronegativitat Ionization Energy Energia d'ionització Nominal Constants (IAU 2015) Constants nominals (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Millors estimacions actuals (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) impedància característica del buit (Z₀) reduced Planck constant (�) constant de Planck reduïda (�) vacuum electric permittivity (ϵ₀) permitivitat elèctrica del buit (ϵ₀) Newtonian constant of gravitation (G) constant newtoniana de la gravitació (G) vacuum magnetic permeability (μ₀) permeabilitat magnètica del buit (μ₀) Planck constant (h) constant de Planck (h) speed of light in vacuum (c) velocitat de la llum en el buit (c) standard acceleration of gravity (gₙ) acceleració estàndard de la gravetat (gₙ) Newtonian constant of gravitation over h-bar c constant newtoniana de la gravitació dividida per h barra c Planck length longitud de Planck Planck constant in eV/Hz (h) constant de Planck en eV/Hz (h) Planck mass massa de Planck Planck mass energy equivalent in GeV equivalent energètic de la massa de Planck en GeV Planck temperature temperatura de Planck Planck time temps de Planck reduced Planck constant in eV·s (�) constant de Planck reduïda en eV·s (�) reduced Planck constant times c in MeV·fm constant de Planck reduïda multiplicat per c en MeV·fm Bohr magneton magnetó de Bohr conductance quantum (G₀) quant de conductància (G₀) Coulomb constant (kₑ) constant de Coulomb (kₑ) elementary charge (e) càrrega elemental (e) elementary charge over h-bar càrrega elemental dividida per h barra conventional value of Josephson constant valor convencional de constant de Josephson Josephson constant constant de Josephson conventional value of ampere-90 valor convencional d'ampere-90 conventional value of coulomb-90 valor convencional de coulomb-90 conventional value of farad-90 valor convencional de farad-90 conventional value of henry-90 valor convencional de henry-90 conventional value of ohm-90 valor convencional d'ohm-90 conventional value of volt-90 valor convencional de volt-90 conventional value of watt-90 valor convencional de watt-90 magnetic flux quantum (Φ₀) quant de flux magnètic (Φ₀) nuclear magneton magnetó nuclear inverse of conductance quantum invers de quant de conductància conventional value of von Klitzing constant valor convencional de constant de von Klitzing von Klitzing constant constant de von Klitzing atomic unit of magnetic dipole moment unitat atòmica de moment dipolar magnètic atomic unit of magnetic flux density unitat atòmica de densitat de flux magnètic Bohr magneton in eV/T magnetó de Bohr en eV/T Bohr magneton in Hz/T magnetó de Bohr en Hz/T Bohr magneton in inverse meter per tesla magnetó de Bohr en metre invers per tesla Bohr magneton in K/T magnetó de Bohr en K/T nuclear magneton in eV/T magnetó nuclear en eV/T nuclear magneton in inverse meter per tesla magnetó nuclear en metre invers per tesla nuclear magneton in K/T magnetó nuclear en K/T nuclear magneton in MHz/T magnetó nuclear en MHz/T Bohr radius (a₀) radi de Bohr (a₀) fine-structure constant (α) constant d'estructura fina (α) Hartree energy (Eₕ) energia de Hartree (Eₕ) Hartree energy in eV energia de Hartree en eV quantum of circulation quant de circulació quantum of circulation times 2 quant de circulació multiplicat per 2 Rydberg constant (R∞) constant de Rydberg (R∞) atomic mass unit-hartree relationship unitat de massa atòmica-hartree relació atomic mass unit-hertz relationship unitat de massa atòmica-hertz relació atomic mass unit-inverse meter relationship unitat de massa atòmica-metre invers relació atomic mass unit-joule relationship unitat de massa atòmica-joule relació atomic mass unit-kelvin relationship unitat de massa atòmica-kelvin relació atomic mass unit-kilogram relationship unitat de massa atòmica-kilogram relació atomic unit of 1st hyperpolarizability unitat atòmica de 1a hiperpolaritzabilitat atomic unit of 2nd hyperpolarizability unitat atòmica de 2a hiperpolaritzabilitat atomic unit of charge (e) unitat atòmica de càrrega (e) atomic unit of charge density unitat atòmica de densitat de càrrega atomic unit of current unitat atòmica de corrent atomic unit of electric dipole moment unitat atòmica de moment dipolar elèctric atomic unit of electric field unitat atòmica de camp elèctric atomic unit of electric field gradient unitat atòmica de gradient de camp elèctric atomic unit of electric polarizability unitat atòmica de polaritzabilitat elèctrica atomic unit of electric potential unitat atòmica de potencial elèctric atomic unit of electric quadrupole moment unitat atòmica de moment quadrupolar elèctric atomic unit of action unitat atòmica de acció atomic unit of energy unitat atòmica de energia atomic unit of force unitat atòmica de força atomic unit of length unitat atòmica de longitud hertz-atomic mass unit relationship hertz-unitat de massa atòmica relació hertz-electron volt relationship hertz-electróvolt relació hertz-hartree relationship hertz-hartree relació hertz-inverse meter relationship hertz-metre invers relació hertz-joule relationship hertz-joule relació hertz-kelvin relationship hertz-kelvin relació hertz-kilogram relationship hertz-kilogram relació hyperfine transition frequency of Cs-133 freqüència de transició hiperfina del Cs-133 inverse fine-structure constant (α�¹) inverse constant d'estructura fina (α�¹) inverse meter-atomic mass unit relationship metre invers-unitat de massa atòmica relació inverse meter-electron volt relationship metre invers-electróvolt relació inverse meter-hartree relationship metre invers-hartree relació inverse meter-hertz relationship metre invers-hertz relació inverse meter-joule relationship metre invers-joule relació inverse meter-kelvin relationship metre invers-kelvin relació inverse meter-kilogram relationship metre invers-kilogram relació joule-atomic mass unit relationship joule-unitat de massa atòmica relació joule-electron volt relationship joule-electróvolt relació joule-hertz relationship joule-hertz relació joule-hartree relationship joule-hartree relació joule-inverse meter relationship joule-metre invers relació joule-kelvin relationship joule-kelvin relació joule-kilogram relationship joule-kilogram relació kelvin-atomic mass unit relationship kelvin-unitat de massa atòmica relació kelvin-electron volt relationship kelvin-electróvolt relació kelvin-hertz relationship kelvin-hertz relació kelvin-hartree relationship kelvin-hartree relació kelvin-inverse meter relationship kelvin-metre invers relació kelvin-joule relationship kelvin-joule relació kelvin-kilogram relationship kelvin-kilogram relació kilogram-atomic mass unit relationship kilogram-unitat de massa atòmica relació kilogram-electron volt relationship kilogram-electróvolt relació kilogram-hertz relationship kilogram-hertz relació kilogram-hartree relationship kilogram-hartree relació kilogram-inverse meter relationship kilogram-metre invers relació kilogram-joule relationship kilogram-joule relació kilogram-kelvin relationship kilogram-kelvin relació lattice parameter of silicon (a) paràmetre de xarxa del silici (a) luminous efficacy eficàcia lluminosa natural unit of energy unitat natural d'energia natural unit of energy in MeV unitat natural d'energia en MeV natural unit of action (�) unitat natural d'acció (�) natural unit of action in eV·s unitat natural d'acció en eV·s natural unit of length unitat natural de longitud natural unit of mass unitat natural de massa natural unit of momentum unitat natural de moment natural unit of momentum in MeV/c unitat natural de moment en MeV/c natural unit of time unitat natural de temps natural unit of velocity unitat natural de velocitat Rydberg constant times c in Hz constant de Rydberg multiplicat per c en Hz Rydberg constant times hc in eV constant de Rydberg multiplicat per hc en eV Rydberg constant times hc in J constant de Rydberg multiplicat per hc en J Fermi coupling constant constant d'acoblament de Fermi weak mixing angle angle de mescla feble W to Z mass ratio W a Z relació de masses Thomson cross section (σₑ) secció eficaç de Thomson (σₑ) electron mass (mₑ) electró massa (mₑ) electron mass in u electró massa en u electron mass energy equivalent (mₑ·c²) electró equivalent energètic de massa (mₑ·c²) electron mass energy equivalent in MeV electró equivalent energètic de massa en MeV reduced Compton wavelength longitud d'ona de Compton reduïda classical electron radius (rₑ) radi clàssic de l'electró (rₑ) electron charge to mass quotient quocient càrrega-massa de l'electró electron-deuteron magnetic moment ratio electró-deuteró moment magnètic relació electron-deuteron mass ratio electró-deuteró relació de masses electron g factor (gₑ) electró factor g (gₑ) electron gyromagnetic ratio (γₑ) electró relació giromagnètica (γₑ) electron gyromagnetic ratio in MHz/T electró relació giromagnètica en MHz/T electron-helion mass ratio electró-helió relació de masses electron magnetic moment (μₑ) electró moment magnètic (μₑ) electron magnetic moment anomaly (aₑ) electró moment magnètic anomaly (aₑ) electron magnetic moment to Bohr magneton ratio relació entre el moment magnètic de l'electró i el magnetó de Bohr electron magnetic moment to nuclear magneton ratio relació entre el moment magnètic de l'electró i el magnetó nuclear electron molar mass (Mₑ) electró massa molar (Mₑ) electron-muon magnetic moment ratio electró-muó moment magnètic relació electron-muon mass ratio electró-muó relació de masses electron-neutron magnetic moment ratio electró-neutró moment magnètic relació electron-neutron mass ratio electró-neutró relació de masses electron-proton magnetic moment ratio electró-protó moment magnètic relació electron-proton mass ratio electró-protó relació de masses electron relative atomic mass (Ar(e)) electró massa atòmica relativa (Ar(e)) electron-tau mass ratio electró-tau relació de masses electron to alpha particle mass ratio relació de masses entre l'electró i la partícula alfa electron to shielded helion magnetic moment ratio relació entre el moment magnètic de l'electró i el de l'helió apantallat electron to shielded proton magnetic moment ratio relació entre el moment magnètic de l'electró i el del protó apantallat electron-triton mass ratio electró-tritó relació de masses electron volt-atomic mass unit relationship electróvolt-unitat de massa atòmica relació electron volt-hartree relationship electróvolt-hartree relació electron volt-hertz relationship electróvolt-hertz relació electron volt-inverse meter relationship electróvolt-metre invers relació electron volt-joule relationship electróvolt-joule relació electron volt-kelvin relationship electróvolt-kelvin relació electron volt-kilogram relationship electróvolt-kilogram relació hartree-atomic mass unit relationship hartree-unitat de massa atòmica relació hartree-electron volt relationship hartree-electróvolt relació muon Compton wavelength muó Compton longitud d'ona muon-electron mass ratio muó-electró relació de masses muon g factor muó factor g muon magnetic moment muó moment magnètic muon magnetic moment anomaly muó moment magnètic anomaly muon magnetic moment to Bohr magneton ratio relació entre el moment magnètic del muó i el magnetó de Bohr muon magnetic moment to nuclear magneton ratio relació entre el moment magnètic del muó i el magnetó nuclear muon mass muó massa muon mass energy equivalent muó equivalent energètic de massa muon mass energy equivalent in MeV muó equivalent energètic de massa en MeV muon mass in u muó massa en u muon molar mass muó massa molar muon-neutron mass ratio muó-neutró relació de masses muon-proton magnetic moment ratio muó-protó moment magnètic relació muon-proton mass ratio muó-protó relació de masses muon-tau mass ratio muó-tau relació de masses reduced muon Compton wavelength longitud d'ona de Compton reduïda del muó reduced tau Compton wavelength longitud d'ona de Compton reduïda del tau tau Compton wavelength tau Compton longitud d'ona tau-electron mass ratio tau-electró relació de masses tau mass tau massa tau mass energy equivalent tau equivalent energètic de massa tau mass in u tau massa en u tau molar mass tau massa molar tau-muon mass ratio tau-muó relació de masses tau-neutron mass ratio tau-neutró relació de masses tau-proton mass ratio tau-protó relació de masses proton charge to mass quotient quocient càrrega-massa del protó proton Compton wavelength protó Compton longitud d'ona proton-electron mass ratio protó-electró relació de masses proton g factor (gₚ) protó factor g (gₚ) proton gyromagnetic ratio (γₚ) protó relació giromagnètica (γₚ) proton gyromagnetic ratio in MHz/T protó relació giromagnètica en MHz/T proton magnetic moment (μₚ) protó moment magnètic (μₚ) proton magnetic moment to Bohr magneton ratio relació entre el moment magnètic del protó i el magnetó de Bohr proton magnetic moment to nuclear magneton ratio relació entre el moment magnètic del protó i el magnetó nuclear proton magnetic shielding correction protó magnetic correcció d'apantallament proton mass (mₚ) protó massa (mₚ) proton mass energy equivalent protó equivalent energètic de massa proton mass energy equivalent in MeV protó equivalent energètic de massa en MeV proton mass in u protó massa en u proton molar mass (Mₚ) protó massa molar (Mₚ) proton-muon mass ratio protó-muó relació de masses proton-neutron magnetic moment ratio protó-neutró moment magnètic relació proton-neutron mass ratio protó-neutró relació de masses proton relative atomic mass (Ar(p)) protó massa atòmica relativa (Ar(p)) proton rms charge radius protó rms càrrega radi proton-tau mass ratio protó-tau relació de masses reduced proton Compton wavelength longitud d'ona de Compton reduïda del protó shielded proton gyromagnetic ratio shielded protó relació giromagnètica shielded proton gyromagnetic ratio in MHz/T shielded protó relació giromagnètica en MHz/T shielded proton magnetic moment shielded protó moment magnètic shielded proton magnetic moment to Bohr magneton ratio relació entre el moment magnètic del protó apantallat i el magnetó de Bohr shielded proton magnetic moment to nuclear magneton ratio relació entre el moment magnètic del protó apantallat i el magnetó nuclear neutron Compton wavelength neutró Compton longitud d'ona neutron-electron magnetic moment ratio neutró-electró moment magnètic relació neutron-electron mass ratio neutró-electró relació de masses neutron g factor (gₙ) neutró factor g (gₙ) neutron gyromagnetic ratio (γₙ) neutró relació giromagnètica (γₙ) neutron gyromagnetic ratio in MHz/T neutró relació giromagnètica en MHz/T neutron magnetic moment (μₙ) neutró moment magnètic (μₙ) neutron magnetic moment to Bohr magneton ratio relació entre el moment magnètic del neutró i el magnetó de Bohr neutron magnetic moment to nuclear magneton ratio relació entre el moment magnètic del neutró i el magnetó nuclear neutron mass (mₙ) neutró massa (mₙ) neutron mass energy equivalent neutró equivalent energètic de massa neutron mass energy equivalent in MeV neutró equivalent energètic de massa en MeV neutron mass in u neutró massa en u neutron molar mass (Mₙ) neutró massa molar (Mₙ) neutron-muon mass ratio neutró-muó relació de masses neutron-proton magnetic moment ratio neutró-protó moment magnètic relació neutron-proton mass difference neutró-protó massa difference neutron-proton mass difference energy equivalent neutró-protó massa difference energia equivalent neutron-proton mass difference energy equivalent in MeV neutró-protó massa difference energia equivalent en MeV neutron-proton mass difference in u neutró-protó massa difference en u neutron-proton mass ratio neutró-protó relació de masses neutron relative atomic mass (Ar(n)) neutró massa atòmica relativa (Ar(n)) neutron-tau mass ratio neutró-tau relació de masses neutron to shielded proton magnetic moment ratio relació entre el moment magnètic del neutró i el del protó apantallat reduced neutron Compton wavelength longitud d'ona de Compton reduïda del neutró deuteron-electron magnetic moment ratio deuteró-electró moment magnètic relació deuteron-electron mass ratio deuteró-electró relació de masses deuteron g factor deuteró factor g deuteron magnetic moment deuteró moment magnètic deuteron magnetic moment to Bohr magneton ratio relació entre el moment magnètic del deuteró i el magnetó de Bohr deuteron magnetic moment to nuclear magneton ratio relació entre el moment magnètic del deuteró i el magnetó nuclear deuteron mass deuteró massa deuteron mass energy equivalent deuteró equivalent energètic de massa deuteron mass energy equivalent in MeV deuteró equivalent energètic de massa en MeV deuteron mass in u deuteró massa en u deuteron molar mass deuteró massa molar deuteron-neutron magnetic moment ratio deuteró-neutró moment magnètic relació deuteron-proton magnetic moment ratio deuteró-protó moment magnètic relació deuteron-proton mass ratio deuteró-protó relació de masses deuteron relative atomic mass (Ar(d)) deuteró massa atòmica relativa (Ar(d)) deuteron rms charge radius deuteró rms càrrega radi triton-electron mass ratio tritó-electró relació de masses triton g factor (gₜ) tritó factor g (gₜ) triton magnetic moment (μₜ) tritó moment magnètic (μₜ) triton magnetic moment to Bohr magneton ratio relació entre el moment magnètic del tritó i el magnetó de Bohr triton magnetic moment to nuclear magneton ratio relació entre el moment magnètic del tritó i el magnetó nuclear triton mass (mₜ) tritó massa (mₜ) triton mass energy equivalent tritó equivalent energètic de massa triton mass energy equivalent in MeV tritó equivalent energètic de massa en MeV triton mass in u tritó massa en u triton molar mass (Mₜ) tritó massa molar (Mₜ) triton-proton mass ratio tritó-protó relació de masses triton relative atomic mass (Ar(t)) tritó massa atòmica relativa (Ar(t)) triton to proton magnetic moment ratio relació entre el moment magnètic del tritó i el del protó helion-electron mass ratio helió-electró relació de masses helion g factor (gₕ) helió factor g (gₕ) helion magnetic moment (μₕ) helió moment magnètic (μₕ) helion magnetic moment to Bohr magneton ratio relació entre el moment magnètic de l'helió i el magnetó de Bohr helion magnetic moment to nuclear magneton ratio relació entre el moment magnètic de l'helió i el magnetó nuclear helion mass (mₕ) helió massa (mₕ) helion mass energy equivalent helió equivalent energètic de massa helion mass energy equivalent in MeV helió equivalent energètic de massa en MeV helion mass in u helió massa en u helion molar mass (Mₕ) helió massa molar (Mₕ) helion-proton mass ratio helió-protó relació de masses helion relative atomic mass (Ar(h)) helió massa atòmica relativa (Ar(h)) helion shielding shift helió shielding shift shielded helion gyromagnetic ratio shielded helió relació giromagnètica shielded helion gyromagnetic ratio in MHz/T shielded helió relació giromagnètica en MHz/T shielded helion magnetic moment shielded helió moment magnètic shielded helion magnetic moment to Bohr magneton ratio relació entre el moment magnètic de l'helió apantallat i el magnetó de Bohr shielded helion magnetic moment to nuclear magneton ratio relació entre el moment magnètic de l'helió apantallat i el magnetó nuclear shielded helion to proton magnetic moment ratio relació entre el moment magnètic de l'helió apantallat i el del protó shielded helion to shielded proton magnetic moment ratio relació entre el moment magnètic de l'helió apantallat i el del protó apantallat alpha particle mass partícula alfa massa alpha particle mass in u partícula alfa massa en u alpha particle mass energy equivalent partícula alfa equivalent energètic de massa alpha particle mass energy equivalent in MeV partícula alfa equivalent energètic de massa en MeV alpha particle-electron mass ratio partícula alfa-electró relació de masses alpha particle-proton mass ratio partícula alfa-protó relació de masses alpha particle rms charge radius partícula alfa rms càrrega radi alpha particle molar mass partícula alfa massa molar alpha particle relative atomic mass (Ar(α)) partícula alfa massa atòmica relativa (Ar(α)) atomic mass constant (mᵤ) atomic massa constant (mᵤ) Avogadro constant constant d'Avogadro Boltzmann constant (k) constant de Boltzmann (k) Boltzmann constant in eV/K constant de Boltzmann en eV/K Boltzmann constant in Hz/K constant de Boltzmann en Hz/K Boltzmann constant in inverse meter per kelvin constant de Boltzmann en metre invers per kelvin electron volt (eV) electróvolt (eV) Faraday constant (F) constant de Faraday (F) first radiation constant (c�) primera constant de radiació (c�) first radiation constant for spectral radiance primera constant de radiació for spectral radiance molar gas constant (R) constant molar dels gasos (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) constant de Loschmidt (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) constant de Loschmidt (n₀, 273.15 K, 101.325 kPa) molar Planck constant molar constant de Planck second radiation constant (c₂) segona constant de radiació (c₂) Stefan-Boltzmann constant (σ) Stefan-constant de Boltzmann (σ) lattice spacing of ideal Si (d₂₂₀) espaiat reticular del Si ideal (d₂₂₀) atomic mass constant energy equivalent atomic massa constant energia equivalent atomic mass constant energy equivalent in MeV atomic massa constant energia equivalent en MeV atomic mass unit-electron volt relationship unitat de massa atòmica-electróvolt relació molar mass constant (Mᵤ) massa molar constant (Mᵤ) molar mass of carbon-12 massa molar del carboni 12 molar volume of ideal gas (273.15 K, 100 kPa) volum molar del gas ideal (273,15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volum molar del gas ideal (273,15 K, 101,325 kPa) molar volume of silicon volum molar del silici Sackur-Tetrode constant (1 K, 100 kPa) constant de Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) constant de Sackur-Tetrode (1 K, 101,325 kPa) Wien frequency displacement law constant constant de la llei de desplaçament en freqüència de Wien Wien wavelength displacement law constant Wien longitud d'ona displacement law constant standard atmosphere (atm) atmosfera estàndard (atm) standard-state pressure (p°) pressió d'estat estàndard (p°) Angstrom star (Å*) àngstrom estrella (Å*) Copper x unit unitat x de coure Molybdenum x unit unitat x de molibdè atomic unit of magnetizability unitat atòmica de magnetizability atomic unit of mass (mₑ) unitat atòmica de massa (mₑ) atomic unit of momentum unitat atòmica de moment atomic unit of permittivity unitat atòmica de permittivity atomic unit of time unitat atòmica de temps atomic unit of velocity unitat atòmica de velocitat hartree-hertz relationship hartree-hertz relació hartree-inverse meter relationship hartree-metre invers relació hartree-joule relationship hartree-joule relació hartree-kelvin relationship hartree-kelvin relació hartree-kilogram relationship hartree-kilogram relació shielding difference of d and p in HD diferència d'apantallament entre d i p en HD shielding difference of t and p in HT diferència d'apantallament entre t i p en HT pi (π) pi (π) Euler's number (e) nombre d'Euler (e) golden ratio (φ) proporció àuria (φ) Euler-Mascheroni constant (γ) constant d'Euler-Mascheroni (γ) nominal solar radius nominal solar radi nominal solar total irradiance nominal solar total irradiància nominal solar luminosity nominal solar lluminositat nominal solar effective temperature nominal solar effective temperatura nominal solar mass parameter nominal solar massa parameter nominal terrestrial equatorial radius nominal terrestre equatorial radi nominal terrestrial polar radius nominal terrestre polar radi nominal terrestrial mass parameter nominal terrestre massa parameter nominal jovian equatorial radius nominal jovian equatorial radi nominal jovian polar radius nominal jovian polar radi nominal jovian mass parameter nominal jovian massa parameter average value of one minus the rate of TCG relative to TCB valor mitjà d'u menys la taxa de TCG relativa a TCB solar mass parameter (TCB-compatible) solar massa parameter (TCB-compatible) solar mass parameter (TDB-compatible) solar massa parameter (TDB-compatible) equatorial radius of the Earth (TT-compatible) radi equatorial de la Terra (compatible amb TT) dynamical form factor of the Earth factor de forma dinàmic de la Terra time rate of change in the dynamical form factor of the Earth taxa temporal de canvi del factor de forma dinàmic de la Terra geocentric gravitational constant (TCB-compatible) constant gravitacional geocèntrica (compatible amb TCB) geocentric gravitational constant (TT-compatible) constant gravitacional geocèntrica (compatible amb TT) geocentric gravitational constant (TDB-compatible) constant gravitacional geocèntrica (compatible amb TDB) potential of the geoid potencial del geoide nominal mean angular velocity of the Earth (TT-compatible) velocitat angular mitjana nominal de la Terra (compatible amb TT) ratio mass of the Moon to the Earth relació de masses entre la Lluna i la Terra ratio of the mass of the Sun to Mercury relació de la massa del Sol respecte a la de Mercuri ratio of the mass of the Sun to Venus relació de la massa del Sol respecte a la de Venus ratio of the mass of the Sun to Mars relació de la massa del Sol respecte a la de Mart ratio of the mass of the Sun to Jupiter relació de la massa del Sol respecte a la de Júpiter ratio of the mass of the Sun to Saturn relació de la massa del Sol respecte a la de Saturn ratio of the mass of the Sun to Uranus relació de la massa del Sol respecte a la d'Urà ratio of the mass of the Sun to Neptune relació de la massa del Sol respecte a la de Neptú ratio of the mass of the Sun to (134340) Pluto relació de la massa del Sol respecte a la de (134340) Plutó ratio of the mass of the Sun to (136199) Eris relació de la massa del Sol respecte a la de (136199) Eris ratio of the mass of (1) Ceres to the Sun relació de la massa de (1) Ceres respecte a la del Sol ratio of the mass of (2) Pallas to the Sun relació de la massa de (2) Pal·les respecte a la del Sol ratio of the mass of (4) Vesta to the Sun relació de la massa de (4) Vesta respecte a la del Sol mean obliquity of the ecliptic at J2000.0 obliqüitat mitjana de l'eclíptica a J2000.0 Electromagnetic Electromagnètic Compton wavelength longitud d'ona de Compton Astronomy Astronomia ConstantsWidget Domain Domini Subdomain Subdomini No match found No s'han trobat coincidències Name Nom Value Valor Unit Unitat Search Recerca All Tot CustomKeypadDialog Custom Keypad Teclat numèric personalitzat Rows: Files: Columns: Columnes: Copy preset: Copia el predefinit: Basic Bàsic Scientific (wide) Científic (ample) Scientific (narrow) Científic (estret) Apply Aplica Row Fila Column Columna Label Etiqueta Behavior Comportament Text Text DiagnosticsDialog App Diagnostics Diagnòstic de l’aplicació Copy to Clipboard Copia al porta-retalls Editor Unit Unitat User unit Unitat de l'usuari User function Funció de l'usuari Argument Argument Current result:<br/>%1 Resultat actual:<br/>%1 Selection result:<br/>%1 Resultat de la selecció:<br/>%1 Selection result: n/a Resultat de la selecció: n/d Selection result: %1 Resultat de la selecció: %1 second segon metre metre kilogram quilogram mole mol radian radian steradian estereoradian degree Celsius grau Celsius cubic metre metre cúbic cubic millimetre mil·límetre cúbic cubic centimetre centímetre cúbic cubic decimetre decímetre cúbic cubic kilometre quilòmetre cúbic square millimetre mil·límetre quadrat square kilometre quilòmetre quadrat square metre metre quadrat minute minut hour hora day dia astronomical unit unitat astronòmica degree grau arcminute minut d'arc arcsecond segon d'arc milliarcsecond mil·lisegon d'arc microarcsecond microsegon d'arc hectare hectàrea litre litre tonne tona Dalton dalton electronvolt electróvolt Angstrom àngstrom atmosphere atmosfera atomic mass unit unitat de massa atòmica British thermal unit unitat tèrmica britànica calorie caloria carat quirat cup tassa cup (Imperial) tassa (imperial) cup (Japanese) tassa (japonesa) cup (US) tassa (EUA) degree Fahrenheit grau Fahrenheit fathom braça fluid ounce (Imperial) unça líquida (imperial) fluid ounce (US) unça líquida (EUA) fluid dram (Imperial) dracma líquida (imperial) fluid dram (US) dracma líquida (EUA) foot peu square foot peu quadrat cubic foot peu cúbic gallon (Imperial) galó (imperial) gallon (US) galó (EUA) gill (Imperial) gill (imperial) gill (US) gill (EUA) gradian gradian grain gra gram gram Hartley hartley Hartree energy unit energia de Hartree unit horsepower cavall de vapor inch polzada square inch polzada quadrada cubic inch polzada cúbica karat quirat d'or knot nus lightminute minut llum lightsecond segon llum lightyear any llum long ton tona llarga mile milla square mile milla quadrada cubic mile milla cúbica mile per hour milla per hora kilometre per hour quilòmetre per hora nautical mile milla nàutica ounce unça parsec parsec pint (Imperial) pinta (imperial) pint (US) pinta (EUA) pound lliura pounds per square inch lliures per polzada quadrada quart (Imperial) quart (imperial) quart (US) quart (EUA) oil barrel barril de petroli beer barrel (US) barril de cervesa (EUA) square yard iarda quadrada cubic yard iarda cúbica short ton tona curta tablespoon cullerada tablespoon (Australian) cullerada (australiana) tablespoon (Imperial) cullerada (imperial) tablespoon (US) cullerada (EUA) dessert spoon cullera de postres teaspoon culleradeta teaspoon (Imperial) culleradeta (imperial) teaspoon (US) culleradeta (EUA) turn volta revolution revolució revolution per minute revolució per minut week setmana kilowatt hour quilowatt hora millimetre of mercury mil·límetre de mercuri yard iarda Julian century segle julià Julian year any julià sidereal year any sideral tropical year any tropical Evaluator invalid expression expressió invàlida division by zero divisió per cero too time consuming - computation was rejected massa costós en temps: s'ha rebutjat el càlcul dimension mismatch - quantities with different dimensions cannot be compared, added, etc. incompatibilitat de dimensions: les quantitats amb dimensions diferents no es poden comparar, sumar, etc. invalid dimension - operation might require dimensionless arguments dimensió no vàlida: l'operació pot requerir arguments adimensionals Computation aborted - encountered numerical instability S'ha interromput el càlcul: s'ha trobat inestabilitat numèrica invalid dimension - function might require dimensionless arguments dimensió no vàlida: la funció pot requerir arguments adimensionals error error unit must not be zero la unitat no pot ser zero Conversion failed - dimension mismatch Ha fallat la conversió: les dimensions no coincideixen unknown function or variable funció o variable desconeguda recursion not supported no s'admet la recursió cannot operate on a NaN no es pot operar amb un NaN underflow - tiny result is out of SpeedCrunch's number range subdesbordament: el resultat diminut és fora del rang numèric de SpeedCrunch overflow - huge result is out of SpeedCrunch's number range desbordament: el resultat enorme és fora del rang numèric de SpeedCrunch overflow - logic result exceeds maximum of 256 bits desbordament: el resultat lògic supera el màxim de 256 bits overflow - integer result exceeds maximum limit for integers desbordament: el resultat enter supera el límit màxim per als enters operation is not defined for these arguments l'operació no està definida per a aquests arguments wrong number of arguments nombre d'arguments incorrecte does not take NaN as an argument no accepta NaN com a argument result out of range resultat fora de rang undefined for argument domain no definit per al domini de l'argument computation too expensive càlcul massa costós internal error, please report a bug error intern; informeu-ne com a error de programari syntax error error de sintaxi conversion target must be a unit l'objectiu de conversió ha de ser una unitat unknown unit unitat desconeguda %1 is a reserved name, please choose another %1 és un nom reservat; trieu-ne un altre %1 is a global user definition and cannot be overridden in this session. %1 és una definició global de l'usuari i no es pot sobreescriure en aquesta sessió. %1 is a variable name, please choose another or delete the variable %1 és el nom d'una variable; trieu-ne un altre o suprimiu la variable argument %1 is used more than once l'argument %1 s'utilitza més d'una vegada %1 is a built-in unit name, please choose another %1 és el nom d'una unitat integrada; trieu-ne un altre %1 is a user function name, please choose another or delete the function %1 és el nom d'una funció de l'usuari; trieu-ne un altre o suprimiu la funció FunctionRepo max; trials; probability màxim; assaigs; probabilitat trials; probability assaigs; probabilitat hits; trials; probability èxits; assaigs; probabilitat max; total; hits; trials màxim; total; èxits; assaigs total; hits; trials total; èxits; assaigs count; total; hits; trials recompte; total; èxits; assaigs dividend; divisor dividend; divisor x; exponent_bits; significand_bits [; exponent_bias] x; bits_exponent; bits_significand [; biaix_exponent] base; x base; x value; modulo valor; mòdul base; exponent; modulo base; exponent; mòdul events; average_events esdeveniments; esdeveniments_mitjans average_events esdeveniments_mitjans x [; precision] x [; precisió] Absolute Value Valor absolut Absolute Deviation Desviació absoluta Arc Cosine Arccosinus Logical AND I lògic Area Hyperbolic Cosine Arccosinus hiperbòlic Area Hyperbolic Sine Arcsinus hiperbòlic Area Hyperbolic Tangent Arctangent hiperbòlica Arc Sine Arcsinus Arc Tangent Arctangent Arc Tangent with two Arguments Arctangent amb dos arguments Average (Arithmetic Mean) Mitjana (mitjana aritmètica) Binomial Cumulative Distribution Function Funció de distribució acumulada binomial Binomial Distribution Mean Mitjana de la distribució binomial Binomial Probability Mass Function Funció de massa de probabilitat binomial Binomial Distribution Variance Variància de la distribució binomial Cube Root Arrel cúbica Complex Conjugate Conjugat complex Cosine Cosinus Hyperbolic Cosine Cosinus hiperbòlic Cotangent Cotangent Cosecant Cosecant Convert Unix timestamp to Date Converteix la marca de temps Unix en data Degrees of Arc Graus d'arc Error Function Funció d'error Complementary Error Function Funció d'error complementària Exponential Exponencial Fractional Part Part fraccionària Extension of Factorials [= (x-1)!] Extensió dels factorials [= (x-1)!] Greatest Common Divisor Màxim comú divisor Geometric Mean Mitjana geomètrica Gradians of arc Gradians d'arc Hypergeometric Cumulative Distribution Function Funció de distribució acumulada hipergeomètrica Hypergeometric Distribution Mean Mitjana de la distribució hipergeomètrica Hypergeometric Probability Mass Function Funció de massa de probabilitat hipergeomètrica Hypergeometric Distribution Variance Variància de la distribució hipergeomètrica Integer Quotient Quocient enter Integer Part Part entera Imaginary Part Part imaginària Decode IEEE-754 Binary Value Decodifica el valor binari IEEE-754 Encode IEEE-754 Binary Value Codifica el valor binari IEEE-754 Decode 16-bit Half-Precision Value Decodifica el valor de mitja precisió de 16 bits Encode 16-bit Half-Precision Value Codifica el valor de mitja precisió de 16 bits Decode 32-bit Single-Precision Value Decodifica el valor de precisió simple de 32 bits Encode 32-bit Single-Precision Value Codifica el valor de precisió simple de 32 bits Decode 64-bit Double-Precision Value Decodifica el valor de doble precisió de 64 bits Encode 64-bit Double-Precision Value Codifica el valor de doble precisió de 64 bits Decode 128-bit Quad-Precision Value Decodifica el valor de precisió quàdruple de 128 bits Encode 128-bit Quad-Precision Value Codifica el valor de precisió quàdruple de 128 bits Binary Logarithm Logaritme binari Common Logarithm Logaritme decimal Natural Logarithm Logaritme natural Logarithm to Arbitrary Base Logaritme en base arbitrària Mask to a bit size Aplica una màscara a una mida de bits Maximum Màxim Median Value (50th Percentile) Mediana (percentil 50) Minimum Mínim Modulo Mòdul Euclidean Modulo Mòdul euclidià Modular Exponentiation Exponenciació modular Combination (Binomial Coefficient) Combinació (coeficient binomial) Logical NOT NO lògic Permutation (Arrangement) Permutació (arranjament) Convert to Binary Representation Converteix a representació binària Arithmetic Aritmètica Chemistry Química Complex Complexos Combinatorics Combinatòria Probability Probabilitat Statistics Estadística Aggregation Agregació Random Aleatori Base conversion Conversió de base Number formatting Formatació numèrica Integer arithmetic Aritmètica d'enters Special functions Funcions especials Exponential & Logarithmic Exponencials i logarítmiques Angle conversion Conversió angular Trigonometry Trigonometria Bitwise Bit a bit Floating point Punt flotant Date & Time Data i hora Linear algebra Àlgebra lineal unix_timestamp; x hours offset to GMT marca_de_temps_unix; desplaçament de x hores respecte de GMT yyyymmdd.hhmmss; x hours offset to GMT aaaammdd.hhmmss; desplaçament de x hores respecte de GMT [digits] [dígits] max [; min] màxim [; mínim] List Literal Literal de llista Convert to Padded Binary Representation Converteix a representació binària amb farciment Round Toward +∞ (Ceiling) Arrodoneix cap a +∞ (sostre) Cosine plus Imaginary Sine Cosinus més sinus imaginari Convert to Cis Complex Form Converteix a forma complexa cis Matrix Column Count Nombre de columnes de la matriu Population Correlation Matrix (n) Matriu de correlació poblacional (n) Sample Correlation Matrix (n-1) Matriu de correlació mostral (n-1) Count Recompte Population Covariance Matrix (n) Matriu de covariància poblacional (n) Sample Covariance Matrix (n-1) Matriu de covariància mostral (n-1) Cross Product Producte vectorial Convert Date to Unix timestamp Converteix la data en marca de temps Unix Convert to Decimal Representation Converteix a representació decimal Determinant Determinant Convert to Sexagesimal Notation Converteix a notació sexagesimal Dot Product Producte escalar Convert to Engineering Notation Converteix a notació d'enginyeria Convert to Exponential Complex Form Converteix a forma complexa exponencial Round Toward −∞ (Floor) Arrodoneix cap a −∞ (terra) Flatten Matrix Aplana la matriu Least Common Multiple Mínim comú múltiple Convert to Hexadecimal Representation Converteix a representació hexadecimal Convert to Padded Hexadecimal Representation Converteix a representació hexadecimal amb farciment Inverse Matrix Matriu inversa Round to 16-bit Half-Precision Value Arrodoneix a valor de mitja precisió de 16 bits Round to 32-bit Single-Precision Value Arrodoneix a valor de precisió simple de 32 bits Round to 64-bit Double-Precision Value Arrodoneix a valor de doble precisió de 64 bits Round to 128-bit Quad-Precision Value Arrodoneix a valor de precisió quàdruple de 128 bits Residual from 16-bit Half-Precision Rounding Residu de l'arrodoniment a mitja precisió de 16 bits Residual from 32-bit Single-Precision Rounding Residu de l'arrodoniment a precisió simple de 32 bits Residual from 64-bit Double-Precision Rounding Residu de l'arrodoniment a doble precisió de 64 bits Residual from 128-bit Quad-Precision Rounding Residu de l'arrodoniment a precisió quàdruple de 128 bits Substance Mass Massa de substància Molarity Molaritat Molar Mass Massa molar Median Absolute Deviation Desviació absoluta mediana Mean Mitjana Numerical Value of Quantity Valor numèric de la quantitat Random Decimal Number Nombre decimal aleatori Random Integer Number Nombre enter aleatori Convert to Rational Representation Converteix a representació racional Convert to Octal Representation Converteix a representació octal Convert to Padded Octal Representation Converteix a representació octal amb farciment Vector or Matrix Norm Norma de vector o matriu Logical OR O lògic Population Count (Hamming Weight) Recompte de bits a 1 (pes de Hamming) Phase of Complex Number Fase del nombre complex Poissonian Cumulative Distribution Function Funció de distribució acumulada de Poisson Poissonian Distribution Mean Mitjana de la distribució de Poisson Poissonian Probability Mass Function Funció de massa de probabilitat de Poisson Poissonian Distribution Variance Variància de la distribució de Poisson Convert to Phasor Complex Form Converteix a forma complexa fasorial Convert to Rectangular Complex Form Converteix a forma complexa rectangular Round Half Away from Zero Arrodoneix la meitat allunyant-se de zero Round Half Even Arrodoneix la meitat al parell Nth Root Arrel enèsima Convert to Scientific Notation Converteix a notació científica Matrix Row Count Nombre de files de la matriu List or Matrix Shape Forma de la llista o matriu Summation Sumatori Population Standard Deviation (n) Desviació estàndard poblacional (n) Sample Standard Deviation (n-1) Desviació estàndard mostral (n-1) Round Toward Zero (Truncation) Arrodoneix cap a zero (truncament) Matrix Trace Traça de la matriu Transpose Matrix Transposa la matriu Population Variance (n) Variància poblacional (n) Sample Variance (n-1) Variància mostral (n-1) Product Producte Radians Radians Matrix Rank Rang de la matriu Real Part Part real Secant Secant Arithmetic Shift Left Desplaçament aritmètic a l'esquerra Arithmetic Shift Right Desplaçament aritmètic a la dreta Signum Signe Sine Sinus Hyperbolic Sine Sinus hiperbòlic Square Root Arrel quadrada Sum Suma Tangent Tangent Convert to Trigonometric Complex Form Converteix a forma complexa trigonomètrica Turns Voltes Hyperbolic Tangent Tangent hiperbòlica Sign-extend a value Estén el signe d'un valor Logical XOR O exclusiu lògic FunctionsWidget Domain Domini All Tot Name Nom Search Recerca No match found No s'han trobat coincidències Identifier Identificador HistoryWidget Remove All Calculations Above Elimina tots els càlculs de sobre Remove This Calculation Elimina aquest càlcul Remove All Calculations Below Elimina tots els càlculs de sota Keypad Inverse cosine Cosinus invers The last result El darrer resultat Inverse sine Sinus invers Inverse tangent Tangent inversa Evaluate expression Avalua l'expressió Division Divisió Multiplication Multiplicació Subtraction Subtracció Addition Suma Clear expression Esborrar expressió Cosine Cosinus Backspace Retrocés Scientific notation Notació científica Exponential Exponencial Factorial Factorial Natural logarithm Logaritme natural Left parenthesis Parèntesi esquerre Nth root Arrel enèsima Argument separator Separador d’arguments Square Quadrat Common logarithm Logaritme decimal Modulo Mòdul Contextual percentage Percentatge contextual Power Potència Right parenthesis Parèntesi dret Sine Sinus Square root Arrel quadrada Tangent Tangent Pi Pi Decimal separator Separador decimal MainWindow Radian Radian Degree Grau Gradian Gradian Binary Binari Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Engineering decimal Decimal enginyeria Scientific decimal Decimal científica &Import... &Importar... &Quit &Sortir Clear E&xpression Esborrar E&xpressió Clear &History Esborrar &Historial &Copy &Copiar &Paste &Pegar &Select Expression &Seleccionar Expressió &Constants &Constants &Functions &Funcions &History &Historial &Status Bar Barra d'&Estat Bitfield Camp de bits Use&r Functions Funcions d'&usuari &Degree &Grau &Radian &Radian &Gradian &Gradian Re&volution R&evolució Auto-Insert a&ns I&nsereix ans automàticament Automatic &Completion &Completat Automàtic &Built-in Functions &Funcions integrades Built-in &Variables &Variables integrades User &Functions Fu&ncions d'usuari User Va&riables Va&riables d'usuari Open a Private Tab on Startup Obre una pestanya privada en iniciar Open and focus a new private tab whenever SpeedCrunch starts. Obre i activa una pestanya privada nova cada vegada que s’inicia el SpeedCrunch. Syntax &Highlighting &Resaltat de la Sintaxis Group Digits in &Input Agrupa els díg&its d’entrada Automatic Input &Adjustments &Ajustos automàtics de l’entrada Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ajusta automàticament els operadors, els espais, els parèntesis i les potències, i limita l’entrada als caràcters vàlids. Group input digits using the selected number format. Agrupa els dígits introduïts segons el format numèric seleccionat. &Blinking Cursor &Cursor intermitent Blink the cursor in the expression editor. Fes parpellejar el cursor a l’editor d’expressions. &Escape Clears Editor &Escape buida l’editor Clear the focused expression editor with Escape after dismissing any popup or preview. Buida l’editor d’expressions actiu amb Escape després de tancar qualsevol finestra emergent o previsualització. Keep Expression After Evaluation Conserva l’expressió després del càlcul Copy New Results Automatically Copia automàticament els resultats nous &Comma &Coma &System Default Defecte (&Sistema) &Dot &Punt Dot &And Comma Punt i &coma Toward +∞ (&ceil) &Cap a +∞ (ceil) Toward −∞ (&floor) Cap a −∞ (&floor) &Binary &Binari &Engineering &Enginyeria &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Científica User &Manual &Manual d'usuari Issues and &Feedback &Problemes i comentaris &Donate Feu una &donació &About SpeedCrunch Qu&ant a SpeedCrunch App Diag&nostics Diag&nòstic de l’aplicació S&plit &Divideix Angle &Mode &Mode angular &Complex Form Forma &complexa New Tab Pestanya nova Constants Constants Functions Funcions History Historial User Functions Funcions d'usuari &Font... &Tipus de lletra... &Language... &Idioma... &Session &Sessió &Edit &Editar &View &Veure Se&ttings &Configuració &Decimal &Decimal &Keypad &Teclat Numèric Always on &Top Sempre al &davant Disabled Desactivat Small Space Espai petit Medium Space Espai mitjà Large Space Espai gran &0 Digits &0 dígits &15 Digits &15 dígits &2 Digits &2 dígits &3 Digits &3 dígits &50 Digits &50 dígits &8 Digits &8 dígits &Sexagesimal &Sexagesimal Reset All Settings... Restableix tots els paràmetres... &System &Sistema SpeedCrunch &Theme &Tema del SpeedCrunch &Classic &Clàssic &Modern &Modern Context Help Ajuda contextual &Help A&juda Error Error Can't read from file %1 No es pot llegir el fitxer %1 Import Session Importa la sessió Close Session Tanca la sessió Angle Mode: Mode angular: Notation: Notació: Precision: Precisió: Turn Volta Revolution Revolució Fixed-point decimal Decimal de punt fix Rational Racional Automatic decimal Decimal automàtic Automatic Automàtic User &Definitions... &Definicions d'usuari... New &Tab Pestanya &nova New &Private Tab &Pestanya privada nova Keep Conserva Make Private... Fes privada... New &Window &Finestra nova &Open... &Obre... &Rename... C&anvia el nom... Clo&ne... Clo&na... &Close Tab &Tanca la pestanya Reopen Clo&sed Tab To&rna a obrir la pestanya tancada Open Sessions &Folder Obre la &carpeta de sessions &Undo &Desfés &Redo &Refés Cu&t Re&talla Copy &Last Result Copia &l’últim resultat &Wrap in Parentheses &Envolta de parèntesis Full Scr&een Mode M&ode de pantalla completa &Basic &Bàsic &Scientific (wide) &Científic (ample) Scientific (narrow) Científic (estret) &Custom... &Personalitzat... Main &Menu &Menú principal User &Variables &Variables d'usuari &Left &Esquerra &Right D&reta &Up Am&unt &Down &Avall Close Pa&ne Ta&nca el panell User &Units &Unitats d'usuari &Turn &Volta If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Si una expressió nova comença amb +, -, * o /, SpeedCrunch hi insereix "ans" al davant. &Accept with Enter &Accepta amb Retorn Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Accepta el suggeriment actual de compleció automàtica amb Retorn sense seleccionar-lo abans amb les tecles de fletxa. &Units &Unitats Show Live Result &Preview Mostra la &previsualització del resultat en viu Save &Window Position on Exit Desa la posició de la &finestra en sortir Hover Highlighting Ressaltat en passar-hi el cursor Group Integer Part Only Agrupa només la part entera Number Format... Format numèric... Notation && Precision... Notació i precisió... After pressing Enter, keep the entered expression selected in the editor. Després de prémer Retorn, mantén seleccionada l'expressió introduïda a l'editor. Never Mai Always Sempre Only for Single-Line Expressions Només per a expressions d'una sola línia Simplify Displayed Expressions Simplifica les expressions mostrades History Size &Limit... &Límit de mida de l'historial... Remove Trailing &Zeroes Elimina els &zeros finals Nearest, Half &Away (round) Més proper, meitat cap &enfora (round) Nearest, Half &Even (roundeven) Més proper, meitat &parella (roundeven) Toward &Zero (trunc) Cap a &zero (trunc) &Fixed-Point &Punt fix &Rational &Racional &Exponential (m·s�¹) &Exponencial (m·s�¹) &Fractional (m/s) &Fraccionari (m/s) &Rectangular (a + bi) &Rectangular (a + bi) Exponential (re�ᶿ) Exponencial (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonomètric (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Tema... Check for &Updates Comprova si hi ha act&ualitzacions Source Code Codi font &Zoom &Zoom &Results &Resultats Unit Notation Notació d'unitats Rounding Mode Mode d'arrodoniment &Notation &Notació &Imaginary Unit Unitat &imaginària &Window &Finestra &Editing &Edició A&utocomplete Compleció a&utomàtica Up/Down Arrow History Historial amb fletxa amunt/avall &Appearance &Aparença &Menus &Menús &Docks &Plafons acoblables &Input and Results Entrada &i resultats &Disabled &Desactivat &Disable &Desactiva Close preview Tanca la previsualització Rename... Canvia el nom... Clone... Clona... Close Tab Tanca la pestanya New Private Tab Pestanya privada nova Open... Obre... Reopen Closed Tab Torna a obrir la pestanya tancada Split Divideix Left Esquerra Right Dreta Up Amunt Down Avall Clear Buida Delete Suprimeix %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sessió privada: el contingut es descarta en tancar-la. Trieu Sessió > Conserva per convertir-la en una sessió normal. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privada] Reset All Settings Restableix tots els paràmetres Reset all settings to their default values? Voleu restablir els valors predeterminats de tots els paràmetres? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Això inclou l’aparença, l’edició, els formats dels resultats i les preferències de les finestres. Es conservaran els càlculs, les sessions obertes i les definicions de l’usuari. The settings file could not be written. No s’ha pogut escriure el fitxer de paràmetres. Clear this session's calculations, unfinished expression, variables, functions, and units? Voleu buidar els càlculs, l’expressió inacabada, les variables, les funcions i les unitats d’aquesta sessió? Global user definitions are kept. Es conserven les definicions globals de l’usuari. Make Session Private Fes privada la sessió The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Se suprimirà la sessió desada %1. El contingut romandrà obert en una sessió privada i es descartarà quan es tanqui aquesta sessió o se surti del SpeedCrunch. Make Private Fes privada Could not delete the saved session %1. No s’ha pogut suprimir la sessió desada %1. Keep Session Conserva la sessió Could not save the session. It remains private. No s’ha pogut desar la sessió. Continua sent privada. Clone Session Clona la sessió Could not save session file %1. No s’ha pogut desar el fitxer de sessió %1. Could not delete session file %1. No s’ha pogut suprimir el fitxer de sessió %1. JSON file (*.json);;Any file (*.*) Fitxer JSON (*.json);;Qualsevol fitxer (*.*) Export session as JSON Exporta la sessió com a JSON The selected file is not valid JSON: %1 El fitxer seleccionat no és JSON vàlid: %1 The selected file is not a SpeedCrunch session JSON file. El fitxer seleccionat no és un fitxer JSON de sessió de SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Aquest fitxer usa un format de sessió de SpeedCrunch obsolet i no es pot importar. The selected JSON file is missing the required $schema field. Al fitxer JSON seleccionat li falta el camp obligatori $schema. The selected JSON file uses an unsupported JSON schema: %1 El fitxer JSON seleccionat usa un esquema JSON no admès: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Al fitxer JSON seleccionat li falta l'identificador de l'esquema de sessió de SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 El fitxer JSON seleccionat usa un format de sessió de SpeedCrunch no admès: %1 The selected JSON file is missing the required session name. Al fitxer JSON seleccionat li falta el nom de sessió obligatori. The selected JSON file has an empty session name. El fitxer JSON seleccionat té un nom de sessió buit. The selected JSON file has invalid or incomplete SpeedCrunch session data. El fitxer JSON seleccionat té dades de sessió de SpeedCrunch no vàlides o incompletes. Open Sessions Folder Obre la carpeta de sessions Could not create the sessions folder: %1 No s'ha pogut crear la carpeta de sessions: %1 Could not open the sessions folder: %1 No s'ha pogut obrir la carpeta de sessions: %1 Editor and Results Font Tipus de lletra de l’editor i dels resultats Open Session Obre la sessió Community Comunitat Rename Session Canvia el nom de la sessió Clear Session Esborra la sessió Delete Session Suprimeix la sessió Close Pane Tanca el panell User Variables Variables d'usuari User Units Unitats d'usuari Clear History Esborra l'historial Are you sure you want to clear the calculation history? Segur que voleu esborrar l'historial de càlculs? Session name: Nom de la sessió: A session named %1 already exists. Ja existeix una sessió anomenada %1. Could not create session file %1. No s'ha pogut crear el fitxer de sessió %1. Could not write session file %1. No s'ha pogut escriure el fitxer de sessió %1. Are you sure you want to delete this session? Segur que voleu suprimir aquesta sessió? Custom Precision Precisió personalitzada Fractional digits: Dígits fraccionaris: Theme Tema Light Themes Temes clars Dark Themes Temes foscos Preview Previsualització Colors Colors Select color for %1 Seleccioneu el color per a %1 Import... Importa... Export... Exporta... Import Theme Importa el tema Theme file (*.json);;All files (*) Fitxer de tema (*.json);;Tots els fitxers (*) Invalid theme file. El fitxer de tema no és vàlid. Can't import theme "%1" because it conflicts with a built-in theme. No es pot importar el tema "%1" perquè entra en conflicte amb un tema integrat. Can't find a writable theme folder. No s'ha trobat cap carpeta de temes amb permís d'escriptura. Overwrite Theme Sobreescriu el tema A custom theme named "%1" already exists. Do you want to overwrite it? Ja existeix un tema personalitzat anomenat "%1". El voleu sobreescriure? Can't overwrite theme file %1 No es pot sobreescriure el fitxer de tema %1 Can't copy theme file to %1 No es pot copiar el fitxer de tema a %1 Export Theme Exporta el tema Can't export theme as "%1" because it conflicts with a built-in theme. No es pot exportar el tema com a "%1" perquè entra en conflicte amb un tema integrat. Can't write to file %1 No es pot escriure al fitxer %1 Global User Variable Variable global de l'usuari Global User Function Funció global de l'usuari Global User Unit Unitat global de l'usuari User Definitions Definicions de l'usuari These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Aquestes definicions són globals i es carreguen a cada sessió. No es poden modificar des de les sessions i tenen prioritat sobre les definicions amb el mateix nom de l'editor de la sessió. Introduïu una definició per línia. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Exemples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Aplica Validate Valida Test Results Resultats de la prova Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variables importades: %1 Funcions importades: %2 Unitats importades: %3 Números de línia amb errors: %4 none cap Apply Results Resultats de l'aplicació User definitions saved. S'han desat les definicions de l'usuari. History Size Limit Límit de mida de l'historial Maximum number of history entries for this session (0 = unlimited): Nombre màxim d'entrades d'historial per a aquesta sessió (0 = sense límit): Text file (*.txt);;Any file (*.*) Fitxer de text (*.txt);;Qualsevol fitxer (*.*) Could not recalculate from calculation %1: %2 No s'ha pogut recalcular a partir del càlcul %1: %2 History Size Limit Reached S'ha assolit el límit de mida de l'historial This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Aquest càlcul omple l'últim espai disponible de l'historial. Els càlculs futurs eliminaran el càlcul més antic de l'historial. Podeu augmentar el límit des de Sessió > Límit de mida de l'historial. Editing calculation. Press Esc twice to cancel. S'està editant el càlcul. Premeu Esc dues vegades per cancel·lar. Calculation Settings Paràmetres del càlcul Invalid recalculation start index �ndex inicial de recàlcul no vàlid System Default Valor per defecte del sistema Language Idioma Select the language: Seleccioneu l'idioma: Custom Personalitzat Decimal places: Decimals: &Automatic &Automàtic &Precision &Precisió Plain &text &Text net Formula &Book Llibre de &fórmules &Export &Exporta Export session as HTML Exporta la sessió com a HTML HTML file (*.html) Fitxer HTML (*.html) Export session as plain text Exporta la sessió com a text net ManualWindow SpeedCrunch Manual Manual de SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual de SpeedCrunch NumberFormatDialog Number Format Format numèric <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Seleccioneu el format numèric dels resultats i de l’agrupació dels dígits d’entrada.</b><br/><br/>Nota: els nombres introduïts en formats inequívocs s’accepten encara que siguin diferents del format de visualització seleccionat.<br/> QObject Global User Variable Variable global de l'usuari Global User Function Funció global de l'usuari Global User Unit Unitat global de l'usuari Backspace Retrocés Clear expression Esborrar expressió Evaluate expression Avalua l'expressió Insert text Insereix text Automatic decimal Decimal automàtic Fixed-point decimal Decimal de punt fix Engineering decimal Decimal enginyeria Scientific decimal Decimal científica Rational Racional Binary Binari Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Update Available Actualització disponible A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Hi ha disponible una versió més nova (%1).<br/><a href="%2">Visiteu el lloc web per descarregar-la.</a> Check for Updates Comprova si hi ha actualitzacions SpeedCrunch %1 is up to date. SpeedCrunch %1 està actualitzat. No connectivity. Please check your internet connection and try again. No hi ha connectivitat. Comproveu la connexió a Internet i torneu-ho a provar. Could not verify the latest available version. No s'ha pogut verificar l'última versió disponible. ResultDisplay Scroll to bottom Desplaça fins al final Edit Expression Edita l'expressió Change Settings Canvia la configuració New Tab Pestanya nova &Import... &Importa... &Export &Exporta Plain &text &Text net Copy Copiar Selection Selecció Select All Selecciona-ho tot Expression Expressió Result Resultat Calculation Càlcul Calculation as Single Line Càlcul en una sola línia Remove Elimina This Calculation Aquest càlcul All Calculations Above Tots els càlculs de sobre All Calculations Below Tots els càlculs de sota New Private Tab Pestanya privada nova Session Sessió Open... Obre... Clone... Clona... Rename... Canvia el nom... Keep Conserva Make Private... Fes privada... Clear Buida Delete Suprimeix Close Tanca Split Divideix Left Esquerra Right Dreta Up Amunt Down Avall Close Pane Tanca el panell Main Menu Menú principal Cancel editing Cancel·la l'edició Copy result Copia el resultat Edit expression Edita l'expressió Change settings Canvia la configuració Remove calculation Elimina el càlcul ResultSlotsDialog Notation & Precision Notació i precisió Result Line Línia de resultat Enabled Activat Notation Notació Decimal Places Decimals Main Line Línia principal Extra Line #1 Línia extra 1 Extra Line #2 Línia extra 2 Extra Line #3 Línia extra 3 Extra Line #4 Línia extra 4 Auto Automàtic UserFunctionListWidget Name Nom Value Valor Description Descripció Search Recerca No match found No s'han trobat coincidències Insert Insereix Edit Edita Delete Suprimeix Delete All Suprimeix-ho tot UserUnitListWidget Name Nom Value Valor Description Descripció Search Recerca No match found No s'han trobat coincidències Insert Insereix Edit Edita Delete Suprimeix Delete All Suprimeix-ho tot VariableListWidget Name Nom Value Valor Description Descripció Search Recerca No match found No s'han trobat coincidències Insert Insereix Edit Edita Delete Suprimeix Delete All Suprimeix-ho tot heldercorreia-speedcrunch-e7ca37f/src/resources/locale/cs.ts000066400000000000000000010557121526573132500243650ustar00rootroot00000000000000 AboutBox About SpeedCrunch O programu SpeedCrunch Core developers Hlavní vývojáři Original author Původní autor Close Zavřít Math engine Matematické jádro Main author | Logo | Maintainer Hlavní autor | Logo | Správce Thanks Poděkování Copyright (C) 2004-2026 The SpeedCrunch developers Autorská práva (C) 2004-2026 Vývojáři SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Tento program je svobodný software; můžete jej šířit a/nebo upravovat za podmínek Obecné veřejné licence GNU (GNU General Public License), vydané nadací Free Software Foundation; a to bu� verze 2 této licence, nebo (podle vašeho uvážení) kterékoli pozdější verze This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Tento program je šířen v naději, že bude užite�ný, avšak BEZ JAKÉKOLI Z�RUKY; neposkytují se ani odvozené záruky PRODEJNOSTI nebo VHODNOSTI PRO URČIT� ÚČEL. Další podrobnosti najdete v Obecné veřejné licenci GNU (GNU General Public License). BitFieldWidget Reset bits to zero Vynulovat bity Invert bits Invertovat bity Shift bits left Posunout bity doleva Shift bits right Posunout bity doprava Book Index Rejstřík Algebra Algebra Quadratic Equation Kvadratická rovnice Logarithmic Base Conversion Převod logaritmického základu Geometry Geometrie Circle Kruh Sector Výse� Sphere Koule Cube Krychle Cone Kužel Cylinder Válec Electronics Elektronika Ohm's Law Ohmův zákon Power Výkon Reactance Jalový odpor Resonance Rezonance Radio Frequency Rádiová frekvence Antennas Antény Characteristic Impedance (coax) Charakteristická impedance (koaxiál) Velocity of Propagation (coax) Rychlost šíření (koaxiál) Standing Wave Ratio & Return Loss Poměr stojatých vln a zpětná ztráta Free Space Wavelength Vlnová délka ve volném prostoru resistance odpor voltage napětí current proud power Výkon inductive reactance Induk�ní jalový odpor capacitive reactance Kapacitní jalový odpor inductance Induktance capacitance Kapacitance frequency Kmito�et resonance frequency Kmito�et rezonance area Obsah perimeter Obvod diameter Průměr radius Poloměr volume Objem surface area povrch height Výška slant height stranová výška face diagonal úhlopří�ka stěny space diagonal tělesová úhlopří�ka edge length délka hrany arc length Délka oblouku central angle (degrees) Středový úhel (stupně) input power vstupní výkon reflected power odražený výkon transmitted power přenášený výkon return loss útlum odrazu dielectric constant Dielektrická konstanta outer conductor's inner diameter Vnitřní průměr vnějšího vodi�e inner conductor's outer diameter Vnější průměr vnitřního vodi�e speed of light Rychlost světla reflection coefficient Sou�initel odrazu standing wave ratio poměr stojatých vln normalized impedance Normalizovaná impedance frequency (Hz) Kmito�et (Hz) BookDock Formula Book Sbírka vzorců ConstantCompletion Search constants Hledat konstanty No match found Nenalezena žádná shoda Constants Mathematics Matematika Physics (CODATA 2022) Fyzika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chemie (IUPAC - CIAAW 2021) Uncategorized Nezařazeno Universal Všeobecný Physicochemical Fyzikálně-chemické Atomic & Nuclear — General Atomové a jaderné — obecné Atomic & Nuclear — Electroweak Atomové a jaderné — elektroslabé Atomic & Nuclear — Electron Atomové a jaderné — elektron Atomic & Nuclear — Muon Atomové a jaderné — mion Atomic & Nuclear — Tau Atomové a jaderné — tau Atomic & Nuclear — Proton Atomové a jaderné — proton Atomic & Nuclear — Neutron Atomové a jaderné — neutron Atomic & Nuclear — Deuteron Atomové a jaderné — deuteron Atomic & Nuclear — Triton Atomové a jaderné — triton Atomic & Nuclear — Helion Atomové a jaderné — helion Atomic & Nuclear — Alpha particle Atomové a jaderné — �ástice alfa Atomic & Nuclear — Atomic units Atomové a jaderné — atomové jednotky Atomic & Nuclear — Energy conversion relationships Atomové a jaderné — převodní vztahy energie Atomic & Nuclear — X-ray units Atomové a jaderné — rentgenové jednotky Atomic & Nuclear — Magnetic shielding corrections Atomové a jaderné — korekce magnetického stínění Masses Hmotnosti Lifetimes Doby života Molar Masses Molární hmotnosti Electronegativity Elektronegativita Ionization Energy Ioniza�ní energie Nominal Constants (IAU 2015) Nominální konstanty (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Aktuální nejlepší odhady (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) Charakteristická impedance vakua (Z₀) reduced Planck constant (�) Redukovaná Planckova konstanta (�) vacuum electric permittivity (ϵ₀) Elektrická permitivita vakua (ϵ₀) Newtonian constant of gravitation (G) Newtonova gravita�ní konstanta (G) vacuum magnetic permeability (μ₀) Magnetická permeabilita vakua (μ₀) Planck constant (h) Planckova konstanta (h) speed of light in vacuum (c) Rychlost světla ve vakuu (c) standard acceleration of gravity (gₙ) Standardní tíhové zrychlení (gₙ) Newtonian constant of gravitation over h-bar c Newtonova gravita�ní konstanta dělená �c Planck length Planckova délka Planck constant in eV/Hz (h) Planckova konstanta v eV/Hz (h) Planck mass Planckova hmotnost Planck mass energy equivalent in GeV Energetický ekvivalent Planckovy hmotnosti v GeV Planck temperature Planckova teplota Planck time Planckův �as reduced Planck constant in eV·s (�) Redukovaná Planckova konstanta v eV·s (�) reduced Planck constant times c in MeV·fm Redukovaná Planckova konstanta krát c v MeV·fm Bohr magneton Bohrov magneton conductance quantum (G₀) Kvantum vodivosti (G₀) Coulomb constant (kₑ) Coulombova konstanta (kₑ) elementary charge (e) Elementární náboj (e) elementary charge over h-bar Elementární náboj dělený h-bar conventional value of Josephson constant Konven�ní hodnota Josephsonovy konstanty Josephson constant Josephsonova konstanta conventional value of ampere-90 Konven�ní hodnota ampéru-90 conventional value of coulomb-90 Konven�ní hodnota coulombu-90 conventional value of farad-90 Konven�ní hodnota faradu-90 conventional value of henry-90 Konven�ní hodnota henry-90 conventional value of ohm-90 Konven�ní hodnota ohmu-90 conventional value of volt-90 Konven�ní hodnota voltu-90 conventional value of watt-90 Konven�ní hodnota wattu-90 magnetic flux quantum (Φ₀) Kvantum magnetického toku (Φ₀) nuclear magneton Jaderný magneton inverse of conductance quantum Převrácená hodnota kvanta vodivosti conventional value of von Klitzing constant Konven�ní hodnota von Klitzingovy konstanty von Klitzing constant Von Klitzingova konstanta atomic unit of magnetic dipole moment Atomová jednotka magnetického dipólového momentu atomic unit of magnetic flux density Atomová jednotka hustoty magnetického toku Bohr magneton in eV/T Bohrov magneton v eV/T Bohr magneton in Hz/T Bohrov magneton v Hz/T Bohr magneton in inverse meter per tesla Bohrov magneton v převrácených metrech na tesla Bohr magneton in K/T Bohrov magneton v K/T nuclear magneton in eV/T Jaderný magneton v eV/T nuclear magneton in inverse meter per tesla Jaderný magneton v převrácených metrech na tesla nuclear magneton in K/T Jaderný magneton v K/T nuclear magneton in MHz/T Jaderný magneton v MHz/T Bohr radius (a₀) Bohrov poloměr (a₀) fine-structure constant (α) Konstanta jemné struktury (α) Hartree energy (Eₕ) Hartreeho energie (Eₕ) Hartree energy in eV Hartreeho energie v eV quantum of circulation Kvantum cirkulace quantum of circulation times 2 Kvantum cirkulace krát 2 Rydberg constant (R∞) Rydbergova konstanta (R∞) atomic mass unit-hartree relationship Vztah atomové hmotnostní jednotky a hartree atomic mass unit-hertz relationship Vztah atomové hmotnostní jednotky a hertzu atomic mass unit-inverse meter relationship Vztah atomové hmotnostní jednotky a převráceného metru atomic mass unit-joule relationship Vztah atomové hmotnostní jednotky a joulu atomic mass unit-kelvin relationship Vztah atomové hmotnostní jednotky a kelvinu atomic mass unit-kilogram relationship Vztah atomové hmotnostní jednotky a kilogramu atomic unit of 1st hyperpolarizability Atomová jednotka 1. hyperpolarizovatelnosti atomic unit of 2nd hyperpolarizability Atomová jednotka 2. hyperpolarizovatelnosti atomic unit of charge (e) Atomová jednotka náboje (e) atomic unit of charge density Atomová jednotka hustoty náboje atomic unit of current Atomová jednotka proudu atomic unit of electric dipole moment Atomová jednotka elektrického dipólového momentu atomic unit of electric field Atomová jednotka elektrického pole atomic unit of electric field gradient Atomová jednotka gradientu elektrického pole atomic unit of electric polarizability Atomová jednotka elektrické polarizovatelnosti atomic unit of electric potential Atomová jednotka elektrického potenciálu atomic unit of electric quadrupole moment Atomová jednotka elektrického kvadrupólového momentu atomic unit of action Atomová jednotka akce atomic unit of energy Atomová jednotka energie atomic unit of force Atomová jednotka síly atomic unit of length Atomová jednotka délky hertz-atomic mass unit relationship Vztah hertzu a atomové hmotnostní jednotky hertz-electron volt relationship Vztah hertzu a elektronvoltu hertz-hartree relationship Vztah hertzu a hartree hertz-inverse meter relationship Vztah hertzu a převráceného metru hertz-joule relationship Vztah hertzu a joulu hertz-kelvin relationship Vztah hertzu a kelvinu hertz-kilogram relationship Vztah hertzu a kilogramu hyperfine transition frequency of Cs-133 Frekvence hyperjemného přechodu Cs-133 inverse fine-structure constant (α�¹) Převrácená hodnota konstanty jemné struktury (α�¹) inverse meter-atomic mass unit relationship Vztah převráceného metru a atomové hmotnostní jednotky inverse meter-electron volt relationship Vztah převráceného metru a elektronvoltu inverse meter-hartree relationship Vztah převráceného metru a hartree inverse meter-hertz relationship Vztah převráceného metru a hertzu inverse meter-joule relationship Vztah převráceného metru a joulu inverse meter-kelvin relationship Vztah převráceného metru a kelvinu inverse meter-kilogram relationship Vztah převráceného metru a kilogramu joule-atomic mass unit relationship Vztah joulu a atomové hmotnostní jednotky joule-electron volt relationship Vztah joulu a elektronvoltu joule-hertz relationship Vztah joulu a hertzu joule-hartree relationship Vztah joulu a hartree joule-inverse meter relationship Vztah joulu a převráceného metru joule-kelvin relationship Vztah joulu a kelvinu joule-kilogram relationship Vztah joulu a kilogramu kelvin-atomic mass unit relationship Vztah kelvinu a atomové hmotnostní jednotky kelvin-electron volt relationship Vztah kelvinu a elektronvoltu kelvin-hertz relationship Vztah kelvinu a hertzu kelvin-hartree relationship Vztah kelvinu a hartree kelvin-inverse meter relationship Vztah kelvinu a převráceného metru kelvin-joule relationship Vztah kelvinu a joulu kelvin-kilogram relationship Vztah kelvinu a kilogramu kilogram-atomic mass unit relationship Vztah kilogramu a atomové hmotnostní jednotky kilogram-electron volt relationship Vztah kilogramu a elektronvoltu kilogram-hertz relationship Vztah kilogramu a hertzu kilogram-hartree relationship Vztah kilogramu a hartree kilogram-inverse meter relationship Vztah kilogramu a převráceného metru kilogram-joule relationship Vztah kilogramu a joulu kilogram-kelvin relationship Vztah kilogramu a kelvinu lattice parameter of silicon (a) Mřížkový parametr křemíku (a) luminous efficacy Světelná ú�innost natural unit of energy Přirozená jednotka energie natural unit of energy in MeV Přirozená jednotka energie v MeV natural unit of action (�) Přirozená jednotka akce (�) natural unit of action in eV·s Přirozená jednotka akce v eV·s natural unit of length Přirozená jednotka délky natural unit of mass Přirozená jednotka hmotnosti natural unit of momentum Přirozená jednotka hybnosti natural unit of momentum in MeV/c Přirozená jednotka hybnosti v MeV/c natural unit of time Přirozená jednotka �asu natural unit of velocity Přirozená jednotka rychlosti Rydberg constant times c in Hz Rydbergova konstanta krát c v Hz Rydberg constant times hc in eV Rydbergova konstanta krát hc v eV Rydberg constant times hc in J Rydbergova konstanta krát hc v J Fermi coupling constant Fermiho vazebná konstanta weak mixing angle Úhel slabého mísení W to Z mass ratio Poměr hmotností W a Z Thomson cross section (σₑ) Thomsonův ú�inný průřez (σₑ) electron mass (mₑ) Hmotnost elektronu (mₑ) electron mass in u Hmotnost elektronu v u electron mass energy equivalent (mₑ·c²) Energetický ekvivalent hmotnosti elektronu (mₑ·c²) electron mass energy equivalent in MeV Energetický ekvivalent hmotnosti elektronu v MeV reduced Compton wavelength Redukovaná Comptonova vlnová délka classical electron radius (rₑ) Klasický poloměr elektronu (rₑ) electron charge to mass quotient Podíl náboje a hmotnosti elektronu electron-deuteron magnetic moment ratio Poměr magnetických momentů elektronu a deuteronu electron-deuteron mass ratio Poměr hmotností elektronu a deuteronu electron g factor (gₑ) Elektron g-faktor (gₑ) electron gyromagnetic ratio (γₑ) Elektron gyromagnetický poměr (γₑ) electron gyromagnetic ratio in MHz/T Elektron gyromagnetický poměr v MHz/T electron-helion mass ratio Poměr hmotností elektronu a helionu electron magnetic moment (μₑ) Elektron magnetický moment (μₑ) electron magnetic moment anomaly (aₑ) Anomálie magnetického momentu elektronu (aₑ) electron magnetic moment to Bohr magneton ratio Poměr magnetického momentu elektronu k Bohrovu magnetonu electron magnetic moment to nuclear magneton ratio Poměr magnetického momentu elektronu k jadernému magnetonu electron molar mass (Mₑ) Elektron molární hmotnost (Mₑ) electron-muon magnetic moment ratio Poměr magnetických momentů elektronu a mionu electron-muon mass ratio Poměr hmotností elektronu a mionu electron-neutron magnetic moment ratio Poměr magnetických momentů elektronu a neutronu electron-neutron mass ratio Poměr hmotností elektronu a neutronu electron-proton magnetic moment ratio Poměr magnetických momentů elektronu a protonu electron-proton mass ratio Poměr hmotností elektronu a protonu electron relative atomic mass (Ar(e)) Elektron relativní atomová hmotnost (Ar(e)) electron-tau mass ratio Poměr hmotností elektronu a tau electron to alpha particle mass ratio Poměr hmotností elektronu a �ástice alfa electron to shielded helion magnetic moment ratio Poměr magnetických momentů elektronu a stíněného helionu electron to shielded proton magnetic moment ratio Poměr magnetických momentů elektronu a stíněného protonu electron-triton mass ratio Poměr hmotností elektronu a tritonu electron volt-atomic mass unit relationship Vztah elektronvoltu a atomové hmotnostní jednotky electron volt-hartree relationship Vztah elektronvoltu a hartree electron volt-hertz relationship Vztah elektronvoltu a hertzu electron volt-inverse meter relationship Vztah elektronvoltu a převráceného metru electron volt-joule relationship Vztah elektronvoltu a joulu electron volt-kelvin relationship Vztah elektronvoltu a kelvinu electron volt-kilogram relationship Vztah elektronvoltu a kilogramu hartree-atomic mass unit relationship Vztah hartree a atomové hmotnostní jednotky hartree-electron volt relationship Vztah hartree a elektronvoltu muon Compton wavelength Comptonova vlnová délka mionu muon-electron mass ratio Poměr hmotností mionu a elektronu muon g factor Mion g-faktor muon magnetic moment Mion magnetický moment muon magnetic moment anomaly Anomálie magnetického momentu mionu muon magnetic moment to Bohr magneton ratio Poměr magnetického momentu mionu k Bohrovu magnetonu muon magnetic moment to nuclear magneton ratio Poměr magnetického momentu mionu k jadernému magnetonu muon mass Hmotnost mionu muon mass energy equivalent Energetický ekvivalent hmotnosti mionu muon mass energy equivalent in MeV Energetický ekvivalent hmotnosti mionu v MeV muon mass in u Hmotnost mionu v u muon molar mass Mion molární hmotnost muon-neutron mass ratio Poměr hmotností mionu a neutronu muon-proton magnetic moment ratio Poměr magnetických momentů mionu a protonu muon-proton mass ratio Poměr hmotností mionu a protonu muon-tau mass ratio Poměr hmotností mionu a tau reduced muon Compton wavelength Redukovaná Comptonova vlnová délka mionu reduced tau Compton wavelength Redukovaná Comptonova vlnová délka tau tau Compton wavelength Comptonova vlnová délka tau tau-electron mass ratio Poměr hmotností tau a elektronu tau mass Hmotnost tau tau mass energy equivalent Energetický ekvivalent hmotnosti tau tau mass in u Hmotnost tau v u tau molar mass Tau molární hmotnost tau-muon mass ratio Poměr hmotností tau a mionu tau-neutron mass ratio Poměr hmotností tau a neutronu tau-proton mass ratio Poměr hmotností tau a protonu proton charge to mass quotient Podíl náboje a hmotnosti protonu proton Compton wavelength Comptonova vlnová délka protonu proton-electron mass ratio Poměr hmotností protonu a elektronu proton g factor (gₚ) Proton g-faktor (gₚ) proton gyromagnetic ratio (γₚ) Proton gyromagnetický poměr (γₚ) proton gyromagnetic ratio in MHz/T Proton gyromagnetický poměr v MHz/T proton magnetic moment (μₚ) Proton magnetický moment (μₚ) proton magnetic moment to Bohr magneton ratio Poměr magnetického momentu protonu k Bohrovu magnetonu proton magnetic moment to nuclear magneton ratio Poměr magnetického momentu protonu k jadernému magnetonu proton magnetic shielding correction Korekce magnetického stínění protonu proton mass (mₚ) Hmotnost protonu (mₚ) proton mass energy equivalent Energetický ekvivalent hmotnosti protonu proton mass energy equivalent in MeV Energetický ekvivalent hmotnosti protonu v MeV proton mass in u Hmotnost protonu v u proton molar mass (Mₚ) Proton molární hmotnost (Mₚ) proton-muon mass ratio Poměr hmotností protonu a mionu proton-neutron magnetic moment ratio Poměr magnetických momentů protonu a neutronu proton-neutron mass ratio Poměr hmotností protonu a neutronu proton relative atomic mass (Ar(p)) Proton relativní atomová hmotnost (Ar(p)) proton rms charge radius Efektivní poloměr náboje protonu proton-tau mass ratio Poměr hmotností protonu a tau reduced proton Compton wavelength Redukovaná Comptonova vlnová délka protonu shielded proton gyromagnetic ratio Gyromagnetický poměr stíněného protonu shielded proton gyromagnetic ratio in MHz/T Gyromagnetický poměr stíněného protonu v MHz/T shielded proton magnetic moment Magnetický moment stíněného protonu shielded proton magnetic moment to Bohr magneton ratio Poměr magnetického momentu stíněného protonu k Bohrovu magnetonu shielded proton magnetic moment to nuclear magneton ratio Poměr magnetického momentu stíněného protonu k jadernému magnetonu neutron Compton wavelength Comptonova vlnová délka neutronu neutron-electron magnetic moment ratio Poměr magnetických momentů neutronu a elektronu neutron-electron mass ratio Poměr hmotností neutronu a elektronu neutron g factor (gₙ) Neutron g-faktor (gₙ) neutron gyromagnetic ratio (γₙ) Neutron gyromagnetický poměr (γₙ) neutron gyromagnetic ratio in MHz/T Neutron gyromagnetický poměr v MHz/T neutron magnetic moment (μₙ) Neutron magnetický moment (μₙ) neutron magnetic moment to Bohr magneton ratio Poměr magnetického momentu neutronu k Bohrovu magnetonu neutron magnetic moment to nuclear magneton ratio Poměr magnetického momentu neutronu k jadernému magnetonu neutron mass (mₙ) Hmotnost neutronu (mₙ) neutron mass energy equivalent Energetický ekvivalent hmotnosti neutronu neutron mass energy equivalent in MeV Energetický ekvivalent hmotnosti neutronu v MeV neutron mass in u Hmotnost neutronu v u neutron molar mass (Mₙ) Neutron molární hmotnost (Mₙ) neutron-muon mass ratio Poměr hmotností neutronu a mionu neutron-proton magnetic moment ratio Poměr magnetických momentů neutronu a protonu neutron-proton mass difference Rozdíl hmotností neutronu a protonu neutron-proton mass difference energy equivalent Energetický ekvivalent rozdílu hmotností neutronu a protonu neutron-proton mass difference energy equivalent in MeV Energetický ekvivalent rozdílu hmotností neutronu a protonu v MeV neutron-proton mass difference in u Rozdíl hmotností neutronu a protonu v u neutron-proton mass ratio Poměr hmotností neutronu a protonu neutron relative atomic mass (Ar(n)) Neutron relativní atomová hmotnost (Ar(n)) neutron-tau mass ratio Poměr hmotností neutronu a tau neutron to shielded proton magnetic moment ratio Poměr magnetických momentů neutronu a stíněného protonu reduced neutron Compton wavelength Redukovaná Comptonova vlnová délka neutronu deuteron-electron magnetic moment ratio Poměr magnetických momentů deuteronu a elektronu deuteron-electron mass ratio Poměr hmotností deuteronu a elektronu deuteron g factor g-faktor deuteronu deuteron magnetic moment Magnetický moment deuteronu deuteron magnetic moment to Bohr magneton ratio Poměr magnetického momentu deuteronu k Bohrovu magnetonu deuteron magnetic moment to nuclear magneton ratio Poměr magnetického momentu deuteronu k jadernému magnetonu deuteron mass Hmotnost deuteronu deuteron mass energy equivalent Energetický ekvivalent hmotnosti deuteronu deuteron mass energy equivalent in MeV Energetický ekvivalent hmotnosti deuteronu v MeV deuteron mass in u Hmotnost deuteronu v u deuteron molar mass Molární hmotnost deuteronu deuteron-neutron magnetic moment ratio Poměr magnetických momentů deuteronu a neutronu deuteron-proton magnetic moment ratio Poměr magnetických momentů deuteronu a protonu deuteron-proton mass ratio Poměr hmotností deuteronu a protonu deuteron relative atomic mass (Ar(d)) Relativní atomová hmotnost deuteronu (Ar(d)) deuteron rms charge radius Efektivní poloměr náboje deuteronu triton-electron mass ratio Poměr hmotností tritonu a elektronu triton g factor (gₜ) g-faktor tritonu (gₜ) triton magnetic moment (μₜ) Magnetický moment tritonu (μₜ) triton magnetic moment to Bohr magneton ratio Poměr magnetického momentu tritonu k Bohrovu magnetonu triton magnetic moment to nuclear magneton ratio Poměr magnetického momentu tritonu k jadernému magnetonu triton mass (mₜ) Hmotnost tritonu (mₜ) triton mass energy equivalent Energetický ekvivalent hmotnosti tritonu triton mass energy equivalent in MeV Energetický ekvivalent hmotnosti tritonu v MeV triton mass in u Hmotnost tritonu v u triton molar mass (Mₜ) Molární hmotnost tritonu (Mₜ) triton-proton mass ratio Poměr hmotností tritonu a protonu triton relative atomic mass (Ar(t)) Relativní atomová hmotnost tritonu (Ar(t)) triton to proton magnetic moment ratio Poměr magnetických momentů tritonu a protonu helion-electron mass ratio Poměr hmotností helionu a elektronu helion g factor (gₕ) g-faktor helionu (gₕ) helion magnetic moment (μₕ) Magnetický moment helionu (μₕ) helion magnetic moment to Bohr magneton ratio Poměr magnetického momentu helionu k Bohrovu magnetonu helion magnetic moment to nuclear magneton ratio Poměr magnetického momentu helionu k jadernému magnetonu helion mass (mₕ) Hmotnost helionu (mₕ) helion mass energy equivalent Energetický ekvivalent hmotnosti helionu helion mass energy equivalent in MeV Energetický ekvivalent hmotnosti helionu v MeV helion mass in u Hmotnost helionu v u helion molar mass (Mₕ) Molární hmotnost helionu (Mₕ) helion-proton mass ratio Poměr hmotností helionu a protonu helion relative atomic mass (Ar(h)) Relativní atomová hmotnost helionu (Ar(h)) helion shielding shift Posun stínění helionu shielded helion gyromagnetic ratio Gyromagnetický poměr stíněného helionu shielded helion gyromagnetic ratio in MHz/T Gyromagnetický poměr stíněného helionu v MHz/T shielded helion magnetic moment Magnetický moment stíněného helionu shielded helion magnetic moment to Bohr magneton ratio Poměr magnetického momentu stíněného helionu k Bohrovu magnetonu shielded helion magnetic moment to nuclear magneton ratio Poměr magnetického momentu stíněného helionu k jadernému magnetonu shielded helion to proton magnetic moment ratio Poměr magnetických momentů stíněného helionu a protonu shielded helion to shielded proton magnetic moment ratio Poměr magnetických momentů stíněného helionu a stíněného protonu alpha particle mass Hmotnost �ástice alfa alpha particle mass in u Hmotnost �ástice alfa v u alpha particle mass energy equivalent Energetický ekvivalent hmotnosti �ástice alfa alpha particle mass energy equivalent in MeV Energetický ekvivalent hmotnosti �ástice alfa v MeV alpha particle-electron mass ratio Poměr hmotností �ástice alfa a elektronu alpha particle-proton mass ratio Poměr hmotností �ástice alfa a protonu alpha particle rms charge radius Efektivní poloměr náboje �ástice alfa alpha particle molar mass Molární hmotnost �ástice alfa alpha particle relative atomic mass (Ar(α)) Relativní atomová hmotnost �ástice alfa (Ar(α)) atomic mass constant (mᵤ) Atomová hmotnostní konstanta (mᵤ) Avogadro constant Avogadrova konstanta Boltzmann constant (k) Boltzmannova konstanta (k) Boltzmann constant in eV/K Boltzmannova konstanta v eV/K Boltzmann constant in Hz/K Boltzmannova konstanta v Hz/K Boltzmann constant in inverse meter per kelvin Boltzmannova konstanta v převrácených metrech na kelvin electron volt (eV) Elektron volt (eV) Faraday constant (F) Faradayova konstanta (F) first radiation constant (c�) První radia�ní konstanta (c�) first radiation constant for spectral radiance První radia�ní konstanta pro spektrální zářivost molar gas constant (R) Molární plynová konstanta (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidtova konstanta (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Loschmidtova konstanta (n₀, 273.15 K, 101.325 kPa) molar Planck constant Molární Planckova konstanta second radiation constant (c₂) Druhá radia�ní konstanta (c₂) Stefan-Boltzmann constant (σ) Stefan-Boltzmannova konstanta (σ) lattice spacing of ideal Si (d₂₂₀) Mřížková vzdálenost ideálního Si (d₂₂₀) atomic mass constant energy equivalent Energetický ekvivalent atomové hmotnostní konstanty atomic mass constant energy equivalent in MeV Energetický ekvivalent atomové hmotnostní konstanty v MeV atomic mass unit-electron volt relationship Vztah atomové hmotnostní jednotky a elektronvoltu molar mass constant (Mᵤ) Molární hmotnostní konstanta (Mᵤ) molar mass of carbon-12 Molární hmotnost uhlíku-12 molar volume of ideal gas (273.15 K, 100 kPa) Molární objem ideálního plynu (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) Molární objem ideálního plynu (273.15 K, 101.325 kPa) molar volume of silicon Molární objem křemíku Sackur-Tetrode constant (1 K, 100 kPa) Sackurova-Tetrodeova konstanta (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackurova-Tetrodeova konstanta (1 K, 101.325 kPa) Wien frequency displacement law constant Wienova konstanta posunovacího zákona pro frekvenci Wien wavelength displacement law constant Wienova konstanta posunovacího zákona pro vlnovou délku standard atmosphere (atm) Standardní atmosféra (atm) standard-state pressure (p°) Standardní tlak (p°) Angstrom star (Å*) Angstromová hvězda (Å*) Copper x unit Měděná jednotka x Molybdenum x unit Molybdenová jednotka x atomic unit of magnetizability Atomová jednotka magnetizovatelnosti atomic unit of mass (mₑ) Atomová jednotka hmotnosti (mₑ) atomic unit of momentum Atomová jednotka hybnosti atomic unit of permittivity Atomová jednotka permitivity atomic unit of time Atomová jednotka �asu atomic unit of velocity Atomová jednotka rychlosti hartree-hertz relationship Vztah hartree a hertzu hartree-inverse meter relationship Vztah hartree a převráceného metru hartree-joule relationship Vztah hartree a joulu hartree-kelvin relationship Vztah hartree a kelvinu hartree-kilogram relationship Vztah hartree a kilogramu shielding difference of d and p in HD Rozdíl stínění d a p v HD shielding difference of t and p in HT Rozdíl stínění t a p v HT pi (π) pí (π) Euler's number (e) Eulerovo �íslo (e) golden ratio (φ) Zlatý řez (φ) Euler-Mascheroni constant (γ) Eulerova-Mascheroniho konstanta (γ) nominal solar radius Nominální slune�ní poloměr nominal solar total irradiance Nominální celkové slune�ní ozáření nominal solar luminosity Nominální slune�ní zářivost nominal solar effective temperature Nominální slune�ní efektivní teplota nominal solar mass parameter Nominální slune�ní hmotnostní parametr nominal terrestrial equatorial radius Nominální zemský rovníkový poloměr nominal terrestrial polar radius Nominální zemský polární poloměr nominal terrestrial mass parameter Nominální zemský hmotnostní parametr nominal jovian equatorial radius Nominální joviánský rovníkový poloměr nominal jovian polar radius Nominální joviánský polární poloměr nominal jovian mass parameter Nominální joviánský hmotnostní parametr average value of one minus the rate of TCG relative to TCB Průměrná hodnota jedné minus rychlost TCG vů�i TCB solar mass parameter (TCB-compatible) Slune�ní hmotnostní parametr (kompatibilní s TCB) solar mass parameter (TDB-compatible) Slune�ní hmotnostní parametr (kompatibilní s TDB) equatorial radius of the Earth (TT-compatible) Rovníkový poloměr Země (kompatibilní s TT) dynamical form factor of the Earth Dynamický tvarový faktor Země time rate of change in the dynamical form factor of the Earth Časová rychlost změny dynamického tvarového faktoru Země geocentric gravitational constant (TCB-compatible) Geocentrická gravita�ní konstanta (kompatibilní s TCB) geocentric gravitational constant (TT-compatible) Geocentrická gravita�ní konstanta (kompatibilní s TT) geocentric gravitational constant (TDB-compatible) Geocentrická gravita�ní konstanta (kompatibilní s TDB) potential of the geoid Potenciál geoidu nominal mean angular velocity of the Earth (TT-compatible) Nominální střední úhlová rychlost Země (kompatibilní s TT) ratio mass of the Moon to the Earth Poměr hmotnosti Měsíce k hmotnosti Země ratio of the mass of the Sun to Mercury Poměr hmotnosti Slunce k hmotnosti Merkuru ratio of the mass of the Sun to Venus Poměr hmotnosti Slunce k hmotnosti Venuše ratio of the mass of the Sun to Mars Poměr hmotnosti Slunce k hmotnosti Marsu ratio of the mass of the Sun to Jupiter Poměr hmotnosti Slunce k hmotnosti Jupiteru ratio of the mass of the Sun to Saturn Poměr hmotnosti Slunce k hmotnosti Saturnu ratio of the mass of the Sun to Uranus Poměr hmotnosti Slunce k hmotnosti Uranu ratio of the mass of the Sun to Neptune Poměr hmotnosti Slunce k hmotnosti Neptunu ratio of the mass of the Sun to (134340) Pluto Poměr hmotnosti Slunce k hmotnosti (134340) Pluta ratio of the mass of the Sun to (136199) Eris Poměr hmotnosti Slunce k hmotnosti (136199) Eris ratio of the mass of (1) Ceres to the Sun Poměr hmotnosti (1) Ceres k hmotnosti Slunce ratio of the mass of (2) Pallas to the Sun Poměr hmotnosti (2) Pallas k hmotnosti Slunce ratio of the mass of (4) Vesta to the Sun Poměr hmotnosti (4) Vesta k hmotnosti Slunce mean obliquity of the ecliptic at J2000.0 Střední sklon ekliptiky v J2000.0 Electromagnetic Elektromagnetismus Compton wavelength Comptonova vlnová délka Astronomy Astronomie ConstantsWidget Domain Doména Subdomain Poddoména No match found Nenalezena žádná shoda Name Název Value Hodnota Unit Jednotka Search Hledat All Vše CustomKeypadDialog Custom Keypad Vlastní klávesnice Rows: Řádky: Columns: Sloupce: Copy preset: Kopírovat předvolbu: Basic Základní Scientific (wide) Vědecké (široké) Scientific (narrow) Vědecké (úzké) Apply Použít Row Řádek Column Sloupec Label Popis Behavior Chování Text Text DiagnosticsDialog App Diagnostics Diagnostika aplikace Copy to Clipboard Kopírovat do schránky Editor Unit Jednotka User unit Uživatelská jednotka User function Uživatelská funkce Argument Argument Current result:<br/>%1 Aktuální výsledek:<br/>%1 Selection result:<br/>%1 Výsledek výběru:<br/>%1 Selection result: n/a Vybraný výsledek: nedostupný Selection result: %1 Vybraný výsledek: %1 second sekunda metre metr kilogram kilogram mole mol radian radián steradian steradián degree Celsius stupeň Celsia cubic metre krychlový metr cubic millimetre krychlový milimetr cubic centimetre krychlový centimetr cubic decimetre krychlový decimetr cubic kilometre krychlový kilometr square millimetre �tvere�ní milimetr square kilometre �tvere�ní kilometr square metre �tvere�ní metr minute minuta hour hodina day den astronomical unit astronomická jednotka degree stupeň arcminute úhlová minuta arcsecond úhlová sekunda milliarcsecond miliúhlová sekunda microarcsecond mikroúhlová sekunda hectare hektar litre litr tonne tuna Dalton dalton electronvolt elektronvolt Angstrom angstrom atmosphere atmosféra atomic mass unit atomová hmotnostní jednotka British thermal unit britská tepelná jednotka calorie kalorie carat karát cup šálek cup (Imperial) šálek (imperiální) cup (Japanese) šálek (japonský) cup (US) šálek (USA) degree Fahrenheit stupeň Fahrenheita fathom sáh fluid ounce (Imperial) tekutá unce (imperiální) fluid ounce (US) tekutá unce (USA) fluid dram (Imperial) tekutý dram (imperiální) fluid dram (US) tekutý dram (USA) foot stopa square foot �tvere�ní stopa cubic foot kubická stopa gallon (Imperial) galon (imperiální) gallon (US) galon (USA) gill (Imperial) gill (imperiální) gill (US) gill (USA) gradian grad grain grain gram gram Hartley hartley Hartree energy unit Hartreeho jednotka energie horsepower konská síla inch palec square inch �tvere�ní palec cubic inch krychlový palec karat karát knot uzel lightminute světelná minuta lightsecond světelná sekunda lightyear světelný rok long ton dlouhá tuna mile míle square mile �tvere�ní míle cubic mile kubická míle mile per hour míle za hodinu kilometre per hour kilometr za hodinu nautical mile námořní míle ounce unca parsec parsek pint (Imperial) pinta (imperiální) pint (US) pinta (USA) pound libra pounds per square inch libry na �tvere�ní palec quart (Imperial) kvarta (imperiální) quart (US) kvarta (USA) oil barrel ropný barel beer barrel (US) pivní barel (USA) square yard �tvere�ní yard cubic yard krychlový yard short ton krátká tuna tablespoon polévková lžíce tablespoon (Australian) polévková lžíce (australská) tablespoon (Imperial) polévková lžíce (imperiální) tablespoon (US) polévková lžíce (USA) dessert spoon dezertní lžíce teaspoon �ajová lži�ka teaspoon (Imperial) �ajová lži�ka (imperiální) teaspoon (US) �ajová lži�ka (USA) turn otá�ka revolution otá�ka revolution per minute otá�ka za minutu week týden kilowatt hour kilowatthodina millimetre of mercury milimetr rtuťového sloupce yard yard Julian century juliánské století Julian year juliánský rok sidereal year siderický rok tropical year tropický rok Evaluator invalid expression neplatný výraz division by zero dělení nulou too time consuming - computation was rejected příliš �asově náro�né - výpo�et byl odmítnut dimension mismatch - quantities with different dimensions cannot be compared, added, etc. nesoulad rozměrů - veli�iny s odlišnými rozměry nelze porovnávat, s�ítat atd. invalid dimension - operation might require dimensionless arguments neplatný rozměr - operace může vyžadovat bezrozměrné argumenty Computation aborted - encountered numerical instability výpo�et byl přerušen - byla zjištěna numerická nestabilita invalid dimension - function might require dimensionless arguments neplatný rozměr - funkce může vyžadovat bezrozměrné argumenty error Chyba unit must not be zero Jednotka nesmí být nula Conversion failed - dimension mismatch Převod se nezdařil - neodpovídající rozměr unknown function or variable neznámá funkce nebo proměnná recursion not supported Rekurze není podporována cannot operate on a NaN nelze pracovat s ne�íselnou hodnotou underflow - tiny result is out of SpeedCrunch's number range podte�ení - příliš malý výsledek je mimo �íselný rozsah SpeedCrunch overflow - huge result is out of SpeedCrunch's number range přete�ení - příliš velký výsledek je mimo �íselný rozsah SpeedCrunch overflow - logic result exceeds maximum of 256 bits přete�ení - logický výsledek přesáhl maximum 256 bitů overflow - integer result exceeds maximum limit for integers přete�ení - celo�íselný výsledek přesáhl maximum pro celá �ísla operation is not defined for these arguments operace není pro tyto argumenty definována wrong number of arguments nesprávný po�et argumentů does not take NaN as an argument NaN není jako argument dovolen result out of range výsledek je mimo rozsah undefined for argument domain pro defini�ní obor argumentu není definováno computation too expensive výpo�et by byl příliš nákladný internal error, please report a bug vnitřní chyba, nahlaste, prosím, chybu syntax error chyba syntaxe conversion target must be a unit cíl převodu musí být jednotka unknown unit neznámá jednotka %1 is a reserved name, please choose another %1 je vyhrazené jméno, vyberte, prosím, jiné %1 is a global user definition and cannot be overridden in this session. %1 je globální uživatelská definice a v této relaci ji nelze přepsat. %1 is a variable name, please choose another or delete the variable %1 je název proměnné. Vyberte, prosím, jiné nebo smažte proměnnou argument %1 is used more than once argument %1 je použit vícekrát než jednou %1 is a built-in unit name, please choose another %1 je název vestavěné jednotky, zvolte jiný %1 is a user function name, please choose another or delete the function %1 je uživatelská funkce. Vyberte, prosím, jiné nebo smažte funkci FunctionRepo max; trials; probability maximum; pokusy; pravděpodobnost trials; probability pokusy; pravděpodobnost hits; trials; probability úspěchy; pokusy; pravděpodobnost max; total; hits; trials maximum; celkem; úspěchy; pokusy total; hits; trials celkem; úspěchy; pokusy count; total; hits; trials po�et; celkem; úspěchy; pokusy dividend; divisor dělenec; dělitel x; exponent_bits; significand_bits [; exponent_bias] x; bity exponentu; bity mantisy [; posun exponentu] base; x základ; x value; modulo hodnota; modulo base; exponent; modulo základ; exponent; modulo events; average_events události; průměr_událostí average_events průměr_událostí x [; precision] x [; přesnost] Absolute Value Absolutní hodnota Absolute Deviation Absolutní odchylka Arc Cosine Arkus kosinus Logical AND Logické A Area Hyperbolic Cosine Hyperbolický arkus kosinus Area Hyperbolic Sine Hyperbolický arkus sinus Area Hyperbolic Tangent Hyperbolický arkus tangens Arc Sine Arkus sinus Arc Tangent Arkus tangens Arc Tangent with two Arguments Arkus tangens se dvěma argumenty Average (Arithmetic Mean) Průměr (aritmetický) Binomial Cumulative Distribution Function Distribu�ní funkce binomického rozdělení Binomial Distribution Mean Střední hodnota binomického rozdělení Binomial Probability Mass Function Pravděpodobnostní funkce binomického rozdělení Binomial Distribution Variance Rozptyl binomického rozdělení Cube Root Třetí odmocnina Complex Conjugate Sdružený komplex Cosine Kosinus Hyperbolic Cosine Hyperbolický kosinus Cotangent Kotangens Cosecant Kosekans Convert Unix timestamp to Date Převést �asové razítko Unix na datum Degrees of Arc Úhlová míra ve stupních Error Function Chybová funkce Complementary Error Function Doplňková chybová funkce Exponential Exponenciální funkce Fractional Part Zlomková �ást Extension of Factorials [= (x-1)!] Rozšíření faktoriálů [= (x-1)!] Greatest Common Divisor Největší spole�ný dělitel Geometric Mean Geometrický průměr Gradians of arc Gradiány oblouku Hypergeometric Cumulative Distribution Function Distribu�ní funkce hypergeometrického rozdělení Hypergeometric Distribution Mean Střední hodnota hypergeometrického rozdělení Hypergeometric Probability Mass Function Pravděpodobnostní funkce hypergeometrického rozdělení Hypergeometric Distribution Variance Rozptyl hypergeometrického rozdělení Integer Quotient Celo�íselný podíl Integer Part Celo�íselná �ást Imaginary Part Imaginární �ást Decode IEEE-754 Binary Value Dekódovat IEEE-754 binární hodnotu Encode IEEE-754 Binary Value Zakódovat IEEE-754 binární hodnotu Decode 16-bit Half-Precision Value Dekódovat 16-bitovou hodnotu s polovi�ní přesností Encode 16-bit Half-Precision Value Zakódovat 16-bitovou hodnotu s polovi�ní přesností Decode 32-bit Single-Precision Value Dekódovat 32-bitovou hodnotu s jednoduchou přesností Encode 32-bit Single-Precision Value Zakódovat 32-bitovou hodnotu s jednoduchou přesností Decode 64-bit Double-Precision Value Dekódovat 64-bitovou hodnotu s dvojnásobnou přesností Encode 64-bit Double-Precision Value Zakódovat 64-bitovou hodnotu s dvojnásobnou přesností Decode 128-bit Quad-Precision Value Dekódovat 128-bitovou hodnotu se �tyřnásobnou přesností Encode 128-bit Quad-Precision Value Zakódovat 128-bitovou hodnotu se �tyřnásobnou přesností Binary Logarithm Dvojkový logaritmus Common Logarithm Desítkový logaritmus Natural Logarithm Přirozený logaritmus Logarithm to Arbitrary Base Logaritmus na libovolný základ Mask to a bit size Zakrýt na délku bitu Maximum Maximum Median Value (50th Percentile) Střední hodnota (50. percentil) Minimum Minimum Modulo Modulo Euclidean Modulo Eukleidovské modulo Modular Exponentiation Modulární umocňování Combination (Binomial Coefficient) Kombinace (kombina�ní �íslo) Logical NOT Logické NE Permutation (Arrangement) Permutace (uspořádání) Convert to Binary Representation Převést na dvojkovou soustavu Arithmetic Aritmetika Chemistry Chemie Complex Komplexní Combinatorics Kombinatorika Probability Pravděpodobnost Statistics Statistika Aggregation Agregace Random Náhodné Base conversion Převod soustav Number formatting Formátování �ísel Integer arithmetic Celo�íselná aritmetika Special functions Speciální funkce Exponential & Logarithmic Exponenciální a logaritmické Angle conversion Převod úhlů Trigonometry Trigonometrie Bitwise Bitové Floating point Pohyblivá řádová �árka Date & Time Datum a �as Linear algebra Lineární algebra unix_timestamp; x hours offset to GMT unix_timestamp; posun o x hodin oproti GMT yyyymmdd.hhmmss; x hours offset to GMT rrrrmmdd.hhmmss; posun o x hodin oproti GMT [digits] [�íslice] max [; min] max [; min] List Literal Literál seznamu Convert to Padded Binary Representation Převést na doplněnou binární reprezentaci Round Toward +∞ (Ceiling) Zaokrouhlit směrem k +∞ (strop) Cosine plus Imaginary Sine Kosinus plus imaginární sínus Convert to Cis Complex Form Převést na komplexní tvar cis Matrix Column Count Po�et sloupců matice Population Correlation Matrix (n) Korela�ní matice populace (n) Sample Correlation Matrix (n-1) Korela�ní matice vzorku (n-1) Count Po�et Population Covariance Matrix (n) Kovarian�ní matice populace (n) Sample Covariance Matrix (n-1) Kovarian�ní matice vzorku (n-1) Cross Product Vektorový sou�in Convert Date to Unix timestamp Převést datum na unixové �asové razítko Convert to Decimal Representation Převést na desítkovou soustavu Determinant Determinant Convert to Sexagesimal Notation Převést na šedesátkový zápis Dot Product Skalární sou�in Convert to Engineering Notation Převést na technický zápis Convert to Exponential Complex Form Převést na exponenciální komplexní tvar Round Toward −∞ (Floor) Zaokrouhlit směrem k −∞ (floor) Flatten Matrix Zploštit matici Least Common Multiple Nejmenší spole�ný násobek Convert to Hexadecimal Representation Převést na šestnáctkovou soustavu Convert to Padded Hexadecimal Representation Převést na šestnáctkovou reprezentaci s doplněním Inverse Matrix Inverzní matice Round to 16-bit Half-Precision Value Zaokrouhlit na 16bitovou hodnotu s polovi�ní přesností Round to 32-bit Single-Precision Value Zaokrouhlit na 32bitovou hodnotu s jednoduchou přesností Round to 64-bit Double-Precision Value Zaokrouhlit na 64bitovou hodnotu s dvojitou přesností Round to 128-bit Quad-Precision Value Zaokrouhlit na 128bitovou hodnotu se �tyřnásobnou přesností Residual from 16-bit Half-Precision Rounding Zbytek po 16bitovém zaokrouhlení s polovi�ní přesností Residual from 32-bit Single-Precision Rounding Zbytek po 32bitovém zaokrouhlení s jednoduchou přesností Residual from 64-bit Double-Precision Rounding Zbytek po 64bitovém zaokrouhlení s dvojitou přesností Residual from 128-bit Quad-Precision Rounding Zbytek po 128bitovém zaokrouhlení se �tyřnásobnou přesností Substance Mass Hmotnost látky Molarity Molarita Molar Mass Molární hmotnost Median Absolute Deviation Mediánová absolutní odchylka Mean Průměr Numerical Value of Quantity Číselná hodnota veli�iny Random Decimal Number Náhodné desetinné �íslo Random Integer Number Náhodné celé �íslo Convert to Rational Representation Převést na racionální reprezentaci Convert to Octal Representation Převést na osmi�kovou soustavu Convert to Padded Octal Representation Převést na osmi�kovou reprezentaci s doplněním Vector or Matrix Norm Norma vektoru nebo matice Logical OR Logické NEBO Population Count (Hamming Weight) Po�et jedni�ek (Hammingova váha) Phase of Complex Number Fáze komplexního �ísla Poissonian Cumulative Distribution Function Distribu�ní funkce Poissonova rozdělení Poissonian Distribution Mean Střední hodnota Poissonova rozdělení Poissonian Probability Mass Function Pravděpodobnostní funkce Poissonova rozdělení Poissonian Distribution Variance Rozptyl Poissonova rozdělení Convert to Phasor Complex Form Převést na fázorový komplexní tvar Convert to Rectangular Complex Form Převést na pravoúhlý komplexní tvar Round Half Away from Zero Zaokrouhlit polovinu od nuly Round Half Even Zaokrouhlit polovinu na sudé Nth Root N-tá odmocnina Convert to Scientific Notation Převést na vědecký zápis Matrix Row Count Po�et řádků matice List or Matrix Shape Tvar seznamu nebo matice Summation Sou�et Population Standard Deviation (n) Směrodatná odchylka populace (n) Sample Standard Deviation (n-1) Směrodatná odchylka vzorku (n-1) Round Toward Zero (Truncation) Zaokrouhlit směrem k nule (oříznutí) Matrix Trace Stopa matice Transpose Matrix Transponovat matici Population Variance (n) Rozptyl populace (n) Sample Variance (n-1) Rozptyl vzorku (n-1) Product Sou�in Radians Radiány Matrix Rank Hodnost matice Real Part Reálná �ást Secant Sekans Arithmetic Shift Left Aritmetický posuv doleva Arithmetic Shift Right Aritmetický posuv doprava Signum signum Sine Sinus Hyperbolic Sine Hyperbolický sinus Square Root Druhá odmocnina Sum Sou�et Tangent Tangens Convert to Trigonometric Complex Form Převést na trigonometrický komplexní tvar Turns Oto�ky Hyperbolic Tangent Hyperbolický tangens Sign-extend a value Rozšíření znaménka hodnoty Logical XOR Logické výhradní NEBO (XOR; negace ekvivalence) FunctionsWidget Domain Doména All Vše Name Název Search Hledat No match found Nenalezena žádná shoda Identifier Identifikátor HistoryWidget Remove All Calculations Above Odstranit všechny výpo�ty nad Remove This Calculation Odstranit tento výpo�et Remove All Calculations Below Odstranit všechny výpo�ty pod Keypad Inverse cosine Obrácený kosinus The last result Poslední výsledek Inverse sine Obrácený sinus Inverse tangent Obrácený tangens Evaluate expression Vyhodnotit výraz Division Dělení Multiplication Násobení Subtraction Od�ítání Addition S�ítání Clear expression Smazat výraz Cosine Kosinus Backspace Backspace Scientific notation Vědecký zápis Exponential Exponenciální Factorial Faktoriál Natural logarithm Přirozený logaritmus Left parenthesis Levá závorka Nth root N-tá odmocnina Argument separator Oddělova� argumentů Square Druhá mocnina Common logarithm Dekadický logaritmus Modulo Modulo Contextual percentage Kontextové procento Power Mocnina Right parenthesis Pravá závorka Sine Sinus Square root Odmocnina Tangent Tangens Pi Pí Decimal separator Desetinný oddělova� MainWindow Radian Radián Degree Stupeň Gradian Gradián Binary Binární Octal Osmi�kový Hexadecimal Šestnáctková Sexagesimal Šedesátkový Engineering decimal Technická desítková Scientific decimal Vědecká desítková &Import... &Importovat... &Quit U&kon�it Clear E&xpression Smazat vý&raz Clear &History Smazat &historii &Copy K&opírovat &Paste &Vložit &Select Expression &Vybrat výraz &Constants &Konstanty &Functions &Funkce &History &Historie &Status Bar &Stavový řádek Bitfield Bitové pole Use&r Functions &Uživatelské funkce &Degree &Stupeň &Radian &Radián &Gradian &Gradián Re&volution O&tá�ka Auto-Insert a&ns Automaticky vložit a&ns Automatic &Completion Automatické &dokon�ování &Built-in Functions &Vestavěné funkce Built-in &Variables V&estavěné proměnné User &Functions Uživatelské &funkce User Va&riables Uživatelské p&roměnné Open a Private Tab on Startup Při spuštění otevřít soukromou kartu Open and focus a new private tab whenever SpeedCrunch starts. Při každém spuštění SpeedCrunch otevřít a aktivovat novou soukromou kartu. Syntax &Highlighting &Zvýrazňování syntaxe Group Digits in &Input Seskupovat �ísl&ice na vstupu Automatic Input &Adjustments &Automatické úpravy vstupu Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Automaticky upravovat operátory, mezery, závorky a mocniny a omezit vstup na platné znaky. Group input digits using the selected number format. Seskupovat zadané �íslice podle vybraného �íselného formátu. &Blinking Cursor &Blikající kurzor Blink the cursor in the expression editor. Nechat kurzor v editoru výrazů blikat. &Escape Clears Editor &Escape vymaže editor Clear the focused expression editor with Escape after dismissing any popup or preview. Klávesou Escape vymazat aktivní editor výrazů po zavření případných vyskakovacích oken �i náhledů. Keep Expression After Evaluation Ponechat výraz po vyhodnocení Copy New Results Automatically Automaticky kopírovat nové výsledky &Comma Čár&ka &System Default Výchozí nastavení &systému &Dot &Te�ka Dot &And Comma Te�ka &a �árka Toward +∞ (&ceil) Směrem k +∞ (&ceil) Toward −∞ (&floor) Směrem k −∞ (&floor) &Binary &Binární &Engineering &Technický &Hexadecimal &Šestnáctkový &Octal &Osmi�kový &Scientific &Vědecký User &Manual Uživatelská &příru�ka Issues and &Feedback P&roblémy a připomínky &Donate &Darovat &About SpeedCrunch &O programu SpeedCrunch App Diag&nostics Diag&nostika aplikace S&plit &Rozdělit Angle &Mode Reži&m úhlů &Complex Form &Komplexní tvar New Tab Nová karta Constants Konstanty Functions Funkce History Historie User Functions Uživatelské funkce &Font... &Písmo... &Language... &Jazyk... &Session &Relace &Edit Úp&ravy &View &Zobrazení Se&ttings Nas&tavení &Decimal &Desítkový &Keypad &Klávesnice Always on &Top Vždy na&hoře Disabled Zakázáno Small Space Úzká mezera Medium Space Střední mezera Large Space Široká mezera &0 Digits &0 míst &15 Digits &15 míst &2 Digits &2 místa &3 Digits &3 místa &50 Digits &50 míst &8 Digits &8 míst &Sexagesimal &Šedesátkový Reset All Settings... Obnovit všechna nastavení... &System &Systém SpeedCrunch &Theme Mo&tiv SpeedCrunch &Classic Klasi&cký &Modern &Moderní Context Help Související nápověda &Help &Nápověda Error Chyba Can't read from file %1 Nelze �íst ze souboru %1 Import Session Importovat relaci Close Session Zavřít relaci Angle Mode: Režim úhlů: Notation: Zápis: Precision: Přesnost: Turn Oto�ka Revolution Otá�ka Fixed-point decimal Desetinný zápis s pevnou řádovou �árkou Rational Racionální Automatic decimal Automatický desetinný zápis Automatic Automaticky User &Definitions... Uživatelské &definice... New &Tab Nová &karta New &Private Tab &Nová soukromá karta Keep Ponechat Make Private... Změnit na soukromou... New &Window Nové &okno &Open... &Otevřít... &Rename... &Přejmenovat... Clo&ne... Klono&vat... &Close Tab &Zavřít kartu Reopen Clo&sed Tab Znov&u otevřít zavřenou kartu Open Sessions &Folder Otevřít &složku relací &Undo &Zpět &Redo Z&novu Cu&t Vyjmou&t Copy &Last Result Kopírovat pos&lední výsledek &Wrap in Parentheses &Uzavřít do závorek Full Scr&een Mode R&ežim celé obrazovky &Basic &Základní &Scientific (wide) &Vědecké (široké) Scientific (narrow) Vědecké (úzké) &Custom... &Vlastní... Main &Menu Hlavní &nabídka User &Variables Uživatelské &proměnné &Left V&levo &Right Vp&ravo &Up Nahor&u &Down &Dolů Close Pa&ne &Zavřít panel User &Units Uživatelské &jednotky &Turn &Oto�ka If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Pokud nový výraz za�íná na +, -, * nebo /, SpeedCrunch nejprve vloží „ans“. &Accept with Enter &Přijmout klávesou Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Přijmout aktuální návrh automatického doplňování klávesou Enter bez předchozího výběru pomocí šipek. &Units &Jednotky Show Live Result &Preview Zobrazit živý &náhled výsledku Save &Window Position on Exit Uložit polohu &okna při ukon�ení Hover Highlighting Zvýraznění při přejetí myší Group Integer Part Only Seskupovat pouze celo�íselnou �ást Number Format... Formát �ísla... Notation && Precision... Zápis a přesnost... After pressing Enter, keep the entered expression selected in the editor. Po stisknutí klávesy Enter ponechat zadaný výraz vybraný v editoru. Never Nikdy Always Vždy Only for Single-Line Expressions Pouze pro jednořádkové výrazy Simplify Displayed Expressions Zjednodušit zobrazené výrazy History Size &Limit... &Limit velikosti historie... Remove Trailing &Zeroes &Odstranit koncové nuly Nearest, Half &Away (round) Nejbližší, polovina &od nuly (round) Nearest, Half &Even (roundeven) Nejbližší, polovina na &sudé (roundeven) Toward &Zero (trunc) Směrem k &nule (trunc) &Fixed-Point S &pevnou řádovou �árkou &Rational &Racionální &Exponential (m·s�¹) &Exponenciální (m·s�¹) &Fractional (m/s) &Zlomkový (m/s) &Rectangular (a + bi) &Pravouhlý (a + bi) Exponential (re�ᶿ) Exponenciální (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonometrický (r(cos θ + i·sin θ)) Phasor (r∠θ) Fázor (r∠θ) &Theme... &Motiv... Check for &Updates Zkontrolovat &aktualizace Source Code Zdrojový kód &Zoom &Přiblížení &Results &Výsledky Unit Notation Zápis jednotek Rounding Mode Režim zaokrouhlování &Notation &Zápis &Imaginary Unit &Imaginární jednotka &Window &Okno &Editing &Úpravy A&utocomplete A&utomatické doplňování Up/Down Arrow History Historie šipkami nahoru/dolů &Appearance &Vzhled &Menus &Nabídky &Docks &Dokovatelné panely &Input and Results &Vstup a výsledky &Disabled &Vypnuté &Disable &Vypnout Close preview Zavřít náhled Rename... Přejmenovat... Clone... Klonovat... Close Tab Zavřít kartu New Private Tab Nová soukromá karta Open... Otevřít... Reopen Closed Tab Znovu otevřít zavřenou kartu Split Rozdělit Left Vlevo Right Vpravo Up Nahoru Down Dolů Clear Vymazat Delete Smazat %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Soukromé relace: obsah se při zavření zahodí. Volbou Relace > Ponechat jej změníte na běžné relace. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Soukromé] Reset All Settings Obnovit všechna nastavení Reset all settings to their default values? Obnovit výchozí hodnoty všech nastavení? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Zahrnuje to vzhled, úpravy, formáty výsledků a předvolby oken. Vaše výpo�ty, otevřená relace a uživatelské definice zůstanou zachovány. The settings file could not be written. Soubor nastavení se nepodařilo zapsat. Clear this session's calculations, unfinished expression, variables, functions, and units? Vymazat výpo�ty, nedokon�ený výraz, proměnné, funkce a jednotky tohoto relace? Global user definitions are kept. Globální uživatelské definice zůstanou zachovány. Make Session Private Změnit relace na soukromé The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Uložené relace %1 bude odstraněno. Jeho obsah zůstane otevřený v soukromém relace a bude zahozen při zavření tohoto relace nebo ukon�ení SpeedCrunch. Make Private Změnit na soukromou Could not delete the saved session %1. Uložené relace %1 se nepodařilo odstranit. Keep Session Ponechat relace Could not save the session. It remains private. Relace se nepodařilo uložit. Zůstává soukromé. Clone Session Klonovat relace Could not save session file %1. Soubor relace %1 se nepodařilo uložit. Could not delete session file %1. Soubor relace %1 se nepodařilo odstranit. JSON file (*.json);;Any file (*.*) Soubor JSON (*.json);;Libovolný soubor (*.*) Export session as JSON Exportovat relaci jako JSON The selected file is not valid JSON: %1 Vybraný soubor není platný JSON: %1 The selected file is not a SpeedCrunch session JSON file. Vybraný soubor není soubor JSON relace SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Tento soubor používá zastaralý formát relace SpeedCrunch a nelze jej importovat. The selected JSON file is missing the required $schema field. Ve vybraném souboru JSON chybí povinné pole $schema. The selected JSON file uses an unsupported JSON schema: %1 Vybraný soubor JSON používá nepodporované schéma JSON: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Ve vybraném souboru JSON chybí identifikátor schématu relace SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Vybraný soubor JSON používá nepodporovaný formát relace SpeedCrunch: %1 The selected JSON file is missing the required session name. Ve vybraném souboru JSON chybí povinný název relace. The selected JSON file has an empty session name. Vybraný soubor JSON má prázdný název relace. The selected JSON file has invalid or incomplete SpeedCrunch session data. Vybraný soubor JSON obsahuje neplatná nebo neúplná data relace SpeedCrunch. Open Sessions Folder Otevřít složku relací Could not create the sessions folder: %1 Nelze vytvořit složku relací: %1 Could not open the sessions folder: %1 Nelze otevřít složku relací: %1 Editor and Results Font Písmo editoru a výsledků Open Session Otevřít relaci Community Komunita Rename Session Přejmenovat relaci Clear Session Vymazat relaci Delete Session Odstranit relaci Close Pane Zavřít panel User Variables Uživatelské proměnné User Units Uživatelské jednotky Clear History Vymazat historii Are you sure you want to clear the calculation history? Opravdu chcete vymazat historii výpo�tů? Session name: Název relace: A session named %1 already exists. Relace s názvem %1 již existuje. Could not create session file %1. Nepodařilo se vytvořit soubor relace %1. Could not write session file %1. Nepodařilo se zapsat soubor relace %1. Are you sure you want to delete this session? Opravdu chcete odstranit tuto relaci? Custom Precision Vlastní přesnost Fractional digits: Desetinná místa: Theme Motiv Light Themes Světlé motivy Dark Themes Tmavé motivy Preview Náhled Colors Barvy Select color for %1 Vybrat barvu pro %1 Import... Importovat... Export... Exportovat... Import Theme Importovat motiv Theme file (*.json);;All files (*) Soubor motivu (*.json);;Všechny soubory (*) Invalid theme file. Neplatný soubor motivu. Can't import theme "%1" because it conflicts with a built-in theme. Motiv „%1“ nelze importovat, protože je v konfliktu s vestavěným motivem. Can't find a writable theme folder. Nelze najít zapisovatelnou složku motivů. Overwrite Theme Přepsat motiv A custom theme named "%1" already exists. Do you want to overwrite it? Vlastní motiv s názvem „%1“ již existuje. Chcete jej přepsat? Can't overwrite theme file %1 Nelze přepsat soubor motivu %1 Can't copy theme file to %1 Nelze zkopírovat soubor motivu do %1 Export Theme Exportovat motiv Can't export theme as "%1" because it conflicts with a built-in theme. Motiv nelze exportovat jako „%1“, protože je v konfliktu s vestavěným motivem. Can't write to file %1 Nelze zapisovat do souboru %1 Global User Variable Globální uživatelská proměnná Global User Function Globální uživatelská funkce Global User Unit Globální uživatelská jednotka User Definitions Uživatelské definice These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Tyto definice jsou globální a na�ítají se do každé relace. V relacích je nelze měnit a mají přednost před definicemi se stejným názvem z editoru relace. Zadejte jednu definici na řádek. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Příklady: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Použít Validate Ověřit Test Results Výsledky testu Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Importované proměnné: %1 Importované funkce: %2 Importované jednotky: %3 Čísla řádků s chybami: %4 none žádné Apply Results Výsledky použití User definitions saved. Uživatelské definice byly uloženy. History Size Limit Limit velikosti historie Maximum number of history entries for this session (0 = unlimited): Maximální po�et položek historie pro tuto relaci (0 = neomezeno): Text file (*.txt);;Any file (*.*) Textové soubory (*.txt);;Všechny soubory (*.*) Could not recalculate from calculation %1: %2 Nepodařilo se přepo�ítat od výpo�tu %1: %2 History Size Limit Reached Dosažen limit velikosti historie This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Tento výpo�et zaplňuje poslední dostupné místo v historii. Budoucí výpo�ty odstraní z historie nejstarší výpo�et. Limit můžete zvýšit v Relace > Limit velikosti historie. Editing calculation. Press Esc twice to cancel. Upravuje se výpo�et. Zrušíte jej dvojitým stisknutím Esc. Calculation Settings Nastavení výpo�tu Invalid recalculation start index Neplatný po�áte�ní index přepo�tu System Default Výchozí nastavení systému Language Jazyk Select the language: Vyberte jazyk: Custom Vlastní Decimal places: Desetinná místa: &Automatic &Automaticky &Precision &Přesnost Plain &text Prostý &text Formula &Book &Sbírka vzorců &Export &Exportovat Export session as HTML Exportovat relaci jako HTML HTML file (*.html) Soubor HTML (*.html) Export session as plain text Exportovat relaci jako prostý text ManualWindow SpeedCrunch Manual Příru�ka k programu SpeedCrunch %1 - SpeedCrunch Manual %1 - Příru�ka k programu SpeedCrunch NumberFormatDialog Number Format Formát �ísla <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Vyberte �íselný formát výsledků a seskupování �íslic na vstupu.</b><br/><br/>Poznámka: u zadávaných �ísel jsou přijímány jednozna�né formáty, i když se liší od vybraného formátu zobrazení.<br/> QObject Global User Variable Globální uživatelská proměnná Global User Function Globální uživatelská funkce Global User Unit Globální uživatelská jednotka Backspace Backspace Clear expression Smazat výraz Evaluate expression Vyhodnotit výraz Insert text Vložit text Automatic decimal Automatický desetinný zápis Fixed-point decimal Desetinný zápis s pevnou řádovou �árkou Engineering decimal Technický desetinný zápis Scientific decimal Vědecký desetinný zápis Rational Racionální Binary Binární Octal Osmi�kový Hexadecimal Šestnáctkový Sexagesimal Šedesátkový Update Available Dostupná aktualizace A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Je dostupná novější verze (%1).<br/><a href="%2">Navštivte web a stáhněte si ji.</a> Check for Updates Zkontrolovat aktualizace SpeedCrunch %1 is up to date. SpeedCrunch %1 je aktuální. No connectivity. Please check your internet connection and try again. Žádné připojení. Zkontrolujte připojení k internetu a zkuste to znovu. Could not verify the latest available version. Nepodařilo se ověřit nejnovější dostupnou verzi. ResultDisplay Scroll to bottom Posunout dolů Edit Expression Upravit výraz Change Settings Změnit nastavení New Tab Nová karta &Import... &Importovat... &Export &Exportovat Plain &text Prostý &text Copy Kopírovat Selection Výběr Select All Vybrat vše Expression Výraz Result Výsledek Calculation Výpo�et Calculation as Single Line Výpo�et na jednom řádku Remove Odstranit This Calculation Tento výpo�et All Calculations Above Všechny výpo�ty nad tímto All Calculations Below Všechny výpo�ty pod tímto New Private Tab Nová soukromá karta Session Relace Open... Otevřít... Clone... Klonovat... Rename... Přejmenovat... Keep Ponechat Make Private... Změnit na soukromou... Clear Vymazat Delete Smazat Close Zavřít Split Rozdělit Left Vlevo Right Vpravo Up Nahoru Down Dolů Close Pane Zavřít panel Main Menu Hlavní nabídka Cancel editing Zrušit úpravu Copy result Kopírovat výsledek Edit expression Upravit výraz Change settings Změnit nastavení Remove calculation Odstranit výpo�et ResultSlotsDialog Notation & Precision Zápis a přesnost Result Line Řádek výsledku Enabled Povoleno Notation Zápis Decimal Places Desetinná místa Main Line Hlavní řádek Extra Line #1 Doplňkový řádek �. 1 Extra Line #2 Doplňkový řádek �. 2 Extra Line #3 Doplňkový řádek �. 3 Extra Line #4 Doplňkový řádek �. 4 Auto Automaticky UserFunctionListWidget Name Název Value Hodnota Description Popis Search Hledat No match found Nenalezena žádná shoda Insert Vložit Edit Upravit Delete Smazat Delete All Smazat vše UserUnitListWidget Name Název Value Hodnota Description Popis Search Hledat No match found Nenalezena žádná shoda Insert Vložit Edit Upravit Delete Smazat Delete All Smazat vše VariableListWidget Name Název Value Hodnota Description Popis Search Hledat No match found Nenalezena žádná shoda Insert Vložit Edit Upravit Delete Smazat Delete All Smazat vše heldercorreia-speedcrunch-e7ca37f/src/resources/locale/da.ts000066400000000000000000010454301526573132500243400ustar00rootroot00000000000000 AboutBox About SpeedCrunch Om SpeedCrunch Core developers Centrale udviklere Original author Oprindelig forfatter Close Luk Math engine Matematikmotor Main author | Logo | Maintainer Hovedforfatter | Logo | Vedligeholder Thanks Tak Copyright (C) 2004-2026 The SpeedCrunch developers Ophavsret (C) 2004-2026 SpeedCrunchs udviklere This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Dette program er gratis software, og du kan redistribuere det og/eller ændre det under betingelserne i GNU General Public License som er udgivet af Free Software Foundation, enten version 2 af licensen, eller (efter dit valg) enhver senere version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Dette program er distribueret i håb om at det vil være nyttigt, men UDEN NOGEN GARANTI, endda uden den underforståede garanti for SALGBARHED eller EGNETHED TIL ET BESTEMT FORMÅL. Se GNU General Public License for flere detaljer. BitFieldWidget Reset bits to zero Nulstil bit til nul Invert bits Invertér bit Shift bits left Skift bit til venstre Shift bits right Skift bit til højre Book Index Indeks Algebra Algebra Quadratic Equation Kvadratisk ligning Logarithmic Base Conversion Logaritmisk basekonvertering Geometry Geometri Circle Cirkel Sector Sektor Sphere Kugle Cube Kube Cone Kegle Cylinder Cylinder Electronics Elektronik Ohm's Law Ohms lov Power Effekt Reactance Reaktans Resonance Resonans Radio Frequency Radiofrekvens Antennas Antenner Characteristic Impedance (coax) Karakteristisk impedans (koaksial) Velocity of Propagation (coax) Udbredelseshastighed (koaksial) Standing Wave Ratio & Return Loss Standbølgeforhold & returtab Free Space Wavelength Bølgelængde i vakuum resistance resistans voltage Spænding current Strøm power Effekt inductive reactance Induktiv reaktans capacitive reactance Kapacitiv reaktans inductance Induktans capacitance kapacitans frequency frekvens resonance frequency resonansfrekvens area areal perimeter omkreds diameter diameter radius radius volume volumen surface area overfladeareal height højde slant height skrå højde face diagonal overfladediagonal space diagonal rumdiagonal edge length sidelængde arc length buelængde central angle (degrees) centervinkel (grader) input power indgangseffekt reflected power reflekteret effekt transmitted power transmitteret effekt return loss returtab dielectric constant dielektrisk konstant outer conductor's inner diameter ydre leders indre diameter inner conductor's outer diameter indre leders ydre diameter speed of light lysets hastighed reflection coefficient refleksionskoefficient standing wave ratio standbølgeforhold normalized impedance normaliseret impedans frequency (Hz) frekvens (Hz) BookDock Formula Book Formelsamling ConstantCompletion Search constants Søg efter konstanter No match found Ingen match fundet Constants Mathematics Matematik Physics (CODATA 2022) Fysik (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kemi (IUPAC - CIAAW 2021) Uncategorized Ukategoriseret Universal Universel Physicochemical Fysikokemisk Atomic & Nuclear — General Atomar og nuklear - generelt Atomic & Nuclear — Electroweak Atomar og nuklear - elektrosvag Atomic & Nuclear — Electron Atomar og nuklear - elektron Atomic & Nuclear — Muon Atomar og nuklear - myon Atomic & Nuclear — Tau Atomar og nuklear - tau Atomic & Nuclear — Proton Atomar og nuklear - proton Atomic & Nuclear — Neutron Atomar og nuklear - neutron Atomic & Nuclear — Deuteron Atomar og nuklear - deuteron Atomic & Nuclear — Triton Atomar og nuklear - triton Atomic & Nuclear — Helion Atomar og nuklear - helion Atomic & Nuclear — Alpha particle Atomar og nuklear - alfapartikel Atomic & Nuclear — Atomic units Atomar og nuklear - atomare enheder Atomic & Nuclear — Energy conversion relationships Atomar og nuklear - energikonverteringsrelationer Atomic & Nuclear — X-ray units Atomar og nuklear - røntgenenheder Atomic & Nuclear — Magnetic shielding corrections Atomar og nuklear - magnetiske afskærmningskorrektioner Masses Masser Lifetimes Levetider Molar Masses Molmasser Electronegativity Elektronegativitet Ionization Energy Ioniseringsenergi Nominal Constants (IAU 2015) Nominelle konstanter (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Aktuelle bedste estimater (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) impedans i vakuum (Z₀) reduced Planck constant (�) reduceret Planck konstant (�) vacuum electric permittivity (ϵ₀) vacuum elektrisk permittivity (ϵ₀) Newtonian constant of gravitation (G) Newtonian konstant of gravitation (G) vacuum magnetic permeability (μ₀) vacuum magnetisk permeability (μ₀) Planck constant (h) Planck konstant (h) speed of light in vacuum (c) Lysets hastighed i vakuum (c) standard acceleration of gravity (gₙ) Standard tyngdeacceleration (gₙ) Newtonian constant of gravitation over h-bar c Newtonian konstant of gravitation over h-bar c Planck length Planck længde Planck constant in eV/Hz (h) Planck konstant in eV/Hz (h) Planck mass Planck-masse Planck mass energy equivalent in GeV Planck masseenergiækvivalent in GeV Planck temperature Planck temperatur Planck time Planck tid reduced Planck constant in eV·s (�) reduceret Planck konstant in eV·s (�) reduced Planck constant times c in MeV·fm reduceret Planck konstant tids c in MeV·fm Bohr magneton Bohr-magneton conductance quantum (G₀) ledningsevne kvant (G₀) Coulomb constant (kₑ) Coulomb konstant (kₑ) elementary charge (e) elementary ladning (e) elementary charge over h-bar elementary ladning over h-bar conventional value of Josephson constant conventional value of Josephson konstant Josephson constant Josephson konstant conventional value of ampere-90 Konventionel værdi af ampere-90 conventional value of coulomb-90 Konventionel værdi af coulomb-90 conventional value of farad-90 Konventionel værdi af farad-90 conventional value of henry-90 Konventionel værdi af henry-90 conventional value of ohm-90 Konventionel værdi af ohm-90 conventional value of volt-90 Konventionel værdi af volt-90 conventional value of watt-90 Konventionel værdi af watt-90 magnetic flux quantum (Φ₀) magnetisk flux kvant (Φ₀) nuclear magneton kernemagneton inverse of conductance quantum inverse of ledningsevne kvant conventional value of von Klitzing constant conventional value of von Klitzing konstant von Klitzing constant von Klitzing konstant atomic unit of magnetic dipole moment atomic unit of magnetisk dipol moment atomic unit of magnetic flux density atomic unit of magnetisk flux densitet Bohr magneton in eV/T Bohr-magneton in eV/T Bohr magneton in Hz/T Bohr-magneton in Hz/T Bohr magneton in inverse meter per tesla Bohr-magneton in reciprok meter per tesla Bohr magneton in K/T Bohr-magneton in K/T nuclear magneton in eV/T kernemagneton in eV/T nuclear magneton in inverse meter per tesla kernemagneton in reciprok meter per tesla nuclear magneton in K/T kernemagneton in K/T nuclear magneton in MHz/T kernemagneton in MHz/T Bohr radius (a₀) Bore-radius (a₀) fine-structure constant (α) fine-structure konstant (α) Hartree energy (Eₕ) Hartree energi (Eₕ) Hartree energy in eV Hartree energi in eV quantum of circulation kvant of circulation quantum of circulation times 2 kvant of circulation tids 2 Rydberg constant (R∞) Rydberg konstant (R∞) atomic mass unit-hartree relationship atommasseenhed-hartree relation atomic mass unit-hertz relationship atommasseenhed-hertz relation atomic mass unit-inverse meter relationship atommasseenhed-reciprok meter relation atomic mass unit-joule relationship atommasseenhed-joule relation atomic mass unit-kelvin relationship atommasseenhed-kelvin relation atomic mass unit-kilogram relationship atommasseenhed-kilogram relation atomic unit of 1st hyperpolarizability atomic unit of 1st hyperpolariserbarhed atomic unit of 2nd hyperpolarizability atomic unit of 2nd hyperpolariserbarhed atomic unit of charge (e) atomic unit of ladning (e) atomic unit of charge density atomic unit of ladning densitet atomic unit of current atomic unit of strøm atomic unit of electric dipole moment atomic unit of elektrisk dipol moment atomic unit of electric field atomic unit of elektrisk felt atomic unit of electric field gradient atomic unit of elektrisk feltgradient atomic unit of electric polarizability atomic unit of elektrisk polariserbarhed atomic unit of electric potential atomic unit of elektrisk potentiale atomic unit of electric quadrupole moment atomic unit of elektrisk kvadrupol moment atomic unit of action atomic unit of virkning atomic unit of energy atomic unit of energi atomic unit of force atomic unit of kraft atomic unit of length atomic unit of længde hertz-atomic mass unit relationship hertz-atommasseenhed relation hertz-electron volt relationship hertz-elektronvolt relation hertz-hartree relationship hertz-hartree relation hertz-inverse meter relationship hertz-reciprok meter relation hertz-joule relationship hertz-joule relation hertz-kelvin relationship hertz-kelvin relation hertz-kilogram relationship hertz-kilogram relation hyperfine transition frequency of Cs-133 Meget præcis overgangsfrekvens for Cs-133 inverse fine-structure constant (α�¹) inverse fine-structure konstant (α�¹) inverse meter-atomic mass unit relationship reciprok meter-atommasseenhed relation inverse meter-electron volt relationship reciprok meter-elektronvolt relation inverse meter-hartree relationship reciprok meter-hartree relation inverse meter-hertz relationship reciprok meter-hertz relation inverse meter-joule relationship reciprok meter-joule relation inverse meter-kelvin relationship reciprok meter-kelvin relation inverse meter-kilogram relationship reciprok meter-kilogram relation joule-atomic mass unit relationship joule-atommasseenhed relation joule-electron volt relationship joule-elektronvolt relation joule-hertz relationship joule-hertz relation joule-hartree relationship joule-hartree relation joule-inverse meter relationship joule-reciprok meter relation joule-kelvin relationship joule-kelvin relation joule-kilogram relationship joule-kilogram relation kelvin-atomic mass unit relationship kelvin-atommasseenhed relation kelvin-electron volt relationship kelvin-elektronvolt relation kelvin-hertz relationship kelvin-hertz relation kelvin-hartree relationship kelvin-hartree relation kelvin-inverse meter relationship kelvin-reciprok meter relation kelvin-joule relationship kelvin-joule relation kelvin-kilogram relationship kelvin-kilogram relation kilogram-atomic mass unit relationship kilogram-atommasseenhed relation kilogram-electron volt relationship kilogram-elektronvolt relation kilogram-hertz relationship kilogram-hertz relation kilogram-hartree relationship kilogram-hartree relation kilogram-inverse meter relationship kilogram-reciprok meter relation kilogram-joule relationship kilogram-joule relation kilogram-kelvin relationship kilogram-kelvin relation lattice parameter of silicon (a) gitter parameter of silicon (a) luminous efficacy lysstyrke natural unit of energy natural unit of energi natural unit of energy in MeV natural unit of energi in MeV natural unit of action (�) natural unit of virkning (�) natural unit of action in eV·s natural unit of virkning in eV·s natural unit of length natural unit of længde natural unit of mass naturlig enhed for masse natural unit of momentum natural unit of impuls natural unit of momentum in MeV/c natural unit of impuls in MeV/c natural unit of time natural unit of tid natural unit of velocity natural unit of hastighed Rydberg constant times c in Hz Rydberg konstant tids c in Hz Rydberg constant times hc in eV Rydberg konstant tids hc in eV Rydberg constant times hc in J Rydberg konstant tids hc in J Fermi coupling constant Fermi coupling konstant weak mixing angle svag blandingsvinkel W to Z mass ratio W to Z masseforhold Thomson cross section (σₑ) Thomson-tværsnit (σₑ) electron mass (mₑ) elektron mass (mₑ) electron mass in u elektron mass in u electron mass energy equivalent (mₑ·c²) elektron masseenergiækvivalent (mₑ·c²) electron mass energy equivalent in MeV elektron masseenergiækvivalent in MeV reduced Compton wavelength reduceret Compton-bølgelængde classical electron radius (rₑ) classical elektron radius (rₑ) electron charge to mass quotient elektron ladning to mass quotient electron-deuteron magnetic moment ratio elektron-deuteron magnetisk moment-forhold electron-deuteron mass ratio elektron-deuteron masseforhold electron g factor (gₑ) elektron g factor (gₑ) electron gyromagnetic ratio (γₑ) elektron gyromagnetisk forhold (γₑ) electron gyromagnetic ratio in MHz/T elektron gyromagnetisk forhold in MHz/T electron-helion mass ratio elektron-helion masseforhold electron magnetic moment (μₑ) elektron magnetisk moment (μₑ) electron magnetic moment anomaly (aₑ) elektron magnetisk moment anomaly (aₑ) electron magnetic moment to Bohr magneton ratio elektron magnetisk moment to Bohr-magneton ratio electron magnetic moment to nuclear magneton ratio elektron magnetisk moment to kernemagneton ratio electron molar mass (Mₑ) elektron molmasse (Mₑ) electron-muon magnetic moment ratio elektron-myon magnetisk moment-forhold electron-muon mass ratio elektron-myon masseforhold electron-neutron magnetic moment ratio elektron-neutron magnetisk moment-forhold electron-neutron mass ratio elektron-neutron masseforhold electron-proton magnetic moment ratio elektron-proton magnetisk moment-forhold electron-proton mass ratio elektron-proton masseforhold electron relative atomic mass (Ar(e)) elektron relativ atommasse (Ar(e)) electron-tau mass ratio elektron-tau masseforhold electron to alpha particle mass ratio elektron to alfapartikel masseforhold electron to shielded helion magnetic moment ratio elektron to afskærmet helion magnetisk moment-forhold electron to shielded proton magnetic moment ratio elektron to afskærmet proton magnetisk moment-forhold electron-triton mass ratio elektron-triton masseforhold electron volt-atomic mass unit relationship elektronvolt-atommasseenhed relation electron volt-hartree relationship elektronvolt-hartree relation electron volt-hertz relationship elektronvolt-hertz relation electron volt-inverse meter relationship elektronvolt-reciprok meter relation electron volt-joule relationship elektronvolt-joule relation electron volt-kelvin relationship elektronvolt-kelvin relation electron volt-kilogram relationship elektronvolt-kilogram relation hartree-atomic mass unit relationship hartree-atommasseenhed relation hartree-electron volt relationship hartree-elektronvolt relation muon Compton wavelength myon Compton-bølgelængde muon-electron mass ratio myon-elektron masseforhold muon g factor myon g factor muon magnetic moment myon magnetisk moment muon magnetic moment anomaly myon magnetisk moment anomaly muon magnetic moment to Bohr magneton ratio myon magnetisk moment to Bohr-magneton ratio muon magnetic moment to nuclear magneton ratio myon magnetisk moment to kernemagneton ratio muon mass myon mass muon mass energy equivalent myon masseenergiækvivalent muon mass energy equivalent in MeV myon masseenergiækvivalent in MeV muon mass in u myon mass in u muon molar mass myon molmasse muon-neutron mass ratio myon-neutron masseforhold muon-proton magnetic moment ratio myon-proton magnetisk moment-forhold muon-proton mass ratio myon-proton masseforhold muon-tau mass ratio myon-tau masseforhold reduced muon Compton wavelength reduceret myon Compton-bølgelængde reduced tau Compton wavelength reduceret tau Compton-bølgelængde tau Compton wavelength tau Compton-bølgelængde tau-electron mass ratio tau-elektron masseforhold tau mass tau-masse tau mass energy equivalent tau masseenergiækvivalent tau mass in u tau-masse i u tau molar mass tau molmasse tau-muon mass ratio tau-myon masseforhold tau-neutron mass ratio tau-neutron masseforhold tau-proton mass ratio tau-proton masseforhold proton charge to mass quotient proton ladning to mass quotient proton Compton wavelength proton Compton-bølgelængde proton-electron mass ratio proton-elektron masseforhold proton g factor (gₚ) protonens g-faktor (gₚ) proton gyromagnetic ratio (γₚ) proton gyromagnetisk forhold (γₚ) proton gyromagnetic ratio in MHz/T proton gyromagnetisk forhold in MHz/T proton magnetic moment (μₚ) proton magnetisk moment (μₚ) proton magnetic moment to Bohr magneton ratio proton magnetisk moment to Bohr-magneton ratio proton magnetic moment to nuclear magneton ratio proton magnetisk moment to kernemagneton ratio proton magnetic shielding correction proton magnetisk afskærmning korrektion proton mass (mₚ) protonets masse (mₚ) proton mass energy equivalent proton masseenergiækvivalent proton mass energy equivalent in MeV proton masseenergiækvivalent in MeV proton mass in u protonets masse i enheden "u" proton molar mass (Mₚ) proton molmasse (Mₚ) proton-muon mass ratio proton-myon masseforhold proton-neutron magnetic moment ratio proton-neutron magnetisk moment-forhold proton-neutron mass ratio proton-neutron masseforhold proton relative atomic mass (Ar(p)) proton relativ atommasse (Ar(p)) proton rms charge radius proton rms ladningsradius proton-tau mass ratio proton-tau masseforhold reduced proton Compton wavelength reduceret proton Compton-bølgelængde shielded proton gyromagnetic ratio afskærmet proton gyromagnetisk forhold shielded proton gyromagnetic ratio in MHz/T afskærmet proton gyromagnetisk forhold in MHz/T shielded proton magnetic moment afskærmet proton magnetisk moment shielded proton magnetic moment to Bohr magneton ratio afskærmet proton magnetisk moment to Bohr-magneton ratio shielded proton magnetic moment to nuclear magneton ratio afskærmet proton magnetisk moment to kernemagneton ratio neutron Compton wavelength neutron Compton-bølgelængde neutron-electron magnetic moment ratio neutron-elektron magnetisk moment-forhold neutron-electron mass ratio neutron-elektron masseforhold neutron g factor (gₙ) neutron-faktor (gₙ) neutron gyromagnetic ratio (γₙ) neutron gyromagnetisk forhold (γₙ) neutron gyromagnetic ratio in MHz/T neutron gyromagnetisk forhold in MHz/T neutron magnetic moment (μₙ) neutron magnetisk moment (μₙ) neutron magnetic moment to Bohr magneton ratio neutron magnetisk moment to Bohr-magneton ratio neutron magnetic moment to nuclear magneton ratio neutron magnetisk moment to kernemagneton ratio neutron mass (mₙ) neutronets masse (mₙ) neutron mass energy equivalent neutron masseenergiækvivalent neutron mass energy equivalent in MeV neutron masseenergiækvivalent in MeV neutron mass in u neutronets masse i enheden "u" neutron molar mass (Mₙ) neutron molmasse (Mₙ) neutron-muon mass ratio neutron-myon masseforhold neutron-proton magnetic moment ratio neutron-proton magnetisk moment-forhold neutron-proton mass difference Forskellen i masse mellem neutroner og protoner neutron-proton mass difference energy equivalent neutron-proton mass difference energiækvivalent neutron-proton mass difference energy equivalent in MeV neutron-proton mass difference energiækvivalent in MeV neutron-proton mass difference in u Forskellen i masse mellem neutron og proton, målt i enheden "u" neutron-proton mass ratio neutron-proton masseforhold neutron relative atomic mass (Ar(n)) neutron relativ atommasse (Ar(n)) neutron-tau mass ratio neutron-tau masseforhold neutron to shielded proton magnetic moment ratio neutron to afskærmet proton magnetisk moment-forhold reduced neutron Compton wavelength reduceret neutron Compton-bølgelængde deuteron-electron magnetic moment ratio deuteron-elektron magnetisk moment-forhold deuteron-electron mass ratio deuteron-elektron masseforhold deuteron g factor Deuteronens g-faktor deuteron magnetic moment deuteron magnetisk moment deuteron magnetic moment to Bohr magneton ratio deuteron magnetisk moment to Bohr-magneton ratio deuteron magnetic moment to nuclear magneton ratio deuteron magnetisk moment to kernemagneton ratio deuteron mass Deuterons masse deuteron mass energy equivalent deuteron masseenergiækvivalent deuteron mass energy equivalent in MeV deuteron masseenergiækvivalent in MeV deuteron mass in u Deuterons masse i u deuteron molar mass deuteron molmasse deuteron-neutron magnetic moment ratio deuteron-neutron magnetisk moment-forhold deuteron-proton magnetic moment ratio deuteron-proton magnetisk moment-forhold deuteron-proton mass ratio deuteron-proton masseforhold deuteron relative atomic mass (Ar(d)) deuteron relativ atommasse (Ar(d)) deuteron rms charge radius deuteron rms ladningsradius triton-electron mass ratio triton-elektron masseforhold triton g factor (gₜ) Triton G-faktor (Gₜ) triton magnetic moment (μₜ) triton magnetisk moment (μₜ) triton magnetic moment to Bohr magneton ratio triton magnetisk moment to Bohr-magneton ratio triton magnetic moment to nuclear magneton ratio triton magnetisk moment to kernemagneton ratio triton mass (mₜ) Tritons masse (mₜ) triton mass energy equivalent triton masseenergiækvivalent triton mass energy equivalent in MeV triton masseenergiækvivalent in MeV triton mass in u Tritons masse i universet triton molar mass (Mₜ) triton molmasse (Mₜ) triton-proton mass ratio triton-proton masseforhold triton relative atomic mass (Ar(t)) triton relativ atommasse (Ar(t)) triton to proton magnetic moment ratio triton to proton magnetisk moment-forhold helion-electron mass ratio helion-elektron masseforhold helion g factor (gₕ) Helion-g-faktor (gₕ) helion magnetic moment (μₕ) helion magnetisk moment (μₕ) helion magnetic moment to Bohr magneton ratio helion magnetisk moment to Bohr-magneton ratio helion magnetic moment to nuclear magneton ratio helion magnetisk moment to kernemagneton ratio helion mass (mₕ) Helionens masse (mₕ) helion mass energy equivalent helion masseenergiækvivalent helion mass energy equivalent in MeV helion masseenergiækvivalent in MeV helion mass in u Helionens masse i enheden u helion molar mass (Mₕ) helion molmasse (Mₕ) helion-proton mass ratio helion-proton masseforhold helion relative atomic mass (Ar(h)) helion relativ atommasse (Ar(h)) helion shielding shift helion afskærmning shift shielded helion gyromagnetic ratio afskærmet helion gyromagnetisk forhold shielded helion gyromagnetic ratio in MHz/T afskærmet helion gyromagnetisk forhold in MHz/T shielded helion magnetic moment afskærmet helion magnetisk moment shielded helion magnetic moment to Bohr magneton ratio afskærmet helion magnetisk moment to Bohr-magneton ratio shielded helion magnetic moment to nuclear magneton ratio afskærmet helion magnetisk moment to kernemagneton ratio shielded helion to proton magnetic moment ratio afskærmet helion to proton magnetisk moment-forhold shielded helion to shielded proton magnetic moment ratio afskærmet helion to afskærmet proton magnetisk moment-forhold alpha particle mass alfapartikel mass alpha particle mass in u alfapartikel mass in u alpha particle mass energy equivalent alfapartikel masseenergiækvivalent alpha particle mass energy equivalent in MeV alfapartikel masseenergiækvivalent in MeV alpha particle-electron mass ratio alfapartikel-elektron masseforhold alpha particle-proton mass ratio alfapartikel-proton masseforhold alpha particle rms charge radius alfapartikel rms ladningsradius alpha particle molar mass alfapartikel molmasse alpha particle relative atomic mass (Ar(α)) alfapartikel relativ atommasse (Ar(α)) atomic mass constant (mᵤ) atomic mass konstant (mᵤ) Avogadro constant Avogadro konstant Boltzmann constant (k) Boltzmann konstant (k) Boltzmann constant in eV/K Boltzmann konstant in eV/K Boltzmann constant in Hz/K Boltzmann konstant in Hz/K Boltzmann constant in inverse meter per kelvin Boltzmann konstant in reciprok meter per kelvin electron volt (eV) elektronvolt (eV) Faraday constant (F) Faraday konstant (F) first radiation constant (c�) first radiation konstant (c�) first radiation constant for spectral radiance first radiation konstant for spectral radiance molar gas constant (R) molar gas konstant (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidt konstant (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Loschmidt konstant (n₀, 273.15 K, 101.325 kPa) molar Planck constant molar Planck konstant second radiation constant (c₂) second radiation konstant (c₂) Stefan-Boltzmann constant (σ) Stefan-Boltzmann konstant (σ) lattice spacing of ideal Si (d₂₂₀) gitter spacing of ideal Si (d₂₂₀) atomic mass constant energy equivalent atomic mass konstant energiækvivalent atomic mass constant energy equivalent in MeV atomic mass konstant energiækvivalent in MeV atomic mass unit-electron volt relationship atommasseenhed-elektronvolt relation molar mass constant (Mᵤ) molmasse konstant (Mᵤ) molar mass of carbon-12 molmasse of carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) Molar volumen af en ideel gas (273,15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) Molar volumen af en ideal gas (273,15 K, 101,325 kPa) molar volume of silicon molar volumen af silicium Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode konstant (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode konstant (1 K, 101.325 kPa) Wien frequency displacement law constant Wien frequency displacement law konstant Wien wavelength displacement law constant Wien wavelængde displacement law konstant standard atmosphere (atm) standard atmosfære (atm) standard-state pressure (p°) Normaltryk (p°) Angstrom star (Å*) Angstrom-stjerne (Å*) Copper x unit Kobber x enhed Molybdenum x unit Molybdæn – en enhed atomic unit of magnetizability den mindste enhed af magnetisk egenskab atomic unit of mass (mₑ) den mindste enhed af masse (mₑ) atomic unit of momentum atomic unit of impuls atomic unit of permittivity den mindste enhed af dielektrisk konstant atomic unit of time atomic unit of tid atomic unit of velocity atomic unit of hastighed hartree-hertz relationship hartree-hertz relation hartree-inverse meter relationship hartree-reciprok meter relation hartree-joule relationship hartree-joule relation hartree-kelvin relationship hartree-kelvin relation hartree-kilogram relationship hartree-kilogram relation shielding difference of d and p in HD afskærmning difference of d and p in HD shielding difference of t and p in HT afskærmning difference of t and p in HT pi (π) pi (π) Euler's number (e) Euler-tallet (e) golden ratio (φ) gylden snit (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni konstant (γ) nominal solar radius nominel sol radius nominal solar total irradiance nominel sol total irradiance nominal solar luminosity nominel sol luminosity nominal solar effective temperature nominel sol effective temperatur nominal solar mass parameter nominel sol masseparameter nominal terrestrial equatorial radius nominel jordisk ækvatorialradius nominal terrestrial polar radius nominel jordisk polradius nominal terrestrial mass parameter nominel jordisk masseparameter nominal jovian equatorial radius nominel joviansk ækvatorialradius nominal jovian polar radius nominel joviansk polradius nominal jovian mass parameter nominel joviansk masseparameter average value of one minus the rate of TCG relative to TCB Gennemsnitsværdien af én minus forholdet mellem TCG og TCB solar mass parameter (TCB-compatible) sol masseparameter (TCB-compatible) solar mass parameter (TDB-compatible) sol masseparameter (TDB-compatible) equatorial radius of the Earth (TT-compatible) ækvatorialradius of the Jorden (TT-compatible) dynamical form factor of the Earth dynamical form factor of the Jorden time rate of change in the dynamical form factor of the Earth tid rate of change in the dynamical form factor of the Jorden geocentric gravitational constant (TCB-compatible) geocentric gravitational konstant (TCB-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational konstant (TT-compatible) geocentric gravitational constant (TDB-compatible) geocentric gravitational konstant (TDB-compatible) potential of the geoid potentiale of the geoid nominal mean angular velocity of the Earth (TT-compatible) nominel mean angular hastighed of the Jorden (TT-compatible) ratio mass of the Moon to the Earth masseforholdet mellem the Månen to the Jorden ratio of the mass of the Sun to Mercury masseforholdet mellem the Solen to Merkur ratio of the mass of the Sun to Venus masseforholdet mellem the Solen to Venus ratio of the mass of the Sun to Mars masseforholdet mellem the Solen to Mars ratio of the mass of the Sun to Jupiter masseforholdet mellem the Solen to Jupiter ratio of the mass of the Sun to Saturn masseforholdet mellem the Solen to Saturn ratio of the mass of the Sun to Uranus masseforholdet mellem the Solen to Uranus ratio of the mass of the Sun to Neptune masseforholdet mellem the Solen to Neptun ratio of the mass of the Sun to (134340) Pluto masseforholdet mellem the Solen to (134340) Pluto ratio of the mass of the Sun to (136199) Eris masseforholdet mellem the Solen to (136199) Eris ratio of the mass of (1) Ceres to the Sun masseforholdet mellem (1) Ceres to the Solen ratio of the mass of (2) Pallas to the Sun masseforholdet mellem (2) Pallas to the Solen ratio of the mass of (4) Vesta to the Sun masseforholdet mellem (4) Vesta to the Solen mean obliquity of the ecliptic at J2000.0 middelobliquitet of the ekliptika at J2000.0 Electromagnetic Elektromagnetisk Compton wavelength Comptonbølgelængde Astronomy Astronomi ConstantsWidget Domain Domæne Subdomain Underdomæne No match found Ingen match fundet Name Navn Value Værdi Unit Enhed Search Søgning All Alle CustomKeypadDialog Custom Keypad Tilpasset tastatur Rows: Rækker: Columns: Kolonner: Copy preset: Kopiér forvalg: Basic Grundlæggende Scientific (wide) Videnskabelig (bred) Scientific (narrow) Videnskabelig (smal) Apply Anvend Row Række Column Kolonne Label Etiket Behavior Opførsel Text Tekst DiagnosticsDialog App Diagnostics Programdiagnostik Copy to Clipboard Kopiér til udklipsholder Editor Unit Enhed User unit Brugerenhed User function Bruger-funktion Argument Argument Current result:<br/>%1 Aktuelt resultat:<br/>%1 Selection result:<br/>%1 Markeringsresultat:<br/>%1 Selection result: n/a Markering fører til: n/a Selection result: %1 Resultat af udvælgelsen: %1 second sekund metre meter kilogram kilogram mole mol radian radian steradian steradian degree Celsius grad Celsius cubic metre kubikmeter cubic millimetre kubikmillimeter cubic centimetre kubikcentimeter cubic decimetre kubikdecimeter cubic kilometre kubikkilometer square millimetre kvadratmillimeter square kilometre kvadratkilometer square metre kvadratmeter minute minut hour time day dag astronomical unit astronomisk enhed degree grad arcminute bueminut arcsecond buesekund milliarcsecond millibuesekund microarcsecond mikrobuesekund hectare hektar litre liter tonne ton Dalton dalton electronvolt elektronvolt Angstrom ångström atmosphere atmosfære atomic mass unit atommasseenhed British thermal unit Britiske termal enhed calorie kalorie carat karat cup kop cup (Imperial) kop (Imperial) cup (Japanese) kop (japansk) cup (US) kop (amerikansk) degree Fahrenheit grad Fahrenheit fathom forstå fluid ounce (Imperial) unse (britisk måleenhed) fluid ounce (US) unse (amerikansk måleenhed) fluid dram (Imperial) flydende måleske (imperial) fluid dram (US) en dram væske (amerikansk måleenhed) foot fod square foot kvadratfod cubic foot kubikfod gallon (Imperial) gallon (britisk måleenhed) gallon (US) gallon (amerikansk måleenhed) gill (Imperial) hale (Imperial) gill (US) hale (amerikansk) gradian gradient grain korn gram gram Hartley Hartley Hartree energy unit Hartree energi unit horsepower hestekræfter inch tomme square inch kvadratisk tomme cubic inch kubiktomme karat karate knot knude lightminute en minut lightsecond lyssekund lightyear lysår long ton ton mile mil square mile kvadratmile cubic mile kubikmil mile per hour kilometer pr. time kilometre per hour kilometer i timmen nautical mile nautisk mil ounce ounce (enhed for vægt) parsec parsec pint (Imperial) en pint (britisk måleenhed) pint (US) en pint (amerikansk måleenhed) pound pund pounds per square inch pund pr. kvadrattomme quart (Imperial) kvart (britisk måleenhed) quart (US) kvart (amerikansk måleenhed) oil barrel oliebørret beer barrel (US) ølstykk (amerikansk) square yard kvadratmeter cubic yard kubikmeter short ton ton tablespoon spiseskefuld tablespoon (Australian) spiseskefuld (australisk) tablespoon (Imperial) spiseskefuld (britisk måleenhed) tablespoon (US) spiseskefuld (amerikansk måleenhed) dessert spoon dessertebesk teaspoon teskefuld teaspoon (Imperial) teskefuld (britisk måleenhed) teaspoon (US) teske (amerikansk måleenhed) turn drej revolution revolution revolution per minute revolution pr. minut week uge kilowatt hour kilowatt-time millimetre of mercury millimeter af kviksølv yard have Julian century Julian-æraen Julian year Julian år sidereal year sidereal år tropical year tropisk år Evaluator invalid expression ugyldigt udtryk division by zero division med nul too time consuming - computation was rejected for tidskrævende - beregningen blev forkastet dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensionsuoverensstemmelse - værdier med forskellige dimensioner kan ikke sammenlignes, adderes, osv. invalid dimension - operation might require dimensionless arguments ugyldig dimension - operationen kræver muligvis dimensionsløse argumenter Computation aborted - encountered numerical instability Computerberegning afbrudt - er stødt på numerisk ustabilitet invalid dimension - function might require dimensionless arguments dimensionsuoverensstemmelse - funktionen kræver muligvis dimensionsløse argumenter error fejl unit must not be zero enheden skal være forskellig fra nul Conversion failed - dimension mismatch Konvertering mislykkedes - dimensionsuoverensstemmelse unknown function or variable ukendt funktion eller variabel recursion not supported rekursion understøttes ikke cannot operate on a NaN kan ikke operere med et NaN underflow - tiny result is out of SpeedCrunch's number range Underskud – det resulterende tal er uden for SpeedCrunches numeriske område overflow - huge result is out of SpeedCrunch's number range Overløb – et meget stort resultat ligger uden for SpeedCrunches numeriske område. overflow - logic result exceeds maximum of 256 bits Overløb – logisk resultat overstiger den maksimale størrelse på 256 bit overflow - integer result exceeds maximum limit for integers overskridelse – resultatet af en heltal-beregning overstiger det maksimale tilladte for heltal operation is not defined for these arguments operationen er ikke defineret for disse argumenter wrong number of arguments forkert antal argumenter does not take NaN as an argument tager ikke NaN som et argument result out of range resultat uden for området undefined for argument domain Ukendt for argumentdomænet computation too expensive beregningen er for dyr internal error, please report a bug Intern fejl, venligst rapporter en fejl. syntax error syntaksfejl conversion target must be a unit konverteringsmålet skal være en enhed unknown unit ukendt enhed %1 is a reserved name, please choose another %1 er et reserveret navn, venligst vælg et andet. %1 is a global user definition and cannot be overridden in this session. %1 er en global brugerdefinition og kan ikke tilsidesættes i denne session. %1 is a variable name, please choose another or delete the variable %1 er et variabelnavn, venligst vælg et andet navn eller slet variabelen. argument %1 is used more than once Argument %1 bruges flere gange. %1 is a built-in unit name, please choose another %1 er et indbygget enhedsnavn, vælg et andet %1 is a user function name, please choose another or delete the function %1 er et navn for en brugerdefineret funktion. Vælg venligst et andet navn eller slet funktionen. FunctionRepo max; trials; probability maksimum; forsøg; sandsynlighed trials; probability prøver; sandsynlighed hits; trials; probability succeser; udfordringer; sandsynlighed max; total; hits; trials maksimum; samlet; antal; forsøg total; hits; trials samlet; slag; forsøg count; total; hits; trials antal; samlet; slag; forsøg dividend; divisor udbytte; divisor x; exponent_bits; significand_bits [; exponent_bias] x; eksponentbit; betydningsbit [; eksponentbias] base; x grund; x value; modulo værdi; modulo base; exponent; modulo grund; eksponent; modulus events; average_events begivenheder; gennemsnitlige_begivenheder average_events gennemsnitlige begivenheder x [; precision] x [; præcision] Absolute Value Absolut værdi Absolute Deviation Absolut afvigelse Arc Cosine Arc cosinus Logical AND Logisk OG Area Hyperbolic Cosine Område: Hyperbolsk cosinus Area Hyperbolic Sine Område for hyperbolsinus Area Hyperbolic Tangent Område: Hyperbolsk tangens Arc Sine Arcus sinus Arc Tangent Arc-tangent Arc Tangent with two Arguments Arc-funktion med to argument Average (Arithmetic Mean) Gennemsnit (gennemsnitlig værdi) Binomial Cumulative Distribution Function Binomials kumulative fordelingsfunktion Binomial Distribution Mean Gennemsnittet af binomialfordelingen Binomial Probability Mass Function Binomial sandsynlighedstæthedsfunktion Binomial Distribution Variance Varians for binomialfordeling Cube Root Kvadratroden Complex Conjugate Kompleks konjugat Cosine Kosinus Hyperbolic Cosine Hyperbolsk cosinus Cotangent Cotangens Cosecant Cosekant Convert Unix timestamp to Date Konverter Unix-tidsstempel til dato Degrees of Arc Gradier af en cirkel Error Function Fejlfunktion Complementary Error Function Komplementær fejlfunktion Exponential Eksponentiel Fractional Part Resten Extension of Factorials [= (x-1)!] Udvidelse af fakulteter [= (x-1)!] Greatest Common Divisor Største fælles divisor Geometric Mean Geometrisk gennemsnit Gradians of arc Grad i vinkel Hypergeometric Cumulative Distribution Function Hypergeometrisk kumulativ fordelingsfunktion Hypergeometric Distribution Mean Gennemsnittet af den hypergeometriske fordeling Hypergeometric Probability Mass Function Hypergeometrisk sandsynlighedstæthedsfunktion Hypergeometric Distribution Variance Hypergeometrisk fordeling – varians Integer Quotient Heltalskvotient Integer Part Hele del Imaginary Part Imaginærdel Decode IEEE-754 Binary Value Dekodér IEEE-754 binær værdi Encode IEEE-754 Binary Value Kodet IEEE-754 binær værdi Decode 16-bit Half-Precision Value Dekodér værdien 16-bit med halv præcision Encode 16-bit Half-Precision Value Kodet 16-bit halv-præcisionsværdi Decode 32-bit Single-Precision Value Dekodér værdien 32-bit med enkelt præcision Encode 32-bit Single-Precision Value Kodet 32-bit med enkeltpræcision Decode 64-bit Double-Precision Value Dekodér værdien 64-bit med dobbelt præcision Encode 64-bit Double-Precision Value Koder 64-bit-værdien med dobbelt præcision Decode 128-bit Quad-Precision Value Dekodér 128-bit Quad – Præcis værdi Encode 128-bit Quad-Precision Value Koder 128-bit Quad – Præcisionsværdi Binary Logarithm Binær logaritme Common Logarithm Almindelig logaritme Natural Logarithm Naturlig logaritme Logarithm to Arbitrary Base Logaritme til et vilkårligt grundtal Mask to a bit size Maske med størrelse bit Maximum Maksimum Median Value (50th Percentile) Medianværdi (50. percentil) Minimum Minimum Modulo Modul Euclidean Modulo Euklidisk modulo Modular Exponentiation Modulær eksponentiering Combination (Binomial Coefficient) Kombination (Binomialkoefficient) Logical NOT Logisk IKKE Permutation (Arrangement) Permutation (Anordning) Convert to Binary Representation Konverter til binær repræsentation Arithmetic Aritmetik Chemistry Kemi Complex Kompleks Combinatorics Kombinatorik Probability Sandsynlighed Statistics Statistik Aggregation Aggregering Random Tilfældig Base conversion Basekonvertering Number formatting Talformatering Integer arithmetic Heltalsaritmetik Special functions Specialfunktioner Exponential & Logarithmic Eksponentiel og logaritmisk Angle conversion Vinkelkonvertering Trigonometry Trigonometri Bitwise Bitvis Floating point Flydende komma Date & Time Dato og tid Linear algebra Lineær algebra unix_timestamp; x hours offset to GMT unix-tidspunkt; x timers forskydning fra GMT yyyymmdd.hhmmss; x hours offset to GMT dd.mm.år kl.hh:mm:ss; x timerforsinkelse fra GMT [digits] [cifre] max [; min] maksimalt [; minimum] List Literal Listeliteral Convert to Padded Binary Representation Konvertér til udfyldt binær repræsentation Round Toward +∞ (Ceiling) Afrund mod +∞ (loft) Cosine plus Imaginary Sine Kosinus plus imaginær sinus Convert to Cis Complex Form Konvertér til Cis kompleks form Matrix Column Count Antal kolonner i matricen Population Correlation Matrix (n) Population korrelation Matrix (n) Sample Correlation Matrix (n-1) Stikprøve korrelation Matrix (n-1) Count Antal Population Covariance Matrix (n) Population kovarians Matrix (n) Sample Covariance Matrix (n-1) Stikprøve kovarians Matrix (n-1) Cross Product krydsprodukt Convert Date to Unix timestamp Convert dato to Unix tidstamp Convert to Decimal Representation Konverter til decimalrepræsentation Determinant determinant Convert to Sexagesimal Notation Konvertér til Sexagesimal notation Dot Product skalarprodukt Convert to Engineering Notation Konvertér til ingeniør notation Convert to Exponential Complex Form Konvertér til eksponentiel kompleks form Round Toward −∞ (Floor) Afrund mod −∞ (gulv) Flatten Matrix udflad Matrix Least Common Multiple Den mindste fælles multiplum Convert to Hexadecimal Representation Konverter til hexadecimal repræsentation Convert to Padded Hexadecimal Representation Konvertér til udfyldt hexadecimal repræsentation Inverse Matrix Invers matrix Round to 16-bit Half-Precision Value Afrund til 16-bit halv præcision Value Round to 32-bit Single-Precision Value Afrund til 32-bit enkelt præcision Value Round to 64-bit Double-Precision Value Afrund til 64-bit dobbelt præcision Value Round to 128-bit Quad-Precision Value Afrund til 128-bit quad-præcision Value Residual from 16-bit Half-Precision Rounding Rest fra 16-bit halv præcision Rounding Residual from 32-bit Single-Precision Rounding Rest fra 32-bit enkelt præcision Rounding Residual from 64-bit Double-Precision Rounding Rest fra 64-bit dobbelt præcision Rounding Residual from 128-bit Quad-Precision Rounding Rest fra 128-bit quad-præcision Rounding Substance Mass Stofmasse Molarity Molaritet Molar Mass Molmasse Median Absolute Deviation Median absolut afvigelse Mean Middelværdi Numerical Value of Quantity Numerisk værdi af mængden Random Decimal Number tilfældigt Decimal tal Random Integer Number tilfældigt heltal tal Convert to Rational Representation Konvertér til rationel repræsentation Convert to Octal Representation Konverter til oktalt system Convert to Padded Octal Representation Konvertér til udfyldt oktal repræsentation Vector or Matrix Norm Vector or Matrix norm Logical OR Logisk OR Population Count (Hamming Weight) Antallet af etsende bit (Hamming-vægt) Phase of Complex Number Fase af et komplekst tal Poissonian Cumulative Distribution Function Poisson-fordelings kumulative sandsynlighedsfunktion Poissonian Distribution Mean Gennemsnitsværdi for Poisson-fordelingen Poissonian Probability Mass Function Poisson-fordelingens sandsynlighedstæthedsfunktion Poissonian Distribution Variance Poisson-fordelingens varians Convert to Phasor Complex Form Konvertér til fasor kompleks form Convert to Rectangular Complex Form Konvertér til rektangulær kompleks form Round Half Away from Zero Afrundet til nærmeste halvtal, minus nul. Round Half Even Rundt, halvt, lige Nth Root N-te rod Convert to Scientific Notation Konvertér til videnskabelig notation Matrix Row Count Antal rækker i matricen List or Matrix Shape List or Matrix form Summation Summering Population Standard Deviation (n) Population standardafvigelse (n) Sample Standard Deviation (n-1) Stikprøve standardafvigelse (n-1) Round Toward Zero (Truncation) Afrund mod Zero (trunkering) Matrix Trace Matrix spor Transpose Matrix transponér Matrix Population Variance (n) Population varians (n) Sample Variance (n-1) Stikprøve varians (n-1) Product Produkt Radians radianer Matrix Rank Matrix rang Real Part Reel del Secant Sekant Arithmetic Shift Left Venstre aritmetisk forskydning Arithmetic Shift Right Højre aritmetisk forskydning Signum Signum Sine Hendes Hyperbolic Sine Hyperbolsk sinus Square Root Kvadratroden Sum Summen Tangent Afledt Convert to Trigonometric Complex Form Konvertér til trigonometrisk kompleks form Turns Vendinger Hyperbolic Tangent Hyperbolsk tangens Sign-extend a value Udvid en værdi Logical XOR Logisk XOR FunctionsWidget Domain Domæne All Alle Name Navn Search Søg No match found Ingen match fundet Identifier Identifikator HistoryWidget Remove All Calculations Above Fjern alle beregninger ovenfor Remove This Calculation Fjern denne beregning Remove All Calculations Below Fjern alle beregninger nedenfor Keypad Inverse cosine Invers kosmisk funktion The last result Det seneste resultat Inverse sine Invers sinus Inverse tangent Invers tangent Evaluate expression Beregn udtryk Division Afdeling Multiplication Multiplikation Subtraction Subtraktion Addition Tilføjelse Clear expression Klar og tydelig formulering Cosine Kosinus Backspace Tilbage Scientific notation Videnskabelig notation Exponential Eksponentiel Factorial Fakultet Natural logarithm Naturlig logaritme Left parenthesis Venstre parentes Nth root N-te rod Argument separator Argumentseparator Square Kvadrat Common logarithm Briggsk logaritme Modulo Modul Contextual percentage Kontekstuel procent Power Potens Right parenthesis Højre parentes Sine Hendes Square root Kvadratroden Tangent Afledt Pi Pi Decimal separator Decimalseparator MainWindow Radian Radian Degree Grad (uddannelse) Gradian Gradian Binary Binær Octal Okta Hexadecimal Heksadecimal Sexagesimal Sekszimalt system Engineering decimal Ingeniørmæssig decimal Scientific decimal Videnskabelig decimal &Import... &Importer... &Quit &Afslut Clear E&xpression Klar og tydelig udtryk Clear &History Klar og tydelig historie &Copy &Kopier &Paste &Sæt ind &Select Expression &Vælg Udtryk &Constants &Konstanter &Functions &Funktioner &History &Historie &Status Bar &Statuslinje Bitfield Bitfelt Use&r Functions Brugerdefinerede Funktioner &Degree &Grader &Radian &Radianer &Gradian &Gradian Re&volution O&mdrejning Auto-Insert a&ns I&ndsæt ans automatisk Automatic &Completion Automatisk og udfyldning &Built-in Functions Ind&byggede funktioner Built-in &Variables Indbyggede &variabler User &Functions Bruger&funktioner User Va&riables B&rugervariabler Open a Private Tab on Startup Åbn en privat fane ved opstart Open and focus a new private tab whenever SpeedCrunch starts. Åbn og aktivér en ny privat fane, hver gang SpeedCrunch starter. Syntax &Highlighting Syntaks og fremhævning Group Digits in &Input Gruppér c&ifre i indtastningen Automatic Input &Adjustments &Automatiske inputjusteringer Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Tilpas automatisk operatorer, mellemrum, parenteser og potenser, og begræns input til gyldige tegn. Group input digits using the selected number format. Gruppér indtastede cifre efter det valgte talformat. &Blinking Cursor &Blinkende markør Blink the cursor in the expression editor. Lad markøren blinke i udtrykseditoren. &Escape Clears Editor &Escape rydder editoren Clear the focused expression editor with Escape after dismissing any popup or preview. Ryd den aktive udtrykseditor med Escape, når eventuelle pop op-vinduer eller forhåndsvisninger er lukket. Keep Expression After Evaluation Behold udtryk efter beregning Copy New Results Automatically Kopiér nye resultater automatisk &Comma &Komma &System Default &System Standard &Dot &Punktum Dot &And Comma Punktum &Og Komma Toward +∞ (&ceil) Mod +∞ (&ceil) Toward −∞ (&floor) Mod −∞ (&floor) &Binary &Binær &Engineering %Engineering &Hexadecimal &Hexadecimal &Octal &Oktal &Scientific &Videnskabelig User &Manual Brugervejledning Issues and &Feedback Problemer og &feedback &Donate &Doner &About SpeedCrunch O&m SpeedCrunch App Diag&nostics Programdiag&nostik S&plit O&pdel Angle &Mode V&inkeltilstand &Complex Form &Kompleks form New Tab Ny fane Constants Konstanter Functions Funktioner History Historie User Functions Brugerfunktioner &Font... &Skrifttype... &Language... &Sprog... &Session &Session &Edit &Redigere &View &Vis Se&ttings Indstillinger &Decimal &Decimal &Keypad &Numerisk Tastatur Always on &Top Altid &Øverst Disabled Deaktiveret Small Space Lille Mellemrum Medium Space Medium Mellemrum Large Space Stort Mellemrum &0 Digits &0 Cifre &15 Digits &15 Cifre &2 Digits &2 Cifre &3 Digits &3 Cifre &50 Digits &50 Cifre &8 Digits &8 Cifre &Sexagesimal & Seksdagralsystem Reset All Settings... Nulstil alle indstillinger... &System &System SpeedCrunch &Theme SpeedCrunch-&tema &Classic &Klassisk &Modern &Moderne Context Help Kontekst Hjælp &Help &Hjælp Error Fejl Can't read from file %1 Kan ikke læse fra fil %1 Import Session Importere Sessionen Close Session Luk session Angle Mode: Vinkeltilstand: Notation: Notations: Precision: Præcision: Turn Omdrejning Revolution Omdrejning Fixed-point decimal Fastpunktsdecimal Rational Rationel Automatic decimal Automatisk decimal Automatic Automatisk User &Definitions... Bruger&definitioner... New &Tab Ny &fane New &Private Tab Ny &privat fane Keep Behold Make Private... Gør privat... New &Window Nyt &vindue &Open... &Åbn... &Rename... &Omdøb... Clo&ne... Klo&n... &Close Tab &Luk fane Reopen Clo&sed Tab Genå&bn lukket fane Open Sessions &Folder Åbn &sessionsmappe &Undo &Fortryd &Redo &Gentag Cu&t K&lip Copy &Last Result K&opiér seneste resultat &Wrap in Parentheses S&æt i parentes Full Scr&een Mode F&uldskærmstilstand &Basic &Grundlæggende &Scientific (wide) &Videnskabelig (bred) Scientific (narrow) Videnskabelig (smal) &Custom... &Tilpasset... Main &Menu Hoved&menu User &Variables Bruger&variabler &Left &Venstre &Right Høj&re &Up &Op &Down Ne&d Close Pa&ne &Luk rude User &Units Bruger&enheder &Turn &Omdrejning If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Hvis et nyt udtryk starter med +, -, *, eller /, vil SpeedCrunch automatisk indsætte "ans" først. &Accept with Enter &Acceptér med Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Acceptér det aktuelle forslag til automatisk fuldførelse med Enter uden først at vælge det med piletasterne. &Units &Enheder Show Live Result &Preview Vis live&forhåndsvisning af resultat Save &Window Position on Exit Gem &vinduesposition ved afslutning Hover Highlighting Fremhæv ved hover Group Integer Part Only Gruppér kun heltalsdelen Number Format... Talformat... Notation && Precision... Notation og præcision... After pressing Enter, keep the entered expression selected in the editor. Efter at have trykket på Enter, skal du sørge for at beholde den indtastede udtryk valgt i redigeringsprogrammet. Never Aldrig Always Altid Only for Single-Line Expressions Kun for enkeltlinjeudtryk Simplify Displayed Expressions Forenkl viste udtryk History Size &Limit... Historikstørrelses&grænse... Remove Trailing &Zeroes F&jern efterstillede nuller Nearest, Half &Away (round) Nærmeste, halv &væk (round) Nearest, Half &Even (roundeven) Nærmeste, halv &lige (roundeven) Toward &Zero (trunc) Mod &nul (trunc) &Fixed-Point &Fastpunkt &Rational &Rationel &Exponential (m·s�¹) &Eksponentiel (m·s�¹) &Fractional (m/s) &Brøk (m/s) &Rectangular (a + bi) &Rektangulær (a + bi) Exponential (re�ᶿ) eksponentiel (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) trigonometrisk (r(cos θ + i·sin θ)) Phasor (r∠θ) fasor (r∠θ) &Theme... &Tema... Check for &Updates Søg efter &opdateringer Source Code Kildekode &Zoom &Zoom &Results &Resultater Unit Notation Enhedsnotation Rounding Mode Afrundingstilstand &Notation &Notation &Imaginary Unit &Imaginær enhed &Window &Vindue &Editing &Redigering A&utocomplete A&utofuldførelse Up/Down Arrow History Op/ned-pil-historik &Appearance &Udseende &Menus &Menuer &Docks &Dockpaneler &Input and Results &Input og resultater &Disabled &Deaktiveret &Disable &Deaktiver Close preview Luk forhåndsvisning Rename... Omdøb... Clone... Klon... Close Tab Luk fane New Private Tab Ny privat fane Open... Åbn... Reopen Closed Tab Genåbn lukket fane Split Opdel Left Venstre Right Højre Up Op Down Ned Clear Ryd Delete Slet %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Privat session: indholdet kasseres, når den lukkes. Vælg Session > Behold for at gøre den til en almindelig session. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privat] Reset All Settings Nulstil alle indstillinger Reset all settings to their default values? Nulstil alle indstillinger til standardværdierne? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Dette omfatter udseende, redigering, resultatformater og vinduesindstillinger. Dine beregninger, åbne sessioner og brugerdefinitioner bevares. The settings file could not be written. Indstillingsfilen kunne ikke skrives. Clear this session's calculations, unfinished expression, variables, functions, and units? Ryd denne sessions beregninger, ufærdige udtryk, variabler, funktioner og enheder? Global user definitions are kept. Globale brugerdefinitioner bevares. Make Session Private Gør session privat The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Den gemte session %1 slettes. Dens indhold forbliver åbent i en privat session og kasseres, når sessionen lukkes, eller SpeedCrunch afsluttes. Make Private Gør privat Could not delete the saved session %1. Den gemte session %1 kunne ikke slettes. Keep Session Behold session Could not save the session. It remains private. Sessionen kunne ikke gemmes. Den forbliver privat. Clone Session Klon session Could not save session file %1. Sessionsfilen %1 kunne ikke gemmes. Could not delete session file %1. Sessionsfilen %1 kunne ikke slettes. JSON file (*.json);;Any file (*.*) JSON-fil (*.json);;Alle filer (*.*) Export session as JSON Eksportér sessionen som JSON The selected file is not valid JSON: %1 Den valgte fil er ikke gyldig JSON: %1 The selected file is not a SpeedCrunch session JSON file. Den valgte fil er ikke en JSON-fil for en SpeedCrunch-session. This file uses an obsolete SpeedCrunch session format and cannot be imported. Denne fil bruger et forældet SpeedCrunch-sessionsformat og kan ikke importeres. The selected JSON file is missing the required $schema field. Den valgte JSON-fil mangler det påkrævede $schema-felt. The selected JSON file uses an unsupported JSON schema: %1 Den valgte JSON-fil bruger et ikke-understøttet JSON-skema: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Den valgte JSON-fil mangler SpeedCrunch-sessionens skemaidentifikator ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Den valgte JSON-fil bruger et ikke-understøttet SpeedCrunch-sessionsformat: %1 The selected JSON file is missing the required session name. Den valgte JSON-fil mangler det påkrævede sessionsnavn. The selected JSON file has an empty session name. Den valgte JSON-fil har et tomt sessionsnavn. The selected JSON file has invalid or incomplete SpeedCrunch session data. Den valgte JSON-fil har ugyldige eller ufuldstændige SpeedCrunch-sessionsdata. Open Sessions Folder Åbn sessionsmappe Could not create the sessions folder: %1 Kunne ikke oprette sessionsmappen: %1 Could not open the sessions folder: %1 Kunne ikke åbne sessionsmappen: %1 Editor and Results Font Skrifttype til editor og resultater Open Session Åbn session Community Fællesskab Rename Session Omdøb session Clear Session Ryd session Delete Session Slet session Close Pane Luk rude User Variables Brugervariabler User Units Brugerenheder Clear History Ryd historik Are you sure you want to clear the calculation history? Er du sikker på, at du vil rydde beregningshistorikken? Session name: Sessionsnavn: A session named %1 already exists. En session med navnet %1 eksisterer allerede. Could not create session file %1. Kunne ikke oprette sessionsfil %1. Could not write session file %1. Kunne ikke oprette sessionsfil %1. Are you sure you want to delete this session? Er du sikker på, at du vil slette denne session? Custom Precision Tilpasset præcision Fractional digits: Brøkcifre: Theme Tema Light Themes Lyse temaer Dark Themes Mørke temaer Preview Forhåndsvisning Colors Farver Select color for %1 Vælg farve for %1 Import... Importér... Export... Eksportér... Import Theme Importér tema Theme file (*.json);;All files (*) Temafil (*.json);;Alle filer (*) Invalid theme file. Ugyldig temafil. Can't import theme "%1" because it conflicts with a built-in theme. Kan ikke importere tema "%1", da det er i konflikt med et indbygget tema. Can't find a writable theme folder. Kan ikke finde en mappe, hvor temaet kan redigeres. Overwrite Theme Overskriv tema A custom theme named "%1" already exists. Do you want to overwrite it? En brugerdefineret tema med navnet "%1" eksisterer allerede. Vil du overskrive det? Can't overwrite theme file %1 Kan ikke overskrive tema-filen %1 Can't copy theme file to %1 Kan ikke kopiere tema-filen til %1 Export Theme Eksportér tema Can't export theme as "%1" because it conflicts with a built-in theme. Kan ikke eksportere temaet som "%1", da det er i konflikt med et indbygget tema. Can't write to file %1 Kan ikke skrive til fil %1 Global User Variable Global brugervariabel Global User Function Global brugerfunktion Global User Unit Global brugerenhed User Definitions Brugerdefinitioner These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Disse definitioner er globale og indlæses i hver session. De kan ikke ændres i sessionerne og tilsidesætter definitioner med samme navn fra sessionseditoren. Indtast én definition pr. linje. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Eksempler: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Anvend Validate Valider Test Results Testresultater Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Importerede variabler: %1 Importerede funktioner: %2 Importerede enheder: %3 Linjenumre med fejl: %4 none ingen Apply Results Resultater af anvendelsen User definitions saved. Brugerdefinitioner gemt. History Size Limit Grænse for historikstørrelse Maximum number of history entries for this session (0 = unlimited): Maksimalt antal historiske indgange for denne session (0 = ubegrænset): Text file (*.txt);;Any file (*.*) Tekst fil (*.txt);;Alle filtyper (*.*) Could not recalculate from calculation %1: %2 Kunne ikke genberegne fra beregning %1: %2 History Size Limit Reached Historien har nået sin maksimale længde. This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Denne beregning fylder det sidste tilgængelige historiske felt. Fremtidige beregninger vil fjerne den ældste beregning fra historikken. Du kan øge grænsen fra Session > Historisk størrelsesgrænse. Editing calculation. Press Esc twice to cancel. Redigeringsberegning. Tryk Esc to gange for at annullere. Calculation Settings Beregningsindstillinger Invalid recalculation start index Ugyldigt startindeks for genberegning System Default System Standard Language Sprog Select the language: Vælg sprog: Custom Tilpasset Decimal places: Decimaler: &Automatic &Automatisk &Precision &Præcision Plain &text Almindelig &tekst Formula &Book Ligning &Bog &Export &Eksport Export session as HTML Eksportér sessionen som HTML HTML file (*.html) HTML fil (*.html) Export session as plain text Eksportér sessionen som almindelig tekst ManualWindow SpeedCrunch Manual SpeedCrunch brugervejledning %1 - SpeedCrunch Manual %1 - SpeedCrunch brugervejledning NumberFormatDialog Number Format Talformat <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Vælg talformat til resultater og gruppering af indtastede cifre.</b><br/><br/>Bemærk: entydige formater accepteres for indtastede tal, selv når de afviger fra det valgte visningsformat.<br/> QObject Global User Variable Global brugervariabel Global User Function Global brugerfunktion Global User Unit Global brugerenhed Backspace Tilbage Clear expression Ryd udtryk Evaluate expression Beregn udtryk Insert text Indsæt tekst Automatic decimal Automatisk decimal Fixed-point decimal Fastpunktsdecimal Engineering decimal Ingeniørdecimal Scientific decimal Videnskabelig decimal Rational Rationel Binary Binær Octal Oktal Hexadecimal Heksadecimal Sexagesimal Seksagesimal Update Available Opdatering tilgængelig A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> En nyere version (%1) er tilgængelig. <a href="%2">Besøg hjemmesiden for at downloade.</a> Check for Updates Søg efter opdateringer SpeedCrunch %1 is up to date. SpeedCrunch version 1 er opdateret. No connectivity. Please check your internet connection and try again. Ingen forbindelse. Venligst kontroller din internetforbindelse og prøv igen. Could not verify the latest available version. Det var ikke muligt at verificere den seneste tilgængelige version. ResultDisplay Scroll to bottom Rul til bunden Edit Expression Rediger udtryk Change Settings Skift indstillinger New Tab Ny fane &Import... &Importér... &Export &Eksportér Plain &text Almindelig &tekst Copy Kopier Selection Markering Select All Markér alt Expression Udtryk Result Resultat Calculation Beregning Calculation as Single Line Beregning på én linje Remove Fjern This Calculation Denne beregning All Calculations Above Alle beregninger ovenfor All Calculations Below Alle beregninger nedenfor New Private Tab Ny privat fane Session Session Open... Åbn... Clone... Klon... Rename... Omdøb... Keep Behold Make Private... Gør privat... Clear Ryd Delete Slet Close Luk Split Opdel Left Venstre Right Højre Up Op Down Ned Close Pane Luk rude Main Menu Hovedmenu Cancel editing Annuller redigering Copy result Kopiér resultat Edit expression Rediger udtryk Change settings Skift indstillinger Remove calculation Fjern beregning ResultSlotsDialog Notation & Precision Notation og præcision Result Line Resultatlinje Enabled Aktiveret Notation Notations Decimal Places Decimaler Main Line Hovedlinje Extra Line #1 Ekstra linje nr. 1 Extra Line #2 Ekstra linje nr. 2 Extra Line #3 Ekstra linje nr. 3 Extra Line #4 Ekstra linje nr. 4 Auto Bil UserFunctionListWidget Name Navn Value Værdi Description Beskrivelse Search Søgning No match found Ingen match fundet Insert Indsæt Edit Redigere Delete Slet Delete All Slet Alt UserUnitListWidget Name Navn Value Værdi Description Beskrivelse Search Søg No match found Ingen match fundet Insert Indsæt Edit Rediger Delete Slet Delete All Slet alle VariableListWidget Name Navn Value Værdi Description Beskrivelse Search Søg No match found Ingen match fundet Insert Indsæt Edit Rediger Delete Slet Delete All Slet alt heldercorreia-speedcrunch-e7ca37f/src/resources/locale/de.ts000066400000000000000000010533621526573132500243470ustar00rootroot00000000000000 AboutBox About SpeedCrunch Über SpeedCrunch Core developers Hauptentwickler Original author Ursprünglicher Autor Close Schließen Math engine Mathematikmodul Main author | Logo | Maintainer Hauptautor | Logo | Betreuer Thanks Danksagungen Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Die SpeedCrunch-Entwickler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Dieses Programm ist freie Software. Sie können es weitergeben oder ändern, solange Sie dabei den Bedingungen der GNU General Public License Version 2 (GPL) oder einer späteren Version, wie von der Free Software Foundation herausgegeben, folgen This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Dieses Programm wird in der Hoffnung verbreitet, dass es von Nutzen ist, jedoch OHNE JEDE GEWÄHRLEISTUNG und ohne Zusicherung seiner TAUGLICHKEIT, weder im allgemeinen noch für besondere Zwecke. Details finden Sie in der GNU General Public License (GPL). BitFieldWidget Reset bits to zero Bits auf null zurücksetzen Invert bits Bits invertieren Shift bits left Bits nach links verschieben Shift bits right Bits nach rechts verschieben Book Index Inhaltsverzeichnis Algebra Algebra Quadratic Equation Quadratische Gleichung Logarithmic Base Conversion Basisumrechnung von Logarithmen Geometry Geometrie Circle Kreis Sector Ausschnitt Sphere Kugel Cube Würfel Cone Kegel Cylinder Zylinder Electronics Elektronik Ohm's Law Ohmsches Gesetz Power Leistung Reactance Reaktanz Resonance Resonanz Radio Frequency Radiofrequenzband Antennas Antennen Characteristic Impedance (coax) Charakteristische Impedanz (Koax) Velocity of Propagation (coax) Ausbreitungsgeschwindigkeit (Koax) Standing Wave Ratio & Return Loss Stehwellenverhältnis & Rückflussdämpfung Free Space Wavelength Freiraumwellenlänge resistance Widerstand voltage Spannung current Strom power Leistung inductive reactance induktive Reaktanz capacitive reactance kapazitive Reaktanz inductance Induktivität capacitance Kapazität frequency Frequenz resonance frequency Resonanzfrequenz area Fläche perimeter Perimeter diameter Durchmesser radius Radius volume Volumen surface area Oberfläche height Höhe slant height Seitenhöhe face diagonal Flächendiagonale space diagonal Raumdiagonale edge length Kantenlänge arc length Bogenlänge central angle (degrees) Zentriwinkel (Grad) input power Eingangsleistung reflected power reflektierte Leistung transmitted power übertragene Leistung return loss Rückflussdämpfung dielectric constant Dielektrizitätskonstante outer conductor's inner diameter Innendurchmesser der Außenleiter inner conductor's outer diameter Außendurchmesser der Innenleiter speed of light Lichtgeschwindigkeit reflection coefficient Reflexionsfaktor standing wave ratio Stehwellenverhältnis normalized impedance normierte Impedanz frequency (Hz) Frequenz (Hz) BookDock Formula Book Formelsammlung ConstantCompletion Search constants Konstanten suchen No match found Keine Übereinstimmung gefunden Constants Mathematics Mathematik Physics (CODATA 2022) Physik (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chemie (IUPAC - CIAAW 2021) Uncategorized Nicht kategorisiert Universal Allgemein Physicochemical Physikochemisch Atomic & Nuclear — General Atom- & Kernphysik - Allgemein Atomic & Nuclear — Electroweak Atom- & Kernphysik - Elektroschwach Atomic & Nuclear — Electron Atom- & Kernphysik - Elektron Atomic & Nuclear — Muon Atom- & Kernphysik - Myon Atomic & Nuclear — Tau Atom- & Kernphysik - Tau Atomic & Nuclear — Proton Atom- & Kernphysik - Proton Atomic & Nuclear — Neutron Atom- & Kernphysik - Neutron Atomic & Nuclear — Deuteron Atom- & Kernphysik - Deuteron Atomic & Nuclear — Triton Atom- & Kernphysik - Triton Atomic & Nuclear — Helion Atom- & Kernphysik - Helion Atomic & Nuclear — Alpha particle Atom- & Kernphysik - Alphateilchen Atomic & Nuclear — Atomic units Atom- & Kernphysik - Atomare Einheiten Atomic & Nuclear — Energy conversion relationships Atom- & Kernphysik - Energie-Umrechnungsbeziehungen Atomic & Nuclear — X-ray units Atom- & Kernphysik - Röntgeneinheiten Atomic & Nuclear — Magnetic shielding corrections Atom- & Kernphysik - Magnetische Abschirmungskorrekturen Masses Massen Lifetimes Lebensdauern Molar Masses Molmassen Electronegativity Elektronegativität Ionization Energy Ionisierungsenergie Nominal Constants (IAU 2015) Nominalkonstanten (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Aktuelle beste Schätzwerte (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) Wellenwiderstand des Vakuums (Z₀) reduced Planck constant (�) Reduzierte Planck-Konstante (�) vacuum electric permittivity (ϵ₀) Elektrische Feldkonstante (ϵ₀) Newtonian constant of gravitation (G) Newtonsche Gravitationskonstante (G) vacuum magnetic permeability (μ₀) Magnetische Feldkonstante (μ₀) Planck constant (h) Planck-Konstante (h) speed of light in vacuum (c) Lichtgeschwindigkeit im Vakuum (c) standard acceleration of gravity (gₙ) Normfallbeschleunigung (gₙ) Newtonian constant of gravitation over h-bar c Newtonsche Gravitationskonstante über h quer c Planck length Planck-Länge Planck constant in eV/Hz (h) Planck-Konstante in eV/Hz (h) Planck mass Planck-Massee Planck mass energy equivalent in GeV Planck-Massee-Energieäquivalent in GeV Planck temperature Planck-Temperatur Planck time Planck-Zeit reduced Planck constant in eV·s (�) Reduzierte Planck-Konstante in eV·s (�) reduced Planck constant times c in MeV·fm Reduzierte Planck-Konstante mal c in MeV·fm Bohr magneton Bohrsches Magneton conductance quantum (G₀) Leitwertquantum (G₀) Coulomb constant (kₑ) Coulomb-Konstante (kₑ) elementary charge (e) Elementarladung (e) elementary charge over h-bar Elementarladung über h quer conventional value of Josephson constant Konventioneller Wert von Josephson-Konstante Josephson constant Josephson-Konstante conventional value of ampere-90 Konventioneller Wert von Ampere-90 conventional value of coulomb-90 Konventioneller Wert von Coulomb-90 conventional value of farad-90 Konventioneller Wert von Farad-90 conventional value of henry-90 Konventioneller Wert von Henry-90 conventional value of ohm-90 Konventioneller Wert von Ohm-90 conventional value of volt-90 Konventioneller Wert von Volt-90 conventional value of watt-90 Konventioneller Wert von Watt-90 magnetic flux quantum (Φ₀) Magnetisches Flussquantum (Φ₀) nuclear magneton Kernmagneton inverse of conductance quantum Kehrwert von Leitwertquantum conventional value of von Klitzing constant Konventioneller Wert von Von-Klitzing-Konstante von Klitzing constant Von-Klitzing-Konstante atomic unit of magnetic dipole moment Atomare Einheit von magnetisches Dipolmoment atomic unit of magnetic flux density Atomare Einheit von magnetische Flussdichte Bohr magneton in eV/T Bohrsches Magneton in eV/T Bohr magneton in Hz/T Bohrsches Magneton in Hz/T Bohr magneton in inverse meter per tesla Bohrsches Magneton in reziproker Meter pro Tesla Bohr magneton in K/T Bohrsches Magneton in K/T nuclear magneton in eV/T Kernmagneton in eV/T nuclear magneton in inverse meter per tesla Kernmagneton in reziproker Meter pro Tesla nuclear magneton in K/T Kernmagneton in K/T nuclear magneton in MHz/T Kernmagneton in MHz/T Bohr radius (a₀) Bohr-Radius (a₀) fine-structure constant (α) Feinstrukturkonstante (α) Hartree energy (Eₕ) Hartree-Energie (Eₕ) Hartree energy in eV Hartree-Energie in eV quantum of circulation Zirkulationsquantum quantum of circulation times 2 Zirkulationsquantum Zeits 2 Rydberg constant (R∞) Rydberg-Konstante (R∞) atomic mass unit-hartree relationship Atomare Masseeneinheit-hartree Beziehung atomic mass unit-hertz relationship Atomare Masseeneinheit-Hertz Beziehung atomic mass unit-inverse meter relationship Atomare Masseeneinheit-reziproker Meter Beziehung atomic mass unit-joule relationship Atomare Masseeneinheit-Joule Beziehung atomic mass unit-kelvin relationship Atomare Masseeneinheit-Kelvin Beziehung atomic mass unit-kilogram relationship Atomare Masseeneinheit-Kilogramm Beziehung atomic unit of 1st hyperpolarizability Atomare Einheit von 1st Hyperpolarisierbarkeit atomic unit of 2nd hyperpolarizability Atomare Einheit von 2nd Hyperpolarisierbarkeit atomic unit of charge (e) Atomare Einheit von charge (e) atomic unit of charge density Atomare Einheit von Ladungsdichte atomic unit of current Atomare Einheit von current atomic unit of electric dipole moment Atomare Einheit von elektrisches Dipolmoment atomic unit of electric field Atomare Einheit von elektrisches Feld atomic unit of electric field gradient Atomare Einheit von elektrischer Feldgradient atomic unit of electric polarizability Atomare Einheit von elektrische Polarisierbarkeit atomic unit of electric potential Atomare Einheit von elektrisches Potential atomic unit of electric quadrupole moment Atomare Einheit von elektrisches Quadrupolmoment atomic unit of action Atomare Einheit von Wirkung atomic unit of energy Atomare Einheit von Energie atomic unit of force Atomare Einheit von Kraft atomic unit of length Atomare Einheit von Länge hertz-atomic mass unit relationship Hertz-atomare Masseeneinheit Beziehung hertz-electron volt relationship Hertz-Elektronenvolt Beziehung hertz-hartree relationship Hertz-hartree Beziehung hertz-inverse meter relationship Hertz-reziproker Meter Beziehung hertz-joule relationship Hertz-Joule Beziehung hertz-kelvin relationship Hertz-Kelvin Beziehung hertz-kilogram relationship Hertz-Kilogramm Beziehung hyperfine transition frequency of Cs-133 Hyperfein-Übergangsfrequenz von Cs-133 inverse fine-structure constant (α�¹) Inverse Feinstrukturkonstante (α�¹) inverse meter-atomic mass unit relationship Reziproker Meter-atomare Masseeneinheit Beziehung inverse meter-electron volt relationship Reziproker Meter-Elektronenvolt Beziehung inverse meter-hartree relationship Reziproker Meter-hartree Beziehung inverse meter-hertz relationship Reziproker Meter-Hertz Beziehung inverse meter-joule relationship Reziproker Meter-Joule Beziehung inverse meter-kelvin relationship Reziproker Meter-Kelvin Beziehung inverse meter-kilogram relationship Reziproker Meter-Kilogramm Beziehung joule-atomic mass unit relationship Joule-atomare Masseeneinheit Beziehung joule-electron volt relationship Joule-Elektronenvolt Beziehung joule-hertz relationship Joule-Hertz Beziehung joule-hartree relationship Joule-hartree Beziehung joule-inverse meter relationship Joule-reziproker Meter Beziehung joule-kelvin relationship Joule-Kelvin Beziehung joule-kilogram relationship Joule-Kilogramm Beziehung kelvin-atomic mass unit relationship Kelvin-atomare Masseeneinheit Beziehung kelvin-electron volt relationship Kelvin-Elektronenvolt Beziehung kelvin-hertz relationship Kelvin-Hertz Beziehung kelvin-hartree relationship Kelvin-hartree Beziehung kelvin-inverse meter relationship Kelvin-reziproker Meter Beziehung kelvin-joule relationship Kelvin-Joule Beziehung kelvin-kilogram relationship Kelvin-Kilogramm Beziehung kilogram-atomic mass unit relationship Kilogramm-atomare Masseeneinheit Beziehung kilogram-electron volt relationship Kilogramm-Elektronenvolt Beziehung kilogram-hertz relationship Kilogramm-Hertz Beziehung kilogram-hartree relationship Kilogramm-hartree Beziehung kilogram-inverse meter relationship Kilogramm-reziproker Meter Beziehung kilogram-joule relationship Kilogramm-Joule Beziehung kilogram-kelvin relationship Kilogramm-Kelvin Beziehung lattice parameter of silicon (a) Gitterparameter von Silizium (a) luminous efficacy Lichtausbeute natural unit of energy Natürliche Einheit von Energie natural unit of energy in MeV Natürliche Einheit von Energie in MeV natural unit of action (�) Natürliche Einheit von Wirkung (�) natural unit of action in eV·s Natürliche Einheit von Wirkung in eV·s natural unit of length Natürliche Einheit von Länge natural unit of mass Natürliche Einheit von Masse natural unit of momentum Natürliche Einheit von Impuls natural unit of momentum in MeV/c Natürliche Einheit von Impuls in MeV/c natural unit of time Natürliche Einheit von Zeit natural unit of velocity Natürliche Einheit von Geschwindigkeit Rydberg constant times c in Hz Rydberg-Konstante mal c in Hz Rydberg constant times hc in eV Rydberg-Konstante mal hc in eV Rydberg constant times hc in J Rydberg-Konstante mal hc in J Fermi coupling constant Fermi-Kopplungskonstante weak mixing angle Schwacher Mischungswinkel W to Z mass ratio W-zu-Z-Masseenverhältnis Thomson cross section (σₑ) Thomson-Wirkungsquerschnitt (σₑ) electron mass (mₑ) Elektron Masse (mₑ) electron mass in u Elektron Masse in u electron mass energy equivalent (mₑ·c²) Elektron Masse Energie equivalent (mₑ·c²) electron mass energy equivalent in MeV Elektron Masse Energie equivalent in MeV reduced Compton wavelength Reduced Compton waveLänge classical electron radius (rₑ) Klassischer ElektronenRadius (rₑ) electron charge to mass quotient Elektron Ladungs-Massee-Quotient electron-deuteron magnetic moment ratio Elektron-Deuteron Verhältnis der magnetischen Momente electron-deuteron mass ratio Elektron-Deuteron Masseenverhältnis electron g factor (gₑ) Elektron g-Faktor (gₑ) electron gyromagnetic ratio (γₑ) Elektron gyromagnetisches Verhältnis (γₑ) electron gyromagnetic ratio in MHz/T Elektron gyromagnetisches Verhältnis in MHz/T electron-helion mass ratio Elektron-Helion Masseenverhältnis electron magnetic moment (μₑ) Elektron magnetisches Moment (μₑ) electron magnetic moment anomaly (aₑ) Elektron Anomalie des magnetischen Moments (aₑ) electron magnetic moment to Bohr magneton ratio Elektron magnetisches Moment zu Bohrsches Magneton ratio electron magnetic moment to nuclear magneton ratio Elektron magnetisches Moment zu Kernmagneton ratio electron molar mass (Mₑ) Elektron MolMassee (Mₑ) electron-muon magnetic moment ratio Elektron-Myon Verhältnis der magnetischen Momente electron-muon mass ratio Elektron-Myon Masseenverhältnis electron-neutron magnetic moment ratio Elektron-Neutron Verhältnis der magnetischen Momente electron-neutron mass ratio Elektron-Neutron Masseenverhältnis electron-proton magnetic moment ratio Elektron-Proton Verhältnis der magnetischen Momente electron-proton mass ratio Elektron-Proton Masseenverhältnis electron relative atomic mass (Ar(e)) Elektron relative AtomMassee (Ar(e)) electron-tau mass ratio Elektron-Tau Masseenverhältnis electron to alpha particle mass ratio Elektron zu Alphateilchen Masseenverhältnis electron to shielded helion magnetic moment ratio Elektron zu abgeschirmtes Helion Verhältnis der magnetischen Momente electron to shielded proton magnetic moment ratio Elektron zu abgeschirmtes Proton Verhältnis der magnetischen Momente electron-triton mass ratio Elektron-Triton Masseenverhältnis electron volt-atomic mass unit relationship Elektronenvolt-atomare Masseeneinheit Beziehung electron volt-hartree relationship Elektronenvolt-hartree Beziehung electron volt-hertz relationship Elektronenvolt-Hertz Beziehung electron volt-inverse meter relationship Elektronenvolt-reziproker Meter Beziehung electron volt-joule relationship Elektronenvolt-Joule Beziehung electron volt-kelvin relationship Elektronenvolt-Kelvin Beziehung electron volt-kilogram relationship Elektronenvolt-Kilogramm Beziehung hartree-atomic mass unit relationship Hartree-atomare Masseeneinheit Beziehung hartree-electron volt relationship Hartree-Elektronenvolt Beziehung muon Compton wavelength Myon Compton waveLänge muon-electron mass ratio Myon-Elektron Masseenverhältnis muon g factor Myon g-Faktor muon magnetic moment Myon magnetisches Moment muon magnetic moment anomaly Myon Anomalie des magnetischen Moments muon magnetic moment to Bohr magneton ratio Myon magnetisches Moment zu Bohrsches Magneton ratio muon magnetic moment to nuclear magneton ratio Myon magnetisches Moment zu Kernmagneton ratio muon mass Myon Masse muon mass energy equivalent Myon Masse Energie equivalent muon mass energy equivalent in MeV Myon Masse Energie equivalent in MeV muon mass in u Myon Masse in u muon molar mass Myon MolMassee muon-neutron mass ratio Myon-Neutron Masseenverhältnis muon-proton magnetic moment ratio Myon-Proton Verhältnis der magnetischen Momente muon-proton mass ratio Myon-Proton Masseenverhältnis muon-tau mass ratio Myon-Tau Masseenverhältnis reduced muon Compton wavelength Reduced Myon Compton waveLänge reduced tau Compton wavelength Reduced Tau Compton waveLänge tau Compton wavelength Tau Compton waveLänge tau-electron mass ratio Tau-Elektron Masseenverhältnis tau mass Tau Masse tau mass energy equivalent Tau Masse Energie equivalent tau mass in u Tau Masse in u tau molar mass Tau MolMassee tau-muon mass ratio Tau-Myon Masseenverhältnis tau-neutron mass ratio Tau-Neutron Masseenverhältnis tau-proton mass ratio Tau-Proton Masseenverhältnis proton charge to mass quotient Proton Ladungs-Massee-Quotient proton Compton wavelength Proton Compton waveLänge proton-electron mass ratio Proton-Elektron Masseenverhältnis proton g factor (gₚ) Proton g-Faktor (gₚ) proton gyromagnetic ratio (γₚ) Proton gyromagnetisches Verhältnis (γₚ) proton gyromagnetic ratio in MHz/T Proton gyromagnetisches Verhältnis in MHz/T proton magnetic moment (μₚ) Proton magnetisches Moment (μₚ) proton magnetic moment to Bohr magneton ratio Proton magnetisches Moment zu Bohrsches Magneton ratio proton magnetic moment to nuclear magneton ratio Proton magnetisches Moment zu Kernmagneton ratio proton magnetic shielding correction Proton magnetische Abschirmungskorrektur proton mass (mₚ) Proton Masse (mₚ) proton mass energy equivalent Proton Masse Energie equivalent proton mass energy equivalent in MeV Proton Masse Energie equivalent in MeV proton mass in u Proton Masse in u proton molar mass (Mₚ) Proton MolMassee (Mₚ) proton-muon mass ratio Proton-Myon Masseenverhältnis proton-neutron magnetic moment ratio Proton-Neutron Verhältnis der magnetischen Momente proton-neutron mass ratio Proton-Neutron Masseenverhältnis proton relative atomic mass (Ar(p)) Proton relative AtomMassee (Ar(p)) proton rms charge radius Proton RMS-LadungsRadius proton-tau mass ratio Proton-Tau Masseenverhältnis reduced proton Compton wavelength Reduced Proton Compton waveLänge shielded proton gyromagnetic ratio Abgeschirmtes Proton gyromagnetisches Verhältnis shielded proton gyromagnetic ratio in MHz/T Abgeschirmtes Proton gyromagnetisches Verhältnis in MHz/T shielded proton magnetic moment Abgeschirmtes Proton magnetisches Moment shielded proton magnetic moment to Bohr magneton ratio Abgeschirmtes Proton magnetisches Moment zu Bohrsches Magneton ratio shielded proton magnetic moment to nuclear magneton ratio Abgeschirmtes Proton magnetisches Moment zu Kernmagneton ratio neutron Compton wavelength Neutron Compton waveLänge neutron-electron magnetic moment ratio Neutron-Elektron Verhältnis der magnetischen Momente neutron-electron mass ratio Neutron-Elektron Masseenverhältnis neutron g factor (gₙ) Neutron g-Faktor (gₙ) neutron gyromagnetic ratio (γₙ) Neutron gyromagnetisches Verhältnis (γₙ) neutron gyromagnetic ratio in MHz/T Neutron gyromagnetisches Verhältnis in MHz/T neutron magnetic moment (μₙ) Neutron magnetisches Moment (μₙ) neutron magnetic moment to Bohr magneton ratio Neutron magnetisches Moment zu Bohrsches Magneton ratio neutron magnetic moment to nuclear magneton ratio Neutron magnetisches Moment zu Kernmagneton ratio neutron mass (mₙ) Neutron Masse (mₙ) neutron mass energy equivalent Neutron Masse Energie equivalent neutron mass energy equivalent in MeV Neutron Masse Energie equivalent in MeV neutron mass in u Neutron Masse in u neutron molar mass (Mₙ) Neutron MolMassee (Mₙ) neutron-muon mass ratio Neutron-Myon Masseenverhältnis neutron-proton magnetic moment ratio Neutron-Proton Verhältnis der magnetischen Momente neutron-proton mass difference Neutron-Proton Masseenunterschied neutron-proton mass difference energy equivalent Neutron-Proton Masseenunterschied Energie equivalent neutron-proton mass difference energy equivalent in MeV Neutron-Proton Masseenunterschied Energie equivalent in MeV neutron-proton mass difference in u Neutron-Proton Masseenunterschied in u neutron-proton mass ratio Neutron-Proton Masseenverhältnis neutron relative atomic mass (Ar(n)) Neutron relative AtomMassee (Ar(n)) neutron-tau mass ratio Neutron-Tau Masseenverhältnis neutron to shielded proton magnetic moment ratio Neutron zu abgeschirmtes Proton Verhältnis der magnetischen Momente reduced neutron Compton wavelength Reduced Neutron Compton waveLänge deuteron-electron magnetic moment ratio Deuteron-Elektron Verhältnis der magnetischen Momente deuteron-electron mass ratio Deuteron-Elektron Masseenverhältnis deuteron g factor Deuteron g-Faktor deuteron magnetic moment Deuteron magnetisches Moment deuteron magnetic moment to Bohr magneton ratio Deuteron magnetisches Moment zu Bohrsches Magneton ratio deuteron magnetic moment to nuclear magneton ratio Deuteron magnetisches Moment zu Kernmagneton ratio deuteron mass Deuteron Masse deuteron mass energy equivalent Deuteron Masse Energie equivalent deuteron mass energy equivalent in MeV Deuteron Masse Energie equivalent in MeV deuteron mass in u Deuteron Masse in u deuteron molar mass Deuteron MolMassee deuteron-neutron magnetic moment ratio Deuteron-Neutron Verhältnis der magnetischen Momente deuteron-proton magnetic moment ratio Deuteron-Proton Verhältnis der magnetischen Momente deuteron-proton mass ratio Deuteron-Proton Masseenverhältnis deuteron relative atomic mass (Ar(d)) Deuteron relative AtomMassee (Ar(d)) deuteron rms charge radius Deuteron RMS-LadungsRadius triton-electron mass ratio Triton-Elektron Masseenverhältnis triton g factor (gₜ) Triton g-Faktor (gₜ) triton magnetic moment (μₜ) Triton magnetisches Moment (μₜ) triton magnetic moment to Bohr magneton ratio Triton magnetisches Moment zu Bohrsches Magneton ratio triton magnetic moment to nuclear magneton ratio Triton magnetisches Moment zu Kernmagneton ratio triton mass (mₜ) Triton Masse (mₜ) triton mass energy equivalent Triton Masse Energie equivalent triton mass energy equivalent in MeV Triton Masse Energie equivalent in MeV triton mass in u Triton Masse in u triton molar mass (Mₜ) Triton MolMassee (Mₜ) triton-proton mass ratio Triton-Proton Masseenverhältnis triton relative atomic mass (Ar(t)) Triton relative AtomMassee (Ar(t)) triton to proton magnetic moment ratio Triton zu Proton Verhältnis der magnetischen Momente helion-electron mass ratio Helion-Elektron Masseenverhältnis helion g factor (gₕ) Helion g-Faktor (gₕ) helion magnetic moment (μₕ) Helion magnetisches Moment (μₕ) helion magnetic moment to Bohr magneton ratio Helion magnetisches Moment zu Bohrsches Magneton ratio helion magnetic moment to nuclear magneton ratio Helion magnetisches Moment zu Kernmagneton ratio helion mass (mₕ) Helion Masse (mₕ) helion mass energy equivalent Helion Masse Energie equivalent helion mass energy equivalent in MeV Helion Masse Energie equivalent in MeV helion mass in u Helion Masse in u helion molar mass (Mₕ) Helion MolMassee (Mₕ) helion-proton mass ratio Helion-Proton Masseenverhältnis helion relative atomic mass (Ar(h)) Helion relative AtomMassee (Ar(h)) helion shielding shift Helion Abschirmungsverschiebung shielded helion gyromagnetic ratio Abgeschirmtes Helion gyromagnetisches Verhältnis shielded helion gyromagnetic ratio in MHz/T Abgeschirmtes Helion gyromagnetisches Verhältnis in MHz/T shielded helion magnetic moment Abgeschirmtes Helion magnetisches Moment shielded helion magnetic moment to Bohr magneton ratio Abgeschirmtes Helion magnetisches Moment zu Bohrsches Magneton ratio shielded helion magnetic moment to nuclear magneton ratio Abgeschirmtes Helion magnetisches Moment zu Kernmagneton ratio shielded helion to proton magnetic moment ratio Abgeschirmtes Helion zu Proton Verhältnis der magnetischen Momente shielded helion to shielded proton magnetic moment ratio Abgeschirmtes Helion zu abgeschirmtes Proton Verhältnis der magnetischen Momente alpha particle mass Alphateilchen Masse alpha particle mass in u Alphateilchen Masse in u alpha particle mass energy equivalent Alphateilchen Masse Energie equivalent alpha particle mass energy equivalent in MeV Alphateilchen Masse Energie equivalent in MeV alpha particle-electron mass ratio Alphateilchen-Elektron Masseenverhältnis alpha particle-proton mass ratio Alphateilchen-Proton Masseenverhältnis alpha particle rms charge radius Alphateilchen RMS-LadungsRadius alpha particle molar mass Alphateilchen MolMassee alpha particle relative atomic mass (Ar(α)) Alphateilchen relative AtomMassee (Ar(α)) atomic mass constant (mᵤ) Atomare Masseenkonstante (mᵤ) Avogadro constant Avogadro-Konstante Boltzmann constant (k) Boltzmann-Konstante (k) Boltzmann constant in eV/K Boltzmann-Konstante in eV/K Boltzmann constant in Hz/K Boltzmann-Konstante in Hz/K Boltzmann constant in inverse meter per kelvin Boltzmann-Konstante in reziproker Meter pro Kelvin electron volt (eV) Elektronenvolt (eV) Faraday constant (F) Faraday-Konstante (F) first radiation constant (c�) Erste Strahlungskonstante (c�) first radiation constant for spectral radiance Erste Strahlungskonstante für spektrale Strahldichte molar gas constant (R) Molare Gaskonstante (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidt-Konstante (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Loschmidt-Konstante (n₀, 273.15 K, 101.325 kPa) molar Planck constant Molar Planck-Konstante second radiation constant (c₂) Zweite Strahlungskonstante (c₂) Stefan-Boltzmann constant (σ) Stefan-Boltzmann-Konstante (σ) lattice spacing of ideal Si (d₂₂₀) Gitterabstand von idealem Si (d₂₂₀) atomic mass constant energy equivalent Atomare Masseenkonstante Energie equivalent atomic mass constant energy equivalent in MeV Atomare Masseenkonstante Energie equivalent in MeV atomic mass unit-electron volt relationship Atomare Masseeneinheit-Elektronenvolt Beziehung molar mass constant (Mᵤ) MolMassee constant (Mᵤ) molar mass of carbon-12 MolMassee of carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) Molvolumen des idealen Gases (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) Molvolumen des idealen Gases (273.15 K, 101.325 kPa) molar volume of silicon Molvolumen von Silizium Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode-Konstante (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode-Konstante (1 K, 101.325 kPa) Wien frequency displacement law constant Wiensche Frequenz-Verschiebungskonstante Wien wavelength displacement law constant Wien waveLänge displacement law constant standard atmosphere (atm) Standardatmosphäre (atm) standard-state pressure (p°) Standarddruck (p°) Angstrom star (Å*) Ångström-Stern (Å*) Copper x unit Kupfer-X-Einheit Molybdenum x unit Molybdän-X-Einheit atomic unit of magnetizability Atomare Einheit von Magnetisierbarkeit atomic unit of mass (mₑ) Atomare Einheit von Masse (mₑ) atomic unit of momentum Atomare Einheit von Impuls atomic unit of permittivity Atomare Einheit von Permittivität atomic unit of time Atomare Einheit von Zeit atomic unit of velocity Atomare Einheit von Geschwindigkeit hartree-hertz relationship Hartree-Hertz Beziehung hartree-inverse meter relationship Hartree-reziproker Meter Beziehung hartree-joule relationship Hartree-Joule Beziehung hartree-kelvin relationship Hartree-Kelvin Beziehung hartree-kilogram relationship Hartree-Kilogramm Beziehung shielding difference of d and p in HD Abschirmungsdifferenz von d and p in HD shielding difference of t and p in HT Abschirmungsdifferenz von t and p in HT pi (π) Pi (π) Euler's number (e) Eulersche Zahl (e) golden ratio (φ) Goldener Schnitt (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni-Konstante (γ) nominal solar radius Nominaler Sonnen- Radius nominal solar total irradiance Nominaler Sonnen- Gesamtbestrahlungsstärke nominal solar luminosity Nominaler Sonnen- Leuchtkraft nominal solar effective temperature Nominaler Sonnen- effektive Temperatur nominal solar mass parameter Nominaler Sonnen- Masse parameter nominal terrestrial equatorial radius Nominaler Erd- Äquatorradius nominal terrestrial polar radius Nominaler Erd- Polradius nominal terrestrial mass parameter Nominaler Erd- Masse parameter nominal jovian equatorial radius Nominaler Jupiter- Äquatorradius nominal jovian polar radius Nominaler Jupiter- Polradius nominal jovian mass parameter Nominaler Jupiter- Masse parameter average value of one minus the rate of TCG relative to TCB Mittelwert von eins minus der Rate von TCG relativ zu TCB solar mass parameter (TCB-compatible) Solar Masse parameter (TCB-compatible) solar mass parameter (TDB-compatible) Solar Masse parameter (TDB-compatible) equatorial radius of the Earth (TT-compatible) Äquatorradius of the Earth (TT-compatible) dynamical form factor of the Earth Dynamischer Formfaktor der Erde time rate of change in the dynamical form factor of the Earth Zeit rate of change in the dynamischer Formfaktor der Erde geocentric gravitational constant (TCB-compatible) Geozentrische Gravitationskonstante (TCB-compatible) geocentric gravitational constant (TT-compatible) Geozentrische Gravitationskonstante (TT-compatible) geocentric gravitational constant (TDB-compatible) Geozentrische Gravitationskonstante (TDB-compatible) potential of the geoid Potential des Geoids nominal mean angular velocity of the Earth (TT-compatible) Nominal mean angular Geschwindigkeit of the Earth (TT-compatible) ratio mass of the Moon to the Earth Ratio Masse of the Moon zu the Earth ratio of the mass of the Sun to Mercury Ratio of the Masse of the Sun zu Mercury ratio of the mass of the Sun to Venus Ratio of the Masse of the Sun zu Venus ratio of the mass of the Sun to Mars Ratio of the Masse of the Sun zu Mars ratio of the mass of the Sun to Jupiter Ratio of the Masse of the Sun zu JuPiter ratio of the mass of the Sun to Saturn Ratio of the Masse of the Sun zu Saturn ratio of the mass of the Sun to Uranus Ratio of the Masse of the Sun zu Uranus ratio of the mass of the Sun to Neptune Ratio of the Masse of the Sun zu Neptune ratio of the mass of the Sun to (134340) Pluto Ratio of the Masse of the Sun zu (134340) Pluto ratio of the mass of the Sun to (136199) Eris Ratio of the Masse of the Sun zu (136199) Eris ratio of the mass of (1) Ceres to the Sun Ratio of the Masse of (1) Ceres zur Sonne ratio of the mass of (2) Pallas to the Sun Ratio of the Masse of (2) Pallas zur Sonne ratio of the mass of (4) Vesta to the Sun Ratio of the Masse of (4) Vesta zur Sonne mean obliquity of the ecliptic at J2000.0 Mittlere Schiefe der Ekliptik bei J2000.0 Electromagnetic Elektromagnetisch Compton wavelength Compton-Wellenlänge Astronomy Astronomie ConstantsWidget Domain Bereich Subdomain Unterbereich No match found Keine Übereinstimmung Name Name Value Wert Unit Einheit Search Suche All Alle CustomKeypadDialog Custom Keypad Benutzerdefiniertes Tastenfeld Rows: Zeilen: Columns: Spalten: Copy preset: Voreinstellung kopieren: Basic Einfach Scientific (wide) Wissenschaftlich (breit) Scientific (narrow) Wissenschaftlich (schmal) Apply Anwenden Row Zeile Column Spalte Label Beschriftung Behavior Verhalten Text Text DiagnosticsDialog App Diagnostics Anwendungsdiagnose Copy to Clipboard In die Zwischenablage kopieren Editor Unit Einheit User unit Benutzereinheit User function Benutzerdefinierte Funktion Argument Argument Current result:<br/>%1 Aktuelles Ergebnis:<br/>%1 Selection result:<br/>%1 Auswahlergebnis:<br/>%1 Selection result: n/a Ergebnis der Auswahl: nicht verfügbar Selection result: %1 Ergebnis der Auswahl: %1 second Sekunde metre Meter kilogram Kilogramm mole Mol radian Radiant steradian Steradiant degree Celsius Grad Celsius cubic metre Kubikmeter cubic millimetre Kubikmillimeter cubic centimetre Kubikzentimeter cubic decimetre Kubikdezimeter cubic kilometre Kubikkilometer square millimetre Quadratmillimeter square kilometre Quadratkilometer square metre Quadratmeter minute Minute hour Stunde day Tag astronomical unit Astronomische Einheit degree Grad arcminute Bogenminute arcsecond Bogensekunde milliarcsecond Millibogensekunde microarcsecond Mikrobogensekunde hectare Hektar litre Liter tonne Tonne Dalton Dalton electronvolt Elektronenvolt Angstrom Ångström atmosphere Atmosphäre atomic mass unit atomare Masseneinheit British thermal unit Britische Wärmeeinheit calorie Kalorie carat Karat cup Tasse cup (Imperial) Tasse (Imperial) cup (Japanese) Tasse (japanisch) cup (US) Tasse (US) degree Fahrenheit Grad Fahrenheit fathom Faden fluid ounce (Imperial) Flüssigunze (Imperial) fluid ounce (US) Flüssigunze (US) fluid dram (Imperial) Flüssigdrachme (Imperial) fluid dram (US) Flüssigdrachme (US) foot Fuß square foot Quadratfuß cubic foot Kubikfuß gallon (Imperial) Gallone (Imperial) gallon (US) Gallone (US) gill (Imperial) Gill (Imperial) gill (US) Gill (US) gradian Gon grain Grain gram Gramm Hartley Hartley Hartree energy unit Hartree-Energieeinheit horsepower Pferdestärke inch Zoll square inch Quadratzoll cubic inch Kubikzoll karat Karat knot Knoten lightminute Lichtminute lightsecond Lichtsekunde lightyear Lichtjahr long ton Long ton mile Meile square mile Quadratmeile cubic mile Kubikmeile mile per hour Meilen pro Stunde kilometre per hour Kilometer pro Stunde nautical mile Seemeile ounce Unze parsec Parsec pint (Imperial) Pint (Imperial) pint (US) Pint (US) pound Pfund pounds per square inch Pfund pro Quadratzoll quart (Imperial) Quart (Imperial) quart (US) Quart (US) oil barrel Ölfass beer barrel (US) Bierfass (US) square yard Quadratyard cubic yard Kubikyard short ton Short ton tablespoon Esslöffel tablespoon (Australian) Esslöffel (australisch) tablespoon (Imperial) Esslöffel (Imperial) tablespoon (US) Esslöffel (US) dessert spoon Dessertlöffel teaspoon Teelöffel teaspoon (Imperial) Teelöffel (Imperial) teaspoon (US) Teelöffel (US) turn Umdrehung revolution Umdrehung revolution per minute Umdrehungen pro Minute week Woche kilowatt hour Kilowattstunde millimetre of mercury Millimeter Quecksilbersäule yard Yard Julian century Julianisches Jahrhundert Julian year Julianisches Jahr sidereal year Siderisches Jahr tropical year Tropisches Jahr Evaluator invalid expression ungültiger Ausdruck division by zero Division durch null too time consuming - computation was rejected zu aufwändig - Berechnung abgebrochen dimension mismatch - quantities with different dimensions cannot be compared, added, etc. Dimensionsfehler - Größen mit unterschiedlicher Dimension können z.B. nicht verglichen oder addiert werden. invalid dimension - operation might require dimensionless arguments Ungültige Dimension - die Operation benötigt möglicherweise dimensionslose Argumente. Computation aborted - encountered numerical instability Berechnung abgebrochen - numerische Instabilität entdeckt invalid dimension - function might require dimensionless arguments Ungültige Dimension - die Funktion benötigt möglicherweise dimensionslose Argumente. error Fehler unit must not be zero Einheit darf nicht gleich null sein Conversion failed - dimension mismatch Umwandlung fehlgeschlagen - Dimensionen passen nicht zusammen unknown function or variable Unbekannte Funktion oder Variable recursion not supported Rekursion nicht unterstützt cannot operate on a NaN Operation mit einer NaN nicht ausführbar underflow - tiny result is out of SpeedCrunch's number range Underflow - Ergebnis zu klein für SpeedCrunchs Darstellungsbereich overflow - huge result is out of SpeedCrunch's number range Overflow - Ergebnis zu groß für SpeedCrunchs Darstellungsbereich overflow - logic result exceeds maximum of 256 bits Overflow - Ergebnis einer logischen Operation hat mehr als 256 Bit overflow - integer result exceeds maximum limit for integers Overflow - ganzzahliges Ergebnis ist zu groß für Speedcrunch operation is not defined for these arguments Operation ist für diese Argumente nicht definiert wrong number of arguments falsche Anzahl von Argumenten does not take NaN as an argument NaN als Argument nicht erlaubt result out of range Ergebnis nicht im zulässigen Bereich undefined for argument domain für Argument undefiniert computation too expensive Berechnung wäre zu aufwändig internal error, please report a bug internes Problem, bitte Fehler melden syntax error Syntaxfehler conversion target must be a unit Umrechnungsziel muss eine Einheit sein unknown unit unbekannte Einheit %1 is a reserved name, please choose another %1 ist ein reservierter Bezeichner, bitte einen anderen wählen %1 is a global user definition and cannot be overridden in this session. %1 ist eine globale Benutzerdefinition und kann in dieser Sitzung nicht überschrieben werden. %1 is a variable name, please choose another or delete the variable %1 ist ein Name einer Variablen, bitte einen anderen auswählen oder die Variable löschen argument %1 is used more than once Argument %1 wird mehr als einmal verwendet %1 is a built-in unit name, please choose another %1 ist der Name einer eingebauten Einheit, bitte wählen Sie einen anderen %1 is a user function name, please choose another or delete the function %1 ist Name einer benutzerdefinierten Funktion, bitte einen anderen wählen oder die Funktion löschen FunctionRepo max; trials; probability Maximum; Versuche; Wahrscheinlichkeit trials; probability Versuche; Wahrscheinlichkeit hits; trials; probability Treffer; Versuche; Wahrscheinlichkeit max; total; hits; trials Maximum; Gesamt; Treffer; Versuche total; hits; trials Gesamt; Treffer; Versuche count; total; hits; trials Anzahl; Gesamt; Treffer; Versuche dividend; divisor Zähler; Nenner x; exponent_bits; significand_bits [; exponent_bias] x; Exponenten_Bits; signifikante_Bits [; Exponenten_Bias] base; x Basis; x value; modulo Wert; Modulo base; exponent; modulo Basis; Exponent; Modulo events; average_events Ereignisse; Durchschnittsereignisse average_events Durchschnittsereignisse x [; precision] x [; Genauigkeit] Absolute Value Betrag Absolute Deviation Absolutabweichung Arc Cosine Arkuskosinus Logical AND Logisches UND Area Hyperbolic Cosine Areakosinus Hyberbolicus Area Hyperbolic Sine Areasins Hyberbolicus Area Hyperbolic Tangent Areatangens Hyberbolicus Arc Sine Arkussinus Arc Tangent Arkustangens Arc Tangent with two Arguments Arkustangens mit zwei Argumenten Average (Arithmetic Mean) Durchschnitt (Arithmetisches Mittel) Binomial Cumulative Distribution Function Binomialverteilung Binomial Distribution Mean Erwartungswert der Binomialverteilung Binomial Probability Mass Function Wahrscheinlichkeitsfunktion der Binomialverteilung Binomial Distribution Variance Varianz der Binomialverteilung Cube Root Kubikwurzel Complex Conjugate Komplexe Konjugation Cosine Kosinus Hyperbolic Cosine Kosinus Hyberbolicus Cotangent Kotangens Cosecant Kosekans Convert Unix timestamp to Date Unix-Zeitstempel in Datum umwandeln Degrees of Arc Bogenmaß zu Gradmaß Error Function Fehlerfunktion Complementary Error Function Komplementäre Fehlerfunktion Exponential Exponentialfunktion Fractional Part Nachkommastellen Extension of Factorials [= (x-1)!] Eulersche Gammafunktion [= (x-1)!] Greatest Common Divisor Größter gemeinsamer Teiler Geometric Mean Geometrisches Mittel Gradians of arc Gradienten des Bogens Hypergeometric Cumulative Distribution Function Hypergeometrische Verteilung Hypergeometric Distribution Mean Erwartungswert der Hypergeometrischen Verteilung Hypergeometric Probability Mass Function Wahrscheinlichkeitsfunktion der Hypergeometrischen Verteilung Hypergeometric Distribution Variance Varianz der hypergeometrischen Verteilung Integer Quotient Ganzzahliger Quotient Integer Part Ganzzahliger Anteil Imaginary Part Imaginärteil Decode IEEE-754 Binary Value IEEE-754 Binärwert dekodieren Encode IEEE-754 Binary Value IEEE-754 Binärwert kodieren Decode 16-bit Half-Precision Value 16-Bit half-precision Wert dekodieren Encode 16-bit Half-Precision Value 16-Bit half-precision Wert kodieren Decode 32-bit Single-Precision Value 32-Bit single-precision Wert dekodieren Encode 32-bit Single-Precision Value 32-Bit single-precision Wert kodieren Decode 64-bit Double-Precision Value 64-Bit double-precision Wert dekodieren Encode 64-bit Double-Precision Value 64-Bit double-precision Wert kodieren Decode 128-bit Quad-Precision Value 128-Bit quad-precision Wert dekodieren Encode 128-bit Quad-Precision Value 128-Bit quad-precision Wert kodieren Binary Logarithm Logarithmus zur Basis 2 Common Logarithm Logarithmus zur Basis 10 Natural Logarithm Natürlicher Logarithmus Logarithm to Arbitrary Base Logarithmus zu beliebiger Basis Mask to a bit size Auf Anzahl von Bits einschränken Maximum Maximum Median Value (50th Percentile) Median (50-Perzentil) Minimum Minimum Modulo Modulo Euclidean Modulo Euklidisches Modulo Modular Exponentiation Modulare Exponentiation Combination (Binomial Coefficient) Kombination (Binomialkoeffizient) Logical NOT Logisches NICHT Permutation (Arrangement) Permutation (Anordnung) Convert to Binary Representation In binäre Darstellung umwandeln Arithmetic Arithmetik Chemistry Chemie Complex Komplex Combinatorics Kombinatorik Probability Wahrscheinlichkeit Statistics Statistik Aggregation Aggregation Random Zufall Base conversion Basisumrechnung Number formatting Zahlenformatierung Integer arithmetic Ganzzahlarithmetik Special functions Spezielle Funktionen Exponential & Logarithmic Exponential & Logarithmisch Angle conversion Winkelumrechnung Trigonometry Trigonometrie Bitwise Bitweise Floating point Gleitkomma Date & Time Datum & Uhrzeit Linear algebra Lineare Algebra unix_timestamp; x hours offset to GMT unix_timestamp; x Stunden zur GMT versetzt yyyymmdd.hhmmss; x hours offset to GMT jjjjmmtt.hhmmss; x Stunden Versatz zu GMT [digits] [Ziffern] max [; min] Maximum [; Minimum] List Literal Listenliteral Convert to Padded Binary Representation In aufgefüllte Binärdarstellung umwandeln Round Toward +∞ (Ceiling) Gegen +∞ runden (Aufrunden) Cosine plus Imaginary Sine Kosinus plus imaginärer Sinus Convert to Cis Complex Form In Cis-Komplexform umwandeln Matrix Column Count Matrix-Spaltenanzahl Population Correlation Matrix (n) Korrelationsmatrix der Grundgesamtheit (n) Sample Correlation Matrix (n-1) Stichproben-Korrelationsmatrix (n-1) Count Anzahl Population Covariance Matrix (n) Kovarianzmatrix der Grundgesamtheit (n) Sample Covariance Matrix (n-1) Stichproben-Kovarianzmatrix (n-1) Cross Product Kreuzprodukt Convert Date to Unix timestamp Datum in Unix-Zeitstempel umwandeln Convert to Decimal Representation In dezimale Darstellung umwandeln Determinant Determinante Convert to Sexagesimal Notation In Sexagesimalnotation umwandeln Dot Product Skalarprodukt Convert to Engineering Notation In technische Notation umwandeln Convert to Exponential Complex Form In exponentielle Komplexform umwandeln Round Toward −∞ (Floor) Gegen −∞ runden (Abrunden) Flatten Matrix Matrix abflachen Least Common Multiple Kleinstes gemeinsames Vielfaches Convert to Hexadecimal Representation In hexadezimale Darstellung umwandeln Convert to Padded Hexadecimal Representation In aufgefüllte Hexadezimaldarstellung umwandeln Inverse Matrix Inverse Matrix Round to 16-bit Half-Precision Value Auf 16-Bit-Halbpräzisionswert runden Round to 32-bit Single-Precision Value Auf 32-Bit-Einfachpräzisionswert runden Round to 64-bit Double-Precision Value Auf 64-Bit-Doppelpräzisionswert runden Round to 128-bit Quad-Precision Value Auf 128-Bit-Vierfachpräzisionswert runden Residual from 16-bit Half-Precision Rounding Residuum der 16-Bit-Halbpräzisionsrundung Residual from 32-bit Single-Precision Rounding Residuum der 32-Bit-Einfachpräzisionsrundung Residual from 64-bit Double-Precision Rounding Residuum der 64-Bit-Doppelpräzisionsrundung Residual from 128-bit Quad-Precision Rounding Residuum der 128-Bit-Vierfachpräzisionsrundung Substance Mass Stoffmasse Molarity Molarität Molar Mass Molare Masse Median Absolute Deviation Median der absoluten Abweichungen Mean Mittelwert Numerical Value of Quantity Zahlenwert einer Größe Random Decimal Number Zufällige Dezimalzahl Random Integer Number Zufällige Ganzzahl Convert to Rational Representation In rationale Darstellung umwandeln Convert to Octal Representation In oktale Darstellung umwandeln Convert to Padded Octal Representation In aufgefüllte Oktaldarstellung umwandeln Vector or Matrix Norm Vektor- oder Matrixnorm Logical OR Logisches ODER Population Count (Hamming Weight) Populationsanzahl (Hamming-Gewicht) Phase of Complex Number Phase der komplexen Zahl Poissonian Cumulative Distribution Function Poission-Verteilung Poissonian Distribution Mean Erwartungswert der Poisson-Verteilung Poissonian Probability Mass Function Wahrscheinlichkeitsfunktion der Poisson-Verteilung Poissonian Distribution Variance Varianz der Poisson-Verteilung Convert to Phasor Complex Form In Zeiger-Komplexform umwandeln Convert to Rectangular Complex Form In kartesische Komplexform umwandeln Round Half Away from Zero Hälften weg von Null runden Round Half Even Hälften gerade runden Nth Root N-te Wurzel Convert to Scientific Notation In wissenschaftliche Notation umwandeln Matrix Row Count Matrix-Zeilenanzahl List or Matrix Shape Listen- oder Matrixform Summation Summierung Population Standard Deviation (n) Standardabweichung der Grundgesamtheit (n) Sample Standard Deviation (n-1) Stichproben-Standardabweichung (n-1) Round Toward Zero (Truncation) Gegen Null runden (Abschneiden) Matrix Trace Matrixspur Transpose Matrix Matrix transponieren Population Variance (n) Varianz der Grundgesamtheit (n) Sample Variance (n-1) Stichprobenvarianz (n-1) Product Produkt Radians Gradmaß zu Bogenmaß Matrix Rank Matrixrang Real Part Realteil Secant Sekans Arithmetic Shift Left Arithmetisches Verschieben nach links Arithmetic Shift Right Arithmetisches Verschieben nach rechts Signum Vorzeichen Sine Sinu Hyperbolic Sine Sinus Hyperbolicus Square Root Quadratwurzel Sum Summ Tangent Tangens Convert to Trigonometric Complex Form In trigonometrische Komplexform umwandeln Turns Umdrehungen Hyperbolic Tangent Tangens Hyperbolicus Sign-extend a value Vorzeichenerweiterung eines Wertes Logical XOR Logisches XOR FunctionsWidget Domain Bereich All Alle Name Name Search Suchen No match found Keine Übereinstimmung Identifier Bezeichner HistoryWidget Remove All Calculations Above Alle Berechnungen darüber entfernen Remove This Calculation Diese Berechnung entfernen Remove All Calculations Below Alle Berechnungen darunter entfernen Keypad Inverse cosine Inverser Kosinus The last result Letztes Ergebnis Inverse sine Inverser Sinus Inverse tangent Inverser Tangens Evaluate expression Ausdruck auswerten Division Division Multiplication Multiplikation Subtraction Subtraktion Addition Addition Clear expression Ausdruck löschen Cosine Kosinus Backspace Rücktaste Scientific notation Wissenschaftliche Darstellung Exponential Exponentialfunktion Factorial Fakultät Natural logarithm Natürlicher Logarithmus Left parenthesis Linke Klammer Nth root N-te Wurzel Argument separator Argumenttrennzeichen Square Quadrat Common logarithm Dekadischer Logarithmus Modulo Modulo Contextual percentage Kontextbezogener Prozentsatz Power Potenz Right parenthesis Rechte Klammer Sine Sinus Square root Quadratwurzel Tangent Tangens Pi Pi Decimal separator Dezimaltrennzeichen MainWindow Radian Bogenmaß Degree Grad Gradian Gon Binary Binär Octal Oktal Hexadecimal Hexadezimal Sexagesimal Sechzigersystem Engineering decimal Ingenieursformat dezimal Scientific decimal Wissenschaftlich dezimal &Import... &Importieren ... &Quit &Beenden Clear E&xpression &Ausdruck löschen Clear &History Verlau&f löschen &Copy &Kopieren &Paste &Einfügen &Select Expression Ausdruck &markieren &Constants &Konstanten &Functions &Funktionen &History &Verlauf &Status Bar &Statusleiste Bitfield Bit-Feld Use&r Functions Benutze&rdefinierte Funktionen &Degree &Grad &Radian &Bogenmaß &Gradian &Gon Re&volution U&mdrehung Auto-Insert a&ns a&ns automatisch einfügen Automatic &Completion Auto&matische Vervollständigung &Built-in Functions &Integrierte Funktionen Built-in &Variables Integrierte &Variablen User &Functions Benutzerde&finierte Funktionen User Va&riables Benutze&rvariablen Open a Private Tab on Startup Beim Start einen privaten Tab öffnen Open and focus a new private tab whenever SpeedCrunch starts. Bei jedem Start von SpeedCrunch einen neuen privaten Tab öffnen und aktivieren. Syntax &Highlighting Synta&xauszeichnung Group Digits in &Input E&ingabeziffern gruppieren Automatic Input &Adjustments &Automatische Eingabeanpassungen Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Operatoren, Abstände, Klammern und Potenzen automatisch anpassen und die Eingabe auf gültige Zeichen beschränken. Group input digits using the selected number format. Eingabeziffern nach dem gewählten Zahlenformat gruppieren. &Blinking Cursor &Blinkender Cursor Blink the cursor in the expression editor. Den Cursor im Ausdruckseditor blinken lassen. &Escape Clears Editor &Escape leert den Editor Clear the focused expression editor with Escape after dismissing any popup or preview. Den aktiven Ausdruckseditor mit Escape leeren, nachdem alle Einblendungen oder Vorschauen geschlossen wurden. Keep Expression After Evaluation Ausdruck nach der Berechnung beibehalten Copy New Results Automatically Neue Ergebnisse automatisch kopieren &Comma K&omma &System Default S&ystemeinstellungen &Dot &Punkt Dot &And Comma Punkt &und Komma Toward +∞ (&ceil) Ri&chtung +∞ (ceil) Toward −∞ (&floor) Richtung −∞ (&floor) &Binary &Binär &Engineering &Ingenieurformat &Hexadecimal &Hexadezimal &Octal &Oktal &Scientific &Wissenschaftlich User &Manual Benutzer&handbuch Issues and &Feedback &Probleme und Rückmeldungen &Donate &Spenden &About SpeedCrunch &Über SpeedCrunch App Diag&nostics A&nwendungsdiagnose S&plit Te&ilen Angle &Mode Winkel&modus &Complex Form &Komplexe Darstellung New Tab Neuer Tab Constants Konstanten Functions Funktionen History Verlauf User Functions Benutzerdefinierte Funktionen &Font... &Schriftart... &Language... &Sprache ... &Session &Sitzung &Edit &Bearbeiten &View &Ansicht Se&ttings &Einstellungen &Decimal &Dezimal &Keypad &Tastenfeld Always on &Top Immer im &Vordergrund Disabled Deaktiviert Small Space Kleiner Zwischenraum Medium Space Mittlerer Zwischenraum Large Space Großer Zwischenraum &0 Digits &0 Stellen &15 Digits &15 Stellen &2 Digits &2 Stellen &3 Digits &3 Stellen &50 Digits &50 Stellen &8 Digits &8 Stellen &Sexagesimal &Sechzigersystem Reset All Settings... Alle Einstellungen zurücksetzen... &System &System SpeedCrunch &Theme S&peedCrunch-Design &Classic Klassis&ch &Modern &Modern Context Help Kontext-Hilfe &Help &Hilfe Error Fehler Can't read from file %1 Kann Datei %1 nicht lesen Import Session Sitzung importieren Close Session Sitzung schließen Angle Mode: Winkelmodus: Notation: Notation: Precision: Genauigkeit: Turn Umdrehung Revolution Umdrehung Fixed-point decimal Festkommadezimal Rational Rational Automatic decimal Automatische Dezimaldarstellung Automatic Automatisch User &Definitions... Benutzer&definitionen... New &Tab Neuer &Tab New &Private Tab Neuer &privater Tab Keep Behalten Make Private... Privat machen... New &Window Neues &Fenster &Open... &Öffnen ... &Rename... &Umbenennen... Clo&ne... Klo&nen... &Close Tab Tab s&chließen Reopen Clo&sed Tab Ge&schlossenen Tab wieder öffnen Open Sessions &Folder Sitzungs&ordner öffnen &Undo &Rückgängig &Redo &Wiederherstellen Cu&t A&usschneiden Copy &Last Result &Letztes Ergebnis kopieren &Wrap in Parentheses &In Klammern setzen Full Scr&een Mode V&ollbildmodus &Basic &Einfach &Scientific (wide) &Wissenschaftlich (breit) Scientific (narrow) Wissenschaftlich (schmal) &Custom... &Benutzerdefiniert... Main &Menu Haupt&menü User &Variables Benutzer&variablen &Left &Links &Right &Rechts &Up &Oben &Down &Unten Close Pa&ne Bereich schließe&n User &Units Benutzer&einheiten &Turn &Umdrehung If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Wenn ein neuer Ausdruck mit +, -, * oder / beginnt, fügt SpeedCrunch zuerst "ans" ein. &Accept with Enter &Mit Enter übernehmen Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Den aktuellen Autovervollständigungsvorschlag mit Enter übernehmen, ohne ihn zuvor mit den Pfeiltasten auszuwählen. &Units &Einheiten Show Live Result &Preview Live-Ergebnis&vorschau anzeigen Save &Window Position on Exit &Fensterposition beim Beenden speichern Hover Highlighting Hervorhebung beim Darüberfahren Group Integer Part Only Nur Ganzzahlteil gruppieren Number Format... Zahlenformat... Notation && Precision... Notation && Genauigkeit... After pressing Enter, keep the entered expression selected in the editor. Nach dem Drücken der Eingabetaste den eingegebenen Ausdruck im Editor ausgewählt lassen. Never Nie Always Immer Only for Single-Line Expressions Nur für einzeilige Ausdrücke Simplify Displayed Expressions Angezeigte Ausdrücke vereinfachen History Size &Limit... &Begrenzung der Verlaufsgröße... Remove Trailing &Zeroes &Nachgestellte Nullen entfernen Nearest, Half &Away (round) Nächstliegend, Hälfte &weg (round) Nearest, Half &Even (roundeven) Nächstliegend, Hälfte &gerade (roundeven) Toward &Zero (trunc) Gegen &Null (trunc) &Fixed-Point &Festkomma &Rational &Rational &Exponential (m·s�¹) &Exponentiell (m·s�¹) &Fractional (m/s) &Bruchschreibweise (m/s) &Rectangular (a + bi) &Kartesisch (a + bi) Exponential (re�ᶿ) Exponentiell (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonometrisch (r(cos θ + i·sin θ)) Phasor (r∠θ) Zeiger (r∠θ) &Theme... &Design... Check for &Updates Nach &Aktualisierungen suchen Source Code Quellcode &Zoom &Zoom &Results &Ergebnisse Unit Notation Einheitennotation Rounding Mode Rundungsmodus &Notation &Notation &Imaginary Unit &Imaginäre Einheit &Window &Fenster &Editing &Bearbeiten A&utocomplete A&utovervollständigung Up/Down Arrow History Verlauf mit Pfeil auf/ab &Appearance &Darstellung &Menus &Menüs &Docks &Andockfenster &Input and Results E&ingabe und Ergebnisse &Disabled &Deaktiviert &Disable &Deaktivieren Close preview Vorschau schließen Rename... Umbenennen... Clone... Klonen... Close Tab Tab schließen New Private Tab Neuer privater Tab Open... Öffnen ... Reopen Closed Tab Geschlossenen Tab wieder öffnen Split Teilen Left Links Right Rechts Up Oben Down Unten Clear Leeren Delete Löschen %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Private Sitzung: Der Inhalt wird beim Schließen verworfen. Wählen Sie Sitzung > Behalten, um sie in eine reguläre Sitzung umzuwandeln. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privat] Reset All Settings Alle Einstellungen zurücksetzen Reset all settings to their default values? Alle Einstellungen auf ihre Standardwerte zurücksetzen? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Dies umfasst Darstellung, Bearbeitung, Ergebnisformate und Fenstereinstellungen. Ihre Berechnungen, offenen Sitzungen und benutzerdefinierten Definitionen bleiben erhalten. The settings file could not be written. Die Einstellungsdatei konnte nicht geschrieben werden. Clear this session's calculations, unfinished expression, variables, functions, and units? Berechnungen, unfertigen Ausdruck, Variablen, Funktionen und Einheiten dieser Sitzung löschen? Global user definitions are kept. Globale benutzerdefinierte Definitionen bleiben erhalten. Make Session Private Sitzung privat machen The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Die gespeicherte Sitzung %1 wird gelöscht. Ihr Inhalt bleibt in einer privaten Sitzung geöffnet und wird verworfen, wenn diese Sitzung oder SpeedCrunch geschlossen wird. Make Private Privat machen Could not delete the saved session %1. Die gespeicherte Sitzung %1 konnte nicht gelöscht werden. Keep Session Sitzung behalten Could not save the session. It remains private. Die Sitzung konnte nicht gespeichert werden. Sie bleibt privat. Clone Session Sitzung klonen Could not save session file %1. Die Sitzungsdatei %1 konnte nicht gespeichert werden. Could not delete session file %1. Die Sitzungsdatei %1 konnte nicht gelöscht werden. JSON file (*.json);;Any file (*.*) JSON-Datei (*.json);;Alle Dateien (*.*) Export session as JSON Sitzung als JSON exportieren The selected file is not valid JSON: %1 Die ausgewählte Datei enthält kein gültiges JSON: %1 The selected file is not a SpeedCrunch session JSON file. Die ausgewählte Datei ist keine SpeedCrunch-Sitzungsdatei im JSON-Format. This file uses an obsolete SpeedCrunch session format and cannot be imported. Diese Datei verwendet ein veraltetes SpeedCrunch-Sitzungsformat und kann nicht importiert werden. The selected JSON file is missing the required $schema field. Der ausgewählten JSON-Datei fehlt das erforderliche Feld $schema. The selected JSON file uses an unsupported JSON schema: %1 Die ausgewählte JSON-Datei verwendet ein nicht unterstütztes JSON-Schema: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Der ausgewählten JSON-Datei fehlt der SpeedCrunch-Sitzungsschema-Bezeichner ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Die ausgewählte JSON-Datei verwendet ein nicht unterstütztes SpeedCrunch-Sitzungsformat: %1 The selected JSON file is missing the required session name. Der ausgewählten JSON-Datei fehlt der erforderliche Sitzungsname. The selected JSON file has an empty session name. Die ausgewählte JSON-Datei enthält einen leeren Sitzungsnamen. The selected JSON file has invalid or incomplete SpeedCrunch session data. Die ausgewählte JSON-Datei enthält ungültige oder unvollständige SpeedCrunch-Sitzungsdaten. Open Sessions Folder Sitzungsordner öffnen Could not create the sessions folder: %1 Der Sitzungsordner konnte nicht erstellt werden: %1 Could not open the sessions folder: %1 Der Sitzungsordner konnte nicht geöffnet werden: %1 Editor and Results Font Schriftart für Editor und Ergebnisse Open Session Sitzung öffnen Community Gemeinschaft Rename Session Sitzung umbenennen Clear Session Sitzung leeren Delete Session Sitzung löschen Close Pane Bereich schließen User Variables Benutzervariablen User Units Benutzereinheiten Clear History Verlauf leeren Are you sure you want to clear the calculation history? Möchten Sie den Berechnungsverlauf wirklich leeren? Session name: Sitzungsname: A session named %1 already exists. Eine Sitzung mit dem Namen %1 ist bereits vorhanden. Could not create session file %1. Sitzungsdatei %1 konnte nicht erstellt werden. Could not write session file %1. Sitzungsdatei %1 konnte nicht geschrieben werden. Are you sure you want to delete this session? Möchten Sie diese Sitzung wirklich löschen? Custom Precision Benutzerdefinierte Genauigkeit Fractional digits: Nachkommastellen: Theme Design Light Themes Helle Designs Dark Themes Dunkle Designs Preview Vorschau Colors Farben Select color for %1 Farbe für %1 auswählen Import... Importieren... Export... Exportieren... Import Theme Design importieren Theme file (*.json);;All files (*) Designdatei (*.json);;Alle Dateien (*) Invalid theme file. Ungültige Designdatei. Can't import theme "%1" because it conflicts with a built-in theme. Design "%1" kann nicht importiert werden, da es mit einem eingebauten Design kollidiert. Can't find a writable theme folder. Kein beschreibbarer Designordner gefunden. Overwrite Theme Design überschreiben A custom theme named "%1" already exists. Do you want to overwrite it? Ein benutzerdefiniertes Design namens "%1" ist bereits vorhanden. Möchten Sie es überschreiben? Can't overwrite theme file %1 Designdatei %1 kann nicht überschrieben werden Can't copy theme file to %1 Designdatei kann nicht nach %1 kopiert werden Export Theme Design exportieren Can't export theme as "%1" because it conflicts with a built-in theme. Design kann nicht als "%1" exportiert werden, da es mit einem eingebauten Design kollidiert. Can't write to file %1 Kann nicht in Datei %1 schreiben Global User Variable Globale Benutzervariable Global User Function Globale Benutzerfunktion Global User Unit Globale Benutzereinheit User Definitions Benutzerdefinitionen These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Diese Definitionen sind global und werden in jede Sitzung geladen. Sie können in den Sitzungen nicht geändert werden und haben Vorrang vor gleichnamigen Definitionen aus dem Sitzungseditor. Geben Sie eine Definition pro Zeile ein. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Beispiele: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Anwenden Validate Prüfen Test Results Testergebnisse Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Importierte Variablen: %1 Importierte Funktionen: %2 Importierte Einheiten: %3 Zeilennummern mit Fehlern: %4 none keine Apply Results Ergebnisse der Anwendung User definitions saved. Benutzerdefinitionen gespeichert. History Size Limit Begrenzung der Verlaufsgröße Maximum number of history entries for this session (0 = unlimited): Maximale Anzahl von Verlaufseinträgen für diese Sitzung (0 = unbegrenzt): Text file (*.txt);;Any file (*.*) Textdatei (*.txt);;Alle Dateien (*.*) Could not recalculate from calculation %1: %2 Ab Berechnung %1 konnte nicht neu berechnet werden: %2 History Size Limit Reached Begrenzung der Verlaufsgröße erreicht This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Diese Berechnung belegt den letzten verfügbaren Verlaufsplatz. Zukünftige Berechnungen entfernen die älteste Berechnung aus dem Verlauf. Sie können die Begrenzung unter Sitzung > Begrenzung der Verlaufsgröße erhöhen. Editing calculation. Press Esc twice to cancel. Berechnung wird bearbeitet. Drücken Sie Esc zweimal, um abzubrechen. Calculation Settings Berechnungseinstellungen Invalid recalculation start index Ungültiger Startindex für Neuberechnung System Default Systemeinstellungen Language Sprache Select the language: Sprache auswählen: Custom Benutzerdefiniert Decimal places: Dezimalstellen: &Automatic &Automatisch &Precision &Genauigkeit Plain &text Einfacher &Text Formula &Book Formel&sammlung &Export &Exportieren Export session as HTML Sitzung in HTML exportieren HTML file (*.html) HTML-Datei (*.html) Export session as plain text Sitzung als Text exportieren ManualWindow SpeedCrunch Manual SpeedCrunch-Handbuch %1 - SpeedCrunch Manual %1 - SpeedCrunch-Handbuch NumberFormatDialog Number Format Zahlenformat <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Wählen Sie das Zahlenformat für Ergebnisse und die Zifferngruppierung bei der Eingabe.</b><br/><br/>Hinweis: Bei eingegebenen Zahlen werden eindeutige Formate auch dann akzeptiert, wenn sie vom gewählten Anzeigeformat abweichen.<br/> QObject Global User Variable Globale Benutzervariable Global User Function Globale Benutzerfunktion Global User Unit Globale Benutzereinheit Backspace Rücktaste Clear expression Ausdruck löschen Evaluate expression Ausdruck auswerten Insert text Text einfügen Automatic decimal Automatische Dezimaldarstellung Fixed-point decimal Festkommadezimal Engineering decimal Technische Dezimaldarstellung Scientific decimal Wissenschaftliche Dezimaldarstellung Rational Rational Binary Binär Octal Oktal Hexadecimal Hexadezimal Sexagesimal Sechzigersystem Update Available Aktualisierung verfügbar A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Eine neuere Version (%1) ist verfügbar.<br/><a href="%2">Website zum Herunterladen besuchen.</a> Check for Updates Nach Aktualisierungen suchen SpeedCrunch %1 is up to date. SpeedCrunch %1 ist aktuell. No connectivity. Please check your internet connection and try again. Keine Verbindung. Bitte prüfen Sie Ihre Internetverbindung und versuchen Sie es erneut. Could not verify the latest available version. Die neueste verfügbare Version konnte nicht überprüft werden. ResultDisplay Scroll to bottom Zum Ende scrollen Edit Expression Ausdruck bearbeiten Change Settings Einstellungen ändern New Tab Neuer Tab &Import... &Importieren ... &Export &Exportieren Plain &text Einfacher &Text Copy Kopieren Selection Auswahl Select All Alles auswählen Expression Ausdruck Result Ergebnis Calculation Berechnung Calculation as Single Line Berechnung als einzelne Zeile Remove Entfernen This Calculation Diese Berechnung All Calculations Above Alle Berechnungen darüber All Calculations Below Alle Berechnungen darunter New Private Tab Neuer privater Tab Session Sitzung Open... Öffnen ... Clone... Klonen... Rename... Umbenennen... Keep Behalten Make Private... Privat machen... Clear Leeren Delete Löschen Close Schließen Split Teilen Left Links Right Rechts Up Oben Down Unten Close Pane Bereich schließen Main Menu Hauptmenü Cancel editing Bearbeitung abbrechen Copy result Ergebnis kopieren Edit expression Ausdruck bearbeiten Change settings Einstellungen ändern Remove calculation Berechnung entfernen ResultSlotsDialog Notation & Precision Notation & Genauigkeit Result Line Ergebniszeile Enabled Aktiviert Notation Notation Decimal Places Dezimalstellen Main Line Hauptzeile Extra Line #1 Zusatzzeile Nr. 1 Extra Line #2 Zusatzzeile Nr. 2 Extra Line #3 Zusatzzeile Nr. 3 Extra Line #4 Zusatzzeile Nr. 4 Auto Automatisch UserFunctionListWidget Name Name Value Wert Description Beschreibung Search Suchen No match found Keine Übereinstimmung gefunden Insert Einfügen Edit Bearbeiten Delete Löschen Delete All Alles löschen UserUnitListWidget Name Name Value Wert Description Beschreibung Search Suchen No match found Keine Übereinstimmung gefunden Insert Einfügen Edit Bearbeiten Delete Löschen Delete All Alle löschen VariableListWidget Name Name Value Wert Description Beschreibung Search Suchen No match found Keine Übereinstimmung Insert Einfügen Edit Bearbeiten Delete Löschen Delete All Alles löschen heldercorreia-speedcrunch-e7ca37f/src/resources/locale/el.ts000066400000000000000000011434331526573132500243560ustar00rootroot00000000000000 AboutBox About SpeedCrunch Σχετικά με το SpeedCrunch Core developers Κ��ιοι π�ογ�αμματιστές Original author Α�χικός συγγ�αφέας Close Κλείσιμο Math engine Μηχανή μαθηματικών Main author | Logo | Maintainer Κ��ιος δημιου�γός | Λογότυπο | Συντη�ητής Thanks Ευχα�ιστίες Copyright (C) 2004-2026 The SpeedCrunch developers Πνευματικά δικαιώματα (C) 2004-2026 Οι π�ογ�αμματιστές του SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Αυτό το π�όγ�αμμα είναι ελε�θε�ο λογισμικό. Μπο�είτε να το αναδιανείμετε ή/και να το τ�οποποιήσετε σ�μφωνα με τους ό�ους της Γενικής Άδειας Δημόσιας Χ�ήσης GNU, όπως δημοσιε�εται από το Free Software Foundation, είτε την έκδοση 2 της Άδειας είτε, κατ’ επιλογή σας, οποιαδήποτε μεταγενέστε�η έκδοση. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Αυτό το π�όγ�αμμα διανέμεται με την ελπίδα ότι θα είναι χ�ήσιμο, αλλά ΧΩΡΙΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ, χω�ίς καν τη σιωπη�ή εγγ�ηση ΕΜΠΟΡΕΥΣΙΜΟΤΗΤΑΣ ή ΚΑΤΑΛΛΗΛΟΤΗΤΑΣ ΓΙΑ ΣΥΓΚΕΚΡΙΜΕ�Ο ΣΚΟΠΟ. Δείτε τη Γενική Άδεια Δημόσιας Χ�ήσης GNU για πε�ισσότε�ες λεπτομέ�ειες. BitFieldWidget Reset bits to zero Επαναφο�ά bit στο μηδέν Invert bits Αντιστ�οφή bit Shift bits left Μετατόπιση bit α�ιστε�ά Shift bits right Μετατόπιση bit δεξιά Book Index Ευ�ετή�ιο Algebra Άλγεβ�α Quadratic Equation Δευτε�οβάθμια εξίσωση Logarithmic Base Conversion Μετατ�οπή λογα�ιθμικής βάσης Geometry Γεωμετ�ία Circle Κ�κλος Sector Τομέας Sphere Σφαί�α Cube Κ�βος Cone Κώνος Cylinder Κ�λινδ�ος Electronics Ηλεκτ�ονικά Ohm's Law �όμος του Ohm Power Ισχ�ς Reactance Άε�γη αντίσταση Resonance Συντονισμός Radio Frequency Ραδιοσυχνότητα Antennas Κε�αίες Characteristic Impedance (coax) Χα�ακτη�ιστική αντίσταση (ομοαξονικό) Velocity of Propagation (coax) Ταχ�τητα διάδοσης (ομοαξονικό) Standing Wave Ratio & Return Loss Λόγος στάσιμων κυμάτων & απώλεια επιστ�οφής Free Space Wavelength Μήκος κ�ματος στον ελε�θε�ο χώ�ο resistance αντίσταση voltage τάση current �ε�μα power ισχ�ς inductive reactance επαγωγική αντίσταση capacitive reactance χω�ητική αντίσταση inductance επαγωγή capacitance χω�ητικότητα frequency συχνότητα resonance frequency συχνότητα συντονισμο� area εμβαδόν perimeter πε�ίμετ�ος diameter διάμετ�ος radius ακτίνα volume όγκος surface area εμβαδόν επιφανείας height �ψος slant height κεκλιμένο �ψος face diagonal διαγώνιος έδ�ας space diagonal διαγώνιος χώ�ου edge length μήκος ακμής arc length μήκος τόξου central angle (degrees) κεντ�ική γωνία (μοί�ες) input power ισχ�ς εισόδου reflected power ανακλώμενη ισχ�ς transmitted power μεταδιδόμενη ισχ�ς return loss απώλεια επιστ�οφής dielectric constant διηλεκτ�ική σταθε�ά outer conductor's inner diameter εσωτε�ική διάμετ�ος του εξωτε�ικο� αγωγο� inner conductor's outer diameter εξωτε�ική διάμετ�ος του εσωτε�ικο� αγωγο� speed of light ταχ�τητα φωτός reflection coefficient συντελεστής ανάκλασης standing wave ratio λόγος στάσιμων κυμάτων normalized impedance κανονικοποιημένη αντίσταση frequency (Hz) συχνότητα (Hz) BookDock Formula Book Βιβλίο τ�πων ConstantCompletion Search constants Αναζήτηση σταθε�ών No match found Δεν β�έθηκε αντιστοιχία Constants Mathematics Μαθηματικά Physics (CODATA 2022) Φυσική (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Χημεία (IUPAC - CIAAW 2021) Uncategorized Χω�ίς κατηγο�ία Universal Οικουμενική Physicochemical Φυσικοχημικά Atomic & Nuclear — General Ατομικά & Πυ�ηνικά — Γενικά Atomic & Nuclear — Electroweak Ατομικά & Πυ�ηνικά — Ηλεκτ�ασθενή Atomic & Nuclear — Electron Ατομικά & Πυ�ηνικά — Ηλεκτ�όνιο Atomic & Nuclear — Muon Ατομικά & Πυ�ηνικά — Μιόνιο Atomic & Nuclear — Tau Ατομικά & Πυ�ηνικά — Ταυ Atomic & Nuclear — Proton Ατομικά & Πυ�ηνικά — Π�ωτόνιο Atomic & Nuclear — Neutron Ατομικά & Πυ�ηνικά — �ετ�όνιο Atomic & Nuclear — Deuteron Ατομικά & Πυ�ηνικά — Δευτε�όνιο Atomic & Nuclear — Triton Ατομικά & Πυ�ηνικά — Τ�ίτιο Atomic & Nuclear — Helion Ατομικά & Πυ�ηνικά — Ηλίον Atomic & Nuclear — Alpha particle Ατομικά & Πυ�ηνικά — Σωματίδιο άλφα Atomic & Nuclear — Atomic units Ατομικά & Πυ�ηνικά — Ατομικές μονάδες Atomic & Nuclear — Energy conversion relationships Ατομικά & Πυ�ηνικά — Σχέσεις μετατ�οπής ενέ�γειας Atomic & Nuclear — X-ray units Ατομικά & Πυ�ηνικά — Μονάδες ακτίνων Χ Atomic & Nuclear — Magnetic shielding corrections Ατομικά & Πυ�ηνικά — Διο�θώσεις μαγνητικής θω�άκισης Masses Μάζες Lifetimes Χ�όνοι ζωής Molar Masses Μο�ιακές μάζες Electronegativity Ηλεκτ�α�νητικότητα Ionization Energy Ενέ�γεια ιονισμο� Nominal Constants (IAU 2015) Ονομαστικές σταθε�ές (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Τ�έχουσες βέλτιστες εκτιμήσεις (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) χα�ακτη�ιστική αντίσταση του κενο� (Z₀) reduced Planck constant (�) ανηγμένη σταθε�ά του Planck (�) vacuum electric permittivity (ϵ₀) ηλεκτ�ική διαπε�ατότητα του κενο� (ϵ₀) Newtonian constant of gravitation (G) �ευτώνεια σταθε�ά της βα��τητας (G) vacuum magnetic permeability (μ₀) μαγνητική διαπε�ατότητα του κενο� (μ₀) Planck constant (h) σταθε�ά του Planck (h) speed of light in vacuum (c) ταχ�τητα του φωτός στο κενό (c) standard acceleration of gravity (gₙ) τυπική επιτάχυνση της βα��τητας (gₙ) Newtonian constant of gravitation over h-bar c �ευτώνεια σταθε�ά βα��τητας π�ος �c Planck length μήκος Planck Planck constant in eV/Hz (h) σταθε�ά του Planck σε eV/Hz (h) Planck mass μάζα Planck Planck mass energy equivalent in GeV ενε�γειακό ισοδ�ναμο μάζας Planck σε GeV Planck temperature θε�μοκ�ασία Planck Planck time χ�όνος Planck reduced Planck constant in eV·s (�) ανηγμένη σταθε�ά του Planck σε eV·s (�) reduced Planck constant times c in MeV·fm ανηγμένη σταθε�ά του Planck επί c σε MeV·fm Bohr magneton μαγνητόνη Bohr conductance quantum (G₀) κβάντο αγωγιμότητας (G₀) Coulomb constant (kₑ) σταθε�ά Coulomb (kₑ) elementary charge (e) στοιχειώδες φο�τίο (e) elementary charge over h-bar στοιχειώδες φο�τίο π�ος � conventional value of Josephson constant συμβατική τιμή της σταθε�άς Josephson Josephson constant σταθε�ά Josephson conventional value of ampere-90 συμβατική τιμή του αμπέ�-90 conventional value of coulomb-90 συμβατική τιμή του κουλόμπ-90 conventional value of farad-90 συμβατική τιμή του φα�άντ-90 conventional value of henry-90 συμβατική τιμή του χέν�ι-90 conventional value of ohm-90 συμβατική τιμή του ωμ-90 conventional value of volt-90 συμβατική τιμή του βολτ-90 conventional value of watt-90 συμβατική τιμή του βατ-90 magnetic flux quantum (Φ₀) κβάντο μαγνητικής �οής (Φ₀) nuclear magneton πυ�ηνική μαγνητόνη inverse of conductance quantum αντίστ�οφο του κβάντο αγωγιμότητας conventional value of von Klitzing constant συμβατική τιμή της σταθε�άς von Klitzing von Klitzing constant σταθε�ά von Klitzing atomic unit of magnetic dipole moment ατομική μονάδα μαγνητικής διπολικής �οπής atomic unit of magnetic flux density ατομική μονάδα πυκνότητας μαγνητικής �οής Bohr magneton in eV/T μαγνητόνη Bohr σε eV/T Bohr magneton in Hz/T μαγνητόνη Bohr σε Hz/T Bohr magneton in inverse meter per tesla μαγνητόνη Bohr σε αντίστ�οφο μέτ�ο ανά τέσλα Bohr magneton in K/T μαγνητόνη Bohr σε K/T nuclear magneton in eV/T πυ�ηνική μαγνητόνη σε eV/T nuclear magneton in inverse meter per tesla πυ�ηνική μαγνητόνη σε αντίστ�οφο μέτ�ο ανά τέσλα nuclear magneton in K/T πυ�ηνική μαγνητόνη σε K/T nuclear magneton in MHz/T πυ�ηνική μαγνητόνη σε MHz/T Bohr radius (a₀) ακτίνα Bohr (a₀) fine-structure constant (α) σταθε�ά λεπτής υφής (α) Hartree energy (Eₕ) ενέ�γεια Hartree (Eₕ) Hartree energy in eV ενέ�γεια Hartree σε eV quantum of circulation κβάντο κυκλοφο�ίας quantum of circulation times 2 διπλάσιο κβάντο κυκλοφο�ίας Rydberg constant (R∞) σταθε�ά Rydberg (R∞) atomic mass unit-hartree relationship σχέση μονάδας ατομικής μάζας-Hartree atomic mass unit-hertz relationship σχέση μονάδας ατομικής μάζας-χέ�τζ atomic mass unit-inverse meter relationship σχέση μονάδας ατομικής μάζας-αντίστ�οφου μέτ�ου atomic mass unit-joule relationship σχέση μονάδας ατομικής μάζας-τζάουλ atomic mass unit-kelvin relationship σχέση μονάδας ατομικής μάζας-κέλβιν atomic mass unit-kilogram relationship σχέση μονάδας ατομικής μάζας-χιλιογ�άμμου atomic unit of 1st hyperpolarizability ατομική μονάδα π�ώτης υπε�πολωσιμότητας atomic unit of 2nd hyperpolarizability ατομική μονάδα δε�τε�ης υπε�πολωσιμότητας atomic unit of charge (e) ατομική μονάδα φο�τίου (e) atomic unit of charge density ατομική μονάδα πυκνότητας φο�τίου atomic unit of current ατομική μονάδα �ε�ματος atomic unit of electric dipole moment ατομική μονάδα ηλεκτ�ικής διπολικής �οπής atomic unit of electric field ατομική μονάδα ηλεκτ�ικο� πεδίου atomic unit of electric field gradient ατομική μονάδα βαθμίδας ηλεκτ�ικο� πεδίου atomic unit of electric polarizability ατομική μονάδα ηλεκτ�ικής πολωσιμότητας atomic unit of electric potential ατομική μονάδα ηλεκτ�ικο� δυναμικο� atomic unit of electric quadrupole moment ατομική μονάδα ηλεκτ�ικής τετ�απολικής �οπής atomic unit of action ατομική μονάδα δ�άσης atomic unit of energy ατομική μονάδα ενέ�γειας atomic unit of force ατομική μονάδα δ�ναμης atomic unit of length ατομική μονάδα μήκους hertz-atomic mass unit relationship σχέση χέ�τζ-μονάδας ατομικής μάζας hertz-electron volt relationship σχέση χέ�τζ-ηλεκτ�ονιοβόλτ hertz-hartree relationship σχέση χέ�τζ-Hartree hertz-inverse meter relationship σχέση χέ�τζ-αντίστ�οφου μέτ�ου hertz-joule relationship σχέση χέ�τζ-τζάουλ hertz-kelvin relationship σχέση χέ�τζ-κέλβιν hertz-kilogram relationship σχέση χέ�τζ-χιλιογ�άμμου hyperfine transition frequency of Cs-133 συχνότητα υπέ�λεπτης μετάβασης του Cs-133 inverse fine-structure constant (α�¹) αντίστ�οφη σταθε�ά λεπτής υφής (α�¹) inverse meter-atomic mass unit relationship σχέση αντίστ�οφου μέτ�ου-μονάδας ατομικής μάζας inverse meter-electron volt relationship σχέση αντίστ�οφου μέτ�ου-ηλεκτ�ονιοβόλτ inverse meter-hartree relationship σχέση αντίστ�οφου μέτ�ου-Hartree inverse meter-hertz relationship σχέση αντίστ�οφου μέτ�ου-χέ�τζ inverse meter-joule relationship σχέση αντίστ�οφου μέτ�ου-τζάουλ inverse meter-kelvin relationship σχέση αντίστ�οφου μέτ�ου-κέλβιν inverse meter-kilogram relationship σχέση αντίστ�οφου μέτ�ου-χιλιογ�άμμου joule-atomic mass unit relationship σχέση τζάουλ-μονάδας ατομικής μάζας joule-electron volt relationship σχέση τζάουλ-ηλεκτ�ονιοβόλτ joule-hertz relationship σχέση τζάουλ-χέ�τζ joule-hartree relationship σχέση τζάουλ-Hartree joule-inverse meter relationship σχέση τζάουλ-αντίστ�οφου μέτ�ου joule-kelvin relationship σχέση τζάουλ-κέλβιν joule-kilogram relationship σχέση τζάουλ-χιλιογ�άμμου kelvin-atomic mass unit relationship σχέση κέλβιν-μονάδας ατομικής μάζας kelvin-electron volt relationship σχέση κέλβιν-ηλεκτ�ονιοβόλτ kelvin-hertz relationship σχέση κέλβιν-χέ�τζ kelvin-hartree relationship σχέση κέλβιν-Hartree kelvin-inverse meter relationship σχέση κέλβιν-αντίστ�οφου μέτ�ου kelvin-joule relationship σχέση κέλβιν-τζάουλ kelvin-kilogram relationship σχέση κέλβιν-χιλιογ�άμμου kilogram-atomic mass unit relationship σχέση χιλιογ�άμμου-μονάδας ατομικής μάζας kilogram-electron volt relationship σχέση χιλιογ�άμμου-ηλεκτ�ονιοβόλτ kilogram-hertz relationship σχέση χιλιογ�άμμου-χέ�τζ kilogram-hartree relationship σχέση χιλιογ�άμμου-Hartree kilogram-inverse meter relationship σχέση χιλιογ�άμμου-αντίστ�οφου μέτ�ου kilogram-joule relationship σχέση χιλιογ�άμμου-τζάουλ kilogram-kelvin relationship σχέση χιλιογ�άμμου-κέλβιν lattice parameter of silicon (a) πα�άμετ�ος πλέγματος του πυ�ιτίου (a) luminous efficacy φωτεινή απόδοση natural unit of energy φυσική μονάδα ενέ�γειας natural unit of energy in MeV φυσική μονάδα ενέ�γειας σε MeV natural unit of action (�) φυσική μονάδα δ�άσης (�) natural unit of action in eV·s φυσική μονάδα δ�άσης σε eV·s natural unit of length φυσική μονάδα μήκους natural unit of mass φυσική μονάδα μάζας natural unit of momentum φυσική μονάδα ο�μής natural unit of momentum in MeV/c φυσική μονάδα ο�μής σε MeV/c natural unit of time φυσική μονάδα χ�όνου natural unit of velocity φυσική μονάδα ταχ�τητας Rydberg constant times c in Hz σταθε�ά Rydberg επί c σε Hz Rydberg constant times hc in eV σταθε�ά Rydberg επί hc σε eV Rydberg constant times hc in J σταθε�ά Rydberg επί hc σε J Fermi coupling constant σταθε�ά σ�ζευξης Fermi weak mixing angle γωνία ασθενο�ς μίξης W to Z mass ratio λόγος μάζας W π�ος Z Thomson cross section (σₑ) ενε�γός διατομή Thomson (σₑ) electron mass (mₑ) μάζα ηλεκτ�ονίου (mₑ) electron mass in u μάζα ηλεκτ�ονίου σε u electron mass energy equivalent (mₑ·c²) ενε�γειακό ισοδ�ναμο μάζας ηλεκτ�ονίου (mₑ·c²) electron mass energy equivalent in MeV ενε�γειακό ισοδ�ναμο μάζας ηλεκτ�ονίου σε MeV reduced Compton wavelength ανηγμένο μήκος κ�ματος Compton classical electron radius (rₑ) κλασική ακτίνα ηλεκτ�ονίου (rₑ) electron charge to mass quotient πηλίκο φο�τίου π�ος μάζα ηλεκτ�ονίου electron-deuteron magnetic moment ratio λόγος μαγνητικής �οπής ηλεκτ�ονίου π�ος δευτε�όνιο electron-deuteron mass ratio λόγος μάζας ηλεκτ�ονίου π�ος δευτε�όνιο electron g factor (gₑ) πα�άγοντας g ηλεκτ�ονίου (gₑ) electron gyromagnetic ratio (γₑ) γυ�ομαγνητικός λόγος ηλεκτ�ονίου (γₑ) electron gyromagnetic ratio in MHz/T γυ�ομαγνητικός λόγος ηλεκτ�ονίου σε MHz/T electron-helion mass ratio λόγος μάζας ηλεκτ�ονίου π�ος ηλίον electron magnetic moment (μₑ) μαγνητική �οπή ηλεκτ�ονίου (μₑ) electron magnetic moment anomaly (aₑ) ανωμαλία μαγνητικής �οπής ηλεκτ�ονίου (aₑ) electron magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής ηλεκτ�ονίου π�ος μαγνητόνη Bohr electron magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής ηλεκτ�ονίου π�ος πυ�ηνική μαγνητόνη electron molar mass (Mₑ) μο�ιακή μάζα ηλεκτ�ονίου (Mₑ) electron-muon magnetic moment ratio λόγος μαγνητικής �οπής ηλεκτ�ονίου π�ος μιόνιο electron-muon mass ratio λόγος μάζας ηλεκτ�ονίου π�ος μιόνιο electron-neutron magnetic moment ratio λόγος μαγνητικής �οπής ηλεκτ�ονίου π�ος νετ�όνιο electron-neutron mass ratio λόγος μάζας ηλεκτ�ονίου π�ος νετ�όνιο electron-proton magnetic moment ratio λόγος μαγνητικής �οπής ηλεκτ�ονίου π�ος π�ωτόνιο electron-proton mass ratio λόγος μάζας ηλεκτ�ονίου π�ος π�ωτόνιο electron relative atomic mass (Ar(e)) σχετική ατομική μάζα ηλεκτ�ονίου (Ar(e)) electron-tau mass ratio λόγος μάζας ηλεκτ�ονίου π�ος ταυ electron to alpha particle mass ratio λόγος μάζας ηλεκτ�ονίου π�ος σωματίδιο άλφα electron to shielded helion magnetic moment ratio λόγος μαγνητικής �οπής ηλεκτ�ονίου π�ος θω�ακισμένο ηλίον electron to shielded proton magnetic moment ratio λόγος μαγνητικής �οπής ηλεκτ�ονίου π�ος θω�ακισμένο π�ωτόνιο electron-triton mass ratio λόγος μάζας ηλεκτ�ονίου π�ος τ�ίτιο electron volt-atomic mass unit relationship σχέση ηλεκτ�ονιοβόλτ-μονάδας ατομικής μάζας electron volt-hartree relationship σχέση ηλεκτ�ονιοβόλτ-Hartree electron volt-hertz relationship σχέση ηλεκτ�ονιοβόλτ-χέ�τζ electron volt-inverse meter relationship σχέση ηλεκτ�ονιοβόλτ-αντίστ�οφου μέτ�ου electron volt-joule relationship σχέση ηλεκτ�ονιοβόλτ-τζάουλ electron volt-kelvin relationship σχέση ηλεκτ�ονιοβόλτ-κέλβιν electron volt-kilogram relationship σχέση ηλεκτ�ονιοβόλτ-χιλιογ�άμμου hartree-atomic mass unit relationship σχέση Hartree-μονάδας ατομικής μάζας hartree-electron volt relationship σχέση Hartree-ηλεκτ�ονιοβόλτ muon Compton wavelength μήκος κ�ματος Compton μιονίου muon-electron mass ratio λόγος μάζας μιονίου π�ος ηλεκτ�όνιο muon g factor πα�άγοντας g μιονίου muon magnetic moment μαγνητική �οπή μιονίου muon magnetic moment anomaly ανωμαλία μαγνητικής �οπής μιονίου muon magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής μιονίου π�ος μαγνητόνη Bohr muon magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής μιονίου π�ος πυ�ηνική μαγνητόνη muon mass μάζα μιονίου muon mass energy equivalent ενε�γειακό ισοδ�ναμο μάζας μιονίου muon mass energy equivalent in MeV ενε�γειακό ισοδ�ναμο μάζας μιονίου σε MeV muon mass in u μάζα μιονίου σε u muon molar mass μο�ιακή μάζα μιονίου muon-neutron mass ratio λόγος μάζας μιονίου π�ος νετ�όνιο muon-proton magnetic moment ratio λόγος μαγνητικής �οπής μιονίου π�ος π�ωτόνιο muon-proton mass ratio λόγος μάζας μιονίου π�ος π�ωτόνιο muon-tau mass ratio λόγος μάζας μιονίου π�ος ταυ reduced muon Compton wavelength ανηγμένο μήκος κ�ματος Compton μιονίου reduced tau Compton wavelength ανηγμένο μήκος κ�ματος Compton ταυ tau Compton wavelength μήκος κ�ματος Compton ταυ tau-electron mass ratio λόγος μάζας ταυ π�ος ηλεκτ�όνιο tau mass μάζα ταυ tau mass energy equivalent ενε�γειακό ισοδ�ναμο μάζας ταυ tau mass in u μάζα ταυ σε u tau molar mass μο�ιακή μάζα ταυ tau-muon mass ratio λόγος μάζας ταυ π�ος μιόνιο tau-neutron mass ratio λόγος μάζας ταυ π�ος νετ�όνιο tau-proton mass ratio λόγος μάζας ταυ π�ος π�ωτόνιο proton charge to mass quotient πηλίκο φο�τίου π�ος μάζα π�ωτονίου proton Compton wavelength μήκος κ�ματος Compton π�ωτονίου proton-electron mass ratio λόγος μάζας π�ωτονίου π�ος ηλεκτ�όνιο proton g factor (gₚ) πα�άγοντας g π�ωτονίου (gₚ) proton gyromagnetic ratio (γₚ) γυ�ομαγνητικός λόγος π�ωτονίου (γₚ) proton gyromagnetic ratio in MHz/T γυ�ομαγνητικός λόγος π�ωτονίου σε MHz/T proton magnetic moment (μₚ) μαγνητική �οπή π�ωτονίου (μₚ) proton magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής π�ωτονίου π�ος μαγνητόνη Bohr proton magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής π�ωτονίου π�ος πυ�ηνική μαγνητόνη proton magnetic shielding correction διό�θωση μαγνητικής θω�άκισης π�ωτονίου proton mass (mₚ) μάζα π�ωτονίου (mₚ) proton mass energy equivalent ενε�γειακό ισοδ�ναμο μάζας π�ωτονίου proton mass energy equivalent in MeV ενε�γειακό ισοδ�ναμο μάζας π�ωτονίου σε MeV proton mass in u μάζα π�ωτονίου σε u proton molar mass (Mₚ) μο�ιακή μάζα π�ωτονίου (Mₚ) proton-muon mass ratio λόγος μάζας π�ωτονίου π�ος μιόνιο proton-neutron magnetic moment ratio λόγος μαγνητικής �οπής π�ωτονίου π�ος νετ�όνιο proton-neutron mass ratio λόγος μάζας π�ωτονίου π�ος νετ�όνιο proton relative atomic mass (Ar(p)) σχετική ατομική μάζα π�ωτονίου (Ar(p)) proton rms charge radius μέση τετ�αγωνική ακτίνα φο�τίου π�ωτονίου proton-tau mass ratio λόγος μάζας π�ωτονίου π�ος ταυ reduced proton Compton wavelength ανηγμένο μήκος κ�ματος Compton π�ωτονίου shielded proton gyromagnetic ratio γυ�ομαγνητικός λόγος θω�ακισμένου π�ωτονίου shielded proton gyromagnetic ratio in MHz/T γυ�ομαγνητικός λόγος θω�ακισμένου π�ωτονίου σε MHz/T shielded proton magnetic moment μαγνητική �οπή θω�ακισμένου π�ωτονίου shielded proton magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής θω�ακισμένου π�ωτονίου π�ος μαγνητόνη Bohr shielded proton magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής θω�ακισμένου π�ωτονίου π�ος πυ�ηνική μαγνητόνη neutron Compton wavelength μήκος κ�ματος Compton νετ�ονίου neutron-electron magnetic moment ratio λόγος μαγνητικής �οπής νετ�ονίου π�ος ηλεκτ�όνιο neutron-electron mass ratio λόγος μάζας νετ�ονίου π�ος ηλεκτ�όνιο neutron g factor (gₙ) πα�άγοντας g νετ�ονίου (gₙ) neutron gyromagnetic ratio (γₙ) γυ�ομαγνητικός λόγος νετ�ονίου (γₙ) neutron gyromagnetic ratio in MHz/T γυ�ομαγνητικός λόγος νετ�ονίου σε MHz/T neutron magnetic moment (μₙ) μαγνητική �οπή νετ�ονίου (μₙ) neutron magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής νετ�ονίου π�ος μαγνητόνη Bohr neutron magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής νετ�ονίου π�ος πυ�ηνική μαγνητόνη neutron mass (mₙ) μάζα νετ�ονίου (mₙ) neutron mass energy equivalent ενε�γειακό ισοδ�ναμο μάζας νετ�ονίου neutron mass energy equivalent in MeV ενε�γειακό ισοδ�ναμο μάζας νετ�ονίου σε MeV neutron mass in u μάζα νετ�ονίου σε u neutron molar mass (Mₙ) μο�ιακή μάζα νετ�ονίου (Mₙ) neutron-muon mass ratio λόγος μάζας νετ�ονίου π�ος μιόνιο neutron-proton magnetic moment ratio λόγος μαγνητικής �οπής νετ�ονίου π�ος π�ωτόνιο neutron-proton mass difference διαφο�ά μάζας νετ�ονίου-π�ωτονίου neutron-proton mass difference energy equivalent ενε�γειακό ισοδ�ναμο διαφο�άς μάζας νετ�ονίου-π�ωτονίου neutron-proton mass difference energy equivalent in MeV ενε�γειακό ισοδ�ναμο διαφο�άς μάζας νετ�ονίου-π�ωτονίου σε MeV neutron-proton mass difference in u διαφο�ά μάζας νετ�ονίου-π�ωτονίου σε u neutron-proton mass ratio λόγος μάζας νετ�ονίου π�ος π�ωτόνιο neutron relative atomic mass (Ar(n)) σχετική ατομική μάζα νετ�ονίου (Ar(n)) neutron-tau mass ratio λόγος μάζας νετ�ονίου π�ος ταυ neutron to shielded proton magnetic moment ratio λόγος μαγνητικής �οπής νετ�ονίου π�ος θω�ακισμένο π�ωτόνιο reduced neutron Compton wavelength ανηγμένο μήκος κ�ματος Compton νετ�ονίου deuteron-electron magnetic moment ratio λόγος μαγνητικής �οπής δευτε�ονίου π�ος ηλεκτ�όνιο deuteron-electron mass ratio λόγος μάζας δευτε�ονίου π�ος ηλεκτ�όνιο deuteron g factor πα�άγοντας g δευτε�ονίου deuteron magnetic moment μαγνητική �οπή δευτε�ονίου deuteron magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής δευτε�ονίου π�ος μαγνητόνη Bohr deuteron magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής δευτε�ονίου π�ος πυ�ηνική μαγνητόνη deuteron mass μάζα δευτε�ονίου deuteron mass energy equivalent ενε�γειακό ισοδ�ναμο μάζας δευτε�ονίου deuteron mass energy equivalent in MeV ενε�γειακό ισοδ�ναμο μάζας δευτε�ονίου σε MeV deuteron mass in u μάζα δευτε�ονίου σε u deuteron molar mass μο�ιακή μάζα δευτε�ονίου deuteron-neutron magnetic moment ratio λόγος μαγνητικής �οπής δευτε�ονίου π�ος νετ�όνιο deuteron-proton magnetic moment ratio λόγος μαγνητικής �οπής δευτε�ονίου π�ος π�ωτόνιο deuteron-proton mass ratio λόγος μάζας δευτε�ονίου π�ος π�ωτόνιο deuteron relative atomic mass (Ar(d)) σχετική ατομική μάζα δευτε�ονίου (Ar(d)) deuteron rms charge radius μέση τετ�αγωνική ακτίνα φο�τίου δευτε�ονίου triton-electron mass ratio λόγος μάζας τ�ιτίου π�ος ηλεκτ�όνιο triton g factor (gₜ) πα�άγοντας g τ�ιτίου (gₜ) triton magnetic moment (μₜ) μαγνητική �οπή τ�ιτίου (μₜ) triton magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής τ�ιτονίου π�ος μαγνητόνη Bohr triton magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής τ�ιτονίου π�ος πυ�ηνική μαγνητόνη triton mass (mₜ) μάζα τ�ιτίου (mₜ) triton mass energy equivalent ενε�γειακό ισοδ�ναμο μάζας τ�ιτίου triton mass energy equivalent in MeV ενε�γειακό ισοδ�ναμο μάζας τ�ιτίου σε MeV triton mass in u μάζα τ�ιτίου σε u triton molar mass (Mₜ) μο�ιακή μάζα τ�ιτίου (Mₜ) triton-proton mass ratio λόγος μάζας τ�ιτίου π�ος π�ωτόνιο triton relative atomic mass (Ar(t)) σχετική ατομική μάζα τ�ιτίου (Ar(t)) triton to proton magnetic moment ratio λόγος μαγνητικής �οπής τ�ιτονίου π�ος π�ωτόνιο helion-electron mass ratio λόγος μάζας ηλίου π�ος ηλεκτ�όνιο helion g factor (gₕ) πα�άγοντας g ηλίου (gₕ) helion magnetic moment (μₕ) μαγνητική �οπή ηλίου (μₕ) helion magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής ηλίου π�ος μαγνητόνη Bohr helion magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής ηλίου π�ος πυ�ηνική μαγνητόνη helion mass (mₕ) μάζα ηλίου (mₕ) helion mass energy equivalent ενε�γειακό ισοδ�ναμο μάζας ηλίου helion mass energy equivalent in MeV ενε�γειακό ισοδ�ναμο μάζας ηλίου σε MeV helion mass in u μάζα ηλίου σε u helion molar mass (Mₕ) μο�ιακή μάζα ηλίου (Mₕ) helion-proton mass ratio λόγος μάζας ηλίου π�ος π�ωτόνιο helion relative atomic mass (Ar(h)) σχετική ατομική μάζα ηλίου (Ar(h)) helion shielding shift μετατόπιση θω�άκισης ηλίου shielded helion gyromagnetic ratio γυ�ομαγνητικός λόγος θω�ακισμένου ηλίου shielded helion gyromagnetic ratio in MHz/T γυ�ομαγνητικός λόγος θω�ακισμένου ηλίου σε MHz/T shielded helion magnetic moment μαγνητική �οπή θω�ακισμένου ηλίου shielded helion magnetic moment to Bohr magneton ratio λόγος μαγνητικής �οπής θω�ακισμένου ηλίου π�ος μαγνητόνη Bohr shielded helion magnetic moment to nuclear magneton ratio λόγος μαγνητικής �οπής θω�ακισμένου ηλίου π�ος πυ�ηνική μαγνητόνη shielded helion to proton magnetic moment ratio λόγος μαγνητικής �οπής θω�ακισμένου ηλίου π�ος π�ωτόνιο shielded helion to shielded proton magnetic moment ratio λόγος μαγνητικής �οπής θω�ακισμένου ηλίου π�ος θω�ακισμένο π�ωτόνιο alpha particle mass μάζα σωματιδίου άλφα alpha particle mass in u μάζα σωματιδίου άλφα σε u alpha particle mass energy equivalent ενε�γειακό ισοδ�ναμο μάζας σωματιδίου άλφα alpha particle mass energy equivalent in MeV ενε�γειακό ισοδ�ναμο μάζας σωματιδίου άλφα σε MeV alpha particle-electron mass ratio λόγος μάζας σωματιδίου άλφα π�ος ηλεκτ�όνιο alpha particle-proton mass ratio λόγος μάζας σωματιδίου άλφα π�ος π�ωτόνιο alpha particle rms charge radius μέση τετ�αγωνική ακτίνα φο�τίου σωματιδίου άλφα alpha particle molar mass μο�ιακή μάζα σωματιδίου άλφα alpha particle relative atomic mass (Ar(α)) σχετική ατομική μάζα σωματιδίου άλφα (Ar(α)) atomic mass constant (mᵤ) σταθε�ά ατομικής μάζας (mᵤ) Avogadro constant σταθε�ά Avogadro Boltzmann constant (k) σταθε�ά Boltzmann (k) Boltzmann constant in eV/K σταθε�ά Boltzmann σε eV/K Boltzmann constant in Hz/K σταθε�ά Boltzmann σε Hz/K Boltzmann constant in inverse meter per kelvin σταθε�ά Boltzmann σε αντίστ�οφο μέτ�ο ανά κέλβιν electron volt (eV) ηλεκτ�ονιοβόλτ (eV) Faraday constant (F) σταθε�ά Faraday (F) first radiation constant (c�) π�ώτη σταθε�ά ακτινοβολίας (c�) first radiation constant for spectral radiance π�ώτη σταθε�ά ακτινοβολίας για φασματική ακτινοβολία molar gas constant (R) μο�ιακή σταθε�ά αε�ίων (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) σταθε�ά Loschmidt (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) σταθε�ά Loschmidt (n₀, 273.15 K, 101.325 kPa) molar Planck constant μο�ιακή σταθε�ά του Planck second radiation constant (c₂) δε�τε�η σταθε�ά ακτινοβολίας (c₂) Stefan-Boltzmann constant (σ) σταθε�ά Stefan-Boltzmann (σ) lattice spacing of ideal Si (d₂₂₀) πλεγματική απόσταση ιδανικο� Si (d₂₂₀) atomic mass constant energy equivalent ενε�γειακό ισοδ�ναμο σταθε�άς ατομικής μάζας atomic mass constant energy equivalent in MeV ενε�γειακό ισοδ�ναμο σταθε�άς ατομικής μάζας σε MeV atomic mass unit-electron volt relationship σχέση μονάδας ατομικής μάζας-ηλεκτ�ονιοβόλτ molar mass constant (Mᵤ) σταθε�ά μο�ιακής μάζας (Mᵤ) molar mass of carbon-12 μο�ιακή μάζα του άνθ�ακα-12 molar volume of ideal gas (273.15 K, 100 kPa) μο�ιακός όγκος ιδανικο� αε�ίου (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) μο�ιακός όγκος ιδανικο� αε�ίου (273.15 K, 101.325 kPa) molar volume of silicon μο�ιακός όγκος πυ�ιτίου Sackur-Tetrode constant (1 K, 100 kPa) σταθε�ά Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) σταθε�ά Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant σταθε�ά νόμου μετατόπισης συχνότητας Wien Wien wavelength displacement law constant σταθε�ά νόμου μετατόπισης μήκους κ�ματος Wien standard atmosphere (atm) τυπική ατμόσφαι�α (atm) standard-state pressure (p°) πίεση π�ότυπης κατάστασης (p°) Angstrom star (Å*) αστέ�ας Άνγκστ�εμ (Å*) Copper x unit μονάδα x χαλκο� Molybdenum x unit μονάδα x μολυβδαινίου atomic unit of magnetizability ατομική μονάδα μαγνητισιμότητας atomic unit of mass (mₑ) ατομική μονάδα μάζας (mₑ) atomic unit of momentum ατομική μονάδα ο�μής atomic unit of permittivity ατομική μονάδα διαπε�ατότητας atomic unit of time ατομική μονάδα χ�όνου atomic unit of velocity ατομική μονάδα ταχ�τητας hartree-hertz relationship σχέση Hartree-χέ�τζ hartree-inverse meter relationship σχέση Hartree-αντίστ�οφου μέτ�ου hartree-joule relationship σχέση Hartree-τζάουλ hartree-kelvin relationship σχέση Hartree-κέλβιν hartree-kilogram relationship σχέση Hartree-χιλιογ�άμμου shielding difference of d and p in HD διαφο�ά θω�άκισης του d και p σε HD shielding difference of t and p in HT διαφο�ά θω�άκισης του t και p σε HT pi (π) πι (π) Euler's number (e) α�ιθμός του Euler (e) golden ratio (φ) χ�υσή τομή (φ) Euler-Mascheroni constant (γ) σταθε�ά Euler-Mascheroni (γ) nominal solar radius ονομαστική ηλιακή ακτίνα nominal solar total irradiance ονομαστική ολική ηλιακή ακτινοβολία nominal solar luminosity ονομαστική ηλιακή φωτεινότητα nominal solar effective temperature ονομαστική ενε�γός θε�μοκ�ασία του Ήλιου nominal solar mass parameter ονομαστική πα�άμετ�ος μάζας του Ήλιου nominal terrestrial equatorial radius ονομαστική ισημε�ινή ακτίνα της Γης nominal terrestrial polar radius ονομαστική πολική ακτίνα της Γης nominal terrestrial mass parameter ονομαστική πα�άμετ�ος μάζας της Γης nominal jovian equatorial radius ονομαστική ισημε�ινή ακτίνα του Δία nominal jovian polar radius ονομαστική πολική ακτίνα του Δία nominal jovian mass parameter ονομαστική πα�άμετ�ος μάζας του Δία average value of one minus the rate of TCG relative to TCB μέση τιμή του ενός μείον τον �υθμό του TCG ως π�ος το TCB solar mass parameter (TCB-compatible) πα�άμετ�ος μάζας του Ήλιου (συμβατή με TCB) solar mass parameter (TDB-compatible) πα�άμετ�ος μάζας του Ήλιου (συμβατή με TDB) equatorial radius of the Earth (TT-compatible) ισημε�ινή ακτίνα της Γης (συμβατή με TT) dynamical form factor of the Earth δυναμικός συντελεστής μο�φής της Γης time rate of change in the dynamical form factor of the Earth χ�ονικός �υθμός μεταβολής του δυναμικο� συντελεστή μο�φής της Γης geocentric gravitational constant (TCB-compatible) γεωκεντ�ική βα�υτική σταθε�ά (συμβατή με TCB) geocentric gravitational constant (TT-compatible) γεωκεντ�ική βα�υτική σταθε�ά (συμβατή με TT) geocentric gravitational constant (TDB-compatible) γεωκεντ�ική βα�υτική σταθε�ά (συμβατή με TDB) potential of the geoid δυναμικό του γεωειδο�ς nominal mean angular velocity of the Earth (TT-compatible) ονομαστική μέση γωνιακή ταχ�τητα της Γης (συμβατή με TT) ratio mass of the Moon to the Earth λόγος μάζας της Σελήνης π�ος τη Γη ratio of the mass of the Sun to Mercury λόγος μάζας του Ήλιου π�ος τον Ε�μή ratio of the mass of the Sun to Venus λόγος μάζας του Ήλιου π�ος την Αφ�οδίτη ratio of the mass of the Sun to Mars λόγος μάζας του Ήλιου π�ος τον Ά�η ratio of the mass of the Sun to Jupiter λόγος μάζας του Ήλιου π�ος τον Δία ratio of the mass of the Sun to Saturn λόγος μάζας του Ήλιου π�ος τον Κ�όνο ratio of the mass of the Sun to Uranus λόγος μάζας του Ήλιου π�ος τον Ου�ανό ratio of the mass of the Sun to Neptune λόγος μάζας του Ήλιου π�ος τον Ποσειδώνα ratio of the mass of the Sun to (134340) Pluto λόγος μάζας του Ήλιου π�ος τον (134340) Πλο�τωνα ratio of the mass of the Sun to (136199) Eris λόγος μάζας του Ήλιου π�ος την (136199) Έ�ιδα ratio of the mass of (1) Ceres to the Sun λόγος μάζας της (1) Δήμητ�ας π�ος τον Ήλιο ratio of the mass of (2) Pallas to the Sun λόγος μάζας της (2) Παλλάδας π�ος τον Ήλιο ratio of the mass of (4) Vesta to the Sun λόγος μάζας της (4) Εστίας π�ος τον Ήλιο mean obliquity of the ecliptic at J2000.0 μέση λόξωση της εκλειπτικής στο J2000.0 Electromagnetic Ηλεκτ�ομαγνητική Compton wavelength Μήκος κ�ματος Compton Astronomy Αστ�ονομία ConstantsWidget Domain Τομέας Subdomain Υποτομέας No match found Δεν β�έθηκε αντιστοιχία Name Όνομα Value Τιμή Unit Μονάδα Search Αναζήτηση All Όλα CustomKeypadDialog Custom Keypad Π�οσα�μοσμένο πληκτ�ολόγιο Rows: Γ�αμμές: Columns: Στήλες: Copy preset: Αντιγ�αφή π�οεπιλογής: Basic Βασικό Scientific (wide) Επιστημονικό (πλατ�) Scientific (narrow) Επιστημονικό (στενό) Apply Εφα�μογή Row Γ�αμμή Column Στήλη Label Ετικέτα Behavior Συμπε�ιφο�ά Text Κείμενο DiagnosticsDialog App Diagnostics Διαγνωστικά εφα�μογής Copy to Clipboard Αντιγ�αφή στο π�όχει�ο Editor Unit Μονάδα User unit Μονάδα χ�ήστη User function Συνά�τηση χ�ήστη Argument Ό�ισμα Current result:<br/>%1 Τ�έχον αποτέλεσμα:<br/>%1 Selection result:<br/>%1 Αποτέλεσμα επιλογής:<br/>%1 Selection result: n/a Αποτέλεσμα επιλογής: δ/υ Selection result: %1 Αποτέλεσμα επιλογής: %1 second δευτε�όλεπτο metre μέτ�ο kilogram χιλιόγ�αμμο mole μολ radian ακτίνιο steradian στε�ακτίνιο degree Celsius βαθμός Κελσίου cubic metre κυβικό μέτ�ο cubic millimetre κυβικό χιλιοστόμετ�ο cubic centimetre κυβικό εκατοστόμετ�ο cubic decimetre κυβικό δεκατόμετ�ο cubic kilometre κυβικό χιλιόμετ�ο square millimetre τετ�αγωνικό χιλιοστόμετ�ο square kilometre τετ�αγωνικό χιλιόμετ�ο square metre τετ�αγωνικό μέτ�ο minute λεπτό hour ώ�α day ημέ�α astronomical unit αστ�ονομική μονάδα degree μοί�α arcminute λεπτό τόξου arcsecond δευτε�όλεπτο τόξου milliarcsecond χιλιοστοδευτε�όλεπτο τόξου microarcsecond μικ�οδευτε�όλεπτο τόξου hectare εκτά�ιο litre λίτ�ο tonne τόνος Dalton ντάλτον electronvolt ηλεκτ�ονιοβόλτ Angstrom Άνγκστ�εμ atmosphere ατμόσφαι�α atomic mass unit μονάδα ατομικής μάζας British thermal unit β�ετανική θε�μική μονάδα calorie θε�μίδα carat κα�άτι cup φλιτζάνι cup (Imperial) φλιτζάνι (β�ετανικό) cup (Japanese) φλιτζάνι (Ιαπωνίας) cup (US) φλιτζάνι (ΗΠΑ) degree Fahrenheit βαθμός Φα�ενάιτ fathom ο�γυιά fluid ounce (Imperial) �ευστή ουγγιά (β�ετανική) fluid ounce (US) �ευστή ουγγιά (ΗΠΑ) fluid dram (Imperial) �ευστή δ�αχμή (β�ετανική) fluid dram (US) �ευστή δ�αχμή (ΗΠΑ) foot πόδι square foot τετ�αγωνικό πόδι cubic foot κυβικό πόδι gallon (Imperial) γαλόνι (β�ετανικό) gallon (US) γαλόνι (ΗΠΑ) gill (Imperial) gill (β�ετανικό) gill (US) gill (ΗΠΑ) gradian βαθμός grad grain κόκκος gram γ�αμμά�ιο Hartley Hartley Hartree energy unit μονάδα ενέ�γειας Hartree horsepower ίππος inch ίντσα square inch τετ�αγωνική ίντσα cubic inch κυβική ίντσα karat κα�άτι καθα�ότητας knot κόμβος lightminute λεπτό φωτός lightsecond δευτε�όλεπτο φωτός lightyear έτος φωτός long ton μεγάλος τόνος mile μίλι square mile τετ�αγωνικό μίλι cubic mile κυβικό μίλι mile per hour μίλι ανά ώ�α kilometre per hour χιλιόμετ�ο ανά ώ�α nautical mile ναυτικό μίλι ounce ουγγιά parsec πα�σέκ pint (Imperial) πίντα (β�ετανική) pint (US) πίντα (ΗΠΑ) pound λίβ�α pounds per square inch λίβ�ες ανά τετ�αγωνική ίντσα quart (Imperial) κουά�το (β�ετανικό) quart (US) κουά�το (ΗΠΑ) oil barrel βα�έλι πετ�ελαίου beer barrel (US) βα�έλι μπ��ας (ΗΠΑ) square yard τετ�αγωνική γιά�δα cubic yard κυβική γιά�δα short ton μικ�ός τόνος tablespoon κουτάλι σο�πας tablespoon (Australian) κουτάλι σο�πας (Αυστ�αλίας) tablespoon (Imperial) κουτάλι σο�πας (β�ετανικό) tablespoon (US) κουτάλι σο�πας (ΗΠΑ) dessert spoon κουτάλι επιδο�πίου teaspoon κουταλάκι του γλυκο� teaspoon (Imperial) κουταλάκι του γλυκο� (β�ετανικό) teaspoon (US) κουταλάκι του γλυκο� (ΗΠΑ) turn στ�οφή revolution πε�ιστ�οφή revolution per minute πε�ιστ�οφές ανά λεπτό week εβδομάδα kilowatt hour κιλοβατώ�α millimetre of mercury χιλιοστόμετ�ο υδ�α�γ��ου yard γιά�δα Julian century Ιουλιανός αιώνας Julian year Ιουλιανό έτος sidereal year αστ�ικό έτος tropical year τ�οπικό έτος Evaluator invalid expression μη έγκυ�η έκφ�αση division by zero διαί�εση με το μηδέν too time consuming - computation was rejected υπε�βολικά χ�ονοβό�ο - ο υπολογισμός απο��ίφθηκε dimension mismatch - quantities with different dimensions cannot be compared, added, etc. αναντιστοιχία διαστάσεων - ποσότητες με διαφο�ετικές διαστάσεις δεν μπο�ο�ν να συγκ�ιθο�ν, να π�οστεθο�ν κ.λπ. invalid dimension - operation might require dimensionless arguments μη έγκυ�η διάσταση - η π�άξη ενδέχεται να απαιτεί αδιάστατα ο�ίσματα Computation aborted - encountered numerical instability Ο υπολογισμός διακόπηκε - εντοπίστηκε α�ιθμητική αστάθεια invalid dimension - function might require dimensionless arguments μη έγκυ�η διάσταση - η συνά�τηση ενδέχεται να απαιτεί αδιάστατα ο�ίσματα error Σφάλμα unit must not be zero η μονάδα δεν π�έπει να είναι μηδέν Conversion failed - dimension mismatch Η μετατ�οπή απέτυχε - οι διαστάσεις δεν συμφωνο�ν unknown function or variable άγνωστη συνά�τηση ή μεταβλητή recursion not supported Η αναδ�ομή δεν υποστη�ίζεται cannot operate on a NaN δεν είναι δυνατή η π�άξη σε NaN underflow - tiny result is out of SpeedCrunch's number range υποχείλιση - το πολ� μικ�ό αποτέλεσμα είναι εκτός του ε��ους α�ιθμών του SpeedCrunch overflow - huge result is out of SpeedCrunch's number range υπε�χείλιση - το πολ� μεγάλο αποτέλεσμα είναι εκτός του ε��ους α�ιθμών του SpeedCrunch overflow - logic result exceeds maximum of 256 bits υπε�χείλιση - το λογικό αποτέλεσμα υπε�βαίνει το μέγιστο των 256 bit overflow - integer result exceeds maximum limit for integers υπε�χείλιση - το ακέ�αιο αποτέλεσμα υπε�βαίνει το μέγιστο ό�ιο για ακέ�αιους operation is not defined for these arguments η π�άξη δεν ο�ίζεται για αυτά τα ο�ίσματα wrong number of arguments εσφαλμένος α�ιθμός ο�ισμάτων does not take NaN as an argument δεν δέχεται NaN ως ό�ισμα result out of range αποτέλεσμα εκτός ε��ους undefined for argument domain δεν ο�ίζεται για το πεδίο ο�ισμο� του ο�ίσματος computation too expensive ο υπολογισμός είναι υπε�βολικά απαιτητικός internal error, please report a bug εσωτε�ικό σφάλμα, αναφέ�ετε το π�όβλημα syntax error συντακτικό σφάλμα conversion target must be a unit ο στόχος μετατ�οπής π�έπει να είναι μονάδα unknown unit άγνωστη μονάδα %1 is a reserved name, please choose another Το %1 είναι δεσμευμένο όνομα, επιλέξτε άλλο %1 is a global user definition and cannot be overridden in this session. Το %1 είναι καθολικός ο�ισμός χ�ήστη και δεν μπο�εί να πα�ακαμφθεί σε αυτήν τη συνεδ�ία. %1 is a variable name, please choose another or delete the variable Το %1 είναι όνομα μεταβλητής, επιλέξτε άλλο ή διαγ�άψτε τη μεταβλητή argument %1 is used more than once το ό�ισμα %1 χ�ησιμοποιείται πε�ισσότε�ες από μία φο�ές %1 is a built-in unit name, please choose another Το %1 είναι όνομα ενσωματωμένης μονάδας, επιλέξτε άλλο %1 is a user function name, please choose another or delete the function Το %1 είναι όνομα συνά�τησης χ�ήστη, επιλέξτε άλλο ή διαγ�άψτε τη συνά�τηση FunctionRepo max; trials; probability μέγιστο; δοκιμές; πιθανότητα trials; probability δοκιμές; πιθανότητα hits; trials; probability επιτυχίες; δοκιμές; πιθανότητα max; total; hits; trials μέγιστο; σ�νολο; επιτυχίες; δοκιμές total; hits; trials σ�νολο; επιτυχίες; δοκιμές count; total; hits; trials πλήθος; σ�νολο; επιτυχίες; δοκιμές dividend; divisor μέ�ισμα; διαι�έτης x; exponent_bits; significand_bits [; exponent_bias] x; bit_εκθέτη; bit_σημαντικο� [; πόλωση_εκθέτη] base; x βάση; x value; modulo τιμή; μέτ�ο base; exponent; modulo βάση; εκθέτης; μέτ�ο events; average_events γεγονότα; μέσος_ό�ος_γεγονότων average_events μέσος_ό�ος_γεγονότων x [; precision] x [; ακ�ίβεια] Absolute Value Απόλυτη Τιμή Absolute Deviation Απόλυτη Απόκλιση Arc Cosine Αντίστ�οφο συνημίτονο Logical AND Λογικό ΚΑΙ Area Hyperbolic Cosine Αντίστ�οφο υπε�βολικό συνημίτονο Area Hyperbolic Sine Αντίστ�οφο υπε�βολικό ημίτονο Area Hyperbolic Tangent Αντίστ�οφη υπε�βολική εφαπτομένη Arc Sine Αντίστ�οφο ημίτονο Arc Tangent Αντίστ�οφη εφαπτομένη Arc Tangent with two Arguments Αντίστ�οφη εφαπτομένη με δ�ο ο�ίσματα Average (Arithmetic Mean) Μέση τιμή (α�ιθμητικός μέσος ό�ος) Binomial Cumulative Distribution Function Συνά�τηση αθ�οιστικής κατανομής της διωνυμικής κατανομής Binomial Distribution Mean Μέσος ό�ος διωνυμικής κατανομής Binomial Probability Mass Function Συνά�τηση μάζας πιθανότητας της διωνυμικής κατανομής Binomial Distribution Variance Διακ�μανση διωνυμικής κατανομής Cube Root Κυβική Ρίζα Complex Conjugate Συζυγής Μιγαδικός Cosine Συνημίτονο Hyperbolic Cosine Υπε�βολικό Συνημίτονο Cotangent Συνεφαπτομένη Cosecant Συντεμνο�σα Convert Unix timestamp to Date Μετατ�οπή Χ�ονικής Σήμανσης Unix σε Ημε�ομηνία Degrees of Arc Μοί�ες Τόξου Error Function Συνά�τηση Σφάλματος Complementary Error Function Συνά�τηση Συμπλη�ωματικο� Σφάλματος Exponential Εκθετική Fractional Part Κλασματικό Τμήμα Extension of Factorials [= (x-1)!] Επέκταση των Πα�αγοντικών [= (x-1)!] Greatest Common Divisor Μέγιστος Κοινός Διαι�έτης Geometric Mean Γεωμετ�ικός Μέσος Gradians of arc Βαθμοί grad τόξου Hypergeometric Cumulative Distribution Function Συνά�τηση αθ�οιστικής κατανομής της υπε�γεωμετ�ικής κατανομής Hypergeometric Distribution Mean Μέσος ό�ος υπε�γεωμετ�ικής κατανομής Hypergeometric Probability Mass Function Συνά�τηση μάζας πιθανότητας της υπε�γεωμετ�ικής κατανομής Hypergeometric Distribution Variance Διακ�μανση υπε�γεωμετ�ικής κατανομής Integer Quotient Ακέ�αιο πηλίκο Integer Part Ακέ�αιο τμήμα Imaginary Part Φανταστικό Τμήμα Decode IEEE-754 Binary Value Αποκωδικοποίηση Δυαδικής Τιμής IEEE-754 Encode IEEE-754 Binary Value Κωδικοποίηση Δυαδικής Τιμής IEEE-754 Decode 16-bit Half-Precision Value Αποκωδικοποίηση Τιμής Μισής Ακ�ίβειας 16-bit Encode 16-bit Half-Precision Value Κωδικοποίηση Τιμής Μισής Ακ�ίβειας 16-bit Decode 32-bit Single-Precision Value Αποκωδικοποίηση Τιμής Απλής Ακ�ίβειας 32-bit Encode 32-bit Single-Precision Value Κωδικοποίηση Τιμής Απλής Ακ�ίβειας 32-bit Decode 64-bit Double-Precision Value Αποκωδικοποίηση Τιμής Διπλής Ακ�ίβειας 64-bit Encode 64-bit Double-Precision Value Κωδικοποίηση Τιμής Διπλής Ακ�ίβειας 64-bit Decode 128-bit Quad-Precision Value Αποκωδικοποίηση Τιμής Τετ�απλής Ακ�ίβειας 128-bit Encode 128-bit Quad-Precision Value Κωδικοποίηση Τιμής Τετ�απλής Ακ�ίβειας 128-bit Binary Logarithm Δυαδικός Λογά�ιθμος Common Logarithm Κοινός Λογά�ιθμος Natural Logarithm Φυσικός Λογά�ιθμος Logarithm to Arbitrary Base Λογά�ιθμος σε Αυθαί�ετη Βάση Mask to a bit size Μάσκα σε μέγεθος bit Maximum Μέγιστο Median Value (50th Percentile) Διάμεση Τιμή (50ο Εκατοστημό�ιο) Minimum Ελάχιστο Modulo Υπόλοιπο Euclidean Modulo Ευκλείδειο υπόλοιπο Modular Exponentiation Εκθετοποίηση κατά μέτ�ο Combination (Binomial Coefficient) Συνδυασμός (Διωνυμικός Συντελεστής) Logical NOT Λογικό ΟΧΙ Permutation (Arrangement) Μετάθεση (διάταξη) Convert to Binary Representation Μετατ�οπή σε Δυαδική Απεικόνιση Arithmetic Α�ιθμητική Chemistry Χημεία Complex Μιγαδικοί Combinatorics Συνδυαστική Probability Πιθανότητες Statistics Στατιστική Aggregation Συνάθ�οιση Random Τυχαία Base conversion Μετατ�οπή βάσης Number formatting Μο�φοποίηση α�ιθμών Integer arithmetic Ακέ�αια α�ιθμητική Special functions Ειδικές συνα�τήσεις Exponential & Logarithmic Εκθετικές & λογα�ιθμικές Angle conversion Μετατ�οπή γωνιών Trigonometry Τ�ιγωνομετ�ία Bitwise Κατά bit Floating point Κινητής υποδιαστολής Date & Time Ημε�ομηνία & ώ�α Linear algebra Γ�αμμική άλγεβ�α unix_timestamp; x hours offset to GMT χ�ονοσήμανση_unix; x ώ�ες μετατόπιση σε GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; μετατόπιση x ω�ών από GMT [digits] [ψηφία] max [; min] μέγιστο [; ελάχιστο] List Literal Κυ�ιολεκτική λίστα Convert to Padded Binary Representation Μετατ�οπή σε δυαδική αναπα�άσταση με συμπλή�ωση Round Toward +∞ (Ceiling) Στ�ογγυλοποίηση π�ος +∞ (ο�οφή) Cosine plus Imaginary Sine Συνημίτονο συν φανταστικό ημίτονο Convert to Cis Complex Form Μετατ�οπή σε μιγαδική μο�φή cis Matrix Column Count Πλήθος στηλών πίνακα Population Correlation Matrix (n) Πίνακας συσχέτισης πληθυσμο� (n) Sample Correlation Matrix (n-1) Πίνακας συσχέτισης δείγματος (n-1) Count Πλήθος Population Covariance Matrix (n) Πίνακας συνδιακ�μανσης πληθυσμο� (n) Sample Covariance Matrix (n-1) Πίνακας συνδιακ�μανσης δείγματος (n-1) Cross Product Διανυσματικό γινόμενο Convert Date to Unix timestamp Μετατ�οπή ημε�ομηνίας σε χ�ονοσήμανση Unix Convert to Decimal Representation Μετατ�οπή σε Δεκαδική Απεικόνιση Determinant Ο�ίζουσα Convert to Sexagesimal Notation Μετατ�οπή σε εξηκονταδικό συμβολισμό Dot Product Εσωτε�ικό γινόμενο Convert to Engineering Notation Μετατ�οπή σε μηχανικό συμβολισμό Convert to Exponential Complex Form Μετατ�οπή σε εκθετική μιγαδική μο�φή Round Toward −∞ (Floor) Στ�ογγυλοποίηση π�ος −∞ (δάπεδο) Flatten Matrix Επιπέδωση πίνακα Least Common Multiple Ελάχιστο κοινό πολλαπλάσιο Convert to Hexadecimal Representation Μετατ�οπή σε Δεκαεξαδική Απεικόνιση Convert to Padded Hexadecimal Representation Μετατ�οπή σε δεκαεξαδική αναπα�άσταση με συμπλή�ωση Inverse Matrix Αντίστ�οφος πίνακας Round to 16-bit Half-Precision Value Στ�ογγυλοποίηση σε τιμή μισής ακ�ίβειας 16-bit Round to 32-bit Single-Precision Value Στ�ογγυλοποίηση σε τιμή απλής ακ�ίβειας 32-bit Round to 64-bit Double-Precision Value Στ�ογγυλοποίηση σε τιμή διπλής ακ�ίβειας 64-bit Round to 128-bit Quad-Precision Value Στ�ογγυλοποίηση σε τιμή τετ�απλής ακ�ίβειας 128-bit Residual from 16-bit Half-Precision Rounding Υπόλοιπο από στ�ογγυλοποίηση μισής ακ�ίβειας 16-bit Residual from 32-bit Single-Precision Rounding Υπόλοιπο από στ�ογγυλοποίηση απλής ακ�ίβειας 32-bit Residual from 64-bit Double-Precision Rounding Υπόλοιπο από στ�ογγυλοποίηση διπλής ακ�ίβειας 64-bit Residual from 128-bit Quad-Precision Rounding Υπόλοιπο από στ�ογγυλοποίηση τετ�απλής ακ�ίβειας 128-bit Substance Mass Μάζα ουσίας Molarity Μο�ιακότητα Molar Mass Μο�ιακή μάζα Median Absolute Deviation Διάμεση απόλυτη απόκλιση Mean Μέσος ό�ος Numerical Value of Quantity Α�ιθμητική τιμή ποσότητας Random Decimal Number Τυχαίος δεκαδικός α�ιθμός Random Integer Number Τυχαίος ακέ�αιος α�ιθμός Convert to Rational Representation Μετατ�οπή σε �ητή αναπα�άσταση Convert to Octal Representation Μετατ�οπή σε Οκταδική Απεικόνιση Convert to Padded Octal Representation Μετατ�οπή σε οκταδική αναπα�άσταση με συμπλή�ωση Vector or Matrix Norm �ό�μα διαν�σματος ή πίνακα Logical OR Λογικό Ή Population Count (Hamming Weight) Πλήθος ενε�γών bit (βά�ος Hamming) Phase of Complex Number Φάση Μιγαδικο� Α�ιθμο� Poissonian Cumulative Distribution Function Συνά�τηση αθ�οιστικής κατανομής Poisson Poissonian Distribution Mean Μέσος ό�ος κατανομής Poisson Poissonian Probability Mass Function Συνά�τηση μάζας πιθανότητας Poisson Poissonian Distribution Variance Διακ�μανση κατανομής Poisson Convert to Phasor Complex Form Μετατ�οπή σε φασική μιγαδική μο�φή Convert to Rectangular Complex Form Μετατ�οπή σε ο�θογώνια μιγαδική μο�φή Round Half Away from Zero Στ�ογγυλοποίηση στη μέση μακ�ιά από το μηδέν Round Half Even Στ�ογγυλοποίηση στη μέση π�ος ά�τιο Nth Root �ιοστή �ίζα Convert to Scientific Notation Μετατ�οπή σε επιστημονικό συμβολισμό Matrix Row Count Πλήθος γ�αμμών πίνακα List or Matrix Shape Σχήμα λίστας ή πίνακα Summation Άθ�οιση Population Standard Deviation (n) Τυπική απόκλιση πληθυσμο� (n) Sample Standard Deviation (n-1) Τυπική απόκλιση δείγματος (n-1) Round Toward Zero (Truncation) Στ�ογγυλοποίηση π�ος το μηδέν (αποκοπή) Matrix Trace Ίχνος πίνακα Transpose Matrix Μεταφο�ά πίνακα Population Variance (n) Διακ�μανση πληθυσμο� (n) Sample Variance (n-1) Διακ�μανση δείγματος (n-1) Product Γινόμενο Radians Ακτίνια Matrix Rank Βαθμός πίνακα Real Part Π�αγματικό Τμήμα Secant Διατεμνο�σα Arithmetic Shift Left Α�ιθμητική Μετατόπιση Α�ιστε�ά Arithmetic Shift Right Α�ιθμητική Μετατόπιση Δεξιά Signum Π�όσημο Sine Ημίτονο Hyperbolic Sine Υπε�βολικό Ημίτονο Square Root Τετ�αγωνική �ίζα Sum Άθ�οισμα Tangent Εφαπτομένη Convert to Trigonometric Complex Form Μετατ�οπή σε τ�ιγωνομετ�ική μιγαδική μο�φή Turns Στ�οφές Hyperbolic Tangent Υπε�βολική Εφαπτομένη Sign-extend a value Επέκταση τιμής με π�όσημο Logical XOR Λογικό αποκλειστικό Ή FunctionsWidget Domain Τομέας All Όλα Name Όνομα Search Αναζήτηση No match found Δεν β�έθηκε αντιστοιχία Identifier Π�οσδιο�ιστικό HistoryWidget Remove All Calculations Above Αφαί�εση όλων των υπολογισμών επάνω Remove This Calculation Αφαί�εση αυτο� του υπολογισμο� Remove All Calculations Below Αφαί�εση όλων των υπολογισμών κάτω Keypad Inverse cosine Αντίστ�οφο συνημίτονο The last result Το τελευταίο αποτέλεσμα Inverse sine Αντίστ�οφο ημίτονο Inverse tangent Αντίστ�οφη εφαπτομένη Evaluate expression Υπολογισμός έκφ�ασης Division Διαί�εση Multiplication Πολλαπλασιασμός Subtraction Αφαί�εση Addition Π�όσθεση Clear expression Εκκαθά�ιση έκφ�ασης Cosine Συνημίτονο Backspace Οπισθοδιαγ�αφή Scientific notation Επιστημονική σημειογ�αφία Exponential Εκθετική Factorial Πα�αγοντικό Natural logarithm Φυσικός λογά�ιθμος Left parenthesis Α�ιστε�ή πα�ένθεση Nth root �ιοστή �ίζα Argument separator Διαχω�ιστικό ο�ισμάτων Square Τετ�άγωνο Common logarithm Κοινός λογά�ιθμος Modulo Υπόλοιπο Contextual percentage Ποσοστό με βάση τα συμφ�αζόμενα Power Ύψωση σε δ�ναμη Right parenthesis Δεξιά πα�ένθεση Sine Ημίτονο Square root Τετ�αγωνική Ρίζα Tangent Εφαπτομένη Pi Πι Decimal separator Δεκαδικό διαχω�ιστικό MainWindow Radian Ακτίνιο Degree Μοί�α Gradian Βαθμός grad Binary Δυαδικό Octal Οκταδικό Hexadecimal Δεκαεξαδικό Sexagesimal Εξηκονταδικό Engineering decimal Δεκαδικό μηχανικών Scientific decimal Επιστημονικό δεκαδικό &Import... &Εισαγωγή... &Quit &Έξοδος Clear E&xpression Εκκαθά�ιση έκ&φ�ασης Clear &History Εκκαθά�ιση &ιστο�ικο� &Copy &Αντιγ�αφή &Paste &Επικόλληση &Select Expression Ε&πιλογή έκφ�ασης &Constants &Σταθε�ές &Functions Σ&υνα�τήσεις &History &Ιστο�ικό &Status Bar Γ�αμμή &κατάστασης Bitfield Πεδίο bit Use&r Functions Συνα�τήσεις Χ&�ήστη &Degree &Μοί�ες &Radian &Ακτίνιο &Gradian &Βαθμός grad Re&volution &Πε�ιστ�οφή Auto-Insert a&ns Αυτόματη εισαγωγή a&ns Automatic &Completion Αυτόματη &συμπλή�ωση &Built-in Functions &Ενσωματωμένες συνα�τήσεις Built-in &Variables Ε&νσωματωμένες μεταβλητές User &Functions &Συνα�τήσεις χ�ήστη User Va&riables Με&ταβλητές χ�ήστη Open a Private Tab on Startup Άνοιγμα ιδιωτικής κα�τέλας κατά την εκκίνηση Open and focus a new private tab whenever SpeedCrunch starts. Άνοιγμα και εστίαση νέας ιδιωτικής κα�τέλας σε κάθε εκκίνηση του SpeedCrunch. Syntax &Highlighting Επισήμανση &σ�νταξης Group Digits in &Input &Ομαδοποίηση ψηφίων εισόδου Automatic Input &Adjustments &Αυτόματες π�οσα�μογές εισόδου Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Αυτόματη π�οσα�μογή τελεστών, διαστημάτων, πα�ενθέσεων και δυνάμεων και πε�ιο�ισμός της εισόδου σε έγκυ�ους χα�ακτή�ες. Group input digits using the selected number format. Ομαδοποίηση των ψηφίων εισόδου σ�μφωνα με την επιλεγμένη μο�φή α�ιθμών. &Blinking Cursor &Δ�ομέας που αναβοσβήνει Blink the cursor in the expression editor. Αναβόσβημα του δ�ομέα στον επεξε�γαστή πα�αστάσεων. &Escape Clears Editor Το &Escape καθα�ίζει τον επεξε�γαστή Clear the focused expression editor with Escape after dismissing any popup or preview. Καθα�ισμός του ενε�γο� επεξε�γαστή πα�αστάσεων με το Escape μετά το κλείσιμο τυχόν αναδυόμενων πα�αθ��ων ή π�οεπισκοπήσεων. Keep Expression After Evaluation Διατή�ηση πα�άστασης μετά τον υπολογισμό Copy New Results Automatically Αυτόματη αντιγ�αφή νέων αποτελεσμάτων &Comma &Κόμμα &System Default Π�οεπιλογή &συστήματος &Dot &Τελεία Dot &And Comma Τελεία &και κόμμα Toward +∞ (&ceil) Π�ος +∞ (&ceil) Toward −∞ (&floor) Π�ος −∞ (&floor) &Binary &Δυαδικό &Engineering &Μηχανικό &Hexadecimal &Δεκαεξαδική &Octal &Οκταδικό &Scientific &Επιστημονική User &Manual Εγχει�ίδιο &χ�ήστη Issues and &Feedback &Π�οβλήματα και σχόλια &Donate &Δω�εά &About SpeedCrunch &Σχετικά με το SpeedCrunch App Diag&nostics Δ&ιαγνωστικά εφα�μογής S&plit &Διαί�εση π�οβολής Angle &Mode Λε&ιτου�γία γωνιών &Complex Form &Μιγαδική μο�φή New Tab �έα κα�τέλα Constants Σταθε�ές Functions Συνα�τήσεις History Ιστο�ικό User Functions Συνα�τήσεις χ�ήστη &Font... &Γ�αμματοσει�ά... &Language... Γ&λώσσα... &Session &Συνεδ�ία &Edit &Επεξε�γασία &View &Π�οβολή Se&ttings &Ρυθμίσεις &Decimal &Δεκαδικό &Keypad &Πληκτ�ολόγιο Always on &Top Πάντα σε &π�ώτο πλάνο Disabled Ανενε�γό Small Space Μικ�ό Κενό Medium Space Μεσαίο Κενό Large Space Μεγάλο Κενό &0 Digits &0 Ψηφία &15 Digits &15 Ψηφία &2 Digits &2 Ψηφία &3 Digits &3 Ψηφία &50 Digits &50 Ψηφία &8 Digits &8 Ψηφία &Sexagesimal &Εξηκονταδικό Reset All Settings... Επαναφο�ά όλων των �υθμίσεων... &System &Σ�στημα SpeedCrunch &Theme &Θέμα SpeedCrunch &Classic &Κλασικό &Modern &Σ�γχ�ονο Context Help Βοήθεια Συμφ�αζομένων &Help &Βοήθεια Error Σφάλμα Can't read from file %1 Δεν είναι δυνατή η ανάγνωση από το α�χείο %1 Import Session Εισαγωγή συνεδ�ίας Close Session Κλείσιμο συνεδ�ίας Angle Mode: Λειτου�γία γωνίας: Notation: Συμβολισμός: Precision: Ακ�ίβεια: Turn Στ�οφή Revolution Πε�ιστ�οφή Fixed-point decimal Δεκαδικό σταθε�ής υποδιαστολής Rational Ρητός Automatic decimal Αυτόματο δεκαδικό Automatic Αυτόματο User &Definitions... &Ο�ισμοί χ�ήστη... New &Tab �έα &κα�τέλα New &Private Tab &�έα ιδιωτική κα�τέλα Keep Διατή�ηση Make Private... Μετατ�οπή σε ιδιωτική... New &Window �έο &πα�άθυ�ο &Open... &Άνοιγμα... &Rename... Με&τονομασία... Clo&ne... Κ&λωνοποίηση... &Close Tab Κλε&ίσιμο κα�τέλας Reopen Clo&sed Tab Επ&αναφο�ά κλειστής κα�τέλας Open Sessions &Folder Άνοιγμα &φακέλου συνεδ�ιών &Undo Α&ναί�εση &Redo Επαν&άληψη Cu&t Απ&οκοπή Copy &Last Result Αν&τιγ�αφή τελευταίου αποτελέσματος &Wrap in Parentheses Πε&�ικλείσιμο σε πα�ενθέσεις Full Scr&een Mode Λ&ειτου�γία πλή�ους οθόνης &Basic &Βασικό &Scientific (wide) &Επιστημονικό (πλατ�) Scientific (narrow) Επιστημονικό (στενό) &Custom... &Π�οσα�μοσμένο... Main &Menu Κ��ιο &μενο� User &Variables &Μεταβλητές χ�ήστη &Left &Α�ιστε�ά &Right &Δεξιά &Up &Πάνω &Down &Κάτω Close Pa&ne Κ&λείσιμο τμήματος User &Units &Μονάδες χ�ήστη &Turn &Στ�οφή If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Αν μια νέα έκφ�αση ξεκινά με +, -, * ή /, το SpeedCrunch εισάγει π�ώτα το "ans". &Accept with Enter &Αποδοχή με Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Αποδοχή της τ�έχουσας π�ότασης αυτόματης συμπλή�ωσης με Enter χω�ίς π�οηγο�μενη επιλογή της με τα πλήκτ�α βέλους. &Units &Μονάδες Show Live Result &Preview Εμφάνιση ζωντανής &π�οεπισκόπησης αποτελέσματος Save &Window Position on Exit Αποθήκευση &θέσης πα�αθ��ου κατά την έξοδο Hover Highlighting Επισήμανση στο πέ�ασμα του δείκτη Group Integer Part Only Ομαδοποίηση μόνο του ακέ�αιου μέ�ους Number Format... Μο�φή α�ιθμο�... Notation && Precision... Συμβολισμός && ακ�ίβεια... After pressing Enter, keep the entered expression selected in the editor. Μετά το πάτημα του Enter, διατή�ηση της εισαγμένης έκφ�ασης επιλεγμένης στον επεξε�γαστή. Never Ποτέ Always Πάντα Only for Single-Line Expressions Μόνο για εκφ�άσεις μίας γ�αμμής Simplify Displayed Expressions Απλοποίηση εμφανιζόμενων εκφ�άσεων History Size &Limit... Ό�ιο &μεγέθους ιστο�ικο�... Remove Trailing &Zeroes &Αφαί�εση τελικών μηδενικών Nearest, Half &Away (round) Πλησιέστε�ο, στη μέση &μακ�ιά (round) Nearest, Half &Even (roundeven) Πλησιέστε�ο, στη μέση π�ος &ά�τιο (roundeven) Toward &Zero (trunc) Π�ος το &μηδέν (trunc) &Fixed-Point &Σταθε�ή υποδιαστολή &Rational &Ρητός &Exponential (m·s�¹) &Εκθετική (m·s�¹) &Fractional (m/s) &Κλασματική (m/s) &Rectangular (a + bi) &Ο�θογώνια (a + bi) Exponential (re�ᶿ) Εκθετική (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Τ�ιγωνομετ�ική (r(cos θ + i·sin θ)) Phasor (r∠θ) Φασική μο�φή (r∠θ) &Theme... &Θέμα... Check for &Updates Έλεγχος για &ενημε�ώσεις Source Code Πηγαίος κώδικας &Zoom &Ζουμ &Results &Αποτελέσματα Unit Notation Συμβολισμός μονάδων Rounding Mode Λειτου�γία στ�ογγυλοποίησης &Notation &Συμβολισμός &Imaginary Unit &Φανταστική μονάδα &Window &Πα�άθυ�ο &Editing &Επεξε�γασία A&utocomplete Α&υτόματη συμπλή�ωση Up/Down Arrow History Ιστο�ικό με βέλη επάνω/κάτω &Appearance &Εμφάνιση &Menus &Μενο� &Docks Π&�οσα�τώμενοι πίνακες &Input and Results &Είσοδος και αποτελέσματα &Disabled &Απενε�γοποιημένο &Disable &Απενε�γοποίηση Close preview Κλείσιμο π�οεπισκόπησης Rename... Μετονομασία... Clone... Κλωνοποίηση... Close Tab Κλείσιμο κα�τέλας New Private Tab �έα ιδιωτική κα�τέλα Open... Άνοιγμα... Reopen Closed Tab Επαναφο�ά κλειστής κα�τέλας Split Διαί�εση π�οβολής Left Α�ιστε�ά Right Δεξιά Up Πάνω Down Κάτω Clear Εκκαθά�ιση Delete Διαγ�αφή %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Ιδιωτική συνεδ�ία: το πε�ιεχόμενο απο��ίπτεται κατά το κλείσιμο. Επιλέξτε Συνεδ�ία > Διατή�ηση για μετατ�οπή σε κανονική συνεδ�ία. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Ιδιωτική] Reset All Settings Επαναφο�ά όλων των �υθμίσεων Reset all settings to their default values? Επαναφο�ά όλων των �υθμίσεων στις π�οεπιλεγμένες τιμές τους? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Πε�ιλαμβάνονται η εμφάνιση, η επεξε�γασία, οι μο�φές αποτελεσμάτων και οι π�οτιμήσεις πα�αθ��ων. Οι υπολογισμοί, οι ανοιχτές συνεδ�ίες και οι ο�ισμοί χ�ήστη θα διατη�ηθο�ν. The settings file could not be written. Δεν ήταν δυνατή η εγγ�αφή του α�χείου �υθμίσεων. Clear this session's calculations, unfinished expression, variables, functions, and units? Εκκαθά�ιση των υπολογισμών, της ημιτελο�ς πα�άστασης, των μεταβλητών, των συνα�τήσεων και των μονάδων αυτής της συνεδ�ίας? Global user definitions are kept. Οι καθολικοί ο�ισμοί χ�ήστη διατη�ο�νται. Make Session Private Μετατ�οπή συνεδ�ίας σε ιδιωτική The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Η αποθηκευμένη συνεδ�ία %1 θα διαγ�αφεί. Το πε�ιεχόμενό της θα πα�αμείνει ανοιχτό σε ιδιωτική συνεδ�ία και θα απο��ιφθεί όταν κλείσει αυτή η συνεδ�ία ή το SpeedCrunch. Make Private Μετατ�οπή σε ιδιωτική Could not delete the saved session %1. Δεν ήταν δυνατή η διαγ�αφή της αποθηκευμένης συνεδ�ίας %1. Keep Session Διατή�ηση συνεδ�ίας Could not save the session. It remains private. Δεν ήταν δυνατή η αποθήκευση της συνεδ�ίας. Πα�αμένει ιδιωτική. Clone Session Κλωνοποίηση συνεδ�ίας Could not save session file %1. Δεν ήταν δυνατή η αποθήκευση του α�χείου συνεδ�ίας %1. Could not delete session file %1. Δεν ήταν δυνατή η διαγ�αφή του α�χείου συνεδ�ίας %1. JSON file (*.json);;Any file (*.*) Α�χείο JSON (*.json);;Οποιοδήποτε α�χείο (*.*) Export session as JSON Εξαγωγή συνεδ�ίας ως JSON The selected file is not valid JSON: %1 Το επιλεγμένο α�χείο δεν είναι έγκυ�ο JSON: %1 The selected file is not a SpeedCrunch session JSON file. Το επιλεγμένο α�χείο δεν είναι α�χείο JSON συνεδ�ίας SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Αυτό το α�χείο χ�ησιμοποιεί πα�ωχημένη μο�φή συνεδ�ίας SpeedCrunch και δεν μπο�εί να εισαχθεί. The selected JSON file is missing the required $schema field. Από το επιλεγμένο α�χείο JSON λείπει το απαιτο�μενο πεδίο $schema. The selected JSON file uses an unsupported JSON schema: %1 Το επιλεγμένο α�χείο JSON χ�ησιμοποιεί μη υποστη�ιζόμενο σχήμα JSON: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Από το επιλεγμένο α�χείο JSON λείπει το αναγνω�ιστικό σχήματος συνεδ�ίας SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Το επιλεγμένο α�χείο JSON χ�ησιμοποιεί μη υποστη�ιζόμενη μο�φή συνεδ�ίας SpeedCrunch: %1 The selected JSON file is missing the required session name. Από το επιλεγμένο α�χείο JSON λείπει το απαιτο�μενο όνομα συνεδ�ίας. The selected JSON file has an empty session name. Το επιλεγμένο α�χείο JSON έχει κενό όνομα συνεδ�ίας. The selected JSON file has invalid or incomplete SpeedCrunch session data. Το επιλεγμένο α�χείο JSON έχει μη έγκυ�α ή ελλιπή δεδομένα συνεδ�ίας SpeedCrunch. Open Sessions Folder Άνοιγμα φακέλου συνεδ�ιών Could not create the sessions folder: %1 Δεν ήταν δυνατή η δημιου�γία του φακέλου συνεδ�ιών: %1 Could not open the sessions folder: %1 Δεν ήταν δυνατό το άνοιγμα του φακέλου συνεδ�ιών: %1 Editor and Results Font Γ�αμματοσει�ά επεξε�γαστή και αποτελεσμάτων Open Session Άνοιγμα συνεδ�ίας Community Κοινότητα Rename Session Μετονομασία συνεδ�ίας Clear Session Εκκαθά�ιση συνεδ�ίας Delete Session Διαγ�αφή συνεδ�ίας Close Pane Κλείσιμο τμήματος User Variables Μεταβλητές χ�ήστη User Units Μονάδες χ�ήστη Clear History Εκκαθά�ιση ιστο�ικο� Are you sure you want to clear the calculation history? Είστε βέβαιοι ότι θέλετε να εκκαθα�ίσετε το ιστο�ικό υπολογισμών; Session name: Όνομα συνεδ�ίας: A session named %1 already exists. Υπά�χει ήδη συνεδ�ία με όνομα %1. Could not create session file %1. Δεν ήταν δυνατή η δημιου�γία του α�χείου συνεδ�ίας %1. Could not write session file %1. Δεν ήταν δυνατή η εγγ�αφή του α�χείου συνεδ�ίας %1. Are you sure you want to delete this session? Είστε βέβαιοι ότι θέλετε να διαγ�άψετε αυτήν τη συνεδ�ία; Custom Precision Π�οσα�μοσμένη ακ�ίβεια Fractional digits: Ψηφία κλασματικο� μέ�ους: Theme Θέμα Light Themes Ανοιχτόχ�ωμα θέματα Dark Themes Σκο��α θέματα Preview Π�οεπισκόπηση Colors Χ�ώματα Select color for %1 Επιλογή χ�ώματος για %1 Import... Εισαγωγή... Export... Εξαγωγή... Import Theme Εισαγωγή θέματος Theme file (*.json);;All files (*) Α�χείο θέματος (*.json);;Όλα τα α�χεία (*) Invalid theme file. Μη έγκυ�ο α�χείο θέματος. Can't import theme "%1" because it conflicts with a built-in theme. Δεν είναι δυνατή η εισαγωγή του θέματος "%1" επειδή συγκ�ο�εται με ενσωματωμένο θέμα. Can't find a writable theme folder. Δεν β�έθηκε εγγ�άψιμος φάκελος θεμάτων. Overwrite Theme Αντικατάσταση θέματος A custom theme named "%1" already exists. Do you want to overwrite it? Υπά�χει ήδη π�οσα�μοσμένο θέμα με όνομα "%1". Θέλετε να το αντικαταστήσετε; Can't overwrite theme file %1 Δεν είναι δυνατή η αντικατάσταση του α�χείου θέματος %1 Can't copy theme file to %1 Δεν είναι δυνατή η αντιγ�αφή του α�χείου θέματος στο %1 Export Theme Εξαγωγή θέματος Can't export theme as "%1" because it conflicts with a built-in theme. Δεν είναι δυνατή η εξαγωγή του θέματος ως "%1" επειδή συγκ�ο�εται με ενσωματωμένο θέμα. Can't write to file %1 Αδυναμία εγγ�αφής στο α�χείο %1 Global User Variable Καθολική μεταβλητή χ�ήστη Global User Function Καθολική συνά�τηση χ�ήστη Global User Unit Καθολική μονάδα χ�ήστη User Definitions Ο�ισμοί χ�ήστη These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Αυτοί οι ο�ισμοί είναι καθολικοί και φο�τώνονται σε κάθε συνεδ�ία. Δεν μπο�ο�ν να τ�οποποιηθο�ν μέσα στις συνεδ�ίες και υπε�ισχ�ουν των ο�ισμών με το ίδιο όνομα από τον επεξε�γαστή της συνεδ�ίας. Εισαγάγετε έναν ο�ισμό ανά γ�αμμή. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Πα�αδείγματα: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Εφα�μογή Validate Επικ��ωση Test Results Αποτελέσματα δοκιμής Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Εισαγόμενες μεταβλητές: %1 Εισαγόμενες συνα�τήσεις: %2 Εισαγόμενες μονάδες: %3 Α�ιθμοί γ�αμμών με σφάλματα: %4 none κανένας Apply Results Αποτελέσματα εφα�μογής User definitions saved. Οι ο�ισμοί χ�ήστη αποθηκε�τηκαν. History Size Limit Ό�ιο μεγέθους ιστο�ικο� Maximum number of history entries for this session (0 = unlimited): Μέγιστος α�ιθμός καταχω�ίσεων ιστο�ικο� για αυτήν τη συνεδ�ία (0 = απε�ιό�ιστο): Text file (*.txt);;Any file (*.*) Α�χείο κειμένου (*.txt);;Όλα τα α�χεία (*.*) Could not recalculate from calculation %1: %2 Δεν ήταν δυνατός ο επανυπολογισμός από τον υπολογισμό %1: %2 History Size Limit Reached Το ό�ιο μεγέθους ιστο�ικο� συμπλη�ώθηκε This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Αυτός ο υπολογισμός καταλαμβάνει την τελευταία διαθέσιμη θέση ιστο�ικο�. Οι μελλοντικοί υπολογισμοί θα αφαι�ο�ν τον παλαιότε�ο υπολογισμό από το ιστο�ικό. Μπο�είτε να αυξήσετε το ό�ιο από Συνεδ�ία > Ό�ιο μεγέθους ιστο�ικο�. Editing calculation. Press Esc twice to cancel. Επεξε�γασία υπολογισμο�. Πατήστε Esc δ�ο φο�ές για ακ��ωση. Calculation Settings Ρυθμίσεις υπολογισμο� Invalid recalculation start index Μη έγκυ�ος α�χικός δείκτης επανυπολογισμο� System Default Π�οεπιλογή συστήματος Language Γλώσσα Select the language: Επιλογή γλώσσας: Custom Π�οσα�μοσμένο Decimal places: Δεκαδικά ψηφία: &Automatic &Αυτόματο &Precision &Ακ�ίβεια Plain &text Απλό &κείμενο Formula &Book Βιβλίο &τ�πων &Export &Εξαγωγή Export session as HTML Εξαγωγή συνεδ�ίας ως HTML HTML file (*.html) Α�χείο HTML (*.html) Export session as plain text Εξαγωγή συνεδ�ίας ως απλό κείμενο ManualWindow SpeedCrunch Manual Εγχει�ίδιο SpeedCrunch %1 - SpeedCrunch Manual %1 - Εγχει�ίδιο SpeedCrunch NumberFormatDialog Number Format Μο�φή α�ιθμο� <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Επιλέξτε τη μο�φή α�ιθμών για τα αποτελέσματα και την ομαδοποίηση ψηφίων εισόδου.</b><br/><br/>Σημείωση: στα εισαγόμενα α�ιθμητικά δεδομένα γίνονται δεκτές σαφείς μο�φές, ακόμη κι αν διαφέ�ουν από την επιλεγμένη μο�φή εμφάνισης.<br/> QObject Global User Variable Καθολική μεταβλητή χ�ήστη Global User Function Καθολική συνά�τηση χ�ήστη Global User Unit Καθολική μονάδα χ�ήστη Backspace Οπισθοδιαγ�αφή Clear expression Εκκαθά�ιση έκφ�ασης Evaluate expression Υπολογισμός έκφ�ασης Insert text Εισαγωγή κειμένου Automatic decimal Αυτόματο δεκαδικό Fixed-point decimal Δεκαδικό σταθε�ής υποδιαστολής Engineering decimal Δεκαδικό μηχανικών Scientific decimal Επιστημονικό δεκαδικό Rational Ρητός Binary Δυαδικό Octal Οκταδικό Hexadecimal Δεκαεξαδικό Sexagesimal Εξηκονταδικό Update Available Διαθέσιμη ενημέ�ωση A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Διατίθεται νεότε�η έκδοση (%1).<br/><a href="%2">Επισκεφθείτε τον ιστότοπο για λήψη.</a> Check for Updates Έλεγχος για ενημε�ώσεις SpeedCrunch %1 is up to date. Το SpeedCrunch %1 είναι ενημε�ωμένο. No connectivity. Please check your internet connection and try again. Δεν υπά�χει σ�νδεση. Ελέγξτε τη σ�νδεσή σας στο διαδίκτυο και δοκιμάστε ξανά. Could not verify the latest available version. Δεν ήταν δυνατή η επαλήθευση της πιο π�όσφατης διαθέσιμης έκδοσης. ResultDisplay Scroll to bottom Κ�λιση στο τέλος Edit Expression Επεξε�γασία έκφ�ασης Change Settings Αλλαγή �υθμίσεων New Tab �έα κα�τέλα &Import... &Εισαγωγή... &Export &Εξαγωγή Plain &text Απλό &κείμενο Copy Αντιγ�αφή Selection Επιλογή Select All Επιλογή όλων Expression Πα�άσταση Result Αποτέλεσμα Calculation Υπολογισμός Calculation as Single Line Υπολογισμός σε μία γ�αμμή Remove Αφαί�εση This Calculation Αυτός ο υπολογισμός All Calculations Above Όλοι οι υπολογισμοί από πάνω All Calculations Below Όλοι οι υπολογισμοί από κάτω New Private Tab �έα ιδιωτική κα�τέλα Session Συνεδ�ία Open... Άνοιγμα... Clone... Κλωνοποίηση... Rename... Μετονομασία... Keep Διατή�ηση Make Private... Μετατ�οπή σε ιδιωτική... Clear Εκκαθά�ιση Delete Διαγ�αφή Close Κλείσιμο Split Διαί�εση π�οβολής Left Α�ιστε�ά Right Δεξιά Up Πάνω Down Κάτω Close Pane Κλείσιμο τμήματος Main Menu Κ��ιο μενο� Cancel editing Ακ��ωση επεξε�γασίας Copy result Αντιγ�αφή αποτελέσματος Edit expression Επεξε�γασία έκφ�ασης Change settings Αλλαγή �υθμίσεων Remove calculation Αφαί�εση υπολογισμο� ResultSlotsDialog Notation & Precision Συμβολισμός & ακ�ίβεια Result Line Γ�αμμή αποτελέσματος Enabled Ενε�γό Notation Συμβολισμός Decimal Places Δεκαδικά ψηφία Main Line Κ��ια γ�αμμή Extra Line #1 Επιπλέον γ�αμμή #1 Extra Line #2 Επιπλέον γ�αμμή #2 Extra Line #3 Επιπλέον γ�αμμή #3 Extra Line #4 Επιπλέον γ�αμμή #4 Auto Αυτόματο UserFunctionListWidget Name Όνομα Value Τιμή Description Πε�ιγ�αφή Search Αναζήτηση No match found Δεν β�έθηκε αντιστοιχία Insert Εισαγωγή Edit Επεξε�γασία Delete Διαγ�αφή Delete All Διαγ�αφή όλων UserUnitListWidget Name Όνομα Value Τιμή Description Πε�ιγ�αφή Search Αναζήτηση No match found Δεν β�έθηκε αντιστοιχία Insert Εισαγωγή Edit Επεξε�γασία Delete Διαγ�αφή Delete All Διαγ�αφή όλων VariableListWidget Name Όνομα Value Τιμή Description Πε�ιγ�αφή Search Αναζήτηση No match found Δεν β�έθηκε αντιστοιχία Insert Εισαγωγή Edit Επεξε�γασία Delete Διαγ�αφή Delete All Διαγ�αφή όλων heldercorreia-speedcrunch-e7ca37f/src/resources/locale/en_GB.ts000066400000000000000000010423161526573132500247260ustar00rootroot00000000000000 AboutBox About SpeedCrunch About SpeedCrunch Core developers Core developers Original author Original author Close Close Math engine Maths engine Main author | Logo | Maintainer Main author | Logo | Maintainer Thanks Thanks Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 The SpeedCrunch developers This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. BitFieldWidget Reset bits to zero Reset bits to zero Invert bits Invert bits Shift bits left Shift bits left Shift bits right Shift bits right Book Index Index Algebra Algebra Quadratic Equation Quadratic Equation Logarithmic Base Conversion Logarithmic Base Conversion Geometry Geometry Circle Circle Sector Sector Sphere Sphere Cube Cube Cone Cone Cylinder Cylinder Electronics Electronics Ohm's Law Ohm's Law Power Power Reactance Reactance Resonance Resonance Radio Frequency Radio Frequency Antennas Antennas Characteristic Impedance (coax) Characteristic Impedance (coax) Velocity of Propagation (coax) Velocity of Propagation (coax) Standing Wave Ratio & Return Loss Standing Wave Ratio & Return Loss Free Space Wavelength Free Space Wavelength resistance resistance voltage voltage current current power power inductive reactance inductive reactance capacitive reactance capacitive reactance inductance inductance capacitance capacitance frequency frequency resonance frequency resonant frequency area area perimeter perimeter diameter diameter radius radius volume volume surface area surface area height height slant height slant height face diagonal face diagonal space diagonal space diagonal edge length edge length arc length arc length central angle (degrees) central angle (degrees) input power input power reflected power reflected power transmitted power transmitted power return loss return loss dielectric constant dielectric constant outer conductor's inner diameter outer conductor's inner diameter inner conductor's outer diameter inner conductor's outer diameter speed of light speed of light reflection coefficient reflection coefficient standing wave ratio standing wave ratio normalized impedance normalised impedance frequency (Hz) frequency (Hz) BookDock Formula Book Formula Book ConstantCompletion Search constants Search constants No match found No match found Constants Mathematics Mathematics Physics (CODATA 2022) Physics (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chemistry (IUPAC - CIAAW 2021) Uncategorized Uncategorized Universal Universal Physicochemical Physicochemical Atomic & Nuclear — General Atomic & Nuclear — General Atomic & Nuclear — Electroweak Atomic & Nuclear — Electroweak Atomic & Nuclear — Electron Atomic & Nuclear — Electron Atomic & Nuclear — Muon Atomic & Nuclear — Muon Atomic & Nuclear — Tau Atomic & Nuclear — Tau Atomic & Nuclear — Proton Atomic & Nuclear — Proton Atomic & Nuclear — Neutron Atomic & Nuclear — Neutron Atomic & Nuclear — Deuteron Atomic & Nuclear — Deuteron Atomic & Nuclear — Triton Atomic & Nuclear — Triton Atomic & Nuclear — Helion Atomic & Nuclear — Helion Atomic & Nuclear — Alpha particle Atomic & Nuclear — Alpha particle Atomic & Nuclear — Atomic units Atomic & Nuclear — Atomic units Atomic & Nuclear — Energy conversion relationships Atomic & Nuclear — Energy conversion relationships Atomic & Nuclear — X-ray units Atomic & Nuclear — X-ray units Atomic & Nuclear — Magnetic shielding corrections Atomic & Nuclear — Magnetic shielding corrections Masses Masses Lifetimes Lifetimes Molar Masses Molar Masses Electronegativity Electronegativity Ionization Energy Ionisation Energy Nominal Constants (IAU 2015) Nominal Constants (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Current Best Estimates (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) characteristic impedance of vacuum (Z₀) reduced Planck constant (�) reduced Planck constant (�) vacuum electric permittivity (ϵ₀) vacuum electric permittivity (ϵ₀) Newtonian constant of gravitation (G) Newtonian constant of gravitation (G) vacuum magnetic permeability (μ₀) vacuum magnetic permeability (μ₀) Planck constant (h) Planck constant (h) speed of light in vacuum (c) speed of light in vacuum (c) standard acceleration of gravity (gₙ) standard acceleration of gravity (gₙ) Newtonian constant of gravitation over h-bar c Newtonian constant of gravitation over h-bar c Planck length Planck length Planck constant in eV/Hz (h) Planck constant in eV/Hz (h) Planck mass Planck mass Planck mass energy equivalent in GeV Planck mass energy equivalent in GeV Planck temperature Planck temperature Planck time Planck time reduced Planck constant in eV·s (�) reduced Planck constant in eV·s (�) reduced Planck constant times c in MeV·fm reduced Planck constant times c in MeV·fm Bohr magneton Bohr magneton conductance quantum (G₀) conductance quantum (G₀) Coulomb constant (kₑ) Coulomb constant (kₑ) elementary charge (e) elementary charge (e) elementary charge over h-bar elementary charge over h-bar conventional value of Josephson constant conventional value of Josephson constant Josephson constant Josephson constant conventional value of ampere-90 conventional value of ampere-90 conventional value of coulomb-90 conventional value of coulomb-90 conventional value of farad-90 conventional value of farad-90 conventional value of henry-90 conventional value of henry-90 conventional value of ohm-90 conventional value of ohm-90 conventional value of volt-90 conventional value of volt-90 conventional value of watt-90 conventional value of watt-90 magnetic flux quantum (Φ₀) magnetic flux quantum (Φ₀) nuclear magneton nuclear magneton inverse of conductance quantum inverse of conductance quantum conventional value of von Klitzing constant conventional value of von Klitzing constant von Klitzing constant von Klitzing constant atomic unit of magnetic dipole moment atomic unit of magnetic dipole moment atomic unit of magnetic flux density atomic unit of magnetic flux density Bohr magneton in eV/T Bohr magneton in eV/T Bohr magneton in Hz/T Bohr magneton in Hz/T Bohr magneton in inverse meter per tesla Bohr magneton in inverse metre per tesla Bohr magneton in K/T Bohr magneton in K/T nuclear magneton in eV/T nuclear magneton in eV/T nuclear magneton in inverse meter per tesla nuclear magneton in inverse metre per tesla nuclear magneton in K/T nuclear magneton in K/T nuclear magneton in MHz/T nuclear magneton in MHz/T Bohr radius (a₀) Bohr radius (a₀) fine-structure constant (α) fine-structure constant (α) Hartree energy (Eₕ) Hartree energy (Eₕ) Hartree energy in eV Hartree energy in eV quantum of circulation quantum of circulation quantum of circulation times 2 quantum of circulation times 2 Rydberg constant (R∞) Rydberg constant (R∞) atomic mass unit-hartree relationship atomic mass unit-hartree relationship atomic mass unit-hertz relationship atomic mass unit-hertz relationship atomic mass unit-inverse meter relationship atomic mass unit-inverse metre relationship atomic mass unit-joule relationship atomic mass unit-joule relationship atomic mass unit-kelvin relationship atomic mass unit-kelvin relationship atomic mass unit-kilogram relationship atomic mass unit-kilogram relationship atomic unit of 1st hyperpolarizability atomic unit of 1st hyperpolarizability atomic unit of 2nd hyperpolarizability atomic unit of 2nd hyperpolarizability atomic unit of charge (e) atomic unit of charge (e) atomic unit of charge density atomic unit of charge density atomic unit of current atomic unit of current atomic unit of electric dipole moment atomic unit of electric dipole moment atomic unit of electric field atomic unit of electric field atomic unit of electric field gradient atomic unit of electric field gradient atomic unit of electric polarizability atomic unit of electric polarizability atomic unit of electric potential atomic unit of electric potential atomic unit of electric quadrupole moment atomic unit of electric quadrupole moment atomic unit of action atomic unit of action atomic unit of energy atomic unit of energy atomic unit of force atomic unit of force atomic unit of length atomic unit of length hertz-atomic mass unit relationship hertz-atomic mass unit relationship hertz-electron volt relationship hertz-electron volt relationship hertz-hartree relationship hertz-hartree relationship hertz-inverse meter relationship hertz-inverse metre relationship hertz-joule relationship hertz-joule relationship hertz-kelvin relationship hertz-kelvin relationship hertz-kilogram relationship hertz-kilogram relationship hyperfine transition frequency of Cs-133 hyperfine transition frequency of Cs-133 inverse fine-structure constant (α�¹) inverse fine-structure constant (α�¹) inverse meter-atomic mass unit relationship inverse metre-atomic mass unit relationship inverse meter-electron volt relationship inverse metre-electron volt relationship inverse meter-hartree relationship inverse metre-hartree relationship inverse meter-hertz relationship inverse metre-hertz relationship inverse meter-joule relationship inverse metre-joule relationship inverse meter-kelvin relationship inverse metre-kelvin relationship inverse meter-kilogram relationship inverse metre-kilogram relationship joule-atomic mass unit relationship joule-atomic mass unit relationship joule-electron volt relationship joule-electron volt relationship joule-hertz relationship joule-hertz relationship joule-hartree relationship joule-hartree relationship joule-inverse meter relationship joule-inverse metre relationship joule-kelvin relationship joule-kelvin relationship joule-kilogram relationship joule-kilogram relationship kelvin-atomic mass unit relationship kelvin-atomic mass unit relationship kelvin-electron volt relationship kelvin-electron volt relationship kelvin-hertz relationship kelvin-hertz relationship kelvin-hartree relationship kelvin-hartree relationship kelvin-inverse meter relationship kelvin-inverse metre relationship kelvin-joule relationship kelvin-joule relationship kelvin-kilogram relationship kelvin-kilogram relationship kilogram-atomic mass unit relationship kilogram-atomic mass unit relationship kilogram-electron volt relationship kilogram-electron volt relationship kilogram-hertz relationship kilogram-hertz relationship kilogram-hartree relationship kilogram-hartree relationship kilogram-inverse meter relationship kilogram-inverse metre relationship kilogram-joule relationship kilogram-joule relationship kilogram-kelvin relationship kilogram-kelvin relationship lattice parameter of silicon (a) lattice parameter of silicon (a) luminous efficacy luminous efficacy natural unit of energy natural unit of energy natural unit of energy in MeV natural unit of energy in MeV natural unit of action (�) natural unit of action (�) natural unit of action in eV·s natural unit of action in eV·s natural unit of length natural unit of length natural unit of mass natural unit of mass natural unit of momentum natural unit of momentum natural unit of momentum in MeV/c natural unit of momentum in MeV/c natural unit of time natural unit of time natural unit of velocity natural unit of velocity Rydberg constant times c in Hz Rydberg constant times c in Hz Rydberg constant times hc in eV Rydberg constant times hc in eV Rydberg constant times hc in J Rydberg constant times hc in J Fermi coupling constant Fermi coupling constant weak mixing angle weak mixing angle W to Z mass ratio W to Z mass ratio Thomson cross section (σₑ) Thomson cross section (σₑ) electron mass (mₑ) electron mass (mₑ) electron mass in u electron mass in u electron mass energy equivalent (mₑ·c²) electron mass energy equivalent (mₑ·c²) electron mass energy equivalent in MeV electron mass energy equivalent in MeV reduced Compton wavelength reduced Compton wavelength classical electron radius (rₑ) classical electron radius (rₑ) electron charge to mass quotient electron charge to mass quotient electron-deuteron magnetic moment ratio electron-deuteron magnetic moment ratio electron-deuteron mass ratio electron-deuteron mass ratio electron g factor (gₑ) electron g factor (gₑ) electron gyromagnetic ratio (γₑ) electron gyromagnetic ratio (γₑ) electron gyromagnetic ratio in MHz/T electron gyromagnetic ratio in MHz/T electron-helion mass ratio electron-helion mass ratio electron magnetic moment (μₑ) electron magnetic moment (μₑ) electron magnetic moment anomaly (aₑ) electron magnetic moment anomaly (aₑ) electron magnetic moment to Bohr magneton ratio electron magnetic moment to Bohr magneton ratio electron magnetic moment to nuclear magneton ratio electron magnetic moment to nuclear magneton ratio electron molar mass (Mₑ) electron molar mass (Mₑ) electron-muon magnetic moment ratio electron-muon magnetic moment ratio electron-muon mass ratio electron-muon mass ratio electron-neutron magnetic moment ratio electron-neutron magnetic moment ratio electron-neutron mass ratio electron-neutron mass ratio electron-proton magnetic moment ratio electron-proton magnetic moment ratio electron-proton mass ratio electron-proton mass ratio electron relative atomic mass (Ar(e)) electron relative atomic mass (Ar(e)) electron-tau mass ratio electron-tau mass ratio electron to alpha particle mass ratio electron to alpha particle mass ratio electron to shielded helion magnetic moment ratio electron to shielded helion magnetic moment ratio electron to shielded proton magnetic moment ratio electron to shielded proton magnetic moment ratio electron-triton mass ratio electron-triton mass ratio electron volt-atomic mass unit relationship electron volt-atomic mass unit relationship electron volt-hartree relationship electron volt-hartree relationship electron volt-hertz relationship electron volt-hertz relationship electron volt-inverse meter relationship electron volt-inverse metre relationship electron volt-joule relationship electron volt-joule relationship electron volt-kelvin relationship electron volt-kelvin relationship electron volt-kilogram relationship electron volt-kilogram relationship hartree-atomic mass unit relationship hartree-atomic mass unit relationship hartree-electron volt relationship hartree-electron volt relationship muon Compton wavelength muon Compton wavelength muon-electron mass ratio muon-electron mass ratio muon g factor muon g factor muon magnetic moment muon magnetic moment muon magnetic moment anomaly muon magnetic moment anomaly muon magnetic moment to Bohr magneton ratio muon magnetic moment to Bohr magneton ratio muon magnetic moment to nuclear magneton ratio muon magnetic moment to nuclear magneton ratio muon mass muon mass muon mass energy equivalent muon mass energy equivalent muon mass energy equivalent in MeV muon mass energy equivalent in MeV muon mass in u muon mass in u muon molar mass muon molar mass muon-neutron mass ratio muon-neutron mass ratio muon-proton magnetic moment ratio muon-proton magnetic moment ratio muon-proton mass ratio muon-proton mass ratio muon-tau mass ratio muon-tau mass ratio reduced muon Compton wavelength reduced muon Compton wavelength reduced tau Compton wavelength reduced tau Compton wavelength tau Compton wavelength tau Compton wavelength tau-electron mass ratio tau-electron mass ratio tau mass tau mass tau mass energy equivalent tau mass energy equivalent tau mass in u tau mass in u tau molar mass tau molar mass tau-muon mass ratio tau-muon mass ratio tau-neutron mass ratio tau-neutron mass ratio tau-proton mass ratio tau-proton mass ratio proton charge to mass quotient proton charge to mass quotient proton Compton wavelength proton Compton wavelength proton-electron mass ratio proton-electron mass ratio proton g factor (gₚ) proton g factor (gₚ) proton gyromagnetic ratio (γₚ) proton gyromagnetic ratio (γₚ) proton gyromagnetic ratio in MHz/T proton gyromagnetic ratio in MHz/T proton magnetic moment (μₚ) proton magnetic moment (μₚ) proton magnetic moment to Bohr magneton ratio proton magnetic moment to Bohr magneton ratio proton magnetic moment to nuclear magneton ratio proton magnetic moment to nuclear magneton ratio proton magnetic shielding correction proton magnetic shielding correction proton mass (mₚ) proton mass (mₚ) proton mass energy equivalent proton mass energy equivalent proton mass energy equivalent in MeV proton mass energy equivalent in MeV proton mass in u proton mass in u proton molar mass (Mₚ) proton molar mass (Mₚ) proton-muon mass ratio proton-muon mass ratio proton-neutron magnetic moment ratio proton-neutron magnetic moment ratio proton-neutron mass ratio proton-neutron mass ratio proton relative atomic mass (Ar(p)) proton relative atomic mass (Ar(p)) proton rms charge radius proton rms charge radius proton-tau mass ratio proton-tau mass ratio reduced proton Compton wavelength reduced proton Compton wavelength shielded proton gyromagnetic ratio shielded proton gyromagnetic ratio shielded proton gyromagnetic ratio in MHz/T shielded proton gyromagnetic ratio in MHz/T shielded proton magnetic moment shielded proton magnetic moment shielded proton magnetic moment to Bohr magneton ratio shielded proton magnetic moment to Bohr magneton ratio shielded proton magnetic moment to nuclear magneton ratio shielded proton magnetic moment to nuclear magneton ratio neutron Compton wavelength neutron Compton wavelength neutron-electron magnetic moment ratio neutron-electron magnetic moment ratio neutron-electron mass ratio neutron-electron mass ratio neutron g factor (gₙ) neutron g factor (gₙ) neutron gyromagnetic ratio (γₙ) neutron gyromagnetic ratio (γₙ) neutron gyromagnetic ratio in MHz/T neutron gyromagnetic ratio in MHz/T neutron magnetic moment (μₙ) neutron magnetic moment (μₙ) neutron magnetic moment to Bohr magneton ratio neutron magnetic moment to Bohr magneton ratio neutron magnetic moment to nuclear magneton ratio neutron magnetic moment to nuclear magneton ratio neutron mass (mₙ) neutron mass (mₙ) neutron mass energy equivalent neutron mass energy equivalent neutron mass energy equivalent in MeV neutron mass energy equivalent in MeV neutron mass in u neutron mass in u neutron molar mass (Mₙ) neutron molar mass (Mₙ) neutron-muon mass ratio neutron-muon mass ratio neutron-proton magnetic moment ratio neutron-proton magnetic moment ratio neutron-proton mass difference neutron-proton mass difference neutron-proton mass difference energy equivalent neutron-proton mass difference energy equivalent neutron-proton mass difference energy equivalent in MeV neutron-proton mass difference energy equivalent in MeV neutron-proton mass difference in u neutron-proton mass difference in u neutron-proton mass ratio neutron-proton mass ratio neutron relative atomic mass (Ar(n)) neutron relative atomic mass (Ar(n)) neutron-tau mass ratio neutron-tau mass ratio neutron to shielded proton magnetic moment ratio neutron to shielded proton magnetic moment ratio reduced neutron Compton wavelength reduced neutron Compton wavelength deuteron-electron magnetic moment ratio deuteron-electron magnetic moment ratio deuteron-electron mass ratio deuteron-electron mass ratio deuteron g factor deuteron g factor deuteron magnetic moment deuteron magnetic moment deuteron magnetic moment to Bohr magneton ratio deuteron magnetic moment to Bohr magneton ratio deuteron magnetic moment to nuclear magneton ratio deuteron magnetic moment to nuclear magneton ratio deuteron mass deuteron mass deuteron mass energy equivalent deuteron mass energy equivalent deuteron mass energy equivalent in MeV deuteron mass energy equivalent in MeV deuteron mass in u deuteron mass in u deuteron molar mass deuteron molar mass deuteron-neutron magnetic moment ratio deuteron-neutron magnetic moment ratio deuteron-proton magnetic moment ratio deuteron-proton magnetic moment ratio deuteron-proton mass ratio deuteron-proton mass ratio deuteron relative atomic mass (Ar(d)) deuteron relative atomic mass (Ar(d)) deuteron rms charge radius deuteron rms charge radius triton-electron mass ratio triton-electron mass ratio triton g factor (gₜ) triton g factor (gₜ) triton magnetic moment (μₜ) triton magnetic moment (μₜ) triton magnetic moment to Bohr magneton ratio triton magnetic moment to Bohr magneton ratio triton magnetic moment to nuclear magneton ratio triton magnetic moment to nuclear magneton ratio triton mass (mₜ) triton mass (mₜ) triton mass energy equivalent triton mass energy equivalent triton mass energy equivalent in MeV triton mass energy equivalent in MeV triton mass in u triton mass in u triton molar mass (Mₜ) triton molar mass (Mₜ) triton-proton mass ratio triton-proton mass ratio triton relative atomic mass (Ar(t)) triton relative atomic mass (Ar(t)) triton to proton magnetic moment ratio triton to proton magnetic moment ratio helion-electron mass ratio helion-electron mass ratio helion g factor (gₕ) helion g factor (gₕ) helion magnetic moment (μₕ) helion magnetic moment (μₕ) helion magnetic moment to Bohr magneton ratio helion magnetic moment to Bohr magneton ratio helion magnetic moment to nuclear magneton ratio helion magnetic moment to nuclear magneton ratio helion mass (mₕ) helion mass (mₕ) helion mass energy equivalent helion mass energy equivalent helion mass energy equivalent in MeV helion mass energy equivalent in MeV helion mass in u helion mass in u helion molar mass (Mₕ) helion molar mass (Mₕ) helion-proton mass ratio helion-proton mass ratio helion relative atomic mass (Ar(h)) helion relative atomic mass (Ar(h)) helion shielding shift helion shielding shift shielded helion gyromagnetic ratio shielded helion gyromagnetic ratio shielded helion gyromagnetic ratio in MHz/T shielded helion gyromagnetic ratio in MHz/T shielded helion magnetic moment shielded helion magnetic moment shielded helion magnetic moment to Bohr magneton ratio shielded helion magnetic moment to Bohr magneton ratio shielded helion magnetic moment to nuclear magneton ratio shielded helion magnetic moment to nuclear magneton ratio shielded helion to proton magnetic moment ratio shielded helion to proton magnetic moment ratio shielded helion to shielded proton magnetic moment ratio shielded helion to shielded proton magnetic moment ratio alpha particle mass alpha particle mass alpha particle mass in u alpha particle mass in u alpha particle mass energy equivalent alpha particle mass energy equivalent alpha particle mass energy equivalent in MeV alpha particle mass energy equivalent in MeV alpha particle-electron mass ratio alpha particle-electron mass ratio alpha particle-proton mass ratio alpha particle-proton mass ratio alpha particle rms charge radius alpha particle rms charge radius alpha particle molar mass alpha particle molar mass alpha particle relative atomic mass (Ar(α)) alpha particle relative atomic mass (Ar(α)) atomic mass constant (mᵤ) atomic mass constant (mᵤ) Avogadro constant Avogadro constant Boltzmann constant (k) Boltzmann constant (k) Boltzmann constant in eV/K Boltzmann constant in eV/K Boltzmann constant in Hz/K Boltzmann constant in Hz/K Boltzmann constant in inverse meter per kelvin Boltzmann constant in inverse metre per kelvin electron volt (eV) electron volt (eV) Faraday constant (F) Faraday constant (F) first radiation constant (c�) first radiation constant (c�) first radiation constant for spectral radiance first radiation constant for spectral radiance molar gas constant (R) molar gas constant (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) molar Planck constant molar Planck constant second radiation constant (c₂) second radiation constant (c₂) Stefan-Boltzmann constant (σ) Stefan-Boltzmann constant (σ) lattice spacing of ideal Si (d₂₂₀) lattice spacing of ideal Si (d₂₂₀) atomic mass constant energy equivalent atomic mass constant energy equivalent atomic mass constant energy equivalent in MeV atomic mass constant energy equivalent in MeV atomic mass unit-electron volt relationship atomic mass unit-electron volt relationship molar mass constant (Mᵤ) molar mass constant (Mᵤ) molar mass of carbon-12 molar mass of carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) molar volume of silicon molar volume of silicon Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Wien frequency displacement law constant Wien frequency displacement law constant Wien wavelength displacement law constant Wien wavelength displacement law constant standard atmosphere (atm) standard atmosphere (atm) standard-state pressure (p°) standard-state pressure (p°) Angstrom star (Å*) Angstrom star (Å*) Copper x unit Copper x unit Molybdenum x unit Molybdenum x unit atomic unit of magnetizability atomic unit of magnetizability atomic unit of mass (mₑ) atomic unit of mass (mₑ) atomic unit of momentum atomic unit of momentum atomic unit of permittivity atomic unit of permittivity atomic unit of time atomic unit of time atomic unit of velocity atomic unit of velocity hartree-hertz relationship hartree-hertz relationship hartree-inverse meter relationship hartree-inverse metre relationship hartree-joule relationship hartree-joule relationship hartree-kelvin relationship hartree-kelvin relationship hartree-kilogram relationship hartree-kilogram relationship shielding difference of d and p in HD shielding difference of d and p in HD shielding difference of t and p in HT shielding difference of t and p in HT pi (π) pi (π) Euler's number (e) Euler's number (e) golden ratio (φ) golden ratio (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni constant (γ) nominal solar radius nominal solar radius nominal solar total irradiance nominal solar total irradiance nominal solar luminosity nominal solar luminosity nominal solar effective temperature nominal solar effective temperature nominal solar mass parameter nominal solar mass parameter nominal terrestrial equatorial radius nominal terrestrial equatorial radius nominal terrestrial polar radius nominal terrestrial polar radius nominal terrestrial mass parameter nominal terrestrial mass parameter nominal jovian equatorial radius nominal jovian equatorial radius nominal jovian polar radius nominal jovian polar radius nominal jovian mass parameter nominal jovian mass parameter average value of one minus the rate of TCG relative to TCB average value of one minus the rate of TCG relative to TCB solar mass parameter (TCB-compatible) solar mass parameter (TCB-compatible) solar mass parameter (TDB-compatible) solar mass parameter (TDB-compatible) equatorial radius of the Earth (TT-compatible) equatorial radius of the Earth (TT-compatible) dynamical form factor of the Earth dynamical form factor of the Earth time rate of change in the dynamical form factor of the Earth time rate of change in the dynamical form factor of the Earth geocentric gravitational constant (TCB-compatible) geocentric gravitational constant (TCB-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational constant (TDB-compatible) geocentric gravitational constant (TDB-compatible) potential of the geoid potential of the geoid nominal mean angular velocity of the Earth (TT-compatible) nominal mean angular velocity of the Earth (TT-compatible) ratio mass of the Moon to the Earth ratio mass of the Moon to the Earth ratio of the mass of the Sun to Mercury ratio of the mass of the Sun to Mercury ratio of the mass of the Sun to Venus ratio of the mass of the Sun to Venus ratio of the mass of the Sun to Mars ratio of the mass of the Sun to Mars ratio of the mass of the Sun to Jupiter ratio of the mass of the Sun to Jupiter ratio of the mass of the Sun to Saturn ratio of the mass of the Sun to Saturn ratio of the mass of the Sun to Uranus ratio of the mass of the Sun to Uranus ratio of the mass of the Sun to Neptune ratio of the mass of the Sun to Neptune ratio of the mass of the Sun to (134340) Pluto ratio of the mass of the Sun to (134340) Pluto ratio of the mass of the Sun to (136199) Eris ratio of the mass of the Sun to (136199) Eris ratio of the mass of (1) Ceres to the Sun ratio of the mass of (1) Ceres to the Sun ratio of the mass of (2) Pallas to the Sun ratio of the mass of (2) Pallas to the Sun ratio of the mass of (4) Vesta to the Sun ratio of the mass of (4) Vesta to the Sun mean obliquity of the ecliptic at J2000.0 mean obliquity of the ecliptic at J2000.0 Electromagnetic Electromagnetic Compton wavelength Compton wavelength Astronomy Astronomy ConstantsWidget Domain Domain Subdomain Subdomain No match found No match found Name Name Value Value Unit Unit Search Search All All CustomKeypadDialog Custom Keypad Custom Keypad Rows: Rows: Columns: Columns: Copy preset: Copy preset: Basic Basic Scientific (wide) Scientific (wide) Scientific (narrow) Scientific (narrow) Apply Apply Row Row Column Column Label Label Behavior Behaviour Text Text DiagnosticsDialog App Diagnostics App Diagnostics Copy to Clipboard Copy to Clipboard Editor Unit Unit User unit User unit User function User function Argument Argument Current result:<br/>%1 Current result:<br/>%1 Selection result:<br/>%1 Selection result:<br/>%1 Selection result: n/a Selection result: n/a Selection result: %1 Selection result: %1 second second metre metre kilogram kilogram mole mole radian radian steradian steradian degree Celsius degree Celsius cubic metre cubic metre cubic millimetre cubic millimetre cubic centimetre cubic centimetre cubic decimetre cubic decimetre cubic kilometre cubic kilometre square millimetre square millimetre square kilometre square kilometre square metre square metre minute minute hour hour day day astronomical unit astronomical unit degree degree arcminute arcminute arcsecond arcsecond milliarcsecond milliarcsecond microarcsecond microarcsecond hectare hectare litre litre tonne tonne Dalton Dalton electronvolt electronvolt Angstrom Angstrom atmosphere atmosphere atomic mass unit atomic mass unit British thermal unit British thermal unit calorie calorie carat carat cup cup cup (Imperial) cup (Imperial) cup (Japanese) cup (Japanese) cup (US) cup (US) degree Fahrenheit degree Fahrenheit fathom fathom fluid ounce (Imperial) fluid ounce (Imperial) fluid ounce (US) fluid ounce (US) fluid dram (Imperial) fluid dram (Imperial) fluid dram (US) fluid dram (US) foot foot square foot square foot cubic foot cubic foot gallon (Imperial) gallon (Imperial) gallon (US) gallon (US) gill (Imperial) gill (Imperial) gill (US) gill (US) gradian gradian grain grain gram gram Hartley Hartley Hartree energy unit Hartree energy unit horsepower horsepower inch inch square inch square inch cubic inch cubic inch karat karat knot knot lightminute lightminute lightsecond lightsecond lightyear lightyear long ton long ton mile mile square mile square mile cubic mile cubic mile mile per hour mile per hour kilometre per hour kilometre per hour nautical mile nautical mile ounce ounce parsec parsec pint (Imperial) pint (Imperial) pint (US) pint (US) pound pound pounds per square inch pounds per square inch quart (Imperial) quart (Imperial) quart (US) quart (US) oil barrel oil barrel beer barrel (US) beer barrel (US) square yard square yard cubic yard cubic yard short ton short ton tablespoon tablespoon tablespoon (Australian) tablespoon (Australian) tablespoon (Imperial) tablespoon (Imperial) tablespoon (US) tablespoon (US) dessert spoon dessert spoon teaspoon teaspoon teaspoon (Imperial) teaspoon (Imperial) teaspoon (US) teaspoon (US) turn turn revolution revolution revolution per minute revolution per minute week week kilowatt hour kilowatt hour millimetre of mercury millimetre of mercury yard yard Julian century Julian century Julian year Julian year sidereal year sidereal year tropical year tropical year Evaluator invalid expression invalid expression division by zero division by zero too time consuming - computation was rejected too time consuming - computation was rejected dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimension mismatch - quantities with different dimensions cannot be compared, added, etc. invalid dimension - operation might require dimensionless arguments invalid dimension - operation might require dimensionless arguments Computation aborted - encountered numerical instability Computation aborted - encountered numerical instability invalid dimension - function might require dimensionless arguments invalid dimension - function might require dimensionless arguments error error unit must not be zero unit must not be zero Conversion failed - dimension mismatch Conversion failed - dimension mismatch unknown function or variable unknown function or variable recursion not supported recursion not supported cannot operate on a NaN cannot operate on a NaN underflow - tiny result is out of SpeedCrunch's number range underflow - tiny result is out of SpeedCrunch's number range overflow - huge result is out of SpeedCrunch's number range overflow - huge result is out of SpeedCrunch's number range overflow - logic result exceeds maximum of 256 bits overflow - logic result exceeds maximum of 256 bits overflow - integer result exceeds maximum limit for integers overflow - integer result exceeds maximum limit for integers operation is not defined for these arguments operation is not defined for these arguments wrong number of arguments wrong number of arguments does not take NaN as an argument does not take NaN as an argument result out of range result out of range undefined for argument domain undefined for argument domain computation too expensive computation too expensive internal error, please report a bug internal error, please report a bug syntax error syntax error conversion target must be a unit conversion target must be a unit unknown unit unknown unit %1 is a reserved name, please choose another %1 is a reserved name, please choose another %1 is a global user definition and cannot be overridden in this session. %1 is a global user definition and cannot be overridden in this session. %1 is a variable name, please choose another or delete the variable %1 is a variable name, please choose another or delete the variable argument %1 is used more than once argument %1 is used more than once %1 is a built-in unit name, please choose another %1 is a built-in unit name, please choose another %1 is a user function name, please choose another or delete the function %1 is a user function name, please choose another or delete the function FunctionRepo max; trials; probability max; trials; probability trials; probability trials; probability hits; trials; probability hits; trials; probability max; total; hits; trials max; total; hits; trials total; hits; trials total; hits; trials count; total; hits; trials count; total; hits; trials dividend; divisor dividend; divisor x; exponent_bits; significand_bits [; exponent_bias] x; exponent_bits; significand_bits [; exponent_bias] base; x base; x value; modulo value; modulo base; exponent; modulo base; exponent; modulo events; average_events events; average_events average_events average_events x [; precision] x [; precision] Absolute Value Absolute Value Absolute Deviation Absolute Deviation Arc Cosine Arc Cosine Logical AND Logical AND Area Hyperbolic Cosine Area Hyperbolic Cosine Area Hyperbolic Sine Area Hyperbolic Sine Area Hyperbolic Tangent Area Hyperbolic Tangent Arc Sine Arc Sine Arc Tangent Arc Tangent Arc Tangent with two Arguments Arc Tangent with two Arguments Average (Arithmetic Mean) Average (Arithmetic Mean) Binomial Cumulative Distribution Function Binomial Cumulative Distribution Function Binomial Distribution Mean Binomial Distribution Mean Binomial Probability Mass Function Binomial Probability Mass Function Binomial Distribution Variance Binomial Distribution Variance Cube Root Cube Root Complex Conjugate Complex Conjugate Cosine Cosine Hyperbolic Cosine Hyperbolic Cosine Cotangent Cotangent Cosecant Cosecant Convert Unix timestamp to Date Convert Unix timestamp to Date Degrees of Arc Degrees of Arc Error Function Error Function Complementary Error Function Complementary Error Function Exponential Exponential Fractional Part Fractional Part Extension of Factorials [= (x-1)!] Extension of Factorials [= (x-1)!] Greatest Common Divisor Highest Common Factor Geometric Mean Geometric Mean Gradians of arc Gradians of arc Hypergeometric Cumulative Distribution Function Hypergeometric Cumulative Distribution Function Hypergeometric Distribution Mean Hypergeometric Distribution Mean Hypergeometric Probability Mass Function Hypergeometric Probability Mass Function Hypergeometric Distribution Variance Hypergeometric Distribution Variance Integer Quotient Integer Quotient Integer Part Integer Part Imaginary Part Imaginary Part Decode IEEE-754 Binary Value Decode IEEE-754 Binary Value Encode IEEE-754 Binary Value Encode IEEE-754 Binary Value Decode 16-bit Half-Precision Value Decode 16-bit Half-Precision Value Encode 16-bit Half-Precision Value Encode 16-bit Half-Precision Value Decode 32-bit Single-Precision Value Decode 32-bit Single-Precision Value Encode 32-bit Single-Precision Value Encode 32-bit Single-Precision Value Decode 64-bit Double-Precision Value Decode 64-bit Double-Precision Value Encode 64-bit Double-Precision Value Encode 64-bit Double-Precision Value Decode 128-bit Quad-Precision Value Decode 128-bit Quad-Precision Value Encode 128-bit Quad-Precision Value Encode 128-bit Quad-Precision Value Binary Logarithm Binary Logarithm Common Logarithm Common Logarithm Natural Logarithm Natural Logarithm Logarithm to Arbitrary Base Logarithm to Arbitrary Base Mask to a bit size Mask to a bit size Maximum Maximum Median Value (50th Percentile) Median Value (50th Percentile) Minimum Minimum Modulo Modulo Euclidean Modulo Euclidean Modulo Modular Exponentiation Modular Exponentiation Combination (Binomial Coefficient) Combination (Binomial Coefficient) Logical NOT Logical NOT Permutation (Arrangement) Permutation (Arrangement) Convert to Binary Representation Convert to Binary Representation Arithmetic Arithmetic Chemistry Chemistry Complex Complex Combinatorics Combinatorics Probability Probability Statistics Statistics Aggregation Aggregation Random Random Base conversion Base conversion Number formatting Number formatting Integer arithmetic Integer arithmetic Special functions Special functions Exponential & Logarithmic Exponential & Logarithmic Angle conversion Angle conversion Trigonometry Trigonometry Bitwise Bitwise Floating point Floating point Date & Time Date & Time Linear algebra Linear algebra unix_timestamp; x hours offset to GMT unix_timestamp; x hours offset to GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; x hours offset to GMT [digits] [digits] max [; min] max [; min] List Literal List Literal Convert to Padded Binary Representation Convert to Padded Binary Representation Round Toward +∞ (Ceiling) Round Toward +∞ (Ceiling) Cosine plus Imaginary Sine Cosine plus Imaginary Sine Convert to Cis Complex Form Convert to Cis Complex Form Matrix Column Count Matrix Column Count Population Correlation Matrix (n) Population Correlation Matrix (n) Sample Correlation Matrix (n-1) Sample Correlation Matrix (n-1) Count Count Population Covariance Matrix (n) Population Covariance Matrix (n) Sample Covariance Matrix (n-1) Sample Covariance Matrix (n-1) Cross Product Cross Product Convert Date to Unix timestamp Convert Date to Unix timestamp Convert to Decimal Representation Convert to Decimal Representation Determinant Determinant Convert to Sexagesimal Notation Convert to Sexagesimal Notation Dot Product Dot Product Convert to Engineering Notation Convert to Engineering Notation Convert to Exponential Complex Form Convert to Exponential Complex Form Round Toward −∞ (Floor) Round Toward −∞ (Floor) Flatten Matrix Flatten Matrix Least Common Multiple Least Common Multiple Convert to Hexadecimal Representation Convert to Hexadecimal Representation Convert to Padded Hexadecimal Representation Convert to Padded Hexadecimal Representation Inverse Matrix Inverse Matrix Round to 16-bit Half-Precision Value Round to 16-bit Half-Precision Value Round to 32-bit Single-Precision Value Round to 32-bit Single-Precision Value Round to 64-bit Double-Precision Value Round to 64-bit Double-Precision Value Round to 128-bit Quad-Precision Value Round to 128-bit Quad-Precision Value Residual from 16-bit Half-Precision Rounding Residual from 16-bit Half-Precision Rounding Residual from 32-bit Single-Precision Rounding Residual from 32-bit Single-Precision Rounding Residual from 64-bit Double-Precision Rounding Residual from 64-bit Double-Precision Rounding Residual from 128-bit Quad-Precision Rounding Residual from 128-bit Quad-Precision Rounding Substance Mass Substance Mass Molarity Molarity Molar Mass Molar Mass Median Absolute Deviation Median Absolute Deviation Mean Mean Numerical Value of Quantity Numerical Value of Quantity Random Decimal Number Random Decimal Number Random Integer Number Random Integer Number Convert to Rational Representation Convert to Rational Representation Convert to Octal Representation Convert to Octal Representation Convert to Padded Octal Representation Convert to Padded Octal Representation Vector or Matrix Norm Vector or Matrix Norm Logical OR Logical OR Population Count (Hamming Weight) Population Count (Hamming Weight) Phase of Complex Number Phase of Complex Number Poissonian Cumulative Distribution Function Poissonian Cumulative Distribution Function Poissonian Distribution Mean Poissonian Distribution Mean Poissonian Probability Mass Function Poissonian Probability Mass Function Poissonian Distribution Variance Poissonian Distribution Variance Convert to Phasor Complex Form Convert to Phasor Complex Form Convert to Rectangular Complex Form Convert to Rectangular Complex Form Round Half Away from Zero Round Half Away from Zero Round Half Even Round Half Even Nth Root Nth Root Convert to Scientific Notation Convert to Scientific Notation Matrix Row Count Matrix Row Count List or Matrix Shape List or Matrix Shape Summation Summation Population Standard Deviation (n) Population Standard Deviation (n) Sample Standard Deviation (n-1) Sample Standard Deviation (n-1) Round Toward Zero (Truncation) Round Toward Zero (Truncation) Matrix Trace Matrix Trace Transpose Matrix Transpose Matrix Population Variance (n) Population Variance (n) Sample Variance (n-1) Sample Variance (n-1) Product Product Radians Radians Matrix Rank Matrix Rank Real Part Real Part Secant Secant Arithmetic Shift Left Arithmetic Shift Left Arithmetic Shift Right Arithmetic Shift Right Signum Signum Sine Sine Hyperbolic Sine Hyperbolic Sine Square Root Square Root Sum Sum Tangent Tangent Convert to Trigonometric Complex Form Convert to Trigonometric Complex Form Turns Turns Hyperbolic Tangent Hyperbolic Tangent Sign-extend a value Sign-extend a value Logical XOR Logical XOR FunctionsWidget Domain Domain All All Name Name Search Search No match found No match found Identifier Identifier HistoryWidget Remove All Calculations Above Remove All Calculations Above Remove This Calculation Remove This Calculation Remove All Calculations Below Remove All Calculations Below Keypad Inverse cosine Inverse cosine The last result The last result Inverse sine Inverse sine Inverse tangent Inverse tangent Evaluate expression Evaluate expression Division Division Multiplication Multiplication Subtraction Subtraction Addition Addition Clear expression Clear expression Cosine Cosine Backspace Backspace Scientific notation Scientific notation Exponential Exponential Factorial Factorial Natural logarithm Natural logarithm Left parenthesis Left parenthesis Nth root Nth root Argument separator Argument separator Square Square Common logarithm Common logarithm Modulo Modulo Contextual percentage Contextual percentage Power Power Right parenthesis Right parenthesis Sine Sine Square root Square root Tangent Tangent Pi Pi Decimal separator Decimal separator MainWindow Radian Radian Degree Degree Gradian Gradian Binary Binary Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Engineering decimal Engineering decimal Scientific decimal Scientific decimal &Import... &Import... &Quit &Quit Clear E&xpression Clear E&xpression Clear &History Clear &History &Copy &Copy &Paste &Paste &Select Expression &Select Expression &Constants &Constants &Functions &Functions &History &History &Status Bar &Status Bar Bitfield Bitfield Use&r Functions Use&r Functions &Degree &Degree &Radian &Radian &Gradian &Gradian Re&volution Re&volution Auto-Insert a&ns Auto-Insert a&ns Automatic &Completion Automatic &Completion &Built-in Functions &Built-in Functions Built-in &Variables Built-in &Variables User &Functions User &Functions User Va&riables User Va&riables Open a Private Tab on Startup Open a Private Tab on Startup Open and focus a new private tab whenever SpeedCrunch starts. Open and focus a new private tab whenever SpeedCrunch starts. Syntax &Highlighting Syntax &Highlighting Group Digits in &Input Group Digits in &Input Automatic Input &Adjustments Automatic Input &Adjustments Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Group input digits using the selected number format. Group input digits using the selected number format. &Blinking Cursor &Blinking Cursor Blink the cursor in the expression editor. Blink the cursor in the expression editor. &Escape Clears Editor &Escape Clears Editor Clear the focused expression editor with Escape after dismissing any popup or preview. Clear the focused expression editor with Escape after dismissing any popup or preview. Keep Expression After Evaluation Keep Expression After Evaluation Copy New Results Automatically Copy New Results Automatically &Comma &Comma &System Default &System Default &Dot &Dot Dot &And Comma Dot &And Comma Toward +∞ (&ceil) Toward +∞ (&ceil) Toward −∞ (&floor) Toward −∞ (&floor) &Binary &Binary &Engineering &Engineering &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Scientific User &Manual User &Manual Issues and &Feedback Issues and &Feedback &Donate &Donate &About SpeedCrunch &About SpeedCrunch App Diag&nostics App Diag&nostics S&plit S&plit Angle &Mode Angle &Mode &Complex Form &Complex Form New Tab New Tab Constants Constants Functions Functions History History User Functions User Functions &Font... &Font... &Language... &Language... &Session &Session &Edit &Edit &View &View Se&ttings Se&ttings &Decimal &Decimal &Keypad &Keypad Always on &Top Always on &Top Disabled Disabled Small Space Small Space Medium Space Medium Space Large Space Large Space &0 Digits &0 Digits &15 Digits &15 Digits &2 Digits &2 Digits &3 Digits &3 Digits &50 Digits &50 Digits &8 Digits &8 Digits &Sexagesimal &Sexagesimal Reset All Settings... Reset All Settings... &System &System SpeedCrunch &Theme SpeedCrunch &Theme &Classic &Classic &Modern &Modern Context Help Context Help &Help &Help Error Error Can't read from file %1 Can't read from file %1 Import Session Import Session Close Session Close Session Angle Mode: Angle Mode: Notation: Notation: Precision: Precision: Turn Turn Revolution Revolution Fixed-point decimal Fixed-point decimal Rational Rational Automatic decimal Automatic decimal Automatic Automatic User &Definitions... User &Definitions... New &Tab New &Tab New &Private Tab New &Private Tab Keep Keep Make Private... Make Private... New &Window New &Window &Open... &Open... &Rename... &Rename... Clo&ne... Clo&ne... &Close Tab &Close Tab Reopen Clo&sed Tab Reopen Clo&sed Tab Open Sessions &Folder Open Sessions &Folder &Undo &Undo &Redo &Redo Cu&t Cu&t Copy &Last Result Copy &Last Result &Wrap in Parentheses &Wrap in Parentheses Full Scr&een Mode Full Scr&een Mode &Basic &Basic &Scientific (wide) &Scientific (wide) Scientific (narrow) Scientific (narrow) &Custom... &Custom... Main &Menu Main &Menu User &Variables User &Variables &Left &Left &Right &Right &Up &Up &Down &Down Close Pa&ne Close Pa&ne User &Units User &Units &Turn &Turn If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. &Accept with Enter &Accept with Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. &Units &Units Show Live Result &Preview Show Live Result &Preview Save &Window Position on Exit Save &Window Position on Exit Hover Highlighting Hover Highlighting Group Integer Part Only Group Integer Part Only Number Format... Number Format... Notation && Precision... Notation && Precision... After pressing Enter, keep the entered expression selected in the editor. After pressing Enter, keep the entered expression selected in the editor. Never Never Always Always Only for Single-Line Expressions Only for Single-Line Expressions Simplify Displayed Expressions Simplify Displayed Expressions History Size &Limit... History Size &Limit... Remove Trailing &Zeroes Remove Trailing &Zeroes Nearest, Half &Away (round) Nearest, Half &Away (round) Nearest, Half &Even (roundeven) Nearest, Half &Even (roundeven) Toward &Zero (trunc) Toward &Zero (trunc) &Fixed-Point &Fixed-Point &Rational &Rational &Exponential (m·s�¹) &Exponential (m·s�¹) &Fractional (m/s) &Fractional (m/s) &Rectangular (a + bi) &Rectangular (a + bi) Exponential (re�ᶿ) Exponential (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonometric (r(cos θ + i·sin θ)) Phasor (r∠θ) Phasor (r∠θ) &Theme... &Theme... Check for &Updates Check for &Updates Source Code Source Code &Zoom &Zoom &Results &Results Unit Notation Unit Notation Rounding Mode Rounding Mode &Notation &Notation &Imaginary Unit &Imaginary Unit &Window &Window &Editing &Editing A&utocomplete A&utocomplete Up/Down Arrow History Up/Down Arrow History &Appearance &Appearance &Menus &Menus &Docks &Docks &Input and Results &Input and Results &Disabled &Disabled &Disable &Disable Close preview Close preview Rename... Rename... Clone... Clone... Close Tab Close Tab New Private Tab New Private Tab Open... Open... Reopen Closed Tab Reopen Closed Tab Split Split Left Left Right Right Up Up Down Down Clear Clear Delete Delete %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Private] Reset All Settings Reset All Settings Reset all settings to their default values? Reset all settings to their default values? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. The settings file could not be written. The settings file could not be written. Clear this session's calculations, unfinished expression, variables, functions, and units? Clear this session's calculations, unfinished expression, variables, functions, and units? Global user definitions are kept. Global user definitions are kept. Make Session Private Make Session Private The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Make Private Make Private Could not delete the saved session %1. Could not delete the saved session %1. Keep Session Keep Session Could not save the session. It remains private. Could not save the session. It remains private. Clone Session Clone Session Could not save session file %1. Could not save session file %1. Could not delete session file %1. Could not delete session file %1. JSON file (*.json);;Any file (*.*) JSON file (*.json);;Any file (*.*) Export session as JSON Export session as JSON The selected file is not valid JSON: %1 The selected file is not valid JSON: %1 The selected file is not a SpeedCrunch session JSON file. The selected file is not a SpeedCrunch session JSON file. This file uses an obsolete SpeedCrunch session format and cannot be imported. This file uses an obsolete SpeedCrunch session format and cannot be imported. The selected JSON file is missing the required $schema field. The selected JSON file is missing the required $schema field. The selected JSON file uses an unsupported JSON schema: %1 The selected JSON file uses an unsupported JSON schema: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). The selected JSON file is missing the SpeedCrunch session schema identifier ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 The selected JSON file uses an unsupported SpeedCrunch session format: %1 The selected JSON file is missing the required session name. The selected JSON file is missing the required session name. The selected JSON file has an empty session name. The selected JSON file has an empty session name. The selected JSON file has invalid or incomplete SpeedCrunch session data. The selected JSON file has invalid or incomplete SpeedCrunch session data. Open Sessions Folder Open Sessions Folder Could not create the sessions folder: %1 Could not create the sessions folder: %1 Could not open the sessions folder: %1 Could not open the sessions folder: %1 Editor and Results Font Editor and Results Font Open Session Open Session Community Community Rename Session Rename Session Clear Session Clear Session Delete Session Delete Session Close Pane Close Pane User Variables User Variables User Units User Units Clear History Clear History Are you sure you want to clear the calculation history? Are you sure you want to clear the calculation history? Session name: Session name: A session named %1 already exists. A session named %1 already exists. Could not create session file %1. Could not create session file %1. Could not write session file %1. Could not write session file %1. Are you sure you want to delete this session? Are you sure you want to delete this session? Custom Precision Custom Precision Fractional digits: Fractional digits: Theme Theme Light Themes Light Themes Dark Themes Dark Themes Preview Preview Colors Colours Select color for %1 Select colour for %1 Import... Import... Export... Export... Import Theme Import Theme Theme file (*.json);;All files (*) Theme file (*.json);;All files (*) Invalid theme file. Invalid theme file. Can't import theme "%1" because it conflicts with a built-in theme. Can't import theme "%1" because it conflicts with a built-in theme. Can't find a writable theme folder. Can't find a writable theme folder. Overwrite Theme Overwrite Theme A custom theme named "%1" already exists. Do you want to overwrite it? A custom theme named "%1" already exists. Do you want to overwrite it? Can't overwrite theme file %1 Can't overwrite theme file %1 Can't copy theme file to %1 Can't copy theme file to %1 Export Theme Export Theme Can't export theme as "%1" because it conflicts with a built-in theme. Can't export theme as "%1" because it conflicts with a built-in theme. Can't write to file %1 Can't write to file %1 Global User Variable Global User Variable Global User Function Global User Function Global User Unit Global User Unit User Definitions User Definitions These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Apply Validate Validate Test Results Test Results Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 none none Apply Results Apply Results User definitions saved. User definitions saved. History Size Limit History Size Limit Maximum number of history entries for this session (0 = unlimited): Maximum number of history entries for this session (0 = unlimited): Text file (*.txt);;Any file (*.*) Text file (*.txt);;Any file (*.*) Could not recalculate from calculation %1: %2 Could not recalculate from calculation %1: %2 History Size Limit Reached History Size Limit Reached This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Editing calculation. Press Esc twice to cancel. Editing calculation. Press Esc twice to cancel. Calculation Settings Calculation Settings Invalid recalculation start index Invalid recalculation start index System Default System Default Language Language Select the language: Select the language: Custom Custom Decimal places: Decimal places: &Automatic &Automatic &Precision &Precision Plain &text Plain &text Formula &Book Formula &Book &Export &Export Export session as HTML Export session as HTML HTML file (*.html) HTML file (*.html) Export session as plain text Export session as plain text ManualWindow SpeedCrunch Manual SpeedCrunch Manual %1 - SpeedCrunch Manual %1 - SpeedCrunch Manual NumberFormatDialog Number Format Number Format <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> QObject Global User Variable Global User Variable Global User Function Global User Function Global User Unit Global User Unit Backspace Backspace Clear expression Clear expression Evaluate expression Evaluate expression Insert text Insert text Automatic decimal Automatic decimal Fixed-point decimal Fixed-point decimal Engineering decimal Engineering decimal Scientific decimal Scientific decimal Rational Rational Binary Binary Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Update Available Update Available A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Check for Updates Check for Updates SpeedCrunch %1 is up to date. SpeedCrunch %1 is up to date. No connectivity. Please check your internet connection and try again. No connectivity. Please check your internet connection and try again. Could not verify the latest available version. Could not verify the latest available version. ResultDisplay Scroll to bottom Scroll to bottom Edit Expression Edit Expression Change Settings Change Settings New Tab New Tab &Import... &Import... &Export &Export Plain &text Plain &text Copy Copy Selection Selection Select All Select All Expression Expression Result Result Calculation Calculation Calculation as Single Line Calculation as Single Line Remove Remove This Calculation This Calculation All Calculations Above All Calculations Above All Calculations Below All Calculations Below New Private Tab New Private Tab Session Session Open... Open... Clone... Clone... Rename... Rename... Keep Keep Make Private... Make Private... Clear Clear Delete Delete Close Close Split Split Left Left Right Right Up Up Down Down Close Pane Close Pane Main Menu Main Menu Cancel editing Cancel editing Copy result Copy result Edit expression Edit expression Change settings Change settings Remove calculation Remove calculation ResultSlotsDialog Notation & Precision Notation & Precision Result Line Result Line Enabled Enabled Notation Notation Decimal Places Decimal Places Main Line Main Line Extra Line #1 Extra Line #1 Extra Line #2 Extra Line #2 Extra Line #3 Extra Line #3 Extra Line #4 Extra Line #4 Auto Auto UserFunctionListWidget Name Name Value Value Description Description Search Search No match found No match found Insert Insert Edit Edit Delete Delete Delete All Delete All UserUnitListWidget Name Name Value Value Description Description Search Search No match found No match found Insert Insert Edit Edit Delete Delete Delete All Delete All VariableListWidget Name Name Value Value Description Description Search Search No match found No match found Insert Insert Edit Edit Delete Delete Delete All Delete All heldercorreia-speedcrunch-e7ca37f/src/resources/locale/en_US.ts000066400000000000000000007544431526573132500247770ustar00rootroot00000000000000 AboutBox About SpeedCrunch Main author | Logo | Maintainer Core developers Original author Math engine Thanks Copyright (C) 2004-2026 The SpeedCrunch developers This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Close Book Index Algebra Quadratic Equation Logarithmic Base Conversion Geometry Circle Sector Sphere Cube Cone Cylinder Electronics Ohm's Law Power Reactance Resonance Radio Frequency Antennas Characteristic Impedance (coax) Velocity of Propagation (coax) Standing Wave Ratio & Return Loss Free Space Wavelength resistance voltage current power inductive reactance capacitive reactance inductance capacitance frequency resonance frequency area perimeter diameter radius volume surface area height slant height face diagonal space diagonal edge length arc length central angle (degrees) dielectric constant outer conductor's inner diameter inner conductor's outer diameter speed of light input power reflected power transmitted power return loss reflection coefficient standing wave ratio normalized impedance frequency (Hz) BookDock Formula Book ConstantCompletion All Constants Mathematics Physics (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Uncategorized Universal Physicochemical Atomic & Nuclear — General Atomic & Nuclear — Electroweak Atomic & Nuclear — Electron Atomic & Nuclear — Muon Atomic & Nuclear — Tau Atomic & Nuclear — Proton Atomic & Nuclear — Neutron Atomic & Nuclear — Deuteron Atomic & Nuclear — Triton Atomic & Nuclear — Helion Atomic & Nuclear — Alpha particle Atomic & Nuclear — Atomic units Atomic & Nuclear — Energy conversion relationships Atomic & Nuclear — X-ray units Atomic & Nuclear — Magnetic shielding corrections Masses Lifetimes Molar Masses Electronegativity Ionization Energy Nominal Constants (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) reduced Planck constant (�) vacuum electric permittivity (ϵ₀) Newtonian constant of gravitation (G) vacuum magnetic permeability (μ₀) Planck constant (h) speed of light in vacuum (c) standard acceleration of gravity (gₙ) Newtonian constant of gravitation over h-bar c Planck length Planck constant in eV/Hz (h) Planck mass Planck mass energy equivalent in GeV Planck temperature Planck time reduced Planck constant in eV·s (�) reduced Planck constant times c in MeV·fm Bohr magneton conductance quantum (G₀) Coulomb constant (kₑ) elementary charge (e) elementary charge over h-bar conventional value of Josephson constant Josephson constant conventional value of ampere-90 conventional value of coulomb-90 conventional value of farad-90 conventional value of henry-90 conventional value of ohm-90 conventional value of volt-90 conventional value of watt-90 magnetic flux quantum (Φ₀) nuclear magneton inverse of conductance quantum conventional value of von Klitzing constant von Klitzing constant atomic unit of magnetic dipole moment atomic unit of magnetic flux density Bohr magneton in eV/T Bohr magneton in Hz/T Bohr magneton in inverse meter per tesla Bohr magneton in K/T nuclear magneton in eV/T nuclear magneton in inverse meter per tesla nuclear magneton in K/T nuclear magneton in MHz/T Bohr radius (a₀) fine-structure constant (α) Hartree energy (Eₕ) Hartree energy in eV quantum of circulation quantum of circulation times 2 Rydberg constant (R∞) atomic mass unit-hartree relationship atomic mass unit-hertz relationship atomic mass unit-inverse meter relationship atomic mass unit-joule relationship atomic mass unit-kelvin relationship atomic mass unit-kilogram relationship atomic unit of 1st hyperpolarizability atomic unit of 2nd hyperpolarizability atomic unit of charge (e) atomic unit of charge density atomic unit of current atomic unit of electric dipole moment atomic unit of electric field atomic unit of electric field gradient atomic unit of electric polarizability atomic unit of electric potential atomic unit of electric quadrupole moment atomic unit of action atomic unit of energy atomic unit of force atomic unit of length hertz-atomic mass unit relationship hertz-electron volt relationship hertz-hartree relationship hertz-inverse meter relationship hertz-joule relationship hertz-kelvin relationship hertz-kilogram relationship hyperfine transition frequency of Cs-133 inverse fine-structure constant (α�¹) inverse meter-atomic mass unit relationship inverse meter-electron volt relationship inverse meter-hartree relationship inverse meter-hertz relationship inverse meter-joule relationship inverse meter-kelvin relationship inverse meter-kilogram relationship joule-atomic mass unit relationship joule-electron volt relationship joule-hertz relationship joule-hartree relationship joule-inverse meter relationship joule-kelvin relationship joule-kilogram relationship kelvin-atomic mass unit relationship kelvin-electron volt relationship kelvin-hertz relationship kelvin-hartree relationship kelvin-inverse meter relationship kelvin-joule relationship kelvin-kilogram relationship kilogram-atomic mass unit relationship kilogram-electron volt relationship kilogram-hertz relationship kilogram-hartree relationship kilogram-inverse meter relationship kilogram-joule relationship kilogram-kelvin relationship lattice parameter of silicon (a) luminous efficacy natural unit of energy natural unit of energy in MeV natural unit of action (�) natural unit of action in eV·s natural unit of length natural unit of mass natural unit of momentum natural unit of momentum in MeV/c natural unit of time natural unit of velocity Rydberg constant times c in Hz Rydberg constant times hc in eV Rydberg constant times hc in J Fermi coupling constant weak mixing angle W to Z mass ratio Thomson cross section (σₑ) electron mass (mₑ) electron mass in u electron mass energy equivalent (mₑ·c²) electron mass energy equivalent in MeV reduced Compton wavelength classical electron radius (rₑ) electron charge to mass quotient electron-deuteron magnetic moment ratio electron-deuteron mass ratio electron g factor (gₑ) electron gyromagnetic ratio (γₑ) electron gyromagnetic ratio in MHz/T electron-helion mass ratio electron magnetic moment (μₑ) electron magnetic moment anomaly (aₑ) electron magnetic moment to Bohr magneton ratio electron magnetic moment to nuclear magneton ratio electron molar mass (Mₑ) electron-muon magnetic moment ratio electron-muon mass ratio electron-neutron magnetic moment ratio electron-neutron mass ratio electron-proton magnetic moment ratio electron-proton mass ratio electron relative atomic mass (Ar(e)) electron-tau mass ratio electron to alpha particle mass ratio electron to shielded helion magnetic moment ratio electron to shielded proton magnetic moment ratio electron-triton mass ratio electron volt-atomic mass unit relationship electron volt-hartree relationship electron volt-hertz relationship electron volt-inverse meter relationship electron volt-joule relationship electron volt-kelvin relationship electron volt-kilogram relationship hartree-atomic mass unit relationship hartree-electron volt relationship muon Compton wavelength muon-electron mass ratio muon g factor muon magnetic moment muon magnetic moment anomaly muon magnetic moment to Bohr magneton ratio muon magnetic moment to nuclear magneton ratio muon mass muon mass energy equivalent muon mass energy equivalent in MeV muon mass in u muon molar mass muon-neutron mass ratio muon-proton magnetic moment ratio muon-proton mass ratio muon-tau mass ratio reduced muon Compton wavelength reduced tau Compton wavelength tau Compton wavelength tau-electron mass ratio tau mass tau mass energy equivalent tau mass in u tau molar mass tau-muon mass ratio tau-neutron mass ratio tau-proton mass ratio proton charge to mass quotient proton Compton wavelength proton-electron mass ratio proton g factor (gₚ) proton gyromagnetic ratio (γₚ) proton gyromagnetic ratio in MHz/T proton magnetic moment (μₚ) proton magnetic moment to Bohr magneton ratio proton magnetic moment to nuclear magneton ratio proton magnetic shielding correction proton mass (mₚ) proton mass energy equivalent proton mass energy equivalent in MeV proton mass in u proton molar mass (Mₚ) proton-muon mass ratio proton-neutron magnetic moment ratio proton-neutron mass ratio proton relative atomic mass (Ar(p)) proton rms charge radius proton-tau mass ratio reduced proton Compton wavelength shielded proton gyromagnetic ratio shielded proton gyromagnetic ratio in MHz/T shielded proton magnetic moment shielded proton magnetic moment to Bohr magneton ratio shielded proton magnetic moment to nuclear magneton ratio neutron Compton wavelength neutron-electron magnetic moment ratio neutron-electron mass ratio neutron g factor (gₙ) neutron gyromagnetic ratio (γₙ) neutron gyromagnetic ratio in MHz/T neutron magnetic moment (μₙ) neutron magnetic moment to Bohr magneton ratio neutron magnetic moment to nuclear magneton ratio neutron mass (mₙ) neutron mass energy equivalent neutron mass energy equivalent in MeV neutron mass in u neutron molar mass (Mₙ) neutron-muon mass ratio neutron-proton magnetic moment ratio neutron-proton mass difference neutron-proton mass difference energy equivalent neutron-proton mass difference energy equivalent in MeV neutron-proton mass difference in u neutron-proton mass ratio neutron relative atomic mass (Ar(n)) neutron-tau mass ratio neutron to shielded proton magnetic moment ratio reduced neutron Compton wavelength deuteron-electron magnetic moment ratio deuteron-electron mass ratio deuteron g factor deuteron magnetic moment deuteron magnetic moment to Bohr magneton ratio deuteron magnetic moment to nuclear magneton ratio deuteron mass deuteron mass energy equivalent deuteron mass energy equivalent in MeV deuteron mass in u deuteron molar mass deuteron-neutron magnetic moment ratio deuteron-proton magnetic moment ratio deuteron-proton mass ratio deuteron relative atomic mass (Ar(d)) deuteron rms charge radius triton-electron mass ratio triton g factor (gₜ) triton magnetic moment (μₜ) triton magnetic moment to Bohr magneton ratio triton magnetic moment to nuclear magneton ratio triton mass (mₜ) triton mass energy equivalent triton mass energy equivalent in MeV triton mass in u triton molar mass (Mₜ) triton-proton mass ratio triton relative atomic mass (Ar(t)) triton to proton magnetic moment ratio helion-electron mass ratio helion g factor (gₕ) helion magnetic moment (μₕ) helion magnetic moment to Bohr magneton ratio helion magnetic moment to nuclear magneton ratio helion mass (mₕ) helion mass energy equivalent helion mass energy equivalent in MeV helion mass in u helion molar mass (Mₕ) helion-proton mass ratio helion relative atomic mass (Ar(h)) helion shielding shift shielded helion gyromagnetic ratio shielded helion gyromagnetic ratio in MHz/T shielded helion magnetic moment shielded helion magnetic moment to Bohr magneton ratio shielded helion magnetic moment to nuclear magneton ratio shielded helion to proton magnetic moment ratio shielded helion to shielded proton magnetic moment ratio alpha particle mass alpha particle mass in u alpha particle mass energy equivalent alpha particle mass energy equivalent in MeV alpha particle-electron mass ratio alpha particle-proton mass ratio alpha particle rms charge radius alpha particle molar mass alpha particle relative atomic mass (Ar(α)) atomic mass constant (mᵤ) Avogadro constant Boltzmann constant (k) Boltzmann constant in eV/K Boltzmann constant in Hz/K Boltzmann constant in inverse meter per kelvin electron volt (eV) Faraday constant (F) first radiation constant (c�) first radiation constant for spectral radiance molar gas constant (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) molar Planck constant second radiation constant (c₂) Stefan-Boltzmann constant (σ) lattice spacing of ideal Si (d₂₂₀) atomic mass constant energy equivalent atomic mass constant energy equivalent in MeV atomic mass unit-electron volt relationship molar mass constant (Mᵤ) molar mass of carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) molar volume of silicon Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Wien frequency displacement law constant Wien wavelength displacement law constant standard atmosphere (atm) standard-state pressure (p°) Angstrom star (Å*) Copper x unit Molybdenum x unit atomic unit of magnetizability atomic unit of mass (mₑ) atomic unit of momentum atomic unit of permittivity atomic unit of time atomic unit of velocity hartree-hertz relationship hartree-inverse meter relationship hartree-joule relationship hartree-kelvin relationship hartree-kilogram relationship shielding difference of d and p in HD shielding difference of t and p in HT pi (π) pi (π) Euler's number (e) golden ratio (φ) Euler-Mascheroni constant (γ) nominal solar radius nominal solar total irradiance nominal solar luminosity nominal solar effective temperature nominal solar mass parameter nominal terrestrial equatorial radius nominal terrestrial polar radius nominal terrestrial mass parameter nominal jovian equatorial radius nominal jovian polar radius nominal jovian mass parameter average value of one minus the rate of TCG relative to TCB solar mass parameter (TCB-compatible) solar mass parameter (TDB-compatible) equatorial radius of the Earth (TT-compatible) dynamical form factor of the Earth time rate of change in the dynamical form factor of the Earth geocentric gravitational constant (TCB-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational constant (TDB-compatible) potential of the geoid nominal mean angular velocity of the Earth (TT-compatible) ratio mass of the Moon to the Earth ratio of the mass of the Sun to Mercury ratio of the mass of the Sun to Venus ratio of the mass of the Sun to Mars ratio of the mass of the Sun to Jupiter ratio of the mass of the Sun to Saturn ratio of the mass of the Sun to Uranus ratio of the mass of the Sun to Neptune ratio of the mass of the Sun to (134340) Pluto ratio of the mass of the Sun to (136199) Eris ratio of the mass of (1) Ceres to the Sun ratio of the mass of (2) Pallas to the Sun ratio of the mass of (4) Vesta to the Sun mean obliquity of the ecliptic at J2000.0 Electromagnetic Compton wavelength Astronomy ConstantsWidget Domain Subdomain Search No match found Name Value Unit All CustomKeypadDialog Custom Keypad Rows: Columns: Copy preset: Basic Scientific (wide) Scientific (narrow) Apply Row Column Label Behavior Text Editor Unit User unit User function Argument Current result:<br/>%1 Selection result:<br/>%1 Selection result: n/a Selection result: %1 second metre kilogram mole radian steradian degree Celsius cubic metre cubic millimetre cubic centimetre cubic decimetre cubic kilometre square millimetre square kilometre square metre minute hour day astronomical unit degree arcminute arcsecond milliarcsecond microarcsecond hectare litre tonne Dalton electronvolt Angstrom atmosphere atomic mass unit British thermal unit calorie carat cup cup (Imperial) cup (Japanese) cup (US) degree Fahrenheit fathom fluid ounce (Imperial) fluid ounce (US) fluid dram (Imperial) fluid dram (US) foot square foot cubic foot gallon (Imperial) gallon (US) gill (Imperial) gill (US) gradian grain gram Hartley Hartree energy unit horsepower inch square inch cubic inch karat knot lightminute lightsecond lightyear long ton mile square mile cubic mile mile per hour kilometre per hour nautical mile ounce parsec pint (Imperial) pint (US) pound pounds per square inch quart (Imperial) quart (US) oil barrel beer barrel (US) square yard cubic yard short ton tablespoon tablespoon (Australian) tablespoon (Imperial) tablespoon (US) dessert spoon teaspoon teaspoon (Imperial) teaspoon (US) turn revolution revolution per minute week kilowatt hour millimetre of mercury yard Julian century Julian year sidereal year tropical year Evaluator cannot operate on a NaN underflow - tiny result is out of SpeedCrunch's number range overflow - huge result is out of SpeedCrunch's number range division by zero overflow - logic result exceeds maximum of 256 bits overflow - integer result exceeds maximum limit for integers too time consuming - computation was rejected dimension mismatch - quantities with different dimensions cannot be compared, added, etc. invalid dimension - operation might require dimensionless arguments operation is not defined for these arguments Computation aborted - encountered numerical instability wrong number of arguments does not take NaN as an argument result out of range undefined for argument domain computation too expensive invalid dimension - function might require dimensionless arguments internal error, please report a bug error invalid expression syntax error conversion target must be a unit unit must not be zero Conversion failed - dimension mismatch unknown function or variable unknown unit recursion not supported %1 is a reserved name, please choose another %1 is a global user definition and cannot be overridden in this session. %1 is a variable name, please choose another or delete the variable argument %1 is used more than once %1 is a built-in unit name, please choose another %1 is a user function name, please choose another or delete the function FunctionRepo max; trials; probability trials; probability hits; trials; probability unix_timestamp; x hours offset to GMT max; total; hits; trials total; hits; trials count; total; hits; trials dividend; divisor x; exponent_bits; significand_bits [; exponent_bias] base; x value; modulo base; exponent; modulo events; average_events average_events x [; precision] Absolute Value Absolute Deviation Arc Cosine Logical AND Area Hyperbolic Cosine Area Hyperbolic Sine Area Hyperbolic Tangent Arc Sine Arc Tangent Arc Tangent with two Arguments Average (Arithmetic Mean) Convert to Binary Representation Binomial Cumulative Distribution Function Binomial Distribution Mean Binomial Probability Mass Function Binomial Distribution Variance Cube Root Complex Conjugate Cosine Hyperbolic Cosine Cotangent Cosecant Convert Unix timestamp to Date Convert to Decimal Representation Degrees of Arc Error Function Complementary Error Function Exponential Arithmetic Chemistry Complex Combinatorics Probability Statistics Aggregation Random Base conversion Number formatting Integer arithmetic Special functions Exponential & Logarithmic Angle conversion Trigonometry Bitwise Floating point Date & Time Linear algebra yyyymmdd.hhmmss; x hours offset to GMT [digits] max [; min] List Literal Convert to Padded Binary Representation Round Toward +∞ (Ceiling) Cosine plus Imaginary Sine Convert to Cis Complex Form Matrix Column Count Population Correlation Matrix (n) Sample Correlation Matrix (n-1) Count Population Covariance Matrix (n) Sample Covariance Matrix (n-1) Cross Product Convert Date to Unix timestamp Determinant Convert to Sexagesimal Notation Dot Product Convert to Engineering Notation Convert to Exponential Complex Form Round Toward −∞ (Floor) Flatten Matrix Fractional Part Extension of Factorials [= (x-1)!] Greatest Common Divisor Least Common Multiple Geometric Mean Gradians of arc Convert to Hexadecimal Representation Convert to Padded Hexadecimal Representation Hypergeometric Cumulative Distribution Function Hypergeometric Distribution Mean Hypergeometric Probability Mass Function Hypergeometric Distribution Variance Integer Quotient Integer Part Imaginary Part Inverse Matrix Decode IEEE-754 Binary Value Encode IEEE-754 Binary Value Decode 16-bit Half-Precision Value Encode 16-bit Half-Precision Value Decode 32-bit Single-Precision Value Encode 32-bit Single-Precision Value Decode 64-bit Double-Precision Value Encode 64-bit Double-Precision Value Decode 128-bit Quad-Precision Value Encode 128-bit Quad-Precision Value Round to 16-bit Half-Precision Value Round to 32-bit Single-Precision Value Round to 64-bit Double-Precision Value Round to 128-bit Quad-Precision Value Residual from 16-bit Half-Precision Rounding Residual from 32-bit Single-Precision Rounding Residual from 64-bit Double-Precision Rounding Residual from 128-bit Quad-Precision Rounding Binary Logarithm Common Logarithm Natural Logarithm Substance Mass Molarity Molar Mass Logarithm to Arbitrary Base Median Absolute Deviation Mask to a bit size Maximum Median Value (50th Percentile) Mean Minimum Numerical Value of Quantity Random Decimal Number Random Integer Number Convert to Rational Representation Modulo Euclidean Modulo Modular Exponentiation Combination (Binomial Coefficient) Logical NOT Permutation (Arrangement) Convert to Octal Representation Convert to Padded Octal Representation Vector or Matrix Norm Logical OR Population Count (Hamming Weight) Phase of Complex Number Poissonian Cumulative Distribution Function Poissonian Distribution Mean Poissonian Probability Mass Function Poissonian Distribution Variance Convert to Phasor Complex Form Convert to Rectangular Complex Form Round Half Away from Zero Round Half Even Convert to Scientific Notation Matrix Row Count List or Matrix Shape Summation Population Standard Deviation (n) Sample Standard Deviation (n-1) Round Toward Zero (Truncation) Matrix Trace Transpose Matrix Population Variance (n) Sample Variance (n-1) Product Radians Matrix Rank Real Part Secant Arithmetic Shift Left Arithmetic Shift Right Signum Sine Hyperbolic Sine Square Root Sum Tangent Convert to Trigonometric Complex Form Turns Hyperbolic Tangent Sign-extend a value Logical XOR FunctionsWidget Domain All Identifier Name Search No match found HistoryWidget Remove All Calculations Above Remove This Calculation Remove All Calculations Below Keypad Inverse cosine The last result Inverse sine Inverse tangent Evaluate expression Division Multiplication Subtraction Addition Clear expression Cosine Backspace Scientific notation Exponential Factorial Natural logarithm Left parenthesis Cube root Common logarithm Modulo Contextual percentage Power Right parenthesis Sine Square root Tangent Pi Decimal separator Assign variable x The variable x MainWindow Radian Gradian Degree Binary Octal Hexadecimal Sexagesimal Engineering decimal Scientific decimal Plain &text &Import... &Load... &Quit &Save... Clear E&xpression Clear &History Copy Last &Result &Copy &Paste &Select Expression &Wrap Selection in Parentheses &Constants F&ull Screen Mode &Functions &History &Keypad Formula &Book &Status Bar Bitfield Use&r Functions &Degree &Radian &Gradian Always on &Top Automatic &Completion Syntax &Highlighting Disabled Small Space Medium Space Large Space &Comma &System Default &Dot Dot &And Comma &0 Digits &15 Digits &2 Digits &3 Digits &50 Digits &8 Digits &Automatic &Engineering &Scientific &Binary &Octal &Hexadecimal &Sexagesimal &Font... &Language... User &Manual Context Help &Donate About &SpeedCrunch &Session &Export &Edit &View Se&ttings &Decimal &Precision &Help Constants Functions History User Functions Type an expression here SpeedCrunch Sessions (*.json);;All Files (*) Load Session Error Can't read from file %1 Merge session being loaded with current session? If no, current variables and display will be cleared. Merge? Save Session Can't write to file %1 All Files (*) Import Session Close Session Angle Mode: Notation: Precision: Turn Revolution Fixed-point decimal Rational Automatic decimal Automatic User &Definitions... &Basic &Scientific (wide) Scientific (narrow) &Custom... Main &Menu User &Variables User &Units &Turn &Revolution Auto-Insert "ans" When Starting with an Operator If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Built-in &functions Built-in &variables &Units User &functions User &variables Show Empty History &Hint When history is empty, show a hint in the status area. Show Live Result &Preview Save &Window Position on Exit Hover Highlighting Group Integer Part Only Keep Entered Expression After Evaluate Number Format... Notation && Precision... After pressing Enter, keep the entered expression selected in the editor. Never Always Only for Single-Line Expressions Automatically Copy New Results to Clipboard Simplify Displayed Expressions History Size &Limit... Nearest, Half &Away (round) Nearest, Half &Even (roundeven) Toward &Zero (trunc) Toward +&∞ (ceil) Toward −&∞ (floor) &Fixed-Point &Rational &Exponential (m·s�¹) &Fractional (m/s) &Rectangular (a + bi) Exponential (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Phasor (r∠θ) &Theme... Check for &Updates Issue Tracker Google Group Facebook &Group &Blogspot Source Code &Zoom &Results &Symbols Unit Notation Rounding Mode &Notation &Angle Mode Complex &Numbers &Form &Imaginary Unit &Window &Editing A&utocomplete Up/Down Arrow History &Appearance &Disabled &Disable Close preview New Session Open Session Split Left Split Right Split Up Split Down Export Session Duplicate Session Rename Session Clear Session Delete Session Close Pane User Variables User Units Clear History Are you sure you want to clear the calculation history? Session name: A session named %1 already exists. Could not create session file %1. Could not write session file %1. Could not rename session file %1. Are you sure you want to delete this session? Custom Precision Fractional digits: Theme Light Themes Dark Themes Preview Colors Select color for %1 Import... Export... Import Theme Theme file (*.json);;All files (*) Invalid theme file. Can't import theme "%1" because it conflicts with a built-in theme. Can't find a writable theme folder. Overwrite Theme A custom theme named "%1" already exists. Do you want to overwrite it? Can't overwrite theme file %1 Can't copy theme file to %1 Export Theme Can't export theme as "%1" because it conflicts with a built-in theme. Can't read the selected session file. Merge session being imported with current session? If no, current variables and display will be cleared. Ignore error? Global User Variable Global User Function Global User Unit History Size Limit Maximum number of history entries for this session (0 = unlimited): Export session as HTML HTML file (*.html) Export session as plain text Text file (*.txt);;Any file (*.*) Display font Could not recalculate from calculation %1: %2 History Size Limit Reached This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Editing calculation. Press Esc twice to cancel. Calculation Settings Invalid recalculation start index System Default Language Select the language: Custom Decimal places: ManualWindow SpeedCrunch Manual %1 - SpeedCrunch Manual NumberFormatDialog Number Format <b>Select the number format for display.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> QObject Global User Variable Global User Function Global User Unit Backspace Clear expression Evaluate expression Insert text Automatic decimal Fixed-point decimal Engineering decimal Scientific decimal Rational Binary Octal Hexadecimal Sexagesimal Update Available A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Check for Updates SpeedCrunch %1 is up to date. No connectivity. Please check your internet connection and try again. Could not verify the latest available version. ResultDisplay Scroll to bottom Copy Expression Copy Result Edit Expression Change Settings Remove Calculation Remove All Calculations Above Remove All Calculations Below New Session Open Session Split Left Split Right Split Up Split Down Import Session Export Session Duplicate Session Rename Session Clear Session Delete Session Close Session Close Pane Main Menu Cancel editing Copy result Edit expression Change settings Remove calculation ResultSlotsDialog Notation & Precision Result Line Enabled Notation Decimal Places Main Line Extra Line #1 Extra Line #2 Extra Line #3 Extra Line #4 Auto UserFunctionListWidget Name Value Description Search No match found Insert Edit Delete Delete All UserUnitListWidget Name Value Description Search No match found Insert Edit Delete Delete All VariableListWidget Name Value Description Search No match found Insert Edit Delete Delete All heldercorreia-speedcrunch-e7ca37f/src/resources/locale/es.ts000066400000000000000000010546201526573132500243640ustar00rootroot00000000000000 AboutBox About SpeedCrunch Acerca de SpeedCrunch Core developers Desarrolladores Original author Autor original Close Cerrar Math engine Motor de cálculo Main author | Logo | Maintainer Autor principal | Logotipo | Mantenedor Thanks Agradecimientos Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Desarrolladores de SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este programa es software libre; puede redistribuirlo y/o modificarlo bajo los términos de la GNU General Public License publicada por la Free Software Foundation, ya sea la versión 2 de la licencia o (a su elección) cualquier versión posterior. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANT�A; ni siquiera la garantía implícita de COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la GNU General Public License para más detalles. BitFieldWidget Reset bits to zero Restablecer bits a cero Invert bits Invertir bits Shift bits left Desplazar bits a la izquierda Shift bits right Desplazar bits a la derecha Book Index �ndice Algebra �lgebra Quadratic Equation Ecuación Cuadrática Logarithmic Base Conversion Cambio de Base de Logaritmo Geometry Geometría Circle Círculo Sector Sector circular Sphere Esfera Cube Cubo Cone Cono Cylinder Cilindro Electronics Electrónica Ohm's Law Ley de Ohm Power Potencia Reactance Reactancia Resonance Resonancia Radio Frequency Frecuencia de Radio Antennas Antenas Characteristic Impedance (coax) Impedancia característica (coaxial) Velocity of Propagation (coax) Velocidad de Propagación (coax) Standing Wave Ratio & Return Loss Razón de Onda Estacionaria y Pérdida de Retorno Free Space Wavelength Longitud de Onda en el Vacío resistance resistencia voltage voltaje current corriente power potencia inductive reactance reactancia inductiva capacitive reactance reactancia capacitiva inductance inductancia capacitance capacitancia frequency frecuencia resonance frequency frecuencia de resonancia area área perimeter perímetro diameter diámetro radius radio volume volumen surface area área de la superficie height altura slant height altura inclinada face diagonal diagonal de la cara space diagonal diagonal espacial edge length largo del lado arc length largo del arco central angle (degrees) ángulo central (en grados) input power potencia de entrada reflected power potencia reflejada transmitted power potencia transmitida return loss pérdida de retorno dielectric constant constante dieléctrica outer conductor's inner diameter diámetro interno del conductor externo inner conductor's outer diameter diámetro externo del conductor interno speed of light velocidad de la luz reflection coefficient coeficiente de reflexión standing wave ratio razón de onda estacionaria normalized impedance impedancia normalizada frequency (Hz) frecuencia (en Hz) BookDock Formula Book Libro de Fórmulas ConstantCompletion Search constants Buscar constantes No match found No se encontraron coincidencias Constants Mathematics Matemáticas Physics (CODATA 2022) Física (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Química (IUPAC - CIAAW 2021) Uncategorized Sin categoría Universal Universales Physicochemical Fisicoquímica Atomic & Nuclear — General Atómica y nuclear — General Atomic & Nuclear — Electroweak Atómica y nuclear — Electrodébil Atomic & Nuclear — Electron Atómica y nuclear — Electrón Atomic & Nuclear — Muon Atómica y nuclear — Muón Atomic & Nuclear — Tau Atómica y nuclear — Tau Atomic & Nuclear — Proton Atómica y nuclear — Protón Atomic & Nuclear — Neutron Atómica y nuclear — Neutrón Atomic & Nuclear — Deuteron Atómica y nuclear — Deuterón Atomic & Nuclear — Triton Atómica y nuclear — Tritón Atomic & Nuclear — Helion Atómica y nuclear — Helión Atomic & Nuclear — Alpha particle Atómica y nuclear — Partícula alfa Atomic & Nuclear — Atomic units Atómica y nuclear — Unidades atómicas Atomic & Nuclear — Energy conversion relationships Atómica y nuclear — Relaciones de conversión de energía Atomic & Nuclear — X-ray units Atómica y nuclear — Unidades de rayos X Atomic & Nuclear — Magnetic shielding corrections Atómica y nuclear — Correcciones de apantallamiento magnético Masses Masas Lifetimes Tiempos de vida Molar Masses Masas molares Electronegativity Electronegatividad Ionization Energy Energía de ionización Nominal Constants (IAU 2015) Constantes nominales (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Mejores estimaciones actuales (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) impedancia característica of vacuum (Z₀) reduced Planck constant (�) constante de Planck reducida (�) vacuum electric permittivity (ϵ₀) permitividad eléctrica del vacío (ϵ₀) Newtonian constant of gravitation (G) Constante newaniana de gravitación (G) vacuum magnetic permeability (μ₀) permeabilidad magnética del vacío (μ₀) Planck constant (h) Constante de Planck (h) speed of light in vacuum (c) velocidad de la luz en el vacío (c) standard acceleration of gravity (gₙ) aceleración estándar de la gravedad (gₙ) Newtonian constant of gravitation over h-bar c Constante newaniana de gravitación sobre h-bar c Planck length Longitud de Planck Planck constant in eV/Hz (h) Constante de Planck en eV/Hz (h) Planck mass Masa de Planck Planck mass energy equivalent in GeV Equivalente energético de la masa de Planck en GeV Planck temperature Temperatura de Planck Planck time Tiempo de Planck reduced Planck constant in eV·s (�) constante de Planck reducida en eV·s (�) reduced Planck constant times c in MeV·fm constante de Planck reducida por c en MeV·fm Bohr magneton Magnetón de Bohr conductance quantum (G₀) cuana de conductancia (G₀) Coulomb constant (kₑ) Constante de Coulomb (kₑ) elementary charge (e) carga elemental (e) elementary charge over h-bar carga elemental sobre h-bar conventional value of Josephson constant valor convencional de constante de Josephson Josephson constant Constante de Josephson conventional value of ampere-90 valor convencional de ampere-90 conventional value of coulomb-90 valor convencional de coulomb-90 conventional value of farad-90 valor convencional de farad-90 conventional value of henry-90 valor convencional de henry-90 conventional value of ohm-90 valor convencional de ohm-90 conventional value of volt-90 valor convencional de volt-90 conventional value of watt-90 valor convencional de watt-90 magnetic flux quantum (Φ₀) cuana de flujo magnético (Φ₀) nuclear magneton magnetón nuclear inverse of conductance quantum enverso de cuana de conductancia conventional value of von Klitzing constant valor convencional de constante de von Klitzeng von Klitzing constant constante de von Klitzeng atomic unit of magnetic dipole moment unidad atómica de momena dipolar magnético atomic unit of magnetic flux density unidad atómica de densidad de flujo magnético Bohr magneton in eV/T Magnetón de Bohr en eV/T Bohr magneton in Hz/T Magnetón de Bohr en Hz/T Bohr magneton in inverse meter per tesla Magnetón de Bohr en metro enverso per tesla Bohr magneton in K/T Magnetón de Bohr en K/T nuclear magneton in eV/T magnetón nuclear en eV/T nuclear magneton in inverse meter per tesla magnetón nuclear en metro enverso per tesla nuclear magneton in K/T magnetón nuclear en K/T nuclear magneton in MHz/T magnetón nuclear en MHz/T Bohr radius (a₀) Radio de Bohr (a₀) fine-structure constant (α) constante de estructura fena (α) Hartree energy (Eₕ) Energía de hartree (Eₕ) Hartree energy in eV Energía de hartree en eV quantum of circulation cuana de circulación quantum of circulation times 2 cuana de circulación por 2 Rydberg constant (R∞) Constante de Rydberg (R∞) atomic mass unit-hartree relationship unidad de masa atómica-hartree relación atomic mass unit-hertz relationship unidad de masa atómica-hercio relación atomic mass unit-inverse meter relationship unidad de masa atómica-metro enverso relación atomic mass unit-joule relationship unidad de masa atómica-julio relación atomic mass unit-kelvin relationship unidad de masa atómica-kelven relación atomic mass unit-kilogram relationship unidad de masa atómica-kilogramo relación atomic unit of 1st hyperpolarizability unidad atómica de 1st hiperpolarizabilidad atomic unit of 2nd hyperpolarizability unidad atómica de 2nd hiperpolarizabilidad atomic unit of charge (e) unidad atómica de carga (e) atomic unit of charge density unidad atómica de densidad de carga atomic unit of current unidad atómica de corriente atomic unit of electric dipole moment unidad atómica de momena dipolar eléctrico atomic unit of electric field unidad atómica de campo eléctrico atomic unit of electric field gradient unidad atómica de gradiente de campo eléctrico atomic unit of electric polarizability unidad atómica de polarizabilidad eléctrica atomic unit of electric potential unidad atómica de potencial eléctrico atomic unit of electric quadrupole moment unidad atómica de momena cuadrupolar eléctrico atomic unit of action unidad atómica de acción atomic unit of energy unidad atómica de energía atomic unit of force unidad atómica de fuerza atomic unit of length unidad atómica de longitud hertz-atomic mass unit relationship hercio-unidad de masa atómica relación hertz-electron volt relationship hercio-electrónvoltio relación hertz-hartree relationship hercio-hartree relación hertz-inverse meter relationship hercio-metro enverso relación hertz-joule relationship hercio-julio relación hertz-kelvin relationship hercio-kelven relación hertz-kilogram relationship hercio-kilogramo relación hyperfine transition frequency of Cs-133 frecuencia de transición hiperfena of Cs-133 inverse fine-structure constant (α�¹) enverse constante de estructura fena (α�¹) inverse meter-atomic mass unit relationship metro enverso-unidad de masa atómica relación inverse meter-electron volt relationship metro enverso-electrónvoltio relación inverse meter-hartree relationship metro enverso-hartree relación inverse meter-hertz relationship metro enverso-hercio relación inverse meter-joule relationship metro enverso-julio relación inverse meter-kelvin relationship metro enverso-kelven relación inverse meter-kilogram relationship metro enverso-kilogramo relación joule-atomic mass unit relationship julio-unidad de masa atómica relación joule-electron volt relationship julio-electrónvoltio relación joule-hertz relationship julio-hercio relación joule-hartree relationship julio-hartree relación joule-inverse meter relationship julio-metro enverso relación joule-kelvin relationship julio-kelven relación joule-kilogram relationship julio-kilogramo relación kelvin-atomic mass unit relationship kelven-unidad de masa atómica relación kelvin-electron volt relationship kelven-electrónvoltio relación kelvin-hertz relationship kelven-hercio relación kelvin-hartree relationship kelven-hartree relación kelvin-inverse meter relationship kelven-metro enverso relación kelvin-joule relationship kelven-julio relación kelvin-kilogram relationship kelven-kilogramo relación kilogram-atomic mass unit relationship kilogramo-unidad de masa atómica relación kilogram-electron volt relationship kilogramo-electrónvoltio relación kilogram-hertz relationship kilogramo-hercio relación kilogram-hartree relationship kilogramo-hartree relación kilogram-inverse meter relationship kilogramo-metro enverso relación kilogram-joule relationship kilogramo-julio relación kilogram-kelvin relationship kilogramo-kelven relación lattice parameter of silicon (a) parámetro reticular of silicon (a) luminous efficacy eficacia lumenosa natural unit of energy unidad natural de energía natural unit of energy in MeV unidad natural de energía en MeV natural unit of action (�) unidad natural de acción (�) natural unit of action in eV·s unidad natural de acción en eV·s natural unit of length unidad natural de longitud natural unit of mass unidad natural de masa natural unit of momentum unidad natural de momena natural unit of momentum in MeV/c unidad natural de momena en MeV/c natural unit of time unidad natural de tiempo natural unit of velocity unidad natural de velocidad Rydberg constant times c in Hz Constante de Rydberg por c en Hz Rydberg constant times hc in eV Constante de Rydberg por hc en eV Rydberg constant times hc in J Constante de Rydberg por hc en J Fermi coupling constant Constante de acoplamiena de Fermi weak mixing angle ángulo de mezcla débil W to Z mass ratio W a Z relación de masas Thomson cross section (σₑ) Sección eficaz de Thomson (σₑ) electron mass (mₑ) electrón masa (mₑ) electron mass in u electrón masa en u electron mass energy equivalent (mₑ·c²) electrón equivalente energético de la masa (mₑ·c²) electron mass energy equivalent in MeV electrón equivalente energético de la masa en MeV reduced Compton wavelength reduced longitud de onda de Compan classical electron radius (rₑ) radio clásico del electrón (rₑ) electron charge to mass quotient electrón cociente carga-masa electron-deuteron magnetic moment ratio electrón-deuterón momena magnético ratio electron-deuteron mass ratio electrón-deuterón relación de masas electron g factor (gₑ) electrón g facar (gₑ) electron gyromagnetic ratio (γₑ) electrón relación giromagnética (γₑ) electron gyromagnetic ratio in MHz/T electrón relación giromagnética en MHz/T electron-helion mass ratio electrón-helión relación de masas electron magnetic moment (μₑ) electrón momena magnético (μₑ) electron magnetic moment anomaly (aₑ) electrón anomalía del momena magnético (aₑ) electron magnetic moment to Bohr magneton ratio electrón momena magnético a magnetón de Bohr ratio electron magnetic moment to nuclear magneton ratio electrón momena magnético a magnetón nuclear ratio electron molar mass (Mₑ) electrón masa molar (Mₑ) electron-muon magnetic moment ratio electrón-muón momena magnético ratio electron-muon mass ratio electrón-muón relación de masas electron-neutron magnetic moment ratio electrón-neutrón momena magnético ratio electron-neutron mass ratio electrón-neutrón relación de masas electron-proton magnetic moment ratio electrón-protón momena magnético ratio electron-proton mass ratio electrón-protón relación de masas electron relative atomic mass (Ar(e)) electrón masa atómica relativa (Ar(e)) electron-tau mass ratio electrón-tau relación de masas electron to alpha particle mass ratio electrón a partícula alfa relación de masas electron to shielded helion magnetic moment ratio electrón a apantallado helión momena magnético ratio electron to shielded proton magnetic moment ratio electrón a apantallado protón momena magnético ratio electron-triton mass ratio electrón-tritón relación de masas electron volt-atomic mass unit relationship electrónvoltio-unidad de masa atómica relación electron volt-hartree relationship electrónvoltio-hartree relación electron volt-hertz relationship electrónvoltio-hercio relación electron volt-inverse meter relationship electrónvoltio-metro enverso relación electron volt-joule relationship electrónvoltio-julio relación electron volt-kelvin relationship electrónvoltio-kelven relación electron volt-kilogram relationship electrónvoltio-kilogramo relación hartree-atomic mass unit relationship hartree-unidad de masa atómica relación hartree-electron volt relationship hartree-electrónvoltio relación muon Compton wavelength muón longitud de onda de Compan muon-electron mass ratio muón-electrón relación de masas muon g factor muón g facar muon magnetic moment muón momena magnético muon magnetic moment anomaly muón anomalía del momena magnético muon magnetic moment to Bohr magneton ratio muón momena magnético a magnetón de Bohr ratio muon magnetic moment to nuclear magneton ratio muón momena magnético a magnetón nuclear ratio muon mass muón masa muon mass energy equivalent muón equivalente energético de la masa muon mass energy equivalent in MeV muón equivalente energético de la masa en MeV muon mass in u muón masa en u muon molar mass muón masa molar muon-neutron mass ratio muón-neutrón relación de masas muon-proton magnetic moment ratio muón-protón momena magnético ratio muon-proton mass ratio muón-protón relación de masas muon-tau mass ratio muón-tau relación de masas reduced muon Compton wavelength reduced muón longitud de onda de Compan reduced tau Compton wavelength reduced tau longitud de onda de Compan tau Compton wavelength tau longitud de onda de Compan tau-electron mass ratio tau-electrón relación de masas tau mass tau masa tau mass energy equivalent tau equivalente energético de la masa tau mass in u tau masa en u tau molar mass tau masa molar tau-muon mass ratio tau-muón relación de masas tau-neutron mass ratio tau-neutrón relación de masas tau-proton mass ratio tau-protón relación de masas proton charge to mass quotient protón cociente carga-masa proton Compton wavelength protón longitud de onda de Compan proton-electron mass ratio protón-electrón relación de masas proton g factor (gₚ) protón g facar (gₚ) proton gyromagnetic ratio (γₚ) protón relación giromagnética (γₚ) proton gyromagnetic ratio in MHz/T protón relación giromagnética en MHz/T proton magnetic moment (μₚ) protón momena magnético (μₚ) proton magnetic moment to Bohr magneton ratio protón momena magnético a magnetón de Bohr ratio proton magnetic moment to nuclear magneton ratio protón momena magnético a magnetón nuclear ratio proton magnetic shielding correction protón corrección de apantallamiena magnético proton mass (mₚ) protón masa (mₚ) proton mass energy equivalent protón equivalente energético de la masa proton mass energy equivalent in MeV protón equivalente energético de la masa en MeV proton mass in u protón masa en u proton molar mass (Mₚ) protón masa molar (Mₚ) proton-muon mass ratio protón-muón relación de masas proton-neutron magnetic moment ratio protón-neutrón momena magnético ratio proton-neutron mass ratio protón-neutrón relación de masas proton relative atomic mass (Ar(p)) protón masa atómica relativa (Ar(p)) proton rms charge radius protón radio de carga rms proton-tau mass ratio protón-tau relación de masas reduced proton Compton wavelength reduced protón longitud de onda de Compan shielded proton gyromagnetic ratio apantallado protón relación giromagnética shielded proton gyromagnetic ratio in MHz/T apantallado protón relación giromagnética en MHz/T shielded proton magnetic moment apantallado protón momena magnético shielded proton magnetic moment to Bohr magneton ratio apantallado protón momena magnético a magnetón de Bohr ratio shielded proton magnetic moment to nuclear magneton ratio apantallado protón momena magnético a magnetón nuclear ratio neutron Compton wavelength neutrón longitud de onda de Compan neutron-electron magnetic moment ratio neutrón-electrón momena magnético ratio neutron-electron mass ratio neutrón-electrón relación de masas neutron g factor (gₙ) neutrón g facar (gₙ) neutron gyromagnetic ratio (γₙ) neutrón relación giromagnética (γₙ) neutron gyromagnetic ratio in MHz/T neutrón relación giromagnética en MHz/T neutron magnetic moment (μₙ) neutrón momena magnético (μₙ) neutron magnetic moment to Bohr magneton ratio neutrón momena magnético a magnetón de Bohr ratio neutron magnetic moment to nuclear magneton ratio neutrón momena magnético a magnetón nuclear ratio neutron mass (mₙ) neutrón masa (mₙ) neutron mass energy equivalent neutrón equivalente energético de la masa neutron mass energy equivalent in MeV neutrón equivalente energético de la masa en MeV neutron mass in u neutrón masa en u neutron molar mass (Mₙ) neutrón masa molar (Mₙ) neutron-muon mass ratio neutrón-muón relación de masas neutron-proton magnetic moment ratio neutrón-protón momena magnético ratio neutron-proton mass difference neutrón-protón diferencia de masa neutron-proton mass difference energy equivalent neutrón-protón equivalente energético de la diferencia de masa neutron-proton mass difference energy equivalent in MeV neutrón-protón equivalente energético de la diferencia de masa en MeV neutron-proton mass difference in u neutrón-protón diferencia de masa en u neutron-proton mass ratio neutrón-protón relación de masas neutron relative atomic mass (Ar(n)) neutrón masa atómica relativa (Ar(n)) neutron-tau mass ratio neutrón-tau relación de masas neutron to shielded proton magnetic moment ratio neutrón a apantallado protón momena magnético ratio reduced neutron Compton wavelength reduced neutrón longitud de onda de Compan deuteron-electron magnetic moment ratio deuterón-electrón momena magnético ratio deuteron-electron mass ratio deuterón-electrón relación de masas deuteron g factor deuterón g facar deuteron magnetic moment deuterón momena magnético deuteron magnetic moment to Bohr magneton ratio deuterón momena magnético a magnetón de Bohr ratio deuteron magnetic moment to nuclear magneton ratio deuterón momena magnético a magnetón nuclear ratio deuteron mass deuterón masa deuteron mass energy equivalent deuterón equivalente energético de la masa deuteron mass energy equivalent in MeV deuterón equivalente energético de la masa en MeV deuteron mass in u deuterón masa en u deuteron molar mass deuterón masa molar deuteron-neutron magnetic moment ratio deuterón-neutrón momena magnético ratio deuteron-proton magnetic moment ratio deuterón-protón momena magnético ratio deuteron-proton mass ratio deuterón-protón relación de masas deuteron relative atomic mass (Ar(d)) deuterón masa atómica relativa (Ar(d)) deuteron rms charge radius deuterón radio de carga rms triton-electron mass ratio tritón-electrón relación de masas triton g factor (gₜ) tritón g facar (gₜ) triton magnetic moment (μₜ) tritón momena magnético (μₜ) triton magnetic moment to Bohr magneton ratio tritón momena magnético a magnetón de Bohr ratio triton magnetic moment to nuclear magneton ratio tritón momena magnético a magnetón nuclear ratio triton mass (mₜ) tritón masa (mₜ) triton mass energy equivalent tritón equivalente energético de la masa triton mass energy equivalent in MeV tritón equivalente energético de la masa en MeV triton mass in u tritón masa en u triton molar mass (Mₜ) tritón masa molar (Mₜ) triton-proton mass ratio tritón-protón relación de masas triton relative atomic mass (Ar(t)) tritón masa atómica relativa (Ar(t)) triton to proton magnetic moment ratio tritón a protón momena magnético ratio helion-electron mass ratio helión-electrón relación de masas helion g factor (gₕ) helión g facar (gₕ) helion magnetic moment (μₕ) helión momena magnético (μₕ) helion magnetic moment to Bohr magneton ratio helión momena magnético a magnetón de Bohr ratio helion magnetic moment to nuclear magneton ratio helión momena magnético a magnetón nuclear ratio helion mass (mₕ) helión masa (mₕ) helion mass energy equivalent helión equivalente energético de la masa helion mass energy equivalent in MeV helión equivalente energético de la masa en MeV helion mass in u helión masa en u helion molar mass (Mₕ) helión masa molar (Mₕ) helion-proton mass ratio helión-protón relación de masas helion relative atomic mass (Ar(h)) helión masa atómica relativa (Ar(h)) helion shielding shift helión desplazamiena de apantallamiena shielded helion gyromagnetic ratio apantallado helión relación giromagnética shielded helion gyromagnetic ratio in MHz/T apantallado helión relación giromagnética en MHz/T shielded helion magnetic moment apantallado helión momena magnético shielded helion magnetic moment to Bohr magneton ratio apantallado helión momena magnético a magnetón de Bohr ratio shielded helion magnetic moment to nuclear magneton ratio apantallado helión momena magnético a magnetón nuclear ratio shielded helion to proton magnetic moment ratio apantallado helión a protón momena magnético ratio shielded helion to shielded proton magnetic moment ratio apantallado helión a apantallado protón momena magnético ratio alpha particle mass partícula alfa masa alpha particle mass in u partícula alfa masa en u alpha particle mass energy equivalent partícula alfa equivalente energético de la masa alpha particle mass energy equivalent in MeV partícula alfa equivalente energético de la masa en MeV alpha particle-electron mass ratio partícula alfa-electrón relación de masas alpha particle-proton mass ratio partícula alfa-protón relación de masas alpha particle rms charge radius partícula alfa radio de carga rms alpha particle molar mass partícula alfa masa molar alpha particle relative atomic mass (Ar(α)) partícula alfa masa atómica relativa (Ar(α)) atomic mass constant (mᵤ) constante de masa atómica (mᵤ) Avogadro constant Constante de Avogadro Boltzmann constant (k) Constante de Boltzmann (k) Boltzmann constant in eV/K Constante de Boltzmann en eV/K Boltzmann constant in Hz/K Constante de Boltzmann en Hz/K Boltzmann constant in inverse meter per kelvin Constante de Boltzmann en metro enverso per kelven electron volt (eV) electrónvoltio (eV) Faraday constant (F) Constante de Faraday (F) first radiation constant (c�) primera constante de radiación (c�) first radiation constant for spectral radiance primera constante de radiación para radiancia espectral molar gas constant (R) constante molar de los gases (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Constante de Loschmidt (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Constante de Loschmidt (n₀, 273.15 K, 101.325 kPa) molar Planck constant molar constante de Planck second radiation constant (c₂) segunda constante de radiación (c₂) Stefan-Boltzmann constant (σ) Stefan-constante de Boltzmann (σ) lattice spacing of ideal Si (d₂₂₀) espaciado reticular of ideal Si (d₂₂₀) atomic mass constant energy equivalent equivalente energético de la constante de masa atómica atomic mass constant energy equivalent in MeV equivalente energético de la constante de masa atómica en MeV atomic mass unit-electron volt relationship unidad de masa atómica-electrónvoltio relación molar mass constant (Mᵤ) masa molar constant (Mᵤ) molar mass of carbon-12 masa molar of carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) volumen molar del gas ideal (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volumen molar del gas ideal (273.15 K, 101.325 kPa) molar volume of silicon volumen molar del silicio Sackur-Tetrode constant (1 K, 100 kPa) Constante de Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Constante de Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant Constante de la ley de desplazamiena en frecuencia de Wien Wien wavelength displacement law constant Constante de la ley de desplazamiena en longitud de onda de Wien standard atmosphere (atm) atmósfera estándar (atm) standard-state pressure (p°) presión de estado estándar (p°) Angstrom star (Å*) Angstrom estrella (Å*) Copper x unit Unidad x de cobre Molybdenum x unit Unidad x de molibdeno atomic unit of magnetizability unidad atómica de magnetizabilidad atomic unit of mass (mₑ) unidad atómica de masa (mₑ) atomic unit of momentum unidad atómica de momena atomic unit of permittivity unidad atómica de permitividad atomic unit of time unidad atómica de tiempo atomic unit of velocity unidad atómica de velocidad hartree-hertz relationship hartree-hercio relación hartree-inverse meter relationship hartree-metro enverso relación hartree-joule relationship hartree-julio relación hartree-kelvin relationship hartree-kelven relación hartree-kilogram relationship hartree-kilogramo relación shielding difference of d and p in HD diferencia de apantallamiena of d and p en HD shielding difference of t and p in HT diferencia de apantallamiena of t and p en HT pi (π) pi (π) Euler's number (e) Número de Euler (e) golden ratio (φ) razón áurea (φ) Euler-Mascheroni constant (γ) Constante de Euler-Mascheroni (γ) nominal solar radius radio solar nomenal nominal solar total irradiance irradiancia solar atal nomenal nominal solar luminosity lumenosidad solar nomenal nominal solar effective temperature temperatura efectiva solar nomenal nominal solar mass parameter parámetro de masa solar nomenal nominal terrestrial equatorial radius radio ecuaarial terrestre nomenal nominal terrestrial polar radius radio polar terrestre nomenal nominal terrestrial mass parameter parámetro de masa terrestre nomenal nominal jovian equatorial radius radio ecuaarial joviano nomenal nominal jovian polar radius radio polar joviano nomenal nominal jovian mass parameter parámetro de masa joviano nomenal average value of one minus the rate of TCG relative to TCB valor medio de uno menos la tasa de TCG relativa a TCB solar mass parameter (TCB-compatible) parámetro de masa solar (TCB-compatible) solar mass parameter (TDB-compatible) parámetro de masa solar (TDB-compatible) equatorial radius of the Earth (TT-compatible) radio ecuaarial de la Tierra (TT-compatible) dynamical form factor of the Earth facar de forma denámico de la Tierra time rate of change in the dynamical form factor of the Earth tiempo rate of change en the facar de forma denámico de la Tierra geocentric gravitational constant (TCB-compatible) constante gravitacional geocéntrica (TCB-compatible) geocentric gravitational constant (TT-compatible) constante gravitacional geocéntrica (TT-compatible) geocentric gravitational constant (TDB-compatible) constante gravitacional geocéntrica (TDB-compatible) potential of the geoid potencial del geoide nominal mean angular velocity of the Earth (TT-compatible) velocidad angular media nomenal de la Tierra (TT-compatible) ratio mass of the Moon to the Earth relación de masa de la Luna respeca a la Tierra ratio of the mass of the Sun to Mercury relación de la masa del Sol respeca a Mercury ratio of the mass of the Sun to Venus relación de la masa del Sol respeca a Venus ratio of the mass of the Sun to Mars relación de la masa del Sol respeca a Mars ratio of the mass of the Sun to Jupiter relación de la masa del Sol respeca a Jupiter ratio of the mass of the Sun to Saturn relación de la masa del Sol respeca a Saturn ratio of the mass of the Sun to Uranus relación de la masa del Sol respeca a Uranus ratio of the mass of the Sun to Neptune relación de la masa del Sol respeca a Neptune ratio of the mass of the Sun to (134340) Pluto relación de la masa del Sol respeca a (134340) Plua ratio of the mass of the Sun to (136199) Eris relación de la masa del Sol respeca a (136199) Eris ratio of the mass of (1) Ceres to the Sun relación de la masa de (1) Ceres a the Sun ratio of the mass of (2) Pallas to the Sun relación de la masa de (2) Pallas a the Sun ratio of the mass of (4) Vesta to the Sun relación de la masa de (4) Vesta a the Sun mean obliquity of the ecliptic at J2000.0 oblicuidad media de la eclíptica en J2000.0 Electromagnetic Electromagnetismo Compton wavelength Longitud de onda Compton Astronomy Astronomía ConstantsWidget Domain Dominio Subdomain Subdominio No match found No se encontraron coincidencias Name Nombre Value Valor Unit Unidad Search Búsqueda All Todas CustomKeypadDialog Custom Keypad Teclado personalizado Rows: Filas: Columns: Columnas: Copy preset: Copiar preajuste: Basic Básico Scientific (wide) Científico (ancho) Scientific (narrow) Científico (estrecho) Apply Aplicar Row Fila Column Columna Label Etiqueta Behavior Comportamiento Text Texto DiagnosticsDialog App Diagnostics Diagnóstico de la aplicación Copy to Clipboard Copiar al portapapeles Editor Unit Unidad User unit Unidad de usuario User function Función de usuario Argument Argumento Current result:<br/>%1 Resultado actual:<br/>%1 Selection result:<br/>%1 Resultado de la selección:<br/>%1 Selection result: n/a Resultado de la selección: vacío Selection result: %1 Resultado de la selección: %1 second segundo metre metro kilogram kilogramo mole mol radian radián steradian estereorradián degree Celsius grado Celsius cubic metre metro cúbico cubic millimetre milímetro cúbico cubic centimetre centímetro cúbico cubic decimetre decímetro cúbico cubic kilometre kilómetro cúbico square millimetre milímetro cuadrado square kilometre kilómetro cuadrado square metre metro cuadrado minute minuto hour hora day día astronomical unit unidad astronómica degree grado arcminute minuto de arco arcsecond segundo de arco milliarcsecond milisegundo de arco microarcsecond microsegundo de arco hectare hectárea litre litro tonne tonelada Dalton dalton electronvolt electronvoltio Angstrom angstrom atmosphere atmósfera atomic mass unit unidad de masa atómica British thermal unit unidad térmica británica calorie caloría carat quilate cup taza cup (Imperial) taza (imperial) cup (Japanese) taza (japonesa) cup (US) taza (EE. UU.) degree Fahrenheit grado Fahrenheit fathom braza fluid ounce (Imperial) onza líquida (imperial) fluid ounce (US) onza líquida (EE. UU.) fluid dram (Imperial) dracma líquido (imperial) fluid dram (US) dracma líquido (EE. UU.) foot pie square foot pie cuadrado cubic foot pie cúbico gallon (Imperial) galón (imperial) gallon (US) galón (EE. UU.) gill (Imperial) gill (imperial) gill (US) gill (EE. UU.) gradian gradián grain grano gram gramo Hartley hartley Hartree energy unit unidad de energía Hartree horsepower caballo de fuerza inch pulgada square inch pulgada cuadrada cubic inch pulgada cúbica karat quilate knot nudo lightminute minuto luz lightsecond segundo luz lightyear año luz long ton tonelada larga mile milla square mile milla cuadrada cubic mile milla cúbica mile per hour milla por hora kilometre per hour kilómetro por hora nautical mile milla náutica ounce onza parsec pársec pint (Imperial) pinta (imperial) pint (US) pinta (EE. UU.) pound libra pounds per square inch libras por pulgada cuadrada quart (Imperial) cuarto (imperial) quart (US) cuarto (EE. UU.) oil barrel barril de petróleo beer barrel (US) barril de cerveza (EE. UU.) square yard yarda cuadrada cubic yard yarda cúbica short ton tonelada corta tablespoon cucharada tablespoon (Australian) cucharada (australiana) tablespoon (Imperial) cucharada (imperial) tablespoon (US) cucharada (EE. UU.) dessert spoon cuchara de postre teaspoon cucharadita teaspoon (Imperial) cucharadita (imperial) teaspoon (US) cucharadita (EE. UU.) turn vuelta revolution revolución revolution per minute revolución por minuto week semana kilowatt hour kilovatio hora millimetre of mercury milímetro de mercurio yard yarda Julian century siglo juliano Julian year año juliano sidereal year año sidéreo tropical year año tropical Evaluator invalid expression expresión inválida division by zero división por cero too time consuming - computation was rejected demasiado tiempo de cálculo - operación denegada dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensión incompatible - no se pueden comparar, sumar, etc. cantidades con distintas dimensiones invalid dimension - operation might require dimensionless arguments dimensión incorrecta - puede que la operación necesite argumentos adimensionales Computation aborted - encountered numerical instability Cálculo detenido - se ha encontrado una inestabilidad numérica invalid dimension - function might require dimensionless arguments dimensión incorrecta - puede que la función necesite argumentos adimensionales error error unit must not be zero la unidad no puede ser cero Conversion failed - dimension mismatch Fallo de conversión - las dimensiones no concuerdan unknown function or variable función o variable desconocida recursion not supported no se permite la recursividad cannot operate on a NaN No se puede operar con un NaN underflow - tiny result is out of SpeedCrunch's number range El resultado es demasiado pequeño para ser representado dentro del rango numérico de SpeedCrunch overflow - huge result is out of SpeedCrunch's number range El resultado es demasiado grande para ser representado dentro del rango numérico de SpeedCrunch overflow - logic result exceeds maximum of 256 bits El resultado lógico excede los 256 bits permitidos overflow - integer result exceeds maximum limit for integers El resultado excede el límite máximo para enteros operation is not defined for these arguments la operación no está definida para estos argumentos wrong number of arguments número de argumentos incorrecto does not take NaN as an argument no puede usarse un NaN como argumento result out of range resultado fuera de rango undefined for argument domain indefinido para el dominio del argumento computation too expensive operación demasiado costosa internal error, please report a bug error interno, informe de este error syntax error error de sintaxis conversion target must be a unit el destino de conversión debe ser una unidad unknown unit unidad desconocida %1 is a reserved name, please choose another %1 es un nombre reservado; elija otro %1 is a global user definition and cannot be overridden in this session. %1 es una definición global de usuario y no puede sobrescribirse en esta sesión. %1 is a variable name, please choose another or delete the variable %1 es el nombre de una variable; elija otro o elimine la variable argument %1 is used more than once el argumento %1 se usa más de una vez %1 is a built-in unit name, please choose another %1 es un nombre de unidad integrado; elija otro %1 is a user function name, please choose another or delete the function %1 es el nombre de una función definida por el usuario; elija otro o elimine la función FunctionRepo max; trials; probability máximo; intentos; probabilidad trials; probability intentos; probabilidad hits; trials; probability aciertos; intentos; probabilidad max; total; hits; trials máximo; total; aciertos; intentos total; hits; trials total; aciertos; intentos count; total; hits; trials cuenta; total; aciertos; intentos dividend; divisor dividendo; divisor x; exponent_bits; significand_bits [; exponent_bias] x; bits_exponente; bits_significativos [; sesgo_exponente] base; x base; x value; modulo valor; módulo base; exponent; modulo base; exponente; módulo events; average_events sucesos; sucesos_promedio average_events sucesos_promedio x [; precision] x [; precisión] Absolute Value Valor Absoluto Absolute Deviation Desviación Absoluta Arc Cosine Arcocoseno Logical AND Conjunción lógica Area Hyperbolic Cosine Arcocoseno Hiperbólico Area Hyperbolic Sine Arcoseno Hiperbólico Area Hyperbolic Tangent Arcotangente Hiperbólico Arc Sine Arcoseno Arc Tangent Arcotangente Arc Tangent with two Arguments Arcotangente con dos argumentos Average (Arithmetic Mean) Promedio (Media Aritmética) Binomial Cumulative Distribution Function Función de Distribución Binomial Binomial Distribution Mean Media de Distribución Binomial Binomial Probability Mass Function Función de Probabilidad Binomial Binomial Distribution Variance Varianza de Distribución Binomial Cube Root Raíz Cúbica Complex Conjugate Conjugado complejo Cosine Coseno Hyperbolic Cosine Coseno Hiperbólico Cotangent Cotangente Cosecant Cosecante Convert Unix timestamp to Date Convertir marca de tiempo Unix a fecha Degrees of Arc Grados de Arco Error Function Función de Error Complementary Error Function Función de Error Complementaria Exponential Exponencial Fractional Part Parte Fraccionaria Extension of Factorials [= (x-1)!] Extensión de Factoriales [= (x-1)!] Greatest Common Divisor Máximo Común Divisor Geometric Mean Media Geométrica Gradians of arc Gradianes de arco Hypergeometric Cumulative Distribution Function Función de Distribución Hipergeométrica Hypergeometric Distribution Mean Media de Distribución Hipergeométrica Hypergeometric Probability Mass Function Función de Probabilidad Hipergeométrica Hypergeometric Distribution Variance Varianza de Distribución Hipergeométrica Integer Quotient Cociente Entero Integer Part Parte Entera Imaginary Part Parte Imaginaria Decode IEEE-754 Binary Value Decodificar valor binario IEEE-754 Encode IEEE-754 Binary Value Codificar valor binario IEEE-754 Decode 16-bit Half-Precision Value Decodificar valor de media precisión de 16 bits Encode 16-bit Half-Precision Value Codificar valor de media precisión de 16 bits Decode 32-bit Single-Precision Value Decodificar valor de precisión simple de 32 bits Encode 32-bit Single-Precision Value Codificar valor de precisión simple de 32 bits Decode 64-bit Double-Precision Value Decodificar valor de doble precisión de 64 bits Encode 64-bit Double-Precision Value Codificar valor de doble precisión de 64 bits Decode 128-bit Quad-Precision Value Decodificar valor de precisión cuádruple de 128 bits Encode 128-bit Quad-Precision Value Codificar valor de precisión cuádruple de 128 bits Binary Logarithm Logaritmo Binario Common Logarithm Logaritmo Vulgar Natural Logarithm Logaritmo Natural Logarithm to Arbitrary Base Logaritmo de Base Arbitraria Mask to a bit size Emascaramiento de bits Maximum Máximo Median Value (50th Percentile) Valor Medio (Percentil 50) Minimum Mínimo Modulo Módulo Euclidean Modulo Módulo euclidiano Modular Exponentiation Exponenciación modular Combination (Binomial Coefficient) Combinación (Coeficiente Binomial) Logical NOT Negación lógica Permutation (Arrangement) Permutación (Arreglo) Convert to Binary Representation Convertir a Binario Arithmetic Aritmética Chemistry Química Complex Complejos Combinatorics Combinatoria Probability Probabilidad Statistics Estadística Aggregation Agregación Random Aleatorio Base conversion Conversión de base Number formatting Formato numérico Integer arithmetic Aritmética de enteros Special functions Funciones especiales Exponential & Logarithmic Exponencial y logarítmica Angle conversion Conversión de ángulos Trigonometry Trigonometría Bitwise Bit a bit Floating point Coma flotante Date & Time Fecha y hora Linear algebra �lgebra lineal unix_timestamp; x hours offset to GMT unix_timestamp; x horas de desfase con respecto a GMT yyyymmdd.hhmmss; x hours offset to GMT aaaammdd.hhmmss; x horas de desfase respecto a GMT [digits] [dígitos] max [; min] máx [; mín] List Literal Literal de lista Convert to Padded Binary Representation Convertir a representación binaria con relleno Round Toward +∞ (Ceiling) Redondear hacia +∞ (techo) Cosine plus Imaginary Sine Coseno más seno imaginario Convert to Cis Complex Form Convertir a forma compleja cis Matrix Column Count Número de columnas de la matriz Population Correlation Matrix (n) Matriz de correlación poblacional (n) Sample Correlation Matrix (n-1) Matriz de correlación muestral (n-1) Count Conteo Population Covariance Matrix (n) Matriz de covarianza poblacional (n) Sample Covariance Matrix (n-1) Matriz de covarianza muestral (n-1) Cross Product Producto vectorial Convert Date to Unix timestamp Convertir fecha a marca de tiempo Unix Convert to Decimal Representation Convertir a Decimal Determinant Determinante Convert to Sexagesimal Notation Convertir a notación sexagesimal Dot Product Producto escalar Convert to Engineering Notation Convertir a notación de ingeniería Convert to Exponential Complex Form Convertir a forma compleja exponencial Round Toward −∞ (Floor) Redondear hacia −∞ (suelo) Flatten Matrix Aplanar matriz Least Common Multiple Mínimo común múltiplo Convert to Hexadecimal Representation Convertir a Hexadecimal Convert to Padded Hexadecimal Representation Convertir a representación hexadecimal con relleno Inverse Matrix Matriz inversa Round to 16-bit Half-Precision Value Redondear a valor de media precisión de 16 bits Round to 32-bit Single-Precision Value Redondear a valor de precisión simple de 32 bits Round to 64-bit Double-Precision Value Redondear a valor de doble precisión de 64 bits Round to 128-bit Quad-Precision Value Redondear a valor de precisión cuádruple de 128 bits Residual from 16-bit Half-Precision Rounding Residuo del redondeo de media precisión de 16 bits Residual from 32-bit Single-Precision Rounding Residuo del redondeo de precisión simple de 32 bits Residual from 64-bit Double-Precision Rounding Residuo del redondeo de doble precisión de 64 bits Residual from 128-bit Quad-Precision Rounding Residuo del redondeo de precisión cuádruple de 128 bits Substance Mass Masa de sustancia Molarity Molaridad Molar Mass Masa molar Median Absolute Deviation Desviación absoluta mediana Mean Media Numerical Value of Quantity Valor numérico de la magnitud Random Decimal Number Número decimal aleatorio Random Integer Number Número entero aleatorio Convert to Rational Representation Convertir a representación racional Convert to Octal Representation Convertir a Octal Convert to Padded Octal Representation Convertir a representación octal con relleno Vector or Matrix Norm Norma de vector o matriz Logical OR Disyunción lógica Population Count (Hamming Weight) Conteo de población (peso de Hamming) Phase of Complex Number Fase del Número Complejo Poissonian Cumulative Distribution Function Función de Distribución de Poisson Poissonian Distribution Mean Media de Distribución de Poisson Poissonian Probability Mass Function Función de Probabilidad de Poisson Poissonian Distribution Variance Varianza de Distribución de Poisson Convert to Phasor Complex Form Convertir a forma compleja fasorial Convert to Rectangular Complex Form Convertir a forma compleja rectangular Round Half Away from Zero Redondear mitad alejándose de cero Round Half Even Redondear mitad al par Nth Root Raíz enésima Convert to Scientific Notation Convertir a notación científica Matrix Row Count Número de filas de la matriz List or Matrix Shape Forma de lista o matriz Summation Sumatoria Population Standard Deviation (n) Desviación estándar poblacional (n) Sample Standard Deviation (n-1) Desviación estándar muestral (n-1) Round Toward Zero (Truncation) Redondear hacia cero (truncamiento) Matrix Trace Traza de la matriz Transpose Matrix Transponer matriz Population Variance (n) Varianza poblacional (n) Sample Variance (n-1) Varianza muestral (n-1) Product Producto Radians Radianes Matrix Rank Rango de matriz Real Part Parte Real Secant Secante Arithmetic Shift Left Desplazamiento Aritmético hacia la Izquierda Arithmetic Shift Right Desplazamiento Aritmético hacia la Derecha Signum Signo Sine Seno Hyperbolic Sine Seno Hiperbólico Square Root Raíz Cuadrada Sum Suma Tangent Tangente Convert to Trigonometric Complex Form Convertir a forma compleja trigonométrica Turns Vueltas Hyperbolic Tangent Tangente Hiperbólica Sign-extend a value Extender el signo de un valor Logical XOR Disyunción excluyente FunctionsWidget Domain Dominio All Todo Name Nombre Search Búsqueda No match found No se encontraron coincidencias Identifier Identificador HistoryWidget Remove All Calculations Above Eliminar todos los cálculos superiores Remove This Calculation Eliminar este cálculo Remove All Calculations Below Eliminar todos los cálculos inferiores Keypad Inverse cosine Inversa del coseno The last result Último resultado Inverse sine Inversa del seno Inverse tangent Inversa de la tangente Evaluate expression Evaluar expresión Division División Multiplication Multiplicación Subtraction Resta Addition Suma Clear expression Borrar expresión Cosine Coseno Backspace Retroceso Scientific notation Notación científica Exponential Exponencial Factorial Factorial Natural logarithm Logaritmo natural Left parenthesis Paréntesis izquierdo Nth root Raíz enésima Argument separator Separador de argumentos Square Cuadrado Common logarithm Logaritmo común Modulo Módulo Contextual percentage Porcentaje contextual Power Potencia Right parenthesis Paréntesis derecho Sine Seno Square root Raíz cuadrada Tangent Tangente Pi Pi Decimal separator Separador decimal MainWindow Radian Radián Degree Grado Gradian Gradián Binary Binario Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Engineering decimal Decimal de ingeniería Scientific decimal Decimal científico &Import... &Importar... &Quit &Salir Clear E&xpression Borrar E&xpresión Clear &History Borrar &Historial &Copy &Copiar &Paste &Pegar &Select Expression &Seleccionar expresión &Constants &Constantes &Functions &Funciones &History &Historial &Status Bar Barra de &estado Bitfield Campo de bits Use&r Functions Funciones de Usua&rio &Degree Gra&do &Radian Ra&dián &Gradian &Gradián Re&volution &Revolución Auto-Insert a&ns I&nsertar ans automáticamente Automatic &Completion &Completado Automático &Built-in Functions &Funciones integradas Built-in &Variables &Variables integradas User &Functions Fu&nciones del Usuario User Va&riables Va&riables de usuario Open a Private Tab on Startup Abrir una pestaña privada al iniciar Open and focus a new private tab whenever SpeedCrunch starts. Abrir y activar una nueva pestaña privada cada vez que se inicie SpeedCrunch. Syntax &Highlighting &Resaltado de la Sintaxis Group Digits in &Input Agrupar díg&itos en la entrada Automatic Input &Adjustments &Ajustes automáticos de entrada Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ajustar automáticamente los operadores, los espacios, los paréntesis y las potencias, y limitar la entrada a caracteres válidos. Group input digits using the selected number format. Agrupar los dígitos de entrada según el formato numérico seleccionado. &Blinking Cursor &Cursor parpadeante Blink the cursor in the expression editor. Hacer parpadear el cursor en el editor de expresiones. &Escape Clears Editor &Escape vacía el editor Clear the focused expression editor with Escape after dismissing any popup or preview. Vaciar el editor de expresiones activo con Escape después de cerrar cualquier ventana emergente o vista previa. Keep Expression After Evaluation Conservar la expresión después del cálculo Copy New Results Automatically Copiar automáticamente los nuevos resultados &Comma &Coma &System Default Predeterminado del &sistema &Dot &Punto Dot &And Comma Punto &y coma Toward +∞ (&ceil) &Hacia +∞ (ceil) Toward −∞ (&floor) Hacia −∞ (&floor) &Binary &Binario &Engineering Ing&eniería &Hexadecimal &Hexadecimal &Octal &Octal &Scientific C&ientífico User &Manual Manual del &usuario Issues and &Feedback &Problemas y comentarios &Donate &Donar &About SpeedCrunch A&cerca de SpeedCrunch App Diag&nostics Diag&nóstico de la aplicación S&plit &Dividir Angle &Mode &Modo angular &Complex Form Forma &compleja New Tab Nueva pestaña Constants Constantes Functions Funciones History Historial User Functions Funciones del Usuario &Font... &Fuente... &Language... &Idioma... &Session &Sesión &Edit &Editar &View &Ver Se&ttings &Configuración &Decimal &Decimal &Keypad &Teclado Always on &Top Siempre &Encima Disabled Deshabilitado Small Space Espacio pequeño Medium Space Espacio medio Large Space Espacio grande &0 Digits &0 Dígitos &15 Digits &15 Dígitos &2 Digits &2 Dígitos &3 Digits &3 Dígitos &50 Digits &50 Dígitos &8 Digits &8 Dígitos &Sexagesimal &Sexagesimal Reset All Settings... Restablecer todos los ajustes... &System &Sistema SpeedCrunch &Theme &Tema de SpeedCrunch &Classic &Clásico &Modern &Moderno Context Help Ayuda contextual &Help A&yuda Error Error Can't read from file %1 No se puede leer el archivo %1 Import Session Importar sesión Close Session Cerrar sesión Angle Mode: Modo angular: Notation: Notación: Precision: Precisión: Turn Vuelta Revolution Revolución Fixed-point decimal Decimal de punto fijo Rational Racional Automatic decimal Decimal automático Automatic Automático User &Definitions... &Definiciones de usuario... New &Tab Nueva &pestaña New &Private Tab &Nueva pestaña privada Keep Conservar Make Private... Hacer privada... New &Window Nueva &ventana &Open... &Abrir... &Rename... Cambia&r nombre... Clo&ne... Cl&onar... &Close Tab Cerrar pes&taña Reopen Clo&sed Tab Rea&brir pestaña cerrada Open Sessions &Folder Abrir &carpeta de sesiones &Undo &Deshacer &Redo &Rehacer Cu&t Cor&tar Copy &Last Result Copiar e&l último resultado &Wrap in Parentheses &Encerrar entre paréntesis Full Scr&een Mode M&odo de pantalla completa &Basic &Básico &Scientific (wide) &Científico (ancho) Scientific (narrow) Científico (estrecho) &Custom... &Personalizado... Main &Menu &Menú principal User &Variables &Variables de usuario &Left &Izquierda &Right De&recha &Up &Arriba &Down A&bajo Close Pa&ne Cerrar pa&nel User &Units &Unidades de usuario &Turn &Vuelta If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Si una expresión nueva empieza por +, -, * o /, SpeedCrunch inserta primero "ans". &Accept with Enter &Aceptar con Intro Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Aceptar la sugerencia actual de autocompletado con Intro sin seleccionarla primero con las teclas de flecha. &Units &Unidades Show Live Result &Preview Mostrar &vista previa del resultado en vivo Save &Window Position on Exit Guardar la posición de la &ventana al salir Hover Highlighting Resaltado al pasar el cursor Group Integer Part Only Agrupar solo la parte entera Number Format... Formato numérico... Notation && Precision... Notación y precisión... After pressing Enter, keep the entered expression selected in the editor. Tras pulsar Intro, conservar seleccionada en el editor la expresión introducida. Never Nunca Always Siempre Only for Single-Line Expressions Solo para expresiones de una línea Simplify Displayed Expressions Simplificar expresiones mostradas History Size &Limit... &Límite de tamaño del historial... Remove Trailing &Zeroes &Eliminar ceros finales Nearest, Half &Away (round) Más cercano, mitad &alejada (round) Nearest, Half &Even (roundeven) Más cercano, mitad &par (roundeven) Toward &Zero (trunc) Hacia &cero (trunc) &Fixed-Point &Punto fijo &Rational &Racional &Exponential (m·s�¹) &Exponencial (m·s�¹) &Fractional (m/s) &Fraccionaria (m/s) &Rectangular (a + bi) &Rectangular (a + bi) Exponential (re�ᶿ) Exponencial (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonométrica (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasorial (r∠θ) &Theme... &Tema... Check for &Updates Buscar &actualizaciones Source Code Código fuente &Zoom &Zoom &Results &Resultados Unit Notation Notación de unidades Rounding Mode Modo de redondeo &Notation &Notación &Imaginary Unit Unidad &imaginaria &Window &Ventana &Editing &Edición A&utocomplete A&utocompletar Up/Down Arrow History Historial con flechas arriba/abajo &Appearance &Apariencia &Menus &Menús &Docks &Paneles acoplables &Input and Results E&ntrada y resultados &Disabled &Desactivado &Disable &Desactivar Close preview Cerrar vista previa Rename... Cambiar nombre... Clone... Clonar... Close Tab Cerrar pestaña New Private Tab Nueva pestaña privada Open... Abrir... Reopen Closed Tab Reabrir pestaña cerrada Split Dividir Left Izquierda Right Derecha Up Arriba Down Abajo Clear Vaciar Delete Eliminar %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sesión privada: su contenido se descarta al cerrarla. Elija Sesión > Conservar para convertirla en una sesión normal. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privada] Reset All Settings Restablecer todos los ajustes Reset all settings to their default values? ¿Restablecer todos los ajustes a sus valores predeterminados? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Esto incluye la apariencia, la edición, los formatos de resultados y las preferencias de las ventanas. Se conservarán los cálculos, las sesiones abiertas y las definiciones del usuario. The settings file could not be written. No se pudo escribir el archivo de ajustes. Clear this session's calculations, unfinished expression, variables, functions, and units? ¿Borrar los cálculos, la expresión sin terminar, las variables, las funciones y las unidades de esta sesión? Global user definitions are kept. Se conservan las definiciones globales del usuario. Make Session Private Hacer privada la sesión The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Se eliminará la sesión guardada %1. Su contenido permanecerá abierto en una sesión privada y se descartará al cerrar esa sesión o salir de SpeedCrunch. Make Private Hacer privada Could not delete the saved session %1. No se pudo eliminar la sesión guardada %1. Keep Session Conservar sesión Could not save the session. It remains private. No se pudo guardar la sesión. Sigue siendo privada. Clone Session Clonar sesión Could not save session file %1. No se pudo guardar el archivo de sesión %1. Could not delete session file %1. No se pudo eliminar el archivo de sesión %1. JSON file (*.json);;Any file (*.*) Archivo JSON (*.json);;Cualquier archivo (*.*) Export session as JSON Exportar sesión como JSON The selected file is not valid JSON: %1 El archivo seleccionado no es JSON válido: %1 The selected file is not a SpeedCrunch session JSON file. El archivo seleccionado no es un archivo JSON de sesión de SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Este archivo usa un formato de sesión de SpeedCrunch obsoleto y no se puede importar. The selected JSON file is missing the required $schema field. Al archivo JSON seleccionado le falta el campo obligatorio $schema. The selected JSON file uses an unsupported JSON schema: %1 El archivo JSON seleccionado usa un esquema JSON no compatible: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Al archivo JSON seleccionado le falta el identificador del esquema de sesión de SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 El archivo JSON seleccionado usa un formato de sesión de SpeedCrunch no compatible: %1 The selected JSON file is missing the required session name. Al archivo JSON seleccionado le falta el nombre de sesión obligatorio. The selected JSON file has an empty session name. El archivo JSON seleccionado tiene un nombre de sesión vacío. The selected JSON file has invalid or incomplete SpeedCrunch session data. El archivo JSON seleccionado tiene datos de sesión de SpeedCrunch no válidos o incompletos. Open Sessions Folder Abrir carpeta de sesiones Could not create the sessions folder: %1 No se pudo crear la carpeta de sesiones: %1 Could not open the sessions folder: %1 No se pudo abrir la carpeta de sesiones: %1 Editor and Results Font Fuente del editor y de los resultados Open Session Abrir sesión Community Comunidad Rename Session Renombrar sesión Clear Session Borrar sesión Delete Session Eliminar sesión Close Pane Cerrar panel User Variables Variables de usuario User Units Unidades de usuario Clear History Borrar historial Are you sure you want to clear the calculation history? ¿Seguro que quiere borrar el historial de cálculos? Session name: Nombre de sesión: A session named %1 already exists. Ya existe una sesión llamada %1. Could not create session file %1. No se pudo crear el archivo de sesión %1. Could not write session file %1. No se pudo escribir el archivo de sesión %1. Are you sure you want to delete this session? ¿Seguro que quiere eliminar esta sesión? Custom Precision Precisión personalizada Fractional digits: Dígitos fraccionarios: Theme Tema Light Themes Temas claros Dark Themes Temas oscuros Preview Vista previa Colors Colores Select color for %1 Seleccionar color para %1 Import... Importar... Export... Exportar... Import Theme Importar tema Theme file (*.json);;All files (*) Archivo de tema (*.json);;Todos los archivos (*) Invalid theme file. Archivo de tema no válido. Can't import theme "%1" because it conflicts with a built-in theme. No se puede importar el tema "%1" porque entra en conflicto con un tema integrado. Can't find a writable theme folder. No se puede encontrar una carpeta de temas con permisos de escritura. Overwrite Theme Sobrescribir tema A custom theme named "%1" already exists. Do you want to overwrite it? Ya existe un tema personalizado llamado "%1". ¿Quiere sobrescribirlo? Can't overwrite theme file %1 No se puede sobrescribir el archivo de tema %1 Can't copy theme file to %1 No se puede copiar el archivo de tema a %1 Export Theme Exportar tema Can't export theme as "%1" because it conflicts with a built-in theme. No se puede exportar el tema como "%1" porque entra en conflicto con un tema integrado. Can't write to file %1 No se puede escribir en el archivo %1 Global User Variable Variable global de usuario Global User Function Función global de usuario Global User Unit Unidad global de usuario User Definitions Definiciones de usuario These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Estas definiciones son globales y se cargan en cada sesión. No se pueden modificar desde las sesiones y tienen prioridad sobre las definiciones con el mismo nombre del editor de la sesión. Introduzca una definición por línea. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Ejemplos: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Aplicar Validate Validar Test Results Resultados de la prueba Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variables importadas: %1 Funciones importadas: %2 Unidades importadas: %3 Números de línea con errores: %4 none ninguno Apply Results Resultados de la aplicación User definitions saved. Se han guardado las definiciones de usuario. History Size Limit Límite de tamaño del historial Maximum number of history entries for this session (0 = unlimited): Número máximo de entradas del historial para esta sesión (0 = ilimitado): Text file (*.txt);;Any file (*.*) Archivo de texto (*.txt);;Todos los archivos (*.*) Could not recalculate from calculation %1: %2 No se pudo recalcular desde el cálculo %1: %2 History Size Limit Reached Se alcanzó el límite de tamaño del historial This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Este cálculo ocupa el último espacio disponible del historial. Los cálculos futuros eliminarán del historial el cálculo más antiguo. Puede aumentar el límite en Sesión > Límite de tamaño del historial. Editing calculation. Press Esc twice to cancel. Editando cálculo. Pulse Esc dos veces para cancelar. Calculation Settings Configuración del cálculo Invalid recalculation start index �ndice inicial de recálculo no válido System Default Predeterminado del sistema Language Idioma Select the language: Seleccione el idioma: Custom Personalizado Decimal places: Decimales: &Automatic &Automático &Precision &Precisión Plain &text &Texto sin formato Formula &Book Li&bro de Fórmulas &Export &Exportar Export session as HTML Exportar sesión como HTML HTML file (*.html) Documento HTML (*.html) Export session as plain text Exportar sesión como texto sin formato ManualWindow SpeedCrunch Manual Manual de SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual de SpeedCrunch NumberFormatDialog Number Format Formato numérico <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Seleccione el formato numérico para los resultados y la agrupación de dígitos de entrada.</b><br/><br/>Nota: los números introducidos se aceptan en formatos inequívocos aunque difieran del formato de visualización seleccionado.<br/> QObject Global User Variable Variable global de usuario Global User Function Función global de usuario Global User Unit Unidad global de usuario Backspace Retroceso Clear expression Borrar expresión Evaluate expression Evaluar expresión Insert text Insertar texto Automatic decimal Decimal automático Fixed-point decimal Decimal de punto fijo Engineering decimal Decimal de ingeniería Scientific decimal Decimal científico Rational Racional Binary Binario Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Update Available Actualización disponible A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Hay una versión más reciente (%1) disponible.<br/><a href="%2">Visite el sitio web para descargarla.</a> Check for Updates Buscar actualizaciones SpeedCrunch %1 is up to date. SpeedCrunch %1 está actualizado. No connectivity. Please check your internet connection and try again. Sin conectividad. Compruebe su conexión a Internet e inténtelo de nuevo. Could not verify the latest available version. No se pudo verificar la última versión disponible. ResultDisplay Scroll to bottom Desplazarse al final Edit Expression Editar expresión Change Settings Cambiar configuración New Tab Nueva pestaña &Import... &Importar... &Export &Exportar Plain &text &Texto sin formato Copy Copiar Selection Selección Select All Seleccionar todo Expression Expresión Result Resultado Calculation Cálculo Calculation as Single Line Cálculo en una sola línea Remove Eliminar This Calculation Este cálculo All Calculations Above Todos los cálculos anteriores All Calculations Below Todos los cálculos posteriores New Private Tab Nueva pestaña privada Session Sesión Open... Abrir... Clone... Clonar... Rename... Cambiar nombre... Keep Conservar Make Private... Hacer privada... Clear Vaciar Delete Eliminar Close Cerrar Split Dividir Left Izquierda Right Derecha Up Arriba Down Abajo Close Pane Cerrar panel Main Menu Menú principal Cancel editing Cancelar edición Copy result Copiar resultado Edit expression Editar expresión Change settings Cambiar configuración Remove calculation Eliminar cálculo ResultSlotsDialog Notation & Precision Notación y precisión Result Line Línea de resultado Enabled Activado Notation Notación Decimal Places Decimales Main Line Línea principal Extra Line #1 Línea adicional n.º 1 Extra Line #2 Línea adicional n.º 2 Extra Line #3 Línea adicional n.º 3 Extra Line #4 Línea adicional n.º 4 Auto Automático UserFunctionListWidget Name Nombre Value Valor Description Descripción Search Búsqueda No match found No se han encontrado coincidencias Insert Insertar Edit Editar Delete Eliminar Delete All Eliminar todo UserUnitListWidget Name Nombre Value Valor Description Descripción Search Buscar No match found No se encontraron coincidencias Insert Insertar Edit Editar Delete Eliminar Delete All Eliminar todo VariableListWidget Name Nombre Value Valor Description Descripción Search Búsqueda No match found No se han encontrado coincidencias Insert Insertar Edit Editar Delete Eliminar Delete All Eliminar todo heldercorreia-speedcrunch-e7ca37f/src/resources/locale/es_ES.ts000066400000000000000000010606061526573132500247540ustar00rootroot00000000000000 AboutBox About SpeedCrunch Acerca de SpeedCrunch Core developers Desarrolladores principales Original author Autor original Close Cerrar Math engine Motor de cálculo Main author | Logo | Maintainer Autor principal | Logotipo | Mantenedor Thanks Agradecimientos Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Los desarrolladores de SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este programa es software libre; puede redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General GNU, tal como la publica la Free Software Foundation, ya sea la versión 2 de la Licencia o, a su elección, cualquier versión posterior This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANT�A; ni siquiera la garantía implícita de COMERCIALIZACIÓN o IDONEIDAD PARA UN FIN DETERMINADO. Consulte la Licencia Pública General GNU para obtener más detalles. BitFieldWidget Reset bits to zero Restablecer bits a cero Invert bits Invertir bits Shift bits left Desplazar bits a la izquierda Shift bits right Desplazar bits a la derecha Book Index �ndice Algebra �lgebra Quadratic Equation Ecuación cuadrática Logarithmic Base Conversion Conversión de base logarítmica Geometry Geometría Circle Círculo Sector Sector circular Sphere Esfera Cube Cubo Cone Cono Cylinder Cilindro Electronics Electrónica Ohm's Law Ley de Ohm Power Potencia Reactance Reactancia Resonance Resonancia Radio Frequency Radiofrecuencia Antennas Antenas Characteristic Impedance (coax) Impedancia característica (coaxial) Velocity of Propagation (coax) Velocidad de propagación (coaxial) Standing Wave Ratio & Return Loss Relación de onda estacionaria y pérdida de retorno Free Space Wavelength Longitud de onda en el espacio libre resistance resistencia voltage tensión current corriente power potencia inductive reactance reactancia inductiva capacitive reactance reactancia capacitiva inductance inductancia capacitance capacitancia frequency frecuencia resonance frequency frecuencia de resonancia area área perimeter perímetro diameter diámetro radius radio volume volumen surface area área superficial height altura slant height altura inclinada face diagonal diagonal de la cara space diagonal diagonal espacial edge length longitud del lado arc length longitud del arco central angle (degrees) ángulo central (en grados) input power potencia de entrada reflected power potencia reflejada transmitted power potencia transmitida return loss pérdida de retorno dielectric constant constante dieléctrica outer conductor's inner diameter diámetro interno del conductor externo inner conductor's outer diameter diámetro externo del conductor interno speed of light velocidad de la luz reflection coefficient coeficiente de reflexión standing wave ratio razón de onda estacionaria normalized impedance impedancia normalizada frequency (Hz) frecuencia (en Hz) BookDock Formula Book Libro de fórmulas ConstantCompletion Search constants Buscar constantes No match found No se encontraron coincidencias Constants Mathematics Matemáticas Physics (CODATA 2022) Física (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Química (IUPAC - CIAAW 2021) Uncategorized Sin categoría Universal Universales Physicochemical Fisicoquímica Atomic & Nuclear — General Atómica y nuclear — general Atomic & Nuclear — Electroweak Atómica y nuclear — electrodébil Atomic & Nuclear — Electron Atómica y nuclear — electrón Atomic & Nuclear — Muon Atómica y nuclear — muón Atomic & Nuclear — Tau Atómica y nuclear — tau Atomic & Nuclear — Proton Atómica y nuclear — protón Atomic & Nuclear — Neutron Atómica y nuclear — neutrón Atomic & Nuclear — Deuteron Atómica y nuclear — deuterón Atomic & Nuclear — Triton Atómica y nuclear — tritón Atomic & Nuclear — Helion Atómica y nuclear — helión Atomic & Nuclear — Alpha particle Atómica y nuclear — partícula alfa Atomic & Nuclear — Atomic units Atómica y nuclear — unidades atómicas Atomic & Nuclear — Energy conversion relationships Atómica y nuclear — relaciones de conversión de energía Atomic & Nuclear — X-ray units Atómica y nuclear — unidades de rayos X Atomic & Nuclear — Magnetic shielding corrections Atómica y nuclear — correcciones de apantallamiento magnético Masses Masas Lifetimes Tiempos de vida Molar Masses Masas molares Electronegativity Electronegatividad Ionization Energy Energía de ionización Nominal Constants (IAU 2015) Constantes nominales (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Mejores estimaciones actuales (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) impedancia característica del vacío (Z₀) reduced Planck constant (�) constante de Planck reducida (�) vacuum electric permittivity (ϵ₀) permitividad eléctrica del vacío (ϵ₀) Newtonian constant of gravitation (G) constante newtoniana de gravitación (G) vacuum magnetic permeability (μ₀) permeabilidad magnética del vacío (μ₀) Planck constant (h) constante de Planck (h) speed of light in vacuum (c) velocidad de la luz en el vacío (c) standard acceleration of gravity (gₙ) aceleración estándar de la gravedad (gₙ) Newtonian constant of gravitation over h-bar c constante newtoniana de gravitación sobre h barra c Planck length longitud de Planck Planck constant in eV/Hz (h) constante de Planck en eV/Hz (h) Planck mass masa de Planck Planck mass energy equivalent in GeV equivalente energético de la masa de Planck en GeV Planck temperature temperatura de Planck Planck time tiempo de Planck reduced Planck constant in eV·s (�) constante de Planck reducida en eV·s (�) reduced Planck constant times c in MeV·fm constante de Planck reducida por c en MeV·fm Bohr magneton magnetón de Bohr conductance quantum (G₀) cuanto de conductancia (G₀) Coulomb constant (kₑ) constante de Coulomb (kₑ) elementary charge (e) carga elemental (e) elementary charge over h-bar carga elemental sobre h barra conventional value of Josephson constant valor convencional de la constante de Josephson Josephson constant constante de Josephson conventional value of ampere-90 valor convencional del amperio-90 conventional value of coulomb-90 valor convencional del culombio-90 conventional value of farad-90 valor convencional del faradio-90 conventional value of henry-90 valor convencional del henrio-90 conventional value of ohm-90 valor convencional del ohmio-90 conventional value of volt-90 valor convencional del voltio-90 conventional value of watt-90 valor convencional del vatio-90 magnetic flux quantum (Φ₀) cuanto de flujo magnético (Φ₀) nuclear magneton magnetón nuclear inverse of conductance quantum inverso del cuanto de conductancia conventional value of von Klitzing constant valor convencional de la constante de von Klitzing von Klitzing constant constante de von Klitzing atomic unit of magnetic dipole moment unidad atómica de momento dipolar magnético atomic unit of magnetic flux density unidad atómica de densidad de flujo magnético Bohr magneton in eV/T Magnetón de Bohr en eV/T Bohr magneton in Hz/T Magnetón de Bohr en Hz/T Bohr magneton in inverse meter per tesla magnetón de Bohr en metro inverso por tesla Bohr magneton in K/T Magnetón de Bohr en K/T nuclear magneton in eV/T magnetón nuclear en eV/T nuclear magneton in inverse meter per tesla magnetón nuclear en metro inverso por tesla nuclear magneton in K/T magnetón nuclear en K/T nuclear magneton in MHz/T magnetón nuclear en MHz/T Bohr radius (a₀) radio de Bohr (a₀) fine-structure constant (α) constante de estructura fina (α) Hartree energy (Eₕ) energía de Hartree (Eₕ) Hartree energy in eV energía de Hartree en eV quantum of circulation cuanto de circulación quantum of circulation times 2 cuanto de circulación multiplicado por 2 Rydberg constant (R∞) constante de Rydberg (R∞) atomic mass unit-hartree relationship relación entre la unidad de masa atómica y el hartree atomic mass unit-hertz relationship relación entre la unidad de masa atómica y el hercio atomic mass unit-inverse meter relationship relación entre la unidad de masa atómica y el metro inverso atomic mass unit-joule relationship relación entre la unidad de masa atómica y el julio atomic mass unit-kelvin relationship relación entre la unidad de masa atómica y el kelvin atomic mass unit-kilogram relationship relación entre la unidad de masa atómica y el kilogramo atomic unit of 1st hyperpolarizability unidad atómica de primera hiperpolarizabilidad atomic unit of 2nd hyperpolarizability unidad atómica de segunda hiperpolarizabilidad atomic unit of charge (e) unidad atómica de carga (e) atomic unit of charge density unidad atómica de densidad de carga atomic unit of current unidad atómica de corriente atomic unit of electric dipole moment unidad atómica de momento dipolar eléctrico atomic unit of electric field unidad atómica de campo eléctrico atomic unit of electric field gradient unidad atómica de gradiente de campo eléctrico atomic unit of electric polarizability unidad atómica de polarizabilidad eléctrica atomic unit of electric potential unidad atómica de potencial eléctrico atomic unit of electric quadrupole moment unidad atómica de momento cuadrupolar eléctrico atomic unit of action unidad atómica de acción atomic unit of energy unidad atómica de energía atomic unit of force unidad atómica de fuerza atomic unit of length unidad atómica de longitud hertz-atomic mass unit relationship relación entre el hercio y la unidad de masa atómica hertz-electron volt relationship relación entre el hercio y el electronvoltio hertz-hartree relationship relación entre el hercio y el hartree hertz-inverse meter relationship relación entre el hercio y el metro inverso hertz-joule relationship relación entre el hercio y el julio hertz-kelvin relationship relación entre el hercio y el kelvin hertz-kilogram relationship relación entre el hercio y el kilogramo hyperfine transition frequency of Cs-133 frecuencia de transición hiperfina del Cs-133 inverse fine-structure constant (α�¹) inversa de la constante de estructura fina (α�¹) inverse meter-atomic mass unit relationship relación entre el metro inverso y la unidad de masa atómica inverse meter-electron volt relationship relación entre el metro inverso y el electronvoltio inverse meter-hartree relationship relación entre el metro inverso y el hartree inverse meter-hertz relationship relación entre el metro inverso y el hercio inverse meter-joule relationship relación entre el metro inverso y el julio inverse meter-kelvin relationship relación entre el metro inverso y el kelvin inverse meter-kilogram relationship relación entre el metro inverso y el kilogramo joule-atomic mass unit relationship relación entre el julio y la unidad de masa atómica joule-electron volt relationship relación entre el julio y el electronvoltio joule-hertz relationship relación entre el julio y el hercio joule-hartree relationship relación entre el julio y el hartree joule-inverse meter relationship relación entre el julio y el metro inverso joule-kelvin relationship relación entre el julio y el kelvin joule-kilogram relationship relación entre el julio y el kilogramo kelvin-atomic mass unit relationship relación entre el kelvin y la unidad de masa atómica kelvin-electron volt relationship relación entre el kelvin y el electronvoltio kelvin-hertz relationship relación entre el kelvin y el hercio kelvin-hartree relationship relación entre el kelvin y el hartree kelvin-inverse meter relationship relación entre el kelvin y el metro inverso kelvin-joule relationship relación entre el kelvin y el julio kelvin-kilogram relationship relación entre el kelvin y el kilogramo kilogram-atomic mass unit relationship relación entre el kilogramo y la unidad de masa atómica kilogram-electron volt relationship relación entre el kilogramo y el electronvoltio kilogram-hertz relationship relación entre el kilogramo y el hercio kilogram-hartree relationship relación entre el kilogramo y el hartree kilogram-inverse meter relationship relación entre el kilogramo y el metro inverso kilogram-joule relationship relación entre el kilogramo y el julio kilogram-kelvin relationship relación entre el kilogramo y el kelvin lattice parameter of silicon (a) parámetro reticular del silicio (a) luminous efficacy eficacia luminosa natural unit of energy unidad natural de energía natural unit of energy in MeV unidad natural de energía en MeV natural unit of action (�) unidad natural de acción (�) natural unit of action in eV·s unidad natural de acción en eV·s natural unit of length unidad natural de longitud natural unit of mass unidad natural de masa natural unit of momentum unidad natural de momento natural unit of momentum in MeV/c unidad natural de momento en MeV/c natural unit of time unidad natural de tiempo natural unit of velocity unidad natural de velocidad Rydberg constant times c in Hz constante de Rydberg por c en Hz Rydberg constant times hc in eV constante de Rydberg por hc en eV Rydberg constant times hc in J constante de Rydberg por hc en J Fermi coupling constant constante de acoplamiento de Fermi weak mixing angle ángulo de mezcla débil W to Z mass ratio relación de masas W/Z Thomson cross section (σₑ) sección eficaz de Thomson (σₑ) electron mass (mₑ) masa del electrón (mₑ) electron mass in u masa del electrón en u electron mass energy equivalent (mₑ·c²) equivalente energético de la masa del electrón (mₑ·c²) electron mass energy equivalent in MeV equivalente energético de la masa del electrón en MeV reduced Compton wavelength longitud de onda de Compton reducida classical electron radius (rₑ) radio clásico del electrón (rₑ) electron charge to mass quotient cociente carga-masa del electrón electron-deuteron magnetic moment ratio relación de momentos magnéticos electrón-deuterón electron-deuteron mass ratio relación de masas electrón-deuterón electron g factor (gₑ) factor g del electrón (gₑ) electron gyromagnetic ratio (γₑ) relación giromagnética del electrón (γₑ) electron gyromagnetic ratio in MHz/T relación giromagnética del electrón en MHz/T electron-helion mass ratio relación de masas electrón-helión electron magnetic moment (μₑ) momento magnético del electrón (μₑ) electron magnetic moment anomaly (aₑ) anomalía del momento magnético del electrón (aₑ) electron magnetic moment to Bohr magneton ratio relación entre el momento magnético del electrón y el magnetón de Bohr electron magnetic moment to nuclear magneton ratio relación entre el momento magnético del electrón y el magnetón nuclear electron molar mass (Mₑ) masa molar del electrón (Mₑ) electron-muon magnetic moment ratio relación de momentos magnéticos electrón-muón electron-muon mass ratio relación de masas electrón-muón electron-neutron magnetic moment ratio relación de momentos magnéticos electrón-neutrón electron-neutron mass ratio relación de masas electrón-neutrón electron-proton magnetic moment ratio relación de momentos magnéticos electrón-protón electron-proton mass ratio relación de masas electrón-protón electron relative atomic mass (Ar(e)) masa atómica relativa del electrón (Ar(e)) electron-tau mass ratio relación de masas electrón-tau electron to alpha particle mass ratio relación de masas electrón-partícula alfa electron to shielded helion magnetic moment ratio relación entre el momento magnético del electrón y el del helión apantallado electron to shielded proton magnetic moment ratio relación entre el momento magnético del electrón y el del protón apantallado electron-triton mass ratio relación de masas electrón-tritón electron volt-atomic mass unit relationship relación entre el electronvoltio y la unidad de masa atómica electron volt-hartree relationship relación entre el electronvoltio y el hartree electron volt-hertz relationship relación entre el electronvoltio y el hercio electron volt-inverse meter relationship relación entre el electronvoltio y el metro inverso electron volt-joule relationship relación entre el electronvoltio y el julio electron volt-kelvin relationship relación entre el electronvoltio y el kelvin electron volt-kilogram relationship relación entre el electronvoltio y el kilogramo hartree-atomic mass unit relationship relación entre el hartree y la unidad de masa atómica hartree-electron volt relationship relación entre el hartree y el electronvoltio muon Compton wavelength longitud de onda de Compton del muón muon-electron mass ratio relación de masas muón-electrón muon g factor factor g del muón muon magnetic moment momento magnético del muón muon magnetic moment anomaly anomalía del momento magnético del muón muon magnetic moment to Bohr magneton ratio relación entre el momento magnético del muón y el magnetón de Bohr muon magnetic moment to nuclear magneton ratio relación entre el momento magnético del muón y el magnetón nuclear muon mass masa del muón muon mass energy equivalent equivalente energético de la masa del muón muon mass energy equivalent in MeV equivalente energético de la masa del muón en MeV muon mass in u masa del muón en u muon molar mass masa molar del muón muon-neutron mass ratio relación de masas muón-neutrón muon-proton magnetic moment ratio relación de momentos magnéticos muón-protón muon-proton mass ratio relación de masas muón-protón muon-tau mass ratio relación de masas muón-tau reduced muon Compton wavelength longitud de onda de Compton reducida del muón reduced tau Compton wavelength longitud de onda de Compton reducida del tau tau Compton wavelength longitud de onda de Compton del tau tau-electron mass ratio relación de masas tau-electrón tau mass masa del tau tau mass energy equivalent equivalente energético de la masa del tau tau mass in u masa del tau en u tau molar mass masa molar del tau tau-muon mass ratio relación de masas tau-muón tau-neutron mass ratio relación de masas tau-neutrón tau-proton mass ratio relación de masas tau-protón proton charge to mass quotient cociente carga-masa del protón proton Compton wavelength longitud de onda de Compton del protón proton-electron mass ratio relación de masas protón-electrón proton g factor (gₚ) factor g del protón (gₚ) proton gyromagnetic ratio (γₚ) relación giromagnética del protón (γₚ) proton gyromagnetic ratio in MHz/T relación giromagnética del protón en MHz/T proton magnetic moment (μₚ) momento magnético del protón (μₚ) proton magnetic moment to Bohr magneton ratio relación entre el momento magnético del protón y el magnetón de Bohr proton magnetic moment to nuclear magneton ratio relación entre el momento magnético del protón y el magnetón nuclear proton magnetic shielding correction corrección de apantallamiento magnético del protón proton mass (mₚ) masa del protón (mₚ) proton mass energy equivalent equivalente energético de la masa del protón proton mass energy equivalent in MeV equivalente energético de la masa del protón en MeV proton mass in u masa del protón en u proton molar mass (Mₚ) masa molar del protón (Mₚ) proton-muon mass ratio relación de masas protón-muón proton-neutron magnetic moment ratio relación de momentos magnéticos protón-neutrón proton-neutron mass ratio relación de masas protón-neutrón proton relative atomic mass (Ar(p)) masa atómica relativa del protón (Ar(p)) proton rms charge radius radio de carga rms del protón proton-tau mass ratio relación de masas protón-tau reduced proton Compton wavelength longitud de onda de Compton reducida del protón shielded proton gyromagnetic ratio relación giromagnética del protón apantallado shielded proton gyromagnetic ratio in MHz/T relación giromagnética del protón apantallado en MHz/T shielded proton magnetic moment momento magnético del protón apantallado shielded proton magnetic moment to Bohr magneton ratio relación entre el momento magnético del protón apantallado y el magnetón de Bohr shielded proton magnetic moment to nuclear magneton ratio relación entre el momento magnético del protón apantallado y el magnetón nuclear neutron Compton wavelength longitud de onda de Compton del neutrón neutron-electron magnetic moment ratio relación de momentos magnéticos neutrón-electrón neutron-electron mass ratio relación de masas neutrón-electrón neutron g factor (gₙ) factor g del neutrón (gₙ) neutron gyromagnetic ratio (γₙ) relación giromagnética del neutrón (γₙ) neutron gyromagnetic ratio in MHz/T relación giromagnética del neutrón en MHz/T neutron magnetic moment (μₙ) momento magnético del neutrón (μₙ) neutron magnetic moment to Bohr magneton ratio relación entre el momento magnético del neutrón y el magnetón de Bohr neutron magnetic moment to nuclear magneton ratio relación entre el momento magnético del neutrón y el magnetón nuclear neutron mass (mₙ) masa del neutrón (mₙ) neutron mass energy equivalent equivalente energético de la masa del neutrón neutron mass energy equivalent in MeV equivalente energético de la masa del neutrón en MeV neutron mass in u masa del neutrón en u neutron molar mass (Mₙ) masa molar del neutrón (Mₙ) neutron-muon mass ratio relación de masas neutrón-muón neutron-proton magnetic moment ratio relación de momentos magnéticos neutrón-protón neutron-proton mass difference diferencia de masa neutrón-protón neutron-proton mass difference energy equivalent equivalente energético de la diferencia de masa neutrón-protón neutron-proton mass difference energy equivalent in MeV equivalente energético de la diferencia de masa neutrón-protón en MeV neutron-proton mass difference in u diferencia de masa neutrón-protón en u neutron-proton mass ratio relación de masas neutrón-protón neutron relative atomic mass (Ar(n)) masa atómica relativa del neutrón (Ar(n)) neutron-tau mass ratio relación de masas neutrón-tau neutron to shielded proton magnetic moment ratio relación entre el momento magnético del neutrón y el del protón apantallado reduced neutron Compton wavelength longitud de onda de Compton reducida del neutrón deuteron-electron magnetic moment ratio relación de momentos magnéticos deuterón-electrón deuteron-electron mass ratio relación de masas deuterón-electrón deuteron g factor factor g del deuterón deuteron magnetic moment momento magnético del deuterón deuteron magnetic moment to Bohr magneton ratio relación entre el momento magnético del deuterón y el magnetón de Bohr deuteron magnetic moment to nuclear magneton ratio relación entre el momento magnético del deuterón y el magnetón nuclear deuteron mass masa del deuterón deuteron mass energy equivalent equivalente energético de la masa del deuterón deuteron mass energy equivalent in MeV equivalente energético de la masa del deuterón en MeV deuteron mass in u masa del deuterón en u deuteron molar mass masa molar del deuterón deuteron-neutron magnetic moment ratio relación de momentos magnéticos deuterón-neutrón deuteron-proton magnetic moment ratio relación de momentos magnéticos deuterón-protón deuteron-proton mass ratio relación de masas deuterón-protón deuteron relative atomic mass (Ar(d)) masa atómica relativa del deuterón (Ar(d)) deuteron rms charge radius radio de carga rms del deuterón triton-electron mass ratio relación de masas tritón-electrón triton g factor (gₜ) factor g del tritón (gₜ) triton magnetic moment (μₜ) momento magnético del tritón (μₜ) triton magnetic moment to Bohr magneton ratio relación entre el momento magnético del tritón y el magnetón de Bohr triton magnetic moment to nuclear magneton ratio relación entre el momento magnético del tritón y el magnetón nuclear triton mass (mₜ) masa del tritón (mₜ) triton mass energy equivalent equivalente energético de la masa del tritón triton mass energy equivalent in MeV equivalente energético de la masa del tritón en MeV triton mass in u masa del tritón en u triton molar mass (Mₜ) masa molar del tritón (Mₜ) triton-proton mass ratio relación de masas tritón-protón triton relative atomic mass (Ar(t)) masa atómica relativa del tritón (Ar(t)) triton to proton magnetic moment ratio relación de momentos magnéticos tritón-protón helion-electron mass ratio relación de masas helión-electrón helion g factor (gₕ) factor g del helión (gₕ) helion magnetic moment (μₕ) momento magnético del helión (μₕ) helion magnetic moment to Bohr magneton ratio relación entre el momento magnético del helión y el magnetón de Bohr helion magnetic moment to nuclear magneton ratio relación entre el momento magnético del helión y el magnetón nuclear helion mass (mₕ) masa del helión (mₕ) helion mass energy equivalent equivalente energético de la masa del helión helion mass energy equivalent in MeV equivalente energético de la masa del helión en MeV helion mass in u masa del helión en u helion molar mass (Mₕ) masa molar del helión (Mₕ) helion-proton mass ratio relación de masas helión-protón helion relative atomic mass (Ar(h)) masa atómica relativa del helión (Ar(h)) helion shielding shift desplazamiento de apantallamiento del helión shielded helion gyromagnetic ratio relación giromagnética del helión apantallado shielded helion gyromagnetic ratio in MHz/T relación giromagnética del helión apantallado en MHz/T shielded helion magnetic moment momento magnético del helión apantallado shielded helion magnetic moment to Bohr magneton ratio relación entre el momento magnético del helión apantallado y el magnetón de Bohr shielded helion magnetic moment to nuclear magneton ratio relación entre el momento magnético del helión apantallado y el magnetón nuclear shielded helion to proton magnetic moment ratio relación entre el momento magnético del helión apantallado y el del protón shielded helion to shielded proton magnetic moment ratio relación entre el momento magnético del helión apantallado y el del protón apantallado alpha particle mass masa de la partícula alfa alpha particle mass in u masa de la partícula alfa en u alpha particle mass energy equivalent equivalente energético de la masa de la partícula alfa alpha particle mass energy equivalent in MeV equivalente energético de la masa de la partícula alfa en MeV alpha particle-electron mass ratio relación de masas partícula alfa-electrón alpha particle-proton mass ratio relación de masas partícula alfa-protón alpha particle rms charge radius radio de carga rms de la partícula alfa alpha particle molar mass masa molar de la partícula alfa alpha particle relative atomic mass (Ar(α)) masa atómica relativa de la partícula alfa (Ar(α)) atomic mass constant (mᵤ) constante de masa atómica (mᵤ) Avogadro constant constante de Avogadro Boltzmann constant (k) constante de Boltzmann (k) Boltzmann constant in eV/K constante de Boltzmann en eV/K Boltzmann constant in Hz/K constante de Boltzmann en Hz/K Boltzmann constant in inverse meter per kelvin constante de Boltzmann en metro inverso por kelvin electron volt (eV) electronvoltio (eV) Faraday constant (F) constante de Faraday (F) first radiation constant (c�) primera constante de radiación (c�) first radiation constant for spectral radiance primera constante de radiación para radiancia espectral molar gas constant (R) constante molar de los gases (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Constante de Loschmidt (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Constante de Loschmidt (n₀, 273.15 K, 101.325 kPa) molar Planck constant constante molar de Planck second radiation constant (c₂) segunda constante de radiación (c₂) Stefan-Boltzmann constant (σ) constante de Stefan-Boltzmann (σ) lattice spacing of ideal Si (d₂₂₀) espaciado reticular del Si ideal (d₂₂₀) atomic mass constant energy equivalent equivalente energético de la constante de masa atómica atomic mass constant energy equivalent in MeV equivalente energético de la constante de masa atómica en MeV atomic mass unit-electron volt relationship relación entre la unidad de masa atómica y el electronvoltio molar mass constant (Mᵤ) constante de masa molar (Mᵤ) molar mass of carbon-12 masa molar del carbono-12 molar volume of ideal gas (273.15 K, 100 kPa) volumen molar del gas ideal (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volumen molar del gas ideal (273.15 K, 101.325 kPa) molar volume of silicon volumen molar del silicio Sackur-Tetrode constant (1 K, 100 kPa) constante de Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) constante de Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant constante de la ley de desplazamiento en frecuencia de Wien Wien wavelength displacement law constant constante de la ley de desplazamiento en longitud de onda de Wien standard atmosphere (atm) atmósfera estándar (atm) standard-state pressure (p°) presión de estado estándar (p°) Angstrom star (Å*) angstrom estrella (Å*) Copper x unit Unidad x de cobre Molybdenum x unit Unidad x de molibdeno atomic unit of magnetizability unidad atómica de magnetizabilidad atomic unit of mass (mₑ) unidad atómica de masa (mₑ) atomic unit of momentum unidad atómica de momento atomic unit of permittivity unidad atómica de permitividad atomic unit of time unidad atómica de tiempo atomic unit of velocity unidad atómica de velocidad hartree-hertz relationship relación entre el hartree y el hercio hartree-inverse meter relationship relación entre el hartree y el metro inverso hartree-joule relationship relación entre el hartree y el julio hartree-kelvin relationship relación entre el hartree y el kelvin hartree-kilogram relationship relación entre el hartree y el kilogramo shielding difference of d and p in HD diferencia de apantallamiento entre d y p en HD shielding difference of t and p in HT diferencia de apantallamiento entre t y p en HT pi (π) pi (π) Euler's number (e) Número de Euler (e) golden ratio (φ) razón áurea (φ) Euler-Mascheroni constant (γ) constante de Euler-Mascheroni (γ) nominal solar radius radio solar nominal nominal solar total irradiance irradiancia solar total nominal nominal solar luminosity luminosidad solar nominal nominal solar effective temperature temperatura efectiva solar nominal nominal solar mass parameter parámetro de masa solar nominal nominal terrestrial equatorial radius radio ecuatorial terrestre nominal nominal terrestrial polar radius radio polar terrestre nominal nominal terrestrial mass parameter parámetro de masa terrestre nominal nominal jovian equatorial radius radio ecuatorial joviano nominal nominal jovian polar radius radio polar joviano nominal nominal jovian mass parameter parámetro de masa joviano nominal average value of one minus the rate of TCG relative to TCB valor medio de uno menos la tasa de TCG relativa a TCB solar mass parameter (TCB-compatible) parámetro de masa solar (compatible con TCB) solar mass parameter (TDB-compatible) parámetro de masa solar (compatible con TDB) equatorial radius of the Earth (TT-compatible) radio ecuatorial de la Tierra (compatible con TT) dynamical form factor of the Earth factor de forma dinámico de la Tierra time rate of change in the dynamical form factor of the Earth tasa temporal de cambio del factor de forma dinámico de la Tierra geocentric gravitational constant (TCB-compatible) constante gravitacional geocéntrica (compatible con TCB) geocentric gravitational constant (TT-compatible) constante gravitacional geocéntrica (compatible con TT) geocentric gravitational constant (TDB-compatible) constante gravitacional geocéntrica (compatible con TDB) potential of the geoid potencial del geoide nominal mean angular velocity of the Earth (TT-compatible) velocidad angular media nominal de la Tierra (compatible con TT) ratio mass of the Moon to the Earth relación de masa de la Luna respecto a la Tierra ratio of the mass of the Sun to Mercury relación de la masa del Sol respecto a Mercurio ratio of the mass of the Sun to Venus relación de la masa del Sol respecto a Venus ratio of the mass of the Sun to Mars relación de la masa del Sol respecto a Marte ratio of the mass of the Sun to Jupiter relación de la masa del Sol respecto a Júpiter ratio of the mass of the Sun to Saturn relación de la masa del Sol respecto a Saturno ratio of the mass of the Sun to Uranus relación de la masa del Sol respecto a Urano ratio of the mass of the Sun to Neptune relación de la masa del Sol respecto a Neptuno ratio of the mass of the Sun to (134340) Pluto relación de la masa del Sol respecto a (134340) Plutón ratio of the mass of the Sun to (136199) Eris relación de la masa del Sol respecto a (136199) Eris ratio of the mass of (1) Ceres to the Sun relación de la masa de (1) Ceres respecto al Sol ratio of the mass of (2) Pallas to the Sun relación de la masa de (2) Palas respecto al Sol ratio of the mass of (4) Vesta to the Sun relación de la masa de (4) Vesta respecto al Sol mean obliquity of the ecliptic at J2000.0 oblicuidad media de la eclíptica en J2000.0 Electromagnetic Electromagnetismo Compton wavelength longitud de onda de Compton Astronomy Astronomía ConstantsWidget Domain Dominio Subdomain Subdominio No match found No se encontraron coincidencias Name Nombre Value Valor Unit Unidad Search Búsqueda All Todas CustomKeypadDialog Custom Keypad Teclado personalizado Rows: Filas: Columns: Columnas: Copy preset: Copiar preajuste: Basic Básico Scientific (wide) Científico (ancho) Scientific (narrow) Científico (estrecho) Apply Aplicar Row Fila Column Columna Label Etiqueta Behavior Comportamiento Text Texto DiagnosticsDialog App Diagnostics Diagnóstico de la aplicación Copy to Clipboard Copiar al portapapeles Editor Unit Unidad User unit Unidad de usuario User function Función de usuario Argument Argumento Current result:<br/>%1 Resultado actual:<br/>%1 Selection result:<br/>%1 Resultado de la selección:<br/>%1 Selection result: n/a Resultado de la selección: vacío Selection result: %1 Resultado de la selección: %1 second segundo metre metro kilogram kilogramo mole mol radian radián steradian estereorradián degree Celsius grado Celsius cubic metre metro cúbico cubic millimetre milímetro cúbico cubic centimetre centímetro cúbico cubic decimetre decímetro cúbico cubic kilometre kilómetro cúbico square millimetre milímetro cuadrado square kilometre kilómetro cuadrado square metre metro cuadrado minute minuto hour hora day día astronomical unit unidad astronómica degree grado arcminute minuto de arco arcsecond segundo de arco milliarcsecond milisegundo de arco microarcsecond microsegundo de arco hectare hectárea litre litro tonne tonelada Dalton dalton electronvolt electronvoltio Angstrom angstrom atmosphere atmósfera atomic mass unit unidad de masa atómica British thermal unit unidad térmica británica calorie caloría carat quilate cup taza cup (Imperial) taza (imperial) cup (Japanese) taza (japonesa) cup (US) taza (EE. UU.) degree Fahrenheit grado Fahrenheit fathom braza fluid ounce (Imperial) onza líquida (imperial) fluid ounce (US) onza líquida (EE. UU.) fluid dram (Imperial) dracma líquido (imperial) fluid dram (US) dracma líquido (EE. UU.) foot pie square foot pie cuadrado cubic foot pie cúbico gallon (Imperial) galón (imperial) gallon (US) galón (EE. UU.) gill (Imperial) gill (imperial) gill (US) gill (EE. UU.) gradian gradián grain grano gram gramo Hartley hartley Hartree energy unit unidad de energía Hartree horsepower caballo de fuerza inch pulgada square inch pulgada cuadrada cubic inch pulgada cúbica karat quilate knot nudo lightminute minuto luz lightsecond segundo luz lightyear año luz long ton tonelada larga mile milla square mile milla cuadrada cubic mile milla cúbica mile per hour milla por hora kilometre per hour kilómetro por hora nautical mile milla náutica ounce onza parsec pársec pint (Imperial) pinta (imperial) pint (US) pinta (EE. UU.) pound libra pounds per square inch libras por pulgada cuadrada quart (Imperial) cuarto (imperial) quart (US) cuarto (EE. UU.) oil barrel barril de petróleo beer barrel (US) barril de cerveza (EE. UU.) square yard yarda cuadrada cubic yard yarda cúbica short ton tonelada corta tablespoon cucharada tablespoon (Australian) cucharada (australiana) tablespoon (Imperial) cucharada (imperial) tablespoon (US) cucharada (EE. UU.) dessert spoon cuchara de postre teaspoon cucharadita teaspoon (Imperial) cucharadita (imperial) teaspoon (US) cucharadita (EE. UU.) turn vuelta revolution revolución revolution per minute revolución por minuto week semana kilowatt hour kilovatio hora millimetre of mercury milímetro de mercurio yard yarda Julian century siglo juliano Julian year año juliano sidereal year año sidéreo tropical year año tropical Evaluator invalid expression expresión inválida division by zero división por cero too time consuming - computation was rejected demasiado tiempo de cálculo - operación denegada dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensión incompatible - no se pueden comparar, sumar, etc. cantidades con distintas dimensiones invalid dimension - operation might require dimensionless arguments dimensión incorrecta - puede que la operación necesite argumentos adimensionales Computation aborted - encountered numerical instability Cálculo detenido - se ha encontrado una inestabilidad numérica invalid dimension - function might require dimensionless arguments dimensión incorrecta - puede que la función necesite argumentos adimensionales error error unit must not be zero la unidad no puede ser cero Conversion failed - dimension mismatch Fallo de conversión - las dimensiones no concuerdan unknown function or variable función o variable desconocida recursion not supported no se permite la recursividad cannot operate on a NaN No se puede operar con un NaN underflow - tiny result is out of SpeedCrunch's number range subdesbordamiento: el resultado es demasiado pequeño para representarse dentro del rango numérico de SpeedCrunch overflow - huge result is out of SpeedCrunch's number range desbordamiento: el resultado es demasiado grande para representarse dentro del rango numérico de SpeedCrunch overflow - logic result exceeds maximum of 256 bits El resultado lógico excede los 256 bits permitidos overflow - integer result exceeds maximum limit for integers El resultado excede el límite máximo para enteros operation is not defined for these arguments la operación no está definida para estos argumentos wrong number of arguments número de argumentos incorrecto does not take NaN as an argument no admite NaN como argumento result out of range resultado fuera de rango undefined for argument domain indefinido para el dominio del argumento computation too expensive operación demasiado costosa internal error, please report a bug error interno; informe de este fallo syntax error error de sintaxis conversion target must be a unit el destino de conversión debe ser una unidad unknown unit unidad desconocida %1 is a reserved name, please choose another %1 es un nombre reservado; elija otro %1 is a global user definition and cannot be overridden in this session. %1 es una definición global de usuario y no puede sobrescribirse en esta sesión. %1 is a variable name, please choose another or delete the variable %1 es el nombre de una variable; elija otro o elimine la variable argument %1 is used more than once el argumento %1 se usa más de una vez %1 is a built-in unit name, please choose another %1 es un nombre de unidad integrado; elija otro %1 is a user function name, please choose another or delete the function %1 es el nombre de una función definida por el usuario; elija otro o elimine la función FunctionRepo max; trials; probability máximo; intentos; probabilidad trials; probability intentos; probabilidad hits; trials; probability aciertos; intentos; probabilidad max; total; hits; trials máximo; total; aciertos; intentos total; hits; trials total; aciertos; intentos count; total; hits; trials cuenta; total; aciertos; intentos dividend; divisor dividendo; divisor x; exponent_bits; significand_bits [; exponent_bias] x; bits_exponente; bits_significativos [; sesgo_exponente] base; x base; x value; modulo valor; módulo base; exponent; modulo base; exponente; módulo events; average_events sucesos; sucesos_promedio average_events sucesos_promedio x [; precision] x [; precisión] Absolute Value Valor absoluto Absolute Deviation Desviación absoluta Arc Cosine Arcocoseno Logical AND Conjunción Lógica Area Hyperbolic Cosine Arcocoseno Hiperbólico Area Hyperbolic Sine Arcoseno Hiperbólico Area Hyperbolic Tangent Arcotangente hiperbólica Arc Sine Arcoseno Arc Tangent Arcotangente Arc Tangent with two Arguments Arcotangente con dos argumentos Average (Arithmetic Mean) Promedio (media aritmética) Binomial Cumulative Distribution Function Función de Distribución Binomial Binomial Distribution Mean Media de Distribución Binomial Binomial Probability Mass Function Función de Probabilidad Binomial Binomial Distribution Variance Varianza de Distribución Binomial Cube Root Raíz Cúbica Complex Conjugate Conjugado complejo Cosine Coseno Hyperbolic Cosine Coseno Hiperbólico Cotangent Cotangente Cosecant Cosecante Convert Unix timestamp to Date Convertir marca de tiempo Unix a fecha Degrees of Arc Grados de arco Error Function Función error Complementary Error Function Función error complementaria Exponential Exponencial Fractional Part Parte fraccionaria Extension of Factorials [= (x-1)!] Extensión de factoriales [= (x-1)!] Greatest Common Divisor Máximo común divisor Geometric Mean Media geométrica Gradians of arc Gradianes de arco Hypergeometric Cumulative Distribution Function Función de Distribución Hipergeométrica Hypergeometric Distribution Mean Media de Distribución Hipergeométrica Hypergeometric Probability Mass Function Función de Probabilidad Hipergeométrica Hypergeometric Distribution Variance Varianza de Distribución Hipergeométrica Integer Quotient Cociente entero Integer Part Parte entera Imaginary Part Parte imaginaria Decode IEEE-754 Binary Value Decodificar valor binario IEEE-754 Encode IEEE-754 Binary Value Codificar valor binario IEEE-754 Decode 16-bit Half-Precision Value Decodificar valor de media precisión de 16 bits Encode 16-bit Half-Precision Value Codificar valor de media precisión de 16 bits Decode 32-bit Single-Precision Value Decodificar valor de precisión simple de 32 bits Encode 32-bit Single-Precision Value Codificar valor de precisión simple de 32 bits Decode 64-bit Double-Precision Value Decodificar valor de doble precisión de 64 bits Encode 64-bit Double-Precision Value Codificar valor de doble precisión de 64 bits Decode 128-bit Quad-Precision Value Decodificar valor de precisión cuádruple de 128 bits Encode 128-bit Quad-Precision Value Codificar valor de precisión cuádruple de 128 bits Binary Logarithm Logaritmo binario Common Logarithm Logaritmo decimal Natural Logarithm Logaritmo natural Logarithm to Arbitrary Base Logaritmo de base arbitraria Mask to a bit size Enmascarar a un tamaño en bits Maximum Máximo Median Value (50th Percentile) Valor mediano (percentil 50) Minimum Mínimo Modulo Módulo Euclidean Modulo Módulo euclidiano Modular Exponentiation Exponenciación modular Combination (Binomial Coefficient) Combinación (Coeficiente Binomial) Logical NOT Negación lógica Permutation (Arrangement) Permutación (variación) Convert to Binary Representation Convertir a Binario Arithmetic Aritmética Chemistry Química Complex Complejos Combinatorics Combinatoria Probability Probabilidad Statistics Estadística Aggregation Agregación Random Aleatorio Base conversion Conversión de base Number formatting Formato numérico Integer arithmetic Aritmética de enteros Special functions Funciones especiales Exponential & Logarithmic Exponencial y logarítmica Angle conversion Conversión de ángulos Trigonometry Trigonometría Bitwise Bit a bit Floating point Coma flotante Date & Time Fecha y hora Linear algebra �lgebra lineal unix_timestamp; x hours offset to GMT unix_timestamp; x horas de desfase con respecto a GMT yyyymmdd.hhmmss; x hours offset to GMT aaaammdd.hhmmss; x horas de desfase respecto a GMT [digits] [dígitos] max [; min] máx [; mín] List Literal Literal de lista Convert to Padded Binary Representation Convertir a representación binaria con relleno Round Toward +∞ (Ceiling) Redondear hacia +∞ (techo) Cosine plus Imaginary Sine Coseno más seno imaginario Convert to Cis Complex Form Convertir a forma compleja cis Matrix Column Count Número de columnas de la matriz Population Correlation Matrix (n) Matriz de correlación poblacional (n) Sample Correlation Matrix (n-1) Matriz de correlación muestral (n-1) Count Conteo Population Covariance Matrix (n) Matriz de covarianza poblacional (n) Sample Covariance Matrix (n-1) Matriz de covarianza muestral (n-1) Cross Product Producto vectorial Convert Date to Unix timestamp Convertir fecha a marca de tiempo Unix Convert to Decimal Representation Convertir a decimal Determinant Determinante Convert to Sexagesimal Notation Convertir a notación sexagesimal Dot Product Producto escalar Convert to Engineering Notation Convertir a notación de ingeniería Convert to Exponential Complex Form Convertir a forma compleja exponencial Round Toward −∞ (Floor) Redondear hacia −∞ (suelo) Flatten Matrix Aplanar matriz Least Common Multiple Mínimo común múltiplo Convert to Hexadecimal Representation Convertir a hexadecimal Convert to Padded Hexadecimal Representation Convertir a representación hexadecimal con relleno Inverse Matrix Matriz inversa Round to 16-bit Half-Precision Value Redondear a valor de media precisión de 16 bits Round to 32-bit Single-Precision Value Redondear a valor de precisión simple de 32 bits Round to 64-bit Double-Precision Value Redondear a valor de doble precisión de 64 bits Round to 128-bit Quad-Precision Value Redondear a valor de precisión cuádruple de 128 bits Residual from 16-bit Half-Precision Rounding Residuo del redondeo de media precisión de 16 bits Residual from 32-bit Single-Precision Rounding Residuo del redondeo de precisión simple de 32 bits Residual from 64-bit Double-Precision Rounding Residuo del redondeo de doble precisión de 64 bits Residual from 128-bit Quad-Precision Rounding Residuo del redondeo de precisión cuádruple de 128 bits Substance Mass Masa de sustancia Molarity Molaridad Molar Mass Masa molar Median Absolute Deviation Desviación absoluta mediana Mean Media Numerical Value of Quantity Valor numérico de la magnitud Random Decimal Number Número decimal aleatorio Random Integer Number Número entero aleatorio Convert to Rational Representation Convertir a representación racional Convert to Octal Representation Convertir a octal Convert to Padded Octal Representation Convertir a representación octal con relleno Vector or Matrix Norm Norma de vector o matriz Logical OR Disyunción lógica Population Count (Hamming Weight) Conteo de población (peso de Hamming) Phase of Complex Number Fase del número complejo Poissonian Cumulative Distribution Function Función de Distribución de Poisson Poissonian Distribution Mean Media de Distribución de Poisson Poissonian Probability Mass Function Función de Probabilidad de Poisson Poissonian Distribution Variance Varianza de Distribución de Poisson Convert to Phasor Complex Form Convertir a forma compleja fasorial Convert to Rectangular Complex Form Convertir a forma compleja rectangular Round Half Away from Zero Redondear mitad alejándose de cero Round Half Even Redondear mitad al par Nth Root Raíz enésima Convert to Scientific Notation Convertir a notación científica Matrix Row Count Número de filas de la matriz List or Matrix Shape Forma de lista o matriz Summation Sumatoria Population Standard Deviation (n) Desviación estándar poblacional (n) Sample Standard Deviation (n-1) Desviación estándar muestral (n-1) Round Toward Zero (Truncation) Redondear hacia cero (truncamiento) Matrix Trace Traza de la matriz Transpose Matrix Transponer matriz Population Variance (n) Varianza poblacional (n) Sample Variance (n-1) Varianza muestral (n-1) Product Producto Radians Radianes Matrix Rank Rango de matriz Real Part Parte Real Secant Secante Arithmetic Shift Left Desplazamiento aritmético a la izquierda Arithmetic Shift Right Desplazamiento aritmético a la derecha Signum Signo Sine Seno Hyperbolic Sine Seno Hiperbólico Square Root Raíz Cuadrada Sum Suma Tangent Tangente Convert to Trigonometric Complex Form Convertir a forma compleja trigonométrica Turns Vueltas Hyperbolic Tangent Tangente Hiperbólica Sign-extend a value Extender el signo de un valor Logical XOR Disyunción exclusiva FunctionsWidget Domain Dominio All Todo Name Nombre Search Búsqueda No match found No se encontraron coincidencias Identifier Identificador HistoryWidget Remove All Calculations Above Eliminar todos los cálculos superiores Remove This Calculation Eliminar este cálculo Remove All Calculations Below Eliminar todos los cálculos inferiores Keypad Inverse cosine Inversa del coseno The last result Último resultado Inverse sine Inversa del seno Inverse tangent Inversa de la tangente Evaluate expression Evaluar expresión Division División Multiplication Multiplicación Subtraction Resta Addition Suma Clear expression Borrar expresión Cosine Coseno Backspace Retroceso Scientific notation Notación científica Exponential Exponencial Factorial Factorial Natural logarithm Logaritmo natural Left parenthesis Paréntesis izquierdo Nth root Raíz enésima Argument separator Separador de argumentos Square Cuadrado Common logarithm Logaritmo común Modulo Módulo Contextual percentage Porcentaje contextual Power Potencia Right parenthesis Paréntesis derecho Sine Seno Square root Raíz cuadrada Tangent Tangente Pi Pi Decimal separator Separador decimal MainWindow Radian Radián Degree Grado Gradian Gradián Binary Binario Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Engineering decimal Decimal de ingeniería Scientific decimal Decimal científico &Import... &Importar... &Quit &Salir Clear E&xpression Borrar E&xpresión Clear &History Borrar &Historial &Copy &Copiar &Paste &Pegar &Select Expression &Seleccionar Expresión &Constants &Constantes &Functions &Funciones &History &Historial &Status Bar Barra de &Estado Bitfield Campo de Bits Use&r Functions Funciones de Usua&rio &Degree Gra&do &Radian Ra&dián &Gradian &Gradián Re&volution &Revolución Auto-Insert a&ns I&nsertar ans automáticamente Automatic &Completion &Completado Automático &Built-in Functions &Funciones integradas Built-in &Variables &Variables integradas User &Functions Fu&nciones de usuario User Va&riables Va&riables de usuario Open a Private Tab on Startup Abrir una pestaña privada al iniciar Open and focus a new private tab whenever SpeedCrunch starts. Abrir y activar una nueva pestaña privada cada vez que se inicie SpeedCrunch. Syntax &Highlighting &Resaltado de sintaxis Group Digits in &Input Agrupar díg&itos en la entrada Automatic Input &Adjustments &Ajustes automáticos de entrada Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ajustar automáticamente los operadores, los espacios, los paréntesis y las potencias, y limitar la entrada a caracteres válidos. Group input digits using the selected number format. Agrupar los dígitos de entrada según el formato numérico seleccionado. &Blinking Cursor &Cursor parpadeante Blink the cursor in the expression editor. Hacer parpadear el cursor en el editor de expresiones. &Escape Clears Editor &Escape vacía el editor Clear the focused expression editor with Escape after dismissing any popup or preview. Vaciar el editor de expresiones activo con Escape después de cerrar cualquier ventana emergente o vista previa. Keep Expression After Evaluation Conservar la expresión después del cálculo Copy New Results Automatically Copiar automáticamente los nuevos resultados &Comma &Coma &System Default Predeterminado del &sistema &Dot &Punto Dot &And Comma Punto &y coma Toward +∞ (&ceil) &Hacia +∞ (ceil) Toward −∞ (&floor) Hacia −∞ (&floor) &Binary &Binario &Engineering Ing&eniería &Hexadecimal &Hexadecimal &Octal &Octal &Scientific C&ientífico User &Manual Manual del &usuario Issues and &Feedback &Problemas y comentarios &Donate &Donar &About SpeedCrunch A&cerca de SpeedCrunch App Diag&nostics Diag&nóstico de la aplicación S&plit &Dividir Angle &Mode &Modo angular &Complex Form Forma &compleja New Tab Nueva pestaña Constants Constantes Functions Funciones History Historial User Functions Funciones de usuario &Font... &Fuente... &Language... &Idioma... &Session &Sesión &Edit &Editar &View &Ver Se&ttings &Configuración &Decimal &Decimal &Keypad &Teclado Always on &Top Siempre &encima Disabled Deshabilitado Small Space Espacio pequeño Medium Space Espacio mediano Large Space Espacio grande &0 Digits &0 dígitos &15 Digits &15 dígitos &2 Digits &2 dígitos &3 Digits &3 dígitos &50 Digits &50 dígitos &8 Digits &8 dígitos &Sexagesimal &Sexagesimal Reset All Settings... Restablecer todos los ajustes... &System &Sistema SpeedCrunch &Theme &Tema de SpeedCrunch &Classic &Clásico &Modern &Moderno Context Help Ayuda contextual &Help A&yuda Error Error Can't read from file %1 No puede leerse desde el archivo %1 Import Session Importar Sesión Close Session Cerrar sesión Angle Mode: Modo angular: Notation: Notación: Precision: Precisión: Turn Vuelta Revolution Revolución Fixed-point decimal Decimal de punto fijo Rational Racional Automatic decimal Decimal automático Automatic Automático User &Definitions... &Definiciones de usuario... New &Tab Nueva &pestaña New &Private Tab &Nueva pestaña privada Keep Conservar Make Private... Hacer privada... New &Window Nueva &ventana &Open... &Abrir... &Rename... Cambia&r nombre... Clo&ne... Cl&onar... &Close Tab Cerrar pes&taña Reopen Clo&sed Tab Rea&brir pestaña cerrada Open Sessions &Folder Abrir &carpeta de sesiones &Undo &Deshacer &Redo &Rehacer Cu&t Cor&tar Copy &Last Result Copiar e&l último resultado &Wrap in Parentheses &Encerrar entre paréntesis Full Scr&een Mode M&odo de pantalla completa &Basic &Básico &Scientific (wide) &Científico (ancho) Scientific (narrow) Científico (estrecho) &Custom... &Personalizado... Main &Menu &Menú principal User &Variables &Variables de usuario &Left &Izquierda &Right De&recha &Up &Arriba &Down A&bajo Close Pa&ne Cerrar pa&nel User &Units &Unidades de usuario &Turn &Vuelta If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Si una expresión nueva empieza por +, -, * o /, SpeedCrunch inserta primero "ans". &Accept with Enter &Aceptar con Intro Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Aceptar la sugerencia actual de autocompletado con Intro sin seleccionarla primero con las teclas de flecha. &Units &Unidades Show Live Result &Preview Mostrar &vista previa del resultado en vivo Save &Window Position on Exit Guardar la posición de la &ventana al salir Hover Highlighting Resaltado al pasar el cursor Group Integer Part Only Agrupar solo la parte entera Number Format... Formato numérico... Notation && Precision... Notación y precisión... After pressing Enter, keep the entered expression selected in the editor. Tras pulsar Intro, conservar seleccionada en el editor la expresión introducida. Never Nunca Always Siempre Only for Single-Line Expressions Solo para expresiones de una línea Simplify Displayed Expressions Simplificar expresiones mostradas History Size &Limit... &Límite de tamaño del historial... Remove Trailing &Zeroes &Eliminar ceros finales Nearest, Half &Away (round) Más cercano, mitad &alejada (round) Nearest, Half &Even (roundeven) Más cercano, mitad &par (roundeven) Toward &Zero (trunc) Hacia &cero (trunc) &Fixed-Point &Punto fijo &Rational &Racional &Exponential (m·s�¹) &Exponencial (m·s�¹) &Fractional (m/s) &Fraccionaria (m/s) &Rectangular (a + bi) &Rectangular (a + bi) Exponential (re�ᶿ) Exponencial (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonométrica (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasorial (r∠θ) &Theme... &Tema... Check for &Updates Buscar &actualizaciones Source Code Código fuente &Zoom &Zoom &Results &Resultados Unit Notation Notación de unidades Rounding Mode Modo de redondeo &Notation &Notación &Imaginary Unit Unidad &imaginaria &Window &Ventana &Editing &Edición A&utocomplete A&utocompletar Up/Down Arrow History Historial con flechas arriba/abajo &Appearance &Apariencia &Menus &Menús &Docks &Paneles acoplables &Input and Results E&ntrada y resultados &Disabled &Desactivado &Disable &Desactivar Close preview Cerrar vista previa Rename... Cambiar nombre... Clone... Clonar... Close Tab Cerrar pestaña New Private Tab Nueva pestaña privada Open... Abrir... Reopen Closed Tab Reabrir pestaña cerrada Split Dividir Left Izquierda Right Derecha Up Arriba Down Abajo Clear Vaciar Delete Eliminar %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sesión privada: su contenido se descarta al cerrarla. Elija Sesión > Conservar para convertirla en una sesión normal. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privada] Reset All Settings Restablecer todos los ajustes Reset all settings to their default values? ¿Restablecer todos los ajustes a sus valores predeterminados? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Esto incluye la apariencia, la edición, los formatos de resultados y las preferencias de las ventanas. Se conservarán los cálculos, las sesiones abiertas y las definiciones del usuario. The settings file could not be written. No se pudo escribir el archivo de ajustes. Clear this session's calculations, unfinished expression, variables, functions, and units? ¿Borrar los cálculos, la expresión sin terminar, las variables, las funciones y las unidades de esta sesión? Global user definitions are kept. Se conservan las definiciones globales del usuario. Make Session Private Hacer privada la sesión The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Se eliminará la sesión guardada %1. Su contenido permanecerá abierto en una sesión privada y se descartará al cerrar esa sesión o salir de SpeedCrunch. Make Private Hacer privada Could not delete the saved session %1. No se pudo eliminar la sesión guardada %1. Keep Session Conservar sesión Could not save the session. It remains private. No se pudo guardar la sesión. Sigue siendo privada. Clone Session Clonar sesión Could not save session file %1. No se pudo guardar el archivo de sesión %1. Could not delete session file %1. No se pudo eliminar el archivo de sesión %1. JSON file (*.json);;Any file (*.*) Archivo JSON (*.json);;Cualquier archivo (*.*) Export session as JSON Exportar sesión como JSON The selected file is not valid JSON: %1 El archivo seleccionado no es JSON válido: %1 The selected file is not a SpeedCrunch session JSON file. El archivo seleccionado no es un archivo JSON de sesión de SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Este archivo usa un formato de sesión de SpeedCrunch obsoleto y no se puede importar. The selected JSON file is missing the required $schema field. Al archivo JSON seleccionado le falta el campo obligatorio $schema. The selected JSON file uses an unsupported JSON schema: %1 El archivo JSON seleccionado usa un esquema JSON no compatible: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Al archivo JSON seleccionado le falta el identificador del esquema de sesión de SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 El archivo JSON seleccionado usa un formato de sesión de SpeedCrunch no compatible: %1 The selected JSON file is missing the required session name. Al archivo JSON seleccionado le falta el nombre de sesión obligatorio. The selected JSON file has an empty session name. El archivo JSON seleccionado tiene un nombre de sesión vacío. The selected JSON file has invalid or incomplete SpeedCrunch session data. El archivo JSON seleccionado tiene datos de sesión de SpeedCrunch no válidos o incompletos. Open Sessions Folder Abrir carpeta de sesiones Could not create the sessions folder: %1 No se pudo crear la carpeta de sesiones: %1 Could not open the sessions folder: %1 No se pudo abrir la carpeta de sesiones: %1 Editor and Results Font Fuente del editor y de los resultados Open Session Abrir sesión Community Comunidad Rename Session Renombrar sesión Clear Session Borrar sesión Delete Session Eliminar sesión Close Pane Cerrar panel User Variables Variables de usuario User Units Unidades de usuario Clear History Borrar historial Are you sure you want to clear the calculation history? ¿Seguro que quiere borrar el historial de cálculos? Session name: Nombre de sesión: A session named %1 already exists. Ya existe una sesión llamada %1. Could not create session file %1. No se pudo crear el archivo de sesión %1. Could not write session file %1. No se pudo escribir el archivo de sesión %1. Are you sure you want to delete this session? ¿Seguro que quiere eliminar esta sesión? Custom Precision Precisión personalizada Fractional digits: Dígitos fraccionarios: Theme Tema Light Themes Temas claros Dark Themes Temas oscuros Preview Vista previa Colors Colores Select color for %1 Seleccionar color para %1 Import... Importar... Export... Exportar... Import Theme Importar tema Theme file (*.json);;All files (*) Archivo de tema (*.json);;Todos los archivos (*) Invalid theme file. Archivo de tema no válido. Can't import theme "%1" because it conflicts with a built-in theme. No se puede importar el tema "%1" porque entra en conflicto con un tema integrado. Can't find a writable theme folder. No se puede encontrar una carpeta de temas con permisos de escritura. Overwrite Theme Sobrescribir tema A custom theme named "%1" already exists. Do you want to overwrite it? Ya existe un tema personalizado llamado "%1". ¿Quiere sobrescribirlo? Can't overwrite theme file %1 No se puede sobrescribir el archivo de tema %1 Can't copy theme file to %1 No se puede copiar el archivo de tema a %1 Export Theme Exportar tema Can't export theme as "%1" because it conflicts with a built-in theme. No se puede exportar el tema como "%1" porque entra en conflicto con un tema integrado. Can't write to file %1 No se puede escribir en el archivo %1 Global User Variable Variable global de usuario Global User Function Función global de usuario Global User Unit Unidad global de usuario User Definitions Definiciones de usuario These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Estas definiciones son globales y se cargan en cada sesión. No se pueden modificar desde las sesiones y tienen prioridad sobre las definiciones con el mismo nombre del editor de la sesión. Introduzca una definición por línea. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Ejemplos: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Aplicar Validate Validar Test Results Resultados de la prueba Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variables importadas: %1 Funciones importadas: %2 Unidades importadas: %3 Números de línea con errores: %4 none ninguno Apply Results Resultados de la aplicación User definitions saved. Se han guardado las definiciones de usuario. History Size Limit Límite de tamaño del historial Maximum number of history entries for this session (0 = unlimited): Número máximo de entradas del historial para esta sesión (0 = ilimitado): Text file (*.txt);;Any file (*.*) Archivo de texto (*.txt);;Todos los archivos (*.*) Could not recalculate from calculation %1: %2 No se pudo recalcular desde el cálculo %1: %2 History Size Limit Reached Se alcanzó el límite de tamaño del historial This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Este cálculo ocupa el último espacio disponible del historial. Los cálculos futuros eliminarán del historial el cálculo más antiguo. Puede aumentar el límite en Sesión > Límite de tamaño del historial. Editing calculation. Press Esc twice to cancel. Editando cálculo. Pulse Esc dos veces para cancelar. Calculation Settings Configuración del cálculo Invalid recalculation start index �ndice inicial de recálculo no válido System Default Predeterminado del sistema Language Idioma Select the language: Seleccione el idioma: Custom Personalizado Decimal places: Decimales: &Automatic &Automático &Precision &Precisión Plain &text &Texto sin formato Formula &Book Li&bro de fórmulas &Export &Exportar Export session as HTML Exportar sesión como HTML HTML file (*.html) Documento HTML (*.html) Export session as plain text Exportar sesión como texto sin formato ManualWindow SpeedCrunch Manual Manual de SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual de SpeedCrunch NumberFormatDialog Number Format Formato numérico <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Seleccione el formato numérico para los resultados y la agrupación de dígitos de entrada.</b><br/><br/>Nota: los números introducidos se aceptan en formatos inequívocos aunque difieran del formato de visualización seleccionado.<br/> QObject Global User Variable Variable global de usuario Global User Function Función global de usuario Global User Unit Unidad global de usuario Backspace Retroceso Clear expression Borrar expresión Evaluate expression Evaluar expresión Insert text Insertar texto Automatic decimal Decimal automático Fixed-point decimal Decimal de punto fijo Engineering decimal Decimal de ingeniería Scientific decimal Decimal científico Rational Racional Binary Binario Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Update Available Actualización disponible A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Hay una versión más reciente (%1) disponible.<br/><a href="%2">Visite el sitio web para descargarla.</a> Check for Updates Buscar actualizaciones SpeedCrunch %1 is up to date. SpeedCrunch %1 está actualizado. No connectivity. Please check your internet connection and try again. Sin conectividad. Compruebe su conexión a Internet e inténtelo de nuevo. Could not verify the latest available version. No se pudo verificar la última versión disponible. ResultDisplay Scroll to bottom Desplazarse al final Edit Expression Editar expresión Change Settings Cambiar configuración New Tab Nueva pestaña &Import... &Importar... &Export &Exportar Plain &text &Texto sin formato Copy Copiar Selection Selección Select All Seleccionar todo Expression Expresión Result Resultado Calculation Cálculo Calculation as Single Line Cálculo en una sola línea Remove Eliminar This Calculation Este cálculo All Calculations Above Todos los cálculos anteriores All Calculations Below Todos los cálculos posteriores New Private Tab Nueva pestaña privada Session Sesión Open... Abrir... Clone... Clonar... Rename... Cambiar nombre... Keep Conservar Make Private... Hacer privada... Clear Vaciar Delete Eliminar Close Cerrar Split Dividir Left Izquierda Right Derecha Up Arriba Down Abajo Close Pane Cerrar panel Main Menu Menú principal Cancel editing Cancelar edición Copy result Copiar resultado Edit expression Editar expresión Change settings Cambiar configuración Remove calculation Eliminar cálculo ResultSlotsDialog Notation & Precision Notación y precisión Result Line Línea de resultado Enabled Activado Notation Notación Decimal Places Decimales Main Line Línea principal Extra Line #1 Línea adicional n.º 1 Extra Line #2 Línea adicional n.º 2 Extra Line #3 Línea adicional n.º 3 Extra Line #4 Línea adicional n.º 4 Auto Automático UserFunctionListWidget Name Nombre Value Valor Description Descripción Search Búsqueda No match found No se han encontrado coincidencias Insert Insertar Edit Editar Delete Eliminar Delete All Eliminar Todo UserUnitListWidget Name Nombre Value Valor Description Descripción Search Buscar No match found No se encontraron coincidencias Insert Insertar Edit Editar Delete Eliminar Delete All Eliminar todo VariableListWidget Name Nombre Value Valor Description Descripción Search Búsqueda No match found No se han encontrado coincidencias Insert Insertar Edit Editar Delete Eliminar Delete All Eliminar Todo heldercorreia-speedcrunch-e7ca37f/src/resources/locale/et.ts000066400000000000000000010455711526573132500243720ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunchi info Core developers Põhiarendajad Original author Algne autor Close Sulge Math engine Matemaatikamootor Main author | Logo | Maintainer Peamine autor | Logo | Hooldaja Thanks Tänuavaldused Copyright (C) 2004-2026 The SpeedCrunch developers Autoriõigus (C) 2004-2026 SpeedCrunchi arendajad This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version See programm on vaba tarkvara; seda võib edasi levitada ja/või muuta vastavalt GNU Üldise Avaliku Litsentsi tingimustele, nagu need Vaba Tarkvara Fondi poolt avaldatud on; kas Litsentsi versioon 2 või (vabal valikul) ükskõik milline hilisem versioon This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Seda programmi levitatakse lootuses, et see on kasulik, kuid ILMA IGASUGUSE GARANTIITA; isegi ilma TAVALISE KVALITEEDI või TEATUD OTSTARBEKS SOBIVUSE kaudse garantiita. Üksikasjad on kirjas GNU Üldises Avalikus Litsentsis. BitFieldWidget Reset bits to zero Lähtesta bitid nulliks Invert bits Inverteeri bitid Shift bits left Nihuta bitte vasakule Shift bits right Nihuta bitte paremale Book Index Sisukord Algebra Algebra Quadratic Equation Ruutvõrrand Logarithmic Base Conversion Logaritmi aluse vahetamine Geometry Geomeetria Circle Ring Sector Sektor Sphere Kera Cube Kuup Cone Koonus Cylinder Silinder Electronics Elektroonika Ohm's Law Ohmi seadus Power Võimsus Reactance Reaktiivtakistus Resonance Resonants Radio Frequency Raadiosagedus Antennas Antennid Characteristic Impedance (coax) Lainetakistus (koaksiaalkaabel) Velocity of Propagation (coax) Levikiirus (koaksiaalkaabel) Standing Wave Ratio & Return Loss Seisulaine tegur ja tagasikadu Free Space Wavelength Lainepikkus vabas ruumis resistance takistus voltage pinge current voolutugevus power võimsus inductive reactance induktiivtakistus capacitive reactance mahtuvustakistus inductance induktiivsus capacitance mahtuvus frequency sagedus resonance frequency resonantssagedus area pindala perimeter ümbermõõt diameter diameeter radius raadius volume ruumala surface area pindala height kõrgus slant height apoteem face diagonal tahu diagonaal space diagonal kuubi diagonaal edge length küljepikkus arc length kaare pikkus central angle (degrees) kesknurk (kraadides) input power sisendvõimsus reflected power peegeldunud võimsus transmitted power ülekantud võimsus return loss tagasikadu dielectric constant dielektriline konstant outer conductor's inner diameter välisjuhi siseläbimõõt inner conductor's outer diameter sisejuhi välisläbimõõt speed of light valguse kiirus reflection coefficient peegeldustegur standing wave ratio seisulaine tegur normalized impedance normaliseeritud impedants frequency (Hz) sagedus (Hz) BookDock Formula Book Valemivihik ConstantCompletion Search constants Otsi konstante No match found Vastet ei leitud Constants Mathematics Matemaatika Physics (CODATA 2022) Füüsika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Keemia (IUPAC - CIAAW 2021) Uncategorized Kategoriseerimata Universal Universaalne Physicochemical Füüsikalis-keemilised Atomic & Nuclear — General Aatomi- ja tuumafüüsika - üldine Atomic & Nuclear — Electroweak Aatomi- ja tuumafüüsika - elektronõrk Atomic & Nuclear — Electron Aatomi- ja tuumafüüsika - elektron Atomic & Nuclear — Muon Aatomi- ja tuumafüüsika - müüon Atomic & Nuclear — Tau Aatomi- ja tuumafüüsika - tau Atomic & Nuclear — Proton Aatomi- ja tuumafüüsika - prooton Atomic & Nuclear — Neutron Aatomi- ja tuumafüüsika - neutron Atomic & Nuclear — Deuteron Aatomi- ja tuumafüüsika - deuteron Atomic & Nuclear — Triton Aatomi- ja tuumafüüsika - triiton Atomic & Nuclear — Helion Aatomi- ja tuumafüüsika - heelion Atomic & Nuclear — Alpha particle Aatomi- ja tuumafüüsika - alfaosake Atomic & Nuclear — Atomic units Aatomi- ja tuumafüüsika - aatomiühikud Atomic & Nuclear — Energy conversion relationships Aatomi- ja tuumafüüsika - energia teisendussuhted Atomic & Nuclear — X-ray units Aatomi- ja tuumafüüsika - röntgenühikud Atomic & Nuclear — Magnetic shielding corrections Aatomi- ja tuumafüüsika - magnetvarjestuse parandused Masses Massid Lifetimes Eluead Molar Masses Molaarmassid Electronegativity Elektronegatiivsus Ionization Energy Ionisatsioonienergia Nominal Constants (IAU 2015) Nominaalkonstandid (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Praegused parimad hinnangud (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) vaakumi lainetakistus (Z₀) reduced Planck constant (�) redutseeritud Plancki konstant (�) vacuum electric permittivity (ϵ₀) vaakumi elektriline läbitavus (ϵ₀) Newtonian constant of gravitation (G) Newtoni gravitatsioonikonstant (G) vacuum magnetic permeability (μ₀) vaakumi magnetiline läbitavus (μ₀) Planck constant (h) Plancki konstant (h) speed of light in vacuum (c) valguse kiirus vaakumis (c) standard acceleration of gravity (gₙ) normaalraskuskiirendus (gₙ) Newtonian constant of gravitation over h-bar c Newtoni gravitatsioonikonstant jagatud h-bar c-ga Planck length Plancki pikkus Planck constant in eV/Hz (h) Plancki konstant ühikutes eV/Hz (h) Planck mass Plancki mass Planck mass energy equivalent in GeV Plancki massi energiaekvivalent GeV-des Planck temperature Plancki temperatuur Planck time Plancki aeg reduced Planck constant in eV·s (�) redutseeritud Plancki konstant ühikutes eV·s (�) reduced Planck constant times c in MeV·fm redutseeritud Plancki konstant korda c ühikutes MeV·fm Bohr magneton Bohri magneton conductance quantum (G₀) juhtivuskvant (G₀) Coulomb constant (kₑ) Coulombi konstant (kₑ) elementary charge (e) elementaarlaeng (e) elementary charge over h-bar elementaarlaeng jagatud h-bar-iga conventional value of Josephson constant Josephsoni konstandi kokkuleppeline väärtus Josephson constant Josephson konstant conventional value of ampere-90 ampere-90 kokkuleppeline väärtus conventional value of coulomb-90 coulomb-90 kokkuleppeline väärtus conventional value of farad-90 farad-90 kokkuleppeline väärtus conventional value of henry-90 henry-90 kokkuleppeline väärtus conventional value of ohm-90 ohm-90 kokkuleppeline väärtus conventional value of volt-90 volt-90 kokkuleppeline väärtus conventional value of watt-90 watt-90 kokkuleppeline väärtus magnetic flux quantum (Φ₀) magnetvoo kvant (Φ₀) nuclear magneton tuumamagneton inverse of conductance quantum juhtivuskvandi pöördväärtus conventional value of von Klitzing constant von Klitzingi konstandi kokkuleppeline väärtus von Klitzing constant von Klitzingi konstant atomic unit of magnetic dipole moment magnetilise dipoolmomendi aatomiühik atomic unit of magnetic flux density magnetvoo tiheduse aatomiühik Bohr magneton in eV/T Bohri magneton ühikutes eV/T Bohr magneton in Hz/T Bohri magneton ühikutes Hz/T Bohr magneton in inverse meter per tesla Bohri magneton ühikutes pöördmeeter tesla kohta Bohr magneton in K/T Bohri magneton ühikutes K/T nuclear magneton in eV/T tuumamagneton ühikutes eV/T nuclear magneton in inverse meter per tesla tuumamagneton ühikutes pöördmeeter tesla kohta nuclear magneton in K/T tuumamagneton ühikutes K/T nuclear magneton in MHz/T tuumamagneton ühikutes MHz/T Bohr radius (a₀) Bohri raadius (a₀) fine-structure constant (α) peenstruktuurikonstant (α) Hartree energy (Eₕ) Hartree energia (Eₕ) Hartree energy in eV Hartree energia eV-des quantum of circulation tsirkulatsioonikvant quantum of circulation times 2 kahekordne tsirkulatsioonikvant Rydberg constant (R∞) Rydberg konstant (R∞) atomic mass unit-hartree relationship aatommassiühiku-hartree seos atomic mass unit-hertz relationship aatommassiühiku-hertz seos atomic mass unit-inverse meter relationship aatommassiühiku-pöördmeetri seos atomic mass unit-joule relationship aatommassiühiku-joule seos atomic mass unit-kelvin relationship aatommassiühiku-kelvin seos atomic mass unit-kilogram relationship aatommassiühiku-kilogram seos atomic unit of 1st hyperpolarizability esimese hüperpolariseeritavuse aatomiühik atomic unit of 2nd hyperpolarizability teise hüperpolariseeritavuse aatomiühik atomic unit of charge (e) laengu aatomiühik (e) atomic unit of charge density laengutiheduse aatomiühik atomic unit of current voolu aatomiühik atomic unit of electric dipole moment elektrilise dipoolmomendi aatomiühik atomic unit of electric field elektrivälja aatomiühik atomic unit of electric field gradient elektrivälja gradiendi aatomiühik atomic unit of electric polarizability elektrilise polariseeritavuse aatomiühik atomic unit of electric potential elektripotentsiaali aatomiühik atomic unit of electric quadrupole moment elektrilise kvadrupoolmomendi aatomiühik atomic unit of action mõju aatomiühik atomic unit of energy energia aatomiühik atomic unit of force jõu aatomiühik atomic unit of length pikkuse aatomiühik hertz-atomic mass unit relationship hertz-aatommassiühiku seos hertz-electron volt relationship hertz-elektronvoldi seos hertz-hartree relationship hertz-hartree seos hertz-inverse meter relationship hertz-pöördmeetri seos hertz-joule relationship hertz-joule seos hertz-kelvin relationship hertz-kelvin seos hertz-kilogram relationship hertz-kilogram seos hyperfine transition frequency of Cs-133 Cs-133 ülipeensiirde sagedus inverse fine-structure constant (α�¹) peenstruktuurikonstandi pöördväärtus (α�¹) inverse meter-atomic mass unit relationship pöördmeetri-aatommassiühiku seos inverse meter-electron volt relationship pöördmeetri-elektronvoldi seos inverse meter-hartree relationship pöördmeetri-hartree seos inverse meter-hertz relationship pöördmeetri-hertz seos inverse meter-joule relationship pöördmeetri-joule seos inverse meter-kelvin relationship pöördmeetri-kelvin seos inverse meter-kilogram relationship pöördmeetri-kilogram seos joule-atomic mass unit relationship joule-aatommassiühiku seos joule-electron volt relationship joule-elektronvoldi seos joule-hertz relationship joule-hertz seos joule-hartree relationship joule-hartree seos joule-inverse meter relationship joule-pöördmeetri seos joule-kelvin relationship joule-kelvin seos joule-kilogram relationship joule-kilogram seos kelvin-atomic mass unit relationship kelvin-aatommassiühiku seos kelvin-electron volt relationship kelvin-elektronvoldi seos kelvin-hertz relationship kelvin-hertz seos kelvin-hartree relationship kelvin-hartree seos kelvin-inverse meter relationship kelvin-pöördmeetri seos kelvin-joule relationship kelvin-joule seos kelvin-kilogram relationship kelvin-kilogram seos kilogram-atomic mass unit relationship kilogram-aatommassiühiku seos kilogram-electron volt relationship kilogram-elektronvoldi seos kilogram-hertz relationship kilogram-hertz seos kilogram-hartree relationship kilogram-hartree seos kilogram-inverse meter relationship kilogram-pöördmeetri seos kilogram-joule relationship kilogram-joule seos kilogram-kelvin relationship kilogram-kelvin seos lattice parameter of silicon (a) räni võreparameeter (a) luminous efficacy valguslik tõhusus natural unit of energy energia loomulik ühik natural unit of energy in MeV energia loomulik ühik MeV-des natural unit of action (�) mõju loomulik ühik (�) natural unit of action in eV·s mõju loomulik ühik ühikutes eV·s natural unit of length pikkuse loomulik ühik natural unit of mass massi loomulik ühik natural unit of momentum impulsi loomulik ühik natural unit of momentum in MeV/c impulsi loomulik ühik MeV/c-des natural unit of time aja loomulik ühik natural unit of velocity kiiruse loomulik ühik Rydberg constant times c in Hz Rydbergi konstant korda c hertsides Rydberg constant times hc in eV Rydbergi konstant korda hc elektronvoltides Rydberg constant times hc in J Rydbergi konstant korda hc džaulides Fermi coupling constant Fermi sidestuskonstant weak mixing angle nõrga vastastikmõju segunemisnurk W to Z mass ratio W- ja Z-bosoni masside suhe Thomson cross section (σₑ) Thomsoni ristlõige (σₑ) electron mass (mₑ) elektroni mass (mₑ) electron mass in u elektroni mass aatommassiühikutes electron mass energy equivalent (mₑ·c²) elektroni massi energiaekvivalent (mₑ·c²) electron mass energy equivalent in MeV elektroni massi energiaekvivalent MeV-des reduced Compton wavelength redutseeritud Comptoni lainepikkus classical electron radius (rₑ) klassikaline elektroni raadius (rₑ) electron charge to mass quotient elektroni laengu ja massi suhe electron-deuteron magnetic moment ratio elektroni-deuteroni magnetmomendi suhe electron-deuteron mass ratio elektroni-deuteroni massisuhe electron g factor (gₑ) elektroni g-tegur (gₑ) electron gyromagnetic ratio (γₑ) elektroni güromagnetiline suhe (γₑ) electron gyromagnetic ratio in MHz/T elektroni güromagnetiline suhe ühikutes MHz/T electron-helion mass ratio elektroni-heelioni massisuhe electron magnetic moment (μₑ) elektroni magnetmoment (μₑ) electron magnetic moment anomaly (aₑ) elektroni magnetmomendi anomaalia (aₑ) electron magnetic moment to Bohr magneton ratio elektroni magnetmomendi ja Bohri magnetoni suhe electron magnetic moment to nuclear magneton ratio elektroni magnetmomendi ja tuumamagnetoni suhe electron molar mass (Mₑ) elektroni molaarmass (Mₑ) electron-muon magnetic moment ratio elektroni-müüoni magnetmomendi suhe electron-muon mass ratio elektroni-müüoni massisuhe electron-neutron magnetic moment ratio elektroni-neutroni magnetmomendi suhe electron-neutron mass ratio elektroni-neutroni massisuhe electron-proton magnetic moment ratio elektroni-prootoni magnetmomendi suhe electron-proton mass ratio elektroni-prootoni massisuhe electron relative atomic mass (Ar(e)) elektroni suhteline aatommass (Ar(e)) electron-tau mass ratio elektroni-tau massisuhe electron to alpha particle mass ratio elektroni ja alfaosakese masside suhe electron to shielded helion magnetic moment ratio elektroni ja varjestatud heelioni magnetmomendi suhe electron to shielded proton magnetic moment ratio elektroni ja varjestatud prootoni magnetmomendi suhe electron-triton mass ratio elektroni-triitoni massisuhe electron volt-atomic mass unit relationship elektronvoldi-aatommassiühiku seos electron volt-hartree relationship elektronvoldi-hartree seos electron volt-hertz relationship elektronvoldi-hertz seos electron volt-inverse meter relationship elektronvoldi-pöördmeetri seos electron volt-joule relationship elektronvoldi-joule seos electron volt-kelvin relationship elektronvoldi-kelvin seos electron volt-kilogram relationship elektronvoldi-kilogram seos hartree-atomic mass unit relationship hartree-aatommassiühiku seos hartree-electron volt relationship hartree-elektronvoldi seos muon Compton wavelength müüoni Comptoni lainepikkus muon-electron mass ratio müüoni-elektroni massisuhe muon g factor müüoni g-tegur muon magnetic moment müüoni magnetmoment muon magnetic moment anomaly müüoni magnetmomendi anomaalia muon magnetic moment to Bohr magneton ratio müüoni magnetmomendi ja Bohri magnetoni suhe muon magnetic moment to nuclear magneton ratio müüoni magnetmomendi ja tuumamagnetoni suhe muon mass müüoni mass muon mass energy equivalent müüoni massi energiaekvivalent muon mass energy equivalent in MeV müüoni massi energiaekvivalent MeV-des muon mass in u müüoni mass aatommassiühikutes muon molar mass müüoni molaarmass muon-neutron mass ratio müüoni-neutroni massisuhe muon-proton magnetic moment ratio müüoni-prootoni magnetmomendi suhe muon-proton mass ratio müüoni-prootoni massisuhe muon-tau mass ratio müüoni-tau massisuhe reduced muon Compton wavelength redutseeritud müüoni Comptoni lainepikkus reduced tau Compton wavelength redutseeritud tau Comptoni lainepikkus tau Compton wavelength tau Comptoni lainepikkus tau-electron mass ratio tau-elektroni massisuhe tau mass tau mass tau mass energy equivalent tau massi energiaekvivalent tau mass in u tau mass aatommassiühikutes tau molar mass tau molaarmass tau-muon mass ratio tau-müüoni massisuhe tau-neutron mass ratio tau-neutroni massisuhe tau-proton mass ratio tau-prootoni massisuhe proton charge to mass quotient prootoni laengu ja massi suhe proton Compton wavelength prootoni Comptoni lainepikkus proton-electron mass ratio prootoni-elektroni massisuhe proton g factor (gₚ) prootoni g-tegur (gₚ) proton gyromagnetic ratio (γₚ) prootoni güromagnetiline suhe (γₚ) proton gyromagnetic ratio in MHz/T prootoni güromagnetiline suhe ühikutes MHz/T proton magnetic moment (μₚ) prootoni magnetmoment (μₚ) proton magnetic moment to Bohr magneton ratio prootoni magnetmomendi ja Bohri magnetoni suhe proton magnetic moment to nuclear magneton ratio prootoni magnetmomendi ja tuumamagnetoni suhe proton magnetic shielding correction prootoni magnetvarjestuse parandus proton mass (mₚ) prootoni mass (mₚ) proton mass energy equivalent prootoni massi energiaekvivalent proton mass energy equivalent in MeV prootoni massi energiaekvivalent MeV-des proton mass in u prootoni mass aatommassiühikutes proton molar mass (Mₚ) prootoni molaarmass (Mₚ) proton-muon mass ratio prootoni-müüoni massisuhe proton-neutron magnetic moment ratio prootoni-neutroni magnetmomendi suhe proton-neutron mass ratio prootoni-neutroni massisuhe proton relative atomic mass (Ar(p)) prootoni suhteline aatommass (Ar(p)) proton rms charge radius prootoni rms laenguraadius proton-tau mass ratio prootoni-tau massisuhe reduced proton Compton wavelength redutseeritud prootoni Comptoni lainepikkuse shielded proton gyromagnetic ratio varjestatud prootoni güromagnetiline suhe shielded proton gyromagnetic ratio in MHz/T varjestatud prootoni güromagnetiline suhe ühikutes MHz/T shielded proton magnetic moment varjestatud prootoni magnetmoment shielded proton magnetic moment to Bohr magneton ratio varjestatud prootoni magnetmomendi ja Bohri magnetoni suhe shielded proton magnetic moment to nuclear magneton ratio varjestatud prootoni magnetmomendi ja tuumamagnetoni suhe neutron Compton wavelength neutroni Comptoni lainepikkus neutron-electron magnetic moment ratio neutroni-elektroni magnetmomendi suhe neutron-electron mass ratio neutroni-elektroni massisuhe neutron g factor (gₙ) neutroni g-tegur (gₙ) neutron gyromagnetic ratio (γₙ) neutroni güromagnetiline suhe (γₙ) neutron gyromagnetic ratio in MHz/T neutroni güromagnetiline suhe ühikutes MHz/T neutron magnetic moment (μₙ) neutroni magnetmoment (μₙ) neutron magnetic moment to Bohr magneton ratio neutroni magnetmomendi ja Bohri magnetoni suhe neutron magnetic moment to nuclear magneton ratio neutroni magnetmomendi ja tuumamagnetoni suhe neutron mass (mₙ) neutroni mass (mₙ) neutron mass energy equivalent neutroni massi energiaekvivalent neutron mass energy equivalent in MeV neutroni massi energiaekvivalent MeV-des neutron mass in u neutroni mass aatommassiühikutes neutron molar mass (Mₙ) neutroni molaarmass (Mₙ) neutron-muon mass ratio neutroni-müüoni massisuhe neutron-proton magnetic moment ratio neutroni-prootoni magnetmomendi suhe neutron-proton mass difference neutroni ja prootoni massierinevus neutron-proton mass difference energy equivalent neutroni ja prootoni massierinevuse energiaekvivalent neutron-proton mass difference energy equivalent in MeV neutroni ja prootoni massierinevuse energiaekvivalent MeV-des neutron-proton mass difference in u neutroni ja prootoni massierinevus aatommassiühikutes neutron-proton mass ratio neutroni-prootoni massisuhe neutron relative atomic mass (Ar(n)) neutroni suhteline aatommass (Ar(n)) neutron-tau mass ratio neutroni-tau massisuhe neutron to shielded proton magnetic moment ratio neutroni ja varjestatud prootoni magnetmomendi suhe reduced neutron Compton wavelength redutseeritud neutroni Comptoni lainepikkuse deuteron-electron magnetic moment ratio deuteroni-elektroni magnetmomendi suhe deuteron-electron mass ratio deuteroni-elektroni massisuhe deuteron g factor deuteroni g-tegur deuteron magnetic moment deuteroni magnetmoment deuteron magnetic moment to Bohr magneton ratio deuteroni magnetmomendi ja Bohri magnetoni suhe deuteron magnetic moment to nuclear magneton ratio deuteroni magnetmomendi ja tuumamagnetoni suhe deuteron mass deuteroni mass deuteron mass energy equivalent deuteroni massi energiaekvivalent deuteron mass energy equivalent in MeV deuteroni massi energiaekvivalent MeV-des deuteron mass in u deuteroni mass aatommassiühikutes deuteron molar mass deuteroni molaarmass deuteron-neutron magnetic moment ratio deuteroni-neutroni magnetmomendi suhe deuteron-proton magnetic moment ratio deuteroni-prootoni magnetmomendi suhe deuteron-proton mass ratio deuteroni-prootoni massisuhe deuteron relative atomic mass (Ar(d)) deuteroni suhteline aatommass (Ar(d)) deuteron rms charge radius deuteroni rms laenguraadius triton-electron mass ratio triitoni-elektroni massisuhe triton g factor (gₜ) triitoni g-tegur (gₜ) triton magnetic moment (μₜ) triitoni magnetmoment (μₜ) triton magnetic moment to Bohr magneton ratio triitoni magnetmomendi ja Bohri magnetoni suhe triton magnetic moment to nuclear magneton ratio triitoni magnetmomendi ja tuumamagnetoni suhe triton mass (mₜ) triitoni mass (mₜ) triton mass energy equivalent triitoni massi energiaekvivalent triton mass energy equivalent in MeV triitoni massi energiaekvivalent MeV-des triton mass in u triitoni mass aatommassiühikutes triton molar mass (Mₜ) triitoni molaarmass (Mₜ) triton-proton mass ratio triitoni-prootoni massisuhe triton relative atomic mass (Ar(t)) triitoni suhteline aatommass (Ar(t)) triton to proton magnetic moment ratio triitoni ja prootoni magnetmomendi suhe helion-electron mass ratio heelioni-elektroni massisuhe helion g factor (gₕ) heelioni g-tegur (gₕ) helion magnetic moment (μₕ) heelioni magnetmoment (μₕ) helion magnetic moment to Bohr magneton ratio heelioni magnetmomendi ja Bohri magnetoni suhe helion magnetic moment to nuclear magneton ratio heelioni magnetmomendi ja tuumamagnetoni suhe helion mass (mₕ) heelioni mass (mₕ) helion mass energy equivalent heelioni massi energiaekvivalent helion mass energy equivalent in MeV heelioni massi energiaekvivalent MeV-des helion mass in u heelioni mass aatommassiühikutes helion molar mass (Mₕ) heelioni molaarmass (Mₕ) helion-proton mass ratio heelioni-prootoni massisuhe helion relative atomic mass (Ar(h)) heelioni suhteline aatommass (Ar(h)) helion shielding shift heelioni varjestusnihe shielded helion gyromagnetic ratio varjestatud heelioni güromagnetiline suhe shielded helion gyromagnetic ratio in MHz/T varjestatud heelioni güromagnetiline suhe ühikutes MHz/T shielded helion magnetic moment varjestatud heelioni magnetmoment shielded helion magnetic moment to Bohr magneton ratio varjestatud heelioni magnetmomendi ja Bohri magnetoni suhe shielded helion magnetic moment to nuclear magneton ratio varjestatud heelioni magnetmomendi ja tuumamagnetoni suhe shielded helion to proton magnetic moment ratio varjestatud heelioni ja prootoni magnetmomendi suhe shielded helion to shielded proton magnetic moment ratio varjestatud heelioni ja varjestatud prootoni magnetmomendi suhe alpha particle mass alfaosakese mass alpha particle mass in u alfaosakese mass aatommassiühikutes alpha particle mass energy equivalent alfaosakese massi energiaekvivalent alpha particle mass energy equivalent in MeV alfaosakese massi energiaekvivalent MeV-des alpha particle-electron mass ratio alfaosakese ja elektroni masside suhe alpha particle-proton mass ratio alfaosakese ja prootoni masside suhe alpha particle rms charge radius alfaosakese ruutkeskmine laenguraadius alpha particle molar mass alfaosakese molaarmass alpha particle relative atomic mass (Ar(α)) alfaosakese suhteline aatommass (Ar(α)) atomic mass constant (mᵤ) aatommassikonstant (mᵤ) Avogadro constant Avogadro konstant Boltzmann constant (k) Boltzmann konstant (k) Boltzmann constant in eV/K Boltzmanni konstant ühikutes eV/K Boltzmann constant in Hz/K Boltzmanni konstant ühikutes Hz/K Boltzmann constant in inverse meter per kelvin Boltzmanni konstant ühikutes pöördmeeter kelvini kohta electron volt (eV) elektronvoldi (eV) Faraday constant (F) Faraday konstant (F) first radiation constant (c�) esimene kiirguskonstant (c�) first radiation constant for spectral radiance spektraalse kiirgavuse esimene kiirguskonstant molar gas constant (R) molaarne gaasi konstant (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidt konstant (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Loschmidt konstant (n₀, 273.15 K, 101.325 kPa) molar Planck constant molaarne Plancki konstant second radiation constant (c₂) teine kiirguskonstant (c₂) Stefan-Boltzmann constant (σ) Stefan-Boltzmann konstant (σ) lattice spacing of ideal Si (d₂₂₀) ideaalse Si võrevahe (d₂₂₀) atomic mass constant energy equivalent aatommassikonstandi energiaekvivalent atomic mass constant energy equivalent in MeV aatommassikonstandi energiaekvivalent MeV-des atomic mass unit-electron volt relationship aatommassiühiku-elektronvoldi seos molar mass constant (Mᵤ) molaarmassikonstant (Mᵤ) molar mass of carbon-12 süsinik-12 molaarmass molar volume of ideal gas (273.15 K, 100 kPa) ideaalse gaasi molaarmaht (273,15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ideaalse gaasi molaarmaht (273,15 K, 101,325 kPa) molar volume of silicon räni molaarmaht Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode konstant (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode konstant (1 K, 101.325 kPa) Wien frequency displacement law constant Wieni sageduse nihkeseaduse konstant Wien wavelength displacement law constant Wieni lainepikkuse nihkeseaduse konstant standard atmosphere (atm) standardne atmosfäär (atm) standard-state pressure (p°) standardoleku rõhk (p°) Angstrom star (Å*) ångströmi täht (Å*) Copper x unit vase x-ühik Molybdenum x unit molübdeeni x-ühik atomic unit of magnetizability magnetiseeritavuse aatomiühik atomic unit of mass (mₑ) massi aatomiühik (mₑ) atomic unit of momentum impulsi aatomiühik atomic unit of permittivity dielektrilise läbitavuse aatomiühik atomic unit of time aja aatomiühik atomic unit of velocity kiiruse aatomiühik hartree-hertz relationship hartree-hertz seos hartree-inverse meter relationship hartree-pöördmeetri seos hartree-joule relationship hartree-joule seos hartree-kelvin relationship hartree-kelvin seos hartree-kilogram relationship hartree-kilogram seos shielding difference of d and p in HD d ja p varjestuse erinevus HD-s shielding difference of t and p in HT t ja p varjestuse erinevus HT-s pi (π) pii (π) Euler's number (e) Euleri arv (e) golden ratio (φ) kuldlõige (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni konstant (γ) nominal solar radius nominaalne Päikese raadius nominal solar total irradiance Päikese nominaalne kogukiiritustihedus nominal solar luminosity Päikese nominaalne heledus nominal solar effective temperature Päikese nominaalne efektiivne temperatuur nominal solar mass parameter Päikese nominaalne massiparameeter nominal terrestrial equatorial radius nominaalne Maa ekvatoriaalne raadius nominal terrestrial polar radius nominaalne Maa polaarne raadius nominal terrestrial mass parameter Maa nominaalne massiparameeter nominal jovian equatorial radius nominaalne Jupiteri ekvatoriaalne raadius nominal jovian polar radius nominaalne Jupiteri polaarne raadius nominal jovian mass parameter Jupiteri nominaalne massiparameeter average value of one minus the rate of TCG relative to TCB keskmine väärtus suurusele üks miinus TCG kulgemiskiirus TCB suhtes solar mass parameter (TCB-compatible) Päikese massiparameeter (TCB-ühilduv) solar mass parameter (TDB-compatible) Päikese massiparameeter (TDB-ühilduv) equatorial radius of the Earth (TT-compatible) Maa ekvatoriaalraadius (TT-ühilduv) dynamical form factor of the Earth Maa dünaamiline kujutegur time rate of change in the dynamical form factor of the Earth Maa dünaamilise kujuteguri ajaline muutumiskiirus geocentric gravitational constant (TCB-compatible) geotsentriline gravitatsioonikonstant (TCB-ühilduv) geocentric gravitational constant (TT-compatible) geotsentriline gravitatsioonikonstant (TT-ühilduv) geocentric gravitational constant (TDB-compatible) geotsentriline gravitatsioonikonstant (TDB-ühilduv) potential of the geoid geoidi potentsiaal nominal mean angular velocity of the Earth (TT-compatible) Maa nominaalne keskmine nurkkiirus (TT-ühilduv) ratio mass of the Moon to the Earth Kuu ja Maa massisuhe ratio of the mass of the Sun to Mercury Päikese ja Merkuuri massisuhe ratio of the mass of the Sun to Venus Päikese ja Veenuse massisuhe ratio of the mass of the Sun to Mars Päikese ja Marsi massisuhe ratio of the mass of the Sun to Jupiter Päikese ja Jupiteri massisuhe ratio of the mass of the Sun to Saturn Päikese ja Saturni massisuhe ratio of the mass of the Sun to Uranus Päikese ja Uraani massisuhe ratio of the mass of the Sun to Neptune Päikese ja Neptuuni massisuhe ratio of the mass of the Sun to (134340) Pluto Päikese ja (134340) Pluto massisuhe ratio of the mass of the Sun to (136199) Eris Päikese ja (136199) Erise massisuhe ratio of the mass of (1) Ceres to the Sun (1) Cerese ja Päikese massisuhe ratio of the mass of (2) Pallas to the Sun (2) Pallase ja Päikese massisuhe ratio of the mass of (4) Vesta to the Sun (4) Vesta ja Päikese massisuhe mean obliquity of the ecliptic at J2000.0 ekliptika keskmine kalle epohhil J2000.0 Electromagnetic Elektromagnetism Compton wavelength Comptoni lainepikkus Astronomy Astronoomia ConstantsWidget Domain Valdkond Subdomain Alamvaldkond No match found Vastet ei leitud Name Nimi Value Väärtus Unit Ühik Search Otsing All Kõik CustomKeypadDialog Custom Keypad Kohandatud klahvistik Rows: Read: Columns: Veerud: Copy preset: Kopeeri eelseadistus: Basic Põhiline Scientific (wide) Teaduslik (lai) Scientific (narrow) Teaduslik (kitsas) Apply Rakenda Row Rida Column Veerg Label Silt Behavior Käitumine Text Tekst DiagnosticsDialog App Diagnostics Rakenduse diagnostika Copy to Clipboard Kopeeri lõikelauale Editor Unit Ühik User unit Kasutaja ühik User function Kasutaja funktsioon Argument Argument Current result:<br/>%1 Praegune tulemus:<br/>%1 Selection result:<br/>%1 Valiku tulemus:<br/>%1 Selection result: n/a Valiku tulemus: n/a Selection result: %1 Valiku tulemus: %1 second sekund metre meeter kilogram kilogramm mole mool radian radiaan steradian steradiaan degree Celsius Celsiuse kraad cubic metre kuupmeeter cubic millimetre kuupmillimeeter cubic centimetre kuupsentimeeter cubic decimetre kuupdetsimeeter cubic kilometre kuupkilomeeter square millimetre ruutmillimeeter square kilometre ruutkilomeeter square metre ruutmeeter minute minut hour tund day päev astronomical unit astronoomiline ühik degree kraad arcminute kaareminut arcsecond kaaresekund milliarcsecond millikaaresekund microarcsecond mikrokaaresekund hectare hektar litre liiter tonne tonn Dalton dalton electronvolt elektronvolt Angstrom ångström atmosphere atmosfäär atomic mass unit aatommassiühik British thermal unit Briti soojusühik calorie kalor carat karaat cup tass cup (Imperial) tass (Briti) cup (Japanese) tass (Jaapani) cup (US) tass (USA) degree Fahrenheit Fahrenheiti kraad fathom süld fluid ounce (Imperial) vedelikuunts (Briti) fluid ounce (US) vedelikuunts (USA) fluid dram (Imperial) vedelikudrahm (Briti) fluid dram (US) vedelikudrahm (USA) foot jalg square foot ruutjalg cubic foot kuupjalg gallon (Imperial) gallon (Briti) gallon (US) gallon (USA) gill (Imperial) gill (Briti) gill (US) gill (USA) gradian goon grain graan gram gramm Hartley hartley Hartree energy unit Hartree energiaühik horsepower hobujõud inch toll square inch ruuttoll cubic inch kuuptoll karat kullakaraat knot sõlm lightminute valgusminut lightsecond valgussekund lightyear valgusaasta long ton pikk tonn mile miil square mile ruutmiil cubic mile kuupmiil mile per hour miil tunnis kilometre per hour kilomeeter tunnis nautical mile meremiil ounce unts parsec parsek pint (Imperial) pint (Briti) pint (US) pint (USA) pound nael pounds per square inch naela ruuttolli kohta quart (Imperial) kvart (Briti) quart (US) kvart (USA) oil barrel naftabarrel beer barrel (US) õllebarrel (USA) square yard ruutjard cubic yard kuupjard short ton lühike tonn tablespoon supilusikas tablespoon (Australian) supilusikas (Austraalia) tablespoon (Imperial) supilusikas (Briti) tablespoon (US) supilusikas (USA) dessert spoon dessertlusikas teaspoon teelusikas teaspoon (Imperial) teelusikas (Briti) teaspoon (US) teelusikas (USA) turn täispööre revolution pööre revolution per minute pööret minutis week nädal kilowatt hour kilovatt-tund millimetre of mercury elavhõbedamillimeeter yard jard Julian century Juliuse sajand Julian year Juliuse aasta sidereal year sideeriline aasta tropical year troopiline aasta Evaluator invalid expression Vigane avaldis division by zero nulliga jagamine too time consuming - computation was rejected liialt aeganõudev - arvutamine lükati tagasi dimension mismatch - quantities with different dimensions cannot be compared, added, etc. mõõtmete sobimatus - eri mõõtmetega suurusi ei saa võrrelda, liita jne. invalid dimension - operation might require dimensionless arguments vigane mõõde - tehe võib nõuda mõõtmeteta argumente Computation aborted - encountered numerical instability Arvutamine katkestati - ilmnes arvuline ebastabiilsus invalid dimension - function might require dimensionless arguments vigane mõõde - funktsioon võib nõuda mõõtmeteta argumente error viga unit must not be zero ühik ei tohi olla null Conversion failed - dimension mismatch Teisendamine ebaõnnestus - mõõtmete sobimatus unknown function or variable tundmatu funktsioon või muutuja recursion not supported rekursiooni ei toetata cannot operate on a NaN mittearvudega pole võimalik tehteid sooritada underflow - tiny result is out of SpeedCrunch's number range alatäitumine - tulemus on nii väike, et jääb SpeedCrunchi arvuulatusest välja overflow - huge result is out of SpeedCrunch's number range ületäitumine - tulemus on nii suur, et jääb SpeedCrunchi arvuulatusest välja overflow - logic result exceeds maximum of 256 bits ületäitumine - loogika tulemus ületab lubatud 256 bitti overflow - integer result exceeds maximum limit for integers ületäitumine - täisarvuline tulemus ületab täisarvudele seatud piiri operation is not defined for these arguments tehe pole nende argumentide jaoks defineeritud wrong number of arguments sobimatu arv argumente does not take NaN as an argument mittearv ei sobi argumendiks result out of range tulemus on vahemikust väljas undefined for argument domain argumendi määramispiirkonnas määratlemata computation too expensive arvutus on liiga kulukas internal error, please report a bug sisemine viga, palun saada vearaport syntax error süntaksiviga conversion target must be a unit teisenduse siht peab olema ühik unknown unit tundmatu ühik %1 is a reserved name, please choose another "%1" on reserveeritud nimi, palun vali teistsugune %1 is a global user definition and cannot be overridden in this session. %1 on globaalne kasutaja definitsioon ja seda ei saa selles seansis üle kirjutada. %1 is a variable name, please choose another or delete the variable "%1" on muutuja nimi, palun vali teistsugune või kustuta muutuja argument %1 is used more than once argumenti %1 on kasutatud rohkem kui üks kord %1 is a built-in unit name, please choose another %1 on sisseehitatud ühiku nimi, palun vali teine %1 is a user function name, please choose another or delete the function "%1" on kasutaja funktsiooni nimi, palun vali teistsugune või kustuta muutuja FunctionRepo max; trials; probability max; katsed; tõenäosus trials; probability katsed; tõenäosus hits; trials; probability tabamused; katsed; tõenäosus max; total; hits; trials max; koguarv; tabamused; katsed total; hits; trials koguarv; tabamused; katsed count; total; hits; trials arv; koguarv; tabamused; katsed dividend; divisor jagatav; jagaja x; exponent_bits; significand_bits [; exponent_bias] x; astendaja_bitid; mantissi_bitid [; astendaja_nihe] base; x alus; x value; modulo väärtus; moodul base; exponent; modulo alus; astendaja; moodul events; average_events sündmused; keskmine_sündmuste_arv average_events keskmine_sündmuste_arv x [; precision] x [; täpsus] Absolute Value Absoluutväärtus Absolute Deviation Absoluuthälve Arc Cosine Arkuskoosinus Logical AND Loogiline JA Area Hyperbolic Cosine Areakoosinus Area Hyperbolic Sine Areasiinus Area Hyperbolic Tangent Areatangens Arc Sine Arkussiinus Arc Tangent Arkustangens Arc Tangent with two Arguments Arkustangens kahe argumendiga Average (Arithmetic Mean) Keskmine (aritmeetiline keskmine) Binomial Cumulative Distribution Function Binoomjaotuse kumulatiivne jaotusfunktsioon Binomial Distribution Mean Binoomjaotuse keskväärtus Binomial Probability Mass Function Binoomjaotuse suhteline sagedusfunktsioon Binomial Distribution Variance Binoomjaotuse dispersioon Cube Root Kuupjuur Complex Conjugate Kaaskompleksarv Cosine Koosinus Hyperbolic Cosine Hüperboolne koosinus Cotangent Kootangens Cosecant Koosekans Convert Unix timestamp to Date Unixi ajatempli teisendamine kuupäevaks Degrees of Arc Kaarekraadid Error Function Veafunktsioon Complementary Error Function Täiendav veafunktsioon Exponential Eksponentfunktsioon Fractional Part Murdosa Extension of Factorials [= (x-1)!] Gammafunktsioon (faktoriaali üldistus) [= (x-1)!] Greatest Common Divisor Suurim ühistegur Geometric Mean Geomeetriline keskmine Gradians of arc Goonid Hypergeometric Cumulative Distribution Function Hüpergeomeetrilise jaotuse kumulatiivne jaotusfunktsioon Hypergeometric Distribution Mean Hüpergeomeetrilise jaotuse keskväärtus Hypergeometric Probability Mass Function Hüpergeomeetrilise jaotuse suhteline sagedusfunktsioon Hypergeometric Distribution Variance Hüpergeomeetrilise jaotuse dispersioon Integer Quotient Jagatise täisosa Integer Part Täisosa Imaginary Part Imaginaarosa Decode IEEE-754 Binary Value IEEE-754 kahendväärtuse dekodeerimine Encode IEEE-754 Binary Value IEEE-754 kahendväärtuse kodeerimine Decode 16-bit Half-Precision Value 16-bitise pooltäpsusega väärtuse dekodeerimine Encode 16-bit Half-Precision Value 16-bitise pooltäpsusega väärtuse kodeerimine Decode 32-bit Single-Precision Value 32-bitise üksiktäpsusega väärtuse dekodeerimine Encode 32-bit Single-Precision Value 32-bitise üksiktäpsusega väärtuse kodeerimine Decode 64-bit Double-Precision Value 64-bitise topelttäpsusega väärtuse dekodeerimine Encode 64-bit Double-Precision Value 64-bitise topelttäpsusega väärtuse kodeerimine Decode 128-bit Quad-Precision Value 128-bitise neliktäpsusega väärtuse dekodeerimine Encode 128-bit Quad-Precision Value 128-bitise neliktäpsusega väärtuse kodeerimine Binary Logarithm Kahendlogaritm Common Logarithm Kümnendlogaritm Natural Logarithm Naturaallogaritm Logarithm to Arbitrary Base Logaritm mistahes alusel Mask to a bit size Maskimine bitisuuruseni Maximum Maksimum Median Value (50th Percentile) Mediaanväärtus (50. protsentiil) Minimum Miinimum Modulo Jääk Euclidean Modulo Eukleidiline jääk Modular Exponentiation Moodulastendamine Combination (Binomial Coefficient) Kombinatsioonide arv Logical NOT Loogiline EI Permutation (Arrangement) Variatsioonide arv Convert to Binary Representation Teisendamine kahendsüsteemi Arithmetic Aritmeetika Chemistry Keemia Complex Kompleksarvud Combinatorics Kombinatoorika Probability Tõenäosus Statistics Statistika Aggregation Agregeerimine Random Juhuslik Base conversion Aluse teisendus Number formatting Arvu vormindamine Integer arithmetic Täisarvuaritmeetika Special functions Erifunktsioonid Exponential & Logarithmic Eksponentsiaalne ja logaritmiline Angle conversion Nurga teisendus Trigonometry Trigonomeetria Bitwise Bitikaupa Floating point Ujukoma Date & Time Kuupäev ja kellaaeg Linear algebra Lineaaralgebra unix_timestamp; x hours offset to GMT unixi_ajatempel; x-tunnine nihe GMT/UTC suhtes yyyymmdd.hhmmss; x hours offset to GMT aaaakkpp.hhmmss; x-tunnine nihe GMT/UTC suhtes [digits] [numbrid] max [; min] maks [; min] List Literal Loendiliteraal Convert to Padded Binary Representation Teisenda täidetud kahendesituseks Round Toward +∞ (Ceiling) Ümarda +∞ suunas (lagi) Cosine plus Imaginary Sine Koosinus pluss imaginaarne siinus Convert to Cis Complex Form Teisenda cis-komplekskujule Matrix Column Count Maatriksi veergude arv Population Correlation Matrix (n) Populatsiooni korrelatsioonimaatriks (n) Sample Correlation Matrix (n-1) Valimi korrelatsioonimaatriks (n-1) Count Arv Population Covariance Matrix (n) Populatsiooni kovariatsioonimaatriks (n) Sample Covariance Matrix (n-1) Valimi kovariatsioonimaatriks (n-1) Cross Product Vektorkorrutis Convert Date to Unix timestamp Kuupäeva teisendamine Unixi ajatempliks Convert to Decimal Representation Teisendamine kümnendsüsteemi Determinant Determinant Convert to Sexagesimal Notation Teisenda kuuekümnendsüsteemi esituseks Dot Product Skalaarkorrutis Convert to Engineering Notation Teisenda inseneriesituseks Convert to Exponential Complex Form Teisenda eksponentsiaalsele komplekskujule Round Toward −∞ (Floor) Ümarda −∞ suunas (põrand) Flatten Matrix Tasanda maatriks Least Common Multiple Vähim ühiskordne Convert to Hexadecimal Representation Teisendamine kuueteistkümnendsüsteemi Convert to Padded Hexadecimal Representation Teisenda täidetud kuueteistkümnendesituseks Inverse Matrix Pöördmaatriks Round to 16-bit Half-Precision Value Ümarda 16-bit pooltäpsusega väärtuseks Round to 32-bit Single-Precision Value Ümarda 32-bit üksiktäpsusega väärtuseks Round to 64-bit Double-Precision Value Ümarda 64-bit topelttäpsusega väärtuseks Round to 128-bit Quad-Precision Value Ümarda 128-bit neliktäpsusega väärtuseks Residual from 16-bit Half-Precision Rounding Jääk pärast 16-bit pooltäpsusega ümardamist Residual from 32-bit Single-Precision Rounding Jääk pärast 32-bit üksiktäpsusega ümardamist Residual from 64-bit Double-Precision Rounding Jääk pärast 64-bit topelttäpsusega ümardamist Residual from 128-bit Quad-Precision Rounding Jääk pärast 128-bit neliktäpsusega ümardamist Substance Mass Aine mass Molarity Molaarsus Molar Mass Molaarmass Median Absolute Deviation Mediaani absoluutne hälve Mean Keskmine Numerical Value of Quantity Suuruse arvväärtus Random Decimal Number Juhuslik kümnendarv Random Integer Number Juhuslik täisarv Convert to Rational Representation Teisenda ratsionaalesituseks Convert to Octal Representation Teisendamine kaheksandsüsteemi Convert to Padded Octal Representation Teisenda täidetud kaheksandesituseks Vector or Matrix Norm Vektori või maatriksi norm Logical OR Loogiline VÕI Population Count (Hamming Weight) Ühtede arv (Hammingi kaal) Phase of Complex Number Kompleksarvu faas Poissonian Cumulative Distribution Function Poissoni jaotuse kumulatiivne jaotusfunktsioon Poissonian Distribution Mean Poissoni jaotuse keskväärtus Poissonian Probability Mass Function Poissoni jaotuse suhteline sagedusfunktsioon Poissonian Distribution Variance Poissoni jaotuse dispersioon Convert to Phasor Complex Form Teisenda faasorkujule Convert to Rectangular Complex Form Teisenda ristkoordinaatkujule Round Half Away from Zero Ümarda pool nullist eemale Round Half Even Ümarda pool paarisarvuni Nth Root N-astme juur Convert to Scientific Notation Teisenda teaduslikuks esituseks Matrix Row Count Maatriksi ridade arv List or Matrix Shape Loendi või maatriksi kuju Summation Summeerimine Population Standard Deviation (n) Populatsiooni standardhälve (n) Sample Standard Deviation (n-1) Valimi standardhälve (n-1) Round Toward Zero (Truncation) Ümarda nulli suunas (kärpimine) Matrix Trace Maatriksi jälg Transpose Matrix Transponeeri maatriks Population Variance (n) Populatsiooni dispersioon (n) Sample Variance (n-1) Valimi dispersioon (n-1) Product Korrutis Radians Radiaanid Matrix Rank Maatriksi astak Real Part Reaalosa Secant Seekans Arithmetic Shift Left Väärtuse bitthaaval vasakule nihutamine Arithmetic Shift Right Väärtuse bitthaaval paremale nihutamine Signum Arvu märk Sine Siinus Hyperbolic Sine Hüperboolne siinus Square Root Ruutjuur Sum Summa Tangent Tangens Convert to Trigonometric Complex Form Teisenda trigonomeetrilisele komplekskujule Turns Täispöörded Hyperbolic Tangent Hüperboolne tangens Sign-extend a value Väärtuse märgilaiendus Logical XOR Loogiline VÄLISTAV VÕI FunctionsWidget Domain Valdkond All Kõik Name Nimetus Search Otsing No match found Vastet ei leitud Identifier Tähis HistoryWidget Remove All Calculations Above Eemalda kõik arvutused ülevalt Remove This Calculation Eemalda see arvutus Remove All Calculations Below Eemalda kõik arvutused alt Keypad Inverse cosine Arkuskoosinus The last result Eelmine tulemus Inverse sine Arkussiinus Inverse tangent Arkustangens Evaluate expression Arvuta avaldis Division Jagamine Multiplication Korrutamine Subtraction Lahutamine Addition Liitmine Clear expression Kustuta avaldis Cosine Koosinus Backspace Tagasilüke Scientific notation Teaduslik kirjaviis Exponential Eksponentfunktsioon Factorial Faktoriaal Natural logarithm Naturaallogaritm Left parenthesis Vasak sulg Nth root N-astme juur Argument separator Argumentide eraldaja Square Ruut Common logarithm Kümnendlogaritm Modulo Moodul Contextual percentage Kontekstipõhine protsent Power Aste Right parenthesis Parem sulg Sine Siinus Square root Ruutjuur Tangent Tangens Pi Pii Decimal separator Kümnenderaldaja MainWindow Radian Radiaanid Degree Kraadid Gradian Goonid Binary Kahendsüsteem Octal Kaheksandsüsteem Hexadecimal Kuueteistkümnendsüsteem Sexagesimal Kuuekümnendsüsteem Engineering decimal Insenerikujuline kümnendarv Scientific decimal Teaduslik kümnendarv &Import... &Impordi... &Quit &Välju Clear E&xpression Kustuta aval&dis Clear &History Kustuta a&jalugu &Copy &Kopeeri &Paste &Aseta &Select Expression &Vali avaldis &Constants K&onstandid &Functions &Funktsioonid &History &Ajalugu &Status Bar Oleku&riba Bitfield &Bitiväli Use&r Functions Ka&sutaja funktsioonid &Degree &Kraad &Radian &Radiaan &Gradian &Goon Re&volution &Pööre Auto-Insert a&ns Lisa a&ns automaatselt Automatic &Completion Automaatne &lõpetamine &Built-in Functions &Sisseehitatud funktsioonid Built-in &Variables S&isseehitatud muutujad User &Functions Kasutaja &funktsioonid User Va&riables &Kasutaja muutujad Open a Private Tab on Startup Ava käivitamisel privaatne kaart Open and focus a new private tab whenever SpeedCrunch starts. Ava ja aktiveeri uus privaatne kaart igal SpeedCrunchi käivitamisel. Syntax &Highlighting &Süntaksi esiletõstmine Group Digits in &Input Rühm&ita sisestatavad numbrid Automatic Input &Adjustments Sisendi &automaatne kohandamine Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Kohanda automaatselt tehtemärke, tühikuid, sulge ja astmeid ning luba sisestada ainult sobivaid märke. Group input digits using the selected number format. Rühmita sisestatud numbrid valitud arvuvormingu järgi. &Blinking Cursor &Vilkuv kursor Blink the cursor in the expression editor. Lase kursoril avaldiseredaktoris vilkuda. &Escape Clears Editor &Escape tühjendab redaktori Clear the focused expression editor with Escape after dismissing any popup or preview. Tühjenda aktiivne avaldiseredaktor Escape-klahviga pärast hüpikakende või eelvaadete sulgemist. Keep Expression After Evaluation Säilita avaldis pärast arvutamist Copy New Results Automatically Kopeeri uued tulemused automaatselt &Comma &Koma &System Default &Süsteemi vaikeväärtus &Dot &Punkt Dot &And Comma Punkt &ja koma Toward +∞ (&ceil) +∞ suunas (&ceil) Toward −∞ (&floor) −∞ suunas (&floor) &Binary &Kahendarvud &Engineering &Inseneriarvutused &Hexadecimal K&uueteistkümnendarvud &Octal K&aheksandarvud &Scientific &Teaduslik User &Manual &Käsiraamat Issues and &Feedback &Probleemid ja tagasiside &Donate A&nneta &About SpeedCrunch &SpeedCrunchi info App Diag&nostics &Rakenduse diagnostika S&plit &Poolita Angle &Mode &Nurgarežiim &Complex Form &Kompleksarvu kuju New Tab Uus kaart Constants Konstandid Functions Funktsioonid History Ajalugu User Functions Kasutaja funktsioonid &Font... &Font... &Language... Kee&l... &Session &Seanss &Edit &Redigeerimine &View &Vaade Se&ttings S&eadistused &Decimal Kümnen&darvud &Keypad &Klahvistik Always on &Top Alati &pealmine Disabled &Keelatud Small Space K&itsas tühik Medium Space Keskmine &tühik Large Space &Lai tühik &0 Digits &0 komakohta &15 Digits &15 komakohta &2 Digits &2 komakohta &3 Digits &3 komakohta &50 Digits &50 komakohta &8 Digits &8 komakohta &Sexagesimal Kuu&ekümnendarvud Reset All Settings... Lähtesta kõik sätted... &System &Süsteem SpeedCrunch &Theme SpeedCrunchi &teema &Classic &Klassikaline &Modern &Moodne Context Help Konteksti&abi &Help &Abi Error Viga Can't read from file %1 Failist "%1" pole võimalik lugeda Import Session Seansi importimine Close Session Sulge seanss Angle Mode: Nurgarežiim: Notation: Esitus: Precision: Täpsus: Turn Täispööre Revolution Pööre Fixed-point decimal Fikseeritud komakohtadega kümnendarv Rational Ratsionaalarv Automatic decimal Automaatne kümnendarv Automatic Automaatne User &Definitions... Kasutaja &definitsioonid... New &Tab Uus &kaart New &Private Tab &Uus privaatne kaart Keep Säilita Make Private... Muuda privaatseks... New &Window Uus &aken &Open... &Ava... &Rename... Nimeta ümbe&r... Clo&ne... Kloo&ni... &Close Tab &Sulge kaart Reopen Clo&sed Tab Ava su&letud kaart uuesti Open Sessions &Folder Ava seansside &kaust &Undo V&õta tagasi &Redo &Tee uuesti Cu&t &Lõika Copy &Last Result K&opeeri viimane tulemus &Wrap in Parentheses &Ümbritse sulgudega Full Scr&een Mode Täis&ekraanirežiim &Basic &Põhiline &Scientific (wide) &Teaduslik (lai) Scientific (narrow) Teaduslik (kitsas) &Custom... &Kohandatud... Main &Menu Pea&menüü User &Variables Kasutaja &muutujad &Left Vasaku&le &Right Pa&remale &Up &Üles &Down &Alla Close Pa&ne Sulge paa&n User &Units Kasutaja ü&hikud &Turn &Täispööre If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Kui uus avaldis algab märgiga +, -, * või /, lisab SpeedCrunch ette "ans". &Accept with Enter Ki&nnita Enteriga Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Kinnita praegune automaatse lõpetamise soovitus Enteriga, ilma seda esmalt nooleklahvidega valimata. &Units Ü&hikud Show Live Result &Preview Näita tulemuse reaalaja &eelvaadet Save &Window Position on Exit Salvesta väljumisel &akna asukoht Hover Highlighting Esiletõstmine hiire all Group Integer Part Only Rühmita ainult täisosa Number Format... Arvu vorming... Notation && Precision... Esitus ja täpsus... After pressing Enter, keep the entered expression selected in the editor. Pärast Enteri vajutamist jäta sisestatud avaldis redaktoris valituks. Never Mitte kunagi Always Alati Only for Single-Line Expressions Ainult üherealiste avaldiste korral Simplify Displayed Expressions Lihtsusta kuvatavaid avaldisi History Size &Limit... Ajaloo suuruse &piirang... Remove Trailing &Zeroes Ee&malda lõpunullid Nearest, Half &Away (round) Lähim, pool nullist &eemale (round) Nearest, Half &Even (roundeven) Lähim, pool &paarisarvuni (roundeven) Toward &Zero (trunc) &Nulli suunas (trunc) &Fixed-Point &Fikseeritud komakohtadega &Rational &Ratsionaalne &Exponential (m·s�¹) &Eksponentsiaalne (m·s�¹) &Fractional (m/s) &Murruna (m/s) &Rectangular (a + bi) &Ristkoordinaatne (a + bi) Exponential (re�ᶿ) Eksponentsiaalne (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonomeetriline (r(cos θ + i·sin θ)) Phasor (r∠θ) Faasor (r∠θ) &Theme... &Teema... Check for &Updates Kontrolli &uuendusi Source Code Lähtekood &Zoom &Suum &Results &Tulemused Unit Notation Ühikute esitus Rounding Mode Ümardamisrežiim &Notation &Esitus &Imaginary Unit &Imaginaarühik &Window &Aken &Editing &Muutmine A&utocomplete Automaat&täiendus Up/Down Arrow History Üles/alla noole ajalugu &Appearance &Välimus &Menus &Menüüd &Docks &Dokitavad paneelid &Input and Results S&isend ja tulemused &Disabled &Keelatud &Disable &Keela Close preview Sulge eelvaade Rename... Nimeta ümber... Clone... Klooni... Close Tab Sulge kaart New Private Tab Uus privaatne kaart Open... Ava... Reopen Closed Tab Ava suletud kaart uuesti Split Poolita Left Vasakule Right Paremale Up Üles Down Alla Clear Tühjenda Delete Kustuta %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Privaatne seanss: sisu hüljatakse sulgemisel. Vali Seanss > Säilita, et muuta see tavaliseks seansiks. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privaatne] Reset All Settings Lähtesta kõik sätted Reset all settings to their default values? Kas lähtestada kõik sätted vaikeväärtustele? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. See hõlmab välimust, redigeerimist, tulemuste vorminguid ja aknaeelistusi. Arvutused, avatud seansid ja kasutaja definitsioonid säilivad. The settings file could not be written. Sätete faili kirjutamine nurjus. Clear this session's calculations, unfinished expression, variables, functions, and units? Kas tühjendada selle seansi arvutused, lõpetamata avaldis, muutujad, funktsioonid ja ühikud? Global user definitions are kept. Globaalsed kasutaja definitsioonid säilivad. Make Session Private Muuda seanss privaatseks The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Salvestatud seanss %1 kustutatakse. Selle sisu jääb privaatses seansis avatuks ning hüljatakse selle seansi sulgemisel või SpeedCrunchist väljumisel. Make Private Muuda privaatseks Could not delete the saved session %1. Salvestatud seanssi %1 ei saanud kustutada. Keep Session Säilita seanss Could not save the session. It remains private. Seanssi ei saanud salvestada. See jääb privaatseks. Clone Session Klooni seanss Could not save session file %1. Seansifaili %1 ei saanud salvestada. Could not delete session file %1. Seansifaili %1 ei saanud kustutada. JSON file (*.json);;Any file (*.*) JSON-fail (*.json);;Kõik failid (*.*) Export session as JSON Seansi eksportimine JSON-ina The selected file is not valid JSON: %1 Valitud fail ei ole korrektne JSON: %1 The selected file is not a SpeedCrunch session JSON file. Valitud fail ei ole SpeedCrunchi seansi JSON-fail. This file uses an obsolete SpeedCrunch session format and cannot be imported. See fail kasutab vananenud SpeedCrunchi seansivormingut ja seda ei saa importida. The selected JSON file is missing the required $schema field. Valitud JSON-failist puudub nõutav väli $schema. The selected JSON file uses an unsupported JSON schema: %1 Valitud JSON-fail kasutab toetamata JSON-skeemi: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Valitud JSON-failist puudub SpeedCrunchi seansi skeemi identifikaator ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Valitud JSON-fail kasutab toetamata SpeedCrunchi seansivormingut: %1 The selected JSON file is missing the required session name. Valitud JSON-failist puudub nõutav seansi nimi. The selected JSON file has an empty session name. Valitud JSON-failis on tühi seansi nimi. The selected JSON file has invalid or incomplete SpeedCrunch session data. Valitud JSON-failis on vigased või mittetäielikud SpeedCrunchi seansiandmed. Open Sessions Folder Ava seansside kaust Could not create the sessions folder: %1 Seansside kausta ei saanud luua: %1 Could not open the sessions folder: %1 Seansside kausta ei saanud avada: %1 Editor and Results Font Redaktori ja tulemuste font Open Session Ava seanss Community Kogukond Rename Session Nimeta seanss ümber Clear Session Tühjenda seanss Delete Session Kustuta seanss Close Pane Sulge paan User Variables Kasutaja muutujad User Units Kasutaja ühikud Clear History Tühjenda ajalugu Are you sure you want to clear the calculation history? Kas soovid kindlasti arvutusajaloo tühjendada? Session name: Seansi nimi: A session named %1 already exists. Seanss nimega %1 on juba olemas. Could not create session file %1. Seansifaili %1 ei saanud luua. Could not write session file %1. Seansifaili %1 ei saanud kirjutada. Are you sure you want to delete this session? Kas soovid kindlasti selle seansi kustutada? Custom Precision Kohandatud täpsus Fractional digits: Murdosa numbrid: Theme Teema Light Themes Heledad teemad Dark Themes Tumedad teemad Preview Eelvaade Colors Värvid Select color for %1 Vali %1 värv Import... Impordi... Export... Ekspordi... Import Theme Impordi teema Theme file (*.json);;All files (*) Teemafail (*.json);;Kõik failid (*) Invalid theme file. Vigane teemafail. Can't import theme "%1" because it conflicts with a built-in theme. Teemat "%1" ei saa importida, sest see läheb vastuollu sisseehitatud teemaga. Can't find a writable theme folder. Kirjutatavat teemakausta ei leitud. Overwrite Theme Kirjuta teema üle A custom theme named "%1" already exists. Do you want to overwrite it? Kohandatud teema nimega "%1" on juba olemas. Kas soovid selle üle kirjutada? Can't overwrite theme file %1 Teemafaili %1 ei saa üle kirjutada Can't copy theme file to %1 Teemafaili ei saa kopeerida asukohta %1 Export Theme Ekspordi teema Can't export theme as "%1" because it conflicts with a built-in theme. Teemat ei saa eksportida nimega "%1", sest see läheb vastuollu sisseehitatud teemaga. Can't write to file %1 Faili "%1" pole võimalik kirjutada Global User Variable Globaalne kasutaja muutuja Global User Function Globaalne kasutaja funktsioon Global User Unit Globaalne kasutaja ühik User Definitions Kasutaja definitsioonid These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Need definitsioonid on globaalsed ja laaditakse igasse seanssi. Neid ei saa seanssides muuta ja need on seansiredaktori samanimeliste definitsioonide suhtes ülimuslikud. Sisesta igale reale üks definitsioon. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Näited: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Rakenda Validate Kontrolli Test Results Testi tulemused Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Imporditud muutujad: %1 Imporditud funktsioonid: %2 Imporditud ühikud: %3 Vigadega ridade numbrid: %4 none puuduvad Apply Results Rakendamise tulemused User definitions saved. Kasutaja definitsioonid salvestatud. History Size Limit Ajaloo suuruse piirang Maximum number of history entries for this session (0 = unlimited): Selle seansi ajalookirjete maksimaalne arv (0 = piiramatu): Text file (*.txt);;Any file (*.*) Tekstifail (*.txt);;Suvaline fail (*.*) Could not recalculate from calculation %1: %2 Arvutust %1 ei saanud ümber arvutada: %2 History Size Limit Reached Ajaloo suuruse piirang saavutatud This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. See arvutus täidab viimase vaba ajalookoha. Järgmised arvutused eemaldavad ajaloost vanima arvutuse. Piirangut saab suurendada menüüst Seanss > Ajaloo suuruse piirang. Editing calculation. Press Esc twice to cancel. Arvutuse muutmine. Tühistamiseks vajuta kaks korda Esc. Calculation Settings Arvutuse sätted Invalid recalculation start index Vigane ümberarvutuse algusindeks System Default Süsteemi vaikeväärtus Language Keel Select the language: Vali keel: Custom Kohandatud Decimal places: Kümnendkohad: &Automatic &Automaatne &Precision Tä&psus Plain &text &Lihttekst Formula &Book &Valemivihik &Export &Eksportimine Export session as HTML Seansi eksportimine HTML-ina HTML file (*.html) HTML-fail (*.html) Export session as plain text Seansi eksportimine lihttekstina ManualWindow SpeedCrunch Manual SpeedCrunchi käsiraamat %1 - SpeedCrunch Manual %1 - SpeedCrunchi käsiraamat NumberFormatDialog Number Format Arvu vorming <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Vali arvuvorming tulemuste ja sisestatud numbrite rühmitamise jaoks.</b><br/><br/>Märkus: sisestatud arvude üheselt mõistetavad vormingud on lubatud ka siis, kui need erinevad valitud kuvavormingust.<br/> QObject Global User Variable Globaalne kasutaja muutuja Global User Function Globaalne kasutaja funktsioon Global User Unit Globaalne kasutaja ühik Backspace Tagasilüke Clear expression Tühjenda avaldis Evaluate expression Arvuta avaldis Insert text Sisesta tekst Automatic decimal Automaatne kümnendarv Fixed-point decimal Fikseeritud komakohtadega kümnendarv Engineering decimal Insenerikujuline kümnendarv Scientific decimal Teaduslik kümnendarv Rational Ratsionaalarv Binary Kahendsüsteem Octal Kaheksandsüsteem Hexadecimal Kuueteistkümnendsüsteem Sexagesimal Kuuekümnendsüsteem Update Available Uuendus on saadaval A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Saadaval on uuem versioon (%1).<br/><a href="%2">Allalaadimiseks ava veebisait.</a> Check for Updates Kontrolli uuendusi SpeedCrunch %1 is up to date. SpeedCrunch %1 on ajakohane. No connectivity. Please check your internet connection and try again. Ühendus puudub. Kontrolli internetiühendust ja proovi uuesti. Could not verify the latest available version. Uusimat saadaolevat versiooni ei saanud kontrollida. ResultDisplay Scroll to bottom Keri lõppu Edit Expression Muuda avaldist Change Settings Muuda sätteid New Tab Uus kaart &Import... &Impordi... &Export &Ekspordi Plain &text &Lihttekst Copy Kopeeri Selection Valik Select All Vali kõik Expression Avaldis Result Tulemus Calculation Arvutus Calculation as Single Line Arvutus ühel real Remove Eemalda This Calculation See arvutus All Calculations Above Kõik ülalpool olevad arvutused All Calculations Below Kõik allpool olevad arvutused New Private Tab Uus privaatne kaart Session Seanss Open... Ava... Clone... Klooni... Rename... Nimeta ümber... Keep Säilita Make Private... Muuda privaatseks... Clear Tühjenda Delete Kustuta Close Sulge Split Poolita Left Vasakule Right Paremale Up Üles Down Alla Close Pane Sulge paan Main Menu Peamenüü Cancel editing Tühista muutmine Copy result Kopeeri tulemus Edit expression Muuda avaldist Change settings Muuda sätteid Remove calculation Eemalda arvutus ResultSlotsDialog Notation & Precision Esitus ja täpsus Result Line Tulemuse rida Enabled Lubatud Notation Esitus Decimal Places Kümnendkohad Main Line Põhirida Extra Line #1 Lisarea #1 Extra Line #2 Lisarea #2 Extra Line #3 Lisarea #3 Extra Line #4 Lisarea #4 Auto Automaatne UserFunctionListWidget Name Nimetus Value Väärtus Description Kirjeldus Search Otsing No match found Vastet ei leitud Insert Sisesta Edit Muuda Delete Kustuta Delete All Kustuta kõik UserUnitListWidget Name Nimi Value Väärtus Description Kirjeldus Search Otsing No match found Vastet ei leitud Insert Sisesta Edit Muuda Delete Kustuta Delete All Kustuta kõik VariableListWidget Name Nimetus Value Väärtus Description Kirjeldus Search Otsing No match found Vastet ei leitud Insert Sisesta Edit Muuda Delete Kustuta Delete All Kustuta kõik heldercorreia-speedcrunch-e7ca37f/src/resources/locale/eu.ts000066400000000000000000010541521526573132500243660ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunch-i buruz Core developers Garatzaile nagusiak Original author Jatorrizko egilea Close Itxi Math engine Matematika-motorra Main author | Logo | Maintainer Egile nagusia | Logotipoa | Mantentzailea Thanks Eskerrak Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 SpeedCrunch garatzaileak This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Programa hau software askea da; Free Software Foundation-ek argitaratutako GNU Lizentzia Publiko Orokorraren baldintzen arabera birbanatu eta/edo aldatu dezakezu, lizentziaren 2. bertsioaren edo (zure aukeran) ondorengo edozein bertsioren arabera This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Programa hau erabilgarria izango delakoan banatzen da, baina INOLAKO BERMERIK GABE; ezta MERKATURATZEKO edo HELBURU JAKIN BATERAKO EGOKITASUNAREN bermerik ere. Ikusi GNU Lizentzia Publiko Orokorra xehetasun gehiagorako. BitFieldWidget Reset bits to zero Berrezarri bitak zerora Invert bits Alderantzikatu bitak Shift bits left Lerratu bitak ezkerrera Shift bits right Lerratu bitak eskuinera Book Index Aurkibidea Algebra Aljebra Quadratic Equation Bigarren mailako ekuazioa Logarithmic Base Conversion Logaritmoaren oinarri-bihurketa Geometry Geometria Circle Zirkulua Sector Sektorea Sphere Esfera Cube Kuboa Cone Konoa Cylinder Zilindroa Electronics Elektronika Ohm's Law Ohmen legea Power Potentzia Reactance Erreaktantzia Resonance Erresonantzia Radio Frequency Irrati-maiztasuna Antennas Antenak Characteristic Impedance (coax) Inpedantzia karakteristikoa (koaxiala) Velocity of Propagation (coax) Hedapen-abiadura (koaxiala) Standing Wave Ratio & Return Loss Uhin geldikorraren erlazioa eta itzulera-galera Free Space Wavelength Espazio libreko uhin-luzera resistance erresistentzia voltage tentsioa current korrontea power potentzia inductive reactance erreaktantzia induktiboa capacitive reactance erreaktantzia kapazitiboa inductance induktantzia capacitance kapazitantzia frequency maiztasuna resonance frequency erresonantzia-maiztasuna area azalera perimeter perimetroa diameter diametroa radius erradioa volume bolumena surface area gainazal-azalera height altuera slant height altuera inklinatua face diagonal aurpegiaren diagonala space diagonal espazio-diagonala edge length ertzaren luzera arc length arkuaren luzera central angle (degrees) erdiko angelua (graduak) input power sarrerako potentzia reflected power islatutako potentzia transmitted power transmititutako potentzia return loss itzulera-galera dielectric constant konstante dielektrikoa outer conductor's inner diameter kanpoko eroalearen barne-diametroa inner conductor's outer diameter barneko eroalearen kanpo-diametroa speed of light argiaren abiadura reflection coefficient islatze-koefizientea standing wave ratio uhin geldikorraren erlazioa normalized impedance inpedantzia normalizatua frequency (Hz) maiztasuna (Hz) BookDock Formula Book Formula-liburua ConstantCompletion Search constants Bilatu konstanteak No match found Ez da bat datorrenik aurkitu Constants Mathematics Matematika Physics (CODATA 2022) Fisika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kimika (IUPAC - CIAAW 2021) Uncategorized Kategoriarik gabe Universal Unibertsala Physicochemical Fisiko-kimikoa Atomic & Nuclear — General Atomikoa eta nuklearra — Orokorra Atomic & Nuclear — Electroweak Atomikoa eta nuklearra — Elektroahula Atomic & Nuclear — Electron Atomikoa eta nuklearra — Elektroia Atomic & Nuclear — Muon Atomikoa eta nuklearra — Muoia Atomic & Nuclear — Tau Atomikoa eta nuklearra — Tau Atomic & Nuclear — Proton Atomikoa eta nuklearra — Protoia Atomic & Nuclear — Neutron Atomikoa eta nuklearra — Neutroia Atomic & Nuclear — Deuteron Atomikoa eta nuklearra — Deuteroia Atomic & Nuclear — Triton Atomikoa eta nuklearra — Tritoia Atomic & Nuclear — Helion Atomikoa eta nuklearra — Helioia Atomic & Nuclear — Alpha particle Atomikoa eta nuklearra — Alfa partikula Atomic & Nuclear — Atomic units Atomikoa eta nuklearra — Unitate atomikoak Atomic & Nuclear — Energy conversion relationships Atomikoa eta nuklearra — Energia-bihurketako erlazioak Atomic & Nuclear — X-ray units Atomikoa eta nuklearra — X izpien unitateak Atomic & Nuclear — Magnetic shielding corrections Atomikoa eta nuklearra — Babes magnetikoaren zuzenketak Masses Masak Lifetimes Bizitza-denborak Molar Masses Masa molarrak Electronegativity Elektronegatibitatea Ionization Energy Ionizazio-energia Nominal Constants (IAU 2015) Konstante nominalak (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Uneko estimazio onenak (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) hutsaren inpedantzia karakteristikoa (Z₀) reduced Planck constant (�) Plancken konstante murriztua (�) vacuum electric permittivity (ϵ₀) hutsaren permitibitate elektrikoa (ϵ₀) Newtonian constant of gravitation (G) grabitatearen konstante newtoniarra (G) vacuum magnetic permeability (μ₀) hutsaren iragazkortasun magnetikoa (μ₀) Planck constant (h) Plancken konstantea (h) speed of light in vacuum (c) argiaren abiadura hutsean (c) standard acceleration of gravity (gₙ) grabitatearen azelerazio estandarra (gₙ) Newtonian constant of gravitation over h-bar c grabitatearen konstante newtoniarra h-bar c-ren gainean Planck length Plancken luzera Planck constant in eV/Hz (h) Plancken konstantea eV/Hz-tan (h) Planck mass Plancken masa Planck mass energy equivalent in GeV Plancken masaren energia-baliokidea GeV-tan Planck temperature Plancken tenperatura Planck time Plancken denbora reduced Planck constant in eV·s (�) Plancken konstante murriztua eV·s-tan (�) reduced Planck constant times c in MeV·fm Plancken konstante murriztua bider c MeV·fm-tan Bohr magneton Bohr magnetoia conductance quantum (G₀) konduktantzia-kuantua (G₀) Coulomb constant (kₑ) Coulomben konstantea (kₑ) elementary charge (e) oinarrizko karga (e) elementary charge over h-bar oinarrizko karga h-bar-ren gainean conventional value of Josephson constant Josephsonen konstantearen balio konbentzionala Josephson constant Josephsonen konstantea conventional value of ampere-90 ampere-90ren balio konbentzionala conventional value of coulomb-90 coulomb-90ren balio konbentzionala conventional value of farad-90 farad-90ren balio konbentzionala conventional value of henry-90 henry-90ren balio konbentzionala conventional value of ohm-90 ohm-90ren balio konbentzionala conventional value of volt-90 volt-90ren balio konbentzionala conventional value of watt-90 watt-90ren balio konbentzionala magnetic flux quantum (Φ₀) fluxu magnetikoaren kuantua (Φ₀) nuclear magneton magnetoi nuklearra inverse of conductance quantum konduktantzia-kuantuaren alderantzizkoa conventional value of von Klitzing constant von Klitzingen konstantearen balio konbentzionala von Klitzing constant von Klitzingen konstantea atomic unit of magnetic dipole moment dipolo magnetikoaren momentuaren unitate atomikoa atomic unit of magnetic flux density fluxu magnetikoaren dentsitatearen unitate atomikoa Bohr magneton in eV/T Bohr magnetoia eV/T-tan Bohr magneton in Hz/T Bohr magnetoia Hz/T-tan Bohr magneton in inverse meter per tesla Bohr magnetoia alderantzizko metro teslakoetan Bohr magneton in K/T Bohr magnetoia K/T-tan nuclear magneton in eV/T magnetoi nuklearra eV/T-tan nuclear magneton in inverse meter per tesla magnetoi nuklearra alderantzizko metro teslakoetan nuclear magneton in K/T magnetoi nuklearra K/T-tan nuclear magneton in MHz/T magnetoi nuklearra MHz/T-tan Bohr radius (a₀) Bohr-en erradioa (a₀) fine-structure constant (α) egitura finaren konstantea (α) Hartree energy (Eₕ) Hartree energia (Eₕ) Hartree energy in eV Hartree energia eV-tan quantum of circulation zirkulazio-kuantua quantum of circulation times 2 zirkulazio-kuantua bider 2 Rydberg constant (R∞) Rydbergen konstantea (R∞) atomic mass unit-hartree relationship masa atomikoaren unitatea-hartree erlazioa atomic mass unit-hertz relationship masa atomikoaren unitatea-hertz erlazioa atomic mass unit-inverse meter relationship masa atomikoaren unitatea-alderantzizko metroa erlazioa atomic mass unit-joule relationship masa atomikoaren unitatea-joule erlazioa atomic mass unit-kelvin relationship masa atomikoaren unitatea-kelvin erlazioa atomic mass unit-kilogram relationship masa atomikoaren unitatea-kilogramo erlazioa atomic unit of 1st hyperpolarizability 1st hyperpolarizabilityren unitate atomikoa atomic unit of 2nd hyperpolarizability 2nd hyperpolarizabilityren unitate atomikoa atomic unit of charge (e) karga (e)ren unitate atomikoa atomic unit of charge density karga-dentsitatearen unitate atomikoa atomic unit of current korrontearen unitate atomikoa atomic unit of electric dipole moment dipolo elektrikoaren momentuaren unitate atomikoa atomic unit of electric field eremu elektrikoaren unitate atomikoa atomic unit of electric field gradient eremu elektrikoaren gradientearen unitate atomikoa atomic unit of electric polarizability polarizagarritasun elektrikoaren unitate atomikoa atomic unit of electric potential potentzial elektrikoaren unitate atomikoa atomic unit of electric quadrupole moment kuadrupolo elektrikoaren momentuaren unitate atomikoa atomic unit of action akzioaren unitate atomikoa atomic unit of energy energiaren unitate atomikoa atomic unit of force indarraren unitate atomikoa atomic unit of length luzeraren unitate atomikoa hertz-atomic mass unit relationship hertz-masa atomikoaren unitatea erlazioa hertz-electron volt relationship hertz-elektronvolta erlazioa hertz-hartree relationship hertz-hartree erlazioa hertz-inverse meter relationship hertz-alderantzizko metroa erlazioa hertz-joule relationship hertz-joule erlazioa hertz-kelvin relationship hertz-kelvin erlazioa hertz-kilogram relationship hertz-kilogramo erlazioa hyperfine transition frequency of Cs-133 Cs-133ren trantsizio hiperfinaren maiztasuna inverse fine-structure constant (α�¹) egitura finaren konstantearen alderantzizkoa (α�¹) inverse meter-atomic mass unit relationship alderantzizko metroa-masa atomikoaren unitatea erlazioa inverse meter-electron volt relationship alderantzizko metroa-elektronvolta erlazioa inverse meter-hartree relationship alderantzizko metroa-hartree erlazioa inverse meter-hertz relationship alderantzizko metroa-hertz erlazioa inverse meter-joule relationship alderantzizko metroa-joule erlazioa inverse meter-kelvin relationship alderantzizko metroa-kelvin erlazioa inverse meter-kilogram relationship alderantzizko metroa-kilogramo erlazioa joule-atomic mass unit relationship joule-masa atomikoaren unitatea erlazioa joule-electron volt relationship joule-elektronvolta erlazioa joule-hertz relationship joule-hertz erlazioa joule-hartree relationship joule-hartree erlazioa joule-inverse meter relationship joule-alderantzizko metroa erlazioa joule-kelvin relationship joule-kelvin erlazioa joule-kilogram relationship joule-kilogramo erlazioa kelvin-atomic mass unit relationship kelvin-masa atomikoaren unitatea erlazioa kelvin-electron volt relationship kelvin-elektronvolta erlazioa kelvin-hertz relationship kelvin-hertz erlazioa kelvin-hartree relationship kelvin-hartree erlazioa kelvin-inverse meter relationship kelvin-alderantzizko metroa erlazioa kelvin-joule relationship kelvin-joule erlazioa kelvin-kilogram relationship kelvin-kilogramo erlazioa kilogram-atomic mass unit relationship kilogramo-masa atomikoaren unitatea erlazioa kilogram-electron volt relationship kilogramo-elektronvolta erlazioa kilogram-hertz relationship kilogramo-hertz erlazioa kilogram-hartree relationship kilogramo-hartree erlazioa kilogram-inverse meter relationship kilogramo-alderantzizko metroa erlazioa kilogram-joule relationship kilogramo-joule erlazioa kilogram-kelvin relationship kilogramo-kelvin erlazioa lattice parameter of silicon (a) silizioaren sare-parametroa (a) luminous efficacy argi-eraginkortasuna natural unit of energy energiaren unitate naturala natural unit of energy in MeV energiaren unitate naturala MeV-tan natural unit of action (�) akzioa (�)ren unitate naturala natural unit of action in eV·s akzioaren unitate naturala eV·s-tan natural unit of length luzeraren unitate naturala natural unit of mass masaren unitate naturala natural unit of momentum momentuaren unitate naturala natural unit of momentum in MeV/c momentuaren unitate naturala MeV/c-tan natural unit of time denboraren unitate naturala natural unit of velocity abiaduraren unitate naturala Rydberg constant times c in Hz Rydbergen konstantea bider c Hz-tan Rydberg constant times hc in eV Rydbergen konstantea bider hc eV-tan Rydberg constant times hc in J Rydbergen konstantea bider hc J-tan Fermi coupling constant Fermiren akoplamendu-konstantea weak mixing angle nahasketa ahularen angelua W to Z mass ratio W eta Z masen arteko erlazioa Thomson cross section (σₑ) Thomsonen sekzio eraginkorra (σₑ) electron mass (mₑ) elektroiaren masa (mₑ) electron mass in u elektroiaren masa u-tan electron mass energy equivalent (mₑ·c²) elektroiaren masaren energia-baliokidea (mₑ·c²) electron mass energy equivalent in MeV elektroiaren masaren energia-baliokidea MeV-tan reduced Compton wavelength Comptonen uhin-luzera murriztua classical electron radius (rₑ) elektroiaren erradio klasikoa (rₑ) electron charge to mass quotient elektroiaren karga/masa zatidura electron-deuteron magnetic moment ratio elektroi-deuteroi momentu magnetikoaren erlazioa electron-deuteron mass ratio elektroi-deuteroi masa-erlazioa electron g factor (gₑ) elektroiaren g faktorea (gₑ) electron gyromagnetic ratio (γₑ) elektroiaren erlazio giromagnetikoa (γₑ) electron gyromagnetic ratio in MHz/T elektroiaren erlazio giromagnetikoa MHz/T-tan electron-helion mass ratio elektroi-helioi masa-erlazioa electron magnetic moment (μₑ) elektroiaren momentu magnetikoa (μₑ) electron magnetic moment anomaly (aₑ) elektroiaren momentu magnetikoaren anomalia (aₑ) electron magnetic moment to Bohr magneton ratio elektroiaren momentu magnetikoa / Bohr magnetoia erlazioa electron magnetic moment to nuclear magneton ratio elektroiaren momentu magnetikoa / magnetoi nuklearra erlazioa electron molar mass (Mₑ) elektroiaren masa molarra (Mₑ) electron-muon magnetic moment ratio elektroi-muoi momentu magnetikoaren erlazioa electron-muon mass ratio elektroi-muoi masa-erlazioa electron-neutron magnetic moment ratio elektroi-neutroi momentu magnetikoaren erlazioa electron-neutron mass ratio elektroi-neutroi masa-erlazioa electron-proton magnetic moment ratio elektroi-protoi momentu magnetikoaren erlazioa electron-proton mass ratio elektroi-protoi masa-erlazioa electron relative atomic mass (Ar(e)) elektroiaren masa atomiko erlatiboa (Ar(e)) electron-tau mass ratio elektroi-tau masa-erlazioa electron to alpha particle mass ratio elektroia / alfa partikula masa-erlazioa electron to shielded helion magnetic moment ratio elektroia / blindatutako helioia momentu magnetikoaren erlazioa electron to shielded proton magnetic moment ratio elektroia / blindatutako protoia momentu magnetikoaren erlazioa electron-triton mass ratio elektroi-tritoi masa-erlazioa electron volt-atomic mass unit relationship elektronvolta-masa atomikoaren unitatea erlazioa electron volt-hartree relationship elektronvolta-hartree erlazioa electron volt-hertz relationship elektronvolta-hertz erlazioa electron volt-inverse meter relationship elektronvolta-alderantzizko metroa erlazioa electron volt-joule relationship elektronvolta-joule erlazioa electron volt-kelvin relationship elektronvolta-kelvin erlazioa electron volt-kilogram relationship elektronvolta-kilogramo erlazioa hartree-atomic mass unit relationship hartree-masa atomikoaren unitatea erlazioa hartree-electron volt relationship hartree-elektronvolta erlazioa muon Compton wavelength muoiaren Comptonen uhin-luzera muon-electron mass ratio muoi-elektroi masa-erlazioa muon g factor muoiaren g faktorea muon magnetic moment muoiaren momentu magnetikoa muon magnetic moment anomaly muoiaren momentu magnetikoaren anomalia muon magnetic moment to Bohr magneton ratio muoiaren momentu magnetikoa / Bohr magnetoia erlazioa muon magnetic moment to nuclear magneton ratio muoiaren momentu magnetikoa / magnetoi nuklearra erlazioa muon mass muoiaren masa muon mass energy equivalent muoiaren masaren energia-baliokidea muon mass energy equivalent in MeV muoiaren masaren energia-baliokidea MeV-tan muon mass in u muoiaren masa u-tan muon molar mass muoiaren masa molarra muon-neutron mass ratio muoi-neutroi masa-erlazioa muon-proton magnetic moment ratio muoi-protoi momentu magnetikoaren erlazioa muon-proton mass ratio muoi-protoi masa-erlazioa muon-tau mass ratio muoi-tau masa-erlazioa reduced muon Compton wavelength muoiaren Comptonen uhin-luzera murriztua reduced tau Compton wavelength tauaren Comptonen uhin-luzera murriztua tau Compton wavelength tauaren Comptonen uhin-luzera tau-electron mass ratio tau-elektroi masa-erlazioa tau mass tauaren masa tau mass energy equivalent tauaren masaren energia-baliokidea tau mass in u tauaren masa u-tan tau molar mass tauaren masa molarra tau-muon mass ratio tau-muoi masa-erlazioa tau-neutron mass ratio tau-neutroi masa-erlazioa tau-proton mass ratio tau-protoi masa-erlazioa proton charge to mass quotient protoiaren karga/masa zatidura proton Compton wavelength protoiaren Comptonen uhin-luzera proton-electron mass ratio protoi-elektroi masa-erlazioa proton g factor (gₚ) protoiaren g faktorea (gₚ) proton gyromagnetic ratio (γₚ) protoiaren erlazio giromagnetikoa (γₚ) proton gyromagnetic ratio in MHz/T protoiaren erlazio giromagnetikoa MHz/T-tan proton magnetic moment (μₚ) protoiaren momentu magnetikoa (μₚ) proton magnetic moment to Bohr magneton ratio protoiaren momentu magnetikoa / Bohr magnetoia erlazioa proton magnetic moment to nuclear magneton ratio protoiaren momentu magnetikoa / magnetoi nuklearra erlazioa proton magnetic shielding correction protoia blindaje magnetikoaren zuzenketa proton mass (mₚ) protoiaren masa (mₚ) proton mass energy equivalent protoiaren masaren energia-baliokidea proton mass energy equivalent in MeV protoiaren masaren energia-baliokidea MeV-tan proton mass in u protoiaren masa u-tan proton molar mass (Mₚ) protoiaren masa molarra (Mₚ) proton-muon mass ratio protoi-muoi masa-erlazioa proton-neutron magnetic moment ratio protoi-neutroi momentu magnetikoaren erlazioa proton-neutron mass ratio protoi-neutroi masa-erlazioa proton relative atomic mass (Ar(p)) protoiaren masa atomiko erlatiboa (Ar(p)) proton rms charge radius protoiaren rms karga-erradioa proton-tau mass ratio protoi-tau masa-erlazioa reduced proton Compton wavelength protoiaren Comptonen uhin-luzera murriztua shielded proton gyromagnetic ratio blindatutako protoia erlazio giromagnetikoa shielded proton gyromagnetic ratio in MHz/T blindatutako protoia erlazio giromagnetikoa MHz/T-tan shielded proton magnetic moment blindatutako protoia momentu magnetikoa shielded proton magnetic moment to Bohr magneton ratio blindatutako protoia momentu magnetikoa / Bohr magnetoia erlazioa shielded proton magnetic moment to nuclear magneton ratio blindatutako protoia momentu magnetikoa / magnetoi nuklearra erlazioa neutron Compton wavelength neutroiaren Comptonen uhin-luzera neutron-electron magnetic moment ratio neutroi-elektroi momentu magnetikoaren erlazioa neutron-electron mass ratio neutroi-elektroi masa-erlazioa neutron g factor (gₙ) neutroiaren g faktorea (gₙ) neutron gyromagnetic ratio (γₙ) neutroiaren erlazio giromagnetikoa (γₙ) neutron gyromagnetic ratio in MHz/T neutroiaren erlazio giromagnetikoa MHz/T-tan neutron magnetic moment (μₙ) neutroiaren momentu magnetikoa (μₙ) neutron magnetic moment to Bohr magneton ratio neutroiaren momentu magnetikoa / Bohr magnetoia erlazioa neutron magnetic moment to nuclear magneton ratio neutroiaren momentu magnetikoa / magnetoi nuklearra erlazioa neutron mass (mₙ) neutroiaren masa (mₙ) neutron mass energy equivalent neutroiaren masaren energia-baliokidea neutron mass energy equivalent in MeV neutroiaren masaren energia-baliokidea MeV-tan neutron mass in u neutroiaren masa u-tan neutron molar mass (Mₙ) neutroiaren masa molarra (Mₙ) neutron-muon mass ratio neutroi-muoi masa-erlazioa neutron-proton magnetic moment ratio neutroi-protoi momentu magnetikoaren erlazioa neutron-proton mass difference neutroiaren eta protoiaren masa-diferentzia neutron-proton mass difference energy equivalent neutroiaren eta protoiaren masa-diferentziaren energia-baliokidea neutron-proton mass difference energy equivalent in MeV neutroiaren eta protoiaren masa-diferentziaren energia-baliokidea MeV-tan neutron-proton mass difference in u neutroiaren eta protoiaren masa-diferentzia u-tan neutron-proton mass ratio neutroi-protoi masa-erlazioa neutron relative atomic mass (Ar(n)) neutroiaren masa atomiko erlatiboa (Ar(n)) neutron-tau mass ratio neutroi-tau masa-erlazioa neutron to shielded proton magnetic moment ratio neutroia / blindatutako protoia momentu magnetikoaren erlazioa reduced neutron Compton wavelength neutroiaren Comptonen uhin-luzera murriztua deuteron-electron magnetic moment ratio deuteroi-elektroi momentu magnetikoaren erlazioa deuteron-electron mass ratio deuteroi-elektroi masa-erlazioa deuteron g factor deuteroiaren g faktorea deuteron magnetic moment deuteroiaren momentu magnetikoa deuteron magnetic moment to Bohr magneton ratio deuteroiaren momentu magnetikoa / Bohr magnetoia erlazioa deuteron magnetic moment to nuclear magneton ratio deuteroiaren momentu magnetikoa / magnetoi nuklearra erlazioa deuteron mass deuteroiaren masa deuteron mass energy equivalent deuteroiaren masaren energia-baliokidea deuteron mass energy equivalent in MeV deuteroiaren masaren energia-baliokidea MeV-tan deuteron mass in u deuteroiaren masa u-tan deuteron molar mass deuteroiaren masa molarra deuteron-neutron magnetic moment ratio deuteroi-neutroi momentu magnetikoaren erlazioa deuteron-proton magnetic moment ratio deuteroi-protoi momentu magnetikoaren erlazioa deuteron-proton mass ratio deuteroi-protoi masa-erlazioa deuteron relative atomic mass (Ar(d)) deuteroiaren masa atomiko erlatiboa (Ar(d)) deuteron rms charge radius deuteroiaren rms karga-erradioa triton-electron mass ratio tritoi-elektroi masa-erlazioa triton g factor (gₜ) tritoiaren g faktorea (gₜ) triton magnetic moment (μₜ) tritoiaren momentu magnetikoa (μₜ) triton magnetic moment to Bohr magneton ratio tritoiaren momentu magnetikoa / Bohr magnetoia erlazioa triton magnetic moment to nuclear magneton ratio tritoiaren momentu magnetikoa / magnetoi nuklearra erlazioa triton mass (mₜ) tritoiaren masa (mₜ) triton mass energy equivalent tritoiaren masaren energia-baliokidea triton mass energy equivalent in MeV tritoiaren masaren energia-baliokidea MeV-tan triton mass in u tritoiaren masa u-tan triton molar mass (Mₜ) tritoiaren masa molarra (Mₜ) triton-proton mass ratio tritoi-protoi masa-erlazioa triton relative atomic mass (Ar(t)) tritoiaren masa atomiko erlatiboa (Ar(t)) triton to proton magnetic moment ratio tritoia / protoia momentu magnetikoaren erlazioa helion-electron mass ratio helioi-elektroi masa-erlazioa helion g factor (gₕ) helioiaren g faktorea (gₕ) helion magnetic moment (μₕ) helioiaren momentu magnetikoa (μₕ) helion magnetic moment to Bohr magneton ratio helioiaren momentu magnetikoa / Bohr magnetoia erlazioa helion magnetic moment to nuclear magneton ratio helioiaren momentu magnetikoa / magnetoi nuklearra erlazioa helion mass (mₕ) helioiaren masa (mₕ) helion mass energy equivalent helioiaren masaren energia-baliokidea helion mass energy equivalent in MeV helioiaren masaren energia-baliokidea MeV-tan helion mass in u helioiaren masa u-tan helion molar mass (Mₕ) helioiaren masa molarra (Mₕ) helion-proton mass ratio helioi-protoi masa-erlazioa helion relative atomic mass (Ar(h)) helioiaren masa atomiko erlatiboa (Ar(h)) helion shielding shift helioia blindaje-desplazamendua shielded helion gyromagnetic ratio blindatutako helioia erlazio giromagnetikoa shielded helion gyromagnetic ratio in MHz/T blindatutako helioia erlazio giromagnetikoa MHz/T-tan shielded helion magnetic moment blindatutako helioia momentu magnetikoa shielded helion magnetic moment to Bohr magneton ratio blindatutako helioia momentu magnetikoa / Bohr magnetoia erlazioa shielded helion magnetic moment to nuclear magneton ratio blindatutako helioia momentu magnetikoa / magnetoi nuklearra erlazioa shielded helion to proton magnetic moment ratio blindatutako helioia / protoia momentu magnetikoaren erlazioa shielded helion to shielded proton magnetic moment ratio blindatutako helioia / blindatutako protoia momentu magnetikoaren erlazioa alpha particle mass alfa partikularen masa alpha particle mass in u alfa partikularen masa u-tan alpha particle mass energy equivalent alfa partikularen masaren energia-baliokidea alpha particle mass energy equivalent in MeV alfa partikularen masaren energia-baliokidea MeV-tan alpha particle-electron mass ratio alfa partikula-elektroi masa-erlazioa alpha particle-proton mass ratio alfa partikula-protoi masa-erlazioa alpha particle rms charge radius alfa partikularen rms karga-erradioa alpha particle molar mass alfa partikularen masa molarra alpha particle relative atomic mass (Ar(α)) alfa partikularen masa atomiko erlatiboa (Ar(α)) atomic mass constant (mᵤ) masa atomikoaren konstantea (mᵤ) Avogadro constant Avogadroren konstantea Boltzmann constant (k) Boltzmannen konstantea (k) Boltzmann constant in eV/K Boltzmannen konstantea eV/K-tan Boltzmann constant in Hz/K Boltzmannen konstantea Hz/K-tan Boltzmann constant in inverse meter per kelvin Boltzmannen konstantea alderantzizko metro kelvinekoetan electron volt (eV) elektronvolta (eV) Faraday constant (F) Faradayren konstantea (F) first radiation constant (c�) lehen erradiazio-konstantea (c�) first radiation constant for spectral radiance erradiantzia espektralerako lehen erradiazio-konstantea molar gas constant (R) gasen konstante molarra (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidten konstantea (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Loschmidten konstantea (n₀, 273.15 K, 101.325 kPa) molar Planck constant Plancken konstante molarra second radiation constant (c₂) bigarren erradiazio-konstantea (c₂) Stefan-Boltzmann constant (σ) Stefan-Boltzmannen konstantea (σ) lattice spacing of ideal Si (d₂₂₀) Si idealaren sare-tartea (d₂₂₀) atomic mass constant energy equivalent masa atomikoaren konstantearen energia-baliokidea atomic mass constant energy equivalent in MeV masa atomikoaren konstantearen energia-baliokidea MeV-tan atomic mass unit-electron volt relationship masa atomikoaren unitatea-elektronvolta erlazioa molar mass constant (Mᵤ) masa molarraren konstantea (Mᵤ) molar mass of carbon-12 karbono-12aren masa molarra molar volume of ideal gas (273.15 K, 100 kPa) gas idealaren bolumen molarra (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) gas idealaren bolumen molarra (273.15 K, 101.325 kPa) molar volume of silicon silizioaren bolumen molarra Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetroderen konstantea (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetroderen konstantea (1 K, 101.325 kPa) Wien frequency displacement law constant Wienen maiztasunaren desplazamendu-legearen konstantea Wien wavelength displacement law constant Wienen uhin-luzeraren desplazamendu-legearen konstantea standard atmosphere (atm) atmosfera estandarra (atm) standard-state pressure (p°) egoera estandarreko presioa (p°) Angstrom star (Å*) angstrom izarra (Å*) Copper x unit kobrearen x unitatea Molybdenum x unit molibdenoaren x unitatea atomic unit of magnetizability magnetizagarritasunaren unitate atomikoa atomic unit of mass (mₑ) masa (mₑ)ren unitate atomikoa atomic unit of momentum momentuaren unitate atomikoa atomic unit of permittivity permitibitatearen unitate atomikoa atomic unit of time denboraren unitate atomikoa atomic unit of velocity abiaduraren unitate atomikoa hartree-hertz relationship hartree-hertz erlazioa hartree-inverse meter relationship hartree-alderantzizko metroa erlazioa hartree-joule relationship hartree-joule erlazioa hartree-kelvin relationship hartree-kelvin erlazioa hartree-kilogram relationship hartree-kilogramo erlazioa shielding difference of d and p in HD d eta p-ren blindaje-diferentzia HDn shielding difference of t and p in HT t eta p-ren blindaje-diferentzia HTn pi (π) pi (π) Euler's number (e) Euler-en zenbakia (e) golden ratio (φ) urrezko proportzioa (φ) Euler-Mascheroni constant (γ) Euler-Mascheroniren konstantea (γ) nominal solar radius Eguzkiaren erradio nominala nominal solar total irradiance Eguzkiaren irradiantzia oso nominala nominal solar luminosity Eguzkiaren argitasun nominala nominal solar effective temperature Eguzkiaren tenperatura eraginkor nominala nominal solar mass parameter Eguzkiaren masa-parametro nominala nominal terrestrial equatorial radius Lurraren erradio ekuatorial nominala nominal terrestrial polar radius Lurraren erradio polar nominala nominal terrestrial mass parameter Lurraren masa-parametro nominala nominal jovian equatorial radius Jupiterren erradio ekuatorial nominala nominal jovian polar radius Jupiterren erradio polar nominala nominal jovian mass parameter Jupiterren masa-parametro nominala average value of one minus the rate of TCG relative to TCB TCGren TCBrekiko tasaren bat kenaren batez besteko balioa solar mass parameter (TCB-compatible) Eguzkiaren masa-parametroa (TCBrekin bateragarria) solar mass parameter (TDB-compatible) Eguzkiaren masa-parametroa (TDBrekin bateragarria) equatorial radius of the Earth (TT-compatible) Lurraren erradio ekuatoriala (TTrekin bateragarria) dynamical form factor of the Earth Lurraren forma-faktore dinamikoa time rate of change in the dynamical form factor of the Earth Lurraren forma-faktore dinamikoaren denborarekiko aldaketa-tasa geocentric gravitational constant (TCB-compatible) konstante grabitatorio geozentrikoa (TCBrekin bateragarria) geocentric gravitational constant (TT-compatible) konstante grabitatorio geozentrikoa (TTrekin bateragarria) geocentric gravitational constant (TDB-compatible) konstante grabitatorio geozentrikoa (TDBrekin bateragarria) potential of the geoid geoidearen potentziala nominal mean angular velocity of the Earth (TT-compatible) Lurraren batez besteko abiadura angeluar nominala (TTrekin bateragarria) ratio mass of the Moon to the Earth Ilargiaren eta Lurraren masen arteko erlazioa ratio of the mass of the Sun to Mercury Eguzkiaren eta Merkurioren masen arteko erlazioa ratio of the mass of the Sun to Venus Eguzkiaren eta Artizarraren masen arteko erlazioa ratio of the mass of the Sun to Mars Eguzkiaren eta Marteren masen arteko erlazioa ratio of the mass of the Sun to Jupiter Eguzkiaren eta Jupiterren masen arteko erlazioa ratio of the mass of the Sun to Saturn Eguzkiaren eta Saturnoren masen arteko erlazioa ratio of the mass of the Sun to Uranus Eguzkiaren eta Uranoren masen arteko erlazioa ratio of the mass of the Sun to Neptune Eguzkiaren eta Neptunoren masen arteko erlazioa ratio of the mass of the Sun to (134340) Pluto Eguzkiaren eta (134340) Plutoren masen arteko erlazioa ratio of the mass of the Sun to (136199) Eris Eguzkiaren eta (136199) Erisen masen arteko erlazioa ratio of the mass of (1) Ceres to the Sun (1) Ceresen eta Eguzkiaren masen arteko erlazioa ratio of the mass of (2) Pallas to the Sun (2) Pallasen eta Eguzkiaren masen arteko erlazioa ratio of the mass of (4) Vesta to the Sun (4) Vestaren eta Eguzkiaren masen arteko erlazioa mean obliquity of the ecliptic at J2000.0 ekliptikaren batez besteko zeihartasuna J2000.0n Electromagnetic Elektromagnetikoa Compton wavelength Comptonen uhin-luzera Astronomy Astronomia ConstantsWidget Domain Domeinua Subdomain Azpidomeinua No match found Ez da bat datorrenik aurkitu Name Izena Value Balioa Unit Unitatea Search Bilatu All Guztia CustomKeypadDialog Custom Keypad Teklatu pertsonalizatua Rows: Errenkadak: Columns: Zutabeak: Copy preset: Kopiatu aurrezarpena: Basic Oinarrizkoa Scientific (wide) Zientifikoa (zabala) Scientific (narrow) Zientifikoa (estua) Apply Aplikatu Row Errenkada Column Zutabea Label Etiketa Behavior Portaera Text Testua DiagnosticsDialog App Diagnostics Aplikazioaren diagnostikoa Copy to Clipboard Kopiatu arbelean Editor Unit Unitatea User unit Erabiltzaile-unitatea User function Erabiltzailearen funtzioa Argument Argumentua Current result:<br/>%1 Uneko emaitza:<br/>%1 Selection result:<br/>%1 Hautapenaren emaitza:<br/>%1 Selection result: n/a Hautapenaren emaitza: ez dago erabilgarri Selection result: %1 Hautapenaren emaitza: %1 second segundo metre metro kilogram kilogramo mole mol radian radian steradian estereorradian degree Celsius Celsius gradu cubic metre metro kubiko cubic millimetre milimetro kubiko cubic centimetre zentimetro kubiko cubic decimetre dezimetro kubiko cubic kilometre kilometro kubiko square millimetre milimetro karratu square kilometre kilometro karratu square metre metro karratu minute minutu hour ordu day egun astronomical unit unitate astronomiko degree gradu arcminute arku-minutu arcsecond arku-segundo milliarcsecond miliarku-segundo microarcsecond mikroarku-segundo hectare hektarea litre litro tonne tona Dalton dalton electronvolt elektronvolt Angstrom angstrom atmosphere atmosfera atomic mass unit masa atomikoaren unitate British thermal unit Britainiar unitate termiko calorie kaloria carat kilate cup katilu cup (Imperial) katilu (inperiala) cup (Japanese) katilu (japoniarra) cup (US) katilu (AEB) degree Fahrenheit Fahrenheit gradu fathom fathom fluid ounce (Imperial) ontza likido (inperiala) fluid ounce (US) ontza likido (AEB) fluid dram (Imperial) drakma likido (inperiala) fluid dram (US) drakma likido (AEB) foot oin square foot oin karratu cubic foot oin kubiko gallon (Imperial) galoi (inperiala) gallon (US) galoi (AEB) gill (Imperial) gill (inperiala) gill (US) gill (AEB) gradian gradian grain grain gram gramo Hartley hartley Hartree energy unit Hartree energia-unitate horsepower zaldi-potentzia inch hazbete square inch hazbete karratu cubic inch hazbete kubiko karat kilate knot korapilo lightminute argi-minutu lightsecond argi-segundo lightyear argi-urte long ton tona luze mile milia square mile milia karratu cubic mile milia kubiko mile per hour milia orduko kilometre per hour kilometro orduko nautical mile itsas milia ounce ontza parsec parsec pint (Imperial) pinta (inperiala) pint (US) pinta (AEB) pound libra pounds per square inch libra hazbete karratuko quart (Imperial) kuarto (inperiala) quart (US) kuarto (AEB) oil barrel petrolio-upel beer barrel (US) garagardo-upel (AEB) square yard yarda karratu cubic yard yarda kubiko short ton tona labur tablespoon koilarakada tablespoon (Australian) koilarakada (australiarra) tablespoon (Imperial) koilarakada (inperiala) tablespoon (US) koilarakada (AEB) dessert spoon postre-koilara teaspoon koilaratxo teaspoon (Imperial) koilaratxo (inperiala) teaspoon (US) koilaratxo (AEB) turn bira revolution bira revolution per minute bira minutuko week aste kilowatt hour kilowatt-ordu millimetre of mercury merkurio-milimetro yard yarda Julian century mende juliotar Julian year urte juliotar sidereal year urte sideral tropical year urte tropikal Evaluator invalid expression Adierazpen baliogabea division by zero zergatiko zatiketa too time consuming - computation was rejected Denbora gehiegi behar du: kalkulua baztertu da dimension mismatch - quantities with different dimensions cannot be compared, added, etc. Dimentsioak ez datoz bat: dimentsio desberdineko kantitateak ezin dira konparatu, batu, eta abar. invalid dimension - operation might require dimensionless arguments Dimentsio baliogabea: baliteke eragiketak dimentsiorik gabeko argumentuak behar izatea Computation aborted - encountered numerical instability Kalkulua bertan behera utzi da: ezegonkortasun numerikoa aurkitu da invalid dimension - function might require dimensionless arguments Dimentsio baliogabea: baliteke funtzioak dimentsiorik gabeko argumentuak behar izatea error errorea unit must not be zero Unitateak ezin du zero izan Conversion failed - dimension mismatch Bihurketak huts egin du: dimentsioak ez datoz bat unknown function or variable funtzio edo aldagai ezezaguna recursion not supported Ez da errekurtsiorik onartzen cannot operate on a NaN Ezin da NaN batekin eragiketarik egin underflow - tiny result is out of SpeedCrunch's number range Azpigainezkatzea: emaitza oso txikia SpeedCrunchen zenbaki-barrutitik kanpo dago overflow - huge result is out of SpeedCrunch's number range Gainezkatzea: emaitza erraldoia SpeedCrunchen zenbaki-barrutitik kanpo dago overflow - logic result exceeds maximum of 256 bits Gainezkatzea: emaitza logikoak 256 biteko gehienekoa gainditzen du overflow - integer result exceeds maximum limit for integers Gainezkatzea: emaitza osoak zenbaki osoen gehieneko muga gainditzen du operation is not defined for these arguments Eragiketa ez dago definituta argumentu hauetarako wrong number of arguments Argumentu kopuru okerra does not take NaN as an argument ez du NaN argumentu gisa onartzen result out of range Emaitza barrutitik kanpo dago undefined for argument domain Definitu gabe argumentuaren domeinurako computation too expensive Kalkulua garestiegia da internal error, please report a bug Barne-errorea; jakinarazi akatsa, mesedez syntax error Sintaxi-errorea conversion target must be a unit Bihurketaren helburuak unitatea izan behar du unknown unit unitate ezezaguna %1 is a reserved name, please choose another %1 izen erreserbatua da; aukeratu beste bat %1 is a global user definition and cannot be overridden in this session. %1 erabiltzailearen definizio globala da eta ezin da saio honetan gainidatzi. %1 is a variable name, please choose another or delete the variable %1 aldagai baten izena da; aukeratu beste bat edo ezabatu aldagaia argument %1 is used more than once %1 argumentua behin baino gehiagotan erabiltzen da %1 is a built-in unit name, please choose another %1 unitate-izen integratua da; aukeratu beste bat %1 is a user function name, please choose another or delete the function %1 erabiltzailearen funtzio baten izena da; aukeratu beste bat edo ezabatu funtzioa FunctionRepo max; trials; probability max; saiakerak; probabilitatea trials; probability saiakerak; probabilitatea hits; trials; probability arrakastak; saiakerak; probabilitatea max; total; hits; trials max; guztira; arrakastak; saiakerak total; hits; trials guztira; arrakastak; saiakerak count; total; hits; trials zenbaketa; guztira; arrakastak; saiakerak dividend; divisor zatikizuna; zatitzailea x; exponent_bits; significand_bits [; exponent_bias] x; berretzaile_bitak; adierazgarri_bitak [; berretzaile_biasa] base; x oinarria; x value; modulo balioa; modulua base; exponent; modulo oinarria; berretzailea; modulua events; average_events gertaerak; batezbesteko_gertaerak average_events batezbesteko_gertaerak x [; precision] x [; doitasuna] Absolute Value Balio absolutua Absolute Deviation Desbideratze absolutua Arc Cosine Arku kosinua Logical AND ETA logikoa Area Hyperbolic Cosine Arku kosinu hiperbolikoa Area Hyperbolic Sine Arku sinu hiperbolikoa Area Hyperbolic Tangent Arku tangente hiperbolikoa Arc Sine Arku sinua Arc Tangent Arku tangentea Arc Tangent with two Arguments Bi argumentuko arku tangentea Average (Arithmetic Mean) Batezbestekoa (batezbesteko aritmetikoa) Binomial Cumulative Distribution Function Banaketa binomialaren banaketa-funtzio metatua Binomial Distribution Mean Banaketa binomialaren batezbestekoa Binomial Probability Mass Function Banaketa binomialaren probabilitate-masa funtzioa Binomial Distribution Variance Banaketa binomialaren bariantza Cube Root Erro kubikoa Complex Conjugate Konjugatu konplexua Cosine Kosinu Hyperbolic Cosine Kosinu hiperbolikoa Cotangent Kotangentea Cosecant Kosekantea Convert Unix timestamp to Date Bihurtu Unix denbora-zigilua datara Degrees of Arc Arku-graduak Error Function Errore-funtzioa Complementary Error Function Errore-funtzio osagarria Exponential Esponentzial Fractional Part Zati frakzionarioa Extension of Factorials [= (x-1)!] Faktorialen hedapena [= (x-1)!] Greatest Common Divisor Zatitzaile komun handiena Geometric Mean Batezbesteko geometrikoa Gradians of arc Arku-gradianak Hypergeometric Cumulative Distribution Function Banaketa hipergeometrikoaren banaketa-funtzio metatua Hypergeometric Distribution Mean Banaketa hipergeometrikoaren batezbestekoa Hypergeometric Probability Mass Function Banaketa hipergeometrikoaren probabilitate-masa funtzioa Hypergeometric Distribution Variance Banaketa hipergeometrikoaren bariantza Integer Quotient Zatidura osoa Integer Part Zati osoa Imaginary Part Zati irudikaria Decode IEEE-754 Binary Value Deskodetu IEEE-754 balio bitarra Encode IEEE-754 Binary Value Kodetu IEEE-754 balio bitarra Decode 16-bit Half-Precision Value Deskodetu 16 biteko doitasun erdiko balioa Encode 16-bit Half-Precision Value Kodetu 16 biteko doitasun erdiko balioa Decode 32-bit Single-Precision Value Deskodetu 32 biteko doitasun bakuneko balioa Encode 32-bit Single-Precision Value Kodetu 32 biteko doitasun bakuneko balioa Decode 64-bit Double-Precision Value Deskodetu 64 biteko doitasun bikoitzeko balioa Encode 64-bit Double-Precision Value Kodetu 64 biteko doitasun bikoitzeko balioa Decode 128-bit Quad-Precision Value Deskodetu 128 biteko laukoiztasuneko balioa Encode 128-bit Quad-Precision Value Kodetu 128 biteko laukoiztasuneko balioa Binary Logarithm Logaritmo bitarra Common Logarithm Logaritmo hamartarra Natural Logarithm Logaritmo naturala Logarithm to Arbitrary Base Oinarri arbitrarioko logaritmoa Mask to a bit size Maskaratu bit-tamaina batera Maximum Maximoa Median Value (50th Percentile) Mediana (50. pertzentila) Minimum Minimoa Modulo Modulua Euclidean Modulo Modulu euklidearra Modular Exponentiation Berreketa modularra Combination (Binomial Coefficient) Konbinazioa (koefiziente binomiala) Logical NOT EZ logikoa Permutation (Arrangement) Permutazioa (antolaketa) Convert to Binary Representation Bihurtu adierazpen bitarrera Arithmetic Aritmetika Chemistry Kimika Complex Konplexuak Combinatorics Konbinatoria Probability Probabilitatea Statistics Estatistika Aggregation Agregazioa Random Ausazkoa Base conversion Oinarri-bihurketa Number formatting Zenbaki-formatua Integer arithmetic Zenbaki osoen aritmetika Special functions Funtzio bereziak Exponential & Logarithmic Esponentziala eta logaritmikoa Angle conversion Angelu-bihurketa Trigonometry Trigonometria Bitwise Bit mailakoa Floating point Koma mugikorra Date & Time Data eta ordua Linear algebra Aljebra lineala unix_timestamp; x hours offset to GMT unix_timestamp; x orduko desfasea GMTren aldean yyyymmdd.hhmmss; x hours offset to GMT uuuuhhee.hhmmss; x orduko desfasea GMTren aldean [digits] [zifrak] max [; min] max [; min] List Literal Zerrenda literala Convert to Padded Binary Representation Bihurtu: bitar adierazpen betea Round Toward +∞ (Ceiling) Biribildu norabiderantz: +∞ (sabaia) Cosine plus Imaginary Sine Kosinua gehi sinu irudikaria Convert to Cis Complex Form Bihurtu: cis forma konplexua Matrix Column Count Matrizearen zutabe-kopurua Population Correlation Matrix (n) Populazioa korrelazio-matrizea (n) Sample Correlation Matrix (n-1) Lagina korrelazio-matrizea (n-1) Count Zenbaketa Population Covariance Matrix (n) Populazioa kobariantza-matrizea (n) Sample Covariance Matrix (n-1) Lagina kobariantza-matrizea (n-1) Cross Product Biderketa bektoriala Convert Date to Unix timestamp Bihurtu data Unix denbora-zigilura Convert to Decimal Representation Bihurtu adierazpen hamartarrera Determinant Determinatzailea Convert to Sexagesimal Notation Bihurtu: notazio hirurogeitarra Dot Product Biderketa eskalarra Convert to Engineering Notation Bihurtu: ingeniaritza-notazioa Convert to Exponential Complex Form Bihurtu: forma konplexu esponentziala Round Toward −∞ (Floor) Biribildu norabiderantz: −∞ (zorua) Flatten Matrix Lautu matrizea Least Common Multiple Multiplo komun txikiena Convert to Hexadecimal Representation Bihurtu adierazpen hamaseitarrera Convert to Padded Hexadecimal Representation Bihurtu adierazpen hamaseitar betera Inverse Matrix Alderantzizko matrizea Round to 16-bit Half-Precision Value Biribildu: 16-bit doitasun erdiko balioa Round to 32-bit Single-Precision Value Biribildu: 32-bit doitasun bakarreko balioa Round to 64-bit Double-Precision Value Biribildu: 64-bit doitasun bikoitzeko balioa Round to 128-bit Quad-Precision Value Biribildu: 128-bit doitasun laukoitzeko balioa Residual from 16-bit Half-Precision Rounding Hondarra: 16-bit Half-Precision biribiltzea Residual from 32-bit Single-Precision Rounding Hondarra: 32-bit Single-Precision biribiltzea Residual from 64-bit Double-Precision Rounding Hondarra: 64-bit Double-Precision biribiltzea Residual from 128-bit Quad-Precision Rounding Hondarra: 128-bit Quad-Precision biribiltzea Substance Mass Substantziaren masa Molarity Molartasuna Molar Mass Masa molarra Median Absolute Deviation desbideratze absolutu mediana Mean Batezbestekoa Numerical Value of Quantity Kantitatearen zenbakizko balioa Random Decimal Number Ausazko zenbaki hamartarra Random Integer Number Ausazko zenbaki osoa Convert to Rational Representation Bihurtu: adierazpen arrazionala Convert to Octal Representation Bihurtu adierazpen zortzitarrera Convert to Padded Octal Representation Bihurtu adierazpen zortzitar betera Vector or Matrix Norm Bektorearen edo matrizearen norma Logical OR EDO logikoa Population Count (Hamming Weight) Populazio-kontaketa (Hamming pisua) Phase of Complex Number Zenbaki konplexuaren fasea Poissonian Cumulative Distribution Function Poissonen banaketaren banaketa-funtzio metatua Poissonian Distribution Mean Poissonen banaketaren batezbestekoa Poissonian Probability Mass Function Poissonen banaketaren probabilitate-masa funtzioa Poissonian Distribution Variance Poissonen banaketaren bariantza Convert to Phasor Complex Form Bihurtu zenbaki konplexuen fasore-formara Convert to Rectangular Complex Form Bihurtu: forma konplexu laukizuzena Round Half Away from Zero Biribildu erdia zerotik urrun Round Half Even Biribildu erdia bikoitira Nth Root N. erroa Convert to Scientific Notation Bihurtu: notazio zientifikoa Matrix Row Count Matrizearen errenkada-kopurua List or Matrix Shape Zerrendaren edo matrizearen forma Summation Batuketa Population Standard Deviation (n) Populazioa desbideratze estandarra (n) Sample Standard Deviation (n-1) Lagina desbideratze estandarra (n-1) Round Toward Zero (Truncation) Biribildu norabiderantz: Zero (mozketa) Matrix Trace Matrizearen traza Transpose Matrix Matrize iraulia Population Variance (n) Populazioa bariantza (n) Sample Variance (n-1) Lagina bariantza (n-1) Product Biderkadura Radians Radianak Matrix Rank Matrizearen heina Real Part Zati erreala Secant Sekantea Arithmetic Shift Left Desplazamendu aritmetikoa ezkerrera Arithmetic Shift Right Desplazamendu aritmetikoa eskuinera Signum Zeinu-funtzioa Sine Sinu Hyperbolic Sine Sinu hiperbolikoa Square Root Erro karratua Sum Batura Tangent Tangente Convert to Trigonometric Complex Form Bihurtu zenbaki konplexuen forma trigonometrikora Turns Birak Hyperbolic Tangent Tangente hiperbolikoa Sign-extend a value Hedatu balioaren zeinu-bita Logical XOR XOR logikoa FunctionsWidget Domain Domeinua All Guztia Name Izena Search Bilatu No match found Ez da bat datorrenik aurkitu Identifier Identifikatzailea HistoryWidget Remove All Calculations Above Kendu gaineko kalkulu guztiak Remove This Calculation Kendu kalkulu hau Remove All Calculations Below Kendu beheko kalkulu guztiak Keypad Inverse cosine Arku kosinu The last result Azken emaitza Inverse sine Arku sinu Inverse tangent Arku tangente Evaluate expression Ebaluatu adierazpena Division Zatiketa Multiplication Biderketa Subtraction Kenketa Addition Batuketa Clear expression Adierazpena ezabatu Cosine Kosinu Backspace Atzera ezabatu Scientific notation Notazio zientifikoa Exponential Esponentzial Factorial Faktoriala Natural logarithm Logaritmo Nepertarra Left parenthesis Ezker parentesia Nth root N. erroa Argument separator Argumentu-bereizlea Square Karratua Common logarithm Logaritmo arrunta Modulo Modulua Contextual percentage Testuinguruko ehunekoa Power Potentzia Right parenthesis Eskuineko parentesia Sine Sinu Square root Erro karratu Tangent Tangente Pi Pi Decimal separator Bereizle hamartarra MainWindow Radian Radiana Degree Gradu Gradian Gradiana Binary Bitarra Octal Zortzitarra Hexadecimal Hamaseitarra Sexagesimal Hirurogeitarra Engineering decimal Ingeniaritzako hamartarra Scientific decimal Hamartar zientifikoa &Import... &Inportatu... &Quit &Irten Clear E&xpression &Adierazpena Ezabatu Clear &History &Historia Garbitu &Copy &Kopiatu &Paste &Itsatsi &Select Expression &Adierazpena Aukeratu &Constants &Konstanteak &Functions &Funtzioak &History &Historia &Status Bar &Egoera Barra Bitfield Bit-eremua Use&r Functions Erabiltzailearen &funtzioak &Degree &Gradu &Radian &Radiana &Gradian &Gradiana Re&volution B&iraketa Auto-Insert a&ns Txertatu a&ns automatikoki Automatic &Completion Automatikoki &Osatu &Built-in Functions &Funtzio integratuak Built-in &Variables &Aldagai integratuak User &Functions &Erabiltzailearen funtzioak User Va&riables E&rabiltzailearen aldagaiak Open a Private Tab on Startup Ireki fitxa pribatua abioan Open and focus a new private tab whenever SpeedCrunch starts. Ireki eta aktibatu fitxa pribatu berri bat SpeedCrunch abiarazten den bakoitzean. Syntax &Highlighting Sintaxia &Nabarmendu Group Digits in &Input Taldekatu sarrerako d&igituak Automatic Input &Adjustments S&arreraren doikuntza automatikoak Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Doitu automatikoki eragileak, tarteak, parentesiak eta berreturak, eta mugatu sarrera baliozko karaktereetara. Group input digits using the selected number format. Taldekatu sartutako digituak hautatutako zenbaki-formatuaren arabera. &Blinking Cursor &Kurtsore keinukaria Blink the cursor in the expression editor. Egin keinu kurtsorearekin adierazpen-editorean. &Escape Clears Editor &Escape teklak editorea garbitzen du Clear the focused expression editor with Escape after dismissing any popup or preview. Garbitu adierazpen-editore aktiboa Escape teklarekin, leiho gainerakorrak edo aurrebistak itxi ondoren. Keep Expression After Evaluation Mantendu adierazpena kalkulatu ondoren Copy New Results Automatically Kopiatu emaitza berriak automatikoki &Comma &Koma &System Default &Sistema Lehenetsia &Dot &Puntua Dot &And Comma Puntua &eta koma Toward +∞ (&ceil) +∞ aldera (&ceil) Toward −∞ (&floor) −∞ aldera (&floor) &Binary &Bitarra &Engineering &Ingeniaritza &Hexadecimal &Hamaseitarra &Octal &Zortzitarra &Scientific &Zientifikoa User &Manual Erabiltzailearen &eskuliburua Issues and &Feedback &Arazoak eta iritziak &Donate Egin &dohaintza &About SpeedCrunch &SpeedCrunch-i buruz App Diag&nostics Aplikazioare&n diagnostikoa S&plit Za&titu Angle &Mode Angelu &modua &Complex Form &Forma konplexua New Tab Fitxa berria Constants Konstanteak Functions Funtzioak History Historia User Functions Erabiltzailearen funtzioak &Font... &Letra-tipoa... &Language... &Hizkuntza... &Session &Saioa &Edit &Editatu &View &Erakutsi Se&ttings &Ezarpenak &Decimal &Hamartarra &Keypad &Zenbakizko teklatua Always on &Top Beti &gainean Disabled Desgaituta Small Space Tarte txikia Medium Space Tarte ertaina Large Space Tarte handia &0 Digits &0 digitu &15 Digits &15 digitu &2 Digits &2 digitu &3 Digits &3 digitu &50 Digits &50 digitu &8 Digits &8 digitu &Sexagesimal &Hirurogeitarra Reset All Settings... Berrezarri ezarpen guztiak... &System &Sistema SpeedCrunch &Theme S&peedCrunch gaia &Classic &Klasikoa &Modern &Modernoa Context Help Testuinguruko laguntza &Help &Laguntza Error Akatsa Can't read from file %1 Ezin %1 fitxategitik irakurri Import Session Inportatu saioa Close Session Itxi saioa Angle Mode: Angelu-modua: Notation: Notazioa: Precision: Doitasuna: Turn Bira Revolution Biraketa Fixed-point decimal Koma finkoko hamartarra Rational Arrazionala Automatic decimal Hamartar automatikoa Automatic Automatikoa User &Definitions... Erabiltzailearen &definizioak... New &Tab Fitxa &berria New &Private Tab Fitxa &pribatu berria Keep Mantendu Make Private... Bihurtu pribatu... New &Window Leiho &berria &Open... &Ireki... &Rename... &Aldatu izena... Clo&ne... Klo&natu... &Close Tab I&txi fitxa Reopen Clo&sed Tab I&reki berriro itxitako fitxa Open Sessions &Folder Ireki saioen &karpeta &Undo &Desegin &Redo Be&rregin Cu&t &Ebaki Copy &Last Result K&opiatu azken emaitza &Wrap in Parentheses &Jarri parentesi artean Full Scr&een Mode &Pantaila osoko modua &Basic &Oinarrizkoa &Scientific (wide) &Zientifikoa (zabala) Scientific (narrow) Zientifikoa (estua) &Custom... &Pertsonalizatua... Main &Menu &Menu nagusia User &Variables Erabiltzailearen &aldagaiak &Left &Ezkerra &Right E&skuina &Up &Gora &Down &Behera Close Pa&ne Itxi pa&nela User &Units Erabiltzailearen &unitateak &Turn &Bira If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Adierazpen berri bat +, -, * edo / ikurrarekin hasten bada, SpeedCrunch-ek "ans" txertatzen du lehenik. &Accept with Enter &Onartu Sartu teklarekin Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Onartu uneko osatze automatikoko iradokizuna Sartu teklarekin, aurretik gezi-teklak erabiliz hautatu gabe. &Units &Unitateak Show Live Result &Preview Erakutsi emaitzaren zuzeneko &aurrebista Save &Window Position on Exit Gorde &leihoaren kokapena irtetean Hover Highlighting Nabarmentzea gainetik pasatzean Group Integer Part Only Taldekatu zati osoa soilik Number Format... Zenbaki-formatua... Notation && Precision... Notazioa eta doitasuna... After pressing Enter, keep the entered expression selected in the editor. Enter sakatu ondoren, mantendu sartutako adierazpena hautatuta editorean. Never Inoiz ez Always Beti Only for Single-Line Expressions Lerro bakarreko adierazpenetarako soilik Simplify Displayed Expressions Sinplifikatu bistaratutako adierazpenak History Size &Limit... Historiaren tamainaren &muga... Remove Trailing &Zeroes Kendu amaierako &zeroak Nearest, Half &Away (round) Hurbilena, erdia &kanpora (round) Nearest, Half &Even (roundeven) Hurbilena, erdia &parekora (roundeven) Toward &Zero (trunc) &Zerorantz (trunc) &Fixed-Point Koma &finkoa &Rational &Arrazionala &Exponential (m·s�¹) &Esponentziala (m·s�¹) &Fractional (m/s) &Frakzioaal (m/s) &Rectangular (a + bi) &Kartesiarra (a + bi) Exponential (re�ᶿ) Esponentziala (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonometrikoa (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasorea (r∠θ) &Theme... &Gaia... Check for &Updates Bilatu &eguneraketak Source Code Iturburu-kodea &Zoom &Zooma &Results &Emaitzak Unit Notation Unitate-notazioa Rounding Mode Biribiltze-modua &Notation &Notazioa &Imaginary Unit Unitate &irudikaria &Window &Leihoa &Editing &Edizioa A&utocomplete A&utobetetzea Up/Down Arrow History Gora/behera gezien historia &Appearance &Itxura &Menus &Menuak &Docks &Panel atrakagarriak &Input and Results Sarrera eta ema&itzak &Disabled &Desgaituta &Disable &Desgaitu Close preview Itxi aurrebista Rename... Aldatu izena... Clone... Klonatu... Close Tab Itxi fitxa New Private Tab Fitxa pribatu berria Open... Ireki... Reopen Closed Tab Ireki berriro itxitako fitxa Split Zatitu Left Ezkerra Right Eskuina Up Gora Down Behera Clear Garbitu Delete Ezabatu %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Saio pribatua: edukia baztertu egiten da ixtean. Aukeratu Saioa > Mantendu saio arrunt bihurtzeko. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Pribatua] Reset All Settings Berrezarri ezarpen guztiak Reset all settings to their default values? Berrezarri ezarpen guztiak balio lehenetsietara? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Itxura, edizioa, emaitzen formatuak eta leihoen hobespenak barne hartzen ditu. Kalkuluak, irekitako saioak eta erabiltzailearen definizioak mantenduko dira. The settings file could not be written. Ezin izan da ezarpenen fitxategia idatzi. Clear this session's calculations, unfinished expression, variables, functions, and units? Garbitu saio honetako kalkuluak, amaitu gabeko adierazpena, aldagaiak, funtzioak eta unitateak? Global user definitions are kept. Erabiltzailearen definizio globalak mantentzen dira. Make Session Private Bihurtu saioa pribatu The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Gordetako %1 saioa ezabatuko da. Edukia saio pribatu batean irekita mantenduko da eta saio hori ixtean edo SpeedCrunch-etik irtetean baztertuko da. Make Private Bihurtu pribatu Could not delete the saved session %1. Ezin izan da gordetako %1 saioa ezabatu. Keep Session Mantendu saioa Could not save the session. It remains private. Ezin izan da saioa gorde. Pribatua izaten jarraitzen du. Clone Session Klonatu saioa Could not save session file %1. Ezin izan da %1 saio-fitxategia gorde. Could not delete session file %1. Ezin izan da %1 saio-fitxategia ezabatu. JSON file (*.json);;Any file (*.*) JSON fitxategia (*.json);;Edozein fitxategi (*.*) Export session as JSON Esportatu saioa JSON gisa The selected file is not valid JSON: %1 Hautatutako fitxategia ez da baliozko JSONa: %1 The selected file is not a SpeedCrunch session JSON file. Hautatutako fitxategia ez da SpeedCrunch saio baten JSON fitxategia. This file uses an obsolete SpeedCrunch session format and cannot be imported. Fitxategi honek SpeedCrunch saio-formatu zaharkitua erabiltzen du eta ezin da inportatu. The selected JSON file is missing the required $schema field. Hautatutako JSON fitxategian beharrezko $schema eremua falta da. The selected JSON file uses an unsupported JSON schema: %1 Hautatutako JSON fitxategiak onartzen ez den JSON eskema erabiltzen du: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Hautatutako JSON fitxategian SpeedCrunch saio-eskemaren identifikatzailea ($id) falta da. The selected JSON file uses an unsupported SpeedCrunch session format: %1 Hautatutako JSON fitxategiak onartzen ez den SpeedCrunch saio-formatua erabiltzen du: %1 The selected JSON file is missing the required session name. Hautatutako JSON fitxategian beharrezko saio-izena falta da. The selected JSON file has an empty session name. Hautatutako JSON fitxategiak saio-izen hutsa du. The selected JSON file has invalid or incomplete SpeedCrunch session data. Hautatutako JSON fitxategiak SpeedCrunch saio-datu baliogabeak edo osatu gabeak ditu. Open Sessions Folder Ireki saioen karpeta Could not create the sessions folder: %1 Ezin izan da saioen karpeta sortu: %1 Could not open the sessions folder: %1 Ezin izan da saioen karpeta ireki: %1 Editor and Results Font Editorearen eta emaitzen letra-tipoa Open Session Ireki saioa Community Komunitatea Rename Session Aldatu saioaren izena Clear Session Garbitu saioa Delete Session Ezabatu saioa Close Pane Itxi panela User Variables Erabiltzailearen aldagaiak User Units Erabiltzailearen unitateak Clear History Garbitu historia Are you sure you want to clear the calculation history? Ziur zaude kalkuluen historia garbitu nahi duzula? Session name: Saioaren izena: A session named %1 already exists. %1 izeneko saioa badago lehendik. Could not create session file %1. Ezin izan da %1 saio-fitxategia sortu. Could not write session file %1. Ezin izan da %1 saio-fitxategia idatzi. Are you sure you want to delete this session? Ziur zaude saio hau ezabatu nahi duzula? Custom Precision Doitasun pertsonalizatua Fractional digits: Zifra hamartarrak: Theme Gaia Light Themes Gai argiak Dark Themes Gai ilunak Preview Aurrebista Colors Koloreak Select color for %1 Hautatu %1(r)en kolorea Import... Inportatu... Export... Esportatu... Import Theme Inportatu gaia Theme file (*.json);;All files (*) Gai-fitxategia (*.json);;Fitxategi guztiak (*) Invalid theme file. Gai-fitxategi baliogabea. Can't import theme "%1" because it conflicts with a built-in theme. Ezin da "%1" gaia inportatu, gai integratu batekin gatazkan dagoelako. Can't find a writable theme folder. Ezin da idazteko moduko gai-karpetarik aurkitu. Overwrite Theme Gainidatzi gaia A custom theme named "%1" already exists. Do you want to overwrite it? "%1" izeneko gai pertsonalizatua badago. Gainidatzi nahi duzu? Can't overwrite theme file %1 Ezin da %1 gai-fitxategia gainidatzi Can't copy theme file to %1 Ezin da gaiaren fitxategia %1(e)ra kopiatu Export Theme Esportatu gaia Can't export theme as "%1" because it conflicts with a built-in theme. Ezin da gaia "%1" gisa esportatu, gai integratu batekin gatazkan dagoelako. Can't write to file %1 Ezin %1 fitxategira idatzi Global User Variable Erabiltzailearen aldagai globala Global User Function Erabiltzailearen funtzio globala Global User Unit Erabiltzailearen unitate globala User Definitions Erabiltzailearen definizioak These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Definizio hauek globalak dira eta saio guztietan kargatzen dira. Ezin dira saioetan aldatu, eta saioko editoreko izen bereko definizioen gainetik lehentasuna dute. Sartu definizio bat lerro bakoitzeko. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Adibideak: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Aplikatu Validate Baliozkotu Test Results Probaren emaitzak Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Inportatutako aldagaiak: %1 Inportatutako funtzioak: %2 Inportatutako unitateak: %3 Erroreak dituzten lerroen zenbakiak: %4 none bat ere ez Apply Results Aplikazioaren emaitzak User definitions saved. Erabiltzailearen definizioak gorde dira. History Size Limit Historiaren tamainaren muga Maximum number of history entries for this session (0 = unlimited): Saio honetako historiako sarrera kopuru maximoa (0 = mugagabea): Text file (*.txt);;Any file (*.*) Testu-fitxategia (*.txt);;Edozein fitxategi (*.*) Could not recalculate from calculation %1: %2 Ezin izan da %1 kalkulutik berriro kalkulatu: %2 History Size Limit Reached Historiaren tamainaren muga iritsi da This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Kalkulu honek historiako azken leku erabilgarria betetzen du. Etorkizuneko kalkuluek historiako kalkulu zaharrena kenduko dute. Muga handitu dezakezu Saioa > Historiaren tamaina-muga ataletik. Editing calculation. Press Esc twice to cancel. Kalkulua editatzen. Sakatu Esc bi aldiz bertan behera uzteko. Calculation Settings Kalkulu-ezarpenak Invalid recalculation start index Birkalkuluaren hasiera-indize baliogabea System Default Sistemaren lehenetsia Language Hizkuntza Select the language: Hautatu hizkuntza: Custom Pertsonalizatua Decimal places: Hamartar-kopurua: &Automatic &Automatikoa &Precision &Doitasuna Plain &text &Testu arrunta Formula &Book Formula-&liburua &Export &Esportatu Export session as HTML Esportatu saioa HTML gisa HTML file (*.html) HTML fitxategia (*.html) Export session as plain text Esportatu saioa testu arrunt gisa ManualWindow SpeedCrunch Manual SpeedCrunch eskuliburua %1 - SpeedCrunch Manual %1 - SpeedCrunch eskuliburua NumberFormatDialog Number Format Zenbaki-formatua <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Hautatu emaitzen eta sarrerako digituen taldekatzeen zenbaki-formatua.</b><br/><br/>Oharra: sartutako zenbakietarako formatu argiak onartzen dira, hautatutako bistaratze-formatutik desberdinak izan arren.<br/> QObject Global User Variable Erabiltzailearen aldagai globala Global User Function Erabiltzailearen funtzio globala Global User Unit Erabiltzailearen unitate globala Backspace Atzera ezabatu Clear expression Adierazpena ezabatu Evaluate expression Ebaluatu adierazpena Insert text Txertatu testua Automatic decimal Hamartar automatikoa Fixed-point decimal Koma finkoko hamartarra Engineering decimal Ingeniaritzako hamartarra Scientific decimal Hamartar zientifikoa Rational Arrazionala Binary Bitarra Octal Zortzitarra Hexadecimal Hamaseitarra Sexagesimal Hirurogeitarra Update Available Eguneraketa eskuragarri A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Bertsio berriago bat (%1) eskuragarri dago.<br/><a href="%2">Bisitatu webgunea deskargatzeko.</a> Check for Updates Bilatu eguneraketak SpeedCrunch %1 is up to date. SpeedCrunch %1 eguneratuta dago. No connectivity. Please check your internet connection and try again. Ez dago konexiorik. Egiaztatu Interneteko konexioa eta saiatu berriro. Could not verify the latest available version. Ezin izan da azken bertsio eskuragarria egiaztatu. ResultDisplay Scroll to bottom Joan behealdera Edit Expression Editatu adierazpena Change Settings Aldatu ezarpenak New Tab Fitxa berria &Import... &Inportatu... &Export &Esportatu Plain &text &Testu arrunta Copy Kopiatu Selection Hautapena Select All Hautatu dena Expression Adierazpena Result Emaitza Calculation Kalkulua Calculation as Single Line Kalkulua lerro bakarrean Remove Kendu This Calculation Kalkulu hau All Calculations Above Goiko kalkulu guztiak All Calculations Below Beheko kalkulu guztiak New Private Tab Fitxa pribatu berria Session Saioa Open... Ireki... Clone... Klonatu... Rename... Aldatu izena... Keep Mantendu Make Private... Bihurtu pribatu... Clear Garbitu Delete Ezabatu Close Itxi Split Zatitu Left Ezkerra Right Eskuina Up Gora Down Behera Close Pane Itxi panela Main Menu Menu nagusia Cancel editing Utzi edizioa Copy result Kopiatu emaitza Edit expression Editatu adierazpena Change settings Aldatu ezarpenak Remove calculation Kendu kalkulua ResultSlotsDialog Notation & Precision Notazioa eta doitasuna Result Line Emaitza-lerroa Enabled Gaituta Notation Notazioa Decimal Places Hamartar-kopurua Main Line Lerro nagusia Extra Line #1 Lerro gehigarria #1 Extra Line #2 Lerro gehigarria #2 Extra Line #3 Lerro gehigarria #3 Extra Line #4 Lerro gehigarria #4 Auto Automatikoa UserFunctionListWidget Name Izena Value Balioa Description Deskribapena Search Bilatu No match found Ez da bat datorrenik aurkitu Insert Txertatu Edit Editatu Delete Ezabatu Delete All Ezabatu dena UserUnitListWidget Name Izena Value Balioa Description Deskribapena Search Bilatu No match found Ez da bat datorrenik aurkitu Insert Txertatu Edit Editatu Delete Ezabatu Delete All Ezabatu dena VariableListWidget Name Izena Value Balioa Description Deskribapena Search Bilatu No match found Ez da bat datorrenik aurkitu Insert Txertatu Edit Editatu Delete Ezabatu Delete All Ezabatu dena heldercorreia-speedcrunch-e7ca37f/src/resources/locale/fa.ts000066400000000000000000011014621526573132500243400ustar00rootroot00000000000000 AboutBox About SpeedCrunch درباره SpeedCrunch Core developers توسعه‌دهندگان هسته Original author نویسنده اصلی Close بستن Math engine موتور ریاضی Main author | Logo | Maintainer نویسنده اصلی | نشان‌واره | نگهدارنده Thanks با تشکر از Copyright (C) 2004-2026 The SpeedCrunch developers حق نشر (C) ۲۰۰۴-۲۰۲۶ توسعه‌دهندگان SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version این برنامه نرم‌ا�زار آزاد است؛ شما می‌توانید آن را تحت شرایط پروانه عمومی همگانی گنو، آن‌گونه که بنیاد نرم‌ا�زار آزاد منتشر کرده است، بازتوزیع و/یا اصلاح کنید؛ چه نسخه ۲ پروانه، و چه هر نسخه بعدی به انتخاب شما This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. این برنامه با این امید توزیع می‌شود که م�ید باشد، اما بدون هیچ ضمانتی؛ حتی بدون ضمانت ضمنی قابلیت �روش یا تناسب برای هد�ی خاص. برای جزئیات بیشتر پروانه عمومی همگانی گنو را ببینید. BitFieldWidget Reset bits to zero بازنشانی بیت‌ها به ص�ر Invert bits وارونه کردن بیت‌ها Shift bits left انتقال بیت‌ها به چپ Shift bits right انتقال بیت‌ها به راست Book Index �هرست Algebra جبر Quadratic Equation معادله درجه دوم Logarithmic Base Conversion تبدیل پایه لگاریتمی Geometry هندسه Circle دایره Sector قطاع Sphere کره Cube مکعب Cone مخروط Cylinder استوانه Electronics الکترونیک Ohm's Law قانون اهم Power توان Reactance راکتانس Resonance تشدید Radio Frequency بسامد رادیویی Antennas آنتن Characteristic Impedance (coax) امپدانس مشخصه (هم‌محور) Velocity of Propagation (coax) سرعت انتشار(هم محور) Standing Wave Ratio & Return Loss نسبت موج ایستاده و ا�ت بازگشتی Free Space Wavelength طول موج در �ضای آزاد resistance مقاومت voltage ولتاژ current جریان power توان inductive reactance راکتانس القایی capacitive reactance راکتانس خازنی inductance اندوکتانس capacitance ظر�یت خازنی frequency �رکانس resonance frequency بسامد تشدید area مساحت perimeter محیط diameter قطر radius شعاع volume حجم surface area مساحت سطح height ارت�اع slant height ارت�اع مایل face diagonal قطر وجه space diagonal قطر �ضایی edge length طول لبه arc length طول قوس central angle (degrees) زاویه مرکزی (درجه) input power توان ورودی reflected power توان بازتابی transmitted power توان انتقالی return loss ا�ت بازگشتی dielectric constant ثابت دی‌الکتریک outer conductor's inner diameter قطر داخلی هادی بیرونی inner conductor's outer diameter قطر بیرونی هادی داخلی speed of light سرعت نور reflection coefficient ضریب انعکاس standing wave ratio نسبت موج ایستاده normalized impedance ثابت مقاومت ظاهری frequency (Hz) �رکانس(برحسب هرتز) BookDock Formula Book کتاب �رمول ConstantCompletion Search constants جستجوی ثابت‌ها No match found نتیجه‌ای پیدا نشد Constants Mathematics ریاضیات Physics (CODATA 2022) �یزیک (CODATA ۲۰۲۲) Chemistry (IUPAC - CIAAW 2021) شیمی (IUPAC - CIAAW ۲۰۲۱) Uncategorized دسته‌بندی‌نشده Universal جهانی Physicochemical �یزیکوشیمیایی Atomic & Nuclear — General اتمی و هسته‌ای — عمومی Atomic & Nuclear — Electroweak اتمی و هسته‌ای — الکتروضعی� Atomic & Nuclear — Electron اتمی و هسته‌ای — الکترون Atomic & Nuclear — Muon اتمی و هسته‌ای — میون Atomic & Nuclear — Tau اتمی و هسته‌ای — تاو Atomic & Nuclear — Proton اتمی و هسته‌ای — پروتون Atomic & Nuclear — Neutron اتمی و هسته‌ای — نوترون Atomic & Nuclear — Deuteron اتمی و هسته‌ای — دوترون Atomic & Nuclear — Triton اتمی و هسته‌ای — تریتون Atomic & Nuclear — Helion اتمی و هسته‌ای — هلیون Atomic & Nuclear — Alpha particle اتمی و هسته‌ای — ذره آل�ا Atomic & Nuclear — Atomic units اتمی و هسته‌ای — یکاهای اتمی Atomic & Nuclear — Energy conversion relationships اتمی و هسته‌ای — روابط تبدیل انرژی Atomic & Nuclear — X-ray units اتمی و هسته‌ای — یکاهای پرتو ایکس Atomic & Nuclear — Magnetic shielding corrections اتمی و هسته‌ای — تصحیحات پوشش مغناطیسی Masses جرم‌ها Lifetimes طول عمرها Molar Masses جرم‌های مولی Electronegativity الکترونگاتیوی Ionization Energy انرژی یونش Nominal Constants (IAU 2015) ثابت‌های اسمی (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) بهترین برآوردهای کنونی (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) امپدانس مشخصه خلأ (Z₀) reduced Planck constant (�) ثابت کاهش‌یا�ته پلانک (�) vacuum electric permittivity (ϵ₀) گذردهی الکتریکی خلأ (ϵ₀) Newtonian constant of gravitation (G) ثابت گرانش نیوتنی (G) vacuum magnetic permeability (μ₀) تراوایی مغناطیسی خلأ (μ₀) Planck constant (h) ثابت پلانک (h) speed of light in vacuum (c) سرعت نور در خلأ (c) standard acceleration of gravity (gₙ) شتاب استاندارد گرانش (gₙ) Newtonian constant of gravitation over h-bar c ثابت گرانش نیوتنی over h-بار c Planck length طول پلانک Planck constant in eV/Hz (h) ثابت پلانک در eV/Hz (h) Planck mass جرم پلانک Planck mass energy equivalent in GeV Planck معادل انرژی جرم در GeV Planck temperature دمای پلانک Planck time زمان پلانک reduced Planck constant in eV·s (�) ثابت کاهش‌یا�ته پلانک در eV·s (�) reduced Planck constant times c in MeV·fm ثابت کاهش‌یا�ته پلانک ضربدر c در MeV·fm Bohr magneton مگنتون بور conductance quantum (G₀) کوانتوم رسانایی (G₀) Coulomb constant (kₑ) ثابت کولن (kₑ) elementary charge (e) بار بنیادی (e) elementary charge over h-bar بار بنیادی over h-بار conventional value of Josephson constant conventional value از ثابت جوز�سون Josephson constant ثابت جوز�سون conventional value of ampere-90 conventional value از ampere-90 conventional value of coulomb-90 conventional value از coulomb-90 conventional value of farad-90 conventional value از farad-90 conventional value of henry-90 conventional value از henry-90 conventional value of ohm-90 conventional value از ohm-90 conventional value of volt-90 conventional value از volt-90 conventional value of watt-90 conventional value از watt-90 magnetic flux quantum (Φ₀) کوانتوم شار مغناطیسی (Φ₀) nuclear magneton مگنتون هسته‌ای inverse of conductance quantum inverse از کوانتوم رسانایی conventional value of von Klitzing constant conventional value از ثابت �ون کلیتسینگ von Klitzing constant ثابت �ون کلیتسینگ atomic unit of magnetic dipole moment یکای اتمی از مغناطیسی dipole گشتاور atomic unit of magnetic flux density یکای اتمی از مغناطیسی fلوکس چگالی Bohr magneton in eV/T مگنتون بور در eV/T Bohr magneton in Hz/T مگنتون بور در Hz/T Bohr magneton in inverse meter per tesla مگنتون بور در inverse meter بر tesla Bohr magneton in K/T مگنتون بور در K/T nuclear magneton in eV/T مگنتون هسته‌ای در eV/T nuclear magneton in inverse meter per tesla مگنتون هسته‌ای در inverse meter بر tesla nuclear magneton in K/T مگنتون هسته‌ای در K/T nuclear magneton in MHz/T مگنتون هسته‌ای در MHz/T Bohr radius (a₀) شعاع بور (a₀) fine-structure constant (α) ثابت ساختار ریز (α) Hartree energy (Eₕ) انرژی هارتری (Eₕ) Hartree energy in eV انرژی هارتری در eV quantum of circulation quantum از circulation quantum of circulation times 2 quantum از circulation ضربدر 2 Rydberg constant (R∞) ثابت ریدبرگ (R∞) atomic mass unit-hartree relationship یکای جرم اتمی-hartree رابطه atomic mass unit-hertz relationship یکای جرم اتمی-hertz رابطه atomic mass unit-inverse meter relationship یکای جرم اتمی-inverse meter رابطه atomic mass unit-joule relationship یکای جرم اتمی-joule رابطه atomic mass unit-kelvin relationship یکای جرم اتمی-kelvin رابطه atomic mass unit-kilogram relationship یکای جرم اتمی-کیلوگرم رابطه atomic unit of 1st hyperpolarizability یکای اتمی از 1st hyperpolarizability atomic unit of 2nd hyperpolarizability یکای اتمی از 2nd hyperpolarizability atomic unit of charge (e) یکای اتمی از بار (e) atomic unit of charge density یکای اتمی از بار چگالی atomic unit of current یکای اتمی از جریان atomic unit of electric dipole moment یکای اتمی از الکتریکی dipole گشتاور atomic unit of electric field یکای اتمی از الکتریکی میدان atomic unit of electric field gradient یکای اتمی از الکتریکی میدان gradient atomic unit of electric polarizability یکای اتمی از الکتریکی polarizability atomic unit of electric potential یکای اتمی از الکتریکی پتانسیل atomic unit of electric quadrupole moment یکای اتمی از الکتریکی quadrبالاole گشتاور atomic unit of action یکای اتمی از action atomic unit of energy یکای اتمی از انرژی atomic unit of force یکای اتمی از نیرو atomic unit of length یکای اتمی از طول hertz-atomic mass unit relationship hertz-یکای جرم اتمی رابطه hertz-electron volt relationship hertz-الکترون volt رابطه hertz-hartree relationship hertz-hartree رابطه hertz-inverse meter relationship hertz-inverse meter رابطه hertz-joule relationship hertz-joule رابطه hertz-kelvin relationship hertz-kelvin رابطه hertz-kilogram relationship hertz-کیلوگرم رابطه hyperfine transition frequency of Cs-133 بسامد گذار ابرریز از Cs-133 inverse fine-structure constant (α�¹) inverse ثابت ساختار ریز (α�¹) inverse meter-atomic mass unit relationship inverse meter-یکای جرم اتمی رابطه inverse meter-electron volt relationship inverse meter-الکترون volt رابطه inverse meter-hartree relationship inverse meter-hartree رابطه inverse meter-hertz relationship inverse meter-hertz رابطه inverse meter-joule relationship inverse meter-joule رابطه inverse meter-kelvin relationship inverse meter-kelvin رابطه inverse meter-kilogram relationship inverse meter-کیلوگرم رابطه joule-atomic mass unit relationship joule-یکای جرم اتمی رابطه joule-electron volt relationship joule-الکترون volt رابطه joule-hertz relationship joule-hertz رابطه joule-hartree relationship joule-hartree رابطه joule-inverse meter relationship joule-inverse meter رابطه joule-kelvin relationship joule-kelvin رابطه joule-kilogram relationship joule-کیلوگرم رابطه kelvin-atomic mass unit relationship kelvin-یکای جرم اتمی رابطه kelvin-electron volt relationship kelvin-الکترون volt رابطه kelvin-hertz relationship kelvin-hertz رابطه kelvin-hartree relationship kelvin-hartree رابطه kelvin-inverse meter relationship kelvin-inverse meter رابطه kelvin-joule relationship kelvin-joule رابطه kelvin-kilogram relationship kelvin-کیلوگرم رابطه kilogram-atomic mass unit relationship کیلوگرم-یکای جرم اتمی رابطه kilogram-electron volt relationship کیلوگرم-الکترون volt رابطه kilogram-hertz relationship کیلوگرم-hertz رابطه kilogram-hartree relationship کیلوگرم-hartree رابطه kilogram-inverse meter relationship کیلوگرم-inverse meter رابطه kilogram-joule relationship کیلوگرم-joule رابطه kilogram-kelvin relationship کیلوگرم-kelvin رابطه lattice parameter of silicon (a) پارامتر شبکه از silicon (a) luminous efficacy بهره نوری natural unit of energy یکای طبیعی از انرژی natural unit of energy in MeV یکای طبیعی از انرژی در MeV natural unit of action (�) یکای طبیعی از action (�) natural unit of action in eV·s یکای طبیعی از action در eV·s natural unit of length یکای طبیعی از طول natural unit of mass یکای طبیعی از جرم natural unit of momentum یکای طبیعی از گشتاورum natural unit of momentum in MeV/c یکای طبیعی از گشتاورum در MeV/c natural unit of time یکای طبیعی از زمان natural unit of velocity یکای طبیعی از سرعت Rydberg constant times c in Hz ثابت ریدبرگ ضربدر c در Hz Rydberg constant times hc in eV ثابت ریدبرگ ضربدر hc در eV Rydberg constant times hc in J ثابت ریدبرگ ضربدر hc در J Fermi coupling constant ثابت ج�ت‌شدگی �رمی weak mixing angle زاویه اختلاط ضعی� W to Z mass ratio W به Z نسبت جرم Thomson cross section (σₑ) سطح مقطع تامسون (σₑ) electron mass (mₑ) الکترون جرم (mₑ) electron mass in u الکترون جرم در u electron mass energy equivalent (mₑ·c²) الکترون معادل انرژی جرم (mₑ·c²) electron mass energy equivalent in MeV الکترون معادل انرژی جرم در MeV reduced Compton wavelength کاهش‌یا�ته طول موج کامپتون classical electron radius (rₑ) classical الکترون شعاع (rₑ) electron charge to mass quotient الکترون بار به جرم quotient electron-deuteron magnetic moment ratio الکترون-دوترون نسبت گشتاور مغناطیسی electron-deuteron mass ratio الکترون-دوترون نسبت جرم electron g factor (gₑ) الکترون عامل g (gₑ) electron gyromagnetic ratio (γₑ) الکترون نسبت ژیرومغناطیسی (γₑ) electron gyromagnetic ratio in MHz/T الکترون نسبت ژیرومغناطیسی در MHz/T electron-helion mass ratio الکترون-هلیون نسبت جرم electron magnetic moment (μₑ) الکترون گشتاور مغناطیسی (μₑ) electron magnetic moment anomaly (aₑ) الکترون گشتاور مغناطیسی anomaly (aₑ) electron magnetic moment to Bohr magneton ratio الکترون گشتاور مغناطیسی به مگنتون بور نسبت electron magnetic moment to nuclear magneton ratio الکترون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت electron molar mass (Mₑ) الکترون جرم مولی (Mₑ) electron-muon magnetic moment ratio الکترون-میون نسبت گشتاور مغناطیسی electron-muon mass ratio الکترون-میون نسبت جرم electron-neutron magnetic moment ratio الکترون-نوترون نسبت گشتاور مغناطیسی electron-neutron mass ratio الکترون-نوترون نسبت جرم electron-proton magnetic moment ratio الکترون-پروتون نسبت گشتاور مغناطیسی electron-proton mass ratio الکترون-پروتون نسبت جرم electron relative atomic mass (Ar(e)) الکترون جرم اتمی نسبی (Ar(e)) electron-tau mass ratio الکترون-تاو نسبت جرم electron to alpha particle mass ratio الکترون به ذره آل�ا نسبت جرم electron to shielded helion magnetic moment ratio الکترون به پوشش‌یا�ته هلیون نسبت گشتاور مغناطیسی electron to shielded proton magnetic moment ratio الکترون به پوشش‌یا�ته پروتون نسبت گشتاور مغناطیسی electron-triton mass ratio الکترون-تریتون نسبت جرم electron volt-atomic mass unit relationship الکترون volt-یکای جرم اتمی رابطه electron volt-hartree relationship الکترون volt-hartree رابطه electron volt-hertz relationship الکترون volt-hertz رابطه electron volt-inverse meter relationship الکترون volt-inverse meter رابطه electron volt-joule relationship الکترون volt-joule رابطه electron volt-kelvin relationship الکترون volt-kelvin رابطه electron volt-kilogram relationship الکترون volt-کیلوگرم رابطه hartree-atomic mass unit relationship hartree-یکای جرم اتمی رابطه hartree-electron volt relationship hartree-الکترون volt رابطه muon Compton wavelength میون طول موج کامپتون muon-electron mass ratio میون-الکترون نسبت جرم muon g factor میون عامل g muon magnetic moment میون گشتاور مغناطیسی muon magnetic moment anomaly میون گشتاور مغناطیسی anomaly muon magnetic moment to Bohr magneton ratio میون گشتاور مغناطیسی به مگنتون بور نسبت muon magnetic moment to nuclear magneton ratio میون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت muon mass میون جرم muon mass energy equivalent میون معادل انرژی جرم muon mass energy equivalent in MeV میون معادل انرژی جرم در MeV muon mass in u میون جرم در u muon molar mass میون جرم مولی muon-neutron mass ratio میون-نوترون نسبت جرم muon-proton magnetic moment ratio میون-پروتون نسبت گشتاور مغناطیسی muon-proton mass ratio میون-پروتون نسبت جرم muon-tau mass ratio میون-تاو نسبت جرم reduced muon Compton wavelength کاهش‌یا�ته میون طول موج کامپتون reduced tau Compton wavelength کاهش‌یا�ته تاو طول موج کامپتون tau Compton wavelength تاو طول موج کامپتون tau-electron mass ratio تاو-الکترون نسبت جرم tau mass تاو جرم tau mass energy equivalent تاو معادل انرژی جرم tau mass in u تاو جرم در u tau molar mass تاو جرم مولی tau-muon mass ratio تاو-میون نسبت جرم tau-neutron mass ratio تاو-نوترون نسبت جرم tau-proton mass ratio تاو-پروتون نسبت جرم proton charge to mass quotient پروتون بار به جرم quotient proton Compton wavelength پروتون طول موج کامپتون proton-electron mass ratio پروتون-الکترون نسبت جرم proton g factor (gₚ) پروتون عامل g (gₚ) proton gyromagnetic ratio (γₚ) پروتون نسبت ژیرومغناطیسی (γₚ) proton gyromagnetic ratio in MHz/T پروتون نسبت ژیرومغناطیسی در MHz/T proton magnetic moment (μₚ) پروتون گشتاور مغناطیسی (μₚ) proton magnetic moment to Bohr magneton ratio پروتون گشتاور مغناطیسی به مگنتون بور نسبت proton magnetic moment to nuclear magneton ratio پروتون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت proton magnetic shielding correction پروتون مغناطیسی shielding correction proton mass (mₚ) پروتون جرم (mₚ) proton mass energy equivalent پروتون معادل انرژی جرم proton mass energy equivalent in MeV پروتون معادل انرژی جرم در MeV proton mass in u پروتون جرم در u proton molar mass (Mₚ) پروتون جرم مولی (Mₚ) proton-muon mass ratio پروتون-میون نسبت جرم proton-neutron magnetic moment ratio پروتون-نوترون نسبت گشتاور مغناطیسی proton-neutron mass ratio پروتون-نوترون نسبت جرم proton relative atomic mass (Ar(p)) پروتون جرم اتمی نسبی (Ar(p)) proton rms charge radius پروتون rms شعاع بار proton-tau mass ratio پروتون-تاو نسبت جرم reduced proton Compton wavelength کاهش‌یا�ته پروتون طول موج کامپتون shielded proton gyromagnetic ratio پوشش‌یا�ته پروتون نسبت ژیرومغناطیسی shielded proton gyromagnetic ratio in MHz/T پوشش‌یا�ته پروتون نسبت ژیرومغناطیسی در MHz/T shielded proton magnetic moment پوشش‌یا�ته پروتون گشتاور مغناطیسی shielded proton magnetic moment to Bohr magneton ratio پوشش‌یا�ته پروتون گشتاور مغناطیسی به مگنتون بور نسبت shielded proton magnetic moment to nuclear magneton ratio پوشش‌یا�ته پروتون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت neutron Compton wavelength نوترون طول موج کامپتون neutron-electron magnetic moment ratio نوترون-الکترون نسبت گشتاور مغناطیسی neutron-electron mass ratio نوترون-الکترون نسبت جرم neutron g factor (gₙ) نوترون عامل g (gₙ) neutron gyromagnetic ratio (γₙ) نوترون نسبت ژیرومغناطیسی (γₙ) neutron gyromagnetic ratio in MHz/T نوترون نسبت ژیرومغناطیسی در MHz/T neutron magnetic moment (μₙ) نوترون گشتاور مغناطیسی (μₙ) neutron magnetic moment to Bohr magneton ratio نوترون گشتاور مغناطیسی به مگنتون بور نسبت neutron magnetic moment to nuclear magneton ratio نوترون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت neutron mass (mₙ) نوترون جرم (mₙ) neutron mass energy equivalent نوترون معادل انرژی جرم neutron mass energy equivalent in MeV نوترون معادل انرژی جرم در MeV neutron mass in u نوترون جرم در u neutron molar mass (Mₙ) نوترون جرم مولی (Mₙ) neutron-muon mass ratio نوترون-میون نسبت جرم neutron-proton magnetic moment ratio نوترون-پروتون نسبت گشتاور مغناطیسی neutron-proton mass difference نوترون-پروتون جرم difference neutron-proton mass difference energy equivalent نوترون-پروتون جرم difference انرژی معادل neutron-proton mass difference energy equivalent in MeV نوترون-پروتون جرم difference انرژی معادل در MeV neutron-proton mass difference in u نوترون-پروتون جرم difference در u neutron-proton mass ratio نوترون-پروتون نسبت جرم neutron relative atomic mass (Ar(n)) نوترون جرم اتمی نسبی (Ar(n)) neutron-tau mass ratio نوترون-تاو نسبت جرم neutron to shielded proton magnetic moment ratio نوترون به پوشش‌یا�ته پروتون نسبت گشتاور مغناطیسی reduced neutron Compton wavelength کاهش‌یا�ته نوترون طول موج کامپتون deuteron-electron magnetic moment ratio دوترون-الکترون نسبت گشتاور مغناطیسی deuteron-electron mass ratio دوترون-الکترون نسبت جرم deuteron g factor دوترون عامل g deuteron magnetic moment دوترون گشتاور مغناطیسی deuteron magnetic moment to Bohr magneton ratio دوترون گشتاور مغناطیسی به مگنتون بور نسبت deuteron magnetic moment to nuclear magneton ratio دوترون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت deuteron mass دوترون جرم deuteron mass energy equivalent دوترون معادل انرژی جرم deuteron mass energy equivalent in MeV دوترون معادل انرژی جرم در MeV deuteron mass in u دوترون جرم در u deuteron molar mass دوترون جرم مولی deuteron-neutron magnetic moment ratio دوترون-نوترون نسبت گشتاور مغناطیسی deuteron-proton magnetic moment ratio دوترون-پروتون نسبت گشتاور مغناطیسی deuteron-proton mass ratio دوترون-پروتون نسبت جرم deuteron relative atomic mass (Ar(d)) دوترون جرم اتمی نسبی (Ar(d)) deuteron rms charge radius دوترون rms شعاع بار triton-electron mass ratio تریتون-الکترون نسبت جرم triton g factor (gₜ) تریتون عامل g (gₜ) triton magnetic moment (μₜ) تریتون گشتاور مغناطیسی (μₜ) triton magnetic moment to Bohr magneton ratio تریتون گشتاور مغناطیسی به مگنتون بور نسبت triton magnetic moment to nuclear magneton ratio تریتون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت triton mass (mₜ) تریتون جرم (mₜ) triton mass energy equivalent تریتون معادل انرژی جرم triton mass energy equivalent in MeV تریتون معادل انرژی جرم در MeV triton mass in u تریتون جرم در u triton molar mass (Mₜ) تریتون جرم مولی (Mₜ) triton-proton mass ratio تریتون-پروتون نسبت جرم triton relative atomic mass (Ar(t)) تریتون جرم اتمی نسبی (Ar(t)) triton to proton magnetic moment ratio تریتون به پروتون نسبت گشتاور مغناطیسی helion-electron mass ratio هلیون-الکترون نسبت جرم helion g factor (gₕ) هلیون عامل g (gₕ) helion magnetic moment (μₕ) هلیون گشتاور مغناطیسی (μₕ) helion magnetic moment to Bohr magneton ratio هلیون گشتاور مغناطیسی به مگنتون بور نسبت helion magnetic moment to nuclear magneton ratio هلیون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت helion mass (mₕ) هلیون جرم (mₕ) helion mass energy equivalent هلیون معادل انرژی جرم helion mass energy equivalent in MeV هلیون معادل انرژی جرم در MeV helion mass in u هلیون جرم در u helion molar mass (Mₕ) هلیون جرم مولی (Mₕ) helion-proton mass ratio هلیون-پروتون نسبت جرم helion relative atomic mass (Ar(h)) هلیون جرم اتمی نسبی (Ar(h)) helion shielding shift هلیون shielding shift shielded helion gyromagnetic ratio پوشش‌یا�ته هلیون نسبت ژیرومغناطیسی shielded helion gyromagnetic ratio in MHz/T پوشش‌یا�ته هلیون نسبت ژیرومغناطیسی در MHz/T shielded helion magnetic moment پوشش‌یا�ته هلیون گشتاور مغناطیسی shielded helion magnetic moment to Bohr magneton ratio پوشش‌یا�ته هلیون گشتاور مغناطیسی به مگنتون بور نسبت shielded helion magnetic moment to nuclear magneton ratio پوشش‌یا�ته هلیون گشتاور مغناطیسی به مگنتون هسته‌ای نسبت shielded helion to proton magnetic moment ratio پوشش‌یا�ته هلیون به پروتون نسبت گشتاور مغناطیسی shielded helion to shielded proton magnetic moment ratio پوشش‌یا�ته هلیون به پوشش‌یا�ته پروتون نسبت گشتاور مغناطیسی alpha particle mass ذره آل�ا جرم alpha particle mass in u ذره آل�ا جرم در u alpha particle mass energy equivalent ذره آل�ا معادل انرژی جرم alpha particle mass energy equivalent in MeV ذره آل�ا معادل انرژی جرم در MeV alpha particle-electron mass ratio ذره آل�ا-الکترون نسبت جرم alpha particle-proton mass ratio ذره آل�ا-پروتون نسبت جرم alpha particle rms charge radius ذره آل�ا rms شعاع بار alpha particle molar mass ذره آل�ا جرم مولی alpha particle relative atomic mass (Ar(α)) ذره آل�ا جرم اتمی نسبی (Ar(α)) atomic mass constant (mᵤ) atomic جرم ثابت (mᵤ) Avogadro constant ثابت آووگادرو Boltzmann constant (k) ثابت بولتسمان (k) Boltzmann constant in eV/K ثابت بولتسمان در eV/K Boltzmann constant in Hz/K ثابت بولتسمان در Hz/K Boltzmann constant in inverse meter per kelvin ثابت بولتسمان در inverse meter بر kelvin electron volt (eV) الکترون volt (eV) Faraday constant (F) ثابت �ارادی (F) first radiation constant (c�) first radiation ثابت (c�) first radiation constant for spectral radiance first radiation ثابت for spectral رادیانce molar gas constant (R) ثابت گاز مولی (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) ثابت لوشمیت (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) ثابت لوشمیت (n₀, 273.15 K, 101.325 kPa) molar Planck constant مولی ثابت پلانک second radiation constant (c₂) ثانیه radiation ثابت (c₂) Stefan-Boltzmann constant (σ) ثابت است�ان-بولتسمان (σ) lattice spacing of ideal Si (d₂₂₀) lattice spacing از ideal Si (d₂₂₀) atomic mass constant energy equivalent atomic جرم ثابت انرژی معادل atomic mass constant energy equivalent in MeV atomic جرم ثابت انرژی معادل در MeV atomic mass unit-electron volt relationship یکای جرم اتمی-الکترون volt رابطه molar mass constant (Mᵤ) جرم مولی ثابت (Mᵤ) molar mass of carbon-12 جرم مولی از carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) مولی volume از گاز ایده‌آل (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) مولی volume از گاز ایده‌آل (273.15 K, 101.325 kPa) molar volume of silicon مولی volume از silicon Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode ثابت (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode ثابت (1 K, 101.325 kPa) Wien frequency displacement law constant Wien بسامد displacement law ثابت Wien wavelength displacement law constant Wien طول موج displacement law ثابت standard atmosphere (atm) اتمس�ر استاندارد (atm) standard-state pressure (p°) �شار حالت استاندارد (p°) Angstrom star (Å*) آنگستروم star (Å*) Copper x unit یکای ایکس مس Molybdenum x unit یکای ایکس مولیبدن atomic unit of magnetizability یکای اتمی از magnetizability atomic unit of mass (mₑ) یکای اتمی از جرم (mₑ) atomic unit of momentum یکای اتمی از گشتاورum atomic unit of permittivity یکای اتمی از permittivity atomic unit of time یکای اتمی از زمان atomic unit of velocity یکای اتمی از سرعت hartree-hertz relationship hartree-hertz رابطه hartree-inverse meter relationship hartree-inverse meter رابطه hartree-joule relationship hartree-joule رابطه hartree-kelvin relationship hartree-kelvin رابطه hartree-kilogram relationship hartree-کیلوگرم رابطه shielding difference of d and p in HD shielding difference از d and p در HD shielding difference of t and p in HT shielding difference از t and p در HT pi (π) پی (π) Euler's number (e) عدد اویلر (e) golden ratio (φ) نسبت طلایی (φ) Euler-Mascheroni constant (γ) ثابت اویلر-ماسکرونی (γ) nominal solar radius nominal خورشیدی شعاع nominal solar total irradiance nominal خورشیدی total irرادیانce nominal solar luminosity nominal خورشیدی luminosity nominal solar effective temperature nominal خورشیدی effective دما nominal solar mass parameter nominal خورشیدی پارامتر جرم nominal terrestrial equatorial radius nominal زمینی شعاع استوایی nominal terrestrial polar radius nominal زمینی شعاع قطبی nominal terrestrial mass parameter nominal زمینی پارامتر جرم nominal jovian equatorial radius nominal مشتری شعاع استوایی nominal jovian polar radius nominal مشتری شعاع قطبی nominal jovian mass parameter nominal مشتری پارامتر جرم average value of one minus the rate of TCG relative to TCB average value از one minus the rate از TCG relative به TCB solar mass parameter (TCB-compatible) خورشیدی پارامتر جرم (TCB-compatible) solar mass parameter (TDB-compatible) خورشیدی پارامتر جرم (TDB-compatible) equatorial radius of the Earth (TT-compatible) شعاع استوایی از the زمین (TT-compatible) dynamical form factor of the Earth dynamical form factor از the زمین time rate of change in the dynamical form factor of the Earth زمان rate از change در the dynamical form factor از the زمین geocentric gravitational constant (TCB-compatible) geocentric gravitational ثابت (TCB-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational ثابت (TT-compatible) geocentric gravitational constant (TDB-compatible) geocentric gravitational ثابت (TDB-compatible) potential of the geoid پتانسیل از the geoid nominal mean angular velocity of the Earth (TT-compatible) nominal mean angular سرعت از the زمین (TT-compatible) ratio mass of the Moon to the Earth نسبت جرم از the ماه به the زمین ratio of the mass of the Sun to Mercury نسبت از the جرم از the خورشید به عطارد ratio of the mass of the Sun to Venus نسبت از the جرم از the خورشید به زهره ratio of the mass of the Sun to Mars نسبت از the جرم از the خورشید به مریخ ratio of the mass of the Sun to Jupiter نسبت از the جرم از the خورشید به مشتری ratio of the mass of the Sun to Saturn نسبت از the جرم از the خورشید به زحل ratio of the mass of the Sun to Uranus نسبت از the جرم از the خورشید به اورانوس ratio of the mass of the Sun to Neptune نسبت از the جرم از the خورشید به نپتون ratio of the mass of the Sun to (134340) Pluto نسبت از the جرم از the خورشید به (134340) پلوتو ratio of the mass of the Sun to (136199) Eris نسبت از the جرم از the خورشید به (136199) Eris ratio of the mass of (1) Ceres to the Sun نسبت از the جرم از (1) Ceres به the خورشید ratio of the mass of (2) Pallas to the Sun نسبت از the جرم از (2) Pallas به the خورشید ratio of the mass of (4) Vesta to the Sun نسبت از the جرم از (4) Vesta به the خورشید mean obliquity of the ecliptic at J2000.0 mean obliquity از the ecliptic at J2000.0 Electromagnetic الکترومغناطیس Compton wavelength طول موج کامپتون Astronomy نجومی ConstantsWidget Domain دامنه Subdomain زیر دامنه No match found نتیجه‌ای پیدا نشد Name نام Value مقدار Unit واحد Search جستجو All همه CustomKeypadDialog Custom Keypad ص�حه‌کلید س�ارشی Rows: ردی�‌ها: Columns: ستون‌ها: Copy preset: کپی پیش‌تنظیم: Basic پایه Scientific (wide) علمی (عریض) Scientific (narrow) علمی (باریک) Apply اعمال Row ردی� Column ستون Label برچسب Behavior ر�تار Text متن DiagnosticsDialog App Diagnostics عیب‌یابی برنامه Copy to Clipboard کپی در کلیپ‌بورد Editor Unit واحد User unit یکای کاربر User function تابع کاربر Argument آرگومان Current result:<br/>%1 نتیجه �علی:<br/>%1 Selection result:<br/>%1 نتیجه انتخاب:<br/>%1 Selection result: n/a نتیجه انتخاب: n/a Selection result: %1 نتیجه انتخاب: %1 second ثانیه metre متر kilogram کیلوگرم mole مول radian رادیان steradian استرادیان degree Celsius درجه سلسیوس cubic metre مکعب متر cubic millimetre میلی‌متر مکعب cubic centimetre سانتی‌متر مکعب cubic decimetre دسی‌متر مکعب cubic kilometre کیلومتر مکعب square millimetre میلی‌متر مربع square kilometre کیلومتر مربع square metre مربع متر minute دقیقه hour ساعت day روز astronomical unit یکای نجومی degree درجه arcminute دقیقه قوسی arcsecond ثانیه قوسی milliarcsecond میلی‌ثانیه قوسی microarcsecond میکروثانیه قوسی hectare هکتار litre لیتر tonne تن Dalton دالتون electronvolt الکترون‌ولت Angstrom آنگستروم atmosphere اتمس�ر atomic mass unit یکای جرم اتمی British thermal unit یکای حرارتی بریتانیا calorie کالری carat قیراط cup �نجان cup (Imperial) �نجان (امپراتوری) cup (Japanese) �نجان (ژاپنی) cup (US) �نجان (آمریکا) degree Fahrenheit درجه �ارنهایت fathom �اتوم fluid ounce (Imperial) اونس مایع (امپراتوری) fluid ounce (US) اونس مایع (آمریکا) fluid dram (Imperial) درم مایع (امپراتوری) fluid dram (US) درم مایع (آمریکا) foot �وت square foot مربع �وت cubic foot مکعب �وت gallon (Imperial) گالن (امپراتوری) gallon (US) گالن (آمریکا) gill (Imperial) گیل (امپراتوری) gill (US) گیل (آمریکا) gradian گرادیان grain گرین gram گرم Hartley هارتلی Hartree energy unit یکای انرژی هارتری horsepower اسب بخار inch اینچ square inch مربع اینچ cubic inch مکعب اینچ karat عیار knot گره lightminute دقیقه نوری lightsecond ثانیه نوری lightyear سال نوری long ton تن بلند mile مایل square mile مربع مایل cubic mile مکعب مایل mile per hour مایل بر ساعت kilometre per hour کیلومتر بر ساعت nautical mile مایل دریایی ounce اونس parsec پارسک pint (Imperial) پاینت (امپراتوری) pint (US) پاینت (آمریکا) pound پوند pounds per square inch پوند بر اینچ مربع quart (Imperial) کوارت (امپراتوری) quart (US) کوارت (آمریکا) oil barrel بشکه ن�ت beer barrel (US) بشکه آبجو (آمریکا) square yard مربع یارد cubic yard مکعب یارد short ton تن کوتاه tablespoon قاشق غذاخوری tablespoon (Australian) قاشق غذاخوری (استرالیا) tablespoon (Imperial) قاشق غذاخوری (امپراتوری) tablespoon (US) قاشق غذاخوری (آمریکا) dessert spoon قاشق دسرخوری teaspoon قاشق چای‌خوری teaspoon (Imperial) قاشق چای‌خوری (امپراتوری) teaspoon (US) قاشق چای‌خوری (آمریکا) turn دور revolution چرخش revolution per minute دور بر دقیقه week ه�ته kilowatt hour کیلووات ساعت millimetre of mercury میلی‌متر جیوه yard یارد Julian century قرن ژولیانی Julian year سال ژولیانی sidereal year سال نجومی tropical year سال اعتدالی Evaluator invalid expression نامعتمبر division by zero تقسیم بر ص�ر too time consuming - computation was rejected بیش از حد زمان‌بر است - محاسبه رد شد dimension mismatch - quantities with different dimensions cannot be compared, added, etc. عدم تطابق ب�عد - کمیت‌هایی با ب�عدهای مت�اوت را نمی‌توان مقایسه، جمع و مانند آن کرد. invalid dimension - operation might require dimensionless arguments ب�عد نامعتبر - عمل ممکن است به آرگومان‌های بی‌ب�عد نیاز داشته باشد Computation aborted - encountered numerical instability محاسبه متوق� شد - ناپایداری عددی رخ داد invalid dimension - function might require dimensionless arguments ب�عد نامعتبر - تابع ممکن است به آرگومان‌های بی‌ب�عد نیاز داشته باشد error خطا unit must not be zero یکا نباید ص�ر باشد Conversion failed - dimension mismatch تبدیل نامو�ق بود - عدم تطابق ب�عد unknown function or variable عملکرد ناشناخته یا متغیر recursion not supported بازگشت پشتیبانی نمی‌شود cannot operate on a NaN نمی‌توان روی NaN عملیات انجام داد underflow - tiny result is out of SpeedCrunch's number range نتیجه بدست امده خارج از محدود توانایی های نرم ا�زار می باشد(بسیار کوچک است) overflow - huge result is out of SpeedCrunch's number range عدد بدست آمده بسیار بزرگ است و خارج از توانایی های نرم ا�زار می باشد overflow - logic result exceeds maximum of 256 bits بیش از اندازه توانایی نرم ا�زار می باشد.عدد بدست آمده بیش رقم 256 رقم دارد. overflow - integer result exceeds maximum limit for integers نرم ا�زار توانایی انجام این تقسیم را به علت بزرگی اعداد ندارد operation is not defined for these arguments این عمل برای این آرگومان‌ها تعری� نشده است wrong number of arguments تعداد نادرست آرگومان does not take NaN as an argument NaN را به عنوان آرگومان نمی‌پذیرد result out of range نتیجه خارج از محدوده undefined for argument domain دامنه بحث تعری� نشده computation too expensive محاسبات سنگین internal error, please report a bug خطای داخلی، لط�ا گزارش اشکال syntax error خطای نحوی conversion target must be a unit مقصد تبدیل باید یک یکا باشد unknown unit یکای ناشناخته %1 is a reserved name, please choose another %1 مح�وظ می باشد انتخاب کنید، لط�ا پوشه دیگری انتخاب کنید %1 is a global user definition and cannot be overridden in this session. %1 یک تعری� سراسری کاربر است و در این نشست نمی‌توان آن را بازنویسی کرد. %1 is a variable name, please choose another or delete the variable %1نام متغیر است، لط�ا پوشه دیگری انتخاب کنید یا حذ� متغیر argument %1 is used more than once آرگومان %1 برای بیش از یک بار است�اده می شود %1 is a built-in unit name, please choose another %1 نام یکای داخلی است؛ لط�اً نام دیگری انتخاب کنید %1 is a user function name, please choose another or delete the function %1نام تابع کاربر است، لط�ا پوشه دیگری انتخاب کنید یا حذ� تابع FunctionRepo max; trials; probability حداکثر; محاکمات; احتمال trials; probability محاکمات; احتمال hits; trials; probability بازدید; محاکمات; احتمال max; total; hits; trials حداکثر; مجموع; بازدید; محاکمه total; hits; trials مجموع; بازدید; محاکمه count; total; hits; trials تعداد د�عات مشاهده; مجموع; بازدید; محاکمه dividend; divisor بخش پذیر:مقسوم علیه x; exponent_bits; significand_bits [; exponent_bias] x؛ بیت‌های نما؛ بیت‌های مانتیسا [؛ بایاس نما] base; x پایه؛ x value; modulo مقدار؛ پیمانه base; exponent; modulo پایه؛ نما؛ پیمانه events; average_events رویدادها؛ میانگین_رویدادها average_events میانگین رویدادها x [; precision] x [؛ دقت] Absolute Value ارزش مطلق Absolute Deviation انرحا� از معیار Arc Cosine کوسینوس معکوس Logical AND منطقی و Area Hyperbolic Cosine منطقه کسینوس هذلولی Area Hyperbolic Sine ناحیه سینوس هذلولی Area Hyperbolic Tangent منطقه تانژانت هذلولی Arc Sine سینوس معکوس Arc Tangent تانژانت معکوس Arc Tangent with two Arguments تانژانت معکوس با دو آرگومان Average (Arithmetic Mean) میانگین(میانگین حسابی) Binomial Cumulative Distribution Function تابع توزیع دوجمله ای تجمعی Binomial Distribution Mean ميانگين توزیع دوجمله ای Binomial Probability Mass Function تابع جرم احتمالات علمی Binomial Distribution Variance واریانس توزیع دوجمله ای Cube Root ریشه مکعب Complex Conjugate مزدوج مختلط Cosine کسینوس Hyperbolic Cosine کسینوس هذلولی Cotangent کتانژانت Cosecant کسکانت Convert Unix timestamp to Date تبدیل برچسب زمانی یونیکس به تاریخ Degrees of Arc درجه از کمان Error Function خطای تابع Complementary Error Function خطا در تابع مکمل Exponential تابع نمایی Fractional Part قسمت اعشاری Extension of Factorials [= (x-1)!] تعمیم �اکتوریل‌ها [= (x-1)!] Greatest Common Divisor بزرگ ترین مقسوم علیه مشترک(ب.م.م) Geometric Mean میانگین هندسی Gradians of arc گرادیان‌های کمان Hypergeometric Cumulative Distribution Function تابع تجمعی هندسی Hypergeometric Distribution Mean ميانگين توزیع هندسی Hypergeometric Probability Mass Function تابع جرم احتمالات هندسی Hypergeometric Distribution Variance واریانس توزیع هندسی Integer Quotient خارج قسمت صحیح Integer Part قسمت عدد صحیح Imaginary Part بخش موهومی Decode IEEE-754 Binary Value رمزگشایی مقدار دودویی IEEE-754 Encode IEEE-754 Binary Value رمزگذاری مقدار دودویی IEEE-754 Decode 16-bit Half-Precision Value رمزگشایی مقدار ۱۶ بیتی نیم‌دقت Encode 16-bit Half-Precision Value رمزگذاری مقدار ۱۶ بیتی نیم‌دقت Decode 32-bit Single-Precision Value رمزگشایی مقدار ۳۲ بیتی تک‌دقت Encode 32-bit Single-Precision Value رمزگذاری مقدار ۳۲ بیتی تک‌دقت Decode 64-bit Double-Precision Value رمزگشایی مقدار ۶۴ بیتی دقت دوگانه Encode 64-bit Double-Precision Value رمزگذاری مقدار ۶۴ بیتی دقت دوگانه Decode 128-bit Quad-Precision Value رمزگشایی مقدار ۱۲۸ بیتی دقت چهارگانه Encode 128-bit Quad-Precision Value رمزگذاری مقدار ۱۲۸ بیتی دقت چهارگانه Binary Logarithm لگاریتم دودویی(باینری) Common Logarithm لگاریتم اعشاری Natural Logarithm لگاریتم طبیعی Logarithm to Arbitrary Base لگاریتم به پایه های دلخواه Mask to a bit size ماسک به اندازه ذره Maximum حداکثر Median Value (50th Percentile) میانه ارزش Minimum حداقل Modulo ماژول Euclidean Modulo پیمانه اقلیدسی Modular Exponentiation توان‌رسانی پیمانه‌ای Combination (Binomial Coefficient) ترکیبی (ضريب دوجمله ای) Logical NOT منطقی نیست Permutation (Arrangement) جایگشت (تنظیم) Convert to Binary Representation تبدیل به دو دویی یا باینوری Arithmetic حساب Chemistry شیمی Complex مختلط Combinatorics ترکیبیات Probability احتمال Statistics آمار Aggregation تجمیع Random تصاد�ی Base conversion تبدیل مبنا Number formatting قالب‌بندی عدد Integer arithmetic حساب صحیح Special functions توابع ویژه Exponential & Logarithmic نمایی و لگاریتمی Angle conversion تبدیل زاویه Trigonometry مثلثات Bitwise بیتی Floating point ممیز شناور Date & Time تاریخ و زمان Linear algebra جبر خطی unix_timestamp; x hours offset to GMT unix_timestamp؛ x ساعت اختلا� با GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss؛ x ساعت اختلا� با GMT [digits] [رقم‌ها] max [; min] بیشینه [؛ کمینه] List Literal ثابت �هرست Convert to Padded Binary Representation تبدیل به نمایش دودویی هم‌طول Round Toward +∞ (Ceiling) گرد کردن به سوی +∞ (سق�) Cosine plus Imaginary Sine کسینوس به‌علاوه سینوس موهومی Convert to Cis Complex Form تبدیل به �رم مختلط cis Matrix Column Count ماتریس ستون شمارش Population Correlation Matrix (n) جامعه همبستگی ماتریس (n) Sample Correlation Matrix (n-1) نمونه همبستگی ماتریس (n-1) Count شمارش Population Covariance Matrix (n) جامعه کوواریانس ماتریس (n) Sample Covariance Matrix (n-1) نمونه کوواریانس ماتریس (n-1) Cross Product ضرب برداری Convert Date to Unix timestamp تبدیل تاریخ به برچسب زمانی یونیکس Convert to Decimal Representation تبدیل به اعشاری Determinant دترمینان Convert to Sexagesimal Notation تبدیل به شصتگانی نمادگذاری Dot Product ضرب داخلی Convert to Engineering Notation تبدیل به مهندسی نمادگذاری Convert to Exponential Complex Form تبدیل به �رم نمایی مختلط Round Toward −∞ (Floor) گرد کردن به سوی −∞ (ک�) Flatten Matrix تخت کردن ماتریس Least Common Multiple کوچک‌ترین مضرب مشترک Convert to Hexadecimal Representation تبدیل به هگزادسیمال Convert to Padded Hexadecimal Representation تبدیل به نمایش شانزده‌تایی هم‌طول Inverse Matrix ماتریس معکوس Round to 16-bit Half-Precision Value گرد کردن به مقدار ۱۶ بیتی نیم‌دقت Round to 32-bit Single-Precision Value گرد کردن به مقدار ۳۲ بیتی تک‌دقت Round to 64-bit Double-Precision Value گرد کردن به مقدار ۶۴ بیتی دقت دوگانه Round to 128-bit Quad-Precision Value گرد کردن به مقدار ۱۲۸ بیتی دقت چهارگانه Residual from 16-bit Half-Precision Rounding باقیمانده گرد کردن ۱۶ بیتی نیم‌دقت Residual from 32-bit Single-Precision Rounding باقیمانده گرد کردن ۳۲ بیتی تک‌دقت Residual from 64-bit Double-Precision Rounding باقیمانده گرد کردن ۶۴ بیتی دقت دوگانه Residual from 128-bit Quad-Precision Rounding باقیمانده گرد کردن ۱۲۸ بیتی دقت چهارگانه Substance Mass جرم ماده Molarity مولاریته Molar Mass جرم ماه Median Absolute Deviation انحرا� مطلق از میانه Mean میانگین Numerical Value of Quantity مقدار عددی کمیت Random Decimal Number عدد دهدهی تصاد�ی Random Integer Number عدد صحیح تصاد�ی Convert to Rational Representation تبدیل به نمایش گویا Convert to Octal Representation تبدیل به اوکتالی ای هشتایی Convert to Padded Octal Representation تبدیل به نمایش هشت‌تایی هم‌طول Vector or Matrix Norm نرم بردار یا ماتریس Logical OR یا منطقی Population Count (Hamming Weight) شمارش بیت‌های یک (وزن همینگ) Phase of Complex Number �از عدد مختلط Poissonian Cumulative Distribution Function تابع توزیع تجمعی پواسون Poissonian Distribution Mean میانگین توزیع پواسون Poissonian Probability Mass Function تابع جرم احتمال پواسون Poissonian Distribution Variance واریانس توزیع پواسون Convert to Phasor Complex Form تبدیل به �رم �یزوری مختلط Convert to Rectangular Complex Form تبدیل به �رم مستطیلی مختلط Round Half Away from Zero گرد کردن نیمه دور از ص�ر Round Half Even گرد کردن نیمه به زوج Nth Root ریشهٔ nام Convert to Scientific Notation تبدیل به علمی نمادگذاری Matrix Row Count ماتریس ردی� شمارش List or Matrix Shape شکل �هرست یا ماتریس Summation جمع Population Standard Deviation (n) انحرا� معیار جامعه (n) Sample Standard Deviation (n-1) انحرا� معیار نمونه (n-1) Round Toward Zero (Truncation) گرد کردن به سوی ص�ر (برش) Matrix Trace رد ماتریس Transpose Matrix ترانهاده ماتریس Population Variance (n) واریانس جامعه (n) Sample Variance (n-1) واریانس نمونه (n-1) Product حاصل Radians رادیان Matrix Rank رتبه ماتریس Real Part بخش حقیقی Secant قطع کردن Arithmetic Shift Left ریاضی شی�ت چپ Arithmetic Shift Right ریاضی شی�ت راست Signum معنا Sine سینوس Hyperbolic Sine سینوس هذلولی Square Root ریشه مربع Sum جمع Tangent مماس Convert to Trigonometric Complex Form تبدیل به �رم مثلثاتی مختلط Turns دور Hyperbolic Tangent مماس هذلولی Sign-extend a value نشانه گسترش ارزش Logical XOR XOR منطقی FunctionsWidget Domain دامنه All همه Name نام Search جستجو No match found نتیجه‌ای پیدا نشد Identifier شناسه HistoryWidget Remove All Calculations Above حذ� همه محاسبه‌های بالا Remove This Calculation حذ� اين محاسبه Remove All Calculations Below حذ� همه محاسبه‌های پایین Keypad Inverse cosine کسینوس معکوس The last result آخرین نتیجه Inverse sine سینوس معکوس Inverse tangent تانژانت معکوس Evaluate expression ارزیابی عبارت Division تقسیم Multiplication ضرب Subtraction ت�ریق Addition جمع Clear expression پاک کردن عبارت Cosine کسینوس Backspace پس‌بر Scientific notation نمایش علمی Exponential تابع نمایی Factorial �اکتوریل Natural logarithm لگاریتم طبیعی Left parenthesis پرانتز چپ Nth root ریشهٔ nام Argument separator جداکنندهٔ آرگومان‌ها Square توان دوم Common logarithm لگاریتم دهدهی Modulo ماژول Contextual percentage درصد زمینه‌ای Power توان Right parenthesis پرانتز راست Sine سینوس Square root ریشه مربع Tangent مماس Pi پی Decimal separator جداساز اعشاری MainWindow Radian رادیان Degree درجه Gradian گرادیان Binary باینری Octal هشتایی Hexadecimal شانزده‌تایی Sexagesimal شصت‌گانی Engineering decimal دهدهی مهندسی Scientific decimal دهدهی علمی &Import... &وارد کردن... &Quit &خروج Clear E&xpression پاک کردن &عبارت Clear &History پاک کردن &تاریخچه &Copy &کپی &Paste &چسباندن &Select Expression &انتخاب عبارت &Constants &ثابت‌ها &Functions &توابع &History &تاریخچه &Status Bar &نوار وضعیت Bitfield میدان بیتی Use&r Functions توابع &کاربر &Degree &درجه &Radian &رادیان &Gradian &گرادیان Re&volution &چرخش Auto-Insert a&ns درج خودکار a&ns Automatic &Completion تکمیل &خودکار &Built-in Functions &توابع داخلی Built-in &Variables &متغیرهای داخلی User &Functions ت&وابع کاربر User Va&riables مت&غیرهای کاربر Open a Private Tab on Startup باز کردن زبانهٔ خصوصی هنگام راه‌اندازی Open and focus a new private tab whenever SpeedCrunch starts. هر بار که SpeedCrunch شروع می‌شود، زبانهٔ خصوصی تازه‌ای باز و �عال شود. Syntax &Highlighting برجسته‌سازی &نحو Group Digits in &Input &گروه‌بندی رقم‌های ورودی Automatic Input &Adjustments &تنظیم خودکار ورودی Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. عملگرها، �اصله‌ها، پرانتزها و توان‌ها خودکار تنظیم شوند و ورودی به نویسه‌های معتبر محدود شود. Group input digits using the selected number format. رقم‌های ورودی بر اساس قالب عددی انتخاب‌شده گروه‌بندی شوند. &Blinking Cursor &مکان‌نمای چشمک‌زن Blink the cursor in the expression editor. مکان‌نما در ویرایشگر عبارت چشمک بزند. &Escape Clears Editor &Escape ویرایشگر را پاک می‌کند Clear the focused expression editor with Escape after dismissing any popup or preview. پس از بستن پنجره‌های بازشو یا پیش‌نمایش‌ها، ویرایشگر عبارت �عال با Escape پاک شود. Keep Expression After Evaluation نگه داشتن عبارت پس از محاسبه Copy New Results Automatically کپی خودکار نتایج تازه &Comma &کاما &System Default پیش‌�رض &سیستم &Dot &نقطه Dot &And Comma نقطه &و کاما Toward +∞ (&ceil) به سوی +∞ (&ceil) Toward −∞ (&floor) به سوی −∞ (&floor) &Binary &دودویی &Engineering &مهندسی &Hexadecimal &شانزده‌تایی &Octal &هشتایی &Scientific &علمی User &Manual &راهنمای کاربر Issues and &Feedback &مشکلات و بازخورد &Donate &کمک مالی &About SpeedCrunch &درباره SpeedCrunch App Diag&nostics &عیب‌یابی برنامه S&plit ت&قسیم Angle &Mode &حالت زاویه &Complex Form &شکل مختلط New Tab زبانه جدید Constants ثابت‌ها Functions توابع History تاریخچه User Functions توابع کاربر &Font... &�ونت... &Language... &زبان... &Session &نشست &Edit &ویرایش &View &نمایش Se&ttings &تنظیمات &Decimal &دهدهی &Keypad &ص�حه‌کلید Always on &Top همیشه در &بالا Disabled غیر�عال Small Space �ضای کوچک Medium Space �ضای متوسط Large Space �ضای بزرگ &0 Digits &۰ رقم &15 Digits &۱۵ رقم &2 Digits &۲ رقم &3 Digits &۳ رقم &50 Digits &۵۰ رقم &8 Digits &۸ رقم &Sexagesimal &شصت‌گانی Reset All Settings... بازنشانی همهٔ تنظیمات... &System &سیستم SpeedCrunch &Theme &پوستهٔ SpeedCrunch &Classic &کلاسیک &Modern &مدرن Context Help راهنمای زمینه‌ای &Help &راهنما Error خطا Can't read from file %1 نمی‌توان از پرونده %1 خواند Import Session وارد کردن نشست Close Session بستن نشست Angle Mode: حالت زاویه: Notation: نمادگذاری: Precision: دقت: Turn دور Revolution چرخش Fixed-point decimal دهدهی ممیز ثابت Rational گویا Automatic decimal دهدهی خودکار Automatic خودکار User &Definitions... &تعری�‌های کاربر... New &Tab &زبانه جدید New &Private Tab زب&انهٔ خصوصی تازه Keep نگه داشتن Make Private... خصوصی کردن... New &Window &پنجره جدید &Open... &باز کردن... &Rename... &تغییر نام... Clo&ne... &همسان‌سازی... &Close Tab ب&ستن زبانه Reopen Clo&sed Tab باز &کردن دوبارهٔ زبانهٔ بسته‌شده Open Sessions &Folder باز کردن &پوشه نشست‌ها &Undo &واگرد &Redo ا&زنو Cu&t &برش Copy &Last Result ک&پی آخرین نتیجه &Wrap in Parentheses &قرار دادن در پرانتز Full Scr&een Mode &حالت تمام‌ص�حه &Basic &پایه &Scientific (wide) &علمی (عریض) Scientific (narrow) علمی (باریک) &Custom... &س�ارشی... Main &Menu &منوی اصلی User &Variables &متغیرهای کاربر &Left &چپ &Right &راست &Up &بالا &Down &پایین Close Pa&ne &بستن قاب User &Units &یکاهای کاربر &Turn &دور If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. اگر عبارت جدیدی با +، -، * یا / شروع شود، SpeedCrunch ابتدا "ans" را درج می‌کند. &Accept with Enter &پذیرش با Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. پیشنهاد �علی تکمیل خودکار را با Enter بپذیرید، بدون اینکه ابتدا آن را با کلیدهای جهت‌نما انتخاب کنید. &Units &یکاها Show Live Result &Preview نمایش &پیش‌نمایش زنده نتیجه Save &Window Position on Exit ذخیره موقعیت &پنجره هنگام خروج Hover Highlighting برجسته‌سازی هنگام شناور شدن Group Integer Part Only �قط بخش صحیح را گروه‌بندی کن Number Format... قالب عدد... Notation && Precision... نمادگذاری و دقت... After pressing Enter, keep the entered expression selected in the editor. پس از �شردن Enter، عبارت واردشده در ویرایشگر انتخاب‌شده باقی بماند. Never هرگز Always همیشه Only for Single-Line Expressions �قط برای عبارت‌های تک‌خطی Simplify Displayed Expressions ساده‌سازی عبارت‌های نمایش‌داده‌شده History Size &Limit... &محدودیت اندازه تاریخچه... Remove Trailing &Zeroes &حذ� ص�رهای انتهایی Nearest, Half &Away (round) نزدیک‌ترین، نیمه &دور (round) Nearest, Half &Even (roundeven) نزدیک‌ترین، نیمه &زوج (roundeven) Toward &Zero (trunc) به سوی &ص�ر (برش) &Fixed-Point &ممیز ثابت &Rational &گویا &Exponential (m·s�¹) &نمایی (m·s�¹) &Fractional (m/s) &کسری (m/s) &Rectangular (a + bi) &مستطیلی (a + bi) Exponential (re�ᶿ) نمایی (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) مثلثاتی (r(cos θ + i·sin θ)) Phasor (r∠θ) �یزور (r∠θ) &Theme... &پوسته... Check for &Updates بررسی &به‌روزرسانی‌ها Source Code کد منبع &Zoom &بزرگ‌نمایی &Results &نتایج Unit Notation یکا نمادگذاری Rounding Mode حالت گرد کردن &Notation &نمادگذاری &Imaginary Unit یکای &موهومی &Window &پنجره &Editing &ویرایش A&utocomplete تکمیل &خودکار Up/Down Arrow History تاریخچه با پیکان بالا/پایین &Appearance &ظاهر &Menus &منوها &Docks پن&ل‌های قابل اتصال &Input and Results &ورودی و نتایج &Disabled &غیر�عال &Disable &غیر�عال کردن Close preview بستن پیش‌نمایش Rename... تغییر نام... Clone... همسان‌سازی... Close Tab بستن زبانه New Private Tab زبانهٔ خصوصی تازه Open... باز کردن... Reopen Closed Tab باز کردن دوبارهٔ زبانهٔ بسته‌شده Split تقسیم Left چپ Right راست Up بالا Down پایین Clear پاک کردن Delete حذ� %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 نشست خصوصی: محتوا هنگام بسته شدن دور ریخته می‌شود. برای تبدیل به نشست عادی، نشست > نگه داشتن را انتخاب کنید. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [خصوصی] Reset All Settings بازنشانی همهٔ تنظیمات Reset all settings to their default values? همهٔ تنظیمات به مقدارهای پیش‌�رض بازنشانی شوند؟ This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. این شامل ظاهر، ویرایش، قالب‌های نتیجه و ترجیحات پنجره‌هاست. محاسبات، نشست‌های باز و تعری�‌های کاربر نگه داشته می‌شوند. The settings file could not be written. نوشتن پروندهٔ تنظیمات ممکن نشد. Clear this session's calculations, unfinished expression, variables, functions, and units? محاسبات، عبارت ناتمام، متغیرها، توابع و یکاهای این نشست پاک شوند؟ Global user definitions are kept. تعری�‌های سراسری کاربر نگه داشته می‌شوند. Make Session Private خصوصی کردن نشست The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. نشست ذخیره‌شدهٔ %1 حذ� خواهد شد. محتوای آن در نشستی خصوصی باز می‌ماند و با بستن آن نشست یا خروج از SpeedCrunch دور ریخته می‌شود. Make Private خصوصی کردن Could not delete the saved session %1. حذ� نشست ذخیره‌شدهٔ %1 ممکن نشد. Keep Session نگه داشتن نشست Could not save the session. It remains private. ذخیرهٔ نشست ممکن نشد. خصوصی باقی می‌ماند. Clone Session همسان‌سازی نشست Could not save session file %1. ذخیرهٔ پروندهٔ نشست %1 ممکن نشد. Could not delete session file %1. حذ� پروندهٔ نشست %1 ممکن نشد. JSON file (*.json);;Any file (*.*) پرونده JSON (*.json);;هر پرونده (*.*) Export session as JSON صادر کردن نشست به صورت JSON The selected file is not valid JSON: %1 پرونده انتخاب‌شده JSON معتبر نیست: %1 The selected file is not a SpeedCrunch session JSON file. پرونده انتخاب‌شده یک پرونده JSON نشست SpeedCrunch نیست. This file uses an obsolete SpeedCrunch session format and cannot be imported. این پرونده از قالب منسوخ نشست SpeedCrunch است�اده می‌کند و نمی‌توان آن را وارد کرد. The selected JSON file is missing the required $schema field. پرونده JSON انتخاب‌شده �یلد ضروری $schema را ندارد. The selected JSON file uses an unsupported JSON schema: %1 پرونده JSON انتخاب‌شده از ش�مای JSON پشتیبانی‌نشده است�اده می‌کند: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). پرونده JSON انتخاب‌شده شناسه ش�مای نشست SpeedCrunch ($id) را ندارد. The selected JSON file uses an unsupported SpeedCrunch session format: %1 پرونده JSON انتخاب‌شده از قالب نشست SpeedCrunch پشتیبانی‌نشده است�اده می‌کند: %1 The selected JSON file is missing the required session name. پرونده JSON انتخاب‌شده نام ضروری نشست را ندارد. The selected JSON file has an empty session name. پرونده JSON انتخاب‌شده نام نشست خالی دارد. The selected JSON file has invalid or incomplete SpeedCrunch session data. پرونده JSON انتخاب‌شده داده‌های نشست SpeedCrunch نامعتبر یا ناقص دارد. Open Sessions Folder باز کردن پوشه نشست‌ها Could not create the sessions folder: %1 نمی‌توان پوشه نشست‌ها را ایجاد کرد: %1 Could not open the sessions folder: %1 نمی‌توان پوشه نشست‌ها را باز کرد: %1 Editor and Results Font قلم ویرایشگر و نتایج Open Session باز کردن نشست Community جامعه Rename Session تغییر نام نشست Clear Session پاک کردن نشست Delete Session حذ� نشست Close Pane بستن قاب User Variables متغیرهای کاربر User Units یکاهای کاربر Clear History پاک کردن تاریخچه Are you sure you want to clear the calculation history? آیا مطمئنید می‌خواهید تاریخچه محاسبات را پاک کنید؟ Session name: نام نشست: A session named %1 already exists. نشستی با نام %1 از قبل وجود دارد. Could not create session file %1. نمی‌توان پرونده نشست %1 را ایجاد کرد. Could not write session file %1. نمی‌توان پرونده نشست %1 را نوشت. Are you sure you want to delete this session? آیا مطمئنید می‌خواهید این نشست را حذ� کنید؟ Custom Precision دقت س�ارشی Fractional digits: رقم‌های کسری: Theme پوسته Light Themes پوسته‌های روشن Dark Themes پوسته‌های تیره Preview پیش‌نمایش Colors رنگ‌ها Select color for %1 انتخاب رنگ برای %1 Import... وارد کردن... Export... صادر کردن... Import Theme وارد کردن پوسته Theme file (*.json);;All files (*) پرونده پوسته (*.json);;همه پرونده‌ها (*) Invalid theme file. پرونده پوسته نامعتبر است. Can't import theme "%1" because it conflicts with a built-in theme. نمی‌توان پوسته "%1" را وارد کرد، چون با یک پوسته داخلی تداخل دارد. Can't find a writable theme folder. پوشه پوسته قابل نوشتن پیدا نشد. Overwrite Theme بازنویسی پوسته A custom theme named "%1" already exists. Do you want to overwrite it? پوسته‌ای س�ارشی با نام "%1" از قبل وجود دارد. آیا می‌خواهید آن را بازنویسی کنید؟ Can't overwrite theme file %1 نمی‌توان پرونده پوسته %1 را بازنویسی کرد Can't copy theme file to %1 نمی‌توان پرونده پوسته را در %1 کپی کرد Export Theme صادر کردن پوسته Can't export theme as "%1" because it conflicts with a built-in theme. نمی‌توان پوسته را با نام "%1" صادر کرد، چون با یک پوسته داخلی تداخل دارد. Can't write to file %1 نمی‌توان در پرونده %1 نوشت Global User Variable متغیر سراسری کاربر Global User Function تابع سراسری کاربر Global User Unit یکای سراسری کاربر User Definitions تعری�‌های کاربر These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. این تعری�‌ها سراسری هستند و در هر نشست بارگذاری می‌شوند. در نشست‌ها نمی‌توان آن‌ها را تغییر داد و بر تعری�‌های هم‌نام در ویرایشگر نشست اولویت دارند. در هر خط یک تعری� وارد کنید. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] نمونه‌ها: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply اعمال Validate اعتبارسنجی Test Results نتایج آزمون Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 متغیرهای واردشده: %1 توابع واردشده: %2 یکاهای واردشده: %3 شمارهٔ خط‌های دارای خطا: %4 none هیچ‌کدام Apply Results نتایج اعمال User definitions saved. تعری�‌های کاربر ذخیره شدند. History Size Limit محدودیت اندازه تاریخچه Maximum number of history entries for this session (0 = unlimited): بیشینه تعداد ورودی‌های تاریخچه برای این نشست (0 = نامحدود): Text file (*.txt);;Any file (*.*) پرونده متنی (*.txt);;هر پرونده (*.*) Could not recalculate from calculation %1: %2 امکان محاسبه مجدد از محاسبه %1 وجود ندارد: %2 History Size Limit Reached به محدودیت اندازه تاریخچه رسید This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. این محاسبه آخرین جای خالی تاریخچه را پر می‌کند. محاسبه‌های بعدی قدیمی‌ترین محاسبه را از تاریخچه حذ� می‌کنند. می‌توانید این محدودیت را از نشست > محدودیت اندازه تاریخچه ا�زایش دهید. Editing calculation. Press Esc twice to cancel. در حال ویرایش محاسبه. برای لغو، Esc را دو بار �شار دهید. Calculation Settings تنظیمات محاسبه Invalid recalculation start index نمایه شروع محاسبه مجدد نامعتبر است System Default پیش‌�رض سیستم Language زبان Select the language: زبان را انتخاب کنید: Custom س�ارشی Decimal places: رقم‌های اعشار: &Automatic &خودکار &Precision &دقت Plain &text متن &ساده Formula &Book کتاب &�رمول‌ها &Export &صادر کردن Export session as HTML صادر کردن نشست به صورت HTML HTML file (*.html) پرونده HTML (*.html) Export session as plain text صادر کردن نشست به صورت متن ساده ManualWindow SpeedCrunch Manual راهنمای SpeedCrunch %1 - SpeedCrunch Manual %1 - راهنمای SpeedCrunch NumberFormatDialog Number Format قالب عدد <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>قالب عددی نتایج و گروه‌بندی رقم‌های ورودی را انتخاب کنید.</b><br/><br/>توجه: قالب‌های بدون ابهام برای عددهای ورودی پذیر�ته می‌شوند، حتی اگر با قالب نمایش انتخاب‌شده مت�اوت باشند.<br/> QObject Global User Variable متغیر سراسری کاربر Global User Function تابع سراسری کاربر Global User Unit یکای سراسری کاربر Backspace پس‌بر Clear expression پاک کردن عبارت Evaluate expression ارزیابی عبارت Insert text درج متن Automatic decimal دهدهی خودکار Fixed-point decimal دهدهی ممیز ثابت Engineering decimal دهدهی مهندسی Scientific decimal دهدهی علمی Rational گویا Binary باینری Octal هشتایی Hexadecimal شانزده‌تایی Sexagesimal شصت‌گانی Update Available به‌روزرسانی موجود است A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> نسخه جدیدتری (%1) موجود است.<br/><a href="%2">برای دانلود به وب‌سایت بروید.</a> Check for Updates بررسی به‌روزرسانی‌ها SpeedCrunch %1 is up to date. SpeedCrunch %1 به‌روز است. No connectivity. Please check your internet connection and try again. اتصال برقرار نیست. لط�اً اتصال اینترنت خود را بررسی کنید و دوباره تلاش کنید. Could not verify the latest available version. امکان بررسی آخرین نسخه موجود وجود ندارد. ResultDisplay Scroll to bottom پیمایش به پایین Edit Expression ویرایش عبارت Change Settings تغییر تنظیمات New Tab زبانه جدید &Import... &وارد کردن... &Export &صادر کردن Plain &text متن &ساده Copy کپی Selection انتخاب Select All انتخاب همه Expression عبارت Result نتیجه Calculation محاسبه Calculation as Single Line محاسبه در یک خط Remove حذ� This Calculation این محاسبه All Calculations Above همهٔ محاسبات بالاتر All Calculations Below همهٔ محاسبات پایین‌تر New Private Tab زبانهٔ خصوصی تازه Session نشست Open... باز کردن... Clone... همسان‌سازی... Rename... تغییر نام... Keep نگه داشتن Make Private... خصوصی کردن... Clear پاک کردن Delete حذ� Close بستن Split تقسیم Left چپ Right راست Up بالا Down پایین Close Pane بستن قاب Main Menu منوی اصلی Cancel editing لغو ویرایش Copy result کپی نتیجه Edit expression ویرایش عبارت Change settings تغییر تنظیمات Remove calculation حذ� محاسبه ResultSlotsDialog Notation & Precision نمادگذاری و دقت Result Line خط نتیجه Enabled �عال Notation نمادگذاری Decimal Places رقم‌های اعشار Main Line خط اصلی Extra Line #1 خط اضا�ی شماره ۱ Extra Line #2 خط اضا�ی شماره ۲ Extra Line #3 خط اضا�ی شماره ۳ Extra Line #4 خط اضا�ی شماره ۴ Auto خودکار UserFunctionListWidget Name نام Value مقدار Description شرح Search جستجو No match found نتیجه‌ای پیدا نشد Insert درج Edit ویرایش Delete حذ� Delete All حذ� همه UserUnitListWidget Name نام Value مقدار Description شرح Search جستجو No match found نتیجه‌ای پیدا نشد Insert درج Edit ویرایش Delete حذ� Delete All حذ� همه VariableListWidget Name نام Value مقدار Description شرح Search جستجو No match found نتیجه‌ای پیدا نشد Insert درج Edit ویرایش Delete حذ� Delete All حذ� همه heldercorreia-speedcrunch-e7ca37f/src/resources/locale/fi.ts000066400000000000000000010522601526573132500243510ustar00rootroot00000000000000 AboutBox About SpeedCrunch Tietoa SpeedCrunchista Core developers Pääkehittäjät Original author Alkuperäinen tekijä Close Sulje Math engine Matematiikkamoottori Main author | Logo | Maintainer Päätekijä | logo | ylläpitäjä Thanks Kiitokset Copyright (C) 2004-2026 The SpeedCrunch developers Copyright © 2004–2026 SpeedCrunchin kehittäjät This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Tämä ohjelma on vapaa; tätä ohjelmaa on sallittu levittää edelleen ja muuttaa GNU yleisen lisenssin (GPL lisenssin) ehtojen mukaan sellaisina kuin Free Software Foundation on ne julkaissut; joko Lisenssin version 2, tai (valinnan mukaan) minkä tahansa myöhemmän version mukaisesti This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Tätä ohjelmaa levitetään siinä toivossa, että se olisi hyödyllinen, mutta ilman mitään takuuta; ilman edes hiljaista takuuta kaupallisesti hyväksyttävästä laadusta tai soveltuvuudesta tiettyyn tarkoitukseen. Katso GPL lisenssistä lisää yksityiskohtia. BitFieldWidget Reset bits to zero Palauta bitit nolliksi Invert bits Käännä bitit Shift bits left Siirrä bittejä vasemmalle Shift bits right Siirrä bittejä oikealle Book Index Hakemisto Algebra Algebra Quadratic Equation Toisen asteen yhtälö Logarithmic Base Conversion Logaritmin kannan vaihto Geometry Geometria Circle Ympyrä Sector Sektori Sphere Pallo Cube Kuutio Cone Kartio Cylinder Lieriö Electronics Elektroniikka Ohm's Law Ohmin laki Power Teho Reactance Reaktanssi Resonance Resonanssi Radio Frequency Radiotaajuus Antennas Antennit Characteristic Impedance (coax) Ominaisimpedanssi (koaksiaali) Velocity of Propagation (coax) Etenemisnopeus (koaksiaali) Standing Wave Ratio & Return Loss Seisovan aallon suhde & heijastushäviö Free Space Wavelength Vapaan tilan aallonpituus resistance resistanssi voltage jännite current virta power teho inductive reactance induktiivinen reaktanssi capacitive reactance kapasitiivinen reaktanssi inductance induktanssi capacitance kapasitanssi frequency taajuus resonance frequency resonanssitaajuus area ala perimeter kehä diameter halkaisija radius säde volume tilavuus surface area pinta-ala height korkeus slant height sivujanan pituus face diagonal tahkon lävistäjä space diagonal avaruuslävistäjä edge length särmän pituus arc length kaaren pituus central angle (degrees) keskuskulma (asteina) input power ottoteho reflected power heijastunut teho transmitted power siirretty teho return loss heijastushäviö dielectric constant dielektrinen vakio outer conductor's inner diameter ulomman johteen sisähalkaisija inner conductor's outer diameter sisemmän johteen ulkohalkaisija speed of light valonnopeus reflection coefficient heijastuskerroin standing wave ratio seisovan aallon suhde normalized impedance normalisoitu impedanssi frequency (Hz) taajuus (Hz) BookDock Formula Book Kaavakirja ConstantCompletion Search constants Etsi vakioita No match found Ei tuloksia Constants Mathematics Matematiikka Physics (CODATA 2022) Fysiikka (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kemia (IUPAC - CIAAW 2021) Uncategorized Luokittelematon Universal Yleiset Physicochemical Fysikaalis-kemialliset Atomic & Nuclear — General Atomi- ja ydinfysiikka — yleiset Atomic & Nuclear — Electroweak Atomi- ja ydinfysiikka — sähköheikot Atomic & Nuclear — Electron Atomi- ja ydinfysiikka — elektroni Atomic & Nuclear — Muon Atomi- ja ydinfysiikka — myoni Atomic & Nuclear — Tau Atomi- ja ydinfysiikka — tau Atomic & Nuclear — Proton Atomi- ja ydinfysiikka — protoni Atomic & Nuclear — Neutron Atomi- ja ydinfysiikka — neutroni Atomic & Nuclear — Deuteron Atomi- ja ydinfysiikka — deuteroni Atomic & Nuclear — Triton Atomi- ja ydinfysiikka — tritoni Atomic & Nuclear — Helion Atomi- ja ydinfysiikka — helioni Atomic & Nuclear — Alpha particle Atomi- ja ydinfysiikka — alfahiukkanen Atomic & Nuclear — Atomic units Atomi- ja ydinfysiikka — atomiyksiköt Atomic & Nuclear — Energy conversion relationships Atomi- ja ydinfysiikka — energiamuunnosten vastaavuudet Atomic & Nuclear — X-ray units Atomi- ja ydinfysiikka — röntgenyksiköt Atomic & Nuclear — Magnetic shielding corrections Atomi- ja ydinfysiikka — magneettiset suojauskorjaukset Masses Massat Lifetimes Elinajat Molar Masses Moolimassat Electronegativity Elektronegatiivisuus Ionization Energy Ionisaatioenergia Nominal Constants (IAU 2015) Nimelliset vakiot (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Nykyiset parhaat arviot (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) tyhjiön ominaisimpedanssi (Z₀) reduced Planck constant (�) redusoitu Planckin vakio (�) vacuum electric permittivity (ϵ₀) Tyhjiön permittiivisyys (ϵ₀) Newtonian constant of gravitation (G) Newtonin gravitaatiovakio (G) vacuum magnetic permeability (μ₀) Tyhjiön permeabiliteetti (μ₀) Planck constant (h) Planckin vakio (h) speed of light in vacuum (c) Valonnopeus tyhjiössä (c) standard acceleration of gravity (gₙ) Normaaliputoamiskiihtyvyys (gₙ) Newtonian constant of gravitation over h-bar c Newtonin gravitaatiovakio jaettuna �c:llä Planck length Planckin pituus Planck constant in eV/Hz (h) Planckin vakio yksikkönä eV/Hz (h) Planck mass Planckin massa Planck mass energy equivalent in GeV Planckin massan energiaekvivalentti yksikkönä GeV Planck temperature Planckin lämpötila Planck time Planckin aika reduced Planck constant in eV·s (�) redusoitu Planckin vakio yksikkönä eV·s (�) reduced Planck constant times c in MeV·fm redusoitu Planckin vakio kertaa c yksikkönä MeV·fm Bohr magneton Bohrin magnetoni conductance quantum (G₀) Konduktanssikvantti (G₀) Coulomb constant (kₑ) Coulombin vakio (kₑ) elementary charge (e) Alkeisvaraus (e) elementary charge over h-bar Alkeisvaraus jaettuna �:lla conventional value of Josephson constant Josephsonin vakion konventionaalinen arvo Josephson constant Josephsonin vakio conventional value of ampere-90 ampeeri-90:n konventionaalinen arvo conventional value of coulomb-90 coulombi-90:n konventionaalinen arvo conventional value of farad-90 faradi-90:n konventionaalinen arvo conventional value of henry-90 henry-90:n konventionaalinen arvo conventional value of ohm-90 ohmi-90:n konventionaalinen arvo conventional value of volt-90 voltti-90:n konventionaalinen arvo conventional value of watt-90 watti-90:n konventionaalinen arvo magnetic flux quantum (Φ₀) Magneettivuon kvantti (Φ₀) nuclear magneton Ydinmagnetoni inverse of conductance quantum konduktanssikvantin käänteisarvo conventional value of von Klitzing constant von Klitzingin vakion konventionaalinen arvo von Klitzing constant von Klitzingin vakio atomic unit of magnetic dipole moment Atomiyksikkö: magneettinen dipolimomentti atomic unit of magnetic flux density Atomiyksikkö: magneettivuon tiheys Bohr magneton in eV/T Bohrin magnetoni yksikkönä eV/T Bohr magneton in Hz/T Bohrin magnetoni yksikkönä Hz/T Bohr magneton in inverse meter per tesla Bohrin magnetoni yksikkönä käänteismetri per tesla Bohr magneton in K/T Bohrin magnetoni yksikkönä K/T nuclear magneton in eV/T Ydinmagnetoni yksikkönä eV/T nuclear magneton in inverse meter per tesla Ydinmagnetoni yksikkönä käänteismetri per tesla nuclear magneton in K/T Ydinmagnetoni yksikkönä K/T nuclear magneton in MHz/T Ydinmagnetoni yksikkönä MHz/T Bohr radius (a₀) Bohrin säde (a₀) fine-structure constant (α) hienorakennevakio (α) Hartree energy (Eₕ) Hartree-energia (Eₕ) Hartree energy in eV Hartree-energia yksikkönä eV quantum of circulation kiertokvantti quantum of circulation times 2 kiertokvantti kertaa 2 Rydberg constant (R∞) Rydbergin vakio (R∞) atomic mass unit-hartree relationship Atomimassayksikkö-hartree vastaavuus atomic mass unit-hertz relationship Atomimassayksikkö-hertsi vastaavuus atomic mass unit-inverse meter relationship Atomimassayksikkö-käänteismetri vastaavuus atomic mass unit-joule relationship Atomimassayksikkö-joule vastaavuus atomic mass unit-kelvin relationship Atomimassayksikkö-kelvin vastaavuus atomic mass unit-kilogram relationship Atomimassayksikkö-kilogramma vastaavuus atomic unit of 1st hyperpolarizability Atomiyksikkö: ensimmäinen hyperpolarisoituvuus atomic unit of 2nd hyperpolarizability Atomiyksikkö: toinen hyperpolarisoituvuus atomic unit of charge (e) Atomiyksikkö: varaus (e) atomic unit of charge density Atomiyksikkö: varaustiheys atomic unit of current Atomiyksikkö: virta atomic unit of electric dipole moment Atomiyksikkö: sähköinen dipolimomentti atomic unit of electric field Atomiyksikkö: sähkökenttä atomic unit of electric field gradient Atomiyksikkö: sähkökentän gradientti atomic unit of electric polarizability Atomiyksikkö: sähköinen polarisoituvuus atomic unit of electric potential Atomiyksikkö: sähköpotentiaali atomic unit of electric quadrupole moment Atomiyksikkö: sähköinen kvadrupolimomentti atomic unit of action Atomiyksikkö: vaikutus atomic unit of energy Atomiyksikkö: energia atomic unit of force Atomiyksikkö: voima atomic unit of length Atomiyksikkö: pituus hertz-atomic mass unit relationship hertsin ja atomimassayksikön vastaavuus hertz-electron volt relationship hertsin ja elektronivoltin vastaavuus hertz-hartree relationship hertsin ja hartreen vastaavuus hertz-inverse meter relationship hertsin ja käänteismetrin vastaavuus hertz-joule relationship hertsin ja joulen vastaavuus hertz-kelvin relationship hertsin ja kelvinin vastaavuus hertz-kilogram relationship hertsin ja kilogramman vastaavuus hyperfine transition frequency of Cs-133 Cs-133:n hyperhienorakennesiirtymän taajuus inverse fine-structure constant (α�¹) hienorakennevakion käänteisarvo (α�¹) inverse meter-atomic mass unit relationship käänteismetrin ja atomimassayksikön vastaavuus inverse meter-electron volt relationship käänteismetrin ja elektronivoltin vastaavuus inverse meter-hartree relationship käänteismetrin ja hartreen vastaavuus inverse meter-hertz relationship käänteismetrin ja hertsin vastaavuus inverse meter-joule relationship käänteismetrin ja joulen vastaavuus inverse meter-kelvin relationship käänteismetrin ja kelvinin vastaavuus inverse meter-kilogram relationship käänteismetrin ja kilogramman vastaavuus joule-atomic mass unit relationship joulen ja atomimassayksikön vastaavuus joule-electron volt relationship joulen ja elektronivoltin vastaavuus joule-hertz relationship joulen ja hertsin vastaavuus joule-hartree relationship joulen ja hartreen vastaavuus joule-inverse meter relationship joulen ja käänteismetrin vastaavuus joule-kelvin relationship joulen ja kelvinin vastaavuus joule-kilogram relationship joulen ja kilogramman vastaavuus kelvin-atomic mass unit relationship kelvinin ja atomimassayksikön vastaavuus kelvin-electron volt relationship kelvinin ja elektronivoltin vastaavuus kelvin-hertz relationship kelvinin ja hertsin vastaavuus kelvin-hartree relationship kelvinin ja hartreen vastaavuus kelvin-inverse meter relationship kelvinin ja käänteismetrin vastaavuus kelvin-joule relationship kelvinin ja joulen vastaavuus kelvin-kilogram relationship kelvinin ja kilogramman vastaavuus kilogram-atomic mass unit relationship kilogramman ja atomimassayksikön vastaavuus kilogram-electron volt relationship kilogramman ja elektronivoltin vastaavuus kilogram-hertz relationship kilogramman ja hertsin vastaavuus kilogram-hartree relationship kilogramman ja hartreen vastaavuus kilogram-inverse meter relationship kilogramman ja käänteismetrin vastaavuus kilogram-joule relationship kilogramman ja joulen vastaavuus kilogram-kelvin relationship kilogramman ja kelvinin vastaavuus lattice parameter of silicon (a) piin hilaparametri (a) luminous efficacy valotehokkuus natural unit of energy Luonnollinen yksikkö: energia natural unit of energy in MeV Luonnollinen yksikkö: energia yksikkönä MeV natural unit of action (�) Luonnollinen yksikkö: vaikutus (�) natural unit of action in eV·s Luonnollinen yksikkö: vaikutus yksikkönä eV·s natural unit of length Luonnollinen yksikkö: pituus natural unit of mass Luonnollinen yksikkö: massa natural unit of momentum Luonnollinen yksikkö: liikemäärä natural unit of momentum in MeV/c Luonnollinen yksikkö: liikemäärä yksikkönä MeV/c natural unit of time Luonnollinen yksikkö: aika natural unit of velocity Luonnollinen yksikkö: nopeus Rydberg constant times c in Hz Rydbergin vakio kertaa c yksikkönä Hz Rydberg constant times hc in eV Rydbergin vakio kertaa hc yksikkönä eV Rydberg constant times hc in J Rydbergin vakio kertaa hc yksikkönä J Fermi coupling constant Fermin kytkentävakio weak mixing angle heikon vuorovaikutuksen sekoituskulma W to Z mass ratio W- ja Z-bosonien massasuhde Thomson cross section (σₑ) Thomsonin vaikutusala (σₑ) electron mass (mₑ) elektronin massa (mₑ) electron mass in u elektronin massa yksikkönä u electron mass energy equivalent (mₑ·c²) elektronin massan energiaekvivalentti (mₑ·c²) electron mass energy equivalent in MeV elektronin massan energiaekvivalentti yksikkönä MeV reduced Compton wavelength Redusoitu Comptonin aallonpituus classical electron radius (rₑ) klassinen elektronin säde (rₑ) electron charge to mass quotient elektronin varauksen ja massan osamäärä electron-deuteron magnetic moment ratio Elektroni-deuteroni magneettisen momentin suhde electron-deuteron mass ratio elektroni-deuteroni-massasuhde electron g factor (gₑ) elektronin g-tekijä (gₑ) electron gyromagnetic ratio (γₑ) elektronin gyromagneettinen suhde (γₑ) electron gyromagnetic ratio in MHz/T elektronin gyromagneettinen suhde yksikkönä MHz/T electron-helion mass ratio elektroni-helioni-massasuhde electron magnetic moment (μₑ) elektronin magneettinen momentti (μₑ) electron magnetic moment anomaly (aₑ) elektronin magneettisen momentin anomalia (aₑ) electron magnetic moment to Bohr magneton ratio elektronin magneettisen momentin suhde Bohrin magnetoniin electron magnetic moment to nuclear magneton ratio elektronin magneettisen momentin suhde ydinmagnetoniin electron molar mass (Mₑ) elektronin moolimassa (Mₑ) electron-muon magnetic moment ratio Elektroni-myoni magneettisen momentin suhde electron-muon mass ratio elektroni-myoni-massasuhde electron-neutron magnetic moment ratio Elektroni-neutroni magneettisen momentin suhde electron-neutron mass ratio Elektroni-neutroni massasuhde electron-proton magnetic moment ratio Elektroni-protoni magneettisen momentin suhde electron-proton mass ratio Elektroni-protoni massasuhde electron relative atomic mass (Ar(e)) Elektroni suhteellinen atomimassa (Ar(e)) electron-tau mass ratio Elektroni-tau massasuhde electron to alpha particle mass ratio elektronin massan suhde alfahiukkasen massaan electron to shielded helion magnetic moment ratio elektronin magneettisen momentin suhde suojatun helionin magneettiseen momenttiin electron to shielded proton magnetic moment ratio elektronin magneettisen momentin suhde suojatun protonin magneettiseen momenttiin electron-triton mass ratio Elektroni-tritoni massasuhde electron volt-atomic mass unit relationship Elektronivoltti-atomimassayksikkö vastaavuus electron volt-hartree relationship Elektronivoltti-hartree vastaavuus electron volt-hertz relationship Elektronivoltti-hertsi vastaavuus electron volt-inverse meter relationship Elektronivoltti-käänteismetri vastaavuus electron volt-joule relationship Elektronivoltti-joule vastaavuus electron volt-kelvin relationship Elektronivoltti-kelvin vastaavuus electron volt-kilogram relationship Elektronivoltti-kilogramma vastaavuus hartree-atomic mass unit relationship Hartree-atomimassayksikkö vastaavuus hartree-electron volt relationship Hartree-elektronivoltti vastaavuus muon Compton wavelength Myoni Comptonin aallonpituus muon-electron mass ratio Myoni-elektroni massasuhde muon g factor Myoni g-tekijä muon magnetic moment Myoni magneettinen momentti muon magnetic moment anomaly Myoni magneettinen momentti anomalia muon magnetic moment to Bohr magneton ratio Myoni magneettisen momentin suhde Bohrin magnetoniin muon magnetic moment to nuclear magneton ratio Myoni magneettisen momentin suhde ydinmagnetoniin muon mass Myoni massa muon mass energy equivalent Myoni massan energiaekvivalentti muon mass energy equivalent in MeV Myoni massan energiaekvivalentti yksikkönä MeV muon mass in u Myoni massa yksikkönä u muon molar mass Myoni moolimassa muon-neutron mass ratio Myoni-neutroni massasuhde muon-proton magnetic moment ratio Myoni-protoni magneettisen momentin suhde muon-proton mass ratio Myoni-protoni massasuhde muon-tau mass ratio Myoni-tau massasuhde reduced muon Compton wavelength Redusoitu myoni Comptonin aallonpituus reduced tau Compton wavelength Redusoitu tau Comptonin aallonpituus tau Compton wavelength Tau Comptonin aallonpituus tau-electron mass ratio Tau-elektroni massasuhde tau mass Tau massa tau mass energy equivalent Tau massan energiaekvivalentti tau mass in u Tau massa yksikkönä u tau molar mass Tau moolimassa tau-muon mass ratio Tau-myoni massasuhde tau-neutron mass ratio Tau-neutroni massasuhde tau-proton mass ratio Tau-protoni massasuhde proton charge to mass quotient Protoni varauksen ja massan osamäärä proton Compton wavelength Protoni Comptonin aallonpituus proton-electron mass ratio Protoni-elektroni massasuhde proton g factor (gₚ) Protoni g-tekijä (gₚ) proton gyromagnetic ratio (γₚ) Protoni gyromagneettinen suhde (γₚ) proton gyromagnetic ratio in MHz/T Protoni gyromagneettinen suhde yksikkönä MHz/T proton magnetic moment (μₚ) Protoni magneettinen momentti (μₚ) proton magnetic moment to Bohr magneton ratio Protoni magneettisen momentin suhde Bohrin magnetoniin proton magnetic moment to nuclear magneton ratio Protoni magneettisen momentin suhde ydinmagnetoniin proton magnetic shielding correction Protoni magnetic suojauskorjaus proton mass (mₚ) Protoni massa (mₚ) proton mass energy equivalent Protoni massan energiaekvivalentti proton mass energy equivalent in MeV Protoni massan energiaekvivalentti yksikkönä MeV proton mass in u Protoni massa yksikkönä u proton molar mass (Mₚ) Protoni moolimassa (Mₚ) proton-muon mass ratio Protoni-myoni massasuhde proton-neutron magnetic moment ratio Protoni-neutroni magneettisen momentin suhde proton-neutron mass ratio Protoni-neutroni massasuhde proton relative atomic mass (Ar(p)) Protoni suhteellinen atomimassa (Ar(p)) proton rms charge radius Protoni rms-varaussäde proton-tau mass ratio Protoni-tau massasuhde reduced proton Compton wavelength Redusoitu protoni Comptonin aallonpituus shielded proton gyromagnetic ratio Suojattu protoni gyromagneettinen suhde shielded proton gyromagnetic ratio in MHz/T Suojattu protoni gyromagneettinen suhde yksikkönä MHz/T shielded proton magnetic moment Suojattu protoni magneettinen momentti shielded proton magnetic moment to Bohr magneton ratio Suojattu protoni magneettisen momentin suhde Bohrin magnetoniin shielded proton magnetic moment to nuclear magneton ratio Suojattu protoni magneettisen momentin suhde ydinmagnetoniin neutron Compton wavelength Neutroni Comptonin aallonpituus neutron-electron magnetic moment ratio Neutroni-elektroni magneettisen momentin suhde neutron-electron mass ratio Neutroni-elektroni massasuhde neutron g factor (gₙ) Neutroni g-tekijä (gₙ) neutron gyromagnetic ratio (γₙ) Neutroni gyromagneettinen suhde (γₙ) neutron gyromagnetic ratio in MHz/T Neutroni gyromagneettinen suhde yksikkönä MHz/T neutron magnetic moment (μₙ) Neutroni magneettinen momentti (μₙ) neutron magnetic moment to Bohr magneton ratio Neutroni magneettisen momentin suhde Bohrin magnetoniin neutron magnetic moment to nuclear magneton ratio Neutroni magneettisen momentin suhde ydinmagnetoniin neutron mass (mₙ) Neutroni massa (mₙ) neutron mass energy equivalent Neutroni massan energiaekvivalentti neutron mass energy equivalent in MeV Neutroni massan energiaekvivalentti yksikkönä MeV neutron mass in u Neutroni massa yksikkönä u neutron molar mass (Mₙ) Neutroni moolimassa (Mₙ) neutron-muon mass ratio Neutroni-myoni massasuhde neutron-proton magnetic moment ratio Neutroni-protoni magneettisen momentin suhde neutron-proton mass difference Neutroni-protoni massa ero neutron-proton mass difference energy equivalent Neutroni-protoni massa ero energiaekvivalentti neutron-proton mass difference energy equivalent in MeV Neutroni-protoni massa ero energiaekvivalentti yksikkönä MeV neutron-proton mass difference in u Neutroni-protoni massa ero yksikkönä u neutron-proton mass ratio Neutroni-protoni massasuhde neutron relative atomic mass (Ar(n)) Neutroni suhteellinen atomimassa (Ar(n)) neutron-tau mass ratio Neutroni-tau massasuhde neutron to shielded proton magnetic moment ratio neutronin magneettisen momentin suhde suojatun protonin magneettiseen momenttiin reduced neutron Compton wavelength Redusoitu neutroni Comptonin aallonpituus deuteron-electron magnetic moment ratio Deuteroni-elektroni magneettisen momentin suhde deuteron-electron mass ratio Deuteroni-elektroni massasuhde deuteron g factor Deuteroni g-tekijä deuteron magnetic moment Deuteroni magneettinen momentti deuteron magnetic moment to Bohr magneton ratio Deuteroni magneettisen momentin suhde Bohrin magnetoniin deuteron magnetic moment to nuclear magneton ratio Deuteroni magneettisen momentin suhde ydinmagnetoniin deuteron mass Deuteroni massa deuteron mass energy equivalent Deuteroni massan energiaekvivalentti deuteron mass energy equivalent in MeV Deuteroni massan energiaekvivalentti yksikkönä MeV deuteron mass in u Deuteroni massa yksikkönä u deuteron molar mass Deuteroni moolimassa deuteron-neutron magnetic moment ratio Deuteroni-neutroni magneettisen momentin suhde deuteron-proton magnetic moment ratio Deuteroni-protoni magneettisen momentin suhde deuteron-proton mass ratio Deuteroni-protoni massasuhde deuteron relative atomic mass (Ar(d)) Deuteroni suhteellinen atomimassa (Ar(d)) deuteron rms charge radius Deuteroni rms-varaussäde triton-electron mass ratio Tritoni-elektroni massasuhde triton g factor (gₜ) Tritoni g-tekijä (gₜ) triton magnetic moment (μₜ) Tritoni magneettinen momentti (μₜ) triton magnetic moment to Bohr magneton ratio Tritoni magneettisen momentin suhde Bohrin magnetoniin triton magnetic moment to nuclear magneton ratio Tritoni magneettisen momentin suhde ydinmagnetoniin triton mass (mₜ) Tritoni massa (mₜ) triton mass energy equivalent Tritoni massan energiaekvivalentti triton mass energy equivalent in MeV Tritoni massan energiaekvivalentti yksikkönä MeV triton mass in u Tritoni massa yksikkönä u triton molar mass (Mₜ) Tritoni moolimassa (Mₜ) triton-proton mass ratio Tritoni-protoni massasuhde triton relative atomic mass (Ar(t)) Tritoni suhteellinen atomimassa (Ar(t)) triton to proton magnetic moment ratio tritonin magneettisen momentin suhde protonin magneettiseen momenttiin helion-electron mass ratio Helioni-elektroni massasuhde helion g factor (gₕ) Helioni g-tekijä (gₕ) helion magnetic moment (μₕ) Helioni magneettinen momentti (μₕ) helion magnetic moment to Bohr magneton ratio Helioni magneettisen momentin suhde Bohrin magnetoniin helion magnetic moment to nuclear magneton ratio Helioni magneettisen momentin suhde ydinmagnetoniin helion mass (mₕ) Helioni massa (mₕ) helion mass energy equivalent Helioni massan energiaekvivalentti helion mass energy equivalent in MeV Helioni massan energiaekvivalentti yksikkönä MeV helion mass in u Helioni massa yksikkönä u helion molar mass (Mₕ) Helioni moolimassa (Mₕ) helion-proton mass ratio Helioni-protoni massasuhde helion relative atomic mass (Ar(h)) Helioni suhteellinen atomimassa (Ar(h)) helion shielding shift Helioni suojaussiirtymä shielded helion gyromagnetic ratio Suojattu helioni gyromagneettinen suhde shielded helion gyromagnetic ratio in MHz/T Suojattu helioni gyromagneettinen suhde yksikkönä MHz/T shielded helion magnetic moment Suojattu helioni magneettinen momentti shielded helion magnetic moment to Bohr magneton ratio Suojattu helioni magneettisen momentin suhde Bohrin magnetoniin shielded helion magnetic moment to nuclear magneton ratio Suojattu helioni magneettisen momentin suhde ydinmagnetoniin shielded helion to proton magnetic moment ratio suojatun helionin magneettisen momentin suhde protonin magneettiseen momenttiin shielded helion to shielded proton magnetic moment ratio suojatun helionin magneettisen momentin suhde suojatun protonin magneettiseen momenttiin alpha particle mass Alfahiukkanen massa alpha particle mass in u Alfahiukkanen massa yksikkönä u alpha particle mass energy equivalent Alfahiukkanen massan energiaekvivalentti alpha particle mass energy equivalent in MeV Alfahiukkanen massan energiaekvivalentti yksikkönä MeV alpha particle-electron mass ratio Alfahiukkanen-elektroni massasuhde alpha particle-proton mass ratio Alfahiukkanen-protoni massasuhde alpha particle rms charge radius Alfahiukkanen rms-varaussäde alpha particle molar mass Alfahiukkanen moolimassa alpha particle relative atomic mass (Ar(α)) Alfahiukkanen suhteellinen atomimassa (Ar(α)) atomic mass constant (mᵤ) atomimassavakio (mᵤ) Avogadro constant Avogadron vakio Boltzmann constant (k) Boltzmannin vakio (k) Boltzmann constant in eV/K Boltzmannin vakio yksikkönä eV/K Boltzmann constant in Hz/K Boltzmannin vakio yksikkönä Hz/K Boltzmann constant in inverse meter per kelvin Boltzmannin vakio yksikkönä käänteismetri per kelvin electron volt (eV) Elektronivoltti (eV) Faraday constant (F) Faradayn vakio (F) first radiation constant (c�) ensimmäinen säteilyvakio (c�) first radiation constant for spectral radiance ensimmäinen säteilyvakio spektristä radianssia varten molar gas constant (R) moolinen kaasuvakio (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) Loschmidtin vakio (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) Loschmidtin vakio (n₀, 273.15 K, 101.325 kPa) molar Planck constant moolinen Planckin vakio second radiation constant (c₂) toinen säteilyvakio (c₂) Stefan-Boltzmann constant (σ) Stefan-Boltzmannin vakio (σ) lattice spacing of ideal Si (d₂₂₀) ihanteellisen Si:n hilaväli (d₂₂₀) atomic mass constant energy equivalent atomimassavakion energiaekvivalentti atomic mass constant energy equivalent in MeV atomimassavakion energiaekvivalentti yksikkönä MeV atomic mass unit-electron volt relationship atomimassayksikön ja elektronivoltin vastaavuus molar mass constant (Mᵤ) moolimassavakio (Mᵤ) molar mass of carbon-12 hiili-12:n moolimassa molar volume of ideal gas (273.15 K, 100 kPa) ideaalikaasun moolitilavuus (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ideaalikaasun moolitilavuus (273.15 K, 101.325 kPa) molar volume of silicon piin moolitilavuus Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetroden vakio (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetroden vakio (1 K, 101.325 kPa) Wien frequency displacement law constant Wienin taajuussiirtymälain vakio Wien wavelength displacement law constant Wienin aallonpituussiirtymälain vakio standard atmosphere (atm) Standardi-ilmakehä (atm) standard-state pressure (p°) standarditilan paine (p°) Angstrom star (Å*) ångströmtähti (Å*) Copper x unit kuparin x-yksikkö Molybdenum x unit molybdeenin x-yksikkö atomic unit of magnetizability Atomiyksikkö: magnetoituvuus atomic unit of mass (mₑ) Atomiyksikkö: massa (mₑ) atomic unit of momentum Atomiyksikkö: liikemäärä atomic unit of permittivity Atomiyksikkö: permittiivisyys atomic unit of time Atomiyksikkö: aika atomic unit of velocity Atomiyksikkö: nopeus hartree-hertz relationship hartreen ja hertsin vastaavuus hartree-inverse meter relationship hartreen ja käänteismetrin vastaavuus hartree-joule relationship hartreen ja joulen vastaavuus hartree-kelvin relationship hartreen ja kelvinin vastaavuus hartree-kilogram relationship hartreen ja kilogramman vastaavuus shielding difference of d and p in HD d:n ja p:n suojausero HD:ssä shielding difference of t and p in HT t:n ja p:n suojausero HT:ssä pi (π) pii (π) Euler's number (e) Eulerin luku (e) golden ratio (φ) kultainen leikkaus (φ) Euler-Mascheroni constant (γ) Eulerin-Mascheronin vakio (γ) nominal solar radius Nimellinen Auringon säde nominal solar total irradiance Auringon nimellinen kokonaissäteilyvoimakkuus nominal solar luminosity Nimellinen Auringon luminositeetti nominal solar effective temperature Auringon nimellinen efektiivinen lämpötila nominal solar mass parameter Auringon nimellinen massaparametri nominal terrestrial equatorial radius Maan nimellinen päiväntasaajasäde nominal terrestrial polar radius Maan nimellinen napasäde nominal terrestrial mass parameter Maan nimellinen massaparametri nominal jovian equatorial radius Jupiterin nimellinen päiväntasaajasäde nominal jovian polar radius Jupiterin nimellinen napasäde nominal jovian mass parameter Jupiterin nimellinen massaparametri average value of one minus the rate of TCG relative to TCB Arvon yksi miinus TCG:n nopeus suhteessa TCB:hen keskiarvo solar mass parameter (TCB-compatible) Auringon massaparametri (TCB-yhteensopiva) solar mass parameter (TDB-compatible) Auringon massaparametri (TDB-yhteensopiva) equatorial radius of the Earth (TT-compatible) Maan päiväntasaajasäde (TT-yhteensopiva) dynamical form factor of the Earth Maan dynaaminen muotokerroin time rate of change in the dynamical form factor of the Earth Maan dynaamisen muotokertoimen muutosnopeus geocentric gravitational constant (TCB-compatible) geosentrinen gravitaatiovakio (TCB-yhteensopiva) geocentric gravitational constant (TT-compatible) geosentrinen gravitaatiovakio (TT-yhteensopiva) geocentric gravitational constant (TDB-compatible) geosentrinen gravitaatiovakio (TDB-yhteensopiva) potential of the geoid Geoidin potentiaali nominal mean angular velocity of the Earth (TT-compatible) Maan nimellinen keskikulmanopeus (TT-yhteensopiva) ratio mass of the Moon to the Earth Kuun massan suhde Maan massan ratio of the mass of the Sun to Mercury Auringon massan suhde Merkuriuksen massan ratio of the mass of the Sun to Venus Auringon massan suhde Venuksen massan ratio of the mass of the Sun to Mars Auringon massan suhde Marsin massan ratio of the mass of the Sun to Jupiter Auringon massan suhde Jupiterin massan ratio of the mass of the Sun to Saturn Auringon massan suhde Saturnuksen massan ratio of the mass of the Sun to Uranus Auringon massan suhde Uranuksen massan ratio of the mass of the Sun to Neptune Auringon massan suhde Neptunuksen massan ratio of the mass of the Sun to (134340) Pluto Auringon massan suhde (134340) Pluton massan ratio of the mass of the Sun to (136199) Eris Auringon massan suhde (136199) Eriksen massan ratio of the mass of (1) Ceres to the Sun (1) Ceresin massan suhde Auringon massan ratio of the mass of (2) Pallas to the Sun (2) Pallaksen massan suhde Auringon massan ratio of the mass of (4) Vesta to the Sun (4) Vestan massan suhde Auringon massan mean obliquity of the ecliptic at J2000.0 Ekliptikan keskikaltevuus epookissa J2000.0 Electromagnetic Sähkömagnetiikka Compton wavelength Comptonin aallonpituus Astronomy Tähtitiede ConstantsWidget Domain Alue Subdomain Osa-alue No match found Ei tuloksia Name Nimi Value Arvo Unit Yksikkö Search Etsi All Kaikki CustomKeypadDialog Custom Keypad Mukautettu näppäimistö Rows: Rivejä: Columns: Sarakkeita: Copy preset: Kopioi esiasetus: Basic Perus Scientific (wide) Tieteellinen (leveä) Scientific (narrow) Tieteellinen (kapea) Apply Käytä Row Rivi Column Sarake Label Selite Behavior Toiminta Text Teksti DiagnosticsDialog App Diagnostics Sovelluksen diagnostiikka Copy to Clipboard Kopioi leikepöydälle Editor Unit Yksikkö User unit Käyttäjän yksikkö User function Käyttäjän funktio Argument Parametri Current result:<br/>%1 Nykyinen tulos:<br/>%1 Selection result:<br/>%1 Valinnan tulos:<br/>%1 Selection result: n/a Valinnan tulos: – Selection result: %1 Valinnan tulos: %1 second sekunti metre metri kilogram kilogramma mole mooli radian radiaani steradian steradiaani degree Celsius celsiusaste cubic metre kuutiometri cubic millimetre kuutiomillimetri cubic centimetre kuutiosenttimetri cubic decimetre kuutiodesimetri cubic kilometre kuutiokilometri square millimetre neliömillimetri square kilometre neliökilometri square metre neliömetri minute minuutti hour tunti day päivä astronomical unit astronominen yksikkö degree aste arcminute kaariminuutti arcsecond kaarisekunti milliarcsecond millikaarisekunti microarcsecond mikrokaarisekunti hectare hehtaari litre litra tonne tonni Dalton dalton electronvolt elektronivoltti Angstrom ångström atmosphere ilmakehä atomic mass unit atomimassayksikkö British thermal unit brittiläinen lämpöyksikkö calorie kalori carat karaatti cup kuppi cup (Imperial) kuppi (brittiläinen) cup (Japanese) kuppi (japanilainen) cup (US) kuppi (US) degree Fahrenheit fahrenheitaste fathom syli fluid ounce (Imperial) nesteunssi (brittiläinen) fluid ounce (US) nesteunssi (US) fluid dram (Imperial) nestedrammi (brittiläinen) fluid dram (US) nestedrammi (US) foot jalka square foot neliöjalka cubic foot kuutiojalka gallon (Imperial) gallona (brittiläinen) gallon (US) gallona (US) gill (Imperial) gill (brittiläinen) gill (US) gill (US) gradian graadi grain graani gram gramma Hartley hartley Hartree energy unit Hartreen energiayksikkö horsepower hevosvoima inch tuuma square inch neliötuuma cubic inch kuutiotuuma karat karaatti knot solmu lightminute valominuutti lightsecond valosekunti lightyear valovuosi long ton pitkä tonni mile maili square mile neliömaili cubic mile kuutiomaili mile per hour mailia tunnissa kilometre per hour kilometriä tunnissa nautical mile meripeninkulma ounce unssi parsec parsek pint (Imperial) pintti (brittiläinen) pint (US) pintti (US) pound pauna pounds per square inch paunaa neliötuumaa kohti quart (Imperial) kvartti (brittiläinen) quart (US) kvartti (US) oil barrel öljytynnyri beer barrel (US) oluttynnyri (US) square yard neliöjaardi cubic yard kuutiojaardi short ton lyhyt tonni tablespoon ruokalusikka tablespoon (Australian) ruokalusikka (australialainen) tablespoon (Imperial) ruokalusikka (brittiläinen) tablespoon (US) ruokalusikka (US) dessert spoon jälkiruokalusikka teaspoon teelusikka teaspoon (Imperial) teelusikka (brittiläinen) teaspoon (US) teelusikka (US) turn kierros revolution kierros revolution per minute kierrosta minuutissa week viikko kilowatt hour kilowattitunti millimetre of mercury elohopeamillimetri yard jaardi Julian century juliaaninen vuosisata Julian year juliaaninen vuosi sidereal year sideerinen vuosi tropical year trooppinen vuosi Evaluator invalid expression virheellinen lauseke division by zero jako nollalla too time consuming - computation was rejected vei liikaa aikaa – lasku hylättiin dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensioiden epäsuhta - eridimensioisia suureita ei voi verrata, laskea yhteen yms. invalid dimension - operation might require dimensionless arguments kelpaamaton dimensio - laskutoimitus saattaa vaatia argumenttejä ilman dimensiota Computation aborted - encountered numerical instability Laskenta keskeytetty - ilmeni numeerista epästabilisuutta invalid dimension - function might require dimensionless arguments kelpaamaton dimensio - funktio saattaa vaatia argumenttejä ilman dimensiota error virhe unit must not be zero yksikkö ei saa olla nolla Conversion failed - dimension mismatch Muunnos epäonnistui - dimensioiden epäsuhta unknown function or variable tuntematon funktio tai muuttuja recursion not supported rekursiota ei tueta cannot operate on a NaN toimintoa ei voi suorittaa NaN:llä (ei-luvulla) underflow - tiny result is out of SpeedCrunch's number range alivuoto - pienen pieni tulos on SpeedCrunchin lukualueen ulkopuolella overflow - huge result is out of SpeedCrunch's number range ylivuoto - valtava tulos on SpeedCrunchin lukualueen ulkopuolella overflow - logic result exceeds maximum of 256 bits ylivuoto - looginen tulos ylittää 256-bitin ylärajan overflow - integer result exceeds maximum limit for integers ylivuoto - kokonaislukutulos ylittää suurimman mahdollisen kokonaislukuarvon operation is not defined for these arguments toimitusta ei ole määritelty näille argumenteille wrong number of arguments väärä määrä parametreja does not take NaN as an argument ei ota epälukua (NaN) parametrikseen result out of range tulos lukualueen ulkopuolella undefined for argument domain funktio on määrittelemättä parametrin määrittelyjoukolle computation too expensive lasku liian raskas internal error, please report a bug sisäinen virhe; ilmoita viasta syntax error sintaksivirhe conversion target must be a unit muunnoksen kohteen on oltava yksikkö unknown unit tuntematon yksikkö %1 is a reserved name, please choose another %1 on varattu sana; ole hyvä ja käytä jotain toista %1 is a global user definition and cannot be overridden in this session. %1 on globaali käyttäjämääritys, eikä sitä voi ohittaa tässä istunnossa. %1 is a variable name, please choose another or delete the variable %1 on muuttujan nimi; ole hyvä ja käytä jotain toista tai poista muuttuja argument %1 is used more than once parametria %1 on käytetty useammin kuin kerran %1 is a built-in unit name, please choose another %1 on sisäänrakennetun yksikön nimi, valitse toinen %1 is a user function name, please choose another or delete the function %1 on käyttäjän funktion nimi; ole hyvä ja käytä jotain toista tai poista funktio FunctionRepo max; trials; probability maksimi; kokeita; todennäköisyys trials; probability kokeita; todennäköisyys hits; trials; probability onnistumisia; kokeita; todennäköisyys max; total; hits; trials maksimi; yhteensä; onnistumisia; kokeita total; hits; trials yhteensä; onnistumisia; kokeita count; total; hits; trials lukumäärä; yhteensä; onnistumisia; kokeita dividend; divisor jaettava; jakaja x; exponent_bits; significand_bits [; exponent_bias] x; eksponentti_bitit; merkitseviä_bittejä [;eksponentti_muoto] base; x kanta; x value; modulo arvo; modulo base; exponent; modulo kantaluku; eksponentti; modulo events; average_events tapahtumia; tapahtumia_keskimäärin average_events tapahtumia_keskimäärin x [; precision] x [; tarkkuus] Absolute Value Itseisarvo Absolute Deviation Absoluuttinen poikkeama Arc Cosine Arkuskosini Logical AND Looginen JA Area Hyperbolic Cosine Hyperbolinen arkuskosini Area Hyperbolic Sine Hyperbolinen arkussini Area Hyperbolic Tangent Hyperbolinen arkustangentti Arc Sine Arkussini Arc Tangent Arkustangentti Arc Tangent with two Arguments Arkustangentti kahdella argumentilla Average (Arithmetic Mean) Aritmeettinen keskiarvo Binomial Cumulative Distribution Function Binomijakauman kertymäfunktio Binomial Distribution Mean Binomijakauman keskiarvo Binomial Probability Mass Function Binomijakauman pistetodennäköisyysfunktio Binomial Distribution Variance Binomijakauman varianssi Cube Root Kuutiojuuri Complex Conjugate Kompleksikonjugaatti Cosine Kosini Hyperbolic Cosine Hyperbolinen kosini Cotangent Kotangentti Cosecant Kosekantti Convert Unix timestamp to Date Muunna Unix aikaleima päiväykseksi Degrees of Arc Radiaanit asteina Error Function Virhefunktio Complementary Error Function Virhefunktion komplementti Exponential Eksponentti Fractional Part Murto-osa Extension of Factorials [= (x-1)!] Kertoman yleistys [= (x-1)!] Greatest Common Divisor Suurin yhteinen tekijä Geometric Mean Geometrinen keskiarvo Gradians of arc Radiaanit graadeina Hypergeometric Cumulative Distribution Function Hypergeometrisen jakauman kertymäfunktio Hypergeometric Distribution Mean Hypergeometrisen jakauman keskiarvo Hypergeometric Probability Mass Function Hypergeometrisen jakauman pistetodennäköisyysfunktio Hypergeometric Distribution Variance Hypergeometrisen jakauman varianssi Integer Quotient Osamäärä kokonaislukuna Integer Part Kokonaisosa Imaginary Part Imaginaariosa Decode IEEE-754 Binary Value Dekoodaa IEEE-754-binääriarvo Encode IEEE-754 Binary Value Enkoodaa IEEE-754-binääriarvo Decode 16-bit Half-Precision Value Dekoodaa 16-bittinen puolitarkkuuksinen arvo Encode 16-bit Half-Precision Value Enkoodaa 16-bittinen puolitarkkuuksinen arvo Decode 32-bit Single-Precision Value Dekoodaa 32-bittinen puolitarkkuuksinen arvo Encode 32-bit Single-Precision Value Enkoodaa 32-bittinen perustarkkuuksinen arvo Decode 64-bit Double-Precision Value Dekoodaa 64-bittinen kaksoistarkkuuksinen arvo Encode 64-bit Double-Precision Value Enkoodaa 64-bittinen kaksoistarkkuuksinen arvo Decode 128-bit Quad-Precision Value Enkoodaa 128-bittinen nelitarkkuuksinen arvo Encode 128-bit Quad-Precision Value Enkoodaa 128-bittinen nelitarkkuuksinen arvo Binary Logarithm 2-kantainen logaritmi Common Logarithm 10-kantainen logaritmi Natural Logarithm Luonnollinen logaritmi Logarithm to Arbitrary Base Logaritmi Mask to a bit size Maskaa bittikokoon Maximum Maksimi Median Value (50th Percentile) Mediaani (50. prosenttipiste) Minimum Minimi Modulo Modulo Euclidean Modulo Euklidinen modulo Modular Exponentiation Modulaarinen potenssi Combination (Binomial Coefficient) Kombinaatio (binomikerroin) Logical NOT Looginen EI Permutation (Arrangement) Permutaatio (järjestäminen) Convert to Binary Representation Muunna binäärimerkintään Arithmetic Aritmetiikka Chemistry Kemia Complex Kompleksiluvut Combinatorics Kombinatoriikka Probability Todennäköisyys Statistics Tilastot Aggregation Koonti Random Satunnainen Base conversion Kantalukumuunnos Number formatting Lukujen muotoilu Integer arithmetic Kokonaislukuaritmetiikka Special functions Erikoisfunktiot Exponential & Logarithmic Eksponentti ja logaritminen Angle conversion Kulmamuunnos Trigonometry Trigonometria Bitwise Bittikohtainen Floating point Liukuluku Date & Time Päivä ja aika Linear algebra Lineaarialgebra unix_timestamp; x hours offset to GMT unix_aikaleima; x tuntia GMT:stä yyyymmdd.hhmmss; x hours offset to GMT vvvvkkpp.ttmmss; x tunnin poikkeama GMT:stä [digits] [numerot] max [; min] maks [; min] List Literal Listaliteraali Convert to Padded Binary Representation Muunna: täydennetty binääriesitys Round Toward +∞ (Ceiling) Pyöristä kohti +∞ (katto) Cosine plus Imaginary Sine Kosini plus imaginaarinen sini Convert to Cis Complex Form Muunna: cis-kompleksimuoto Matrix Column Count Matriisin sarakemäärä Population Correlation Matrix (n) Populaation korrelaatiomatriisi (n) Sample Correlation Matrix (n-1) Otoksen korrelaatiomatriisi (n-1) Count Lukumäärä Population Covariance Matrix (n) Populaation kovarianssimatriisi (n) Sample Covariance Matrix (n-1) Otoksen kovarianssimatriisi (n-1) Cross Product Ristitulo Convert Date to Unix timestamp Muunna päiväys Unix-aikaleimaksi Convert to Decimal Representation Muunna desimaalimerkintään Determinant Determinantti Convert to Sexagesimal Notation Muunna: seksagesimaalimerkintä Dot Product Pistetulo Convert to Engineering Notation Muunna: tekninen merkintä Convert to Exponential Complex Form Muunna: eksponentiaalinen kompleksimuoto Round Toward −∞ (Floor) Pyöristä kohti −∞ (lattia) Flatten Matrix Litistä matriisi Least Common Multiple Pienin yhteinen jaettava Convert to Hexadecimal Representation Muunna heksadesimaalimerkintään Convert to Padded Hexadecimal Representation Muunna: täydennetty heksadesimaaliesitys Inverse Matrix Käänteismatriisi Round to 16-bit Half-Precision Value Pyöristä 16-bittiseksi puolikkaan tarkkuuden arvoksi Round to 32-bit Single-Precision Value Pyöristä 32-bittiseksi yksinkertaisen tarkkuuden arvoksi Round to 64-bit Double-Precision Value Pyöristä 64-bittiseksi kaksinkertaisen tarkkuuden arvoksi Round to 128-bit Quad-Precision Value Pyöristä 128-bittiseksi nelinkertaisen tarkkuuden arvoksi Residual from 16-bit Half-Precision Rounding Jäännös 16-bittisestä puolikkaan tarkkuuden pyöristyksestä Residual from 32-bit Single-Precision Rounding Jäännös 32-bittisestä yksinkertaisen tarkkuuden pyöristyksestä Residual from 64-bit Double-Precision Rounding Jäännös 64-bittisestä kaksinkertaisen tarkkuuden pyöristyksestä Residual from 128-bit Quad-Precision Rounding Jäännös 128-bittisestä nelinkertaisen tarkkuuden pyöristyksestä Substance Mass Aineen massa Molarity Molaarisuus Molar Mass Moolimassa Median Absolute Deviation Absoluuttisen poikkeaman mediaani Mean Keskiarvo Numerical Value of Quantity Suureen numeerinen arvo Random Decimal Number Satunnainen desimaaliluku Random Integer Number Satunnainen kokonaisluku Convert to Rational Representation Muunna: rationaaliesitys Convert to Octal Representation Muunna oktaalimerkintään Convert to Padded Octal Representation Muunna: täydennetty oktaaliesitys Vector or Matrix Norm Vektorin tai matriisin normi Logical OR Looginen TAI Population Count (Hamming Weight) Ykkösbittien määrä (Hamming-paino) Phase of Complex Number Kompleksiluvun vaihekulma Poissonian Cumulative Distribution Function Poissonin jakauman kertymäfunktio Poissonian Distribution Mean Poissonin jakauman keskiarvo Poissonian Probability Mass Function Poissonin jakauman pistetodennäköisyysfunktio Poissonian Distribution Variance Poissonin jakauman varianssi Convert to Phasor Complex Form Muunna: osoitinkompleksimuoto Convert to Rectangular Complex Form Muunna: suorakulmainen kompleksimuoto Round Half Away from Zero Pyöristä puoliväli poispäin nollasta Round Half Even Pyöristä puoliväli parilliseen Nth Root N:s juuri Convert to Scientific Notation Muunna: tieteellinen merkintä Matrix Row Count Matriisin rivimäärä List or Matrix Shape Listan tai matriisin muoto Summation Summa Population Standard Deviation (n) Populaation keskihajonta (n) Sample Standard Deviation (n-1) Otoksen keskihajonta (n-1) Round Toward Zero (Truncation) Pyöristä kohti nollaa (katkaisu) Matrix Trace Matriisin jälki Transpose Matrix Transponoi matriisi Population Variance (n) Populaation varianssi (n) Sample Variance (n-1) Otoksen varianssi (n-1) Product Tulo Radians Radiaanit Matrix Rank Matriisin ranki Real Part Reaaliosa Secant Sekantti Arithmetic Shift Left Aritmeettinen siirto vasemmalle Arithmetic Shift Right Aritmeettinen siirto oikealle Signum Etumerkki Sine Sini Hyperbolic Sine Hyperbolinen sini Square Root Neliöjuuri Sum Summa Tangent Tangentti Convert to Trigonometric Complex Form Muunna: trigonometrinen kompleksimuoto Turns Kierrokset Hyperbolic Tangent Hyperbolinen tangentti Sign-extend a value Pidennä arvo etumerkillä Logical XOR Looginen poissulkeva TAI FunctionsWidget Domain Alue All Kaikki Name Nimi Search Etsi No match found Ei tuloksia Identifier Tunniste HistoryWidget Remove All Calculations Above Poista kaikki laskut yllä Remove This Calculation Poista tämä laskutoimitus Remove All Calculations Below Poista kaikki laskut alla Keypad Inverse cosine Arkuskosini The last result Edellinen tulos Inverse sine Arkussini Inverse tangent Arkustangentti Evaluate expression Laske lauseke Division Jako Multiplication Kertolasku Subtraction Vähennyslasku Addition Yhteenlasku Clear expression Tyhjennä lauseke Cosine Kosini Backspace Askelpalautin Scientific notation Tieteellinen merkintä Exponential Eksponentti Factorial Kertoma Natural logarithm Luonnollinen logaritmi Left parenthesis Vasen sulku Nth root N:s juuri Argument separator Argumenttien erotin Square Neliö Common logarithm Kymmenkantainen logaritmi Modulo Modulo Contextual percentage Kontekstuaalinen prosentti Power Teho Right parenthesis Oikea sulku Sine Sini Square root Neliöjuuri Tangent Tangentti Pi Pii Decimal separator Desimaalierotin MainWindow Radian Radiaanit Degree Asteet Gradian Graadi Binary Binääri Octal Oktaali Hexadecimal Heksadesimaali Sexagesimal seksagesimaali, 60-järjestelmässä Engineering decimal Tekninen desimaali Scientific decimal Tieteellinen desimaali &Import... T&uo… &Quit &Lopeta Clear E&xpression Tyhjennä l&auseke Clear &History Tyhjennä &historia &Copy &Kopioi &Paste &Liitä &Select Expression &Valitse lauseke &Constants &Vakiot &Functions &Funktiot &History &Historia &Status Bar &Tilarivi Bitfield Bittikenttä Use&r Functions Käyttäjän f&unktiot &Degree &Asteet &Radian &Radiaanit &Gradian &Graadi Re&volution K&ierros Auto-Insert a&ns Lisää a&ns automaattisesti Automatic &Completion Automaattinen &täydennys &Built-in Functions &Sisäänrakennetut funktiot Built-in &Variables S&isäänrakennetut muuttujat User &Functions Käyttäjän &funktiot User Va&riables &Käyttäjän muuttujat Open a Private Tab on Startup Avaa yksityinen välilehti käynnistettäessä Open and focus a new private tab whenever SpeedCrunch starts. Avaa ja aktivoi uusi yksityinen välilehti aina SpeedCrunchin käynnistyessä. Syntax &Highlighting Syntaksin &korostus Group Digits in &Input Ryhm&ittele syötteen numerot Automatic Input &Adjustments &Automaattiset syötteen mukautukset Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Mukauta operaattoreita, välejä, sulkeita ja potensseja automaattisesti ja rajoita syöte kelvollisiin merkkeihin. Group input digits using the selected number format. Ryhmittele syötetyt numerot valitun lukumuodon mukaan. &Blinking Cursor &Vilkkuva kohdistin Blink the cursor in the expression editor. Vilkuta kohdistinta lauseke-editorissa. &Escape Clears Editor &Escape tyhjentää editorin Clear the focused expression editor with Escape after dismissing any popup or preview. Tyhjennä aktiivinen lauseke-editori Escapella, kun ponnahdusikkunat tai esikatselut on suljettu. Keep Expression After Evaluation Säilytä lauseke laskennan jälkeen Copy New Results Automatically Kopioi uudet tulokset automaattisesti &Comma Pil&kku &System Default Järjestelmän &oletus &Dot Pi&ste Dot &And Comma &Piste ja pilkku Toward +∞ (&ceil) Kohti +∞ (&ceil) Toward −∞ (&floor) Kohti −∞ (&floor) &Binary &Binääri &Engineering T&ekninen &Hexadecimal &Heksadesimaali &Octal &Oktaali &Scientific &Tieteellinen User &Manual &Käyttöopas Issues and &Feedback &Ongelmat ja palaute &Donate L&ahjoita &About SpeedCrunch &Tietoa SpeedCrunchista App Diag&nostics Sovellukse&n diagnostiikka S&plit &Jaa Angle &Mode &Kulmatila &Complex Form &Kompleksiluvun muoto New Tab Uusi välilehti Constants Vakiot Functions Funktiot History Historia User Functions Käyttäjän funktiot &Font... &Fontti… &Language... Ki&eli… &Session &Istunto &Edit &Muokkaa &View &Näytä Se&ttings &Asetukset &Decimal &Desimaali &Keypad &Näppäimistö Always on &Top Aina &päällimmäisenä Disabled Ei käytössä Small Space Pieni väli Medium Space Keskisuuri väli Large Space Suuri väli &0 Digits &0 numeroa &15 Digits &15 numeroa &2 Digits &2 numeroa &3 Digits &3 numeroa &50 Digits &50 numeroa &8 Digits &8 numeroa &Sexagesimal &seksagesimaali Reset All Settings... Palauta kaikki asetukset... &System Järje&stelmä SpeedCrunch &Theme SpeedCrunch-&teema &Classic &Perinteinen &Modern &Moderni Context Help Tilannekohtainen ohje &Help O&hje Error Virhe Can't read from file %1 Tiedoston %1 lukeminen ei onnistunut Import Session Tuo istunto Close Session Sulje istunto Angle Mode: Kulmatila: Notation: Merkintätapa: Precision: Tarkkuus: Turn Kierros Revolution Kierros Fixed-point decimal Kiinteän pisteen desimaali Rational Rationaalinen Automatic decimal Automaattinen desimaali Automatic Automaattinen User &Definitions... Käyttäjän &määritykset... New &Tab Uusi &välilehti New &Private Tab Uu&si yksityinen välilehti Keep Säilytä Make Private... Muuta yksityiseksi... New &Window Uusi &ikkuna &Open... &Avaa... &Rename... &Nimeä uudelleen... Clo&ne... &Kloonaa... &Close Tab Sul&je välilehti Reopen Clo&sed Tab Avaa sulj&ettu välilehti uudelleen Open Sessions &Folder Avaa &istuntokansio &Undo K&umoa &Redo &Tee uudelleen Cu&t L&eikkaa Copy &Last Result K&opioi viimeisin tulos &Wrap in Parentheses &Ympäröi sulkeilla Full Scr&een Mode K&oko näytön tila &Basic &Perus &Scientific (wide) &Tieteellinen (leveä) Scientific (narrow) Tieteellinen (kapea) &Custom... &Mukautettu... Main &Menu Pää&valikko User &Variables Käyttäjän &muuttujat &Left Vasemma&lle &Right &Oikealle &Up &Ylös &Down &Alas Close Pa&ne &Sulje ruutu User &Units Käyttäjän &yksiköt &Turn &Kierros If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Jos uusi lauseke alkaa merkillä +, -, * tai /, SpeedCrunch lisää alkuun "ans". &Accept with Enter &Hyväksy Enterillä Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Hyväksy nykyinen automaattisen täydennyksen ehdotus Enterillä valitsematta sitä ensin nuolinäppäimillä. &Units &Yksiköt Show Live Result &Preview Näytä tuloksen live-&esikatselu Save &Window Position on Exit Tallenna &ikkunan sijainti lopetettaessa Hover Highlighting Korostus osoitettaessa Group Integer Part Only Ryhmittele vain kokonaisosa Number Format... Lukumuoto... Notation && Precision... Merkintätapa ja tarkkuus... After pressing Enter, keep the entered expression selected in the editor. Pidä syötetty lauseke valittuna editorissa Enterin painamisen jälkeen. Never Ei koskaan Always Aina Only for Single-Line Expressions Vain yksirivisille lausekkeille Simplify Displayed Expressions Yksinkertaista näytettävät lausekkeet History Size &Limit... Historian koko&raja... Remove Trailing &Zeroes &Poista loppunollat Nearest, Half &Away (round) Lähin, puolikas &poispäin (round) Nearest, Half &Even (roundeven) Lähin, puolikas &parilliseen (roundeven) Toward &Zero (trunc) Kohti &nollaa (trunc) &Fixed-Point &Kiinteä piste &Rational &Rationaalinen &Exponential (m·s�¹) &Eksponentiaalinen (m·s�¹) &Fractional (m/s) &Murtoluku (m/s) &Rectangular (a + bi) &Suorakulmainen (a + bi) Exponential (re�ᶿ) Eksponentiaalinen (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonometrinen (r(cos θ + i·sin θ)) Phasor (r∠θ) Osoitin (r∠θ) &Theme... &Teema... Check for &Updates Tarkista &päivitykset Source Code Lähdekoodi &Zoom &Zoomaus &Results &Tulokset Unit Notation Yksikkömerkintä Rounding Mode Pyöristystila &Notation &Merkintätapa &Imaginary Unit &Imaginaariyksikkö &Window &Ikkuna &Editing &Muokkaus A&utocomplete A&utomaattinen täydennys Up/Down Arrow History Ylös/alas-nuolten historia &Appearance &Ulkoasu &Menus &Valikot &Docks T&elakoitavat paneelit &Input and Results &Syöte ja tulokset &Disabled &Ei käytössä &Disable &Poista käytöstä Close preview Sulje esikatselu Rename... Nimeä uudelleen... Clone... Kloonaa... Close Tab Sulje välilehti New Private Tab Uusi yksityinen välilehti Open... Avaa... Reopen Closed Tab Avaa suljettu välilehti uudelleen Split Jaa Left Vasemmalle Right Oikealle Up Ylös Down Alas Clear Tyhjennä Delete Poista %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Yksityinen istunto: sisältö hylätään suljettaessa. Valitse Istunto > Säilytä, niin istunnosta tulee tavallinen. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Yksityinen] Reset All Settings Palauta kaikki asetukset Reset all settings to their default values? Palautetaanko kaikkien asetusten oletusarvot? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Tämä koskee ulkoasua, muokkausta, tulosten muotoiluja ja ikkuna-asetuksia. Laskelmat, avoimet istunnot ja käyttäjän määrittelyt säilytetään. The settings file could not be written. Asetustiedostoa ei voitu kirjoittaa. Clear this session's calculations, unfinished expression, variables, functions, and units? Tyhjennetäänkö tämän istunnon laskelmat, keskeneräinen lauseke, muuttujat, funktiot ja yksiköt? Global user definitions are kept. Yleiset käyttäjän määrittelyt säilytetään. Make Session Private Muuta istunto yksityiseksi The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Tallennettu istunto %1 poistetaan. Sen sisältö jää auki yksityiseen istuntoon ja hylätään, kun istunto suljetaan tai SpeedCrunch lopetetaan. Make Private Muuta yksityiseksi Could not delete the saved session %1. Tallennettua istuntoa %1 ei voitu poistaa. Keep Session Säilytä istunto Could not save the session. It remains private. Istuntoa ei voitu tallentaa. Se pysyy yksityisenä. Clone Session Kloonaa istunto Could not save session file %1. Istuntotiedostoa %1 ei voitu tallentaa. Could not delete session file %1. Istuntotiedostoa %1 ei voitu poistaa. JSON file (*.json);;Any file (*.*) JSON-tiedosto (*.json);;Mikä tahansa tiedosto (*.*) Export session as JSON Vie istunto JSON:nä The selected file is not valid JSON: %1 Valittu tiedosto ei ole kelvollista JSONia: %1 The selected file is not a SpeedCrunch session JSON file. Valittu tiedosto ei ole SpeedCrunch-istunnon JSON-tiedosto. This file uses an obsolete SpeedCrunch session format and cannot be imported. Tämä tiedosto käyttää vanhentunutta SpeedCrunch-istuntomuotoa, eikä sitä voi tuoda. The selected JSON file is missing the required $schema field. Valitusta JSON-tiedostosta puuttuu pakollinen $schema-kenttä. The selected JSON file uses an unsupported JSON schema: %1 Valittu JSON-tiedosto käyttää tukematonta JSON-skeemaa: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Valitusta JSON-tiedostosta puuttuu SpeedCrunch-istunnon skeematunniste ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Valittu JSON-tiedosto käyttää tukematonta SpeedCrunch-istuntomuotoa: %1 The selected JSON file is missing the required session name. Valitusta JSON-tiedostosta puuttuu pakollinen istunnon nimi. The selected JSON file has an empty session name. Valitussa JSON-tiedostossa on tyhjä istunnon nimi. The selected JSON file has invalid or incomplete SpeedCrunch session data. Valitussa JSON-tiedostossa on virheellisiä tai puutteellisia SpeedCrunch-istunnon tietoja. Open Sessions Folder Avaa istuntokansio Could not create the sessions folder: %1 Istuntokansiota ei voitu luoda: %1 Could not open the sessions folder: %1 Istuntokansiota ei voitu avata: %1 Editor and Results Font Editorin ja tulosten fontti Open Session Avaa istunto Community Yhteisö Rename Session Nimeä istunto uudelleen Clear Session Tyhjennä istunto Delete Session Poista istunto Close Pane Sulje ruutu User Variables Käyttäjän muuttujat User Units Käyttäjän yksiköt Clear History Tyhjennä historia Are you sure you want to clear the calculation history? Haluatko varmasti tyhjentää laskentahistorian? Session name: Istunnon nimi: A session named %1 already exists. Istunto nimeltä %1 on jo olemassa. Could not create session file %1. Istuntotiedoston %1 luominen ei onnistunut. Could not write session file %1. Istuntotiedostoon %1 ei voitu kirjoittaa. Are you sure you want to delete this session? Haluatko varmasti poistaa tämän istunnon? Custom Precision Mukautettu tarkkuus Fractional digits: Desimaalien määrä: Theme Teema Light Themes Vaaleat teemat Dark Themes Tummat teemat Preview Esikatselu Colors Värit Select color for %1 Valitse väri kohteelle %1 Import... Tuo... Export... Vie... Import Theme Tuo teema Theme file (*.json);;All files (*) Teematiedosto (*.json);;Kaikki tiedostot (*) Invalid theme file. Virheellinen teematiedosto. Can't import theme "%1" because it conflicts with a built-in theme. Teemaa "%1" ei voi tuoda, koska se on ristiriidassa sisäänrakennetun teeman kanssa. Can't find a writable theme folder. Kirjoituskelpoista teemakansiota ei löydy. Overwrite Theme Korvaa teema A custom theme named "%1" already exists. Do you want to overwrite it? Mukautettu teema nimeltä "%1" on jo olemassa. Haluatko korvata sen? Can't overwrite theme file %1 Teematiedostoa %1 ei voi korvata Can't copy theme file to %1 Teematiedostoa ei voi kopioida kohteeseen %1 Export Theme Vie teema Can't export theme as "%1" because it conflicts with a built-in theme. Teemaa ei voi viedä nimellä "%1", koska se on ristiriidassa sisäänrakennetun teeman kanssa. Can't write to file %1 Tiedostoon %1 ei voitu kirjoittaa Global User Variable Globaali käyttäjämuuttuja Global User Function Globaali käyttäjäfunktio Global User Unit Globaali käyttäjäyksikkö User Definitions Käyttäjän määrittelyt These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Nämä määrittelyt ovat globaaleja ja ne ladataan jokaiseen istuntoon. Niitä ei voi muuttaa istunnoissa, ja ne ohittavat istuntoeditorin samannimiset määrittelyt. Kirjoita yksi määrittely riville. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Esimerkkejä: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Käytä Validate Tarkista Test Results Testitulokset Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Tuodut muuttujat: %1 Tuodut funktiot: %2 Tuodut yksiköt: %3 Virheitä sisältävien rivien numerot: %4 none ei yhtään Apply Results Käyttöönoton tulokset User definitions saved. Käyttäjän määrittelyt tallennettu. History Size Limit Historian kokoraja Maximum number of history entries for this session (0 = unlimited): Historiamerkintöjen enimmäismäärä tässä istunnossa (0 = rajoittamaton): Text file (*.txt);;Any file (*.*) Tekstitiedostot (*.txt);;Kaikki tiedostot (*.*) Could not recalculate from calculation %1: %2 Uudelleenlaskenta laskusta %1 ei onnistunut: %2 History Size Limit Reached Historian kokoraja saavutettu This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Tämä lasku täyttää viimeisen vapaan historiapaikan. Tulevat laskut poistavat vanhimman laskun historiasta. Voit kasvattaa rajaa kohdasta Istunto > Historian kokoraja. Editing calculation. Press Esc twice to cancel. Laskua muokataan. Peruuta painamalla Esc kahdesti. Calculation Settings Laskun asetukset Invalid recalculation start index Virheellinen uudelleenlaskennan aloitusindeksi System Default Järjestelmän oletus Language Kieli Select the language: Valitse kieli: Custom Mukautettu Decimal places: Desimaalit: &Automatic &Automaattinen &Precision T&arkkuus Plain &text Pelkkä &teksti Formula &Book &Kaavakirja &Export &Vie Export session as HTML Vie istunto HTML:nä HTML file (*.html) HTML-tiedosto (*.html) Export session as plain text Vie istunto pelkkänä tekstinä ManualWindow SpeedCrunch Manual SpeedCrunch-käyttöopas %1 - SpeedCrunch Manual %1 – SpeedCrunch-käyttöopas NumberFormatDialog Number Format Lukumuoto <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Valitse lukumuoto tuloksille ja syötteen numeroiden ryhmittelylle.</b><br/><br/>Huomautus: syötettyjen lukujen yksiselitteiset muodot hyväksytään, vaikka ne poikkeaisivat valitusta näyttömuodosta.<br/> QObject Global User Variable Globaali käyttäjämuuttuja Global User Function Globaali käyttäjäfunktio Global User Unit Globaali käyttäjäyksikkö Backspace Askelpalautin Clear expression Tyhjennä lauseke Evaluate expression Laske lauseke Insert text Lisää teksti Automatic decimal Automaattinen desimaali Fixed-point decimal Kiinteän pisteen desimaali Engineering decimal Tekninen desimaali Scientific decimal Tieteellinen desimaali Rational Rationaalinen Binary Binääri Octal Oktaali Hexadecimal Heksadesimaali Sexagesimal seksagesimaali, 60-järjestelmässä Update Available Päivitys saatavilla A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Uudempi versio (%1) on saatavilla.<br/><a href="%2">Siirry verkkosivulle lataamaan.</a> Check for Updates Tarkista päivitykset SpeedCrunch %1 is up to date. SpeedCrunch %1 on ajan tasalla. No connectivity. Please check your internet connection and try again. Ei yhteyttä. Tarkista internetyhteytesi ja yritä uudelleen. Could not verify the latest available version. Uusinta saatavilla olevaa versiota ei voitu tarkistaa. ResultDisplay Scroll to bottom Vieritä alas Edit Expression Muokkaa lauseketta Change Settings Muuta asetuksia New Tab Uusi välilehti &Import... T&uo... &Export &Vie Plain &text Pelkkä &teksti Copy Kopioi Selection Valinta Select All Valitse kaikki Expression Lauseke Result Tulos Calculation Laskelma Calculation as Single Line Laskelma yhdellä rivillä Remove Poista This Calculation Tämä laskelma All Calculations Above Kaikki yllä olevat laskelmat All Calculations Below Kaikki alla olevat laskelmat New Private Tab Uusi yksityinen välilehti Session Istunto Open... Avaa... Clone... Kloonaa... Rename... Nimeä uudelleen... Keep Säilytä Make Private... Muuta yksityiseksi... Clear Tyhjennä Delete Poista Close Sulje Split Jaa Left Vasemmalle Right Oikealle Up Ylös Down Alas Close Pane Sulje ruutu Main Menu Päävalikko Cancel editing Peruuta muokkaus Copy result Kopioi tulos Edit expression Muokkaa lauseketta Change settings Muuta asetuksia Remove calculation Poista lasku ResultSlotsDialog Notation & Precision Merkintätapa ja tarkkuus Result Line Tulosrivi Enabled Käytössä Notation Merkintätapa Decimal Places Desimaalit Main Line Päärivi Extra Line #1 Lisärivi 1 Extra Line #2 Lisärivi 2 Extra Line #3 Lisärivi 3 Extra Line #4 Lisärivi 4 Auto Automaattinen UserFunctionListWidget Name Nimi Value Arvo Description Kuvaus Search Etsi No match found Ei tuloksia Insert Lisää Edit Muokkaa Delete Poista Delete All Poista kaikki UserUnitListWidget Name Nimi Value Arvo Description Kuvaus Search Etsi No match found Ei tuloksia Insert Lisää Edit Muokkaa Delete Poista Delete All Poista kaikki VariableListWidget Name Nimi Value Arvo Description Kuvaus Search Etsi No match found Ei tuloksia Insert Lisää Edit Muokkaa Delete Poista Delete All Poista kaikki heldercorreia-speedcrunch-e7ca37f/src/resources/locale/fr.ts000066400000000000000000010603201526573132500243560ustar00rootroot00000000000000 AboutBox About SpeedCrunch À propos de SpeedCrunch Core developers Développeurs principaux Original author Auteur initial Close Fermer Math engine Moteur de calcul Main author | Logo | Maintainer Auteur principal | Logo | Mainteneur Thanks Merci Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Les développeurs de SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version SpeedCrunch est un logiciel libre ; vous pouvez le redistribuer et le modifier conformément à la licence « GNU General Public License » telle que publiée à la « Free Software Foundation » ; soit la version 2, soit (à votre convenance) n'importe quelle version ultérieure à cette dernière This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS GARANTIE AUCUNE ; même sans garantie implicite de VALEUR MARCHANDE ou d'ADÉQUATION à un USAGE PARTICULIER. Référez-vous pour plus de détails à la « GNU General Public License ». BitFieldWidget Reset bits to zero Réinitialiser les bits à zéro Invert bits Inverser les bits Shift bits left Décaler les bits vers la gauche Shift bits right Décaler les bits vers la droite Book Index Index Algebra Algèbre Quadratic Equation Équation du second degré Logarithmic Base Conversion Changement de base logarithmique Geometry Géométrie Circle Cercle Sector Secteur Sphere Sphère Cube Cube Cone Cône Cylinder Cylindre Electronics Électronique Ohm's Law Loi d'Ohm Power Puissance Reactance Réactance Resonance Résonance Radio Frequency Fréquence radio Antennas Antennes Characteristic Impedance (coax) Impédance caractéristique (coax) Velocity of Propagation (coax) Vitesse de propagation (coax) Standing Wave Ratio & Return Loss Rapport d'onde stationnaire et perte de retour Free Space Wavelength Longueur d'onde dans le vide resistance résistance voltage tension current intensité power puissance inductive reactance réactance inductive capacitive reactance réactance capacitative inductance inductance capacitance Capacité frequency fréquence resonance frequency fréquence de résonance area aire perimeter périmètre diameter diamètre radius rayon volume volume surface area aire de la base height hauteur slant height apothème face diagonal Diagonale d'une face space diagonal grande diagonale edge length arête arc length Longueur d'arc central angle (degrees) angle (degrés) input power puissance à l'entrée reflected power puissance réfléchie transmitted power puissance transmise return loss perte de retour dielectric constant constante diélectrique outer conductor's inner diameter diamètre intérieur du blindage inner conductor's outer diameter diamètre extérieur de l'âme speed of light vitesse de la lumière reflection coefficient coefficient de réflexion standing wave ratio rapport d'onde stationnaire normalized impedance impédance normalisée frequency (Hz) fréquence (Hz) BookDock Formula Book Recueil de formules ConstantCompletion Search constants Rechercher des constantes No match found Aucune correspondance trouvée Constants Mathematics Mathématiques Physics (CODATA 2022) Physique (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chimie (IUPAC - CIAAW 2021) Uncategorized Non classé Universal Universel Physicochemical Physico-chimie Atomic & Nuclear — General Atomique et nucléaire — Général Atomic & Nuclear — Electroweak Atomique et nucléaire — Électrofaible Atomic & Nuclear — Electron Atomique et nucléaire — Électron Atomic & Nuclear — Muon Atomique et nucléaire — Muon Atomic & Nuclear — Tau Atomique et nucléaire — Tau Atomic & Nuclear — Proton Atomique et nucléaire — Proton Atomic & Nuclear — Neutron Atomique et nucléaire — Neutron Atomic & Nuclear — Deuteron Atomique et nucléaire — Deutéron Atomic & Nuclear — Triton Atomique et nucléaire — Triton Atomic & Nuclear — Helion Atomique et nucléaire — Hélion Atomic & Nuclear — Alpha particle Atomique et nucléaire — Particule alpha Atomic & Nuclear — Atomic units Atomique et nucléaire — Unités atomiques Atomic & Nuclear — Energy conversion relationships Atomique et nucléaire — Relations de conversion d’énergie Atomic & Nuclear — X-ray units Atomique et nucléaire — Unités de rayons X Atomic & Nuclear — Magnetic shielding corrections Atomique et nucléaire — Corrections de blindage magnétique Masses Masses Lifetimes Durées de vie Molar Masses Masses molaires Electronegativity Électronégativité Ionization Energy Énergie d’ionisation Nominal Constants (IAU 2015) Constantes nominales (UAI 2015) Current Best Estimates (IAU NSFA 2026-04) Meilleures estimations actuelles (UAI NSFA 2026-04) characteristic impedance of vacuum (Z₀) impédance caractéristique du vide (Z₀) reduced Planck constant (�) constante de Planck réduite (�) vacuum electric permittivity (ϵ₀) permittivité électrique du vide (ϵ₀) Newtonian constant of gravitation (G) constante gravitationnelle newtonienne (G) vacuum magnetic permeability (μ₀) perméabilité magnétique du vide (μ₀) Planck constant (h) constante de Planck (h) speed of light in vacuum (c) vitesse de la lumière dans le vide (c) standard acceleration of gravity (gₙ) accélération normale de la pesanteur (gₙ) Newtonian constant of gravitation over h-bar c constante gravitationnelle newtonienne sur h-bar c Planck length longueur de Planck Planck constant in eV/Hz (h) constante de Planck en eV/Hz (h) Planck mass masse de Planck Planck mass energy equivalent in GeV équivalent énergétique de la masse de Planck en GeV Planck temperature température de Planck Planck time temps de Planck reduced Planck constant in eV·s (�) constante de Planck réduite en eV·s (�) reduced Planck constant times c in MeV·fm constante de Planck réduite fois c en MeV·fm Bohr magneton magnéton de Bohr conductance quantum (G₀) quantum de conductance (G₀) Coulomb constant (kₑ) constante de Coulomb (kₑ) elementary charge (e) charge élémentaire (e) elementary charge over h-bar charge élémentaire sur h-bar conventional value of Josephson constant valeur conventionnelle de la constante de Josephson Josephson constant constante de Josephson conventional value of ampere-90 valeur conventionnelle de l’ampère-90 conventional value of coulomb-90 valeur conventionnelle du coulomb-90 conventional value of farad-90 valeur conventionnelle du farad-90 conventional value of henry-90 valeur conventionnelle du henry-90 conventional value of ohm-90 valeur conventionnelle de l’ohm-90 conventional value of volt-90 valeur conventionnelle du volt-90 conventional value of watt-90 valeur conventionnelle du watt-90 magnetic flux quantum (Φ₀) quantum de flux magnétique (Φ₀) nuclear magneton magnéton nucléaire inverse of conductance quantum inverse du quantum de conductance conventional value of von Klitzing constant valeur conventionnelle de la constante de von Klitzing von Klitzing constant constante de von Klitzing atomic unit of magnetic dipole moment unité atomique de moment dipolaire magnétique atomic unit of magnetic flux density unité atomique de densité de flux magnétique Bohr magneton in eV/T magnéton de Bohr en eV/T Bohr magneton in Hz/T magnéton de Bohr en Hz/T Bohr magneton in inverse meter per tesla magnéton de Bohr en mètre inverse par tesla Bohr magneton in K/T magnéton de Bohr en K/T nuclear magneton in eV/T magnéton nucléaire en eV/T nuclear magneton in inverse meter per tesla magnéton nucléaire en mètre inverse par tesla nuclear magneton in K/T magnéton nucléaire en K/T nuclear magneton in MHz/T magnéton nucléaire en MHz/T Bohr radius (a₀) rayon de Bohr (a₀) fine-structure constant (α) constante de structure fine (α) Hartree energy (Eₕ) énergie de Hartree (Eₕ) Hartree energy in eV énergie de Hartree en eV quantum of circulation quantum de circulation quantum of circulation times 2 quantum de circulation fois 2 Rydberg constant (R∞) constante de Rydberg (R∞) atomic mass unit-hartree relationship relation unité de masse atomique-hartree atomic mass unit-hertz relationship relation unité de masse atomique-hertz atomic mass unit-inverse meter relationship relation unité de masse atomique-mètre inverse atomic mass unit-joule relationship relation unité de masse atomique-joule atomic mass unit-kelvin relationship relation unité de masse atomique-kelvin atomic mass unit-kilogram relationship relation unité de masse atomique-kilogramme atomic unit of 1st hyperpolarizability unité atomique de première hyperpolarisabilité atomic unit of 2nd hyperpolarizability unité atomique de deuxième hyperpolarisabilité atomic unit of charge (e) unité atomique de charge (e) atomic unit of charge density unité atomique de densité de charge atomic unit of current unité atomique de courant atomic unit of electric dipole moment unité atomique de moment dipolaire électrique atomic unit of electric field unité atomique de champ électrique atomic unit of electric field gradient unité atomique de gradient de champ électrique atomic unit of electric polarizability unité atomique de polarisabilité électrique atomic unit of electric potential unité atomique de potentiel électrique atomic unit of electric quadrupole moment unité atomique de moment quadrupolaire électrique atomic unit of action unité atomique d’action atomic unit of energy unité atomique d’énergie atomic unit of force unité atomique de force atomic unit of length unité atomique de longueur hertz-atomic mass unit relationship relation hertz-unité de masse atomique hertz-electron volt relationship relation hertz-électronvolt hertz-hartree relationship relation hertz-hartree hertz-inverse meter relationship relation hertz-mètre inverse hertz-joule relationship relation hertz-joule hertz-kelvin relationship relation hertz-kelvin hertz-kilogram relationship relation hertz-kilogramme hyperfine transition frequency of Cs-133 fréquence de transition hyperfine du Cs-133 inverse fine-structure constant (α�¹) inverse de la constante de structure fine (α�¹) inverse meter-atomic mass unit relationship relation mètre inverse-unité de masse atomique inverse meter-electron volt relationship relation mètre inverse-électronvolt inverse meter-hartree relationship relation mètre inverse-hartree inverse meter-hertz relationship relation mètre inverse-hertz inverse meter-joule relationship relation mètre inverse-joule inverse meter-kelvin relationship relation mètre inverse-kelvin inverse meter-kilogram relationship relation mètre inverse-kilogramme joule-atomic mass unit relationship relation joule-unité de masse atomique joule-electron volt relationship relation joule-électronvolt joule-hertz relationship relation joule-hertz joule-hartree relationship relation joule-hartree joule-inverse meter relationship relation joule-mètre inverse joule-kelvin relationship relation joule-kelvin joule-kilogram relationship relation joule-kilogramme kelvin-atomic mass unit relationship relation kelvin-unité de masse atomique kelvin-electron volt relationship relation kelvin-électronvolt kelvin-hertz relationship relation kelvin-hertz kelvin-hartree relationship relation kelvin-hartree kelvin-inverse meter relationship relation kelvin-mètre inverse kelvin-joule relationship relation kelvin-joule kelvin-kilogram relationship relation kelvin-kilogramme kilogram-atomic mass unit relationship relation kilogramme-unité de masse atomique kilogram-electron volt relationship relation kilogramme-électronvolt kilogram-hertz relationship relation kilogramme-hertz kilogram-hartree relationship relation kilogramme-hartree kilogram-inverse meter relationship relation kilogramme-mètre inverse kilogram-joule relationship relation kilogramme-joule kilogram-kelvin relationship relation kilogramme-kelvin lattice parameter of silicon (a) paramètre de maille du silicium (a) luminous efficacy efficacité lumineuse natural unit of energy unité naturelle de énergie natural unit of energy in MeV unité naturelle de énergie en MeV natural unit of action (�) unité naturelle de action (�) natural unit of action in eV·s unité naturelle de action en eV·s natural unit of length unité naturelle de longueur natural unit of mass unité naturelle de masse natural unit of momentum unité naturelle de quantité de mouvement natural unit of momentum in MeV/c unité naturelle de quantité de mouvement en MeV/c natural unit of time unité naturelle de temps natural unit of velocity unité naturelle de vitesse Rydberg constant times c in Hz constante de Rydberg fois c en Hz Rydberg constant times hc in eV constante de Rydberg fois hc en eV Rydberg constant times hc in J constante de Rydberg fois hc en J Fermi coupling constant constante de couplage de Fermi weak mixing angle angle de mélange faible W to Z mass ratio rapport de masse W/Z Thomson cross section (σₑ) section efficace de Thomson (σₑ) electron mass (mₑ) masse de l’électron (mₑ) electron mass in u masse de l’électron en u electron mass energy equivalent (mₑ·c²) équivalent énergétique de la masse de l’électron (mₑ·c²) electron mass energy equivalent in MeV équivalent énergétique de la masse de l’électron en MeV reduced Compton wavelength longueur d’onde de Compton réduite classical electron radius (rₑ) rayon classique de l’électron (rₑ) electron charge to mass quotient quotient charge/masse de l’électron electron-deuteron magnetic moment ratio rapport des moments magnétiques électron-deutéron electron-deuteron mass ratio rapport de masse électron-deutéron electron g factor (gₑ) facteur g de l’électron (gₑ) electron gyromagnetic ratio (γₑ) rapport gyromagnétique de l’électron (γₑ) electron gyromagnetic ratio in MHz/T rapport gyromagnétique de l’électron en MHz/T electron-helion mass ratio rapport de masse électron-hélion electron magnetic moment (μₑ) moment magnétique de l’électron (μₑ) electron magnetic moment anomaly (aₑ) anomalie du moment magnétique de l’électron (aₑ) electron magnetic moment to Bohr magneton ratio rapport du moment magnétique de l’électron au magnéton de Bohr electron magnetic moment to nuclear magneton ratio rapport du moment magnétique de l’électron au magnéton nucléaire electron molar mass (Mₑ) masse molaire de l’électron (Mₑ) electron-muon magnetic moment ratio rapport des moments magnétiques électron-muon electron-muon mass ratio rapport de masse électron-muon electron-neutron magnetic moment ratio rapport des moments magnétiques électron-neutron electron-neutron mass ratio rapport de masse électron-neutron electron-proton magnetic moment ratio rapport des moments magnétiques électron-proton electron-proton mass ratio rapport de masse électron-proton electron relative atomic mass (Ar(e)) masse atomique relative de l’électron (Ar(e)) electron-tau mass ratio rapport de masse électron-tau electron to alpha particle mass ratio rapport de masse électron/particule alpha electron to shielded helion magnetic moment ratio rapport du moment magnétique de l’électron à celui de l’hélion écranté electron to shielded proton magnetic moment ratio rapport du moment magnétique de l’électron à celui du proton écranté electron-triton mass ratio rapport de masse électron-triton electron volt-atomic mass unit relationship relation électronvolt-unité de masse atomique electron volt-hartree relationship relation électronvolt-hartree electron volt-hertz relationship relation électronvolt-hertz electron volt-inverse meter relationship relation électronvolt-mètre inverse electron volt-joule relationship relation électronvolt-joule electron volt-kelvin relationship relation électronvolt-kelvin electron volt-kilogram relationship relation électronvolt-kilogramme hartree-atomic mass unit relationship relation hartree-unité de masse atomique hartree-electron volt relationship relation hartree-électronvolt muon Compton wavelength longueur d’onde de Compton du muon muon-electron mass ratio rapport de masse muon-électron muon g factor facteur g du muon muon magnetic moment moment magnétique du muon muon magnetic moment anomaly anomalie du moment magnétique du muon muon magnetic moment to Bohr magneton ratio rapport du moment magnétique du muon au magnéton de Bohr muon magnetic moment to nuclear magneton ratio rapport du moment magnétique du muon au magnéton nucléaire muon mass masse du muon muon mass energy equivalent équivalent énergétique de la masse du muon muon mass energy equivalent in MeV équivalent énergétique de la masse du muon en MeV muon mass in u masse du muon en u muon molar mass masse molaire du muon muon-neutron mass ratio rapport de masse muon-neutron muon-proton magnetic moment ratio rapport des moments magnétiques muon-proton muon-proton mass ratio rapport de masse muon-proton muon-tau mass ratio rapport de masse muon-tau reduced muon Compton wavelength longueur d’onde de Compton réduite du muon reduced tau Compton wavelength longueur d’onde de Compton réduite du tau tau Compton wavelength longueur d’onde de Compton du tau tau-electron mass ratio rapport de masse tau-électron tau mass masse du tau tau mass energy equivalent équivalent énergétique de la masse du tau tau mass in u masse du tau en u tau molar mass masse molaire du tau tau-muon mass ratio rapport de masse tau-muon tau-neutron mass ratio rapport de masse tau-neutron tau-proton mass ratio rapport de masse tau-proton proton charge to mass quotient quotient charge/masse du proton proton Compton wavelength longueur d’onde de Compton du proton proton-electron mass ratio rapport de masse proton-électron proton g factor (gₚ) facteur g du proton (gₚ) proton gyromagnetic ratio (γₚ) rapport gyromagnétique du proton (γₚ) proton gyromagnetic ratio in MHz/T rapport gyromagnétique du proton en MHz/T proton magnetic moment (μₚ) moment magnétique du proton (μₚ) proton magnetic moment to Bohr magneton ratio rapport du moment magnétique du proton au magnéton de Bohr proton magnetic moment to nuclear magneton ratio rapport du moment magnétique du proton au magnéton nucléaire proton magnetic shielding correction correction de blindage magnétique du proton proton mass (mₚ) masse du proton (mₚ) proton mass energy equivalent équivalent énergétique de la masse du proton proton mass energy equivalent in MeV équivalent énergétique de la masse du proton en MeV proton mass in u masse du proton en u proton molar mass (Mₚ) masse molaire du proton (Mₚ) proton-muon mass ratio rapport de masse proton-muon proton-neutron magnetic moment ratio rapport des moments magnétiques proton-neutron proton-neutron mass ratio rapport de masse proton-neutron proton relative atomic mass (Ar(p)) masse atomique relative du proton (Ar(p)) proton rms charge radius rayon de charge quadratique moyen du proton proton-tau mass ratio rapport de masse proton-tau reduced proton Compton wavelength longueur d’onde de Compton réduite du proton shielded proton gyromagnetic ratio rapport gyromagnétique du proton écranté shielded proton gyromagnetic ratio in MHz/T rapport gyromagnétique du proton écranté en MHz/T shielded proton magnetic moment moment magnétique du proton écranté shielded proton magnetic moment to Bohr magneton ratio rapport du moment magnétique du proton écranté au magnéton de Bohr shielded proton magnetic moment to nuclear magneton ratio rapport du moment magnétique du proton écranté au magnéton nucléaire neutron Compton wavelength longueur d’onde de Compton du neutron neutron-electron magnetic moment ratio rapport des moments magnétiques neutron-électron neutron-electron mass ratio rapport de masse neutron-électron neutron g factor (gₙ) facteur g du neutron (gₙ) neutron gyromagnetic ratio (γₙ) rapport gyromagnétique du neutron (γₙ) neutron gyromagnetic ratio in MHz/T rapport gyromagnétique du neutron en MHz/T neutron magnetic moment (μₙ) moment magnétique du neutron (μₙ) neutron magnetic moment to Bohr magneton ratio rapport du moment magnétique du neutron au magnéton de Bohr neutron magnetic moment to nuclear magneton ratio rapport du moment magnétique du neutron au magnéton nucléaire neutron mass (mₙ) masse du neutron (mₙ) neutron mass energy equivalent équivalent énergétique de la masse du neutron neutron mass energy equivalent in MeV équivalent énergétique de la masse du neutron en MeV neutron mass in u masse du neutron en u neutron molar mass (Mₙ) masse molaire du neutron (Mₙ) neutron-muon mass ratio rapport de masse neutron-muon neutron-proton magnetic moment ratio rapport des moments magnétiques neutron-proton neutron-proton mass difference différence de masse neutron-proton neutron-proton mass difference energy equivalent équivalent énergétique de la différence de masse neutron-proton neutron-proton mass difference energy equivalent in MeV équivalent énergétique de la différence de masse neutron-proton en MeV neutron-proton mass difference in u différence de masse neutron-proton en u neutron-proton mass ratio rapport de masse neutron-proton neutron relative atomic mass (Ar(n)) masse atomique relative du neutron (Ar(n)) neutron-tau mass ratio rapport de masse neutron-tau neutron to shielded proton magnetic moment ratio rapport du moment magnétique du neutron à celui du proton écranté reduced neutron Compton wavelength longueur d’onde de Compton réduite du neutron deuteron-electron magnetic moment ratio rapport des moments magnétiques deutéron-électron deuteron-electron mass ratio rapport de masse deutéron-électron deuteron g factor facteur g du deutéron deuteron magnetic moment moment magnétique du deutéron deuteron magnetic moment to Bohr magneton ratio rapport du moment magnétique du deutéron au magnéton de Bohr deuteron magnetic moment to nuclear magneton ratio rapport du moment magnétique du deutéron au magnéton nucléaire deuteron mass masse du deutéron deuteron mass energy equivalent équivalent énergétique de la masse du deutéron deuteron mass energy equivalent in MeV équivalent énergétique de la masse du deutéron en MeV deuteron mass in u masse du deutéron en u deuteron molar mass masse molaire du deutéron deuteron-neutron magnetic moment ratio rapport des moments magnétiques deutéron-neutron deuteron-proton magnetic moment ratio rapport des moments magnétiques deutéron-proton deuteron-proton mass ratio rapport de masse deutéron-proton deuteron relative atomic mass (Ar(d)) masse atomique relative du deutéron (Ar(d)) deuteron rms charge radius rayon de charge quadratique moyen du deutéron triton-electron mass ratio rapport de masse triton-électron triton g factor (gₜ) facteur g du triton (gₜ) triton magnetic moment (μₜ) moment magnétique du triton (μₜ) triton magnetic moment to Bohr magneton ratio rapport du moment magnétique du triton au magnéton de Bohr triton magnetic moment to nuclear magneton ratio rapport du moment magnétique du triton au magnéton nucléaire triton mass (mₜ) masse du triton (mₜ) triton mass energy equivalent équivalent énergétique de la masse du triton triton mass energy equivalent in MeV équivalent énergétique de la masse du triton en MeV triton mass in u masse du triton en u triton molar mass (Mₜ) masse molaire du triton (Mₜ) triton-proton mass ratio rapport de masse triton-proton triton relative atomic mass (Ar(t)) masse atomique relative du triton (Ar(t)) triton to proton magnetic moment ratio rapport du moment magnétique du triton à celui du proton helion-electron mass ratio rapport de masse hélion-électron helion g factor (gₕ) facteur g de l’hélion (gₕ) helion magnetic moment (μₕ) moment magnétique de l’hélion (μₕ) helion magnetic moment to Bohr magneton ratio rapport du moment magnétique de l’hélion au magnéton de Bohr helion magnetic moment to nuclear magneton ratio rapport du moment magnétique de l’hélion au magnéton nucléaire helion mass (mₕ) masse de l’hélion (mₕ) helion mass energy equivalent équivalent énergétique de la masse de l’hélion helion mass energy equivalent in MeV équivalent énergétique de la masse de l’hélion en MeV helion mass in u masse de l’hélion en u helion molar mass (Mₕ) masse molaire de l’hélion (Mₕ) helion-proton mass ratio rapport de masse hélion-proton helion relative atomic mass (Ar(h)) masse atomique relative de l’hélion (Ar(h)) helion shielding shift déplacement de blindage de l’hélion shielded helion gyromagnetic ratio rapport gyromagnétique de l’hélion écranté shielded helion gyromagnetic ratio in MHz/T rapport gyromagnétique de l’hélion écranté en MHz/T shielded helion magnetic moment moment magnétique de l’hélion écranté shielded helion magnetic moment to Bohr magneton ratio rapport du moment magnétique de l’hélion écranté au magnéton de Bohr shielded helion magnetic moment to nuclear magneton ratio rapport du moment magnétique de l’hélion écranté au magnéton nucléaire shielded helion to proton magnetic moment ratio rapport du moment magnétique de l’hélion écranté à celui du proton shielded helion to shielded proton magnetic moment ratio rapport du moment magnétique de l’hélion écranté à celui du proton écranté alpha particle mass masse de la particule alpha alpha particle mass in u masse de la particule alpha en u alpha particle mass energy equivalent équivalent énergétique de la masse de la particule alpha alpha particle mass energy equivalent in MeV équivalent énergétique de la masse de la particule alpha en MeV alpha particle-electron mass ratio rapport de masse particule alpha-électron alpha particle-proton mass ratio rapport de masse particule alpha-proton alpha particle rms charge radius rayon de charge quadratique moyen de la particule alpha alpha particle molar mass masse molaire de la particule alpha alpha particle relative atomic mass (Ar(α)) masse atomique relative de la particule alpha (Ar(α)) atomic mass constant (mᵤ) constante de masse atomique (mᵤ) Avogadro constant constante d’Avogadro Boltzmann constant (k) constante de Boltzmann (k) Boltzmann constant in eV/K constante de Boltzmann en eV/K Boltzmann constant in Hz/K constante de Boltzmann en Hz/K Boltzmann constant in inverse meter per kelvin constante de Boltzmann en mètre inverse par kelvin electron volt (eV) électronvolt (eV) Faraday constant (F) constante de Faraday (F) first radiation constant (c�) première constante de rayonnement (c�) first radiation constant for spectral radiance première constante de rayonnement pour la luminance spectrale molar gas constant (R) constante molaire des gaz (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) constante de Loschmidt (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) constante de Loschmidt (n₀, 273.15 K, 101.325 kPa) molar Planck constant constante de Planck molaire second radiation constant (c₂) deuxième constante de rayonnement (c₂) Stefan-Boltzmann constant (σ) constante de Stefan-Boltzmann (σ) lattice spacing of ideal Si (d₂₂₀) espacement du réseau du Si idéal (d₂₂₀) atomic mass constant energy equivalent équivalent énergétique de la constante de masse atomique atomic mass constant energy equivalent in MeV équivalent énergétique de la constante de masse atomique en MeV atomic mass unit-electron volt relationship relation unité de masse atomique-électronvolt molar mass constant (Mᵤ) constante de masse molaire (Mᵤ) molar mass of carbon-12 masse molaire du carbone 12 molar volume of ideal gas (273.15 K, 100 kPa) volume molaire du gaz parfait (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volume molaire du gaz parfait (273.15 K, 101.325 kPa) molar volume of silicon volume molaire du silicium Sackur-Tetrode constant (1 K, 100 kPa) constante de Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) constante de Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant constante de la loi de déplacement en fréquence de Wien Wien wavelength displacement law constant constante de la loi de déplacement en longueur d’onde de Wien standard atmosphere (atm) atmosphère normale (atm) standard-state pressure (p°) pression d’état standard (p°) Angstrom star (Å*) ångström étoile (Å*) Copper x unit unité x du cuivre Molybdenum x unit unité x du molybdène atomic unit of magnetizability unité atomique de magnétisabilité atomic unit of mass (mₑ) unité atomique de masse (mₑ) atomic unit of momentum unité atomique de quantité de mouvement atomic unit of permittivity unité atomique de permittivité atomic unit of time unité atomique de temps atomic unit of velocity unité atomique de vitesse hartree-hertz relationship relation hartree-hertz hartree-inverse meter relationship relation hartree-mètre inverse hartree-joule relationship relation hartree-joule hartree-kelvin relationship relation hartree-kelvin hartree-kilogram relationship relation hartree-kilogramme shielding difference of d and p in HD différence de blindage entre d et p dans HD shielding difference of t and p in HT différence de blindage entre t et p dans HT pi (π) pi (π) Euler's number (e) nombre d’Euler (e) golden ratio (φ) nombre d’or (φ) Euler-Mascheroni constant (γ) constante d’Euler-Mascheroni (γ) nominal solar radius rayon solaire nominal nominal solar total irradiance irradiance solaire totale nominale nominal solar luminosity luminosité solaire nominale nominal solar effective temperature température effective solaire nominale nominal solar mass parameter paramètre de masse solaire nominal nominal terrestrial equatorial radius rayon équatorial terrestre nominal nominal terrestrial polar radius rayon polaire terrestre nominal nominal terrestrial mass parameter paramètre de masse terrestre nominal nominal jovian equatorial radius rayon équatorial jovien nominal nominal jovian polar radius rayon polaire jovien nominal nominal jovian mass parameter paramètre de masse jovien nominal average value of one minus the rate of TCG relative to TCB valeur moyenne de un moins le taux de TCG par rapport au TCB solar mass parameter (TCB-compatible) paramètre de masse solaire (compatible TCB) solar mass parameter (TDB-compatible) paramètre de masse solaire (compatible TDB) equatorial radius of the Earth (TT-compatible) rayon équatorial de la Terre (compatible TT) dynamical form factor of the Earth facteur de forme dynamique de la Terre time rate of change in the dynamical form factor of the Earth taux de variation du facteur de forme dynamique de la Terre geocentric gravitational constant (TCB-compatible) constante gravitationnelle géocentrique (TCB-compatible) geocentric gravitational constant (TT-compatible) constante gravitationnelle géocentrique (TT-compatible) geocentric gravitational constant (TDB-compatible) constante gravitationnelle géocentrique (TDB-compatible) potential of the geoid potentiel du géoïde nominal mean angular velocity of the Earth (TT-compatible) vitesse angulaire moyenne nominale de la Terre (compatible TT) ratio mass of the Moon to the Earth rapport de masse de la Lune à la Terre ratio of the mass of the Sun to Mercury rapport de la masse du Soleil à Mercure ratio of the mass of the Sun to Venus rapport de la masse du Soleil à Vénus ratio of the mass of the Sun to Mars rapport de la masse du Soleil à Mars ratio of the mass of the Sun to Jupiter rapport de la masse du Soleil à Jupiter ratio of the mass of the Sun to Saturn rapport de la masse du Soleil à Saturne ratio of the mass of the Sun to Uranus rapport de la masse du Soleil à Uranus ratio of the mass of the Sun to Neptune rapport de la masse du Soleil à Neptune ratio of the mass of the Sun to (134340) Pluto rapport de la masse du Soleil à (134340) Pluton ratio of the mass of the Sun to (136199) Eris rapport de la masse du Soleil à (136199) Éris ratio of the mass of (1) Ceres to the Sun rapport de la masse de (1) Cérès au Soleil ratio of the mass of (2) Pallas to the Sun rapport de la masse de (2) Pallas au Soleil ratio of the mass of (4) Vesta to the Sun rapport de la masse de (4) Vesta au Soleil mean obliquity of the ecliptic at J2000.0 obliquité moyenne de l’écliptique à J2000.0 Electromagnetic Électromagnétique Compton wavelength Longueur d'onde de Compton Astronomy Astronomie ConstantsWidget Domain Domaine Subdomain Sous-domaine No match found Introuvable Name Nom Value Valeur Unit Unité Search Rechercher All Tout CustomKeypadDialog Custom Keypad Pavé personnalisé Rows: Lignes : Columns: Colonnes : Copy preset: Copier le préréglage : Basic Basique Scientific (wide) Scientifique (large) Scientific (narrow) Scientifique (étroit) Apply Appliquer Row Ligne Column Colonne Label Étiquette Behavior Comportement Text Texte DiagnosticsDialog App Diagnostics Diagnostic de l’application Copy to Clipboard Copier dans le presse-papiers Editor Unit Unité User unit Unité utilisateur User function Fonction utilisateur Argument Argument Current result:<br/>%1 Résultat actuel :<br/>%1 Selection result:<br/>%1 Résultat de la sélection :<br/>%1 Selection result: n/a Résultat de la sélection : n/a Selection result: %1 Résultat de la sélection : %1 second seconde metre mètre kilogram kilogramme mole mole radian radian steradian stéradian degree Celsius degré Celsius cubic metre mètre cube cubic millimetre millimètre cube cubic centimetre centimètre cube cubic decimetre décimètre cube cubic kilometre kilomètre cube square millimetre millimètre carré square kilometre kilomètre carré square metre mètre carré minute minute hour heure day jour astronomical unit unité astronomique degree degré arcminute minute d’arc arcsecond seconde d’arc milliarcsecond milliseconde d’arc microarcsecond microseconde d’arc hectare hectare litre litre tonne tonne Dalton dalton electronvolt électronvolt Angstrom ångström atmosphere atmosphère atomic mass unit unité de masse atomique British thermal unit unité thermique britannique calorie calorie carat carat cup tasse cup (Imperial) tasse (impériale) cup (Japanese) tasse (japonaise) cup (US) tasse (US) degree Fahrenheit degré Fahrenheit fathom brasse fluid ounce (Imperial) once liquide (impériale) fluid ounce (US) once liquide (US) fluid dram (Imperial) drachme liquide (impériale) fluid dram (US) drachme liquide (US) foot pied square foot pied carré cubic foot pied cube gallon (Imperial) gallon (impérial) gallon (US) gallon (US) gill (Imperial) gill (impérial) gill (US) gill (US) gradian grade grain grain gram gramme Hartley hartley Hartree energy unit unité d’énergie de Hartree horsepower cheval-vapeur inch pouce square inch pouce carré cubic inch pouce cube karat carat knot nœud lightminute minute-lumière lightsecond seconde-lumière lightyear année-lumière long ton tonne longue mile mille square mile mille carré cubic mile mille cube mile per hour mille par heure kilometre per hour kilomètre par heure nautical mile mille marin ounce once parsec parsec pint (Imperial) pinte (impériale) pint (US) pinte (US) pound livre pounds per square inch livres par pouce carré quart (Imperial) quart (impérial) quart (US) quart (US) oil barrel baril de pétrole beer barrel (US) baril de bière (US) square yard yard carré cubic yard yard cube short ton tonne courte tablespoon cuillère à soupe tablespoon (Australian) cuillère à soupe (australienne) tablespoon (Imperial) cuillère à soupe (impériale) tablespoon (US) cuillère à soupe (US) dessert spoon cuillère à dessert teaspoon cuillère à café teaspoon (Imperial) cuillère à café (impériale) teaspoon (US) cuillère à café (US) turn tour revolution révolution revolution per minute révolution par minute week semaine kilowatt hour kilowattheure millimetre of mercury millimètre de mercure yard yard Julian century siècle julien Julian year année julienne sidereal year année sidérale tropical year année tropique Evaluator invalid expression expression invalide division by zero division par zéro too time consuming - computation was rejected le calcul a été abandonné car trop long dimension mismatch - quantities with different dimensions cannot be compared, added, etc. Incompatibilité de dimension - les quantités avec différentes dimensions ne peuvent être comparées, additionnées, etc. invalid dimension - operation might require dimensionless arguments Dimension invalide - l'opération pourrait requérir des arguments sans dimension Computation aborted - encountered numerical instability le calcul a été abandonné en raison d'une instabilité numérique invalid dimension - function might require dimensionless arguments Dimension invalide - la fonction pourrait requérir des arguments sans dimension error erreur unit must not be zero L'unité ne doit pas être égale à zéro Conversion failed - dimension mismatch Échec de la conversion - incompatibilité des dimensions unknown function or variable fonction ou variable inconnue recursion not supported récursion non supportée cannot operate on a NaN opération non permise sur un NaN underflow - tiny result is out of SpeedCrunch's number range sous-dépassement - ce très petit résultat est hors de la plage numérique de SpeedCrunch overflow - huge result is out of SpeedCrunch's number range dépassement - ce gigantesque résultat est en dehors des possibilités de SpeedCrunch overflow - logic result exceeds maximum of 256 bits dépassement - le résultat logique dépasse la valeur maximum (256 bits) overflow - integer result exceeds maximum limit for integers dépassement - le résultat entier dépasse le maximum pour les entiers operation is not defined for these arguments l’opération n’est pas définie pour ces arguments wrong number of arguments nombre d'arguments incorrect does not take NaN as an argument l'argument ne doit pas être un NaN result out of range résultat hors limites undefined for argument domain argument hors domaine computation too expensive calcul trop coûteux internal error, please report a bug erreur interne, merci de déclarer ce bug syntax error erreur de syntaxe conversion target must be a unit la cible de conversion doit être une unité unknown unit unité inconnue %1 is a reserved name, please choose another %1 est un mot réservé, merci d'en choisir un autre %1 is a global user definition and cannot be overridden in this session. %1 est une définition utilisateur globale et ne peut pas être redéfinie dans cette session. %1 is a variable name, please choose another or delete the variable %1 est un nom de variable, merci de choisir un autre nom ou d'effacer la variable argument %1 is used more than once l'argument %1 est utilisé plus d'une fois %1 is a built-in unit name, please choose another %1 est un nom d’unité intégré, veuillez en choisir un autre %1 is a user function name, please choose another or delete the function %1 est le nom d'une fonction utilisateur, merci de choisir un autre nom et d'effacer la fonction FunctionRepo max; trials; probability max ; tirages ; probabilité trials; probability tirages ; probabilité hits; trials; probability succès ; tirages ; probabilité max; total; hits; trials max ; total ; succès ; tirages total; hits; trials total ; succès ; tirages count; total; hits; trials nombre ; total ; succès ; tirages dividend; divisor dividende ; diviseur x; exponent_bits; significand_bits [; exponent_bias] x; bits_d_exposant; bits_de_significande [; décalage_d_exposant] base; x base ; x value; modulo valeur ; modulo base; exponent; modulo base ; exposant ; modulo events; average_events événements ; fréquence moyenne average_events fréquence moyenne x [; precision] x [; précision] Absolute Value Valeur absolue Absolute Deviation Déviation absolue Arc Cosine Arc cosinus Logical AND ET logique Area Hyperbolic Cosine Surface cosinus hyperbolique Area Hyperbolic Sine Surface sinus hyperbolique Area Hyperbolic Tangent Surface tangente hyperbolique Arc Sine Arc sinus Arc Tangent Arc tangente Arc Tangent with two Arguments Arc tangente avec deux arguments Average (Arithmetic Mean) Moyenne arithmétique Binomial Cumulative Distribution Function Fonction de répartition Binomial Distribution Mean Espérance d'une distribution binomiale Binomial Probability Mass Function Densité de probabilité d'une distribution binomiale Binomial Distribution Variance Variance d'une distribution binomiale Cube Root Racine cubique Complex Conjugate Conjugué Cosine Cosinus Hyperbolic Cosine Cosinus hyperbolique Cotangent Cotangente Cosecant Cosécante Convert Unix timestamp to Date Convertir l'heure Unix en date Degrees of Arc Degrés d'arc Error Function Fonction d'erreur Complementary Error Function Fonction d'erreur complémentaire Exponential Exponentielle Fractional Part Partie fractionnaire Extension of Factorials [= (x-1)!] Factorielle généralisée [= (x-1)!] Greatest Common Divisor Plus Grand Commun Diviseur Geometric Mean Moyenne géométrique Gradians of arc Convertir en grade Hypergeometric Cumulative Distribution Function Fonction de distribution hypergéométrique Hypergeometric Distribution Mean Moyenne d'une distribution hypergéométrique Hypergeometric Probability Mass Function Densité de probabilité d'une distribution hypergéométrique Hypergeometric Distribution Variance Variance d'une distribution hypergéométrique Integer Quotient Division euclidienne Integer Part Partie entière Imaginary Part Partie imaginaire Decode IEEE-754 Binary Value Décoder une valeur binaire IEEE-754 Encode IEEE-754 Binary Value Encoder une valeur binaire IEEE-754 Decode 16-bit Half-Precision Value Décoder une valeur 16 bit demi précision Encode 16-bit Half-Precision Value Encoder une valeur 16 bit demi précision Decode 32-bit Single-Precision Value Décoder une valeur 32 bit simple précision Encode 32-bit Single-Precision Value Encoder une valeur 32 bit simple précision Decode 64-bit Double-Precision Value Décoder une valeur 64 bit double précision Encode 64-bit Double-Precision Value Encoder une valeur 64 bit double précision Decode 128-bit Quad-Precision Value Décoder une valeur 128 bit quadruple précision Encode 128-bit Quad-Precision Value Encoder une valeur 128 bit quadruple précision Binary Logarithm Logarithme binaire Common Logarithm Logarithme décimal Natural Logarithm Logarithme népérien Logarithm to Arbitrary Base Logarithme de base arbitraire Mask to a bit size Masque binaire Maximum Maximum Median Value (50th Percentile) Médiane (50%) Minimum Minimum Modulo Modulo Euclidean Modulo Modulo euclidien Modular Exponentiation Exponentiation modulaire Combination (Binomial Coefficient) Coefficient binomial (combinaison) Logical NOT NON logique Permutation (Arrangement) Permutation (arrangement) Convert to Binary Representation Convertir en binaire Arithmetic Arithmétique Chemistry Chimie Complex Complexes Combinatorics Combinatoire Probability Probabilités Statistics Statistiques Aggregation Agrégation Random Aléatoire Base conversion Conversion de base Number formatting Formatage des nombres Integer arithmetic Arithmétique entière Special functions Fonctions spéciales Exponential & Logarithmic Exponentielles et logarithmes Angle conversion Conversion d’angles Trigonometry Trigonométrie Bitwise Bit à bit Floating point Virgule flottante Date & Time Date et heure Linear algebra Algèbre linéaire unix_timestamp; x hours offset to GMT heure_unix; écart en heures vers GMT yyyymmdd.hhmmss; x hours offset to GMT aaaammjj.hhmmss ; décalage de x heures par rapport au GMT [digits] [chiffres] max [; min] max [; min] List Literal Littéral de liste Convert to Padded Binary Representation Convertir en représentation binaire complétée Round Toward +∞ (Ceiling) Arrondir vers +∞ (plafond) Cosine plus Imaginary Sine Cosinus plus sinus imaginaire Convert to Cis Complex Form Convertir en forme complexe cis Matrix Column Count Nombre de colonnes de la matrice Population Correlation Matrix (n) Matrice de corrélation de population (n) Sample Correlation Matrix (n-1) Matrice de corrélation d’échantillon (n-1) Count Nombre Population Covariance Matrix (n) Matrice de covariance de population (n) Sample Covariance Matrix (n-1) Matrice de covariance d’échantillon (n-1) Cross Product Produit vectoriel Convert Date to Unix timestamp Convertir la date en horodatage Unix Convert to Decimal Representation Convertir en décimal Determinant Déterminant Convert to Sexagesimal Notation Convertir en notation sexagésimale Dot Product Produit scalaire Convert to Engineering Notation Convertir en notation d’ingénierie Convert to Exponential Complex Form Convertir en forme complexe exponentielle Round Toward −∞ (Floor) Arrondir vers −∞ (plancher) Flatten Matrix Aplatir la matrice Least Common Multiple Plus petit commun multiple Convert to Hexadecimal Representation Convertir en hexadécimal Convert to Padded Hexadecimal Representation Convertir en représentation hexadécimale complétée Inverse Matrix Matrice inverse Round to 16-bit Half-Precision Value Arrondir en demi-précision 16 bits Round to 32-bit Single-Precision Value Arrondir en simple précision 32 bits Round to 64-bit Double-Precision Value Arrondir en double précision 64 bits Round to 128-bit Quad-Precision Value Arrondir en quadruple précision 128 bits Residual from 16-bit Half-Precision Rounding Résidu de l’arrondi en demi-précision 16 bits Residual from 32-bit Single-Precision Rounding Résidu de l’arrondi en simple précision 32 bits Residual from 64-bit Double-Precision Rounding Résidu de l’arrondi en double précision 64 bits Residual from 128-bit Quad-Precision Rounding Résidu de l’arrondi en quadruple précision 128 bits Substance Mass Masse de substance Molarity Molarité Molar Mass Masse molaire Median Absolute Deviation Écart absolu médian Mean Moyenne Numerical Value of Quantity Valeur numérique de la grandeur Random Decimal Number Nombre décimal aléatoire Random Integer Number Nombre entier aléatoire Convert to Rational Representation Convertir en représentation rationnelle Convert to Octal Representation Convertir en octal Convert to Padded Octal Representation Convertir en représentation octale complétée Vector or Matrix Norm Norme de vecteur ou de matrice Logical OR OU logique Population Count (Hamming Weight) Nombre de bits à 1 (poids de Hamming) Phase of Complex Number Argument d'un nombre complexe Poissonian Cumulative Distribution Function Fonction de distribution de Poisson Poissonian Distribution Mean Espérance d'une distribution de Poisson Poissonian Probability Mass Function Densité de probabilité d'une loi de Poisson Poissonian Distribution Variance Variance d'une distribution de Poisson Convert to Phasor Complex Form Convertir en forme complexe phaseur Convert to Rectangular Complex Form Convertir en forme complexe rectangulaire Round Half Away from Zero Arrondir au demi en s’éloignant de zéro Round Half Even Arrondir au demi pair Nth Root Racine n-ième Convert to Scientific Notation Convertir en notation scientifique Matrix Row Count Nombre de lignes de la matrice List or Matrix Shape Dimensions de la liste ou de la matrice Summation Somme Population Standard Deviation (n) Écart type de population (n) Sample Standard Deviation (n-1) Écart type d’échantillon (n-1) Round Toward Zero (Truncation) Arrondir vers zéro (troncature) Matrix Trace Trace de la matrice Transpose Matrix Transposer la matrice Population Variance (n) Variance de population (n) Sample Variance (n-1) Variance d’échantillon (n-1) Product Produit Radians Radians Matrix Rank Rang de la matrice Real Part Partie réelle Secant Sécante Arithmetic Shift Left Décalage arithmétique vers la gauche Arithmetic Shift Right Décalage arithmétique vers la droite Signum Signe Sine Sinus Hyperbolic Sine Sinus hyperbolique Square Root Racine carrée Sum Somme Tangent Tangente Convert to Trigonometric Complex Form Convertir en forme complexe trigonométrique Turns Tours Hyperbolic Tangent Tangente hyperbolique Sign-extend a value Extension de signe Logical XOR XOR logique FunctionsWidget Domain Domaine All Tout Name Nom Search Rechercher No match found Introuvable Identifier Identifiant HistoryWidget Remove All Calculations Above Supprimer tous les calculs au-dessus Remove This Calculation Supprimer ce calcul Remove All Calculations Below Supprimer tous les calculs au-dessous Keypad Inverse cosine Arc cosinus The last result Le dernier résultat Inverse sine Arc sinus Inverse tangent Arc tangent Evaluate expression Évaluer l’expression Division Division Multiplication Multiplication Subtraction Soustraction Addition Addition Clear expression Effacer l'expression Cosine Cosinus Backspace Retour arrière Scientific notation Notation scientifique Exponential Exponentielle Factorial Factorielle Natural logarithm Logarithme naturel Left parenthesis Parenthèse gauche Nth root Racine n-ième Argument separator Séparateur d’arguments Square Carré Common logarithm Logarithme décimal Modulo Modulo Contextual percentage Pourcentage contextuel Power Puissance Right parenthesis Parenthèse droite Sine Sinus Square root Racine carrée Tangent Tangente Pi Pi Decimal separator Séparateur décimal MainWindow Radian Radian Degree Degrés Gradian Grade Binary Binaire Octal Octal Hexadecimal Hexadécimal Sexagesimal Sexagésimal Engineering decimal Décimal d'ingénierie Scientific decimal Décimal scientifique &Import... &Importer... &Quit &Quitter Clear E&xpression Effacer l'e&xpression Clear &History Effacer l'&historique &Copy &Copier &Paste C&oller &Select Expression &Sélectionner une expression &Constants &Constantes &Functions &Fonctions &History &Historique &Status Bar &Barre d'état Bitfield Champ de bits Use&r Functions Fonctions utilisateu&r &Degree &Degrés &Radian &Radian &Gradian &Grade Re&volution Ré&volution Auto-Insert a&ns I&nsérer automatiquement ans Automatic &Completion &Compléter automatiquement &Built-in Functions &Fonctions intégrées Built-in &Variables &Variables intégrées User &Functions F&onctions utilisateur User Va&riables Va&riables utilisateur Open a Private Tab on Startup Ouvrir un onglet privé au démarrage Open and focus a new private tab whenever SpeedCrunch starts. Ouvrir un nouvel onglet privé et l’activer à chaque démarrage de SpeedCrunch. Syntax &Highlighting Mettre la &syntaxe en évidence Group Digits in &Input Grouper les ch&iffres saisis Automatic Input &Adjustments &Ajustements automatiques de la saisie Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ajuster automatiquement les opérateurs, les espaces, les parenthèses et les puissances, et limiter la saisie aux caractères valides. Group input digits using the selected number format. Grouper les chiffres saisis selon le format numérique choisi. &Blinking Cursor &Curseur clignotant Blink the cursor in the expression editor. Faire clignoter le curseur dans l’éditeur d’expressions. &Escape Clears Editor Échap &efface l’éditeur Clear the focused expression editor with Escape after dismissing any popup or preview. Effacer le contenu de l’éditeur d’expressions actif avec Échap après avoir fermé toute fenêtre contextuelle ou tout aperçu. Keep Expression After Evaluation Conserver l’expression après le calcul Copy New Results Automatically Copier automatiquement les nouveaux résultats &Comma &Virgule &System Default &Séparateur par défaut &Dot &Point Dot &And Comma Point &et virgule Toward +∞ (&ceil) Vers +∞ (&ceil) Toward −∞ (&floor) Vers −∞ (&floor) &Binary &Binaire &Engineering &Ingénierie &Hexadecimal &Hexadécimal &Octal &Octal &Scientific &Scientifique User &Manual &Manuel utilisateur Issues and &Feedback &Problèmes et commentaires &Donate Faire un &don &About SpeedCrunch &À propos de SpeedCrunch App Diag&nostics Diag&nostic de l’application S&plit &Scinder Angle &Mode &Mode angulaire &Complex Form Forme &complexe New Tab Nouvel onglet Constants Constantes Functions Fonctions History Historique User Functions Fonctions utilisateur &Font... Police... &Language... &Langue... &Session &Session &Edit &Édition &View &Affichage Se&ttings Op&tions &Decimal &Décimal &Keypad &Pavé numérique Always on &Top &Toujours au premier plan Disabled Désactivé Small Space Petit espace Medium Space Espace moyen Large Space Grand espace &0 Digits &0 décimales &15 Digits &15 décimales &2 Digits &2 décimales &3 Digits &3 décimales &50 Digits &50 décimales &8 Digits &8 décimales &Sexagesimal &Sexagésimal Reset All Settings... Réinitialiser tous les paramètres... &System &Système SpeedCrunch &Theme &Thème SpeedCrunch &Classic &Classique &Modern &Moderne Context Help Aide contextuelle &Help &Aide Error Erreur Can't read from file %1 Impossible de lire le fichier %1 Import Session Importer une session Close Session Fermer la session Angle Mode: Mode angulaire : Notation: Notation : Precision: Précision : Turn Tour Revolution Révolution Fixed-point decimal Décimal à virgule fixe Rational Rationnel Automatic decimal Décimal automatique Automatic Automatique User &Definitions... &Définitions utilisateur... New &Tab Nouvel &onglet New &Private Tab Nouvel onglet &privé Keep Conserver Make Private... Rendre privé... New &Window Nouvelle &fenêtre &Open... &Ouvrir... &Rename... &Renommer... Clo&ne... Clo&ner... &Close Tab F&ermer l’onglet Reopen Clo&sed Tab Ro&uvrir l’onglet fermé Open Sessions &Folder Ouvrir le &dossier des sessions &Undo Ann&uler &Redo &Rétablir Cu&t Cou&per Copy &Last Result Copier &le dernier résultat &Wrap in Parentheses &Entourer de parenthèses Full Scr&een Mode M&ode plein écran &Basic &Basique &Scientific (wide) &Scientifique (large) Scientific (narrow) Scientifique (étroit) &Custom... &Personnalisé... Main &Menu &Menu principal User &Variables &Variables utilisateur &Left &Gauche &Right D&roite &Up Ha&ut &Down &Bas Close Pa&ne F&ermer le volet User &Units &Unités utilisateur &Turn &Tour If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Si une nouvelle expression commence par +, -, * ou /, SpeedCrunch insère d’abord « ans ». &Accept with Enter &Accepter avec Entrée Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Accepter la suggestion actuelle de complétion automatique avec Entrée sans la sélectionner d’abord avec les touches fléchées. &Units &Unités Show Live Result &Preview Afficher l’&aperçu du résultat en direct Save &Window Position on Exit Enregistrer la position de la &fenêtre en quittant Hover Highlighting Surbrillance au survol Group Integer Part Only Grouper seulement la partie entière Number Format... Format des nombres... Notation && Precision... Notation et précision... After pressing Enter, keep the entered expression selected in the editor. Après avoir appuyé sur Entrée, conserver l’expression saisie sélectionnée dans l’éditeur. Never Jamais Always Toujours Only for Single-Line Expressions Seulement pour les expressions sur une ligne Simplify Displayed Expressions Simplifier les expressions affichées History Size &Limit... &Limite de taille de l’historique... Remove Trailing &Zeroes Supprimer les &zéros finaux Nearest, Half &Away (round) Le plus proche, demi &éloigné (round) Nearest, Half &Even (roundeven) Le plus proche, demi &pair (roundeven) Toward &Zero (trunc) Vers &zéro (trunc) &Fixed-Point Virgule &fixe &Rational &Rationnel &Exponential (m·s�¹) &Exponentielle (m·s�¹) &Fractional (m/s) &Fractionnaire (m/s) &Rectangular (a + bi) &Rectangulaire (a + bi) Exponential (re�ᶿ) Exponentielle (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonométrique (r(cos θ + i·sin θ)) Phasor (r∠θ) Phaseur (r∠θ) &Theme... &Thème... Check for &Updates Rechercher des &mises à jour Source Code Code source &Zoom &Zoom &Results &Résultats Unit Notation Notation des unités Rounding Mode Mode d’arrondi &Notation &Notation &Imaginary Unit Unité &imaginaire &Window &Fenêtre &Editing &Édition A&utocomplete Saisie semi-a&utomatique Up/Down Arrow History Historique avec flèches haut/bas &Appearance &Apparence &Menus &Menus &Docks P&anneaux ancrables &Input and Results Sa&isie et résultats &Disabled &Désactivé &Disable &Désactiver Close preview Fermer l’aperçu Rename... Renommer... Clone... Cloner... Close Tab Fermer l’onglet New Private Tab Nouvel onglet privé Open... Ouvrir... Reopen Closed Tab Rouvrir l’onglet fermé Split Scinder Left Gauche Right Droite Up Haut Down Bas Clear Vider Delete Effacer %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Session privée : son contenu est supprimé à sa fermeture. Choisissez Session > Conserver pour en faire une session normale. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privé] Reset All Settings Réinitialiser tous les paramètres Reset all settings to their default values? Rétablir les valeurs par défaut de tous les paramètres ? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Cela comprend l’apparence, la saisie, les formats de résultats et les préférences de fenêtre. Vos calculs, sessions ouvertes et définitions utilisateur seront conservés. The settings file could not be written. Impossible d’écrire le fichier de paramètres. Clear this session's calculations, unfinished expression, variables, functions, and units? Effacer les calculs, l’expression inachevée, les variables, les fonctions et les unités de cette session ? Global user definitions are kept. Les définitions utilisateur globales sont conservées. Make Session Private Rendre la session privée The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. La session enregistrée %1 sera supprimée. Son contenu restera ouvert dans une session privée et sera supprimé à la fermeture de cette session ou de SpeedCrunch. Make Private Rendre privé Could not delete the saved session %1. Impossible de supprimer la session enregistrée %1. Keep Session Conserver la session Could not save the session. It remains private. Impossible d’enregistrer la session. Elle reste privée. Clone Session Cloner la session Could not save session file %1. Impossible d’enregistrer le fichier de session %1. Could not delete session file %1. Impossible de supprimer le fichier de session %1. JSON file (*.json);;Any file (*.*) Fichier JSON (*.json);;Tout fichier (*.*) Export session as JSON Exporter la session en JSON The selected file is not valid JSON: %1 Le fichier sélectionné n'est pas un JSON valide : %1 The selected file is not a SpeedCrunch session JSON file. Le fichier sélectionné n'est pas un fichier JSON de session SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Ce fichier utilise un format de session SpeedCrunch obsolète et ne peut pas être importé. The selected JSON file is missing the required $schema field. Le fichier JSON sélectionné ne contient pas le champ obligatoire $schema. The selected JSON file uses an unsupported JSON schema: %1 Le fichier JSON sélectionné utilise un schéma JSON non pris en charge : %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Le fichier JSON sélectionné ne contient pas l'identifiant de schéma de session SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Le fichier JSON sélectionné utilise un format de session SpeedCrunch non pris en charge : %1 The selected JSON file is missing the required session name. Le fichier JSON sélectionné ne contient pas le nom de session obligatoire. The selected JSON file has an empty session name. Le fichier JSON sélectionné a un nom de session vide. The selected JSON file has invalid or incomplete SpeedCrunch session data. Le fichier JSON sélectionné contient des données de session SpeedCrunch invalides ou incomplètes. Open Sessions Folder Ouvrir le dossier des sessions Could not create the sessions folder: %1 Impossible de créer le dossier des sessions : %1 Could not open the sessions folder: %1 Impossible d'ouvrir le dossier des sessions : %1 Editor and Results Font Police de l’éditeur et des résultats Open Session Ouvrir une session Community Communauté Rename Session Renommer la session Clear Session Effacer la session Delete Session Supprimer la session Close Pane Fermer le volet User Variables Variables utilisateur User Units Unités utilisateur Clear History Effacer l’historique Are you sure you want to clear the calculation history? Voulez-vous vraiment effacer l’historique des calculs ? Session name: Nom de la session : A session named %1 already exists. Une session nommée %1 existe déjà. Could not create session file %1. Impossible de créer le fichier de session %1. Could not write session file %1. Impossible d’écrire le fichier de session %1. Are you sure you want to delete this session? Voulez-vous vraiment supprimer cette session ? Custom Precision Précision personnalisée Fractional digits: Chiffres fractionnaires : Theme Thème Light Themes Thèmes clairs Dark Themes Thèmes sombres Preview Aperçu Colors Couleurs Select color for %1 Sélectionner la couleur pour %1 Import... Importer... Export... Exporter... Import Theme Importer un thème Theme file (*.json);;All files (*) Fichier de thème (*.json);;Tous les fichiers (*) Invalid theme file. Fichier de thème invalide. Can't import theme "%1" because it conflicts with a built-in theme. Impossible d’importer le thème « %1 » car il est en conflit avec un thème intégré. Can't find a writable theme folder. Impossible de trouver un dossier de thèmes accessible en écriture. Overwrite Theme Écraser le thème A custom theme named "%1" already exists. Do you want to overwrite it? Un thème personnalisé nommé « %1 » existe déjà. Voulez-vous l’écraser ? Can't overwrite theme file %1 Impossible d’écraser le fichier de thème %1 Can't copy theme file to %1 Impossible de copier le fichier de thème vers %1 Export Theme Exporter le thème Can't export theme as "%1" because it conflicts with a built-in theme. Impossible d’exporter le thème sous « %1 » car il est en conflit avec un thème intégré. Can't write to file %1 Impossible d'écrire dans le fichier %1 Global User Variable Variable utilisateur globale Global User Function Fonction utilisateur globale Global User Unit Unité utilisateur globale User Definitions Définitions utilisateur These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Ces définitions sont globales et sont chargées dans chaque session. Elles ne peuvent pas être modifiées dans les sessions et ont priorité sur les définitions de même nom de l'éditeur de session. Saisissez une définition par ligne. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Exemples : my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Appliquer Validate Valider Test Results Résultats du test Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variables importées : %1 Fonctions importées : %2 Unités importées : %3 Numéros des lignes comportant des erreurs : %4 none aucun Apply Results Résultats de l'application User definitions saved. Définitions utilisateur enregistrées. History Size Limit Limite de taille de l’historique Maximum number of history entries for this session (0 = unlimited): Nombre maximal d’entrées d’historique pour cette session (0 = illimité) : Text file (*.txt);;Any file (*.*) Fichier texte (*.txt);;Tout fichier (*.*) Could not recalculate from calculation %1: %2 Impossible de recalculer depuis le calcul %1 : %2 History Size Limit Reached Limite de taille de l’historique atteinte This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Ce calcul remplit le dernier emplacement disponible de l’historique. Les prochains calculs supprimeront le calcul le plus ancien de l’historique. Vous pouvez augmenter la limite depuis Session > Limite de taille de l’historique. Editing calculation. Press Esc twice to cancel. Modification du calcul. Appuyez deux fois sur Échap pour annuler. Calculation Settings Paramètres du calcul Invalid recalculation start index Indice de départ du recalcul invalide System Default Par défaut Language Langue Select the language: Choisissez la langue : Custom Personnalisé Decimal places: Décimales : &Automatic Automatique &Precision Précision Plain &text Texte simple Formula &Book Recueil de formules &Export Exporter Export session as HTML Exporter la session en HTML HTML file (*.html) Fichier HTML (*.html) Export session as plain text Exporter la session en texte simple ManualWindow SpeedCrunch Manual Manuel de SpeedCrunch %1 - SpeedCrunch Manual %1 - Manuel de SpeedCrunch NumberFormatDialog Number Format Format des nombres <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Choisissez le format numérique des résultats et du groupement des chiffres saisis.</b><br/><br/>Remarque : pour les nombres saisis, les formats non ambigus sont acceptés même s’ils diffèrent du format d’affichage choisi.<br/> QObject Global User Variable Variable utilisateur globale Global User Function Fonction utilisateur globale Global User Unit Unité utilisateur globale Backspace Retour arrière Clear expression Effacer l’expression Evaluate expression Évaluer l’expression Insert text Insérer du texte Automatic decimal Décimal automatique Fixed-point decimal Décimal à virgule fixe Engineering decimal Décimal d’ingénierie Scientific decimal Décimal scientifique Rational Rationnel Binary Binaire Octal Octal Hexadecimal Hexadécimal Sexagesimal Sexagésimal Update Available Mise à jour disponible A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Une version plus récente (%1) est disponible.<br/><a href="%2">Visitez le site web pour la télécharger.</a> Check for Updates Rechercher des mises à jour SpeedCrunch %1 is up to date. SpeedCrunch %1 est à jour. No connectivity. Please check your internet connection and try again. Aucune connexion. Veuillez vérifier votre connexion internet et réessayer. Could not verify the latest available version. Impossible de vérifier la dernière version disponible. ResultDisplay Scroll to bottom Faire défiler vers le bas Edit Expression Modifier l’expression Change Settings Modifier les paramètres New Tab Nouvel onglet &Import... &Importer... &Export &Exporter Plain &text &Texte simple Copy Copier Selection Sélection Select All Tout sélectionner Expression Expression Result Résultat Calculation Calcul Calculation as Single Line Calcul sur une seule ligne Remove Supprimer This Calculation Ce calcul All Calculations Above Tous les calculs au-dessus All Calculations Below Tous les calculs au-dessous New Private Tab Nouvel onglet privé Session Session Open... Ouvrir... Clone... Cloner... Rename... Renommer... Keep Conserver Make Private... Rendre privé... Clear Vider Delete Effacer Close Fermer Split Scinder Left Gauche Right Droite Up Haut Down Bas Close Pane Fermer le volet Main Menu Menu principal Cancel editing Annuler la modification Copy result Copier le résultat Edit expression Modifier l’expression Change settings Modifier les paramètres Remove calculation Supprimer le calcul ResultSlotsDialog Notation & Precision Notation et précision Result Line Ligne de résultat Enabled Activé Notation Notation Decimal Places Décimales Main Line Ligne principale Extra Line #1 Ligne supplémentaire n° 1 Extra Line #2 Ligne supplémentaire n° 2 Extra Line #3 Ligne supplémentaire n° 3 Extra Line #4 Ligne supplémentaire n° 4 Auto Auto UserFunctionListWidget Name Nom Value Valeur Description Description Search Recherche No match found Aucun élément trouvé Insert Insérer Edit Édition Delete Effacer Delete All Effacer tout UserUnitListWidget Name Nom Value Valeur Description Description Search Rechercher No match found Aucun résultat trouvé Insert Insérer Edit Modifier Delete Supprimer Delete All Tout supprimer VariableListWidget Name Nom Value Valeur Description Description Search Rechercher No match found Introuvable Insert Insérer Edit Modifier Delete Effacer Delete All Effacer tout heldercorreia-speedcrunch-e7ca37f/src/resources/locale/gl.ts000066400000000000000000010555561526573132500243700ustar00rootroot00000000000000 AboutBox About SpeedCrunch Acerca de SpeedCrunch Main author | Logo | Maintainer Autor principal | Logotipo | Mantedor Core developers Desenvolvedores principais Original author Autor orixinal Math engine Motor matemático Thanks Agradecementos Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Os desenvolvedores de SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este programa é software libre; pode redistribuílo e/ou modificalo baixo os termos da Licenza Pública Xeral GNU publicada pola Free Software Foundation; ben a versión 2 da licenza, ou (á súa elección) calquera versión posterior This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa distribúese coa esperanza de que sexa útil, pero SEN NINGUNHA GARANT�A; nin sequera a garantía implícita de COMERCIALIZACIÓN ou IDONEIDADE PARA UN PROPÓSITO PARTICULAR. Vexa a Licenza Pública Xeral GNU para máis detalles. Close Pechar BitFieldWidget Reset bits to zero Restablecer os bits a cero Invert bits Inverter os bits Shift bits left Desprazar os bits á esquerda Shift bits right Desprazar os bits á dereita Book Index �ndice Algebra �lxebra Quadratic Equation Ecuación cadrática Logarithmic Base Conversion Conversión de base logarítmica Geometry Xeometría Circle Círculo Sector Sector Sphere Esfera Cube Cubo Cone Cono Cylinder Cilindro Electronics Electrónica Ohm's Law Lei de Ohm Power Potencia Reactance Reactancia Resonance Resonancia Radio Frequency Radiofrecuencia Antennas Antenas Characteristic Impedance (coax) Impedancia característica (coaxial) Velocity of Propagation (coax) Velocidade de propagación (coaxial) Standing Wave Ratio & Return Loss Relación de onda estacionaria e perda de retorno Free Space Wavelength Lonxitude de onda no espazo libre resistance resistencia voltage tensión current corrente power potencia inductive reactance reactancia indutiva capacitive reactance reactancia capacitiva inductance indutancia capacitance capacitancia frequency frecuencia resonance frequency frecuencia de resonancia area área perimeter perímetro diameter diámetro radius raio volume volume surface area área superficial height altura slant height xeratriz face diagonal diagonal da face space diagonal diagonal espacial edge length lonxitude da aresta arc length lonxitude do arco central angle (degrees) ángulo central (graos) dielectric constant constante dieléctrica outer conductor's inner diameter diámetro interior do condutor exterior inner conductor's outer diameter diámetro exterior do condutor interior speed of light velocidade da luz input power potencia de entrada reflected power potencia reflectida transmitted power potencia transmitida return loss perda de retorno reflection coefficient coeficiente de reflexión standing wave ratio relación de onda estacionaria normalized impedance impedancia normalizada frequency (Hz) frecuencia (Hz) BookDock Formula Book Libro de fórmulas ConstantCompletion Search constants Buscar constantes No match found Non se atopou ningunha coincidencia Constants Mathematics Matemáticas Physics (CODATA 2022) Física (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Química (IUPAC - CIAAW 2021) Uncategorized Sen categoría Universal Universal Physicochemical Físico-química Atomic & Nuclear — General Atómica e nuclear — Xeral Atomic & Nuclear — Electroweak Atómica e nuclear — Electrodébil Atomic & Nuclear — Electron Atómica e nuclear — Electrón Atomic & Nuclear — Muon Atómica e nuclear — Muón Atomic & Nuclear — Tau Atómica e nuclear — Tau Atomic & Nuclear — Proton Atómica e nuclear — Protón Atomic & Nuclear — Neutron Atómica e nuclear — Neutrón Atomic & Nuclear — Deuteron Atómica e nuclear — Deuterón Atomic & Nuclear — Triton Atómica e nuclear — Tritón Atomic & Nuclear — Helion Atómica e nuclear — Helión Atomic & Nuclear — Alpha particle Atómica e nuclear — Partícula alfa Atomic & Nuclear — Atomic units Atómica e nuclear — Unidades atómicas Atomic & Nuclear — Energy conversion relationships Atómica e nuclear — Relacións de conversión de enerxía Atomic & Nuclear — X-ray units Atómica e nuclear — Unidades de raios X Atomic & Nuclear — Magnetic shielding corrections Atómica e nuclear — Correccións de blindaxe magnética Masses Masas Lifetimes Tempos de vida Molar Masses Masas molares Electronegativity Electronegatividade Ionization Energy Enerxía de ionización Nominal Constants (IAU 2015) Constantes nominais (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Mellores estimacións actuais (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) impedancia característica do baleiro (Z₀) reduced Planck constant (�) constante de Planck reducida (�) vacuum electric permittivity (ϵ₀) permitividade eléctrica do baleiro (ϵ₀) Newtonian constant of gravitation (G) constante newtoniana da gravitación (G) vacuum magnetic permeability (μ₀) permeabilidade magnética do baleiro (μ₀) Planck constant (h) constante de Planck (h) speed of light in vacuum (c) velocidade da luz no baleiro (c) standard acceleration of gravity (gₙ) aceleración normal da gravidade (gₙ) Newtonian constant of gravitation over h-bar c constante newtoniana da gravitación sobre h-bar c Planck length lonxitude de Planck Planck constant in eV/Hz (h) constante de Planck en eV/Hz (h) Planck mass masa de Planck Planck mass energy equivalent in GeV equivalente energético da masa de Planck en GeV Planck temperature temperatura de Planck Planck time tempo de Planck reduced Planck constant in eV·s (�) constante de Planck reducida en eV·s (�) reduced Planck constant times c in MeV·fm constante de Planck reducida veces c en MeV·fm Bohr magneton magnetón de Bohr conductance quantum (G₀) quantum de condutancia (G₀) Coulomb constant (kₑ) constante de Coulomb (kₑ) elementary charge (e) carga elemental (e) elementary charge over h-bar carga elemental sobre h-bar conventional value of Josephson constant valor convencional da constante de Josephson Josephson constant constante de Josephson conventional value of ampere-90 valor convencional do ampere-90 conventional value of coulomb-90 valor convencional do coulomb-90 conventional value of farad-90 valor convencional do farad-90 conventional value of henry-90 valor convencional do henry-90 conventional value of ohm-90 valor convencional do ohm-90 conventional value of volt-90 valor convencional do volt-90 conventional value of watt-90 valor convencional do watt-90 magnetic flux quantum (Φ₀) quantum de fluxo magnético (Φ₀) nuclear magneton magnetón nuclear inverse of conductance quantum inverso do quantum de condutancia conventional value of von Klitzing constant valor convencional da constante de von Klitzing von Klitzing constant constante de von Klitzing atomic unit of magnetic dipole moment unidade atómica de momento dipolar magnético atomic unit of magnetic flux density unidade atómica de densidade de fluxo magnético Bohr magneton in eV/T magnetón de Bohr en eV/T Bohr magneton in Hz/T magnetón de Bohr en Hz/T Bohr magneton in inverse meter per tesla magnetón de Bohr en metro inverso por tesla Bohr magneton in K/T magnetón de Bohr en K/T nuclear magneton in eV/T magnetón nuclear en eV/T nuclear magneton in inverse meter per tesla magnetón nuclear en metro inverso por tesla nuclear magneton in K/T magnetón nuclear en K/T nuclear magneton in MHz/T magnetón nuclear en MHz/T Bohr radius (a₀) raio de Bohr (a₀) fine-structure constant (α) constante de estrutura fina (α) Hartree energy (Eₕ) enerxía de Hartree (Eₕ) Hartree energy in eV enerxía de Hartree en eV quantum of circulation quantum de circulación quantum of circulation times 2 quantum de circulación veces 2 Rydberg constant (R∞) constante de Rydberg (R∞) atomic mass unit-hartree relationship relación unidade de masa atómica-hartree atomic mass unit-hertz relationship relación unidade de masa atómica-hertz atomic mass unit-inverse meter relationship relación unidade de masa atómica-metro inverso atomic mass unit-joule relationship relación unidade de masa atómica-joule atomic mass unit-kelvin relationship relación unidade de masa atómica-kelvin atomic mass unit-kilogram relationship relación unidade de masa atómica-quilograma atomic unit of 1st hyperpolarizability unidade atómica de 1.ª hiperpolarizabilidade atomic unit of 2nd hyperpolarizability unidade atómica de 2.ª hiperpolarizabilidade atomic unit of charge (e) unidade atómica de carga (e) atomic unit of charge density unidade atómica de densidade de carga atomic unit of current unidade atómica de corrente atomic unit of electric dipole moment unidade atómica de momento dipolar eléctrico atomic unit of electric field unidade atómica de campo eléctrico atomic unit of electric field gradient unidade atómica de gradiente de campo eléctrico atomic unit of electric polarizability unidade atómica de polarizabilidade eléctrica atomic unit of electric potential unidade atómica de potencial eléctrico atomic unit of electric quadrupole moment unidade atómica de momento quadrupolar eléctrico atomic unit of action unidade atómica de acción atomic unit of energy unidade atómica de enerxía atomic unit of force unidade atómica de forza atomic unit of length unidade atómica de lonxitude hertz-atomic mass unit relationship relación hertz-unidade de masa atómica hertz-electron volt relationship relación hertz-electrón-volt hertz-hartree relationship relación hertz-hartree hertz-inverse meter relationship relación hertz-metro inverso hertz-joule relationship relación hertz-joule hertz-kelvin relationship relación hertz-kelvin hertz-kilogram relationship relación hertz-quilograma hyperfine transition frequency of Cs-133 frecuencia de transición hiperfina do Cs-133 inverse fine-structure constant (α�¹) constante inversa de estrutura fina (α�¹) inverse meter-atomic mass unit relationship relación metro inverso-unidade de masa atómica inverse meter-electron volt relationship relación metro inverso-electrón-volt inverse meter-hartree relationship relación metro inverso-hartree inverse meter-hertz relationship relación metro inverso-hertz inverse meter-joule relationship relación metro inverso-joule inverse meter-kelvin relationship relación metro inverso-kelvin inverse meter-kilogram relationship relación metro inverso-quilograma joule-atomic mass unit relationship relación joule-unidade de masa atómica joule-electron volt relationship relación joule-electrón-volt joule-hertz relationship relación joule-hertz joule-hartree relationship relación joule-hartree joule-inverse meter relationship relación joule-metro inverso joule-kelvin relationship relación joule-kelvin joule-kilogram relationship relación joule-quilograma kelvin-atomic mass unit relationship relación kelvin-unidade de masa atómica kelvin-electron volt relationship relación kelvin-electrón-volt kelvin-hertz relationship relación kelvin-hertz kelvin-hartree relationship relación kelvin-hartree kelvin-inverse meter relationship relación kelvin-metro inverso kelvin-joule relationship relación kelvin-joule kelvin-kilogram relationship relación kelvin-quilograma kilogram-atomic mass unit relationship relación quilograma-unidade de masa atómica kilogram-electron volt relationship relación quilograma-electrón-volt kilogram-hertz relationship relación quilograma-hertz kilogram-hartree relationship relación quilograma-hartree kilogram-inverse meter relationship relación quilograma-metro inverso kilogram-joule relationship relación quilograma-joule kilogram-kelvin relationship relación quilograma-kelvin lattice parameter of silicon (a) parámetro de rede do silicio (a) luminous efficacy eficácia luminosa natural unit of energy unidade natural de enerxía natural unit of energy in MeV unidade natural de enerxía en MeV natural unit of action (�) unidade natural de acción (�) natural unit of action in eV·s unidade natural de acción en eV·s natural unit of length unidade natural de lonxitude natural unit of mass unidade natural de masa natural unit of momentum unidade natural de momento natural unit of momentum in MeV/c unidade natural de momento en MeV/c natural unit of time unidade natural de tempo natural unit of velocity unidade natural de velocidade Rydberg constant times c in Hz constante de Rydberg veces c en Hz Rydberg constant times hc in eV constante de Rydberg veces hc en eV Rydberg constant times hc in J constante de Rydberg veces hc en J Fermi coupling constant constante de acoplamento de Fermi weak mixing angle ángulo de mistura fraca W to Z mass ratio razón entre as masas W e Z Thomson cross section (σₑ) sección eficaz de Thomson (σₑ) electron mass (mₑ) masa do electrón (mₑ) electron mass in u masa do electrón en u electron mass energy equivalent (mₑ·c²) equivalente energético da masa do electrón (mₑ·c²) electron mass energy equivalent in MeV equivalente energético da masa do electrón en MeV reduced Compton wavelength lonxitude de onda de Compton reducida classical electron radius (rₑ) raio clássico do electrón (rₑ) electron charge to mass quotient cociente carga-masa do electrón electron-deuteron magnetic moment ratio razón dos momentos magnéticos electrón-deuterón electron-deuteron mass ratio razón das masas electrón-deuterón electron g factor (gₑ) factor g do electrón (gₑ) electron gyromagnetic ratio (γₑ) razón giromagnética do electrón (γₑ) electron gyromagnetic ratio in MHz/T razón giromagnética do electrón en MHz/T electron-helion mass ratio razón das masas electrón-helión electron magnetic moment (μₑ) momento magnético do electrón (μₑ) electron magnetic moment anomaly (aₑ) anomalia do momento magnético do electrón (aₑ) electron magnetic moment to Bohr magneton ratio razón entre o momento magnético do electrón e o magnetón de Bohr electron magnetic moment to nuclear magneton ratio razón entre o momento magnético do electrón e o magnetón nuclear electron molar mass (Mₑ) masa molar do electrón (Mₑ) electron-muon magnetic moment ratio razón dos momentos magnéticos electrón-muón electron-muon mass ratio razón das masas electrón-muón electron-neutron magnetic moment ratio razón dos momentos magnéticos electrón-neutrón electron-neutron mass ratio razón das masas electrón-neutrón electron-proton magnetic moment ratio razón dos momentos magnéticos electrón-protón electron-proton mass ratio razón das masas electrón-protón electron relative atomic mass (Ar(e)) masa atómica relativa do electrón (Ar(e)) electron-tau mass ratio razón das masas electrón-tau electron to alpha particle mass ratio razón entre as masas do electrón e da partícula alfa electron to shielded helion magnetic moment ratio razón entre os momentos magnéticos do electrón e do helión blindado electron to shielded proton magnetic moment ratio razón entre os momentos magnéticos do electrón e do protón blindado electron-triton mass ratio razón das masas electrón-tritón electron volt-atomic mass unit relationship relación electrón-volt-unidade de masa atómica electron volt-hartree relationship relación electrón-volt-hartree electron volt-hertz relationship relación electrón-volt-hertz electron volt-inverse meter relationship relación electrón-volt-metro inverso electron volt-joule relationship relación electrón-volt-joule electron volt-kelvin relationship relación electrón-volt-kelvin electron volt-kilogram relationship relación electrón-volt-quilograma hartree-atomic mass unit relationship relación hartree-unidade de masa atómica hartree-electron volt relationship relación hartree-electrón-volt muon Compton wavelength lonxitude de onda de Compton do muón muon-electron mass ratio razón das masas muón-electrón muon g factor factor g do muón muon magnetic moment momento magnético do muón muon magnetic moment anomaly anomalia do momento magnético do muón muon magnetic moment to Bohr magneton ratio razón entre o momento magnético do muón e o magnetón de Bohr muon magnetic moment to nuclear magneton ratio razón entre o momento magnético do muón e o magnetón nuclear muon mass masa do muón muon mass energy equivalent equivalente energético da masa do muón muon mass energy equivalent in MeV equivalente energético da masa do muón en MeV muon mass in u masa do muón en u muon molar mass masa molar do muón muon-neutron mass ratio razón das masas muón-neutrón muon-proton magnetic moment ratio razón dos momentos magnéticos muón-protón muon-proton mass ratio razón das masas muón-protón muon-tau mass ratio razón das masas muón-tau reduced muon Compton wavelength lonxitude de onda de Compton reducida do muón reduced tau Compton wavelength lonxitude de onda de Compton reducida do tau tau Compton wavelength lonxitude de onda de Compton do tau tau-electron mass ratio razón das masas tau-electrón tau mass masa do tau tau mass energy equivalent equivalente energético da masa do tau tau mass in u masa do tau en u tau molar mass masa molar do tau tau-muon mass ratio razón das masas tau-muón tau-neutron mass ratio razón das masas tau-neutrón tau-proton mass ratio razón das masas tau-protón proton charge to mass quotient cociente carga-masa do protón proton Compton wavelength lonxitude de onda de Compton do protón proton-electron mass ratio razón das masas protón-electrón proton g factor (gₚ) factor g do protón (gₚ) proton gyromagnetic ratio (γₚ) razón giromagnética do protón (γₚ) proton gyromagnetic ratio in MHz/T razón giromagnética do protón en MHz/T proton magnetic moment (μₚ) momento magnético do protón (μₚ) proton magnetic moment to Bohr magneton ratio razón entre o momento magnético do protón e o magnetón de Bohr proton magnetic moment to nuclear magneton ratio razón entre o momento magnético do protón e o magnetón nuclear proton magnetic shielding correction corrección de blindaxe magnética do protón proton mass (mₚ) masa do protón (mₚ) proton mass energy equivalent equivalente energético da masa do protón proton mass energy equivalent in MeV equivalente energético da masa do protón en MeV proton mass in u masa do protón en u proton molar mass (Mₚ) masa molar do protón (Mₚ) proton-muon mass ratio razón das masas protón-muón proton-neutron magnetic moment ratio razón dos momentos magnéticos protón-neutrón proton-neutron mass ratio razón das masas protón-neutrón proton relative atomic mass (Ar(p)) masa atómica relativa do protón (Ar(p)) proton rms charge radius raio de carga rms do protón proton-tau mass ratio razón das masas protón-tau reduced proton Compton wavelength lonxitude de onda de Compton reducida do protón shielded proton gyromagnetic ratio razón giromagnética do protón blindado shielded proton gyromagnetic ratio in MHz/T razón giromagnética do protón blindado en MHz/T shielded proton magnetic moment momento magnético do protón blindado shielded proton magnetic moment to Bohr magneton ratio razón entre o momento magnético do protón blindado e o magnetón de Bohr shielded proton magnetic moment to nuclear magneton ratio razón entre o momento magnético do protón blindado e o magnetón nuclear neutron Compton wavelength lonxitude de onda de Compton do neutrón neutron-electron magnetic moment ratio razón dos momentos magnéticos neutrón-electrón neutron-electron mass ratio razón das masas neutrón-electrón neutron g factor (gₙ) factor g do neutrón (gₙ) neutron gyromagnetic ratio (γₙ) razón giromagnética do neutrón (γₙ) neutron gyromagnetic ratio in MHz/T razón giromagnética do neutrón en MHz/T neutron magnetic moment (μₙ) momento magnético do neutrón (μₙ) neutron magnetic moment to Bohr magneton ratio razón entre o momento magnético do neutrón e o magnetón de Bohr neutron magnetic moment to nuclear magneton ratio razón entre o momento magnético do neutrón e o magnetón nuclear neutron mass (mₙ) masa do neutrón (mₙ) neutron mass energy equivalent equivalente energético da masa do neutrón neutron mass energy equivalent in MeV equivalente energético da masa do neutrón en MeV neutron mass in u masa do neutrón en u neutron molar mass (Mₙ) masa molar do neutrón (Mₙ) neutron-muon mass ratio razón das masas neutrón-muón neutron-proton magnetic moment ratio razón dos momentos magnéticos neutrón-protón neutron-proton mass difference diferenza de masas neutrón-protón neutron-proton mass difference energy equivalent equivalente energético da diferenza de masas neutrón-protón neutron-proton mass difference energy equivalent in MeV equivalente energético da diferenza de masas neutrón-protón en MeV neutron-proton mass difference in u diferenza de masas neutrón-protón en u neutron-proton mass ratio razón das masas neutrón-protón neutron relative atomic mass (Ar(n)) masa atómica relativa do neutrón (Ar(n)) neutron-tau mass ratio razón das masas neutrón-tau neutron to shielded proton magnetic moment ratio razón entre os momentos magnéticos do neutrón e do protón blindado reduced neutron Compton wavelength lonxitude de onda de Compton reducida do neutrón deuteron-electron magnetic moment ratio razón dos momentos magnéticos deuterón-electrón deuteron-electron mass ratio razón das masas deuterón-electrón deuteron g factor factor g do deuterón deuteron magnetic moment momento magnético do deuterón deuteron magnetic moment to Bohr magneton ratio razón entre o momento magnético do deuterón e o magnetón de Bohr deuteron magnetic moment to nuclear magneton ratio razón entre o momento magnético do deuterón e o magnetón nuclear deuteron mass masa do deuterón deuteron mass energy equivalent equivalente energético da masa do deuterón deuteron mass energy equivalent in MeV equivalente energético da masa do deuterón en MeV deuteron mass in u masa do deuterón en u deuteron molar mass masa molar do deuterón deuteron-neutron magnetic moment ratio razón dos momentos magnéticos deuterón-neutrón deuteron-proton magnetic moment ratio razón dos momentos magnéticos deuterón-protón deuteron-proton mass ratio razón das masas deuterón-protón deuteron relative atomic mass (Ar(d)) masa atómica relativa do deuterón (Ar(d)) deuteron rms charge radius raio de carga rms do deuterón triton-electron mass ratio razón das masas tritón-electrón triton g factor (gₜ) factor g do tritón (gₜ) triton magnetic moment (μₜ) momento magnético do tritón (μₜ) triton magnetic moment to Bohr magneton ratio razón entre o momento magnético do tritón e o magnetón de Bohr triton magnetic moment to nuclear magneton ratio razón entre o momento magnético do tritón e o magnetón nuclear triton mass (mₜ) masa do tritón (mₜ) triton mass energy equivalent equivalente energético da masa do tritón triton mass energy equivalent in MeV equivalente energético da masa do tritón en MeV triton mass in u masa do tritón en u triton molar mass (Mₜ) masa molar do tritón (Mₜ) triton-proton mass ratio razón das masas tritón-protón triton relative atomic mass (Ar(t)) masa atómica relativa do tritón (Ar(t)) triton to proton magnetic moment ratio razón entre os momentos magnéticos do tritón e do protón helion-electron mass ratio razón das masas helión-electrón helion g factor (gₕ) factor g do helión (gₕ) helion magnetic moment (μₕ) momento magnético do helión (μₕ) helion magnetic moment to Bohr magneton ratio razón entre o momento magnético do helión e o magnetón de Bohr helion magnetic moment to nuclear magneton ratio razón entre o momento magnético do helión e o magnetón nuclear helion mass (mₕ) masa do helión (mₕ) helion mass energy equivalent equivalente energético da masa do helión helion mass energy equivalent in MeV equivalente energético da masa do helión en MeV helion mass in u masa do helión en u helion molar mass (Mₕ) masa molar do helión (Mₕ) helion-proton mass ratio razón das masas helión-protón helion relative atomic mass (Ar(h)) masa atómica relativa do helión (Ar(h)) helion shielding shift desprazamento de blindaxe do helión shielded helion gyromagnetic ratio razón giromagnética do helión blindado shielded helion gyromagnetic ratio in MHz/T razón giromagnética do helión blindado en MHz/T shielded helion magnetic moment momento magnético do helión blindado shielded helion magnetic moment to Bohr magneton ratio razón entre o momento magnético do helión blindado e o magnetón de Bohr shielded helion magnetic moment to nuclear magneton ratio razón entre o momento magnético do helión blindado e o magnetón nuclear shielded helion to proton magnetic moment ratio razón entre os momentos magnéticos do helión blindado e do protón shielded helion to shielded proton magnetic moment ratio razón entre os momentos magnéticos do helión blindado e do protón blindado alpha particle mass masa da partícula alfa alpha particle mass in u masa da partícula alfa en u alpha particle mass energy equivalent equivalente energético da masa da partícula alfa alpha particle mass energy equivalent in MeV equivalente energético da masa da partícula alfa en MeV alpha particle-electron mass ratio razón das masas partícula alfa-electrón alpha particle-proton mass ratio razón das masas partícula alfa-protón alpha particle rms charge radius raio de carga rms da partícula alfa alpha particle molar mass masa molar da partícula alfa alpha particle relative atomic mass (Ar(α)) masa atómica relativa da partícula alfa (Ar(α)) atomic mass constant (mᵤ) constante de masa atómica (mᵤ) Avogadro constant constante de Avogadro Boltzmann constant (k) constante de Boltzmann (k) Boltzmann constant in eV/K constante de Boltzmann en eV/K Boltzmann constant in Hz/K constante de Boltzmann en Hz/K Boltzmann constant in inverse meter per kelvin constante de Boltzmann en metro inverso por kelvin electron volt (eV) electrón-volt (eV) Faraday constant (F) constante de Faraday (F) first radiation constant (c�) primeira constante de radiación (c�) first radiation constant for spectral radiance primeira constante de radiación para radiancia espectral molar gas constant (R) constante molar dos gases (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) constante de Loschmidt (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) constante de Loschmidt (n₀, 273.15 K, 101.325 kPa) molar Planck constant constante de Planck molar second radiation constant (c₂) segunda constante de radiación (c₂) Stefan-Boltzmann constant (σ) constante de Stefan-Boltzmann (σ) lattice spacing of ideal Si (d₂₂₀) espazamento de rede do Si ideal (d₂₂₀) atomic mass constant energy equivalent equivalente energético da constante de masa atómica atomic mass constant energy equivalent in MeV equivalente energético da constante de masa atómica en MeV atomic mass unit-electron volt relationship relación unidade de masa atómica-electrón-volt molar mass constant (Mᵤ) constante de masa molar (Mᵤ) molar mass of carbon-12 masa molar do carbono-12 molar volume of ideal gas (273.15 K, 100 kPa) volume molar dun gas ideal (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volume molar dun gas ideal (273.15 K, 101.325 kPa) molar volume of silicon volume molar do silicio Sackur-Tetrode constant (1 K, 100 kPa) constante de Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) constante de Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant constante da lei do desprazamento de frecuencia de Wien Wien wavelength displacement law constant constante da lei do desprazamento de lonxitude de onda de Wien standard atmosphere (atm) atmosfera normal (atm) standard-state pressure (p°) presión de estado estándar (p°) Angstrom star (Å*) ångström estrela (Å*) Copper x unit unidade x do cobre Molybdenum x unit unidade x do molibdénio atomic unit of magnetizability unidade atómica de magnetizabilidade atomic unit of mass (mₑ) unidade atómica de masa (mₑ) atomic unit of momentum unidade atómica de momento atomic unit of permittivity unidade atómica de permitividade atomic unit of time unidade atómica de tempo atomic unit of velocity unidade atómica de velocidade hartree-hertz relationship relación hartree-hertz hartree-inverse meter relationship relación hartree-metro inverso hartree-joule relationship relación hartree-joule hartree-kelvin relationship relación hartree-kelvin hartree-kilogram relationship relación hartree-quilograma shielding difference of d and p in HD diferenza de blindaxe de d e p en HD shielding difference of t and p in HT diferenza de blindaxe de t e p en HT pi (π) pi (π) Euler's number (e) número de Euler (e) golden ratio (φ) razón áurea (φ) Euler-Mascheroni constant (γ) constante de Euler-Mascheroni (γ) nominal solar radius raio solar nominal nominal solar total irradiance irradiancia solar total nominal nominal solar luminosity luminosidade solar nominal nominal solar effective temperature temperatura efectiva solar nominal nominal solar mass parameter parámetro de masa solar nominal nominal terrestrial equatorial radius raio equatorial terrestre nominal nominal terrestrial polar radius raio polar terrestre nominal nominal terrestrial mass parameter parámetro de masa terrestre nominal nominal jovian equatorial radius raio equatorial joviano nominal nominal jovian polar radius raio polar joviano nominal nominal jovian mass parameter parámetro de masa joviano nominal average value of one minus the rate of TCG relative to TCB valor medio de un menos a taxa de TCG respecto de TCB solar mass parameter (TCB-compatible) parámetro de masa solar (compatible con TCB) solar mass parameter (TDB-compatible) parámetro de masa solar (compatible con TDB) equatorial radius of the Earth (TT-compatible) raio equatorial da Terra (compatible con TT) dynamical form factor of the Earth factor de forma dinámico da Terra time rate of change in the dynamical form factor of the Earth taxa temporal de variación do factor de forma dinámico da Terra geocentric gravitational constant (TCB-compatible) constante gravitacional xeocéntrica (compatible con TCB) geocentric gravitational constant (TT-compatible) constante gravitacional xeocéntrica (compatible con TT) geocentric gravitational constant (TDB-compatible) constante gravitacional xeocéntrica (compatible con TDB) potential of the geoid potencial do geoide nominal mean angular velocity of the Earth (TT-compatible) velocidade angular media nominal da Terra (compatible con TT) ratio mass of the Moon to the Earth razón entre a masa da Lua e a da Terra ratio of the mass of the Sun to Mercury razón entre a masa do Sol e a de Mercurio ratio of the mass of the Sun to Venus razón entre a masa do Sol e a de Vénus ratio of the mass of the Sun to Mars razón entre a masa do Sol e a de Marte ratio of the mass of the Sun to Jupiter razón entre a masa do Sol e a de Júpiter ratio of the mass of the Sun to Saturn razón entre a masa do Sol e a de Saturno ratio of the mass of the Sun to Uranus razón entre a masa do Sol e a de Urano ratio of the mass of the Sun to Neptune razón entre a masa do Sol e a de Neptuno ratio of the mass of the Sun to (134340) Pluto razón entre a masa do Sol e a de (134340) Plutón ratio of the mass of the Sun to (136199) Eris razón entre a masa do Sol e a de (136199) Eris ratio of the mass of (1) Ceres to the Sun razón entre a masa de (1) Ceres e a do Sol ratio of the mass of (2) Pallas to the Sun razón entre a masa de (2) Pallas e a do Sol ratio of the mass of (4) Vesta to the Sun razón entre a masa de (4) Vesta e a do Sol mean obliquity of the ecliptic at J2000.0 obliquidade media da eclíptica en J2000.0 Electromagnetic Electromagnético Compton wavelength Lonxitude de onda de Compton Astronomy Astronomía ConstantsWidget Domain Dominio Subdomain Subdominio Search Buscar No match found Non se atopou ningunha coincidencia Name Nome Value Valor Unit Unidade All Todo CustomKeypadDialog Custom Keypad Teclado numérico personalizado Rows: Liñas: Columns: Columnas: Copy preset: Copiar predefinición: Basic Básico Scientific (wide) Científico (largo) Scientific (narrow) Científica (estreita) Apply Aplicar Row Liña Column Columna Label Etiqueta Behavior Comportamento Text Texto DiagnosticsDialog App Diagnostics Diagnóstico da aplicación Copy to Clipboard Copiar ao portapapeis Editor Unit Unidade User unit Unidade do usuario User function Función do usuario Argument Argumento Current result:<br/>%1 Resultado actual:<br/>%1 Selection result:<br/>%1 Resultado da selección:<br/>%1 Selection result: n/a Resultado da selección: n/d Selection result: %1 Resultado da selección: %1 second segundo metre metro kilogram quilograma mole mol radian radián steradian estereorradián degree Celsius grao Celsius cubic metre metro cúbico cubic millimetre milímetro cúbico cubic centimetre centímetro cúbico cubic decimetre decímetro cúbico cubic kilometre quilómetro cúbico square millimetre milímetro cadrado square kilometre quilómetro cadrado square metre metro cadrado minute minuto hour hora day día astronomical unit unidade astronómica degree grao arcminute minuto de arco arcsecond segundo de arco milliarcsecond milisegundo de arco microarcsecond microsegundo de arco hectare hectárea litre litro tonne tonelada Dalton dalton electronvolt electrón-volt Angstrom ångström atmosphere atmosfera atomic mass unit unidade de masa atómica British thermal unit unidade térmica británica calorie caloria carat quilate cup cunca cup (Imperial) cunca (imperial) cup (Japanese) cunca (japonesa) cup (US) cunca (EUA) degree Fahrenheit grao Fahrenheit fathom braza fluid ounce (Imperial) onza fluida (imperial) fluid ounce (US) onza fluida (EUA) fluid dram (Imperial) dracma fluida (imperial) fluid dram (US) dracma fluida (EUA) foot pé square foot pé cadrado cubic foot pé cúbico gallon (Imperial) galón (imperial) gallon (US) galón (EUA) gill (Imperial) gill (imperial) gill (US) gill (EUA) gradian gradián grain gran gram grama Hartley hartley Hartree energy unit unidade de enerxía Hartree horsepower cabalo de vapor inch polegada square inch polegada cadrada cubic inch polegada cúbica karat quilate knot nó lightminute minuto-luz lightsecond segundo-luz lightyear ano-luz long ton tonelada longa mile milla square mile milla cadrada cubic mile milla cúbica mile per hour milla por hora kilometre per hour quilómetro por hora nautical mile milla náutica ounce onza parsec pársec pint (Imperial) pinta (imperial) pint (US) pinta (EUA) pound libra pounds per square inch libras por polegada cadrada quart (Imperial) cuarto (imperial) quart (US) cuarto (EUA) oil barrel barril de petróleo beer barrel (US) barril de cervexa (EUA) square yard iarda cadrada cubic yard iarda cúbica short ton tonelada curta tablespoon culler de sopa tablespoon (Australian) culler de sopa (australiana) tablespoon (Imperial) culler de sopa (imperial) tablespoon (US) culler de sopa (EUA) dessert spoon culler de sobremesa teaspoon culler de té teaspoon (Imperial) culler de té (imperial) teaspoon (US) culler de té (EUA) turn volta revolution revolución revolution per minute revolución por minuto week semana kilowatt hour quilowatt-hora millimetre of mercury milímetro de mercurio yard iarda Julian century século juliano Julian year ano juliano sidereal year ano sideral tropical year ano tropical Evaluator cannot operate on a NaN non se pode operar cun NaN underflow - tiny result is out of SpeedCrunch's number range underflow - o resultado, demasiado pequeno, está fóra do intervalo numérico de SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflow - o resultado, demasiado grande, está fóra do intervalo numérico de SpeedCrunch division by zero división por cero overflow - logic result exceeds maximum of 256 bits overflow - o resultado lóxico supera o máximo de 256 bits overflow - integer result exceeds maximum limit for integers overflow - o resultado enteiro supera o límite máximo para os enteiros too time consuming - computation was rejected demasiado custoso en tempo - o cálculo foi rexeitado dimension mismatch - quantities with different dimensions cannot be compared, added, etc. incompatibilidade de dimensións - as magnitudes con dimensións diferentes non se poden comparar, sumar etc. invalid dimension - operation might require dimensionless arguments dimensión non válida - a operación pode requirir argumentos sen dimensión operation is not defined for these arguments a operación non está definida para estes argumentos Computation aborted - encountered numerical instability Cálculo interrompido - atopouse inestabilidade numérica wrong number of arguments número incorrecto de argumentos does not take NaN as an argument non admite NaN como argumento result out of range resultado fóra do intervalo undefined for argument domain non definido para o dominio do argumento computation too expensive cálculo demasiado custoso invalid dimension - function might require dimensionless arguments dimensión non válida - a función pode requirir argumentos sen dimensión internal error, please report a bug erro interno, informe dun fallo error erro invalid expression expresión non válida syntax error erro de sintaxe conversion target must be a unit o destino da conversión ten que ser unha unidade unit must not be zero a unidade non debe ser cero Conversion failed - dimension mismatch A conversión fallou - incompatibilidade de dimensións unknown function or variable función ou variable descoñecida unknown unit unidade descoñecida recursion not supported non se admite recursión %1 is a reserved name, please choose another %1 é un nome reservado, escolla outro %1 is a global user definition and cannot be overridden in this session. %1 é unha definición global do usuario e non pode ser substituída nesta sesión. %1 is a variable name, please choose another or delete the variable %1 é un nome de variable, escolla outro ou elimine a variable argument %1 is used more than once o argumento %1 úsase máis dunha vez %1 is a built-in unit name, please choose another %1 é o nome dunha unidade incorporada; escolla outro %1 is a user function name, please choose another or delete the function %1 é un nome de función de usuario, escolla outro ou elimine a función FunctionRepo max; trials; probability máx; probas; probabilidade trials; probability probas; probabilidade hits; trials; probability acertos; probas; probabilidade unix_timestamp; x hours offset to GMT marca_temporal_unix; desfase de x horas respecto de GMT max; total; hits; trials máx; total; acertos; probas total; hits; trials total; acertos; probas count; total; hits; trials reconto; total; acertos; probas dividend; divisor dividendo; divisor x; exponent_bits; significand_bits [; exponent_bias] x; bits_expoñente; bits_significando [; sesgo_expoñente] base; x base; x value; modulo valor; módulo base; exponent; modulo base; expoñente; módulo events; average_events eventos; eventos_medios average_events eventos_medios x [; precision] x [; precisión] Absolute Value Valor absoluto Absolute Deviation Desviación absoluta Arc Cosine Arco coseno Logical AND E lóxico Area Hyperbolic Cosine �rea coseno hiperbólico Area Hyperbolic Sine �rea seno hiperbólico Area Hyperbolic Tangent �rea tanxente hiperbólica Arc Sine Arco seno Arc Tangent Arco tanxente Arc Tangent with two Arguments Arco tanxente con dous argumentos Average (Arithmetic Mean) Media (media aritmética) Convert to Binary Representation Converter á representación binaria Binomial Cumulative Distribution Function Función de distribución acumulada binomial Binomial Distribution Mean Media da distribución binomial Binomial Probability Mass Function Función de masa de probabilidade binomial Binomial Distribution Variance Varianza da distribución binomial Cube Root Raíz cúbica Complex Conjugate Conxugado complexo Cosine Coseno Hyperbolic Cosine Coseno hiperbólico Cotangent Cotanxente Cosecant Cosecante Convert Unix timestamp to Date Converter unha marca temporal Unix en data Convert to Decimal Representation Converter á representación decimal Degrees of Arc Graos de arco Error Function Función de erro Complementary Error Function Función de erro complementaria Exponential Exponencial Arithmetic Aritmética Chemistry Química Complex Complexos Combinatorics Combinatoria Probability Probabilidade Statistics Estatística Aggregation Agregación Random Aleatorio Base conversion Conversión de base Number formatting Formatación de números Integer arithmetic Aritmética de enteiros Special functions Funcións especiais Exponential & Logarithmic Exponenciais e logarítmicas Angle conversion Conversión de ángulos Trigonometry Trigonometría Bitwise Operacións bit a bit Floating point Coma flotante Date & Time Data e hora Linear algebra �lgebra linear yyyymmdd.hhmmss; x hours offset to GMT aaaammdd.hhmmss; desprazamento de x horas en relación a GMT [digits] [dígitos] max [; min] máx [; mín] List Literal Literal de lista Convert to Padded Binary Representation Converter á representación binaria con recheo Round Toward +∞ (Ceiling) Redondear cara a +∞ (teito) Cosine plus Imaginary Sine Coseno máis seno imaxinario Convert to Cis Complex Form Converter para forma complexa cis Matrix Column Count Número de columnas da matriz Population Correlation Matrix (n) Matriz de correlación poboacional (n) Sample Correlation Matrix (n-1) Matriz de correlación mostral (n-1) Count Reconto Population Covariance Matrix (n) Matriz de covarianza poboacional (n) Sample Covariance Matrix (n-1) Matriz de covarianza mostral (n-1) Cross Product Produto vectorial Convert Date to Unix timestamp Converter data para marca temporal Unix Determinant Determinante Convert to Sexagesimal Notation Converter para notación sexaxesimal Dot Product Produto escalar Convert to Engineering Notation Converter para notación de enxeñaría Convert to Exponential Complex Form Converter para forma complexa exponencial Round Toward −∞ (Floor) Redondear cara a −∞ (chan) Flatten Matrix Aplanar matriz Fractional Part Parte fraccionaria Extension of Factorials [= (x-1)!] Extensión dos factoriais [= (x-1)!] Greatest Common Divisor Máximo común divisor Least Common Multiple Mínimo múltiplo común Geometric Mean Media xeométrica Gradians of arc Gradiáns de arco Convert to Hexadecimal Representation Converter á representación hexadecimal Convert to Padded Hexadecimal Representation Converter á representación hexadecimal con recheo Hypergeometric Cumulative Distribution Function Función de distribución acumulada hipergeométrica Hypergeometric Distribution Mean Media da distribución hipergeométrica Hypergeometric Probability Mass Function Función de masa de probabilidade hipergeométrica Hypergeometric Distribution Variance Varianza da distribución hipergeométrica Integer Quotient Cociente enteiro Integer Part Parte enteira Imaginary Part Parte imaxinaria Inverse Matrix Matriz inversa Decode IEEE-754 Binary Value Descodificar valor binario IEEE-754 Encode IEEE-754 Binary Value Codificar valor binario IEEE-754 Decode 16-bit Half-Precision Value Descodificar valor de media precisión de 16 bits Encode 16-bit Half-Precision Value Codificar valor de media precisión de 16 bits Decode 32-bit Single-Precision Value Descodificar valor de precisión simple de 32 bits Encode 32-bit Single-Precision Value Codificar valor de precisión simple de 32 bits Decode 64-bit Double-Precision Value Descodificar valor de precisión dobre de 64 bits Encode 64-bit Double-Precision Value Codificar valor de precisión dobre de 64 bits Decode 128-bit Quad-Precision Value Descodificar valor de precisión cuádrupla de 128 bits Encode 128-bit Quad-Precision Value Codificar valor de precisión cuádrupla de 128 bits Round to 16-bit Half-Precision Value Redondear a valor de media precisión de 16 bits Round to 32-bit Single-Precision Value Redondear a valor de precisión simple de 32 bits Round to 64-bit Double-Precision Value Redondear a valor de precisión dobre de 64 bits Round to 128-bit Quad-Precision Value Redondear a valor de precisión cuádrupla de 128 bits Residual from 16-bit Half-Precision Rounding Residuo do redondeo de media precisión de 16 bits Residual from 32-bit Single-Precision Rounding Residuo do redondeo de precisión simple de 32 bits Residual from 64-bit Double-Precision Rounding Residuo do redondeo de precisión dobre de 64 bits Residual from 128-bit Quad-Precision Rounding Residuo do redondeo de precisión cuádrupla de 128 bits Binary Logarithm Logaritmo binario Common Logarithm Logaritmo decimal Natural Logarithm Logaritmo natural Substance Mass Masa da substancia Molarity Molaridade Molar Mass Masa molar Logarithm to Arbitrary Base Logaritmo nunha base arbitraria Median Absolute Deviation Desviación absoluta mediana Mask to a bit size Máscara para un tamaño de bits Maximum Máximo Median Value (50th Percentile) Valor mediano (percentil 50) Mean Media Minimum Mínimo Numerical Value of Quantity Valor numérico da cantidade Random Decimal Number Número decimal aleatorio Random Integer Number Número enteiro aleatorio Convert to Rational Representation Converter para representación racional Modulo Módulo Euclidean Modulo Módulo euclidiano Modular Exponentiation Exponenciación modular Combination (Binomial Coefficient) Combinación (coeficiente binomial) Logical NOT NON lóxico Permutation (Arrangement) Permutación (arranxo) Convert to Octal Representation Converter á representación octal Convert to Padded Octal Representation Converter á representación octal con recheo Vector or Matrix Norm Norma de vector ou matriz Logical OR OU lóxico Population Count (Hamming Weight) Reconto de poboación (peso de Hamming) Phase of Complex Number Fase do número complexo Poissonian Cumulative Distribution Function Función de distribución acumulada de Poisson Poissonian Distribution Mean Media da distribución de Poisson Poissonian Probability Mass Function Función de masa de probabilidade de Poisson Poissonian Distribution Variance Varianza da distribución de Poisson Convert to Phasor Complex Form Converter para forma complexa fasorial Convert to Rectangular Complex Form Converter para forma complexa rectangular Round Half Away from Zero Redondear metade afastándose de cero Round Half Even Redondear metade a par Nth Root Raíz enésima Convert to Scientific Notation Converter para notación científica Matrix Row Count Número de liñas da matriz List or Matrix Shape Forma de lista ou matriz Summation Sumatorio Population Standard Deviation (n) Desviación estándar poboacional (n) Sample Standard Deviation (n-1) Desviación estándar mostral (n-1) Round Toward Zero (Truncation) Redondear cara a cero (truncamento) Matrix Trace Traza da matriz Transpose Matrix Transpoñer matriz Population Variance (n) Varianza poboacional (n) Sample Variance (n-1) Varianza mostral (n-1) Product Produto Radians Radiáns Matrix Rank Rango da matriz Real Part Parte real Secant Secante Arithmetic Shift Left Desprazamento aritmético á esquerda Arithmetic Shift Right Desprazamento aritmético á dereita Signum Signo Sine Seno Hyperbolic Sine Seno hiperbólico Square Root Raíz cadrada Sum Suma Tangent Tanxente Convert to Trigonometric Complex Form Converter para forma complexa trigonométrica Turns Voltas Hyperbolic Tangent Tanxente hiperbólica Sign-extend a value Estender o signo dun valor Logical XOR OU exclusivo lóxico FunctionsWidget Domain Dominio All Todo Identifier Identificador Name Nome Search Buscar No match found Non se atopou ningunha coincidencia HistoryWidget Remove All Calculations Above Eliminar todos os cálculos de arriba Remove This Calculation Eliminar este cálculo Remove All Calculations Below Eliminar todos os cálculos de abaixo Keypad Inverse cosine Coseno inverso The last result O último resultado Inverse sine Seno inverso Inverse tangent Tanxente inversa Evaluate expression Calcular expresión Division División Multiplication Multiplicación Subtraction Subtracción Addition Adición Clear expression Limpar expresión Cosine Coseno Backspace Retroceso Scientific notation Notación científica Exponential Exponencial Factorial Factorial Natural logarithm Logaritmo natural Left parenthesis Paréntese esquerdo Nth root Raíz enésima Argument separator Separador de argumentos Square Cadrado Common logarithm Logaritmo común Modulo Módulo Contextual percentage Porcentaxe contextual Power Potencia Right parenthesis Paréntese direito Sine Seno Square root Raíz cadrada Tangent Tanxente Pi Pi Decimal separator Separador decimal MainWindow Radian Radián Gradian Gradián Degree Grao Binary Binario Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexaxesimal Engineering decimal Decimal de enxeñaría Scientific decimal Decimal científico Plain &text &texto simple &Import... &Importar... &Quit &Saír Clear E&xpression Limpar e&xpresión Clear &History Limpar &historial &Copy &Copiar &Paste &Pegar &Select Expression &Seleccionar expresión &Constants &Constantes &Functions &Funcións &History &Historial &Keypad &Teclado Formula &Book Libro de &fórmulas New &Private Tab Nova la&pela privada Keep Manter Make Private... Facer privada... &Rename... &Renomear... Clo&ne... Clo&nar... &Close Tab Pec&har lapela Reopen Clo&sed Tab Rea&brir a lapela pechada &Undo &Desfacer &Redo &Refacer Cu&t Cor&tar Copy &Last Result Copiar o ú&ltimo resultado &Wrap in Parentheses P&oñer entre parénteses Full Scr&een Mode Modo de &pantalla completa &Status Bar Barra de &estado Bitfield Campo de bits &Left &Esquerda &Right De&reita &Up &Arriba &Down A&baixo Close Pa&ne Pechar pa&nel Use&r Functions Funcións do usuari&o &Degree &Grao &Radian &Radián &Gradian &Gradián Re&volution R&evolución Always on &Top Sempre enriba Auto-Insert a&ns I&nserir ans automaticamente Automatic &Completion Completado automático &Built-in Functions &Funcións integradas Built-in &Variables &Variábeis integradas User &Functions Fu&ncións do usuario User Va&riables Va&riables do usuario Open a Private Tab on Startup Abrir unha lapela privada ao iniciar Open and focus a new private tab whenever SpeedCrunch starts. Abrir e activar unha nova lapela privada cada vez que se inicie SpeedCrunch. Syntax &Highlighting Realce de sintaxe Group Digits in &Input Agrupar díx&itos na entrada Automatic Input &Adjustments &Axustes automáticos da entrada Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Axustar automaticamente os operadores, os espazos, as parénteses e as potencias, e limitar a entrada a caracteres válidos. Group input digits using the selected number format. Agrupar os díxitos introducidos segundo o formato numérico seleccionado. &Blinking Cursor &Cursor intermitente Blink the cursor in the expression editor. Facer pestanexar o cursor no editor de expresións. &Escape Clears Editor &Escape baleira o editor Clear the focused expression editor with Escape after dismissing any popup or preview. Baleirar o editor de expresións activo con Escape despois de pechar calquera xanela emerxente ou vista previa. Disabled Desactivado Small Space Espazo pequeno Medium Space Espazo mediano Large Space Espazo grande Keep Expression After Evaluation Manter a expresión despois do cálculo Copy New Results Automatically Copiar automaticamente os novos resultados &Comma &Coma &System Default &Predeterminado do sistema &Dot &Punto Dot &And Comma Punto e &coma &0 Digits &0 díxitos &15 Digits &15 díxitos &2 Digits &2 díxitos &3 Digits &3 díxitos &50 Digits &50 díxitos &8 Digits &8 díxitos Toward +∞ (&ceil) Ca&ra a +∞ (ceil) Toward −∞ (&floor) Cara a −∞ (&floor) &Automatic &Automático &Engineering &Enxeñaría &Scientific &Científico &Binary &Binario &Octal &Octal &Hexadecimal &Hexadecimal &Sexagesimal &Sexaxesimal &Font... &Tipo de letra... Reset All Settings... Restabelecer todos os axustes... &System &Sistema SpeedCrunch &Theme &Tema de SpeedCrunch &Classic &Clásico &Modern &Moderno &Language... &Idioma... User &Manual &Manual do usuario Context Help Axuda contextual Issues and &Feedback &Problemas e comentarios &Donate &Doar Editor and Results Font Tipo de letra do editor e dos resultados &Session &Sesión &Export &Exportar &Edit &Editar &View &Ver S&plit &Dividir Se&ttings Con&figuración &Decimal &Decimal &Precision &Precisión Angle &Mode &Modo angular &Complex Form Forma &complexa &Help &Axuda New Tab Nova lapela Constants Constantes Functions Funcións History Historial User Functions Funcións do usuario Error Erro Can't read from file %1 Non se pode ler o ficheiro %1 Can't write to file %1 Non se pode escribir no ficheiro %1 Import Session Importar sesión Close Session Pechar sesión Angle Mode: Modo de ángulo: Notation: Notación: Precision: Precisión: Turn Volta Revolution Revolución Fixed-point decimal Decimal de coma fixa Rational Racional Automatic decimal Decimal automático Automatic Automático User &Definitions... &Definicións do usuario... New &Tab Nova &lapela New &Window Nova &xanela &Open... &Abrir... Open Sessions &Folder Abrir &cartafol de sesións &Basic &Básico &Scientific (wide) &Científica (larga) Scientific (narrow) Científica (estreita) &Custom... &Personalizado... Main &Menu &Menu principal User &Variables &Variables do usuario User &Units &Unidades do usuario &Turn &Volta If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Se unha nova expresión comeza por +, -, * ou /, SpeedCrunch insire primeiro "ans". &Accept with Enter &Aceptar con Intro Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Aceptar a suxestión actual de completado automático con Intro sen seleccionala primeiro coas teclas de frecha. &Units &Unidades Show Live Result &Preview Amosar &previsualización do resultado en directo Save &Window Position on Exit Gardar a posición da &xanela ao saír Hover Highlighting Realce ao pasar o rato Group Integer Part Only Agrupar só a parte enteira Number Format... Formato do número... Notation && Precision... Notación e precisión... After pressing Enter, keep the entered expression selected in the editor. Despois de premer Intro, manter a expresión introducida seleccionada no editor. Never Nunca Always Sempre Only for Single-Line Expressions Só para expresións dunha liña Simplify Displayed Expressions Simplificar as expresións amosadas History Size &Limit... &Límite do tamaño do historial... Remove Trailing &Zeroes &Eliminar ceros finais Nearest, Half &Away (round) Máis próximo, metade &afastándose de cero (round) Nearest, Half &Even (roundeven) Máis próximo, metade a &par (roundeven) Toward &Zero (trunc) Cara a &cero (trunc) &Fixed-Point &Coma fixa &Rational &Racional &Exponential (m·s�¹) &Exponencial (m·s�¹) &Fractional (m/s) &Fraccionaria (m/s) &Rectangular (a + bi) &Rectangular (a + bi) Exponential (re�ᶿ) Exponencial (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) Trigonométrica (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Tema... Check for &Updates Buscar &actualizacións Source Code Código fonte &Zoom &Zoom &Results &Resultados Unit Notation Notación de unidades Rounding Mode Modo de redondeo &Notation &Notación &Imaginary Unit Unidade &imaxinaria &Window &Xanela &Editing &Edición A&utocomplete A&utoconpletar Up/Down Arrow History Historial coas frechas arriba/abaixo &Appearance &Aparencia &Menus &Menús &Docks &Paneis acoplábeis &Input and Results E&ntrada e resultados &Disabled &Desactivado &Disable &Desactivar Close preview Pechar previsualización Rename... Renomear... Clone... Clonar... Close Tab Pechar lapela New Private Tab Nova lapela privada Open... Abrir... Reopen Closed Tab Reabrir a lapela pechada Split Dividir Left Esquerda Right Dereita Up Arriba Down Abaixo Clear Baleirar Delete Eliminar %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sesión privada: o contido descártase ao pechala. Escolla Sesión > Manter para convertela nunha sesión normal. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privada] Reset All Settings Restabelecer todos os axustes Reset all settings to their default values? Restabelecer todos os axustes aos valores predeterminados? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Isto inclúe a aparencia, a edición, os formatos dos resultados e as preferencias das xanelas. Manteranse os cálculos, as sesións abertas e as definicións do usuario. The settings file could not be written. Non se puido escribir o ficheiro de axustes. Clear this session's calculations, unfinished expression, variables, functions, and units? Baleirar os cálculos, a expresión sen rematar, as variábeis, as funcións e as unidades desta sesión? Global user definitions are kept. Mantéñense as definicións globais do usuario. Make Session Private Facer privada a sesión The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Eliminarase a sesión gardada %1. O seu contido seguirá aberto nunha sesión privada e descartarase cando se peche esa sesión ou se saia de SpeedCrunch. Make Private Facer privada Could not delete the saved session %1. Non se puido eliminar a sesión gardada %1. Keep Session Manter sesión Could not save the session. It remains private. Non se puido gardar a sesión. Segue sendo privada. Clone Session Clonar sesión Could not save session file %1. Non se puido gardar o ficheiro de sesión %1. Could not delete session file %1. Non se puido eliminar o ficheiro de sesión %1. JSON file (*.json);;Any file (*.*) Ficheiro JSON (*.json);;Calquera ficheiro (*.*) Export session as JSON Exportar sesión como JSON The selected file is not valid JSON: %1 O ficheiro seleccionado non é JSON válido: %1 The selected file is not a SpeedCrunch session JSON file. O ficheiro seleccionado non é un ficheiro JSON de sesión de SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Este ficheiro usa un formato de sesión de SpeedCrunch obsoleto e non se pode importar. The selected JSON file is missing the required $schema field. Ao ficheiro JSON seleccionado fáltalle o campo obrigatorio $schema. The selected JSON file uses an unsupported JSON schema: %1 O ficheiro JSON seleccionado usa un esquema JSON non compatíbel: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Ao ficheiro JSON seleccionado fáltalle o identificador do esquema de sesión de SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 O ficheiro JSON seleccionado usa un formato de sesión de SpeedCrunch non compatíbel: %1 The selected JSON file is missing the required session name. Ao ficheiro JSON seleccionado fáltalle o nome de sesión obrigatorio. The selected JSON file has an empty session name. O ficheiro JSON seleccionado ten un nome de sesión baleiro. The selected JSON file has invalid or incomplete SpeedCrunch session data. O ficheiro JSON seleccionado ten datos de sesión de SpeedCrunch non válidos ou incompletos. Open Sessions Folder Abrir cartafol de sesións Could not create the sessions folder: %1 Non se puido crear o cartafol de sesións: %1 Could not open the sessions folder: %1 Non se puido abrir o cartafol de sesións: %1 Open Session Abrir sesión Community Comunidade Rename Session Renomear sesión Clear Session Limpar sesión Delete Session Eliminar sesión Close Pane Pechar panel &About SpeedCrunch A&cerca de SpeedCrunch App Diag&nostics Diag&nóstico da aplicación User Variables Variables do usuario User Units Unidades do usuario Clear History Limpar historial Are you sure you want to clear the calculation history? Ten a certeza de que quere limpar o historial de cálculos? Session name: Nome da sesión: A session named %1 already exists. Xa existe unha sesión chamada %1. Could not create session file %1. Non foi posible crear o ficheiro de sesión %1. Could not write session file %1. Non foi posible escribir o ficheiro de sesión %1. Are you sure you want to delete this session? Ten a certeza de que quere eliminar esta sesión? Custom Precision Precisión personalizada Fractional digits: Díxitos fraccionarios: Theme Tema Light Themes Temas claros Dark Themes Temas escuros Preview Previsualización Colors Cores Select color for %1 Seleccionar cor para %1 Import... Importar... Export... Exportar... Import Theme Importar tema Theme file (*.json);;All files (*) Ficheiro de tema (*.json);;Todos os ficheiros (*) Invalid theme file. Ficheiro de tema inválido. Can't import theme "%1" because it conflicts with a built-in theme. Non é posible importar o tema "%1" porque entra en conflito cun tema incorporado. Can't find a writable theme folder. Non é posible atopar un cartafol de temas gravable. Overwrite Theme Substituír tema A custom theme named "%1" already exists. Do you want to overwrite it? Xa existe un tema personalizado chamado "%1". Desexa substituílo? Can't overwrite theme file %1 Non é posible substituír o ficheiro de tema %1 Can't copy theme file to %1 Non é posible copiar o ficheiro de tema en %1 Export Theme Exportar tema Can't export theme as "%1" because it conflicts with a built-in theme. Non é posible exportar o tema como "%1" porque entra en conflito cun tema incorporado. Global User Variable Variable global do usuario Global User Function Función global do usuario Global User Unit Unidade global do usuario User Definitions Definicións do usuario These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Estas definicións son globais e cárganse en cada sesión. Non se poden modificar desde as sesións e teñen prioridade sobre as definicións co mesmo nome do editor da sesión. Introduza unha definición por liña. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Exemplos: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Aplicar Validate Validar Test Results Resultados da proba Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variables importadas: %1 Funcións importadas: %2 Unidades importadas: %3 Números de liña con erros: %4 none ningún Apply Results Resultados da aplicación User definitions saved. Gardáronse as definicións do usuario. History Size Limit Límite do tamaño do historial Maximum number of history entries for this session (0 = unlimited): Número máximo de entradas de historial para esta sesión (0 = ilimitado): Export session as HTML Exportar sesión como HTML HTML file (*.html) Ficheiro HTML (*.html) Export session as plain text Exportar sesión como texto simple Text file (*.txt);;Any file (*.*) Ficheiro de texto (*.txt);;Calquera ficheiro (*.*) Could not recalculate from calculation %1: %2 Non foi posible recalcular a partir do cálculo %1: %2 History Size Limit Reached Límite do tamaño do historial alcanzado This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Este cálculo enche o último espazo dispoñible do historial. Os cálculos futuros eliminarán o cálculo máis antigo do historial. Pode aumentar o límite en Sesión > Límite do tamaño do historial. Editing calculation. Press Esc twice to cancel. Editando cálculo. Prema Esc dúas veces para cancelar. Calculation Settings Configuración de cálculo Invalid recalculation start index �ndice inicial de recálculo inválido System Default Predeterminado do sistema Language Idioma Select the language: Seleccione o idioma: Custom Personalizado Decimal places: Cifras decimais: ManualWindow SpeedCrunch Manual Manual de SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual de SpeedCrunch NumberFormatDialog Number Format Formato do número <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Seleccione o formato numérico dos resultados e da agrupación de díxitos de entrada.</b><br/><br/>Nota: os números introducidos en formatos inequívocos acéptanse aínda que difiran do formato de visualización seleccionado.<br/> QObject Global User Variable Variable global do usuario Global User Function Función global do usuario Global User Unit Unidade global do usuario Backspace Retroceso Clear expression Limpar expresión Evaluate expression Calcular expresión Insert text Inserir texto Automatic decimal Decimal automático Fixed-point decimal Decimal de coma fixa Engineering decimal Decimal de enxeñaría Scientific decimal Decimal científico Rational Racional Binary Binario Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexaxesimal Update Available Actualización dispoñible A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Está dispoñible unha versión máis recente (%1).<br/><a href="%2">Visite o sitio web para descargala.</a> Check for Updates Buscar actualizacións SpeedCrunch %1 is up to date. O SpeedCrunch %1 está actualizado. No connectivity. Please check your internet connection and try again. Sen conectividade. Comprobe a conexión á Internet e ténteo de novo. Could not verify the latest available version. Non foi posible verificar a versión máis recente dispoñible. ResultDisplay Scroll to bottom Desprazar ao final Edit Expression Editar expresión Change Settings Cambiar configuración New Tab Nova lapela &Import... &Importar... &Export &Exportar Plain &text &Texto simple Copy Copiar Selection Selección Select All Seleccionar todo Expression Expresión Result Resultado Calculation Cálculo Calculation as Single Line Cálculo nunha soa liña Remove Eliminar This Calculation Este cálculo All Calculations Above Todos os cálculos de enriba All Calculations Below Todos os cálculos de embaixo New Private Tab Nova lapela privada Session Sesión Open... Abrir... Clone... Clonar... Rename... Renomear... Keep Manter Make Private... Facer privada... Clear Baleirar Delete Eliminar Close Pechar Split Dividir Left Esquerda Right Dereita Up Arriba Down Abaixo Close Pane Pechar panel Main Menu Menu principal Cancel editing Cancelar edición Copy result Copiar resultado Edit expression Editar expresión Change settings Cambiar configuración Remove calculation Eliminar cálculo ResultSlotsDialog Notation & Precision Notación e precisión Result Line Liña do resultado Enabled Activado Notation Notación Decimal Places Cifras decimais Main Line Liña principal Extra Line #1 Liña extra n.º 1 Extra Line #2 Liña extra n.º 2 Extra Line #3 Liña extra n.º 3 Extra Line #4 Liña extra n.º 4 Auto Automático UserFunctionListWidget Name Nome Value Valor Description Descrición Search Buscar No match found Non se atopou ningunha coincidencia Insert Inserir Edit Editar Delete Eliminar Delete All Eliminar todo UserUnitListWidget Name Nome Value Valor Description Descrición Search Buscar No match found Non se atopou ningunha coincidencia Insert Inserir Edit Editar Delete Eliminar Delete All Eliminar todo VariableListWidget Name Nome Value Valor Description Descrición Search Buscar No match found Non se atopou ningunha coincidencia Insert Inserir Edit Editar Delete Eliminar Delete All Eliminar todo heldercorreia-speedcrunch-e7ca37f/src/resources/locale/he.ts000066400000000000000000011011251526573132500243420ustar00rootroot00000000000000 AboutBox About SpeedCrunch �ודות SpeedCrunch Core developers מפתחי ליבה Original author יוצר מקורי Close סגירה Math engine מנוע מתמטי Main author | Logo | Maintainer מחבר ר�שי | לוגו | מתחזק Thanks תודות Copyright (C) 2004-2026 The SpeedCrunch developers זכויות יוצרי� (C) 2004-2026 מפתחי SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version תוכנית זו הי� תוכנה חופשית; מותר להפיץ �ותה ו/�ו לשנות �ותה בכפוף לתנ�י הרישיון הציבורי הכללי של GNU כפי שפורס� על ידי קרן התוכנה החופשית; גרסה 2 של הרישיון, �ו (לפי בחירתך) כל גרסה מ�וחרת יותר This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. תוכנית זו מופצת בתקווה שתהיה מועילה, �ך לל� כל �חריות; �פילו לל� �חריות משתמעת לסחירות �ו להת�מה למטרה מסוימת. לפרטי� נוספי� ר�ה �ת הרישיון הציבורי הכללי של GNU. BitFieldWidget Reset bits to zero �פס סיביות ל�פס Invert bits הפוך סיביות Shift bits left הזז סיביות שמ�לה Shift bits right הזז סיביות ימינה Book Index �ינדקס Algebra �לגברה Quadratic Equation משוו�ה ריבועית Logarithmic Base Conversion המרה על בסיס לוגריתמי Geometry ג�ומטריה Circle עיגול Sector גזרה Sphere כדור Cube קובייה Cone חרוט Cylinder גליל Electronics �לקטרוניקה Ohm's Law חוק �וה� Power הספק Reactance היגב Resonance תהודה Radio Frequency תדר רדיו Antennas �נטנות Characteristic Impedance (coax) עכבה �ופיינית (קו�קס) Velocity of Propagation (coax) מהירות התפשטות (קו�קס) Standing Wave Ratio & Return Loss יחס גלי� עומדי� והפסד החזרה Free Space Wavelength �ורך גל בחלל חופשי resistance התנגדות voltage מתח current זר� power הספק inductive reactance היגב השר�תי capacitive reactance היגב קיבולי inductance השר�ות capacitance קיבולת frequency תדר resonance frequency תדר תהודה area �זור perimeter היקף diameter קוטר radius רדיוס volume נפח surface area שטח פני� height גובה slant height גובה �לכסוני face diagonal �לכסון פ�ה space diagonal �לכסון מרחבי edge length �ורך צלע arc length �ורך קשת central angle (degrees) זווית מרכזית (מעלות) input power הספק כניסה reflected power הספק מוחזר transmitted power הספק מועבר return loss הפסד החזרה dielectric constant קבוע די�לקטרי outer conductor's inner diameter הקוטר הפנימי של המוליך החיצוני inner conductor's outer diameter הקוטר החיצוני של המוליך הפנימי speed of light מהירות ה�ור reflection coefficient מקד� החזרה standing wave ratio יחס גלי� עומדי� normalized impedance עכבה מנורמלת frequency (Hz) תדר (Hz) BookDock Formula Book ספר נוסח�ות ConstantCompletion Search constants חיפוש קבועי� No match found ל� נמצ�ה הת�מה Constants Mathematics מתמטיקה Physics (CODATA 2022) פיזיקה (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) כימיה (IUPAC - CIAAW 2021) Uncategorized לל� קטגוריה Universal �וניברסלי Physicochemical פיזיקוכימי Atomic & Nuclear — General �טומי וגרעיני — כללי Atomic & Nuclear — Electroweak �טומי וגרעיני — �לקטרוחלש Atomic & Nuclear — Electron �טומי וגרעיני — �לקטרון Atomic & Nuclear — Muon �טומי וגרעיני — מיו�ון Atomic & Nuclear — Tau �טומי וגרעיני — ט�ו Atomic & Nuclear — Proton �טומי וגרעיני — פרוטון Atomic & Nuclear — Neutron �טומי וגרעיני — נייטרון Atomic & Nuclear — Deuteron �טומי וגרעיני — דויטרון Atomic & Nuclear — Triton �טומי וגרעיני — טריטון Atomic & Nuclear — Helion �טומי וגרעיני — הליון Atomic & Nuclear — Alpha particle �טומי וגרעיני — חלקיק �לפ� Atomic & Nuclear — Atomic units �טומי וגרעיני — יחידות �טומיות Atomic & Nuclear — Energy conversion relationships �טומי וגרעיני — יחסי המרת �נרגיה Atomic & Nuclear — X-ray units �טומי וגרעיני — יחידות קרני רנטגן Atomic & Nuclear — Magnetic shielding corrections �טומי וגרעיני — תיקוני מיסוך מגנטי Masses מסות Lifetimes זמני חיי� Molar Masses מסות מולריות Electronegativity �לקטרושליליות Ionization Energy �נרגיית יינון Nominal Constants (IAU 2015) קבועי� נומינליי� (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) ה�ומדני� העדכניי� הטובי� ביותר (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) עכבה �ופיינית של הריק (Z₀) reduced Planck constant (�) קבוע פל�נק המצומצ� (�) vacuum electric permittivity (ϵ₀) פרמיטיביות חשמלית של הריק (ϵ₀) Newtonian constant of gravitation (G) קבוע הכבידה הניוטוני (G) vacuum magnetic permeability (μ₀) חדירות מגנטית של הריק (μ₀) Planck constant (h) קבוע פל�נק (h) speed of light in vacuum (c) מהירות ה�ור בריק (c) standard acceleration of gravity (gₙ) ת�וצת הכובד התקנית (gₙ) Newtonian constant of gravitation over h-bar c קבוע הכבידה הניוטוני חלקי �c Planck length �ורך פל�נק Planck constant in eV/Hz (h) קבוע פל�נק ב-eV/Hz (h) Planck mass מסת פל�נק Planck mass energy equivalent in GeV שקול �נרגיית מסת פל�נק ב-GeV Planck temperature טמפרטורת פל�נק Planck time זמן פל�נק reduced Planck constant in eV·s (�) קבוע פל�נק המצומצ� ב-eV·s (�) reduced Planck constant times c in MeV·fm קבוע פל�נק המצומצ� כפול c ב-MeV·fm Bohr magneton מגנטון בוהר conductance quantum (G₀) קוונטו� המוליכות (G₀) Coulomb constant (kₑ) קבוע קולון (kₑ) elementary charge (e) מטען יסודי (e) elementary charge over h-bar מטען יסודי חלקי � conventional value of Josephson constant ערך מוסכ� של קבוע ג׳וזפסון Josephson constant קבוע ג׳וזפסון conventional value of ampere-90 ערך מוסכ� של �מפר-90 conventional value of coulomb-90 ערך מוסכ� של קולון-90 conventional value of farad-90 ערך מוסכ� של פ�ר�ד-90 conventional value of henry-90 ערך מוסכ� של הנרי-90 conventional value of ohm-90 ערך מוסכ� של �וה�-90 conventional value of volt-90 ערך מוסכ� של וולט-90 conventional value of watt-90 ערך מוסכ� של ו�ט-90 magnetic flux quantum (Φ₀) קוונטו� השטף המגנטי (Φ₀) nuclear magneton מגנטון גרעיני inverse of conductance quantum הופכי קוונטו� המוליכות conventional value of von Klitzing constant ערך מוסכ� של קבוע פון קליצינג von Klitzing constant קבוע פון קליצינג atomic unit of magnetic dipole moment יחידה �טומית של מומנט דיפול מגנטי atomic unit of magnetic flux density יחידה �טומית של צפיפות שטף מגנטי Bohr magneton in eV/T מגנטון בוהר ב-eV/T Bohr magneton in Hz/T מגנטון בוהר ב-Hz/T Bohr magneton in inverse meter per tesla מגנטון בוהר במטר הופכי לטסלה Bohr magneton in K/T מגנטון בוהר ב-K/T nuclear magneton in eV/T מגנטון גרעיני ב-eV/T nuclear magneton in inverse meter per tesla מגנטון גרעיני במטר הופכי לטסלה nuclear magneton in K/T מגנטון גרעיני ב-K/T nuclear magneton in MHz/T מגנטון גרעיני ב-MHz/T Bohr radius (a₀) רדיוס בוהר (a₀) fine-structure constant (α) קבוע המבנה העדין (α) Hartree energy (Eₕ) �נרגיית ה�רטרי (Eₕ) Hartree energy in eV �נרגיית ה�רטרי ב-eV quantum of circulation קוונטו� הסחרור quantum of circulation times 2 קוונטו� הסחרור כפול 2 Rydberg constant (R∞) קבוע רידברג (R∞) atomic mass unit-hartree relationship יחס המרה בין יחידת מסה �טומית ל-ה�רטרי atomic mass unit-hertz relationship יחס המרה בין יחידת מסה �טומית ל-הרץ atomic mass unit-inverse meter relationship יחס המרה בין יחידת מסה �טומית ל-מטר הופכי atomic mass unit-joule relationship יחס המרה בין יחידת מסה �טומית ל-ג׳�ול atomic mass unit-kelvin relationship יחס המרה בין יחידת מסה �טומית ל-קלווין atomic mass unit-kilogram relationship יחס המרה בין יחידת מסה �טומית ל-קילוגר� atomic unit of 1st hyperpolarizability יחידה �טומית של היפר-פולריזביליות מסדר ר�שון atomic unit of 2nd hyperpolarizability יחידה �טומית של היפר-פולריזביליות מסדר שני atomic unit of charge (e) יחידה �טומית של מטען (e) atomic unit of charge density יחידה �טומית של צפיפות מטען atomic unit of current יחידה �טומית של זר� atomic unit of electric dipole moment יחידה �טומית של מומנט דיפול חשמלי atomic unit of electric field יחידה �טומית של שדה חשמלי atomic unit of electric field gradient יחידה �טומית של מפל שדה חשמלי atomic unit of electric polarizability יחידה �טומית של פולריזביליות חשמלית atomic unit of electric potential יחידה �טומית של פוטנצי�ל חשמלי atomic unit of electric quadrupole moment יחידה �טומית של מומנט קוודרופול חשמלי atomic unit of action יחידה �טומית של פעולה atomic unit of energy יחידה �טומית של �נרגיה atomic unit of force יחידה �טומית של כוח atomic unit of length יחידה �טומית של �ורך hertz-atomic mass unit relationship יחס המרה בין הרץ ל-יחידת מסה �טומית hertz-electron volt relationship יחס המרה בין הרץ ל-�לקטרון-וולט hertz-hartree relationship יחס המרה בין הרץ ל-ה�רטרי hertz-inverse meter relationship יחס המרה בין הרץ ל-מטר הופכי hertz-joule relationship יחס המרה בין הרץ ל-ג׳�ול hertz-kelvin relationship יחס המרה בין הרץ ל-קלווין hertz-kilogram relationship יחס המרה בין הרץ ל-קילוגר� hyperfine transition frequency of Cs-133 תדירות המעבר העל-דק של Cs-133 inverse fine-structure constant (α�¹) הופכי קבוע המבנה העדין (α�¹) inverse meter-atomic mass unit relationship יחס המרה בין מטר הופכי ל-יחידת מסה �טומית inverse meter-electron volt relationship יחס המרה בין מטר הופכי ל-�לקטרון-וולט inverse meter-hartree relationship יחס המרה בין מטר הופכי ל-ה�רטרי inverse meter-hertz relationship יחס המרה בין מטר הופכי ל-הרץ inverse meter-joule relationship יחס המרה בין מטר הופכי ל-ג׳�ול inverse meter-kelvin relationship יחס המרה בין מטר הופכי ל-קלווין inverse meter-kilogram relationship יחס המרה בין מטר הופכי ל-קילוגר� joule-atomic mass unit relationship יחס המרה בין ג׳�ול ל-יחידת מסה �טומית joule-electron volt relationship יחס המרה בין ג׳�ול ל-�לקטרון-וולט joule-hertz relationship יחס המרה בין ג׳�ול ל-הרץ joule-hartree relationship יחס המרה בין ג׳�ול ל-ה�רטרי joule-inverse meter relationship יחס המרה בין ג׳�ול ל-מטר הופכי joule-kelvin relationship יחס המרה בין ג׳�ול ל-קלווין joule-kilogram relationship יחס המרה בין ג׳�ול ל-קילוגר� kelvin-atomic mass unit relationship יחס המרה בין קלווין ל-יחידת מסה �טומית kelvin-electron volt relationship יחס המרה בין קלווין ל-�לקטרון-וולט kelvin-hertz relationship יחס המרה בין קלווין ל-הרץ kelvin-hartree relationship יחס המרה בין קלווין ל-ה�רטרי kelvin-inverse meter relationship יחס המרה בין קלווין ל-מטר הופכי kelvin-joule relationship יחס המרה בין קלווין ל-ג׳�ול kelvin-kilogram relationship יחס המרה בין קלווין ל-קילוגר� kilogram-atomic mass unit relationship יחס המרה בין קילוגר� ל-יחידת מסה �טומית kilogram-electron volt relationship יחס המרה בין קילוגר� ל-�לקטרון-וולט kilogram-hertz relationship יחס המרה בין קילוגר� ל-הרץ kilogram-hartree relationship יחס המרה בין קילוגר� ל-ה�רטרי kilogram-inverse meter relationship יחס המרה בין קילוגר� ל-מטר הופכי kilogram-joule relationship יחס המרה בין קילוגר� ל-ג׳�ול kilogram-kelvin relationship יחס המרה בין קילוגר� ל-קלווין lattice parameter of silicon (a) פרמטר הסריג של סיליקון (a) luminous efficacy נצילות �ורית natural unit of energy יחידה טבעית של �נרגיה natural unit of energy in MeV יחידה טבעית של �נרגיה ב-MeV natural unit of action (�) יחידה טבעית של פעולה (�) natural unit of action in eV·s יחידה טבעית של פעולה ב-eV·s natural unit of length יחידה טבעית של �ורך natural unit of mass יחידה טבעית של מסה natural unit of momentum יחידה טבעית של תנע natural unit of momentum in MeV/c יחידה טבעית של תנע ב-MeV/c natural unit of time יחידה טבעית של זמן natural unit of velocity יחידה טבעית של מהירות Rydberg constant times c in Hz קבוע רידברג כפול c ב-Hz Rydberg constant times hc in eV קבוע רידברג כפול hc ב-eV Rydberg constant times hc in J קבוע רידברג כפול hc ב-J Fermi coupling constant קבוע הצימוד של פרמי weak mixing angle זווית הערבוב החלש W to Z mass ratio יחס המסות W ל-Z Thomson cross section (σₑ) חתך הפעולה של תומסון (σₑ) electron mass (mₑ) מסת ה�לקטרון (mₑ) electron mass in u מסת ה�לקטרון ב-u electron mass energy equivalent (mₑ·c²) שקול �נרגיית המסה של ה�לקטרון (mₑ·c²) electron mass energy equivalent in MeV שקול �נרגיית המסה של ה�לקטרון ב-MeV reduced Compton wavelength �ורך גל קומפטון מצומצ� classical electron radius (rₑ) רדיוס ה�לקטרון הקל�סי (rₑ) electron charge to mass quotient מנת המטען למסה של ה�לקטרון electron-deuteron magnetic moment ratio יחס מומנטי� מגנטיי� �לקטרון-דויטרון electron-deuteron mass ratio יחס מסות �לקטרון-דויטרון electron g factor (gₑ) גור� g של ה�לקטרון (gₑ) electron gyromagnetic ratio (γₑ) יחס גירומגנטי של ה�לקטרון (γₑ) electron gyromagnetic ratio in MHz/T יחס גירומגנטי של ה�לקטרון ב-MHz/T electron-helion mass ratio יחס מסות �לקטרון-הליון electron magnetic moment (μₑ) מומנט מגנטי של ה�לקטרון (μₑ) electron magnetic moment anomaly (aₑ) �נומליית המומנט המגנטי של ה�לקטרון (aₑ) electron magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של ה�לקטרון למגנטון בוהר electron magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של ה�לקטרון למגנטון גרעיני electron molar mass (Mₑ) מסה מולרית של ה�לקטרון (Mₑ) electron-muon magnetic moment ratio יחס מומנטי� מגנטיי� �לקטרון-מיו�ון electron-muon mass ratio יחס מסות �לקטרון-מיו�ון electron-neutron magnetic moment ratio יחס מומנטי� מגנטיי� �לקטרון-נייטרון electron-neutron mass ratio יחס מסות �לקטרון-נייטרון electron-proton magnetic moment ratio יחס מומנטי� מגנטיי� �לקטרון-פרוטון electron-proton mass ratio יחס מסות �לקטרון-פרוטון electron relative atomic mass (Ar(e)) מסה �טומית יחסית של ה�לקטרון (Ar(e)) electron-tau mass ratio יחס מסות �לקטרון-ט�ו electron to alpha particle mass ratio יחס מסות �לקטרון-חלקיק �לפ� electron to shielded helion magnetic moment ratio יחס מומנטי� מגנטיי� �לקטרון-הליון מסוכך electron to shielded proton magnetic moment ratio יחס מומנטי� מגנטיי� �לקטרון-פרוטון מסוכך electron-triton mass ratio יחס מסות �לקטרון-טריטון electron volt-atomic mass unit relationship יחס המרה בין �לקטרון-וולט ל-יחידת מסה �טומית electron volt-hartree relationship יחס המרה בין �לקטרון-וולט ל-ה�רטרי electron volt-hertz relationship יחס המרה בין �לקטרון-וולט ל-הרץ electron volt-inverse meter relationship יחס המרה בין �לקטרון-וולט ל-מטר הופכי electron volt-joule relationship יחס המרה בין �לקטרון-וולט ל-ג׳�ול electron volt-kelvin relationship יחס המרה בין �לקטרון-וולט ל-קלווין electron volt-kilogram relationship יחס המרה בין �לקטרון-וולט ל-קילוגר� hartree-atomic mass unit relationship יחס המרה בין ה�רטרי ל-יחידת מסה �טומית hartree-electron volt relationship יחס המרה בין ה�רטרי ל-�לקטרון-וולט muon Compton wavelength �ורך גל קומפטון של המיו�ון muon-electron mass ratio יחס מסות מיו�ון-�לקטרון muon g factor גור� g של המיו�ון muon magnetic moment מומנט מגנטי של המיו�ון muon magnetic moment anomaly �נומליית המומנט המגנטי של המיו�ון muon magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של המיו�ון למגנטון בוהר muon magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של המיו�ון למגנטון גרעיני muon mass מסת המיו�ון muon mass energy equivalent שקול �נרגיית המסה של המיו�ון muon mass energy equivalent in MeV שקול �נרגיית המסה של המיו�ון ב-MeV muon mass in u מסת המיו�ון ב-u muon molar mass מסה מולרית של המיו�ון muon-neutron mass ratio יחס מסות מיו�ון-נייטרון muon-proton magnetic moment ratio יחס מומנטי� מגנטיי� מיו�ון-פרוטון muon-proton mass ratio יחס מסות מיו�ון-פרוטון muon-tau mass ratio יחס מסות מיו�ון-ט�ו reduced muon Compton wavelength �ורך גל קומפטון מצומצ� של המיו�ון reduced tau Compton wavelength �ורך גל קומפטון מצומצ� של הט�ו tau Compton wavelength �ורך גל קומפטון של הט�ו tau-electron mass ratio יחס מסות ט�ו-�לקטרון tau mass מסת הט�ו tau mass energy equivalent שקול �נרגיית המסה של הט�ו tau mass in u מסת הט�ו ב-u tau molar mass מסה מולרית של הט�ו tau-muon mass ratio יחס מסות ט�ו-מיו�ון tau-neutron mass ratio יחס מסות ט�ו-נייטרון tau-proton mass ratio יחס מסות ט�ו-פרוטון proton charge to mass quotient מנת המטען למסה של הפרוטון proton Compton wavelength �ורך גל קומפטון של הפרוטון proton-electron mass ratio יחס מסות פרוטון-�לקטרון proton g factor (gₚ) גור� g של הפרוטון (gₚ) proton gyromagnetic ratio (γₚ) יחס גירומגנטי של הפרוטון (γₚ) proton gyromagnetic ratio in MHz/T יחס גירומגנטי של הפרוטון ב-MHz/T proton magnetic moment (μₚ) מומנט מגנטי של הפרוטון (μₚ) proton magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של הפרוטון למגנטון בוהר proton magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של הפרוטון למגנטון גרעיני proton magnetic shielding correction תיקון המיסוך המגנטי של הפרוטון proton mass (mₚ) מסת הפרוטון (mₚ) proton mass energy equivalent שקול �נרגיית המסה של הפרוטון proton mass energy equivalent in MeV שקול �נרגיית המסה של הפרוטון ב-MeV proton mass in u מסת הפרוטון ב-u proton molar mass (Mₚ) מסה מולרית של הפרוטון (Mₚ) proton-muon mass ratio יחס מסות פרוטון-מיו�ון proton-neutron magnetic moment ratio יחס מומנטי� מגנטיי� פרוטון-נייטרון proton-neutron mass ratio יחס מסות פרוטון-נייטרון proton relative atomic mass (Ar(p)) מסה �טומית יחסית של הפרוטון (Ar(p)) proton rms charge radius רדיוס מטען RMS של הפרוטון proton-tau mass ratio יחס מסות פרוטון-ט�ו reduced proton Compton wavelength �ורך גל קומפטון מצומצ� של הפרוטון shielded proton gyromagnetic ratio יחס גירומגנטי של הפרוטון המסוכך shielded proton gyromagnetic ratio in MHz/T יחס גירומגנטי של הפרוטון המסוכך ב-MHz/T shielded proton magnetic moment מומנט מגנטי של הפרוטון המסוכך shielded proton magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של הפרוטון המסוכך למגנטון בוהר shielded proton magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של הפרוטון המסוכך למגנטון גרעיני neutron Compton wavelength �ורך גל קומפטון של הנייטרון neutron-electron magnetic moment ratio יחס מומנטי� מגנטיי� נייטרון-�לקטרון neutron-electron mass ratio יחס מסות נייטרון-�לקטרון neutron g factor (gₙ) גור� g של הנייטרון (gₙ) neutron gyromagnetic ratio (γₙ) יחס גירומגנטי של הנייטרון (γₙ) neutron gyromagnetic ratio in MHz/T יחס גירומגנטי של הנייטרון ב-MHz/T neutron magnetic moment (μₙ) מומנט מגנטי של הנייטרון (μₙ) neutron magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של הנייטרון למגנטון בוהר neutron magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של הנייטרון למגנטון גרעיני neutron mass (mₙ) מסת הנייטרון (mₙ) neutron mass energy equivalent שקול �נרגיית המסה של הנייטרון neutron mass energy equivalent in MeV שקול �נרגיית המסה של הנייטרון ב-MeV neutron mass in u מסת הנייטרון ב-u neutron molar mass (Mₙ) מסה מולרית של הנייטרון (Mₙ) neutron-muon mass ratio יחס מסות נייטרון-מיו�ון neutron-proton magnetic moment ratio יחס מומנטי� מגנטיי� נייטרון-פרוטון neutron-proton mass difference הפרש המסות נייטרון-פרוטון neutron-proton mass difference energy equivalent שקול �נרגיית הפרש המסות נייטרון-פרוטון neutron-proton mass difference energy equivalent in MeV שקול �נרגיית הפרש המסות נייטרון-פרוטון ב-MeV neutron-proton mass difference in u הפרש המסות נייטרון-פרוטון ב-u neutron-proton mass ratio יחס מסות נייטרון-פרוטון neutron relative atomic mass (Ar(n)) מסה �טומית יחסית של הנייטרון (Ar(n)) neutron-tau mass ratio יחס מסות נייטרון-ט�ו neutron to shielded proton magnetic moment ratio יחס מומנטי� מגנטיי� נייטרון-פרוטון מסוכך reduced neutron Compton wavelength �ורך גל קומפטון מצומצ� של הנייטרון deuteron-electron magnetic moment ratio יחס מומנטי� מגנטיי� דויטרון-�לקטרון deuteron-electron mass ratio יחס מסות דויטרון-�לקטרון deuteron g factor גור� g של הדויטרון deuteron magnetic moment מומנט מגנטי של הדויטרון deuteron magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של הדויטרון למגנטון בוהר deuteron magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של הדויטרון למגנטון גרעיני deuteron mass מסת הדויטרון deuteron mass energy equivalent שקול �נרגיית המסה של הדויטרון deuteron mass energy equivalent in MeV שקול �נרגיית המסה של הדויטרון ב-MeV deuteron mass in u מסת הדויטרון ב-u deuteron molar mass מסה מולרית של הדויטרון deuteron-neutron magnetic moment ratio יחס מומנטי� מגנטיי� דויטרון-נייטרון deuteron-proton magnetic moment ratio יחס מומנטי� מגנטיי� דויטרון-פרוטון deuteron-proton mass ratio יחס מסות דויטרון-פרוטון deuteron relative atomic mass (Ar(d)) מסה �טומית יחסית של הדויטרון (Ar(d)) deuteron rms charge radius רדיוס מטען RMS של הדויטרון triton-electron mass ratio יחס מסות טריטון-�לקטרון triton g factor (gₜ) גור� g של הטריטון (gₜ) triton magnetic moment (μₜ) מומנט מגנטי של הטריטון (μₜ) triton magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של הטריטון למגנטון בוהר triton magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של הטריטון למגנטון גרעיני triton mass (mₜ) מסת הטריטון (mₜ) triton mass energy equivalent שקול �נרגיית המסה של הטריטון triton mass energy equivalent in MeV שקול �נרגיית המסה של הטריטון ב-MeV triton mass in u מסת הטריטון ב-u triton molar mass (Mₜ) מסה מולרית של הטריטון (Mₜ) triton-proton mass ratio יחס מסות טריטון-פרוטון triton relative atomic mass (Ar(t)) מסה �טומית יחסית של הטריטון (Ar(t)) triton to proton magnetic moment ratio יחס מומנטי� מגנטיי� טריטון-פרוטון helion-electron mass ratio יחס מסות הליון-�לקטרון helion g factor (gₕ) גור� g של ההליון (gₕ) helion magnetic moment (μₕ) מומנט מגנטי של ההליון (μₕ) helion magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של ההליון למגנטון בוהר helion magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של ההליון למגנטון גרעיני helion mass (mₕ) מסת ההליון (mₕ) helion mass energy equivalent שקול �נרגיית המסה של ההליון helion mass energy equivalent in MeV שקול �נרגיית המסה של ההליון ב-MeV helion mass in u מסת ההליון ב-u helion molar mass (Mₕ) מסה מולרית של ההליון (Mₕ) helion-proton mass ratio יחס מסות הליון-פרוטון helion relative atomic mass (Ar(h)) מסה �טומית יחסית של ההליון (Ar(h)) helion shielding shift היסט המיסוך של ההליון shielded helion gyromagnetic ratio יחס גירומגנטי של ההליון המסוכך shielded helion gyromagnetic ratio in MHz/T יחס גירומגנטי של ההליון המסוכך ב-MHz/T shielded helion magnetic moment מומנט מגנטי של ההליון המסוכך shielded helion magnetic moment to Bohr magneton ratio יחס המומנט המגנטי של ההליון המסוכך למגנטון בוהר shielded helion magnetic moment to nuclear magneton ratio יחס המומנט המגנטי של ההליון המסוכך למגנטון גרעיני shielded helion to proton magnetic moment ratio יחס מומנטי� מגנטיי� הליון מסוכך-פרוטון shielded helion to shielded proton magnetic moment ratio יחס מומנטי� מגנטיי� הליון מסוכך-פרוטון מסוכך alpha particle mass מסת חלקיק ה�לפ� alpha particle mass in u מסת חלקיק ה�לפ� ב-u alpha particle mass energy equivalent שקול �נרגיית המסה של חלקיק ה�לפ� alpha particle mass energy equivalent in MeV שקול �נרגיית המסה של חלקיק ה�לפ� ב-MeV alpha particle-electron mass ratio יחס מסות חלקיק �לפ�-�לקטרון alpha particle-proton mass ratio יחס מסות חלקיק �לפ�-פרוטון alpha particle rms charge radius רדיוס מטען RMS של חלקיק ה�לפ� alpha particle molar mass מסה מולרית של חלקיק ה�לפ� alpha particle relative atomic mass (Ar(α)) מסה �טומית יחסית של חלקיק ה�לפ� (Ar(α)) atomic mass constant (mᵤ) קבוע המסה ה�טומית (mᵤ) Avogadro constant קבוע �בוגדרו Boltzmann constant (k) קבוע בולצמן (k) Boltzmann constant in eV/K קבוע בולצמן ב-eV/K Boltzmann constant in Hz/K קבוע בולצמן ב-Hz/K Boltzmann constant in inverse meter per kelvin קבוע בולצמן במטר הופכי לקלווין electron volt (eV) �לקטרון-וולט (eV) Faraday constant (F) קבוע פ�ר�דיי (F) first radiation constant (c�) קבוע הקרינה הר�שון (c�) first radiation constant for spectral radiance קבוע הקרינה הר�שון לקרינה ספקטרלית molar gas constant (R) קבוע הגזי� המולרי (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) קבוע לושמידט (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) קבוע לושמידט (n₀, 273.15 K, 101.325 kPa) molar Planck constant קבוע פל�נק מולרי second radiation constant (c₂) קבוע הקרינה השני (c₂) Stefan-Boltzmann constant (σ) קבוע סטפן-בולצמן (σ) lattice spacing of ideal Si (d₂₂₀) מרווח הסריג של Si �יד�לי (d₂₂₀) atomic mass constant energy equivalent שקול �נרגיית קבוע המסה ה�טומית atomic mass constant energy equivalent in MeV שקול �נרגיית קבוע המסה ה�טומית ב-MeV atomic mass unit-electron volt relationship יחס המרה בין יחידת מסה �טומית ל-�לקטרון-וולט molar mass constant (Mᵤ) קבוע המסה המולרית (Mᵤ) molar mass of carbon-12 מסה מולרית של פחמן-12 molar volume of ideal gas (273.15 K, 100 kPa) נפח מולרי של גז �יד�לי (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) נפח מולרי של גז �יד�לי (273.15 K, 101.325 kPa) molar volume of silicon נפח מולרי של סיליקון Sackur-Tetrode constant (1 K, 100 kPa) קבוע שקור-טטרודה (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) קבוע שקור-טטרודה (1 K, 101.325 kPa) Wien frequency displacement law constant קבוע חוק ההעתק של וין לתדירות Wien wavelength displacement law constant קבוע חוק ההעתק של וין ל�ורך גל standard atmosphere (atm) �טמוספרה תקנית (atm) standard-state pressure (p°) לחץ מצב תקני (p°) Angstrom star (Å*) �נגסטרו� כוכב (Å*) Copper x unit יחידת x של נחושת Molybdenum x unit יחידת x של מוליבדן atomic unit of magnetizability יחידה �טומית של מגנטיזביליות atomic unit of mass (mₑ) יחידה �טומית של מסה (mₑ) atomic unit of momentum יחידה �טומית של תנע atomic unit of permittivity יחידה �טומית של פרמיטיביות atomic unit of time יחידה �טומית של זמן atomic unit of velocity יחידה �טומית של מהירות hartree-hertz relationship יחס המרה בין ה�רטרי ל-הרץ hartree-inverse meter relationship יחס המרה בין ה�רטרי ל-מטר הופכי hartree-joule relationship יחס המרה בין ה�רטרי ל-ג׳�ול hartree-kelvin relationship יחס המרה בין ה�רטרי ל-קלווין hartree-kilogram relationship יחס המרה בין ה�רטרי ל-קילוגר� shielding difference of d and p in HD הפרש המיסוך של d ו-p ב-HD shielding difference of t and p in HT הפרש המיסוך של t ו-p ב-HT pi (π) פ�י (π) Euler's number (e) מספר �וילר (e) golden ratio (φ) יחס הזהב (φ) Euler-Mascheroni constant (γ) קבוע �וילר-מסקרוני (γ) nominal solar radius רדיוס שמשי נומינלי nominal solar total irradiance קרינה שמשית כוללת נומינלית nominal solar luminosity בהירות שמשית נומינלית nominal solar effective temperature טמפרטורה �פקטיבית שמשית נומינלית nominal solar mass parameter פרמטר מסה שמשי נומינלי nominal terrestrial equatorial radius רדיוס משווני �רצי נומינלי nominal terrestrial polar radius רדיוס קוטבי �רצי נומינלי nominal terrestrial mass parameter פרמטר מסה �רצי נומינלי nominal jovian equatorial radius רדיוס משווני צדקי נומינלי nominal jovian polar radius רדיוס קוטבי צדקי נומינלי nominal jovian mass parameter פרמטר מסה צדקי נומינלי average value of one minus the rate of TCG relative to TCB ערך ממוצע של �חד פחות קצב TCG ביחס ל-TCB solar mass parameter (TCB-compatible) פרמטר מסה שמשי (תו�� TCB) solar mass parameter (TDB-compatible) פרמטר מסה שמשי (תו�� TDB) equatorial radius of the Earth (TT-compatible) הרדיוס המשווני של כדור ה�רץ (תו�� TT) dynamical form factor of the Earth גור� הצורה הדינמי של כדור ה�רץ time rate of change in the dynamical form factor of the Earth קצב השינוי בזמן של גור� הצורה הדינמי של כדור ה�רץ geocentric gravitational constant (TCB-compatible) קבוע כבידה ג�וצנטרי (תו�� TCB) geocentric gravitational constant (TT-compatible) קבוע כבידה ג�וצנטרי (תו�� TT) geocentric gravitational constant (TDB-compatible) קבוע כבידה ג�וצנטרי (תו�� TDB) potential of the geoid פוטנצי�ל הג�ו�יד nominal mean angular velocity of the Earth (TT-compatible) מהירות זוויתית ממוצעת נומינלית של כדור ה�רץ (תו�מת TT) ratio mass of the Moon to the Earth יחס המסה של הירח לכדור ה�רץ ratio of the mass of the Sun to Mercury יחס מסת השמש למסת חמה ratio of the mass of the Sun to Venus יחס מסת השמש למסת נוגה ratio of the mass of the Sun to Mars יחס מסת השמש למסת מ�די� ratio of the mass of the Sun to Jupiter יחס מסת השמש למסת צדק ratio of the mass of the Sun to Saturn יחס מסת השמש למסת שבת�י ratio of the mass of the Sun to Uranus יחס מסת השמש למסת �ורנוס ratio of the mass of the Sun to Neptune יחס מסת השמש למסת נפטון ratio of the mass of the Sun to (134340) Pluto יחס מסת השמש למסת (134340) פלוטו ratio of the mass of the Sun to (136199) Eris יחס מסת השמש למסת (136199) �ריס ratio of the mass of (1) Ceres to the Sun יחס מסת (1) קרס למסת השמש ratio of the mass of (2) Pallas to the Sun יחס מסת (2) פ�ל�ס למסת השמש ratio of the mass of (4) Vesta to the Sun יחס מסת (4) וסטה למסת השמש mean obliquity of the ecliptic at J2000.0 נטייה ממוצעת של המילקה ב-J2000.0 Electromagnetic �לקטרומגנטי Compton wavelength �ורך גל קומפטון Astronomy �סטרונומיה ConstantsWidget Domain תחו� Subdomain תת-תחו� No match found ל� נמצ�ה הת�מה Name ש� Value ערך Unit יחידה Search חיפוש All הכול CustomKeypadDialog Custom Keypad לוח מקשי� מות�� �ישית Rows: שורות: Columns: עמודות: Copy preset: העתק ערכה מוכנה: Basic בסיסי Scientific (wide) מדעי (רחב) Scientific (narrow) מדעי (צר) Apply החל Row שורה Column עמודה Label תווית Behavior התנהגות Text טקסט DiagnosticsDialog App Diagnostics �בחון היישו� Copy to Clipboard העתקה ללוח Editor Unit יחידה User unit יחידת משתמש User function פונקציית משתמש Argument �רגומנט Current result:<br/>%1 תוצ�ה נוכחית:<br/>%1 Selection result:<br/>%1 תוצ�ת הבחירה:<br/>%1 Selection result: n/a תוצ�ת הבחירה: ל� זמין Selection result: %1 תוצ�ת הבחירה: %1 second שנייה metre מטר kilogram קילוגר� mole מול radian רדי�ן steradian סטרדי�ן degree Celsius מעלה צלזיוס cubic metre מטר מעוקב cubic millimetre מילימטר מעוקב cubic centimetre סנטימטר מעוקב cubic decimetre דצימטר מעוקב cubic kilometre קילומטר מעוקב square millimetre מילימטר רבוע square kilometre קילומטר רבוע square metre מטר רבוע minute דקה hour שעה day יו� astronomical unit יחידה �סטרונומית degree מעלה arcminute דקת קשת arcsecond שניית קשת milliarcsecond מילישניית קשת microarcsecond מיקרושניית קשת hectare הקטר litre ליטר tonne טונה Dalton דלטון electronvolt �לקטרון־וולט Angstrom �נגסטרו� atmosphere �טמוספרה atomic mass unit יחידת מסה �טומית British thermal unit יחידה תרמית בריטית calorie קלוריה carat קר�ט cup כוס cup (Imperial) כוס (�ימפרי�לית) cup (Japanese) כוס (יפנית) cup (US) כוס (�רה״ב) degree Fahrenheit מעלה פרנהייט fathom פ�תו� fluid ounce (Imperial) �ונקיית נוזלי� (�ימפרי�לית) fluid ounce (US) �ונקיית נוזלי� (�רה״ב) fluid dram (Imperial) דר�� נוזלי (�ימפרי�לי) fluid dram (US) דר�� נוזלי (�רה״ב) foot רגל square foot רגל רבועה cubic foot רגל מעוקבת gallon (Imperial) גלון (�ימפרי�לי) gallon (US) גלון (�רה״ב) gill (Imperial) גיל (�ימפרי�לי) gill (US) גיל (�רה״ב) gradian גרדי�ן grain גריין gram גר� Hartley הרטלי Hartree energy unit יחידת �נרגיה ה�רטרי horsepower כוח סוס inch �ינץ׳ square inch �ינץ׳ רבוע cubic inch �ינץ׳ מעוקב karat קר�ט knot קשר lightminute דקת �ור lightsecond שניית �ור lightyear שנת �ור long ton טון �רוך mile מייל square mile מייל רבוע cubic mile מייל מעוקב mile per hour מייל לשעה kilometre per hour קילומטר לשעה nautical mile מייל ימי ounce �ונקיה parsec פ�רסק pint (Imperial) פיינט (�ימפרי�לי) pint (US) פיינט (�רה״ב) pound פ�ונד pounds per square inch פ�ונד ל�ינץ׳ רבוע quart (Imperial) קוורט (�ימפרי�לי) quart (US) קוורט (�רה״ב) oil barrel חבית נפט beer barrel (US) חבית בירה (�רה״ב) square yard י�רד רבוע cubic yard י�רד מעוקב short ton טון קצר tablespoon כף tablespoon (Australian) כף (�וסטרלית) tablespoon (Imperial) כף (�ימפרי�לית) tablespoon (US) כף (�רה״ב) dessert spoon כף קינוח teaspoon כפית teaspoon (Imperial) כפית (�ימפרי�לית) teaspoon (US) כפית (�רה״ב) turn סיבוב revolution הקפה revolution per minute הקפות לדקה week שבוע kilowatt hour קילוו�ט שעה millimetre of mercury מילימטר כספית yard י�רד Julian century מ�ה יולי�נית Julian year שנה יולי�נית sidereal year שנה כוכבית tropical year שנה טרופית Evaluator invalid expression ביטוי ל� מובן division by zero חלוקה ב�פס too time consuming - computation was rejected החישוב דורש זמן רב מדי - הבקשה נדחתה dimension mismatch - quantities with different dimensions cannot be compared, added, etc. �י-הת�מה בממדי� - ל� ניתן להשוות, לחבר וכדומה גדלי� בעלי ממדי� שוני� invalid dimension - operation might require dimensionless arguments ממד ל� תקין - הפעולה עשויה לדרוש �רגומנטי� חסרי ממד Computation aborted - encountered numerical instability החישוב הופסק - זוהתה �י-יציבות נומרית invalid dimension - function might require dimensionless arguments ממד ל� תקין - הפונקציה עשויה לדרוש �רגומנטי� חסרי ממד error שגי�ה unit must not be zero היחידה �ינה יכולה להיות �פס Conversion failed - dimension mismatch ההמרה נכשלה - �י-הת�מה בממדי� unknown function or variable פונקציה �ו משתנה ל� מזוהה recursion not supported רקורסיה �ינה נתמכת cannot operate on a NaN ל� ניתן לבצע פעולה על NaN underflow - tiny result is out of SpeedCrunch's number range תת-זרימה - התוצ�ה קטנה מדי לטווח המספרי� של SpeedCrunch overflow - huge result is out of SpeedCrunch's number range גלישה - התוצ�ה גדולה מדי לטווח המספרי� של SpeedCrunch overflow - logic result exceeds maximum of 256 bits גלישה - התוצ�ה הלוגית חורגת מהמקסימו� של 256 סיביות overflow - integer result exceeds maximum limit for integers גלישה - תוצ�ת המספר השל� חורגת מהמגבלה המרבית operation is not defined for these arguments הפעולה �ינה מוגדרת עבור ה�רגומנטי� ה�לה wrong number of arguments מספר שגוי של �רגומנטי� does not take NaN as an argument �ינה מקבלת NaN כ�רגומנט result out of range תוצ�ה מחוץ לתחו� undefined for argument domain ל� מוגדר עבור תחו� ה�רגומנט computation too expensive החישוב יקר מדי internal error, please report a bug תקלה פנימית, דווח על ב�ג syntax error שגי�ת תחביר conversion target must be a unit יעד ההמרה חייב להיות יחידה unknown unit יחידה ל� ידועה %1 is a reserved name, please choose another %1 הו� ש� שמור, נ� לבחור ש� �חר %1 is a global user definition and cannot be overridden in this session. %1 הי� הגדרת משתמש גלובלית ו�י �פשר לעקוף �ותה בהפעלה זו. %1 is a variable name, please choose another or delete the variable %1 הו� ש� של משתנה, נ� לבחור ש� �חר �ו למחוק �ת המשתנה argument %1 is used more than once ה�רגומנט %1 מופיע יותר מפע� �חת %1 is a built-in unit name, please choose another %1 הו� ש� יחידה מובנה, נ� לבחור ש� �חר %1 is a user function name, please choose another or delete the function %1 הו� ש� של פונקציית משתמש, נ� לבחור ש� �חר �ו למחוק �ת הפונקציה FunctionRepo max; trials; probability מקסימו�; ניסויי�; הסתברות trials; probability ניסויי�; הסתברות hits; trials; probability הצלחות; ניסויי�; הסתברות max; total; hits; trials מקסימו�; סך הכול; הצלחות; ניסויי� total; hits; trials סך הכול; הצלחות; ניסויי� count; total; hits; trials ספירה; סך הכול; הצלחות; ניסויי� dividend; divisor מחולק; מחלק x; exponent_bits; significand_bits [; exponent_bias] x; סיביות מעריך; סיביות מנטיסה [; הטיית מעריך] base; x בסיס; x value; modulo ערך; מודולו base; exponent; modulo בסיס; מעריך; מודולו events; average_events �ירועי�; ממוצע �ירועי� average_events ממוצע �ירועי� x [; precision] x [; דיוק] Absolute Value ערך מוחלט Absolute Deviation סטייה מוחלטת Arc Cosine �רק-קוסינוס Logical AND וג� לוגי (AND) Area Hyperbolic Cosine קוסינוס היפרבולי הפוך Area Hyperbolic Sine סינוס היפרבולי הפוך Area Hyperbolic Tangent טנגנס היפרבולי הפוך Arc Sine �רק-סינוס Arc Tangent �רק-טנגנס Arc Tangent with two Arguments �רק-טנגנס ע� שני �רגומנטי� Average (Arithmetic Mean) ממוצע (ממוצע �ריתמטי) Binomial Cumulative Distribution Function פונקציית התפלגות מצטברת בינומית Binomial Distribution Mean הממוצע של התפלגות בינומית Binomial Probability Mass Function פונקציית מסת הסתברות בינומית Binomial Distribution Variance השונות של התפלגות בינומית Cube Root שורש שלישי Complex Conjugate צמוד מרוכב Cosine קוסינוס Hyperbolic Cosine קוסינוס היפרבולי Cotangent קוטנגנס Cosecant קוסק�נט Convert Unix timestamp to Date המרת חותמת זמן Unix לת�ריך Degrees of Arc מעלות קשת Error Function פונקציית שגי�ה Complementary Error Function פונקציית שגי�ה משלימה Exponential �קספוננט Fractional Part החלק השברי Extension of Factorials [= (x-1)!] הרחבת עצרות [= (x-1)!] Greatest Common Divisor המחלק המשותף הגדול ביותר Geometric Mean ממוצע הנדסי Gradians of arc גרדי�ני� של קשת Hypergeometric Cumulative Distribution Function פונקציית התפלגות מצטברת היפרג�ומטרית Hypergeometric Distribution Mean הממוצע של התפלגות היפרג�ומטרית Hypergeometric Probability Mass Function פונקציית מסת הסתברות היפרג�ומטרית Hypergeometric Distribution Variance השונות של התפלגות היפרג�ומטרית Integer Quotient מנה שלמה Integer Part החלק השל� Imaginary Part החלק המדומה Decode IEEE-754 Binary Value פענוח ערך בינ�רי IEEE-754 Encode IEEE-754 Binary Value קידוד ערך בינ�רי IEEE-754 Decode 16-bit Half-Precision Value פענוח ערך חצי-דיוק של 16 סיביות Encode 16-bit Half-Precision Value קידוד ערך חצי-דיוק של 16 סיביות Decode 32-bit Single-Precision Value פענוח ערך דיוק יחיד של 32 סיביות Encode 32-bit Single-Precision Value קידוד ערך דיוק יחיד של 32 סיביות Decode 64-bit Double-Precision Value פענוח ערך דיוק כפול של 64 סיביות Encode 64-bit Double-Precision Value קידוד ערך דיוק כפול של 64 סיביות Decode 128-bit Quad-Precision Value פענוח ערך דיוק מרובע של 128 סיביות Encode 128-bit Quad-Precision Value קידוד ערך דיוק מרובע של 128 סיביות Binary Logarithm לוגרית� בינ�רי Common Logarithm לוגרית� עשרוני Natural Logarithm לוגרית� טבעי Logarithm to Arbitrary Base לוגרית� לבסיס שרירותי Mask to a bit size מיסוך לפי גודל סיביות Maximum מקסימו� Median Value (50th Percentile) ערך חציוני (�חוזון 50) Minimum מינימו� Modulo מודולו Euclidean Modulo מודולו �וקלידי Modular Exponentiation חזקה מודולרית Combination (Binomial Coefficient) צירוף (מקד� בינומי) Logical NOT ל� לוגי (NOT) Permutation (Arrangement) תמורה Convert to Binary Representation המרה לייצוג בינ�רי Arithmetic �ריתמטיקה Chemistry כימיה Complex מרוכבי� Combinatorics קומבינטוריקה Probability הסתברות Statistics סטטיסטיקה Aggregation צבירה Random �קר�י Base conversion המרת בסיס Number formatting עיצוב מספרי� Integer arithmetic �ריתמטיקה של מספרי� שלמי� Special functions פונקציות מיוחדות Exponential & Logarithmic מעריכיות ולוגריתמיות Angle conversion המרת זוויות Trigonometry טריגונומטריה Bitwise פעולות סיביות Floating point נקודה צפה Date & Time ת�ריך ושעה Linear algebra �לגברה ליני�רית unix_timestamp; x hours offset to GMT חותמת זמן Unix; היסט של x שעות מ-GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; היסט של x שעות מ-GMT [digits] [ספרות] max [; min] מקסימו� [; מינימו�] List Literal ליטרל רשימה Convert to Padded Binary Representation המרה לייצוג בינ�רי מרופד Round Toward +∞ (Ceiling) עיגול לכיוון +∞ (תקרה) Cosine plus Imaginary Sine קוסינוס ועוד סינוס מדומה Convert to Cis Complex Form המרה לצורה מרוכבת Cis Matrix Column Count מספר עמודות במטריצה Population Correlation Matrix (n) מטריצת מת�� של �וכלוסייה (n) Sample Correlation Matrix (n-1) מטריצת מת�� של מדג� (n-1) Count ספירה Population Covariance Matrix (n) מטריצת שונות משותפת של �וכלוסייה (n) Sample Covariance Matrix (n-1) מטריצת שונות משותפת של מדג� (n-1) Cross Product מכפלה וקטורית Convert Date to Unix timestamp המרת ת�ריך לחותמת זמן Unix Convert to Decimal Representation המרה לייצוג עשרוני Determinant דטרמיננטה Convert to Sexagesimal Notation המרה לסימון שישוני Dot Product מכפלה סקלרית Convert to Engineering Notation המרה לסימון הנדסי Convert to Exponential Complex Form המרה לצורה מרוכבת מעריכית Round Toward −∞ (Floor) עיגול לכיוון −∞ (רצפה) Flatten Matrix השטחת מטריצה Least Common Multiple כפולה משותפת מינימלית Convert to Hexadecimal Representation המרה לייצוג הקסדצימלי Convert to Padded Hexadecimal Representation המרה לייצוג הקסדצימלי מרופד Inverse Matrix מטריצה הופכית Round to 16-bit Half-Precision Value עיגול לערך חצי-דיוק של 16 סיביות Round to 32-bit Single-Precision Value עיגול לערך דיוק יחיד של 32 סיביות Round to 64-bit Double-Precision Value עיגול לערך דיוק כפול של 64 סיביות Round to 128-bit Quad-Precision Value עיגול לערך דיוק מרובע של 128 סיביות Residual from 16-bit Half-Precision Rounding ש�רית מעיגול חצי-דיוק של 16 סיביות Residual from 32-bit Single-Precision Rounding ש�רית מעיגול דיוק יחיד של 32 סיביות Residual from 64-bit Double-Precision Rounding ש�רית מעיגול דיוק כפול של 64 סיביות Residual from 128-bit Quad-Precision Rounding ש�רית מעיגול דיוק מרובע של 128 סיביות Substance Mass מסת חומר Molarity מולריות Molar Mass מסה מולרית Median Absolute Deviation סטייה מוחלטת חציונית Mean ממוצע Numerical Value of Quantity ערך מספרי של גודל Random Decimal Number מספר עשרוני �קר�י Random Integer Number מספר של� �קר�י Convert to Rational Representation המרה לייצוג רציונלי Convert to Octal Representation המרה לייצוג �וקטלי Convert to Padded Octal Representation המרה לייצוג �וקטלי מרופד Vector or Matrix Norm נורמה של וקטור �ו מטריצה Logical OR �ו לוגי (OR) Population Count (Hamming Weight) ספירת ביטי� דלוקי� (משקל המינג) Phase of Complex Number הפ�זה של מספר מרוכב Poissonian Cumulative Distribution Function פונקציית התפלגות מצטברת פו�סונית Poissonian Distribution Mean הממוצע של התפלגות פו�סונית Poissonian Probability Mass Function פונקציית מסת הסתברות פו�סונית Poissonian Distribution Variance השונות של התפלגות פו�סונית Convert to Phasor Complex Form המרה לצורה מרוכבת פ�זורית Convert to Rectangular Complex Form המרה לצורה מרוכבת קרטזית Round Half Away from Zero עיגול חצי הרחק מ�פס Round Half Even עיגול חצי לזוגי Nth Root שורש מסדר n Convert to Scientific Notation המרה לסימון מדעי Matrix Row Count מספר שורות במטריצה List or Matrix Shape צורת רשימה �ו מטריצה Summation סכימה Population Standard Deviation (n) סטיית תקן של �וכלוסייה (n) Sample Standard Deviation (n-1) סטיית תקן של מדג� (n-1) Round Toward Zero (Truncation) עיגול לכיוון �פס (קיטו�) Matrix Trace עקבת מטריצה Transpose Matrix שחלוף מטריצה Population Variance (n) שונות של �וכלוסייה (n) Sample Variance (n-1) שונות של מדג� (n-1) Product מכפלה Radians רדי�ני� Matrix Rank דרגת מטריצה Real Part החלק הממשי Secant סקנט Arithmetic Shift Left הזזה �ריתמטית שמ�לה Arithmetic Shift Right הזזה �ריתמטית ימינה Signum סימן Sine סינוס Hyperbolic Sine סינוס היפרבולי Square Root שורש ריבועי Sum סכו� Tangent טנגנס Convert to Trigonometric Complex Form המרה לצורה מרוכבת טריגונומטרית Turns סיבובי� Hyperbolic Tangent טנגנס היפרבולי Sign-extend a value הרחבת סימן לערך Logical XOR �ו בלעדי לוגי (XOR) FunctionsWidget Domain תחו� All הכול Name ש� Search חיפוש No match found ל� נמצ�ה הת�מה Identifier מזהה HistoryWidget Remove All Calculations Above הסר �ת כל החישובי� מעל Remove This Calculation הסר חישוב זה Remove All Calculations Below הסר �ת כל החישובי� מתחת Keypad Inverse cosine קוסינוס הפוך The last result התוצ�ה ה�חרונה Inverse sine סינוס הפוך Inverse tangent טנגנס הפוך Evaluate expression חשב ביטוי Division חילוק Multiplication כפל Subtraction חיסור Addition חיבור Clear expression נקה ביטוי Cosine קוסינוס Backspace מחיקה ל�חור Scientific notation סימון מדעי Exponential �קספוננט Factorial עצרת Natural logarithm לוגרית� טבעי Left parenthesis סוגריי� שמ�ליי� Nth root שורש מסדר n Argument separator מפריד �רגומנטי� Square ריבוע Common logarithm לוגרית� עשרוני Modulo מודולו Contextual percentage �חוז תלוי הקשר Power הספק Right parenthesis סוגריי� ימניי� Sine סינוס Square root שורש ריבועי Tangent טנגנס Pi פ�י Decimal separator מפריד עשרוני MainWindow Radian רדי�ן Degree מעלה Gradian גרדי�ן Binary בינ�רי Octal �וקטלי Hexadecimal הקסדצימלי Sexagesimal שיטה שישונית Engineering decimal נקודה עשרונית הנדסית Scientific decimal נקודה עשרונית מדעית &Import... י&בו�... &Quit &יצי�ה Clear E&xpression &ניקוי חישוב Clear &History ניקוי &היסטוריה &Copy &העתקה &Paste &הדבקה &Select Expression &בחירת ביטוי &Constants &קבועי� &Functions &פונקציות &History &היסטוריה &Status Bar פס המ&צב Bitfield שדה סיביות Use&r Functions פונקציות &משתמש &Degree &מעלה &Radian &רדי�ן &Gradian &גרדי�ן Re&volution &הקפה Auto-Insert a&ns הוספת a&ns �וטומטית Automatic &Completion השלמה &�וטומטית &Built-in Functions &פונקציות מובנות Built-in &Variables &משתני� מובני� User &Functions פ&ונקציות משתמש User Va&riables מ&שתני משתמש Open a Private Tab on Startup פתיחת לשונית פרטית בהפעלה Open and focus a new private tab whenever SpeedCrunch starts. פתיחה ומיקוד של לשונית פרטית חדשה בכל הפעלה של SpeedCrunch. Syntax &Highlighting &הדגשת דקדוק Group Digits in &Input &קיבוץ ספרות בקלט Automatic Input &Adjustments &הת�מות קלט �וטומטיות Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. הת�מה �וטומטית של �ופרטורי�, רווחי�, סוגריי� וחזקות, והגבלת הקלט לתווי� תקיני�. Group input digits using the selected number format. קיבוץ ספרות הקלט לפי תבנית המספרי� שנבחרה. &Blinking Cursor &סמן מהבהב Blink the cursor in the expression editor. הבהוב הסמן בעורך הביטויי�. &Escape Clears Editor &Escape מנקה �ת העורך Clear the focused expression editor with Escape after dismissing any popup or preview. ניקוי עורך הביטויי� הפעיל ב�מצעות Escape ל�חר סגירת חלונות קופצי� �ו תצוגות מקדימות. Keep Expression After Evaluation שמירת הביטוי ל�חר החישוב Copy New Results Automatically העתקת תוצ�ות חדשות �וטומטית &Comma &פסיק &System Default &ברירת מחדל &Dot &נקודה Dot &And Comma נקודה ו&פסיק Toward +∞ (&ceil) לכיוון +∞ (&ceil) Toward −∞ (&floor) לכיוון −∞ (&floor) &Binary &בינ�רי &Engineering &הנדסי &Hexadecimal ה&קסדצימלי &Octal &�וקטלי &Scientific &מדעי User &Manual &מדריך למשתמש Issues and &Feedback &בעיות ומשוב &Donate &תרומה &About SpeedCrunch �&ודות SpeedCrunch App Diag&nostics &�בחון היישו� S&plit פ&יצול Angle &Mode מ&צב זווית &Complex Form &צורה מרוכבת New Tab כרטיסייה חדשה Constants קבועי� Functions פונקציות History היסטוריה User Functions פונקציות משתמש &Font... &גופן... &Language... &שפה... &Session &קובץ &Edit &עריכה &View &תצוגה Se&ttings &הגדרות &Decimal &דצימלי &Keypad &מקשי ספרות Always on &Top תמיד &מעל Disabled מושבת Small Space רווח קטן Medium Space רווח בינוני Large Space רווח גדול &0 Digits &0 ספרות &15 Digits &15 ספרות &2 Digits &2 ספרות &3 Digits &3 ספרות &50 Digits &50 ספרות &8 Digits &8 ספרות &Sexagesimal &שיטה שישונית Reset All Settings... �יפוס כל ההגדרות... &System &מערכת SpeedCrunch &Theme &ערכת הנוש� של SpeedCrunch &Classic &קל�סי &Modern &מודרני Context Help עזרה לפי הקשר &Help &עזרה Error שגי�ה Can't read from file %1 ל� ניתן לקרו� מהקובץ %1 Import Session יבו� חישוב Close Session סגור הפעלה Angle Mode: מצב זווית: Notation: סימון: Precision: דיוק: Turn סיבוב Revolution הקפה Fixed-point decimal עשרוני בנקודה קבועה Rational רציונלי Automatic decimal עשרוני �וטומטי Automatic �וטומטי User &Definitions... הגדרות &משתמש... New &Tab כרטיסייה &חדשה New &Private Tab &לשונית פרטית חדשה Keep שמירה Make Private... הפיכה לפרטי... New &Window &חלון חדש &Open... &פתח... &Rename... &שינוי ש�... Clo&ne... ש&כפול... &Close Tab &סגירת לשונית Reopen Clo&sed Tab פתיח&ה מחדש של לשונית שנסגרה Open Sessions &Folder פתח �ת &תיקיית ההפעלות &Undo ב&יטול &Redo בי&צוע חוזר Cu&t &גזירה Copy &Last Result ה&עתקת התוצ�ה ה�חרונה &Wrap in Parentheses ע&טיפה בסוגריי� Full Scr&een Mode מצ&ב מסך מל� &Basic &בסיסי &Scientific (wide) &מדעי (רחב) Scientific (narrow) מדעי (צר) &Custom... &מות�� �ישית... Main &Menu תפריט &ר�שי User &Variables משתני &משתמש &Left &שמ�לה &Right &ימינה &Up &למעלה &Down ל&מטה Close Pa&ne ס&גור חלונית User &Units יחידות &משתמש &Turn &סיבוב If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. �� ביטוי חדש מתחיל ב-+, -, * �ו /, SpeedCrunch מוסיף תחילה �ת "ans". &Accept with Enter &�ישור ב�מצעות Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. �ישור הצעת ההשלמה ה�וטומטית הנוכחית ב�מצעות Enter בלי לבחור בה תחילה בעזרת מקשי החצי�. &Units &יחידות Show Live Result &Preview הצג &תצוגה מקדימה חיה של התוצ�ה Save &Window Position on Exit שמור �ת מיקו� ה&חלון ביצי�ה Hover Highlighting הדגשה בריחוף Group Integer Part Only קבץ �ת החלק השל� בלבד Number Format... תבנית מספר... Notation && Precision... סימון && דיוק... After pressing Enter, keep the entered expression selected in the editor. ל�חר הקשה על Enter, הש�ר �ת הביטוי שהוזן מסומן בעורך. Never �ף פע� Always תמיד Only for Single-Line Expressions רק לביטויי� בשורה �חת Simplify Displayed Expressions פשט ביטויי� מוצגי� History Size &Limit... &מגבלת גודל היסטוריה... Remove Trailing &Zeroes &הסרת �פסי� בסוף Nearest, Half &Away (round) הקרוב ביותר, חצי &הל�ה (round) Nearest, Half &Even (roundeven) הקרוב ביותר, חצי &לזוגי (roundeven) Toward &Zero (trunc) לכיוון &�פס (trunc) &Fixed-Point נקודה &קבועה &Rational &רציונלי &Exponential (m·s�¹) &מעריכי (m·s�¹) &Fractional (m/s) &שברי (m/s) &Rectangular (a + bi) &קרטזי (a + bi) Exponential (re�ᶿ) מעריכי (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) טריגונומטרי (r(cos θ + i·sin θ)) Phasor (r∠θ) פ�זור (r∠θ) &Theme... &ערכת נוש�... Check for &Updates בדוק &עדכוני� Source Code קוד מקור &Zoom &תקריב &Results &תוצ�ות Unit Notation סימון יחידות Rounding Mode מצב עיגול &Notation &סימון &Imaginary Unit יחידה &מדומה &Window &חלון &Editing &עריכה A&utocomplete השלמה &�וטומטית Up/Down Arrow History היסטוריה בחיצי� למעלה/למטה &Appearance &מר�ה &Menus &תפריטי� &Docks &לוחות ניתני� לעגינה &Input and Results &קלט ותוצ�ות &Disabled &מושבת &Disable ה&שבת Close preview סגור תצוגה מקדימה Rename... שינוי ש�... Clone... שכפול... Close Tab סגירת לשונית New Private Tab לשונית פרטית חדשה Open... פתח... Reopen Closed Tab פתיחה מחדש של לשונית שנסגרה Split פיצול Left שמ�לה Right ימינה Up למעלה Down למטה Clear ניקוי Delete מחק %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 הפעלה פרטית: התוכן נמחק ע� הסגירה. יש לבחור קובץ > שמירה כדי להפוך �ותה להפעלה רגילה. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [פרטי] Reset All Settings �יפוס כל ההגדרות Reset all settings to their default values? ל�פס �ת כל ההגדרות לערכי ברירת המחדל שלהן? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. זה כולל מר�ה, עריכה, תבניות תוצ�ות והעדפות חלונות. החישובי�, ההפעלות הפתוחות והגדרות המשתמש יישמרו. The settings file could not be written. ל� ניתן היה לכתוב �ת קובץ ההגדרות. Clear this session's calculations, unfinished expression, variables, functions, and units? לנקות �ת החישובי�, הביטוי של� הושל�, המשתני�, הפונקציות והיחידות של ההפעלה הזו? Global user definitions are kept. הגדרות המשתמש הכלליות נשמרות. Make Session Private הפיכת ההפעלה לפרטית The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. ההפעלה השמורה %1 תימחק. התוכן שלה ייש�ר פתוח בהפעלה פרטית ויימחק ע� סגירת ההפעלה �ו היצי�ה מ־SpeedCrunch. Make Private הפיכה לפרטי Could not delete the saved session %1. ל� ניתן היה למחוק �ת ההפעלה השמורה %1. Keep Session שמירת ההפעלה Could not save the session. It remains private. ל� ניתן היה לשמור �ת ההפעלה. הי� נש�רת פרטית. Clone Session שכפול הפעלה Could not save session file %1. ל� ניתן היה לשמור �ת קובץ ההפעלה %1. Could not delete session file %1. ל� ניתן היה למחוק �ת קובץ ההפעלה %1. JSON file (*.json);;Any file (*.*) קובץ JSON (*.json);;כל קובץ (*.*) Export session as JSON ייצו� ההפעלה כ-JSON The selected file is not valid JSON: %1 הקובץ שנבחר �ינו JSON תקין: %1 The selected file is not a SpeedCrunch session JSON file. הקובץ שנבחר �ינו קובץ JSON של הפעלת SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. קובץ זה משתמש בתבנית הפעלה מיושנת של SpeedCrunch ו�י �פשר לייב� �ותו. The selected JSON file is missing the required $schema field. בקובץ ה-JSON שנבחר חסר השדה הדרוש $schema. The selected JSON file uses an unsupported JSON schema: %1 קובץ ה-JSON שנבחר משתמש בסכמת JSON ש�ינה נתמכת: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). בקובץ ה-JSON שנבחר חסר מזהה סכמת ההפעלה של SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 קובץ ה-JSON שנבחר משתמש בתבנית הפעלה של SpeedCrunch ש�ינה נתמכת: %1 The selected JSON file is missing the required session name. בקובץ ה-JSON שנבחר חסר ש� ההפעלה הדרוש. The selected JSON file has an empty session name. בקובץ ה-JSON שנבחר ש� ההפעלה ריק. The selected JSON file has invalid or incomplete SpeedCrunch session data. בקובץ ה-JSON שנבחר יש נתוני הפעלת SpeedCrunch ל� תקיני� �ו ל� שלמי�. Open Sessions Folder פתח �ת תיקיית ההפעלות Could not create the sessions folder: %1 ל� ניתן ליצור �ת תיקיית ההפעלות: %1 Could not open the sessions folder: %1 ל� ניתן לפתוח �ת תיקיית ההפעלות: %1 Editor and Results Font גופן העורך והתוצ�ות Open Session פתח הפעלה Community קהילה Rename Session שנה ש� הפעלה Clear Session נקה הפעלה Delete Session מחק הפעלה Close Pane סגור חלונית User Variables משתני משתמש User Units יחידות משתמש Clear History נקה היסטוריה Are you sure you want to clear the calculation history? ה�� למחוק �ת היסטוריית החישובי�? Session name: ש� ההפעלה: A session named %1 already exists. הפעלה בש� %1 כבר קיימת. Could not create session file %1. ל� ניתן ליצור �ת קובץ ההפעלה %1. Could not write session file %1. ל� ניתן לכתוב �ת קובץ ההפעלה %1. Are you sure you want to delete this session? ה�� למחוק �ת ההפעלה הזו? Custom Precision דיוק מות�� �ישית Fractional digits: ספרות שבריות: Theme ערכת נוש� Light Themes ערכות נוש� בהירות Dark Themes ערכות נוש� כהות Preview תצוגה מקדימה Colors צבעי� Select color for %1 בחירת צבע עבור %1 Import... יבו�... Export... יצו�... Import Theme ייבו� ערכת נוש� Theme file (*.json);;All files (*) קובץ ערכת נוש� (*.json);;כל הקבצי� (*) Invalid theme file. קובץ ערכת הנוש� �ינו תקין. Can't import theme "%1" because it conflicts with a built-in theme. ל� ניתן לייב� �ת ערכת הנוש� "%1" כי הי� מתנגשת ע� ערכת נוש� מובנית. Can't find a writable theme folder. ל� ניתן למצו� תיקיית ערכות נוש� שניתן לכתוב �ליה. Overwrite Theme דרוס ערכת נוש� A custom theme named "%1" already exists. Do you want to overwrite it? ערכת נוש� מות�מת �ישית בש� "%1" כבר קיימת. ה�� לדרוס �ותה? Can't overwrite theme file %1 ל� ניתן לדרוס �ת קובץ ערכת הנוש� %1 Can't copy theme file to %1 ל� ניתן להעתיק �ת קובץ ערכת הנוש� �ל %1 Export Theme ייצו� ערכת נוש� Can't export theme as "%1" because it conflicts with a built-in theme. ל� ניתן לייצ� �ת ערכת הנוש� בש� "%1" כי הי� מתנגשת ע� ערכת נוש� מובנית. Can't write to file %1 ל� ניתן לכתוב לקובץ %1 Global User Variable משתנה משתמש גלובלי Global User Function פונקציית משתמש גלובלית Global User Unit יחידת משתמש גלובלית User Definitions הגדרות משתמש These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. הגדרות �לו הן גלובליות ונטענות בכל הפעלה. ל� ניתן לשנות �ותן מתוך ההפעלות, והן מקבלות עדיפות על פני הגדרות בעלות �ותו ש� מעורך ההפעלה. יש להזין הגדרה �חת בכל שורה. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] דוגמ�ות: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply החל Validate �מת Test Results תוצ�ות הבדיקה Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 משתני� שיוב�ו: %1 פונקציות שיוב�ו: %2 יחידות שיוב�ו: %3 מספרי שורות ע� שגי�ות: %4 none �ין Apply Results תוצ�ות ההחלה User definitions saved. הגדרות המשתמש נשמרו. History Size Limit מגבלת גודל היסטוריה Maximum number of history entries for this session (0 = unlimited): מספר רשומות ההיסטוריה המרבי להפעלה זו (0 = לל� הגבלה): Text file (*.txt);;Any file (*.*) קובץ טקסט (*.txt);;כל קובץ (*.*) Could not recalculate from calculation %1: %2 ל� ניתן לחשב מחדש החל מחישוב %1: %2 History Size Limit Reached הגעת למגבלת גודל ההיסטוריה This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. חישוב זה ממל� �ת מקו� ההיסטוריה ה�חרון הזמין. חישובי� עתידיי� יסירו מההיסטוריה �ת החישוב הישן ביותר. ניתן להגדיל �ת המגבלה דרך הפעלה > מגבלת גודל היסטוריה. Editing calculation. Press Esc twice to cancel. עריכת חישוב. הקש Esc פעמיי� לביטול. Calculation Settings הגדרות חישוב Invalid recalculation start index �ינדקס התחלה ל� תקין לחישוב מחדש System Default ברירת מחדל Language שפה Select the language: בחר שפה: Custom מות�� �ישית Decimal places: מקומות עשרוניי�: &Automatic &�וטומטי &Precision &דיוק Plain &text טקסט &פשוט Formula &Book &ספר נוסח�ות &Export &ייצו� Export session as HTML ייצו� ההפעלה כ-HTML HTML file (*.html) קובץ HTML (*.html) Export session as plain text ייצו� המפגש כטקסט פשוט ManualWindow SpeedCrunch Manual מדריך SpeedCrunch %1 - SpeedCrunch Manual %1 - מדריך SpeedCrunch NumberFormatDialog Number Format תבנית מספר <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>יש לבחור �ת תבנית המספרי� לתוצ�ות ולקיבוץ ספרות הקלט.</b><br/><br/>הערה: בקלט מספרי� מתקבלות תבניות חד־משמעיות ג� �� הן שונות מתבנית התצוגה שנבחרה.<br/> QObject Global User Variable משתנה משתמש גלובלי Global User Function פונקציית משתמש גלובלית Global User Unit יחידת משתמש גלובלית Backspace מחיקה ל�חור Clear expression נקה ביטוי Evaluate expression חשב ביטוי Insert text הוסף טקסט Automatic decimal עשרוני �וטומטי Fixed-point decimal עשרוני בנקודה קבועה Engineering decimal עשרוני הנדסי Scientific decimal עשרוני מדעי Rational רציונלי Binary בינ�רי Octal �וקטלי Hexadecimal הקסדצימלי Sexagesimal שישוני Update Available קיי� עדכון A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> גרסה חדשה יותר (%1) זמינה.<br/><a href="%2">בקר ב�תר כדי להוריד.</a> Check for Updates בדוק עדכוני� SpeedCrunch %1 is up to date. SpeedCrunch %1 מעודכן. No connectivity. Please check your internet connection and try again. �ין חיבור. נ� לבדוק �ת החיבור ל�ינטרנט ולנסות שוב. Could not verify the latest available version. ל� ניתן ל�מת �ת הגרסה ה�חרונה הזמינה. ResultDisplay Scroll to bottom גלול לתחתית Edit Expression ערוך ביטוי Change Settings שנה הגדרות New Tab כרטיסייה חדשה &Import... י&בו�... &Export &ייצו� Plain &text טקסט &פשוט Copy העתקה Selection בחירה Select All בחירת הכול Expression ביטוי Result תוצ�ה Calculation חישוב Calculation as Single Line חישוב בשורה �חת Remove הסרה This Calculation החישוב הזה All Calculations Above כל החישובי� שמעל All Calculations Below כל החישובי� שמתחת New Private Tab לשונית פרטית חדשה Session קובץ Open... פתח... Clone... שכפול... Rename... שינוי ש�... Keep שמירה Make Private... הפיכה לפרטי... Clear ניקוי Delete מחק Close סגירה Split פיצול Left שמ�לה Right ימינה Up למעלה Down למטה Close Pane סגור חלונית Main Menu תפריט ר�שי Cancel editing בטל עריכה Copy result העתק תוצ�ה Edit expression ערוך ביטוי Change settings שנה הגדרות Remove calculation הסר חישוב ResultSlotsDialog Notation & Precision סימון ודיוק Result Line שורת תוצ�ה Enabled מופעל Notation סימון Decimal Places מקומות עשרוניי� Main Line שורה ר�שית Extra Line #1 שורה נוספת #1 Extra Line #2 שורה נוספת #2 Extra Line #3 שורה נוספת #3 Extra Line #4 שורה נוספת #4 Auto �וטומטי UserFunctionListWidget Name ש� Value ערך Description תי�ור Search חיפוש No match found ל� נמצ�ה הת�מה Insert הוסף Edit ערוך Delete מחק Delete All מחק הכל UserUnitListWidget Name ש� Value ערך Description תי�ור Search חיפוש No match found ל� נמצ�ה הת�מה Insert הוסף Edit ערוך Delete מחק Delete All מחק הכול VariableListWidget Name ש� Value ערך Description תי�ור Search חיפוש No match found ל� נמצ�ה הת�מה Insert הוסף Edit ערוך Delete מחק Delete All מחק הכל heldercorreia-speedcrunch-e7ca37f/src/resources/locale/hi.ts000066400000000000000000011744161526573132500243630ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunch के बारे में Main author | Logo | Maintainer म�ख�य लेखक | लोगो | अन�रक�षक Core developers म�ख�य डेवलपर Original author मूल लेखक Math engine गणित इंजन Thanks आभार Copyright (C) 2004-2026 The SpeedCrunch developers कॉपीराइट (C) 2004-2026 SpeedCrunch डेवलपर This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version यह प�रोग�राम म�क�त सॉफ़�टवेयर है; आप इसे फ�री सॉफ़�टवेयर फ़ाउंडेशन द�वारा प�रकाशित GNU जनरल पब�लिक लाइसेंस की शर�तों के अंतर�गत प�नर�वितरित और/या संशोधित कर सकते हैं; लाइसेंस के संस�करण 2 या आपकी इच�छा अन�सार उसके किसी भी बाद के संस�करण के अंतर�गत। This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. यह प�रोग�राम इस आशा में वितरित किया जाता है कि यह उपयोगी होगा, लेकिन बिना किसी वारंटी के; यहा� तक कि व�यापारयोग�यता या किसी विशेष उद�देश�य के लि� उपय�क�तता की निहित वारंटी के बिना भी। अधिक विवरण के लि� GNU जनरल पब�लिक लाइसेंस देखें। Close बंद करें BitFieldWidget Reset bits to zero बिट�स को शून�य पर रीसेट करें Invert bits बिट�स उलटें Shift bits left बिट�स को बा�� शिफ�ट करें Shift bits right बिट�स को दा�� शिफ�ट करें Book Index सूची Algebra बीजगणित Quadratic Equation द�विघात समीकरण Logarithmic Base Conversion लघ�गणकीय आधार रूपांतरण Geometry ज�यामिति Circle वृत�त Sector वृत�तखंड Sphere गोला Cube घन Cone शंक� Cylinder बेलन Electronics इलेक�ट�रॉनिक�स Ohm's Law ओम का नियम Power शक�ति Reactance रि�क�टैंस Resonance अन�नाद Radio Frequency रेडियो आवृत�ति Antennas �ंटेना Characteristic Impedance (coax) विशिष�ट प�रतिबाधा (को�क�स) Velocity of Propagation (coax) प�रसार वेग (को�क�स) Standing Wave Ratio & Return Loss स�थिर तरंग अन�पात और रिटर�न लॉस Free Space Wavelength म�क�त अंतरिक�ष तरंगदैर�घ�य resistance प�रतिरोध voltage वोल�टेज current धारा power शक�ति inductive reactance प�रेरकीय रि�क�टैंस capacitive reactance धारिता रि�क�टैंस inductance प�रेरकत�व capacitance धारिता frequency आवृत�ति resonance frequency अन�नाद आवृत�ति area क�षेत�रफल perimeter परिमाप diameter व�यास radius त�रिज�या volume आयतन surface area पृष�ठीय क�षेत�रफल height ऊ�चाई slant height तिर�यक ऊ�चाई face diagonal फलक विकर�ण space diagonal अंतरिक�ष विकर�ण edge length भ�जा की लंबाई arc length चाप लंबाई central angle (degrees) केंद�रीय कोण (डिग�री) dielectric constant डाइइलेक�ट�रिक स�थिरांक outer conductor's inner diameter बाहरी चालक का आंतरिक व�यास inner conductor's outer diameter भीतरी चालक का बाहरी व�यास speed of light प�रकाश की गति input power इनप�ट शक�ति reflected power परावर�तित शक�ति transmitted power प�रेषित शक�ति return loss रिटर�न लॉस reflection coefficient परावर�तन ग�णांक standing wave ratio स�थिर तरंग अन�पात normalized impedance सामान�यीकृत प�रतिबाधा frequency (Hz) आवृत�ति (Hz) BookDock Formula Book सूत�र प�स�तक ConstantCompletion Search constants स�थिरांक खोजें No match found कोई मेल नहीं मिला Constants Mathematics गणित Physics (CODATA 2022) भौतिकी (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) रसायन विज�ञान (IUPAC - CIAAW 2021) Uncategorized अवर�गीकृत Universal सार�वत�रिक Physicochemical भौतिक-रासायनिक Atomic & Nuclear — General परमाण� और नाभिकीय — सामान�य Atomic & Nuclear — Electroweak परमाण� और नाभिकीय — विद�य�त-द�र�बल Atomic & Nuclear — Electron परमाण� और नाभिकीय — इलेक�ट�रॉन Atomic & Nuclear — Muon परमाण� और नाभिकीय — म�यूऑन Atomic & Nuclear — Tau परमाण� और नाभिकीय — टाऊ Atomic & Nuclear — Proton परमाण� और नाभिकीय — प�रोटॉन Atomic & Nuclear — Neutron परमाण� और नाभिकीय — न�यूट�रॉन Atomic & Nuclear — Deuteron परमाण� और नाभिकीय — ड�यूटेरॉन Atomic & Nuclear — Triton परमाण� और नाभिकीय — ट�राइटॉन Atomic & Nuclear — Helion परमाण� और नाभिकीय — हीलियन Atomic & Nuclear — Alpha particle परमाण� और नाभिकीय — अल�फ़ा कण Atomic & Nuclear — Atomic units परमाण� और नाभिकीय — परमाण� इकाइया� Atomic & Nuclear — Energy conversion relationships परमाण� और नाभिकीय — ऊर�जा रूपांतरण संबंध Atomic & Nuclear — X-ray units परमाण� और नाभिकीय — �क�स-रे इकाइया� Atomic & Nuclear — Magnetic shielding corrections परमाण� और नाभिकीय — च�ंबकीय शील�डिंग स�धार Masses द�रव�यमान Lifetimes आय� Molar Masses मोलर द�रव�यमान Electronegativity विद�य�तऋणात�मकता Ionization Energy आयनीकरण ऊर�जा Nominal Constants (IAU 2015) नाममात�र नियतांक (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) वर�तमान सर�वोत�तम अन�मान (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) अभिलाक�षणिक प�रतिबाधा of vacuum (Z₀) reduced Planck constant (�) लघ�कृत प�लांक नियतांक (�) vacuum electric permittivity (ϵ₀) निर�वात वैद�य�त पारगम�यता (ϵ₀) Newtonian constant of gravitation (G) न�यूटनीय ग�र�त�वाकर�षण नियतांक (G) vacuum magnetic permeability (μ₀) निर�वात च�ंबकीय पारगम�यता (μ₀) Planck constant (h) प�लांक नियतांक (h) speed of light in vacuum (c) vacuum में प�रकाश की चाल (c) standard acceleration of gravity (gₙ) ग�र�त�व का मानक त�वरण (gₙ) Newtonian constant of gravitation over h-bar c न�यूटनीय ग�र�त�वाकर�षण नियतांक / h-bar c Planck length प�लांक लंबाई Planck constant in eV/Hz (h) eV/Hz में प�लांक नियतांक (h) Planck mass प�लांक द�रव�यमान Planck mass energy equivalent in GeV GeV में प�लांक द�रव�यमान ऊर�जा समत�ल�य Planck temperature प�लांक तापमान Planck time प�लांक समय reduced Planck constant in eV·s (�) eV·s में लघ�कृत प�लांक नियतांक (�) reduced Planck constant times c in MeV·fm MeV·fm में लघ�कृत प�लांक नियतांक × c Bohr magneton बोर मैग�नेटॉन conductance quantum (G₀) चालकता क�वांटम (G₀) Coulomb constant (kₑ) कूलॉम नियतांक (kₑ) elementary charge (e) मूल आवेश (e) elementary charge over h-bar मूल आवेश / h-bar conventional value of Josephson constant जोसेफसन नियतांक का पारंपरिक मान Josephson constant जोसेफसन नियतांक conventional value of ampere-90 ampere-90 का पारंपरिक मान conventional value of coulomb-90 coulomb-90 का पारंपरिक मान conventional value of farad-90 farad-90 का पारंपरिक मान conventional value of henry-90 henry-90 का पारंपरिक मान conventional value of ohm-90 ohm-90 का पारंपरिक मान conventional value of volt-90 volt-90 का पारंपरिक मान conventional value of watt-90 watt-90 का पारंपरिक मान magnetic flux quantum (Φ₀) च�ंबकीय फ�लक�स क�वांटम (Φ₀) nuclear magneton नाभिकीय मैग�नेटॉन inverse of conductance quantum चालकता क�वांटम का प�रतिलोम conventional value of von Klitzing constant वॉन क�लिट�ज़िंग नियतांक का पारंपरिक मान von Klitzing constant वॉन क�लिट�ज़िंग नियतांक atomic unit of magnetic dipole moment च�ंबकीय द�विध�र�व आघूर�ण की परमाण� इकाई atomic unit of magnetic flux density magnetic flux density की परमाण� इकाई Bohr magneton in eV/T eV/T में बोर मैग�नेटॉन Bohr magneton in Hz/T Hz/T में बोर मैग�नेटॉन Bohr magneton in inverse meter per tesla inverse meter per tesla में बोर मैग�नेटॉन Bohr magneton in K/T K/T में बोर मैग�नेटॉन nuclear magneton in eV/T eV/T में नाभिकीय मैग�नेटॉन nuclear magneton in inverse meter per tesla inverse meter per tesla में नाभिकीय मैग�नेटॉन nuclear magneton in K/T K/T में नाभिकीय मैग�नेटॉन nuclear magneton in MHz/T MHz/T में नाभिकीय मैग�नेटॉन Bohr radius (a₀) बोर त�रिज�या (a₀) fine-structure constant (α) सूक�ष�म-संरचना नियतांक (α) Hartree energy (Eₕ) हार�ट�री ऊर�जा (Eₕ) Hartree energy in eV eV में हार�ट�री ऊर�जा quantum of circulation परिसंचरण क�वांटम quantum of circulation times 2 परिसंचरण क�वांटम × 2 Rydberg constant (R∞) राइडबर�ग नियतांक (R∞) atomic mass unit-hartree relationship परमाण� द�रव�यमान इकाई-हार�ट�री संबंध atomic mass unit-hertz relationship परमाण� द�रव�यमान इकाई-हर�ट�ज संबंध atomic mass unit-inverse meter relationship परमाण� द�रव�यमान इकाई-प�रतिलोम मीटर संबंध atomic mass unit-joule relationship परमाण� द�रव�यमान इकाई-जूल संबंध atomic mass unit-kelvin relationship परमाण� द�रव�यमान इकाई-केल�विन संबंध atomic mass unit-kilogram relationship परमाण� द�रव�यमान इकाई-किलोग�राम संबंध atomic unit of 1st hyperpolarizability 1st hyperध�र�वीयizability की परमाण� इकाई atomic unit of 2nd hyperpolarizability 2nd hyperध�र�वीयizability की परमाण� इकाई atomic unit of charge (e) आवेश (e) की परमाण� इकाई atomic unit of charge density आवेश घनत�व की परमाण� इकाई atomic unit of current धारा की परमाण� इकाई atomic unit of electric dipole moment वैद�य�त द�विध�र�व आघूर�ण की परमाण� इकाई atomic unit of electric field वैद�य�त क�षेत�र की परमाण� इकाई atomic unit of electric field gradient वैद�य�त क�षेत�र प�रवणता की परमाण� इकाई atomic unit of electric polarizability वैद�य�त ध�र�वणीयता की परमाण� इकाई atomic unit of electric potential वैद�य�त विभव की परमाण� इकाई atomic unit of electric quadrupole moment वैद�य�त चत�र�ध�र�व आघूर�ण की परमाण� इकाई atomic unit of action क�रिया की परमाण� इकाई atomic unit of energy ऊर�जा की परमाण� इकाई atomic unit of force बल की परमाण� इकाई atomic unit of length लंबाई की परमाण� इकाई hertz-atomic mass unit relationship हर�ट�ज-परमाण� द�रव�यमान इकाई संबंध hertz-electron volt relationship हर�ट�ज-इलेक�ट�रॉन वोल�ट संबंध hertz-hartree relationship हर�ट�ज-हार�ट�री संबंध hertz-inverse meter relationship हर�ट�ज-प�रतिलोम मीटर संबंध hertz-joule relationship हर�ट�ज-जूल संबंध hertz-kelvin relationship हर�ट�ज-केल�विन संबंध hertz-kilogram relationship हर�ट�ज-किलोग�राम संबंध hyperfine transition frequency of Cs-133 Cs-133 की हाइपरफाइन संक�रमण आवृत�ति inverse fine-structure constant (α�¹) inverse सूक�ष�म-संरचना नियतांक (α�¹) inverse meter-atomic mass unit relationship प�रतिलोम मीटर-परमाण� द�रव�यमान इकाई संबंध inverse meter-electron volt relationship प�रतिलोम मीटर-इलेक�ट�रॉन वोल�ट संबंध inverse meter-hartree relationship प�रतिलोम मीटर-हार�ट�री संबंध inverse meter-hertz relationship प�रतिलोम मीटर-हर�ट�ज संबंध inverse meter-joule relationship प�रतिलोम मीटर-जूल संबंध inverse meter-kelvin relationship प�रतिलोम मीटर-केल�विन संबंध inverse meter-kilogram relationship प�रतिलोम मीटर-किलोग�राम संबंध joule-atomic mass unit relationship जूल-परमाण� द�रव�यमान इकाई संबंध joule-electron volt relationship जूल-इलेक�ट�रॉन वोल�ट संबंध joule-hertz relationship जूल-हर�ट�ज संबंध joule-hartree relationship जूल-हार�ट�री संबंध joule-inverse meter relationship जूल-प�रतिलोम मीटर संबंध joule-kelvin relationship जूल-केल�विन संबंध joule-kilogram relationship जूल-किलोग�राम संबंध kelvin-atomic mass unit relationship केल�विन-परमाण� द�रव�यमान इकाई संबंध kelvin-electron volt relationship केल�विन-इलेक�ट�रॉन वोल�ट संबंध kelvin-hertz relationship केल�विन-हर�ट�ज संबंध kelvin-hartree relationship केल�विन-हार�ट�री संबंध kelvin-inverse meter relationship केल�विन-प�रतिलोम मीटर संबंध kelvin-joule relationship केल�विन-जूल संबंध kelvin-kilogram relationship केल�विन-किलोग�राम संबंध kilogram-atomic mass unit relationship किलोग�राम-परमाण� द�रव�यमान इकाई संबंध kilogram-electron volt relationship किलोग�राम-इलेक�ट�रॉन वोल�ट संबंध kilogram-hertz relationship किलोग�राम-हर�ट�ज संबंध kilogram-hartree relationship किलोग�राम-हार�ट�री संबंध kilogram-inverse meter relationship किलोग�राम-प�रतिलोम मीटर संबंध kilogram-joule relationship किलोग�राम-जूल संबंध kilogram-kelvin relationship किलोग�राम-केल�विन संबंध lattice parameter of silicon (a) lattice पैरामीटर of सिलिकॉन (a) luminous efficacy प�रकाशीय प�रभावकारिता natural unit of energy ऊर�जा की प�राकृतिक इकाई natural unit of energy in MeV MeV में ऊर�जा की प�राकृतिक इकाई natural unit of action (�) क�रिया (�) की प�राकृतिक इकाई natural unit of action in eV·s eV·s में क�रिया की प�राकृतिक इकाई natural unit of length लंबाई की प�राकृतिक इकाई natural unit of mass द�रव�यमान की प�राकृतिक इकाई natural unit of momentum संवेग की प�राकृतिक इकाई natural unit of momentum in MeV/c MeV/c में संवेग की प�राकृतिक इकाई natural unit of time समय की प�राकृतिक इकाई natural unit of velocity वेग की प�राकृतिक इकाई Rydberg constant times c in Hz Hz में राइडबर�ग नियतांक × c Rydberg constant times hc in eV eV में राइडबर�ग नियतांक × hc Rydberg constant times hc in J J में राइडबर�ग नियतांक × hc Fermi coupling constant Fermi coupling नियतांक weak mixing angle कमज़ोर मिश�रण कोण W to Z mass ratio W और Z द�रव�यमान का अन�पात Thomson cross section (σₑ) थॉमसन अन�प�रस�थ काट (σₑ) electron mass (mₑ) इलेक�ट�रॉन द�रव�यमान (mₑ) electron mass in u u में इलेक�ट�रॉन द�रव�यमान electron mass energy equivalent (mₑ·c²) इलेक�ट�रॉन द�रव�यमान ऊर�जा समत�ल�य (mₑ·c²) electron mass energy equivalent in MeV MeV में इलेक�ट�रॉन द�रव�यमान ऊर�जा समत�ल�य reduced Compton wavelength लघ�कृत कॉम�पटन तरंगदैर�घ�य classical electron radius (rₑ) शास�त�रीय इलेक�ट�रॉन त�रिज�या (rₑ) electron charge to mass quotient इलेक�ट�रॉन आवेश-द�रव�यमान भागफल electron-deuteron magnetic moment ratio इलेक�ट�रॉन-ड�यूटेरॉन च�ंबकीय आघूर�ण अन�पात electron-deuteron mass ratio इलेक�ट�रॉन-ड�यूटेरॉन द�रव�यमान अन�पात electron g factor (gₑ) इलेक�ट�रॉन g-कारक (gₑ) electron gyromagnetic ratio (γₑ) इलेक�ट�रॉन जाइरोमैग�नेटिक अन�पात (γₑ) electron gyromagnetic ratio in MHz/T MHz/T में इलेक�ट�रॉन जाइरोमैग�नेटिक अन�पात electron-helion mass ratio इलेक�ट�रॉन-हीलियन द�रव�यमान अन�पात electron magnetic moment (μₑ) इलेक�ट�रॉन च�ंबकीय आघूर�ण (μₑ) electron magnetic moment anomaly (aₑ) इलेक�ट�रॉन च�ंबकीय आघूर�ण विसंगति (aₑ) electron magnetic moment to Bohr magneton ratio इलेक�ट�रॉन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात electron magnetic moment to nuclear magneton ratio इलेक�ट�रॉन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात electron molar mass (Mₑ) इलेक�ट�रॉन मोलर द�रव�यमान (Mₑ) electron-muon magnetic moment ratio इलेक�ट�रॉन-म�यूऑन च�ंबकीय आघूर�ण अन�पात electron-muon mass ratio इलेक�ट�रॉन-म�यूऑन द�रव�यमान अन�पात electron-neutron magnetic moment ratio इलेक�ट�रॉन-न�यूट�रॉन च�ंबकीय आघूर�ण अन�पात electron-neutron mass ratio इलेक�ट�रॉन-न�यूट�रॉन द�रव�यमान अन�पात electron-proton magnetic moment ratio इलेक�ट�रॉन-प�रोटॉन च�ंबकीय आघूर�ण अन�पात electron-proton mass ratio इलेक�ट�रॉन-प�रोटॉन द�रव�यमान अन�पात electron relative atomic mass (Ar(e)) इलेक�ट�रॉन सापेक�ष परमाण� द�रव�यमान (Ar(e)) electron-tau mass ratio इलेक�ट�रॉन-टाऊ द�रव�यमान अन�पात electron to alpha particle mass ratio इलेक�ट�रॉन और अल�फ़ा कण द�रव�यमान का अन�पात electron to shielded helion magnetic moment ratio इलेक�ट�रॉन और शील�डित हीलियन च�ंबकीय आघूर�ण का अन�पात electron to shielded proton magnetic moment ratio इलेक�ट�रॉन और शील�डित प�रोटॉन च�ंबकीय आघूर�ण का अन�पात electron-triton mass ratio इलेक�ट�रॉन-ट�राइटॉन द�रव�यमान अन�पात electron volt-atomic mass unit relationship इलेक�ट�रॉन वोल�ट-परमाण� द�रव�यमान इकाई संबंध electron volt-hartree relationship इलेक�ट�रॉन वोल�ट-हार�ट�री संबंध electron volt-hertz relationship इलेक�ट�रॉन वोल�ट-हर�ट�ज संबंध electron volt-inverse meter relationship इलेक�ट�रॉन वोल�ट-प�रतिलोम मीटर संबंध electron volt-joule relationship इलेक�ट�रॉन वोल�ट-जूल संबंध electron volt-kelvin relationship इलेक�ट�रॉन वोल�ट-केल�विन संबंध electron volt-kilogram relationship इलेक�ट�रॉन वोल�ट-किलोग�राम संबंध hartree-atomic mass unit relationship हार�ट�री-परमाण� द�रव�यमान इकाई संबंध hartree-electron volt relationship हार�ट�री-इलेक�ट�रॉन वोल�ट संबंध muon Compton wavelength म�यूऑन कॉम�पटन तरंगदैर�घ�य muon-electron mass ratio म�यूऑन-इलेक�ट�रॉन द�रव�यमान अन�पात muon g factor म�यूऑन g-कारक muon magnetic moment म�यूऑन च�ंबकीय आघूर�ण muon magnetic moment anomaly म�यूऑन च�ंबकीय आघूर�ण विसंगति muon magnetic moment to Bohr magneton ratio म�यूऑन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात muon magnetic moment to nuclear magneton ratio म�यूऑन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात muon mass म�यूऑन द�रव�यमान muon mass energy equivalent म�यूऑन द�रव�यमान ऊर�जा समत�ल�य muon mass energy equivalent in MeV MeV में म�यूऑन द�रव�यमान ऊर�जा समत�ल�य muon mass in u u में म�यूऑन द�रव�यमान muon molar mass म�यूऑन मोलर द�रव�यमान muon-neutron mass ratio म�यूऑन-न�यूट�रॉन द�रव�यमान अन�पात muon-proton magnetic moment ratio म�यूऑन-प�रोटॉन च�ंबकीय आघूर�ण अन�पात muon-proton mass ratio म�यूऑन-प�रोटॉन द�रव�यमान अन�पात muon-tau mass ratio म�यूऑन-टाऊ द�रव�यमान अन�पात reduced muon Compton wavelength लघ�कृत म�यूऑन कॉम�पटन तरंगदैर�घ�य reduced tau Compton wavelength लघ�कृत टाऊ कॉम�पटन तरंगदैर�घ�य tau Compton wavelength टाऊ कॉम�पटन तरंगदैर�घ�य tau-electron mass ratio टाऊ-इलेक�ट�रॉन द�रव�यमान अन�पात tau mass टाऊ द�रव�यमान tau mass energy equivalent टाऊ द�रव�यमान ऊर�जा समत�ल�य tau mass in u u में टाऊ द�रव�यमान tau molar mass टाऊ मोलर द�रव�यमान tau-muon mass ratio टाऊ-म�यूऑन द�रव�यमान अन�पात tau-neutron mass ratio टाऊ-न�यूट�रॉन द�रव�यमान अन�पात tau-proton mass ratio टाऊ-प�रोटॉन द�रव�यमान अन�पात proton charge to mass quotient प�रोटॉन आवेश-द�रव�यमान भागफल proton Compton wavelength प�रोटॉन कॉम�पटन तरंगदैर�घ�य proton-electron mass ratio प�रोटॉन-इलेक�ट�रॉन द�रव�यमान अन�पात proton g factor (gₚ) प�रोटॉन g-कारक (gₚ) proton gyromagnetic ratio (γₚ) प�रोटॉन जाइरोमैग�नेटिक अन�पात (γₚ) proton gyromagnetic ratio in MHz/T MHz/T में प�रोटॉन जाइरोमैग�नेटिक अन�पात proton magnetic moment (μₚ) प�रोटॉन च�ंबकीय आघूर�ण (μₚ) proton magnetic moment to Bohr magneton ratio प�रोटॉन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात proton magnetic moment to nuclear magneton ratio प�रोटॉन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात proton magnetic shielding correction प�रोटॉन magnetic शील�डिंग स�धार proton mass (mₚ) प�रोटॉन द�रव�यमान (mₚ) proton mass energy equivalent प�रोटॉन द�रव�यमान ऊर�जा समत�ल�य proton mass energy equivalent in MeV MeV में प�रोटॉन द�रव�यमान ऊर�जा समत�ल�य proton mass in u u में प�रोटॉन द�रव�यमान proton molar mass (Mₚ) प�रोटॉन मोलर द�रव�यमान (Mₚ) proton-muon mass ratio प�रोटॉन-म�यूऑन द�रव�यमान अन�पात proton-neutron magnetic moment ratio प�रोटॉन-न�यूट�रॉन च�ंबकीय आघूर�ण अन�पात proton-neutron mass ratio प�रोटॉन-न�यूट�रॉन द�रव�यमान अन�पात proton relative atomic mass (Ar(p)) प�रोटॉन सापेक�ष परमाण� द�रव�यमान (Ar(p)) proton rms charge radius प�रोटॉन RMS आवेश त�रिज�या proton-tau mass ratio प�रोटॉन-टाऊ द�रव�यमान अन�पात reduced proton Compton wavelength लघ�कृत प�रोटॉन कॉम�पटन तरंगदैर�घ�य shielded proton gyromagnetic ratio शील�डित प�रोटॉन जाइरोमैग�नेटिक अन�पात shielded proton gyromagnetic ratio in MHz/T MHz/T में शील�डित प�रोटॉन जाइरोमैग�नेटिक अन�पात shielded proton magnetic moment शील�डित प�रोटॉन च�ंबकीय आघूर�ण shielded proton magnetic moment to Bohr magneton ratio शील�डित प�रोटॉन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात shielded proton magnetic moment to nuclear magneton ratio शील�डित प�रोटॉन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात neutron Compton wavelength न�यूट�रॉन कॉम�पटन तरंगदैर�घ�य neutron-electron magnetic moment ratio न�यूट�रॉन-इलेक�ट�रॉन च�ंबकीय आघूर�ण अन�पात neutron-electron mass ratio न�यूट�रॉन-इलेक�ट�रॉन द�रव�यमान अन�पात neutron g factor (gₙ) न�यूट�रॉन g-कारक (gₙ) neutron gyromagnetic ratio (γₙ) न�यूट�रॉन जाइरोमैग�नेटिक अन�पात (γₙ) neutron gyromagnetic ratio in MHz/T MHz/T में न�यूट�रॉन जाइरोमैग�नेटिक अन�पात neutron magnetic moment (μₙ) न�यूट�रॉन च�ंबकीय आघूर�ण (μₙ) neutron magnetic moment to Bohr magneton ratio न�यूट�रॉन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात neutron magnetic moment to nuclear magneton ratio न�यूट�रॉन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात neutron mass (mₙ) न�यूट�रॉन द�रव�यमान (mₙ) neutron mass energy equivalent न�यूट�रॉन द�रव�यमान ऊर�जा समत�ल�य neutron mass energy equivalent in MeV MeV में न�यूट�रॉन द�रव�यमान ऊर�जा समत�ल�य neutron mass in u u में न�यूट�रॉन द�रव�यमान neutron molar mass (Mₙ) न�यूट�रॉन मोलर द�रव�यमान (Mₙ) neutron-muon mass ratio न�यूट�रॉन-म�यूऑन द�रव�यमान अन�पात neutron-proton magnetic moment ratio न�यूट�रॉन-प�रोटॉन च�ंबकीय आघूर�ण अन�पात neutron-proton mass difference न�यूट�रॉन-प�रोटॉन द�रव�यमान अंतर neutron-proton mass difference energy equivalent न�यूट�रॉन-प�रोटॉन द�रव�यमान अंतर ऊर�जा समत�ल�य neutron-proton mass difference energy equivalent in MeV MeV में न�यूट�रॉन-प�रोटॉन द�रव�यमान अंतर ऊर�जा समत�ल�य neutron-proton mass difference in u u में न�यूट�रॉन-प�रोटॉन द�रव�यमान अंतर neutron-proton mass ratio न�यूट�रॉन-प�रोटॉन द�रव�यमान अन�पात neutron relative atomic mass (Ar(n)) न�यूट�रॉन सापेक�ष परमाण� द�रव�यमान (Ar(n)) neutron-tau mass ratio न�यूट�रॉन-टाऊ द�रव�यमान अन�पात neutron to shielded proton magnetic moment ratio न�यूट�रॉन और शील�डित प�रोटॉन च�ंबकीय आघूर�ण का अन�पात reduced neutron Compton wavelength लघ�कृत न�यूट�रॉन कॉम�पटन तरंगदैर�घ�य deuteron-electron magnetic moment ratio ड�यूटेरॉन-इलेक�ट�रॉन च�ंबकीय आघूर�ण अन�पात deuteron-electron mass ratio ड�यूटेरॉन-इलेक�ट�रॉन द�रव�यमान अन�पात deuteron g factor ड�यूटेरॉन g-कारक deuteron magnetic moment ड�यूटेरॉन च�ंबकीय आघूर�ण deuteron magnetic moment to Bohr magneton ratio ड�यूटेरॉन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात deuteron magnetic moment to nuclear magneton ratio ड�यूटेरॉन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात deuteron mass ड�यूटेरॉन द�रव�यमान deuteron mass energy equivalent ड�यूटेरॉन द�रव�यमान ऊर�जा समत�ल�य deuteron mass energy equivalent in MeV MeV में ड�यूटेरॉन द�रव�यमान ऊर�जा समत�ल�य deuteron mass in u u में ड�यूटेरॉन द�रव�यमान deuteron molar mass ड�यूटेरॉन मोलर द�रव�यमान deuteron-neutron magnetic moment ratio ड�यूटेरॉन-न�यूट�रॉन च�ंबकीय आघूर�ण अन�पात deuteron-proton magnetic moment ratio ड�यूटेरॉन-प�रोटॉन च�ंबकीय आघूर�ण अन�पात deuteron-proton mass ratio ड�यूटेरॉन-प�रोटॉन द�रव�यमान अन�पात deuteron relative atomic mass (Ar(d)) ड�यूटेरॉन सापेक�ष परमाण� द�रव�यमान (Ar(d)) deuteron rms charge radius ड�यूटेरॉन RMS आवेश त�रिज�या triton-electron mass ratio ट�राइटॉन-इलेक�ट�रॉन द�रव�यमान अन�पात triton g factor (gₜ) ट�राइटॉन g-कारक (gₜ) triton magnetic moment (μₜ) ट�राइटॉन च�ंबकीय आघूर�ण (μₜ) triton magnetic moment to Bohr magneton ratio ट�राइटॉन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात triton magnetic moment to nuclear magneton ratio ट�राइटॉन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात triton mass (mₜ) ट�राइटॉन द�रव�यमान (mₜ) triton mass energy equivalent ट�राइटॉन द�रव�यमान ऊर�जा समत�ल�य triton mass energy equivalent in MeV MeV में ट�राइटॉन द�रव�यमान ऊर�जा समत�ल�य triton mass in u u में ट�राइटॉन द�रव�यमान triton molar mass (Mₜ) ट�राइटॉन मोलर द�रव�यमान (Mₜ) triton-proton mass ratio ट�राइटॉन-प�रोटॉन द�रव�यमान अन�पात triton relative atomic mass (Ar(t)) ट�राइटॉन सापेक�ष परमाण� द�रव�यमान (Ar(t)) triton to proton magnetic moment ratio ट�राइटॉन और प�रोटॉन च�ंबकीय आघूर�ण का अन�पात helion-electron mass ratio हीलियन-इलेक�ट�रॉन द�रव�यमान अन�पात helion g factor (gₕ) हीलियन g-कारक (gₕ) helion magnetic moment (μₕ) हीलियन च�ंबकीय आघूर�ण (μₕ) helion magnetic moment to Bohr magneton ratio हीलियन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात helion magnetic moment to nuclear magneton ratio हीलियन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात helion mass (mₕ) हीलियन द�रव�यमान (mₕ) helion mass energy equivalent हीलियन द�रव�यमान ऊर�जा समत�ल�य helion mass energy equivalent in MeV MeV में हीलियन द�रव�यमान ऊर�जा समत�ल�य helion mass in u u में हीलियन द�रव�यमान helion molar mass (Mₕ) हीलियन मोलर द�रव�यमान (Mₕ) helion-proton mass ratio हीलियन-प�रोटॉन द�रव�यमान अन�पात helion relative atomic mass (Ar(h)) हीलियन सापेक�ष परमाण� द�रव�यमान (Ar(h)) helion shielding shift हीलियन शील�डिंग शिफ�ट shielded helion gyromagnetic ratio शील�डित हीलियन जाइरोमैग�नेटिक अन�पात shielded helion gyromagnetic ratio in MHz/T MHz/T में शील�डित हीलियन जाइरोमैग�नेटिक अन�पात shielded helion magnetic moment शील�डित हीलियन च�ंबकीय आघूर�ण shielded helion magnetic moment to Bohr magneton ratio शील�डित हीलियन च�ंबकीय आघूर�ण और बोर मैग�नेटॉन का अन�पात shielded helion magnetic moment to nuclear magneton ratio शील�डित हीलियन च�ंबकीय आघूर�ण और नाभिकीय मैग�नेटॉन का अन�पात shielded helion to proton magnetic moment ratio शील�डित हीलियन और प�रोटॉन च�ंबकीय आघूर�ण का अन�पात shielded helion to shielded proton magnetic moment ratio शील�डित हीलियन और शील�डित प�रोटॉन च�ंबकीय आघूर�ण का अन�पात alpha particle mass अल�फ़ा कण द�रव�यमान alpha particle mass in u u में अल�फ़ा कण द�रव�यमान alpha particle mass energy equivalent अल�फ़ा कण द�रव�यमान ऊर�जा समत�ल�य alpha particle mass energy equivalent in MeV MeV में अल�फ़ा कण द�रव�यमान ऊर�जा समत�ल�य alpha particle-electron mass ratio अल�फ़ा कण-इलेक�ट�रॉन द�रव�यमान अन�पात alpha particle-proton mass ratio अल�फ़ा कण-प�रोटॉन द�रव�यमान अन�पात alpha particle rms charge radius अल�फ़ा कण RMS आवेश त�रिज�या alpha particle molar mass अल�फ़ा कण मोलर द�रव�यमान alpha particle relative atomic mass (Ar(α)) अल�फ़ा कण सापेक�ष परमाण� द�रव�यमान (Ar(α)) atomic mass constant (mᵤ) परमाण� द�रव�यमान नियतांक (mᵤ) Avogadro constant अवोगाद�रो नियतांक Boltzmann constant (k) बोल�ट�ज़मान नियतांक (k) Boltzmann constant in eV/K eV/K में बोल�ट�ज़मान नियतांक Boltzmann constant in Hz/K Hz/K में बोल�ट�ज़मान नियतांक Boltzmann constant in inverse meter per kelvin inverse meter per kelvin में बोल�ट�ज़मान नियतांक electron volt (eV) इलेक�ट�रॉन वोल�ट (eV) Faraday constant (F) फ़ैराडे नियतांक (F) first radiation constant (c�) प�रथम विकिरण नियतांक (c�) first radiation constant for spectral radiance वर�णक�रमीय रेडियंस के लि� प�रथम विकिरण नियतांक molar gas constant (R) मोलर गैस नियतांक (R) Loschmidt constant (n₀, 273.15 K, 100 kPa) लॉश�मिट नियतांक (n₀, 273.15 K, 100 kPa) Loschmidt constant (n₀, 273.15 K, 101.325 kPa) लॉश�मिट नियतांक (n₀, 273.15 K, 101.325 kPa) molar Planck constant मोलर प�लांक नियतांक second radiation constant (c₂) द�वितीय विकिरण नियतांक (c₂) Stefan-Boltzmann constant (σ) स�टेफ़न-बोल�ट�ज़मान नियतांक (σ) lattice spacing of ideal Si (d₂₂₀) आदर�श Si का जालक अंतराल (d₂₂₀) atomic mass constant energy equivalent परमाण� द�रव�यमान नियतांक ऊर�जा समत�ल�य atomic mass constant energy equivalent in MeV MeV में परमाण� द�रव�यमान नियतांक ऊर�जा समत�ल�य atomic mass unit-electron volt relationship परमाण� द�रव�यमान इकाई-इलेक�ट�रॉन वोल�ट संबंध molar mass constant (Mᵤ) मोलर द�रव�यमान नियतांक (Mᵤ) molar mass of carbon-12 कार�बन-12 का मोलर द�रव�यमान molar volume of ideal gas (273.15 K, 100 kPa) आदर�श गैस का मोलर आयतन (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) आदर�श गैस का मोलर आयतन (273.15 K, 101.325 kPa) molar volume of silicon सिलिकॉन का मोलर आयतन Sackur-Tetrode constant (1 K, 100 kPa) सैक�र-टेट�रोड नियतांक (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) सैक�र-टेट�रोड नियतांक (1 K, 101.325 kPa) Wien frequency displacement law constant वीन आवृत�ति विस�थापन नियम नियतांक Wien wavelength displacement law constant वीन तरंगदैर�घ�य विस�थापन नियम नियतांक standard atmosphere (atm) मानक वाय�मंडल (atm) standard-state pressure (p°) मानक-अवस�था दाब (p°) Angstrom star (Å*) आंगस�ट�रॉम स�टार (Å*) Copper x unit कॉपर x इकाई Molybdenum x unit मोलिब�डेनम x इकाई atomic unit of magnetizability च�ंबकनीयता की परमाण� इकाई atomic unit of mass (mₑ) द�रव�यमान (mₑ) की परमाण� इकाई atomic unit of momentum संवेग की परमाण� इकाई atomic unit of permittivity पारगम�यता की परमाण� इकाई atomic unit of time समय की परमाण� इकाई atomic unit of velocity वेग की परमाण� इकाई hartree-hertz relationship हार�ट�री-हर�ट�ज संबंध hartree-inverse meter relationship हार�ट�री-प�रतिलोम मीटर संबंध hartree-joule relationship हार�ट�री-जूल संबंध hartree-kelvin relationship हार�ट�री-केल�विन संबंध hartree-kilogram relationship हार�ट�री-किलोग�राम संबंध shielding difference of d and p in HD HD में शील�डिंग अंतर of d and p shielding difference of t and p in HT HT में शील�डिंग अंतर of t and p pi (π) पाई (π) Euler's number (e) यूलर संख�या (e) golden ratio (φ) स�वर�ण अन�पात (φ) Euler-Mascheroni constant (γ) यूलर-माशेरोनी नियतांक (γ) nominal solar radius नाममात�र सौर त�रिज�या nominal solar total irradiance नाममात�र सौर क�ल विकिरणता nominal solar luminosity नाममात�र सौर दीप�ति nominal solar effective temperature नाममात�र सौर प�रभावी तापमान nominal solar mass parameter नाममात�र सौर द�रव�यमान पैरामीटर nominal terrestrial equatorial radius नाममात�र स�थलीय भूमध�य त�रिज�या nominal terrestrial polar radius नाममात�र स�थलीय ध�र�वीय त�रिज�या nominal terrestrial mass parameter नाममात�र स�थलीय द�रव�यमान पैरामीटर nominal jovian equatorial radius नाममात�र बृहस�पतीय भूमध�य त�रिज�या nominal jovian polar radius नाममात�र बृहस�पतीय ध�र�वीय त�रिज�या nominal jovian mass parameter नाममात�र बृहस�पतीय द�रव�यमान पैरामीटर average value of one minus the rate of TCG relative to TCB TCB के सापेक�ष TCG की दर को �क से घटाने का औसत मान solar mass parameter (TCB-compatible) सौर द�रव�यमान पैरामीटर (TCB-compatible) solar mass parameter (TDB-compatible) सौर द�रव�यमान पैरामीटर (TDB-compatible) equatorial radius of the Earth (TT-compatible) पृथ�वी की भूमध�य त�रिज�या (TT-compatible) dynamical form factor of the Earth पृथ�वी का गतिशील रूप ग�णक time rate of change in the dynamical form factor of the Earth the dynamical form factor of the Earth में समय rate of change geocentric gravitational constant (TCB-compatible) भूकेंद�रीय ग�र�त�वाकर�षण नियतांक (TCB-compatible) geocentric gravitational constant (TT-compatible) भूकेंद�रीय ग�र�त�वाकर�षण नियतांक (TT-compatible) geocentric gravitational constant (TDB-compatible) भूकेंद�रीय ग�र�त�वाकर�षण नियतांक (TDB-compatible) potential of the geoid जियोइड का विभव nominal mean angular velocity of the Earth (TT-compatible) पृथ�वी का नाममात�र माध�य कोणीय वेग (TT-compatible) ratio mass of the Moon to the Earth चंद�रमा और पृथ�वी के द�रव�यमान का अन�पात ratio of the mass of the Sun to Mercury सूर�य और ब�ध के द�रव�यमान का अन�पात ratio of the mass of the Sun to Venus सूर�य और श�क�र के द�रव�यमान का अन�पात ratio of the mass of the Sun to Mars सूर�य और मंगल के द�रव�यमान का अन�पात ratio of the mass of the Sun to Jupiter सूर�य और बृहस�पति के द�रव�यमान का अन�पात ratio of the mass of the Sun to Saturn सूर�य और शनि के द�रव�यमान का अन�पात ratio of the mass of the Sun to Uranus सूर�य और यूरेनस के द�रव�यमान का अन�पात ratio of the mass of the Sun to Neptune सूर�य और नेपच�यून के द�रव�यमान का अन�पात ratio of the mass of the Sun to (134340) Pluto सूर�य और (134340) प�लूटो के द�रव�यमान का अन�पात ratio of the mass of the Sun to (136199) Eris सूर�य और (136199) �रिस के द�रव�यमान का अन�पात ratio of the mass of (1) Ceres to the Sun (1) सेरेस और सूर�य के द�रव�यमान का अन�पात ratio of the mass of (2) Pallas to the Sun (2) पैलस और सूर�य के द�रव�यमान का अन�पात ratio of the mass of (4) Vesta to the Sun (4) वेस�टा और सूर�य के द�रव�यमान का अन�पात mean obliquity of the ecliptic at J2000.0 J2000.0 पर क�रांतिवृत�त की माध�य तिर�यकता Electromagnetic विद�य�तच�ंबकीय Compton wavelength कॉम�पटन तरंगदैर�घ�य Astronomy खगोलशास�त�र ConstantsWidget Domain डोमेन Subdomain उपडोमेन Search खोज No match found कोई मेल नहीं मिला Name नाम Value मान Unit इकाई All सभी CustomKeypadDialog Custom Keypad कस�टम कीपैड Rows: पंक�तिया�: Columns: स�तंभ: Copy preset: प�रीसेट कॉपी करें: Basic मूल Scientific (wide) वैज�ञानिक (चौड़ा) Scientific (narrow) वैज�ञानिक (संकरी) Apply लागू करें Row पंक�ति Column स�तंभ Label लेबल Behavior व�यवहार Text पाठ DiagnosticsDialog App Diagnostics �प निदान Copy to Clipboard क�लिपबोर�ड पर कॉपी करें Editor Unit इकाई User unit उपयोगकर�ता इकाई User function उपयोगकर�ता फलन Argument तर�क Current result:<br/>%1 वर�तमान परिणाम:<br/>%1 Selection result:<br/>%1 चयन परिणाम:<br/>%1 Selection result: n/a चयन परिणाम: उपलब�ध नहीं Selection result: %1 चयन परिणाम: %1 second सेकंड metre मीटर kilogram किलोग�राम mole मोल radian रेडियन steradian स�टेरेडियन degree Celsius डिग�री सेल�सियस cubic metre घन मीटर cubic millimetre घन मिलीमीटर cubic centimetre घन सेंटीमीटर cubic decimetre घन डेसीमीटर cubic kilometre घन किलोमीटर square millimetre वर�ग मिलीमीटर square kilometre वर�ग किलोमीटर square metre वर�ग मीटर minute मिनट hour घंटा day दिन astronomical unit खगोलीय इकाई degree डिग�री arcminute चापमिनट arcsecond चापसेकंड milliarcsecond मिलिचापसेकंड microarcsecond माइक�रोचापसेकंड hectare हेक�टेयर litre लीटर tonne टन Dalton डाल�टन electronvolt इलेक�ट�रॉनवोल�ट Angstrom आंगस�ट�रॉम atmosphere वाय�मंडल atomic mass unit परमाण� द�रव�यमान इकाई British thermal unit ब�रिटिश तापीय इकाई calorie कैलोरी carat कैरेट cup कप cup (Imperial) कप (इंपीरियल) cup (Japanese) कप (जापानी) cup (US) कप (US) degree Fahrenheit डिग�री फ़ारेनहाइट fathom फैदम fluid ounce (Imperial) द�रव औंस (इंपीरियल) fluid ounce (US) द�रव औंस (US) fluid dram (Imperial) द�रव ड�राम (इंपीरियल) fluid dram (US) द�रव ड�राम (US) foot फ़�ट square foot वर�ग फ़�ट cubic foot घन फ़�ट gallon (Imperial) गैलन (इंपीरियल) gallon (US) गैलन (US) gill (Imperial) गिल (इंपीरियल) gill (US) गिल (US) gradian ग�रेडियन grain ग�रेन gram ग�राम Hartley हार�टले Hartree energy unit हार�ट�री ऊर�जा इकाई horsepower अश�वशक�ति inch इंच square inch वर�ग इंच cubic inch घन इंच karat कैरट knot नॉट lightminute प�रकाश-मिनट lightsecond प�रकाश-सेकंड lightyear प�रकाश-वर�ष long ton लॉन�ग टन mile मील square mile वर�ग मील cubic mile घन मील mile per hour मील प�रति घंटा kilometre per hour किलोमीटर प�रति घंटा nautical mile सम�द�री मील ounce औंस parsec पारसेक pint (Imperial) पाइंट (इंपीरियल) pint (US) पाइंट (US) pound पाउंड pounds per square inch पाउंड प�रति वर�ग इंच quart (Imperial) क�वार�ट (इंपीरियल) quart (US) क�वार�ट (US) oil barrel तेल बैरल beer barrel (US) बीयर बैरल (US) square yard वर�ग गज cubic yard घन गज short ton शॉर�ट टन tablespoon बड़ा चम�मच tablespoon (Australian) बड़ा चम�मच (ऑस�ट�रेलियाई) tablespoon (Imperial) बड़ा चम�मच (इंपीरियल) tablespoon (US) बड़ा चम�मच (US) dessert spoon डेज़र�ट चम�मच teaspoon छोटा चम�मच teaspoon (Imperial) छोटा चम�मच (इंपीरियल) teaspoon (US) छोटा चम�मच (US) turn टर�न revolution परिक�रमण revolution per minute परिक�रमण प�रति मिनट week सप�ताह kilowatt hour किलोवाट घंटा millimetre of mercury पारे का मिलीमीटर yard गज Julian century जूलियन शताब�दी Julian year जूलियन वर�ष sidereal year नाक�षत�र वर�ष tropical year उष�णकटिबंधीय वर�ष Evaluator cannot operate on a NaN NaN पर क�रिया नहीं की जा सकती underflow - tiny result is out of SpeedCrunch's number range अंडरफ़�लो - बह�त छोटा परिणाम SpeedCrunch की संख�या सीमा से बाहर है overflow - huge result is out of SpeedCrunch's number range ओवरफ़�लो - बह�त बड़ा परिणाम SpeedCrunch की संख�या सीमा से बाहर है division by zero शून�य से भाग overflow - logic result exceeds maximum of 256 bits ओवरफ़�लो - तार�किक परिणाम 256 बिट की अधिकतम सीमा से अधिक है overflow - integer result exceeds maximum limit for integers ओवरफ़�लो - पूर�णांक परिणाम पूर�णांकों की अधिकतम सीमा से अधिक है too time consuming - computation was rejected अत�यधिक समय लेने वाला - गणना अस�वीकार कर दी गई dimension mismatch - quantities with different dimensions cannot be compared, added, etc. आयाम असंगति - अलग-अलग आयाम वाली राशियों की त�लना, जोड़ आदि नहीं किया जा सकता invalid dimension - operation might require dimensionless arguments अमान�य आयाम - क�रिया के लि� आयामरहित तर�क आवश�यक हो सकते हैं operation is not defined for these arguments इन तर�कों के लि� क�रिया परिभाषित नहीं है Computation aborted - encountered numerical instability गणना रोकी गई - संख�यात�मक अस�थिरता मिली wrong number of arguments तर�कों की संख�या गलत है does not take NaN as an argument NaN को तर�क के रूप में स�वीकार नहीं करता result out of range परिणाम सीमा से बाहर है undefined for argument domain तर�क डोमेन के लि� अपरिभाषित computation too expensive गणना बह�त महंगी है invalid dimension - function might require dimensionless arguments अमान�य आयाम - फलन के लि� आयामरहित तर�क आवश�यक हो सकते हैं internal error, please report a bug आंतरिक त�र�टि, कृपया बग की रिपोर�ट करें error त�र�टि invalid expression अमान�य व�यंजक syntax error वाक�यविन�यास त�र�टि conversion target must be a unit रूपांतरण लक�ष�य �क इकाई होना चाहि� unit must not be zero इकाई शून�य नहीं होनी चाहि� Conversion failed - dimension mismatch रूपांतरण विफल - आयाम असंगति unknown function or variable अज�ञात फलन या चर unknown unit अज�ञात इकाई recursion not supported प�नरावर�तन समर�थित नहीं है %1 is a reserved name, please choose another %1 आरक�षित नाम है, कृपया कोई दूसरा च�नें %1 is a global user definition and cannot be overridden in this session. %1 �क वैश�विक उपयोगकर�ता परिभाषा है और इस सत�र में अधिलेखित नहीं की जा सकती। %1 is a variable name, please choose another or delete the variable %1 �क चर नाम है, कृपया कोई दूसरा च�नें या चर हटा�� argument %1 is used more than once तर�क %1 �क से अधिक बार उपयोग ह�आ है %1 is a built-in unit name, please choose another %1 �क अंतर�निहित इकाई नाम है, कृपया कोई दूसरा च�नें %1 is a user function name, please choose another or delete the function %1 �क उपयोगकर�ता फलन का नाम है, कृपया कोई दूसरा च�नें या फलन हटा�� FunctionRepo max; trials; probability अधिकतम; परीक�षण; प�रायिकता trials; probability परीक�षण; प�रायिकता hits; trials; probability सफलता��; परीक�षण; प�रायिकता unix_timestamp; x hours offset to GMT unix_timestamp; GMT से x घंटे का अंतर max; total; hits; trials अधिकतम; क�ल; सफलता��; परीक�षण total; hits; trials क�ल; सफलता��; परीक�षण count; total; hits; trials गणना; क�ल; सफलता��; परीक�षण dividend; divisor भाज�य; भाजक x; exponent_bits; significand_bits [; exponent_bias] x; घातांक बिट; सार�थकांश बिट [; घातांक बायस] base; x आधार; x value; modulo मान; मॉड�यूलो base; exponent; modulo आधार; घातांक; मॉड�यूलो events; average_events घटना��; औसत_घटना�� average_events औसत_घटना�� x [; precision] x [; परिश�द�धता] Absolute Value परम मान Absolute Deviation परम विचलन Arc Cosine आर�क कोसाइन Logical AND तार�किक AND Area Hyperbolic Cosine प�रतिलोम अतिपरवलयिक कोसाइन Area Hyperbolic Sine प�रतिलोम अतिपरवलयिक साइन Area Hyperbolic Tangent प�रतिलोम अतिपरवलयिक टैन�जेंट Arc Sine आर�क साइन Arc Tangent आर�क टैन�जेंट Arc Tangent with two Arguments दो तर�कों वाला आर�क टैन�जेंट Average (Arithmetic Mean) औसत (अंकगणितीय माध�य) Convert to Binary Representation बाइनरी निरूपण में बदलें Binomial Cumulative Distribution Function द�विपद संचयी वितरण फलन Binomial Distribution Mean द�विपद वितरण माध�य Binomial Probability Mass Function द�विपद प�रायिकता द�रव�यमान फलन Binomial Distribution Variance द�विपद वितरण प�रसरण Cube Root घनमूल Complex Conjugate समिश�र सहय�ग�म Cosine कोसाइन Hyperbolic Cosine अतिपरवलयिक कोसाइन Cotangent कोटैन�जेंट Cosecant कोसीकैंट Convert Unix timestamp to Date यूनिक�स टाइमस�टैम�प को तिथि में बदलें Convert to Decimal Representation दशमलव निरूपण में बदलें Degrees of Arc चाप की डिग�रिया� Error Function त�र�टि फलन Complementary Error Function पूरक त�र�टि फलन Exponential घातांकीय Arithmetic अंकगणित Chemistry रसायन Complex समिश�र Combinatorics संचय-विन�यास Probability प�रायिकता Statistics सांख�यिकी Aggregation सम�च�चयन Random यादृच�छिक Base conversion आधार रूपांतरण Number formatting संख�या स�वरूपण Integer arithmetic पूर�णांक अंकगणित Special functions विशेष फलन Exponential & Logarithmic घातांकीय और लघ�गणकीय Angle conversion कोण रूपांतरण Trigonometry त�रिकोणमिति Bitwise बिट-वार Floating point फ़�लोटिंग पॉइंट Date & Time दिनांक और समय Linear algebra रैखिक बीजगणित yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; GMT से x घंटे का अंतर [digits] [अंक] max [; min] अधिकतम [; न�यूनतम] List Literal सूची शाब�दिक Convert to Padded Binary Representation शून�य-भरित बाइनरी निरूपण में बदलें Round Toward +∞ (Ceiling) +∞ की ओर पूर�णांकन (सीलिंग) Cosine plus Imaginary Sine कोसाइन और काल�पनिक साइन Convert to Cis Complex Form Cis समिश�र रूप में बदलें Matrix Column Count मैट�रिक�स स�तंभ संख�या Population Correlation Matrix (n) जनसंख�या सहसंबंध मैट�रिक�स (n) Sample Correlation Matrix (n-1) नमूना सहसंबंध मैट�रिक�स (n-1) Count गिनती Population Covariance Matrix (n) जनसंख�या सहप�रसरण मैट�रिक�स (n) Sample Covariance Matrix (n-1) नमूना सहप�रसरण मैट�रिक�स (n-1) Cross Product क�रॉस ग�णनफल Convert Date to Unix timestamp दिनांक को यूनिक�स टाइमस�टैम�प में बदलें Determinant सारणिक Convert to Sexagesimal Notation षष�ट�यंश संकेतन में बदलें Dot Product डॉट ग�णनफल Convert to Engineering Notation इंजीनियरिंग संकेतन में बदलें Convert to Exponential Complex Form घातांकीय समिश�र रूप में बदलें Round Toward −∞ (Floor) −∞ की ओर पूर�णांकन (फ़�लोर) Flatten Matrix मैट�रिक�स समतल करें Fractional Part भिन�नात�मक भाग Extension of Factorials [= (x-1)!] फैक�टोरियल का विस�तार [= (x-1)!] Greatest Common Divisor महत�तम समापवर�तक Least Common Multiple लघ�त�तम समापवर�त�य Geometric Mean ज�यामितीय माध�य Gradians of arc चाप के ग�रेडियन Convert to Hexadecimal Representation हेक�साडेसिमल निरूपण में बदलें Convert to Padded Hexadecimal Representation शून�य-भरित हेक�साडेसिमल निरूपण में बदलें Hypergeometric Cumulative Distribution Function हाइपरज�यामितीय संचयी वितरण फलन Hypergeometric Distribution Mean हाइपरज�यामितीय वितरण माध�य Hypergeometric Probability Mass Function हाइपरज�यामितीय प�रायिकता द�रव�यमान फलन Hypergeometric Distribution Variance हाइपरज�यामितीय वितरण प�रसरण Integer Quotient पूर�णांक भागफल Integer Part पूर�णांक भाग Imaginary Part काल�पनिक भाग Inverse Matrix व�य�त�क�रम मैट�रिक�स Decode IEEE-754 Binary Value IEEE-754 बाइनरी मान को डिकोड करें Encode IEEE-754 Binary Value IEEE-754 बाइनरी मान को �न�कोड करें Decode 16-bit Half-Precision Value 16-बिट हाफ-प�रिसिजन मान को डिकोड करें Encode 16-bit Half-Precision Value 16-बिट हाफ-प�रिसिजन मान को �न�कोड करें Decode 32-bit Single-Precision Value 32-बिट सिंगल-प�रिसिजन मान को डिकोड करें Encode 32-bit Single-Precision Value 32-बिट सिंगल-प�रिसिजन मान को �न�कोड करें Decode 64-bit Double-Precision Value 64-बिट डबल-प�रिसिजन मान को डिकोड करें Encode 64-bit Double-Precision Value 64-बिट डबल-प�रिसिजन मान को �न�कोड करें Decode 128-bit Quad-Precision Value 128-बिट क�वाड-प�रिसिजन मान को डिकोड करें Encode 128-bit Quad-Precision Value 128-बिट क�वाड-प�रिसिजन मान को �न�कोड करें Round to 16-bit Half-Precision Value 16-बिट हाफ-प�रिसिजन मान में पूर�णांकित करें Round to 32-bit Single-Precision Value 32-बिट सिंगल-प�रिसिजन मान में पूर�णांकित करें Round to 64-bit Double-Precision Value 64-बिट डबल-प�रिसिजन मान में पूर�णांकित करें Round to 128-bit Quad-Precision Value 128-बिट क�वाड-प�रिसिजन मान में पूर�णांकित करें Residual from 16-bit Half-Precision Rounding 16-बिट हाफ-प�रिसिजन पूर�णांकन का अवशेष Residual from 32-bit Single-Precision Rounding 32-बिट सिंगल-प�रिसिजन पूर�णांकन का अवशेष Residual from 64-bit Double-Precision Rounding 64-बिट डबल-प�रिसिजन पूर�णांकन का अवशेष Residual from 128-bit Quad-Precision Rounding 128-बिट क�वाड-प�रिसिजन पूर�णांकन का अवशेष Binary Logarithm बाइनरी लघ�गणक Common Logarithm सामान�य लघ�गणक Natural Logarithm प�राकृतिक लघ�गणक Substance Mass पदार�थ द�रव�यमान Molarity मोलरता Molar Mass मोलर द�रव�यमान Logarithm to Arbitrary Base मनमाने आधार का लघ�गणक Median Absolute Deviation माध�यिका परम विचलन Mask to a bit size बिट आकार के लि� मास�क Maximum अधिकतम Median Value (50th Percentile) माध�यिका मान (50वा� प�रतिशतक) Mean माध�य Minimum न�यूनतम Numerical Value of Quantity राशि का संख�यात�मक मान Random Decimal Number यादृच�छिक दशमलव संख�या Random Integer Number यादृच�छिक पूर�णांक संख�या Convert to Rational Representation परिमेय निरूपण में बदलें Modulo मॉड�यूलो Euclidean Modulo यूक�लिडीय मॉड�यूलो Modular Exponentiation मॉड�यूलर घातांकन Combination (Binomial Coefficient) संयोजन (द�विपद ग�णांक) Logical NOT तार�किक NOT Permutation (Arrangement) क�रमचय (व�यवस�था) Convert to Octal Representation ऑक�टल निरूपण में बदलें Convert to Padded Octal Representation शून�य-भरित ऑक�टल निरूपण में बदलें Vector or Matrix Norm वेक�टर या मैट�रिक�स मानक Logical OR तार�किक OR Population Count (Hamming Weight) बिट संख�या (हैमिंग भार) Phase of Complex Number समिश�र संख�या का चरण Poissonian Cumulative Distribution Function पॉइसोनियन संचयी वितरण फलन Poissonian Distribution Mean पॉइसोनियन वितरण माध�य Poissonian Probability Mass Function पॉइसोनियन प�रायिकता द�रव�यमान फलन Poissonian Distribution Variance पॉइसोनियन वितरण प�रसरण Convert to Phasor Complex Form फ़ेज़र समिश�र रूप में बदलें Convert to Rectangular Complex Form आयताकार समिश�र रूप में बदलें Round Half Away from Zero आधा शून�य से दूर पूर�णांकित करें Round Half Even आधा सम पर पूर�णांकित करें Nth Root n-वा� मूल Convert to Scientific Notation वैज�ञानिक संकेतन में बदलें Matrix Row Count मैट�रिक�स पंक�ति संख�या List or Matrix Shape सूची या मैट�रिक�स आकृति Summation संकलन Population Standard Deviation (n) जनसंख�या मानक विचलन (n) Sample Standard Deviation (n-1) नमूना मानक विचलन (n-1) Round Toward Zero (Truncation) शून�य की ओर पूर�णांकन (ट�रंकेशन) Matrix Trace मैट�रिक�स ट�रेस Transpose Matrix मैट�रिक�स ट�रांसपोज़ Population Variance (n) जनसंख�या प�रसरण (n) Sample Variance (n-1) नमूना प�रसरण (n-1) Product ग�णनफल Radians रेडियन Matrix Rank मैट�रिक�स रैंक Real Part वास�तविक भाग Secant सीकैंट Arithmetic Shift Left अंकगणितीय बाया� शिफ�ट Arithmetic Shift Right अंकगणितीय दाया� शिफ�ट Signum साइनम Sine साइन Hyperbolic Sine अतिपरवलयिक साइन Square Root वर�गमूल Sum योग Tangent टैन�जेंट Convert to Trigonometric Complex Form त�रिकोणमितीय समिश�र रूप में बदलें Turns टर�न Hyperbolic Tangent अतिपरवलयिक टैन�जेंट Sign-extend a value किसी मान का साइन-विस�तार करें Logical XOR तार�किक XOR FunctionsWidget Domain डोमेन All सभी Identifier पहचानकर�ता Name नाम Search खोज No match found कोई मेल नहीं मिला HistoryWidget Remove All Calculations Above ऊपर की सभी गणना�� हटा�� Remove This Calculation यह गणना हटा�� Remove All Calculations Below नीचे की सभी गणना�� हटा�� Keypad Inverse cosine व�य�त�क�रम कोसाइन The last result अंतिम परिणाम Inverse sine व�य�त�क�रम साइन Inverse tangent व�य�त�क�रम टैन�जेंट Evaluate expression व�यंजक का मूल�यांकन करें Division भाग Multiplication ग�णा Subtraction घटाव Addition जोड़ Clear expression व�यंजक साफ़ करें Cosine कोसाइन Backspace बैकस�पेस Scientific notation वैज�ञानिक संकेतन Exponential घातांकीय Factorial फैक�टोरियल Natural logarithm प�राकृतिक लघ�गणक Left parenthesis बाया� कोष�ठक Nth root n-वा� मूल Argument separator तर�क विभाजक Square वर�ग Common logarithm सामान�य लघ�गणक Modulo मॉड�यूलो Contextual percentage संदर�भगत प�रतिशत Power शक�ति Right parenthesis दाया� कोष�ठक Sine साइन Square root वर�गमूल Tangent टैन�जेंट Pi पाई Decimal separator दशमलव विभाजक MainWindow Radian रेडियन Gradian ग�रेडियन Degree डिग�री Binary बाइनरी Octal ऑक�टल Hexadecimal हेक�साडेसिमल Sexagesimal सेक�साजेसिमल Engineering decimal इंजीनियरिंग दशमलव Scientific decimal वैज�ञानिक दशमलव Plain &text सादा &पाठ &Import... &आयात... &Quit &बाहर निकलें Clear E&xpression व�यंजक सा&फ करें Clear &History इतिहास &साफ़ करें &Copy &कॉपी &Paste &पेस�ट &Select Expression व�यंजक &च�नें &Constants &स�थिरांक &Functions &फलन &History &इतिहास &Keypad &कीपैड Formula &Book सूत�र &प�स�तक New &Private Tab न&या निजी टैब Keep रखें Make Private... निजी बना��... &Rename... ना&म बदलें... Clo&ne... &प�रतिरूप बना��... &Close Tab टैब बं&द करें Reopen Clo&sed Tab बंद टैब फि&र खोलें &Undo पू&र�ववत करें &Redo &फिर करें Cu&t का&टें Copy &Last Result &अंतिम परिणाम कॉपी करें &Wrap in Parentheses को&ष�ठकों में रखें Full Scr&een Mode पू&र�ण स�क�रीन मोड &Status Bar &स�थिति पट�टी Bitfield बिटफ़ील�ड &Left &बा�� &Right &दा�� &Up &ऊपर &Down &नीचे Close Pa&ne फ&लक बंद करें Use&r Functions उपयो&क�ता फलन &Degree &डिग�री &Radian &रेडियन &Gradian &ग�रेडियन Re&volution &परिक�रमण Always on &Top हमेशा &ऊपर Auto-Insert a&ns a&ns अपने आप डालें Automatic &Completion स�वचालित &पूर�णता &Built-in Functions &अंतर�निहित फलन Built-in &Variables अं&तर�निहित चर User &Functions &उपयोगकर�ता फलन User Va&riables उ&पयोगकर�ता चर Open a Private Tab on Startup श�रू होने पर निजी टैब खोलें Open and focus a new private tab whenever SpeedCrunch starts. SpeedCrunch के हर बार श�रू होने पर नया निजी टैब खोलें और उस पर फ़ोकस करें। Syntax &Highlighting वाक�यविन�यास &हाइलाइटिंग Group Digits in &Input &इनप�ट के अंकों का समूहन Automatic Input &Adjustments &अपने आप इनप�ट समायोजन Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. संकारकों, रिक�त स�थानों, कोष�ठकों और घातों को अपने आप समायोजित करें और इनप�ट को मान�य वर�णों तक सीमित करें। Group input digits using the selected number format. च�ने ग� संख�या प�रारूप के अन�सार इनप�ट के अंकों को समूहों में बा�टें। &Blinking Cursor &टिमटिमाता कर�सर Blink the cursor in the expression editor. व�यंजक संपादक में कर�सर को टिमटिमाने दें। &Escape Clears Editor &Escape संपादक खाली करता है Clear the focused expression editor with Escape after dismissing any popup or preview. किसी भी पॉपअप या पूर�वावलोकन को बंद करने के बाद Escape से फ़ोकस वाले व�यंजक संपादक को खाली करें। Disabled अक�षम Small Space छोटी दूरी Medium Space मध�यम दूरी Large Space बड़ी दूरी Keep Expression After Evaluation गणना के बाद व�यंजक रखें Copy New Results Automatically न� परिणाम अपने आप कॉपी करें &Comma &अल�पविराम &System Default &सिस�टम डिफ़ॉल�ट &Dot &बिंद� Dot &And Comma बिंद� &और अल�पविराम &0 Digits &0 अंक &15 Digits &15 अंक &2 Digits &2 अंक &3 Digits &3 अंक &50 Digits &50 अंक &8 Digits &8 अंक Toward +∞ (&ceil) +∞ की ओर (&ceil) Toward −∞ (&floor) −∞ की ओर (&floor) &Automatic &स�वचालित &Engineering &इंजीनियरिंग &Scientific &वैज�ञानिक &Binary &बाइनरी &Octal &ऑक�टल &Hexadecimal &हेक�साडेसिमल &Sexagesimal &सेक�साजेसिमल &Font... &फ़ॉन�ट... Reset All Settings... सभी सेटिंग रीसेट करें... &System &सिस�टम SpeedCrunch &Theme &SpeedCrunch थीम &Classic &पारंपरिक &Modern &आध�निक &Language... &भाषा... User &Manual उपयोगकर�ता &मैन�अल Context Help प�रासंगिक सहायता Issues and &Feedback &समस�या�� और प�रतिक�रिया &Donate &दान Editor and Results Font संपादक और परिणाम का फ़ॉन�ट &Session &सत�र &Export &निर�यात &Edit &संपादन &View &दृश�य S&plit &विभाजित करें Se&ttings से&टिंग�स &Decimal &दशमलव &Precision &परिश�द�धता Angle &Mode &कोण मोड &Complex Form &सम�मिश�र रूप &Help &सहायता New Tab नया टैब Constants स�थिरांक Functions फलन History इतिहास User Functions उपयोगकर�ता फलन Error त�र�टि Can't read from file %1 फ़ाइल %1 से पढ़ा नहीं जा सकता Can't write to file %1 फ़ाइल %1 में लिखा नहीं जा सकता Import Session सत�र आयात करें Close Session सत�र बंद करें Angle Mode: कोण मोड: Notation: संकेतन: Precision: परिश�द�धता: Turn टर�न Revolution परिक�रमण Fixed-point decimal स�थिर-बिंद� दशमलव Rational परिमेय Automatic decimal स�वचालित दशमलव Automatic स�वचालित User &Definitions... &उपयोगकर�ता परिभाषा��... New &Tab नया &टैब New &Window नई &विंडो &Open... &खोलें... Open Sessions &Folder सत�रों का &फ़ोल�डर खोलें &Basic &मूल &Scientific (wide) &वैज�ञानिक (चौड़ा) Scientific (narrow) वैज�ञानिक (संकरी) &Custom... &कस�टम... Main &Menu म�ख�य &मेनू User &Variables उपयोगकर�ता &चर User &Units उपयोगकर�ता &इकाइया� &Turn &टर�न If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. यदि नया व�यंजक +, -, * या / से श�रू होता है, तो SpeedCrunch पहले "ans" डालता है। &Accept with Enter &Enter से स�वीकार करें Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. तीर क�ंजियों से पहले च�ने बिना ही Enter से स�वतः पूर�णता के मौजूदा स��ाव को स�वीकार करें। &Units &इकाइया� Show Live Result &Preview लाइव परिणाम &पूर�वावलोकन दिखा�� Save &Window Position on Exit बाहर निकलते समय &विंडो स�थिति सहेजें Hover Highlighting होवर हाइलाइटिंग Group Integer Part Only केवल पूर�णांक भाग समूहित करें Number Format... संख�या प�रारूप... Notation && Precision... संकेतन && परिश�द�धता... After pressing Enter, keep the entered expression selected in the editor. Enter दबाने के बाद दर�ज व�यंजक को संपादक में चयनित रखें। Never कभी नहीं Always हमेशा Only for Single-Line Expressions केवल �क-पंक�ति व�यंजकों के लि� Simplify Displayed Expressions दिखा� ग� व�यंजक सरल करें History Size &Limit... इतिहास आकार &सीमा... Remove Trailing &Zeroes &अंत के शून�य हटा�� Nearest, Half &Away (round) निकटतम, आधा &दूर (round) Nearest, Half &Even (roundeven) निकटतम, आधा &सम (roundeven) Toward &Zero (trunc) &शून�य की ओर (trunc) &Fixed-Point &स�थिर-बिंद� &Rational &परिमेय &Exponential (m·s�¹) &घातांकीय (m·s�¹) &Fractional (m/s) &भिन�नात�मक (m/s) &Rectangular (a + bi) &आयताकार (a + bi) Exponential (re�ᶿ) घातांकीय (re�ᶿ) Trigonometric (r(cos θ + i·sin θ)) त�रिकोणमितीय (r(cos θ + i·sin θ)) Phasor (r∠θ) फ़ेज़र (r∠θ) &Theme... &थीम... Check for &Updates &अपडेट जा�चें Source Code स�रोत कोड &Zoom &ज़ूम &Results &परिणाम Unit Notation इकाई संकेतन Rounding Mode राउंडिंग मोड &Notation &संकेतन &Imaginary Unit &काल�पनिक इकाई &Window &विंडो &Editing &संपादन A&utocomplete स�वतः&पूर�णता Up/Down Arrow History ऊपर/नीचे तीर इतिहास &Appearance &दिखावट &Menus &मेनू &Docks &डॉक करने योग�य पैनल &Input and Results &इनप�ट और परिणाम &Disabled &अक�षम &Disable &अक�षम करें Close preview पूर�वावलोकन बंद करें Rename... नाम बदलें... Clone... प�रतिरूप बना��... Close Tab टैब बंद करें New Private Tab नया निजी टैब Open... खोलें... Reopen Closed Tab बंद टैब फिर खोलें Split विभाजित करें Left बा�� Right दा�� Up ऊपर Down नीचे Clear खाली करें Delete हटा�� %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 निजी सत�र: बंद करने पर सामग�री मिटा दी जाती है। इसे सामान�य सत�र बनाने के लि� सत�र > रखें च�नें। SpeedCrunch - %1 [Private] SpeedCrunch - %1 [निजी] Reset All Settings सभी सेटिंग रीसेट करें Reset all settings to their default values? सभी सेटिंग उनके मूलभूत मानों पर रीसेट करें? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. इसमें रूप, संपादन, परिणाम प�रारूप और विंडो की प�राथमिकता�� शामिल हैं। आपकी गणना��, ख�ले सत�र और उपयोगकर�ता परिभाषा�� रखी जा��गी। The settings file could not be written. सेटिंग फ़ाइल लिखी नहीं जा सकी। Clear this session's calculations, unfinished expression, variables, functions, and units? इस सत�र की गणना��, अधूरा व�यंजक, चर, फलन और इकाइया� मिटा��? Global user definitions are kept. वैश�विक उपयोगकर�ता परिभाषा�� रखी जाती हैं। Make Session Private सत�र निजी बना�� The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. सहेजा गया सत�र %1 मिटा दिया जा�गा। इसकी सामग�री निजी सत�र में ख�ली रहेगी और उस सत�र को बंद करने या SpeedCrunch से बाहर निकलने पर मिटा दी जा�गी। Make Private निजी बना�� Could not delete the saved session %1. सहेजा गया सत�र %1 मिटाया नहीं जा सका। Keep Session सत�र रखें Could not save the session. It remains private. सत�र सहेजा नहीं जा सका। यह निजी ही रहेगा। Clone Session सत�र का प�रतिरूप बना�� Could not save session file %1. सत�र फ़ाइल %1 सहेजी नहीं जा सकी। Could not delete session file %1. सत�र फ़ाइल %1 मिटाई नहीं जा सकी। JSON file (*.json);;Any file (*.*) JSON फ़ाइल (*.json);;कोई भी फ़ाइल (*.*) Export session as JSON सत�र को JSON के रूप में निर�यात करें The selected file is not valid JSON: %1 चयनित फ़ाइल वैध JSON नहीं है: %1 The selected file is not a SpeedCrunch session JSON file. चयनित फ़ाइल SpeedCrunch सत�र की JSON फ़ाइल नहीं है। This file uses an obsolete SpeedCrunch session format and cannot be imported. यह फ़ाइल प�राने SpeedCrunch सत�र प�रारूप का उपयोग करती है और आयात नहीं की जा सकती। The selected JSON file is missing the required $schema field. चयनित JSON फ़ाइल में आवश�यक $schema फ़ील�ड नहीं है। The selected JSON file uses an unsupported JSON schema: %1 चयनित JSON फ़ाइल असमर�थित JSON स�कीमा का उपयोग करती है: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). चयनित JSON फ़ाइल में SpeedCrunch सत�र स�कीमा पहचानकर�ता ($id) नहीं है। The selected JSON file uses an unsupported SpeedCrunch session format: %1 चयनित JSON फ़ाइल असमर�थित SpeedCrunch सत�र प�रारूप का उपयोग करती है: %1 The selected JSON file is missing the required session name. चयनित JSON फ़ाइल में आवश�यक सत�र नाम नहीं है। The selected JSON file has an empty session name. चयनित JSON फ़ाइल में सत�र नाम खाली है। The selected JSON file has invalid or incomplete SpeedCrunch session data. चयनित JSON फ़ाइल में अमान�य या अधूरा SpeedCrunch सत�र डेटा है। Open Sessions Folder सत�र फ़ोल�डर खोलें Could not create the sessions folder: %1 सत�र फ़ोल�डर नहीं बनाया जा सका: %1 Could not open the sessions folder: %1 सत�र फ़ोल�डर नहीं खोला जा सका: %1 Open Session सत�र खोलें Community सम�दाय Rename Session सत�र का नाम बदलें Clear Session सत�र साफ़ करें Delete Session सत�र हटा�� Close Pane फलक बंद करें &About SpeedCrunch &SpeedCrunch के बारे में App Diag&nostics &�प निदान User Variables उपयोगकर�ता चर User Units उपयोगकर�ता इकाइया� Clear History इतिहास साफ़ करें Are you sure you want to clear the calculation history? क�या आप गणना इतिहास साफ़ करना चाहते हैं? Session name: सत�र नाम: A session named %1 already exists. %1 नाम का सत�र पहले से मौजूद है। Could not create session file %1. सत�र फ़ाइल %1 बनाई नहीं जा सकी। Could not write session file %1. सत�र फ़ाइल %1 लिखी नहीं जा सकी। Are you sure you want to delete this session? क�या आप इस सत�र को हटाना चाहते हैं? Custom Precision कस�टम परिश�द�धता Fractional digits: भिन�नात�मक अंक: Theme थीम Light Themes हल�की थीम Dark Themes गहरी थीम Preview पूर�वावलोकन Colors रंग Select color for %1 %1 के लि� रंग च�नें Import... आयात... Export... निर�यात... Import Theme थीम आयात करें Theme file (*.json);;All files (*) थीम फ़ाइल (*.json);;सभी फ़ाइलें (*) Invalid theme file. अमान�य थीम फ़ाइल। Can't import theme "%1" because it conflicts with a built-in theme. अंतर�निहित थीम से टकराव के कारण थीम "%1" आयात नहीं की जा सकती। Can't find a writable theme folder. लिखने योग�य थीम फ़ोल�डर नहीं मिल सका। Overwrite Theme थीम अधिलेखित करें A custom theme named "%1" already exists. Do you want to overwrite it? "%1" नाम की कस�टम थीम पहले से मौजूद है। क�या आप उसे अधिलेखित करना चाहते हैं? Can't overwrite theme file %1 थीम फ़ाइल %1 अधिलेखित नहीं की जा सकती Can't copy theme file to %1 थीम फ़ाइल को %1 में कॉपी नहीं किया जा सकता Export Theme थीम निर�यात करें Can't export theme as "%1" because it conflicts with a built-in theme. अंतर�निहित थीम से टकराव के कारण थीम को "%1" के रूप में निर�यात नहीं किया जा सकता। Global User Variable वैश�विक उपयोगकर�ता चर Global User Function वैश�विक उपयोगकर�ता फलन Global User Unit वैश�विक उपयोगकर�ता इकाई User Definitions उपयोगकर�ता परिभाषा�� These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. ये परिभाषा�� वैश�विक हैं और हर सत�र में लोड की जाती हैं। इन�हें सत�रों से बदला नहीं जा सकता और इन�हें सत�र संपादक की समान नाम वाली परिभाषाओं पर प�राथमिकता दी जाती है। प�रत�येक पंक�ति में �क परिभाषा दर�ज करें। Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] उदाहरण: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply लागू करें Validate सत�यापित करें Test Results परीक�षण के परिणाम Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 आयातित चर: %1 आयातित फलन: %2 आयातित इकाइया�: %3 त�र�टियों वाली पंक�तियों की संख�या��: %4 none कोई नहीं Apply Results लागू करने के परिणाम User definitions saved. उपयोगकर�ता परिभाषा�� सहेजी गईं। History Size Limit इतिहास आकार सीमा Maximum number of history entries for this session (0 = unlimited): इस सत�र के लि� इतिहास प�रविष�टियों की अधिकतम संख�या (0 = असीमित): Export session as HTML सत�र को HTML के रूप में निर�यात करें HTML file (*.html) HTML फ़ाइल (*.html) Export session as plain text सत�र को सादे पाठ के रूप में निर�यात करें Text file (*.txt);;Any file (*.*) पाठ फ़ाइल (*.txt);;कोई भी फ़ाइल (*.*) Could not recalculate from calculation %1: %2 गणना %1 से प�नर�गणना नहीं की जा सकी: %2 History Size Limit Reached इतिहास आकार सीमा पह��च गई This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. यह गणना अंतिम उपलब�ध इतिहास स�थान भरती है। आगे की गणना�� इतिहास से सबसे प�रानी गणना हटा��गी। आप सत�र > इतिहास आकार सीमा से सीमा बढ़ा सकते हैं। Editing calculation. Press Esc twice to cancel. गणना संपादित हो रही है। रद�द करने के लि� Esc दो बार दबा��। Calculation Settings गणना सेटिंग�स Invalid recalculation start index अमान�य प�नर�गणना प�रारंभ सूचकांक System Default सिस�टम डिफ़ॉल�ट Language भाषा Select the language: भाषा च�नें: Custom कस�टम Decimal places: दशमलव स�थान: ManualWindow SpeedCrunch Manual SpeedCrunch मैन�अल %1 - SpeedCrunch Manual %1 - SpeedCrunch मैन�अल NumberFormatDialog Number Format संख�या प�रारूप <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>परिणाम और इनप�ट के अंकों के समूहन के लि� संख�या प�रारूप च�नें।</b><br/><br/>ध�यान दें: इनप�ट संख�याओं के स�पष�ट प�रारूप च�ने ग� प�रदर�शन प�रारूप से भिन�न होने पर भी स�वीकार कि� जाते हैं।<br/> QObject Global User Variable वैश�विक उपयोगकर�ता चर Global User Function वैश�विक उपयोगकर�ता फलन Global User Unit वैश�विक उपयोगकर�ता इकाई Backspace बैकस�पेस Clear expression व�यंजक साफ़ करें Evaluate expression व�यंजक का मूल�यांकन करें Insert text पाठ डालें Automatic decimal स�वचालित दशमलव Fixed-point decimal स�थिर-बिंद� दशमलव Engineering decimal इंजीनियरिंग दशमलव Scientific decimal वैज�ञानिक दशमलव Rational परिमेय Binary बाइनरी Octal ऑक�टल Hexadecimal हेक�साडेसिमल Sexagesimal सेक�साजेसिमल Update Available अपडेट उपलब�ध A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> �क नया संस�करण (%1) उपलब�ध है।<br/><a href="%2">डाउनलोड करने के लि� वेबसाइट पर जा��।</a> Check for Updates अपडेट जा�चें SpeedCrunch %1 is up to date. SpeedCrunch %1 अद�यतित है। No connectivity. Please check your internet connection and try again. कनेक�टिविटी नहीं है। अपना इंटरनेट कनेक�शन जा�चें और फिर प�रयास करें। Could not verify the latest available version. नवीनतम उपलब�ध संस�करण सत�यापित नहीं किया जा सका। ResultDisplay Scroll to bottom नीचे तक स�क�रॉल करें Edit Expression व�यंजक संपादित करें Change Settings सेटिंग�स बदलें New Tab नया टैब &Import... &आयात... &Export &निर�यात Plain &text सादा &पाठ Copy कॉपी Selection चयन Select All सभी च�नें Expression व�यंजक Result परिणाम Calculation गणना Calculation as Single Line �क पंक�ति में गणना Remove हटा�� This Calculation यह गणना All Calculations Above ऊपर की सभी गणना�� All Calculations Below नीचे की सभी गणना�� New Private Tab नया निजी टैब Session सत�र Open... खोलें... Clone... प�रतिरूप बना��... Rename... नाम बदलें... Keep रखें Make Private... निजी बना��... Clear खाली करें Delete हटा�� Close बंद करें Split विभाजित करें Left बा�� Right दा�� Up ऊपर Down नीचे Close Pane फलक बंद करें Main Menu म�ख�य मेनू Cancel editing संपादन रद�द करें Copy result परिणाम कॉपी करें Edit expression व�यंजक संपादित करें Change settings सेटिंग�स बदलें Remove calculation गणना हटा�� ResultSlotsDialog Notation & Precision संकेतन और परिश�द�धता Result Line परिणाम पंक�ति Enabled सक�षम Notation संकेतन Decimal Places दशमलव स�थान Main Line म�ख�य पंक�ति Extra Line #1 अतिरिक�त पंक�ति #1 Extra Line #2 अतिरिक�त पंक�ति #2 Extra Line #3 अतिरिक�त पंक�ति #3 Extra Line #4 अतिरिक�त पंक�ति #4 Auto स�वतः UserFunctionListWidget Name नाम Value मान Description विवरण Search खोज No match found कोई मेल नहीं मिला Insert सम�मिलित करें Edit संपादित करें Delete हटा�� Delete All सभी हटा�� UserUnitListWidget Name नाम Value मान Description विवरण Search खोज No match found कोई मेल नहीं मिला Insert सम�मिलित करें Edit संपादित करें Delete हटा�� Delete All सभी हटा�� VariableListWidget Name नाम Value मान Description विवरण Search खोज No match found कोई मेल नहीं मिला Insert सम�मिलित करें Edit संपादित करें Delete हटा�� Delete All सभी हटा�� heldercorreia-speedcrunch-e7ca37f/src/resources/locale/hu.ts000066400000000000000000010553171526573132500243750ustar00rootroot00000000000000 AboutBox About SpeedCrunch A SpeedCrunch névjegye Core developers Fő fejlesztők Original author Eredeti szerző Close Bezár Math engine Matematikai motor Main author | Logo | Maintainer Fő szerző | Logó | Karbantartó Thanks Köszönetnyilvánítás Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 A SpeedCrunch fejlesztői This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Ez a program szabad szoftver; továbbterjesztheti és/vagy módosíthatja a Free Software Foundation által közzétett GNU General Public License feltételei szerint, akár a licenc 2. verziója, akár (választása szerint) bármely későbbi verzió alapján This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Ezt a programot abban a reményben terjesztjük, hogy hasznos lesz, de MINDENFÉLE GARANCIA NÉLKÜL; még az ELADHATÓS�GRA vagy EGY ADOTT CÉLRA VALÓ ALKALMASS�GRA vonatkozó vélelmezett garancia nélkül is. További részletekért lásd a GNU General Public License-t. BitFieldWidget Reset bits to zero Bitek nullázása Invert bits Bitek invertálása Shift bits left Bitek eltolása balra Shift bits right Bitek eltolása jobbra Book Index Tárgymutató Algebra Algebra Quadratic Equation Másodfokú egyenlet Logarithmic Base Conversion Logaritmusalap átváltása Geometry Geometria Circle Kör Sector Körcikk Sphere Gömb Cube Kocka Cone Kúp Cylinder Henger Electronics Elektronika Ohm's Law Ohm törvénye Power Teljesítmény Reactance Reaktancia Resonance Rezonancia Radio Frequency Rádiófrekvencia Antennas Antennák Characteristic Impedance (coax) Hullámimpedancia (koax) Velocity of Propagation (coax) Tovaterjedési sebesség (koax) Standing Wave Ratio & Return Loss �llóhullámarány és visszaverési veszteség Free Space Wavelength szabad térbeli hullámhossz resistance ellenállás voltage feszültség current áramerősség power teljesítmény inductive reactance induktív reaktancia capacitive reactance kapacitív reaktancia inductance induktivitás capacitance kapacitás frequency frekvencia resonance frequency rezonancia frekvencia area terület perimeter kerület diameter átmérő radius sugár volume térfogat surface area felület height magasság slant height oldalmagasság face diagonal lapátló space diagonal testátló edge length élhossz arc length ívhossz central angle (degrees) középponti szög (fok) input power bemeneti teljesítmény reflected power visszavert teljesítmény transmitted power átmenő teljesítmény return loss visszirányú csillapítás dielectric constant relatív dielektromos állandó outer conductor's inner diameter külső vezető belső átmérője inner conductor's outer diameter belső vezető külső átmérője speed of light fénysebesség reflection coefficient visszaverődési együttható standing wave ratio �llóhullám-viszony normalized impedance normált impedancia frequency (Hz) frekvencia (Hz) BookDock Formula Book Függvénytáblázat ConstantCompletion Search constants �llandók keresése No match found Nincs találat Constants Mathematics Matematika Physics (CODATA 2022) Fizika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kémia (IUPAC - CIAAW 2021) Uncategorized Kategorizálatlan Universal Univerzális Physicochemical Fizikai-kémiai Atomic & Nuclear — General Atomi és nukleáris — általános Atomic & Nuclear — Electroweak Atomi és nukleáris — gyenge-elektromos Atomic & Nuclear — Electron Atomi és nukleáris — elektron Atomic & Nuclear — Muon Atomi és nukleáris — müon Atomic & Nuclear — Tau Atomi és nukleáris — tau Atomic & Nuclear — Proton Atomi és nukleáris — proton Atomic & Nuclear — Neutron Atomi és nukleáris — neutron Atomic & Nuclear — Deuteron Atomi és nukleáris — deuteron Atomic & Nuclear — Triton Atomi és nukleáris — triton Atomic & Nuclear — Helion Atomi és nukleáris — helion Atomic & Nuclear — Alpha particle Atomi és nukleáris — alfa-részecske Atomic & Nuclear — Atomic units Atomi és nukleáris — atomi egységek Atomic & Nuclear — Energy conversion relationships Atomi és nukleáris — energiaátváltási összefüggések Atomic & Nuclear — X-ray units Atomi és nukleáris — röntgenegységek Atomic & Nuclear — Magnetic shielding corrections Atomi és nukleáris — mágneses árnyékolási korrekciók Masses Tömegek Lifetimes Élettartamok Molar Masses Moláris tömegek Electronegativity Elektronegativitás Ionization Energy Ionizációs energia Nominal Constants (IAU 2015) Névleges állandók (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Jelenlegi legjobb becslések (IAU NSFA 2026-04) characteristic impedance of vacuum (Z₀) vákuum karakterisztikus impedanciája (Z₀) reduced Planck constant (�) redukált Planck-állandó (�) vacuum electric permittivity (ϵ₀) vákuum elektromos permittivitása (ϵ₀) Newtonian constant of gravitation (G) Newton-féle gravitációs állandó (G) vacuum magnetic permeability (μ₀) vákuum mágneses permeabilitása (μ₀) Planck constant (h) Planck-állandó (h) speed of light in vacuum (c) fénysebesség vákuumban (c) standard acceleration of gravity (gₙ) standard nehézségi gyorsulás (gₙ) Newtonian constant of gravitation over h-bar c Newton-féle gravitációs állandó h-vonás c-re osztva Planck length Planck-hossz Planck constant in eV/Hz (h) Planck-állandó eV/Hz-ben (h) Planck mass Planck-tömeg Planck mass energy equivalent in GeV Planck-tömeg energia-egyenértéke GeV-ben Planck temperature Planck-hőmérséklet Planck time Planck-idő reduced Planck constant in eV·s (�) redukált Planck-állandó eV·s-ben (�) reduced Planck constant times c in MeV·fm redukált Planck-állandó c-vel szorozva MeV·fm-ben Bohr magneton Bohr-magneton conductance quantum (G₀) vezetőképesség-kvantum (G₀) Coulomb constant (kₑ) Coulomb-állandó (kₑ) elementary charge (e) elemi töltés (e) elementary charge over h-bar elemi töltés h-vonással osztva conventional value of Josephson constant Josephson-állandó konvencionális értéke Josephson constant Josephson-állandó conventional value of ampere-90 ampere-90 konvencionális értéke conventional value of coulomb-90 coulomb-90 konvencionális értéke conventional value of farad-90 farad-90 konvencionális értéke conventional value of henry-90 henry-90 konvencionális értéke conventional value of ohm-90 ohm-90 konvencionális értéke conventional value of volt-90 volt-90 konvencionális értéke conventional value of watt-90 watt-90 konvencionális értéke magnetic flux quantum (Φ₀) mágneses fluxuskvantum (Φ₀) nuclear magneton nukleáris magneton inverse of conductance quantum vezetőképesség-kvantum reciproka conventional value of von Klitzing constant von Klitzing-állandó konvencionális értéke von Klitzing constant von Klitzing-állandó atomic unit of magnetic dipole moment atomi egység: mágneses dipólusmomentum atomic unit of magnetic flux density atomi egység: mágneses fluxussűrűség Bohr magneton in eV/T Bohr-magneton eV/T-ben Bohr magneton in Hz/T Bohr-magneton Hz/T-ben Bohr magneton in inverse meter per tesla Bohr-magneton reciprok méter/tesla egységben Bohr magneton in K/T Bohr-magneton K/T-ben nuclear magneton in eV/T nukleáris magneton eV/T-ben nuclear magneton in inverse meter per tesla nukleáris magneton reciprok méter/tesla egységben nuclear magneton in K/T nukleáris magneton K/T-ben nuclear magneton in MHz/T nukleáris magneton MHz/T-ben Bohr radius (a₀) Bohr-sugár (a₀) fine-structure constant (α) finomszerkezeti állandó (α) Hartree energy (Eₕ) Hartree-energia (Eₕ) Hartree energy in eV Hartree-energia eV-ban quantum of circulation cirkulációs kvantum quantum of circulation times 2 cirkulációs kvantum kétszerese Rydberg constant (R∞) Rydberg-állandó (R∞) atomic mass unit-hartree relationship atomi tömegegység–hartree összefüggés atomic mass unit-hertz relationship atomi tömegegység–hertz összefüggés atomic mass unit-inverse meter relationship atomi tömegegység–reciprok méter összefüggés atomic mass unit-joule relationship atomi tömegegység–joule összefüggés atomic mass unit-kelvin relationship atomi tömegegység–kelvin összefüggés atomic mass unit-kilogram relationship atomi tömegegység–kilogramm összefüggés atomic unit of 1st hyperpolarizability atomi egység: első hiperpolarizálhatóság atomic unit of 2nd hyperpolarizability atomi egység: második hiperpolarizálhatóság atomic unit of charge (e) atomi egység: töltés (e) atomic unit of charge density atomi egység: töltéssűrűség atomic unit of current atomi egység: áramerősség atomic unit of electric dipole moment atomi egység: elektromos dipólusmomentum atomic unit of electric field atomi egység: elektromos tér atomic unit of electric field gradient atomi egység: elektromos tér gradiens atomic unit of electric polarizability atomi egység: elektromos polárisizálhatóság atomic unit of electric potential atomi egység: elektromos potenciál atomic unit of electric quadrupole moment atomi egység: elektromos kvadrupólmomentum atomic unit of action atomi egység: hatás atomic unit of energy atomi egység: energia atomic unit of force atomi egység: erő atomic unit of length atomi egység: hossz hertz-atomic mass unit relationship hertz–atomi tömegegység összefüggés hertz-electron volt relationship hertz-elektronvolt összefüggés hertz-hartree relationship hertz-hartree összefüggés hertz-inverse meter relationship hertz–reciprok méter összefüggés hertz-joule relationship hertz-joule összefüggés hertz-kelvin relationship hertz-kelvin összefüggés hertz-kilogram relationship hertz-kilogram összefüggés hyperfine transition frequency of Cs-133 Cs-133 hiperfinom átmeneti frekvenciája inverse fine-structure constant (α�¹) finomszerkezeti állandó reciproka (α�¹) inverse meter-atomic mass unit relationship reciprok méter–atomi tömegegység összefüggés inverse meter-electron volt relationship reciprok méter–elektronvolt összefüggés inverse meter-hartree relationship reciprok méter–hartree összefüggés inverse meter-hertz relationship reciprok méter–hertz összefüggés inverse meter-joule relationship reciprok méter–joule összefüggés inverse meter-kelvin relationship reciprok méter–kelvin összefüggés inverse meter-kilogram relationship reciprok méter–kilogramm összefüggés joule-atomic mass unit relationship joule–atomi tömegegység összefüggés joule-electron volt relationship joule-elektronvolt összefüggés joule-hertz relationship joule-hertz összefüggés joule-hartree relationship joule-hartree összefüggés joule-inverse meter relationship joule–reciprok méter összefüggés joule-kelvin relationship joule-kelvin összefüggés joule-kilogram relationship joule-kilogram összefüggés kelvin-atomic mass unit relationship kelvin–atomi tömegegység összefüggés kelvin-electron volt relationship kelvin-elektronvolt összefüggés kelvin-hertz relationship kelvin-hertz összefüggés kelvin-hartree relationship kelvin-hartree összefüggés kelvin-inverse meter relationship kelvin–reciprok méter összefüggés kelvin-joule relationship kelvin-joule összefüggés kelvin-kilogram relationship kelvin-kilogram összefüggés kilogram-atomic mass unit relationship kilogramm–atomi tömegegység összefüggés kilogram-electron volt relationship kilogram-elektronvolt összefüggés kilogram-hertz relationship kilogram-hertz összefüggés kilogram-hartree relationship kilogram-hartree összefüggés kilogram-inverse meter relationship kilogramm–reciprok méter összefüggés kilogram-joule relationship kilogram-joule összefüggés kilogram-kelvin relationship kilogram-kelvin összefüggés lattice parameter of silicon (a) szilícium rácsparamétere (a) luminous efficacy fényhasznosítás natural unit of energy természetes egység: energia natural unit of energy in MeV természetes egység: energia MeV-ben natural unit of action (�) természetes egység: hatás (�) natural unit of action in eV·s természetes egység: hatás eV·s-ben natural unit of length természetes egység: hossz natural unit of mass természetes egység: tömeg natural unit of momentum természetes egység: impulzus natural unit of momentum in MeV/c természetes egység: impulzus MeV/c-ben natural unit of time természetes egység: idő natural unit of velocity természetes egység: sebesség Rydberg constant times c in Hz Rydberg-állandó c-vel szorozva Hz-ben Rydberg constant times hc in eV Rydberg-állandó hc-vel szorozva eV-ban Rydberg constant times hc in J Rydberg-állandó hc-vel szorozva J-ban Fermi coupling constant Fermi-csatolási állandó weak mixing angle gyenge keveredési szög W to Z mass ratio W/Z tömegarány Thomson cross section (σₑ) Thomson-hatáskeresztmetszet (σₑ) electron mass (mₑ) elektron tömege (mₑ) electron mass in u elektron tömege u-ban electron mass energy equivalent (mₑ·c²) elektron tömeg-energia egyenértéke (mₑ·c²) electron mass energy equivalent in MeV elektron tömeg-energia egyenértéke MeV-ben reduced Compton wavelength redukált Compton-hullámhossz classical electron radius (rₑ) klasszikus elektronsugár (rₑ) electron charge to mass quotient elektron töltés/tömeg hányadosa electron-deuteron magnetic moment ratio elektron-deuteron mágnesesmomentum-arány electron-deuteron mass ratio elektron-deuteron tömegarány electron g factor (gₑ) elektron g-faktor (gₑ) electron gyromagnetic ratio (γₑ) elektron giromágneses arány (γₑ) electron gyromagnetic ratio in MHz/T elektron giromágneses aránya MHz/T-ben electron-helion mass ratio elektron-helion tömegarány electron magnetic moment (μₑ) elektron mágneses momentum (μₑ) electron magnetic moment anomaly (aₑ) elektron mágneses momentumának anomáliája (aₑ) electron magnetic moment to Bohr magneton ratio elektron mágneses momentumának aránya a Bohr-magnetonhoz electron magnetic moment to nuclear magneton ratio elektron mágneses momentumának aránya a nukleáris magnetonhoz electron molar mass (Mₑ) elektron moláris tömeg (Mₑ) electron-muon magnetic moment ratio elektron-müon mágnesesmomentum-arány electron-muon mass ratio elektron-müon tömegarány electron-neutron magnetic moment ratio elektron-neutron mágnesesmomentum-arány electron-neutron mass ratio elektron-neutron tömegarány electron-proton magnetic moment ratio elektron-proton mágnesesmomentum-arány electron-proton mass ratio elektron-proton tömegarány electron relative atomic mass (Ar(e)) elektron relatív atomtömeg (Ar(e)) electron-tau mass ratio elektron-tau tömegarány electron to alpha particle mass ratio elektron és alfa-részecske tömegaránya electron to shielded helion magnetic moment ratio elektron és árnyékolt helion mágnesesmomentum-arány electron to shielded proton magnetic moment ratio elektron és árnyékolt proton mágnesesmomentum-arány electron-triton mass ratio elektron-triton tömegarány electron volt-atomic mass unit relationship elektronvolt–atomi tömegegység összefüggés electron volt-hartree relationship elektronvolt-hartree összefüggés electron volt-hertz relationship elektronvolt-hertz összefüggés electron volt-inverse meter relationship elektronvolt–reciprok méter összefüggés electron volt-joule relationship elektronvolt-joule összefüggés electron volt-kelvin relationship elektronvolt-kelvin összefüggés electron volt-kilogram relationship elektronvolt-kilogram összefüggés hartree-atomic mass unit relationship hartree–atomi tömegegység összefüggés hartree-electron volt relationship hartree-elektronvolt összefüggés muon Compton wavelength müon Compton-hullámhossza muon-electron mass ratio müon-elektron tömegarány muon g factor müon g-faktor muon magnetic moment müon mágneses momentum muon magnetic moment anomaly müon mágneses momentumának anomáliája muon magnetic moment to Bohr magneton ratio müon mágneses momentumának aránya a Bohr-magnetonhoz muon magnetic moment to nuclear magneton ratio müon mágneses momentumának aránya a nukleáris magnetonhoz muon mass müon tömege muon mass energy equivalent müon tömeg-energia egyenértéke muon mass energy equivalent in MeV müon tömeg-energia egyenértéke MeV-ben muon mass in u müon tömege u-ban muon molar mass müon moláris tömeg muon-neutron mass ratio müon-neutron tömegarány muon-proton magnetic moment ratio müon-proton mágnesesmomentum-arány muon-proton mass ratio müon-proton tömegarány muon-tau mass ratio müon-tau tömegarány reduced muon Compton wavelength müon redukált Compton-hullámhossza reduced tau Compton wavelength tau redukált Compton-hullámhossza tau Compton wavelength tau Compton-hullámhossza tau-electron mass ratio tau-elektron tömegarány tau mass tau tömege tau mass energy equivalent tau tömeg-energia egyenértéke tau mass in u tau tömege u-ban tau molar mass tau moláris tömeg tau-muon mass ratio tau-müon tömegarány tau-neutron mass ratio tau-neutron tömegarány tau-proton mass ratio tau-proton tömegarány proton charge to mass quotient proton töltés-tömeg hányados proton Compton wavelength proton Compton-hullámhossza proton-electron mass ratio proton-elektron tömegarány proton g factor (gₚ) proton g-faktor (gₚ) proton gyromagnetic ratio (γₚ) proton giromágneses arány (γₚ) proton gyromagnetic ratio in MHz/T proton giromágneses aránya MHz/T-ben proton magnetic moment (μₚ) proton mágneses momentum (μₚ) proton magnetic moment to Bohr magneton ratio proton mágneses momentumának aránya a Bohr-magnetonhoz proton magnetic moment to nuclear magneton ratio proton mágneses momentumának aránya a nukleáris magnetonhoz proton magnetic shielding correction proton magnetic árnyékolási correction proton mass (mₚ) proton tömege (mₚ) proton mass energy equivalent proton tömeg-energia egyenértéke proton mass energy equivalent in MeV proton tömeg-energia egyenértéke MeV-ben proton mass in u proton tömege u-ban proton molar mass (Mₚ) proton moláris tömeg (Mₚ) proton-muon mass ratio proton-müon tömegarány proton-neutron magnetic moment ratio proton-neutron mágnesesmomentum-arány proton-neutron mass ratio proton-neutron tömegarány proton relative atomic mass (Ar(p)) proton relatív atomtömeg (Ar(p)) proton rms charge radius proton négyzetes közép töltéssugár proton-tau mass ratio proton-tau tömegarány reduced proton Compton wavelength proton redukált Compton-hullámhossza shielded proton gyromagnetic ratio árnyékolt proton giromágneses arány shielded proton gyromagnetic ratio in MHz/T árnyékolt proton giromágneses aránya MHz/T-ben shielded proton magnetic moment árnyékolt proton mágneses momentum shielded proton magnetic moment to Bohr magneton ratio árnyékolt proton mágneses momentumának aránya a Bohr-magnetonhoz shielded proton magnetic moment to nuclear magneton ratio árnyékolt proton mágneses momentumának aránya a nukleáris magnetonhoz neutron Compton wavelength neutron Compton-hullámhossza neutron-electron magnetic moment ratio neutron-elektron mágnesesmomentum-arány neutron-electron mass ratio neutron-elektron tömegarány neutron g factor (gâ‚™) neutron g-faktor (gâ‚™) neutron gyromagnetic ratio (γₙ) neutron giromágneses arány (γₙ) neutron gyromagnetic ratio in MHz/T neutron giromágneses aránya MHz/T-ben neutron magnetic moment (μₙ) neutron mágneses momentum (μₙ) neutron magnetic moment to Bohr magneton ratio neutron mágneses momentumának aránya a Bohr-magnetonhoz neutron magnetic moment to nuclear magneton ratio neutron mágneses momentumának aránya a nukleáris magnetonhoz neutron mass (mâ‚™) neutron tömege (mâ‚™) neutron mass energy equivalent neutron tömeg-energia egyenértéke neutron mass energy equivalent in MeV neutron tömeg-energia egyenértéke MeV-ben neutron mass in u neutron tömege u-ban neutron molar mass (Mâ‚™) neutron moláris tömeg (Mâ‚™) neutron-muon mass ratio neutron-müon tömegarány neutron-proton magnetic moment ratio neutron-proton mágnesesmomentum-arány neutron-proton mass difference neutron-proton tömegkülönbség neutron-proton mass difference energy equivalent neutron-proton tömegkülönbség energia-egyenértéke neutron-proton mass difference energy equivalent in MeV neutron-proton tömegkülönbség energia-egyenértéke MeV-ben neutron-proton mass difference in u neutron-proton tömegkülönbség u-ban neutron-proton mass ratio neutron-proton tömegarány neutron relative atomic mass (Ar(n)) neutron relatív atomtömeg (Ar(n)) neutron-tau mass ratio neutron-tau tömegarány neutron to shielded proton magnetic moment ratio neutron és árnyékolt proton mágnesesmomentum-arány reduced neutron Compton wavelength neutron redukált Compton-hullámhossza deuteron-electron magnetic moment ratio deuteron-elektron mágnesesmomentum-arány deuteron-electron mass ratio deuteron-elektron tömegarány deuteron g factor deuteron g-faktor deuteron magnetic moment deuteron mágneses momentum deuteron magnetic moment to Bohr magneton ratio deuteron mágneses momentumának aránya a Bohr-magnetonhoz deuteron magnetic moment to nuclear magneton ratio deuteron mágneses momentumának aránya a nukleáris magnetonhoz deuteron mass deuteron tömege deuteron mass energy equivalent deuteron tömeg-energia egyenértéke deuteron mass energy equivalent in MeV deuteron tömeg-energia egyenértéke MeV-ben deuteron mass in u deuteron tömege u-ban deuteron molar mass deuteron moláris tömeg deuteron-neutron magnetic moment ratio deuteron-neutron mágnesesmomentum-arány deuteron-proton magnetic moment ratio deuteron-proton mágnesesmomentum-arány deuteron-proton mass ratio deuteron-proton tömegarány deuteron relative atomic mass (Ar(d)) deuteron relatív atomtömeg (Ar(d)) deuteron rms charge radius deuteron négyzetes közép töltéssugár triton-electron mass ratio triton-elektron tömegarány triton g factor (gₜ) triton g-faktor (gₜ) triton magnetic moment (μₜ) triton mágneses momentum (μₜ) triton magnetic moment to Bohr magneton ratio triton mágneses momentumának aránya a Bohr-magnetonhoz triton magnetic moment to nuclear magneton ratio triton mágneses momentumának aránya a nukleáris magnetonhoz triton mass (mₜ) triton tömege (mₜ) triton mass energy equivalent triton tömeg-energia egyenértéke triton mass energy equivalent in MeV triton tömeg-energia egyenértéke MeV-ben triton mass in u triton tömege u-ban triton molar mass (Mₜ) triton moláris tömeg (Mₜ) triton-proton mass ratio triton-proton tömegarány triton relative atomic mass (Ar(t)) triton relatív atomtömeg (Ar(t)) triton to proton magnetic moment ratio triton és proton mágnesesmomentum-arány helion-electron mass ratio helion-elektron tömegarány helion g factor (gâ‚•) helion g-faktor (gâ‚•) helion magnetic moment (μₕ) helion mágneses momentum (μₕ) helion magnetic moment to Bohr magneton ratio helion mágneses momentumának aránya a Bohr-magnetonhoz helion magnetic moment to nuclear magneton ratio helion mágneses momentumának aránya a nukleáris magnetonhoz helion mass (mâ‚•) helion tömege (mâ‚•) helion mass energy equivalent helion tömeg-energia egyenértéke helion mass energy equivalent in MeV helion tömeg-energia egyenértéke MeV-ben helion mass in u helion tömege u-ban helion molar mass (Mâ‚•) helion moláris tömeg (Mâ‚•) helion-proton mass ratio helion-proton tömegarány helion relative atomic mass (Ar(h)) helion relatív atomtömeg (Ar(h)) helion shielding shift helion árnyékolási shift shielded helion gyromagnetic ratio árnyékolt helion giromágneses arány shielded helion gyromagnetic ratio in MHz/T árnyékolt helion giromágneses aránya MHz/T-ben shielded helion magnetic moment árnyékolt helion mágneses momentum shielded helion magnetic moment to Bohr magneton ratio árnyékolt helion mágneses momentumának aránya a Bohr-magnetonhoz shielded helion magnetic moment to nuclear magneton ratio árnyékolt helion mágneses momentumának aránya a nukleáris magnetonhoz shielded helion to proton magnetic moment ratio árnyékolt helion és proton mágnesesmomentum-arány shielded helion to shielded proton magnetic moment ratio árnyékolt helion és árnyékolt proton mágnesesmomentum-arány alpha particle mass alfa-részecske tömege alpha particle mass in u alfa-részecske tömege u-ban alpha particle mass energy equivalent alfa-részecske tömeg-energia egyenértéke alpha particle mass energy equivalent in MeV alfa-részecske tömeg-energia egyenértéke MeV-ben alpha particle-electron mass ratio alfa-részecske-elektron tömegarány alpha particle-proton mass ratio alfa-részecske-proton tömegarány alpha particle rms charge radius alfa-részecske négyzetes közép töltéssugár alpha particle molar mass alfa-részecske moláris tömeg alpha particle relative atomic mass (Ar(α)) alfa-részecske relatív atomtömeg (Ar(α)) atomic mass constant (mᵤ) atomi tömegállandó (mᵤ) Avogadro constant Avogadro-állandó Boltzmann constant (k) Boltzmann-állandó (k) Boltzmann constant in eV/K Boltzmann-állandó eV/K-ben Boltzmann constant in Hz/K Boltzmann-állandó Hz/K-ben Boltzmann constant in inverse meter per kelvin Boltzmann-állandó reciprok méter/kelvin egységben electron volt (eV) elektronvolt (eV) Faraday constant (F) Faraday-állandó (F) first radiation constant (câ‚�) first sugárzási állandó (câ‚�) first radiation constant for spectral radiance first sugárzási állandó for spectral radiance molar gas constant (R) moláris gázállandó (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Loschmidt-állandó (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Loschmidt-állandó (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molar Planck-állandó second radiation constant (câ‚‚) second sugárzási állandó (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Boltzmann-állandó (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ideális Si rácssíktávolsága (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atomi tömegállandó energia-egyenértéke atomic mass constant energy equivalent in MeV atomi tömegállandó energia-egyenértéke MeV-ben atomic mass unit-electron volt relationship atomi tömegegység–elektronvolt összefüggés molar mass constant (Mᵤ) moláris tömeg constant (Mᵤ) molar mass of carbon-12 szén-12 moláris tömege molar volume of ideal gas (273.15 K, 100 kPa) ideális gáz moláris térfogata (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ideális gáz moláris térfogata (273.15 K, 101.325 kPa) molar volume of silicon szilícium moláris térfogata Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode-állandó (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode-állandó (1 K, 101.325 kPa) Wien frequency displacement law constant Wien-féle frekvencia-eltolódási törvény állandója Wien wavelength displacement law constant Wien-féle hullámhossz-eltolódási törvény állandója standard atmosphere (atm) standard atmoszféra (atm) standard-state pressure (p°) standardállapotú nyomás (p°) Angstrom star (Ã…*) Angström-csillag (Ã…*) Copper x unit réz x-egység Molybdenum x unit molibdén x-egység atomic unit of magnetizability atomi egység: mágnesezhetÅ‘ség atomic unit of mass (mâ‚‘) atomi egység: tömeg (mâ‚‘) atomic unit of momentum atomi egység: impulzus atomic unit of permittivity atomi egység: permittivitás atomic unit of time atomi egység: idÅ‘ atomic unit of velocity atomi egység: sebesség hartree-hertz relationship hartree-hertz összefüggés hartree-inverse meter relationship hartree–reciprok méter összefüggés hartree-joule relationship hartree-joule összefüggés hartree-kelvin relationship hartree-kelvin összefüggés hartree-kilogram relationship hartree-kilogram összefüggés shielding difference of d and p in HD d és p árnyékolási különbsége HD-ben shielding difference of t and p in HT t és p árnyékolási különbsége HT-ben pi (Ï€) pí (Ï€) Euler's number (e) Euler-szám (e) golden ratio (φ) aranymetszés (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni-állandó (γ) nominal solar radius névleges napsugár nominal solar total irradiance névleges teljes napsugárzás nominal solar luminosity névleges napluminozitás nominal solar effective temperature névleges effektív naphÅ‘mérséklet nominal solar mass parameter névleges naptömeg-paraméter nominal terrestrial equatorial radius névleges földi egyenlítÅ‘i sugár nominal terrestrial polar radius névleges földi pólussugár nominal terrestrial mass parameter névleges földtömeg-paraméter nominal jovian equatorial radius névleges jupiteri egyenlítÅ‘i sugár nominal jovian polar radius névleges jupiteri pólussugár nominal jovian mass parameter névleges jupitertömeg-paraméter average value of one minus the rate of TCG relative to TCB egy mínusz a TCG TCB-hez viszonyított arányának átlagértéke solar mass parameter (TCB-compatible) naptömeg-paraméter (TCB-kompatibilis) solar mass parameter (TDB-compatible) naptömeg-paraméter (TDB-kompatibilis) equatorial radius of the Earth (TT-compatible) a Föld egyenlítÅ‘i sugara (TT-kompatibilis) dynamical form factor of the Earth a Föld dinamikai alaktényezÅ‘je time rate of change in the dynamical form factor of the Earth a Föld dinamikai alaktényezÅ‘jének idÅ‘beli változási üteme geocentric gravitational constant (TCB-compatible) geocentrikus gravitációs állandó (TCB-kompatibilis) geocentric gravitational constant (TT-compatible) geocentrikus gravitációs állandó (TT-kompatibilis) geocentric gravitational constant (TDB-compatible) geocentrikus gravitációs állandó (TDB-kompatibilis) potential of the geoid geoid potenciálja nominal mean angular velocity of the Earth (TT-compatible) a Föld névleges közepes szögsebessége (TT-kompatibilis) ratio mass of the Moon to the Earth a Hold és a Föld tömegének aránya ratio of the mass of the Sun to Mercury a Nap tömegének aránya a Merkúréhoz ratio of the mass of the Sun to Venus a Nap tömegének aránya a Vénuszéhoz ratio of the mass of the Sun to Mars a Nap tömegének aránya a Marséhoz ratio of the mass of the Sun to Jupiter a Nap tömegének aránya a Jupiteréhez ratio of the mass of the Sun to Saturn a Nap tömegének aránya a Szaturnuszéhoz ratio of the mass of the Sun to Uranus a Nap tömegének aránya az Uránuszéhoz ratio of the mass of the Sun to Neptune a Nap tömegének aránya a Neptunuszéhoz ratio of the mass of the Sun to (134340) Pluto a Nap tömegének aránya a (134340) Pluto tömegéhez ratio of the mass of the Sun to (136199) Eris a Nap tömegének aránya a (136199) Eris tömegéhez ratio of the mass of (1) Ceres to the Sun a (1) Ceres tömegének aránya a Napéhoz ratio of the mass of (2) Pallas to the Sun a (2) Pallas tömegének aránya a Napéhoz ratio of the mass of (4) Vesta to the Sun a (4) Vesta tömegének aránya a Napéhoz mean obliquity of the ecliptic at J2000.0 az ekliptika közepes ferdesége J2000.0 idÅ‘pontban Electromagnetic Elektromágnesesség Compton wavelength Compton hullámhossz Astronomy Csillagászat ConstantsWidget Domain Tartomány Subdomain Altartomány No match found Nincs találat Name Név Value Érték Unit Egység Search Keresés All Mind CustomKeypadDialog Custom Keypad Egyéni billentyűzet Rows: Sorok: Columns: Oszlopok: Copy preset: ElÅ‘beállítás másolása: Basic Alap Scientific (wide) Tudományos (széles) Scientific (narrow) Tudományos (keskeny) Apply Alkalmaz Row Sor Column Oszlop Label Címke Behavior Viselkedés Text Szöveg DiagnosticsDialog App Diagnostics Alkalmazásdiagnosztika Copy to Clipboard Másolás a vágólapra Editor Unit Mértékegység User unit Felhasználói egység User function Felhasználói föggvény Argument Argumentum Current result:<br/>%1 Aktuális eredmény:<br/>%1 Selection result:<br/>%1 Kijelölés eredménye:<br/>%1 Selection result: n/a Kiválasztott eredmény: n/a Selection result: %1 Kiválasztott eredmény: %1 second másodperc metre méter kilogram kilogramm mole mól radian radián steradian szteradián degree Celsius Celsius-fok cubic metre köbméter cubic millimetre köbmilliméter cubic centimetre köbcentiméter cubic decimetre köbdeciméter cubic kilometre köbkilométer square millimetre négyzetmilliméter square kilometre négyzetkilométer square metre négyzetméter minute perc hour óra day nap astronomical unit csillagászati egység degree fok arcminute ívperc arcsecond ívmásodperc milliarcsecond milliívmásodperc microarcsecond mikroívmásodperc hectare hektár litre liter tonne tonna Dalton dalton electronvolt elektronvolt Angstrom Ã¥ngström atmosphere atmoszféra atomic mass unit atomi tömegegység British thermal unit brit hÅ‘egység calorie kalória carat karát cup csésze cup (Imperial) csésze (brit) cup (Japanese) csésze (japán) cup (US) csésze (USA) degree Fahrenheit Fahrenheit-fok fathom öl fluid ounce (Imperial) folyadékuncia (brit) fluid ounce (US) folyadékuncia (USA) fluid dram (Imperial) folyadékdram (brit) fluid dram (US) folyadékdram (USA) foot láb square foot négyzetláb cubic foot köbláb gallon (Imperial) gallon (brit) gallon (US) gallon (USA) gill (Imperial) gill (brit) gill (US) gill (USA) gradian gradián grain grain gram gramm Hartley hartley Hartree energy unit Hartree-energiaegység horsepower lóerÅ‘ inch hüvelyk square inch négyzethüvelyk cubic inch köbhüvelyk karat karát knot csomó lightminute fényperc lightsecond fénymásodperc lightyear fényév long ton hosszú tonna mile mérföld square mile négyzetmérföld cubic mile köbmérföld mile per hour mérföld/óra kilometre per hour kilométer/óra nautical mile tengeri mérföld ounce uncia parsec parszek pint (Imperial) pint (brit) pint (US) pint (USA) pound font pounds per square inch font/négyzethüvelyk quart (Imperial) quart (brit) quart (US) quart (USA) oil barrel olajhordó beer barrel (US) söröshordó (USA) square yard négyzetyard cubic yard köbyard short ton rövid tonna tablespoon evÅ‘kanál tablespoon (Australian) evÅ‘kanál (ausztrál) tablespoon (Imperial) evÅ‘kanál (brit) tablespoon (US) evÅ‘kanál (USA) dessert spoon desszertkanál teaspoon teáskanál teaspoon (Imperial) teáskanál (brit) teaspoon (US) teáskanál (USA) turn fordulat revolution körülfordulás revolution per minute fordulat/perc week hét kilowatt hour kilowattóra millimetre of mercury higanymilliméter yard yard Julian century Julián évszázad Julian year Julián év sidereal year sziderikus év tropical year tropikus év Evaluator invalid expression Érvénytelen egyenlet division by zero Nullával nem osztunk too time consuming - computation was rejected túlságosan idÅ‘igényes - a számítást elutasítottuk dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimenziók különbözÅ‘sége - mennyiságek eltérÅ‘ dimenzióval nem hasonlíthatók, adhatók össze. invalid dimension - operation might require dimensionless arguments helytelen dimenzió - a művelet dimenziómentes argumentumokat kíván Computation aborted - encountered numerical instability Számítás megszakítva - numerikus instabilitással találkoztam invalid dimension - function might require dimensionless arguments helytelen dimenzió - a függvény dimenziómentes argumentumokat kíván error hiba unit must not be zero az egység nem lehet nulla Conversion failed - dimension mismatch Konvertálás sikertelen - dimenziók nem egyeznek unknown function or variable Ismeretlen függvény vagy változó recursion not supported rekurzió nem támogatott cannot operate on a NaN Csak számértéket fogad el underflow - tiny result is out of SpeedCrunch's number range túlcsordulás - túl kis eredmény kívül a SpeedCrunch határain overflow - huge result is out of SpeedCrunch's number range túlcsordulás - túl nagy eredmény kívül a SpeedCrunch határain overflow - logic result exceeds maximum of 256 bits túlcsordulás - a logikai eredmény túlépi a 256 bitet overflow - integer result exceeds maximum limit for integers túlcsordulás - az egész eredmény túllépi a maximumot operation is not defined for these arguments a művelet nincs definiálva ezekre az argumentumokra wrong number of arguments argumentumok száma nem megfelelÅ‘ does not take NaN as an argument Csak számérték lehet a változó result out of range tartományon kívüli eredmény undefined for argument domain nem értelmezett argumentum tartományra computation too expensive túl nagy számításigény internal error, please report a bug belsÅ‘ hiba, kérem küldjön hibajelentést syntax error szintaktikai hiba conversion target must be a unit az átváltási cél mértékegység kell legyen unknown unit ismeretlen mértékegység %1 is a reserved name, please choose another %1 név foglalt, kérem válasszon másikat %1 is a global user definition and cannot be overridden in this session. %1 globális felhasználói definíció, és ebben a munkamenetben nem írható felül. %1 is a variable name, please choose another or delete the variable %1 egy változó neve, kérem válasszon másikat, vagy törölje a változót argument %1 is used more than once %1 argumentum egynél többször van használatban %1 is a built-in unit name, please choose another %1 beépített egységnév, válasszon másikat %1 is a user function name, please choose another or delete the function %1 egy felhasználói függvény neve, kérem válasszon másikat, vagy törölje a függvényt FunctionRepo max; trials; probability max; kísérletek; valószínűség trials; probability kísérletek; valószínűség hits; trials; probability találatok; kísérletek; valószínűség max; total; hits; trials max; össz; találatok; kísérletek total; hits; trials össz; találat; kísérletek count; total; hits; trials darab; össz; találatok; kísérletek dividend; divisor osztandó; osztó x; exponent_bits; significand_bits [; exponent_bias] x; kitevÅ‘_bitek; mantissza_bitek [; kitevÅ‘_eltolás] base; x alap; x value; modulo érték; modulo base; exponent; modulo alap; kitevÅ‘; modulo events; average_events események; átlagos_események average_events átlagos_események x [; precision] x [; pontosság] Absolute Value Abszolútérték Absolute Deviation Abszolút eltérés Arc Cosine Arkuszkoszinusz Logical AND Logikai ÉS Area Hyperbolic Cosine Area hiperbolikus koszinusz Area Hyperbolic Sine Area hiperbolikus szinusz Area Hyperbolic Tangent Area hiperbolikus tangens Arc Sine Arkuszszinusz Arc Tangent Arkusztangens Arc Tangent with two Arguments Arkusz tangens két argumentummal Average (Arithmetic Mean) Ã�tlag (számtani közép) Binomial Cumulative Distribution Function Binomiális eloszlásfüggvény Binomial Distribution Mean Binomiális eloszlás átlaga Binomial Probability Mass Function Binomiális valószínűségi tömegfüggvény Binomial Distribution Variance Binomiális eloszlás varianciája Cube Root Köbgyök Complex Conjugate Komplex konjugált Cosine Koszinusz Hyperbolic Cosine Hiperbolikus koszinusz Cotangent Kotangens Cosecant Koszekáns Convert Unix timestamp to Date Unix idÅ‘bélyeg átalakítása dátummá Degrees of Arc Szög fokokban Error Function Hibafüggvény Complementary Error Function Komplementer hibafüggvény Exponential Exponenciális Fractional Part Törtrész Extension of Factorials [= (x-1)!] Faktoriálisok kifejtése [= (x-1)!] Greatest Common Divisor Legnagyobb közös osztó Geometric Mean Geometriai közép Gradians of arc Ã�vgradián Hypergeometric Cumulative Distribution Function Hipergeometriai eloszlásfüggvény Hypergeometric Distribution Mean Hipergeometriai eloszlás átlaga Hypergeometric Probability Mass Function Hipergeometrikus valószínűségi tömegfüggvény Hypergeometric Distribution Variance Hipergeometriai eloszlás varianciája Integer Quotient egész hányados Integer Part egész rész Imaginary Part Képzetes rész Decode IEEE-754 Binary Value IEEE-754 bináris érték dekódolása Encode IEEE-754 Binary Value IEEE-754 bináris érték kódolása Decode 16-bit Half-Precision Value 16 bites félpontosságú érték dekódolása Encode 16-bit Half-Precision Value 16 bites félpontosságú érték kódolása Decode 32-bit Single-Precision Value 32 bites egyszeres pontosságú érték dekódolása Encode 32-bit Single-Precision Value 32 bites egyszeres pontosságú érték kódolása Decode 64-bit Double-Precision Value 64 bites dupla pontosságú érték dekódolása Encode 64-bit Double-Precision Value 64 bites dupla pontosságú érték kódolása Decode 128-bit Quad-Precision Value 128 bites négyszeres pontosságú érték dekódolása Encode 128-bit Quad-Precision Value 128 bites négyszeres pontosságú érték kódolása Binary Logarithm 2-es alapú logaritmus Common Logarithm 10-es alapú logaritmus Natural Logarithm Természetes logaritmus Logarithm to Arbitrary Base TetszÅ‘leges alapú logaritmus Mask to a bit size Maszkolás adott bitszélességre Maximum Maximum Median Value (50th Percentile) Medián Minimum Minimum Modulo Modulo Euclidean Modulo Euklideszi modulo Modular Exponentiation Moduláris hatványozás Combination (Binomial Coefficient) Binomiális együttható Logical NOT Logikai NEM Permutation (Arrangement) Permutáció (rendezés) Convert to Binary Representation Bináris számrendszerbe Arithmetic Aritmetika Chemistry Kémia Complex Komplex Combinatorics Kombinatorika Probability Valószínűség Statistics Statisztika Aggregation Összesítés Random Véletlen Base conversion Számrendszer-átváltás Number formatting Számformázás Integer arithmetic Egész aritmetika Special functions Speciális függvények Exponential & Logarithmic Exponenciális és logaritmikus Angle conversion Szögátváltás Trigonometry Trigonometria Bitwise Bitenkénti Floating point LebegÅ‘pontos Date & Time Dátum és idÅ‘ Linear algebra Lineáris algebra unix_timestamp; x hours offset to GMT unix_timestamp; x óra eltérés a GMT-hez képest yyyymmdd.hhmmss; x hours offset to GMT ééééhhnn.óóppmm; x óra eltolás GMT-hez képest [digits] [számjegyek] max [; min] max [; min] List Literal Lista literál Convert to Padded Binary Representation Ã�talakítás kitöltött bináris alakra Round Toward +∞ (Ceiling) Kerekítés +∞ felé (plafon) Cosine plus Imaginary Sine Koszinusz plusz imaginárius szinusz Convert to Cis Complex Form Ã�talakítás cis komplex alakra Matrix Column Count Mátrixoszlopok száma Population Correlation Matrix (n) Populációs korrelációs mátrix (n) Sample Correlation Matrix (n-1) Mintabeli korrelációs mátrix (n-1) Count Darab Population Covariance Matrix (n) Populációs kovarianciamátrix (n) Sample Covariance Matrix (n-1) Mintabeli kovarianciamátrix (n-1) Cross Product Vektoriális szorzat Convert Date to Unix timestamp Dátum átalakítása Unix idÅ‘bélyeggé Convert to Decimal Representation Decimális számrendszerbe Determinant Determináns Convert to Sexagesimal Notation Ã�talakítás hatvanas jelölésre Dot Product Skaláris szorzat Convert to Engineering Notation Ã�talakítás mérnöki jelölésre Convert to Exponential Complex Form Ã�talakítás exponenciális komplex alakra Round Toward −∞ (Floor) Kerekítés −∞ felé (padló) Flatten Matrix Mátrix lapítása Least Common Multiple Legkisebb közös többszörös Convert to Hexadecimal Representation Hexadecimális számrendszerbe Convert to Padded Hexadecimal Representation Ã�talakítás kitöltött hexadecimális alakra Inverse Matrix Inverz mátrix Round to 16-bit Half-Precision Value Kerekítés 16 bites félpontosságú értékre Round to 32-bit Single-Precision Value Kerekítés 32 bites egyszeres pontosságú értékre Round to 64-bit Double-Precision Value Kerekítés 64 bites dupla pontosságú értékre Round to 128-bit Quad-Precision Value Kerekítés 128 bites négyszeres pontosságú értékre Residual from 16-bit Half-Precision Rounding Maradék 16 bites félpontosságú kerekítésbÅ‘l Residual from 32-bit Single-Precision Rounding Maradék 32 bites egyszeres pontosságú kerekítésbÅ‘l Residual from 64-bit Double-Precision Rounding Maradék 64 bites dupla pontosságú kerekítésbÅ‘l Residual from 128-bit Quad-Precision Rounding Maradék 128 bites négyszeres pontosságú kerekítésbÅ‘l Substance Mass Anyagtömeg Molarity Molaritás Molar Mass Moláris tömeg Median Absolute Deviation Medián abszolút eltérés Mean Ã�tlag Numerical Value of Quantity Mennyiség numerikus értéke Random Decimal Number Véletlen decimális szám Random Integer Number Véletlen egész szám Convert to Rational Representation Ã�talakítás racionális alakra Convert to Octal Representation Oktális számrendszerbe Convert to Padded Octal Representation Ã�talakítás kitöltött oktális alakra Vector or Matrix Norm Vektor- vagy mátrixnorma Logical OR Logikai VAGY Population Count (Hamming Weight) Bitek száma (Hamming-súly) Phase of Complex Number Komplex szám fázisszöge Poissonian Cumulative Distribution Function Poisson-eloszlás eloszlásfüggvénye Poissonian Distribution Mean Poisson-eloszlás átlaga Poissonian Probability Mass Function Poisson valószínűségi tömegfüggvény Poissonian Distribution Variance Poisson-eloszlás varianciája Convert to Phasor Complex Form Ã�talakítás fázor komplex alakra Convert to Rectangular Complex Form Ã�talakítás derékszögű komplex alakra Round Half Away from Zero Fél érték kerekítése nullától el Round Half Even Fél érték kerekítése párosra Nth Root N-edik gyök Convert to Scientific Notation Ã�talakítás tudományos jelölésre Matrix Row Count Mátrixsorok száma List or Matrix Shape Lista vagy mátrix alakja Summation Összegzés Population Standard Deviation (n) Populációs szórás (n) Sample Standard Deviation (n-1) Mintabeli szórás (n-1) Round Toward Zero (Truncation) Kerekítés nulla felé (csonkítás) Matrix Trace Mátrix nyoma Transpose Matrix Mátrix transzponálása Population Variance (n) Populációs variancia (n) Sample Variance (n-1) Mintabeli variancia (n-1) Product Szorzat Radians Radián Matrix Rank Mátrix rangja Real Part Valós rész Secant Szekáns Arithmetic Shift Left Aritmetikai eltolás balra Arithmetic Shift Right Aritmetikai eltolás jobbra Signum ElÅ‘jel Sine Szinusz Hyperbolic Sine Hiperbolikus szinusz Square Root Négyzetgyök Sum Összeg Tangent Tangens Convert to Trigonometric Complex Form Ã�talakítás trigonometrikus komplex alakra Turns Fordulatok Hyperbolic Tangent Hiperbolikus tangens Sign-extend a value Érték elÅ‘jellel való kiegészítése Logical XOR Logikai kizáró VAGY (XOR) FunctionsWidget Domain Tartomány All Mind Name Név Search Keresés No match found Nincs találat Identifier Azonosító HistoryWidget Remove All Calculations Above Az összes fenti számítás eltávolítása Remove This Calculation Számítás eltávolítása Remove All Calculations Below Az összes lenti számítás eltávolítása Keypad Inverse cosine Arkusz koszinusz The last result Utolsó eredmény Inverse sine Arkusz szinusz Inverse tangent Arkusz tangens Evaluate expression Kifejezés kiértékelése Division Osztás Multiplication Szorzás Subtraction Kivonás Addition Összeadás Clear expression Kifejezés törlése Cosine Koszinusz Backspace Visszatörlés Scientific notation Tudományos jelölés Exponential Exponenciális függvény Factorial Faktoriális Natural logarithm Természetes logaritmus Left parenthesis Bal zárójel Nth root N-edik gyök Argument separator Argumentumelválasztó Square Négyzet Common logarithm Tízes alapú logaritmus Modulo Modulo Contextual percentage Kontextuális százalék Power Hatvány Right parenthesis Jobb zárójel Sine Szinusz Square root Négyzetgyök Tangent Tangens Pi Pí Decimal separator Tizedeselválasztó MainWindow Radian Radián Degree Fok Gradian Gradián Binary Bináris Octal Oktális Hexadecimal Hexadecimális Sexagesimal Szexageszimális Engineering decimal Mérnöki tizedes Scientific decimal Tudományos tizedes &Import... &Importálás... &Quit &Kilépés Clear E&xpression E&gyenlet törlése Clear &History ElÅ‘&zmények törlése &Copy &Másolás &Paste &Beillesztés &Select Expression &Egyenlet kiválasztása &Constants &Ã�llandók &Functions &Függvények &History &ElÅ‘zmények &Status Bar Ã�&llapotsor Bitfield BitmezÅ‘ Use&r Functions Felhasználói &függvények &Degree &Fok &Radian &Radián &Gradian &Gradián Re&volution &Körülfordulás Auto-Insert a&ns a&ns automatikus beszúrása Automatic &Completion Automatikus &Kiegészítés &Built-in Functions &Beépített függvények Built-in &Variables Beépített &változók User &Functions &Felhasználói függvények User Va&riables Fe&lhasználói változók Open a Private Tab on Startup Privát lap megnyitása indításkor Open and focus a new private tab whenever SpeedCrunch starts. Új privát lap megnyitása és aktiválása a SpeedCrunch minden indításakor. Syntax &Highlighting &Kiemelés és szintaktika Group Digits in &Input Bev&iteli számjegyek csoportosítása Automatic Input &Adjustments &Automatikus beviteli igazítások Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Az operátorok, térközök, zárójelek és hatványok automatikus igazítása, a bevitel korlátozása érvényes karakterekre. Group input digits using the selected number format. A beírt számjegyek csoportosítása a kiválasztott számformátum szerint. &Blinking Cursor &Villogó kurzor Blink the cursor in the expression editor. A kurzor villogtatása a kifejezésszerkesztÅ‘ben. &Escape Clears Editor &Escape törli a szerkesztÅ‘ tartalmát Clear the focused expression editor with Escape after dismissing any popup or preview. Az aktív kifejezésszerkesztÅ‘ tartalmának törlése az Escape billentyűvel a felugró ablakok és elÅ‘nézetek bezárása után. Keep Expression After Evaluation Kifejezés megtartása kiértékelés után Copy New Results Automatically Új eredmények automatikus másolása &Comma &VesszÅ‘ &System Default Rendszer &alapértelmezett &Dot &Pont Dot &And Comma Pont &és vesszÅ‘ Toward +∞ (&ceil) +∞ felé (&ceil) Toward −∞ (&floor) −∞ &felé (floor) &Binary &Bináris &Engineering &Mérnöki &Hexadecimal &Hexadecimális &Octal &Oktális &Scientific &Tudományos User &Manual Felhasználói &kézikönyv Issues and &Feedback &Hibák és visszajelzések &Donate &Adományozás &About SpeedCrunch A &SpeedCrunch névjegye App Diag&nostics Alkalmazásdiag&nosztika S&plit Fel&osztás Angle &Mode S&zögmód &Complex Form &Komplex alak New Tab Új lap Constants Konstansok Functions Függvények History ElÅ‘zmények User Functions Felhasználói függvények &Font... &Betűtípus &Language... &Nyelv... &Session &Munkamenet &Edit &Szerkesztés &View &Nézet Se&ttings &Beállítások &Decimal &Decimális &Keypad &Numerikus billentyűzet Always on &Top &Mindig felül Disabled Letiltva Small Space Rövid szóköz Medium Space Közepes szóköz Large Space Nagy szóköz &0 Digits &0 tizedesig &15 Digits &15 tizedesig &2 Digits &2 tizedesig &3 Digits &3 tizedesig &50 Digits &50 tizedesig &8 Digits &8 tizedesig &Sexagesimal &Szexageszimális Reset All Settings... Minden beállítás visszaállítása... &System Rend&szer SpeedCrunch &Theme SpeedCrunch-&téma &Classic &Klasszikus &Modern &Modern Context Help Környezetérzékeny segítség &Help &Segítség Error Hiba Can't read from file %1 Nem tudom beolvasni a fájlt: %1 Import Session Munkamenet importálása Close Session Munkamenet bezárása Angle Mode: Szögmód: Notation: Jelölés: Precision: Pontosság: Turn Fordulat Revolution Körülfordulás Fixed-point decimal Fixpontos decimális Rational Racionális Automatic decimal Automatikus decimális Automatic Automatikus User &Definitions... Felhasználói &definíciók... New &Tab Új &lap New &Private Tab Új &privát lap Keep Megtartás Make Private... Priváttá tétel... New &Window Új &ablak &Open... &Megnyitás... &Rename... &Ã�tnevezés... Clo&ne... Kló&nozás... &Close Tab Lap &bezárása Reopen Clo&sed Tab Bezárt lap újranyitá&sa Open Sessions &Folder Munkamenetek &mappájának megnyitása &Undo &Visszavonás &Redo Új&ra Cu&t &Kivágás Copy &Last Result Uto&lsó eredmény másolása &Wrap in Parentheses Z&árójelbe foglalás Full Scr&een Mode Tel&jes képernyÅ‘s mód &Basic &Alap &Scientific (wide) &Tudományos (széles) Scientific (narrow) Tudományos (keskeny) &Custom... &Egyéni... Main &Menu FÅ‘ &menü User &Variables Felhasználói &változók &Left Ba&lra &Right Jobb&ra &Up &Fel &Down L&e Close Pa&ne &Panel bezárása User &Units Felhasználói &egységek &Turn &Fordulat If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Ha egy új kifejezés +, -, * vagy / jellel kezdÅ‘dik, a SpeedCrunch elÅ‘ször beszúrja az „ansâ€�-t. &Accept with Enter Elf&ogadás Enterrel Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Az automatikus kiegészítés aktuális javaslatának elfogadása Enterrel, a nyílbillentyűkkel történÅ‘ elÅ‘zetes kiválasztás nélkül. &Units &Egységek Show Live Result &Preview ÉlÅ‘ eredmény-&elÅ‘nézet megjelenítése Save &Window Position on Exit &Ablakpozíció mentése kilépéskor Hover Highlighting Kiemelés rámutatáskor Group Integer Part Only Csak az egész rész csoportosítása Number Format... Számformátum... Notation && Precision... Jelölés és pontosság... After pressing Enter, keep the entered expression selected in the editor. Az Enter megnyomása után a megadott kifejezés kijelölve marad a szerkesztÅ‘ben. Never Soha Always Mindig Only for Single-Line Expressions Csak egysoros kifejezéseknél Simplify Displayed Expressions Megjelenített kifejezések egyszerűsítése History Size &Limit... ElÅ‘zmények méret&korlátja... Remove Trailing &Zeroes &Záró nullák eltávolítása Nearest, Half &Away (round) Legközelebbi, fél &távolabb (round) Nearest, Half &Even (roundeven) Legközelebbi, fél &páros (roundeven) Toward &Zero (trunc) &Nulla felé (trunc) &Fixed-Point &Fixpontos &Rational &Racionális &Exponential (m·sâ�»Â¹) &Exponenciális (m·sâ�»Â¹) &Fractional (m/s) &Tört (m/s) &Rectangular (a + bi) &Derékszögű (a + bi) Exponential (reâ�±á¶¿) Exponenciális (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrikus (r(cos θ + i·sin θ)) Phasor (r∠θ) Fázor (r∠θ) &Theme... &Téma... Check for &Updates &Frissítések keresése Source Code Forráskód &Zoom &Nagyítás &Results &Eredmények Unit Notation Egységjelölés Rounding Mode Kerekítési mód &Notation &Jelölés &Imaginary Unit &Imaginárius egység &Window &Ablak &Editing &Szerkesztés A&utocomplete A&utomatikus kiegészítés Up/Down Arrow History Fel/le nyilas elÅ‘zmények &Appearance &Megjelenés &Menus &Menük &Docks &Dokkolható panelek &Input and Results Bev&itel és eredmények &Disabled &Letiltva &Disable &Letiltás Close preview ElÅ‘nézet bezárása Rename... Ã�tnevezés... Clone... Klónozás... Close Tab Lap bezárása New Private Tab Új privát lap Open... Megnyitás... Reopen Closed Tab Bezárt lap újranyitása Split Felosztás Left Balra Right Jobbra Up Fel Down Le Clear Törlés Delete Törlés %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Privát munkamenet: a tartalom bezáráskor elvész. Válassza a Munkamenet > Megtartás menüpontot a szokásos munkamenetté alakításhoz. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privát] Reset All Settings Minden beállítás visszaállítása Reset all settings to their default values? Visszaállítja az összes beállítást az alapértékre? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Ez a megjelenést, a szerkesztést, az eredményformátumokat és az ablakbeállításokat érinti. A számítások, a nyitott munkamenetek és a felhasználói definíciók megmaradnak. The settings file could not be written. Nem sikerült írni a beállításfájlt. Clear this session's calculations, unfinished expression, variables, functions, and units? Törli a munkamenet számításait, befejezetlen kifejezését, változóit, függvényeit és mértékegységeit? Global user definitions are kept. A globális felhasználói definíciók megmaradnak. Make Session Private Munkamenet priváttá tétele The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. A mentett %1 munkamenet törlÅ‘dik. Tartalma egy privát munkamenetben nyitva marad, és a munkamenet bezárásakor vagy a SpeedCrunch leállításakor elvész. Make Private Priváttá tétel Could not delete the saved session %1. Nem sikerült törölni a mentett %1 munkamenetet. Keep Session Munkamenet megtartása Could not save the session. It remains private. Nem sikerült menteni a munkamenetet. Privát marad. Clone Session Munkamenet klónozása Could not save session file %1. Nem sikerült menteni a(z) %1 munkamenetfájlt. Could not delete session file %1. Nem sikerült törölni a(z) %1 munkamenetfájlt. JSON file (*.json);;Any file (*.*) JSON-fájl (*.json);;Bármely fájl (*.*) Export session as JSON Munkamenet exportálása JSON-be The selected file is not valid JSON: %1 A kiválasztott fájl nem érvényes JSON: %1 The selected file is not a SpeedCrunch session JSON file. A kiválasztott fájl nem SpeedCrunch-munkamenet JSON-fájlja. This file uses an obsolete SpeedCrunch session format and cannot be imported. Ez a fájl elavult SpeedCrunch-munkamenetformátumot használ, ezért nem importálható. The selected JSON file is missing the required $schema field. A kiválasztott JSON-fájlból hiányzik a kötelezÅ‘ $schema mezÅ‘. The selected JSON file uses an unsupported JSON schema: %1 A kiválasztott JSON-fájl nem támogatott JSON-sémát használ: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). A kiválasztott JSON-fájlból hiányzik a SpeedCrunch-munkamenetséma azonosítója ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 A kiválasztott JSON-fájl nem támogatott SpeedCrunch-munkamenetformátumot használ: %1 The selected JSON file is missing the required session name. A kiválasztott JSON-fájlból hiányzik a kötelezÅ‘ munkamenetnév. The selected JSON file has an empty session name. A kiválasztott JSON-fájl üres munkamenetnevet tartalmaz. The selected JSON file has invalid or incomplete SpeedCrunch session data. A kiválasztott JSON-fájl érvénytelen vagy hiányos SpeedCrunch-munkamenetadatokat tartalmaz. Open Sessions Folder Munkamenetek mappájának megnyitása Could not create the sessions folder: %1 Nem sikerült létrehozni a munkamenetek mappáját: %1 Could not open the sessions folder: %1 Nem sikerült megnyitni a munkamenetek mappáját: %1 Editor and Results Font A szerkesztÅ‘ és az eredmények betűtípusa Open Session Munkamenet megnyitása Community Közösség Rename Session Munkamenet átnevezése Clear Session Munkamenet törlése Delete Session Munkamenet törlése Close Pane Panel bezárása User Variables Felhasználói változók User Units Felhasználói egységek Clear History ElÅ‘zmények törlése Are you sure you want to clear the calculation history? Biztosan törölni szeretné a számítási elÅ‘zményeket? Session name: Munkamenet neve: A session named %1 already exists. Már létezik %1 nevű munkamenet. Could not create session file %1. Nem sikerült létrehozni a(z) %1 munkamenetfájlt. Could not write session file %1. Nem sikerült írni a(z) %1 munkamenetfájlt. Are you sure you want to delete this session? Biztosan törölni szeretné ezt a munkamenetet? Custom Precision Egyéni pontosság Fractional digits: Tizedesjegyek: Theme Téma Light Themes Világos témák Dark Themes Sötét témák Preview ElÅ‘nézet Colors Színek Select color for %1 Szín kiválasztása ehhez: %1 Import... Importálás... Export... Exportálás... Import Theme Téma importálása Theme file (*.json);;All files (*) Témafájl (*.json);;Minden fájl (*) Invalid theme file. Érvénytelen témafájl. Can't import theme "%1" because it conflicts with a built-in theme. Nem importálható a(z) „%1â€� téma, mert ütközik egy beépített témával. Can't find a writable theme folder. Nem található írható témamappa. Overwrite Theme Téma felülírása A custom theme named "%1" already exists. Do you want to overwrite it? Már létezik „%1â€� nevű egyéni téma. Felül szeretné írni? Can't overwrite theme file %1 Nem írható felül a(z) %1 témafájl Can't copy theme file to %1 Nem másolható a témafájl ide: %1 Export Theme Téma exportálása Can't export theme as "%1" because it conflicts with a built-in theme. Nem exportálható a téma „%1â€� néven, mert ütközik egy beépített témával. Can't write to file %1 Nem tudok ebbe a fájlba írni: %1 Global User Variable Globális felhasználói változó Global User Function Globális felhasználói függvény Global User Unit Globális felhasználói egység User Definitions Felhasználói definíciók These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Ezek a definíciók globálisak, és minden munkamenetbe betöltÅ‘dnek. A munkamenetekben nem módosíthatók, és felülírják a munkamenet-szerkesztÅ‘ azonos nevű definícióit. Soronként egy definíciót adjon meg. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Példák: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Alkalmaz Validate EllenÅ‘rzés Test Results Teszteredmények Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Importált változók: %1 Importált függvények: %2 Importált egységek: %3 Hibás sorok sorszámai: %4 none nincs Apply Results Alkalmazás eredményei User definitions saved. Felhasználói definíciók mentve. History Size Limit ElÅ‘zmények méretkorlátja Maximum number of history entries for this session (0 = unlimited): Az elÅ‘zménybejegyzések maximális száma ebben a munkamenetben (0 = korlátlan): Text file (*.txt);;Any file (*.*) Szövegfájl (*.txt);;Minden fájl (*.*) Could not recalculate from calculation %1: %2 Nem sikerült újraszámolni a(z) %1 számítástól: %2 History Size Limit Reached Elérte az elÅ‘zmények méretkorlátját This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Ez a számítás kitölti az utolsó elérhetÅ‘ elÅ‘zményhelyet. A további számítások eltávolítják a legrégebbi számítást az elÅ‘zményekbÅ‘l. A korlát a Munkamenet > ElÅ‘zmények méretkorlátja menüben növelhetÅ‘. Editing calculation. Press Esc twice to cancel. Számítás szerkesztése. A megszakításhoz nyomja meg kétszer az Esc billentyűt. Calculation Settings Számítási beállítások Invalid recalculation start index Érvénytelen újraszámítási kezdÅ‘index System Default Rendszer alapértelmezett Language Nyelv Select the language: Nyelv kiválasztása: Custom Egyéni Decimal places: Tizedesjegyek: &Automatic &Automatikus &Precision &Pontosság Plain &text E&gyszerű szöveg Formula &Book Függvény&táblázat &Export &Exportálás Export session as HTML Munkamenet exportálása HTML-be HTML file (*.html) HTML fájl (*.html) Export session as plain text Munkamenet exportálása szövegként ManualWindow SpeedCrunch Manual SpeedCrunch kézikönyv %1 - SpeedCrunch Manual %1 - SpeedCrunch kézikönyv NumberFormatDialog Number Format Számformátum <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Válassza ki az eredmények és a beviteli számjegycsoportosítás számformátumát.</b><br/><br/>Megjegyzés: a beírt számok egyértelmű formátumai akkor is elfogadhatók, ha eltérnek a kiválasztott megjelenítési formátumtól.<br/> QObject Global User Variable Globális felhasználói változó Global User Function Globális felhasználói függvény Global User Unit Globális felhasználói egység Backspace Visszatörlés Clear expression Kifejezés törlése Evaluate expression Kifejezés kiértékelése Insert text Szöveg beszúrása Automatic decimal Automatikus decimális Fixed-point decimal Fixpontos decimális Engineering decimal Mérnöki decimális Scientific decimal Tudományos decimális Rational Racionális Binary Bináris Octal Oktális Hexadecimal Hexadecimális Sexagesimal Hatvanas Update Available Frissítés érhetÅ‘ el A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Újabb verzió (%1) érhetÅ‘ el.<br/><a href="%2">A letöltéshez keresse fel a webhelyet.</a> Check for Updates Frissítések keresése SpeedCrunch %1 is up to date. A SpeedCrunch %1 naprakész. No connectivity. Please check your internet connection and try again. Nincs kapcsolat. EllenÅ‘rizze az internetkapcsolatot, és próbálja újra. Could not verify the latest available version. Nem sikerült ellenÅ‘rizni a legújabb elérhetÅ‘ verziót. ResultDisplay Scroll to bottom Görgetés alulra Edit Expression Kifejezés szerkesztése Change Settings Beállítások módosítása New Tab Új lap &Import... &Importálás... &Export &Exportálás Plain &text E&gyszerű szöveg Copy Másolás Selection Kijelölés Select All Összes kijelölése Expression Kifejezés Result Eredmény Calculation Számítás Calculation as Single Line Számítás egy sorban Remove Eltávolítás This Calculation Ez a számítás All Calculations Above Az összes számítás felette All Calculations Below Az összes számítás alatta New Private Tab Új privát lap Session Munkamenet Open... Megnyitás... Clone... Klónozás... Rename... Ã�tnevezés... Keep Megtartás Make Private... Priváttá tétel... Clear Törlés Delete Törlés Close Bezár Split Felosztás Left Balra Right Jobbra Up Fel Down Le Close Pane Panel bezárása Main Menu FÅ‘menü Cancel editing Szerkesztés megszakítása Copy result Eredmény másolása Edit expression Kifejezés szerkesztése Change settings Beállítások módosítása Remove calculation Számítás eltávolítása ResultSlotsDialog Notation & Precision Jelölés és pontosság Result Line Eredménysor Enabled Engedélyezve Notation Jelölés Decimal Places Tizedesjegyek Main Line FÅ‘sor Extra Line #1 1. extra sor Extra Line #2 2. extra sor Extra Line #3 3. extra sor Extra Line #4 4. extra sor Auto Automatikus UserFunctionListWidget Name Név Value Érték Description Leírás Search Keresés No match found Nincs találat Insert Beszúrás Edit Szerkesztés Delete Törlés Delete All Összes törlése UserUnitListWidget Name Név Value Érték Description Leírás Search Keresés No match found Nincs találat Insert Beszúrás Edit Szerkesztés Delete Törlés Delete All Összes törlése VariableListWidget Name Név Value Érték Description Leírás Search Keresés No match found Nincs találat Insert Beszúrás Edit Szerkesztés Delete Törlés Delete All Összes törlése heldercorreia-speedcrunch-e7ca37f/src/resources/locale/id.ts000066400000000000000000010437501526573132500243530ustar00rootroot00000000000000 AboutBox About SpeedCrunch Tentang SpeedCrunch Core developers Pengembang utama Original author Penulis asli Close Tutup Math engine Mesin matematika Main author | Logo | Maintainer Penulis utama | Logo | Pemelihara Thanks Terima kasih Copyright (C) 2004-2026 The SpeedCrunch developers Hak cipta (C) 2004-2026 para pengembang SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Program ini adalah perangkat lunak bebas; Anda dapat menyebarluaskannya dan/atau memodifikasinya di bawah ketentuan-ketentuan dari GNU General Public License seperti yang diterbitkan oleh Free Software Foundation; baik versi 2 dari Lisensi tersebut, atau (dengan pilihan Anda) versi lain yang lebih tinggi This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Program ini didistribusikan dengan harapan akan berguna, tetapi TANPA JAMINAN APA PUN; bahkan tanpa jaminan tersirat atas KELAYAKDAGANGAN atau KESESUAIAN UNTUK TUJUAN TERTENTU. Lihat GNU General Public License untuk rincian lebih lanjut. BitFieldWidget Reset bits to zero Atur ulang bit ke nol Invert bits Balikkan bit Shift bits left Geser bit ke kiri Shift bits right Geser bit ke kanan Book Index Indeks Algebra Aljabar Quadratic Equation Persamaan Kuadrat Logarithmic Base Conversion Konversi Basis Logaritmik Geometry Geometri Circle Lingkaran Sector Sektor Sphere Bola Cube Kubus Cone Kerucut Cylinder Silinder Electronics Elektronik Ohm's Law Hukum Ohm Power Daya Reactance Reaktansi Resonance Resonansi Radio Frequency Frekuensi Radio Antennas Antena Characteristic Impedance (coax) Impedansi Karakteristik (koaks) Velocity of Propagation (coax) Laju Propagasi (koaks) Standing Wave Ratio & Return Loss Rasio Gelombang Berdiri & Redaman Pantul Free Space Wavelength Panjang Gelombang Ruang Bebas resistance resistansi voltage voltase current arus power daya inductive reactance reaktansi induktif capacitive reactance reaktansi kapasitif inductance induktansi capacitance kapasitansi frequency frekuensi resonance frequency frekuensi resonansi area luas perimeter keliling diameter diameter radius jari-jari volume volume surface area luas permukaan height tinggi slant height tinggi sisi miring face diagonal diagonal sisi space diagonal diagonal ruang edge length panjang tepi arc length panjang lengkung central angle (degrees) sudut pusat (derajat) input power daya masukan reflected power daya pantul transmitted power daya terkirim return loss redaman pantul dielectric constant konstanta dielektrik outer conductor's inner diameter diameter dalam konduktor luar inner conductor's outer diameter diameter luar konduktor dalam speed of light kecepatan cahaya reflection coefficient koefisien refleksi standing wave ratio rasio gelombang berdiri normalized impedance impedansi ternormalisasi frequency (Hz) frekuensi (Hz) BookDock Formula Book Buku Rumus ConstantCompletion Search constants Cari konstanta No match found Tidak ada yang cocok Constants Mathematics Matematika Physics (CODATA 2022) Fisika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kimia (IUPAC - CIAAW 2021) Uncategorized Tidak dikategorikan Universal Universal Physicochemical Fisikokimia Atomic & Nuclear — General Atomik & Nuklir - Umum Atomic & Nuclear — Electroweak Atomik & Nuklir - Elektrolemah Atomic & Nuclear — Electron Atomik & Nuklir - Elektron Atomic & Nuclear — Muon Atomik & Nuklir - Muon Atomic & Nuclear — Tau Atomik & Nuklir - Tau Atomic & Nuclear — Proton Atomik & Nuklir - Proton Atomic & Nuclear — Neutron Atomik & Nuklir - Neutron Atomic & Nuclear — Deuteron Atomik & Nuklir - Deuteron Atomic & Nuclear — Triton Atomik & Nuklir - Triton Atomic & Nuclear — Helion Atomik & Nuklir - Helion Atomic & Nuclear — Alpha particle Atomik & Nuklir - Partikel alfa Atomic & Nuclear — Atomic units Atomik & Nuklir - Satuan atomik Atomic & Nuclear — Energy conversion relationships Atomik & Nuklir - Hubungan konversi energi Atomic & Nuclear — X-ray units Atomik & Nuklir - Satuan sinar-X Atomic & Nuclear — Magnetic shielding corrections Atomik & Nuklir - Koreksi perisai magnetik Masses Massa Lifetimes Masa hidup Molar Masses Massa molar Electronegativity Keelektronegatifan Ionization Energy Energi ionisasi Nominal Constants (IAU 2015) Konstanta nominal (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Estimasi terbaik saat ini (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) impedansi karakteristik vakum (Zâ‚€) reduced Planck constant (â„�) konstanta Planck tereduksi (â„�) vacuum electric permittivity (ϵ₀) permitivitas listrik vakum (ϵ₀) Newtonian constant of gravitation (G) konstanta gravitasi Newton (G) vacuum magnetic permeability (μ₀) permeabilitas magnetik vakum (μ₀) Planck constant (h) konstanta Planck (h) speed of light in vacuum (c) kecepatan cahaya dalam vakum (c) standard acceleration of gravity (gâ‚™) percepatan gravitasi standar (gâ‚™) Newtonian constant of gravitation over h-bar c konstanta gravitasi Newton per h-bar c Planck length panjang Planck Planck constant in eV/Hz (h) konstanta Planck dalam eV/Hz (h) Planck mass massa Planck Planck mass energy equivalent in GeV ekuivalen energi massa Planck dalam GeV Planck temperature suhu Planck Planck time waktu Planck reduced Planck constant in eV·s (â„�) konstanta Planck tereduksi dalam eV·s (â„�) reduced Planck constant times c in MeV·fm konstanta Planck tereduksi dikali c dalam MeV·fm Bohr magneton magneton Bohr conductance quantum (Gâ‚€) kuantum konduktansi (Gâ‚€) Coulomb constant (kâ‚‘) konstanta Coulomb (kâ‚‘) elementary charge (e) muatan elementer (e) elementary charge over h-bar muatan elementer per h-bar conventional value of Josephson constant nilai konvensional konstanta Josephson Josephson constant konstanta Josephson conventional value of ampere-90 nilai konvensional ampere-90 conventional value of coulomb-90 nilai konvensional coulomb-90 conventional value of farad-90 nilai konvensional farad-90 conventional value of henry-90 nilai konvensional henry-90 conventional value of ohm-90 nilai konvensional ohm-90 conventional value of volt-90 nilai konvensional volt-90 conventional value of watt-90 nilai konvensional watt-90 magnetic flux quantum (Φ₀) kuantum fluks magnetik (Φ₀) nuclear magneton magneton nuklir inverse of conductance quantum invers kuantum konduktansi conventional value of von Klitzing constant nilai konvensional konstanta von Klitzing von Klitzing constant konstanta von Klitzing atomic unit of magnetic dipole moment satuan atomik momen dipol magnetik atomic unit of magnetic flux density satuan atomik kerapatan fluks magnetik Bohr magneton in eV/T magneton Bohr dalam eV/T Bohr magneton in Hz/T magneton Bohr dalam Hz/T Bohr magneton in inverse meter per tesla magneton Bohr dalam meter invers per tesla Bohr magneton in K/T magneton Bohr dalam K/T nuclear magneton in eV/T magneton nuklir dalam eV/T nuclear magneton in inverse meter per tesla magneton nuklir dalam meter invers per tesla nuclear magneton in K/T magneton nuklir dalam K/T nuclear magneton in MHz/T magneton nuklir dalam MHz/T Bohr radius (aâ‚€) jari-jari Bohr (aâ‚€) fine-structure constant (α) konstanta struktur halus (α) Hartree energy (Eâ‚•) energi Hartree (Eâ‚•) Hartree energy in eV energi Hartree dalam eV quantum of circulation kuantum sirkulasi quantum of circulation times 2 kuantum sirkulasi dikali 2 Rydberg constant (R∞) konstanta Rydberg (R∞) atomic mass unit-hartree relationship hubungan satuan massa atom-hartree atomic mass unit-hertz relationship hubungan satuan massa atom-hertz atomic mass unit-inverse meter relationship hubungan satuan massa atom-meter invers atomic mass unit-joule relationship hubungan satuan massa atom-joule atomic mass unit-kelvin relationship hubungan satuan massa atom-kelvin atomic mass unit-kilogram relationship hubungan satuan massa atom-kilogram atomic unit of 1st hyperpolarizability satuan atomik 1st hyperpolarizability atomic unit of 2nd hyperpolarizability satuan atomik 2nd hyperpolarizability atomic unit of charge (e) satuan atomik muatan (e) atomic unit of charge density satuan atomik kerapatan muatan atomic unit of current satuan atomik arus atomic unit of electric dipole moment satuan atomik momen dipol listrik atomic unit of electric field satuan atomik medan listrik atomic unit of electric field gradient satuan atomik gradien medan listrik atomic unit of electric polarizability satuan atomik polarisabilitas listrik atomic unit of electric potential satuan atomik potensial listrik atomic unit of electric quadrupole moment satuan atomik momen kuadrupol listrik atomic unit of action satuan atomik aksi atomic unit of energy satuan atomik energi atomic unit of force satuan atomik gaya atomic unit of length satuan atomik panjang hertz-atomic mass unit relationship hubungan hertz-satuan massa atom hertz-electron volt relationship hertz-elektronvolt hubungan hertz-hartree relationship hertz-hartree hubungan hertz-inverse meter relationship hubungan hertz-meter invers hertz-joule relationship hertz-joule hubungan hertz-kelvin relationship hertz-kelvin hubungan hertz-kilogram relationship hertz-kilogram hubungan hyperfine transition frequency of Cs-133 frekuensi transisi hiperhalus Cs-133 inverse fine-structure constant (αâ�»Â¹) invers konstanta struktur halus (αâ�»Â¹) inverse meter-atomic mass unit relationship hubungan meter invers-satuan massa atom inverse meter-electron volt relationship hubungan meter invers-elektronvolt inverse meter-hartree relationship hubungan meter invers-hartree inverse meter-hertz relationship hubungan meter invers-hertz inverse meter-joule relationship hubungan meter invers-joule inverse meter-kelvin relationship hubungan meter invers-kelvin inverse meter-kilogram relationship hubungan meter invers-kilogram joule-atomic mass unit relationship hubungan joule-satuan massa atom joule-electron volt relationship joule-elektronvolt hubungan joule-hertz relationship joule-hertz hubungan joule-hartree relationship joule-hartree hubungan joule-inverse meter relationship hubungan joule-meter invers joule-kelvin relationship joule-kelvin hubungan joule-kilogram relationship joule-kilogram hubungan kelvin-atomic mass unit relationship hubungan kelvin-satuan massa atom kelvin-electron volt relationship kelvin-elektronvolt hubungan kelvin-hertz relationship kelvin-hertz hubungan kelvin-hartree relationship kelvin-hartree hubungan kelvin-inverse meter relationship hubungan kelvin-meter invers kelvin-joule relationship kelvin-joule hubungan kelvin-kilogram relationship kelvin-kilogram hubungan kilogram-atomic mass unit relationship hubungan kilogram-satuan massa atom kilogram-electron volt relationship kilogram-elektronvolt hubungan kilogram-hertz relationship kilogram-hertz hubungan kilogram-hartree relationship kilogram-hartree hubungan kilogram-inverse meter relationship hubungan kilogram-meter invers kilogram-joule relationship kilogram-joule hubungan kilogram-kelvin relationship kilogram-kelvin hubungan lattice parameter of silicon (a) parameter kisi silikon (a) luminous efficacy efikasi cahaya natural unit of energy satuan alami energi natural unit of energy in MeV satuan alami energi dalam MeV natural unit of action (â„�) satuan alami aksi (â„�) natural unit of action in eV·s satuan alami aksi dalam eV·s natural unit of length satuan alami panjang natural unit of mass satuan alami massa natural unit of momentum satuan alami momentum natural unit of momentum in MeV/c satuan alami momentum dalam MeV/c natural unit of time satuan alami waktu natural unit of velocity satuan alami kecepatan Rydberg constant times c in Hz konstanta Rydberg dikali c dalam Hz Rydberg constant times hc in eV konstanta Rydberg dikali hc dalam eV Rydberg constant times hc in J konstanta Rydberg dikali hc dalam J Fermi coupling constant konstanta kopling Fermi weak mixing angle sudut pencampuran lemah W to Z mass ratio rasio massa W terhadap Z Thomson cross section (σₑ) penampang lintang Thomson (σₑ) electron mass (mâ‚‘) massa elektron (mâ‚‘) electron mass in u massa elektron dalam u electron mass energy equivalent (mₑ·c²) ekuivalen energi massa elektron (mₑ·c²) electron mass energy equivalent in MeV ekuivalen energi massa elektron dalam MeV reduced Compton wavelength panjang gelombang Compton tereduksi classical electron radius (râ‚‘) jari-jari elektron klasik (râ‚‘) electron charge to mass quotient hasil bagi muatan terhadap massa elektron electron-deuteron magnetic moment ratio electron-deuteron rasio momen magnetik electron-deuteron mass ratio electron-deuteron rasio massa electron g factor (gâ‚‘) faktor g elektron (gâ‚‘) electron gyromagnetic ratio (γₑ) electron rasio giromagnetik (γₑ) electron gyromagnetic ratio in MHz/T rasio giromagnetik elektron dalam MHz/T electron-helion mass ratio electron-helion rasio massa electron magnetic moment (μₑ) electron momen magnetik (μₑ) electron magnetic moment anomaly (aâ‚‘) anomali momen magnetik elektron (aâ‚‘) electron magnetic moment to Bohr magneton ratio rasio momen magnetik elektron terhadap magneton Bohr electron magnetic moment to nuclear magneton ratio rasio momen magnetik elektron terhadap magneton nuklir electron molar mass (Mâ‚‘) massa molar elektron (Mâ‚‘) electron-muon magnetic moment ratio electron-muon rasio momen magnetik electron-muon mass ratio electron-muon rasio massa electron-neutron magnetic moment ratio electron-neutron rasio momen magnetik electron-neutron mass ratio electron-neutron rasio massa electron-proton magnetic moment ratio electron-proton rasio momen magnetik electron-proton mass ratio electron-proton rasio massa electron relative atomic mass (Ar(e)) massa atom relatif elektron (Ar(e)) electron-tau mass ratio electron-tau rasio massa electron to alpha particle mass ratio rasio massa elektron terhadap partikel alfa electron to shielded helion magnetic moment ratio rasio momen magnetik elektron terhadap helion terperisai electron to shielded proton magnetic moment ratio rasio momen magnetik elektron terhadap proton terperisai electron-triton mass ratio electron-triton rasio massa electron volt-atomic mass unit relationship hubungan elektronvolt-satuan massa atom electron volt-hartree relationship elektronvolt-hartree hubungan electron volt-hertz relationship elektronvolt-hertz hubungan electron volt-inverse meter relationship hubungan elektronvolt-meter invers electron volt-joule relationship elektronvolt-joule hubungan electron volt-kelvin relationship elektronvolt-kelvin hubungan electron volt-kilogram relationship elektronvolt-kilogram hubungan hartree-atomic mass unit relationship hubungan hartree-satuan massa atom hartree-electron volt relationship hartree-elektronvolt hubungan muon Compton wavelength muon panjang gelombang Compton muon-electron mass ratio muon-electron rasio massa muon g factor muon faktor g muon magnetic moment muon momen magnetik muon magnetic moment anomaly muon momen magnetik anomaly muon magnetic moment to Bohr magneton ratio rasio momen magnetik muon terhadap magneton Bohr muon magnetic moment to nuclear magneton ratio rasio momen magnetik muon terhadap magneton nuklir muon mass massa muon muon mass energy equivalent ekuivalen energi massa muon muon mass energy equivalent in MeV ekuivalen energi massa muon dalam MeV muon mass in u massa muon dalam u muon molar mass muon massa molar muon-neutron mass ratio muon-neutron rasio massa muon-proton magnetic moment ratio muon-proton rasio momen magnetik muon-proton mass ratio muon-proton rasio massa muon-tau mass ratio muon-tau rasio massa reduced muon Compton wavelength panjang gelombang Compton muon tereduksi reduced tau Compton wavelength panjang gelombang Compton tau tereduksi tau Compton wavelength tau panjang gelombang Compton tau-electron mass ratio tau-electron rasio massa tau mass massa tau tau mass energy equivalent ekuivalen energi massa tau tau mass in u massa tau dalam u tau molar mass tau massa molar tau-muon mass ratio tau-muon rasio massa tau-neutron mass ratio tau-neutron rasio massa tau-proton mass ratio tau-proton rasio massa proton charge to mass quotient hasil bagi muatan terhadap massa proton proton Compton wavelength proton panjang gelombang Compton proton-electron mass ratio proton-electron rasio massa proton g factor (gₚ) proton faktor g (gₚ) proton gyromagnetic ratio (γₚ) proton rasio giromagnetik (γₚ) proton gyromagnetic ratio in MHz/T rasio giromagnetik proton dalam MHz/T proton magnetic moment (μₚ) proton momen magnetik (μₚ) proton magnetic moment to Bohr magneton ratio rasio momen magnetik proton terhadap magneton Bohr proton magnetic moment to nuclear magneton ratio rasio momen magnetik proton terhadap magneton nuklir proton magnetic shielding correction koreksi perisai magnetik proton proton mass (mₚ) massa proton (mₚ) proton mass energy equivalent ekuivalen energi massa proton proton mass energy equivalent in MeV ekuivalen energi massa proton dalam MeV proton mass in u massa proton dalam u proton molar mass (Mₚ) massa molar proton (Mₚ) proton-muon mass ratio proton-muon rasio massa proton-neutron magnetic moment ratio proton-neutron rasio momen magnetik proton-neutron mass ratio proton-neutron rasio massa proton relative atomic mass (Ar(p)) proton massa atom relatif (Ar(p)) proton rms charge radius proton jari-jari muatan rms proton-tau mass ratio proton-tau rasio massa reduced proton Compton wavelength panjang gelombang Compton proton tereduksi shielded proton gyromagnetic ratio terperisai proton rasio giromagnetik shielded proton gyromagnetic ratio in MHz/T rasio giromagnetik proton terperisai dalam MHz/T shielded proton magnetic moment terperisai proton momen magnetik shielded proton magnetic moment to Bohr magneton ratio rasio momen magnetik proton terperisai terhadap magneton Bohr shielded proton magnetic moment to nuclear magneton ratio rasio momen magnetik proton terperisai terhadap magneton nuklir neutron Compton wavelength neutron panjang gelombang Compton neutron-electron magnetic moment ratio neutron-electron rasio momen magnetik neutron-electron mass ratio neutron-electron rasio massa neutron g factor (gâ‚™) neutron faktor g (gâ‚™) neutron gyromagnetic ratio (γₙ) neutron rasio giromagnetik (γₙ) neutron gyromagnetic ratio in MHz/T rasio giromagnetik neutron dalam MHz/T neutron magnetic moment (μₙ) neutron momen magnetik (μₙ) neutron magnetic moment to Bohr magneton ratio rasio momen magnetik neutron terhadap magneton Bohr neutron magnetic moment to nuclear magneton ratio rasio momen magnetik neutron terhadap magneton nuklir neutron mass (mâ‚™) massa neutron (mâ‚™) neutron mass energy equivalent ekuivalen energi massa neutron neutron mass energy equivalent in MeV ekuivalen energi massa neutron dalam MeV neutron mass in u massa neutron dalam u neutron molar mass (Mâ‚™) massa molar neutron (Mâ‚™) neutron-muon mass ratio neutron-muon rasio massa neutron-proton magnetic moment ratio neutron-proton rasio momen magnetik neutron-proton mass difference selisih massa neutron-proton neutron-proton mass difference energy equivalent ekuivalen energi selisih massa neutron-proton neutron-proton mass difference energy equivalent in MeV ekuivalen energi selisih massa neutron-proton dalam MeV neutron-proton mass difference in u selisih massa neutron-proton dalam u neutron-proton mass ratio neutron-proton rasio massa neutron relative atomic mass (Ar(n)) neutron massa atom relatif (Ar(n)) neutron-tau mass ratio neutron-tau rasio massa neutron to shielded proton magnetic moment ratio rasio momen magnetik neutron terhadap proton terperisai reduced neutron Compton wavelength panjang gelombang Compton neutron tereduksi deuteron-electron magnetic moment ratio deuteron-electron rasio momen magnetik deuteron-electron mass ratio deuteron-electron rasio massa deuteron g factor deuteron faktor g deuteron magnetic moment deuteron momen magnetik deuteron magnetic moment to Bohr magneton ratio rasio momen magnetik deuteron terhadap magneton Bohr deuteron magnetic moment to nuclear magneton ratio rasio momen magnetik deuteron terhadap magneton nuklir deuteron mass massa deuteron deuteron mass energy equivalent ekuivalen energi massa deuteron deuteron mass energy equivalent in MeV ekuivalen energi massa deuteron dalam MeV deuteron mass in u massa deuteron dalam u deuteron molar mass deuteron massa molar deuteron-neutron magnetic moment ratio deuteron-neutron rasio momen magnetik deuteron-proton magnetic moment ratio deuteron-proton rasio momen magnetik deuteron-proton mass ratio deuteron-proton rasio massa deuteron relative atomic mass (Ar(d)) deuteron massa atom relatif (Ar(d)) deuteron rms charge radius deuteron jari-jari muatan rms triton-electron mass ratio triton-electron rasio massa triton g factor (gₜ) triton faktor g (gₜ) triton magnetic moment (μₜ) triton momen magnetik (μₜ) triton magnetic moment to Bohr magneton ratio rasio momen magnetik triton terhadap magneton Bohr triton magnetic moment to nuclear magneton ratio rasio momen magnetik triton terhadap magneton nuklir triton mass (mₜ) massa triton (mₜ) triton mass energy equivalent ekuivalen energi massa triton triton mass energy equivalent in MeV ekuivalen energi massa triton dalam MeV triton mass in u massa triton dalam u triton molar mass (Mₜ) triton massa molar (Mₜ) triton-proton mass ratio triton-proton rasio massa triton relative atomic mass (Ar(t)) triton massa atom relatif (Ar(t)) triton to proton magnetic moment ratio rasio momen magnetik triton terhadap proton helion-electron mass ratio helion-electron rasio massa helion g factor (gâ‚•) helion faktor g (gâ‚•) helion magnetic moment (μₕ) helion momen magnetik (μₕ) helion magnetic moment to Bohr magneton ratio rasio momen magnetik helion terhadap magneton Bohr helion magnetic moment to nuclear magneton ratio rasio momen magnetik helion terhadap magneton nuklir helion mass (mâ‚•) massa helion (mâ‚•) helion mass energy equivalent ekuivalen energi massa helion helion mass energy equivalent in MeV ekuivalen energi massa helion dalam MeV helion mass in u massa helion dalam u helion molar mass (Mâ‚•) helion massa molar (Mâ‚•) helion-proton mass ratio helion-proton rasio massa helion relative atomic mass (Ar(h)) helion massa atom relatif (Ar(h)) helion shielding shift pergeseran perisai helion shielded helion gyromagnetic ratio terperisai helion rasio giromagnetik shielded helion gyromagnetic ratio in MHz/T rasio giromagnetik helion terperisai dalam MHz/T shielded helion magnetic moment terperisai helion momen magnetik shielded helion magnetic moment to Bohr magneton ratio rasio momen magnetik helion terperisai terhadap magneton Bohr shielded helion magnetic moment to nuclear magneton ratio rasio momen magnetik helion terperisai terhadap magneton nuklir shielded helion to proton magnetic moment ratio rasio momen magnetik helion terperisai terhadap proton shielded helion to shielded proton magnetic moment ratio rasio momen magnetik helion terperisai terhadap proton terperisai alpha particle mass massa partikel alfa alpha particle mass in u massa partikel alfa dalam u alpha particle mass energy equivalent ekuivalen energi massa partikel alfa alpha particle mass energy equivalent in MeV ekuivalen energi massa partikel alfa dalam MeV alpha particle-electron mass ratio partikel alfa-electron rasio massa alpha particle-proton mass ratio partikel alfa-proton rasio massa alpha particle rms charge radius jari-jari muatan rms partikel alfa alpha particle molar mass partikel alfa massa molar alpha particle relative atomic mass (Ar(α)) partikel alfa massa atom relatif (Ar(α)) atomic mass constant (mᵤ) konstanta massa atom (mᵤ) Avogadro constant konstanta Avogadro Boltzmann constant (k) konstanta Boltzmann (k) Boltzmann constant in eV/K konstanta Boltzmann dalam eV/K Boltzmann constant in Hz/K konstanta Boltzmann dalam Hz/K Boltzmann constant in inverse meter per kelvin konstanta Boltzmann dalam meter invers per kelvin electron volt (eV) elektronvolt (eV) Faraday constant (F) konstanta Faraday (F) first radiation constant (câ‚�) konstanta radiasi pertama (câ‚�) first radiation constant for spectral radiance konstanta radiasi pertama untuk radiansi spektral molar gas constant (R) konstanta gas molar (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) konstanta Loschmidt (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) konstanta Loschmidt (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant konstanta Planck molar second radiation constant (câ‚‚) konstanta radiasi kedua (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-konstanta Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) jarak kisi Si ideal (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent ekuivalen energi konstanta massa atom atomic mass constant energy equivalent in MeV ekuivalen energi konstanta massa atom dalam MeV atomic mass unit-electron volt relationship hubungan satuan massa atom-elektronvolt molar mass constant (Mᵤ) konstanta massa molar (Mᵤ) molar mass of carbon-12 massa molar karbon-12 molar volume of ideal gas (273.15 K, 100 kPa) volume molar gas ideal (273,15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volume molar gas ideal (273,15 K, 101,325 kPa) molar volume of silicon volume molar silikon Sackur-Tetrode constant (1 K, 100 kPa) konstanta Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) konstanta Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant konstanta hukum pergeseran frekuensi Wien Wien wavelength displacement law constant konstanta hukum pergeseran panjang gelombang Wien standard atmosphere (atm) atmosfer standar (atm) standard-state pressure (p°) tekanan keadaan standar (p°) Angstrom star (Ã…*) bintang Angstrom (Ã…*) Copper x unit satuan x tembaga Molybdenum x unit satuan x molibdenum atomic unit of magnetizability satuan atomik magnetisabilitas atomic unit of mass (mâ‚‘) satuan atomik massa (mâ‚‘) atomic unit of momentum satuan atomik momentum atomic unit of permittivity satuan atomik permitivitas atomic unit of time satuan atomik waktu atomic unit of velocity satuan atomik kecepatan hartree-hertz relationship hartree-hertz hubungan hartree-inverse meter relationship hubungan hartree-meter invers hartree-joule relationship hartree-joule hubungan hartree-kelvin relationship hartree-kelvin hubungan hartree-kilogram relationship hartree-kilogram hubungan shielding difference of d and p in HD perbedaan perisai d dan p dalam HD shielding difference of t and p in HT perbedaan perisai t dan p dalam HT pi (Ï€) pi (Ï€) Euler's number (e) bilangan Euler (e) golden ratio (φ) rasio emas (φ) Euler-Mascheroni constant (γ) konstanta Euler-Mascheroni (γ) nominal solar radius jari-jari Matahari nominal nominal solar total irradiance iradiansi total Matahari nominal nominal solar luminosity luminositas Matahari nominal nominal solar effective temperature suhu efektif Matahari nominal nominal solar mass parameter parameter massa Matahari nominal nominal terrestrial equatorial radius jari-jari ekuatorial Bumi nominal nominal terrestrial polar radius jari-jari kutub Bumi nominal nominal terrestrial mass parameter parameter massa Bumi nominal nominal jovian equatorial radius jari-jari ekuatorial Jupiter nominal nominal jovian polar radius jari-jari kutub Jupiter nominal nominal jovian mass parameter parameter massa Jupiter nominal average value of one minus the rate of TCG relative to TCB nilai rata-rata satu dikurangi laju TCG relatif terhadap TCB solar mass parameter (TCB-compatible) parameter massa Matahari (kompatibel TCB) solar mass parameter (TDB-compatible) parameter massa Matahari (kompatibel TDB) equatorial radius of the Earth (TT-compatible) jari-jari ekuatorial Bumi (kompatibel TT) dynamical form factor of the Earth faktor bentuk dinamis Bumi time rate of change in the dynamical form factor of the Earth laju perubahan waktu faktor bentuk dinamis Bumi geocentric gravitational constant (TCB-compatible) konstanta gravitasi geosentris (kompatibel TCB) geocentric gravitational constant (TT-compatible) konstanta gravitasi geosentris (kompatibel TT) geocentric gravitational constant (TDB-compatible) konstanta gravitasi geosentris (kompatibel TDB) potential of the geoid potensial geoid nominal mean angular velocity of the Earth (TT-compatible) kecepatan sudut rata-rata nominal Bumi (kompatibel TT) ratio mass of the Moon to the Earth rasio massa Bulan terhadap Bumi ratio of the mass of the Sun to Mercury rasio massa Matahari terhadap Merkurius ratio of the mass of the Sun to Venus rasio massa Matahari terhadap Venus ratio of the mass of the Sun to Mars rasio massa Matahari terhadap Mars ratio of the mass of the Sun to Jupiter rasio massa Matahari terhadap Jupiter ratio of the mass of the Sun to Saturn rasio massa Matahari terhadap Saturnus ratio of the mass of the Sun to Uranus rasio massa Matahari terhadap Uranus ratio of the mass of the Sun to Neptune rasio massa Matahari terhadap Neptunus ratio of the mass of the Sun to (134340) Pluto rasio massa Matahari terhadap (134340) Pluto ratio of the mass of the Sun to (136199) Eris rasio massa Matahari terhadap (136199) Eris ratio of the mass of (1) Ceres to the Sun rasio massa (1) Ceres terhadap Matahari ratio of the mass of (2) Pallas to the Sun rasio massa (2) Pallas terhadap Matahari ratio of the mass of (4) Vesta to the Sun rasio massa (4) Vesta terhadap Matahari mean obliquity of the ecliptic at J2000.0 kemiringan rata-rata ekliptika pada J2000.0 Electromagnetic Elektromagnetik Compton wavelength panjang gelombang Compton Astronomy Astronomi ConstantsWidget Domain Ranah Subdomain Subranah No match found Tidak ada yang cocok Name Nama Value Nilai Unit Satuan Search Cari All Semua CustomKeypadDialog Custom Keypad Papan tombol kustom Rows: Baris: Columns: Kolom: Copy preset: Salin prasetel: Basic Dasar Scientific (wide) Ilmiah (lebar) Scientific (narrow) Ilmiah (sempit) Apply Terapkan Row Baris Column Kolom Label Label Behavior Perilaku Text Teks DiagnosticsDialog App Diagnostics Diagnostik Aplikasi Copy to Clipboard Salin ke Papan Klip Editor Unit Satuan User unit Satuan pengguna User function Fungsi pengguna Argument Argumen Current result:<br/>%1 Hasil saat ini:<br/>%1 Selection result:<br/>%1 Hasil pilihan:<br/>%1 Selection result: n/a Hasil pilihan: t/a Selection result: %1 Hasil pilihan: %1 second detik metre meter kilogram kilogram mole mol radian radian steradian steradian degree Celsius derajat Celsius cubic metre meter kubik cubic millimetre milimeter kubik cubic centimetre sentimeter kubik cubic decimetre desimeter kubik cubic kilometre kilometer kubik square millimetre milimeter persegi square kilometre kilometer persegi square metre meter persegi minute menit hour jam day hari astronomical unit satuan astronomi degree derajat arcminute menit busur arcsecond detik busur milliarcsecond miliarcdetik microarcsecond mikroarcdetik hectare hektare litre liter tonne ton Dalton Dalton electronvolt elektronvolt Angstrom Angstrom atmosphere atmosfer atomic mass unit satuan massa atom British thermal unit satuan termal Britania calorie kalori carat karat cup cangkir cup (Imperial) cangkir (Imperial) cup (Japanese) cangkir (Jepang) cup (US) cangkir (AS) degree Fahrenheit derajat Fahrenheit fathom depa fluid ounce (Imperial) ons cair (Imperial) fluid ounce (US) ons cair (AS) fluid dram (Imperial) dram cair (Imperial) fluid dram (US) dram cair (AS) foot kaki square foot kaki persegi cubic foot kaki kubik gallon (Imperial) galon (Imperial) gallon (US) galon (AS) gill (Imperial) gill (Imperial) gill (US) gill (AS) gradian gradian grain grain gram gram Hartley Hartley Hartree energy unit satuan energi Hartree horsepower tenaga kuda inch inci square inch inci persegi cubic inch inci kubik karat karat knot knot lightminute menit cahaya lightsecond detik cahaya lightyear tahun cahaya long ton ton panjang mile mil square mile mil persegi cubic mile mil kubik mile per hour mil per jam kilometre per hour kilometer per jam nautical mile mil laut ounce ons parsec parsek pint (Imperial) pint (Imperial) pint (US) pint (AS) pound pon pounds per square inch pon per inci persegi quart (Imperial) quart (Imperial) quart (US) quart (AS) oil barrel barel minyak beer barrel (US) barel bir (AS) square yard yard persegi cubic yard yard kubik short ton ton pendek tablespoon sendok makan tablespoon (Australian) sendok makan (Australia) tablespoon (Imperial) sendok makan (Imperial) tablespoon (US) sendok makan (AS) dessert spoon sendok pencuci mulut teaspoon sendok teh teaspoon (Imperial) sendok teh (Imperial) teaspoon (US) sendok teh (AS) turn putaran revolution revolusi revolution per minute putaran per menit week minggu kilowatt hour kilowatt jam millimetre of mercury milimeter air raksa yard yard Julian century abad Julian Julian year tahun Julian sidereal year tahun sideris tropical year tahun tropis Evaluator invalid expression ekspresi tidak valid division by zero pembagian dengan nol too time consuming - computation was rejected makan waktu terlalu banyak - komputasi ditolak dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensi tidak cocok - kuantitas dengan dimensi berbeda tidak dapat dibandingkan, dijumlahkan, dsb. invalid dimension - operation might require dimensionless arguments dimensi tidak valid - operasi mungkin memerlukan argumen tak berdimensi Computation aborted - encountered numerical instability Komputasi dibatalkan - terjadi ketidakstabilan numerik invalid dimension - function might require dimensionless arguments dimensi tidak valid - fungsi mungkin memerlukan argumen tak berdimensi error kesalahan unit must not be zero satuan tidak boleh nol Conversion failed - dimension mismatch Konversi gagal - dimensi tidak cocok unknown function or variable fungsi atau variabel tak dikenal recursion not supported rekursi tidak didukung cannot operate on a NaN tak bisa beroperasi pada suatu NaN underflow - tiny result is out of SpeedCrunch's number range underflow - hasil sangat kecil di luar jangkauan angka SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflow - hasil sangat besar di luar jangkauan angka SpeedCrunch overflow - logic result exceeds maximum of 256 bits overflow - hasil lojik melebihi maksimum 256 bit overflow - integer result exceeds maximum limit for integers overflow - hasil bilangan bulat melebihi batas bagi bilangan bulat operation is not defined for these arguments operasi tidak didefinisikan untuk argumen ini wrong number of arguments cacah argumen salah does not take NaN as an argument tak menerima NaN sebagai suatu argumen result out of range hasil di luar jangkauan undefined for argument domain tidak terdefinisi untuk ranah argumen computation too expensive komputasi terlalu berat internal error, please report a bug kesalahan internal, laporkan bug syntax error kesalahan sintaks conversion target must be a unit target konversi harus berupa satuan unknown unit satuan tidak dikenal %1 is a reserved name, please choose another %1 adalah nama yang dicadangkan, pilih nama lain %1 is a global user definition and cannot be overridden in this session. %1 adalah definisi pengguna global dan tidak dapat ditimpa dalam sesi ini. %1 is a variable name, please choose another or delete the variable %1 adalah nama variabel, pilih nama lain atau hapus variabel tersebut argument %1 is used more than once argumen %1 digunakan lebih dari sekali %1 is a built-in unit name, please choose another %1 adalah nama satuan bawaan, pilih nama lain %1 is a user function name, please choose another or delete the function %1 adalah nama fungsi pengguna, pilih nama lain atau hapus fungsi tersebut FunctionRepo max; trials; probability maks; percobaan; probabilitas trials; probability percobaan; probabilitas hits; trials; probability keberhasilan; percobaan; probabilitas max; total; hits; trials maks; total; keberhasilan; percobaan total; hits; trials total; keberhasilan; percobaan count; total; hits; trials jumlah; total; keberhasilan; percobaan dividend; divisor dividen; pembagi x; exponent_bits; significand_bits [; exponent_bias] x; bit_eksponen; bit_signifikan [; bias_eksponen] base; x basis; x value; modulo nilai; modulo base; exponent; modulo basis; eksponen; modulo events; average_events kejadian; rata_rata_kejadian average_events rata_rata_kejadian x [; precision] x [; presisi] Absolute Value Nilai Absolut Absolute Deviation Deviasi Absolut Arc Cosine Arkkosinus Logical AND DAN Logis Area Hyperbolic Cosine Arkkosinus Hiperbolik Area Hyperbolic Sine Arksinus Hiperbolik Area Hyperbolic Tangent Arktangen Hiperbolik Arc Sine Arksinus Arc Tangent Arktangen Arc Tangent with two Arguments Arktangen dengan dua Argumen Average (Arithmetic Mean) Rata-rata (Rerata Aritmetika) Binomial Cumulative Distribution Function Fungsi Distribusi Kumulatif Binomial Binomial Distribution Mean Rata-rata Distribusi Binomial Binomial Probability Mass Function Fungsi Massa Probabilitas Binomial Binomial Distribution Variance Varians Distribusi Binomial Cube Root Akar Kubik Complex Conjugate Konjugat Kompleks Cosine Kosinus Hyperbolic Cosine Kosinus Hiperbolik Cotangent Kotangen Cosecant Kosekan Convert Unix timestamp to Date Konversi timestamp Unix ke tanggal Degrees of Arc Derajat Busur Error Function Fungsi Galat Complementary Error Function Fungsi Galat Komplementer Exponential Eksponensial Fractional Part Bagian Pecahan Extension of Factorials [= (x-1)!] Perluasan Faktorial [= (x-1)!] Greatest Common Divisor Pembagi Persekutuan Terbesar Geometric Mean Rata-rata Geometrik Gradians of arc Gradian busur Hypergeometric Cumulative Distribution Function Fungsi Distribusi Kumulatif Hipergeometrik Hypergeometric Distribution Mean Rata-rata Distribusi Hipergeometrik Hypergeometric Probability Mass Function Fungsi Massa Probabilitas Hipergeometrik Hypergeometric Distribution Variance Varians Distribusi Hipergeometrik Integer Quotient Hasil Bagi Bilangan Bulat Integer Part Bagian Bilangan Bulat Imaginary Part Bagian Imajiner Decode IEEE-754 Binary Value Dekode Nilai Biner IEEE-754 Encode IEEE-754 Binary Value Enkode Nilai Biner IEEE-754 Decode 16-bit Half-Precision Value Dekode Nilai Presisi Setengah 16-bit Encode 16-bit Half-Precision Value Enkode Nilai Presisi Setengah 16-bit Decode 32-bit Single-Precision Value Dekode Nilai Presisi Tunggal 32-bit Encode 32-bit Single-Precision Value Enkode Nilai Presisi Tunggal 32-bit Decode 64-bit Double-Precision Value Dekode Nilai Presisi Ganda 64-bit Encode 64-bit Double-Precision Value Enkode Nilai Presisi Ganda 64-bit Decode 128-bit Quad-Precision Value Dekode Nilai Presisi Kuadruple 128-bit Encode 128-bit Quad-Precision Value Enkode Nilai Presisi Kuadruple 128-bit Binary Logarithm Logaritma Biner Common Logarithm Logaritma Umum Natural Logarithm Logaritma Natural Logarithm to Arbitrary Base Logaritma dengan Basis Sembarang Mask to a bit size Masker ke ukuran bit Maximum Maksimum Median Value (50th Percentile) Nilai Median (Persentil ke-50) Minimum Minimum Modulo Modulo Euclidean Modulo Modulo Euklides Modular Exponentiation Eksponensiasi Modular Combination (Binomial Coefficient) Kombinasi (Koefisien Binomial) Logical NOT BUKAN Logis Permutation (Arrangement) Permutasi (Susunan) Convert to Binary Representation Konversi ke Representasi Biner Arithmetic Aritmetika Chemistry Kimia Complex Kompleks Combinatorics Kombinatorika Probability Probabilitas Statistics Statistik Aggregation Agregasi Random Acak Base conversion Konversi basis Number formatting Pemformatan angka Integer arithmetic Aritmetika bilangan bulat Special functions Fungsi khusus Exponential & Logarithmic Eksponensial & Logaritmik Angle conversion Konversi sudut Trigonometry Trigonometri Bitwise Per Bit Floating point Titik mengambang Date & Time Tanggal & Waktu Linear algebra Aljabar linear unix_timestamp; x hours offset to GMT timestamp_unix; offset x jam terhadap GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; offset x jam terhadap GMT [digits] [digit] max [; min] maks [; min] List Literal Literal daftar Convert to Padded Binary Representation Konversi ke Representasi biner berpading Round Toward +∞ (Ceiling) Bulatkan Menuju +∞ (Pembulatan ke Atas) Cosine plus Imaginary Sine Kosinus plus Sinus Imajiner Convert to Cis Complex Form Konversi ke Bentuk Kompleks Cis Matrix Column Count Jumlah Kolom Matriks Population Correlation Matrix (n) Matriks Korelasi Populasi (n) Sample Correlation Matrix (n-1) Matriks Korelasi Sampel (n-1) Count Hitung Population Covariance Matrix (n) Matriks Kovarians Populasi (n) Sample Covariance Matrix (n-1) Matriks Kovarians Sampel (n-1) Cross Product Perkalian silang Convert Date to Unix timestamp Konversi tanggal ke timestamp Unix Convert to Decimal Representation Konversi ke Representasi Desimal Determinant Determinan Convert to Sexagesimal Notation Konversi ke Notasi Seksagesimal Dot Product Perkalian titik Convert to Engineering Notation Konversi ke Notasi teknik Convert to Exponential Complex Form Konversi ke Bentuk Kompleks Eksponensial Round Toward −∞ (Floor) Bulatkan Menuju −∞ (Pembulatan ke Bawah) Flatten Matrix Ratakan Matriks Least Common Multiple Kelipatan Persekutuan Terkecil Convert to Hexadecimal Representation Konversi ke Representasi Heksadesimal Convert to Padded Hexadecimal Representation Konversi ke Representasi heksadesimal berpading Inverse Matrix Matriks Invers Round to 16-bit Half-Precision Value Bulatkan ke Nilai Presisi Setengah 16-bit Round to 32-bit Single-Precision Value Bulatkan ke Nilai Presisi Tunggal 32-bit Round to 64-bit Double-Precision Value Bulatkan ke Nilai Presisi Ganda 64-bit Round to 128-bit Quad-Precision Value Bulatkan ke Nilai Presisi Kuadruple 128-bit Residual from 16-bit Half-Precision Rounding Residu dari Pembulatan Presisi Setengah 16-bit Residual from 32-bit Single-Precision Rounding Residu dari Pembulatan Presisi Tunggal 32-bit Residual from 64-bit Double-Precision Rounding Residu dari Pembulatan Presisi Ganda 64-bit Residual from 128-bit Quad-Precision Rounding Residu dari Pembulatan Presisi Kuadruple 128-bit Substance Mass Massa zat Molarity Molaritas Molar Mass Massa Molar Median Absolute Deviation Deviasi absolut median Mean Rata-rata Numerical Value of Quantity Nilai Numerik Kuantitas Random Decimal Number Angka desimal acak Random Integer Number Bilangan bulat acak Convert to Rational Representation Konversi ke Representasi rasional Convert to Octal Representation Konversi ke Representasi Oktal Convert to Padded Octal Representation Konversi ke Representasi oktal berpading Vector or Matrix Norm Norma Vektor atau Matriks Logical OR ATAU Logis Population Count (Hamming Weight) Hitungan Populasi (Bobot Hamming) Phase of Complex Number Fase Bilangan Kompleks Poissonian Cumulative Distribution Function Fungsi Distribusi Kumulatif Poisson Poissonian Distribution Mean Rata-rata Distribusi Poisson Poissonian Probability Mass Function Fungsi Massa Probabilitas Poisson Poissonian Distribution Variance Varians Distribusi Poisson Convert to Phasor Complex Form Konversi ke Bentuk Kompleks Fasor Convert to Rectangular Complex Form Konversi ke Bentuk kompleks persegi panjang Round Half Away from Zero Bulatkan Setengah Menjauh dari Nol Round Half Even Bulatkan Setengah Genap Nth Root Akar Pangkat N Convert to Scientific Notation Konversi ke Notasi ilmiah Matrix Row Count Jumlah Baris Matriks List or Matrix Shape Bentuk Daftar atau Matriks Summation Penjumlahan Population Standard Deviation (n) Populasi Simpangan baku (n) Sample Standard Deviation (n-1) Sampel Simpangan baku (n-1) Round Toward Zero (Truncation) Bulatkan Menuju Nol (Pemotongan) Matrix Trace Jejak Matriks Transpose Matrix Transpos Matriks Population Variance (n) Populasi Varians (n) Sample Variance (n-1) Sampel Varians (n-1) Product Hasil Kali Radians Radian Matrix Rank Peringkat Matriks Real Part Bagian Real Secant Sekan Arithmetic Shift Left Geser Aritmetika Kiri Arithmetic Shift Right Geser Aritmetika Kanan Signum Signum Sine Sinus Hyperbolic Sine Sinus Hiperbolik Square Root Akar Kuadrat Sum Jumlah Tangent Tangen Convert to Trigonometric Complex Form Konversi ke Bentuk Kompleks Trigonometri Turns Putaran Hyperbolic Tangent Tangen Hiperbolik Sign-extend a value Perluas tanda suatu nilai Logical XOR XOR Logis FunctionsWidget Domain Ranah All Semua Name Nama Search Cari No match found Tidak ada yang cocok Identifier Pengenal HistoryWidget Remove All Calculations Above Hapus semua perhitungan di atas Remove This Calculation Hapus perhitungan ini Remove All Calculations Below Hapus semua perhitungan di bawah Keypad Inverse cosine Arccos The last result Hasil terakhir Inverse sine Arcsin Inverse tangent Arctan Evaluate expression Evaluasi ekspresi Division Pembagian Multiplication Perkalian Subtraction Pengurangan Addition Penjumlahan Clear expression Bersihkan ekspresi Cosine Kosinus Backspace Backspace Scientific notation Notasi ilmiah Exponential Eksponensial Factorial Faktorial Natural logarithm Logaritma natural Left parenthesis Kurung kiri Nth root Akar Pangkat N Argument separator Pemisah argumen Square Kuadrat Common logarithm Logaritma umum Modulo Modulo Contextual percentage Persentase kontekstual Power Pangkat Right parenthesis Kurung kanan Sine Sinus Square root Akar kuadrat Tangent Tangen Pi Pi Decimal separator Pemisah desimal MainWindow Radian Radian Degree Derajat Gradian Gradian Binary Biner Octal Oktal Hexadecimal Heksadesimal Sexagesimal Seksagesimal Engineering decimal Desimal teknik Scientific decimal Desimal ilmiah &Import... &Impor... &Quit &Keluar Clear E&xpression Bersihkan &Ekspresi Clear &History Bersihkan Histor&y &Copy &Salin &Paste &Tempel &Select Expression Pilih &Ekspresi &Constants &Konstanta &Functions &Fungsi &History &Riwayat &Status Bar Bilah &Status Bitfield Bidang Bit Use&r Functions Fungsi &Pengguna &Degree &Derajat &Radian &Radian &Gradian &Gradian Re&volution Re&volusi Auto-Insert a&ns Sisipka&n ans Otomatis Automatic &Completion Pelengkapan &Otomatis &Built-in Functions Fungsi &Bawaan Built-in &Variables &Variabel Bawaan User &Functions &Fungsi Pengguna User Va&riables Va&riabel pengguna Open a Private Tab on Startup Buka Tab Privat Saat Memulai Open and focus a new private tab whenever SpeedCrunch starts. Buka dan fokuskan tab privat baru setiap kali SpeedCrunch dimulai. Syntax &Highlighting Penyorotan &Sintaks Group Digits in &Input Kelompokkan D&igit Masukan Automatic Input &Adjustments Penyesu&aian Masukan Otomatis Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Sesuaikan operator, spasi, tanda kurung, dan pangkat secara otomatis, serta batasi masukan ke karakter yang valid. Group input digits using the selected number format. Kelompokkan digit masukan sesuai format angka yang dipilih. &Blinking Cursor Kursor &Berkedip Blink the cursor in the expression editor. Kedipkan kursor di penyunting ekspresi. &Escape Clears Editor &Escape Mengosongkan Penyunting Clear the focused expression editor with Escape after dismissing any popup or preview. Kosongkan penyunting ekspresi yang aktif dengan Escape setelah menutup sembulan atau pratinjau. Keep Expression After Evaluation Pertahankan Ekspresi Setelah Perhitungan Copy New Results Automatically Salin Hasil Baru Otomatis &Comma &Koma &System Default Default &Sistem &Dot &Titik Dot &And Comma Titik &dan Koma Toward +∞ (&ceil) Menuju +∞ (&ceil) Toward −∞ (&floor) Menuju −∞ (&floor) &Binary &Biner &Engineering &Teknik &Hexadecimal &Heksadesimal &Octal &Oktal &Scientific &Ilmiah User &Manual &Manual Pengguna Issues and &Feedback M&asalah dan Masukan &Donate &Donasi &About SpeedCrunch &Tentang SpeedCrunch App Diag&nostics Diag&nostik Aplikasi S&plit &Bagi Angle &Mode &Mode Sudut &Complex Form &Bentuk Kompleks New Tab Tab baru Constants Konstanta Functions Fungsi History Riwayat User Functions Fungsi Pengguna &Font... &Fonta... &Language... &Bahasa... &Session &Sesi &Edit &Ubah &View &Tilik Se&ttings &Pengaturan &Decimal &Desimal &Keypad Papan &Tombol Always on &Top Selalu di &Atas Disabled Dinonaktifkan Small Space Spasi Kecil Medium Space Spasi Sedang Large Space Spasi Besar &0 Digits &0 Digit &15 Digits &15 Digit &2 Digits &2 Digit &3 Digits &3 Digit &50 Digits &50 Digit &8 Digits &8 Digit &Sexagesimal &Seksagesimal Reset All Settings... Atur Ulang Semua Pengaturan... &System &Sistem SpeedCrunch &Theme &Tema SpeedCrunch &Classic &Klasik &Modern &Modern Context Help Bantuan Kontekstual &Help &Bantuan Error Kesalahan Can't read from file %1 Tidak dapat membaca dari berkas %1 Import Session Impor Sesi Close Session Tutup sesi Angle Mode: Mode sudut: Notation: Notasi: Precision: Presisi: Turn Putaran Revolution Revolusi Fixed-point decimal Desimal titik tetap Rational Rasional Automatic decimal Desimal otomatis Automatic Otomatis User &Definitions... &Definisi pengguna... New &Tab &Tab baru New &Private Tab Tab &Privat Baru Keep Pertahankan Make Private... Jadikan Privat... New &Window &Jendela baru &Open... &Buka... &Rename... &Ubah Nama... Clo&ne... Klo&nakan... &Close Tab Tutup T&ab Reopen Clo&sed Tab Buka Ke&mbali Tab yang Ditutup Open Sessions &Folder Buka &folder sesi &Undo &Urungkan &Redo U&langi Cu&t &Potong Copy &Last Result S&alin Hasil Terakhir &Wrap in Parentheses Ap&it dengan Tanda Kurung Full Scr&een Mode Mod&e Layar Penuh &Basic &Dasar &Scientific (wide) &Ilmiah (lebar) Scientific (narrow) Ilmiah (sempit) &Custom... &Kustom... Main &Menu &Menu utama User &Variables &Variabel pengguna &Left &Kiri &Right K&anan &Up A&tas &Down &Bawah Close Pa&ne Tutup pa&nel User &Units &Satuan pengguna &Turn &Putaran If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Jika ekspresi baru dimulai dengan +, -, *, atau /, SpeedCrunch menyisipkan "ans" terlebih dahulu. &Accept with Enter &Terima dengan Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Terima saran pelengkapan otomatis saat ini dengan Enter tanpa memilihnya terlebih dahulu menggunakan tombol panah. &Units &Satuan Show Live Result &Preview Tampilkan &pratinjau hasil langsung Save &Window Position on Exit Simpan posisi &jendela saat keluar Hover Highlighting Penyorotan saat diarahkan Group Integer Part Only Kelompokkan bagian bilangan bulat saja Number Format... Format angka... Notation && Precision... Notasi && Presisi... After pressing Enter, keep the entered expression selected in the editor. Setelah menekan Enter, pertahankan ekspresi yang dimasukkan tetap dipilih di editor. Never Tidak pernah Always Selalu Only for Single-Line Expressions Hanya untuk ekspresi satu baris Simplify Displayed Expressions Sederhanakan ekspresi yang ditampilkan History Size &Limit... &Batas ukuran riwayat... Remove Trailing &Zeroes &Hapus Nol di Belakang Nearest, Half &Away (round) Terdekat, setengah &menjauh (round) Nearest, Half &Even (roundeven) Terdekat, setengah &genap (roundeven) Toward &Zero (trunc) Menuju &nol (trunc) &Fixed-Point Titik &tetap &Rational &Rasional &Exponential (m·sâ�»Â¹) &Eksponensial (m·sâ�»Â¹) &Fractional (m/s) &Pecahan (m/s) &Rectangular (a + bi) &Persegi panjang (a + bi) Exponential (reâ�±á¶¿) Eksponensial (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometri (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Tema... Check for &Updates Periksa &pembaruan Source Code Kode sumber &Zoom &Zum &Results &Hasil Unit Notation Notasi satuan Rounding Mode Mode pembulatan &Notation &Notasi &Imaginary Unit Satuan &imajiner &Window &Jendela &Editing P&engeditan A&utocomplete Pelengkapan &otomatis Up/Down Arrow History Riwayat panah atas/bawah &Appearance T&ampilan &Menus &Menu &Docks &Panel Tambatan &Input and Results Masukan dan Has&il &Disabled &Dinonaktifkan &Disable &Nonaktifkan Close preview Tutup pratinjau Rename... Ubah Nama... Clone... Klonakan... Close Tab Tutup Tab New Private Tab Tab Privat Baru Open... Buka... Reopen Closed Tab Buka Kembali Tab yang Ditutup Split Bagi Left Kiri Right Kanan Up Atas Down Bawah Clear Kosongkan Delete Hapus %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sesi privat: isinya dibuang saat ditutup. Pilih Sesi > Pertahankan untuk mengubahnya menjadi sesi biasa. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privat] Reset All Settings Atur Ulang Semua Pengaturan Reset all settings to their default values? Atur ulang semua pengaturan ke nilai bawaan? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Ini mencakup tampilan, penyuntingan, format hasil, dan preferensi jendela. Perhitungan, sesi yang terbuka, dan definisi pengguna Anda akan dipertahankan. The settings file could not be written. Berkas pengaturan tidak dapat ditulis. Clear this session's calculations, unfinished expression, variables, functions, and units? Kosongkan perhitungan, ekspresi yang belum selesai, variabel, fungsi, dan satuan sesi ini? Global user definitions are kept. Definisi pengguna global dipertahankan. Make Session Private Jadikan Sesi Privat The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Sesi tersimpan %1 akan dihapus. Isinya akan tetap terbuka dalam sesi privat dan akan dibuang saat sesi itu ditutup atau SpeedCrunch dihentikan. Make Private Jadikan Privat Could not delete the saved session %1. Tidak dapat menghapus sesi tersimpan %1. Keep Session Pertahankan Sesi Could not save the session. It remains private. Tidak dapat menyimpan sesi. Sesi tetap privat. Clone Session Klonakan Sesi Could not save session file %1. Tidak dapat menyimpan berkas sesi %1. Could not delete session file %1. Tidak dapat menghapus berkas sesi %1. JSON file (*.json);;Any file (*.*) Berkas JSON (*.json);;Berkas apa pun (*.*) Export session as JSON Ekspor sesi sebagai JSON The selected file is not valid JSON: %1 Berkas yang dipilih bukan JSON valid: %1 The selected file is not a SpeedCrunch session JSON file. Berkas yang dipilih bukan berkas JSON sesi SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Berkas ini menggunakan format sesi SpeedCrunch usang dan tidak dapat diimpor. The selected JSON file is missing the required $schema field. Berkas JSON yang dipilih tidak memiliki bidang $schema yang diperlukan. The selected JSON file uses an unsupported JSON schema: %1 Berkas JSON yang dipilih menggunakan skema JSON yang tidak didukung: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Berkas JSON yang dipilih tidak memiliki pengenal skema sesi SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Berkas JSON yang dipilih menggunakan format sesi SpeedCrunch yang tidak didukung: %1 The selected JSON file is missing the required session name. Berkas JSON yang dipilih tidak memiliki nama sesi yang diperlukan. The selected JSON file has an empty session name. Berkas JSON yang dipilih memiliki nama sesi kosong. The selected JSON file has invalid or incomplete SpeedCrunch session data. Berkas JSON yang dipilih memiliki data sesi SpeedCrunch yang tidak valid atau tidak lengkap. Open Sessions Folder Buka folder sesi Could not create the sessions folder: %1 Tidak dapat membuat folder sesi: %1 Could not open the sessions folder: %1 Tidak dapat membuka folder sesi: %1 Editor and Results Font Font Penyunting dan Hasil Open Session Buka sesi Community Komunitas Rename Session Ubah nama sesi Clear Session Bersihkan sesi Delete Session Hapus sesi Close Pane Tutup panel User Variables Variabel pengguna User Units Satuan pengguna Clear History Bersihkan riwayat Are you sure you want to clear the calculation history? Anda yakin ingin membersihkan riwayat perhitungan? Session name: Nama sesi: A session named %1 already exists. Sesi bernama %1 sudah ada. Could not create session file %1. Tidak dapat membuat berkas sesi %1. Could not write session file %1. Tidak dapat menulis berkas sesi %1. Are you sure you want to delete this session? Anda yakin ingin menghapus sesi ini? Custom Precision Presisi kustom Fractional digits: Digit pecahan: Theme Tema Light Themes Tema terang Dark Themes Tema gelap Preview Pratinjau Colors Warna Select color for %1 Pilih warna untuk %1 Import... Impor... Export... Ekspor... Import Theme Impor tema Theme file (*.json);;All files (*) Berkas tema (*.json);;Semua berkas (*) Invalid theme file. Berkas tema tidak valid. Can't import theme "%1" because it conflicts with a built-in theme. Tidak dapat mengimpor tema "%1" karena bertentangan dengan tema bawaan. Can't find a writable theme folder. Tidak dapat menemukan folder tema yang dapat ditulis. Overwrite Theme Timpa tema A custom theme named "%1" already exists. Do you want to overwrite it? Tema kustom bernama "%1" sudah ada. Apakah Anda ingin menimpanya? Can't overwrite theme file %1 Tidak dapat menimpa berkas tema %1 Can't copy theme file to %1 Tidak dapat menyalin berkas tema ke %1 Export Theme Ekspor tema Can't export theme as "%1" because it conflicts with a built-in theme. Tidak dapat mengekspor tema sebagai "%1" karena bertentangan dengan tema bawaan. Can't write to file %1 Tidak dapat menulis ke berkas %1 Global User Variable Variabel pengguna global Global User Function Fungsi pengguna global Global User Unit Satuan pengguna global User Definitions Definisi Pengguna These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Definisi ini bersifat global dan dimuat ke setiap sesi. Definisi ini tidak dapat diubah dari sesi dan mengesampingkan definisi dengan nama yang sama dari editor sesi. Masukkan satu definisi per baris. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Contoh: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Terapkan Validate Validasi Test Results Hasil Pengujian Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variabel yang diimpor: %1 Fungsi yang diimpor: %2 Satuan yang diimpor: %3 Nomor baris dengan kesalahan: %4 none tidak ada Apply Results Hasil Penerapan User definitions saved. Definisi pengguna disimpan. History Size Limit Batas ukuran riwayat Maximum number of history entries for this session (0 = unlimited): Jumlah maksimum entri riwayat untuk sesi ini (0 = tak terbatas): Text file (*.txt);;Any file (*.*) Berkas teks (*.txt);;Berkas apa pun (*.*) Could not recalculate from calculation %1: %2 Tidak dapat menghitung ulang dari perhitungan %1: %2 History Size Limit Reached Batas ukuran riwayat tercapai This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Perhitungan ini mengisi slot riwayat terakhir yang tersedia. Perhitungan berikutnya akan menghapus perhitungan tertua dari riwayat. Anda dapat meningkatkan batas dari Sesi > Batas Ukuran Riwayat. Editing calculation. Press Esc twice to cancel. Mengedit perhitungan. Tekan Esc dua kali untuk membatalkan. Calculation Settings Pengaturan perhitungan Invalid recalculation start index Indeks awal penghitungan ulang tidak valid System Default Default Sistem Language Bahasa Select the language: Pilih bahasa: Custom Kustom Decimal places: Jumlah desimal: &Automatic Otom&atis &Precision &Presisi Plain &text &Teks polos Formula &Book Buku &Rumus &Export &Ekspor Export session as HTML Ekspor sesi sebagai HTML HTML file (*.html) Berkas HTML (*.html) Export session as plain text Ekspor sesi sebagai teks polos ManualWindow SpeedCrunch Manual Manual SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual SpeedCrunch NumberFormatDialog Number Format Format angka <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Pilih format angka untuk hasil dan pengelompokan digit masukan.</b><br/><br/>Catatan: format angka masukan yang tidak ambigu diterima meskipun berbeda dari format tampilan yang dipilih.<br/> QObject Global User Variable Variabel pengguna global Global User Function Fungsi pengguna global Global User Unit Satuan pengguna global Backspace Backspace Clear expression Bersihkan ekspresi Evaluate expression Evaluasi ekspresi Insert text Sisipkan teks Automatic decimal Desimal otomatis Fixed-point decimal Desimal titik tetap Engineering decimal Desimal teknik Scientific decimal Desimal ilmiah Rational Rasional Binary Biner Octal Oktal Hexadecimal Heksadesimal Sexagesimal Seksagesimal Update Available Pembaruan tersedia A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Versi yang lebih baru (%1) tersedia.<br/><a href="%2">Kunjungi situs web untuk mengunduh.</a> Check for Updates Periksa pembaruan SpeedCrunch %1 is up to date. SpeedCrunch %1 sudah mutakhir. No connectivity. Please check your internet connection and try again. Tidak ada konektivitas. Periksa koneksi internet Anda dan coba lagi. Could not verify the latest available version. Tidak dapat memverifikasi versi terbaru yang tersedia. ResultDisplay Scroll to bottom Gulir ke bawah Edit Expression Edit Ekspresi Change Settings Ubah pengaturan New Tab Tab baru &Import... &Impor... &Export &Ekspor Plain &text &Teks polos Copy Salin Selection Pilihan Select All Pilih Semua Expression Ekspresi Result Hasil Calculation Perhitungan Calculation as Single Line Perhitungan dalam Satu Baris Remove Hapus This Calculation Perhitungan Ini All Calculations Above Semua Perhitungan di Atas All Calculations Below Semua Perhitungan di Bawah New Private Tab Tab Privat Baru Session Sesi Open... Buka... Clone... Klonakan... Rename... Ubah Nama... Keep Pertahankan Make Private... Jadikan Privat... Clear Kosongkan Delete Hapus Close Tutup Split Bagi Left Kiri Right Kanan Up Atas Down Bawah Close Pane Tutup panel Main Menu Menu utama Cancel editing Batalkan pengeditan Copy result Salin hasil Edit expression Edit ekspresi Change settings Ubah pengaturan Remove calculation Hapus perhitungan ResultSlotsDialog Notation & Precision Notasi & Presisi Result Line Baris hasil Enabled Diaktifkan Notation Notasi Decimal Places Jumlah desimal Main Line Baris utama Extra Line #1 Baris tambahan #1 Extra Line #2 Baris tambahan #2 Extra Line #3 Baris tambahan #3 Extra Line #4 Baris tambahan #4 Auto Otomatis UserFunctionListWidget Name Nama Value Nilai Description Deskripsi Search Cari No match found Tidak ada yang cocok Insert Sisip Edit Edit Delete Hapus Delete All Hapus Semua UserUnitListWidget Name Nama Value Nilai Description Deskripsi Search Cari No match found Tidak ditemukan kecocokan Insert Sisipkan Edit Edit Delete Hapus Delete All Hapus semua VariableListWidget Name Nama Value Nilai Description Deskripsi Search Cari No match found Tidak ada yang cocok Insert Sisip Edit Edit Delete Hapus Delete All Hapus Semua heldercorreia-speedcrunch-e7ca37f/src/resources/locale/it.ts000066400000000000000000010615421526573132500243720ustar00rootroot00000000000000 AboutBox About SpeedCrunch Informazioni su SpeedCrunch Core developers Sviluppatori principali Original author Autore originale Close Chiudi Math engine Motore matematico Main author | Logo | Maintainer Autore principale | Logo | Manutentore Thanks Ringraziamenti Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Gli sviluppatori di SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Questo programma è software libero; può essere ridistribuito e/o modificato sotto i termini della GNU General Public License come pubblicata dalla Free Software Foundation; sia la versione 2 della licenza che, a vostra discrezione, qualsiasi versione successiva This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Questo programma è distribuito nella speranza che possa essere utile, ma SENZA ALCUNA GARANZIA; senza neppure l'implicita garanzia di COMMERCIABILITÀ o IDONEITÀ PER UNO SCOPO PARTICOLARE. Consultare la GNU General Public License per maggiori dettagli. BitFieldWidget Reset bits to zero Reimposta i bit a zero Invert bits Inverti i bit Shift bits left Sposta i bit a sinistra Shift bits right Sposta i bit a destra Book Index Indice Algebra Algebra Quadratic Equation Equazione di secondo grado Logarithmic Base Conversion Conversione della base logaritmica Geometry Geometria Circle Circonferenza Sector Settore Sphere Sfera Cube Cubo Cone Cono Cylinder Cilindro Electronics Elettronica Ohm's Law Legge di Ohm Power Potenza Reactance Reattanza Resonance Risonanza Radio Frequency Frequenza radio Antennas Antenne Characteristic Impedance (coax) Impedenza caratteristica (coassiale) Velocity of Propagation (coax) Velocità di propagazione (coassiale) Standing Wave Ratio & Return Loss Rapporto di onda stazionaria e perdita di ritorno Free Space Wavelength Lunghezza d'onda nel vuoto resistance resistenza voltage tensione current corrente power potenza inductive reactance reattanza induttiva capacitive reactance reattanza capacitiva inductance induttanza capacitance capacità frequency frequenza resonance frequency frequenza di risonanza area area perimeter perimetro diameter diametro radius raggio volume volume surface area area della superficie height altezza slant height apotema face diagonal diagonale della faccia space diagonal diagonale spaziale edge length lunghezza dello spigolo arc length lunghezza dell'arco central angle (degrees) angolo al centro (gradi) input power potenza in ingresso reflected power potenza riflessa transmitted power potenza trasmessa return loss perdita di ritorno dielectric constant costante dielettrica outer conductor's inner diameter diametro interno del conduttore esterno inner conductor's outer diameter diametro esterno del conduttore interno speed of light velocità della luce reflection coefficient coefficiente di riflessione standing wave ratio rapporto di onda stazionaria normalized impedance impedenza normalizzata frequency (Hz) frequenza (Hz) BookDock Formula Book Raccolta di formule ConstantCompletion Search constants Cerca costanti No match found Nessuna corrispondenza trovata Constants Mathematics Matematica Physics (CODATA 2022) Fisica (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chimica (IUPAC - CIAAW 2021) Uncategorized Senza categoria Universal Universale Physicochemical Fisico-chimica Atomic & Nuclear — General Atomica e nucleare — Generale Atomic & Nuclear — Electroweak Atomica e nucleare — Elettrodebole Atomic & Nuclear — Electron Atomica e nucleare — Elettrone Atomic & Nuclear — Muon Atomica e nucleare — Muone Atomic & Nuclear — Tau Atomica e nucleare — Tau Atomic & Nuclear — Proton Atomica e nucleare — Protone Atomic & Nuclear — Neutron Atomica e nucleare — Neutrone Atomic & Nuclear — Deuteron Atomica e nucleare — Deuterone Atomic & Nuclear — Triton Atomica e nucleare — Tritone Atomic & Nuclear — Helion Atomica e nucleare — Elione Atomic & Nuclear — Alpha particle Atomica e nucleare — Particella alfa Atomic & Nuclear — Atomic units Atomica e nucleare — Unità atomiche Atomic & Nuclear — Energy conversion relationships Atomica e nucleare — Relazioni di conversione dell’energia Atomic & Nuclear — X-ray units Atomica e nucleare — Unità radiologiche Atomic & Nuclear — Magnetic shielding corrections Atomica e nucleare — Correzioni di schermatura magnetica Masses Masse Lifetimes Vite medie Molar Masses Masse molari Electronegativity Elettronegatività Ionization Energy Energia di ionizzazione Nominal Constants (IAU 2015) Costanti nominali (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Migliori stime attuali (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) impedenza caratteristica del vuoto (Zâ‚€) reduced Planck constant (â„�) costante di Planck ridotta (â„�) vacuum electric permittivity (ϵ₀) permittività elettrica del vuoto (ϵ₀) Newtonian constant of gravitation (G) costante di gravitazione newtoniana (G) vacuum magnetic permeability (μ₀) permeabilità magnetica del vuoto (μ₀) Planck constant (h) costante di Planck (h) speed of light in vacuum (c) velocità della luce nel vuoto (c) standard acceleration of gravity (gâ‚™) accelerazione standard di gravità (gâ‚™) Newtonian constant of gravitation over h-bar c costante di gravitazione newtoniana divisa per h-bar c Planck length lunghezza di Planck Planck constant in eV/Hz (h) costante di Planck in eV/Hz (h) Planck mass massa di Planck Planck mass energy equivalent in GeV equivalente energetico della massa di Planck in GeV Planck temperature temperatura di Planck Planck time tempo di Planck reduced Planck constant in eV·s (â„�) costante di Planck ridotta in eV·s (â„�) reduced Planck constant times c in MeV·fm costante di Planck ridotta moltiplicata per c in MeV·fm Bohr magneton magnetone di Bohr conductance quantum (Gâ‚€) quanto di conduttanza (Gâ‚€) Coulomb constant (kâ‚‘) costante di Coulomb (kâ‚‘) elementary charge (e) carica elementare (e) elementary charge over h-bar carica elementare divisa per h-bar conventional value of Josephson constant valore convenzionale della costante di Josephson Josephson constant costante di Josephson conventional value of ampere-90 valore convenzionale di ampere-90 conventional value of coulomb-90 valore convenzionale di coulomb-90 conventional value of farad-90 valore convenzionale di farad-90 conventional value of henry-90 valore convenzionale di henry-90 conventional value of ohm-90 valore convenzionale di ohm-90 conventional value of volt-90 valore convenzionale di volt-90 conventional value of watt-90 valore convenzionale di watt-90 magnetic flux quantum (Φ₀) quanto di flusso magnetico (Φ₀) nuclear magneton magnetone nucleare inverse of conductance quantum inverso di quanto di conduttanza conventional value of von Klitzing constant valore convenzionale della costante di von Klitzing von Klitzing constant costante di von Klitzing atomic unit of magnetic dipole moment unità atomica di momento di dipolo magnetico atomic unit of magnetic flux density unità atomica di densità di flusso magnetico Bohr magneton in eV/T magnetone di Bohr in eV/T Bohr magneton in Hz/T magnetone di Bohr in Hz/T Bohr magneton in inverse meter per tesla magnetone di Bohr in metro inverso per tesla Bohr magneton in K/T magnetone di Bohr in K/T nuclear magneton in eV/T magnetone nucleare in eV/T nuclear magneton in inverse meter per tesla magnetone nucleare in metro inverso per tesla nuclear magneton in K/T magnetone nucleare in K/T nuclear magneton in MHz/T magnetone nucleare in MHz/T Bohr radius (aâ‚€) raggio di Bohr (aâ‚€) fine-structure constant (α) costante di struttura fine (α) Hartree energy (Eâ‚•) energia di Hartree (Eâ‚•) Hartree energy in eV energia di Hartree in eV quantum of circulation quanto di circolazione quantum of circulation times 2 quanto di circolazione moltiplicato per 2 Rydberg constant (R∞) costante di Rydberg (R∞) atomic mass unit-hartree relationship relazione tra unità di massa atomica e hartree atomic mass unit-hertz relationship relazione tra unità di massa atomica e hertz atomic mass unit-inverse meter relationship relazione tra unità di massa atomica e metro inverso atomic mass unit-joule relationship relazione tra unità di massa atomica e joule atomic mass unit-kelvin relationship relazione tra unità di massa atomica e kelvin atomic mass unit-kilogram relationship relazione tra unità di massa atomica e chilogrammo atomic unit of 1st hyperpolarizability unità atomica di iperpolarizzabilità del primo ordine atomic unit of 2nd hyperpolarizability unità atomica di iperpolarizzabilità del secondo ordine atomic unit of charge (e) unità atomica di carica (e) atomic unit of charge density unità atomica di densità di carica atomic unit of current unità atomica di corrente atomic unit of electric dipole moment unità atomica di momento di dipolo elettrico atomic unit of electric field unità atomica di campo elettrico atomic unit of electric field gradient unità atomica di gradiente del campo elettrico atomic unit of electric polarizability unità atomica di polarizzabilità elettrica atomic unit of electric potential unità atomica di potenziale elettrico atomic unit of electric quadrupole moment unità atomica di momento di quadrupolo elettrico atomic unit of action unità atomica di azione atomic unit of energy unità atomica di energia atomic unit of force unità atomica di forza atomic unit of length unità atomica di lunghezza hertz-atomic mass unit relationship relazione tra hertz e unità di massa atomica hertz-electron volt relationship relazione tra hertz e elettronvolt hertz-hartree relationship relazione tra hertz e hartree hertz-inverse meter relationship relazione tra hertz e metro inverso hertz-joule relationship relazione tra hertz e joule hertz-kelvin relationship relazione tra hertz e kelvin hertz-kilogram relationship relazione tra hertz e chilogrammo hyperfine transition frequency of Cs-133 frequenza di transizione iperfine del Cs-133 inverse fine-structure constant (αâ�»Â¹) costante di struttura fine inversa (αâ�»Â¹) inverse meter-atomic mass unit relationship relazione tra metro inverso e unità di massa atomica inverse meter-electron volt relationship relazione tra metro inverso e elettronvolt inverse meter-hartree relationship relazione tra metro inverso e hartree inverse meter-hertz relationship relazione tra metro inverso e hertz inverse meter-joule relationship relazione tra metro inverso e joule inverse meter-kelvin relationship relazione tra metro inverso e kelvin inverse meter-kilogram relationship relazione tra metro inverso e chilogrammo joule-atomic mass unit relationship relazione tra joule e unità di massa atomica joule-electron volt relationship relazione tra joule e elettronvolt joule-hertz relationship relazione tra joule e hertz joule-hartree relationship relazione tra joule e hartree joule-inverse meter relationship relazione tra joule e metro inverso joule-kelvin relationship relazione tra joule e kelvin joule-kilogram relationship relazione tra joule e chilogrammo kelvin-atomic mass unit relationship relazione tra kelvin e unità di massa atomica kelvin-electron volt relationship relazione tra kelvin e elettronvolt kelvin-hertz relationship relazione tra kelvin e hertz kelvin-hartree relationship relazione tra kelvin e hartree kelvin-inverse meter relationship relazione tra kelvin e metro inverso kelvin-joule relationship relazione tra kelvin e joule kelvin-kilogram relationship relazione tra kelvin e chilogrammo kilogram-atomic mass unit relationship relazione tra chilogrammo e unità di massa atomica kilogram-electron volt relationship relazione tra chilogrammo e elettronvolt kilogram-hertz relationship relazione tra chilogrammo e hertz kilogram-hartree relationship relazione tra chilogrammo e hartree kilogram-inverse meter relationship relazione tra chilogrammo e metro inverso kilogram-joule relationship relazione tra chilogrammo e joule kilogram-kelvin relationship relazione tra chilogrammo e kelvin lattice parameter of silicon (a) parametro reticolare del silicio (a) luminous efficacy efficacia luminosa natural unit of energy unità naturale di energia natural unit of energy in MeV unità naturale di energia in MeV natural unit of action (â„�) unità naturale di azione (â„�) natural unit of action in eV·s unità naturale di azione in eV·s natural unit of length unità naturale di lunghezza natural unit of mass unità naturale di massa natural unit of momentum unità naturale di quantità di moto natural unit of momentum in MeV/c unità naturale di quantità di moto in MeV/c natural unit of time unità naturale di tempo natural unit of velocity unità naturale di velocità Rydberg constant times c in Hz costante di Rydberg moltiplicata per c in Hz Rydberg constant times hc in eV costante di Rydberg moltiplicata per hc in eV Rydberg constant times hc in J costante di Rydberg moltiplicata per hc in J Fermi coupling constant costante di accoppiamento di Fermi weak mixing angle angolo di mescolamento debole W to Z mass ratio rapporto di massa W-Z Thomson cross section (σₑ) sezione d’urto di Thomson (σₑ) electron mass (mâ‚‘) massa dell'elettrone (mâ‚‘) electron mass in u massa dell'elettrone in u electron mass energy equivalent (mₑ·c²) equivalente energetico della massa dell'elettrone (mₑ·c²) electron mass energy equivalent in MeV equivalente energetico della massa dell'elettrone in MeV reduced Compton wavelength ridotta lunghezza d’onda di Compton classical electron radius (râ‚‘) classico elettrone raggio (râ‚‘) electron charge to mass quotient quoziente carica-massa dell'elettrone electron-deuteron magnetic moment ratio rapporto tra i momenti magnetici dell'elettrone e del deuterone electron-deuteron mass ratio rapporto tra la massa dell'elettrone e quella del deuterone electron g factor (gâ‚‘) fattore g dell'elettrone (gâ‚‘) electron gyromagnetic ratio (γₑ) rapporto giromagnetico dell'elettrone (γₑ) electron gyromagnetic ratio in MHz/T rapporto giromagnetico dell'elettrone in MHz/T electron-helion mass ratio rapporto tra la massa dell'elettrone e quella dell'elione electron magnetic moment (μₑ) momento magnetico dell'elettrone (μₑ) electron magnetic moment anomaly (aâ‚‘) elettrone anomalia del momento magnetico (aâ‚‘) electron magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico dell'elettrone e il magnetone di Bohr electron magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico dell'elettrone e il magnetone nucleare electron molar mass (Mâ‚‘) massa molare dell'elettrone (Mâ‚‘) electron-muon magnetic moment ratio rapporto tra i momenti magnetici dell'elettrone e del muone electron-muon mass ratio rapporto tra la massa dell'elettrone e quella del muone electron-neutron magnetic moment ratio rapporto tra i momenti magnetici dell'elettrone e del neutrone electron-neutron mass ratio rapporto tra la massa dell'elettrone e quella del neutrone electron-proton magnetic moment ratio rapporto tra i momenti magnetici dell'elettrone e del protone electron-proton mass ratio rapporto tra la massa dell'elettrone e quella del protone electron relative atomic mass (Ar(e)) massa atomica relativa dell'elettrone (Ar(e)) electron-tau mass ratio rapporto tra la massa dell'elettrone e quella del tau electron to alpha particle mass ratio rapporto tra la massa dell'elettrone e quella della particella alfa electron to shielded helion magnetic moment ratio rapporto tra i momenti magnetici dell'elettrone e dell'elione schermato electron to shielded proton magnetic moment ratio rapporto tra i momenti magnetici dell'elettrone e del protone schermato electron-triton mass ratio rapporto tra la massa dell'elettrone e quella del tritone electron volt-atomic mass unit relationship relazione tra elettronvolt e unità di massa atomica electron volt-hartree relationship relazione tra elettronvolt e hartree electron volt-hertz relationship relazione tra elettronvolt e hertz electron volt-inverse meter relationship relazione tra elettronvolt e metro inverso electron volt-joule relationship relazione tra elettronvolt e joule electron volt-kelvin relationship relazione tra elettronvolt e kelvin electron volt-kilogram relationship relazione tra elettronvolt e chilogrammo hartree-atomic mass unit relationship relazione tra hartree e unità di massa atomica hartree-electron volt relationship relazione tra hartree e elettronvolt muon Compton wavelength lunghezza d'onda Compton del muone muon-electron mass ratio rapporto tra la massa del muone e quella dell'elettrone muon g factor fattore g del muone muon magnetic moment momento magnetico del muone muon magnetic moment anomaly anomalia del momento magnetico del muone muon magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico del muone e il magnetone di Bohr muon magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico del muone e il magnetone nucleare muon mass massa del muone muon mass energy equivalent equivalente energetico della massa del muone muon mass energy equivalent in MeV equivalente energetico della massa del muone in MeV muon mass in u massa del muone in u muon molar mass massa molare del muone muon-neutron mass ratio rapporto tra la massa del muone e quella del neutrone muon-proton magnetic moment ratio rapporto tra i momenti magnetici del muone e del protone muon-proton mass ratio rapporto tra la massa del muone e quella del protone muon-tau mass ratio rapporto tra la massa del muone e quella del tau reduced muon Compton wavelength lunghezza d'onda Compton ridotta del muone reduced tau Compton wavelength lunghezza d'onda Compton ridotta del tau tau Compton wavelength lunghezza d'onda Compton del tau tau-electron mass ratio rapporto tra la massa del tau e quella dell'elettrone tau mass massa del tau tau mass energy equivalent equivalente energetico della massa del tau tau mass in u massa del tau in u tau molar mass massa molare del tau tau-muon mass ratio rapporto tra la massa del tau e quella del muone tau-neutron mass ratio rapporto tra la massa del tau e quella del neutrone tau-proton mass ratio rapporto tra la massa del tau e quella del protone proton charge to mass quotient quoziente carica-massa del protone proton Compton wavelength lunghezza d'onda Compton del protone proton-electron mass ratio rapporto tra la massa del protone e quella dell'elettrone proton g factor (gₚ) fattore g del protone (gₚ) proton gyromagnetic ratio (γₚ) rapporto giromagnetico del protone (γₚ) proton gyromagnetic ratio in MHz/T rapporto giromagnetico del protone in MHz/T proton magnetic moment (μₚ) momento magnetico del protone (μₚ) proton magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico del protone e il magnetone di Bohr proton magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico del protone e il magnetone nucleare proton magnetic shielding correction correzione di schermatura magnetica del protone proton mass (mₚ) massa del protone (mₚ) proton mass energy equivalent equivalente energetico della massa del protone proton mass energy equivalent in MeV equivalente energetico della massa del protone in MeV proton mass in u massa del protone in u proton molar mass (Mₚ) massa molare del protone (Mₚ) proton-muon mass ratio rapporto tra la massa del protone e quella del muone proton-neutron magnetic moment ratio rapporto tra i momenti magnetici del protone e del neutrone proton-neutron mass ratio rapporto tra la massa del protone e quella del neutrone proton relative atomic mass (Ar(p)) massa atomica relativa del protone (Ar(p)) proton rms charge radius raggio di carica rms del protone proton-tau mass ratio rapporto tra la massa del protone e quella del tau reduced proton Compton wavelength lunghezza d'onda Compton ridotta del protone shielded proton gyromagnetic ratio rapporto giromagnetico del protone schermato shielded proton gyromagnetic ratio in MHz/T rapporto giromagnetico del protone schermato in MHz/T shielded proton magnetic moment momento magnetico del protone schermato shielded proton magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico del protone schermato e il magnetone di Bohr shielded proton magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico del protone schermato e il magnetone nucleare neutron Compton wavelength lunghezza d'onda Compton del neutrone neutron-electron magnetic moment ratio rapporto tra i momenti magnetici del neutrone e dell'elettrone neutron-electron mass ratio rapporto tra la massa del neutrone e quella dell'elettrone neutron g factor (gâ‚™) fattore g del neutrone (gâ‚™) neutron gyromagnetic ratio (γₙ) rapporto giromagnetico del neutrone (γₙ) neutron gyromagnetic ratio in MHz/T rapporto giromagnetico del neutrone in MHz/T neutron magnetic moment (μₙ) momento magnetico del neutrone (μₙ) neutron magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico del neutrone e il magnetone di Bohr neutron magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico del neutrone e il magnetone nucleare neutron mass (mâ‚™) massa del neutrone (mâ‚™) neutron mass energy equivalent equivalente energetico della massa del neutrone neutron mass energy equivalent in MeV equivalente energetico della massa del neutrone in MeV neutron mass in u massa del neutrone in u neutron molar mass (Mâ‚™) massa molare del neutrone (Mâ‚™) neutron-muon mass ratio rapporto tra la massa del neutrone e quella del muone neutron-proton magnetic moment ratio rapporto tra i momenti magnetici del neutrone e del protone neutron-proton mass difference differenza di massa neutrone-protone neutron-proton mass difference energy equivalent equivalente energetico della differenza di massa neutrone-protone neutron-proton mass difference energy equivalent in MeV equivalente energetico della differenza di massa neutrone-protone in MeV neutron-proton mass difference in u differenza di massa neutrone-protone in u neutron-proton mass ratio rapporto tra la massa del neutrone e quella del protone neutron relative atomic mass (Ar(n)) massa atomica relativa del neutrone (Ar(n)) neutron-tau mass ratio rapporto tra la massa del neutrone e quella del tau neutron to shielded proton magnetic moment ratio rapporto tra i momenti magnetici del neutrone e del protone schermato reduced neutron Compton wavelength lunghezza d'onda Compton ridotta del neutrone deuteron-electron magnetic moment ratio rapporto tra i momenti magnetici del deuterone e dell'elettrone deuteron-electron mass ratio rapporto tra la massa del deuterone e quella dell'elettrone deuteron g factor fattore g del deuterone deuteron magnetic moment momento magnetico del deuterone deuteron magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico del deuterone e il magnetone di Bohr deuteron magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico del deuterone e il magnetone nucleare deuteron mass massa del deuterone deuteron mass energy equivalent equivalente energetico della massa del deuterone deuteron mass energy equivalent in MeV equivalente energetico della massa del deuterone in MeV deuteron mass in u massa del deuterone in u deuteron molar mass massa molare del deuterone deuteron-neutron magnetic moment ratio rapporto tra i momenti magnetici del deuterone e del neutrone deuteron-proton magnetic moment ratio rapporto tra i momenti magnetici del deuterone e del protone deuteron-proton mass ratio rapporto tra la massa del deuterone e quella del protone deuteron relative atomic mass (Ar(d)) massa atomica relativa del deuterone (Ar(d)) deuteron rms charge radius raggio di carica rms del deuterone triton-electron mass ratio rapporto tra la massa del tritone e quella dell'elettrone triton g factor (gₜ) fattore g del tritone (gₜ) triton magnetic moment (μₜ) momento magnetico del tritone (μₜ) triton magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico del tritone e il magnetone di Bohr triton magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico del tritone e il magnetone nucleare triton mass (mₜ) massa del tritone (mₜ) triton mass energy equivalent equivalente energetico della massa del tritone triton mass energy equivalent in MeV equivalente energetico della massa del tritone in MeV triton mass in u massa del tritone in u triton molar mass (Mₜ) massa molare del tritone (Mₜ) triton-proton mass ratio rapporto tra la massa del tritone e quella del protone triton relative atomic mass (Ar(t)) massa atomica relativa del tritone (Ar(t)) triton to proton magnetic moment ratio rapporto tra i momenti magnetici del tritone e del protone helion-electron mass ratio rapporto tra la massa dell'elione e quella dell'elettrone helion g factor (gâ‚•) fattore g dell'elione (gâ‚•) helion magnetic moment (μₕ) momento magnetico dell'elione (μₕ) helion magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico dell'elione e il magnetone di Bohr helion magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico dell'elione e il magnetone nucleare helion mass (mâ‚•) massa dell'elione (mâ‚•) helion mass energy equivalent equivalente energetico della massa dell'elione helion mass energy equivalent in MeV equivalente energetico della massa dell'elione in MeV helion mass in u massa dell'elione in u helion molar mass (Mâ‚•) massa molare dell'elione (Mâ‚•) helion-proton mass ratio rapporto tra la massa dell'elione e quella del protone helion relative atomic mass (Ar(h)) massa atomica relativa dell'elione (Ar(h)) helion shielding shift spostamento di schermatura dell'elione shielded helion gyromagnetic ratio rapporto giromagnetico dell'elione schermato shielded helion gyromagnetic ratio in MHz/T rapporto giromagnetico dell'elione schermato in MHz/T shielded helion magnetic moment momento magnetico dell'elione schermato shielded helion magnetic moment to Bohr magneton ratio rapporto tra il momento magnetico dell'elione schermato e il magnetone di Bohr shielded helion magnetic moment to nuclear magneton ratio rapporto tra il momento magnetico dell'elione schermato e il magnetone nucleare shielded helion to proton magnetic moment ratio rapporto tra i momenti magnetici dell'elione schermato e del protone shielded helion to shielded proton magnetic moment ratio rapporto tra i momenti magnetici dell'elione schermato e del protone schermato alpha particle mass massa della particella alfa alpha particle mass in u massa della particella alfa in u alpha particle mass energy equivalent equivalente energetico della massa della particella alfa alpha particle mass energy equivalent in MeV equivalente energetico della massa della particella alfa in MeV alpha particle-electron mass ratio rapporto tra la massa della particella alfa e quella dell'elettrone alpha particle-proton mass ratio rapporto tra la massa della particella alfa e quella del protone alpha particle rms charge radius raggio di carica rms della particella alfa alpha particle molar mass massa molare della particella alfa alpha particle relative atomic mass (Ar(α)) massa atomica relativa della particella alfa (Ar(α)) atomic mass constant (mᵤ) costante di massa atomica (mᵤ) Avogadro constant costante di Avogadro Boltzmann constant (k) costante di Boltzmann (k) Boltzmann constant in eV/K costante di Boltzmann in eV/K Boltzmann constant in Hz/K costante di Boltzmann in Hz/K Boltzmann constant in inverse meter per kelvin costante di Boltzmann in metri inversi per kelvin electron volt (eV) elettronvolt (eV) Faraday constant (F) costante di Faraday (F) first radiation constant (câ‚�) prima costante di radiazione (câ‚�) first radiation constant for spectral radiance prima costante di radiazione per la radianza spettrale molar gas constant (R) costante molare dei gas (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) costante di Loschmidt (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) costante di Loschmidt (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant costante molare di Planck second radiation constant (câ‚‚) seconda costante di radiazione (câ‚‚) Stefan-Boltzmann constant (σ) costante di Stefan-Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) spaziatura reticolare del Si ideale (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent equivalente energetico della costante di massa atomica atomic mass constant energy equivalent in MeV equivalente energetico della costante di massa atomica in MeV atomic mass unit-electron volt relationship relazione tra unità di massa atomica e elettronvolt molar mass constant (Mᵤ) costante di massa molare (Mᵤ) molar mass of carbon-12 massa molare del carbonio-12 molar volume of ideal gas (273.15 K, 100 kPa) volume molare del gas ideale (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volume molare del gas ideale (273.15 K, 101.325 kPa) molar volume of silicon volume molare del silicio Sackur-Tetrode constant (1 K, 100 kPa) costante di Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) costante di Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant costante della legge dello spostamento in frequenza di Wien Wien wavelength displacement law constant costante della legge dello spostamento in lunghezza d’onda di Wien standard atmosphere (atm) atmosfera standard (atm) standard-state pressure (p°) pressione allo stato standard (p°) Angstrom star (Ã…*) Ã¥ngström star (Ã…*) Copper x unit unità x del rame Molybdenum x unit unità x del molibdeno atomic unit of magnetizability unità atomica di magnetizzabilità atomic unit of mass (mâ‚‘) unità atomica di massa (mâ‚‘) atomic unit of momentum unità atomica di quantità di moto atomic unit of permittivity unità atomica di permittività atomic unit of time unità atomica di tempo atomic unit of velocity unità atomica di velocità hartree-hertz relationship relazione tra hartree e hertz hartree-inverse meter relationship relazione tra hartree e metro inverso hartree-joule relationship relazione tra hartree e joule hartree-kelvin relationship relazione tra hartree e kelvin hartree-kilogram relationship relazione tra hartree e chilogrammo shielding difference of d and p in HD differenza di schermatura tra d e p in HD shielding difference of t and p in HT differenza di schermatura tra t e p in HT pi (Ï€) pi greco (Ï€) Euler's number (e) numero di Eulero (e) golden ratio (φ) rapporto aureo (φ) Euler-Mascheroni constant (γ) costante di Eulero-Mascheroni (γ) nominal solar radius raggio solare nominale nominal solar total irradiance irradianza solare totale nominale nominal solar luminosity luminosità solare nominale nominal solar effective temperature temperatura efficace solare nominale nominal solar mass parameter parametro di massa solare nominale nominal terrestrial equatorial radius raggio equatoriale terrestre nominale nominal terrestrial polar radius raggio polare terrestre nominale nominal terrestrial mass parameter parametro di massa terrestre nominale nominal jovian equatorial radius raggio equatoriale gioviano nominale nominal jovian polar radius raggio polare gioviano nominale nominal jovian mass parameter parametro di massa gioviano nominale average value of one minus the rate of TCG relative to TCB valore medio di uno meno il tasso di TCG rispetto a TCB solar mass parameter (TCB-compatible) parametro di massa solare (compatibile con TCB) solar mass parameter (TDB-compatible) parametro di massa solare (compatibile con TDB) equatorial radius of the Earth (TT-compatible) raggio equatoriale della Terra (compatibile con TT) dynamical form factor of the Earth fattore di forma dinamico della Terra time rate of change in the dynamical form factor of the Earth tasso temporale di variazione del fattore di forma dinamico della Terra geocentric gravitational constant (TCB-compatible) costante gravitazionale geocentrica (compatibile con TCB) geocentric gravitational constant (TT-compatible) costante gravitazionale geocentrica (compatibile con TT) geocentric gravitational constant (TDB-compatible) costante gravitazionale geocentrica (compatibile con TDB) potential of the geoid potenziale del geoide nominal mean angular velocity of the Earth (TT-compatible) velocità angolare media nominale della Terra (compatibile con TT) ratio mass of the Moon to the Earth rapporto tra la massa della Luna e quella della Terra ratio of the mass of the Sun to Mercury rapporto tra la massa del Sole e quella di Mercurio ratio of the mass of the Sun to Venus rapporto tra la massa del Sole e quella di Venere ratio of the mass of the Sun to Mars rapporto tra la massa del Sole e quella di Marte ratio of the mass of the Sun to Jupiter rapporto tra la massa del Sole e quella di Giove ratio of the mass of the Sun to Saturn rapporto tra la massa del Sole e quella di Saturno ratio of the mass of the Sun to Uranus rapporto tra la massa del Sole e quella di Urano ratio of the mass of the Sun to Neptune rapporto tra la massa del Sole e quella di Nettuno ratio of the mass of the Sun to (134340) Pluto rapporto tra la massa del Sole e quella di (134340) Plutone ratio of the mass of the Sun to (136199) Eris rapporto tra la massa del Sole e quella di (136199) Eris ratio of the mass of (1) Ceres to the Sun rapporto tra la massa di (1) Cerere e quella del Sole ratio of the mass of (2) Pallas to the Sun rapporto tra la massa di (2) Pallade e quella del Sole ratio of the mass of (4) Vesta to the Sun rapporto tra la massa di (4) Vesta e quella del Sole mean obliquity of the ecliptic at J2000.0 obliquità media dell'eclittica a J2000.0 Electromagnetic Elettromagnetico Compton wavelength Lunghezza d'onda Compton Astronomy Astronomia ConstantsWidget Domain Dominio Subdomain Sottodominio No match found Nessuna corrispondenza Name Nome Value Valore Unit Unità Search Cerca All Tutto CustomKeypadDialog Custom Keypad Tastierino personalizzato Rows: Righe: Columns: Colonne: Copy preset: Copia preimpostazione: Basic Base Scientific (wide) Scientifico (ampio) Scientific (narrow) Scientifico (stretto) Apply Applica Row Riga Column Colonna Label Etichetta Behavior Comportamento Text Testo DiagnosticsDialog App Diagnostics Diagnostica dell’applicazione Copy to Clipboard Copia negli appunti Editor Unit Unità User unit Unità utente User function Funzione utente Argument Argomento Current result:<br/>%1 Risultato corrente:<br/>%1 Selection result:<br/>%1 Risultato della selezione:<br/>%1 Selection result: n/a Risultato della selezione: n.d. Selection result: %1 Risultato della selezione: %1 second secondo metre metro kilogram chilogrammo mole mole radian radiante steradian steradiante degree Celsius grado Celsius cubic metre metro cubo cubic millimetre millimetro cubo cubic centimetre centimetro cubo cubic decimetre decimetro cubo cubic kilometre chilometro cubo square millimetre millimetro quadrato square kilometre chilometro quadrato square metre metro quadrato minute minuto hour ora day giorno astronomical unit unità astronomica degree grado arcminute minuto d'arco arcsecond secondo d'arco milliarcsecond millisecondo d'arco microarcsecond microsecondo d'arco hectare ettaro litre litro tonne tonnellata Dalton dalton electronvolt elettronevolt Angstrom Ã¥ngström atmosphere atmosfera atomic mass unit unità di massa atomica British thermal unit unità termica britannica calorie caloria carat carato cup tazza cup (Imperial) tazza (imperiale) cup (Japanese) tazza (giapponese) cup (US) tazza (USA) degree Fahrenheit grado Fahrenheit fathom braccio fluid ounce (Imperial) oncia fluida (imperiale) fluid ounce (US) oncia fluida (USA) fluid dram (Imperial) dramma fluido (imperiale) fluid dram (US) dramma fluido (USA) foot piede square foot piede quadrato cubic foot piede cubo gallon (Imperial) gallone (imperiale) gallon (US) gallone (USA) gill (Imperial) gill (imperiale) gill (US) gill (USA) gradian gradiante grain grano gram grammo Hartley hartley Hartree energy unit unità di energia di Hartree horsepower cavallo vapore inch pollice square inch pollice quadrato cubic inch pollice cubo karat carato knot nodo lightminute minuto luce lightsecond secondo luce lightyear anno luce long ton tonnellata lunga mile miglio square mile miglio quadrato cubic mile miglio cubo mile per hour miglia all'ora kilometre per hour chilometri all'ora nautical mile miglio nautico ounce oncia parsec parsec pint (Imperial) pinta (imperiale) pint (US) pinta (USA) pound libbra pounds per square inch libbre per pollice quadrato quart (Imperial) quarto (imperiale) quart (US) quarto (USA) oil barrel barile di petrolio beer barrel (US) barile di birra (USA) square yard iarda quadrata cubic yard iarda cubica short ton tonnellata corta tablespoon cucchiaio tablespoon (Australian) cucchiaio (australiano) tablespoon (Imperial) cucchiaio (imperiale) tablespoon (US) cucchiaio (USA) dessert spoon cucchiaio da dessert teaspoon cucchiaino teaspoon (Imperial) cucchiaino (imperiale) teaspoon (US) cucchiaino (USA) turn giro revolution rivoluzione revolution per minute rivoluzioni al minuto week settimana kilowatt hour chilowattora millimetre of mercury millimetro di mercurio yard iarda Julian century secolo giuliano Julian year anno giuliano sidereal year anno siderale tropical year anno tropico Evaluator invalid expression espressione non valida division by zero divisione per zero too time consuming - computation was rejected richiede troppo tempo - il calcolo è stato rifiutato dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensioni non corrispondenti - quantità con dimensioni diverse non possono essere confrontate, sommate, ecc. invalid dimension - operation might require dimensionless arguments dimensione non valida - l'operazione potrebbe richiedere argomenti adimensionali Computation aborted - encountered numerical instability Calcolo interrotto - rilevata instabilità numerica invalid dimension - function might require dimensionless arguments dimensione non valida - la funzione potrebbe richiedere argomenti adimensionali error errore unit must not be zero l'unità non deve essere zero Conversion failed - dimension mismatch Conversione non riuscita - dimensioni non corrispondenti unknown function or variable funzione o variabile sconosciuta recursion not supported ricorsione non supportata cannot operate on a NaN impossibile operare su un NaN underflow - tiny result is out of SpeedCrunch's number range underflow - il valore risultante è troppo piccolo per essere rappresentato da SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflow - il valore risultante è troppo grande per essere rappresentato da SpeedCrunch overflow - logic result exceeds maximum of 256 bits overflow - il risultato logico eccede il valore massimo di 256 bits overflow - integer result exceeds maximum limit for integers overflow - il risultato in formato intero eccede il valore massimo per gli interi operation is not defined for these arguments operazione non definita per questi argomenti wrong number of arguments numero di argomenti errato does not take NaN as an argument non sono accettati NaN (Not-a-Number) come argomento result out of range risultato fuori range undefined for argument domain non definito nel dominio dell'argomento computation too expensive calcolo troppo complesso internal error, please report a bug errore interno, segnalare il problema syntax error errore di sintassi conversion target must be a unit la destinazione della conversione deve essere un'unità unknown unit unità sconosciuta %1 is a reserved name, please choose another %1 è un nome riservato, sceglierne un altro %1 is a global user definition and cannot be overridden in this session. %1 è una definizione utente globale e non può essere sovrascritta in questa sessione. %1 is a variable name, please choose another or delete the variable %1 è il nome di una variabile, sceglierne un altro o eliminare la variabile argument %1 is used more than once l'argomento %1 è usato più di una volta %1 is a built-in unit name, please choose another %1 è il nome di un'unità integrata, sceglierne un altro %1 is a user function name, please choose another or delete the function %1 è il nome di una funzione utente, sceglierne un altro o eliminare la funzione FunctionRepo max; trials; probability massimo; processi; probabilità trials; probability processi; probabilità hits; trials; probability successi; tentativi; probabilità max; total; hits; trials max; totale; successi; tentativi total; hits; trials totale; successi; tentativi count; total; hits; trials numero; totale; successi; tentativi dividend; divisor dividendo; divisore x; exponent_bits; significand_bits [; exponent_bias] x; bit_esponenti; bit_significativi [; exponent_bias] base; x base; x value; modulo valore; modulo base; exponent; modulo base; esponente; modulo events; average_events eventi; media_eventi average_events media_eventi x [; precision] x [; precisione] Absolute Value Valore assoluto Absolute Deviation Deviazione assoluta Arc Cosine Arcocoseno Logical AND Congiunzione logica AND Area Hyperbolic Cosine Area del coseno iperbolico Area Hyperbolic Sine Area del seno iperbolico Area Hyperbolic Tangent Area della tangente iperbolica Arc Sine Arcoseno Arc Tangent Arcotangente Arc Tangent with two Arguments Arcotangente con due argomenti Average (Arithmetic Mean) Media (media aritmetica) Binomial Cumulative Distribution Function Funzione di distribuzione cumulativa binomiale Binomial Distribution Mean Media della distribuzione binomiale Binomial Probability Mass Function Funzione di massa della probabilità binomiale Binomial Distribution Variance Varianza della distribuzione binomiale Cube Root Radice cubica Complex Conjugate Complesso Coniugato Cosine Coseno Hyperbolic Cosine Coseno iperbolico Cotangent Cotangente Cosecant Cosecante Convert Unix timestamp to Date Converti data e ora Unix Degrees of Arc Gradi sessagesimali Error Function Funzione d'errore Complementary Error Function Funzione d'errore complementare Exponential Esponenziale Fractional Part Parte frazionaria Extension of Factorials [= (x-1)!] Estensione del fattoriale [= (x-1)!] Greatest Common Divisor Massimo comune divisore Geometric Mean Media geometrica Gradians of arc Gradianti arco Hypergeometric Cumulative Distribution Function Funzione di Distribuzione Cumulativa Ipergeometrica Hypergeometric Distribution Mean Media della distribuzione ipergeometrica Hypergeometric Probability Mass Function Funzione di massa di probabilità ipergeometrica Hypergeometric Distribution Variance Varianza della distribuzione ipergeometrica Integer Quotient Quoziente intero Integer Part Parte intera Imaginary Part Parte immaginaria Decode IEEE-754 Binary Value Decodifica valore binario IEEE-754 Encode IEEE-754 Binary Value Codifica valore binario IEEE-754 Decode 16-bit Half-Precision Value Decodifica valore a 16 bit a mezza precisione Encode 16-bit Half-Precision Value Codifica valore a 16 bit a mezza precisione Decode 32-bit Single-Precision Value Decodifica valore a 32 bit a precisione singola Encode 32-bit Single-Precision Value Codifica valore a 32 bit a precisione singola Decode 64-bit Double-Precision Value Decodifica valore a 64 bit a precisione doppia Encode 64-bit Double-Precision Value Codifica valore a 64 bit a precisione doppia Decode 128-bit Quad-Precision Value Decodifica valore a 128 bit a precisione quadrupla Encode 128-bit Quad-Precision Value Codifica valore a 128 bit a precisione quadrupla Binary Logarithm Logaritmo binario Common Logarithm Logaritmo decimale Natural Logarithm Logaritmo naturale Logarithm to Arbitrary Base Logaritmo in base arbitraria Mask to a bit size Maschera a dimensioni ridotte Maximum Massimo Median Value (50th Percentile) Valore medio (50simo percentile) Minimum Minimo Modulo Modulo Euclidean Modulo Modulo Euclideo Modular Exponentiation Esponenziazione Modulare Combination (Binomial Coefficient) Combinazione (coefficiente binomiale) Logical NOT Negazione logica NOT Permutation (Arrangement) Permutazione (arrangiamento) Convert to Binary Representation Converti in rappresentazione binaria Arithmetic Aritmetica Chemistry Chimica Complex Complessi Combinatorics Combinatoria Probability Probabilità Statistics Statistica Aggregation Aggregazione Random Casuale Base conversion Conversione di base Number formatting Formattazione dei numeri Integer arithmetic Aritmetica intera Special functions Funzioni speciali Exponential & Logarithmic Esponenziali e logaritmiche Angle conversion Conversione angolare Trigonometry Trigonometria Bitwise Bit per bit Floating point Virgola mobile Date & Time Data e ora Linear algebra Algebra lineare unix_timestamp; x hours offset to GMT unix_timestamp; x x ore compensate a GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; offset di x ore rispetto a GMT [digits] [cifre] max [; min] massimo [; minimo] List Literal Letterale di lista Convert to Padded Binary Representation Converti in rappresentazione binaria con riempimento Round Toward +∞ (Ceiling) Arrotonda verso +∞ (ceil) Cosine plus Imaginary Sine Coseno più seno immaginario Convert to Cis Complex Form Converti in forma complessa cis Matrix Column Count Numero di colonne della matrice Population Correlation Matrix (n) Matrice di correlazione della popolazione (n) Sample Correlation Matrix (n-1) Matrice di correlazione del campione (n-1) Count Conteggio Population Covariance Matrix (n) Matrice di covarianza della popolazione (n) Sample Covariance Matrix (n-1) Matrice di covarianza del campione (n-1) Cross Product Prodotto vettoriale Convert Date to Unix timestamp Converti data in timestamp Unix Convert to Decimal Representation Converti in rappresentazione decimale Determinant Determinante Convert to Sexagesimal Notation Converti in notazione sessagesimale Dot Product Prodotto scalare Convert to Engineering Notation Converti in notazione ingegneristica Convert to Exponential Complex Form Converti in forma complessa esponenziale Round Toward −∞ (Floor) Arrotonda verso −∞ (floor) Flatten Matrix Appiattisci matrice Least Common Multiple Minimo comune multiplo Convert to Hexadecimal Representation Converti in rappresentazione esadecimale Convert to Padded Hexadecimal Representation Converti in rappresentazione esadecimale con riempimento Inverse Matrix Matrice inversa Round to 16-bit Half-Precision Value Arrotonda a valore a mezza precisione a 16 bit Round to 32-bit Single-Precision Value Arrotonda a valore a precisione singola a 32 bit Round to 64-bit Double-Precision Value Arrotonda a valore a precisione doppia a 64 bit Round to 128-bit Quad-Precision Value Arrotonda a valore a precisione quadrupla a 128 bit Residual from 16-bit Half-Precision Rounding Residuo dell'arrotondamento a mezza precisione a 16 bit Residual from 32-bit Single-Precision Rounding Residuo dell'arrotondamento a precisione singola a 32 bit Residual from 64-bit Double-Precision Rounding Residuo dell'arrotondamento a precisione doppia a 64 bit Residual from 128-bit Quad-Precision Rounding Residuo dell'arrotondamento a precisione quadrupla a 128 bit Substance Mass Massa della sostanza Molarity Molarità Molar Mass massa molare Median Absolute Deviation Deviazione assoluta mediana Mean Media Numerical Value of Quantity Valore numerico della quantità Random Decimal Number Numero decimale casuale Random Integer Number Numero intero casuale Convert to Rational Representation Converti in rappresentazione razionale Convert to Octal Representation Converti in rappresentazione ottale Convert to Padded Octal Representation Converti in rappresentazione ottale con riempimento Vector or Matrix Norm Norma di vettore o matrice Logical OR Disgiunzione logica OR Population Count (Hamming Weight) Conteggio dei bit impostati (peso di Hamming) Phase of Complex Number Fase di un numero complesso Poissonian Cumulative Distribution Function Funzione di distribuzione cumulativa di Poisson Poissonian Distribution Mean Media della distribuzione di Poisson Poissonian Probability Mass Function Funzione di massa della probabilità di Poisson Poissonian Distribution Variance Varianza della distribuzione di Poisson Convert to Phasor Complex Form Converti in forma complessa fasoriale Convert to Rectangular Complex Form Converti in forma complessa rettangolare Round Half Away from Zero Arrotonda metà lontano da zero Round Half Even Arrotonda metà al pari Nth Root Radice ennesima Convert to Scientific Notation Converti in notazione scientifica Matrix Row Count Numero di righe della matrice List or Matrix Shape Forma di lista o matrice Summation Sommatoria Population Standard Deviation (n) Deviazione standard della popolazione (n) Sample Standard Deviation (n-1) Deviazione standard del campione (n-1) Round Toward Zero (Truncation) Arrotonda verso zero (troncamento) Matrix Trace Traccia della matrice Transpose Matrix Trasponi matrice Population Variance (n) Varianza della popolazione (n) Sample Variance (n-1) Varianza del campione (n-1) Product Prodotto Radians Radianti Matrix Rank Rango della matrice Real Part Parte reale Secant Secante Arithmetic Shift Left Scorrimento aritmetico a sinistra Arithmetic Shift Right Scorrimento aritmetico a destra Signum Segno Sine Seno Hyperbolic Sine Seno iperbolico Square Root Radice quadrata Sum Somma Tangent Tangente Convert to Trigonometric Complex Form Converti in forma complessa trigonometrica Turns Giri Hyperbolic Tangent Tangente iperbolica Sign-extend a value Estensione con segno di un valore Logical XOR Disgiunzione esclusiva XOR FunctionsWidget Domain Dominio All Tutto Name Nome Search Cerca No match found Nessuna corrispondenza trovata Identifier Identificatore HistoryWidget Remove All Calculations Above Rimuovi tutti i calcoli sopra Remove This Calculation Rimuovi questo calcolo Remove All Calculations Below Rimuovi tutti i calcoli sotto Keypad Inverse cosine Coseno inverso The last result L'ultimo risultato Inverse sine Seno inverso Inverse tangent Tangente inversa Evaluate expression Valuta espressione Division Divisione Multiplication Moltiplicazione Subtraction Subtrazione Addition Addizione Clear expression Cancella espressione Cosine Coseno Backspace Backspace Scientific notation Notazione scientifica Exponential Esponenziale Factorial Fattoriale Natural logarithm Logaritmo naturale Left parenthesis Parentesi sinistra Nth root Radice ennesima Argument separator Separatore degli argomenti Square Quadrato Common logarithm Logaritmo decimale Modulo Modulo Contextual percentage Percentuale contestuale Power Potenza Right parenthesis Parentesi destra Sine Seno Square root Radice quadrata Tangent Tangente Pi Pi greco Decimal separator Separatore decimale MainWindow Radian Radianti Degree Gradi Gradian Gradianti Binary Binario Octal Ottale Hexadecimal Esadecimale Sexagesimal Sessagesimale Engineering decimal Decimale ingegneristico Scientific decimal Decimale scientifico &Import... &Importa... &Quit &Esci Clear E&xpression Cancella l'e&spressione Clear &History Cancella la &cronologia &Copy &Copia &Paste &Incolla &Select Expression &Seleziona l'espressione &Constants &Costanti &Functions &Funzioni &History &Cronologia &Status Bar Barra di &stato Bitfield Campo di bit Use&r Functions Funzioni uten&te &Degree &Gradi &Radian &Radianti &Gradian &Gradiante Re&volution Ri&voluzione Auto-Insert a&ns I&nserisci ans automaticamente Automatic &Completion &Completamento automatico &Built-in Functions &Funzioni integrate Built-in &Variables &Variabili integrate User &Functions Fu&nzioni utente User Va&riables Va&riabili utente Open a Private Tab on Startup Apri una scheda privata all’avvio Open and focus a new private tab whenever SpeedCrunch starts. Apri e attiva una nuova scheda privata a ogni avvio di SpeedCrunch. Syntax &Highlighting &Evidenziazione della sintassi Group Digits in &Input Raggruppa le c&ifre in ingresso Automatic Input &Adjustments Correzioni &automatiche dell’input Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Correggi automaticamente operatori, spazi, parentesi e potenze e limita l’input ai caratteri validi. Group input digits using the selected number format. Raggruppa le cifre inserite secondo il formato numerico selezionato. &Blinking Cursor &Cursore lampeggiante Blink the cursor in the expression editor. Fai lampeggiare il cursore nell’editor delle espressioni. &Escape Clears Editor &Escape svuota l’editor Clear the focused expression editor with Escape after dismissing any popup or preview. Svuota l’editor delle espressioni attivo con Escape dopo aver chiuso eventuali finestre a comparsa o anteprime. Keep Expression After Evaluation Mantieni l’espressione dopo il calcolo Copy New Results Automatically Copia automaticamente i nuovi risultati &Comma &Virgola &System Default Predefinita di &sistema &Dot &Punto Dot &And Comma Punto &e virgola Toward +∞ (&ceil) Verso +∞ (&ceil) Toward −∞ (&floor) Verso −∞ (&floor) &Binary &Binario &Engineering &Ingegneristica &Hexadecimal &Esadecimale &Octal &Ottale &Scientific &Scientifica User &Manual &Manuale utente Issues and &Feedback &Problemi e commenti &Donate &Dona &About SpeedCrunch &Informazioni su SpeedCrunch App Diag&nostics Diag&nostica dell’applicazione S&plit &Dividi Angle &Mode M&odalità angolare &Complex Form Forma &complessa New Tab Nuova scheda Constants Costanti Functions Funzioni History Cronologia User Functions Funzioni utente &Font... &Carattere... &Language... &Lingua... &Session &Sessione &Edit &Modifica &View &Visualizza Se&ttings Impos&tazioni &Decimal &Decimale &Keypad &Tastierino numerico Always on &Top Sempre in &primo piano Disabled Disabilitato Small Space Spazio piccolo Medium Space Spazio medio Large Space Spazio grande &0 Digits &0 cifre &15 Digits &15 cifre &2 Digits &2 cifre &3 Digits &3 cifre &50 Digits &50 cifre &8 Digits &8 cifre &Sexagesimal &Sessagesimale Reset All Settings... Ripristina tutte le impostazioni... &System &Sistema SpeedCrunch &Theme &Tema di SpeedCrunch &Classic C&lassico &Modern &Moderno Context Help Aiuto contestuale &Help &Aiuto Error Errore Can't read from file %1 Impossibile leggere dal file %1 Import Session Importa sessione Close Session Chiudi sessione Angle Mode: Modalità angolare: Notation: Notazione: Precision: Precisione: Turn Giro Revolution Rivoluzione Fixed-point decimal Decimale a virgola fissa Rational Razionale Automatic decimal Decimale automatico Automatic Automatico User &Definitions... &Definizioni utente... New &Tab Nuova &scheda New &Private Tab Nuova scheda &privata Keep Mantieni Make Private... Rendi privata... New &Window Nuova &finestra &Open... &Apri... &Rename... &Rinomina... Clo&ne... Clo&na... &Close Tab C&hiudi scheda Reopen Clo&sed Tab Riapri sche&da chiusa Open Sessions &Folder Apri &cartella sessioni &Undo Ann&ulla &Redo &Ripeti Cu&t &Taglia Copy &Last Result Copia &l’ultimo risultato &Wrap in Parentheses R&acchiudi tra parentesi Full Scr&een Mode Modalità a sch&ermo intero &Basic Di &base &Scientific (wide) &Scientifico (ampio) Scientific (narrow) Scientifico (stretto) &Custom... &Personalizzato... Main &Menu &Menu principale User &Variables &Variabili utente &Left &Sinistra &Right Dest&ra &Up S&u &Down &Giù Close Pa&ne Chiudi pa&nnello User &Units &Unità utente &Turn &Giro If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Se una nuova espressione inizia con +, -, * o /, SpeedCrunch inserisce prima "ans". &Accept with Enter &Accetta con Invio Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Accetta il suggerimento attuale di completamento automatico con Invio senza prima selezionarlo con i tasti freccia. &Units &Unità Show Live Result &Preview Mostra &anteprima del risultato in tempo reale Save &Window Position on Exit Salva &posizione della finestra all'uscita Hover Highlighting Evidenziazione al passaggio del mouse Group Integer Part Only Raggruppa solo la parte intera Number Format... Formato numerico... Notation && Precision... Notazione && precisione... After pressing Enter, keep the entered expression selected in the editor. Dopo aver premuto Invio, mantieni selezionata nell’editor l’espressione inserita. Never Mai Always Sempre Only for Single-Line Expressions Solo per espressioni su una riga Simplify Displayed Expressions Semplifica le espressioni visualizzate History Size &Limit... &Limite dimensione cronologia... Remove Trailing &Zeroes Rimuovi gli &zeri finali Nearest, Half &Away (round) Più vicino, metà &lontano da zero (round) Nearest, Half &Even (roundeven) Più vicino, metà &pari (roundeven) Toward &Zero (trunc) Verso &zero (trunc) &Fixed-Point Virgola &fissa &Rational &Razionale &Exponential (m·sâ�»Â¹) &Esponenziale (m·sâ�»Â¹) &Fractional (m/s) &Frazionaria (m/s) &Rectangular (a + bi) &Rettangolare (a + bi) Exponential (reâ�±á¶¿) Esponenziale (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrica (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasore (r∠θ) &Theme... &Tema... Check for &Updates Controlla &aggiornamenti Source Code Codice sorgente &Zoom &Zoom &Results &Risultati Unit Notation Notazione delle unità Rounding Mode Modalità di arrotondamento &Notation &Notazione &Imaginary Unit Unità &immaginaria &Window &Finestra &Editing &Modifica A&utocomplete Completamento a&utomatico Up/Down Arrow History Cronologia con freccia su/giù &Appearance &Aspetto &Menus &Menu &Docks &Pannelli agganciabili &Input and Results &Input e risultati &Disabled &Disabilitato &Disable &Disabilita Close preview Chiudi anteprima Rename... Rinomina... Clone... Clona... Close Tab Chiudi scheda New Private Tab Nuova scheda privata Open... Apri... Reopen Closed Tab Riapri scheda chiusa Split Dividi Left Sinistra Right Destra Up Su Down Giù Clear Svuota Delete Elimina %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sessione privata: il contenuto viene eliminato alla chiusura. Scegli Sessione > Mantieni per trasformarla in una sessione normale. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privata] Reset All Settings Ripristina tutte le impostazioni Reset all settings to their default values? Ripristinare i valori predefiniti di tutte le impostazioni? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Sono inclusi aspetto, modifica, formati dei risultati e preferenze delle finestre. I calcoli, le sessioni aperte e le definizioni utente verranno mantenuti. The settings file could not be written. Impossibile scrivere il file delle impostazioni. Clear this session's calculations, unfinished expression, variables, functions, and units? Eliminare i calcoli, l’espressione incompleta, le variabili, le funzioni e le unità di questa sessione? Global user definitions are kept. Le definizioni utente globali vengono mantenute. Make Session Private Rendi privata la sessione The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. La sessione salvata %1 verrà eliminata. Il suo contenuto resterà aperto in una sessione privata e verrà eliminato alla chiusura della sessione o di SpeedCrunch. Make Private Rendi privata Could not delete the saved session %1. Impossibile eliminare la sessione salvata %1. Keep Session Mantieni sessione Could not save the session. It remains private. Impossibile salvare la sessione. Rimane privata. Clone Session Clona sessione Could not save session file %1. Impossibile salvare il file di sessione %1. Could not delete session file %1. Impossibile eliminare il file di sessione %1. JSON file (*.json);;Any file (*.*) File JSON (*.json);;Qualsiasi file (*.*) Export session as JSON Esporta la sessione come JSON The selected file is not valid JSON: %1 Il file selezionato non è JSON valido: %1 The selected file is not a SpeedCrunch session JSON file. Il file selezionato non è un file JSON di sessione SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Questo file usa un formato di sessione SpeedCrunch obsoleto e non può essere importato. The selected JSON file is missing the required $schema field. Nel file JSON selezionato manca il campo obbligatorio $schema. The selected JSON file uses an unsupported JSON schema: %1 Il file JSON selezionato usa uno schema JSON non supportato: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Nel file JSON selezionato manca l'identificatore dello schema di sessione SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Il file JSON selezionato usa un formato di sessione SpeedCrunch non supportato: %1 The selected JSON file is missing the required session name. Nel file JSON selezionato manca il nome sessione obbligatorio. The selected JSON file has an empty session name. Il file JSON selezionato ha un nome sessione vuoto. The selected JSON file has invalid or incomplete SpeedCrunch session data. Il file JSON selezionato contiene dati di sessione SpeedCrunch non validi o incompleti. Open Sessions Folder Apri cartella sessioni Could not create the sessions folder: %1 Impossibile creare la cartella sessioni: %1 Could not open the sessions folder: %1 Impossibile aprire la cartella sessioni: %1 Editor and Results Font Carattere dell’editor e dei risultati Open Session Apri sessione Community Comunità Rename Session Rinomina sessione Clear Session Cancella sessione Delete Session Elimina sessione Close Pane Chiudi pannello User Variables Variabili utente User Units Unità utente Clear History Cancella cronologia Are you sure you want to clear the calculation history? Cancellare davvero la cronologia dei calcoli? Session name: Nome sessione: A session named %1 already exists. Esiste già una sessione chiamata %1. Could not create session file %1. Impossibile creare il file di sessione %1. Could not write session file %1. Impossibile scrivere il file di sessione %1. Are you sure you want to delete this session? Eliminare davvero questa sessione? Custom Precision Precisione personalizzata Fractional digits: Cifre frazionarie: Theme Tema Light Themes Temi chiari Dark Themes Temi scuri Preview Anteprima Colors Colori Select color for %1 Seleziona il colore per %1 Import... Importa... Export... Esporta... Import Theme Importa tema Theme file (*.json);;All files (*) File tema (*.json);;Tutti i file (*) Invalid theme file. File tema non valido. Can't import theme "%1" because it conflicts with a built-in theme. Impossibile importare il tema "%1" perché è in conflitto con un tema integrato. Can't find a writable theme folder. Impossibile trovare una cartella dei temi scrivibile. Overwrite Theme Sovrascrivi tema A custom theme named "%1" already exists. Do you want to overwrite it? Esiste già un tema personalizzato chiamato "%1". Sovrascriverlo? Can't overwrite theme file %1 Impossibile sovrascrivere il file del tema %1 Can't copy theme file to %1 Impossibile copiare il file del tema in %1 Export Theme Esporta tema Can't export theme as "%1" because it conflicts with a built-in theme. Impossibile esportare il tema come "%1" perché è in conflitto con un tema integrato. Can't write to file %1 Impossibile scrivere sul file %1 Global User Variable Variabile utente globale Global User Function Funzione utente globale Global User Unit Unità utente globale User Definitions Definizioni utente These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Queste definizioni sono globali e vengono caricate in ogni sessione. Non possono essere modificate dalle sessioni e hanno la precedenza sulle definizioni con lo stesso nome nell'editor della sessione. Inserire una definizione per riga. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Esempi: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Applica Validate Convalida Test Results Risultati del test Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variabili importate: %1 Funzioni importate: %2 Unità importate: %3 Numeri delle righe con errori: %4 none nessuno Apply Results Risultati dell'applicazione User definitions saved. Definizioni utente salvate. History Size Limit Limite dimensione cronologia Maximum number of history entries for this session (0 = unlimited): Numero massimo di voci della cronologia per questa sessione (0 = illimitato): Text file (*.txt);;Any file (*.*) File di testo (*.txt);;Tutti i file (*.*) Could not recalculate from calculation %1: %2 Impossibile ricalcolare dal calcolo %1: %2 History Size Limit Reached Limite dimensione cronologia raggiunto This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Questo calcolo occupa l'ultimo spazio disponibile nella cronologia. I calcoli futuri rimuoveranno dalla cronologia il calcolo più vecchio. È possibile aumentare il limite da Sessione > Limite dimensione cronologia. Editing calculation. Press Esc twice to cancel. Modifica del calcolo. Premi Esc due volte per annullare. Calculation Settings Impostazioni di calcolo Invalid recalculation start index Indice iniziale di ricalcolo non valido System Default Predefinita di sistema Language Lingua Select the language: Selezionare la lingua: Custom Personalizzato Decimal places: Cifre decimali: &Automatic &Automatico &Precision &Precisione Plain &text &Testo semplice Formula &Book &Raccolta di formule &Export &Esporta Export session as HTML Esporta la sessione come HTML HTML file (*.html) File HTML (*.html) Export session as plain text Esporta la sessione come testo semplice ManualWindow SpeedCrunch Manual Manuale di SpeedCrunch %1 - SpeedCrunch Manual %1 - Manuale di SpeedCrunch NumberFormatDialog Number Format Formato numerico <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Seleziona il formato numerico dei risultati e del raggruppamento delle cifre in ingresso.</b><br/><br/>Nota: i numeri inseriti in formati non ambigui vengono accettati anche se diversi dal formato di visualizzazione selezionato.<br/> QObject Global User Variable Variabile utente globale Global User Function Funzione utente globale Global User Unit Unità utente globale Backspace Backspace Clear expression Cancella espressione Evaluate expression Valuta espressione Insert text Inserisci testo Automatic decimal Decimale automatico Fixed-point decimal Decimale a virgola fissa Engineering decimal Decimale ingegneristico Scientific decimal Decimale scientifico Rational Razionale Binary Binario Octal Ottale Hexadecimal Esadecimale Sexagesimal Sessagesimale Update Available Aggiornamento disponibile A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> È disponibile una versione più recente (%1).<br/><a href="%2">Visita il sito web per scaricarla.</a> Check for Updates Controlla aggiornamenti SpeedCrunch %1 is up to date. SpeedCrunch %1 è aggiornato. No connectivity. Please check your internet connection and try again. Nessuna connettività. Controlla la connessione a Internet e riprova. Could not verify the latest available version. Impossibile verificare l’ultima versione disponibile. ResultDisplay Scroll to bottom Scorri in fondo Edit Expression Modifica espressione Change Settings Modifica impostazioni New Tab Nuova scheda &Import... &Importa... &Export &Esporta Plain &text &Testo semplice Copy Copia Selection Selezione Select All Seleziona tutto Expression Espressione Result Risultato Calculation Calcolo Calculation as Single Line Calcolo su una sola riga Remove Rimuovi This Calculation Questo calcolo All Calculations Above Tutti i calcoli sopra All Calculations Below Tutti i calcoli sotto New Private Tab Nuova scheda privata Session Sessione Open... Apri... Clone... Clona... Rename... Rinomina... Keep Mantieni Make Private... Rendi privata... Clear Svuota Delete Elimina Close Chiudi Split Dividi Left Sinistra Right Destra Up Su Down Giù Close Pane Chiudi pannello Main Menu Menu principale Cancel editing Annulla modifica Copy result Copia risultato Edit expression Modifica espressione Change settings Modifica impostazioni Remove calculation Rimuovi calcolo ResultSlotsDialog Notation & Precision Notazione e precisione Result Line Riga risultato Enabled Abilitato Notation Notazione Decimal Places Cifre decimali Main Line Riga principale Extra Line #1 Riga extra n. 1 Extra Line #2 Riga extra n. 2 Extra Line #3 Riga extra n. 3 Extra Line #4 Riga extra n. 4 Auto Auto UserFunctionListWidget Name Nome Value Valore Description Descrizione Search Ricerca No match found Nessuna corrispondenza trovata Insert Inserisci Edit Modifica Delete Elimina Delete All Elimina tutto UserUnitListWidget Name Nome Value Valore Description Descrizione Search Cerca No match found Nessuna corrispondenza trovata Insert Inserisci Edit Modifica Delete Elimina Delete All Elimina tutto VariableListWidget Name Nome Value Valore Description Descrizione Search Cerca No match found Nessuna corrispondenza Insert Inserisci Edit Modifica Delete Elimina Delete All Elimina tutto heldercorreia-speedcrunch-e7ca37f/src/resources/locale/ja.ts000066400000000000000000010542711526573132500243510ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunchã�«ã�¤ã�„ã�¦ Core developers コア開発者 Original author 原作者 Close é–‰ã�˜ã‚‹ Math engine æ•°å¼�処ç�†ã‚¨ãƒ³ã‚¸ãƒ³ Main author | Logo | Maintainer 主ã�ªä½œè€… | ロゴ | メンテナー Thanks 感è¬� Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 SpeedCrunch 開発ãƒ�ーム This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version ã�“ã�®ãƒ—ログラムã�¯ãƒ•リーソフトウェアã�§ã�™ã€‚ã�‚ã�ªã�Ÿã�¯ã�“れをã€�フリーソフトウェア財団ã�«ã‚ˆã�£ã�¦ç™ºè¡Œã�•れã�Ÿ GNU 一般公衆利用許諾契約書(ãƒ�ージョン2ã�‹ã€�希望ã�«ã‚ˆã�£ã�¦ã�¯ã��れ以é™�ã�®ãƒ�ージョンã�®ã�†ã�¡ã�©ã‚Œã�‹)ã�®å®šã‚�ã‚‹æ�¡ä»¶ã�®ä¸‹ã�§å†�頒布ã�¾ã�Ÿã�¯æ”¹å¤‰ã�™ã‚‹ã�“ã�¨ã�Œã�§ã��ã�¾ã�™ã€‚ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ã�“ã�®ãƒ—ログラムã�¯æœ‰ç”¨ã�§ã�‚ã‚‹ã�“ã�¨ã‚’願ã�£ã�¦é ’布ã�•れã�¾ã�™ã�Œã€�*å…¨ã��ã�®ç„¡ä¿�証*ã�§ã�™ã€‚商業å�¯èƒ½æ€§ã�®ä¿�証や特定ã�®ç›®çš„ã�¸ã�®é�©å�ˆæ€§ã�¯ã€�言外ã�«ç¤ºã�•れã�Ÿã‚‚ã�®ã‚‚å�«ã‚�å…¨ã��存在ã�—ã�¾ã�›ã‚“。詳ã�—ã��ã�¯GNU 一般公衆利用許諾契約書をã�”覧ã��ã� ã�•ã�„。 BitFieldWidget Reset bits to zero ビットをゼロã�«ãƒªã‚»ãƒƒãƒˆ Invert bits ビットをå��転 Shift bits left ビットを左ã�«ã‚·ãƒ•ト Shift bits right ビットをå�³ã�«ã‚·ãƒ•ト Book Index 目次 Algebra 代数 Quadratic Equation 二次方程å¼� Logarithmic Base Conversion 底ã�®å¤‰æ�› Geometry 幾何学 Circle 円 Sector 扇形 Sphere ç�ƒ Cube 立方体 Cone 円éŒ� Cylinder 円柱 Electronics é›»å­�工学 Ohm's Law オームã�®æ³•則 Power 指数 Reactance リアクタンス Resonance 共振 Radio Frequency 無線周波数 Antennas アンテナ Characteristic Impedance (coax) 特性インピーダンス (å�Œè»¸) Velocity of Propagation (coax) ä¼�æ�¬é€Ÿåº¦ (å�Œè»¸) Standing Wave Ratio & Return Loss 定在波比ã�¨å��射減衰é‡� Free Space Wavelength 自由空間波長 resistance 抵抗 voltage 電圧 current é›»æµ� power 電力 inductive reactance 誘導性リアクタンス capacitive reactance 容é‡�性リアクタンス inductance インダクタンス capacitance é�™é›»å®¹é‡� frequency 周波数 resonance frequency 共振周波数 area é�¢ç©� perimeter 周辺 diameter 直径 radius å�Šå¾„ volume 体ç©� surface area 表é�¢ç©� height 高ã�• slant height 斜高 face diagonal é�¢å¯¾è§’ç·š space diagonal 空間対角線 edge length 辺長 arc length å¼§é•· central angle (degrees) 中心角 (度) input power 入力電力 reflected power å��射電力 transmitted power ä¼�é€�電力 return loss å��射減衰é‡� dielectric constant 比誘電率 outer conductor's inner diameter 外å�´å°Žä½“ã�®å†…径 inner conductor's outer diameter 内å�´å°Žä½“ã�®å¤–径 speed of light 光速 reflection coefficient å��å°„ä¿‚æ•° standing wave ratio 定在波比 normalized impedance æ­£è¦�化インピーダンス frequency (Hz) 周波数 (Hz) BookDock Formula Book å…¬å¼�集 ConstantCompletion Search constants 定数を検索 No match found 見ã�¤ã�‹ã‚Šã�¾ã�›ã‚“ã�§ã�—ã�Ÿ Constants Mathematics æ•°å­¦ Physics (CODATA 2022) 物ç�† (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) 化学 (IUPAC - CIAAW 2021) Uncategorized 未分類 Universal æ™®é��定数 Physicochemical 物ç�†åŒ–å­¦ Atomic & Nuclear — General 原å­�・核 — 一般 Atomic & Nuclear — Electroweak 原å­�・核 — 電弱 Atomic & Nuclear — Electron 原å­�・核 — é›»å­� Atomic & Nuclear — Muon 原å­�・核 — ミューオン Atomic & Nuclear — Tau 原å­�・核 — タウ Atomic & Nuclear — Proton 原å­�・核 — 陽å­� Atomic & Nuclear — Neutron 原å­�・核 — 中性å­� Atomic & Nuclear — Deuteron 原å­�・核 — é‡�陽å­� Atomic & Nuclear — Triton 原å­�・核 — 三é‡�陽å­� Atomic & Nuclear — Helion 原å­�・核 — ヘリオン Atomic & Nuclear — Alpha particle 原å­�・核 — アルファ粒å­� Atomic & Nuclear — Atomic units 原å­�・核 — 原å­�å�˜ä½� Atomic & Nuclear — Energy conversion relationships 原å­�・核 — エãƒ�ルギーæ�›ç®—関係 Atomic & Nuclear — X-ray units 原å­�・核 — Xç·šå�˜ä½� Atomic & Nuclear — Magnetic shielding corrections 原å­�・核 — ç£�æ°—é�®è”½è£œæ­£ Masses 質é‡� Lifetimes 寿命 Molar Masses モル質é‡� Electronegativity 電気陰性度 Ionization Energy イオン化エãƒ�ルギー Nominal Constants (IAU 2015) 公称定数 (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) ç�¾åœ¨ã�®æœ€è‰¯æŽ¨å®šå€¤ (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) 真空ã�®ç‰¹æ€§ã‚¤ãƒ³ãƒ”ーダンス (Zâ‚€) reduced Planck constant (â„�) æ�›ç®—プランク定数 (â„�) vacuum electric permittivity (ϵ₀) 真空ã�®èª˜é›»çއ (ϵ₀) Newtonian constant of gravitation (G) 万有引力定数 (G) vacuum magnetic permeability (μ₀) 真空ã�®é€�ç£�率 (μ₀) Planck constant (h) プランク定数 (h) speed of light in vacuum (c) 真空中ã�®å…‰é€Ÿ (c) standard acceleration of gravity (gâ‚™) 標準é‡�力加速度 (gâ‚™) Newtonian constant of gravitation over h-bar c 万有引力定数 / â„�c Planck length プランク長 Planck constant in eV/Hz (h) プランク定数 (eV/Hz) (h) Planck mass プランク質é‡� Planck mass energy equivalent in GeV プランク質é‡�エãƒ�ルギー等価 (GeV) Planck temperature プランク温度 Planck time プランク時間 reduced Planck constant in eV·s (â„�) æ�›ç®—プランク定数 (eV·s) (â„�) reduced Planck constant times c in MeV·fm æ�›ç®—プランク定数 × c (MeV·fm) Bohr magneton ボーアç£�å­� conductance quantum (Gâ‚€) コンダクタンスé‡�å­� (Gâ‚€) Coulomb constant (kâ‚‘) クーロン定数 (kâ‚‘) elementary charge (e) ç´ é›»è�· (e) elementary charge over h-bar ç´ é›»è�· / â„� conventional value of Josephson constant ジョセフソン定数ã�®å�”定値 Josephson constant ジョセフソン定数 conventional value of ampere-90 アンペア90ã�®å�”定値 conventional value of coulomb-90 クーロン90ã�®å�”定値 conventional value of farad-90 ファラド90ã�®å�”定値 conventional value of henry-90 ヘンリー90ã�®å�”定値 conventional value of ohm-90 オーム90ã�®å�”定値 conventional value of volt-90 ボルト90ã�®å�”定値 conventional value of watt-90 ワット90ã�®å�”定値 magnetic flux quantum (Φ₀) ç£�æ�Ÿé‡�å­� (Φ₀) nuclear magneton æ ¸ç£�å­� inverse of conductance quantum コンダクタンスé‡�å­�ã�®é€†æ•° conventional value of von Klitzing constant フォン・クリッツィング定数ã�®å�”定値 von Klitzing constant フォン・クリッツィング定数 atomic unit of magnetic dipole moment 原å­�å�˜ä½�ã�®ç£�æ°—å�Œæ¥µå­�モーメント atomic unit of magnetic flux density 原å­�å�˜ä½�ã�®ç£�æ�Ÿå¯†åº¦ Bohr magneton in eV/T ボーアç£�å­� (eV/T) Bohr magneton in Hz/T ボーアç£�å­� (Hz/T) Bohr magneton in inverse meter per tesla ボーアç£�å­� (逆メートル/テスラ) Bohr magneton in K/T ボーアç£�å­� (K/T) nuclear magneton in eV/T æ ¸ç£�å­� (eV/T) nuclear magneton in inverse meter per tesla æ ¸ç£�å­� (逆メートル/テスラ) nuclear magneton in K/T æ ¸ç£�å­� (K/T) nuclear magneton in MHz/T æ ¸ç£�å­� (MHz/T) Bohr radius (aâ‚€) ボーアå�Šå¾„ (aâ‚€) fine-structure constant (α) 微細構造定数 (α) Hartree energy (Eâ‚•) ãƒ�ートリーエãƒ�ルギー (Eâ‚•) Hartree energy in eV ãƒ�ートリーエãƒ�ルギー (eV) quantum of circulation 循環é‡�å­� quantum of circulation times 2 循環é‡�å­� × 2 Rydberg constant (R∞) リュードベリ定数 (R∞) atomic mass unit-hartree relationship 原å­�質é‡�å�˜ä½�-ãƒ�ートリーæ�›ç®—関係 atomic mass unit-hertz relationship 原å­�質é‡�å�˜ä½�-ヘルツæ�›ç®—関係 atomic mass unit-inverse meter relationship 原å­�質é‡�å�˜ä½�-逆メートルæ�›ç®—関係 atomic mass unit-joule relationship 原å­�質é‡�å�˜ä½�-ジュールæ�›ç®—関係 atomic mass unit-kelvin relationship 原å­�質é‡�å�˜ä½�-ケルビンæ�›ç®—関係 atomic mass unit-kilogram relationship 原å­�質é‡�å�˜ä½�-キログラムæ�›ç®—関係 atomic unit of 1st hyperpolarizability 1次超分極率ã�®åŽŸå­�å�˜ä½� atomic unit of 2nd hyperpolarizability 2次超分極率ã�®åŽŸå­�å�˜ä½� atomic unit of charge (e) 原å­�å�˜ä½�ã�®é›»è�· (e) atomic unit of charge density 原å­�å�˜ä½�ã�®é›»è�·å¯†åº¦ atomic unit of current 原å­�å�˜ä½�ã�®é›»æµ� atomic unit of electric dipole moment 原å­�å�˜ä½�ã�®é›»æ°—å�Œæ¥µå­�モーメント atomic unit of electric field 原å­�å�˜ä½�ã�®é›»å ´ atomic unit of electric field gradient 原å­�å�˜ä½�ã�®é›»å ´å‹¾é…� atomic unit of electric polarizability 原å­�å�˜ä½�ã�®é›»æ°—分極率 atomic unit of electric potential 原å­�å�˜ä½�ã�®é›»ä½� atomic unit of electric quadrupole moment 原å­�å�˜ä½�ã�®é›»æ°—å››é‡�極モーメント atomic unit of action 作用ã�®åŽŸå­�å�˜ä½� atomic unit of energy 原å­�å�˜ä½�ã�®ã‚¨ãƒ�ルギー atomic unit of force 原å­�å�˜ä½�ã�®åŠ› atomic unit of length 原å­�å�˜ä½�ã�®é•·ã�• hertz-atomic mass unit relationship ヘルツ-原å­�質é‡�å�˜ä½�æ�›ç®—関係 hertz-electron volt relationship ヘルツ-é›»å­�ボルトæ�›ç®—関係 hertz-hartree relationship ヘルツ-ãƒ�ートリー æ�›ç®—関係 hertz-inverse meter relationship ヘルツ-逆メートル æ�›ç®—関係 hertz-joule relationship ヘルツ-ジュール æ�›ç®—関係 hertz-kelvin relationship ヘルツ-ケルビン æ�›ç®—関係 hertz-kilogram relationship ヘルツ-キログラム æ�›ç®—関係 hyperfine transition frequency of Cs-133 Cs-133ã�®è¶…微細é�·ç§»å‘¨æ³¢æ•° inverse fine-structure constant (αâ�»Â¹) 微細構造定数ã�®é€†æ•° (αâ�»Â¹) inverse meter-atomic mass unit relationship 逆メートル-原å­�質é‡�å�˜ä½�æ�›ç®—関係 inverse meter-electron volt relationship 逆メートル-é›»å­�ボルトæ�›ç®—関係 inverse meter-hartree relationship 逆メートル-ãƒ�ートリー æ�›ç®—関係 inverse meter-hertz relationship 逆メートル-ヘルツ æ�›ç®—関係 inverse meter-joule relationship 逆メートル-ジュール æ�›ç®—関係 inverse meter-kelvin relationship 逆メートル-ケルビン æ�›ç®—関係 inverse meter-kilogram relationship 逆メートル-キログラム æ�›ç®—関係 joule-atomic mass unit relationship ジュール-原å­�質é‡�å�˜ä½�æ�›ç®—関係 joule-electron volt relationship ジュール-é›»å­�ボルトæ�›ç®—関係 joule-hertz relationship ジュール-ヘルツ æ�›ç®—関係 joule-hartree relationship ジュール-ãƒ�ートリー æ�›ç®—関係 joule-inverse meter relationship ジュール-逆メートル æ�›ç®—関係 joule-kelvin relationship ジュール-ケルビン æ�›ç®—関係 joule-kilogram relationship ジュール-キログラム æ�›ç®—関係 kelvin-atomic mass unit relationship ケルビン-原å­�質é‡�å�˜ä½�æ�›ç®—関係 kelvin-electron volt relationship ケルビン-é›»å­�ボルトæ�›ç®—関係 kelvin-hertz relationship ケルビン-ヘルツ æ�›ç®—関係 kelvin-hartree relationship ケルビン-ãƒ�ートリー æ�›ç®—関係 kelvin-inverse meter relationship ケルビン-逆メートル æ�›ç®—関係 kelvin-joule relationship ケルビン-ジュール æ�›ç®—関係 kelvin-kilogram relationship ケルビン-キログラム æ�›ç®—関係 kilogram-atomic mass unit relationship キログラム-原å­�質é‡�å�˜ä½�æ�›ç®—関係 kilogram-electron volt relationship キログラム-é›»å­�ボルトæ�›ç®—関係 kilogram-hertz relationship キログラム-ヘルツ æ�›ç®—関係 kilogram-hartree relationship キログラム-ãƒ�ートリー æ�›ç®—関係 kilogram-inverse meter relationship キログラム-逆メートル æ�›ç®—関係 kilogram-joule relationship キログラム-ジュール æ�›ç®—関係 kilogram-kelvin relationship キログラム-ケルビン æ�›ç®—関係 lattice parameter of silicon (a) シリコンã�®æ ¼å­�定数 (a) luminous efficacy 視感効果度 natural unit of energy 自然å�˜ä½�ã�®ã‚¨ãƒ�ルギー natural unit of energy in MeV 自然å�˜ä½�ã�®ã‚¨ãƒ�ルギー (MeV) natural unit of action (â„�) 作用ã�®è‡ªç„¶å�˜ä½� (â„�) natural unit of action in eV·s 作用ã�®è‡ªç„¶å�˜ä½� (eV·s) natural unit of length 自然å�˜ä½�ã�®é•·ã�• natural unit of mass 自然å�˜ä½�ã�®è³ªé‡� natural unit of momentum 自然å�˜ä½�ã�®é�‹å‹•é‡� natural unit of momentum in MeV/c 自然å�˜ä½�ã�®é�‹å‹•é‡� (MeV/c) natural unit of time 自然å�˜ä½�ã�®æ™‚é–“ natural unit of velocity 自然å�˜ä½�ã�®é€Ÿåº¦ Rydberg constant times c in Hz リュードベリ定数 × c (Hz) Rydberg constant times hc in eV リュードベリ定数 × hc (eV) Rydberg constant times hc in J リュードベリ定数 × hc (J) Fermi coupling constant フェルミçµ�å�ˆå®šæ•° weak mixing angle 弱混å�ˆè§’ W to Z mass ratio W / Z 質é‡�比 Thomson cross section (σₑ) トムソン散乱断é�¢ç©� (σₑ) electron mass (mâ‚‘) é›»å­�質é‡� (mâ‚‘) electron mass in u é›»å­�質é‡� (u) electron mass energy equivalent (mₑ·c²) é›»å­�質é‡�エãƒ�ルギー等価 (mₑ·c²) electron mass energy equivalent in MeV é›»å­�質é‡�エãƒ�ルギー等価 (MeV) reduced Compton wavelength æ�›ç®—コンプトン波長 classical electron radius (râ‚‘) å�¤å…¸é›»å­�å�Šå¾„ (râ‚‘) electron charge to mass quotient é›»å­�ã�®é›»è�·è³ªé‡�比 electron-deuteron magnetic moment ratio é›»å­�-é‡�陽å­�ç£�気モーメント比 electron-deuteron mass ratio é›»å­�-é‡�陽å­� 質é‡�比 electron g factor (gâ‚‘) é›»å­� gå› å­� (gâ‚‘) electron gyromagnetic ratio (γₑ) é›»å­�ç£�気回転比 (γₑ) electron gyromagnetic ratio in MHz/T é›»å­�ç£�気回転比 (MHz/T) electron-helion mass ratio é›»å­�-ヘリオン 質é‡�比 electron magnetic moment (μₑ) é›»å­�ç£�気モーメント (μₑ) electron magnetic moment anomaly (aâ‚‘) é›»å­�ç£�気モーメント異常 (aâ‚‘) electron magnetic moment to Bohr magneton ratio é›»å­�ç£�気モーメント/ボーアç£�å­�比 electron magnetic moment to nuclear magneton ratio é›»å­�ç£�気モーメント/æ ¸ç£�å­�比 electron molar mass (Mâ‚‘) é›»å­�モル質é‡� (Mâ‚‘) electron-muon magnetic moment ratio é›»å­�-ミューオンç£�気モーメント比 electron-muon mass ratio é›»å­�-ミューオン 質é‡�比 electron-neutron magnetic moment ratio é›»å­�-中性å­�ç£�気モーメント比 electron-neutron mass ratio é›»å­�-中性å­� 質é‡�比 electron-proton magnetic moment ratio é›»å­�-陽å­�ç£�気モーメント比 electron-proton mass ratio é›»å­�-陽å­� 質é‡�比 electron relative atomic mass (Ar(e)) é›»å­� 相対原å­�質é‡� (Ar(e)) electron-tau mass ratio é›»å­�-タウ 質é‡�比 electron to alpha particle mass ratio é›»å­�/アルファ粒å­�質é‡�比 electron to shielded helion magnetic moment ratio é›»å­�/é�®è”½ãƒ˜ãƒªã‚ªãƒ³ç£�気モーメント比 electron to shielded proton magnetic moment ratio é›»å­�/é�®è”½é™½å­�ç£�気モーメント比 electron-triton mass ratio é›»å­�-三é‡�陽å­� 質é‡�比 electron volt-atomic mass unit relationship é›»å­�ボルト-原å­�質é‡�å�˜ä½�æ�›ç®—関係 electron volt-hartree relationship é›»å­�ボルト-ãƒ�ートリーæ�›ç®—関係 electron volt-hertz relationship é›»å­�ボルト-ヘルツæ�›ç®—関係 electron volt-inverse meter relationship é›»å­�ボルト-逆メートルæ�›ç®—関係 electron volt-joule relationship é›»å­�ボルト-ジュールæ�›ç®—関係 electron volt-kelvin relationship é›»å­�ボルト-ケルビンæ�›ç®—関係 electron volt-kilogram relationship é›»å­�ボルト-キログラムæ�›ç®—関係 hartree-atomic mass unit relationship ãƒ�ートリー-原å­�質é‡�å�˜ä½�æ�›ç®—関係 hartree-electron volt relationship ãƒ�ートリー-é›»å­�ボルトæ�›ç®—関係 muon Compton wavelength ミューオン コンプトン波長 muon-electron mass ratio ミューオン-é›»å­� 質é‡�比 muon g factor ミューオン gå› å­� muon magnetic moment ミューオン ç£�気モーメント muon magnetic moment anomaly ミューオンç£�気モーメント異常 muon magnetic moment to Bohr magneton ratio ミューオンç£�気モーメント/ボーアç£�å­�比 muon magnetic moment to nuclear magneton ratio ミューオンç£�気モーメント/æ ¸ç£�å­�比 muon mass ミューオン質é‡� muon mass energy equivalent ミューオン質é‡�エãƒ�ルギー等価 muon mass energy equivalent in MeV ミューオン質é‡�エãƒ�ルギー等価 (MeV) muon mass in u ミューオン質é‡� (u) muon molar mass ミューオンモル質é‡� muon-neutron mass ratio ミューオン-中性å­� 質é‡�比 muon-proton magnetic moment ratio ミューオン-陽å­�ç£�気モーメント比 muon-proton mass ratio ミューオン-陽å­� 質é‡�比 muon-tau mass ratio ミューオン-タウ 質é‡�比 reduced muon Compton wavelength æ�›ç®—ミューオンコンプトン波長 reduced tau Compton wavelength æ�›ç®—タウコンプトン波長 tau Compton wavelength タウコンプトン波長 tau-electron mass ratio タウ-é›»å­� 質é‡�比 tau mass タウ質é‡� tau mass energy equivalent タウ質é‡�エãƒ�ルギー等価 tau mass in u タウ質é‡� (u) tau molar mass タウモル質é‡� tau-muon mass ratio タウ-ミューオン 質é‡�比 tau-neutron mass ratio タウ-中性å­� 質é‡�比 tau-proton mass ratio タウ-陽å­� 質é‡�比 proton charge to mass quotient 陽å­�ã�®é›»è�·è³ªé‡�比 proton Compton wavelength 陽å­�コンプトン波長 proton-electron mass ratio 陽å­�-é›»å­� 質é‡�比 proton g factor (gₚ) 陽å­� gå› å­� (gₚ) proton gyromagnetic ratio (γₚ) 陽å­�ç£�気回転比 (γₚ) proton gyromagnetic ratio in MHz/T 陽å­�ç£�気回転比 (MHz/T) proton magnetic moment (μₚ) 陽å­�ç£�気モーメント (μₚ) proton magnetic moment to Bohr magneton ratio 陽å­�ç£�気モーメント/ボーアç£�å­�比 proton magnetic moment to nuclear magneton ratio 陽å­�ç£�気モーメント/æ ¸ç£�å­�比 proton magnetic shielding correction 陽å­�ç£�æ°—é�®è”½è£œæ­£ proton mass (mₚ) 陽å­�質é‡� (mₚ) proton mass energy equivalent 陽å­�質é‡�エãƒ�ルギー等価 proton mass energy equivalent in MeV 陽å­�質é‡�エãƒ�ルギー等価 (MeV) proton mass in u 陽å­�質é‡� (u) proton molar mass (Mₚ) 陽å­�モル質é‡� (Mₚ) proton-muon mass ratio 陽å­�-ミューオン 質é‡�比 proton-neutron magnetic moment ratio 陽å­�-中性å­�ç£�気モーメント比 proton-neutron mass ratio 陽å­�-中性å­� 質é‡�比 proton relative atomic mass (Ar(p)) 陽å­�相対原å­�質é‡� (Ar(p)) proton rms charge radius 陽å­� rms é›»è�·å�Šå¾„ proton-tau mass ratio 陽å­�-タウ 質é‡�比 reduced proton Compton wavelength æ�›ç®—陽å­�コンプトン波長 shielded proton gyromagnetic ratio é�®è”½é™½å­�ç£�気回転比 shielded proton gyromagnetic ratio in MHz/T é�®è”½é™½å­�ç£�気回転比 (MHz/T) shielded proton magnetic moment é�®è”½é™½å­�ç£�気モーメント shielded proton magnetic moment to Bohr magneton ratio é�®è”½é™½å­�ç£�気モーメント/ボーアç£�å­�比 shielded proton magnetic moment to nuclear magneton ratio é�®è”½é™½å­�ç£�気モーメント/æ ¸ç£�å­�比 neutron Compton wavelength 中性å­�コンプトン波長 neutron-electron magnetic moment ratio 中性å­�-é›»å­�ç£�気モーメント比 neutron-electron mass ratio 中性å­�-é›»å­� 質é‡�比 neutron g factor (gâ‚™) 中性å­� gå› å­� (gâ‚™) neutron gyromagnetic ratio (γₙ) 中性å­�ç£�気回転比 (γₙ) neutron gyromagnetic ratio in MHz/T 中性å­�ç£�気回転比 (MHz/T) neutron magnetic moment (μₙ) 中性å­�ç£�気モーメント (μₙ) neutron magnetic moment to Bohr magneton ratio 中性å­�ç£�気モーメント/ボーアç£�å­�比 neutron magnetic moment to nuclear magneton ratio 中性å­�ç£�気モーメント/æ ¸ç£�å­�比 neutron mass (mâ‚™) 中性å­�質é‡� (mâ‚™) neutron mass energy equivalent 中性å­�質é‡�エãƒ�ルギー等価 neutron mass energy equivalent in MeV 中性å­�質é‡�エãƒ�ルギー等価 (MeV) neutron mass in u 中性å­�質é‡� (u) neutron molar mass (Mâ‚™) 中性å­�モル質é‡� (Mâ‚™) neutron-muon mass ratio 中性å­�-ミューオン 質é‡�比 neutron-proton magnetic moment ratio 中性å­�-陽å­�ç£�気モーメント比 neutron-proton mass difference 中性å­�-陽å­�質é‡�å·® neutron-proton mass difference energy equivalent 中性å­�-陽å­�質é‡�差エãƒ�ルギー等価 neutron-proton mass difference energy equivalent in MeV 中性å­�-陽å­�質é‡�差エãƒ�ルギー等価 (MeV) neutron-proton mass difference in u 中性å­�-陽å­�質é‡�å·® (u) neutron-proton mass ratio 中性å­�-陽å­� 質é‡�比 neutron relative atomic mass (Ar(n)) 中性å­�相対原å­�質é‡� (Ar(n)) neutron-tau mass ratio 中性å­�-タウ 質é‡�比 neutron to shielded proton magnetic moment ratio 中性å­�/é�®è”½é™½å­�ç£�気モーメント比 reduced neutron Compton wavelength æ�›ç®—中性å­�コンプトン波長 deuteron-electron magnetic moment ratio é‡�陽å­�-é›»å­�ç£�気モーメント比 deuteron-electron mass ratio é‡�陽å­�-é›»å­� 質é‡�比 deuteron g factor é‡�陽å­� gå› å­� deuteron magnetic moment é‡�陽å­�ç£�気モーメント deuteron magnetic moment to Bohr magneton ratio é‡�陽å­�ç£�気モーメント/ボーアç£�å­�比 deuteron magnetic moment to nuclear magneton ratio é‡�陽å­�ç£�気モーメント/æ ¸ç£�å­�比 deuteron mass é‡�陽å­�質é‡� deuteron mass energy equivalent é‡�陽å­�質é‡�エãƒ�ルギー等価 deuteron mass energy equivalent in MeV é‡�陽å­�質é‡�エãƒ�ルギー等価 (MeV) deuteron mass in u é‡�陽å­�質é‡� (u) deuteron molar mass é‡�陽å­�モル質é‡� deuteron-neutron magnetic moment ratio é‡�陽å­�-中性å­�ç£�気モーメント比 deuteron-proton magnetic moment ratio é‡�陽å­�-陽å­�ç£�気モーメント比 deuteron-proton mass ratio é‡�陽å­�-陽å­� 質é‡�比 deuteron relative atomic mass (Ar(d)) é‡�陽å­�相対原å­�質é‡� (Ar(d)) deuteron rms charge radius é‡�陽å­� rms é›»è�·å�Šå¾„ triton-electron mass ratio 三é‡�陽å­�-é›»å­� 質é‡�比 triton g factor (gₜ) 三é‡�陽å­� gå› å­� (gₜ) triton magnetic moment (μₜ) 三é‡�陽å­�ç£�気モーメント (μₜ) triton magnetic moment to Bohr magneton ratio 三é‡�陽å­�ç£�気モーメント/ボーアç£�å­�比 triton magnetic moment to nuclear magneton ratio 三é‡�陽å­�ç£�気モーメント/æ ¸ç£�å­�比 triton mass (mₜ) 三é‡�陽å­�質é‡� (mₜ) triton mass energy equivalent 三é‡�陽å­�質é‡�エãƒ�ルギー等価 triton mass energy equivalent in MeV 三é‡�陽å­�質é‡�エãƒ�ルギー等価 (MeV) triton mass in u 三é‡�陽å­�質é‡� (u) triton molar mass (Mₜ) 三é‡�陽å­�モル質é‡� (Mₜ) triton-proton mass ratio 三é‡�陽å­�-陽å­� 質é‡�比 triton relative atomic mass (Ar(t)) 三é‡�陽å­�相対原å­�質é‡� (Ar(t)) triton to proton magnetic moment ratio 三é‡�陽å­�/陽å­�ç£�気モーメント比 helion-electron mass ratio ヘリオン-é›»å­� 質é‡�比 helion g factor (gâ‚•) ヘリオン gå› å­� (gâ‚•) helion magnetic moment (μₕ) ヘリオンç£�気モーメント (μₕ) helion magnetic moment to Bohr magneton ratio ヘリオンç£�気モーメント/ボーアç£�å­�比 helion magnetic moment to nuclear magneton ratio ヘリオンç£�気モーメント/æ ¸ç£�å­�比 helion mass (mâ‚•) ヘリオン質é‡� (mâ‚•) helion mass energy equivalent ヘリオン質é‡�エãƒ�ルギー等価 helion mass energy equivalent in MeV ヘリオン質é‡�エãƒ�ルギー等価 (MeV) helion mass in u ヘリオン質é‡� (u) helion molar mass (Mâ‚•) ヘリオンモル質é‡� (Mâ‚•) helion-proton mass ratio ヘリオン-陽å­� 質é‡�比 helion relative atomic mass (Ar(h)) ヘリオン相対原å­�質é‡� (Ar(h)) helion shielding shift ヘリオンé�®è”½ã‚·ãƒ•ト shielded helion gyromagnetic ratio é�®è”½ãƒ˜ãƒªã‚ªãƒ³ç£�気回転比 shielded helion gyromagnetic ratio in MHz/T é�®è”½ãƒ˜ãƒªã‚ªãƒ³ç£�気回転比 (MHz/T) shielded helion magnetic moment é�®è”½ãƒ˜ãƒªã‚ªãƒ³ç£�気モーメント shielded helion magnetic moment to Bohr magneton ratio é�®è”½ãƒ˜ãƒªã‚ªãƒ³ç£�気モーメント/ボーアç£�å­�比 shielded helion magnetic moment to nuclear magneton ratio é�®è”½ãƒ˜ãƒªã‚ªãƒ³ç£�気モーメント/æ ¸ç£�å­�比 shielded helion to proton magnetic moment ratio é�®è”½ãƒ˜ãƒªã‚ªãƒ³/陽å­�ç£�気モーメント比 shielded helion to shielded proton magnetic moment ratio é�®è”½ãƒ˜ãƒªã‚ªãƒ³/é�®è”½é™½å­�ç£�気モーメント比 alpha particle mass アルファ粒å­�質é‡� alpha particle mass in u アルファ粒å­�質é‡� (u) alpha particle mass energy equivalent アルファ粒å­�質é‡�エãƒ�ルギー等価 alpha particle mass energy equivalent in MeV アルファ粒å­�質é‡�エãƒ�ルギー等価 (MeV) alpha particle-electron mass ratio アルファ粒å­�-é›»å­� 質é‡�比 alpha particle-proton mass ratio アルファ粒å­�-陽å­� 質é‡�比 alpha particle rms charge radius アルファ粒å­� rms é›»è�·å�Šå¾„ alpha particle molar mass アルファ粒å­�モル質é‡� alpha particle relative atomic mass (Ar(α)) アルファ粒å­�相対原å­�質é‡� (Ar(α)) atomic mass constant (mᵤ) 原å­�質é‡�定数 (mᵤ) Avogadro constant アボガドロ定数 Boltzmann constant (k) ボルツマン定数 (k) Boltzmann constant in eV/K ボルツマン定数 (eV/K) Boltzmann constant in Hz/K ボルツマン定数 (Hz/K) Boltzmann constant in inverse meter per kelvin ボルツマン定数 (逆メートル/ケルビン) electron volt (eV) é›»å­�ボルト (eV) Faraday constant (F) ファラデー定数 (F) first radiation constant (câ‚�) 第1放射定数 (câ‚�) first radiation constant for spectral radiance 分光放射è¼�度用第1放射定数 molar gas constant (R) モル気体定数 (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) ロシュミット定数 (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) ロシュミット定数 (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant モルプランク定数 second radiation constant (câ‚‚) 第2放射定数 (câ‚‚) Stefan-Boltzmann constant (σ) シュテファン・ボルツマン定数 (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ç�†æƒ³Siã�®æ ¼å­�é–“éš” (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent 原å­�質é‡�定数エãƒ�ルギー等価 atomic mass constant energy equivalent in MeV 原å­�質é‡�定数エãƒ�ルギー等価 (MeV) atomic mass unit-electron volt relationship 原å­�質é‡�å�˜ä½�-é›»å­�ボルトæ�›ç®—関係 molar mass constant (Mᵤ) モル質é‡�定数 (Mᵤ) molar mass of carbon-12 ç‚­ç´ 12ã�®ãƒ¢ãƒ«è³ªé‡� molar volume of ideal gas (273.15 K, 100 kPa) ç�†æƒ³æ°—体ã�®ãƒ¢ãƒ«ä½“ç©� (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ç�†æƒ³æ°—体ã�®ãƒ¢ãƒ«ä½“ç©� (273.15 K, 101.325 kPa) molar volume of silicon シリコンã�®ãƒ¢ãƒ«ä½“ç©� Sackur-Tetrode constant (1 K, 100 kPa) サックール・テトロード定数 (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) サックール・テトロード定数 (1 K, 101.325 kPa) Wien frequency displacement law constant ウィーン周波数変ä½�則定数 Wien wavelength displacement law constant ウィーン波長変ä½�則定数 standard atmosphere (atm) 標準大気圧 (atm) standard-state pressure (p°) 標準状態圧力 (p°) Angstrom star (Ã…*) オングストロームスター (Ã…*) Copper x unit 銅 x å�˜ä½� Molybdenum x unit モリブデン x å�˜ä½� atomic unit of magnetizability ç£�化率ã�®åŽŸå­�å�˜ä½� atomic unit of mass (mâ‚‘) 原å­�å�˜ä½�ã�®è³ªé‡� (mâ‚‘) atomic unit of momentum 原å­�å�˜ä½�ã�®é�‹å‹•é‡� atomic unit of permittivity 誘電率ã�®åŽŸå­�å�˜ä½� atomic unit of time 原å­�å�˜ä½�ã�®æ™‚é–“ atomic unit of velocity 原å­�å�˜ä½�ã�®é€Ÿåº¦ hartree-hertz relationship ãƒ�ートリー-ヘルツæ�›ç®—関係 hartree-inverse meter relationship ãƒ�ートリー-逆メートルæ�›ç®—関係 hartree-joule relationship ãƒ�ートリー-ジュールæ�›ç®—関係 hartree-kelvin relationship ãƒ�ートリー-ケルビンæ�›ç®—関係 hartree-kilogram relationship ãƒ�ートリー-キログラムæ�›ç®—関係 shielding difference of d and p in HD HDã�«ã�Šã�‘ã‚‹dã�¨pã�®é�®è”½å·® shielding difference of t and p in HT HTã�«ã�Šã�‘ã‚‹tã�¨pã�®é�®è”½å·® pi (Ï€) 円周率 (Ï€) Euler's number (e) ãƒ�イピア数 (e) golden ratio (φ) 黄金比 (φ) Euler-Mascheroni constant (γ) オイラー・マスケローニ定数 (γ) nominal solar radius 公称太陽å�Šå¾„ nominal solar total irradiance 公称太陽ç·�放射照度 nominal solar luminosity 公称太陽光度 nominal solar effective temperature 公称太陽有効温度 nominal solar mass parameter 公称太陽質é‡�パラメータ nominal terrestrial equatorial radius 公称地ç�ƒèµ¤é�“å�Šå¾„ nominal terrestrial polar radius 公称地ç�ƒæ¥µå�Šå¾„ nominal terrestrial mass parameter 公称地ç�ƒè³ªé‡�パラメータ nominal jovian equatorial radius 公称木星赤é�“å�Šå¾„ nominal jovian polar radius 公称木星極å�Šå¾„ nominal jovian mass parameter 公称木星質é‡�パラメータ average value of one minus the rate of TCG relative to TCB TCBã�«å¯¾ã�™ã‚‹TCGã�®ãƒ¬ãƒ¼ãƒˆã‚’1ã�‹ã‚‰å¼•ã�„ã�Ÿå¹³å�‡å€¤ solar mass parameter (TCB-compatible) 太陽質é‡�パラメータ (TCB互æ�›) solar mass parameter (TDB-compatible) 太陽質é‡�パラメータ (TDB互æ�›) equatorial radius of the Earth (TT-compatible) 地ç�ƒã�®èµ¤é�“å�Šå¾„ (TT互æ�›) dynamical form factor of the Earth 地ç�ƒã�®åŠ›å­¦çš„å½¢çŠ¶ä¿‚æ•° time rate of change in the dynamical form factor of the Earth 地ç�ƒã�®åŠ›å­¦çš„å½¢çŠ¶ä¿‚æ•°ã�®æ™‚間変化率 geocentric gravitational constant (TCB-compatible) 地心é‡�力定数 (TCB互æ�›) geocentric gravitational constant (TT-compatible) 地心é‡�力定数 (TT互æ�›) geocentric gravitational constant (TDB-compatible) 地心é‡�力定数 (TDB互æ�›) potential of the geoid ジオイドãƒ�テンシャル nominal mean angular velocity of the Earth (TT-compatible) 公称地ç�ƒå¹³å�‡è§’速度 (TT互æ�›) ratio mass of the Moon to the Earth 月ã�¨åœ°ç�ƒã�®è³ªé‡�比 ratio of the mass of the Sun to Mercury 太陽ã�¨æ°´æ˜Ÿã�®è³ªé‡�比 ratio of the mass of the Sun to Venus 太陽ã�¨é‡‘星ã�®è³ªé‡�比 ratio of the mass of the Sun to Mars 太陽ã�¨ç�«æ˜Ÿã�®è³ªé‡�比 ratio of the mass of the Sun to Jupiter 太陽ã�¨æœ¨æ˜Ÿã�®è³ªé‡�比 ratio of the mass of the Sun to Saturn 太陽ã�¨åœŸæ˜Ÿã�®è³ªé‡�比 ratio of the mass of the Sun to Uranus 太陽ã�¨å¤©çŽ‹æ˜Ÿã�®è³ªé‡�比 ratio of the mass of the Sun to Neptune 太陽ã�¨æµ·çŽ‹æ˜Ÿã�®è³ªé‡�比 ratio of the mass of the Sun to (134340) Pluto 太陽ã�¨(134340)冥王星ã�®è³ªé‡�比 ratio of the mass of the Sun to (136199) Eris 太陽ã�¨(136199)エリスã�®è³ªé‡�比 ratio of the mass of (1) Ceres to the Sun (1)ケレスã�¨å¤ªé™½ã�®è³ªé‡�比 ratio of the mass of (2) Pallas to the Sun (2)パラスã�¨å¤ªé™½ã�®è³ªé‡�比 ratio of the mass of (4) Vesta to the Sun (4)ベスタã�¨å¤ªé™½ã�®è³ªé‡�比 mean obliquity of the ecliptic at J2000.0 J2000.0ã�«ã�Šã�‘る黄é�“傾斜角ã�®å¹³å�‡å€¤ Electromagnetic é›»ç£�æ°— Compton wavelength コンプトン波長 Astronomy 天文学 ConstantsWidget Domain 分野 Subdomain サブ分野 No match found 見ã�¤ã�‹ã‚Šã�¾ã�›ã‚“ã�§ã�—ã�Ÿ Name å��å‰� Value 値 Unit å�˜ä½� Search 検索 All ã�™ã�¹ã�¦ CustomKeypadDialog Custom Keypad カスタムキーパッド Rows: 行: Columns: 列: Copy preset: プリセットをコピー: Basic 基本 Scientific (wide) ç§‘å­¦ (広ã�„) Scientific (narrow) ç§‘å­¦ (ç‹­ã�„) Apply é�©ç”¨ Row 行 Column 列 Label ラベル Behavior 動作 Text テキスト DiagnosticsDialog App Diagnostics アプリã�®è¨ºæ–­ Copy to Clipboard クリップボードã�«ã‚³ãƒ”ー Editor Unit å�˜ä½� User unit ユーザーå�˜ä½� User function ユーザー関数 Argument 引数 Current result:<br/>%1 ç�¾åœ¨ã�®çµ�æžœ:<br/>%1 Selection result:<br/>%1 é�¸æŠžç¯„囲ã�®çµ�æžœ:<br/>%1 Selection result: n/a é�¸æŠžçµ�æžœ: 該当ã�ªã�— Selection result: %1 é�¸æŠžçµ�æžœ: %1 second ç§’ metre メートル kilogram キログラム mole モル radian ラジアン steradian ステラジアン degree Celsius セルシウス度 cubic metre 立方メートル cubic millimetre 立方ミリメートル cubic centimetre ç«‹æ–¹cen時間tre cubic decimetre 立方デシメートル cubic kilometre 立方キロメートル square millimetre 平方ミリメートル square kilometre 平方キロメートル square metre 平方メートル minute 分 hour 時 day æ—¥ astronomical unit 天文å�˜ä½� degree 度 arcminute 分角 arcsecond ç§’è§’ milliarcsecond ミリ秒角 microarcsecond マイクロ秒角 hectare ヘクタール litre リットル tonne トン Dalton ダルトン electronvolt é›»å­�ボルト Angstrom オングストローム atmosphere 気圧 atomic mass unit 原å­�質é‡�å�˜ä½� British thermal unit 英国熱é‡�å�˜ä½� calorie カロリー carat カラット cup カップ cup (Imperial) カップ (英) cup (Japanese) カップ (日本) cup (US) カップ (ç±³) degree Fahrenheit è�¯æ°�度 fathom ファゾム fluid ounce (Imperial) æ¶²é‡�オンス (英) fluid ounce (US) æ¶²é‡�オンス (ç±³) fluid dram (Imperial) æ¶²é‡�ドラム (英) fluid dram (US) æ¶²é‡�ドラム (ç±³) foot フィート square foot 平方フィート cubic foot 立方フィート gallon (Imperial) ガロン (英) gallon (US) ガロン (ç±³) gill (Imperial) ジル (英) gill (US) ジル (ç±³) gradian グラード grain グレーン gram グラム Hartley ãƒ�ートリー Hartree energy unit ãƒ�ートリーエãƒ�ルギーå�˜ä½� horsepower 馬力 inch インãƒ� square inch 平方インãƒ� cubic inch 立方インãƒ� karat カラット (金純度) knot ノット lightminute 光分 lightsecond 光秒 lightyear 光年 long ton 英トン mile マイル square mile 平方マイル cubic mile 立方マイル mile per hour マイル毎時 kilometre per hour キロメートル毎時 nautical mile 海里 ounce オンス parsec パーセク pint (Imperial) パイント (英) pint (US) パイント (ç±³) pound ãƒ�ンド pounds per square inch ãƒ�ンド毎平方インãƒ� quart (Imperial) クォート (英) quart (US) クォート (ç±³) oil barrel 石油ãƒ�レル beer barrel (US) ビールãƒ�レル (ç±³) square yard 平方ヤード cubic yard 立方ヤード short ton 米トン tablespoon 大ã�•ã�˜ tablespoon (Australian) 大ã�•ã�˜ (豪) tablespoon (Imperial) 大ã�•ã�˜ (英) tablespoon (US) 大ã�•ã�˜ (ç±³) dessert spoon デザートスプーン teaspoon å°�ã�•ã�˜ teaspoon (Imperial) å°�ã�•ã�˜ (英) teaspoon (US) å°�ã�•ã�˜ (ç±³) turn ターン revolution 回転 revolution per minute 回転毎分 week 週 kilowatt hour キロワット時 millimetre of mercury 水銀柱ミリメートル yard ヤード Julian century ユリウス世紀 Julian year ユリウス年 sidereal year æ�’星年 tropical year 回帰年 Evaluator invalid expression å¼�ã�Œæ­£ã�—ã��ã�‚りã�¾ã�›ã‚“ division by zero 0ã�§é™¤ç®—ã�•れã�¾ã�—ã�Ÿ too time consuming - computation was rejected 時間ã�Œã�‹ã�‹ã‚Šã�™ã�Žã‚‹ã�Ÿã‚�ã€�計算ã�¯æ‹’å�¦ã�•れã�¾ã�—ã�Ÿ dimension mismatch - quantities with different dimensions cannot be compared, added, etc. 次元ã�Œä¸€è‡´ã�—ã�¾ã�›ã‚“ - ç•°ã�ªã‚‹æ¬¡å…ƒã�®é‡�ã�¯æ¯”較ã€�加算ã�ªã�©ã�Œã�§ã��ã�¾ã�›ã‚“ invalid dimension - operation might require dimensionless arguments 無効ã�ªæ¬¡å…ƒã�§ã�™ - ã�“ã�®æ¼”ç®—ã�¯ç„¡æ¬¡å…ƒã�®å¼•æ•°ã‚’å¿…è¦�ã�¨ã�™ã‚‹å�¯èƒ½æ€§ã�Œã�‚りã�¾ã�™ Computation aborted - encountered numerical instability 計算を中止ã�—ã�¾ã�—ã�Ÿ - 数値的ä¸�安定ã�Œç™ºç”Ÿã�—ã�¾ã�—ã�Ÿ invalid dimension - function might require dimensionless arguments 無効ã�ªæ¬¡å…ƒã�§ã�™ - ã�“ã�®é–¢æ•°ã�¯ç„¡æ¬¡å…ƒã�®å¼•æ•°ã‚’å¿…è¦�ã�¨ã�™ã‚‹å�¯èƒ½æ€§ã�Œã�‚りã�¾ã�™ error エラー unit must not be zero å�˜ä½�ã�¯ 0 ã�§ã�‚ã�£ã�¦ã�¯ã�ªã‚Šã�¾ã�›ã‚“ Conversion failed - dimension mismatch 変æ�›ã�«å¤±æ•—ã�—ã�¾ã�—ã�Ÿ - 次元ã�Œä¸€è‡´ã�—ã�¾ã�›ã‚“ unknown function or variable 定義ã�•れã�ªã�„関数ã�¾ã�Ÿã�¯å¤‰æ•°ã�§ã�™ recursion not supported å†�帰ã�¯ã‚µãƒ�ートã�•れã�¦ã�„ã�¾ã�›ã‚“ cannot operate on a NaN NaNを処ç�†ã�™ã‚‹ã�“ã�¨ã�¯ã�§ã��ã�¾ã�›ã‚“. underflow - tiny result is out of SpeedCrunch's number range アンダーフロー - 極ã‚�ã�¦å°�ã�•ã�„çµ�æžœã�ŒSpeedCrunchã�§è¡¨ç�¾ã�§ã��る値ã�®ç¯„囲を超ã�ˆã�¾ã�—ã�Ÿï¼Ž overflow - huge result is out of SpeedCrunch's number range オーãƒ�ーフロー - 極ã‚�ã�¦å¤§ã��ã�ªçµ�æžœã�ŒSpeedCrunchã�§è¡¨ç�¾ã�§ã��る値ã�®ç¯„囲を超ã�ˆã�¾ã�—ã�Ÿï¼Ž overflow - logic result exceeds maximum of 256 bits オーãƒ�ーフロー - è«–ç�†å€¤ã�®çµ�æžœã�Œæœ€å¤§256bitsã�®ç¯„囲を超ã�ˆã�¾ã�—ã�Ÿï¼Ž overflow - integer result exceeds maximum limit for integers オーãƒ�ーフロー - 整数値ã�®çµ�æžœã�Œè¡¨ç�¾ã�§ã��る範囲ã�®ä¸Šé™�ã‚’è¶…ã�ˆã�¾ã�—ã�Ÿï¼Ž operation is not defined for these arguments ã�“れらã�®å¼•æ•°ã�§ã�¯æ¼”ç®—ã�Œå®šç¾©ã�•れã�¦ã�„ã�¾ã�›ã‚“ wrong number of arguments 引数ã�®æ•°ã�Œé–“é�•ã�£ã�¦ã�„ã�¾ã�™ does not take NaN as an argument 引数ã�«NaNã‚’å�–ã‚‹ã�“ã�¨ã�¯ã�§ã��ã�¾ã�›ã‚“ result out of range çµ�æžœã�Œç¯„囲外ã�§ã�™ undefined for argument domain 未定義ã�®å¼•数領域ã�§ã�™ computation too expensive 計算é‡�ã�Œå¤šã�™ã�Žã�¾ã�™ internal error, please report a bug 内部エラーã�§ã�™ã€‚ãƒ�グを報告ã�—ã�¦ã��ã� ã�•ã�„。 syntax error 構文エラー conversion target must be a unit 変æ�›å…ˆã�¯å�˜ä½�ã�§ã�ªã�‘れã�°ã�ªã‚Šã�¾ã�›ã‚“ unknown unit ä¸�明ã�ªå�˜ä½�ã�§ã�™ %1 is a reserved name, please choose another %1 ã�¯äºˆç´„ã�•れã�¦ã�„ã�¾ã�™ã€‚ä»–ã�®å��å‰�ã‚’é�¸æŠžã�—ã�¦ã��ã� ã�•ã�„。 %1 is a global user definition and cannot be overridden in this session. %1 ã�¯ã‚°ãƒ­ãƒ¼ãƒ�ルユーザー定義ã�§ã�‚りã€�ã�“ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã�§ã�¯ä¸Šæ›¸ã��ã�§ã��ã�¾ã�›ã‚“。 %1 is a variable name, please choose another or delete the variable %1 ã�¯å¤‰æ•°å��ã�§ã�™ã€‚別ã�®å��å‰�ã‚’é�¸ã�¶ã�‹ã€�ã��ã�®å¤‰æ•°ã‚’削除ã�—ã�¦ã��ã� ã�•ã�„ argument %1 is used more than once 引数 %1 ã�Œè¤‡æ•°å›žä½¿ç”¨ã�•れã�¦ã�„ã�¾ã�™ %1 is a built-in unit name, please choose another %1 ã�¯çµ„ã�¿è¾¼ã�¿å�˜ä½�å��ã�§ã�™ã€‚別ã�®å��å‰�ã‚’é�¸ã‚“ã�§ã��ã� ã�•ã�„ %1 is a user function name, please choose another or delete the function %1 ã�¯ãƒ¦ãƒ¼ã‚¶ãƒ¼é–¢æ•°å��ã�§ã�™ã€‚別ã�®å��å‰�ã‚’é�¸ã�¶ã�‹ã€�ã��ã�®é–¢æ•°ã‚’削除ã�—ã�¦ã��ã� ã�•ã�„ FunctionRepo max; trials; probability 最大値; 試行回数; 確率 trials; probability 試行回数; 確率 hits; trials; probability æˆ�功回数; 試行回数; æˆ�功確率 max; total; hits; trials 最大値; è¦�ç´ æ•°; æˆ�功回数; 試行回数 total; hits; trials å�ˆè¨ˆ; æˆ�功回数; 試行回数 count; total; hits; trials æˆ�功数; è¦�ç´ æ•°; æˆ�功状態ã�®è¦�ç´ æ•°; 試行回数 dividend; divisor 被除数; 除数 x; exponent_bits; significand_bits [; exponent_bias] x; 指数部ã�®ãƒ“ット数; 仮数部ã�®ãƒ“ット数 [; 指数ãƒ�イアス] base; x 底; x value; modulo 値; 法 base; exponent; modulo 底; 指数; 法 events; average_events 発生回数; 期待発生回数 average_events 期待発生回数 x [; precision] x [; 精度] Absolute Value 絶対値 Absolute Deviation 絶対å��å·® Arc Cosine 逆余弦 Logical AND è«–ç�†ç©� Area Hyperbolic Cosine 逆å�Œæ›²ç·šä½™å¼¦é–¢æ•° Area Hyperbolic Sine 逆å�Œæ›²ç·šæ­£å¼¦é–¢æ•° Area Hyperbolic Tangent 逆å�Œæ›²ç·šæ­£æŽ¥ Arc Sine 逆正弦 Arc Tangent 逆正接 Arc Tangent with two Arguments 2引数ã�®é€†æ­£æŽ¥ Average (Arithmetic Mean) å¹³å�‡ (ç®—è¡“å¹³å�‡) Binomial Cumulative Distribution Function 二項累ç©�分布関数 Binomial Distribution Mean 二項分布ã�®å¹³å�‡ Binomial Probability Mass Function 二項分布ã�®ç¢ºçŽ‡è³ªé‡�関数 Binomial Distribution Variance 二項分布ã�®åˆ†æ•£ Cube Root 立方根 Complex Conjugate 複素共役 Cosine 余弦 Hyperbolic Cosine å�Œæ›²ç·šä½™å¼¦é–¢æ•° Cotangent 余接 Cosecant 余割 Convert Unix timestamp to Date Unix タイムスタンプを日付ã�«å¤‰æ�› Degrees of Arc å¼§ã�®è§’度 Error Function 誤差関数 Complementary Error Function 相補誤差関数 Exponential 指数関数 Fractional Part å°�数部分 Extension of Factorials [= (x-1)!] 階乗ã�®æ‹¡å¼µ [= (x-1)!] Greatest Common Divisor 最大公約数 Geometric Mean 幾何平å�‡ Gradians of arc グラード角 Hypergeometric Cumulative Distribution Function 超幾何累ç©�分布関数 Hypergeometric Distribution Mean 超幾何分布ã�®å¹³å�‡ Hypergeometric Probability Mass Function 超幾何分布ã�®ç¢ºçŽ‡è³ªé‡�関数 Hypergeometric Distribution Variance 超幾何分布ã�®åˆ†æ•£ Integer Quotient 整数商 Integer Part 整数部分 Imaginary Part 虚部 Decode IEEE-754 Binary Value IEEE-754 ãƒ�イナリ値をデコード Encode IEEE-754 Binary Value IEEE-754 ãƒ�イナリ値をエンコード Decode 16-bit Half-Precision Value 16 ビットå�Šç²¾åº¦å€¤ã‚’デコード Encode 16-bit Half-Precision Value 16 ビットå�Šç²¾åº¦å€¤ã‚’エンコード Decode 32-bit Single-Precision Value 32 ビットå�˜ç²¾åº¦å€¤ã‚’デコード Encode 32-bit Single-Precision Value 32 ビットå�˜ç²¾åº¦å€¤ã‚’エンコード Decode 64-bit Double-Precision Value 64 ビットå€�精度値をデコード Encode 64-bit Double-Precision Value 64 ビットå€�精度値をエンコード Decode 128-bit Quad-Precision Value 128 ビット四å€�精度値をデコード Encode 128-bit Quad-Precision Value 128 ビット四å€�精度値をエンコード Binary Logarithm 二進対数 Common Logarithm 常用対数 Natural Logarithm 自然対数 Logarithm to Arbitrary Base ä»»æ„�ã�®åº•ã�®å¯¾æ•° Mask to a bit size 指定ビット幅ã�§ãƒžã‚¹ã‚¯ Maximum 最大値 Median Value (50th Percentile) 中央値 (50 パーセンタイル) Minimum 最å°�値 Modulo 剰余 Euclidean Modulo ユークリッド剰余 Modular Exponentiation 法付ã��ã�¹ã��ä¹— Combination (Binomial Coefficient) 組ã�¿å�ˆã‚�ã�› (二項係数) Logical NOT è«–ç�†å�¦å®š Permutation (Arrangement) 順列 Convert to Binary Representation 2進表ç�¾ã�¸ã�®å¤‰æ�› Arithmetic ç®—è¡“ Chemistry 化学 Complex 複素数 Combinatorics 組å�ˆã�› Probability 確率 Statistics 統計 Aggregation 集計 Random 乱数 Base conversion 基数変æ�› Number formatting 数値書å¼� Integer arithmetic 整数演算 Special functions 特殊関数 Exponential & Logarithmic 指数ã�¨å¯¾æ•° Angle conversion 角度変æ�› Trigonometry 三角法 Bitwise ビット演算 Floating point 浮動å°�数点 Date & Time 日付ã�¨æ™‚刻 Linear algebra 線形代数 unix_timestamp; x hours offset to GMT Unixタイムスタンプ; GMT ã�‹ã‚‰ x 時間ã�®ã‚ªãƒ•セット yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; GMT ã�‹ã‚‰ x 時間ã�®ã‚ªãƒ•セット [digits] [æ¡�æ•°] max [; min] 最大 [; 最å°�] List Literal リストリテラル Convert to Padded Binary Representation ゼロ埋ã‚�ã�•れã�Ÿ2進表ç�¾ã�¸å¤‰æ�› Round Toward +∞ (Ceiling) +∞方å�‘ã�¸ä¸¸ã‚� (天井関数) Cosine plus Imaginary Sine 余弦 + 虚数正弦 Convert to Cis Complex Form cis複素形å¼�ã�¸å¤‰æ�› Matrix Column Count 行列ã�®åˆ—æ•° Population Correlation Matrix (n) æ¯�集団 相関 行列 (n) Sample Correlation Matrix (n-1) 標本 相関 行列 (n-1) Count 個数 Population Covariance Matrix (n) æ¯�集団 共分散 行列 (n) Sample Covariance Matrix (n-1) 標本 共分散 行列 (n-1) Cross Product 外ç©� Convert Date to Unix timestamp 日付をUnixタイムスタンプã�«å¤‰æ�› Convert to Decimal Representation 10進表ç�¾ã�¸ã�®å¤‰æ�› Determinant 行列å¼� Convert to Sexagesimal Notation 60進表記ã�¸å¤‰æ�› Dot Product 内ç©� Convert to Engineering Notation 工学表記ã�¸å¤‰æ�› Convert to Exponential Complex Form 指数複素形å¼�ã�¸å¤‰æ�› Round Toward −∞ (Floor) −∞方å�‘ã�¸ä¸¸ã‚� (床関数) Flatten Matrix 行列を平å�¦åŒ– Least Common Multiple 最å°�å…¬å€�æ•° Convert to Hexadecimal Representation 16進表ç�¾ã�¸ã�®å¤‰æ�› Convert to Padded Hexadecimal Representation ゼロ埋ã‚�ã�•れã�Ÿ16進表ç�¾ã�¸å¤‰æ�› Inverse Matrix 逆行列 Round to 16-bit Half-Precision Value 16ビットå�Šç²¾åº¦å€¤ã�«ä¸¸ã‚�ã‚‹ Round to 32-bit Single-Precision Value 32ビットå�˜ç²¾åº¦å€¤ã�«ä¸¸ã‚�ã‚‹ Round to 64-bit Double-Precision Value 64ビットå€�精度値ã�«ä¸¸ã‚�ã‚‹ Round to 128-bit Quad-Precision Value 128ビット四å€�精度値ã�«ä¸¸ã‚�ã‚‹ Residual from 16-bit Half-Precision Rounding 16ビットå�Šç²¾åº¦ä¸¸ã‚�ã�®æ®‹å·® Residual from 32-bit Single-Precision Rounding 32ビットå�˜ç²¾åº¦ä¸¸ã‚�ã�®æ®‹å·® Residual from 64-bit Double-Precision Rounding 64ビットå€�精度丸ã‚�ã�®æ®‹å·® Residual from 128-bit Quad-Precision Rounding 128ビット四å€�精度丸ã‚�ã�®æ®‹å·® Substance Mass 物質é‡�ã�®è³ªé‡� Molarity モル濃度 Molar Mass モル質é‡� Median Absolute Deviation 中央絶対å��å·® Mean å¹³å�‡ Numerical Value of Quantity é‡�ã�®æ•°å€¤ Random Decimal Number ランダムã�ª10進数 Random Integer Number ランダムã�ªæ•´æ•° Convert to Rational Representation 有ç�†æ•°è¡¨ç�¾ã�¸å¤‰æ�› Convert to Octal Representation 8進表ç�¾ã�¸ã�®å¤‰æ�› Convert to Padded Octal Representation ゼロ埋ã‚�ã�•れã�Ÿ8進表ç�¾ã�¸å¤‰æ�› Vector or Matrix Norm ベクトルã�¾ã�Ÿã�¯è¡Œåˆ—ã�®ãƒŽãƒ«ãƒ  Logical OR è«–ç�†å’Œ Population Count (Hamming Weight) ビット数 (ãƒ�ミングé‡�ã�¿) Phase of Complex Number 複素数ã�®ä½�相 Poissonian Cumulative Distribution Function ãƒ�アソン分布ã�®ç´¯ç©�分布関数 Poissonian Distribution Mean ãƒ�アソン分布ã�®å¹³å�‡ Poissonian Probability Mass Function ãƒ�アソン分布ã�®ç¢ºçŽ‡è³ªé‡�関数 Poissonian Distribution Variance ãƒ�アソン分布ã�®åˆ†æ•£ Convert to Phasor Complex Form フェーザ複素形å¼�ã�¸å¤‰æ�› Convert to Rectangular Complex Form 直交複素形å¼�ã�¸å¤‰æ�› Round Half Away from Zero å�Šåˆ†ã‚’ゼロã�‹ã‚‰é� ã�„æ–¹ã�¸ä¸¸ã‚� Round Half Even å�Šåˆ†ã‚’å�¶æ•°ã�¸ä¸¸ã‚� Nth Root nä¹—æ ¹ Convert to Scientific Notation 科学表記ã�¸å¤‰æ�› Matrix Row Count 行列ã�®è¡Œæ•° List or Matrix Shape リストã�¾ã�Ÿã�¯è¡Œåˆ—ã�®å½¢çж Summation ç·�å’Œ Population Standard Deviation (n) æ¯�集団 標準å��å·® (n) Sample Standard Deviation (n-1) 標本 標準å��å·® (n-1) Round Toward Zero (Truncation) ゼロ方å�‘ã�¸ä¸¸ã‚� (切りæ�¨ã�¦) Matrix Trace 行列 トレース Transpose Matrix 転置行列 Population Variance (n) æ¯�集団 分散 (n) Sample Variance (n-1) 標本 分散 (n-1) Product ç©� Radians ラジアン Matrix Rank 行列ã�®éšŽæ•° Real Part 実部 Secant 正割 Arithmetic Shift Left 算術左シフト Arithmetic Shift Right ç®—è¡“å�³ã‚·ãƒ•ト Signum 符å�·é–¢æ•° Sine 正弦 Hyperbolic Sine å�Œæ›²ç·šæ­£å¼¦é–¢æ•° Square Root 平方根 Sum å�ˆè¨ˆ Tangent 正接 Convert to Trigonometric Complex Form 三角関数複素形å¼�ã�¸å¤‰æ�› Turns ターン Hyperbolic Tangent å�Œæ›²ç·šæ­£æŽ¥ Sign-extend a value 値を符å�·æ‹¡å¼µ Logical XOR 排他的論ç�†å’Œ FunctionsWidget Domain 分野 All ã�™ã�¹ã�¦ Name å��å‰� Search 検索 No match found 見ã�¤ã�‹ã‚Šã�¾ã�›ã‚“ã�§ã�—ã�Ÿ Identifier 識別å­� HistoryWidget Remove All Calculations Above 上ã�®ã�™ã�¹ã�¦ã�®è¨ˆç®—を削除 Remove This Calculation ã�“ã�®è¨ˆç®—を削除 Remove All Calculations Below 下ã�®ã�™ã�¹ã�¦ã�®è¨ˆç®—を削除 Keypad Inverse cosine 逆余弦 The last result 最後ã�®çµ�æžœ Inverse sine 逆正弦 Inverse tangent 逆正接 Evaluate expression å¼�を評価 Division 除算 Multiplication ä¹—ç®— Subtraction 減算 Addition 加算 Clear expression å¼�ã�®æ¶ˆåŽ» Cosine 余弦 Backspace ãƒ�ックスペース Scientific notation 科学的表記法 Exponential 指数関数 Factorial 階乗 Natural logarithm 自然対数 Left parenthesis å·¦ã�‹ã�£ã�“ Nth root nä¹—æ ¹ Argument separator 引数ã�®åŒºåˆ‡ã‚Š Square 2ä¹— Common logarithm 常用対数 Modulo 剰余 Contextual percentage 文脈ä¾�å­˜ã�®ãƒ‘ーセント Power ã�¹ã��ä¹— Right parenthesis å�³ã�‹ã�£ã�“ Sine 正弦 Square root 平方根 Tangent 正接 Pi 円周率 Decimal separator å°�数点記å�· MainWindow Radian ラジアン Degree 度 Gradian グラード Binary 2進数 Octal 8進数 Hexadecimal 16進数 Sexagesimal å…­å��進法 Engineering decimal 工学的10進表記 Scientific decimal 科学技術10進数 &Import... インãƒ�ート(&I)... &Quit 終了(&Q) Clear E&xpression å¼�ã�®å‰Šé™¤(&x) Clear &History 履歴ã�®å‰Šé™¤(&H) &Copy コピー(&C) &Paste 貼り付ã�‘(&P) &Select Expression å¼�ã�®é�¸æŠž(&S) &Constants 定数(&C) &Functions 関数(&F) &History 履歴(&H) &Status Bar ステータスãƒ�ー(&S) Bitfield ビットフィールド Use&r Functions ユーザー関数(&R) &Degree 度(&D) &Radian ラジアン(&R) &Gradian グラード(&G) Re&volution 回転(&V) Auto-Insert a&ns ansを自動挿入(&N) Automatic &Completion 自動補完(&C) &Built-in Functions 組ã�¿è¾¼ã�¿é–¢æ•°(&B) Built-in &Variables 組ã�¿è¾¼ã�¿å¤‰æ•°(&V) User &Functions ユーザー関数(&F) User Va&riables ユーザー変数(&R) Open a Private Tab on Startup 起動時ã�«ãƒ—ライベートタブを開ã�� Open and focus a new private tab whenever SpeedCrunch starts. SpeedCrunchã�®èµ·å‹•時ã�«ã€�æ–°ã�—ã�„プライベートタブを開ã�„ã�¦ãƒ•ォーカスã�—ã�¾ã�™ã€‚ Syntax &Highlighting 構文強調表示(&H) Group Digits in &Input 入力ã�™ã‚‹æ•°å­—ã‚’æ¡�区切り(&I) Automatic Input &Adjustments 入力ã�®è‡ªå‹•調整(&A) Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. 演算å­�ã€�空白ã€�括弧ã€�累乗を自動調整ã�—ã€�有効ã�ªæ–‡å­—ã�®ã�¿å…¥åŠ›ã�§ã��るよã�†ã�«ã�—ã�¾ã�™ã€‚ Group input digits using the selected number format. é�¸æŠžã�—ã�Ÿæ•°å€¤å½¢å¼�ã�«å¾“ã�£ã�¦å…¥åŠ›ã�™ã‚‹æ•°å­—ã‚’æ¡�区切りã�—ã�¾ã�™ã€‚ &Blinking Cursor カーソルã�®ç‚¹æ»…(&B) Blink the cursor in the expression editor. æ•°å¼�エディターã�®ã‚«ãƒ¼ã‚½ãƒ«ã‚’点滅ã�•ã�›ã�¾ã�™ã€‚ &Escape Clears Editor Escapeã�§ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã‚’クリア(&E) Clear the focused expression editor with Escape after dismissing any popup or preview. ãƒ�ップアップやプレビューを閉ã�˜ã�Ÿå¾Œã€�Escapeã�§ãƒ•ォーカスã�®ã�‚ã‚‹æ•°å¼�エディターをクリアã�—ã�¾ã�™ã€‚ Keep Expression After Evaluation 計算後も数å¼�ã‚’ä¿�æŒ� Copy New Results Automatically æ–°ã�—ã�„çµ�果を自動コピー &Comma カンマ(&C) &System Default 既定ã�®è¨­å®š(&S) &Dot ドット(&D) Dot &And Comma ドットã�¨ã‚«ãƒ³ãƒž(&A) Toward +∞ (&ceil) +∞方å�‘ (ceil)(&C) Toward −∞ (&floor) −∞方å�‘ (floor)(&F) &Binary 2進数(B&) &Engineering 工学(&E) &Hexadecimal 16進数(&H) &Octal 8進数(&O) &Scientific ç§‘å­¦(&S) User &Manual ユーザーマニュアル(&M) Issues and &Feedback å•�題ã�¨ãƒ•ィードãƒ�ック(&F) &Donate 寄付ã�™ã‚‹(&D) &About SpeedCrunch SpeedCrunchã�«ã�¤ã�„ã�¦(&A) App Diag&nostics アプリã�®è¨ºæ–­(&N) S&plit 分割(&P) Angle &Mode 角度モード(&M) &Complex Form 複素数ã�®å½¢å¼�(&C) New Tab æ–°ã�—ã�„タブ Constants 定数 Functions 関数 History 履歴 User Functions ユーザー関数 &Font... フォント (&F) &Language... 言語(&L)... &Session セッション(&S) &Edit 編集(&E) &View 表示(&V) Se&ttings 設定(&t) &Decimal 10進数(&D) &Keypad キーパッド(&K) Always on &Top 常ã�«æœ€å‰�é�¢ã�«è¡¨ç¤ºï¼ˆ&T) Disabled ã�ªã�— Small Space 空白(狭) Medium Space 空白(中) Large Space 空白(広ã�„) &0 Digits 0æ¡�(&0) &15 Digits 15æ¡�(&1) &2 Digits 2æ¡�(&2) &3 Digits 3æ¡�(&3) &50 Digits 50æ¡�(&5) &8 Digits 8æ¡�(&8) &Sexagesimal å…­å��進法(&S) Reset All Settings... ã�™ã�¹ã�¦ã�®è¨­å®šã‚’リセット... &System システム(&S) SpeedCrunch &Theme SpeedCrunchã�®ãƒ†ãƒ¼ãƒž(&T) &Classic クラシック(&C) &Modern モダン(&M) Context Help コンテキストヘルプ &Help ヘルプ(&H) Error エラー Can't read from file %1 %1 を読ã�¿è¾¼ã‚€ã�“ã�¨ã�Œã�§ã��ã�¾ã�›ã‚“ Import Session セッションã�®ã‚¤ãƒ³ãƒ�ート Close Session セッションを閉ã�˜ã‚‹ Angle Mode: 角度モード: Notation: 表記: Precision: 精度: Turn ターン Revolution 回転 Fixed-point decimal 固定å°�数点10進表記 Rational 有ç�†æ•° Automatic decimal 自動10進表記 Automatic 自動 User &Definitions... ユーザー定義(&D)... New &Tab æ–°ã�—ã�„タブ(&T) New &Private Tab æ–°ã�—ã�„プライベートタブ(&P) Keep ä¿�æŒ� Make Private... プライベートã�«ã�™ã‚‹... New &Window æ–°ã�—ã�„ウィンドウ(&W) &Open... é–‹ã��(&O)... &Rename... å��å‰�を変更(&R)... Clo&ne... 複製(&N)... &Close Tab タブを閉ã�˜ã‚‹(&C) Reopen Clo&sed Tab é–‰ã�˜ã�Ÿã‚¿ãƒ–ã‚’é–‹ã��ç›´ã�™(&S) Open Sessions &Folder セッションフォルダーを開ã��(&F) &Undo å…ƒã�«æˆ»ã�™(&U) &Redo やり直ã�™(&R) Cu&t 切りå�–り(&T) Copy &Last Result 最後ã�®çµ�果をコピー(&L) &Wrap in Parentheses 括弧ã�§å›²ã‚€(&W) Full Scr&een Mode 全画é�¢ãƒ¢ãƒ¼ãƒ‰(&E) &Basic 基本(&B) &Scientific (wide) ç§‘å­¦ (広ã�„)(&S) Scientific (narrow) ç§‘å­¦ (ç‹­ã�„) &Custom... カスタム(&C)... Main &Menu メインメニュー(&M) User &Variables ユーザー変数(&V) &Left å·¦(&L) &Right å�³(&R) &Up 上(&U) &Down 下(&D) Close Pa&ne ペインを閉ã�˜ã‚‹(&N) User &Units ユーザーå�˜ä½�(&U) &Turn ターン(&T) If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. æ–°ã�—ã�„å¼�ã�Œ +ã€�-ã€�*ã€�/ ã�§å§‹ã�¾ã‚‹å ´å�ˆã€�SpeedCrunch ã�¯å…ˆé ­ã�« "ans" を挿入ã�—ã�¾ã�™ã€‚ &Accept with Enter Enterã�§ç¢ºå®š(&A) Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. 矢å�°ã‚­ãƒ¼ã�§é�¸æŠžã�—ã�ªã��ã�¦ã‚‚ã€�Enterキーã�§ç�¾åœ¨ã�®è‡ªå‹•補完候補を確定ã�—ã�¾ã�™ã€‚ &Units å�˜ä½�(&U) Show Live Result &Preview ライブçµ�果プレビューを表示(&P) Save &Window Position on Exit 終了時ã�«ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ä½�置をä¿�å­˜(&W) Hover Highlighting ホãƒ�ー強調表示 Group Integer Part Only 整数部ã�®ã�¿ã‚°ãƒ«ãƒ¼ãƒ—化 Number Format... 数値形å¼�... Notation && Precision... 表記ã�¨ç²¾åº¦... After pressing Enter, keep the entered expression selected in the editor. Enter キーを押ã�—ã�Ÿå¾Œã€�入力ã�—ã�Ÿå¼�をエディター内ã�§é�¸æŠžã�—ã�Ÿã�¾ã�¾ã�«ã�—ã�¾ã�™ã€‚ Never ã�—ã�ªã�„ Always 常ã�« Only for Single-Line Expressions å�˜ä¸€è¡Œã�®å¼�ã�®ã�¿ Simplify Displayed Expressions 表示ã�•れるå¼�を簡略化 History Size &Limit... 履歴サイズ制é™�(&L)... Remove Trailing &Zeroes 末尾ã�®ã‚¼ãƒ­ã‚’削除(&Z) Nearest, Half &Away (round) 最近接ã€�å�Šåˆ†ã�¯ã‚¼ãƒ­ã�‹ã‚‰é� ã�„æ–¹(&A) (round) Nearest, Half &Even (roundeven) 最近接ã€�å�Šåˆ†ã�¯å�¶æ•°(&E) (roundeven) Toward &Zero (trunc) ゼロ方å�‘(&Z) (trunc) &Fixed-Point 固定å°�数点(&F) &Rational 有ç�†æ•°(&R) &Exponential (m·sâ�»Â¹) 指数表記(&E) (m·sâ�»Â¹) &Fractional (m/s) 分数表記(&F) (m/s) &Rectangular (a + bi) 直交形å¼�(&R) (a + bi) Exponential (reâ�±á¶¿) 指数形å¼� (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) 三角形å¼� (r(cos θ + i·sin θ)) Phasor (r∠θ) フェーザ形å¼� (r∠θ) &Theme... テーマ(&T)... Check for &Updates 更新を確èª�(&U) Source Code ソースコード &Zoom ズーム(&Z) &Results çµ�æžœ(&R) Unit Notation å�˜ä½�表記 Rounding Mode 丸ã‚�モード &Notation 表記(&N) &Imaginary Unit 虚数å�˜ä½�(&I) &Window ウィンドウ(&W) &Editing 編集(&E) A&utocomplete 自動補完(&U) Up/Down Arrow History 上下矢å�°ã�§å±¥æ­´ &Appearance 外観(&A) &Menus メニュー(&M) &Docks ドック(&D) &Input and Results 入力ã�¨çµ�æžœ(&I) &Disabled 無効(&D) &Disable 無効化(&D) Close preview プレビューを閉ã�˜ã‚‹ Rename... å��å‰�を変更... Clone... 複製... Close Tab タブを閉ã�˜ã‚‹ New Private Tab æ–°ã�—ã�„プライベートタブ Open... é–‹ã��... Reopen Closed Tab é–‰ã�˜ã�Ÿã‚¿ãƒ–ã‚’é–‹ã��ç›´ã�™ Split 分割 Left å·¦ Right å�³ Up 上 Down 下 Clear クリア Delete 削除 %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 プライベートセッション: é–‰ã�˜ã‚‹ã�¨å†…容ã�¯ç ´æ£„ã�•れã�¾ã�™ã€‚ 通常ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã�«ã�™ã‚‹ã�«ã�¯ã€�セッション > ä¿�æŒ�ã‚’é�¸æŠžã�—ã�¦ã��ã� ã�•ã�„。 SpeedCrunch - %1 [Private] SpeedCrunch - %1 [プライベート] Reset All Settings ã�™ã�¹ã�¦ã�®è¨­å®šã‚’リセット Reset all settings to their default values? ã�™ã�¹ã�¦ã�®è¨­å®šã‚’既定値ã�«æˆ»ã�—ã�¾ã�™ã�‹ï¼Ÿ This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. 外観ã€�編集ã€�çµ�æžœã�®å½¢å¼�ã€�ウィンドウã�®è¨­å®šã�Œå¯¾è±¡ã�§ã�™ã€‚計算ã€�é–‹ã�„ã�¦ã�„るセッションã€�ユーザー定義ã�¯ä¿�æŒ�ã�•れã�¾ã�™ã€‚ The settings file could not be written. 設定ファイルを書ã��è¾¼ã‚�ã�¾ã�›ã‚“ã�§ã�—ã�Ÿã€‚ Clear this session's calculations, unfinished expression, variables, functions, and units? ã�“ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã�®è¨ˆç®—ã€�未完æˆ�ã�®æ•°å¼�ã€�変数ã€�関数ã€�å�˜ä½�をクリアã�—ã�¾ã�™ã�‹ï¼Ÿ Global user definitions are kept. グローãƒ�ルã�ªãƒ¦ãƒ¼ã‚¶ãƒ¼å®šç¾©ã�¯ä¿�æŒ�ã�•れã�¾ã�™ã€‚ Make Session Private セッションをプライベートã�«ã�™ã‚‹ The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. ä¿�存済ã�¿ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ %1 ã�¯å‰Šé™¤ã�•れã�¾ã�™ã€‚内容ã�¯ãƒ—ライベートセッションã�§é–‹ã�„ã�Ÿã�¾ã�¾ã�«ã�ªã‚Šã€�ã��ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’é–‰ã�˜ã‚‹ã�‹SpeedCrunchを終了ã�™ã‚‹ã�¨ç ´æ£„ã�•れã�¾ã�™ã€‚ Make Private プライベートã�«ã�™ã‚‹ Could not delete the saved session %1. ä¿�存済ã�¿ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ %1 を削除ã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿã€‚ Keep Session セッションをä¿�æŒ� Could not save the session. It remains private. セッションをä¿�å­˜ã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿã€‚プライベートã�®ã�¾ã�¾ã�§ã�™ã€‚ Clone Session セッションを複製 Could not save session file %1. セッションファイル %1 ã‚’ä¿�å­˜ã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿã€‚ Could not delete session file %1. セッションファイル %1 を削除ã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿã€‚ JSON file (*.json);;Any file (*.*) JSONファイル (*.json);;ä»»æ„�ã�®ãƒ•ァイル (*.*) Export session as JSON セッションをJSONã�¨ã�—ã�¦å‡ºåŠ› The selected file is not valid JSON: %1 é�¸æŠžã�—ã�Ÿãƒ•ァイルã�¯æœ‰åйã�ªJSONã�§ã�¯ã�‚りã�¾ã�›ã‚“: %1 The selected file is not a SpeedCrunch session JSON file. é�¸æŠžã�—ã�Ÿãƒ•ァイルã�¯SpeedCrunchセッションã�®JSONファイルã�§ã�¯ã�‚りã�¾ã�›ã‚“。 This file uses an obsolete SpeedCrunch session format and cannot be imported. ã�“ã�®ãƒ•ァイルã�¯å�¤ã�„SpeedCrunchセッション形å¼�を使用ã�—ã�¦ã�„ã‚‹ã�Ÿã‚�ã€�インãƒ�ートã�§ã��ã�¾ã�›ã‚“。 The selected JSON file is missing the required $schema field. é�¸æŠžã�—ã�ŸJSONファイルã�«ã�¯å¿…é ˆã�®$schemaフィールドã�Œã�‚りã�¾ã�›ã‚“。 The selected JSON file uses an unsupported JSON schema: %1 é�¸æŠžã�—ã�ŸJSONファイルã�¯ã‚µãƒ�ートã�•れã�¦ã�„ã�ªã�„JSONスキーマを使用ã�—ã�¦ã�„ã�¾ã�™: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). é�¸æŠžã�—ã�ŸJSONファイルã�«ã�¯SpeedCrunchセッションスキーマ識別å­�($id)ã�Œã�‚りã�¾ã�›ã‚“。 The selected JSON file uses an unsupported SpeedCrunch session format: %1 é�¸æŠžã�—ã�ŸJSONファイルã�¯ã‚µãƒ�ートã�•れã�¦ã�„ã�ªã�„SpeedCrunchセッション形å¼�を使用ã�—ã�¦ã�„ã�¾ã�™: %1 The selected JSON file is missing the required session name. é�¸æŠžã�—ã�ŸJSONファイルã�«ã�¯å¿…é ˆã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³å��ã�Œã�‚りã�¾ã�›ã‚“。 The selected JSON file has an empty session name. é�¸æŠžã�—ã�ŸJSONファイルã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³å��ã�¯ç©ºã�§ã�™ã€‚ The selected JSON file has invalid or incomplete SpeedCrunch session data. é�¸æŠžã�—ã�ŸJSONファイルã�«ã�¯ç„¡åйã�¾ã�Ÿã�¯ä¸�完全ã�ªSpeedCrunchセッションデータã�Œã�‚りã�¾ã�™ã€‚ Open Sessions Folder セッションフォルダーを開ã�� Could not create the sessions folder: %1 セッションフォルダーを作æˆ�ã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿ: %1 Could not open the sessions folder: %1 セッションフォルダーを開ã�‘ã�¾ã�›ã‚“ã�§ã�—ã�Ÿ: %1 Editor and Results Font エディターã�¨çµ�æžœã�®ãƒ•ォント Open Session セッションを開ã�� Community コミュニティ Rename Session セッションå��を変更 Clear Session セッションをクリア Delete Session セッションを削除 Close Pane ペインを閉ã�˜ã‚‹ User Variables ユーザー変数 User Units ユーザーå�˜ä½� Clear History 履歴をクリア Are you sure you want to clear the calculation history? 計算履歴をクリアã�—ã�¦ã‚‚よã‚�ã�—ã�„ã�§ã�™ã�‹? Session name: セッションå��: A session named %1 already exists. %1 ã�¨ã�„ã�†å��å‰�ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã�¯æ—¢ã�«å­˜åœ¨ã�—ã�¾ã�™ã€‚ Could not create session file %1. セッションファイル %1 を作æˆ�ã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿã€‚ Could not write session file %1. セッションファイル %1 ã�«æ›¸ã��è¾¼ã‚�ã�¾ã�›ã‚“ã�§ã�—ã�Ÿã€‚ Are you sure you want to delete this session? ã�“ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’削除ã�—ã�¦ã‚‚よã‚�ã�—ã�„ã�§ã�™ã�‹? Custom Precision カスタム精度 Fractional digits: å°�æ•°æ¡�æ•°: Theme テーマ Light Themes ライトテーマ Dark Themes ダークテーマ Preview プレビュー Colors 色 Select color for %1 %1 ã�®è‰²ã‚’é�¸æŠž Import... インãƒ�ート... Export... エクスãƒ�ート... Import Theme テーマをインãƒ�ート Theme file (*.json);;All files (*) テーマファイル (*.json);;ã�™ã�¹ã�¦ã�®ãƒ•ァイル (*) Invalid theme file. 無効ã�ªãƒ†ãƒ¼ãƒžãƒ•ァイルã�§ã�™ã€‚ Can't import theme "%1" because it conflicts with a built-in theme. 組ã�¿è¾¼ã�¿ãƒ†ãƒ¼ãƒžã�¨ç«¶å�ˆã�™ã‚‹ã�Ÿã‚�ã€�テーマ "%1" をインãƒ�ートã�§ã��ã�¾ã�›ã‚“。 Can't find a writable theme folder. 書ã��è¾¼ã�¿å�¯èƒ½ã�ªãƒ†ãƒ¼ãƒžãƒ•ォルダーã�Œè¦‹ã�¤ã�‹ã‚Šã�¾ã�›ã‚“。 Overwrite Theme テーマを上書ã�� A custom theme named "%1" already exists. Do you want to overwrite it? "%1" ã�¨ã�„ã�†å��å‰�ã�®ã‚«ã‚¹ã‚¿ãƒ ãƒ†ãƒ¼ãƒžã�¯æ—¢ã�«å­˜åœ¨ã�—ã�¾ã�™ã€‚上書ã��ã�—ã�¾ã�™ã�‹? Can't overwrite theme file %1 テーマファイル %1 を上書ã��ã�§ã��ã�¾ã�›ã‚“。 Can't copy theme file to %1 テーマファイルを %1 ã�«ã‚³ãƒ”ーã�§ã��ã�¾ã�›ã‚“。 Export Theme テーマをエクスãƒ�ート Can't export theme as "%1" because it conflicts with a built-in theme. 組ã�¿è¾¼ã�¿ãƒ†ãƒ¼ãƒžã�¨ç«¶å�ˆã�™ã‚‹ã�Ÿã‚�ã€�テーマを "%1" ã�¨ã�—ã�¦ã‚¨ã‚¯ã‚¹ãƒ�ートã�§ã��ã�¾ã�›ã‚“。 Can't write to file %1 %1 ã‚’ä¿�å­˜ã�™ã‚‹ã�“ã�¨ã�Œã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿ Global User Variable グローãƒ�ルユーザー変数 Global User Function グローãƒ�ルユーザー関数 Global User Unit グローãƒ�ルユーザーå�˜ä½� User Definitions ユーザー定義 These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. ã�“れらã�®å®šç¾©ã�¯ã‚°ãƒ­ãƒ¼ãƒ�ルã�§ã€�ã�™ã�¹ã�¦ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã�«èª­ã�¿è¾¼ã�¾ã‚Œã�¾ã�™ã€‚ セッション内ã�§ã�¯å¤‰æ›´ã�§ã��ã�šã€�セッションエディターã�®å�Œå��ã�®å®šç¾©ã‚ˆã‚Šå„ªå…ˆã�•れã�¾ã�™ã€‚ 1 行ã�« 1 ã�¤ã�®å®šç¾©ã‚’入力ã�—ã�¦ã��ã� ã�•ã�„。 Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] 例: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply é�©ç”¨ Validate 検証 Test Results テストçµ�æžœ Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 インãƒ�ートã�•れã�Ÿå¤‰æ•°: %1 インãƒ�ートã�•れã�Ÿé–¢æ•°: %2 インãƒ�ートã�•れã�Ÿå�˜ä½�: %3 エラーã�®ã�‚る行番å�·: %4 none ã�ªã�— Apply Results é�©ç”¨çµ�æžœ User definitions saved. ユーザー定義をä¿�å­˜ã�—ã�¾ã�—ã�Ÿã€‚ History Size Limit 履歴サイズ制é™� Maximum number of history entries for this session (0 = unlimited): ã�“ã�®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã�®å±¥æ­´é …ç›®ã�®æœ€å¤§æ•° (0 = 無制é™�): Text file (*.txt);;Any file (*.*) テキストファイル(*.txt);;ã�™ã�¹ã�¦ã�®ãƒ•ァイル(*.*) Could not recalculate from calculation %1: %2 計算 %1 ã�‹ã‚‰å†�計算ã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿ: %2 History Size Limit Reached 履歴サイズ制é™�ã�«é�”ã�—ã�¾ã�—ã�Ÿ This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. ã�“ã�®è¨ˆç®—ã�§æœ€å¾Œã�®åˆ©ç”¨å�¯èƒ½ã�ªå±¥æ­´æž ã�ŒåŸ‹ã�¾ã‚Šã�¾ã�™ã€‚今後ã�®è¨ˆç®—ã�§ã�¯ã€�履歴ã�‹ã‚‰æœ€ã‚‚å�¤ã�„計算ã�Œå‰Šé™¤ã�•れã�¾ã�™ã€‚上é™�ã�¯ セッション > 履歴サイズ制é™� ã�‹ã‚‰å¢—ã‚„ã�›ã�¾ã�™ã€‚ Editing calculation. Press Esc twice to cancel. 計算を編集中ã�§ã�™ã€‚キャンセルã�™ã‚‹ã�«ã�¯ Esc ã‚’2回押ã�—ã�¦ã��ã� ã�•ã�„。 Calculation Settings 計算設定 Invalid recalculation start index å†�計算開始インデックスã�Œç„¡åйã�§ã�™ System Default システムã�®æ—¢å®š Language 言語 Select the language: 言語ã�®é�¸æŠž: Custom カスタム Decimal places: å°�æ•°æ¡�æ•°: &Automatic 自動(&A) &Precision 精度(&P) Plain &text プレーンテキスト (&t) Formula &Book å…¬å¼�集 (&B) &Export エクスãƒ�ート (&E) Export session as HTML セッションをHTMLã�§å‡ºåŠ› HTML file (*.html) HTMLファイル(*.html) Export session as plain text セッションをテキストã�§å‡ºåŠ› ManualWindow SpeedCrunch Manual SpeedCrunch マニュアル %1 - SpeedCrunch Manual %1 - SpeedCrunch マニュアル NumberFormatDialog Number Format 数値形å¼� <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>çµ�æžœã�¨å…¥åŠ›ã�®æ¡�区切りã�«ä½¿ç”¨ã�™ã‚‹æ•°å€¤å½¢å¼�ã‚’é�¸æŠžã�—ã�¦ã��ã� ã�•ã�„。</b><br/><br/>注: 入力ã�™ã‚‹æ•°å€¤ã�®å½¢å¼�ã�Œæ˜Žç¢ºã�ªå ´å�ˆã�¯ã€�é�¸æŠžã�—ã�Ÿè¡¨ç¤ºå½¢å¼�ã�¨ç•°ã�ªã�£ã�¦ã�„ã�¦ã‚‚å�—ã�‘付ã�‘ã�¾ã�™ã€‚<br/> QObject Global User Variable グローãƒ�ルユーザー変数 Global User Function グローãƒ�ルユーザー関数 Global User Unit グローãƒ�ルユーザーå�˜ä½� Backspace ãƒ�ックスペース Clear expression å¼�を消去 Evaluate expression å¼�を評価 Insert text テキストを挿入 Automatic decimal 自動10進表記 Fixed-point decimal 固定å°�数点10進表記 Engineering decimal 工学10進表記 Scientific decimal ç§‘å­¦10進表記 Rational 有ç�†æ•° Binary 2進数 Octal 8進数 Hexadecimal 16進数 Sexagesimal 60進数 Update Available æ›´æ–°ã�Œã�‚りã�¾ã�™ A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> æ–°ã�—ã�„ãƒ�ージョン (%1) ã�Œåˆ©ç”¨å�¯èƒ½ã�§ã�™ã€‚<br/><a href="%2">Webサイトã�«ã‚¢ã‚¯ã‚»ã‚¹ã�—ã�¦ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã�—ã�¦ã��ã� ã�•ã�„。</a> Check for Updates 更新を確èª� SpeedCrunch %1 is up to date. SpeedCrunch %1 ã�¯æœ€æ–°ã�§ã�™ã€‚ No connectivity. Please check your internet connection and try again. 接続ã�§ã��ã�¾ã�›ã‚“。インターãƒ�ット接続を確èª�ã�—ã�¦å†�試行ã�—ã�¦ã��ã� ã�•ã�„。 Could not verify the latest available version. 利用å�¯èƒ½ã�ªæœ€æ–°ãƒ�ージョンを確èª�ã�§ã��ã�¾ã�›ã‚“ã�§ã�—ã�Ÿã€‚ ResultDisplay Scroll to bottom 一番下ã�¸ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ« Edit Expression å¼�を編集 Change Settings 設定を変更 New Tab æ–°ã�—ã�„タブ &Import... インãƒ�ート(&I)... &Export エクスãƒ�ート(&E) Plain &text プレーンテキスト(&T) Copy コピー Selection é�¸æŠžç¯„囲 Select All ã�™ã�¹ã�¦é�¸æŠž Expression æ•°å¼� Result çµ�æžœ Calculation 計算 Calculation as Single Line 計算を1行ã�«ã�¾ã�¨ã‚�ã‚‹ Remove 削除 This Calculation ã�“ã�®è¨ˆç®— All Calculations Above 上ã�®ã�™ã�¹ã�¦ã�®è¨ˆç®— All Calculations Below 下ã�®ã�™ã�¹ã�¦ã�®è¨ˆç®— New Private Tab æ–°ã�—ã�„プライベートタブ Session セッション Open... é–‹ã��... Clone... 複製... Rename... å��å‰�を変更... Keep ä¿�æŒ� Make Private... プライベートã�«ã�™ã‚‹... Clear クリア Delete 削除 Close é–‰ã�˜ã‚‹ Split 分割 Left å·¦ Right å�³ Up 上 Down 下 Close Pane ペインを閉ã�˜ã‚‹ Main Menu メインメニュー Cancel editing 編集をキャンセル Copy result çµ�果をコピー Edit expression å¼�を編集 Change settings 設定を変更 Remove calculation 計算を削除 ResultSlotsDialog Notation & Precision 表記ã�¨ç²¾åº¦ Result Line çµ�果行 Enabled 有効 Notation 表記 Decimal Places å°�æ•°æ¡�æ•° Main Line メイン行 Extra Line #1 追加行 #1 Extra Line #2 追加行 #2 Extra Line #3 追加行 #3 Extra Line #4 追加行 #4 Auto 自動 UserFunctionListWidget Name å��å‰� Value 値 Description 説明 Search 検索 No match found 見ã�¤ã�‹ã‚Šã�¾ã�›ã‚“ã�§ã�—ã�Ÿ Insert 挿入 Edit 編集 Delete 削除 Delete All å…¨ã�¦å‰Šé™¤ UserUnitListWidget Name å��å‰� Value 値 Description 説明 Search 検索 No match found 一致ã�™ã‚‹ã‚‚ã�®ã�Œè¦‹ã�¤ã�‹ã‚Šã�¾ã�›ã‚“ Insert 挿入 Edit 編集 Delete 削除 Delete All ã�™ã�¹ã�¦å‰Šé™¤ VariableListWidget Name å��å‰� Value 値 Description 説明 Search 検索 No match found 見ã�¤ã�‹ã‚Šã�¾ã�›ã‚“ã�§ã�—ã�Ÿ Insert 挿入 Edit 編集 Delete 削除 Delete All å…¨ã�¦å‰Šé™¤ heldercorreia-speedcrunch-e7ca37f/src/resources/locale/ko.ts000066400000000000000000010475021526573132500243670ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunch ì •ë³´ Core developers 핵심 개발ìž� Original author 최초 개발ìž� Close 닫기 Math engine 수학 엔진 Main author | Logo | Maintainer 주 ì €ìž� | 로고 | 관리ìž� Thanks ê°�사한 ë¶„ Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 SpeedCrunch 개발팀 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version ì�´ 프로그램ì�€ ìž�유 소프트웨어입니다. 소프트웨어ì�˜ 피양ë�„ìž�는 ìž�유 소프트웨어 재단ì�´ 공표한 GNU ì�¼ë°˜ 공중 사용 허가서 2íŒ� ë˜�는 ê·¸ ì�´í›„ íŒ�ì�„ ìž„ì�˜ë¡œ ì„ íƒ�해서, ê·¸ 규정ì—� ë”°ë�¼ 프로그램ì�„ 개작하거나 재배í�¬í•  수 있습니다 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ì�´ 프로그램ì�€ 유용하게 사용ë�  수 있으리ë�¼ëŠ” í�¬ë§�ì—�서 ë°°í�¬ë�˜ê³  있지만, 특정한 목ì �ì—� 맞는 ì �합성 여부나 íŒ�매용으로 사용할 수 있으리ë�¼ëŠ” 묵시ì �ì�¸ ë³´ì¦�ì�„ í�¬í•¨í•œ 어떠한 형태ì�˜ ë³´ì¦�ë�„ 제공하지 않습니다. 보다 ìž�세한 사항ì—� 대해서는 GNU ì�¼ë°˜ 공중 사용 허가서를 참고하시기 ë°”ëž�니다. BitFieldWidget Reset bits to zero 비트를 0으로 재설정 Invert bits 비트 반전 Shift bits left 비트를 왼쪽으로 시프트 Shift bits right 비트를 오른쪽으로 시프트 Book Index 목차 Algebra 대수학 Quadratic Equation 2ì°¨ ë°©ì •ì‹� Logarithmic Base Conversion 로그 ë°‘ 변환 Geometry 기하학 Circle ì›� Sector 부채꼴 Sphere 구 Cube 정육면체 Cone ì›�ë¿” Cylinder ì›�기둥 Electronics ì „ìž�공학 Ohm's Law 옴ì�˜ 법칙 Power ì „ë ¥ Reactance 리액턴스 Resonance 공진 Radio Frequency 무선 주파수 Antennas 안테나 Characteristic Impedance (coax) 특성 임피ë�˜ìФ(ë�™ì¶•ì¼€ì�´ë¸”) Velocity of Propagation (coax) 전파 ì†�ë�„(ë�™ì¶•ì¼€ì�´ë¸”) Standing Wave Ratio & Return Loss 정지파 비율 ë°� 반사 ì†�실 Free Space Wavelength ìž�유 공간 파장 resistance 저항 voltage ì „ì•• current 전류 power ì „ë ¥ inductive reactance 유ë�„ 리액턴스 capacitive reactance 용량 리액턴스 inductance ì�¸ë�•턴스 capacitance 전기 용량 frequency 주파수 resonance frequency 공진 주파수 area ë©´ì � perimeter 둘레 diameter 지름 radius 반지름 volume 부피 surface area 표면ì � height 높ì�´ slant height 비탈 높ì�´ face diagonal í�‰ë©´ 대ê°�ì„  space diagonal ìž…ì²´ 대ê°�ì„  edge length 모서리 길ì�´ arc length 호 길ì�´ central angle (degrees) 중심ê°�(ë�„) input power ìž…ë ¥ ì „ë ¥ reflected power 반사 ì „ë ¥ transmitted power 전달 ì „ë ¥ return loss 반사 ì†�실 dielectric constant 유전 ìƒ�수 outer conductor's inner diameter 외부 ë�„ì²´ì�˜ 안지름 inner conductor's outer diameter ë‚´ë¶€ ë�„ì²´ì�˜ 바깥지름 speed of light ë¹›ì�˜ ì†�ë ¥ reflection coefficient 반사 계수 standing wave ratio 정지파 비율 normalized impedance 정규화 임피ë�˜ìФ frequency (Hz) ì§„ë�™ìˆ˜(Hz) BookDock Formula Book ê³µì‹� ì±… ConstantCompletion Search constants ìƒ�수 검색 No match found ì�¼ì¹˜í•˜ëŠ” 항목 ì—†ì�Œ Constants Mathematics 수학 Physics (CODATA 2022) 물리학 (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) 화학 (IUPAC - CIAAW 2021) Uncategorized 분류 ì—†ì�Œ Universal ì�¼ë°˜ ìƒ�수 Physicochemical 물리화학 Atomic & Nuclear — General ì›�ìž� ë°� 핵 — ì�¼ë°˜ Atomic & Nuclear — Electroweak ì›�ìž� ë°� 핵 — 전기약력 Atomic & Nuclear — Electron ì›�ìž� ë°� 핵 — ì „ìž� Atomic & Nuclear — Muon ì›�ìž� ë°� 핵 — 뮤온 Atomic & Nuclear — Tau ì›�ìž� ë°� 핵 — 타우 Atomic & Nuclear — Proton ì›�ìž� ë°� 핵 — 양성ìž� Atomic & Nuclear — Neutron ì›�ìž� ë°� 핵 — 중성ìž� Atomic & Nuclear — Deuteron ì›�ìž� ë°� 핵 — 중양성ìž� Atomic & Nuclear — Triton ì›�ìž� ë°� 핵 — 삼중양성ìž� Atomic & Nuclear — Helion ì›�ìž� ë°� 핵 — 헬리온 Atomic & Nuclear — Alpha particle ì›�ìž� ë°� 핵 — 알파 ìž…ìž� Atomic & Nuclear — Atomic units ì›�ìž� ë°� 핵 — ì›�ìž� 단위 Atomic & Nuclear — Energy conversion relationships ì›�ìž� ë°� 핵 — ì—�너지 변환 관계 Atomic & Nuclear — X-ray units ì›�ìž� ë°� 핵 — Xì„  단위 Atomic & Nuclear — Magnetic shielding corrections ì›�ìž� ë°� 핵 — ìž�기 ì°¨í�� ë³´ì • Masses 질량 Lifetimes 수명 Molar Masses 몰 질량 Electronegativity 전기 ì�Œì„±ë�„ Ionization Energy ì�´ì˜¨í™” ì—�너지 Nominal Constants (IAU 2015) 명목 ìƒ�수 (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) 현재 최ì � 추정값 (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) ì§„ê³µì�˜ 특성 임피ë�˜ìФ (Zâ‚€) reduced Planck constant (â„�) 축소 플랑í�¬ ìƒ�수 (â„�) vacuum electric permittivity (ϵ₀) ì§„ê³µ 유전율 (ϵ₀) Newtonian constant of gravitation (G) 뉴턴 중력 ìƒ�수 (G) vacuum magnetic permeability (μ₀) ì§„ê³µ 투ìž�율 (μ₀) Planck constant (h) 플랑í�¬ ìƒ�수 (h) speed of light in vacuum (c) ì§„ê³µì—�서ì�˜ ë¹›ì�˜ ì†�ë�„ (c) standard acceleration of gravity (gâ‚™) 표준 중력 ê°€ì†�ë�„ (gâ‚™) Newtonian constant of gravitation over h-bar c â„�c로 나눈 뉴턴 중력 ìƒ�수 Planck length 플랑í�¬ 길ì�´ Planck constant in eV/Hz (h) eV/Hz 단위ì�˜ 플랑í�¬ ìƒ�수 (h) Planck mass 플랑í�¬ 질량 Planck mass energy equivalent in GeV GeV 단위ì�˜ 플랑í�¬ 질량 ì—�너지 등가 Planck temperature 플랑í�¬ 온ë�„ Planck time 플랑í�¬ 시간 reduced Planck constant in eV·s (â„�) eV·s 단위ì�˜ 축소 플랑í�¬ ìƒ�수 (â„�) reduced Planck constant times c in MeV·fm MeV·fm 단위ì�˜ 축소 플랑í�¬ ìƒ�수 곱하기 c Bohr magneton ë³´ì–´ 마그네톤 conductance quantum (Gâ‚€) 컨ë�•턴스 ì–‘ìž� (Gâ‚€) Coulomb constant (kâ‚‘) 쿨롱 ìƒ�수 (kâ‚‘) elementary charge (e) 기본 전하 (e) elementary charge over h-bar â„�로 나눈 기본 전하 conventional value of Josephson constant 조셉슨 ìƒ�수ì�˜ 관례값 Josephson constant 조셉슨 ìƒ�수 conventional value of ampere-90 암페어-90ì�˜ 관례값 conventional value of coulomb-90 쿨롱-90ì�˜ 관례값 conventional value of farad-90 패럿-90ì�˜ 관례값 conventional value of henry-90 헨리-90ì�˜ 관례값 conventional value of ohm-90 옴-90ì�˜ 관례값 conventional value of volt-90 볼트-90ì�˜ 관례값 conventional value of watt-90 와트-90ì�˜ 관례값 magnetic flux quantum (Φ₀) ìž�ì†� ì–‘ìž� (Φ₀) nuclear magneton 핵 마그네톤 inverse of conductance quantum 컨ë�•턴스 ì–‘ìž�ì�˜ 역수 conventional value of von Klitzing constant í�° í�´ë¦¬ì¹­ ìƒ�수ì�˜ 관례값 von Klitzing constant í�° í�´ë¦¬ì¹­ ìƒ�수 atomic unit of magnetic dipole moment ìž�기 ìŒ�ê·¹ìž� 모멘트ì�˜ ì›�ìž� 단위 atomic unit of magnetic flux density ìž�ì†� ë°€ë�„ì�˜ ì›�ìž� 단위 Bohr magneton in eV/T eV/T 단위ì�˜ ë³´ì–´ 마그네톤 Bohr magneton in Hz/T Hz/T 단위ì�˜ ë³´ì–´ 마그네톤 Bohr magneton in inverse meter per tesla 테슬ë�¼ë‹¹ 역미터 단위ì�˜ ë³´ì–´ 마그네톤 Bohr magneton in K/T K/T 단위ì�˜ ë³´ì–´ 마그네톤 nuclear magneton in eV/T eV/T 단위ì�˜ 핵 마그네톤 nuclear magneton in inverse meter per tesla 테슬ë�¼ë‹¹ 역미터 단위ì�˜ 핵 마그네톤 nuclear magneton in K/T K/T 단위ì�˜ 핵 마그네톤 nuclear magneton in MHz/T MHz/T 단위ì�˜ 핵 마그네톤 Bohr radius (aâ‚€) ë³´ì–´ 반지름 (aâ‚€) fine-structure constant (α) 미세 구조 ìƒ�수 (α) Hartree energy (Eâ‚•) 하트리 ì—�너지 (Eâ‚•) Hartree energy in eV eV 단위ì�˜ 하트리 ì—�너지 quantum of circulation 순환 ì–‘ìž� quantum of circulation times 2 순환 ì–‘ìž�ì�˜ 2ë°° Rydberg constant (R∞) 리드베리 ìƒ�수 (R∞) atomic mass unit-hartree relationship ì›�ìž� 질량 단위-하트리 관계 atomic mass unit-hertz relationship ì›�ìž� 질량 단위-헤르츠 관계 atomic mass unit-inverse meter relationship ì›�ìž� 질량 단위-역미터 관계 atomic mass unit-joule relationship ì›�ìž� 질량 단위-줄 관계 atomic mass unit-kelvin relationship ì›�ìž� 질량 단위-켈빈 관계 atomic mass unit-kilogram relationship ì›�ìž� 질량 단위-킬로그램 관계 atomic unit of 1st hyperpolarizability 1ì°¨ 초분극률ì�˜ ì›�ìž� 단위 atomic unit of 2nd hyperpolarizability 2ì°¨ 초분극률ì�˜ ì›�ìž� 단위 atomic unit of charge (e) 전하ì�˜ ì›�ìž� 단위 (e) atomic unit of charge density 전하 ë°€ë�„ì�˜ ì›�ìž� 단위 atomic unit of current 전류ì�˜ ì›�ìž� 단위 atomic unit of electric dipole moment 전기 ìŒ�ê·¹ìž� 모멘트ì�˜ ì›�ìž� 단위 atomic unit of electric field 전기장ì�˜ ì›�ìž� 단위 atomic unit of electric field gradient 전기장 기울기ì�˜ ì›�ìž� 단위 atomic unit of electric polarizability 전기 분극률ì�˜ ì›�ìž� 단위 atomic unit of electric potential 전기 í�¼í…�ì…œì�˜ ì›�ìž� 단위 atomic unit of electric quadrupole moment 전기 사중극ìž� 모멘트ì�˜ ì›�ìž� 단위 atomic unit of action 작용ì�˜ ì›�ìž� 단위 atomic unit of energy ì—�너지ì�˜ ì›�ìž� 단위 atomic unit of force 힘ì�˜ ì›�ìž� 단위 atomic unit of length 길ì�´ì�˜ ì›�ìž� 단위 hertz-atomic mass unit relationship 헤르츠-ì›�ìž� 질량 단위 관계 hertz-electron volt relationship 헤르츠-ì „ìž�볼트 관계 hertz-hartree relationship 헤르츠-하트리 관계 hertz-inverse meter relationship 헤르츠-역미터 관계 hertz-joule relationship 헤르츠-줄 관계 hertz-kelvin relationship 헤르츠-켈빈 관계 hertz-kilogram relationship 헤르츠-킬로그램 관계 hyperfine transition frequency of Cs-133 Cs-133ì�˜ 초미세 ì „ì�´ 주파수 inverse fine-structure constant (αâ�»Â¹) 미세 구조 ìƒ�수ì�˜ 역수 (αâ�»Â¹) inverse meter-atomic mass unit relationship 역미터-ì›�ìž� 질량 단위 관계 inverse meter-electron volt relationship 역미터-ì „ìž�볼트 관계 inverse meter-hartree relationship 역미터-하트리 관계 inverse meter-hertz relationship 역미터-헤르츠 관계 inverse meter-joule relationship 역미터-줄 관계 inverse meter-kelvin relationship 역미터-켈빈 관계 inverse meter-kilogram relationship 역미터-킬로그램 관계 joule-atomic mass unit relationship 줄-ì›�ìž� 질량 단위 관계 joule-electron volt relationship 줄-ì „ìž�볼트 관계 joule-hertz relationship 줄-헤르츠 관계 joule-hartree relationship 줄-하트리 관계 joule-inverse meter relationship 줄-역미터 관계 joule-kelvin relationship 줄-켈빈 관계 joule-kilogram relationship 줄-킬로그램 관계 kelvin-atomic mass unit relationship 켈빈-ì›�ìž� 질량 단위 관계 kelvin-electron volt relationship 켈빈-ì „ìž�볼트 관계 kelvin-hertz relationship 켈빈-헤르츠 관계 kelvin-hartree relationship 켈빈-하트리 관계 kelvin-inverse meter relationship 켈빈-역미터 관계 kelvin-joule relationship 켈빈-줄 관계 kelvin-kilogram relationship 켈빈-킬로그램 관계 kilogram-atomic mass unit relationship 킬로그램-ì›�ìž� 질량 단위 관계 kilogram-electron volt relationship 킬로그램-ì „ìž�볼트 관계 kilogram-hertz relationship 킬로그램-헤르츠 관계 kilogram-hartree relationship 킬로그램-하트리 관계 kilogram-inverse meter relationship 킬로그램-역미터 관계 kilogram-joule relationship 킬로그램-줄 관계 kilogram-kelvin relationship 킬로그램-켈빈 관계 lattice parameter of silicon (a) 규소ì�˜ 격ìž� 매개변수 (a) luminous efficacy 발광 효율 natural unit of energy ì—�너지ì�˜ ìž�ì—° 단위 natural unit of energy in MeV MeV 단위ì�˜ ì—�너지 ìž�ì—° 단위 natural unit of action (â„�) 작용ì�˜ ìž�ì—° 단위 (â„�) natural unit of action in eV·s eV·s 단위ì�˜ 작용 ìž�ì—° 단위 natural unit of length 길ì�´ì�˜ ìž�ì—° 단위 natural unit of mass 질량ì�˜ ìž�ì—° 단위 natural unit of momentum ìš´ë�™ëŸ‰ì�˜ ìž�ì—° 단위 natural unit of momentum in MeV/c MeV/c 단위ì�˜ ìš´ë�™ëŸ‰ ìž�ì—° 단위 natural unit of time 시간ì�˜ ìž�ì—° 단위 natural unit of velocity ì†�ë�„ì�˜ ìž�ì—° 단위 Rydberg constant times c in Hz Hz 단위ì�˜ 리드베리 ìƒ�수 곱하기 c Rydberg constant times hc in eV eV 단위ì�˜ 리드베리 ìƒ�수 곱하기 hc Rydberg constant times hc in J J 단위ì�˜ 리드베리 ìƒ�수 곱하기 hc Fermi coupling constant 페르미 ê²°í•© ìƒ�수 weak mixing angle 약한 혼합ê°� W to Z mass ratio W 대 Z 질량비 Thomson cross section (σₑ) 톰슨 산란 단면ì � (σₑ) electron mass (mâ‚‘) ì „ìž� 질량 (mâ‚‘) electron mass in u u 단위ì�˜ ì „ìž� 질량 electron mass energy equivalent (mₑ·c²) ì „ìž� 질량 ì—�너지 등가 (mₑ·c²) electron mass energy equivalent in MeV ì „ìž� 질량 ì—�너지 등가 단위 MeV reduced Compton wavelength 축소 콤프턴 파장 classical electron radius (râ‚‘) ê³ ì „ì � ì „ìž� 반지름 (râ‚‘) electron charge to mass quotient ì „ìž� 전하 대 질량 몫 electron-deuteron magnetic moment ratio ì „ìž�-중양성ìž� ìž�기 모멘트비 electron-deuteron mass ratio ì „ìž�-중양성ìž� 질량비 electron g factor (gâ‚‘) ì „ìž� g ì�¸ìž� (gâ‚‘) electron gyromagnetic ratio (γₑ) ì „ìž� ìž�기회전비 (γₑ) electron gyromagnetic ratio in MHz/T ì „ìž� ìž�기회전비 단위 MHz/T electron-helion mass ratio ì „ìž�-헬리온 질량비 electron magnetic moment (μₑ) ì „ìž� ìž�기 모멘트 (μₑ) electron magnetic moment anomaly (aâ‚‘) ì „ìž� ìž�기 모멘트 ì�´ìƒ� (aâ‚‘) electron magnetic moment to Bohr magneton ratio ì „ìž� ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 electron magnetic moment to nuclear magneton ratio ì „ìž� ìž�기 모멘트 대 핵 마그네톤 비 electron molar mass (Mâ‚‘) ì „ìž� 몰 질량 (Mâ‚‘) electron-muon magnetic moment ratio ì „ìž�-뮤온 ìž�기 모멘트비 electron-muon mass ratio ì „ìž�-뮤온 질량비 electron-neutron magnetic moment ratio ì „ìž�-중성ìž� ìž�기 모멘트비 electron-neutron mass ratio ì „ìž�-중성ìž� 질량비 electron-proton magnetic moment ratio ì „ìž�-양성ìž� ìž�기 모멘트비 electron-proton mass ratio ì „ìž�-양성ìž� 질량비 electron relative atomic mass (Ar(e)) ì „ìž� ìƒ�대 ì›�ìž� 질량 (Ar(e)) electron-tau mass ratio ì „ìž�-타우 질량비 electron to alpha particle mass ratio ì „ìž� 대 알파 ìž…ìž� 질량비 electron to shielded helion magnetic moment ratio ì „ìž� 대 ì°¨í��ë�œ 헬리온 ìž�기 모멘트비 electron to shielded proton magnetic moment ratio ì „ìž� 대 ì°¨í��ë�œ 양성ìž� ìž�기 모멘트비 electron-triton mass ratio ì „ìž�-삼중양성ìž� 질량비 electron volt-atomic mass unit relationship ì „ìž�볼트-ì›�ìž� 질량 단위 관계 electron volt-hartree relationship ì „ìž�볼트-하트리 관계 electron volt-hertz relationship ì „ìž�볼트-헤르츠 관계 electron volt-inverse meter relationship ì „ìž�볼트-역미터 관계 electron volt-joule relationship ì „ìž�볼트-줄 관계 electron volt-kelvin relationship ì „ìž�볼트-켈빈 관계 electron volt-kilogram relationship ì „ìž�볼트-킬로그램 관계 hartree-atomic mass unit relationship 하트리-ì›�ìž� 질량 단위 관계 hartree-electron volt relationship 하트리-ì „ìž�볼트 관계 muon Compton wavelength 뮤온 콤프턴 파장 muon-electron mass ratio 뮤온-ì „ìž� 질량비 muon g factor 뮤온 g ì�¸ìž� muon magnetic moment 뮤온 ìž�기 모멘트 muon magnetic moment anomaly 뮤온 ìž�기 모멘트 ì�´ìƒ� muon magnetic moment to Bohr magneton ratio 뮤온 ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 muon magnetic moment to nuclear magneton ratio 뮤온 ìž�기 모멘트 대 핵 마그네톤 비 muon mass 뮤온 질량 muon mass energy equivalent 뮤온 질량 ì—�너지 등가 muon mass energy equivalent in MeV 뮤온 질량 ì—�너지 등가 단위 MeV muon mass in u u 단위ì�˜ 뮤온 질량 muon molar mass 뮤온 몰 질량 muon-neutron mass ratio 뮤온-중성ìž� 질량비 muon-proton magnetic moment ratio 뮤온-양성ìž� ìž�기 모멘트비 muon-proton mass ratio 뮤온-양성ìž� 질량비 muon-tau mass ratio 뮤온-타우 질량비 reduced muon Compton wavelength 축소 뮤온 콤프턴 파장 reduced tau Compton wavelength 축소 타우 콤프턴 파장 tau Compton wavelength 타우 콤프턴 파장 tau-electron mass ratio 타우-ì „ìž� 질량비 tau mass 타우 질량 tau mass energy equivalent 타우 질량 ì—�너지 등가 tau mass in u u 단위ì�˜ 타우 질량 tau molar mass 타우 몰 질량 tau-muon mass ratio 타우-뮤온 질량비 tau-neutron mass ratio 타우-중성ìž� 질량비 tau-proton mass ratio 타우-양성ìž� 질량비 proton charge to mass quotient 양성ìž� 전하 대 질량 몫 proton Compton wavelength 양성ìž� 콤프턴 파장 proton-electron mass ratio 양성ìž�-ì „ìž� 질량비 proton g factor (gₚ) 양성ìž� g ì�¸ìž� (gₚ) proton gyromagnetic ratio (γₚ) 양성ìž� ìž�기회전비 (γₚ) proton gyromagnetic ratio in MHz/T 양성ìž� ìž�기회전비 단위 MHz/T proton magnetic moment (μₚ) 양성ìž� ìž�기 모멘트 (μₚ) proton magnetic moment to Bohr magneton ratio 양성ìž� ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 proton magnetic moment to nuclear magneton ratio 양성ìž� ìž�기 모멘트 대 핵 마그네톤 비 proton magnetic shielding correction 양성ìž� ìž�기 ì°¨í�� ë³´ì • proton mass (mₚ) 양성ìž� 질량 (mₚ) proton mass energy equivalent 양성ìž� 질량 ì—�너지 등가 proton mass energy equivalent in MeV 양성ìž� 질량 ì—�너지 등가 단위 MeV proton mass in u u 단위ì�˜ 양성ìž� 질량 proton molar mass (Mₚ) 양성ìž� 몰 질량 (Mₚ) proton-muon mass ratio 양성ìž�-뮤온 질량비 proton-neutron magnetic moment ratio 양성ìž�-중성ìž� ìž�기 모멘트비 proton-neutron mass ratio 양성ìž�-중성ìž� 질량비 proton relative atomic mass (Ar(p)) 양성ìž� ìƒ�대 ì›�ìž� 질량 (Ar(p)) proton rms charge radius 양성ìž� rms 전하 반지름 proton-tau mass ratio 양성ìž�-타우 질량비 reduced proton Compton wavelength 축소 양성ìž� 콤프턴 파장 shielded proton gyromagnetic ratio ì°¨í��ë�œ 양성ìž� ìž�기회전비 shielded proton gyromagnetic ratio in MHz/T ì°¨í��ë�œ 양성ìž� ìž�기회전비 단위 MHz/T shielded proton magnetic moment ì°¨í��ë�œ 양성ìž� ìž�기 모멘트 shielded proton magnetic moment to Bohr magneton ratio ì°¨í��ë�œ 양성ìž� ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 shielded proton magnetic moment to nuclear magneton ratio ì°¨í��ë�œ 양성ìž� ìž�기 모멘트 대 핵 마그네톤 비 neutron Compton wavelength 중성ìž� 콤프턴 파장 neutron-electron magnetic moment ratio 중성ìž�-ì „ìž� ìž�기 모멘트비 neutron-electron mass ratio 중성ìž�-ì „ìž� 질량비 neutron g factor (gâ‚™) 중성ìž� g ì�¸ìž� (gâ‚™) neutron gyromagnetic ratio (γₙ) 중성ìž� ìž�기회전비 (γₙ) neutron gyromagnetic ratio in MHz/T 중성ìž� ìž�기회전비 단위 MHz/T neutron magnetic moment (μₙ) 중성ìž� ìž�기 모멘트 (μₙ) neutron magnetic moment to Bohr magneton ratio 중성ìž� ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 neutron magnetic moment to nuclear magneton ratio 중성ìž� ìž�기 모멘트 대 핵 마그네톤 비 neutron mass (mâ‚™) 중성ìž� 질량 (mâ‚™) neutron mass energy equivalent 중성ìž� 질량 ì—�너지 등가 neutron mass energy equivalent in MeV 중성ìž� 질량 ì—�너지 등가 단위 MeV neutron mass in u u 단위ì�˜ 중성ìž� 질량 neutron molar mass (Mâ‚™) 중성ìž� 몰 질량 (Mâ‚™) neutron-muon mass ratio 중성ìž�-뮤온 질량비 neutron-proton magnetic moment ratio 중성ìž�-양성ìž� ìž�기 모멘트비 neutron-proton mass difference 중성ìž�-양성ìž� 질량 ì°¨ì�´ neutron-proton mass difference energy equivalent 중성ìž�-양성ìž� 질량 ì°¨ì�´ ì—�너지 등가 neutron-proton mass difference energy equivalent in MeV MeV 단위ì�˜ 중성ìž�-양성ìž� 질량 ì°¨ì�´ ì—�너지 등가 neutron-proton mass difference in u u 단위ì�˜ 중성ìž�-양성ìž� 질량 ì°¨ì�´ neutron-proton mass ratio 중성ìž�-양성ìž� 질량비 neutron relative atomic mass (Ar(n)) 중성ìž� ìƒ�대 ì›�ìž� 질량 (Ar(n)) neutron-tau mass ratio 중성ìž�-타우 질량비 neutron to shielded proton magnetic moment ratio 중성ìž� 대 ì°¨í��ë�œ 양성ìž� ìž�기 모멘트비 reduced neutron Compton wavelength 축소 중성ìž� 콤프턴 파장 deuteron-electron magnetic moment ratio 중양성ìž�-ì „ìž� ìž�기 모멘트비 deuteron-electron mass ratio 중양성ìž�-ì „ìž� 질량비 deuteron g factor 중양성ìž� g ì�¸ìž� deuteron magnetic moment 중양성ìž� ìž�기 모멘트 deuteron magnetic moment to Bohr magneton ratio 중양성ìž� ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 deuteron magnetic moment to nuclear magneton ratio 중양성ìž� ìž�기 모멘트 대 핵 마그네톤 비 deuteron mass 중양성ìž� 질량 deuteron mass energy equivalent 중양성ìž� 질량 ì—�너지 등가 deuteron mass energy equivalent in MeV 중양성ìž� 질량 ì—�너지 등가 단위 MeV deuteron mass in u u 단위ì�˜ 중양성ìž� 질량 deuteron molar mass 중양성ìž� 몰 질량 deuteron-neutron magnetic moment ratio 중양성ìž�-중성ìž� ìž�기 모멘트비 deuteron-proton magnetic moment ratio 중양성ìž�-양성ìž� ìž�기 모멘트비 deuteron-proton mass ratio 중양성ìž�-양성ìž� 질량비 deuteron relative atomic mass (Ar(d)) 중양성ìž� ìƒ�대 ì›�ìž� 질량 (Ar(d)) deuteron rms charge radius 중양성ìž� rms 전하 반지름 triton-electron mass ratio 삼중양성ìž�-ì „ìž� 질량비 triton g factor (gₜ) 삼중양성ìž� g ì�¸ìž� (gₜ) triton magnetic moment (μₜ) 삼중양성ìž� ìž�기 모멘트 (μₜ) triton magnetic moment to Bohr magneton ratio 삼중양성ìž� ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 triton magnetic moment to nuclear magneton ratio 삼중양성ìž� ìž�기 모멘트 대 핵 마그네톤 비 triton mass (mₜ) 삼중양성ìž� 질량 (mₜ) triton mass energy equivalent 삼중양성ìž� 질량 ì—�너지 등가 triton mass energy equivalent in MeV 삼중양성ìž� 질량 ì—�너지 등가 단위 MeV triton mass in u u 단위ì�˜ 삼중양성ìž� 질량 triton molar mass (Mₜ) 삼중양성ìž� 몰 질량 (Mₜ) triton-proton mass ratio 삼중양성ìž�-양성ìž� 질량비 triton relative atomic mass (Ar(t)) 삼중양성ìž� ìƒ�대 ì›�ìž� 질량 (Ar(t)) triton to proton magnetic moment ratio 삼중양성ìž� 대 양성ìž� ìž�기 모멘트비 helion-electron mass ratio 헬리온-ì „ìž� 질량비 helion g factor (gâ‚•) 헬리온 g ì�¸ìž� (gâ‚•) helion magnetic moment (μₕ) 헬리온 ìž�기 모멘트 (μₕ) helion magnetic moment to Bohr magneton ratio 헬리온 ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 helion magnetic moment to nuclear magneton ratio 헬리온 ìž�기 모멘트 대 핵 마그네톤 비 helion mass (mâ‚•) 헬리온 질량 (mâ‚•) helion mass energy equivalent 헬리온 질량 ì—�너지 등가 helion mass energy equivalent in MeV 헬리온 질량 ì—�너지 등가 단위 MeV helion mass in u u 단위ì�˜ 헬리온 질량 helion molar mass (Mâ‚•) 헬리온 몰 질량 (Mâ‚•) helion-proton mass ratio 헬리온-양성ìž� 질량비 helion relative atomic mass (Ar(h)) 헬리온 ìƒ�대 ì›�ìž� 질량 (Ar(h)) helion shielding shift 헬리온 ì°¨í�� ì�´ë�™ shielded helion gyromagnetic ratio ì°¨í��ë�œ 헬리온 ìž�기회전비 shielded helion gyromagnetic ratio in MHz/T ì°¨í��ë�œ 헬리온 ìž�기회전비 단위 MHz/T shielded helion magnetic moment ì°¨í��ë�œ 헬리온 ìž�기 모멘트 shielded helion magnetic moment to Bohr magneton ratio ì°¨í��ë�œ 헬리온 ìž�기 모멘트 대 ë³´ì–´ 마그네톤 비 shielded helion magnetic moment to nuclear magneton ratio ì°¨í��ë�œ 헬리온 ìž�기 모멘트 대 핵 마그네톤 비 shielded helion to proton magnetic moment ratio ì°¨í��ë�œ 헬리온 대 양성ìž� ìž�기 모멘트비 shielded helion to shielded proton magnetic moment ratio ì°¨í��ë�œ 헬리온 대 ì°¨í��ë�œ 양성ìž� ìž�기 모멘트비 alpha particle mass 알파 ìž…ìž� 질량 alpha particle mass in u u 단위ì�˜ 알파 ìž…ìž� 질량 alpha particle mass energy equivalent 알파 ìž…ìž� 질량 ì—�너지 등가 alpha particle mass energy equivalent in MeV 알파 ìž…ìž� 질량 ì—�너지 등가 단위 MeV alpha particle-electron mass ratio 알파 ìž…ìž�-ì „ìž� 질량비 alpha particle-proton mass ratio 알파 ìž…ìž�-양성ìž� 질량비 alpha particle rms charge radius 알파 ìž…ìž� rms 전하 반지름 alpha particle molar mass 알파 ìž…ìž� 몰 질량 alpha particle relative atomic mass (Ar(α)) 알파 ìž…ìž� ìƒ�대 ì›�ìž� 질량 (Ar(α)) atomic mass constant (mᵤ) ì›�ìž� 질량 ìƒ�수 (mᵤ) Avogadro constant 아보가드로 ìƒ�수 Boltzmann constant (k) 볼츠만 ìƒ�수 (k) Boltzmann constant in eV/K eV/K 단위ì�˜ 볼츠만 ìƒ�수 Boltzmann constant in Hz/K Hz/K 단위ì�˜ 볼츠만 ìƒ�수 Boltzmann constant in inverse meter per kelvin 켈빈당 역미터 단위ì�˜ 볼츠만 ìƒ�수 electron volt (eV) ì „ìž�볼트 (eV) Faraday constant (F) 패러ë�°ì�´ ìƒ�수 (F) first radiation constant (câ‚�) ì œ1 복사 ìƒ�수 (câ‚�) first radiation constant for spectral radiance 스펙트럼 복사휘ë�„ì—� 대한 ì œ1 복사 ìƒ�수 molar gas constant (R) 몰 기체 ìƒ�수 (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) 로슈미트 ìƒ�수 (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) 로슈미트 ìƒ�수 (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant 몰 플랑í�¬ ìƒ�수 second radiation constant (câ‚‚) ì œ2 복사 ìƒ�수 (câ‚‚) Stefan-Boltzmann constant (σ) 슈테íŒ�-볼츠만 ìƒ�수 (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ì�´ìƒ�ì �ì�¸ Siì�˜ 격ìž� 간격 (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent ì›�ìž� 질량 ìƒ�수 ì—�너지 등가 atomic mass constant energy equivalent in MeV MeV 단위ì�˜ ì›�ìž� 질량 ìƒ�수 ì—�너지 등가 atomic mass unit-electron volt relationship ì›�ìž� 질량 단위-ì „ìž�볼트 관계 molar mass constant (Mᵤ) 몰 질량 ìƒ�수 (Mᵤ) molar mass of carbon-12 탄소-12ì�˜ 몰 질량 molar volume of ideal gas (273.15 K, 100 kPa) ì�´ìƒ� 기체ì�˜ 몰 부피 (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ì�´ìƒ� 기체ì�˜ 몰 부피 (273.15 K, 101.325 kPa) molar volume of silicon 규소ì�˜ 몰 부피 Sackur-Tetrode constant (1 K, 100 kPa) 사쿠르-테트로드 ìƒ�수 (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) 사쿠르-테트로드 ìƒ�수 (1 K, 101.325 kPa) Wien frequency displacement law constant 빈 주파수 변위 법칙 ìƒ�수 Wien wavelength displacement law constant 빈 파장 변위 법칙 ìƒ�수 standard atmosphere (atm) 표준 대기압 (atm) standard-state pressure (p°) 표준 ìƒ�태 ì••ë ¥ (p°) Angstrom star (Ã…*) 옹스트롬 스타 (Ã…*) Copper x unit 구리 x 단위 Molybdenum x unit 몰리브ë�´ x 단위 atomic unit of magnetizability ìž�화율ì�˜ ì›�ìž� 단위 atomic unit of mass (mâ‚‘) 질량ì�˜ ì›�ìž� 단위 (mâ‚‘) atomic unit of momentum ìš´ë�™ëŸ‰ì�˜ ì›�ìž� 단위 atomic unit of permittivity 유전율ì�˜ ì›�ìž� 단위 atomic unit of time 시간ì�˜ ì›�ìž� 단위 atomic unit of velocity ì†�ë�„ì�˜ ì›�ìž� 단위 hartree-hertz relationship 하트리-헤르츠 관계 hartree-inverse meter relationship 하트리-역미터 관계 hartree-joule relationship 하트리-줄 관계 hartree-kelvin relationship 하트리-켈빈 관계 hartree-kilogram relationship 하트리-킬로그램 관계 shielding difference of d and p in HD HDì—�서 d와 pì�˜ ì°¨í�� ì°¨ì�´ shielding difference of t and p in HT HTì—�서 t와 pì�˜ ì°¨í�� ì°¨ì�´ pi (Ï€) ì›�주율 (Ï€) Euler's number (e) 오ì�¼ëŸ¬ 수 (e) golden ratio (φ) 황금비 (φ) Euler-Mascheroni constant (γ) 오ì�¼ëŸ¬-마스케로니 ìƒ�수 (γ) nominal solar radius 명목 태양 반지름 nominal solar total irradiance 명목 태양 ì´� 복사조ë�„ nominal solar luminosity 명목 태양 ê´‘ë�„ nominal solar effective temperature 명목 태양 유효 온ë�„ nominal solar mass parameter 명목 태양 질량 매개변수 nominal terrestrial equatorial radius 명목 지구 ì �ë�„ 반지름 nominal terrestrial polar radius 명목 지구 ê·¹ 반지름 nominal terrestrial mass parameter 명목 지구 질량 매개변수 nominal jovian equatorial radius 명목 목성 ì �ë�„ 반지름 nominal jovian polar radius 명목 목성 ê·¹ 반지름 nominal jovian mass parameter 명목 목성 질량 매개변수 average value of one minus the rate of TCG relative to TCB TCBì—� 대한 TCG 비율ì�„ 1ì—�서 뺀 í�‰ê· ê°’ solar mass parameter (TCB-compatible) 태양 질량 매개변수 (TCB 호환) solar mass parameter (TDB-compatible) 태양 질량 매개변수 (TDB 호환) equatorial radius of the Earth (TT-compatible) 지구ì�˜ ì �ë�„ 반지름 (TT 호환) dynamical form factor of the Earth 지구ì�˜ ë�™ì—­í•™ì � 형ìƒ� 계수 time rate of change in the dynamical form factor of the Earth 지구 ë�™ì—­í•™ì � 형ìƒ� 계수ì�˜ 시간 변화율 geocentric gravitational constant (TCB-compatible) 지구 중심 중력 ìƒ�수 (TCB 호환) geocentric gravitational constant (TT-compatible) 지구 중심 중력 ìƒ�수 (TT 호환) geocentric gravitational constant (TDB-compatible) 지구 중심 중력 ìƒ�수 (TDB 호환) potential of the geoid 지오ì�´ë“œ í�¼í…�ì…œ nominal mean angular velocity of the Earth (TT-compatible) 명목 지구 í�‰ê·  ê°�ì†�ë�„ (TT 호환) ratio mass of the Moon to the Earth 달 대 지구 질량비 ratio of the mass of the Sun to Mercury 태양 대 수성 질량비 ratio of the mass of the Sun to Venus 태양 대 금성 질량비 ratio of the mass of the Sun to Mars 태양 대 화성 질량비 ratio of the mass of the Sun to Jupiter 태양 대 목성 질량비 ratio of the mass of the Sun to Saturn 태양 대 토성 질량비 ratio of the mass of the Sun to Uranus 태양 대 천왕성 질량비 ratio of the mass of the Sun to Neptune 태양 대 해왕성 질량비 ratio of the mass of the Sun to (134340) Pluto 태양 대 (134340) 명왕성 질량비 ratio of the mass of the Sun to (136199) Eris 태양 대 (136199) ì—�리스 질량비 ratio of the mass of (1) Ceres to the Sun (1) 세레스 대 태양 질량비 ratio of the mass of (2) Pallas to the Sun (2) 팔ë�¼ìФ 대 태양 질량비 ratio of the mass of (4) Vesta to the Sun (4) 베스타 대 태양 질량비 mean obliquity of the ecliptic at J2000.0 J2000.0ì—�서ì�˜ í�‰ê·  황ë�„ 경사 Electromagnetic ì „ìž�기학 Compton wavelength 콤프턴 파장 Astronomy 천문 ConstantsWidget Domain 분야 Subdomain 하위 분야 No match found ì�¼ì¹˜í•˜ëŠ” 것 ì—†ì�Œ Name ì�´ë¦„ Value ê°’ Unit 단위 Search 검색 All 모ë‘� CustomKeypadDialog Custom Keypad 사용ìž� 지정 키패드 Rows: í–‰: Columns: ì—´: Copy preset: 프리셋 복사: Basic 기본 Scientific (wide) 공학용 (넓게) Scientific (narrow) 공학용(ì¢�게) Apply ì �ìš© Row í–‰ Column ì—´ Label ë ˆì�´ë¸” Behavior ë�™ìž‘ Text í…�스트 DiagnosticsDialog App Diagnostics 앱 진단 Copy to Clipboard í�´ë¦½ë³´ë“œì—� 복사 Editor Unit 단위 User unit 사용ìž� 단위 User function 사용ìž� 함수 Argument ì�¸ìˆ˜ Current result:<br/>%1 현재 ê²°ê³¼:<br/>%1 Selection result:<br/>%1 ì„ íƒ� ê²°ê³¼:<br/>%1 Selection result: n/a ì„ íƒ� ê²°ê³¼: n/a Selection result: %1 ì„ íƒ� ê²°ê³¼: %1 second ì´ˆ metre 미터 kilogram 킬로그램 mole 몰 radian ë�¼ë””안 steradian 스테ë�¼ë””안 degree Celsius 섭씨ë�„ cubic metre 세제곱미터 cubic millimetre 세제곱밀리미터 cubic centimetre 세제곱센티미터 cubic decimetre 세제곱ë�°ì‹œë¯¸í„° cubic kilometre 세제곱킬로미터 square millimetre 제곱밀리미터 square kilometre 제곱킬로미터 square metre 제곱미터 minute ë¶„ hour 시간 day ì�¼ astronomical unit 천문단위 degree ë�„ arcminute ë¶„ê°� arcsecond ì´ˆê°� milliarcsecond 밀리초ê°� microarcsecond 마ì�´í�¬ë¡œì´ˆê°� hectare 헥타르 litre 리터 tonne 톤 Dalton ë�Œí„´ electronvolt ì „ìž�볼트 Angstrom 옹스트롬 atmosphere 기압 atomic mass unit ì›�ìž� 질량 단위 British thermal unit ì˜�êµ­ 열량 단위 calorie 칼로리 carat ìº�럿 cup 컵 cup (Imperial) 컵 (ì˜�êµ­ì‹�) cup (Japanese) 컵 (ì�¼ë³¸ì‹�) cup (US) 컵 (미국ì‹�) degree Fahrenheit 화씨ë�„ fathom 패ë�¤ fluid ounce (Imperial) 액량 온스 (ì˜�êµ­ì‹�) fluid ounce (US) 액량 온스 (미국ì‹�) fluid dram (Imperial) 액량 드램 (ì˜�êµ­ì‹�) fluid dram (US) 액량 드램 (미국ì‹�) foot 피트 square foot 제곱피트 cubic foot 세제곱피트 gallon (Imperial) 갤런 (ì˜�êµ­ì‹�) gallon (US) 갤런 (미국ì‹�) gill (Imperial) 질 (ì˜�êµ­ì‹�) gill (US) 질 (미국ì‹�) gradian 그레ì�´ë“œ grain 그레ì�¸ gram 그램 Hartley 하틀리 Hartree energy unit 하트리 ì—�너지 단위 horsepower 마력 inch ì�¸ì¹˜ square inch 제곱ì�¸ì¹˜ cubic inch 세제곱ì�¸ì¹˜ karat ìº�럿 knot 노트 lightminute ê´‘ë¶„ lightsecond ê´‘ì´ˆ lightyear ê´‘ë…„ long ton 롱톤 mile 마ì�¼ square mile 제곱마ì�¼ cubic mile 세제곱마ì�¼ mile per hour 마ì�¼ 매시 kilometre per hour 킬로미터 매시 nautical mile 해리 ounce 온스 parsec 파섹 pint (Imperial) 파ì�¸íЏ (ì˜�êµ­ì‹�) pint (US) 파ì�¸íЏ (미국ì‹�) pound 파운드 pounds per square inch 제곱ì�¸ì¹˜ë‹¹ 파운드 quart (Imperial) 쿼트 (ì˜�êµ­ì‹�) quart (US) 쿼트 (미국ì‹�) oil barrel ì„�유 배럴 beer barrel (US) 맥주 배럴 (미국ì‹�) square yard 제곱야드 cubic yard 세제곱야드 short ton ìˆ�톤 tablespoon í�°ìˆ  tablespoon (Australian) í�°ìˆ  (호주ì‹�) tablespoon (Imperial) í�°ìˆ  (ì˜�êµ­ì‹�) tablespoon (US) í�°ìˆ  (미국ì‹�) dessert spoon 디저트스푼 teaspoon ìž‘ì�€ìˆ  teaspoon (Imperial) ìž‘ì�€ìˆ  (ì˜�êµ­ì‹�) teaspoon (US) ìž‘ì�€ìˆ  (미국ì‹�) turn í„´ revolution 회전 revolution per minute 분당 회전수 week 주 kilowatt hour 킬로와트시 millimetre of mercury 수ì�€ 밀리미터 yard 야드 Julian century 율리우스 세기 Julian year 율리우스년 sidereal year 항성년 tropical year 회귀년 Evaluator invalid expression 유효하지 않ì�€ 수ì‹� division by zero 0으로 나눔 too time consuming - computation was rejected 너무 ë§Žì�€ 시간ì�´ 소요ë�¨ - 계산ì�´ ê±°ë¶€ë�¨ dimension mismatch - quantities with different dimensions cannot be compared, added, etc. 치수 불ì�¼ì¹˜-치수가 다른 수량ì�„ 비êµ�하거나 추가 í•  수 없습니다. invalid dimension - operation might require dimensionless arguments 잘못ë�œ ì°¨ì›� - ì�´ ì—°ì‚°ì�€ 무차ì›� ì�¸ìˆ˜ë¥¼ 필요로 í•  수 있습니다 Computation aborted - encountered numerical instability 계산 중단 - 수치ì � 불안정ì�´ ë°œìƒ�했습니다 invalid dimension - function might require dimensionless arguments 잘못ë�œ ì°¨ì›� - ì�´ 함수는 무차ì›� ì�¸ìˆ˜ë¥¼ 필요로 í•  수 있습니다 error 오류 unit must not be zero 단위가 0ì�´ 아니어야 합니다. Conversion failed - dimension mismatch 변환 실패 - ì°¨ì›�ì�´ ì�¼ì¹˜í•˜ì§€ 않습니다 unknown function or variable 알려지지 않ì�€ 함수나 변수 recursion not supported 재귀는 ì§€ì›�ë�˜ì§€ 않습니다 cannot operate on a NaN NaN으로 ì—°ì‚°í•  수 ì—†ì�Œ underflow - tiny result is out of SpeedCrunch's number range ì–¸ë�”플로우 - 매우 ìž‘ì�€ 결과가 SpeedCrunchì�˜ 수 범위를 벗어납니다 overflow - huge result is out of SpeedCrunch's number range 오버플로우 - 매우 í�° 결과가 SpeedCrunchì�˜ 수 범위를 벗어납니다 overflow - logic result exceeds maximum of 256 bits 오버플로우 - 논리 결과가 256비트ì�˜ 최대값ì�„ 초과합니다 overflow - integer result exceeds maximum limit for integers 오버플로우 - 정수 결과가 정수ì�˜ 최대 한계를 초과합니다 operation is not defined for these arguments ì�´ ì�¸ìˆ˜ì—�는 ì—°ì‚°ì�´ ì •ì�˜ë�˜ì–´ 있지 않습니다 wrong number of arguments 잘못ë�œ ì�¸ìž� 개수 does not take NaN as an argument ì�¸ìž�로 NaNì�„ 쓸 수 ì—†ì�Œ result out of range 범위를 벗어난 ê²°ê³¼ undefined for argument domain ì�¸ìž� 범위ì—� 대해 ì •ì�˜ë�˜ì§€ 않ì�Œ computation too expensive 너무 오래 걸리는 계산 internal error, please report a bug ë‚´ë¶€ 오류. 버그를 보내주십시오 syntax error 구문 오류 conversion target must be a unit 변환 대ìƒ�ì�€ 단위여야 합니다 unknown unit 알 수 없는 단위 %1 is a reserved name, please choose another %1ì�€ 예약ë�œ ì�´ë¦„입니다. 다른 것ì�„ 사용하십시오 %1 is a global user definition and cannot be overridden in this session. %1ì�€ ì „ì—­ 사용ìž� ì •ì�˜ì�´ë¯€ë¡œ ì�´ 세션ì—�서 재정ì�˜í•  수 없습니다. %1 is a variable name, please choose another or delete the variable %1ì�€ (는) 변수 ì�´ë¦„입니다. 다른 변수를 ì„ íƒ�하거나 변수를 삭제하십시오 argument %1 is used more than once ì�¸ìˆ˜ %1ì�´ (ê°€) ë‘� 번 ì�´ìƒ� 사용ë�˜ì—ˆìŠµë‹ˆë‹¤ %1 is a built-in unit name, please choose another %1ì�€ 내장 단위 ì�´ë¦„입니다. 다른 ì�´ë¦„ì�„ ì„ íƒ�하세요 %1 is a user function name, please choose another or delete the function %1ì�€ 사용ìž� 기능 ì�´ë¦„ì�´ë©°, 다른 기능ì�„ ì„ íƒ�하거나 삭제하십시오. FunctionRepo max; trials; probability 최대성공횟수; 시행횟수; 성공확률 trials; probability 시행횟수; 성공확률 hits; trials; probability 성공횟수; 시행횟수; 성공확률 max; total; hits; trials 표본성공최대횟수; 모집단í�¬ê¸°; 모집단성공횟수; 표본í�¬ê¸° total; hits; trials 모집단í�¬ê¸°; 모집단성공횟수; 표본í�¬ê¸° count; total; hits; trials 표본성공횟수; 모집단í�¬ê¸°; 모집단성공횟수; 표본í�¬ê¸° dividend; divisor 피제수; 제수 x; exponent_bits; significand_bits [; exponent_bias] x; 지수 비트; 유효숫ìž� 비트 [; 지수 ë°”ì�´ì–´ìФ] base; x ë°‘; x value; modulo ê°’; 모듈로 base; exponent; modulo ë°‘; 지수; 모듈로 events; average_events 사건횟수; 사건ì�˜ 기대값 average_events 사건ì�˜ 기대값 x [; precision] x [; ì •ë°€ë�„] Absolute Value 절대값 Absolute Deviation 절대 편차 Arc Cosine ì•„í�¬ 코사ì�¸ Logical AND 298 논리 AND Area Hyperbolic Cosine ì—­ìŒ�곡선 코사ì�¸ Area Hyperbolic Sine ì—­ìŒ�곡선 사ì�¸ Area Hyperbolic Tangent ì—­ìŒ�곡선 탄젠트 Arc Sine ì•„í�¬ 사ì�¸ Arc Tangent ì•„í�¬ 탄젠트 Arc Tangent with two Arguments 2ì�¸ìˆ˜ ì•„í�¬íƒ„젠트 Average (Arithmetic Mean) í�‰ê·  (산술í�‰ê· ) Binomial Cumulative Distribution Function ì�´í•­ 누ì �ë¶„í�¬í•¨ìˆ˜ Binomial Distribution Mean ì�´í•­ë¶„í�¬ í�‰ê·  Binomial Probability Mass Function ì�´í•­ 확률질량함수 Binomial Distribution Variance ì�´í•­ë¶„í�¬ ë¶„ì‚° Cube Root 세제곱근 Complex Conjugate 복소켤레 Cosine 코사ì�¸ Hyperbolic Cosine ìŒ�곡선 코사ì�¸ Cotangent 코탄젠트 Cosecant 코시컨트 Convert Unix timestamp to Date 유닉스 타임스탬프를 날짜로 변환 Degrees of Arc 호 ê°�ë�„ Error Function 오차 함수 Complementary Error Function ìƒ�ë³´ 오차 함수 Exponential 지수 함수 Fractional Part 소수 부분 Extension of Factorials [= (x-1)!] 팩토리얼ì�˜ 확장 [= (x-1)!] Greatest Common Divisor 최대공약수 Geometric Mean 기하í�‰ê·  Gradians of arc ê·¸ë�¼ë””안 ê°�ë�„ Hypergeometric Cumulative Distribution Function 초기하 누ì �ë¶„í�¬í•¨ìˆ˜ Hypergeometric Distribution Mean 초기하분í�¬ í�‰ê·  Hypergeometric Probability Mass Function 초기하 확률질량함수 Hypergeometric Distribution Variance 초기하분í�¬ ë¶„ì‚° Integer Quotient 정수 몫 Integer Part 정수 부분 Imaginary Part 허수 부분 Decode IEEE-754 Binary Value IEEE-754 ì�´ì§„ê°’ 디코드 Encode IEEE-754 Binary Value IEEE-754 ì�´ì§„ê°’ ì�¸ì½”드 Decode 16-bit Half-Precision Value 16비트 반정밀ë�„ ê°’ 디코드 Encode 16-bit Half-Precision Value 16비트 반정밀ë�„ ê°’ ì�¸ì½”드 Decode 32-bit Single-Precision Value 32비트 단정밀ë�„ ê°’ 디코드 Encode 32-bit Single-Precision Value 32비트 단정밀ë�„ ê°’ ì�¸ì½”드 Decode 64-bit Double-Precision Value 64비트 ë°°ì •ë°€ë�„ ê°’ 디코드 Encode 64-bit Double-Precision Value 64비트 ë°°ì •ë°€ë�„ ê°’ ì�¸ì½”드 Decode 128-bit Quad-Precision Value 128비트 사중정밀ë�„ ê°’ 디코드 Encode 128-bit Quad-Precision Value 128비트 사중정밀ë�„ ê°’ ì�¸ì½”드 Binary Logarithm ì�´ì§„ 로그 Common Logarithm ìƒ�용로그 Natural Logarithm ìž�연로그 Logarithm to Arbitrary Base ìž„ì�˜ ë°‘ 로그 Mask to a bit size 비트 í�¬ê¸°ë¡œ 마스í�¬ Maximum 최대값 Median Value (50th Percentile) 중앙값 (50백분위수) Minimum 최소값 Modulo 모듈로 Euclidean Modulo 유í�´ë¦¬ë“œ 모듈로 Modular Exponentiation 모듈러 거듭제곱 Combination (Binomial Coefficient) ì¡°í•© (ì�´í•­ê³„수) Logical NOT 논리 NOT Permutation (Arrangement) 순열 Convert to Binary Representation ì�´ì§„ 표현으로 변환 Arithmetic 산술 Chemistry 화학 Complex 복소수 Combinatorics ì¡°í•©ë¡  Probability 확률 Statistics 통계 Aggregation 집계 Random 난수 Base conversion 진법 변환 Number formatting 숫ìž� 형ì‹� Integer arithmetic 정수 산술 Special functions 특수 함수 Exponential & Logarithmic 지수 ë°� 로그 Angle conversion ê°�ë�„ 변환 Trigonometry 삼ê°�법 Bitwise 비트 ì—°ì‚° Floating point ë¶€ë�™ 소수ì � Date & Time ë‚ ì§œ ë°� 시간 Linear algebra 선형대수 unix_timestamp; x hours offset to GMT unix_timestamp; GMT로부터 x시간 오프셋 yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; GMT로부터 x시간 오프셋 [digits] [ìž�릿수] max [; min] 최대 [; 최소] List Literal 목ë¡� 리터럴 Convert to Padded Binary Representation 패딩ë�œ ì�´ì§„ 표현으로 변환 Round Toward +∞ (Ceiling) +∞ 방향으로 반올림 (올림) Cosine plus Imaginary Sine 코사ì�¸ ë�”하기 허수 사ì�¸ Convert to Cis Complex Form cis 복소수 형ì‹�으로 변환 Matrix Column Count 행렬 ì—´ 개수 Population Correlation Matrix (n) 모집단 ìƒ�관행렬 (n) Sample Correlation Matrix (n-1) 표본 ìƒ�관행렬 (n-1) Count 개수 Population Covariance Matrix (n) 모집단 공분산행렬 (n) Sample Covariance Matrix (n-1) 표본 공분산행렬 (n-1) Cross Product 외ì � Convert Date to Unix timestamp 날짜를 유닉스 타임스탬프로 변환 Convert to Decimal Representation ì‹­ì§„ 표현으로 변환 Determinant 행렬ì‹� Convert to Sexagesimal Notation 육십진 표기법으로 변환 Dot Product ë‚´ì � Convert to Engineering Notation 공학 표기법으로 변환 Convert to Exponential Complex Form 지수 복소수 형ì‹�으로 변환 Round Toward −∞ (Floor) −∞ 방향으로 반올림 (내림) Flatten Matrix 행렬 펼치기 Least Common Multiple 최소공배수 Convert to Hexadecimal Representation 십육진 표현으로 변환 Convert to Padded Hexadecimal Representation 패딩ë�œ 십육진 표현으로 변환 Inverse Matrix 역행렬 Round to 16-bit Half-Precision Value 16비트 반정밀ë�„ 값으로 반올림 Round to 32-bit Single-Precision Value 32비트 단정밀ë�„ 값으로 반올림 Round to 64-bit Double-Precision Value 64비트 ë°°ì •ë°€ë�„ 값으로 반올림 Round to 128-bit Quad-Precision Value 128비트 사중정밀ë�„ 값으로 반올림 Residual from 16-bit Half-Precision Rounding 16비트 반정밀ë�„ 반올림ì�˜ 잔차 Residual from 32-bit Single-Precision Rounding 32비트 단정밀ë�„ 반올림ì�˜ 잔차 Residual from 64-bit Double-Precision Rounding 64비트 ë°°ì •ë°€ë�„ 반올림ì�˜ 잔차 Residual from 128-bit Quad-Precision Rounding 128비트 사중정밀ë�„ 반올림ì�˜ 잔차 Substance Mass 물질 질량 Molarity 몰ë†�ë�„ Molar Mass 몰 질량 Median Absolute Deviation 중앙값 절대 편차 Mean í�‰ê·  Numerical Value of Quantity 물리량ì�˜ 수치값 Random Decimal Number 무작위 소수 Random Integer Number 무작위 정수 Convert to Rational Representation 유리수 표현으로 변환 Convert to Octal Representation 팔진 표현으로 변환 Convert to Padded Octal Representation 패딩ë�œ 팔진 표현으로 변환 Vector or Matrix Norm 벡터 ë˜�는 행렬 노름 Logical OR 논리 OR   Population Count (Hamming Weight) 비트 개수 (í•´ë°� 가중치) Phase of Complex Number 복소수ì�˜ 위ìƒ� Poissonian Cumulative Distribution Function í�¬ì•„송 누ì �ë¶„í�¬í•¨ìˆ˜ Poissonian Distribution Mean í�¬ì•„송분í�¬ í�‰ê·  Poissonian Probability Mass Function í�¬ì•„송 확률질량함수 Poissonian Distribution Variance í�¬ì•„송분í�¬ ë¶„ì‚° Convert to Phasor Complex Form 페ì�´ì € 복소수 형ì‹�으로 변환 Convert to Rectangular Complex Form ì§�êµ�좌표 복소수 형ì‹�으로 변환 Round Half Away from Zero 절반ì�€ 0ì—�서 멀리 반올림 Round Half Even 절반ì�€ ì§�수로 반올림 Nth Root n제곱근 Convert to Scientific Notation 과학 표기법으로 변환 Matrix Row Count 행렬 í–‰ 개수 List or Matrix Shape 목ë¡� ë˜�는 행렬 형태 Summation í•©ì‚° Population Standard Deviation (n) 모집단 표준편차 (n) Sample Standard Deviation (n-1) 표본 표준편차 (n-1) Round Toward Zero (Truncation) 0 방향으로 반올림 (버림) Matrix Trace 행렬 대ê°�í•© Transpose Matrix 전치 행렬 Population Variance (n) 모집단 ë¶„ì‚° (n) Sample Variance (n-1) 표본 ë¶„ì‚° (n-1) Product 순서대로 곱하기 Radians ë�¼ë””안 Matrix Rank 행렬 계수 Real Part 실수 부분 Secant 시컨트 Arithmetic Shift Left 산술 왼쪽 시프트 Arithmetic Shift Right 산술 오른쪽 시프트 Signum 부호 함수 Sine 사ì�¸ Hyperbolic Sine ìŒ�곡선 사ì�¸ Square Root 제곱근 Sum 합계 Tangent 탄젠트 Convert to Trigonometric Complex Form 삼ê°� 복소수 형ì‹�으로 변환 Turns 회전 Hyperbolic Tangent ìŒ�곡선 탄젠트 Sign-extend a value 부호-ê°’ 확장 Logical XOR 논리 XOR FunctionsWidget Domain 분야 All 모ë‘� Name ì�´ë¦„ Search 검색 No match found ì�¼ì¹˜í•˜ëŠ” 것 ì—†ì�Œ Identifier ì‹�별ìž� HistoryWidget Remove All Calculations Above 위ì�˜ 모든 계산 제거 Remove This Calculation ì�´ 계산 제거 Remove All Calculations Below 아래ì�˜ 모든 계산 제거 Keypad Inverse cosine 역코사ì�¸ The last result 마지막 ê²°ê³¼ Inverse sine 역사ì�¸ Inverse tangent 역탄젠트 Evaluate expression ì‹� 계산 Division 나누기 Multiplication 곱하기 Subtraction 빼기 Addition ë�”하기 Clear expression 수ì‹� 지우기 Cosine 코사ì�¸ Backspace 백스페ì�´ìФ Scientific notation 지수 표기법 Exponential 지수 함수 Factorial 팩토리얼 Natural logarithm ìž�ì—° 로그 Left parenthesis 왼쪽 괄호 Nth root n제곱근 Argument separator ì�¸ìˆ˜ 구분ìž� Square 제곱 Common logarithm ìƒ�용로그 Modulo 나머지 Contextual percentage 문맥별 백분율 Power 거듭제곱 Right parenthesis 오른쪽 괄호 Sine 사ì�¸ Square root 제곱근 Tangent 탄젠트 Pi 파ì�´ Decimal separator 소수 구분 기호 MainWindow Radian ë�¼ë””안 Degree ê°�ë�„ Gradian ê·¸ë�¼ë””안 Binary 2진법 Octal 8진법 Hexadecimal 16진법 Sexagesimal 육십진법 Engineering decimal 공학ì � 소수ì � Scientific decimal 과학ì � 소수ì � &Import... 가져오기(&I)... &Quit 종료(&Q) Clear E&xpression 수ì‹� 지우기(&E) Clear &History 기ë¡� 지우기(&H) &Copy 복사(&C) &Paste 붙여넣기(&P) &Select Expression 수ì‹� ì„ íƒ�하기(&S) &Constants ìƒ�수(&C) &Functions 함수(&F) &History 기ë¡�(&H) &Status Bar ìƒ�태 표시줄(&S) Bitfield 비트필드 Use&r Functions 사용ìž� 함수(&R) &Degree ë�„(&D) &Radian ë�¼ë””안(&R) &Gradian ê·¸ë�¼ë””안(&G) Re&volution 회전(&V) Auto-Insert a&ns ans ìž�ë�™ 삽입(&N) Automatic &Completion ìž�ë�™ 완성(&C) &Built-in Functions 내장 함수(&B) Built-in &Variables 내장 변수(&V) User &Functions 사용ìž� 함수(&F) User Va&riables 사용ìž� 변수(&R) Open a Private Tab on Startup 시작할 때 비공개 탭 열기 Open and focus a new private tab whenever SpeedCrunch starts. SpeedCrunch를 시작할 때마다 새 비공개 탭ì�„ ì—´ê³  í�¬ì»¤ìŠ¤ë¥¼ 맞춥니다. Syntax &Highlighting 문법 강조하기(&H) Group Digits in &Input ìž…ë ¥ 숫ìž� ìž�릿수 구분(&I) Automatic Input &Adjustments ìž�ë�™ ìž…ë ¥ ì¡°ì •(&A) Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. ì—°ì‚°ìž�, 공백, 괄호, 거듭제곱ì�„ ìž�ë�™ìœ¼ë¡œ 조정하고 유효한 문ìž�ë§Œ 입력하ë�„ë¡� 제한합니다. Group input digits using the selected number format. ì„ íƒ�한 숫ìž� 형ì‹�ì—� ë”°ë�¼ ìž…ë ¥ 숫ìž�ì�˜ ìž�릿수를 구분합니다. &Blinking Cursor 커서 깜박임(&B) Blink the cursor in the expression editor. 수ì‹� 편집기ì�˜ 커서를 깜박ì�´ê²Œ 합니다. &Escape Clears Editor Escape로 편집기 지우기(&E) Clear the focused expression editor with Escape after dismissing any popup or preview. íŒ�ì—…ì�´ë‚˜ 미리 보기를 ë‹«ì�€ 다ì�Œ Escape로 í�¬ì»¤ìŠ¤ê°€ 있는 수ì‹� 편집기를 ì§€ì›�니다. Keep Expression After Evaluation 계산 후 수ì‹� 유지 Copy New Results Automatically 새 ê²°ê³¼ ìž�ë�™ 복사 &Comma 콤마(&C) &System Default 시스템 기본(&S) &Dot ì �(&D) Dot &And Comma ì � ë˜�는 콤마(&A) Toward +∞ (&ceil) +∞ ë°©í–¥ (ceil)(&C) Toward −∞ (&floor) −∞ ë°©í–¥ (floor)(&F) &Binary 2진법(&B) &Engineering 공학ì �(&E) &Hexadecimal 16진법(&H) &Octal 8진법(&O) &Scientific 과학ì �(&S) User &Manual 사용ìž� 매뉴얼(&M) Issues and &Feedback 문제 ë°� ì�˜ê²¬(&F) &Donate 기부(&D) &About SpeedCrunch SpeedCrunch ì •ë³´(&A) App Diag&nostics 앱 진단(&N) S&plit ë¶„í• (&P) Angle &Mode ê°�ë�„ 모드(&M) &Complex Form 복소수 형ì‹�(&C) New Tab 새 탭 Constants ìƒ�수 Functions 함수 History 기ë¡� User Functions 사용ìž� 함수 &Font... 글꼴(&F)... &Language... 언어(&L)... &Session 세션(&S) &Edit 편집(&E) &View 보기(&V) Se&ttings 설정(&T) &Decimal 소수ì �(&D) &Keypad 키패드(&K) Always on &Top 편집 ë�„구창 í•­ìƒ� 앞으로(&T) Disabled 사용 안 함 Small Space 1 ê¹� Medium Space 2 칸 Large Space 3 칸 &0 Digits 0 ìž�리 수(&0) &15 Digits 15 ìž�리 수(&1) &2 Digits 2 ìž�리 수(&2) &3 Digits 3 ìž�리 수(&3) &50 Digits 50 ìž�리 수(&5) &8 Digits 8 ìž�리 수(&8) &Sexagesimal 육십진법(&S) Reset All Settings... 모든 설정 초기화... &System 시스템(&S) SpeedCrunch &Theme SpeedCrunch 테마(&T) &Classic í�´ëž˜ì‹�(&C) &Modern 모ë�˜(&M) Context Help ìž…ë ¥ë�œ 함수 ë�„움ë§� &Help ë�„움ë§�(&H) Error 오류 Can't read from file %1 %1로부터 파ì�¼ì�„ ì�½ì�„ 수 ì—†ì�Œ Import Session 세션 가져오기 Close Session 세션 닫기 Angle Mode: ê°�ë�„ 모드: Notation: 표기법: Precision: ì •ë°€ë�„: Turn í„´ Revolution 회전 Fixed-point decimal ê³ ì • 소수ì � Rational 유리수 Automatic decimal ìž�ë�™ 소수ì � Automatic ìž�ë�™ User &Definitions... 사용ìž� ì •ì�˜(&D)... New &Tab 새 탭(&T) New &Private Tab 새 비공개 탭(&P) Keep 유지 Make Private... 비공개로 전환... New &Window 새 ì°½(&W) &Open... 열기(&O)... &Rename... ì�´ë¦„ 바꾸기(&R)... Clo&ne... 복제(&N)... &Close Tab 탭 닫기(&C) Reopen Clo&sed Tab ë‹«ì�€ 탭 다시 열기(&S) Open Sessions &Folder 세션 í�´ë�” 열기(&F) &Undo 실행 취소(&U) &Redo 다시 실행(&R) Cu&t 잘ë�¼ë‚´ê¸°(&T) Copy &Last Result 마지막 ê²°ê³¼ 복사(&L) &Wrap in Parentheses 괄호로 묶기(&W) Full Scr&een Mode ì „ì²´ 화면 모드(&E) &Basic 기본(&B) &Scientific (wide) 공학용(넓게)(&S) Scientific (narrow) 공학용(ì¢�게) &Custom... 사용ìž� 지정(&C)... Main &Menu 주 메뉴(&M) User &Variables 사용ìž� 변수(&V) &Left 왼쪽(&L) &Right 오른쪽(&R) &Up 위(&U) &Down 아래(&D) Close Pa&ne ì°½ 닫기(&N) User &Units 사용ìž� 단위(&U) &Turn í„´(&T) If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. 새 ì‹�ì�´ +, -, *, /로 시작하면 SpeedCrunchê°€ 앞ì—� "ans"를 삽입합니다. &Accept with Enter Enter로 수ë�½(&A) Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. 화살표 키로 먼저 ì„ íƒ�하지 않고 Enter로 현재 ìž�ë�™ 완성 제안ì�„ 수ë�½í•©ë‹ˆë‹¤. &Units 단위(&U) Show Live Result &Preview 실시간 ê²°ê³¼ 미리보기 표시(&P) Save &Window Position on Exit 종료 시 ì°½ 위치 저장(&W) Hover Highlighting 마우스 오버 ê°•ì¡° Group Integer Part Only 정수부만 그룹화 Number Format... 숫ìž� 형ì‹�... Notation && Precision... 표기법 ë°� ì •ë°€ë�„... After pressing Enter, keep the entered expression selected in the editor. Enter를 누른 후 편집기ì—�서 입력한 ì‹�ì�„ ì„ íƒ�ë�œ ìƒ�태로 유지합니다. Never 안 함 Always í•­ìƒ� Only for Single-Line Expressions 한 줄 ì‹�ë§Œ Simplify Displayed Expressions 표시ë�œ ì‹� 단순화 History Size &Limit... 기ë¡� í�¬ê¸° 제한(&L)... Remove Trailing &Zeroes ë��ìž�리 0 제거(&Z) Nearest, Half &Away (round) 가장 가까운 ê°’, 절반ì�€ 0ì—�서 멀리(&A) (round) Nearest, Half &Even (roundeven) 가장 가까운 ê°’, 절반ì�€ ì§�수(&E) (roundeven) Toward &Zero (trunc) 0 ë°©í–¥(&Z) (trunc) &Fixed-Point ê³ ì • 소수ì �(&F) &Rational 유리수(&R) &Exponential (m·sâ�»Â¹) 지수형(&E) (m·sâ�»Â¹) &Fractional (m/s) 분수형(&F) (m/s) &Rectangular (a + bi) ì§�êµ�형(&R) (a + bi) Exponential (reâ�±á¶¿) 지수형 (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) 삼ê°�형 (r(cos θ + i·sin θ)) Phasor (r∠θ) 페ì�´ì € (r∠θ) &Theme... 테마(&T)... Check for &Updates ì—…ë�°ì�´íЏ 확ì�¸(&U) Source Code 소스 코드 &Zoom 확대/축소(&Z) &Results ê²°ê³¼(&R) Unit Notation 단위 표기법 Rounding Mode 반올림 모드 &Notation 표기법(&N) &Imaginary Unit 허수 단위(&I) &Window ì°½(&W) &Editing 편집(&E) A&utocomplete ìž�ë�™ 완성(&U) Up/Down Arrow History 위/아래 화살표 기ë¡� &Appearance 모양(&A) &Menus 메뉴(&M) &Docks ë�„킹 패ë„�(&D) &Input and Results ìž…ë ¥ ë°� ê²°ê³¼(&I) &Disabled 비활성화(&D) &Disable 비활성화(&D) Close preview 미리보기 닫기 Rename... ì�´ë¦„ 바꾸기... Clone... 복제... Close Tab 탭 닫기 New Private Tab 새 비공개 탭 Open... 열기... Reopen Closed Tab ë‹«ì�€ 탭 다시 열기 Split ë¶„í•  Left 왼쪽 Right 오른쪽 Up 위 Down 아래 Clear 지우기 Delete ì‚­ì œ %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 비공개 세션: 닫으면 ë‚´ìš©ì�´ ì‚­ì œë�©ë‹ˆë‹¤. ì�¼ë°˜ 세션으로 전환하려면 세션 > 유지를 ì„ íƒ�하세요. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [비공개] Reset All Settings 모든 설정 초기화 Reset all settings to their default values? 모든 설정ì�„ 기본값으로 초기화하시겠습니까? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. 모양, 편집, ê²°ê³¼ 형ì‹� ë°� ì°½ 환경 설정ì�´ í�¬í•¨ë�©ë‹ˆë‹¤. 계산, 열린 세션 ë°� 사용ìž� ì •ì�˜ëŠ” 유지ë�©ë‹ˆë‹¤. The settings file could not be written. 설정 파ì�¼ì�„ 쓸 수 없습니다. Clear this session's calculations, unfinished expression, variables, functions, and units? ì�´ 세션ì�˜ 계산, 미완성 수ì‹�, 변수, 함수 ë°� 단위를 지우시겠습니까? Global user definitions are kept. ì „ì—­ 사용ìž� ì •ì�˜ëŠ” 유지ë�©ë‹ˆë‹¤. Make Session Private 세션ì�„ 비공개로 전환 The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. 저장ë�œ 세션 %1ì�´(ê°€) ì‚­ì œë�©ë‹ˆë‹¤. ë‚´ìš©ì�€ 비공개 세션ì—�서 열린 ìƒ�태로 유지ë�˜ë©° 해당 세션ì�„ 닫거나 SpeedCrunch를 종료하면 ì‚­ì œë�©ë‹ˆë‹¤. Make Private 비공개로 전환 Could not delete the saved session %1. 저장ë�œ 세션 %1ì�„(를) 삭제할 수 없습니다. Keep Session 세션 유지 Could not save the session. It remains private. 세션ì�„ 저장할 수 없습니다. 비공개로 유지ë�©ë‹ˆë‹¤. Clone Session 세션 복제 Could not save session file %1. 세션 파ì�¼ %1ì�„(를) 저장할 수 없습니다. Could not delete session file %1. 세션 파ì�¼ %1ì�„(를) 삭제할 수 없습니다. JSON file (*.json);;Any file (*.*) JSON 파ì�¼ (*.json);;모든 파ì�¼ (*.*) Export session as JSON JSON으로 세션 내보내기 The selected file is not valid JSON: %1 ì„ íƒ�한 파ì�¼ì�€ 올바른 JSONì�´ 아닙니다: %1 The selected file is not a SpeedCrunch session JSON file. ì„ íƒ�한 파ì�¼ì�€ SpeedCrunch 세션 JSON 파ì�¼ì�´ 아닙니다. This file uses an obsolete SpeedCrunch session format and cannot be imported. ì�´ 파ì�¼ì�€ 오래ë�œ SpeedCrunch 세션 형ì‹�ì�„ 사용하므로 가져올 수 없습니다. The selected JSON file is missing the required $schema field. ì„ íƒ�한 JSON 파ì�¼ì—� 필수 $schema 필드가 없습니다. The selected JSON file uses an unsupported JSON schema: %1 ì„ íƒ�한 JSON 파ì�¼ì�´ ì§€ì›�ë�˜ì§€ 않는 JSON 스키마를 사용합니다: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). ì„ íƒ�한 JSON 파ì�¼ì—� SpeedCrunch 세션 스키마 ì‹�별ìž�($id)ê°€ 없습니다. The selected JSON file uses an unsupported SpeedCrunch session format: %1 ì„ íƒ�한 JSON 파ì�¼ì�´ ì§€ì›�ë�˜ì§€ 않는 SpeedCrunch 세션 형ì‹�ì�„ 사용합니다: %1 The selected JSON file is missing the required session name. ì„ íƒ�한 JSON 파ì�¼ì—� 필수 세션 ì�´ë¦„ì�´ 없습니다. The selected JSON file has an empty session name. ì„ íƒ�한 JSON 파ì�¼ì�˜ 세션 ì�´ë¦„ì�´ 비어 있습니다. The selected JSON file has invalid or incomplete SpeedCrunch session data. ì„ íƒ�한 JSON 파ì�¼ì—� 잘못ë�˜ì—ˆê±°ë‚˜ 불완전한 SpeedCrunch 세션 ë�°ì�´í„°ê°€ 있습니다. Open Sessions Folder 세션 í�´ë�” 열기 Could not create the sessions folder: %1 세션 í�´ë�”를 만들 수 없습니다: %1 Could not open the sessions folder: %1 세션 í�´ë�”를 ì—´ 수 없습니다: %1 Editor and Results Font 편집기 ë°� ê²°ê³¼ 글꼴 Open Session 세션 열기 Community 커뮤니티 Rename Session 세션 ì�´ë¦„ 바꾸기 Clear Session 세션 지우기 Delete Session 세션 ì‚­ì œ Close Pane ì°½ 닫기 User Variables 사용ìž� 변수 User Units 사용ìž� 단위 Clear History 기ë¡� 지우기 Are you sure you want to clear the calculation history? 계산 기ë¡�ì�„ 지우시겠습니까? Session name: 세션 ì�´ë¦„: A session named %1 already exists. %1 ì�´ë¦„ì�˜ 세션ì�´ ì�´ë¯¸ 있습니다. Could not create session file %1. 세션 파ì�¼ %1ì�„ 만들 수 없습니다. Could not write session file %1. 세션 파ì�¼ %1ì—� 쓸 수 없습니다. Are you sure you want to delete this session? ì�´ 세션ì�„ 삭제하시겠습니까? Custom Precision 사용ìž� 지정 ì •ë°€ë�„ Fractional digits: 소수 ìž�릿수: Theme 테마 Light Themes ë°�ì�€ 테마 Dark Themes ì–´ë‘�ìš´ 테마 Preview 미리보기 Colors 색ìƒ� Select color for %1 %1 색ìƒ� ì„ íƒ� Import... 가져오기... Export... 내보내기... Import Theme 테마 가져오기 Theme file (*.json);;All files (*) 테마 파ì�¼ (*.json);;모든 파ì�¼ (*) Invalid theme file. 잘못ë�œ 테마 파ì�¼ìž…니다. Can't import theme "%1" because it conflicts with a built-in theme. 내장 테마와 ì¶©ë�Œí•˜ë¯€ë¡œ "%1" 테마를 가져올 수 없습니다. Can't find a writable theme folder. 쓸 수 있는 테마 í�´ë�”를 ì°¾ì�„ 수 없습니다. Overwrite Theme 테마 ë�®ì–´ì“°ê¸° A custom theme named "%1" already exists. Do you want to overwrite it? "%1" ì�´ë¦„ì�˜ 사용ìž� 지정 테마가 ì�´ë¯¸ 있습니다. ë�®ì–´ì“°ì‹œê² ìŠµë‹ˆê¹Œ? Can't overwrite theme file %1 테마 파ì�¼ %1ì�„ ë�®ì–´ì“¸ 수 없습니다 Can't copy theme file to %1 테마 파ì�¼ì�„ %1ì—� 복사할 수 없습니다 Export Theme 테마 내보내기 Can't export theme as "%1" because it conflicts with a built-in theme. 내장 테마와 ì¶©ë�Œí•˜ë¯€ë¡œ 테마를 "%1"로 내보낼 수 없습니다. Can't write to file %1 %1ì—� 파ì�¼ì�„ 쓸 수 ì—†ì�Œ Global User Variable ì „ì—­ 사용ìž� 변수 Global User Function ì „ì—­ 사용ìž� 함수 Global User Unit ì „ì—­ 사용ìž� 단위 User Definitions 사용ìž� ì •ì�˜ These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. ì�´ ì •ì�˜ëŠ” ì „ì—­ì �으로 ì �ìš©ë�˜ë©° 모든 세션ì—� 불러옵니다. 세션 ë‚´ì—�서는 변경할 수 없으며 세션 편집기ì�˜ ê°™ì�€ ì�´ë¦„ì�„ 가진 ì •ì�˜ë³´ë‹¤ 우선합니다. 한 줄ì—� 하나ì�˜ ì •ì�˜ë¥¼ 입력하세요. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] 예: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply ì �ìš© Validate ê²€ì¦� Test Results 테스트 ê²°ê³¼ Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 가져온 변수: %1 가져온 함수: %2 가져온 단위: %3 오류가 있는 줄 번호: %4 none ì—†ì�Œ Apply Results ì �ìš© ê²°ê³¼ User definitions saved. 사용ìž� ì •ì�˜ë¥¼ 저장했습니다. History Size Limit 기ë¡� í�¬ê¸° 제한 Maximum number of history entries for this session (0 = unlimited): ì�´ 세션ì�˜ 최대 기ë¡� 항목 수 (0 = 무제한): Text file (*.txt);;Any file (*.*) í…�스트 파ì�¼(*.txt);; 모든 파ì�¼(*.*) Could not recalculate from calculation %1: %2 계산 %1부터 다시 계산할 수 없습니다: %2 History Size Limit Reached 기ë¡� í�¬ê¸° 제한ì—� ë�„달함 This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. ì�´ 계산ì�´ 마지막 남ì�€ 기ë¡� 슬롯ì�„ 사용합니다. ì�´í›„ 계산ì�€ 기ë¡�ì—�서 가장 오래ë�œ 계산ì�„ 제거합니다. 세션 > 기ë¡� í�¬ê¸° 제한ì—�서 제한ì�„ 늘릴 수 있습니다. Editing calculation. Press Esc twice to cancel. 계산ì�„ 편집 중입니다. 취소하려면 Esc를 ë‘� 번 누르세요. Calculation Settings 계산 설정 Invalid recalculation start index 잘못ë�œ 재계산 시작 ì�¸ë�±ìФ System Default 시스템 기본값 Language 언어 Select the language: 언어 ì„ íƒ�: Custom 사용ìž� 지정 Decimal places: 소수 ìž�릿수: &Automatic ìž�ë�™(&A) &Precision ì •ë°€ë�„(&P) Plain &text ì�¼ë°˜ í…�스트(&T) Formula &Book ê³µì‹� ì±…(&B) &Export 내보내기(&E) Export session as HTML HTML로 세션 내보내기 HTML file (*.html) HTML 파ì�¼ (*.html) Export session as plain text ì�¼ë°˜ í…�스트로 세션 내보내기 ManualWindow SpeedCrunch Manual SpeedCrunch 설명서 %1 - SpeedCrunch Manual %1 - SpeedCrunch 매뉴얼 NumberFormatDialog Number Format 숫ìž� 형ì‹� <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>결과와 ìž…ë ¥ ìž�릿수 구분ì—� 사용할 숫ìž� 형ì‹�ì�„ ì„ íƒ�하세요.</b><br/><br/>참고: ìž…ë ¥ë�œ 숫ìž�ì�˜ 형ì‹�ì�´ 명확하면 ì„ íƒ�한 표시 형ì‹�ê³¼ 달ë�¼ë�„ 허용ë�©ë‹ˆë‹¤.<br/> QObject Global User Variable ì „ì—­ 사용ìž� 변수 Global User Function ì „ì—­ 사용ìž� 함수 Global User Unit ì „ì—­ 사용ìž� 단위 Backspace 백스페ì�´ìФ Clear expression ì‹� 지우기 Evaluate expression ì‹� 계산 Insert text í…�스트 삽입 Automatic decimal ìž�ë�™ 소수ì � Fixed-point decimal ê³ ì • 소수ì � Engineering decimal 공학ì � 소수ì � Scientific decimal 과학ì � 소수ì � Rational 유리수 Binary 2진법 Octal 8진법 Hexadecimal 16진법 Sexagesimal 육십진법 Update Available ì—…ë�°ì�´íЏ 사용 가능 A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> 새 버전(%1)ì�„ 사용할 수 있습니다.<br/><a href="%2">다운로드하려면 웹사ì�´íŠ¸ë¥¼ 방문하세요.</a> Check for Updates ì—…ë�°ì�´íЏ 확ì�¸ SpeedCrunch %1 is up to date. SpeedCrunch %1ì�€ 최신 버전입니다. No connectivity. Please check your internet connection and try again. ì—°ê²°í•  수 없습니다. ì�¸í„°ë„· ì—°ê²°ì�„ 확ì�¸í•œ 후 다시 시ë�„하세요. Could not verify the latest available version. 사용 가능한 최신 버전ì�„ 확ì�¸í•  수 없습니다. ResultDisplay Scroll to bottom 맨 아래로 스í�¬ë¡¤ Edit Expression ì‹� 편집 Change Settings 설정 변경 New Tab 새 탭 &Import... 가져오기(&I)... &Export 내보내기(&E) Plain &text ì�¼ë°˜ í…�스트(&T) Copy 복사 Selection ì„ íƒ� ì˜�ì—­ Select All 모ë‘� ì„ íƒ� Expression 수ì‹� Result ê²°ê³¼ Calculation 계산 Calculation as Single Line 계산ì�„ 한 줄로 Remove 제거 This Calculation ì�´ 계산 All Calculations Above 위ì�˜ 모든 계산 All Calculations Below 아래ì�˜ 모든 계산 New Private Tab 새 비공개 탭 Session 세션 Open... 열기... Clone... 복제... Rename... ì�´ë¦„ 바꾸기... Keep 유지 Make Private... 비공개로 전환... Clear 지우기 Delete ì‚­ì œ Close 닫기 Split ë¶„í•  Left 왼쪽 Right 오른쪽 Up 위 Down 아래 Close Pane ì°½ 닫기 Main Menu 주 메뉴 Cancel editing 편집 취소 Copy result ê²°ê³¼ 복사 Edit expression ì‹� 편집 Change settings 설정 변경 Remove calculation 계산 제거 ResultSlotsDialog Notation & Precision 표기법 ë°� ì •ë°€ë�„ Result Line ê²°ê³¼ 줄 Enabled 사용 Notation 표기법 Decimal Places 소수 ìž�릿수 Main Line 기본 줄 Extra Line #1 추가 줄 #1 Extra Line #2 추가 줄 #2 Extra Line #3 추가 줄 #3 Extra Line #4 추가 줄 #4 Auto ìž�ë�™ UserFunctionListWidget Name ì�´ë¦„ Value ê°’ Description 설명 Search 검색 No match found ì�¼ì¹˜í•˜ëŠ” 것 ì—†ì�Œ Insert 삽입 Edit 편집 Delete ì‚­ì œ Delete All 모ë‘� ì‚­ì œ UserUnitListWidget Name ì�´ë¦„ Value ê°’ Description 설명 Search 검색 No match found ì�¼ì¹˜í•˜ëŠ” 항목 ì—†ì�Œ Insert 삽입 Edit 편집 Delete ì‚­ì œ Delete All 모ë‘� ì‚­ì œ VariableListWidget Name ì�´ë¦„ Value ê°’ Description 설명 Search 검색 No match found ì�¼ì¹˜í•˜ëŠ” 것 ì—†ì�Œ Insert 삽입 Edit 편집 Delete ì‚­ì œ Delete All 모ë‘� ì‚­ì œ heldercorreia-speedcrunch-e7ca37f/src/resources/locale/lt.ts000066400000000000000000010572731526573132500244030ustar00rootroot00000000000000 AboutBox About SpeedCrunch Apie SpeedCrunch Core developers Pagrindiniai kÅ«rÄ—jai Original author Pradinis autorius Close Užverti Math engine Matematikos modulis Main author | Logo | Maintainer Pagrindinis autorius | Logotipas | PrižiÅ«rÄ—tojas Thanks PadÄ—kos Copyright (C) 2004-2026 The SpeedCrunch developers Autorių teisÄ—s (C) 2004-2026 SpeedCrunch kÅ«rÄ—jai This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Å i programa yra laisva programinÄ— įranga; jÅ«s galite jÄ… platinti ir/arba modifikuoti remdamiesi Free Software Foundation paskelbtomis GNU Bendrosios VieÅ¡osios Licencijos sÄ…lygomis; arba licencijos 2 versija, arba (savo nuožiÅ«ra) bet kuria vÄ—lesne versija. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Å i programa platinama, tikintis, kad ji bus naudinga, taÄ�iau BE JOKIŲ GARANTIJŲ; netgi be numanomos PARDAVIMO ar TINKAMUMO TAM TIKRAM TIKSLUI garantijos. IÅ¡samiau apie tai, žiÅ«rÄ—kite GNU Bendrojoje VieÅ¡ojoje Licencijoje. BitFieldWidget Reset bits to zero Atstatyti bitus į nulį Invert bits Invertuoti bitus Shift bits left Pastumti bitus į kairÄ™ Shift bits right Pastumti bitus į deÅ¡inÄ™ Book Index RodyklÄ— Algebra Algebra Quadratic Equation KvadratinÄ— lygtis Logarithmic Base Conversion Logaritmo pagrindo keitimas Geometry Geometrija Circle Apskritimas Sector Sektorius Sphere Sfera Cube Kubas Cone KÅ«gis Cylinder Cilindras Electronics Elektronika Ohm's Law Omo dÄ—snis Power Galia Reactance Reaktyvioji varža Resonance Rezonansas Radio Frequency Radijo dažnis Antennas Antenos Characteristic Impedance (coax) BÅ«dingoji pilnutinÄ— varža (bendraaÅ¡is kabelis) Velocity of Propagation (coax) Sklidimo greitis (bendraaÅ¡is kabelis) Standing Wave Ratio & Return Loss StovinÄ�iosios bangos koeficientas ir grįžtamieji nuostoliai Free Space Wavelength LaisvaerdvÄ—s bangos ilgis resistance varža voltage elektrinÄ— įtampa current srovÄ— power galia inductive reactance induktyvioji varža capacitive reactance talpioji varža inductance induktyvumas capacitance elektrinÄ— talpa frequency dažnis resonance frequency rezonanso dažnis area plotas perimeter perimetras (ilgis) diameter diametras (skersmuo) radius spindulys volume tÅ«ris surface area pavirÅ¡iaus plotas height aukÅ¡tis slant height sudaromoji face diagonal sienos įstrižainÄ— space diagonal erdvinÄ— įstrižainÄ— edge length briaunos ilgis arc length lanko ilgis central angle (degrees) centrinis kampas (laipsniai) input power įėjimo galia reflected power atspindÄ—toji galia transmitted power perduodamoji galia return loss grįžtamieji nuostoliai dielectric constant dielektrinÄ— skvarba outer conductor's inner diameter iÅ¡orinio konduktoriaus vidinis skersmuo inner conductor's outer diameter vidinio konduktoriaus iÅ¡orinis skersmuo speed of light Å¡viesos greitis reflection coefficient atspindžio koeficientas standing wave ratio stovinÄ�iosios bangos koeficientas normalized impedance normuotoji pilnutinÄ— varža frequency (Hz) dažnis (Hz) BookDock Formula Book Formulių knyga ConstantCompletion Search constants IeÅ¡koti konstantų No match found Nerasta atitikmens Constants Mathematics Matematika Physics (CODATA 2022) Fizika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chemija (IUPAC - CIAAW 2021) Uncategorized Nekategorizuota Universal Universalios Physicochemical Fizikocheminiai Atomic & Nuclear — General Atominiai ir branduoliniai — bendrieji Atomic & Nuclear — Electroweak Atominiai ir branduoliniai — elektrosilpnieji Atomic & Nuclear — Electron Atominiai ir branduoliniai — elektronas Atomic & Nuclear — Muon Atominiai ir branduoliniai — miuonas Atomic & Nuclear — Tau Atominiai ir branduoliniai — tau Atomic & Nuclear — Proton Atominiai ir branduoliniai — protonas Atomic & Nuclear — Neutron Atominiai ir branduoliniai — neutronas Atomic & Nuclear — Deuteron Atominiai ir branduoliniai — deuteronas Atomic & Nuclear — Triton Atominiai ir branduoliniai — tritonas Atomic & Nuclear — Helion Atominiai ir branduoliniai — helionas Atomic & Nuclear — Alpha particle Atominiai ir branduoliniai — alfa dalelÄ— Atomic & Nuclear — Atomic units Atominiai ir branduoliniai — atominiai vienetai Atomic & Nuclear — Energy conversion relationships Atominiai ir branduoliniai — energijos konvertavimo ryÅ¡iai Atomic & Nuclear — X-ray units Atominiai ir branduoliniai — rentgeno vienetai Atomic & Nuclear — Magnetic shielding corrections Atominiai ir branduoliniai — magnetinio ekranavimo pataisos Masses MasÄ—s Lifetimes Gyvavimo trukmÄ—s Molar Masses MolinÄ—s masÄ—s Electronegativity Elektroneigiamumas Ionization Energy Jonizacijos energija Nominal Constants (IAU 2015) Nominaliosios konstantos (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Dabartiniai geriausi įverÄ�iai (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) vakuumo banginÄ— varža (Zâ‚€) reduced Planck constant (â„�) redukuotoji Planko konstanta (â„�) vacuum electric permittivity (ϵ₀) vakuumo elektrinÄ— skvarba (ϵ₀) Newtonian constant of gravitation (G) Niutono gravitacijos konstanta (G) vacuum magnetic permeability (μ₀) vakuumo magnetinÄ— skvarba (μ₀) Planck constant (h) Planko konstanta (h) speed of light in vacuum (c) Å¡viesos greitis vakuume (c) standard acceleration of gravity (gâ‚™) standartinis laisvojo kritimo pagreitis (gâ‚™) Newtonian constant of gravitation over h-bar c Niutono gravitacijos konstanta per h su brÅ«kÅ¡niu c Planck length Planko ilgis Planck constant in eV/Hz (h) Planko konstanta vienetais eV/Hz (h) Planck mass Planko masÄ— Planck mass energy equivalent in GeV Planko masÄ—s energijos ekvivalentas vienetais GeV Planck temperature Planko temperatÅ«ra Planck time Planko laikas reduced Planck constant in eV·s (â„�) redukuotoji Planko konstanta vienetais eV·s (â„�) reduced Planck constant times c in MeV·fm redukuotoji Planko konstanta kart c vienetais MeV·fm Bohr magneton Boro magnetonas conductance quantum (Gâ‚€) laidumo kvantas (Gâ‚€) Coulomb constant (kâ‚‘) Kulono konstanta (kâ‚‘) elementary charge (e) elementarusis krÅ«vis (e) elementary charge over h-bar elementarusis krÅ«vis per h su brÅ«kÅ¡niu conventional value of Josephson constant sutartinÄ— vertÄ—: Josephson konstanta Josephson constant Josephson konstanta conventional value of ampere-90 sutartinÄ— ampero-90 vertÄ— conventional value of coulomb-90 sutartinÄ— kulono-90 vertÄ— conventional value of farad-90 sutartinÄ— farado-90 vertÄ— conventional value of henry-90 sutartinÄ— henrio-90 vertÄ— conventional value of ohm-90 sutartinÄ— omo-90 vertÄ— conventional value of volt-90 sutartinÄ— volto-90 vertÄ— conventional value of watt-90 sutartinÄ— vato-90 vertÄ— magnetic flux quantum (Φ₀) magnetinio srauto kvantas (Φ₀) nuclear magneton branduolinis magnetonas inverse of conductance quantum atvirkÅ¡tinÄ— vertÄ—: laidumo kvantas conventional value of von Klitzing constant sutartinÄ— vertÄ—: von Klitzingo konstanta von Klitzing constant von Klitzingo konstanta atomic unit of magnetic dipole moment atominis vienetas: magnetinio dipolio momentas atomic unit of magnetic flux density atominis vienetas: magnetinio srauto tankis Bohr magneton in eV/T Boro magnetonas vienetais eV/T Bohr magneton in Hz/T Boro magnetonas vienetais Hz/T Bohr magneton in inverse meter per tesla Boro magnetonas vienetais atvirkÅ¡tinis metras vienai teslai Bohr magneton in K/T Boro magnetonas vienetais K/T nuclear magneton in eV/T branduolinis magnetonas vienetais eV/T nuclear magneton in inverse meter per tesla branduolinis magnetonas vienetais atvirkÅ¡tinis metras vienai teslai nuclear magneton in K/T branduolinis magnetonas vienetais K/T nuclear magneton in MHz/T branduolinis magnetonas vienetais MHz/T Bohr radius (aâ‚€) Boro spindulys (aâ‚€) fine-structure constant (α) smulkiosios sandaros konstanta (α) Hartree energy (Eâ‚•) Hartrio energija (Eâ‚•) Hartree energy in eV Hartrio energija vienetais eV quantum of circulation cirkuliacijos kvantas quantum of circulation times 2 cirkuliacijos kvantas kart 2 Rydberg constant (R∞) Rydbergo konstanta (R∞) atomic mass unit-hartree relationship atominÄ—s masÄ—s vienetas-hartree ryÅ¡ys atomic mass unit-hertz relationship atominÄ—s masÄ—s vienetas-hercas ryÅ¡ys atomic mass unit-inverse meter relationship atominÄ—s masÄ—s vienetas-atvirkÅ¡tinis metras ryÅ¡ys atomic mass unit-joule relationship atominÄ—s masÄ—s vienetas-džaulis ryÅ¡ys atomic mass unit-kelvin relationship atominÄ—s masÄ—s vienetas-kelvinas ryÅ¡ys atomic mass unit-kilogram relationship atominÄ—s masÄ—s vienetas-kilogramas ryÅ¡ys atomic unit of 1st hyperpolarizability pirmojo hiperpoliarizuojamumo atominis vienetas atomic unit of 2nd hyperpolarizability antrojo hiperpoliarizuojamumo atominis vienetas atomic unit of charge (e) krÅ«vio atominis vienetas (e) atomic unit of charge density atominis vienetas: krÅ«vio tankis atomic unit of current atominis vienetas: srovÄ— atomic unit of electric dipole moment atominis vienetas: elektrinio dipolio momentas atomic unit of electric field atominis vienetas: elektrinis laukas atomic unit of electric field gradient atominis vienetas: elektrinio lauko gradientas atomic unit of electric polarizability atominis vienetas: elektrinis poliarizuojamumas atomic unit of electric potential atominis vienetas: elektrinis potencialas atomic unit of electric quadrupole moment atominis vienetas: elektrinio kvadrupolio momentas atomic unit of action atominis vienetas: veiksmas atomic unit of energy atominis vienetas: energija atomic unit of force atominis vienetas: jÄ—ga atomic unit of length atominis vienetas: ilgis hertz-atomic mass unit relationship hercas-atominÄ—s masÄ—s vienetas ryÅ¡ys hertz-electron volt relationship hercas-elektronvoltas ryÅ¡ys hertz-hartree relationship hercas-hartree ryÅ¡ys hertz-inverse meter relationship hercas-atvirkÅ¡tinis metras ryÅ¡ys hertz-joule relationship hercas-džaulis ryÅ¡ys hertz-kelvin relationship hercas-kelvinas ryÅ¡ys hertz-kilogram relationship hercas-kilogramas ryÅ¡ys hyperfine transition frequency of Cs-133 Cs-133 hipersmulkiojo perÄ—jimo dažnis inverse fine-structure constant (αâ�»Â¹) inverse smulkiosios sandaros konstanta (αâ�»Â¹) inverse meter-atomic mass unit relationship atvirkÅ¡tinis metras-atominÄ—s masÄ—s vienetas ryÅ¡ys inverse meter-electron volt relationship atvirkÅ¡tinis metras-elektronvoltas ryÅ¡ys inverse meter-hartree relationship atvirkÅ¡tinis metras-hartree ryÅ¡ys inverse meter-hertz relationship atvirkÅ¡tinis metras-hercas ryÅ¡ys inverse meter-joule relationship atvirkÅ¡tinis metras-džaulis ryÅ¡ys inverse meter-kelvin relationship atvirkÅ¡tinis metras-kelvinas ryÅ¡ys inverse meter-kilogram relationship atvirkÅ¡tinis metras-kilogramas ryÅ¡ys joule-atomic mass unit relationship džaulis-atominÄ—s masÄ—s vienetas ryÅ¡ys joule-electron volt relationship džaulis-elektronvoltas ryÅ¡ys joule-hertz relationship džaulis-hercas ryÅ¡ys joule-hartree relationship džaulis-hartree ryÅ¡ys joule-inverse meter relationship džaulis-atvirkÅ¡tinis metras ryÅ¡ys joule-kelvin relationship džaulis-kelvinas ryÅ¡ys joule-kilogram relationship džaulis-kilogramas ryÅ¡ys kelvin-atomic mass unit relationship kelvinas-atominÄ—s masÄ—s vienetas ryÅ¡ys kelvin-electron volt relationship kelvinas-elektronvoltas ryÅ¡ys kelvin-hertz relationship kelvinas-hercas ryÅ¡ys kelvin-hartree relationship kelvinas-hartree ryÅ¡ys kelvin-inverse meter relationship kelvinas-atvirkÅ¡tinis metras ryÅ¡ys kelvin-joule relationship kelvinas-džaulis ryÅ¡ys kelvin-kilogram relationship kelvinas-kilogramas ryÅ¡ys kilogram-atomic mass unit relationship kilogramas-atominÄ—s masÄ—s vienetas ryÅ¡ys kilogram-electron volt relationship kilogramas-elektronvoltas ryÅ¡ys kilogram-hertz relationship kilogramas-hercas ryÅ¡ys kilogram-hartree relationship kilogramas-hartree ryÅ¡ys kilogram-inverse meter relationship kilogramas-atvirkÅ¡tinis metras ryÅ¡ys kilogram-joule relationship kilogramas-džaulis ryÅ¡ys kilogram-kelvin relationship kilogramas-kelvinas ryÅ¡ys lattice parameter of silicon (a) silicio gardelÄ—s parametras (a) luminous efficacy Å¡viesinis efektyvumas natural unit of energy natÅ«ralusis vienetas: energija natural unit of energy in MeV natÅ«ralusis vienetas: energija vienetais MeV natural unit of action (â„�) natÅ«ralusis vienetas: veiksmas (â„�) natural unit of action in eV·s natÅ«ralusis vienetas: veiksmas vienetais eV·s natural unit of length natÅ«ralusis vienetas: ilgis natural unit of mass natÅ«ralusis masÄ—s vienetas natural unit of momentum natÅ«ralusis vienetas: judesio kiekis natural unit of momentum in MeV/c natÅ«ralusis vienetas: judesio kiekis vienetais MeV/c natural unit of time natÅ«ralusis laiko vienetas natural unit of velocity natÅ«ralusis vienetas: greitis Rydberg constant times c in Hz Rydbergo konstanta kart c vienetais Hz Rydberg constant times hc in eV Rydbergo konstanta kart hc vienetais eV Rydberg constant times hc in J Rydbergo konstanta kart hc vienetais J Fermi coupling constant Fermio sÄ…veikos konstanta weak mixing angle silpnojo maiÅ¡ymosi kampas W to Z mass ratio W ir Z masių santykis Thomson cross section (σₑ) Tomsono skerspjÅ«vis (σₑ) electron mass (mâ‚‘) elektrono masÄ— (mâ‚‘) electron mass in u elektrono masÄ— vienetais u electron mass energy equivalent (mₑ·c²) elektrono masÄ—s energijos ekvivalentas (mₑ·c²) electron mass energy equivalent in MeV elektrono masÄ—s energijos ekvivalentas vienetais MeV reduced Compton wavelength redukuotasis Compton waveilgis classical electron radius (râ‚‘) classical elektronas radius (râ‚‘) electron charge to mass quotient elektrono krÅ«vio ir masÄ—s santykis electron-deuteron magnetic moment ratio elektronas-deuteronas magnetinių momentų santykis electron-deuteron mass ratio elektronas-deuteronas masių santykis electron g factor (gâ‚‘) elektronas g faktorius (gâ‚‘) electron gyromagnetic ratio (γₑ) elektronas giromagnetinis santykis (γₑ) electron gyromagnetic ratio in MHz/T elektronas giromagnetinis santykis vienetais MHz/T electron-helion mass ratio elektronas-helionas masių santykis electron magnetic moment (μₑ) elektronas magnetinis momentas (μₑ) electron magnetic moment anomaly (aâ‚‘) elektronas magnetinis momentas anomaly (aâ‚‘) electron magnetic moment to Bohr magneton ratio elektrono magnetinio momento ir Boro magnetono santykis electron magnetic moment to nuclear magneton ratio elektrono magnetinio momento ir branduolinio magnetono santykis electron molar mass (Mâ‚‘) elektronas molinÄ— masÄ— (Mâ‚‘) electron-muon magnetic moment ratio elektronas-miuonas magnetinių momentų santykis electron-muon mass ratio elektronas-miuonas masių santykis electron-neutron magnetic moment ratio elektronas-neutronas magnetinių momentų santykis electron-neutron mass ratio elektronas-neutronas masių santykis electron-proton magnetic moment ratio elektronas-protonas magnetinių momentų santykis electron-proton mass ratio elektronas-protonas masių santykis electron relative atomic mass (Ar(e)) elektronas santykinÄ— atominÄ— masÄ— (Ar(e)) electron-tau mass ratio elektronas-tau masių santykis electron to alpha particle mass ratio elektrono ir alfa dalelÄ—s masių santykis electron to shielded helion magnetic moment ratio elektrono ir ekranuoto heliono magnetinių momentų santykis electron to shielded proton magnetic moment ratio elektrono ir ekranuoto protono magnetinių momentų santykis electron-triton mass ratio elektronas-tritonas masių santykis electron volt-atomic mass unit relationship elektronvoltas-atominÄ—s masÄ—s vienetas ryÅ¡ys electron volt-hartree relationship elektronvoltas-hartree ryÅ¡ys electron volt-hertz relationship elektronvoltas-hercas ryÅ¡ys electron volt-inverse meter relationship elektronvoltas-atvirkÅ¡tinis metras ryÅ¡ys electron volt-joule relationship elektronvoltas-džaulis ryÅ¡ys electron volt-kelvin relationship elektronvoltas-kelvinas ryÅ¡ys electron volt-kilogram relationship elektronvoltas-kilogramas ryÅ¡ys hartree-atomic mass unit relationship hartree-atominÄ—s masÄ—s vienetas ryÅ¡ys hartree-electron volt relationship hartree-elektronvoltas ryÅ¡ys muon Compton wavelength miuonas Compton waveilgis muon-electron mass ratio miuonas-elektronas masių santykis muon g factor miuonas g faktorius muon magnetic moment miuonas magnetinis momentas muon magnetic moment anomaly miuonas magnetinis momentas anomaly muon magnetic moment to Bohr magneton ratio miuono magnetinio momento ir Boro magnetono santykis muon magnetic moment to nuclear magneton ratio miuono magnetinio momento ir branduolinio magnetono santykis muon mass miuono masÄ— muon mass energy equivalent miuono masÄ—s energijos ekvivalentas muon mass energy equivalent in MeV miuono masÄ—s energijos ekvivalentas vienetais MeV muon mass in u miuono masÄ— vienetais u muon molar mass miuonas molinÄ— masÄ— muon-neutron mass ratio miuonas-neutronas masių santykis muon-proton magnetic moment ratio miuonas-protonas magnetinių momentų santykis muon-proton mass ratio miuonas-protonas masių santykis muon-tau mass ratio miuonas-tau masių santykis reduced muon Compton wavelength redukuotasis miuonas Compton waveilgis reduced tau Compton wavelength redukuotasis tau Compton waveilgis tau Compton wavelength tau Compton waveilgis tau-electron mass ratio tau-elektronas masių santykis tau mass tau dalelÄ—s masÄ— tau mass energy equivalent tau dalelÄ—s masÄ—s energijos ekvivalentas tau mass in u tau dalelÄ—s masÄ— vienetais u tau molar mass tau molinÄ— masÄ— tau-muon mass ratio tau-miuonas masių santykis tau-neutron mass ratio tau-neutronas masių santykis tau-proton mass ratio tau-protonas masių santykis proton charge to mass quotient protono krÅ«vio ir masÄ—s santykis proton Compton wavelength protonas Compton waveilgis proton-electron mass ratio protonas-elektronas masių santykis proton g factor (gₚ) protonas g faktorius (gₚ) proton gyromagnetic ratio (γₚ) protonas giromagnetinis santykis (γₚ) proton gyromagnetic ratio in MHz/T protonas giromagnetinis santykis vienetais MHz/T proton magnetic moment (μₚ) protonas magnetinis momentas (μₚ) proton magnetic moment to Bohr magneton ratio protono magnetinio momento ir Boro magnetono santykis proton magnetic moment to nuclear magneton ratio protono magnetinio momento ir branduolinio magnetono santykis proton magnetic shielding correction protonas magnetic ekranavimas correction proton mass (mₚ) protono masÄ— (mₚ) proton mass energy equivalent protono masÄ—s energijos ekvivalentas proton mass energy equivalent in MeV protono masÄ—s energijos ekvivalentas vienetais MeV proton mass in u protono masÄ— vienetais u proton molar mass (Mₚ) protonas molinÄ— masÄ— (Mₚ) proton-muon mass ratio protonas-miuonas masių santykis proton-neutron magnetic moment ratio protonas-neutronas magnetinių momentų santykis proton-neutron mass ratio protonas-neutronas masių santykis proton relative atomic mass (Ar(p)) protonas santykinÄ— atominÄ— masÄ— (Ar(p)) proton rms charge radius protonas vidutinis kvadratinis krÅ«vio spindulys proton-tau mass ratio protonas-tau masių santykis reduced proton Compton wavelength redukuotasis protonas Compton waveilgis shielded proton gyromagnetic ratio ekranuotas protonas giromagnetinis santykis shielded proton gyromagnetic ratio in MHz/T ekranuotas protonas giromagnetinis santykis vienetais MHz/T shielded proton magnetic moment ekranuotas protonas magnetinis momentas shielded proton magnetic moment to Bohr magneton ratio ekranuoto protono magnetinio momento ir Boro magnetono santykis shielded proton magnetic moment to nuclear magneton ratio ekranuoto protono magnetinio momento ir branduolinio magnetono santykis neutron Compton wavelength neutronas Compton waveilgis neutron-electron magnetic moment ratio neutronas-elektronas magnetinių momentų santykis neutron-electron mass ratio neutronas-elektronas masių santykis neutron g factor (gâ‚™) neutronas g faktorius (gâ‚™) neutron gyromagnetic ratio (γₙ) neutronas giromagnetinis santykis (γₙ) neutron gyromagnetic ratio in MHz/T neutronas giromagnetinis santykis vienetais MHz/T neutron magnetic moment (μₙ) neutronas magnetinis momentas (μₙ) neutron magnetic moment to Bohr magneton ratio neutrono magnetinio momento ir Boro magnetono santykis neutron magnetic moment to nuclear magneton ratio neutrono magnetinio momento ir branduolinio magnetono santykis neutron mass (mâ‚™) neutrono masÄ— (mâ‚™) neutron mass energy equivalent neutrono masÄ—s energijos ekvivalentas neutron mass energy equivalent in MeV neutrono masÄ—s energijos ekvivalentas vienetais MeV neutron mass in u neutrono masÄ— vienetais u neutron molar mass (Mâ‚™) neutronas molinÄ— masÄ— (Mâ‚™) neutron-muon mass ratio neutronas-miuonas masių santykis neutron-proton magnetic moment ratio neutronas-protonas magnetinių momentų santykis neutron-proton mass difference neutronas-protonas masių skirtumas neutron-proton mass difference energy equivalent neutrono ir protono masių skirtumo energijos ekvivalentas neutron-proton mass difference energy equivalent in MeV neutrono ir protono masių skirtumo energijos ekvivalentas vienetais MeV neutron-proton mass difference in u neutronas-protonas masių skirtumas vienetais u neutron-proton mass ratio neutronas-protonas masių santykis neutron relative atomic mass (Ar(n)) neutronas santykinÄ— atominÄ— masÄ— (Ar(n)) neutron-tau mass ratio neutronas-tau masių santykis neutron to shielded proton magnetic moment ratio neutrono ir ekranuoto protono magnetinių momentų santykis reduced neutron Compton wavelength redukuotasis neutronas Compton waveilgis deuteron-electron magnetic moment ratio deuteronas-elektronas magnetinių momentų santykis deuteron-electron mass ratio deuteronas-elektronas masių santykis deuteron g factor deuteronas g faktorius deuteron magnetic moment deuteronas magnetinis momentas deuteron magnetic moment to Bohr magneton ratio deuterono magnetinio momento ir Boro magnetono santykis deuteron magnetic moment to nuclear magneton ratio deuterono magnetinio momento ir branduolinio magnetono santykis deuteron mass deuterono masÄ— deuteron mass energy equivalent deuterono masÄ—s energijos ekvivalentas deuteron mass energy equivalent in MeV deuterono masÄ—s energijos ekvivalentas vienetais MeV deuteron mass in u deuterono masÄ— vienetais u deuteron molar mass deuteronas molinÄ— masÄ— deuteron-neutron magnetic moment ratio deuteronas-neutronas magnetinių momentų santykis deuteron-proton magnetic moment ratio deuteronas-protonas magnetinių momentų santykis deuteron-proton mass ratio deuteronas-protonas masių santykis deuteron relative atomic mass (Ar(d)) deuteronas santykinÄ— atominÄ— masÄ— (Ar(d)) deuteron rms charge radius deuteronas vidutinis kvadratinis krÅ«vio spindulys triton-electron mass ratio tritonas-elektronas masių santykis triton g factor (gₜ) tritonas g faktorius (gₜ) triton magnetic moment (μₜ) tritonas magnetinis momentas (μₜ) triton magnetic moment to Bohr magneton ratio tritono magnetinio momento ir Boro magnetono santykis triton magnetic moment to nuclear magneton ratio tritono magnetinio momento ir branduolinio magnetono santykis triton mass (mₜ) tritono masÄ— (mₜ) triton mass energy equivalent tritono masÄ—s energijos ekvivalentas triton mass energy equivalent in MeV tritono masÄ—s energijos ekvivalentas vienetais MeV triton mass in u tritono masÄ— vienetais u triton molar mass (Mₜ) tritonas molinÄ— masÄ— (Mₜ) triton-proton mass ratio tritonas-protonas masių santykis triton relative atomic mass (Ar(t)) tritonas santykinÄ— atominÄ— masÄ— (Ar(t)) triton to proton magnetic moment ratio tritono ir protono magnetinių momentų santykis helion-electron mass ratio helionas-elektronas masių santykis helion g factor (gâ‚•) helionas g faktorius (gâ‚•) helion magnetic moment (μₕ) helionas magnetinis momentas (μₕ) helion magnetic moment to Bohr magneton ratio heliono magnetinio momento ir Boro magnetono santykis helion magnetic moment to nuclear magneton ratio heliono magnetinio momento ir branduolinio magnetono santykis helion mass (mâ‚•) heliono masÄ— (mâ‚•) helion mass energy equivalent heliono masÄ—s energijos ekvivalentas helion mass energy equivalent in MeV heliono masÄ—s energijos ekvivalentas vienetais MeV helion mass in u heliono masÄ— vienetais u helion molar mass (Mâ‚•) helionas molinÄ— masÄ— (Mâ‚•) helion-proton mass ratio helionas-protonas masių santykis helion relative atomic mass (Ar(h)) helionas santykinÄ— atominÄ— masÄ— (Ar(h)) helion shielding shift helionas ekranavimas shift shielded helion gyromagnetic ratio ekranuotas helionas giromagnetinis santykis shielded helion gyromagnetic ratio in MHz/T ekranuotas helionas giromagnetinis santykis vienetais MHz/T shielded helion magnetic moment ekranuotas helionas magnetinis momentas shielded helion magnetic moment to Bohr magneton ratio ekranuoto heliono magnetinio momento ir Boro magnetono santykis shielded helion magnetic moment to nuclear magneton ratio ekranuoto heliono magnetinio momento ir branduolinio magnetono santykis shielded helion to proton magnetic moment ratio ekranuoto heliono ir protono magnetinių momentų santykis shielded helion to shielded proton magnetic moment ratio ekranuoto heliono ir ekranuoto protono magnetinių momentų santykis alpha particle mass alfa dalelÄ—s masÄ— alpha particle mass in u alfa dalelÄ—s masÄ— vienetais u alpha particle mass energy equivalent alfa dalelÄ—s masÄ—s energijos ekvivalentas alpha particle mass energy equivalent in MeV alfa dalelÄ—s masÄ—s energijos ekvivalentas vienetais MeV alpha particle-electron mass ratio alfa dalelÄ—-elektronas masių santykis alpha particle-proton mass ratio alfa dalelÄ—-protonas masių santykis alpha particle rms charge radius alfa dalelÄ— vidutinis kvadratinis krÅ«vio spindulys alpha particle molar mass alfa dalelÄ— molinÄ— masÄ— alpha particle relative atomic mass (Ar(α)) alfa dalelÄ— santykinÄ— atominÄ— masÄ— (Ar(α)) atomic mass constant (mᵤ) atominÄ—s masÄ—s konstanta (mᵤ) Avogadro constant Avogadro konstanta Boltzmann constant (k) Bolcmano konstanta (k) Boltzmann constant in eV/K Bolcmano konstanta vienetais eV/K Boltzmann constant in Hz/K Bolcmano konstanta vienetais Hz/K Boltzmann constant in inverse meter per kelvin Bolcmano konstanta vienetais atvirkÅ¡tinis metras kelvinui electron volt (eV) elektronvoltas (eV) Faraday constant (F) FaradÄ—jaus konstanta (F) first radiation constant (câ‚�) first spinduliuotÄ—s konstanta (câ‚�) first radiation constant for spectral radiance pirmoji spinduliuotÄ—s konstanta spektriniam spindžiui molar gas constant (R) molinÄ— dujų konstanta (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) LoÅ¡midto konstanta (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) LoÅ¡midto konstanta (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molinÄ— Planko konstanta second radiation constant (câ‚‚) second spinduliuotÄ—s konstanta (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Bolcmano konstanta (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) idealaus Si gardelÄ—s tarpas (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atominÄ—s masÄ—s konstantos energijos ekvivalentas atomic mass constant energy equivalent in MeV atominÄ—s masÄ—s konstantos energijos ekvivalentas vienetais MeV atomic mass unit-electron volt relationship atominÄ—s masÄ—s vienetas-elektronvoltas ryÅ¡ys molar mass constant (Mᵤ) molinÄ— masÄ— konstanta (Mᵤ) molar mass of carbon-12 anglies-12 molinÄ— masÄ— molar volume of ideal gas (273.15 K, 100 kPa) idealiųjų dujų molinis tÅ«ris (273,15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) idealiųjų dujų molinis tÅ«ris (273,15 K, 101,325 kPa) molar volume of silicon silicio molinis tÅ«ris Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode konstanta (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode konstanta (1 K, 101.325 kPa) Wien frequency displacement law constant Wien frequency displacement law konstanta Wien wavelength displacement law constant Wien waveilgis displacement law konstanta standard atmosphere (atm) standartinÄ— atmosfera (atm) standard-state pressure (p°) standartinÄ—s bÅ«senos slÄ—gis (p°) Angstrom star (Ã…*) Angstremo žvaigždutÄ— (Ã…*) Copper x unit vario x vienetas Molybdenum x unit molibdeno x vienetas atomic unit of magnetizability atominis vienetas: magnetizuojamumas atomic unit of mass (mâ‚‘) masÄ—s atominis vienetas (mâ‚‘) atomic unit of momentum atominis vienetas: judesio kiekis atomic unit of permittivity atominis vienetas: skvarba atomic unit of time laiko atominis vienetas atomic unit of velocity atominis vienetas: greitis hartree-hertz relationship hartree-hercas ryÅ¡ys hartree-inverse meter relationship hartree-atvirkÅ¡tinis metras ryÅ¡ys hartree-joule relationship hartree-džaulis ryÅ¡ys hartree-kelvin relationship hartree-kelvinas ryÅ¡ys hartree-kilogram relationship hartree-kilogramas ryÅ¡ys shielding difference of d and p in HD d ir p ekranavimo skirtumas HD shielding difference of t and p in HT t ir p ekranavimo skirtumas HT pi (Ï€) pi (Ï€) Euler's number (e) Eulerio skaiÄ�ius (e) golden ratio (φ) aukso pjÅ«vis (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni konstanta (γ) nominal solar radius nominalusis SaulÄ—s radius nominal solar total irradiance nominalusis SaulÄ—s total irradiance nominal solar luminosity nominalusis SaulÄ—s luminosity nominal solar effective temperature nominalusis SaulÄ—s effective temperature nominal solar mass parameter nominalusis SaulÄ—s masÄ—s parametras nominal terrestrial equatorial radius nominalusis ŽemÄ—s pusiaujo spindulys nominal terrestrial polar radius nominalusis ŽemÄ—s aÅ¡igalinis spindulys nominal terrestrial mass parameter nominalusis ŽemÄ—s masÄ—s parametras nominal jovian equatorial radius nominalusis Jupiterio pusiaujo spindulys nominal jovian polar radius nominalusis Jupiterio aÅ¡igalinis spindulys nominal jovian mass parameter nominalusis Jupiterio masÄ—s parametras average value of one minus the rate of TCG relative to TCB vidutinÄ— vieneto minus TCG spartos TCB atžvilgiu reikÅ¡mÄ— solar mass parameter (TCB-compatible) solar masÄ—s parametras (TCB-compatible) solar mass parameter (TDB-compatible) solar masÄ—s parametras (TDB-compatible) equatorial radius of the Earth (TT-compatible) ŽemÄ—s pusiaujo spindulys (suderinamas su TT) dynamical form factor of the Earth ŽemÄ—s dinaminis formos faktorius time rate of change in the dynamical form factor of the Earth ŽemÄ—s dinaminio formos faktoriaus kitimo laike sparta geocentric gravitational constant (TCB-compatible) geocentric gravitational konstanta (TCB-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational konstanta (TT-compatible) geocentric gravitational constant (TDB-compatible) geocentric gravitational konstanta (TDB-compatible) potential of the geoid geoido potencialas nominal mean angular velocity of the Earth (TT-compatible) nominalusis vidutinis ŽemÄ—s kampinis greitis (suderinamas su TT) ratio mass of the Moon to the Earth MÄ—nulio ir ŽemÄ—s masių santykis ratio of the mass of the Sun to Mercury SaulÄ—s ir Merkurijaus masių santykis ratio of the mass of the Sun to Venus SaulÄ—s ir Veneros masių santykis ratio of the mass of the Sun to Mars SaulÄ—s ir Marso masių santykis ratio of the mass of the Sun to Jupiter SaulÄ—s ir Jupiterio masių santykis ratio of the mass of the Sun to Saturn SaulÄ—s ir Saturno masių santykis ratio of the mass of the Sun to Uranus SaulÄ—s ir Urano masių santykis ratio of the mass of the Sun to Neptune SaulÄ—s ir NeptÅ«no masių santykis ratio of the mass of the Sun to (134340) Pluto SaulÄ—s ir (134340) Plutono masių santykis ratio of the mass of the Sun to (136199) Eris SaulÄ—s ir (136199) EridÄ—s masių santykis ratio of the mass of (1) Ceres to the Sun (1) Cereros ir SaulÄ—s masių santykis ratio of the mass of (2) Pallas to the Sun (2) PaladÄ—s ir SaulÄ—s masių santykis ratio of the mass of (4) Vesta to the Sun (4) Vestos ir SaulÄ—s masių santykis mean obliquity of the ecliptic at J2000.0 vidutinis ekliptikos posvyris at J2000.0 Electromagnetic ElektromagnetinÄ—s Compton wavelength Komptono bangos ilgis Astronomy Astronomija ConstantsWidget Domain Sritis Subdomain Posritis No match found Nerasta atitikmens Name Pavadinimas Value ReikÅ¡mÄ— Unit Vienetas Search PaieÅ¡ka All Visos CustomKeypadDialog Custom Keypad Pasirinktinis klaviatÅ«ros skydelis Rows: EilutÄ—s: Columns: Stulpeliai: Copy preset: Kopijuoti ruoÅ¡inį: Basic Pagrindinis Scientific (wide) Mokslinis (platus) Scientific (narrow) Mokslinis (siauras) Apply Taikyti Row EilutÄ— Column Stulpelis Label EtiketÄ— Behavior Elgsena Text Tekstas DiagnosticsDialog App Diagnostics Programos diagnostika Copy to Clipboard Kopijuoti į iÅ¡karpinÄ™ Editor Unit Vienetas User unit Naudotojo vienetas User function Naudotojo funkcija Argument Argumentas Current result:<br/>%1 Dabartinis rezultatas:<br/>%1 Selection result:<br/>%1 PažymÄ—jimo rezultatas:<br/>%1 Selection result: n/a ŽymÄ—jimo rezultatas: n/d Selection result: %1 PažymÄ—jimo rezultatas: %1 second sekundÄ— metre metras kilogram kilogramas mole molis radian radianas steradian steradianas degree Celsius Celsijaus laipsnis cubic metre kubinis metras cubic millimetre kubinis milimetras cubic centimetre kubinis centimetras cubic decimetre kubinis decimetras cubic kilometre kubinis kilometras square millimetre kvadratinis milimetras square kilometre kvadratinis kilometras square metre kvadratinis metras minute minutÄ— hour valanda day diena astronomical unit astronominis vienetas degree laipsnis arcminute kampinÄ— minutÄ— arcsecond kampinÄ— sekundÄ— milliarcsecond kampinÄ— milisekundÄ— microarcsecond kampinÄ— mikrosekundÄ— hectare hektaras litre litras tonne tona Dalton daltonas electronvolt elektronvoltas Angstrom angstromas atmosphere atmosfera atomic mass unit atominÄ—s masÄ—s vienetas British thermal unit britų Å¡iluminis vienetas calorie kalorija carat karatas cup puodelis cup (Imperial) puodelis (imperinis) cup (Japanese) puodelis (japoniÅ¡kas) cup (US) puodelis (JAV) degree Fahrenheit Farenheito laipsnis fathom fatomas fluid ounce (Imperial) skysÄ�io uncija (imperinÄ—) fluid ounce (US) skysÄ�io uncija (JAV) fluid dram (Imperial) skysÄ�io drachma (imperinÄ—) fluid dram (US) skysÄ�io drachma (JAV) foot pÄ—da square foot kvadratinÄ— pÄ—da cubic foot kubinÄ— pÄ—da gallon (Imperial) galonas (imperinis) gallon (US) galonas (JAV) gill (Imperial) gilis (imperinis) gill (US) gilis (JAV) gradian gradas grain granas gram gramas Hartley hartlis Hartree energy unit Hartrio energijos vienetas horsepower arklio galia inch colis square inch kvadratinis colis cubic inch kubinis colis karat karatas knot mazgas lightminute Å¡viesos minutÄ— lightsecond Å¡viesos sekundÄ— lightyear Å¡viesmetis long ton ilgoji tona mile mylia square mile kvadratinÄ— mylia cubic mile kubinÄ— mylia mile per hour mylia per valandÄ… kilometre per hour kilometras per valandÄ… nautical mile jÅ«rmylÄ— ounce uncija parsec parsekas pint (Imperial) pinta (imperinÄ—) pint (US) pinta (JAV) pound svaras pounds per square inch svarai kvadratiniam coliui quart (Imperial) kvorta (imperinÄ—) quart (US) kvorta (JAV) oil barrel naftos barelis beer barrel (US) alaus barelis (JAV) square yard kvadratinis jardas cubic yard kubinis jardas short ton trumpoji tona tablespoon valgomasis Å¡aukÅ¡tas tablespoon (Australian) valgomasis Å¡aukÅ¡tas (australiÅ¡kas) tablespoon (Imperial) valgomasis Å¡aukÅ¡tas (imperinis) tablespoon (US) valgomasis Å¡aukÅ¡tas (JAV) dessert spoon desertinis Å¡aukÅ¡tas teaspoon arbatinis Å¡aukÅ¡telis teaspoon (Imperial) arbatinis Å¡aukÅ¡telis (imperinis) teaspoon (US) arbatinis Å¡aukÅ¡telis (JAV) turn apsisukimas revolution apsisukimas revolution per minute apsisukimai per minutÄ™ week savaitÄ— kilowatt hour kilovatvalandÄ— millimetre of mercury gyvsidabrio milimetras yard jardas Julian century Julijaus amžius Julian year Julijaus metai sidereal year žvaigždiniai metai tropical year tropiniai metai Evaluator invalid expression neteisingas reiÅ¡kinys division by zero dalinimas iÅ¡ nulio too time consuming - computation was rejected operacija reikalauja per daug laiko - skaiÄ�iavimas atmestas dimension mismatch - quantities with different dimensions cannot be compared, added, etc. matmenų neatitikimas - skirtingų matmenų kiekiai negali bÅ«ti lyginami, pridedami ir t.t. invalid dimension - operation might require dimensionless arguments neteisingas matmuo - operacija gali reikalauti argumentų be matmenų Computation aborted - encountered numerical instability SkaiÄ�iavimas nutrauktas - susidurta su skaitiniu nesubalansuotumu invalid dimension - function might require dimensionless arguments neteisingas matmuo - funkcija gali reikalauti argumentų be matmenų error klaida unit must not be zero vienetas privalo bÅ«ti ne nulis Conversion failed - dimension mismatch Konvertuoti nepavyko - matmenys nesutampa unknown function or variable nežinoma funkcija arba kintamasis recursion not supported rekursija nepalaikoma cannot operate on a NaN negalima atlikti operacijos su NaN underflow - tiny result is out of SpeedCrunch's number range atvirkÅ¡tinis perpildymas - mažytis rezultatas yra už programos SpeedCrunch skaiÄ�ių ribų overflow - huge result is out of SpeedCrunch's number range perpildymas - milžiniÅ¡kas rezultatas yra už programos SpeedCrunch skaiÄ�ių ribų overflow - logic result exceeds maximum of 256 bits perpilda - loginis rezultatas virÅ¡ija didžiausiÄ… 256 bitų ribÄ… overflow - integer result exceeds maximum limit for integers perpilda - sveikasis rezultatas virÅ¡ija didžiausiÄ… sveikųjų skaiÄ�ių ribÄ… operation is not defined for these arguments operacija Å¡iems argumentams neapibrėžta wrong number of arguments neteisingas argumentų skaiÄ�ius does not take NaN as an argument NaN negali bÅ«ti argumentas result out of range rezultatas virÅ¡ija ribas undefined for argument domain neapibrėžta Å¡iai argumento apibrėžimo sriÄ�iai computation too expensive skaiÄ�iavimas pernelyg brangus internal error, please report a bug vidinÄ— klaida, praÅ¡ome apie jÄ… praneÅ¡ti syntax error sintaksÄ—s klaida conversion target must be a unit konvertavimo tikslas turi bÅ«ti vienetas unknown unit nežinomas vienetas %1 is a reserved name, please choose another %1 yra rezervuotas pavadinimas, praÅ¡ome pasirinkti kitÄ… %1 is a global user definition and cannot be overridden in this session. %1 yra globalus naudotojo apibrėžimas ir Å¡iame seanse negali bÅ«ti perraÅ¡ytas. %1 is a variable name, please choose another or delete the variable %1 yra kintamojo pavadinimas, praÅ¡ome pasirinkti kitÄ… arba iÅ¡trinti kintamÄ…jį argument %1 is used more than once argumentas %1 yra panaudotas daugiau negu vienÄ… kartÄ… %1 is a built-in unit name, please choose another %1 yra įtaisytasis vieneto pavadinimas, pasirinkite kitÄ… %1 is a user function name, please choose another or delete the function %1 yra funkcijos pavadinimas, praÅ¡ome pasirinkti kitÄ… arba iÅ¡trinti funkcijÄ… FunctionRepo max; trials; probability maks.; bandymai; tikimybÄ— trials; probability bandymai; tikimybÄ— hits; trials; probability sÄ—kmÄ—s; bandymai; tikimybÄ— max; total; hits; trials maks.; visuma; sÄ—kmÄ—s; bandymai total; hits; trials visuma; sÄ—kmÄ—s; bandymai count; total; hits; trials skaiÄ�ius; visuma; sÄ—kmÄ—s; bandymai dividend; divisor dalinys; daliklis x; exponent_bits; significand_bits [; exponent_bias] x; eksponentÄ—s_bitai; mantisÄ—s_bitai [; eksponentÄ—s_poslinkis] base; x pagrindas; x value; modulo reikÅ¡mÄ—; modulis base; exponent; modulo pagrindas; eksponentÄ—; modulis events; average_events įvykiai; vidutinis_įvykių_skaiÄ�ius average_events vidutinis_įvykių_skaiÄ�ius x [; precision] x [; tikslumas] Absolute Value Aboliuti reikÅ¡mÄ— Absolute Deviation Absoliutusis nuokrypis Arc Cosine Arkkosinusas Logical AND Loginis IR Area Hyperbolic Cosine Hiperbolinis areakosinusas Area Hyperbolic Sine Hiperbolinis areasinusas Area Hyperbolic Tangent Hiperbolinis areatangentas Arc Sine Arksinusas Arc Tangent Arktangentas Arc Tangent with two Arguments Arktangentas su dviem argumentais Average (Arithmetic Mean) Vidurkis (aritmetinis vidurkis) Binomial Cumulative Distribution Function Binominio skirstinio kaupiamoji pasiskirstymo funkcija Binomial Distribution Mean Binominio skirstinio vidurkis Binomial Probability Mass Function Binominio skirstinio tikimybinÄ— masÄ—s funkcija Binomial Distribution Variance Binominio skirstinio dispersija Cube Root KubinÄ— Å¡aknis Complex Conjugate Kompleksinis jungtinis Cosine Kosinusas Hyperbolic Cosine Hiperbolinis kosinusas Cotangent Kontangentas Cosecant Kosekantas Convert Unix timestamp to Date Konvertuoti Unix laiko žymÄ… į datÄ… Degrees of Arc Lanko laipsniai Error Function Klaidos funkcija Complementary Error Function Papildomoji klaidos funkcija Exponential EksponentÄ— Fractional Part TrupmeninÄ— dalis Extension of Factorials [= (x-1)!] Faktorialų apibendrinimas [= (x-1)!] Greatest Common Divisor Didžiausiasis bendrasis daliklis Geometric Mean Geometrinis vidurkis Gradians of arc Lanko gradianai Hypergeometric Cumulative Distribution Function Hipergeometrinio skirstinio kaupiamoji pasiskirstymo funkcija Hypergeometric Distribution Mean Hipergeometrinio skirstinio vidurkis Hypergeometric Probability Mass Function Hipergeometrinio skirstinio tikimybinÄ— masÄ—s funkcija Hypergeometric Distribution Variance Hipergeometrinio skirstinio dispersija Integer Quotient Sveikasis dalmuo Integer Part Sveikoji dalis Imaginary Part Menamoji dalis Decode IEEE-754 Binary Value Dekoduoti IEEE-754 dvejetainÄ™ reikÅ¡mÄ™ Encode IEEE-754 Binary Value Koduoti IEEE-754 dvejetainÄ™ reikÅ¡mÄ™ Decode 16-bit Half-Precision Value Dekoduoti 16 bitų pusinio tikslumo reikÅ¡mÄ™ Encode 16-bit Half-Precision Value Koduoti 16 bitų pusinio tikslumo reikÅ¡mÄ™ Decode 32-bit Single-Precision Value Dekoduoti 32 bitų viengubo tikslumo reikÅ¡mÄ™ Encode 32-bit Single-Precision Value Koduoti 32 bitų viengubo tikslumo reikÅ¡mÄ™ Decode 64-bit Double-Precision Value Dekoduoti 64 bitų dvigubo tikslumo reikÅ¡mÄ™ Encode 64-bit Double-Precision Value Koduoti 64 bitų dvigubo tikslumo reikÅ¡mÄ™ Decode 128-bit Quad-Precision Value Dekoduoti 128 bitų keturgubo tikslumo reikÅ¡mÄ™ Encode 128-bit Quad-Precision Value Koduoti 128 bitų keturgubo tikslumo reikÅ¡mÄ™ Binary Logarithm Dvejetainis logaritmas Common Logarithm DeÅ¡imtainis (paprastasis) logaritmas Natural Logarithm NatÅ«ralusis logaritmas Logarithm to Arbitrary Base Logaritmas bet kuriuo pagrindu Mask to a bit size Maskuoti iki bitų skaiÄ�iaus Maximum Maksimumas Median Value (50th Percentile) Mediana (50-asis procentilis) Minimum Minimumas Modulo Liekana pagal modulį Euclidean Modulo EuklidinÄ— liekana pagal modulį Modular Exponentiation KÄ—limas laipsniu pagal modulį Combination (Binomial Coefficient) Derinys (binominis koeficientas) Logical NOT Loginis NE Permutation (Arrangement) Gretinys (permutacija) Convert to Binary Representation Konvertuoti į dvejetainį vaizdavimÄ… Arithmetic Aritmetika Chemistry Chemija Complex Kompleksiniai Combinatorics Kombinatorika Probability TikimybÄ— Statistics Statistika Aggregation Agregavimas Random Atsitiktiniai Base conversion Pagrindo konvertavimas Number formatting SkaiÄ�ių formatavimas Integer arithmetic Sveikųjų skaiÄ�ių aritmetika Special functions Specialiosios funkcijos Exponential & Logarithmic EksponentinÄ—s ir logaritminÄ—s Angle conversion Kampų konvertavimas Trigonometry Trigonometrija Bitwise BitinÄ—s Floating point Slankusis kablelis Date & Time Data ir laikas Linear algebra TiesinÄ— algebra unix_timestamp; x hours offset to GMT Unix_laiko_žyma; x valandų poslinkis nuo GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; x valandų poslinkis nuo GMT [digits] [skaitmenys] max [; min] maks. [; min.] List Literal SÄ…raÅ¡o literalas Convert to Padded Binary Representation Konvertuoti į papildytÄ… dvejetainį vaizdavimÄ… Round Toward +∞ (Ceiling) Apvalinti link +∞ (lubos) Cosine plus Imaginary Sine Kosinusas ir menamasis sinusas Convert to Cis Complex Form Konvertuoti į cis kompleksinÄ™ formÄ… Matrix Column Count Matricos stulpelių skaiÄ�ius Population Correlation Matrix (n) Populiacijos koreliacijos matrica (n) Sample Correlation Matrix (n-1) Imties koreliacijos matrica (n-1) Count SkaiÄ�ius Population Covariance Matrix (n) Populiacijos kovariacijos matrica (n) Sample Covariance Matrix (n-1) Imties kovariacijos matrica (n-1) Cross Product Vektorinis sandauga Convert Date to Unix timestamp Konvertuoti datÄ… į Unix laiko žymÄ… Convert to Decimal Representation Konvertuoti į deÅ¡imtainį vaizdavimÄ… Determinant Determinantas Convert to Sexagesimal Notation Konvertuoti į Å¡eÅ¡iasdeÅ¡imtainį žymÄ—jimÄ… Dot Product SkaliarinÄ— sandauga Convert to Engineering Notation Konvertuoti į inžinerinį žymÄ—jimÄ… Convert to Exponential Complex Form Konvertuoti į eksponentinÄ™ kompleksinÄ™ formÄ… Round Toward −∞ (Floor) Apvalinti link −∞ (grindys) Flatten Matrix IÅ¡lyginti matricÄ… Least Common Multiple Mažiausias bendras kartotinis Convert to Hexadecimal Representation Konvertuoti į Å¡eÅ¡ioliktainį vaizdavimÄ… Convert to Padded Hexadecimal Representation Konvertuoti į papildytÄ… Å¡eÅ¡ioliktainį vaizdavimÄ… Inverse Matrix AtvirkÅ¡tinÄ— matrica Round to 16-bit Half-Precision Value Apvalinti iki 16 bitų pusinio tikslumo reikÅ¡mÄ—s Round to 32-bit Single-Precision Value Apvalinti iki 32 bitų viengubo tikslumo reikÅ¡mÄ—s Round to 64-bit Double-Precision Value Apvalinti iki 64 bitų dvigubo tikslumo reikÅ¡mÄ—s Round to 128-bit Quad-Precision Value Apvalinti iki 128 bitų keturgubo tikslumo reikÅ¡mÄ—s Residual from 16-bit Half-Precision Rounding Likutis po 16 bitų pusinio tikslumo apvalinimo Residual from 32-bit Single-Precision Rounding Likutis po 32 bitų viengubo tikslumo apvalinimo Residual from 64-bit Double-Precision Rounding Likutis po 64 bitų dvigubo tikslumo apvalinimo Residual from 128-bit Quad-Precision Rounding Likutis po 128 bitų keturgubo tikslumo apvalinimo Substance Mass Medžiagos masÄ— Molarity MoliariÅ¡kumas Molar Mass MolinÄ— masÄ— Median Absolute Deviation Medianinis absoliutusis nuokrypis Mean Vidurkis Numerical Value of Quantity Dydžio skaitinÄ— reikÅ¡mÄ— Random Decimal Number Atsitiktinis deÅ¡imtainis skaiÄ�ius Random Integer Number Atsitiktinis sveikasis skaiÄ�ius Convert to Rational Representation Konvertuoti į racionalųjį vaizdavimÄ… Convert to Octal Representation Konvertuoti į aÅ¡tuonetainį vaizdavimÄ… Convert to Padded Octal Representation Konvertuoti į papildytÄ… aÅ¡tuonetainį vaizdavimÄ… Vector or Matrix Norm Vektoriaus arba matricos norma Logical OR Loginis ARBA Population Count (Hamming Weight) Vienetų skaiÄ�ius (Hamingo svoris) Phase of Complex Number Kompleksinio skaiÄ�iaus fazÄ— Poissonian Cumulative Distribution Function Puasono skirstinio kaupiamoji pasiskirstymo funkcija Poissonian Distribution Mean Puasono skirstinio vidurkis Poissonian Probability Mass Function Puasono skirstinio tikimybinÄ— masÄ—s funkcija Poissonian Distribution Variance Puasono skirstinio dispersija Convert to Phasor Complex Form Konvertuoti į fazorinÄ™ kompleksinÄ™ formÄ… Convert to Rectangular Complex Form Konvertuoti į staÄ�iakampÄ™ kompleksinÄ™ formÄ… Round Half Away from Zero Apvalinti pusÄ™ nuo nulio Round Half Even Apvalinti pusÄ™ į lyginį Nth Root N-tojo laipsnio Å¡aknis Convert to Scientific Notation Konvertuoti į mokslinį žymÄ—jimÄ… Matrix Row Count Matricos eiluÄ�ių skaiÄ�ius List or Matrix Shape SÄ…raÅ¡o arba matricos forma Summation Suma Population Standard Deviation (n) Populiacijos standartinis nuokrypis (n) Sample Standard Deviation (n-1) Imties standartinis nuokrypis (n-1) Round Toward Zero (Truncation) Apvalinti link nulio (trumpinimas) Matrix Trace Matricos pÄ—dsakas Transpose Matrix Transponuoti matricÄ… Population Variance (n) Populiacijos dispersija (n) Sample Variance (n-1) Imties dispersija (n-1) Product Sandauga Radians Radianai Matrix Rank Matricos rangas Real Part Realioji dalis Secant Sekantas Arithmetic Shift Left Aritmetinis postÅ«mis kairÄ—n Arithmetic Shift Right Aritmetinis postÅ«mis deÅ¡inÄ—n Signum Signum (ženklo) funkcija Sine Sinusas Hyperbolic Sine Hiperbolinis sinusas Square Root KvadratinÄ— Å¡aknis Sum Suma Tangent Tangentas Convert to Trigonometric Complex Form Konvertuoti į trigonometrinÄ™ kompleksinÄ™ formÄ… Turns Apsisukimai Hyperbolic Tangent Hiperbolinis tangentas Sign-extend a value IÅ¡plÄ—sti reikÅ¡mÄ—s ženklÄ… Logical XOR Loginis iÅ¡skirtinis ARBA FunctionsWidget Domain Sritis All Visi Name Pavadinimas Search PaieÅ¡ka No match found Nerasta atitikmens Identifier Identifikatorius HistoryWidget Remove All Calculations Above PaÅ¡alinti visus skaiÄ�iavimus aukÅ¡Ä�iau Remove This Calculation Pasalinti si skaiciavima Remove All Calculations Below PaÅ¡alinti visus skaiÄ�iavimus žemiau Keypad Inverse cosine Arkkosinusas The last result Paskutinis rezultatas Inverse sine Arksinusas Inverse tangent Arktangentas Evaluate expression ApskaiÄ�iuoti reiÅ¡kinį Division Dalyba Multiplication Daugyba Subtraction Atimtis Addition SudÄ—tis Clear expression IÅ¡valyti reiÅ¡kinį Cosine Kosinusas Backspace Naikinti atgal Scientific notation Slankiojo kablelio formatas Exponential EksponentinÄ— funkcija Factorial Faktorialas Natural logarithm NatÅ«ralusis logaritmas Left parenthesis Kairysis skliaustas Nth root N-tojo laipsnio Å¡aknis Argument separator Argumentų skirtukas Square Kvadratas Common logarithm DeÅ¡imtainis logaritmas Modulo Liekana pagal modulį Contextual percentage Kontekstinis procentas Power Laipsnis Right parenthesis DeÅ¡inysis skliaustas Sine Sinusas Square root KvadratinÄ— Å¡aknis Tangent Tangentas Pi Pi Decimal separator DeÅ¡imtainis skirtukas MainWindow Radian Radianai Degree Laipsniai Gradian Gradianas Binary Dvejetainis Octal AÅ¡tuonetainis Hexadecimal Å eÅ¡ioliktainis Sexagesimal Å eÅ¡iasdeÅ¡imtainis Engineering decimal Inžinerinis deÅ¡imtainis Scientific decimal Mokslinis deÅ¡imtainis &Import... &Importuoti... &Quit &IÅ¡eiti Clear E&xpression IÅ¡valyti reiÅ¡ki&nį Clear &History IÅ¡valyti ž&urnalÄ… &Copy K&opijuoti &Paste Ä®&dÄ—ti &Select Expression Ž&ymÄ—ti reiÅ¡kinį &Constants &Konstantos &Functions F&unkcijos &History Žurna&las &Status Bar &BÅ«senos juosta Bitfield Bitų laukas Use&r Functions Naudo&tojo funkcijos &Degree &Laipsniai &Radian &Radianai &Gradian &Gradianas Re&volution A&psisukimas Auto-Insert a&ns AutomatiÅ¡kai įterpti a&ns Automatic &Completion Automatinis &užbaigimas &Built-in Functions &Ä®taisytosios funkcijos Built-in &Variables Ä®&taisytieji kintamieji User &Functions Naudotojo &funkcijos User Va&riables &Naudotojo kintamieji Open a Private Tab on Startup Paleidžiant atverti privatų skirtukÄ… Open and focus a new private tab whenever SpeedCrunch starts. KiekvienÄ… kartÄ… paleidžiant SpeedCrunch atverti ir aktyvuoti naujÄ… privatų skirtukÄ…. Syntax &Highlighting SintaksÄ—s par&yÅ¡kinimas Group Digits in &Input Grupuot&i įvesties skaitmenis Automatic Input &Adjustments &Automatiniai įvesties taisymai Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. AutomatiÅ¡kai taisyti operatorius, tarpus, skliaustus ir laipsnius bei leisti įvesti tik tinkamus simbolius. Group input digits using the selected number format. Grupuoti įvestus skaitmenis pagal pasirinktÄ… skaiÄ�ių formatÄ…. &Blinking Cursor &Mirksintis žymeklis Blink the cursor in the expression editor. Ä®jungti žymeklio mirksÄ—jimÄ… reiÅ¡kinių rengyklÄ—je. &Escape Clears Editor &Escape iÅ¡valo rengyklÄ™ Clear the focused expression editor with Escape after dismissing any popup or preview. IÅ¡valyti aktyviÄ… reiÅ¡kinių rengyklÄ™ klaviÅ¡u Escape, užvÄ—rus iÅ¡kylanÄ�iuosius langus ar peržiÅ«ras. Keep Expression After Evaluation Palikti reiÅ¡kinį po skaiÄ�iavimo Copy New Results Automatically AutomatiÅ¡kai kopijuoti naujus rezultatus &Comma &Kablelis &System Default &Sistemos numatytasis &Dot &TaÅ¡kas Dot &And Comma TaÅ¡kas &ir kablelis Toward +∞ (&ceil) Link +∞ (&ceil) Toward −∞ (&floor) Link −∞ (&floor) &Binary D&vejetainis &Engineering &Inžinerinis &Hexadecimal Å &eÅ¡ioliktainis &Octal &AÅ¡tuonetainis &Scientific &Mokslinis User &Manual Naudoto&jo vadovas Issues and &Feedback P&roblemos ir atsiliepimai &Donate &Paaukoti &About SpeedCrunch &Apie SpeedCrunch App Diag&nostics Pr&ogramos diagnostika S&plit P&adalyti Angle &Mode Ka&mpų veiksena &Complex Form &KompleksinÄ— forma New Tab Nauja kortelÄ— Constants Konstantos Functions Funkcijos History Žurnalas User Functions Naudotojo funkcijos &Font... Å ri&ftas... &Language... Ka&lba... &Session &Seansas &Edit &Taisa &View &Rodinys Se&ttings &Nustatymai &Decimal &DeÅ¡imtainis &Keypad &PagalbinÄ— klaviatÅ«ra Always on &Top Visada &virÅ¡uje Disabled IÅ¡jungta Small Space Mažas tarpas Medium Space Vidutinis tarpas Large Space Didelis tarpas &0 Digits &0 skaitmenų &15 Digits &15 skaitmenų &2 Digits &2 skaitmenys &3 Digits &3 skaitmenys &50 Digits &50 skaitmenų &8 Digits &8 skaitmenys &Sexagesimal &Å eÅ¡iasdeÅ¡imtainis Reset All Settings... Atkurti visas nuostatas... &System &Sistema SpeedCrunch &Theme S&peedCrunch apipavidalinimas &Classic &Klasikinis &Modern &Å iuolaikinis Context Help Konteksto pagalba &Help &Pagalba Error Klaida Can't read from file %1 Nepavyksta perskaityti iÅ¡ failo %1 Import Session Importuoti seansÄ… Close Session Užverti seansÄ… Angle Mode: Kampų veiksena: Notation: ŽymÄ—jimas: Precision: Tikslumas: Turn Apsisukimas Revolution Apsisukimas Fixed-point decimal Fiksuoto kablelio deÅ¡imtainis Rational Racionalusis Automatic decimal Automatinis deÅ¡imtainis Automatic Automatinis User &Definitions... Naudotojo &apibrėžimai... New &Tab Nauja &kortelÄ— New &Private Tab Naujas &privatus skirtukas Keep IÅ¡saugoti Make Private... Padaryti privatų... New &Window Naujas &langas &Open... &Atverti... &Rename... Per&vadinti... Clo&ne... Klo&nuoti... &Close Tab &Užverti skirtukÄ… Reopen Clo&sed Tab VÄ—l atverti užvertÄ… &skirtukÄ… Open Sessions &Folder Atverti seansų &aplankÄ… &Undo &AtÅ¡aukti &Redo G&rąžinti Cu&t IÅ¡kirp&ti Copy &Last Result Kopijuoti paskutinį rezu&ltatÄ… &Wrap in Parentheses A&pskliausti Full Scr&een Mode Viso &ekrano veiksena &Basic &Pagrindinis &Scientific (wide) &Mokslinis (platus) Scientific (narrow) Mokslinis (siauras) &Custom... &Pasirinktinis... Main &Menu Pagrindinis &meniu User &Variables Naudotojo &kintamieji &Left &KairÄ—n &Right &DeÅ¡inÄ—n &Up A&ukÅ¡tyn &Down &Žemyn Close Pa&ne Užverti pola&ngį User &Units Naudotojo &vienetai &Turn &Apsisukimas If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Jei naujas reiÅ¡kinys prasideda +, -, * arba /, SpeedCrunch pirmiausia įterpia „ans“. &Accept with Enter &Priimti klaviÅ¡u Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Priimti dabartinį automatinio užbaigimo pasiÅ«lymÄ… klaviÅ¡u Enter, prieÅ¡ tai jo nepasirinkus rodyklių klaviÅ¡ais. &Units &Vienetai Show Live Result &Preview Rodyti tiesioginÄ™ rezultato &peržiÅ«rÄ… Save &Window Position on Exit IÅ¡einant įraÅ¡yti &lango padÄ—tį Hover Highlighting ParyÅ¡kinimas užvedus Group Integer Part Only Grupuoti tik sveikÄ…jÄ… dalį Number Format... SkaiÄ�ių formatas... Notation && Precision... ŽymÄ—jimas ir tikslumas... After pressing Enter, keep the entered expression selected in the editor. Paspaudus Enter, palikti įvestÄ… reiÅ¡kinį pažymÄ—tÄ… rengyklÄ—je. Never Niekada Always Visada Only for Single-Line Expressions Tik vienos eilutÄ—s reiÅ¡kiniams Simplify Displayed Expressions Supaprastinti rodomus reiÅ¡kinius History Size &Limit... Istorijos dydžio &riba... Remove Trailing &Zeroes &Å alinti galinius nulius Nearest, Half &Away (round) Artimiausias, pusÄ— &nuo nulio (round) Nearest, Half &Even (roundeven) Artimiausias, pusÄ— į &lyginį (roundeven) Toward &Zero (trunc) Link &nulio (trunc) &Fixed-Point &Fiksuoto kablelio &Rational &Racionalusis &Exponential (m·sâ�»Â¹) &Eksponentinis (m·sâ�»Â¹) &Fractional (m/s) &Trupmeninis (m/s) &Rectangular (a + bi) &StaÄ�iakampis (a + bi) Exponential (reâ�±á¶¿) Eksponentinis (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrinis (r(cos θ + i·sin θ)) Phasor (r∠θ) Fazorius (r∠θ) &Theme... &Tema... Check for &Updates Tikrinti, ar yra &naujinimų Source Code Pirminis kodas &Zoom &Mastelis &Results &Rezultatai Unit Notation Vienetų žymÄ—jimas Rounding Mode Apvalinimo veiksena &Notation &ŽymÄ—jimas &Imaginary Unit &Menamasis vienetas &Window &Langas &Editing &Redagavimas A&utocomplete A&utomatinis užbaigimas Up/Down Arrow History Rodyklių aukÅ¡tyn/žemyn istorija &Appearance &IÅ¡vaizda &Menus &Meniu &Docks Prikabinami sky&deliai &Input and Results Ä®vest&is ir rezultatai &Disabled &IÅ¡jungta &Disable &IÅ¡jungti Close preview Užverti peržiÅ«rÄ… Rename... Pervadinti... Clone... Klonuoti... Close Tab Užverti skirtukÄ… New Private Tab Naujas privatus skirtukas Open... Atverti... Reopen Closed Tab VÄ—l atverti užvertÄ… skirtukÄ… Split Padalyti Left KairÄ—n Right DeÅ¡inÄ—n Up AukÅ¡tyn Down Žemyn Clear IÅ¡valyti Delete IÅ¡trinti %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Privatus seansas: užvÄ—rus jo turinys paÅ¡alinamas. Pasirinkite Seansas > IÅ¡saugoti, kad jis taptų įprastu seansu. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privatus] Reset All Settings Atkurti visas nuostatas Reset all settings to their default values? Atkurti visų nuostatų numatytÄ…sias reikÅ¡mes? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Tai apima iÅ¡vaizdÄ…, redagavimÄ…, rezultatų formatus ir langų nuostatas. SkaiÄ�iavimai, atverti seansai ir naudotojo apibrėžtys bus iÅ¡saugoti. The settings file could not be written. Nepavyko įraÅ¡yti nuostatų failo. Clear this session's calculations, unfinished expression, variables, functions, and units? IÅ¡valyti Å¡io seanso skaiÄ�iavimus, nebaigtÄ… reiÅ¡kinį, kintamuosius, funkcijas ir vienetus? Global user definitions are kept. VisuotinÄ—s naudotojo apibrėžtys iÅ¡saugomos. Make Session Private Padaryti seansÄ… privatų The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Ä®raÅ¡ytas seansas %1 bus paÅ¡alintas. Jo turinys liks atvertas privaÄ�iame seanse ir bus paÅ¡alintas užvÄ—rus tÄ… seansÄ… arba išėjus iÅ¡ SpeedCrunch. Make Private Padaryti privatų Could not delete the saved session %1. Nepavyko paÅ¡alinti įraÅ¡yto seanso %1. Keep Session IÅ¡saugoti seansÄ… Could not save the session. It remains private. Nepavyko įraÅ¡yti seanso. Jis lieka privatus. Clone Session Klonuoti seansÄ… Could not save session file %1. Nepavyko įraÅ¡yti seanso failo %1. Could not delete session file %1. Nepavyko paÅ¡alinti seanso failo %1. JSON file (*.json);;Any file (*.*) JSON failas (*.json);;Bet koks failas (*.*) Export session as JSON Eksportuoti seansÄ… kaip JSON The selected file is not valid JSON: %1 Pasirinktas failas nÄ—ra tinkamas JSON: %1 The selected file is not a SpeedCrunch session JSON file. Pasirinktas failas nÄ—ra SpeedCrunch seanso JSON failas. This file uses an obsolete SpeedCrunch session format and cannot be imported. Å is failas naudoja pasenusį SpeedCrunch seanso formatÄ… ir negali bÅ«ti importuotas. The selected JSON file is missing the required $schema field. Pasirinktame JSON faile trÅ«ksta privalomo $schema lauko. The selected JSON file uses an unsupported JSON schema: %1 Pasirinktas JSON failas naudoja nepalaikomÄ… JSON schemÄ…: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Pasirinktame JSON faile trÅ«ksta SpeedCrunch seanso schemos identifikatoriaus ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Pasirinktas JSON failas naudoja nepalaikomÄ… SpeedCrunch seanso formatÄ…: %1 The selected JSON file is missing the required session name. Pasirinktame JSON faile trÅ«ksta privalomo seanso pavadinimo. The selected JSON file has an empty session name. Pasirinktame JSON faile seanso pavadinimas yra tuÅ¡Ä�ias. The selected JSON file has invalid or incomplete SpeedCrunch session data. Pasirinktame JSON faile yra neteisingų arba neiÅ¡samių SpeedCrunch seanso duomenų. Open Sessions Folder Atverti seansų aplankÄ… Could not create the sessions folder: %1 Nepavyko sukurti seansų aplanko: %1 Could not open the sessions folder: %1 Nepavyko atverti seansų aplanko: %1 Editor and Results Font RengyklÄ—s ir rezultatų Å¡riftas Open Session Atverti seansÄ… Community BendruomenÄ— Rename Session Pervadinti seansÄ… Clear Session IÅ¡valyti seansÄ… Delete Session IÅ¡trinti seansÄ… Close Pane Užverti polangį User Variables Naudotojo kintamieji User Units Naudotojo vienetai Clear History IÅ¡valyti istorijÄ… Are you sure you want to clear the calculation history? Ar tikrai norite iÅ¡valyti skaiÄ�iavimų istorijÄ…? Session name: Seanso pavadinimas: A session named %1 already exists. Seansas pavadinimu %1 jau yra. Could not create session file %1. Nepavyko sukurti seanso failo %1. Could not write session file %1. Nepavyko įraÅ¡yti seanso failo %1. Are you sure you want to delete this session? Ar tikrai norite iÅ¡trinti šį seansÄ…? Custom Precision Pasirinktinis tikslumas Fractional digits: TrupmeninÄ—s dalies skaitmenys: Theme Tema Light Themes Å viesios temos Dark Themes Tamsios temos Preview PeržiÅ«ra Colors Spalvos Select color for %1 Pasirinkite spalvÄ… elementui %1 Import... Importuoti... Export... Eksportuoti... Import Theme Importuoti temÄ… Theme file (*.json);;All files (*) Temos failas (*.json);;Visi failai (*) Invalid theme file. Netinkamas temos failas. Can't import theme "%1" because it conflicts with a built-in theme. Nepavyksta importuoti temos „%1“, nes ji konfliktuoja su įtaisytÄ…ja tema. Can't find a writable theme folder. Nepavyksta rasti įraÅ¡omo temos aplanko. Overwrite Theme PerraÅ¡yti temÄ… A custom theme named "%1" already exists. Do you want to overwrite it? PasirinktinÄ— tema pavadinimu „%1“ jau yra. Ar norite jÄ… perraÅ¡yti? Can't overwrite theme file %1 Nepavyksta perraÅ¡yti temos failo %1 Can't copy theme file to %1 Nepavyksta nukopijuoti temos failo į %1 Export Theme Eksportuoti temÄ… Can't export theme as "%1" because it conflicts with a built-in theme. Nepavyksta eksportuoti temos kaip „%1“, nes ji konfliktuoja su įtaisytÄ…ja tema. Can't write to file %1 Nepavyksta įraÅ¡yti į failÄ… %1 Global User Variable Globalus naudotojo kintamasis Global User Function Globali naudotojo funkcija Global User Unit Globalus naudotojo vienetas User Definitions Naudotojo apibrėžimai These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Å ie apibrėžimai yra globalÅ«s ir įkeliami į kiekvienÄ… seansÄ…. Seansuose jų keisti negalima, ir jie turi pirmenybÄ™ prieÅ¡ seanso rengyklÄ—s apibrėžimus tuo paÄ�iu pavadinimu. Kiekvienoje eilutÄ—je įveskite po vienÄ… apibrėžimÄ…. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Pavyzdžiai: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Taikyti Validate Tikrinti Test Results Bandymo rezultatai Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Importuoti kintamieji: %1 Importuotos funkcijos: %2 Importuoti vienetai: %3 EiluÄ�ių su klaidomis numeriai: %4 none nÄ—ra Apply Results Taikymo rezultatai User definitions saved. Naudotojo apibrėžimai iÅ¡saugoti. History Size Limit Istorijos dydžio riba Maximum number of history entries for this session (0 = unlimited): Didžiausias Å¡io seanso istorijos įrašų skaiÄ�ius (0 = neribota): Text file (*.txt);;Any file (*.*) Tekstinis failas (*.txt);;Bet koks failas (*.*) Could not recalculate from calculation %1: %2 Nepavyko perskaiÄ�iuoti nuo skaiÄ�iavimo %1: %2 History Size Limit Reached Pasiekta istorijos dydžio riba This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Å is skaiÄ�iavimas užpildo paskutinÄ™ laisvÄ… istorijos vietÄ…. BÅ«simi skaiÄ�iavimai paÅ¡alins seniausiÄ… skaiÄ�iavimÄ… iÅ¡ istorijos. RibÄ… galite padidinti meniu Seansas > Istorijos dydžio riba. Editing calculation. Press Esc twice to cancel. SkaiÄ�iavimas redaguojamas. NorÄ—dami atÅ¡aukti, du kartus paspauskite Esc. Calculation Settings SkaiÄ�iavimo nustatymai Invalid recalculation start index Netinkamas perskaiÄ�iavimo pradžios indeksas System Default Sistemos numatytoji Language Kalba Select the language: Pasirinkite kalbÄ…: Custom Pasirinktinis Decimal places: DeÅ¡imtainÄ—s vietos: &Automatic &AutomatiÅ¡kai &Precision &Tikslumas Plain &text Grynasis &tekstas Formula &Book &Formulių knyga &Export &Eksportuoti Export session as HTML Eksportuoti seansÄ… kaip HTML HTML file (*.html) HTML failas (*.html) Export session as plain text Eksportuoti seansÄ… kaip grynÄ…jį tekstÄ… ManualWindow SpeedCrunch Manual SpeedCrunch vadovas %1 - SpeedCrunch Manual %1 - SpeedCrunch vadovas NumberFormatDialog Number Format SkaiÄ�ių formatas <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Pasirinkite skaiÄ�ių formatÄ… rezultatams ir įvesties skaitmenų grupavimui.</b><br/><br/>Pastaba: įvedamų skaiÄ�ių vienareikÅ¡miai formatai priimami net tada, kai skiriasi nuo pasirinkto rodymo formato.<br/> QObject Global User Variable Globalus naudotojo kintamasis Global User Function Globali naudotojo funkcija Global User Unit Globalus naudotojo vienetas Backspace Naikinti atgal Clear expression IÅ¡valyti reiÅ¡kinį Evaluate expression ApskaiÄ�iuoti reiÅ¡kinį Insert text Ä®terpti tekstÄ… Automatic decimal Automatinis deÅ¡imtainis Fixed-point decimal Fiksuoto kablelio deÅ¡imtainis Engineering decimal Inžinerinis deÅ¡imtainis Scientific decimal Mokslinis deÅ¡imtainis Rational Racionalusis Binary Dvejetainis Octal AÅ¡tuonetainis Hexadecimal Å eÅ¡ioliktainis Sexagesimal Å eÅ¡iasdeÅ¡imtainis Update Available Yra naujinimas A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Yra naujesnÄ— versija (%1).<br/><a href="%2">Apsilankykite svetainÄ—je ir atsisiųskite.</a> Check for Updates Tikrinti, ar yra naujinimų SpeedCrunch %1 is up to date. SpeedCrunch %1 yra naujausia versija. No connectivity. Please check your internet connection and try again. NÄ—ra ryÅ¡io. Patikrinkite interneto ryšį ir bandykite dar kartÄ…. Could not verify the latest available version. Nepavyko patikrinti naujausios prieinamos versijos. ResultDisplay Scroll to bottom Slinkti į apaÄ�iÄ… Edit Expression Redaguoti reiÅ¡kinį Change Settings Keisti nustatymus New Tab Nauja kortelÄ— &Import... &Importuoti... &Export &Eksportuoti Plain &text Grynasis &tekstas Copy Kopijuoti Selection PažymÄ—ta sritis Select All PažymÄ—ti viskÄ… Expression ReiÅ¡kinys Result Rezultatas Calculation SkaiÄ�iavimas Calculation as Single Line SkaiÄ�iavimas vienoje eilutÄ—je Remove Å alinti This Calculation Å is skaiÄ�iavimas All Calculations Above Visi aukÅ¡Ä�iau esantys skaiÄ�iavimai All Calculations Below Visi žemiau esantys skaiÄ�iavimai New Private Tab Naujas privatus skirtukas Session Seansas Open... Atverti... Clone... Klonuoti... Rename... Pervadinti... Keep IÅ¡saugoti Make Private... Padaryti privatų... Clear IÅ¡valyti Delete IÅ¡trinti Close Užverti Split Padalyti Left KairÄ—n Right DeÅ¡inÄ—n Up AukÅ¡tyn Down Žemyn Close Pane Užverti polangį Main Menu Pagrindinis meniu Cancel editing AtÅ¡aukti redagavimÄ… Copy result Kopijuoti rezultatÄ… Edit expression Redaguoti reiÅ¡kinį Change settings Keisti nustatymus Remove calculation PaÅ¡alinti skaiÄ�iavimÄ… ResultSlotsDialog Notation & Precision ŽymÄ—jimas ir tikslumas Result Line Rezultato eilutÄ— Enabled Ä®jungta Notation ŽymÄ—jimas Decimal Places DeÅ¡imtainÄ—s vietos Main Line PagrindinÄ— eilutÄ— Extra Line #1 Papildoma eilutÄ— Nr. 1 Extra Line #2 Papildoma eilutÄ— Nr. 2 Extra Line #3 Papildoma eilutÄ— Nr. 3 Extra Line #4 Papildoma eilutÄ— Nr. 4 Auto AutomatiÅ¡kai UserFunctionListWidget Name Pavadinimas Value ReikÅ¡mÄ— Description ApraÅ¡as Search PaieÅ¡ka No match found Nerasta atitikmens Insert Ä®terpti Edit Redaguoti Delete IÅ¡trinti Delete All IÅ¡trinti visus UserUnitListWidget Name Pavadinimas Value ReikÅ¡mÄ— Description ApraÅ¡as Search PaieÅ¡ka No match found Atitikmenų nerasta Insert Ä®terpti Edit Redaguoti Delete IÅ¡trinti Delete All IÅ¡trinti viskÄ… VariableListWidget Name Pavadinimas Value ReikÅ¡mÄ— Description ApraÅ¡as Search PaieÅ¡ka No match found Nerasta atitikmens Insert Ä®terpti Edit Redaguoti Delete IÅ¡trinti Delete All IÅ¡trinti visus heldercorreia-speedcrunch-e7ca37f/src/resources/locale/lv.ts000066400000000000000000010560341526573132500243770ustar00rootroot00000000000000 AboutBox About SpeedCrunch Par SpeedCrunch Core developers PamatizstrÄ�dÄ�tÄ�ji Original author SÄ�kotnÄ“jais autors Close AizvÄ“rt Math engine MatemÄ�tiskais dzinis Main author | Logo | Maintainer Galvenais autors | Logotips | UzturÄ“tÄ�js Thanks PateicÄ«bas Copyright (C) 2004-2026 The SpeedCrunch developers AutortiesÄ«bas (C) 2004-2026 SpeedCrunch izstrÄ�dÄ�tÄ�ji This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Å Ä« programma ir brÄ«vÄ� programmatÅ«ra; to drÄ«kst izplatÄ«t un/vai modificÄ“t saskaņÄ� ar GNU VispÄ�rÄ“jÄ�s publiskÄ�s licences noteikumiem, ko publicÄ“jis BrÄ«vÄ�s programmatÅ«ras fonds; vai nu licences 2. versiju, vai (pÄ“c jÅ«su izvÄ“les) jebkuru vÄ“lÄ�ku versiju This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Å Ä« programma tiek izplatÄ«ta cerÄ«bÄ�, ka tÄ� bÅ«s noderÄ«ga, bet BEZ JEBKÄ€DÄ€M GARANTIJÄ€M; pat bez netieÅ¡as garantijas par PIEMÄ’ROTĪBU PÄ€RDOÅ ANAI vai ATBILSTĪBU KONKRÄ’TAM MÄ’RĶIM. PlaÅ¡Ä�ku informÄ�ciju skatiet GNU VispÄ�rÄ“jÄ� publiskajÄ� licencÄ“. BitFieldWidget Reset bits to zero AtiestatÄ«t bitus uz nulli Invert bits InvertÄ“t bitus Shift bits left BÄ«dÄ«t bitus pa kreisi Shift bits right BÄ«dÄ«t bitus pa labi Book Index RÄ�dÄ«tÄ�js Algebra Algebra Quadratic Equation KvadrÄ�tvienÄ�dojums Logarithmic Base Conversion Logaritma bÄ�zes pÄ�rveidoÅ¡ana Geometry Ä¢eometrija Circle Riņķis Sector Sektors Sphere SfÄ“ra Cube Kubs Cone Konuss Cylinder Cilindrs Electronics Elektronika Ohm's Law Oma likums Power Jauda Reactance ReaktÄ«vÄ� pretestÄ«ba Resonance Rezonanse Radio Frequency Radiofrekvence Antennas Antenas Characteristic Impedance (coax) RaksturÄ«gÄ� pretestÄ«ba (koaksiÄ�lais kabelis) Velocity of Propagation (coax) IzplatīšanÄ�s Ä�trums (koaksiÄ�lais kabelis) Standing Wave Ratio & Return Loss StÄ�vviļņa koeficients un atstarojuma zudumi Free Space Wavelength Viļņa garums brÄ«vÄ� telpÄ� resistance pretestÄ«ba voltage spriegums current strÄ�va power jauda inductive reactance induktÄ«vÄ� pretestÄ«ba capacitive reactance kapacitÄ«vÄ� pretestÄ«ba inductance induktivitÄ�te capacitance kapacitÄ�te frequency frekvence resonance frequency rezonanses frekvence area laukums perimeter perimetrs diameter diametrs radius rÄ�diuss volume tilpums surface area virsmas laukums height augstums slant height slÄ«pais augstums face diagonal skaldnes diagonÄ�le space diagonal telpiskÄ� diagonÄ�le edge length šķautnes garums arc length loka garums central angle (degrees) centrÄ�lais leņķis (grÄ�di) input power ievades jauda reflected power atstarotÄ� jauda transmitted power pÄ�rvadÄ«tÄ� jauda return loss atstarojuma zudumi dielectric constant dielektriskÄ� konstante outer conductor's inner diameter Ä�rÄ“jÄ� vadÄ«tÄ�ja iekšējais diametrs inner conductor's outer diameter iekšējÄ� vadÄ«tÄ�ja Ä�rÄ“jais diametrs speed of light gaismas Ä�trums reflection coefficient atstaroÅ¡anas koeficients standing wave ratio stÄ�vviļņa koeficients normalized impedance normalizÄ“tÄ� pretestÄ«ba frequency (Hz) frekvence (Hz) BookDock Formula Book Formulu grÄ�mata ConstantCompletion Search constants MeklÄ“t konstantes No match found Nav atrasta atbilstÄ«ba Constants Mathematics MatemÄ�tika Physics (CODATA 2022) Fizika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Ķīmija (IUPAC - CIAAW 2021) Uncategorized NekategorizÄ“ts Universal UniversÄ�lÄ�s Physicochemical FizikÄ�li Ä·Ä«miskÄ�s Atomic & Nuclear — General Atomu un kodolfizika — vispÄ�rÄ«gi Atomic & Nuclear — Electroweak Atomu un kodolfizika — elektrovÄ�jÄ� mijiedarbÄ«ba Atomic & Nuclear — Electron Atomu un kodolfizika — elektrons Atomic & Nuclear — Muon Atomu un kodolfizika — mions Atomic & Nuclear — Tau Atomu un kodolfizika — tau leptons Atomic & Nuclear — Proton Atomu un kodolfizika — protons Atomic & Nuclear — Neutron Atomu un kodolfizika — neitrons Atomic & Nuclear — Deuteron Atomu un kodolfizika — deiterons Atomic & Nuclear — Triton Atomu un kodolfizika — tritons Atomic & Nuclear — Helion Atomu un kodolfizika — helions Atomic & Nuclear — Alpha particle Atomu un kodolfizika — alfa daļiņa Atomic & Nuclear — Atomic units Atomu un kodolfizika — atomÄ�rÄ�s vienÄ«bas Atomic & Nuclear — Energy conversion relationships Atomu un kodolfizika — enerÄ£ijas pÄ�rvÄ“rÅ¡anas attiecÄ«bas Atomic & Nuclear — X-ray units Atomu un kodolfizika — rentgenstaru vienÄ«bas Atomic & Nuclear — Magnetic shielding corrections Atomu un kodolfizika — magnÄ“tiskÄ�s ekranēšanas korekcijas Masses Masas Lifetimes DzÄ«ves ilgumi Molar Masses Molmasas Electronegativity ElektronegativitÄ�te Ionization Energy JonizÄ�cijas enerÄ£ija Nominal Constants (IAU 2015) NominÄ�lÄ�s konstantes (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) PaÅ¡reizÄ“jÄ�s labÄ�kÄ�s aplÄ“ses (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) vakuuma raksturÄ«gÄ� pretestÄ«ba (Zâ‚€) reduced Planck constant (â„�) reducÄ“tÄ� Planka konstante (â„�) vacuum electric permittivity (ϵ₀) vakuuma elektriskÄ� caurlaidÄ«ba (ϵ₀) Newtonian constant of gravitation (G) Å…Å«tona gravitÄ�cijas konstante (G) vacuum magnetic permeability (μ₀) vakuuma magnÄ“tiskÄ� caurlaidÄ«ba (μ₀) Planck constant (h) Planka konstante (h) speed of light in vacuum (c) gaismas Ä�trums vakuumÄ� (c) standard acceleration of gravity (gâ‚™) standarta brÄ«vÄ�s kriÅ¡anas paÄ�trinÄ�jums (gâ‚™) Newtonian constant of gravitation over h-bar c Å…Å«tona gravitÄ�cijas konstante dalÄ«ta ar â„�c Planck length Planka garums Planck constant in eV/Hz (h) Planka konstante eV/Hz (h) Planck mass Planka masa Planck mass energy equivalent in GeV Planka masas enerÄ£ijas ekvivalents GeV Planck temperature Planka temperatÅ«ra Planck time Planka laiks reduced Planck constant in eV·s (â„�) reducÄ“tÄ� Planka konstante eV·s (â„�) reduced Planck constant times c in MeV·fm reducÄ“tÄ� Planka konstante reiz c MeV·fm Bohr magneton Bora magnetons conductance quantum (Gâ‚€) vadÄ«tspÄ“jas kvants (Gâ‚€) Coulomb constant (kâ‚‘) Kulona konstante (kâ‚‘) elementary charge (e) elementÄ�rlÄ�diņš (e) elementary charge over h-bar elementÄ�rlÄ�diņš dalÄ«ts ar â„� conventional value of Josephson constant Džozefsona konstantes konvencionÄ�lÄ� vÄ“rtÄ«ba Josephson constant Džozefsona konstante conventional value of ampere-90 ampÄ“ra-90 konvencionÄ�lÄ� vÄ“rtÄ«ba conventional value of coulomb-90 kulona-90 konvencionÄ�lÄ� vÄ“rtÄ«ba conventional value of farad-90 farada-90 konvencionÄ�lÄ� vÄ“rtÄ«ba conventional value of henry-90 henrija-90 konvencionÄ�lÄ� vÄ“rtÄ«ba conventional value of ohm-90 oma-90 konvencionÄ�lÄ� vÄ“rtÄ«ba conventional value of volt-90 volta-90 konvencionÄ�lÄ� vÄ“rtÄ«ba conventional value of watt-90 vata-90 konvencionÄ�lÄ� vÄ“rtÄ«ba magnetic flux quantum (Φ₀) magnÄ“tiskÄ�s plÅ«smas kvants (Φ₀) nuclear magneton kodola magnetons inverse of conductance quantum vadÄ«tspÄ“jas kvanta apgrieztÄ� vÄ“rtÄ«ba conventional value of von Klitzing constant fon Klicinga konstantes konvencionÄ�lÄ� vÄ“rtÄ«ba von Klitzing constant fon Klicinga konstante atomic unit of magnetic dipole moment atomÄ�rÄ� magnÄ“tiskÄ� dipola momenta vienÄ«ba atomic unit of magnetic flux density atomÄ�rÄ� magnÄ“tiskÄ�s plÅ«smas blÄ«vuma vienÄ«ba Bohr magneton in eV/T Bora magnetons eV/T Bohr magneton in Hz/T Bora magnetons Hz/T Bohr magneton in inverse meter per tesla Bora magnetons apgrieztajos metros uz teslu Bohr magneton in K/T Bora magnetons K/T nuclear magneton in eV/T kodola magnetons eV/T nuclear magneton in inverse meter per tesla kodola magnetons apgrieztajos metros uz teslu nuclear magneton in K/T kodola magnetons K/T nuclear magneton in MHz/T kodola magnetons MHz/T Bohr radius (aâ‚€) Bora rÄ�diuss (aâ‚€) fine-structure constant (α) smalkstruktÅ«ras konstante (α) Hartree energy (Eâ‚•) HÄ�rtija enerÄ£ija (Eâ‚•) Hartree energy in eV HÄ�rtija enerÄ£ija eV quantum of circulation cirkulÄ�cijas kvants quantum of circulation times 2 cirkulÄ�cijas kvants reiz 2 Rydberg constant (R∞) Ridberga konstante (R∞) atomic mass unit-hartree relationship atommasas vienÄ«bas un HÄ�rtija attiecÄ«ba atomic mass unit-hertz relationship atommasas vienÄ«bas un herca attiecÄ«ba atomic mass unit-inverse meter relationship atommasas vienÄ«bas un apgrieztÄ� metra attiecÄ«ba atomic mass unit-joule relationship atommasas vienÄ«bas un džoula attiecÄ«ba atomic mass unit-kelvin relationship atommasas vienÄ«bas un kelvina attiecÄ«ba atomic mass unit-kilogram relationship atommasas vienÄ«bas un kilograma attiecÄ«ba atomic unit of 1st hyperpolarizability atomÄ�rÄ� pirmÄ�s hiperpolarizÄ“jamÄ«bas vienÄ«ba atomic unit of 2nd hyperpolarizability atomÄ�rÄ� otrÄ�s hiperpolarizÄ“jamÄ«bas vienÄ«ba atomic unit of charge (e) atomÄ�rÄ� lÄ�diņa vienÄ«ba (e) atomic unit of charge density atomÄ�rÄ� lÄ�diņa blÄ«vuma vienÄ«ba atomic unit of current atomÄ�rÄ� strÄ�vas vienÄ«ba atomic unit of electric dipole moment atomÄ�rÄ� elektriskÄ� dipola momenta vienÄ«ba atomic unit of electric field atomÄ�rÄ� elektriskÄ� lauka vienÄ«ba atomic unit of electric field gradient atomÄ�rÄ� elektriskÄ� lauka gradienta vienÄ«ba atomic unit of electric polarizability atomÄ�rÄ� elektriskÄ�s polarizÄ“jamÄ«bas vienÄ«ba atomic unit of electric potential atomÄ�rÄ� elektriskÄ� potenciÄ�la vienÄ«ba atomic unit of electric quadrupole moment atomÄ�rÄ� elektriskÄ� kvadrupola momenta vienÄ«ba atomic unit of action atomÄ�rÄ� darbÄ«bas vienÄ«ba atomic unit of energy atomÄ�rÄ� enerÄ£ijas vienÄ«ba atomic unit of force atomÄ�rÄ� spÄ“ka vienÄ«ba atomic unit of length atomÄ�rÄ� garuma vienÄ«ba hertz-atomic mass unit relationship herca un atommasas vienÄ«bas attiecÄ«ba hertz-electron volt relationship herca un elektronvolta attiecÄ«ba hertz-hartree relationship herca un HÄ�rtija attiecÄ«ba hertz-inverse meter relationship herca un apgrieztÄ� metra attiecÄ«ba hertz-joule relationship herca un džoula attiecÄ«ba hertz-kelvin relationship herca un kelvina attiecÄ«ba hertz-kilogram relationship herca un kilograma attiecÄ«ba hyperfine transition frequency of Cs-133 Cs-133 hipersÄ«kstruktÅ«ras pÄ�rejas frekvence inverse fine-structure constant (αâ�»Â¹) smalkstruktÅ«ras konstantes apgrieztÄ� vÄ“rtÄ«ba (αâ�»Â¹) inverse meter-atomic mass unit relationship apgrieztÄ� metra un atommasas vienÄ«bas attiecÄ«ba inverse meter-electron volt relationship apgrieztÄ� metra un elektronvolta attiecÄ«ba inverse meter-hartree relationship apgrieztÄ� metra un HÄ�rtija attiecÄ«ba inverse meter-hertz relationship apgrieztÄ� metra un herca attiecÄ«ba inverse meter-joule relationship apgrieztÄ� metra un džoula attiecÄ«ba inverse meter-kelvin relationship apgrieztÄ� metra un kelvina attiecÄ«ba inverse meter-kilogram relationship apgrieztÄ� metra un kilograma attiecÄ«ba joule-atomic mass unit relationship džoula un atommasas vienÄ«bas attiecÄ«ba joule-electron volt relationship džoula un elektronvolta attiecÄ«ba joule-hertz relationship džoula un herca attiecÄ«ba joule-hartree relationship džoula un HÄ�rtija attiecÄ«ba joule-inverse meter relationship džoula un apgrieztÄ� metra attiecÄ«ba joule-kelvin relationship džoula un kelvina attiecÄ«ba joule-kilogram relationship džoula un kilograma attiecÄ«ba kelvin-atomic mass unit relationship kelvina un atommasas vienÄ«bas attiecÄ«ba kelvin-electron volt relationship kelvina un elektronvolta attiecÄ«ba kelvin-hertz relationship kelvina un herca attiecÄ«ba kelvin-hartree relationship kelvina un HÄ�rtija attiecÄ«ba kelvin-inverse meter relationship kelvina un apgrieztÄ� metra attiecÄ«ba kelvin-joule relationship kelvina un džoula attiecÄ«ba kelvin-kilogram relationship kelvina un kilograma attiecÄ«ba kilogram-atomic mass unit relationship kilograma un atommasas vienÄ«bas attiecÄ«ba kilogram-electron volt relationship kilograma un elektronvolta attiecÄ«ba kilogram-hertz relationship kilograma un herca attiecÄ«ba kilogram-hartree relationship kilograma un HÄ�rtija attiecÄ«ba kilogram-inverse meter relationship kilograma un apgrieztÄ� metra attiecÄ«ba kilogram-joule relationship kilograma un džoula attiecÄ«ba kilogram-kelvin relationship kilograma un kelvina attiecÄ«ba lattice parameter of silicon (a) silÄ«cija režģa parametrs (a) luminous efficacy gaismas efektivitÄ�te natural unit of energy dabiskÄ� enerÄ£ijas vienÄ«ba natural unit of energy in MeV dabiskÄ� enerÄ£ijas vienÄ«ba MeV natural unit of action (â„�) dabiskÄ� darbÄ«bas vienÄ«ba (â„�) natural unit of action in eV·s dabiskÄ� darbÄ«bas vienÄ«ba eV·s natural unit of length dabiskÄ� garuma vienÄ«ba natural unit of mass dabiskÄ� masas vienÄ«ba natural unit of momentum dabiskÄ� impulsa vienÄ«ba natural unit of momentum in MeV/c dabiskÄ� impulsa vienÄ«ba MeV/c natural unit of time dabiskÄ� laika vienÄ«ba natural unit of velocity dabiskÄ� Ä�truma vienÄ«ba Rydberg constant times c in Hz Ridberga konstante reiz c Hz Rydberg constant times hc in eV Ridberga konstante reiz hc eV Rydberg constant times hc in J Ridberga konstante reiz hc J Fermi coupling constant Fermi sasaistes konstante weak mixing angle vÄ�jÄ�s mijiedarbÄ«bas sajaukÅ¡anÄ�s leņķis W to Z mass ratio W un Z masu attiecÄ«ba Thomson cross section (σₑ) Tomsona šķērsgriezums (σₑ) electron mass (mâ‚‘) elektrona masa (mâ‚‘) electron mass in u elektrona masa vienÄ«bÄ�s u electron mass energy equivalent (mₑ·c²) elektrona masas enerÄ£ijas ekvivalents (mₑ·c²) electron mass energy equivalent in MeV elektrona masas enerÄ£ijas ekvivalents MeV reduced Compton wavelength reducÄ“tais Komptona viļņa garums classical electron radius (râ‚‘) klasiskais elektrona rÄ�diuss (râ‚‘) electron charge to mass quotient elektrona lÄ�diņa un masas attiecÄ«ba electron-deuteron magnetic moment ratio elektrona un deiterona magnÄ“tisko momentu attiecÄ«ba electron-deuteron mass ratio elektrona un deiterona masu attiecÄ«ba electron g factor (gâ‚‘) elektrona g faktors (gâ‚‘) electron gyromagnetic ratio (γₑ) elektrona giromagnÄ“tiskÄ� attiecÄ«ba (γₑ) electron gyromagnetic ratio in MHz/T elektrona giromagnÄ“tiskÄ� attiecÄ«ba MHz/T electron-helion mass ratio elektrona un heliona masu attiecÄ«ba electron magnetic moment (μₑ) elektrona magnÄ“tiskais moments (μₑ) electron magnetic moment anomaly (aâ‚‘) elektrona magnÄ“tiskÄ� momenta anomÄ�lija (aâ‚‘) electron magnetic moment to Bohr magneton ratio elektrona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba electron magnetic moment to nuclear magneton ratio elektrona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba electron molar mass (Mâ‚‘) elektrona molmasa (Mâ‚‘) electron-muon magnetic moment ratio elektrona un miona magnÄ“tisko momentu attiecÄ«ba electron-muon mass ratio elektrona un miona masu attiecÄ«ba electron-neutron magnetic moment ratio elektrona un neitrona magnÄ“tisko momentu attiecÄ«ba electron-neutron mass ratio elektrona un neitrona masu attiecÄ«ba electron-proton magnetic moment ratio elektrona un protona magnÄ“tisko momentu attiecÄ«ba electron-proton mass ratio elektrona un protona masu attiecÄ«ba electron relative atomic mass (Ar(e)) elektrona relatÄ«vÄ� atommasa (Ar(e)) electron-tau mass ratio elektrona un tau leptona masu attiecÄ«ba electron to alpha particle mass ratio elektrona un alfa daļiņas masu attiecÄ«ba electron to shielded helion magnetic moment ratio elektrona un ekranÄ“tÄ� heliona magnÄ“tisko momentu attiecÄ«ba electron to shielded proton magnetic moment ratio elektrona un ekranÄ“tÄ� protona magnÄ“tisko momentu attiecÄ«ba electron-triton mass ratio elektrona un tritona masu attiecÄ«ba electron volt-atomic mass unit relationship elektronvolta un atommasas vienÄ«bas attiecÄ«ba electron volt-hartree relationship elektronvolta un HÄ�rtija attiecÄ«ba electron volt-hertz relationship elektronvolta un herca attiecÄ«ba electron volt-inverse meter relationship elektronvolta un apgrieztÄ� metra attiecÄ«ba electron volt-joule relationship elektronvolta un džoula attiecÄ«ba electron volt-kelvin relationship elektronvolta un kelvina attiecÄ«ba electron volt-kilogram relationship elektronvolta un kilograma attiecÄ«ba hartree-atomic mass unit relationship HÄ�rtija un atommasas vienÄ«bas attiecÄ«ba hartree-electron volt relationship HÄ�rtija un elektronvolta attiecÄ«ba muon Compton wavelength miona Komptona viļņa garums muon-electron mass ratio miona un elektrona masu attiecÄ«ba muon g factor miona g faktors muon magnetic moment miona magnÄ“tiskais moments muon magnetic moment anomaly miona magnÄ“tiskÄ� momenta anomÄ�lija muon magnetic moment to Bohr magneton ratio miona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba muon magnetic moment to nuclear magneton ratio miona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba muon mass miona masa muon mass energy equivalent miona masas enerÄ£ijas ekvivalents muon mass energy equivalent in MeV miona masas enerÄ£ijas ekvivalents MeV muon mass in u miona masa vienÄ«bÄ�s u muon molar mass miona molmasa muon-neutron mass ratio miona un neitrona masu attiecÄ«ba muon-proton magnetic moment ratio miona un protona magnÄ“tisko momentu attiecÄ«ba muon-proton mass ratio miona un protona masu attiecÄ«ba muon-tau mass ratio miona un tau leptona masu attiecÄ«ba reduced muon Compton wavelength reduced muon Komptona viļņa garums reduced tau Compton wavelength reduced tau Komptona viļņa garums tau Compton wavelength tau leptona Komptona viļņa garums tau-electron mass ratio tau leptona un elektrona masu attiecÄ«ba tau mass tau leptona masa tau mass energy equivalent tau leptona masas enerÄ£ijas ekvivalents tau mass in u tau leptona masa vienÄ«bÄ�s u tau molar mass tau leptona molmasa tau-muon mass ratio tau leptona un miona masu attiecÄ«ba tau-neutron mass ratio tau leptona un neitrona masu attiecÄ«ba tau-proton mass ratio tau leptona un protona masu attiecÄ«ba proton charge to mass quotient protona lÄ�diņa un masas attiecÄ«ba proton Compton wavelength protona Komptona viļņa garums proton-electron mass ratio protona un elektrona masu attiecÄ«ba proton g factor (gₚ) protona g faktors (gₚ) proton gyromagnetic ratio (γₚ) protona giromagnÄ“tiskÄ� attiecÄ«ba (γₚ) proton gyromagnetic ratio in MHz/T protona giromagnÄ“tiskÄ� attiecÄ«ba MHz/T proton magnetic moment (μₚ) protona magnÄ“tiskais moments (μₚ) proton magnetic moment to Bohr magneton ratio protona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba proton magnetic moment to nuclear magneton ratio protona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba proton magnetic shielding correction protona magnÄ“tiskÄ�s ekranēšanas korekcija proton mass (mₚ) protona masa (mₚ) proton mass energy equivalent protona masas enerÄ£ijas ekvivalents proton mass energy equivalent in MeV protona masas enerÄ£ijas ekvivalents MeV proton mass in u protona masa vienÄ«bÄ�s u proton molar mass (Mₚ) protona molmasa (Mₚ) proton-muon mass ratio protona un miona masu attiecÄ«ba proton-neutron magnetic moment ratio protona un neitrona magnÄ“tisko momentu attiecÄ«ba proton-neutron mass ratio protona un neitrona masu attiecÄ«ba proton relative atomic mass (Ar(p)) protona relatÄ«vÄ� atommasa (Ar(p)) proton rms charge radius protona lÄ�diņa vidÄ“jais kvadrÄ�tiskais rÄ�diuss proton-tau mass ratio protona un tau leptona masu attiecÄ«ba reduced proton Compton wavelength reduced proton Komptona viļņa garums shielded proton gyromagnetic ratio ekranÄ“tÄ� protona giromagnÄ“tiskÄ� attiecÄ«ba shielded proton gyromagnetic ratio in MHz/T ekranÄ“tÄ� protona giromagnÄ“tiskÄ� attiecÄ«ba MHz/T shielded proton magnetic moment ekranÄ“tÄ� protona magnÄ“tiskais moments shielded proton magnetic moment to Bohr magneton ratio ekranÄ“tÄ� protona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba shielded proton magnetic moment to nuclear magneton ratio ekranÄ“tÄ� protona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba neutron Compton wavelength neitrona Komptona viļņa garums neutron-electron magnetic moment ratio neitrona un elektrona magnÄ“tisko momentu attiecÄ«ba neutron-electron mass ratio neitrona un elektrona masu attiecÄ«ba neutron g factor (gâ‚™) neitrona g faktors (gâ‚™) neutron gyromagnetic ratio (γₙ) neitrona giromagnÄ“tiskÄ� attiecÄ«ba (γₙ) neutron gyromagnetic ratio in MHz/T neitrona giromagnÄ“tiskÄ� attiecÄ«ba MHz/T neutron magnetic moment (μₙ) neitrona magnÄ“tiskais moments (μₙ) neutron magnetic moment to Bohr magneton ratio neitrona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba neutron magnetic moment to nuclear magneton ratio neitrona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba neutron mass (mâ‚™) neitrona masa (mâ‚™) neutron mass energy equivalent neitrona masas enerÄ£ijas ekvivalents neutron mass energy equivalent in MeV neitrona masas enerÄ£ijas ekvivalents MeV neutron mass in u neitrona masa vienÄ«bÄ�s u neutron molar mass (Mâ‚™) neitrona molmasa (Mâ‚™) neutron-muon mass ratio neitrona un miona masu attiecÄ«ba neutron-proton magnetic moment ratio neitrona un protona magnÄ“tisko momentu attiecÄ«ba neutron-proton mass difference neitrona un protona masu starpÄ«ba neutron-proton mass difference energy equivalent neitrona un protona masu starpÄ«bas enerÄ£ijas ekvivalents neutron-proton mass difference energy equivalent in MeV neitrona un protona masu starpÄ«bas enerÄ£ijas ekvivalents MeV neutron-proton mass difference in u neitrona un protona masu starpÄ«ba vienÄ«bÄ�s u neutron-proton mass ratio neitrona un protona masu attiecÄ«ba neutron relative atomic mass (Ar(n)) neitrona relatÄ«vÄ� atommasa (Ar(n)) neutron-tau mass ratio neitrona un tau leptona masu attiecÄ«ba neutron to shielded proton magnetic moment ratio neitrona un ekranÄ“tÄ� protona magnÄ“tisko momentu attiecÄ«ba reduced neutron Compton wavelength reduced neutron Komptona viļņa garums deuteron-electron magnetic moment ratio deiterona un elektrona magnÄ“tisko momentu attiecÄ«ba deuteron-electron mass ratio deiterona un elektrona masu attiecÄ«ba deuteron g factor deiterona g faktors deuteron magnetic moment deiterona magnÄ“tiskais moments deuteron magnetic moment to Bohr magneton ratio deiterona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba deuteron magnetic moment to nuclear magneton ratio deiterona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba deuteron mass deiterona masa deuteron mass energy equivalent deiterona masas enerÄ£ijas ekvivalents deuteron mass energy equivalent in MeV deiterona masas enerÄ£ijas ekvivalents MeV deuteron mass in u deiterona masa vienÄ«bÄ�s u deuteron molar mass deiterona molmasa deuteron-neutron magnetic moment ratio deiterona un neitrona magnÄ“tisko momentu attiecÄ«ba deuteron-proton magnetic moment ratio deiterona un protona magnÄ“tisko momentu attiecÄ«ba deuteron-proton mass ratio deiterona un protona masu attiecÄ«ba deuteron relative atomic mass (Ar(d)) deiterona relatÄ«vÄ� atommasa (Ar(d)) deuteron rms charge radius deiterona lÄ�diņa vidÄ“jais kvadrÄ�tiskais rÄ�diuss triton-electron mass ratio tritona un elektrona masu attiecÄ«ba triton g factor (gₜ) tritona g faktors (gₜ) triton magnetic moment (μₜ) tritona magnÄ“tiskais moments (μₜ) triton magnetic moment to Bohr magneton ratio tritona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba triton magnetic moment to nuclear magneton ratio tritona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba triton mass (mₜ) tritona masa (mₜ) triton mass energy equivalent tritona masas enerÄ£ijas ekvivalents triton mass energy equivalent in MeV tritona masas enerÄ£ijas ekvivalents MeV triton mass in u tritona masa vienÄ«bÄ�s u triton molar mass (Mₜ) tritona molmasa (Mₜ) triton-proton mass ratio tritona un protona masu attiecÄ«ba triton relative atomic mass (Ar(t)) tritona relatÄ«vÄ� atommasa (Ar(t)) triton to proton magnetic moment ratio tritona un protona magnÄ“tisko momentu attiecÄ«ba helion-electron mass ratio heliona un elektrona masu attiecÄ«ba helion g factor (gâ‚•) heliona g faktors (gâ‚•) helion magnetic moment (μₕ) heliona magnÄ“tiskais moments (μₕ) helion magnetic moment to Bohr magneton ratio heliona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba helion magnetic moment to nuclear magneton ratio heliona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba helion mass (mâ‚•) heliona masa (mâ‚•) helion mass energy equivalent heliona masas enerÄ£ijas ekvivalents helion mass energy equivalent in MeV heliona masas enerÄ£ijas ekvivalents MeV helion mass in u heliona masa vienÄ«bÄ�s u helion molar mass (Mâ‚•) heliona molmasa (Mâ‚•) helion-proton mass ratio heliona un protona masu attiecÄ«ba helion relative atomic mass (Ar(h)) heliona relatÄ«vÄ� atommasa (Ar(h)) helion shielding shift heliona ekranēšanas nobÄ«de shielded helion gyromagnetic ratio ekranÄ“tÄ� heliona giromagnÄ“tiskÄ� attiecÄ«ba shielded helion gyromagnetic ratio in MHz/T ekranÄ“tÄ� heliona giromagnÄ“tiskÄ� attiecÄ«ba MHz/T shielded helion magnetic moment ekranÄ“tÄ� heliona magnÄ“tiskais moments shielded helion magnetic moment to Bohr magneton ratio ekranÄ“tÄ� heliona magnÄ“tiskÄ� momenta un Bora magnetona attiecÄ«ba shielded helion magnetic moment to nuclear magneton ratio ekranÄ“tÄ� heliona magnÄ“tiskÄ� momenta un kodola magnetona attiecÄ«ba shielded helion to proton magnetic moment ratio ekranÄ“tÄ� heliona un protona magnÄ“tisko momentu attiecÄ«ba shielded helion to shielded proton magnetic moment ratio ekranÄ“tÄ� heliona un ekranÄ“tÄ� protona magnÄ“tisko momentu attiecÄ«ba alpha particle mass alfa daļiņas masa alpha particle mass in u alfa daļiņas masa vienÄ«bÄ�s u alpha particle mass energy equivalent alfa daļiņas masas enerÄ£ijas ekvivalents alpha particle mass energy equivalent in MeV alfa daļiņas masas enerÄ£ijas ekvivalents MeV alpha particle-electron mass ratio alfa daļiņas un elektrona masu attiecÄ«ba alpha particle-proton mass ratio alfa daļiņas un protona masu attiecÄ«ba alpha particle rms charge radius alfa daļiņas lÄ�diņa vidÄ“jais kvadrÄ�tiskais rÄ�diuss alpha particle molar mass alfa daļiņas molmasa alpha particle relative atomic mass (Ar(α)) alfa daļiņas relatÄ«vÄ� atommasa (Ar(α)) atomic mass constant (mᵤ) atommasas konstante (mᵤ) Avogadro constant Avogadro konstante Boltzmann constant (k) Bolcmaņa konstante (k) Boltzmann constant in eV/K Bolcmaņa konstante eV/K Boltzmann constant in Hz/K Bolcmaņa konstante Hz/K Boltzmann constant in inverse meter per kelvin Bolcmaņa konstante apgrieztajos metros uz kelvinu electron volt (eV) elektronvolts (eV) Faraday constant (F) Faradeja konstante (F) first radiation constant (câ‚�) pirmÄ� starojuma konstante (câ‚�) first radiation constant for spectral radiance pirmÄ� starojuma konstante spektrÄ�lajam starojumam molar gas constant (R) molÄ�rÄ� gÄ�zu konstante (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) LoÅ¡mita konstante (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) LoÅ¡mita konstante (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molÄ�rÄ� Planka konstante second radiation constant (câ‚‚) otrÄ� starojuma konstante (câ‚‚) Stefan-Boltzmann constant (σ) Stefana-Bolcmaņa konstante (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ideÄ�la Si režģa atstatums (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atommasas konstantes enerÄ£ijas ekvivalents atomic mass constant energy equivalent in MeV atommasas konstantes enerÄ£ijas ekvivalents MeV atomic mass unit-electron volt relationship atommasas vienÄ«bas un elektronvolta attiecÄ«ba molar mass constant (Mᵤ) molmasas konstante (Mᵤ) molar mass of carbon-12 oglekļa-12 molmasa molar volume of ideal gas (273.15 K, 100 kPa) ideÄ�las gÄ�zes molÄ�rais tilpums (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ideÄ�las gÄ�zes molÄ�rais tilpums (273.15 K, 101.325 kPa) molar volume of silicon silÄ«cija molÄ�rais tilpums Sackur-Tetrode constant (1 K, 100 kPa) ZakÅ«ra-Tetrodes konstante (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) ZakÅ«ra-Tetrodes konstante (1 K, 101.325 kPa) Wien frequency displacement law constant VÄ«na frekvences nobÄ«des likuma konstante Wien wavelength displacement law constant VÄ«na viļņa garuma nobÄ«des likuma konstante standard atmosphere (atm) standarta atmosfÄ“ra (atm) standard-state pressure (p°) standartstÄ�vokļa spiediens (p°) Angstrom star (Ã…*) AngstrÄ“ma zvaigzne (Ã…*) Copper x unit vara x vienÄ«ba Molybdenum x unit molibdÄ“na x vienÄ«ba atomic unit of magnetizability atomÄ�rÄ� magnetizÄ“jamÄ«bas vienÄ«ba atomic unit of mass (mâ‚‘) atomÄ�rÄ� masas vienÄ«ba (mâ‚‘) atomic unit of momentum atomÄ�rÄ� impulsa vienÄ«ba atomic unit of permittivity atomÄ�rÄ� elektriskÄ�s caurlaidÄ«bas vienÄ«ba atomic unit of time atomÄ�rÄ� laika vienÄ«ba atomic unit of velocity atomÄ�rÄ� Ä�truma vienÄ«ba hartree-hertz relationship HÄ�rtija un herca attiecÄ«ba hartree-inverse meter relationship HÄ�rtija un apgrieztÄ� metra attiecÄ«ba hartree-joule relationship HÄ�rtija un džoula attiecÄ«ba hartree-kelvin relationship HÄ�rtija un kelvina attiecÄ«ba hartree-kilogram relationship HÄ�rtija un kilograma attiecÄ«ba shielding difference of d and p in HD d un p ekranēšanas starpÄ«ba HD shielding difference of t and p in HT t un p ekranēšanas starpÄ«ba HT pi (Ï€) pÄ« (Ï€) Euler's number (e) Eilera skaitlis (e) golden ratio (φ) zelta griezums (φ) Euler-Mascheroni constant (γ) Eilera-Maskeroni konstante (γ) nominal solar radius nominÄ�lais Saules rÄ�diuss nominal solar total irradiance nominÄ�lais Saules kopÄ“jais apstarojums nominal solar luminosity nominÄ�lÄ� Saules starjauda nominal solar effective temperature nominÄ�lÄ� Saules efektÄ«vÄ� temperatÅ«ra nominal solar mass parameter nominÄ�lais Saules masas parametrs nominal terrestrial equatorial radius nominÄ�lais Zemes ekvatoriÄ�lais rÄ�diuss nominal terrestrial polar radius nominÄ�lais Zemes polÄ�rais rÄ�diuss nominal terrestrial mass parameter nominÄ�lais Zemes masas parametrs nominal jovian equatorial radius nominÄ�lais Jupitera ekvatoriÄ�lais rÄ�diuss nominal jovian polar radius nominÄ�lais Jupitera polÄ�rais rÄ�diuss nominal jovian mass parameter nominÄ�lais Jupitera masas parametrs average value of one minus the rate of TCG relative to TCB vidÄ“jÄ� vÄ“rtÄ«ba vienam mÄ«nus TCG Ä�trums attiecÄ«bÄ� pret TCB solar mass parameter (TCB-compatible) Saules masas parametrs (TCB-compatible) solar mass parameter (TDB-compatible) Saules masas parametrs (TDB-compatible) equatorial radius of the Earth (TT-compatible) Zemes ekvatoriÄ�lais rÄ�diuss (TT-compatible) dynamical form factor of the Earth Zemes dinamiskais formas faktors time rate of change in the dynamical form factor of the Earth Zemes dinamiskÄ� formas faktora izmaiņas Ä�trums geocentric gravitational constant (TCB-compatible) Ä£eocentriskÄ� gravitÄ�cijas konstante (TCB-compatible) geocentric gravitational constant (TT-compatible) Ä£eocentriskÄ� gravitÄ�cijas konstante (TT-compatible) geocentric gravitational constant (TDB-compatible) Ä£eocentriskÄ� gravitÄ�cijas konstante (TDB-compatible) potential of the geoid Ä£eoÄ«da potenciÄ�ls nominal mean angular velocity of the Earth (TT-compatible) Zemes nominÄ�lais vidÄ“jais leņķiskais Ä�trums (TT-compatible) ratio mass of the Moon to the Earth MÄ“ness un Zemes masu attiecÄ«ba ratio of the mass of the Sun to Mercury Saules un Merkura masu attiecÄ«ba ratio of the mass of the Sun to Venus Saules un VenÄ“ras masu attiecÄ«ba ratio of the mass of the Sun to Mars Saules un Marsa masu attiecÄ«ba ratio of the mass of the Sun to Jupiter Saules un Jupitera masu attiecÄ«ba ratio of the mass of the Sun to Saturn Saules un Saturna masu attiecÄ«ba ratio of the mass of the Sun to Uranus Saules un UrÄ�na masu attiecÄ«ba ratio of the mass of the Sun to Neptune Saules un NeptÅ«na masu attiecÄ«ba ratio of the mass of the Sun to (134340) Pluto Saules un (134340) Plutona masu attiecÄ«ba ratio of the mass of the Sun to (136199) Eris Saules un (136199) ErÄ«das masu attiecÄ«ba ratio of the mass of (1) Ceres to the Sun (1) CerÄ“ras un Saules masu attiecÄ«ba ratio of the mass of (2) Pallas to the Sun (2) PallÄ�das un Saules masu attiecÄ«ba ratio of the mass of (4) Vesta to the Sun (4) Vestas un Saules masu attiecÄ«ba mean obliquity of the ecliptic at J2000.0 ekliptikas vidÄ“jais slÄ«pums J2000.0 laikmetÄ� Electromagnetic ElektromagnÄ“tiskais Compton wavelength Komptona viļņa garums Astronomy Astronomija ConstantsWidget Domain Joma Subdomain ApakÅ¡joma No match found Nav atrasta atbilstÄ«ba Name Nosaukums Value VÄ“rtÄ«ba Unit VienÄ«ba Search MeklÄ“t All Visi CustomKeypadDialog Custom Keypad PielÄ�gota tastatÅ«ra Rows: Rindas: Columns: Kolonnas: Copy preset: KopÄ“t priekÅ¡iestatÄ«jumu: Basic Pamata Scientific (wide) ZinÄ�tniskÄ� (plata) Scientific (narrow) ZinÄ�tniskÄ� (Å¡aura) Apply Lietot Row Rinda Column Kolonna Label EtiÄ·ete Behavior DarbÄ«ba Text Teksts DiagnosticsDialog App Diagnostics Lietotnes diagnostika Copy to Clipboard KopÄ“t starpliktuvÄ“ Editor Unit VienÄ«ba User unit LietotÄ�ja vienÄ«ba User function LietotÄ�ja funkcija Argument Arguments Current result:<br/>%1 PaÅ¡reizÄ“jais rezultÄ�ts:<br/>%1 Selection result:<br/>%1 Atlases rezultÄ�ts:<br/>%1 Selection result: n/a Atlases rezultÄ�ts: n/p Selection result: %1 Atlases rezultÄ�ts: %1 second sekunde metre metrs kilogram kilograms mole mols radian radiÄ�ns steradian steradiÄ�ns degree Celsius Celsija grÄ�ds cubic metre kubikmetrs cubic millimetre kubikmilimetrs cubic centimetre kubikcentimetrs cubic decimetre kubikdecimetrs cubic kilometre kubikkilometrs square millimetre kvadrÄ�tmilimetrs square kilometre kvadrÄ�tkilometrs square metre kvadrÄ�tmetrs minute minÅ«te hour stunda day diena astronomical unit astronomiskÄ� vienÄ«ba degree grÄ�ds arcminute loka minÅ«te arcsecond loka sekunde milliarcsecond loka milisekunde microarcsecond loka mikrosekunde hectare hektÄ�rs litre litrs tonne tonna Dalton daltons electronvolt elektronvolts Angstrom angstrÄ“ms atmosphere atmosfÄ“ra atomic mass unit atommasas vienÄ«ba British thermal unit britu termiskÄ� vienÄ«ba calorie kalorija carat karÄ�ts cup tase cup (Imperial) tase (britu) cup (Japanese) tase (japÄ�ņu) cup (US) tase (ASV) degree Fahrenheit FÄ�renheita grÄ�ds fathom fatoms fluid ounce (Imperial) šķidruma unce (britu) fluid ounce (US) šķidruma unce (ASV) fluid dram (Imperial) šķidruma drahma (britu) fluid dram (US) šķidruma drahma (ASV) foot pÄ“da square foot kvadrÄ�tpÄ“da cubic foot kubikpÄ“da gallon (Imperial) galons (britu) gallon (US) galons (ASV) gill (Imperial) džila (britu) gill (US) džila (ASV) gradian gradians grain greins gram grams Hartley hartlijs Hartree energy unit HÄ�rtija enerÄ£ijas vienÄ«ba horsepower zirgspÄ“ks inch colla square inch kvadrÄ�tcolla cubic inch kubikcolla karat karÄ�ts knot mezgls lightminute gaismas minÅ«te lightsecond gaismas sekunde lightyear gaismas gads long ton garÄ� tonna mile jÅ«dze square mile kvadrÄ�tjÅ«dze cubic mile kubikjÅ«dze mile per hour jÅ«dze stundÄ� kilometre per hour kilometrs stundÄ� nautical mile jÅ«ras jÅ«dze ounce unce parsec parseks pint (Imperial) pinte (britu) pint (US) pinte (ASV) pound mÄ�rciņa pounds per square inch mÄ�rciņas uz kvadrÄ�tcollu quart (Imperial) kvarta (britu) quart (US) kvarta (ASV) oil barrel naftas barels beer barrel (US) alus barels (ASV) square yard kvadrÄ�tjards cubic yard kubikjards short ton Ä«sÄ� tonna tablespoon Ä“damkarote tablespoon (Australian) Ä“damkarote (AustrÄ�lijas) tablespoon (Imperial) Ä“damkarote (britu) tablespoon (US) Ä“damkarote (ASV) dessert spoon deserta karote teaspoon tÄ“jkarote teaspoon (Imperial) tÄ“jkarote (britu) teaspoon (US) tÄ“jkarote (ASV) turn apgrieziens revolution apgrieziens revolution per minute apgriezieni minÅ«tÄ“ week nedēļa kilowatt hour kilovatstunda millimetre of mercury dzÄ«vsudraba staba milimetrs yard jards Julian century JÅ«lija gadsimts Julian year JÅ«lija gads sidereal year zvaigžņu gads tropical year tropiskais gads Evaluator invalid expression nederÄ«ga izteiksme division by zero dalÄ«jums ar nulli too time consuming - computation was rejected pÄ�rÄ�k laikietilpÄ«gi — aprēķins tika noraidÄ«ts dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensiju neatbilstÄ«ba — lielumus ar dažÄ�dÄ�m dimensijÄ�m nevar salÄ«dzinÄ�t, saskaitÄ«t u. tml. invalid dimension - operation might require dimensionless arguments nederÄ«ga dimensija — operÄ�cijai var bÅ«t nepiecieÅ¡ami bezdimensionÄ�li argumenti Computation aborted - encountered numerical instability Aprēķins pÄ�rtraukts — konstatÄ“ta skaitliska nestabilitÄ�te invalid dimension - function might require dimensionless arguments nederÄ«ga dimensija — funkcijai var bÅ«t nepiecieÅ¡ami bezdimensionÄ�li argumenti error kļūda unit must not be zero vienÄ«ba nedrÄ«kst bÅ«t nulle Conversion failed - dimension mismatch PÄ�rveidoÅ¡ana neizdevÄ�s — dimensiju neatbilstÄ«ba unknown function or variable nezinÄ�ma funkcija vai mainÄ«gais recursion not supported rekursija netiek atbalstÄ«ta cannot operate on a NaN nevar darboties ar ne-skaitļiem underflow - tiny result is out of SpeedCrunch's number range rezultÄ�ts ir pÄ�rÄ�k mazs - Ä�rpus SpeedCrunch skaitļu diapazona overflow - huge result is out of SpeedCrunch's number range rezultÄ�ts ir pÄ�rÄ�k liels - Ä�rpus SpeedCrunch skaitļu diapazona overflow - logic result exceeds maximum of 256 bits loÄ£iskÄ� izteiksme pÄ�rsniedz maksimÄ�li atļautos 256 bitus overflow - integer result exceeds maximum limit for integers rezultÄ�ts pÄ�rsniedz veselo skaitļu maksimumu operation is not defined for these arguments operÄ�cija Å¡iem argumentiem nav definÄ“ta wrong number of arguments nepareizs argumentu skaits does not take NaN as an argument nepieņem NaN kÄ� argumentu result out of range rezultÄ�ts ir Ä�rpus diapazona undefined for argument domain nav definÄ“ts argumenta apgabalÄ� computation too expensive aprēķins ir pÄ�rÄ�k dÄ�rgs internal error, please report a bug iekšēja kļūda; lÅ«dzu, ziņojiet par kļūdu syntax error sintakses kļūda conversion target must be a unit pÄ�rveidoÅ¡anas mÄ“rÄ·im jÄ�bÅ«t vienÄ«bai unknown unit nezinÄ�ma vienÄ«ba %1 is a reserved name, please choose another %1 ir rezervÄ“ts nosaukums, lÅ«dzu izvÄ“lies citu %1 is a global user definition and cannot be overridden in this session. %1 ir globÄ�la lietotÄ�ja definÄ«cija, un Å¡ajÄ� sesijÄ� to nevar pÄ�rrakstÄ«t. %1 is a variable name, please choose another or delete the variable %1 ir mainÄ«gÄ� nosaukums; izvÄ“lieties citu vai dzÄ“siet Å¡o mainÄ«go argument %1 is used more than once arguments %1 tiek izmantots vairÄ�k nekÄ� vienu reizi %1 is a built-in unit name, please choose another %1 ir iebÅ«vÄ“tas vienÄ«bas nosaukums; izvÄ“lieties citu %1 is a user function name, please choose another or delete the function %1 ir lietotÄ�ja funkcijas nosaukums; izvÄ“lieties citu vai dzÄ“siet Å¡o funkciju FunctionRepo max; trials; probability maksimums; mēģinÄ�jumi; varbÅ«tÄ«ba trials; probability mēģinÄ�jumi; varbÅ«tÄ«ba hits; trials; probability trÄ�pÄ«jumi; mēģinÄ�jumi; varbÅ«tÄ«ba max; total; hits; trials maksimums; kopskaits; trÄ�pÄ«jumi; mēģinÄ�jumi total; hits; trials kopskaits; trÄ�pÄ«jumi; mēģinÄ�jumi count; total; hits; trials skaits; kopskaits; trÄ�pÄ«jumi; mēģinÄ�jumi dividend; divisor dalÄ�mais; dalÄ«tÄ�js x; exponent_bits; significand_bits [; exponent_bias] x; eksponenta biti; mantisas biti [; eksponenta nobÄ«de] base; x bÄ�ze; x value; modulo vÄ“rtÄ«ba; modulis base; exponent; modulo bÄ�ze; kÄ�pinÄ�tÄ�js; modulis events; average_events notikumi; vidÄ“jais notikumu skaits average_events vidÄ“jais notikumu skaits x [; precision] x [; precizitÄ�te] Absolute Value AbsolÅ«tÄ� vÄ“rtÄ«ba Absolute Deviation AbsolÅ«tÄ� novirze Arc Cosine Arkuskosinuss Logical AND LoÄ£iskais UN Area Hyperbolic Cosine Apgrieztais hiperboliskais kosinuss Area Hyperbolic Sine Apgrieztais hiperboliskais sinuss Area Hyperbolic Tangent Apgrieztais hiperboliskais tangenss Arc Sine Arkussinuss Arc Tangent Arkustangenss Arc Tangent with two Arguments Arkustangenss ar diviem argumentiem Average (Arithmetic Mean) VidÄ“jÄ� vÄ“rtÄ«ba (aritmÄ“tiskais vidÄ“jais) Binomial Cumulative Distribution Function BinomiÄ�lÄ� sadalÄ«juma kumulatÄ«vÄ� sadalÄ«juma funkcija Binomial Distribution Mean BinomiÄ�lÄ� sadalÄ«juma vidÄ“jÄ� vÄ“rtÄ«ba Binomial Probability Mass Function BinomiÄ�lÄ� sadalÄ«juma varbÅ«tÄ«bas masas funkcija Binomial Distribution Variance BinomiÄ�lÄ� sadalÄ«juma dispersija Cube Root KubiskÄ� sakne Complex Conjugate Kompleksi saistÄ«tais skaitlis Cosine Kosinuss Hyperbolic Cosine Hiperboliskais kosinuss Cotangent Kotangenss Cosecant Kosekanss Convert Unix timestamp to Date PÄ�rveidot Unix laikspiedolu datumÄ� Degrees of Arc Loka grÄ�di Error Function Kļūdas funkcija Complementary Error Function KomplementÄ�rÄ� kļūdas funkcija Exponential Eksponente Fractional Part Daļveida daļa Extension of Factorials [= (x-1)!] FaktoriÄ�ļu paplaÅ¡inÄ�jums [= (x-1)!] Greatest Common Divisor LielÄ�kais kopÄ«gais dalÄ«tÄ�js Geometric Mean Ä¢eometriskais vidÄ“jais Gradians of arc Loka gradiÄ�ni Hypergeometric Cumulative Distribution Function HiperÄ£eometriskÄ� sadalÄ«juma kumulatÄ«vÄ� sadalÄ«juma funkcija Hypergeometric Distribution Mean HiperÄ£eometriskÄ� sadalÄ«juma vidÄ“jÄ� vÄ“rtÄ«ba Hypergeometric Probability Mass Function HiperÄ£eometriskÄ� sadalÄ«juma varbÅ«tÄ«bas masas funkcija Hypergeometric Distribution Variance HiperÄ£eometriskÄ� sadalÄ«juma dispersija Integer Quotient Veselais dalÄ«jums Integer Part VeselÄ� daļa Imaginary Part ImaginÄ�rÄ� daļa Decode IEEE-754 Binary Value DekodÄ“t IEEE-754 binÄ�ro vÄ“rtÄ«bu Encode IEEE-754 Binary Value KodÄ“t IEEE-754 binÄ�ro vÄ“rtÄ«bu Decode 16-bit Half-Precision Value DekodÄ“t 16 bitu pusprecizitÄ�tes vÄ“rtÄ«bu Encode 16-bit Half-Precision Value KodÄ“t 16 bitu pusprecizitÄ�tes vÄ“rtÄ«bu Decode 32-bit Single-Precision Value DekodÄ“t 32 bitu vienprecizitÄ�tes vÄ“rtÄ«bu Encode 32-bit Single-Precision Value KodÄ“t 32 bitu vienprecizitÄ�tes vÄ“rtÄ«bu Decode 64-bit Double-Precision Value DekodÄ“t 64 bitu dubultprecizitÄ�tes vÄ“rtÄ«bu Encode 64-bit Double-Precision Value KodÄ“t 64 bitu dubultprecizitÄ�tes vÄ“rtÄ«bu Decode 128-bit Quad-Precision Value DekodÄ“t 128 bitu Ä�etrkÄ�rÅ¡Ä�s precizitÄ�tes vÄ“rtÄ«bu Encode 128-bit Quad-Precision Value KodÄ“t 128 bitu Ä�etrkÄ�rÅ¡Ä�s precizitÄ�tes vÄ“rtÄ«bu Binary Logarithm BinÄ�rais logaritms Common Logarithm DecimÄ�llogaritms Natural Logarithm NaturÄ�lais logaritms Logarithm to Arbitrary Base Logaritms ar patvaļīgu bÄ�zi Mask to a bit size MaskÄ“t lÄ«dz bitu izmÄ“ram Maximum Maksimums Median Value (50th Percentile) MediÄ�na (50. procentile) Minimum Minimums Modulo Modulis Euclidean Modulo EiklÄ«da modulis Modular Exponentiation ModulÄ�rÄ� kÄ�pinÄ�Å¡ana Combination (Binomial Coefficient) KombinÄ�cija (binomiÄ�lais koeficients) Logical NOT LoÄ£iskais NE Permutation (Arrangement) PermutÄ�cija (izkÄ�rtojums) Convert to Binary Representation PÄ�rveidot binÄ�rajÄ� attÄ“lojumÄ� Arithmetic AritmÄ“tika Chemistry Ķīmija Complex Kompleksie skaitļi Combinatorics Kombinatorika Probability VarbÅ«tÄ«ba Statistics Statistika Aggregation ApkopoÅ¡ana Random Nejaušība Base conversion BÄ�zes pÄ�rveidoÅ¡ana Number formatting Skaitļu formatēšana Integer arithmetic Veselo skaitļu aritmÄ“tika Special functions SpeciÄ�lÄ�s funkcijas Exponential & Logarithmic Eksponentfunkcijas un logaritmiskÄ�s funkcijas Angle conversion Leņķu pÄ�rveidoÅ¡ana Trigonometry Trigonometrija Bitwise Bitu operÄ�cijas Floating point PeldoÅ¡ais komats Date & Time Datums un laiks Linear algebra LineÄ�rÄ� algebra unix_timestamp; x hours offset to GMT Unix laikspiedols; x stundu nobÄ«de no GMT yyyymmdd.hhmmss; x hours offset to GMT ggggmmdd.hhmmss; x stundu nobÄ«de no GMT [digits] [cipari] max [; min] maksimums [; minimums] List Literal Saraksta literÄ�lis Convert to Padded Binary Representation PÄ�rveidot papildinÄ�tÄ� binÄ�rajÄ� attÄ“lojumÄ� Round Toward +∞ (Ceiling) Noapaļot uz +∞ (griesti) Cosine plus Imaginary Sine Kosinuss plus imaginÄ�rais sinuss Convert to Cis Complex Form PÄ�rveidot cis kompleksajÄ� formÄ� Matrix Column Count Matricas kolonnu skaits Population Correlation Matrix (n) Ä¢enerÄ�lkopas korelÄ�cijas matrica (n) Sample Correlation Matrix (n-1) Izlases korelÄ�cijas matrica (n-1) Count Skaits Population Covariance Matrix (n) Ä¢enerÄ�lkopas kovariÄ�cijas matrica (n) Sample Covariance Matrix (n-1) Izlases kovariÄ�cijas matrica (n-1) Cross Product VektoriÄ�lais reizinÄ�jums Convert Date to Unix timestamp PÄ�rveidot datumu Unix laikspiedolÄ� Convert to Decimal Representation PÄ�rveidot decimÄ�lajÄ� attÄ“lojumÄ� Determinant Determinants Convert to Sexagesimal Notation PÄ�rveidot seÅ¡desmitnieku pierakstÄ� Dot Product SkalÄ�rais reizinÄ�jums Convert to Engineering Notation PÄ�rveidot inženieru pierakstÄ� Convert to Exponential Complex Form PÄ�rveidot eksponenciÄ�lajÄ� kompleksajÄ� formÄ� Round Toward −∞ (Floor) Noapaļot uz −∞ (grÄ«da) Flatten Matrix SaplacinÄ�t matricu Least Common Multiple MazÄ�kais kopÄ«gais dalÄ�mais Convert to Hexadecimal Representation PÄ�rveidot heksadecimÄ�lajÄ� attÄ“lojumÄ� Convert to Padded Hexadecimal Representation PÄ�rveidot papildinÄ�tÄ� heksadecimÄ�lajÄ� attÄ“lojumÄ� Inverse Matrix ApgrieztÄ� matrica Round to 16-bit Half-Precision Value Noapaļot uz 16 bitu pusprecizitÄ�tes vÄ“rtÄ«bu Round to 32-bit Single-Precision Value Noapaļot uz 32 bitu vienprecizitÄ�tes vÄ“rtÄ«bu Round to 64-bit Double-Precision Value Noapaļot uz 64 bitu dubultprecizitÄ�tes vÄ“rtÄ«bu Round to 128-bit Quad-Precision Value Noapaļot uz 128 bitu Ä�etrkÄ�rÅ¡Ä�s precizitÄ�tes vÄ“rtÄ«bu Residual from 16-bit Half-Precision Rounding Atlikums pÄ“c 16 bitu pusprecizitÄ�tes noapaļoÅ¡anas Residual from 32-bit Single-Precision Rounding Atlikums pÄ“c 32 bitu vienprecizitÄ�tes noapaļoÅ¡anas Residual from 64-bit Double-Precision Rounding Atlikums pÄ“c 64 bitu dubultprecizitÄ�tes noapaļoÅ¡anas Residual from 128-bit Quad-Precision Rounding Atlikums pÄ“c 128 bitu Ä�etrkÄ�rÅ¡Ä�s precizitÄ�tes noapaļoÅ¡anas Substance Mass Vielas masa Molarity MolaritÄ�te Molar Mass Molmasa Median Absolute Deviation MediÄ�nÄ� absolÅ«tÄ� novirze Mean VidÄ“jÄ� vÄ“rtÄ«ba Numerical Value of Quantity Lieluma skaitliskÄ� vÄ“rtÄ«ba Random Decimal Number NejauÅ¡s decimÄ�lskaitlis Random Integer Number NejauÅ¡s vesels skaitlis Convert to Rational Representation PÄ�rveidot racionÄ�lÄ� attÄ“lojumÄ� Convert to Octal Representation PÄ�rveidot oktÄ�lajÄ� attÄ“lojumÄ� Convert to Padded Octal Representation PÄ�rveidot papildinÄ�tÄ� oktÄ�lajÄ� attÄ“lojumÄ� Vector or Matrix Norm Vektora vai matricas norma Logical OR LoÄ£iskais VAI Population Count (Hamming Weight) IestatÄ«to bitu skaits (Heminga svars) Phase of Complex Number Kompleksa skaitļa fÄ�ze Poissonian Cumulative Distribution Function Puasona sadalÄ«juma kumulatÄ«vÄ� sadalÄ«juma funkcija Poissonian Distribution Mean Puasona sadalÄ«juma vidÄ“jÄ� vÄ“rtÄ«ba Poissonian Probability Mass Function Puasona sadalÄ«juma varbÅ«tÄ«bas masas funkcija Poissonian Distribution Variance Puasona sadalÄ«juma dispersija Convert to Phasor Complex Form PÄ�rveidot fazora kompleksajÄ� formÄ� Convert to Rectangular Complex Form PÄ�rveidot taisnleņķa kompleksajÄ� formÄ� Round Half Away from Zero Pusi noapaļot prom no nulles Round Half Even Pusi noapaļot lÄ«dz pÄ�ra skaitlim Nth Root N-tÄ�s pakÄ�pes sakne Convert to Scientific Notation PÄ�rveidot zinÄ�tniskajÄ� pierakstÄ� Matrix Row Count Matricas rindu skaits List or Matrix Shape Saraksta vai matricas forma Summation Summēšana Population Standard Deviation (n) Ä¢enerÄ�lkopas standartnovirze (n) Sample Standard Deviation (n-1) Izlases standartnovirze (n-1) Round Toward Zero (Truncation) Noapaļot uz nulli (apcirpÅ¡ana) Matrix Trace Matricas pÄ“da Transpose Matrix TransponÄ“t matricu Population Variance (n) Ä¢enerÄ�lkopas dispersija (n) Sample Variance (n-1) Izlases dispersija (n-1) Product ReizinÄ�jums Radians RadiÄ�ni Matrix Rank Matricas rangs Real Part ReÄ�lÄ� daļa Secant Sekanss Arithmetic Shift Left AritmÄ“tiskÄ� nobÄ«de pa kreisi Arithmetic Shift Right AritmÄ“tiskÄ� nobÄ«de pa labi Signum Signum Sine Sinuss Hyperbolic Sine Hiperboliskais sinuss Square Root KvadrÄ�tsakne Sum Summa Tangent Tangenss Convert to Trigonometric Complex Form PÄ�rveidot trigonometriskajÄ� kompleksajÄ� formÄ� Turns Apgriezieni Hyperbolic Tangent Hiperboliskais tangenss Sign-extend a value PaplaÅ¡inÄ�t vÄ“rtÄ«bu ar zÄ«mes bitu Logical XOR LoÄ£iskais XOR FunctionsWidget Domain Joma All Visi Name Nosaukums Search MeklÄ“t No match found Nav atrasta atbilstÄ«ba Identifier Identifikators HistoryWidget Remove All Calculations Above Noņemt visus aprēķinus augstÄ�k Remove This Calculation Noņemt Å¡o aprēķinu Remove All Calculations Below Noņemt visus aprēķinus zemÄ�k Keypad Inverse cosine Inversais kosinuss The last result PÄ“dejais rezultÄ�ts Inverse sine Inversais sinuss Inverse tangent Inversais tangenss Evaluate expression AprēķinÄ�t izteiksmi Division Dalīšana Multiplication ReizinÄ�Å¡ana Subtraction AtņemÅ¡ana Addition Saskaitīšana Clear expression NotÄ«rÄ«t izteiksmi Cosine Kosinuss Backspace AtpakaļatkÄ�pe Scientific notation ZinÄ�tniskÄ� notÄ�cija Exponential Eksponente Factorial FaktoriÄ�lis Natural logarithm NaturÄ�lais logaritms Left parenthesis KreisÄ� iekava Nth root N-tÄ�s pakÄ�pes sakne Argument separator Argumentu atdalÄ«tÄ�js Square KvadrÄ�ts Common logarithm DecimÄ�llogaritms Modulo Modulis Contextual percentage KontekstuÄ�lais procents Power KÄ�pinÄ�Å¡ana Right parenthesis LabÄ� iekava Sine Sinuss Square root KvadrÄ�tsakne Tangent Tangenss Pi PÄ« Decimal separator DecimÄ�latdalÄ«tÄ�js MainWindow Radian RadiÄ�ni Degree GrÄ�di Gradian Gradians Binary BinÄ�rais Octal OktÄ�lais Hexadecimal HeksadecimÄ�lais Sexagesimal SeÅ¡desmitnieku Engineering decimal Inženieru decimÄ�lformÄ�ts Scientific decimal ZinÄ�tniskais decimÄ�lformÄ�ts &Import... &ImportÄ“t... &Quit &Iziet Clear E&xpression NodzÄ“st i&zteiksmi Clear &History NodzÄ“st &vÄ“sturi &Copy &KopÄ“t &Paste &IelÄ«mÄ“t &Select Expression &IzvÄ“lÄ“ties izteiksmi &Constants &Konstantes &Functions &Funkcijas &History &VÄ“sture &Status Bar &Statusa josla Bitfield Bitu lauks Use&r Functions LietotÄ�ja &funkcijas &Degree &GrÄ�di &Radian &RadiÄ�ni &Gradian &Gradians Re&volution A&pgrieziens Auto-Insert a&ns AutomÄ�tiski ievietot a&ns Automatic &Completion AutomÄ�tiskÄ� &pabeigÅ¡ana &Built-in Functions Ie&bÅ«vÄ“tÄ�s funkcijas Built-in &Variables &IebÅ«vÄ“tie mainÄ«gie User &Functions LietotÄ�ja &funkcijas User Va&riables &LietotÄ�ja mainÄ«gie Open a Private Tab on Startup StartÄ“jot atvÄ“rt privÄ�tu cilni Open and focus a new private tab whenever SpeedCrunch starts. KatrÄ� SpeedCrunch palaiÅ¡anas reizÄ“ atvÄ“rt un aktivizÄ“t jaunu privÄ�tu cilni. Syntax &Highlighting Sintakses &iezÄ«mēšana Group Digits in &Input GrupÄ“t &ievades ciparus Automatic Input &Adjustments &AutomÄ�tiska ievades pielÄ�goÅ¡ana Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. AutomÄ�tiski pielÄ�got operatorus, atstarpes, iekavas un pakÄ�pes un atļaut ievadÄ«t tikai derÄ«gas rakstzÄ«mes. Group input digits using the selected number format. GrupÄ“t ievadÄ«tos ciparus atbilstoÅ¡i izvÄ“lÄ“tajam skaitļu formÄ�tam. &Blinking Cursor &MirgojoÅ¡s kursors Blink the cursor in the expression editor. IeslÄ“gt kursora mirgoÅ¡anu izteiksmju redaktorÄ�. &Escape Clears Editor &Escape notÄ«ra redaktoru Clear the focused expression editor with Escape after dismissing any popup or preview. NotÄ«rÄ«t aktÄ«vo izteiksmju redaktoru ar Escape pÄ“c uznirstoÅ¡o logu vai priekÅ¡skatÄ«jumu aizvÄ“rÅ¡anas. Keep Expression After Evaluation PaturÄ“t izteiksmi pÄ“c aprēķina Copy New Results Automatically AutomÄ�tiski kopÄ“t jaunus rezultÄ�tus &Comma &Komats &System Default &SistÄ“mas noklusÄ“tais &Dot &Punkts Dot &And Comma Punkts &un komats Toward +∞ (&ceil) VirzienÄ� uz +∞ (&ceil) Toward −∞ (&floor) VirzienÄ� uz −∞ (&floor) &Binary &BinÄ�rais &Engineering &Inžinierijas &Hexadecimal &HeksadecimÄ�lais &Octal &OktÄ�lais &Scientific &ZinÄ�tniskais User &Manual LietotÄ�ja &rokasgrÄ�mata Issues and &Feedback &ProblÄ“mas un atsauksmes &Donate &Ziedot &About SpeedCrunch Par &SpeedCrunch App Diag&nostics Lietot&nes diagnostika S&plit S&adalÄ«t Angle &Mode Leņķu režī&ms &Complex Form &KompleksÄ� forma New Tab Jauna cilne Constants Konstantes Functions Funkcijas History VÄ“sture User Functions LietotÄ�ja funkcijas &Font... &Fonts... &Language... &Valoda... &Session &Projekts &Edit &Rediģēt &View &Skats Se&ttings R&Ä«ki &Decimal &DecimÄ�lais &Keypad &TastatÅ«ra Always on &Top VienmÄ“r &virspusÄ“ Disabled AtspÄ“jots Small Space Maza atstarpe Medium Space VidÄ“ja atstarpe Large Space Liela atstarpe &0 Digits &0 cipari &15 Digits &15 cipari &2 Digits &2 cipari &3 Digits &3 cipari &50 Digits &50 cipari &8 Digits &8 cipari &Sexagesimal &SeÅ¡desmitnieku Reset All Settings... AtiestatÄ«t visus iestatÄ«jumus... &System &SistÄ“ma SpeedCrunch &Theme SpeedCrunch mo&tÄ«vs &Classic &Klasisks &Modern &MÅ«sdienÄ«gs Context Help Konteksta palÄ«dzÄ«ba &Help &PalÄ«dzÄ«ba Error Kļūda Can't read from file %1 Nevar nolasÄ«t failu %1 Import Session ImportÄ“t sesiju Close Session AizvÄ“rt sesiju Angle Mode: Leņķa režīms: Notation: Pieraksts: Precision: PrecizitÄ�te: Turn Apgrieziens Revolution Apgrieziens Fixed-point decimal FiksÄ“tÄ� punkta decimÄ�lformÄ�ts Rational RacionÄ�ls Automatic decimal AutomÄ�tisks decimÄ�lformÄ�ts Automatic AutomÄ�tiski User &Definitions... LietotÄ�ja &definÄ«cijas... New &Tab Jauna &cilne New &Private Tab Jauna &privÄ�ta cilne Keep PaturÄ“t Make Private... PadarÄ«t privÄ�tu... New &Window Jauns &logs &Open... &AtvÄ“rt... &Rename... PÄ�&rdÄ“vÄ“t... Clo&ne... Klo&nÄ“t... &Close Tab Ai&zvÄ“rt cilni Reopen Clo&sed Tab A&tvÄ“rt aizvÄ“rto cilni vÄ“lreiz Open Sessions &Folder AtvÄ“rt sesiju &mapi &Undo Atsa&ukt &Redo &Atcelt atsaukÅ¡anu Cu&t Izgriez&t Copy &Last Result KopÄ“t pÄ“dÄ“jo rezu&ltÄ�tu &Wrap in Parentheses I&ekļaut iekavÄ�s Full Scr&een Mode Piln&ekrÄ�na režīms &Basic &Pamata &Scientific (wide) &ZinÄ�tniskÄ� (plata) Scientific (narrow) ZinÄ�tniskÄ� (Å¡aura) &Custom... &PielÄ�gots... Main &Menu GalvenÄ� &izvÄ“lne User &Variables LietotÄ�ja &mainÄ«gie &Left &Pa kreisi &Right P&a labi &Up &Uz augÅ¡u &Down U&z leju Close Pa&ne Ai&zvÄ“rt rÅ«ti User &Units LietotÄ�ja &vienÄ«bas &Turn &Apgrieziens If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Ja jauna izteiksme sÄ�kas ar +, -, * vai /, SpeedCrunch sÄ�kumÄ� ievieto "ans". &Accept with Enter &Pieņemt ar Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Pieņemt paÅ¡reizÄ“jo automÄ�tiskÄ�s pabeigÅ¡anas ieteikumu ar Enter, vispirms to neatlasot ar bulttaustiņiem. &Units &VienÄ«bas Show Live Result &Preview RÄ�dÄ«t rezultÄ�ta tieÅ¡o &priekÅ¡skatÄ«jumu Save &Window Position on Exit Izejot saglabÄ�t &loga pozÄ«ciju Hover Highlighting IzcÄ“lums, norÄ�dot ar peli Group Integer Part Only GrupÄ“t tikai veselo daļu Number Format... Skaitļu formÄ�ts... Notation && Precision... Pieraksts && precizitÄ�te... After pressing Enter, keep the entered expression selected in the editor. PÄ“c Enter nospieÅ¡anas paturÄ“t ievadÄ«to izteiksmi atlasÄ«tu redaktorÄ�. Never Nekad Always VienmÄ“r Only for Single-Line Expressions Tikai vienrindas izteiksmÄ“m Simplify Displayed Expressions VienkÄ�rÅ¡ot attÄ“lotÄ�s izteiksmes History Size &Limit... VÄ“stures lieluma &ierobežojums... Remove Trailing &Zeroes &Noņemt beigu nulles Nearest, Half &Away (round) TuvÄ�kais, puse &prom (round) Nearest, Half &Even (roundeven) TuvÄ�kais, puse &pÄ�ra (roundeven) Toward &Zero (trunc) Uz &nulli (trunc) &Fixed-Point &FiksÄ“tais punkts &Rational &RacionÄ�ls &Exponential (m·sâ�»Â¹) &EksponenciÄ�ls (m·sâ�»Â¹) &Fractional (m/s) &Daļskaitļa (m/s) &Rectangular (a + bi) &Taisnleņķa (a + bi) Exponential (reâ�±á¶¿) EksponenciÄ�ls (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrisks (r(cos θ + i·sin θ)) Phasor (r∠θ) Fazors (r∠θ) &Theme... &TÄ“ma... Check for &Updates PÄ�rbaudÄ«t &atjauninÄ�jumus Source Code Pirmkods &Zoom &TÄ�lummaiņa &Results &RezultÄ�ti Unit Notation VienÄ«bu pieraksts Rounding Mode NoapaļoÅ¡anas režīms &Notation &Pieraksts &Imaginary Unit &ImaginÄ�rÄ� vienÄ«ba &Window &Logs &Editing &Rediģēšana A&utocomplete A&utopabeigÅ¡ana Up/Down Arrow History VÄ“sture ar augÅ¡up/lejup bultiņÄ�m &Appearance &Izskats &Menus I&zvÄ“lnes &Docks &Dokojamie paneļi &Input and Results I&evade un rezultÄ�ti &Disabled &AtspÄ“jots &Disable &AtspÄ“jot Close preview AizvÄ“rt priekÅ¡skatÄ«jumu Rename... PÄ�rdÄ“vÄ“t... Clone... KlonÄ“t... Close Tab AizvÄ“rt cilni New Private Tab Jauna privÄ�ta cilne Open... AtvÄ“rt... Reopen Closed Tab AtvÄ“rt aizvÄ“rto cilni vÄ“lreiz Split SadalÄ«t Left Pa kreisi Right Pa labi Up Uz augÅ¡u Down Uz leju Clear NotÄ«rÄ«t Delete DzÄ“st %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 PrivÄ�ta sesija: aizverot saturs tiek atmests. IzvÄ“lieties Projekts > PaturÄ“t, lai to pÄ�rvÄ“rstu par parastu sesiju. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [PrivÄ�ta] Reset All Settings AtiestatÄ«t visus iestatÄ«jumus Reset all settings to their default values? AtiestatÄ«t visus iestatÄ«jumus uz noklusÄ“juma vÄ“rtÄ«bÄ�m? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Tas ietver izskatu, rediģēšanu, rezultÄ�tu formÄ�tus un logu preferences. Aprēķini, atvÄ“rtÄ�s sesijas un lietotÄ�ja definÄ«cijas tiks paturÄ“tas. The settings file could not be written. NeizdevÄ�s ierakstÄ«t iestatÄ«jumu failu. Clear this session's calculations, unfinished expression, variables, functions, and units? NotÄ«rÄ«t šīs sesijas aprēķinus, nepabeigto izteiksmi, mainÄ«gos, funkcijas un mÄ“rvienÄ«bas? Global user definitions are kept. GlobÄ�lÄ�s lietotÄ�ja definÄ«cijas tiek paturÄ“tas. Make Session Private PadarÄ«t sesiju privÄ�tu The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. SaglabÄ�tÄ� sesija %1 tiks dzÄ“sta. TÄ�s saturs paliks atvÄ“rts privÄ�tÄ� sesijÄ� un tiks atmests, aizverot Å¡o sesiju vai izejot no SpeedCrunch. Make Private PadarÄ«t privÄ�tu Could not delete the saved session %1. NeizdevÄ�s dzÄ“st saglabÄ�to sesiju %1. Keep Session PaturÄ“t sesiju Could not save the session. It remains private. NeizdevÄ�s saglabÄ�t sesiju. TÄ� paliek privÄ�ta. Clone Session KlonÄ“t sesiju Could not save session file %1. NeizdevÄ�s saglabÄ�t sesijas failu %1. Could not delete session file %1. NeizdevÄ�s dzÄ“st sesijas failu %1. JSON file (*.json);;Any file (*.*) JSON fails (*.json);;JebkurÅ¡ fails (*.*) Export session as JSON EksportÄ“t sesiju kÄ� JSON The selected file is not valid JSON: %1 AtlasÄ«tais fails nav derÄ«gs JSON: %1 The selected file is not a SpeedCrunch session JSON file. AtlasÄ«tais fails nav SpeedCrunch sesijas JSON fails. This file uses an obsolete SpeedCrunch session format and cannot be imported. Å is fails izmanto novecojuÅ¡u SpeedCrunch sesijas formÄ�tu un to nevar importÄ“t. The selected JSON file is missing the required $schema field. AtlasÄ«tajÄ� JSON failÄ� trÅ«kst obligÄ�tÄ� $schema lauka. The selected JSON file uses an unsupported JSON schema: %1 AtlasÄ«tais JSON fails izmanto neatbalstÄ«tu JSON shÄ“mu: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). AtlasÄ«tajÄ� JSON failÄ� trÅ«kst SpeedCrunch sesijas shÄ“mas identifikatora ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 AtlasÄ«tais JSON fails izmanto neatbalstÄ«tu SpeedCrunch sesijas formÄ�tu: %1 The selected JSON file is missing the required session name. AtlasÄ«tajÄ� JSON failÄ� trÅ«kst obligÄ�tÄ� sesijas nosaukuma. The selected JSON file has an empty session name. AtlasÄ«tajÄ� JSON failÄ� sesijas nosaukums ir tukÅ¡s. The selected JSON file has invalid or incomplete SpeedCrunch session data. AtlasÄ«tajÄ� JSON failÄ� ir nederÄ«gi vai nepilnÄ«gi SpeedCrunch sesijas dati. Open Sessions Folder AtvÄ“rt sesiju mapi Could not create the sessions folder: %1 NevarÄ“ja izveidot sesiju mapi: %1 Could not open the sessions folder: %1 NevarÄ“ja atvÄ“rt sesiju mapi: %1 Editor and Results Font Redaktora un rezultÄ�tu fonts Open Session AtvÄ“rt sesiju Community Kopiena Rename Session PÄ�rdÄ“vÄ“t sesiju Clear Session NotÄ«rÄ«t sesiju Delete Session DzÄ“st sesiju Close Pane AizvÄ“rt rÅ«ti User Variables LietotÄ�ja mainÄ«gie User Units LietotÄ�ja vienÄ«bas Clear History NotÄ«rÄ«t vÄ“sturi Are you sure you want to clear the calculation history? Vai tieÅ¡Ä�m vÄ“laties notÄ«rÄ«t aprēķinu vÄ“sturi? Session name: Sesijas nosaukums: A session named %1 already exists. Sesija ar nosaukumu %1 jau pastÄ�v. Could not create session file %1. NeizdevÄ�s izveidot sesijas failu %1. Could not write session file %1. NeizdevÄ�s ierakstÄ«t sesijas failu %1. Are you sure you want to delete this session? Vai tieÅ¡Ä�m vÄ“laties dzÄ“st Å¡o sesiju? Custom Precision PielÄ�gota precizitÄ�te Fractional digits: Daļskaitļa cipari: Theme TÄ“ma Light Themes GaiÅ¡Ä�s tÄ“mas Dark Themes TumÅ¡Ä�s tÄ“mas Preview PriekÅ¡skatÄ«jums Colors KrÄ�sas Select color for %1 Atlasiet krÄ�su priekÅ¡ %1 Import... ImportÄ“t... Export... EksportÄ“t... Import Theme ImportÄ“t tÄ“mu Theme file (*.json);;All files (*) TÄ“mas fails (*.json);;Visi faili (*) Invalid theme file. NederÄ«gs tÄ“mas fails. Can't import theme "%1" because it conflicts with a built-in theme. Nevar importÄ“t tÄ“mu "%1", jo tÄ� konfliktÄ“ ar iebÅ«vÄ“tu tÄ“mu. Can't find a writable theme folder. Nevar atrast rakstÄ�mu tÄ“mu mapi. Overwrite Theme PÄ�rrakstÄ«t tÄ“mu A custom theme named "%1" already exists. Do you want to overwrite it? PielÄ�gota tÄ“ma ar nosaukumu "%1" jau pastÄ�v. Vai vÄ“laties to pÄ�rrakstÄ«t? Can't overwrite theme file %1 Nevar pÄ�rrakstÄ«t tÄ“mas failu %1 Can't copy theme file to %1 Nevar kopÄ“t tÄ“mas failu uz %1 Export Theme EksportÄ“t tÄ“mu Can't export theme as "%1" because it conflicts with a built-in theme. Nevar eksportÄ“t tÄ“mu kÄ� "%1", jo tÄ� konfliktÄ“ ar iebÅ«vÄ“tu tÄ“mu. Can't write to file %1 Nevar ierakstÄ«t failÄ� %1 Global User Variable GlobÄ�ls lietotÄ�ja mainÄ«gais Global User Function GlobÄ�la lietotÄ�ja funkcija Global User Unit GlobÄ�la lietotÄ�ja vienÄ«ba User Definitions LietotÄ�ja definÄ«cijas These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Å Ä«s definÄ«cijas ir globÄ�las un tiek ielÄ�dÄ“tas katrÄ� sesijÄ�. SesijÄ�s tÄ�s nevar mainÄ«t, un tÄ�m ir prioritÄ�te pÄ�r sesijas redaktora definÄ«cijÄ�m ar tÄ�du paÅ¡u nosaukumu. Ievadiet vienu definÄ«ciju katrÄ� rindÄ�. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] PiemÄ“ri: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Lietot Validate PÄ�rbaudÄ«t Test Results PÄ�rbaudes rezultÄ�ti Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 ImportÄ“tie mainÄ«gie: %1 ImportÄ“tÄ�s funkcijas: %2 ImportÄ“tÄ�s vienÄ«bas: %3 Rindu numuri ar kļūdÄ�m: %4 none nav Apply Results LietoÅ¡anas rezultÄ�ti User definitions saved. LietotÄ�ja definÄ«cijas saglabÄ�tas. History Size Limit VÄ“stures lieluma ierobežojums Maximum number of history entries for this session (0 = unlimited): MaksimÄ�lais vÄ“stures ierakstu skaits Å¡ai sesijai (0 = neierobežots): Text file (*.txt);;Any file (*.*) Teksta fails (*.txt);;JebkurÅ¡ fails (*.*) Could not recalculate from calculation %1: %2 NeizdevÄ�s pÄ�rrēķinÄ�t no aprēķina %1: %2 History Size Limit Reached Sasniegts vÄ“stures lieluma ierobežojums This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Å is aprēķins aizpilda pÄ“dÄ“jo pieejamo vÄ“stures vietu. TurpmÄ�kie aprēķini no vÄ“stures noņems vecÄ�ko aprēķinu. Ierobežojumu var palielinÄ�t sadaļÄ� Sesija > VÄ“stures lieluma ierobežojums. Editing calculation. Press Esc twice to cancel. Aprēķina rediģēšana. Nospiediet Esc divreiz, lai atceltu. Calculation Settings Aprēķina iestatÄ«jumi Invalid recalculation start index NederÄ«gs pÄ�rrēķinÄ�Å¡anas sÄ�kuma indekss System Default SistÄ“mas noklusÄ“jums Language Valoda Select the language: Atlasiet valodu: Custom PielÄ�gots Decimal places: DecimÄ�lzÄ«mes: &Automatic &AutomÄ�tiski &Precision &PrecizitÄ�te Plain &text VienkÄ�rÅ¡s &teksts Formula &Book Formulu &grÄ�mata &Export &EksportÄ“t Export session as HTML EksportÄ“t sesiju kÄ� HTML HTML file (*.html) HTML fails (*.html) Export session as plain text EksportÄ“t sesiju kÄ� vienkÄ�rÅ¡u tekstu ManualWindow SpeedCrunch Manual SpeedCrunch rokasgrÄ�mata %1 - SpeedCrunch Manual %1 - SpeedCrunch rokasgrÄ�mata NumberFormatDialog Number Format Skaitļu formÄ�ts <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>IzvÄ“lieties skaitļu formÄ�tu rezultÄ�tiem un ievades ciparu grupēšanai.</b><br/><br/>PiezÄ«me: ievadÄ«tiem skaitļiem tiek pieņemti nepÄ�rprotami formÄ�ti arÄ« tad, ja tie atšķiras no izvÄ“lÄ“tÄ� attÄ“loÅ¡anas formÄ�ta.<br/> QObject Global User Variable GlobÄ�ls lietotÄ�ja mainÄ«gais Global User Function GlobÄ�la lietotÄ�ja funkcija Global User Unit GlobÄ�la lietotÄ�ja vienÄ«ba Backspace AtpakaļatkÄ�pe Clear expression NotÄ«rÄ«t izteiksmi Evaluate expression AprēķinÄ�t izteiksmi Insert text Ievietot tekstu Automatic decimal AutomÄ�tisks decimÄ�lformÄ�ts Fixed-point decimal FiksÄ“tÄ� punkta decimÄ�lformÄ�ts Engineering decimal Inženieru decimÄ�lformÄ�ts Scientific decimal ZinÄ�tniskais decimÄ�lformÄ�ts Rational RacionÄ�ls Binary BinÄ�rais Octal OktÄ�lais Hexadecimal HeksadecimÄ�lais Sexagesimal SeÅ¡desmitnieku Update Available Pieejams atjauninÄ�jums A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Ir pieejama jaunÄ�ka versija (%1).<br/><a href="%2">ApmeklÄ“jiet tÄ«mekļa vietni, lai lejupielÄ�dÄ“tu.</a> Check for Updates PÄ�rbaudÄ«t atjauninÄ�jumus SpeedCrunch %1 is up to date. SpeedCrunch %1 ir atjauninÄ�ts. No connectivity. Please check your internet connection and try again. Nav savienojuma. LÅ«dzu, pÄ�rbaudiet interneta savienojumu un mēģiniet vÄ“lreiz. Could not verify the latest available version. NeizdevÄ�s pÄ�rbaudÄ«t jaunÄ�ko pieejamo versiju. ResultDisplay Scroll to bottom RitinÄ�t uz leju Edit Expression Rediģēt izteiksmi Change Settings MainÄ«t iestatÄ«jumus New Tab Jauna cilne &Import... &ImportÄ“t... &Export &EksportÄ“t Plain &text VienkÄ�rÅ¡s &teksts Copy KopÄ“t Selection Atlase Select All AtlasÄ«t visu Expression Izteiksme Result RezultÄ�ts Calculation Aprēķins Calculation as Single Line Aprēķins vienÄ� rindÄ� Remove Noņemt This Calculation Å is aprēķins All Calculations Above Visi augstÄ�k esoÅ¡ie aprēķini All Calculations Below Visi zemÄ�k esoÅ¡ie aprēķini New Private Tab Jauna privÄ�ta cilne Session Projekts Open... AtvÄ“rt... Clone... KlonÄ“t... Rename... PÄ�rdÄ“vÄ“t... Keep PaturÄ“t Make Private... PadarÄ«t privÄ�tu... Clear NotÄ«rÄ«t Delete DzÄ“st Close AizvÄ“rt Split SadalÄ«t Left Pa kreisi Right Pa labi Up Uz augÅ¡u Down Uz leju Close Pane AizvÄ“rt rÅ«ti Main Menu GalvenÄ� izvÄ“lne Cancel editing Atcelt rediģēšanu Copy result KopÄ“t rezultÄ�tu Edit expression Rediģēt izteiksmi Change settings MainÄ«t iestatÄ«jumus Remove calculation Noņemt aprēķinu ResultSlotsDialog Notation & Precision Pieraksts un precizitÄ�te Result Line RezultÄ�ta rinda Enabled IespÄ“jots Notation Pieraksts Decimal Places DecimÄ�lzÄ«mes Main Line GalvenÄ� rinda Extra Line #1 Papildu rinda #1 Extra Line #2 Papildu rinda #2 Extra Line #3 Papildu rinda #3 Extra Line #4 Papildu rinda #4 Auto AutomÄ�tiski UserFunctionListWidget Name Nosaukums Value VÄ“rtÄ«ba Description Apraksts Search MeklÄ“t No match found Nav atrasta atbilstÄ«ba Insert Ievietot Edit Rediģēt Delete DzÄ“st Delete All DzÄ“st visu UserUnitListWidget Name Nosaukums Value VÄ“rtÄ«ba Description Apraksts Search MeklÄ“t No match found Nav atrasta atbilstÄ«ba Insert Ievietot Edit Rediģēt Delete DzÄ“st Delete All DzÄ“st visu VariableListWidget Name Nosaukums Value VÄ“rtÄ«ba Description Apraksts Search MeklÄ“t No match found Nav atrasta atbilstÄ«ba Insert Ievietot Edit Rediģēt Delete DzÄ“st Delete All DzÄ“st visu heldercorreia-speedcrunch-e7ca37f/src/resources/locale/ms.ts000066400000000000000000010440601526573132500243710ustar00rootroot00000000000000 AboutBox About SpeedCrunch Perihal SpeedCrunch Main author | Logo | Maintainer Penulis utama | Logo | Penyelenggara Core developers Pembangun teras Original author Pengarang asal Math engine Enjin matematik Thanks Penghargaan Copyright (C) 2004-2026 The SpeedCrunch developers Hak Cipta (C) 2004-2026 Pembangun SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Program ini ialah perisian bebas; anda boleh mengagihkannya semula dan/atau mengubah suainya di bawah syarat Lesen Awam Am GNU sebagaimana diterbitkan oleh Free Software Foundation; sama ada versi 2 lesen tersebut, atau (mengikut pilihan anda) mana-mana versi yang lebih baharu This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Program ini diedarkan dengan harapan ia akan berguna, tetapi TANPA SEBARANG JAMINAN; malah tanpa jaminan tersirat KEBOLEHDAGANGAN atau KESESUAIAN UNTUK TUJUAN TERTENTU. Lihat Lesen Awam Am GNU untuk maklumat lanjut. Close Tutup BitFieldWidget Reset bits to zero Tetapkan semula bit kepada sifar Invert bits Songsangkan bit Shift bits left Anjak bit ke kiri Shift bits right Anjak bit ke kanan Book Index Indeks Algebra Algebra Quadratic Equation Persamaan Kuadratik Logarithmic Base Conversion Penukaran Asas Logaritma Geometry Geometri Circle Bulatan Sector Sektor Sphere Sfera Cube Kubus Cone Kon Cylinder Silinder Electronics Elektronik Ohm's Law Hukum Ohm Power Kuasa Reactance Reaktans Resonance Resonans Radio Frequency Frekuensi Radio Antennas Antena Characteristic Impedance (coax) Impedans Ciri (koaks) Velocity of Propagation (coax) Halaju Perambatan (koaks) Standing Wave Ratio & Return Loss Nisbah Gelombang Berdiri & Kehilangan Balik Free Space Wavelength Panjang Gelombang Ruang Bebas resistance rintangan voltage voltan current arus power kuasa inductive reactance reaktans induktif capacitive reactance reaktans kapasitif inductance induktans capacitance kapasitans frequency frekuensi resonance frequency frekuensi resonans area luas perimeter perimeter diameter diameter radius jejari volume isipadu surface area luas permukaan height tinggi slant height tinggi condong face diagonal diagonal muka space diagonal diagonal ruang edge length panjang sisi arc length panjang lengkok central angle (degrees) sudut pusat (darjah) dielectric constant pemalar dielektrik outer conductor's inner diameter diameter dalam konduktor luar inner conductor's outer diameter diameter luar konduktor dalam speed of light kelajuan cahaya input power kuasa input reflected power kuasa terpantul transmitted power kuasa dihantar return loss kehilangan balik reflection coefficient pekali pantulan standing wave ratio nisbah gelombang berdiri normalized impedance impedans ternormal frequency (Hz) frekuensi (Hz) BookDock Formula Book Buku Formula ConstantCompletion Search constants Cari pemalar No match found Tiada padanan ditemui Constants Mathematics Matematik Physics (CODATA 2022) Fizik (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kimia (IUPAC - CIAAW 2021) Uncategorized Tidak dikategorikan Universal Sejagat Physicochemical Fizikokimia Atomic & Nuclear — General Atomik & Nuklear — Umum Atomic & Nuclear — Electroweak Atomik & Nuklear — Elektrolemah Atomic & Nuclear — Electron Atomik & Nuklear — Elektron Atomic & Nuclear — Muon Atomik & Nuklear — Muon Atomic & Nuclear — Tau Atomik & Nuklear — Tau Atomic & Nuclear — Proton Atomik & Nuklear — Proton Atomic & Nuclear — Neutron Atomik & Nuklear — Neutron Atomic & Nuclear — Deuteron Atomik & Nuklear — Deuteron Atomic & Nuclear — Triton Atomik & Nuklear — Triton Atomic & Nuclear — Helion Atomik & Nuklear — Helion Atomic & Nuclear — Alpha particle Atomik & Nuklear — Partikel alfa Atomic & Nuclear — Atomic units Atomik & Nuklear — Unit atom Atomic & Nuclear — Energy conversion relationships Atomik & Nuklear — Hubungan penukaran tenaga Atomic & Nuclear — X-ray units Atomik & Nuklear — Unit sinar-X Atomic & Nuclear — Magnetic shielding corrections Atomik & Nuklear — Pembetulan pelindungan magnetik Masses Jisim Lifetimes Masa hidup Molar Masses Jisim molar Electronegativity Keelektronegatifan Ionization Energy Tenaga pengionan Nominal Constants (IAU 2015) Pemalar nominal (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Anggaran terbaik semasa (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) impedans ciri vakum (Zâ‚€) reduced Planck constant (â„�) pemalar Planck tereduksi (â„�) vacuum electric permittivity (ϵ₀) permitiviti elektrik vakum (ϵ₀) Newtonian constant of gravitation (G) pemalar graviti Newton (G) vacuum magnetic permeability (μ₀) kebolehtelapan magnetik vakum (μ₀) Planck constant (h) pemalar Planck (h) speed of light in vacuum (c) kelajuan cahaya dalam vakum (c) standard acceleration of gravity (gâ‚™) pecutan graviti piawai (gâ‚™) Newtonian constant of gravitation over h-bar c pemalar graviti Newton per h-bar c Planck length panjang Planck Planck constant in eV/Hz (h) pemalar Planck dalam eV/Hz (h) Planck mass jisim Planck Planck mass energy equivalent in GeV kesetaraan tenaga jisim Planck dalam GeV Planck temperature suhu Planck Planck time masa Planck reduced Planck constant in eV·s (â„�) pemalar Planck tereduksi dalam eV·s (â„�) reduced Planck constant times c in MeV·fm pemalar Planck tereduksi darab c dalam MeV·fm Bohr magneton magneton Bohr conductance quantum (Gâ‚€) kuantum kekonduksian (Gâ‚€) Coulomb constant (kâ‚‘) pemalar Coulomb (kâ‚‘) elementary charge (e) cas asas (e) elementary charge over h-bar cas asas per h-bar conventional value of Josephson constant nilai konvensional pemalar Josephson Josephson constant pemalar Josephson conventional value of ampere-90 nilai konvensional ampere-90 conventional value of coulomb-90 nilai konvensional coulomb-90 conventional value of farad-90 nilai konvensional farad-90 conventional value of henry-90 nilai konvensional henry-90 conventional value of ohm-90 nilai konvensional ohm-90 conventional value of volt-90 nilai konvensional volt-90 conventional value of watt-90 nilai konvensional watt-90 magnetic flux quantum (Φ₀) kuantum fluks magnetik (Φ₀) nuclear magneton magneton nuklear inverse of conductance quantum songsangan kuantum kekonduksian conventional value of von Klitzing constant nilai konvensional pemalar von Klitzing von Klitzing constant pemalar von Klitzing atomic unit of magnetic dipole moment unit atom bagi momen dipol magnetik atomic unit of magnetic flux density unit atom bagi ketumpatan fluks magnetik Bohr magneton in eV/T magneton Bohr dalam eV/T Bohr magneton in Hz/T magneton Bohr dalam Hz/T Bohr magneton in inverse meter per tesla magneton Bohr dalam meter songsang per tesla Bohr magneton in K/T magneton Bohr dalam K/T nuclear magneton in eV/T magneton nuklear dalam eV/T nuclear magneton in inverse meter per tesla magneton nuklear dalam meter songsang per tesla nuclear magneton in K/T magneton nuklear dalam K/T nuclear magneton in MHz/T magneton nuklear dalam MHz/T Bohr radius (aâ‚€) jejari Bohr (aâ‚€) fine-structure constant (α) pemalar struktur halus (α) Hartree energy (Eâ‚•) tenaga Hartree (Eâ‚•) Hartree energy in eV tenaga Hartree dalam eV quantum of circulation kuantum peredaran quantum of circulation times 2 kuantum peredaran darab 2 Rydberg constant (R∞) pemalar Rydberg (R∞) atomic mass unit-hartree relationship hubungan unit jisim atom-hartree atomic mass unit-hertz relationship hubungan unit jisim atom-hertz atomic mass unit-inverse meter relationship hubungan unit jisim atom-meter songsang atomic mass unit-joule relationship hubungan unit jisim atom-joule atomic mass unit-kelvin relationship hubungan unit jisim atom-kelvin atomic mass unit-kilogram relationship hubungan unit jisim atom-kilogram atomic unit of 1st hyperpolarizability unit atom bagi kebolehpolaran hiper pertama atomic unit of 2nd hyperpolarizability unit atom bagi kebolehpolaran hiper kedua atomic unit of charge (e) unit atom bagi cas (e) atomic unit of charge density unit atom bagi ketumpatan cas atomic unit of current unit atom bagi arus atomic unit of electric dipole moment unit atom bagi momen dipol elektrik atomic unit of electric field unit atom bagi medan elektrik atomic unit of electric field gradient unit atom bagi kecerunan medan elektrik atomic unit of electric polarizability unit atom bagi kebolehpolaran elektrik atomic unit of electric potential unit atom bagi keupayaan elektrik atomic unit of electric quadrupole moment unit atom bagi momen kuadrupol elektrik atomic unit of action unit atom bagi tindakan atomic unit of energy unit atom bagi tenaga atomic unit of force unit atom bagi daya atomic unit of length unit atom bagi panjang hertz-atomic mass unit relationship hubungan hertz-unit jisim atom hertz-electron volt relationship hubungan hertz-elektronvolt hertz-hartree relationship hubungan hertz-hartree hertz-inverse meter relationship hubungan hertz-meter songsang hertz-joule relationship hubungan hertz-joule hertz-kelvin relationship hubungan hertz-kelvin hertz-kilogram relationship hubungan hertz-kilogram hyperfine transition frequency of Cs-133 frekuensi peralihan hiperhalus Cs-133 inverse fine-structure constant (αâ�»Â¹) songsangan pemalar struktur halus (αâ�»Â¹) inverse meter-atomic mass unit relationship hubungan meter songsang-unit jisim atom inverse meter-electron volt relationship hubungan meter songsang-elektronvolt inverse meter-hartree relationship hubungan meter songsang-hartree inverse meter-hertz relationship hubungan meter songsang-hertz inverse meter-joule relationship hubungan meter songsang-joule inverse meter-kelvin relationship hubungan meter songsang-kelvin inverse meter-kilogram relationship hubungan meter songsang-kilogram joule-atomic mass unit relationship hubungan joule-unit jisim atom joule-electron volt relationship hubungan joule-elektronvolt joule-hertz relationship hubungan joule-hertz joule-hartree relationship hubungan joule-hartree joule-inverse meter relationship hubungan joule-meter songsang joule-kelvin relationship hubungan joule-kelvin joule-kilogram relationship hubungan joule-kilogram kelvin-atomic mass unit relationship hubungan kelvin-unit jisim atom kelvin-electron volt relationship hubungan kelvin-elektronvolt kelvin-hertz relationship hubungan kelvin-hertz kelvin-hartree relationship hubungan kelvin-hartree kelvin-inverse meter relationship hubungan kelvin-meter songsang kelvin-joule relationship hubungan kelvin-joule kelvin-kilogram relationship hubungan kelvin-kilogram kilogram-atomic mass unit relationship hubungan kilogram-unit jisim atom kilogram-electron volt relationship hubungan kilogram-elektronvolt kilogram-hertz relationship hubungan kilogram-hertz kilogram-hartree relationship hubungan kilogram-hartree kilogram-inverse meter relationship hubungan kilogram-meter songsang kilogram-joule relationship hubungan kilogram-joule kilogram-kelvin relationship hubungan kilogram-kelvin lattice parameter of silicon (a) parameter kekisi silikon (a) luminous efficacy keberkesanan cahaya natural unit of energy unit semula jadi bagi tenaga natural unit of energy in MeV unit semula jadi bagi tenaga dalam MeV natural unit of action (â„�) unit semula jadi bagi tindakan (â„�) natural unit of action in eV·s unit semula jadi bagi tindakan dalam eV·s natural unit of length unit semula jadi bagi panjang natural unit of mass unit semula jadi bagi jisim natural unit of momentum unit semula jadi bagi momentum natural unit of momentum in MeV/c unit semula jadi bagi momentum dalam MeV/c natural unit of time unit semula jadi bagi masa natural unit of velocity unit semula jadi bagi halaju Rydberg constant times c in Hz pemalar Rydberg darab c dalam Hz Rydberg constant times hc in eV pemalar Rydberg darab hc dalam eV Rydberg constant times hc in J pemalar Rydberg darab hc dalam J Fermi coupling constant pemalar gandingan Fermi weak mixing angle sudut campuran lemah W to Z mass ratio nisbah jisim W kepada Z Thomson cross section (σₑ) keratan rentas Thomson (σₑ) electron mass (mâ‚‘) jisim elektron (mâ‚‘) electron mass in u jisim elektron dalam u electron mass energy equivalent (mₑ·c²) kesetaraan tenaga jisim elektron (mₑ·c²) electron mass energy equivalent in MeV kesetaraan tenaga jisim elektron dalam MeV reduced Compton wavelength panjang gelombang Compton tereduksi classical electron radius (râ‚‘) jejari elektron klasik (râ‚‘) electron charge to mass quotient hasil bahagi cas kepada jisim elektron electron-deuteron magnetic moment ratio nisbah momen magnetik elektron-deuteron electron-deuteron mass ratio nisbah jisim elektron-deuteron electron g factor (gâ‚‘) faktor g elektron (gâ‚‘) electron gyromagnetic ratio (γₑ) nisbah giromagnet elektron (γₑ) electron gyromagnetic ratio in MHz/T nisbah giromagnet elektron dalam MHz/T electron-helion mass ratio nisbah jisim elektron-helion electron magnetic moment (μₑ) momen magnetik elektron (μₑ) electron magnetic moment anomaly (aâ‚‘) anomali momen magnetik elektron (aâ‚‘) electron magnetic moment to Bohr magneton ratio nisbah momen magnetik elektron kepada magneton Bohr electron magnetic moment to nuclear magneton ratio nisbah momen magnetik elektron kepada magneton nuklear electron molar mass (Mâ‚‘) jisim molar elektron (Mâ‚‘) electron-muon magnetic moment ratio nisbah momen magnetik elektron-muon electron-muon mass ratio nisbah jisim elektron-muon electron-neutron magnetic moment ratio nisbah momen magnetik elektron-neutron electron-neutron mass ratio nisbah jisim elektron-neutron electron-proton magnetic moment ratio nisbah momen magnetik elektron-proton electron-proton mass ratio nisbah jisim elektron-proton electron relative atomic mass (Ar(e)) jisim atom relatif elektron (Ar(e)) electron-tau mass ratio nisbah jisim elektron-tau electron to alpha particle mass ratio nisbah jisim elektron kepada partikel alfa electron to shielded helion magnetic moment ratio nisbah momen magnetik elektron kepada helion terlindung electron to shielded proton magnetic moment ratio nisbah momen magnetik elektron kepada proton terlindung electron-triton mass ratio nisbah jisim elektron-triton electron volt-atomic mass unit relationship hubungan elektronvolt-unit jisim atom electron volt-hartree relationship hubungan elektronvolt-hartree electron volt-hertz relationship hubungan elektronvolt-hertz electron volt-inverse meter relationship hubungan elektronvolt-meter songsang electron volt-joule relationship hubungan elektronvolt-joule electron volt-kelvin relationship hubungan elektronvolt-kelvin electron volt-kilogram relationship hubungan elektronvolt-kilogram hartree-atomic mass unit relationship hubungan hartree-unit jisim atom hartree-electron volt relationship hubungan hartree-elektronvolt muon Compton wavelength panjang gelombang Compton muon muon-electron mass ratio nisbah jisim muon-elektron muon g factor faktor g muon muon magnetic moment momen magnetik muon muon magnetic moment anomaly anomali momen magnetik muon muon magnetic moment to Bohr magneton ratio nisbah momen magnetik muon kepada magneton Bohr muon magnetic moment to nuclear magneton ratio nisbah momen magnetik muon kepada magneton nuklear muon mass jisim muon muon mass energy equivalent kesetaraan tenaga jisim muon muon mass energy equivalent in MeV kesetaraan tenaga jisim muon dalam MeV muon mass in u jisim muon dalam u muon molar mass jisim molar muon muon-neutron mass ratio nisbah jisim muon-neutron muon-proton magnetic moment ratio nisbah momen magnetik muon-proton muon-proton mass ratio nisbah jisim muon-proton muon-tau mass ratio nisbah jisim muon-tau reduced muon Compton wavelength panjang gelombang Compton muon tereduksi reduced tau Compton wavelength panjang gelombang Compton tau tereduksi tau Compton wavelength panjang gelombang Compton tau tau-electron mass ratio nisbah jisim tau-elektron tau mass jisim tau tau mass energy equivalent kesetaraan tenaga jisim tau tau mass in u jisim tau dalam u tau molar mass jisim molar tau tau-muon mass ratio nisbah jisim tau-muon tau-neutron mass ratio nisbah jisim tau-neutron tau-proton mass ratio nisbah jisim tau-proton proton charge to mass quotient hasil bahagi cas kepada jisim proton proton Compton wavelength panjang gelombang Compton proton proton-electron mass ratio nisbah jisim proton-elektron proton g factor (gₚ) faktor g proton (gₚ) proton gyromagnetic ratio (γₚ) nisbah giromagnet proton (γₚ) proton gyromagnetic ratio in MHz/T nisbah giromagnet proton dalam MHz/T proton magnetic moment (μₚ) momen magnetik proton (μₚ) proton magnetic moment to Bohr magneton ratio nisbah momen magnetik proton kepada magneton Bohr proton magnetic moment to nuclear magneton ratio nisbah momen magnetik proton kepada magneton nuklear proton magnetic shielding correction pembetulan pelindungan magnetik proton proton mass (mₚ) jisim proton (mₚ) proton mass energy equivalent kesetaraan tenaga jisim proton proton mass energy equivalent in MeV kesetaraan tenaga jisim proton dalam MeV proton mass in u jisim proton dalam u proton molar mass (Mₚ) jisim molar proton (Mₚ) proton-muon mass ratio nisbah jisim proton-muon proton-neutron magnetic moment ratio nisbah momen magnetik proton-neutron proton-neutron mass ratio nisbah jisim proton-neutron proton relative atomic mass (Ar(p)) jisim atom relatif proton (Ar(p)) proton rms charge radius jejari cas rms proton proton-tau mass ratio nisbah jisim proton-tau reduced proton Compton wavelength panjang gelombang Compton proton tereduksi shielded proton gyromagnetic ratio nisbah giromagnet proton terlindung shielded proton gyromagnetic ratio in MHz/T nisbah giromagnet proton terlindung dalam MHz/T shielded proton magnetic moment momen magnetik proton terlindung shielded proton magnetic moment to Bohr magneton ratio nisbah momen magnetik proton terlindung kepada magneton Bohr shielded proton magnetic moment to nuclear magneton ratio nisbah momen magnetik proton terlindung kepada magneton nuklear neutron Compton wavelength panjang gelombang Compton neutron neutron-electron magnetic moment ratio nisbah momen magnetik neutron-elektron neutron-electron mass ratio nisbah jisim neutron-elektron neutron g factor (gâ‚™) faktor g neutron (gâ‚™) neutron gyromagnetic ratio (γₙ) nisbah giromagnet neutron (γₙ) neutron gyromagnetic ratio in MHz/T nisbah giromagnet neutron dalam MHz/T neutron magnetic moment (μₙ) momen magnetik neutron (μₙ) neutron magnetic moment to Bohr magneton ratio nisbah momen magnetik neutron kepada magneton Bohr neutron magnetic moment to nuclear magneton ratio nisbah momen magnetik neutron kepada magneton nuklear neutron mass (mâ‚™) jisim neutron (mâ‚™) neutron mass energy equivalent kesetaraan tenaga jisim neutron neutron mass energy equivalent in MeV kesetaraan tenaga jisim neutron dalam MeV neutron mass in u jisim neutron dalam u neutron molar mass (Mâ‚™) jisim molar neutron (Mâ‚™) neutron-muon mass ratio nisbah jisim neutron-muon neutron-proton magnetic moment ratio nisbah momen magnetik neutron-proton neutron-proton mass difference perbezaan jisim neutron-proton neutron-proton mass difference energy equivalent kesetaraan tenaga perbezaan jisim neutron-proton neutron-proton mass difference energy equivalent in MeV kesetaraan tenaga perbezaan jisim neutron-proton dalam MeV neutron-proton mass difference in u perbezaan jisim neutron-proton dalam u neutron-proton mass ratio nisbah jisim neutron-proton neutron relative atomic mass (Ar(n)) jisim atom relatif neutron (Ar(n)) neutron-tau mass ratio nisbah jisim neutron-tau neutron to shielded proton magnetic moment ratio nisbah momen magnetik neutron kepada proton terlindung reduced neutron Compton wavelength panjang gelombang Compton neutron tereduksi deuteron-electron magnetic moment ratio nisbah momen magnetik deuteron-elektron deuteron-electron mass ratio nisbah jisim deuteron-elektron deuteron g factor faktor g deuteron deuteron magnetic moment momen magnetik deuteron deuteron magnetic moment to Bohr magneton ratio nisbah momen magnetik deuteron kepada magneton Bohr deuteron magnetic moment to nuclear magneton ratio nisbah momen magnetik deuteron kepada magneton nuklear deuteron mass jisim deuteron deuteron mass energy equivalent kesetaraan tenaga jisim deuteron deuteron mass energy equivalent in MeV kesetaraan tenaga jisim deuteron dalam MeV deuteron mass in u jisim deuteron dalam u deuteron molar mass jisim molar deuteron deuteron-neutron magnetic moment ratio nisbah momen magnetik deuteron-neutron deuteron-proton magnetic moment ratio nisbah momen magnetik deuteron-proton deuteron-proton mass ratio nisbah jisim deuteron-proton deuteron relative atomic mass (Ar(d)) jisim atom relatif deuteron (Ar(d)) deuteron rms charge radius jejari cas rms deuteron triton-electron mass ratio nisbah jisim triton-elektron triton g factor (gₜ) faktor g triton (gₜ) triton magnetic moment (μₜ) momen magnetik triton (μₜ) triton magnetic moment to Bohr magneton ratio nisbah momen magnetik triton kepada magneton Bohr triton magnetic moment to nuclear magneton ratio nisbah momen magnetik triton kepada magneton nuklear triton mass (mₜ) jisim triton (mₜ) triton mass energy equivalent kesetaraan tenaga jisim triton triton mass energy equivalent in MeV kesetaraan tenaga jisim triton dalam MeV triton mass in u jisim triton dalam u triton molar mass (Mₜ) jisim molar triton (Mₜ) triton-proton mass ratio nisbah jisim triton-proton triton relative atomic mass (Ar(t)) jisim atom relatif triton (Ar(t)) triton to proton magnetic moment ratio nisbah momen magnetik triton kepada proton helion-electron mass ratio nisbah jisim helion-elektron helion g factor (gâ‚•) faktor g helion (gâ‚•) helion magnetic moment (μₕ) momen magnetik helion (μₕ) helion magnetic moment to Bohr magneton ratio nisbah momen magnetik helion kepada magneton Bohr helion magnetic moment to nuclear magneton ratio nisbah momen magnetik helion kepada magneton nuklear helion mass (mâ‚•) jisim helion (mâ‚•) helion mass energy equivalent kesetaraan tenaga jisim helion helion mass energy equivalent in MeV kesetaraan tenaga jisim helion dalam MeV helion mass in u jisim helion dalam u helion molar mass (Mâ‚•) jisim molar helion (Mâ‚•) helion-proton mass ratio nisbah jisim helion-proton helion relative atomic mass (Ar(h)) jisim atom relatif helion (Ar(h)) helion shielding shift anjakan pelindungan helion shielded helion gyromagnetic ratio nisbah giromagnet helion terlindung shielded helion gyromagnetic ratio in MHz/T nisbah giromagnet helion terlindung dalam MHz/T shielded helion magnetic moment momen magnetik helion terlindung shielded helion magnetic moment to Bohr magneton ratio nisbah momen magnetik helion terlindung kepada magneton Bohr shielded helion magnetic moment to nuclear magneton ratio nisbah momen magnetik helion terlindung kepada magneton nuklear shielded helion to proton magnetic moment ratio nisbah momen magnetik helion terlindung kepada proton shielded helion to shielded proton magnetic moment ratio nisbah momen magnetik helion terlindung kepada proton terlindung alpha particle mass jisim partikel alfa alpha particle mass in u jisim partikel alfa dalam u alpha particle mass energy equivalent kesetaraan tenaga jisim partikel alfa alpha particle mass energy equivalent in MeV kesetaraan tenaga jisim partikel alfa dalam MeV alpha particle-electron mass ratio nisbah jisim partikel alfa-elektron alpha particle-proton mass ratio nisbah jisim partikel alfa-proton alpha particle rms charge radius jejari cas rms partikel alfa alpha particle molar mass jisim molar partikel alfa alpha particle relative atomic mass (Ar(α)) jisim atom relatif partikel alfa (Ar(α)) atomic mass constant (mᵤ) pemalar jisim atom (mᵤ) Avogadro constant pemalar Avogadro Boltzmann constant (k) pemalar Boltzmann (k) Boltzmann constant in eV/K pemalar Boltzmann dalam eV/K Boltzmann constant in Hz/K pemalar Boltzmann dalam Hz/K Boltzmann constant in inverse meter per kelvin pemalar Boltzmann dalam meter songsang per kelvin electron volt (eV) elektronvolt (eV) Faraday constant (F) pemalar Faraday (F) first radiation constant (câ‚�) pemalar sinaran pertama (câ‚�) first radiation constant for spectral radiance pemalar sinaran pertama bagi keserian spektrum molar gas constant (R) pemalar gas molar (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) pemalar Loschmidt (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) pemalar Loschmidt (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant pemalar Planck molar second radiation constant (câ‚‚) pemalar sinaran kedua (câ‚‚) Stefan-Boltzmann constant (σ) pemalar Stefan-Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) jarak kekisi Si unggul (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent kesetaraan tenaga pemalar jisim atom atomic mass constant energy equivalent in MeV kesetaraan tenaga pemalar jisim atom dalam MeV atomic mass unit-electron volt relationship hubungan unit jisim atom-elektronvolt molar mass constant (Mᵤ) pemalar jisim molar (Mᵤ) molar mass of carbon-12 jisim molar karbon-12 molar volume of ideal gas (273.15 K, 100 kPa) isipadu molar gas unggul (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) isipadu molar gas unggul (273.15 K, 101.325 kPa) molar volume of silicon isipadu molar silikon Sackur-Tetrode constant (1 K, 100 kPa) pemalar Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) pemalar Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant pemalar hukum sesaran frekuensi Wien Wien wavelength displacement law constant pemalar hukum sesaran panjang gelombang Wien standard atmosphere (atm) atmosfera piawai (atm) standard-state pressure (p°) tekanan keadaan piawai (p°) Angstrom star (Ã…*) Angstrom star (Ã…*) Copper x unit unit x tembaga Molybdenum x unit unit x molibdenum atomic unit of magnetizability unit atom bagi kebolehmagnetan atomic unit of mass (mâ‚‘) unit atom bagi jisim (mâ‚‘) atomic unit of momentum unit atom bagi momentum atomic unit of permittivity unit atom bagi permitiviti atomic unit of time unit atom bagi masa atomic unit of velocity unit atom bagi halaju hartree-hertz relationship hubungan hartree-hertz hartree-inverse meter relationship hubungan hartree-meter songsang hartree-joule relationship hubungan hartree-joule hartree-kelvin relationship hubungan hartree-kelvin hartree-kilogram relationship hubungan hartree-kilogram shielding difference of d and p in HD perbezaan pelindungan d dan p dalam HD shielding difference of t and p in HT perbezaan pelindungan t dan p dalam HT pi (Ï€) pi (Ï€) Euler's number (e) nombor Euler (e) golden ratio (φ) nisbah keemasan (φ) Euler-Mascheroni constant (γ) pemalar Euler-Mascheroni (γ) nominal solar radius jejari suria nominal nominal solar total irradiance kesinaran jumlah suria nominal nominal solar luminosity luminositi suria nominal nominal solar effective temperature suhu berkesan suria nominal nominal solar mass parameter parameter jisim suria nominal nominal terrestrial equatorial radius jejari khatulistiwa Bumi nominal nominal terrestrial polar radius jejari kutub Bumi nominal nominal terrestrial mass parameter parameter jisim Bumi nominal nominal jovian equatorial radius jejari khatulistiwa Musytari nominal nominal jovian polar radius jejari kutub Musytari nominal nominal jovian mass parameter parameter jisim Musytari nominal average value of one minus the rate of TCG relative to TCB nilai purata satu tolak kadar TCG relatif kepada TCB solar mass parameter (TCB-compatible) parameter jisim suria (serasi TCB) solar mass parameter (TDB-compatible) parameter jisim suria (serasi TDB) equatorial radius of the Earth (TT-compatible) jejari khatulistiwa Bumi (serasi TT) dynamical form factor of the Earth faktor bentuk dinamik Bumi time rate of change in the dynamical form factor of the Earth kadar perubahan masa dalam faktor bentuk dinamik Bumi geocentric gravitational constant (TCB-compatible) pemalar graviti geosentrik (serasi TCB) geocentric gravitational constant (TT-compatible) pemalar graviti geosentrik (serasi TT) geocentric gravitational constant (TDB-compatible) pemalar graviti geosentrik (serasi TDB) potential of the geoid keupayaan geoid nominal mean angular velocity of the Earth (TT-compatible) halaju sudut purata nominal Bumi (serasi TT) ratio mass of the Moon to the Earth nisbah jisim Bulan kepada Bumi ratio of the mass of the Sun to Mercury nisbah jisim Matahari kepada Utarid ratio of the mass of the Sun to Venus nisbah jisim Matahari kepada Zuhrah ratio of the mass of the Sun to Mars nisbah jisim Matahari kepada Marikh ratio of the mass of the Sun to Jupiter nisbah jisim Matahari kepada Musytari ratio of the mass of the Sun to Saturn nisbah jisim Matahari kepada Zuhal ratio of the mass of the Sun to Uranus nisbah jisim Matahari kepada Uranus ratio of the mass of the Sun to Neptune nisbah jisim Matahari kepada Neptun ratio of the mass of the Sun to (134340) Pluto nisbah jisim Matahari kepada (134340) Pluto ratio of the mass of the Sun to (136199) Eris nisbah jisim Matahari kepada (136199) Eris ratio of the mass of (1) Ceres to the Sun nisbah jisim (1) Ceres kepada Matahari ratio of the mass of (2) Pallas to the Sun nisbah jisim (2) Pallas kepada Matahari ratio of the mass of (4) Vesta to the Sun nisbah jisim (4) Vesta kepada Matahari mean obliquity of the ecliptic at J2000.0 kecondongan purata ekliptik pada J2000.0 Electromagnetic Elektromagnet Compton wavelength Panjang gelombang Compton Astronomy Astronomi ConstantsWidget Domain Domain Subdomain Subdomain Search Cari No match found Tiada padanan ditemui Name Nama Value Nilai Unit Unit All Semua CustomKeypadDialog Custom Keypad Pad kekunci tersuai Rows: Baris: Columns: Lajur: Copy preset: Salin pratetap: Basic Asas Scientific (wide) Saintifik (lebar) Scientific (narrow) Saintifik (sempit) Apply Guna Row Baris Column Lajur Label Label Behavior Tingkah laku Text Teks DiagnosticsDialog App Diagnostics Diagnostik Aplikasi Copy to Clipboard Salin ke Papan Klip Editor Unit Unit User unit Unit pengguna User function Fungsi pengguna Argument Argumen Current result:<br/>%1 Hasil semasa:<br/>%1 Selection result:<br/>%1 Hasil pilihan:<br/>%1 Selection result: n/a Hasil pilihan: t/b Selection result: %1 Hasil pilihan: %1 second saat metre meter kilogram kilogram mole mol radian radian steradian steradian degree Celsius darjah Celsius cubic metre meter kubik cubic millimetre milimeter kubik cubic centimetre sentimeter kubik cubic decimetre desimeter kubik cubic kilometre kilometer kubik square millimetre milimeter persegi square kilometre kilometer persegi square metre meter persegi minute minit hour jam day hari astronomical unit unit astronomi degree darjah arcminute minit arka arcsecond saat arka milliarcsecond milisaat arka microarcsecond mikrosaat arka hectare hektare litre liter tonne tan Dalton Dalton electronvolt elektronvolt Angstrom Angstrom atmosphere atmosfer atomic mass unit unit jisim atom British thermal unit unit terma British calorie kalori carat karat cup cawan cup (Imperial) cawan (Imperial) cup (Japanese) cawan (Jepun) cup (US) cawan (AS) degree Fahrenheit darjah Fahrenheit fathom fatom fluid ounce (Imperial) auns cecair (Imperial) fluid ounce (US) auns cecair (AS) fluid dram (Imperial) dram cair (Imperial) fluid dram (US) dram cair (AS) foot kaki square foot kaki persegi cubic foot kaki kubik gallon (Imperial) galon (Imperial) gallon (US) galon (AS) gill (Imperial) gill (Imperial) gill (US) gill (AS) gradian gradian grain grain gram gram Hartley Hartley Hartree energy unit unit tenaga Hartree horsepower tenaga kuda inch inci square inch inci persegi cubic inch inci kubik karat karat knot knot lightminute minit cahaya lightsecond saat cahaya lightyear tahun cahaya long ton tan panjang mile mil square mile mil persegi cubic mile mil kubik mile per hour mil per jam kilometre per hour kilometer per jam nautical mile mil laut ounce ons parsec parsek pint (Imperial) pain (Imperial) pint (US) pain (AS) pound paun pounds per square inch paun per inci persegi quart (Imperial) kuart (Imperial) quart (US) kuart (AS) oil barrel barel minyak beer barrel (US) barel bir (AS) square yard yard persegi cubic yard yard kubik short ton tan pendek tablespoon sudu besar tablespoon (Australian) sudu besar (Australia) tablespoon (Imperial) sudu besar (Imperial) tablespoon (US) sudu besar (AS) dessert spoon sudu pencuci mulut teaspoon sudu teh teaspoon (Imperial) sudu teh (Imperial) teaspoon (US) sudu teh (AS) turn putaran revolution revolusi revolution per minute revolusi per minit week minggu kilowatt hour kilowatt jam millimetre of mercury milimeter air raksa yard ela Julian century abad Julian Julian year tahun Julian sidereal year tahun sideris tropical year tahun tropika Evaluator cannot operate on a NaN tidak boleh beroperasi pada NaN underflow - tiny result is out of SpeedCrunch's number range aliran bawah - hasil yang terlalu kecil berada di luar julat nombor SpeedCrunch overflow - huge result is out of SpeedCrunch's number range aliran limpah - hasil yang terlalu besar berada di luar julat nombor SpeedCrunch division by zero pembahagian dengan sifar overflow - logic result exceeds maximum of 256 bits aliran limpah - hasil logik melebihi maksimum 256 bit overflow - integer result exceeds maximum limit for integers aliran limpah - hasil integer melebihi had maksimum untuk integer too time consuming - computation was rejected terlalu memakan masa - pengiraan ditolak dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensi tidak sepadan - kuantiti dengan dimensi berbeza tidak boleh dibandingkan, ditambah dan sebagainya invalid dimension - operation might require dimensionless arguments dimensi tidak sah - operasi mungkin memerlukan argumen tanpa dimensi operation is not defined for these arguments operasi tidak didefinisikan untuk argumen ini Computation aborted - encountered numerical instability Pengiraan dibatalkan - ketidakstabilan berangka ditemui wrong number of arguments bilangan argumen salah does not take NaN as an argument tidak menerima NaN sebagai argumen result out of range hasil di luar julat undefined for argument domain tidak ditakrif untuk domain argumen computation too expensive pengiraan terlalu mahal invalid dimension - function might require dimensionless arguments dimensi tidak sah - fungsi mungkin memerlukan argumen tanpa dimensi internal error, please report a bug ralat dalaman, sila laporkan pepijat error ralat invalid expression ungkapan tidak sah syntax error ralat sintaks conversion target must be a unit sasaran penukaran mestilah unit unit must not be zero unit tidak boleh sifar Conversion failed - dimension mismatch Penukaran gagal - dimensi tidak sepadan unknown function or variable fungsi atau pembolehubah tidak diketahui unknown unit unit tidak diketahui recursion not supported rekursi tidak disokong %1 is a reserved name, please choose another %1 ialah nama terpelihara, sila pilih nama lain %1 is a global user definition and cannot be overridden in this session. %1 adalah definisi pengguna global dan tidak dapat ditimpa dalam sesi ini. %1 is a variable name, please choose another or delete the variable %1 ialah nama pembolehubah, sila pilih nama lain atau padamkan pembolehubah itu argument %1 is used more than once argumen %1 digunakan lebih daripada sekali %1 is a built-in unit name, please choose another %1 ialah nama unit terbina dalam, sila pilih nama lain %1 is a user function name, please choose another or delete the function %1 ialah nama fungsi pengguna, sila pilih nama lain atau padamkan fungsi itu FunctionRepo max; trials; probability maks; cubaan; kebarangkalian trials; probability cubaan; kebarangkalian hits; trials; probability kejayaan; cubaan; kebarangkalian unix_timestamp; x hours offset to GMT cap masa unix; ofset x jam ke GMT max; total; hits; trials maks; jumlah; kejayaan; cubaan total; hits; trials jumlah; kejayaan; cubaan count; total; hits; trials bilangan; jumlah; kejayaan; cubaan dividend; divisor dividen; pembahagi x; exponent_bits; significand_bits [; exponent_bias] x; bit_eksponen; bit_signifikan [; bias_eksponen] base; x asas; x value; modulo nilai; modulo base; exponent; modulo asas; eksponen; modulo events; average_events peristiwa; purata_peristiwa average_events purata_peristiwa x [; precision] x [; ketepatan] Absolute Value Nilai Mutlak Absolute Deviation Sisihan Mutlak Arc Cosine Arka Kosinus Logical AND DAN logik Area Hyperbolic Cosine Kosinus Hiperbolik Songsang Area Hyperbolic Sine Sinus Hiperbolik Songsang Area Hyperbolic Tangent Tangen Hiperbolik Songsang Arc Sine Arka Sinus Arc Tangent Arka Tangen Arc Tangent with two Arguments Arka Tangen dengan dua Argumen Average (Arithmetic Mean) Purata (Min Aritmetik) Convert to Binary Representation Tukar kepada Perwakilan Perduaan Binomial Cumulative Distribution Function Fungsi Taburan Kumulatif Binomial Binomial Distribution Mean Min Taburan Binomial Binomial Probability Mass Function Fungsi Jisim Kebarangkalian Binomial Binomial Distribution Variance Varians Taburan Binomial Cube Root Punca Kuasa Tiga Complex Conjugate Konjugat Kompleks Cosine Kosinus Hyperbolic Cosine Kosinus Hiperbolik Cotangent Kotangen Cosecant Kosekan Convert Unix timestamp to Date Tukar cap masa Unix kepada Tarikh Convert to Decimal Representation Tukar kepada Perwakilan Perpuluhan Degrees of Arc Darjah Lengkok Error Function Fungsi Ralat Complementary Error Function Fungsi Ralat Pelengkap Exponential Eksponen Arithmetic Aritmetik Chemistry Kimia Complex Kompleks Combinatorics Kombinatorik Probability Kebarangkalian Statistics Statistik Aggregation Pengagregatan Random Rawak Base conversion Penukaran asas Number formatting Pemformatan nombor Integer arithmetic Aritmetik integer Special functions Fungsi khas Exponential & Logarithmic Eksponen & Logaritma Angle conversion Penukaran sudut Trigonometry Trigonometri Bitwise Bit demi bit Floating point Titik terapung Date & Time Tarikh & Masa Linear algebra Algebra linear yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; ofset x jam ke GMT [digits] [digit] max [; min] maks [; min] List Literal Literal senarai Convert to Padded Binary Representation Tukar kepada perwakilan perduaan berpad Round Toward +∞ (Ceiling) Bundarkan ke arah +∞ (siling) Cosine plus Imaginary Sine Kosinus tambah sinus khayalan Convert to Cis Complex Form Tukar kepada bentuk kompleks cis Matrix Column Count Bilangan lajur matriks Population Correlation Matrix (n) Matriks korelasi populasi (n) Sample Correlation Matrix (n-1) Matriks korelasi sampel (n-1) Count Bilangan Population Covariance Matrix (n) Matriks kovarians populasi (n) Sample Covariance Matrix (n-1) Matriks kovarians sampel (n-1) Cross Product Hasil darab silang Convert Date to Unix timestamp Tukar tarikh kepada cap masa Unix Determinant Determinan Convert to Sexagesimal Notation Tukar kepada notasi seksagesimal Dot Product Hasil darab titik Convert to Engineering Notation Tukar kepada notasi kejuruteraan Convert to Exponential Complex Form Tukar kepada bentuk kompleks eksponen Round Toward −∞ (Floor) Bundarkan ke arah −∞ (lantai) Flatten Matrix Ratakan matriks Fractional Part Bahagian Pecahan Extension of Factorials [= (x-1)!] Lanjutan Faktorial [= (x-1)!] Greatest Common Divisor Pembahagi Sepunya Terbesar Least Common Multiple Gandaan sepunya terkecil Geometric Mean Min Geometri Gradians of arc Gradian lengkok Convert to Hexadecimal Representation Tukar kepada Perwakilan Perenambelasan Convert to Padded Hexadecimal Representation Tukar kepada perwakilan perenambelasan berpad Hypergeometric Cumulative Distribution Function Fungsi Taburan Kumulatif Hipergeometri Hypergeometric Distribution Mean Min Taburan Hipergeometri Hypergeometric Probability Mass Function Fungsi Jisim Kebarangkalian Hipergeometri Hypergeometric Distribution Variance Varians Taburan Hipergeometri Integer Quotient Hasil bahagi integer Integer Part Bahagian integer Imaginary Part Bahagian khayal Inverse Matrix Matriks songsang Decode IEEE-754 Binary Value Nyahkod Nilai Perduaan IEEE-754 Encode IEEE-754 Binary Value Kodkan Nilai Perduaan IEEE-754 Decode 16-bit Half-Precision Value Nyahkod Nilai 16-bit Separuh Ketepatan Encode 16-bit Half-Precision Value Kodkan Nilai 16-bit Separuh Ketepatan Decode 32-bit Single-Precision Value Nyahkod Nilai 32-bit Ketepatan Tunggal Encode 32-bit Single-Precision Value Kodkan Nilai 32-bit Ketepatan Tunggal Decode 64-bit Double-Precision Value Nyahkod Nilai 64-bit Ketepatan Berganda Encode 64-bit Double-Precision Value Kodkan Nilai 64-bit Ketepatan Berganda Decode 128-bit Quad-Precision Value Nyahkod Nilai 128-bit Ketepatan Empat Kali Ganda Encode 128-bit Quad-Precision Value Kodkan Nilai 128-bit Ketepatan Empat Kali Ganda Round to 16-bit Half-Precision Value Bundarkan kepada nilai 16-bit separuh ketepatan Round to 32-bit Single-Precision Value Bundarkan kepada nilai 32-bit ketepatan tunggal Round to 64-bit Double-Precision Value Bundarkan kepada nilai 64-bit ketepatan berganda Round to 128-bit Quad-Precision Value Bundarkan kepada nilai 128-bit ketepatan kuad Residual from 16-bit Half-Precision Rounding Baki daripada pembundaran 16-bit separuh ketepatan Residual from 32-bit Single-Precision Rounding Baki daripada pembundaran 32-bit ketepatan tunggal Residual from 64-bit Double-Precision Rounding Baki daripada pembundaran 64-bit ketepatan berganda Residual from 128-bit Quad-Precision Rounding Baki daripada pembundaran 128-bit ketepatan kuad Binary Logarithm Logaritma Perduaan Common Logarithm Logaritma Sepunya Natural Logarithm Logaritma Tabii Substance Mass Jisim bahan Molarity Kemolaran Molar Mass Jisim molar Logarithm to Arbitrary Base Logaritma kepada Asas Sebarang Median Absolute Deviation Sisihan mutlak median Mask to a bit size Topeng kepada saiz bit Maximum Maksimum Median Value (50th Percentile) Nilai Median (Persentil ke-50) Mean Min Minimum Minimum Numerical Value of Quantity Nilai berangka kuantiti Random Decimal Number Nombor perpuluhan rawak Random Integer Number Nombor integer rawak Convert to Rational Representation Tukar kepada perwakilan rasional Modulo Modulo Euclidean Modulo Modulo Euclid Modular Exponentiation Pengeksponenan modular Combination (Binomial Coefficient) Kombinasi (Pekali Binomial) Logical NOT BUKAN logik Permutation (Arrangement) Permutasi (Susunan) Convert to Octal Representation Tukar kepada Perwakilan Perlapanan Convert to Padded Octal Representation Tukar kepada perwakilan perlapanan berpad Vector or Matrix Norm Norma vektor atau matriks Logical OR ATAU logik Population Count (Hamming Weight) Kiraan populasi (berat Hamming) Phase of Complex Number Fasa Nombor Kompleks Poissonian Cumulative Distribution Function Fungsi Taburan Kumulatif Poisson Poissonian Distribution Mean Min Taburan Poisson Poissonian Probability Mass Function Fungsi Jisim Kebarangkalian Poisson Poissonian Distribution Variance Varians Taburan Poisson Convert to Phasor Complex Form Tukar kepada bentuk kompleks fasor Convert to Rectangular Complex Form Tukar kepada bentuk kompleks segi empat Round Half Away from Zero Bundarkan separuh menjauhi sifar Round Half Even Bundarkan separuh genap Nth Root Punca Kuasa Ke-N Convert to Scientific Notation Tukar kepada notasi saintifik Matrix Row Count Bilangan baris matriks List or Matrix Shape Bentuk senarai atau matriks Summation Penambahan Population Standard Deviation (n) Sisihan piawai populasi (n) Sample Standard Deviation (n-1) Sisihan piawai sampel (n-1) Round Toward Zero (Truncation) Bundarkan ke arah sifar (pemangkasan) Matrix Trace Jejak matriks Transpose Matrix Transpos matriks Population Variance (n) Varians populasi (n) Sample Variance (n-1) Varians sampel (n-1) Product Hasil darab Radians Radian Matrix Rank Pangkat matriks Real Part Bahagian nyata Secant Sekan Arithmetic Shift Left Anjakan Aritmetik Kiri Arithmetic Shift Right Anjakan Aritmetik Kanan Signum Signum Sine Sinus Hyperbolic Sine Sinus Hiperbolik Square Root Punca Kuasa Dua Sum Jumlah Tangent Tangen Convert to Trigonometric Complex Form Tukar kepada bentuk kompleks trigonometri Turns Putaran Hyperbolic Tangent Tangen Hiperbolik Sign-extend a value Lanjutkan tanda nilai Logical XOR XOR logik FunctionsWidget Domain Domain All Semua Identifier Pengenal pasti Name Nama Search Cari No match found Tiada padanan ditemui HistoryWidget Remove All Calculations Above Buang semua pengiraan di atas Remove This Calculation Buang pengiraan ini Remove All Calculations Below Buang semua pengiraan di bawah Keypad Inverse cosine Kosinus songsang The last result Hasil terakhir Inverse sine Sinus songsang Inverse tangent Tangen songsang Evaluate expression Nilaikan ungkapan Division Pembahagian Multiplication Pendaraban Subtraction Penolakan Addition Penambahan Clear expression Kosongkan ungkapan Cosine Kosinus Backspace Undur ruang Scientific notation Notasi saintifik Exponential Eksponen Factorial Faktorial Natural logarithm Logaritma tabii Left parenthesis Kurung kiri Nth root Punca Kuasa Ke-N Argument separator Pemisah argumen Square Kuasa dua Common logarithm Logaritma sepunya Modulo Modulo Contextual percentage Peratusan berkonteks Power Kuasa Right parenthesis Kurung kanan Sine Sinus Square root Punca kuasa dua Tangent Tangen Pi Pi Decimal separator Pemisah perpuluhan MainWindow Radian Radian Gradian Gradian Degree Darjah Binary Perduaan Octal Perlapanan Hexadecimal Perenambelasan Sexagesimal Seksagesimal Engineering decimal Perpuluhan kejuruteraan Scientific decimal Perpuluhan saintifik Plain &text &Teks biasa &Import... &Import... &Quit &Keluar Clear E&xpression Kosongkan U&ngkapan Clear &History Kosongkan &Sejarah &Copy &Salin &Paste &Tampal &Select Expression &Pilih Ungkapan &Constants &Pemalar &Functions &Fungsi &History &Sejarah &Keypad &Pad Kekunci Formula &Book &Buku Formula New &Private Tab Tab &Peribadi Baharu Keep Kekalkan Make Private... Jadikan Peribadi... &Rename... &Namakan Semula... Clo&ne... K&lon... &Close Tab T&utup Tab Reopen Clo&sed Tab Buka &Semula Tab yang Ditutup &Undo B&uat Asal &Redo &Buat Semula Cu&t P&otong Copy &Last Result Sa&lin Hasil Terakhir &Wrap in Parentheses &Apit dengan Kurungan Full Scr&een Mode Mod Skrin P&enuh &Status Bar &Bar Status Bitfield Medan bit &Left &Kiri &Right K&anan &Up A&tas &Down &Bawah Close Pa&ne Tutup pa&nel Use&r Functions Fungsi Penggun&a &Degree &Darjah &Radian &Radian &Gradian &Gradian Re&volution Re&volusi Always on &Top Sentiasa di &Atas Auto-Insert a&ns Sisip a&ns Secara Automatik Automatic &Completion Pelengkapan &Automatik &Built-in Functions Fungsi Ter&bina Dalam Built-in &Variables &Pemboleh Ubah Terbina Dalam User &Functions &Fungsi Pengguna User Va&riables P&embolehubah pengguna Open a Private Tab on Startup Buka Tab Peribadi Semasa Permulaan Open and focus a new private tab whenever SpeedCrunch starts. Buka dan fokuskan tab peribadi baharu setiap kali SpeedCrunch bermula. Syntax &Highlighting Penyo&rotan Sintaks Group Digits in &Input Kumpulkan D&igit Input Automatic Input &Adjustments Pel&arasan Input Automatik Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Laraskan operator, jarak, kurungan dan kuasa secara automatik, serta hadkan input kepada aksara yang sah. Group input digits using the selected number format. Kumpulkan digit input mengikut format nombor yang dipilih. &Blinking Cursor Kursor &Berkelip Blink the cursor in the expression editor. Kelipkan kursor dalam penyunting ungkapan. &Escape Clears Editor &Escape Mengosongkan Penyunting Clear the focused expression editor with Escape after dismissing any popup or preview. Kosongkan penyunting ungkapan yang aktif dengan Escape selepas menutup tetingkap timbul atau pratonton. Disabled Dilumpuhkan Small Space Ruang Kecil Medium Space Ruang Sederhana Large Space Ruang Besar Keep Expression After Evaluation Kekalkan Ungkapan Selepas Pengiraan Copy New Results Automatically Salin Hasil Baharu Secara Automatik &Comma &Koma &System Default &Lalai Sistem &Dot &Titik Dot &And Comma Titik d&an Koma &0 Digits &0 Digit &15 Digits &15 Digit &2 Digits &2 Digit &3 Digits &3 Digit &50 Digits &50 Digit &8 Digits &8 Digit Toward +∞ (&ceil) Ke Arah +∞ (&ceil) Toward −∞ (&floor) Ke Arah −∞ (&floor) &Automatic &Automatik &Engineering &Kejuruteraan &Scientific &Saintifik &Binary &Perduaan &Octal &Perlapanan &Hexadecimal &Perenambelasan &Sexagesimal &Seksagesimal &Font... &Fon... Reset All Settings... Tetapkan Semula Semua Tetapan... &System &Sistem SpeedCrunch &Theme &Tema SpeedCrunch &Classic &Klasik &Modern &Moden &Language... &Bahasa... User &Manual &Manual Pengguna Context Help Bantuan Konteks Issues and &Feedback M&asalah dan Maklum Balas &Donate &Derma Editor and Results Font Fon Penyunting dan Hasil &Session &Sesi &Export &Eksport &Edit &Sunting &View &Lihat S&plit P&isahkan Se&ttings Teta&pan &Decimal &Perpuluhan &Precision &Ketepatan Angle &Mode &Mod Sudut &Complex Form B&entuk Kompleks &Help &Bantuan New Tab Tab baharu Constants Pemalar Functions Fungsi History Sejarah User Functions Fungsi Pengguna Error Ralat Can't read from file %1 Tidak dapat membaca daripada fail %1 Can't write to file %1 Tidak dapat menulis ke fail %1 Import Session Import Sesi Close Session Tutup sesi Angle Mode: Mod sudut: Notation: Notasi: Precision: Ketepatan: Turn Putaran Revolution Revolusi Fixed-point decimal Perpuluhan titik tetap Rational Rasional Automatic decimal Perpuluhan automatik Automatic Automatik User &Definitions... &Definisi pengguna... New &Tab &Tab baharu New &Window &Tetingkap baharu &Open... &Buka... Open Sessions &Folder Buka &folder sesi &Basic &Asas &Scientific (wide) &Saintifik (lebar) Scientific (narrow) Saintifik (sempit) &Custom... &Tersuai... Main &Menu &Menu utama User &Variables &Pembolehubah pengguna User &Units &Unit pengguna &Turn &Putaran If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Jika ungkapan baharu bermula dengan +, -, *, atau /, SpeedCrunch menyisipkan "ans" terlebih dahulu. &Accept with Enter &Terima dengan Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Terima cadangan pelengkapan automatik semasa dengan Enter tanpa memilihnya terlebih dahulu menggunakan kekunci anak panah. &Units &Unit Show Live Result &Preview Paparkan &pratonton hasil langsung Save &Window Position on Exit Simpan kedudukan &tetingkap apabila keluar Hover Highlighting Penyorotan saat diarahkan Group Integer Part Only Kumpulkan bahagian integer sahaja Number Format... Format nombor... Notation && Precision... Notasi && Ketepatan... After pressing Enter, keep the entered expression selected in the editor. Selepas menekan Enter, kekalkan ungkapan yang dimasukkan dipilih dalam editor. Never Tidak pernah Always Selalu Only for Single-Line Expressions Hanya untuk ungkapan satu baris Simplify Displayed Expressions Permudahkan ungkapan yang dipaparkan History Size &Limit... &Had saiz sejarah... Remove Trailing &Zeroes &Buang Sifar di Hujung Nearest, Half &Away (round) Terdekat, separuh &menjauh (round) Nearest, Half &Even (roundeven) Terdekat, separuh &genap (roundeven) Toward &Zero (trunc) Ke arah &sifar (trunc) &Fixed-Point Titik &tetap &Rational &Rasional &Exponential (m·sâ�»Â¹) &Eksponen (m·sâ�»Â¹) &Fractional (m/s) &Pecahan (m/s) &Rectangular (a + bi) &Segi empat (a + bi) Exponential (reâ�±á¶¿) Eksponen (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometri (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Tema... Check for &Updates Semak &kemas kini Source Code Kod sumber &Zoom &Zum &Results &Hasil Unit Notation Notasi unit Rounding Mode Mod pembundaran &Notation &Notasi &Imaginary Unit Unit &khayalan &Window &Tetingkap &Editing P&enyuntingan A&utocomplete A&utolengkap Up/Down Arrow History Sejarah panah atas/bawah &Appearance &Penampilan &Menus &Menu &Docks Panel Boleh &Dok &Input and Results &Input dan Hasil &Disabled &Dinonaktifkan &Disable &Nonaktifkan Close preview Tutup pratinjau Rename... Namakan Semula... Clone... Klon... Close Tab Tutup Tab New Private Tab Tab Peribadi Baharu Open... Buka... Reopen Closed Tab Buka Semula Tab yang Ditutup Split Pisahkan Left Kiri Right Kanan Up Atas Down Bawah Clear Kosongkan Delete Padam %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sesi peribadi: kandungan dibuang apabila ditutup. Pilih Sesi > Kekalkan untuk menjadikannya sesi biasa. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Peribadi] Reset All Settings Tetapkan Semula Semua Tetapan Reset all settings to their default values? Tetapkan semula semua tetapan kepada nilai lalai? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Ini termasuk rupa, penyuntingan, format hasil dan keutamaan tetingkap. Pengiraan, sesi terbuka dan takrif pengguna anda akan dikekalkan. The settings file could not be written. Fail tetapan tidak dapat ditulis. Clear this session's calculations, unfinished expression, variables, functions, and units? Kosongkan pengiraan, ungkapan belum selesai, pemboleh ubah, fungsi dan unit sesi ini? Global user definitions are kept. Takrif pengguna global dikekalkan. Make Session Private Jadikan Sesi Peribadi The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Sesi tersimpan %1 akan dipadamkan. Kandungannya akan kekal terbuka dalam sesi peribadi dan akan dibuang apabila sesi itu ditutup atau SpeedCrunch ditamatkan. Make Private Jadikan Peribadi Could not delete the saved session %1. Tidak dapat memadamkan sesi tersimpan %1. Keep Session Kekalkan Sesi Could not save the session. It remains private. Tidak dapat menyimpan sesi. Sesi kekal peribadi. Clone Session Klon Sesi Could not save session file %1. Tidak dapat menyimpan fail sesi %1. Could not delete session file %1. Tidak dapat memadamkan fail sesi %1. JSON file (*.json);;Any file (*.*) Fail JSON (*.json);;Sebarang fail (*.*) Export session as JSON Eksport sesi sebagai JSON The selected file is not valid JSON: %1 Fail yang dipilih bukan JSON yang sah: %1 The selected file is not a SpeedCrunch session JSON file. Fail yang dipilih bukan fail JSON sesi SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Fail ini menggunakan format sesi SpeedCrunch yang lapuk dan tidak boleh diimport. The selected JSON file is missing the required $schema field. Fail JSON yang dipilih tiada medan $schema yang diperlukan. The selected JSON file uses an unsupported JSON schema: %1 Fail JSON yang dipilih menggunakan skema JSON yang tidak disokong: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Fail JSON yang dipilih tiada pengecam skema sesi SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Fail JSON yang dipilih menggunakan format sesi SpeedCrunch yang tidak disokong: %1 The selected JSON file is missing the required session name. Fail JSON yang dipilih tiada nama sesi yang diperlukan. The selected JSON file has an empty session name. Fail JSON yang dipilih mempunyai nama sesi kosong. The selected JSON file has invalid or incomplete SpeedCrunch session data. Fail JSON yang dipilih mempunyai data sesi SpeedCrunch yang tidak sah atau tidak lengkap. Open Sessions Folder Buka folder sesi Could not create the sessions folder: %1 Tidak dapat mencipta folder sesi: %1 Could not open the sessions folder: %1 Tidak dapat membuka folder sesi: %1 Open Session Buka sesi Community Komuniti Rename Session Namakan semula sesi Clear Session Kosongkan sesi Delete Session Padam sesi Close Pane Tutup panel &About SpeedCrunch &Perihal SpeedCrunch App Diag&nostics Diag&nostik Aplikasi User Variables Pembolehubah pengguna User Units Unit pengguna Clear History Kosongkan sejarah Are you sure you want to clear the calculation history? Adakah anda pasti mahu mengosongkan sejarah pengiraan? Session name: Nama sesi: A session named %1 already exists. Sesi bernama %1 sudah wujud. Could not create session file %1. Tidak dapat mencipta fail sesi %1. Could not write session file %1. Tidak dapat menulis fail sesi %1. Are you sure you want to delete this session? Adakah anda pasti mahu memadam sesi ini? Custom Precision Ketepatan tersuai Fractional digits: Digit pecahan: Theme Tema Light Themes Tema terang Dark Themes Tema gelap Preview Pratinjau Colors Warna Select color for %1 Pilih warna untuk %1 Import... Import... Export... Eksport... Import Theme Import tema Theme file (*.json);;All files (*) Fail tema (*.json);;Semua fail (*) Invalid theme file. Fail tema tidak sah. Can't import theme "%1" because it conflicts with a built-in theme. Tidak dapat mengimport tema "%1" kerana bercanggah dengan tema terbina dalam. Can't find a writable theme folder. Tidak dapat mencari folder tema yang boleh ditulis. Overwrite Theme Timpa tema A custom theme named "%1" already exists. Do you want to overwrite it? Tema tersuai bernama "%1" sudah wujud. Adakah anda mahu menimpanya? Can't overwrite theme file %1 Tidak dapat menimpa fail tema %1 Can't copy theme file to %1 Tidak dapat menyalin fail tema ke %1 Export Theme Eksport tema Can't export theme as "%1" because it conflicts with a built-in theme. Tidak dapat mengeksport tema sebagai "%1" kerana bercanggah dengan tema terbina dalam. Global User Variable Pembolehubah pengguna global Global User Function Fungsi pengguna global Global User Unit Unit pengguna global User Definitions Takrif Pengguna These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Takrif ini bersifat global dan dimuatkan ke dalam setiap sesi. Takrif ini tidak boleh diubah dalam sesi dan mengatasi takrif dengan nama yang sama daripada penyunting sesi. Masukkan satu takrif bagi setiap baris. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Contoh: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Guna Validate Sahkan Test Results Keputusan Ujian Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Pembolehubah yang diimport: %1 Fungsi yang diimport: %2 Unit yang diimport: %3 Nombor baris yang mengandungi ralat: %4 none tiada Apply Results Keputusan Penggunaan User definitions saved. Takrif pengguna disimpan. History Size Limit Had saiz sejarah Maximum number of history entries for this session (0 = unlimited): Bilangan maksimum entri sejarah untuk sesi ini (0 = tanpa had): Export session as HTML Eksport sesi sebagai HTML HTML file (*.html) Fail HTML (*.html) Export session as plain text Eksport sesi sebagai teks biasa Text file (*.txt);;Any file (*.*) Fail teks (*.txt);;Sebarang fail (*.*) Could not recalculate from calculation %1: %2 Tidak dapat mengira semula daripada pengiraan %1: %2 History Size Limit Reached Had saiz sejarah dicapai This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Pengiraan ini mengisi slot sejarah terakhir yang tersedia. Pengiraan seterusnya akan membuang pengiraan tertua daripada sejarah. Anda boleh meningkatkan had melalui Sesi > Had Saiz Sejarah. Editing calculation. Press Esc twice to cancel. Menyunting pengiraan. Tekan Esc dua kali untuk membatalkan. Calculation Settings Tetapan pengiraan Invalid recalculation start index Indeks mula pengiraan semula tidak sah System Default Lalai Sistem Language Bahasa Select the language: Pilih bahasa: Custom Tersuai Decimal places: Tempat perpuluhan: ManualWindow SpeedCrunch Manual Manual SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual SpeedCrunch NumberFormatDialog Number Format Format nombor <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Pilih format nombor untuk hasil dan pengumpulan digit input.</b><br/><br/>Nota: format nombor input yang jelas diterima walaupun berbeza daripada format paparan yang dipilih.<br/> QObject Global User Variable Pembolehubah pengguna global Global User Function Fungsi pengguna global Global User Unit Unit pengguna global Backspace Undur ruang Clear expression Kosongkan ungkapan Evaluate expression Nilaikan ungkapan Insert text Sisip teks Automatic decimal Perpuluhan automatik Fixed-point decimal Perpuluhan titik tetap Engineering decimal Perpuluhan kejuruteraan Scientific decimal Perpuluhan saintifik Rational Rasional Binary Perduaan Octal Perlapanan Hexadecimal Perenambelasan Sexagesimal Seksagesimal Update Available Kemas kini tersedia A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Versi yang lebih baharu (%1) tersedia.<br/><a href="%2">Lawati laman web untuk memuat turun.</a> Check for Updates Semak kemas kini SpeedCrunch %1 is up to date. SpeedCrunch %1 sudah terkini. No connectivity. Please check your internet connection and try again. Tiada sambungan. Sila semak sambungan internet anda dan cuba lagi. Could not verify the latest available version. Tidak dapat mengesahkan versi terkini yang tersedia. ResultDisplay Scroll to bottom Tatal ke bawah Edit Expression Sunting ungkapan Change Settings Ubah tetapan New Tab Tab baharu &Import... &Import... &Export &Eksport Plain &text &Teks biasa Copy Salin Selection Pilihan Select All Pilih Semua Expression Ungkapan Result Hasil Calculation Pengiraan Calculation as Single Line Pengiraan dalam Satu Baris Remove Buang This Calculation Pengiraan Ini All Calculations Above Semua Pengiraan di Atas All Calculations Below Semua Pengiraan di Bawah New Private Tab Tab Peribadi Baharu Session Sesi Open... Buka... Clone... Klon... Rename... Namakan Semula... Keep Kekalkan Make Private... Jadikan Peribadi... Clear Kosongkan Delete Padam Close Tutup Split Pisahkan Left Kiri Right Kanan Up Atas Down Bawah Close Pane Tutup panel Main Menu Menu utama Cancel editing Batalkan penyuntingan Copy result Salin hasil Edit expression Sunting ungkapan Change settings Ubah tetapan Remove calculation Padam pengiraan ResultSlotsDialog Notation & Precision Notasi & Ketepatan Result Line Baris hasil Enabled Didayakan Notation Notasi Decimal Places Tempat perpuluhan Main Line Baris utama Extra Line #1 Baris tambahan #1 Extra Line #2 Baris tambahan #2 Extra Line #3 Baris tambahan #3 Extra Line #4 Baris tambahan #4 Auto Automatik UserFunctionListWidget Name Nama Value Nilai Description Perihalan Search Cari No match found Tiada padanan ditemui Insert Sisip Edit Sunting Delete Padam Delete All Padam semua UserUnitListWidget Name Nama Value Nilai Description Perihalan Search Cari No match found Tiada padanan ditemui Insert Sisip Edit Sunting Delete Padam Delete All Padam semua VariableListWidget Name Nama Value Nilai Description Perihalan Search Cari No match found Tiada padanan ditemui Insert Sisip Edit Sunting Delete Padam Delete All Padam semua heldercorreia-speedcrunch-e7ca37f/src/resources/locale/nb.ts000066400000000000000000010470611526573132500243550ustar00rootroot00000000000000 AboutBox About SpeedCrunch Om SpeedCrunch Core developers Kjerneutviklere Original author Opprinnelig forfatter Close Lukk Math engine Matematikkmotor Main author | Logo | Maintainer Hovedforfatter | Logo | Vedlikeholder Thanks Takk Copyright (C) 2004-2026 The SpeedCrunch developers Opphavsrett (C) 2004-2026 SpeedCrunch-utviklerne This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Dette programmet er fri programvare. Du kan redistribuere og/eller endre det i henhold til vilkÃ¥rene i GNU General Public License, som utgitt av Free Software Foundation, enten versjon 2 av lisensen eller (etter eget valg) en senere versjon. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Dette programmet distribueres i hÃ¥p om at det vil være nyttig, men UTEN NOEN GARANTI, ikke engang implisitt garanti om SALGBARHET eller EGNETHET FOR ET BESTEMT FORMÃ…L. Se GNU General Public License for flere detaljer. BitFieldWidget Reset bits to zero Tilbakestill bit til null Invert bits Inverter bit Shift bits left Skift bit til venstre Shift bits right Skift bit til høyre Book Index Indeks Algebra Algebra Quadratic Equation Andregradslikning Logarithmic Base Conversion Konvertering av logaritmebase Geometry Geometri Circle Sirkel Sector Sektor Sphere Kule Cube Kube Cone Kjegle Cylinder Sylinder Electronics Elektronikk Ohm's Law Ohms lov Power Effekt Reactance Reaktans Resonance Resonans Radio Frequency Radiofrekvens Antennas Antenner Characteristic Impedance (coax) Karakteristisk impedans (koaks) Velocity of Propagation (coax) Forplantningshastighet (koaks) Standing Wave Ratio & Return Loss StÃ¥ende bølgeforhold og returtap Free Space Wavelength Bølgelengde i fritt rom resistance motstand voltage spenning current strøm power effekt inductive reactance induktiv reaktans capacitive reactance kapasitiv reaktans inductance induktans capacitance kapasitans frequency frekvens resonance frequency resonansfrekvens area areal perimeter omkrets diameter diameter radius radius volume volum surface area overflateareal height høyde slant height skrÃ¥høyde face diagonal flatediagonal space diagonal romdiagonal edge length kantlengde arc length buelengde central angle (degrees) sentralvinkel (grader) input power inngangseffekt reflected power reflektert effekt transmitted power overført effekt return loss returtap dielectric constant dielektrisk konstant outer conductor's inner diameter innerdiameteren til ytre leder inner conductor's outer diameter ytterdiameteren til indre leder speed of light lyshastighet reflection coefficient refleksjonskoeffisient standing wave ratio stÃ¥ende bølgeforhold normalized impedance normalisert impedans frequency (Hz) frekvens (Hz) BookDock Formula Book Formelsamling ConstantCompletion Search constants Søk etter konstanter No match found Ingen treff funnet Constants Mathematics Matematikk Physics (CODATA 2022) Fysikk (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kjemi (IUPAC - CIAAW 2021) Uncategorized Ukategorisert Universal Universelle Physicochemical Fysikalsk-kjemisk Atomic & Nuclear — General Atom- og kjernefysikk - generelt Atomic & Nuclear — Electroweak Atom- og kjernefysikk - elektrosvak Atomic & Nuclear — Electron Atom- og kjernefysikk - elektron Atomic & Nuclear — Muon Atom- og kjernefysikk - myon Atomic & Nuclear — Tau Atom- og kjernefysikk - tau Atomic & Nuclear — Proton Atom- og kjernefysikk - proton Atomic & Nuclear — Neutron Atom- og kjernefysikk - nøytron Atomic & Nuclear — Deuteron Atom- og kjernefysikk - deuteron Atomic & Nuclear — Triton Atom- og kjernefysikk - triton Atomic & Nuclear — Helion Atom- og kjernefysikk - helion Atomic & Nuclear — Alpha particle Atom- og kjernefysikk - alfapartikkel Atomic & Nuclear — Atomic units Atom- og kjernefysikk - atomære enheter Atomic & Nuclear — Energy conversion relationships Atom- og kjernefysikk - energiomregningsforhold Atomic & Nuclear — X-ray units Atom- og kjernefysikk - røntgenenheter Atomic & Nuclear — Magnetic shielding corrections Atom- og kjernefysikk - magnetiske skjermingskorreksjoner Masses Masser Lifetimes Levetider Molar Masses Molmasser Electronegativity Elektronegativitet Ionization Energy Ioniseringsenergi Nominal Constants (IAU 2015) Nominelle konstanter (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Gjeldende beste estimater (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) karakteristisk impedans i vakuum (Zâ‚€) reduced Planck constant (â„�) redusert Planck-konstant (â„�) vacuum electric permittivity (ϵ₀) elektrisk permittivitet i vakuum (ϵ₀) Newtonian constant of gravitation (G) Newtons gravitasjonskonstant (G) vacuum magnetic permeability (μ₀) magnetisk permeabilitet i vakuum (μ₀) Planck constant (h) Planck-konstant (h) speed of light in vacuum (c) lyshastighet i vakuum (c) standard acceleration of gravity (gâ‚™) standard tyngdeakselerasjon (gâ‚™) Newtonian constant of gravitation over h-bar c Newtons gravitasjonskonstant dividert med h-bar c Planck length Planck-lengde Planck constant in eV/Hz (h) Planck-konstant i eV/Hz (h) Planck mass Planck-masse Planck mass energy equivalent in GeV Planck-massens energi-ekvivalent i GeV Planck temperature Planck-temperatur Planck time Planck-tid reduced Planck constant in eV·s (â„�) redusert Planck-konstant i eV·s (â„�) reduced Planck constant times c in MeV·fm redusert Planck-konstant ganger c i MeV·fm Bohr magneton Bohr-magneton conductance quantum (Gâ‚€) konduktanskvant (Gâ‚€) Coulomb constant (kâ‚‘) Coulomb-konstant (kâ‚‘) elementary charge (e) elementærladning (e) elementary charge over h-bar elementærladning dividert med h-bar conventional value of Josephson constant konvensjonell verdi for Josephson-konstanten Josephson constant Josephson-konstant conventional value of ampere-90 konvensjonell verdi for ampere-90 conventional value of coulomb-90 konvensjonell verdi for coulomb-90 conventional value of farad-90 konvensjonell verdi for farad-90 conventional value of henry-90 konvensjonell verdi for henry-90 conventional value of ohm-90 konvensjonell verdi for ohm-90 conventional value of volt-90 konvensjonell verdi for volt-90 conventional value of watt-90 konvensjonell verdi for watt-90 magnetic flux quantum (Φ₀) magnetisk flukskvant (Φ₀) nuclear magneton kjernemagneton inverse of conductance quantum invers av konduktanskvant conventional value of von Klitzing constant konvensjonell verdi for von Klitzing-konstanten von Klitzing constant von Klitzing-konstant atomic unit of magnetic dipole moment atomær enhet for magnetisk dipolmoment atomic unit of magnetic flux density atomær enhet for magnetisk flukstetthet Bohr magneton in eV/T Bohr-magneton i eV/T Bohr magneton in Hz/T Bohr-magneton i Hz/T Bohr magneton in inverse meter per tesla Bohr-magneton i inverse meter per tesla Bohr magneton in K/T Bohr-magneton i K/T nuclear magneton in eV/T kjernemagneton i eV/T nuclear magneton in inverse meter per tesla kjernemagneton i inverse meter per tesla nuclear magneton in K/T kjernemagneton i K/T nuclear magneton in MHz/T kjernemagneton i MHz/T Bohr radius (aâ‚€) Bohr-radius (aâ‚€) fine-structure constant (α) finstrukturkonstant (α) Hartree energy (Eâ‚•) Hartree-energi (Eâ‚•) Hartree energy in eV Hartree-energi i eV quantum of circulation sirkulasjonskvant quantum of circulation times 2 sirkulasjonskvant ganger 2 Rydberg constant (R∞) Rydberg-konstant (R∞) atomic mass unit-hartree relationship sammenheng mellom atommasseenhet og hartree atomic mass unit-hertz relationship sammenheng mellom atommasseenhet og hertz atomic mass unit-inverse meter relationship sammenheng mellom atommasseenhet og invers meter atomic mass unit-joule relationship sammenheng mellom atommasseenhet og joule atomic mass unit-kelvin relationship sammenheng mellom atommasseenhet og kelvin atomic mass unit-kilogram relationship sammenheng mellom atommasseenhet og kilogram atomic unit of 1st hyperpolarizability atomær enhet for 1. hyperpolariserbarhet atomic unit of 2nd hyperpolarizability atomær enhet for 2. hyperpolariserbarhet atomic unit of charge (e) atomær enhet for ladning (e) atomic unit of charge density atomær enhet for ladningstetthet atomic unit of current atomær enhet for strøm atomic unit of electric dipole moment atomær enhet for elektrisk dipolmoment atomic unit of electric field atomær enhet for elektrisk felt atomic unit of electric field gradient atomær enhet for elektrisk feltgradient atomic unit of electric polarizability atomær enhet for elektrisk polariserbarhet atomic unit of electric potential atomær enhet for elektrisk potensial atomic unit of electric quadrupole moment atomær enhet for elektrisk kvadrupolmoment atomic unit of action atomær enhet for virkning atomic unit of energy atomær enhet for energi atomic unit of force atomær enhet for kraft atomic unit of length atomær enhet for lengde hertz-atomic mass unit relationship sammenheng mellom hertz og atommasseenhet hertz-electron volt relationship sammenheng mellom hertz og elektronvolt hertz-hartree relationship sammenheng mellom hertz og hartree hertz-inverse meter relationship sammenheng mellom hertz og invers meter hertz-joule relationship sammenheng mellom hertz og joule hertz-kelvin relationship sammenheng mellom hertz og kelvin hertz-kilogram relationship sammenheng mellom hertz og kilogram hyperfine transition frequency of Cs-133 hyperfin overgangsfrekvens for Cs-133 inverse fine-structure constant (αâ�»Â¹) invers finstrukturkonstant (αâ�»Â¹) inverse meter-atomic mass unit relationship sammenheng mellom invers meter og atommasseenhet inverse meter-electron volt relationship sammenheng mellom invers meter og elektronvolt inverse meter-hartree relationship sammenheng mellom invers meter og hartree inverse meter-hertz relationship sammenheng mellom invers meter og hertz inverse meter-joule relationship sammenheng mellom invers meter og joule inverse meter-kelvin relationship sammenheng mellom invers meter og kelvin inverse meter-kilogram relationship sammenheng mellom invers meter og kilogram joule-atomic mass unit relationship sammenheng mellom joule og atommasseenhet joule-electron volt relationship sammenheng mellom joule og elektronvolt joule-hertz relationship sammenheng mellom joule og hertz joule-hartree relationship sammenheng mellom joule og hartree joule-inverse meter relationship sammenheng mellom joule og invers meter joule-kelvin relationship sammenheng mellom joule og kelvin joule-kilogram relationship sammenheng mellom joule og kilogram kelvin-atomic mass unit relationship sammenheng mellom kelvin og atommasseenhet kelvin-electron volt relationship sammenheng mellom kelvin og elektronvolt kelvin-hertz relationship sammenheng mellom kelvin og hertz kelvin-hartree relationship sammenheng mellom kelvin og hartree kelvin-inverse meter relationship sammenheng mellom kelvin og invers meter kelvin-joule relationship sammenheng mellom kelvin og joule kelvin-kilogram relationship sammenheng mellom kelvin og kilogram kilogram-atomic mass unit relationship sammenheng mellom kilogram og atommasseenhet kilogram-electron volt relationship sammenheng mellom kilogram og elektronvolt kilogram-hertz relationship sammenheng mellom kilogram og hertz kilogram-hartree relationship sammenheng mellom kilogram og hartree kilogram-inverse meter relationship sammenheng mellom kilogram og invers meter kilogram-joule relationship sammenheng mellom kilogram og joule kilogram-kelvin relationship sammenheng mellom kilogram og kelvin lattice parameter of silicon (a) gitterparameter for silisium (a) luminous efficacy lyseffektivitet natural unit of energy naturlig enhet for energi natural unit of energy in MeV naturlig enhet for energi i MeV natural unit of action (â„�) naturlig enhet for virkning (â„�) natural unit of action in eV·s naturlig enhet for virkning i eV·s natural unit of length naturlig enhet for lengde natural unit of mass naturlig enhet for masse natural unit of momentum naturlig enhet for bevegelsesmengde natural unit of momentum in MeV/c naturlig enhet for bevegelsesmengde i MeV/c natural unit of time naturlig enhet for tid natural unit of velocity naturlig enhet for hastighet Rydberg constant times c in Hz Rydberg-konstant ganger c i Hz Rydberg constant times hc in eV Rydberg-konstant ganger hc i eV Rydberg constant times hc in J Rydberg-konstant ganger hc i J Fermi coupling constant Fermi-koblingskonstant weak mixing angle svak blandingsvinkel W to Z mass ratio masseforhold mellom W og Z Thomson cross section (σₑ) Thomson-tverrsnitt (σₑ) electron mass (mâ‚‘) elektronmasse (mâ‚‘) electron mass in u elektronmasse i u electron mass energy equivalent (mₑ·c²) elektronets masse-energiekvivalent (mₑ·c²) electron mass energy equivalent in MeV elektronets masse-energiekvivalent i MeV reduced Compton wavelength redusert Compton-bølgelengde classical electron radius (râ‚‘) klassisk elektronradius (râ‚‘) electron charge to mass quotient elektronets ladning-masse-forhold electron-deuteron magnetic moment ratio forhold mellom magnetisk moment for elektron og deuteron electron-deuteron mass ratio masseforhold mellom elektron og deuteron electron g factor (gâ‚‘) elektronets g-faktor (gâ‚‘) electron gyromagnetic ratio (γₑ) elektronets gyromagnetiske forhold (γₑ) electron gyromagnetic ratio in MHz/T elektronets gyromagnetiske forhold i MHz/T electron-helion mass ratio masseforhold mellom elektron og helion electron magnetic moment (μₑ) elektronets magnetiske moment (μₑ) electron magnetic moment anomaly (aâ‚‘) elektronets magnetiske moment-anomali (aâ‚‘) electron magnetic moment to Bohr magneton ratio forhold mellom elektronets magnetiske moment og Bohr-magnetonet electron magnetic moment to nuclear magneton ratio forhold mellom elektronets magnetiske moment og kjernemagnetonet electron molar mass (Mâ‚‘) elektronets molmasse (Mâ‚‘) electron-muon magnetic moment ratio forhold mellom magnetisk moment for elektron og myon electron-muon mass ratio masseforhold mellom elektron og myon electron-neutron magnetic moment ratio forhold mellom magnetisk moment for elektron og nøytron electron-neutron mass ratio masseforhold mellom elektron og nøytron electron-proton magnetic moment ratio forhold mellom magnetisk moment for elektron og proton electron-proton mass ratio masseforhold mellom elektron og proton electron relative atomic mass (Ar(e)) elektronets relative atommasse (Ar(e)) electron-tau mass ratio masseforhold mellom elektron og tau electron to alpha particle mass ratio masseforhold mellom elektron og alfapartikkel electron to shielded helion magnetic moment ratio forhold mellom elektronets magnetiske moment og skjermet helions magnetiske moment electron to shielded proton magnetic moment ratio forhold mellom elektronets magnetiske moment og skjermet protons magnetiske moment electron-triton mass ratio masseforhold mellom elektron og triton electron volt-atomic mass unit relationship sammenheng mellom elektronvolt og atommasseenhet electron volt-hartree relationship sammenheng mellom elektronvolt og hartree electron volt-hertz relationship sammenheng mellom elektronvolt og hertz electron volt-inverse meter relationship sammenheng mellom elektronvolt og invers meter electron volt-joule relationship sammenheng mellom elektronvolt og joule electron volt-kelvin relationship sammenheng mellom elektronvolt og kelvin electron volt-kilogram relationship sammenheng mellom elektronvolt og kilogram hartree-atomic mass unit relationship sammenheng mellom hartree og atommasseenhet hartree-electron volt relationship sammenheng mellom hartree og elektronvolt muon Compton wavelength myonets Compton-bølgelengde muon-electron mass ratio masseforhold mellom myon og elektron muon g factor myonets g-faktor muon magnetic moment myonets magnetiske moment muon magnetic moment anomaly myonets magnetiske moment-anomali muon magnetic moment to Bohr magneton ratio forhold mellom myonets magnetiske moment og Bohr-magnetonet muon magnetic moment to nuclear magneton ratio forhold mellom myonets magnetiske moment og kjernemagnetonet muon mass myonmasse muon mass energy equivalent myonets masse-energiekvivalent muon mass energy equivalent in MeV myonets masse-energiekvivalent i MeV muon mass in u myonmasse i u muon molar mass myonets molmasse muon-neutron mass ratio masseforhold mellom myon og nøytron muon-proton magnetic moment ratio forhold mellom magnetisk moment for myon og proton muon-proton mass ratio masseforhold mellom myon og proton muon-tau mass ratio masseforhold mellom myon og tau reduced muon Compton wavelength redusert Compton-bølgelengde for myon reduced tau Compton wavelength redusert Compton-bølgelengde for tau tau Compton wavelength tauets Compton-bølgelengde tau-electron mass ratio masseforhold mellom tau og elektron tau mass taumasse tau mass energy equivalent tauets masse-energiekvivalent tau mass in u taumasse i u tau molar mass tauets molmasse tau-muon mass ratio masseforhold mellom tau og myon tau-neutron mass ratio masseforhold mellom tau og nøytron tau-proton mass ratio masseforhold mellom tau og proton proton charge to mass quotient protonets ladning-masse-forhold proton Compton wavelength protonets Compton-bølgelengde proton-electron mass ratio masseforhold mellom proton og elektron proton g factor (gₚ) protonets g-faktor (gₚ) proton gyromagnetic ratio (γₚ) protonets gyromagnetiske forhold (γₚ) proton gyromagnetic ratio in MHz/T protonets gyromagnetiske forhold i MHz/T proton magnetic moment (μₚ) protonets magnetiske moment (μₚ) proton magnetic moment to Bohr magneton ratio forhold mellom protonets magnetiske moment og Bohr-magnetonet proton magnetic moment to nuclear magneton ratio forhold mellom protonets magnetiske moment og kjernemagnetonet proton magnetic shielding correction magnetisk skjermingskorreksjon for proton proton mass (mₚ) protonmasse (mₚ) proton mass energy equivalent protonets masse-energiekvivalent proton mass energy equivalent in MeV protonets masse-energiekvivalent i MeV proton mass in u protonmasse i u proton molar mass (Mₚ) protonets molmasse (Mₚ) proton-muon mass ratio masseforhold mellom proton og myon proton-neutron magnetic moment ratio forhold mellom magnetisk moment for proton og nøytron proton-neutron mass ratio masseforhold mellom proton og nøytron proton relative atomic mass (Ar(p)) protonets relative atommasse (Ar(p)) proton rms charge radius protonets rms-ladningsradius proton-tau mass ratio masseforhold mellom proton og tau reduced proton Compton wavelength redusert Compton-bølgelengde for proton shielded proton gyromagnetic ratio gyromagnetisk forhold for skjermet proton shielded proton gyromagnetic ratio in MHz/T gyromagnetisk forhold for skjermet proton i MHz/T shielded proton magnetic moment magnetisk moment for skjermet proton shielded proton magnetic moment to Bohr magneton ratio forhold mellom magnetisk moment for skjermet proton og Bohr-magnetonet shielded proton magnetic moment to nuclear magneton ratio forhold mellom magnetisk moment for skjermet proton og kjernemagnetonet neutron Compton wavelength nøytronets Compton-bølgelengde neutron-electron magnetic moment ratio forhold mellom magnetisk moment for nøytron og elektron neutron-electron mass ratio masseforhold mellom nøytron og elektron neutron g factor (gâ‚™) nøytronets g-faktor (gâ‚™) neutron gyromagnetic ratio (γₙ) nøytronets gyromagnetiske forhold (γₙ) neutron gyromagnetic ratio in MHz/T nøytronets gyromagnetiske forhold i MHz/T neutron magnetic moment (μₙ) nøytronets magnetiske moment (μₙ) neutron magnetic moment to Bohr magneton ratio forhold mellom nøytronets magnetiske moment og Bohr-magnetonet neutron magnetic moment to nuclear magneton ratio forhold mellom nøytronets magnetiske moment og kjernemagnetonet neutron mass (mâ‚™) nøytronmasse (mâ‚™) neutron mass energy equivalent nøytronets masse-energiekvivalent neutron mass energy equivalent in MeV nøytronets masse-energiekvivalent i MeV neutron mass in u nøytronmasse i u neutron molar mass (Mâ‚™) nøytronets molmasse (Mâ‚™) neutron-muon mass ratio masseforhold mellom nøytron og myon neutron-proton magnetic moment ratio forhold mellom magnetisk moment for nøytron og proton neutron-proton mass difference masseforskjell mellom nøytron og proton neutron-proton mass difference energy equivalent energi-ekvivalent for masseforskjell mellom nøytron og proton neutron-proton mass difference energy equivalent in MeV energi-ekvivalent for masseforskjell mellom nøytron og proton i MeV neutron-proton mass difference in u masseforskjell mellom nøytron og proton i u neutron-proton mass ratio masseforhold mellom nøytron og proton neutron relative atomic mass (Ar(n)) nøytronets relative atommasse (Ar(n)) neutron-tau mass ratio masseforhold mellom nøytron og tau neutron to shielded proton magnetic moment ratio forhold mellom nøytronets magnetiske moment og skjermet protons magnetiske moment reduced neutron Compton wavelength redusert Compton-bølgelengde for nøytron deuteron-electron magnetic moment ratio forhold mellom magnetisk moment for deuteron og elektron deuteron-electron mass ratio masseforhold mellom deuteron og elektron deuteron g factor deuteronets g-faktor deuteron magnetic moment deuteronets magnetiske moment deuteron magnetic moment to Bohr magneton ratio forhold mellom deuteronets magnetiske moment og Bohr-magnetonet deuteron magnetic moment to nuclear magneton ratio forhold mellom deuteronets magnetiske moment og kjernemagnetonet deuteron mass deuteronmasse deuteron mass energy equivalent deuteronets masse-energiekvivalent deuteron mass energy equivalent in MeV deuteronets masse-energiekvivalent i MeV deuteron mass in u deuteronmasse i u deuteron molar mass deuteronets molmasse deuteron-neutron magnetic moment ratio forhold mellom magnetisk moment for deuteron og nøytron deuteron-proton magnetic moment ratio forhold mellom magnetisk moment for deuteron og proton deuteron-proton mass ratio masseforhold mellom deuteron og proton deuteron relative atomic mass (Ar(d)) deuteronets relative atommasse (Ar(d)) deuteron rms charge radius deuteronets rms-ladningsradius triton-electron mass ratio masseforhold mellom triton og elektron triton g factor (gₜ) tritonets g-faktor (gₜ) triton magnetic moment (μₜ) tritonets magnetiske moment (μₜ) triton magnetic moment to Bohr magneton ratio forhold mellom tritonets magnetiske moment og Bohr-magnetonet triton magnetic moment to nuclear magneton ratio forhold mellom tritonets magnetiske moment og kjernemagnetonet triton mass (mₜ) tritonmasse (mₜ) triton mass energy equivalent tritonets masse-energiekvivalent triton mass energy equivalent in MeV tritonets masse-energiekvivalent i MeV triton mass in u tritonmasse i u triton molar mass (Mₜ) tritonets molmasse (Mₜ) triton-proton mass ratio masseforhold mellom triton og proton triton relative atomic mass (Ar(t)) tritonets relative atommasse (Ar(t)) triton to proton magnetic moment ratio forhold mellom tritonets magnetiske moment og protonets magnetiske moment helion-electron mass ratio masseforhold mellom helion og elektron helion g factor (gâ‚•) helionets g-faktor (gâ‚•) helion magnetic moment (μₕ) helionets magnetiske moment (μₕ) helion magnetic moment to Bohr magneton ratio forhold mellom helionets magnetiske moment og Bohr-magnetonet helion magnetic moment to nuclear magneton ratio forhold mellom helionets magnetiske moment og kjernemagnetonet helion mass (mâ‚•) helionmasse (mâ‚•) helion mass energy equivalent helionets masse-energiekvivalent helion mass energy equivalent in MeV helionets masse-energiekvivalent i MeV helion mass in u helionmasse i u helion molar mass (Mâ‚•) helionets molmasse (Mâ‚•) helion-proton mass ratio masseforhold mellom helion og proton helion relative atomic mass (Ar(h)) helionets relative atommasse (Ar(h)) helion shielding shift skjermingsforskyvning for helion shielded helion gyromagnetic ratio gyromagnetisk forhold for skjermet helion shielded helion gyromagnetic ratio in MHz/T gyromagnetisk forhold for skjermet helion i MHz/T shielded helion magnetic moment magnetisk moment for skjermet helion shielded helion magnetic moment to Bohr magneton ratio forhold mellom magnetisk moment for skjermet helion og Bohr-magnetonet shielded helion magnetic moment to nuclear magneton ratio forhold mellom magnetisk moment for skjermet helion og kjernemagnetonet shielded helion to proton magnetic moment ratio forhold mellom skjermet helions magnetiske moment og protonets magnetiske moment shielded helion to shielded proton magnetic moment ratio forhold mellom magnetisk moment for skjermet helion og skjermet proton alpha particle mass alfapartikkelmasse alpha particle mass in u alfapartikkelmasse i u alpha particle mass energy equivalent alfapartikkelens masse-energiekvivalent alpha particle mass energy equivalent in MeV alfapartikkelens masse-energiekvivalent i MeV alpha particle-electron mass ratio masseforhold mellom alfapartikkel og elektron alpha particle-proton mass ratio masseforhold mellom alfapartikkel og proton alpha particle rms charge radius alfapartikkelens rms-ladningsradius alpha particle molar mass alfapartikkelens molmasse alpha particle relative atomic mass (Ar(α)) alfapartikkelens relative atommasse (Ar(α)) atomic mass constant (mᵤ) atommassekonstant (mᵤ) Avogadro constant Avogadro-konstant Boltzmann constant (k) Boltzmann-konstant (k) Boltzmann constant in eV/K Boltzmann-konstant i eV/K Boltzmann constant in Hz/K Boltzmann-konstant i Hz/K Boltzmann constant in inverse meter per kelvin Boltzmann-konstant i inverse meter per kelvin electron volt (eV) elektronvolt (eV) Faraday constant (F) Faraday-konstant (F) first radiation constant (câ‚�) første strÃ¥lingskonstant (câ‚�) first radiation constant for spectral radiance første strÃ¥lingskonstant for spektral radians molar gas constant (R) molar gasskonstant (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Loschmidt-konstant (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Loschmidt-konstant (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molar Planck-konstant second radiation constant (câ‚‚) andre strÃ¥lingskonstant (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Boltzmann-konstant (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) gitteravstand for ideelt Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atommassekonstantens energi-ekvivalent atomic mass constant energy equivalent in MeV atommassekonstantens energi-ekvivalent i MeV atomic mass unit-electron volt relationship sammenheng mellom atommasseenhet og elektronvolt molar mass constant (Mᵤ) molmassekonstant (Mᵤ) molar mass of carbon-12 molmasse for karbon-12 molar volume of ideal gas (273.15 K, 100 kPa) molart volum for ideell gass (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) molart volum for ideell gass (273.15 K, 101.325 kPa) molar volume of silicon molart volum for silisium Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode-konstant (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode-konstant (1 K, 101.325 kPa) Wien frequency displacement law constant Wiens frekvensforskyvningskonstant Wien wavelength displacement law constant Wiens bølgelengdeforskyvningskonstant standard atmosphere (atm) standardatmosfære (atm) standard-state pressure (p°) standardtilstandstrykk (p°) Angstrom star (Ã…*) angstrom-stjerne (Ã…*) Copper x unit kobber-x-enhet Molybdenum x unit molybden-x-enhet atomic unit of magnetizability atomær enhet for magnetiserbarhet atomic unit of mass (mâ‚‘) atomær enhet for masse (mâ‚‘) atomic unit of momentum atomær enhet for bevegelsesmengde atomic unit of permittivity atomær enhet for permittivitet atomic unit of time atomær enhet for tid atomic unit of velocity atomær enhet for hastighet hartree-hertz relationship sammenheng mellom hartree og hertz hartree-inverse meter relationship sammenheng mellom hartree og invers meter hartree-joule relationship sammenheng mellom hartree og joule hartree-kelvin relationship sammenheng mellom hartree og kelvin hartree-kilogram relationship sammenheng mellom hartree og kilogram shielding difference of d and p in HD skjermingsforskjell mellom d og p i HD shielding difference of t and p in HT skjermingsforskjell mellom t og p i HT pi (Ï€) pi (Ï€) Euler's number (e) Eulers tall (e) golden ratio (φ) det gylne snitt (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni-konstant (γ) nominal solar radius nominell solradius nominal solar total irradiance nominell total solinnstrÃ¥ling nominal solar luminosity nominell solluminositet nominal solar effective temperature nominell effektiv soltemperatur nominal solar mass parameter nominell solmasseparameter nominal terrestrial equatorial radius nominell ekvatorialradius for jorden nominal terrestrial polar radius nominell polarradius for jorden nominal terrestrial mass parameter nominell jordmasseparameter nominal jovian equatorial radius nominell ekvatorialradius for Jupiter nominal jovian polar radius nominell polarradius for Jupiter nominal jovian mass parameter nominell jupitermasseparameter average value of one minus the rate of TCG relative to TCB gjennomsnittsverdi av én minus raten for TCG relativt til TCB solar mass parameter (TCB-compatible) solmasseparameter (TCB-kompatibel) solar mass parameter (TDB-compatible) solmasseparameter (TDB-kompatibel) equatorial radius of the Earth (TT-compatible) jordens ekvatorialradius (TT-kompatibel) dynamical form factor of the Earth jordens dynamiske formfaktor time rate of change in the dynamical form factor of the Earth endringsrate for jordens dynamiske formfaktor geocentric gravitational constant (TCB-compatible) geosentrisk gravitasjonskonstant (TCB-kompatibel) geocentric gravitational constant (TT-compatible) geosentrisk gravitasjonskonstant (TT-kompatibel) geocentric gravitational constant (TDB-compatible) geosentrisk gravitasjonskonstant (TDB-kompatibel) potential of the geoid geoidens potensial nominal mean angular velocity of the Earth (TT-compatible) jordens nominelle midlere vinkelhastighet (TT-kompatibel) ratio mass of the Moon to the Earth masseforhold mellom mÃ¥nen og jorden ratio of the mass of the Sun to Mercury masseforhold mellom solen og Merkur ratio of the mass of the Sun to Venus masseforhold mellom solen og Venus ratio of the mass of the Sun to Mars masseforhold mellom solen og Mars ratio of the mass of the Sun to Jupiter masseforhold mellom solen og Jupiter ratio of the mass of the Sun to Saturn masseforhold mellom solen og Saturn ratio of the mass of the Sun to Uranus masseforhold mellom solen og Uranus ratio of the mass of the Sun to Neptune masseforhold mellom solen og Neptun ratio of the mass of the Sun to (134340) Pluto masseforhold mellom solen og (134340) Pluto ratio of the mass of the Sun to (136199) Eris masseforhold mellom solen og (136199) Eris ratio of the mass of (1) Ceres to the Sun masseforhold mellom (1) Ceres og solen ratio of the mass of (2) Pallas to the Sun masseforhold mellom (2) Pallas og solen ratio of the mass of (4) Vesta to the Sun masseforhold mellom (4) Vesta og solen mean obliquity of the ecliptic at J2000.0 ekliptikkens midlere helning ved J2000.0 Electromagnetic Elektromagnetiske Compton wavelength Compton-bølgelengde Astronomy Astronomi ConstantsWidget Domain Domene Subdomain Underdomene No match found Ingen treff funnet Name Navn Value Verdi Unit Enhet Search Søk All Alle CustomKeypadDialog Custom Keypad Tilpasset tastatur Rows: Rader: Columns: Kolonner: Copy preset: Kopier forhÃ¥ndsinnstilling: Basic Grunnleggende Scientific (wide) Vitenskapelig (bredt) Scientific (narrow) Vitenskapelig (smalt) Apply Bruk Row Rad Column Kolonne Label Etikett Behavior VirkemÃ¥te Text Tekst DiagnosticsDialog App Diagnostics Programdiagnostikk Copy to Clipboard Kopier til utklippstavlen Editor Unit Enhet User unit Brukerenhet User function Brukerfunksjon Argument Argument Current result:<br/>%1 Gjeldende resultat:<br/>%1 Selection result:<br/>%1 Resultat for utvalg:<br/>%1 Selection result: n/a Valgresultat: i/t Selection result: %1 Valgresultat: %1 second sekund metre meter kilogram kilogram mole mol radian radian steradian steradian degree Celsius grad celsius cubic metre kubikkmeter cubic millimetre kubikkmillimeter cubic centimetre kubikkcentimeter cubic decimetre kubikkdesimeter cubic kilometre kubikkkilometer square millimetre kvadratmillimeter square kilometre kvadratkilometer square metre kvadratmeter minute minutt hour time day dag astronomical unit astronomisk enhet degree grad arcminute bueminutt arcsecond buesekund milliarcsecond millibuesekund microarcsecond mikrobuesekund hectare hektar litre liter tonne tonn Dalton dalton electronvolt elektronvolt Angstrom Ã¥ngstrøm atmosphere atmosfære atomic mass unit atommasseenhet British thermal unit britisk termisk enhet calorie kalori carat karat cup kopp cup (Imperial) kopp (britisk) cup (Japanese) kopp (japansk) cup (US) kopp (USA) degree Fahrenheit grad fahrenheit fathom favn fluid ounce (Imperial) fluid ounce (britisk) fluid ounce (US) fluid ounce (USA) fluid dram (Imperial) fluid dram (britisk) fluid dram (US) fluid dram (USA) foot fot square foot kvadratfot cubic foot kubikkfot gallon (Imperial) gallon (britisk) gallon (US) gallon (USA) gill (Imperial) gill (britisk) gill (US) gill (USA) gradian gon grain grain gram gram Hartley hartley Hartree energy unit Hartree-energienhet horsepower hestekraft inch tomme square inch kvadrattomme cubic inch kubikktomme karat karat knot knop lightminute lysminutt lightsecond lyssekund lightyear lysÃ¥r long ton long ton mile mile square mile kvadratmile cubic mile kubikkmile mile per hour mile per time kilometre per hour kilometer per time nautical mile nautisk mil ounce unse parsec parsec pint (Imperial) pint (britisk) pint (US) pint (USA) pound pund pounds per square inch pund per kvadrattomme quart (Imperial) quart (britisk) quart (US) quart (USA) oil barrel oljefat beer barrel (US) ølfat (USA) square yard kvadratyard cubic yard kubikkyard short ton short ton tablespoon spiseskje tablespoon (Australian) spiseskje (australsk) tablespoon (Imperial) spiseskje (britisk) tablespoon (US) spiseskje (USA) dessert spoon dessertskje teaspoon teskje teaspoon (Imperial) teskje (britisk) teaspoon (US) teskje (USA) turn omdreining revolution omdreining revolution per minute omdreining per minutt week uke kilowatt hour kilowattime millimetre of mercury millimeter kvikksølv yard yard Julian century juliansk Ã¥rhundre Julian year juliansk Ã¥r sidereal year siderisk Ã¥r tropical year tropisk Ã¥r Evaluator invalid expression Ugyldig uttrykk division by zero Deling pÃ¥ null too time consuming - computation was rejected for tidkrevende - beregningen ble avvist dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensjonskonflikt - størrelser med ulike dimensjoner kan ikke sammenlignes, legges sammen osv. invalid dimension - operation might require dimensionless arguments ugyldig dimensjon - operasjonen kan kreve dimensjonsløse argumenter Computation aborted - encountered numerical instability Beregning avbrutt - numerisk ustabilitet oppstod invalid dimension - function might require dimensionless arguments ugyldig dimensjon - funksjonen kan kreve dimensjonsløse argumenter error feil unit must not be zero enheten mÃ¥ ikke være null Conversion failed - dimension mismatch Konvertering mislyktes - dimensjonskonflikt unknown function or variable Ukjent funskjon eller variabel recursion not supported rekursjon støttes ikke cannot operate on a NaN kan ikke operere pÃ¥ en NaN underflow - tiny result is out of SpeedCrunch's number range underflyt - svært lite resultat er utenfor tallomrÃ¥det til SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflyt - svært stort resultat er utenfor tallomrÃ¥det til SpeedCrunch overflow - logic result exceeds maximum of 256 bits overflyt - logisk resultat overstiger maksimum pÃ¥ 256 biter overflow - integer result exceeds maximum limit for integers overflyt - heltallsresultat overstiger maksimalgrensen for heltall operation is not defined for these arguments operasjonen er ikke definert for disse argumentene wrong number of arguments feil antall argumenter does not take NaN as an argument tar ikke NaN som argument result out of range resultatet er utenfor gyldig omrÃ¥de undefined for argument domain udefinert for argumentomrÃ¥det computation too expensive beregningen er for kostbar internal error, please report a bug intern feil, vennligst rapporter en feil syntax error syntaksfeil conversion target must be a unit konverteringsmÃ¥let mÃ¥ være en enhet unknown unit ukjent enhet %1 is a reserved name, please choose another %1 er et reservert navn, velg et annet %1 is a global user definition and cannot be overridden in this session. %1 er en global brukerdefinisjon og kan ikke overstyres i denne økten. %1 is a variable name, please choose another or delete the variable %1 er et variabelnavn, velg et annet eller slett variabelen argument %1 is used more than once argumentet %1 brukes mer enn én gang %1 is a built-in unit name, please choose another %1 er et innebygd enhetsnavn, velg et annet %1 is a user function name, please choose another or delete the function %1 er navnet pÃ¥ en brukerfunksjon, velg et annet eller slett funksjonen FunctionRepo max; trials; probability maks; forsøk; sannsynlighet trials; probability forsøk; sannsynlighet hits; trials; probability treff; forsøk; sannsynlighet max; total; hits; trials maks; totalt; treff; forsøk total; hits; trials totalt; treff; forsøk count; total; hits; trials antall; totalt; treff; forsøk dividend; divisor dividend; divisor x; exponent_bits; significand_bits [; exponent_bias] x; eksponentbiter; signifikandbiter [; eksponentskjevhet] base; x base; x value; modulo verdi; modulo base; exponent; modulo base; eksponent; modulo events; average_events hendelser; gjennomsnittlige_hendelser average_events gjennomsnittlige_hendelser x [; precision] x [; presisjon] Absolute Value Absoluttverdi Absolute Deviation Absolutt avvik Arc Cosine Arkuskosinus Logical AND Logisk OG Area Hyperbolic Cosine Areal hyperbolsk kosinus Area Hyperbolic Sine Areal hyperbolsk sinus Area Hyperbolic Tangent Areal hyperbolsk tangens Arc Sine Arkussinus Arc Tangent Arkustangens Arc Tangent with two Arguments Arkustangens med to argumenter Average (Arithmetic Mean) Gjennomsnitt (aritmetisk middel) Binomial Cumulative Distribution Function Binomisk kumulativ fordelingsfunksjon Binomial Distribution Mean Middelverdi for binomisk fordeling Binomial Probability Mass Function Sannsynlighetsmassefunksjon for binomisk fordeling Binomial Distribution Variance Varians for binomisk fordeling Cube Root Kubikkrot Complex Conjugate Komplekst konjugat Cosine Kosinus Hyperbolic Cosine Hyperbolsk kosinus Cotangent Kotangens Cosecant Kosekans Convert Unix timestamp to Date Konverter Unix-tidsstempel til dato Degrees of Arc Buegrader Error Function Feilfunksjon Complementary Error Function Komplementær feilfunksjon Exponential Exponentiell Fractional Part Brøkdel Extension of Factorials [= (x-1)!] Utvidelse av fakulteter [= (x-1)!] Greatest Common Divisor Største felles divisor Geometric Mean Geometrisk middel Gradians of arc Buegradianer Hypergeometric Cumulative Distribution Function Hypergeometrisk kumulativ fordelingsfunksjon Hypergeometric Distribution Mean Middelverdi for hypergeometrisk fordeling Hypergeometric Probability Mass Function Sannsynlighetsmassefunksjon for hypergeometrisk fordeling Hypergeometric Distribution Variance Varians for hypergeometrisk fordeling Integer Quotient Heltallskvotient Integer Part Heltallsdel Imaginary Part Imaginærdel Decode IEEE-754 Binary Value Avkod IEEE-754-binærverdi Encode IEEE-754 Binary Value Kod IEEE-754-binærverdi Decode 16-bit Half-Precision Value Avkod 16-bits halvpresisjonsverdi Encode 16-bit Half-Precision Value Kod 16-bits halvpresisjonsverdi Decode 32-bit Single-Precision Value Avkod 32-bits enkelpresisjonsverdi Encode 32-bit Single-Precision Value Kod 32-bits enkelpresisjonsverdi Decode 64-bit Double-Precision Value Avkod 64-bits dobbeltpresisjonsverdi Encode 64-bit Double-Precision Value Kod 64-bits dobbeltpresisjonsverdi Decode 128-bit Quad-Precision Value Avkod 128-bits firedobbel presisjonsverdi Encode 128-bit Quad-Precision Value Kod 128-bits firedobbel presisjonsverdi Binary Logarithm Binær logaritme Common Logarithm Vanlig logaritme Natural Logarithm Naturlig logaritme Logarithm to Arbitrary Base Logaritme med vilkÃ¥rlig base Mask to a bit size Masker til en bitstørrelse Maximum Maksimum Median Value (50th Percentile) Medianverdi (50. persentil) Minimum Minimum Modulo Modulo Euclidean Modulo Euklidisk modulo Modular Exponentiation Modulær eksponentiering Combination (Binomial Coefficient) Kombinasjon (binomialkoeffisient) Logical NOT Logisk IKKE Permutation (Arrangement) Permutasjon (arrangement) Convert to Binary Representation Konverter til binær representasjon Arithmetic Aritmetikk Chemistry Kjemi Complex Kompleks Combinatorics Kombinatorikk Probability Sannsynlighet Statistics Statistikk Aggregation Aggregering Random Tilfeldig Base conversion Basekonvertering Number formatting Tallformatering Integer arithmetic Heltallsaritmetikk Special functions Spesialfunksjoner Exponential & Logarithmic Eksponentiell og logaritmisk Angle conversion Vinkelkonvertering Trigonometry Trigonometri Bitwise Bitvis Floating point Flyttall Date & Time Dato og klokkeslett Linear algebra Lineær algebra unix_timestamp; x hours offset to GMT unix_tidsstempel; x timers forskyvning fra GMT yyyymmdd.hhmmss; x hours offset to GMT ååååmmdd.ttmmss; x timers forskyvning fra GMT [digits] [sifre] max [; min] maks [; min] List Literal Listeliteral Convert to Padded Binary Representation Konverter til utfylt binær representasjon Round Toward +∞ (Ceiling) Avrund mot +∞ (tak) Cosine plus Imaginary Sine Cosinus pluss imaginær sinus Convert to Cis Complex Form Konverter til cis-kompleksform Matrix Column Count Antall matrise-kolonner Population Correlation Matrix (n) Populasjonskorrelasjonsmatrise (n) Sample Correlation Matrix (n-1) Utvalgskorrelasjonsmatrise (n-1) Count Antall Population Covariance Matrix (n) Populasjonskovariansmatrise (n) Sample Covariance Matrix (n-1) Utvalgskovariansmatrise (n-1) Cross Product Kryssprodukt Convert Date to Unix timestamp Konverter dato til Unix-tidsstempel Convert to Decimal Representation Konverter til desimal representasjon Determinant Determinant Convert to Sexagesimal Notation Konverter til seksagesimal notasjon Dot Product Prikkprodukt Convert to Engineering Notation Konverter til teknisk notasjon Convert to Exponential Complex Form Konverter til eksponentiell kompleksform Round Toward −∞ (Floor) Avrund mot −∞ (gulv) Flatten Matrix Flat ut matrise Least Common Multiple Minste felles multiplum Convert to Hexadecimal Representation Konverter til heksadesimal representasjon Convert to Padded Hexadecimal Representation Konverter til utfylt heksadesimal representasjon Inverse Matrix Invers matrise Round to 16-bit Half-Precision Value Avrund til 16-biters halvpresisjonsverdi Round to 32-bit Single-Precision Value Avrund til 32-biters enkeltpresisjonsverdi Round to 64-bit Double-Precision Value Avrund til 64-biters dobbeltpresisjonsverdi Round to 128-bit Quad-Precision Value Avrund til 128-biters kvadruppelpresisjonsverdi Residual from 16-bit Half-Precision Rounding Rest fra 16-biters halvpresisjonsavrunding Residual from 32-bit Single-Precision Rounding Rest fra 32-biters enkeltpresisjonsavrunding Residual from 64-bit Double-Precision Rounding Rest fra 64-biters dobbeltpresisjonsavrunding Residual from 128-bit Quad-Precision Rounding Rest fra 128-biters kvadruppelpresisjonsavrunding Substance Mass Stoffmasse Molarity Molaritet Molar Mass Molmasse Median Absolute Deviation Median absoluttavvik Mean Gjennomsnitt Numerical Value of Quantity Numerisk verdi av størrelse Random Decimal Number Tilfeldig desimaltall Random Integer Number Tilfeldig heltall Convert to Rational Representation Konverter til rasjonal representasjon Convert to Octal Representation Konverter til oktal representasjon Convert to Padded Octal Representation Konverter til utfylt oktal representasjon Vector or Matrix Norm Vektor- eller matrisenorm Logical OR Logisk ELLER Population Count (Hamming Weight) Populasjonstelling (Hamming-vekt) Phase of Complex Number Fase til komplekst tall Poissonian Cumulative Distribution Function Poissonsk kumulativ fordelingsfunksjon Poissonian Distribution Mean Middelverdi for poissonfordeling Poissonian Probability Mass Function Sannsynlighetsmassefunksjon for poissonfordeling Poissonian Distribution Variance Varians for poissonfordeling Convert to Phasor Complex Form Konverter til fasor-kompleksform Convert to Rectangular Complex Form Konverter til rektangulær kompleksform Round Half Away from Zero Avrund halv bort fra null Round Half Even Avrund halv til partall Nth Root N-te rot Convert to Scientific Notation Konverter til vitenskapelig notasjon Matrix Row Count Antall matrise-rader List or Matrix Shape Liste- eller matriseform Summation Summering Population Standard Deviation (n) Populasjonsstandardavvik (n) Sample Standard Deviation (n-1) Utvalgsstandardavvik (n-1) Round Toward Zero (Truncation) Avrund mot null (trunkering) Matrix Trace Matrisens spor Transpose Matrix Transponer matrise Population Variance (n) Populasjonsvarians (n) Sample Variance (n-1) Utvalgsvarians (n-1) Product Produkt Radians Radianer Matrix Rank Matriserang Real Part Realdel Secant Sekans Arithmetic Shift Left Aritmetisk venstreskift Arithmetic Shift Right Aritmetisk høyreskift Signum Signum Sine Sinus Hyperbolic Sine Hyperbolsk sinus Square Root Kvadratrot Sum Sum Tangent Tangens Convert to Trigonometric Complex Form Konverter til trigonometrisk kompleksform Turns Omdreininger Hyperbolic Tangent Hyperbolsk tangens Sign-extend a value Fortegnsekstender en verdi Logical XOR Logisk XOR FunctionsWidget Domain Domene All Alle Name Navn Search Søk No match found Ingen treff funnet Identifier Identifikator HistoryWidget Remove All Calculations Above Fjern alle beregninger over Remove This Calculation Fjern denne beregningen Remove All Calculations Below Fjern alle beregninger under Keypad Inverse cosine Invers kosinus The last result Siste resultat Inverse sine Invers sinus Inverse tangent Arc tangens Evaluate expression Evaluer uttrykk Division Divisjon Multiplication Multiplikasjon Subtraction Subtraksjon Addition Addisjon Clear expression Fjern uttrykk Cosine Kosinus Backspace Tilbake Scientific notation Teknisk notasjon Exponential Exponentiell Factorial Fakultet Natural logarithm Naturlig logaritme Left parenthesis Venstre parentes Nth root N-te rot Argument separator Argumentskilletegn Square Kvadrat Common logarithm Titalslogaritme Modulo Modulo Contextual percentage Kontekstuell prosent Power Potens Right parenthesis Høyre parentes Sine Sinus Square root Kvadratrot Tangent Tangens Pi Pi Decimal separator Desimalskilletegn MainWindow Radian Radian Degree Grader Gradian Gon Binary Binær Octal Oktal Hexadecimal Heksadesimal Sexagesimal Seksagesimal Engineering decimal Teknisk desimal Scientific decimal Vitenskapelig desimal &Import... &Importer... &Quit &Avslutt Clear E&xpression Fjern &uttrykk Clear &History Tøm &historikk &Copy &Kopier &Paste &Lim inn &Select Expression &Velg uttrykk &Constants &Konstanter &Functions &Funksjoner &History &Historikk &Status Bar Status&linje Bitfield Bitfelt Use&r Functions Bruker&funksjoner &Degree &Grader &Radian &Radian &Gradian &Gon Re&volution O&mdreining Auto-Insert a&ns Sett i&nn ans automatisk Automatic &Completion Automatisk &fullføring &Built-in Functions Inne&bygde funksjoner Built-in &Variables Innebygde &variabler User &Functions Bruker&funksjoner User Va&riables B&rukervariabler Open a Private Tab on Startup Ã…pne en privat fane ved oppstart Open and focus a new private tab whenever SpeedCrunch starts. Ã…pne og aktiver en ny privat fane hver gang SpeedCrunch starter. Syntax &Highlighting Syntaks&utheving Group Digits in &Input Grupper s&ifre i inndata Automatic Input &Adjustments &Automatiske inndatajusteringer Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Juster operatorer, mellomrom, parenteser og potenser automatisk, og begrens inndata til gyldige tegn. Group input digits using the selected number format. Grupper inntastede sifre etter det valgte tallformatet. &Blinking Cursor &Blinkende markør Blink the cursor in the expression editor. La markøren blinke i uttrykksredigereren. &Escape Clears Editor &Escape tømmer redigereren Clear the focused expression editor with Escape after dismissing any popup or preview. Tøm den aktive uttrykksredigereren med Escape etter at eventuelle sprettoppvinduer eller forhÃ¥ndsvisninger er lukket. Keep Expression After Evaluation Behold uttrykket etter beregning Copy New Results Automatically Kopier nye resultater automatisk &Comma &Komma &System Default &Systemstandard &Dot &Punktum Dot &And Comma Punktum &og komma Toward +∞ (&ceil) Mot +∞ (&ceil) Toward −∞ (&floor) Mot −∞ (&floor) &Binary &Binær &Engineering &Teknisk &Hexadecimal &Heksadesimal &Octal &Oktal &Scientific &Vitenskapelig User &Manual Bruker&hÃ¥ndbok Issues and &Feedback &Problemer og tilbakemeldinger &Donate &Doner &About SpeedCrunch O&m SpeedCrunch App Diag&nostics Programdiag&nostikk S&plit &Del Angle &Mode Vinkel&modus &Complex Form &Kompleks form New Tab Ny fane Constants Konstanter Functions Funksjoner History Historikk User Functions Brukerfunksjoner &Font... &Skrift... &Language... &SprÃ¥k... &Session &Økt &Edit &Rediger &View &Vis Se&ttings &Innstillinger &Decimal &Desimal &Keypad &Nummertastatur Always on &Top Alltid &øverst Disabled Deaktivert Small Space Liten avstand Medium Space Middels avstand Large Space Stor avstand &0 Digits &0 sifre &15 Digits &15 sifre &2 Digits &2 sifre &3 Digits &3 sifre &50 Digits &50 sifre &8 Digits &8 sifre &Sexagesimal &Seksagesimal Reset All Settings... Tilbakestill alle innstillinger... &System &System SpeedCrunch &Theme SpeedCrunch-&tema &Classic &Klassisk &Modern &Moderne Context Help Konteksthjelp &Help &Hjelp Error Feil Can't read from file %1 Kan ikke lese fra fil %1 Import Session Importer økt Close Session Lukk økt Angle Mode: Vinkelmodus: Notation: Notasjon: Precision: Presisjon: Turn Omdreining Revolution Omdreining Fixed-point decimal Fast desimal Rational Rasjonal Automatic decimal Automatisk desimal Automatic Automatisk User &Definitions... Bruker&definisjoner... New &Tab Ny &fane New &Private Tab Ny &privat fane Keep Behold Make Private... Gjør privat... New &Window Nytt &vindu &Open... &Ã…pne... &Rename... Gi &nytt navn... Clo&ne... &Klon... &Close Tab &Lukk fane Reopen Clo&sed Tab Ã…pne l&ukket fane pÃ¥ nytt Open Sessions &Folder Ã…pne &øktmappe &Undo &Angre &Redo Gjø&r om Cu&t Klipp u&t Copy &Last Result K&opier siste resultat &Wrap in Parentheses &Sett i parentes Full Scr&een Mode Fullsk&jermmodus &Basic &Grunnleggende &Scientific (wide) &Vitenskapelig (bredt) Scientific (narrow) Vitenskapelig (smalt) &Custom... &Tilpasset... Main &Menu Hoved&meny User &Variables Bruker&variabler &Left &Venstre &Right Høy&re &Up &Opp &Down Ne&d Close Pa&ne L&ukk rute User &Units Bruker&enheter &Turn &Omdreining If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Hvis et nytt uttrykk starter med +, -, *, eller /, setter SpeedCrunch inn "ans" først. &Accept with Enter &Godta med Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Godta det gjeldende forslaget til automatisk fullføring med Enter uten først Ã¥ velge det med piltastene. &Units &Enheter Show Live Result &Preview Vis levende resultat&forhÃ¥ndsvisning Save &Window Position on Exit Lagre &vindusposisjon ved avslutning Hover Highlighting Utheving ved peking Group Integer Part Only Grupper bare heltallsdelen Number Format... Tallformat... Notation && Precision... Notasjon og presisjon... After pressing Enter, keep the entered expression selected in the editor. Behold det inntastede uttrykket markert i redigeringsfeltet etter Enter. Never Aldri Always Alltid Only for Single-Line Expressions Bare for uttrykk pÃ¥ én linje Simplify Displayed Expressions Forenkle viste uttrykk History Size &Limit... &Grense for historikkstørrelse... Remove Trailing &Zeroes F&jern etterfølgende nuller Nearest, Half &Away (round) Nærmeste, halv &bort (round) Nearest, Half &Even (roundeven) Nærmeste, halv &partall (roundeven) Toward &Zero (trunc) Mot &null (trunc) &Fixed-Point &Fast desimal &Rational &Rasjonal &Exponential (m·sâ�»Â¹) &Eksponentiell (m·sâ�»Â¹) &Fractional (m/s) &Brøkform (m/s) &Rectangular (a + bi) &Rektangulær (a + bi) Exponential (reâ�±á¶¿) Eksponentiell (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrisk (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Tema... Check for &Updates Se etter &oppdateringer Source Code Kildekode &Zoom &Zoom &Results &Resultater Unit Notation Enhetsnotasjon Rounding Mode Avrundingsmodus &Notation &Notasjon &Imaginary Unit &Imaginær enhet &Window &Vindu &Editing &Redigering A&utocomplete A&utofullfør Up/Down Arrow History Historikk med pil opp/ned &Appearance &Utseende &Menus &Menyer &Docks &Dokkpaneler &Input and Results &Inndata og resultater &Disabled &Deaktivert &Disable &Deaktiver Close preview Lukk forhÃ¥ndsvisning Rename... Gi nytt navn... Clone... Klon... Close Tab Lukk fane New Private Tab Ny privat fane Open... Ã…pne... Reopen Closed Tab Ã…pne lukket fane pÃ¥ nytt Split Del Left Venstre Right Høyre Up Opp Down Ned Clear Tøm Delete Slett %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Privat økt: innholdet forkastes nÃ¥r den lukkes. Velg Økt > Behold for Ã¥ gjøre den til en vanlig økt. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privat] Reset All Settings Tilbakestill alle innstillinger Reset all settings to their default values? Tilbakestille alle innstillinger til standardverdiene? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Dette omfatter utseende, redigering, resultatformater og vindusinnstillinger. Beregningene dine, Ã¥pne økter og brukerdefinisjoner beholdes. The settings file could not be written. Kunne ikke skrive innstillingsfilen. Clear this session's calculations, unfinished expression, variables, functions, and units? Tømme denne øktens beregninger, uferdige uttrykk, variabler, funksjoner og enheter? Global user definitions are kept. Globale brukerdefinisjoner beholdes. Make Session Private Gjør økten privat The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Den lagrede økten %1 slettes. Innholdet forblir Ã¥pent i en privat økt og forkastes nÃ¥r økten lukkes eller SpeedCrunch avsluttes. Make Private Gjør privat Could not delete the saved session %1. Kunne ikke slette den lagrede økten %1. Keep Session Behold økt Could not save the session. It remains private. Kunne ikke lagre økten. Den forblir privat. Clone Session Klon økt Could not save session file %1. Kunne ikke lagre øktfilen %1. Could not delete session file %1. Kunne ikke slette øktfilen %1. JSON file (*.json);;Any file (*.*) JSON-fil (*.json);;Alle filer (*.*) Export session as JSON Eksporter økt som JSON The selected file is not valid JSON: %1 Den valgte filen er ikke gyldig JSON: %1 The selected file is not a SpeedCrunch session JSON file. Den valgte filen er ikke en JSON-fil for en SpeedCrunch-økt. This file uses an obsolete SpeedCrunch session format and cannot be imported. Denne filen bruker et foreldet SpeedCrunch-øktformat og kan ikke importeres. The selected JSON file is missing the required $schema field. Den valgte JSON-filen mangler det pÃ¥krevde $schema-feltet. The selected JSON file uses an unsupported JSON schema: %1 Den valgte JSON-filen bruker et JSON-skjema som ikke støttes: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Den valgte JSON-filen mangler SpeedCrunch-øktens skjemaidentifikator ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Den valgte JSON-filen bruker et SpeedCrunch-øktformat som ikke støttes: %1 The selected JSON file is missing the required session name. Den valgte JSON-filen mangler det pÃ¥krevde øktnavnet. The selected JSON file has an empty session name. Den valgte JSON-filen har et tomt øktnavn. The selected JSON file has invalid or incomplete SpeedCrunch session data. Den valgte JSON-filen har ugyldige eller ufullstendige SpeedCrunch-øktdata. Open Sessions Folder Ã…pne øktmappe Could not create the sessions folder: %1 Kunne ikke opprette øktmappen: %1 Could not open the sessions folder: %1 Kunne ikke Ã¥pne øktmappen: %1 Editor and Results Font Skrift for redigerer og resultater Open Session Ã…pne økt Community Fellesskap Rename Session Gi økten nytt navn Clear Session Tøm økt Delete Session Slett økt Close Pane Lukk rute User Variables Brukervariabler User Units Brukerenheter Clear History Tøm historikk Are you sure you want to clear the calculation history? Er du sikker pÃ¥ at du vil tømme beregningshistorikken? Session name: Øktnavn: A session named %1 already exists. En økt med navnet %1 finnes allerede. Could not create session file %1. Kunne ikke opprette øktfilen %1. Could not write session file %1. Kunne ikke skrive øktfilen %1. Are you sure you want to delete this session? Er du sikker pÃ¥ at du vil slette denne økten? Custom Precision Tilpasset presisjon Fractional digits: Desimaler: Theme Tema Light Themes Lyse temaer Dark Themes Mørke temaer Preview ForhÃ¥ndsvisning Colors Farger Select color for %1 Velg farge for %1 Import... Importer... Export... Eksporter... Import Theme Importer tema Theme file (*.json);;All files (*) Temafil (*.json);;Alle filer (*) Invalid theme file. Ugyldig temafil. Can't import theme "%1" because it conflicts with a built-in theme. Kan ikke importere temaet "%1" fordi det er i konflikt med et innebygd tema. Can't find a writable theme folder. Finner ingen skrivbar temamappe. Overwrite Theme Overskriv tema A custom theme named "%1" already exists. Do you want to overwrite it? Et tilpasset tema med navnet "%1" finnes allerede. Vil du overskrive det? Can't overwrite theme file %1 Kan ikke overskrive temafilen %1 Can't copy theme file to %1 Kan ikke kopiere temafilen til %1 Export Theme Eksporter tema Can't export theme as "%1" because it conflicts with a built-in theme. Kan ikke eksportere temaet som "%1" fordi det er i konflikt med et innebygd tema. Can't write to file %1 Kan ikke lagre filen %1 Global User Variable Global brukervariabel Global User Function Global brukerfunksjon Global User Unit Global brukerenhet User Definitions Brukerdefinisjoner These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Disse definisjonene er globale og lastes inn i hver økt. De kan ikke endres i øktene og overstyrer definisjoner med samme navn fra økteditoren. Skriv én definisjon per linje. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Eksempler: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Bruk Validate Valider Test Results Testresultater Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Importerte variabler: %1 Importerte funksjoner: %2 Importerte enheter: %3 Linjenumre med feil: %4 none ingen Apply Results Resultater av bruk User definitions saved. Brukerdefinisjoner lagret. History Size Limit Grense for historikkstørrelse Maximum number of history entries for this session (0 = unlimited): Maksimalt antall historikkoppføringer for denne økten (0 = ubegrenset): Text file (*.txt);;Any file (*.*) Tekstfil (*.txt);;Alle filer (*.*) Could not recalculate from calculation %1: %2 Kunne ikke beregne pÃ¥ nytt fra beregning %1: %2 History Size Limit Reached Grense for historikkstørrelse nÃ¥dd This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Denne beregningen fyller den siste tilgjengelige historikkplassen. Fremtidige beregninger fjerner den eldste beregningen fra historikken. Du kan øke grensen fra Økt > Grense for historikkstørrelse. Editing calculation. Press Esc twice to cancel. Redigerer beregning. Trykk Esc to ganger for Ã¥ avbryte. Calculation Settings Beregningsinnstillinger Invalid recalculation start index Ugyldig startindeks for ny beregning System Default Systemstandard Language SprÃ¥k Select the language: Velg sprÃ¥k: Custom Tilpasset Decimal places: Desimalplasser: &Automatic &Automatisk &Precision &Presisjon Plain &text Ren &tekst Formula &Book Formel&samling &Export &Eksporter Export session as HTML Eksporter økt som HTML HTML file (*.html) HTML-fil (*.html) Export session as plain text Eksporter økt som ren tekst ManualWindow SpeedCrunch Manual SpeedCrunch-hÃ¥ndbok %1 - SpeedCrunch Manual %1 - SpeedCrunch-hÃ¥ndbok NumberFormatDialog Number Format Tallformat <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Velg tallformat for resultater og gruppering av inntastede sifre.</b><br/><br/>Merk: entydige formater godtas for inntastede tall selv om de avviker fra det valgte visningsformatet.<br/> QObject Global User Variable Global brukervariabel Global User Function Global brukerfunksjon Global User Unit Global brukerenhet Backspace Tilbake Clear expression Fjern uttrykk Evaluate expression Evaluer uttrykk Insert text Sett inn tekst Automatic decimal Automatisk desimal Fixed-point decimal Fast desimal Engineering decimal Teknisk desimal Scientific decimal Vitenskapelig desimal Rational Rasjonal Binary Binær Octal Oktal Hexadecimal Heksadesimal Sexagesimal Seksagesimal Update Available Oppdatering tilgjengelig A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> En nyere versjon (%1) er tilgjengelig.<br/><a href="%2">Besøk nettstedet for Ã¥ laste ned.</a> Check for Updates Se etter oppdateringer SpeedCrunch %1 is up to date. SpeedCrunch %1 er oppdatert. No connectivity. Please check your internet connection and try again. Ingen tilkobling. Kontroller internettforbindelsen og prøv igjen. Could not verify the latest available version. Kunne ikke kontrollere nyeste tilgjengelige versjon. ResultDisplay Scroll to bottom Rull til bunnen Edit Expression Rediger uttrykk Change Settings Endre innstillinger New Tab Ny fane &Import... &Importer... &Export &Eksporter Plain &text Ren &tekst Copy Kopier Selection Utvalg Select All Velg alt Expression Uttrykk Result Resultat Calculation Beregning Calculation as Single Line Beregning pÃ¥ én linje Remove Fjern This Calculation Denne beregningen All Calculations Above Alle beregninger ovenfor All Calculations Below Alle beregninger nedenfor New Private Tab Ny privat fane Session Økt Open... Ã…pne... Clone... Klon... Rename... Gi nytt navn... Keep Behold Make Private... Gjør privat... Clear Tøm Delete Slett Close Lukk Split Del Left Venstre Right Høyre Up Opp Down Ned Close Pane Lukk rute Main Menu Hovedmeny Cancel editing Avbryt redigering Copy result Kopier resultat Edit expression Rediger uttrykk Change settings Endre innstillinger Remove calculation Fjern beregning ResultSlotsDialog Notation & Precision Notasjon og presisjon Result Line Resultatlinje Enabled Aktivert Notation Notasjon Decimal Places Desimalplasser Main Line Hovedlinje Extra Line #1 Ekstra linje nr. 1 Extra Line #2 Ekstra linje nr. 2 Extra Line #3 Ekstra linje nr. 3 Extra Line #4 Ekstra linje nr. 4 Auto Auto UserFunctionListWidget Name Navn Value Verdi Description Beskrivelse Search Søk No match found Ingen treff funnet Insert Sett inn Edit Rediger Delete Slett Delete All Slett alle UserUnitListWidget Name Navn Value Verdi Description Beskrivelse Search Søk No match found Ingen treff funnet Insert Sett inn Edit Rediger Delete Slett Delete All Slett alle VariableListWidget Name Navn Value Verdi Description Beskrivelse Search Søk No match found Ingen treff funnet Insert Sett inn Edit Rediger Delete Slett Delete All Slett alle heldercorreia-speedcrunch-e7ca37f/src/resources/locale/nl.ts000066400000000000000000010551101526573132500243610ustar00rootroot00000000000000 AboutBox About SpeedCrunch Over SpeedCrunch Core developers Hoofdontwikkelaars Original author Originele auteur Close Sluiten Math engine Rekenmotor Main author | Logo | Maintainer Hoofdauteur | Logo | Onderhouder Thanks Dankbetuigingen Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 De ontwikkelaars van SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Dit programma is vrije software; u mag het verspreiden en/of wijzigen onder de voorwaarden van de GNU General Public License, zoals gepubliceerd door de Free Software Foundation; versie 2 van de licentie, of (naar keuze) een latere versie This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Dit programma wordt verspreid in de hoop dat het nuttig zal zijn, maar ZONDER ENIGE GARANTIE; zelfs zonder de impliciete garantie van VERKOOPBAARHEID of GESCHIKTHEID VOOR EEN BEPAALD DOEL. Zie de GNU General Public License voor meer informatie. BitFieldWidget Reset bits to zero Bits terugzetten naar nul Invert bits Bits inverteren Shift bits left Bits naar links verschuiven Shift bits right Bits naar rechts verschuiven Book Index Inhoud Algebra Algebra Quadratic Equation Kwadratische vergelijking Logarithmic Base Conversion Logaritmische basisconversie Geometry Geometrie Circle Cirkel Sector Cirkelsector Sphere Bol Cube Kubus Cone Kegel Cylinder Cilinder Electronics Elektronica Ohm's Law Wet van Ohm Power Macht Reactance Reactantie Resonance Resonantie Radio Frequency Radiofrequentie Antennas Antennes Characteristic Impedance (coax) Karakteristieke impedantie (coax) Velocity of Propagation (coax) Voortplantingssnelheid (coax) Standing Wave Ratio & Return Loss Staande golfratio & retourverlies Free Space Wavelength Golflengte in vrije ruimte resistance weerstand voltage spanning current stroom power vermogen inductive reactance inductieve reactantie capacitive reactance capacitieve reactantie inductance inductantie capacitance capaciteit frequency frequentie resonance frequency resonantiefrequentie area oppervlakte perimeter omtrek diameter middellijn radius straal volume inhoud surface area oppervlakte height hoogte slant height schuine hoogte face diagonal zijdediagonaal space diagonal ruimtediagonaal edge length ribbelengte arc length booglengte central angle (degrees) centrale hoek (graden) input power ingangsvermogen reflected power gereflecteerd vermogen transmitted power overgedragen vermogen return loss retourverlies dielectric constant diëlektrische constante outer conductor's inner diameter binnendiameter van buitenste geleider inner conductor's outer diameter buitendiameter van binnenste geleider speed of light lichtsnelheid reflection coefficient reflectiecoëfficiënt standing wave ratio staande golfratio normalized impedance genormaliseerde impedantie frequency (Hz) frequentie (Hz) BookDock Formula Book Formuleboek ConstantCompletion Search constants Constanten zoeken No match found Geen overeenkomsten gevonden Constants Mathematics Wiskunde Physics (CODATA 2022) Natuurkunde (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Scheikunde (IUPAC - CIAAW 2021) Uncategorized Niet-gecategoriseerd Universal Universeel Physicochemical Fysisch-chemisch Atomic & Nuclear — General Atomair en nucleair - algemeen Atomic & Nuclear — Electroweak Atomair en nucleair - elektrozwak Atomic & Nuclear — Electron Atomair en nucleair - elektron Atomic & Nuclear — Muon Atomair en nucleair - muon Atomic & Nuclear — Tau Atomair en nucleair — Tau Atomic & Nuclear — Proton Atomair en nucleair — Proton Atomic & Nuclear — Neutron Atomair en nucleair — Neutron Atomic & Nuclear — Deuteron Atomair en nucleair — Deuteron Atomic & Nuclear — Triton Atomair en nucleair — Triton Atomic & Nuclear — Helion Atomair en nucleair — Helion Atomic & Nuclear — Alpha particle Atomair & nucleair — alfadeeltje Atomic & Nuclear — Atomic units Atomair & nucleair — atomaire eenheden Atomic & Nuclear — Energy conversion relationships Atomair & nucleair — energieconversierelaties Atomic & Nuclear — X-ray units Atomair & nucleair — röntgeneenheden Atomic & Nuclear — Magnetic shielding corrections Atomair & nucleair — magnetische afschermingscorrecties Masses Massa's Lifetimes Levensduren Molar Masses Molaire massa's Electronegativity Elektronegativiteit Ionization Energy Ionisatie-energie Nominal Constants (IAU 2015) Nominale constanten (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Huidige beste schattingen (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) karakteristieke impedantie van het vacuüm (Zâ‚€) reduced Planck constant (â„�) gereduceerde constante van Planck (â„�) vacuum electric permittivity (ϵ₀) elektrische permittiviteit van het vacuüm (ϵ₀) Newtonian constant of gravitation (G) Newtoniaanse gravitatieconstante (G) vacuum magnetic permeability (μ₀) magnetische permeabiliteit van het vacuüm (μ₀) Planck constant (h) constante van Planck (h) speed of light in vacuum (c) lichtsnelheid in vacuüm (c) standard acceleration of gravity (gâ‚™) standaardvalversnelling (gâ‚™) Newtonian constant of gravitation over h-bar c Newtoniaanse gravitatieconstante gedeeld door h-bar c Planck length Plancklengte Planck constant in eV/Hz (h) constante van Planck in eV/Hz (h) Planck mass Planckmassa Planck mass energy equivalent in GeV energie-equivalent van de Planckmassa in GeV Planck temperature Plancktemperatuur Planck time Plancktijd reduced Planck constant in eV·s (â„�) gereduceerde constante van Planck in eV·s (â„�) reduced Planck constant times c in MeV·fm gereduceerde constante van Planck maal c in MeV·fm Bohr magneton Bohrmagneton conductance quantum (Gâ‚€) geleidingskwantum (Gâ‚€) Coulomb constant (kâ‚‘) constante van Coulomb (kâ‚‘) elementary charge (e) elementaire lading (e) elementary charge over h-bar elementaire lading gedeeld door h-bar conventional value of Josephson constant conventionele waarde van de Josephsonconstante Josephson constant Josephsonconstante conventional value of ampere-90 conventionele waarde van de ampère-90 conventional value of coulomb-90 conventionele waarde van de coulomb-90 conventional value of farad-90 conventionele waarde van de farad-90 conventional value of henry-90 conventionele waarde van de henry-90 conventional value of ohm-90 conventionele waarde van de ohm-90 conventional value of volt-90 conventionele waarde van de volt-90 conventional value of watt-90 conventionele waarde van de watt-90 magnetic flux quantum (Φ₀) magnetisch fluxkwantum (Φ₀) nuclear magneton kernmagneton inverse of conductance quantum inverse van het geleidingskwantum conventional value of von Klitzing constant conventionele waarde van de von Klitzingconstante von Klitzing constant von Klitzingconstante atomic unit of magnetic dipole moment atoomaire eenheid van magnetisch dipoolmoment atomic unit of magnetic flux density atomaire eenheid van magnetische fluxdichtheid Bohr magneton in eV/T Bohrmagneton in eV/T Bohr magneton in Hz/T Bohrmagneton in Hz/T Bohr magneton in inverse meter per tesla Bohrmagneton in inverse meter per tesla Bohr magneton in K/T Bohrmagneton in K/T nuclear magneton in eV/T kernmagneton in eV/T nuclear magneton in inverse meter per tesla kernmagneton in inverse meter per tesla nuclear magneton in K/T kernmagneton in K/T nuclear magneton in MHz/T kernmagneton in MHz/T Bohr radius (aâ‚€) Bohrstraal (aâ‚€) fine-structure constant (α) fijnstructuurconstante (α) Hartree energy (Eâ‚•) Hartree-energie (Eâ‚•) Hartree energy in eV Hartree-energie in eV quantum of circulation circulatiekwantum quantum of circulation times 2 circulatiekwantum maal 2 Rydberg constant (R∞) Rydbergconstante (R∞) atomic mass unit-hartree relationship relatie tussen atomaire massa-eenheid en hartree atomic mass unit-hertz relationship relatie tussen atomaire massa-eenheid en hertz atomic mass unit-inverse meter relationship relatie tussen atomaire massa-eenheid en inverse meter atomic mass unit-joule relationship relatie tussen atomaire massa-eenheid en joule atomic mass unit-kelvin relationship relatie tussen atomaire massa-eenheid en kelvin atomic mass unit-kilogram relationship relatie tussen atomaire massa-eenheid en kilogram atomic unit of 1st hyperpolarizability atomaire eenheid van eerste hyperpolariseerbaarheid atomic unit of 2nd hyperpolarizability atomaire eenheid van tweede hyperpolariseerbaarheid atomic unit of charge (e) atomaire eenheid van lading (e) atomic unit of charge density atomaire eenheid van ladingsdichtheid atomic unit of current atomaire eenheid van stroom atomic unit of electric dipole moment atomaire eenheid van elektrisch dipoolmoment atomic unit of electric field atomaire eenheid van elektrisch veld atomic unit of electric field gradient atomaire eenheid van elektrische veldgradiënt atomic unit of electric polarizability atomaire eenheid van elektrische polariseerbaarheid atomic unit of electric potential atomaire eenheid van elektrische potentiaal atomic unit of electric quadrupole moment atomaire eenheid van elektrisch quadrupoolmoment atomic unit of action atomaire eenheid van werking atomic unit of energy atomaire eenheid van energie atomic unit of force atomaire eenheid van kracht atomic unit of length atomaire eenheid van lengte hertz-atomic mass unit relationship relatie tussen hertz en atomaire massa-eenheid hertz-electron volt relationship relatie tussen hertz en elektronvolt hertz-hartree relationship relatie tussen hertz en hartree hertz-inverse meter relationship relatie tussen hertz en inverse meter hertz-joule relationship relatie tussen hertz en joule hertz-kelvin relationship relatie tussen hertz en kelvin hertz-kilogram relationship relatie tussen hertz en kilogram hyperfine transition frequency of Cs-133 hyperfijne overgangsfrequentie van Cs-133 inverse fine-structure constant (αâ�»Â¹) inverse fijnstructuurconstante (αâ�»Â¹) inverse meter-atomic mass unit relationship relatie tussen inverse meter en atomaire massa-eenheid inverse meter-electron volt relationship relatie tussen inverse meter en elektronvolt inverse meter-hartree relationship relatie tussen inverse meter en hartree inverse meter-hertz relationship relatie tussen inverse meter en hertz inverse meter-joule relationship relatie tussen inverse meter en joule inverse meter-kelvin relationship relatie tussen inverse meter en kelvin inverse meter-kilogram relationship relatie tussen inverse meter en kilogram joule-atomic mass unit relationship relatie tussen joule en atomaire massa-eenheid joule-electron volt relationship relatie tussen joule en elektronvolt joule-hertz relationship relatie tussen joule en hertz joule-hartree relationship relatie tussen joule en hartree joule-inverse meter relationship relatie tussen joule en inverse meter joule-kelvin relationship relatie tussen joule en kelvin joule-kilogram relationship relatie tussen joule en kilogram kelvin-atomic mass unit relationship relatie tussen kelvin en atomaire massa-eenheid kelvin-electron volt relationship relatie tussen kelvin en elektronvolt kelvin-hertz relationship relatie tussen kelvin en hertz kelvin-hartree relationship relatie tussen kelvin en hartree kelvin-inverse meter relationship relatie tussen kelvin en inverse meter kelvin-joule relationship relatie tussen kelvin en joule kelvin-kilogram relationship relatie tussen kelvin en kilogram kilogram-atomic mass unit relationship relatie tussen kilogram en atomaire massa-eenheid kilogram-electron volt relationship relatie tussen kilogram en elektronvolt kilogram-hertz relationship relatie tussen kilogram en hertz kilogram-hartree relationship relatie tussen kilogram en hartree kilogram-inverse meter relationship relatie tussen kilogram en inverse meter kilogram-joule relationship relatie tussen kilogram en joule kilogram-kelvin relationship relatie tussen kilogram en kelvin lattice parameter of silicon (a) roosterparameter van silicium (a) luminous efficacy lichtopbrengst natural unit of energy natuurlijke eenheid van energie natural unit of energy in MeV natuurlijke eenheid van energie in MeV natural unit of action (â„�) natuurlijke eenheid van werking (â„�) natural unit of action in eV·s natuurlijke eenheid van werking in eV·s natural unit of length natuurlijke eenheid van lengte natural unit of mass natuurlijke eenheid van massa natural unit of momentum natuurlijke eenheid van impuls natural unit of momentum in MeV/c natuurlijke eenheid van impuls in MeV/c natural unit of time natuurlijke eenheid van tijd natural unit of velocity natuurlijke eenheid van snelheid Rydberg constant times c in Hz Rydbergconstante maal c in Hz Rydberg constant times hc in eV Rydbergconstante maal hc in eV Rydberg constant times hc in J Rydbergconstante maal hc in J Fermi coupling constant Fermi-koppelingsconstante weak mixing angle zwakke menghoek W to Z mass ratio massaverhouding W tot Z Thomson cross section (σₑ) Thomson-werkzame doorsnede (σₑ) electron mass (mâ‚‘) elektronenmassa (mâ‚‘) electron mass in u elektronenmassa in u electron mass energy equivalent (mₑ·c²) energie-equivalent van de elektronenmassa (mₑ·c²) electron mass energy equivalent in MeV energie-equivalent van de elektronenmassa in MeV reduced Compton wavelength gereduceerde Comptongolflengte classical electron radius (râ‚‘) klassieke elektronenstraal (râ‚‘) electron charge to mass quotient quotiënt van elektronenlading en massa electron-deuteron magnetic moment ratio verhouding tussen magnetisch moment van elektron en deuteron electron-deuteron mass ratio massaverhouding tussen elektron en deuteron electron g factor (gâ‚‘) g-factor van het elektron (gâ‚‘) electron gyromagnetic ratio (γₑ) gyromagnetische verhouding van het elektron (γₑ) electron gyromagnetic ratio in MHz/T gyromagnetische verhouding van het elektron in MHz/T electron-helion mass ratio massaverhouding tussen elektron en helion electron magnetic moment (μₑ) magnetisch moment van het elektron (μₑ) electron magnetic moment anomaly (aâ‚‘) anomalie van het magnetisch moment van het elektron (aâ‚‘) electron magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het elektron en Bohrmagneton electron magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het elektron en kernmagneton electron molar mass (Mâ‚‘) molaire massa van het elektron (Mâ‚‘) electron-muon magnetic moment ratio verhouding tussen magnetisch moment van elektron en muon electron-muon mass ratio massaverhouding tussen elektron en muon electron-neutron magnetic moment ratio verhouding tussen magnetisch moment van elektron en neutron electron-neutron mass ratio massaverhouding tussen elektron en neutron electron-proton magnetic moment ratio verhouding tussen magnetisch moment van elektron en proton electron-proton mass ratio massaverhouding tussen elektron en proton electron relative atomic mass (Ar(e)) relatieve atoommassa van het elektron (Ar(e)) electron-tau mass ratio massaverhouding tussen elektron en tau electron to alpha particle mass ratio massaverhouding tussen elektron en alfadeeltje electron to shielded helion magnetic moment ratio verhouding tussen magnetisch moment van elektron en afgeschermd helion electron to shielded proton magnetic moment ratio verhouding tussen magnetisch moment van elektron en afgeschermd proton electron-triton mass ratio massaverhouding tussen elektron en triton electron volt-atomic mass unit relationship relatie tussen elektronvolt en atomaire massa-eenheid electron volt-hartree relationship relatie tussen elektronvolt en hartree electron volt-hertz relationship relatie tussen elektronvolt en hertz electron volt-inverse meter relationship relatie tussen elektronvolt en inverse meter electron volt-joule relationship relatie tussen elektronvolt en joule electron volt-kelvin relationship relatie tussen elektronvolt en kelvin electron volt-kilogram relationship relatie tussen elektronvolt en kilogram hartree-atomic mass unit relationship relatie tussen hartree en atomaire massa-eenheid hartree-electron volt relationship relatie tussen hartree en elektronvolt muon Compton wavelength Comptongolflengte van het muon muon-electron mass ratio massaverhouding tussen muon en elektron muon g factor g-factor van het muon muon magnetic moment magnetisch moment van het muon muon magnetic moment anomaly anomalie van het magnetisch moment van het muon muon magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het muon en Bohrmagneton muon magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het muon en kernmagneton muon mass muonmassa muon mass energy equivalent energie-equivalent van de muonmassa muon mass energy equivalent in MeV energie-equivalent van de muonmassa in MeV muon mass in u muonmassa in u muon molar mass molaire massa van het muon muon-neutron mass ratio massaverhouding tussen muon en neutron muon-proton magnetic moment ratio verhouding tussen magnetisch moment van muon en proton muon-proton mass ratio massaverhouding tussen muon en proton muon-tau mass ratio massaverhouding tussen muon en tau reduced muon Compton wavelength gereduceerde Comptongolflengte van het muon reduced tau Compton wavelength gereduceerde Comptongolflengte van het tau tau Compton wavelength Comptongolflengte van het tau tau-electron mass ratio massaverhouding tussen tau en elektron tau mass taumassa tau mass energy equivalent energie-equivalent van de taumassa tau mass in u taumassa in u tau molar mass molaire massa van het tau tau-muon mass ratio massaverhouding tussen tau en muon tau-neutron mass ratio massaverhouding tussen tau en neutron tau-proton mass ratio massaverhouding tussen tau en proton proton charge to mass quotient quotiënt van protonlading en massa proton Compton wavelength Comptongolflengte van het proton proton-electron mass ratio massaverhouding tussen proton en elektron proton g factor (gₚ) g-factor van het proton (gₚ) proton gyromagnetic ratio (γₚ) gyromagnetische verhouding van het proton (γₚ) proton gyromagnetic ratio in MHz/T gyromagnetische verhouding van het proton in MHz/T proton magnetic moment (μₚ) magnetisch moment van het proton (μₚ) proton magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het proton en Bohrmagneton proton magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het proton en kernmagneton proton magnetic shielding correction magnetische afschermingscorrectie van het proton proton mass (mₚ) protonmassa (mₚ) proton mass energy equivalent energie-equivalent van de protonmassa proton mass energy equivalent in MeV energie-equivalent van de protonmassa in MeV proton mass in u protonmassa in u proton molar mass (Mₚ) molaire massa van het proton (Mₚ) proton-muon mass ratio massaverhouding tussen proton en muon proton-neutron magnetic moment ratio verhouding tussen magnetisch moment van proton en neutron proton-neutron mass ratio massaverhouding tussen proton en neutron proton relative atomic mass (Ar(p)) relatieve atoommassa van het proton (Ar(p)) proton rms charge radius rms-ladingsstraal van het proton proton-tau mass ratio massaverhouding tussen proton en tau reduced proton Compton wavelength gereduceerde Comptongolflengte van het proton shielded proton gyromagnetic ratio gyromagnetische verhouding van het afgeschermde proton shielded proton gyromagnetic ratio in MHz/T gyromagnetische verhouding van het afgeschermde proton in MHz/T shielded proton magnetic moment magnetisch moment van het afgeschermde proton shielded proton magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het afgeschermde proton en Bohrmagneton shielded proton magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het afgeschermde proton en kernmagneton neutron Compton wavelength Comptongolflengte van het neutron neutron-electron magnetic moment ratio verhouding tussen magnetisch moment van neutron en elektron neutron-electron mass ratio massaverhouding tussen neutron en elektron neutron g factor (gâ‚™) g-factor van het neutron (gâ‚™) neutron gyromagnetic ratio (γₙ) gyromagnetische verhouding van het neutron (γₙ) neutron gyromagnetic ratio in MHz/T gyromagnetische verhouding van het neutron in MHz/T neutron magnetic moment (μₙ) magnetisch moment van het neutron (μₙ) neutron magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het neutron en Bohrmagneton neutron magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het neutron en kernmagneton neutron mass (mâ‚™) neutronmassa (mâ‚™) neutron mass energy equivalent energie-equivalent van de neutronmassa neutron mass energy equivalent in MeV energie-equivalent van de neutronmassa in MeV neutron mass in u neutronmassa in u neutron molar mass (Mâ‚™) molaire massa van het neutron (Mâ‚™) neutron-muon mass ratio massaverhouding tussen neutron en muon neutron-proton magnetic moment ratio verhouding tussen magnetisch moment van neutron en proton neutron-proton mass difference massaverschil tussen neutron en proton neutron-proton mass difference energy equivalent energie-equivalent van het massaverschil tussen neutron en proton neutron-proton mass difference energy equivalent in MeV energie-equivalent van het massaverschil tussen neutron en proton in MeV neutron-proton mass difference in u massaverschil tussen neutron en proton in u neutron-proton mass ratio massaverhouding tussen neutron en proton neutron relative atomic mass (Ar(n)) relatieve atoommassa van het neutron (Ar(n)) neutron-tau mass ratio massaverhouding tussen neutron en tau neutron to shielded proton magnetic moment ratio verhouding tussen magnetisch moment van neutron en afgeschermd proton reduced neutron Compton wavelength gereduceerde Comptongolflengte van het neutron deuteron-electron magnetic moment ratio verhouding tussen magnetisch moment van deuteron en elektron deuteron-electron mass ratio massaverhouding tussen deuteron en elektron deuteron g factor g-factor van het deuteron deuteron magnetic moment magnetisch moment van het deuteron deuteron magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het deuteron en Bohrmagneton deuteron magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het deuteron en kernmagneton deuteron mass deuteronmassa deuteron mass energy equivalent energie-equivalent van de deuteronmassa deuteron mass energy equivalent in MeV energie-equivalent van de deuteronmassa in MeV deuteron mass in u deuteronmassa in u deuteron molar mass molaire massa van het deuteron deuteron-neutron magnetic moment ratio verhouding tussen magnetisch moment van deuteron en neutron deuteron-proton magnetic moment ratio verhouding tussen magnetisch moment van deuteron en proton deuteron-proton mass ratio massaverhouding tussen deuteron en proton deuteron relative atomic mass (Ar(d)) relatieve atoommassa van het deuteron (Ar(d)) deuteron rms charge radius rms-ladingsstraal van het deuteron triton-electron mass ratio massaverhouding tussen triton en elektron triton g factor (gₜ) g-factor van het triton (gₜ) triton magnetic moment (μₜ) magnetisch moment van het triton (μₜ) triton magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het triton en Bohrmagneton triton magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het triton en kernmagneton triton mass (mₜ) tritonmassa (mₜ) triton mass energy equivalent energie-equivalent van de tritonmassa triton mass energy equivalent in MeV energie-equivalent van de tritonmassa in MeV triton mass in u tritonmassa in u triton molar mass (Mₜ) molaire massa van het triton (Mₜ) triton-proton mass ratio massaverhouding tussen triton en proton triton relative atomic mass (Ar(t)) relatieve atoommassa van het triton (Ar(t)) triton to proton magnetic moment ratio verhouding tussen magnetisch moment van triton en proton helion-electron mass ratio massaverhouding tussen helion en elektron helion g factor (gâ‚•) g-factor van het helion (gâ‚•) helion magnetic moment (μₕ) magnetisch moment van het helion (μₕ) helion magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het helion en Bohrmagneton helion magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het helion en kernmagneton helion mass (mâ‚•) helionmassa (mâ‚•) helion mass energy equivalent energie-equivalent van de helionmassa helion mass energy equivalent in MeV energie-equivalent van de helionmassa in MeV helion mass in u helionmassa in u helion molar mass (Mâ‚•) molaire massa van het helion (Mâ‚•) helion-proton mass ratio massaverhouding tussen helion en proton helion relative atomic mass (Ar(h)) relatieve atoommassa van het helion (Ar(h)) helion shielding shift afschermingsverschuiving van het helion shielded helion gyromagnetic ratio gyromagnetische verhouding van het afgeschermde helion shielded helion gyromagnetic ratio in MHz/T gyromagnetische verhouding van het afgeschermde helion in MHz/T shielded helion magnetic moment magnetisch moment van het afgeschermde helion shielded helion magnetic moment to Bohr magneton ratio verhouding tussen magnetisch moment van het afgeschermde helion en Bohrmagneton shielded helion magnetic moment to nuclear magneton ratio verhouding tussen magnetisch moment van het afgeschermde helion en kernmagneton shielded helion to proton magnetic moment ratio verhouding tussen magnetisch moment van afgeschermd helion en proton shielded helion to shielded proton magnetic moment ratio verhouding tussen magnetisch moment van afgeschermd helion en afgeschermd proton alpha particle mass massa van het alfadeeltje alpha particle mass in u massa van het alfadeeltje in u alpha particle mass energy equivalent energie-equivalent van de massa van het alfadeeltje alpha particle mass energy equivalent in MeV energie-equivalent van de massa van het alfadeeltje in MeV alpha particle-electron mass ratio massaverhouding tussen alfadeeltje en elektron alpha particle-proton mass ratio massaverhouding tussen alfadeeltje en proton alpha particle rms charge radius rms-ladingsstraal van het alfadeeltje alpha particle molar mass molaire massa van het alfadeeltje alpha particle relative atomic mass (Ar(α)) relatieve atoommassa van het alfadeeltje (Ar(α)) atomic mass constant (mᵤ) atomaire massaconstante (mᵤ) Avogadro constant constante van Avogadro Boltzmann constant (k) constante van Boltzmann (k) Boltzmann constant in eV/K constante van Boltzmann in eV/K Boltzmann constant in Hz/K constante van Boltzmann in Hz/K Boltzmann constant in inverse meter per kelvin constante van Boltzmann in inverse meter per kelvin electron volt (eV) elektronvolt (eV) Faraday constant (F) constante van Faraday (F) first radiation constant (câ‚�) eerste stralingsconstante (câ‚�) first radiation constant for spectral radiance eerste stralingsconstante voor spectrale radiantie molar gas constant (R) molaire gasconstante (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) constante van Loschmidt (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) constante van Loschmidt (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molaire constante van Planck second radiation constant (câ‚‚) tweede stralingsconstante (câ‚‚) Stefan-Boltzmann constant (σ) constante van Stefan-Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) roosterafstand van ideaal Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent energie-equivalent van de atomaire massaconstante atomic mass constant energy equivalent in MeV energie-equivalent van de atomaire massaconstante in MeV atomic mass unit-electron volt relationship relatie tussen atomaire massa-eenheid en elektronvolt molar mass constant (Mᵤ) molaire-massaconstante (Mᵤ) molar mass of carbon-12 molaire massa van koolstof-12 molar volume of ideal gas (273.15 K, 100 kPa) molair volume van ideaal gas (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) molair volume van ideaal gas (273.15 K, 101.325 kPa) molar volume of silicon molair volume van silicium Sackur-Tetrode constant (1 K, 100 kPa) constante van Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) constante van Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant constante van de frequentieverschuivingswet van Wien Wien wavelength displacement law constant constante van de golflengteverschuivingswet van Wien standard atmosphere (atm) standaardatmosfeer (atm) standard-state pressure (p°) standaardtoestandsdruk (p°) Angstrom star (Ã…*) Ã¥ngströmster (Ã…*) Copper x unit koper-x-eenheid Molybdenum x unit molybdeen-x-eenheid atomic unit of magnetizability atomaire eenheid van magnetiseerbaarheid atomic unit of mass (mâ‚‘) atomaire eenheid van massa (mâ‚‘) atomic unit of momentum atomaire eenheid van impuls atomic unit of permittivity atomaire eenheid van permittiviteit atomic unit of time atomaire eenheid van tijd atomic unit of velocity atomaire eenheid van snelheid hartree-hertz relationship relatie tussen hartree en hertz hartree-inverse meter relationship relatie tussen hartree en inverse meter hartree-joule relationship relatie tussen hartree en joule hartree-kelvin relationship relatie tussen hartree en kelvin hartree-kilogram relationship relatie tussen hartree en kilogram shielding difference of d and p in HD afschermingsverschil tussen d en p in HD shielding difference of t and p in HT afschermingsverschil tussen t en p in HT pi (Ï€) pi (Ï€) Euler's number (e) getal van Euler (e) golden ratio (φ) gulden snede (φ) Euler-Mascheroni constant (γ) constante van Euler-Mascheroni (γ) nominal solar radius nominale zonnestraal nominal solar total irradiance nominale totale zonnestralingssterkte nominal solar luminosity nominale zonnelichtkracht nominal solar effective temperature nominale effectieve zonnetemperatuur nominal solar mass parameter nominale zonnemassaparameter nominal terrestrial equatorial radius nominale equatoriale aardstraal nominal terrestrial polar radius nominale polaire aardstraal nominal terrestrial mass parameter nominale aardmassaparameter nominal jovian equatorial radius nominale equatoriale Jupiterstraal nominal jovian polar radius nominale polaire Jupiterstraal nominal jovian mass parameter nominale Jupitermassaparameter average value of one minus the rate of TCG relative to TCB gemiddelde waarde van één min de snelheid van TCG ten opzichte van TCB solar mass parameter (TCB-compatible) zonnemassaparameter (TCB-compatibel) solar mass parameter (TDB-compatible) zonnemassaparameter (TDB-compatibel) equatorial radius of the Earth (TT-compatible) equatoriale straal van de aarde (TT-compatibel) dynamical form factor of the Earth dynamische vormfactor van de aarde time rate of change in the dynamical form factor of the Earth tijdssnelheid van verandering van de dynamische vormfactor van de aarde geocentric gravitational constant (TCB-compatible) geocentrische gravitatieconstante (TCB-compatibel) geocentric gravitational constant (TT-compatible) geocentrische gravitatieconstante (TT-compatibel) geocentric gravitational constant (TDB-compatible) geocentrische gravitatieconstante (TDB-compatibel) potential of the geoid potentiaal van de geoïde nominal mean angular velocity of the Earth (TT-compatible) nominale gemiddelde hoeksnelheid van de aarde (TT-compatibel) ratio mass of the Moon to the Earth massaverhouding tussen de maan en de aarde ratio of the mass of the Sun to Mercury massaverhouding tussen de zon en Mercurius ratio of the mass of the Sun to Venus massaverhouding tussen de zon en Venus ratio of the mass of the Sun to Mars massaverhouding tussen de zon en Mars ratio of the mass of the Sun to Jupiter massaverhouding tussen de zon en Jupiter ratio of the mass of the Sun to Saturn massaverhouding tussen de zon en Saturnus ratio of the mass of the Sun to Uranus massaverhouding tussen de zon en Uranus ratio of the mass of the Sun to Neptune massaverhouding tussen de zon en Neptunus ratio of the mass of the Sun to (134340) Pluto massaverhouding tussen de zon en (134340) Pluto ratio of the mass of the Sun to (136199) Eris massaverhouding tussen de zon en (136199) Eris ratio of the mass of (1) Ceres to the Sun massaverhouding tussen (1) Ceres en de zon ratio of the mass of (2) Pallas to the Sun massaverhouding tussen (2) Pallas en de zon ratio of the mass of (4) Vesta to the Sun massaverhouding tussen (4) Vesta en de zon mean obliquity of the ecliptic at J2000.0 gemiddelde helling van de ecliptica op J2000.0 Electromagnetic Elektromagnetisch Compton wavelength Compton-golflengte Astronomy Sterrenkunde ConstantsWidget Domain Domein Subdomain Subdomein No match found Geen resultaten gevonden Name Naam Value Waarde Unit Eenheid Search Zoeken All Alle CustomKeypadDialog Custom Keypad Aangepast toetsenblok Rows: Rijen: Columns: Kolommen: Copy preset: Voorinstelling kopiëren: Basic Basis Scientific (wide) Wetenschappelijk (breed) Scientific (narrow) Wetenschappelijk (smal) Apply Toepassen Row Rij Column Kolom Label Label Behavior Gedrag Text Tekst DiagnosticsDialog App Diagnostics Appdiagnostiek Copy to Clipboard Naar klembord kopiëren Editor Unit Eenheid User unit Gebruikerseenheid User function Gebruikergedefinieerde functie Argument Argument Current result:<br/>%1 Huidig resultaat:<br/>%1 Selection result:<br/>%1 Selectieresultaat:<br/>%1 Selection result: n/a Selectieresultaat: n.v.t. Selection result: %1 Selectieresultaat: %1 second seconde metre meter kilogram kilogram mole mol radian radiaal steradian steradiaal degree Celsius graad Celsius cubic metre kubieke metre cubic millimetre kubieke millimetre cubic centimetre kubieke centimetre cubic decimetre kubieke decimetre cubic kilometre kubieke kilometre square millimetre vierkante millimetre square kilometre vierkante kilometre square metre vierkante metre minute minuut hour uur day dag astronomical unit astronomische eenheid degree graad arcminute boogminuut arcsecond boogseconde milliarcsecond milliboogseconde microarcsecond microboogseconde hectare hectare litre liter tonne ton Dalton dalton electronvolt elektronvolt Angstrom Ã¥ngström atmosphere atmosfeer atomic mass unit atomaire massa-eenheid British thermal unit Britse thermische eenheid calorie calorie carat karaat cup kop cup (Imperial) kop (imperiaal) cup (Japanese) kop (Japans) cup (US) kop (VS) degree Fahrenheit graad Fahrenheit fathom vadem fluid ounce (Imperial) vloeibare ounce (imperiaal) fluid ounce (US) vloeibare ounce (VS) fluid dram (Imperial) vloeibare drachme (imperiaal) fluid dram (US) vloeibare drachme (VS) foot voet square foot vierkante voet cubic foot kubieke voet gallon (Imperial) gallon (imperiaal) gallon (US) gallon (VS) gill (Imperial) gill (imperiaal) gill (US) gill (VS) gradian decimale graad grain grain gram gram Hartley Hartley Hartree energy unit Hartree-energie-eenheid horsepower paardenkracht inch duim square inch vierkante inch cubic inch kubieke inch karat karaat knot knoop lightminute lichtminuut lightsecond lichtseconde lightyear lichtjaar long ton lange ton mile mijl square mile vierkante mijl cubic mile kubieke mijl mile per hour mijl per uur kilometre per hour kilometer per uur nautical mile zeemijl ounce ounce parsec parsec pint (Imperial) pint (imperiaal) pint (US) pint (VS) pound pond pounds per square inch pond per vierkante inch quart (Imperial) quart (imperiaal) quart (US) quart (VS) oil barrel olievat beer barrel (US) biervat (VS) square yard vierkante yard cubic yard kubieke yard short ton korte ton tablespoon eetlepel tablespoon (Australian) eetlepel (Australisch) tablespoon (Imperial) eetlepel (imperiaal) tablespoon (US) eetlepel (VS) dessert spoon dessertlepel teaspoon theelepel teaspoon (Imperial) theelepel (imperiaal) teaspoon (US) theelepel (VS) turn omwenteling revolution revolutie revolution per minute omwentelingen per minuut week week kilowatt hour kilowattuur millimetre of mercury millimeter kwik yard yard Julian century Juliaanse eeuw Julian year Juliaans jaar sidereal year siderisch jaar tropical year tropisch jaar Evaluator invalid expression ongeldige expressie division by zero deling door nul too time consuming - computation was rejected de berekening duurt te lang en werd afgewezen dimension mismatch - quantities with different dimensions cannot be compared, added, etc. eenheden komen niet overeen - hoeveelheden met verschillende dimensies kunnen niet worden vergeleken, opgeteld etc. invalid dimension - operation might require dimensionless arguments verkeerde eenheid - operatie vereist wellicht eenheidsloze argumenten Computation aborted - encountered numerical instability Berekening afgebroken - numerieke instabiliteit gedetecteerd invalid dimension - function might require dimensionless arguments verkeerde eenheid - operatie vereist wellicht eenheidsloze argumenten error fout unit must not be zero eenheid kan geen nul zijn Conversion failed - dimension mismatch Conversie mislukt - eenheden komen niet overeen unknown function or variable onbekende functie of variabele recursion not supported recursie wordt niet ondersteund cannot operate on a NaN kan niet werken met NaN underflow - tiny result is out of SpeedCrunch's number range underflow - klein resultaat valt buiten het numerieke bereik van SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflow - enorm resultaat valt buiten het numerieke bereik van SpeedCrunch overflow - logic result exceeds maximum of 256 bits overflow - logisch resultaat overschrijdt maximum van 256 bits overflow - integer result exceeds maximum limit for integers overflow - integerresultaat overschrijdt de maximumlimiet voor integers operation is not defined for these arguments bewerking is niet gedefinieerd voor deze argumenten wrong number of arguments verkeerd aantal argumenten does not take NaN as an argument NaN als argument niet mogelijk result out of range resultaat buiten bereik undefined for argument domain ongedefinieerd voor domein van argument computation too expensive berekening te kostbaar internal error, please report a bug interne fout, meld alstublieft een bug syntax error syntaxisfout conversion target must be a unit conversiedoel moet een eenheid zijn unknown unit onbekende eenheid %1 is a reserved name, please choose another %1 is een gereserveerde naam, kies een andere naam %1 is a global user definition and cannot be overridden in this session. %1 is een globale gebruikersdefinitie en kan in deze sessie niet worden overschreven. %1 is a variable name, please choose another or delete the variable %1 is de naam van een variabele, kies een andere naam of verwijder de variabele argument %1 is used more than once argument %1 wordt meer dan eens gebruikt %1 is a built-in unit name, please choose another %1 is een ingebouwde eenheidsnaam, kies een andere %1 is a user function name, please choose another or delete the function %1 is de naam van een gebruiksgedefiniëerde functie, kies een andere naam of verwijder de functie FunctionRepo max; trials; probability max; pogingen; kans trials; probability pogingen; kans hits; trials; probability treffers; pogingen; kans max; total; hits; trials max; totaal; treffers; pogingen total; hits; trials totaal; treffers; pogingen count; total; hits; trials aantal; totaal; treffers; pogingen dividend; divisor deeltal; deler x; exponent_bits; significand_bits [; exponent_bias] x; exponentbits; significandbits [; exponentbias] base; x grondtal; x value; modulo waarde; modulo base; exponent; modulo basis; exponent; modulo events; average_events gebeurtenissen; gemiddelde_gebeurtenissen average_events gemiddelde_gebeurtenissen x [; precision] x [; precisie] Absolute Value Absolute waarde Absolute Deviation Absolute afwijking Arc Cosine Arc-cosinus Logical AND Logische AND Area Hyperbolic Cosine areaal cosinus hyperbolicus Area Hyperbolic Sine areaal sinus hyperbolicus Area Hyperbolic Tangent areaal tangens hyperbolicus Arc Sine Arcsinus Arc Tangent Arctangens Arc Tangent with two Arguments Arctangens met twee argumenten Average (Arithmetic Mean) Gemiddelde (rekenkundig gemiddelde) Binomial Cumulative Distribution Function Binomiale verdelingsfunctie Binomial Distribution Mean Binomiaal distributiegemiddelde Binomial Probability Mass Function Binomiale kansdichtheidsfunctie Binomial Distribution Variance Binomiale variantie Cube Root Derdemachtswortel Complex Conjugate Complex geconjugeerde Cosine Cosinus Hyperbolic Cosine Cosinus hyperbolicus Cotangent Cotangens Cosecant cosecans Convert Unix timestamp to Date Unix-tijdstempel converteren naar datum Degrees of Arc Hoek van een boog Error Function Errorfunctie Complementary Error Function Complementaire errorfunctie Exponential E-macht Fractional Part Breukdeel Extension of Factorials [= (x-1)!] Faculteitsuitbreiding [=(x-1)!] Greatest Common Divisor Grootst gemeenschappelijke deler Geometric Mean Geometrisch gemiddelde Gradians of arc Gon van hoek Hypergeometric Cumulative Distribution Function Cumulatieve verdelingsfunctie (hypergeometrisch) Hypergeometric Distribution Mean Distributiegemiddelde (hypergeometrisch) Hypergeometric Probability Mass Function Kansdichtheidsfunctie (hypergeometrisch) Hypergeometric Distribution Variance Variantie (hypergeometrisch) Integer Quotient Integerquotiënt Integer Part Gehele deel Imaginary Part Complexe deel Decode IEEE-754 Binary Value Binaire waarde decoderen (IEEE-754) Encode IEEE-754 Binary Value Binaire waarde encoderen (IEEE-754) Decode 16-bit Half-Precision Value 16-bits half-precisiewaarde decoderen Encode 16-bit Half-Precision Value 16-bits half-precisiewaarde encoderen Decode 32-bit Single-Precision Value 32-bits single-precisiewaarde decoderen Encode 32-bit Single-Precision Value 32-bits single-precisiewaarde encoderen Decode 64-bit Double-Precision Value 64-bits double-precisiewaarde decoderen Encode 64-bit Double-Precision Value 64-bits double-precisiewaarde encoderen Decode 128-bit Quad-Precision Value 128-bits quad-precisiewaarde decoderen Encode 128-bit Quad-Precision Value 128-bits quad-precisiewaarde encoderen Binary Logarithm Binair logaritme Common Logarithm Logaritme (grondtal 10) Natural Logarithm Natuurlijk logaritme Logarithm to Arbitrary Base Logaritme met arbitrair grondtal Mask to a bit size Masker naar een bitgrootte Maximum Maximum Median Value (50th Percentile) Mediaan (50e percentiel) Minimum Minimum Modulo Modulo Euclidean Modulo Euclidische modulo Modular Exponentiation Modulaire exponentiatie Combination (Binomial Coefficient) Binomiaalcoëfficiënt (x1 boven x2) Logical NOT Logische NOT Permutation (Arrangement) Permutatie (rangschikking) Convert to Binary Representation Converteren naar binaire weergave Arithmetic Rekenkunde Chemistry Scheikunde Complex Complex Combinatorics Combinatoriek Probability Kansrekening Statistics Statistiek Aggregation Aggregatie Random Willekeurig Base conversion Grondtalconversie Number formatting Getalnotatie Integer arithmetic Integerrekenen Special functions Speciale functies Exponential & Logarithmic Exponentieel & logaritmisch Angle conversion Hoekconversie Trigonometry Trigonometrie Bitwise Bitsgewijs Floating point Drijvende komma Date & Time Datum & tijd Linear algebra Lineaire algebra unix_timestamp; x hours offset to GMT unix_timestamp; x uren verschuiving t.o.v. GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; x uur verschuiving t.o.v. GMT [digits] [cijfers] max [; min] max [; min] List Literal Lijstliteral Convert to Padded Binary Representation Converteren naar aangevulde binaire weergave Round Toward +∞ (Ceiling) Afronden naar +∞ (plafond) Cosine plus Imaginary Sine Cosinus plus imaginaire sinus Convert to Cis Complex Form Converteren naar complexe cis-vorm Matrix Column Count Aantal matrixkolommen Population Correlation Matrix (n) Populatiecorrelatiematrix (n) Sample Correlation Matrix (n-1) Steekproefcorrelatiematrix (n-1) Count Aantal Population Covariance Matrix (n) Populatiecovariantiematrix (n) Sample Covariance Matrix (n-1) Steekproefcovariantiematrix (n-1) Cross Product Kruisproduct Convert Date to Unix timestamp Datum converteren naar Unix-tijdstempel Convert to Decimal Representation Converteren naar decimale weergave Determinant Determinant Convert to Sexagesimal Notation Converteren naar zestigtallige notatie Dot Product Inwendig product Convert to Engineering Notation Converteren naar technische notatie Convert to Exponential Complex Form Converteren naar exponentiële complexe vorm Round Toward −∞ (Floor) Afronden naar −∞ (vloer) Flatten Matrix Matrix afvlakken Least Common Multiple Kleinste gemene veelvoud Convert to Hexadecimal Representation Converteren naar hexadecimale weergave Convert to Padded Hexadecimal Representation Converteren naar aangevulde hexadecimale weergave Inverse Matrix Inverse matrix Round to 16-bit Half-Precision Value Afronden naar 16-bits half-precisiewaarde Round to 32-bit Single-Precision Value Afronden naar 32-bits single-precisiewaarde Round to 64-bit Double-Precision Value Afronden naar 64-bits double-precisiewaarde Round to 128-bit Quad-Precision Value Afronden naar 128-bits quad-precisiewaarde Residual from 16-bit Half-Precision Rounding Rest na 16-bits half-precisieafronding Residual from 32-bit Single-Precision Rounding Rest na 32-bits single-precisieafronding Residual from 64-bit Double-Precision Rounding Rest na 64-bits double-precisieafronding Residual from 128-bit Quad-Precision Rounding Rest na 128-bits quad-precisieafronding Substance Mass Stofmassa Molarity Molariteit Molar Mass Molaire massa Median Absolute Deviation Mediane absolute afwijking Mean Gemiddelde Numerical Value of Quantity Numerieke waarde van grootheid Random Decimal Number Willekeurig decimaal getal Random Integer Number Willekeurig geheel getal Convert to Rational Representation Converteren naar rationale weergave Convert to Octal Representation Converteren naar octale weergave Convert to Padded Octal Representation Converteren naar aangevulde octale weergave Vector or Matrix Norm Vector- of matrixnorm Logical OR Logische OR Population Count (Hamming Weight) Populatietelling (Hamminggewicht) Phase of Complex Number Fase van complex getal Poissonian Cumulative Distribution Function Cumulatieve distributiefunctie (poisson) Poissonian Distribution Mean Gemiddelde (poisson) Poissonian Probability Mass Function Kansdichtheidsfunctie (poisson) Poissonian Distribution Variance Variantie (poisson) Convert to Phasor Complex Form Converteren naar fasorvorm Convert to Rectangular Complex Form Converteren naar rechthoekige complexe vorm Round Half Away from Zero Half van nul af afronden Round Half Even Half naar even afronden Nth Root N-de wortel Convert to Scientific Notation Converteren naar wetenschappelijke notatie Matrix Row Count Aantal matrixrijen List or Matrix Shape Vorm van lijst of matrix Summation Sommatie Population Standard Deviation (n) Populatiestandaardafwijking (n) Sample Standard Deviation (n-1) Steekproefstandaardafwijking (n-1) Round Toward Zero (Truncation) Afronden naar nul (afkappen) Matrix Trace Spoor van matrix Transpose Matrix Matrix transponeren Population Variance (n) Populatievariantie (n) Sample Variance (n-1) Steekproefvariantie (n-1) Product Product Radians Radiaan Matrix Rank Matrixrang Real Part Reëel deel Secant Secans Arithmetic Shift Left Aritmetische verschuiving naar links Arithmetic Shift Right Aritmetische verschuiving naar rechts Signum Tekenfunctie Sine Sinus Hyperbolic Sine Sinus hyperbolicus Square Root Vierkantswortel Sum Som Tangent Tangens Convert to Trigonometric Complex Form Converteren naar trigonometrische complexe vorm Turns Omwentelingen Hyperbolic Tangent Hyperbolische tangens Sign-extend a value Teken-uitbreiden Logical XOR Logische XOR FunctionsWidget Domain Domein All Alles Name Naam Search Zoeken No match found Geen resultaten gevonden Identifier Unieke naam HistoryWidget Remove All Calculations Above Alle berekeningen hierboven verwijderen Remove This Calculation Deze berekening verwijderen Remove All Calculations Below Alle berekeningen hieronder verwijderen Keypad Inverse cosine Inverse cosinus The last result Het laatste resultaat Inverse sine Inverse sinus Inverse tangent Inverse tangens Evaluate expression Expressie evalueren Division Delen Multiplication Vermenigvuldigen Subtraction Aftrekken Addition Optellen Clear expression Expressie wissen Cosine Cosinus Backspace Backspace Scientific notation Wetenschappelijke notering Exponential Exponentieel Factorial Faculteit Natural logarithm Natuurlijk logaritme Left parenthesis Linkerhaakje Nth root N-de wortel Argument separator Argumentscheidingsteken Square Kwadraat Common logarithm Logaritme (grondtal 10) Modulo Modulo Contextual percentage Contextueel percentage Power Macht Right parenthesis Rechterhaakje Sine Sinus Square root Vierkantswortel Tangent Tangens Pi Pi Decimal separator Decimaalteken MainWindow Radian Radiaan Degree Graden Gradian Gon Binary Binair Octal Octaal Hexadecimal Hexadecimaal Sexagesimal Zestigtallig Engineering decimal Technische notatie Scientific decimal Wetenschappelijke notatie &Import... &Importeren... &Quit &Afsluiten Clear E&xpression E&xpressie wissen Clear &History &Geschiedenis wissen &Copy &Kopiëren &Paste &Plakken &Select Expression Expressie &selecteren &Constants &Constanten &Functions &Functies &History &Geschiedenis &Status Bar &Statusbalk Bitfield Bitveld Use&r Functions Gebruikers&functies &Degree &Graden &Radian &Radiaan &Gradian &Gon Re&volution Re&volutie Auto-Insert a&ns a&ns automatisch invoegen Automatic &Completion Automatisch &aanvullen &Built-in Functions Inge&bouwde functies Built-in &Variables Ingebouwde &variabelen User &Functions Gebruikergede&finieerde functies User Va&riables Geb&ruikersvariabelen Open a Private Tab on Startup Privétabblad openen bij het opstarten Open and focus a new private tab whenever SpeedCrunch starts. Bij elke start van SpeedCrunch een nieuw privétabblad openen en activeren. Syntax &Highlighting Syntaxis&markering Group Digits in &Input &Ingevoerde cijfers groeperen Automatic Input &Adjustments &Automatische invoeraanpassingen Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Operatoren, spaties, haakjes en machten automatisch aanpassen en de invoer beperken tot geldige tekens. Group input digits using the selected number format. Ingevoerde cijfers groeperen volgens de gekozen getalnotatie. &Blinking Cursor &Knipperende cursor Blink the cursor in the expression editor. De cursor in de expressie-editor laten knipperen. &Escape Clears Editor &Escape maakt de editor leeg Clear the focused expression editor with Escape after dismissing any popup or preview. De actieve expressie-editor met Escape leegmaken nadat pop-ups of voorbeelden zijn gesloten. Keep Expression After Evaluation Expressie behouden na berekening Copy New Results Automatically Nieuwe resultaten automatisch kopiëren &Comma &Komma &System Default &Systeemstandaard &Dot &Punt Dot &And Comma Punt &en komma Toward +∞ (&ceil) Naar +∞ (&ceil) Toward −∞ (&floor) Naar −∞ (&floor) &Binary &Binair &Engineering &Technisch &Hexadecimal &Hexadecimaal &Octal &Octaal &Scientific &Wetenschappelijk User &Manual Gebruikers&handleiding Issues and &Feedback Problemen en &feedback &Donate &Doneren &About SpeedCrunch &Over SpeedCrunch App Diag&nostics Appdiag&nostiek S&plit S&plitsen Angle &Mode Hoek&modus &Complex Form &Complexe vorm New Tab Nieuw tabblad Constants Constanten Functions Functies History Geschiedenis User Functions Gebruikergedefinieerde functies &Font... &Lettertype... &Language... Taa&l... &Session &Sessie &Edit &Bewerken &View &Beeld Se&ttings &Instellingen &Decimal &Decimaal &Keypad &Toetsenpaneel Always on &Top Altijd &bovenaan Disabled Uitgeschakeld Small Space Kleine ruimte Medium Space Middelgrote ruimte Large Space Grote ruimte &0 Digits &0 decimalen &15 Digits &15 decimalen &2 Digits &2 decimalen &3 Digits &3 decimalen &50 Digits &50 decimalen &8 Digits &8 decimalen &Sexagesimal &Zestigtallig Reset All Settings... Alle instellingen herstellen... &System &Systeem SpeedCrunch &Theme SpeedCrunch-&thema &Classic &Klassiek &Modern &Modern Context Help Contextuele help &Help &Hulp Error Fout Can't read from file %1 Kan niet van bestand %1 lezen Import Session Sessie importeren Close Session Sessie sluiten Angle Mode: Hoekmodus: Notation: Notatie: Precision: Precisie: Turn Omwenteling Revolution Revolutie Fixed-point decimal Vastekommanotatie Rational Rationaal Automatic decimal Automatische decimale notatie Automatic Automatisch User &Definitions... Gebruikers&definities... New &Tab Nieuw &tabblad New &Private Tab Nieuw &privétabblad Keep Behouden Make Private... Privé maken... New &Window Nieuw &venster &Open... &Openen... &Rename... He&rnoemen... Clo&ne... Klo&nen... &Close Tab Ta&bblad sluiten Reopen Clo&sed Tab Ge&sloten tabblad heropenen Open Sessions &Folder Sessies&map openen &Undo &Ongedaan maken &Redo Opnieuw uitvoe&ren Cu&t K&nippen Copy &Last Result &Laatste resultaat kopiëren &Wrap in Parentheses &Tussen haakjes plaatsen Full Scr&een Mode V&olledig scherm &Basic &Basis &Scientific (wide) &Wetenschappelijk (breed) Scientific (narrow) Wetenschappelijk (smal) &Custom... &Aangepast... Main &Menu Hoofd&menu User &Variables Gebruikers&variabelen &Left &Links &Right &Rechts &Up &Omhoog &Down O&mlaag Close Pa&ne Pa&neel sluiten User &Units Gebruikers&eenheden &Turn &Omwenteling If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Als een nieuwe expressie begint met +, -, *, of /, voegt SpeedCrunch eerst "ans" in. &Accept with Enter &Accepteren met Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Accepteer de huidige suggestie voor automatisch aanvullen met Enter zonder deze eerst met de pijltoetsen te selecteren. &Units &Eenheden Show Live Result &Preview Live &resultaatvoorbeeld tonen Save &Window Position on Exit Vensterpositie bij afsluiten &opslaan Hover Highlighting Markering bij aanwijzen Group Integer Part Only Alleen geheel deel groeperen Number Format... Getalnotatie... Notation && Precision... Notatie && precisie... After pressing Enter, keep the entered expression selected in the editor. Na drukken op Enter de ingevoerde expressie geselecteerd houden in de editor. Never Nooit Always Altijd Only for Single-Line Expressions Alleen voor expressies op één regel Simplify Displayed Expressions Weergegeven expressies vereenvoudigen History Size &Limit... Limiet voor &geschiedenisgrootte... Remove Trailing &Zeroes &Nullen aan het einde verwijderen Nearest, Half &Away (round) Dichtstbij, half &van nul af (round) Nearest, Half &Even (roundeven) Dichtstbij, half &even (roundeven) Toward &Zero (trunc) Naar &nul (trunc) &Fixed-Point &Vaste komma &Rational &Rationaal &Exponential (m·sâ�»Â¹) &Exponentieel (m·sâ�»Â¹) &Fractional (m/s) &Breukvorm (m/s) &Rectangular (a + bi) &Rechthoekig (a + bi) Exponential (reâ�±á¶¿) Exponentieel (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrisch (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Thema... Check for &Updates Controleren op &updates Source Code Broncode &Zoom &Zoomen &Results &Resultaten Unit Notation Eenheidsnotatie Rounding Mode Afrondingsmodus &Notation &Notatie &Imaginary Unit &Imaginaire eenheid &Window &Venster &Editing &Bewerken A&utocomplete A&utomatisch aanvullen Up/Down Arrow History Geschiedenis met pijl omhoog/omlaag &Appearance &Uiterlijk &Menus M&enu’s &Docks &Dockpanelen &Input and Results &Invoer en resultaten &Disabled &Uitgeschakeld &Disable &Uitschakelen Close preview Voorbeeld sluiten Rename... Hernoemen... Clone... Klonen... Close Tab Tabblad sluiten New Private Tab Nieuw privétabblad Open... Openen... Reopen Closed Tab Gesloten tabblad heropenen Split Splitsen Left Links Right Rechts Up Omhoog Down Omlaag Clear Wissen Delete Verwijderen %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Privésessie: de inhoud wordt bij het sluiten verwijderd. Kies Sessie > Behouden om er een gewone sessie van te maken. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privé] Reset All Settings Alle instellingen herstellen Reset all settings to their default values? Alle instellingen terugzetten naar hun standaardwaarden? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Dit omvat weergave, bewerking, resultaatnotaties en venstervoorkeuren. Uw berekeningen, geopende sessies en gebruikersdefinities blijven behouden. The settings file could not be written. Het instellingenbestand kon niet worden geschreven. Clear this session's calculations, unfinished expression, variables, functions, and units? De berekeningen, onvoltooide expressie, variabelen, functies en eenheden van deze sessie wissen? Global user definitions are kept. Globale gebruikersdefinities blijven behouden. Make Session Private Sessie privé maken The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. De opgeslagen sessie %1 wordt verwijderd. De inhoud blijft open in een privésessie en wordt verwijderd wanneer die sessie wordt gesloten of SpeedCrunch wordt afgesloten. Make Private Privé maken Could not delete the saved session %1. De opgeslagen sessie %1 kon niet worden verwijderd. Keep Session Sessie behouden Could not save the session. It remains private. De sessie kon niet worden opgeslagen. Deze blijft privé. Clone Session Sessie klonen Could not save session file %1. Sessiebestand %1 kon niet worden opgeslagen. Could not delete session file %1. Sessiebestand %1 kon niet worden verwijderd. JSON file (*.json);;Any file (*.*) JSON-bestand (*.json);;Elk bestand (*.*) Export session as JSON Sessie exporteren als JSON The selected file is not valid JSON: %1 Het geselecteerde bestand is geen geldige JSON: %1 The selected file is not a SpeedCrunch session JSON file. Het geselecteerde bestand is geen JSON-bestand van een SpeedCrunch-sessie. This file uses an obsolete SpeedCrunch session format and cannot be imported. Dit bestand gebruikt een verouderde SpeedCrunch-sessie-indeling en kan niet worden geïmporteerd. The selected JSON file is missing the required $schema field. In het geselecteerde JSON-bestand ontbreekt het vereiste veld $schema. The selected JSON file uses an unsupported JSON schema: %1 Het geselecteerde JSON-bestand gebruikt een niet-ondersteund JSON-schema: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). In het geselecteerde JSON-bestand ontbreekt de schema-identificatie van de SpeedCrunch-sessie ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Het geselecteerde JSON-bestand gebruikt een niet-ondersteunde SpeedCrunch-sessie-indeling: %1 The selected JSON file is missing the required session name. In het geselecteerde JSON-bestand ontbreekt de vereiste sessienaam. The selected JSON file has an empty session name. Het geselecteerde JSON-bestand heeft een lege sessienaam. The selected JSON file has invalid or incomplete SpeedCrunch session data. Het geselecteerde JSON-bestand bevat ongeldige of onvolledige SpeedCrunch-sessiegegevens. Open Sessions Folder Sessiesmap openen Could not create the sessions folder: %1 Kon de sessiesmap niet aanmaken: %1 Could not open the sessions folder: %1 Kon de sessiesmap niet openen: %1 Editor and Results Font Lettertype voor editor en resultaten Open Session Sessie openen Community Gemeenschap Rename Session Sessie hernoemen Clear Session Sessie wissen Delete Session Sessie verwijderen Close Pane Paneel sluiten User Variables Gebruikersvariabelen User Units Gebruikerseenheden Clear History Geschiedenis wissen Are you sure you want to clear the calculation history? Weet u zeker dat u de berekeningsgeschiedenis wilt wissen? Session name: Sessienaam: A session named %1 already exists. Er bestaat al een sessie met de naam %1. Could not create session file %1. Kon sessiebestand %1 niet maken. Could not write session file %1. Kon sessiebestand %1 niet schrijven. Are you sure you want to delete this session? Weet u zeker dat u deze sessie wilt verwijderen? Custom Precision Aangepaste precisie Fractional digits: Aantal decimalen: Theme Thema Light Themes Lichte thema's Dark Themes Donkere thema's Preview Voorbeeld Colors Kleuren Select color for %1 Kleur voor %1 selecteren Import... Importeren... Export... Exporteren... Import Theme Thema importeren Theme file (*.json);;All files (*) Themabestand (*.json);;Alle bestanden (*) Invalid theme file. Ongeldig themabestand. Can't import theme "%1" because it conflicts with a built-in theme. Kan thema "%1" niet importeren omdat het conflicteert met een ingebouwd thema. Can't find a writable theme folder. Kan geen beschrijfbare themamap vinden. Overwrite Theme Thema overschrijven A custom theme named "%1" already exists. Do you want to overwrite it? Er bestaat al een aangepast thema met de naam "%1". Wilt u het overschrijven? Can't overwrite theme file %1 Kan themabestand %1 niet overschrijven Can't copy theme file to %1 Kan themabestand niet naar %1 kopiëren Export Theme Thema exporteren Can't export theme as "%1" because it conflicts with a built-in theme. Kan thema niet als "%1" exporteren omdat het conflicteert met een ingebouwd thema. Can't write to file %1 Kan niet naar bestand %1 schrijven Global User Variable Globale gebruikersvariabele Global User Function Globale gebruikersfunctie Global User Unit Globale gebruikerseenheid User Definitions Gebruikersdefinities These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Deze definities zijn globaal en worden in elke sessie geladen. Ze kunnen niet in sessies worden gewijzigd en hebben voorrang op definities met dezelfde naam uit de sessie-editor. Voer één definitie per regel in. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Voorbeelden: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Toepassen Validate Valideren Test Results Testresultaten Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Geïmporteerde variabelen: %1 Geïmporteerde functies: %2 Geïmporteerde eenheden: %3 Regelnummers met fouten: %4 none geen Apply Results Resultaten van toepassing User definitions saved. Gebruikersdefinities opgeslagen. History Size Limit Limiet voor geschiedenisgrootte Maximum number of history entries for this session (0 = unlimited): Maximumaantal geschiedenisitems voor deze sessie (0 = onbeperkt): Text file (*.txt);;Any file (*.*) Tekstbestanden (*.txt);;Alle bestanden (*.*) Could not recalculate from calculation %1: %2 Kon niet herberekenen vanaf berekening %1: %2 History Size Limit Reached Limiet voor geschiedenisgrootte bereikt This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Deze berekening vult de laatste beschikbare plek in de geschiedenis. Toekomstige berekeningen verwijderen de oudste berekening uit de geschiedenis. U kunt de limiet verhogen via Sessie > Limiet voor geschiedenisgrootte. Editing calculation. Press Esc twice to cancel. Berekening wordt bewerkt. Druk tweemaal op Esc om te annuleren. Calculation Settings Berekeningsinstellingen Invalid recalculation start index Ongeldige startindex voor herberekening System Default Systeemstandaard Language Taal Select the language: Selecteer de taal: Custom Aangepast Decimal places: Decimalen: &Automatic &Automatisch &Precision &Precisie Plain &text Platte &tekst Formula &Book Formule&boek &Export &Exporteren Export session as HTML Sessie exporteren als HTML HTML file (*.html) HTML-bestand (*.html) Export session as plain text Sessie exporteren als platte tekst ManualWindow SpeedCrunch Manual Handleiding SpeedCrunch %1 - SpeedCrunch Manual %1 - Handleiding SpeedCrunch NumberFormatDialog Number Format Getalnotatie <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Kies de getalnotatie voor resultaten en de groepering van ingevoerde cijfers.</b><br/><br/>Opmerking: bij ingevoerde getallen worden eenduidige notaties geaccepteerd, ook als ze afwijken van de gekozen weergavenotatie.<br/> QObject Global User Variable Globale gebruikersvariabele Global User Function Globale gebruikersfunctie Global User Unit Globale gebruikerseenheid Backspace Backspace Clear expression Expressie wissen Evaluate expression Expressie evalueren Insert text Tekst invoegen Automatic decimal Automatische decimale notatie Fixed-point decimal Vastekommanotatie Engineering decimal Technische notatie Scientific decimal Wetenschappelijke notatie Rational Rationaal Binary Binair Octal Octaal Hexadecimal Hexadecimaal Sexagesimal Zestigtallig Update Available Update beschikbaar A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Er is een nieuwere versie (%1) beschikbaar.<br/><a href="%2">Bezoek de website om te downloaden.</a> Check for Updates Controleren op updates SpeedCrunch %1 is up to date. SpeedCrunch %1 is up-to-date. No connectivity. Please check your internet connection and try again. Geen verbinding. Controleer uw internetverbinding en probeer het opnieuw. Could not verify the latest available version. Kon de nieuwste beschikbare versie niet controleren. ResultDisplay Scroll to bottom Naar onderen scrollen Edit Expression Expressie bewerken Change Settings Instellingen wijzigen New Tab Nieuw tabblad &Import... &Importeren... &Export &Exporteren Plain &text Platte &tekst Copy Kopiëren Selection Selectie Select All Alles selecteren Expression Expressie Result Resultaat Calculation Berekening Calculation as Single Line Berekening op één regel Remove Verwijderen This Calculation Deze berekening All Calculations Above Alle berekeningen hierboven All Calculations Below Alle berekeningen hieronder New Private Tab Nieuw privétabblad Session Sessie Open... Openen... Clone... Klonen... Rename... Hernoemen... Keep Behouden Make Private... Privé maken... Clear Wissen Delete Verwijderen Close Sluiten Split Splitsen Left Links Right Rechts Up Omhoog Down Omlaag Close Pane Paneel sluiten Main Menu Hoofdmenu Cancel editing Bewerken annuleren Copy result Resultaat kopiëren Edit expression Expressie bewerken Change settings Instellingen wijzigen Remove calculation Berekening verwijderen ResultSlotsDialog Notation & Precision Notatie & precisie Result Line Resultaatregel Enabled Ingeschakeld Notation Notatie Decimal Places Decimalen Main Line Hoofdregel Extra Line #1 Extra regel #1 Extra Line #2 Extra regel #2 Extra Line #3 Extra regel #3 Extra Line #4 Extra regel #4 Auto Auto UserFunctionListWidget Name Naam Value Waarde Description Beschrijving Search Zoeken No match found Geen resultaten gevonden Insert Invoegen Edit Bewerken Delete Verwijderen Delete All Alles verwijderen UserUnitListWidget Name Naam Value Waarde Description Beschrijving Search Zoeken No match found Geen resultaten gevonden Insert Invoegen Edit Bewerken Delete Verwijderen Delete All Alles verwijderen VariableListWidget Name Naam Value Waarde Description Beschrijving Search Zoek No match found Geen resultaten gevonden Insert Invoegen Edit Bewerken Delete Verwijderen Delete All Alles verwijderen heldercorreia-speedcrunch-e7ca37f/src/resources/locale/pl.ts000066400000000000000000010553401526573132500243700ustar00rootroot00000000000000 AboutBox About SpeedCrunch O SpeedCrunch Core developers Główni programiÅ›ci Original author Pierwotny autor Close Zamknij Math engine Silnik matematyczny Main author | Logo | Maintainer Główny autor | Logo | Opiekun Thanks PodziÄ™kowania Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 twórcy SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Ten program jest wolnym oprogramowaniem; możesz go rozpowszechniać i/lub modyfikować zgodnie z warunkami Powszechnej Licencji Publicznej GNU opublikowanej przez Free Software Foundation; w wersji 2 tej Licencji lub (wedÅ‚ug wyboru) dowolnej późniejszej wersji This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Ten program jest rozpowszechniany z nadziejÄ…, że bÄ™dzie użyteczny, ale BEZ Å»ADNEJ GWARANCJI; nawet bez dorozumianej gwarancji PRZYDATNOÅšCI HANDLOWEJ lub PRZYDATNOÅšCI DO OKREÅšLONEGO CELU. Szczegóły znajdziesz w Powszechnej Licencji Publicznej GNU. BitFieldWidget Reset bits to zero Wyzeruj bity Invert bits Odwróć bity Shift bits left PrzesuÅ„ bity w lewo Shift bits right PrzesuÅ„ bity w prawo Book Index Indeks Algebra Algebra Quadratic Equation Równanie kwadratowe Logarithmic Base Conversion Zmiana podstawy logarytmu Geometry Geometria Circle KoÅ‚o Sector Sektor Sphere Kula Cube SzeÅ›cian Cone Stożek Cylinder Walec Electronics Elektronika Ohm's Law Prawo Ohma Power Moc Reactance Reaktancja Resonance Rezonans Radio Frequency CzÄ™stotliwość radiowa Antennas Anteny Characteristic Impedance (coax) Impedancja charakterystyczna (koncentryk) Velocity of Propagation (coax) PrÄ™dkość propagacji (koncentryk) Standing Wave Ratio & Return Loss Współczynnik fali stojÄ…cej i tÅ‚umienie odbicia Free Space Wavelength DÅ‚ugość fali w wolnej przestrzeni resistance rezystancja voltage napiÄ™cie current prÄ…d power moc inductive reactance reaktancja indukcyjna capacitive reactance reaktancja pojemnoÅ›ciowa inductance indukcyjność capacitance pojemność frequency czÄ™stotliwość resonance frequency czÄ™stotliwość rezonansowa area powierzchnia perimeter obwód diameter Å›rednica radius promieÅ„ volume objÄ™tość surface area pole powierzchni height wysokość slant height tworzÄ…ca stożka face diagonal przekÄ…tna Å›ciany space diagonal przekÄ…tna bryÅ‚y edge length dÅ‚ugość krawÄ™dzi arc length dÅ‚ugość Å‚uku central angle (degrees) kÄ…t Å›rodkowy (stopnie) input power moc wejÅ›ciowa reflected power moc odbita transmitted power moc przekazywana return loss straty odbiciowe dielectric constant przenikalność elektryczna wzglÄ™dna outer conductor's inner diameter Å›rednica wewnÄ™trzna zewnÄ™trznego przewodu inner conductor's outer diameter Å›rednica zewnÄ™trzna wewnÄ™trznego przewodu speed of light prÄ™dkość Å›wiatÅ‚a reflection coefficient współczynnik odbicia standing wave ratio współczynnik fali stojÄ…cej normalized impedance impedancja znormalizowana frequency (Hz) czÄ™stotliwość (Hz) BookDock Formula Book Zbiór formuÅ‚ ConstantCompletion Search constants Szukaj staÅ‚ych No match found Brak dopasowaÅ„ Constants Mathematics Matematyka Physics (CODATA 2022) Fizyka (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chemia (IUPAC - CIAAW 2021) Uncategorized Bez kategorii Universal Uniwersalne Physicochemical Fizykochemiczne Atomic & Nuclear — General Atomowe i jÄ…drowe — ogólne Atomic & Nuclear — Electroweak Atomowe i jÄ…drowe — elektrosÅ‚abe Atomic & Nuclear — Electron Atomowe i jÄ…drowe — elektron Atomic & Nuclear — Muon Atomowe i jÄ…drowe — mion Atomic & Nuclear — Tau Atomowe i jÄ…drowe — tau Atomic & Nuclear — Proton Atomowe i jÄ…drowe — proton Atomic & Nuclear — Neutron Atomowe i jÄ…drowe — neutron Atomic & Nuclear — Deuteron Atomowe i jÄ…drowe — deuteron Atomic & Nuclear — Triton Atomowe i jÄ…drowe — tryton Atomic & Nuclear — Helion Atomowe i jÄ…drowe — helion Atomic & Nuclear — Alpha particle Atomowe i jÄ…drowe — czÄ…stka alfa Atomic & Nuclear — Atomic units Atomowe i jÄ…drowe — jednostki atomowe Atomic & Nuclear — Energy conversion relationships Atomowe i jÄ…drowe — zależnoÅ›ci konwersji energii Atomic & Nuclear — X-ray units Atomowe i jÄ…drowe — jednostki rentgenowskie Atomic & Nuclear — Magnetic shielding corrections Atomowe i jÄ…drowe — poprawki ekranowania magnetycznego Masses Masy Lifetimes Czasy życia Molar Masses Masy molowe Electronegativity Elektroujemność Ionization Energy Energia jonizacji Nominal Constants (IAU 2015) StaÅ‚e nominalne (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Aktualne najlepsze oszacowania (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) impedancja charakterystyczna próżni (Zâ‚€) reduced Planck constant (â„�) zredukowana staÅ‚a Plancka (â„�) vacuum electric permittivity (ϵ₀) przenikalność elektryczna próżni (ϵ₀) Newtonian constant of gravitation (G) staÅ‚a grawitacji Newtona (G) vacuum magnetic permeability (μ₀) przenikalność magnetyczna próżni (μ₀) Planck constant (h) staÅ‚a Plancka (h) speed of light in vacuum (c) prÄ™dkość Å›wiatÅ‚a w próżni (c) standard acceleration of gravity (gâ‚™) standardowe przyspieszenie ziemskie (gâ‚™) Newtonian constant of gravitation over h-bar c staÅ‚a grawitacji Newtona podzielona przez â„�c Planck length dÅ‚ugość Plancka Planck constant in eV/Hz (h) staÅ‚a Plancka w eV/Hz (h) Planck mass masa Plancka Planck mass energy equivalent in GeV równoważnik energetyczny masy Plancka w GeV Planck temperature temperatura Plancka Planck time czas Plancka reduced Planck constant in eV·s (â„�) zredukowana staÅ‚a Plancka w eV·s (â„�) reduced Planck constant times c in MeV·fm zredukowana staÅ‚a Plancka razy c w MeV·fm Bohr magneton magneton Bohra conductance quantum (Gâ‚€) kwant przewodnictwa (Gâ‚€) Coulomb constant (kâ‚‘) staÅ‚a Coulomba (kâ‚‘) elementary charge (e) Å‚adunek elementarny (e) elementary charge over h-bar Å‚adunek elementarny przez â„� conventional value of Josephson constant wartość umowna staÅ‚ej Josephsona Josephson constant staÅ‚a Josephsona conventional value of ampere-90 wartość umowna ampera-90 conventional value of coulomb-90 wartość umowna kulomba-90 conventional value of farad-90 wartość umowna farada-90 conventional value of henry-90 wartość umowna henra-90 conventional value of ohm-90 wartość umowna oma-90 conventional value of volt-90 wartość umowna wolta-90 conventional value of watt-90 wartość umowna wata-90 magnetic flux quantum (Φ₀) kwant strumienia magnetycznego (Φ₀) nuclear magneton magneton jÄ…drowy inverse of conductance quantum odwrotność kwantu przewodnictwa conventional value of von Klitzing constant wartość umowna staÅ‚ej von Klitzinga von Klitzing constant staÅ‚a von Klitzinga atomic unit of magnetic dipole moment atomowa jednostka magnetycznego momentu dipolowego atomic unit of magnetic flux density atomowa jednostka indukcji magnetycznej Bohr magneton in eV/T magneton Bohra w eV/T Bohr magneton in Hz/T magneton Bohra w Hz/T Bohr magneton in inverse meter per tesla magneton Bohra w metrach odwrotnych na teslÄ™ Bohr magneton in K/T magneton Bohra w K/T nuclear magneton in eV/T magneton jÄ…drowy w eV/T nuclear magneton in inverse meter per tesla magneton jÄ…drowy w metrach odwrotnych na teslÄ™ nuclear magneton in K/T magneton jÄ…drowy w K/T nuclear magneton in MHz/T magneton jÄ…drowy w MHz/T Bohr radius (aâ‚€) promieÅ„ Bohra (aâ‚€) fine-structure constant (α) staÅ‚a struktury subtelnej (α) Hartree energy (Eâ‚•) energia Hartreego (Eâ‚•) Hartree energy in eV energia Hartreego w eV quantum of circulation kwant cyrkulacji quantum of circulation times 2 kwant cyrkulacji razy 2 Rydberg constant (R∞) staÅ‚a Rydberga (R∞) atomic mass unit-hartree relationship zależność: jednostka masy atomowej–hartree atomic mass unit-hertz relationship zależność: jednostka masy atomowej–herc atomic mass unit-inverse meter relationship zależność: jednostka masy atomowej–metr odwrotny atomic mass unit-joule relationship zależność: jednostka masy atomowej–dżul atomic mass unit-kelvin relationship zależność: jednostka masy atomowej–kelwin atomic mass unit-kilogram relationship zależność: jednostka masy atomowej–kilogram atomic unit of 1st hyperpolarizability atomowa jednostka pierwszej hiperpolaryzowalnoÅ›ci atomic unit of 2nd hyperpolarizability atomowa jednostka drugiej hiperpolaryzowalnoÅ›ci atomic unit of charge (e) atomowa jednostka Å‚adunku (e) atomic unit of charge density atomowa jednostka gÄ™stoÅ›ci Å‚adunku atomic unit of current atomowa jednostka prÄ…du atomic unit of electric dipole moment atomowa jednostka elektrycznego momentu dipolowego atomic unit of electric field atomowa jednostka pola elektrycznego atomic unit of electric field gradient atomowa jednostka gradientu pola elektrycznego atomic unit of electric polarizability atomowa jednostka polaryzowalnoÅ›ci elektrycznej atomic unit of electric potential atomowa jednostka potencjaÅ‚u elektrycznego atomic unit of electric quadrupole moment atomowa jednostka elektrycznego momentu kwadrupolowego atomic unit of action atomowa jednostka dziaÅ‚ania atomic unit of energy atomowa jednostka energii atomic unit of force atomowa jednostka siÅ‚y atomic unit of length atomowa jednostka dÅ‚ugoÅ›ci hertz-atomic mass unit relationship zależność: herc–jednostka masy atomowej hertz-electron volt relationship zależność: herc–elektronowolt hertz-hartree relationship zależność: herc–hartree hertz-inverse meter relationship zależność: herc–metr odwrotny hertz-joule relationship zależność: herc–dżul hertz-kelvin relationship zależność: herc–kelwin hertz-kilogram relationship zależność: herc–kilogram hyperfine transition frequency of Cs-133 czÄ™stotliwość przejÅ›cia nadsubtelnego Cs-133 inverse fine-structure constant (αâ�»Â¹) odwrotność staÅ‚ej struktury subtelnej (αâ�»Â¹) inverse meter-atomic mass unit relationship zależność: metr odwrotny–jednostka masy atomowej inverse meter-electron volt relationship zależność: metr odwrotny–elektronowolt inverse meter-hartree relationship zależność: metr odwrotny–hartree inverse meter-hertz relationship zależność: metr odwrotny–herc inverse meter-joule relationship zależność: metr odwrotny–dżul inverse meter-kelvin relationship zależność: metr odwrotny–kelwin inverse meter-kilogram relationship zależność: metr odwrotny–kilogram joule-atomic mass unit relationship zależność: dżul–jednostka masy atomowej joule-electron volt relationship zależność: dżul–elektronowolt joule-hertz relationship zależność: dżul–herc joule-hartree relationship zależność: dżul–hartree joule-inverse meter relationship zależność: dżul–metr odwrotny joule-kelvin relationship zależność: dżul–kelwin joule-kilogram relationship zależność: dżul–kilogram kelvin-atomic mass unit relationship zależność: kelwin–jednostka masy atomowej kelvin-electron volt relationship zależność: kelwin–elektronowolt kelvin-hertz relationship zależność: kelwin–herc kelvin-hartree relationship zależność: kelwin–hartree kelvin-inverse meter relationship zależność: kelwin–metr odwrotny kelvin-joule relationship zależność: kelwin–dżul kelvin-kilogram relationship zależność: kelwin–kilogram kilogram-atomic mass unit relationship zależność: kilogram–jednostka masy atomowej kilogram-electron volt relationship zależność: kilogram–elektronowolt kilogram-hertz relationship zależność: kilogram–herc kilogram-hartree relationship zależność: kilogram–hartree kilogram-inverse meter relationship zależność: kilogram–metr odwrotny kilogram-joule relationship zależność: kilogram–dżul kilogram-kelvin relationship zależność: kilogram–kelwin lattice parameter of silicon (a) parametr sieci krzemu (a) luminous efficacy skuteczność Å›wietlna natural unit of energy naturalna jednostka energii natural unit of energy in MeV naturalna jednostka energii w MeV natural unit of action (â„�) naturalna jednostka dziaÅ‚ania (â„�) natural unit of action in eV·s naturalna jednostka dziaÅ‚ania w eV·s natural unit of length naturalna jednostka dÅ‚ugoÅ›ci natural unit of mass naturalna jednostka masy natural unit of momentum naturalna jednostka pÄ™du natural unit of momentum in MeV/c naturalna jednostka pÄ™du w MeV/c natural unit of time naturalna jednostka czasu natural unit of velocity naturalna jednostka prÄ™dkoÅ›ci Rydberg constant times c in Hz staÅ‚a Rydberga razy c w Hz Rydberg constant times hc in eV staÅ‚a Rydberga razy hc w eV Rydberg constant times hc in J staÅ‚a Rydberga razy hc w J Fermi coupling constant staÅ‚a sprzężenia Fermiego weak mixing angle kÄ…t mieszania sÅ‚abego W to Z mass ratio stosunek mas W do Z Thomson cross section (σₑ) przekrój czynny Thomsona (σₑ) electron mass (mâ‚‘) masa elektronu (mâ‚‘) electron mass in u masa elektronu w u electron mass energy equivalent (mₑ·c²) równoważnik energetyczny masy elektronu (mₑ·c²) electron mass energy equivalent in MeV równoważnik energetyczny masy elektronu w MeV reduced Compton wavelength zredukowana dÅ‚ugość fali Comptona classical electron radius (râ‚‘) klasyczny promieÅ„ elektronu (râ‚‘) electron charge to mass quotient iloraz Å‚adunku i masy elektronu electron-deuteron magnetic moment ratio stosunek momentu magnetycznego elektronu do momentu magnetycznego deuteronu electron-deuteron mass ratio stosunek masy elektronu do masy deuteronu electron g factor (gâ‚‘) czynnik g elektronu (gâ‚‘) electron gyromagnetic ratio (γₑ) stosunek żyromagnetyczny elektronu (γₑ) electron gyromagnetic ratio in MHz/T stosunek żyromagnetyczny elektronu w MHz/T electron-helion mass ratio stosunek masy elektronu do masy helionu electron magnetic moment (μₑ) moment magnetyczny elektronu (μₑ) electron magnetic moment anomaly (aâ‚‘) anomalia momentu magnetycznego elektronu (aâ‚‘) electron magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego elektronu do magnetonu Bohra electron magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego elektronu do magnetonu jÄ…drowego electron molar mass (Mâ‚‘) masa molowa elektronu (Mâ‚‘) electron-muon magnetic moment ratio stosunek momentu magnetycznego elektronu do momentu magnetycznego mionu electron-muon mass ratio stosunek masy elektronu do masy mionu electron-neutron magnetic moment ratio stosunek momentu magnetycznego elektronu do momentu magnetycznego neutronu electron-neutron mass ratio stosunek masy elektronu do masy neutronu electron-proton magnetic moment ratio stosunek momentu magnetycznego elektronu do momentu magnetycznego protonu electron-proton mass ratio stosunek masy elektronu do masy protonu electron relative atomic mass (Ar(e)) wzglÄ™dna masa atomowa elektronu (Ar(e)) electron-tau mass ratio stosunek masy elektronu do masy tau electron to alpha particle mass ratio stosunek masy elektronu do masy czÄ…stki alfa electron to shielded helion magnetic moment ratio stosunek momentu magnetycznego elektronu do momentu magnetycznego ekranowanego helionu electron to shielded proton magnetic moment ratio stosunek momentu magnetycznego elektronu do momentu magnetycznego ekranowanego protonu electron-triton mass ratio stosunek masy elektronu do masy trytonu electron volt-atomic mass unit relationship zależność: elektronowolt–jednostka masy atomowej electron volt-hartree relationship zależność: elektronowolt–hartree electron volt-hertz relationship zależność: elektronowolt–herc electron volt-inverse meter relationship zależność: elektronowolt–metr odwrotny electron volt-joule relationship zależność: elektronowolt–dżul electron volt-kelvin relationship zależność: elektronowolt–kelwin electron volt-kilogram relationship zależność: elektronowolt–kilogram hartree-atomic mass unit relationship zależność: hartree–jednostka masy atomowej hartree-electron volt relationship zależność: hartree–elektronowolt muon Compton wavelength dÅ‚ugość fali Comptona mionu muon-electron mass ratio stosunek masy mionu do masy elektronu muon g factor czynnik g mionu muon magnetic moment moment magnetyczny mionu muon magnetic moment anomaly anomalia momentu magnetycznego mionu muon magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego mionu do magnetonu Bohra muon magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego mionu do magnetonu jÄ…drowego muon mass masa mionu muon mass energy equivalent równoważnik energetyczny masy mionu muon mass energy equivalent in MeV równoważnik energetyczny masy mionu w MeV muon mass in u masa mionu w u muon molar mass masa molowa mionu muon-neutron mass ratio stosunek masy mionu do masy neutronu muon-proton magnetic moment ratio stosunek momentu magnetycznego mionu do momentu magnetycznego protonu muon-proton mass ratio stosunek masy mionu do masy protonu muon-tau mass ratio stosunek masy mionu do masy tau reduced muon Compton wavelength zredukowana dÅ‚ugość fali Comptona mionu reduced tau Compton wavelength zredukowana dÅ‚ugość fali Comptona tau tau Compton wavelength dÅ‚ugość fali Comptona tau tau-electron mass ratio stosunek masy tau do masy elektronu tau mass masa tau tau mass energy equivalent równoważnik energetyczny masy tau tau mass in u masa tau w u tau molar mass masa molowa tau tau-muon mass ratio stosunek masy tau do masy mionu tau-neutron mass ratio stosunek masy tau do masy neutronu tau-proton mass ratio stosunek masy tau do masy protonu proton charge to mass quotient iloraz Å‚adunku i masy protonu proton Compton wavelength dÅ‚ugość fali Comptona protonu proton-electron mass ratio stosunek masy protonu do masy elektronu proton g factor (gₚ) czynnik g protonu (gₚ) proton gyromagnetic ratio (γₚ) stosunek żyromagnetyczny protonu (γₚ) proton gyromagnetic ratio in MHz/T stosunek żyromagnetyczny protonu w MHz/T proton magnetic moment (μₚ) moment magnetyczny protonu (μₚ) proton magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego protonu do magnetonu Bohra proton magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego protonu do magnetonu jÄ…drowego proton magnetic shielding correction poprawka ekranowania magnetycznego protonu proton mass (mₚ) masa protonu (mₚ) proton mass energy equivalent równoważnik energetyczny masy protonu proton mass energy equivalent in MeV równoważnik energetyczny masy protonu w MeV proton mass in u masa protonu w u proton molar mass (Mₚ) masa molowa protonu (Mₚ) proton-muon mass ratio stosunek masy protonu do masy mionu proton-neutron magnetic moment ratio stosunek momentu magnetycznego protonu do momentu magnetycznego neutronu proton-neutron mass ratio stosunek masy protonu do masy neutronu proton relative atomic mass (Ar(p)) wzglÄ™dna masa atomowa protonu (Ar(p)) proton rms charge radius promieÅ„ Å‚adunkowy RMS protonu proton-tau mass ratio stosunek masy protonu do masy tau reduced proton Compton wavelength zredukowana dÅ‚ugość fali Comptona protonu shielded proton gyromagnetic ratio stosunek żyromagnetyczny ekranowanego protonu shielded proton gyromagnetic ratio in MHz/T stosunek żyromagnetyczny ekranowanego protonu w MHz/T shielded proton magnetic moment moment magnetyczny ekranowanego protonu shielded proton magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego ekranowanego protonu do magnetonu Bohra shielded proton magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego ekranowanego protonu do magnetonu jÄ…drowego neutron Compton wavelength dÅ‚ugość fali Comptona neutronu neutron-electron magnetic moment ratio stosunek momentu magnetycznego neutronu do momentu magnetycznego elektronu neutron-electron mass ratio stosunek masy neutronu do masy elektronu neutron g factor (gâ‚™) czynnik g neutronu (gâ‚™) neutron gyromagnetic ratio (γₙ) stosunek żyromagnetyczny neutronu (γₙ) neutron gyromagnetic ratio in MHz/T stosunek żyromagnetyczny neutronu w MHz/T neutron magnetic moment (μₙ) moment magnetyczny neutronu (μₙ) neutron magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego neutronu do magnetonu Bohra neutron magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego neutronu do magnetonu jÄ…drowego neutron mass (mâ‚™) masa neutronu (mâ‚™) neutron mass energy equivalent równoważnik energetyczny masy neutronu neutron mass energy equivalent in MeV równoważnik energetyczny masy neutronu w MeV neutron mass in u masa neutronu w u neutron molar mass (Mâ‚™) masa molowa neutronu (Mâ‚™) neutron-muon mass ratio stosunek masy neutronu do masy mionu neutron-proton magnetic moment ratio stosunek momentu magnetycznego neutronu do momentu magnetycznego protonu neutron-proton mass difference różnica mas neutronu i protonu neutron-proton mass difference energy equivalent równoważnik energetyczny różnicy mas neutronu i protonu neutron-proton mass difference energy equivalent in MeV równoważnik energetyczny różnicy mas neutronu i protonu w MeV neutron-proton mass difference in u różnica mas neutronu i protonu w u neutron-proton mass ratio stosunek masy neutronu do masy protonu neutron relative atomic mass (Ar(n)) wzglÄ™dna masa atomowa neutronu (Ar(n)) neutron-tau mass ratio stosunek masy neutronu do masy tau neutron to shielded proton magnetic moment ratio stosunek momentu magnetycznego neutronu do momentu magnetycznego ekranowanego protonu reduced neutron Compton wavelength zredukowana dÅ‚ugość fali Comptona neutronu deuteron-electron magnetic moment ratio stosunek momentu magnetycznego deuteronu do momentu magnetycznego elektronu deuteron-electron mass ratio stosunek masy deuteronu do masy elektronu deuteron g factor czynnik g deuteronu deuteron magnetic moment moment magnetyczny deuteronu deuteron magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego deuteronu do magnetonu Bohra deuteron magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego deuteronu do magnetonu jÄ…drowego deuteron mass masa deuteronu deuteron mass energy equivalent równoważnik energetyczny masy deuteronu deuteron mass energy equivalent in MeV równoważnik energetyczny masy deuteronu w MeV deuteron mass in u masa deuteronu w u deuteron molar mass masa molowa deuteronu deuteron-neutron magnetic moment ratio stosunek momentu magnetycznego deuteronu do momentu magnetycznego neutronu deuteron-proton magnetic moment ratio stosunek momentu magnetycznego deuteronu do momentu magnetycznego protonu deuteron-proton mass ratio stosunek masy deuteronu do masy protonu deuteron relative atomic mass (Ar(d)) wzglÄ™dna masa atomowa deuteronu (Ar(d)) deuteron rms charge radius promieÅ„ Å‚adunkowy RMS deuteronu triton-electron mass ratio stosunek masy trytonu do masy elektronu triton g factor (gₜ) czynnik g trytonu (gₜ) triton magnetic moment (μₜ) moment magnetyczny trytonu (μₜ) triton magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego trytonu do magnetonu Bohra triton magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego trytonu do magnetonu jÄ…drowego triton mass (mₜ) masa trytonu (mₜ) triton mass energy equivalent równoważnik energetyczny masy trytonu triton mass energy equivalent in MeV równoważnik energetyczny masy trytonu w MeV triton mass in u masa trytonu w u triton molar mass (Mₜ) masa molowa trytonu (Mₜ) triton-proton mass ratio stosunek masy trytonu do masy protonu triton relative atomic mass (Ar(t)) wzglÄ™dna masa atomowa trytonu (Ar(t)) triton to proton magnetic moment ratio stosunek momentu magnetycznego trytonu do momentu magnetycznego protonu helion-electron mass ratio stosunek masy helionu do masy elektronu helion g factor (gâ‚•) czynnik g helionu (gâ‚•) helion magnetic moment (μₕ) moment magnetyczny helionu (μₕ) helion magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego helionu do magnetonu Bohra helion magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego helionu do magnetonu jÄ…drowego helion mass (mâ‚•) masa helionu (mâ‚•) helion mass energy equivalent równoważnik energetyczny masy helionu helion mass energy equivalent in MeV równoważnik energetyczny masy helionu w MeV helion mass in u masa helionu w u helion molar mass (Mâ‚•) masa molowa helionu (Mâ‚•) helion-proton mass ratio stosunek masy helionu do masy protonu helion relative atomic mass (Ar(h)) wzglÄ™dna masa atomowa helionu (Ar(h)) helion shielding shift przesuniÄ™cie ekranowania helionu shielded helion gyromagnetic ratio stosunek żyromagnetyczny ekranowanego helionu shielded helion gyromagnetic ratio in MHz/T stosunek żyromagnetyczny ekranowanego helionu w MHz/T shielded helion magnetic moment moment magnetyczny ekranowanego helionu shielded helion magnetic moment to Bohr magneton ratio stosunek momentu magnetycznego ekranowanego helionu do magnetonu Bohra shielded helion magnetic moment to nuclear magneton ratio stosunek momentu magnetycznego ekranowanego helionu do magnetonu jÄ…drowego shielded helion to proton magnetic moment ratio stosunek momentu magnetycznego ekranowanego helionu do momentu magnetycznego protonu shielded helion to shielded proton magnetic moment ratio stosunek momentu magnetycznego ekranowanego helionu do momentu magnetycznego ekranowanego protonu alpha particle mass masa czÄ…stki alfa alpha particle mass in u masa czÄ…stki alfa w u alpha particle mass energy equivalent równoważnik energetyczny masy czÄ…stki alfa alpha particle mass energy equivalent in MeV równoważnik energetyczny masy czÄ…stki alfa w MeV alpha particle-electron mass ratio stosunek masy czÄ…stki alfa do masy elektronu alpha particle-proton mass ratio stosunek masy czÄ…stki alfa do masy protonu alpha particle rms charge radius promieÅ„ Å‚adunkowy RMS czÄ…stki alfa alpha particle molar mass masa molowa czÄ…stki alfa alpha particle relative atomic mass (Ar(α)) wzglÄ™dna masa atomowa czÄ…stki alfa (Ar(α)) atomic mass constant (mᵤ) staÅ‚a masy atomowej (mᵤ) Avogadro constant staÅ‚a Avogadra Boltzmann constant (k) staÅ‚a Boltzmanna (k) Boltzmann constant in eV/K staÅ‚a Boltzmanna w eV/K Boltzmann constant in Hz/K staÅ‚a Boltzmanna w Hz/K Boltzmann constant in inverse meter per kelvin staÅ‚a Boltzmanna w metrach odwrotnych na kelwin electron volt (eV) elektronowolt (eV) Faraday constant (F) staÅ‚a Faradaya (F) first radiation constant (câ‚�) pierwsza staÅ‚a promieniowania (câ‚�) first radiation constant for spectral radiance pierwsza staÅ‚a promieniowania dla radiancji widmowej molar gas constant (R) molowa staÅ‚a gazowa (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) staÅ‚a Loschmidta (nâ‚€, 273,15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) staÅ‚a Loschmidta (nâ‚€, 273,15 K, 101,325 kPa) molar Planck constant molowa staÅ‚a Plancka second radiation constant (câ‚‚) druga staÅ‚a promieniowania (câ‚‚) Stefan-Boltzmann constant (σ) staÅ‚a Stefana-Boltzmanna (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) odstÄ™p sieciowy idealnego Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent równoważnik energetyczny staÅ‚ej masy atomowej atomic mass constant energy equivalent in MeV równoważnik energetyczny staÅ‚ej masy atomowej w MeV atomic mass unit-electron volt relationship zależność: jednostka masy atomowej–elektronowolt molar mass constant (Mᵤ) staÅ‚a masy molowej (Mᵤ) molar mass of carbon-12 masa molowa wÄ™gla-12 molar volume of ideal gas (273.15 K, 100 kPa) objÄ™tość molowa gazu doskonaÅ‚ego (273,15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) objÄ™tość molowa gazu doskonaÅ‚ego (273,15 K, 101,325 kPa) molar volume of silicon objÄ™tość molowa krzemu Sackur-Tetrode constant (1 K, 100 kPa) staÅ‚a Sackura-Tetrodego (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) staÅ‚a Sackura-Tetrodego (1 K, 101,325 kPa) Wien frequency displacement law constant staÅ‚a prawa przesunięć Wiena dla czÄ™stotliwoÅ›ci Wien wavelength displacement law constant staÅ‚a prawa przesunięć Wiena dla dÅ‚ugoÅ›ci fali standard atmosphere (atm) atmosfera standardowa (atm) standard-state pressure (p°) ciÅ›nienie stanu standardowego (p°) Angstrom star (Ã…*) angstrem gwiazdkowy (Ã…*) Copper x unit jednostka rentgenowska miedzi Molybdenum x unit jednostka rentgenowska molibdenu atomic unit of magnetizability atomowa jednostka magnetyzowalnoÅ›ci atomic unit of mass (mâ‚‘) atomowa jednostka masy (mâ‚‘) atomic unit of momentum atomowa jednostka pÄ™du atomic unit of permittivity atomowa jednostka przenikalnoÅ›ci elektrycznej atomic unit of time atomowa jednostka czasu atomic unit of velocity atomowa jednostka prÄ™dkoÅ›ci hartree-hertz relationship zależność: hartree–herc hartree-inverse meter relationship zależność: hartree–metr odwrotny hartree-joule relationship zależność: hartree–dżul hartree-kelvin relationship zależność: hartree–kelwin hartree-kilogram relationship zależność: hartree–kilogram shielding difference of d and p in HD różnica ekranowania d i p w HD shielding difference of t and p in HT różnica ekranowania t i p w HT pi (Ï€) pi (Ï€) Euler's number (e) liczba Eulera (e) golden ratio (φ) zÅ‚ota proporcja (φ) Euler-Mascheroni constant (γ) staÅ‚a Eulera-Mascheroniego (γ) nominal solar radius nominalny promieÅ„ SÅ‚oÅ„ca nominal solar total irradiance nominalne caÅ‚kowite natężenie promieniowania sÅ‚onecznego nominal solar luminosity nominalna jasność SÅ‚oÅ„ca nominal solar effective temperature nominalna temperatura efektywna SÅ‚oÅ„ca nominal solar mass parameter nominalny parametr masowy SÅ‚oÅ„ca nominal terrestrial equatorial radius nominalny promieÅ„ równikowy Ziemi nominal terrestrial polar radius nominalny promieÅ„ biegunowy Ziemi nominal terrestrial mass parameter nominalny parametr masowy Ziemi nominal jovian equatorial radius nominalny promieÅ„ równikowy Jowisza nominal jovian polar radius nominalny promieÅ„ biegunowy Jowisza nominal jovian mass parameter nominalny parametr masowy Jowisza average value of one minus the rate of TCG relative to TCB Å›rednia wartość jednoÅ›ci minus tempo TCG wzglÄ™dem TCB solar mass parameter (TCB-compatible) parametr masowy SÅ‚oÅ„ca (zgodny z TCB) solar mass parameter (TDB-compatible) parametr masowy SÅ‚oÅ„ca (zgodny z TDB) equatorial radius of the Earth (TT-compatible) promieÅ„ równikowy Ziemi (zgodny z TT) dynamical form factor of the Earth dynamiczny współczynnik ksztaÅ‚tu Ziemi time rate of change in the dynamical form factor of the Earth tempo zmiany dynamicznego współczynnika ksztaÅ‚tu Ziemi geocentric gravitational constant (TCB-compatible) geocentryczna staÅ‚a grawitacyjna (zgodna z TCB) geocentric gravitational constant (TT-compatible) geocentryczna staÅ‚a grawitacyjna (zgodna z TT) geocentric gravitational constant (TDB-compatible) geocentryczna staÅ‚a grawitacyjna (zgodna z TDB) potential of the geoid potencjaÅ‚ geoidy nominal mean angular velocity of the Earth (TT-compatible) nominalna Å›rednia prÄ™dkość kÄ…towa Ziemi (zgodna z TT) ratio mass of the Moon to the Earth stosunek masy Księżyca do masy Ziemi ratio of the mass of the Sun to Mercury stosunek masy SÅ‚oÅ„ca do masy Merkurego ratio of the mass of the Sun to Venus stosunek masy SÅ‚oÅ„ca do masy Wenus ratio of the mass of the Sun to Mars stosunek masy SÅ‚oÅ„ca do masy Marsa ratio of the mass of the Sun to Jupiter stosunek masy SÅ‚oÅ„ca do masy Jowisza ratio of the mass of the Sun to Saturn stosunek masy SÅ‚oÅ„ca do masy Saturna ratio of the mass of the Sun to Uranus stosunek masy SÅ‚oÅ„ca do masy Urana ratio of the mass of the Sun to Neptune stosunek masy SÅ‚oÅ„ca do masy Neptuna ratio of the mass of the Sun to (134340) Pluto stosunek masy SÅ‚oÅ„ca do masy (134340) Plutona ratio of the mass of the Sun to (136199) Eris stosunek masy SÅ‚oÅ„ca do masy (136199) Eris ratio of the mass of (1) Ceres to the Sun stosunek masy (1) Ceres do masy SÅ‚oÅ„ca ratio of the mass of (2) Pallas to the Sun stosunek masy (2) Pallas do masy SÅ‚oÅ„ca ratio of the mass of (4) Vesta to the Sun stosunek masy (4) Westy do masy SÅ‚oÅ„ca mean obliquity of the ecliptic at J2000.0 Å›rednie nachylenie ekliptyki w J2000.0 Electromagnetic Elektromagnetyczne Compton wavelength dÅ‚ugość fali Comptona Astronomy Astronomia ConstantsWidget Domain Dziedzina Subdomain Poddziedzina No match found Brak dopasowaÅ„ Name Nazwa Value Wartość Unit Jednostka Search Wyszukiwanie All Wszystko CustomKeypadDialog Custom Keypad WÅ‚asna klawiatura Rows: Wiersze: Columns: Kolumny: Copy preset: Kopiuj ustawienie wstÄ™pne: Basic Podstawowa Scientific (wide) Naukowa (szeroka) Scientific (narrow) Naukowa (wÄ…ska) Apply Zastosuj Row Wiersz Column Kolumna Label Etykieta Behavior Zachowanie Text Tekst DiagnosticsDialog App Diagnostics Diagnostyka aplikacji Copy to Clipboard Kopiuj do schowka Editor Unit Jednostka User unit Jednostka użytkownika User function Funkcja użytkownika Argument Argument Current result:<br/>%1 Bieżący wynik:<br/>%1 Selection result:<br/>%1 Wynik zaznaczenia:<br/>%1 Selection result: n/a Wynik zaznaczenia: brak Selection result: %1 Wynik zaznaczenia: %1 second sekunda metre metr kilogram kilogram mole mol radian radian steradian steradian degree Celsius stopieÅ„ Celsjusza cubic metre metr szeÅ›cienny cubic millimetre milimetr szeÅ›cienny cubic centimetre centymetr szeÅ›cienny cubic decimetre decymetr szeÅ›cienny cubic kilometre kilometr szeÅ›cienny square millimetre milimetr kwadratowy square kilometre kilometr kwadratowy square metre metr kwadratowy minute minuta hour godzina day dzieÅ„ astronomical unit jednostka astronomiczna degree stopieÅ„ arcminute minuta kÄ…towa arcsecond sekunda kÄ…towa milliarcsecond milisekunda kÄ…towa microarcsecond mikrosekunda kÄ…towa hectare hektar litre litr tonne tona Dalton dalton electronvolt elektronowolt Angstrom angstrem atmosphere atmosfera atomic mass unit jednostka masy atomowej British thermal unit brytyjska jednostka cieplna calorie kaloria carat karat metryczny cup kubek cup (Imperial) kubek (imperialny) cup (Japanese) kubek (japoÅ„ski) cup (US) kubek (USA) degree Fahrenheit stopieÅ„ Fahrenheita fathom sążeÅ„ fluid ounce (Imperial) uncja pÅ‚ynu (imperialna) fluid ounce (US) uncja pÅ‚ynu (USA) fluid dram (Imperial) drachma pÅ‚ynna (imperialna) fluid dram (US) drachma pÅ‚ynna (USA) foot stopa square foot stopa kwadratowa cubic foot stopa szeÅ›cienna gallon (Imperial) galon (imperialny) gallon (US) galon (USA) gill (Imperial) gill (imperialny) gill (US) gill (USA) gradian grad grain gran gram gram Hartley hartley Hartree energy unit jednostka energii Hartreego horsepower koÅ„ mechaniczny inch cal square inch cal kwadratowy cubic inch cal szeÅ›cienny karat karat knot wÄ™zeÅ‚ lightminute minuta Å›wietlna lightsecond sekunda Å›wietlna lightyear rok Å›wietlny long ton tona dÅ‚uga mile mila square mile mila kwadratowa cubic mile mila szeÅ›cienna mile per hour mila na godzinÄ™ kilometre per hour kilometr na godzinÄ™ nautical mile mila morska ounce uncja parsec parsek pint (Imperial) pinta (imperialna) pint (US) pinta (USA) pound funt pounds per square inch funty na cal kwadratowy quart (Imperial) kwarta (imperialna) quart (US) kwarta (USA) oil barrel baryÅ‚ka ropy beer barrel (US) beczka piwa (USA) square yard jard kwadratowy cubic yard jard szeÅ›cienny short ton tona krótka tablespoon Å‚yżka stoÅ‚owa tablespoon (Australian) Å‚yżka stoÅ‚owa (australijska) tablespoon (Imperial) Å‚yżka stoÅ‚owa (imperialna) tablespoon (US) Å‚yżka stoÅ‚owa (USA) dessert spoon Å‚yżka deserowa teaspoon Å‚yżeczka teaspoon (Imperial) Å‚yżeczka (imperialna) teaspoon (US) Å‚yżeczka (USA) turn obrót revolution peÅ‚ny obrót revolution per minute obroty na minutÄ™ week tydzieÅ„ kilowatt hour kilowatogodzina millimetre of mercury milimetr sÅ‚upa rtÄ™ci yard jard Julian century wiek juliaÅ„ski Julian year rok juliaÅ„ski sidereal year rok gwiazdowy tropical year rok zwrotnikowy Evaluator invalid expression nieprawidÅ‚owe wyrażenie division by zero dzielenie przez zero too time consuming - computation was rejected zbyt czasochÅ‚onne - obliczenia zostaÅ‚y odrzucone dimension mismatch - quantities with different dimensions cannot be compared, added, etc. błąd wymiaru - wartoÅ›ci o różnych wymiarach nie mogÄ… być porównywane lub dodawane. invalid dimension - operation might require dimensionless arguments nieprawidÅ‚owy wymiar - operacja może wymagać bezwymiarowych argumentów Computation aborted - encountered numerical instability Obliczanie przerwane - napotkano niestabilność numerycznÄ… invalid dimension - function might require dimensionless arguments nieprawidÅ‚owy wymiar - funkcja może wymagać bezwymiarowych argumentów error błąd unit must not be zero jednostka nie może być równa zero Conversion failed - dimension mismatch Konwersja nie powiodÅ‚a siÄ™ - niedopasowane wymiary unknown function or variable nieznana funkcja albo zmienna recursion not supported rekurencja nie jest obsÅ‚ugiwana cannot operate on a NaN nie można wykonywać operacji na NaN underflow - tiny result is out of SpeedCrunch's number range niedomiar - bardzo maÅ‚y wynik jest poza zakresem liczb SpeedCrunch overflow - huge result is out of SpeedCrunch's number range przepeÅ‚nienie - ogromny wynik jest poza zakresem liczb SpeedCrunch overflow - logic result exceeds maximum of 256 bits przepeÅ‚nienie - dÅ‚ugość wyniku logicznego przekracza 256 bitów overflow - integer result exceeds maximum limit for integers przepeÅ‚nienie - wynik caÅ‚kowity przekracza maksymalny limit dla liczb caÅ‚kowitych operation is not defined for these arguments operacja nie jest zdefiniowana dla tych argumentów wrong number of arguments nieprawidÅ‚owa liczba argumentów does not take NaN as an argument NaN nie jest dozwolony jako argument result out of range wynik znajduje siÄ™ poza zakresem undefined for argument domain niezdefiniowany dla domeny argumentu computation too expensive obliczenia byÅ‚yby zbyt kosztowne internal error, please report a bug wewnÄ™trzny błąd, zgÅ‚oÅ› problem syntax error błąd skÅ‚adni conversion target must be a unit cel konwersji musi być jednostkÄ… unknown unit nieznana jednostka %1 is a reserved name, please choose another %1 jest nazwÄ… zarezerwowanÄ…, wybierz innÄ… %1 is a global user definition and cannot be overridden in this session. %1 jest globalnÄ… definicjÄ… użytkownika i nie można jej zastÄ…pić w tej sesji. %1 is a variable name, please choose another or delete the variable %1 jest nazwÄ… zmiennej, wybierz innÄ… albo usuÅ„ tÄ™ zmiennÄ… argument %1 is used more than once argument %1 używany jest wiÄ™cej niż raz %1 is a built-in unit name, please choose another %1 jest nazwÄ… wbudowanej jednostki, wybierz innÄ… %1 is a user function name, please choose another or delete the function %1 jest nazwÄ… funkcji użytkownika, wybierz innÄ… albo usuÅ„ tÄ™ funkcjÄ™ FunctionRepo max; trials; probability maksimum; próby; prawdopodobieÅ„stwo trials; probability próby; prawdopodobieÅ„stwo hits; trials; probability sukcesy; próby; prawdopodobieÅ„stwo max; total; hits; trials maksimum; łącznie; sukcesy; próby total; hits; trials łącznie; sukcesy; próby count; total; hits; trials liczba; łącznie; sukcesy; próby dividend; divisor dzielna; dzielnik x; exponent_bits; significand_bits [; exponent_bias] x; bity_wykÅ‚adnika; bity_mantysy [; przesuniÄ™cie_wykÅ‚adnika] base; x podstawa; x value; modulo wartość; moduÅ‚ base; exponent; modulo podstawa; wykÅ‚adnik; moduÅ‚ events; average_events zdarzenia; Å›rednia_liczba_zdarzeÅ„ average_events Å›rednia_liczba_zdarzeÅ„ x [; precision] x [; precyzja] Absolute Value Wartość bezwzglÄ™dna Absolute Deviation Odchylenie bezwzglÄ™dne Arc Cosine Arcus cosinus Logical AND Logiczne AND Area Hyperbolic Cosine Area cosinus hiperboliczny Area Hyperbolic Sine Area sinus hiperboliczny Area Hyperbolic Tangent Area tangens hiperboliczny Arc Sine Arcus sinus Arc Tangent Arcus tangens Arc Tangent with two Arguments Arcus tangens z dwoma argumentami Average (Arithmetic Mean) Åšrednia arytmetyczna Binomial Cumulative Distribution Function Dystrybuanta rozkÅ‚adu dwumianowego Binomial Distribution Mean Åšrednia rozkÅ‚adu dwumianowego Binomial Probability Mass Function Funkcja masy prawdopodobieÅ„stwa rozkÅ‚adu dwumianowego Binomial Distribution Variance Wariancja rozkÅ‚adu dwumianowego Cube Root Pierwiastek szeÅ›cienny Complex Conjugate Sprzężenie zespolone Cosine Cosinus Hyperbolic Cosine Cosinus hiperboliczny Cotangent Cotangens Cosecant Kosekans Convert Unix timestamp to Date Konwersja znacznika czasu Unix na datÄ™ Degrees of Arc KÄ…t w stopniach Error Function Funkcja błędu Complementary Error Function DopeÅ‚niajÄ…ca funkcja błędu Exponential WykÅ‚adnicza Fractional Part Część uÅ‚amkowa Extension of Factorials [= (x-1)!] Rozszerzenie silni [= (x-1)!] Greatest Common Divisor NajwiÄ™kszy wspólny dzielnik Geometric Mean Åšrednia geometryczna Gradians of arc KÄ…t w gradach Hypergeometric Cumulative Distribution Function Dystrybuanta rozkÅ‚adu hipergeometrycznego Hypergeometric Distribution Mean Åšrednia rozkÅ‚adu hipergeometrycznego Hypergeometric Probability Mass Function Funkcja masy prawdopodobieÅ„stwa rozkÅ‚adu hipergeometrycznego Hypergeometric Distribution Variance Wariancja rozkÅ‚adu hipergeometrycznego Integer Quotient Iloraz caÅ‚kowity Integer Part Część caÅ‚kowita Imaginary Part Część urojona Decode IEEE-754 Binary Value Dekodowanie wartoÅ›ci binarnej IEEE-754 Encode IEEE-754 Binary Value Kodowanie wartoÅ›ci binarnej IEEE-754 Decode 16-bit Half-Precision Value Dekodowanie wartoÅ›ci 16-bitowej półprecyzji Encode 16-bit Half-Precision Value Kodowanie wartoÅ›ci 16-bitowej półprecyzji Decode 32-bit Single-Precision Value Dekodowanie wartoÅ›ci 32-bitowej pojedynczej precyzji Encode 32-bit Single-Precision Value Kodowanie wartoÅ›ci 32-bitowej pojedynczej precyzji Decode 64-bit Double-Precision Value Dekodowanie wartoÅ›ci 64-bitowej podwójnej precyzji Encode 64-bit Double-Precision Value Kodowanie wartoÅ›ci 64-bitowej podwójnej precyzji Decode 128-bit Quad-Precision Value Dekodowanie wartoÅ›ci 128-bitowej poczwórnej precyzji Encode 128-bit Quad-Precision Value Kodowanie wartoÅ›ci 128-bitowej poczwórnej precyzji Binary Logarithm Logarytm binarny Common Logarithm Logarytm dziesiÄ™tny Natural Logarithm Logarytm naturalny Logarithm to Arbitrary Base Logarytm o dowolnej podstawie Mask to a bit size Maskowanie do rozmiaru bitowego Maximum Maksimum Median Value (50th Percentile) Mediana (50. percentyl) Minimum Minimum Modulo Modulo Euclidean Modulo Modulo euklidesowe Modular Exponentiation PotÄ™gowanie modularne Combination (Binomial Coefficient) Kombinacja (współczynnik dwumianowy) Logical NOT Logiczne NOT Permutation (Arrangement) Permutacja (wariacja) Convert to Binary Representation Konwersja do reprezentacji dwójkowej Arithmetic Arytmetyka Chemistry Chemia Complex Liczby zespolone Combinatorics Kombinatoryka Probability PrawdopodobieÅ„stwo Statistics Statystyka Aggregation Agregacja Random Losowe Base conversion Konwersja podstawy Number formatting Formatowanie liczb Integer arithmetic Arytmetyka caÅ‚kowita Special functions Funkcje specjalne Exponential & Logarithmic WykÅ‚adnicze i logarytmiczne Angle conversion Konwersja kÄ…tów Trigonometry Trygonometria Bitwise Bitowe Floating point Zmiennoprzecinkowe Date & Time Data i czas Linear algebra Algebra liniowa unix_timestamp; x hours offset to GMT znacznik_unix; przesuniÄ™cie x godzin wzglÄ™dem GMT yyyymmdd.hhmmss; x hours offset to GMT rrrrmmdd.hhmmss; przesuniÄ™cie x godzin wzglÄ™dem GMT [digits] [cyfry] max [; min] maks. [; min.] List Literal LiteraÅ‚ listy Convert to Padded Binary Representation Konwersja do uzupeÅ‚nionej reprezentacji dwójkowej Round Toward +∞ (Ceiling) ZaokrÄ…glenie w kierunku +∞ (sufit) Cosine plus Imaginary Sine Cosinus plus sinus urojony Convert to Cis Complex Form Konwersja do postaci zespolonej cis Matrix Column Count Liczba kolumn macierzy Population Correlation Matrix (n) Macierz korelacji populacji (n) Sample Correlation Matrix (n-1) Macierz korelacji próby (n-1) Count Liczba elementów Population Covariance Matrix (n) Macierz kowariancji populacji (n) Sample Covariance Matrix (n-1) Macierz kowariancji próby (n-1) Cross Product Iloczyn wektorowy Convert Date to Unix timestamp Konwersja daty na znacznik czasu Unix Convert to Decimal Representation Konwersja do reprezentacji dziesiÄ™tnej Determinant Wyznacznik Convert to Sexagesimal Notation Konwersja do zapisu sześćdziesiÄ…tkowego Dot Product Iloczyn skalarny Convert to Engineering Notation Konwersja do notacji inżynierskiej Convert to Exponential Complex Form Konwersja do wykÅ‚adniczej postaci zespolonej Round Toward −∞ (Floor) ZaokrÄ…glenie w kierunku −∞ (podÅ‚oga) Flatten Matrix SpÅ‚aszczenie macierzy Least Common Multiple Najmniejsza wspólna wielokrotność Convert to Hexadecimal Representation Konwersja do reprezentacji szesnastkowej Convert to Padded Hexadecimal Representation Konwersja do uzupeÅ‚nionej reprezentacji szesnastkowej Inverse Matrix Macierz odwrotna Round to 16-bit Half-Precision Value ZaokrÄ…glenie do wartoÅ›ci 16-bitowej półprecyzji Round to 32-bit Single-Precision Value ZaokrÄ…glenie do wartoÅ›ci 32-bitowej pojedynczej precyzji Round to 64-bit Double-Precision Value ZaokrÄ…glenie do wartoÅ›ci 64-bitowej podwójnej precyzji Round to 128-bit Quad-Precision Value ZaokrÄ…glenie do wartoÅ›ci 128-bitowej poczwórnej precyzji Residual from 16-bit Half-Precision Rounding Reszta po zaokrÄ…gleniu do 16-bitowej półprecyzji Residual from 32-bit Single-Precision Rounding Reszta po zaokrÄ…gleniu do 32-bitowej pojedynczej precyzji Residual from 64-bit Double-Precision Rounding Reszta po zaokrÄ…gleniu do 64-bitowej podwójnej precyzji Residual from 128-bit Quad-Precision Rounding Reszta po zaokrÄ…gleniu do 128-bitowej poczwórnej precyzji Substance Mass Masa substancji Molarity Stężenie molowe Molar Mass Masa molowa Median Absolute Deviation Mediana odchyleÅ„ bezwzglÄ™dnych Mean Åšrednia Numerical Value of Quantity Wartość liczbowa wielkoÅ›ci Random Decimal Number Losowa liczba dziesiÄ™tna Random Integer Number Losowa liczba caÅ‚kowita Convert to Rational Representation Konwersja do reprezentacji wymiernej Convert to Octal Representation Konwersja do reprezentacji ósemkowej Convert to Padded Octal Representation Konwersja do uzupeÅ‚nionej reprezentacji ósemkowej Vector or Matrix Norm Norma wektora lub macierzy Logical OR Logiczne OR Population Count (Hamming Weight) Liczba ustawionych bitów (waga Hamminga) Phase of Complex Number Faza liczby zespolonej Poissonian Cumulative Distribution Function Dystrybuanta rozkÅ‚adu Poissona Poissonian Distribution Mean Åšrednia rozkÅ‚adu Poissona Poissonian Probability Mass Function Funkcja masy prawdopodobieÅ„stwa rozkÅ‚adu Poissona Poissonian Distribution Variance Wariancja rozkÅ‚adu Poissona Convert to Phasor Complex Form Konwersja do postaci fazorowej Convert to Rectangular Complex Form Konwersja do postaci prostokÄ…tnej liczby zespolonej Round Half Away from Zero ZaokrÄ…glenie połówek od zera Round Half Even ZaokrÄ…glenie połówek do parzystej Nth Root Pierwiastek n-tego stopnia Convert to Scientific Notation Konwersja do notacji naukowej Matrix Row Count Liczba wierszy macierzy List or Matrix Shape KsztaÅ‚t listy lub macierzy Summation Sumowanie Population Standard Deviation (n) Odchylenie standardowe populacji (n) Sample Standard Deviation (n-1) Odchylenie standardowe próby (n-1) Round Toward Zero (Truncation) ZaokrÄ…glenie w kierunku zera (obciÄ™cie) Matrix Trace Åšlad macierzy Transpose Matrix Transpozycja macierzy Population Variance (n) Wariancja populacji (n) Sample Variance (n-1) Wariancja próby (n-1) Product Iloczyn Radians Radiany Matrix Rank RzÄ…d macierzy Real Part Część rzeczywista Secant Sekans Arithmetic Shift Left PrzesuniÄ™cie arytmetyczne w lewo Arithmetic Shift Right PrzesuniÄ™cie arytmetyczne w prawo Signum Znak liczby Sine Sinus Hyperbolic Sine Sinus hiperboliczny Square Root Pierwiastek kwadratowy Sum Suma Tangent Tangens Convert to Trigonometric Complex Form Konwersja do trygonometrycznej postaci zespolonej Turns Obroty Hyperbolic Tangent Tangens hiperboliczny Sign-extend a value Rozszerzenie znaku wartoÅ›ci Logical XOR Logiczne XOR FunctionsWidget Domain Dziedzina All Wszystko Name Nazwa Search Wyszukiwanie No match found Brak dopasowaÅ„ Identifier Identyfikator HistoryWidget Remove All Calculations Above UsuÅ„ wszystkie obliczenia powyżej Remove This Calculation UsuÅ„ to obliczenie Remove All Calculations Below UsuÅ„ wszystkie obliczenia poniżej Keypad Inverse cosine Odwrotny kosinus The last result Poprzedni wynik Inverse sine Odwrotny sinus Inverse tangent Odwrotny tangens Evaluate expression Oblicz wyrażenie Division Dzielenie Multiplication Mnożenie Subtraction Odejmowanie Addition Dodawanie Clear expression Wyczyść wyrażenie Cosine Cosinus Backspace Backspace Scientific notation Notacja naukowa Exponential WykÅ‚adnicza Factorial Silnia Natural logarithm Logarytm naturalny Left parenthesis Lewy nawias Nth root Pierwiastek n-tego stopnia Argument separator Separator argumentów Square Kwadrat Common logarithm Logarytm dziesiÄ™tny Modulo Modulo Contextual percentage Procent kontekstowy Power PotÄ™gowanie Right parenthesis Prawy nawias Sine Sinus Square root Pierwiastek kwadratowy Tangent Tangens Pi Pi Decimal separator Separator dziesiÄ™tny MainWindow Radian Radian Degree StopieÅ„ Gradian Grad Binary Dwójkowa Octal Ósemkowa Hexadecimal Szesnastkowa Sexagesimal SześćdziesiÄ…tkowa Engineering decimal DziesiÄ™tna inżynierska Scientific decimal DziesiÄ™tna naukowa &Import... &Importuj... &Quit &ZakoÅ„cz Clear E&xpression W&yczyść wyrażenie Clear &History Wyczyść &historiÄ™ &Copy &Kopiuj &Paste &Wklej &Select Expression &Zaznacz wyrażenie &Constants &StaÅ‚e &Functions &Funkcje &History &Historia &Status Bar Pasek s&tanu Bitfield Pole bitowe Use&r Functions Fun&kcje użytkownika &Degree &StopieÅ„ &Radian &Radian &Gradian &Grad Re&volution &PeÅ‚ny obrót Auto-Insert a&ns Automatycz&nie wstawiaj ans Automatic &Completion Automatyczne &dopeÅ‚nianie &Built-in Functions Funkcje w&budowane Built-in &Variables &Zmienne wbudowane User &Functions &Funkcje użytkownika User Va&riables Z&mienne użytkownika Open a Private Tab on Startup Otwieraj kartÄ™ prywatnÄ… przy uruchamianiu Open and focus a new private tab whenever SpeedCrunch starts. Otwieraj i uaktywniaj nowÄ… kartÄ™ prywatnÄ… przy każdym uruchomieniu SpeedCrunch. Syntax &Highlighting PodÅ›wietlanie &skÅ‚adni Group Digits in &Input Grupuj cyfry na wejÅ›c&iu Automatic Input &Adjustments &Automatyczne korekty wejÅ›cia Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Automatycznie dostosowuj operatory, odstÄ™py, nawiasy i potÄ™gi oraz ograniczaj wejÅ›cie do prawidÅ‚owych znaków. Group input digits using the selected number format. Grupuj wprowadzane cyfry zgodnie z wybranym formatem liczb. &Blinking Cursor &MigajÄ…cy kursor Blink the cursor in the expression editor. Włącz miganie kursora w edytorze wyrażeÅ„. &Escape Clears Editor &Escape czyÅ›ci edytor Clear the focused expression editor with Escape after dismissing any popup or preview. Czyść aktywny edytor wyrażeÅ„ klawiszem Escape po zamkniÄ™ciu okien podrÄ™cznych lub podglÄ…du. Keep Expression After Evaluation Zachowuj wyrażenie po obliczeniu Copy New Results Automatically Automatycznie kopiuj nowe wyniki &Comma &Przecinek &System Default DomyÅ›lne &systemowe &Dot &Kropka Dot &And Comma Kropka &i przecinek Toward +∞ (&ceil) W stronÄ™ +∞ (&ceil) Toward −∞ (&floor) W stronÄ™ −∞ (&floor) &Binary &Dwójkowy &Engineering &Inżynierska &Hexadecimal &Szesnastkowy &Octal Ósemk&owy &Scientific &Naukowa User &Manual &Instrukcja Issues and &Feedback &Problemy i opinie &Donate &Wesprzyj &About SpeedCrunch &O SpeedCrunch App Diag&nostics Diag&nostyka aplikacji S&plit &Podziel Angle &Mode &Tryb kÄ…towy &Complex Form &Postać zespolona New Tab Nowa karta Constants StaÅ‚e Functions Funkcje History Historia User Functions Funkcje użytkownika &Font... &Czcionka... &Language... &JÄ™zyk... &Session &Sesja &Edit &Edycja &View &Widok Se&ttings Us&tawienia &Decimal D&ziesiÄ™tny &Keypad &Klawiatura Always on &Top Zawsze na &wierzchu Disabled Wyłączony Small Space MaÅ‚y odstÄ™p Medium Space Åšredni odstÄ™p Large Space Duży odstÄ™p &0 Digits &0 cyfr &15 Digits &15 cyfr &2 Digits &2 cyfry &3 Digits &3 cyfry &50 Digits &50 cyfr &8 Digits &8 cyfr &Sexagesimal &SześćdziesiÄ…tkowy Reset All Settings... Przywróć wszystkie ustawienia... &System &System SpeedCrunch &Theme Mo&tyw SpeedCrunch &Classic &Klasyczny &Modern &Nowoczesny Context Help Pomoc kontekstowa &Help &Pomoc Error Błąd Can't read from file %1 Nie można czytać z pliku %1 Import Session Importuj sesjÄ™ Close Session Zamknij sesjÄ™ Angle Mode: Tryb kÄ…ta: Notation: Notacja: Precision: Precyzja: Turn Obrót Revolution PeÅ‚ny obrót Fixed-point decimal DziesiÄ™tna staÅ‚oprzecinkowa Rational Wymierna Automatic decimal Automatyczna dziesiÄ™tna Automatic Automatycznie User &Definitions... &Definicje użytkownika... New &Tab Nowa &karta New &Private Tab Nowa karta &prywatna Keep Zachowaj Make Private... Ustaw jako prywatnÄ…... New &Window Nowe &okno &Open... &Otwórz... &Rename... Z&mieÅ„ nazwÄ™... Clo&ne... Klo&nuj... &Close Tab Z&amknij kartÄ™ Reopen Clo&sed Tab O&twórz ponownie zamkniÄ™tÄ… kartÄ™ Open Sessions &Folder Otwórz &folder sesji &Undo &Cofnij &Redo &Ponów Cu&t Wy&tnij Copy &Last Result K&opiuj ostatni wynik &Wrap in Parentheses &Ujmij w nawiasy Full Scr&een Mode Tryb p&eÅ‚noekranowy &Basic &Podstawowa &Scientific (wide) &Naukowa (szeroka) Scientific (narrow) Naukowa (wÄ…ska) &Custom... &WÅ‚asne... Main &Menu &Menu główne User &Variables &Zmienne użytkownika &Left W &lewo &Right W p&rawo &Up &W górÄ™ &Down W &dół Close Pa&ne Zamk&nij panel User &Units &Jednostki użytkownika &Turn O&brót If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. JeÅ›li nowe wyrażenie zaczyna siÄ™ od +, -, * lub /, SpeedCrunch najpierw wstawia "ans". &Accept with Enter &Akceptuj klawiszem Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Akceptuj bieżącÄ… sugestiÄ™ autouzupeÅ‚niania klawiszem Enter bez wczeÅ›niejszego wybierania jej klawiszami strzaÅ‚ek. &Units &Jednostki Show Live Result &Preview Pokaż podglÄ…d wyniku na ż&ywo Save &Window Position on Exit Zapisuj pozycjÄ™ &okna przy wyjÅ›ciu Hover Highlighting PodÅ›wietlanie po najechaniu Group Integer Part Only Grupuj tylko część caÅ‚kowitÄ… Number Format... Format liczb... Notation && Precision... Notacja i precyzja... After pressing Enter, keep the entered expression selected in the editor. Po naciÅ›niÄ™ciu Enter zachowuj wprowadzone wyrażenie zaznaczone w edytorze. Never Nigdy Always Zawsze Only for Single-Line Expressions Tylko dla wyrażeÅ„ jednowierszowych Simplify Displayed Expressions Upraszczaj wyÅ›wietlane wyrażenia History Size &Limit... &Limit rozmiaru historii... Remove Trailing &Zeroes UsuÅ„ koÅ„cowe &zera Nearest, Half &Away (round) Najbliższe, połówki &od zera (round) Nearest, Half &Even (roundeven) Najbliższe, połówki do &parzystej (roundeven) Toward &Zero (trunc) W kierunku &zera (trunc) &Fixed-Point &StaÅ‚oprzecinkowa &Rational &Wymierna &Exponential (m·sâ�»Â¹) &WykÅ‚adnicza (m·sâ�»Â¹) &Fractional (m/s) &UÅ‚amkowa (m/s) &Rectangular (a + bi) &ProstokÄ…tna (a + bi) Exponential (reâ�±á¶¿) WykÅ‚adnicza (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trygonometryczna (r(cos θ + i·sin θ)) Phasor (r∠θ) Fazorowa (r∠θ) &Theme... &Motyw... Check for &Updates Sprawdź &aktualizacje Source Code Kod źródÅ‚owy &Zoom &PowiÄ™kszenie &Results &Wyniki Unit Notation Notacja jednostek Rounding Mode Tryb zaokrÄ…glania &Notation &Notacja &Imaginary Unit Jednostka &urojona &Window &Okno &Editing &Edycja A&utocomplete Auto&uzupeÅ‚nianie Up/Down Arrow History Historia strzaÅ‚kami góra/dół &Appearance &WyglÄ…d &Menus M&enu &Docks Panele &dokowane &Input and Results WejÅ›c&ie i wyniki &Disabled &Wyłączona &Disable &Wyłącz Close preview Zamknij podglÄ…d Rename... ZmieÅ„ nazwÄ™... Clone... Klonuj... Close Tab Zamknij kartÄ™ New Private Tab Nowa karta prywatna Open... Otwórz... Reopen Closed Tab Otwórz ponownie zamkniÄ™tÄ… kartÄ™ Split Podziel Left W lewo Right W prawo Up W górÄ™ Down W dół Clear Wyczyść Delete UsuÅ„ %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sesja prywatna: zawartość jest usuwana przy zamkniÄ™ciu. Wybierz Sesja > Zachowaj, aby zmienić jÄ… w zwykłą sesjÄ™. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Prywatna] Reset All Settings Przywróć wszystkie ustawienia Reset all settings to their default values? Przywrócić domyÅ›lne wartoÅ›ci wszystkich ustawieÅ„? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Dotyczy to wyglÄ…du, edycji, formatów wyników i preferencji okien. Obliczenia, otwarte sesje i definicje użytkownika zostanÄ… zachowane. The settings file could not be written. Nie można zapisać pliku ustawieÅ„. Clear this session's calculations, unfinished expression, variables, functions, and units? WyczyÅ›cić obliczenia, niedokoÅ„czone wyrażenie, zmienne, funkcje i jednostki tej sesji? Global user definitions are kept. Globalne definicje użytkownika zostanÄ… zachowane. Make Session Private Ustaw sesjÄ™ jako prywatnÄ… The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Zapisana sesja %1 zostanie usuniÄ™ta. Jej zawartość pozostanie otwarta w sesji prywatnej i zostanie usuniÄ™ta po zamkniÄ™ciu tej sesji lub zakoÅ„czeniu SpeedCrunch. Make Private Ustaw jako prywatnÄ… Could not delete the saved session %1. Nie można usunąć zapisanej sesji %1. Keep Session Zachowaj sesjÄ™ Could not save the session. It remains private. Nie można zapisać sesji. Pozostaje prywatna. Clone Session Klonuj sesjÄ™ Could not save session file %1. Nie można zapisać pliku sesji %1. Could not delete session file %1. Nie można usunąć pliku sesji %1. JSON file (*.json);;Any file (*.*) Plik JSON (*.json);;Dowolny plik (*.*) Export session as JSON Eksportuj sesjÄ™ jako JSON The selected file is not valid JSON: %1 Wybrany plik nie jest prawidÅ‚owym JSON-em: %1 The selected file is not a SpeedCrunch session JSON file. Wybrany plik nie jest plikiem JSON sesji SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Ten plik używa przestarzaÅ‚ego formatu sesji SpeedCrunch i nie może zostać zaimportowany. The selected JSON file is missing the required $schema field. W wybranym pliku JSON brakuje wymaganego pola $schema. The selected JSON file uses an unsupported JSON schema: %1 Wybrany plik JSON używa nieobsÅ‚ugiwanego schematu JSON: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). W wybranym pliku JSON brakuje identyfikatora schematu sesji SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Wybrany plik JSON używa nieobsÅ‚ugiwanego formatu sesji SpeedCrunch: %1 The selected JSON file is missing the required session name. W wybranym pliku JSON brakuje wymaganej nazwy sesji. The selected JSON file has an empty session name. Wybrany plik JSON ma pustÄ… nazwÄ™ sesji. The selected JSON file has invalid or incomplete SpeedCrunch session data. Wybrany plik JSON zawiera nieprawidÅ‚owe lub niekompletne dane sesji SpeedCrunch. Open Sessions Folder Otwórz folder sesji Could not create the sessions folder: %1 Nie można utworzyć folderu sesji: %1 Could not open the sessions folder: %1 Nie można otworzyć folderu sesji: %1 Editor and Results Font Czcionka edytora i wyników Open Session Otwórz sesjÄ™ Community SpoÅ‚eczność Rename Session ZmieÅ„ nazwÄ™ sesji Clear Session Wyczyść sesjÄ™ Delete Session UsuÅ„ sesjÄ™ Close Pane Zamknij panel User Variables Zmienne użytkownika User Units Jednostki użytkownika Clear History Wyczyść historiÄ™ Are you sure you want to clear the calculation history? Czy na pewno chcesz wyczyÅ›cić historiÄ™ obliczeÅ„? Session name: Nazwa sesji: A session named %1 already exists. Sesja o nazwie %1 już istnieje. Could not create session file %1. Nie można utworzyć pliku sesji %1. Could not write session file %1. Nie można zapisać pliku sesji %1. Are you sure you want to delete this session? Czy na pewno chcesz usunąć tÄ™ sesjÄ™? Custom Precision WÅ‚asna precyzja Fractional digits: Cyfry uÅ‚amkowe: Theme Motyw Light Themes Jasne motywy Dark Themes Ciemne motywy Preview PodglÄ…d Colors Kolory Select color for %1 Wybierz kolor dla %1 Import... Importuj... Export... Eksportuj... Import Theme Importuj motyw Theme file (*.json);;All files (*) Plik motywu (*.json);;Wszystkie pliki (*) Invalid theme file. NieprawidÅ‚owy plik motywu. Can't import theme "%1" because it conflicts with a built-in theme. Nie można zaimportować motywu "%1", ponieważ koliduje z motywem wbudowanym. Can't find a writable theme folder. Nie można znaleźć zapisywalnego folderu motywów. Overwrite Theme ZastÄ…p motyw A custom theme named "%1" already exists. Do you want to overwrite it? Motyw użytkownika o nazwie "%1" już istnieje. Czy chcesz go zastÄ…pić? Can't overwrite theme file %1 Nie można zastÄ…pić pliku motywu %1 Can't copy theme file to %1 Nie można skopiować pliku motywu do %1 Export Theme Eksportuj motyw Can't export theme as "%1" because it conflicts with a built-in theme. Nie można wyeksportować motywu jako "%1", ponieważ koliduje z motywem wbudowanym. Can't write to file %1 Nie można zapisać do pliku %1 Global User Variable Globalna zmienna użytkownika Global User Function Globalna funkcja użytkownika Global User Unit Globalna jednostka użytkownika User Definitions Definicje użytkownika These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Te definicje sÄ… globalne i sÄ… wczytywane do każdej sesji. Nie można ich zmieniać w sesjach i majÄ… pierwszeÅ„stwo przed definicjami o tej samej nazwie z edytora sesji. Wprowadź jednÄ… definicjÄ™ w każdym wierszu. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] PrzykÅ‚ady: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Zastosuj Validate Sprawdź Test Results Wyniki testu Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Zaimportowane zmienne: %1 Zaimportowane funkcje: %2 Zaimportowane jednostki: %3 Numery wierszy z błędami: %4 none brak Apply Results Wyniki zastosowania User definitions saved. Zapisano definicje użytkownika. History Size Limit Limit rozmiaru historii Maximum number of history entries for this session (0 = unlimited): Maksymalna liczba wpisów historii dla tej sesji (0 = bez limitu): Text file (*.txt);;Any file (*.*) Plik tekstowy (*.txt);;Dowolny plik (*.*) Could not recalculate from calculation %1: %2 Nie można ponownie obliczyć od obliczenia %1: %2 History Size Limit Reached OsiÄ…gniÄ™to limit rozmiaru historii This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. To obliczenie zajmuje ostatnie dostÄ™pne miejsce w historii. Kolejne obliczenia bÄ™dÄ… usuwać najstarsze obliczenie z historii. Limit można zwiÄ™kszyć w menu Sesja > Limit rozmiaru historii. Editing calculation. Press Esc twice to cancel. Edycja obliczenia. NaciÅ›nij Esc dwa razy, aby anulować. Calculation Settings Ustawienia obliczenia Invalid recalculation start index NieprawidÅ‚owy indeks poczÄ…tkowy ponownego obliczania System Default DomyÅ›lnie Language JÄ™zyk Select the language: Wybierz jÄ™zyk: Custom WÅ‚asne Decimal places: Miejsca dziesiÄ™tne: &Automatic &Automatyczne &Precision &DokÅ‚adność Plain &text ZwykÅ‚y &tekst Formula &Book Zbiór &formuÅ‚ &Export &Eksportuj Export session as HTML Eksportuj sesjÄ™ jako HTML HTML file (*.html) Plik HTML (*.html) Export session as plain text Eksportuj sesjÄ™ jako zwykÅ‚y tekst ManualWindow SpeedCrunch Manual Instrukcja SpeedCrunch %1 - SpeedCrunch Manual %1 - Instrukcja SpeedCrunch NumberFormatDialog Number Format Format liczb <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Wybierz format liczb dla wyników i grupowania cyfr na wejÅ›ciu.</b><br/><br/>Uwaga: jednoznaczne formaty wprowadzanych liczb sÄ… akceptowane nawet wtedy, gdy różniÄ… siÄ™ od wybranego formatu wyÅ›wietlania.<br/> QObject Global User Variable Globalna zmienna użytkownika Global User Function Globalna funkcja użytkownika Global User Unit Globalna jednostka użytkownika Backspace Backspace Clear expression Wyczyść wyrażenie Evaluate expression Oblicz wyrażenie Insert text Wstaw tekst Automatic decimal Automatyczna dziesiÄ™tna Fixed-point decimal DziesiÄ™tna staÅ‚oprzecinkowa Engineering decimal DziesiÄ™tna inżynierska Scientific decimal DziesiÄ™tna naukowa Rational Wymierna Binary Dwójkowa Octal Ósemkowa Hexadecimal Szesnastkowa Sexagesimal SześćdziesiÄ…tkowa Update Available DostÄ™pna aktualizacja A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> DostÄ™pna jest nowsza wersja (%1).<br/><a href="%2">Odwiedź stronÄ™, aby jÄ… pobrać.</a> Check for Updates Sprawdź aktualizacje SpeedCrunch %1 is up to date. SpeedCrunch %1 jest aktualny. No connectivity. Please check your internet connection and try again. Brak połączenia. Sprawdź połączenie z internetem i spróbuj ponownie. Could not verify the latest available version. Nie można zweryfikować najnowszej dostÄ™pnej wersji. ResultDisplay Scroll to bottom PrzewiÅ„ na dół Edit Expression Edytuj wyrażenie Change Settings ZmieÅ„ ustawienia New Tab Nowa karta &Import... &Importuj... &Export &Eksportuj Plain &text ZwykÅ‚y &tekst Copy Kopiuj Selection Zaznaczenie Select All Zaznacz wszystko Expression Wyrażenie Result Wynik Calculation Obliczenie Calculation as Single Line Obliczenie w jednym wierszu Remove UsuÅ„ This Calculation To obliczenie All Calculations Above Wszystkie obliczenia powyżej All Calculations Below Wszystkie obliczenia poniżej New Private Tab Nowa karta prywatna Session Sesja Open... Otwórz... Clone... Klonuj... Rename... ZmieÅ„ nazwÄ™... Keep Zachowaj Make Private... Ustaw jako prywatnÄ…... Clear Wyczyść Delete UsuÅ„ Close Zamknij Split Podziel Left W lewo Right W prawo Up W górÄ™ Down W dół Close Pane Zamknij panel Main Menu Menu główne Cancel editing Anuluj edycjÄ™ Copy result Kopiuj wynik Edit expression Edytuj wyrażenie Change settings ZmieÅ„ ustawienia Remove calculation UsuÅ„ obliczenie ResultSlotsDialog Notation & Precision Notacja i precyzja Result Line Wiersz wyniku Enabled Włączone Notation Notacja Decimal Places Miejsca dziesiÄ™tne Main Line Wiersz główny Extra Line #1 Dodatkowy wiersz nr 1 Extra Line #2 Dodatkowy wiersz nr 2 Extra Line #3 Dodatkowy wiersz nr 3 Extra Line #4 Dodatkowy wiersz nr 4 Auto Automatycznie UserFunctionListWidget Name Nazwa Value Wartość Description Opis Search Wyszukiwanie No match found Brak dopasowaÅ„ Insert Wstaw Edit Edytuj Delete UsuÅ„ Delete All UsuÅ„ wszystko UserUnitListWidget Name Nazwa Value Wartość Description Opis Search Wyszukiwanie No match found Brak dopasowaÅ„ Insert Wstaw Edit Edytuj Delete UsuÅ„ Delete All UsuÅ„ wszystko VariableListWidget Name Nazwa Value Wartość Description Opis Search Wyszukiwanie No match found Brak dopasowaÅ„ Insert Wstaw Edit Edytuj Delete UsuÅ„ Delete All UsuÅ„ wszystko heldercorreia-speedcrunch-e7ca37f/src/resources/locale/pt_BR.ts000066400000000000000000010560341526573132500247640ustar00rootroot00000000000000 AboutBox About SpeedCrunch Sobre o SpeedCrunch Core developers Desenvolvedores centrais Original author Autor original Close Fechar Math engine Motor matemático Main author | Logo | Maintainer Autor principal | Logo | Mantenedor Thanks Agradecimentos Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Desenvolvedores do SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este programa é software livre; você pode redistribuí-lo e/ou modificá-lo sob os termos da Licença Pública Geral GNU, conforme publicada pela Free Software Foundation; a versão 2 da Licença ou, a seu critério, qualquer versão posterior This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa é distribuído na expectativa de que seja útil, mas SEM NENHUMA GARANTIA; sem mesmo a garantia implícita de COMERCIABILIDADE ou ADEQUAÇÃO A UM PROPÓSITO ESPECÃ�FICO. Consulte a Licença Pública Geral GNU para obter mais detalhes. BitFieldWidget Reset bits to zero Redefinir bits para zero Invert bits Inverter bits Shift bits left Deslocar bits para a esquerda Shift bits right Deslocar bits para a direita Book Index Ã�ndice Algebra Ã�lgebra Quadratic Equation Equação do Segundo Grau Logarithmic Base Conversion Conversão de Base Logarítmica Geometry Geometria Circle Círculo Sector Setor Sphere Esfera Cube Cubo Cone Cone Cylinder Cilindro Electronics Eletrônica Ohm's Law Lei de Ohm Power Potência Reactance Reatância Resonance Ressonância Radio Frequency Rádio Frequência Antennas Antenas Characteristic Impedance (coax) Impedância Característica (coax) Velocity of Propagation (coax) Velocidade de Propagação (coax) Standing Wave Ratio & Return Loss Relação de Ondas Estacionárias e Perda de Retorno Free Space Wavelength Comprimento de Onda no Vácuo resistance resistência voltage tensão current corrente power potência inductive reactance reatância indutiva capacitive reactance reatância capacitiva inductance indutância capacitance capacitância frequency frequência resonance frequency frequência de ressonância area área perimeter perímetro diameter diâmetro radius raio volume volume surface area área de superfície height altura slant height altura inclinada face diagonal face diagonal interna space diagonal diagonal interna edge length comprimento da aresta arc length comprimento do arco central angle (degrees) ângulo central (graus) input power potência de entrada reflected power potência refletida transmitted power potência transmitida return loss perda no retorno dielectric constant constante dielétrica outer conductor's inner diameter diâmetro interior do condutor externo inner conductor's outer diameter diâmetro exterior do condutor interno speed of light velocidade da luz reflection coefficient coeficiente de reflexão standing wave ratio relação de onda estacionária normalized impedance impedância normalizada frequency (Hz) frequência (Hz) BookDock Formula Book Livro de Fórmulas ConstantCompletion Search constants Pesquisar constantes No match found Nenhum resultado encontrado Constants Mathematics Matemática Physics (CODATA 2022) Física (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Química (IUPAC - CIAAW 2021) Uncategorized Sem categoria Universal Constantes universais Physicochemical Físico-química Atomic & Nuclear — General Atômica e nuclear — Geral Atomic & Nuclear — Electroweak Atômica e nuclear — Eletrofraca Atomic & Nuclear — Electron Atômica e nuclear — Elétron Atomic & Nuclear — Muon Atômica e nuclear — Múon Atomic & Nuclear — Tau Atômica e nuclear — Tau Atomic & Nuclear — Proton Atômica e nuclear — Próton Atomic & Nuclear — Neutron Atômica e nuclear — Nêutron Atomic & Nuclear — Deuteron Atômica e nuclear — Dêuteron Atomic & Nuclear — Triton Atômica e nuclear — Tríton Atomic & Nuclear — Helion Atômica e nuclear — Hélion Atomic & Nuclear — Alpha particle Atômica e nuclear — Partícula alfa Atomic & Nuclear — Atomic units Atômica e nuclear — Unidades atômicas Atomic & Nuclear — Energy conversion relationships Atômica e nuclear — Relações de conversão de energia Atomic & Nuclear — X-ray units Atômica e nuclear — Unidades de raios X Atomic & Nuclear — Magnetic shielding corrections Atômica e nuclear — Correções de blindagem magnética Masses Massas Lifetimes Tempos de vida Molar Masses Massas molares Electronegativity Eletronegatividade Ionization Energy Energia de ionização Nominal Constants (IAU 2015) Constantes nominais (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Melhores estimativas atuais (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) impedância característica do vácuo (Zâ‚€) reduced Planck constant (â„�) constante de Planck reduzida (â„�) vacuum electric permittivity (ϵ₀) permitividade elétrica do vácuo (ϵ₀) Newtonian constant of gravitation (G) constante newtoniana da gravitação (G) vacuum magnetic permeability (μ₀) permeabilidade magnética do vácuo (μ₀) Planck constant (h) constante de Planck (h) speed of light in vacuum (c) velocidade da luz no vácuo (c) standard acceleration of gravity (gâ‚™) aceleração normal da gravidade (gâ‚™) Newtonian constant of gravitation over h-bar c constante newtoniana da gravitação sobre h-bar c Planck length comprimento de Planck Planck constant in eV/Hz (h) constante de Planck em eV/Hz (h) Planck mass massa de Planck Planck mass energy equivalent in GeV equivalente energético da massa de Planck em GeV Planck temperature temperatura de Planck Planck time tempo de Planck reduced Planck constant in eV·s (â„�) constante de Planck reduzida em eV·s (â„�) reduced Planck constant times c in MeV·fm constante de Planck reduzida vezes c em MeV·fm Bohr magneton magneton de Bohr conductance quantum (Gâ‚€) quantum de condutância (Gâ‚€) Coulomb constant (kâ‚‘) constante de Coulomb (kâ‚‘) elementary charge (e) carga elementar (e) elementary charge over h-bar carga elementar sobre h-bar conventional value of Josephson constant valor convencional da constante de Josephson Josephson constant constante de Josephson conventional value of ampere-90 valor convencional do ampere-90 conventional value of coulomb-90 valor convencional do coulomb-90 conventional value of farad-90 valor convencional do farad-90 conventional value of henry-90 valor convencional do henry-90 conventional value of ohm-90 valor convencional do ohm-90 conventional value of volt-90 valor convencional do volt-90 conventional value of watt-90 valor convencional do watt-90 magnetic flux quantum (Φ₀) quantum de fluxo magnético (Φ₀) nuclear magneton magneton nuclear inverse of conductance quantum inverso do quantum de condutância conventional value of von Klitzing constant valor convencional da constante de von Klitzing von Klitzing constant constante de von Klitzing atomic unit of magnetic dipole moment unidade atômica de momento dipolar magnético atomic unit of magnetic flux density unidade atômica de densidade de fluxo magnético Bohr magneton in eV/T magneton de Bohr em eV/T Bohr magneton in Hz/T magneton de Bohr em Hz/T Bohr magneton in inverse meter per tesla magneton de Bohr em metro inverso por tesla Bohr magneton in K/T magneton de Bohr em K/T nuclear magneton in eV/T magneton nuclear em eV/T nuclear magneton in inverse meter per tesla magneton nuclear em metro inverso por tesla nuclear magneton in K/T magneton nuclear em K/T nuclear magneton in MHz/T magneton nuclear em MHz/T Bohr radius (aâ‚€) raio de Bohr (aâ‚€) fine-structure constant (α) constante de estrutura fina (α) Hartree energy (Eâ‚•) energia de Hartree (Eâ‚•) Hartree energy in eV energia de Hartree em eV quantum of circulation quantum de circulação quantum of circulation times 2 quantum de circulação vezes 2 Rydberg constant (R∞) constante de Rydberg (R∞) atomic mass unit-hartree relationship relação unidade de massa atômica-hartree atomic mass unit-hertz relationship relação unidade de massa atômica-hertz atomic mass unit-inverse meter relationship relação unidade de massa atômica-metro inverso atomic mass unit-joule relationship relação unidade de massa atômica-joule atomic mass unit-kelvin relationship relação unidade de massa atômica-kelvin atomic mass unit-kilogram relationship relação unidade de massa atômica-quilograma atomic unit of 1st hyperpolarizability unidade atômica de 1.ª hiperpolarizabilidade atomic unit of 2nd hyperpolarizability unidade atômica de 2.ª hiperpolarizabilidade atomic unit of charge (e) unidade atômica de carga (e) atomic unit of charge density unidade atômica de densidade de carga atomic unit of current unidade atômica de corrente atomic unit of electric dipole moment unidade atômica de momento dipolar elétrico atomic unit of electric field unidade atômica de campo elétrico atomic unit of electric field gradient unidade atômica de gradiente de campo elétrico atomic unit of electric polarizability unidade atômica de polarizabilidade elétrica atomic unit of electric potential unidade atômica de potencial elétrico atomic unit of electric quadrupole moment unidade atômica de momento quadrupolar elétrico atomic unit of action unidade atômica de ação atomic unit of energy unidade atômica de energia atomic unit of force unidade atômica de força atomic unit of length unidade atômica de comprimento hertz-atomic mass unit relationship relação hertz-unidade de massa atômica hertz-electron volt relationship relação hertz-elétron-volt hertz-hartree relationship relação hertz-hartree hertz-inverse meter relationship relação hertz-metro inverso hertz-joule relationship relação hertz-joule hertz-kelvin relationship relação hertz-kelvin hertz-kilogram relationship relação hertz-quilograma hyperfine transition frequency of Cs-133 frequência de transição hiperfina do Cs-133 inverse fine-structure constant (αâ�»Â¹) constante inversa de estrutura fina (αâ�»Â¹) inverse meter-atomic mass unit relationship relação metro inverso-unidade de massa atômica inverse meter-electron volt relationship relação metro inverso-elétron-volt inverse meter-hartree relationship relação metro inverso-hartree inverse meter-hertz relationship relação metro inverso-hertz inverse meter-joule relationship relação metro inverso-joule inverse meter-kelvin relationship relação metro inverso-kelvin inverse meter-kilogram relationship relação metro inverso-quilograma joule-atomic mass unit relationship relação joule-unidade de massa atômica joule-electron volt relationship relação joule-elétron-volt joule-hertz relationship relação joule-hertz joule-hartree relationship relação joule-hartree joule-inverse meter relationship relação joule-metro inverso joule-kelvin relationship relação joule-kelvin joule-kilogram relationship relação joule-quilograma kelvin-atomic mass unit relationship relação kelvin-unidade de massa atômica kelvin-electron volt relationship relação kelvin-elétron-volt kelvin-hertz relationship relação kelvin-hertz kelvin-hartree relationship relação kelvin-hartree kelvin-inverse meter relationship relação kelvin-metro inverso kelvin-joule relationship relação kelvin-joule kelvin-kilogram relationship relação kelvin-quilograma kilogram-atomic mass unit relationship relação quilograma-unidade de massa atômica kilogram-electron volt relationship relação quilograma-elétron-volt kilogram-hertz relationship relação quilograma-hertz kilogram-hartree relationship relação quilograma-hartree kilogram-inverse meter relationship relação quilograma-metro inverso kilogram-joule relationship relação quilograma-joule kilogram-kelvin relationship relação quilograma-kelvin lattice parameter of silicon (a) parâmetro de rede do silício (a) luminous efficacy eficácia luminosa natural unit of energy unidade natural de energia natural unit of energy in MeV unidade natural de energia em MeV natural unit of action (â„�) unidade natural de ação (â„�) natural unit of action in eV·s unidade natural de ação em eV·s natural unit of length unidade natural de comprimento natural unit of mass unidade natural de massa natural unit of momentum unidade natural de momento natural unit of momentum in MeV/c unidade natural de momento em MeV/c natural unit of time unidade natural de tempo natural unit of velocity unidade natural de velocidade Rydberg constant times c in Hz constante de Rydberg vezes c em Hz Rydberg constant times hc in eV constante de Rydberg vezes hc em eV Rydberg constant times hc in J constante de Rydberg vezes hc em J Fermi coupling constant constante de acoplamento de Fermi weak mixing angle ângulo de mistura fraca W to Z mass ratio razão entre as massas W e Z Thomson cross section (σₑ) secção eficaz de Thomson (σₑ) electron mass (mâ‚‘) massa do elétron (mâ‚‘) electron mass in u massa do elétron em u electron mass energy equivalent (mₑ·c²) equivalente energético da massa do elétron (mₑ·c²) electron mass energy equivalent in MeV equivalente energético da massa do elétron em MeV reduced Compton wavelength comprimento de onda de Compton reduzido classical electron radius (râ‚‘) raio clássico do elétron (râ‚‘) electron charge to mass quotient quociente carga-massa do elétron electron-deuteron magnetic moment ratio razão dos momentos magnéticos elétron-dêuteron electron-deuteron mass ratio razão das massas elétron-dêuteron electron g factor (gâ‚‘) fator g do elétron (gâ‚‘) electron gyromagnetic ratio (γₑ) razão giromagnética do elétron (γₑ) electron gyromagnetic ratio in MHz/T razão giromagnética do elétron em MHz/T electron-helion mass ratio razão das massas elétron-hélion electron magnetic moment (μₑ) momento magnético do elétron (μₑ) electron magnetic moment anomaly (aâ‚‘) anomalia do momento magnético do elétron (aâ‚‘) electron magnetic moment to Bohr magneton ratio razão entre o momento magnético do elétron e o magneton de Bohr electron magnetic moment to nuclear magneton ratio razão entre o momento magnético do elétron e o magneton nuclear electron molar mass (Mâ‚‘) massa molar do elétron (Mâ‚‘) electron-muon magnetic moment ratio razão dos momentos magnéticos elétron-múon electron-muon mass ratio razão das massas elétron-múon electron-neutron magnetic moment ratio razão dos momentos magnéticos elétron-nêutron electron-neutron mass ratio razão das massas elétron-nêutron electron-proton magnetic moment ratio razão dos momentos magnéticos elétron-próton electron-proton mass ratio razão das massas elétron-próton electron relative atomic mass (Ar(e)) massa atômica relativa do elétron (Ar(e)) electron-tau mass ratio razão das massas elétron-tau electron to alpha particle mass ratio razão entre as massas do elétron e da partícula alfa electron to shielded helion magnetic moment ratio razão entre os momentos magnéticos do elétron e do hélion blindado electron to shielded proton magnetic moment ratio razão entre os momentos magnéticos do elétron e do próton blindado electron-triton mass ratio razão das massas elétron-tríton electron volt-atomic mass unit relationship relação elétron-volt-unidade de massa atômica electron volt-hartree relationship relação elétron-volt-hartree electron volt-hertz relationship relação elétron-volt-hertz electron volt-inverse meter relationship relação elétron-volt-metro inverso electron volt-joule relationship relação elétron-volt-joule electron volt-kelvin relationship relação elétron-volt-kelvin electron volt-kilogram relationship relação elétron-volt-quilograma hartree-atomic mass unit relationship relação hartree-unidade de massa atômica hartree-electron volt relationship relação hartree-elétron-volt muon Compton wavelength comprimento de onda de Compton do múon muon-electron mass ratio razão das massas múon-elétron muon g factor fator g do múon muon magnetic moment momento magnético do múon muon magnetic moment anomaly anomalia do momento magnético do múon muon magnetic moment to Bohr magneton ratio razão entre o momento magnético do múon e o magneton de Bohr muon magnetic moment to nuclear magneton ratio razão entre o momento magnético do múon e o magneton nuclear muon mass massa do múon muon mass energy equivalent equivalente energético da massa do múon muon mass energy equivalent in MeV equivalente energético da massa do múon em MeV muon mass in u massa do múon em u muon molar mass massa molar do múon muon-neutron mass ratio razão das massas múon-nêutron muon-proton magnetic moment ratio razão dos momentos magnéticos múon-próton muon-proton mass ratio razão das massas múon-próton muon-tau mass ratio razão das massas múon-tau reduced muon Compton wavelength comprimento de onda de Compton reduzido do múon reduced tau Compton wavelength comprimento de onda de Compton reduzido do tau tau Compton wavelength comprimento de onda de Compton do tau tau-electron mass ratio razão das massas tau-elétron tau mass massa do tau tau mass energy equivalent equivalente energético da massa do tau tau mass in u massa do tau em u tau molar mass massa molar do tau tau-muon mass ratio razão das massas tau-múon tau-neutron mass ratio razão das massas tau-nêutron tau-proton mass ratio razão das massas tau-próton proton charge to mass quotient quociente carga-massa do próton proton Compton wavelength comprimento de onda de Compton do próton proton-electron mass ratio razão das massas próton-elétron proton g factor (gₚ) fator g do próton (gₚ) proton gyromagnetic ratio (γₚ) razão giromagnética do próton (γₚ) proton gyromagnetic ratio in MHz/T razão giromagnética do próton em MHz/T proton magnetic moment (μₚ) momento magnético do próton (μₚ) proton magnetic moment to Bohr magneton ratio razão entre o momento magnético do próton e o magneton de Bohr proton magnetic moment to nuclear magneton ratio razão entre o momento magnético do próton e o magneton nuclear proton magnetic shielding correction correção de blindagem magnética do próton proton mass (mₚ) massa do próton (mₚ) proton mass energy equivalent equivalente energético da massa do próton proton mass energy equivalent in MeV equivalente energético da massa do próton em MeV proton mass in u massa do próton em u proton molar mass (Mₚ) massa molar do próton (Mₚ) proton-muon mass ratio razão das massas próton-múon proton-neutron magnetic moment ratio razão dos momentos magnéticos próton-nêutron proton-neutron mass ratio razão das massas próton-nêutron proton relative atomic mass (Ar(p)) massa atômica relativa do próton (Ar(p)) proton rms charge radius raio de carga rms do próton proton-tau mass ratio razão das massas próton-tau reduced proton Compton wavelength comprimento de onda de Compton reduzido do próton shielded proton gyromagnetic ratio razão giromagnética do próton blindado shielded proton gyromagnetic ratio in MHz/T razão giromagnética do próton blindado em MHz/T shielded proton magnetic moment momento magnético do próton blindado shielded proton magnetic moment to Bohr magneton ratio razão entre o momento magnético do próton blindado e o magneton de Bohr shielded proton magnetic moment to nuclear magneton ratio razão entre o momento magnético do próton blindado e o magneton nuclear neutron Compton wavelength comprimento de onda de Compton do nêutron neutron-electron magnetic moment ratio razão dos momentos magnéticos nêutron-elétron neutron-electron mass ratio razão das massas nêutron-elétron neutron g factor (gâ‚™) fator g do nêutron (gâ‚™) neutron gyromagnetic ratio (γₙ) razão giromagnética do nêutron (γₙ) neutron gyromagnetic ratio in MHz/T razão giromagnética do nêutron em MHz/T neutron magnetic moment (μₙ) momento magnético do nêutron (μₙ) neutron magnetic moment to Bohr magneton ratio razão entre o momento magnético do nêutron e o magneton de Bohr neutron magnetic moment to nuclear magneton ratio razão entre o momento magnético do nêutron e o magneton nuclear neutron mass (mâ‚™) massa do nêutron (mâ‚™) neutron mass energy equivalent equivalente energético da massa do nêutron neutron mass energy equivalent in MeV equivalente energético da massa do nêutron em MeV neutron mass in u massa do nêutron em u neutron molar mass (Mâ‚™) massa molar do nêutron (Mâ‚™) neutron-muon mass ratio razão das massas nêutron-múon neutron-proton magnetic moment ratio razão dos momentos magnéticos nêutron-próton neutron-proton mass difference diferença de massas nêutron-próton neutron-proton mass difference energy equivalent equivalente energético da diferença de massas nêutron-próton neutron-proton mass difference energy equivalent in MeV equivalente energético da diferença de massas nêutron-próton em MeV neutron-proton mass difference in u diferença de massas nêutron-próton em u neutron-proton mass ratio razão das massas nêutron-próton neutron relative atomic mass (Ar(n)) massa atômica relativa do nêutron (Ar(n)) neutron-tau mass ratio razão das massas nêutron-tau neutron to shielded proton magnetic moment ratio razão entre os momentos magnéticos do nêutron e do próton blindado reduced neutron Compton wavelength comprimento de onda de Compton reduzido do nêutron deuteron-electron magnetic moment ratio razão dos momentos magnéticos dêuteron-elétron deuteron-electron mass ratio razão das massas dêuteron-elétron deuteron g factor fator g do dêuteron deuteron magnetic moment momento magnético do dêuteron deuteron magnetic moment to Bohr magneton ratio razão entre o momento magnético do dêuteron e o magneton de Bohr deuteron magnetic moment to nuclear magneton ratio razão entre o momento magnético do dêuteron e o magneton nuclear deuteron mass massa do dêuteron deuteron mass energy equivalent equivalente energético da massa do dêuteron deuteron mass energy equivalent in MeV equivalente energético da massa do dêuteron em MeV deuteron mass in u massa do dêuteron em u deuteron molar mass massa molar do dêuteron deuteron-neutron magnetic moment ratio razão dos momentos magnéticos dêuteron-nêutron deuteron-proton magnetic moment ratio razão dos momentos magnéticos dêuteron-próton deuteron-proton mass ratio razão das massas dêuteron-próton deuteron relative atomic mass (Ar(d)) massa atômica relativa do dêuteron (Ar(d)) deuteron rms charge radius raio de carga rms do dêuteron triton-electron mass ratio razão das massas tríton-elétron triton g factor (gₜ) fator g do tríton (gₜ) triton magnetic moment (μₜ) momento magnético do tríton (μₜ) triton magnetic moment to Bohr magneton ratio razão entre o momento magnético do tríton e o magneton de Bohr triton magnetic moment to nuclear magneton ratio razão entre o momento magnético do tríton e o magneton nuclear triton mass (mₜ) massa do tríton (mₜ) triton mass energy equivalent equivalente energético da massa do tríton triton mass energy equivalent in MeV equivalente energético da massa do tríton em MeV triton mass in u massa do tríton em u triton molar mass (Mₜ) massa molar do tríton (Mₜ) triton-proton mass ratio razão das massas tríton-próton triton relative atomic mass (Ar(t)) massa atômica relativa do tríton (Ar(t)) triton to proton magnetic moment ratio razão entre os momentos magnéticos do tríton e do próton helion-electron mass ratio razão das massas hélion-elétron helion g factor (gâ‚•) fator g do hélion (gâ‚•) helion magnetic moment (μₕ) momento magnético do hélion (μₕ) helion magnetic moment to Bohr magneton ratio razão entre o momento magnético do hélion e o magneton de Bohr helion magnetic moment to nuclear magneton ratio razão entre o momento magnético do hélion e o magneton nuclear helion mass (mâ‚•) massa do hélion (mâ‚•) helion mass energy equivalent equivalente energético da massa do hélion helion mass energy equivalent in MeV equivalente energético da massa do hélion em MeV helion mass in u massa do hélion em u helion molar mass (Mâ‚•) massa molar do hélion (Mâ‚•) helion-proton mass ratio razão das massas hélion-próton helion relative atomic mass (Ar(h)) massa atômica relativa do hélion (Ar(h)) helion shielding shift deslocamento de blindagem do hélion shielded helion gyromagnetic ratio razão giromagnética do hélion blindado shielded helion gyromagnetic ratio in MHz/T razão giromagnética do hélion blindado em MHz/T shielded helion magnetic moment momento magnético do hélion blindado shielded helion magnetic moment to Bohr magneton ratio razão entre o momento magnético do hélion blindado e o magneton de Bohr shielded helion magnetic moment to nuclear magneton ratio razão entre o momento magnético do hélion blindado e o magneton nuclear shielded helion to proton magnetic moment ratio razão entre os momentos magnéticos do hélion blindado e do próton shielded helion to shielded proton magnetic moment ratio razão entre os momentos magnéticos do hélion blindado e do próton blindado alpha particle mass massa da partícula alfa alpha particle mass in u massa da partícula alfa em u alpha particle mass energy equivalent equivalente energético da massa da partícula alfa alpha particle mass energy equivalent in MeV equivalente energético da massa da partícula alfa em MeV alpha particle-electron mass ratio razão das massas partícula alfa-elétron alpha particle-proton mass ratio razão das massas partícula alfa-próton alpha particle rms charge radius raio de carga rms da partícula alfa alpha particle molar mass massa molar da partícula alfa alpha particle relative atomic mass (Ar(α)) massa atômica relativa da partícula alfa (Ar(α)) atomic mass constant (mᵤ) constante de massa atômica (mᵤ) Avogadro constant constante de Avogadro Boltzmann constant (k) constante de Boltzmann (k) Boltzmann constant in eV/K constante de Boltzmann em eV/K Boltzmann constant in Hz/K constante de Boltzmann em Hz/K Boltzmann constant in inverse meter per kelvin constante de Boltzmann em metro inverso por kelvin electron volt (eV) elétron-volt (eV) Faraday constant (F) constante de Faraday (F) first radiation constant (câ‚�) primeira constante de radiação (câ‚�) first radiation constant for spectral radiance primeira constante de radiação para radiância espectral molar gas constant (R) constante molar dos gases (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) constante de Loschmidt (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) constante de Loschmidt (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant constante de Planck molar second radiation constant (câ‚‚) segunda constante de radiação (câ‚‚) Stefan-Boltzmann constant (σ) constante de Stefan-Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) espaçamento de rede do Si ideal (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent equivalente energético da constante de massa atômica atomic mass constant energy equivalent in MeV equivalente energético da constante de massa atômica em MeV atomic mass unit-electron volt relationship relação unidade de massa atômica-elétron-volt molar mass constant (Mᵤ) constante de massa molar (Mᵤ) molar mass of carbon-12 massa molar do carbono-12 molar volume of ideal gas (273.15 K, 100 kPa) volume molar de gás ideal (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volume molar de gás ideal (273.15 K, 101.325 kPa) molar volume of silicon volume molar do silício Sackur-Tetrode constant (1 K, 100 kPa) constante de Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) constante de Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant constante da lei do deslocamento de frequência de Wien Wien wavelength displacement law constant constante da lei do deslocamento de comprimento de onda de Wien standard atmosphere (atm) atmosfera normal (atm) standard-state pressure (p°) pressão de estado padrão (p°) Angstrom star (Ã…*) Ã¥ngström estrela (Ã…*) Copper x unit unidade x do cobre Molybdenum x unit unidade x do molibdénio atomic unit of magnetizability unidade atômica de magnetizabilidade atomic unit of mass (mâ‚‘) unidade atômica de massa (mâ‚‘) atomic unit of momentum unidade atômica de momento atomic unit of permittivity unidade atômica de permitividade atomic unit of time unidade atômica de tempo atomic unit of velocity unidade atômica de velocidade hartree-hertz relationship relação hartree-hertz hartree-inverse meter relationship relação hartree-metro inverso hartree-joule relationship relação hartree-joule hartree-kelvin relationship relação hartree-kelvin hartree-kilogram relationship relação hartree-quilograma shielding difference of d and p in HD diferença de blindagem de d e p em HD shielding difference of t and p in HT diferença de blindagem de t e p em HT pi (Ï€) pi (Ï€) Euler's number (e) número de Euler (e) golden ratio (φ) razão áurea (φ) Euler-Mascheroni constant (γ) constante de Euler-Mascheroni (γ) nominal solar radius raio solar nominal nominal solar total irradiance irradiância solar total nominal nominal solar luminosity luminosidade solar nominal nominal solar effective temperature temperatura efetiva solar nominal nominal solar mass parameter parâmetro de massa solar nominal nominal terrestrial equatorial radius raio equatorial terrestre nominal nominal terrestrial polar radius raio polar terrestre nominal nominal terrestrial mass parameter parâmetro de massa terrestre nominal nominal jovian equatorial radius raio equatorial joviano nominal nominal jovian polar radius raio polar joviano nominal nominal jovian mass parameter parâmetro de massa joviano nominal average value of one minus the rate of TCG relative to TCB valor médio de um menos a taxa de TCG relativamente a TCB solar mass parameter (TCB-compatible) parâmetro de massa solar (compatível com TCB) solar mass parameter (TDB-compatible) parâmetro de massa solar (compatível com TDB) equatorial radius of the Earth (TT-compatible) raio equatorial da Terra (compatível com TT) dynamical form factor of the Earth fator de forma dinâmico da Terra time rate of change in the dynamical form factor of the Earth taxa temporal de variação do fator de forma dinâmico da Terra geocentric gravitational constant (TCB-compatible) constante gravitacional geocêntrica (compatível com TCB) geocentric gravitational constant (TT-compatible) constante gravitacional geocêntrica (compatível com TT) geocentric gravitational constant (TDB-compatible) constante gravitacional geocêntrica (compatível com TDB) potential of the geoid potencial do geoide nominal mean angular velocity of the Earth (TT-compatible) velocidade angular média nominal da Terra (compatível com TT) ratio mass of the Moon to the Earth razão entre a massa da Lua e a da Terra ratio of the mass of the Sun to Mercury razão entre a massa do Sol e a de Mercúrio ratio of the mass of the Sun to Venus razão entre a massa do Sol e a de Vénus ratio of the mass of the Sun to Mars razão entre a massa do Sol e a de Marte ratio of the mass of the Sun to Jupiter razão entre a massa do Sol e a de Júpiter ratio of the mass of the Sun to Saturn razão entre a massa do Sol e a de Saturno ratio of the mass of the Sun to Uranus razão entre a massa do Sol e a de Urano ratio of the mass of the Sun to Neptune razão entre a massa do Sol e a de Neptuno ratio of the mass of the Sun to (134340) Pluto razão entre a massa do Sol e a de (134340) Plutão ratio of the mass of the Sun to (136199) Eris razão entre a massa do Sol e a de (136199) Éris ratio of the mass of (1) Ceres to the Sun razão entre a massa de (1) Ceres e a do Sol ratio of the mass of (2) Pallas to the Sun razão entre a massa de (2) Pallas e a do Sol ratio of the mass of (4) Vesta to the Sun razão entre a massa de (4) Vesta e a do Sol mean obliquity of the ecliptic at J2000.0 obliquidade média da eclíptica em J2000.0 Electromagnetic Eletromagnético Compton wavelength Comprimento de onda Compton Astronomy Astronomia ConstantsWidget Domain Domínio Subdomain Subdomínio No match found Nenhum resultado encontrado Name Nome Value Valor Unit Unidade Search Pesquisar All Todas CustomKeypadDialog Custom Keypad Teclado numérico personalizado Rows: Linhas: Columns: Colunas: Copy preset: Copiar predefinição: Basic Básico Scientific (wide) Científico (largo) Scientific (narrow) Científica (estreita) Apply Aplicar Row Linha Column Coluna Label Etiqueta Behavior Comportamento Text Texto DiagnosticsDialog App Diagnostics Diagnóstico do aplicativo Copy to Clipboard Copiar para a área de transferência Editor Unit Unidade User unit Unidade do usuário User function Função do usuário Argument Argumento Current result:<br/>%1 Resultado atual:<br/>%1 Selection result:<br/>%1 Resultado da seleção:<br/>%1 Selection result: n/a Resultado da seleção: indisponível Selection result: %1 Resultado da seleção: %1 second segundo metre metro kilogram quilograma mole mol radian radiano steradian esterradiano degree Celsius grau Celsius cubic metre metro cúbico cubic millimetre milímetro cúbico cubic centimetre centímetro cúbico cubic decimetre decímetro cúbico cubic kilometre quilômetro cúbico square millimetre milímetro quadrado square kilometre quilômetro quadrado square metre metro quadrado minute minuto hour hora day dia astronomical unit unidade astronômica degree grau arcminute minuto de arco arcsecond segundo de arco milliarcsecond milissegundo de arco microarcsecond microssegundo de arco hectare hectare litre litro tonne tonelada Dalton dalton electronvolt elétron-volt Angstrom Ã¥ngström atmosphere atmosfera atomic mass unit unidade de massa atômica British thermal unit unidade térmica britânica calorie caloria carat quilate cup xícara cup (Imperial) xícara (imperial) cup (Japanese) xícara (japonesa) cup (US) xícara (EUA) degree Fahrenheit grau Fahrenheit fathom braça fluid ounce (Imperial) onça fluida (imperial) fluid ounce (US) onça fluida (EUA) fluid dram (Imperial) dracma fluida (imperial) fluid dram (US) dracma fluida (EUA) foot pé square foot pé quadrado cubic foot pé cúbico gallon (Imperial) galão (imperial) gallon (US) galão (EUA) gill (Imperial) gill (imperial) gill (US) gill (EUA) gradian grado grain grão gram grama Hartley hartley Hartree energy unit unidade de energia Hartree horsepower cavalo-vapor inch polegada square inch polegada quadrada cubic inch polegada cúbica karat quilate knot nó lightminute minuto-luz lightsecond segundo-luz lightyear ano-luz long ton tonelada longa mile milha square mile milha quadrada cubic mile milha cúbica mile per hour milha por hora kilometre per hour quilômetro por hora nautical mile milha náutica ounce onça parsec parsec pint (Imperial) pinta (imperial) pint (US) pinta (EUA) pound libra pounds per square inch libras por polegada quadrada quart (Imperial) quarto (imperial) quart (US) quarto (EUA) oil barrel barril de petróleo beer barrel (US) barril de cerveja (EUA) square yard jarda quadrada cubic yard jarda cúbica short ton tonelada curta tablespoon colher de sopa tablespoon (Australian) colher de sopa (australiana) tablespoon (Imperial) colher de sopa (imperial) tablespoon (US) colher de sopa (EUA) dessert spoon colher de sobremesa teaspoon colher de chá teaspoon (Imperial) colher de chá (imperial) teaspoon (US) colher de chá (EUA) turn volta revolution revolução revolution per minute revolução por minuto week semana kilowatt hour quilowatt-hora millimetre of mercury milímetro de mercúrio yard jarda Julian century século juliano Julian year ano juliano sidereal year ano sideral tropical year ano tropical Evaluator invalid expression expressão inválida division by zero divisão por zero too time consuming - computation was rejected demorado demais - o cálculo foi rejeitado dimension mismatch - quantities with different dimensions cannot be compared, added, etc. incompatibilidade de dimensão - quantidades com diferentes dimensões não podem ser comparadas, somadas, etc. invalid dimension - operation might require dimensionless arguments dimensão inválida - a operação pode exigir argumentos adimensionais Computation aborted - encountered numerical instability Cálculo interrompido - foi detectada instabilidade numérica invalid dimension - function might require dimensionless arguments dimensão inválida - a função pode exigir argumentos adimensionais error Erro unit must not be zero A unidade não pode ser zero Conversion failed - dimension mismatch Falha na conversão - incompatibilidade de dimensões unknown function or variable função ou variável desconhecida recursion not supported recursividade não suportada cannot operate on a NaN não pode operar com um NaN underflow - tiny result is out of SpeedCrunch's number range underflow - resultado muito pequeno está fora do intervalo numérico do SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflow - resultado muito grande está fora do intervalo numérico do SpeedCrunch overflow - logic result exceeds maximum of 256 bits overflow - resultado lógico excede o máximo de 256 bits overflow - integer result exceeds maximum limit for integers overflow - resultado inteiro excede o limite máximo de inteiros operation is not defined for these arguments a operação não está definida para estes argumentos wrong number of arguments número de argumentos incorreto does not take NaN as an argument não aceita NaN como argumento result out of range resultado fora do intervalo undefined for argument domain indefinido para domínio do argumento computation too expensive computação muito custosa internal error, please report a bug erro interno, reporte um defeito syntax error erro de sintaxe conversion target must be a unit o destino da conversão tem de ser uma unidade unknown unit unidade desconhecida %1 is a reserved name, please choose another %1 é um nome reservado; escolha outro %1 is a global user definition and cannot be overridden in this session. %1 é uma definição global do usuário e não pode ser substituída nesta sessão. %1 is a variable name, please choose another or delete the variable %1 é um nome de variável; escolha outro ou exclua a variável argument %1 is used more than once argumento %1 é usado mais de uma vez %1 is a built-in unit name, please choose another %1 é o nome de uma unidade integrada; escolha outro %1 is a user function name, please choose another or delete the function %1 é um nome de função do usuário; escolha outro ou exclua a função FunctionRepo max; trials; probability máx; tentativas; probabilidade trials; probability tentativas; probabilidade hits; trials; probability acertos; tentativas; probabilidade max; total; hits; trials máx; total; acertos; tentativas total; hits; trials total; acertos; tentativas count; total; hits; trials contagem; total; acertos; tentativas dividend; divisor dividendo; divisor x; exponent_bits; significand_bits [; exponent_bias] x; bits_do_expoente; bits_do_significando [; adição_ao_expoente] base; x base; x value; modulo valor; módulo base; exponent; modulo base; expoente; módulo events; average_events eventos; média_eventos average_events média_eventos x [; precision] x [; precisão] Absolute Value Valor absoluto Absolute Deviation Desvio absoluto Arc Cosine Arco cosseno Logical AND E lógico Area Hyperbolic Cosine Cosseno hiperbólico inverso Area Hyperbolic Sine Seno hiperbólico inverso Area Hyperbolic Tangent Tangente hiperbólica inversa Arc Sine Arco seno Arc Tangent Arco tangente Arc Tangent with two Arguments Arco tangente com dois argumentos Average (Arithmetic Mean) Média (média aritmética) Binomial Cumulative Distribution Function Função de distribuição acumulada binomial Binomial Distribution Mean Média da distribuição binomial Binomial Probability Mass Function Função massa de probabilidade binomial Binomial Distribution Variance Variância da distribuição binomial Cube Root Raiz cúbica Complex Conjugate Conjugado de um número complexo Cosine Cosseno Hyperbolic Cosine Cosseno hiperbólico Cotangent Cotangente Cosecant Cossecante Convert Unix timestamp to Date Converter timestamp Unix para data Degrees of Arc Graus de arco Error Function Função erro Complementary Error Function Função erro complementar Exponential Exponencial Fractional Part Parte fracionária Extension of Factorials [= (x-1)!] Extensão dos fatoriais [= (x-1)!] Greatest Common Divisor Máximo divisor comum Geometric Mean Média geométrica Gradians of arc Grados de arco Hypergeometric Cumulative Distribution Function Função de distribuição acumulada hipergeométrica Hypergeometric Distribution Mean Média da distribuição hipergeométrica Hypergeometric Probability Mass Function Função massa de probabilidade hipergeométrica Hypergeometric Distribution Variance Variância da distribuição hipergeométrica Integer Quotient Quociente inteiro Integer Part Parte inteira Imaginary Part Parte imaginária Decode IEEE-754 Binary Value Decodificar valor binário IEEE-754 Encode IEEE-754 Binary Value Codificar valor binário IEEE-754 Decode 16-bit Half-Precision Value Decodificar valor de meia precisão de 16 bits Encode 16-bit Half-Precision Value Codificar valor de meia precisão de 16 bits Decode 32-bit Single-Precision Value Decodificar valor de precisão simples de 32 bits Encode 32-bit Single-Precision Value Codificar valor de precisão simples de 32 bits Decode 64-bit Double-Precision Value Decodificar valor de precisão dupla de 64 bits Encode 64-bit Double-Precision Value Codificar valor de precisão dupla de 64 bits Decode 128-bit Quad-Precision Value Decodificar valor de precisão quádrupla de 128 bits Encode 128-bit Quad-Precision Value Codificar valor de precisão quádrupla de 128 bits Binary Logarithm Logaritmo binário Common Logarithm Logaritmo comum Natural Logarithm Logaritmo natural Logarithm to Arbitrary Base Logaritmo em base arbitrária Mask to a bit size Mascarar para um tamanho de bit Maximum Máximo Median Value (50th Percentile) Valor mediano (50º percentil) Minimum Mínimo Modulo Módulo Euclidean Modulo Módulo euclidiano Modular Exponentiation Exponenciação modular Combination (Binomial Coefficient) Combinação (coeficiente binomial) Logical NOT NÃO lógico Permutation (Arrangement) Permutação (Arranjo) Convert to Binary Representation Converter para representação binária Arithmetic Aritmética Chemistry Química Complex Complexos Combinatorics Combinatória Probability Probabilidade Statistics Estatística Aggregation Agregação Random Aleatório Base conversion Conversão de base Number formatting Formatação de números Integer arithmetic Aritmética de inteiros Special functions Funções especiais Exponential & Logarithmic Exponenciais e logarítmicas Angle conversion Conversão de ângulos Trigonometry Trigonometria Bitwise Operações bit a bit Floating point Ponto flutuante Date & Time Data e hora Linear algebra Ã�lgebra linear unix_timestamp; x hours offset to GMT unix_timestamp; deslocamento de x horas em relação a GMT yyyymmdd.hhmmss; x hours offset to GMT aaaammdd.hhmmss; deslocamento de x horas em relação a GMT [digits] [dígitos] max [; min] máx [; mín] List Literal Literal de lista Convert to Padded Binary Representation Converter para representação binária preenchida Round Toward +∞ (Ceiling) Arredondar para +∞ (teto) Cosine plus Imaginary Sine Cosseno mais seno imaginário Convert to Cis Complex Form Converter para forma complexa cis Matrix Column Count Número de colunas da matriz Population Correlation Matrix (n) Matriz de correlação populacional (n) Sample Correlation Matrix (n-1) Matriz de correlação amostral (n-1) Count Contagem Population Covariance Matrix (n) Matriz de covariância populacional (n) Sample Covariance Matrix (n-1) Matriz de covariância amostral (n-1) Cross Product Produto vetorial Convert Date to Unix timestamp Converter data para timestamp Unix Convert to Decimal Representation Converter para representação decimal Determinant Determinante Convert to Sexagesimal Notation Converter para notação sexagesimal Dot Product Produto escalar Convert to Engineering Notation Converter para notação de engenharia Convert to Exponential Complex Form Converter para forma complexa exponencial Round Toward −∞ (Floor) Arredondar para −∞ (piso) Flatten Matrix Achatar matriz Least Common Multiple Mínimo múltiplo comum Convert to Hexadecimal Representation Converter para representação hexadecimal Convert to Padded Hexadecimal Representation Converter para representação hexadecimal preenchida Inverse Matrix Matriz inversa Round to 16-bit Half-Precision Value Arredondar para valor de meia precisão de 16 bits Round to 32-bit Single-Precision Value Arredondar para valor de precisão simples de 32 bits Round to 64-bit Double-Precision Value Arredondar para valor de precisão dupla de 64 bits Round to 128-bit Quad-Precision Value Arredondar para valor de precisão quádrupla de 128 bits Residual from 16-bit Half-Precision Rounding Resíduo do arredondamento de meia precisão de 16 bits Residual from 32-bit Single-Precision Rounding Resíduo do arredondamento de precisão simples de 32 bits Residual from 64-bit Double-Precision Rounding Resíduo do arredondamento de precisão dupla de 64 bits Residual from 128-bit Quad-Precision Rounding Resíduo do arredondamento de precisão quádrupla de 128 bits Substance Mass Massa da substância Molarity Molaridade Molar Mass Massa molar Median Absolute Deviation Desvio absoluto mediano Mean Média Numerical Value of Quantity Valor numérico da quantidade Random Decimal Number Número decimal aleatório Random Integer Number Número inteiro aleatório Convert to Rational Representation Converter para representação racional Convert to Octal Representation Converter para representação octal Convert to Padded Octal Representation Converter para representação octal preenchida Vector or Matrix Norm Norma de vetor ou matriz Logical OR OU lógico Population Count (Hamming Weight) Contagem de bits (peso de Hamming) Phase of Complex Number Fase do número complexo Poissonian Cumulative Distribution Function Função de distribuição acumulada de Poisson Poissonian Distribution Mean Média da distribuição de Poisson Poissonian Probability Mass Function Função massa de probabilidade da distribuição de Poisson Poissonian Distribution Variance Variância da distribuição de Poisson Convert to Phasor Complex Form Converter para forma complexa fasorial Convert to Rectangular Complex Form Converter para forma complexa retangular Round Half Away from Zero Arredondar metade para longe de zero Round Half Even Arredondar metade para par Nth Root Raiz enésima Convert to Scientific Notation Converter para notação científica Matrix Row Count Número de linhas da matriz List or Matrix Shape Forma de lista ou matriz Summation Somatório Population Standard Deviation (n) Desvio-padrão populacional (n) Sample Standard Deviation (n-1) Desvio-padrão amostral (n-1) Round Toward Zero (Truncation) Arredondar para zero (truncagem) Matrix Trace Traço da matriz Transpose Matrix Transpor matriz Population Variance (n) Variância populacional (n) Sample Variance (n-1) Variância amostral (n-1) Product Produto Radians Radianos Matrix Rank Posto da matriz Real Part Parte real Secant Secante Arithmetic Shift Left Deslocamento aritmético à esquerda Arithmetic Shift Right Deslocamento aritmético à direita Signum Sinal Sine Seno Hyperbolic Sine Seno hiperbólico Square Root Raiz quadrada Sum Soma Tangent Tangente Convert to Trigonometric Complex Form Converter para forma complexa trigonométrica Turns Voltas Hyperbolic Tangent Tangente hiperbólica Sign-extend a value Extender sinal de um valor Logical XOR XOR lógico FunctionsWidget Domain Domínio All Tudo Name Nome Search Pesquisar No match found Nenhum resultado encontrado Identifier Identificador HistoryWidget Remove All Calculations Above Remover todos os cálculos acima Remove This Calculation Remover este cálculo Remove All Calculations Below Remover todos os cálculos abaixo Keypad Inverse cosine Arco cosseno The last result Último resultado Inverse sine Arco seno Inverse tangent Arco tangente Evaluate expression Calcular expressão Division Divisão Multiplication Multiplicação Subtraction Subtracção Addition Adição Clear expression Limpar expressão Cosine Cosseno Backspace Retrocesso Scientific notation Notação científica Exponential Exponencial Factorial Fatorial Natural logarithm Logaritmo natural Left parenthesis Parêntese esquerdo Nth root Raiz enésima Argument separator Separador de argumentos Square Quadrado Common logarithm Logaritmo comum Modulo Módulo Contextual percentage Porcentagem contextual Power Potência Right parenthesis Parêntese direito Sine Seno Square root Raiz quadrada Tangent Tangente Pi Pi Decimal separator Separador decimal MainWindow Radian Radiano Degree Grau Gradian Grado centesimal Binary Binário Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Engineering decimal Decimal de engenharia Scientific decimal Decimal científico &Import... &Importar... &Quit &Sair Clear E&xpression Limpar e&xpressão Clear &History Limpar &histórico &Copy &Copiar &Paste &Colar &Select Expression &Selecionar expressão &Constants &Constantes &Functions &Funções &History &Histórico &Status Bar Barra de &status Bitfield Campo de bits Use&r Functions Funções de usuá&rio &Degree &Grau &Radian &Radiano &Gradian G&rado centesimal Re&volution R&evolução Auto-Insert a&ns I&nserir ans automaticamente Automatic &Completion Completação &automática &Built-in Functions &Funções integradas Built-in &Variables &Variáveis integradas User &Functions Fu&nções de Usuário User Va&riables Va&riáveis do usuário Open a Private Tab on Startup Abrir uma aba privada ao iniciar Open and focus a new private tab whenever SpeedCrunch starts. Abrir e ativar uma nova aba privada sempre que o SpeedCrunch iniciar. Syntax &Highlighting Realce de &sintaxe Group Digits in &Input Agrupar díg&itos na entrada Automatic Input &Adjustments &Ajustes automáticos de entrada Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ajustar automaticamente operadores, espaçamento, parênteses e potências, e limitar a entrada a caracteres válidos. Group input digits using the selected number format. Agrupar os dígitos de entrada conforme o formato numérico selecionado. &Blinking Cursor &Cursor piscante Blink the cursor in the expression editor. Fazer o cursor piscar no editor de expressões. &Escape Clears Editor &Escape limpa o editor Clear the focused expression editor with Escape after dismissing any popup or preview. Limpar o editor de expressões ativo com Escape depois de fechar qualquer janela pop-up ou prévia. Keep Expression After Evaluation Manter a expressão após o cálculo Copy New Results Automatically Copiar novos resultados automaticamente &Comma &Vírgula &System Default Padrão do &sistema &Dot &Ponto Dot &And Comma Ponto &e vírgula Toward +∞ (&ceil) Em direção a +∞ (&ceil) Toward −∞ (&floor) Em direção a −∞ (&floor) &Binary &Binário &Engineering &Engenharia &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Científico User &Manual Manual do &usuário Issues and &Feedback &Problemas e comentários &Donate &Doar &About SpeedCrunch &Sobre o SpeedCrunch App Diag&nostics Diag&nóstico do aplicativo S&plit &Dividir Angle &Mode &Modo angular &Complex Form Forma &complexa New Tab Nova aba Constants Constantes Functions Funções History Histórico User Functions Funções de Usuário &Font... &Fonte... &Language... &Idioma... &Session &Sessão &Edit &Editar &View &Visualizar Se&ttings Configura&ções &Decimal &Decimal &Keypad &Teclado numérico Always on &Top Sempre no &topo Disabled Desativado Small Space Espaço pequeno Medium Space Espaço médio Large Space Espaço grande &0 Digits &0 dígitos &15 Digits &15 dígitos &2 Digits &2 dígitos &3 Digits &3 dígitos &50 Digits &50 dígitos &8 Digits &8 dígitos &Sexagesimal &Sexagesimal Reset All Settings... Redefinir todas as configurações... &System &Sistema SpeedCrunch &Theme &Tema do SpeedCrunch &Classic &Clássico &Modern &Moderno Context Help Ajuda contextual &Help &Ajuda Error Erro Can't read from file %1 Não foi possível ler o arquivo %1 Import Session Importar sessão Close Session Fechar sessão Angle Mode: Modo de ângulo: Notation: Notação: Precision: Precisão: Turn Volta Revolution Revolução Fixed-point decimal Decimal de ponto fixo Rational Racional Automatic decimal Decimal automático Automatic Automático User &Definitions... &Definições do usuário... New &Tab Nova &aba New &Private Tab &Nova aba privada Keep Manter Make Private... Tornar privada... New &Window Nova &janela &Open... &Abrir... &Rename... &Renomear... Clo&ne... &Clonar... &Close Tab &Fechar aba Reopen Clo&sed Tab Rea&brir aba fechada Open Sessions &Folder Abrir &pasta de sessões &Undo &Desfazer &Redo &Refazer Cu&t Recor&tar Copy &Last Result Copiar o ú&ltimo resultado &Wrap in Parentheses C&olocar entre parênteses Full Scr&een Mode Modo d&e tela cheia &Basic &Básico &Scientific (wide) &Científica (larga) Scientific (narrow) Científica (estreita) &Custom... &Personalizado... Main &Menu &Menu principal User &Variables &Variáveis do usuário &Left &Esquerda &Right Di&reita &Up &Acima &Down A&baixo Close Pa&ne Fechar pai&nel User &Units &Unidades do usuário &Turn &Volta If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Se uma nova expressão começar com +, -, * ou /, o SpeedCrunch insere primeiro "ans". &Accept with Enter &Aceitar com Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Aceitar a sugestão atual de preenchimento automático com Enter sem selecioná-la primeiro com as teclas de seta. &Units &Unidades Show Live Result &Preview Mostrar &pré-visualização do resultado em directo Save &Window Position on Exit Guardar posição da &janela ao sair Hover Highlighting Realce ao passar o rato Group Integer Part Only Agrupar apenas a parte inteira Number Format... Formato do número... Notation && Precision... Notação e precisão... After pressing Enter, keep the entered expression selected in the editor. Depois de pressionar Enter, manter a expressão inserida selecionada no editor. Never Nunca Always Sempre Only for Single-Line Expressions Apenas para expressões de uma linha Simplify Displayed Expressions Simplificar expressões apresentadas History Size &Limit... &Limite do tamanho do histórico... Remove Trailing &Zeroes Remover &zeros finais Nearest, Half &Away (round) Mais próximo, metade para &longe (round) Nearest, Half &Even (roundeven) Mais próximo, metade para &par (roundeven) Toward &Zero (trunc) Para &zero (trunc) &Fixed-Point &Ponto fixo &Rational &Racional &Exponential (m·sâ�»Â¹) &Exponencial (m·sâ�»Â¹) &Fractional (m/s) &Fraccionária (m/s) &Rectangular (a + bi) &Retangular (a + bi) Exponential (reâ�±á¶¿) Exponencial (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonométrica (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Tema... Check for &Updates Procurar &atualizações Source Code Código-fonte &Zoom &Zoom &Results &Resultados Unit Notation Notação de unidades Rounding Mode Modo de arredondamento &Notation &Notação &Imaginary Unit Unidade &imaginária &Window &Janela &Editing &Edição A&utocomplete A&utocompletar Up/Down Arrow History Histórico com setas para cima/baixo &Appearance &Aparência &Menus &Menus &Docks &Painéis acopláveis &Input and Results &Entrada e resultados &Disabled &Desactivado &Disable &Desactivar Close preview Fechar pré-visualização Rename... Renomear... Clone... Clonar... Close Tab Fechar aba New Private Tab Nova aba privada Open... Abrir... Reopen Closed Tab Reabrir aba fechada Split Dividir Left Esquerda Right Direita Up Acima Down Abaixo Clear Limpar Delete Excluir %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sessão privada: o conteúdo é descartado ao fechar. Escolha Sessão > Manter para transformá-la em uma sessão normal. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privada] Reset All Settings Redefinir todas as configurações Reset all settings to their default values? Redefinir todas as configurações para os valores padrão? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Isso inclui aparência, edição, formatos de resultados e preferências das janelas. Os cálculos, as sessões abertas e as definições do usuário serão mantidos. The settings file could not be written. Não foi possível gravar o arquivo de configurações. Clear this session's calculations, unfinished expression, variables, functions, and units? Limpar os cálculos, a expressão inacabada, as variáveis, as funções e as unidades desta sessão? Global user definitions are kept. As definições globais do usuário são mantidas. Make Session Private Tornar a sessão privada The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. A sessão salva %1 será excluída. O conteúdo permanecerá aberto em uma sessão privada e será descartado quando essa sessão for fechada ou o SpeedCrunch for encerrado. Make Private Tornar privada Could not delete the saved session %1. Não foi possível excluir a sessão salva %1. Keep Session Manter sessão Could not save the session. It remains private. Não foi possível salvar a sessão. Ela continua privada. Clone Session Clonar sessão Could not save session file %1. Não foi possível salvar o arquivo de sessão %1. Could not delete session file %1. Não foi possível excluir o arquivo de sessão %1. JSON file (*.json);;Any file (*.*) Arquivo JSON (*.json);;Qualquer arquivo (*.*) Export session as JSON Exportar sessão como JSON The selected file is not valid JSON: %1 O arquivo selecionado não é JSON válido: %1 The selected file is not a SpeedCrunch session JSON file. O arquivo selecionado não é um arquivo JSON de sessão do SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Este arquivo usa um formato de sessão do SpeedCrunch obsoleto e não pode ser importado. The selected JSON file is missing the required $schema field. O arquivo JSON selecionado não contém o campo obrigatório $schema. The selected JSON file uses an unsupported JSON schema: %1 O arquivo JSON selecionado usa um esquema JSON sem suporte: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). O arquivo JSON selecionado não contém o identificador de esquema de sessão do SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 O arquivo JSON selecionado usa um formato de sessão do SpeedCrunch sem suporte: %1 The selected JSON file is missing the required session name. O arquivo JSON selecionado não contém o nome de sessão obrigatório. The selected JSON file has an empty session name. O arquivo JSON selecionado tem um nome de sessão vazio. The selected JSON file has invalid or incomplete SpeedCrunch session data. O arquivo JSON selecionado contém dados de sessão do SpeedCrunch inválidos ou incompletos. Open Sessions Folder Abrir pasta de sessões Could not create the sessions folder: %1 Não foi possível criar a pasta de sessões: %1 Could not open the sessions folder: %1 Não foi possível abrir a pasta de sessões: %1 Editor and Results Font Fonte do editor e dos resultados Open Session Abrir sessão Community Comunidade Rename Session Renomear sessão Clear Session Limpar sessão Delete Session Excluir sessão Close Pane Fechar painel User Variables Variáveis do usuário User Units Unidades do usuário Clear History Limpar histórico Are you sure you want to clear the calculation history? Tem certeza de que deseja limpar o histórico de cálculos? Session name: Nome da sessão: A session named %1 already exists. Já existe uma sessão chamada %1. Could not create session file %1. Não foi possível criar o arquivo de sessão %1. Could not write session file %1. Não foi possível escrever o arquivo de sessão %1. Are you sure you want to delete this session? Tem certeza de que deseja excluir esta sessão? Custom Precision Precisão personalizada Fractional digits: Dígitos fracionários: Theme Tema Light Themes Temas claros Dark Themes Temas escuros Preview Pré-visualização Colors Cores Select color for %1 Selecionar cor para %1 Import... Importar... Export... Exportar... Import Theme Importar tema Theme file (*.json);;All files (*) Arquivo de tema (*.json);;Todos os arquivos (*) Invalid theme file. Arquivo de tema inválido. Can't import theme "%1" because it conflicts with a built-in theme. Não é possível importar o tema "%1" porque ele entra em conflito com um tema integrado. Can't find a writable theme folder. Não é possível encontrar uma pasta de temas gravável. Overwrite Theme Substituir tema A custom theme named "%1" already exists. Do you want to overwrite it? Já existe um tema personalizado chamado "%1". Deseja substituí-lo? Can't overwrite theme file %1 Não é possível substituir o arquivo de tema %1 Can't copy theme file to %1 Não é possível copiar o arquivo de tema para %1 Export Theme Exportar tema Can't export theme as "%1" because it conflicts with a built-in theme. Não é possível exportar o tema como "%1" porque ele entra em conflito com um tema integrado. Can't write to file %1 Não foi possível escrever no arquivo %1 Global User Variable Variável global do usuário Global User Function Função global do usuário Global User Unit Unidade global do usuário User Definitions Definições do usuário These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Estas definições são globais e são carregadas em todas as sessões. Não podem ser alteradas nas sessões e têm prioridade sobre as definições com o mesmo nome do editor da sessão. Insira uma definição por linha. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Exemplos: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Aplicar Validate Validar Test Results Resultados do teste Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variáveis importadas: %1 Funções importadas: %2 Unidades importadas: %3 Números das linhas com erros: %4 none nenhum Apply Results Resultados da aplicação User definitions saved. Definições do usuário salvas. History Size Limit Limite do tamanho do histórico Maximum number of history entries for this session (0 = unlimited): Número máximo de entradas de histórico para esta sessão (0 = ilimitado): Text file (*.txt);;Any file (*.*) Arquivo de texto (*.txt);;Qualquer arquivo (*.*) Could not recalculate from calculation %1: %2 Não foi possível recalcular a partir do cálculo %1: %2 History Size Limit Reached Limite do tamanho do histórico atingido This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Este cálculo ocupa o último espaço disponível do histórico. Cálculos futuros removerão o cálculo mais antigo do histórico. Você pode aumentar o limite em Sessão > Limite do tamanho do histórico. Editing calculation. Press Esc twice to cancel. Editando cálculo. Pressione Esc duas vezes para cancelar. Calculation Settings Configurações de cálculo Invalid recalculation start index Ã�ndice inicial de recálculo inválido System Default Padrão do sistema Language Idioma Select the language: Selecione o idioma: Custom Personalizado Decimal places: Casas decimais: &Automatic &Automático &Precision &Precisão Plain &text Texto &simples Formula &Book &Livro de Fórmulas &Export &Exportar Export session as HTML Exportar sessão como HTML HTML file (*.html) Arquivo HTML (*.html) Export session as plain text Exportar sessão como texto simples ManualWindow SpeedCrunch Manual Manual do SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual do SpeedCrunch NumberFormatDialog Number Format Formato do número <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Selecione o formato numérico dos resultados e do agrupamento de dígitos de entrada.</b><br/><br/>Nota: números inseridos em formatos inequívocos são aceitos mesmo quando diferem do formato de exibição selecionado.<br/> QObject Global User Variable Variável global do usuário Global User Function Função global do usuário Global User Unit Unidade global do usuário Backspace Retrocesso Clear expression Limpar expressão Evaluate expression Calcular expressão Insert text Inserir texto Automatic decimal Decimal automático Fixed-point decimal Decimal de ponto fixo Engineering decimal Decimal de engenharia Scientific decimal Decimal científico Rational Racional Binary Binário Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Update Available Atualização disponível A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Uma versão mais recente (%1) está disponível.<br/><a href="%2">Visite o site para baixar.</a> Check for Updates Procurar atualizações SpeedCrunch %1 is up to date. O SpeedCrunch %1 está atualizado. No connectivity. Please check your internet connection and try again. Sem conectividade. Verifique a ligação à Internet e tente novamente. Could not verify the latest available version. Não foi possível verificar a versão mais recente disponível. ResultDisplay Scroll to bottom Deslocar para o fim Edit Expression Editar expressão Change Settings Alterar configurações New Tab Nova aba &Import... &Importar... &Export &Exportar Plain &text Texto &simples Copy Copiar Selection Seleção Select All Selecionar tudo Expression Expressão Result Resultado Calculation Cálculo Calculation as Single Line Cálculo em uma única linha Remove Remover This Calculation Este cálculo All Calculations Above Todos os cálculos acima All Calculations Below Todos os cálculos abaixo New Private Tab Nova aba privada Session Sessão Open... Abrir... Clone... Clonar... Rename... Renomear... Keep Manter Make Private... Tornar privada... Clear Limpar Delete Excluir Close Fechar Split Dividir Left Esquerda Right Direita Up Acima Down Abaixo Close Pane Fechar painel Main Menu Menu principal Cancel editing Cancelar edição Copy result Copiar resultado Edit expression Editar expressão Change settings Alterar configurações Remove calculation Remover cálculo ResultSlotsDialog Notation & Precision Notação e precisão Result Line Linha do resultado Enabled Activado Notation Notação Decimal Places Casas decimais Main Line Linha principal Extra Line #1 Linha extra n.º 1 Extra Line #2 Linha extra n.º 2 Extra Line #3 Linha extra n.º 3 Extra Line #4 Linha extra n.º 4 Auto Automático UserFunctionListWidget Name Nome Value Valor Description Descrição Search Busca No match found Nenhum resultado encontrado Insert Inserir Edit Editar Delete Excluir Delete All Excluir tudo UserUnitListWidget Name Nome Value Valor Description Descrição Search Procurar No match found Sem resultados Insert Inserir Edit Editar Delete Excluir Delete All Excluir tudo VariableListWidget Name Nome Value Valor Description Descrição Search Pesquisar No match found Nenhum resultado encontrado Insert Inserir Edit Editar Delete Excluir Delete All Excluir tudo heldercorreia-speedcrunch-e7ca37f/src/resources/locale/pt_PT.ts000066400000000000000000010561601526573132500250040ustar00rootroot00000000000000 AboutBox About SpeedCrunch Acerca do SpeedCrunch Core developers Principais programadores Original author Autor original Close Fechar Math engine Mecanismo matemático Main author | Logo | Maintainer Autor principal | Logo | Responsável de manutenção Thanks Agradecimentos Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Os programadores do SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Este é um programa livre; pode redistribuí-lo e/ou modificá-lo nos termos da GNU General Public License conforme publicada pela Free Software Foundation; quer a versão 2 da Licença, quer (à sua escolha) qualquer versão posterior. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Este programa é distribuído na esperança de que seja útil, mas SEM QUALQUER GARANTIA. Consulte a GNU General Public License para mais detalhes. BitFieldWidget Reset bits to zero Repor bits a zero Invert bits Inverter bits Shift bits left Deslocar bits para a esquerda Shift bits right Deslocar bits para a direita Book Index Ã�ndice Algebra Ã�lgebra Quadratic Equation Equação quadrática Logarithmic Base Conversion Conversão de base logarítmica Geometry Geometria Circle Círculo Sector Setor Sphere Esfera Cube Cubo Cone Cone Cylinder Cilindro Electronics Eletrónica Ohm's Law Lei de Ohm Power Potência Reactance Reatância Resonance Ressonância Radio Frequency Radiofrequência Antennas Antenas Characteristic Impedance (coax) Impedância característica (coax) Velocity of Propagation (coax) Velocidade de propagação (coax) Standing Wave Ratio & Return Loss Rácio de onda estacionária e perda de retorno Free Space Wavelength Comprimento de onda em espaço livre resistance resistência voltage tensão current corrente power potência inductive reactance reatância indutiva capacitive reactance reatância capacitiva inductance indutância capacitance capacitância frequency frequência resonance frequency frequência de ressonância area área perimeter perímetro diameter diâmetro radius raio volume volume surface area área da superfície height altura slant height geratriz face diagonal diagonal da face space diagonal diagonal do cubo edge length comprimento da aresta arc length comprimento de arco central angle (degrees) ângulo central (graus) input power potência de entrada reflected power potência refletida transmitted power potência transmitida return loss perda de retorno dielectric constant constante dielétrica outer conductor's inner diameter diâmetro interno do condutor externo inner conductor's outer diameter diâmetro externo do condutor interno speed of light velocidade da luz reflection coefficient coeficiente de reflexão standing wave ratio rácio de ondas estacionárias normalized impedance impedância normalizada frequency (Hz) frequência (Hz) BookDock Formula Book Livro de fórmulas ConstantCompletion Search constants Pesquisar constantes No match found Sem resultados Constants Mathematics Matemática Physics (CODATA 2022) Física (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Química (IUPAC - CIAAW 2021) Uncategorized Sem categoria Universal Universal Physicochemical Físico-química Atomic & Nuclear — General Atómica e nuclear — Geral Atomic & Nuclear — Electroweak Atómica e nuclear — Eletrofraca Atomic & Nuclear — Electron Atómica e nuclear — Eletrão Atomic & Nuclear — Muon Atómica e nuclear — Muão Atomic & Nuclear — Tau Atómica e nuclear — Tau Atomic & Nuclear — Proton Atómica e nuclear — Protão Atomic & Nuclear — Neutron Atómica e nuclear — Neutrão Atomic & Nuclear — Deuteron Atómica e nuclear — Deuterão Atomic & Nuclear — Triton Atómica e nuclear — Tritão Atomic & Nuclear — Helion Atómica e nuclear — Helião Atomic & Nuclear — Alpha particle Atómica e nuclear — Partícula alfa Atomic & Nuclear — Atomic units Atómica e nuclear — Unidades atómicas Atomic & Nuclear — Energy conversion relationships Atómica e nuclear — Relações de conversão de energia Atomic & Nuclear — X-ray units Atómica e nuclear — Unidades de raios X Atomic & Nuclear — Magnetic shielding corrections Atómica e nuclear — Correções de blindagem magnética Masses Massas Lifetimes Tempos de vida Molar Masses Massas molares Electronegativity Eletronegatividade Ionization Energy Energia de ionização Nominal Constants (IAU 2015) Constantes nominais (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Melhores estimativas atuais (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) impedância característica do vácuo (Zâ‚€) reduced Planck constant (â„�) constante de Planck reduzida (â„�) vacuum electric permittivity (ϵ₀) permitividade elétrica do vácuo (ϵ₀) Newtonian constant of gravitation (G) constante newtoniana da gravitação (G) vacuum magnetic permeability (μ₀) permeabilidade magnética do vácuo (μ₀) Planck constant (h) constante de Planck (h) speed of light in vacuum (c) velocidade da luz no vácuo (c) standard acceleration of gravity (gâ‚™) aceleração normal da gravidade (gâ‚™) Newtonian constant of gravitation over h-bar c constante newtoniana da gravitação sobre h-bar c Planck length comprimento de Planck Planck constant in eV/Hz (h) constante de Planck em eV/Hz (h) Planck mass massa de Planck Planck mass energy equivalent in GeV equivalente energético da massa de Planck em GeV Planck temperature temperatura de Planck Planck time tempo de Planck reduced Planck constant in eV·s (â„�) constante de Planck reduzida em eV·s (â„�) reduced Planck constant times c in MeV·fm constante de Planck reduzida vezes c em MeV·fm Bohr magneton magnetão de Bohr conductance quantum (Gâ‚€) quantum de condutância (Gâ‚€) Coulomb constant (kâ‚‘) constante de Coulomb (kâ‚‘) elementary charge (e) carga elementar (e) elementary charge over h-bar carga elementar sobre h-bar conventional value of Josephson constant valor convencional da constante de Josephson Josephson constant constante de Josephson conventional value of ampere-90 valor convencional do ampere-90 conventional value of coulomb-90 valor convencional do coulomb-90 conventional value of farad-90 valor convencional do farad-90 conventional value of henry-90 valor convencional do henry-90 conventional value of ohm-90 valor convencional do ohm-90 conventional value of volt-90 valor convencional do volt-90 conventional value of watt-90 valor convencional do watt-90 magnetic flux quantum (Φ₀) quantum de fluxo magnético (Φ₀) nuclear magneton magnetão nuclear inverse of conductance quantum inverso do quantum de condutância conventional value of von Klitzing constant valor convencional da constante de von Klitzing von Klitzing constant constante de von Klitzing atomic unit of magnetic dipole moment unidade atómica de momento dipolar magnético atomic unit of magnetic flux density unidade atómica de densidade de fluxo magnético Bohr magneton in eV/T magnetão de Bohr em eV/T Bohr magneton in Hz/T magnetão de Bohr em Hz/T Bohr magneton in inverse meter per tesla magnetão de Bohr em metro inverso por tesla Bohr magneton in K/T magnetão de Bohr em K/T nuclear magneton in eV/T magnetão nuclear em eV/T nuclear magneton in inverse meter per tesla magnetão nuclear em metro inverso por tesla nuclear magneton in K/T magnetão nuclear em K/T nuclear magneton in MHz/T magnetão nuclear em MHz/T Bohr radius (aâ‚€) raio de Bohr (aâ‚€) fine-structure constant (α) constante de estrutura fina (α) Hartree energy (Eâ‚•) energia de Hartree (Eâ‚•) Hartree energy in eV energia de Hartree em eV quantum of circulation quantum de circulação quantum of circulation times 2 quantum de circulação vezes 2 Rydberg constant (R∞) constante de Rydberg (R∞) atomic mass unit-hartree relationship relação unidade de massa atómica-hartree atomic mass unit-hertz relationship relação unidade de massa atómica-hertz atomic mass unit-inverse meter relationship relação unidade de massa atómica-metro inverso atomic mass unit-joule relationship relação unidade de massa atómica-joule atomic mass unit-kelvin relationship relação unidade de massa atómica-kelvin atomic mass unit-kilogram relationship relação unidade de massa atómica-quilograma atomic unit of 1st hyperpolarizability unidade atómica de 1.ª hiperpolarizabilidade atomic unit of 2nd hyperpolarizability unidade atómica de 2.ª hiperpolarizabilidade atomic unit of charge (e) unidade atómica de carga (e) atomic unit of charge density unidade atómica de densidade de carga atomic unit of current unidade atómica de corrente atomic unit of electric dipole moment unidade atómica de momento dipolar elétrico atomic unit of electric field unidade atómica de campo elétrico atomic unit of electric field gradient unidade atómica de gradiente de campo elétrico atomic unit of electric polarizability unidade atómica de polarizabilidade elétrica atomic unit of electric potential unidade atómica de potencial elétrico atomic unit of electric quadrupole moment unidade atómica de momento quadrupolar elétrico atomic unit of action unidade atómica de ação atomic unit of energy unidade atómica de energia atomic unit of force unidade atómica de força atomic unit of length unidade atómica de comprimento hertz-atomic mass unit relationship relação hertz-unidade de massa atómica hertz-electron volt relationship relação hertz-eletrão-volt hertz-hartree relationship relação hertz-hartree hertz-inverse meter relationship relação hertz-metro inverso hertz-joule relationship relação hertz-joule hertz-kelvin relationship relação hertz-kelvin hertz-kilogram relationship relação hertz-quilograma hyperfine transition frequency of Cs-133 frequência de transição hiperfina do Cs-133 inverse fine-structure constant (αâ�»Â¹) constante inversa de estrutura fina (αâ�»Â¹) inverse meter-atomic mass unit relationship relação metro inverso-unidade de massa atómica inverse meter-electron volt relationship relação metro inverso-eletrão-volt inverse meter-hartree relationship relação metro inverso-hartree inverse meter-hertz relationship relação metro inverso-hertz inverse meter-joule relationship relação metro inverso-joule inverse meter-kelvin relationship relação metro inverso-kelvin inverse meter-kilogram relationship relação metro inverso-quilograma joule-atomic mass unit relationship relação joule-unidade de massa atómica joule-electron volt relationship relação joule-eletrão-volt joule-hertz relationship relação joule-hertz joule-hartree relationship relação joule-hartree joule-inverse meter relationship relação joule-metro inverso joule-kelvin relationship relação joule-kelvin joule-kilogram relationship relação joule-quilograma kelvin-atomic mass unit relationship relação kelvin-unidade de massa atómica kelvin-electron volt relationship relação kelvin-eletrão-volt kelvin-hertz relationship relação kelvin-hertz kelvin-hartree relationship relação kelvin-hartree kelvin-inverse meter relationship relação kelvin-metro inverso kelvin-joule relationship relação kelvin-joule kelvin-kilogram relationship relação kelvin-quilograma kilogram-atomic mass unit relationship relação quilograma-unidade de massa atómica kilogram-electron volt relationship relação quilograma-eletrão-volt kilogram-hertz relationship relação quilograma-hertz kilogram-hartree relationship relação quilograma-hartree kilogram-inverse meter relationship relação quilograma-metro inverso kilogram-joule relationship relação quilograma-joule kilogram-kelvin relationship relação quilograma-kelvin lattice parameter of silicon (a) parâmetro de rede do silício (a) luminous efficacy eficácia luminosa natural unit of energy unidade natural de energia natural unit of energy in MeV unidade natural de energia em MeV natural unit of action (â„�) unidade natural de ação (â„�) natural unit of action in eV·s unidade natural de ação em eV·s natural unit of length unidade natural de comprimento natural unit of mass unidade natural de massa natural unit of momentum unidade natural de momento natural unit of momentum in MeV/c unidade natural de momento em MeV/c natural unit of time unidade natural de tempo natural unit of velocity unidade natural de velocidade Rydberg constant times c in Hz constante de Rydberg vezes c em Hz Rydberg constant times hc in eV constante de Rydberg vezes hc em eV Rydberg constant times hc in J constante de Rydberg vezes hc em J Fermi coupling constant constante de acoplamento de Fermi weak mixing angle ângulo de mistura fraca W to Z mass ratio razão entre as massas W e Z Thomson cross section (σₑ) secção eficaz de Thomson (σₑ) electron mass (mâ‚‘) massa do eletrão (mâ‚‘) electron mass in u massa do eletrão em u electron mass energy equivalent (mₑ·c²) equivalente energético da massa do eletrão (mₑ·c²) electron mass energy equivalent in MeV equivalente energético da massa do eletrão em MeV reduced Compton wavelength comprimento de onda de Compton reduzido classical electron radius (râ‚‘) raio clássico do eletrão (râ‚‘) electron charge to mass quotient quociente carga-massa do eletrão electron-deuteron magnetic moment ratio razão dos momentos magnéticos eletrão-deuterão electron-deuteron mass ratio razão das massas eletrão-deuterão electron g factor (gâ‚‘) fator g do eletrão (gâ‚‘) electron gyromagnetic ratio (γₑ) razão giromagnética do eletrão (γₑ) electron gyromagnetic ratio in MHz/T razão giromagnética do eletrão em MHz/T electron-helion mass ratio razão das massas eletrão-helião electron magnetic moment (μₑ) momento magnético do eletrão (μₑ) electron magnetic moment anomaly (aâ‚‘) anomalia do momento magnético do eletrão (aâ‚‘) electron magnetic moment to Bohr magneton ratio razão entre o momento magnético do eletrão e o magnetão de Bohr electron magnetic moment to nuclear magneton ratio razão entre o momento magnético do eletrão e o magnetão nuclear electron molar mass (Mâ‚‘) massa molar do eletrão (Mâ‚‘) electron-muon magnetic moment ratio razão dos momentos magnéticos eletrão-muão electron-muon mass ratio razão das massas eletrão-muão electron-neutron magnetic moment ratio razão dos momentos magnéticos eletrão-neutrão electron-neutron mass ratio razão das massas eletrão-neutrão electron-proton magnetic moment ratio razão dos momentos magnéticos eletrão-protão electron-proton mass ratio razão das massas eletrão-protão electron relative atomic mass (Ar(e)) massa atómica relativa do eletrão (Ar(e)) electron-tau mass ratio razão das massas eletrão-tau electron to alpha particle mass ratio razão entre as massas do eletrão e da partícula alfa electron to shielded helion magnetic moment ratio razão entre os momentos magnéticos do eletrão e do helião blindado electron to shielded proton magnetic moment ratio razão entre os momentos magnéticos do eletrão e do protão blindado electron-triton mass ratio razão das massas eletrão-tritão electron volt-atomic mass unit relationship relação eletrão-volt-unidade de massa atómica electron volt-hartree relationship relação eletrão-volt-hartree electron volt-hertz relationship relação eletrão-volt-hertz electron volt-inverse meter relationship relação eletrão-volt-metro inverso electron volt-joule relationship relação eletrão-volt-joule electron volt-kelvin relationship relação eletrão-volt-kelvin electron volt-kilogram relationship relação eletrão-volt-quilograma hartree-atomic mass unit relationship relação hartree-unidade de massa atómica hartree-electron volt relationship relação hartree-eletrão-volt muon Compton wavelength comprimento de onda de Compton do muão muon-electron mass ratio razão das massas muão-eletrão muon g factor fator g do muão muon magnetic moment momento magnético do muão muon magnetic moment anomaly anomalia do momento magnético do muão muon magnetic moment to Bohr magneton ratio razão entre o momento magnético do muão e o magnetão de Bohr muon magnetic moment to nuclear magneton ratio razão entre o momento magnético do muão e o magnetão nuclear muon mass massa do muão muon mass energy equivalent equivalente energético da massa do muão muon mass energy equivalent in MeV equivalente energético da massa do muão em MeV muon mass in u massa do muão em u muon molar mass massa molar do muão muon-neutron mass ratio razão das massas muão-neutrão muon-proton magnetic moment ratio razão dos momentos magnéticos muão-protão muon-proton mass ratio razão das massas muão-protão muon-tau mass ratio razão das massas muão-tau reduced muon Compton wavelength comprimento de onda de Compton reduzido do muão reduced tau Compton wavelength comprimento de onda de Compton reduzido do tau tau Compton wavelength comprimento de onda de Compton do tau tau-electron mass ratio razão das massas tau-eletrão tau mass massa do tau tau mass energy equivalent equivalente energético da massa do tau tau mass in u massa do tau em u tau molar mass massa molar do tau tau-muon mass ratio razão das massas tau-muão tau-neutron mass ratio razão das massas tau-neutrão tau-proton mass ratio razão das massas tau-protão proton charge to mass quotient quociente carga-massa do protão proton Compton wavelength comprimento de onda de Compton do protão proton-electron mass ratio razão das massas protão-eletrão proton g factor (gₚ) fator g do protão (gₚ) proton gyromagnetic ratio (γₚ) razão giromagnética do protão (γₚ) proton gyromagnetic ratio in MHz/T razão giromagnética do protão em MHz/T proton magnetic moment (μₚ) momento magnético do protão (μₚ) proton magnetic moment to Bohr magneton ratio razão entre o momento magnético do protão e o magnetão de Bohr proton magnetic moment to nuclear magneton ratio razão entre o momento magnético do protão e o magnetão nuclear proton magnetic shielding correction correção de blindagem magnética do protão proton mass (mₚ) massa do protão (mₚ) proton mass energy equivalent equivalente energético da massa do protão proton mass energy equivalent in MeV equivalente energético da massa do protão em MeV proton mass in u massa do protão em u proton molar mass (Mₚ) massa molar do protão (Mₚ) proton-muon mass ratio razão das massas protão-muão proton-neutron magnetic moment ratio razão dos momentos magnéticos protão-neutrão proton-neutron mass ratio razão das massas protão-neutrão proton relative atomic mass (Ar(p)) massa atómica relativa do protão (Ar(p)) proton rms charge radius raio de carga rms do protão proton-tau mass ratio razão das massas protão-tau reduced proton Compton wavelength comprimento de onda de Compton reduzido do protão shielded proton gyromagnetic ratio razão giromagnética do protão blindado shielded proton gyromagnetic ratio in MHz/T razão giromagnética do protão blindado em MHz/T shielded proton magnetic moment momento magnético do protão blindado shielded proton magnetic moment to Bohr magneton ratio razão entre o momento magnético do protão blindado e o magnetão de Bohr shielded proton magnetic moment to nuclear magneton ratio razão entre o momento magnético do protão blindado e o magnetão nuclear neutron Compton wavelength comprimento de onda de Compton do neutrão neutron-electron magnetic moment ratio razão dos momentos magnéticos neutrão-eletrão neutron-electron mass ratio razão das massas neutrão-eletrão neutron g factor (gâ‚™) fator g do neutrão (gâ‚™) neutron gyromagnetic ratio (γₙ) razão giromagnética do neutrão (γₙ) neutron gyromagnetic ratio in MHz/T razão giromagnética do neutrão em MHz/T neutron magnetic moment (μₙ) momento magnético do neutrão (μₙ) neutron magnetic moment to Bohr magneton ratio razão entre o momento magnético do neutrão e o magnetão de Bohr neutron magnetic moment to nuclear magneton ratio razão entre o momento magnético do neutrão e o magnetão nuclear neutron mass (mâ‚™) massa do neutrão (mâ‚™) neutron mass energy equivalent equivalente energético da massa do neutrão neutron mass energy equivalent in MeV equivalente energético da massa do neutrão em MeV neutron mass in u massa do neutrão em u neutron molar mass (Mâ‚™) massa molar do neutrão (Mâ‚™) neutron-muon mass ratio razão das massas neutrão-muão neutron-proton magnetic moment ratio razão dos momentos magnéticos neutrão-protão neutron-proton mass difference diferença de massas neutrão-protão neutron-proton mass difference energy equivalent equivalente energético da diferença de massas neutrão-protão neutron-proton mass difference energy equivalent in MeV equivalente energético da diferença de massas neutrão-protão em MeV neutron-proton mass difference in u diferença de massas neutrão-protão em u neutron-proton mass ratio razão das massas neutrão-protão neutron relative atomic mass (Ar(n)) massa atómica relativa do neutrão (Ar(n)) neutron-tau mass ratio razão das massas neutrão-tau neutron to shielded proton magnetic moment ratio razão entre os momentos magnéticos do neutrão e do protão blindado reduced neutron Compton wavelength comprimento de onda de Compton reduzido do neutrão deuteron-electron magnetic moment ratio razão dos momentos magnéticos deuterão-eletrão deuteron-electron mass ratio razão das massas deuterão-eletrão deuteron g factor fator g do deuterão deuteron magnetic moment momento magnético do deuterão deuteron magnetic moment to Bohr magneton ratio razão entre o momento magnético do deuterão e o magnetão de Bohr deuteron magnetic moment to nuclear magneton ratio razão entre o momento magnético do deuterão e o magnetão nuclear deuteron mass massa do deuterão deuteron mass energy equivalent equivalente energético da massa do deuterão deuteron mass energy equivalent in MeV equivalente energético da massa do deuterão em MeV deuteron mass in u massa do deuterão em u deuteron molar mass massa molar do deuterão deuteron-neutron magnetic moment ratio razão dos momentos magnéticos deuterão-neutrão deuteron-proton magnetic moment ratio razão dos momentos magnéticos deuterão-protão deuteron-proton mass ratio razão das massas deuterão-protão deuteron relative atomic mass (Ar(d)) massa atómica relativa do deuterão (Ar(d)) deuteron rms charge radius raio de carga rms do deuterão triton-electron mass ratio razão das massas tritão-eletrão triton g factor (gₜ) fator g do tritão (gₜ) triton magnetic moment (μₜ) momento magnético do tritão (μₜ) triton magnetic moment to Bohr magneton ratio razão entre o momento magnético do tritão e o magnetão de Bohr triton magnetic moment to nuclear magneton ratio razão entre o momento magnético do tritão e o magnetão nuclear triton mass (mₜ) massa do tritão (mₜ) triton mass energy equivalent equivalente energético da massa do tritão triton mass energy equivalent in MeV equivalente energético da massa do tritão em MeV triton mass in u massa do tritão em u triton molar mass (Mₜ) massa molar do tritão (Mₜ) triton-proton mass ratio razão das massas tritão-protão triton relative atomic mass (Ar(t)) massa atómica relativa do tritão (Ar(t)) triton to proton magnetic moment ratio razão entre os momentos magnéticos do tritão e do protão helion-electron mass ratio razão das massas helião-eletrão helion g factor (gâ‚•) fator g do helião (gâ‚•) helion magnetic moment (μₕ) momento magnético do helião (μₕ) helion magnetic moment to Bohr magneton ratio razão entre o momento magnético do helião e o magnetão de Bohr helion magnetic moment to nuclear magneton ratio razão entre o momento magnético do helião e o magnetão nuclear helion mass (mâ‚•) massa do helião (mâ‚•) helion mass energy equivalent equivalente energético da massa do helião helion mass energy equivalent in MeV equivalente energético da massa do helião em MeV helion mass in u massa do helião em u helion molar mass (Mâ‚•) massa molar do helião (Mâ‚•) helion-proton mass ratio razão das massas helião-protão helion relative atomic mass (Ar(h)) massa atómica relativa do helião (Ar(h)) helion shielding shift deslocamento de blindagem do helião shielded helion gyromagnetic ratio razão giromagnética do helião blindado shielded helion gyromagnetic ratio in MHz/T razão giromagnética do helião blindado em MHz/T shielded helion magnetic moment momento magnético do helião blindado shielded helion magnetic moment to Bohr magneton ratio razão entre o momento magnético do helião blindado e o magnetão de Bohr shielded helion magnetic moment to nuclear magneton ratio razão entre o momento magnético do helião blindado e o magnetão nuclear shielded helion to proton magnetic moment ratio razão entre os momentos magnéticos do helião blindado e do protão shielded helion to shielded proton magnetic moment ratio razão entre os momentos magnéticos do helião blindado e do protão blindado alpha particle mass massa da partícula alfa alpha particle mass in u massa da partícula alfa em u alpha particle mass energy equivalent equivalente energético da massa da partícula alfa alpha particle mass energy equivalent in MeV equivalente energético da massa da partícula alfa em MeV alpha particle-electron mass ratio razão das massas partícula alfa-eletrão alpha particle-proton mass ratio razão das massas partícula alfa-protão alpha particle rms charge radius raio de carga rms da partícula alfa alpha particle molar mass massa molar da partícula alfa alpha particle relative atomic mass (Ar(α)) massa atómica relativa da partícula alfa (Ar(α)) atomic mass constant (mᵤ) constante de massa atómica (mᵤ) Avogadro constant constante de Avogadro Boltzmann constant (k) constante de Boltzmann (k) Boltzmann constant in eV/K constante de Boltzmann em eV/K Boltzmann constant in Hz/K constante de Boltzmann em Hz/K Boltzmann constant in inverse meter per kelvin constante de Boltzmann em metro inverso por kelvin electron volt (eV) eletrão-volt (eV) Faraday constant (F) constante de Faraday (F) first radiation constant (câ‚�) primeira constante de radiação (câ‚�) first radiation constant for spectral radiance primeira constante de radiação para radiância espectral molar gas constant (R) constante molar dos gases (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) constante de Loschmidt (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) constante de Loschmidt (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant constante de Planck molar second radiation constant (câ‚‚) segunda constante de radiação (câ‚‚) Stefan-Boltzmann constant (σ) constante de Stefan-Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) espaçamento de rede do Si ideal (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent equivalente energético da constante de massa atómica atomic mass constant energy equivalent in MeV equivalente energético da constante de massa atómica em MeV atomic mass unit-electron volt relationship relação unidade de massa atómica-eletrão-volt molar mass constant (Mᵤ) constante de massa molar (Mᵤ) molar mass of carbon-12 massa molar do carbono-12 molar volume of ideal gas (273.15 K, 100 kPa) volume molar de gás ideal (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volume molar de gás ideal (273.15 K, 101.325 kPa) molar volume of silicon volume molar do silício Sackur-Tetrode constant (1 K, 100 kPa) constante de Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) constante de Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant constante da lei do deslocamento de frequência de Wien Wien wavelength displacement law constant constante da lei do deslocamento de comprimento de onda de Wien standard atmosphere (atm) atmosfera normal (atm) standard-state pressure (p°) pressão de estado padrão (p°) Angstrom star (Ã…*) Ã¥ngström estrela (Ã…*) Copper x unit unidade x do cobre Molybdenum x unit unidade x do molibdénio atomic unit of magnetizability unidade atómica de magnetizabilidade atomic unit of mass (mâ‚‘) unidade atómica de massa (mâ‚‘) atomic unit of momentum unidade atómica de momento atomic unit of permittivity unidade atómica de permitividade atomic unit of time unidade atómica de tempo atomic unit of velocity unidade atómica de velocidade hartree-hertz relationship relação hartree-hertz hartree-inverse meter relationship relação hartree-metro inverso hartree-joule relationship relação hartree-joule hartree-kelvin relationship relação hartree-kelvin hartree-kilogram relationship relação hartree-quilograma shielding difference of d and p in HD diferença de blindagem de d e p em HD shielding difference of t and p in HT diferença de blindagem de t e p em HT pi (Ï€) pi (Ï€) Euler's number (e) número de Euler (e) golden ratio (φ) razão áurea (φ) Euler-Mascheroni constant (γ) constante de Euler-Mascheroni (γ) nominal solar radius raio solar nominal nominal solar total irradiance irradiância solar total nominal nominal solar luminosity luminosidade solar nominal nominal solar effective temperature temperatura efetiva solar nominal nominal solar mass parameter parâmetro de massa solar nominal nominal terrestrial equatorial radius raio equatorial terrestre nominal nominal terrestrial polar radius raio polar terrestre nominal nominal terrestrial mass parameter parâmetro de massa terrestre nominal nominal jovian equatorial radius raio equatorial joviano nominal nominal jovian polar radius raio polar joviano nominal nominal jovian mass parameter parâmetro de massa joviano nominal average value of one minus the rate of TCG relative to TCB valor médio de um menos a taxa de TCG relativamente a TCB solar mass parameter (TCB-compatible) parâmetro de massa solar (compatível com TCB) solar mass parameter (TDB-compatible) parâmetro de massa solar (compatível com TDB) equatorial radius of the Earth (TT-compatible) raio equatorial da Terra (compatível com TT) dynamical form factor of the Earth fator de forma dinâmico da Terra time rate of change in the dynamical form factor of the Earth taxa temporal de variação do fator de forma dinâmico da Terra geocentric gravitational constant (TCB-compatible) constante gravitacional geocêntrica (compatível com TCB) geocentric gravitational constant (TT-compatible) constante gravitacional geocêntrica (compatível com TT) geocentric gravitational constant (TDB-compatible) constante gravitacional geocêntrica (compatível com TDB) potential of the geoid potencial do geoide nominal mean angular velocity of the Earth (TT-compatible) velocidade angular média nominal da Terra (compatível com TT) ratio mass of the Moon to the Earth razão entre a massa da Lua e a da Terra ratio of the mass of the Sun to Mercury razão entre a massa do Sol e a de Mercúrio ratio of the mass of the Sun to Venus razão entre a massa do Sol e a de Vénus ratio of the mass of the Sun to Mars razão entre a massa do Sol e a de Marte ratio of the mass of the Sun to Jupiter razão entre a massa do Sol e a de Júpiter ratio of the mass of the Sun to Saturn razão entre a massa do Sol e a de Saturno ratio of the mass of the Sun to Uranus razão entre a massa do Sol e a de Urano ratio of the mass of the Sun to Neptune razão entre a massa do Sol e a de Neptuno ratio of the mass of the Sun to (134340) Pluto razão entre a massa do Sol e a de (134340) Plutão ratio of the mass of the Sun to (136199) Eris razão entre a massa do Sol e a de (136199) Éris ratio of the mass of (1) Ceres to the Sun razão entre a massa de (1) Ceres e a do Sol ratio of the mass of (2) Pallas to the Sun razão entre a massa de (2) Pallas e a do Sol ratio of the mass of (4) Vesta to the Sun razão entre a massa de (4) Vesta e a do Sol mean obliquity of the ecliptic at J2000.0 obliquidade média da eclíptica em J2000.0 Electromagnetic Eletromagnetismo Compton wavelength comprimento de onda de Compton Astronomy Astronomia ConstantsWidget Domain Domínio Subdomain Subdomínio No match found Sem resultados Name Nome Value Valor Unit Unidade Search Procurar All Todas CustomKeypadDialog Custom Keypad Teclado numérico personalizado Rows: Linhas: Columns: Colunas: Copy preset: Copiar predefinição: Basic Básico Scientific (wide) Científico (largo) Scientific (narrow) Científico (estreito) Apply Aplicar Row Linha Column Coluna Label Etiqueta Behavior Comportamento Text Texto DiagnosticsDialog App Diagnostics Diagnóstico da aplicação Copy to Clipboard Copiar para a área de transferência Editor Unit Unidade User unit Unidade do utilizador User function Função do utilizador Argument Argumento Current result:<br/>%1 Resultado atual:<br/>%1 Selection result:<br/>%1 Resultado da seleção:<br/>%1 Selection result: n/a Resultado da seleção: n/d Selection result: %1 Resultado da seleção: %1 second segundo metre metro kilogram quilograma mole mole radian radiano steradian esterradiano degree Celsius grau Celsius cubic metre metro cúbico cubic millimetre milímetro cúbico cubic centimetre centímetro cúbico cubic decimetre decímetro cúbico cubic kilometre quilómetro cúbico square millimetre milímetro quadrado square kilometre quilómetro quadrado square metre metro quadrado minute minuto hour hora day dia astronomical unit unidade astronómica degree grau arcminute minuto de arco arcsecond segundo de arco milliarcsecond milissegundo de arco microarcsecond microssegundo de arco hectare hectare litre litro tonne tonelada Dalton Dalton electronvolt eletrão-volt Angstrom Ã¥ngström atmosphere atmosfera atomic mass unit unidade de massa atómica British thermal unit unidade térmica britânica calorie caloria carat quilate cup chávena cup (Imperial) chávena (imperial) cup (Japanese) chávena (japonesa) cup (US) chávena (EUA) degree Fahrenheit grau Fahrenheit fathom braça fluid ounce (Imperial) onça fluida (imperial) fluid ounce (US) onça fluida (EUA) fluid dram (Imperial) dracma fluida (imperial) fluid dram (US) dracma fluida (EUA) foot pé square foot pé quadrado cubic foot pé cúbico gallon (Imperial) galão (imperial) gallon (US) galão (EUA) gill (Imperial) gill (imperial) gill (US) gill (EUA) gradian grado grain grão gram grama Hartley Hartley Hartree energy unit unidade de energia Hartree horsepower cavalo-vapor inch polegada square inch polegada quadrada cubic inch polegada cúbica karat quilate knot nó lightminute minuto-luz lightsecond segundo-luz lightyear ano-luz long ton tonelada longa mile milha square mile milha quadrada cubic mile milha cúbica mile per hour milha por hora kilometre per hour quilómetro por hora nautical mile milha náutica ounce onça parsec parsec pint (Imperial) pinta (imperial) pint (US) pinta (EUA) pound libra pounds per square inch libras por polegada quadrada quart (Imperial) quarto (imperial) quart (US) quarto (EUA) oil barrel barril de petróleo beer barrel (US) barril de cerveja (EUA) square yard jarda quadrada cubic yard jarda cúbica short ton tonelada curta tablespoon colher de sopa tablespoon (Australian) colher de sopa (australiana) tablespoon (Imperial) colher de sopa (imperial) tablespoon (US) colher de sopa (EUA) dessert spoon colher de sobremesa teaspoon colher de chá teaspoon (Imperial) colher de chá (imperial) teaspoon (US) colher de chá (EUA) turn volta revolution revolução revolution per minute revolução por minuto week semana kilowatt hour quilowatt-hora millimetre of mercury milímetro de mercúrio yard jarda Julian century século juliano Julian year ano juliano sidereal year ano sideral tropical year ano tropical Evaluator invalid expression expressão inválida division by zero divisão por zero too time consuming - computation was rejected demasiado demorado - o cálculo foi rejeitado dimension mismatch - quantities with different dimensions cannot be compared, added, etc. incompatibilidade de dimensão - quantidades com diferentes dimensões não podem ser comparadas, somadas, etc. invalid dimension - operation might require dimensionless arguments dimensão inválida - a operação pode exigir argumentos adimensionais Computation aborted - encountered numerical instability cálculo abortado - encontrada instabilidade numérica invalid dimension - function might require dimensionless arguments dimensão inválida - a função pode exigir argumentos adimensionais error erro unit must not be zero a unidade não pode ser zero Conversion failed - dimension mismatch Falha na conversão - incompatibilidade de dimensão unknown function or variable função ou variável desconhecida recursion not supported recursividade não suportada cannot operate on a NaN não é possível operar sobre NaN underflow - tiny result is out of SpeedCrunch's number range underflow - resultado muito pequeno para o intervalo numérico do SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflow - resultado muito grande para o intervalo numérico do SpeedCrunch overflow - logic result exceeds maximum of 256 bits overflow - resultado lógico excede máximo de 256 bits overflow - integer result exceeds maximum limit for integers overflow - resultado inteiro excede limite máximo para inteiros operation is not defined for these arguments a operação não está definida para estes argumentos wrong number of arguments número errado de argumentos does not take NaN as an argument não aceita NaN como argumento result out of range resultado fora do intervalo undefined for argument domain indefinido no domínio do argumento computation too expensive cálculo demasiado dispendioso internal error, please report a bug erro interno, por favor reporte o problema syntax error erro de sintaxe conversion target must be a unit o destino da conversão tem de ser uma unidade unknown unit unidade desconhecida %1 is a reserved name, please choose another %1 é um nome reservado, por favor escolha outro %1 is a global user definition and cannot be overridden in this session. %1 é uma definição global do utilizador e não pode ser substituída nesta sessão. %1 is a variable name, please choose another or delete the variable %1 é um nome de variável, por favor escolha outro nome ou apague a variável argument %1 is used more than once argumento %1 utilizado mais do que uma vez %1 is a built-in unit name, please choose another %1 é o nome de uma unidade incorporada; escolha outro %1 is a user function name, please choose another or delete the function %1 é um nome de uma função de utilizador, por favor escolha outro nome ou apague a função FunctionRepo max; trials; probability máx; tentativas; probabilidade trials; probability tentativas; probabilidade hits; trials; probability sucessos; tentativas; probabilidade max; total; hits; trials máx; total; sucessos; tentativas total; hits; trials total; sucessos; tentativas count; total; hits; trials contagem; total; sucessos; tentativas dividend; divisor dividendo; divisor x; exponent_bits; significand_bits [; exponent_bias] x; bits_do_expoente; bits_do_significando [; desvio_do_expoente] base; x base; x value; modulo valor; módulo base; exponent; modulo base; expoente; módulo events; average_events eventos; média_eventos average_events média_eventos x [; precision] x [; precisão] Absolute Value Valor absoluto Absolute Deviation Desvio absoluto Arc Cosine Arco de cosseno Logical AND E lógico Area Hyperbolic Cosine Cosseno hiperbólico inverso Area Hyperbolic Sine Seno hiperbólico inverso Area Hyperbolic Tangent Tangente hiperbólica inversa Arc Sine Arco de seno Arc Tangent Arco de tangente Arc Tangent with two Arguments Arco de tangente com dois argumentos Average (Arithmetic Mean) Média (aritmética) Binomial Cumulative Distribution Function Função de distribuição binomial cumulativa Binomial Distribution Mean Média da distribuição binomial Binomial Probability Mass Function Função massa de probabilidade binomial Binomial Distribution Variance Variância da distribuição binomial Cube Root Raiz cúbica Complex Conjugate Complexo conjugado Cosine Cosseno Hyperbolic Cosine Cosseno hiperbólico Cotangent Cotangente Cosecant Cosecante Convert Unix timestamp to Date Converter marcas temporais Unix para data Degrees of Arc Graus de arco Error Function Função de erro Complementary Error Function Função de erro complementar Exponential Exponencial Fractional Part Parte fracionária Extension of Factorials [= (x-1)!] Extensão do fatorial [= (x-1)!] Greatest Common Divisor Máximo divisor comum Geometric Mean Média geométrica Gradians of arc Gradianos de arco Hypergeometric Cumulative Distribution Function Função de distribuição hipergeométrica cumulativa Hypergeometric Distribution Mean Média da distribuição hipergeométrica Hypergeometric Probability Mass Function Função massa de probabilidade hipergeométrica Hypergeometric Distribution Variance Variância da distribuição hipergeométrica Integer Quotient Quociente inteiro Integer Part Parte inteira Imaginary Part Parte imaginária Decode IEEE-754 Binary Value Descodificar valor binário IEEE-754 Encode IEEE-754 Binary Value Codificar valor binário IEEE-754 Decode 16-bit Half-Precision Value Descodificar valor de meia precisão de 16 bits Encode 16-bit Half-Precision Value Codificar valor de meia precisão de 16 bits Decode 32-bit Single-Precision Value Descodificar valor de precisão simples de 32 bits Encode 32-bit Single-Precision Value Codificar valor de precisão simples de 32 bits Decode 64-bit Double-Precision Value Descodificar valor de precisão dupla de 64 bits Encode 64-bit Double-Precision Value Codificar valor de precisão dupla de 64 bits Decode 128-bit Quad-Precision Value Descodificar valor de precisão quádrupla de 128 bits Encode 128-bit Quad-Precision Value Codificar valor de precisão quádrupla de 128 bits Binary Logarithm Logaritmo binário Common Logarithm Logaritmo comum Natural Logarithm Logaritmo natural Logarithm to Arbitrary Base Logaritmo de base arbitrária Mask to a bit size Mascarar com número de bits Maximum Máximo Median Value (50th Percentile) Mediana (percentil 50) Minimum Mínimo Modulo Módulo Euclidean Modulo Módulo euclidiano Modular Exponentiation Exponenciação modular Combination (Binomial Coefficient) Combinação (coeficiente binomial) Logical NOT NÃO lógico Permutation (Arrangement) Permutação (arranjo) Convert to Binary Representation Converter para representação binária Arithmetic Aritmética Chemistry Química Complex Complexos Combinatorics Combinatória Probability Probabilidade Statistics Estatística Aggregation Agregação Random Aleatório Base conversion Conversão de base Number formatting Formatação de números Integer arithmetic Aritmética de inteiros Special functions Funções especiais Exponential & Logarithmic Exponenciais e logarítmicas Angle conversion Conversão de ângulos Trigonometry Trigonometria Bitwise Operações bit a bit Floating point Vírgula flutuante Date & Time Data e hora Linear algebra Ã�lgebra linear unix_timestamp; x hours offset to GMT unix_timestamp; deslocamento de x horas para GMT yyyymmdd.hhmmss; x hours offset to GMT aaaammdd.hhmmss; deslocamento de x horas em relação a GMT [digits] [dígitos] max [; min] máx [; mín] List Literal Literal de lista Convert to Padded Binary Representation Converter para representação binária preenchida Round Toward +∞ (Ceiling) Arredondar para +∞ (teto) Cosine plus Imaginary Sine Cosseno mais seno imaginário Convert to Cis Complex Form Converter para forma complexa cis Matrix Column Count Número de colunas da matriz Population Correlation Matrix (n) Matriz de correlação populacional (n) Sample Correlation Matrix (n-1) Matriz de correlação amostral (n-1) Count Contagem Population Covariance Matrix (n) Matriz de covariância populacional (n) Sample Covariance Matrix (n-1) Matriz de covariância amostral (n-1) Cross Product Produto vetorial Convert Date to Unix timestamp Converter data para carimbo temporal Unix Convert to Decimal Representation Converter para representação decimal Determinant Determinante Convert to Sexagesimal Notation Converter para notação sexagesimal Dot Product Produto escalar Convert to Engineering Notation Converter para notação de engenharia Convert to Exponential Complex Form Converter para forma complexa exponencial Round Toward −∞ (Floor) Arredondar para −∞ (piso) Flatten Matrix Achatar matriz Least Common Multiple Mínimo múltiplo comum Convert to Hexadecimal Representation Converter para representação hexadecimal Convert to Padded Hexadecimal Representation Converter para representação hexadecimal preenchida Inverse Matrix Matriz inversa Round to 16-bit Half-Precision Value Arredondar para valor de meia precisão de 16 bits Round to 32-bit Single-Precision Value Arredondar para valor de precisão simples de 32 bits Round to 64-bit Double-Precision Value Arredondar para valor de precisão dupla de 64 bits Round to 128-bit Quad-Precision Value Arredondar para valor de precisão quádrupla de 128 bits Residual from 16-bit Half-Precision Rounding Resíduo do arredondamento de meia precisão de 16 bits Residual from 32-bit Single-Precision Rounding Resíduo do arredondamento de precisão simples de 32 bits Residual from 64-bit Double-Precision Rounding Resíduo do arredondamento de precisão dupla de 64 bits Residual from 128-bit Quad-Precision Rounding Resíduo do arredondamento de precisão quádrupla de 128 bits Substance Mass Massa da substância Molarity Molaridade Molar Mass Massa molar Median Absolute Deviation Desvio absoluto mediano Mean Média Numerical Value of Quantity Valor numérico da quantidade Random Decimal Number Número decimal aleatório Random Integer Number Número inteiro aleatório Convert to Rational Representation Converter para representação racional Convert to Octal Representation Converter para representação octal Convert to Padded Octal Representation Converter para representação octal preenchida Vector or Matrix Norm Norma de vetor ou matriz Logical OR OU lógico Population Count (Hamming Weight) Contagem de população (peso de Hamming) Phase of Complex Number Fase do número complexo Poissonian Cumulative Distribution Function Função de distribuição acumulada de Poisson Poissonian Distribution Mean Média da distribuição de Poisson Poissonian Probability Mass Function Função de massa de probabilidade de Poisson Poissonian Distribution Variance Variância da distribuição de Poisson Convert to Phasor Complex Form Converter para forma complexa fasorial Convert to Rectangular Complex Form Converter para forma complexa retangular Round Half Away from Zero Arredondar metade para longe de zero Round Half Even Arredondar metade para par Nth Root Raiz enésima Convert to Scientific Notation Converter para notação científica Matrix Row Count Número de linhas da matriz List or Matrix Shape Forma de lista ou matriz Summation Somatório Population Standard Deviation (n) Desvio-padrão populacional (n) Sample Standard Deviation (n-1) Desvio-padrão amostral (n-1) Round Toward Zero (Truncation) Arredondar para zero (truncagem) Matrix Trace Traço da matriz Transpose Matrix Transpor matriz Population Variance (n) Variância populacional (n) Sample Variance (n-1) Variância amostral (n-1) Product Produto Radians Radianos Matrix Rank Posto da matriz Real Part Parte real Secant Secante Arithmetic Shift Left Deslocamento aritmético para a esquerda Arithmetic Shift Right Deslocamento aritmético para a direita Signum Sinal Sine Seno Hyperbolic Sine Seno hiperbólico Square Root Raiz quadrada Sum Soma Tangent Tangente Convert to Trigonometric Complex Form Converter para forma complexa trigonométrica Turns Voltas Hyperbolic Tangent Tangente hiperbólica Sign-extend a value Aumentar número de bits mantendo o sinal Logical XOR XOU lógico FunctionsWidget Domain Domínio All Tudo Name Nome Search Pesquisar No match found Sem resultados Identifier Identificador HistoryWidget Remove All Calculations Above Remover todos os cálculos acima Remove This Calculation Remover este cálculo Remove All Calculations Below Remover todos os cálculos abaixo Keypad Inverse cosine Arco de cosseno The last result Último resultado Inverse sine Arco de seno Inverse tangent Arco de tangente Evaluate expression Calcular expressão Division Divisão Multiplication Multiplicação Subtraction Subtração Addition Adição Clear expression Limpar expressão Cosine Cosseno Backspace Retrocesso Scientific notation Notação científica Exponential Exponencial Factorial Fatorial Natural logarithm Logaritmo natural Left parenthesis Parêntese esquerdo Nth root Raiz enésima Argument separator Separador de argumentos Square Quadrado Common logarithm Logaritmo comum Modulo Módulo Contextual percentage Percentagem contextual Power Potência Right parenthesis Parêntese direito Sine Seno Square root Raiz quadrada Tangent Tangente Pi Pi Decimal separator Separador decimal MainWindow Radian Radiano Degree Grau Gradian Gradiano Binary Binário Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Engineering decimal Decimal de engenharia Scientific decimal Decimal científico &Import... &Importar... &Quit &Sair Clear E&xpression Limpar e&xpressão Clear &History Limpar &histórico &Copy &Copiar &Paste Co&lar &Select Expression &Selecionar expressão &Constants &Constantes &Functions &Funções &History &Histórico &Status Bar Barra de e&stado Bitfield Campo de bits Use&r Functions Funções de &utilizador &Degree &Grau &Radian &Radiano &Gradian &Gradiano Re&volution R&evolução Auto-Insert a&ns I&nserir ans automaticamente Automatic &Completion &Conclusão automática &Built-in Functions &Funções incorporadas Built-in &Variables &Variáveis incorporadas User &Functions Fu&nções do utilizador User Va&riables Va&riáveis do utilizador Open a Private Tab on Startup Abrir um separador privado ao iniciar Open and focus a new private tab whenever SpeedCrunch starts. Abrir e ativar um novo separador privado sempre que o SpeedCrunch iniciar. Syntax &Highlighting Realce de &sintaxe Group Digits in &Input Agrupar díg&itos na introdução Automatic Input &Adjustments &Ajustes automáticos da introdução Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ajustar automaticamente operadores, espaçamento, parênteses e potências, e limitar a introdução a carateres válidos. Group input digits using the selected number format. Agrupar os dígitos introduzidos segundo o formato numérico selecionado. &Blinking Cursor &Cursor intermitente Blink the cursor in the expression editor. Fazer piscar o cursor no editor de expressões. &Escape Clears Editor &Escape limpa o editor Clear the focused expression editor with Escape after dismissing any popup or preview. Limpar o editor de expressões ativo com Escape depois de fechar qualquer janela de contexto ou pré-visualização. Keep Expression After Evaluation Manter a expressão após o cálculo Copy New Results Automatically Copiar automaticamente novos resultados &Comma &Vírgula &System Default Predefinição do &sistema &Dot &Ponto Dot &And Comma Ponto e vírgul&a Toward +∞ (&ceil) Em direção a +∞ (&ceil) Toward −∞ (&floor) Em direção a −∞ (&floor) &Binary &Binário &Engineering &Engenharia &Hexadecimal &Hexadecimal &Octal &Octal &Scientific &Científico User &Manual Manual do &utilizador Issues and &Feedback &Problemas e sugestões &Donate &Donativos &About SpeedCrunch A&cerca do SpeedCrunch App Diag&nostics Diag&nóstico da aplicação S&plit &Dividir Angle &Mode &Modo angular &Complex Form Forma &complexa New Tab Novo separador Constants Constantes Functions Funções History Histórico User Functions Funções do utilizador &Font... &Tipo de letra... &Language... &Idioma... &Session &Sessão &Edit &Editar &View &Ver Se&ttings &Definições &Decimal &Decimal &Keypad &Teclado virtual Always on &Top Sempre na fren&te Disabled Desativado Small Space Espaço pequeno Medium Space Espaço médio Large Space Espaço grande &0 Digits &0 dígitos &15 Digits &15 dígitos &2 Digits &2 dígitos &3 Digits &3 dígitos &50 Digits &50 dígitos &8 Digits &8 dígitos &Sexagesimal &Sexagesimal Reset All Settings... Repor todas as definições... &System &Sistema SpeedCrunch &Theme &Tema do SpeedCrunch &Classic &Clássico &Modern &Moderno Context Help Ajuda de contexto &Help &Ajuda Error Erro Can't read from file %1 Erro ao ler do ficheiro %1 Import Session Importar sessão Close Session Fechar sessão Angle Mode: Modo de ângulo: Notation: Notação: Precision: Precisão: Turn Volta Revolution Revolução Fixed-point decimal Decimal de vírgula fixa Rational Racional Automatic decimal Decimal automático Automatic Automático User &Definitions... &Definições do utilizador... New &Tab Novo &separador New &Private Tab &Novo separador privado Keep Manter Make Private... Tornar privada... New &Window Nova &janela &Open... &Abrir... &Rename... Muda&r o nome... Clo&ne... &Clonar... &Close Tab &Fechar separador Reopen Clo&sed Tab Rea&brir separador fechado Open Sessions &Folder Abrir &pasta de sessões &Undo An&ular &Redo &Refazer Cu&t Cor&tar Copy &Last Result C&opiar o último resultado &Wrap in Parentheses Coloc&ar entre parênteses Full Scr&een Mode Modo d&e ecrã inteiro &Basic &Básico &Scientific (wide) &Científico (largo) Scientific (narrow) Científico (estreito) &Custom... &Personalizado... Main &Menu &Menu principal User &Variables &Variáveis do utilizador &Left &Esquerda &Right Di&reita &Up &Cima &Down &Baixo Close Pa&ne Fechar pai&nel User &Units &Unidades do utilizador &Turn &Volta If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Se uma nova expressão começar por +, -, * ou /, o SpeedCrunch insere primeiro "ans". &Accept with Enter &Aceitar com Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Aceitar a sugestão atual de conclusão automática com Enter sem a selecionar primeiro com as teclas de direção. &Units &Unidades Show Live Result &Preview Mostrar &pré-visualização do resultado em direto Save &Window Position on Exit Guardar posição da &janela ao sair Hover Highlighting Realce ao passar o rato Group Integer Part Only Agrupar apenas a parte inteira Number Format... Formato do número... Notation && Precision... Notação e precisão... After pressing Enter, keep the entered expression selected in the editor. Depois de premir Enter, manter a expressão introduzida selecionada no editor. Never Nunca Always Sempre Only for Single-Line Expressions Apenas para expressões de uma linha Simplify Displayed Expressions Simplificar expressões apresentadas History Size &Limit... &Limite do tamanho do histórico... Remove Trailing &Zeroes Remover &zeros finais Nearest, Half &Away (round) Mais próximo, metade para &longe (round) Nearest, Half &Even (roundeven) Mais próximo, metade para &par (roundeven) Toward &Zero (trunc) Para &zero (trunc) &Fixed-Point &Vírgula fixa &Rational &Racional &Exponential (m·sâ�»Â¹) &Exponencial (m·sâ�»Â¹) &Fractional (m/s) &Fracionária (m/s) &Rectangular (a + bi) &Retangular (a + bi) Exponential (reâ�±á¶¿) Exponencial (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonométrica (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Tema... Check for &Updates Procurar &atualizações Source Code Código-fonte &Zoom &Zoom &Results &Resultados Unit Notation Notação de unidades Rounding Mode Modo de arredondamento &Notation &Notação &Imaginary Unit Unidade &imaginária &Window &Janela &Editing &Edição A&utocomplete A&utocompletar Up/Down Arrow History Histórico com setas para cima/baixo &Appearance &Aparência &Menus &Menus &Docks &Painéis acopláveis &Input and Results &Introdução e resultados &Disabled &Desativado &Disable &Desativar Close preview Fechar pré-visualização Rename... Mudar o nome... Clone... Clonar... Close Tab Fechar separador New Private Tab Novo separador privado Open... Abrir... Reopen Closed Tab Reabrir separador fechado Split Dividir Left Esquerda Right Direita Up Cima Down Baixo Clear Limpar Delete Apagar %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sessão privada: o conteúdo é descartado ao fechar. Escolha Sessão > Manter para a tornar numa sessão normal. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privada] Reset All Settings Repor todas as definições Reset all settings to their default values? Repor os valores predefinidos de todas as definições? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Isto inclui a aparência, a edição, os formatos dos resultados e as preferências das janelas. Os cálculos, as sessões abertas e as definições do utilizador serão mantidos. The settings file could not be written. Não foi possível escrever o ficheiro de definições. Clear this session's calculations, unfinished expression, variables, functions, and units? Limpar os cálculos, a expressão inacabada, as variáveis, as funções e as unidades desta sessão? Global user definitions are kept. As definições globais do utilizador são mantidas. Make Session Private Tornar a sessão privada The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. A sessão guardada %1 será apagada. O conteúdo continuará aberto numa sessão privada e será descartado quando essa sessão for fechada ou o SpeedCrunch terminar. Make Private Tornar privada Could not delete the saved session %1. Não foi possível apagar a sessão guardada %1. Keep Session Manter sessão Could not save the session. It remains private. Não foi possível guardar a sessão. Continua privada. Clone Session Clonar sessão Could not save session file %1. Não foi possível guardar o ficheiro de sessão %1. Could not delete session file %1. Não foi possível apagar o ficheiro de sessão %1. JSON file (*.json);;Any file (*.*) Ficheiro JSON (*.json);;Qualquer ficheiro (*.*) Export session as JSON Exportar sessão como JSON The selected file is not valid JSON: %1 O ficheiro selecionado não é JSON válido: %1 The selected file is not a SpeedCrunch session JSON file. O ficheiro selecionado não é um ficheiro JSON de sessão do SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Este ficheiro usa um formato de sessão do SpeedCrunch obsoleto e não pode ser importado. The selected JSON file is missing the required $schema field. O ficheiro JSON selecionado não contém o campo obrigatório $schema. The selected JSON file uses an unsupported JSON schema: %1 O ficheiro JSON selecionado usa um esquema JSON não suportado: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). O ficheiro JSON selecionado não contém o identificador de esquema de sessão do SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 O ficheiro JSON selecionado usa um formato de sessão do SpeedCrunch não suportado: %1 The selected JSON file is missing the required session name. O ficheiro JSON selecionado não contém o nome de sessão obrigatório. The selected JSON file has an empty session name. O ficheiro JSON selecionado tem um nome de sessão vazio. The selected JSON file has invalid or incomplete SpeedCrunch session data. O ficheiro JSON selecionado contém dados de sessão do SpeedCrunch inválidos ou incompletos. Open Sessions Folder Abrir pasta de sessões Could not create the sessions folder: %1 Não foi possível criar a pasta de sessões: %1 Could not open the sessions folder: %1 Não foi possível abrir a pasta de sessões: %1 Editor and Results Font Tipo de letra do editor e dos resultados Open Session Abrir sessão Community Comunidade Rename Session Mudar nome da sessão Clear Session Limpar sessão Delete Session Apagar sessão Close Pane Fechar painel User Variables Variáveis do utilizador User Units Unidades do utilizador Clear History Limpar histórico Are you sure you want to clear the calculation history? Tem a certeza de que pretende limpar o histórico de cálculos? Session name: Nome da sessão: A session named %1 already exists. Já existe uma sessão chamada %1. Could not create session file %1. Não foi possível criar o ficheiro de sessão %1. Could not write session file %1. Não foi possível escrever o ficheiro de sessão %1. Are you sure you want to delete this session? Tem a certeza de que pretende apagar esta sessão? Custom Precision Precisão personalizada Fractional digits: Dígitos fracionários: Theme Tema Light Themes Temas claros Dark Themes Temas escuros Preview Pré-visualização Colors Cores Select color for %1 Selecionar cor para %1 Import... Importar... Export... Exportar... Import Theme Importar tema Theme file (*.json);;All files (*) Ficheiro de tema (*.json);;Todos os ficheiros (*) Invalid theme file. Ficheiro de tema inválido. Can't import theme "%1" because it conflicts with a built-in theme. Não é possível importar o tema "%1" porque entra em conflito com um tema incorporado. Can't find a writable theme folder. Não é possível encontrar uma pasta de temas gravável. Overwrite Theme Substituir tema A custom theme named "%1" already exists. Do you want to overwrite it? Já existe um tema personalizado chamado "%1". Pretende substituí-lo? Can't overwrite theme file %1 Não é possível substituir o ficheiro de tema %1 Can't copy theme file to %1 Não é possível copiar o ficheiro de tema para %1 Export Theme Exportar tema Can't export theme as "%1" because it conflicts with a built-in theme. Não é possível exportar o tema como "%1" porque entra em conflito com um tema incorporado. Can't write to file %1 Erro ao escrever o ficheiro %1 Global User Variable Variável global do utilizador Global User Function Função global do utilizador Global User Unit Unidade global do utilizador User Definitions Definições do utilizador These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Estas definições são globais e são carregadas em todas as sessões. Não podem ser alteradas nas sessões e têm prioridade sobre as definições com o mesmo nome do editor da sessão. Introduza uma definição por linha. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Exemplos: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Aplicar Validate Validar Test Results Resultados do teste Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variáveis importadas: %1 Funções importadas: %2 Unidades importadas: %3 Números das linhas com erros: %4 none nenhum Apply Results Resultados da aplicação User definitions saved. Definições do utilizador guardadas. History Size Limit Limite do tamanho do histórico Maximum number of history entries for this session (0 = unlimited): Número máximo de entradas de histórico para esta sessão (0 = ilimitado): Text file (*.txt);;Any file (*.*) Ficheiro de texto (*.txt);;Todos os ficheiros (*.*) Could not recalculate from calculation %1: %2 Não foi possível recalcular a partir do cálculo %1: %2 History Size Limit Reached Limite do tamanho do histórico atingido This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Este cálculo preenche o último espaço disponível do histórico. Cálculos futuros removerão o cálculo mais antigo do histórico. Pode aumentar o limite em Sessão > Limite do tamanho do histórico. Editing calculation. Press Esc twice to cancel. A editar cálculo. Prima Esc duas vezes para cancelar. Calculation Settings Definições de cálculo Invalid recalculation start index Ã�ndice inicial de recálculo inválido System Default Predefinição do sistema Language Idioma Select the language: Selecione o idioma: Custom Personalizado Decimal places: Casas decimais: &Automatic &Automático &Precision &Precisão Plain &text &Texto simples Formula &Book Livro de &fórmulas &Export &Exportar Export session as HTML Exportar sessão como HTML HTML file (*.html) Ficheiro HTML (*.html) Export session as plain text Exportar sessão como texto simples ManualWindow SpeedCrunch Manual Manual do SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual do SpeedCrunch NumberFormatDialog Number Format Formato do número <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Selecione o formato numérico dos resultados e do agrupamento de dígitos introduzidos.</b><br/><br/>Nota: os números introduzidos em formatos inequívocos são aceites mesmo que sejam diferentes do formato de apresentação selecionado.<br/> QObject Global User Variable Variável global do utilizador Global User Function Função global do utilizador Global User Unit Unidade global do utilizador Backspace Retrocesso Clear expression Limpar expressão Evaluate expression Calcular expressão Insert text Inserir texto Automatic decimal Decimal automático Fixed-point decimal Decimal de vírgula fixa Engineering decimal Decimal de engenharia Scientific decimal Decimal científico Rational Racional Binary Binário Octal Octal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Update Available Atualização disponível A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Está disponível uma versão mais recente (%1).<br/><a href="%2">Visite o site para descarregar.</a> Check for Updates Procurar atualizações SpeedCrunch %1 is up to date. O SpeedCrunch %1 está atualizado. No connectivity. Please check your internet connection and try again. Sem ligação. Verifique a ligação à Internet e tente novamente. Could not verify the latest available version. Não foi possível verificar a versão mais recente disponível. ResultDisplay Scroll to bottom Deslocar para o fim Edit Expression Editar expressão Change Settings Alterar definições New Tab Novo separador &Import... &Importar... &Export &Exportar Plain &text &Texto simples Copy Copiar Selection Seleção Select All Selecionar tudo Expression Expressão Result Resultado Calculation Cálculo Calculation as Single Line Cálculo numa só linha Remove Remover This Calculation Este cálculo All Calculations Above Todos os cálculos acima All Calculations Below Todos os cálculos abaixo New Private Tab Novo separador privado Session Sessão Open... Abrir... Clone... Clonar... Rename... Mudar o nome... Keep Manter Make Private... Tornar privada... Clear Limpar Delete Apagar Close Fechar Split Dividir Left Esquerda Right Direita Up Cima Down Baixo Close Pane Fechar painel Main Menu Menu principal Cancel editing Cancelar edição Copy result Copiar resultado Edit expression Editar expressão Change settings Alterar definições Remove calculation Remover cálculo ResultSlotsDialog Notation & Precision Notação e precisão Result Line Linha do resultado Enabled Ativado Notation Notação Decimal Places Casas decimais Main Line Linha principal Extra Line #1 Linha extra n.º 1 Extra Line #2 Linha extra n.º 2 Extra Line #3 Linha extra n.º 3 Extra Line #4 Linha extra n.º 4 Auto Automático UserFunctionListWidget Name Nome Value Valor Description Descrição Search Pesquisar No match found Sem resultados Insert Inserir Edit Editar Delete Apagar Delete All Apagar tudo UserUnitListWidget Name Nome Value Valor Description Descrição Search Pesquisar No match found Sem resultados Insert Inserir Edit Editar Delete Apagar Delete All Apagar tudo VariableListWidget Name Nome Value Valor Description Descrição Search Procurar No match found Sem resultados Insert Inserir Edit Editar Delete Apagar Delete All Apagar tudo heldercorreia-speedcrunch-e7ca37f/src/resources/locale/ro.ts000066400000000000000000010560471526573132500244020ustar00rootroot00000000000000 AboutBox About SpeedCrunch Despre SpeedCrunch Core developers Dezvoltatori principali Original author Autor original Close ÃŽnchide Math engine Motor matematic Main author | Logo | Maintainer Autor principal | Logo | Responsabil întreÈ›inere Thanks MulÈ›umiri Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 Dezvoltatorii SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Acest program este software liber; îl puteÈ›i redistribui È™i/sau modifica în conformitate cu termenii LicenÈ›ei Publice Generale GNU, aÈ™a cum este publicată de Free Software Foundation; fie versiunea 2 a LicenÈ›ei, fie (la alegerea dumneavoastră) orice versiune ulterioară This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Acest program este distribuit cu speranÈ›a că va fi util, dar FÄ‚RÄ‚ NICIO GARANÈšIE; nici măcar garanÈ›ia implicită de VANDABILITATE sau ADECVARE PENTRU UN ANUMIT SCOP. ConsultaÈ›i LicenÈ›a Publică Generală GNU pentru mai multe detalii. BitFieldWidget Reset bits to zero Resetează biÈ›ii la zero Invert bits Inversează biÈ›ii Shift bits left Deplasează biÈ›ii la stânga Shift bits right Deplasează biÈ›ii la dreapta Book Index Index Algebra Algebră Quadratic Equation EcuaÈ›ie de gradul 2 Logarithmic Base Conversion Conversia bazei logaritmului Geometry Geometrie Circle Cerc Sector Sector Sphere Sferă Cube Cub Cone Con Cylinder Cilindru Electronics Electronică Ohm's Law Legea lui Ohm Power Putere Reactance Reactanță Resonance Rezonanță Radio Frequency Frecvență radio Antennas Antene Characteristic Impedance (coax) Impedanță caracteristică (coaxial) Velocity of Propagation (coax) Viteză de propagare (coaxial) Standing Wave Ratio & Return Loss Raport de unde staÈ›ionare È™i pierdere prin reflexie Free Space Wavelength Lungimea de undă în spaÈ›iul liber resistance rezistență voltage tensiune current curent power putere inductive reactance reactanță inductivă capacitive reactance reactanță capacitivă inductance inductanță capacitance capacitanță frequency frecvență resonance frequency frecvență de rezonanță area arie perimeter perimetru diameter diametru radius rază volume volum surface area suprafață height înălÈ›ime slant height înălÈ›ime înclinată face diagonal diagonală a unei feÈ›e space diagonal diagonală spaÈ›ială edge length lungime a unei muchii arc length lungime de arc central angle (degrees) unghi central (grade) input power putere de intrare reflected power putere reflectată transmitted power putere transmisă return loss pierdere prin reflexie dielectric constant constanta dielectrică outer conductor's inner diameter diametrul interior al conductorului exterior inner conductor's outer diameter diametrul exterior al conductorului interior speed of light viteza luminii reflection coefficient coeficientul de reflecÈ›ie standing wave ratio raportul de undă staÈ›ionară normalized impedance impedanță normalizată frequency (Hz) frecvență (Hz) BookDock Formula Book Carte de formule ConstantCompletion Search constants Caută constante No match found Nu s-a găsit niciun rezultat Constants Mathematics Matematică Physics (CODATA 2022) Fizică (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chimie (IUPAC - CIAAW 2021) Uncategorized Necategorizat Universal Universale Physicochemical Fizico-chimice Atomic & Nuclear — General Atomic È™i nuclear — generale Atomic & Nuclear — Electroweak Atomic È™i nuclear — electroslabe Atomic & Nuclear — Electron Atomic È™i nuclear — electron Atomic & Nuclear — Muon Atomic È™i nuclear — miuon Atomic & Nuclear — Tau Atomic È™i nuclear — tau Atomic & Nuclear — Proton Atomic È™i nuclear — proton Atomic & Nuclear — Neutron Atomic È™i nuclear — neutron Atomic & Nuclear — Deuteron Atomic È™i nuclear — deuteron Atomic & Nuclear — Triton Atomic È™i nuclear — triton Atomic & Nuclear — Helion Atomic È™i nuclear — helion Atomic & Nuclear — Alpha particle Atomic È™i nuclear — particulă alfa Atomic & Nuclear — Atomic units Atomic È™i nuclear — unități atomice Atomic & Nuclear — Energy conversion relationships Atomic È™i nuclear — relaÈ›ii de conversie a energiei Atomic & Nuclear — X-ray units Atomic È™i nuclear — unități de raze X Atomic & Nuclear — Magnetic shielding corrections Atomic È™i nuclear — corecÈ›ii de ecranare magnetică Masses Mase Lifetimes Durate de viață Molar Masses Mase molare Electronegativity Electronegativitate Ionization Energy Energie de ionizare Nominal Constants (IAU 2015) Constante nominale (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Cele mai bune estimări curente (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) impedanÈ›a caracteristică a vidului (Zâ‚€) reduced Planck constant (â„�) constanta Planck redusă (â„�) vacuum electric permittivity (ϵ₀) permitivitatea electrică a vidului (ϵ₀) Newtonian constant of gravitation (G) constanta gravitaÈ›ională newtoniană (G) vacuum magnetic permeability (μ₀) permeabilitatea magnetică a vidului (μ₀) Planck constant (h) constanta Planck (h) speed of light in vacuum (c) viteza luminii în vid (c) standard acceleration of gravity (gâ‚™) acceleraÈ›ia gravitaÈ›ională standard (gâ‚™) Newtonian constant of gravitation over h-bar c constanta gravitaÈ›ională newtoniană împărÈ›ită la h-bar c Planck length lungimea Planck Planck constant in eV/Hz (h) constanta Planck în eV/Hz (h) Planck mass masa Planck Planck mass energy equivalent in GeV echivalentul energetic al masei Planck în GeV Planck temperature temperatura Planck Planck time timpul Planck reduced Planck constant in eV·s (â„�) constanta Planck redusă în eV·s (â„�) reduced Planck constant times c in MeV·fm constanta Planck redusă înmulÈ›ită cu c în MeV·fm Bohr magneton magnetonul Bohr conductance quantum (Gâ‚€) cuanta de conductanță (Gâ‚€) Coulomb constant (kâ‚‘) constanta Coulomb (kâ‚‘) elementary charge (e) sarcina elementară (e) elementary charge over h-bar sarcina elementară împărÈ›ită la h-bar conventional value of Josephson constant valoarea convenÈ›ională a constantei Josephson Josephson constant constanta Josephson conventional value of ampere-90 valoarea convenÈ›ională a amperului-90 conventional value of coulomb-90 valoarea convenÈ›ională a coulombului-90 conventional value of farad-90 valoarea convenÈ›ională a faradului-90 conventional value of henry-90 valoarea convenÈ›ională a henry-ului-90 conventional value of ohm-90 valoarea convenÈ›ională a ohmului-90 conventional value of volt-90 valoarea convenÈ›ională a voltului-90 conventional value of watt-90 valoarea convenÈ›ională a wattului-90 magnetic flux quantum (Φ₀) cuanta fluxului magnetic (Φ₀) nuclear magneton magnetonul nuclear inverse of conductance quantum inversul cuantei de conductanță conventional value of von Klitzing constant valoarea convenÈ›ională a constantei von Klitzing von Klitzing constant constanta von Klitzing atomic unit of magnetic dipole moment unitatea atomică a momentului dipolar magnetic atomic unit of magnetic flux density unitatea atomică a densității fluxului magnetic Bohr magneton in eV/T magnetonul Bohr în eV/T Bohr magneton in Hz/T magnetonul Bohr în Hz/T Bohr magneton in inverse meter per tesla magnetonul Bohr în metri inversi pe tesla Bohr magneton in K/T magnetonul Bohr în K/T nuclear magneton in eV/T magnetonul nuclear în eV/T nuclear magneton in inverse meter per tesla magnetonul nuclear în metri inversi pe tesla nuclear magneton in K/T magnetonul nuclear în K/T nuclear magneton in MHz/T magnetonul nuclear în MHz/T Bohr radius (aâ‚€) raza Bohr (aâ‚€) fine-structure constant (α) constanta structurii fine (α) Hartree energy (Eâ‚•) energia Hartree (Eâ‚•) Hartree energy in eV energia Hartree în eV quantum of circulation cuanta circulaÈ›iei quantum of circulation times 2 cuanta circulaÈ›iei înmulÈ›ită cu 2 Rydberg constant (R∞) constanta Rydberg (R∞) atomic mass unit-hartree relationship relaÈ›ia unitate de masă atomică-hartree atomic mass unit-hertz relationship relaÈ›ia unitate de masă atomică-hertz atomic mass unit-inverse meter relationship relaÈ›ia unitate de masă atomică-metru invers atomic mass unit-joule relationship relaÈ›ia unitate de masă atomică-joule atomic mass unit-kelvin relationship relaÈ›ia unitate de masă atomică-kelvin atomic mass unit-kilogram relationship relaÈ›ia unitate de masă atomică-kilogram atomic unit of 1st hyperpolarizability unitatea atomică a hiperpolarizabilității de ordinul întâi atomic unit of 2nd hyperpolarizability unitatea atomică a hiperpolarizabilității de ordinul al doilea atomic unit of charge (e) unitatea atomică de sarcină (e) atomic unit of charge density unitatea atomică a densității de sarcină atomic unit of current unitatea atomică de curent atomic unit of electric dipole moment unitatea atomică a momentului dipolar electric atomic unit of electric field unitatea atomică a câmpului electric atomic unit of electric field gradient unitatea atomică a gradientului câmpului electric atomic unit of electric polarizability unitatea atomică a polarizabilității electrice atomic unit of electric potential unitatea atomică a potenÈ›ialului electric atomic unit of electric quadrupole moment unitatea atomică a momentului cvadrupolar electric atomic unit of action unitatea atomică de acÈ›iune atomic unit of energy unitatea atomică de energie atomic unit of force unitatea atomică de forță atomic unit of length unitatea atomică de lungime hertz-atomic mass unit relationship relaÈ›ia hertz-unitate de masă atomică hertz-electron volt relationship relaÈ›ia hertz-electronvolt hertz-hartree relationship relaÈ›ia hertz-hartree hertz-inverse meter relationship relaÈ›ia hertz-metru invers hertz-joule relationship relaÈ›ia hertz-joule hertz-kelvin relationship relaÈ›ia hertz-kelvin hertz-kilogram relationship relaÈ›ia hertz-kilogram hyperfine transition frequency of Cs-133 frecvenÈ›a tranziÈ›iei hiperfine a Cs-133 inverse fine-structure constant (αâ�»Â¹) inversul constantei structurii fine (αâ�»Â¹) inverse meter-atomic mass unit relationship relaÈ›ia metru invers-unitate de masă atomică inverse meter-electron volt relationship relaÈ›ia metru invers-electronvolt inverse meter-hartree relationship relaÈ›ia metru invers-hartree inverse meter-hertz relationship relaÈ›ia metru invers-hertz inverse meter-joule relationship relaÈ›ia metru invers-joule inverse meter-kelvin relationship relaÈ›ia metru invers-kelvin inverse meter-kilogram relationship relaÈ›ia metru invers-kilogram joule-atomic mass unit relationship relaÈ›ia joule-unitate de masă atomică joule-electron volt relationship relaÈ›ia joule-electronvolt joule-hertz relationship relaÈ›ia joule-hertz joule-hartree relationship relaÈ›ia joule-hartree joule-inverse meter relationship relaÈ›ia joule-metru invers joule-kelvin relationship relaÈ›ia joule-kelvin joule-kilogram relationship relaÈ›ia joule-kilogram kelvin-atomic mass unit relationship relaÈ›ia kelvin-unitate de masă atomică kelvin-electron volt relationship relaÈ›ia kelvin-electronvolt kelvin-hertz relationship relaÈ›ia kelvin-hertz kelvin-hartree relationship relaÈ›ia kelvin-hartree kelvin-inverse meter relationship relaÈ›ia kelvin-metru invers kelvin-joule relationship relaÈ›ia kelvin-joule kelvin-kilogram relationship relaÈ›ia kelvin-kilogram kilogram-atomic mass unit relationship relaÈ›ia kilogram-unitate de masă atomică kilogram-electron volt relationship relaÈ›ia kilogram-electronvolt kilogram-hertz relationship relaÈ›ia kilogram-hertz kilogram-hartree relationship relaÈ›ia kilogram-hartree kilogram-inverse meter relationship relaÈ›ia kilogram-metru invers kilogram-joule relationship relaÈ›ia kilogram-joule kilogram-kelvin relationship relaÈ›ia kilogram-kelvin lattice parameter of silicon (a) parametrul reÈ›elei siliciului (a) luminous efficacy eficacitate luminoasă natural unit of energy unitatea naturală de energie natural unit of energy in MeV unitatea naturală de energie în MeV natural unit of action (â„�) unitatea naturală de acÈ›iune (â„�) natural unit of action in eV·s unitatea naturală de acÈ›iune în eV·s natural unit of length unitatea naturală de lungime natural unit of mass unitatea naturală de masă natural unit of momentum unitatea naturală de impuls natural unit of momentum in MeV/c unitatea naturală de impuls în MeV/c natural unit of time unitatea naturală de timp natural unit of velocity unitatea naturală de viteză Rydberg constant times c in Hz constanta Rydberg înmulÈ›ită cu c în Hz Rydberg constant times hc in eV constanta Rydberg înmulÈ›ită cu hc în eV Rydberg constant times hc in J constanta Rydberg înmulÈ›ită cu hc în J Fermi coupling constant constanta de cuplaj Fermi weak mixing angle unghiul de amestec slab W to Z mass ratio raportul maselor W/Z Thomson cross section (σₑ) secÈ›iunea eficace Thomson (σₑ) electron mass (mâ‚‘) masa electronului (mâ‚‘) electron mass in u masa electronului în u electron mass energy equivalent (mₑ·c²) echivalentul energetic al masei electronului (mₑ·c²) electron mass energy equivalent in MeV echivalentul energetic al masei electronului în MeV reduced Compton wavelength lungimea de undă Compton redusă classical electron radius (râ‚‘) raza clasică a electronului (râ‚‘) electron charge to mass quotient raportul sarcină/masă al electronului electron-deuteron magnetic moment ratio raportul momentelor magnetice electron-deuteron electron-deuteron mass ratio raportul maselor electron-deuteron electron g factor (gâ‚‘) factorul g al electronului (gâ‚‘) electron gyromagnetic ratio (γₑ) raportul giromagnetic al electronului (γₑ) electron gyromagnetic ratio in MHz/T raportul giromagnetic al electronului în MHz/T electron-helion mass ratio raportul maselor electron-helion electron magnetic moment (μₑ) momentul magnetic al electronului (μₑ) electron magnetic moment anomaly (aâ‚‘) anomalia momentului magnetic al electronului (aâ‚‘) electron magnetic moment to Bohr magneton ratio raportul momentului magnetic al electronului față de magnetonul Bohr electron magnetic moment to nuclear magneton ratio raportul momentului magnetic al electronului față de magnetonul nuclear electron molar mass (Mâ‚‘) masa molară a electronului (Mâ‚‘) electron-muon magnetic moment ratio raportul momentelor magnetice electron-miuon electron-muon mass ratio raportul maselor electron-miuon electron-neutron magnetic moment ratio raportul momentelor magnetice electron-neutron electron-neutron mass ratio raportul maselor electron-neutron electron-proton magnetic moment ratio raportul momentelor magnetice electron-proton electron-proton mass ratio raportul maselor electron-proton electron relative atomic mass (Ar(e)) masa atomică relativă a electronului (Ar(e)) electron-tau mass ratio raportul maselor electron-tau electron to alpha particle mass ratio raportul maselor electron-particulă alfa electron to shielded helion magnetic moment ratio raportul momentelor magnetice electron-helion ecranat electron to shielded proton magnetic moment ratio raportul momentelor magnetice electron-proton ecranat electron-triton mass ratio raportul maselor electron-triton electron volt-atomic mass unit relationship relaÈ›ia electronvolt-unitate de masă atomică electron volt-hartree relationship relaÈ›ia electronvolt-hartree electron volt-hertz relationship relaÈ›ia electronvolt-hertz electron volt-inverse meter relationship relaÈ›ia electronvolt-metru invers electron volt-joule relationship relaÈ›ia electronvolt-joule electron volt-kelvin relationship relaÈ›ia electronvolt-kelvin electron volt-kilogram relationship relaÈ›ia electronvolt-kilogram hartree-atomic mass unit relationship relaÈ›ia hartree-unitate de masă atomică hartree-electron volt relationship relaÈ›ia hartree-electronvolt muon Compton wavelength lungimea de undă Compton a miuonului muon-electron mass ratio raportul maselor miuon-electron muon g factor factorul g al miuonului muon magnetic moment momentul magnetic al miuonului muon magnetic moment anomaly anomalia momentului magnetic al miuonului muon magnetic moment to Bohr magneton ratio raportul momentului magnetic al miuonului față de magnetonul Bohr muon magnetic moment to nuclear magneton ratio raportul momentului magnetic al miuonului față de magnetonul nuclear muon mass masa miuonului muon mass energy equivalent echivalentul energetic al masei miuonului muon mass energy equivalent in MeV echivalentul energetic al masei miuonului în MeV muon mass in u masa miuonului în u muon molar mass masa molară a miuonului muon-neutron mass ratio raportul maselor miuon-neutron muon-proton magnetic moment ratio raportul momentelor magnetice miuon-proton muon-proton mass ratio raportul maselor miuon-proton muon-tau mass ratio raportul maselor miuon-tau reduced muon Compton wavelength lungimea de undă Compton redusă a miuonului reduced tau Compton wavelength lungimea de undă Compton redusă a particulei tau tau Compton wavelength lungimea de undă Compton a particulei tau tau-electron mass ratio raportul maselor tau-electron tau mass masa particulei tau tau mass energy equivalent echivalentul energetic al masei particulei tau tau mass in u masa particulei tau în u tau molar mass masa molară a particulei tau tau-muon mass ratio raportul maselor tau-miuon tau-neutron mass ratio raportul maselor tau-neutron tau-proton mass ratio raportul maselor tau-proton proton charge to mass quotient raportul sarcină/masă al protonului proton Compton wavelength lungimea de undă Compton a protonului proton-electron mass ratio raportul maselor proton-electron proton g factor (gₚ) factorul g al protonului (gₚ) proton gyromagnetic ratio (γₚ) raportul giromagnetic al protonului (γₚ) proton gyromagnetic ratio in MHz/T raportul giromagnetic al protonului în MHz/T proton magnetic moment (μₚ) momentul magnetic al protonului (μₚ) proton magnetic moment to Bohr magneton ratio raportul momentului magnetic al protonului față de magnetonul Bohr proton magnetic moment to nuclear magneton ratio raportul momentului magnetic al protonului față de magnetonul nuclear proton magnetic shielding correction corecÈ›ia de ecranare magnetică a protonului proton mass (mₚ) masa protonului (mₚ) proton mass energy equivalent echivalentul energetic al masei protonului proton mass energy equivalent in MeV echivalentul energetic al masei protonului în MeV proton mass in u masa protonului în u proton molar mass (Mₚ) masa molară a protonului (Mₚ) proton-muon mass ratio raportul maselor proton-miuon proton-neutron magnetic moment ratio raportul momentelor magnetice proton-neutron proton-neutron mass ratio raportul maselor proton-neutron proton relative atomic mass (Ar(p)) masa atomică relativă a protonului (Ar(p)) proton rms charge radius raza rms de sarcină a protonului proton-tau mass ratio raportul maselor proton-tau reduced proton Compton wavelength lungimea de undă Compton redusă a protonului shielded proton gyromagnetic ratio raportul giromagnetic al protonului ecranat shielded proton gyromagnetic ratio in MHz/T raportul giromagnetic al protonului ecranat în MHz/T shielded proton magnetic moment momentul magnetic al protonului ecranat shielded proton magnetic moment to Bohr magneton ratio raportul momentului magnetic al protonului ecranat față de magnetonul Bohr shielded proton magnetic moment to nuclear magneton ratio raportul momentului magnetic al protonului ecranat față de magnetonul nuclear neutron Compton wavelength lungimea de undă Compton a neutronului neutron-electron magnetic moment ratio raportul momentelor magnetice neutron-electron neutron-electron mass ratio raportul maselor neutron-electron neutron g factor (gâ‚™) factorul g al neutronului (gâ‚™) neutron gyromagnetic ratio (γₙ) raportul giromagnetic al neutronului (γₙ) neutron gyromagnetic ratio in MHz/T raportul giromagnetic al neutronului în MHz/T neutron magnetic moment (μₙ) momentul magnetic al neutronului (μₙ) neutron magnetic moment to Bohr magneton ratio raportul momentului magnetic al neutronului față de magnetonul Bohr neutron magnetic moment to nuclear magneton ratio raportul momentului magnetic al neutronului față de magnetonul nuclear neutron mass (mâ‚™) masa neutronului (mâ‚™) neutron mass energy equivalent echivalentul energetic al masei neutronului neutron mass energy equivalent in MeV echivalentul energetic al masei neutronului în MeV neutron mass in u masa neutronului în u neutron molar mass (Mâ‚™) masa molară a neutronului (Mâ‚™) neutron-muon mass ratio raportul maselor neutron-miuon neutron-proton magnetic moment ratio raportul momentelor magnetice neutron-proton neutron-proton mass difference diferenÈ›a de masă neutron-proton neutron-proton mass difference energy equivalent echivalentul energetic al diferenÈ›ei de masă neutron-proton neutron-proton mass difference energy equivalent in MeV echivalentul energetic al diferenÈ›ei de masă neutron-proton în MeV neutron-proton mass difference in u diferenÈ›a de masă neutron-proton în u neutron-proton mass ratio raportul maselor neutron-proton neutron relative atomic mass (Ar(n)) masa atomică relativă a neutronului (Ar(n)) neutron-tau mass ratio raportul maselor neutron-tau neutron to shielded proton magnetic moment ratio raportul momentelor magnetice neutron-proton ecranat reduced neutron Compton wavelength lungimea de undă Compton redusă a neutronului deuteron-electron magnetic moment ratio raportul momentelor magnetice deuteron-electron deuteron-electron mass ratio raportul maselor deuteron-electron deuteron g factor factorul g al deuteronului deuteron magnetic moment momentul magnetic al deuteronului deuteron magnetic moment to Bohr magneton ratio raportul momentului magnetic al deuteronului față de magnetonul Bohr deuteron magnetic moment to nuclear magneton ratio raportul momentului magnetic al deuteronului față de magnetonul nuclear deuteron mass masa deuteronului deuteron mass energy equivalent echivalentul energetic al masei deuteronului deuteron mass energy equivalent in MeV echivalentul energetic al masei deuteronului în MeV deuteron mass in u masa deuteronului în u deuteron molar mass masa molară a deuteronului deuteron-neutron magnetic moment ratio raportul momentelor magnetice deuteron-neutron deuteron-proton magnetic moment ratio raportul momentelor magnetice deuteron-proton deuteron-proton mass ratio raportul maselor deuteron-proton deuteron relative atomic mass (Ar(d)) masa atomică relativă a deuteronului (Ar(d)) deuteron rms charge radius raza rms de sarcină a deuteronului triton-electron mass ratio raportul maselor triton-electron triton g factor (gₜ) factorul g al tritonului (gₜ) triton magnetic moment (μₜ) momentul magnetic al tritonului (μₜ) triton magnetic moment to Bohr magneton ratio raportul momentului magnetic al tritonului față de magnetonul Bohr triton magnetic moment to nuclear magneton ratio raportul momentului magnetic al tritonului față de magnetonul nuclear triton mass (mₜ) masa tritonului (mₜ) triton mass energy equivalent echivalentul energetic al masei tritonului triton mass energy equivalent in MeV echivalentul energetic al masei tritonului în MeV triton mass in u masa tritonului în u triton molar mass (Mₜ) masa molară a tritonului (Mₜ) triton-proton mass ratio raportul maselor triton-proton triton relative atomic mass (Ar(t)) masa atomică relativă a tritonului (Ar(t)) triton to proton magnetic moment ratio raportul momentelor magnetice triton-proton helion-electron mass ratio raportul maselor helion-electron helion g factor (gâ‚•) factorul g al helionului (gâ‚•) helion magnetic moment (μₕ) momentul magnetic al helionului (μₕ) helion magnetic moment to Bohr magneton ratio raportul momentului magnetic al helionului față de magnetonul Bohr helion magnetic moment to nuclear magneton ratio raportul momentului magnetic al helionului față de magnetonul nuclear helion mass (mâ‚•) masa helionului (mâ‚•) helion mass energy equivalent echivalentul energetic al masei helionului helion mass energy equivalent in MeV echivalentul energetic al masei helionului în MeV helion mass in u masa helionului în u helion molar mass (Mâ‚•) masa molară a helionului (Mâ‚•) helion-proton mass ratio raportul maselor helion-proton helion relative atomic mass (Ar(h)) masa atomică relativă a helionului (Ar(h)) helion shielding shift deplasarea de ecranare a helionului shielded helion gyromagnetic ratio raportul giromagnetic al helionului ecranat shielded helion gyromagnetic ratio in MHz/T raportul giromagnetic al helionului ecranat în MHz/T shielded helion magnetic moment momentul magnetic al helionului ecranat shielded helion magnetic moment to Bohr magneton ratio raportul momentului magnetic al helionului ecranat față de magnetonul Bohr shielded helion magnetic moment to nuclear magneton ratio raportul momentului magnetic al helionului ecranat față de magnetonul nuclear shielded helion to proton magnetic moment ratio raportul momentelor magnetice helion ecranat-proton shielded helion to shielded proton magnetic moment ratio raportul momentelor magnetice helion ecranat-proton ecranat alpha particle mass masa particulei alfa alpha particle mass in u masa particulei alfa în u alpha particle mass energy equivalent echivalentul energetic al masei particulei alfa alpha particle mass energy equivalent in MeV echivalentul energetic al masei particulei alfa în MeV alpha particle-electron mass ratio raportul maselor particulă alfa-electron alpha particle-proton mass ratio raportul maselor particulă alfa-proton alpha particle rms charge radius raza rms de sarcină a particulei alfa alpha particle molar mass masa molară a particulei alfa alpha particle relative atomic mass (Ar(α)) masa atomică relativă a particulei alfa (Ar(α)) atomic mass constant (mᵤ) constanta masei atomice (mᵤ) Avogadro constant constanta Avogadro Boltzmann constant (k) constanta Boltzmann (k) Boltzmann constant in eV/K constanta Boltzmann în eV/K Boltzmann constant in Hz/K constanta Boltzmann în Hz/K Boltzmann constant in inverse meter per kelvin constanta Boltzmann în metri inversi pe kelvin electron volt (eV) electronvolt (eV) Faraday constant (F) constanta Faraday (F) first radiation constant (câ‚�) prima constantă a radiaÈ›iei (câ‚�) first radiation constant for spectral radiance prima constantă a radiaÈ›iei pentru radianÈ›a spectrală molar gas constant (R) constanta molară a gazelor (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) constanta Loschmidt (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) constanta Loschmidt (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant constanta Planck molară second radiation constant (câ‚‚) a doua constantă a radiaÈ›iei (câ‚‚) Stefan-Boltzmann constant (σ) constanta Stefan-Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) spaÈ›ierea reÈ›elei siliciului ideal (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent echivalentul energetic al constantei masei atomice atomic mass constant energy equivalent in MeV echivalentul energetic al constantei masei atomice în MeV atomic mass unit-electron volt relationship relaÈ›ia unitate de masă atomică-electronvolt molar mass constant (Mᵤ) constanta masei molare (Mᵤ) molar mass of carbon-12 masa molară a carbonului-12 molar volume of ideal gas (273.15 K, 100 kPa) volumul molar al gazului ideal (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) volumul molar al gazului ideal (273.15 K, 101.325 kPa) molar volume of silicon volumul molar al siliciului Sackur-Tetrode constant (1 K, 100 kPa) constanta Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) constanta Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant constanta legii deplasării în frecvență a lui Wien Wien wavelength displacement law constant constanta legii deplasării în lungime de undă a lui Wien standard atmosphere (atm) atmosfera standard (atm) standard-state pressure (p°) presiunea în stare standard (p°) Angstrom star (Ã…*) angstrom stea (Ã…*) Copper x unit unitatea x de cupru Molybdenum x unit unitatea x de molibden atomic unit of magnetizability unitatea atomică a magnetizabilității atomic unit of mass (mâ‚‘) unitatea atomică de masă (mâ‚‘) atomic unit of momentum unitatea atomică de impuls atomic unit of permittivity unitatea atomică a permitivității atomic unit of time unitatea atomică de timp atomic unit of velocity unitatea atomică de viteză hartree-hertz relationship relaÈ›ia hartree-hertz hartree-inverse meter relationship relaÈ›ia hartree-metru invers hartree-joule relationship relaÈ›ia hartree-joule hartree-kelvin relationship relaÈ›ia hartree-kelvin hartree-kilogram relationship relaÈ›ia hartree-kilogram shielding difference of d and p in HD diferenÈ›a de ecranare dintre d È™i p în HD shielding difference of t and p in HT diferenÈ›a de ecranare dintre t È™i p în HT pi (Ï€) pi (Ï€) Euler's number (e) numărul lui Euler (e) golden ratio (φ) raportul de aur (φ) Euler-Mascheroni constant (γ) constanta Euler-Mascheroni (γ) nominal solar radius raza solară nominală nominal solar total irradiance iradianÈ›a solară totală nominală nominal solar luminosity luminozitatea solară nominală nominal solar effective temperature temperatura efectivă solară nominală nominal solar mass parameter parametrul masei solare nominale nominal terrestrial equatorial radius raza ecuatorială terestră nominală nominal terrestrial polar radius raza polară terestră nominală nominal terrestrial mass parameter parametrul masei terestre nominale nominal jovian equatorial radius raza ecuatorială joviană nominală nominal jovian polar radius raza polară joviană nominală nominal jovian mass parameter parametrul masei joviene nominale average value of one minus the rate of TCG relative to TCB valoarea medie a lui unu minus rata TCG relativă la TCB solar mass parameter (TCB-compatible) parametrul masei solare (compatibil TCB) solar mass parameter (TDB-compatible) parametrul masei solare (compatibil TDB) equatorial radius of the Earth (TT-compatible) raza ecuatorială a Pământului (compatibilă TT) dynamical form factor of the Earth factorul de formă dinamic al Pământului time rate of change in the dynamical form factor of the Earth rata temporală de variaÈ›ie a factorului de formă dinamic al Pământului geocentric gravitational constant (TCB-compatible) constanta gravitaÈ›ională geocentrică (compatibilă TCB) geocentric gravitational constant (TT-compatible) constanta gravitaÈ›ională geocentrică (compatibilă TT) geocentric gravitational constant (TDB-compatible) constanta gravitaÈ›ională geocentrică (compatibilă TDB) potential of the geoid potenÈ›ialul geoidului nominal mean angular velocity of the Earth (TT-compatible) viteza unghiulară medie nominală a Pământului (compatibilă TT) ratio mass of the Moon to the Earth raportul masei Lunii față de Pământ ratio of the mass of the Sun to Mercury raportul masei Soarelui față de Mercur ratio of the mass of the Sun to Venus raportul masei Soarelui față de Venus ratio of the mass of the Sun to Mars raportul masei Soarelui față de Marte ratio of the mass of the Sun to Jupiter raportul masei Soarelui față de Jupiter ratio of the mass of the Sun to Saturn raportul masei Soarelui față de Saturn ratio of the mass of the Sun to Uranus raportul masei Soarelui față de Uranus ratio of the mass of the Sun to Neptune raportul masei Soarelui față de Neptun ratio of the mass of the Sun to (134340) Pluto raportul masei Soarelui față de (134340) Pluto ratio of the mass of the Sun to (136199) Eris raportul masei Soarelui față de (136199) Eris ratio of the mass of (1) Ceres to the Sun raportul masei lui (1) Ceres față de Soare ratio of the mass of (2) Pallas to the Sun raportul masei lui (2) Pallas față de Soare ratio of the mass of (4) Vesta to the Sun raportul masei lui (4) Vesta față de Soare mean obliquity of the ecliptic at J2000.0 oblicitatea medie a eclipticii la J2000.0 Electromagnetic Electromagnetice Compton wavelength lungimea de undă Compton Astronomy Astronomie ConstantsWidget Domain Domeniu Subdomain Subdomeniu No match found N/A Name Denumire Value Valoare Unit Unitate Search Cauta All Toate CustomKeypadDialog Custom Keypad Tastatură personalizată Rows: Rânduri: Columns: Coloane: Copy preset: Copiază presetarea: Basic De bază Scientific (wide) ȘtiinÈ›ifică (lată) Scientific (narrow) ȘtiinÈ›ifică (îngustă) Apply Aplică Row Rând Column Coloană Label Etichetă Behavior Comportament Text Text DiagnosticsDialog App Diagnostics Diagnosticarea aplicaÈ›iei Copy to Clipboard Copiază în clipboard Editor Unit Unitate User unit Unitate utilizator User function Functie utilizator Argument Argument Current result:<br/>%1 Rezultat curent:<br/>%1 Selection result:<br/>%1 Rezultat selecÈ›ie:<br/>%1 Selection result: n/a Rezultate regasite: n/a Selection result: %1 Rezultatele selecÈ›iei: %1 second secundă metre metru kilogram kilogram mole mol radian radian steradian steradian degree Celsius grad Celsius cubic metre metru cub cubic millimetre milimetru cub cubic centimetre centimetru cub cubic decimetre decimetru cub cubic kilometre kilometru cub square millimetre milimetru pătrat square kilometre kilometru pătrat square metre metru pătrat minute minut hour oră day zi astronomical unit unitate astronomică degree grad arcminute minut de arc arcsecond secundă de arc milliarcsecond milisecundă de arc microarcsecond microsecundă de arc hectare hectar litre litru tonne tonă Dalton dalton electronvolt electronvolt Angstrom angstrom atmosphere atmosferă atomic mass unit unitate de masă atomică British thermal unit unitate termică britanică calorie calorie carat carat cup cană cup (Imperial) cană (imperială) cup (Japanese) cană (japoneză) cup (US) cană (SUA) degree Fahrenheit grad Fahrenheit fathom stânjen fluid ounce (Imperial) uncie fluidă (imperială) fluid ounce (US) uncie fluidă (SUA) fluid dram (Imperial) dram fluid (imperial) fluid dram (US) dram fluid (SUA) foot picior square foot picior pătrat cubic foot picior cub gallon (Imperial) galon (imperial) gallon (US) galon (SUA) gill (Imperial) gill (imperial) gill (US) gill (SUA) gradian gradian grain grain gram gram Hartley hartley Hartree energy unit unitate de energie Hartree horsepower cal-putere inch È›ol square inch È›ol pătrat cubic inch È›ol cub karat carat knot nod lightminute minut-lumină lightsecond secundă-lumină lightyear an-lumină long ton tonă lungă mile milă square mile milă pătrată cubic mile milă cubă mile per hour milă pe oră kilometre per hour kilometru pe oră nautical mile milă marină ounce uncie parsec parsec pint (Imperial) pintă (imperială) pint (US) pintă (SUA) pound livră pounds per square inch livre pe È›ol pătrat quart (Imperial) quart (imperial) quart (US) quart (SUA) oil barrel baril de petrol beer barrel (US) baril de bere (SUA) square yard yard pătrat cubic yard yard cub short ton tonă scurtă tablespoon lingură tablespoon (Australian) lingură (australiană) tablespoon (Imperial) lingură (imperială) tablespoon (US) lingură (SUA) dessert spoon lingură de desert teaspoon linguriță teaspoon (Imperial) linguriță (imperială) teaspoon (US) linguriță (SUA) turn rotaÈ›ie revolution revoluÈ›ie revolution per minute rotaÈ›ie pe minut week săptămână kilowatt hour kilowatt-oră millimetre of mercury milimetru de mercur yard yard Julian century secol iulian Julian year an iulian sidereal year an sideral tropical year an tropical Evaluator invalid expression expresie invalida division by zero împărÈ›ire la zero too time consuming - computation was rejected prea mult timp necesar - calcularea a fost anulată dimension mismatch - quantities with different dimensions cannot be compared, added, etc. unități de măsură neconcordante - măsurile cu diferite criterii nu pot fi comparate, adăugate, etc. invalid dimension - operation might require dimensionless arguments dimensiune nevalidă - operaÈ›ia ar putea necesita argumente fără dimensiuni Computation aborted - encountered numerical instability Calculul a fost întrerupt - a apărut o instabilitate numerică invalid dimension - function might require dimensionless arguments dimensiune invalidă - funcÈ›ia ar putea necesita argumente fără dimensiuni error eroare unit must not be zero unitatea nu trebuie să fie zero Conversion failed - dimension mismatch Conversia nu a reuÈ™it - nepotrivirea dimensiunii unknown function or variable funcÈ›ie sau variabilă necunoscută recursion not supported recursivitatea nu este acceptată cannot operate on a NaN nu se pe poate opera asupra NaN underflow - tiny result is out of SpeedCrunch's number range underflow - rezultatul mic este în afara intervalului numeric al SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflow - rezultatul uriaÈ™ este în afara intervalului numeric al SpeedCrunch overflow - logic result exceeds maximum of 256 bits overflow - rezultatul logic depășeÈ™te maximul de 256 bits overflow - integer result exceeds maximum limit for integers overflow - rezultatul sub formă de număr întreg depășeÈ™te maximul permis pentru numere întregi operation is not defined for these arguments operaÈ›ia nu este definită pentru aceste argumente wrong number of arguments număr greÈ™it de argumente does not take NaN as an argument nu ia ca argument NaN result out of range rezultat înafara intervalului undefined for argument domain nedefinit pentru domeniul de argumente computation too expensive calcul foarte costisitor internal error, please report a bug eroare internă, va rog raportaÈ›i eroarea syntax error eroare de sintaxă conversion target must be a unit È›inta conversiei trebuie să fie o unitate unknown unit unitate necunoscută %1 is a reserved name, please choose another %1 este nume rezervat, va rog să alegeti alt nume %1 is a global user definition and cannot be overridden in this session. %1 este o definiÈ›ie globală a utilizatorului È™i nu poate fi suprascrisă în această sesiune. %1 is a variable name, please choose another or delete the variable %1 este un nume de variabilă, va rugam să alegeÈ›i alt nume sau să stergeÈ›i variabila argument %1 is used more than once argumentul %1 este folosit mai mult decât o singura dată %1 is a built-in unit name, please choose another %1 este un nume de unitate încorporată; alegeÈ›i altul %1 is a user function name, please choose another or delete the function %1 este o denumire de funcÈ›ie, va rugăm să alegeÈ›i altă denumire sau să È™tergeÈ›i numele funcÈ›iei FunctionRepo max; trials; probability maxim; încercări; probabilitate trials; probability încercări; probabilitate hits; trials; probability succese; încercări; probabilitate max; total; hits; trials maxim; total; succese; încercări total; hits; trials total; succese; încercări count; total; hits; trials număr; total; succese; încercări dividend; divisor deîmpărÈ›it; divizor x; exponent_bits; significand_bits [; exponent_bias] x; biÈ›i_exponent; biÈ›i_semnificand [; deplasare_exponent] base; x bază; x value; modulo valoare; modulo base; exponent; modulo bază; exponent; modulo events; average_events evenimente; medie_evenimente average_events medie_evenimente x [; precision] x [; precizie] Absolute Value Valoare Absolută Absolute Deviation DeviaÈ›ie Absolută Arc Cosine Arc cosinus Logical AND ȘI logic Area Hyperbolic Cosine Cosinus hiperbolic de arie Area Hyperbolic Sine Sinus hiperbolic de arie Area Hyperbolic Tangent Tangentă hiperbolică de arie Arc Sine Arc sinus Arc Tangent Arc tangentă Arc Tangent with two Arguments Arc tangentă cu două argumente Average (Arithmetic Mean) Medie (medie aritmetică) Binomial Cumulative Distribution Function FuncÈ›ia de distribuÈ›ie cumulativă binomială Binomial Distribution Mean Media distribuÈ›iei binomiale Binomial Probability Mass Function FuncÈ›ia de masă de probabilitate binomială Binomial Distribution Variance VarianÈ›a distribuÈ›iei binomiale Cube Root Radical Cubic Complex Conjugate Conjugat complex Cosine Cosinus Hyperbolic Cosine Cosinus hiperbolic Cotangent Cotangentă Cosecant Cosecantă Convert Unix timestamp to Date ConverteÈ™te marcajul temporal Unix în dată Degrees of Arc Grade de arc Error Function FuncÈ›ia eroare Complementary Error Function FuncÈ›ia eroare complementară Exponential ExponenÈ›ial Fractional Part Partea fracÈ›ionară Extension of Factorials [= (x-1)!] Extinderea factorialelor [= (x-1)!] Greatest Common Divisor Cel mai mare divizor comun Geometric Mean Medie geometrică Gradians of arc Gradieni de arc Hypergeometric Cumulative Distribution Function FuncÈ›ia de distribuÈ›ie cumulativă hipergeometrică Hypergeometric Distribution Mean Media distribuÈ›iei hipergeometrice Hypergeometric Probability Mass Function FuncÈ›ia de masă de probabilitate hipergeometrică Hypergeometric Distribution Variance VarianÈ›a distribuÈ›iei hipergeometrice Integer Quotient Cât întreg Integer Part Partea întreagă Imaginary Part Partea imaginară Decode IEEE-754 Binary Value Decodează valoarea binară IEEE-754 Encode IEEE-754 Binary Value Codează în valoarea binară IEEE-754 Decode 16-bit Half-Precision Value Decodează valoarea cu semiprecizie pe 16 biÈ›i Encode 16-bit Half-Precision Value Codează valoarea cu semiprecizie pe 16 biÈ›i Decode 32-bit Single-Precision Value Decodează valoarea cu precizie simplă pe 32 de biÈ›i Encode 32-bit Single-Precision Value Codează valoarea cu precizie simplă pe 32 de biÈ›i Decode 64-bit Double-Precision Value Decodează valoarea cu precizie dublă pe 64 de biÈ›i Encode 64-bit Double-Precision Value Codează valoarea cu precizie dublă pe 64 de biÈ›i Decode 128-bit Quad-Precision Value Decodează valoarea cu precizie cvadruplă pe 128 de biÈ›i Encode 128-bit Quad-Precision Value Codează valoarea cu precizie cvadruplă pe 128 de biÈ›i Binary Logarithm Logaritm binar Common Logarithm Logaritm zecimal Natural Logarithm Logaritm natural Logarithm to Arbitrary Base Logaritm în bază arbitrară Mask to a bit size Maschează la o dimensiune în biÈ›i Maximum Maxim Median Value (50th Percentile) Valoarea mediană (percentila 50) Minimum Minim Modulo Modulo Euclidean Modulo Modulo euclidian Modular Exponentiation ExponenÈ›iere modulară Combination (Binomial Coefficient) CombinaÈ›ii (coeficient binomial) Logical NOT NU logic Permutation (Arrangement) Permutări (aranjamente) Convert to Binary Representation Conversie la reprezentare binară Arithmetic Aritmetică Chemistry Chimie Complex Complexe Combinatorics Combinatorică Probability Probabilitate Statistics Statistică Aggregation Agregare Random Aleator Base conversion Conversie de bază Number formatting Formatare numere Integer arithmetic Aritmetică întreagă Special functions FuncÈ›ii speciale Exponential & Logarithmic ExponenÈ›iale È™i logaritmice Angle conversion Conversie unghiuri Trigonometry Trigonometrie Bitwise Pe biÈ›i Floating point Virgulă mobilă Date & Time Dată È™i oră Linear algebra Algebră liniară unix_timestamp; x hours offset to GMT marcaj_temporal_unix; decalaj de x ore față de GMT yyyymmdd.hhmmss; x hours offset to GMT aaaallzz.hhmmss; decalaj de x ore față de GMT [digits] [cifre] max [; min] maxim [; minim] List Literal Literal de listă Convert to Padded Binary Representation Conversie la reprezentare binară completată Round Toward +∞ (Ceiling) Rotunjire spre +∞ (plafon) Cosine plus Imaginary Sine Cosinus plus sinus imaginar Convert to Cis Complex Form Conversie la forma complexă cis Matrix Column Count Numărul de coloane ale matricei Population Correlation Matrix (n) Matricea de corelaÈ›ie a populaÈ›iei (n) Sample Correlation Matrix (n-1) Matricea de corelaÈ›ie a eÈ™antionului (n-1) Count Număr Population Covariance Matrix (n) Matricea de covarianță a populaÈ›iei (n) Sample Covariance Matrix (n-1) Matricea de covarianță a eÈ™antionului (n-1) Cross Product Produs vectorial Convert Date to Unix timestamp ConverteÈ™te data în marcaj temporal Unix Convert to Decimal Representation Conversie la reprezentare zecimală Determinant Determinant Convert to Sexagesimal Notation Conversie la notaÈ›ie sexagesimală Dot Product Produs scalar Convert to Engineering Notation Conversie la notaÈ›ie inginerească Convert to Exponential Complex Form Conversie la forma complexă exponenÈ›ială Round Toward −∞ (Floor) Rotunjire spre −∞ (podea) Flatten Matrix Aplatizează matricea Least Common Multiple Cel mai mic multiplu comun Convert to Hexadecimal Representation Conversie la reprezentare hexazecimală Convert to Padded Hexadecimal Representation Conversie la reprezentare hexazecimală completată Inverse Matrix Matrice inversă Round to 16-bit Half-Precision Value RotunjeÈ™te la valoare cu semiprecizie pe 16 biÈ›i Round to 32-bit Single-Precision Value RotunjeÈ™te la valoare cu precizie simplă pe 32 de biÈ›i Round to 64-bit Double-Precision Value RotunjeÈ™te la valoare cu precizie dublă pe 64 de biÈ›i Round to 128-bit Quad-Precision Value RotunjeÈ™te la valoare cu precizie cvadruplă pe 128 de biÈ›i Residual from 16-bit Half-Precision Rounding Reziduu după rotunjirea cu semiprecizie pe 16 biÈ›i Residual from 32-bit Single-Precision Rounding Reziduu după rotunjirea cu precizie simplă pe 32 de biÈ›i Residual from 64-bit Double-Precision Rounding Reziduu după rotunjirea cu precizie dublă pe 64 de biÈ›i Residual from 128-bit Quad-Precision Rounding Reziduu după rotunjirea cu precizie cvadruplă pe 128 de biÈ›i Substance Mass Masa substanÈ›ei Molarity Molaritate Molar Mass Masă molară Median Absolute Deviation DeviaÈ›ie absolută mediană Mean Medie Numerical Value of Quantity Valoarea numerică a mărimii Random Decimal Number Număr zecimal aleator Random Integer Number Număr întreg aleator Convert to Rational Representation Conversie la reprezentare raÈ›ională Convert to Octal Representation Conversie la reprezentare octală Convert to Padded Octal Representation Conversie la reprezentare octală completată Vector or Matrix Norm Norma vectorului sau matricei Logical OR SAU logic Population Count (Hamming Weight) Număr de biÈ›i setaÈ›i (pondere Hamming) Phase of Complex Number Faza numărului complex Poissonian Cumulative Distribution Function FuncÈ›ia de distribuÈ›ie cumulativă Poisson Poissonian Distribution Mean Media distribuÈ›iei Poisson Poissonian Probability Mass Function FuncÈ›ia de masă de probabilitate Poisson Poissonian Distribution Variance VarianÈ›a distribuÈ›iei Poisson Convert to Phasor Complex Form Conversie la forma complexă fazorială Convert to Rectangular Complex Form Conversie la forma complexă dreptunghiulară Round Half Away from Zero Rotunjire jumătate departe de zero Round Half Even Rotunjire jumătate la par Nth Root Rădăcină de ordinul n Convert to Scientific Notation Conversie la notaÈ›ie È™tiinÈ›ifică Matrix Row Count Numărul de rânduri ale matricei List or Matrix Shape Forma listei sau matricei Summation Sumă Population Standard Deviation (n) Abaterea standard a populaÈ›iei (n) Sample Standard Deviation (n-1) Abaterea standard a eÈ™antionului (n-1) Round Toward Zero (Truncation) Rotunjire spre zero (trunchiere) Matrix Trace Urma matricei Transpose Matrix Transpune matricea Population Variance (n) VarianÈ›a populaÈ›iei (n) Sample Variance (n-1) VarianÈ›a eÈ™antionului (n-1) Product Produs Radians Radiani Matrix Rank Rangul matricei Real Part Parte reală Secant Secantă Arithmetic Shift Left Deplasare aritmetică la stânga Arithmetic Shift Right Deplasare aritmetică la dreapta Signum Signum Sine Sinus Hyperbolic Sine Sinus hiperbolic Square Root Rădăcină pătrată Sum Sumă Tangent Tangentă Convert to Trigonometric Complex Form ConverteÈ™te la Trigonometric Complex Form Turns RotaÈ›ii Hyperbolic Tangent Tangentă hiperbolică Sign-extend a value Valoare extinsă cu semn Logical XOR XOR logic FunctionsWidget Domain Domeniu All Toate Name Denumire Search Caută No match found Niciun rezultat găsit Identifier Identificator HistoryWidget Remove All Calculations Above Elimină toate calculele de deasupra Remove This Calculation EliminaÈ›i acest calcul Remove All Calculations Below Elimină toate calculele de dedesubt Keypad Inverse cosine Cosinus invers The last result Ultimul rezultat Inverse sine Sinus invers Inverse tangent Tangentă inversă Evaluate expression Evaluează expresia Division ÃŽmpărÈ›ire Multiplication ÃŽnmulÈ›ire Subtraction Scădere Addition Adunare Clear expression Șterge expresia Cosine Cosinus Backspace Backspace Scientific notation Notare È™tiinÈ›ifică Exponential ExponenÈ›ial Factorial Factorial Natural logarithm Logaritm natural Left parenthesis Paranteză stângă Nth root Rădăcină de ordinul n Argument separator Separator de argumente Square Pătrat Common logarithm Logaritm zecimal Modulo Modulo Contextual percentage Procent contextual Power Putere Right parenthesis Paranteză dreaptă Sine Sinus Square root Rădăcină pătrată Tangent Tangentă Pi Pi Decimal separator Separator zecimal MainWindow Radian Radian Degree Grad Gradian Gradian Binary Binar Octal Octal Hexadecimal Hexazecimal Sexagesimal Sexagesimal Engineering decimal Zecimal ingineresc Scientific decimal Zecimal È™tiinÈ›ific &Import... &Importă... &Quit &IeÈ™ire Clear E&xpression Șterge E&xpresia Clear &History Șterge &Istoricul &Copy &Copiază &Paste &LipeÈ™te &Select Expression &Selectează expresia &Constants &Constante &Functions &FuncÈ›ii &History &Istoric &Status Bar &Bară de stare Bitfield Câmp de biÈ›i Use&r Functions FuncÈ›ii &utilizator &Degree &Grad &Radian &Radian &Gradian &Gradian Re&volution Re&voluÈ›ie Auto-Insert a&ns I&nserează automat ans Automatic &Completion Completare &automată &Built-in Functions &FuncÈ›ii încorporate Built-in &Variables &Variabile încorporate User &Functions Fu&ncÈ›ii utilizator User Va&riables Va&riabile utilizator Open a Private Tab on Startup Deschide o filă privată la pornire Open and focus a new private tab whenever SpeedCrunch starts. Deschide È™i activează o filă privată nouă la fiecare pornire a SpeedCrunch. Syntax &Highlighting E&videnÈ›iere sintaxă Group Digits in &Input Grupează c&ifrele introduse Automatic Input &Adjustments &Ajustări automate ale intrării Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ajustează automat operatorii, spaÈ›ierea, parantezele È™i puterile È™i limitează intrarea la caractere valide. Group input digits using the selected number format. Grupează cifrele introduse conform formatului numeric selectat. &Blinking Cursor &Cursor intermitent Blink the cursor in the expression editor. Activează clipirea cursorului în editorul de expresii. &Escape Clears Editor &Escape goleÈ™te editorul Clear the focused expression editor with Escape after dismissing any popup or preview. GoleÈ™te editorul de expresii activ cu Escape după închiderea ferestrelor pop-up sau a previzualizărilor. Keep Expression After Evaluation Păstrează expresia după calcul Copy New Results Automatically Copiază automat rezultatele noi &Comma &Virgulă &System Default &Setare implicită de sistem &Dot &Punct Dot &And Comma Punct &È™i virgulă Toward +∞ (&ceil) Spre +∞ (&ceil) Toward −∞ (&floor) Spre −∞ (&floor) &Binary &Binar &Engineering &Ingineresc &Hexadecimal &Hexazecimal &Octal &Octal &Scientific &ȘtiinÈ›ific User &Manual &Manual de utilizare Issues and &Feedback &Probleme È™i sugestii &Donate &Donează &About SpeedCrunch D&espre SpeedCrunch App Diag&nostics Diag&nosticarea aplicaÈ›iei S&plit ÃŽm&parte Angle &Mode &Mod unghiular &Complex Form Formă &complexă New Tab Filă nouă Constants Constante Functions FuncÈ›ii History Istoric User Functions FuncÈ›ii utilizator &Font... &Font... &Language... &Limbă &Session &Sesiune &Edit &Editează &View &Vizualizare Se&ttings Se&tări &Decimal &Zecimal &Keypad &Tastatură numerică Always on &Top Mereu &deasupra Disabled Dezactivat Small Space SpaÈ›iu mic Medium Space SpaÈ›iu mediu Large Space SpaÈ›iu mare &0 Digits &0 zecimale &15 Digits &15 zecimale &2 Digits &2 zecimale &3 Digits &3 zecimale &50 Digits &50 zecimale &8 Digits &8 zecimale &Sexagesimal &Sexagesimal Reset All Settings... Resetează toate setările... &System &Sistem SpeedCrunch &Theme &Tema SpeedCrunch &Classic &Clasic &Modern &Modern Context Help Ajutor contextual &Help &Ajutor Error Eroare Can't read from file %1 Nu se poate citi din fiÈ™ierul %1 Import Session Importă sesiunea Close Session ÃŽnchide sesiunea Angle Mode: Mod unghi: Notation: NotaÈ›ie: Precision: Precizie: Turn RotaÈ›ie Revolution RevoluÈ›ie Fixed-point decimal Zecimal cu punct fix Rational RaÈ›ional Automatic decimal Zecimal automat Automatic Automat User &Definitions... &DefiniÈ›ii utilizator... New &Tab Filă &nouă New &Private Tab Filă &privată nouă Keep Păstrează Make Private... Transformă în privată... New &Window Fereastră &nouă &Open... &Deschide... &Rename... &RedenumeÈ™te... Clo&ne... &Clonează... &Close Tab &ÃŽnchide fila Reopen Clo&sed Tab Rede&schide fila închisă Open Sessions &Folder Deschide &dosarul sesiunilor &Undo An&ulează &Redo &Refă Cu&t &Decupează Copy &Last Result C&opiază ultimul rezultat &Wrap in Parentheses &ÃŽncadrează în paranteze Full Scr&een Mode Mod &ecran complet &Basic &De bază &Scientific (wide) &ȘtiinÈ›ifică (lată) Scientific (narrow) ȘtiinÈ›ifică (îngustă) &Custom... &Personalizat... Main &Menu &Meniu principal User &Variables &Variabile utilizator &Left &Stânga &Right D&reapta &Up S&us &Down &Jos Close Pa&ne ÃŽ&nchide panoul User &Units &Unități utilizator &Turn &RotaÈ›ie If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Dacă o expresie nouă începe cu +, -, * sau /, SpeedCrunch inserează mai întâi „ansâ€�. &Accept with Enter &Acceptă cu Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Acceptă sugestia curentă de completare automată cu Enter fără a o selecta mai întâi cu tastele săgeată. &Units &Unități Show Live Result &Preview AfiÈ™ează &previzualizarea live a rezultatului Save &Window Position on Exit Salvează poziÈ›ia &ferestrei la ieÈ™ire Hover Highlighting EvidenÈ›iere la trecerea cursorului Group Integer Part Only Grupează doar partea întreagă Number Format... Format număr... Notation && Precision... NotaÈ›ie È™i precizie... After pressing Enter, keep the entered expression selected in the editor. După apăsarea Enter, păstrează expresia introdusă selectată în editor. Never Niciodată Always ÃŽntotdeauna Only for Single-Line Expressions Doar pentru expresii pe o singură linie Simplify Displayed Expressions Simplifică expresiile afiÈ™ate History Size &Limit... &Limită dimensiune istoric... Remove Trailing &Zeroes Elimină &zerourile finale Nearest, Half &Away (round) Cel mai apropiat, jumătate &departe (round) Nearest, Half &Even (roundeven) Cel mai apropiat, jumătate &par (roundeven) Toward &Zero (trunc) Spre &zero (trunc) &Fixed-Point Punct &fix &Rational &RaÈ›ional &Exponential (m·sâ�»Â¹) &ExponenÈ›ial (m·sâ�»Â¹) &Fractional (m/s) &FracÈ›ionar (m/s) &Rectangular (a + bi) &Dreptunghiulară (a + bi) Exponential (reâ�±á¶¿) ExponenÈ›ial (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrică (r(cos θ + i·sin θ)) Phasor (r∠θ) Fazor (r∠θ) &Theme... &Temă... Check for &Updates Verifică &actualizări Source Code Cod sursă &Zoom &Zoom &Results &Rezultate Unit Notation NotaÈ›ie pentru unități Rounding Mode Mod de rotunjire &Notation &NotaÈ›ie &Imaginary Unit Unitate &imaginară &Window &Fereastră &Editing &Editare A&utocomplete Completare a&utomată Up/Down Arrow History Istoric cu săgeÈ›ile sus/jos &Appearance &Aspect &Menus &Meniuri &Docks Panouri an&docabile &Input and Results &Intrare È™i rezultate &Disabled &Dezactivat &Disable &Dezactivează Close preview ÃŽnchide previzualizarea Rename... RedenumeÈ™te... Clone... Clonează... Close Tab ÃŽnchide fila New Private Tab Filă privată nouă Open... Deschide... Reopen Closed Tab Redeschide fila închisă Split ÃŽmparte Left Stânga Right Dreapta Up Sus Down Jos Clear GoleÈ™te Delete Șterge %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Sesiune privată: conÈ›inutul se elimină la închidere. AlegeÈ›i Sesiune > Păstrează pentru a o transforma într-o sesiune obiÈ™nuită. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privată] Reset All Settings Resetează toate setările Reset all settings to their default values? ResetaÈ›i toate setările la valorile implicite? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Sunt incluse aspectul, editarea, formatele rezultatelor È™i preferinÈ›ele ferestrelor. Calculele, sesiunile deschise È™i definiÈ›iile utilizatorului vor fi păstrate. The settings file could not be written. FiÈ™ierul de setări nu a putut fi scris. Clear this session's calculations, unfinished expression, variables, functions, and units? GoliÈ›i calculele, expresia neterminată, variabilele, funcÈ›iile È™i unitățile acestei sesiuni? Global user definitions are kept. DefiniÈ›iile globale ale utilizatorului sunt păstrate. Make Session Private Transformă sesiunea în privată The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Sesiunea salvată %1 va fi È™tearsă. ConÈ›inutul ei va rămâne deschis într-o sesiune privată È™i va fi eliminat la închiderea acelei sesiuni sau la ieÈ™irea din SpeedCrunch. Make Private Transformă în privată Could not delete the saved session %1. Sesiunea salvată %1 nu a putut fi È™tearsă. Keep Session Păstrează sesiunea Could not save the session. It remains private. Sesiunea nu a putut fi salvată. Rămâne privată. Clone Session Clonează sesiunea Could not save session file %1. FiÈ™ierul sesiunii %1 nu a putut fi salvat. Could not delete session file %1. FiÈ™ierul sesiunii %1 nu a putut fi È™ters. JSON file (*.json);;Any file (*.*) FiÈ™ier JSON (*.json);;Orice fiÈ™ier (*.*) Export session as JSON Exportă sesiunea ca JSON The selected file is not valid JSON: %1 FiÈ™ierul selectat nu este JSON valid: %1 The selected file is not a SpeedCrunch session JSON file. FiÈ™ierul selectat nu este un fiÈ™ier JSON de sesiune SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Acest fiÈ™ier foloseÈ™te un format de sesiune SpeedCrunch învechit È™i nu poate fi importat. The selected JSON file is missing the required $schema field. FiÈ™ierului JSON selectat îi lipseÈ™te câmpul obligatoriu $schema. The selected JSON file uses an unsupported JSON schema: %1 FiÈ™ierul JSON selectat foloseÈ™te o schemă JSON neacceptată: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). FiÈ™ierului JSON selectat îi lipseÈ™te identificatorul schemei de sesiune SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 FiÈ™ierul JSON selectat foloseÈ™te un format de sesiune SpeedCrunch neacceptat: %1 The selected JSON file is missing the required session name. FiÈ™ierului JSON selectat îi lipseÈ™te numele obligatoriu al sesiunii. The selected JSON file has an empty session name. FiÈ™ierul JSON selectat are un nume de sesiune gol. The selected JSON file has invalid or incomplete SpeedCrunch session data. FiÈ™ierul JSON selectat are date de sesiune SpeedCrunch nevalide sau incomplete. Open Sessions Folder Deschide dosarul sesiunilor Could not create the sessions folder: %1 Nu s-a putut crea dosarul sesiunilor: %1 Could not open the sessions folder: %1 Nu s-a putut deschide dosarul sesiunilor: %1 Editor and Results Font Fontul editorului È™i al rezultatelor Open Session Deschide sesiune Community Comunitate Rename Session RedenumeÈ™te sesiunea Clear Session GoleÈ™te sesiunea Delete Session Șterge sesiunea Close Pane ÃŽnchide panoul User Variables Variabile utilizator User Units Unități utilizator Clear History Șterge istoricul Are you sure you want to clear the calculation history? Sigur doriÈ›i să È™tergeÈ›i istoricul calculelor? Session name: Numele sesiunii: A session named %1 already exists. Există deja o sesiune numită %1. Could not create session file %1. Nu s-a putut crea fiÈ™ierul sesiunii %1. Could not write session file %1. Nu s-a putut scrie fiÈ™ierul sesiunii %1. Are you sure you want to delete this session? Sigur doriÈ›i să È™tergeÈ›i această sesiune? Custom Precision Precizie personalizată Fractional digits: Cifre fracÈ›ionare: Theme Temă Light Themes Teme luminoase Dark Themes Teme întunecate Preview Previzualizare Colors Culori Select color for %1 Selectează culoarea pentru %1 Import... Importă... Export... Exportă... Import Theme Importă tema Theme file (*.json);;All files (*) FiÈ™ier temă (*.json);;Toate fiÈ™ierele (*) Invalid theme file. FiÈ™ier temă nevalid. Can't import theme "%1" because it conflicts with a built-in theme. Nu se poate importa tema „%1â€� deoarece intră în conflict cu o temă încorporată. Can't find a writable theme folder. Nu se poate găsi un folder de teme inscriptibil. Overwrite Theme Suprascrie tema A custom theme named "%1" already exists. Do you want to overwrite it? Există deja o temă personalizată numită „%1â€�. DoriÈ›i să o suprascrieÈ›i? Can't overwrite theme file %1 Nu se poate suprascrie fiÈ™ierul temei %1 Can't copy theme file to %1 Nu se poate copia fiÈ™ierul temei în %1 Export Theme Exportă tema Can't export theme as "%1" because it conflicts with a built-in theme. Nu se poate exporta tema ca „%1â€� deoarece intră în conflict cu o temă încorporată. Can't write to file %1 Nu se poate scrie în fiÈ™ierul %1 Global User Variable Variabilă globală utilizator Global User Function FuncÈ›ie globală utilizator Global User Unit Unitate globală utilizator User Definitions DefiniÈ›ii de utilizator These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Aceste definiÈ›ii sunt globale È™i sunt încărcate în fiecare sesiune. Nu pot fi modificate în sesiuni È™i au prioritate față de definiÈ›iile cu acelaÈ™i nume din editorul sesiunii. IntroduceÈ›i o definiÈ›ie pe linie. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Exemple: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Aplică Validate Validează Test Results Rezultatele testului Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Variabile importate: %1 FuncÈ›ii importate: %2 Unități importate: %3 Numerele liniilor cu erori: %4 none niciunul Apply Results Rezultatele aplicării User definitions saved. DefiniÈ›iile de utilizator au fost salvate. History Size Limit Limită dimensiune istoric Maximum number of history entries for this session (0 = unlimited): Numărul maxim de intrări de istoric pentru această sesiune (0 = nelimitat): Text file (*.txt);;Any file (*.*) FiÈ™ier text (*.txt);;Orice fiÈ™ier (*.*) Could not recalculate from calculation %1: %2 Nu s-a putut recalcula de la calculul %1: %2 History Size Limit Reached Limita dimensiunii istoricului a fost atinsă This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Acest calcul ocupă ultimul loc disponibil din istoric. Calculele viitoare vor elimina cel mai vechi calcul din istoric. PuteÈ›i mări limita din Sesiune > Limită dimensiune istoric. Editing calculation. Press Esc twice to cancel. Se editează calculul. ApăsaÈ›i Esc de două ori pentru anulare. Calculation Settings Setări calcul Invalid recalculation start index Index de pornire recalculare nevalid System Default Setare implicită de sistem Language Limbă Select the language: SelectaÈ›i limba: Custom Personalizat Decimal places: Zecimale: &Automatic &Automat &Precision &Precizie Plain &text &Text simplu Formula &Book Carte de &formule &Export &Exportă Export session as HTML Exportă sesiune în HTML HTML file (*.html) FiÈ™ier HTML (*.html) Export session as plain text Exportă sesiune în text simplu ManualWindow SpeedCrunch Manual Manual SpeedCrunch %1 - SpeedCrunch Manual %1 - Manual SpeedCrunch NumberFormatDialog Number Format Format număr <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>SelectaÈ›i formatul numeric pentru rezultate È™i gruparea cifrelor introduse.</b><br/><br/>Notă: pentru numerele introduse sunt acceptate formatele neechivoce, chiar dacă diferă de formatul de afiÈ™are selectat.<br/> QObject Global User Variable Variabilă globală utilizator Global User Function FuncÈ›ie globală utilizator Global User Unit Unitate globală utilizator Backspace Backspace Clear expression Șterge expresia Evaluate expression Evaluează expresia Insert text Inserează text Automatic decimal Zecimal automat Fixed-point decimal Zecimal cu punct fix Engineering decimal Zecimal ingineresc Scientific decimal Zecimal È™tiinÈ›ific Rational RaÈ›ional Binary Binar Octal Octal Hexadecimal Hexazecimal Sexagesimal Sexagesimal Update Available Actualizare disponibilă A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Este disponibilă o versiune mai nouă (%1).<br/><a href="%2">VizitaÈ›i site-ul pentru descărcare.</a> Check for Updates Verifică actualizări SpeedCrunch %1 is up to date. SpeedCrunch %1 este la zi. No connectivity. Please check your internet connection and try again. Nu există conectivitate. VerificaÈ›i conexiunea la internet È™i încercaÈ›i din nou. Could not verify the latest available version. Nu s-a putut verifica ultima versiune disponibilă. ResultDisplay Scroll to bottom Derulează la sfârÈ™it Edit Expression Editează expresia Change Settings Schimbă setările New Tab Filă nouă &Import... &Importă... &Export &Exportă Plain &text &Text simplu Copy Copiază Selection SelecÈ›ie Select All Selectează tot Expression Expresie Result Rezultat Calculation Calcul Calculation as Single Line Calcul pe un singur rând Remove Elimină This Calculation Acest calcul All Calculations Above Toate calculele de mai sus All Calculations Below Toate calculele de mai jos New Private Tab Filă privată nouă Session Sesiune Open... Deschide... Clone... Clonează... Rename... RedenumeÈ™te... Keep Păstrează Make Private... Transformă în privată... Clear GoleÈ™te Delete Șterge Close ÃŽnchide Split ÃŽmparte Left Stânga Right Dreapta Up Sus Down Jos Close Pane ÃŽnchide panoul Main Menu Meniu principal Cancel editing Anulează editarea Copy result Copiază rezultatul Edit expression Editează expresia Change settings Schimbă setările Remove calculation Elimină calculul ResultSlotsDialog Notation & Precision NotaÈ›ie È™i precizie Result Line Linie rezultat Enabled Activat Notation NotaÈ›ie Decimal Places Zecimale Main Line Linie principală Extra Line #1 Linie suplimentară #1 Extra Line #2 Linie suplimentară #2 Extra Line #3 Linie suplimentară #3 Extra Line #4 Linie suplimentară #4 Auto Automat UserFunctionListWidget Name Denumire Value Valoare Description Descriere Search Caută No match found Nu s-a găsit niciun rezultat Insert Inserează Edit Editează Delete Șterge Delete All Șterge toate UserUnitListWidget Name Nume Value Valoare Description Descriere Search Caută No match found Nu s-a găsit nicio potrivire Insert Inserează Edit Editează Delete Șterge Delete All Șterge tot VariableListWidget Name Denumire Value Valoare Description Descriere Search Caută No match found Nu s-a găsit niciun rezultat Insert Inserează Edit Editează Delete Șterge Delete All Șterge toate heldercorreia-speedcrunch-e7ca37f/src/resources/locale/ru.ts000066400000000000000000011447511526573132500244100ustar00rootroot00000000000000 AboutBox About SpeedCrunch О программе SpeedCrunch Core developers ОÑ�новные разработчики Original author Ð�втор идеи Close Закрыть Math engine МатематичеÑ�кий движок Main author | Logo | Maintainer ОÑ�новной автор | Логотип | Сопровождающий Thanks БлагодарноÑ�ти Copyright (C) 2004-2026 The SpeedCrunch developers Ð�вторÑ�кие права (C) 2004-2026 принадлежат разработчикам SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Эта программа Ñ�влÑ�етÑ�Ñ� Ñ�вободным программным обеÑ�печением; вы можете раÑ�проÑ�транÑ�ть и/или изменÑ�ть её на уÑ�ловиÑ�Ñ… GNU GPL (ОÑ�новной ОбщеÑ�твенной Лицензии), изданной Организацией Свободного П/О второго или (на ваш выбор) более позднего изданиÑ� This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Эта программа раÑ�проÑ�транÑ�етÑ�Ñ� в надежде, что будет полезной, но БЕЗ КÐ�КИХ-ЛИБО ГÐ�РÐ�Ð�ТИЙ, даже без подразумеваемой гарантии ПРИГОДÐ�ОСТИ ДЛЯ КÐ�КОЙ-ЛИБО ЦЕЛИ. Подробнее Ñ�м. GNU GPL. BitFieldWidget Reset bits to zero СброÑ�ить биты в ноль Invert bits Инвертировать биты Shift bits left Сдвинуть биты влево Shift bits right Сдвинуть биты вправо Book Index Содержание Algebra Ð�лгебра Quadratic Equation Квадратное уравнение Logarithmic Base Conversion Переход к натуральному оÑ�нованию Geometry ГеометриÑ� Circle Круг Sector Сектор Sphere Сфера Cube Куб Cone КонуÑ� Cylinder Цилиндр Electronics Электроника Ohm's Law Закон Ома Power МощноÑ�ть Reactance Реактивное Ñ�опротивление Resonance РезонанÑ� Radio Frequency РадиочаÑ�тоты Antennas Ð�нтенны Characteristic Impedance (coax) Волновое Ñ�опротивление (коакÑ�иальный кабель) Velocity of Propagation (coax) СкороÑ�ть раÑ�проÑ�транениÑ� (коакÑ�иальный кабель) Standing Wave Ratio & Return Loss КоÑ�ффициент Ñ�тоÑ�чей волны и обратные потери Free Space Wavelength Длина волны в вакууме resistance Ñ�опротивление voltage напрÑ�жение current ток power мощноÑ�ть inductive reactance индуктивное Ñ�опротивление capacitive reactance ёмкоÑ�тное Ñ�опротивление inductance индуктивноÑ�ть capacitance ёмкоÑ�ть frequency чаÑ�тота resonance frequency чаÑ�тота резонанÑ�а area площадь perimeter периметр diameter диаметр radius радиуÑ� volume объём surface area площадь поверхноÑ�ти height выÑ�ота slant height длина образующей face diagonal диагональ грани space diagonal проÑ�транÑ�твеннаÑ� диагональ edge length длина ребра arc length длина дуги central angle (degrees) центральный угол (градуÑ�Ñ‹) input power ВходнаÑ� мощноÑ�ть reflected power ОтражённаÑ� мощноÑ�ть transmitted power ПередаваемаÑ� мощноÑ�ть return loss Обратные потери dielectric constant ДиÑ�лектричеÑ�каÑ� проницаемоÑ�ть outer conductor's inner diameter Внутренний диаметр внешнего проводника inner conductor's outer diameter Ð�аружный диаметр внутреннего проводника speed of light Ñ�короÑ�ть Ñ�вета reflection coefficient коÑ�ффициент отражениÑ� Ñ�игнала standing wave ratio коÑ�ффициент Ñ�тоÑ�чей волны normalized impedance нормированный импеданÑ� frequency (Hz) чаÑ�тота (Гц) BookDock Formula Book Справочник формул ConstantCompletion Search constants ПоиÑ�к конÑ�тант No match found Совпадений не найдено Constants Mathematics Математика Physics (CODATA 2022) Физика (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) ХимиÑ� (IUPAC - CIAAW 2021) Uncategorized Без категории Universal Общие Physicochemical Физико-химичеÑ�кие Atomic & Nuclear — General Ð�томнаÑ� и Ñ�дернаÑ� физика — общие Atomic & Nuclear — Electroweak Ð�томнаÑ� и Ñ�дернаÑ� физика — Ñ�лектроÑ�лабые взаимодейÑ�твиÑ� Atomic & Nuclear — Electron Ð�томнаÑ� и Ñ�дернаÑ� физика — Ñ�лектрон Atomic & Nuclear — Muon Ð�томнаÑ� и Ñ�дернаÑ� физика — мюон Atomic & Nuclear — Tau Ð�томнаÑ� и Ñ�дернаÑ� физика — тау Atomic & Nuclear — Proton Ð�томнаÑ� и Ñ�дернаÑ� физика — протон Atomic & Nuclear — Neutron Ð�томнаÑ� и Ñ�дернаÑ� физика — нейтрон Atomic & Nuclear — Deuteron Ð�томнаÑ� и Ñ�дернаÑ� физика — дейтрон Atomic & Nuclear — Triton Ð�томнаÑ� и Ñ�дернаÑ� физика — тритон Atomic & Nuclear — Helion Ð�томнаÑ� и Ñ�дернаÑ� физика — гелион Atomic & Nuclear — Alpha particle Ð�томнаÑ� и Ñ�дернаÑ� физика — альфа-чаÑ�тица Atomic & Nuclear — Atomic units Ð�томнаÑ� и Ñ�дернаÑ� физика — атомные единицы Atomic & Nuclear — Energy conversion relationships Ð�томнаÑ� и Ñ�дернаÑ� физика — Ñ�оотношениÑ� преобразованиÑ� Ñ�нергии Atomic & Nuclear — X-ray units Ð�томнаÑ� и Ñ�дернаÑ� физика — рентгеновÑ�кие единицы Atomic & Nuclear — Magnetic shielding corrections Ð�томнаÑ� и Ñ�дернаÑ� физика — поправки магнитного Ñ�кранированиÑ� Masses МаÑ�Ñ�Ñ‹ Lifetimes Времена жизни Molar Masses МолÑ�рные маÑ�Ñ�Ñ‹ Electronegativity ЭлектроотрицательноÑ�ть Ionization Energy ЭнергиÑ� ионизации Nominal Constants (IAU 2015) Ð�оминальные поÑ�тоÑ�нные (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Текущие лучшие оценки (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) характериÑ�тичеÑ�кое Ñ�опротивление вакуума (Zâ‚€) reduced Planck constant (â„�) приведённаÑ� поÑ�тоÑ�ннаÑ� Планка (â„�) vacuum electric permittivity (ϵ₀) Ñ�лектричеÑ�каÑ� проницаемоÑ�ть вакуума (ϵ₀) Newtonian constant of gravitation (G) ньютоновÑ�каÑ� гравитационнаÑ� поÑ�тоÑ�ннаÑ� (G) vacuum magnetic permeability (μ₀) магнитнаÑ� проницаемоÑ�ть вакуума (μ₀) Planck constant (h) поÑ�тоÑ�ннаÑ� Планка (h) speed of light in vacuum (c) Ñ�короÑ�ть Ñ�вета в вакууме (c) standard acceleration of gravity (gâ‚™) Ñ�тандартное уÑ�корение Ñ�вободного падениÑ� (gâ‚™) Newtonian constant of gravitation over h-bar c ньютоновÑ�каÑ� гравитационнаÑ� поÑ�тоÑ�ннаÑ� делённаÑ� на â„�c Planck length планковÑ�каÑ� длина Planck constant in eV/Hz (h) поÑ�тоÑ�ннаÑ� Планка в Ñ�Ð’/Hz (h) Planck mass планковÑ�каÑ� маÑ�Ñ�а Planck mass energy equivalent in GeV Ñ�нергетичеÑ�кий Ñ�квивалент планковÑ�кой маÑ�Ñ�Ñ‹ в ГÑ�Ð’ Planck temperature планковÑ�каÑ� температура Planck time планковÑ�кое времÑ� reduced Planck constant in eV·s (â„�) приведённаÑ� поÑ�тоÑ�ннаÑ� Планка в Ñ�В·s (â„�) reduced Planck constant times c in MeV·fm приведённаÑ� поÑ�тоÑ�ннаÑ� Планка умноженнаÑ� на c в МÑ�В·fm Bohr magneton магнетон Бора conductance quantum (Gâ‚€) квант проводимоÑ�ти (Gâ‚€) Coulomb constant (kâ‚‘) поÑ�тоÑ�ннаÑ� Кулона (kâ‚‘) elementary charge (e) Ñ�лементарный зарÑ�д (e) elementary charge over h-bar Ñ�лементарный зарÑ�д, делённый на â„� conventional value of Josephson constant уÑ�ловное значение поÑ�тоÑ�нной ДжозефÑ�она Josephson constant поÑ�тоÑ�ннаÑ� ДжозефÑ�она conventional value of ampere-90 уÑ�ловное значение ампера-90 conventional value of coulomb-90 уÑ�ловное значение кулона-90 conventional value of farad-90 уÑ�ловное значение фарада-90 conventional value of henry-90 уÑ�ловное значение генри-90 conventional value of ohm-90 уÑ�ловное значение ома-90 conventional value of volt-90 уÑ�ловное значение вольта-90 conventional value of watt-90 уÑ�ловное значение ватта-90 magnetic flux quantum (Φ₀) квант магнитного потока (Φ₀) nuclear magneton Ñ�дерный магнетон inverse of conductance quantum обратнаÑ� величина кванта проводимоÑ�ти conventional value of von Klitzing constant уÑ�ловное значение поÑ�тоÑ�нной фон Клитцинга von Klitzing constant поÑ�тоÑ�ннаÑ� фон Клитцинга atomic unit of magnetic dipole moment атомнаÑ� единица магнитного дипольного момента atomic unit of magnetic flux density атомнаÑ� единица магнитной индукции Bohr magneton in eV/T магнетон Бора в Ñ�Ð’/T Bohr magneton in Hz/T магнетон Бора в Гц/T Bohr magneton in inverse meter per tesla магнетон Бора в обратных метрах на теÑ�лу Bohr magneton in K/T магнетон Бора в К/T nuclear magneton in eV/T Ñ�дерный магнетон в Ñ�Ð’/T nuclear magneton in inverse meter per tesla Ñ�дерный магнетон в обратных метрах на теÑ�лу nuclear magneton in K/T Ñ�дерный магнетон в К/T nuclear magneton in MHz/T Ñ�дерный магнетон в МГц/Тл Bohr radius (aâ‚€) радиуÑ� Бора (aâ‚€) fine-structure constant (α) поÑ�тоÑ�ннаÑ� тонкой Ñ�труктуры (α) Hartree energy (Eâ‚•) Ñ�нергиÑ� Хартри (Eâ‚•) Hartree energy in eV Ñ�нергиÑ� Хартри в Ñ�Ð’ quantum of circulation квант циркулÑ�ции quantum of circulation times 2 квант циркулÑ�ции умноженный на 2 Rydberg constant (R∞) поÑ�тоÑ�ннаÑ� Ридберга (R∞) atomic mass unit-hartree relationship атомнаÑ� единица маÑ�Ñ�Ñ‹-хартри Ñ�оотношение atomic mass unit-hertz relationship атомнаÑ� единица маÑ�Ñ�Ñ‹-герц Ñ�оотношение atomic mass unit-inverse meter relationship атомнаÑ� единица маÑ�Ñ�Ñ‹-обратный метр Ñ�оотношение atomic mass unit-joule relationship атомнаÑ� единица маÑ�Ñ�Ñ‹-джоуль Ñ�оотношение atomic mass unit-kelvin relationship атомнаÑ� единица маÑ�Ñ�Ñ‹-кельвин Ñ�оотношение atomic mass unit-kilogram relationship атомнаÑ� единица маÑ�Ñ�Ñ‹-килограмм Ñ�оотношение atomic unit of 1st hyperpolarizability атомнаÑ� единица первой гиперполÑ�ризуемоÑ�ти atomic unit of 2nd hyperpolarizability атомнаÑ� единица второй гиперполÑ�ризуемоÑ�ти atomic unit of charge (e) атомнаÑ� единица зарÑ�да (e) atomic unit of charge density атомнаÑ� единица плотноÑ�ти зарÑ�да atomic unit of current атомнаÑ� единица тока atomic unit of electric dipole moment атомнаÑ� единица Ñ�лектричеÑ�кого дипольного момента atomic unit of electric field атомнаÑ� единица Ñ�лектричеÑ�кого полÑ� atomic unit of electric field gradient атомнаÑ� единица градиента Ñ�лектричеÑ�кого полÑ� atomic unit of electric polarizability атомнаÑ� единица Ñ�лектричеÑ�кой полÑ�ризуемоÑ�ти atomic unit of electric potential атомнаÑ� единица Ñ�лектричеÑ�кого потенциала atomic unit of electric quadrupole moment атомнаÑ� единица Ñ�лектричеÑ�кого квадрупольного момента atomic unit of action атомнаÑ� единица дейÑ�твиÑ� atomic unit of energy атомнаÑ� единица Ñ�нергии atomic unit of force атомнаÑ� единица Ñ�илы atomic unit of length атомнаÑ� единица длины hertz-atomic mass unit relationship герц-атомнаÑ� единица маÑ�Ñ�Ñ‹ Ñ�оотношение hertz-electron volt relationship герц-Ñ�лектронвольт Ñ�оотношение hertz-hartree relationship герц-хартри Ñ�оотношение hertz-inverse meter relationship герц-обратный метр Ñ�оотношение hertz-joule relationship герц-джоуль Ñ�оотношение hertz-kelvin relationship герц-кельвин Ñ�оотношение hertz-kilogram relationship герц-килограмм Ñ�оотношение hyperfine transition frequency of Cs-133 чаÑ�тота Ñ�верхтонкого перехода Cs-133 inverse fine-structure constant (αâ�»Â¹) обратнаÑ� поÑ�тоÑ�ннаÑ� тонкой Ñ�труктуры (αâ�»Â¹) inverse meter-atomic mass unit relationship обратный метр-атомнаÑ� единица маÑ�Ñ�Ñ‹ Ñ�оотношение inverse meter-electron volt relationship обратный метр-Ñ�лектронвольт Ñ�оотношение inverse meter-hartree relationship обратный метр-хартри Ñ�оотношение inverse meter-hertz relationship обратный метр-герц Ñ�оотношение inverse meter-joule relationship обратный метр-джоуль Ñ�оотношение inverse meter-kelvin relationship обратный метр-кельвин Ñ�оотношение inverse meter-kilogram relationship обратный метр-килограмм Ñ�оотношение joule-atomic mass unit relationship джоуль-атомнаÑ� единица маÑ�Ñ�Ñ‹ Ñ�оотношение joule-electron volt relationship джоуль-Ñ�лектронвольт Ñ�оотношение joule-hertz relationship джоуль-герц Ñ�оотношение joule-hartree relationship джоуль-хартри Ñ�оотношение joule-inverse meter relationship джоуль-обратный метр Ñ�оотношение joule-kelvin relationship джоуль-кельвин Ñ�оотношение joule-kilogram relationship джоуль-килограмм Ñ�оотношение kelvin-atomic mass unit relationship кельвин-атомнаÑ� единица маÑ�Ñ�Ñ‹ Ñ�оотношение kelvin-electron volt relationship кельвин-Ñ�лектронвольт Ñ�оотношение kelvin-hertz relationship кельвин-герц Ñ�оотношение kelvin-hartree relationship кельвин-хартри Ñ�оотношение kelvin-inverse meter relationship кельвин-обратный метр Ñ�оотношение kelvin-joule relationship кельвин-джоуль Ñ�оотношение kelvin-kilogram relationship кельвин-килограмм Ñ�оотношение kilogram-atomic mass unit relationship килограмм-атомнаÑ� единица маÑ�Ñ�Ñ‹ Ñ�оотношение kilogram-electron volt relationship килограмм-Ñ�лектронвольт Ñ�оотношение kilogram-hertz relationship килограмм-герц Ñ�оотношение kilogram-hartree relationship килограмм-хартри Ñ�оотношение kilogram-inverse meter relationship килограмм-обратный метр Ñ�оотношение kilogram-joule relationship килограмм-джоуль Ñ�оотношение kilogram-kelvin relationship килограмм-кельвин Ñ�оотношение lattice parameter of silicon (a) параметр решётки кремниÑ� (a) luminous efficacy Ñ�ветоваÑ� отдача natural unit of energy еÑ�теÑ�твеннаÑ� единица Ñ�нергии natural unit of energy in MeV еÑ�теÑ�твеннаÑ� единица Ñ�нергии в МÑ�Ð’ natural unit of action (â„�) еÑ�теÑ�твеннаÑ� единица дейÑ�твиÑ� (â„�) natural unit of action in eV·s еÑ�теÑ�твеннаÑ� единица дейÑ�твиÑ� в Ñ�В·s natural unit of length еÑ�теÑ�твеннаÑ� единица длины natural unit of mass еÑ�теÑ�твеннаÑ� единица маÑ�Ñ�а natural unit of momentum еÑ�теÑ�твеннаÑ� единица импульÑ�а natural unit of momentum in MeV/c еÑ�теÑ�твеннаÑ� единица импульÑ�а в МÑ�Ð’/c natural unit of time еÑ�теÑ�твеннаÑ� единица времÑ� natural unit of velocity еÑ�теÑ�твеннаÑ� единица Ñ�короÑ�ти Rydberg constant times c in Hz поÑ�тоÑ�ннаÑ� Ридберга умноженнаÑ� на c в Гц Rydberg constant times hc in eV поÑ�тоÑ�ннаÑ� Ридберга времÑ�s hc в Ñ�Ð’ Rydberg constant times hc in J поÑ�тоÑ�ннаÑ� Ридберга времÑ�s hc в Дж Fermi coupling constant поÑ�тоÑ�ннаÑ� Ñ�вÑ�зи Ферми weak mixing angle угол Ñ�лабого Ñ�мешиваниÑ� W to Z mass ratio отношение маÑ�Ñ�Ñ‹ W к маÑ�Ñ�е Z Thomson cross section (σₑ) Ñ�ечение ТомÑ�она (σₑ) electron mass (mâ‚‘) Ñ�лектрон маÑ�Ñ�а (mâ‚‘) electron mass in u Ñ�лектрон маÑ�Ñ�а в а.е.м. electron mass energy equivalent (mₑ·c²) Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ Ñ�лектрона (mₑ·c²) electron mass energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ Ñ�лектрона в МÑ�Ð’ reduced Compton wavelength приведённаÑ� комптоновÑ�каÑ� длина волны classical electron radius (râ‚‘) клаÑ�Ñ�ичеÑ�кий радиуÑ� Ñ�лектрона (râ‚‘) electron charge to mass quotient Ñ�лектрон отношение зарÑ�да к маÑ�Ñ�е electron-deuteron magnetic moment ratio Ñ�лектрон-дейтрон отношение магнитных моментов electron-deuteron mass ratio Ñ�лектрон-дейтрон отношение маÑ�Ñ� electron g factor (gâ‚‘) Ñ�лектрон g-фактор (gâ‚‘) electron gyromagnetic ratio (γₑ) Ñ�лектрон гиромагнитное отношение (γₑ) electron gyromagnetic ratio in MHz/T Ñ�лектрон гиромагнитное отношение в МГц/Тл electron-helion mass ratio Ñ�лектрон-гелион отношение маÑ�Ñ� electron magnetic moment (μₑ) Ñ�лектрон магнитный момент (μₑ) electron magnetic moment anomaly (aâ‚‘) Ñ�лектрон аномалиÑ� магнитного момента (aâ‚‘) electron magnetic moment to Bohr magneton ratio Ñ�лектрон магнитный момент to магнетон Бора отношение electron magnetic moment to nuclear magneton ratio Ñ�лектрон магнитный момент to Ñ�дерный магнетон отношение electron molar mass (Mâ‚‘) Ñ�лектрон молÑ�рнаÑ� маÑ�Ñ�а (Mâ‚‘) electron-muon magnetic moment ratio Ñ�лектрон-мюон отношение магнитных моментов electron-muon mass ratio Ñ�лектрон-мюон отношение маÑ�Ñ� electron-neutron magnetic moment ratio Ñ�лектрон-нейтрон отношение магнитных моментов electron-neutron mass ratio Ñ�лектрон-нейтрон отношение маÑ�Ñ� electron-proton magnetic moment ratio Ñ�лектрон-протон отношение магнитных моментов electron-proton mass ratio Ñ�лектрон-протон отношение маÑ�Ñ� electron relative atomic mass (Ar(e)) Ñ�лектрон отноÑ�ительнаÑ� атомнаÑ� маÑ�Ñ�а (Ar(e)) electron-tau mass ratio Ñ�лектрон-тау отношение маÑ�Ñ� electron to alpha particle mass ratio Ñ�лектрон to альфа-чаÑ�тица отношение маÑ�Ñ� electron to shielded helion magnetic moment ratio Ñ�лектрон to Ñ�кранированный гелион отношение магнитных моментов electron to shielded proton magnetic moment ratio Ñ�лектрон to Ñ�кранированный протон отношение магнитных моментов electron-triton mass ratio Ñ�лектрон-тритон отношение маÑ�Ñ� electron volt-atomic mass unit relationship Ñ�лектронвольт-атомнаÑ� единица маÑ�Ñ�Ñ‹ Ñ�оотношение electron volt-hartree relationship Ñ�лектронвольт-хартри Ñ�оотношение electron volt-hertz relationship Ñ�лектронвольт-герц Ñ�оотношение electron volt-inverse meter relationship Ñ�лектронвольт-обратный метр Ñ�оотношение electron volt-joule relationship Ñ�лектронвольт-джоуль Ñ�оотношение electron volt-kelvin relationship Ñ�лектронвольт-кельвин Ñ�оотношение electron volt-kilogram relationship Ñ�лектронвольт-килограмм Ñ�оотношение hartree-atomic mass unit relationship хартри-атомнаÑ� единица маÑ�Ñ�Ñ‹ Ñ�оотношение hartree-electron volt relationship хартри-Ñ�лектронвольт Ñ�оотношение muon Compton wavelength комптоновÑ�каÑ� длина волны мюона muon-electron mass ratio мюон-Ñ�лектрон отношение маÑ�Ñ� muon g factor мюон g-фактор muon magnetic moment мюон магнитный момент muon magnetic moment anomaly мюон аномалиÑ� магнитного момента muon magnetic moment to Bohr magneton ratio мюон магнитный момент to магнетон Бора отношение muon magnetic moment to nuclear magneton ratio мюон магнитный момент to Ñ�дерный магнетон отношение muon mass мюон маÑ�Ñ�а muon mass energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ мюона muon mass energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ мюона в МÑ�Ð’ muon mass in u мюон маÑ�Ñ�а в а.е.м. muon molar mass мюон молÑ�рнаÑ� маÑ�Ñ�а muon-neutron mass ratio мюон-нейтрон отношение маÑ�Ñ� muon-proton magnetic moment ratio мюон-протон отношение магнитных моментов muon-proton mass ratio мюон-протон отношение маÑ�Ñ� muon-tau mass ratio мюон-тау отношение маÑ�Ñ� reduced muon Compton wavelength приведённаÑ� комптоновÑ�каÑ� длина волны мюона reduced tau Compton wavelength приведённаÑ� комптоновÑ�каÑ� длина волны тау-лептона tau Compton wavelength комптоновÑ�каÑ� длина волны тау-лептона tau-electron mass ratio тау-Ñ�лектрон отношение маÑ�Ñ� tau mass тау маÑ�Ñ�а tau mass energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ тау-лептона tau mass in u тау маÑ�Ñ�а в а.е.м. tau molar mass тау молÑ�рнаÑ� маÑ�Ñ�а tau-muon mass ratio тау-мюон отношение маÑ�Ñ� tau-neutron mass ratio тау-нейтрон отношение маÑ�Ñ� tau-proton mass ratio тау-протон отношение маÑ�Ñ� proton charge to mass quotient протон отношение зарÑ�да к маÑ�Ñ�е proton Compton wavelength комптоновÑ�каÑ� длина волны протона proton-electron mass ratio протон-Ñ�лектрон отношение маÑ�Ñ� proton g factor (gₚ) протон g-фактор (gₚ) proton gyromagnetic ratio (γₚ) протон гиромагнитное отношение (γₚ) proton gyromagnetic ratio in MHz/T протон гиромагнитное отношение в МГц/Тл proton magnetic moment (μₚ) протон магнитный момент (μₚ) proton magnetic moment to Bohr magneton ratio протон магнитный момент to магнетон Бора отношение proton magnetic moment to nuclear magneton ratio протон магнитный момент to Ñ�дерный магнетон отношение proton magnetic shielding correction поправка магнитного Ñ�кранированиÑ� протона proton mass (mₚ) протон маÑ�Ñ�а (mₚ) proton mass energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ протона proton mass energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ протона в МÑ�Ð’ proton mass in u протон маÑ�Ñ�а в а.е.м. proton molar mass (Mₚ) протон молÑ�рнаÑ� маÑ�Ñ�а (Mₚ) proton-muon mass ratio протон-мюон отношение маÑ�Ñ� proton-neutron magnetic moment ratio протон-нейтрон отношение магнитных моментов proton-neutron mass ratio протон-нейтрон отношение маÑ�Ñ� proton relative atomic mass (Ar(p)) протон отноÑ�ительнаÑ� атомнаÑ� маÑ�Ñ�а (Ar(p)) proton rms charge radius Ñ�реднеквадратичный зарÑ�довый радиуÑ� протона proton-tau mass ratio протон-тау отношение маÑ�Ñ� reduced proton Compton wavelength приведённаÑ� комптоновÑ�каÑ� длина волны протона shielded proton gyromagnetic ratio Ñ�кранированный протон гиромагнитное отношение shielded proton gyromagnetic ratio in MHz/T Ñ�кранированный протон гиромагнитное отношение в МГц/Тл shielded proton magnetic moment Ñ�кранированный протон магнитный момент shielded proton magnetic moment to Bohr magneton ratio Ñ�кранированный протон магнитный момент to магнетон Бора отношение shielded proton magnetic moment to nuclear magneton ratio Ñ�кранированный протон магнитный момент to Ñ�дерный магнетон отношение neutron Compton wavelength комптоновÑ�каÑ� длина волны нейтрона neutron-electron magnetic moment ratio нейтрон-Ñ�лектрон отношение магнитных моментов neutron-electron mass ratio нейтрон-Ñ�лектрон отношение маÑ�Ñ� neutron g factor (gâ‚™) нейтрон g-фактор (gâ‚™) neutron gyromagnetic ratio (γₙ) нейтрон гиромагнитное отношение (γₙ) neutron gyromagnetic ratio in MHz/T нейтрон гиромагнитное отношение в МГц/Тл neutron magnetic moment (μₙ) нейтрон магнитный момент (μₙ) neutron magnetic moment to Bohr magneton ratio нейтрон магнитный момент to магнетон Бора отношение neutron magnetic moment to nuclear magneton ratio нейтрон магнитный момент to Ñ�дерный магнетон отношение neutron mass (mâ‚™) нейтрон маÑ�Ñ�а (mâ‚™) neutron mass energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ нейтрона neutron mass energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ нейтрона в МÑ�Ð’ neutron mass in u нейтрон маÑ�Ñ�а в а.е.м. neutron molar mass (Mâ‚™) нейтрон молÑ�рнаÑ� маÑ�Ñ�а (Mâ‚™) neutron-muon mass ratio нейтрон-мюон отношение маÑ�Ñ� neutron-proton magnetic moment ratio нейтрон-протон отношение магнитных моментов neutron-proton mass difference нейтрон-протон разноÑ�ть маÑ�Ñ� neutron-proton mass difference energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент разноÑ�ти маÑ�Ñ� нейтрона и протона neutron-proton mass difference energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент разноÑ�ти маÑ�Ñ� нейтрона и протона в МÑ�Ð’ neutron-proton mass difference in u нейтрон-протон разноÑ�ть маÑ�Ñ� в а.е.м. neutron-proton mass ratio нейтрон-протон отношение маÑ�Ñ� neutron relative atomic mass (Ar(n)) нейтрон отноÑ�ительнаÑ� атомнаÑ� маÑ�Ñ�а (Ar(n)) neutron-tau mass ratio нейтрон-тау отношение маÑ�Ñ� neutron to shielded proton magnetic moment ratio нейтрон to Ñ�кранированный протон отношение магнитных моментов reduced neutron Compton wavelength приведённаÑ� комптоновÑ�каÑ� длина волны нейтрона deuteron-electron magnetic moment ratio дейтрон-Ñ�лектрон отношение магнитных моментов deuteron-electron mass ratio дейтрон-Ñ�лектрон отношение маÑ�Ñ� deuteron g factor дейтрон g-фактор deuteron magnetic moment дейтрон магнитный момент deuteron magnetic moment to Bohr magneton ratio дейтрон магнитный момент to магнетон Бора отношение deuteron magnetic moment to nuclear magneton ratio дейтрон магнитный момент to Ñ�дерный магнетон отношение deuteron mass дейтрон маÑ�Ñ�а deuteron mass energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ дейтрона deuteron mass energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ дейтрона в МÑ�Ð’ deuteron mass in u дейтрон маÑ�Ñ�а в а.е.м. deuteron molar mass дейтрон молÑ�рнаÑ� маÑ�Ñ�а deuteron-neutron magnetic moment ratio дейтрон-нейтрон отношение магнитных моментов deuteron-proton magnetic moment ratio дейтрон-протон отношение магнитных моментов deuteron-proton mass ratio дейтрон-протон отношение маÑ�Ñ� deuteron relative atomic mass (Ar(d)) дейтрон отноÑ�ительнаÑ� атомнаÑ� маÑ�Ñ�а (Ar(d)) deuteron rms charge radius дейтрон Ñ�реднеквадратичный зарÑ�довый радиуÑ� triton-electron mass ratio тритон-Ñ�лектрон отношение маÑ�Ñ� triton g factor (gₜ) тритон g-фактор (gₜ) triton magnetic moment (μₜ) тритон магнитный момент (μₜ) triton magnetic moment to Bohr magneton ratio тритон магнитный момент to магнетон Бора отношение triton magnetic moment to nuclear magneton ratio тритон магнитный момент to Ñ�дерный магнетон отношение triton mass (mₜ) тритон маÑ�Ñ�а (mₜ) triton mass energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ тритона triton mass energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ тритона в МÑ�Ð’ triton mass in u тритон маÑ�Ñ�а в а.е.м. triton molar mass (Mₜ) тритон молÑ�рнаÑ� маÑ�Ñ�а (Mₜ) triton-proton mass ratio тритон-протон отношение маÑ�Ñ� triton relative atomic mass (Ar(t)) тритон отноÑ�ительнаÑ� атомнаÑ� маÑ�Ñ�а (Ar(t)) triton to proton magnetic moment ratio тритон to протон отношение магнитных моментов helion-electron mass ratio гелион-Ñ�лектрон отношение маÑ�Ñ� helion g factor (gâ‚•) гелион g-фактор (gâ‚•) helion magnetic moment (μₕ) гелион магнитный момент (μₕ) helion magnetic moment to Bohr magneton ratio гелион магнитный момент to магнетон Бора отношение helion magnetic moment to nuclear magneton ratio гелион магнитный момент to Ñ�дерный магнетон отношение helion mass (mâ‚•) гелион маÑ�Ñ�а (mâ‚•) helion mass energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ гелиона helion mass energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ гелиона в МÑ�Ð’ helion mass in u гелион маÑ�Ñ�а в а.е.м. helion molar mass (Mâ‚•) гелион молÑ�рнаÑ� маÑ�Ñ�а (Mâ‚•) helion-proton mass ratio гелион-протон отношение маÑ�Ñ� helion relative atomic mass (Ar(h)) гелион отноÑ�ительнаÑ� атомнаÑ� маÑ�Ñ�а (Ar(h)) helion shielding shift Ñ�двиг Ñ�кранированиÑ� гелиона shielded helion gyromagnetic ratio Ñ�кранированный гелион гиромагнитное отношение shielded helion gyromagnetic ratio in MHz/T Ñ�кранированный гелион гиромагнитное отношение в МГц/Тл shielded helion magnetic moment Ñ�кранированный гелион магнитный момент shielded helion magnetic moment to Bohr magneton ratio Ñ�кранированный гелион магнитный момент to магнетон Бора отношение shielded helion magnetic moment to nuclear magneton ratio Ñ�кранированный гелион магнитный момент to Ñ�дерный магнетон отношение shielded helion to proton magnetic moment ratio Ñ�кранированный гелион to протон отношение магнитных моментов shielded helion to shielded proton magnetic moment ratio Ñ�кранированный гелион to Ñ�кранированный протон отношение магнитных моментов alpha particle mass альфа-чаÑ�тица маÑ�Ñ�а alpha particle mass in u альфа-чаÑ�тица маÑ�Ñ�а в а.е.м. alpha particle mass energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ альфа-чаÑ�тицы alpha particle mass energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент маÑ�Ñ�Ñ‹ альфа-чаÑ�тицы в МÑ�Ð’ alpha particle-electron mass ratio альфа-чаÑ�тица-Ñ�лектрон отношение маÑ�Ñ� alpha particle-proton mass ratio альфа-чаÑ�тица-протон отношение маÑ�Ñ� alpha particle rms charge radius альфа-чаÑ�тица Ñ�реднеквадратичный зарÑ�довый радиуÑ� alpha particle molar mass альфа-чаÑ�тица молÑ�рнаÑ� маÑ�Ñ�а alpha particle relative atomic mass (Ar(α)) альфа-чаÑ�тица отноÑ�ительнаÑ� атомнаÑ� маÑ�Ñ�а (Ar(α)) atomic mass constant (mᵤ) атомнаÑ� поÑ�тоÑ�ннаÑ� маÑ�Ñ�Ñ‹ (mᵤ) Avogadro constant поÑ�тоÑ�ннаÑ� Ð�вогадро Boltzmann constant (k) поÑ�тоÑ�ннаÑ� Больцмана (k) Boltzmann constant in eV/K поÑ�тоÑ�ннаÑ� Больцмана в Ñ�Ð’/K Boltzmann constant in Hz/K поÑ�тоÑ�ннаÑ� Больцмана в Гц/K Boltzmann constant in inverse meter per kelvin поÑ�тоÑ�ннаÑ� Больцмана в обратных метрах на кельвин electron volt (eV) Ñ�лектронвольт (eV) Faraday constant (F) поÑ�тоÑ�ннаÑ� ФарадеÑ� (F) first radiation constant (câ‚�) перваÑ� радиационнаÑ� поÑ�тоÑ�ннаÑ� (câ‚�) first radiation constant for spectral radiance перваÑ� радиационнаÑ� поÑ�тоÑ�ннаÑ� длÑ� Ñ�пектральной Ñ�ркоÑ�ти molar gas constant (R) молÑ�рнаÑ� газоваÑ� поÑ�тоÑ�ннаÑ� (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) поÑ�тоÑ�ннаÑ� Лошмидта (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) поÑ�тоÑ�ннаÑ� Лошмидта (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant молÑ�рнаÑ� поÑ�тоÑ�ннаÑ� Планка second radiation constant (câ‚‚) втораÑ� радиационнаÑ� поÑ�тоÑ�ннаÑ� (câ‚‚) Stefan-Boltzmann constant (σ) поÑ�тоÑ�ннаÑ� Стефана-Больцмана (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) межплоÑ�коÑ�тное раÑ�Ñ�тоÑ�ние идеального Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent Ñ�нергетичеÑ�кий Ñ�квивалент атомной поÑ�тоÑ�нной маÑ�Ñ�Ñ‹ atomic mass constant energy equivalent in MeV Ñ�нергетичеÑ�кий Ñ�квивалент атомной поÑ�тоÑ�нной маÑ�Ñ�Ñ‹ в МÑ�Ð’ atomic mass unit-electron volt relationship атомнаÑ� единица маÑ�Ñ�Ñ‹-Ñ�лектронвольт Ñ�оотношение molar mass constant (Mᵤ) поÑ�тоÑ�ннаÑ� молÑ�рной маÑ�Ñ�Ñ‹ (Mᵤ) molar mass of carbon-12 молÑ�рнаÑ� маÑ�Ñ�а углерода-12 molar volume of ideal gas (273.15 K, 100 kPa) молÑ�рный объём идеального газа (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) молÑ�рный объём идеального газа (273.15 K, 101.325 kPa) molar volume of silicon молÑ�рный объём кремниÑ� Sackur-Tetrode constant (1 K, 100 kPa) поÑ�тоÑ�ннаÑ� Сакура-Тетрода (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) поÑ�тоÑ�ннаÑ� Сакура-Тетрода (1 K, 101.325 kPa) Wien frequency displacement law constant поÑ�тоÑ�ннаÑ� закона Ñ�мещениÑ� Вина по чаÑ�тоте Wien wavelength displacement law constant поÑ�тоÑ�ннаÑ� закона Ñ�мещениÑ� Вина по длине волны standard atmosphere (atm) Ñ�тандартнаÑ� атмоÑ�фера (atm) standard-state pressure (p°) давление Ñ�тандартного Ñ�оÑ�тоÑ�ниÑ� (p°) Angstrom star (Ã…*) ангÑ�трем-звезда (Ã…*) Copper x unit меднаÑ� x-единица Molybdenum x unit молибденоваÑ� x-единица atomic unit of magnetizability атомнаÑ� единица магнитной воÑ�приимчивоÑ�ти atomic unit of mass (mâ‚‘) атомнаÑ� единица маÑ�Ñ�Ñ‹ (mâ‚‘) atomic unit of momentum атомнаÑ� единица импульÑ�а atomic unit of permittivity атомнаÑ� единица диÑ�лектричеÑ�кой проницаемоÑ�ти atomic unit of time атомнаÑ� единица времени atomic unit of velocity атомнаÑ� единица Ñ�короÑ�ти hartree-hertz relationship хартри-герц Ñ�оотношение hartree-inverse meter relationship хартри-обратный метр Ñ�оотношение hartree-joule relationship хартри-джоуль Ñ�оотношение hartree-kelvin relationship хартри-кельвин Ñ�оотношение hartree-kilogram relationship хартри-килограмм Ñ�оотношение shielding difference of d and p in HD разноÑ�ть Ñ�кранированиÑ� d и p в HD shielding difference of t and p in HT разноÑ�ть Ñ�кранированиÑ� t и p в HT pi (Ï€) пи (Ï€) Euler's number (e) чиÑ�ло Эйлера (e) golden ratio (φ) золотое Ñ�ечение (φ) Euler-Mascheroni constant (γ) поÑ�тоÑ�ннаÑ� Эйлера-МаÑ�керони (γ) nominal solar radius номинальный Ñ�олнечный радиуÑ� nominal solar total irradiance номинальнаÑ� полнаÑ� Ñ�олнечнаÑ� облучённоÑ�ть nominal solar luminosity номинальнаÑ� Ñ�ветимоÑ�ть Солнца nominal solar effective temperature номинальнаÑ� Ñ�ффективнаÑ� температура Солнца nominal solar mass parameter номинальный параметр маÑ�Ñ�Ñ‹ Солнца nominal terrestrial equatorial radius номинальный Ñ�кваториальный радиуÑ� Земли nominal terrestrial polar radius номинальный полÑ�рный радиуÑ� Земли nominal terrestrial mass parameter номинальный параметр маÑ�Ñ�Ñ‹ Земли nominal jovian equatorial radius номинальный Ñ�кваториальный радиуÑ� Юпитера nominal jovian polar radius номинальный полÑ�рный радиуÑ� Юпитера nominal jovian mass parameter номинальный параметр маÑ�Ñ�Ñ‹ Юпитера average value of one minus the rate of TCG relative to TCB Ñ�реднее значение единицы минуÑ� Ñ�короÑ�ть TCG отноÑ�ительно TCB solar mass parameter (TCB-compatible) параметр маÑ�Ñ�Ñ‹ Солнца (Ñ�овмеÑ�тимый Ñ� TCB) solar mass parameter (TDB-compatible) параметр маÑ�Ñ�Ñ‹ Солнца (Ñ�овмеÑ�тимый Ñ� TDB) equatorial radius of the Earth (TT-compatible) Ñ�кваториальный радиуÑ� Земли (Ñ�овмеÑ�тимый Ñ� TT) dynamical form factor of the Earth динамичеÑ�кий форм-фактор Земли time rate of change in the dynamical form factor of the Earth Ñ�короÑ�ть изменениÑ� динамичеÑ�кого форм-фактора Земли geocentric gravitational constant (TCB-compatible) геоцентричеÑ�каÑ� гравитационнаÑ� поÑ�тоÑ�ннаÑ� (Ñ�овмеÑ�тимаÑ� Ñ� TCB) geocentric gravitational constant (TT-compatible) геоцентричеÑ�каÑ� гравитационнаÑ� поÑ�тоÑ�ннаÑ� (Ñ�овмеÑ�тимаÑ� Ñ� TT) geocentric gravitational constant (TDB-compatible) геоцентричеÑ�каÑ� гравитационнаÑ� поÑ�тоÑ�ннаÑ� (Ñ�овмеÑ�тимаÑ� Ñ� TDB) potential of the geoid потенциал геоида nominal mean angular velocity of the Earth (TT-compatible) номинальнаÑ� Ñ�реднÑ�Ñ� угловаÑ� Ñ�короÑ�ть Земли (Ñ�овмеÑ�тимаÑ� Ñ� TT) ratio mass of the Moon to the Earth отношение маÑ�Ñ�Ñ‹ Луны к маÑ�Ñ�е Земли ratio of the mass of the Sun to Mercury отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е МеркуриÑ� ratio of the mass of the Sun to Venus отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е Венеры ratio of the mass of the Sun to Mars отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е МарÑ�а ratio of the mass of the Sun to Jupiter отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е Юпитера ratio of the mass of the Sun to Saturn отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е Сатурна ratio of the mass of the Sun to Uranus отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е Урана ratio of the mass of the Sun to Neptune отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е Ð�ептуна ratio of the mass of the Sun to (134340) Pluto отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е (134340) Плутона ratio of the mass of the Sun to (136199) Eris отношение маÑ�Ñ�Ñ‹ Солнца к маÑ�Ñ�е (136199) Эриды ratio of the mass of (1) Ceres to the Sun отношение маÑ�Ñ�Ñ‹ (1) Цереры к маÑ�Ñ�е Солнца ratio of the mass of (2) Pallas to the Sun отношение маÑ�Ñ�Ñ‹ (2) Паллады к маÑ�Ñ�е Солнца ratio of the mass of (4) Vesta to the Sun отношение маÑ�Ñ�Ñ‹ (4) ВеÑ�ты к маÑ�Ñ�е Солнца mean obliquity of the ecliptic at J2000.0 Ñ�редний наклон Ñ�клиптики на J2000.0 Electromagnetic Электромагнитный Compton wavelength Длина волны Комптона Astronomy Ð�Ñ�трономиÑ� ConstantsWidget Domain ОблаÑ�ть Subdomain ПодоблаÑ�ть No match found Совпадений не найдено Name Ð�аименование Value Значение Unit Ед. изм. Search ПоиÑ�к All Ð’Ñ�е CustomKeypadDialog Custom Keypad ПользовательÑ�каÑ� клавиатура Rows: Строки: Columns: Столбцы: Copy preset: Скопировать набор: Basic БазоваÑ� Scientific (wide) Ð�аучнаÑ� (широкаÑ�) Scientific (narrow) Ð�аучнаÑ� (узкаÑ�) Apply Применить Row Строка Column Столбец Label Метка Behavior Поведение Text ТекÑ�Ñ‚ DiagnosticsDialog App Diagnostics ДиагноÑ�тика приложениÑ� Copy to Clipboard Копировать в буфер обмена Editor Unit Единица User unit ПользовательÑ�каÑ� единица User function ПользовательÑ�каÑ� функциÑ� Argument Ð�ргумент Current result:<br/>%1 Текущий результат:<br/>%1 Selection result:<br/>%1 Результат выделениÑ�:<br/>%1 Selection result: n/a Выбранный результат: не определён Selection result: %1 Результат выделениÑ�: %1 second Ñ�екунда metre метр kilogram килограмм mole моль radian радиан steradian Ñ�терадиан degree Celsius градуÑ� ЦельÑ�иÑ� cubic metre кубичеÑ�кий метр cubic millimetre кубичеÑ�кий миллиметр cubic centimetre кубичеÑ�кий Ñ�антиметр cubic decimetre кубичеÑ�кий дециметр cubic kilometre кубичеÑ�кий километр square millimetre квадратный миллиметр square kilometre квадратный километр square metre квадратный метр minute минута hour чаÑ� day день astronomical unit аÑ�трономичеÑ�каÑ� единица degree градуÑ� arcminute угловаÑ� минута arcsecond угловаÑ� Ñ�екунда milliarcsecond миллиугловаÑ� Ñ�екунда microarcsecond микроугловаÑ� Ñ�екунда hectare гектар litre литр tonne тонна Dalton дальтон electronvolt Ñ�лектронвольт Angstrom ангÑ�трем atmosphere атмоÑ�фера atomic mass unit атомнаÑ� единица маÑ�Ñ�Ñ‹ British thermal unit британÑ�каÑ� тепловаÑ� единица calorie калориÑ� carat карат cup чашка cup (Imperial) чашка (имперÑ�каÑ�) cup (Japanese) чашка (Ñ�понÑ�каÑ�) cup (US) чашка (СШÐ�) degree Fahrenheit градуÑ� Фаренгейта fathom фатом fluid ounce (Imperial) жидкаÑ� унциÑ� (имперÑ�каÑ�) fluid ounce (US) жидкаÑ� унциÑ� (СШÐ�) fluid dram (Imperial) жидкаÑ� драхма (имперÑ�каÑ�) fluid dram (US) жидкаÑ� драхма (СШÐ�) foot фут square foot квадратный фут cubic foot кубичеÑ�кий фут gallon (Imperial) галлон (имперÑ�кий) gallon (US) галлон (СШÐ�) gill (Imperial) гилл (имперÑ�кий) gill (US) гилл (СШÐ�) gradian град grain гран gram грамм Hartley хартли Hartree energy unit единица Ñ�нергии Хартри horsepower лошадинаÑ� Ñ�ила inch дюйм square inch квадратный дюйм cubic inch кубичеÑ�кий дюйм karat карат knot узел lightminute Ñ�ветоваÑ� минута lightsecond Ñ�ветоваÑ� Ñ�екунда lightyear Ñ�ветовой год long ton длиннаÑ� тонна mile милÑ� square mile квадратнаÑ� милÑ� cubic mile кубичеÑ�каÑ� милÑ� mile per hour милÑ� в чаÑ� kilometre per hour километр в чаÑ� nautical mile морÑ�каÑ� милÑ� ounce унциÑ� parsec парÑ�ек pint (Imperial) пинта (имперÑ�каÑ�) pint (US) пинта (СШÐ�) pound фунт pounds per square inch фунтов на квадратный дюйм quart (Imperial) кварта (имперÑ�каÑ�) quart (US) кварта (СШÐ�) oil barrel нефтÑ�ной баррель beer barrel (US) пивной баррель (СШÐ�) square yard квадратный Ñ�рд cubic yard кубичеÑ�кий Ñ�рд short ton короткаÑ� тонна tablespoon Ñ�толоваÑ� ложка tablespoon (Australian) Ñ�толоваÑ� ложка (авÑ�тралийÑ�каÑ�) tablespoon (Imperial) Ñ�толоваÑ� ложка (имперÑ�каÑ�) tablespoon (US) Ñ�толоваÑ� ложка (СШÐ�) dessert spoon деÑ�ертнаÑ� ложка teaspoon чайнаÑ� ложка teaspoon (Imperial) чайнаÑ� ложка (имперÑ�каÑ�) teaspoon (US) чайнаÑ� ложка (СШÐ�) turn оборот revolution оборот revolution per minute оборот в минуту week неделÑ� kilowatt hour киловатт-чаÑ� millimetre of mercury миллиметр ртутного Ñ�толба yard Ñ�рд Julian century юлианÑ�кий век Julian year юлианÑ�кий год sidereal year звёздный год tropical year тропичеÑ�кий год Evaluator invalid expression неверное выражение division by zero деление на ноль too time consuming - computation was rejected Ñ�лишком долгое вычиÑ�ление — отмена dimension mismatch - quantities with different dimensions cannot be compared, added, etc. неÑ�оответÑ�твие измерений — величины Ñ� различными измерениÑ�ми не могут быть Ñ�опоÑ�тавлены, добавлены и Ñ‚.д. invalid dimension - operation might require dimensionless arguments невернаÑ� размерноÑ�ть - операциÑ� может требовать безразмерные аргументы Computation aborted - encountered numerical instability ВычиÑ�ление прервано - обнаружена чиÑ�леннаÑ� неуÑ�тойчивоÑ�ть invalid dimension - function might require dimensionless arguments невернаÑ� размерноÑ�ть - функциÑ� может требовать безразмерные аргументы error ошибка unit must not be zero ед. изм. не должна равнÑ�тьÑ�Ñ� нулю Conversion failed - dimension mismatch Ошибка преобразованиÑ� - неÑ�оответÑ�твие размерноÑ�тей unknown function or variable неизвеÑ�тнаÑ� функциÑ� или переменнаÑ� recursion not supported рекурÑ�иÑ� не поддерживаетÑ�Ñ� cannot operate on a NaN нельзÑ� выполнÑ�ть операции Ñ� NaN underflow - tiny result is out of SpeedCrunch's number range Ñ�лишком маленький результат выходит за пределы диапазона чиÑ�ел SpeedCrunch overflow - huge result is out of SpeedCrunch's number range Ñ�лишком большой результат выходит за пределы диапазона чиÑ�ел SpeedCrunch overflow - logic result exceeds maximum of 256 bits результат превышает 256 бит overflow - integer result exceeds maximum limit for integers Ñ�лишком большое целое чиÑ�ло operation is not defined for these arguments операциÑ� не определена длÑ� Ñ�тих аргументов wrong number of arguments неверное чиÑ�ло аргументов does not take NaN as an argument NaN нельзÑ� иÑ�пользовать как аргумент result out of range результат выходит за предел диапазона undefined for argument domain не определено длÑ� облаÑ�ти аргумента computation too expensive вычиÑ�ление Ñ�лишком затратно internal error, please report a bug внутреннÑ�Ñ� ошибка, пожалуйÑ�та, отправьте Ñ�ообщение об ошибке syntax error Ñ�интакÑ�ичеÑ�каÑ� ошибка conversion target must be a unit цель преобразованиÑ� должна быть единицей unknown unit неизвеÑ�тнаÑ� единица %1 is a reserved name, please choose another %1 — зарезервированное имÑ�, выберите другое %1 is a global user definition and cannot be overridden in this session. %1 Ñ�влÑ�етÑ�Ñ� глобальным пользовательÑ�ким определением и не может быть переопределено в Ñ�том Ñ�еанÑ�е. %1 is a variable name, please choose another or delete the variable %1 Ñ�то имÑ� переменной, пожалуйÑ�та, выберите другое имÑ� или удалите Ñ�ущеÑ�твующую переменную argument %1 is used more than once аргумент %1 иÑ�пользуетÑ�Ñ� более одного раза %1 is a built-in unit name, please choose another %1 Ñ�влÑ�етÑ�Ñ� вÑ�троенным именем единицы, выберите другое %1 is a user function name, please choose another or delete the function %1 Ñ�то имÑ� функции, пожалуйÑ�та, выберите другое имÑ� или удалите Ñ�ущеÑ�твующую функцию FunctionRepo max; trials; probability макÑ�имумы; пробы; вероÑ�тноÑ�ти trials; probability пробы; вероÑ�тноÑ�ти hits; trials; probability попаданиÑ�; пробы; вероÑ�тноÑ�ть max; total; hits; trials макÑ�имум; вÑ�его; попаданий; попыток total; hits; trials вÑ�его; попаданий; проб count; total; hits; trials Ñ�чёт; макÑ�.; вÑ�его; попаданий; пробы dividend; divisor делимое; делитель x; exponent_bits; significand_bits [; exponent_bias] x; Ñ�кÑ�понент_бит; мантиÑ�Ñ�а_бит [; ЭкÑ�поненциальнаÑ� запиÑ�ÑŒ_Ñ�мещение] base; x оÑ�нование; x value; modulo значение; модуль base; exponent; modulo оÑ�нование; Ñ�тепень; по модулю events; average_events результаты; Ñ�редние результаты average_events Ñ�редние результаты x [; precision] x [; точноÑ�ть] Absolute Value Ð�бÑ�олютное значение Absolute Deviation Ð�бÑ�олютное отклонение Arc Cosine Ð�рккоÑ�инуÑ� Logical AND ЛогичеÑ�кое И Area Hyperbolic Cosine ГиперболичеÑ�кий ареакоÑ�инуÑ� Area Hyperbolic Sine ГиперболичеÑ�кий ареаÑ�инуÑ� Area Hyperbolic Tangent ГиперболичеÑ�кий ареатангенÑ� Arc Sine Ð�ркÑ�инуÑ� Arc Tangent Ð�рктангенÑ� Arc Tangent with two Arguments Ð�рктангенÑ� Ñ� двумÑ� аргументами Average (Arithmetic Mean) Среднее арифметичеÑ�кое Binomial Cumulative Distribution Function Биномиальное раÑ�пределение Binomial Distribution Mean Среднее биномиальное раÑ�пределение Binomial Probability Mass Function БиномиальнаÑ� функциÑ� вероÑ�тноÑ�ти Binomial Distribution Variance РазброÑ� биномиального раÑ�пределениÑ� Cube Root КубичеÑ�кий корень Complex Conjugate комплекÑ�но-Ñ�опрÑ�жённое Cosine КоÑ�инуÑ� Hyperbolic Cosine ГиперболичеÑ�кий коÑ�инуÑ� Cotangent КотангенÑ� Cosecant КоÑ�еканÑ� Convert Unix timestamp to Date Преобразовать метку времени Unix в дату Degrees of Arc Радианы в градуÑ�Ñ‹ Error Function ФункциÑ� погрешноÑ�ти Complementary Error Function ФункциÑ� дополнительной погрешноÑ�ти Exponential ЭкÑ�поненциальный Fractional Part ДробнаÑ� чаÑ�ть Extension of Factorials [= (x-1)!] Разложение факториала [= (x-1)!] Greatest Common Divisor Ð�аибольший общий делитель Geometric Mean Среднее геометричеÑ�кое Gradians of arc Грады дуги Hypergeometric Cumulative Distribution Function ГипергеометричеÑ�каÑ� функциÑ� раÑ�пределениÑ� Hypergeometric Distribution Mean Среднее гипергеометричеÑ�кое раÑ�пределение Hypergeometric Probability Mass Function ГипергеометричеÑ�каÑ� функциÑ� вероÑ�тноÑ�ти Hypergeometric Distribution Variance РаÑ�хождение гипергеометричеÑ�кого раÑ�пределениÑ� Integer Quotient Целое чаÑ�тное Integer Part ЦелаÑ� чаÑ�ть Imaginary Part МнимаÑ� чаÑ�ть Decode IEEE-754 Binary Value Декодирование двоичного значениÑ� IEEE-754 Encode IEEE-754 Binary Value Кодирование двоичного значениÑ� IEEE-754 Decode 16-bit Half-Precision Value Декодирование ЧиÑ�ла половинной точноÑ�ти 16-бит Encode 16-bit Half-Precision Value Кодирование ЧиÑ�ла половинной точноÑ�ти 16-бит Decode 32-bit Single-Precision Value Декодирование ЧиÑ�ла одинарной точноÑ�ти 32-бит Encode 32-bit Single-Precision Value Кодирование ЧиÑ�ла одинарной точноÑ�ти 32-бит Decode 64-bit Double-Precision Value Декодирование ЧиÑ�ла двойной точноÑ�ти 64-бит Encode 64-bit Double-Precision Value Кодирование ЧиÑ�ла двойной точноÑ�ти 64-бит Decode 128-bit Quad-Precision Value Декодирование ЧиÑ�ла четырехкратной точноÑ�ти 128-бит Encode 128-bit Quad-Precision Value Кодирование ЧиÑ�ла четырехкратной точноÑ�ти 128-бит Binary Logarithm Двоичный логарифм Common Logarithm ДеÑ�Ñ�тичный логарифм Natural Logarithm Ð�атуральный логарифм Logarithm to Arbitrary Base Логарифм по произвольному оÑ�нованию Mask to a bit size БитоваÑ� маÑ�ка Maximum МакÑ�имум Median Value (50th Percentile) Значение Медианы (50 процентиль) Minimum Минимум Modulo По модулю Euclidean Modulo Евклидово деление по модулю Modular Exponentiation Модульное возведение в Ñ�тепень Combination (Binomial Coefficient) СочетаниÑ� (биномиальный коÑ�ффициент) Logical NOT ЛогичеÑ�кое Ð�ЕТ Permutation (Arrangement) ПереÑ�тановка (Соглашение) Convert to Binary Representation ПеревеÑ�ти в Двоичное предÑ�тавление Arithmetic Ð�рифметика Chemistry ХимиÑ� Complex КомплекÑ�ные чиÑ�ла Combinatorics Комбинаторика Probability ВероÑ�тноÑ�ть Statistics СтатиÑ�тика Aggregation Ð�грегациÑ� Random Случайные чиÑ�ла Base conversion Преобразование оÑ�нований Number formatting Форматирование чиÑ�ел Integer arithmetic ЦелочиÑ�леннаÑ� арифметика Special functions Специальные функции Exponential & Logarithmic ЭкÑ�поненциальные и логарифмичеÑ�кие Angle conversion Преобразование углов Trigonometry ТригонометриÑ� Bitwise Битовые операции Floating point ЧиÑ�ла Ñ� плавающей точкой Date & Time Дата и времÑ� Linear algebra ЛинейнаÑ� алгебра unix_timestamp; x hours offset to GMT метка времени Unix; Ñ�мещение чаÑ�ов от GMT yyyymmdd.hhmmss; x hours offset to GMT ггггммдд.ччммÑ�Ñ�; x чаÑ�ов Ñ�мещениÑ� от GMT [digits] [цифры] max [; min] макÑ�. [; мин.] List Literal Литерал Ñ�пиÑ�ка Convert to Padded Binary Representation Преобразовать в двоичное предÑ�тавление Ñ� дополнением Round Toward +∞ (Ceiling) Округлить к +∞ (потолок) Cosine plus Imaginary Sine КоÑ�инуÑ� плюÑ� мнимаÑ� Ñ�инуÑ�оида Convert to Cis Complex Form Преобразовать в комплекÑ�ную форму cis Matrix Column Count КоличеÑ�тво Ñ�толбцов матрицы Population Correlation Matrix (n) Матрица коррелÑ�ции генеральной Ñ�овокупноÑ�ти (n) Sample Correlation Matrix (n-1) ВыборочнаÑ� матрица коррелÑ�ции (n-1) Count КоличеÑ�тво Population Covariance Matrix (n) Матрица ковариации генеральной Ñ�овокупноÑ�ти (n) Sample Covariance Matrix (n-1) ВыборочнаÑ� матрица ковариации (n-1) Cross Product Векторное произведение Convert Date to Unix timestamp Преобразовать дату во временную метку Unix Convert to Decimal Representation ПеревеÑ�ти в ДеÑ�Ñ�тичное предÑ�тавление Determinant Определитель Convert to Sexagesimal Notation Преобразовать в шеÑ�тидеÑ�Ñ�теричную запиÑ�ÑŒ Dot Product СкалÑ�рное произведение Convert to Engineering Notation Преобразовать в инженерную запиÑ�ÑŒ Convert to Exponential Complex Form Преобразовать в Ñ�кÑ�поненциальную комплекÑ�ную форму Round Toward −∞ (Floor) Округлить к −∞ (пол) Flatten Matrix Сделать матрицу плоÑ�кой Least Common Multiple Ð�аименьшее общее кратное Convert to Hexadecimal Representation ПеревеÑ�ти в ШеÑ�тнадцатеричное Ð¿Ñ€ÐµÐ´Ñ�тавление Convert to Padded Hexadecimal Representation Преобразовать в шеÑ�тнадцатеричное предÑ�тавление Ñ� дополнением Inverse Matrix ОбратнаÑ� матрица Round to 16-bit Half-Precision Value Округлить до 16-битного значениÑ� половинной точноÑ�ти Round to 32-bit Single-Precision Value Округлить до 32-битного значениÑ� одинарной точноÑ�ти Round to 64-bit Double-Precision Value Округлить до 64-битного значениÑ� двойной точноÑ�ти Round to 128-bit Quad-Precision Value Округлить до 128-битного значениÑ� четверной точноÑ�ти Residual from 16-bit Half-Precision Rounding ОÑ�таток от округлениÑ� до 16-битной половинной точноÑ�ти Residual from 32-bit Single-Precision Rounding ОÑ�таток от округлениÑ� до 32-битной одинарной точноÑ�ти Residual from 64-bit Double-Precision Rounding ОÑ�таток от округлениÑ� до 64-битной двойной точноÑ�ти Residual from 128-bit Quad-Precision Rounding ОÑ�таток от округлениÑ� до 128-битной четверной точноÑ�ти Substance Mass МаÑ�Ñ�а вещеÑ�тва Molarity МолÑ�рноÑ�ть Molar Mass МолÑ�рнаÑ� маÑ�Ñ�а Median Absolute Deviation Медианное абÑ�олютное отклонение Mean Среднее Numerical Value of Quantity ЧиÑ�ловое значение величины Random Decimal Number Случайное деÑ�Ñ�тичное чиÑ�ло Random Integer Number Случайное целое чиÑ�ло Convert to Rational Representation Преобразовать в рациональное предÑ�тавление Convert to Octal Representation ПеревеÑ�ти в ВоÑ�ьмеричное Ð¿Ñ€ÐµÐ´Ñ�тавление Convert to Padded Octal Representation Преобразовать в воÑ�ьмеричное предÑ�тавление Ñ� дополнением Vector or Matrix Norm Ð�орма вектора или матрицы Logical OR ЛогичеÑ�кое ИЛИ Population Count (Hamming Weight) ЧиÑ�ло единичных битов (веÑ� Ð¥Ñ�мминга) Phase of Complex Number Фаза комплекÑ�ного чиÑ�ла Poissonian Cumulative Distribution Function ДополнительнаÑ� функциÑ� раÑ�пределениÑ� ПуаÑ�Ñ�она Poissonian Distribution Mean СреднÑ�Ñ� функциÑ� раÑ�пределениÑ� ПуаÑ�Ñ�она Poissonian Probability Mass Function ФункциÑ� вероÑ�тноÑ�ти ПуаÑ�Ñ�она Poissonian Distribution Variance РаÑ�хождение раÑ�пределениÑ� ПуаÑ�Ñ�она Convert to Phasor Complex Form Преобразовать в фазорную комплекÑ�ную форму Convert to Rectangular Complex Form Преобразовать в алгебраичеÑ�кую комплекÑ�ную форму Round Half Away from Zero Округлить половины от нулÑ� Round Half Even ОкруглитÑŒ половины к чётному Nth Root Корень n-й Ñ�тепени Convert to Scientific Notation Преобразовать в научную запиÑ�ÑŒ Matrix Row Count КоличеÑ�тво Ñ�трок матрицы List or Matrix Shape Форма Ñ�пиÑ�ка или матрицы Summation Суммирование Population Standard Deviation (n) Стандартное отклонение генеральной Ñ�овокупноÑ�ти (n) Sample Standard Deviation (n-1) Выборочное Ñ�тандартное отклонение (n-1) Round Toward Zero (Truncation) Округлить к нулю (уÑ�ечение) Matrix Trace След матрицы Transpose Matrix ТранÑ�понировать матрицу Population Variance (n) ДиÑ�перÑ�иÑ� генеральной Ñ�овокупноÑ�ти (n) Sample Variance (n-1) ВыборочнаÑ� диÑ�перÑ�иÑ� (n-1) Product Произведение Radians Радиан Matrix Rank Ранг матрицы Real Part ДейÑ�твительнаÑ� чаÑ�ть Secant СеканÑ� Arithmetic Shift Left Ð�рифметичеÑ�кий Ñ�двиг влево Arithmetic Shift Right Ð�рифметичеÑ�кий Ñ�двиг вправо Signum Знак Sine СинуÑ� Hyperbolic Sine ГиперболичеÑ�кий Ñ�инуÑ� Square Root Квадратный корень Sum Сумма Tangent ТангенÑ� Convert to Trigonometric Complex Form Преобразовать в тригонометричеÑ�кую комплекÑ�ную форму Turns Обороты Hyperbolic Tangent ГиперболичеÑ�кий тангенÑ� Sign-extend a value РаÑ�ширенное значение Logical XOR ЛогичеÑ�кое иÑ�ключающее ИЛИ FunctionsWidget Domain ОблаÑ�ть All Ð’Ñ�е Name ИмÑ� Search ПоиÑ�к No match found СовпадениÑ� не найдены Identifier ИмÑ� HistoryWidget Remove All Calculations Above Удалить вÑ�е вычиÑ�лениÑ� выше Remove This Calculation Удалить Ñ�то вычиÑ�ление Remove All Calculations Below Удалить вÑ�е вычиÑ�лениÑ� ниже Keypad Inverse cosine Ð�рккоÑ�инуÑ� The last result ПоÑ�ледний результат Inverse sine Ð�ркÑ�инуÑ� Inverse tangent Ð�рктангенÑ� Evaluate expression ВычиÑ�лить выражение Division Деление Multiplication Умножение Subtraction Вычитание Addition Сложение Clear expression ОчиÑ�тить выражение Cosine КоÑ�инуÑ� Backspace Backspace Scientific notation ЭкÑ�поненциальный формат Exponential ЭкÑ�понента Factorial Факториал Natural logarithm Ð�атуральный логарифм Left parenthesis ЛеваÑ� Ñ�кобка Nth root Корень n-й Ñ�тепени Argument separator Разделитель аргументов Square Квадрат Common logarithm ДеÑ�Ñ�тичный логарифм Modulo ОÑ�таток от делениÑ� Contextual percentage КонтекÑ�тный процент Power Степень Right parenthesis ПраваÑ� Ñ�кобка Sine СинуÑ� Square root Квадратный корень Tangent ТангенÑ� Pi Пи Decimal separator ДеÑ�Ñ�тичный разделитель MainWindow Radian Радиан Degree ГрадуÑ� Gradian Град Binary Двоичный Octal ВоÑ�ьмеричный Hexadecimal ШеÑ�тнадцатеричный Sexagesimal ШеÑ�тидеÑ�Ñ�теричнаÑ� Ñ�иÑ�тема Engineering decimal ТехничеÑ�кое деÑ�Ñ�тичное Scientific decimal Ð�аучное деÑ�Ñ�тичное &Import... &Импортировать... &Quit &Выход Clear E&xpression ОчиÑ�тить Ð’&ыражение Clear &History ОчиÑ�тить &иÑ�торию &Copy &Копировать &Paste &Ð’Ñ�тавить &Select Expression &Выбрать выражение &Constants &КонÑ�танты &Functions &Функции &History &Журнал &Status Bar &Строка Ñ�оÑ�тоÑ�ниÑ� Bitfield Поле бит Use&r Functions ПользовательÑ�кие &функции &Degree &ГрадуÑ� &Radian &Радиан &Gradian &Град Re&volution О&борот Auto-Insert a&ns Ð�втоматичеÑ�ки вÑ�тавлÑ�ть a&ns Automatic &Completion Ð�вто&завершение &Built-in Functions &Ð’Ñ�троенные функции Built-in &Variables Ð’&Ñ�троенные переменные User &Functions &ПользовательÑ�кие функции User Va&riables П&ользовательÑ�кие переменные Open a Private Tab on Startup Открывать приватную вкладку при запуÑ�ке Open and focus a new private tab whenever SpeedCrunch starts. Открывать и активировать новую приватную вкладку при каждом запуÑ�ке SpeedCrunch. Syntax &Highlighting &ПодÑ�ветка Ñ�интакÑ�иÑ�а Group Digits in &Input &Группировать цифры при вводе Automatic Input &Adjustments &Ð�втоматичеÑ�каÑ� корректировка ввода Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ð�втоматичеÑ�ки корректировать операторы, пробелы, Ñ�кобки и Ñ�тепени и разрешать ввод только допуÑ�тимых Ñ�имволов. Group input digits using the selected number format. Группировать вводимые цифры Ñ�оглаÑ�но выбранному формату чиÑ�ел. &Blinking Cursor &Мигающий курÑ�ор Blink the cursor in the expression editor. Включить мигание курÑ�ора в редакторе выражений. &Escape Clears Editor &Escape очищает редактор Clear the focused expression editor with Escape after dismissing any popup or preview. Очищать активный редактор выражений клавишей Escape поÑ�ле закрытиÑ� вÑ�плывающих окон и предпроÑ�мотра. Keep Expression After Evaluation СохранÑ�ть выражение поÑ�ле вычиÑ�лениÑ� Copy New Results Automatically Ð�втоматичеÑ�ки копировать новые результаты &Comma &ЗапÑ�таÑ� &System Default &СиÑ�темные наÑ�тройки &Dot &Точка Dot &And Comma Точка &и запÑ�таÑ� Toward +∞ (&ceil) К +∞ (&ceil) Toward −∞ (&floor) К −∞ (&floor) &Binary &ДвоичнаÑ� &Engineering &Инженерный &Hexadecimal &ШеÑ�тнадцатеричнаÑ� &Octal &ВоÑ�ьмеричнаÑ� &Scientific &Ð�аучный User &Manual РуководÑ�тво &пользователÑ� Issues and &Feedback П&роблемы и отзывы &Donate &Пожертвовать &About SpeedCrunch О про&грамме SpeedCrunch App Diag&nostics &ДиагноÑ�тика приложениÑ� S&plit &Разделить Angle &Mode Р&ежим углов &Complex Form &КомплекÑ�наÑ� форма New Tab Ð�оваÑ� вкладка Constants КонÑ�танты Functions Функции History ИÑ�ториÑ� User Functions ПользовательÑ�кие функции &Font... &Шрифт... &Language... &Язык... &Session &СеанÑ� &Edit &Правка &View &Вид Se&ttings &Ð�аÑ�тройки &Decimal &ДеÑ�Ñ�тичное &Keypad &Клавиатура Always on &Top Ð’Ñ�егда &поверх оÑ�тальных окон Disabled Отключено Small Space Малый интервал Medium Space Средний интервал Large Space Большой интервал &0 Digits &0 цифр поÑ�ле запÑ�той &15 Digits &15 цифр поÑ�ле запÑ�той &2 Digits &2 цифры поÑ�ле запÑ�той &3 Digits &3 цифры поÑ�ле запÑ�той &50 Digits &50 цифр поÑ�ле запÑ�той &8 Digits &8 цифр поÑ�ле запÑ�той &Sexagesimal &ШеÑ�тидеÑ�Ñ�теричнаÑ� Ñ�иÑ�тема Reset All Settings... СброÑ�ить вÑ�е наÑ�тройки... &System &СиÑ�тема SpeedCrunch &Theme &Тема SpeedCrunch &Classic &КлаÑ�Ñ�ичеÑ�кий &Modern &Современный Context Help КонтекÑ�тнаÑ� Ñ�правка &Help &Справка Error Ошибка Can't read from file %1 Ð�е удалоÑ�ÑŒ прочитать файл %1 Import Session Импортировать Ñ�еанÑ� Close Session Закрыть Ñ�еанÑ� Angle Mode: Угловой режим: Notation: ЗапиÑ�ÑŒ: Precision: ТочноÑ�ть: Turn Оборот Revolution Оборот Fixed-point decimal ДеÑ�Ñ�тичнаÑ� Ñ� фикÑ�ированной точкой Rational РациональнаÑ� Automatic decimal Ð�втоматичеÑ�каÑ� деÑ�Ñ�тичнаÑ� Automatic Ð�втоматичеÑ�ки User &Definitions... ПользовательÑ�кие &определениÑ�... New &Tab Ð�оваÑ� &вкладка New &Private Tab &Ð�оваÑ� приватнаÑ� вкладка Keep Сохранить Make Private... Сделать приватной... New &Window Ð�овое &окно &Open... &Открыть... &Rename... П&ереименовать... Clo&ne... &Клонировать... &Close Tab &Закрыть вкладку Reopen Clo&sed Tab О&ткрыть закрытую вкладку Open Sessions &Folder Открыть &папку Ñ�еанÑ�ов &Undo &Отменить &Redo &Повторить Cu&t Ð’Ñ‹&резать Copy &Last Result Копиров&ать поÑ�ледний результат &Wrap in Parentheses &Заключить в Ñ�кобки Full Scr&een Mode П&олноÑ�кранный режим &Basic &БазоваÑ� &Scientific (wide) &Ð�аучнаÑ� (широкаÑ�) Scientific (narrow) Ð�аучнаÑ� (узкаÑ�) &Custom... &ПользовательÑ�каÑ�... Main &Menu Главное &меню User &Variables ПользовательÑ�кие &переменные &Left &Влево &Right Ð’&право &Up Вв&ерх &Down Ð’&низ Close Pa&ne &Закрыть панель User &Units ПользовательÑ�кие &единицы &Turn &Оборот If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. ЕÑ�ли новое выражение начинаетÑ�Ñ� Ñ� +, -, * или /, SpeedCrunch Ñ�начала вÑ�тавлÑ�ет "ans". &Accept with Enter П&ринимать по Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Принимать текущее предложение автодополнениÑ� клавишей Enter без предварительного выбора клавишами Ñ�о Ñ�трелками. &Units &Единицы Show Live Result &Preview Показывать &предпроÑ�мотр результата Save &Window Position on Exit СохранÑ�ть положение &окна при выходе Hover Highlighting ПодÑ�ветка при наведении Group Integer Part Only Группировать только целую чаÑ�ть Number Format... Формат чиÑ�ел... Notation && Precision... ЗапиÑ�ÑŒ и точноÑ�ть... After pressing Enter, keep the entered expression selected in the editor. ПоÑ�ле нажатиÑ� Enter оÑ�тавлÑ�ть введённое выражение выделенным в редакторе. Never Ð�икогда Always Ð’Ñ�егда Only for Single-Line Expressions Только длÑ� одноÑ�трочных выражений Simplify Displayed Expressions Упрощать отображаемые выражениÑ� History Size &Limit... &Ограничение размера иÑ�тории... Remove Trailing &Zeroes &УдалÑ�ть конечные нули Nearest, Half &Away (round) Ближайшее, половины &от нулÑ� (round) Nearest, Half &Even (roundeven) Ближайшее, половины к &чётному (roundeven) Toward &Zero (trunc) К &нулю (trunc) &Fixed-Point &ФикÑ�ированнаÑ� точка &Rational &РациональнаÑ� &Exponential (m·sâ�»Â¹) &ЭкÑ�поненциальнаÑ� (m·sâ�»Â¹) &Fractional (m/s) &ДробнаÑ� (m/s) &Rectangular (a + bi) &Ð�лгебраичеÑ�каÑ� (a + bi) Exponential (reâ�±á¶¿) ЭкÑ�поненциальнаÑ� (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) ТригонометричеÑ�каÑ� (r(cos θ + i·sin θ)) Phasor (r∠θ) ФазорнаÑ� (r∠θ) &Theme... &Тема... Check for &Updates Проверить &обновлениÑ� Source Code ИÑ�ходный код &Zoom &МаÑ�штаб &Results &Результаты Unit Notation ЗапиÑ�ÑŒ единиц Rounding Mode Режим округлениÑ� &Notation &ЗапиÑ�ÑŒ &Imaginary Unit &МнимаÑ� единица &Window &Окно &Editing &Редактирование A&utocomplete Ð�&втодополнение Up/Down Arrow History ИÑ�ториÑ� по Ñ�трелкам вверх/вниз &Appearance &Внешний вид &Menus &Меню &Docks &ЗакреплÑ�емые панели &Input and Results &Ввод и результаты &Disabled &Отключено &Disable &Отключить Close preview Закрыть предпроÑ�мотр Rename... Переименовать... Clone... Клонировать... Close Tab Закрыть вкладку New Private Tab Ð�оваÑ� приватнаÑ� вкладка Open... Открыть... Reopen Closed Tab Открыть закрытую вкладку Split Разделить Left Влево Right Вправо Up Вверх Down Вниз Clear ОчиÑ�тить Delete Удалить %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Приватный Ñ�еанÑ�: Ñ�одержимое удалÑ�етÑ�Ñ� при закрытии. Выберите СеанÑ� > Сохранить, чтобы Ñ�делать его обычным Ñ�еанÑ�ом. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Приватный] Reset All Settings СброÑ�ить вÑ�е наÑ�тройки Reset all settings to their default values? СброÑ�ить вÑ�е наÑ�тройки до значений по умолчанию? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Это включает оформление, редактирование, форматы результатов и параметры окон. Ваши вычиÑ�лениÑ�, открытые Ñ�еанÑ�Ñ‹ и пользовательÑ�кие определениÑ� будут Ñ�охранены. The settings file could not be written. Ð�е удалоÑ�ÑŒ запиÑ�ать файл наÑ�троек. Clear this session's calculations, unfinished expression, variables, functions, and units? ОчиÑ�тить вычиÑ�лениÑ�, незавершённое выражение, переменные, функции и единицы Ñ�того Ñ�еанÑ�а? Global user definitions are kept. Глобальные пользовательÑ�кие определениÑ� Ñ�охранÑ�ÑŽÑ‚Ñ�Ñ�. Make Session Private Сделать Ñ�еанÑ� приватным The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Сохранённый Ñ�еанÑ� %1 будет удалён. Его Ñ�одержимое оÑ�танетÑ�Ñ� открытым в приватном Ñ�еанÑ�е и будет удалено при закрытии Ñ�того Ñ�еанÑ�а или выходе из SpeedCrunch. Make Private Сделать приватной Could not delete the saved session %1. Ð�е удалоÑ�ÑŒ удалить Ñ�охранённый Ñ�еанÑ� %1. Keep Session Сохранить Ñ�еанÑ� Could not save the session. It remains private. Ð�е удалоÑ�ÑŒ Ñ�охранить Ñ�еанÑ�. Он оÑ�таётÑ�Ñ� приватным. Clone Session Клонировать Ñ�еанÑ� Could not save session file %1. Ð�е удалоÑ�ÑŒ Ñ�охранить файл Ñ�еанÑ�а %1. Could not delete session file %1. Ð�е удалоÑ�ÑŒ удалить файл Ñ�еанÑ�а %1. JSON file (*.json);;Any file (*.*) Файл JSON (*.json);;Любой файл (*.*) Export session as JSON ЭкÑ�порт Ñ�еанÑ�а в JSON The selected file is not valid JSON: %1 Выбранный файл не Ñ�влÑ�етÑ�Ñ� допуÑ�тимым JSON: %1 The selected file is not a SpeedCrunch session JSON file. Выбранный файл не Ñ�влÑ�етÑ�Ñ� JSON-файлом Ñ�еанÑ�а SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Этот файл иÑ�пользует уÑ�таревший формат Ñ�еанÑ�а SpeedCrunch и не может быть импортирован. The selected JSON file is missing the required $schema field. Ð’ выбранном JSON-файле отÑ�утÑ�твует обÑ�зательное поле $schema. The selected JSON file uses an unsupported JSON schema: %1 Выбранный JSON-файл иÑ�пользует неподдерживаемую Ñ�хему JSON: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Ð’ выбранном JSON-файле отÑ�утÑ�твует идентификатор Ñ�хемы Ñ�еанÑ�а SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Выбранный JSON-файл иÑ�пользует неподдерживаемый формат Ñ�еанÑ�а SpeedCrunch: %1 The selected JSON file is missing the required session name. Ð’ выбранном JSON-файле отÑ�утÑ�твует обÑ�зательное имÑ� Ñ�еанÑ�а. The selected JSON file has an empty session name. Ð’ выбранном JSON-файле указано пуÑ�тое имÑ� Ñ�еанÑ�а. The selected JSON file has invalid or incomplete SpeedCrunch session data. Выбранный JSON-файл Ñ�одержит недопуÑ�тимые или неполные данные Ñ�еанÑ�а SpeedCrunch. Open Sessions Folder Открыть папку Ñ�еанÑ�ов Could not create the sessions folder: %1 Ð�е удалоÑ�ÑŒ Ñ�оздать папку Ñ�еанÑ�ов: %1 Could not open the sessions folder: %1 Ð�е удалоÑ�ÑŒ открыть папку Ñ�еанÑ�ов: %1 Editor and Results Font Шрифт редактора и результатов Open Session Открыть Ñ�еанÑ� Community СообщеÑ�тво Rename Session Переименовать Ñ�еанÑ� Clear Session ОчиÑ�тить Ñ�еанÑ� Delete Session Удалить Ñ�еанÑ� Close Pane Закрыть панель User Variables ПользовательÑ�кие переменные User Units ПользовательÑ�кие единицы Clear History ОчиÑ�тить иÑ�торию Are you sure you want to clear the calculation history? Ð’Ñ‹ дейÑ�твительно хотите очиÑ�тить иÑ�торию вычиÑ�лений? Session name: ИмÑ� Ñ�еанÑ�а: A session named %1 already exists. СеанÑ� Ñ� именем %1 уже Ñ�ущеÑ�твует. Could not create session file %1. Ð�е удалоÑ�ÑŒ Ñ�оздать файл Ñ�еанÑ�а %1. Could not write session file %1. Ð�е удалоÑ�ÑŒ запиÑ�ать файл Ñ�еанÑ�а %1. Are you sure you want to delete this session? Ð’Ñ‹ дейÑ�твительно хотите удалить Ñ�тот Ñ�еанÑ�? Custom Precision ПользовательÑ�каÑ� точноÑ�ть Fractional digits: Дробные разрÑ�ды: Theme Тема Light Themes Светлые темы Dark Themes Тёмные темы Preview ПредпроÑ�мотр Colors Цвета Select color for %1 Выберите цвет длÑ� %1 Import... Импорт... Export... ЭкÑ�порт... Import Theme Импорт темы Theme file (*.json);;All files (*) Файл темы (*.json);;Ð’Ñ�е файлы (*) Invalid theme file. Ð�едопуÑ�тимый файл темы. Can't import theme "%1" because it conflicts with a built-in theme. Ð�ельзÑ� импортировать тему "%1", потому что она конфликтует Ñ�о вÑ�троенной темой. Can't find a writable theme folder. Ð�е удаётÑ�Ñ� найти доÑ�тупную длÑ� запиÑ�и папку тем. Overwrite Theme ПерезапиÑ�ать тему A custom theme named "%1" already exists. Do you want to overwrite it? ПользовательÑ�каÑ� тема Ñ� именем "%1" уже Ñ�ущеÑ�твует. ПерезапиÑ�ать её? Can't overwrite theme file %1 Ð�е удаётÑ�Ñ� перезапиÑ�ать файл темы %1 Can't copy theme file to %1 Ð�е удаётÑ�Ñ� Ñ�копировать файл темы в %1 Export Theme ЭкÑ�порт темы Can't export theme as "%1" because it conflicts with a built-in theme. Ð�ельзÑ� Ñ�кÑ�портировать тему как "%1", потому что она конфликтует Ñ�о вÑ�троенной темой. Can't write to file %1 Ð�е удалоÑ�ÑŒ запиÑ�ать файл %1 Global User Variable ГлобальнаÑ� пользовательÑ�каÑ� переменнаÑ� Global User Function ГлобальнаÑ� пользовательÑ�каÑ� функциÑ� Global User Unit ГлобальнаÑ� пользовательÑ�каÑ� единица User Definitions ПользовательÑ�кие определениÑ� These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Эти определениÑ� Ñ�влÑ�ÑŽÑ‚Ñ�Ñ� глобальными и загружаютÑ�Ñ� в каждый Ñ�еанÑ�. Их нельзÑ� изменÑ�ть в Ñ�еанÑ�ах, и они имеют приоритет над одноимёнными определениÑ�ми из редактора Ñ�еанÑ�а. Вводите по одному определению в Ñ�троке. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Примеры: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Применить Validate Проверить Test Results Результаты проверки Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Импортированные переменные: %1 Импортированные функции: %2 Импортированные единицы: %3 Ð�омера Ñ�трок Ñ� ошибками: %4 none нет Apply Results Результаты применениÑ� User definitions saved. ПользовательÑ�кие определениÑ� Ñ�охранены. History Size Limit Ограничение размера иÑ�тории Maximum number of history entries for this session (0 = unlimited): МакÑ�имальное чиÑ�ло запиÑ�ей иÑ�тории длÑ� Ñ�того Ñ�еанÑ�а (0 = без ограничениÑ�): Text file (*.txt);;Any file (*.*) ТекÑ�товый документ (*.txt);;Любой файл (*.*) Could not recalculate from calculation %1: %2 Ð�е удалоÑ�ÑŒ переÑ�читать начинаÑ� Ñ� вычиÑ�лениÑ� %1: %2 History Size Limit Reached ДоÑ�тигнуто ограничение размера иÑ�тории This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Это вычиÑ�ление занимает поÑ�ледний доÑ�тупный Ñ�лот иÑ�тории. Следующие вычиÑ�лениÑ� будут удалÑ�ть Ñ�амые Ñ�тарые запиÑ�и из иÑ�тории. Ограничение можно увеличить в меню СеанÑ� > Ограничение размера иÑ�тории. Editing calculation. Press Esc twice to cancel. Редактирование вычиÑ�лениÑ�. Ð�ажмите Esc дважды длÑ� отмены. Calculation Settings Параметры вычиÑ�лениÑ� Invalid recalculation start index Ð�едопуÑ�тимый начальный индекÑ� переÑ�чёта System Default ПринÑ�тый в Ñ�иÑ�теме Language Язык Select the language: Выберите Ñ�зык: Custom ПользовательÑ�кий Decimal places: ДеÑ�Ñ�тичных знаков: &Automatic &Ð�втоматичеÑ�ки &Precision &ТочноÑ�ть Plain &text ПроÑ�той &текÑ�Ñ‚ Formula &Book Справочник &формул &Export &ЭкÑ�порт Export session as HTML ЭкÑ�порт Ñ�еанÑ�а в HTML-формат HTML file (*.html) Файл HTML (*.html) Export session as plain text ЭкÑ�порт Ñ�еанÑ�а в текÑ�товый формат ManualWindow SpeedCrunch Manual РуководÑ�тво по SpeedCrunch %1 - SpeedCrunch Manual %1 - РуководÑ�тво по SpeedCrunch NumberFormatDialog Number Format Формат чиÑ�ел <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Выберите формат чиÑ�ел длÑ� результатов и группировки цифр при вводе.</b><br/><br/>Примечание: однозначные форматы вводимых чиÑ�ел принимаютÑ�Ñ�, даже еÑ�ли они отличаютÑ�Ñ� от выбранного формата отображениÑ�.<br/> QObject Global User Variable ГлобальнаÑ� пользовательÑ�каÑ� переменнаÑ� Global User Function ГлобальнаÑ� пользовательÑ�каÑ� функциÑ� Global User Unit ГлобальнаÑ� пользовательÑ�каÑ� единица Backspace Backspace Clear expression ОчиÑ�тить выражение Evaluate expression ВычиÑ�лить выражение Insert text Ð’Ñ�тавить текÑ�Ñ‚ Automatic decimal Ð�втоматичеÑ�каÑ� деÑ�Ñ�тичнаÑ� Fixed-point decimal ДеÑ�Ñ�тичнаÑ� Ñ� фикÑ�ированной точкой Engineering decimal ИнженернаÑ� деÑ�Ñ�тичнаÑ� Scientific decimal Ð�аучнаÑ� деÑ�Ñ�тичнаÑ� Rational РациональнаÑ� Binary ДвоичнаÑ� Octal ВоÑ�ьмеричнаÑ� Hexadecimal ШеÑ�тнадцатеричнаÑ� Sexagesimal ШеÑ�тидеÑ�Ñ�теричнаÑ� Update Available ДоÑ�тупно обновление A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> ДоÑ�тупна новаÑ� верÑ�иÑ� (%1).<br/><a href="%2">ПоÑ�етите Ñ�айт длÑ� загрузки.</a> Check for Updates Проверка обновлений SpeedCrunch %1 is up to date. SpeedCrunch %1 не требует обновлениÑ�. No connectivity. Please check your internet connection and try again. Ð�ет подключениÑ�. Проверьте подключение к интернету и повторите попытку. Could not verify the latest available version. Ð�е удалоÑ�ÑŒ проверить поÑ�леднюю доÑ�тупную верÑ�ию. ResultDisplay Scroll to bottom Прокрутить вниз Edit Expression Редактировать выражение Change Settings Изменить параметры New Tab Ð�оваÑ� вкладка &Import... &Импортировать... &Export &ЭкÑ�порт Plain &text ПроÑ�той &текÑ�Ñ‚ Copy Копировать Selection Выделение Select All Выделить вÑ�Ñ‘ Expression Выражение Result Результат Calculation ВычиÑ�ление Calculation as Single Line ВычиÑ�ление в одну Ñ�троку Remove Удалить This Calculation Это вычиÑ�ление All Calculations Above Ð’Ñ�е вычиÑ�лениÑ� выше All Calculations Below Ð’Ñ�е вычиÑ�лениÑ� ниже New Private Tab Ð�оваÑ� приватнаÑ� вкладка Session СеанÑ� Open... Открыть... Clone... Клонировать... Rename... Переименовать... Keep Сохранить Make Private... Сделать приватной... Clear ОчиÑ�тить Delete Удалить Close Закрыть Split Разделить Left Влево Right Вправо Up Вверх Down Вниз Close Pane Закрыть панель Main Menu Главное меню Cancel editing Отменить редактирование Copy result Копировать результат Edit expression Редактировать выражение Change settings Изменить параметры Remove calculation Удалить вычиÑ�ление ResultSlotsDialog Notation & Precision ЗапиÑ�ÑŒ и точноÑ�ть Result Line Строка результата Enabled Включено Notation ЗапиÑ�ÑŒ Decimal Places ДеÑ�Ñ�тичных знаков Main Line ОÑ�новнаÑ� Ñ�трока Extra Line #1 ДополнительнаÑ� Ñ�трока â„–1 Extra Line #2 ДополнительнаÑ� Ñ�трока â„–2 Extra Line #3 ДополнительнаÑ� Ñ�трока â„–3 Extra Line #4 ДополнительнаÑ� Ñ�трока â„–4 Auto Ð�вто UserFunctionListWidget Name ИмÑ� Value Значение Description ОпиÑ�ание Search ПоиÑ�к No match found СовпадениÑ� не найдены Insert Ð’Ñ�тавить Edit Правка Delete Удалить Delete All Удалить вÑ�Ñ‘ UserUnitListWidget Name ИмÑ� Value Значение Description ОпиÑ�ание Search ПоиÑ�к No match found Совпадений не найдено Insert Ð’Ñ�тавить Edit Изменить Delete Удалить Delete All Удалить вÑ�е VariableListWidget Name Ð�аименование Value Значение Description ОпиÑ�ание Search ПоиÑ�к No match found Совпадений не найдено Insert Ð’Ñ�тавить Edit Изменить Delete Удалить Delete All Удалить вÑ�Ñ‘ heldercorreia-speedcrunch-e7ca37f/src/resources/locale/sk.ts000066400000000000000000010554401526573132500243730ustar00rootroot00000000000000 AboutBox About SpeedCrunch O programe SpeedCrunch Core developers Hlavní vývojári Original author Pôvodný autor Close ZavrieÅ¥ Math engine Matematické jadro Main author | Logo | Maintainer Hlavný autor | Logo | Správca Thanks PoÄ�akovanie Copyright (C) 2004-2026 The SpeedCrunch developers Autorské práva (C) 2004-2026 vývojári SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Tento program je slobodný softvér; môžete ho redistribuovaÅ¥ a / alebo upraviÅ¥ podľa podmienok GNU General Public License, ktoré sú zverejnené Nadáciou Free Software Foundation; buÄ� licenÄ�nou verziou 2, alebo (podľa vlastného uváženia) akoukoľvek novÅ¡ou verziou This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Tento program je distribuovaný v nádeji, že bude užitoÄ�ný, ale BEZ AKEJKOĽVEK ZÃ�RUKY; bez predpokladanej záruky OBCHODOVATEĽNOSTI alebo VHODNOSTI NA KONKRÉTNY ÚČEL. Viac informácií nájdete v GNU General Public License. BitFieldWidget Reset bits to zero VynulovaÅ¥ bity Invert bits InvertovaÅ¥ bity Shift bits left Posunúť bity doľava Shift bits right Posunúť bity doprava Book Index Register Algebra Algebra Quadratic Equation Kvadratická rovnica Logarithmic Base Conversion Prevod základu logaritmu Geometry Geometria Circle Kruh Sector Výsek Sphere Guľa Cube Kocka Cone Kužeľ Cylinder Valec Electronics Elektronika Ohm's Law Ohmov zákon Power Výkon Reactance Reaktancia Resonance Rezonancia Radio Frequency Rádiofrekvencia Antennas Antény Characteristic Impedance (coax) Charakteristická impedancia (koaxiálna) Velocity of Propagation (coax) RýchlosÅ¥ šírenia (koaxiálna) Standing Wave Ratio & Return Loss Pomer stojatých vĺn a útlm odrazu Free Space Wavelength Vlnová dĺžka vo voľnom priestore resistance odpor voltage napätie current aktuálny power výkon inductive reactance indukÄ�ná reaktancia capacitive reactance kapacitná reaktancia inductance indukÄ�nosÅ¥ capacitance kapacita frequency frekvencia resonance frequency rezonanÄ�ná frekvencia area plocha perimeter obvod diameter priemer radius polomer volume objem surface area plocha povrchu height výška slant height Å¡ikmá výška face diagonal uhloprieÄ�ka steny space diagonal telesová uhloprieÄ�ka edge length dĺžka hrany arc length dĺžka oblúka central angle (degrees) stredový uhol (stupne) input power vstupný výkon reflected power odrazený výkon transmitted power prenesený výkon return loss útlm odrazu dielectric constant dielektrická konÅ¡tanta outer conductor's inner diameter vnútorný priemer vonkajÅ¡ieho vodiÄ�a inner conductor's outer diameter vonkajší priemer vnútorného vodiÄ�a speed of light rýchlosÅ¥ svetla reflection coefficient koeficient odrazu standing wave ratio pomer stojatých vĺn normalized impedance normalizovaná impedancia frequency (Hz) frekvencia (Hz) BookDock Formula Book Kniha vzorcov ConstantCompletion Search constants HľadaÅ¥ konÅ¡tanty No match found NenaÅ¡la sa žiadna zhoda Constants Mathematics Matematika Physics (CODATA 2022) Fyzika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Chémia (IUPAC - CIAAW 2021) Uncategorized Nezaradené Universal Univerzálne Physicochemical Fyzikálno-chemické Atomic & Nuclear — General Atómové a jadrové — vÅ¡eobecné Atomic & Nuclear — Electroweak Atómové a jadrové — elektroslabé Atomic & Nuclear — Electron Atómové a jadrové — elektrón Atomic & Nuclear — Muon Atómové a jadrové — mión Atomic & Nuclear — Tau Atómové a jadrové — tau Atomic & Nuclear — Proton Atómové a jadrové — protón Atomic & Nuclear — Neutron Atómové a jadrové — neutrón Atomic & Nuclear — Deuteron Atómové a jadrové — deuterón Atomic & Nuclear — Triton Atómové a jadrové — tritón Atomic & Nuclear — Helion Atómové a jadrové — hélión Atomic & Nuclear — Alpha particle Atómové a jadrové — alfa Ä�astica Atomic & Nuclear — Atomic units Atómové a jadrové — atómové jednotky Atomic & Nuclear — Energy conversion relationships Atómové a jadrové — vzÅ¥ahy premeny energie Atomic & Nuclear — X-ray units Atómové a jadrové — röntgenové jednotky Atomic & Nuclear — Magnetic shielding corrections Atómové a jadrové — korekcie magnetického tienenia Masses Hmotnosti Lifetimes Doby života Molar Masses Molárne hmotnosti Electronegativity Elektronegativita Ionization Energy IonizaÄ�ná energia Nominal Constants (IAU 2015) Nominálne konÅ¡tanty (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Aktuálne najlepÅ¡ie odhady (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) Charakteristická impedancia vacuum (Zâ‚€) reduced Planck constant (â„�) Redukovaná Planckova konÅ¡tanta (â„�) vacuum electric permittivity (ϵ₀) Elektrická permitivita vákua (ϵ₀) Newtonian constant of gravitation (G) Newtonova gravitaÄ�ná konÅ¡tanta (G) vacuum magnetic permeability (μ₀) Magnetická permeabilita vákua (μ₀) Planck constant (h) Planckova konÅ¡tanta (h) speed of light in vacuum (c) RýchlosÅ¥ svetla vo vákuu (c) standard acceleration of gravity (gâ‚™) Å tandardné gravitaÄ�né zrýchlenie (gâ‚™) Newtonian constant of gravitation over h-bar c Newtonova gravitaÄ�ná konÅ¡tanta delená h-bar c Planck length Planckova dĺžka Planck constant in eV/Hz (h) Planckova konÅ¡tanta v eV/Hz (h) Planck mass Planckova hmotnosÅ¥ Planck mass energy equivalent in GeV Energetický ekvivalent Planckovej hmotnosti v GeV Planck temperature Planckova teplota Planck time Planckov Ä�as reduced Planck constant in eV·s (â„�) Redukovaná Planckova konÅ¡tanta v eV·s (â„�) reduced Planck constant times c in MeV·fm Redukovaná Planckova konÅ¡tanta Ä�ass c v MeV·fm Bohr magneton Bohrov magnetón conductance quantum (Gâ‚€) Kvantum vodivosti (Gâ‚€) Coulomb constant (kâ‚‘) Coulombova konÅ¡tanta (kâ‚‘) elementary charge (e) Elementárny náboj (e) elementary charge over h-bar Elementárny náboj delená h-bar conventional value of Josephson constant KonvenÄ�ná hodnota Josephsonova konÅ¡tanta Josephson constant Josephsonova konÅ¡tanta conventional value of ampere-90 KonvenÄ�ná hodnota ampere-90 conventional value of coulomb-90 KonvenÄ�ná hodnota coulomb-90 conventional value of farad-90 KonvenÄ�ná hodnota farad-90 conventional value of henry-90 KonvenÄ�ná hodnota henry-90 conventional value of ohm-90 KonvenÄ�ná hodnota ohm-90 conventional value of volt-90 KonvenÄ�ná hodnota volt-90 conventional value of watt-90 KonvenÄ�ná hodnota watt-90 magnetic flux quantum (Φ₀) Kvantum magnetického toku (Φ₀) nuclear magneton Jadrový magnetón inverse of conductance quantum prevrátená hodnota kvanta vodivosti conventional value of von Klitzing constant KonvenÄ�ná hodnota von Klitzingova konÅ¡tanta von Klitzing constant Von Klitzingova konÅ¡tanta atomic unit of magnetic dipole moment Atómová jednotka magnetický dipólový moment atomic unit of magnetic flux density Atómová jednotka hustota magnetického toku Bohr magneton in eV/T Bohrov magnetón v eV/T Bohr magneton in Hz/T Bohrov magnetón v Hz/T Bohr magneton in inverse meter per tesla Bohrov magnetón v prevrátený meter na tesla Bohr magneton in K/T Bohrov magnetón v K/T nuclear magneton in eV/T Jadrový magnetón v eV/T nuclear magneton in inverse meter per tesla Jadrový magnetón v prevrátený meter na tesla nuclear magneton in K/T Jadrový magnetón v K/T nuclear magneton in MHz/T Jadrový magnetón v MHz/T Bohr radius (aâ‚€) Bohrov polomer (aâ‚€) fine-structure constant (α) KonÅ¡tanta jemnej Å¡truktúry (α) Hartree energy (Eâ‚•) Hartreeho energia (Eâ‚•) Hartree energy in eV Hartreeho energia v eV quantum of circulation Kvantum cirkulácie quantum of circulation times 2 Kvantum cirkulácie Ä�ass 2 Rydberg constant (R∞) Rydbergova konÅ¡tanta (R∞) atomic mass unit-hartree relationship vzÅ¥ah atómovej hmotnostnej jednotky a hartree atomic mass unit-hertz relationship vzÅ¥ah atómovej hmotnostnej jednotky a hertza atomic mass unit-inverse meter relationship vzÅ¥ah atómovej hmotnostnej jednotky a reciproÄ�ného metra atomic mass unit-joule relationship vzÅ¥ah atómovej hmotnostnej jednotky a joula atomic mass unit-kelvin relationship vzÅ¥ah atómovej hmotnostnej jednotky a kelvina atomic mass unit-kilogram relationship vzÅ¥ah atómovej hmotnostnej jednotky a kilogramu atomic unit of 1st hyperpolarizability Atómová jednotka 1. hyperpolárnyizovateľnosÅ¥ atomic unit of 2nd hyperpolarizability Atómová jednotka 2. hyperpolárnyizovateľnosÅ¥ atomic unit of charge (e) Atómová jednotka charge (e) atomic unit of charge density Atómová jednotka hustota náboja atomic unit of current Atómová jednotka prúd atomic unit of electric dipole moment Atómová jednotka elektrický dipólový moment atomic unit of electric field Atómová jednotka elektrické pole atomic unit of electric field gradient Atómová jednotka gradient elektrického poľa atomic unit of electric polarizability Atómová jednotka elektrická polárnyizovateľnosÅ¥ atomic unit of electric potential Atómová jednotka elektrický potenciál atomic unit of electric quadrupole moment Atómová jednotka elektrický kvadrupólový moment atomic unit of action Atómová jednotka akcia atomic unit of energy Atómová jednotka energia atomic unit of force Atómová jednotka sila atomic unit of length Atómová jednotka dĺžka hertz-atomic mass unit relationship vzÅ¥ah hertza a atómovej hmotnostnej jednotky hertz-electron volt relationship Hertz-elektrón volt vzÅ¥ah hertz-hartree relationship Hertz-hartree vzÅ¥ah hertz-inverse meter relationship vzÅ¥ah hertza a reciproÄ�ného metra hertz-joule relationship Hertz-joule vzÅ¥ah hertz-kelvin relationship Hertz-kelvin vzÅ¥ah hertz-kilogram relationship Hertz-kilogram vzÅ¥ah hyperfine transition frequency of Cs-133 Frekvencia hyperjemného prechodu Cs-133 inverse fine-structure constant (αâ�»Â¹) prevrátená hodnota konÅ¡tanty jemnej Å¡truktúry (αâ�»Â¹) inverse meter-atomic mass unit relationship vzÅ¥ah reciproÄ�ného metra a atómovej hmotnostnej jednotky inverse meter-electron volt relationship vzÅ¥ah reciproÄ�ného metra a elektrónvoltu inverse meter-hartree relationship vzÅ¥ah reciproÄ�ného metra a hartree inverse meter-hertz relationship vzÅ¥ah reciproÄ�ného metra a hertza inverse meter-joule relationship vzÅ¥ah reciproÄ�ného metra a joula inverse meter-kelvin relationship vzÅ¥ah reciproÄ�ného metra a kelvina inverse meter-kilogram relationship vzÅ¥ah reciproÄ�ného metra a kilogramu joule-atomic mass unit relationship vzÅ¥ah joula a atómovej hmotnostnej jednotky joule-electron volt relationship Joule-elektrón volt vzÅ¥ah joule-hertz relationship Joule-hertz vzÅ¥ah joule-hartree relationship Joule-hartree vzÅ¥ah joule-inverse meter relationship vzÅ¥ah joula a reciproÄ�ného metra joule-kelvin relationship Joule-kelvin vzÅ¥ah joule-kilogram relationship Joule-kilogram vzÅ¥ah kelvin-atomic mass unit relationship vzÅ¥ah kelvina a atómovej hmotnostnej jednotky kelvin-electron volt relationship Kelvin-elektrón volt vzÅ¥ah kelvin-hertz relationship Kelvin-hertz vzÅ¥ah kelvin-hartree relationship Kelvin-hartree vzÅ¥ah kelvin-inverse meter relationship vzÅ¥ah kelvina a reciproÄ�ného metra kelvin-joule relationship Kelvin-joule vzÅ¥ah kelvin-kilogram relationship Kelvin-kilogram vzÅ¥ah kilogram-atomic mass unit relationship vzÅ¥ah kilogramu a atómovej hmotnostnej jednotky kilogram-electron volt relationship Kilogram-elektrón volt vzÅ¥ah kilogram-hertz relationship Kilogram-hertz vzÅ¥ah kilogram-hartree relationship Kilogram-hartree vzÅ¥ah kilogram-inverse meter relationship vzÅ¥ah kilogramu a reciproÄ�ného metra kilogram-joule relationship Kilogram-joule vzÅ¥ah kilogram-kelvin relationship Kilogram-kelvin vzÅ¥ah lattice parameter of silicon (a) Mriežkový parameter silicon (a) luminous efficacy Svetelná úÄ�innosÅ¥ natural unit of energy Prirodzená jednotka energia natural unit of energy in MeV Prirodzená jednotka energia v MeV natural unit of action (â„�) Prirodzená jednotka akcia (â„�) natural unit of action in eV·s Prirodzená jednotka akcia v eV·s natural unit of length Prirodzená jednotka dĺžka natural unit of mass prirodzená jednotka hmotnosti natural unit of momentum Prirodzená jednotka hybnosÅ¥ natural unit of momentum in MeV/c Prirodzená jednotka hybnosÅ¥ v MeV/c natural unit of time Prirodzená jednotka Ä�as natural unit of velocity Prirodzená jednotka rýchlosÅ¥ Rydberg constant times c in Hz Rydbergova konÅ¡tanta Ä�ass c v Hz Rydberg constant times hc in eV Rydbergova konÅ¡tanta Ä�ass hc v eV Rydberg constant times hc in J Rydbergova konÅ¡tanta Ä�ass hc v J Fermi coupling constant Fermiho väzbová konÅ¡tanta weak mixing angle Slabý zmieÅ¡avací uhol W to Z mass ratio W k Z hmotnostný pomer Thomson cross section (σₑ) Thomsonov úÄ�inný prierez (σₑ) electron mass (mâ‚‘) hmotnosÅ¥ elektrónu (mâ‚‘) electron mass in u hmotnosÅ¥ elektrónu v u electron mass energy equivalent (mₑ·c²) energetický ekvivalent hmotnosti elektrónu (mₑ·c²) electron mass energy equivalent in MeV energetický ekvivalent hmotnosti elektrónu v MeV reduced Compton wavelength Reduced Compton wavedĺžka classical electron radius (râ‚‘) Classical elektrón polomer (râ‚‘) electron charge to mass quotient Elektrón podiel náboja a hmotnosti electron-deuteron magnetic moment ratio Elektrón-deuterón pomer magnetických momentov electron-deuteron mass ratio Elektrón-deuterón hmotnostný pomer electron g factor (gâ‚‘) Elektrón g-faktor (gâ‚‘) electron gyromagnetic ratio (γₑ) Elektrón gyromagnetický pomer (γₑ) electron gyromagnetic ratio in MHz/T Elektrón gyromagnetický pomer v MHz/T electron-helion mass ratio Elektrón-hélión hmotnostný pomer electron magnetic moment (μₑ) Elektrón magnetický moment (μₑ) electron magnetic moment anomaly (aâ‚‘) Elektrón magnetický moment anomália (aâ‚‘) electron magnetic moment to Bohr magneton ratio Elektrón magnetický moment k Bohrov magnetón ratio electron magnetic moment to nuclear magneton ratio Elektrón magnetický moment k jadrový magnetón ratio electron molar mass (Mâ‚‘) Elektrón molárna hmotnosÅ¥ (Mâ‚‘) electron-muon magnetic moment ratio Elektrón-mión pomer magnetických momentov electron-muon mass ratio Elektrón-mión hmotnostný pomer electron-neutron magnetic moment ratio Elektrón-neutrón pomer magnetických momentov electron-neutron mass ratio Elektrón-neutrón hmotnostný pomer electron-proton magnetic moment ratio Elektrón-protón pomer magnetických momentov electron-proton mass ratio Elektrón-protón hmotnostný pomer electron relative atomic mass (Ar(e)) Elektrón relatívna atómová hmotnosÅ¥ (Ar(e)) electron-tau mass ratio Elektrón-tau hmotnostný pomer electron to alpha particle mass ratio Elektrón k alfa Ä�astica hmotnostný pomer electron to shielded helion magnetic moment ratio Elektrón k tienený hélión pomer magnetických momentov electron to shielded proton magnetic moment ratio Elektrón k tienený protón pomer magnetických momentov electron-triton mass ratio Elektrón-tritón hmotnostný pomer electron volt-atomic mass unit relationship vzÅ¥ah elektrónvoltu a atómovej hmotnostnej jednotky electron volt-hartree relationship Elektrón volt-hartree vzÅ¥ah electron volt-hertz relationship Elektrón volt-hertz vzÅ¥ah electron volt-inverse meter relationship vzÅ¥ah elektrónvoltu a reciproÄ�ného metra electron volt-joule relationship Elektrón volt-joule vzÅ¥ah electron volt-kelvin relationship Elektrón volt-kelvin vzÅ¥ah electron volt-kilogram relationship Elektrón volt-kilogram vzÅ¥ah hartree-atomic mass unit relationship vzÅ¥ah hartree a atómovej hmotnostnej jednotky hartree-electron volt relationship Hartree-elektrón volt vzÅ¥ah muon Compton wavelength Mión Compton wavedĺžka muon-electron mass ratio Mión-elektrón hmotnostný pomer muon g factor Mión g-faktor muon magnetic moment Mión magnetický moment muon magnetic moment anomaly Mión magnetický moment anomália muon magnetic moment to Bohr magneton ratio Mión magnetický moment k Bohrov magnetón ratio muon magnetic moment to nuclear magneton ratio Mión magnetický moment k jadrový magnetón ratio muon mass hmotnosÅ¥ miónu muon mass energy equivalent energetický ekvivalent hmotnosti miónu muon mass energy equivalent in MeV energetický ekvivalent hmotnosti miónu v MeV muon mass in u hmotnosÅ¥ miónu v u muon molar mass Mión molárna hmotnosÅ¥ muon-neutron mass ratio Mión-neutrón hmotnostný pomer muon-proton magnetic moment ratio Mión-protón pomer magnetických momentov muon-proton mass ratio Mión-protón hmotnostný pomer muon-tau mass ratio Mión-tau hmotnostný pomer reduced muon Compton wavelength Reduced mión Compton wavedĺžka reduced tau Compton wavelength Reduced tau Compton wavedĺžka tau Compton wavelength Tau Compton wavedĺžka tau-electron mass ratio Tau-elektrón hmotnostný pomer tau mass hmotnosÅ¥ tau leptónu tau mass energy equivalent energetický ekvivalent hmotnosti tau leptónu tau mass in u hmotnosÅ¥ tau leptónu v u tau molar mass Tau molárna hmotnosÅ¥ tau-muon mass ratio Tau-mión hmotnostný pomer tau-neutron mass ratio Tau-neutrón hmotnostný pomer tau-proton mass ratio Tau-protón hmotnostný pomer proton charge to mass quotient Protón podiel náboja a hmotnosti proton Compton wavelength Protón Compton wavedĺžka proton-electron mass ratio Protón-elektrón hmotnostný pomer proton g factor (gₚ) Protón g-faktor (gₚ) proton gyromagnetic ratio (γₚ) Protón gyromagnetický pomer (γₚ) proton gyromagnetic ratio in MHz/T Protón gyromagnetický pomer v MHz/T proton magnetic moment (μₚ) Protón magnetický moment (μₚ) proton magnetic moment to Bohr magneton ratio Protón magnetický moment k Bohrov magnetón ratio proton magnetic moment to nuclear magneton ratio Protón magnetický moment k jadrový magnetón ratio proton magnetic shielding correction Protón magnetic tienenie korekcia proton mass (mₚ) hmotnosÅ¥ protónu (mₚ) proton mass energy equivalent energetický ekvivalent hmotnosti protónu proton mass energy equivalent in MeV energetický ekvivalent hmotnosti protónu v MeV proton mass in u hmotnosÅ¥ protónu v u proton molar mass (Mₚ) Protón molárna hmotnosÅ¥ (Mₚ) proton-muon mass ratio Protón-mión hmotnostný pomer proton-neutron magnetic moment ratio Protón-neutrón pomer magnetických momentov proton-neutron mass ratio Protón-neutrón hmotnostný pomer proton relative atomic mass (Ar(p)) Protón relatívna atómová hmotnosÅ¥ (Ar(p)) proton rms charge radius Protón efektívny polomer náboja proton-tau mass ratio Protón-tau hmotnostný pomer reduced proton Compton wavelength Reduced protón Compton wavedĺžka shielded proton gyromagnetic ratio Tienený protón gyromagnetický pomer shielded proton gyromagnetic ratio in MHz/T Tienený protón gyromagnetický pomer v MHz/T shielded proton magnetic moment Tienený protón magnetický moment shielded proton magnetic moment to Bohr magneton ratio Tienený protón magnetický moment k Bohrov magnetón ratio shielded proton magnetic moment to nuclear magneton ratio Tienený protón magnetický moment k jadrový magnetón ratio neutron Compton wavelength Neutrón Compton wavedĺžka neutron-electron magnetic moment ratio Neutrón-elektrón pomer magnetických momentov neutron-electron mass ratio Neutrón-elektrón hmotnostný pomer neutron g factor (gâ‚™) Neutrón g-faktor (gâ‚™) neutron gyromagnetic ratio (γₙ) Neutrón gyromagnetický pomer (γₙ) neutron gyromagnetic ratio in MHz/T Neutrón gyromagnetický pomer v MHz/T neutron magnetic moment (μₙ) Neutrón magnetický moment (μₙ) neutron magnetic moment to Bohr magneton ratio Neutrón magnetický moment k Bohrov magnetón ratio neutron magnetic moment to nuclear magneton ratio Neutrón magnetický moment k jadrový magnetón ratio neutron mass (mâ‚™) hmotnosÅ¥ neutrónu (mâ‚™) neutron mass energy equivalent energetický ekvivalent hmotnosti neutrónu neutron mass energy equivalent in MeV energetický ekvivalent hmotnosti neutrónu v MeV neutron mass in u hmotnosÅ¥ neutrónu v u neutron molar mass (Mâ‚™) Neutrón molárna hmotnosÅ¥ (Mâ‚™) neutron-muon mass ratio Neutrón-mión hmotnostný pomer neutron-proton magnetic moment ratio Neutrón-protón pomer magnetických momentov neutron-proton mass difference rozdiel hmotností neutrónu a protónu neutron-proton mass difference energy equivalent energetický ekvivalent rozdielu hmotností neutrónu a protónu neutron-proton mass difference energy equivalent in MeV energetický ekvivalent rozdielu hmotností neutrónu a protónu v MeV neutron-proton mass difference in u rozdiel hmotností neutrónu a protónu v u neutron-proton mass ratio Neutrón-protón hmotnostný pomer neutron relative atomic mass (Ar(n)) Neutrón relatívna atómová hmotnosÅ¥ (Ar(n)) neutron-tau mass ratio Neutrón-tau hmotnostný pomer neutron to shielded proton magnetic moment ratio Neutrón k tienený protón pomer magnetických momentov reduced neutron Compton wavelength Reduced neutrón Compton wavedĺžka deuteron-electron magnetic moment ratio Deuterón-elektrón pomer magnetických momentov deuteron-electron mass ratio Deuterón-elektrón hmotnostný pomer deuteron g factor Deuterón g-faktor deuteron magnetic moment Deuterón magnetický moment deuteron magnetic moment to Bohr magneton ratio Deuterón magnetický moment k Bohrov magnetón ratio deuteron magnetic moment to nuclear magneton ratio Deuterón magnetický moment k jadrový magnetón ratio deuteron mass hmotnosÅ¥ deuterónu deuteron mass energy equivalent energetický ekvivalent hmotnosti deuterónu deuteron mass energy equivalent in MeV energetický ekvivalent hmotnosti deuterónu v MeV deuteron mass in u hmotnosÅ¥ deuterónu v u deuteron molar mass Deuterón molárna hmotnosÅ¥ deuteron-neutron magnetic moment ratio Deuterón-neutrón pomer magnetických momentov deuteron-proton magnetic moment ratio Deuterón-protón pomer magnetických momentov deuteron-proton mass ratio Deuterón-protón hmotnostný pomer deuteron relative atomic mass (Ar(d)) Deuterón relatívna atómová hmotnosÅ¥ (Ar(d)) deuteron rms charge radius Deuterón efektívny polomer náboja triton-electron mass ratio Tritón-elektrón hmotnostný pomer triton g factor (gₜ) Tritón g-faktor (gₜ) triton magnetic moment (μₜ) Tritón magnetický moment (μₜ) triton magnetic moment to Bohr magneton ratio Tritón magnetický moment k Bohrov magnetón ratio triton magnetic moment to nuclear magneton ratio Tritón magnetický moment k jadrový magnetón ratio triton mass (mₜ) hmotnosÅ¥ tritónu (mₜ) triton mass energy equivalent energetický ekvivalent hmotnosti tritónu triton mass energy equivalent in MeV energetický ekvivalent hmotnosti tritónu v MeV triton mass in u hmotnosÅ¥ tritónu v u triton molar mass (Mₜ) Tritón molárna hmotnosÅ¥ (Mₜ) triton-proton mass ratio Tritón-protón hmotnostný pomer triton relative atomic mass (Ar(t)) Tritón relatívna atómová hmotnosÅ¥ (Ar(t)) triton to proton magnetic moment ratio Tritón k protón pomer magnetických momentov helion-electron mass ratio Hélión-elektrón hmotnostný pomer helion g factor (gâ‚•) Hélión g-faktor (gâ‚•) helion magnetic moment (μₕ) Hélión magnetický moment (μₕ) helion magnetic moment to Bohr magneton ratio Hélión magnetický moment k Bohrov magnetón ratio helion magnetic moment to nuclear magneton ratio Hélión magnetický moment k jadrový magnetón ratio helion mass (mâ‚•) hmotnosÅ¥ héliónu (mâ‚•) helion mass energy equivalent energetický ekvivalent hmotnosti héliónu helion mass energy equivalent in MeV energetický ekvivalent hmotnosti héliónu v MeV helion mass in u hmotnosÅ¥ héliónu v u helion molar mass (Mâ‚•) Hélión molárna hmotnosÅ¥ (Mâ‚•) helion-proton mass ratio Hélión-protón hmotnostný pomer helion relative atomic mass (Ar(h)) Hélión relatívna atómová hmotnosÅ¥ (Ar(h)) helion shielding shift Hélión tienenie shift shielded helion gyromagnetic ratio Tienený hélión gyromagnetický pomer shielded helion gyromagnetic ratio in MHz/T Tienený hélión gyromagnetický pomer v MHz/T shielded helion magnetic moment Tienený hélión magnetický moment shielded helion magnetic moment to Bohr magneton ratio Tienený hélión magnetický moment k Bohrov magnetón ratio shielded helion magnetic moment to nuclear magneton ratio Tienený hélión magnetický moment k jadrový magnetón ratio shielded helion to proton magnetic moment ratio Tienený hélión k protón pomer magnetických momentov shielded helion to shielded proton magnetic moment ratio Tienený hélión k tienený protón pomer magnetických momentov alpha particle mass hmotnosÅ¥ alfa Ä�astice alpha particle mass in u hmotnosÅ¥ alfa Ä�astice v u alpha particle mass energy equivalent energetický ekvivalent hmotnosti alfa Ä�astice alpha particle mass energy equivalent in MeV energetický ekvivalent hmotnosti alfa Ä�astice v MeV alpha particle-electron mass ratio Alfa Ä�astica-elektrón hmotnostný pomer alpha particle-proton mass ratio Alfa Ä�astica-protón hmotnostný pomer alpha particle rms charge radius Alfa Ä�astica efektívny polomer náboja alpha particle molar mass Alfa Ä�astica molárna hmotnosÅ¥ alpha particle relative atomic mass (Ar(α)) Alfa Ä�astica relatívna atómová hmotnosÅ¥ (Ar(α)) atomic mass constant (mᵤ) Atómová hmotnostná konÅ¡tanta (mᵤ) Avogadro constant Avogadrova konÅ¡tanta Boltzmann constant (k) Boltzmannova konÅ¡tanta (k) Boltzmann constant in eV/K Boltzmannova konÅ¡tanta v eV/K Boltzmann constant in Hz/K Boltzmannova konÅ¡tanta v Hz/K Boltzmann constant in inverse meter per kelvin Boltzmannova konÅ¡tanta v reciproÄ�ných metroch na kelvin electron volt (eV) Elektrón volt (eV) Faraday constant (F) Faradayova konÅ¡tanta (F) first radiation constant (câ‚�) Prvá radiaÄ�ná konÅ¡tanta (câ‚�) first radiation constant for spectral radiance Prvá radiaÄ�ná konÅ¡tanta pre spektrálnu žiarivosÅ¥ molar gas constant (R) Molárna plynová konÅ¡tanta (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Loschmidtova konÅ¡tanta (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Loschmidtova konÅ¡tanta (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant Molar Planckova konÅ¡tanta second radiation constant (câ‚‚) Druhá radiaÄ�ná konÅ¡tanta (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Boltzmannova konÅ¡tanta (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) Mriežková vzdialenosÅ¥ ideal Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent energetický ekvivalent atómovej hmotnostnej konÅ¡tanty atomic mass constant energy equivalent in MeV energetický ekvivalent atómovej hmotnostnej konÅ¡tanty v MeV atomic mass unit-electron volt relationship vzÅ¥ah atómovej hmotnostnej jednotky a elektrónvoltu molar mass constant (Mᵤ) Molárna hmotnosÅ¥ constant (Mᵤ) molar mass of carbon-12 Molárna hmotnosÅ¥ carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) Molárny objem ideálneho plynu (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) Molárny objem ideálneho plynu (273.15 K, 101.325 kPa) molar volume of silicon Molárny objem silicon Sackur-Tetrode constant (1 K, 100 kPa) Sackurova-Tetrodeova konÅ¡tanta (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackurova-Tetrodeova konÅ¡tanta (1 K, 101.325 kPa) Wien frequency displacement law constant KonÅ¡tanta Wienovho posunovacieho zákona pre frekvenciu Wien wavelength displacement law constant Wien wavedĺžka displacement law constant standard atmosphere (atm) Å tandardná atmosféra (atm) standard-state pressure (p°) Å tandardný tlak (p°) Angstrom star (Ã…*) Angstromová hviezda (Ã…*) Copper x unit Medená jednotka x Molybdenum x unit Molybdénová jednotka x atomic unit of magnetizability Atómová jednotka magnetizovateľnosÅ¥ atomic unit of mass (mâ‚‘) atómová jednotka hmotnosti (mâ‚‘) atomic unit of momentum Atómová jednotka hybnosÅ¥ atomic unit of permittivity Atómová jednotka permitivita atomic unit of time Atómová jednotka Ä�as atomic unit of velocity Atómová jednotka rýchlosÅ¥ hartree-hertz relationship Hartree-hertz vzÅ¥ah hartree-inverse meter relationship vzÅ¥ah hartree a reciproÄ�ného metra hartree-joule relationship Hartree-joule vzÅ¥ah hartree-kelvin relationship Hartree-kelvin vzÅ¥ah hartree-kilogram relationship Hartree-kilogram vzÅ¥ah shielding difference of d and p in HD rozdiel tienenia d a p v HD shielding difference of t and p in HT rozdiel tienenia t a p v HT pi (Ï€) pí (Ï€) Euler's number (e) Eulerovo Ä�íslo (e) golden ratio (φ) Zlatý rez (φ) Euler-Mascheroni constant (γ) Eulerova-Mascheroniho konÅ¡tanta (γ) nominal solar radius Nominálny slneÄ�ný polomer nominal solar total irradiance Nominálny slneÄ�ný celkové ožiarenie nominal solar luminosity Nominálny slneÄ�ný svietivosÅ¥ nominal solar effective temperature Nominálny slneÄ�ný efektívna teplota nominal solar mass parameter Nominálny slneÄ�ný hmotnostný parameter nominal terrestrial equatorial radius Nominálny zemský rovníkový polomer nominal terrestrial polar radius Nominálny zemský polárny polomer nominal terrestrial mass parameter Nominálny zemský hmotnostný parameter nominal jovian equatorial radius Nominálny joviánsky rovníkový polomer nominal jovian polar radius Nominálny joviánsky polárny polomer nominal jovian mass parameter Nominálny joviánsky hmotnostný parameter average value of one minus the rate of TCG relative to TCB priemerná hodnota jednej mínus rýchlosÅ¥ TCG vzhľadom na TCB solar mass parameter (TCB-compatible) hmotnostný parameter Slnka (kompatibilný s TCB) solar mass parameter (TDB-compatible) hmotnostný parameter Slnka (kompatibilný s TDB) equatorial radius of the Earth (TT-compatible) rovníkový polomer Zeme (kompatibilný s TT) dynamical form factor of the Earth dynamický tvarový faktor Zeme time rate of change in the dynamical form factor of the Earth Ä�asová rýchlosÅ¥ zmeny dynamického tvarového faktora Zeme geocentric gravitational constant (TCB-compatible) geocentrická gravitaÄ�ná konÅ¡tanta (kompatibilná s TCB) geocentric gravitational constant (TT-compatible) geocentrická gravitaÄ�ná konÅ¡tanta (kompatibilná s TT) geocentric gravitational constant (TDB-compatible) geocentrická gravitaÄ�ná konÅ¡tanta (kompatibilná s TDB) potential of the geoid Potenciál geoidu nominal mean angular velocity of the Earth (TT-compatible) nominálna stredná uhlová rýchlosÅ¥ Zeme (kompatibilná s TT) ratio mass of the Moon to the Earth pomer hmotnosti Mesiaca k hmotnosti Zeme ratio of the mass of the Sun to Mercury pomer hmotnosti Slnka k hmotnosti Merkúra ratio of the mass of the Sun to Venus pomer hmotnosti Slnka k hmotnosti VenuÅ¡e ratio of the mass of the Sun to Mars pomer hmotnosti Slnka k hmotnosti Marsu ratio of the mass of the Sun to Jupiter pomer hmotnosti Slnka k hmotnosti Jupitera ratio of the mass of the Sun to Saturn pomer hmotnosti Slnka k hmotnosti Saturna ratio of the mass of the Sun to Uranus pomer hmotnosti Slnka k hmotnosti Uránu ratio of the mass of the Sun to Neptune pomer hmotnosti Slnka k hmotnosti Neptúna ratio of the mass of the Sun to (134340) Pluto pomer hmotnosti Slnka k hmotnosti (134340) Pluta ratio of the mass of the Sun to (136199) Eris pomer hmotnosti Slnka k hmotnosti (136199) Erisu ratio of the mass of (1) Ceres to the Sun pomer hmotnosti (1) Ceres k hmotnosti Slnka ratio of the mass of (2) Pallas to the Sun pomer hmotnosti (2) Pallas k hmotnosti Slnka ratio of the mass of (4) Vesta to the Sun pomer hmotnosti (4) Vesta k hmotnosti Slnka mean obliquity of the ecliptic at J2000.0 Stredný sklon ekliptiky at J2000.0 Electromagnetic Elektromagnetické Compton wavelength Comptonova vlnová dĺžka Astronomy Astronómia ConstantsWidget Domain Doména Subdomain Poddoména No match found Žiadna zhoda Name Názov Value Hodnota Unit Jednotka Search HľadaÅ¥ All VÅ¡etko CustomKeypadDialog Custom Keypad Vlastná klávesnica Rows: Riadky: Columns: Stĺpce: Copy preset: KopírovaÅ¥ predvoľbu: Basic Základné Scientific (wide) Vedecké (Å¡iroké) Scientific (narrow) Vedecké (úzke) Apply PoužiÅ¥ Row Riadok Column Stĺpec Label Popis Behavior Správanie Text Text DiagnosticsDialog App Diagnostics Diagnostika aplikácie Copy to Clipboard KopírovaÅ¥ do schránky Editor Unit Jednotka User unit Používateľská jednotka User function Používateľská funkcia Argument Argument Current result:<br/>%1 Aktuálny výsledok:<br/>%1 Selection result:<br/>%1 Výsledok výberu:<br/>%1 Selection result: n/a Vybraný výsledok: nedostupný Selection result: %1 Výsledok výberu: %1 second sekunda metre meter kilogram kilogram mole mol radian radián steradian steradián degree Celsius stupeň Celzia cubic metre kubický meter cubic millimetre kubický milimeter cubic centimetre kubický centimeter cubic decimetre kubický decimeter cubic kilometre kubický kilometer square millimetre Å¡tvorcový milimeter square kilometre Å¡tvorcový kilometer square metre Å¡tvorcový meter minute minúta hour hodina day deň astronomical unit astronomická jednotka degree stupeň arcminute uhlová minúta arcsecond uhlová sekunda milliarcsecond milioblúková sekunda microarcsecond mikrooblúková sekunda hectare hektár litre liter tonne tona Dalton dalton electronvolt elektrónvolt Angstrom angstrom atmosphere atmosféra atomic mass unit atómová hmotnostná jednotka British thermal unit britská tepelná jednotka calorie kalória carat karát cup šálka cup (Imperial) šálka (imperiálna) cup (Japanese) šálka (japonská) cup (US) šálka (USA) degree Fahrenheit stupeň Fahrenheita fathom siaha fluid ounce (Imperial) tekutá unca (imperiálna) fluid ounce (US) tekutá unca (USA) fluid dram (Imperial) tekutý dram (imperiálny) fluid dram (US) tekutý dram (USA) foot stopa square foot Å¡tvorcová stopa cubic foot kubická stopa gallon (Imperial) galón (imperiálny) gallon (US) galón (USA) gill (Imperial) gill (imperiálny) gill (US) gill (USA) gradian grad grain grén gram gram Hartley hartley Hartree energy unit Hartreeho jednotka energie horsepower konská sila inch palec square inch Å¡tvorcový palec cubic inch kubický palec karat karát knot uzol lightminute svetelná minúta lightsecond svetelná sekunda lightyear svetelný rok long ton dlhá tona mile míľa square mile Å¡tvorcová míľa cubic mile kubická míľa mile per hour míľa za hodinu kilometre per hour kilometer za hodinu nautical mile námorná míľa ounce unca parsec parsek pint (Imperial) pinta (imperiálna) pint (US) pinta (USA) pound libra pounds per square inch libry na Å¡tvorcový palec quart (Imperial) kvarta (imperiálna) quart (US) kvarta (USA) oil barrel ropný barel beer barrel (US) pivný barel (USA) square yard Å¡tvorcový yard cubic yard kubický yard short ton krátka tona tablespoon polievková lyžica tablespoon (Australian) polievková lyžica (austrálska) tablespoon (Imperial) polievková lyžica (imperiálna) tablespoon (US) polievková lyžica (USA) dessert spoon dezertná lyžica teaspoon Ä�ajová lyžiÄ�ka teaspoon (Imperial) Ä�ajová lyžiÄ�ka (imperiálna) teaspoon (US) Ä�ajová lyžiÄ�ka (USA) turn otáÄ�ka revolution otoÄ�enie revolution per minute otáÄ�ka za minútu week týždeň kilowatt hour kilowatthodina millimetre of mercury milimeter ortuÅ¥ového stĺpca yard yard Julian century juliánske storoÄ�ie Julian year juliánsky rok sidereal year siderický rok tropical year tropický rok Evaluator invalid expression neplatný výraz division by zero delenie nulou too time consuming - computation was rejected príliÅ¡ Ä�asovo nároÄ�né - výpoÄ�et bol odmietnutý dimension mismatch - quantities with different dimensions cannot be compared, added, etc. nezhoda rozmerov - veliÄ�iny s rôznymi rozmermi nemožno porovnávaÅ¥, sÄ�ítavaÅ¥ atÄ�. invalid dimension - operation might require dimensionless arguments Neplatný rozmer - operácia môže vyžadovaÅ¥ bezrozmerné argumenty Computation aborted - encountered numerical instability PoÄ�ítanie zruÅ¡ené. Nastala Ä�íselná nestabilita. invalid dimension - function might require dimensionless arguments Neplatný rozmer - funkcia môže vyžadovaÅ¥ bezrozmerné argumenty error chyba unit must not be zero Jednotka nesmie byÅ¥ nula Conversion failed - dimension mismatch Prevod se nepodaril - nezodpovedajúci rozmer unknown function or variable neznáma funkcia alebo premenná recursion not supported rekurzia nie je podporovaná cannot operate on a NaN nedá sa pracovaÅ¥ s neÄ�íselnou hodnotou underflow - tiny result is out of SpeedCrunch's number range podteÄ�enie - príliÅ¡ malý výsledok je mimo Ä�íselný rozsah SpeedCrunch overflow - huge result is out of SpeedCrunch's number range preteÄ�enie - príliÅ¡ veľký výsledok je mimo Ä�íselný rozsah SpeedCrunch overflow - logic result exceeds maximum of 256 bits preteÄ�enie - logický výsledok presiahol maximum 256 bitov overflow - integer result exceeds maximum limit for integers preteÄ�ení - celoÄ�íselný výsledok presiahol maximum pre celé Ä�ísla operation is not defined for these arguments operácia nie je pre tieto argumenty definovaná wrong number of arguments nesprávny poÄ�et argumentov does not take NaN as an argument neberie NaN ako argument result out of range výsledok mimo rozsah undefined for argument domain nedefinované pre definiÄ�ný obor argumentu computation too expensive výpoÄ�et príliÅ¡ nároÄ�ný internal error, please report a bug interná chyba, prosím nahláste chybu syntax error syntaktická chyba conversion target must be a unit cieľ prevodu musí byÅ¥ jednotka unknown unit neznáma jednotka %1 is a reserved name, please choose another %1 je rezervovaný názov. Prosím, zadajte iný. %1 is a global user definition and cannot be overridden in this session. %1 je globálna používateľská definícia a v tejto relácii ju nemožno prepísaÅ¥. %1 is a variable name, please choose another or delete the variable %1 je názov premennej. Prosím, zadajte iný názov, alebo zmažte premennú. argument %1 is used more than once argument %1 je použitý viac ako raz %1 is a built-in unit name, please choose another %1 je názov vstavanej jednotky, vyberte iný %1 is a user function name, please choose another or delete the function %1 je názov používateľskej funkcie. Prosím, zadajte iná názov, alebo zmažte funkciu. FunctionRepo max; trials; probability maximum; pokusy; pravdepodobnosÅ¥ trials; probability pokusy; pravdepodobnosÅ¥ hits; trials; probability úspechy; pokusy; pravdepodobnosÅ¥ max; total; hits; trials maximum; celkom; úspechy; pokusy total; hits; trials celkom; úspechy; pokusy count; total; hits; trials poÄ�et; celkom; úspechy; pokusy dividend; divisor delenec; deliteľ x; exponent_bits; significand_bits [; exponent_bias] x; bity exponentu; bity signifikandu [; posun exponentu] base; x základ; x value; modulo hodnota; modulo base; exponent; modulo základ; exponent; modulo events; average_events udalosti; priemer_udalostí average_events priemer_udalostí x [; precision] x [; presnosÅ¥] Absolute Value Absolútna hodnota Absolute Deviation Absolútna odchýlka Arc Cosine Arkus kosínus Logical AND Logické A Area Hyperbolic Cosine Hyperbolický arkus kosínus Area Hyperbolic Sine Hyperbolický arkus sínus Area Hyperbolic Tangent Hyperbolický arkus tangens Arc Sine Arkus sínus Arc Tangent Arkus tangens Arc Tangent with two Arguments Arkus tangens s dvoma argumentmi Average (Arithmetic Mean) Priemer (aritmetický priemer) Binomial Cumulative Distribution Function DistribuÄ�ná funkcia binomického rozdelenia Binomial Distribution Mean Stredná hodnota binomického rozdelenia Binomial Probability Mass Function Pravdepodobnostná funkcia binomického rozdelenia Binomial Distribution Variance Rozptyl binomického rozdelenia Cube Root Tretia odmocnina Complex Conjugate Komplexne združené Ä�íslo Cosine Kosínus Hyperbolic Cosine Hyperbolický kosínus Cotangent Kotangens Cosecant Kosekans Convert Unix timestamp to Date PreviesÅ¥ unixovú Ä�asovú peÄ�iatku na dátum Degrees of Arc Stupne oblúka Error Function Chybová funkcia Complementary Error Function Doplnková chybová funkcia Exponential Exponenciálna funkcia Fractional Part Zlomková Ä�asÅ¥ Extension of Factorials [= (x-1)!] Rozšírenie faktoriálov [= (x-1)!] Greatest Common Divisor NajväÄ�ší spoloÄ�ný deliteľ Geometric Mean Geometrický priemer Gradians of arc Gradiány oblúka Hypergeometric Cumulative Distribution Function DistribuÄ�ná funkcia hypergeometrického rozdelenia Hypergeometric Distribution Mean Stredná hodnota hypergeometrického rozdelenia Hypergeometric Probability Mass Function Pravdepodobnostná funkcia hypergeometrického rozdelenia Hypergeometric Distribution Variance Rozptyl hypergeometrického rozdelenia Integer Quotient CeloÄ�íselný podiel Integer Part CeloÄ�íselná Ä�asÅ¥ Imaginary Part Imaginárna Ä�asÅ¥ Decode IEEE-754 Binary Value DekódovaÅ¥ binárnu hodnotu IEEE-754 Encode IEEE-754 Binary Value ZakódovaÅ¥ binárnu hodnotu IEEE-754 Decode 16-bit Half-Precision Value DekódovaÅ¥ 16-bitovú hodnotu s poloviÄ�nou presnosÅ¥ou Encode 16-bit Half-Precision Value ZakódovaÅ¥ 16-bitovú hodnotu s poloviÄ�nou presnosÅ¥ou Decode 32-bit Single-Precision Value DekódovaÅ¥ 32-bitovú hodnotu s jednoduchou presnosÅ¥ou Encode 32-bit Single-Precision Value ZakódovaÅ¥ 32-bitovú hodnotu s jednoduchou presnosÅ¥ou Decode 64-bit Double-Precision Value DekódovaÅ¥ 64-bitovú hodnotu s dvojitou presnosÅ¥ou Encode 64-bit Double-Precision Value ZakódovaÅ¥ 64-bitovú hodnotu s dvojitou presnosÅ¥ou Decode 128-bit Quad-Precision Value DekódovaÅ¥ 128-bitovú hodnotu so Å¡tvoritou presnosÅ¥ou Encode 128-bit Quad-Precision Value ZakódovaÅ¥ 128-bitovú hodnotu so Å¡tvoritou presnosÅ¥ou Binary Logarithm Binárny logaritmus Common Logarithm Dekadický logaritmus Natural Logarithm Prirodzený logaritmus Logarithm to Arbitrary Base Logaritmus s ľubovoľným základom Mask to a bit size MaskovaÅ¥ na veľkosÅ¥ v bitoch Maximum Maximum Median Value (50th Percentile) Medián (50. percentil) Minimum Minimum Modulo Modulo Euclidean Modulo Euklidovské modulo Modular Exponentiation Modulárne umocňovanie Combination (Binomial Coefficient) Kombinácia (binomický koeficient) Logical NOT Logické NIE Permutation (Arrangement) Permutácia (usporiadanie) Convert to Binary Representation ZmeniÅ¥ na binárne vyjadrenie Arithmetic Aritmetika Chemistry Chémia Complex Komplexné Combinatorics Kombinatorika Probability PravdepodobnosÅ¥ Statistics Å tatistika Aggregation Agregácia Random Náhodné Base conversion Prevod sústav Number formatting Formátovanie Ä�ísel Integer arithmetic CeloÄ�íselná aritmetika Special functions Å peciálne funkcie Exponential & Logarithmic Exponenciálne a logaritmické Angle conversion Prevod uhlov Trigonometry Trigonometria Bitwise Bitové Floating point Pohyblivá rádová Ä�iarka Date & Time Dátum a Ä�as Linear algebra Lineárna algebra unix_timestamp; x hours offset to GMT unix_timestamp; posun o x hodín oproti GMT yyyymmdd.hhmmss; x hours offset to GMT rrrrmmdd.hhmmss; x hodín posun voÄ�i GMT [digits] [Ä�íslice] max [; min] max [; min] List Literal Literál zoznamu Convert to Padded Binary Representation PreviesÅ¥ na doplnenú binárnu reprezentáciu Round Toward +∞ (Ceiling) ZaokrúhliÅ¥ smerom k +∞ (strop) Cosine plus Imaginary Sine Kosínus plus imaginárny sínus Convert to Cis Complex Form PreviesÅ¥ na komplexný tvar cis Matrix Column Count PoÄ�et stĺpcov matice Population Correlation Matrix (n) KorelaÄ�ná matica populácie (n) Sample Correlation Matrix (n-1) KorelaÄ�ná matica vzorky (n-1) Count PoÄ�et Population Covariance Matrix (n) KovarianÄ�ná matica populácie (n) Sample Covariance Matrix (n-1) KovarianÄ�ná matica vzorky (n-1) Cross Product Vektorový súÄ�in Convert Date to Unix timestamp PreviesÅ¥ dátum na Ä�asovú peÄ�iatku Unix Convert to Decimal Representation ZmeniÅ¥ na desiatkové vyjadrenie Determinant Determinant Convert to Sexagesimal Notation PreviesÅ¥ na Å¡esÅ¥desiatkový zápis Dot Product Skalárny súÄ�in Convert to Engineering Notation PreviesÅ¥ na inžiniersky zápis Convert to Exponential Complex Form PreviesÅ¥ na exponenciálny komplexný tvar Round Toward −∞ (Floor) ZaokrúhliÅ¥ smerom k −∞ (podlaha) Flatten Matrix SploÅ¡tiÅ¥ maticu Least Common Multiple Najmenší spoloÄ�ný násobok Convert to Hexadecimal Representation ZmeniÅ¥ na hexadecimálne vyjadrenie Convert to Padded Hexadecimal Representation PreviesÅ¥ na doplnenú hexadecimálnu reprezentáciu Inverse Matrix Inverzná matica Round to 16-bit Half-Precision Value ZaokrúhliÅ¥ na 16-bitovú hodnotu s poloviÄ�nou presnosÅ¥ou Round to 32-bit Single-Precision Value ZaokrúhliÅ¥ na 32-bitovú hodnotu s jednoduchou presnosÅ¥ou Round to 64-bit Double-Precision Value ZaokrúhliÅ¥ na 64-bitovú hodnotu s dvojitou presnosÅ¥ou Round to 128-bit Quad-Precision Value ZaokrúhliÅ¥ na 128-bitovú hodnotu so Å¡tvoritou presnosÅ¥ou Residual from 16-bit Half-Precision Rounding ZvyÅ¡ok po 16-bitovom zaokrúhlení s poloviÄ�nou presnosÅ¥ou Residual from 32-bit Single-Precision Rounding ZvyÅ¡ok po 32-bitovom zaokrúhlení s jednoduchou presnosÅ¥ou Residual from 64-bit Double-Precision Rounding ZvyÅ¡ok po 64-bitovom zaokrúhlení s dvojitou presnosÅ¥ou Residual from 128-bit Quad-Precision Rounding ZvyÅ¡ok po 128-bitovom zaokrúhlení so Å¡tvoritou presnosÅ¥ou Substance Mass HmotnosÅ¥ látky Molarity Molarita Molar Mass Molárna hmotnosÅ¥ Median Absolute Deviation Mediánová absolútna odchýlka Mean Priemer Numerical Value of Quantity Číselná hodnota veliÄ�iny Random Decimal Number Náhodné desatinné Ä�íslo Random Integer Number Náhodné celé Ä�íslo Convert to Rational Representation PreviesÅ¥ na racionálnu reprezentáciu Convert to Octal Representation ZmeniÅ¥ na osmiÄ�kové vyjadrenie Convert to Padded Octal Representation PreviesÅ¥ na doplnenú osmiÄ�kovú reprezentáciu Vector or Matrix Norm Norma vektora alebo matice Logical OR Logické ALEBO Population Count (Hamming Weight) PoÄ�et jednotiek (Hammingova váha) Phase of Complex Number Fáza komplexného Ä�ísla Poissonian Cumulative Distribution Function DistribuÄ�ná funkcia Poissonovho rozdelenia Poissonian Distribution Mean Stredná hodnota Poissonovho rozdelenia Poissonian Probability Mass Function Pravdepodobnostná funkcia Poissonovho rozdelenia Poissonian Distribution Variance Rozptyl Poissonovho rozdelenia Convert to Phasor Complex Form PreviesÅ¥ na fázorový komplexný tvar Convert to Rectangular Complex Form PreviesÅ¥ na pravouhlý komplexný tvar Round Half Away from Zero ZaokrúhliÅ¥ polovicu od nuly Round Half Even ZaokrúhliÅ¥ polovicu na párne Nth Root N-tá odmocnina Convert to Scientific Notation PreviesÅ¥ na vedecký zápis Matrix Row Count PoÄ�et riadkov matice List or Matrix Shape Tvar zoznamu alebo matice Summation SúÄ�et Population Standard Deviation (n) Smerodajná odchýlka populácie (n) Sample Standard Deviation (n-1) Smerodajná odchýlka vzorky (n-1) Round Toward Zero (Truncation) ZaokrúhliÅ¥ smerom k nule (orezanie) Matrix Trace Stopa matice Transpose Matrix TransponovaÅ¥ maticu Population Variance (n) Rozptyl populácie (n) Sample Variance (n-1) Rozptyl vzorky (n-1) Product Produkt Radians Radiány Matrix Rank HodnosÅ¥ matice Real Part Reálna Ä�asÅ¥ Secant Sekans Arithmetic Shift Left Aritmetický posun doľava Arithmetic Shift Right Aritmetický posun doprava Signum Signum Sine Sínus Hyperbolic Sine Hyperbolický sínus Square Root Odmocnina Sum Suma Tangent Tangens Convert to Trigonometric Complex Form PreviesÅ¥ na trigonometrický komplexný tvar Turns OtoÄ�ky Hyperbolic Tangent Hyperbolický tangens Sign-extend a value Znamienkovo rozšíriÅ¥ hodnotu Logical XOR Logické XOR FunctionsWidget Domain Doména All VÅ¡etko Name Názov Search HľadaÅ¥ No match found Žiadna zhoda Identifier Identifikátor HistoryWidget Remove All Calculations Above OdstrániÅ¥ vÅ¡etky výpoÄ�ty nad Remove This Calculation OdstrániÅ¥ tento výpoÄ�et Remove All Calculations Below OdstrániÅ¥ vÅ¡etky výpoÄ�ty pod Keypad Inverse cosine Inverzný kosínus The last result Posledný výsledok Inverse sine Inverzný sínus Inverse tangent Arkus tangens Evaluate expression VyhodnotiÅ¥ výraz Division Delenie Multiplication Násobenie Subtraction OdÄ�ítanie Addition SÄ�ítanie Clear expression VymazaÅ¥ výraz Cosine Kosínus Backspace Backspace Scientific notation Vedecký zápis Exponential Exponenciálna funkcia Factorial Faktoriál Natural logarithm Prirodzený logaritmus Left parenthesis Ľavá zátvorka Nth root N-tá odmocnina Argument separator OddeľovaÄ� argumentov Square Druhá mocnina Common logarithm Dekadický logaritmus Modulo Modulo Contextual percentage Kontextové percento Power Mocnina Right parenthesis Pravá zátvorka Sine Sínus Square root Odmocnina Tangent Tangens Pi Pí Decimal separator Desatinný oddeľovaÄ� MainWindow Radian Radián Degree Stupeň Gradian Gradián Binary Binárny Octal OsmiÄ�kový Hexadecimal Å estnástkový Sexagesimal Å esÅ¥desiatkový Engineering decimal Inžiniersky desiatkový Scientific decimal Vedecký desiatkový &Import... &ImportovaÅ¥... &Quit &UkonÄ�iÅ¥ Clear E&xpression ZmazaÅ¥ vý&raz Clear &History ZmazaÅ¥ &históriu &Copy &KopírovaÅ¥ &Paste &VložiÅ¥ &Select Expression &VybraÅ¥ výraz &Constants &KonÅ¡tanty &Functions &Funkcie &History &História &Status Bar &Stavový riadok Bitfield Bitové pole Use&r Functions Funkcie &používateľa &Degree &Stupeň &Radian &Radián &Gradian &Gradián Re&volution O&táÄ�ka Auto-Insert a&ns Automaticky vložiÅ¥ a&ns Automatic &Completion Automatické &dokonÄ�ovanie &Built-in Functions &Vstavané funkcie Built-in &Variables V&stavané premenné User &Functions Používateľské &funkcie User Va&riables Používateľské p&remenné Open a Private Tab on Startup Pri spustení otvoriÅ¥ súkromnú kartu Open and focus a new private tab whenever SpeedCrunch starts. Pri každom spustení SpeedCrunch otvoriÅ¥ a aktivovaÅ¥ novú súkromnú kartu. Syntax &Highlighting Zvýrazňovanie &syntaxe Group Digits in &Input ZoskupovaÅ¥ Ä�ísl&ice na vstupe Automatic Input &Adjustments &Automatické úpravy vstupu Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Automaticky upravovaÅ¥ operátory, medzery, zátvorky a mocniny a obmedziÅ¥ vstup na platné znaky. Group input digits using the selected number format. ZoskupovaÅ¥ zadané Ä�íslice podľa vybraného Ä�íselného formátu. &Blinking Cursor &Blikajúci kurzor Blink the cursor in the expression editor. NechaÅ¥ kurzor v editore výrazov blikaÅ¥. &Escape Clears Editor &Escape vymaže editor Clear the focused expression editor with Escape after dismissing any popup or preview. Klávesom Escape vymazaÅ¥ aktívny editor výrazov po zatvorení prípadných vyskakovacích okien alebo náhľadov. Keep Expression After Evaluation PonechaÅ¥ výraz po vyhodnotení Copy New Results Automatically Automaticky kopírovaÅ¥ nové výsledky &Comma &ÄŒiarka &System Default &Systémové nastavenie &Dot &Bodka Dot &And Comma Bodka &a Ä�iarka Toward +∞ (&ceil) Smerom k +∞ (&ceil) Toward −∞ (&floor) Smerom k −∞ (&floor) &Binary &Binárny &Engineering Inžini&ersky &Hexadecimal &Hexadecimálny &Octal &OsmiÄ�kový &Scientific &Vedecký User &Manual Používateľský &Manuál Issues and &Feedback &Problémy a pripomienky &Donate &DarovaÅ¥ &About SpeedCrunch &O programe SpeedCrunch App Diag&nostics Diag&nostika aplikácie S&plit &RozdeliÅ¥ Angle &Mode Reži&m uhlov &Complex Form &Komplexný tvar New Tab Nová karta Constants KonÅ¡tanty Functions Funkcie History História User Functions Používateľské funkcie &Font... &Písmo... &Language... &Jazyk... &Session &Sedenie &Edit &UpraviÅ¥ &View &ZobraziÅ¥ Se&ttings Nas&tavenia &Decimal &Desiatkový &Keypad &Klávesnica Always on &Top Vždy &navrchu Disabled Zakázané Small Space Malý priestor Medium Space Stredný priestor Large Space Veľký priestor &0 Digits &0 Ä�íslic &15 Digits &15 Ä�íslic &2 Digits &2 Ä�íslice &3 Digits &3 Ä�íslice &50 Digits &50 Ä�íslic &8 Digits &8 Ä�íslic &Sexagesimal &Å esÅ¥desiatkový Reset All Settings... ObnoviÅ¥ vÅ¡etky nastavenia... &System &Systém SpeedCrunch &Theme Mo&tív SpeedCrunch &Classic Klasi&cký &Modern &Moderný Context Help Kontextová pomoc &Help &Pomocník Error Chyba Can't read from file %1 Nemôžem Ä�ítaÅ¥ zo súboru %1 Import Session ImportovaÅ¥ sedenie Close Session ZavrieÅ¥ reláciu Angle Mode: Režim uhlov: Notation: Zápis: Precision: PresnosÅ¥: Turn OtoÄ�ka Revolution OtáÄ�ka Fixed-point decimal Desatinný zápis s pevnou Ä�iarkou Rational Racionálny Automatic decimal Automatický desatinný Automatic Automaticky User &Definitions... Používateľské &definície... New &Tab Nová &karta New &Private Tab &Nová súkromná karta Keep PonechaÅ¥ Make Private... ZmeniÅ¥ na súkromnú... New &Window Nové &okno &Open... &OtvoriÅ¥... &Rename... P&remenovaÅ¥... Clo&ne... Klono&vaÅ¥... &Close Tab &ZavrieÅ¥ kartu Reopen Clo&sed Tab Znovu o&tvoriÅ¥ zavretú kartu Open Sessions &Folder OtvoriÅ¥ &prieÄ�inok relácií &Undo &Späť &Redo &Znova Cu&t Vys&trihnúť Copy &Last Result KopírovaÅ¥ pos&ledný výsledok &Wrap in Parentheses &UzavrieÅ¥ do zátvoriek Full Scr&een Mode R&ežim celej obrazovky &Basic &Základné &Scientific (wide) &Vedecké (Å¡iroké) Scientific (narrow) Vedecké (úzke) &Custom... &Vlastné... Main &Menu Hlavná &ponuka User &Variables Používateľské &premenné &Left &Vľavo &Right Vp&ravo &Up &Nahor &Down Na&dol Close Pa&ne ZavrieÅ¥ pa&nel User &Units Používateľské &jednotky &Turn &OtoÄ�ka If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Ak nový výraz zaÄ�ína +, -, * alebo /, SpeedCrunch najprv vloží „ans“. &Accept with Enter &PrijaÅ¥ klávesom Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. PrijaÅ¥ aktuálny návrh automatického dopĺňania klávesom Enter bez predchádzajúceho výberu pomocou šípok. &Units &Jednotky Show Live Result &Preview ZobraziÅ¥ živý &náhľad výsledku Save &Window Position on Exit UložiÅ¥ polohu &okna pri ukonÄ�ení Hover Highlighting Zvýraznenie pri prejdení myÅ¡ou Group Integer Part Only ZoskupovaÅ¥ iba celú Ä�asÅ¥ Number Format... Formát Ä�ísla... Notation && Precision... Zápis && presnosÅ¥... After pressing Enter, keep the entered expression selected in the editor. Po stlaÄ�ení Enter ponechaÅ¥ zadaný výraz vybraný v editore. Never Nikdy Always Vždy Only for Single-Line Expressions Iba pre jednoriadkové výrazy Simplify Displayed Expressions ZjednoduÅ¡iÅ¥ zobrazené výrazy History Size &Limit... &Limit veľkosti histórie... Remove Trailing &Zeroes &OdstrániÅ¥ koncové nuly Nearest, Half &Away (round) Najbližšie, polovica &od nuly (round) Nearest, Half &Even (roundeven) Najbližšie, polovica na &párne (roundeven) Toward &Zero (trunc) Smerom k &nule (trunc) &Fixed-Point S &pevnou Ä�iarkou &Rational &Racionálny &Exponential (m·sâ�»Â¹) &Exponenciálny (m·sâ�»Â¹) &Fractional (m/s) &Zlomkový (m/s) &Rectangular (a + bi) &Pravouhlý (a + bi) Exponential (reâ�±á¶¿) Exponenciálny (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrický (r(cos θ + i·sin θ)) Phasor (r∠θ) Fázor (r∠θ) &Theme... &Téma... Check for &Updates SkontrolovaÅ¥ &aktualizácie Source Code Zdrojový kód &Zoom &Priblíženie &Results &Výsledky Unit Notation Zápis jednotiek Rounding Mode Režim zaokrúhľovania &Notation &Zápis &Imaginary Unit &Imaginárna jednotka &Window &Okno &Editing &Úpravy A&utocomplete A&utomatické dopĺňanie Up/Down Arrow History História šípkami nahor/nadol &Appearance &Vzhľad &Menus &Ponuky &Docks &Dokovateľné panely &Input and Results &Vstup a výsledky &Disabled &Vypnuté &Disable &Vypnúť Close preview ZavrieÅ¥ náhľad Rename... PremenovaÅ¥... Clone... KlonovaÅ¥... Close Tab ZavrieÅ¥ kartu New Private Tab Nová súkromná karta Open... OtvoriÅ¥... Reopen Closed Tab Znovu otvoriÅ¥ zavretú kartu Split RozdeliÅ¥ Left Vľavo Right Vpravo Up Nahor Down Nadol Clear VymazaÅ¥ Delete ZmazaÅ¥ %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Súkromné sedenie: obsah sa pri zatvorení zahodí. Voľbou Sedenie > PonechaÅ¥ ho zmeníte na bežné sedenie. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Súkromné] Reset All Settings ObnoviÅ¥ vÅ¡etky nastavenia Reset all settings to their default values? ObnoviÅ¥ predvolené hodnoty vÅ¡etkých nastavení? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Zahŕňa to vzhľad, úpravy, formáty výsledkov a predvoľby okien. VaÅ¡e výpoÄ�ty, otvorené sedenia a používateľské definície zostanú zachované. The settings file could not be written. Súbor nastavení sa nepodarilo zapísaÅ¥. Clear this session's calculations, unfinished expression, variables, functions, and units? VymazaÅ¥ výpoÄ�ty, nedokonÄ�ený výraz, premenné, funkcie a jednotky tohto sedenia? Global user definitions are kept. Globálne používateľské definície zostanú zachované. Make Session Private ZmeniÅ¥ sedenie na súkromné The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Uložené sedenie %1 bude odstránené. Jeho obsah zostane otvorený v súkromnom sedení a zahodí sa pri zatvorení tohto sedenia alebo ukonÄ�ení SpeedCrunch. Make Private ZmeniÅ¥ na súkromnú Could not delete the saved session %1. Uložené sedenie %1 sa nepodarilo odstrániÅ¥. Keep Session PonechaÅ¥ sedenie Could not save the session. It remains private. Sedenie sa nepodarilo uložiÅ¥. Zostáva súkromné. Clone Session KlonovaÅ¥ sedenie Could not save session file %1. Súbor sedenia %1 sa nepodarilo uložiÅ¥. Could not delete session file %1. Súbor sedenia %1 sa nepodarilo odstrániÅ¥. JSON file (*.json);;Any file (*.*) Súbor JSON (*.json);;Ľubovoľný súbor (*.*) Export session as JSON ExportovaÅ¥ sedenie ako JSON The selected file is not valid JSON: %1 Vybraný súbor nie je platný JSON: %1 The selected file is not a SpeedCrunch session JSON file. Vybraný súbor nie je JSON súbor sedenia SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Tento súbor používa zastaraný formát sedenia SpeedCrunch a nemožno ho importovaÅ¥. The selected JSON file is missing the required $schema field. Vo vybranom súbore JSON chýba povinné pole $schema. The selected JSON file uses an unsupported JSON schema: %1 Vybraný súbor JSON používa nepodporovanú schému JSON: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Vo vybranom súbore JSON chýba identifikátor schémy sedenia SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Vybraný súbor JSON používa nepodporovaný formát sedenia SpeedCrunch: %1 The selected JSON file is missing the required session name. Vo vybranom súbore JSON chýba povinný názov relácie. The selected JSON file has an empty session name. Vybraný súbor JSON má prázdny názov relácie. The selected JSON file has invalid or incomplete SpeedCrunch session data. Vybraný súbor JSON obsahuje neplatné alebo neúplné údaje sedenia SpeedCrunch. Open Sessions Folder OtvoriÅ¥ prieÄ�inok relácií Could not create the sessions folder: %1 Nepodarilo sa vytvoriÅ¥ prieÄ�inok relácií: %1 Could not open the sessions folder: %1 Nepodarilo sa otvoriÅ¥ prieÄ�inok relácií: %1 Editor and Results Font Písmo editora a výsledkov Open Session OtvoriÅ¥ reláciu Community Komunita Rename Session PremenovaÅ¥ reláciu Clear Session VymazaÅ¥ reláciu Delete Session OdstrániÅ¥ reláciu Close Pane ZavrieÅ¥ panel User Variables Používateľské premenné User Units Používateľské jednotky Clear History VymazaÅ¥ históriu Are you sure you want to clear the calculation history? Naozaj chcete vymazaÅ¥ históriu výpoÄ�tov? Session name: Názov relácie: A session named %1 already exists. Relácia s názvom %1 už existuje. Could not create session file %1. Nepodarilo sa vytvoriÅ¥ súbor relácie %1. Could not write session file %1. Nepodarilo sa zapísaÅ¥ súbor relácie %1. Are you sure you want to delete this session? Naozaj chcete odstrániÅ¥ túto reláciu? Custom Precision Vlastná presnosÅ¥ Fractional digits: Desatinné miesta: Theme Téma Light Themes Svetlé témy Dark Themes Tmavé témy Preview Náhľad Colors Farby Select color for %1 VybraÅ¥ farbu pre %1 Import... ImportovaÅ¥... Export... ExportovaÅ¥... Import Theme ImportovaÅ¥ tému Theme file (*.json);;All files (*) Súbor témy (*.json);;VÅ¡etky súbory (*) Invalid theme file. Neplatný súbor témy. Can't import theme "%1" because it conflicts with a built-in theme. Tému „%1“ nemožno importovaÅ¥, pretože je v konflikte so vstavanou témou. Can't find a writable theme folder. Nemožno nájsÅ¥ zapisovateľný prieÄ�inok tém. Overwrite Theme PrepísaÅ¥ tému A custom theme named "%1" already exists. Do you want to overwrite it? Vlastná téma s názvom „%1“ už existuje. Chcete ju prepísaÅ¥? Can't overwrite theme file %1 Nemožno prepísaÅ¥ súbor témy %1 Can't copy theme file to %1 Nemožno skopírovaÅ¥ súbor témy do %1 Export Theme ExportovaÅ¥ tému Can't export theme as "%1" because it conflicts with a built-in theme. Tému nemožno exportovaÅ¥ ako „%1“, pretože je v konflikte so vstavanou témou. Can't write to file %1 Nemôžem zapisovaÅ¥ do súboru %1 Global User Variable Globálna používateľská premenná Global User Function Globálna používateľská funkcia Global User Unit Globálna používateľská jednotka User Definitions Používateľské definície These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Tieto definície sú globálne a naÄ�ítajú sa do každej relácie. V reláciách ich nemožno meniÅ¥ a majú prednosÅ¥ pred definíciami s rovnakým názvom z editora relácie. Zadajte jednu definíciu na riadok. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Príklady: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply PoužiÅ¥ Validate OveriÅ¥ Test Results Výsledky testu Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Importované premenné: %1 Importované funkcie: %2 Importované jednotky: %3 Čísla riadkov s chybami: %4 none žiadne Apply Results Výsledky použitia User definitions saved. Používateľské definície boli uložené. History Size Limit Limit veľkosti histórie Maximum number of history entries for this session (0 = unlimited): Maximálny poÄ�et položiek histórie pre túto reláciu (0 = neobmedzené): Text file (*.txt);;Any file (*.*) Textový súbor (*.txt);;VÅ¡etky súbory (*.*) Could not recalculate from calculation %1: %2 Nepodarilo sa prepoÄ�ítaÅ¥ od výpoÄ�tu %1: %2 History Size Limit Reached Dosiahnutý limit veľkosti histórie This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Tento výpoÄ�et zapĺňa posledné dostupné miesto v histórii. Budúce výpoÄ�ty odstránia z histórie najstarší výpoÄ�et. Limit môžete zvýšiÅ¥ v Relácia > Limit veľkosti histórie. Editing calculation. Press Esc twice to cancel. Úprava výpoÄ�tu. Zrušíte ju dvojitým stlaÄ�ením Esc. Calculation Settings Nastavenia výpoÄ�tu Invalid recalculation start index Neplatný poÄ�iatoÄ�ný index prepoÄ�tu System Default Systémové nastavenie Language Jazyk Select the language: Vyberte jazyk: Custom Vlastné Decimal places: Desatinné miesta: &Automatic &Automaticky &Precision &PresnosÅ¥ Plain &text ÄŒistý &text Formula &Book Kniha &vzorcov &Export &ExportovaÅ¥ Export session as HTML ExportovaÅ¥ sedenie ako HTML HTML file (*.html) Súbor HTML (*.html) Export session as plain text ExportovaÅ¥ sedenie ako Ä�istý text ManualWindow SpeedCrunch Manual SpeedCrunch manuál %1 - SpeedCrunch Manual %1 - SpeedCrunch manuál NumberFormatDialog Number Format Formát Ä�ísla <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Vyberte Ä�íselný formát výsledkov a zoskupovania Ä�íslic na vstupe.</b><br/><br/>Poznámka: pri zadávaných Ä�íslach sa prijímajú jednoznaÄ�né formáty, aj keÄ� sa líšia od vybraného formátu zobrazenia.<br/> QObject Global User Variable Globálna používateľská premenná Global User Function Globálna používateľská funkcia Global User Unit Globálna používateľská jednotka Backspace Backspace Clear expression VymazaÅ¥ výraz Evaluate expression VyhodnotiÅ¥ výraz Insert text VložiÅ¥ text Automatic decimal Automatický desatinný Fixed-point decimal Desatinný zápis s pevnou Ä�iarkou Engineering decimal Inžiniersky desatinný Scientific decimal Vedecký desatinný Rational Racionálny Binary Binárny Octal OsmiÄ�kový Hexadecimal Hexadecimálny Sexagesimal Å esÅ¥desiatkový Update Available Dostupná aktualizácia A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Je dostupná novÅ¡ia verzia (%1).<br/><a href="%2">Prejdite na webovú stránku a stiahnite ju.</a> Check for Updates SkontrolovaÅ¥ aktualizácie SpeedCrunch %1 is up to date. SpeedCrunch %1 je aktuálny. No connectivity. Please check your internet connection and try again. Žiadne pripojenie. Skontrolujte internetové pripojenie a skúste to znova. Could not verify the latest available version. Nepodarilo sa overiÅ¥ najnovÅ¡iu dostupnú verziu. ResultDisplay Scroll to bottom Posunúť nadol Edit Expression UpraviÅ¥ výraz Change Settings ZmeniÅ¥ nastavenia New Tab Nová karta &Import... &ImportovaÅ¥... &Export &ExportovaÅ¥ Plain &text ÄŒistý &text Copy KopírovaÅ¥ Selection Výber Select All VybraÅ¥ vÅ¡etko Expression Výraz Result Výsledok Calculation VýpoÄ�et Calculation as Single Line VýpoÄ�et na jednom riadku Remove OdstrániÅ¥ This Calculation Tento výpoÄ�et All Calculations Above VÅ¡etky výpoÄ�ty nad týmto All Calculations Below VÅ¡etky výpoÄ�ty pod týmto New Private Tab Nová súkromná karta Session Sedenie Open... OtvoriÅ¥... Clone... KlonovaÅ¥... Rename... PremenovaÅ¥... Keep PonechaÅ¥ Make Private... ZmeniÅ¥ na súkromnú... Clear VymazaÅ¥ Delete ZmazaÅ¥ Close ZavrieÅ¥ Split RozdeliÅ¥ Left Vľavo Right Vpravo Up Nahor Down Nadol Close Pane ZavrieÅ¥ panel Main Menu Hlavná ponuka Cancel editing ZruÅ¡iÅ¥ úpravu Copy result KopírovaÅ¥ výsledok Edit expression UpraviÅ¥ výraz Change settings ZmeniÅ¥ nastavenia Remove calculation OdstrániÅ¥ výpoÄ�et ResultSlotsDialog Notation & Precision Zápis a presnosÅ¥ Result Line Riadok výsledku Enabled Povolené Notation Zápis Decimal Places Desatinné miesta Main Line Hlavný riadok Extra Line #1 Doplnkový riadok Ä�. 1 Extra Line #2 Doplnkový riadok Ä�. 2 Extra Line #3 Doplnkový riadok Ä�. 3 Extra Line #4 Doplnkový riadok Ä�. 4 Auto Automaticky UserFunctionListWidget Name Názov Value Hodnota Description Popis Search HľadaÅ¥ No match found Žiadne zhody Insert VložiÅ¥ Edit UpraviÅ¥ Delete ZmazaÅ¥ Delete All ZmazaÅ¥ vÅ¡etko UserUnitListWidget Name Názov Value Hodnota Description Popis Search HľadaÅ¥ No match found NenaÅ¡la sa žiadna zhoda Insert VložiÅ¥ Edit UpraviÅ¥ Delete OdstrániÅ¥ Delete All OdstrániÅ¥ vÅ¡etko VariableListWidget Name Názov Value Hodnota Description Popis Search HľadaÅ¥ No match found Žiadna zhoda Insert VložiÅ¥ Edit UpraviÅ¥ Delete ZmazaÅ¥ Delete All ZmazaÅ¥ vÅ¡etko heldercorreia-speedcrunch-e7ca37f/src/resources/locale/sl.ts000066400000000000000000010465211526573132500243740ustar00rootroot00000000000000 AboutBox About SpeedCrunch O programu SpeedCrunch Core developers Glavni razvijalci Original author Prvotni avtor Close Zapri Math engine MatematiÄ�ni pogon Main author | Logo | Maintainer Glavni avtor | Logotip | Vzdrževalec Thanks Zahvale Copyright (C) 2004-2026 The SpeedCrunch developers Avtorske pravice (C) 2004-2026 razvijalci SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Ta program je prosta programska oprema; lahko ga razÅ¡irjate in/ali spreminjate pod pogoji SploÅ¡nega dovoljenja GNU, kot ga je objavila Free Software Foundation; bodisi razliÄ�ice 2 dovoljenja ali (po vaÅ¡i izbiri) katere koli poznejÅ¡e razliÄ�ice This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Ta program se razÅ¡irja v upanju, da bo uporaben, vendar BREZ KAKRÅ NEGA KOLI JAMSTVA; tudi brez posrednega jamstva PRODAJNOSTI ali PRIMERNOSTI ZA DOLOÄŒEN NAMEN. Za veÄ� podrobnosti glejte SploÅ¡no dovoljenje GNU. BitFieldWidget Reset bits to zero Ponastavi bite na niÄ� Invert bits Obrni bite Shift bits left Premakni bite levo Shift bits right Premakni bite desno Book Index Kazalo Algebra Algebra Quadratic Equation Kvadratna enaÄ�ba Logarithmic Base Conversion Pretvorba logaritemske osnove Geometry Geometrija Circle Krog Sector Sektor Sphere Krogla Cube Kocka Cone Stožec Cylinder Valj Electronics Elektrotehnika Ohm's Law Ohmov zakon Power MoÄ� Reactance Reaktanca Resonance Resonanca Radio Frequency Radijska frekvenca Antennas Antene Characteristic Impedance (coax) KarakteristiÄ�na impedanca (koaksialen prevodnik) Velocity of Propagation (coax) Hitrost propagacije (koaksialen prevodnik) Standing Wave Ratio & Return Loss Razmerje stojnega vala & povratna izguba Free Space Wavelength Valovna dolžina v prostem prostoru resistance upornost voltage napetost current tok power moÄ� inductive reactance induktivna reaktanca capacitive reactance kapacitivna reaktanca inductance induktivnost capacitance kapacitivnost frequency frekvenca resonance frequency resonanÄ�na frekvenca area povrÅ¡ina perimeter obseg diameter premer radius polmer volume prostornina surface area povrÅ¡ina height viÅ¡ina slant height stranska viÅ¡ina face diagonal diagonala ploskve space diagonal telesna diagonala edge length dolžina roba arc length dolžina loka central angle (degrees) srediÅ¡Ä�ni kot (stopinje) input power vhodna moÄ� reflected power odbita moÄ� transmitted power prenesena moÄ� return loss povratna izguba dielectric constant dielektriÄ�na konstanta outer conductor's inner diameter notranji premer zunanjega vodnika inner conductor's outer diameter zunanji premer notranjega vodnika speed of light hitrost svetlobe reflection coefficient koeficient odboja standing wave ratio razmerje stojnega vala normalized impedance normalizirana impedanca frequency (Hz) frekvenca (Hz) BookDock Formula Book Knjiga formul ConstantCompletion Search constants IÅ¡Ä�i konstante No match found Ni najdenih ujemanj Constants Mathematics Matematika Physics (CODATA 2022) Fizika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kemija (IUPAC - CIAAW 2021) Uncategorized Nekategorizirano Universal Univerzalne Physicochemical Fizikalno-kemijske Atomic & Nuclear — General Atomsko in jedrsko - sploÅ¡no Atomic & Nuclear — Electroweak Atomsko in jedrsko - elektroÅ¡ibko Atomic & Nuclear — Electron Atomsko in jedrsko - elektron Atomic & Nuclear — Muon Atomsko in jedrsko - mion Atomic & Nuclear — Tau Atomsko in jedrsko - tau Atomic & Nuclear — Proton Atomsko in jedrsko - proton Atomic & Nuclear — Neutron Atomsko in jedrsko - nevtron Atomic & Nuclear — Deuteron Atomsko in jedrsko - devteron Atomic & Nuclear — Triton Atomsko in jedrsko - triton Atomic & Nuclear — Helion Atomsko in jedrsko - helion Atomic & Nuclear — Alpha particle Atomsko in jedrsko - delec alfa Atomic & Nuclear — Atomic units Atomsko in jedrsko - atomske enote Atomic & Nuclear — Energy conversion relationships Atomsko in jedrsko - razmerja za pretvorbo energije Atomic & Nuclear — X-ray units Atomsko in jedrsko - rentgenske enote Atomic & Nuclear — Magnetic shielding corrections Atomsko in jedrsko - popravki magnetnega senÄ�enja Masses Mase Lifetimes Življenjske dobe Molar Masses Molske mase Electronegativity Elektronegativnost Ionization Energy Ionizacijska energija Nominal Constants (IAU 2015) Nazivne konstante (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Trenutne najboljÅ¡e ocene (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) karakteristiÄ�na impedanca vakuuma (Zâ‚€) reduced Planck constant (â„�) reducirana Planck konstanta (â„�) vacuum electric permittivity (ϵ₀) elektriÄ�na prepustnost vakuuma (ϵ₀) Newtonian constant of gravitation (G) Newtonian konstanta of gravitation (G) vacuum magnetic permeability (μ₀) magnetna prepustnost vakuuma (μ₀) Planck constant (h) Planck konstanta (h) speed of light in vacuum (c) hitrost svetlobe v vakuumu (c) standard acceleration of gravity (gâ‚™) standardni gravitacijski pospeÅ¡ek (gâ‚™) Newtonian constant of gravitation over h-bar c Newtonian konstanta of gravitation over h-bar c Planck length Planckova dolžina Planck constant in eV/Hz (h) Planck konstanta in eV/Hz (h) Planck mass Planck masa Planck mass energy equivalent in GeV Planck masa energijski ekvivalent in GeV Planck temperature Planckova temperatura Planck time Planckov Ä�as reduced Planck constant in eV·s (â„�) reducirana Planck konstanta in eV·s (â„�) reduced Planck constant times c in MeV·fm reducirana Planck konstanta times c in MeV·fm Bohr magneton Bohrov magneton conductance quantum (Gâ‚€) kvant prevodnosti (Gâ‚€) Coulomb constant (kâ‚‘) Coulomb konstanta (kâ‚‘) elementary charge (e) osnovni naboj (e) elementary charge over h-bar osnovni naboj deljen s h-bar conventional value of Josephson constant conventional value of Josephson konstanta Josephson constant Josephson konstanta conventional value of ampere-90 konvencionalna vrednost ampera-90 conventional value of coulomb-90 konvencionalna vrednost coulomba-90 conventional value of farad-90 konvencionalna vrednost farada-90 conventional value of henry-90 konvencionalna vrednost henryja-90 conventional value of ohm-90 konvencionalna vrednost ohma-90 conventional value of volt-90 konvencionalna vrednost volta-90 conventional value of watt-90 konvencionalna vrednost watta-90 magnetic flux quantum (Φ₀) kvant magnetnega pretoka (Φ₀) nuclear magneton jedrski magneton inverse of conductance quantum obratna vrednost kvanta prevodnosti conventional value of von Klitzing constant conventional value of von Klitzing konstanta von Klitzing constant von Klitzing konstanta atomic unit of magnetic dipole moment atomska enota of magnetic dipole moment atomic unit of magnetic flux density atomska enota of magnetic flux density Bohr magneton in eV/T Bohrov magneton v eV/T Bohr magneton in Hz/T Bohrov magneton v Hz/T Bohr magneton in inverse meter per tesla Bohr magneton in inverzni meter per tesla Bohr magneton in K/T Bohrov magneton v K/T nuclear magneton in eV/T jedrski magneton v eV/T nuclear magneton in inverse meter per tesla nuclear magneton in inverzni meter per tesla nuclear magneton in K/T jedrski magneton v K/T nuclear magneton in MHz/T jedrski magneton v MHz/T Bohr radius (aâ‚€) Bohrov polmer (aâ‚€) fine-structure constant (α) fine-structure konstanta (α) Hartree energy (Eâ‚•) Hartreejeva energija (Eâ‚•) Hartree energy in eV Hartreejeva energija v eV quantum of circulation kvant cirkulacije quantum of circulation times 2 dvakratni kvant cirkulacije Rydberg constant (R∞) Rydberg konstanta (R∞) atomic mass unit-hartree relationship atomic masa unit-hartree razmerje atomic mass unit-hertz relationship atomic masa unit-hertz razmerje atomic mass unit-inverse meter relationship atomic masa unit-inverzni meter razmerje atomic mass unit-joule relationship atomic masa unit-joule razmerje atomic mass unit-kelvin relationship atomic masa unit-kelvin razmerje atomic mass unit-kilogram relationship atomic masa unit-kilogram razmerje atomic unit of 1st hyperpolarizability atomska enota of 1st hyperpolarizability atomic unit of 2nd hyperpolarizability atomska enota of 2nd hyperpolarizability atomic unit of charge (e) atomska enota of charge (e) atomic unit of charge density atomska enota of charge density atomic unit of current atomska enota of current atomic unit of electric dipole moment atomska enota of electric dipole moment atomic unit of electric field atomska enota of electric field atomic unit of electric field gradient atomska enota of electric field gradient atomic unit of electric polarizability atomska enota of electric polarizability atomic unit of electric potential atomska enota of electric potential atomic unit of electric quadrupole moment atomska enota of electric quadrupole moment atomic unit of action atomska enota of action atomic unit of energy atomska enota of energy atomic unit of force atomska enota of force atomic unit of length atomska enota of length hertz-atomic mass unit relationship hertz-atomic masa unit razmerje hertz-electron volt relationship hertz-elektron volt razmerje hertz-hartree relationship hertz-hartree razmerje hertz-inverse meter relationship hertz-inverzni meter razmerje hertz-joule relationship hertz-joule razmerje hertz-kelvin relationship hertz-kelvin razmerje hertz-kilogram relationship hertz-kilogram razmerje hyperfine transition frequency of Cs-133 frekvenca hiperfinega prehoda Cs-133 inverse fine-structure constant (αâ�»Â¹) inverse fine-structure konstanta (αâ�»Â¹) inverse meter-atomic mass unit relationship inverzni meter-atomic masa unit razmerje inverse meter-electron volt relationship inverzni meter-elektron volt razmerje inverse meter-hartree relationship inverzni meter-hartree razmerje inverse meter-hertz relationship inverzni meter-hertz razmerje inverse meter-joule relationship inverzni meter-joule razmerje inverse meter-kelvin relationship inverzni meter-kelvin razmerje inverse meter-kilogram relationship inverzni meter-kilogram razmerje joule-atomic mass unit relationship joule-atomic masa unit razmerje joule-electron volt relationship joule-elektron volt razmerje joule-hertz relationship joule-hertz razmerje joule-hartree relationship joule-hartree razmerje joule-inverse meter relationship joule-inverzni meter razmerje joule-kelvin relationship joule-kelvin razmerje joule-kilogram relationship joule-kilogram razmerje kelvin-atomic mass unit relationship kelvin-atomic masa unit razmerje kelvin-electron volt relationship kelvin-elektron volt razmerje kelvin-hertz relationship kelvin-hertz razmerje kelvin-hartree relationship kelvin-hartree razmerje kelvin-inverse meter relationship kelvin-inverzni meter razmerje kelvin-joule relationship kelvin-joule razmerje kelvin-kilogram relationship kelvin-kilogram razmerje kilogram-atomic mass unit relationship kilogram-atomic masa unit razmerje kilogram-electron volt relationship kilogram-elektron volt razmerje kilogram-hertz relationship kilogram-hertz razmerje kilogram-hartree relationship kilogram-hartree razmerje kilogram-inverse meter relationship kilogram-inverzni meter razmerje kilogram-joule relationship kilogram-joule razmerje kilogram-kelvin relationship kilogram-kelvin razmerje lattice parameter of silicon (a) mrežni parameter silicija (a) luminous efficacy svetlobna uÄ�inkovitost natural unit of energy naravna enota energije natural unit of energy in MeV naravna enota energije v MeV natural unit of action (â„�) naravna enota delovanja (â„�) natural unit of action in eV·s naravna enota delovanja v eV·s natural unit of length naravna enota dolžine natural unit of mass natural unit of masa natural unit of momentum naravna enota gibalne koliÄ�ine natural unit of momentum in MeV/c naravna enota gibalne koliÄ�ine v MeV/c natural unit of time naravna enota Ä�asa natural unit of velocity naravna enota hitrosti Rydberg constant times c in Hz Rydberg konstanta times c in Hz Rydberg constant times hc in eV Rydberg konstanta times hc in eV Rydberg constant times hc in J Rydberg konstanta times hc in J Fermi coupling constant Fermi coupling konstanta weak mixing angle Å¡ibki meÅ¡alni kot W to Z mass ratio W to Z masa ratio Thomson cross section (σₑ) Thomsonov presek (σₑ) electron mass (mâ‚‘) elektron masa (mâ‚‘) electron mass in u elektron masa in u electron mass energy equivalent (mₑ·c²) elektron masa energijski ekvivalent (mₑ·c²) electron mass energy equivalent in MeV elektron masa energijski ekvivalent in MeV reduced Compton wavelength reducirana Comptonova valovna dolzina classical electron radius (râ‚‘) classical elektron radius (râ‚‘) electron charge to mass quotient elektron charge to masa quotient electron-deuteron magnetic moment ratio elektron-devteron magnetni moment ratio electron-deuteron mass ratio elektron-devteron masa ratio electron g factor (gâ‚‘) elektron g factor (gâ‚‘) electron gyromagnetic ratio (γₑ) elektron giromagnetno razmerje (γₑ) electron gyromagnetic ratio in MHz/T elektron giromagnetno razmerje in MHz/T electron-helion mass ratio elektron-helion masa ratio electron magnetic moment (μₑ) elektron magnetni moment (μₑ) electron magnetic moment anomaly (aâ‚‘) elektron magnetni moment anomaly (aâ‚‘) electron magnetic moment to Bohr magneton ratio elektron magnetni moment to Bohr magneton ratio electron magnetic moment to nuclear magneton ratio elektron magnetni moment to nuclear magneton ratio electron molar mass (Mâ‚‘) elektron molar masa (Mâ‚‘) electron-muon magnetic moment ratio elektron-mion magnetni moment ratio electron-muon mass ratio elektron-mion masa ratio electron-neutron magnetic moment ratio elektron-nevtron magnetni moment ratio electron-neutron mass ratio elektron-nevtron masa ratio electron-proton magnetic moment ratio elektron-proton magnetni moment ratio electron-proton mass ratio elektron-proton masa ratio electron relative atomic mass (Ar(e)) elektron relative atomic masa (Ar(e)) electron-tau mass ratio elektron-tau masa ratio electron to alpha particle mass ratio elektron to alfa delec masa ratio electron to shielded helion magnetic moment ratio elektron to shielded helion magnetni moment ratio electron to shielded proton magnetic moment ratio elektron to shielded proton magnetni moment ratio electron-triton mass ratio elektron-triton masa ratio electron volt-atomic mass unit relationship elektron volt-atomic masa unit razmerje electron volt-hartree relationship elektron volt-hartree razmerje electron volt-hertz relationship elektron volt-hertz razmerje electron volt-inverse meter relationship elektron volt-inverzni meter razmerje electron volt-joule relationship elektron volt-joule razmerje electron volt-kelvin relationship elektron volt-kelvin razmerje electron volt-kilogram relationship elektron volt-kilogram razmerje hartree-atomic mass unit relationship hartree-atomic masa unit razmerje hartree-electron volt relationship hartree-elektron volt razmerje muon Compton wavelength mion Comptonova valovna dolzina muon-electron mass ratio mion-elektron masa ratio muon g factor mion g factor muon magnetic moment mion magnetni moment muon magnetic moment anomaly mion magnetni moment anomaly muon magnetic moment to Bohr magneton ratio mion magnetni moment to Bohr magneton ratio muon magnetic moment to nuclear magneton ratio mion magnetni moment to nuclear magneton ratio muon mass mion masa muon mass energy equivalent mion masa energijski ekvivalent muon mass energy equivalent in MeV mion masa energijski ekvivalent in MeV muon mass in u mion masa in u muon molar mass mion molar masa muon-neutron mass ratio mion-nevtron masa ratio muon-proton magnetic moment ratio mion-proton magnetni moment ratio muon-proton mass ratio mion-proton masa ratio muon-tau mass ratio mion-tau masa ratio reduced muon Compton wavelength reducirana mion Comptonova valovna dolzina reduced tau Compton wavelength reducirana tau Comptonova valovna dolzina tau Compton wavelength tau Comptonova valovna dolzina tau-electron mass ratio tau-elektron masa ratio tau mass tau masa tau mass energy equivalent tau masa energijski ekvivalent tau mass in u tau masa in u tau molar mass tau molar masa tau-muon mass ratio tau-mion masa ratio tau-neutron mass ratio tau-nevtron masa ratio tau-proton mass ratio tau-proton masa ratio proton charge to mass quotient proton charge to masa quotient proton Compton wavelength proton Comptonova valovna dolzina proton-electron mass ratio proton-elektron masa ratio proton g factor (gₚ) protonski faktor g (gₚ) proton gyromagnetic ratio (γₚ) proton giromagnetno razmerje (γₚ) proton gyromagnetic ratio in MHz/T proton giromagnetno razmerje in MHz/T proton magnetic moment (μₚ) proton magnetni moment (μₚ) proton magnetic moment to Bohr magneton ratio proton magnetni moment to Bohr magneton ratio proton magnetic moment to nuclear magneton ratio proton magnetni moment to nuclear magneton ratio proton magnetic shielding correction popravek magnetnega senÄ�enja protona proton mass (mₚ) proton masa (mₚ) proton mass energy equivalent proton masa energijski ekvivalent proton mass energy equivalent in MeV proton masa energijski ekvivalent in MeV proton mass in u proton masa in u proton molar mass (Mₚ) proton molar masa (Mₚ) proton-muon mass ratio proton-mion masa ratio proton-neutron magnetic moment ratio proton-nevtron magnetni moment ratio proton-neutron mass ratio proton-nevtron masa ratio proton relative atomic mass (Ar(p)) proton relative atomic masa (Ar(p)) proton rms charge radius rms polmer naboja protona proton-tau mass ratio proton-tau masa ratio reduced proton Compton wavelength reducirana proton Comptonova valovna dolzina shielded proton gyromagnetic ratio shielded proton giromagnetno razmerje shielded proton gyromagnetic ratio in MHz/T shielded proton giromagnetno razmerje in MHz/T shielded proton magnetic moment shielded proton magnetni moment shielded proton magnetic moment to Bohr magneton ratio shielded proton magnetni moment to Bohr magneton ratio shielded proton magnetic moment to nuclear magneton ratio shielded proton magnetni moment to nuclear magneton ratio neutron Compton wavelength nevtron Comptonova valovna dolzina neutron-electron magnetic moment ratio nevtron-elektron magnetni moment ratio neutron-electron mass ratio nevtron-elektron masa ratio neutron g factor (gâ‚™) nevtron g factor (gâ‚™) neutron gyromagnetic ratio (γₙ) nevtron giromagnetno razmerje (γₙ) neutron gyromagnetic ratio in MHz/T nevtron giromagnetno razmerje in MHz/T neutron magnetic moment (μₙ) nevtron magnetni moment (μₙ) neutron magnetic moment to Bohr magneton ratio nevtron magnetni moment to Bohr magneton ratio neutron magnetic moment to nuclear magneton ratio nevtron magnetni moment to nuclear magneton ratio neutron mass (mâ‚™) nevtron masa (mâ‚™) neutron mass energy equivalent nevtron masa energijski ekvivalent neutron mass energy equivalent in MeV nevtron masa energijski ekvivalent in MeV neutron mass in u nevtron masa in u neutron molar mass (Mâ‚™) nevtron molar masa (Mâ‚™) neutron-muon mass ratio nevtron-mion masa ratio neutron-proton magnetic moment ratio nevtron-proton magnetni moment ratio neutron-proton mass difference nevtron-proton masa difference neutron-proton mass difference energy equivalent nevtron-proton masa difference energijski ekvivalent neutron-proton mass difference energy equivalent in MeV nevtron-proton masa difference energijski ekvivalent in MeV neutron-proton mass difference in u nevtron-proton masa difference in u neutron-proton mass ratio nevtron-proton masa ratio neutron relative atomic mass (Ar(n)) nevtron relative atomic masa (Ar(n)) neutron-tau mass ratio nevtron-tau masa ratio neutron to shielded proton magnetic moment ratio nevtron to shielded proton magnetni moment ratio reduced neutron Compton wavelength reducirana nevtron Comptonova valovna dolzina deuteron-electron magnetic moment ratio devteron-elektron magnetni moment ratio deuteron-electron mass ratio devteron-elektron masa ratio deuteron g factor devteron g factor deuteron magnetic moment devteron magnetni moment deuteron magnetic moment to Bohr magneton ratio devteron magnetni moment to Bohr magneton ratio deuteron magnetic moment to nuclear magneton ratio devteron magnetni moment to nuclear magneton ratio deuteron mass devteron masa deuteron mass energy equivalent devteron masa energijski ekvivalent deuteron mass energy equivalent in MeV devteron masa energijski ekvivalent in MeV deuteron mass in u devteron masa in u deuteron molar mass devteron molar masa deuteron-neutron magnetic moment ratio devteron-nevtron magnetni moment ratio deuteron-proton magnetic moment ratio devteron-proton magnetni moment ratio deuteron-proton mass ratio devteron-proton masa ratio deuteron relative atomic mass (Ar(d)) devteron relative atomic masa (Ar(d)) deuteron rms charge radius devteron rms charge radius triton-electron mass ratio triton-elektron masa ratio triton g factor (gₜ) tritonov faktor g (gₜ) triton magnetic moment (μₜ) triton magnetni moment (μₜ) triton magnetic moment to Bohr magneton ratio triton magnetni moment to Bohr magneton ratio triton magnetic moment to nuclear magneton ratio triton magnetni moment to nuclear magneton ratio triton mass (mₜ) triton masa (mₜ) triton mass energy equivalent triton masa energijski ekvivalent triton mass energy equivalent in MeV triton masa energijski ekvivalent in MeV triton mass in u triton masa in u triton molar mass (Mₜ) triton molar masa (Mₜ) triton-proton mass ratio triton-proton masa ratio triton relative atomic mass (Ar(t)) triton relative atomic masa (Ar(t)) triton to proton magnetic moment ratio triton to proton magnetni moment ratio helion-electron mass ratio helion-elektron masa ratio helion g factor (gâ‚•) helionov faktor g (gâ‚•) helion magnetic moment (μₕ) helion magnetni moment (μₕ) helion magnetic moment to Bohr magneton ratio helion magnetni moment to Bohr magneton ratio helion magnetic moment to nuclear magneton ratio helion magnetni moment to nuclear magneton ratio helion mass (mâ‚•) helion masa (mâ‚•) helion mass energy equivalent helion masa energijski ekvivalent helion mass energy equivalent in MeV helion masa energijski ekvivalent in MeV helion mass in u helion masa in u helion molar mass (Mâ‚•) helion molar masa (Mâ‚•) helion-proton mass ratio helion-proton masa ratio helion relative atomic mass (Ar(h)) helion relative atomic masa (Ar(h)) helion shielding shift premik zaradi senÄ�enja heliona shielded helion gyromagnetic ratio shielded helion giromagnetno razmerje shielded helion gyromagnetic ratio in MHz/T shielded helion giromagnetno razmerje in MHz/T shielded helion magnetic moment shielded helion magnetni moment shielded helion magnetic moment to Bohr magneton ratio shielded helion magnetni moment to Bohr magneton ratio shielded helion magnetic moment to nuclear magneton ratio shielded helion magnetni moment to nuclear magneton ratio shielded helion to proton magnetic moment ratio shielded helion to proton magnetni moment ratio shielded helion to shielded proton magnetic moment ratio shielded helion to shielded proton magnetni moment ratio alpha particle mass alfa delec masa alpha particle mass in u alfa delec masa in u alpha particle mass energy equivalent alfa delec masa energijski ekvivalent alpha particle mass energy equivalent in MeV alfa delec masa energijski ekvivalent in MeV alpha particle-electron mass ratio alfa delec-elektron masa ratio alpha particle-proton mass ratio alfa delec-proton masa ratio alpha particle rms charge radius alfa delec rms charge radius alpha particle molar mass alfa delec molar masa alpha particle relative atomic mass (Ar(α)) alfa delec relative atomic masa (Ar(α)) atomic mass constant (mᵤ) atomic masa konstanta (mᵤ) Avogadro constant Avogadro konstanta Boltzmann constant (k) Boltzmann konstanta (k) Boltzmann constant in eV/K Boltzmann konstanta in eV/K Boltzmann constant in Hz/K Boltzmann konstanta in Hz/K Boltzmann constant in inverse meter per kelvin Boltzmann konstanta in inverzni meter per kelvin electron volt (eV) elektron volt (eV) Faraday constant (F) Faraday konstanta (F) first radiation constant (câ‚�) first radiation konstanta (câ‚�) first radiation constant for spectral radiance first radiation konstanta for spectral radiance molar gas constant (R) molar gas konstanta (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Loschmidt konstanta (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Loschmidt konstanta (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molar Planck konstanta second radiation constant (câ‚‚) second radiation konstanta (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Boltzmann konstanta (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) mrežni razmik idealnega Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atomic masa konstanta energijski ekvivalent atomic mass constant energy equivalent in MeV atomic masa konstanta energijski ekvivalent in MeV atomic mass unit-electron volt relationship atomic masa unit-elektron volt razmerje molar mass constant (Mᵤ) molar masa konstanta (Mᵤ) molar mass of carbon-12 molar masa of carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) molska prostornina idealnega plina (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) molska prostornina idealnega plina (273.15 K, 101.325 kPa) molar volume of silicon molska prostornina silicija Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode konstanta (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode konstanta (1 K, 101.325 kPa) Wien frequency displacement law constant Wien frequency displacement law konstanta Wien wavelength displacement law constant Wien wavelength displacement law konstanta standard atmosphere (atm) standardna atmosfera (atm) standard-state pressure (p°) standardni tlak stanja (p°) Angstrom star (Ã…*) angstromova zvezdica (Ã…*) Copper x unit bakrena enota x Molybdenum x unit molibdenova enota x atomic unit of magnetizability atomska enota of magnetizability atomic unit of mass (mâ‚‘) atomska enota of masa (mâ‚‘) atomic unit of momentum atomska enota of momentum atomic unit of permittivity atomska enota of permittivity atomic unit of time atomska enota of time atomic unit of velocity atomska enota of velocity hartree-hertz relationship hartree-hertz razmerje hartree-inverse meter relationship hartree-inverzni meter razmerje hartree-joule relationship hartree-joule razmerje hartree-kelvin relationship hartree-kelvin razmerje hartree-kilogram relationship hartree-kilogram razmerje shielding difference of d and p in HD razlika v senÄ�enju d in p v HD shielding difference of t and p in HT razlika v senÄ�enju t in p v HT pi (Ï€) pi (Ï€) Euler's number (e) Eulerjevo Å¡tevilo (e) golden ratio (φ) zlato razmerje (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni konstanta (γ) nominal solar radius nazivni polmer Sonca nominal solar total irradiance nazivna skupna sonÄ�na obsevanost nominal solar luminosity nazivna SonÄ�eva izsevnost nominal solar effective temperature nazivna efektivna temperatura Sonca nominal solar mass parameter nominal solar masa parameter nominal terrestrial equatorial radius nazivni ekvatorialni polmer Zemlje nominal terrestrial polar radius nazivni polarni polmer Zemlje nominal terrestrial mass parameter nominal terrestrial masa parameter nominal jovian equatorial radius nazivni ekvatorialni polmer Jupitra nominal jovian polar radius nazivni polarni polmer Jupitra nominal jovian mass parameter nominal jovian masa parameter average value of one minus the rate of TCG relative to TCB povpreÄ�na vrednost ena minus hitrost TCG glede na TCB solar mass parameter (TCB-compatible) solar masa parameter (TCB-compatible) solar mass parameter (TDB-compatible) solar masa parameter (TDB-compatible) equatorial radius of the Earth (TT-compatible) ekvatorialni polmer Zemlje (združljiv s TT) dynamical form factor of the Earth dinamiÄ�ni oblikovni faktor Zemlje time rate of change in the dynamical form factor of the Earth Ä�asovna stopnja spremembe dinamiÄ�nega oblikovnega faktorja Zemlje geocentric gravitational constant (TCB-compatible) geocentric gravitational konstanta (TCB-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational konstanta (TT-compatible) geocentric gravitational constant (TDB-compatible) geocentric gravitational konstanta (TDB-compatible) potential of the geoid potencial geoida nominal mean angular velocity of the Earth (TT-compatible) nazivna srednja kotna hitrost Zemlje (združljiva s TT) ratio mass of the Moon to the Earth ratio masa of the Moon to the Earth ratio of the mass of the Sun to Mercury ratio of the masa of the Sun to Mercury ratio of the mass of the Sun to Venus ratio of the masa of the Sun to Venus ratio of the mass of the Sun to Mars ratio of the masa of the Sun to Mars ratio of the mass of the Sun to Jupiter ratio of the masa of the Sun to Jupiter ratio of the mass of the Sun to Saturn ratio of the masa of the Sun to Saturn ratio of the mass of the Sun to Uranus ratio of the masa of the Sun to Uranus ratio of the mass of the Sun to Neptune ratio of the masa of the Sun to Neptune ratio of the mass of the Sun to (134340) Pluto ratio of the masa of the Sun to (134340) Pluto ratio of the mass of the Sun to (136199) Eris ratio of the masa of the Sun to (136199) Eris ratio of the mass of (1) Ceres to the Sun ratio of the masa of (1) Ceres to the Sun ratio of the mass of (2) Pallas to the Sun ratio of the masa of (2) Pallas to the Sun ratio of the mass of (4) Vesta to the Sun ratio of the masa of (4) Vesta to the Sun mean obliquity of the ecliptic at J2000.0 srednja naklonjenost ekliptike pri J2000.0 Electromagnetic Elektromagnetne Compton wavelength Comptonova valovna dolžina Astronomy Astronomija ConstantsWidget Domain Domena Subdomain Poddomena No match found Ni najdenih ujemanj Name Ime Value Vrednost Unit Enota Search IÅ¡Ä�i All Vse CustomKeypadDialog Custom Keypad Tipkovnica po meri Rows: Vrstice: Columns: Stolpci: Copy preset: Kopiraj prednastavitev: Basic Osnovno Scientific (wide) Znanstveno (Å¡iroko) Scientific (narrow) Znanstveno (ozko) Apply Uporabi Row Vrstica Column Stolpec Label Oznaka Behavior Vedenje Text Besedilo DiagnosticsDialog App Diagnostics Diagnostika programa Copy to Clipboard Kopiraj v odložiÅ¡Ä�e Editor Unit Enota User unit UporabniÅ¡ka enota User function UporabniÅ¡ka funkcija Argument Argument Current result:<br/>%1 Trenutni rezultat:<br/>%1 Selection result:<br/>%1 Rezultat izbora:<br/>%1 Selection result: n/a Rezultat izbora: ni na voljo Selection result: %1 Rezultat izbora: %1 second sekunda metre meter kilogram kilogram mole mol radian radian steradian steradian degree Celsius stopinja Celzija cubic metre kubiÄ�ni meter cubic millimetre kubiÄ�ni milimeter cubic centimetre kubiÄ�ni centimeter cubic decimetre kubiÄ�ni decimeter cubic kilometre kubiÄ�ni kilometer square millimetre kvadratni milimeter square kilometre kvadratni kilometer square metre kvadratni meter minute minuta hour ura day dan astronomical unit astronomska enota degree stopinja arcminute loÄ�na minuta arcsecond loÄ�na sekunda milliarcsecond mililoÄ�na sekunda microarcsecond mikroloÄ�na sekunda hectare hektar litre liter tonne tona Dalton dalton electronvolt elektronvolt Angstrom angstrom atmosphere atmosfera atomic mass unit atomska masna enota British thermal unit britanska toplotna enota calorie kalorija carat karat cup skodelica cup (Imperial) skodelica (imperialna) cup (Japanese) skodelica (japonska) cup (US) skodelica (ZDA) degree Fahrenheit stopinja Fahrenheita fathom seženj fluid ounce (Imperial) tekoÄ�inska unÄ�a (imperialna) fluid ounce (US) tekoÄ�inska unÄ�a (ZDA) fluid dram (Imperial) tekoÄ�inski dram (imperialni) fluid dram (US) tekoÄ�inski dram (ZDA) foot cevelj square foot kvadratni Ä�evelj cubic foot kubiÄ�ni Ä�evelj gallon (Imperial) galona (imperialna) gallon (US) galona (ZDA) gill (Imperial) gill (imperialni) gill (US) gill (ZDA) gradian gradian grain gran gram gram Hartley hartley Hartree energy unit Hartreejeva energijska enota horsepower konjska moÄ� inch palec square inch kvadratni palec cubic inch kubiÄ�ni palec karat karat knot vozel lightminute svetlobna minuta lightsecond svetlobna sekunda lightyear svetlobno leto long ton dolga tona mile milja square mile kvadratna milja cubic mile kubiÄ�na milja mile per hour milja na uro kilometre per hour kilometer na uro nautical mile navtiÄ�na milja ounce unca parsec parsek pint (Imperial) pinta (imperialna) pint (US) pinta (ZDA) pound funt pounds per square inch funti na kvadratni palec quart (Imperial) kvart (imperialni) quart (US) kvart (ZDA) oil barrel naftni sod beer barrel (US) pivski sod (ZDA) square yard kvadratni jard cubic yard kubiÄ�ni jard short ton kratka tona tablespoon jedilna žlica tablespoon (Australian) jedilna žlica (avstralska) tablespoon (Imperial) jedilna žlica (imperialna) tablespoon (US) jedilna žlica (ZDA) dessert spoon desertna žliÄ�ka teaspoon Ä�ajna žliÄ�ka teaspoon (Imperial) Ä�ajna žliÄ�ka (imperialna) teaspoon (US) Ä�ajna žliÄ�ka (ZDA) turn obrat revolution vrtljaj revolution per minute vrtljaj na minuto week teden kilowatt hour kilovatna ura millimetre of mercury milimeter živega srebra yard jard Julian century julijansko stoletje Julian year julijansko leto sidereal year zvezdno leto tropical year tropsko leto Evaluator invalid expression neveljaven izraz division by zero deljenje z niÄ�lo too time consuming - computation was rejected preveÄ� zamudno - izraÄ�un je bil zavrnjen dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimenzije se ne ujemajo - koliÄ�in z razliÄ�nimi dimenzijami ni mogoÄ�e primerjati, seÅ¡tevati itd. invalid dimension - operation might require dimensionless arguments neveljavna dimenzija - operacija morda zahteva brezdimenzijske argumente Computation aborted - encountered numerical instability IzraÄ�un je bil prekinjen - zaznana je bila numeriÄ�na nestabilnost invalid dimension - function might require dimensionless arguments neveljavna dimenzija - funkcija morda zahteva brezdimenzijske argumente error napaka unit must not be zero enota ne sme biti niÄ� Conversion failed - dimension mismatch Pretvorba ni uspela - dimenzije se ne ujemajo unknown function or variable neznana funkcija ali spremenljivka recursion not supported rekurzija ni podprta cannot operate on a NaN operacija nad NaN ni mogoÄ�a underflow - tiny result is out of SpeedCrunch's number range podkoraÄ�itev - zelo majhen rezultat je zunaj Å¡tevilskega obsega SpeedCrunch overflow - huge result is out of SpeedCrunch's number range prekoraÄ�itev - ogromen rezultat je zunaj Å¡tevilskega obsega SpeedCrunch overflow - logic result exceeds maximum of 256 bits prekoraÄ�itev - logiÄ�ni rezultat presega najveÄ� 256 bitov overflow - integer result exceeds maximum limit for integers prekoraÄ�itev - celoÅ¡tevilski rezultat presega najveÄ�jo mejo za cela Å¡tevila operation is not defined for these arguments operacija ni definirana za te argumente wrong number of arguments napaÄ�no Å¡tevilo argumentov does not take NaN as an argument ne sprejme NaN kot argumenta result out of range rezultat je zunaj obsega undefined for argument domain ni definirano za domeno argumenta computation too expensive izraÄ�un je prezahteven internal error, please report a bug notranja napaka, prijavite napako v programu syntax error skladenjska napaka conversion target must be a unit cilj pretvorbe mora biti enota unknown unit neznana enota %1 is a reserved name, please choose another %1 je rezervirano ime, izberite drugo %1 is a global user definition and cannot be overridden in this session. %1 je globalna uporabniÅ¡ka definicija in je v tej seji ni mogoÄ�e prepisati. %1 is a variable name, please choose another or delete the variable %1 je ime spremenljivke, izberite drugo ime ali izbriÅ¡ite spremenljivko argument %1 is used more than once argument %1 je uporabljen veÄ� kot enkrat %1 is a built-in unit name, please choose another %1 je ime vgrajene enote, izberite drugo ime %1 is a user function name, please choose another or delete the function %1 je ime uporabniÅ¡ke funkcije, izberite drugo ime ali izbriÅ¡ite funkcijo FunctionRepo max; trials; probability maksimum; poskusi; verjetnost trials; probability poskusi; verjetnost hits; trials; probability zadetki; poskusi; verjetnost max; total; hits; trials maksimum; skupaj; zadetki; poskusi total; hits; trials skupaj; zadetki; poskusi count; total; hits; trials Å¡tevilo; skupaj; zadetki; poskusi dividend; divisor deljenec; delitelj x; exponent_bits; significand_bits [; exponent_bias] x; biti eksponenta; biti significanda [; odmik eksponenta] base; x osnova; x value; modulo vrednost; modul base; exponent; modulo osnova; eksponent; modul events; average_events dogodki; povpreÄ�no_Å¡tevilo_dogodkov average_events povpreÄ�no_Å¡tevilo_dogodkov x [; precision] x [; natanÄ�nost] Absolute Value Absolutna vrednost Absolute Deviation Absolutni odklon Arc Cosine Arkus kosinus Logical AND LogiÄ�ni IN Area Hyperbolic Cosine Inverzni hiperboliÄ�ni kosinus Area Hyperbolic Sine Inverzni hiperboliÄ�ni sinus Area Hyperbolic Tangent Inverzni hiperboliÄ�ni tangens Arc Sine Arkus sinus Arc Tangent Arkus tangens Arc Tangent with two Arguments Arkus tangens z dvema argumentoma Average (Arithmetic Mean) PovpreÄ�je (aritmetiÄ�na sredina) Binomial Cumulative Distribution Function Binomska kumulativna porazdelitvena funkcija Binomial Distribution Mean Srednja vrednost binomske porazdelitve Binomial Probability Mass Function Funkcija verjetnostne mase binomske porazdelitve Binomial Distribution Variance Varianca binomske porazdelitve Cube Root KubiÄ�ni koren Complex Conjugate Kompleksno konjugirano Å¡tevilo Cosine Kosinus Hyperbolic Cosine HiperboliÄ�ni kosinus Cotangent Kotangens Cosecant Kosekans Convert Unix timestamp to Date Pretvori Ä�asovni žig Unix v datum Degrees of Arc Kotne stopinje Error Function Funkcija napake Complementary Error Function Komplementarna funkcija napake Exponential Eksponentna funkcija Fractional Part Ulomljeni del Extension of Factorials [= (x-1)!] RazÅ¡iritev fakultet [= (x-1)!] Greatest Common Divisor NajveÄ�ji skupni delitelj Geometric Mean Geometrijska sredina Gradians of arc Gradiani kota Hypergeometric Cumulative Distribution Function HipergeometriÄ�na kumulativna porazdelitvena funkcija Hypergeometric Distribution Mean Srednja vrednost hipergeometriÄ�ne porazdelitve Hypergeometric Probability Mass Function Funkcija verjetnostne mase hipergeometriÄ�ne porazdelitve Hypergeometric Distribution Variance Varianca hipergeometriÄ�ne porazdelitve Integer Quotient CeloÅ¡tevilski koliÄ�nik Integer Part Celi del Imaginary Part Imaginarni del Decode IEEE-754 Binary Value Dekodiraj dvojiÅ¡ko vrednost IEEE-754 Encode IEEE-754 Binary Value Kodiraj dvojiÅ¡ko vrednost IEEE-754 Decode 16-bit Half-Precision Value Dekodiraj 16-bitno vrednost poloviÄ�ne natanÄ�nosti Encode 16-bit Half-Precision Value Kodiraj 16-bitno vrednost poloviÄ�ne natanÄ�nosti Decode 32-bit Single-Precision Value Dekodiraj 32-bitno vrednost enojne natanÄ�nosti Encode 32-bit Single-Precision Value Kodiraj 32-bitno vrednost enojne natanÄ�nosti Decode 64-bit Double-Precision Value Dekodiraj 64-bitno vrednost dvojne natanÄ�nosti Encode 64-bit Double-Precision Value Kodiraj 64-bitno vrednost dvojne natanÄ�nosti Decode 128-bit Quad-Precision Value Dekodiraj 128-bitno vrednost Ä�etverne natanÄ�nosti Encode 128-bit Quad-Precision Value Kodiraj 128-bitno vrednost Ä�etverne natanÄ�nosti Binary Logarithm DvojiÅ¡ki logaritem Common Logarithm DesetiÅ¡ki logaritem Natural Logarithm Naravni logaritem Logarithm to Arbitrary Base Logaritem s poljubno osnovo Mask to a bit size Maskiraj na velikost v bitih Maximum Maksimum Median Value (50th Percentile) Mediana (50. percentil) Minimum Minimum Modulo Modul Euclidean Modulo Evklidski modul Modular Exponentiation Modularno potenciranje Combination (Binomial Coefficient) Kombinacija (binomski koeficient) Logical NOT LogiÄ�ni NE Permutation (Arrangement) Permutacija (razporeditev) Convert to Binary Representation Pretvori v dvojiÅ¡ki prikaz Arithmetic Aritmetika Chemistry Kemija Complex Kompleksna Å¡tevila Combinatorics Kombinatorika Probability Verjetnost Statistics Statistika Aggregation Agregacija Random Nakljucno Base conversion Pretvorba osnove Number formatting Oblikovanje Å¡tevil Integer arithmetic CeloÅ¡tevilska aritmetika Special functions Posebne funkcije Exponential & Logarithmic Eksponentno in logaritemsko Angle conversion Pretvorba kotov Trigonometry Trigonometrija Bitwise Bitne operacije Floating point PlavajoÄ�a vejica Date & Time Datum in Ä�as Linear algebra Linearna algebra unix_timestamp; x hours offset to GMT Ä�asovni_žig_unix; odmik x ur od GMT yyyymmdd.hhmmss; x hours offset to GMT llllmmdd.hhmmss; odmik x ur od GMT [digits] [Å¡tevke] max [; min] maksimum [; minimum] List Literal Literal seznama Convert to Padded Binary Representation Pretvori v niÄ�lami dopolnjen dvojiÅ¡ki prikaz Round Toward +∞ (Ceiling) Zaokroži proti +∞ (navzgor) Cosine plus Imaginary Sine Kosinus plus imaginarni sinus Convert to Cis Complex Form Pretvori v kompleksno obliko cis Matrix Column Count Å tevilo stolpcev matrike Population Correlation Matrix (n) Populacijska korelacijska matrika (n) Sample Correlation Matrix (n-1) VzorÄ�na korelacijska matrika (n-1) Count Å tevilo Population Covariance Matrix (n) Populacijska kovarianÄ�na matrika (n) Sample Covariance Matrix (n-1) VzorÄ�na kovarianÄ�na matrika (n-1) Cross Product Vektorski produkt Convert Date to Unix timestamp Pretvori datum v Ä�asovni žig Unix Convert to Decimal Representation Pretvori v desetiÅ¡ki prikaz Determinant Determinanta Convert to Sexagesimal Notation Pretvori v Å¡estdesetiÅ¡ki zapis Dot Product Skalarni produkt Convert to Engineering Notation Pretvori v inženirski zapis Convert to Exponential Complex Form Pretvori v eksponentno kompleksno obliko Round Toward −∞ (Floor) Zaokroži proti −∞ (navzdol) Flatten Matrix SploÅ¡Ä�i matriko Least Common Multiple NajmanjÅ¡i skupni veÄ�kratnik Convert to Hexadecimal Representation Pretvori v Å¡estnajstiÅ¡ki prikaz Convert to Padded Hexadecimal Representation Pretvori v niÄ�lami dopolnjen Å¡estnajstiÅ¡ki prikaz Inverse Matrix Inverzna matrika Round to 16-bit Half-Precision Value Zaokroži na 16-bitno vrednost poloviÄ�ne natanÄ�nosti Round to 32-bit Single-Precision Value Zaokroži na 32-bitno vrednost enojne natanÄ�nosti Round to 64-bit Double-Precision Value Zaokroži na 64-bitno vrednost dvojne natanÄ�nosti Round to 128-bit Quad-Precision Value Zaokroži na 128-bitno vrednost Ä�etverne natanÄ�nosti Residual from 16-bit Half-Precision Rounding Ostanek pri zaokroževanju na 16-bitno poloviÄ�no natanÄ�nost Residual from 32-bit Single-Precision Rounding Ostanek pri zaokroževanju na 32-bitno enojno natanÄ�nost Residual from 64-bit Double-Precision Rounding Ostanek pri zaokroževanju na 64-bitno dvojno natanÄ�nost Residual from 128-bit Quad-Precision Rounding Ostanek pri zaokroževanju na 128-bitno Ä�etverno natanÄ�nost Substance Mass Masa snovi Molarity Molarnost Molar Mass Molska masa Median Absolute Deviation Mediana absolutnega odklona Mean PovpreÄ�je Numerical Value of Quantity Å tevilska vrednost koliÄ�ine Random Decimal Number NakljuÄ�no decimalno Å¡tevilo Random Integer Number NakljuÄ�no celo Å¡tevilo Convert to Rational Representation Pretvori v racionalni prikaz Convert to Octal Representation Pretvori v osmiÅ¡ki prikaz Convert to Padded Octal Representation Pretvori v niÄ�lami dopolnjen osmiÅ¡ki prikaz Vector or Matrix Norm Norma vektorja ali matrike Logical OR LogiÄ�ni ALI Population Count (Hamming Weight) Å tevilo enic (Hammingova teža) Phase of Complex Number Faza kompleksnega Å¡tevila Poissonian Cumulative Distribution Function Poissonova kumulativna porazdelitvena funkcija Poissonian Distribution Mean Srednja vrednost Poissonove porazdelitve Poissonian Probability Mass Function Funkcija verjetnostne mase Poissonove porazdelitve Poissonian Distribution Variance Varianca Poissonove porazdelitve Convert to Phasor Complex Form Pretvori v fazorsko kompleksno obliko Convert to Rectangular Complex Form Pretvori v pravokotno kompleksno obliko Round Half Away from Zero Zaokroži polovico stran od niÄ�le Round Half Even Zaokroži polovico na sodo Nth Root N-ti koren Convert to Scientific Notation Pretvori v znanstveni zapis Matrix Row Count Å tevilo vrstic matrike List or Matrix Shape Oblika seznama ali matrike Summation Vsota Population Standard Deviation (n) Populacijski standardni odklon (n) Sample Standard Deviation (n-1) VzorÄ�ni standardni odklon (n-1) Round Toward Zero (Truncation) Zaokroži proti niÄ�li (odrez) Matrix Trace Sled matrike Transpose Matrix Transponiraj matriko Population Variance (n) Populacijska varianca (n) Sample Variance (n-1) VzorÄ�na varianca (n-1) Product Produkt Radians Radiani Matrix Rank Rang matrike Real Part Realni del Secant Sekans Arithmetic Shift Left AritmetiÄ�ni pomik v levo Arithmetic Shift Right AritmetiÄ�ni pomik v desno Signum Signum Sine Sinus Hyperbolic Sine HiperboliÄ�ni sinus Square Root Kvadratni koren Sum Vsota Tangent Tangens Convert to Trigonometric Complex Form Pretvori v trigonometriÄ�no kompleksno obliko Turns Obrati Hyperbolic Tangent HiperboliÄ�ni tangens Sign-extend a value PredznaÄ�no razÅ¡iri vrednost Logical XOR LogiÄ�ni izkljuÄ�ni ALI FunctionsWidget Domain Domena All Vse Name Ime Search IÅ¡Ä�i No match found Ni najdenih ujemanj Identifier Identifikator HistoryWidget Remove All Calculations Above Odstrani vse izraÄ�une zgoraj Remove This Calculation Odstrani ta izraÄ�un Remove All Calculations Below Odstrani vse izraÄ�une spodaj Keypad Inverse cosine Inverzni kosinus The last result Zadnji rezultat Inverse sine Inverzni sinus Inverse tangent Inverzni tangens Evaluate expression Ovrednoti izraz Division Deljenje Multiplication Množenje Subtraction OdÅ¡tevanje Addition SeÅ¡tevanje Clear expression PoÄ�isti izraz Cosine Kosinus Backspace Vracalka Scientific notation Znanstveni zapis Exponential Eksponentna funkcija Factorial Fakulteta Natural logarithm Naravni logaritem Left parenthesis Levi oklepaj Nth root N-ti koren Argument separator LoÄ�ilo argumentov Square Kvadrat Common logarithm DesetiÅ¡ki logaritem Modulo Modul Contextual percentage Kontekstualni odstotek Power Potenca Right parenthesis Desni oklepaj Sine Sinus Square root Kvadratni koren Tangent Tangens Pi Pi Decimal separator Decimalno locilo MainWindow Radian Radian Degree Stopinja Gradian Gradian Binary DvojiÅ¡ko Octal OsmiÅ¡ko Hexadecimal Å estnajstiÅ¡ko Sexagesimal Å estdesetiÅ¡ko Engineering decimal Inženirsko decimalno Scientific decimal Znanstveno decimalno &Import... &Uvozi... &Quit &Zapri Clear E&xpression &PoÄ�isti izraz Clear &History PoÄ�isti &zgodovino &Copy &Kopiraj &Paste &Prilepi &Select Expression &Izberi izraz &Constants &Konstante &Functions &Funkcije &History &Zgodovina &Status Bar &Statusna vrstica Bitfield Bitno polje Use&r Functions UporabniÅ¡ke &funkcije &Degree &Stopinja &Radian &Radian &Gradian &Gradian Re&volution O&brat Auto-Insert a&ns Samodej&no vstavi ans Automatic &Completion Samodejno &dopolnjevanje &Built-in Functions &Vgrajene funkcije Built-in &Variables V&grajene spremenljivke User &Functions UporabniÅ¡ke &funkcije User Va&riables Upo&rabniÅ¡ke spremenljivke Open a Private Tab on Startup Ob zagonu odpri zasebni zavihek Open and focus a new private tab whenever SpeedCrunch starts. Ob vsakem zagonu SpeedCrunch odpri in aktiviraj nov zasebni zavihek. Syntax &Highlighting &Obarvanje sintakse Group Digits in &Input Združuj Å¡tevke pr&i vnosu Automatic Input &Adjustments S&amodejne prilagoditve vnosa Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Samodejno prilagodi operatorje, presledke, oklepaje in potence ter omeji vnos na veljavne znake. Group input digits using the selected number format. Združuj vnesene Å¡tevke po izbrani obliki Å¡tevil. &Blinking Cursor &UtripajoÄ�i kazalec Blink the cursor in the expression editor. Kazalec v urejevalniku izrazov naj utripa. &Escape Clears Editor &Escape poÄ�isti urejevalnik Clear the focused expression editor with Escape after dismissing any popup or preview. S tipko Escape poÄ�isti aktivni urejevalnik izrazov, ko so zaprta vsa pojavna okna ali predogledi. Keep Expression After Evaluation Ohrani izraz po izraÄ�unu Copy New Results Automatically Samodejno kopiraj nove rezultate &Comma &Vejica &System Default &Privzete nastavitve &Dot &Pika Dot &And Comma Pika &in vejica Toward +∞ (&ceil) Proti +∞ (&ceil) Toward −∞ (&floor) Proti −∞ (&floor) &Binary &DvojiÅ¡ko &Engineering &Inženirsko &Hexadecimal &Å estnajstiÅ¡ko &Octal &OsmiÅ¡ko &Scientific &Znanstveno User &Manual UporabniÅ¡ki &priroÄ�nik Issues and &Feedback Težave in povratne in&formacije &Donate &Doniraj &About SpeedCrunch O progr&amu SpeedCrunch App Diag&nostics Diag&nostika programa S&plit &Razdeli Angle &Mode &Kotni naÄ�in &Complex Form &Kompleksna oblika New Tab Nov zavihek Constants Konstante Functions Funkcije History Zgodovina User Functions UporabniÅ¡ke funkcije &Font... &Pisava... &Language... &Jezik... &Session &Seja &Edit &Uredi &View &Pogled Se&ttings Nas&tavitve &Decimal &Decimalno &Keypad &Tipkovnica Always on &Top Vedno na &vrhu Disabled OnemogoÄ�eno Small Space Majhen presledek Medium Space Srednji presledek Large Space Velik presledek &0 Digits &0 Å¡tevk &15 Digits &15 Å¡tevk &2 Digits &2 Å¡tevki &3 Digits &3 Å¡tevke &50 Digits &50 Å¡tevk &8 Digits &8 Å¡tevk &Sexagesimal &Å estdesetiÅ¡ko Reset All Settings... Ponastavi vse nastavitve... &System &Sistem SpeedCrunch &Theme &Tema SpeedCrunch &Classic &KlasiÄ�no &Modern &Sodobno Context Help Kontekstna pomoÄ� &Help &PomoÄ� Error Napaka Can't read from file %1 Ni mogoÄ�e brati iz datoteke %1 Import Session Uvozi sejo Close Session Zapri sejo Angle Mode: Kotni naÄ�in: Notation: Zapis: Precision: NatanÄ�nost: Turn Obrat Revolution Obrat Fixed-point decimal Decimalno s fiksno vejico Rational Racionalno Automatic decimal Samodejno decimalno Automatic Samodejno User &Definitions... UporabniÅ¡ke &definicije... New &Tab Nov &zavihek New &Private Tab &Nov zasebni zavihek Keep Ohrani Make Private... Naredi zasebno... New &Window Novo &okno &Open... &Odpri... &Rename... P&reimenuj... Clo&ne... &Kloniraj... &Close Tab Z&apri zavihek Reopen Clo&sed Tab Zno&va odpri zaprti zavihek Open Sessions &Folder Odpri &mapo sej &Undo &Razveljavi &Redo &Uveljavi Cu&t Izr&eži Copy &Last Result Kopiraj zadnji rezu&ltat &Wrap in Parentheses &Ovij v oklepaje Full Scr&een Mode &Celozaslonski naÄ�in &Basic &Osnovno &Scientific (wide) &Znanstveno (Å¡iroko) Scientific (narrow) Znanstveno (ozko) &Custom... Po &meri... Main &Menu Glavni &meni User &Variables UporabniÅ¡ke &spremenljivke &Left &Levo &Right &Desno &Up &Gor &Down D&ol Close Pa&ne Zapri podok&no User &Units UporabniÅ¡ke &enote &Turn &Obrat If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. ÄŒe se nov izraz zaÄ�ne z +, -, * ali /, SpeedCrunch najprej vstavi "ans". &Accept with Enter &Sprejmi z Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Sprejmi trenutni predlog samodejnega dopolnjevanja s tipko Enter brez predhodne izbire s puÅ¡Ä�iÄ�nimi tipkami. &Units &Enote Show Live Result &Preview Prikaži &predogled rezultata v živo Save &Window Position on Exit Ob izhodu shrani položaj &okna Hover Highlighting OznaÄ�evanje ob prehodu miÅ¡ke Group Integer Part Only Zdruzi samo celi del Number Format... Oblika Å¡tevila... Notation && Precision... Zapis in natanÄ�nost... After pressing Enter, keep the entered expression selected in the editor. Po pritisku Enter naj vneseni izraz ostane izbran v urejevalniku. Never Nikoli Always Vedno Only for Single-Line Expressions Samo za enovrstiÄ�ne izraze Simplify Displayed Expressions Poenostavi prikazane izraze History Size &Limit... &Omejitev velikosti zgodovine... Remove Trailing &Zeroes &Odstrani konÄ�ne niÄ�le Nearest, Half &Away (round) Najbližje, polovica &stran (round) Nearest, Half &Even (roundeven) Najbližje, polovica na &sodo (roundeven) Toward &Zero (trunc) Proti &niÄ�li (trunc) &Fixed-Point &Fiksna vejica &Rational &Racionalno &Exponential (m·sâ�»Â¹) &Eksponentno (m·sâ�»Â¹) &Fractional (m/s) &Ulomkovno (m/s) &Rectangular (a + bi) &Pravokotno (a + bi) Exponential (reâ�±á¶¿) Eksponentno (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) TrigonometriÄ�no (r(cos θ + i·sin θ)) Phasor (r∠θ) Fazor (r∠θ) &Theme... &Tema ... Check for &Updates Preveri &posodobitve Source Code Izvorna koda &Zoom &PoveÄ�ava &Results &Rezultati Unit Notation Zapis enot Rounding Mode NaÄ�in zaokroževanja &Notation &Zapis &Imaginary Unit &Imaginarna enota &Window &Okno &Editing &Urejanje A&utocomplete Samodejno &dopolnjevanje Up/Down Arrow History Zgodovina s puÅ¡Ä�icama gor/dol &Appearance &Videz &Menus &Meniji &Docks Si&drljive ploÅ¡Ä�e &Input and Results Vnos &in rezultati &Disabled &OnemogoÄ�eno &Disable &OnemogoÄ�i Close preview Zapri predogled Rename... Preimenuj... Clone... Kloniraj... Close Tab Zapri zavihek New Private Tab Nov zasebni zavihek Open... Odpri... Reopen Closed Tab Znova odpri zaprti zavihek Split Razdeli Left Levo Right Desno Up Gor Down Dol Clear PoÄ�isti Delete IzbriÅ¡i %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Zasebna seja: vsebina se ob zaprtju zavrže. Izberite Seja > Ohrani, da jo spremenite v obiÄ�ajno sejo. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Zasebno] Reset All Settings Ponastavi vse nastavitve Reset all settings to their default values? Ponastavim vse nastavitve na privzete vrednosti? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. To vkljuÄ�uje videz, urejanje, oblike rezultatov in nastavitve oken. VaÅ¡i izraÄ�uni, odprte seje in uporabniÅ¡ke definicije bodo ohranjeni. The settings file could not be written. Datoteke z nastavitvami ni bilo mogoÄ�e zapisati. Clear this session's calculations, unfinished expression, variables, functions, and units? PoÄ�istim izraÄ�une, nedokonÄ�ani izraz, spremenljivke, funkcije in enote te seje? Global user definitions are kept. Globalne uporabniÅ¡ke definicije se ohranijo. Make Session Private Naredi sejo zasebno The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Shranjena seja %1 bo izbrisana. Njena vsebina bo ostala odprta v zasebni seji in bo zavržena, ko zaprete to sejo ali SpeedCrunch. Make Private Naredi zasebno Could not delete the saved session %1. Shranjene seje %1 ni bilo mogoÄ�e izbrisati. Keep Session Ohrani sejo Could not save the session. It remains private. Seje ni bilo mogoÄ�e shraniti. Ostaja zasebna. Clone Session Kloniraj sejo Could not save session file %1. Datoteke seje %1 ni bilo mogoÄ�e shraniti. Could not delete session file %1. Datoteke seje %1 ni bilo mogoÄ�e izbrisati. JSON file (*.json);;Any file (*.*) Datoteka JSON (*.json);;Katera koli datoteka (*.*) Export session as JSON Izvozi sejo kot JSON The selected file is not valid JSON: %1 Izbrana datoteka ni veljaven JSON: %1 The selected file is not a SpeedCrunch session JSON file. Izbrana datoteka ni datoteka JSON seje SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Ta datoteka uporablja zastarel zapis seje SpeedCrunch in je ni mogoÄ�e uvoziti. The selected JSON file is missing the required $schema field. V izbrani datoteki JSON manjka zahtevano polje $schema. The selected JSON file uses an unsupported JSON schema: %1 Izbrana datoteka JSON uporablja nepodprto shemo JSON: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). V izbrani datoteki JSON manjka identifikator sheme seje SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Izbrana datoteka JSON uporablja nepodprt zapis seje SpeedCrunch: %1 The selected JSON file is missing the required session name. V izbrani datoteki JSON manjka zahtevano ime seje. The selected JSON file has an empty session name. Izbrana datoteka JSON ima prazno ime seje. The selected JSON file has invalid or incomplete SpeedCrunch session data. Izbrana datoteka JSON vsebuje neveljavne ali nepopolne podatke seje SpeedCrunch. Open Sessions Folder Odpri mapo sej Could not create the sessions folder: %1 Mape sej ni bilo mogoÄ�e ustvariti: %1 Could not open the sessions folder: %1 Mape sej ni bilo mogoÄ�e odpreti: %1 Editor and Results Font Pisava urejevalnika in rezultatov Open Session Odpri sejo Community Skupnost Rename Session Preimenuj sejo Clear Session PoÄ�isti sejo Delete Session IzbriÅ¡i sejo Close Pane Zapri podokno User Variables UporabniÅ¡ke spremenljivke User Units UporabniÅ¡ke enote Clear History PoÄ�isti zgodovino Are you sure you want to clear the calculation history? Ali res želite poÄ�istiti zgodovino izraÄ�unov? Session name: Ime seje: A session named %1 already exists. Seja z imenom %1 že obstaja. Could not create session file %1. Datoteke seje %1 ni bilo mogoÄ�e ustvariti. Could not write session file %1. V datoteko seje %1 ni bilo mogoÄ�e pisati. Are you sure you want to delete this session? Ali res želite izbrisati to sejo? Custom Precision NatanÄ�nost po meri Fractional digits: Decimalna mesta: Theme Tema Light Themes Svetle teme Dark Themes Temne teme Preview Predogled Colors Barve Select color for %1 Izberite barvo za %1 Import... Uvozi ... Export... Izvozi ... Import Theme Uvozi temo Theme file (*.json);;All files (*) Datoteka teme (*.json);;Vse datoteke (*) Invalid theme file. Neveljavna datoteka teme. Can't import theme "%1" because it conflicts with a built-in theme. Teme "%1" ni mogoÄ�e uvoziti, ker je v sporu z vgrajeno temo. Can't find a writable theme folder. Ni mogoÄ�e najti zapisljive mape za teme. Overwrite Theme Prepis teme A custom theme named "%1" already exists. Do you want to overwrite it? Tema po meri z imenom "%1" že obstaja. Ali jo želite prepisati? Can't overwrite theme file %1 Datoteke teme %1 ni mogoÄ�e prepisati Can't copy theme file to %1 Datoteke teme ni mogoÄ�e kopirati v %1 Export Theme Izvozi temo Can't export theme as "%1" because it conflicts with a built-in theme. Teme ni mogoÄ�e izvoziti kot "%1", ker je v sporu z vgrajeno temo. Can't write to file %1 Ni mogoÄ�e pisati v datoteko %1 Global User Variable Globalna uporabniska spremenljivka Global User Function Globalna uporabniska funkcija Global User Unit Globalna uporabniska enota User Definitions UporabniÅ¡ke definicije These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Te definicije so globalne in se naložijo v vsako sejo. V sejah jih ni mogoÄ�e spreminjati in imajo prednost pred istoimenskimi definicijami iz urejevalnika seje. Vnesite po eno definicijo na vrstico. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Primeri: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Uporabi Validate Preveri Test Results Rezultati preizkusa Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Uvožene spremenljivke: %1 Uvožene funkcije: %2 Uvožene enote: %3 Å tevilke vrstic z napakami: %4 none ni jih Apply Results Rezultati uveljavitve User definitions saved. UporabniÅ¡ke definicije so shranjene. History Size Limit Omejitev velikosti zgodovine Maximum number of history entries for this session (0 = unlimited): NajveÄ�je Å¡tevilo vnosov zgodovine za to sejo (0 = neomejeno): Text file (*.txt);;Any file (*.*) Besedilna datoteka (*.txt);;Katera koli datoteka (*.*) Could not recalculate from calculation %1: %2 Ni bilo mogoÄ�e znova izraÄ�unati od izraÄ�una %1: %2 History Size Limit Reached Dosežena omejitev velikosti zgodovine This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Ta izraÄ�un zapolni zadnje razpoložljivo mesto v zgodovini. Prihodnji izraÄ�uni bodo odstranili najstarejÅ¡i izraÄ�un iz zgodovine. Omejitev lahko poveÄ�ate v Seja > Omejitev velikosti zgodovine. Editing calculation. Press Esc twice to cancel. Urejanje izraÄ�una. Pritisnite Esc dvakrat za preklic. Calculation Settings Nastavitve izraÄ�una Invalid recalculation start index Neveljaven zaÄ�etni indeks ponovnega izraÄ�una System Default Privzeta sistemska Language Jezik Select the language: Izberite jezik: Custom Po meri Decimal places: Decimalna mesta: &Automatic &Samodejno &Precision &NatanÄ�nost Plain &text Navadno &besedilo Formula &Book Knjiga &formul &Export &Izvoz Export session as HTML Izvozi sejo v HTML HTML file (*.html) Datoteka HTML (*.html) Export session as plain text Izvozi sejo v besedilno datoteko ManualWindow SpeedCrunch Manual PriroÄ�nik SpeedCrunch %1 - SpeedCrunch Manual %1 - priroÄ�nik SpeedCrunch NumberFormatDialog Number Format Oblika Å¡tevila <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Izberite obliko Å¡tevil za rezultate in združevanje Å¡tevk pri vnosu.</b><br/><br/>Opomba: pri vnesenih Å¡tevilih so sprejete nedvoumne oblike, tudi Ä�e se razlikujejo od izbrane oblike prikaza.<br/> QObject Global User Variable Globalna uporabniska spremenljivka Global User Function Globalna uporabniska funkcija Global User Unit Globalna uporabniska enota Backspace Vracalka Clear expression PoÄ�isti izraz Evaluate expression Ovrednoti izraz Insert text Vstavi besedilo Automatic decimal Samodejno decimalno Fixed-point decimal Decimalno s fiksno vejico Engineering decimal Inženirsko decimalno Scientific decimal Znanstveno decimalno Rational Racionalno Binary DvojiÅ¡ko Octal OsmiÅ¡ko Hexadecimal Å estnajstiÅ¡ko Sexagesimal Å estdesetiÅ¡ko Update Available Na voljo je posodobitev A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Na voljo je novejÅ¡a razliÄ�ica (%1).<br/><a href="%2">ObiÅ¡Ä�ite spletno stran za prenos.</a> Check for Updates Preveri posodobitve SpeedCrunch %1 is up to date. SpeedCrunch %1 je posodobljen. No connectivity. Please check your internet connection and try again. Ni povezave. Preverite internetno povezavo in poskusite znova. Could not verify the latest available version. NajnovejÅ¡e razpoložljive razliÄ�ice ni bilo mogoÄ�e preveriti. ResultDisplay Scroll to bottom Pomakni na dno Edit Expression Uredi izraz Change Settings Spremeni nastavitve New Tab Nov zavihek &Import... &Uvozi... &Export &Izvoz Plain &text Navadno &besedilo Copy Kopiraj Selection Izbor Select All Izberi vse Expression Izraz Result Rezultat Calculation IzraÄ�un Calculation as Single Line IzraÄ�un v eni vrstici Remove Odstrani This Calculation Ta izraÄ�un All Calculations Above Vsi izraÄ�uni zgoraj All Calculations Below Vsi izraÄ�uni spodaj New Private Tab Nov zasebni zavihek Session Seja Open... Odpri... Clone... Kloniraj... Rename... Preimenuj... Keep Ohrani Make Private... Naredi zasebno... Clear PoÄ�isti Delete IzbriÅ¡i Close Zapri Split Razdeli Left Levo Right Desno Up Gor Down Dol Close Pane Zapri podokno Main Menu Glavni meni Cancel editing PrekliÄ�i urejanje Copy result Kopiraj rezultat Edit expression Uredi izraz Change settings Spremeni nastavitve Remove calculation Odstrani izraÄ�un ResultSlotsDialog Notation & Precision Zapis in natanÄ�nost Result Line Vrstica rezultata Enabled OmogoÄ�eno Notation Zapis Decimal Places Decimalna mesta Main Line Glavna vrstica Extra Line #1 Dodatna vrstica #1 Extra Line #2 Dodatna vrstica #2 Extra Line #3 Dodatna vrstica #3 Extra Line #4 Dodatna vrstica #4 Auto Samodejno UserFunctionListWidget Name Ime Value Vrednost Description Opis Search IÅ¡Ä�i No match found Ni najdenih ujemanj Insert Vstavi Edit Uredi Delete IzbriÅ¡i Delete All IzbriÅ¡i vse UserUnitListWidget Name Ime Value Vrednost Description Opis Search IÅ¡Ä�i No match found Ni najdenih ujemanj Insert Vstavi Edit Uredi Delete IzbriÅ¡i Delete All IzbriÅ¡i vse VariableListWidget Name Ime Value Vrednost Description Opis Search IÅ¡Ä�i No match found Ni najdenih ujemanj Insert Vstavi Edit Uredi Delete IzbriÅ¡i Delete All IzbriÅ¡i vse heldercorreia-speedcrunch-e7ca37f/src/resources/locale/sv.ts000066400000000000000000010503341526573132500244030ustar00rootroot00000000000000 AboutBox About SpeedCrunch Om SpeedCrunch Core developers Huvudutvecklare Original author Ursprunglig författare Close Stäng Math engine Matematikmotor Main author | Logo | Maintainer Huvudförfattare | Logotyp | UnderhÃ¥llare Thanks Tack Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 SpeedCrunch-utvecklarna This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Detta program är fri mjukvara; du fÃ¥r sprida det vidare och/eller ändra det enligt reglerna i GNU General Public License som publicerat av Free Software Foundation; antingen version 2 av licensen, eller (om du sÃ¥ önskar) valfri senare version This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Detta program distribueras i hopp om att det skall vara användbart, men UTAN NÃ…GON FORM AV GARANTI; utan ens en underförstÃ¥dd garanti vid KÖP eller LÄMPLIGHET FÖR NÃ…GOT SÄRSKILT SYFTE. Detaljer Ã¥terfinns i GNU General Public License. BitFieldWidget Reset bits to zero Ã…terställ bitar till noll Invert bits Invertera bitar Shift bits left Skifta bitar Ã¥t vänster Shift bits right Skifta bitar Ã¥t höger Book Index Index Algebra Algebra Quadratic Equation Andragradsekvation Logarithmic Base Conversion Logaritmisk baskonvertering Geometry Geometri Circle Cirkel Sector Sektor Sphere Sfär Cube Kub Cone Kon Cylinder Cylinder Electronics Elektronik Ohm's Law Ohms lag Power Effekt Reactance Reaktans Resonance Resonans Radio Frequency Radiofrekvens Antennas Antenner Characteristic Impedance (coax) Karakteristisk impedans (koax) Velocity of Propagation (coax) Utbredningshastighet (koax) Standing Wave Ratio & Return Loss StÃ¥endevÃ¥gsförhÃ¥llande (SWR) och returförlust Free Space Wavelength FrirymdsvÃ¥glängd resistance resistans voltage spänning current ström power effekt inductive reactance induktiv reaktans capacitive reactance kapacitiv reaktans inductance induktans capacitance kapacitans frequency frekvens resonance frequency resonansfrekvens area yta perimeter omkrets diameter diameter radius radie volume volym surface area mantelyta height höjd slant height mantelhöjd face diagonal sidodiagonal space diagonal rymddiagonal edge length kantlängd arc length bÃ¥glängd central angle (degrees) mittpunktsvinkel (i grader) input power ingÃ¥ende effekt reflected power reflekterad effekt transmitted power överförd effekt return loss returförlust dielectric constant dielektrisk konstant outer conductor's inner diameter ytterledarens innerdiameter inner conductor's outer diameter innerledarens ytterdiameter speed of light ljushastigheten reflection coefficient reflektionskoefficient standing wave ratio stÃ¥endevÃ¥gförhÃ¥llande normalized impedance normaliserad impedans frequency (Hz) frekvens (Hz) BookDock Formula Book Formelsamling ConstantCompletion Search constants Sök konstanter No match found Ingen träff Constants Mathematics Matematik Physics (CODATA 2022) Fysik (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kemi (IUPAC - CIAAW 2021) Uncategorized Okategoriserat Universal Universella Physicochemical Fysikalisk-kemiska Atomic & Nuclear — General Atom- och kärnfysik - allmänt Atomic & Nuclear — Electroweak Atom- och kärnfysik - elektrosvag Atomic & Nuclear — Electron Atom- och kärnfysik - elektron Atomic & Nuclear — Muon Atom- och kärnfysik - myon Atomic & Nuclear — Tau Atom- och kärnfysik - tau Atomic & Nuclear — Proton Atom- och kärnfysik - proton Atomic & Nuclear — Neutron Atom- och kärnfysik - neutron Atomic & Nuclear — Deuteron Atom- och kärnfysik - deuteron Atomic & Nuclear — Triton Atom- och kärnfysik - triton Atomic & Nuclear — Helion Atom- och kärnfysik - helion Atomic & Nuclear — Alpha particle Atom- och kärnfysik - alfapartikel Atomic & Nuclear — Atomic units Atom- och kärnfysik - atomenheter Atomic & Nuclear — Energy conversion relationships Atom- och kärnfysik - energiomvandlingssamband Atomic & Nuclear — X-ray units Atom- och kärnfysik - röntgenenheter Atomic & Nuclear — Magnetic shielding corrections Atom- och kärnfysik - magnetiska skärmningskorrektioner Masses Massor Lifetimes Livstider Molar Masses Molmassor Electronegativity Elektronegativitet Ionization Energy Joniseringsenergi Nominal Constants (IAU 2015) Nominella konstanter (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Aktuella bästa uppskattningar (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) vakuums karakteristiska impedans (Zâ‚€) reduced Planck constant (â„�) reducerad Plancks konstant (â„�) vacuum electric permittivity (ϵ₀) vakuums elektriska permittivitet (ϵ₀) Newtonian constant of gravitation (G) Newtons gravitationskonstant (G) vacuum magnetic permeability (μ₀) vakuums magnetiska permeabilitet (μ₀) Planck constant (h) Plancks konstant (h) speed of light in vacuum (c) ljusets hastighet i vakuum (c) standard acceleration of gravity (gâ‚™) standardtyngdacceleration (gâ‚™) Newtonian constant of gravitation over h-bar c Newtons gravitationskonstant över h-streck c Planck length Plancklängd Planck constant in eV/Hz (h) Plancks konstant i eV/Hz (h) Planck mass Planckmassa Planck mass energy equivalent in GeV Planckmassans energiekvivalent i GeV Planck temperature Plancktemperatur Planck time Plancktid reduced Planck constant in eV·s (â„�) reducerad Plancks konstant i eV·s (â„�) reduced Planck constant times c in MeV·fm reducerad Plancks konstant gÃ¥nger c i MeV·fm Bohr magneton Bohrmagneton conductance quantum (Gâ‚€) konduktanskvantum (Gâ‚€) Coulomb constant (kâ‚‘) Coulombs konstant (kâ‚‘) elementary charge (e) elementarladdning (e) elementary charge over h-bar elementarladdning över h-streck conventional value of Josephson constant konventionellt värde för Josephsons konstant Josephson constant Josephsons konstant conventional value of ampere-90 konventionellt värde för ampere-90 conventional value of coulomb-90 konventionellt värde för coulomb-90 conventional value of farad-90 konventionellt värde för farad-90 conventional value of henry-90 konventionellt värde för henry-90 conventional value of ohm-90 konventionellt värde för ohm-90 conventional value of volt-90 konventionellt värde för volt-90 conventional value of watt-90 konventionellt värde för watt-90 magnetic flux quantum (Φ₀) magnetiskt flödeskvantum (Φ₀) nuclear magneton kärnmagneton inverse of conductance quantum inversen av konduktanskvantum conventional value of von Klitzing constant konventionellt värde för von Klitzings konstant von Klitzing constant von Klitzings konstant atomic unit of magnetic dipole moment atomenhet för magnetiskt dipolmoment atomic unit of magnetic flux density atomenhet för magnetisk flödestäthet Bohr magneton in eV/T Bohrmagneton i eV/T Bohr magneton in Hz/T Bohrmagneton i Hz/T Bohr magneton in inverse meter per tesla Bohrmagneton i invers meter per tesla Bohr magneton in K/T Bohrmagneton i K/T nuclear magneton in eV/T kärnmagneton i eV/T nuclear magneton in inverse meter per tesla kärnmagneton i invers meter per tesla nuclear magneton in K/T kärnmagneton i K/T nuclear magneton in MHz/T kärnmagneton i MHz/T Bohr radius (aâ‚€) Bohrradie (aâ‚€) fine-structure constant (α) finstrukturkonstant (α) Hartree energy (Eâ‚•) Hartreeenergi (Eâ‚•) Hartree energy in eV Hartreeenergi i eV quantum of circulation cirkulationskvantum quantum of circulation times 2 cirkulationskvantum gÃ¥nger 2 Rydberg constant (R∞) Rydbergs konstant (R∞) atomic mass unit-hartree relationship samband mellan atommassenhet och hartree atomic mass unit-hertz relationship samband mellan atommassenhet och hertz atomic mass unit-inverse meter relationship samband mellan atommassenhet och invers meter atomic mass unit-joule relationship samband mellan atommassenhet och joule atomic mass unit-kelvin relationship samband mellan atommassenhet och kelvin atomic mass unit-kilogram relationship samband mellan atommassenhet och kilogram atomic unit of 1st hyperpolarizability atomenhet för första hyperpolariserbarhet atomic unit of 2nd hyperpolarizability atomenhet för andra hyperpolariserbarhet atomic unit of charge (e) atomenhet för laddning (e) atomic unit of charge density atomenhet för laddningstäthet atomic unit of current atomenhet för ström atomic unit of electric dipole moment atomenhet för elektriskt dipolmoment atomic unit of electric field atomenhet för elektriskt fält atomic unit of electric field gradient atomenhet för elektrisk fältgradient atomic unit of electric polarizability atomenhet för elektrisk polariserbarhet atomic unit of electric potential atomenhet för elektrisk potential atomic unit of electric quadrupole moment atomenhet för elektriskt kvadrupolmoment atomic unit of action atomenhet för verkan atomic unit of energy atomenhet för energi atomic unit of force atomenhet för kraft atomic unit of length atomenhet för längd hertz-atomic mass unit relationship samband mellan hertz och atommassenhet hertz-electron volt relationship samband mellan hertz och elektronvolt hertz-hartree relationship samband mellan hertz och hartree hertz-inverse meter relationship samband mellan hertz och invers meter hertz-joule relationship samband mellan hertz och joule hertz-kelvin relationship samband mellan hertz och kelvin hertz-kilogram relationship samband mellan hertz och kilogram hyperfine transition frequency of Cs-133 hyperfin övergÃ¥ngsfrekvens för Cs-133 inverse fine-structure constant (αâ�»Â¹) inverse finstrukturkonstant (αâ�»Â¹) inverse meter-atomic mass unit relationship samband mellan invers meter och atommassenhet inverse meter-electron volt relationship samband mellan invers meter och elektronvolt inverse meter-hartree relationship samband mellan invers meter och hartree inverse meter-hertz relationship samband mellan invers meter och hertz inverse meter-joule relationship samband mellan invers meter och joule inverse meter-kelvin relationship samband mellan invers meter och kelvin inverse meter-kilogram relationship samband mellan invers meter och kilogram joule-atomic mass unit relationship samband mellan joule och atommassenhet joule-electron volt relationship samband mellan joule och elektronvolt joule-hertz relationship samband mellan joule och hertz joule-hartree relationship samband mellan joule och hartree joule-inverse meter relationship samband mellan joule och invers meter joule-kelvin relationship samband mellan joule och kelvin joule-kilogram relationship samband mellan joule och kilogram kelvin-atomic mass unit relationship samband mellan kelvin och atommassenhet kelvin-electron volt relationship samband mellan kelvin och elektronvolt kelvin-hertz relationship samband mellan kelvin och hertz kelvin-hartree relationship samband mellan kelvin och hartree kelvin-inverse meter relationship samband mellan kelvin och invers meter kelvin-joule relationship samband mellan kelvin och joule kelvin-kilogram relationship samband mellan kelvin och kilogram kilogram-atomic mass unit relationship samband mellan kilogram och atommassenhet kilogram-electron volt relationship samband mellan kilogram och elektronvolt kilogram-hertz relationship samband mellan kilogram och hertz kilogram-hartree relationship samband mellan kilogram och hartree kilogram-inverse meter relationship samband mellan kilogram och invers meter kilogram-joule relationship samband mellan kilogram och joule kilogram-kelvin relationship samband mellan kilogram och kelvin lattice parameter of silicon (a) gitterparameter för kisel (a) luminous efficacy ljusutbyte natural unit of energy naturlig enhet för energi natural unit of energy in MeV naturlig enhet för energi i MeV natural unit of action (â„�) naturlig enhet för verkan (â„�) natural unit of action in eV·s naturlig enhet för verkan i eV·s natural unit of length naturlig enhet för längd natural unit of mass natural unit ofmassa natural unit of momentum naturlig enhet för rörelsemängd natural unit of momentum in MeV/c naturlig enhet för rörelsemängd i MeV/c natural unit of time naturlig enhet för tid natural unit of velocity naturlig enhet för hastighet Rydberg constant times c in Hz Rydbergs konstant gÃ¥nger c i Hz Rydberg constant times hc in eV Rydbergs konstant gÃ¥nger hc i eV Rydberg constant times hc in J Rydbergs konstant gÃ¥nger hc i J Fermi coupling constant Fermis kopplingskonstant weak mixing angle svag blandningsvinkel W to Z mass ratio massförhÃ¥llande mellan W och Z Thomson cross section (σₑ) Thomsons tvärsnitt (σₑ) electron mass (mâ‚‘) elektronmassa (mâ‚‘) electron mass in u elektronmassa i u electron mass energy equivalent (mₑ·c²) massenergiekvivalent för elektron (mₑ·c²) electron mass energy equivalent in MeV massenergiekvivalent för elektron i MeV reduced Compton wavelength ComptonvÃ¥glängd för reduced classical electron radius (râ‚‘) klassisk elektronradie (râ‚‘) electron charge to mass quotient laddning-massa-kvot för elektron electron-deuteron magnetic moment ratio förhÃ¥llande mellan magnetiska moment för elektron och deuteron electron-deuteron mass ratio massförhÃ¥llande elektron-deuteron electron g factor (gâ‚‘) elektronens g-faktor (gâ‚‘) electron gyromagnetic ratio (γₑ) elektronens gyromagnetiska förhÃ¥llande (γₑ) electron gyromagnetic ratio in MHz/T elektronens gyromagnetiska förhÃ¥llande i MHz/T electron-helion mass ratio massförhÃ¥llande elektron-helion electron magnetic moment (μₑ) elektronens magnetiska moment (μₑ) electron magnetic moment anomaly (aâ‚‘) anomali hos elektronens magnetiska moment (aâ‚‘) electron magnetic moment to Bohr magneton ratio förhÃ¥llande mellan elektronens magnetiska moment och Bohrmagnetonen electron magnetic moment to nuclear magneton ratio förhÃ¥llande mellan elektronens magnetiska moment och kärnmagnetonen electron molar mass (Mâ‚‘) electron molarmassa (Mâ‚‘) electron-muon magnetic moment ratio förhÃ¥llande mellan magnetiska moment för elektron och myon electron-muon mass ratio massförhÃ¥llande elektron-myon electron-neutron magnetic moment ratio förhÃ¥llande mellan magnetiska moment för elektron och neutron electron-neutron mass ratio massförhÃ¥llande elektron-neutron electron-proton magnetic moment ratio förhÃ¥llande mellan magnetiska moment för elektron och proton electron-proton mass ratio massförhÃ¥llande elektron-proton electron relative atomic mass (Ar(e)) relativ atommassa för elektron (Ar(e)) electron-tau mass ratio massförhÃ¥llande elektron-tau electron to alpha particle mass ratio massförhÃ¥llande mellan elektron och alfapartikel electron to shielded helion magnetic moment ratio förhÃ¥llande mellan elektronens och skärmade helionens magnetiska moment electron to shielded proton magnetic moment ratio förhÃ¥llande mellan elektronens och skärmade protonens magnetiska moment electron-triton mass ratio massförhÃ¥llande elektron-triton electron volt-atomic mass unit relationship samband mellan elektronvolt och atommassenhet electron volt-hartree relationship samband mellan elektronvolt och hartree electron volt-hertz relationship samband mellan elektronvolt och hertz electron volt-inverse meter relationship samband mellan elektronvolt och invers meter electron volt-joule relationship samband mellan elektronvolt och joule electron volt-kelvin relationship samband mellan elektronvolt och kelvin electron volt-kilogram relationship samband mellan elektronvolt och kilogram hartree-atomic mass unit relationship samband mellan hartree och atommassenhet hartree-electron volt relationship samband mellan hartree och elektronvolt muon Compton wavelength ComptonvÃ¥glängd för myon muon-electron mass ratio massförhÃ¥llande myon-elektron muon g factor myonens g-faktor muon magnetic moment myonens magnetiska moment muon magnetic moment anomaly anomali hos myonens magnetiska moment muon magnetic moment to Bohr magneton ratio förhÃ¥llande mellan myonens magnetiska moment och Bohrmagnetonen muon magnetic moment to nuclear magneton ratio förhÃ¥llande mellan myonens magnetiska moment och kärnmagnetonen muon mass myonmassa muon mass energy equivalent massenergiekvivalent för myon muon mass energy equivalent in MeV massenergiekvivalent för myon i MeV muon mass in u myonmassa i u muon molar mass muon molarmassa muon-neutron mass ratio massförhÃ¥llande myon-neutron muon-proton magnetic moment ratio förhÃ¥llande mellan magnetiska moment för myon och proton muon-proton mass ratio massförhÃ¥llande myon-proton muon-tau mass ratio massförhÃ¥llande myon-tau reduced muon Compton wavelength reducerad ComptonvÃ¥glängd för myon reduced tau Compton wavelength reducerad ComptonvÃ¥glängd för tau tau Compton wavelength ComptonvÃ¥glängd för tau tau-electron mass ratio massförhÃ¥llande tau-elektron tau mass taumassa tau mass energy equivalent massenergiekvivalent för tau tau mass in u taumassa i u tau molar mass tau molarmassa tau-muon mass ratio massförhÃ¥llande tau-myon tau-neutron mass ratio massförhÃ¥llande tau-neutron tau-proton mass ratio massförhÃ¥llande tau-proton proton charge to mass quotient laddning-massa-kvot för proton proton Compton wavelength ComptonvÃ¥glängd för proton proton-electron mass ratio massförhÃ¥llande proton-elektron proton g factor (gₚ) protonens g-faktor (gₚ) proton gyromagnetic ratio (γₚ) protonens gyromagnetiska förhÃ¥llande (γₚ) proton gyromagnetic ratio in MHz/T protonens gyromagnetiska förhÃ¥llande i MHz/T proton magnetic moment (μₚ) protonens magnetiska moment (μₚ) proton magnetic moment to Bohr magneton ratio förhÃ¥llande mellan protonens magnetiska moment och Bohrmagnetonen proton magnetic moment to nuclear magneton ratio förhÃ¥llande mellan protonens magnetiska moment och kärnmagnetonen proton magnetic shielding correction magnetisk skärmningskorrektion för proton proton mass (mₚ) protonmassa (mₚ) proton mass energy equivalent massenergiekvivalent för proton proton mass energy equivalent in MeV massenergiekvivalent för proton i MeV proton mass in u protonmassa i u proton molar mass (Mₚ) proton molarmassa (Mₚ) proton-muon mass ratio massförhÃ¥llande proton-myon proton-neutron magnetic moment ratio förhÃ¥llande mellan magnetiska moment för proton och neutron proton-neutron mass ratio massförhÃ¥llande proton-neutron proton relative atomic mass (Ar(p)) relativ atommassa för proton (Ar(p)) proton rms charge radius rms-laddningsradie för proton proton-tau mass ratio massförhÃ¥llande proton-tau reduced proton Compton wavelength reducerad ComptonvÃ¥glängd för proton shielded proton gyromagnetic ratio skärmad protonens gyromagnetiska förhÃ¥llande shielded proton gyromagnetic ratio in MHz/T skärmad protonens gyromagnetiska förhÃ¥llande i MHz/T shielded proton magnetic moment skärmad protonens magnetiska moment shielded proton magnetic moment to Bohr magneton ratio förhÃ¥llande mellan skärmad protonens magnetiska moment och Bohrmagnetonen shielded proton magnetic moment to nuclear magneton ratio förhÃ¥llande mellan skärmad protonens magnetiska moment och kärnmagnetonen neutron Compton wavelength ComptonvÃ¥glängd för neutron neutron-electron magnetic moment ratio förhÃ¥llande mellan magnetiska moment för neutron och elektron neutron-electron mass ratio massförhÃ¥llande neutron-elektron neutron g factor (gâ‚™) neutronens g-faktor (gâ‚™) neutron gyromagnetic ratio (γₙ) neutronens gyromagnetiska förhÃ¥llande (γₙ) neutron gyromagnetic ratio in MHz/T neutronens gyromagnetiska förhÃ¥llande i MHz/T neutron magnetic moment (μₙ) neutronens magnetiska moment (μₙ) neutron magnetic moment to Bohr magneton ratio förhÃ¥llande mellan neutronens magnetiska moment och Bohrmagnetonen neutron magnetic moment to nuclear magneton ratio förhÃ¥llande mellan neutronens magnetiska moment och kärnmagnetonen neutron mass (mâ‚™) neutronmassa (mâ‚™) neutron mass energy equivalent massenergiekvivalent för neutron neutron mass energy equivalent in MeV massenergiekvivalent för neutron i MeV neutron mass in u neutronmassa i u neutron molar mass (Mâ‚™) neutron molarmassa (Mâ‚™) neutron-muon mass ratio massförhÃ¥llande neutron-myon neutron-proton magnetic moment ratio förhÃ¥llande mellan magnetiska moment för neutron och proton neutron-proton mass difference masskillnad mellan neutron och proton neutron-proton mass difference energy equivalent massenergiekvivalent för masskillnad mellan neutron och proton neutron-proton mass difference energy equivalent in MeV massenergiekvivalent för masskillnad mellan neutron och proton i MeV neutron-proton mass difference in u masskillnad mellan neutron och proton i u neutron-proton mass ratio massförhÃ¥llande neutron-proton neutron relative atomic mass (Ar(n)) relativ atommassa för neutron (Ar(n)) neutron-tau mass ratio massförhÃ¥llande neutron-tau neutron to shielded proton magnetic moment ratio neutron till skärmad proton magnetiskt moment förhÃ¥llande reduced neutron Compton wavelength reducerad ComptonvÃ¥glängd för neutron deuteron-electron magnetic moment ratio förhÃ¥llande mellan magnetiska moment för deuteron och elektron deuteron-electron mass ratio massförhÃ¥llande deuteron-elektron deuteron g factor deuteronens g-faktor deuteron magnetic moment deuteronens magnetiska moment deuteron magnetic moment to Bohr magneton ratio förhÃ¥llande mellan deuteronens magnetiska moment och Bohrmagnetonen deuteron magnetic moment to nuclear magneton ratio förhÃ¥llande mellan deuteronens magnetiska moment och kärnmagnetonen deuteron mass deuteronmassa deuteron mass energy equivalent massenergiekvivalent för deuteron deuteron mass energy equivalent in MeV massenergiekvivalent för deuteron i MeV deuteron mass in u deuteronmassa i u deuteron molar mass deuteron molarmassa deuteron-neutron magnetic moment ratio förhÃ¥llande mellan magnetiska moment för deuteron och neutron deuteron-proton magnetic moment ratio förhÃ¥llande mellan magnetiska moment för deuteron och proton deuteron-proton mass ratio massförhÃ¥llande deuteron-proton deuteron relative atomic mass (Ar(d)) relativ atommassa för deuteron (Ar(d)) deuteron rms charge radius rms-laddningsradie för deuteron triton-electron mass ratio massförhÃ¥llande triton-elektron triton g factor (gₜ) tritonens g-faktor (gₜ) triton magnetic moment (μₜ) tritonens magnetiska moment (μₜ) triton magnetic moment to Bohr magneton ratio förhÃ¥llande mellan tritonens magnetiska moment och Bohrmagnetonen triton magnetic moment to nuclear magneton ratio förhÃ¥llande mellan tritonens magnetiska moment och kärnmagnetonen triton mass (mₜ) tritonmassa (mₜ) triton mass energy equivalent massenergiekvivalent för triton triton mass energy equivalent in MeV massenergiekvivalent för triton i MeV triton mass in u tritonmassa i u triton molar mass (Mₜ) triton molarmassa (Mₜ) triton-proton mass ratio massförhÃ¥llande triton-proton triton relative atomic mass (Ar(t)) relativ atommassa för triton (Ar(t)) triton to proton magnetic moment ratio förhÃ¥llande mellan tritonens och protonens magnetiska moment helion-electron mass ratio massförhÃ¥llande helion-elektron helion g factor (gâ‚•) helionens g-faktor (gâ‚•) helion magnetic moment (μₕ) helionens magnetiska moment (μₕ) helion magnetic moment to Bohr magneton ratio förhÃ¥llande mellan helionens magnetiska moment och Bohrmagnetonen helion magnetic moment to nuclear magneton ratio förhÃ¥llande mellan helionens magnetiska moment och kärnmagnetonen helion mass (mâ‚•) helionmassa (mâ‚•) helion mass energy equivalent massenergiekvivalent för helion helion mass energy equivalent in MeV massenergiekvivalent för helion i MeV helion mass in u helionmassa i u helion molar mass (Mâ‚•) helion molarmassa (Mâ‚•) helion-proton mass ratio massförhÃ¥llande helion-proton helion relative atomic mass (Ar(h)) relativ atommassa för helion (Ar(h)) helion shielding shift helionens skärmningsförskjutning shielded helion gyromagnetic ratio skärmad helionens gyromagnetiska förhÃ¥llande shielded helion gyromagnetic ratio in MHz/T skärmad helionens gyromagnetiska förhÃ¥llande i MHz/T shielded helion magnetic moment skärmad helionens magnetiska moment shielded helion magnetic moment to Bohr magneton ratio förhÃ¥llande mellan skärmad helionens magnetiska moment och Bohrmagnetonen shielded helion magnetic moment to nuclear magneton ratio förhÃ¥llande mellan skärmad helionens magnetiska moment och kärnmagnetonen shielded helion to proton magnetic moment ratio förhÃ¥llande mellan skärmade helionens och protonens magnetiska moment shielded helion to shielded proton magnetic moment ratio förhÃ¥llande mellan skärmade helionens och skärmade protonens magnetiska moment alpha particle mass alfapartikelmassa alpha particle mass in u alfapartikelmassa i u alpha particle mass energy equivalent massenergiekvivalent för alfapartikel alpha particle mass energy equivalent in MeV massenergiekvivalent för alfapartikel i MeV alpha particle-electron mass ratio massförhÃ¥llande alfapartikel-elektron alpha particle-proton mass ratio massförhÃ¥llande alfapartikel-proton alpha particle rms charge radius rms-laddningsradie för alfapartikel alpha particle molar mass alpha particle molarmassa alpha particle relative atomic mass (Ar(α)) relativ atommassa för alfapartikel (Ar(α)) atomic mass constant (mᵤ) atomic massa konstant (mᵤ) Avogadro constant Avogadros konstant Boltzmann constant (k) Boltzmanns konstant (k) Boltzmann constant in eV/K Boltzmanns konstant i eV/K Boltzmann constant in Hz/K Boltzmanns konstant i Hz/K Boltzmann constant in inverse meter per kelvin Boltzmanns konstant i invers meter per kelvin electron volt (eV) elektronvolt (eV) Faraday constant (F) Faradays konstant (F) first radiation constant (câ‚�) första strÃ¥lningskonstanten (câ‚�) first radiation constant for spectral radiance första strÃ¥lningskonstanten för spektral radians molar gas constant (R) molär gaskonstant (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Loschmidts konstant (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Loschmidts konstant (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molär Planckkonstant second radiation constant (câ‚‚) andra strÃ¥lningskonstanten (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Boltzmanns konstant (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) gitteravstÃ¥nd för idealt Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atomic massa konstant energi equivalent atomic mass constant energy equivalent in MeV atomic massa konstant energi equivalent i MeV atomic mass unit-electron volt relationship samband mellan atommassenhet och elektronvolt molar mass constant (Mᵤ) molmasskonstant (Mᵤ) molar mass of carbon-12 molmassa för kol-12 molar volume of ideal gas (273.15 K, 100 kPa) molvolym för ideal gas (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) molvolym för ideal gas (273.15 K, 101.325 kPa) molar volume of silicon molvolym för kisel Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrodes konstant (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrodes konstant (1 K, 101.325 kPa) Wien frequency displacement law constant Wiens frekvensförskjutningskonstant Wien wavelength displacement law constant Wiens vÃ¥glängdsförskjutningskonstant standard atmosphere (atm) standardatmosfär (atm) standard-state pressure (p°) standardtillstÃ¥ndstryck (p°) Angstrom star (Ã…*) Ã¥ngströmstjärna (Ã…*) Copper x unit koppar-x-enhet Molybdenum x unit molybden-x-enhet atomic unit of magnetizability atomenhet för magnetiserbarhet atomic unit of mass (mâ‚‘) atomenhet för massa (mâ‚‘) atomic unit of momentum atomenhet för rörelsemängd atomic unit of permittivity atomenhet för permittivitet atomic unit of time atomenhet för tid atomic unit of velocity atomenhet för hastighet hartree-hertz relationship samband mellan hartree och hertz hartree-inverse meter relationship samband mellan hartree och invers meter hartree-joule relationship samband mellan hartree och joule hartree-kelvin relationship samband mellan hartree och kelvin hartree-kilogram relationship samband mellan hartree och kilogram shielding difference of d and p in HD skärmningsskillnad mellan d och p i HD shielding difference of t and p in HT skärmningsskillnad mellan t och p i HT pi (Ï€) pi (Ï€) Euler's number (e) Eulers tal (e) golden ratio (φ) gyllene snittet (φ) Euler-Mascheroni constant (γ) Euler-Mascheronis konstant (γ) nominal solar radius nominell solradie nominal solar total irradiance nominell total solirradians nominal solar luminosity nominell solluminositet nominal solar effective temperature nominell effektiv soltemperatur nominal solar mass parameter nominell solmassparameter nominal terrestrial equatorial radius nominell ekvatoriell jordradie nominal terrestrial polar radius nominell polär jordradie nominal terrestrial mass parameter nominell jordmassparameter nominal jovian equatorial radius nominell ekvatoriell Jupiterradie nominal jovian polar radius nominell polär Jupiterradie nominal jovian mass parameter nominell Jupitermassparameter average value of one minus the rate of TCG relative to TCB medelvärde av ett minus hastigheten för TCG relativt TCB solar mass parameter (TCB-compatible) solmassparameter (TCB-kompatibel) solar mass parameter (TDB-compatible) solmassparameter (TDB-kompatibel) equatorial radius of the Earth (TT-compatible) jordens ekvatoriella radie (TT-kompatibel) dynamical form factor of the Earth jordens dynamiska formfaktor time rate of change in the dynamical form factor of the Earth tidsderivata för jordens dynamiska formfaktor geocentric gravitational constant (TCB-compatible) geocentrisk gravitationskonstant (TCB-kompatibel) geocentric gravitational constant (TT-compatible) geocentrisk gravitationskonstant (TT-kompatibel) geocentric gravitational constant (TDB-compatible) geocentrisk gravitationskonstant (TDB-kompatibel) potential of the geoid geoidens potential nominal mean angular velocity of the Earth (TT-compatible) jordens nominella medelvinkelhastighet (TT-kompatibel) ratio mass of the Moon to the Earth massförhÃ¥llande mellan mÃ¥nen och jorden ratio of the mass of the Sun to Mercury massförhÃ¥llande mellan solen och Merkurius ratio of the mass of the Sun to Venus massförhÃ¥llande mellan solen och Venus ratio of the mass of the Sun to Mars massförhÃ¥llande mellan solen och Mars ratio of the mass of the Sun to Jupiter massförhÃ¥llande mellan solen och Jupiter ratio of the mass of the Sun to Saturn massförhÃ¥llande mellan solen och Saturnus ratio of the mass of the Sun to Uranus massförhÃ¥llande mellan solen och Uranus ratio of the mass of the Sun to Neptune massförhÃ¥llande mellan solen och Neptunus ratio of the mass of the Sun to (134340) Pluto massförhÃ¥llande mellan solen och (134340) Pluto ratio of the mass of the Sun to (136199) Eris massförhÃ¥llande mellan solen och (136199) Eris ratio of the mass of (1) Ceres to the Sun massförhÃ¥llande mellan (1) Ceres och solen ratio of the mass of (2) Pallas to the Sun massförhÃ¥llande mellan (2) Pallas och solen ratio of the mass of (4) Vesta to the Sun massförhÃ¥llande mellan (4) Vesta och solen mean obliquity of the ecliptic at J2000.0 ekliptikans medellutning vid J2000.0 Electromagnetic Elektromagnetiska Compton wavelength ComptonvÃ¥glängd Astronomy Astronomi ConstantsWidget Domain Domän Subdomain Underdomän No match found Ingen träff Name Namn Value Värde Unit Enhet Search Sök All Alla CustomKeypadDialog Custom Keypad Anpassad knappsats Rows: Rader: Columns: Kolumner: Copy preset: Kopiera förval: Basic Grundläggande Scientific (wide) Vetenskaplig (bred) Scientific (narrow) Vetenskaplig (smal) Apply Tillämpa Row Rad Column Kolumn Label Etikett Behavior Beteende Text Text DiagnosticsDialog App Diagnostics Programdiagnostik Copy to Clipboard Kopiera till urklipp Editor Unit Enhet User unit Användarenhet User function Användarfunktion Argument Argument Current result:<br/>%1 Aktuellt resultat:<br/>%1 Selection result:<br/>%1 Markeringsresultat:<br/>%1 Selection result: n/a Markeringsresultat: ej tillgängligt Selection result: %1 Markeringsresultat: %1 second sekund metre meter kilogram kilogram mole mol radian radian steradian steradian degree Celsius grad Celsius cubic metre kubikmeter cubic millimetre kubikmillimeter cubic centimetre kubikcentimeter cubic decimetre kubikdecimeter cubic kilometre kubikkilometer square millimetre kvadratmillimeter square kilometre kvadratkilometer square metre kvadratmeter minute minut hour timme day dag astronomical unit astronomisk enhet degree grad arcminute bÃ¥gminut arcsecond bÃ¥gsekund milliarcsecond millibÃ¥gsekund microarcsecond mikrobÃ¥gsekund hectare hektar litre liter tonne ton Dalton dalton electronvolt elektronvolt Angstrom Ã¥ngström atmosphere atmosfär atomic mass unit atommassenhet British thermal unit brittisk värmeenhet calorie kalori carat carat cup kopp cup (Imperial) kopp (imperial) cup (Japanese) kopp (japansk) cup (US) kopp (US) degree Fahrenheit grad Fahrenheit fathom famn fluid ounce (Imperial) vätskeunce (imperial) fluid ounce (US) vätskeunce (US) fluid dram (Imperial) vätskedram (imperial) fluid dram (US) vätskedram (US) foot fot square foot kvadratfot cubic foot kubikfot gallon (Imperial) gallon (imperial) gallon (US) gallon (US) gill (Imperial) gill (imperial) gill (US) gill (US) gradian gradian grain grain gram gram Hartley hartley Hartree energy unit Hartree-energienhet horsepower hästkraft inch tum square inch kvadrattum cubic inch kubiktum karat karat knot knop lightminute ljusminut lightsecond ljussekund lightyear ljusÃ¥r long ton brittiskt ton mile engelsk mil square mile kvadratengelsk mil cubic mile kubikengelsk mil mile per hour engelska mil per timme kilometre per hour kilometer per timme nautical mile nautisk mil ounce uns parsec parsec pint (Imperial) pint (imperial) pint (US) pint (US) pound pund pounds per square inch pund per kvadrattum quart (Imperial) quart (imperial) quart (US) quart (US) oil barrel oljefat beer barrel (US) ölfat (US) square yard kvadratyard cubic yard kubikyard short ton amerikanskt ton tablespoon matsked tablespoon (Australian) matsked (australisk) tablespoon (Imperial) matsked (imperial) tablespoon (US) matsked (US) dessert spoon dessertsked teaspoon tesked teaspoon (Imperial) tesked (imperial) teaspoon (US) tesked (US) turn varv revolution varv revolution per minute varv per minut week vecka kilowatt hour kilowattimme millimetre of mercury millimeter kvicksilver yard yard Julian century julianskt Ã¥rhundrade Julian year julianskt Ã¥r sidereal year sideriskt Ã¥r tropical year tropiskt Ã¥r Evaluator invalid expression ogiltigt uttryck division by zero division med noll too time consuming - computation was rejected för tidskrävande - beräkningen avvisades dimension mismatch - quantities with different dimensions cannot be compared, added, etc. dimensionsfel - storheter med olika dimensioner kan inte jämföras, adderas osv. invalid dimension - operation might require dimensionless arguments ogiltig dimension - operationen kan behöva dimensionslösa argument Computation aborted - encountered numerical instability Beräkningen avbröts - numerisk instabilitet uppstod invalid dimension - function might require dimensionless arguments ogiltig dimension - funktionen kan behöva dimensionslösa argument error fel unit must not be zero enhet kan inte vara noll Conversion failed - dimension mismatch Konverteringen misslyckades - dimensionsfel unknown function or variable okänd funktion eller variabel recursion not supported rekursion stöds ej cannot operate on a NaN kan inte räkna med NaN (ogiltigt värde) underflow - tiny result is out of SpeedCrunch's number range för litet värde - SpeedCrunch kan inte representera värdet overflow - huge result is out of SpeedCrunch's number range för stort värde - SpeedCrunch kan inte representera värdet overflow - logic result exceeds maximum of 256 bits för stort värde - det logiska resultatet innehÃ¥ller mer än 256 bitar overflow - integer result exceeds maximum limit for integers för stort värde - heltalsresultatet överskrider gränsen för heltal operation is not defined for these arguments operationen är inte definierad för dessa argument wrong number of arguments fel antal argument does not take NaN as an argument tar ej NaN som ett argument result out of range resultat utanför omrÃ¥det undefined for argument domain odefinierat för argumentets domän computation too expensive beräkningen är för resurskrävande internal error, please report a bug internt fel, vänligen rapportera felet syntax error syntaxfel conversion target must be a unit konverteringsmÃ¥let mÃ¥ste vara en enhet unknown unit okänd enhet %1 is a reserved name, please choose another %1 är ett reserverat namn, vänligen välj ett annat namn %1 is a global user definition and cannot be overridden in this session. %1 är en global användardefinition och kan inte Ã¥sidosättas i den här sessionen. %1 is a variable name, please choose another or delete the variable %1 är ett variabelnamn, vänligen välj ett annat eller ta bort variabeln argument %1 is used more than once argumentet %1 används mer än en gÃ¥ng %1 is a built-in unit name, please choose another %1 är namnet pÃ¥ en inbyggd enhet, välj ett annat %1 is a user function name, please choose another or delete the function %1 är ett namn pÃ¥ en användardefinierad funktion, vänligen välj ett annat eller ta bort funktionen FunctionRepo max; trials; probability max; försök; sannolikhet trials; probability antal försök; sannolikhet hits; trials; probability träffar; försök; sannolikhet max; total; hits; trials max; totalt; träffar; försök total; hits; trials totalt; träffar; försök count; total; hits; trials antal; totalt; träffar; försök dividend; divisor täljare; nämnare x; exponent_bits; significand_bits [; exponent_bias] x; exponentbitar; signifikandbitar [; exponentbias] base; x bas; x value; modulo värde; modulo base; exponent; modulo bas; exponent; modulo events; average_events händelser; genomsnitt_händelser average_events genomsnitt_händelser x [; precision] x [; noggrannhet] Absolute Value Absolutbelopp Absolute Deviation Absolut avvikelse Arc Cosine Arkuscosinus Logical AND Logiskt OCH Area Hyperbolic Cosine Areahyperbolisk cosinus Area Hyperbolic Sine Areahyperbolisk sinus Area Hyperbolic Tangent Areahyperbolisk tangens Arc Sine Arkussinus Arc Tangent Arkustangens Arc Tangent with two Arguments arcus tangens tanâ�»Â¹, med tvÃ¥ argument Average (Arithmetic Mean) medelvärde (aritmetiskt medeltal) Binomial Cumulative Distribution Function Binomial kumulativ fördelningsfunktion Binomial Distribution Mean binomialfördelningens medelvärde Binomial Probability Mass Function Binomial sannolikhetsmassfunktion Binomial Distribution Variance binomialfördelningens varians Cube Root Kubikrot Complex Conjugate Komplexkonjugat Cosine Cosinus Hyperbolic Cosine Hyperbolisk cosinus Cotangent Cotangens Cosecant Cosekans Convert Unix timestamp to Date Konvertera Unix-tidsstämpel till datum Degrees of Arc Vinkel i grader Error Function Felfunktion Complementary Error Function Komplementär felfunktion Exponential Exponentialfunktion Fractional Part BrÃ¥kdel Extension of Factorials [= (x-1)!] Utvidgning av fakultet [= (x-1)!] Greatest Common Divisor Största gemensamma delare Geometric Mean Geometriskt medelvärde Gradians of arc vinkel i gradianer 1/400 varv Hypergeometric Cumulative Distribution Function Hypergeometrisk kumulativ fördelningsfunktion Hypergeometric Distribution Mean Hypergeometriskt medelvärde Hypergeometric Probability Mass Function Hypergeometrisk sannolikhetsmassfunktion Hypergeometric Distribution Variance Hypergeometrisk varians Integer Quotient Heltalskvot Integer Part Heltalsdel Imaginary Part Imaginärdel Decode IEEE-754 Binary Value Avkoda IEEE-754 binärt värde Encode IEEE-754 Binary Value Koda IEEE-754 binärt värde Decode 16-bit Half-Precision Value Avkoda 16-bitars halvprecision Encode 16-bit Half-Precision Value Koda 16-bitars halvprecision Decode 32-bit Single-Precision Value Avkoda 32-bitars enkelprecision Encode 32-bit Single-Precision Value Koda 32-bitars enkelprecision Decode 64-bit Double-Precision Value Avkoda 64-bitars dubbelprecision Encode 64-bit Double-Precision Value Koda 64-bitars dubbelprecision Decode 128-bit Quad-Precision Value Avkoda 128-bitars kvadrupelprecision Encode 128-bit Quad-Precision Value Koda 128-bitars kvadrupelprecision Binary Logarithm Logaritmen med bas 2 Common Logarithm Logaritmen med bas 10, tiologaritmen, briggska logaritmen Natural Logarithm Logaritmen med bas e, naturliga logaritmen Logarithm to Arbitrary Base Logaritm med valfri bas Mask to a bit size Maska till en bitstorlek Maximum Maximum Median Value (50th Percentile) Medianvärde (50:e percentilen) Minimum Minimum Modulo Modulo Euclidean Modulo Euklidisk modulo Modular Exponentiation Modulär exponentiering Combination (Binomial Coefficient) Kombination (binomialkoefficient) Logical NOT Logiskt ICKE Permutation (Arrangement) Permutation (arrangemang) Convert to Binary Representation Konvertera till binär representation Arithmetic Aritmetik Chemistry Kemi Complex Komplexa tal Combinatorics Kombinatorik Probability Sannolikhet Statistics Statistik Aggregation Aggregering Random Slump Base conversion Baskonvertering Number formatting Talformatering Integer arithmetic Heltalsaritmetik Special functions Specialfunktioner Exponential & Logarithmic Exponential- och logaritmfunktioner Angle conversion Vinkelkonvertering Trigonometry Trigonometri Bitwise Bitvis Floating point Flyttal Date & Time Datum och tid Linear algebra Linjär algebra unix_timestamp; x hours offset to GMT unix_tidsstämpel; x timmar avvikelse frÃ¥n GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; x timmars avvikelse frÃ¥n GMT [digits] [siffror] max [; min] max [; min] List Literal Listliteral Convert to Padded Binary Representation Konvertera till utfylld binär representation Round Toward +∞ (Ceiling) Avrunda mot +∞ (tak) Cosine plus Imaginary Sine Cosinus plus imaginär sinus Convert to Cis Complex Form Konvertera till cis-form Matrix Column Count Antal matriskolumner Population Correlation Matrix (n) Korrelationsmatris för population (n) Sample Correlation Matrix (n-1) Korrelationsmatris för stickprov (n-1) Count Antal Population Covariance Matrix (n) Kovariansmatris för population (n) Sample Covariance Matrix (n-1) Kovariansmatris för stickprov (n-1) Cross Product Kryssprodukt Convert Date to Unix timestamp Konvertera datum till Unix-tidsstämpel Convert to Decimal Representation Konvertera till decimal representation Determinant Determinant Convert to Sexagesimal Notation Konvertera till sexagesimal notation Dot Product Skalärprodukt Convert to Engineering Notation Konvertera till ingenjörsnotation Convert to Exponential Complex Form Konvertera till exponentiell komplex form Round Toward −∞ (Floor) Avrunda mot −∞ (golv) Flatten Matrix Platta ut matris Least Common Multiple Minsta gemensamma multipel Convert to Hexadecimal Representation Konvertera till hexadecimal representation Convert to Padded Hexadecimal Representation Konvertera till utfylld hexadecimal representation Inverse Matrix Invers matris Round to 16-bit Half-Precision Value Avrunda till 16-bitars halvprecision Round to 32-bit Single-Precision Value Avrunda till 32-bitars enkelprecision Round to 64-bit Double-Precision Value Avrunda till 64-bitars dubbelprecision Round to 128-bit Quad-Precision Value Avrunda till 128-bitars kvadrupelprecision Residual from 16-bit Half-Precision Rounding Rest frÃ¥n 16-bitars halvprecisionsavrundning Residual from 32-bit Single-Precision Rounding Rest frÃ¥n 32-bitars enkelprecisionsavrundning Residual from 64-bit Double-Precision Rounding Rest frÃ¥n 64-bitars dubbelprecisionsavrundning Residual from 128-bit Quad-Precision Rounding Rest frÃ¥n 128-bitars kvadrupelprecisionsavrundning Substance Mass Ämnets massa Molarity Molaritet Molar Mass Molmassa Median Absolute Deviation Median absolut avvikelse Mean Medelvärde Numerical Value of Quantity Numeriskt värde för storhet Random Decimal Number Slumpmässigt decimaltal Random Integer Number Slumpmässigt heltal Convert to Rational Representation Konvertera till rationell representation Convert to Octal Representation Konvertera till oktal representation Convert to Padded Octal Representation Konvertera till utfylld oktal representation Vector or Matrix Norm Vektor- eller matrisnorm Logical OR Logiskt ELLER Population Count (Hamming Weight) Antal ettbitar (Hammingvikt) Phase of Complex Number Komplext tals argument, vinkel i polär form Poissonian Cumulative Distribution Function Poisson kumulativ fördelningsfunktion Poissonian Distribution Mean Poisson medelvärde Poissonian Probability Mass Function Poissonfördelningens sannolikhetsfunktion Poissonian Distribution Variance Poissonfördelningens varians Convert to Phasor Complex Form Konvertera till fasorform Convert to Rectangular Complex Form Konvertera till rektangulär komplex form Round Half Away from Zero Avrunda halva bort frÃ¥n noll Round Half Even Avrunda halva till jämnt Nth Root N:te roten Convert to Scientific Notation Konvertera till vetenskaplig notation Matrix Row Count Antal matrisrader List or Matrix Shape List- eller matrisform Summation Summering Population Standard Deviation (n) Standardavvikelse för population (n) Sample Standard Deviation (n-1) Standardavvikelse för stickprov (n-1) Round Toward Zero (Truncation) Avrunda mot noll (trunkering) Matrix Trace MatrisspÃ¥r Transpose Matrix Transponera matris Population Variance (n) Varians för population (n) Sample Variance (n-1) Varians för stickprov (n-1) Product Produkt Radians Radianer Matrix Rank Matrisrang Real Part Realdel Secant Sekant Arithmetic Shift Left Aritmetisk skiftning vänster Arithmetic Shift Right Aritmetisk skiftning höger Signum tecken, returnerar +1, 0 eller -1 Sine Sinus Hyperbolic Sine Hyperbolisk sinus Square Root Kvadratrot Sum Summa Tangent Tangens Convert to Trigonometric Complex Form Konvertera till trigonometrisk komplex form Turns Varv Hyperbolic Tangent Hyperbolisk tangens Sign-extend a value Teckenutöka ett värde Logical XOR Logiskt XOR FunctionsWidget Domain Domän All Alla Name Namn Search Sök No match found Ingen träff Identifier Identifierare HistoryWidget Remove All Calculations Above Ta bort alla beräkningar ovanför Remove This Calculation Ta bort den här beräkningen Remove All Calculations Below Ta bort alla beräkningar nedanför Keypad Inverse cosine Invers cosinus The last result Senaste resultatet Inverse sine Invers sinus Inverse tangent Invers tangens Evaluate expression Beräkna uttryck Division Division Multiplication Multiplikation Subtraction Subtraktion Addition Addition Clear expression Rensa uttryck Cosine Cosinus Backspace Backsteg Scientific notation Vetenskaplig notation Exponential Exponentialfunktion Factorial Fakultet Natural logarithm Naturlig logaritm Left parenthesis Vänsterparentes Nth root N:te roten Argument separator Argumentavgränsare Square Kvadrat Common logarithm Tiologaritm Modulo Modulo Contextual percentage Kontextuell procent Power Potens Right parenthesis Högerparentes Sine Sinus Square root Kvadratrot Tangent Tangens Pi Pi Decimal separator Decimaltecken MainWindow Radian Radianer Degree Grader Gradian Gradianer Binary Binär Octal Oktal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Engineering decimal Ingenjörsdecimal Scientific decimal Vetenskaplig decimal &Import... &Importera... &Quit A&vsluta Clear E&xpression Rensa &uttryck Clear &History Rensa &historik &Copy &Kopiera &Paste Klistra &in &Select Expression &Markera uttryck &Constants &Konstanter &Functions &Funktioner &History &Historik &Status Bar &Statusrad Bitfield Bitfält Use&r Functions Använda&rfunktioner &Degree &Grader &Radian &Radianer &Gradian &Gradianer Re&volution V&arv Auto-Insert a&ns I&nfoga ans automatiskt Automatic &Completion Automatisk &komplettering &Built-in Functions In&byggda funktioner Built-in &Variables Inbyggda &variabler User &Functions Användar&funktioner User Va&riables Använda&rvariabler Open a Private Tab on Startup Öppna en privat flik vid start Open and focus a new private tab whenever SpeedCrunch starts. Öppna och aktivera en ny privat flik varje gÃ¥ng SpeedCrunch startar. Syntax &Highlighting Syntax&markering Group Digits in &Input Gruppera s&iffror i inmatningen Automatic Input &Adjustments &Automatiska inmatningsjusteringar Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Justera operatorer, mellanrum, parenteser och potenser automatiskt och begränsa inmatningen till giltiga tecken. Group input digits using the selected number format. Gruppera inmatade siffror enligt det valda talformatet. &Blinking Cursor &Blinkande markör Blink the cursor in the expression editor. LÃ¥t markören blinka i uttrycksredigeraren. &Escape Clears Editor &Escape tömmer redigeraren Clear the focused expression editor with Escape after dismissing any popup or preview. Töm den aktiva uttrycksredigeraren med Escape efter att eventuella popupfönster eller förhandsvisningar har stängts. Keep Expression After Evaluation BehÃ¥ll uttrycket efter beräkning Copy New Results Automatically Kopiera nya resultat automatiskt &Comma &Komma &System Default &Systemstandard &Dot &Punkt Dot &And Comma Punkt &och komma Toward +∞ (&ceil) Mot +∞ (&ceil) Toward −∞ (&floor) Mot −∞ (&floor) &Binary &Binärt &Engineering &Ingenjörsdecimaler &Hexadecimal &Hexadecimalt &Octal &Oktalt &Scientific &Vetenskapligt User &Manual &Användarhandbok Issues and &Feedback &Problem och synpunkter &Donate &Donera &About SpeedCrunch &Om SpeedCrunch App Diag&nostics Programdiag&nostik S&plit &Dela Angle &Mode &Vinkelläge &Complex Form &Komplex form New Tab Ny flik Constants Konstanter Functions Funktioner History Historik User Functions Användarfunktioner &Font... &Typsnitt... &Language... &SprÃ¥k... &Session &Session &Edit &Redigera &View &Visa Se&ttings Ins&tällningar &Decimal &Decimalt &Keypad &Knappsats Always on &Top Alltid &överst Disabled Inaktiverad Small Space Litet mellanrum Medium Space Medelstort mellanrum Large Space Stort mellanrum &0 Digits &0 siffror &15 Digits &15 siffror &2 Digits &2 siffror &3 Digits &3 siffror &50 Digits &50 siffror &8 Digits &8 siffror &Sexagesimal &Sexagesimalt Reset All Settings... Ã…terställ alla inställningar... &System &System SpeedCrunch &Theme SpeedCrunch-&tema &Classic &Klassisk &Modern &Modern Context Help Kontexthjälp &Help &Hjälp Error Fel Can't read from file %1 Kan inte läsa frÃ¥n filen %1 Import Session Importera session Close Session Stäng session Angle Mode: Vinkelläge: Notation: Notation: Precision: Precision: Turn Varv Revolution Varv Fixed-point decimal Fast decimalform Rational Rationell Automatic decimal Automatisk decimal Automatic Automatisk User &Definitions... Användar&definitioner... New &Tab Ny &flik New &Private Tab Ny &privat flik Keep BehÃ¥ll Make Private... Gör privat... New &Window Nytt &fönster &Open... &Öppna... &Rename... &Byt namn... Clo&ne... Klo&na... &Close Tab S&täng flik Reopen Clo&sed Tab Öppn&a stängd flik igen Open Sessions &Folder Öppna &sessionsmapp &Undo &Ã…ngra &Redo Gö&r om Cu&t Klipp u&t Copy &Last Result Kopiera senaste resu&ltatet &Wrap in Parentheses &Omslut med parenteser Full Scr&een Mode He&lskärmsläge &Basic &Grundläggande &Scientific (wide) &Vetenskaplig (bred) Scientific (narrow) Vetenskaplig (smal) &Custom... &Anpassad... Main &Menu Huvud&meny User &Variables Användar&variabler &Left &Vänster &Right Höge&r &Up &Upp &Down Ne&d Close Pa&ne Stä&ng panel User &Units Användar&enheter &Turn &Varv If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Om ett nytt uttryck börjar med +, -, * eller / infogar SpeedCrunch först "ans". &Accept with Enter &Godkänn med Retur Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Godkänn det aktuella förslaget för automatisk komplettering med Retur utan att först välja det med piltangenterna. &Units &Enheter Show Live Result &Preview Visa live&förhandsvisning av resultat Save &Window Position on Exit Spara &fönsterposition vid avslut Hover Highlighting Markering vid hovring Group Integer Part Only Gruppera endast heltalsdelen Number Format... Talformat... Notation && Precision... Notation && precision... After pressing Enter, keep the entered expression selected in the editor. BehÃ¥ll det inmatade uttrycket markerat i redigeraren efter Enter. Never Aldrig Always Alltid Only for Single-Line Expressions Endast för enradsuttryck Simplify Displayed Expressions Förenkla visade uttryck History Size &Limit... Storleks&gräns för historik... Remove Trailing &Zeroes &Ta bort avslutande nollor Nearest, Half &Away (round) Närmaste, halva &bort frÃ¥n noll (round) Nearest, Half &Even (roundeven) Närmaste, halva till &jämnt (roundeven) Toward &Zero (trunc) Mot &noll (trunc) &Fixed-Point &Fast decimalform &Rational &Rationell &Exponential (m·sâ�»Â¹) &Exponentiell (m·sâ�»Â¹) &Fractional (m/s) &BrÃ¥kform (m/s) &Rectangular (a + bi) &Rektangulär (a + bi) Exponential (reâ�±á¶¿) Exponentiell (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrisk (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasor (r∠θ) &Theme... &Tema... Check for &Updates Sök efter &uppdateringar Source Code Källkod &Zoom &Zoom &Results &Resultat Unit Notation Enhetsnotation Rounding Mode Avrundningsläge &Notation &Notation &Imaginary Unit &Imaginär enhet &Window &Fönster &Editing &Redigering A&utocomplete A&utokomplettering Up/Down Arrow History Historik med upp-/nedpil &Appearance &Utseende &Menus M&enyer &Docks &Dockningspaneler &Input and Results &Inmatning och resultat &Disabled &Inaktiverad &Disable &Inaktivera Close preview Stäng förhandsvisning Rename... Byt namn... Clone... Klona... Close Tab Stäng flik New Private Tab Ny privat flik Open... Öppna... Reopen Closed Tab Öppna stängd flik igen Split Dela Left Vänster Right Höger Up Upp Down Ned Clear Töm Delete Ta bort %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Privat session: innehÃ¥llet tas bort när den stängs. Välj Session > BehÃ¥ll för att göra den till en vanlig session. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Privat] Reset All Settings Ã…terställ alla inställningar Reset all settings to their default values? Ã…terställ alla inställningar till standardvärdena? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Detta omfattar utseende, redigering, resultatformat och fönsterinställningar. Dina beräkningar, öppna sessioner och användardefinitioner behÃ¥lls. The settings file could not be written. Det gick inte att skriva inställningsfilen. Clear this session's calculations, unfinished expression, variables, functions, and units? Töm den här sessionens beräkningar, ofärdiga uttryck, variabler, funktioner och enheter? Global user definitions are kept. Globala användardefinitioner behÃ¥lls. Make Session Private Gör sessionen privat The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Den sparade sessionen %1 tas bort. InnehÃ¥llet förblir öppet i en privat session och tas bort när sessionen stängs eller SpeedCrunch avslutas. Make Private Gör privat Could not delete the saved session %1. Det gick inte att ta bort den sparade sessionen %1. Keep Session BehÃ¥ll session Could not save the session. It remains private. Det gick inte att spara sessionen. Den förblir privat. Clone Session Klona session Could not save session file %1. Det gick inte att spara sessionsfilen %1. Could not delete session file %1. Det gick inte att ta bort sessionsfilen %1. JSON file (*.json);;Any file (*.*) JSON-fil (*.json);;Valfri fil (*.*) Export session as JSON Exportera session som JSON The selected file is not valid JSON: %1 Den valda filen är inte giltig JSON: %1 The selected file is not a SpeedCrunch session JSON file. Den valda filen är inte en JSON-fil för en SpeedCrunch-session. This file uses an obsolete SpeedCrunch session format and cannot be imported. Den här filen använder ett förÃ¥ldrat SpeedCrunch-sessionsformat och kan inte importeras. The selected JSON file is missing the required $schema field. Den valda JSON-filen saknar det obligatoriska $schema-fältet. The selected JSON file uses an unsupported JSON schema: %1 Den valda JSON-filen använder ett JSON-schema som inte stöds: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Den valda JSON-filen saknar SpeedCrunch-sessionens schemaidentifierare ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Den valda JSON-filen använder ett SpeedCrunch-sessionsformat som inte stöds: %1 The selected JSON file is missing the required session name. Den valda JSON-filen saknar det obligatoriska sessionsnamnet. The selected JSON file has an empty session name. Den valda JSON-filen har ett tomt sessionsnamn. The selected JSON file has invalid or incomplete SpeedCrunch session data. Den valda JSON-filen har ogiltiga eller ofullständiga SpeedCrunch-sessionsdata. Open Sessions Folder Öppna sessionsmapp Could not create the sessions folder: %1 Kunde inte skapa sessionsmappen: %1 Could not open the sessions folder: %1 Kunde inte öppna sessionsmappen: %1 Editor and Results Font Teckensnitt för redigerare och resultat Open Session Öppna session Community Gemenskap Rename Session Byt namn pÃ¥ session Clear Session Rensa session Delete Session Ta bort session Close Pane Stäng panel User Variables Användarvariabler User Units Användarenheter Clear History Rensa historik Are you sure you want to clear the calculation history? Vill du rensa beräkningshistoriken? Session name: Sessionsnamn: A session named %1 already exists. Det finns redan en session med namnet %1. Could not create session file %1. Kunde inte skapa sessionsfilen %1. Could not write session file %1. Kunde inte skriva sessionsfilen %1. Are you sure you want to delete this session? Vill du ta bort den här sessionen? Custom Precision Anpassad precision Fractional digits: Decimaler: Theme Tema Light Themes Ljusa teman Dark Themes Mörka teman Preview Förhandsvisning Colors Färger Select color for %1 Välj färg för %1 Import... Importera... Export... Exportera... Import Theme Importera tema Theme file (*.json);;All files (*) Temafil (*.json);;Alla filer (*) Invalid theme file. Ogiltig temafil. Can't import theme "%1" because it conflicts with a built-in theme. Kan inte importera temat "%1" eftersom det krockar med ett inbyggt tema. Can't find a writable theme folder. Kan inte hitta en skrivbar temamapp. Overwrite Theme Skriv över tema A custom theme named "%1" already exists. Do you want to overwrite it? Det finns redan ett anpassat tema med namnet "%1". Vill du skriva över det? Can't overwrite theme file %1 Kan inte skriva över temafilen %1 Can't copy theme file to %1 Kan inte kopiera temafilen till %1 Export Theme Exportera tema Can't export theme as "%1" because it conflicts with a built-in theme. Kan inte exportera temat som "%1" eftersom det krockar med ett inbyggt tema. Can't write to file %1 Kan inte skriva till filen %1 Global User Variable Global användarvariabel Global User Function Global användarfunktion Global User Unit Global användarenhet User Definitions Användardefinitioner These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Dessa definitioner är globala och läses in i varje session. De kan inte ändras i sessionerna och har företräde framför definitioner med samma namn frÃ¥n sessionsredigeraren. Ange en definition per rad. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Exempel: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Tillämpa Validate Validera Test Results Testresultat Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Importerade variabler: %1 Importerade funktioner: %2 Importerade enheter: %3 Radnummer med fel: %4 none inga Apply Results Resultat av tillämpningen User definitions saved. Användardefinitioner sparade. History Size Limit Storleksgräns för historik Maximum number of history entries for this session (0 = unlimited): Högsta antal historikposter för den här sessionen (0 = obegränsat): Text file (*.txt);;Any file (*.*) Textfil (*.txt);;Alla filer (*.*) Could not recalculate from calculation %1: %2 Kunde inte räkna om frÃ¥n beräkning %1: %2 History Size Limit Reached Storleksgräns för historik nÃ¥dd This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Den här beräkningen fyller den sista tillgängliga historikplatsen. Framtida beräkningar tar bort den äldsta beräkningen frÃ¥n historiken. Du kan öka gränsen via Session > Storleksgräns för historik. Editing calculation. Press Esc twice to cancel. Redigerar beräkning. Tryck pÃ¥ Esc tvÃ¥ gÃ¥nger för att avbryta. Calculation Settings Beräkningsinställningar Invalid recalculation start index Ogiltigt startindex för omberäkning System Default Systemstandard Language SprÃ¥k Select the language: Välj sprÃ¥k: Custom Anpassad Decimal places: Decimaler: &Automatic &Automatisk &Precision &Precision Plain &text Ren &text Formula &Book &Formelsamling &Export &Exportera Export session as HTML Exportera session som HTML HTML file (*.html) HTML-fil (*.html) Export session as plain text Exportera session som ren text ManualWindow SpeedCrunch Manual SpeedCrunch-handbok %1 - SpeedCrunch Manual %1 - SpeedCrunch-handbok NumberFormatDialog Number Format Talformat <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Välj talformat för resultat och gruppering av inmatade siffror.</b><br/><br/>Obs! Entydiga format godtas för inmatade tal även om de skiljer sig frÃ¥n det valda visningsformatet.<br/> QObject Global User Variable Global användarvariabel Global User Function Global användarfunktion Global User Unit Global användarenhet Backspace Backsteg Clear expression Rensa uttryck Evaluate expression Beräkna uttryck Insert text Infoga text Automatic decimal Automatisk decimal Fixed-point decimal Fast decimalform Engineering decimal Ingenjörsdecimal Scientific decimal Vetenskaplig decimal Rational Rationell Binary Binär Octal Oktal Hexadecimal Hexadecimal Sexagesimal Sexagesimal Update Available Uppdatering tillgänglig A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> En nyare version (%1) finns tillgänglig.<br/><a href="%2">Besök webbplatsen för att ladda ner.</a> Check for Updates Sök efter uppdateringar SpeedCrunch %1 is up to date. SpeedCrunch %1 är uppdaterat. No connectivity. Please check your internet connection and try again. Ingen anslutning. Kontrollera internetanslutningen och försök igen. Could not verify the latest available version. Kunde inte kontrollera den senaste tillgängliga versionen. ResultDisplay Scroll to bottom Rulla längst ned Edit Expression Redigera uttryck Change Settings Ändra inställningar New Tab Ny flik &Import... &Importera... &Export &Exportera Plain &text Ren &text Copy Kopiera Selection Markering Select All Markera allt Expression Uttryck Result Resultat Calculation Beräkning Calculation as Single Line Beräkning pÃ¥ en rad Remove Ta bort This Calculation Denna beräkning All Calculations Above Alla beräkningar ovanför All Calculations Below Alla beräkningar nedanför New Private Tab Ny privat flik Session Session Open... Öppna... Clone... Klona... Rename... Byt namn... Keep BehÃ¥ll Make Private... Gör privat... Clear Töm Delete Ta bort Close Stäng Split Dela Left Vänster Right Höger Up Upp Down Ned Close Pane Stäng panel Main Menu Huvudmeny Cancel editing Avbryt redigering Copy result Kopiera resultat Edit expression Redigera uttryck Change settings Ändra inställningar Remove calculation Ta bort beräkning ResultSlotsDialog Notation & Precision Notation och precision Result Line Resultatrad Enabled Aktiverad Notation Notation Decimal Places Decimaler Main Line Huvudrad Extra Line #1 Extrarad 1 Extra Line #2 Extrarad 2 Extra Line #3 Extrarad 3 Extra Line #4 Extrarad 4 Auto Auto UserFunctionListWidget Name Namn Value Värde Description Beskrivning Search Sök No match found Ingen träff Insert Infoga Edit Redigera Delete Ta bort Delete All Ta bort alla UserUnitListWidget Name Namn Value Värde Description Beskrivning Search Sök No match found Ingen träff Insert Infoga Edit Redigera Delete Ta bort Delete All Ta bort alla VariableListWidget Name Namn Value Värde Description Beskrivning Search Sök No match found Ingen träff Insert Infoga Edit Redigera Delete Ta bort Delete All Ta bort alla heldercorreia-speedcrunch-e7ca37f/src/resources/locale/sw.ts000066400000000000000000010555351526573132500244140ustar00rootroot00000000000000 AboutBox About SpeedCrunch Kuhusu SpeedCrunch Main author | Logo | Maintainer Mwandishi mkuu | Nembo | Mtunzaji Core developers Waendelezaji wakuu Original author Mwandishi asilia Math engine Injini ya hesabu Thanks Shukrani Copyright (C) 2004-2026 The SpeedCrunch developers Hakimiliki (C) 2004-2026 waendelezaji wa SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Programu hii ni programu huria; unaweza kuisambaza tena na/au kuibadilisha chini ya masharti ya Leseni ya Umma ya Jumla ya GNU kama ilivyochapishwa na Free Software Foundation; ama toleo la 2 la Leseni, au (kwa hiari yako) toleo lolote la baadaye This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Programu hii inasambazwa kwa matumaini kwamba itakuwa ya manufaa, lakini BILA DHAMANA YOYOTE; hata bila dhamana inayodokezwa ya UUZIKAJI au UFAA KWA MADHUMUNI FULANI. Tazama Leseni ya Umma ya Jumla ya GNU kwa maelezo zaidi. Close Funga BitFieldWidget Reset bits to zero Weka upya biti ziwe sifuri Invert bits Geuza biti Shift bits left Hamisha biti kushoto Shift bits right Hamisha biti kulia Book Index Faharasa Algebra Aljebra Quadratic Equation Mlinganyo wa kwadrati Logarithmic Base Conversion Ubadilishaji wa msingi wa logaridhimu Geometry Jiometri Circle Mduara Sector Sekta ya mduara Sphere Tufe Cube Mchemraba Cone Koni Cylinder Silinda Electronics Elektroniki Ohm's Law Sheria ya Ohm Power Nguvu Reactance Reaktansi Resonance Resonansi Radio Frequency Masafa ya redio Antennas Antena Characteristic Impedance (coax) Impedansi bainifu (koaksi) Velocity of Propagation (coax) Kasi ya uenezi (koaksi) Standing Wave Ratio & Return Loss Uwiano wa mawimbi yaliyosimama & hasara ya urejesho Free Space Wavelength Urefu wa wimbi katika nafasi huru resistance upinzani voltage volteji current mkondo power nguvu inductive reactance reaktansi ya induktivu capacitive reactance reaktansi ya kapasitivu inductance induktansi capacitance kapasitansi frequency masafa resonance frequency masafa ya resonansi area eneo perimeter mzunguko diameter kipenyo radius radiusi volume ujazo surface area eneo la uso height urefu slant height urefu wa mwinamo face diagonal diagonali ya uso space diagonal diagonali ya nafasi edge length urefu wa ukingo arc length urefu wa tao central angle (degrees) pembe ya katikati (digrii) dielectric constant konstanti ya dielektriki outer conductor's inner diameter kipenyo cha ndani cha kondakta wa nje inner conductor's outer diameter kipenyo cha nje cha kondakta wa ndani speed of light kasi ya mwanga input power nguvu ya ingizo reflected power nguvu iliyoakisiwa transmitted power nguvu iliyopitishwa return loss hasara ya urejesho reflection coefficient mgawo wa uakisi standing wave ratio uwiano wa mawimbi yaliyosimama normalized impedance impedansi iliyosanifishwa frequency (Hz) masafa (Hz) BookDock Formula Book Kitabu cha fomula ConstantCompletion Search constants Tafuta konstanti No match found Hakuna kinacholingana kilichopatikana Constants Mathematics Hisabati Physics (CODATA 2022) Fizikia (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kemia (IUPAC - CIAAW 2021) Uncategorized Haijapangwa Universal Ulimwengu wote Physicochemical Fizikokemia Atomic & Nuclear — General Atomiki & Nyuklia — Jumla Atomic & Nuclear — Electroweak Atomiki & Nyuklia — Umeme-dhaifu Atomic & Nuclear — Electron Atomiki & Nyuklia — Elektroni Atomic & Nuclear — Muon Atomiki & Nyuklia — Muoni Atomic & Nuclear — Tau Atomiki & Nyuklia — Tau Atomic & Nuclear — Proton Atomiki & nyuklia — Protoni Atomic & Nuclear — Neutron Atomiki & nyuklia — Nyutroni Atomic & Nuclear — Deuteron Atomiki & nyuklia — Deuteroni Atomic & Nuclear — Triton Atomiki & nyuklia — Tritoni Atomic & Nuclear — Helion Atomiki & nyuklia — Helioni Atomic & Nuclear — Alpha particle Atomiki & nyuklia — Chembe ya alfa Atomic & Nuclear — Atomic units Atomiki & nyuklia — Vipimo vya atomiki Atomic & Nuclear — Energy conversion relationships Atomiki & nyuklia — Uhusiano wa ubadilishaji wa nishati Atomic & Nuclear — X-ray units Atomiki & nyuklia — Vipimo vya X-ray Atomic & Nuclear — Magnetic shielding corrections Atomiki & nyuklia — Masahihisho ya kinga ya sumaku Masses Misa Lifetimes Muda wa maisha Molar Masses Misa za mola Electronegativity Elektronegativiti Ionization Energy Nishati ya uionishaji Nominal Constants (IAU 2015) Konstanti za kawaida (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Makadirio bora ya sasa (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) impedansi bainifu ya ombwe (Zâ‚€) reduced Planck constant (â„�) konstanti iliyopunguzwa ya Planck (â„�) vacuum electric permittivity (ϵ₀) upermiti wa umeme wa ombwe (ϵ₀) Newtonian constant of gravitation (G) konstanti ya Newton ya uvutano (G) vacuum magnetic permeability (μ₀) upenyezaji wa sumaku wa ombwe (μ₀) Planck constant (h) konstanti ya Planck (h) speed of light in vacuum (c) kasi ya mwanga katika ombwe (c) standard acceleration of gravity (gâ‚™) uharakishaji sanifu wa mvutano (gâ‚™) Newtonian constant of gravitation over h-bar c konstanti ya Newton ya uvutano juu ya h-bar c Planck length urefu wa Planck Planck constant in eV/Hz (h) konstanti ya Planck katika eV/Hz (h) Planck mass misa ya Planck Planck mass energy equivalent in GeV sawa ya nishati ya misa ya Planck katika GeV Planck temperature halijoto ya Planck Planck time muda wa Planck reduced Planck constant in eV·s (â„�) konstanti iliyopunguzwa ya Planck katika eV·s (â„�) reduced Planck constant times c in MeV·fm konstanti iliyopunguzwa ya Planck mara c katika MeV·fm Bohr magneton magnetoni ya Bohr conductance quantum (Gâ‚€) kwantamu ya kondaktansi (Gâ‚€) Coulomb constant (kâ‚‘) konstanti ya Coulomb (kâ‚‘) elementary charge (e) chaji ya msingi (e) elementary charge over h-bar chaji ya msingi juu ya h-bar conventional value of Josephson constant thamani ya kawaida ya konstanti ya Josephson Josephson constant konstanti ya Josephson conventional value of ampere-90 thamani ya kawaida ya ampere-90 conventional value of coulomb-90 thamani ya kawaida ya coulomb-90 conventional value of farad-90 thamani ya kawaida ya farad-90 conventional value of henry-90 thamani ya kawaida ya henry-90 conventional value of ohm-90 thamani ya kawaida ya ohm-90 conventional value of volt-90 thamani ya kawaida ya volt-90 conventional value of watt-90 thamani ya kawaida ya watt-90 magnetic flux quantum (Φ₀) kwantamu ya mtiririko wa sumaku (Φ₀) nuclear magneton magnetoni ya nyuklia inverse of conductance quantum kinyume cha kwantamu ya kondaktansi conventional value of von Klitzing constant thamani ya kawaida ya konstanti ya von Klitzing von Klitzing constant konstanti ya von Klitzing atomic unit of magnetic dipole moment kipimo cha atomiki cha momenti ya dipoli ya sumaku atomic unit of magnetic flux density kipimo cha atomiki cha msongamano wa mtiririko wa sumaku Bohr magneton in eV/T magnetoni ya Bohr katika eV/T Bohr magneton in Hz/T magnetoni ya Bohr katika Hz/T Bohr magneton in inverse meter per tesla magnetoni ya Bohr katika inverse meter per tesla Bohr magneton in K/T magnetoni ya Bohr katika K/T nuclear magneton in eV/T magnetoni ya nyuklia katika eV/T nuclear magneton in inverse meter per tesla magnetoni ya nyuklia katika inverse meter per tesla nuclear magneton in K/T magnetoni ya nyuklia katika K/T nuclear magneton in MHz/T magnetoni ya nyuklia katika MHz/T Bohr radius (aâ‚€) radiusi ya Bohr (aâ‚€) fine-structure constant (α) konstanti ya muundo-faini (α) Hartree energy (Eâ‚•) nishati ya Hartree (Eâ‚•) Hartree energy in eV nishati ya Hartree katika eV quantum of circulation kwantamu ya mzunguko quantum of circulation times 2 kwantamu ya mzunguko mara 2 Rydberg constant (R∞) konstanti ya Rydberg (R∞) atomic mass unit-hartree relationship uhusiano wa kipimo cha misa ya atomiki na Hartree atomic mass unit-hertz relationship uhusiano wa kipimo cha misa ya atomiki na hertzi atomic mass unit-inverse meter relationship uhusiano wa kipimo cha misa ya atomiki na mita kinyume atomic mass unit-joule relationship uhusiano wa kipimo cha misa ya atomiki na jouli atomic mass unit-kelvin relationship uhusiano wa kipimo cha misa ya atomiki na kelvini atomic mass unit-kilogram relationship uhusiano wa kipimo cha misa ya atomiki na kilogramu atomic unit of 1st hyperpolarizability kipimo cha atomiki cha 1st hyperpolarizability atomic unit of 2nd hyperpolarizability kipimo cha atomiki cha 2nd hyperpolarizability atomic unit of charge (e) kipimo cha atomiki cha chaji (e) atomic unit of charge density kipimo cha atomiki cha msongamano wa chaji atomic unit of current kipimo cha atomiki cha mkondo atomic unit of electric dipole moment kipimo cha atomiki cha momenti ya dipoli ya umeme atomic unit of electric field kipimo cha atomiki cha uga wa umeme atomic unit of electric field gradient kipimo cha atomiki cha gradiyenti ya uga wa umeme atomic unit of electric polarizability kipimo cha atomiki cha upolarizikaji wa umeme atomic unit of electric potential kipimo cha atomiki cha potensheli ya umeme atomic unit of electric quadrupole moment kipimo cha atomiki cha momenti ya quadrupole ya umeme atomic unit of action kipimo cha atomiki cha hatua atomic unit of energy kipimo cha atomiki cha nishati atomic unit of force kipimo cha atomiki cha nguvu atomic unit of length kipimo cha atomiki cha urefu hertz-atomic mass unit relationship uhusiano wa hertzi na kipimo cha misa ya atomiki hertz-electron volt relationship uhusiano wa hertzi na elektronivolti hertz-hartree relationship uhusiano wa hertzi na Hartree hertz-inverse meter relationship uhusiano wa hertzi na mita kinyume hertz-joule relationship uhusiano wa hertzi na jouli hertz-kelvin relationship uhusiano wa hertzi na kelvini hertz-kilogram relationship uhusiano wa hertzi na kilogramu hyperfine transition frequency of Cs-133 marudio ya mpito wa hyperfine wa Cs-133 inverse fine-structure constant (αâ�»Â¹) kinyume cha konstanti ya muundo-faini (αâ�»Â¹) inverse meter-atomic mass unit relationship uhusiano wa mita kinyume na kipimo cha misa ya atomiki inverse meter-electron volt relationship uhusiano wa mita kinyume na elektronivolti inverse meter-hartree relationship uhusiano wa mita kinyume na Hartree inverse meter-hertz relationship uhusiano wa mita kinyume na hertzi inverse meter-joule relationship uhusiano wa mita kinyume na jouli inverse meter-kelvin relationship uhusiano wa mita kinyume na kelvini inverse meter-kilogram relationship uhusiano wa mita kinyume na kilogramu joule-atomic mass unit relationship uhusiano wa jouli na kipimo cha misa ya atomiki joule-electron volt relationship uhusiano wa jouli na elektronivolti joule-hertz relationship uhusiano wa jouli na hertzi joule-hartree relationship uhusiano wa jouli na Hartree joule-inverse meter relationship uhusiano wa jouli na mita kinyume joule-kelvin relationship uhusiano wa jouli na kelvini joule-kilogram relationship uhusiano wa jouli na kilogramu kelvin-atomic mass unit relationship uhusiano wa kelvini na kipimo cha misa ya atomiki kelvin-electron volt relationship uhusiano wa kelvini na elektronivolti kelvin-hertz relationship uhusiano wa kelvini na hertzi kelvin-hartree relationship uhusiano wa kelvini na Hartree kelvin-inverse meter relationship uhusiano wa kelvini na mita kinyume kelvin-joule relationship uhusiano wa kelvini na jouli kelvin-kilogram relationship uhusiano wa kelvini na kilogramu kilogram-atomic mass unit relationship uhusiano wa kilogramu na kipimo cha misa ya atomiki kilogram-electron volt relationship uhusiano wa kilogramu na elektronivolti kilogram-hertz relationship uhusiano wa kilogramu na hertzi kilogram-hartree relationship uhusiano wa kilogramu na Hartree kilogram-inverse meter relationship uhusiano wa kilogramu na mita kinyume kilogram-joule relationship uhusiano wa kilogramu na jouli kilogram-kelvin relationship uhusiano wa kilogramu na kelvini lattice parameter of silicon (a) kigezo cha kimiani cha silikoni (a) luminous efficacy ufanisi wa mwangaza natural unit of energy kipimo asilia cha nishati natural unit of energy in MeV kipimo asilia cha nishati katika MeV natural unit of action (â„�) kipimo asilia cha hatua (â„�) natural unit of action in eV·s kipimo asilia cha hatua katika eV·s natural unit of length kipimo asilia cha urefu natural unit of mass kipimo asilia cha misa natural unit of momentum kipimo asilia cha momentamu natural unit of momentum in MeV/c kipimo asilia cha momentamu katika MeV/c natural unit of time kipimo asilia cha muda natural unit of velocity kipimo asilia cha kasi Rydberg constant times c in Hz konstanti ya Rydberg mara c katika Hz Rydberg constant times hc in eV konstanti ya Rydberg mara hc katika eV Rydberg constant times hc in J konstanti ya Rydberg mara hc katika J Fermi coupling constant konstanti ya uunganishaji ya Fermi weak mixing angle pembe ya kuchanganyika dhaifu W to Z mass ratio uwiano wa misa ya W kwa Z Thomson cross section (σₑ) eneo msalaba la Thomson (σₑ) electron mass (mâ‚‘) misa ya elektroni (mâ‚‘) electron mass in u misa ya elektroni katika u electron mass energy equivalent (mₑ·c²) sawa ya nishati ya misa ya elektroni (mₑ·c²) electron mass energy equivalent in MeV sawa ya nishati ya misa ya elektroni katika MeV reduced Compton wavelength urefu wa wimbi wa Compton wa reduced classical electron radius (râ‚‘) radiusi ya elektroni ya kiklasiki (râ‚‘) electron charge to mass quotient mgawo wa chaji kwa misa wa elektroni electron-deuteron magnetic moment ratio uwiano wa momenti ya sumaku ya elektroni na deuteroni electron-deuteron mass ratio uwiano wa misa ya elektroni na deuteroni electron g factor (gâ‚‘) fakta ya g ya elektroni (gâ‚‘) electron gyromagnetic ratio (γₑ) uwiano wa jiromagnetiki wa elektroni (γₑ) electron gyromagnetic ratio in MHz/T uwiano wa jiromagnetiki wa elektroni katika MHz/T electron-helion mass ratio uwiano wa misa ya elektroni na helioni electron magnetic moment (μₑ) momenti ya sumaku ya elektroni (μₑ) electron magnetic moment anomaly (aâ‚‘) anomalio la momenti ya sumaku ya elektroni (aâ‚‘) electron magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya elektroni kwa magnetoni ya Bohr electron magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya elektroni kwa magnetoni ya nyuklia electron molar mass (Mâ‚‘) misa ya mola ya elektroni (Mâ‚‘) electron-muon magnetic moment ratio uwiano wa momenti ya sumaku ya elektroni na muoni electron-muon mass ratio uwiano wa misa ya elektroni na muoni electron-neutron magnetic moment ratio uwiano wa momenti ya sumaku ya elektroni na nyutroni electron-neutron mass ratio uwiano wa misa ya elektroni na nyutroni electron-proton magnetic moment ratio uwiano wa momenti ya sumaku ya elektroni na protoni electron-proton mass ratio uwiano wa misa ya elektroni na protoni electron relative atomic mass (Ar(e)) misa atomiki ya uwiano ya elektroni (Ar(e)) electron-tau mass ratio uwiano wa misa ya elektroni na tau electron to alpha particle mass ratio uwiano wa misa ya elektroni kwa chembe ya alfa electron to shielded helion magnetic moment ratio uwiano wa momenti ya sumaku ya elektroni kwa helioni iliyokingwa electron to shielded proton magnetic moment ratio uwiano wa momenti ya sumaku ya elektroni kwa protoni iliyokingwa electron-triton mass ratio uwiano wa misa ya elektroni na tritoni electron volt-atomic mass unit relationship uhusiano wa elektronivolti na kipimo cha misa ya atomiki electron volt-hartree relationship uhusiano wa elektronivolti na Hartree electron volt-hertz relationship uhusiano wa elektronivolti na hertzi electron volt-inverse meter relationship uhusiano wa elektronivolti na mita kinyume electron volt-joule relationship uhusiano wa elektronivolti na jouli electron volt-kelvin relationship uhusiano wa elektronivolti na kelvini electron volt-kilogram relationship uhusiano wa elektronivolti na kilogramu hartree-atomic mass unit relationship uhusiano wa Hartree na kipimo cha misa ya atomiki hartree-electron volt relationship uhusiano wa Hartree na elektronivolti muon Compton wavelength urefu wa wimbi wa Compton wa muoni muon-electron mass ratio uwiano wa misa ya muoni na elektroni muon g factor fakta ya g ya muoni muon magnetic moment momenti ya sumaku ya muoni muon magnetic moment anomaly anomalio la momenti ya sumaku ya muoni muon magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya muoni kwa magnetoni ya Bohr muon magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya muoni kwa magnetoni ya nyuklia muon mass misa ya muoni muon mass energy equivalent sawa ya nishati ya misa ya muoni muon mass energy equivalent in MeV sawa ya nishati ya misa ya muoni katika MeV muon mass in u misa ya muoni katika u muon molar mass misa ya mola ya muoni muon-neutron mass ratio uwiano wa misa ya muoni na nyutroni muon-proton magnetic moment ratio uwiano wa momenti ya sumaku ya muoni na protoni muon-proton mass ratio uwiano wa misa ya muoni na protoni muon-tau mass ratio uwiano wa misa ya muoni na tau reduced muon Compton wavelength urefu wa wimbi wa Compton wa reduced muon reduced tau Compton wavelength urefu wa wimbi wa Compton wa reduced tau tau Compton wavelength urefu wa wimbi wa Compton wa tau tau-electron mass ratio uwiano wa misa ya tau na elektroni tau mass misa ya tau tau mass energy equivalent sawa ya nishati ya misa ya tau tau mass in u misa ya tau katika u tau molar mass misa ya mola ya tau tau-muon mass ratio uwiano wa misa ya tau na muoni tau-neutron mass ratio uwiano wa misa ya tau na nyutroni tau-proton mass ratio uwiano wa misa ya tau na protoni proton charge to mass quotient mgawo wa chaji kwa misa wa protoni proton Compton wavelength urefu wa wimbi wa Compton wa protoni proton-electron mass ratio uwiano wa misa ya protoni na elektroni proton g factor (gₚ) fakta ya g ya protoni (gₚ) proton gyromagnetic ratio (γₚ) uwiano wa jiromagnetiki wa protoni (γₚ) proton gyromagnetic ratio in MHz/T uwiano wa jiromagnetiki wa protoni katika MHz/T proton magnetic moment (μₚ) momenti ya sumaku ya protoni (μₚ) proton magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya protoni kwa magnetoni ya Bohr proton magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya protoni kwa magnetoni ya nyuklia proton magnetic shielding correction sahihisho la kinga ya sumaku la protoni proton mass (mₚ) misa ya protoni (mₚ) proton mass energy equivalent sawa ya nishati ya misa ya protoni proton mass energy equivalent in MeV sawa ya nishati ya misa ya protoni katika MeV proton mass in u misa ya protoni katika u proton molar mass (Mₚ) misa ya mola ya protoni (Mₚ) proton-muon mass ratio uwiano wa misa ya protoni na muoni proton-neutron magnetic moment ratio uwiano wa momenti ya sumaku ya protoni na nyutroni proton-neutron mass ratio uwiano wa misa ya protoni na nyutroni proton relative atomic mass (Ar(p)) misa atomiki ya uwiano ya protoni (Ar(p)) proton rms charge radius radiusi ya chaji ya rms ya protoni proton-tau mass ratio uwiano wa misa ya protoni na tau reduced proton Compton wavelength urefu wa wimbi wa Compton wa reduced proton shielded proton gyromagnetic ratio uwiano wa jiromagnetiki wa protoni iliyokingwa shielded proton gyromagnetic ratio in MHz/T uwiano wa jiromagnetiki wa protoni iliyokingwa katika MHz/T shielded proton magnetic moment momenti ya sumaku ya protoni iliyokingwa shielded proton magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya protoni iliyokingwa kwa magnetoni ya Bohr shielded proton magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya protoni iliyokingwa kwa magnetoni ya nyuklia neutron Compton wavelength urefu wa wimbi wa Compton wa nyutroni neutron-electron magnetic moment ratio uwiano wa momenti ya sumaku ya nyutroni na elektroni neutron-electron mass ratio uwiano wa misa ya nyutroni na elektroni neutron g factor (gâ‚™) fakta ya g ya nyutroni (gâ‚™) neutron gyromagnetic ratio (γₙ) uwiano wa jiromagnetiki wa nyutroni (γₙ) neutron gyromagnetic ratio in MHz/T uwiano wa jiromagnetiki wa nyutroni katika MHz/T neutron magnetic moment (μₙ) momenti ya sumaku ya nyutroni (μₙ) neutron magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya nyutroni kwa magnetoni ya Bohr neutron magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya nyutroni kwa magnetoni ya nyuklia neutron mass (mâ‚™) misa ya nyutroni (mâ‚™) neutron mass energy equivalent sawa ya nishati ya misa ya nyutroni neutron mass energy equivalent in MeV sawa ya nishati ya misa ya nyutroni katika MeV neutron mass in u misa ya nyutroni katika u neutron molar mass (Mâ‚™) misa ya mola ya nyutroni (Mâ‚™) neutron-muon mass ratio uwiano wa misa ya nyutroni na muoni neutron-proton magnetic moment ratio uwiano wa momenti ya sumaku ya nyutroni na protoni neutron-proton mass difference tofauti ya misa ya nyutroni na protoni neutron-proton mass difference energy equivalent sawa ya nishati ya tofauti ya misa ya nyutroni na protoni neutron-proton mass difference energy equivalent in MeV sawa ya nishati ya tofauti ya misa ya nyutroni na protoni katika MeV neutron-proton mass difference in u tofauti ya misa ya nyutroni na protoni katika u neutron-proton mass ratio uwiano wa misa ya nyutroni na protoni neutron relative atomic mass (Ar(n)) misa atomiki ya uwiano ya nyutroni (Ar(n)) neutron-tau mass ratio uwiano wa misa ya nyutroni na tau neutron to shielded proton magnetic moment ratio uwiano wa momenti ya sumaku ya nyutroni kwa protoni iliyokingwa reduced neutron Compton wavelength urefu wa wimbi wa Compton uliopunguzwa wa nyutroni deuteron-electron magnetic moment ratio uwiano wa momenti ya sumaku ya deuteroni na elektroni deuteron-electron mass ratio uwiano wa misa ya deuteroni na elektroni deuteron g factor fakta ya g ya deuteroni deuteron magnetic moment momenti ya sumaku ya deuteroni deuteron magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya deuteroni kwa magnetoni ya Bohr deuteron magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya deuteroni kwa magnetoni ya nyuklia deuteron mass misa ya deuteroni deuteron mass energy equivalent sawa ya nishati ya misa ya deuteroni deuteron mass energy equivalent in MeV sawa ya nishati ya misa ya deuteroni katika MeV deuteron mass in u misa ya deuteroni katika u deuteron molar mass misa ya mola ya deuteroni deuteron-neutron magnetic moment ratio uwiano wa momenti ya sumaku ya deuteroni na nyutroni deuteron-proton magnetic moment ratio uwiano wa momenti ya sumaku ya deuteroni na protoni deuteron-proton mass ratio uwiano wa misa ya deuteroni na protoni deuteron relative atomic mass (Ar(d)) misa atomiki ya uwiano ya deuteroni (Ar(d)) deuteron rms charge radius radiusi ya chaji ya rms ya deuteroni triton-electron mass ratio uwiano wa misa ya tritoni na elektroni triton g factor (gₜ) fakta ya g ya tritoni (gₜ) triton magnetic moment (μₜ) momenti ya sumaku ya tritoni (μₜ) triton magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya tritoni kwa magnetoni ya Bohr triton magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya tritoni kwa magnetoni ya nyuklia triton mass (mₜ) misa ya tritoni (mₜ) triton mass energy equivalent sawa ya nishati ya misa ya tritoni triton mass energy equivalent in MeV sawa ya nishati ya misa ya tritoni katika MeV triton mass in u misa ya tritoni katika u triton molar mass (Mₜ) misa ya mola ya tritoni (Mₜ) triton-proton mass ratio uwiano wa misa ya tritoni na protoni triton relative atomic mass (Ar(t)) misa atomiki ya uwiano ya tritoni (Ar(t)) triton to proton magnetic moment ratio uwiano wa momenti ya sumaku ya tritoni kwa protoni helion-electron mass ratio uwiano wa misa ya helioni na elektroni helion g factor (gâ‚•) fakta ya g ya helioni (gâ‚•) helion magnetic moment (μₕ) momenti ya sumaku ya helioni (μₕ) helion magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya helioni kwa magnetoni ya Bohr helion magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya helioni kwa magnetoni ya nyuklia helion mass (mâ‚•) misa ya helioni (mâ‚•) helion mass energy equivalent sawa ya nishati ya misa ya helioni helion mass energy equivalent in MeV sawa ya nishati ya misa ya helioni katika MeV helion mass in u misa ya helioni katika u helion molar mass (Mâ‚•) misa ya mola ya helioni (Mâ‚•) helion-proton mass ratio uwiano wa misa ya helioni na protoni helion relative atomic mass (Ar(h)) misa atomiki ya uwiano ya helioni (Ar(h)) helion shielding shift uhamisho wa kinga wa helioni shielded helion gyromagnetic ratio uwiano wa jiromagnetiki wa helioni iliyokingwa shielded helion gyromagnetic ratio in MHz/T uwiano wa jiromagnetiki wa helioni iliyokingwa katika MHz/T shielded helion magnetic moment momenti ya sumaku ya helioni iliyokingwa shielded helion magnetic moment to Bohr magneton ratio uwiano wa momenti ya sumaku ya helioni iliyokingwa kwa magnetoni ya Bohr shielded helion magnetic moment to nuclear magneton ratio uwiano wa momenti ya sumaku ya helioni iliyokingwa kwa magnetoni ya nyuklia shielded helion to proton magnetic moment ratio uwiano wa momenti ya sumaku ya helioni iliyokingwa kwa protoni shielded helion to shielded proton magnetic moment ratio uwiano wa momenti ya sumaku ya helioni iliyokingwa kwa protoni iliyokingwa alpha particle mass misa ya chembe ya alfa alpha particle mass in u misa ya chembe ya alfa katika u alpha particle mass energy equivalent sawa ya nishati ya misa ya chembe ya alfa alpha particle mass energy equivalent in MeV sawa ya nishati ya misa ya chembe ya alfa katika MeV alpha particle-electron mass ratio uwiano wa misa ya chembe ya alfa na elektroni alpha particle-proton mass ratio uwiano wa misa ya chembe ya alfa na protoni alpha particle rms charge radius radiusi ya chaji ya rms ya chembe ya alfa alpha particle molar mass misa ya mola ya chembe ya alfa alpha particle relative atomic mass (Ar(α)) misa atomiki ya uwiano ya chembe ya alfa (Ar(α)) atomic mass constant (mᵤ) konstanti ya misa ya atomiki (mᵤ) Avogadro constant konstanti ya Avogadro Boltzmann constant (k) konstanti ya Boltzmann (k) Boltzmann constant in eV/K konstanti ya Boltzmann katika eV/K Boltzmann constant in Hz/K konstanti ya Boltzmann katika Hz/K Boltzmann constant in inverse meter per kelvin konstanti ya Boltzmann katika inverse meter per kelvin electron volt (eV) elektronivolti (eV) Faraday constant (F) konstanti ya Faraday (F) first radiation constant (câ‚�) konstanti ya kwanza ya mnururisho (câ‚�) first radiation constant for spectral radiance konstanti ya kwanza ya mnururisho kwa mwangaza wa spektramu molar gas constant (R) konstanti ya gesi ya mola (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) konstanti ya Loschmidt (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) konstanti ya Loschmidt (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant konstanti ya Planck ya mola second radiation constant (câ‚‚) konstanti ya pili ya mnururisho (câ‚‚) Stefan-Boltzmann constant (σ) konstanti ya Stefan-Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) nafasi ya kimiani ya Si bora (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent sawa ya nishati ya konstanti ya misa ya atomiki atomic mass constant energy equivalent in MeV sawa ya nishati ya konstanti ya misa ya atomiki katika MeV atomic mass unit-electron volt relationship uhusiano wa kipimo cha misa ya atomiki na elektronivolti molar mass constant (Mᵤ) konstanti ya misa ya mola (Mᵤ) molar mass of carbon-12 misa ya mola ya kaboni-12 molar volume of ideal gas (273.15 K, 100 kPa) ujazo wa mola wa gesi bora (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ujazo wa mola wa gesi bora (273.15 K, 101.325 kPa) molar volume of silicon ujazo wa mola wa silikoni Sackur-Tetrode constant (1 K, 100 kPa) konstanti ya Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) konstanti ya Sackur-Tetrode (1 K, 101.325 kPa) Wien frequency displacement law constant konstanti ya sheria ya uhamisho wa marudio ya Wien Wien wavelength displacement law constant konstanti ya sheria ya uhamisho wa urefu wa wimbi ya Wien standard atmosphere (atm) angahewa sanifu (atm) standard-state pressure (p°) shinikizo la hali sanifu (p°) Angstrom star (Ã…*) nyota ya Angstrom (Ã…*) Copper x unit kipimo x cha shaba Molybdenum x unit kipimo x cha molybdenum atomic unit of magnetizability kipimo cha atomiki cha uwezo wa kusumakishwa atomic unit of mass (mâ‚‘) kipimo cha atomiki cha misa (mâ‚‘) atomic unit of momentum kipimo cha atomiki cha momentamu atomic unit of permittivity kipimo cha atomiki cha upermiti atomic unit of time kipimo cha atomiki cha muda atomic unit of velocity kipimo cha atomiki cha kasi hartree-hertz relationship uhusiano wa Hartree na hertzi hartree-inverse meter relationship uhusiano wa Hartree na mita kinyume hartree-joule relationship uhusiano wa Hartree na jouli hartree-kelvin relationship uhusiano wa Hartree na kelvini hartree-kilogram relationship uhusiano wa Hartree na kilogramu shielding difference of d and p in HD tofauti ya kinga ya d na p katika HD shielding difference of t and p in HT tofauti ya kinga ya t na p katika HT pi (Ï€) pai (Ï€) Euler's number (e) namba ya Euler (e) golden ratio (φ) uwiano wa dhahabu (φ) Euler-Mascheroni constant (γ) konstanti ya Euler-Mascheroni (γ) nominal solar radius radiusi ya kawaida ya Jua nominal solar total irradiance mnururisho jumla wa kawaida wa Jua nominal solar luminosity mwangaza wa kawaida wa Jua nominal solar effective temperature halijoto fanisi ya kawaida ya Jua nominal solar mass parameter kigezo cha kawaida cha misa ya Jua nominal terrestrial equatorial radius radiusi ya kawaida ya ikweta ya Dunia nominal terrestrial polar radius radiusi ya kawaida ya ncha ya Dunia nominal terrestrial mass parameter kigezo cha kawaida cha misa ya Dunia nominal jovian equatorial radius radiusi ya kawaida ya ikweta ya Jupita nominal jovian polar radius radiusi ya kawaida ya ncha ya Jupita nominal jovian mass parameter kigezo cha kawaida cha misa ya Jupita average value of one minus the rate of TCG relative to TCB thamani wastani ya moja kasoro kiwango cha TCG ikilinganishwa na TCB solar mass parameter (TCB-compatible) kigezo cha misa ya Jua (TCB-compatible) solar mass parameter (TDB-compatible) kigezo cha misa ya Jua (TDB-compatible) equatorial radius of the Earth (TT-compatible) radiusi ya ikweta ya Dunia (TT-compatible) dynamical form factor of the Earth fakta ya umbo la kidinamiki la Dunia time rate of change in the dynamical form factor of the Earth kiwango cha mabadiliko kwa muda katika fakta ya umbo la kidinamiki la Dunia geocentric gravitational constant (TCB-compatible) konstanti ya uvutano ya kijiografia (TCB-compatible) geocentric gravitational constant (TT-compatible) konstanti ya uvutano ya kijiografia (TT-compatible) geocentric gravitational constant (TDB-compatible) konstanti ya uvutano ya kijiografia (TDB-compatible) potential of the geoid potensheli ya geoidi nominal mean angular velocity of the Earth (TT-compatible) kasi ya pembe wastani ya kawaida ya Dunia (TT-compatible) ratio mass of the Moon to the Earth uwiano wa misa ya Mwezi kwa Dunia ratio of the mass of the Sun to Mercury uwiano wa misa ya Jua kwa Zebaki ratio of the mass of the Sun to Venus uwiano wa misa ya Jua kwa Zuhura ratio of the mass of the Sun to Mars uwiano wa misa ya Jua kwa Mirihi ratio of the mass of the Sun to Jupiter uwiano wa misa ya Jua kwa Jupita ratio of the mass of the Sun to Saturn uwiano wa misa ya Jua kwa Zohali ratio of the mass of the Sun to Uranus uwiano wa misa ya Jua kwa Uranusi ratio of the mass of the Sun to Neptune uwiano wa misa ya Jua kwa Neptuni ratio of the mass of the Sun to (134340) Pluto uwiano wa misa ya Jua kwa (134340) Pluto ratio of the mass of the Sun to (136199) Eris uwiano wa misa ya Jua kwa (136199) Eris ratio of the mass of (1) Ceres to the Sun uwiano wa misa ya (1) Ceres kwa Jua ratio of the mass of (2) Pallas to the Sun uwiano wa misa ya (2) Pallas kwa Jua ratio of the mass of (4) Vesta to the Sun uwiano wa misa ya (4) Vesta kwa Jua mean obliquity of the ecliptic at J2000.0 mwinamo wastani wa ekliptiki katika J2000.0 Electromagnetic Umeme-sumaku Compton wavelength Urefu wa wimbi wa Compton Astronomy Astronomia ConstantsWidget Domain Kikoa Subdomain Kikoa kidogo Search Tafuta No match found Hakuna kinacholingana kilichopatikana Name Jina Value Thamani Unit Kitengo All Zote CustomKeypadDialog Custom Keypad Kibodi maalum Rows: Safu mlalo: Columns: Safu wima: Copy preset: Nakili mpangilio tayari: Basic Msingi Scientific (wide) Kisayansi (pana) Scientific (narrow) Kisayansi (nyembamba) Apply Tekeleza Row Safu mlalo Column Safu wima Label Lebo Behavior Tabia Text Maandishi DiagnosticsDialog App Diagnostics Uchunguzi wa Programu Copy to Clipboard Nakili kwenye Ubao wa Kunakili Editor Unit Kipimo User unit Kipimo cha mtumiaji User function Chaguo la kukokotoa la mtumiaji Argument Hoja Current result:<br/>%1 Matokeo ya sasa:<br/>%1 Selection result:<br/>%1 Matokeo ya uteuzi:<br/>%1 Selection result: n/a Matokeo ya chaguo: hayapo Selection result: %1 Matokeo ya chaguo: %1 second sekunde metre mita kilogram kilogramu mole moli radian radiani steradian steradiani degree Celsius nyuzi Selsiasi cubic metre mita ya ujazo cubic millimetre milimita ya ujazo cubic centimetre sentimita ya ujazo cubic decimetre desimita ya ujazo cubic kilometre kilomita ya ujazo square millimetre milimita ya mraba square kilometre kilomita ya mraba square metre mita ya mraba minute dakika hour saa day siku astronomical unit kipimo cha astronomia degree nyuzi arcminute dakika ya tao arcsecond sekunde ya tao milliarcsecond milisekunde ya tao microarcsecond mikrosekunde ya tao hectare hekta litre lita tonne tani Dalton Daltoni electronvolt elektronivolti Angstrom Angstromi atmosphere angahewa atomic mass unit kipimo cha misa ya atomiki British thermal unit kipimo cha joto cha Uingereza calorie kalori carat karati cup kikombe cup (Imperial) kikombe (Imperial) cup (Japanese) kikombe (Kijapani) cup (US) kikombe (Marekani) degree Fahrenheit nyuzi Fahrenheit fathom fathomu fluid ounce (Imperial) aunsi ya majimaji (Imperial) fluid ounce (US) aunsi ya majimaji (Marekani) fluid dram (Imperial) dramu ya majimaji (Imperial) fluid dram (US) dramu ya majimaji (Marekani) foot futi square foot futi ya mraba cubic foot futi ya ujazo gallon (Imperial) galoni (Imperial) gallon (US) galoni (Marekani) gill (Imperial) gili (Imperial) gill (US) gili (Marekani) gradian gradiani grain greni gram gramu Hartley Hartley Hartree energy unit kipimo cha nishati cha Hartree horsepower nguvu-farasi inch inchi square inch inchi ya mraba cubic inch inchi ya ujazo karat karati knot noti lightminute dakika-mwanga lightsecond sekunde-mwanga lightyear mwaka-mwanga long ton tani ndefu mile maili square mile maili ya mraba cubic mile maili ya ujazo mile per hour maili kwa saa kilometre per hour kilomita kwa saa nautical mile maili ya baharini ounce aunsi parsec parseki pint (Imperial) painti (Imperial) pint (US) painti (Marekani) pound pauni pounds per square inch pauni kwa inchi ya mraba quart (Imperial) kwati (Imperial) quart (US) kwati (Marekani) oil barrel pipa la mafuta beer barrel (US) pipa la bia (Marekani) square yard yadi ya mraba cubic yard yadi ya ujazo short ton tani fupi tablespoon kijiko kikubwa tablespoon (Australian) kijiko kikubwa (Australia) tablespoon (Imperial) kijiko kikubwa (Imperial) tablespoon (US) kijiko kikubwa (Marekani) dessert spoon kijiko cha kitindamlo teaspoon kijiko kidogo teaspoon (Imperial) kijiko kidogo (Imperial) teaspoon (US) kijiko kidogo (Marekani) turn mzunguko revolution mzunguko kamili revolution per minute mizunguko kwa dakika week wiki kilowatt hour kilowati saa millimetre of mercury milimita ya zebaki yard yadi Julian century karne ya Juliani Julian year mwaka wa Juliani sidereal year mwaka wa nyota tropical year mwaka wa tropiki Evaluator cannot operate on a NaN haiwezi kufanya kazi kwenye NaN underflow - tiny result is out of SpeedCrunch's number range underflow - matokeo madogo yako nje ya masafa ya nambari ya SpeedCrunch overflow - huge result is out of SpeedCrunch's number range overflow - matokeo makubwa yako nje ya masafa ya nambari ya SpeedCrunch division by zero mgawanyiko kwa sifuri overflow - logic result exceeds maximum of 256 bits overflow - matokeo ya mantiki yanazidi kiwango cha juu cha biti 256 overflow - integer result exceeds maximum limit for integers overflow - matokeo ya nambari kamili yanazidi kikomo cha juu kwa nambari kamili too time consuming - computation was rejected inachukua muda mwingi mno - hesabu imekataliwa dimension mismatch - quantities with different dimensions cannot be compared, added, etc. kutolingana kwa vipimo - kiasi chenye vipimo tofauti haviwezi kulinganishwa, kujumlishwa, n.k. invalid dimension - operation might require dimensionless arguments kipimo si sahihi - operesheni inaweza kuhitaji hoja zisizo na kipimo operation is not defined for these arguments operesheni haijafafanuliwa kwa hoja hizi Computation aborted - encountered numerical instability Ukokotoaji umesitishwa - kutotulia kwa kihesabu kumekutwa wrong number of arguments idadi isiyo sahihi ya hoja does not take NaN as an argument haikubali NaN kama hoja result out of range matokeo yako nje ya masafa undefined for argument domain haijafafanuliwa kwa eneo la hoja computation too expensive ukokotoaji ni ghali mno invalid dimension - function might require dimensionless arguments kipimo si sahihi - chaguo la kukokotoa linaweza kuhitaji hoja zisizo na kipimo internal error, please report a bug hitilafu ya ndani, tafadhali ripoti hitilafu error hitilafu invalid expression usemi si sahihi syntax error hitilafu ya sintaksia conversion target must be a unit lengo la ubadilishaji lazima liwe kipimo unit must not be zero kitengo hakipaswi kuwa sifuri Conversion failed - dimension mismatch Ubadilishaji umeshindwa - vipimo havilingani unknown function or variable chaguo la kukokotoa au kigeu kisichojulikana unknown unit kipimo kisichojulikana recursion not supported rekesheni haitumiki %1 is a reserved name, please choose another %1 ni jina lililohifadhiwa, tafadhali chagua lingine %1 is a global user definition and cannot be overridden in this session. %1 ni ufafanuzi wa jumla wa mtumiaji na hauwezi kubatilishwa katika kikao hiki. %1 is a variable name, please choose another or delete the variable %1 ni jina la kigeu, tafadhali chagua lingine au futa kigeu argument %1 is used more than once hoja %1 imetumika zaidi ya mara moja %1 is a built-in unit name, please choose another %1 ni jina la kipimo kilichojengwa ndani, tafadhali chagua jingine %1 is a user function name, please choose another or delete the function %1 ni jina la chaguo la kukokotoa la mtumiaji, tafadhali chagua lingine au futa chaguo la kukokotoa FunctionRepo max; trials; probability kiwango cha juu; majaribio; uwezekano trials; probability majaribio; uwezekano hits; trials; probability mipigo; majaribio; uwezekano unix_timestamp; x hours offset to GMT muhuri_wa_muda_wa_unix; x saa za utofauti na GMT max; total; hits; trials kiwango cha juu; jumla; mipigo; majaribio total; hits; trials jumla; mipigo; majaribio count; total; hits; trials idadi; jumla; mipigo; majaribio dividend; divisor gawanyo; kigawanyaji x; exponent_bits; significand_bits [; exponent_bias] x; biti_za_kipeo; biti_za_signifikandi [; upendeleo_wa_kipeo] base; x msingi; x value; modulo thamani; modulo base; exponent; modulo msingi; kipeo; modulo events; average_events matukio; wastani_wa_matukio average_events wastani_wa_matukio x [; precision] x [; usahihi] Absolute Value Thamani Kamili Absolute Deviation Mkengeuko Kamili Arc Cosine Kosini ya Tao Logical AND NA ya kimantiki Area Hyperbolic Cosine Kosinasi ya hiperboliki kinyume Area Hyperbolic Sine Sinasi ya hiperboliki kinyume Area Hyperbolic Tangent Tanjenti ya hiperboliki kinyume Arc Sine Sinasi ya tao Arc Tangent Tanjenti ya tao Arc Tangent with two Arguments Tanjenti ya tao yenye hoja mbili Average (Arithmetic Mean) Wastani (wastani wa hesabu) Convert to Binary Representation Badilisha kuwa uwakilishi wa binary Binomial Cumulative Distribution Function Chaguo la usambazaji limbikizi la binomia Binomial Distribution Mean Wastani wa usambazaji wa binomia Binomial Probability Mass Function Chaguo la uzito wa uwezekano la binomia Binomial Distribution Variance Tofauti ya usambazaji wa binomia Cube Root Mzizi wa tatu Complex Conjugate Konjugati changamano Cosine Kosini Hyperbolic Cosine Kosini ya hiperboliki Cotangent Kotanjenti Cosecant Kosekanti Convert Unix timestamp to Date Badilisha muhuri wa muda wa Unix kuwa tarehe Convert to Decimal Representation Badilisha kuwa uwakilishi wa desimali Degrees of Arc Digrii za tao Error Function Chaguo la hitilafu Complementary Error Function Chaguo la hitilafu linalokamilisha Exponential Eksponenshali Arithmetic Hesabu Chemistry Kemia Complex Namba changamano Combinatorics Kombinatoriki Probability Uwezekano Statistics Takwimu Aggregation Ujumlishaji Random Nasibu Base conversion Ubadilishaji wa msingi Number formatting Uundaji wa muundo wa namba Integer arithmetic Hesabu ya namba kamili Special functions Vitendakazi maalum Exponential & Logarithmic Eksponensheli & logaridhimu Angle conversion Ubadilishaji wa pembe Trigonometry Trigonometria Bitwise Kibitwise Floating point Nukta inayoelea Date & Time Tarehe & wakati Linear algebra Aljebra mstari yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; x saa tofauti na GMT [digits] [tarakimu] max [; min] kiwango cha juu [; kiwango cha chini] List Literal Literal ya orodha Convert to Padded Binary Representation Badilisha kuwa uwakilishi wa binari wenye vijazio Round Toward +∞ (Ceiling) Zungusha kuelekea +∞ (dari) Cosine plus Imaginary Sine Kosaini pamoja na saini ya kufikirika Convert to Cis Complex Form Badilisha kuwa umbo changamano la cis Matrix Column Count Idadi ya safu wima za matriki Population Correlation Matrix (n) Matriki ya uwiano wa populasheni (n) Sample Correlation Matrix (n-1) Matriki ya uwiano wa sampuli (n-1) Count Hesabu Population Covariance Matrix (n) Matriki ya kovariansia ya populasheni (n) Sample Covariance Matrix (n-1) Matriki ya kovariansia ya sampuli (n-1) Cross Product Zao la msalaba Convert Date to Unix timestamp Badilisha tarehe kuwa muhuri wa muda wa Unix Determinant Determinanti Convert to Sexagesimal Notation Badilisha kuwa nukuu ya seksajisimali Dot Product Zao nukta Convert to Engineering Notation Badilisha kuwa nukuu ya kihandisi Convert to Exponential Complex Form Badilisha kuwa umbo changamano la eksponensheli Round Toward −∞ (Floor) Zungusha kuelekea −∞ (sakafu) Flatten Matrix Fanya matriki kuwa bapa Fractional Part Sehemu ya kasoro Extension of Factorials [= (x-1)!] Upanuzi wa faktoriali [= (x-1)!] Greatest Common Divisor Kigawanyaji kikuu cha pamoja Least Common Multiple Kizidisho cha pamoja kidogo zaidi Geometric Mean Wastani wa jiometri Gradians of arc Gradiani za tao Convert to Hexadecimal Representation Badilisha kuwa uwakilishi wa hexadesimali Convert to Padded Hexadecimal Representation Badilisha kuwa uwakilishi wa heksadesimali wenye vijazio Hypergeometric Cumulative Distribution Function Chaguo la usambazaji limbikizi la hiperjiometriki Hypergeometric Distribution Mean Wastani wa usambazaji wa hiperjiometriki Hypergeometric Probability Mass Function Chaguo la uzito wa uwezekano la hiperjiometriki Hypergeometric Distribution Variance Tofauti ya usambazaji wa hiperjiometriki Integer Quotient Mgawo wa nambari kamili Integer Part Sehemu ya nambari kamili Imaginary Part Sehemu ya kufikirika Inverse Matrix Matriki kinyume Decode IEEE-754 Binary Value Fumbua thamani ya binary ya IEEE-754 Encode IEEE-754 Binary Value Simbika thamani ya binary ya IEEE-754 Decode 16-bit Half-Precision Value Fumbua thamani ya biti-16 ya usahihi nusu Encode 16-bit Half-Precision Value Simbika thamani ya biti-16 ya usahihi nusu Decode 32-bit Single-Precision Value Fumbua thamani ya biti-32 ya usahihi mmoja Encode 32-bit Single-Precision Value Simbika thamani ya biti-32 ya usahihi mmoja Decode 64-bit Double-Precision Value Fumbua thamani ya biti-64 ya usahihi maradufu Encode 64-bit Double-Precision Value Simbika thamani ya biti-64 ya usahihi maradufu Decode 128-bit Quad-Precision Value Fumbua thamani ya biti-128 ya usahihi mara nne Encode 128-bit Quad-Precision Value Simbika thamani ya biti-128 ya usahihi mara nne Round to 16-bit Half-Precision Value Zungusha hadi thamani ya biti 16 ya usahihi nusu Round to 32-bit Single-Precision Value Zungusha hadi thamani ya biti 32 ya usahihi mmoja Round to 64-bit Double-Precision Value Zungusha hadi thamani ya biti 64 ya usahihi maradufu Round to 128-bit Quad-Precision Value Zungusha hadi thamani ya biti 128 ya usahihi wa quad Residual from 16-bit Half-Precision Rounding Salio la kuzungusha kwa biti 16 kwa usahihi nusu Residual from 32-bit Single-Precision Rounding Salio la kuzungusha kwa biti 32 kwa usahihi mmoja Residual from 64-bit Double-Precision Rounding Salio la kuzungusha kwa biti 64 kwa usahihi maradufu Residual from 128-bit Quad-Precision Rounding Salio la kuzungusha kwa biti 128 kwa usahihi wa quad Binary Logarithm Logaridhimu ya binary Common Logarithm Logaridhimu ya kawaida Natural Logarithm Logaridhimu asilia Substance Mass Misa ya dutu Molarity Molariti Molar Mass Misa ya mola Logarithm to Arbitrary Base Logaridhimu kwa msingi wowote Median Absolute Deviation Mkengeuko kamili wa mediana Mask to a bit size Barakoa kwa ukubwa wa biti Maximum Kiwango cha juu Median Value (50th Percentile) Thamani ya kati (asilimia 50) Mean Wastani Minimum Kiwango cha chini Numerical Value of Quantity Thamani ya kinamba ya kiasi Random Decimal Number Namba desimali ya nasibu Random Integer Number Namba kamili ya nasibu Convert to Rational Representation Badilisha kuwa uwakilishi wa rasyonali Modulo Modulo Euclidean Modulo Modulo ya Euclid Modular Exponentiation Eksponentiesheni ya modulo Combination (Binomial Coefficient) Mchanganyiko (koefishenti ya binomia) Logical NOT SIO ya kimantiki Permutation (Arrangement) Permutiesheni (mpangilio) Convert to Octal Representation Badilisha kuwa uwakilishi wa oktali Convert to Padded Octal Representation Badilisha kuwa uwakilishi wa oktali wenye vijazio Vector or Matrix Norm Normu ya vekta au matriki Logical OR AU ya kimantiki Population Count (Hamming Weight) Idadi ya biti moja (uzito wa Hamming) Phase of Complex Number Fazi ya nambari changamano Poissonian Cumulative Distribution Function Chaguo la usambazaji limbikizi la Poisson Poissonian Distribution Mean Wastani wa usambazaji wa Poisson Poissonian Probability Mass Function Chaguo la uzito wa uwezekano la Poisson Poissonian Distribution Variance Tofauti ya usambazaji wa Poisson Convert to Phasor Complex Form Badilisha kuwa umbo changamano la fasori Convert to Rectangular Complex Form Badilisha kuwa umbo changamano la mstatili Round Half Away from Zero Zungusha nusu mbali na sifuri Round Half Even Zungusha nusu hadi jozi Nth Root Mzizi wa Daraja la N Convert to Scientific Notation Badilisha kuwa nukuu ya kisayansi Matrix Row Count Idadi ya safu mlalo za matriki List or Matrix Shape Umbo la orodha au matriki Summation Ujumlishaji Population Standard Deviation (n) Mkengeuko sanifu wa populasheni (n) Sample Standard Deviation (n-1) Mkengeuko sanifu wa sampuli (n-1) Round Toward Zero (Truncation) Zungusha kuelekea sifuri (ukataji) Matrix Trace Trasi ya matriki Transpose Matrix Geuza matriki Population Variance (n) Variansia ya populasheni (n) Sample Variance (n-1) Variansia ya sampuli (n-1) Product Bidhaa Radians Radiani Matrix Rank Cheo cha matriki Real Part Sehemu halisi Secant Sekanti Arithmetic Shift Left Hamisho la hesabu kushoto Arithmetic Shift Right Hamisho la hesabu kulia Signum Ishara Sine Sinasi Hyperbolic Sine Sinasi ya hiperboliki Square Root Mzizi wa mraba Sum Jumla Tangent Tanjenti Convert to Trigonometric Complex Form Badilisha kuwa umbo changamano la trigonometria Turns Mizunguko Hyperbolic Tangent Tanjenti ya hiperboliki Sign-extend a value Panua ishara ya thamani Logical XOR XOR ya kimantiki FunctionsWidget Domain Kikoa All Zote Identifier Kitenzi Name Jina Search Tafuta No match found Hakuna kinacholingana kilichopatikana HistoryWidget Remove All Calculations Above Ondoa hesabu zote zilizo juu Remove This Calculation Ondoa ukokotoaji huu Remove All Calculations Below Ondoa hesabu zote zilizo chini Keypad Inverse cosine Kosini kinyume The last result Matokeo ya mwisho Inverse sine Sinasi kinyume Inverse tangent Tanjenti kinyume Evaluate expression Tathmini usemi Division Ugawaji Multiplication Kuzidisha Subtraction Kutoa Addition Kuongeza Clear expression Futa usemi Cosine Kosini Backspace Futa nyuma Scientific notation Nukuu ya kisayansi Exponential Eksponenshali Factorial Faktoriali Natural logarithm Logaridhimu asilia Left parenthesis Parentesi ya kushoto Nth root Mzizi wa Daraja la N Argument separator Kitenganishi cha hoja Square Mraba Common logarithm Logaridhimu ya kawaida Modulo Modulo Contextual percentage Asilimia ya kimuktadha Power Nguvu Right parenthesis Parentesi ya kulia Sine Sinasi Square root Mzizi wa mraba Tangent Tanjenti Pi Pi Decimal separator Kitenganishi cha desimali MainWindow Radian Radiani Gradian Gradiani Degree Digrii Binary Binari Octal Oktali Hexadecimal Hexadesimali Sexagesimal Seksajisimali Engineering decimal Desimali ya kihandisi Scientific decimal Desimali ya kisayansi Plain &text Maandishi ya kawaid&a &Import... &Leta... &Quit &Toka Clear E&xpression Futa Us&emi Clear &History Futa &Historia &Copy &Nakili &Paste &Bandika &Select Expression &Chagua Usemi &Constants &Konstanti &Functions &Chaguo za kukokotoa &History &Historia &Keypad &Kibodi ya nambari Formula &Book Ki&tabu cha fomula New &Private Tab Kichu&po Kipya cha Faragha Keep Hifadhi Make Private... Fanya ya Faragha... &Rename... &Badili Jina... Clo&ne... Te&ngeneza Nakala... &Close Tab Funga Ki&chupo Reopen Clo&sed Tab F&ungua Tena Kichupo Kilichofungwa &Undo Tend&ua &Redo &Rudia Cu&t Ka&ta Copy &Last Result Naki&li Matokeo ya Mwisho &Wrap in Parentheses &Weka Ndani ya Mabano Full Scr&een Mode H&ali ya Skrini Nzima &Status Bar &Mwambaa wa hali Bitfield Uga wa biti &Left &Kushoto &Right K&ulia &Up &Juu &Down &Chini Close Pa&ne Fu&nga kidirisha Use&r Functions Chaguo za kukokotoa za &mtumiaji &Degree &Digrii &Radian &Radiani &Gradian &Gradiani Re&volution M&zunguko kamili Always on &Top Daima Juu &Kabisa Auto-Insert a&ns I&ngiza ans Kiotomatiki Automatic &Completion Ukamilishaji &Kiotomatiki &Built-in Functions &Chaguo za Kukokotoa Vilivyojengewa Ndani Built-in &Variables V&igeu Vilivyojengewa Ndani User &Functions C&haguo za kukokotoa za mtumiaji User Va&riables Vi&geu vya mtumiaji Open a Private Tab on Startup Fungua Kichupo cha Faragha Wakati wa Kuanza Open and focus a new private tab whenever SpeedCrunch starts. Fungua kichupo kipya cha faragha na ukilenge kila SpeedCrunch inapoanza. Syntax &Highlighting Kuangazia &Sintaksia Group Digits in &Input Panga Tarak&imu za Ingizo katika Makundi Automatic Input &Adjustments M&arekebisho ya Ingizo ya Kiotomatiki Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Rekebisha viendeshaji, nafasi, mabano na vipeo kiotomatiki, na uruhusu kuingiza vibambo halali pekee. Group input digits using the selected number format. Panga tarakimu za ingizo katika makundi kulingana na umbizo la namba lililochaguliwa. &Blinking Cursor Ki&shale Kinachopepesa Blink the cursor in the expression editor. Fanya kishale kipepese katika kihariri cha misemo. &Escape Clears Editor &Escape Husafisha Kihariri Clear the focused expression editor with Escape after dismissing any popup or preview. Safisha kihariri cha misemo kinacholengwa kwa Escape baada ya kufunga madirisha ibukizi au mwonekano wa awali. Disabled Imezimwa Small Space Nafasi ndogo Medium Space Nafasi ya kati Large Space Nafasi kubwa Keep Expression After Evaluation Weka Msemo Baada ya Kukokotoa Copy New Results Automatically Nakili Matokeo Mapya Kiotomatiki &Comma &Koma &System Default Chaguo-msingi la &Mfumo &Dot &Nukta Dot &And Comma Nukta &Na Koma &0 Digits &Tarakimu 0 &15 Digits &Tarakimu 15 &2 Digits &Tarakimu 2 &3 Digits &Tarakimu 3 &50 Digits &Tarakimu 50 &8 Digits &Tarakimu 8 Toward +∞ (&ceil) Kuelekea +∞ (&ceil) Toward −∞ (&floor) Kuelekea −∞ (&floor) &Automatic &Kiotomatiki &Engineering &Kihandisi &Scientific &Kisayansi &Binary &Binari &Octal &Oktali &Hexadecimal &Hexadesimali &Sexagesimal &Seksajisimali &Font... &Fonti... Reset All Settings... Weka Upya Mipangilio Yote... &System &Mfumo SpeedCrunch &Theme M&andhari ya SpeedCrunch &Classic &Ya Kawaida &Modern Y&a Kisasa &Language... &Lugha... User &Manual Mwongozo wa &Mtumiaji Context Help Msaada wa Muktadha Issues and &Feedback M&atatizo na Maoni &Donate &Changia Editor and Results Font Fonti ya Kihariri na Matokeo &Session &Kikao &Export &Hamisha &Edit &Hariri &View &Tazama S&plit &Gawanya Se&ttings Ma&mpangilio &Decimal &Desimali &Precision &Usahihi Angle &Mode &Hali ya Pembe &Complex Form Umbo la Namba &Changamani &Help &Msaada New Tab Kichupo kipya Constants Konstanti Functions Chaguo za kukokotoa History Historia User Functions Chaguo za kukokotoa za mtumiaji Error Hitilafu Can't read from file %1 Haiwezi kusoma kutoka faili %1 Can't write to file %1 Haiwezi kuandika kwenye faili %1 Import Session Leta Kikao Close Session Funga kikao Angle Mode: Hali ya pembe: Notation: Nukuu: Precision: Usahihi: Turn Mzunguko Revolution Mzunguko kamili Fixed-point decimal Desimali ya nukta isiyohama Rational Rasyonali Automatic decimal Desimali otomatiki Automatic Otomatiki User &Definitions... &Fafanuzi za mtumiaji... New &Tab &Kichupo kipya New &Window Dirisha &jipya &Open... &Fungua... Open Sessions &Folder Fungua &folda ya vikao &Basic &Msingi &Scientific (wide) &Kisayansi (pana) Scientific (narrow) Kisayansi (nyembamba) &Custom... &Maalum... Main &Menu &Menyu kuu User &Variables &Vigeu vya mtumiaji User &Units &Vipimo vya mtumiaji &Turn &Mzunguko If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Ikiwa usemi mpya unaanza na +, -, *, au /, SpeedCrunch huingiza "ans" kwanza. &Accept with Enter &Kubali kwa Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Kubali pendekezo la sasa la ukamilishaji otomatiki kwa Enter bila kulichagua kwanza kwa vitufe vya mishale. &Units &Vipimo Show Live Result &Preview Onyesha &hakikisho la matokeo moja kwa moja Save &Window Position on Exit Hifadhi &nafasi ya dirisha wakati wa kutoka Hover Highlighting Kuangazia unapoelea juu Group Integer Part Only Panga sehemu kamili pekee Number Format... Muundo wa namba... Notation && Precision... Nukuu && usahihi... After pressing Enter, keep the entered expression selected in the editor. Baada ya kubonyeza Enter, bakiza usemi uliowekwa ukiwa umechaguliwa kwenye kihariri. Never Kamwe Always Daima Only for Single-Line Expressions Kwa semi za mstari mmoja pekee Simplify Displayed Expressions Rahisisha semi zinazoonyeshwa History Size &Limit... &Kikomo cha ukubwa wa historia... Remove Trailing &Zeroes Ondoa Sifuri &za Mwishoni Nearest, Half &Away (round) Karibu zaidi, nusu &mbali na sifuri (round) Nearest, Half &Even (roundeven) Karibu zaidi, nusu &jozi (roundeven) Toward &Zero (trunc) Kuelekea &sifuri (trunc) &Fixed-Point Nukta &isiyohama &Rational &Rasyonali &Exponential (m·sâ�»Â¹) &Eksponensheli (m·sâ�»Â¹) &Fractional (m/s) &Kisehemu (m/s) &Rectangular (a + bi) &Mstatili (a + bi) Exponential (reâ�±á¶¿) Eksponensheli (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometria (r(cos θ + i·sin θ)) Phasor (r∠θ) Fasori (r∠θ) &Theme... &Mandhari... Check for &Updates Kagua &masasisho Source Code Msimbo chanzo &Zoom &Kuza &Results &Matokeo Unit Notation Nukuu ya vipimo Rounding Mode Hali ya kuzungusha &Notation &Nukuu &Imaginary Unit Kipimo cha &kufikirika &Window &Dirisha &Editing &Uhariri A&utocomplete Kukamilisha &kiotomatiki Up/Down Arrow History Historia kwa vishale vya juu/chini &Appearance &Mwonekano &Menus M&enyu &Docks &Paneli Zinazoweza Kupachikwa &Input and Results &Ingizo na Matokeo &Disabled &Imezimwa &Disable &Zima Close preview Funga hakikisho Rename... Badili Jina... Clone... Tengeneza Nakala... Close Tab Funga Kichupo New Private Tab Kichupo Kipya cha Faragha Open... Fungua... Reopen Closed Tab Fungua Tena Kichupo Kilichofungwa Split Gawanya Left Kushoto Right Kulia Up Juu Down Chini Clear Safisha Delete Futa %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Kikao cha faragha: maudhui hutupwa kinapofungwa. Chagua Kikao > Hifadhi ili kukibadilisha kuwa kikao cha kawaida. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Faragha] Reset All Settings Weka Upya Mipangilio Yote Reset all settings to their default values? Weka upya mipangilio yote kwenye thamani zake chaguomsingi? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Hii inajumuisha mwonekano, uhariri, maumbizo ya matokeo na mapendeleo ya madirisha. Hesabu zako, vikao vilivyo wazi na fasili za mtumiaji zitahifadhiwa. The settings file could not be written. Faili la mipangilio halikuweza kuandikwa. Clear this session's calculations, unfinished expression, variables, functions, and units? Safisha hesabu, msemo ambao haujakamilika, vigeu, chaguo za kukokotoa na vipimo vya kikao hiki? Global user definitions are kept. Fasili za jumla za mtumiaji zinahifadhiwa. Make Session Private Fanya Kikao kuwa cha Faragha The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Kikao kilichohifadhiwa %1 kitafutwa. Maudhui yake yataendelea kuwa wazi katika kikao cha faragha na yatatupwa kikao hicho kinapofungwa au SpeedCrunch inapotoka. Make Private Fanya ya Faragha Could not delete the saved session %1. Haikuweza kufuta kikao kilichohifadhiwa %1. Keep Session Hifadhi Kikao Could not save the session. It remains private. Haikuweza kuhifadhi kikao. Kinaendelea kuwa cha faragha. Clone Session Tengeneza Nakala ya Kikao Could not save session file %1. Haikuweza kuhifadhi faili la kikao %1. Could not delete session file %1. Haikuweza kufuta faili la kikao %1. JSON file (*.json);;Any file (*.*) Faili ya JSON (*.json);;Faili yoyote (*.*) Export session as JSON Hamisha kikao kama JSON The selected file is not valid JSON: %1 Faili iliyochaguliwa si JSON halali: %1 The selected file is not a SpeedCrunch session JSON file. Faili iliyochaguliwa si faili ya JSON ya kikao cha SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Faili hii inatumia umbizo la zamani la kikao cha SpeedCrunch na haiwezi kuletwa. The selected JSON file is missing the required $schema field. Faili ya JSON iliyochaguliwa haina sehemu inayohitajika ya $schema. The selected JSON file uses an unsupported JSON schema: %1 Faili ya JSON iliyochaguliwa inatumia skimu ya JSON isiyotumika: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Faili ya JSON iliyochaguliwa haina kitambulisho cha skimu ya kikao cha SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Faili ya JSON iliyochaguliwa inatumia umbizo la kikao cha SpeedCrunch lisilotumika: %1 The selected JSON file is missing the required session name. Faili ya JSON iliyochaguliwa haina jina la kikao linalohitajika. The selected JSON file has an empty session name. Faili ya JSON iliyochaguliwa ina jina tupu la kikao. The selected JSON file has invalid or incomplete SpeedCrunch session data. Faili ya JSON iliyochaguliwa ina data batili au isiyokamilika ya kikao cha SpeedCrunch. Open Sessions Folder Fungua folda ya vikao Could not create the sessions folder: %1 Haikuweza kuunda folda ya vikao: %1 Could not open the sessions folder: %1 Haikuweza kufungua folda ya vikao: %1 Open Session Fungua kikao Community Jumuiya Rename Session Badili jina la kikao Clear Session Futa yaliyomo ya kikao Delete Session Futa kikao Close Pane Funga kidirisha &About SpeedCrunch &Kuhusu SpeedCrunch App Diag&nostics Uchu&nguzi wa Programu User Variables Vigeu vya mtumiaji User Units Vipimo vya mtumiaji Clear History Futa historia Are you sure you want to clear the calculation history? Una uhakika unataka kufuta historia ya hesabu? Session name: Jina la kikao: A session named %1 already exists. Kikao kinachoitwa %1 tayari kipo. Could not create session file %1. Haikuwezekana kuunda faili ya kikao %1. Could not write session file %1. Haikuwezekana kuandika faili ya kikao %1. Are you sure you want to delete this session? Una uhakika unataka kufuta kikao hiki? Custom Precision Usahihi maalum Fractional digits: Tarakimu za sehemu: Theme Mandhari Light Themes Mandhari mepesi Dark Themes Mandhari meusi Preview Hakikisho Colors Rangi Select color for %1 Chagua rangi ya %1 Import... Leta... Export... Hamisha... Import Theme Leta mandhari Theme file (*.json);;All files (*) Faili ya mandhari (*.json);;Faili zote (*) Invalid theme file. Faili ya mandhari si sahihi. Can't import theme "%1" because it conflicts with a built-in theme. Haiwezi kuleta mandhari "%1" kwa sababu inakinzana na mandhari iliyojengwa ndani. Can't find a writable theme folder. Haiwezi kupata folda ya mandhari inayoweza kuandikwa. Overwrite Theme Andika juu ya mandhari A custom theme named "%1" already exists. Do you want to overwrite it? Mandhari maalum inayoitwa "%1" tayari ipo. Unataka kuiandika juu yake? Can't overwrite theme file %1 Haiwezi kuandika juu ya faili ya mandhari %1 Can't copy theme file to %1 Haiwezi kunakili faili ya mandhari kwenda %1 Export Theme Hamisha mandhari Can't export theme as "%1" because it conflicts with a built-in theme. Haiwezi kuhamisha mandhari kama "%1" kwa sababu inakinzana na mandhari iliyojengwa ndani. Global User Variable Kigeu cha jumla cha mtumiaji Global User Function Kitendakazi cha jumla cha mtumiaji Global User Unit Kipimo cha jumla cha mtumiaji User Definitions Ufafanuzi wa Mtumiaji These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Ufafanuzi huu ni wa jumla na hupakiwa katika kila kipindi. Hauwezi kubadilishwa ndani ya vipindi na una kipaumbele kuliko ufafanuzi wenye majina sawa kutoka kwenye kihariri cha kipindi. Ingiza ufafanuzi mmoja kwa kila mstari. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Mifano: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Tekeleza Validate Thibitisha Test Results Matokeo ya Jaribio Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Vigeu vilivyoingizwa: %1 Vitendakazi vilivyoingizwa: %2 Vipimo vilivyoingizwa: %3 Nambari za mistari yenye makosa: %4 none hakuna Apply Results Matokeo ya Utekelezaji User definitions saved. Ufafanuzi wa mtumiaji umehifadhiwa. History Size Limit Kikomo cha ukubwa wa historia Maximum number of history entries for this session (0 = unlimited): Idadi ya juu ya vipengee vya historia kwa kikao hiki (0 = bila kikomo): Export session as HTML Hamisha kikao kama HTML HTML file (*.html) Faili ya HTML (*.html) Export session as plain text Hamisha kikao kama maandishi ya kawaida Text file (*.txt);;Any file (*.*) Faili ya maandishi (*.txt);;Faili yoyote (*.*) Could not recalculate from calculation %1: %2 Haikuwezekana kukokotoa upya kuanzia hesabu %1: %2 History Size Limit Reached Kikomo cha ukubwa wa historia kimefikiwa This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Hesabu hii inajaza nafasi ya mwisho ya historia inayopatikana. Hesabu za baadaye zitaondoa hesabu ya zamani zaidi kutoka historia. Unaweza kuongeza kikomo kutoka Kikao > Kikomo cha ukubwa wa historia. Editing calculation. Press Esc twice to cancel. Unahariri hesabu. Bonyeza Esc mara mbili ili kughairi. Calculation Settings Mipangilio ya hesabu Invalid recalculation start index Faharasa batili ya kuanzia kukokotoa upya System Default Chaguo-msingi la mfumo Language Lugha Select the language: Chagua lugha: Custom Maalum Decimal places: Nafasi za desimali: ManualWindow SpeedCrunch Manual Mwongozo wa SpeedCrunch %1 - SpeedCrunch Manual %1 - Mwongozo wa SpeedCrunch NumberFormatDialog Number Format Muundo wa namba <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Chagua umbizo la namba kwa matokeo na upangaji wa tarakimu za ingizo katika makundi.</b><br/><br/>Kumbuka: maumbizo yanayoeleweka wazi ya namba zinazoingizwa yanakubaliwa hata kama yanatofautiana na umbizo la kuonyesha lililochaguliwa.<br/> QObject Global User Variable Kigeu cha jumla cha mtumiaji Global User Function Kitendakazi cha jumla cha mtumiaji Global User Unit Kipimo cha jumla cha mtumiaji Backspace Futa nyuma Clear expression Futa usemi Evaluate expression Tathmini usemi Insert text Ingiza maandishi Automatic decimal Desimali otomatiki Fixed-point decimal Desimali ya nukta isiyohama Engineering decimal Desimali ya kihandisi Scientific decimal Desimali ya kisayansi Rational Rasyonali Binary Binari Octal Oktali Hexadecimal Heksadesimali Sexagesimal Seksajisimali Update Available Sasisho linapatikana A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Toleo jipya zaidi (%1) linapatikana.<br/><a href="%2">Tembelea tovuti ili kupakua.</a> Check for Updates Kagua masasisho SpeedCrunch %1 is up to date. SpeedCrunch %1 imesasishwa. No connectivity. Please check your internet connection and try again. Hakuna muunganisho. Tafadhali kagua muunganisho wako wa intaneti na ujaribu tena. Could not verify the latest available version. Haikuwezekana kuthibitisha toleo jipya zaidi linalopatikana. ResultDisplay Scroll to bottom Sogeza hadi chini Edit Expression Hariri usemi Change Settings Badili mipangilio New Tab Kichupo kipya &Import... &Leta... &Export &Hamisha Plain &text Maandishi ya &kawaida Copy Nakili Selection Uteuzi Select All Chagua Yote Expression Msemo Result Matokeo Calculation Hesabu Calculation as Single Line Hesabu katika Mstari Mmoja Remove Ondoa This Calculation Hesabu Hii All Calculations Above Hesabu Zote za Juu All Calculations Below Hesabu Zote za Chini New Private Tab Kichupo Kipya cha Faragha Session Kikao Open... Fungua... Clone... Tengeneza Nakala... Rename... Badili Jina... Keep Hifadhi Make Private... Fanya ya Faragha... Clear Safisha Delete Futa Close Funga Split Gawanya Left Kushoto Right Kulia Up Juu Down Chini Close Pane Funga kidirisha Main Menu Menyu kuu Cancel editing Ghairi kuhariri Copy result Nakili matokeo Edit expression Hariri usemi Change settings Badili mipangilio Remove calculation Ondoa hesabu ResultSlotsDialog Notation & Precision Nukuu & usahihi Result Line Mstari wa matokeo Enabled Imewashwa Notation Nukuu Decimal Places Nafasi za desimali Main Line Mstari mkuu Extra Line #1 Mstari wa ziada #1 Extra Line #2 Mstari wa ziada #2 Extra Line #3 Mstari wa ziada #3 Extra Line #4 Mstari wa ziada #4 Auto Otomatiki UserFunctionListWidget Name Jina Value Thamani Description Maelezo Search Tafuta No match found Hakuna kinacholingana kilichopatikana Insert Ingiza Edit Hariri Delete Futa Delete All Futa zote UserUnitListWidget Name Jina Value Thamani Description Maelezo Search Tafuta No match found Hakuna kinacholingana kilichopatikana Insert Ingiza Edit Hariri Delete Futa Delete All Futa zote VariableListWidget Name Jina Value Thamani Description Maelezo Search Tafuta No match found Hakuna kinacholingana kilichopatikana Insert Ingiza Edit Hariri Delete Futa Delete All Futa zote heldercorreia-speedcrunch-e7ca37f/src/resources/locale/ta.ts000066400000000000000000012236731526573132500243670ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunch பறà¯�றி Core developers à®®à¯�கà¯�கிய உரà¯�வாகà¯�கà¯�நரà¯�களà¯� Original author அசலà¯� ஆசிரியரà¯� Close மூடà¯� Math engine கணித இயநà¯�திரமà¯� Main author | Logo | Maintainer à®®à¯�தனà¯�மை ஆசிரியரà¯� | லோகோ | பராமரிபà¯�பாளரà¯� Thanks நனà¯�றி Copyright (C) 2004-2026 The SpeedCrunch developers பதிபà¯�பà¯�ரிமை (C) 2004-2026 SpeedCrunch உரà¯�வாகà¯�கà¯�நரà¯�களà¯� This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version இநà¯�த திடà¯�டமà¯� இலவச மெனà¯�பொரà¯�ளà¯�; இலவச மெனà¯�பொரà¯�ளà¯� அறகà¯�கடà¯�டளையாலà¯� வெளியிடபà¯�படà¯�ட கà¯�னà¯� பொதà¯� பொதà¯� உரிமதà¯�தினà¯� விதிமà¯�றைகளினà¯� கீழà¯� நீஙà¯�களà¯� அதை மறà¯�பகிரà¯�வà¯� செயà¯�யலாமà¯� மறà¯�à®±à¯�à®®à¯�/அலà¯�லதà¯� மாறà¯�றலாமà¯�; உரிமதà¯�தினà¯� பதிபà¯�பà¯� 2, அலà¯�லதà¯� (உஙà¯�களà¯� விரà¯�பà¯�பபà¯�படி) à®�தேனà¯�à®®à¯� பிநà¯�தைய பதிபà¯�பà¯� This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. இநà¯�த திடà¯�டமà¯� பயனà¯�ளà¯�ளதாக இரà¯�கà¯�கà¯�à®®à¯� எனà¯�à®± நமà¯�பிகà¯�கையிலà¯� விநியோகிகà¯�கபà¯�படà¯�கிறதà¯�, ஆனாலà¯� எநà¯�த உதà¯�தரவாதமà¯�à®®à¯� இலà¯�லாமலà¯�; à®’à®°à¯� கà¯�றிபà¯�பிடà¯�ட நோகà¯�கதà¯�திறà¯�காக வணிகமà¯� அலà¯�லதà¯� உடறà¯�தகà¯�தியினà¯� மறைமà¯�க உதà¯�தரவாதமà¯� கூட இலà¯�லாமலà¯�. மேலà¯�à®®à¯� விவரஙà¯�களà¯�கà¯�கà¯� கà¯�னà¯� பொதà¯� பொதà¯� உரிமதà¯�தைபà¯� பாரà¯�கà¯�கவà¯�à®®à¯�. BitFieldWidget Reset bits to zero பிடà¯�களை பூஜà¯�யமாக மீடà¯�டமை Invert bits பிடà¯�களை தலைகீழாகà¯�கà¯� Shift bits left பிடà¯�களை இடதà¯�பà¯�றமà¯� நகரà¯�தà¯�தà¯� Shift bits right பிடà¯�களை வலதà¯�பà¯�றமà¯� நகரà¯�தà¯�தà¯� Book Index கà¯�றியீடà¯�டà¯� Algebra இயறà¯�கணிதமà¯� Quadratic Equation இரà¯�படி சமனà¯�பாடà¯� Logarithmic Base Conversion மடகà¯�கை அடிபà¯�படை மாறà¯�றமà¯� Geometry வடிவியலà¯� Circle வடà¯�டமà¯� Sector வடà¯�டகà¯� கோணபà¯� பகà¯�தி Sphere கோளமà¯� Cube கனசதà¯�à®°à®®à¯� Cone கூமà¯�பà¯� Cylinder உரà¯�ளை Electronics மினà¯�னணà¯�வியலà¯� Ohm's Law ஓமà¯� விதி Power அடà¯�கà¯�கà¯� Reactance எதிரà¯�வினை Resonance அதிரà¯�வà¯� Radio Frequency வானொலி அதிரà¯�வெணà¯� Antennas உணரà¯�கொமà¯�பà¯�களà¯� Characteristic Impedance (coax) சிறபà¯�பியலà¯�பà¯� மினà¯�மறà¯�பà¯�பà¯� (இணையாக) Velocity of Propagation (coax) பரவலினà¯� வேகமà¯� (இணையாக) Standing Wave Ratio & Return Loss நிலையான அலை விகிதமà¯� & திரà¯�à®®à¯�ப இழபà¯�பà¯� Free Space Wavelength வெறà¯�à®±à¯� இடமà¯� அலைநீளமà¯� resistance மினà¯�எதிரà¯�பà¯�பà¯� voltage மினà¯�னழà¯�தà¯�தமà¯� current மினà¯�சாரமà¯� power சகà¯�தி inductive reactance தூணà¯�டலà¯� எதிரà¯�வினை capacitive reactance கொளà¯�ளளவà¯� எதிரà¯�வினை inductance தூணà¯�டà¯�தà¯�திறனà¯� capacitance கொளà¯�ளளவà¯� frequency அதிரà¯�வெணà¯� resonance frequency அதிரà¯�வà¯� அதிரà¯�வெணà¯� area பரபà¯�பà¯� perimeter சà¯�à®±à¯�றளவà¯� diameter விடà¯�டமà¯� radius ஆரமà¯� volume கொளà¯�ளளவà¯� surface area மேறà¯�பரபà¯�பà¯� height உயரமà¯� slant height சாயà¯�வான உயரமà¯� face diagonal à®®à¯�கமà¯� மூலைவிடà¯�டமà¯� space diagonal விணà¯�வெளி மூலைவிடà¯�டமà¯� edge length விளிமà¯�பà¯� நீளமà¯� arc length விலà¯�லினà¯� நீளமà¯� central angle (degrees) மையகà¯� கோணமà¯� (பாகை) input power உளà¯�ளீடà¯� சகà¯�தி reflected power பிரதிபலிதà¯�த சகà¯�தி transmitted power கடதà¯�தபà¯�படà¯�ட சகà¯�தி return loss திரà¯�à®®à¯�ப இழபà¯�பà¯� dielectric constant மினà¯�கடதà¯�தா மாறிலி outer conductor's inner diameter வெளிபà¯�பà¯�à®± கடதà¯�தியினà¯� உளà¯� விடà¯�டமà¯� inner conductor's outer diameter உளà¯� கடதà¯�தியினà¯� வெளிபà¯�பà¯�à®± விடà¯�டமà¯� speed of light ஒளியினà¯� வேகமà¯� reflection coefficient பிரதிபலிபà¯�பà¯� கà¯�ணகமà¯� standing wave ratio நிலையான அலை விகிதமà¯� normalized impedance இயலà¯�பாகà¯�கபà¯�படà¯�ட மினà¯�மறà¯�பà¯�பà¯� frequency (Hz) அதிரà¯�வெணà¯� (எரà¯�டà¯�சà¯�) BookDock Formula Book சூதà¯�திர பà¯�தà¯�தகமà¯� ConstantCompletion Search constants மாறிலிகளைதà¯� தேடà¯� No match found பொரà¯�தà¯�தமà¯� எதà¯�வà¯�à®®à¯� இலà¯�லை Constants Mathematics கணிதமà¯� Physics (CODATA 2022) இயறà¯�பியலà¯� (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) வேதியியலà¯� (IUPAC - CIAAW 2021) Uncategorized வகைபà¯�படà¯�தà¯�தபà¯�படாததà¯� Universal பொதà¯� Physicochemical இயறà¯�பியலà¯�-வேதியியலà¯� Atomic & Nuclear — General அணà¯� & அணà¯�கà¯�கரà¯� — பொதà¯� Atomic & Nuclear — Electroweak அணà¯� & அணà¯�கà¯�கரà¯� — மினà¯�-பலவீன Atomic & Nuclear — Electron அணà¯� & அணà¯�கà¯�கரà¯� — எலகà¯�டà¯�ரானà¯� Atomic & Nuclear — Muon அணà¯� & அணà¯�கà¯�கரà¯� — மியூயானà¯� Atomic & Nuclear — Tau அணà¯� & அணà¯�கà¯�கரà¯� — டாவà¯� Atomic & Nuclear — Proton அணà¯� & அணà¯�கà¯�கரà¯� — பà¯�ரோடà¯�டானà¯� Atomic & Nuclear — Neutron அணà¯� & அணà¯�கà¯�கரà¯� — நியூடà¯�ரானà¯� Atomic & Nuclear — Deuteron அணà¯� & அணà¯�கà¯�கரà¯� — டியூடà¯�டிரானà¯� Atomic & Nuclear — Triton அணà¯� & அணà¯�கà¯�கரà¯� — டிரிடà¯�டானà¯� Atomic & Nuclear — Helion அணà¯� & அணà¯�கà¯�கரà¯� — ஹீலியானà¯� Atomic & Nuclear — Alpha particle அணà¯� & அணà¯�கà¯�கரà¯� — ஆலà¯�பா தà¯�களà¯� Atomic & Nuclear — Atomic units அணà¯� & அணà¯�கà¯�கரà¯� — அணà¯� அலகà¯�களà¯� Atomic & Nuclear — Energy conversion relationships அணà¯� & அணà¯�கà¯�கரà¯� — ஆறà¯�றலà¯� மாறà¯�றதà¯� தொடரà¯�பà¯�களà¯� Atomic & Nuclear — X-ray units அணà¯� & அணà¯�கà¯�கரà¯� — எகà¯�ஸà¯�-கதிரà¯� அலகà¯�களà¯� Atomic & Nuclear — Magnetic shielding corrections அணà¯� & அணà¯�கà¯�கரà¯� — காநà¯�தகà¯� கவசதà¯� திரà¯�தà¯�தஙà¯�களà¯� Masses நிறைகளà¯� Lifetimes ஆயà¯�டà¯�காலஙà¯�களà¯� Molar Masses மோலாரà¯� நிறைகளà¯� Electronegativity மினà¯�எதிரà¯�மறைதà¯�தனà¯�மை Ionization Energy அயனாகà¯�க ஆறà¯�றலà¯� Nominal Constants (IAU 2015) பெயரளவà¯� மாறிலிகளà¯� (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) தறà¯�போதைய சிறநà¯�த மதிபà¯�பீடà¯�களà¯� (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) வெறà¯�றிடதà¯�தினà¯� சிறபà¯�பியலà¯�பà¯� மினà¯�தடை (Zâ‚€) reduced Planck constant (â„�) கà¯�றைகà¯�கபà¯�படà¯�ட பிளாஙà¯�கà¯� மாறிலி (â„�) vacuum electric permittivity (ϵ₀) வெறà¯�றிட மினà¯�அனà¯�மதி (ϵ₀) Newtonian constant of gravitation (G) நியூடà¯�டனிய ஈரà¯�பà¯�பà¯� மாறிலி (G) vacuum magnetic permeability (μ₀) வெறà¯�றிட காநà¯�த ஊடà¯�à®°à¯�வலà¯� (μ₀) Planck constant (h) பிளாஙà¯�கà¯� மாறிலி (h) speed of light in vacuum (c) வெறà¯�றிடதà¯�திலà¯� ஒளியினà¯� வேகமà¯� (c) standard acceleration of gravity (gâ‚™) ஈரà¯�பà¯�பினà¯� நிலையான à®®à¯�டà¯�கà¯�கமà¯� (gâ‚™) Newtonian constant of gravitation over h-bar c h-bar c-கà¯�கà¯� நியூடà¯�டனிய ஈரà¯�பà¯�பà¯� மாறிலி Planck length பிளாஙà¯�கà¯� நீளமà¯� Planck constant in eV/Hz (h) பிளாஙà¯�கà¯� மாறிலி eV/Hz இலà¯� (h) Planck mass பிளாஙà¯�கà¯� நிறை Planck mass energy equivalent in GeV பிளாஙà¯�கà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� GeV இலà¯� Planck temperature பிளாஙà¯�கà¯� வெபà¯�பநிலை Planck time பிளாஙà¯�கà¯� நேரமà¯� reduced Planck constant in eV·s (â„�) கà¯�றைகà¯�கபà¯�படà¯�ட பிளாஙà¯�கà¯� மாறிலி eV·s இலà¯� (â„�) reduced Planck constant times c in MeV·fm கà¯�றைகà¯�கபà¯�படà¯�ட பிளாஙà¯�கà¯� மாறிலி × c MeV·fm இலà¯� Bohr magneton போரà¯� மாகà¯�னெடà¯�டானà¯� conductance quantum (Gâ‚€) கடதà¯�தà¯�தà¯�திறனà¯� கà¯�வாணà¯�டமà¯� (Gâ‚€) Coulomb constant (kâ‚‘) கூலமà¯�பà¯� மாறிலி (kâ‚‘) elementary charge (e) அடிபà¯�படை மினà¯�சà¯�மை (e) elementary charge over h-bar h-bar-கà¯�கà¯� அடிபà¯�படை மினà¯�சà¯�மை conventional value of Josephson constant ஜோசபà¯�சனà¯� மாறிலியினà¯� மரபà¯� மதிபà¯�பà¯� Josephson constant ஜோசபà¯�சனà¯� மாறிலி conventional value of ampere-90 ஆமà¯�பியரà¯�-90-இனà¯� மரபà¯� மதிபà¯�பà¯� conventional value of coulomb-90 கூலமà¯�பà¯�-90-இனà¯� மரபà¯� மதிபà¯�பà¯� conventional value of farad-90 ஃபாரடà¯�-90-இனà¯� மரபà¯� மதிபà¯�பà¯� conventional value of henry-90 ஹெனà¯�றி-90-இனà¯� மரபà¯� மதிபà¯�பà¯� conventional value of ohm-90 ஓமà¯�-90-இனà¯� மரபà¯� மதிபà¯�பà¯� conventional value of volt-90 வோலà¯�டà¯�-90-இனà¯� மரபà¯� மதிபà¯�பà¯� conventional value of watt-90 வாடà¯�-90-இனà¯� மரபà¯� மதிபà¯�பà¯� magnetic flux quantum (Φ₀) காநà¯�தபà¯� பாயà¯�வà¯� கà¯�வாணà¯�டமà¯� (Φ₀) nuclear magneton அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� inverse of conductance quantum கடதà¯�தà¯�தà¯�திறனà¯� கà¯�வாணà¯�டதà¯�தினà¯� எதிரà¯�மாறà¯�à®±à¯� conventional value of von Klitzing constant வானà¯� கிளிடà¯�சிஙà¯� மாறிலியினà¯� மரபà¯� மதிபà¯�பà¯� von Klitzing constant வானà¯� கிளிடà¯�சிஙà¯� மாறிலி atomic unit of magnetic dipole moment காநà¯�த இரà¯�தà¯�à®°à¯�வ மோமெணà¯�டினà¯� அணà¯� அலகà¯� atomic unit of magnetic flux density காநà¯�தபà¯� பாயà¯�வà¯� அடரà¯�தà¯�தியினà¯� அணà¯� அலகà¯� Bohr magneton in eV/T போரà¯� மாகà¯�னெடà¯�டானà¯� eV/T இலà¯� Bohr magneton in Hz/T போரà¯� மாகà¯�னெடà¯�டானà¯� Hz/T இலà¯� Bohr magneton in inverse meter per tesla போரà¯� மாகà¯�னெடà¯�டானà¯� எதிரà¯� மீடà¯�டரà¯�/டெஸà¯�லா இலà¯� Bohr magneton in K/T போரà¯� மாகà¯�னெடà¯�டானà¯� K/T இலà¯� nuclear magneton in eV/T அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� eV/T இலà¯� nuclear magneton in inverse meter per tesla அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� எதிரà¯� மீடà¯�டரà¯�/டெஸà¯�லா இலà¯� nuclear magneton in K/T அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� K/T இலà¯� nuclear magneton in MHz/T அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� MHz/T இலà¯� Bohr radius (aâ‚€) போரà¯� ஆரமà¯� (aâ‚€) fine-structure constant (α) நà¯�ணà¯�-அமைபà¯�பà¯� மாறிலி (α) Hartree energy (Eâ‚•) ஹாரà¯�டà¯�ரீ ஆறà¯�றலà¯� (Eâ‚•) Hartree energy in eV ஹாரà¯�டà¯�ரீ ஆறà¯�றலà¯� eV இலà¯� quantum of circulation சà¯�à®±à¯�றோடà¯�ட கà¯�வாணà¯�டமà¯� quantum of circulation times 2 சà¯�à®±à¯�றோடà¯�ட கà¯�வாணà¯�டமà¯� × 2 Rydberg constant (R∞) ரிடà¯�பெரà¯�கà¯� மாறிலி (R∞) atomic mass unit-hartree relationship அணà¯� நிறை அலகà¯�-ஹாரà¯�டà¯�ரீ தொடரà¯�பà¯� atomic mass unit-hertz relationship அணà¯� நிறை அலகà¯�-ஹெரà¯�டà¯�ஸà¯� தொடரà¯�பà¯� atomic mass unit-inverse meter relationship அணà¯� நிறை அலகà¯�-எதிரà¯� மீடà¯�டரà¯� தொடரà¯�பà¯� atomic mass unit-joule relationship அணà¯� நிறை அலகà¯�-ஜூலà¯� தொடரà¯�பà¯� atomic mass unit-kelvin relationship அணà¯� நிறை அலகà¯�-கெலà¯�வினà¯� தொடரà¯�பà¯� atomic mass unit-kilogram relationship அணà¯� நிறை அலகà¯�-கிலோகிராமà¯� தொடரà¯�பà¯� atomic unit of 1st hyperpolarizability à®®à¯�தலà¯� அதி தà¯�à®°à¯�வமாதலà¯� திறனினà¯� அணà¯� அலகà¯� atomic unit of 2nd hyperpolarizability இரணà¯�டாமà¯� அதி தà¯�à®°à¯�வமாதலà¯� திறனினà¯� அணà¯� அலகà¯� atomic unit of charge (e) மினà¯�சà¯�மையினà¯� அணà¯� அலகà¯� (e) atomic unit of charge density மினà¯�சà¯�மை அடரà¯�தà¯�தியினà¯� அணà¯� அலகà¯� atomic unit of current மினà¯�னோடà¯�டதà¯�தினà¯� அணà¯� அலகà¯� atomic unit of electric dipole moment மினà¯� இரà¯�தà¯�à®°à¯�வ மோமெணà¯�டினà¯� அணà¯� அலகà¯� atomic unit of electric field மினà¯�பà¯�லதà¯�தினà¯� அணà¯� அலகà¯� atomic unit of electric field gradient மினà¯�பà¯�ல சரிவினà¯� அணà¯� அலகà¯� atomic unit of electric polarizability மினà¯� தà¯�à®°à¯�வமாதலà¯� திறனினà¯� அணà¯� அலகà¯� atomic unit of electric potential மினà¯� நிலை ஆறà¯�றலினà¯� அணà¯� அலகà¯� atomic unit of electric quadrupole moment மினà¯� நானà¯�கà¯�தà¯�à®°à¯�வ மோமெணà¯�டினà¯� அணà¯� அலகà¯� atomic unit of action செயலினà¯� அணà¯� அலகà¯� atomic unit of energy ஆறà¯�றலினà¯� அணà¯� அலகà¯� atomic unit of force விசையினà¯� அணà¯� அலகà¯� atomic unit of length நீளதà¯�தினà¯� அணà¯� அலகà¯� hertz-atomic mass unit relationship ஹெரà¯�டà¯�ஸà¯�-அணà¯� நிறை அலகà¯� தொடரà¯�பà¯� hertz-electron volt relationship ஹெரà¯�டà¯�ஸà¯�-எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� தொடரà¯�பà¯� hertz-hartree relationship ஹெரà¯�டà¯�ஸà¯�-ஹாரà¯�டà¯�ரீ தொடரà¯�பà¯� hertz-inverse meter relationship ஹெரà¯�டà¯�ஸà¯�-எதிரà¯� மீடà¯�டரà¯� தொடரà¯�பà¯� hertz-joule relationship ஹெரà¯�டà¯�ஸà¯�-ஜூலà¯� தொடரà¯�பà¯� hertz-kelvin relationship ஹெரà¯�டà¯�ஸà¯�-கெலà¯�வினà¯� தொடரà¯�பà¯� hertz-kilogram relationship ஹெரà¯�டà¯�ஸà¯�-கிலோகிராமà¯� தொடரà¯�பà¯� hyperfine transition frequency of Cs-133 Cs-133 இனà¯� ஹைபà¯�பரà¯�ஃபைனà¯� மாறà¯�à®± அதிரà¯�வெணà¯� inverse fine-structure constant (αâ�»Â¹) நà¯�ணà¯�-அமைபà¯�பà¯� மாறிலியினà¯� எதிரà¯�மாறà¯�à®±à¯� (αâ�»Â¹) inverse meter-atomic mass unit relationship எதிரà¯� மீடà¯�டரà¯�-அணà¯� நிறை அலகà¯� தொடரà¯�பà¯� inverse meter-electron volt relationship எதிரà¯� மீடà¯�டரà¯�-எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� தொடரà¯�பà¯� inverse meter-hartree relationship எதிரà¯� மீடà¯�டரà¯�-ஹாரà¯�டà¯�ரீ தொடரà¯�பà¯� inverse meter-hertz relationship எதிரà¯� மீடà¯�டரà¯�-ஹெரà¯�டà¯�ஸà¯� தொடரà¯�பà¯� inverse meter-joule relationship எதிரà¯� மீடà¯�டரà¯�-ஜூலà¯� தொடரà¯�பà¯� inverse meter-kelvin relationship எதிரà¯� மீடà¯�டரà¯�-கெலà¯�வினà¯� தொடரà¯�பà¯� inverse meter-kilogram relationship எதிரà¯� மீடà¯�டரà¯�-கிலோகிராமà¯� தொடரà¯�பà¯� joule-atomic mass unit relationship ஜூலà¯�-அணà¯� நிறை அலகà¯� தொடரà¯�பà¯� joule-electron volt relationship ஜூலà¯�-எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� தொடரà¯�பà¯� joule-hertz relationship ஜூலà¯�-ஹெரà¯�டà¯�ஸà¯� தொடரà¯�பà¯� joule-hartree relationship ஜூலà¯�-ஹாரà¯�டà¯�ரீ தொடரà¯�பà¯� joule-inverse meter relationship ஜூலà¯�-எதிரà¯� மீடà¯�டரà¯� தொடரà¯�பà¯� joule-kelvin relationship ஜூலà¯�-கெலà¯�வினà¯� தொடரà¯�பà¯� joule-kilogram relationship ஜூலà¯�-கிலோகிராமà¯� தொடரà¯�பà¯� kelvin-atomic mass unit relationship கெலà¯�வினà¯�-அணà¯� நிறை அலகà¯� தொடரà¯�பà¯� kelvin-electron volt relationship கெலà¯�வினà¯�-எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� தொடரà¯�பà¯� kelvin-hertz relationship கெலà¯�வினà¯�-ஹெரà¯�டà¯�ஸà¯� தொடரà¯�பà¯� kelvin-hartree relationship கெலà¯�வினà¯�-ஹாரà¯�டà¯�ரீ தொடரà¯�பà¯� kelvin-inverse meter relationship கெலà¯�வினà¯�-எதிரà¯� மீடà¯�டரà¯� தொடரà¯�பà¯� kelvin-joule relationship கெலà¯�வினà¯�-ஜூலà¯� தொடரà¯�பà¯� kelvin-kilogram relationship கெலà¯�வினà¯�-கிலோகிராமà¯� தொடரà¯�பà¯� kilogram-atomic mass unit relationship கிலோகிராமà¯�-அணà¯� நிறை அலகà¯� தொடரà¯�பà¯� kilogram-electron volt relationship கிலோகிராமà¯�-எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� தொடரà¯�பà¯� kilogram-hertz relationship கிலோகிராமà¯�-ஹெரà¯�டà¯�ஸà¯� தொடரà¯�பà¯� kilogram-hartree relationship கிலோகிராமà¯�-ஹாரà¯�டà¯�ரீ தொடரà¯�பà¯� kilogram-inverse meter relationship கிலோகிராமà¯�-எதிரà¯� மீடà¯�டரà¯� தொடரà¯�பà¯� kilogram-joule relationship கிலோகிராமà¯�-ஜூலà¯� தொடரà¯�பà¯� kilogram-kelvin relationship கிலோகிராமà¯�-கெலà¯�வினà¯� தொடரà¯�பà¯� lattice parameter of silicon (a) சிலிகானினà¯� படிககà¯�கடà¯�ட அளபà¯�à®°à¯� (a) luminous efficacy ஒளிதà¯�திறனà¯� natural unit of energy ஆறà¯�றலினà¯� இயறà¯�கை அலகà¯� natural unit of energy in MeV ஆறà¯�றலினà¯� இயறà¯�கை அலகà¯� MeV இலà¯� natural unit of action (â„�) செயலினà¯� இயறà¯�கை அலகà¯� (â„�) natural unit of action in eV·s செயலினà¯� இயறà¯�கை அலகà¯� eV·s இலà¯� natural unit of length நீளதà¯�தினà¯� இயறà¯�கை அலகà¯� natural unit of mass நிறையினà¯� இயறà¯�கை அலகà¯� natural unit of momentum இயகà¯�கவெகதà¯�தினà¯� இயறà¯�கை அலகà¯� natural unit of momentum in MeV/c இயகà¯�கவெகதà¯�தினà¯� இயறà¯�கை அலகà¯� MeV/c இலà¯� natural unit of time நேரதà¯�தினà¯� இயறà¯�கை அலகà¯� natural unit of velocity வேகதà¯�தினà¯� இயறà¯�கை அலகà¯� Rydberg constant times c in Hz ரிடà¯�பெரà¯�கà¯� மாறிலி × c Hz இலà¯� Rydberg constant times hc in eV ரிடà¯�பெரà¯�கà¯� மாறிலி × hc eV இலà¯� Rydberg constant times hc in J ரிடà¯�பெரà¯�கà¯� மாறிலி × hc J இலà¯� Fermi coupling constant ஃபெரà¯�மி இணைபà¯�பà¯� மாறிலி weak mixing angle பலவீன கலபà¯�பà¯� கோணமà¯� W to Z mass ratio W à®®à¯�தலà¯� Z வரை நிறை விகிதமà¯� Thomson cross section (σₑ) தாமà¯�சனà¯� கà¯�à®±à¯�கà¯�கà¯�வெடà¯�டà¯� (σₑ) electron mass (mâ‚‘) எலகà¯�டà¯�ரானà¯� நிறை (mâ‚‘) electron mass in u எலகà¯�டà¯�ரானà¯� நிறை u இலà¯� electron mass energy equivalent (mₑ·c²) எலகà¯�டà¯�ரானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� (mₑ·c²) electron mass energy equivalent in MeV எலகà¯�டà¯�ரானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� reduced Compton wavelength கà¯�றைகà¯�கபà¯�படà¯�ட காமà¯�பà¯�டனà¯� அலைநீளமà¯� classical electron radius (râ‚‘) பாரமà¯�பரிய எலகà¯�டà¯�ரானà¯� ஆரமà¯� (râ‚‘) electron charge to mass quotient எலகà¯�டà¯�ரானà¯� மினà¯�சà¯�மை-நிறை ஈவà¯� electron-deuteron magnetic moment ratio எலகà¯�டà¯�ரானà¯�-டியூடà¯�டிரானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� electron-deuteron mass ratio எலகà¯�டà¯�ரானà¯�-டியூடà¯�டிரானà¯� நிறை விகிதமà¯� electron g factor (gâ‚‘) எலகà¯�டà¯�ரானà¯� g காரணி (gâ‚‘) electron gyromagnetic ratio (γₑ) எலகà¯�டà¯�ரானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� (γₑ) electron gyromagnetic ratio in MHz/T எலகà¯�டà¯�ரானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� MHz/T இலà¯� electron-helion mass ratio எலகà¯�டà¯�ரானà¯�-ஹீலியானà¯� நிறை விகிதமà¯� electron magnetic moment (μₑ) எலகà¯�டà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� (μₑ) electron magnetic moment anomaly (aâ‚‘) எலகà¯�டà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� அசாதாரணமà¯� (aâ‚‘) electron magnetic moment to Bohr magneton ratio எலகà¯�டà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� electron magnetic moment to nuclear magneton ratio எலகà¯�டà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� electron molar mass (Mâ‚‘) எலகà¯�டà¯�ரானà¯� மோலாரà¯� நிறை (Mâ‚‘) electron-muon magnetic moment ratio எலகà¯�டà¯�ரானà¯�-மியூயானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� electron-muon mass ratio எலகà¯�டà¯�ரானà¯�-மியூயானà¯� நிறை விகிதமà¯� electron-neutron magnetic moment ratio எலகà¯�டà¯�ரானà¯�-நியூடà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� electron-neutron mass ratio எலகà¯�டà¯�ரானà¯�-நியூடà¯�ரானà¯� நிறை விகிதமà¯� electron-proton magnetic moment ratio எலகà¯�டà¯�ரானà¯�-பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� electron-proton mass ratio எலகà¯�டà¯�ரானà¯�-பà¯�ரோடà¯�டானà¯� நிறை விகிதமà¯� electron relative atomic mass (Ar(e)) எலகà¯�டà¯�ரானà¯� சாரà¯�பà¯� அணà¯� நிறை (Ar(e)) electron-tau mass ratio எலகà¯�டà¯�ரானà¯�-டாவà¯� நிறை விகிதமà¯� electron to alpha particle mass ratio எலகà¯�டà¯�ரானà¯� à®®à¯�தலà¯� ஆலà¯�பா தà¯�களà¯� வரை நிறை விகிதமà¯� electron to shielded helion magnetic moment ratio எலகà¯�டà¯�ரானà¯� à®®à¯�தலà¯� கவசமிடபà¯�படà¯�ட ஹீலியானà¯� வரை காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� electron to shielded proton magnetic moment ratio எலகà¯�டà¯�ரானà¯� à®®à¯�தலà¯� கவசமிடபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� வரை காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� electron-triton mass ratio எலகà¯�டà¯�ரானà¯�-டிரிடà¯�டானà¯� நிறை விகிதமà¯� electron volt-atomic mass unit relationship எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯�-அணà¯� நிறை அலகà¯� தொடரà¯�பà¯� electron volt-hartree relationship எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯�-ஹாரà¯�டà¯�ரீ தொடரà¯�பà¯� electron volt-hertz relationship எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯�-ஹெரà¯�டà¯�ஸà¯� தொடரà¯�பà¯� electron volt-inverse meter relationship எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯�-எதிரà¯� மீடà¯�டரà¯� தொடரà¯�பà¯� electron volt-joule relationship எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯�-ஜூலà¯� தொடரà¯�பà¯� electron volt-kelvin relationship எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯�-கெலà¯�வினà¯� தொடரà¯�பà¯� electron volt-kilogram relationship எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯�-கிலோகிராமà¯� தொடரà¯�பà¯� hartree-atomic mass unit relationship ஹாரà¯�டà¯�ரீ-அணà¯� நிறை அலகà¯� தொடரà¯�பà¯� hartree-electron volt relationship ஹாரà¯�டà¯�ரீ-எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� தொடரà¯�பà¯� muon Compton wavelength மியூயானà¯� காமà¯�பà¯�டனà¯� அலைநீளமà¯� muon-electron mass ratio மியூயானà¯�-எலகà¯�டà¯�ரானà¯� நிறை விகிதமà¯� muon g factor மியூயானà¯� g காரணி muon magnetic moment மியூயானà¯� காநà¯�த மோமெணà¯�டà¯� muon magnetic moment anomaly மியூயானà¯� காநà¯�த மோமெணà¯�டà¯� அசாதாரணமà¯� muon magnetic moment to Bohr magneton ratio மியூயானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� muon magnetic moment to nuclear magneton ratio மியூயானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� muon mass மியூயானà¯� நிறை muon mass energy equivalent மியூயானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� muon mass energy equivalent in MeV மியூயானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� muon mass in u மியூயானà¯� நிறை u இலà¯� muon molar mass மியூயானà¯� மோலாரà¯� நிறை muon-neutron mass ratio மியூயானà¯�-நியூடà¯�ரானà¯� நிறை விகிதமà¯� muon-proton magnetic moment ratio மியூயானà¯�-பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� muon-proton mass ratio மியூயானà¯�-பà¯�ரோடà¯�டானà¯� நிறை விகிதமà¯� muon-tau mass ratio மியூயானà¯�-டாவà¯� நிறை விகிதமà¯� reduced muon Compton wavelength கà¯�றைகà¯�கபà¯�படà¯�ட மியூயானà¯� காமà¯�பà¯�டனà¯� அலைநீளமà¯� reduced tau Compton wavelength கà¯�றைகà¯�கபà¯�படà¯�ட டாவà¯� காமà¯�பà¯�டனà¯� அலைநீளமà¯� tau Compton wavelength டாவà¯� காமà¯�பà¯�டனà¯� அலைநீளமà¯� tau-electron mass ratio டாவà¯�-எலகà¯�டà¯�ரானà¯� நிறை விகிதமà¯� tau mass டாவà¯� நிறை tau mass energy equivalent டாவà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� tau mass in u டாவà¯� நிறை u இலà¯� tau molar mass டாவà¯� மோலாரà¯� நிறை tau-muon mass ratio டாவà¯�-மியூயானà¯� நிறை விகிதமà¯� tau-neutron mass ratio டாவà¯�-நியூடà¯�ரானà¯� நிறை விகிதமà¯� tau-proton mass ratio டாவà¯�-பà¯�ரோடà¯�டானà¯� நிறை விகிதமà¯� proton charge to mass quotient பà¯�ரோடà¯�டானà¯� மினà¯�சà¯�மை-நிறை ஈவà¯� proton Compton wavelength பà¯�ரோடà¯�டானà¯� காமà¯�பà¯�டனà¯� அலைநீளமà¯� proton-electron mass ratio பà¯�ரோடà¯�டானà¯�-எலகà¯�டà¯�ரானà¯� நிறை விகிதமà¯� proton g factor (gₚ) பà¯�ரோடà¯�டானà¯� g காரணி (gₚ) proton gyromagnetic ratio (γₚ) பà¯�ரோடà¯�டானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� (γₚ) proton gyromagnetic ratio in MHz/T பà¯�ரோடà¯�டானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� MHz/T இலà¯� proton magnetic moment (μₚ) பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� (μₚ) proton magnetic moment to Bohr magneton ratio பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� proton magnetic moment to nuclear magneton ratio பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� proton magnetic shielding correction பà¯�ரோடà¯�டானà¯� காநà¯�தகà¯� கவசதà¯� திரà¯�தà¯�தமà¯� proton mass (mₚ) பà¯�ரோடà¯�டானà¯� நிறை (mₚ) proton mass energy equivalent பà¯�ரோடà¯�டானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� proton mass energy equivalent in MeV பà¯�ரோடà¯�டானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� proton mass in u பà¯�ரோடà¯�டானà¯� நிறை u இலà¯� proton molar mass (Mₚ) பà¯�ரோடà¯�டானà¯� மோலாரà¯� நிறை (Mₚ) proton-muon mass ratio பà¯�ரோடà¯�டானà¯�-மியூயானà¯� நிறை விகிதமà¯� proton-neutron magnetic moment ratio பà¯�ரோடà¯�டானà¯�-நியூடà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� proton-neutron mass ratio பà¯�ரோடà¯�டானà¯�-நியூடà¯�ரானà¯� நிறை விகிதமà¯� proton relative atomic mass (Ar(p)) பà¯�ரோடà¯�டானà¯� சாரà¯�பà¯� அணà¯� நிறை (Ar(p)) proton rms charge radius பà¯�ரோடà¯�டானà¯� rms மினà¯�சà¯�மை ஆரமà¯� proton-tau mass ratio பà¯�ரோடà¯�டானà¯�-டாவà¯� நிறை விகிதமà¯� reduced proton Compton wavelength கà¯�றைகà¯�கபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� காமà¯�பà¯�டனà¯� அலைநீளமà¯� shielded proton gyromagnetic ratio கவசமிடபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� shielded proton gyromagnetic ratio in MHz/T கவசமிடபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� MHz/T இலà¯� shielded proton magnetic moment கவசமிடபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� shielded proton magnetic moment to Bohr magneton ratio கவசமிடபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� shielded proton magnetic moment to nuclear magneton ratio கவசமிடபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� neutron Compton wavelength நியூடà¯�ரானà¯� காமà¯�பà¯�டனà¯� அலைநீளமà¯� neutron-electron magnetic moment ratio நியூடà¯�ரானà¯�-எலகà¯�டà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� neutron-electron mass ratio நியூடà¯�ரானà¯�-எலகà¯�டà¯�ரானà¯� நிறை விகிதமà¯� neutron g factor (gâ‚™) நியூடà¯�ரானà¯� g காரணி (gâ‚™) neutron gyromagnetic ratio (γₙ) நியூடà¯�ரானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� (γₙ) neutron gyromagnetic ratio in MHz/T நியூடà¯�ரானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� MHz/T இலà¯� neutron magnetic moment (μₙ) நியூடà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� (μₙ) neutron magnetic moment to Bohr magneton ratio நியூடà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� neutron magnetic moment to nuclear magneton ratio நியூடà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� neutron mass (mâ‚™) நியூடà¯�ரானà¯� நிறை (mâ‚™) neutron mass energy equivalent நியூடà¯�ரானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� neutron mass energy equivalent in MeV நியூடà¯�ரானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� neutron mass in u நியூடà¯�ரானà¯� நிறை u இலà¯� neutron molar mass (Mâ‚™) நியூடà¯�ரானà¯� மோலாரà¯� நிறை (Mâ‚™) neutron-muon mass ratio நியூடà¯�ரானà¯�-மியூயானà¯� நிறை விகிதமà¯� neutron-proton magnetic moment ratio நியூடà¯�ரானà¯�-பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� neutron-proton mass difference நியூடà¯�ரானà¯�-பà¯�ரோடà¯�டானà¯� நிறை வேறà¯�பாடà¯� neutron-proton mass difference energy equivalent நியூடà¯�ரானà¯�-பà¯�ரோடà¯�டானà¯� நிறை வேறà¯�பாடà¯�டினà¯� ஆறà¯�றலà¯� சமமதிபà¯�பà¯� neutron-proton mass difference energy equivalent in MeV நியூடà¯�ரானà¯�-பà¯�ரோடà¯�டானà¯� நிறை வேறà¯�பாடà¯�டினà¯� ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� neutron-proton mass difference in u நியூடà¯�ரானà¯�-பà¯�ரோடà¯�டானà¯� நிறை வேறà¯�பாடà¯� u இலà¯� neutron-proton mass ratio நியூடà¯�ரானà¯�-பà¯�ரோடà¯�டானà¯� நிறை விகிதமà¯� neutron relative atomic mass (Ar(n)) நியூடà¯�ரானà¯� சாரà¯�பà¯� அணà¯� நிறை (Ar(n)) neutron-tau mass ratio நியூடà¯�ரானà¯�-டாவà¯� நிறை விகிதமà¯� neutron to shielded proton magnetic moment ratio நியூடà¯�ரானà¯� à®®à¯�தலà¯� கவசமிடபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� வரை காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� reduced neutron Compton wavelength கà¯�றைகà¯�கபà¯�படà¯�ட நியூடà¯�ரானà¯� காமà¯�பà¯�டனà¯� அலைநீளமà¯� deuteron-electron magnetic moment ratio டியூடà¯�டிரானà¯�-எலகà¯�டà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� deuteron-electron mass ratio டியூடà¯�டிரானà¯�-எலகà¯�டà¯�ரானà¯� நிறை விகிதமà¯� deuteron g factor டியூடà¯�டிரானà¯� g காரணி deuteron magnetic moment டியூடà¯�டிரானà¯� காநà¯�த மோமெணà¯�டà¯� deuteron magnetic moment to Bohr magneton ratio டியூடà¯�டிரானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� deuteron magnetic moment to nuclear magneton ratio டியூடà¯�டிரானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� deuteron mass டியூடà¯�டிரானà¯� நிறை deuteron mass energy equivalent டியூடà¯�டிரானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� deuteron mass energy equivalent in MeV டியூடà¯�டிரானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� deuteron mass in u டியூடà¯�டிரானà¯� நிறை u இலà¯� deuteron molar mass டியூடà¯�டிரானà¯� மோலாரà¯� நிறை deuteron-neutron magnetic moment ratio டியூடà¯�டிரானà¯�-நியூடà¯�ரானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� deuteron-proton magnetic moment ratio டியூடà¯�டிரானà¯�-பà¯�ரோடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� deuteron-proton mass ratio டியூடà¯�டிரானà¯�-பà¯�ரோடà¯�டானà¯� நிறை விகிதமà¯� deuteron relative atomic mass (Ar(d)) டியூடà¯�டிரானà¯� சாரà¯�பà¯� அணà¯� நிறை (Ar(d)) deuteron rms charge radius டியூடà¯�டிரானà¯� rms மினà¯�சà¯�மை ஆரமà¯� triton-electron mass ratio டிரிடà¯�டானà¯�-எலகà¯�டà¯�ரானà¯� நிறை விகிதமà¯� triton g factor (gₜ) டிரிடà¯�டானà¯� g காரணி (gₜ) triton magnetic moment (μₜ) டிரிடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� (μₜ) triton magnetic moment to Bohr magneton ratio டிரிடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� triton magnetic moment to nuclear magneton ratio டிரிடà¯�டானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� triton mass (mₜ) டிரிடà¯�டானà¯� நிறை (mₜ) triton mass energy equivalent டிரிடà¯�டானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� triton mass energy equivalent in MeV டிரிடà¯�டானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� triton mass in u டிரிடà¯�டானà¯� நிறை u இலà¯� triton molar mass (Mₜ) டிரிடà¯�டானà¯� மோலாரà¯� நிறை (Mₜ) triton-proton mass ratio டிரிடà¯�டானà¯�-பà¯�ரோடà¯�டானà¯� நிறை விகிதமà¯� triton relative atomic mass (Ar(t)) டிரிடà¯�டானà¯� சாரà¯�பà¯� அணà¯� நிறை (Ar(t)) triton to proton magnetic moment ratio டிரிடà¯�டானà¯� à®®à¯�தலà¯� பà¯�ரோடà¯�டானà¯� வரை காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� helion-electron mass ratio ஹீலியானà¯�-எலகà¯�டà¯�ரானà¯� நிறை விகிதமà¯� helion g factor (gâ‚•) ஹீலியானà¯� g காரணி (gâ‚•) helion magnetic moment (μₕ) ஹீலியானà¯� காநà¯�த மோமெணà¯�டà¯� (μₕ) helion magnetic moment to Bohr magneton ratio ஹீலியானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� helion magnetic moment to nuclear magneton ratio ஹீலியானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� helion mass (mâ‚•) ஹீலியானà¯� நிறை (mâ‚•) helion mass energy equivalent ஹீலியானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� helion mass energy equivalent in MeV ஹீலியானà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� helion mass in u ஹீலியானà¯� நிறை u இலà¯� helion molar mass (Mâ‚•) ஹீலியானà¯� மோலாரà¯� நிறை (Mâ‚•) helion-proton mass ratio ஹீலியானà¯�-பà¯�ரோடà¯�டானà¯� நிறை விகிதமà¯� helion relative atomic mass (Ar(h)) ஹீலியானà¯� சாரà¯�பà¯� அணà¯� நிறை (Ar(h)) helion shielding shift ஹீலியானà¯� கவச இடமாறà¯�றமà¯� shielded helion gyromagnetic ratio கவசமிடபà¯�படà¯�ட ஹீலியானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� shielded helion gyromagnetic ratio in MHz/T கவசமிடபà¯�படà¯�ட ஹீலியானà¯� கைரோமகà¯�னெடிகà¯� விகிதமà¯� MHz/T இலà¯� shielded helion magnetic moment கவசமிடபà¯�படà¯�ட ஹீலியானà¯� காநà¯�த மோமெணà¯�டà¯� shielded helion magnetic moment to Bohr magneton ratio கவசமிடபà¯�படà¯�ட ஹீலியானà¯� காநà¯�த மோமெணà¯�டà¯� / போரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� shielded helion magnetic moment to nuclear magneton ratio கவசமிடபà¯�படà¯�ட ஹீலியானà¯� காநà¯�த மோமெணà¯�டà¯� / அணà¯�கà¯�கரà¯� மாகà¯�னெடà¯�டானà¯� விகிதமà¯� shielded helion to proton magnetic moment ratio கவசமிடபà¯�படà¯�ட ஹீலியானà¯� à®®à¯�தலà¯� பà¯�ரோடà¯�டானà¯� வரை காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� shielded helion to shielded proton magnetic moment ratio கவசமிடபà¯�படà¯�ட ஹீலியானà¯� à®®à¯�தலà¯� கவசமிடபà¯�படà¯�ட பà¯�ரோடà¯�டானà¯� வரை காநà¯�த மோமெணà¯�டà¯� விகிதமà¯� alpha particle mass ஆலà¯�பா தà¯�களà¯� நிறை alpha particle mass in u ஆலà¯�பா தà¯�களà¯� நிறை u இலà¯� alpha particle mass energy equivalent ஆலà¯�பா தà¯�களà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� alpha particle mass energy equivalent in MeV ஆலà¯�பா தà¯�களà¯� நிறை-ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� alpha particle-electron mass ratio ஆலà¯�பா தà¯�களà¯�-எலகà¯�டà¯�ரானà¯� நிறை விகிதமà¯� alpha particle-proton mass ratio ஆலà¯�பா தà¯�களà¯�-பà¯�ரோடà¯�டானà¯� நிறை விகிதமà¯� alpha particle rms charge radius ஆலà¯�பா தà¯�களà¯� rms மினà¯�சà¯�மை ஆரமà¯� alpha particle molar mass ஆலà¯�பா தà¯�களà¯� மோலாரà¯� நிறை alpha particle relative atomic mass (Ar(α)) ஆலà¯�பா தà¯�களà¯� சாரà¯�பà¯� அணà¯� நிறை (Ar(α)) atomic mass constant (mᵤ) அணà¯� நிறை மாறிலி (mᵤ) Avogadro constant அவோகாடà¯�ரோ மாறிலி Boltzmann constant (k) போலà¯�டà¯�ஸà¯�மானà¯� மாறிலி (k) Boltzmann constant in eV/K போலà¯�டà¯�ஸà¯�மானà¯� மாறிலி eV/K இலà¯� Boltzmann constant in Hz/K போலà¯�டà¯�ஸà¯�மானà¯� மாறிலி Hz/K இலà¯� Boltzmann constant in inverse meter per kelvin போலà¯�டà¯�ஸà¯�மானà¯� மாறிலி எதிரà¯� மீடà¯�டரà¯�/கெலà¯�வினà¯� இலà¯� electron volt (eV) எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� (eV) Faraday constant (F) ஃபாரடே மாறிலி (F) first radiation constant (câ‚�) à®®à¯�தலà¯� கதிரà¯�வீசà¯�சà¯� மாறிலி (câ‚�) first radiation constant for spectral radiance வரà¯�ணதிரளà¯� கதிரொளிகà¯�கான à®®à¯�தலà¯� கதிரà¯�வீசà¯�சà¯� மாறிலி molar gas constant (R) மோலாரà¯� வாயà¯� மாறிலி (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) லோஷà¯�மிடà¯� மாறிலி (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) லோஷà¯�மிடà¯� மாறிலி (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant மோலாரà¯� பிளாஙà¯�கà¯� மாறிலி second radiation constant (câ‚‚) இரணà¯�டாமà¯� கதிரà¯�வீசà¯�சà¯� மாறிலி (câ‚‚) Stefan-Boltzmann constant (σ) ஸà¯�டீஃபனà¯�-போலà¯�டà¯�ஸà¯�மானà¯� மாறிலி (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) இயலà¯�பான Si-இனà¯� படிககà¯�கடà¯�ட இடைவெளி (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent அணà¯� நிறை மாறிலியினà¯� ஆறà¯�றலà¯� சமமதிபà¯�பà¯� atomic mass constant energy equivalent in MeV அணà¯� நிறை மாறிலியினà¯� ஆறà¯�றலà¯� சமமதிபà¯�பà¯� MeV இலà¯� atomic mass unit-electron volt relationship அணà¯� நிறை அலகà¯�-எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� தொடரà¯�பà¯� molar mass constant (Mᵤ) மோலாரà¯� நிறை மாறிலி (Mᵤ) molar mass of carbon-12 காரà¯�பனà¯�-12 இனà¯� மோலாரà¯� நிறை molar volume of ideal gas (273.15 K, 100 kPa) இயலà¯�பான வாயà¯�வினà¯� மோலாரà¯� பரà¯�மனà¯� (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) இயலà¯�பான வாயà¯�வினà¯� மோலாரà¯� பரà¯�மனà¯� (273.15 K, 101.325 kPa) molar volume of silicon சிலிகானினà¯� மோலாரà¯� பரà¯�மனà¯� Sackur-Tetrode constant (1 K, 100 kPa) சாகà¯�கà¯�à®°à¯�-டெடà¯�ரோடà¯� மாறிலி (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) சாகà¯�கà¯�à®°à¯�-டெடà¯�ரோடà¯� மாறிலி (1 K, 101.325 kPa) Wien frequency displacement law constant வீனà¯� அதிரà¯�வெணà¯� இடபà¯�பெயரà¯�வà¯� விதி மாறிலி Wien wavelength displacement law constant வீனà¯� அலைநீள இடபà¯�பெயரà¯�வà¯� விதி மாறிலி standard atmosphere (atm) நிலையான வளிமணà¯�டலமà¯� (atm) standard-state pressure (p°) நிலையான நிலை à®…à®´à¯�தà¯�தமà¯� (p°) Angstrom star (Ã…*) ஆஙà¯�கà¯�ஸà¯�டà¯�ரோமà¯� நடà¯�சதà¯�திரமà¯� (Ã…*) Copper x unit செமà¯�பà¯� x அலகà¯� Molybdenum x unit மாலிபà¯�டினமà¯� x அலகà¯� atomic unit of magnetizability காநà¯�தமாதலà¯� திறனினà¯� அணà¯� அலகà¯� atomic unit of mass (mâ‚‘) நிறையினà¯� அணà¯� அலகà¯� (mâ‚‘) atomic unit of momentum இயகà¯�கவெகதà¯�தினà¯� அணà¯� அலகà¯� atomic unit of permittivity அனà¯�மதியினà¯� அணà¯� அலகà¯� atomic unit of time நேரதà¯�தினà¯� அணà¯� அலகà¯� atomic unit of velocity வேகதà¯�தினà¯� அணà¯� அலகà¯� hartree-hertz relationship ஹாரà¯�டà¯�ரீ-ஹெரà¯�டà¯�ஸà¯� தொடரà¯�பà¯� hartree-inverse meter relationship ஹாரà¯�டà¯�ரீ-எதிரà¯� மீடà¯�டரà¯� தொடரà¯�பà¯� hartree-joule relationship ஹாரà¯�டà¯�ரீ-ஜூலà¯� தொடரà¯�பà¯� hartree-kelvin relationship ஹாரà¯�டà¯�ரீ-கெலà¯�வினà¯� தொடரà¯�பà¯� hartree-kilogram relationship ஹாரà¯�டà¯�ரீ-கிலோகிராமà¯� தொடரà¯�பà¯� shielding difference of d and p in HD HD இலà¯� d மறà¯�à®±à¯�à®®à¯� p கவச வேறà¯�பாடà¯� shielding difference of t and p in HT HT இலà¯� t மறà¯�à®±à¯�à®®à¯� p கவச வேறà¯�பாடà¯� pi (Ï€) பை (Ï€) Euler's number (e) à®�லரினà¯� எணà¯� (e) golden ratio (φ) தஙà¯�க விகிதமà¯� (φ) Euler-Mascheroni constant (γ) à®�லரà¯�-மாஸà¯�கெரோனி மாறிலி (γ) nominal solar radius பெயரளவà¯� சூரிய ஆரமà¯� nominal solar total irradiance பெயரளவà¯� சூரிய மொதà¯�த கதிரà¯�வீசà¯�சà¯� nominal solar luminosity பெயரளவà¯� சூரிய ஒளிரà¯�வà¯� nominal solar effective temperature பெயரளவà¯� சூரிய செயலà¯�திறனà¯� வெபà¯�பநிலை nominal solar mass parameter பெயரளவà¯� சூரிய நிறை அளபà¯�à®°à¯� nominal terrestrial equatorial radius பெயரளவà¯� பூமி விசà¯�வதà¯�தà¯�à®°à¯�வ ஆரமà¯� nominal terrestrial polar radius பெயரளவà¯� பூமி தà¯�à®°à¯�வ ஆரமà¯� nominal terrestrial mass parameter பெயரளவà¯� பூமி நிறை அளபà¯�à®°à¯� nominal jovian equatorial radius பெயரளவà¯� வியாழனà¯� விசà¯�வதà¯�தà¯�à®°à¯�வ ஆரமà¯� nominal jovian polar radius பெயரளவà¯� வியாழனà¯� தà¯�à®°à¯�வ ஆரமà¯� nominal jovian mass parameter பெயரளவà¯� வியாழனà¯� நிறை அளபà¯�à®°à¯� average value of one minus the rate of TCG relative to TCB TCB-கà¯�கà¯� ஒபà¯�பான TCG விகிததà¯�தை 1-இலிரà¯�நà¯�தà¯� கழிதà¯�த சராசரி மதிபà¯�பà¯� solar mass parameter (TCB-compatible) சூரிய நிறை அளபà¯�à®°à¯� (TCB-இணகà¯�கமான) solar mass parameter (TDB-compatible) சூரிய நிறை அளபà¯�à®°à¯� (TDB-இணகà¯�கமான) equatorial radius of the Earth (TT-compatible) பூமியினà¯� விசà¯�வதà¯�தà¯�à®°à¯�வ ஆரமà¯� (TT-இணகà¯�கமான) dynamical form factor of the Earth பூமியினà¯� இயகà¯�க வடிவ காரணி time rate of change in the dynamical form factor of the Earth பூமியினà¯� இயகà¯�க வடிவ காரணியினà¯� கால மாறà¯�à®± விகிதமà¯� geocentric gravitational constant (TCB-compatible) பூமிமைய ஈரà¯�பà¯�பà¯� மாறிலி (TCB-இணகà¯�கமான) geocentric gravitational constant (TT-compatible) பூமிமைய ஈரà¯�பà¯�பà¯� மாறிலி (TT-இணகà¯�கமான) geocentric gravitational constant (TDB-compatible) பூமிமைய ஈரà¯�பà¯�பà¯� மாறிலி (TDB-இணகà¯�கமான) potential of the geoid ஜியாயà¯�டினà¯� ஈரà¯�பà¯�பà¯� திறனà¯� nominal mean angular velocity of the Earth (TT-compatible) பூமியினà¯� பெயரளவà¯� சராசரி கோண வேகமà¯� (TT-இணகà¯�கமான) ratio mass of the Moon to the Earth சநà¯�திரனà¯� மறà¯�à®±à¯�à®®à¯� பூமியினà¯� நிறை விகிதமà¯� ratio of the mass of the Sun to Mercury சூரியனà¯� மறà¯�à®±à¯�à®®à¯� பà¯�தனà¯� நிறை விகிதமà¯� ratio of the mass of the Sun to Venus சூரியனà¯� மறà¯�à®±à¯�à®®à¯� வெளà¯�ளி நிறை விகிதமà¯� ratio of the mass of the Sun to Mars சூரியனà¯� மறà¯�à®±à¯�à®®à¯� செவà¯�வாயà¯� நிறை விகிதமà¯� ratio of the mass of the Sun to Jupiter சூரியனà¯� மறà¯�à®±à¯�à®®à¯� வியாழனà¯� நிறை விகிதமà¯� ratio of the mass of the Sun to Saturn சூரியனà¯� மறà¯�à®±à¯�à®®à¯� சனி நிறை விகிதமà¯� ratio of the mass of the Sun to Uranus சூரியனà¯� மறà¯�à®±à¯�à®®à¯� யà¯�ரேனஸà¯� நிறை விகிதமà¯� ratio of the mass of the Sun to Neptune சூரியனà¯� மறà¯�à®±à¯�à®®à¯� நெபà¯�டியூனà¯� நிறை விகிதமà¯� ratio of the mass of the Sun to (134340) Pluto சூரியனà¯� மறà¯�à®±à¯�à®®à¯� (134340) பà¯�ளூடà¯�டோ நிறை விகிதமà¯� ratio of the mass of the Sun to (136199) Eris சூரியனà¯� மறà¯�à®±à¯�à®®à¯� (136199) எரிஸà¯� நிறை விகிதமà¯� ratio of the mass of (1) Ceres to the Sun (1) செரெஸà¯� மறà¯�à®±à¯�à®®à¯� சூரியனà¯� நிறை விகிதமà¯� ratio of the mass of (2) Pallas to the Sun (2) பாலஸà¯� மறà¯�à®±à¯�à®®à¯� சூரியனà¯� நிறை விகிதமà¯� ratio of the mass of (4) Vesta to the Sun (4) வெஸà¯�டா மறà¯�à®±à¯�à®®à¯� சூரியனà¯� நிறை விகிதமà¯� mean obliquity of the ecliptic at J2000.0 J2000.0 இலà¯� சூரியவழியினà¯� சராசரி சாயà¯�வà¯� Electromagnetic மினà¯�காநà¯�தமà¯� Compton wavelength காமà¯�பà¯�டனà¯� அலைநீளமà¯� Astronomy வானியலà¯� ConstantsWidget Domain பிரிவà¯� Subdomain தà¯�ணைபà¯� பிரிவà¯� No match found பொரà¯�தà¯�தமà¯� எதà¯�வà¯�à®®à¯� இலà¯�லை Name பெயரà¯� Value மதிபà¯�பà¯� Unit அலகà¯� Search தேடà¯� All அனைதà¯�தà¯�à®®à¯� CustomKeypadDialog Custom Keypad தனிபà¯�பயனà¯� விசைபà¯�பலகை Rows: வரிகளà¯�: Columns: நெடà¯�வரிசைகளà¯�: Copy preset: à®®à¯�னà¯�னமைவை நகலெடà¯�: Basic அடிபà¯�படை Scientific (wide) அறிவியலà¯� (அகலமà¯�) Scientific (narrow) அறிவியலà¯� (கà¯�à®±à¯�கலà¯�) Apply பயனà¯�படà¯�தà¯�தà¯� Row வரி Column நெடà¯�வரிசை Label சிடà¯�டை Behavior நடதà¯�தை Text உரை DiagnosticsDialog App Diagnostics செயலிகà¯� கணà¯�டறிதலà¯� Copy to Clipboard இடைநிலைபà¯� பலகைகà¯�கà¯� நகலெடà¯� Editor Unit அலகà¯� User unit பயனரà¯� அலகà¯� User function பயனரà¯� செயலà¯�பாடà¯� Argument வாதமà¯� Current result:<br/>%1 தறà¯�போதைய à®®à¯�டிவà¯�:<br/>%1 Selection result:<br/>%1 தேரà¯�வà¯� à®®à¯�டிவà¯�:<br/>%1 Selection result: n/a தேரà¯�வà¯� à®®à¯�டிவà¯�: பொரà¯�நà¯�தாதà¯� Selection result: %1 தேரà¯�வà¯� à®®à¯�டிவà¯�: %1 second விநாடி metre மீடà¯�டரà¯� kilogram கிலோகிராமà¯� mole மோலà¯� radian ரேடியனà¯� steradian ஸà¯�டெரேடியனà¯� degree Celsius செலà¯�சியஸà¯� டிகிரி cubic metre கன மீடà¯�டரà¯� cubic millimetre கன மிலà¯�லிமீடà¯�டரà¯� cubic centimetre கன செனà¯�டிமீடà¯�டரà¯� cubic decimetre கன டெசிமீடà¯�டரà¯� cubic kilometre கன கிலோமீடà¯�டரà¯� square millimetre சதà¯�à®° மிலà¯�லிமீடà¯�டரà¯� square kilometre சதà¯�à®° கிலோமீடà¯�டரà¯� square metre சதà¯�à®° மீடà¯�டரà¯� minute நிமிடமà¯� hour மணி day நாளà¯� astronomical unit வானியலà¯� அலகà¯� degree டிகிரி arcminute வளைநிமிடமà¯� arcsecond வளைவிநாடி milliarcsecond மிலà¯�லி வளைவிநாடி microarcsecond மைகà¯�ரோ வளைவிநாடி hectare ஹெகà¯�டேரà¯� litre லிடà¯�டரà¯� tonne மெடà¯�ரிகà¯� டனà¯� Dalton டாலà¯�டனà¯� electronvolt எலகà¯�டà¯�ரானà¯� வோலà¯�டà¯� Angstrom ஆஙà¯�கà¯�ஸà¯�டà¯�ரோமà¯� atmosphere வளிமணà¯�டலமà¯� atomic mass unit அணà¯� நிறை அலகà¯� British thermal unit பிரிடà¯�டிஷà¯� வெபà¯�ப அலகà¯� calorie கலோரி carat கரடà¯� cup கபà¯� cup (Imperial) கபà¯� (இமà¯�பீரியலà¯�) cup (Japanese) கபà¯� (ஜபà¯�பானிய) cup (US) கபà¯� (அமெரிகà¯�க) degree Fahrenheit ஃபாரனà¯�ஹீடà¯� டிகிரி fathom ஃபாதமà¯� fluid ounce (Imperial) திரவ அவà¯�னà¯�ஸà¯� (இமà¯�பீரியலà¯�) fluid ounce (US) திரவ அவà¯�னà¯�ஸà¯� (அமெரிகà¯�க) fluid dram (Imperial) திரவ டிராமà¯� (இமà¯�பீரியலà¯�) fluid dram (US) திரவ டிராமà¯� (அமெரிகà¯�க) foot அடி square foot சதà¯�à®° அடி cubic foot கன அடி gallon (Imperial) கேலனà¯� (இமà¯�பீரியலà¯�) gallon (US) கேலனà¯� (அமெரிகà¯�க) gill (Imperial) கிலà¯� (இமà¯�பீரியலà¯�) gill (US) கிலà¯� (அமெரிகà¯�க) gradian கிரேடியனà¯� grain கிரெயினà¯� gram கிராமà¯� Hartley ஹாரà¯�டà¯�லி Hartree energy unit ஹாரà¯�டà¯�ரீ ஆறà¯�றலà¯� அலகà¯� horsepower கà¯�திரைதà¯�திறனà¯� inch à®…à®™à¯�கà¯�லமà¯� square inch சதà¯�à®° à®…à®™à¯�கà¯�லமà¯� cubic inch கன à®…à®™à¯�கà¯�லமà¯� karat காரடà¯� knot நாடà¯� lightminute ஒளி-நிமிடமà¯� lightsecond ஒளி-விநாடி lightyear ஒளி ஆணà¯�டà¯� long ton நீணà¯�ட டனà¯� mile மைலà¯� square mile சதà¯�à®° மைலà¯� cubic mile கன மைலà¯� mile per hour மணிகà¯�கà¯� மைலà¯� kilometre per hour மணிகà¯�கà¯� கிலோமீடà¯�டரà¯� nautical mile கடலà¯� மைலà¯� ounce அவà¯�னà¯�ஸà¯� parsec பாரà¯�செகà¯� pint (Imperial) பைனà¯�டà¯� (இமà¯�பீரியலà¯�) pint (US) பைனà¯�டà¯� (அமெரிகà¯�க) pound பவà¯�ணà¯�டà¯� pounds per square inch சதà¯�à®° à®…à®™à¯�கà¯�லதà¯�திறà¯�கà¯� பவà¯�ணà¯�டà¯�களà¯� quart (Imperial) கà¯�வாரà¯�டà¯� (இமà¯�பீரியலà¯�) quart (US) கà¯�வாரà¯�டà¯� (அமெரிகà¯�க) oil barrel எணà¯�ணெயà¯� பீபà¯�பாயà¯� beer barrel (US) பீரà¯� பீபà¯�பாயà¯� (அமெரிகà¯�க) square yard சதà¯�à®° யாரà¯�டà¯� cubic yard கன யாரà¯�டà¯� short ton கà¯�à®±à¯�கிய டனà¯� tablespoon மேசைகà¯�கரணà¯�டி tablespoon (Australian) மேசைகà¯�கரணà¯�டி (ஆஸà¯�திரேலிய) tablespoon (Imperial) மேசைகà¯�கரணà¯�டி (இமà¯�பீரியலà¯�) tablespoon (US) மேசைகà¯�கரணà¯�டி (அமெரிகà¯�க) dessert spoon இனிபà¯�பà¯�கà¯� கரணà¯�டி teaspoon தேகà¯�கரணà¯�டி teaspoon (Imperial) தேகà¯�கரணà¯�டி (இமà¯�பீரியலà¯�) teaspoon (US) தேகà¯�கரணà¯�டி (அமெரிகà¯�க) turn திரà¯�பà¯�பà¯� revolution சà¯�à®´à®±à¯�சி revolution per minute நிமிடதà¯�திறà¯�கà¯� சà¯�à®´à®±à¯�சி week வாரமà¯� kilowatt hour கிலோவாடà¯� மணி millimetre of mercury பாதரச மிலà¯�லிமீடà¯�டரà¯� yard யாரà¯�டà¯� Julian century ஜூலியனà¯� நூறà¯�றாணà¯�டà¯� Julian year ஜூலியனà¯� ஆணà¯�டà¯� sidereal year நடà¯�சதà¯�திர ஆணà¯�டà¯� tropical year வெபà¯�பமணà¯�டல ஆணà¯�டà¯� Evaluator invalid expression தவறான வெளிபà¯�பாடà¯� division by zero சà¯�ழியதà¯�தாலà¯� வகà¯�தà¯�தலà¯� too time consuming - computation was rejected அதிக நேரமà¯� எடà¯�கà¯�கà¯�à®®à¯� - கணகà¯�கீடà¯� நிராகரிகà¯�கபà¯�படà¯�டதà¯� dimension mismatch - quantities with different dimensions cannot be compared, added, etc. பரிமாண பொரà¯�தà¯�தமினà¯�மை - வெவà¯�வேறà¯� பரிமாணஙà¯�களைகà¯� கொணà¯�ட அளவà¯�களை ஒபà¯�பிடவோ, சேரà¯�கà¯�கவோ à®®à¯�டியாதà¯�. invalid dimension - operation might require dimensionless arguments தவறான பரிமாணமà¯� - செயலà¯�பாடà¯�டிறà¯�கà¯� பரிமாணமறà¯�à®± வாதஙà¯�களà¯� தேவைபà¯�படலாமà¯� Computation aborted - encountered numerical instability கணகà¯�கீடà¯� நிறà¯�தà¯�தபà¯�படà¯�டதà¯� - எணà¯�ணியலà¯� உறà¯�தியறà¯�à®± தனà¯�மையை எதிரà¯�கொணà¯�டதà¯� invalid dimension - function might require dimensionless arguments தவறான பரிமாணமà¯� - செயலà¯�பாடà¯�டிறà¯�கà¯� பரிமாணமறà¯�à®± வாதஙà¯�களà¯� தேவைபà¯�படலாமà¯� error பிழை unit must not be zero அலகà¯� சà¯�ழியமாக இரà¯�கà¯�ககà¯�கூடாதà¯� Conversion failed - dimension mismatch மாறà¯�à®±à¯�வதிலà¯� தோலà¯�வி - பரிமாண பொரà¯�தà¯�தமினà¯�மை unknown function or variable அறியபà¯�படாத செயலà¯�பாடà¯� அலà¯�லதà¯� மாறி recursion not supported மறà¯�நிகழà¯�வà¯� ஆதரிகà¯�கபà¯�படவிலà¯�லை cannot operate on a NaN எணà¯�அலà¯�லாததிலà¯� செயலà¯�பட à®®à¯�டியாதà¯� underflow - tiny result is out of SpeedCrunch's number range கீழிறகà¯�கமà¯� - சிறிய à®®à¯�டிவà¯� வேகநொறà¯�கà¯�கினà¯� எணà¯� வரமà¯�பிறà¯�கà¯� வெளியே உளà¯�ளதà¯� overflow - huge result is out of SpeedCrunch's number range வழிநà¯�தோடà¯�à®®à¯� - பெரிய à®®à¯�டிவà¯� வேகநொறà¯�கà¯�கினà¯� எணà¯� வரமà¯�பிறà¯�கà¯� வெளியே உளà¯�ளதà¯� overflow - logic result exceeds maximum of 256 bits வழிநà¯�தோடà¯�à®®à¯� - தரà¯�கà¯�க à®®à¯�டிவà¯� அதிகபடà¯�சமà¯� 256 பிடà¯�களை தாணà¯�டியதà¯� overflow - integer result exceeds maximum limit for integers வழிநà¯�தோடà¯�à®®à¯� - à®®à¯�à®´à¯� எணà¯�களினà¯� à®®à¯�டிவà¯� à®®à¯�à®´à¯� எணà¯�களà¯�கà¯�கான அதிகபடà¯�ச வரமà¯�பை மீறà¯�கிறதà¯� operation is not defined for these arguments இநà¯�த வாதஙà¯�களà¯�கà¯�கà¯� செயலà¯� வரையறà¯�கà¯�கபà¯�படவிலà¯�லை wrong number of arguments தவறான எணà¯�ணிகà¯�கையிலான வாதஙà¯�களà¯� does not take NaN as an argument எணà¯�அலà¯�லாததை à®’à®°à¯� வாதமாக எடà¯�தà¯�தà¯�கà¯� கொளà¯�ளவிலà¯�லை result out of range வரமà¯�பிறà¯�கà¯� வெளியே à®®à¯�டிவà¯� undefined for argument domain வாத களதà¯�திறà¯�கà¯� வரையறà¯�கà¯�கபà¯�படவிலà¯�லை computation too expensive கணகà¯�கீடà¯� மிகவà¯�à®®à¯� விலை உயரà¯�நà¯�ததà¯� internal error, please report a bug உளà¯� பிழை, பிழையைபà¯� பà¯�காரளிகà¯�கவà¯�à®®à¯� syntax error தொடரியலà¯� பிழை conversion target must be a unit மாறà¯�à®± இலகà¯�கà¯� à®’à®°à¯� அலகாக இரà¯�கà¯�க வேணà¯�டà¯�à®®à¯� unknown unit தெரியாத அலகà¯� %1 is a reserved name, please choose another %1 எனà¯�பதà¯� ஒதà¯�கà¯�கபà¯�படà¯�ட பெயரà¯�, தயவà¯�செயà¯�தà¯� வேறà¯� ஒனà¯�றைதà¯� தேரà¯�வà¯� செயà¯�யவà¯�à®®à¯� %1 is a global user definition and cannot be overridden in this session. %1 à®’à®°à¯� à®®à¯�à®´à¯�மையான பயனரà¯� வரையறை; இநà¯�த அமரà¯�விலà¯� அதை மீற à®®à¯�டியாதà¯�. %1 is a variable name, please choose another or delete the variable %1 எனà¯�பதà¯� à®’à®°à¯� மாறி பெயரà¯�, தயவà¯�செயà¯�தà¯� வேறொனà¯�றைதà¯� தேரà¯�வà¯� செயà¯�யவà¯�à®®à¯� அலà¯�லதà¯� மாறியை நீகà¯�கவà¯�à®®à¯� argument %1 is used more than once வாதமà¯� %1 ஒனà¯�à®±à¯�கà¯�கà¯� மேறà¯�படà¯�ட à®®à¯�றை பயனà¯�படà¯�தà¯�தபà¯�படà¯�கிறதà¯� %1 is a built-in unit name, please choose another %1 à®’à®°à¯� உளà¯�ளமைநà¯�த அலகà¯�பà¯� பெயரà¯�; வேறà¯� ஒனà¯�றைதà¯� தேரà¯�நà¯�தெடà¯�கà¯�கவà¯�à®®à¯� %1 is a user function name, please choose another or delete the function %1 எனà¯�பதà¯� à®’à®°à¯� பயனரà¯� செயலà¯�பாடà¯�டà¯�பà¯� பெயரà¯�, தயவà¯�செயà¯�தà¯� இனà¯�னொனà¯�றைதà¯� தேரà¯�வà¯� செயà¯�யவà¯�à®®à¯� அலà¯�லதà¯� செயலà¯�பாடà¯�டை நீகà¯�கவà¯�à®®à¯� FunctionRepo max; trials; probability அதிகபடà¯�சமà¯�; சோதனைகளà¯�; நிகழà¯�தகவà¯� trials; probability சோதனைகளà¯�; நிகழà¯�தகவà¯� hits; trials; probability வெறà¯�றிகளà¯�; சோதனைகளà¯�; நிகழà¯�தகவà¯� max; total; hits; trials அதிகபடà¯�சமà¯�; மொதà¯�தமà¯�; வெறà¯�றிகளà¯�; சோதனைகளà¯� total; hits; trials மொதà¯�தமà¯�; வெறà¯�றிகளà¯�; சோதனைகளà¯� count; total; hits; trials எணà¯�ணிகà¯�கை; மொதà¯�தமà¯�; வெறà¯�றிகளà¯�; சோதனைகளà¯� dividend; divisor வகà¯�படà¯�à®®à¯�எணà¯�; வகà¯�பà¯�பானà¯� x; exponent_bits; significand_bits [; exponent_bias] ஃ; அடà¯�கà¯�கà¯�_பிடà¯�களà¯�; கà¯�றிபà¯�பிடதà¯�தகà¯�க மறà¯�à®±à¯�à®®à¯�_பிடà¯�களà¯� [; அடà¯�கà¯�கà¯�_சாரà¯�பà¯�] base; x அடிபà¯�படை எணà¯�; ஃ value; modulo மதிபà¯�பà¯�; தொகà¯�தி base; exponent; modulo அடிபà¯�படை; அடà¯�கà¯�கெணà¯�; மாடà¯�யூலோ events; average_events நிகழà¯�வà¯�களà¯�; சராசரி_நிகழà¯�வà¯�களà¯� average_events சராசரி_நிகழà¯�வà¯�களà¯� x [; precision] ஃ [; தà¯�லà¯�லியமà¯�] Absolute Value தà¯�லà¯�லியமான மதிபà¯�பà¯� Absolute Deviation à®®à¯�à®´à¯�மையான விலகலà¯� Arc Cosine ஆரà¯�கà¯� கொசைனà¯� Logical AND தரà¯�கà¯�க மறà¯�à®±à¯�à®®à¯� Area Hyperbolic Cosine பரபà¯�பà¯� ஹைபரà¯�போலிகà¯� கொசைனà¯� Area Hyperbolic Sine பரபà¯�பà¯� ஹைபரà¯�போலிகà¯� சைனà¯� Area Hyperbolic Tangent பரபà¯�பà¯� ஹைபரà¯�போலிகà¯� தொடà¯�கோடà¯� Arc Sine விறà¯�சைனà¯� Arc Tangent விரà¯�தà¯�தபாகமà¯� தொடà¯�கோடà¯� Arc Tangent with two Arguments இரணà¯�டà¯� வாதஙà¯�களà¯� கொணà¯�ட விரà¯�தà¯�தபாகமà¯� தொடà¯�கோடà¯� Average (Arithmetic Mean) சராசரி (எணà¯�கணித சராசரி) Binomial Cumulative Distribution Function இரà¯�வகை ஒடà¯�டà¯�மொதà¯�த விநியோக செயலà¯�பாடà¯� Binomial Distribution Mean இரà¯�வகை விநியோக சராசரி Binomial Probability Mass Function இரà¯�வகை நிகழà¯�தகவà¯� நிறை செயலà¯�பாடà¯� Binomial Distribution Variance இரà¯�வகை விநியோக மாறà¯�பாடà¯� Cube Root கனசதà¯�à®° மூலமà¯� Complex Conjugate இணைசà¯� சிகà¯�கலெணà¯� Cosine கொசைனà¯� Hyperbolic Cosine ஹைபரà¯�போலிகà¯� கொசைனà¯� Cotangent தலைகீழà¯� தொடà¯�கோடà¯� Cosecant தலைகீழà¯� சைனà¯� Convert Unix timestamp to Date யà¯�னிகà¯�சà¯� நேர à®®à¯�தà¯�திரையை தேதியாக மாறà¯�றவà¯�à®®à¯� Degrees of Arc விலà¯� பாகைகளà¯� Error Function பிழை செயலà¯�பாடà¯� Complementary Error Function நிரபà¯�பà¯� பிழை செயலà¯�பாடà¯� Exponential அடà¯�கà¯�கà¯�கà¯�கà¯�றிஎணà¯� Fractional Part பினà¯�ன பகà¯�தி Extension of Factorials [= (x-1)!] காரணிகளினà¯� நீடà¯�டிபà¯�பà¯� [= (x-1)!] Greatest Common Divisor மிகபà¯� பெரிய பொதà¯� வகà¯�பà¯�பானà¯� Geometric Mean வடிவியலà¯� சராசரி Gradians of arc விலà¯� கிரேடியனà¯�களà¯� Hypergeometric Cumulative Distribution Function மிகைவடிவியலà¯� ஒடà¯�டà¯�மொதà¯�த விநியோக செயலà¯�பாடà¯� Hypergeometric Distribution Mean மிகைவடிவியலà¯� விநியோக சராசரி Hypergeometric Probability Mass Function மிகைவடிவியலà¯� நிகழà¯�தகவà¯� நிறை செயலà¯�பாடà¯� Hypergeometric Distribution Variance மிகைவடிவியலà¯� விநியோக மாறà¯�பாடà¯� Integer Quotient à®®à¯�à®´à¯� எணà¯� அளவà¯� Integer Part à®®à¯�à®´à¯� எணà¯� பகà¯�தி Imaginary Part கறà¯�பனை பாகமà¯� Decode IEEE-754 Binary Value மதிபà¯�பை à®�இஇஇ-754 இரà¯�à®® கà¯�றிவிலகà¯�கவà¯�à®®à¯� Encode IEEE-754 Binary Value மதிபà¯�பை à®�இஇஇ-754 இரà¯�à®® கà¯�றியீடாகà¯�கவà¯�à®®à¯� Decode 16-bit Half-Precision Value 16-இரà¯�à®® இலகà¯�கஎணà¯� அரை தà¯�லà¯�லிய மதிபà¯�பà¯� கà¯�றிவிலகà¯�கவà¯�à®®à¯� Encode 16-bit Half-Precision Value 16-இரà¯�à®® இலகà¯�கஎணà¯� அரை தà¯�லà¯�லிய மதிபà¯�பà¯� கà¯�றியீடாகà¯�கவà¯�à®®à¯� Decode 32-bit Single-Precision Value 32-இரà¯�à®® இலகà¯�கஎணà¯� à®’à®±à¯�றை தà¯�லà¯�லிய மதிபà¯�பà¯� கà¯�றிவிலகà¯�கவà¯�à®®à¯� Encode 32-bit Single-Precision Value 32-இரà¯�à®® இலகà¯�கஎணà¯� à®’à®±à¯�றை தà¯�லà¯�லிய மதிபà¯�பà¯� கà¯�றியீடாகà¯�கவà¯�à®®à¯� Decode 64-bit Double-Precision Value 32-இரà¯�à®® இலகà¯�கஎணà¯� இரடà¯�டை தà¯�லà¯�லிய மதிபà¯�பà¯� கà¯�றிவிலகà¯�கவà¯�à®®à¯� Encode 64-bit Double-Precision Value 32-இரà¯�à®® இலகà¯�கஎணà¯� இரடà¯�டை தà¯�லà¯�லிய மதிபà¯�பà¯� கà¯�றியீடாகà¯�கவà¯�à®®à¯� Decode 128-bit Quad-Precision Value 32-இரà¯�à®® இலகà¯�கஎணà¯� நானà¯�கà¯� தà¯�லà¯�லிய மதிபà¯�பà¯� கà¯�றிவிலகà¯�கவà¯�à®®à¯� Encode 128-bit Quad-Precision Value 32-இரà¯�à®® இலகà¯�கஎணà¯� நானà¯�கà¯� தà¯�லà¯�லிய மதிபà¯�பà¯� கà¯�றியீடாகà¯�கவà¯�à®®à¯� Binary Logarithm இரà¯�à®® மடகà¯�கை Common Logarithm பொதà¯�வான மடகà¯�கை Natural Logarithm இயறà¯�கை மடகà¯�கை Logarithm to Arbitrary Base தனà¯�னிசà¯�சையான எணà¯�ணà¯�கà¯�கà¯� மடகà¯�கை Mask to a bit size à®®à¯�கமூடியை இரà¯�à®® அளவà¯� Maximum அதிகபடà¯�சமà¯� Median Value (50th Percentile) இடைநிலை மதிபà¯�பà¯� (50வதà¯� சதவீதமà¯�) Minimum கà¯�றைநà¯�தபடà¯�சமà¯� Modulo மாடà¯�லோ Euclidean Modulo யூகà¯�லிடியனà¯� மாடà¯�யூலோ Modular Exponentiation மாடà¯�யூலரà¯� அடà¯�கà¯�கீடà¯� Combination (Binomial Coefficient) சேரà¯�கà¯�கை (இரà¯�மை கà¯�ணகமà¯�) Logical NOT தரà¯�கà¯�கரீதியான இலà¯�லை Permutation (Arrangement) வரிசைமாறà¯�றமà¯� (à®�à®±à¯�பாடà¯�) Convert to Binary Representation இரà¯�மைபà¯� பிரதிநிதிதà¯�தà¯�வதà¯�திறà¯�கà¯� மாறà¯�றவà¯�à®®à¯� Arithmetic எணà¯�கணிதமà¯� Chemistry வேதியியலà¯� Complex கலபà¯�பà¯� எணà¯�களà¯� Combinatorics சேரà¯�கà¯�கையியலà¯� Probability நிகழà¯�தகவà¯� Statistics பà¯�ளà¯�ளியியலà¯� Aggregation திரடà¯�டலà¯� Random சீரறà¯�à®± Base conversion அடிமான மாறà¯�றமà¯� Number formatting எணà¯� வடிவமைபà¯�பà¯� Integer arithmetic à®®à¯�à®´à¯� எணà¯� கணிதமà¯� Special functions சிறபà¯�பà¯� சாரà¯�பà¯�களà¯� Exponential & Logarithmic அடà¯�கà¯�கியலà¯� & மடகà¯�கியலà¯� Angle conversion கோண மாறà¯�றமà¯� Trigonometry à®®à¯�கà¯�கோணவியலà¯� Bitwise பிடà¯�வாரி Floating point மிதகà¯�கà¯�à®®à¯� பà¯�ளà¯�ளி Date & Time தேதி & நேரமà¯� Linear algebra நேரியலà¯� இயறà¯�கணிதமà¯� unix_timestamp; x hours offset to GMT யà¯�னிகà¯�சà¯�_நேரமà¯�தà¯�திரை;; ஃ மணிநேரமà¯� உ.à®’.நே.கà¯�கà¯� ஈடà¯�செயà¯�யபà¯�படà¯�டதà¯� yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; GMT-இலிரà¯�நà¯�தà¯� x மணிநேர விலகலà¯� [digits] [இலகà¯�கஙà¯�களà¯�] max [; min] அதிகபடà¯�சமà¯� [; கà¯�றைநà¯�தபடà¯�சமà¯�] List Literal படà¯�டியலà¯� நிலைமதிபà¯�பà¯� Convert to Padded Binary Representation நிரபà¯�பிய இரà¯�மபà¯� பிரதிநிதிதà¯�தà¯�வமாக மாறà¯�à®±à¯� Round Toward +∞ (Ceiling) +∞ நோகà¯�கி வடà¯�டமிடà¯� (மேலà¯�à®®à¯�à®´à¯�மை) Cosine plus Imaginary Sine கோசைனà¯� கூடà¯�டலà¯� கறà¯�பனை சைனà¯� Convert to Cis Complex Form cis கலபà¯�பà¯� வடிவமாக மாறà¯�à®±à¯� Matrix Column Count அணி நெடà¯�வரிசை எணà¯�ணிகà¯�கை Population Correlation Matrix (n) à®®à¯�à®´à¯�தà¯�தொகà¯�தி தொடரà¯�பà¯� அணி (n) Sample Correlation Matrix (n-1) மாதிரி தொடரà¯�பà¯� அணி (n-1) Count எணà¯�ணிகà¯�கை Population Covariance Matrix (n) à®®à¯�à®´à¯�தà¯�தொகà¯�தி இணைமாறà¯�பாடà¯� அணி (n) Sample Covariance Matrix (n-1) மாதிரி இணைமாறà¯�பாடà¯� அணி (n-1) Cross Product கà¯�à®±à¯�கà¯�கà¯� பெரà¯�கà¯�கலà¯� Convert Date to Unix timestamp தேதியை Unix நேரமà¯�தà¯�திரையாக மாறà¯�à®±à¯� Convert to Decimal Representation தசம பிரதிநிதிதà¯�தà¯�வதà¯�திறà¯�கà¯� மாறà¯�றவà¯�à®®à¯� Determinant நிரà¯�ணாயகமà¯� Convert to Sexagesimal Notation à®…à®±à¯�பதடிமà¯�றை கà¯�றியீடà¯�டà¯�கà¯�கà¯� மாறà¯�à®±à¯� Dot Product பà¯�ளà¯�ளி பெரà¯�கà¯�கலà¯� Convert to Engineering Notation பொறியியலà¯� கà¯�றியீடà¯�டà¯�கà¯�கà¯� மாறà¯�à®±à¯� Convert to Exponential Complex Form அடà¯�கà¯�கியலà¯� கலபà¯�பà¯� வடிவமாக மாறà¯�à®±à¯� Round Toward −∞ (Floor) −∞ நோகà¯�கி வடà¯�டமிடà¯� (கீழà¯�à®®à¯�à®´à¯�மை) Flatten Matrix அணியை சமபà¯�படà¯�தà¯�தà¯� Least Common Multiple கà¯�றைநà¯�த பொதà¯�பà¯� பெரà¯�கà¯�கà¯� Convert to Hexadecimal Representation பதினà¯�à®® பிரதிநிதிதà¯�தà¯�வதà¯�திறà¯�கà¯� மாறà¯�றவà¯�à®®à¯� Convert to Padded Hexadecimal Representation நிரபà¯�பிய பதினாறà¯�மபà¯� பிரதிநிதிதà¯�தà¯�வமாக மாறà¯�à®±à¯� Inverse Matrix எதிரà¯� அணி Round to 16-bit Half-Precision Value 16-bit அரைதà¯� தà¯�லà¯�லிய மதிபà¯�பாக வடà¯�டமிடà¯� Round to 32-bit Single-Precision Value 32-bit à®’à®±à¯�றைதà¯� தà¯�லà¯�லிய மதிபà¯�பாக வடà¯�டமிடà¯� Round to 64-bit Double-Precision Value 64-bit இரடà¯�டைதà¯� தà¯�லà¯�லிய மதிபà¯�பாக வடà¯�டமிடà¯� Round to 128-bit Quad-Precision Value 128-bit நானà¯�கà¯� மடஙà¯�கà¯� தà¯�லà¯�லிய மதிபà¯�பாக வடà¯�டமிடà¯� Residual from 16-bit Half-Precision Rounding 16-bit அரைதà¯� தà¯�லà¯�லிய வடà¯�டமிடலினà¯� மீதி Residual from 32-bit Single-Precision Rounding 32-bit à®’à®±à¯�றைதà¯� தà¯�லà¯�லிய வடà¯�டமிடலினà¯� மீதி Residual from 64-bit Double-Precision Rounding 64-bit இரடà¯�டைதà¯� தà¯�லà¯�லிய வடà¯�டமிடலினà¯� மீதி Residual from 128-bit Quad-Precision Rounding 128-bit நானà¯�கà¯� மடஙà¯�கà¯� தà¯�லà¯�லிய வடà¯�டமிடலினà¯� மீதி Substance Mass பொரà¯�ளà¯� நிறை Molarity மோலாரிடà¯�டி Molar Mass மோலாரà¯� நிறை Median Absolute Deviation மதà¯�தியனà¯� à®®à¯�à®´à¯�மை விலகலà¯� Mean சராசரி Numerical Value of Quantity அளவினà¯� எணà¯� மதிபà¯�பà¯� Random Decimal Number சீரறà¯�à®± தசம எணà¯� Random Integer Number சீரறà¯�à®± à®®à¯�à®´à¯� எணà¯� Convert to Rational Representation விகிதமà¯�றை பிரதிநிதிதà¯�தà¯�வமாக மாறà¯�à®±à¯� Convert to Octal Representation எணà¯�à®® பிரதிநிதிதà¯�தà¯�வதà¯�திறà¯�கà¯� மாறà¯�றவà¯�à®®à¯� Convert to Padded Octal Representation நிரபà¯�பிய எணà¯�மபà¯� பிரதிநிதிதà¯�தà¯�வமாக மாறà¯�à®±à¯� Vector or Matrix Norm வெகà¯�டரà¯� அலà¯�லதà¯� அணி நெறி Logical OR தரà¯�கà¯�க அலà¯�லதà¯� Population Count (Hamming Weight) ஒனà¯�à®±à¯� பிடà¯� எணà¯�ணிகà¯�கை (ஹாமிஙà¯� எடை) Phase of Complex Number சிகà¯�கலான எணà¯�ணினà¯� கடà¯�டமà¯� Poissonian Cumulative Distribution Function பாயà¯�சோனியனà¯� ஒடà¯�டà¯�மொதà¯�த விநியோக செயலà¯�பாடà¯� Poissonian Distribution Mean பாயà¯�சோனியனà¯� விநியோக சராசரி Poissonian Probability Mass Function பாயà¯�சோனியனà¯� நிகழà¯�தகவà¯� நிறை செயலà¯�பாடà¯� Poissonian Distribution Variance பாயà¯�சோனியனà¯� விநியோக மாறà¯�பாடà¯� Convert to Phasor Complex Form ஃபேசரà¯� கலபà¯�பà¯� வடிவமாக மாறà¯�à®±à¯� Convert to Rectangular Complex Form செவà¯�வக கலபà¯�பà¯� வடிவமாக மாறà¯�à®±à¯� Round Half Away from Zero பாதியை பூஜà¯�ஜியதà¯�திலிரà¯�நà¯�தà¯� விலகà¯�கி வடà¯�டமிடà¯� Round Half Even பாதியை சமானமாக வடà¯�டமிடà¯� Nth Root n-ஆமà¯� படி மூலமà¯� Convert to Scientific Notation அறிவியலà¯� கà¯�றியீடà¯�டà¯�கà¯�கà¯� மாறà¯�à®±à¯� Matrix Row Count அணி வரி எணà¯�ணிகà¯�கை List or Matrix Shape படà¯�டியலà¯� அலà¯�லதà¯� அணியினà¯� வடிவமà¯� Summation கூடà¯�டà¯�தà¯�தொகை Population Standard Deviation (n) à®®à¯�à®´à¯�தà¯�தொகà¯�தி திடà¯�டவிலகà¯�கமà¯� (n) Sample Standard Deviation (n-1) மாதிரி திடà¯�டவிலகà¯�கமà¯� (n-1) Round Toward Zero (Truncation) பூஜà¯�ஜியதà¯�தை நோகà¯�கி வடà¯�டமிடà¯� (தà¯�ணà¯�டிதà¯�தலà¯�) Matrix Trace அணி தடமà¯� Transpose Matrix அணியை மாறà¯�à®±à¯� Population Variance (n) à®®à¯�à®´à¯�தà¯�தொகà¯�தி மாறà¯�பாடà¯� (n) Sample Variance (n-1) மாதிரி மாறà¯�பாடà¯� (n-1) Product பெரà¯�கà¯�கà¯� Radians ரேடியனà¯�களà¯� Matrix Rank அணி படிநிலை Real Part மெயà¯� பகà¯�தி Secant தலைகீழà¯� கொசைனà¯� Arithmetic Shift Left எணà¯�கணித மாறà¯�றமà¯� இடதà¯� Arithmetic Shift Right எணà¯�கணித மாறà¯�றமà¯� வலதà¯� Signum அடையாளமà¯� Sine சைனà¯� Hyperbolic Sine அதிபரவளைய சைனà¯� Square Root வரà¯�கà¯�கமூலமà¯� Sum தொகை Tangent தொடà¯�கோடà¯� Convert to Trigonometric Complex Form à®®à¯�கà¯�கோணவியலà¯� கலபà¯�பà¯� வடிவமாக மாறà¯�à®±à¯� Turns திரà¯�பà¯�பà¯�களà¯� Hyperbolic Tangent அதிபரவளைய தொடà¯�கோடà¯� Sign-extend a value à®’à®°à¯� மதிபà¯�பை கà¯�றிநீடà¯�டிகà¯�கவà¯�à®®à¯� Logical XOR தரà¯�கà¯�க இலà¯�லை அலà¯�லதà¯� FunctionsWidget Domain பிரிவà¯� All அனைதà¯�தà¯�à®®à¯� Name பெயரà¯� Search தேடà¯� No match found பொரà¯�தà¯�தமà¯� எதà¯�வà¯�à®®à¯� இலà¯�லை Identifier அடையாளஙà¯�காடà¯�டி HistoryWidget Remove All Calculations Above மேலà¯�ளà¯�ள அனைதà¯�தà¯� கணகà¯�கீடà¯�களையà¯�à®®à¯� அகறà¯�à®±à¯� Remove This Calculation இநà¯�த கணகà¯�கீடà¯�டை அகறà¯�à®±à¯� Remove All Calculations Below கீழà¯�ளà¯�ள அனைதà¯�தà¯� கணகà¯�கீடà¯�களையà¯�à®®à¯� அகறà¯�à®±à¯� Keypad Inverse cosine தலைகீழà¯� கொசைனà¯� The last result கடைசி à®®à¯�டிவà¯� Inverse sine தலைகீழà¯� சைனà¯� Inverse tangent தலைகீழà¯� தொடà¯�கோடà¯� Evaluate expression கூறà¯�றை கணகà¯�கிடà¯� Division வகà¯�தà¯�தலà¯� Multiplication பெரà¯�கà¯�கலà¯� Subtraction கழிதà¯�தலà¯� Addition கூடà¯�டலà¯� Clear expression கூறà¯�றை அழி Cosine கொசைனà¯� Backspace பினà¯�நீகà¯�கà¯� Scientific notation அறிவியலà¯� கà¯�றியீடà¯� Exponential அடà¯�கà¯�கà¯�கà¯�கà¯�றிகà¯�கà¯�ரிய Factorial காரணியலà¯� Natural logarithm இயறà¯�கை மடகà¯�கை Left parenthesis இடதà¯� அடைபà¯�பà¯�கà¯�கà¯�றி Nth root n-ஆமà¯� படி மூலமà¯� Argument separator மதிபà¯�பà¯�à®°à¯�பà¯� பிரிபà¯�பானà¯� Square வரà¯�கà¯�கமà¯� Common logarithm பொதà¯� மடகà¯�கை Modulo மாடà¯�லோ Contextual percentage சூழலியலà¯� சதவீதமà¯� Power அடà¯�கà¯�கà¯� Right parenthesis வலதà¯� அடைபà¯�பà¯�கà¯�கà¯�றி Sine சைனà¯� Square root வரà¯�கà¯�கமூலமà¯� Tangent தொடà¯�கோடà¯� Pi பை Decimal separator தசமபà¯� பிரிபà¯�பானà¯� MainWindow Radian ரேடியனà¯� Degree பாகை Gradian கிரேடியனà¯� Binary இரà¯�மமà¯� Octal எணà¯�மமà¯� Hexadecimal பதினாறà¯�மமà¯� Sexagesimal à®…à®±à¯�பதடிமà¯�றை Engineering decimal பொறியியலà¯� தசமமà¯� Scientific decimal அறிவியலà¯� தசமமà¯� &Import... &இறகà¯�கà¯�மதி... &Quit &வெளியேறà¯� Clear E&xpression வெ&ளிபà¯�பாடà¯� அழி Clear &History அழி &வரலாறà¯� &Copy &நகலà¯� &Paste &ஒடà¯�டà¯� &Select Expression &வெளிபà¯�பாடà¯�டை தேரà¯�நà¯�தெடà¯�கà¯�கவà¯�à®®à¯� &Constants &மாறிலிகளà¯� &Functions &செயலà¯�பாடà¯�களà¯� &History &வரலாறà¯� &Status Bar &நிலைமை படà¯�டை Bitfield இரà¯�மபà¯�லமà¯� Use&r Functions ப&யனரà¯� செயலà¯�பாடà¯� &Degree &பாகை &Radian &ரேடியனà¯� &Gradian &கிரேடியனà¯� Re&volution &சà¯�à®´à®±à¯�சி Auto-Insert a&ns a&ns-à®�தà¯� தானாகசà¯� செரà¯�கà¯� Automatic &Completion தானியஙà¯�கி &நிறைவà¯� &Built-in Functions &உளà¯�ளமைநà¯�த சாரà¯�பà¯�களà¯� Built-in &Variables உ&ளà¯�ளமைநà¯�த மாறிகளà¯� User &Functions &பயனரà¯� செயலà¯�பாடà¯� User Va&riables ப&யனரà¯� மாறிகளà¯� Open a Private Tab on Startup தொடகà¯�கதà¯�திலà¯� தனிபà¯�படà¯�ட தாவலைதà¯� திற Open and focus a new private tab whenever SpeedCrunch starts. SpeedCrunch தொடஙà¯�கà¯�à®®à¯�போதெலà¯�லாமà¯� பà¯�திய தனிபà¯�படà¯�ட தாவலைதà¯� திறநà¯�தà¯� அதிலà¯� கவனமà¯� செலà¯�தà¯�தà¯�. Syntax &Highlighting தொடரியலà¯� &சிறபà¯�பமà¯�சமாக Group Digits in &Input &உளà¯�ளீடà¯�டà¯� இலகà¯�கஙà¯�களைகà¯� கà¯�à®´à¯�வாகà¯�கà¯� Automatic Input &Adjustments தா&னியஙà¯�கà¯� உளà¯�ளீடà¯�டà¯�சà¯� சரிசெயà¯�தலà¯� Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. செயறà¯�கà¯�றிகளà¯�, இடைவெளிகளà¯�, அடைபà¯�பà¯�கà¯�கà¯�றிகளà¯� மறà¯�à®±à¯�à®®à¯� அடà¯�கà¯�கà¯�களைதà¯� தானாகசà¯� சரிசெயà¯�தà¯�, செலà¯�லà¯�படியான எழà¯�தà¯�தà¯�களை மடà¯�டà¯�à®®à¯� உளà¯�ளிட அனà¯�மதி. Group input digits using the selected number format. தேரà¯�நà¯�தெடà¯�தà¯�த எணà¯� வடிவதà¯�தினà¯�படி உளà¯�ளீடà¯�டà¯� இலகà¯�கஙà¯�களைகà¯� கà¯�à®´à¯�வாகà¯�கà¯�. &Blinking Cursor &மினà¯�à®™à¯�கà¯�à®®à¯� சà¯�டà¯�டி Blink the cursor in the expression editor. கோவைதà¯� திரà¯�தà¯�தியிலà¯� சà¯�டà¯�டியை மினà¯�à®™à¯�கசà¯� செயà¯�. &Escape Clears Editor &Escape திரà¯�தà¯�தியை அழிகà¯�கà¯�à®®à¯� Clear the focused expression editor with Escape after dismissing any popup or preview. மேலà¯�தோனà¯�à®±à¯�à®®à¯� சாளரஙà¯�களà¯� அலà¯�லதà¯� à®®à¯�னà¯�னோடà¯�டஙà¯�களை மூடிய பினà¯�, கவனதà¯�திலà¯� உளà¯�ள கோவைதà¯� திரà¯�தà¯�தியை Escape மூலமà¯� அழி. Keep Expression After Evaluation கணகà¯�கீடà¯�டà¯�கà¯�கà¯�பà¯� பினà¯� கோவையை வைதà¯�திரà¯� Copy New Results Automatically பà¯�திய à®®à¯�டிவà¯�களைதà¯� தானாக நகலெடà¯� &Comma &காறà¯�பà¯�ளà¯�ளி &System Default &கணினி இயலà¯�பà¯�நிலை &Dot &பà¯�ளà¯�ளி Dot &And Comma பà¯�ளà¯�ளி &மறà¯�à®±à¯�à®®à¯� காறà¯�பà¯�ளà¯�ளி Toward +∞ (&ceil) +∞ நோகà¯�கி (&ceil) Toward −∞ (&floor) −∞ நோகà¯�கி (&floor) &Binary &இரà¯�மமà¯� &Engineering &பொறியியலà¯� &Hexadecimal &பதினà¯�மஙà¯�களà¯� &Octal &எடà¯�டà¯�தà¯�தொகை &Scientific &அறிவியலà¯� User &Manual பயனரà¯� &கையேடà¯� Issues and &Feedback &சிகà¯�கலà¯�களà¯�à®®à¯� கரà¯�தà¯�தà¯�களà¯�à®®à¯� &Donate &நனà¯�கொடை &About SpeedCrunch &SpeedCrunch பறà¯�றி App Diag&nostics செ&யலிகà¯� கணà¯�டறிதலà¯� S&plit பி&ரி Angle &Mode &கோண à®®à¯�றை &Complex Form க&லபà¯�பெணà¯� வடிவமà¯� New Tab பà¯�திய தாவலà¯� Constants மாறிலிகளà¯� Functions செயலà¯�பாடà¯�களà¯� History வரலாறà¯� User Functions பயனரà¯� செயலà¯�பாடà¯� &Font... &எழà¯�தà¯�தà¯�à®°à¯�... &Language... &மொழி... &Session &அமரà¯�வà¯� &Edit &தொகà¯� &View &நோகà¯�கà¯� Se&ttings à®…&மைபà¯�பà¯�களà¯� &Decimal &தசம &Keypad &விசைபà¯�பலகை Always on &Top எபà¯�போதà¯�à®®à¯� &மேலே Disabled à®®à¯�டகà¯�கபà¯�படà¯�டதà¯� Small Space சிறிய இடமà¯� Medium Space நடà¯�தà¯�தர இடமà¯� Large Space பெரிய இடமà¯� &0 Digits &0 இலகà¯�கஙà¯�களà¯� &15 Digits &15 இலகà¯�கஙà¯�களà¯� &2 Digits &2 இலகà¯�கஙà¯�களà¯� &3 Digits &3 இலகà¯�கஙà¯�களà¯� &50 Digits &50 இலகà¯�கஙà¯�களà¯� &8 Digits &8 இலகà¯�கஙà¯�களà¯� &Sexagesimal &à®…à®±à¯�பதà¯� சாரà¯�நà¯�த Reset All Settings... அனைதà¯�தà¯� அமைபà¯�பà¯�களையà¯�à®®à¯� மீடà¯�டமை... &System &கணினி அமைபà¯�பà¯� SpeedCrunch &Theme &SpeedCrunch தோறà¯�றகà¯�கரà¯� &Classic &மரபான &Modern &நவீன Context Help சூழலà¯� உதவி &Help &உதவி Error பிழை Can't read from file %1 %1 கோபà¯�பிலிரà¯�நà¯�தà¯� படிகà¯�க à®®à¯�டியவிலà¯�லை Import Session அமரà¯�வை இறகà¯�கà¯�மதி செயà¯� Close Session அமரà¯�வை மூடà¯� Angle Mode: கோண à®®à¯�றை: Notation: கà¯�றியீடà¯�டà¯�à®®à¯�றை: Precision: தà¯�லà¯�லியமà¯�: Turn திரà¯�பà¯�பà¯� Revolution சà¯�à®´à®±à¯�சி Fixed-point decimal நிலைதà¯�த பà¯�ளà¯�ளி தசமமà¯� Rational விகிதமà¯�றை Automatic decimal தானியஙà¯�கி தசமமà¯� Automatic தானியஙà¯�கி User &Definitions... பயனரà¯� &வரையறைகளà¯�... New &Tab பà¯�திய &தாவலà¯� New &Private Tab &பà¯�திய தனிபà¯�படà¯�ட தாவலà¯� Keep வைதà¯�திரà¯� Make Private... தனிபà¯�படà¯�டதாகà¯�கà¯�... New &Window பà¯�திய &சாளரமà¯� &Open... &திற... &Rename... &மறà¯�பெயரிடà¯�... Clo&ne... ப&டியெடà¯�... &Close Tab தாவ&லை மூடà¯� Reopen Clo&sed Tab மூடி&ய தாவலை மீணà¯�டà¯�à®®à¯� திற Open Sessions &Folder அமரà¯�வà¯�களà¯� &கோபà¯�பà¯�றையைதà¯� திற &Undo &செயலà¯�தவிரà¯� &Redo &மீணà¯�டà¯�à®®à¯� செயà¯� Cu&t வெ&டà¯�டà¯� Copy &Last Result &கடைசி à®®à¯�டிவை நகலெடà¯� &Wrap in Parentheses &அடைபà¯�பà¯�கà¯�கà¯�றிகளà¯�கà¯�கà¯�ளà¯� இடà¯� Full Scr&een Mode à®®à¯�&à®´à¯�தà¯�திரை à®®à¯�றை &Basic &அடிபà¯�படை &Scientific (wide) &அறிவியலà¯� (அகலமà¯�) Scientific (narrow) அறிவியலà¯� (கà¯�à®±à¯�கலà¯�) &Custom... &தனிபà¯�பயனà¯�... Main &Menu à®®à¯�தனà¯�மை &படà¯�டி User &Variables பயனரà¯� &மாறிகளà¯� &Left &இடதà¯� &Right &வலதà¯� &Up &மேலே &Down &கீழே Close Pa&ne ப&லதà¯�தை மூடà¯� User &Units பயனரà¯� &அலகà¯�களà¯� &Turn &திரà¯�பà¯�பà¯� If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. பà¯�திய கூறà¯�à®±à¯� +, -, *, அலà¯�லதà¯� / கொணà¯�டà¯� தொடஙà¯�கினாலà¯�, SpeedCrunch à®®à¯�தலிலà¯� "ans"-à®� செரà¯�கà¯�à®®à¯�. &Accept with Enter &Enter மூலமà¯� à®�à®±à¯�à®±à¯�கà¯�கொளà¯� Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. தானியஙà¯�கà¯�நிரபà¯�பலினà¯� தறà¯�போதைய பரிநà¯�தà¯�ரையை à®®à¯�தலிலà¯� à®…à®®à¯�பà¯�கà¯�கà¯�றி விசைகளாலà¯� தேரà¯�நà¯�தெடà¯�கà¯�காமலேயே Enter மூலமà¯� à®�à®±à¯�à®±à¯�கà¯�கொளà¯�. &Units &அலகà¯�களà¯� Show Live Result &Preview உடனடி à®®à¯�டிவà¯� &à®®à¯�னà¯�னோடà¯�டதà¯�தைகà¯� காடà¯�டà¯� Save &Window Position on Exit வெளியேறà¯�à®®à¯� போதà¯� &சாளர நிலையை சேமி Hover Highlighting சà¯�டà¯�டி மேலிரà¯�கà¯�கà¯�à®®à¯� போதà¯� à®®à¯�னà¯�னிறà¯�தà¯�தலà¯� Group Integer Part Only à®®à¯�à®´à¯� எணà¯� பகà¯�தியை மடà¯�டà¯�à®®à¯� கà¯�à®´à¯�வாகà¯�கà¯� Number Format... எணà¯� வடிவமà¯�... Notation && Precision... கà¯�றியீடà¯�டà¯�à®®à¯�றை && தà¯�லà¯�லியமà¯�... After pressing Enter, keep the entered expression selected in the editor. Enter à®…à®´à¯�தà¯�திய பிறகà¯�, உளà¯�ளிடபà¯�படà¯�ட கூறà¯�றை திரà¯�தà¯�தியிலà¯� தேரà¯�நà¯�தெடà¯�தà¯�தபடி வைதà¯�திரà¯�. Never à®’à®°à¯�போதà¯�à®®à¯� இலà¯�லை Always எபà¯�போதà¯�à®®à¯� Only for Single-Line Expressions à®’à®±à¯�றைவரி கூறà¯�à®±à¯�களà¯�கà¯�கà¯� மடà¯�டà¯�à®®à¯� Simplify Displayed Expressions காடà¯�சியளிகà¯�கà¯�à®®à¯� கூறà¯�à®±à¯�களை எளிமைபà¯�படà¯�தà¯�தà¯� History Size &Limit... வரலாறà¯� அளவà¯� &வரமà¯�பà¯�... Remove Trailing &Zeroes &இறà¯�தி பூசà¯�சியஙà¯�களை அகறà¯�à®±à¯� Nearest, Half &Away (round) à®…à®°à¯�கியதà¯�, பாதி &விலகி (round) Nearest, Half &Even (roundeven) à®…à®°à¯�கியதà¯�, பாதி &சமமà¯� (roundeven) Toward &Zero (trunc) &பூஜà¯�ஜியதà¯�தை நோகà¯�கி (trunc) &Fixed-Point &நிலைதà¯�த பà¯�ளà¯�ளி &Rational &விகிதமà¯�றை &Exponential (m·sâ�»Â¹) &அடà¯�கà¯�கியலà¯� (m·sâ�»Â¹) &Fractional (m/s) &பினà¯�ன (m/s) &Rectangular (a + bi) &செவà¯�வக (a + bi) Exponential (reâ�±á¶¿) அடà¯�கà¯�கியலà¯� (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) à®®à¯�கà¯�கோணவியலà¯� (r(cos θ + i·sin θ)) Phasor (r∠θ) ஃபேசரà¯� (r∠θ) &Theme... &கரà¯�பà¯�பொரà¯�ளà¯�... Check for &Updates &பà¯�தà¯�பà¯�பிபà¯�பà¯�களைசà¯� சரிபாரà¯� Source Code மூலகà¯� கà¯�றியீடà¯� &Zoom &பெரிதாகà¯�கà¯� &Results &à®®à¯�டிவà¯�களà¯� Unit Notation அலகà¯� கà¯�றியீடà¯�டà¯�à®®à¯�றை Rounding Mode வடà¯�டமிடà¯�à®®à¯� à®®à¯�றை &Notation &கà¯�றியீடà¯�டà¯�à®®à¯�றை &Imaginary Unit &கறà¯�பனை அலகà¯� &Window &சாளரமà¯� &Editing &திரà¯�தà¯�தமà¯� A&utocomplete &தானியகà¯�க நிறைவà¯� Up/Down Arrow History மேலà¯�/கீழà¯� à®…à®®à¯�பà¯� வரலாறà¯� &Appearance &தோறà¯�றமà¯� &Menus &படà¯�டிகளà¯� &Docks நி&லையிணைபà¯�பà¯�பà¯� பலகைகளà¯� &Input and Results &உளà¯�ளீடà¯�à®®à¯� à®®à¯�டிவà¯�களà¯�à®®à¯� &Disabled &à®®à¯�டகà¯�கபà¯�படà¯�டதà¯� &Disable &à®®à¯�டகà¯�கà¯� Close preview à®®à¯�னà¯�னோடà¯�டதà¯�தை மூடà¯� Rename... மறà¯�பெயரிடà¯�... Clone... படியெடà¯�... Close Tab தாவலை மூடà¯� New Private Tab பà¯�திய தனிபà¯�படà¯�ட தாவலà¯� Open... திற... Reopen Closed Tab மூடிய தாவலை மீணà¯�டà¯�à®®à¯� திற Split பிரி Left இடதà¯� Right வலதà¯� Up மேலே Down கீழே Clear அழி Delete நீகà¯�கà¯� %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 தனிபà¯�படà¯�ட அமரà¯�வà¯�: மூடà¯�à®®à¯�போதà¯� உளà¯�ளடகà¯�கமà¯� கைவிடபà¯�படà¯�à®®à¯�. வழகà¯�கமான அமரà¯�வாக மாறà¯�à®± அமரà¯�வà¯� > வைதà¯�திரà¯� எனà¯�பதைதà¯� தேரà¯�நà¯�தெடà¯�கà¯�கவà¯�à®®à¯�. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [தனிபà¯�படà¯�டதà¯�] Reset All Settings அனைதà¯�தà¯� அமைபà¯�பà¯�களையà¯�à®®à¯� மீடà¯�டமை Reset all settings to their default values? எலà¯�லா அமைபà¯�பà¯�களையà¯�à®®à¯� இயலà¯�பà¯�நிலை மதிபà¯�பà¯�களà¯�கà¯�கà¯� மீடà¯�டமைகà¯�கவா? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. இதிலà¯� தோறà¯�றமà¯�, திரà¯�தà¯�தமà¯�, à®®à¯�டிவà¯� வடிவஙà¯�களà¯� மறà¯�à®±à¯�à®®à¯� சாளர விரà¯�பà¯�பஙà¯�களà¯� அடஙà¯�கà¯�à®®à¯�. உஙà¯�களà¯� கணகà¯�கீடà¯�களà¯�, திறநà¯�த அமரà¯�வà¯�களà¯� மறà¯�à®±à¯�à®®à¯� பயனரà¯� வரையறைகளà¯� பாதà¯�காகà¯�கபà¯�படà¯�à®®à¯�. The settings file could not be written. அமைபà¯�பà¯�கà¯� கோபà¯�பை எழà¯�த à®®à¯�டியவிலà¯�லை. Clear this session's calculations, unfinished expression, variables, functions, and units? இநà¯�த அமரà¯�வினà¯� கணகà¯�கீடà¯�களà¯�, à®®à¯�டிகà¯�காத கோவை, மாறிகளà¯�, சாரà¯�பà¯�களà¯� மறà¯�à®±à¯�à®®à¯� அலகà¯�களை அழிகà¯�கவா? Global user definitions are kept. பொதà¯�வான பயனரà¯� வரையறைகளà¯� பாதà¯�காகà¯�கபà¯�படà¯�à®®à¯�. Make Session Private அமரà¯�வைதà¯� தனிபà¯�படà¯�டதாகà¯�கà¯� The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. சேமிதà¯�த அமரà¯�வà¯� %1 நீகà¯�கபà¯�படà¯�à®®à¯�. அதனà¯� உளà¯�ளடகà¯�கமà¯� தனிபà¯�படà¯�ட அமரà¯�விலà¯� திறநà¯�திரà¯�கà¯�கà¯�à®®à¯�. அநà¯�த அமரà¯�வை மூடà¯�à®®à¯�போதà¯� அலà¯�லதà¯� SpeedCrunch-இலிரà¯�நà¯�தà¯� வெளியேறà¯�à®®à¯�போதà¯� அதà¯� கைவிடபà¯�படà¯�à®®à¯�. Make Private தனிபà¯�படà¯�டதாகà¯�கà¯� Could not delete the saved session %1. சேமிதà¯�த அமரà¯�வà¯� %1-à®� நீகà¯�க à®®à¯�டியவிலà¯�லை. Keep Session அமரà¯�வை வைதà¯�திரà¯� Could not save the session. It remains private. அமரà¯�வைசà¯� சேமிகà¯�க à®®à¯�டியவிலà¯�லை. அதà¯� தனிபà¯�படà¯�டதாகவே உளà¯�ளதà¯�. Clone Session அமரà¯�வைபà¯� படியெடà¯� Could not save session file %1. அமரà¯�வà¯�கà¯� கோபà¯�பà¯� %1-à®�சà¯� சேமிகà¯�க à®®à¯�டியவிலà¯�லை. Could not delete session file %1. அமரà¯�வà¯�கà¯� கோபà¯�பà¯� %1-à®� நீகà¯�க à®®à¯�டியவிலà¯�லை. JSON file (*.json);;Any file (*.*) JSON கோபà¯�பà¯� (*.json);;எநà¯�த கோபà¯�பà¯�à®®à¯� (*.*) Export session as JSON அமரà¯�வை JSON ஆக à®�à®±à¯�à®±à¯�மதி செயà¯�யவà¯�à®®à¯� The selected file is not valid JSON: %1 தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட கோபà¯�பà¯� செலà¯�லà¯�படியாகà¯�à®®à¯� JSON அலà¯�ல: %1 The selected file is not a SpeedCrunch session JSON file. தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட கோபà¯�பà¯� SpeedCrunch அமரà¯�வà¯� JSON கோபà¯�பà¯� அலà¯�ல. This file uses an obsolete SpeedCrunch session format and cannot be imported. இநà¯�த கோபà¯�பà¯� காலாவதியான SpeedCrunch அமரà¯�வà¯� வடிவதà¯�தைபà¯� பயனà¯�படà¯�தà¯�தà¯�கிறதà¯�, இறகà¯�கà¯�மதி செயà¯�ய à®®à¯�டியாதà¯�. The selected JSON file is missing the required $schema field. தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட JSON கோபà¯�பிலà¯� தேவையான $schema பà¯�லமà¯� இலà¯�லை. The selected JSON file uses an unsupported JSON schema: %1 தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட JSON கோபà¯�பà¯� ஆதரிகà¯�கபà¯�படாத JSON திடà¯�டதà¯�தைபà¯� பயனà¯�படà¯�தà¯�தà¯�கிறதà¯�: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட JSON கோபà¯�பிலà¯� SpeedCrunch அமரà¯�வà¯� திடà¯�ட அடையாளஙà¯�காடà¯�டி ($id) இலà¯�லை. The selected JSON file uses an unsupported SpeedCrunch session format: %1 தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட JSON கோபà¯�பà¯� ஆதரிகà¯�கபà¯�படாத SpeedCrunch அமரà¯�வà¯� வடிவதà¯�தைபà¯� பயனà¯�படà¯�தà¯�தà¯�கிறதà¯�: %1 The selected JSON file is missing the required session name. தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட JSON கோபà¯�பிலà¯� தேவையான அமரà¯�வà¯� பெயரà¯� இலà¯�லை. The selected JSON file has an empty session name. தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட JSON கோபà¯�பிலà¯� அமரà¯�வà¯� பெயரà¯� காலியாக உளà¯�ளதà¯�. The selected JSON file has invalid or incomplete SpeedCrunch session data. தேரà¯�நà¯�தெடà¯�கà¯�கபà¯�படà¯�ட JSON கோபà¯�பிலà¯� செலà¯�லà¯�படியாகாத அலà¯�லதà¯� à®®à¯�à®´à¯�மையறà¯�à®± SpeedCrunch அமரà¯�வà¯� தரவà¯� உளà¯�ளதà¯�. Open Sessions Folder அமரà¯�வà¯�களà¯� கோபà¯�பà¯�றையைதà¯� திற Could not create the sessions folder: %1 அமரà¯�வà¯�களà¯� கோபà¯�பà¯�றையை உரà¯�வாகà¯�க à®®à¯�டியவிலà¯�லை: %1 Could not open the sessions folder: %1 அமரà¯�வà¯�களà¯� கோபà¯�பà¯�றையைதà¯� திறகà¯�க à®®à¯�டியவிலà¯�லை: %1 Editor and Results Font திரà¯�தà¯�தி மறà¯�à®±à¯�à®®à¯� à®®à¯�டிவà¯�களினà¯� எழà¯�தà¯�தà¯�à®°à¯� Open Session அமரà¯�வைதà¯� திற Community சமூகமà¯� Rename Session அமரà¯�வினà¯� பெயரை மாறà¯�à®±à¯� Clear Session அமரà¯�வை அழி Delete Session அமரà¯�வை நீகà¯�கà¯� Close Pane பலதà¯�தை மூடà¯� User Variables பயனரà¯� மாறிகளà¯� User Units பயனரà¯� அலகà¯�களà¯� Clear History வரலாறà¯�றை அழி Are you sure you want to clear the calculation history? கணகà¯�கீடà¯�டà¯� வரலாறà¯�றை அழிகà¯�க வேணà¯�டà¯�மா? Session name: அமரà¯�வà¯� பெயரà¯�: A session named %1 already exists. %1 எனà¯�à®± பெயரà¯�டைய அமரà¯�வà¯� à®�à®±à¯�கனவே உளà¯�ளதà¯�. Could not create session file %1. %1 அமரà¯�வà¯� கோபà¯�பை உரà¯�வாகà¯�க à®®à¯�டியவிலà¯�லை. Could not write session file %1. %1 அமரà¯�வà¯� கோபà¯�பை எழà¯�த à®®à¯�டியவிலà¯�லை. Are you sure you want to delete this session? இநà¯�த அமரà¯�வை நீகà¯�க வேணà¯�டà¯�மா? Custom Precision தனிபà¯�பயனà¯� தà¯�லà¯�லியமà¯� Fractional digits: பினà¯�ன இலகà¯�கஙà¯�களà¯�: Theme கரà¯�பà¯�பொரà¯�ளà¯� Light Themes ஒளி கரà¯�பà¯�பொரà¯�ளà¯�களà¯� Dark Themes இரà¯�ளà¯� கரà¯�பà¯�பொரà¯�ளà¯�களà¯� Preview à®®à¯�னà¯�னோடà¯�டமà¯� Colors நிறஙà¯�களà¯� Select color for %1 %1-கà¯�கà¯� நிறதà¯�தைதà¯� தேரà¯�நà¯�தெடà¯� Import... இறகà¯�கà¯�மதி... Export... à®�à®±à¯�à®±à¯�மதி... Import Theme கரà¯�பà¯�பொரà¯�ளை இறகà¯�கà¯�மதி செயà¯� Theme file (*.json);;All files (*) கரà¯�பà¯�பொரà¯�ளà¯� கோபà¯�பà¯� (*.json);;அனைதà¯�தà¯� கோபà¯�பà¯�களà¯�à®®à¯� (*) Invalid theme file. செலà¯�லாத கரà¯�பà¯�பொரà¯�ளà¯� கோபà¯�பà¯�. Can't import theme "%1" because it conflicts with a built-in theme. "%1" கரà¯�பà¯�பொரà¯�ளை இறகà¯�கà¯�மதி செயà¯�ய à®®à¯�டியவிலà¯�லை; அதà¯� உளà¯�ளமைநà¯�த கரà¯�பà¯�பொரà¯�ளà¯�டனà¯� à®®à¯�ரணà¯�படà¯�கிறதà¯�. Can't find a writable theme folder. எழà¯�தகà¯�கூடிய கரà¯�பà¯�பொரà¯�ளà¯� அடைவை கணà¯�டà¯�பிடிகà¯�க à®®à¯�டியவிலà¯�லை. Overwrite Theme கரà¯�பà¯�பொரà¯�ளை மேலெழà¯�தà¯� A custom theme named "%1" already exists. Do you want to overwrite it? "%1" எனà¯�à®± தனிபà¯�பயனà¯� கரà¯�பà¯�பொரà¯�ளà¯� à®�à®±à¯�கனவே உளà¯�ளதà¯�. அதை மேலெழà¯�த வேணà¯�டà¯�மா? Can't overwrite theme file %1 %1 கரà¯�பà¯�பொரà¯�ளà¯� கோபà¯�பை மேலெழà¯�த à®®à¯�டியவிலà¯�லை Can't copy theme file to %1 கரà¯�பà¯�பொரà¯�ளà¯� கோபà¯�பை %1-கà¯�கà¯� நகலெடà¯�கà¯�க à®®à¯�டியவிலà¯�லை Export Theme கரà¯�பà¯�பொரà¯�ளை à®�à®±à¯�à®±à¯�மதி செயà¯� Can't export theme as "%1" because it conflicts with a built-in theme. "%1" என கரà¯�பà¯�பொரà¯�ளை à®�à®±à¯�à®±à¯�மதி செயà¯�ய à®®à¯�டியவிலà¯�லை; அதà¯� உளà¯�ளமைநà¯�த கரà¯�பà¯�பொரà¯�ளà¯�டனà¯� à®®à¯�ரணà¯�படà¯�கிறதà¯�. Can't write to file %1 %1 கோபà¯�பிலà¯� எழà¯�த à®®à¯�டியவிலà¯�லை Global User Variable à®®à¯�à®´à¯�மையான பயனரà¯� மாறி Global User Function à®®à¯�à®´à¯�மையான பயனரà¯� சாரà¯�பà¯� Global User Unit à®®à¯�à®´à¯�மையான பயனரà¯� அலகà¯� User Definitions பயனரà¯� வரையறைகளà¯� These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. இநà¯�த வரையறைகளà¯� உலகளாவியவை; ஒவà¯�வொரà¯� அமரà¯�விலà¯�à®®à¯� à®�à®±à¯�றபà¯�படà¯�à®®à¯�. அமரà¯�வà¯�களிலà¯� இவறà¯�றை மாறà¯�à®± à®®à¯�டியாதà¯�; அமரà¯�வà¯�தà¯� திரà¯�தà¯�தியிலà¯� உளà¯�ள அதே பெயரà¯�டைய வரையறைகளை விட இவறà¯�à®±à¯�கà¯�கே à®®à¯�னà¯�னà¯�ரிமை உணà¯�டà¯�. ஒவà¯�வொரà¯� வரியிலà¯�à®®à¯� à®’à®°à¯� வரையறையை உளà¯�ளிடவà¯�à®®à¯�. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] எடà¯�தà¯�தà¯�கà¯�காடà¯�டà¯�களà¯�: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply பயனà¯�படà¯�தà¯�தà¯� Validate சரிபாரà¯� Test Results சோதனை à®®à¯�டிவà¯�களà¯� Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 இறகà¯�கà¯�மதி செயà¯�யபà¯�படà¯�ட மாறிகளà¯�: %1 இறகà¯�கà¯�மதி செயà¯�யபà¯�படà¯�ட சாரà¯�பà¯�களà¯�: %2 இறகà¯�கà¯�மதி செயà¯�யபà¯�படà¯�ட அலகà¯�களà¯�: %3 பிழைகளà¯� உளà¯�ள வரிகளினà¯� எணà¯�களà¯�: %4 none எதà¯�வà¯�மிலà¯�லை Apply Results பயனà¯�படà¯�தà¯�தியதனà¯� à®®à¯�டிவà¯�களà¯� User definitions saved. பயனரà¯� வரையறைகளà¯� சேமிகà¯�கபà¯�படà¯�டன. History Size Limit வரலாறà¯� அளவà¯� வரமà¯�பà¯� Maximum number of history entries for this session (0 = unlimited): இநà¯�த அமரà¯�விறà¯�கான அதிகபடà¯�ச வரலாறà¯� பதிவà¯�களà¯� (0 = வரமà¯�பிலà¯�லை): Text file (*.txt);;Any file (*.*) உரை கோபà¯�பà¯� (*.txt);; எநà¯�த கோபà¯�பà¯�à®®à¯� (*.*) Could not recalculate from calculation %1: %2 %1 கணகà¯�கீடà¯�டிலிரà¯�நà¯�தà¯� மறà¯�கணகà¯�கிட à®®à¯�டியவிலà¯�லை: %2 History Size Limit Reached வரலாறà¯� அளவà¯� வரமà¯�பை எடà¯�டியதà¯� This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. இநà¯�த கணகà¯�கீடà¯� கிடைகà¯�கà¯�à®®à¯� கடைசி வரலாறà¯� இடதà¯�தை நிரபà¯�பà¯�கிறதà¯�. இனி வரà¯�à®®à¯� கணகà¯�கீடà¯�களà¯� வரலாறà¯�றிலிரà¯�நà¯�தà¯� மிகபà¯� பழைய கணகà¯�கீடà¯�டை அகறà¯�à®±à¯�à®®à¯�. அமரà¯�வà¯� > வரலாறà¯� அளவà¯� வரமà¯�பà¯� வழியாக வரமà¯�பை அதிகரிகà¯�கலாமà¯�. Editing calculation. Press Esc twice to cancel. கணகà¯�கீடà¯� திரà¯�தà¯�தபà¯�படà¯�கிறதà¯�. ரதà¯�தà¯�செயà¯�ய Esc-à®� இரà¯�à®®à¯�றை à®…à®´à¯�தà¯�தவà¯�à®®à¯�. Calculation Settings கணகà¯�கீடà¯�டà¯� அமைபà¯�பà¯�களà¯� Invalid recalculation start index மறà¯�கணகà¯�கீடà¯�டà¯� தொடகà¯�க கà¯�றியீடà¯� செலà¯�லாதà¯� System Default கணினி இயலà¯�பà¯�நிலை Language மொழி Select the language: மொழியைதà¯� தேரà¯�நà¯�தெடà¯�கà¯�கவà¯�à®®à¯�: Custom தனிபà¯�பயனà¯� Decimal places: தசம இடஙà¯�களà¯�: &Automatic &தானியஙà¯�கி &Precision &தà¯�லà¯�லியமà¯� Plain &text எளிய &உரை Formula &Book சூதà¯�திரமà¯� &பà¯�தà¯�தகமà¯� &Export &à®�à®±à¯�à®±à¯�மதி Export session as HTML அமரà¯�வை மிஉகà¯�மொ ஆக à®�à®±à¯�à®±à¯�மதி செயà¯�யவà¯�à®®à¯� HTML file (*.html) மிஉகà¯�மொ கோபà¯�பà¯� (*.html) Export session as plain text அமரà¯�வை எளிய உரையாக à®�à®±à¯�à®±à¯�மதி செயà¯�யவà¯�à®®à¯� ManualWindow SpeedCrunch Manual SpeedCrunch கையேடà¯� %1 - SpeedCrunch Manual %1 - SpeedCrunch கையேடà¯� NumberFormatDialog Number Format எணà¯� வடிவமà¯� <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>à®®à¯�டிவà¯�களà¯�கà¯�கà¯�à®®à¯� உளà¯�ளீடà¯�டà¯� இலகà¯�ககà¯� கà¯�à®´à¯�வாகà¯�கதà¯�திறà¯�கà¯�மான எணà¯� வடிவதà¯�தைதà¯� தேரà¯�நà¯�தெடà¯�கà¯�கவà¯�à®®à¯�.</b><br/><br/>கà¯�றிபà¯�பà¯�: உளà¯�ளிடà¯�à®®à¯� எணà¯�களினà¯� தெளிவான வடிவஙà¯�களà¯� தேரà¯�நà¯�தெடà¯�தà¯�த காடà¯�சி வடிவதà¯�திலிரà¯�நà¯�தà¯� மாறà¯�படà¯�டாலà¯�à®®à¯� à®�à®±à¯�கபà¯�படà¯�à®®à¯�.<br/> QObject Global User Variable à®®à¯�à®´à¯�மையான பயனரà¯� மாறி Global User Function à®®à¯�à®´à¯�மையான பயனரà¯� சாரà¯�பà¯� Global User Unit à®®à¯�à®´à¯�மையான பயனரà¯� அலகà¯� Backspace பினà¯�நீகà¯�கà¯� Clear expression கூறà¯�றை அழி Evaluate expression கூறà¯�றை கணகà¯�கிடà¯� Insert text உரையைசà¯� செரà¯�கà¯� Automatic decimal தானியஙà¯�கி தசமமà¯� Fixed-point decimal நிலைதà¯�த பà¯�ளà¯�ளி தசமமà¯� Engineering decimal பொறியியலà¯� தசமமà¯� Scientific decimal அறிவியலà¯� தசமமà¯� Rational விகிதமà¯�றை Binary இரà¯�மமà¯� Octal எணà¯�மமà¯� Hexadecimal பதினாறà¯�மமà¯� Sexagesimal à®…à®±à¯�பதடிமà¯�றை Update Available பà¯�தà¯�பà¯�பிபà¯�பà¯� உளà¯�ளதà¯� A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> பà¯�திய பதிபà¯�பà¯� (%1) உளà¯�ளதà¯�.<br/><a href="%2">பதிவிறகà¯�க இணையதளதà¯�திறà¯�கà¯�சà¯� செலà¯�லவà¯�à®®à¯�.</a> Check for Updates பà¯�தà¯�பà¯�பிபà¯�பà¯�களைசà¯� சரிபாரà¯� SpeedCrunch %1 is up to date. SpeedCrunch %1 பà¯�தà¯�பà¯�பிதà¯�த நிலையிலà¯� உளà¯�ளதà¯�. No connectivity. Please check your internet connection and try again. இணைபà¯�பà¯� இலà¯�லை. உஙà¯�களà¯� இணைய இணைபà¯�பைசà¯� சரிபாரà¯�தà¯�தà¯� மீணà¯�டà¯�à®®à¯� à®®à¯�யறà¯�சிகà¯�கவà¯�à®®à¯�. Could not verify the latest available version. கிடைகà¯�கà¯�à®®à¯� சமீபதà¯�திய பதிபà¯�பைசà¯� சரிபாரà¯�கà¯�க à®®à¯�டியவிலà¯�லை. ResultDisplay Scroll to bottom கீழே உரà¯�டà¯�டà¯� Edit Expression கூறà¯�றைதà¯� திரà¯�தà¯�தà¯� Change Settings அமைபà¯�பà¯�களை மாறà¯�à®±à¯� New Tab பà¯�திய தாவலà¯� &Import... &இறகà¯�கà¯�மதி... &Export &à®�à®±à¯�à®±à¯�மதி Plain &text எளிய &உரை Copy நகலà¯� Selection தேரà¯�வà¯� Select All அனைதà¯�தையà¯�à®®à¯� தேரà¯�நà¯�தெடà¯� Expression கோவை Result à®®à¯�டிவà¯� Calculation கணகà¯�கீடà¯� Calculation as Single Line ஒரே வரியிலà¯� கணகà¯�கீடà¯� Remove அகறà¯�à®±à¯� This Calculation இநà¯�தகà¯� கணகà¯�கீடà¯� All Calculations Above மேலà¯�ளà¯�ள எலà¯�லாகà¯� கணகà¯�கீடà¯�களà¯�à®®à¯� All Calculations Below கீழà¯�ளà¯�ள எலà¯�லாகà¯� கணகà¯�கீடà¯�களà¯�à®®à¯� New Private Tab பà¯�திய தனிபà¯�படà¯�ட தாவலà¯� Session அமரà¯�வà¯� Open... திற... Clone... படியெடà¯�... Rename... மறà¯�பெயரிடà¯�... Keep வைதà¯�திரà¯� Make Private... தனிபà¯�படà¯�டதாகà¯�கà¯�... Clear அழி Delete நீகà¯�கà¯� Close மூடà¯� Split பிரி Left இடதà¯� Right வலதà¯� Up மேலே Down கீழே Close Pane பலதà¯�தை மூடà¯� Main Menu à®®à¯�தனà¯�மை படà¯�டி Cancel editing திரà¯�தà¯�ததà¯�தை ரதà¯�தà¯�செயà¯� Copy result à®®à¯�டிவை நகலெடà¯� Edit expression கூறà¯�றைதà¯� திரà¯�தà¯�தà¯� Change settings அமைபà¯�பà¯�களை மாறà¯�à®±à¯� Remove calculation கணகà¯�கீடà¯�டை அகறà¯�à®±à¯� ResultSlotsDialog Notation & Precision கà¯�றியீடà¯�டà¯�à®®à¯�றை & தà¯�லà¯�லியமà¯� Result Line à®®à¯�டிவà¯� வரி Enabled இயகà¯�கபà¯�படà¯�டதà¯� Notation கà¯�றியீடà¯�டà¯�à®®à¯�றை Decimal Places தசம இடஙà¯�களà¯� Main Line à®®à¯�தனà¯�மை வரி Extra Line #1 கூடà¯�தலà¯� வரி #1 Extra Line #2 கூடà¯�தலà¯� வரி #2 Extra Line #3 கூடà¯�தலà¯� வரி #3 Extra Line #4 கூடà¯�தலà¯� வரி #4 Auto தானியஙà¯�கà¯� UserFunctionListWidget Name பெயரà¯� Value மதிபà¯�பà¯� Description விளகà¯�கமà¯� Search தேடà¯� No match found பொரà¯�தà¯�தமà¯� எதà¯�வà¯�à®®à¯� இலà¯�லை Insert செரà¯�கà¯� Edit திரà¯�தà¯�தà¯� Delete நீகà¯�கà¯� Delete All அனைதà¯�தையà¯�à®®à¯� நீகà¯�கà¯� UserUnitListWidget Name பெயரà¯� Value மதிபà¯�பà¯� Description விளகà¯�கமà¯� Search தேடà¯� No match found பொரà¯�தà¯�தமà¯� எதà¯�வà¯�à®®à¯� இலà¯�லை Insert செரà¯�கà¯� Edit திரà¯�தà¯�தà¯� Delete நீகà¯�கà¯� Delete All அனைதà¯�தையà¯�à®®à¯� நீகà¯�கà¯� VariableListWidget Name பெயரà¯� Value மதிபà¯�பà¯� Description விளகà¯�கமà¯� Search தேடà¯� No match found பொரà¯�தà¯�தமà¯� எதà¯�வà¯�à®®à¯� இலà¯�லை Insert செரà¯�கà¯� Edit திரà¯�தà¯�தà¯� Delete நீகà¯�கà¯� Delete All அனைதà¯�தையà¯�à®®à¯� நீகà¯�கà¯� heldercorreia-speedcrunch-e7ca37f/src/resources/locale/te.ts000066400000000000000000012004511526573132500243600ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunch à°—à±�à°°à°¿à°‚à°šà°¿ Core developers à°ªà±�రధాన డెవలపరà±�à°²à±� Original author అసలà±� రచయిత Close మూసివేయి Math engine గణిత ఇంజినà±� Main author | Logo | Maintainer à°ªà±�రధాన రచయిత | లోగో | నిరà±�వహణకరà±�à°¤ Thanks à°§à°¨à±�యవాదాలà±� Copyright (C) 2004-2026 The SpeedCrunch developers కాపీరైటà±� (C) 2004-2026 SpeedCrunch అభివృదà±�à°§à°¿à°•à°°à±�తలà±� This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version à°ˆ à°ªà±�రోగà±�రామà±� ఉచిత సాఫà±�à°Ÿà±�‌వేరà±�; ఉచిత సాఫà±�à°Ÿà±�‌వేరà±� ఫౌండేషనà±� à°ªà±�à°°à°šà±�రించినటà±�à°²à±� మీరà±� దానిని à°ªà±�నఃపంపిణీ చేయవచà±�à°šà±� మరియà±� / లేదా GNU జనరలà±� పబà±�లికà±� లైసెనà±�à°¸à±� నిబంధనల à°ªà±�రకారం సవరించవచà±�à°šà±�; లైసెనà±�à°¸à±� యొకà±�à°• సంసà±�à°•à°°à°£ 2, లేదా (మీ ఎంపిక వదà±�à°¦) à°�దైనా తరà±�వాతి సంసà±�à°•à°°à°£ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. à°ˆ à°ªà±�రోగà±�రామà±� ఉపయోగకరంగా ఉంటà±�ందనే ఆశతో పంపిణీ చేయబడà±�à°¤à±�ంది, కానీ à°Žà°Ÿà±�వంటి వారంటీ లేకà±�à°‚à°¡à°¾; వాణిజà±�యయోగà±�యత లేదా నిరà±�దిషà±�à°Ÿ à°ªà±�రయోజనానికి à°…à°¨à±�కూలత అనే సూచిత వారంటీ కూడా లేకà±�à°‚à°¡à°¾. మరినà±�ని వివరాలకà±� GNU జనరలà±� పబà±�లికà±� లైసెనà±�à°¸à±� చూడండి. BitFieldWidget Reset bits to zero బిటà±�‌లనà±� à°¸à±�à°¨à±�నాకà±� రీసెటà±� చేయండి Invert bits బిటà±�‌లనà±� తలకిందà±�à°²à±� చేయండి Shift bits left బిటà±�‌లనà±� ఎడమకà±� జరపండి Shift bits right బిటà±�‌లనà±� à°•à±�à°¡à°¿à°•à°¿ జరపండి Book Index సూచిక Algebra బీజగణితం Quadratic Equation à°¦à±�విఘాత సమీకరణం Logarithmic Base Conversion లాగారిథమికà±� ఆధార మారà±�పిడి Geometry à°œà±�యామితి Circle వృతà±�తం Sector వృతà±�à°¤ à°–à°‚à°¡à°‚ Sphere గోళం Cube ఘనం Cone à°¶à°‚à°•à±�à°µà±� Cylinder సిలిండరà±� Electronics ఎలకà±�à°Ÿà±�రానికà±�à°¸à±� Ohm's Law à°“à°®à±� నియమం Power విదà±�à°¯à±�à°¤à±� à°¶à°•à±�తి Reactance రియాకà±�టెనà±�à°¸à±� Resonance రెసొనెనà±�à°¸à±� Radio Frequency రేడియో à°«à±�రీకà±�వెనà±�సీ Antennas యాంటెనà±�నాలà±� Characteristic Impedance (coax) లాకà±�షణిక ఇంపీడెనà±�à°¸à±� (coax) Velocity of Propagation (coax) à°ªà±�రసరణ వేగం (coax) Standing Wave Ratio & Return Loss à°¸à±�టాండింగà±� వేవà±� నిషà±�పతà±�తి & à°°à°¿à°Ÿà°°à±�à°¨à±� లాసà±� Free Space Wavelength à°¸à±�వేచà±�ఛా à°¸à±�థల తరంగదైరà±�à°˜à±�యం resistance à°ªà±�రతిరోధం voltage వోలà±�టేజà±� current విదà±�à°¯à±�à°¤à±� à°ªà±�రవాహం power à°¶à°•à±�తి inductive reactance ఇండకà±�à°Ÿà°¿à°µà±� రియాకà±�టెనà±�à°¸à±� capacitive reactance కెపాసిటివà±� రియాకà±�టెనà±�à°¸à±� inductance ఇండకà±�టెనà±�à°¸à±� capacitance కెపాసిటెనà±�à°¸à±� frequency ఆవృతà±�తి resonance frequency రెసొనెనà±�à°¸à±� ఆవృతà±�తి area వైశాలà±�యం perimeter పరిధి diameter à°µà±�యాసం radius à°µà±�యాసారà±�థం volume ఘనపరిమాణం surface area ఉపరితల వైశాలà±�యం height à°Žà°¤à±�à°¤à±� slant height వాలà±� à°Žà°¤à±�à°¤à±� face diagonal à°®à±�à°– వికరà±�ణం space diagonal à°¸à±�థల వికరà±�ణం edge length à°…à°‚à°šà±� పొడవà±� arc length చాప పొడవà±� central angle (degrees) కేందà±�à°° కోణం (à°¡à°¿à°—à±�రీలà±�) input power ఇనà±�‌పà±�à°Ÿà±� à°¶à°•à±�తి reflected power à°ªà±�రతిఫలిత à°¶à°•à±�తి transmitted power à°ªà±�రసారిత à°¶à°•à±�తి return loss à°°à°¿à°Ÿà°°à±�à°¨à±� లాసà±� dielectric constant డైఎలకà±�à°Ÿà±�à°°à°¿à°•à±� à°¸à±�థిరాంకం outer conductor's inner diameter బాహà±�à°¯ à°•à°‚à°¡à°•à±�à°Ÿà°°à±� అంతరà±�à°—à°¤ à°µà±�యాసం inner conductor's outer diameter అంతరà±�à°—à°¤ à°•à°‚à°¡à°•à±�à°Ÿà°°à±� బాహà±�à°¯ à°µà±�యాసం speed of light కాంతి వేగం reflection coefficient à°ªà±�రతిఫలన à°—à±�ణకం standing wave ratio à°¸à±�టాండింగà±� వేవà±� నిషà±�పతà±�తి normalized impedance సాధారణీకరించిన ఇంపీడెనà±�à°¸à±� frequency (Hz) ఆవృతà±�తి (Hz) BookDock Formula Book సూతà±�రాల à°ªà±�à°¸à±�తకం ConstantCompletion Search constants à°¸à±�థిరాంకాలనà±� శోధించà±� No match found సరిపోలిక కనబడలేదà±� Constants Mathematics గణితం Physics (CODATA 2022) భౌతికశాసà±�à°¤à±�à°°à°‚ (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) రసాయనశాసà±�à°¤à±�à°°à°‚ (IUPAC - CIAAW 2021) Uncategorized వరà±�గీకరించనివి Universal సారà±�వతà±�à°°à°¿à°• Physicochemical భౌతిక రసాయన సంబంధిత Atomic & Nuclear — General à°…à°£à±� & à°…à°£à±�కేందà±�à°° — సాధారణ Atomic & Nuclear — Electroweak à°…à°£à±� & à°…à°£à±�కేందà±�à°° — ఎలకà±�à°Ÿà±�రోవీకà±� Atomic & Nuclear — Electron à°…à°£à±� & à°…à°£à±�కేందà±�à°° — ఎలకà±�à°Ÿà±�రానà±� Atomic & Nuclear — Muon à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°®à±�యూయానà±� Atomic & Nuclear — Tau à°…à°£à±� & à°…à°£à±�కేందà±�à°° — టౌ Atomic & Nuclear — Proton à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°ªà±�రోటానà±� Atomic & Nuclear — Neutron à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°¨à±�యూటà±�రానà±� Atomic & Nuclear — Deuteron à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°¡à±�యూటెరానà±� Atomic & Nuclear — Triton à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°Ÿà±�రిటానà±� Atomic & Nuclear — Helion à°…à°£à±� & à°…à°£à±�కేందà±�à°° — హీలియనà±� Atomic & Nuclear — Alpha particle à°…à°£à±� & à°…à°£à±�కేందà±�à°° — ఆలà±�à°«à°¾ కణం Atomic & Nuclear — Atomic units à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°…à°£à±� యూనిటà±�à°²à±� Atomic & Nuclear — Energy conversion relationships à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°¶à°•à±�తి మారà±�పిడి సంబంధాలà±� Atomic & Nuclear — X-ray units à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°Žà°•à±�à°¸à±�-రే యూనిటà±�à°²à±� Atomic & Nuclear — Magnetic shielding corrections à°…à°£à±� & à°…à°£à±�కేందà±�à°° — à°šà±�ంబక కవచ సవరణలà±� Masses à°¦à±�à°°à°µà±�యరాశà±�à°²à±� Lifetimes జీవితకాలాలà±� Molar Masses మోలారà±� à°¦à±�à°°à°µà±�యరాశà±�à°²à±� Electronegativity విదà±�à°¯à±�à°¤à±� ఋణాతà±�మకత Ionization Energy అయనీకరణ à°¶à°•à±�తి Nominal Constants (IAU 2015) నామమాతà±�à°° à°¸à±�థిరాంకాలà±� (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) à°ªà±�à°°à°¸à±�à°¤à±�à°¤ ఉతà±�తమ అంచనాలà±� (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) లాకà±�షణిక ఇంపెడెనà±�à°¸à±� యొకà±�à°• శూనà±�యం (Zâ‚€) reduced Planck constant (â„�) తగà±�à°—à°¿à°‚à°šà°¿à°¨ à°ªà±�లాంకà±� à°¸à±�థిరాంకం (â„�) vacuum electric permittivity (ϵ₀) శూనà±�యం విదà±�à°¯à±�à°¤à±� పరà±�మిటివిటీ (ϵ₀) Newtonian constant of gravitation (G) à°¨à±�యూటనియనà±� à°¸à±�థిరాంకం యొకà±�à°• à°—à±�à°°à±�à°¤à±�వాకరà±�à°·à°£ (G) vacuum magnetic permeability (μ₀) శూనà±�యం à°šà±�ంబక పరà±�మియబిలిటీ (μ₀) Planck constant (h) à°ªà±�లాంకà±� à°¸à±�థిరాంకం (h) speed of light in vacuum (c) కాంతి వేగం లో శూనà±�యం (c) standard acceleration of gravity (gâ‚™) à°—à±�à°°à±�à°¤à±�à°µ à°ªà±�రమాణ à°¤à±�వరణం (gâ‚™) Newtonian constant of gravitation over h-bar c à°¨à±�యూటనియనà±� à°¸à±�థిరాంకం యొకà±�à°• à°—à±�à°°à±�à°¤à±�వాకరà±�à°·à°£ పై h-bar c Planck length à°ªà±�లాంకà±� పొడవà±� Planck constant in eV/Hz (h) à°ªà±�లాంకà±� à°¸à±�థిరాంకం లో eV/Hz (h) Planck mass à°ªà±�లాంకà±� à°¦à±�à°°à°µà±�యరాశి Planck mass energy equivalent in GeV à°ªà±�లాంకà±� à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో GeV Planck temperature à°ªà±�లాంకà±� ఉషà±�ణోగà±�à°°à°¤ Planck time à°ªà±�లాంకà±� సమయం reduced Planck constant in eV·s (â„�) తగà±�à°—à°¿à°‚à°šà°¿à°¨ à°ªà±�లాంకà±� à°¸à±�థిరాంకం లో eV·s (â„�) reduced Planck constant times c in MeV·fm తగà±�à°—à°¿à°‚à°šà°¿à°¨ à°ªà±�లాంకà±� à°¸à±�థిరాంకం రెటà±�à°²à±� c లో MeV·fm Bohr magneton బోరà±� మాగà±�నెటానà±� conductance quantum (Gâ‚€) వాహకతà±�à°µ à°•à±�వాంటం (Gâ‚€) Coulomb constant (kâ‚‘) కూలాంబà±� à°¸à±�థిరాంకం (kâ‚‘) elementary charge (e) à°ªà±�రాథమిక ఆవేశం (e) elementary charge over h-bar à°ªà±�రాథమిక ఆవేశం పై h-bar conventional value of Josephson constant సంపà±�రదాయ విలà±�à°µ యొకà±�à°• జోసెఫà±�సనà±� à°¸à±�థిరాంకం Josephson constant జోసెఫà±�సనà±� à°¸à±�థిరాంకం conventional value of ampere-90 సంపà±�రదాయ విలà±�à°µ యొకà±�à°• ఆంపియరà±�-90 conventional value of coulomb-90 సంపà±�రదాయ విలà±�à°µ యొకà±�à°• కూలాంబà±�-90 conventional value of farad-90 సంపà±�రదాయ విలà±�à°µ యొకà±�à°• ఫారడà±�-90 conventional value of henry-90 సంపà±�రదాయ విలà±�à°µ యొకà±�à°• హెనà±�à°°à±€-90 conventional value of ohm-90 సంపà±�రదాయ విలà±�à°µ యొకà±�à°• à°“à°‚-90 conventional value of volt-90 సంపà±�రదాయ విలà±�à°µ యొకà±�à°• వోలà±�à°Ÿà±�-90 conventional value of watt-90 సంపà±�రదాయ విలà±�à°µ యొకà±�à°• వాటà±�-90 magnetic flux quantum (Φ₀) à°šà±�ంబక à°«à±�లకà±�à°¸à±� à°•à±�వాంటం (Φ₀) nuclear magneton à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� inverse of conductance quantum విలోమ యొకà±�à°• వాహకతà±�à°µ à°•à±�వాంటం conventional value of von Klitzing constant సంపà±�రదాయ విలà±�à°µ యొకà±�à°• వానà±� à°•à±�లిటà±�జింగà±� à°¸à±�థిరాంకం von Klitzing constant వానà±� à°•à±�లిటà±�జింగà±� à°¸à±�థిరాంకం atomic unit of magnetic dipole moment à°…à°£à±� యూనిటà±� యొకà±�à°• à°šà±�ంబక à°¦à±�విధà±�à°°à±�à°µ à°•à±�షణం atomic unit of magnetic flux density à°…à°£à±� యూనిటà±� యొకà±�à°• à°šà±�ంబక à°«à±�లకà±�à°¸à±� సాందà±�à°°à°¤ Bohr magneton in eV/T బోరà±� మాగà±�నెటానà±� లో eV/T Bohr magneton in Hz/T బోరà±� మాగà±�నెటానà±� లో Hz/T Bohr magneton in inverse meter per tesla బోరà±� మాగà±�నెటానà±� లో విలోమ మీటరà±� à°•à±� టెసà±�లా Bohr magneton in K/T బోరà±� మాగà±�నెటానà±� లో K/T nuclear magneton in eV/T à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� లో eV/T nuclear magneton in inverse meter per tesla à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� లో విలోమ మీటరà±� à°•à±� టెసà±�లా nuclear magneton in K/T à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� లో K/T nuclear magneton in MHz/T à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� లో MHz/T Bohr radius (aâ‚€) బోరà±� à°µà±�యాసారà±�థం (aâ‚€) fine-structure constant (α) సూకà±�à°·à±�à°®-నిరà±�మాణ à°¸à±�థిరాంకం (α) Hartree energy (Eâ‚•) హారà±�à°Ÿà±�à±�à°°à±€ à°¶à°•à±�తి (Eâ‚•) Hartree energy in eV హారà±�à°Ÿà±�à±�à°°à±€ à°¶à°•à±�తి లో eV quantum of circulation à°ªà±�రసరణ à°•à±�వాంటం quantum of circulation times 2 à°ªà±�రసరణ à°•à±�వాంటం రెటà±�à°²à±� 2 Rydberg constant (R∞) à°°à°¿à°¡à±�‌బరà±�à°—à±� à°¸à±�థిరాంకం (R∞) atomic mass unit-hartree relationship à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±�-hartree సంబంధం atomic mass unit-hertz relationship à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±�-హెరà±�à°Ÿà±�à°œà±� సంబంధం atomic mass unit-inverse meter relationship à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±�-విలోమ మీటరà±� సంబంధం atomic mass unit-joule relationship à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±�-జూలà±� సంబంధం atomic mass unit-kelvin relationship à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±�-కెలà±�వినà±� సంబంధం atomic mass unit-kilogram relationship à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±�-కిలోగà±�రామà±� సంబంధం atomic unit of 1st hyperpolarizability à°…à°£à±� యూనిటà±� యొకà±�à°• 1st hyperpolarizability atomic unit of 2nd hyperpolarizability à°…à°£à±� యూనిటà±� యొకà±�à°• 2nd hyperpolarizability atomic unit of charge (e) à°…à°£à±� యూనిటà±� యొకà±�à°• charge (e) atomic unit of charge density à°…à°£à±� యూనిటà±� యొకà±�à°• ఆవేశ సాందà±�à°°à°¤ atomic unit of current à°…à°£à±� యూనిటà±� యొకà±�à°• విదà±�à°¯à±�à°¤à±� à°ªà±�రవాహం atomic unit of electric dipole moment à°…à°£à±� యూనిటà±� యొకà±�à°• విదà±�à°¯à±�à°¤à±� à°¦à±�విధà±�à°°à±�à°µ à°•à±�షణం atomic unit of electric field à°…à°£à±� యూనిటà±� యొకà±�à°• విదà±�à°¯à±�à°¤à±� à°•à±�షేతà±�à°°à°‚ atomic unit of electric field gradient à°…à°£à±� యూనిటà±� యొకà±�à°• విదà±�à°¯à±�à°¤à±� à°•à±�షేతà±�à°° à°ªà±�రవణత atomic unit of electric polarizability à°…à°£à±� యూనిటà±� యొకà±�à°• విదà±�à°¯à±�à°¤à±� à°§à±�à°°à±�వణీయత atomic unit of electric potential à°…à°£à±� యూనిటà±� యొకà±�à°• విదà±�à°¯à±�à°¤à±� పొటెనà±�షియలà±� atomic unit of electric quadrupole moment à°…à°£à±� యూనిటà±� యొకà±�à°• విదà±�à°¯à±�à°¤à±� à°šà°¤à±�à°°à±�à°§à±�à°°à±�à°µ à°•à±�షణం atomic unit of action à°…à°£à±� యూనిటà±� యొకà±�à°• à°šà°°à±�à°¯ atomic unit of energy à°…à°£à±� యూనిటà±� యొకà±�à°• à°¶à°•à±�తి atomic unit of force à°…à°£à±� యూనిటà±� యొకà±�à°• బలం atomic unit of length à°…à°£à±� యూనిటà±� యొకà±�à°• పొడవà±� hertz-atomic mass unit relationship హెరà±�à°Ÿà±�à°œà±�-à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±� సంబంధం hertz-electron volt relationship హెరà±�à°Ÿà±�à°œà±�-ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±� సంబంధం hertz-hartree relationship హెరà±�à°Ÿà±�à°œà±�-hartree సంబంధం hertz-inverse meter relationship హెరà±�à°Ÿà±�à°œà±�-విలోమ మీటరà±� సంబంధం hertz-joule relationship హెరà±�à°Ÿà±�à°œà±�-జూలà±� సంబంధం hertz-kelvin relationship హెరà±�à°Ÿà±�à°œà±�-కెలà±�వినà±� సంబంధం hertz-kilogram relationship హెరà±�à°Ÿà±�à°œà±�-కిలోగà±�రామà±� సంబంధం hyperfine transition frequency of Cs-133 హైపరà±�‌ఫైనà±� మారà±�à°ªà±� ఆవరà±�తనం యొకà±�à°• Cs-133 inverse fine-structure constant (αâ�»Â¹) విలోమ సూకà±�à°·à±�à°®-నిరà±�మాణ à°¸à±�థిరాంకం (αâ�»Â¹) inverse meter-atomic mass unit relationship విలోమ మీటరà±�-à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±� సంబంధం inverse meter-electron volt relationship విలోమ మీటరà±�-ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±� సంబంధం inverse meter-hartree relationship విలోమ మీటరà±�-hartree సంబంధం inverse meter-hertz relationship విలోమ మీటరà±�-హెరà±�à°Ÿà±�à°œà±� సంబంధం inverse meter-joule relationship విలోమ మీటరà±�-జూలà±� సంబంధం inverse meter-kelvin relationship విలోమ మీటరà±�-కెలà±�వినà±� సంబంధం inverse meter-kilogram relationship విలోమ మీటరà±�-కిలోగà±�రామà±� సంబంధం joule-atomic mass unit relationship జూలà±�-à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±� సంబంధం joule-electron volt relationship జూలà±�-ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±� సంబంధం joule-hertz relationship జూలà±�-హెరà±�à°Ÿà±�à°œà±� సంబంధం joule-hartree relationship జూలà±�-hartree సంబంధం joule-inverse meter relationship జూలà±�-విలోమ మీటరà±� సంబంధం joule-kelvin relationship జూలà±�-కెలà±�వినà±� సంబంధం joule-kilogram relationship జూలà±�-కిలోగà±�రామà±� సంబంధం kelvin-atomic mass unit relationship కెలà±�వినà±�-à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±� సంబంధం kelvin-electron volt relationship కెలà±�వినà±�-ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±� సంబంధం kelvin-hertz relationship కెలà±�వినà±�-హెరà±�à°Ÿà±�à°œà±� సంబంధం kelvin-hartree relationship కెలà±�వినà±�-hartree సంబంధం kelvin-inverse meter relationship కెలà±�వినà±�-విలోమ మీటరà±� సంబంధం kelvin-joule relationship కెలà±�వినà±�-జూలà±� సంబంధం kelvin-kilogram relationship కెలà±�వినà±�-కిలోగà±�రామà±� సంబంధం kilogram-atomic mass unit relationship కిలోగà±�రామà±�-à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±� సంబంధం kilogram-electron volt relationship కిలోగà±�రామà±�-ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±� సంబంధం kilogram-hertz relationship కిలోగà±�రామà±�-హెరà±�à°Ÿà±�à°œà±� సంబంధం kilogram-hartree relationship కిలోగà±�రామà±�-hartree సంబంధం kilogram-inverse meter relationship కిలోగà±�రామà±�-విలోమ మీటరà±� సంబంధం kilogram-joule relationship కిలోగà±�రామà±�-జూలà±� సంబంధం kilogram-kelvin relationship కిలోగà±�రామà±�-కెలà±�వినà±� సంబంధం lattice parameter of silicon (a) lattice parameter యొకà±�à°• silicon (a) luminous efficacy à°ªà±�రకాశ సామరà±�à°¥à±�యం natural unit of energy natural unit యొకà±�à°• à°¶à°•à±�తి natural unit of energy in MeV natural unit యొకà±�à°• à°¶à°•à±�తి లో MeV natural unit of action (â„�) natural unit యొకà±�à°• à°šà°°à±�à°¯ (â„�) natural unit of action in eV·s natural unit యొకà±�à°• à°šà°°à±�à°¯ లో eV·s natural unit of length natural unit యొకà±�à°• పొడవà±� natural unit of mass natural unit యొకà±�à°• à°¦à±�à°°à°µà±�యరాశి natural unit of momentum natural unit యొకà±�à°• momentum natural unit of momentum in MeV/c natural unit యొకà±�à°• momentum లో MeV/c natural unit of time natural unit యొకà±�à°• సమయం natural unit of velocity natural unit యొకà±�à°• velocity Rydberg constant times c in Hz à°°à°¿à°¡à±�‌బరà±�à°—à±� à°¸à±�థిరాంకం రెటà±�à°²à±� c లో Hz Rydberg constant times hc in eV à°°à°¿à°¡à±�‌బరà±�à°—à±� à°¸à±�థిరాంకం రెటà±�à°²à±� hc లో eV Rydberg constant times hc in J à°°à°¿à°¡à±�‌బరà±�à°—à±� à°¸à±�థిరాంకం రెటà±�à°²à±� hc లో J Fermi coupling constant Fermi coupling à°¸à±�థిరాంకం weak mixing angle బలహీన మిశà±�à°°à°£ కోణం W to Z mass ratio W to Z à°¦à±�à°°à°µà±�యరాశి ratio Thomson cross section (σₑ) థామà±�సనà±� à°•à±�రాసà±� సెకà±�à°·à°¨à±� (σₑ) electron mass (mâ‚‘) electron à°¦à±�à°°à°µà±�యరాశి (mâ‚‘) electron mass in u electron à°¦à±�à°°à°µà±�యరాశి లో u electron mass energy equivalent (mₑ·c²) electron à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� (mₑ·c²) electron mass energy equivalent in MeV electron à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో MeV reduced Compton wavelength తగà±�à°—à°¿à°‚à°šà°¿à°¨ Compton wavelength classical electron radius (râ‚‘) classical electron à°µà±�యాసారà±�థం (râ‚‘) electron charge to mass quotient electron charge to à°¦à±�à°°à°µà±�యరాశి quotient electron-deuteron magnetic moment ratio ఎలకà±�à°Ÿà±�రానà±�-à°¡à±�యూటెరానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి electron-deuteron mass ratio electron-deuteron à°¦à±�à°°à°µà±�యరాశి ratio electron g factor (gâ‚‘) ఎలకà±�à°Ÿà±�రానà±� g కారకం (gâ‚‘) electron gyromagnetic ratio (γₑ) ఎలకà±�à°Ÿà±�రానà±� గైరోమాగà±�నెటికà±� నిషà±�పతà±�తి (γₑ) electron gyromagnetic ratio in MHz/T electron gyromagnetic ratio లో MHz/T electron-helion mass ratio electron-helion à°¦à±�à°°à°µà±�యరాశి ratio electron magnetic moment (μₑ) ఎలకà±�à°Ÿà±�రానà±� అయసà±�కాంత ఘూరà±�ణం (μₑ) electron magnetic moment anomaly (aâ‚‘) ఎలకà±�à°Ÿà±�రానà±� అయసà±�కాంత ఘూరà±�ణం అసాధారణత (aâ‚‘) electron magnetic moment to Bohr magneton ratio electron magnetic moment to బోరà±� మాగà±�నెటానà±� ratio electron magnetic moment to nuclear magneton ratio electron magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio electron molar mass (Mâ‚‘) electron molar à°¦à±�à°°à°µà±�యరాశి (Mâ‚‘) electron-muon magnetic moment ratio ఎలకà±�à°Ÿà±�రానà±�-à°®à±�యూయానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి electron-muon mass ratio electron-muon à°¦à±�à°°à°µà±�యరాశి ratio electron-neutron magnetic moment ratio ఎలకà±�à°Ÿà±�రానà±�-à°¨à±�యూటà±�రానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి electron-neutron mass ratio electron-neutron à°¦à±�à°°à°µà±�యరాశి ratio electron-proton magnetic moment ratio ఎలకà±�à°Ÿà±�రానà±�-à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి electron-proton mass ratio electron-proton à°¦à±�à°°à°µà±�యరాశి ratio electron relative atomic mass (Ar(e)) electron relative atomic à°¦à±�à°°à°µà±�యరాశి (Ar(e)) electron-tau mass ratio electron-tau à°¦à±�à°°à°µà±�యరాశి ratio electron to alpha particle mass ratio electron to alpha particle à°¦à±�à°°à°µà±�యరాశి ratio electron to shielded helion magnetic moment ratio ఎలకà±�à°Ÿà±�రానà±� à°¨à±�à°‚à°¡à°¿ షీలà±�à°¡à±� చేసిన హీలియనà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి electron to shielded proton magnetic moment ratio ఎలకà±�à°Ÿà±�రానà±� à°¨à±�à°‚à°¡à°¿ షీలà±�à°¡à±� చేసిన à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి electron-triton mass ratio electron-triton à°¦à±�à°°à°µà±�యరాశి ratio electron volt-atomic mass unit relationship ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±�-à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±� సంబంధం electron volt-hartree relationship ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±�-hartree సంబంధం electron volt-hertz relationship ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±�-హెరà±�à°Ÿà±�à°œà±� సంబంధం electron volt-inverse meter relationship ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±�-విలోమ మీటరà±� సంబంధం electron volt-joule relationship ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±�-జూలà±� సంబంధం electron volt-kelvin relationship ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±�-కెలà±�వినà±� సంబంధం electron volt-kilogram relationship ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±�-కిలోగà±�రామà±� సంబంధం hartree-atomic mass unit relationship hartree-à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±� సంబంధం hartree-electron volt relationship hartree-ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±� సంబంధం muon Compton wavelength à°®à±�యూయానà±� కాంపà±�à°Ÿà°¨à±� తరంగదైరà±�à°˜à±�యం muon-electron mass ratio muon-electron à°¦à±�à°°à°µà±�యరాశి ratio muon g factor à°®à±�యూయానà±� g కారకం muon magnetic moment à°®à±�యూయానà±� అయసà±�కాంత ఘూరà±�ణం muon magnetic moment anomaly à°®à±�యూయానà±� అయసà±�కాంత ఘూరà±�ణం అసాధారణత muon magnetic moment to Bohr magneton ratio muon magnetic moment to బోరà±� మాగà±�నెటానà±� ratio muon magnetic moment to nuclear magneton ratio muon magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio muon mass muon à°¦à±�à°°à°µà±�యరాశి muon mass energy equivalent muon à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� muon mass energy equivalent in MeV muon à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో MeV muon mass in u muon à°¦à±�à°°à°µà±�యరాశి లో u muon molar mass muon molar à°¦à±�à°°à°µà±�యరాశి muon-neutron mass ratio muon-neutron à°¦à±�à°°à°µà±�యరాశి ratio muon-proton magnetic moment ratio à°®à±�యూయానà±�-à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి muon-proton mass ratio muon-proton à°¦à±�à°°à°µà±�యరాశి ratio muon-tau mass ratio muon-tau à°¦à±�à°°à°µà±�యరాశి ratio reduced muon Compton wavelength తగà±�à°—à°¿à°‚à°šà°¿à°¨ muon Compton wavelength reduced tau Compton wavelength తగà±�à°—à°¿à°‚à°šà°¿à°¨ tau Compton wavelength tau Compton wavelength టావà±� కాంపà±�à°Ÿà°¨à±� తరంగదైరà±�à°˜à±�యం tau-electron mass ratio tau-electron à°¦à±�à°°à°µà±�యరాశి ratio tau mass tau à°¦à±�à°°à°µà±�యరాశి tau mass energy equivalent tau à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� tau mass in u tau à°¦à±�à°°à°µà±�యరాశి లో u tau molar mass tau molar à°¦à±�à°°à°µà±�యరాశి tau-muon mass ratio tau-muon à°¦à±�à°°à°µà±�యరాశి ratio tau-neutron mass ratio tau-neutron à°¦à±�à°°à°µà±�యరాశి ratio tau-proton mass ratio tau-proton à°¦à±�à°°à°µà±�యరాశి ratio proton charge to mass quotient proton charge to à°¦à±�à°°à°µà±�యరాశి quotient proton Compton wavelength à°ªà±�రోటానà±� కాంపà±�à°Ÿà°¨à±� తరంగదైరà±�à°˜à±�యం proton-electron mass ratio proton-electron à°¦à±�à°°à°µà±�యరాశి ratio proton g factor (gₚ) à°ªà±�రోటానà±� g కారకం (gₚ) proton gyromagnetic ratio (γₚ) à°ªà±�రోటానà±� గైరోమాగà±�నెటికà±� నిషà±�పతà±�తి (γₚ) proton gyromagnetic ratio in MHz/T proton gyromagnetic ratio లో MHz/T proton magnetic moment (μₚ) à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం (μₚ) proton magnetic moment to Bohr magneton ratio proton magnetic moment to బోరà±� మాగà±�నెటానà±� ratio proton magnetic moment to nuclear magneton ratio proton magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio proton magnetic shielding correction à°ªà±�రోటానà±� అయసà±�కాంత షీలà±�à°¡à°¿à°‚à°—à±� సవరణ proton mass (mₚ) proton à°¦à±�à°°à°µà±�యరాశి (mₚ) proton mass energy equivalent proton à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� proton mass energy equivalent in MeV proton à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో MeV proton mass in u proton à°¦à±�à°°à°µà±�యరాశి లో u proton molar mass (Mₚ) proton molar à°¦à±�à°°à°µà±�యరాశి (Mₚ) proton-muon mass ratio proton-muon à°¦à±�à°°à°µà±�యరాశి ratio proton-neutron magnetic moment ratio à°ªà±�రోటానà±�-à°¨à±�యూటà±�రానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి proton-neutron mass ratio proton-neutron à°¦à±�à°°à°µà±�యరాశి ratio proton relative atomic mass (Ar(p)) proton relative atomic à°¦à±�à°°à°µà±�యరాశి (Ar(p)) proton rms charge radius proton rms charge à°µà±�యాసారà±�థం proton-tau mass ratio proton-tau à°¦à±�à°°à°µà±�యరాశి ratio reduced proton Compton wavelength తగà±�à°—à°¿à°‚à°šà°¿à°¨ proton Compton wavelength shielded proton gyromagnetic ratio షీలà±�à°¡à±� చేసిన à°ªà±�రోటానà±� గైరోమాగà±�నెటికà±� నిషà±�పతà±�తి shielded proton gyromagnetic ratio in MHz/T shielded proton gyromagnetic ratio లో MHz/T shielded proton magnetic moment షీలà±�à°¡à±� చేసిన à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం shielded proton magnetic moment to Bohr magneton ratio shielded proton magnetic moment to బోరà±� మాగà±�నెటానà±� ratio shielded proton magnetic moment to nuclear magneton ratio shielded proton magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio neutron Compton wavelength à°¨à±�యూటà±�రానà±� కాంపà±�à°Ÿà°¨à±� తరంగదైరà±�à°˜à±�యం neutron-electron magnetic moment ratio à°¨à±�యూటà±�రానà±�-ఎలకà±�à°Ÿà±�రానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి neutron-electron mass ratio neutron-electron à°¦à±�à°°à°µà±�యరాశి ratio neutron g factor (gâ‚™) à°¨à±�యూటà±�రానà±� g కారకం (gâ‚™) neutron gyromagnetic ratio (γₙ) à°¨à±�యూటà±�రానà±� గైరోమాగà±�నెటికà±� నిషà±�పతà±�తి (γₙ) neutron gyromagnetic ratio in MHz/T neutron gyromagnetic ratio లో MHz/T neutron magnetic moment (μₙ) à°¨à±�యూటà±�రానà±� అయసà±�కాంత ఘూరà±�ణం (μₙ) neutron magnetic moment to Bohr magneton ratio neutron magnetic moment to బోరà±� మాగà±�నెటానà±� ratio neutron magnetic moment to nuclear magneton ratio neutron magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio neutron mass (mâ‚™) neutron à°¦à±�à°°à°µà±�యరాశి (mâ‚™) neutron mass energy equivalent neutron à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� neutron mass energy equivalent in MeV neutron à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో MeV neutron mass in u neutron à°¦à±�à°°à°µà±�యరాశి లో u neutron molar mass (Mâ‚™) neutron molar à°¦à±�à°°à°µà±�యరాశి (Mâ‚™) neutron-muon mass ratio neutron-muon à°¦à±�à°°à°µà±�యరాశి ratio neutron-proton magnetic moment ratio à°¨à±�యూటà±�రానà±�-à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి neutron-proton mass difference neutron-proton à°¦à±�à°°à°µà±�యరాశి difference neutron-proton mass difference energy equivalent neutron-proton à°¦à±�à°°à°µà±�యరాశి difference à°¶à°•à±�తి equivalent neutron-proton mass difference energy equivalent in MeV neutron-proton à°¦à±�à°°à°µà±�యరాశి difference à°¶à°•à±�తి equivalent లో MeV neutron-proton mass difference in u neutron-proton à°¦à±�à°°à°µà±�యరాశి difference లో u neutron-proton mass ratio neutron-proton à°¦à±�à°°à°µà±�యరాశి ratio neutron relative atomic mass (Ar(n)) neutron relative atomic à°¦à±�à°°à°µà±�యరాశి (Ar(n)) neutron-tau mass ratio neutron-tau à°¦à±�à°°à°µà±�యరాశి ratio neutron to shielded proton magnetic moment ratio à°¨à±�యూటà±�రానà±� à°¨à±�à°‚à°¡à°¿ షీలà±�à°¡à±� చేసిన à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి reduced neutron Compton wavelength తగà±�à°—à°¿à°‚à°šà°¿à°¨ neutron Compton wavelength deuteron-electron magnetic moment ratio à°¡à±�యూటెరానà±�-ఎలకà±�à°Ÿà±�రానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి deuteron-electron mass ratio deuteron-electron à°¦à±�à°°à°µà±�యరాశి ratio deuteron g factor à°¡à±�యూటెరానà±� g కారకం deuteron magnetic moment à°¡à±�యూటెరానà±� అయసà±�కాంత ఘూరà±�ణం deuteron magnetic moment to Bohr magneton ratio deuteron magnetic moment to బోరà±� మాగà±�నెటానà±� ratio deuteron magnetic moment to nuclear magneton ratio deuteron magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio deuteron mass deuteron à°¦à±�à°°à°µà±�యరాశి deuteron mass energy equivalent deuteron à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� deuteron mass energy equivalent in MeV deuteron à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో MeV deuteron mass in u deuteron à°¦à±�à°°à°µà±�యరాశి లో u deuteron molar mass deuteron molar à°¦à±�à°°à°µà±�యరాశి deuteron-neutron magnetic moment ratio à°¡à±�యూటెరానà±�-à°¨à±�యూటà±�రానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి deuteron-proton magnetic moment ratio à°¡à±�యూటెరానà±�-à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి deuteron-proton mass ratio deuteron-proton à°¦à±�à°°à°µà±�యరాశి ratio deuteron relative atomic mass (Ar(d)) deuteron relative atomic à°¦à±�à°°à°µà±�యరాశి (Ar(d)) deuteron rms charge radius deuteron rms charge à°µà±�యాసారà±�థం triton-electron mass ratio triton-electron à°¦à±�à°°à°µà±�యరాశి ratio triton g factor (gₜ) à°Ÿà±�రైటానà±� g కారకం (gₜ) triton magnetic moment (μₜ) à°Ÿà±�రైటానà±� అయసà±�కాంత ఘూరà±�ణం (μₜ) triton magnetic moment to Bohr magneton ratio triton magnetic moment to బోరà±� మాగà±�నెటానà±� ratio triton magnetic moment to nuclear magneton ratio triton magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio triton mass (mₜ) triton à°¦à±�à°°à°µà±�యరాశి (mₜ) triton mass energy equivalent triton à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� triton mass energy equivalent in MeV triton à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో MeV triton mass in u triton à°¦à±�à°°à°µà±�యరాశి లో u triton molar mass (Mₜ) triton molar à°¦à±�à°°à°µà±�యరాశి (Mₜ) triton-proton mass ratio triton-proton à°¦à±�à°°à°µà±�యరాశి ratio triton relative atomic mass (Ar(t)) triton relative atomic à°¦à±�à°°à°µà±�యరాశి (Ar(t)) triton to proton magnetic moment ratio à°Ÿà±�రైటానà±� à°¨à±�à°‚à°¡à°¿ à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి helion-electron mass ratio helion-electron à°¦à±�à°°à°µà±�యరాశి ratio helion g factor (gâ‚•) హీలియనà±� g కారకం (gâ‚•) helion magnetic moment (μₕ) హీలియనà±� అయసà±�కాంత ఘూరà±�ణం (μₕ) helion magnetic moment to Bohr magneton ratio helion magnetic moment to బోరà±� మాగà±�నెటానà±� ratio helion magnetic moment to nuclear magneton ratio helion magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio helion mass (mâ‚•) helion à°¦à±�à°°à°µà±�యరాశి (mâ‚•) helion mass energy equivalent helion à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� helion mass energy equivalent in MeV helion à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో MeV helion mass in u helion à°¦à±�à°°à°µà±�యరాశి లో u helion molar mass (Mâ‚•) helion molar à°¦à±�à°°à°µà±�యరాశి (Mâ‚•) helion-proton mass ratio helion-proton à°¦à±�à°°à°µà±�యరాశి ratio helion relative atomic mass (Ar(h)) helion relative atomic à°¦à±�à°°à°µà±�యరాశి (Ar(h)) helion shielding shift హీలియనà±� షీలà±�à°¡à°¿à°‚à°—à±� మారà±�à°ªà±� shielded helion gyromagnetic ratio షీలà±�à°¡à±� చేసిన హీలియనà±� గైరోమాగà±�నెటికà±� నిషà±�పతà±�తి shielded helion gyromagnetic ratio in MHz/T shielded helion gyromagnetic ratio లో MHz/T shielded helion magnetic moment షీలà±�à°¡à±� చేసిన హీలియనà±� అయసà±�కాంత ఘూరà±�ణం shielded helion magnetic moment to Bohr magneton ratio shielded helion magnetic moment to బోరà±� మాగà±�నెటానà±� ratio shielded helion magnetic moment to nuclear magneton ratio shielded helion magnetic moment to à°…à°£à±�కేందà±�à°° మాగà±�నెటానà±� ratio shielded helion to proton magnetic moment ratio షీలà±�à°¡à±� చేసిన హీలియనà±� à°¨à±�à°‚à°¡à°¿ à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి shielded helion to shielded proton magnetic moment ratio షీలà±�à°¡à±� చేసిన హీలియనà±� à°¨à±�à°‚à°¡à°¿ షీలà±�à°¡à±� చేసిన à°ªà±�రోటానà±� అయసà±�కాంత ఘూరà±�ణం నిషà±�పతà±�తి alpha particle mass alpha particle à°¦à±�à°°à°µà±�యరాశి alpha particle mass in u alpha particle à°¦à±�à°°à°µà±�యరాశి లో u alpha particle mass energy equivalent alpha particle à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� alpha particle mass energy equivalent in MeV alpha particle à°¦à±�à°°à°µà±�యరాశి à°¶à°•à±�తి సమానమà±� లో MeV alpha particle-electron mass ratio alpha particle-electron à°¦à±�à°°à°µà±�యరాశి ratio alpha particle-proton mass ratio alpha particle-proton à°¦à±�à°°à°µà±�యరాశి ratio alpha particle rms charge radius alpha particle rms charge à°µà±�యాసారà±�థం alpha particle molar mass alpha particle molar à°¦à±�à°°à°µà±�యరాశి alpha particle relative atomic mass (Ar(α)) alpha particle relative atomic à°¦à±�à°°à°µà±�యరాశి (Ar(α)) atomic mass constant (mᵤ) atomic à°¦à±�à°°à°µà±�యరాశి à°¸à±�థిరాంకం (mᵤ) Avogadro constant Avogadro à°¸à±�థిరాంకం Boltzmann constant (k) Boltzmann à°¸à±�థిరాంకం (k) Boltzmann constant in eV/K Boltzmann à°¸à±�థిరాంకం లో eV/K Boltzmann constant in Hz/K Boltzmann à°¸à±�థిరాంకం లో Hz/K Boltzmann constant in inverse meter per kelvin Boltzmann à°¸à±�థిరాంకం లో విలోమ మీటరà±� à°•à±� కెలà±�వినà±� electron volt (eV) ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±� (eV) Faraday constant (F) Faraday à°¸à±�థిరాంకం (F) first radiation constant (câ‚�) first radiation à°¸à±�థిరాంకం (câ‚�) first radiation constant for spectral radiance first radiation à°¸à±�థిరాంకం for spectral radiance molar gas constant (R) molar gas à°¸à±�థిరాంకం (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Loschmidt à°¸à±�థిరాంకం (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Loschmidt à°¸à±�థిరాంకం (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molar à°ªà±�లాంకà±� à°¸à±�థిరాంకం second radiation constant (câ‚‚) second radiation à°¸à±�థిరాంకం (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Boltzmann à°¸à±�థిరాంకం (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) lattice spacing యొకà±�à°• ideal Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atomic à°¦à±�à°°à°µà±�యరాశి à°¸à±�థిరాంకం à°¶à°•à±�తి equivalent atomic mass constant energy equivalent in MeV atomic à°¦à±�à°°à°µà±�యరాశి à°¸à±�థిరాంకం à°¶à°•à±�తి equivalent లో MeV atomic mass unit-electron volt relationship à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±�-ఎలకà±�à°Ÿà±�రానà±� వోలà±�à°Ÿà±� సంబంధం molar mass constant (Mᵤ) molar à°¦à±�à°°à°µà±�యరాశి à°¸à±�థిరాంకం (Mᵤ) molar mass of carbon-12 molar à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) molar volume యొకà±�à°• ideal gas (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) molar volume యొకà±�à°• ideal gas (273.15 K, 101.325 kPa) molar volume of silicon molar volume యొకà±�à°• silicon Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode à°¸à±�థిరాంకం (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode à°¸à±�థిరాంకం (1 K, 101.325 kPa) Wien frequency displacement law constant Wien ఆవరà±�తనం displacement law à°¸à±�థిరాంకం Wien wavelength displacement law constant Wien wavelength displacement law à°¸à±�థిరాంకం standard atmosphere (atm) à°ªà±�రామాణిక వాతావరణం (atm) standard-state pressure (p°) à°ªà±�రామాణిక-à°¸à±�థితి పీడనం (p°) Angstrom star (Ã…*) ఆంగà±�‌సà±�à°Ÿà±�రామà±� à°¸à±�టారà±� (Ã…*) Copper x unit కాపరà±� x యూనిటà±� Molybdenum x unit మోలిబà±�డినమà±� x యూనిటà±� atomic unit of magnetizability à°…à°£à±� యూనిటà±� యొకà±�à°• magnetizability atomic unit of mass (mâ‚‘) à°…à°£à±� యూనిటà±� యొకà±�à°• à°¦à±�à°°à°µà±�యరాశి (mâ‚‘) atomic unit of momentum à°…à°£à±� యూనిటà±� యొకà±�à°• momentum atomic unit of permittivity à°…à°£à±� యూనిటà±� యొకà±�à°• permittivity atomic unit of time à°…à°£à±� యూనిటà±� యొకà±�à°• సమయం atomic unit of velocity à°…à°£à±� యూనిటà±� యొకà±�à°• velocity hartree-hertz relationship hartree-హెరà±�à°Ÿà±�à°œà±� సంబంధం hartree-inverse meter relationship hartree-విలోమ మీటరà±� సంబంధం hartree-joule relationship hartree-జూలà±� సంబంధం hartree-kelvin relationship hartree-కెలà±�వినà±� సంబంధం hartree-kilogram relationship hartree-కిలోగà±�రామà±� సంబంధం shielding difference of d and p in HD shielding difference యొకà±�à°• d మరియà±� p లో HD shielding difference of t and p in HT shielding difference యొకà±�à°• t మరియà±� p లో HT pi (Ï€) పై (Ï€) Euler's number (e) యూలరà±� సంఖà±�à°¯ (e) golden ratio (φ) à°¸à±�వరà±�à°£ నిషà±�పతà±�తి (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni à°¸à±�థిరాంకం (γ) nominal solar radius nominal solar à°µà±�యాసారà±�థం nominal solar total irradiance నామమాతà±�à°° సౌర మొతà±�తం వికిరణం nominal solar luminosity నామమాతà±�à°° సౌర à°ªà±�రకాశం nominal solar effective temperature nominal solar effective ఉషà±�ణోగà±�à°°à°¤ nominal solar mass parameter nominal solar à°¦à±�à°°à°µà±�యరాశి parameter nominal terrestrial equatorial radius nominal terrestrial equatorial à°µà±�యాసారà±�థం nominal terrestrial polar radius nominal terrestrial polar à°µà±�యాసారà±�థం nominal terrestrial mass parameter nominal terrestrial à°¦à±�à°°à°µà±�యరాశి parameter nominal jovian equatorial radius nominal jovian equatorial à°µà±�యాసారà±�థం nominal jovian polar radius nominal jovian polar à°µà±�యాసారà±�థం nominal jovian mass parameter nominal jovian à°¦à±�à°°à°µà±�యరాశి parameter average value of one minus the rate of TCG relative to TCB average value యొకà±�à°• one minus the rate యొకà±�à°• TCG relative to TCB solar mass parameter (TCB-compatible) solar à°¦à±�à°°à°µà±�యరాశి parameter (TCB-compatible) solar mass parameter (TDB-compatible) solar à°¦à±�à°°à°µà±�యరాశి parameter (TDB-compatible) equatorial radius of the Earth (TT-compatible) equatorial à°µà±�యాసారà±�థం యొకà±�à°• the Earth (TT-compatible) dynamical form factor of the Earth dynamical form factor యొకà±�à°• the Earth time rate of change in the dynamical form factor of the Earth సమయం rate యొకà±�à°• change లో the dynamical form factor యొకà±�à°• the Earth geocentric gravitational constant (TCB-compatible) geocentric gravitational à°¸à±�థిరాంకం (TCB-compatible) geocentric gravitational constant (TT-compatible) geocentric gravitational à°¸à±�థిరాంకం (TT-compatible) geocentric gravitational constant (TDB-compatible) geocentric gravitational à°¸à±�థిరాంకం (TDB-compatible) potential of the geoid potential యొకà±�à°• the geoid nominal mean angular velocity of the Earth (TT-compatible) nominal mean angular velocity యొకà±�à°• the Earth (TT-compatible) ratio mass of the Moon to the Earth ratio à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Moon to the Earth ratio of the mass of the Sun to Mercury ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to Mercury ratio of the mass of the Sun to Venus ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to Venus ratio of the mass of the Sun to Mars ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to Mars ratio of the mass of the Sun to Jupiter ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to Jupiter ratio of the mass of the Sun to Saturn ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to Saturn ratio of the mass of the Sun to Uranus ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to Uranus ratio of the mass of the Sun to Neptune ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to Neptune ratio of the mass of the Sun to (134340) Pluto ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to (134340) Pluto ratio of the mass of the Sun to (136199) Eris ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• the Sun to (136199) Eris ratio of the mass of (1) Ceres to the Sun ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• (1) Ceres to the Sun ratio of the mass of (2) Pallas to the Sun ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• (2) Pallas to the Sun ratio of the mass of (4) Vesta to the Sun ratio యొకà±�à°• the à°¦à±�à°°à°µà±�యరాశి యొకà±�à°• (4) Vesta to the Sun mean obliquity of the ecliptic at J2000.0 mean obliquity యొకà±�à°• the ecliptic at J2000.0 Electromagnetic విదà±�à°¯à±�à°¤à±�‌చà±�ంబక Compton wavelength కాంపà±�à°Ÿà°¨à±� తరంగదైరà±�à°˜à±�యం Astronomy ఖగోళశాసà±�à°¤à±�à°°à°‚ ConstantsWidget Domain డొమైనà±� Subdomain ఉపడొమైనà±� No match found సరిపోలిక కనబడలేదà±� Name పేరà±� Value విలà±�à°µ Unit యూనిటà±� Search శోధించà±� All à°…à°¨à±�నీ CustomKeypadDialog Custom Keypad à°…à°¨à±�కూల కీపà±�యాడà±� Rows: వరà±�సలà±�: Columns: నిలà±�à°µà±� వరà±�సలà±�: Copy preset: à°ªà±�రీసెటà±�‌నà±� కాపీ చేయి: Basic à°ªà±�రాథమిక Scientific (wide) శాసà±�à°¤à±�రీయ (వెడలà±�à°ªà±�) Scientific (narrow) శాసà±�à°¤à±�రీయ (ఇరà±�à°•à±�) Apply వరà±�తింపజేయి Row వరà±�à°¸ Column నిలà±�à°µà±� వరà±�à°¸ Label లేబà±�à°²à±� Behavior à°ªà±�రవరà±�తన Text పాఠà±�యం DiagnosticsDialog App Diagnostics à°…à°¨à±�వరà±�తన విశà±�లేషణ Copy to Clipboard à°•à±�లిపà±�‌బోరà±�à°¡à±�à°•à±� కాపీ చేయి Editor Unit యూనిటà±� User unit వినియోగదారà±� యూనిటà±� User function వినియోగదారà±� à°«à°‚à°•à±�à°·à°¨à±� Argument ఆరà±�à°—à±�à°¯à±�మెంటà±� Current result:<br/>%1 à°ªà±�à°°à°¸à±�à°¤à±�à°¤ ఫలితం:<br/>%1 Selection result:<br/>%1 ఎంపిక ఫలితం:<br/>%1 Selection result: n/a ఎంపిక ఫలితం: వరà±�తించదà±� Selection result: %1 ఎంపిక ఫలితం: %1 second సెకనà±� metre మీటరà±� kilogram కిలోగà±�రామà±� mole మోలà±� radian రేడియనà±� steradian à°¸à±�టెరేడియనà±� degree Celsius à°¡à°¿à°—à±�à°°à±€ సెలà±�సియసà±� cubic metre ఘన మీటరà±� cubic millimetre ఘన మిలà±�లీమీటరà±� cubic centimetre ఘన సెంటీమీటరà±� cubic decimetre ఘన డెసీమీటరà±� cubic kilometre ఘన కిలోమీటరà±� square millimetre చదరపà±� మిలà±�లీమీటరà±� square kilometre చదరపà±� కిలోమీటరà±� square metre చదరపà±� మీటరà±� minute నిమిషం hour à°—à°‚à°Ÿ day రోజà±� astronomical unit ఖగోళ యూనిటà±� degree à°¡à°¿à°—à±�à°°à±€ arcminute ఆరà±�à°•à±�‌మినిటà±� arcsecond ఆరà±�à°•à±�‌సెకనà±� milliarcsecond మిలà±�లీఆరà±�à°•à±�‌సెకనà±� microarcsecond మైకà±�రోఆరà±�à°•à±�‌సెకనà±� hectare హెకà±�టారà±� litre లీటరà±� tonne à°Ÿà°¨à±�à°¨à±� Dalton డాలà±�à°Ÿà°¨à±� electronvolt ఎలకà±�à°Ÿà±�రానà±�‌వోలà±�à°Ÿà±� Angstrom ఆంగà±�‌సà±�à°Ÿà±�రామà±� atmosphere వాతావరణం atomic mass unit à°…à°£à±� à°¦à±�à°°à°µà±�యరాశి యూనిటà±� British thermal unit à°¬à±�à°°à°¿à°Ÿà°¿à°·à±� థరà±�మలà±� యూనిటà±� calorie à°•à±�యాలరీ carat à°•à±�యారెటà±� cup à°•à°ªà±�à°ªà±� cup (Imperial) à°•à°ªà±�à°ªà±� (ఇంపీరియలà±�) cup (Japanese) à°•à°ªà±�à°ªà±� (జపనీసà±�) cup (US) à°•à°ªà±�à°ªà±� (US) degree Fahrenheit à°¡à°¿à°—à±�à°°à±€ ఫారెనà±�‌హీటà±� fathom ఫాథమà±� fluid ounce (Imperial) à°¦à±�à°°à°µ ఔనà±�à°¸à±� (ఇంపీరియలà±�) fluid ounce (US) à°¦à±�à°°à°µ ఔనà±�à°¸à±� (US) fluid dram (Imperial) à°¦à±�à°°à°µ à°¡à±�రామà±� (ఇంపీరియలà±�) fluid dram (US) à°¦à±�à°°à°µ à°¡à±�రామà±� (US) foot à°…à°¡à±�à°—à±� square foot చదరపà±� à°…à°¡à±�à°—à±� cubic foot ఘన à°…à°¡à±�à°—à±� gallon (Imperial) గాలనà±� (ఇంపీరియలà±�) gallon (US) గాలనà±� (US) gill (Imperial) à°—à°¿à°²à±� (ఇంపీరియలà±�) gill (US) à°—à°¿à°²à±� (US) gradian à°—à±�రేడియనà±� grain à°—à±�రెయినà±� gram à°—à±�రామà±� Hartley హారà±�à°Ÿà±�‌లీ Hartree energy unit హారà±�à°Ÿà±�à±�à°°à±€ à°¶à°•à±�తి యూనిటà±� horsepower హారà±�à°¸à±�‌పవరà±� inch à°…à°‚à°—à±�ళం square inch చదరపà±� à°…à°‚à°—à±�ళం cubic inch ఘన à°…à°‚à°—à±�ళం karat à°•à±�యారటà±� knot నాటà±� lightminute కాంతి నిమిషం lightsecond కాంతి సెకనà±� lightyear కాంతి సంవతà±�సరం long ton లాంగà±� à°Ÿà°¨à±� mile మైలà±� square mile చదరపà±� మైలà±� cubic mile ఘన మైలà±� mile per hour à°—à°‚à°Ÿà°•à±� మైలà±� kilometre per hour à°—à°‚à°Ÿà°•à±� కిలోమీటరà±� nautical mile నాటికలà±� మైలà±� ounce ఔనà±�à°¸à±� parsec పారà±�సెకà±� pint (Imperial) పైంటà±� (ఇంపీరియలà±�) pint (US) పైంటà±� (US) pound పౌండà±� pounds per square inch చదరపà±� à°…à°‚à°—à±�ళానికి పౌండà±�à°²à±� quart (Imperial) à°•à±�వారà±�à°Ÿà±� (ఇంపీరియలà±�) quart (US) à°•à±�వారà±�à°Ÿà±� (US) oil barrel à°šà°®à±�à°°à±� à°¬à±�యారెలà±� beer barrel (US) బీరà±� à°¬à±�యారెలà±� (US) square yard చదరపà±� యారà±�à°¡à±� cubic yard ఘన యారà±�à°¡à±� short ton షారà±�à°Ÿà±� à°Ÿà°¨à±� tablespoon టేబà±�à°²à±� à°¸à±�పూనà±� tablespoon (Australian) టేబà±�à°²à±� à°¸à±�పూనà±� (ఆసà±�à°Ÿà±�రేలియనà±�) tablespoon (Imperial) టేబà±�à°²à±� à°¸à±�పూనà±� (ఇంపీరియలà±�) tablespoon (US) టేబà±�à°²à±� à°¸à±�పూనà±� (US) dessert spoon డెజరà±�à°Ÿà±� à°¸à±�పూనà±� teaspoon à°Ÿà±€ à°¸à±�పూనà±� teaspoon (Imperial) à°Ÿà±€ à°¸à±�పూనà±� (ఇంపీరియలà±�) teaspoon (US) à°Ÿà±€ à°¸à±�పూనà±� (US) turn à°Ÿà°°à±�à°¨à±� revolution పరిభà±�రమణం revolution per minute నిమిషానికి పరిభà±�రమణాలà±� week వారం kilowatt hour కిలోవాటà±� à°—à°‚à°Ÿ millimetre of mercury పాదరసం మిలà±�లీమీటరà±� yard యారà±�à°¡à±� Julian century జూలియనà±� శతాబà±�దం Julian year జూలియనà±� సంవతà±�సరం sidereal year నాకà±�à°·à°¤à±�à°°à°¿à°• సంవతà±�సరం tropical year à°Ÿà±�రాపికలà±� సంవతà±�సరం Evaluator invalid expression చెలà±�లని à°µà±�యకà±�తీకరణ division by zero à°¸à±�à°¨à±�నాతో భాగహారం too time consuming - computation was rejected చాలా సమయం తీసà±�à°•à±�à°‚à°Ÿà±�ంది - గణన తిరసà±�కరించబడింది dimension mismatch - quantities with different dimensions cannot be compared, added, etc. పరిమాణం సరిపోలలేదà±� - వేరà±�వేరà±� పరిమాణాల పరిమాణాలనà±� పోలà±�à°šà°¡à°‚, జోడించడం మొదలైనవి చేయలేరà±� invalid dimension - operation might require dimensionless arguments చెలà±�లని పరిమాణం - ఆపరేషనà±�‌కà±� పరిమాణరహిత ఆరà±�à°—à±�à°¯à±�మెంటà±�à°²à±� అవసరం కావచà±�à°šà±� Computation aborted - encountered numerical instability గణన నిలిపివేయబడింది - సంఖà±�యాతà±�మక à°…à°¸à±�థిరత à°Žà°¦à±�రైంది invalid dimension - function might require dimensionless arguments చెలà±�లని పరిమాణం - à°«à°‚à°•à±�à°·à°¨à±�‌కà±� పరిమాణరహిత ఆరà±�à°—à±�à°¯à±�మెంటà±�à°²à±� అవసరం కావచà±�à°šà±� error లోపం unit must not be zero యూనిటà±� à°¸à±�à°¨à±�నా కాకూడదà±� Conversion failed - dimension mismatch మారà±�పిడి విఫలమైంది - పరిమాణం సరిపోలలేదà±� unknown function or variable తెలియని à°«à°‚à°•à±�à°·à°¨à±� లేదా చరరాశి recursion not supported à°°à°¿à°•à°°à±�à°·à°¨à±�‌కà±� మదà±�దతà±� లేదà±� cannot operate on a NaN NaN పై ఆపరేషనà±� చేయలేరà±� underflow - tiny result is out of SpeedCrunch's number range à°…à°‚à°¡à°°à±�‌ఫà±�లో - à°šà°¿à°¨à±�à°¨ ఫలితం SpeedCrunch సంఖà±�à°¯ పరిధికి బయట ఉంది overflow - huge result is out of SpeedCrunch's number range ఓవరà±�‌ఫà±�లో - పెదà±�à°¦ ఫలితం SpeedCrunch సంఖà±�à°¯ పరిధికి బయట ఉంది overflow - logic result exceeds maximum of 256 bits ఓవరà±�‌ఫà±�లో - లాజికà±� ఫలితం 256 బిటà±�à°² à°—à°°à°¿à°·à±�ఠానà±�ని మించింది overflow - integer result exceeds maximum limit for integers ఓవరà±�‌ఫà±�లో - పూరà±�ణసంఖà±�à°¯ ఫలితం పూరà±�ణసంఖà±�యల à°—à°°à°¿à°·à±�à°  పరిమితిని మించింది operation is not defined for these arguments à°ˆ ఆరà±�à°—à±�à°¯à±�మెంటà±�లకà±� ఆపరేషనà±� నిరà±�వచించబడలేదà±� wrong number of arguments ఆరà±�à°—à±�à°¯à±�మెంటà±�à°² సంఖà±�à°¯ తపà±�à°ªà±� does not take NaN as an argument NaN à°¨à±� ఆరà±�à°—à±�à°¯à±�మెంటà±�‌గా తీసà±�కోదà±� result out of range ఫలితం పరిధికి బయట ఉంది undefined for argument domain ఆరà±�à°—à±�à°¯à±�మెంటà±� డొమైనà±�‌కà±� నిరà±�వచించబడలేదà±� computation too expensive గణన చాలా ఖరీదైనది internal error, please report a bug అంతరà±�à°—à°¤ లోపం, దయచేసి బగà±�‌నà±� నివేదించండి syntax error వాకà±�యనిరà±�మాణ లోపం conversion target must be a unit మారà±�పిడి లకà±�à°·à±�యం యూనిటà±� అయి ఉండాలి unknown unit తెలియని యూనిటà±� %1 is a reserved name, please choose another %1 రిజరà±�à°µà±� చేయబడిన పేరà±�, దయచేసి మరొకటి à°Žà°‚à°šà±�కోండి %1 is a global user definition and cannot be overridden in this session. %1 à°—à±�లోబలà±� వినియోగదారà±� నిరà±�వచనం; à°ˆ సెషనà±�‌లో దానిని అధిగమించలేరà±�. %1 is a variable name, please choose another or delete the variable %1 చరరాశి పేరà±�, దయచేసి మరొకటి à°Žà°‚à°šà±�కోండి లేదా చరరాశిని తొలగించండి argument %1 is used more than once ఆరà±�à°—à±�à°¯à±�మెంటà±� %1 à°’à°•à°Ÿà°¿ కంటే à°Žà°•à±�à°•à±�వసారà±�à°²à±� ఉపయోగించబడింది %1 is a built-in unit name, please choose another %1 అంతరà±�నిరà±�మిత యూనిటà±� పేరà±�, దయచేసి మరొకటి à°Žà°‚à°šà±�కోండి %1 is a user function name, please choose another or delete the function %1 వినియోగదారà±� à°«à°‚à°•à±�à°·à°¨à±� పేరà±�, దయచేసి మరొకటి à°Žà°‚à°šà±�కోండి లేదా à°«à°‚à°•à±�à°·à°¨à±�‌నà±� తొలగించండి FunctionRepo max; trials; probability à°—à°°à°¿à°·à±�à° à°‚; à°ªà±�రయతà±�నాలà±�; సంభావà±�యత trials; probability à°ªà±�రయతà±�నాలà±�; సంభావà±�యత hits; trials; probability హిటà±�à°²à±�; à°ªà±�రయతà±�నాలà±�; సంభావà±�యత max; total; hits; trials à°—à°°à°¿à°·à±�à° à°‚; మొతà±�తం; హిటà±�à°²à±�; à°ªà±�రయతà±�నాలà±� total; hits; trials మొతà±�తం; హిటà±�à°²à±�; à°ªà±�రయతà±�నాలà±� count; total; hits; trials లెకà±�à°•; మొతà±�తం; హిటà±�à°²à±�; à°ªà±�రయతà±�నాలà±� dividend; divisor భాజà±�యం; భాజకం x; exponent_bits; significand_bits [; exponent_bias] x; ఘాతం_బిటà±�à°²à±�; సిగà±�నిఫికాండà±�_బిటà±�à°²à±� [; ఘాతం_బయాసà±�] base; x ఆధారం; x value; modulo విలà±�à°µ; మాడà±�à°¯à±�లో base; exponent; modulo ఆధారం; ఘాతం; మాడà±�à°¯à±�లో events; average_events ఘటనలà±�; సగటà±�_ఘటనలà±� average_events సగటà±�_ఘటనలà±� x [; precision] x [; à°–à°šà±�చితతà±�వం] Absolute Value నిరపేకà±�à°· విలà±�à°µ Absolute Deviation నిరపేకà±�à°· విచలనం Arc Cosine ఆరà±�à°•à±� కోసైనà±� Logical AND లాజికలà±� AND Area Hyperbolic Cosine ఇనà±�వరà±�à°¸à±� హైపరà±�‌బాలికà±� కోసైనà±� Area Hyperbolic Sine ఇనà±�వరà±�à°¸à±� హైపరà±�‌బాలికà±� సైనà±� Area Hyperbolic Tangent ఇనà±�వరà±�à°¸à±� హైపరà±�‌బాలికà±� à°Ÿà±�యాంజెంటà±� Arc Sine ఆరà±�à°•à±� సైనà±� Arc Tangent ఆరà±�à°•à±� à°Ÿà±�యాంజెంటà±� Arc Tangent with two Arguments రెండà±� ఆరà±�à°—à±�à°¯à±�మెంటà±�లతో ఆరà±�à°•à±� à°Ÿà±�యాంజెంటà±� Average (Arithmetic Mean) సగటà±� (అంకగణిత సగటà±�) Binomial Cumulative Distribution Function బైనోమియలà±� సమాకలిత పంపిణి à°«à°‚à°•à±�à°·à°¨à±� Binomial Distribution Mean బైనోమియలà±� పంపిణి సగటà±� Binomial Probability Mass Function బైనోమియలà±� సంభావà±�యత à°¦à±�à°°à°µà±�యరాశి à°«à°‚à°•à±�à°·à°¨à±� Binomial Distribution Variance బైనోమియలà±� పంపిణి à°µà±�యతà±�యాసం Cube Root ఘన మూలం Complex Conjugate సంకà±�లిషà±�à°Ÿ సంయà±�à°—à±�మం Cosine కోసైనà±� Hyperbolic Cosine హైపరà±�‌బాలికà±� కోసైనà±� Cotangent కోటà±�యాంజెంటà±� Cosecant కోసెకెంటà±� Convert Unix timestamp to Date Unix టైమà±�‌సà±�టాంపà±�‌నà±� తేదీకి మారà±�à°šà±� Degrees of Arc చాప à°¡à°¿à°—à±�రీలà±� Error Function లోప à°«à°‚à°•à±�à°·à°¨à±� Complementary Error Function పూరక లోప à°«à°‚à°•à±�à°·à°¨à±� Exponential ఘాతాంక Fractional Part à°­à°¿à°¨à±�à°¨ భాగం Extension of Factorials [= (x-1)!] à°«à±�యాకà±�టోరియలà±�à°¸à±� విసà±�తరణ [= (x-1)!] Greatest Common Divisor à°—à°°à°¿à°·à±�à°  సామానà±�à°¯ భాజకం Geometric Mean à°œà±�యామితీయ సగటà±� Gradians of arc చాప à°—à±�రేడియనà±�à°²à±� Hypergeometric Cumulative Distribution Function హైపరà±�‌జà±�యామితీయ సమాకలిత పంపిణి à°«à°‚à°•à±�à°·à°¨à±� Hypergeometric Distribution Mean హైపరà±�‌జà±�యామితీయ పంపిణి సగటà±� Hypergeometric Probability Mass Function హైపరà±�‌జà±�యామితీయ సంభావà±�యత à°¦à±�à°°à°µà±�యరాశి à°«à°‚à°•à±�à°·à°¨à±� Hypergeometric Distribution Variance హైపరà±�‌జà±�యామితీయ పంపిణి à°µà±�యతà±�యాసం Integer Quotient పూరà±�ణసంఖà±�à°¯ భాగఫలం Integer Part పూరà±�ణసంఖà±�à°¯ భాగం Imaginary Part à°•à°²à±�పిత భాగం Decode IEEE-754 Binary Value IEEE-754 à°¦à±�విమాన విలà±�వనà±� డీకోడà±� చేయి Encode IEEE-754 Binary Value IEEE-754 à°¦à±�విమాన విలà±�వనà±� à°Žà°¨à±�‌కోడà±� చేయి Decode 16-bit Half-Precision Value 16-బిటà±� à°…à°°à±�à°§-à°–à°šà±�చితతà±�à°µ విలà±�వనà±� డీకోడà±� చేయి Encode 16-bit Half-Precision Value 16-బిటà±� à°…à°°à±�à°§-à°–à°šà±�చితతà±�à°µ విలà±�వనà±� à°Žà°¨à±�‌కోడà±� చేయి Decode 32-bit Single-Precision Value 32-బిటà±� సింగిలà±�-à°–à°šà±�చితతà±�à°µ విలà±�వనà±� డీకోడà±� చేయి Encode 32-bit Single-Precision Value 32-బిటà±� సింగిలà±�-à°–à°šà±�చితతà±�à°µ విలà±�వనà±� à°Žà°¨à±�‌కోడà±� చేయి Decode 64-bit Double-Precision Value 64-బిటà±� à°¡à°¬à±�à°²à±�-à°–à°šà±�చితతà±�à°µ విలà±�వనà±� డీకోడà±� చేయి Encode 64-bit Double-Precision Value 64-బిటà±� à°¡à°¬à±�à°²à±�-à°–à°šà±�చితతà±�à°µ విలà±�వనà±� à°Žà°¨à±�‌కోడà±� చేయి Decode 128-bit Quad-Precision Value 128-బిటà±� à°•à±�వాడà±�-à°–à°šà±�చితతà±�à°µ విలà±�వనà±� డీకోడà±� చేయి Encode 128-bit Quad-Precision Value 128-బిటà±� à°•à±�వాడà±�-à°–à°šà±�చితతà±�à°µ విలà±�వనà±� à°Žà°¨à±�‌కోడà±� చేయి Binary Logarithm à°¦à±�విమాన లాగారిథం Common Logarithm సాధారణ లాగారిథం Natural Logarithm సహజ లాగారిథం Logarithm to Arbitrary Base à°� ఆధారానికైనా లాగారిథం Mask to a bit size బిటà±� పరిమాణానికి మాసà±�à°•à±� చేయి Maximum à°—à°°à°¿à°·à±�à° à°‚ Median Value (50th Percentile) మధà±�యక విలà±�à°µ (50à°µ శతకం) Minimum కనిషà±�à° à°‚ Modulo మాడà±�à°¯à±�లో Euclidean Modulo యూకà±�లిడియనà±� మాడà±�à°¯à±�లో Modular Exponentiation మాడà±�à°¯à±�లరà±� ఘాతాంకీకరణ Combination (Binomial Coefficient) సంయోజనం (బైనోమియలà±� à°—à±�ణకం) Logical NOT లాజికలà±� NOT Permutation (Arrangement) à°ªà±�à°°à°¸à±�తారం (అమరిక) Convert to Binary Representation à°¦à±�విమాన రూపానికి మారà±�à°šà±� Arithmetic అంకగణితం Chemistry రసాయనశాసà±�à°¤à±�à°°à°‚ Complex సంకà±�లిషà±�à°Ÿ Combinatorics సంయోజన శాసà±�à°¤à±�à°°à°‚ Probability సంభావà±�యత Statistics గణాంకాలà±� Aggregation సమీకరణ Random యాదృచà±�ఛిక Base conversion ఆధార మారà±�పిడి Number formatting సంఖà±�à°¯ ఆకృతీకరణ Integer arithmetic పూరà±�ణసంఖà±�à°¯ గణితం Special functions à°ªà±�à°°à°¤à±�యేక à°«à°‚à°•à±�à°·à°¨à±�à°²à±� Exponential & Logarithmic ఘాతాంక & లాగారిథమికà±� Angle conversion కోణ మారà±�పిడి Trigonometry à°¤à±�రికోణమితి Bitwise బిటà±�‌వారీ Floating point à°«à±�లోటింగà±� పాయింటà±� Date & Time తేదీ & సమయం Linear algebra రేఖీయ బీజగణితం unix_timestamp; x hours offset to GMT unix_timestamp; GMTà°•à±� x à°—à°‚à°Ÿà°² à°µà±�యతà±�యాసం yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; GMTà°•à±� x à°—à°‚à°Ÿà°² à°µà±�యతà±�యాసం [digits] [అంకెలà±�] max [; min] à°—à°°à°¿à°·à±�à° à°‚ [; కనిషà±�à° à°‚] List Literal జాబితా లిటరలà±� Convert to Padded Binary Representation Convert to Padded à°¦à±�విమాన Representation Round Toward +∞ (Ceiling) +∞ వైపà±� రౌండà±� చేయి (Ceiling) Cosine plus Imaginary Sine కోసైనà±� మరియà±� à°•à°²à±�పిత సైనà±� Convert to Cis Complex Form Cis సంకà±�లిషà±�à°Ÿ రూపానికి మారà±�à°šà±� Matrix Column Count à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� నిలà±�à°µà±� వరà±�సల సంఖà±�à°¯ Population Correlation Matrix (n) జనాభా సహసంబంధ à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� (n) Sample Correlation Matrix (n-1) నమూనా సహసంబంధ à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� (n-1) Count లెకà±�à°• Population Covariance Matrix (n) జనాభా సహపà±�రసరణ à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� (n) Sample Covariance Matrix (n-1) నమూనా సహపà±�రసరణ à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� (n-1) Cross Product à°•à±�రాసà±� à°ªà±�రోడకà±�à°Ÿà±� Convert Date to Unix timestamp తేదీని Unix టైమà±�‌సà±�టాంపà±�‌కà±� మారà±�à°šà±� Convert to Decimal Representation దశాంశ రూపానికి మారà±�à°šà±� Determinant నిరà±�ణాయకం Convert to Sexagesimal Notation à°·à°·à±�à°Ÿà±�యంశ సంకేతనానికి మారà±�à°šà±� Dot Product డాటà±� à°ªà±�రోడకà±�à°Ÿà±� Convert to Engineering Notation ఇంజినీరింగà±� సంకేతనానికి మారà±�à°šà±� Convert to Exponential Complex Form ఘాతాంక సంకà±�లిషà±�à°Ÿ రూపానికి మారà±�à°šà±� Round Toward −∞ (Floor) −∞ వైపà±� రౌండà±� చేయి (Floor) Flatten Matrix à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±�‌నà±� సమతలీకరించà±� Least Common Multiple కనిషà±�à°  సామానà±�à°¯ à°—à±�ణితం Convert to Hexadecimal Representation షోడశమాన రూపానికి మారà±�à°šà±� Convert to Padded Hexadecimal Representation పూరించిన షోడశమాన రూపానికి మారà±�à°šà±� Inverse Matrix విలోమ à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� Round to 16-bit Half-Precision Value 16-బిటà±� à°…à°°à±�à°§-à°–à°šà±�చితతà±�à°µ విలà±�వకà±� రౌండà±� చేయి Round to 32-bit Single-Precision Value 32-బిటà±� సింగిలà±�-à°–à°šà±�చితతà±�à°µ విలà±�వకà±� రౌండà±� చేయి Round to 64-bit Double-Precision Value 64-బిటà±� à°¡à°¬à±�à°²à±�-à°–à°šà±�చితతà±�à°µ విలà±�వకà±� రౌండà±� చేయి Round to 128-bit Quad-Precision Value 128-బిటà±� à°•à±�వాడà±�-à°–à°šà±�చితతà±�à°µ విలà±�వకà±� రౌండà±� చేయి Residual from 16-bit Half-Precision Rounding 16-బిటà±� à°…à°°à±�à°§-à°–à°šà±�చితతà±�à°µ రౌండింగà±�‌లో మిగà±�à°²à±� Residual from 32-bit Single-Precision Rounding 32-బిటà±� సింగిలà±�-à°–à°šà±�చితతà±�à°µ రౌండింగà±�‌లో మిగà±�à°²à±� Residual from 64-bit Double-Precision Rounding 64-బిటà±� à°¡à°¬à±�à°²à±�-à°–à°šà±�చితతà±�à°µ రౌండింగà±�‌లో మిగà±�à°²à±� Residual from 128-bit Quad-Precision Rounding 128-బిటà±� à°•à±�వాడà±�-à°–à°šà±�చితతà±�à°µ రౌండింగà±�‌లో మిగà±�à°²à±� Substance Mass పదారà±�à°¥ à°¦à±�à°°à°µà±�యరాశి Molarity మోలారిటీ Molar Mass మోలారà±� à°¦à±�à°°à°µà±�యరాశి Median Absolute Deviation మధà±�యక నిరపేకà±�à°· విచలనం Mean సగటà±� Numerical Value of Quantity పరిమాణం యొకà±�à°• సంఖà±�యాతà±�మక విలà±�à°µ Random Decimal Number యాదృచà±�ఛిక దశాంశ సంఖà±�à°¯ Random Integer Number యాదృచà±�ఛిక పూరà±�ణసంఖà±�à°¯ Convert to Rational Representation రేషనలà±� రూపానికి మారà±�à°šà±� Convert to Octal Representation à°…à°·à±�టమాన రూపానికి మారà±�à°šà±� Convert to Padded Octal Representation పూరించిన à°…à°·à±�టమాన రూపానికి మారà±�à°šà±� Vector or Matrix Norm వెకà±�à°Ÿà°°à±� లేదా à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� నారà±�à°®à±� Logical OR లాజికలà±� OR Population Count (Hamming Weight) పాపà±�à°¯à±�లేషనà±� కౌంటà±� (హామింగà±� వెయిటà±�) Phase of Complex Number సంకà±�లిషà±�à°Ÿ సంఖà±�à°¯ దశ Poissonian Cumulative Distribution Function పోయà±�సానà±� సమాకలిత పంపిణి à°«à°‚à°•à±�à°·à°¨à±� Poissonian Distribution Mean పోయà±�సానà±� పంపిణి సగటà±� Poissonian Probability Mass Function పోయà±�సానà±� సంభావà±�యత à°¦à±�à°°à°µà±�యరాశి à°«à°‚à°•à±�à°·à°¨à±� Poissonian Distribution Variance పోయà±�సానà±� పంపిణి à°µà±�యతà±�యాసం Convert to Phasor Complex Form ఫేజరà±� సంకà±�లిషà±�à°Ÿ రూపానికి మారà±�à°šà±� Convert to Rectangular Complex Form ఆయతాకార సంకà±�లిషà±�à°Ÿ రూపానికి మారà±�à°šà±� Round Half Away from Zero à°¸à±�à°¨à±�నా à°¨à±�à°‚à°¡à°¿ దూరంగా సగం రౌండà±� చేయి Round Half Even సగం సమసంఖà±�యకà±� రౌండà±� చేయి Nth Root nà°µ మూలం Convert to Scientific Notation శాసà±�à°¤à±�రీయ సంకేతనానికి మారà±�à°šà±� Matrix Row Count à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� వరà±�సల సంఖà±�à°¯ List or Matrix Shape జాబితా లేదా à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� ఆకారం Summation మొతà±�తం గణన Population Standard Deviation (n) జనాభా à°ªà±�రమాణ విచలనం (n) Sample Standard Deviation (n-1) నమూనా à°ªà±�రమాణ విచలనం (n-1) Round Toward Zero (Truncation) à°¸à±�à°¨à±�నా వైపà±� రౌండà±� చేయి (Truncation) Matrix Trace à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� à°Ÿà±�రేసà±� Transpose Matrix à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±�‌నà±� à°Ÿà±�రానà±�à°¸à±�‌పోజà±� చేయి Population Variance (n) జనాభా à°µà±�యతà±�యాసం (n) Sample Variance (n-1) నమూనా à°µà±�యతà±�యాసం (n-1) Product లబà±�à°§à°‚ Radians రేడియనà±�à°²à±� Matrix Rank à°®à±�యాటà±�à°°à°¿à°•à±�à°¸à±� à°°à±�యాంకà±� Real Part వాసà±�తవ భాగం Secant సెకెంటà±� Arithmetic Shift Left అంకగణిత à°Žà°¡à°® à°·à°¿à°«à±�à°Ÿà±� Arithmetic Shift Right అంకగణిత à°•à±�à°¡à°¿ à°·à°¿à°«à±�à°Ÿà±� Signum సిగà±�నమà±� Sine సైనà±� Hyperbolic Sine హైపరà±�‌బాలికà±� సైనà±� Square Root వరà±�గమూలం Sum మొతà±�తం Tangent à°Ÿà±�యాంజెంటà±� Convert to Trigonometric Complex Form à°¤à±�రికోణమితీయ సంకà±�లిషà±�à°Ÿ రూపానికి మారà±�à°šà±� Turns à°Ÿà°°à±�à°¨à±�à°²à±� Hyperbolic Tangent హైపరà±�‌బాలికà±� à°Ÿà±�యాంజెంటà±� Sign-extend a value విలà±�వనà±� సైనà±�-à°Žà°•à±�à°¸à±�‌టెండà±� చేయి Logical XOR లాజికలà±� XOR FunctionsWidget Domain డొమైనà±� All à°…à°¨à±�నీ Name పేరà±� Search శోధించà±� No match found సరిపోలిక కనబడలేదà±� Identifier à°—à±�à°°à±�తింపà±� పేరà±� HistoryWidget Remove All Calculations Above పై ఉనà±�à°¨ à°…à°¨à±�ని గణనలనà±� తొలగించà±� Remove This Calculation à°ˆ గణననà±� తొలగించà±� Remove All Calculations Below à°•à±�à°°à°¿à°‚à°¦ ఉనà±�à°¨ à°…à°¨à±�ని గణనలనà±� తొలగించà±� Keypad Inverse cosine విలోమ కోసైనà±� The last result చివరి ఫలితం Inverse sine విలోమ సైనà±� Inverse tangent విలోమ à°Ÿà±�యాంజెంటà±� Evaluate expression à°µà±�యకà±�తీకరణనà±� లెకà±�à°•à°¿à°‚à°šà±� Division భాగహారం Multiplication à°—à±�ణకారం Subtraction à°µà±�యవకలనం Addition సంకలనం Clear expression à°µà±�యకà±�తీకరణనà±� à°•à±�లియరà±� చేయి Cosine కోసైనà±� Backspace à°¬à±�యాకà±�‌సà±�పేసà±� Scientific notation శాసà±�à°¤à±�రీయ సంకేతనం Exponential ఘాతాంక Factorial à°«à±�యాకà±�టోరియలà±� Natural logarithm సహజ లాగారిథం Left parenthesis à°Žà°¡à°® à°•à±�ండలి Nth root nà°µ మూలం Argument separator ఆరà±�à°—à±�à°¯à±�మెంటà±� విభాజకం Square వరà±�à°—à°‚ Common logarithm సాధారణ లాగారిథం Modulo మాడà±�à°¯à±�లో Contextual percentage సందరà±�భానà±�సార శాతం Power విదà±�à°¯à±�à°¤à±� à°¶à°•à±�తి Right parenthesis à°•à±�à°¡à°¿ à°•à±�ండలి Sine సైనà±� Square root వరà±�గమూలం Tangent à°Ÿà±�యాంజెంటà±� Pi పై Decimal separator దశాంశ విభజకమà±� MainWindow Radian రేడియనà±� Degree à°¡à°¿à°—à±�à°°à±€ Gradian à°—à±�రేడియనà±� Binary à°¦à±�విమానం Octal à°…à°·à±�టమానం Hexadecimal షోడశమానం Sexagesimal à°·à°·à±�à°Ÿà±�యంశం Engineering decimal ఇంజినీరింగà±� దశాంశం Scientific decimal శాసà±�à°¤à±�రీయ దశాంశం &Import... &దిగà±�మతి... &Quit &నిషà±�à°•à±�రమించà±� Clear E&xpression à°µà±�యకà±�తీకరణనà±� &à°•à±�లియరà±� చేయి Clear &History à°šà°°à°¿à°¤à±�à°°à°¨à±� &à°•à±�లియరà±� చేయి &Copy &కాపీ చేయి &Paste &అతికించà±� &Select Expression à°µà±�యకà±�తీకరణనà±� &à°Žà°‚à°šà±�కో &Constants &à°¸à±�థిరాంకాలà±� &Functions &à°«à°‚à°•à±�à°·à°¨à±�à°²à±� &History &à°šà°°à°¿à°¤à±�à°° &Status Bar &à°¸à±�థితి పటà±�à°Ÿà±€ Bitfield బిటà±�‌ఫీలà±�à°¡à±� Use&r Functions వినియోగదారà±� &à°«à°‚à°•à±�à°·à°¨à±�à°²à±� &Degree &à°¡à°¿à°—à±�à°°à±€ &Radian &రేడియనà±� &Gradian &à°—à±�రేడియనà±� Re&volution &పరిభà±�రమణం Auto-Insert a&ns a&nsà°¨à±� à°¸à±�వయంచాలకంగా చేరà±�à°šà±� Automatic &Completion à°¸à±�వయంచాలక &పూరà±�తి &Built-in Functions &అంతరà±�నిరà±�మిత à°«à°‚à°•à±�à°·à°¨à±�à°²à±� Built-in &Variables à°…à°‚&తరà±�నిరà±�మిత చరరాశà±�à°²à±� User &Functions &వినియోగదారà±� à°«à°‚à°•à±�à°·à°¨à±�à°²à±� User Va&riables వి&నియోగదారà±� చరరాశà±�à°²à±� Open a Private Tab on Startup à°ªà±�రారంభంలో à°ªà±�రైవేటà±� à°Ÿà±�యాబà±� తెరà±�à°µà±� Open and focus a new private tab whenever SpeedCrunch starts. SpeedCrunch à°ªà±�రారంభమైన à°ªà±�రతిసారీ కొతà±�à°¤ à°ªà±�రైవేటà±� à°Ÿà±�యాబà±� తెరిచి దానిపై దృషà±�à°Ÿà°¿ పెటà±�à°Ÿà±�. Syntax &Highlighting వాకà±�యనిరà±�మాణ &హైలైటింగà±� Group Digits in &Input &ఇనà±�‌పà±�à°Ÿà±� అంకెలనà±� సమూహపరచà±� Automatic Input &Adjustments à°¸à±�&వయంచాలక ఇనà±�‌పà±�à°Ÿà±� సరà±�à°¦à±�బాటà±�à°²à±� Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. ఆపరేటరà±�à°²à±�, ఖాళీలà±�, à°¬à±�రాకెటà±�à°²à±�, ఘాతాలనà±� à°¸à±�వయంచాలకంగా సరà±�à°¦à±�బాటà±� చేసి, చెలà±�à°²à±�బాటà±� à°…à°¯à±�యే à°…à°•à±�షరాలనà±� మాతà±�రమే à°…à°¨à±�మతించà±�. Group input digits using the selected number format. à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ సంఖà±�యా ఆకృతి à°ªà±�రకారం ఇనà±�‌పà±�à°Ÿà±� అంకెలనà±� సమూహపరచà±�. &Blinking Cursor &మెరిసే à°•à°°à±�సరà±� Blink the cursor in the expression editor. సమాస à°Žà°¡à°¿à°Ÿà°°à±�‌లో à°•à°°à±�సరà±�‌నà±� మెరిపించà±�. &Escape Clears Editor &Escape à°Žà°¡à°¿à°Ÿà°°à±�‌నà±� ఖాళీ చేసà±�à°¤à±�ంది Clear the focused expression editor with Escape after dismissing any popup or preview. పాపపà±� లేదా à°®à±�ందసà±�à°¤à±� వీకà±�షణలనà±� మూసిన తరà±�వాత, దృషà±�టిలో ఉనà±�à°¨ సమాస à°Žà°¡à°¿à°Ÿà°°à±�‌నà±� Escapeతో ఖాళీ చేయి. Keep Expression After Evaluation గణన తరà±�వాత సమాసానà±�ని ఉంచà±� Copy New Results Automatically కొతà±�à°¤ ఫలితాలనà±� à°¸à±�వయంచాలకంగా కాపీ చేయి &Comma &కామా &System Default &సిసà±�à°Ÿà°®à±� డిఫాలà±�à°Ÿà±� &Dot &à°šà±�à°•à±�à°• Dot &And Comma à°šà±�à°•à±�à°• &మరియà±� కామా Toward +∞ (&ceil) +∞ వైపà±� (&ceil) Toward −∞ (&floor) −∞ వైపà±� (&floor) &Binary &à°¦à±�విమానం &Engineering &ఇంజినీరింగà±� &Hexadecimal &షోడశమానం &Octal &à°…à°·à±�టమానం &Scientific &శాసà±�à°¤à±�రీయ User &Manual వినియోగదారà±� &మానà±�à°¯à±�వలà±� Issues and &Feedback &సమసà±�యలà±� మరియà±� à°…à°­à°¿à°ªà±�రాయం &Donate &విరాళం ఇవà±�వండి &About SpeedCrunch &SpeedCrunch à°—à±�à°°à°¿à°‚à°šà°¿ App Diag&nostics &à°…à°¨à±�వరà±�తన విశà±�లేషణ S&plit &విభజించà±� Angle &Mode &కోణ విధానం &Complex Form &సంకీరà±�à°£ రూపం New Tab కొతà±�à°¤ à°Ÿà±�యాబà±� Constants à°¸à±�థిరాంకాలà±� Functions à°«à°‚à°•à±�à°·à°¨à±�à°²à±� History à°šà°°à°¿à°¤à±�à°° User Functions వినియోగదారà±� à°«à°‚à°•à±�à°·à°¨à±�à°²à±� &Font... &ఫాంటà±�... &Language... &భాష... &Session &సెషనà±� &Edit &సవరించà±� &View &వీకà±�à°·à°£ Se&ttings &సెటà±�à°Ÿà°¿à°‚à°—à±�‌లà±� &Decimal &దశాంశం &Keypad &కీపà±�యాడà±� Always on &Top à°Žà°²à±�లపà±�à°ªà±�డూ &పైన Disabled నిలిపివేయబడింది Small Space à°šà°¿à°¨à±�à°¨ ఖాళీ Medium Space మధà±�యసà±�à°¥ ఖాళీ Large Space పెదà±�à°¦ ఖాళీ &0 Digits &0 అంకెలà±� &15 Digits &15 అంకెలà±� &2 Digits &2 అంకెలà±� &3 Digits &3 అంకెలà±� &50 Digits &50 అంకెలà±� &8 Digits &8 అంకెలà±� &Sexagesimal &à°·à°·à±�à°Ÿà±�యంశం Reset All Settings... à°…à°¨à±�ని అమరికలనà±� రీసెటà±� చేయి... &System &à°µà±�యవసà±�à°¥ SpeedCrunch &Theme &SpeedCrunch థీమà±� &Classic &సంపà±�రదాయ &Modern &ఆధà±�నిక Context Help సందరà±�à°­ సహాయం &Help &సహాయం Error లోపం Can't read from file %1 %1 ఫైలà±� à°¨à±�à°‚à°¡à°¿ చదవలేరà±� Import Session సెషనà±�‌నà±� దిగà±�మతి చేయి Close Session సెషనà±�‌నà±� మూసివేయి Angle Mode: కోణ మోడà±�: Notation: సంకేతనం: Precision: à°–à°šà±�చితతà±�వం: Turn à°Ÿà°°à±�à°¨à±� Revolution పరిభà±�రమణం Fixed-point decimal à°¸à±�థిర-బిందà±� దశాంశం Rational రేషనలà±� Automatic decimal à°¸à±�వయంచాలక దశాంశం Automatic à°¸à±�వయంచాలక User &Definitions... వినియోగదారà±� &నిరà±�వచనలà±�... New &Tab కొతà±�à°¤ &à°Ÿà±�యాబà±� New &Private Tab &కొతà±�à°¤ à°ªà±�రైవేటà±� à°Ÿà±�యాబà±� Keep ఉంచà±� Make Private... à°ªà±�రైవేటà±�‌గా మారà±�à°šà±�... New &Window కొతà±�à°¤ &విండో &Open... &తెరà±�à°µà±�... &Rename... పే&à°°à±� మారà±�à°šà±�... Clo&ne... నక&à°²à±� సృషà±�à°Ÿà°¿à°‚à°šà±�... &Close Tab à°Ÿà±�&యాబà±� మూసివేయి Reopen Clo&sed Tab &మూసిన à°Ÿà±�యాబà±� మళà±�లీ తెరà±�à°µà±� Open Sessions &Folder సెషనà±�à°² &ఫోలà±�à°¡à°°à±�‌నà±� తెరà±�à°µà±� &Undo &à°°à°¦à±�à°¦à±� చేయి &Redo &మళà±�లీ చేయి Cu&t à°•&à°¤à±�తిరించà±� Copy &Last Result &చివరి ఫలితానà±�ని కాపీ చేయి &Wrap in Parentheses à°•à±�à°‚&డలీకరణాలà±�లో ఉంచà±� Full Scr&een Mode పూ&à°°à±�తి తెర విధానం &Basic &à°ªà±�రాథమిక &Scientific (wide) &శాసà±�à°¤à±�రీయ (వెడలà±�à°ªà±�) Scientific (narrow) శాసà±�à°¤à±�రీయ (ఇరà±�à°•à±�) &Custom... &à°…à°¨à±�కూల... Main &Menu à°ªà±�రధాన &మెనà±� User &Variables వినియోగదారà±� &చరరాశà±�à°²à±� &Left &à°Žà°¡à°® &Right &à°•à±�à°¡à°¿ &Up &పైకి &Down à°•à°¿à°‚&దికి Close Pa&ne పే&à°¨à±�‌నà±� మూసివేయి User &Units వినియోగదారà±� &యూనిటà±�à°²à±� &Turn &à°Ÿà°°à±�à°¨à±� If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. కొతà±�à°¤ à°µà±�యకà±�తీకరణ +, -, *, లేదా / తో à°ªà±�రారంభమైతే, SpeedCrunch à°®à±�à°‚à°¦à±�à°—à°¾ "ans" à°¨à±� చొపà±�పిసà±�à°¤à±�ంది. &Accept with Enter &Enterతో ఆమోదించà±� Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. à°ªà±�à°°à°¸à±�à°¤à±�à°¤ à°¸à±�వయంపూరణ సూచననà±� à°®à±�à°‚à°¦à±�à°—à°¾ బాణం కీలతో à°Žà°‚à°šà±�కోకà±�ండానే Enterతో ఆమోదించà±�. &Units &యూనిటà±�à°²à±� Show Live Result &Preview à°ªà±�à°°à°¤à±�యకà±�à°· ఫలిత &à°ªà±�à°°à°¿à°µà±�యూనà±� చూపà±� Save &Window Position on Exit నిషà±�à°•à±�రమించినపà±�à°ªà±�à°¡à±� &విండో à°¸à±�థానానà±�ని సేవà±� చేయి Hover Highlighting హోవరà±� హైలైటింగà±� Group Integer Part Only పూరà±�ణసంఖà±�à°¯ భాగానà±�ని మాతà±�రమే సమూహీకరించà±� Number Format... సంఖà±�à°¯ ఆకృతి... Notation && Precision... సంకేతనం && à°–à°šà±�చితతà±�వం... After pressing Enter, keep the entered expression selected in the editor. Enter నొకà±�à°•à°¿à°¨ తరà±�వాత, నమోదà±� చేసిన à°µà±�యకà±�తీకరణనà±� à°Žà°¡à°¿à°Ÿà°°à±�‌లో ఎంపికగా ఉంచà±�. Never à°Žà°ªà±�à°ªà±�డూ కాదà±� Always à°Žà°²à±�లపà±�à°ªà±�డూ Only for Single-Line Expressions ఒకే-లైనà±� à°µà±�యకà±�తీకరణలకే Simplify Displayed Expressions à°ªà±�రదరà±�à°¶à°¿à°‚à°šà°¿à°¨ à°µà±�యకà±�తీకరణలనà±� సరళీకరించà±� History Size &Limit... à°šà°°à°¿à°¤à±�à°° పరిమాణ &పరిమితి... Remove Trailing &Zeroes &చివరి à°¸à±�à°¨à±�నాలనà±� తొలగించà±� Nearest, Half &Away (round) సమీపం, సగం &దూరంగా (round) Nearest, Half &Even (roundeven) సమీపం, సగం &సమసంఖà±�యకà±� (roundeven) Toward &Zero (trunc) &à°¸à±�à°¨à±�నా వైపà±� (trunc) &Fixed-Point &à°¸à±�థిర-బిందà±� &Rational &రేషనలà±� &Exponential (m·sâ�»Â¹) &ఘాతాంక (m·sâ�»Â¹) &Fractional (m/s) &à°­à°¿à°¨à±�à°¨ (m/s) &Rectangular (a + bi) &ఆయతాకార (a + bi) Exponential (reâ�±á¶¿) ఘాతాంక (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) à°¤à±�రికోణమితీయ (r(cos θ + i·sin θ)) Phasor (r∠θ) ఫేజరà±� (r∠θ) &Theme... &థీమà±�... Check for &Updates &నవీకరణల కోసం తనిఖీ చేయి Source Code మూల కోడà±� &Zoom &జూమà±� &Results &ఫలితాలà±� Unit Notation యూనిటà±� సంకేతనం Rounding Mode రౌండింగà±� మోడà±� &Notation &సంకేతనం &Imaginary Unit &à°•à°²à±�పిత యూనిటà±� &Window &విండో &Editing &సవరణ A&utocomplete &à°¸à±�వయంపూరà±�తి Up/Down Arrow History పై/à°•à±�రింది బాణం à°šà°°à°¿à°¤à±�à°° &Appearance &రూపà±�రేఖలà±� &Menus &మెనూలà±� &Docks &డాకà±� చేయగల à°ªà±�యానెలà±�‌లà±� &Input and Results &ఇనà±�‌పà±�à°Ÿà±� మరియà±� ఫలితాలà±� &Disabled &నిలిపివేయబడింది &Disable &నిలిపివేయి Close preview à°ªà±�à°°à°¿à°µà±�యూనà±� మూసివేయి Rename... పేరà±� మారà±�à°šà±�... Clone... నకలà±� సృషà±�à°Ÿà°¿à°‚à°šà±�... Close Tab à°Ÿà±�యాబà±� మూసివేయి New Private Tab కొతà±�à°¤ à°ªà±�రైవేటà±� à°Ÿà±�యాబà±� Open... తెరà±�à°µà±�... Reopen Closed Tab మూసిన à°Ÿà±�యాబà±� మళà±�లీ తెరà±�à°µà±� Split విభజించà±� Left à°Žà°¡à°® Right à°•à±�à°¡à°¿ Up పైకి Down కిందికి Clear ఖాళీ చేయి Delete తొలగించà±� %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 à°ªà±�రైవేటà±� సెషనà±�: మూసివేసినపà±�à°ªà±�à°¡à±� విషయం విసà±�మరించబడà±�à°¤à±�ంది. సాధారణ సెషనà±�‌గా మారà±�చడానికి సెషనà±� > ఉంచà±� à°Žà°‚à°šà±�కోండి. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [à°ªà±�రైవేటà±�] Reset All Settings à°…à°¨à±�ని అమరికలనà±� రీసెటà±� చేయి Reset all settings to their default values? à°…à°¨à±�ని అమరికలనà±� వాటి à°…à°ªà±�రమేయ విలà±�వలకà±� రీసెటà±� చేయాలా? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. ఇందà±�లో రూపం, సవరణ, ఫలితాల ఆకృతà±�à°²à±�, విండో à°ªà±�రాధానà±�యతలà±� ఉంటాయి. మీ గణనలà±�, తెరిచిన సెషనà±�‌లà±�, వినియోగదారà±� నిరà±�వచనాలà±� ఉంచబడతాయి. The settings file could not be written. అమరికల ఫైలà±�‌నà±� à°µà±�రాయలేకపోయింది. Clear this session's calculations, unfinished expression, variables, functions, and units? à°ˆ సెషనà±� గణనలà±�, అసంపూరà±�à°£ సమాసం, చరరాశà±�à°²à±�, à°«à°‚à°•à±�à°·à°¨à±�à°²à±�, à°ªà±�రమాణాలనà±� ఖాళీ చేయాలా? Global user definitions are kept. సారà±�వతà±�à°°à°¿à°• వినియోగదారà±� నిరà±�వచనాలà±� ఉంచబడతాయి. Make Session Private సెషనà±�‌నà±� à°ªà±�రైవేటà±�‌గా మారà±�à°šà±� The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. à°­à°¦à±�రపరచిన సెషనà±� %1 తొలగించబడà±�à°¤à±�ంది. దాని విషయం à°ªà±�రైవేటà±� సెషనà±�‌లో తెరిచి ఉంటà±�ంది. à°† సెషనà±�‌నà±� మూసినపà±�à°ªà±�à°¡à±� లేదా SpeedCrunch à°¨à±�à°‚à°¡à°¿ నిషà±�à°•à±�రమించినపà±�à°ªà±�à°¡à±� విసà±�మరించబడà±�à°¤à±�ంది. Make Private à°ªà±�రైవేటà±�‌గా మారà±�à°šà±� Could not delete the saved session %1. à°­à°¦à±�రపరచిన సెషనà±� %1à°¨à±� తొలగించలేకపోయింది. Keep Session సెషనà±�‌నà±� ఉంచà±� Could not save the session. It remains private. సెషనà±�‌నà±� à°­à°¦à±�రపరచలేకపోయింది. ఇది à°ªà±�రైవేటà±�‌గానే ఉంటà±�ంది. Clone Session సెషనà±� నకలà±� సృషà±�à°Ÿà°¿à°‚à°šà±� Could not save session file %1. సెషనà±� ఫైలà±� %1à°¨à±� à°­à°¦à±�రపరచలేకపోయింది. Could not delete session file %1. సెషనà±� ఫైలà±� %1à°¨à±� తొలగించలేకపోయింది. JSON file (*.json);;Any file (*.*) JSON ఫైలà±� (*.json);;à°� ఫైలà±� అయినా (*.*) Export session as JSON సెషనà±�‌నà±� JSONà°—à°¾ à°Žà°—à±�మతి చేయి The selected file is not valid JSON: %1 à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ ఫైలà±� చెలà±�à°²à±�బాటà±� à°…à°¯à±�యే JSON కాదà±�: %1 The selected file is not a SpeedCrunch session JSON file. à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ ఫైలà±� SpeedCrunch సెషనà±� JSON ఫైలà±� కాదà±�. This file uses an obsolete SpeedCrunch session format and cannot be imported. à°ˆ ఫైలà±� పాతబడిన SpeedCrunch సెషనà±� ఆకృతిని ఉపయోగిసà±�à°¤à±�ంది మరియà±� దిగà±�మతి చేయలేరà±�. The selected JSON file is missing the required $schema field. à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ JSON ఫైలà±�‌లో అవసరమైన $schema ఫీలà±�à°¡à±� లేదà±�. The selected JSON file uses an unsupported JSON schema: %1 à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ JSON ఫైలà±� మదà±�దతà±� లేని JSON à°¸à±�కీమానà±� ఉపయోగిసà±�తోంది: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ JSON ఫైలà±�‌లో SpeedCrunch సెషనà±� à°¸à±�కీమా à°—à±�à°°à±�తింపà±� ($id) లేదà±�. The selected JSON file uses an unsupported SpeedCrunch session format: %1 à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ JSON ఫైలà±� మదà±�దతà±� లేని SpeedCrunch సెషనà±� ఆకృతిని ఉపయోగిసà±�తోంది: %1 The selected JSON file is missing the required session name. à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ JSON ఫైలà±�‌లో అవసరమైన సెషనà±� పేరà±� లేదà±�. The selected JSON file has an empty session name. à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ JSON ఫైలà±�‌లో సెషనà±� పేరà±� ఖాళీగా ఉంది. The selected JSON file has invalid or incomplete SpeedCrunch session data. à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ JSON ఫైలà±�‌లో చెలà±�లని లేదా అసంపూరà±�à°£ SpeedCrunch సెషనà±� డేటా ఉంది. Open Sessions Folder సెషనà±�à°² ఫోలà±�à°¡à°°à±�‌నà±� తెరà±�à°µà±� Could not create the sessions folder: %1 సెషనà±�à°² ఫోలà±�à°¡à°°à±�‌నà±� సృషà±�టించలేకపోయింది: %1 Could not open the sessions folder: %1 సెషనà±�à°² ఫోలà±�à°¡à°°à±�‌నà±� తెరవలేకపోయింది: %1 Editor and Results Font à°Žà°¡à°¿à°Ÿà°°à±� మరియà±� ఫలితాల ఫాంటà±� Open Session సెషనà±�‌నà±� తెరà±�à°µà±� Community సమà±�దాయం Rename Session సెషనà±� పేరà±� మారà±�à°šà±� Clear Session సెషనà±�‌నà±� à°•à±�లియరà±� చేయి Delete Session సెషనà±�‌నà±� తొలగించà±� Close Pane పేనà±�‌నà±� మూసివేయి User Variables వినియోగదారà±� చరరాశà±�à°²à±� User Units వినియోగదారà±� యూనిటà±�à°²à±� Clear History à°šà°°à°¿à°¤à±�à°°à°¨à±� à°•à±�లియరà±� చేయి Are you sure you want to clear the calculation history? గణన à°šà°°à°¿à°¤à±�à°°à°¨à±� à°•à±�లియరà±� చేయాలనà±�à°•à±�à°‚à°Ÿà±�à°¨à±�నారా? Session name: సెషనà±� పేరà±�: A session named %1 already exists. %1 అనే సెషనà±� ఇపà±�పటికే ఉంది. Could not create session file %1. సెషనà±� ఫైలà±� %1 సృషà±�టించలేకపోయింది. Could not write session file %1. సెషనà±� ఫైలà±� %1 à°µà±�రాయలేకపోయింది. Are you sure you want to delete this session? à°ˆ సెషనà±�‌నà±� తొలగించాలనà±�à°•à±�à°‚à°Ÿà±�à°¨à±�నారా? Custom Precision à°…à°¨à±�కూల à°–à°šà±�చితతà±�వం Fractional digits: à°­à°¿à°¨à±�à°¨ అంకెలà±�: Theme థీమà±� Light Themes లైటà±� థీమà±�‌లà±� Dark Themes డారà±�à°•à±� థీమà±�‌లà±� Preview à°ªà±�à°°à°¿à°µà±�యూ Colors à°°à°‚à°—à±�à°²à±� Select color for %1 %1 కోసం à°°à°‚à°—à±�à°¨à±� à°Žà°‚à°šà±�కోండి Import... దిగà±�మతి... Export... à°Žà°—à±�మతి... Import Theme థీమà±�‌నà±� దిగà±�మతి చేయి Theme file (*.json);;All files (*) థీమà±� ఫైలà±� (*.json);;à°…à°¨à±�ని ఫైళà±�à°²à±� (*) Invalid theme file. చెలà±�లని థీమà±� ఫైలà±�. Can't import theme "%1" because it conflicts with a built-in theme. "%1" థీమà±�‌నà±� దిగà±�మతి చేయలేరà±�, à°Žà°‚à°¦à±�కంటే అది అంతరà±�నిరà±�మిత థీమà±�‌తో విరà±�à°¦à±�à°§à°‚à°—à°¾ ఉంది. Can't find a writable theme folder. à°µà±�రాయగల థీమà±� ఫోలà±�à°¡à°°à±� కనబడలేదà±�. Overwrite Theme థీమà±�‌నà±� ఓవరà±�‌రైటà±� చేయి A custom theme named "%1" already exists. Do you want to overwrite it? "%1" అనే à°…à°¨à±�కూల థీమà±� ఇపà±�పటికే ఉంది. దానిని ఓవరà±�‌రైటà±� చేయాలా? Can't overwrite theme file %1 థీమà±� ఫైలà±� %1 à°¨à±� ఓవరà±�‌రైటà±� చేయలేరà±� Can't copy theme file to %1 థీమà±� ఫైలà±�‌నà±� %1 à°•à±� కాపీ చేయలేరà±� Export Theme థీమà±�‌నà±� à°Žà°—à±�మతి చేయి Can't export theme as "%1" because it conflicts with a built-in theme. "%1" à°—à°¾ థీమà±�‌నà±� à°Žà°—à±�మతి చేయలేరà±�, à°Žà°‚à°¦à±�కంటే అది అంతరà±�నిరà±�మిత థీమà±�‌తో విరà±�à°¦à±�à°§à°‚à°—à°¾ ఉంది. Can't write to file %1 %1 ఫైలà±�‌కà±� à°µà±�రాయలేరà±� Global User Variable à°—à±�లోబలà±� వినియోగదారà±� చరరాశి Global User Function à°—à±�లోబలà±� వినియోగదారà±� à°«à°‚à°•à±�à°·à°¨à±� Global User Unit à°—à±�లోబలà±� వినియోగదారà±� యూనిటà±� User Definitions వినియోగదారà±� నిరà±�వచనాలà±� These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. à°ˆ నిరà±�వచనాలà±� à°—à±�లోబలà±�‌గా ఉంటాయి మరియà±� à°ªà±�రతి సెషనà±�‌లో లోడà±� చేయబడతాయి. సెషనà±�‌లలో వీటిని మారà±�చలేరà±� మరియà±� సెషనà±� à°Žà°¡à°¿à°Ÿà°°à±�‌లోని అదే పేరà±� à°—à°² నిరà±�వచనాల కంటే వీటికే à°ªà±�రాధానà±�యత ఉంటà±�ంది. à°ªà±�రతి పంకà±�తిలో à°’à°• నిరà±�వచనానà±�ని నమోదà±� చేయండి. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] ఉదాహరణలà±�: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply వరà±�తింపజేయి Validate ధృవీకరించà±� Test Results పరీకà±�à°· ఫలితాలà±� Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 దిగà±�మతి చేసిన చరరాశà±�à°²à±�: %1 దిగà±�మతి చేసిన à°«à°‚à°•à±�à°·à°¨à±�à°²à±�: %2 దిగà±�మతి చేసిన యూనిటà±�à°²à±�: %3 లోపాలà±� ఉనà±�à°¨ పంకà±�à°¤à±�à°² సంఖà±�యలà±�: %4 none à°�వీ లేవà±� Apply Results వరà±�తింపజేసిన ఫలితాలà±� User definitions saved. వినియోగదారà±� నిరà±�వచనాలà±� సేవà±� చేయబడà±�డాయి. History Size Limit à°šà°°à°¿à°¤à±�à°° పరిమాణ పరిమితి Maximum number of history entries for this session (0 = unlimited): à°ˆ సెషనà±�‌లో à°šà°°à°¿à°¤à±�à°° నమోదà±�à°² à°—à°°à°¿à°·à±�à°  సంఖà±�à°¯ (0 = అపరిమితం): Text file (*.txt);;Any file (*.*) పాఠà±�à°¯ ఫైలà±� (*.txt);;à°� ఫైలà±� అయినా (*.*) Could not recalculate from calculation %1: %2 గణన %1 à°¨à±�à°‚à°¡à°¿ మళà±�లీ లెకà±�కించలేకపోయింది: %2 History Size Limit Reached à°šà°°à°¿à°¤à±�à°° పరిమాణ పరిమితి చేరà±�à°•à±�ంది This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. à°ˆ గణన చివరి à°…à°‚à°¦à±�బాటà±�లో ఉనà±�à°¨ à°šà°°à°¿à°¤à±�à°° à°¸à±�థానానà±�ని నింపà±�à°¤à±�ంది. భవిషà±�యతà±� గణనలà±� à°šà°°à°¿à°¤à±�రలోని అతి పాత గణననà±� తొలగిసà±�తాయి. Session > History Size Limit à°¨à±�à°‚à°¡à°¿ పరిమితిని పెంచవచà±�à°šà±�. Editing calculation. Press Esc twice to cancel. గణననà±� సవరిసà±�à°¤à±�à°¨à±�నారà±�. à°°à°¦à±�à°¦à±� చేయడానికి Esc à°¨à±� రెండà±�సారà±�à°²à±� నొకà±�à°•à°‚à°¡à°¿. Calculation Settings గణన సెటà±�à°Ÿà°¿à°‚à°—à±�‌లà±� Invalid recalculation start index చెలà±�లని మళà±�లీ గణన à°ªà±�రారంభ సూచిక System Default సిసà±�à°Ÿà°®à±� డిఫాలà±�à°Ÿà±� Language భాష Select the language: భాషనà±� à°Žà°‚à°šà±�కోండి: Custom à°…à°¨à±�కూలం Decimal places: దశాంశ à°¸à±�థానాలà±�: &Automatic &à°¸à±�వయంచాలక &Precision &à°–à°šà±�చితతà±�వం Plain &text సాధారణ &పాఠà±�యం Formula &Book సూతà±�రాల &à°ªà±�à°¸à±�తకం &Export &à°Žà°—à±�మతి Export session as HTML సెషనà±�‌నà±� HTMLà°—à°¾ à°Žà°—à±�మతి చేయి HTML file (*.html) HTML ఫైలà±� (*.html) Export session as plain text సెషనà±�‌నà±� సాధారణ పాఠà±�యంగా à°Žà°—à±�మతి చేయి ManualWindow SpeedCrunch Manual SpeedCrunch మానà±�à°¯à±�వలà±� %1 - SpeedCrunch Manual %1 - SpeedCrunch మానà±�à°¯à±�వలà±� NumberFormatDialog Number Format సంఖà±�à°¯ ఆకృతి <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>ఫలితాలà±� మరియà±� ఇనà±�‌పà±�à°Ÿà±� అంకెల సమూహానికి సంఖà±�యా ఆకృతిని à°Žà°‚à°šà±�కోండి.</b><br/><br/>గమనిక: ఇనà±�‌పà±�à°Ÿà±� సంఖà±�యల à°¸à±�పషà±�టమైన ఆకృతà±�à°²à±� à°Žà°‚à°šà±�à°•à±�à°¨à±�à°¨ à°ªà±�రదరà±�à°¶à°¨ ఆకృతికి à°­à°¿à°¨à±�నంగా ఉనà±�నా ఆమోదించబడతాయి.<br/> QObject Global User Variable à°—à±�లోబలà±� వినియోగదారà±� చరరాశి Global User Function à°—à±�లోబలà±� వినియోగదారà±� à°«à°‚à°•à±�à°·à°¨à±� Global User Unit à°—à±�లోబలà±� వినియోగదారà±� యూనిటà±� Backspace à°¬à±�యాకà±�‌సà±�పేసà±� Clear expression à°µà±�యకà±�తీకరణనà±� à°•à±�లియరà±� చేయి Evaluate expression à°µà±�యకà±�తీకరణనà±� లెకà±�à°•à°¿à°‚à°šà±� Insert text పాఠà±�యానà±�ని చొపà±�పించà±� Automatic decimal à°¸à±�వయంచాలక దశాంశం Fixed-point decimal à°¸à±�థిర-బిందà±� దశాంశం Engineering decimal ఇంజినీరింగà±� దశాంశం Scientific decimal శాసà±�à°¤à±�రీయ దశాంశం Rational రేషనలà±� Binary à°¦à±�విమానం Octal à°…à°·à±�టమానం Hexadecimal షోడశమానం Sexagesimal à°·à°·à±�à°Ÿà±�యంశం Update Available నవీకరణ à°…à°‚à°¦à±�బాటà±�లో ఉంది A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> కొతà±�à°¤ వెరà±�à°·à°¨à±� (%1) à°…à°‚à°¦à±�బాటà±�లో ఉంది.<br/><a href="%2">డౌనà±�‌లోడà±� చేయడానికి వెబà±�‌సైటà±�‌నà±� సందరà±�à°¶à°¿à°‚à°šà°‚à°¡à°¿.</a> Check for Updates నవీకరణల కోసం తనిఖీ చేయి SpeedCrunch %1 is up to date. SpeedCrunch %1 తాజాగానే ఉంది. No connectivity. Please check your internet connection and try again. కనెకà±�టివిటీ లేదà±�. దయచేసి మీ ఇంటరà±�నెటà±� కనెకà±�à°·à°¨à±�‌నà±� తనిఖీ చేసి మళà±�లీ à°ªà±�రయతà±�నించండి. Could not verify the latest available version. తాజా à°…à°‚à°¦à±�బాటà±�లో ఉనà±�à°¨ వెరà±�à°·à°¨à±�‌నà±� ధృవీకరించలేకపోయింది. ResultDisplay Scroll to bottom కిందకà±� à°¸à±�à°•à±�రోలà±� చేయి Edit Expression à°µà±�యకà±�తీకరణనà±� సవరించà±� Change Settings సెటà±�à°Ÿà°¿à°‚à°—à±�‌లనà±� మారà±�à°šà±� New Tab కొతà±�à°¤ à°Ÿà±�యాబà±� &Import... &దిగà±�మతి... &Export &à°Žà°—à±�మతి Plain &text సాధారణ &పాఠà±�యం Copy కాపీ చేయి Selection ఎంపిక Select All à°…à°¨à±�నీ à°Žà°‚à°šà±�కోండి Expression సమాసం Result ఫలితం Calculation గణన Calculation as Single Line ఒకే పంకà±�తిలో గణన Remove తొలగించà±� This Calculation à°ˆ గణన All Calculations Above పైన ఉనà±�à°¨ à°…à°¨à±�ని గణనలà±� All Calculations Below à°•à°¿à°‚à°¦ ఉనà±�à°¨ à°…à°¨à±�ని గణనలà±� New Private Tab కొతà±�à°¤ à°ªà±�రైవేటà±� à°Ÿà±�యాబà±� Session సెషనà±� Open... తెరà±�à°µà±�... Clone... నకలà±� సృషà±�à°Ÿà°¿à°‚à°šà±�... Rename... పేరà±� మారà±�à°šà±�... Keep ఉంచà±� Make Private... à°ªà±�రైవేటà±�‌గా మారà±�à°šà±�... Clear ఖాళీ చేయి Delete తొలగించà±� Close మూసివేయి Split విభజించà±� Left à°Žà°¡à°® Right à°•à±�à°¡à°¿ Up పైకి Down కిందికి Close Pane పేనà±�‌నà±� మూసివేయి Main Menu à°ªà±�రధాన మెనà±� Cancel editing సవరణనà±� à°°à°¦à±�à°¦à±� చేయి Copy result ఫలితానà±�ని కాపీ చేయి Edit expression à°µà±�యకà±�తీకరణనà±� సవరించà±� Change settings సెటà±�à°Ÿà°¿à°‚à°—à±�‌లనà±� మారà±�à°šà±� Remove calculation గణననà±� తొలగించà±� ResultSlotsDialog Notation & Precision సంకేతనం & à°–à°šà±�చితతà±�వం Result Line ఫలిత పంకà±�తి Enabled à°ªà±�రారంభించబడింది Notation సంకేతనం Decimal Places దశాంశ à°¸à±�థానాలà±� Main Line à°ªà±�రధాన పంకà±�తి Extra Line #1 అదనపà±� పంకà±�తి #1 Extra Line #2 అదనపà±� పంకà±�తి #2 Extra Line #3 అదనపà±� పంకà±�తి #3 Extra Line #4 అదనపà±� పంకà±�తి #4 Auto à°¸à±�వయంచాలక UserFunctionListWidget Name పేరà±� Value విలà±�à°µ Description వివరణ Search శోధించà±� No match found సరిపోలిక కనబడలేదà±� Insert చొపà±�పించà±� Edit సవరించà±� Delete తొలగించà±� Delete All à°…à°¨à±�నీ తొలగించà±� UserUnitListWidget Name పేరà±� Value విలà±�à°µ Description వివరణ Search శోధించà±� No match found సరిపోలిక కనబడలేదà±� Insert చొపà±�పించà±� Edit సవరించà±� Delete తొలగించà±� Delete All à°…à°¨à±�నీ తొలగించà±� VariableListWidget Name పేరà±� Value విలà±�à°µ Description వివరణ Search శోధించà±� No match found సరిపోలిక కనబడలేదà±� Insert చొపà±�పించà±� Edit సవరించà±� Delete తొలగించà±� Delete All à°…à°¨à±�నీ తొలగించà±� heldercorreia-speedcrunch-e7ca37f/src/resources/locale/th.ts000066400000000000000000012116051526573132500243660ustar00rootroot00000000000000 AboutBox About SpeedCrunch เà¸�ี่ยวà¸�ับ SpeedCrunch Main author | Logo | Maintainer ผู้เขียนหลัà¸� | โลโà¸�้ | ผู้ดูà¹�ล Core developers ผู้พัฒนาหลัà¸� Original author ผู้เขียนต้นฉบับ Math engine เอนจินคณิตศาสตร์ Thanks ขอบคุณ Copyright (C) 2004-2026 The SpeedCrunch developers ลิขสิทธิ์ (C) 2004-2026 ผู้พัฒนา SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version โปรà¹�à¸�รมนี้เป็นซอฟต์à¹�วร์เสรี คุณสามารถà¹�จà¸�จ่ายต่อà¹�ละ/หรือà¹�à¸�้ไขได้ภายใต้เงื่อนไขของสัà¸�à¸�าอนุà¸�าต GNU General Public License ตามที่มูลนิธิซอฟต์à¹�วร์เสรีเผยà¹�พร่ โดยเป็นสัà¸�à¸�าอนุà¸�าตรุ่นที่ 2 หรือ (ตามที่คุณเลือà¸�) รุ่นที่ใหม่à¸�ว่า This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. โปรà¹�à¸�รมนี้เผยà¹�พร่ด้วยความหวังว่าจะเป็นประโยชน์ à¹�ต่ไม่มีà¸�ารรับประà¸�ันใดๆ ทั้งสิ้น à¹�ม้à¹�ต่à¸�ารรับประà¸�ันโดยนัยด้านความสามารถเชิงพาณิชย์หรือความเหมาะสมสำหรับวัตถุประสงค์เฉพาะ โปรดดูรายละเอียดเพิ่มเติมใน GNU General Public License Close ปิด BitFieldWidget Reset bits to zero รีเซ็ตบิตเป็นศูนย์ Invert bits à¸�ลับค่าบิต Shift bits left เลื่อนบิตไปทางซ้าย Shift bits right เลื่อนบิตไปทางขวา Book Index สารบัà¸� Algebra พีชคณิต Quadratic Equation สมà¸�ารà¸�ำลังสอง Logarithmic Base Conversion à¸�ารà¹�ปลงà¸�านลอà¸�าริทึม Geometry เรขาคณิต Circle วงà¸�ลม Sector ภาคของวงà¸�ลม Sphere ทรงà¸�ลม Cube ลูà¸�บาศà¸�์ Cone ทรงà¸�รวย Cylinder ทรงà¸�ระบอà¸� Electronics อิเล็à¸�ทรอนิà¸�ส์ Ohm's Law à¸�ฎของโอห์ม Power à¸�ำลังไฟฟ้า Reactance รีà¹�อคà¹�ตนซ์ Resonance เรโซà¹�นนซ์ Radio Frequency ความถี่วิทยุ Antennas เสาอาà¸�าศ Characteristic Impedance (coax) อิมพีà¹�ดนซ์ลัà¸�ษณะเฉพาะ (coax) Velocity of Propagation (coax) ความเร็วà¸�ารà¹�พร่à¸�ระจาย (coax) Standing Wave Ratio & Return Loss อัตราส่วนคลื่นนิ่ง à¹�ละà¸�ารสูà¸�เสียย้อนà¸�ลับ Free Space Wavelength ความยาวคลื่นในอวà¸�าศอิสระ resistance ความต้านทาน voltage à¹�รงดันไฟฟ้า current à¸�ระà¹�สไฟฟ้า power à¸�ำลังไฟฟ้า inductive reactance รีà¹�อคà¹�ตนซ์เหนี่ยวนำ capacitive reactance รีà¹�อคà¹�ตนซ์เชิงความจุ inductance ค่าความเหนี่ยวนำ capacitance ค่าความจุไฟฟ้า frequency ความถี่ resonance frequency ความถี่เรโซà¹�นนซ์ area พื้นที่ perimeter เส้นรอบรูป diameter เส้นผ่านศูนย์à¸�ลาง radius รัศมี volume ปริมาตร surface area พื้นที่ผิว height ความสูง slant height ความสูงเอียง face diagonal เส้นทà¹�ยงมุมของหน้า space diagonal เส้นทà¹�ยงมุมภายในทรง edge length ความยาวขอบ arc length ความยาวส่วนโค้ง central angle (degrees) มุมที่จุดศูนย์à¸�ลาง (องศา) dielectric constant ค่าคงที่ไดอิเล็à¸�ทริà¸� outer conductor's inner diameter เส้นผ่านศูนย์à¸�ลางด้านในของตัวนำชั้นนอà¸� inner conductor's outer diameter เส้นผ่านศูนย์à¸�ลางด้านนอà¸�ของตัวนำชั้นใน speed of light ความเร็วà¹�สง input power à¸�ำลังไฟฟ้าขาเข้า reflected power à¸�ำลังไฟฟ้าสะท้อนà¸�ลับ transmitted power à¸�ำลังไฟฟ้าที่ส่งผ่าน return loss à¸�ารสูà¸�เสียย้อนà¸�ลับ reflection coefficient สัมประสิทธิ์à¸�ารสะท้อน standing wave ratio อัตราส่วนคลื่นนิ่ง normalized impedance อิมพีà¹�ดนซ์ที่ทำให้เป็นมาตรà¸�าน frequency (Hz) ความถี่ (Hz) BookDock Formula Book หนังสือสูตร ConstantCompletion Search constants ค้นหาค่าคงที่ No match found ไม่พบรายà¸�ารที่ตรงà¸�ัน Constants Mathematics คณิตศาสตร์ Physics (CODATA 2022) ฟิสิà¸�ส์ (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) เคมี (IUPAC - CIAAW 2021) Uncategorized ไม่จัดหมวดหมู่ Universal สาà¸�ล Physicochemical เคมีฟิสิà¸�ส์ Atomic & Nuclear — General อะตอมà¹�ละนิวเคลียร์ — ทั่วไป Atomic & Nuclear — Electroweak อะตอมà¹�ละนิวเคลียร์ — อิเล็à¸�โทรวีค Atomic & Nuclear — Electron อะตอมà¹�ละนิวเคลียร์ — อิเล็à¸�ตรอน Atomic & Nuclear — Muon อะตอมà¹�ละนิวเคลียร์ — มิวออน Atomic & Nuclear — Tau อะตอมà¹�ละนิวเคลียร์ — เทา Atomic & Nuclear — Proton อะตอมà¹�ละนิวเคลียร์ — โปรตอน Atomic & Nuclear — Neutron อะตอมà¹�ละนิวเคลียร์ — นิวตรอน Atomic & Nuclear — Deuteron อะตอมà¹�ละนิวเคลียร์ — ดิวเทอรอน Atomic & Nuclear — Triton อะตอมà¹�ละนิวเคลียร์ — ทริทอน Atomic & Nuclear — Helion อะตอมà¹�ละนิวเคลียร์ — ฮีเลียน Atomic & Nuclear — Alpha particle อะตอมà¹�ละนิวเคลียร์ — อนุภาคà¹�อลฟา Atomic & Nuclear — Atomic units อะตอมà¹�ละนิวเคลียร์ — หน่วยอะตอม Atomic & Nuclear — Energy conversion relationships อะตอมà¹�ละนิวเคลียร์ — ความสัมพันธ์à¸�ารà¹�ปลงพลังงาน Atomic & Nuclear — X-ray units อะตอมà¹�ละนิวเคลียร์ — หน่วยรังสีเอà¸�ซ์ Atomic & Nuclear — Magnetic shielding corrections อะตอมà¹�ละนิวเคลียร์ — à¸�ารà¹�à¸�้ไขà¸�ารà¸�ำบังà¹�ม่เหล็à¸� Masses มวล Lifetimes อายุขัย Molar Masses มวลโมลาร์ Electronegativity อิเล็à¸�โทรเนà¸�าติวิตี Ionization Energy พลังงานไอออไนเซชัน Nominal Constants (IAU 2015) ค่าคงที่เชิงนาม (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) ค่าประมาณที่ดีที่สุดปัจจุบัน (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) อิมพีà¹�ดนซ์ลัà¸�ษณะเฉพาะของสุà¸�à¸�าà¸�าศ (Zâ‚€) reduced Planck constant (â„�) ค่าคงที่พลังค์à¹�บบลดรูป (â„�) vacuum electric permittivity (ϵ₀) สภาพยอมทางไฟฟ้าของสุà¸�à¸�าà¸�าศ (ϵ₀) Newtonian constant of gravitation (G) ค่าคงที่ความโน้มถ่วงนิวตัน (G) vacuum magnetic permeability (μ₀) สภาพซึมผ่านทางà¹�ม่เหล็à¸�ของสุà¸�à¸�าà¸�าศ (μ₀) Planck constant (h) ค่าคงที่พลังค์ (h) speed of light in vacuum (c) ความเร็วà¹�สงในสุà¸�à¸�าà¸�าศ (c) standard acceleration of gravity (gâ‚™) ความเร่งโน้มถ่วงมาตรà¸�าน (gâ‚™) Newtonian constant of gravitation over h-bar c ค่าคงที่ความโน้มถ่วงนิวตันต่อ h-bar c Planck length ความยาวพลังค์ Planck constant in eV/Hz (h) ค่าคงที่พลังค์ใน eV/Hz (h) Planck mass มวลพลังค์ Planck mass energy equivalent in GeV พลังงานสมมูลมวลพลังค์ใน GeV Planck temperature อุณหภูมิพลังค์ Planck time เวลาพลังค์ reduced Planck constant in eV·s (â„�) ค่าคงที่พลังค์à¹�บบลดรูปใน eV·s (â„�) reduced Planck constant times c in MeV·fm ค่าคงที่พลังค์à¹�บบลดรูปคูณ c ใน MeV·fm Bohr magneton à¹�มà¸�นีตอนบอร์ conductance quantum (Gâ‚€) ควอนตัมความนำไฟฟ้า (Gâ‚€) Coulomb constant (kâ‚‘) ค่าคงที่คูลอมบ์ (kâ‚‘) elementary charge (e) ประจุมูลà¸�าน (e) elementary charge over h-bar ประจุมูลà¸�านหารด้วย h-bar conventional value of Josephson constant ค่าตามà¹�บบà¹�ผนของค่าคงที่โจเซฟสัน Josephson constant ค่าคงที่โจเซฟสัน conventional value of ampere-90 ค่าตามà¹�บบà¹�ผนของà¹�อมà¹�ปร์-90 conventional value of coulomb-90 ค่าตามà¹�บบà¹�ผนของคูลอมบ์-90 conventional value of farad-90 ค่าตามà¹�บบà¹�ผนของฟารัด-90 conventional value of henry-90 ค่าตามà¹�บบà¹�ผนของเฮนรี-90 conventional value of ohm-90 ค่าตามà¹�บบà¹�ผนของโอห์ม-90 conventional value of volt-90 ค่าตามà¹�บบà¹�ผนของโวลต์-90 conventional value of watt-90 ค่าตามà¹�บบà¹�ผนของวัตต์-90 magnetic flux quantum (Φ₀) ควอนตัมฟลัà¸�ซ์à¹�ม่เหล็à¸� (Φ₀) nuclear magneton à¹�มà¸�นีตอนนิวเคลียร์ inverse of conductance quantum ส่วนà¸�ลับของควอนตัมความนำไฟฟ้า conventional value of von Klitzing constant ค่าตามà¹�บบà¹�ผนของค่าคงที่ฟอนคลิตซิง von Klitzing constant ค่าคงที่ฟอนคลิตซิง atomic unit of magnetic dipole moment หน่วยอะตอมของโมเมนต์ไดโพลà¹�ม่เหล็à¸� atomic unit of magnetic flux density หน่วยอะตอมของความหนาà¹�น่นฟลัà¸�ซ์à¹�ม่เหล็à¸� Bohr magneton in eV/T à¹�มà¸�นีตอนบอร์ใน eV/T Bohr magneton in Hz/T à¹�มà¸�นีตอนบอร์ใน Hz/T Bohr magneton in inverse meter per tesla à¹�มà¸�นีตอนบอร์ในเมตรผà¸�ผันต่อเทสลา Bohr magneton in K/T à¹�มà¸�นีตอนบอร์ใน K/T nuclear magneton in eV/T à¹�มà¸�นีตอนนิวเคลียร์ใน eV/T nuclear magneton in inverse meter per tesla à¹�มà¸�นีตอนนิวเคลียร์ในเมตรผà¸�ผันต่อเทสลา nuclear magneton in K/T à¹�มà¸�นีตอนนิวเคลียร์ใน K/T nuclear magneton in MHz/T à¹�มà¸�นีตอนนิวเคลียร์ใน MHz/T Bohr radius (aâ‚€) รัศมีบอร์ (aâ‚€) fine-structure constant (α) ค่าคงที่โครงสร้างละเอียด (α) Hartree energy (Eâ‚•) พลังงานฮาร์ทรี (Eâ‚•) Hartree energy in eV พลังงานฮาร์ทรีใน eV quantum of circulation ควอนตัมà¸�ารไหลวน quantum of circulation times 2 ควอนตัมà¸�ารไหลวนคูณ 2 Rydberg constant (R∞) ค่าคงที่ริดเบิร์à¸� (R∞) atomic mass unit-hartree relationship ความสัมพันธ์ระหว่างหน่วยมวลอะตอมà¸�ับฮาร์ทรี atomic mass unit-hertz relationship ความสัมพันธ์ระหว่างหน่วยมวลอะตอมà¸�ับเฮิรตซ์ atomic mass unit-inverse meter relationship ความสัมพันธ์ระหว่างหน่วยมวลอะตอมà¸�ับเมตรผà¸�ผัน atomic mass unit-joule relationship ความสัมพันธ์ระหว่างหน่วยมวลอะตอมà¸�ับจูล atomic mass unit-kelvin relationship ความสัมพันธ์ระหว่างหน่วยมวลอะตอมà¸�ับเคลวิน atomic mass unit-kilogram relationship ความสัมพันธ์ระหว่างหน่วยมวลอะตอมà¸�ับà¸�ิโลà¸�รัม atomic unit of 1st hyperpolarizability หน่วยอะตอมของไฮเปอร์โพลาไรซาบิลิตีอันดับที่ 1 atomic unit of 2nd hyperpolarizability หน่วยอะตอมของไฮเปอร์โพลาไรซาบิลิตีอันดับที่ 2 atomic unit of charge (e) หน่วยอะตอมของประจุ (e) atomic unit of charge density หน่วยอะตอมของความหนาà¹�น่นประจุ atomic unit of current หน่วยอะตอมของà¸�ระà¹�สไฟฟ้า atomic unit of electric dipole moment หน่วยอะตอมของโมเมนต์ไดโพลไฟฟ้า atomic unit of electric field หน่วยอะตอมของสนามไฟฟ้า atomic unit of electric field gradient หน่วยอะตอมของเà¸�รเดียนต์สนามไฟฟ้า atomic unit of electric polarizability หน่วยอะตอมของสภาพมีขั้วทางไฟฟ้า atomic unit of electric potential หน่วยอะตอมของศัà¸�ย์ไฟฟ้า atomic unit of electric quadrupole moment หน่วยอะตอมของโมเมนต์ควอดรูโพลไฟฟ้า atomic unit of action หน่วยอะตอมของà¹�อ็à¸�ชัน atomic unit of energy หน่วยอะตอมของพลังงาน atomic unit of force หน่วยอะตอมของà¹�รง atomic unit of length หน่วยอะตอมของความยาว hertz-atomic mass unit relationship ความสัมพันธ์ระหว่างเฮิรตซ์à¸�ับหน่วยมวลอะตอม hertz-electron volt relationship ความสัมพันธ์ระหว่างเฮิรตซ์à¸�ับอิเล็à¸�ตรอนโวลต์ hertz-hartree relationship ความสัมพันธ์ระหว่างเฮิรตซ์à¸�ับฮาร์ทรี hertz-inverse meter relationship ความสัมพันธ์ระหว่างเฮิรตซ์à¸�ับเมตรผà¸�ผัน hertz-joule relationship ความสัมพันธ์ระหว่างเฮิรตซ์à¸�ับจูล hertz-kelvin relationship ความสัมพันธ์ระหว่างเฮิรตซ์à¸�ับเคลวิน hertz-kilogram relationship ความสัมพันธ์ระหว่างเฮิรตซ์à¸�ับà¸�ิโลà¸�รัม hyperfine transition frequency of Cs-133 ความถี่ทรานซิชันไฮเปอร์ไฟน์ของ Cs-133 inverse fine-structure constant (αâ�»Â¹) ส่วนà¸�ลับของค่าคงที่โครงสร้างละเอียด (αâ�»Â¹) inverse meter-atomic mass unit relationship ความสัมพันธ์ระหว่างเมตรผà¸�ผันà¸�ับหน่วยมวลอะตอม inverse meter-electron volt relationship ความสัมพันธ์ระหว่างเมตรผà¸�ผันà¸�ับอิเล็à¸�ตรอนโวลต์ inverse meter-hartree relationship ความสัมพันธ์ระหว่างเมตรผà¸�ผันà¸�ับฮาร์ทรี inverse meter-hertz relationship ความสัมพันธ์ระหว่างเมตรผà¸�ผันà¸�ับเฮิรตซ์ inverse meter-joule relationship ความสัมพันธ์ระหว่างเมตรผà¸�ผันà¸�ับจูล inverse meter-kelvin relationship ความสัมพันธ์ระหว่างเมตรผà¸�ผันà¸�ับเคลวิน inverse meter-kilogram relationship ความสัมพันธ์ระหว่างเมตรผà¸�ผันà¸�ับà¸�ิโลà¸�รัม joule-atomic mass unit relationship ความสัมพันธ์ระหว่างจูลà¸�ับหน่วยมวลอะตอม joule-electron volt relationship ความสัมพันธ์ระหว่างจูลà¸�ับอิเล็à¸�ตรอนโวลต์ joule-hertz relationship ความสัมพันธ์ระหว่างจูลà¸�ับเฮิรตซ์ joule-hartree relationship ความสัมพันธ์ระหว่างจูลà¸�ับฮาร์ทรี joule-inverse meter relationship ความสัมพันธ์ระหว่างจูลà¸�ับเมตรผà¸�ผัน joule-kelvin relationship ความสัมพันธ์ระหว่างจูลà¸�ับเคลวิน joule-kilogram relationship ความสัมพันธ์ระหว่างจูลà¸�ับà¸�ิโลà¸�รัม kelvin-atomic mass unit relationship ความสัมพันธ์ระหว่างเคลวินà¸�ับหน่วยมวลอะตอม kelvin-electron volt relationship ความสัมพันธ์ระหว่างเคลวินà¸�ับอิเล็à¸�ตรอนโวลต์ kelvin-hertz relationship ความสัมพันธ์ระหว่างเคลวินà¸�ับเฮิรตซ์ kelvin-hartree relationship ความสัมพันธ์ระหว่างเคลวินà¸�ับฮาร์ทรี kelvin-inverse meter relationship ความสัมพันธ์ระหว่างเคลวินà¸�ับเมตรผà¸�ผัน kelvin-joule relationship ความสัมพันธ์ระหว่างเคลวินà¸�ับจูล kelvin-kilogram relationship ความสัมพันธ์ระหว่างเคลวินà¸�ับà¸�ิโลà¸�รัม kilogram-atomic mass unit relationship ความสัมพันธ์ระหว่างà¸�ิโลà¸�รัมà¸�ับหน่วยมวลอะตอม kilogram-electron volt relationship ความสัมพันธ์ระหว่างà¸�ิโลà¸�รัมà¸�ับอิเล็à¸�ตรอนโวลต์ kilogram-hertz relationship ความสัมพันธ์ระหว่างà¸�ิโลà¸�รัมà¸�ับเฮิรตซ์ kilogram-hartree relationship ความสัมพันธ์ระหว่างà¸�ิโลà¸�รัมà¸�ับฮาร์ทรี kilogram-inverse meter relationship ความสัมพันธ์ระหว่างà¸�ิโลà¸�รัมà¸�ับเมตรผà¸�ผัน kilogram-joule relationship ความสัมพันธ์ระหว่างà¸�ิโลà¸�รัมà¸�ับจูล kilogram-kelvin relationship ความสัมพันธ์ระหว่างà¸�ิโลà¸�รัมà¸�ับเคลวิน lattice parameter of silicon (a) พารามิเตอร์à¹�ลตทิซของซิลิคอน (a) luminous efficacy ประสิทธิภาพà¸�ารส่องสว่าง natural unit of energy หน่วยธรรมชาติของพลังงาน natural unit of energy in MeV หน่วยธรรมชาติของพลังงานใน MeV natural unit of action (â„�) หน่วยธรรมชาติของà¹�อ็à¸�ชัน (â„�) natural unit of action in eV·s หน่วยธรรมชาติของà¹�อ็à¸�ชันใน eV·s natural unit of length หน่วยธรรมชาติของความยาว natural unit of mass หน่วยธรรมชาติของมวล natural unit of momentum หน่วยธรรมชาติของโมเมนตัม natural unit of momentum in MeV/c หน่วยธรรมชาติของโมเมนตัมใน MeV/c natural unit of time หน่วยธรรมชาติของเวลา natural unit of velocity หน่วยธรรมชาติของความเร็ว Rydberg constant times c in Hz ค่าคงที่ริดเบิร์à¸�คูณ c ใน Hz Rydberg constant times hc in eV ค่าคงที่ริดเบิร์à¸�คูณ hc ใน eV Rydberg constant times hc in J ค่าคงที่ริดเบิร์à¸�คูณ hc ใน J Fermi coupling constant ค่าคงที่คัปปลิงà¹�ฟร์มี weak mixing angle มุมผสมà¹�บบอ่อน W to Z mass ratio อัตราส่วนมวล W ต่อ Z Thomson cross section (σₑ) ภาคตัดขวางทอมสัน (σₑ) electron mass (mâ‚‘) มวลของอิเล็à¸�ตรอน(mâ‚‘) electron mass in u มวลของอิเล็à¸�ตรอนใน u electron mass energy equivalent (mₑ·c²) พลังงานสมมูลมวลของอิเล็à¸�ตรอน(mₑ·c²) electron mass energy equivalent in MeV พลังงานสมมูลมวลของอิเล็à¸�ตรอนใน MeV reduced Compton wavelength ความยาวคลื่นคอมป์ตันà¹�บบลดรูป classical electron radius (râ‚‘) รัศมีอิเล็à¸�ตรอนà¹�บบคลาสสิà¸� (râ‚‘) electron charge to mass quotient ผลหารประจุต่อมวลของอิเล็à¸�ตรอน electron-deuteron magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�อิเล็à¸�ตรอนต่อดิวเทอรอน electron-deuteron mass ratio อัตราส่วนมวลอิเล็à¸�ตรอนต่อดิวเทอรอน electron g factor (gâ‚‘) à¹�ฟà¸�เตอร์ g ของอิเล็à¸�ตรอน(gâ‚‘) electron gyromagnetic ratio (γₑ) อัตราส่วนไจโรà¹�ม่เหล็à¸�ของอิเล็à¸�ตรอน(γₑ) electron gyromagnetic ratio in MHz/T อัตราส่วนไจโรà¹�ม่เหล็à¸�ของอิเล็à¸�ตรอนใน MHz/T electron-helion mass ratio อัตราส่วนมวลอิเล็à¸�ตรอนต่อฮีเลียน electron magnetic moment (μₑ) โมเมนต์à¹�ม่เหล็à¸�ของอิเล็à¸�ตรอน(μₑ) electron magnetic moment anomaly (aâ‚‘) ความผิดปà¸�ติของโมเมนต์à¹�ม่เหล็à¸�ของอิเล็à¸�ตรอน(aâ‚‘) electron magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของอิเล็à¸�ตรอนต่อà¹�มà¸�นีตอนบอร์ electron magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของอิเล็à¸�ตรอนต่อà¹�มà¸�นีตอนนิวเคลียร์ electron molar mass (Mâ‚‘) มวลโมลาร์ของอิเล็à¸�ตรอน(Mâ‚‘) electron-muon magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�อิเล็à¸�ตรอนต่อมิวออน electron-muon mass ratio อัตราส่วนมวลอิเล็à¸�ตรอนต่อมิวออน electron-neutron magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�อิเล็à¸�ตรอนต่อนิวตรอน electron-neutron mass ratio อัตราส่วนมวลอิเล็à¸�ตรอนต่อนิวตรอน electron-proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�อิเล็à¸�ตรอนต่อโปรตอน electron-proton mass ratio อัตราส่วนมวลอิเล็à¸�ตรอนต่อโปรตอน electron relative atomic mass (Ar(e)) มวลอะตอมสัมพัทธ์ของอิเล็à¸�ตรอน (Ar(e)) electron-tau mass ratio อัตราส่วนมวลอิเล็à¸�ตรอนต่อเทา electron to alpha particle mass ratio อัตราส่วนมวลอิเล็à¸�ตรอนต่ออนุภาคà¹�อลฟา electron to shielded helion magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�อิเล็à¸�ตรอนต่อฮีเลียนที่ถูà¸�à¸�ำบัง electron to shielded proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�อิเล็à¸�ตรอนต่อโปรตอนที่ถูà¸�à¸�ำบัง electron-triton mass ratio อัตราส่วนมวลอิเล็à¸�ตรอนต่อทริทอน electron volt-atomic mass unit relationship ความสัมพันธ์ระหว่างอิเล็à¸�ตรอนโวลต์à¸�ับหน่วยมวลอะตอม electron volt-hartree relationship ความสัมพันธ์ระหว่างอิเล็à¸�ตรอนโวลต์à¸�ับฮาร์ทรี electron volt-hertz relationship ความสัมพันธ์ระหว่างอิเล็à¸�ตรอนโวลต์à¸�ับเฮิรตซ์ electron volt-inverse meter relationship ความสัมพันธ์ระหว่างอิเล็à¸�ตรอนโวลต์à¸�ับเมตรผà¸�ผัน electron volt-joule relationship ความสัมพันธ์ระหว่างอิเล็à¸�ตรอนโวลต์à¸�ับจูล electron volt-kelvin relationship ความสัมพันธ์ระหว่างอิเล็à¸�ตรอนโวลต์à¸�ับเคลวิน electron volt-kilogram relationship ความสัมพันธ์ระหว่างอิเล็à¸�ตรอนโวลต์à¸�ับà¸�ิโลà¸�รัม hartree-atomic mass unit relationship ความสัมพันธ์ระหว่างฮาร์ทรีà¸�ับหน่วยมวลอะตอม hartree-electron volt relationship ความสัมพันธ์ระหว่างฮาร์ทรีà¸�ับอิเล็à¸�ตรอนโวลต์ muon Compton wavelength ความยาวคลื่นคอมป์ตันของมิวออน muon-electron mass ratio อัตราส่วนมวลมิวออนต่ออิเล็à¸�ตรอน muon g factor à¹�ฟà¸�เตอร์ g ของมิวออน muon magnetic moment โมเมนต์à¹�ม่เหล็à¸�ของมิวออน muon magnetic moment anomaly ความผิดปà¸�ติของโมเมนต์à¹�ม่เหล็à¸�ของมิวออน muon magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของมิวออนต่อà¹�มà¸�นีตอนบอร์ muon magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของมิวออนต่อà¹�มà¸�นีตอนนิวเคลียร์ muon mass มวลของมิวออน muon mass energy equivalent พลังงานสมมูลมวลของมิวออน muon mass energy equivalent in MeV พลังงานสมมูลมวลของมิวออนใน MeV muon mass in u มวลของมิวออนใน u muon molar mass มวลโมลาร์ของมิวออน muon-neutron mass ratio อัตราส่วนมวลมิวออนต่อนิวตรอน muon-proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�มิวออนต่อโปรตอน muon-proton mass ratio อัตราส่วนมวลมิวออนต่อโปรตอน muon-tau mass ratio อัตราส่วนมวลมิวออนต่อเทา reduced muon Compton wavelength ความยาวคลื่นคอมป์ตันà¹�บบลดรูปของมิวออน reduced tau Compton wavelength ความยาวคลื่นคอมป์ตันà¹�บบลดรูปของเทา tau Compton wavelength ความยาวคลื่นคอมป์ตันของเทา tau-electron mass ratio อัตราส่วนมวลเทาต่ออิเล็à¸�ตรอน tau mass มวลของเทา tau mass energy equivalent พลังงานสมมูลมวลของเทา tau mass in u มวลของเทาใน u tau molar mass มวลโมลาร์ของเทา tau-muon mass ratio อัตราส่วนมวลเทาต่อมิวออน tau-neutron mass ratio อัตราส่วนมวลเทาต่อนิวตรอน tau-proton mass ratio อัตราส่วนมวลเทาต่อโปรตอน proton charge to mass quotient ผลหารประจุต่อมวลของโปรตอน proton Compton wavelength ความยาวคลื่นคอมป์ตันของโปรตอน proton-electron mass ratio อัตราส่วนมวลโปรตอนต่ออิเล็à¸�ตรอน proton g factor (gₚ) à¹�ฟà¸�เตอร์ g ของโปรตอน(gₚ) proton gyromagnetic ratio (γₚ) อัตราส่วนไจโรà¹�ม่เหล็à¸�ของโปรตอน(γₚ) proton gyromagnetic ratio in MHz/T อัตราส่วนไจโรà¹�ม่เหล็à¸�ของโปรตอนใน MHz/T proton magnetic moment (μₚ) โมเมนต์à¹�ม่เหล็à¸�ของโปรตอน(μₚ) proton magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของโปรตอนต่อà¹�มà¸�นีตอนบอร์ proton magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของโปรตอนต่อà¹�มà¸�นีตอนนิวเคลียร์ proton magnetic shielding correction à¸�ารà¹�à¸�้ไขà¸�ารà¸�ำบังà¹�ม่เหล็à¸�ของโปรตอน proton mass (mₚ) มวลของโปรตอน(mₚ) proton mass energy equivalent พลังงานสมมูลมวลของโปรตอน proton mass energy equivalent in MeV พลังงานสมมูลมวลของโปรตอนใน MeV proton mass in u มวลของโปรตอนใน u proton molar mass (Mₚ) มวลโมลาร์ของโปรตอน(Mₚ) proton-muon mass ratio อัตราส่วนมวลโปรตอนต่อมิวออน proton-neutron magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�โปรตอนต่อนิวตรอน proton-neutron mass ratio อัตราส่วนมวลโปรตอนต่อนิวตรอน proton relative atomic mass (Ar(p)) มวลอะตอมสัมพัทธ์ของโปรตอน (Ar(p)) proton rms charge radius รัศมีประจุ rms ของโปรตอน proton-tau mass ratio อัตราส่วนมวลโปรตอนต่อเทา reduced proton Compton wavelength ความยาวคลื่นคอมป์ตันà¹�บบลดรูปของโปรตอน shielded proton gyromagnetic ratio อัตราส่วนไจโรà¹�ม่เหล็à¸�ของโปรตอนที่ถูà¸�à¸�ำบัง shielded proton gyromagnetic ratio in MHz/T อัตราส่วนไจโรà¹�ม่เหล็à¸�ของโปรตอนที่ถูà¸�à¸�ำบังใน MHz/T shielded proton magnetic moment โมเมนต์à¹�ม่เหล็à¸�ของโปรตอนที่ถูà¸�à¸�ำบัง shielded proton magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของโปรตอนที่ถูà¸�à¸�ำบังต่อà¹�มà¸�นีตอนบอร์ shielded proton magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของโปรตอนที่ถูà¸�à¸�ำบังต่อà¹�มà¸�นีตอนนิวเคลียร์ neutron Compton wavelength ความยาวคลื่นคอมป์ตันของนิวตรอน neutron-electron magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�นิวตรอนต่ออิเล็à¸�ตรอน neutron-electron mass ratio อัตราส่วนมวลนิวตรอนต่ออิเล็à¸�ตรอน neutron g factor (gâ‚™) à¹�ฟà¸�เตอร์ g ของนิวตรอน(gâ‚™) neutron gyromagnetic ratio (γₙ) อัตราส่วนไจโรà¹�ม่เหล็à¸�ของนิวตรอน(γₙ) neutron gyromagnetic ratio in MHz/T อัตราส่วนไจโรà¹�ม่เหล็à¸�ของนิวตรอนใน MHz/T neutron magnetic moment (μₙ) โมเมนต์à¹�ม่เหล็à¸�ของนิวตรอน(μₙ) neutron magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของนิวตรอนต่อà¹�มà¸�นีตอนบอร์ neutron magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของนิวตรอนต่อà¹�มà¸�นีตอนนิวเคลียร์ neutron mass (mâ‚™) มวลของนิวตรอน(mâ‚™) neutron mass energy equivalent พลังงานสมมูลมวลของนิวตรอน neutron mass energy equivalent in MeV พลังงานสมมูลมวลของนิวตรอนใน MeV neutron mass in u มวลของนิวตรอนใน u neutron molar mass (Mâ‚™) มวลโมลาร์ของนิวตรอน(Mâ‚™) neutron-muon mass ratio อัตราส่วนมวลนิวตรอนต่อมิวออน neutron-proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�นิวตรอนต่อโปรตอน neutron-proton mass difference ผลต่างมวลระหว่างนิวตรอนà¸�ับโปรตอน neutron-proton mass difference energy equivalent พลังงานสมมูลของผลต่างมวลระหว่างนิวตรอนà¸�ับโปรตอน neutron-proton mass difference energy equivalent in MeV พลังงานสมมูลของผลต่างมวลระหว่างนิวตรอนà¸�ับโปรตอนใน MeV neutron-proton mass difference in u ผลต่างมวลระหว่างนิวตรอนà¸�ับโปรตอนใน u neutron-proton mass ratio อัตราส่วนมวลนิวตรอนต่อโปรตอน neutron relative atomic mass (Ar(n)) มวลอะตอมสัมพัทธ์ของนิวตรอน (Ar(n)) neutron-tau mass ratio อัตราส่วนมวลนิวตรอนต่อเทา neutron to shielded proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�นิวตรอนต่อโปรตอนที่ถูà¸�à¸�ำบัง reduced neutron Compton wavelength ความยาวคลื่นคอมป์ตันà¹�บบลดรูปของนิวตรอน deuteron-electron magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ดิวเทอรอนต่ออิเล็à¸�ตรอน deuteron-electron mass ratio อัตราส่วนมวลดิวเทอรอนต่ออิเล็à¸�ตรอน deuteron g factor à¹�ฟà¸�เตอร์ g ของดิวเทอรอน deuteron magnetic moment โมเมนต์à¹�ม่เหล็à¸�ของดิวเทอรอน deuteron magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของดิวเทอรอนต่อà¹�มà¸�นีตอนบอร์ deuteron magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของดิวเทอรอนต่อà¹�มà¸�นีตอนนิวเคลียร์ deuteron mass มวลของดิวเทอรอน deuteron mass energy equivalent พลังงานสมมูลมวลของดิวเทอรอน deuteron mass energy equivalent in MeV พลังงานสมมูลมวลของดิวเทอรอนใน MeV deuteron mass in u มวลของดิวเทอรอนใน u deuteron molar mass มวลโมลาร์ของดิวเทอรอน deuteron-neutron magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ดิวเทอรอนต่อนิวตรอน deuteron-proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ดิวเทอรอนต่อโปรตอน deuteron-proton mass ratio อัตราส่วนมวลดิวเทอรอนต่อโปรตอน deuteron relative atomic mass (Ar(d)) มวลอะตอมสัมพัทธ์ของดิวเทอรอน (Ar(d)) deuteron rms charge radius รัศมีประจุ rms ของดิวเทอรอน triton-electron mass ratio อัตราส่วนมวลทริทอนต่ออิเล็à¸�ตรอน triton g factor (gₜ) à¹�ฟà¸�เตอร์ g ของทริทอน(gₜ) triton magnetic moment (μₜ) โมเมนต์à¹�ม่เหล็à¸�ของทริทอน(μₜ) triton magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของทริทอนต่อà¹�มà¸�นีตอนบอร์ triton magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของทริทอนต่อà¹�มà¸�นีตอนนิวเคลียร์ triton mass (mₜ) มวลของทริทอน(mₜ) triton mass energy equivalent พลังงานสมมูลมวลของทริทอน triton mass energy equivalent in MeV พลังงานสมมูลมวลของทริทอนใน MeV triton mass in u มวลของทริทอนใน u triton molar mass (Mₜ) มวลโมลาร์ของทริทอน(Mₜ) triton-proton mass ratio อัตราส่วนมวลทริทอนต่อโปรตอน triton relative atomic mass (Ar(t)) มวลอะตอมสัมพัทธ์ของทริทอน (Ar(t)) triton to proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ทริทอนต่อโปรตอน helion-electron mass ratio อัตราส่วนมวลฮีเลียนต่ออิเล็à¸�ตรอน helion g factor (gâ‚•) à¹�ฟà¸�เตอร์ g ของฮีเลียน(gâ‚•) helion magnetic moment (μₕ) โมเมนต์à¹�ม่เหล็à¸�ของฮีเลียน(μₕ) helion magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของฮีเลียนต่อà¹�มà¸�นีตอนบอร์ helion magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของฮีเลียนต่อà¹�มà¸�นีตอนนิวเคลียร์ helion mass (mâ‚•) มวลของฮีเลียน(mâ‚•) helion mass energy equivalent พลังงานสมมูลมวลของฮีเลียน helion mass energy equivalent in MeV พลังงานสมมูลมวลของฮีเลียนใน MeV helion mass in u มวลของฮีเลียนใน u helion molar mass (Mâ‚•) มวลโมลาร์ของฮีเลียน(Mâ‚•) helion-proton mass ratio อัตราส่วนมวลฮีเลียนต่อโปรตอน helion relative atomic mass (Ar(h)) มวลอะตอมสัมพัทธ์ของฮีเลียน (Ar(h)) helion shielding shift à¸�ารเลื่อนจาà¸�à¸�ารà¸�ำบังของฮีเลียน shielded helion gyromagnetic ratio อัตราส่วนไจโรà¹�ม่เหล็à¸�ของฮีเลียนที่ถูà¸�à¸�ำบัง shielded helion gyromagnetic ratio in MHz/T อัตราส่วนไจโรà¹�ม่เหล็à¸�ของฮีเลียนที่ถูà¸�à¸�ำบังใน MHz/T shielded helion magnetic moment โมเมนต์à¹�ม่เหล็à¸�ของฮีเลียนที่ถูà¸�à¸�ำบัง shielded helion magnetic moment to Bohr magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของฮีเลียนที่ถูà¸�à¸�ำบังต่อà¹�มà¸�นีตอนบอร์ shielded helion magnetic moment to nuclear magneton ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ของฮีเลียนที่ถูà¸�à¸�ำบังต่อà¹�มà¸�นีตอนนิวเคลียร์ shielded helion to proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ฮีเลียนที่ถูà¸�à¸�ำบังต่อโปรตอน shielded helion to shielded proton magnetic moment ratio อัตราส่วนโมเมนต์à¹�ม่เหล็à¸�ฮีเลียนที่ถูà¸�à¸�ำบังต่อโปรตอนที่ถูà¸�à¸�ำบัง alpha particle mass มวลของอนุภาคà¹�อลฟา alpha particle mass in u มวลของอนุภาคà¹�อลฟาใน u alpha particle mass energy equivalent พลังงานสมมูลมวลของอนุภาคà¹�อลฟา alpha particle mass energy equivalent in MeV พลังงานสมมูลมวลของอนุภาคà¹�อลฟาใน MeV alpha particle-electron mass ratio อัตราส่วนมวลอนุภาคà¹�อลฟาต่ออิเล็à¸�ตรอน alpha particle-proton mass ratio อัตราส่วนมวลอนุภาคà¹�อลฟาต่อโปรตอน alpha particle rms charge radius รัศมีประจุ rms ของอนุภาคà¹�อลฟา alpha particle molar mass มวลโมลาร์ของอนุภาคà¹�อลฟา alpha particle relative atomic mass (Ar(α)) มวลอะตอมสัมพัทธ์ของอนุภาคà¹�อลฟา (Ar(α)) atomic mass constant (mᵤ) ค่าคงที่มวลอะตอม (mᵤ) Avogadro constant ค่าคงที่อาโวà¸�าโดร Boltzmann constant (k) ค่าคงที่โบลทซ์มันน์ (k) Boltzmann constant in eV/K ค่าคงที่โบลทซ์มันน์ ใน eV/K Boltzmann constant in Hz/K ค่าคงที่โบลทซ์มันน์ ใน Hz/K Boltzmann constant in inverse meter per kelvin ค่าคงที่โบลทซ์มันน์ ในเมตรผà¸�ผันต่อเคลวิน electron volt (eV) อิเล็à¸�ตรอนโวลต์ (eV) Faraday constant (F) ค่าคงที่ฟาราเดย์ (F) first radiation constant (câ‚�) ค่าคงที่à¸�ารà¹�ผ่รังสีลำดับที่หนึ่ง (câ‚�) first radiation constant for spectral radiance ค่าคงที่à¸�ารà¹�ผ่รังสีลำดับที่หนึ่งสำหรับความส่องสว่างเชิงสเปà¸�ตรัม molar gas constant (R) ค่าคงที่à¹�à¸�๊สโมลาร์ (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) ค่าคงที่ลอชมิดท์ (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) ค่าคงที่ลอชมิดท์ (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant ค่าคงที่พลังค์โมลาร์ second radiation constant (câ‚‚) ค่าคงที่à¸�ารà¹�ผ่รังสีลำดับที่สอง (câ‚‚) Stefan-Boltzmann constant (σ) ค่าคงที่สเตฟาน-โบลทซ์มันน์ (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ระยะห่างà¹�ลตทิซของ Si อุดมคติ (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent พลังงานสมมูลของค่าคงที่มวลอะตอม atomic mass constant energy equivalent in MeV พลังงานสมมูลของค่าคงที่มวลอะตอมใน MeV atomic mass unit-electron volt relationship ความสัมพันธ์ระหว่างหน่วยมวลอะตอมà¸�ับอิเล็à¸�ตรอนโวลต์ molar mass constant (Mᵤ) ค่าคงที่มวลโมลาร์ (Mᵤ) molar mass of carbon-12 มวลโมลาร์ของคาร์บอน-12 molar volume of ideal gas (273.15 K, 100 kPa) ปริมาตรโมลาร์ของà¹�à¸�๊สอุดมคติ (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ปริมาตรโมลาร์ของà¹�à¸�๊สอุดมคติ (273.15 K, 101.325 kPa) molar volume of silicon ปริมาตรโมลาร์ของซิลิคอน Sackur-Tetrode constant (1 K, 100 kPa) ค่าคงที่ซาคูร์-เทโทรด (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) ค่าคงที่ซาคูร์-เทโทรด (1 K, 101.325 kPa) Wien frequency displacement law constant ค่าคงที่à¸�ฎà¸�ารà¸�ระจัดเชิงความถี่ของวีน Wien wavelength displacement law constant ค่าคงที่à¸�ฎà¸�ารà¸�ระจัดเชิงความยาวคลื่นของวีน standard atmosphere (atm) บรรยาà¸�าศมาตรà¸�าน (atm) standard-state pressure (p°) ความดันสถานะมาตรà¸�าน (p°) Angstrom star (Ã…*) อังสตรอมสตาร์ (Ã…*) Copper x unit หน่วยเอà¸�ซ์ของทองà¹�ดง Molybdenum x unit หน่วยเอà¸�ซ์ของโมลิบดีนัม atomic unit of magnetizability หน่วยอะตอมของสภาพถูà¸�ทำให้เป็นà¹�ม่เหล็à¸� atomic unit of mass (mâ‚‘) หน่วยอะตอมของมวล (mâ‚‘) atomic unit of momentum หน่วยอะตอมของโมเมนตัม atomic unit of permittivity หน่วยอะตอมของสภาพยอม atomic unit of time หน่วยอะตอมของเวลา atomic unit of velocity หน่วยอะตอมของความเร็ว hartree-hertz relationship ความสัมพันธ์ระหว่างฮาร์ทรีà¸�ับเฮิรตซ์ hartree-inverse meter relationship ความสัมพันธ์ระหว่างฮาร์ทรีà¸�ับเมตรผà¸�ผัน hartree-joule relationship ความสัมพันธ์ระหว่างฮาร์ทรีà¸�ับจูล hartree-kelvin relationship ความสัมพันธ์ระหว่างฮาร์ทรีà¸�ับเคลวิน hartree-kilogram relationship ความสัมพันธ์ระหว่างฮาร์ทรีà¸�ับà¸�ิโลà¸�รัม shielding difference of d and p in HD ความà¹�ตà¸�ต่างà¸�ารà¸�ำบังของ d à¹�ละ p ใน HD shielding difference of t and p in HT ความà¹�ตà¸�ต่างà¸�ารà¸�ำบังของ t à¹�ละ p ใน HT pi (Ï€) พาย (Ï€) Euler's number (e) จำนวนออยเลอร์ (e) golden ratio (φ) อัตราส่วนทองคำ (φ) Euler-Mascheroni constant (γ) ค่าคงที่ออยเลอร์-มาสเคโรนี (γ) nominal solar radius รัศมีดวงอาทิตย์เชิงนาม nominal solar total irradiance ความฉายรังสีรวมของดวงอาทิตย์เชิงนาม nominal solar luminosity à¸�ำลังส่องสว่างของดวงอาทิตย์เชิงนาม nominal solar effective temperature อุณหภูมิประสิทธิผลของดวงอาทิตย์เชิงนาม nominal solar mass parameter พารามิเตอร์มวลดวงอาทิตย์เชิงนาม nominal terrestrial equatorial radius รัศมีเส้นศูนย์สูตรของโลà¸�เชิงนาม nominal terrestrial polar radius รัศมีขั้วโลà¸�เชิงนาม nominal terrestrial mass parameter พารามิเตอร์มวลโลà¸�เชิงนาม nominal jovian equatorial radius รัศมีเส้นศูนย์สูตรของดาวพฤหัสบดีเชิงนาม nominal jovian polar radius รัศมีขั้วของดาวพฤหัสบดีเชิงนาม nominal jovian mass parameter พารามิเตอร์มวลดาวพฤหัสบดีเชิงนาม average value of one minus the rate of TCG relative to TCB ค่าเฉลี่ยของหนึ่งลบด้วยอัตราของ TCG เทียบà¸�ับ TCB solar mass parameter (TCB-compatible) พารามิเตอร์มวลดวงอาทิตย์ (เข้าà¸�ันได้à¸�ับ TCB) solar mass parameter (TDB-compatible) พารามิเตอร์มวลดวงอาทิตย์ (เข้าà¸�ันได้à¸�ับ TDB) equatorial radius of the Earth (TT-compatible) รัศมีเส้นศูนย์สูตรของโลà¸� (เข้าà¸�ันได้à¸�ับ TT) dynamical form factor of the Earth à¹�ฟà¸�เตอร์รูปทรงเชิงพลวัตของโลà¸� time rate of change in the dynamical form factor of the Earth อัตราà¸�ารเปลี่ยนà¹�ปลงตามเวลาของà¹�ฟà¸�เตอร์รูปทรงเชิงพลวัตของโลà¸� geocentric gravitational constant (TCB-compatible) ค่าคงที่ความโน้มถ่วงศูนย์à¸�ลางโลà¸� (เข้าà¸�ันได้à¸�ับ TCB) geocentric gravitational constant (TT-compatible) ค่าคงที่ความโน้มถ่วงศูนย์à¸�ลางโลà¸� (เข้าà¸�ันได้à¸�ับ TT) geocentric gravitational constant (TDB-compatible) ค่าคงที่ความโน้มถ่วงศูนย์à¸�ลางโลà¸� (เข้าà¸�ันได้à¸�ับ TDB) potential of the geoid ศัà¸�ย์ของจีออยด์ nominal mean angular velocity of the Earth (TT-compatible) ความเร็วเชิงมุมเฉลี่ยของโลà¸�เชิงนาม (เข้าà¸�ันได้à¸�ับ TT) ratio mass of the Moon to the Earth อัตราส่วนมวลดวงจันทร์ต่อโลà¸� ratio of the mass of the Sun to Mercury อัตราส่วนมวลดวงอาทิตย์ต่อดาวพุธ ratio of the mass of the Sun to Venus อัตราส่วนมวลดวงอาทิตย์ต่อดาวศุà¸�ร์ ratio of the mass of the Sun to Mars อัตราส่วนมวลดวงอาทิตย์ต่อดาวอังคาร ratio of the mass of the Sun to Jupiter อัตราส่วนมวลดวงอาทิตย์ต่อดาวพฤหัสบดี ratio of the mass of the Sun to Saturn อัตราส่วนมวลดวงอาทิตย์ต่อดาวเสาร์ ratio of the mass of the Sun to Uranus อัตราส่วนมวลดวงอาทิตย์ต่อดาวยูเรนัส ratio of the mass of the Sun to Neptune อัตราส่วนมวลดวงอาทิตย์ต่อดาวเนปจูน ratio of the mass of the Sun to (134340) Pluto อัตราส่วนมวลดวงอาทิตย์ต่อ (134340) พลูโต ratio of the mass of the Sun to (136199) Eris อัตราส่วนมวลดวงอาทิตย์ต่อ (136199) อีริส ratio of the mass of (1) Ceres to the Sun อัตราส่วนมวลของ (1) ซีรีสต่อดวงอาทิตย์ ratio of the mass of (2) Pallas to the Sun อัตราส่วนมวลของ (2) พัลลัสต่อดวงอาทิตย์ ratio of the mass of (4) Vesta to the Sun อัตราส่วนมวลของ (4) เวสตาต่อดวงอาทิตย์ mean obliquity of the ecliptic at J2000.0 ความเอียงเฉลี่ยของสุริยวิถีที่ J2000.0 Electromagnetic à¹�ม่เหล็à¸�ไฟฟ้า Compton wavelength ความยาวคลื่นคอมป์ตัน Astronomy ดาราศาสตร์ ConstantsWidget Domain โดเมน Subdomain โดเมนย่อย Search ค้นหา No match found ไม่พบรายà¸�ารที่ตรงà¸�ัน Name ชื่อ Value ค่า Unit หน่วย All ทั้งหมด CustomKeypadDialog Custom Keypad à¹�ป้นà¸�ดà¸�ำหนดเอง Rows: à¹�ถว: Columns: คอลัมน์: Copy preset: คัดลอà¸�ค่าตั้งล่วงหน้า: Basic พื้นà¸�าน Scientific (wide) วิทยาศาสตร์ (à¸�ว้าง) Scientific (narrow) วิทยาศาสตร์ (à¹�คบ) Apply ใช้ Row à¹�ถว Column คอลัมน์ Label ป้ายà¸�ำà¸�ับ Behavior พฤติà¸�รรม Text ข้อความ DiagnosticsDialog App Diagnostics à¸�ารวินิจฉัยà¹�อป Copy to Clipboard คัดลอà¸�ไปยังคลิปบอร์ด Editor Unit หน่วย User unit หน่วยผู้ใช้ User function ฟังà¸�์ชันผู้ใช้ Argument อาร์à¸�ิวเมนต์ Current result:<br/>%1 ผลลัพธ์ปัจจุบัน:<br/>%1 Selection result:<br/>%1 ผลลัพธ์ที่เลือà¸�:<br/>%1 Selection result: n/a ผลลัพธ์ที่เลือà¸�: ไม่มี Selection result: %1 ผลลัพธ์ที่เลือà¸�: %1 second วินาที metre เมตร kilogram à¸�ิโลà¸�รัม mole โมล radian เรเดียน steradian สเตอเรเดียน degree Celsius องศาเซลเซียส cubic metre ลูà¸�บาศà¸�์เมตร cubic millimetre ลูà¸�บาศà¸�์มิลลิเมตร cubic centimetre ลูà¸�บาศà¸�์เซนติเมตร cubic decimetre ลูà¸�บาศà¸�์เดซิเมตร cubic kilometre ลูà¸�บาศà¸�์à¸�ิโลเมตร square millimetre ตารางมิลลิเมตร square kilometre ตารางà¸�ิโลเมตร square metre ตารางเมตร minute นาที hour ชั่วโมง day วัน astronomical unit หน่วยดาราศาสตร์ degree องศา arcminute ลิปดา arcsecond ฟิลิปดา milliarcsecond มิลลิฟิลิปดา microarcsecond ไมโครฟิลิปดา hectare เฮà¸�ตาร์ litre ลิตร tonne ตันเมตริà¸� Dalton ดาลตัน electronvolt อิเล็à¸�ตรอนโวลต์ Angstrom อังสตรอม atmosphere บรรยาà¸�าศ atomic mass unit หน่วยมวลอะตอม British thermal unit หน่วยความร้อนบริติช calorie à¹�คลอรี carat à¸�ะรัต cup ถ้วย cup (Imperial) ถ้วย (อิมพีเรียล) cup (Japanese) ถ้วย (à¸�ี่ปุ่น) cup (US) ถ้วย (สหรัà¸�ฯ) degree Fahrenheit องศาฟาเรนไฮต์ fathom ฟาทอม fluid ounce (Imperial) ฟลูอิดออนซ์ (อิมพีเรียล) fluid ounce (US) ฟลูอิดออนซ์ (สหรัà¸�ฯ) fluid dram (Imperial) ฟลูอิดà¹�ดรม (อิมพีเรียล) fluid dram (US) ฟลูอิดà¹�ดรม (สหรัà¸�ฯ) foot ฟุต square foot ตารางฟุต cubic foot ลูà¸�บาศà¸�์ฟุต gallon (Imperial) à¹�à¸�ลลอน (อิมพีเรียล) gallon (US) à¹�à¸�ลลอน (สหรัà¸�ฯ) gill (Imperial) à¸�ิลล์ (อิมพีเรียล) gill (US) à¸�ิลล์ (สหรัà¸�ฯ) gradian เà¸�รเดียน grain เà¸�รน gram à¸�รัม Hartley ฮาร์ตลีย์ Hartree energy unit หน่วยพลังงานฮาร์ทรี horsepower à¹�รงม้า inch นิ้ว square inch ตารางนิ้ว cubic inch ลูà¸�บาศà¸�์นิ้ว karat à¸�ะรัตทอง knot นอต lightminute นาทีà¹�สง lightsecond วินาทีà¹�สง lightyear ปีà¹�สง long ton ลองตัน mile ไมล์ square mile ตารางไมล์ cubic mile ลูà¸�บาศà¸�์ไมล์ mile per hour ไมล์ต่อชั่วโมง kilometre per hour à¸�ิโลเมตรต่อชั่วโมง nautical mile ไมล์ทะเล ounce ออนซ์ parsec พาร์เซà¸� pint (Imperial) ไพนต์ (อิมพีเรียล) pint (US) ไพนต์ (สหรัà¸�ฯ) pound ปอนด์ pounds per square inch ปอนด์ต่อตารางนิ้ว quart (Imperial) ควอร์ต (อิมพีเรียล) quart (US) ควอร์ต (สหรัà¸�ฯ) oil barrel บาร์เรลน้ำมัน beer barrel (US) บาร์เรลเบียร์ (สหรัà¸�ฯ) square yard ตารางหลา cubic yard ลูà¸�บาศà¸�์หลา short ton ชอร์ตตัน tablespoon ช้อนโต๊ะ tablespoon (Australian) ช้อนโต๊ะ (ออสเตรเลีย) tablespoon (Imperial) ช้อนโต๊ะ (อิมพีเรียล) tablespoon (US) ช้อนโต๊ะ (สหรัà¸�ฯ) dessert spoon ช้อนของหวาน teaspoon ช้อนชา teaspoon (Imperial) ช้อนชา (อิมพีเรียล) teaspoon (US) ช้อนชา (สหรัà¸�ฯ) turn รอบ revolution รอบหมุน revolution per minute รอบต่อนาที week สัปดาห์ kilowatt hour à¸�ิโลวัตต์ชั่วโมง millimetre of mercury มิลลิเมตรปรอท yard หลา Julian century ศตวรรษจูเลียน Julian year ปีจูเลียน sidereal year ปีดาราคติ tropical year ปีสุริยคติ Evaluator cannot operate on a NaN ไม่สามารถดำเนินà¸�ารà¸�ับ NaN ได้ underflow - tiny result is out of SpeedCrunch's number range อันเดอร์โฟลว์ - ผลลัพธ์ที่เล็à¸�มาà¸�อยู่นอà¸�ช่วงตัวเลขของ SpeedCrunch overflow - huge result is out of SpeedCrunch's number range โอเวอร์โฟลว์ - ผลลัพธ์ที่ใหà¸�่มาà¸�อยู่นอà¸�ช่วงตัวเลขของ SpeedCrunch division by zero หารด้วยศูนย์ overflow - logic result exceeds maximum of 256 bits โอเวอร์โฟลว์ - ผลลัพธ์เชิงตรรà¸�ะเà¸�ินค่าสูงสุด 256 บิต overflow - integer result exceeds maximum limit for integers โอเวอร์โฟลว์ - ผลลัพธ์จำนวนเต็มเà¸�ินขีดจำà¸�ัดสูงสุดสำหรับจำนวนเต็ม too time consuming - computation was rejected ใช้เวลามาà¸�เà¸�ินไป - à¸�ารคำนวณถูà¸�ปà¸�ิเสธ dimension mismatch - quantities with different dimensions cannot be compared, added, etc. มิติไม่ตรงà¸�ัน - ปริมาณที่มีมิติต่างà¸�ันไม่สามารถเปรียบเทียบ บวà¸� ฯลฯ ได้ invalid dimension - operation might require dimensionless arguments มิติไม่ถูà¸�ต้อง - à¸�ารดำเนินà¸�ารนี้อาจต้องใช้อาร์à¸�ิวเมนต์ไร้มิติ operation is not defined for these arguments ไม่ได้à¸�ำหนดà¸�ารดำเนินà¸�ารสำหรับอาร์à¸�ิวเมนต์เหล่านี้ Computation aborted - encountered numerical instability à¸�ารคำนวณถูà¸�ยà¸�เลิà¸� - พบความไม่เสถียรเชิงตัวเลข wrong number of arguments จำนวนอาร์à¸�ิวเมนต์ไม่ถูà¸�ต้อง does not take NaN as an argument ไม่รองรับ NaN เป็นอาร์à¸�ิวเมนต์ result out of range ผลลัพธ์อยู่นอà¸�ช่วง undefined for argument domain ไม่à¸�ำหนดสำหรับโดเมนของอาร์à¸�ิวเมนต์ computation too expensive à¸�ารคำนวณมีค่าใช้จ่ายสูงเà¸�ินไป invalid dimension - function might require dimensionless arguments มิติไม่ถูà¸�ต้อง - ฟังà¸�์ชันนี้อาจต้องใช้อาร์à¸�ิวเมนต์ไร้มิติ internal error, please report a bug ข้อผิดพลาดภายใน โปรดรายงานบั๊à¸� error ข้อผิดพลาด invalid expression นิพจน์ไม่ถูà¸�ต้อง syntax error ไวยาà¸�รณ์ผิดพลาด conversion target must be a unit เป้าหมายà¸�ารà¹�ปลงต้องเป็นหน่วย unit must not be zero หน่วยต้องไม่เป็นศูนย์ Conversion failed - dimension mismatch à¸�ารà¹�ปลงล้มเหลว - มิติไม่ตรงà¸�ัน unknown function or variable ฟังà¸�์ชันหรือตัวà¹�ปรไม่รู้จัà¸� unknown unit ไม่รู้จัà¸�หน่วย recursion not supported ไม่รองรับà¸�ารเรียà¸�ซ้ำ %1 is a reserved name, please choose another %1 เป็นชื่อที่สงวนไว้ โปรดเลือà¸�ชื่ออื่น %1 is a global user definition and cannot be overridden in this session. %1 เป็นนิยามผู้ใช้ส่วนà¸�ลางà¹�ละไม่สามารถà¹�ทนที่ในเซสชันนี้ %1 is a variable name, please choose another or delete the variable %1 เป็นชื่อตัวà¹�ปร โปรดเลือà¸�ชื่ออื่นหรือลบตัวà¹�ปรนี้ argument %1 is used more than once อาร์à¸�ิวเมนต์ %1 ถูà¸�ใช้มาà¸�à¸�ว่าหนึ่งครั้ง %1 is a built-in unit name, please choose another %1 เป็นชื่อหน่วยในตัว โปรดเลือà¸�ชื่ออื่น %1 is a user function name, please choose another or delete the function %1 เป็นชื่อฟังà¸�์ชันผู้ใช้ โปรดเลือà¸�ชื่ออื่นหรือลบฟังà¸�์ชันนี้ FunctionRepo max; trials; probability สูงสุด; ครั้งทดลอง; ความน่าจะเป็น trials; probability ครั้งทดลอง; ความน่าจะเป็น hits; trials; probability จำนวนครั้งสำเร็จ; ครั้งทดลอง; ความน่าจะเป็น unix_timestamp; x hours offset to GMT unix_timestamp; ค่าชดเชยจาà¸� GMT x ชั่วโมง max; total; hits; trials สูงสุด; ทั้งหมด; จำนวนครั้งสำเร็จ; ครั้งทดลอง total; hits; trials ทั้งหมด; จำนวนครั้งสำเร็จ; ครั้งทดลอง count; total; hits; trials จำนวน; ทั้งหมด; จำนวนครั้งสำเร็จ; ครั้งทดลอง dividend; divisor ตัวตั้ง; ตัวหาร x; exponent_bits; significand_bits [; exponent_bias] x; บิตเลขชี้à¸�ำลัง; บิตซิà¸�นิฟิà¹�คนด์ [; ไบอัสเลขชี้à¸�ำลัง] base; x à¸�าน; x value; modulo ค่า; โมดูโล base; exponent; modulo à¸�าน; เลขชี้à¸�ำลัง; โมดูโล events; average_events เหตุà¸�ารณ์; เหตุà¸�ารณ์เฉลี่ย average_events เหตุà¸�ารณ์เฉลี่ย x [; precision] x [; ความà¹�ม่นยำ] Absolute Value ค่าสัมบูรณ์ Absolute Deviation ส่วนเบี่ยงเบนสัมบูรณ์ Arc Cosine อาร์à¸�โคไซน์ Logical AND ตรรà¸�ะ AND Area Hyperbolic Cosine ไฮเพอร์โบลิà¸�โคไซน์ผà¸�ผัน Area Hyperbolic Sine ไฮเพอร์โบลิà¸�ไซน์ผà¸�ผัน Area Hyperbolic Tangent ไฮเพอร์โบลิà¸�à¹�ทนเจนต์ผà¸�ผัน Arc Sine อาร์à¸�ไซน์ Arc Tangent อาร์à¸�à¹�ทนเจนต์ Arc Tangent with two Arguments อาร์à¸�à¹�ทนเจนต์à¹�บบสองอาร์à¸�ิวเมนต์ Average (Arithmetic Mean) ค่าเฉลี่ย (ค่าเฉลี่ยเลขคณิต) Convert to Binary Representation à¹�ปลงเป็นà¸�ารà¹�ทนค่าà¹�บบà¸�านสอง Binomial Cumulative Distribution Function ฟังà¸�์ชันà¸�ารà¹�จà¸�à¹�จงสะสมà¹�บบทวินาม Binomial Distribution Mean ค่าเฉลี่ยของà¸�ารà¹�จà¸�à¹�จงà¹�บบทวินาม Binomial Probability Mass Function ฟังà¸�์ชันมวลความน่าจะเป็นà¹�บบทวินาม Binomial Distribution Variance ความà¹�ปรปรวนของà¸�ารà¹�จà¸�à¹�จงà¹�บบทวินาม Cube Root ราà¸�ที่สาม Complex Conjugate คอนจูเà¸�ตเชิงซ้อน Cosine โคไซน์ Hyperbolic Cosine ไฮเพอร์โบลิà¸�โคไซน์ Cotangent โคà¹�ทนเจนต์ Cosecant โคซีà¹�คนต์ Convert Unix timestamp to Date à¹�ปลงเวลา Unix เป็นวันที่ Convert to Decimal Representation à¹�ปลงเป็นà¸�ารà¹�ทนค่าà¹�บบà¸�านสิบ Degrees of Arc องศาของส่วนโค้ง Error Function ฟังà¸�์ชันเออร์เรอร์ Complementary Error Function ฟังà¸�์ชันเออร์เรอร์เชิงเสริม Exponential เลขยà¸�à¸�ำลัง Arithmetic เลขคณิต Chemistry เคมี Complex จำนวนเชิงซ้อน Combinatorics คณิตศาสตร์เชิงจัดหมู่ Probability ความน่าจะเป็น Statistics สถิติ Aggregation à¸�ารรวมค่า Random สุ่ม Base conversion à¸�ารà¹�ปลงà¸�าน Number formatting à¸�ารจัดรูปà¹�บบตัวเลข Integer arithmetic เลขคณิตจำนวนเต็ม Special functions ฟังà¸�์ชันพิเศษ Exponential & Logarithmic เอ็à¸�ซ์โพเนนเชียลà¹�ละลอà¸�าริทึม Angle conversion à¸�ารà¹�ปลงมุม Trigonometry ตรีโà¸�ณมิติ Bitwise ระดับบิต Floating point ทศนิยมลอยตัว Date & Time วันที่à¹�ละเวลา Linear algebra พีชคณิตเชิงเส้น yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; x ชั่วโมงชดเชยจาà¸� GMT [digits] [หลัà¸�] max [; min] สูงสุด [; ต่ำสุด] List Literal ลิเทอรัลรายà¸�าร Convert to Padded Binary Representation à¹�ปลงเป็นรูปà¹�บบà¸�านสองเติมศูนย์ Round Toward +∞ (Ceiling) ปัดเศษไปทาง +∞ (เพดาน) Cosine plus Imaginary Sine โคไซน์บวà¸�ไซน์จินตภาพ Convert to Cis Complex Form à¹�ปลงเป็นรูปà¹�บบเชิงซ้อน cis Matrix Column Count จำนวนคอลัมน์ของเมทริà¸�ซ์ Population Correlation Matrix (n) เมทริà¸�ซ์สหสัมพันธ์ประชาà¸�ร (n) Sample Correlation Matrix (n-1) เมทริà¸�ซ์สหสัมพันธ์ตัวอย่าง (n-1) Count นับ Population Covariance Matrix (n) เมทริà¸�ซ์ความà¹�ปรปรวนร่วมประชาà¸�ร (n) Sample Covariance Matrix (n-1) เมทริà¸�ซ์ความà¹�ปรปรวนร่วมตัวอย่าง (n-1) Cross Product ผลคูณเวà¸�เตอร์ Convert Date to Unix timestamp à¹�ปลงวันที่เป็นเวลาประทับ Unix Determinant ดีเทอร์มิà¹�นนต์ Convert to Sexagesimal Notation à¹�ปลงเป็นสัà¸�à¸�รณ์à¸�านหà¸�สิบ Dot Product ผลคูณจุด Convert to Engineering Notation à¹�ปลงเป็นสัà¸�à¸�รณ์วิศวà¸�รรม Convert to Exponential Complex Form à¹�ปลงเป็นรูปà¹�บบเชิงซ้อนเอ็à¸�ซ์โพเนนเชียล Round Toward −∞ (Floor) ปัดเศษไปทาง −∞ (พื้น) Flatten Matrix ทำเมทริà¸�ซ์ให้à¹�บน Fractional Part ส่วนเศษ Extension of Factorials [= (x-1)!] ส่วนขยายของà¹�ฟà¸�ทอเรียล [= (x-1)!] Greatest Common Divisor ตัวหารร่วมมาà¸� Least Common Multiple ตัวคูณร่วมน้อย Geometric Mean ค่าเฉลี่ยเรขาคณิต Gradians of arc เà¸�รเดียนของส่วนโค้ง Convert to Hexadecimal Representation à¹�ปลงเป็นà¸�ารà¹�ทนค่าà¹�บบà¸�านสิบหà¸� Convert to Padded Hexadecimal Representation à¹�ปลงเป็นรูปà¹�บบà¸�านสิบหà¸�เติมศูนย์ Hypergeometric Cumulative Distribution Function ฟังà¸�์ชันà¸�ารà¹�จà¸�à¹�จงสะสมà¹�บบไฮเพอร์จีโอเมตริà¸� Hypergeometric Distribution Mean ค่าเฉลี่ยของà¸�ารà¹�จà¸�à¹�จงà¹�บบไฮเพอร์จีโอเมตริà¸� Hypergeometric Probability Mass Function ฟังà¸�์ชันมวลความน่าจะเป็นà¹�บบไฮเพอร์จีโอเมตริà¸� Hypergeometric Distribution Variance ความà¹�ปรปรวนของà¸�ารà¹�จà¸�à¹�จงà¹�บบไฮเพอร์จีโอเมตริà¸� Integer Quotient ผลหารจำนวนเต็ม Integer Part ส่วนจำนวนเต็ม Imaginary Part ส่วนจินตภาพ Inverse Matrix เมทริà¸�ซ์ผà¸�ผัน Decode IEEE-754 Binary Value ถอดรหัสค่าไบนารี IEEE-754 Encode IEEE-754 Binary Value เข้ารหัสค่าไบนารี IEEE-754 Decode 16-bit Half-Precision Value ถอดรหัสค่า Half-Precision 16 บิต Encode 16-bit Half-Precision Value เข้ารหัสค่า Half-Precision 16 บิต Decode 32-bit Single-Precision Value ถอดรหัสค่า Single-Precision 32 บิต Encode 32-bit Single-Precision Value เข้ารหัสค่า Single-Precision 32 บิต Decode 64-bit Double-Precision Value ถอดรหัสค่า Double-Precision 64 บิต Encode 64-bit Double-Precision Value เข้ารหัสค่า Double-Precision 64 บิต Decode 128-bit Quad-Precision Value ถอดรหัสค่า Quad-Precision 128 บิต Encode 128-bit Quad-Precision Value เข้ารหัสค่า Quad-Precision 128 บิต Round to 16-bit Half-Precision Value ปัดเป็นค่าความละเอียดครึ่ง 16 บิต Round to 32-bit Single-Precision Value ปัดเป็นค่าความละเอียดเดี่ยว 32 บิต Round to 64-bit Double-Precision Value ปัดเป็นค่าความละเอียดคู่ 64 บิต Round to 128-bit Quad-Precision Value ปัดเป็นค่าความละเอียดจตุร 128 บิต Residual from 16-bit Half-Precision Rounding เศษเหลือจาà¸�à¸�ารปัดความละเอียดครึ่ง 16 บิต Residual from 32-bit Single-Precision Rounding เศษเหลือจาà¸�à¸�ารปัดความละเอียดเดี่ยว 32 บิต Residual from 64-bit Double-Precision Rounding เศษเหลือจาà¸�à¸�ารปัดความละเอียดคู่ 64 บิต Residual from 128-bit Quad-Precision Rounding เศษเหลือจาà¸�à¸�ารปัดความละเอียดจตุร 128 บิต Binary Logarithm ลอà¸�าริทึมà¸�านสอง Common Logarithm ลอà¸�าริทึมสามัà¸� Natural Logarithm ลอà¸�าริทึมธรรมชาติ Substance Mass มวลสาร Molarity โมลาริตี Molar Mass มวลโมลาร์ Logarithm to Arbitrary Base ลอà¸�าริทึมà¸�านใดๆ Median Absolute Deviation มัธยà¸�านของค่าเบี่ยงเบนสัมบูรณ์ Mask to a bit size มาสà¸�์ตามขนาดบิต Maximum ค่าสูงสุด Median Value (50th Percentile) ค่ามัธยà¸�าน (เปอร์เซ็นไทล์ที่ 50) Mean ค่าเฉลี่ย Minimum ค่าต่ำสุด Numerical Value of Quantity ค่าตัวเลขของปริมาณ Random Decimal Number เลขทศนิยมสุ่ม Random Integer Number เลขจำนวนเต็มสุ่ม Convert to Rational Representation à¹�ปลงเป็นรูปà¹�บบจำนวนตรรà¸�ยะ Modulo โมดูโล Euclidean Modulo โมดูโลà¹�บบยูคลิด Modular Exponentiation à¸�ารยà¸�à¸�ำลังà¹�บบโมดูลาร์ Combination (Binomial Coefficient) คอมบิเนชัน (สัมประสิทธิ์ทวินาม) Logical NOT ตรรà¸�ะ NOT Permutation (Arrangement) เพอร์มิวเทชัน (à¸�ารจัดเรียง) Convert to Octal Representation à¹�ปลงเป็นà¸�ารà¹�ทนค่าà¹�บบà¸�านà¹�ปด Convert to Padded Octal Representation à¹�ปลงเป็นรูปà¹�บบà¸�านà¹�ปดเติมศูนย์ Vector or Matrix Norm นอร์มของเวà¸�เตอร์หรือเมทริà¸�ซ์ Logical OR ตรรà¸�ะ OR Population Count (Hamming Weight) จำนวนบิตที่เป็นหนึ่ง (น้ำหนัà¸�à¹�ฮมมิง) Phase of Complex Number เฟสของจำนวนเชิงซ้อน Poissonian Cumulative Distribution Function ฟังà¸�์ชันà¸�ารà¹�จà¸�à¹�จงสะสมà¹�บบปัวซอง Poissonian Distribution Mean ค่าเฉลี่ยของà¸�ารà¹�จà¸�à¹�จงà¹�บบปัวซอง Poissonian Probability Mass Function ฟังà¸�์ชันมวลความน่าจะเป็นà¹�บบปัวซอง Poissonian Distribution Variance ความà¹�ปรปรวนของà¸�ารà¹�จà¸�à¹�จงà¹�บบปัวซอง Convert to Phasor Complex Form à¹�ปลงเป็นรูปà¹�บบเชิงซ้อนเฟสเซอร์ Convert to Rectangular Complex Form à¹�ปลงเป็นรูปà¹�บบเชิงซ้อนสี่เหลี่ยม Round Half Away from Zero ปัดครึ่งออà¸�จาà¸�ศูนย์ Round Half Even ปัดครึ่งไปเลขคู่ Nth Root ราà¸�ที่ n Convert to Scientific Notation à¹�ปลงเป็นสัà¸�à¸�รณ์วิทยาศาสตร์ Matrix Row Count จำนวนà¹�ถวของเมทริà¸�ซ์ List or Matrix Shape รูปร่างของรายà¸�ารหรือเมทริà¸�ซ์ Summation ผลรวม Population Standard Deviation (n) ส่วนเบี่ยงเบนมาตรà¸�านประชาà¸�ร (n) Sample Standard Deviation (n-1) ส่วนเบี่ยงเบนมาตรà¸�านตัวอย่าง (n-1) Round Toward Zero (Truncation) ปัดเข้าหาศูนย์ (ตัดทอน) Matrix Trace เทรซของเมทริà¸�ซ์ Transpose Matrix เมทริà¸�ซ์ทรานสโพส Population Variance (n) ความà¹�ปรปรวนประชาà¸�ร (n) Sample Variance (n-1) ความà¹�ปรปรวนตัวอย่าง (n-1) Product ผลคูณ Radians เรเดียน Matrix Rank อันดับเมทริà¸�ซ์ Real Part ส่วนจริง Secant ซีà¹�คนต์ Arithmetic Shift Left เลื่อนซ้ายเชิงเลขคณิต Arithmetic Shift Right เลื่อนขวาเชิงเลขคณิต Signum ซิà¸�นัม Sine ไซน์ Hyperbolic Sine ไฮเพอร์โบลิà¸�ไซน์ Square Root ราà¸�ที่สอง Sum ผลรวม Tangent à¹�ทนเจนต์ Convert to Trigonometric Complex Form à¹�ปลงเป็นรูปà¹�บบเชิงซ้อนตรีโà¸�ณมิติ Turns รอบ Hyperbolic Tangent ไฮเพอร์โบลิà¸�à¹�ทนเจนต์ Sign-extend a value ขยายบิตเครื่องหมายของค่า Logical XOR ตรรà¸�ะ XOR FunctionsWidget Domain โดเมน All ทั้งหมด Identifier ตัวระบุ Name ชื่อ Search ค้นหา No match found ไม่พบรายà¸�ารที่ตรงà¸�ัน HistoryWidget Remove All Calculations Above ลบà¸�ารคำนวณทั้งหมดด้านบน Remove This Calculation ลบà¸�ารคำนวณนี้ Remove All Calculations Below ลบà¸�ารคำนวณทั้งหมดด้านล่าง Keypad Inverse cosine โคไซน์ผà¸�ผัน The last result ผลลัพธ์ล่าสุด Inverse sine ไซน์ผà¸�ผัน Inverse tangent à¹�ทนเจนต์ผà¸�ผัน Evaluate expression ประเมินนิพจน์ Division à¸�ารหาร Multiplication à¸�ารคูณ Subtraction à¸�ารลบ Addition à¸�ารบวà¸� Clear expression ล้างนิพจน์ Cosine โคไซน์ Backspace ลบถอยหลัง Scientific notation รูปà¹�บบสัà¸�à¸�รณ์วิทยาศาสตร์ Exponential เลขยà¸�à¸�ำลัง Factorial à¹�ฟà¸�ทอเรียล Natural logarithm ลอà¸�าริทึมธรรมชาติ Left parenthesis วงเล็บซ้าย Nth root ราà¸�ที่ n Argument separator ตัวคั่นอาร์à¸�ิวเมนต์ Square ยà¸�à¸�ำลังสอง Common logarithm ลอà¸�าริทึมสามัà¸� Modulo โมดูโล Contextual percentage เปอร์เซ็นต์ตามบริบท Power ยà¸�à¸�ำลัง Right parenthesis วงเล็บขวา Sine ไซน์ Square root ราà¸�ที่สอง Tangent à¹�ทนเจนต์ Pi พาย Decimal separator ตัวคั่นทศนิยม MainWindow Radian เรเดียน Gradian เà¸�รเดียน Degree องศา Binary à¸�านสอง Octal à¸�านà¹�ปด Hexadecimal à¸�านสิบหà¸� Sexagesimal à¸�านหà¸�สิบ Engineering decimal ทศนิยมà¹�บบวิศวà¸�รรม Scientific decimal ทศนิยมà¹�บบวิทยาศาสตร์ Plain &text ข้อความ&ธรรมดา &Import... &นำเข้า... &Quit &ออà¸� Clear E&xpression ล้าง&นิพจน์ Clear &History ล้าง&ประวัติ &Copy &คัดลอà¸� &Paste &วาง &Select Expression &เลือà¸�นิพจน์ &Constants &ค่าคงที่ &Functions &ฟังà¸�์ชัน &History &ประวัติ &Keypad &à¹�ป้นพิมพ์ตัวเลข Formula &Book หนังสือ&สูตร New &Private Tab à¹�&ท็บส่วนตัวใหม่ Keep เà¸�็บไว้ Make Private... ทำให้เป็นส่วนตัว... &Rename... เ&ปลี่ยนชื่อ... Clo&ne... โ&คลน... &Close Tab ปิ&ดà¹�ท็บ Reopen Clo&sed Tab เปิดà¹�ท็&บที่ปิดไปอีà¸�ครั้ง &Undo เ&ลิà¸�ทำ &Redo &ทำซ้ำ Cu&t &ตัด Copy &Last Result คั&ดลอà¸�ผลลัพธ์ล่าสุด &Wrap in Parentheses ค&รอบด้วยวงเล็บ Full Scr&een Mode &โหมดเต็มหน้าจอ &Status Bar à¹�ถบ&สถานะ Bitfield บิตฟิลด์ &Left &ซ้าย &Right &ขวา &Up ขึ้&น &Down &ลง Close Pa&ne ปิ&ดบานหน้าต่าง Use&r Functions ฟังà¸�์ชัน&ผู้ใช้ &Degree &องศา &Radian &เรเดียน &Gradian &เà¸�รเดียน Re&volution รอ&บหมุน Always on &Top อยู่&บนสุดเสมอ Auto-Insert a&ns à¹�ทรà¸� a&ns อัตโนมัติ Automatic &Completion เติม&ข้อความอัตโนมัติ &Built-in Functions &ฟังà¸�์ชันในตัว Built-in &Variables &ตัวà¹�ปรในตัว User &Functions ฟั&งà¸�์ชันผู้ใช้ User Va&riables ตั&วà¹�ปรผู้ใช้ Open a Private Tab on Startup เปิดà¹�ท็บส่วนตัวเมื่อเริ่มต้น Open and focus a new private tab whenever SpeedCrunch starts. เปิดà¹�ท็บส่วนตัวใหม่à¹�ละย้ายโฟà¸�ัสไปที่à¹�ท็บนั้นทุà¸�ครั้งที่เริ่ม SpeedCrunch Syntax &Highlighting ไฮไลต์&ไวยาà¸�รณ์ Group Digits in &Input &จัดà¸�ลุ่มหลัà¸�ของตัวเลขที่ป้อน Automatic Input &Adjustments &ปรับข้อมูลป้อนเข้าอัตโนมัติ Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. ปรับตัวดำเนินà¸�าร ระยะห่าง วงเล็บ à¹�ละเลขยà¸�à¸�ำลังโดยอัตโนมัติ à¹�ละจำà¸�ัดให้ป้อนได้เฉพาะอัà¸�ขระที่ถูà¸�ต้อง Group input digits using the selected number format. จัดà¸�ลุ่มหลัà¸�ของตัวเลขที่ป้อนตามรูปà¹�บบตัวเลขที่เลือà¸� &Blinking Cursor &เคอร์เซอร์à¸�ะพริบ Blink the cursor in the expression editor. ให้เคอร์เซอร์ในตัวà¹�à¸�้ไขนิพจน์à¸�ะพริบ &Escape Clears Editor &Escape ล้างตัวà¹�à¸�้ไข Clear the focused expression editor with Escape after dismissing any popup or preview. ล้างตัวà¹�à¸�้ไขนิพจน์ที่มีโฟà¸�ัสด้วย Escape หลังจาà¸�ปิดป๊อปอัปหรือภาพตัวอย่างà¹�ล้ว Disabled ปิดใช้งาน Small Space เว้นวรรคเล็à¸� Medium Space เว้นวรรคปานà¸�ลาง Large Space เว้นวรรคใหà¸�่ Keep Expression After Evaluation เà¸�็บนิพจน์หลังคำนวณ Copy New Results Automatically คัดลอà¸�ผลลัพธ์ใหม่อัตโนมัติ &Comma &จุลภาค &System Default ค่าเริ่มต้น&ระบบ &Dot &จุด Dot &And Comma จุดà¹�ละ&จุลภาค &0 Digits &0 หลัà¸� &15 Digits &15 หลัà¸� &2 Digits &2 หลัà¸� &3 Digits &3 หลัà¸� &50 Digits &50 หลัà¸� &8 Digits &8 หลัà¸� Toward +∞ (&ceil) เข้าหา +∞ (&ceil) Toward −∞ (&floor) เข้าหา −∞ (&floor) &Automatic &อัตโนมัติ &Engineering &วิศวà¸�รรม &Scientific &วิทยาศาสตร์ &Binary &à¸�านสอง &Octal &à¸�านà¹�ปด &Hexadecimal &à¸�านสิบหà¸� &Sexagesimal &à¸�านหà¸�สิบ &Font... &à¹�บบอัà¸�ษร... Reset All Settings... รีเซ็ตà¸�ารตั้งค่าทั้งหมด... &System &ระบบ SpeedCrunch &Theme &ชุดรูปà¹�บบ SpeedCrunch &Classic &ดั้งเดิม &Modern &สมัยใหม่ &Language... &ภาษา... User &Manual &คู่มือผู้ใช้ Context Help ความช่วยเหลือตามบริบท Issues and &Feedback &ปัà¸�หาà¹�ละข้อเสนอà¹�นะ &Donate &บริจาค Editor and Results Font à¹�บบอัà¸�ษรของตัวà¹�à¸�้ไขà¹�ละผลลัพธ์ &Session &เซสชัน &Export &ส่งออà¸� &Edit &à¹�à¸�้ไข &View &มุมมอง S&plit à¹�&บ่ง Se&ttings &à¸�ารตั้งค่า &Decimal &ทศนิยม &Precision &ความà¹�ม่นยำ Angle &Mode &โหมดมุม &Complex Form &รูปà¹�บบจำนวนเชิงซ้อน &Help &ช่วยเหลือ New Tab à¹�ท็บใหม่ Constants ค่าคงที่ Functions ฟังà¸�์ชัน History ประวัติ User Functions ฟังà¸�์ชันผู้ใช้ Error ข้อผิดพลาด Can't read from file %1 ไม่สามารถอ่านจาà¸�ไฟล์ %1 Can't write to file %1 ไม่สามารถเขียนลงไฟล์ %1 Import Session นำเข้าเซสชัน Close Session ปิดเซสชัน Angle Mode: โหมดมุม: Notation: สัà¸�à¸�รณ์: Precision: ความละเอียด: Turn รอบ Revolution รอบหมุน Fixed-point decimal ทศนิยมจุดคงที่ Rational ตรรà¸�ยะ Automatic decimal ทศนิยมอัตโนมัติ Automatic อัตโนมัติ User &Definitions... &นิยามผู้ใช้... New &Tab &à¹�ท็บใหม่ New &Window &หน้าต่างใหม่ &Open... &เปิด... Open Sessions &Folder เปิด&โฟลเดอร์เซสชัน &Basic &พื้นà¸�าน &Scientific (wide) &วิทยาศาสตร์ (à¸�ว้าง) Scientific (narrow) วิทยาศาสตร์ (à¹�คบ) &Custom... &à¸�ำหนดเอง... Main &Menu &เมนูหลัà¸� User &Variables &ตัวà¹�ปรผู้ใช้ User &Units &หน่วยผู้ใช้ &Turn &รอบ If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. ถ้านิพจน์ใหม่เริ่มด้วย +, -, *, หรือ / SpeedCrunch จะà¹�ทรà¸� "ans" à¸�่อน &Accept with Enter &ยอมรับด้วย Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. ยอมรับคำà¹�นะนำà¸�ารเติมข้อความอัตโนมัติปัจจุบันด้วย Enter โดยไม่ต้องเลือà¸�ด้วยปุ่มลูà¸�ศรà¸�่อน &Units &หน่วย Show Live Result &Preview à¹�สดง&ตัวอย่างผลลัพธ์สด Save &Window Position on Exit บันทึà¸�ตำà¹�หน่ง&หน้าต่างเมื่อออà¸� Hover Highlighting เน้นเมื่อชี้เมาส์ Group Integer Part Only จัดà¸�ลุ่มเฉพาะส่วนจำนวนเต็ม Number Format... รูปà¹�บบตัวเลข... Notation && Precision... สัà¸�à¸�รณ์à¹�ละความละเอียด... After pressing Enter, keep the entered expression selected in the editor. หลังจาà¸�à¸�ด Enter ให้คงนิพจน์ที่ป้อนไว้โดยเลือà¸�อยู่ในตัวà¹�à¸�้ไข Never ไม่เลย Always เสมอ Only for Single-Line Expressions เฉพาะนิพจน์บรรทัดเดียว Simplify Displayed Expressions ทำให้นิพจน์ที่à¹�สดงง่ายขึ้น History Size &Limit... &ขีดจำà¸�ัดขนาดประวัติ... Remove Trailing &Zeroes &ลบศูนย์ท้ายตัวเลข Nearest, Half &Away (round) ใà¸�ล้สุด ครึ่ง&ออà¸�ห่าง (round) Nearest, Half &Even (roundeven) ใà¸�ล้สุด ครึ่ง&คู่ (roundeven) Toward &Zero (trunc) เข้าหา&ศูนย์ (trunc) &Fixed-Point &จุดคงที่ &Rational &ตรรà¸�ยะ &Exponential (m·sâ�»Â¹) &เอ็à¸�ซ์โพเนนเชียล (m·sâ�»Â¹) &Fractional (m/s) &เศษส่วน (m/s) &Rectangular (a + bi) &สี่เหลี่ยม (a + bi) Exponential (reâ�±á¶¿) เอ็à¸�ซ์โพเนนเชียล (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) ตรีโà¸�ณมิติ (r(cos θ + i·sin θ)) Phasor (r∠θ) เฟสเซอร์ (r∠θ) &Theme... &ธีม... Check for &Updates ตรวจสอบ&อัปเดต Source Code ซอร์สโค้ด &Zoom &ซูม &Results &ผลลัพธ์ Unit Notation สัà¸�à¸�รณ์หน่วย Rounding Mode โหมดà¸�ารปัดเศษ &Notation &สัà¸�à¸�รณ์ &Imaginary Unit &หน่วยจินตภาพ &Window &หน้าต่าง &Editing &à¸�ารà¹�à¸�้ไข A&utocomplete เ&ติมข้อความอัตโนมัติ Up/Down Arrow History ประวัติด้วยลูà¸�ศรขึ้น/ลง &Appearance &รูปลัà¸�ษณ์ &Menus &เมนู &Docks à¹�&ผงที่ยึดติดได้ &Input and Results &ข้อมูลป้อนเข้าà¹�ละผลลัพธ์ &Disabled &ปิดใช้งาน &Disable &ปิดใช้งาน Close preview ปิดตัวอย่าง Rename... เปลี่ยนชื่อ... Clone... โคลน... Close Tab ปิดà¹�ท็บ New Private Tab à¹�ท็บส่วนตัวใหม่ Open... เปิด... Reopen Closed Tab เปิดà¹�ท็บที่ปิดไปอีà¸�ครั้ง Split à¹�บ่ง Left ซ้าย Right ขวา Up ขึ้น Down ลง Clear ล้าง Delete ลบ %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 เซสชันส่วนตัว: เนื้อหาจะถูà¸�ทิ้งเมื่อปิด เลือà¸� เซสชัน > เà¸�็บไว้ เพื่อเปลี่ยนเป็นเซสชันปà¸�ติ SpeedCrunch - %1 [Private] SpeedCrunch - %1 [ส่วนตัว] Reset All Settings รีเซ็ตà¸�ารตั้งค่าทั้งหมด Reset all settings to their default values? รีเซ็ตà¸�ารตั้งค่าทั้งหมดเป็นค่าเริ่มต้นหรือไม่? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. รวมถึงรูปลัà¸�ษณ์ à¸�ารà¹�à¸�้ไข รูปà¹�บบผลลัพธ์ à¹�ละà¸�ารตั้งค่าหน้าต่าง โดยจะเà¸�็บà¸�ารคำนวณ เซสชันที่เปิดอยู่ à¹�ละนิยามของผู้ใช้ไว้ The settings file could not be written. ไม่สามารถเขียนไฟล์à¸�ารตั้งค่าได้ Clear this session's calculations, unfinished expression, variables, functions, and units? ล้างà¸�ารคำนวณ นิพจน์ที่ยังไม่เสร็จ ตัวà¹�ปร ฟังà¸�์ชัน à¹�ละหน่วยของเซสชันนี้หรือไม่? Global user definitions are kept. นิยามส่วนà¸�ลางของผู้ใช้จะถูà¸�เà¸�็บไว้ Make Session Private ทำให้เซสชันเป็นส่วนตัว The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. เซสชันที่บันทึà¸�ไว้ %1 จะถูà¸�ลบ เนื้อหาจะยังคงเปิดอยู่ในเซสชันส่วนตัว à¹�ละจะถูà¸�ทิ้งเมื่อปิดเซสชันนั้นหรือออà¸�จาà¸� SpeedCrunch Make Private ทำให้เป็นส่วนตัว Could not delete the saved session %1. ไม่สามารถลบเซสชันที่บันทึà¸�ไว้ %1 ได้ Keep Session เà¸�็บเซสชันไว้ Could not save the session. It remains private. ไม่สามารถบันทึà¸�เซสชันได้ เซสชันยังคงเป็นส่วนตัว Clone Session โคลนเซสชัน Could not save session file %1. ไม่สามารถบันทึà¸�ไฟล์เซสชัน %1 ได้ Could not delete session file %1. ไม่สามารถลบไฟล์เซสชัน %1 ได้ JSON file (*.json);;Any file (*.*) ไฟล์ JSON (*.json);;ไฟล์ใดà¸�็ได้ (*.*) Export session as JSON ส่งออà¸�เซสชันเป็น JSON The selected file is not valid JSON: %1 ไฟล์ที่เลือà¸�ไม่ใช่ JSON ที่ถูà¸�ต้อง: %1 The selected file is not a SpeedCrunch session JSON file. ไฟล์ที่เลือà¸�ไม่ใช่ไฟล์ JSON ของเซสชัน SpeedCrunch This file uses an obsolete SpeedCrunch session format and cannot be imported. ไฟล์นี้ใช้รูปà¹�บบเซสชัน SpeedCrunch ที่ล้าสมัยà¹�ละไม่สามารถนำเข้าได้ The selected JSON file is missing the required $schema field. ไฟล์ JSON ที่เลือà¸�ไม่มีฟิลด์ $schema ที่จำเป็น The selected JSON file uses an unsupported JSON schema: %1 ไฟล์ JSON ที่เลือà¸�ใช้สคีมา JSON ที่ไม่รองรับ: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). ไฟล์ JSON ที่เลือà¸�ไม่มีตัวระบุสคีมาเซสชัน SpeedCrunch ($id) The selected JSON file uses an unsupported SpeedCrunch session format: %1 ไฟล์ JSON ที่เลือà¸�ใช้รูปà¹�บบเซสชัน SpeedCrunch ที่ไม่รองรับ: %1 The selected JSON file is missing the required session name. ไฟล์ JSON ที่เลือà¸�ไม่มีชื่อเซสชันที่จำเป็น The selected JSON file has an empty session name. ไฟล์ JSON ที่เลือà¸�มีชื่อเซสชันว่าง The selected JSON file has invalid or incomplete SpeedCrunch session data. ไฟล์ JSON ที่เลือà¸�มีข้อมูลเซสชัน SpeedCrunch ที่ไม่ถูà¸�ต้องหรือไม่สมบูรณ์ Open Sessions Folder เปิดโฟลเดอร์เซสชัน Could not create the sessions folder: %1 ไม่สามารถสร้างโฟลเดอร์เซสชันได้: %1 Could not open the sessions folder: %1 ไม่สามารถเปิดโฟลเดอร์เซสชันได้: %1 Open Session เปิดเซสชัน Community ชุมชน Rename Session เปลี่ยนชื่อเซสชัน Clear Session ล้างเซสชัน Delete Session ลบเซสชัน Close Pane ปิดบานหน้าต่าง &About SpeedCrunch &เà¸�ี่ยวà¸�ับ SpeedCrunch App Diag&nostics &à¸�ารวินิจฉัยà¹�อป User Variables ตัวà¹�ปรผู้ใช้ User Units หน่วยผู้ใช้ Clear History ล้างประวัติ Are you sure you want to clear the calculation history? คุณà¹�น่ใจหรือไม่ว่าต้องà¸�ารล้างประวัติà¸�ารคำนวณ? Session name: ชื่อเซสชัน: A session named %1 already exists. มีเซสชันชื่อ %1 อยู่à¹�ล้ว Could not create session file %1. ไม่สามารถสร้างไฟล์เซสชัน %1 Could not write session file %1. ไม่สามารถเขียนไฟล์เซสชัน %1 Are you sure you want to delete this session? คุณà¹�น่ใจหรือไม่ว่าต้องà¸�ารลบเซสชันนี้? Custom Precision ความละเอียดà¸�ำหนดเอง Fractional digits: จำนวนหลัà¸�เศษส่วน: Theme ธีม Light Themes ธีมสว่าง Dark Themes ธีมมืด Preview ตัวอย่าง Colors สี Select color for %1 เลือà¸�สีสำหรับ %1 Import... นำเข้า... Export... ส่งออà¸�... Import Theme นำเข้าธีม Theme file (*.json);;All files (*) ไฟล์ธีม (*.json);;ไฟล์ทั้งหมด (*) Invalid theme file. ไฟล์ธีมไม่ถูà¸�ต้อง Can't import theme "%1" because it conflicts with a built-in theme. ไม่สามารถนำเข้าธีม "%1" เพราะขัดà¹�ย้งà¸�ับธีมในตัว Can't find a writable theme folder. ไม่พบโฟลเดอร์ธีมที่เขียนได้ Overwrite Theme เขียนทับธีม A custom theme named "%1" already exists. Do you want to overwrite it? มีธีมà¸�ำหนดเองชื่อ "%1" อยู่à¹�ล้ว คุณต้องà¸�ารเขียนทับหรือไม่? Can't overwrite theme file %1 ไม่สามารถเขียนทับไฟล์ธีม %1 Can't copy theme file to %1 ไม่สามารถคัดลอà¸�ไฟล์ธีมไปยัง %1 Export Theme ส่งออà¸�ธีม Can't export theme as "%1" because it conflicts with a built-in theme. ไม่สามารถส่งออà¸�ธีมเป็น "%1" เพราะขัดà¹�ย้งà¸�ับธีมในตัว Global User Variable ตัวà¹�ปรผู้ใช้ส่วนà¸�ลาง Global User Function ฟังà¸�์ชันผู้ใช้ส่วนà¸�ลาง Global User Unit หน่วยผู้ใช้ส่วนà¸�ลาง User Definitions นิยามของผู้ใช้ These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. นิยามเหล่านี้เป็นนิยามส่วนà¸�ลางà¹�ละจะถูà¸�โหลดในทุà¸�เซสชัน ไม่สามารถเปลี่ยนà¹�ปลงได้ภายในเซสชัน à¹�ละมีลำดับความสำคัà¸�เหนือนิยามชื่อเดียวà¸�ันจาà¸�ตัวà¹�à¸�้ไขเซสชัน ป้อนหนึ่งนิยามต่อหนึ่งบรรทัด Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] ตัวอย่าง: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply ใช้ Validate ตรวจสอบความถูà¸�ต้อง Test Results ผลà¸�ารทดสอบ Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 ตัวà¹�ปรที่นำเข้า: %1 ฟังà¸�์ชันที่นำเข้า: %2 หน่วยที่นำเข้า: %3 หมายเลขบรรทัดที่มีข้อผิดพลาด: %4 none ไม่มี Apply Results ผลà¸�ารนำไปใช้ User definitions saved. บันทึà¸�นิยามของผู้ใช้à¹�ล้ว History Size Limit ขีดจำà¸�ัดขนาดประวัติ Maximum number of history entries for this session (0 = unlimited): จำนวนรายà¸�ารประวัติสูงสุดสำหรับเซสชันนี้ (0 = ไม่จำà¸�ัด): Export session as HTML ส่งออà¸�เซสชันเป็น HTML HTML file (*.html) ไฟล์ HTML (*.html) Export session as plain text ส่งออà¸�เซสชันเป็นข้อความธรรมดา Text file (*.txt);;Any file (*.*) ไฟล์ข้อความ (*.txt);;ไฟล์ใดๆ (*.*) Could not recalculate from calculation %1: %2 ไม่สามารถคำนวณใหม่จาà¸�à¸�ารคำนวณ %1: %2 History Size Limit Reached ถึงขีดจำà¸�ัดขนาดประวัติà¹�ล้ว This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. à¸�ารคำนวณนี้ใช้ช่องประวัติสุดท้ายที่เหลืออยู่ à¸�ารคำนวณต่อไปจะลบà¸�ารคำนวณที่เà¸�่าที่สุดออà¸�จาà¸�ประวัติ คุณสามารถเพิ่มขีดจำà¸�ัดได้จาà¸� เซสชัน > ขีดจำà¸�ัดขนาดประวัติ Editing calculation. Press Esc twice to cancel. à¸�ำลังà¹�à¸�้ไขà¸�ารคำนวณ à¸�ด Esc สองครั้งเพื่อยà¸�เลิà¸� Calculation Settings à¸�ารตั้งค่าà¸�ารคำนวณ Invalid recalculation start index ดัชนีเริ่มคำนวณใหม่ไม่ถูà¸�ต้อง System Default ค่าเริ่มต้นระบบ Language ภาษา Select the language: เลือà¸�ภาษา: Custom à¸�ำหนดเอง Decimal places: ตำà¹�หน่งทศนิยม: ManualWindow SpeedCrunch Manual คู่มือ SpeedCrunch %1 - SpeedCrunch Manual %1 - คู่มือ SpeedCrunch NumberFormatDialog Number Format รูปà¹�บบตัวเลข <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>เลือà¸�รูปà¹�บบตัวเลขสำหรับผลลัพธ์à¹�ละà¸�ารจัดà¸�ลุ่มหลัà¸�ของตัวเลขที่ป้อน</b><br/><br/>หมายเหตุ: ยอมรับรูปà¹�บบที่ชัดเจนสำหรับตัวเลขที่ป้อน à¹�ม้จะà¹�ตà¸�ต่างจาà¸�รูปà¹�บบà¸�ารà¹�สดงผลที่เลือà¸�ไว้<br/> QObject Global User Variable ตัวà¹�ปรผู้ใช้ส่วนà¸�ลาง Global User Function ฟังà¸�์ชันผู้ใช้ส่วนà¸�ลาง Global User Unit หน่วยผู้ใช้ส่วนà¸�ลาง Backspace ลบถอยหลัง Clear expression ล้างนิพจน์ Evaluate expression ประเมินนิพจน์ Insert text à¹�ทรà¸�ข้อความ Automatic decimal ทศนิยมอัตโนมัติ Fixed-point decimal ทศนิยมจุดคงที่ Engineering decimal ทศนิยมà¹�บบวิศวà¸�รรม Scientific decimal ทศนิยมà¹�บบวิทยาศาสตร์ Rational ตรรà¸�ยะ Binary à¸�านสอง Octal à¸�านà¹�ปด Hexadecimal à¸�านสิบหà¸� Sexagesimal à¸�านหà¸�สิบ Update Available มีอัปเดต A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> มีเวอร์ชันใหม่à¸�ว่า (%1)<br/><a href="%2">ไปที่เว็บไซต์เพื่อดาวน์โหลด</a> Check for Updates ตรวจสอบอัปเดต SpeedCrunch %1 is up to date. SpeedCrunch %1 เป็นเวอร์ชันล่าสุด No connectivity. Please check your internet connection and try again. ไม่มีà¸�ารเชื่อมต่อ โปรดตรวจสอบà¸�ารเชื่อมต่ออินเทอร์เน็ตà¹�ล้วลองอีà¸�ครั้ง Could not verify the latest available version. ไม่สามารถตรวจสอบเวอร์ชันล่าสุดที่มีได้ ResultDisplay Scroll to bottom เลื่อนไปด้านล่าง Edit Expression à¹�à¸�้ไขนิพจน์ Change Settings เปลี่ยนà¸�ารตั้งค่า New Tab à¹�ท็บใหม่ &Import... &นำเข้า... &Export &ส่งออà¸� Plain &text ข้อความ&ธรรมดา Copy คัดลอà¸� Selection ส่วนที่เลือà¸� Select All เลือà¸�ทั้งหมด Expression นิพจน์ Result ผลลัพธ์ Calculation à¸�ารคำนวณ Calculation as Single Line à¸�ารคำนวณในบรรทัดเดียว Remove นำออà¸� This Calculation à¸�ารคำนวณนี้ All Calculations Above à¸�ารคำนวณทั้งหมดด้านบน All Calculations Below à¸�ารคำนวณทั้งหมดด้านล่าง New Private Tab à¹�ท็บส่วนตัวใหม่ Session เซสชัน Open... เปิด... Clone... โคลน... Rename... เปลี่ยนชื่อ... Keep เà¸�็บไว้ Make Private... ทำให้เป็นส่วนตัว... Clear ล้าง Delete ลบ Close ปิด Split à¹�บ่ง Left ซ้าย Right ขวา Up ขึ้น Down ลง Close Pane ปิดบานหน้าต่าง Main Menu เมนูหลัà¸� Cancel editing ยà¸�เลิà¸�à¸�ารà¹�à¸�้ไข Copy result คัดลอà¸�ผลลัพธ์ Edit expression à¹�à¸�้ไขนิพจน์ Change settings เปลี่ยนà¸�ารตั้งค่า Remove calculation ลบà¸�ารคำนวณ ResultSlotsDialog Notation & Precision สัà¸�à¸�รณ์à¹�ละความละเอียด Result Line บรรทัดผลลัพธ์ Enabled เปิดใช้งาน Notation สัà¸�à¸�รณ์ Decimal Places ตำà¹�หน่งทศนิยม Main Line บรรทัดหลัà¸� Extra Line #1 บรรทัดเพิ่มเติม #1 Extra Line #2 บรรทัดเพิ่มเติม #2 Extra Line #3 บรรทัดเพิ่มเติม #3 Extra Line #4 บรรทัดเพิ่มเติม #4 Auto อัตโนมัติ UserFunctionListWidget Name ชื่อ Value ค่า Description คำอธิบาย Search ค้นหา No match found ไม่พบรายà¸�ารที่ตรงà¸�ัน Insert à¹�ทรà¸� Edit à¹�à¸�้ไข Delete ลบ Delete All ลบทั้งหมด UserUnitListWidget Name ชื่อ Value ค่า Description คำอธิบาย Search ค้นหา No match found ไม่พบรายà¸�ารที่ตรงà¸�ัน Insert à¹�ทรà¸� Edit à¹�à¸�้ไข Delete ลบ Delete All ลบทั้งหมด VariableListWidget Name ชื่อ Value ค่า Description คำอธิบาย Search ค้นหา No match found ไม่พบรายà¸�ารที่ตรงà¸�ัน Insert à¹�ทรà¸� Edit à¹�à¸�้ไข Delete ลบ Delete All ลบทั้งหมด heldercorreia-speedcrunch-e7ca37f/src/resources/locale/tr.ts000066400000000000000000010501321526573132500243740ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunch Hakkında Core developers Ana geliÅŸtiriciler Original author Programı ilk yazan Close Kapat Math engine Matematik altyapısı Main author | Logo | Maintainer Ana yazar | Logo | Bakımcı Thanks TeÅŸekkürler Copyright (C) 2004-2026 The SpeedCrunch developers Telif hakkı (C) 2004-2026 SpeedCrunch geliÅŸtiricileri This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Bu uygulama bir özgür yazılımdır; Free Software Foundation tarafından yayınlanan GNU Genel Kamu Lisansı ikinci sürümünün veya daha yeni bir sürümünün belirlediÄŸi ÅŸartlar altında bu uygulamayı deÄŸiÅŸtirebilir ve/veya yeniden dağıtabilirsiniz. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Bu uygulama yararlı olması umuduyla dağıtılmaktadır, ancak HİÇBİR GARANTİ VERİLMEZ; buna TİCARİ ELVERİŞLİLİK veya BELİRLİ BİR AMACA UYGUNLUK yönündeki zımni garantiler de dahildir. Daha fazla ayrıntı için GNU Genel Kamu Lisansına bakınız. BitFieldWidget Reset bits to zero Bitleri sıfıra sıfırla Invert bits Bitleri tersine çevir Shift bits left Bitleri sola kaydır Shift bits right Bitleri saÄŸa kaydır Book Index Dizin Algebra Cebir Quadratic Equation İkinci dereceden denklem Logarithmic Base Conversion Logaritmik taban dönüştürme Geometry Geometri Circle Daire Sector Sektör Sphere Küre Cube Küp Cone Koni Cylinder Silindir Electronics Elektronik Ohm's Law Ohm Kanunu Power Güç Reactance Reaktans Resonance Rezonans Radio Frequency Radyo frekansı Antennas Anten Characteristic Impedance (coax) Karakteristik empedans (Koaksiyel) Velocity of Propagation (coax) Yayılma hızı (koaksiyel) Standing Wave Ratio & Return Loss Sabit dalga oranı ve geri dönüş kaybı Free Space Wavelength Serbest uzay dalga boyu resistance direnç voltage voltaj current akım power güç inductive reactance endüktif reaktans capacitive reactance kapasitif reaktans inductance endüktans capacitance kapasitans frequency frekans resonance frequency rezonans frekansı area alan perimeter çevre diameter çap radius yarıçap volume hacim surface area yüzey alanı height yükseklik slant height eÄŸim yüksekliÄŸi face diagonal yüz köşegeni space diagonal uzay köşegeni edge length kenar uzunluÄŸu arc length yay uzunluÄŸu central angle (degrees) merkez açı (derece) input power giriÅŸ gücü reflected power yansıyan güç transmitted power iletilen güç return loss geri dönüş kaybı dielectric constant dielektrik sabiti outer conductor's inner diameter dış iletkenin iç çapı inner conductor's outer diameter iç iletkenin dış çapı speed of light ışık hızı reflection coefficient yansıma katsayısı standing wave ratio sabit dalga oranı normalized impedance normalize edilmiÅŸ empedans frequency (Hz) frekans (Hz) BookDock Formula Book Formül kitabı ConstantCompletion Search constants Sabitleri ara No match found EÅŸleÅŸen bulunamadı Constants Mathematics Matematik Physics (CODATA 2022) Fizik (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kimya (IUPAC - CIAAW 2021) Uncategorized Kategorisiz Universal Evrensel Physicochemical Fizikokimyasal Atomic & Nuclear — General Atomik ve Nükleer — Genel Atomic & Nuclear — Electroweak Atomik ve Nükleer — Elektrozayıf Atomic & Nuclear — Electron Atomik ve Nükleer — Elektron Atomic & Nuclear — Muon Atomik ve Nükleer — Müon Atomic & Nuclear — Tau Atomik ve Nükleer — Tau Atomic & Nuclear — Proton Atomik ve Nükleer — Proton Atomic & Nuclear — Neutron Atomik ve Nükleer — Nötron Atomic & Nuclear — Deuteron Atomik ve Nükleer — Döteron Atomic & Nuclear — Triton Atomik ve Nükleer — Triton Atomic & Nuclear — Helion Atomik ve Nükleer — Helyon Atomic & Nuclear — Alpha particle Atomik ve Nükleer — Alfa parçacığı Atomic & Nuclear — Atomic units Atomik ve Nükleer — Atomik birimler Atomic & Nuclear — Energy conversion relationships Atomik ve Nükleer — Enerji dönüşüm iliÅŸkileri Atomic & Nuclear — X-ray units Atomik ve Nükleer — X ışını birimleri Atomic & Nuclear — Magnetic shielding corrections Atomik ve Nükleer — Manyetik perdeleme düzeltmeleri Masses Kütleler Lifetimes Ömürler Molar Masses Molar Kütleler Electronegativity Elektronegatiflik Ionization Energy İyonlaÅŸma Enerjisi Nominal Constants (IAU 2015) Nominal Sabitler (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Güncel En İyi Tahminler (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) vakumun karakteristik empedansı (Zâ‚€) reduced Planck constant (â„�) indirgenmiÅŸ Planck sabiti (â„�) vacuum electric permittivity (ϵ₀) vakumun elektriksel geçirgenliÄŸi (ϵ₀) Newtonian constant of gravitation (G) Newton kütleçekim sabiti (G) vacuum magnetic permeability (μ₀) vakumun manyetik geçirgenliÄŸi (μ₀) Planck constant (h) Planck sabiti (h) speed of light in vacuum (c) vakumda ışık hızı (c) standard acceleration of gravity (gâ‚™) standart yerçekimi ivmesi (gâ‚™) Newtonian constant of gravitation over h-bar c Newton kütleçekim sabiti bölü h-bar c Planck length Planck uzunluÄŸu Planck constant in eV/Hz (h) Planck sabiti cinsinden eV/Hz (h) Planck mass Planck kütlesi Planck mass energy equivalent in GeV Planck kütlesi enerji eÅŸdeÄŸeri cinsinden GeV Planck temperature Planck sıcaklığı Planck time Planck zamanı reduced Planck constant in eV·s (â„�) indirgenmiÅŸ Planck sabiti cinsinden eV·s (â„�) reduced Planck constant times c in MeV·fm indirgenmiÅŸ Planck sabiti çarpı c cinsinden MeV·fm Bohr magneton Bohr magnetonu conductance quantum (Gâ‚€) iletkenlik kuantumu (Gâ‚€) Coulomb constant (kâ‚‘) Coulomb sabiti (kâ‚‘) elementary charge (e) temel yük (e) elementary charge over h-bar temel yük bölü h-bar conventional value of Josephson constant Josephson sabitinin konvansiyonel deÄŸeri Josephson constant Josephson sabiti conventional value of ampere-90 ampere-90'ın konvansiyonel deÄŸeri conventional value of coulomb-90 coulomb-90'ın konvansiyonel deÄŸeri conventional value of farad-90 farad-90'ın konvansiyonel deÄŸeri conventional value of henry-90 henry-90'ın konvansiyonel deÄŸeri conventional value of ohm-90 ohm-90'ın konvansiyonel deÄŸeri conventional value of volt-90 volt-90'ın konvansiyonel deÄŸeri conventional value of watt-90 watt-90'ın konvansiyonel deÄŸeri magnetic flux quantum (Φ₀) manyetik akı kuantumu (Φ₀) nuclear magneton nükleer magneton inverse of conductance quantum iletkenlik kuantumunun tersi conventional value of von Klitzing constant von Klitzing sabitinin konvansiyonel deÄŸeri von Klitzing constant von Klitzing sabiti atomic unit of magnetic dipole moment manyetik dipol momentin atomik birimi atomic unit of magnetic flux density manyetik akı yoÄŸunluÄŸunun atomik birimi Bohr magneton in eV/T eV/T cinsinden Bohr magnetonu Bohr magneton in Hz/T Hz/T cinsinden Bohr magnetonu Bohr magneton in inverse meter per tesla tesla başına ters metre cinsinden Bohr magnetonu Bohr magneton in K/T K/T cinsinden Bohr magnetonu nuclear magneton in eV/T eV/T cinsinden nükleer magneton nuclear magneton in inverse meter per tesla tesla başına ters metre cinsinden nükleer magneton nuclear magneton in K/T K/T cinsinden nükleer magneton nuclear magneton in MHz/T MHz/T cinsinden nükleer magneton Bohr radius (aâ‚€) Bohr yarıçapı (aâ‚€) fine-structure constant (α) ince yapı sabiti (α) Hartree energy (Eâ‚•) Hartree enerjisi (Eâ‚•) Hartree energy in eV eV cinsinden Hartree enerjisi quantum of circulation dolanım kuantumu quantum of circulation times 2 dolanım kuantumu çarpı 2 Rydberg constant (R∞) Rydberg sabiti (R∞) atomic mass unit-hartree relationship atomik kütle birimi-Hartree iliÅŸkisi atomic mass unit-hertz relationship atomik kütle birimi-hertz iliÅŸkisi atomic mass unit-inverse meter relationship atomik kütle birimi-ters metre iliÅŸkisi atomic mass unit-joule relationship atomik kütle birimi-joule iliÅŸkisi atomic mass unit-kelvin relationship atomik kütle birimi-kelvin iliÅŸkisi atomic mass unit-kilogram relationship atomik kütle birimi-kilogram iliÅŸkisi atomic unit of 1st hyperpolarizability birinci hiperpolarize olabilirliÄŸin atomik birimi atomic unit of 2nd hyperpolarizability ikinci hiperpolarize olabilirliÄŸin atomik birimi atomic unit of charge (e) yükün atomik birimi (e) atomic unit of charge density yük yoÄŸunluÄŸunun atomik birimi atomic unit of current akımın atomik birimi atomic unit of electric dipole moment elektrik dipol momentin atomik birimi atomic unit of electric field elektrik alanın atomik birimi atomic unit of electric field gradient elektrik alan gradyanının atomik birimi atomic unit of electric polarizability elektrik polarize olabilirliÄŸin atomik birimi atomic unit of electric potential elektrik potansiyelin atomik birimi atomic unit of electric quadrupole moment elektrik kuadrupol momentin atomik birimi atomic unit of action etkinin atomik birimi atomic unit of energy enerjinin atomik birimi atomic unit of force kuvvetin atomik birimi atomic unit of length uzunluÄŸun atomik birimi hertz-atomic mass unit relationship hertz-atomik kütle birimi iliÅŸkisi hertz-electron volt relationship hertz-elektronvolt iliÅŸkisi hertz-hartree relationship hertz-Hartree iliÅŸkisi hertz-inverse meter relationship hertz-ters metre iliÅŸkisi hertz-joule relationship hertz-joule iliÅŸkisi hertz-kelvin relationship hertz-kelvin iliÅŸkisi hertz-kilogram relationship hertz-kilogram iliÅŸkisi hyperfine transition frequency of Cs-133 Cs-133'ün aşırı ince geçiÅŸ frekansı inverse fine-structure constant (αâ�»Â¹) ters ince yapı sabiti (αâ�»Â¹) inverse meter-atomic mass unit relationship ters metre-atomik kütle birimi iliÅŸkisi inverse meter-electron volt relationship ters metre-elektronvolt iliÅŸkisi inverse meter-hartree relationship ters metre-Hartree iliÅŸkisi inverse meter-hertz relationship ters metre-hertz iliÅŸkisi inverse meter-joule relationship ters metre-joule iliÅŸkisi inverse meter-kelvin relationship ters metre-kelvin iliÅŸkisi inverse meter-kilogram relationship ters metre-kilogram iliÅŸkisi joule-atomic mass unit relationship joule-atomik kütle birimi iliÅŸkisi joule-electron volt relationship joule-elektronvolt iliÅŸkisi joule-hertz relationship joule-hertz iliÅŸkisi joule-hartree relationship joule-Hartree iliÅŸkisi joule-inverse meter relationship joule-ters metre iliÅŸkisi joule-kelvin relationship joule-kelvin iliÅŸkisi joule-kilogram relationship joule-kilogram iliÅŸkisi kelvin-atomic mass unit relationship kelvin-atomik kütle birimi iliÅŸkisi kelvin-electron volt relationship kelvin-elektronvolt iliÅŸkisi kelvin-hertz relationship kelvin-hertz iliÅŸkisi kelvin-hartree relationship kelvin-Hartree iliÅŸkisi kelvin-inverse meter relationship kelvin-ters metre iliÅŸkisi kelvin-joule relationship kelvin-joule iliÅŸkisi kelvin-kilogram relationship kelvin-kilogram iliÅŸkisi kilogram-atomic mass unit relationship kilogram-atomik kütle birimi iliÅŸkisi kilogram-electron volt relationship kilogram-elektronvolt iliÅŸkisi kilogram-hertz relationship kilogram-hertz iliÅŸkisi kilogram-hartree relationship kilogram-Hartree iliÅŸkisi kilogram-inverse meter relationship kilogram-ters metre iliÅŸkisi kilogram-joule relationship kilogram-joule iliÅŸkisi kilogram-kelvin relationship kilogram-kelvin iliÅŸkisi lattice parameter of silicon (a) silisyumun kafes parametresi (a) luminous efficacy ışık etkinliÄŸi natural unit of energy enerjinin doÄŸal birimi natural unit of energy in MeV MeV cinsinden enerjinin doÄŸal birimi natural unit of action (â„�) etkinin doÄŸal birimi (â„�) natural unit of action in eV·s eV·s cinsinden etkinin doÄŸal birimi natural unit of length uzunluÄŸun doÄŸal birimi natural unit of mass kütlenin doÄŸal birimi natural unit of momentum momentumun doÄŸal birimi natural unit of momentum in MeV/c MeV/c cinsinden momentumun doÄŸal birimi natural unit of time zamanın doÄŸal birimi natural unit of velocity hızın doÄŸal birimi Rydberg constant times c in Hz Rydberg sabiti çarpı c cinsinden Hz Rydberg constant times hc in eV Rydberg sabiti çarpı hc cinsinden eV Rydberg constant times hc in J Rydberg sabiti çarpı hc cinsinden J Fermi coupling constant Fermi baÄŸlaşım sabiti weak mixing angle zayıf karışım açısı W to Z mass ratio W/Z kütle oranı Thomson cross section (σₑ) Thomson tesir kesiti (σₑ) electron mass (mâ‚‘) elektron kütlesi (mâ‚‘) electron mass in u elektron kütlesi cinsinden u electron mass energy equivalent (mₑ·c²) elektron kütlesi enerji eÅŸdeÄŸeri (mₑ·c²) electron mass energy equivalent in MeV elektron kütlesi enerji eÅŸdeÄŸeri cinsinden MeV reduced Compton wavelength indirgenmiÅŸ Compton dalga boyu classical electron radius (râ‚‘) klasik elektron yarıçapı (râ‚‘) electron charge to mass quotient elektron yük-kütle bölümü electron-deuteron magnetic moment ratio elektron-döteron manyetik moment oranı electron-deuteron mass ratio elektron-döteron kütle oranı electron g factor (gâ‚‘) elektron g faktörü (gâ‚‘) electron gyromagnetic ratio (γₑ) elektron jiromanyetik oranı (γₑ) electron gyromagnetic ratio in MHz/T MHz/T cinsinden elektron jiromanyetik oranı electron-helion mass ratio elektron-helyon kütle oranı electron magnetic moment (μₑ) elektron manyetik momenti (μₑ) electron magnetic moment anomaly (aâ‚‘) elektron manyetik moment anomalisi (aâ‚‘) electron magnetic moment to Bohr magneton ratio elektron manyetik momentinin Bohr magnetonuna oranı electron magnetic moment to nuclear magneton ratio elektron manyetik momentinin nükleer magnetona oranı electron molar mass (Mâ‚‘) elektronun molar kütlesi (Mâ‚‘) electron-muon magnetic moment ratio elektron-müon manyetik moment oranı electron-muon mass ratio elektron-müon kütle oranı electron-neutron magnetic moment ratio elektron-nötron manyetik moment oranı electron-neutron mass ratio elektron-nötron kütle oranı electron-proton magnetic moment ratio elektron-proton manyetik moment oranı electron-proton mass ratio elektron-proton kütle oranı electron relative atomic mass (Ar(e)) elektron bağıl atom kütlesi (Ar(e)) electron-tau mass ratio elektron-tau kütle oranı electron to alpha particle mass ratio elektron-alfa parçacığı kütle oranı electron to shielded helion magnetic moment ratio elektron-perdelenmiÅŸ helyon manyetik moment oranı electron to shielded proton magnetic moment ratio elektron-perdelenmiÅŸ proton manyetik moment oranı electron-triton mass ratio elektron-triton kütle oranı electron volt-atomic mass unit relationship elektronvolt-atomik kütle birimi iliÅŸkisi electron volt-hartree relationship elektronvolt-Hartree iliÅŸkisi electron volt-hertz relationship elektronvolt-hertz iliÅŸkisi electron volt-inverse meter relationship elektronvolt-ters metre iliÅŸkisi electron volt-joule relationship elektronvolt-joule iliÅŸkisi electron volt-kelvin relationship elektronvolt-kelvin iliÅŸkisi electron volt-kilogram relationship elektronvolt-kilogram iliÅŸkisi hartree-atomic mass unit relationship Hartree-atomik kütle birimi iliÅŸkisi hartree-electron volt relationship Hartree-elektronvolt iliÅŸkisi muon Compton wavelength müon Compton dalga boyu muon-electron mass ratio müon-elektron kütle oranı muon g factor müon g faktörü muon magnetic moment müon manyetik momenti muon magnetic moment anomaly müon manyetik moment anomalisi muon magnetic moment to Bohr magneton ratio müon manyetik momentinin Bohr magnetonuna oranı muon magnetic moment to nuclear magneton ratio müon manyetik momentinin nükleer magnetona oranı muon mass müon kütlesi muon mass energy equivalent müon kütlesi enerji eÅŸdeÄŸeri muon mass energy equivalent in MeV müon kütlesi enerji eÅŸdeÄŸeri cinsinden MeV muon mass in u müon kütlesi cinsinden u muon molar mass müon molar kütlesi muon-neutron mass ratio müon-nötron kütle oranı muon-proton magnetic moment ratio müon-proton manyetik moment oranı muon-proton mass ratio müon-proton kütle oranı muon-tau mass ratio müon-tau kütle oranı reduced muon Compton wavelength indirgenmiÅŸ müon Compton dalga boyu reduced tau Compton wavelength indirgenmiÅŸ tau Compton dalga boyu tau Compton wavelength tau Compton dalga boyu tau-electron mass ratio tau-elektron kütle oranı tau mass tau kütlesi tau mass energy equivalent tau kütlesi enerji eÅŸdeÄŸeri tau mass in u tau kütlesi cinsinden u tau molar mass tau molar kütlesi tau-muon mass ratio tau-müon kütle oranı tau-neutron mass ratio tau-nötron kütle oranı tau-proton mass ratio tau-proton kütle oranı proton charge to mass quotient proton yük-kütle bölümü proton Compton wavelength proton Compton dalga boyu proton-electron mass ratio proton-elektron kütle oranı proton g factor (gₚ) proton g faktörü (gₚ) proton gyromagnetic ratio (γₚ) proton jiromanyetik oranı (γₚ) proton gyromagnetic ratio in MHz/T MHz/T cinsinden proton jiromanyetik oranı proton magnetic moment (μₚ) proton manyetik momenti (μₚ) proton magnetic moment to Bohr magneton ratio proton manyetik momentinin Bohr magnetonuna oranı proton magnetic moment to nuclear magneton ratio proton manyetik momentinin nükleer magnetona oranı proton magnetic shielding correction proton manyetik perdeleme düzeltmesi proton mass (mₚ) proton kütlesi (mₚ) proton mass energy equivalent proton kütlesi enerji eÅŸdeÄŸeri proton mass energy equivalent in MeV proton kütlesi enerji eÅŸdeÄŸeri cinsinden MeV proton mass in u proton kütlesi cinsinden u proton molar mass (Mₚ) protonun molar kütlesi (Mₚ) proton-muon mass ratio proton-müon kütle oranı proton-neutron magnetic moment ratio proton-nötron manyetik moment oranı proton-neutron mass ratio proton-nötron kütle oranı proton relative atomic mass (Ar(p)) proton bağıl atom kütlesi (Ar(p)) proton rms charge radius proton rms yük yarıçapı proton-tau mass ratio proton-tau kütle oranı reduced proton Compton wavelength indirgenmiÅŸ proton Compton dalga boyu shielded proton gyromagnetic ratio perdelenmiÅŸ proton jiromanyetik oranı shielded proton gyromagnetic ratio in MHz/T MHz/T cinsinden perdelenmiÅŸ proton jiromanyetik oranı shielded proton magnetic moment perdelenmiÅŸ proton manyetik momenti shielded proton magnetic moment to Bohr magneton ratio perdelenmiÅŸ proton manyetik momentinin Bohr magnetonuna oranı shielded proton magnetic moment to nuclear magneton ratio perdelenmiÅŸ proton manyetik momentinin nükleer magnetona oranı neutron Compton wavelength nötron Compton dalga boyu neutron-electron magnetic moment ratio nötron-elektron manyetik moment oranı neutron-electron mass ratio nötron-elektron kütle oranı neutron g factor (gâ‚™) nötron g faktörü (gâ‚™) neutron gyromagnetic ratio (γₙ) nötron jiromanyetik oranı (γₙ) neutron gyromagnetic ratio in MHz/T MHz/T cinsinden nötron jiromanyetik oranı neutron magnetic moment (μₙ) nötron manyetik momenti (μₙ) neutron magnetic moment to Bohr magneton ratio nötron manyetik momentinin Bohr magnetonuna oranı neutron magnetic moment to nuclear magneton ratio nötron manyetik momentinin nükleer magnetona oranı neutron mass (mâ‚™) nötron kütlesi (mâ‚™) neutron mass energy equivalent nötron kütlesi enerji eÅŸdeÄŸeri neutron mass energy equivalent in MeV nötron kütlesi enerji eÅŸdeÄŸeri cinsinden MeV neutron mass in u nötron kütlesi cinsinden u neutron molar mass (Mâ‚™) nötronun molar kütlesi (Mâ‚™) neutron-muon mass ratio nötron-müon kütle oranı neutron-proton magnetic moment ratio nötron-proton manyetik moment oranı neutron-proton mass difference nötron-proton kütle farkı neutron-proton mass difference energy equivalent nötron-proton kütle farkı enerji eÅŸdeÄŸeri neutron-proton mass difference energy equivalent in MeV MeV cinsinden nötron-proton kütle farkı enerji eÅŸdeÄŸeri neutron-proton mass difference in u u cinsinden nötron-proton kütle farkı neutron-proton mass ratio nötron-proton kütle oranı neutron relative atomic mass (Ar(n)) nötron bağıl atom kütlesi (Ar(n)) neutron-tau mass ratio nötron-tau kütle oranı neutron to shielded proton magnetic moment ratio nötron-perdelenmiÅŸ proton manyetik moment oranı reduced neutron Compton wavelength indirgenmiÅŸ nötron Compton dalga boyu deuteron-electron magnetic moment ratio döteron-elektron manyetik moment oranı deuteron-electron mass ratio döteron-elektron kütle oranı deuteron g factor döteron g faktörü deuteron magnetic moment döteron manyetik momenti deuteron magnetic moment to Bohr magneton ratio döteron manyetik momentinin Bohr magnetonuna oranı deuteron magnetic moment to nuclear magneton ratio döteron manyetik momentinin nükleer magnetona oranı deuteron mass döteron kütlesi deuteron mass energy equivalent döteron kütlesi enerji eÅŸdeÄŸeri deuteron mass energy equivalent in MeV döteron kütlesi enerji eÅŸdeÄŸeri cinsinden MeV deuteron mass in u döteron kütlesi cinsinden u deuteron molar mass döteron molar kütlesi deuteron-neutron magnetic moment ratio döteron-nötron manyetik moment oranı deuteron-proton magnetic moment ratio döteron-proton manyetik moment oranı deuteron-proton mass ratio döteron-proton kütle oranı deuteron relative atomic mass (Ar(d)) döteron bağıl atom kütlesi (Ar(d)) deuteron rms charge radius döteron rms yük yarıçapı triton-electron mass ratio triton-elektron kütle oranı triton g factor (gₜ) triton g faktörü (gₜ) triton magnetic moment (μₜ) triton manyetik momenti (μₜ) triton magnetic moment to Bohr magneton ratio triton manyetik momentinin Bohr magnetonuna oranı triton magnetic moment to nuclear magneton ratio triton manyetik momentinin nükleer magnetona oranı triton mass (mₜ) triton kütlesi (mₜ) triton mass energy equivalent triton kütlesi enerji eÅŸdeÄŸeri triton mass energy equivalent in MeV triton kütlesi enerji eÅŸdeÄŸeri cinsinden MeV triton mass in u triton kütlesi cinsinden u triton molar mass (Mₜ) tritonun molar kütlesi (Mₜ) triton-proton mass ratio triton-proton kütle oranı triton relative atomic mass (Ar(t)) triton bağıl atom kütlesi (Ar(t)) triton to proton magnetic moment ratio triton-proton manyetik moment oranı helion-electron mass ratio helyon-elektron kütle oranı helion g factor (gâ‚•) helyon g faktörü (gâ‚•) helion magnetic moment (μₕ) helyon manyetik momenti (μₕ) helion magnetic moment to Bohr magneton ratio helyon manyetik momentinin Bohr magnetonuna oranı helion magnetic moment to nuclear magneton ratio helyon manyetik momentinin nükleer magnetona oranı helion mass (mâ‚•) helyon kütlesi (mâ‚•) helion mass energy equivalent helyon kütlesi enerji eÅŸdeÄŸeri helion mass energy equivalent in MeV helyon kütlesi enerji eÅŸdeÄŸeri cinsinden MeV helion mass in u helyon kütlesi cinsinden u helion molar mass (Mâ‚•) helyonun molar kütlesi (Mâ‚•) helion-proton mass ratio helyon-proton kütle oranı helion relative atomic mass (Ar(h)) helyon bağıl atom kütlesi (Ar(h)) helion shielding shift helyon perdeleme kayması shielded helion gyromagnetic ratio perdelenmiÅŸ helyon jiromanyetik oranı shielded helion gyromagnetic ratio in MHz/T MHz/T cinsinden perdelenmiÅŸ helyon jiromanyetik oranı shielded helion magnetic moment perdelenmiÅŸ helyon manyetik momenti shielded helion magnetic moment to Bohr magneton ratio perdelenmiÅŸ helyon manyetik momentinin Bohr magnetonuna oranı shielded helion magnetic moment to nuclear magneton ratio perdelenmiÅŸ helyon manyetik momentinin nükleer magnetona oranı shielded helion to proton magnetic moment ratio perdelenmiÅŸ helyon-proton manyetik moment oranı shielded helion to shielded proton magnetic moment ratio perdelenmiÅŸ helyon-perdelenmiÅŸ proton manyetik moment oranı alpha particle mass alfa parçacığı kütlesi alpha particle mass in u alfa parçacığı kütlesi cinsinden u alpha particle mass energy equivalent alfa parçacığı kütlesi enerji eÅŸdeÄŸeri alpha particle mass energy equivalent in MeV alfa parçacığı kütlesi enerji eÅŸdeÄŸeri cinsinden MeV alpha particle-electron mass ratio alfa parçacığı-elektron kütle oranı alpha particle-proton mass ratio alfa parçacığı-proton kütle oranı alpha particle rms charge radius alfa parçacığı rms yük yarıçapı alpha particle molar mass alfa parçacığı molar kütlesi alpha particle relative atomic mass (Ar(α)) alfa parçacığı bağıl atom kütlesi (Ar(α)) atomic mass constant (mᵤ) atomik kütle sabiti (mᵤ) Avogadro constant Avogadro sabiti Boltzmann constant (k) Boltzmann sabiti (k) Boltzmann constant in eV/K Boltzmann sabiti cinsinden eV/K Boltzmann constant in Hz/K Boltzmann sabiti cinsinden Hz/K Boltzmann constant in inverse meter per kelvin Boltzmann sabiti cinsinden ters metre başına kelvin electron volt (eV) elektron volt (eV) Faraday constant (F) Faraday sabiti (F) first radiation constant (câ‚�) birinci ışıma sabiti (câ‚�) first radiation constant for spectral radiance spektral radyans için birinci ışıma sabiti molar gas constant (R) molar gaz sabiti (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Loschmidt sabiti (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Loschmidt sabiti (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molar Planck sabiti second radiation constant (câ‚‚) ikinci ışıma sabiti (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Boltzmann sabiti (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ideal Si kafes aralığı (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atomik kütle sabiti enerji eÅŸdeÄŸeri atomic mass constant energy equivalent in MeV MeV cinsinden atomik kütle sabiti enerji eÅŸdeÄŸeri atomic mass unit-electron volt relationship atomik kütle birimi-elektronvolt iliÅŸkisi molar mass constant (Mᵤ) molar kütle sabiti (Mᵤ) molar mass of carbon-12 karbon-12'nin molar kütlesi molar volume of ideal gas (273.15 K, 100 kPa) ideal gazın molar hacmi (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ideal gazın molar hacmi (273.15 K, 101.325 kPa) molar volume of silicon molar hacmi silisyum Sackur-Tetrode constant (1 K, 100 kPa) Sackur-Tetrode sabiti (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sackur-Tetrode sabiti (1 K, 101.325 kPa) Wien frequency displacement law constant Wien frekans kayma yasası sabiti Wien wavelength displacement law constant Wien dalga boyu kayma yasası sabiti standard atmosphere (atm) standart atmosfer (atm) standard-state pressure (p°) standart durum basıncı (p°) Angstrom star (Ã…*) Angstrom yıldızı (Ã…*) Copper x unit Bakır x birimi Molybdenum x unit Molibden x birimi atomic unit of magnetizability manyetize olabilirliÄŸin atomik birimi atomic unit of mass (mâ‚‘) kütlenin atomik birimi (mâ‚‘) atomic unit of momentum momentumun atomik birimi atomic unit of permittivity geçirgenliÄŸin atomik birimi atomic unit of time zamanın atomik birimi atomic unit of velocity hızın atomik birimi hartree-hertz relationship hartree-hertz iliÅŸkisi hartree-inverse meter relationship Hartree-ters metre iliÅŸkisi hartree-joule relationship hartree-joule iliÅŸkisi hartree-kelvin relationship hartree-kelvin iliÅŸkisi hartree-kilogram relationship hartree-kilogram iliÅŸkisi shielding difference of d and p in HD HD'deki d ve p perdeleme farkı shielding difference of t and p in HT HT'deki t ve p perdeleme farkı pi (Ï€) pi (Ï€) Euler's number (e) Euler sayısı (e) golden ratio (φ) altın oran (φ) Euler-Mascheroni constant (γ) Euler-Mascheroni sabiti (γ) nominal solar radius nominal GüneÅŸ yarıçapı nominal solar total irradiance nominal güneÅŸ toplam ışınımı nominal solar luminosity nominal güneÅŸ ışınırlığı nominal solar effective temperature nominal güneÅŸ etkin sıcaklığı nominal solar mass parameter nominal güneÅŸ kütle parametresi nominal terrestrial equatorial radius nominal Yer ekvatoral yarıçapı nominal terrestrial polar radius nominal Yer kutupsal yarıçapı nominal terrestrial mass parameter nominal Yer kütlesi parametresi nominal jovian equatorial radius nominal Jüpiter ekvatoral yarıçapı nominal jovian polar radius nominal Jüpiter kutupsal yarıçapı nominal jovian mass parameter nominal Jüpiter kütlesi parametresi average value of one minus the rate of TCG relative to TCB TCB'ye göre TCG hızının bir eksiÄŸinin ortalama deÄŸeri solar mass parameter (TCB-compatible) güneÅŸ kütle parametresi (TCB uyumlu) solar mass parameter (TDB-compatible) güneÅŸ kütle parametresi (TDB uyumlu) equatorial radius of the Earth (TT-compatible) Dünya'nın ekvator yarıçapı (TT uyumlu) dynamical form factor of the Earth Dünya'nın dinamik ÅŸekil faktörü time rate of change in the dynamical form factor of the Earth Dünya'nın dinamik ÅŸekil faktörünün zamana göre deÄŸiÅŸim hızı geocentric gravitational constant (TCB-compatible) yermerkezli kütleçekim sabiti (TCB uyumlu) geocentric gravitational constant (TT-compatible) yermerkezli kütleçekim sabiti (TT uyumlu) geocentric gravitational constant (TDB-compatible) yermerkezli kütleçekim sabiti (TDB uyumlu) potential of the geoid jeoid potansiyeli nominal mean angular velocity of the Earth (TT-compatible) Dünya'nın nominal ortalama açısal hızı (TT uyumlu) ratio mass of the Moon to the Earth Ay kütlesinin Dünya kütlesine oranı ratio of the mass of the Sun to Mercury GüneÅŸ kütlesinin Merkür kütlesine oranı ratio of the mass of the Sun to Venus GüneÅŸ kütlesinin Venüs kütlesine oranı ratio of the mass of the Sun to Mars GüneÅŸ kütlesinin Mars kütlesine oranı ratio of the mass of the Sun to Jupiter GüneÅŸ kütlesinin Jüpiter kütlesine oranı ratio of the mass of the Sun to Saturn GüneÅŸ kütlesinin Satürn kütlesine oranı ratio of the mass of the Sun to Uranus GüneÅŸ kütlesinin Uranüs kütlesine oranı ratio of the mass of the Sun to Neptune GüneÅŸ kütlesinin Neptün kütlesine oranı ratio of the mass of the Sun to (134340) Pluto GüneÅŸ kütlesinin (134340) Plüton kütlesine oranı ratio of the mass of the Sun to (136199) Eris GüneÅŸ kütlesinin (136199) Eris kütlesine oranı ratio of the mass of (1) Ceres to the Sun (1) Ceres kütlesinin GüneÅŸ kütlesine oranı ratio of the mass of (2) Pallas to the Sun (2) Pallas kütlesinin GüneÅŸ kütlesine oranı ratio of the mass of (4) Vesta to the Sun (4) Vesta kütlesinin GüneÅŸ kütlesine oranı mean obliquity of the ecliptic at J2000.0 J2000.0'da ekliptiÄŸin ortalama eÄŸikliÄŸi Electromagnetic Elektromanyetik Compton wavelength Compton dalga boyu Astronomy Astronomi ConstantsWidget Domain Alan Subdomain Alt alan No match found EÅŸleÅŸen bulunamadı Name Ad Value DeÄŸer Unit Birim Search Ara All Tümü CustomKeypadDialog Custom Keypad Özel TuÅŸ Takımı Rows: Satırlar: Columns: Sütunlar: Copy preset: Ön ayarı kopyala: Basic Temel Scientific (wide) Bilimsel (geniÅŸ) Scientific (narrow) Bilimsel (dar) Apply Uygula Row Satır Column Sütun Label Etiket Behavior Davranış Text Metin DiagnosticsDialog App Diagnostics Uygulama Tanılaması Copy to Clipboard Panoya Kopyala Editor Unit Birim User unit Kullanıcı birimi User function Kullanıcı iÅŸlevi Argument Bağımsız deÄŸiÅŸken Current result:<br/>%1 Geçerli sonuç:<br/>%1 Selection result:<br/>%1 Seçim sonucu:<br/>%1 Selection result: n/a Seçim sonucu: n/a Selection result: %1 Seçim sonucu: %1 second saniye metre metre kilogram kilogram mole mol radian radyan steradian steradyan degree Celsius Santigrat derece cubic metre metreküp cubic millimetre milimetreküp cubic centimetre santimetreküp cubic decimetre desimetreküp cubic kilometre kilometreküp square millimetre milimetrekare square kilometre kilometrekare square metre metrekare minute dakika hour saat day gün astronomical unit astronomik birim degree derece arcminute yay dakikası arcsecond yay saniyesi milliarcsecond mili yay saniyesi microarcsecond mikro yay saniyesi hectare hektar litre litre tonne ton Dalton Dalton electronvolt elektronvolt Angstrom Angstrom atmosphere atmosfer atomic mass unit atomik kütle birimi British thermal unit İngiliz ısı birimi calorie kalori carat karat cup fincan cup (Imperial) fincan (İngiliz) cup (Japanese) fincan (Japon) cup (US) fincan (ABD) degree Fahrenheit Fahrenheit derece fathom kulaç fluid ounce (Imperial) sıvı ons (İngiliz) fluid ounce (US) sıvı ons (ABD) fluid dram (Imperial) sıvı dram (İngiliz) fluid dram (US) sıvı dram (ABD) foot fit square foot fit kare cubic foot fit küp gallon (Imperial) galon (İngiliz) gallon (US) galon (ABD) gill (Imperial) gill (İngiliz) gill (US) gill (ABD) gradian gradyan grain grain gram gram Hartley Hartley Hartree energy unit Hartree enerji birimi horsepower beygir gücü inch inç square inch inç kare cubic inch inç küp karat karat knot knot lightminute ışık dakikası lightsecond ışık saniyesi lightyear ışık yılı long ton uzun ton mile mil square mile mil kare cubic mile mil küp mile per hour saatte mil kilometre per hour saatte kilometre nautical mile deniz mili ounce ons parsec parsek pint (Imperial) pint (İngiliz) pint (US) pint (ABD) pound pound pounds per square inch inç kare başına pound quart (Imperial) kuart (İngiliz) quart (US) kuart (ABD) oil barrel petrol varili beer barrel (US) bira varili (ABD) square yard yard kare cubic yard yard küp short ton kısa ton tablespoon yemek kaşığı tablespoon (Australian) yemek kaşığı (Avustralya) tablespoon (Imperial) yemek kaşığı (İngiliz) tablespoon (US) yemek kaşığı (ABD) dessert spoon tatlı kaşığı teaspoon çay kaşığı teaspoon (Imperial) çay kaşığı (İngiliz) teaspoon (US) çay kaşığı (ABD) turn tur revolution devir revolution per minute dakikadaki devir week hafta kilowatt hour kilovat saat millimetre of mercury milimetre cıva yard yard Julian century Jülyen yüzyılı Julian year Jülyen yılı sidereal year yıldız yılı tropical year tropikal yıl Evaluator invalid expression geçersiz ifade division by zero sıfıra bölme too time consuming - computation was rejected çok zaman alıyor - hesaplama reddedildi dimension mismatch - quantities with different dimensions cannot be compared, added, etc. boyut uyuÅŸmazlığı - farklı boyutlu nicelikler karşılaÅŸtırılamaz, eklenemez ve sair. invalid dimension - operation might require dimensionless arguments geçersiz boyut - iÅŸlem boyutsuz deÄŸiÅŸkenler gerektirebilir Computation aborted - encountered numerical instability Hesaplama iptal edildi - sayısal kararsızlık saptandı invalid dimension - function might require dimensionless arguments geçersiz boyut - iÅŸlev boyutsuz deÄŸiÅŸkenler gerektirebilir error hata unit must not be zero birim sıfır olmamalıdır Conversion failed - dimension mismatch Dönüştürme baÅŸarısız - boyut uyuÅŸmazlığı unknown function or variable bilinmeyen iÅŸlev veya deÄŸiÅŸken recursion not supported özyineleme desteklenmiyor cannot operate on a NaN NaN üzerinde iÅŸlem yapılamaz underflow - tiny result is out of SpeedCrunch's number range alt taÅŸma - sonuç SpeedCrunch sayı aralığının altında kaldı overflow - huge result is out of SpeedCrunch's number range taÅŸma - sonuç SpeedCrunch sayı aralığının dışına çıktı overflow - logic result exceeds maximum of 256 bits taÅŸma - lojik sonuç 256 bit sınırını aşıyor overflow - integer result exceeds maximum limit for integers taÅŸma - tamsayı sonucu tamsayılar için maksimum sınırını aşıyor operation is not defined for these arguments iÅŸlem bu bağımsız deÄŸiÅŸkenler için tanımlı deÄŸil wrong number of arguments bağımsız deÄŸiÅŸken sayısı yanlış does not take NaN as an argument NaN, bağımsız deÄŸiÅŸken olarak kullanılamaz result out of range erim dışı bir sonuç undefined for argument domain bağımsız deÄŸiÅŸken etki alanı için tanımsız computation too expensive hesaplama çok maliyetli internal error, please report a bug iç hata, lütfen hata bildirimi yapın syntax error sözdizimi hatası conversion target must be a unit dönüştürme hedefi bir birim olmalıdır unknown unit bilinmeyen birim %1 is a reserved name, please choose another %1 ayrılmış bir isimdir, lütfen baÅŸka bir isim seçin %1 is a global user definition and cannot be overridden in this session. %1 genel bir kullanıcı tanımıdır ve bu oturumda geçersiz kılınamaz. %1 is a variable name, please choose another or delete the variable %1 bir deÄŸiÅŸken adıdır, lütfen baÅŸka bir ad seçin veya deÄŸiÅŸkeni silin argument %1 is used more than once %1 bağımsız deÄŸiÅŸkeni birden çok kez kullanıldı %1 is a built-in unit name, please choose another %1 yerleÅŸik bir birim adıdır, lütfen baÅŸka bir ad seçin %1 is a user function name, please choose another or delete the function %1 bir kullanıcı iÅŸlevi adıdır, lütfen baÅŸka bir ad seçin veya iÅŸlevi silin FunctionRepo max; trials; probability en çok; deneme; olasılık trials; probability deneme; olasılık hits; trials; probability isabet; deneme; olasılık max; total; hits; trials en çok; toplam; isabet; deneme total; hits; trials toplam; isabet; deneme count; total; hits; trials sayı; toplam; isabet; deneme dividend; divisor bölünen sayı; bölen x; exponent_bits; significand_bits [; exponent_bias] x; üs_bitleri; belirgin_bitler [; üs_yanlılığı] base; x temel; x value; modulo deÄŸer; modül base; exponent; modulo taban; üs; modül events; average_events olay; ortalama_olay average_events ortalama_olay x [; precision] x [; hassasiyet] Absolute Value Mutlak deÄŸer Absolute Deviation Mutlak sapma Arc Cosine Ark Kosinüs Logical AND Mantıksal VE Area Hyperbolic Cosine Alan Hiperbolik Kosinüsü Area Hyperbolic Sine Alan Hiperbolik Sinüsü Area Hyperbolic Tangent Alan Hiperbolik Tanjantı Arc Sine Ark Sinüs Arc Tangent Ark Tanjant Arc Tangent with two Arguments İki deÄŸiÅŸkenli Ark Tanjant Average (Arithmetic Mean) Ortalama (Aritmetik ortalama) Binomial Cumulative Distribution Function Binom kümülatif dağılım fonksiyonu Binomial Distribution Mean Binom dağılımı ortalaması Binomial Probability Mass Function Binom olasılık kütle fonksiyonu Binomial Distribution Variance Binom dağılımı varyansı Cube Root Küp Kök Complex Conjugate Karmaşık EÅŸlenik Cosine Kosinüs Hyperbolic Cosine Hiperbolik Kosinüs Cotangent Kotanjant Cosecant Kosekant Convert Unix timestamp to Date Unix zaman damgasını tarihe dönüştür Degrees of Arc Ark Dereceleri Error Function Hata Fonksiyonu Complementary Error Function Tamamlayıcı Hata Fonksiyonu Exponential Üstel Fractional Part Kesirli Bölüm Extension of Factorials [= (x-1)!] Faktöriyel uzantısı [=(x-1)!] Greatest Common Divisor En Büyük Ortak Bölen Geometric Mean Geometrik Ortalama Gradians of arc Ark gradyanları Hypergeometric Cumulative Distribution Function Kümülatif Hipergeometrik Olasılık Fonksiyonu Hypergeometric Distribution Mean Hipergeometrik Dağılım Ortalaması Hypergeometric Probability Mass Function Hipergeometrik Olasılık Kütle Fonksiyonu Hypergeometric Distribution Variance Hipergeometrik Dağılım Varyansı Integer Quotient Tamsayı Bölümü Integer Part Tamsayı Kısmı Imaginary Part Hayali kısım Decode IEEE-754 Binary Value IEEE-754 ikili deÄŸerin kodunu çöz Encode IEEE-754 Binary Value IEEE-754 ikili deÄŸeri kodla Decode 16-bit Half-Precision Value 16 bit yarı kesin deÄŸerin kodunu çöz Encode 16-bit Half-Precision Value 16 bit yarı kesin deÄŸeri kodla Decode 32-bit Single-Precision Value 32 bit tekli kesin deÄŸerin kodunu çöz Encode 32-bit Single-Precision Value 32 bit tekli kesin deÄŸeri kodla Decode 64-bit Double-Precision Value 64 bit çiftli kesin deÄŸerin kodunu çöz Encode 64-bit Double-Precision Value 64 bit çiftli kesin deÄŸeri kodla Decode 128-bit Quad-Precision Value 128 bit dörtlü kesin deÄŸerin kodunu çöz Encode 128-bit Quad-Precision Value 128 bit dörtlü kesin deÄŸeri kodla Binary Logarithm İkili logaritma Common Logarithm Onluk logaritma Natural Logarithm DoÄŸal Logaritma Logarithm to Arbitrary Base İstenen tabanda logaritma Mask to a bit size Bit boyutuna göre maskele Maximum En büyük Median Value (50th Percentile) Medyan deÄŸeri (50. yüzdelik) Minimum En küçük Modulo Mod Euclidean Modulo Öklid modu Modular Exponentiation Modüler Üslendirme Combination (Binomial Coefficient) Kombinasyon (Binom Katsayısı) Logical NOT Mantıksal DEĞİL Permutation (Arrangement) Permütasyon (Sıralama) Convert to Binary Representation İkilik gösterime dönüştür Arithmetic Aritmetik Chemistry Kimya Complex Karmaşık Combinatorics Kombinatorik Probability Olasılık Statistics İstatistik Aggregation Toplama Random Rastgele Base conversion Taban dönüştürme Number formatting Sayı biçimlendirme Integer arithmetic Tamsayı aritmetiÄŸi Special functions Özel iÅŸlevler Exponential & Logarithmic Üstel ve Logaritmik Angle conversion Açı dönüştürme Trigonometry Trigonometri Bitwise Bitsel Floating point Kayan nokta Date & Time Tarih ve Saat Linear algebra DoÄŸrusal cebir unix_timestamp; x hours offset to GMT unix_timestamp; GMT'den x saat farklı yyyymmdd.hhmmss; x hours offset to GMT unix_timestamp; GMT’ye x saat fark [digits] [basamaklar] max [; min] en çok [; en az] List Literal Liste sabiti Convert to Padded Binary Representation DoldurulmuÅŸ ikilik gösterime dönüştür Round Toward +∞ (Ceiling) +∞ yönüne yuvarla (tavan) Cosine plus Imaginary Sine Kosinüs artı sanal sinüs Convert to Cis Complex Form Cis karmaşık biçimine dönüştür Matrix Column Count Matris sütun sayısı Population Correlation Matrix (n) Popülasyon korelasyon matrisi (n) Sample Correlation Matrix (n-1) Örneklem korelasyon matrisi (n-1) Count Öğe sayısı Population Covariance Matrix (n) Popülasyon kovaryans matrisi (n) Sample Covariance Matrix (n-1) Örneklem kovaryans matrisi (n-1) Cross Product Çapraz çarpım Convert Date to Unix timestamp Tarihi Unix zaman damgasına dönüştür Convert to Decimal Representation Ondalık gösterime dönüştür Determinant Determinant Convert to Sexagesimal Notation Altmışlık gösterimine dönüştür Dot Product Noktasal çarpım Convert to Engineering Notation Mühendislik gösterimine dönüştür Convert to Exponential Complex Form Üstel karmaşık biçime dönüştür Round Toward −∞ (Floor) −∞ (floor) yönüne yuvarla Flatten Matrix Matrisi düzleÅŸtir Least Common Multiple En küçük ortak kat Convert to Hexadecimal Representation Onaltılık gösterime dönüştür Convert to Padded Hexadecimal Representation DoldurulmuÅŸ onaltılık gösterime dönüştür Inverse Matrix Ters matris Round to 16-bit Half-Precision Value 16 bit yarı duyarlıklı deÄŸere yuvarla Round to 32-bit Single-Precision Value 32 bit tek duyarlıklı deÄŸere yuvarla Round to 64-bit Double-Precision Value 64 bit çift duyarlıklı deÄŸere yuvarla Round to 128-bit Quad-Precision Value 128 bit dört kat duyarlıklı deÄŸere yuvarla Residual from 16-bit Half-Precision Rounding 16 bit yarı duyarlıklı yuvarlama artığı Residual from 32-bit Single-Precision Rounding 32 bit tek duyarlıklı yuvarlama artığı Residual from 64-bit Double-Precision Rounding 64 bit çift duyarlıklı yuvarlama artığı Residual from 128-bit Quad-Precision Rounding 128 bit dört kat duyarlıklı yuvarlama artığı Substance Mass Madde kütlesi Molarity Molarite Molar Mass Molar kütle Median Absolute Deviation Medyan mutlak sapma Mean Ortalama Numerical Value of Quantity NiceliÄŸin sayısal deÄŸeri Random Decimal Number Rastgele ondalık sayı Random Integer Number Rastgele tam sayı Convert to Rational Representation Rasyonel gösterime dönüştür Convert to Octal Representation Sekizlik gösterime dönüştür Convert to Padded Octal Representation DoldurulmuÅŸ sekizlik gösterime dönüştür Vector or Matrix Norm Vektör veya matris normu Logical OR Mantıksal VEYA Population Count (Hamming Weight) Bit sayısı (Hamming ağırlığı) Phase of Complex Number Karmaşık Sayının Fazı Poissonian Cumulative Distribution Function Poisson kümülatif dağılım fonksiyonu Poissonian Distribution Mean Poisson dağılımı ortalaması Poissonian Probability Mass Function Poisson olasılık kütle fonksiyonu Poissonian Distribution Variance Poisson dağılımı varyansı Convert to Phasor Complex Form Fazör karmaşık biçimine dönüştür Convert to Rectangular Complex Form Dikdörtgensel karmaşık biçime dönüştür Round Half Away from Zero Yarıyı sıfırdan uzaÄŸa yuvarla Round Half Even Yarıyı çifte yuvarla Nth Root N'inci Kök Convert to Scientific Notation Bilimsel gösterime dönüştür Matrix Row Count Matris satır sayısı List or Matrix Shape Liste veya matris ÅŸekli Summation Toplam Population Standard Deviation (n) Popülasyon standart sapması (n) Sample Standard Deviation (n-1) Örneklem standart sapması (n-1) Round Toward Zero (Truncation) Sıfıra doÄŸru yuvarla (kırpma) Matrix Trace Matris izi Transpose Matrix Matrisi transpoze et Population Variance (n) Popülasyon varyansı (n) Sample Variance (n-1) Örneklem varyansı (n-1) Product Ürün Radians Radyan Matrix Rank Matris rankı Real Part Gerçek Kısım Secant Sekant Arithmetic Shift Left Aritmetik Sola Kayma Arithmetic Shift Right Aritmetik SaÄŸa Kayma Signum İşaret Sine Sinüs Hyperbolic Sine Hiperbolik Sinüs Square Root Kare Kök Sum Toplama Tangent Tanjant Convert to Trigonometric Complex Form Trigonometrik karmaşık biçime dönüştür Turns Tur Hyperbolic Tangent Hiperbolik Tanjant Sign-extend a value Bir deÄŸerin iÅŸaretini geniÅŸlet Logical XOR Mantıksal ÖZEL VEYA FunctionsWidget Domain Alan All Tümü Name İsim Search Ara No match found EÅŸleÅŸen bulunamadı Identifier Kimlik HistoryWidget Remove All Calculations Above Yukarıdaki Tüm Hesaplamaları Kaldır Remove This Calculation Bu Hesaplamayı Kaldır Remove All Calculations Below AÅŸağıdaki Tüm Hesaplamaları Kaldır Keypad Inverse cosine Ters kosinüs The last result Son sonuç Inverse sine Ters sinüs Inverse tangent Ters tanjant Evaluate expression İfadeyi deÄŸerlendir Division Bölme Multiplication Çarpma Subtraction Çıkarma Addition Toplama Clear expression İfadeyi temizle Cosine Kosinüs Backspace Geri sil Scientific notation Bilimsel notasyon Exponential Üstel Factorial Faktöriyel Natural logarithm DoÄŸal logaritma Left parenthesis Sol parantez Nth root N'inci Kök Argument separator Bağımsız deÄŸiÅŸken ayırıcı Square Kare Common logarithm Ortak logaritma Modulo Modül Contextual percentage BaÄŸlamsal yüzde Power Güç Right parenthesis SaÄŸ parantez Sine Sinüs Square root Kare kök Tangent Tanjant Pi Pi Decimal separator Ondalık ayırıcı MainWindow Radian Radyan Degree Derece Gradian Gradyan Binary İkilik Octal Sekizlik Hexadecimal Onaltılık Sexagesimal Altmışlık Engineering decimal Mühendislik ondalığı Scientific decimal Bilimsel ondalık &Import... &İçe Aktar... &Quit &Çık Clear E&xpression İ&fadeyi Temizle Clear &History GeçmiÅŸi &Temizle &Copy &Kopyala &Paste &Yapıştır &Select Expression İfade &Seç &Constants Sa&bitler &Functions İşlevle&r &History &GeçmiÅŸ &Status Bar &Durum ÇubuÄŸu Bitfield Bit alanı Use&r Functions Kullanıcı İşlevleri(&R) &Degree &Derece &Radian &Radyan &Gradian &Gradyan Re&volution De&vir Auto-Insert a&ns a&ns DeÄŸerini Otomatik Ekle Automatic &Completion Otomatik &Tamamlama &Built-in Functions &YerleÅŸik İşlevler Built-in &Variables Y&erleÅŸik DeÄŸiÅŸkenler User &Functions &Kullanıcı İşlevleri User Va&riables Kullanıcı DeÄŸiÅŸkenle&ri Open a Private Tab on Startup BaÅŸlangıçta Gizli Sekme Aç Open and focus a new private tab whenever SpeedCrunch starts. SpeedCrunch her baÅŸladığında yeni bir gizli sekme aç ve odakla. Syntax &Highlighting Sözdizim &Vurgulama Group Digits in &Input G&iriÅŸteki Basamakları Grupla Automatic Input &Adjustments Otom&atik GiriÅŸ Düzenlemeleri Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. İşleçleri, boÅŸlukları, parantezleri ve üsleri otomatik düzenle ve giriÅŸi geçerli karakterlerle sınırla. Group input digits using the selected number format. Girilen basamakları seçilen sayı biçimine göre grupla. &Blinking Cursor &Yanıp Sönen İmleç Blink the cursor in the expression editor. İfade düzenleyicisindeki imlecin yanıp sönmesini saÄŸla. &Escape Clears Editor &Escape Düzenleyiciyi Temizler Clear the focused expression editor with Escape after dismissing any popup or preview. Açılır pencereler veya önizlemeler kapatıldıktan sonra etkin ifade düzenleyicisini Escape ile temizle. Keep Expression After Evaluation Hesaplamadan Sonra İfadeyi Koru Copy New Results Automatically Yeni Sonuçları Otomatik Kopyala &Comma &Virgül &System Default &Sistem Varsayılanı &Dot &Nokta Dot &And Comma Nokta ve Virgü&l Toward +∞ (&ceil) +∞ Yönünde (&ceil) Toward −∞ (&floor) −∞ Yönünde (&floor) &Binary &İkilik &Engineering &Mühendislik &Hexadecimal &Onaltılık &Octal &Sekizlik &Scientific &Bilimsel User &Manual Kullanıcı &Kılavuzu Issues and &Feedback &Sorunlar ve Geri Bildirim &Donate &Bağış Yap &About SpeedCrunch SpeedCrunch H&akkında App Diag&nostics Uygulama Ta&nılaması S&plit B&öl Angle &Mode &Açı Kipi &Complex Form &Karmaşık Biçim New Tab Yeni Sekme Constants Sabitler Functions İşlevler History GeçmiÅŸ User Functions Kullanıcı İşlevleri &Font... &Yazıtipi... &Language... &Dil... &Session &Oturum &Edit &Düzenle &View &Görünüm Se&ttings &Ayarlar &Decimal &Ondalık &Keypad &TuÅŸ Takımı Always on &Top &Her zaman üstte Disabled Devre Dışı Small Space Küçük Aralık Medium Space Orta Aralık Large Space GeniÅŸ Aralık &0 Digits &0 basamak &15 Digits &15 basamak &2 Digits &2 basamak &3 Digits &3 basamak &50 Digits &50 basamak &8 Digits &8 basamak &Sexagesimal &Altmışlık Reset All Settings... Tüm Ayarları Sıfırla... &System &Sistem SpeedCrunch &Theme SpeedCrunch &Teması &Classic &Klasik &Modern &Modern Context Help BaÄŸlam yardımı &Help &Yardım Error Hata Can't read from file %1 %1 dosyasından okunamadı Import Session Oturumu İçe Aktar Close Session Oturumu Kapat Angle Mode: Açı Modu: Notation: Gösterim: Precision: Hassasiyet: Turn Tur Revolution Devir Fixed-point decimal Sabit noktalı ondalık Rational Rasyonel Automatic decimal Otomatik ondalık Automatic Otomatik User &Definitions... Kullanıcı &Tanımları... New &Tab Yeni &Sekme New &Private Tab &Yeni Gizli Sekme Keep Sakla Make Private... Gizli Yap... New &Window Yeni &Pencere &Open... &Aç... &Rename... Yeniden Adlandı&r... Clo&ne... Klo&nla... &Close Tab S&ekmeyi Kapat Reopen Clo&sed Tab Kapa&tılan Sekmeyi Yeniden Aç Open Sessions &Folder Oturumlar &Klasörünü Aç &Undo &Geri Al &Redo Y&inele Cu&t K&es Copy &Last Result Son Sonucu Kopya&la &Wrap in Parentheses &Parantez İçine Al Full Scr&een Mode Tam &Ekran Kipi &Basic &Temel &Scientific (wide) &Bilimsel (geniÅŸ) Scientific (narrow) Bilimsel (dar) &Custom... &Özel... Main &Menu Ana &Menü User &Variables Kullanıcı &DeÄŸiÅŸkenleri &Left So&l &Right &SaÄŸ &Up Y&ukarı &Down &AÅŸağı Close Pa&ne Bö&lmeyi Kapat User &Units Kullanıcı &Birimleri &Turn &Tur If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Yeni bir ifade +, -, * veya / ile baÅŸlarsa SpeedCrunch önce "ans" ekler. &Accept with Enter E&nter ile Kabul Et Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Geçerli otomatik tamamlama önerisini önce ok tuÅŸlarıyla seçmeden Enter ile kabul et. &Units &Birimler Show Live Result &Preview Canlı Sonuç &Önizlemesini Göster Save &Window Position on Exit Çıkışta &Pencere Konumunu Kaydet Hover Highlighting Üzerine Gelme Vurgusu Group Integer Part Only Yalnızca Tamsayı Kısmını Grupla Number Format... Sayı Biçimi... Notation && Precision... Gösterim ve Hassasiyet... After pressing Enter, keep the entered expression selected in the editor. Enter tuÅŸuna bastıktan sonra girilen ifadeyi düzenleyicide seçili tut. Never Hiçbir zaman Always Her zaman Only for Single-Line Expressions Yalnızca Tek Satırlı İfadeler İçin Simplify Displayed Expressions Görüntülenen İfadeleri SadeleÅŸtir History Size &Limit... GeçmiÅŸ Boyutu &Sınırı... Remove Trailing &Zeroes S&ondaki Sıfırları Kaldır Nearest, Half &Away (round) En yakın, yarım &uzaÄŸa (round) Nearest, Half &Even (roundeven) En yakın, yarım &çifte (roundeven) Toward &Zero (trunc) &Sıfıra doÄŸru (trunc) &Fixed-Point &Sabit Noktalı &Rational &Rasyonel &Exponential (m·sâ�»Â¹) &Üstel (m·sâ�»Â¹) &Fractional (m/s) &Kesirli (m/s) &Rectangular (a + bi) &Dikdörtgensel (a + bi) Exponential (reâ�±á¶¿) Üstel (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrik (r(cos θ + i·sin θ)) Phasor (r∠θ) Fazör (r∠θ) &Theme... &Tema... Check for &Updates &Güncellemeleri Denetle Source Code Kaynak Kodu &Zoom &YakınlaÅŸtırma &Results &Sonuçlar Unit Notation Birim Gösterimi Rounding Mode Yuvarlama Modu &Notation &Gösterim &Imaginary Unit &Sanal Birim &Window &Pencere &Editing &Düzenleme A&utocomplete Otomatik &Tamamlama Up/Down Arrow History Yukarı/AÅŸağı Ok GeçmiÅŸi &Appearance &Görünüm &Menus &Menüler &Docks &Kenetlenebilir Paneller &Input and Results G&iriÅŸ ve Sonuçlar &Disabled &Devre Dışı &Disable &Devre Dışı Bırak Close preview Önizlemeyi kapat Rename... Yeniden Adlandır... Clone... Klonla... Close Tab Sekmeyi Kapat New Private Tab Yeni Gizli Sekme Open... Aç... Reopen Closed Tab Kapatılan Sekmeyi Yeniden Aç Split Böl Left Sol Right SaÄŸ Up Yukarı Down AÅŸağı Clear Temizle Delete Sil %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Gizli oturum: kapatıldığında içerik silinir. Normal oturuma dönüştürmek için Oturum > Sakla seçeneÄŸini kullanın. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Gizli] Reset All Settings Tüm Ayarları Sıfırla Reset all settings to their default values? Tüm ayarlar varsayılan deÄŸerlerine sıfırlansın mı? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Görünüm, düzenleme, sonuç biçimleri ve pencere tercihleri buna dahildir. Hesaplamalarınız, açık oturumlarınız ve kullanıcı tanımlarınız korunur. The settings file could not be written. Ayar dosyası yazılamadı. Clear this session's calculations, unfinished expression, variables, functions, and units? Bu oturumun hesaplamaları, tamamlanmamış ifadesi, deÄŸiÅŸkenleri, iÅŸlevleri ve birimleri temizlensin mi? Global user definitions are kept. Genel kullanıcı tanımları korunur. Make Session Private Oturumu Gizli Yap The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. KaydedilmiÅŸ %1 oturumu silinecek. İçeriÄŸi gizli bir oturumda açık kalacak ve o oturum kapatıldığında veya SpeedCrunch'tan çıkıldığında silinecek. Make Private Gizli Yap Could not delete the saved session %1. KaydedilmiÅŸ %1 oturumu silinemedi. Keep Session Oturumu Sakla Could not save the session. It remains private. Oturum kaydedilemedi. Gizli kalıyor. Clone Session Oturumu Klonla Could not save session file %1. %1 oturum dosyası kaydedilemedi. Could not delete session file %1. %1 oturum dosyası silinemedi. JSON file (*.json);;Any file (*.*) JSON dosyası (*.json);;Herhangi bir dosya (*.*) Export session as JSON Oturumu JSON olarak dışa aktar The selected file is not valid JSON: %1 Seçilen dosya geçerli JSON deÄŸil: %1 The selected file is not a SpeedCrunch session JSON file. Seçilen dosya bir SpeedCrunch oturumu JSON dosyası deÄŸil. This file uses an obsolete SpeedCrunch session format and cannot be imported. Bu dosya eski bir SpeedCrunch oturum biçimi kullanıyor ve içe aktarılamaz. The selected JSON file is missing the required $schema field. Seçilen JSON dosyasında gerekli $schema alanı eksik. The selected JSON file uses an unsupported JSON schema: %1 Seçilen JSON dosyası desteklenmeyen bir JSON ÅŸeması kullanıyor: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Seçilen JSON dosyasında SpeedCrunch oturum ÅŸeması tanımlayıcısı ($id) eksik. The selected JSON file uses an unsupported SpeedCrunch session format: %1 Seçilen JSON dosyası desteklenmeyen bir SpeedCrunch oturum biçimi kullanıyor: %1 The selected JSON file is missing the required session name. Seçilen JSON dosyasında gerekli oturum adı eksik. The selected JSON file has an empty session name. Seçilen JSON dosyasında boÅŸ bir oturum adı var. The selected JSON file has invalid or incomplete SpeedCrunch session data. Seçilen JSON dosyasında geçersiz veya eksik SpeedCrunch oturum verileri var. Open Sessions Folder Oturumlar Klasörünü Aç Could not create the sessions folder: %1 Oturumlar klasörü oluÅŸturulamadı: %1 Could not open the sessions folder: %1 Oturumlar klasörü açılamadı: %1 Editor and Results Font Düzenleyici ve Sonuç Yazı Tipi Open Session Oturumu Aç Community Topluluk Rename Session Oturumu Yeniden Adlandır Clear Session Oturumu Temizle Delete Session Oturumu Sil Close Pane Bölmeyi Kapat User Variables Kullanıcı DeÄŸiÅŸkenleri User Units Kullanıcı Birimleri Clear History GeçmiÅŸi Temizle Are you sure you want to clear the calculation history? Hesaplama geçmiÅŸini temizlemek istediÄŸinizden emin misiniz? Session name: Oturum adı: A session named %1 already exists. %1 adlı bir oturum zaten var. Could not create session file %1. %1 oturum dosyası oluÅŸturulamadı. Could not write session file %1. %1 oturum dosyasına yazılamadı. Are you sure you want to delete this session? Bu oturumu silmek istediÄŸinizden emin misiniz? Custom Precision Özel Hassasiyet Fractional digits: Kesir basamakları: Theme Tema Light Themes Açık Temalar Dark Themes Koyu Temalar Preview Önizleme Colors Renkler Select color for %1 %1 için renk seç Import... İçe Aktar... Export... Dışa Aktar... Import Theme Temayı İçe Aktar Theme file (*.json);;All files (*) Tema dosyası (*.json);;Tüm dosyalar (*) Invalid theme file. Geçersiz tema dosyası. Can't import theme "%1" because it conflicts with a built-in theme. "%1" teması yerleÅŸik bir temayla çakıştığı için içe aktarılamıyor. Can't find a writable theme folder. Yazılabilir bir tema klasörü bulunamıyor. Overwrite Theme Temanın Üzerine Yaz A custom theme named "%1" already exists. Do you want to overwrite it? "%1" adlı özel tema zaten var. Üzerine yazmak istiyor musunuz? Can't overwrite theme file %1 %1 tema dosyasının üzerine yazılamıyor Can't copy theme file to %1 Tema dosyası %1 konumuna kopyalanamıyor Export Theme Temayı Dışa Aktar Can't export theme as "%1" because it conflicts with a built-in theme. YerleÅŸik bir temayla çakıştığı için tema "%1" olarak dışa aktarılamıyor. Can't write to file %1 %1 dosyasına yazılamıyor Global User Variable Genel Kullanıcı DeÄŸiÅŸkeni Global User Function Genel Kullanıcı İşlevi Global User Unit Genel Kullanıcı Birimi User Definitions Kullanıcı Tanımları These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Bu tanımlar geneldir ve her oturuma yüklenir. Oturumlarda deÄŸiÅŸtirilemezler ve oturum düzenleyicisindeki aynı adlı tanımlara göre önceliklidirler. Her satıra bir tanım girin. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Örnekler: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Uygula Validate DoÄŸrula Test Results Test Sonuçları Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 İçe aktarılan deÄŸiÅŸkenler: %1 İçe aktarılan iÅŸlevler: %2 İçe aktarılan birimler: %3 Hata içeren satır numaraları: %4 none yok Apply Results Uygulama Sonuçları User definitions saved. Kullanıcı tanımları kaydedildi. History Size Limit GeçmiÅŸ Boyutu Sınırı Maximum number of history entries for this session (0 = unlimited): Bu oturum için en fazla geçmiÅŸ girdisi sayısı (0 = sınırsız): Text file (*.txt);;Any file (*.*) Metin dosyası (*.txt);;Herhangi bir dosya (*.*) Could not recalculate from calculation %1: %2 %1 hesaplamasından yeniden hesaplanamadı: %2 History Size Limit Reached GeçmiÅŸ Boyutu Sınırına Ulaşıldı This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Bu hesaplama son kullanılabilir geçmiÅŸ yuvasını doldurur. Gelecekteki hesaplamalar geçmiÅŸteki en eski hesaplamayı kaldırır. Sınırı Oturum > GeçmiÅŸ Boyutu Sınırı bölümünden artırabilirsiniz. Editing calculation. Press Esc twice to cancel. Hesaplama düzenleniyor. İptal etmek için Esc tuÅŸuna iki kez basın. Calculation Settings Hesaplama Ayarları Invalid recalculation start index Geçersiz yeniden hesaplama baÅŸlangıç indeksi System Default Sistem Öntanımlı Language Dil Select the language: Dil seçin: Custom Özel Decimal places: Ondalık basamaklar: &Automatic &Otomatik &Precision &Hassasiyet Plain &text Düz &Metin Formula &Book Formül &Kitabı &Export &Dışa Aktar Export session as HTML Oturumu HTML olarak dışa aktar HTML file (*.html) HTML dosyası (*.html) Export session as plain text Oturumu düz metin olarak dışa aktar ManualWindow SpeedCrunch Manual SpeedCrunch kılavuzu %1 - SpeedCrunch Manual %1 - SpeedCrunch kılavuzu NumberFormatDialog Number Format Sayı Biçimi <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Sonuçlar ve giriÅŸ basamaklarının gruplandırılması için sayı biçimini seçin.</b><br/><br/>Not: girilen sayılar için açıkça anlaşılabilen biçimler, seçilen görüntüleme biçiminden farklı olsalar bile kabul edilir.<br/> QObject Global User Variable Genel Kullanıcı DeÄŸiÅŸkeni Global User Function Genel Kullanıcı İşlevi Global User Unit Genel Kullanıcı Birimi Backspace Geri sil Clear expression İfadeyi temizle Evaluate expression İfadeyi deÄŸerlendir Insert text Metin ekle Automatic decimal Otomatik ondalık Fixed-point decimal Sabit noktalı ondalık Engineering decimal Mühendislik ondalığı Scientific decimal Bilimsel ondalık Rational Rasyonel Binary İkilik Octal Sekizlik Hexadecimal Onaltılık Sexagesimal Altmışlık Update Available Güncelleme Mevcut A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Yeni bir sürüm (%1) kullanılabilir.<br/><a href="%2">İndirmek için web sitesini ziyaret edin.</a> Check for Updates Güncellemeleri Denetle SpeedCrunch %1 is up to date. SpeedCrunch %1 güncel. No connectivity. Please check your internet connection and try again. BaÄŸlantı yok. Lütfen internet baÄŸlantınızı denetleyip yeniden deneyin. Could not verify the latest available version. Kullanılabilir en son sürüm doÄŸrulanamadı. ResultDisplay Scroll to bottom En alta kaydır Edit Expression İfadeyi Düzenle Change Settings Ayarları DeÄŸiÅŸtir New Tab Yeni Sekme &Import... &İçe Aktar... &Export &Dışa Aktar Plain &text Düz &Metin Copy Kopyala Selection Seçim Select All Tümünü Seç Expression İfade Result Sonuç Calculation Hesaplama Calculation as Single Line Tek Satırda Hesaplama Remove Kaldır This Calculation Bu Hesaplama All Calculations Above Yukarıdaki Tüm Hesaplamalar All Calculations Below AÅŸağıdaki Tüm Hesaplamalar New Private Tab Yeni Gizli Sekme Session Oturum Open... Aç... Clone... Klonla... Rename... Yeniden Adlandır... Keep Sakla Make Private... Gizli Yap... Clear Temizle Delete Sil Close Kapat Split Böl Left Sol Right SaÄŸ Up Yukarı Down AÅŸağı Close Pane Bölmeyi Kapat Main Menu Ana Menü Cancel editing Düzenlemeyi iptal et Copy result Sonucu kopyala Edit expression İfadeyi düzenle Change settings Ayarları deÄŸiÅŸtir Remove calculation Hesaplamayı kaldır ResultSlotsDialog Notation & Precision Gösterim ve Hassasiyet Result Line Sonuç Satırı Enabled Etkin Notation Gösterim Decimal Places Ondalık Basamaklar Main Line Ana Satır Extra Line #1 Ek Satır #1 Extra Line #2 Ek Satır #2 Extra Line #3 Ek Satır #3 Extra Line #4 Ek Satır #4 Auto Otomatik UserFunctionListWidget Name Ad Value DeÄŸer Description Açıklama Search Ara No match found EÅŸleÅŸen bulunamadı Insert Ekle Edit Düzenle Delete Sil Delete All Tümünü Sil UserUnitListWidget Name Ad Value DeÄŸer Description Açıklama Search Ara No match found EÅŸleÅŸen bulunamadı Insert Ekle Edit Düzenle Delete Sil Delete All Tümünü Sil VariableListWidget Name Ad Value DeÄŸer Description Açıklama Search Ara No match found EÅŸleÅŸen bulunamadı Insert Ekle Edit Düzenle Delete Sil Delete All Tümünü Sil heldercorreia-speedcrunch-e7ca37f/src/resources/locale/translation-stats.py000077500000000000000000000146421526573132500274530ustar00rootroot00000000000000#!/usr/bin/env python3 """ Translation statistics for Qt Linguist TS/QM files. This repository ships Qt translation source files (*.ts) and compiled catalogs (*.qm). A TS file is an XML document with entries containing a element. Untranslated entries are typically marked as: ... or have an empty translation text. """ from __future__ import annotations import argparse import os import sys import xml.etree.ElementTree as ET MessageKey = tuple[str, str] RED = "\033[31m" GREEN = "\033[32m" YELLOW = "\033[33m" RESET = "\033[0m" def _pct(n: int, d: int) -> float: if d <= 0: return 100.0 return (100.0 * n) / d def _is_untranslated(tr_el: ET.Element | None) -> bool: if tr_el is None: return True # Qt uses type="unfinished" for missing translations. if (tr_el.get("type") or "").strip().lower() == "unfinished": return True # Some catalogs still carry empty strings without the attribute. txt = (tr_el.text or "").strip() return txt == "" def _is_inactive_message(msg_el: ET.Element) -> bool: # Message-level inactive marker (less common). if (msg_el.get("type") or "").strip().lower() in {"vanished", "obsolete"}: return True # Qt often stores inactive state on the node instead. tr_el = msg_el.find("translation") if tr_el is not None and (tr_el.get("type") or "").strip().lower() in {"vanished", "obsolete"}: return True return False def _message_key(msg_el: ET.Element, ctx_name: str) -> MessageKey: src = (msg_el.findtext("source") or "").strip() return (ctx_name, src) def _ts_messages(ts_path: str) -> dict[MessageKey, bool]: tree = ET.parse(ts_path) root = tree.getroot() messages: dict[MessageKey, bool] = {} for ctx in root.findall("context"): ctx_name = (ctx.findtext("name") or "").strip() for msg in ctx.findall("message"): # Ignore inactive messages; they don't ship in compiled catalogs. if _is_inactive_message(msg): continue tr_el = msg.find("translation") messages[_message_key(msg, ctx_name)] = not _is_untranslated(tr_el) return messages def _ts_message_stats(ts_path: str) -> tuple[int, int, dict[MessageKey, bool]]: messages = _ts_messages(ts_path) translated = sum(1 for is_translated in messages.values() if is_translated) return len(messages), translated, messages def _qm_info(qm_path: str) -> dict: try: st = os.stat(qm_path) return {"present": True, "size": st.st_size, "mtime": int(st.st_mtime)} except FileNotFoundError: return {"present": False, "size": 0, "mtime": 0} def main(argv: list[str]) -> int: ap = argparse.ArgumentParser( description="Print translation statistics for src/resources/locale (*.ts/*.qm)." ) script_dir = os.path.dirname(os.path.abspath(__file__)) ap.add_argument( "--root", default=script_dir, help="Locale directory (default: directory containing this script)", ) ap.add_argument( "--samples", type=int, default=0, help="Show up to N sample untranslated source strings per language.", ) ap.add_argument( "--complete-ts-files", action="store_true", help="Only print a space-separated list of .ts files with 100%% completion.", ) args = ap.parse_args(argv) root_dir = os.path.abspath(args.root) if not os.path.isdir(root_dir): print(f"error: not a directory: {root_dir}", file=sys.stderr) return 2 ts_files = sorted( f for f in os.listdir(root_dir) if f.endswith(".ts") and os.path.isfile(os.path.join(root_dir, f)) ) if not ts_files: print(f"No .ts files found under {root_dir}") return 0 rows = [] g_total = g_translated = g_unfinished = 0 template_path = os.path.join(root_dir, "en_US.ts") if not os.path.isfile(template_path): print(f"error: missing canonical template: {template_path}", file=sys.stderr) return 2 template_messages = _ts_messages(template_path) template_keys = set(template_messages.keys()) for ts_name in ts_files: ts_path = os.path.join(root_dir, ts_name) lang = ts_name[:-3] if lang == "en_US": continue qm_name = lang + ".qm" total, translated, lang_messages = _ts_message_stats(ts_path) # Keep some samples for optional debug output. samples: list[tuple[str, str]] = [] for key in sorted(template_keys - set(lang_messages.keys())): if key[1]: samples.append(key) unfinished = total - translated g_total += total g_translated += translated g_unfinished += unfinished rows.append( { "ts_name": ts_name, "lang": lang, "total": total, "translated": translated, "unfinished": unfinished, "completion": _pct(translated, total), "samples": samples, } ) if args.complete_ts_files: print(" ".join(r["ts_name"] for r in rows if r["completion"] == 100.0)) return 0 print("Qt TS/QM Translation Statistics") print(f"Locale root: {root_dir}") print(f"Languages: {len(rows)}\n") header = f"{'language':<12} {'total':>7} {'translated':>11} {'unfinished':>11} {'completion':>11}" print(header) for r in rows: row = ( f"{r['lang']:<12} {r['total']:>7} {r['translated']:>11} " f"{r['unfinished']:>11} {r['completion']:>10.1f}%" ) if r["completion"] == 100.0: row = f"{GREEN}{row}{RESET}" elif r["completion"] < 50.0: row = f"{RED}{row}{RESET}" else: row = f"{YELLOW}{row}{RESET}" print(row) if args.samples > 0: shown = 0 for ctx_name, src in r["samples"]: if shown >= args.samples: break # Keep this single-line for greppable output. print(f" - [{ctx_name}] {src}") shown += 1 print( f"\nGlobal: languages={len(rows)} total={g_total} translated={g_translated} unfinished={g_unfinished} completion={_pct(g_translated, g_total):.1f}%" ) return 0 if __name__ == "__main__": raise SystemExit(main(sys.argv[1:])) heldercorreia-speedcrunch-e7ca37f/src/resources/locale/uk.ts000066400000000000000000011420361526573132500243730ustar00rootroot00000000000000 AboutBox About SpeedCrunch Про SpeedCrunch Core developers ОÑ�новні розробники Original author Початковий автор Close Закрити Math engine Математичний рушій Main author | Logo | Maintainer Головний автор | Логотип | Супровідник Thanks ПодÑ�ка Copyright (C) 2004-2026 The SpeedCrunch developers Ð�вторÑ�ькі права (C) 2004-2026 належать розробникам SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version ЦÑ� програма Ñ” безкоштовним програмним забезпеченнÑ�м; ви можете розповÑ�юджувати його та/або змінювати на умовах GNU GPL (Загальної публічної ліцензії), опублікованої Фондом вільного програмного забезпеченнÑ� другого або (на ваш вибір) пізнішого виданнÑ� This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ЦÑ� програма розповÑ�юджуєтьÑ�Ñ� в надії, що вона буде кориÑ�ною, але БЕЗ БУДЬ-ЯКИХ ГÐ�РÐ�Ð�ТІЙ; навіть без неÑ�вної гарантії ПРИДÐ�ТÐ�ОСТІ ДО БУДЬ-ЯКОЇ МЕТИ. Докладніше дивітьÑ�Ñ� GNU GPL. BitFieldWidget Reset bits to zero Скинути біти до нулÑ� Invert bits Інвертувати біти Shift bits left ЗÑ�унути біти вліво Shift bits right ЗÑ�унути біти вправо Book Index ЗміÑ�Ñ‚ Algebra Ð�лгебра Quadratic Equation Квадратне рівнÑ�ннÑ� Logarithmic Base Conversion Зміна оÑ�нови логарифму Geometry ГеометріÑ� Circle Коло Sector Сектор Sphere Сфера Cube Куб Cone КонуÑ� Cylinder Циліндр Electronics Електроніка Ohm's Law Закон Ома Power ПотужніÑ�ть Reactance Реактивний опір Resonance РезонанÑ� Radio Frequency РадіочаÑ�тота Antennas Ð�нтени Characteristic Impedance (coax) Хвильовий опір (коакÑ�іал) Velocity of Propagation (coax) ШвидкіÑ�ть поширеннÑ� (коакÑ�іал) Standing Wave Ratio & Return Loss КСХ Ñ– зворотні втрати Free Space Wavelength Довжина хвилі у вакуумі resistance опір voltage напруга current Ñ�трум power потужніÑ�ть inductive reactance індуктивний опір capacitive reactance ємніÑ�ний опір inductance індуктивніÑ�ть capacitance ємніÑ�ть frequency чаÑ�тота resonance frequency резонанÑ�на чаÑ�тота area площа perimeter периметр diameter діаметр radius радіуÑ� volume об'єм surface area площа поверхні height виÑ�ота slant height довжина твірної face diagonal діагональ грані space diagonal проÑ�торова діагональ edge length довжина ребра arc length довжина дуги central angle (degrees) кут Ñ�ектора (градуÑ�) input power вхідна потужніÑ�ть reflected power відзеркалена потужніÑ�ть transmitted power передана потужніÑ�ть return loss поÑ�лабленнÑ� dielectric constant діелектрична Ñ�тала outer conductor's inner diameter внутрішній діаметр зовнішнього провідника inner conductor's outer diameter зовнішній діаметр внутрішнього провідника speed of light швидкіÑ�ть Ñ�вітла reflection coefficient коефіцієнт відзеркаленнÑ� standing wave ratio коефіцієнт Ñ�тоÑ�чої хвилі normalized impedance нормалізований опір frequency (Hz) чаÑ�тота (Гц) BookDock Formula Book Формули ConstantCompletion Search constants Пошук конÑ�тант No match found Збігів не знайдено Constants Mathematics Математика Physics (CODATA 2022) Фізика (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) ХіміÑ� (IUPAC - CIAAW 2021) Uncategorized Без категорії Universal Загальні Physicochemical Фізико-хімічні Atomic & Nuclear — General Ð�томні й Ñ�дерні — загальні Atomic & Nuclear — Electroweak Ð�томні й Ñ�дерні — електроÑ�лабкі Atomic & Nuclear — Electron Ð�томні й Ñ�дерні — електрон Atomic & Nuclear — Muon Ð�томні й Ñ�дерні — мюон Atomic & Nuclear — Tau Ð�томні й Ñ�дерні — тау Atomic & Nuclear — Proton Ð�томні й Ñ�дерні — протон Atomic & Nuclear — Neutron Ð�томні й Ñ�дерні — нейтрон Atomic & Nuclear — Deuteron Ð�томні й Ñ�дерні — дейтрон Atomic & Nuclear — Triton Ð�томні й Ñ�дерні — тритон Atomic & Nuclear — Helion Ð�томні й Ñ�дерні — геліон Atomic & Nuclear — Alpha particle Ð�томні й Ñ�дерні — альфа-чаÑ�тинка Atomic & Nuclear — Atomic units Ð�томні й Ñ�дерні — атомні одиниці Atomic & Nuclear — Energy conversion relationships Ð�томні й Ñ�дерні — Ñ�піввідношеннÑ� перетвореннÑ� енергії Atomic & Nuclear — X-ray units Ð�томні й Ñ�дерні — рентгенівÑ�ькі одиниці Atomic & Nuclear — Magnetic shielding corrections Ð�томні й Ñ�дерні — поправки магнітного екрануваннÑ� Masses МаÑ�и Lifetimes ЧаÑ�и життÑ� Molar Masses МолÑ�рні маÑ�и Electronegativity ЕлектронегативніÑ�ть Ionization Energy ЕнергіÑ� іонізації Nominal Constants (IAU 2015) Ð�омінальні Ñ�талі (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Поточні найкращі оцінки (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) ХарактериÑ�тичний імпеданÑ� вакууму (Zâ‚€) reduced Planck constant (â„�) Зведена Ñ�тала Планка (â„�) vacuum electric permittivity (ϵ₀) Електрична проникніÑ�ть вакууму (ϵ₀) Newtonian constant of gravitation (G) Ð�ьютонівÑ�ька гравітаційна Ñ�тала (G) vacuum magnetic permeability (μ₀) Магнітна проникніÑ�ть вакууму (μ₀) Planck constant (h) Стала Планка (h) speed of light in vacuum (c) ШвидкіÑ�ть Ñ�вітла у вакуумі (c) standard acceleration of gravity (gâ‚™) Стандартне приÑ�кореннÑ� вільного падіннÑ� (gâ‚™) Newtonian constant of gravitation over h-bar c Ð�ьютонівÑ�ька гравітаційна Ñ�тала поділена на â„�c Planck length ПланківÑ�ька довжина Planck constant in eV/Hz (h) Стала Планка в eV/Hz (h) Planck mass ПланківÑ�ька маÑ�а Planck mass energy equivalent in GeV Енергетичний еквівалент маÑ�и Планка в GeV Planck temperature ПланківÑ�ька температура Planck time ПланківÑ�ький чаÑ� reduced Planck constant in eV·s (â„�) Зведена Ñ�тала Планка в eV·s (â„�) reduced Planck constant times c in MeV·fm Зведена Ñ�тала Планка, помножена на c, в MeV·fm Bohr magneton Магнетон Бора conductance quantum (Gâ‚€) Квант провідноÑ�ті (Gâ‚€) Coulomb constant (kâ‚‘) Стала Кулона (kâ‚‘) elementary charge (e) Елементарний зарÑ�д (e) elementary charge over h-bar Елементарний зарÑ�д, поділений на h-bar conventional value of Josephson constant Умовне значеннÑ� Ñ�талої ДжозефÑ�она Josephson constant Стала ДжозефÑ�она conventional value of ampere-90 Умовне значеннÑ� ампера-90 conventional value of coulomb-90 Умовне значеннÑ� кулона-90 conventional value of farad-90 Умовне значеннÑ� фарада-90 conventional value of henry-90 Умовне значеннÑ� генрі-90 conventional value of ohm-90 Умовне значеннÑ� ома-90 conventional value of volt-90 Умовне значеннÑ� вольта-90 conventional value of watt-90 Умовне значеннÑ� вата-90 magnetic flux quantum (Φ₀) Квант магнітного потоку (Φ₀) nuclear magneton Ядерний магнетон inverse of conductance quantum Обернене значеннÑ� кванта провідноÑ�ті conventional value of von Klitzing constant Умовне значеннÑ� Ñ�талої фон Клітцінга von Klitzing constant Стала фон Клітцінга atomic unit of magnetic dipole moment Ð�томна одиницÑ� магнітного дипольного моменту atomic unit of magnetic flux density Ð�томна одиницÑ� гуÑ�тини магнітного потоку Bohr magneton in eV/T Магнетон Бора в eV/T Bohr magneton in Hz/T Магнетон Бора в Hz/T Bohr magneton in inverse meter per tesla Магнетон Бора в обернених метрах на теÑ�лу Bohr magneton in K/T Магнетон Бора в K/T nuclear magneton in eV/T Ядерний магнетон в eV/T nuclear magneton in inverse meter per tesla Ядерний магнетон в обернених метрах на теÑ�лу nuclear magneton in K/T Ядерний магнетон в K/T nuclear magneton in MHz/T Ядерний магнетон в MHz/T Bohr radius (aâ‚€) РадіуÑ� Бора (aâ‚€) fine-structure constant (α) Стала тонкої Ñ�труктури (α) Hartree energy (Eâ‚•) ЕнергіÑ� Гартрі (Eâ‚•) Hartree energy in eV ЕнергіÑ� Гартрі в eV quantum of circulation Квант циркулÑ�ції quantum of circulation times 2 Квант циркулÑ�ції, помножений на 2 Rydberg constant (R∞) Стала Рідберга (R∞) atomic mass unit-hartree relationship СпіввідношеннÑ� атомної одиниці маÑ�и й гартрі atomic mass unit-hertz relationship СпіввідношеннÑ� атомної одиниці маÑ�и й герца atomic mass unit-inverse meter relationship СпіввідношеннÑ� атомної одиниці маÑ�и й оберненого метра atomic mass unit-joule relationship СпіввідношеннÑ� атомної одиниці маÑ�и й джоулÑ� atomic mass unit-kelvin relationship СпіввідношеннÑ� атомної одиниці маÑ�и й кельвіна atomic mass unit-kilogram relationship СпіввідношеннÑ� атомної одиниці маÑ�и й кілограма atomic unit of 1st hyperpolarizability Ð�томна одиницÑ� гіперполÑ�ризовноÑ�ті 1-го порÑ�дку atomic unit of 2nd hyperpolarizability Ð�томна одиницÑ� гіперполÑ�ризовноÑ�ті 2-го порÑ�дку atomic unit of charge (e) Ð�томна одиницÑ� зарÑ�ду (e) atomic unit of charge density Ð�томна одиницÑ� гуÑ�тини зарÑ�ду atomic unit of current Ð�томна одиницÑ� Ñ�труму atomic unit of electric dipole moment Ð�томна одиницÑ� електричного дипольного моменту atomic unit of electric field Ð�томна одиницÑ� електричного полÑ� atomic unit of electric field gradient Ð�томна одиницÑ� градієнта електричного полÑ� atomic unit of electric polarizability Ð�томна одиницÑ� електричної полÑ�ризовноÑ�ті atomic unit of electric potential Ð�томна одиницÑ� електричного потенціалу atomic unit of electric quadrupole moment Ð�томна одиницÑ� електричного квадрупольного моменту atomic unit of action Ð�томна одиницÑ� дії atomic unit of energy Ð�томна одиницÑ� енергії atomic unit of force Ð�томна одиницÑ� Ñ�или atomic unit of length Ð�томна одиницÑ� довжини hertz-atomic mass unit relationship СпіввідношеннÑ� герца й атомної одиниці маÑ�и hertz-electron volt relationship СпіввідношеннÑ� герца й електронвольта hertz-hartree relationship СпіввідношеннÑ� герца й гартрі hertz-inverse meter relationship СпіввідношеннÑ� герца й оберненого метра hertz-joule relationship СпіввідношеннÑ� герца й джоулÑ� hertz-kelvin relationship СпіввідношеннÑ� герца й кельвіна hertz-kilogram relationship СпіввідношеннÑ� герца й кілограма hyperfine transition frequency of Cs-133 ЧаÑ�тота надтонкого переходу Cs-133 inverse fine-structure constant (αâ�»Â¹) Обернена Ñ�тала тонкої Ñ�труктури (αâ�»Â¹) inverse meter-atomic mass unit relationship СпіввідношеннÑ� оберненого метра й атомної одиниці маÑ�и inverse meter-electron volt relationship СпіввідношеннÑ� оберненого метра й електронвольта inverse meter-hartree relationship СпіввідношеннÑ� оберненого метра й гартрі inverse meter-hertz relationship СпіввідношеннÑ� оберненого метра й герца inverse meter-joule relationship СпіввідношеннÑ� оберненого метра й джоулÑ� inverse meter-kelvin relationship СпіввідношеннÑ� оберненого метра й кельвіна inverse meter-kilogram relationship СпіввідношеннÑ� оберненого метра й кілограма joule-atomic mass unit relationship СпіввідношеннÑ� джоулÑ� й атомної одиниці маÑ�и joule-electron volt relationship СпіввідношеннÑ� джоулÑ� й електронвольта joule-hertz relationship СпіввідношеннÑ� джоулÑ� й герца joule-hartree relationship СпіввідношеннÑ� джоулÑ� й гартрі joule-inverse meter relationship СпіввідношеннÑ� джоулÑ� й оберненого метра joule-kelvin relationship СпіввідношеннÑ� джоулÑ� й кельвіна joule-kilogram relationship СпіввідношеннÑ� джоулÑ� й кілограма kelvin-atomic mass unit relationship СпіввідношеннÑ� кельвіна й атомної одиниці маÑ�и kelvin-electron volt relationship СпіввідношеннÑ� кельвіна й електронвольта kelvin-hertz relationship СпіввідношеннÑ� кельвіна й герца kelvin-hartree relationship СпіввідношеннÑ� кельвіна й гартрі kelvin-inverse meter relationship СпіввідношеннÑ� кельвіна й оберненого метра kelvin-joule relationship СпіввідношеннÑ� кельвіна й джоулÑ� kelvin-kilogram relationship СпіввідношеннÑ� кельвіна й кілограма kilogram-atomic mass unit relationship СпіввідношеннÑ� кілограма й атомної одиниці маÑ�и kilogram-electron volt relationship СпіввідношеннÑ� кілограма й електронвольта kilogram-hertz relationship СпіввідношеннÑ� кілограма й герца kilogram-hartree relationship СпіввідношеннÑ� кілограма й гартрі kilogram-inverse meter relationship СпіввідношеннÑ� кілограма й оберненого метра kilogram-joule relationship СпіввідношеннÑ� кілограма й джоулÑ� kilogram-kelvin relationship СпіввідношеннÑ� кілограма й кельвіна lattice parameter of silicon (a) Параметр ґратки кремнію (a) luminous efficacy Світлова ефективніÑ�ть natural unit of energy Природна одиницÑ� енергії natural unit of energy in MeV Природна одиницÑ� енергії в MeV natural unit of action (â„�) Природна одиницÑ� дії (â„�) natural unit of action in eV·s Природна одиницÑ� дії в eV·s natural unit of length Природна одиницÑ� довжини natural unit of mass Природна одиницÑ� маÑ�и natural unit of momentum Природна одиницÑ� імпульÑ�у natural unit of momentum in MeV/c Природна одиницÑ� імпульÑ�у в MeV/c natural unit of time Природна одиницÑ� чаÑ�у natural unit of velocity Природна одиницÑ� швидкоÑ�ті Rydberg constant times c in Hz Стала Рідберга, помножена на c, в Hz Rydberg constant times hc in eV Стала Рідберга, помножена на hc, в eV Rydberg constant times hc in J Стала Рідберга, помножена на hc, в J Fermi coupling constant Стала зв’Ñ�зку Фермі weak mixing angle Кут Ñ�лабкого змішуваннÑ� W to Z mass ratio ВідношеннÑ� маÑ� W Ñ– Z Thomson cross section (σₑ) Переріз ТомÑ�она (σₑ) electron mass (mâ‚‘) МаÑ�а електрона (mâ‚‘) electron mass in u МаÑ�а електрона в u electron mass energy equivalent (mₑ·c²) Енергетичний еквівалент маÑ�и електрона (mₑ·c²) electron mass energy equivalent in MeV Енергетичний еквівалент маÑ�и електрона в MeV reduced Compton wavelength Зведена комптонівÑ�ька довжина хвилі classical electron radius (râ‚‘) КлаÑ�ичний радіуÑ� електрона (râ‚‘) electron charge to mass quotient ВідношеннÑ� зарÑ�ду електрона до маÑ�и electron-deuteron magnetic moment ratio ВідношеннÑ� магнітних моментів електрона й дейтрона electron-deuteron mass ratio ВідношеннÑ� маÑ�и електрона до маÑ�и дейтрона electron g factor (gâ‚‘) g-фактор електрона (gâ‚‘) electron gyromagnetic ratio (γₑ) Гіромагнітне відношеннÑ� електрона (γₑ) electron gyromagnetic ratio in MHz/T Гіромагнітне відношеннÑ� електрона в MHz/T electron-helion mass ratio ВідношеннÑ� маÑ�и електрона до маÑ�и геліона electron magnetic moment (μₑ) Магнітний момент електрона (μₑ) electron magnetic moment anomaly (aâ‚‘) Ð�номаліÑ� магнітного моменту електрона (aâ‚‘) electron magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту електрона до магнетона Бора electron magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту електрона до Ñ�дерного магнетона electron molar mass (Mâ‚‘) МолÑ�рна маÑ�а електрона (Mâ‚‘) electron-muon magnetic moment ratio ВідношеннÑ� магнітних моментів електрона й мюона electron-muon mass ratio ВідношеннÑ� маÑ�и електрона до маÑ�и мюона electron-neutron magnetic moment ratio ВідношеннÑ� магнітних моментів електрона й нейтрона electron-neutron mass ratio ВідношеннÑ� маÑ�и електрона до маÑ�и нейтрона electron-proton magnetic moment ratio ВідношеннÑ� магнітних моментів електрона й протона electron-proton mass ratio ВідношеннÑ� маÑ�и електрона до маÑ�и протона electron relative atomic mass (Ar(e)) ВідноÑ�на атомна маÑ�а електрона (Ar(e)) electron-tau mass ratio ВідношеннÑ� маÑ�и електрона до маÑ�и тау electron to alpha particle mass ratio ВідношеннÑ� маÑ�и електрона до маÑ�и альфа-чаÑ�тинки electron to shielded helion magnetic moment ratio ВідношеннÑ� магнітного моменту електрона до магнітного моменту екранованого геліона electron to shielded proton magnetic moment ratio ВідношеннÑ� магнітного моменту електрона до магнітного моменту екранованого протона electron-triton mass ratio ВідношеннÑ� маÑ�и електрона до маÑ�и тритона electron volt-atomic mass unit relationship СпіввідношеннÑ� електронвольта й атомної одиниці маÑ�и electron volt-hartree relationship СпіввідношеннÑ� електронвольта й гартрі electron volt-hertz relationship СпіввідношеннÑ� електронвольта й герца electron volt-inverse meter relationship СпіввідношеннÑ� електронвольта й оберненого метра electron volt-joule relationship СпіввідношеннÑ� електронвольта й джоулÑ� electron volt-kelvin relationship СпіввідношеннÑ� електронвольта й кельвіна electron volt-kilogram relationship СпіввідношеннÑ� електронвольта й кілограма hartree-atomic mass unit relationship СпіввідношеннÑ� гартрі й атомної одиниці маÑ�и hartree-electron volt relationship СпіввідношеннÑ� гартрі й електронвольта muon Compton wavelength КомптонівÑ�ька довжина хвилі мюона muon-electron mass ratio ВідношеннÑ� маÑ�и мюона до маÑ�и електрона muon g factor g-фактор мюона muon magnetic moment Магнітний момент мюона muon magnetic moment anomaly Ð�номаліÑ� магнітного моменту мюона muon magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту мюона до магнетона Бора muon magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту мюона до Ñ�дерного магнетона muon mass МаÑ�а мюона muon mass energy equivalent Енергетичний еквівалент маÑ�и мюона muon mass energy equivalent in MeV Енергетичний еквівалент маÑ�и мюона в MeV muon mass in u МаÑ�а мюона в u muon molar mass МолÑ�рна маÑ�а мюона muon-neutron mass ratio ВідношеннÑ� маÑ�и мюона до маÑ�и нейтрона muon-proton magnetic moment ratio ВідношеннÑ� магнітних моментів мюона й протона muon-proton mass ratio ВідношеннÑ� маÑ�и мюона до маÑ�и протона muon-tau mass ratio ВідношеннÑ� маÑ�и мюона до маÑ�и тау reduced muon Compton wavelength Зведена комптонівÑ�ька довжина хвилі мюона reduced tau Compton wavelength Зведена комптонівÑ�ька довжина хвилі тау tau Compton wavelength КомптонівÑ�ька довжина хвилі тау tau-electron mass ratio ВідношеннÑ� маÑ�и тау до маÑ�и електрона tau mass МаÑ�а тау tau mass energy equivalent Енергетичний еквівалент маÑ�и тау tau mass in u МаÑ�а тау в u tau molar mass МолÑ�рна маÑ�а тау tau-muon mass ratio ВідношеннÑ� маÑ�и тау до маÑ�и мюона tau-neutron mass ratio ВідношеннÑ� маÑ�и тау до маÑ�и нейтрона tau-proton mass ratio ВідношеннÑ� маÑ�и тау до маÑ�и протона proton charge to mass quotient ВідношеннÑ� зарÑ�ду протона до маÑ�и proton Compton wavelength КомптонівÑ�ька довжина хвилі протона proton-electron mass ratio ВідношеннÑ� маÑ�и протона до маÑ�и електрона proton g factor (gₚ) g-фактор протона (gₚ) proton gyromagnetic ratio (γₚ) Гіромагнітне відношеннÑ� протона (γₚ) proton gyromagnetic ratio in MHz/T Гіромагнітне відношеннÑ� протона в MHz/T proton magnetic moment (μₚ) Магнітний момент протона (μₚ) proton magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту протона до магнетона Бора proton magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту протона до Ñ�дерного магнетона proton magnetic shielding correction Поправка магнітного екрануваннÑ� протона proton mass (mₚ) МаÑ�а протона (mₚ) proton mass energy equivalent Енергетичний еквівалент маÑ�и протона proton mass energy equivalent in MeV Енергетичний еквівалент маÑ�и протона в MeV proton mass in u МаÑ�а протона в u proton molar mass (Mₚ) МолÑ�рна маÑ�а протона (Mₚ) proton-muon mass ratio ВідношеннÑ� маÑ�и протона до маÑ�и мюона proton-neutron magnetic moment ratio ВідношеннÑ� магнітних моментів протона й нейтрона proton-neutron mass ratio ВідношеннÑ� маÑ�и протона до маÑ�и нейтрона proton relative atomic mass (Ar(p)) ВідноÑ�на атомна маÑ�а протона (Ar(p)) proton rms charge radius Середньоквадратичний радіуÑ� зарÑ�ду протона proton-tau mass ratio ВідношеннÑ� маÑ�и протона до маÑ�и тау reduced proton Compton wavelength Зведена комптонівÑ�ька довжина хвилі протона shielded proton gyromagnetic ratio Гіромагнітне відношеннÑ� екранованого протона shielded proton gyromagnetic ratio in MHz/T Гіромагнітне відношеннÑ� екранованого протона в MHz/T shielded proton magnetic moment Магнітний момент екранованого протона shielded proton magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту екранованого протона до магнетона Бора shielded proton magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту екранованого протона до Ñ�дерного магнетона neutron Compton wavelength КомптонівÑ�ька довжина хвилі нейтрона neutron-electron magnetic moment ratio ВідношеннÑ� магнітних моментів нейтрона й електрона neutron-electron mass ratio ВідношеннÑ� маÑ�и нейтрона до маÑ�и електрона neutron g factor (gâ‚™) g-фактор нейтрона (gâ‚™) neutron gyromagnetic ratio (γₙ) Гіромагнітне відношеннÑ� нейтрона (γₙ) neutron gyromagnetic ratio in MHz/T Гіромагнітне відношеннÑ� нейтрона в MHz/T neutron magnetic moment (μₙ) Магнітний момент нейтрона (μₙ) neutron magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту нейтрона до магнетона Бора neutron magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту нейтрона до Ñ�дерного магнетона neutron mass (mâ‚™) МаÑ�а нейтрона (mâ‚™) neutron mass energy equivalent Енергетичний еквівалент маÑ�и нейтрона neutron mass energy equivalent in MeV Енергетичний еквівалент маÑ�и нейтрона в MeV neutron mass in u МаÑ�а нейтрона в u neutron molar mass (Mâ‚™) МолÑ�рна маÑ�а нейтрона (Mâ‚™) neutron-muon mass ratio ВідношеннÑ� маÑ�и нейтрона до маÑ�и мюона neutron-proton magnetic moment ratio ВідношеннÑ� магнітних моментів нейтрона й протона neutron-proton mass difference РізницÑ� маÑ� нейтрона й протона neutron-proton mass difference energy equivalent Енергетичний еквівалент різниці маÑ� нейтрона й протона neutron-proton mass difference energy equivalent in MeV Енергетичний еквівалент різниці маÑ� нейтрона й протона в MeV neutron-proton mass difference in u РізницÑ� маÑ� нейтрона й протона в u neutron-proton mass ratio ВідношеннÑ� маÑ�и нейтрона до маÑ�и протона neutron relative atomic mass (Ar(n)) ВідноÑ�на атомна маÑ�а нейтрона (Ar(n)) neutron-tau mass ratio ВідношеннÑ� маÑ�и нейтрона до маÑ�и тау neutron to shielded proton magnetic moment ratio ВідношеннÑ� магнітного моменту нейтрона до магнітного моменту екранованого протона reduced neutron Compton wavelength Зведена комптонівÑ�ька довжина хвилі нейтрона deuteron-electron magnetic moment ratio ВідношеннÑ� магнітних моментів дейтрона й електрона deuteron-electron mass ratio ВідношеннÑ� маÑ�и дейтрона до маÑ�и електрона deuteron g factor g-фактор дейтрона deuteron magnetic moment Магнітний момент дейтрона deuteron magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту дейтрона до магнетона Бора deuteron magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту дейтрона до Ñ�дерного магнетона deuteron mass МаÑ�а дейтрона deuteron mass energy equivalent Енергетичний еквівалент маÑ�и дейтрона deuteron mass energy equivalent in MeV Енергетичний еквівалент маÑ�и дейтрона в MeV deuteron mass in u МаÑ�а дейтрона в u deuteron molar mass МолÑ�рна маÑ�а дейтрона deuteron-neutron magnetic moment ratio ВідношеннÑ� магнітних моментів дейтрона й нейтрона deuteron-proton magnetic moment ratio ВідношеннÑ� магнітних моментів дейтрона й протона deuteron-proton mass ratio ВідношеннÑ� маÑ�и дейтрона до маÑ�и протона deuteron relative atomic mass (Ar(d)) ВідноÑ�на атомна маÑ�а дейтрона (Ar(d)) deuteron rms charge radius Середньоквадратичний радіуÑ� зарÑ�ду дейтрона triton-electron mass ratio ВідношеннÑ� маÑ�и тритона до маÑ�и електрона triton g factor (gₜ) g-фактор тритона (gₜ) triton magnetic moment (μₜ) Магнітний момент тритона (μₜ) triton magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту тритона до магнетона Бора triton magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту тритона до Ñ�дерного магнетона triton mass (mₜ) МаÑ�а тритона (mₜ) triton mass energy equivalent Енергетичний еквівалент маÑ�и тритона triton mass energy equivalent in MeV Енергетичний еквівалент маÑ�и тритона в MeV triton mass in u МаÑ�а тритона в u triton molar mass (Mₜ) МолÑ�рна маÑ�а тритона (Mₜ) triton-proton mass ratio ВідношеннÑ� маÑ�и тритона до маÑ�и протона triton relative atomic mass (Ar(t)) ВідноÑ�на атомна маÑ�а тритона (Ar(t)) triton to proton magnetic moment ratio ВідношеннÑ� магнітного моменту тритона до магнітного моменту протона helion-electron mass ratio ВідношеннÑ� маÑ�и геліона до маÑ�и електрона helion g factor (gâ‚•) g-фактор геліона (gâ‚•) helion magnetic moment (μₕ) Магнітний момент геліона (μₕ) helion magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту геліона до магнетона Бора helion magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту геліона до Ñ�дерного магнетона helion mass (mâ‚•) МаÑ�а геліона (mâ‚•) helion mass energy equivalent Енергетичний еквівалент маÑ�и геліона helion mass energy equivalent in MeV Енергетичний еквівалент маÑ�и геліона в MeV helion mass in u МаÑ�а геліона в u helion molar mass (Mâ‚•) МолÑ�рна маÑ�а геліона (Mâ‚•) helion-proton mass ratio ВідношеннÑ� маÑ�и геліона до маÑ�и протона helion relative atomic mass (Ar(h)) ВідноÑ�на атомна маÑ�а геліона (Ar(h)) helion shielding shift ЗÑ�ув екрануваннÑ� геліона shielded helion gyromagnetic ratio Гіромагнітне відношеннÑ� екранованого геліона shielded helion gyromagnetic ratio in MHz/T Гіромагнітне відношеннÑ� екранованого геліона в MHz/T shielded helion magnetic moment Магнітний момент екранованого геліона shielded helion magnetic moment to Bohr magneton ratio ВідношеннÑ� магнітного моменту екранованого геліона до магнетона Бора shielded helion magnetic moment to nuclear magneton ratio ВідношеннÑ� магнітного моменту екранованого геліона до Ñ�дерного магнетона shielded helion to proton magnetic moment ratio ВідношеннÑ� магнітного моменту екранованого геліона до магнітного моменту протона shielded helion to shielded proton magnetic moment ratio ВідношеннÑ� магнітного моменту екранованого геліона до магнітного моменту екранованого протона alpha particle mass МаÑ�а альфа-чаÑ�тинки alpha particle mass in u МаÑ�а альфа-чаÑ�тинки в u alpha particle mass energy equivalent Енергетичний еквівалент маÑ�и альфа-чаÑ�тинки alpha particle mass energy equivalent in MeV Енергетичний еквівалент маÑ�и альфа-чаÑ�тинки в MeV alpha particle-electron mass ratio ВідношеннÑ� маÑ�и альфа-чаÑ�тинки до маÑ�и електрона alpha particle-proton mass ratio ВідношеннÑ� маÑ�и альфа-чаÑ�тинки до маÑ�и протона alpha particle rms charge radius Ð�льфа-чаÑ�тинка Ñ�ередньоквадратичний радіуÑ� зарÑ�ду alpha particle molar mass МолÑ�рна маÑ�а альфа-чаÑ�тинки alpha particle relative atomic mass (Ar(α)) ВідноÑ�на атомна маÑ�а альфа-чаÑ�тинки (Ar(α)) atomic mass constant (mᵤ) Стала атомної маÑ�и (mᵤ) Avogadro constant Стала Ð�вогадро Boltzmann constant (k) Стала Больцмана (k) Boltzmann constant in eV/K Стала Больцмана в eV/K Boltzmann constant in Hz/K Стала Больцмана в Hz/K Boltzmann constant in inverse meter per kelvin Стала Больцмана в обернених метрах на кельвін electron volt (eV) Електронвольт (eV) Faraday constant (F) Стала ФарадеÑ� (F) first radiation constant (câ‚�) Перша радіаційна Ñ�тала (câ‚�) first radiation constant for spectral radiance Перша радіаційна Ñ�тала длÑ� Ñ�пектральної Ñ�Ñ�кравоÑ�ті molar gas constant (R) МолÑ�рна газова Ñ�тала (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Стала Лошмідта (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Стала Лошмідта (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant МолÑ�рна Ñ�тала Планка second radiation constant (câ‚‚) Друга радіаційна Ñ�тала (câ‚‚) Stefan-Boltzmann constant (σ) Стала Стефана-Больцмана (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ВідÑ�тань між площинами ґратки ідеального Si (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent Енергетичний еквівалент Ñ�талої атомної маÑ�и atomic mass constant energy equivalent in MeV Енергетичний еквівалент Ñ�талої атомної маÑ�и в MeV atomic mass unit-electron volt relationship СпіввідношеннÑ� атомної одиниці маÑ�и й електронвольта molar mass constant (Mᵤ) Стала молÑ�рної маÑ�и (Mᵤ) molar mass of carbon-12 МолÑ�рна маÑ�а вуглецю-12 molar volume of ideal gas (273.15 K, 100 kPa) МолÑ�рний об’єм ідеального газу (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) МолÑ�рний об’єм ідеального газу (273.15 K, 101.325 kPa) molar volume of silicon МолÑ�рний об’єм кремнію Sackur-Tetrode constant (1 K, 100 kPa) Стала Сакура-Тетрода (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Стала Сакура-Тетрода (1 K, 101.325 kPa) Wien frequency displacement law constant Стала закону зміщеннÑ� Віна за чаÑ�тотою Wien wavelength displacement law constant Стала закону зміщеннÑ� Віна длÑ� довжини хвилі standard atmosphere (atm) Стандартна атмоÑ�фера (atm) standard-state pressure (p°) Стандартний тиÑ�к Ñ�тану (p°) Angstrom star (Ã…*) Ð�нгÑ�трем-зірка (Ã…*) Copper x unit Мідна x-одиницÑ� Molybdenum x unit Молібденова x-одиницÑ� atomic unit of magnetizability Ð�томна одиницÑ� магнітизовноÑ�ті atomic unit of mass (mâ‚‘) Ð�томна одиницÑ� маÑ�и (mâ‚‘) atomic unit of momentum Ð�томна одиницÑ� імпульÑ�у atomic unit of permittivity Ð�томна одиницÑ� проникноÑ�ті atomic unit of time Ð�томна одиницÑ� чаÑ�у atomic unit of velocity Ð�томна одиницÑ� швидкоÑ�ті hartree-hertz relationship СпіввідношеннÑ� гартрі й герца hartree-inverse meter relationship СпіввідношеннÑ� гартрі й оберненого метра hartree-joule relationship СпіввідношеннÑ� гартрі й джоулÑ� hartree-kelvin relationship СпіввідношеннÑ� гартрі й кельвіна hartree-kilogram relationship СпіввідношеннÑ� гартрі й кілограма shielding difference of d and p in HD РізницÑ� екрануваннÑ� d Ñ– p в HD shielding difference of t and p in HT РізницÑ� екрануваннÑ� t Ñ– p в HT pi (Ï€) пі (Ï€) Euler's number (e) ЧиÑ�ло Ейлера (e) golden ratio (φ) Золотий перетин (φ) Euler-Mascheroni constant (γ) Стала Ейлера-МаÑ�кероні (γ) nominal solar radius Ð�омінальний радіуÑ� СонцÑ� nominal solar total irradiance Ð�омінальна повна опроміненіÑ�ть СонцÑ� nominal solar luminosity Ð�омінальна Ñ�вітніÑ�ть СонцÑ� nominal solar effective temperature Ð�омінальна ефективна температура СонцÑ� nominal solar mass parameter Ð�омінальний гравітаційний параметр СонцÑ� nominal terrestrial equatorial radius Ð�омінальний екваторіальний радіуÑ� Землі nominal terrestrial polar radius Ð�омінальний полÑ�рний радіуÑ� Землі nominal terrestrial mass parameter Ð�омінальний гравітаційний параметр Землі nominal jovian equatorial radius Ð�омінальний екваторіальний радіуÑ� Юпітера nominal jovian polar radius Ð�омінальний полÑ�рний радіуÑ� Юпітера nominal jovian mass parameter Ð�омінальний гравітаційний параметр Юпітера average value of one minus the rate of TCG relative to TCB Середнє значеннÑ� одиниці мінуÑ� темп TCG відноÑ�но TCB solar mass parameter (TCB-compatible) Гравітаційний параметр СонцÑ� (Ñ�уміÑ�ний з TCB) solar mass parameter (TDB-compatible) Гравітаційний параметр СонцÑ� (Ñ�уміÑ�ний з TDB) equatorial radius of the Earth (TT-compatible) Екваторіальний радіуÑ� Землі (Ñ�уміÑ�ний з TT) dynamical form factor of the Earth Динамічний форм-фактор Землі time rate of change in the dynamical form factor of the Earth Темп зміни динамічного форм-фактора Землі geocentric gravitational constant (TCB-compatible) Геоцентрична гравітаційна Ñ�тала (Ñ�уміÑ�на з TCB) geocentric gravitational constant (TT-compatible) Геоцентрична гравітаційна Ñ�тала (Ñ�уміÑ�на з TT) geocentric gravitational constant (TDB-compatible) Геоцентрична гравітаційна Ñ�тала (Ñ�уміÑ�на з TDB) potential of the geoid Потенціал геоїда nominal mean angular velocity of the Earth (TT-compatible) Ð�омінальна Ñ�ереднÑ� кутова швидкіÑ�ть Землі (Ñ�уміÑ�на з TT) ratio mass of the Moon to the Earth ВідношеннÑ� маÑ�и МіÑ�Ñ�цÑ� до маÑ�и Землі ratio of the mass of the Sun to Mercury ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и МеркуріÑ� ratio of the mass of the Sun to Venus ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и Венери ratio of the mass of the Sun to Mars ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и МарÑ�а ratio of the mass of the Sun to Jupiter ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и Юпітера ratio of the mass of the Sun to Saturn ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и Сатурна ratio of the mass of the Sun to Uranus ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и Урана ratio of the mass of the Sun to Neptune ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и Ð�ептуна ratio of the mass of the Sun to (134340) Pluto ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и (134340) Плутона ratio of the mass of the Sun to (136199) Eris ВідношеннÑ� маÑ�и СонцÑ� до маÑ�и (136199) Ериди ratio of the mass of (1) Ceres to the Sun ВідношеннÑ� маÑ�и (1) Церери до маÑ�и СонцÑ� ratio of the mass of (2) Pallas to the Sun ВідношеннÑ� маÑ�и (2) Паллади до маÑ�и СонцÑ� ratio of the mass of (4) Vesta to the Sun ВідношеннÑ� маÑ�и (4) ВеÑ�ти до маÑ�и СонцÑ� mean obliquity of the ecliptic at J2000.0 Середній нахил екліптики на J2000.0 Electromagnetic Електромагнітні Compton wavelength КомптонівÑ�ька довжина хвилі Astronomy Ð�Ñ�трономіÑ� ConstantsWidget Domain ОблаÑ�ть Subdomain ПідоблаÑ�ть No match found Збігів не знайдено Name Ім'Ñ� Value ЗначеннÑ� Unit Од. виміру Search Пошук All УÑ�Ñ– CustomKeypadDialog Custom Keypad ВлаÑ�на клавіатура Rows: РÑ�дки: Columns: Стовпці: Copy preset: Копіювати шаблон: Basic Базова Scientific (wide) Ð�аукова (широка) Scientific (narrow) Ð�аукова (вузька) Apply ЗаÑ�тоÑ�увати Row РÑ�док Column Стовпець Label Мітка Behavior Поведінка Text ТекÑ�Ñ‚ DiagnosticsDialog App Diagnostics ДіагноÑ�тика заÑ�тоÑ�унку Copy to Clipboard Копіювати до буфера обміну Editor Unit ОдиницÑ� User unit КориÑ�тувацька одиницÑ� User function ФункціÑ� кориÑ�тувача Argument Ð�ргумент Current result:<br/>%1 Поточний результат:<br/>%1 Selection result:<br/>%1 Результат вибору:<br/>%1 Selection result: n/a Вибраний результат: н/д (не визначено) Selection result: %1 Вибраний результат: %1 second Ñ�екунда metre метр kilogram кілограм mole моль radian радіан steradian Ñ�терадіан degree Celsius градуÑ� ЦельÑ�Ñ–Ñ� cubic metre кубічний метр cubic millimetre кубічний міліметр cubic centimetre кубічний Ñ�антиметр cubic decimetre кубічний дециметр cubic kilometre кубічний кілометр square millimetre квадратний міліметр square kilometre квадратний кілометр square metre квадратний метр minute хвилина hour година day день astronomical unit аÑ�трономічна одиницÑ� degree градуÑ� arcminute кутова мінута arcsecond кутова Ñ�екунда milliarcsecond мілікутова Ñ�екунда microarcsecond мікрокутова Ñ�екунда hectare гектар litre літр tonne тонна Dalton дальтон electronvolt електронвольт Angstrom ангÑ�трем atmosphere атмоÑ�фера atomic mass unit атомна одиницÑ� маÑ�и British thermal unit британÑ�ька теплова одиницÑ� calorie калоріÑ� carat карат cup чашка cup (Imperial) чашка (імперÑ�ька) cup (Japanese) чашка (Ñ�понÑ�ька) cup (US) чашка (СШÐ�) degree Fahrenheit градуÑ� Фаренгейта fathom Ñ�ажень fluid ounce (Imperial) рідка унціÑ� (імперÑ�ька) fluid ounce (US) рідка унціÑ� (СШÐ�) fluid dram (Imperial) рідка драхма (імперÑ�ька) fluid dram (US) рідка драхма (СШÐ�) foot фут square foot квадратний фут cubic foot кубічний фут gallon (Imperial) галон (імперÑ�ький) gallon (US) галон (СШÐ�) gill (Imperial) джил (імперÑ�ький) gill (US) джил (СШÐ�) gradian град grain гран gram грам Hartley гартлі Hartree energy unit одиницÑ� енергії Гартрі horsepower кінÑ�ька Ñ�ила inch дюйм square inch квадратний дюйм cubic inch кубічний дюйм karat карат knot вузол lightminute Ñ�вітлова хвилина lightsecond Ñ�вітлова Ñ�екунда lightyear Ñ�вітловий рік long ton довга тонна mile милÑ� square mile квадратна милÑ� cubic mile кубічна милÑ� mile per hour милÑ� на годину kilometre per hour кілометр на годину nautical mile морÑ�ька милÑ� ounce унціÑ� parsec парÑ�ек pint (Imperial) пінта (імперÑ�ька) pint (US) пінта (СШÐ�) pound фунт pounds per square inch фунти на квадратний дюйм quart (Imperial) кварта (імперÑ�ька) quart (US) кварта (СШÐ�) oil barrel нафтовий барель beer barrel (US) пивний барель (СШÐ�) square yard квадратний Ñ�рд cubic yard кубічний Ñ�рд short ton коротка тонна tablespoon Ñ�толова ложка tablespoon (Australian) Ñ�толова ложка (авÑ�тралійÑ�ька) tablespoon (Imperial) Ñ�толова ложка (імперÑ�ька) tablespoon (US) Ñ�толова ложка (СШÐ�) dessert spoon деÑ�ертна ложка teaspoon чайна ложка teaspoon (Imperial) чайна ложка (імперÑ�ька) teaspoon (US) чайна ложка (СШÐ�) turn оберт revolution оберт revolution per minute оберт за хвилину week тиждень kilowatt hour кіловат-година millimetre of mercury міліметр ртутного Ñ�товпа yard Ñ�рд Julian century юліанÑ�ьке Ñ�толіттÑ� Julian year юліанÑ�ький рік sidereal year Ñ�идеричний рік tropical year тропічний рік Evaluator invalid expression вираз недійÑ�ний division by zero діленнÑ� на нуль too time consuming - computation was rejected занадто багато чаÑ�у - обчиÑ�леннÑ� було відхилено dimension mismatch - quantities with different dimensions cannot be compared, added, etc. невідповідніÑ�ть розміроÑ�тей - величини з різними розмірноÑ�Ñ‚Ñ�ми не можна порівнювати, додавати тощо. invalid dimension - operation might require dimensionless arguments недійÑ�на розмірніÑ�ть - длÑ� операції можуть знадобитиÑ�Ñ� аргументи без розмірноÑ�ті Computation aborted - encountered numerical instability ОбчиÑ�леннÑ� перервано – виÑ�влено чиÑ�ельну неÑ�табільніÑ�ть invalid dimension - function might require dimensionless arguments недійÑ�на розмірніÑ�ть - функціÑ� може потребувати аргументи без розмірноÑ�ті error помилка unit must not be zero елемент не повинен дорівнювати нулю Conversion failed - dimension mismatch Помилка перетвореннÑ� – невідповідніÑ�ть розмірноÑ�ті unknown function or variable невідома функціÑ� або змінна recursion not supported рекурÑ�Ñ–Ñ� не підтримуєтьÑ�Ñ� cannot operate on a NaN не прцює з не-чиÑ�лом underflow - tiny result is out of SpeedCrunch's number range антипереповненнÑ� - надто малий результат виходить за межі діапазону чиÑ�ел SpeedCrunch overflow - huge result is out of SpeedCrunch's number range переповненнÑ� - надто великий результат виходить за межі діапазону чиÑ�ел SpeedCrunch overflow - logic result exceeds maximum of 256 bits переповненнÑ� - логічний результат перевищує макÑ�имум 256 біт overflow - integer result exceeds maximum limit for integers переповненнÑ� - цілочиÑ�ельний результат перевищує макÑ�имальний ліміт длÑ� цілих чиÑ�ел operation is not defined for these arguments операцію не визначено длÑ� цих аргументів wrong number of arguments неправильна кількіÑ�ть аргументів does not take NaN as an argument не приймає не-чиÑ�ло Ñ�к аргумент result out of range результат за межами діапазону undefined for argument domain не визначено длÑ� облаÑ�ті аргументу computation too expensive занадто витратне обчиÑ�леннÑ� internal error, please report a bug внутрішнÑ� помилка, повідомте про помилку syntax error Ñ�интакÑ�ична помилка conversion target must be a unit ціль перетвореннÑ� має бути одиницею unknown unit невідома одиницÑ� %1 is a reserved name, please choose another %1 це зарезервована назва, виберіть іншу %1 is a global user definition and cannot be overridden in this session. %1 Ñ” глобальним кориÑ�тувацьким визначеннÑ�м Ñ– не може бути перевизначено в цьому Ñ�еанÑ�Ñ–. %1 is a variable name, please choose another or delete the variable %1 це ім'Ñ� змінної, виберіть інше або видаліть змінну argument %1 is used more than once аргумент %1 викориÑ�товуєтьÑ�Ñ� більше одного разу %1 is a built-in unit name, please choose another %1 Ñ” назвою вбудованої одиниці, виберіть іншу %1 is a user function name, please choose another or delete the function %1 це назва функції кориÑ�тувача, виберіть іншу або видаліть функцію FunctionRepo max; trials; probability макÑ�имуми; Ñ�проби; ймовірноÑ�ті trials; probability Ñ�проби; ймовірноÑ�ті hits; trials; probability Ñ�півпаданнÑ�; Ñ�проби; ймовірноÑ�ті max; total; hits; trials макÑ�имуми; вÑ�ього; Ñ�півпадань; Ñ�проб total; hits; trials вÑ�ього; Ñ�півпадань; Ñ�проб count; total; hits; trials підрахунок; вÑ�ього; Ñ�півпадань; Ñ�проб dividend; divisor ділене; дільник x; exponent_bits; significand_bits [; exponent_bias] x; екÑ�понент_біт; мантіÑ�а_біт [; ЕкÑ�понентний_запиÑ�_зміщеннÑ�] base; x оÑ�нова; x value; modulo значеннÑ�; по_модулю base; exponent; modulo оÑ�нова; показник; модуль events; average_events результати; Ñ�ередні_результати average_events Ñ�ередні_результати x [; precision] x [; точніÑ�ть] Absolute Value Ð�бÑ�олютне значеннÑ� Absolute Deviation Ð�бÑ�олютне відхиленнÑ� Arc Cosine Ð�рккоÑ�инуÑ� Logical AND Логічне І Area Hyperbolic Cosine Гіперболічний ареакоÑ�инуÑ� Area Hyperbolic Sine Гіперболічний ареаÑ�инуÑ� Area Hyperbolic Tangent Гіперболічний ареатангенÑ� Arc Sine Ð�ркÑ�инуÑ� Arc Tangent Ð�рктангенÑ� Arc Tangent with two Arguments Ð�рктангенÑ� із двома аргументами Average (Arithmetic Mean) Середнє (Ñ�ереднє арифметичне) Binomial Cumulative Distribution Function Біноміальна функціÑ� розподілу Binomial Distribution Mean Медіана біноміального розподілу Binomial Probability Mass Function Біноміальна функціÑ� маÑ�ової імовірноÑ�ті Binomial Distribution Variance РозбіжніÑ�ть біноміального розподілу Cube Root Кубічний корінь Complex Conjugate КомплекÑ�но-Ñ�получене Cosine КоÑ�инуÑ� Hyperbolic Cosine Гіперболічний коÑ�инуÑ� Cotangent КотангеÑ� Cosecant КоÑ�еканÑ� Convert Unix timestamp to Date ПеретвореннÑ� мітки чаÑ�у Unix на дату Degrees of Arc Радіани в градуÑ�и Error Function ФункціÑ� похибки Complementary Error Function ФункціÑ� додаткової похибки Exponential ЕкÑ�поненціальний Fractional Part Дробова чаÑ�тина Extension of Factorials [= (x-1)!] РозклаÑ�ти факторіал [= (x-1)!] Greatest Common Divisor Ð�айбільший Ñ�пільний дільник Geometric Mean Середнє геометричне Gradians of arc Градіани дуги Hypergeometric Cumulative Distribution Function Гіпергеометрична функціÑ� розподілу Hypergeometric Distribution Mean Медіана гіпергеометричного розподілу Hypergeometric Probability Mass Function Гіпергеометрична функціÑ� маÑ�ової імовірноÑ�ті Hypergeometric Distribution Variance РозбіжніÑ�ть гіпергеометричного розподілу Integer Quotient Ціле чиÑ�ло Integer Part Ціла чаÑ�тина Imaginary Part УÑ�вна чаÑ�тина Decode IEEE-754 Binary Value Декодувати двійкове значеннÑ� IEEE-754 Encode IEEE-754 Binary Value Кодувати двійкове значеннÑ� IEEE-754 Decode 16-bit Half-Precision Value Декодувати значеннÑ� половинної точноÑ�ті 16-біт Encode 16-bit Half-Precision Value Кодувати значеннÑ� половинної точноÑ�ті 16-біт Decode 32-bit Single-Precision Value Декодувати значеннÑ� одинарної точноÑ�ті 32-біт Encode 32-bit Single-Precision Value Кодувати значеннÑ� одинарної точноÑ�ті 32-біт Decode 64-bit Double-Precision Value Декодувати значеннÑ� подвійної точноÑ�ті 64-біт Encode 64-bit Double-Precision Value Кодувати значеннÑ� подвійної точноÑ�ті 64-біт Decode 128-bit Quad-Precision Value Декодувати значеннÑ� чотирикратної точноÑ�ті 128-біт Encode 128-bit Quad-Precision Value Кодувати значеннÑ� чотирикратної точноÑ�ті 128-біт Binary Logarithm Двійковий логарифм Common Logarithm ДеÑ�Ñ�тковий логарифм Natural Logarithm Ð�атуральний логарифм Logarithm to Arbitrary Base Логарифм до довільної оÑ�нови Mask to a bit size Бітова маÑ�ка Maximum МакÑ�имум Median Value (50th Percentile) Медіанне значеннÑ� (50-й процентиль) Minimum Мінімум Modulo По модулю Euclidean Modulo Евклідів модуль Modular Exponentiation Модульне піднеÑ�еннÑ� до Ñ�тепенÑ� Combination (Binomial Coefficient) КомбінаціÑ� (біноміальний коефіцієнт) Logical NOT Логічне Ð�І Permutation (Arrangement) ПереÑ�тановка (РозташуваннÑ�) Convert to Binary Representation Перетворити на двійкове поданнÑ� Arithmetic Ð�рифметика Chemistry ХіміÑ� Complex КомплекÑ�ні чиÑ�ла Combinatorics Комбінаторика Probability ЙмовірніÑ�ть Statistics СтатиÑ�тика Aggregation Ð�грегаціÑ� Random Випадкові Base conversion ПеретвореннÑ� оÑ�нови Number formatting ФорматуваннÑ� чиÑ�ел Integer arithmetic ЦілочиÑ�ельна арифметика Special functions Спеціальні функції Exponential & Logarithmic ЕкÑ�поненційні й логарифмічні Angle conversion ПеретвореннÑ� кутів Trigonometry ТригонометріÑ� Bitwise Побітові Floating point Рухома кома Date & Time Дата й чаÑ� Linear algebra Лінійна алгебра unix_timestamp; x hours offset to GMT мітка чаÑ�у Unix; зміщеннÑ� на x годин від GMT yyyymmdd.hhmmss; x hours offset to GMT ррррммдд.ггххÑ�Ñ�; x годин зміщеннÑ� від GMT [digits] [цифри] max [; min] макÑ� [; мін] List Literal Літерал Ñ�пиÑ�ку Convert to Padded Binary Representation Перетворити на двійковий запиÑ� із доповненнÑ�м Round Toward +∞ (Ceiling) Округлити до +∞ (Ñ�телÑ�) Cosine plus Imaginary Sine КоÑ�инуÑ� плюÑ� уÑ�вний Ñ�инуÑ� Convert to Cis Complex Form Перетворити на комплекÑ�ну форму cis Matrix Column Count КількіÑ�ть Ñ�товпців матриці Population Correlation Matrix (n) МатрицÑ� корелÑ�ції генеральної Ñ�укупноÑ�ті (n) Sample Correlation Matrix (n-1) МатрицÑ� корелÑ�ції вибірки (n-1) Count КількіÑ�ть Population Covariance Matrix (n) МатрицÑ� коваріації генеральної Ñ�укупноÑ�ті (n) Sample Covariance Matrix (n-1) МатрицÑ� коваріації вибірки (n-1) Cross Product Векторний добуток Convert Date to Unix timestamp Перетворити дату на мітку чаÑ�у Unix Convert to Decimal Representation Перетворити на деÑ�Ñ�ткове поданнÑ� Determinant Визначник Convert to Sexagesimal Notation Перетворити на шіÑ�тдеÑ�Ñ�тковий запиÑ� Dot Product СкалÑ�рний добуток Convert to Engineering Notation Перетворити на інженерний запиÑ� Convert to Exponential Complex Form Перетворити на екÑ�поненційну комплекÑ�ну форму Round Toward −∞ (Floor) Округлити до −∞ (підлога) Flatten Matrix Сплющити матрицю Least Common Multiple Ð�айменше Ñ�пільне кратне Convert to Hexadecimal Representation Перетворити на шіÑ�тнадцÑ�ткове поданнÑ� Convert to Padded Hexadecimal Representation Перетворити на шіÑ�тнадцÑ�тковий запиÑ� із доповненнÑ�м Inverse Matrix Обернена матрицÑ� Round to 16-bit Half-Precision Value Округлити до 16-бітного значеннÑ� половинної точноÑ�ті Round to 32-bit Single-Precision Value Округлити до 32-бітного значеннÑ� одинарної точноÑ�ті Round to 64-bit Double-Precision Value Округлити до 64-бітного значеннÑ� подвійної точноÑ�ті Round to 128-bit Quad-Precision Value Округлити до 128-бітного значеннÑ� четверної точноÑ�ті Residual from 16-bit Half-Precision Rounding Залишок від округленнÑ� до 16-бітної половинної точноÑ�ті Residual from 32-bit Single-Precision Rounding Залишок від округленнÑ� до 32-бітної одинарної точноÑ�ті Residual from 64-bit Double-Precision Rounding Залишок від округленнÑ� до 64-бітної подвійної точноÑ�ті Residual from 128-bit Quad-Precision Rounding Залишок від округленнÑ� до 128-бітної четверної точноÑ�ті Substance Mass МаÑ�а речовини Molarity МолÑ�рніÑ�ть Molar Mass МолÑ�рна маÑ�а Median Absolute Deviation Медіанне абÑ�олютне відхиленнÑ� Mean Середнє Numerical Value of Quantity ЧиÑ�лове значеннÑ� величини Random Decimal Number Випадкове деÑ�Ñ�ткове чиÑ�ло Random Integer Number Випадкове ціле чиÑ�ло Convert to Rational Representation Перетворити на раціональний запиÑ� Convert to Octal Representation Перетворити на віÑ�імкове поданнÑ� Convert to Padded Octal Representation Перетворити на віÑ�імковий запиÑ� із доповненнÑ�м Vector or Matrix Norm Ð�орма вектора або матриці Logical OR Логічне Ð�БО Population Count (Hamming Weight) КількіÑ�ть одиничних бітів (вага Геммінга) Phase of Complex Number Фаза комплекÑ�ного чиÑ�ла Poissonian Cumulative Distribution Function ФункціÑ� розподілу ПуаÑ�Ñ�она Poissonian Distribution Mean Медіана розподілу ПуаÑ�Ñ�она Poissonian Probability Mass Function ФункціÑ� маÑ�ової імовірноÑ�ті ПуаÑ�Ñ�она Poissonian Distribution Variance РозбіжніÑ�ть розподілу ПуаÑ�Ñ�она Convert to Phasor Complex Form Перетворити на фазорну комплекÑ�ну форму Convert to Rectangular Complex Form Перетворити на прÑ�мокутну комплекÑ�ну форму Round Half Away from Zero Округлити половину від нулÑ� Round Half Even Округлити половину до парного Nth Root Корінь n-го Ñ�тепенÑ� Convert to Scientific Notation Перетворити на науковий запиÑ� Matrix Row Count КількіÑ�ть Ñ€Ñ�дків матриці List or Matrix Shape Форма Ñ�пиÑ�ку або матриці Summation СумуваннÑ� Population Standard Deviation (n) Стандартне відхиленнÑ� генеральної Ñ�укупноÑ�ті (n) Sample Standard Deviation (n-1) Стандартне відхиленнÑ� вибірки (n-1) Round Toward Zero (Truncation) Округлити до нулÑ� (відÑ�іканнÑ�) Matrix Trace Слід матриці Transpose Matrix ТранÑ�понувати матрицю Population Variance (n) ДиÑ�перÑ�Ñ–Ñ� генеральної Ñ�укупноÑ�ті (n) Sample Variance (n-1) ДиÑ�перÑ�Ñ–Ñ� вибірки (n-1) Product Добуток Radians ПеретвореннÑ� градуÑ�ів в радіани Matrix Rank Ранг матриці Real Part ДійÑ�на чаÑ�тина Secant СеканÑ� Arithmetic Shift Left Ð�рифметичний зÑ�ув вліво Arithmetic Shift Right Ð�рифметичний зÑ�ув вправо Signum Знак (від'ємне чи додатне чиÑ�ло) Sine СинуÑ� Hyperbolic Sine Гіперболічний Ñ�инуÑ� Square Root Квадратний корінь Sum Сума Tangent ТангенÑ� Convert to Trigonometric Complex Form Перетворити на тригонометричну комплекÑ�ну форму Turns Оберти Hyperbolic Tangent Гіперболічний тангенÑ� Sign-extend a value Розширене значеннÑ� Logical XOR Логічна виключна диз'юнкціÑ� (XOR) FunctionsWidget Domain ОблаÑ�ть All УÑ�Ñ– Name Ім'Ñ� Search Пошук No match found Збігів не знайдено Identifier Ідентифікатор HistoryWidget Remove All Calculations Above Вилучити вÑ�Ñ– обчиÑ�леннÑ� вище Remove This Calculation Вилучити це обчиÑ�леннÑ� Remove All Calculations Below Вилучити вÑ�Ñ– обчиÑ�леннÑ� нижче Keypad Inverse cosine Ð�рккоÑ�инуÑ� The last result ОÑ�танній результат Inverse sine Ð�ркÑ�инуÑ� Inverse tangent Ð�рктангенÑ� Evaluate expression ОбчиÑ�лити вираз Division ДіленнÑ� Multiplication МноженнÑ� Subtraction ВідніманнÑ� Addition ДодаваннÑ� Clear expression ОчиÑ�тити вираз Cosine КоÑ�инуÑ� Backspace Видалити попередній Ñ�имвол Scientific notation Ð�аукова нотаціÑ� Exponential ЕкÑ�понента Factorial Факторіал Natural logarithm Ð�атуральний логарифм Left parenthesis Ліва дужка Nth root Корінь n-го Ñ�тепенÑ� Argument separator Роздільник аргументів Square Квадрат Common logarithm ДеÑ�Ñ�тковий логарифм Modulo Модуль Contextual percentage КонтекÑ�тний відÑ�оток Power Степінь Right parenthesis Права дужка Sine СинуÑ� Square root Квадратний корінь Tangent ТангенÑ� Pi Пі Decimal separator ДеÑ�Ñ�тковий роздільник MainWindow Radian Радіан Degree ГрадуÑ� Gradian Градіан Binary Двійковий Octal Ð’Ñ–Ñ�імковий Hexadecimal ШіÑ�тнадцÑ�тковий Sexagesimal ШіÑ�тдеÑ�Ñ�тковий Engineering decimal Інженерний Scientific decimal Ð�ауковий &Import... &Імпортувати... &Quit Ви&хід Clear E&xpression ОчиÑ�тити &вираз Clear &History ОчиÑ�тити &Ñ–Ñ�торію &Copy &Копіювати &Paste &Ð’Ñ�тавити &Select Expression &Вибрати вираз &Constants &КонÑ�танти &Functions &Функції &History &ІÑ�торіÑ� &Status Bar &РÑ�док Ñ�тану Bitfield Бітове поле Use&r Functions Функції &кориÑ�тувача &Degree &ГрадуÑ� &Radian &Радіан &Gradian &Градіан Re&volution О&берт Auto-Insert a&ns Ð�втоматично вÑ�тавлÑ�ти a&ns Automatic &Completion Ð�втоматичне &доповненнÑ� &Built-in Functions &Вбудовані функції Built-in &Variables Ð’&будовані змінні User &Functions &Функції кориÑ�тувача User Va&riables &КориÑ�тувацькі змінні Open a Private Tab on Startup Відкривати приватну вкладку під чаÑ� запуÑ�ку Open and focus a new private tab whenever SpeedCrunch starts. Відкривати й активувати нову приватну вкладку під чаÑ� кожного запуÑ�ку SpeedCrunch. Syntax &Highlighting ПідÑ�вічуваннÑ� &Ñ�интакÑ�иÑ�у Group Digits in &Input &Групувати цифри під чаÑ� введеннÑ� Automatic Input &Adjustments &Ð�втоматичне коригуваннÑ� введеннÑ� Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Ð�втоматично коригувати оператори, пробіли, дужки й Ñ�тепені та дозволÑ�ти введеннÑ� лише допуÑ�тимих Ñ�имволів. Group input digits using the selected number format. Групувати введені цифри відповідно до вибраного формату чиÑ�ел. &Blinking Cursor &БлиманнÑ� курÑ�ора Blink the cursor in the expression editor. Увімкнути блиманнÑ� курÑ�ора в редакторі виразів. &Escape Clears Editor &Escape очищає редактор Clear the focused expression editor with Escape after dismissing any popup or preview. Очищати активний редактор виразів клавішею Escape піÑ�лÑ� закриттÑ� Ñ�пливних вікон або попереднього переглÑ�ду. Keep Expression After Evaluation Зберігати вираз піÑ�лÑ� обчиÑ�леннÑ� Copy New Results Automatically Ð�втоматично копіювати нові результати &Comma &Кома &System Default &Типове длÑ� Ñ�иÑ�теми &Dot &Крапка Dot &And Comma Крапка &Ñ– кома Toward +∞ (&ceil) До +∞ (&ceil) Toward −∞ (&floor) До −∞ (&floor) &Binary &Двійковий &Engineering &Інженерний &Hexadecimal &ШіÑ�тнадцÑ�тковий &Octal &Ð’Ñ–Ñ�імковий &Scientific &Ð�ауковий User &Manual ПоÑ�ібник &кориÑ�тувача Issues and &Feedback П&роблеми та відгуки &Donate &Пожертвувати &About SpeedCrunch Про &SpeedCrunch App Diag&nostics &ДіагноÑ�тика заÑ�тоÑ�унку S&plit Роз&ділити Angle &Mode Р&ежим кутів &Complex Form &КомплекÑ�на форма New Tab Ð�ова вкладка Constants КонÑ�танти Functions Функції History ІÑ�торіÑ� User Functions Функції кориÑ�тувача &Font... &Шрифт... &Language... &Мова... &Session &СеанÑ� &Edit &Редагувати &View &ВиглÑ�д Se&ttings Ð�ала&штуваннÑ� &Decimal &ДеÑ�Ñ�тковий &Keypad &Клавіатура Always on &Top Завжди &зверху Disabled Відключено Small Space Малий проміжок Medium Space Середній проміжок Large Space Великий проміжок &0 Digits &0 розрÑ�дів &15 Digits &15 розрÑ�дів &2 Digits &2 розрÑ�ди &3 Digits &3 розрÑ�ди &50 Digits &50 розрÑ�дів &8 Digits &8 розрÑ�дів &Sexagesimal &ШіÑ�тдеÑ�Ñ�тковий Reset All Settings... Скинути вÑ�Ñ– налаштуваннÑ�... &System &СиÑ�тема SpeedCrunch &Theme &Тема SpeedCrunch &Classic &КлаÑ�ичний &Modern &СучаÑ�ний Context Help КонтекÑ�тна довідка &Help &Довідка Error Помилка Can't read from file %1 Ð�еможливо прочитати файл %1 Import Session Імпорт Ñ�еанÑ�у Close Session Закрити Ñ�еанÑ� Angle Mode: Кутовий режим: Notation: ЗапиÑ�: Precision: ТочніÑ�ть: Turn Оберт Revolution Оберт Fixed-point decimal ДеÑ�Ñ�тковий з фікÑ�ованою комою Rational Раціональний Automatic decimal Ð�втоматичний деÑ�Ñ�тковий Automatic Ð�втоматично User &Definitions... КориÑ�тувацькі &визначеннÑ�... New &Tab Ð�ова &вкладка New &Private Tab &Ð�ова приватна вкладка Keep Зберегти Make Private... Зробити приватним... New &Window Ð�ове &вікно &Open... &Відкрити... &Rename... &Перейменувати... Clo&ne... &Клонувати... &Close Tab &Закрити вкладку Reopen Clo&sed Tab Знов&у відкрити закриту вкладку Open Sessions &Folder Відкрити &теку Ñ�еанÑ�ів &Undo &СкаÑ�увати &Redo &Повторити Cu&t Ð’&ирізати Copy &Last Result К&опіювати оÑ�танній результат &Wrap in Parentheses Ð’&зÑ�ти в дужки Full Scr&een Mode &Повноекранний режим &Basic &Базова &Scientific (wide) &Ð�аукова (широка) Scientific (narrow) Ð�аукова (вузька) &Custom... &ВлаÑ�на... Main &Menu Головне &меню User &Variables КориÑ�тувацькі &змінні &Left &Ліворуч &Right &Праворуч &Up &Угору &Down У&низ Close Pa&ne З&акрити панель User &Units КориÑ�тувацькі &одиниці &Turn &Оберт If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Якщо новий вираз починаєтьÑ�Ñ� з +, -, * або /, SpeedCrunch Ñ�початку вÑ�тавлÑ�Ñ” "ans". &Accept with Enter &Приймати клавішею Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Приймати поточну пропозицію автодоповненнÑ� клавішею Enter без попереднього вибору клавішами зі Ñ�трілками. &Units &Одиниці Show Live Result &Preview Показувати попередній &переглÑ�д результату наживо Save &Window Position on Exit Зберігати положеннÑ� &вікна при виході Hover Highlighting ПідÑ�вічуваннÑ� при наведенні Group Integer Part Only Групувати лише цілу чаÑ�тину Number Format... Формат чиÑ�ла... Notation && Precision... ЗапиÑ� Ñ– точніÑ�ть... After pressing Enter, keep the entered expression selected in the editor. ПіÑ�лÑ� натиÑ�каннÑ� Enter залишати введений вираз вибраним у редакторі. Never Ð�іколи Always Завжди Only for Single-Line Expressions Лише длÑ� однорÑ�дкових виразів Simplify Displayed Expressions Спрощувати показані вирази History Size &Limit... &ОбмеженнÑ� розміру Ñ–Ñ�торії... Remove Trailing &Zeroes &ВидалÑ�ти кінцеві нулі Nearest, Half &Away (round) Ð�айближче, половина &від нулÑ� (round) Nearest, Half &Even (roundeven) Ð�айближче, половина до &парного (roundeven) Toward &Zero (trunc) До &нулÑ� (trunc) &Fixed-Point &ФікÑ�ована кома &Rational &Раціональний &Exponential (m·sâ�»Â¹) &ЕкÑ�поненційний (m·sâ�»Â¹) &Fractional (m/s) &Дробовий (m/s) &Rectangular (a + bi) &ПрÑ�мокутний (a + bi) Exponential (reâ�±á¶¿) ЕкÑ�поненційний (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Тригонометричний (r(cos θ + i·sin θ)) Phasor (r∠θ) Фазор (r∠θ) &Theme... &Тема... Check for &Updates Перевірити &оновленнÑ� Source Code Джерельний код &Zoom &МаÑ�штаб &Results &Результати Unit Notation ЗапиÑ� одиниць Rounding Mode Режим округленнÑ� &Notation &ЗапиÑ� &Imaginary Unit &УÑ�вна одиницÑ� &Window &Вікно &Editing &РедагуваннÑ� A&utocomplete Ð�&втодоповненнÑ� Up/Down Arrow History ІÑ�торіÑ� Ñ�трілками вгору/вниз &Appearance &ВиглÑ�д &Menus &Меню &Docks &Панелі з можливіÑ�тю закріпленнÑ� &Input and Results &ВведеннÑ� та результати &Disabled &Вимкнено &Disable &Вимкнути Close preview Закрити попередній переглÑ�д Rename... Перейменувати... Clone... Клонувати... Close Tab Закрити вкладку New Private Tab Ð�ова приватна вкладка Open... Відкрити... Reopen Closed Tab Знову відкрити закриту вкладку Split Розділити Left Ліворуч Right Праворуч Up Угору Down Униз Clear ОчиÑ�тити Delete Видалити %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Приватний Ñ�еанÑ�: вміÑ�Ñ‚ видалÑ�єтьÑ�Ñ� піÑ�лÑ� закриттÑ�. Виберіть СеанÑ� > Зберегти, щоб зробити його звичайним Ñ�еанÑ�ом. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Приватний] Reset All Settings Скинути вÑ�Ñ– налаштуваннÑ� Reset all settings to their default values? Скинути вÑ�Ñ– налаштуваннÑ� до типових значень? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Це включає виглÑ�д, редагуваннÑ�, формати результатів Ñ– параметри вікон. Ваші обчиÑ�леннÑ�, відкриті Ñ�еанÑ�и та кориÑ�тувацькі визначеннÑ� буде збережено. The settings file could not be written. Ð�е вдалоÑ�Ñ� запиÑ�ати файл налаштувань. Clear this session's calculations, unfinished expression, variables, functions, and units? ОчиÑ�тити обчиÑ�леннÑ�, незавершений вираз, змінні, функції та одиниці цього Ñ�еанÑ�у? Global user definitions are kept. Глобальні кориÑ�тувацькі визначеннÑ� зберігаютьÑ�Ñ�. Make Session Private Зробити Ñ�еанÑ� приватним The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Збережений Ñ�еанÑ� %1 буде видалено. Його вміÑ�Ñ‚ залишитьÑ�Ñ� відкритим у приватному Ñ�еанÑ�Ñ– й буде видалений піÑ�лÑ� закриттÑ� цього Ñ�еанÑ�у або виходу зі SpeedCrunch. Make Private Зробити приватним Could not delete the saved session %1. Ð�е вдалоÑ�Ñ� видалити збережений Ñ�еанÑ� %1. Keep Session Зберегти Ñ�еанÑ� Could not save the session. It remains private. Ð�е вдалоÑ�Ñ� зберегти Ñ�еанÑ�. Він залишаєтьÑ�Ñ� приватним. Clone Session Клонувати Ñ�еанÑ� Could not save session file %1. Ð�е вдалоÑ�Ñ� зберегти файл Ñ�еанÑ�у %1. Could not delete session file %1. Ð�е вдалоÑ�Ñ� видалити файл Ñ�еанÑ�у %1. JSON file (*.json);;Any file (*.*) Файл JSON (*.json);;Будь-Ñ�кий файл (*.*) Export session as JSON ЕкÑ�портувати Ñ�еанÑ� Ñ�к JSON The selected file is not valid JSON: %1 Вибраний файл не Ñ” коректним JSON: %1 The selected file is not a SpeedCrunch session JSON file. Вибраний файл не Ñ” JSON-файлом Ñ�еанÑ�у SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Цей файл викориÑ�товує заÑ�тарілий формат Ñ�еанÑ�у SpeedCrunch Ñ– не може бути імпортований. The selected JSON file is missing the required $schema field. У вибраному JSON-файлі бракує обов'Ñ�зкового полÑ� $schema. The selected JSON file uses an unsupported JSON schema: %1 Вибраний JSON-файл викориÑ�товує непідтримувану Ñ�хему JSON: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). У вибраному JSON-файлі бракує ідентифікатора Ñ�хеми Ñ�еанÑ�у SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Вибраний JSON-файл викориÑ�товує непідтримуваний формат Ñ�еанÑ�у SpeedCrunch: %1 The selected JSON file is missing the required session name. У вибраному JSON-файлі бракує обов'Ñ�зкової назви Ñ�еанÑ�у. The selected JSON file has an empty session name. У вибраному JSON-файлі порожнÑ� назва Ñ�еанÑ�у. The selected JSON file has invalid or incomplete SpeedCrunch session data. Вибраний JSON-файл міÑ�тить некоректні або неповні дані Ñ�еанÑ�у SpeedCrunch. Open Sessions Folder Відкрити теку Ñ�еанÑ�ів Could not create the sessions folder: %1 Ð�е вдалоÑ�Ñ� Ñ�творити теку Ñ�еанÑ�ів: %1 Could not open the sessions folder: %1 Ð�е вдалоÑ�Ñ� відкрити теку Ñ�еанÑ�ів: %1 Editor and Results Font Шрифт редактора та результатів Open Session Відкрити Ñ�еанÑ� Community Спільнота Rename Session Перейменувати Ñ�еанÑ� Clear Session ОчиÑ�тити Ñ�еанÑ� Delete Session Видалити Ñ�еанÑ� Close Pane Закрити панель User Variables КориÑ�тувацькі змінні User Units КориÑ�тувацькі одиниці Clear History ОчиÑ�тити Ñ–Ñ�торію Are you sure you want to clear the calculation history? Ви впевнені, що хочете очиÑ�тити Ñ–Ñ�торію обчиÑ�лень? Session name: Ð�азва Ñ�еанÑ�у: A session named %1 already exists. СеанÑ� із назвою %1 уже Ñ–Ñ�нує. Could not create session file %1. Ð�е вдалоÑ�Ñ� Ñ�творити файл Ñ�еанÑ�у %1. Could not write session file %1. Ð�е вдалоÑ�Ñ� запиÑ�ати файл Ñ�еанÑ�у %1. Are you sure you want to delete this session? Ви впевнені, що хочете видалити цей Ñ�еанÑ�? Custom Precision ВлаÑ�на точніÑ�ть Fractional digits: Дробові розрÑ�ди: Theme Тема Light Themes Світлі теми Dark Themes Темні теми Preview Попередній переглÑ�д Colors Кольори Select color for %1 Виберіть колір длÑ� %1 Import... Імпортувати... Export... ЕкÑ�портувати... Import Theme Імпортувати тему Theme file (*.json);;All files (*) Файл теми (*.json);;УÑ�Ñ– файли (*) Invalid theme file. Ð�еприпуÑ�тимий файл теми. Can't import theme "%1" because it conflicts with a built-in theme. Ð�е можна імпортувати тему "%1", бо вона конфліктує з вбудованою темою. Can't find a writable theme folder. Ð�е вдалоÑ�Ñ� знайти придатну длÑ� запиÑ�у теку тем. Overwrite Theme ПерезапиÑ�ати тему A custom theme named "%1" already exists. Do you want to overwrite it? ВлаÑ�на тема з назвою "%1" уже Ñ–Ñ�нує. ПерезапиÑ�ати Ñ—Ñ—? Can't overwrite theme file %1 Ð�е вдалоÑ�Ñ� перезапиÑ�ати файл теми %1 Can't copy theme file to %1 Ð�е вдалоÑ�Ñ� Ñ�копіювати файл теми до %1 Export Theme ЕкÑ�портувати тему Can't export theme as "%1" because it conflicts with a built-in theme. Ð�е можна екÑ�портувати тему Ñ�к "%1", бо вона конфліктує з вбудованою темою. Can't write to file %1 Ð�еможливо запиÑ�ати у файл %1 Global User Variable Глобальна кориÑ�тувацька змінна Global User Function Глобальна кориÑ�тувацька функціÑ� Global User Unit Глобальна кориÑ�тувацька одиницÑ� User Definitions КориÑ�тувацькі визначеннÑ� These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Ці визначеннÑ� Ñ” глобальними та завантажуютьÑ�Ñ� в кожен Ñ�еанÑ�. Їх не можна змінювати в Ñ�еанÑ�ах, Ñ– вони мають пріоритет над однойменними визначеннÑ�ми з редактора Ñ�еанÑ�у. Вводьте по одному визначенню в Ñ€Ñ�дку. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Приклади: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply ЗаÑ�тоÑ�увати Validate Перевірити Test Results Результати перевірки Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Імпортовані змінні: %1 Імпортовані функції: %2 Імпортовані одиниці: %3 Ð�омери Ñ€Ñ�дків із помилками: %4 none немає Apply Results Результати заÑ�тоÑ�уваннÑ� User definitions saved. КориÑ�тувацькі визначеннÑ� збережено. History Size Limit ОбмеженнÑ� розміру Ñ–Ñ�торії Maximum number of history entries for this session (0 = unlimited): МакÑ�имальна кількіÑ�ть запиÑ�ів Ñ–Ñ�торії длÑ� цього Ñ�еанÑ�у (0 = без обмежень): Text file (*.txt);;Any file (*.*) ТекÑ�товий файл (*.txt);;Будь-Ñ�кий файл (*.*) Could not recalculate from calculation %1: %2 Ð�е вдалоÑ�Ñ� переобчиÑ�лити від обчиÑ�леннÑ� %1: %2 History Size Limit Reached ДоÑ�Ñ�гнуто обмеженнÑ� розміру Ñ–Ñ�торії This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Це обчиÑ�леннÑ� заповнює оÑ�таннє доÑ�тупне міÑ�це в Ñ–Ñ�торії. Ð�аÑ�тупні обчиÑ�леннÑ� вилучатимуть найÑ�таріше обчиÑ�леннÑ� з Ñ–Ñ�торії. Збільшити обмеженнÑ� можна в меню СеанÑ� > ОбмеженнÑ� розміру Ñ–Ñ�торії. Editing calculation. Press Esc twice to cancel. РедагуваннÑ� обчиÑ�леннÑ�. Ð�атиÑ�ніть Esc двічі, щоб Ñ�каÑ�увати. Calculation Settings Параметри обчиÑ�леннÑ� Invalid recalculation start index Ð�еприпуÑ�тимий початковий індекÑ� переобчиÑ�леннÑ� System Default Типове длÑ� Ñ�иÑ�теми Language Мова Select the language: Виберіть мову: Custom ВлаÑ�ний Decimal places: ДеÑ�Ñ�ткові розрÑ�ди: &Automatic &Ð�втоматично &Precision &ТочніÑ�ть Plain &text ПроÑ�тий &текÑ�Ñ‚ Formula &Book Книга &формул &Export &ЕкÑ�порт Export session as HTML ЕкÑ�порт Ñ�еанÑ�у Ñ�к HTML HTML file (*.html) Файл HTML (*.html) Export session as plain text ЕкÑ�портувати Ñ�еанÑ� Ñ�к звичайний текÑ�Ñ‚ ManualWindow SpeedCrunch Manual ПоÑ�ібник SpeedCrunch %1 - SpeedCrunch Manual %1 - ПоÑ�ібник SpeedCrunch NumberFormatDialog Number Format Формат чиÑ�ла <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Виберіть формат чиÑ�ел длÑ� результатів Ñ– групуваннÑ� цифр під чаÑ� введеннÑ�.</b><br/><br/>Примітка: однозначні формати введених чиÑ�ел приймаютьÑ�Ñ�, навіть Ñ�кщо вони відрізнÑ�ютьÑ�Ñ� від вибраного формату відображеннÑ�.<br/> QObject Global User Variable Глобальна кориÑ�тувацька змінна Global User Function Глобальна кориÑ�тувацька функціÑ� Global User Unit Глобальна кориÑ�тувацька одиницÑ� Backspace Видалити попередній Ñ�имвол Clear expression ОчиÑ�тити вираз Evaluate expression ОбчиÑ�лити вираз Insert text Ð’Ñ�тавити текÑ�Ñ‚ Automatic decimal Ð�втоматичний деÑ�Ñ�тковий Fixed-point decimal ДеÑ�Ñ�тковий з фікÑ�ованою комою Engineering decimal Інженерний деÑ�Ñ�тковий Scientific decimal Ð�ауковий деÑ�Ñ�тковий Rational Раціональний Binary Двійковий Octal Ð’Ñ–Ñ�імковий Hexadecimal ШіÑ�тнадцÑ�тковий Sexagesimal ШіÑ�тдеÑ�Ñ�тковий Update Available ДоÑ�тупне оновленнÑ� A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> ДоÑ�тупна новіша верÑ�Ñ–Ñ� (%1).<br/><a href="%2">Відвідайте Ñ�айт длÑ� завантаженнÑ�.</a> Check for Updates Перевірити оновленнÑ� SpeedCrunch %1 is up to date. SpeedCrunch %1 актуальний. No connectivity. Please check your internet connection and try again. Ð�емає з’єднаннÑ�. Перевірте підключеннÑ� до інтернету й повторіть Ñ�пробу. Could not verify the latest available version. Ð�е вдалоÑ�Ñ� перевірити найновішу доÑ�тупну верÑ�Ñ–ÑŽ. ResultDisplay Scroll to bottom Прокрутити вниз Edit Expression Редагувати вираз Change Settings Змінити параметри New Tab Ð�ова вкладка &Import... &Імпортувати... &Export &ЕкÑ�порт Plain &text ПроÑ�тий &текÑ�Ñ‚ Copy Копіювати Selection ВиділеннÑ� Select All Вибрати вÑ�е Expression Вираз Result Результат Calculation ОбчиÑ�леннÑ� Calculation as Single Line ОбчиÑ�леннÑ� в один Ñ€Ñ�док Remove Видалити This Calculation Це обчиÑ�леннÑ� All Calculations Above УÑ�Ñ– обчиÑ�леннÑ� вище All Calculations Below УÑ�Ñ– обчиÑ�леннÑ� нижче New Private Tab Ð�ова приватна вкладка Session СеанÑ� Open... Відкрити... Clone... Клонувати... Rename... Перейменувати... Keep Зберегти Make Private... Зробити приватним... Clear ОчиÑ�тити Delete Видалити Close Закрити Split Розділити Left Ліворуч Right Праворуч Up Угору Down Униз Close Pane Закрити панель Main Menu Головне меню Cancel editing СкаÑ�увати редагуваннÑ� Copy result Копіювати результат Edit expression Редагувати вираз Change settings Змінити параметри Remove calculation Вилучити обчиÑ�леннÑ� ResultSlotsDialog Notation & Precision ЗапиÑ� Ñ– точніÑ�ть Result Line РÑ�док результату Enabled Увімкнено Notation ЗапиÑ� Decimal Places ДеÑ�Ñ�ткові розрÑ�ди Main Line Головний Ñ€Ñ�док Extra Line #1 Додатковий Ñ€Ñ�док #1 Extra Line #2 Додатковий Ñ€Ñ�док #2 Extra Line #3 Додатковий Ñ€Ñ�док #3 Extra Line #4 Додатковий Ñ€Ñ�док #4 Auto Ð�втоматично UserFunctionListWidget Name Ім'Ñ� Value ЗначеннÑ� Description ОпиÑ� Search Пошук No match found Ð�е знайдено відповідноÑ�ті Insert Ð’Ñ�тавити Edit Редагувати Delete Видалити Delete All Видалити вÑ�е UserUnitListWidget Name Ім’Ñ� Value ЗначеннÑ� Description ОпиÑ� Search Пошук No match found Збігів не знайдено Insert Ð’Ñ�тавити Edit Редагувати Delete Видалити Delete All Видалити вÑ�е VariableListWidget Name Ім'Ñ� Value ЗначеннÑ� Description ОпиÑ� Search Пошук No match found Ð�е знайдено відповідноÑ�ті Insert Ð’Ñ�тавити Edit Редагувати Delete Видалити Delete All Видалити вÑ�е heldercorreia-speedcrunch-e7ca37f/src/resources/locale/uz_Latn.ts000066400000000000000000010543501526573132500253710ustar00rootroot00000000000000 AboutBox About SpeedCrunch SpeedCrunch haqida Core developers Asosiy dasturchilar Original author Asl muallif Close Yopish Math engine Matematika dvijogi Main author | Logo | Maintainer Asosiy muallif | Logotip | Texnik xizmat ko'rsatuvchi Thanks Tashakkurlar Copyright (C) 2004-2026 The SpeedCrunch developers Copyright (C) 2004-2026 SpeedCrunch dasturchilari This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Bu dastur erkin dasturiy ta'minot; uni Free Software Foundation tomonidan chop etilgan GNU General Public License shartlari asosida, litsenziyaning 2-versiyasi yoki (xohishingizga ko'ra) keyingi istalgan versiyasi bo'yicha qayta tarqatishingiz va/yoki o'zgartirishingiz mumkin This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Bu dastur foydali bo'ladi degan umidda tarqatiladi, ammo HECH QANDAY KAFOLATSIZ; hatto SOTILISHGA YAROQLILIK yoki MUAYYAN MAQSADGA MUVOFIQLIK bo'yicha nazarda tutilgan kafolatsiz. Batafsil ma'lumot uchun GNU General Public License ga qarang. BitFieldWidget Reset bits to zero Bitlarni nolga qaytarish Invert bits Bitlarni invertlash Shift bits left Bitlarni chapga siljitish Shift bits right Bitlarni o‘ngga siljitish Book Index Indeks Algebra Algebra Quadratic Equation Kvadrat tenglama Logarithmic Base Conversion Logarifm asosini almashtirish Geometry Geometriya Circle Aylana Sector Sektor Sphere Sfera Cube Kub Cone Konus Cylinder Silindr Electronics Elektronika Ohm's Law Om qonuni Power Quvvat Reactance Reaktiv qarshilik Resonance Rezonans Radio Frequency Radiochastota Antennas Antennalar Characteristic Impedance (coax) Xarakteristik impedans (koaksial) Velocity of Propagation (coax) Tarqalish tezligi (koaksial) Standing Wave Ratio & Return Loss Turg'un to'lqin nisbati & qaytish yo'qotishi Free Space Wavelength Erkin fazodagi to'lqin uzunligi resistance qarshilik voltage kuchlanish current tok power quvvat inductive reactance induktiv reaktiv qarshilik capacitive reactance sig'imli reaktiv qarshilik inductance induktivlik capacitance sig'im frequency chastota resonance frequency rezonans chastotasi area maydon perimeter perimetr diameter diametr radius radius volume hajm surface area sirt maydoni height balandlik slant height yon balandlik face diagonal yoq diagonali space diagonal fazoviy diagonal edge length qirra uzunligi arc length yoy uzunligi central angle (degrees) markaziy burchak (daraja) input power kirish quvvati reflected power qaytgan quvvat transmitted power uzatilgan quvvat return loss qaytish yo'qotishi dielectric constant dielektrik konstantasi outer conductor's inner diameter tashqi o'tkazgichning ichki diametri inner conductor's outer diameter ichki o'tkazgichning tashqi diametri speed of light yorug'lik tezligi reflection coefficient qaytish koeffitsiyenti standing wave ratio turg'un to'lqin nisbati normalized impedance normallangan impedans frequency (Hz) chastota (Hz) BookDock Formula Book Formulalar kitobi ConstantCompletion Search constants Konstantalarni qidirish No match found Moslik topilmadi Constants Mathematics Matematika Physics (CODATA 2022) Fizika (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Kimyo (IUPAC - CIAAW 2021) Uncategorized Turkumlanmagan Universal Universal Physicochemical Fizik-kimyoviy Atomic & Nuclear — General Atom & yadro — Umumiy Atomic & Nuclear — Electroweak Atom & yadro — Elektrokuchsiz Atomic & Nuclear — Electron Atom & yadro — Elektron Atomic & Nuclear — Muon Atom & yadro — Myuon Atomic & Nuclear — Tau Atom & yadro — Tau Atomic & Nuclear — Proton Atom & yadro — Proton Atomic & Nuclear — Neutron Atom & yadro — Neytron Atomic & Nuclear — Deuteron Atom & yadro — Deytron Atomic & Nuclear — Triton Atom & yadro — Triton Atomic & Nuclear — Helion Atom & yadro — Gelion Atomic & Nuclear — Alpha particle Atom & yadro — Alfa zarracha Atomic & Nuclear — Atomic units Atom & yadro — Atom birliklari Atomic & Nuclear — Energy conversion relationships Atom & yadro — Energiya aylantirish munosabatlari Atomic & Nuclear — X-ray units Atom & yadro — Rentgen birliklari Atomic & Nuclear — Magnetic shielding corrections Atom & yadro — Magnit ekranlash tuzatmalari Masses Massalar Lifetimes Yashash vaqtlari Molar Masses Molyar massalar Electronegativity Elektrmanfiylik Ionization Energy Ionlanish energiyasi Nominal Constants (IAU 2015) Nominal konstantalar (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Joriy eng yaxshi baholar (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) vakuumning xarakteristik impedansi (Zâ‚€) reduced Planck constant (â„�) keltirilgan Plank konstantasi (â„�) vacuum electric permittivity (ϵ₀) vakuum elektr singdiruvchanligi (ϵ₀) Newtonian constant of gravitation (G) Nyuton gravitatsiya konstantasi (G) vacuum magnetic permeability (μ₀) vakuum magnit singdiruvchanligi (μ₀) Planck constant (h) Plank konstantasi (h) speed of light in vacuum (c) vakuumdagi yorug'lik tezligi (c) standard acceleration of gravity (gâ‚™) standart erkin tushish tezlanishi (gâ‚™) Newtonian constant of gravitation over h-bar c h-bar c ga bo'lingan Nyuton gravitatsiya konstantasi Planck length Plank uzunligi Planck constant in eV/Hz (h) eV/Hz dagi Plank konstantasi (h) Planck mass Plank massasi Planck mass energy equivalent in GeV GeV dagi Plank massasining energiya ekvivalenti Planck temperature Plank harorati Planck time Plank vaqti reduced Planck constant in eV·s (â„�) eV·s dagi keltirilgan Plank konstantasi (â„�) reduced Planck constant times c in MeV·fm MeV·fm dagi keltirilgan Plank konstantasining c ga ko'paytmasi Bohr magneton Bor magnetoni conductance quantum (Gâ‚€) o'tkazuvchanlik kvanti (Gâ‚€) Coulomb constant (kâ‚‘) Kulon konstantasi (kâ‚‘) elementary charge (e) elementar zaryad (e) elementary charge over h-bar h-bar ga bo'lingan elementar zaryad conventional value of Josephson constant Josephson konstantasi ning an'anaviy qiymati Josephson constant Jozefson konstantasi conventional value of ampere-90 ampere-90 ning an'anaviy qiymati conventional value of coulomb-90 coulomb-90 ning an'anaviy qiymati conventional value of farad-90 farad-90 ning an'anaviy qiymati conventional value of henry-90 henry-90 ning an'anaviy qiymati conventional value of ohm-90 ohm-90 ning an'anaviy qiymati conventional value of volt-90 volt-90 ning an'anaviy qiymati conventional value of watt-90 watt-90 ning an'anaviy qiymati magnetic flux quantum (Φ₀) magnit oqim kvanti (Φ₀) nuclear magneton yadro magnetoni inverse of conductance quantum o'tkazuvchanlik kvantining teskarisi conventional value of von Klitzing constant von Klitzing konstantasi ning an'anaviy qiymati von Klitzing constant fon Klitsing konstantasi atomic unit of magnetic dipole moment magnit dipol momentining atom birligi atomic unit of magnetic flux density magnit oqim zichligining atom birligi Bohr magneton in eV/T eV/T dagi Bor magnetoni Bohr magneton in Hz/T Hz/T dagi Bor magnetoni Bohr magneton in inverse meter per tesla inverse meter per tesla dagi Bor magnetoni Bohr magneton in K/T K/T dagi Bor magnetoni nuclear magneton in eV/T eV/T dagi yadro magnetoni nuclear magneton in inverse meter per tesla inverse meter per tesla dagi yadro magnetoni nuclear magneton in K/T K/T dagi yadro magnetoni nuclear magneton in MHz/T MHz/T dagi yadro magnetoni Bohr radius (aâ‚€) Bor radiusi (aâ‚€) fine-structure constant (α) nozik tuzilma konstantasi (α) Hartree energy (Eâ‚•) Hartri energiyasi (Eâ‚•) Hartree energy in eV eV dagi Hartri energiyasi quantum of circulation sirkulyatsiya kvanti quantum of circulation times 2 sirkulyatsiya kvantining 2 ga ko'paytmasi Rydberg constant (R∞) Ridberg konstantasi (R∞) atomic mass unit-hartree relationship atom massa birligi-hartri munosabati atomic mass unit-hertz relationship atom massa birligi-gers munosabati atomic mass unit-inverse meter relationship atom massa birligi-teskari metr munosabati atomic mass unit-joule relationship atom massa birligi-joul munosabati atomic mass unit-kelvin relationship atom massa birligi-kelvin munosabati atomic mass unit-kilogram relationship atom massa birligi-kilogramm munosabati atomic unit of 1st hyperpolarizability 1st hyperpolarizabilityning atom birligi atomic unit of 2nd hyperpolarizability 2nd hyperpolarizabilityning atom birligi atomic unit of charge (e) zaryadning atom birligi (e) atomic unit of charge density zaryad zichligining atom birligi atomic unit of current tokning atom birligi atomic unit of electric dipole moment elektr dipol momentining atom birligi atomic unit of electric field elektr maydonining atom birligi atomic unit of electric field gradient elektr maydoni gradientining atom birligi atomic unit of electric polarizability elektr qutblanuvchanlikning atom birligi atomic unit of electric potential elektr potensialining atom birligi atomic unit of electric quadrupole moment elektr kvadrupol momentining atom birligi atomic unit of action ta'sirning atom birligi atomic unit of energy energiyaning atom birligi atomic unit of force kuchning atom birligi atomic unit of length uzunlikning atom birligi hertz-atomic mass unit relationship gers-atom massa birligi munosabati hertz-electron volt relationship gers-elektronvolt munosabati hertz-hartree relationship gers-hartri munosabati hertz-inverse meter relationship gers-teskari metr munosabati hertz-joule relationship gers-joul munosabati hertz-kelvin relationship gers-kelvin munosabati hertz-kilogram relationship gers-kilogramm munosabati hyperfine transition frequency of Cs-133 Cs-133 ning gipernafis o'tish chastotasi inverse fine-structure constant (αâ�»Â¹) nozik tuzilma konstantasining teskarisi (αâ�»Â¹) inverse meter-atomic mass unit relationship teskari metr-atom massa birligi munosabati inverse meter-electron volt relationship teskari metr-elektronvolt munosabati inverse meter-hartree relationship teskari metr-hartri munosabati inverse meter-hertz relationship teskari metr-gers munosabati inverse meter-joule relationship teskari metr-joul munosabati inverse meter-kelvin relationship teskari metr-kelvin munosabati inverse meter-kilogram relationship teskari metr-kilogramm munosabati joule-atomic mass unit relationship joul-atom massa birligi munosabati joule-electron volt relationship joul-elektronvolt munosabati joule-hertz relationship joul-gers munosabati joule-hartree relationship joul-hartri munosabati joule-inverse meter relationship joul-teskari metr munosabati joule-kelvin relationship joul-kelvin munosabati joule-kilogram relationship joul-kilogramm munosabati kelvin-atomic mass unit relationship kelvin-atom massa birligi munosabati kelvin-electron volt relationship kelvin-elektronvolt munosabati kelvin-hertz relationship kelvin-gers munosabati kelvin-hartree relationship kelvin-hartri munosabati kelvin-inverse meter relationship kelvin-teskari metr munosabati kelvin-joule relationship kelvin-joul munosabati kelvin-kilogram relationship kelvin-kilogramm munosabati kilogram-atomic mass unit relationship kilogramm-atom massa birligi munosabati kilogram-electron volt relationship kilogramm-elektronvolt munosabati kilogram-hertz relationship kilogramm-gers munosabati kilogram-hartree relationship kilogramm-hartri munosabati kilogram-inverse meter relationship kilogramm-teskari metr munosabati kilogram-joule relationship kilogramm-joul munosabati kilogram-kelvin relationship kilogramm-kelvin munosabati lattice parameter of silicon (a) kremniyning panjara parametri (a) luminous efficacy yorug'lik samaradorligi natural unit of energy energiyaning tabiiy birligi natural unit of energy in MeV MeV dagi energiyaning tabiiy birligi natural unit of action (â„�) ta'sirning tabiiy birligi (â„�) natural unit of action in eV·s eV·s dagi ta'sirning tabiiy birligi natural unit of length uzunlikning tabiiy birligi natural unit of mass massaning tabiiy birligi natural unit of momentum impulsning tabiiy birligi natural unit of momentum in MeV/c MeV/c dagi impulsning tabiiy birligi natural unit of time vaqtning tabiiy birligi natural unit of velocity tezlikning tabiiy birligi Rydberg constant times c in Hz Hz dagi Rydberg konstantasining c ga ko'paytmasi Rydberg constant times hc in eV eV dagi Rydberg konstantasining hc ga ko'paytmasi Rydberg constant times hc in J J dagi Rydberg konstantasining hc ga ko'paytmasi Fermi coupling constant Fermi bog'lanish konstantasi weak mixing angle kuchsiz aralashish burchagi W to Z mass ratio W va Z massalarining nisbati Thomson cross section (σₑ) Tomson kesimi (σₑ) electron mass (mâ‚‘) elektronning massasi (mâ‚‘) electron mass in u u dagi elektronning massasi electron mass energy equivalent (mₑ·c²) elektronning massa-energiya ekvivalenti (mₑ·c²) electron mass energy equivalent in MeV MeV dagi elektronning massa-energiya ekvivalenti reduced Compton wavelength reduced Kompton to'lqin uzunligi classical electron radius (râ‚‘) klassik elektron radiusi (râ‚‘) electron charge to mass quotient elektron zaryad-massa bo'linmasi electron-deuteron magnetic moment ratio elektron-deytron magnit moment nisbati electron-deuteron mass ratio elektron-deytron massa nisbati electron g factor (gâ‚‘) elektronning g-faktori (gâ‚‘) electron gyromagnetic ratio (γₑ) elektronning giromagnit nisbati (γₑ) electron gyromagnetic ratio in MHz/T MHz/T dagi elektronning giromagnit nisbati electron-helion mass ratio elektron-gelion massa nisbati electron magnetic moment (μₑ) elektronning magnit momenti (μₑ) electron magnetic moment anomaly (aâ‚‘) elektronning magnit moment anomaliyasi (aâ‚‘) electron magnetic moment to Bohr magneton ratio elektronning magnit momentining Bor magnetoniga nisbati electron magnetic moment to nuclear magneton ratio elektronning magnit momentining yadro magnetoniga nisbati electron molar mass (Mâ‚‘) elektronning molyar massasi (Mâ‚‘) electron-muon magnetic moment ratio elektron-myuon magnit moment nisbati electron-muon mass ratio elektron-myuon massa nisbati electron-neutron magnetic moment ratio elektron-neytron magnit moment nisbati electron-neutron mass ratio elektron-neytron massa nisbati electron-proton magnetic moment ratio elektron-proton magnit moment nisbati electron-proton mass ratio elektron-proton massa nisbati electron relative atomic mass (Ar(e)) elektron nisbiy atom massasi (Ar(e)) electron-tau mass ratio elektron-tau massa nisbati electron to alpha particle mass ratio elektronning massasining alfa zarrachaga nisbati electron to shielded helion magnetic moment ratio elektronning magnit momentining ekranlangan gelionga nisbati electron to shielded proton magnetic moment ratio elektronning magnit momentining ekranlangan protonga nisbati electron-triton mass ratio elektron-triton massa nisbati electron volt-atomic mass unit relationship elektronvolt-atom massa birligi munosabati electron volt-hartree relationship elektronvolt-hartri munosabati electron volt-hertz relationship elektronvolt-gers munosabati electron volt-inverse meter relationship elektronvolt-teskari metr munosabati electron volt-joule relationship elektronvolt-joul munosabati electron volt-kelvin relationship elektronvolt-kelvin munosabati electron volt-kilogram relationship elektronvolt-kilogramm munosabati hartree-atomic mass unit relationship hartri-atom massa birligi munosabati hartree-electron volt relationship hartri-elektronvolt munosabati muon Compton wavelength myuon Kompton to'lqin uzunligi muon-electron mass ratio myuon-elektron massa nisbati muon g factor myuonning g-faktori muon magnetic moment myuonning magnit momenti muon magnetic moment anomaly myuonning magnit moment anomaliyasi muon magnetic moment to Bohr magneton ratio myuonning magnit momentining Bor magnetoniga nisbati muon magnetic moment to nuclear magneton ratio myuonning magnit momentining yadro magnetoniga nisbati muon mass myuonning massasi muon mass energy equivalent myuonning massa-energiya ekvivalenti muon mass energy equivalent in MeV MeV dagi myuonning massa-energiya ekvivalenti muon mass in u u dagi myuonning massasi muon molar mass myuonning molyar massasi muon-neutron mass ratio myuon-neytron massa nisbati muon-proton magnetic moment ratio myuon-proton magnit moment nisbati muon-proton mass ratio myuon-proton massa nisbati muon-tau mass ratio myuon-tau massa nisbati reduced muon Compton wavelength keltirilgan myuon Kompton to'lqin uzunligi reduced tau Compton wavelength keltirilgan tau Kompton to'lqin uzunligi tau Compton wavelength tau Kompton to'lqin uzunligi tau-electron mass ratio tau-elektron massa nisbati tau mass tauning massasi tau mass energy equivalent tauning massa-energiya ekvivalenti tau mass in u u dagi tauning massasi tau molar mass tauning molyar massasi tau-muon mass ratio tau-myuon massa nisbati tau-neutron mass ratio tau-neytron massa nisbati tau-proton mass ratio tau-proton massa nisbati proton charge to mass quotient proton zaryad-massa bo'linmasi proton Compton wavelength proton Kompton to'lqin uzunligi proton-electron mass ratio proton-elektron massa nisbati proton g factor (gₚ) protonning g-faktori (gₚ) proton gyromagnetic ratio (γₚ) protonning giromagnit nisbati (γₚ) proton gyromagnetic ratio in MHz/T MHz/T dagi protonning giromagnit nisbati proton magnetic moment (μₚ) protonning magnit momenti (μₚ) proton magnetic moment to Bohr magneton ratio protonning magnit momentining Bor magnetoniga nisbati proton magnetic moment to nuclear magneton ratio protonning magnit momentining yadro magnetoniga nisbati proton magnetic shielding correction proton magnit ekranlash tuzatmasi proton mass (mₚ) protonning massasi (mₚ) proton mass energy equivalent protonning massa-energiya ekvivalenti proton mass energy equivalent in MeV MeV dagi protonning massa-energiya ekvivalenti proton mass in u u dagi protonning massasi proton molar mass (Mₚ) protonning molyar massasi (Mₚ) proton-muon mass ratio proton-myuon massa nisbati proton-neutron magnetic moment ratio proton-neytron magnit moment nisbati proton-neutron mass ratio proton-neytron massa nisbati proton relative atomic mass (Ar(p)) proton nisbiy atom massasi (Ar(p)) proton rms charge radius protonning o'rtacha kvadratik zaryad radiusi proton-tau mass ratio proton-tau massa nisbati reduced proton Compton wavelength keltirilgan proton Kompton to'lqin uzunligi shielded proton gyromagnetic ratio ekranlangan protonning giromagnit nisbati shielded proton gyromagnetic ratio in MHz/T MHz/T dagi ekranlangan protonning giromagnit nisbati shielded proton magnetic moment ekranlangan protonning magnit momenti shielded proton magnetic moment to Bohr magneton ratio ekranlangan protonning magnit momentining Bor magnetoniga nisbati shielded proton magnetic moment to nuclear magneton ratio ekranlangan protonning magnit momentining yadro magnetoniga nisbati neutron Compton wavelength neytron Kompton to'lqin uzunligi neutron-electron magnetic moment ratio neytron-elektron magnit moment nisbati neutron-electron mass ratio neytron-elektron massa nisbati neutron g factor (gâ‚™) neytronning g-faktori (gâ‚™) neutron gyromagnetic ratio (γₙ) neytronning giromagnit nisbati (γₙ) neutron gyromagnetic ratio in MHz/T MHz/T dagi neytronning giromagnit nisbati neutron magnetic moment (μₙ) neytronning magnit momenti (μₙ) neutron magnetic moment to Bohr magneton ratio neytronning magnit momentining Bor magnetoniga nisbati neutron magnetic moment to nuclear magneton ratio neytronning magnit momentining yadro magnetoniga nisbati neutron mass (mâ‚™) neytronning massasi (mâ‚™) neutron mass energy equivalent neytronning massa-energiya ekvivalenti neutron mass energy equivalent in MeV MeV dagi neytronning massa-energiya ekvivalenti neutron mass in u u dagi neytronning massasi neutron molar mass (Mâ‚™) neytronning molyar massasi (Mâ‚™) neutron-muon mass ratio neytron-myuon massa nisbati neutron-proton magnetic moment ratio neytron-proton magnit moment nisbati neutron-proton mass difference neytron-proton massa farqi neutron-proton mass difference energy equivalent neytron-proton massa farqining energiya ekvivalenti neutron-proton mass difference energy equivalent in MeV MeV dagi neytron-proton massa farqining energiya ekvivalenti neutron-proton mass difference in u u dagi neytron-proton massa farqi neutron-proton mass ratio neytron-proton massa nisbati neutron relative atomic mass (Ar(n)) neytron nisbiy atom massasi (Ar(n)) neutron-tau mass ratio neytron-tau massa nisbati neutron to shielded proton magnetic moment ratio neytronning magnit momentining ekranlangan protonga nisbati reduced neutron Compton wavelength keltirilgan neytron Kompton to'lqin uzunligi deuteron-electron magnetic moment ratio deytron-elektron magnit moment nisbati deuteron-electron mass ratio deytron-elektron massa nisbati deuteron g factor deytronning g-faktori deuteron magnetic moment deytronning magnit momenti deuteron magnetic moment to Bohr magneton ratio deytronning magnit momentining Bor magnetoniga nisbati deuteron magnetic moment to nuclear magneton ratio deytronning magnit momentining yadro magnetoniga nisbati deuteron mass deytronning massasi deuteron mass energy equivalent deytronning massa-energiya ekvivalenti deuteron mass energy equivalent in MeV MeV dagi deytronning massa-energiya ekvivalenti deuteron mass in u u dagi deytronning massasi deuteron molar mass deytronning molyar massasi deuteron-neutron magnetic moment ratio deytron-neytron magnit moment nisbati deuteron-proton magnetic moment ratio deytron-proton magnit moment nisbati deuteron-proton mass ratio deytron-proton massa nisbati deuteron relative atomic mass (Ar(d)) deytron nisbiy atom massasi (Ar(d)) deuteron rms charge radius deytronning o'rtacha kvadratik zaryad radiusi triton-electron mass ratio triton-elektron massa nisbati triton g factor (gₜ) tritonning g-faktori (gₜ) triton magnetic moment (μₜ) tritonning magnit momenti (μₜ) triton magnetic moment to Bohr magneton ratio tritonning magnit momentining Bor magnetoniga nisbati triton magnetic moment to nuclear magneton ratio tritonning magnit momentining yadro magnetoniga nisbati triton mass (mₜ) tritonning massasi (mₜ) triton mass energy equivalent tritonning massa-energiya ekvivalenti triton mass energy equivalent in MeV MeV dagi tritonning massa-energiya ekvivalenti triton mass in u u dagi tritonning massasi triton molar mass (Mₜ) tritonning molyar massasi (Mₜ) triton-proton mass ratio triton-proton massa nisbati triton relative atomic mass (Ar(t)) triton nisbiy atom massasi (Ar(t)) triton to proton magnetic moment ratio tritonning magnit momentining protonga nisbati helion-electron mass ratio gelion-elektron massa nisbati helion g factor (gâ‚•) gelionning g-faktori (gâ‚•) helion magnetic moment (μₕ) gelionning magnit momenti (μₕ) helion magnetic moment to Bohr magneton ratio gelionning magnit momentining Bor magnetoniga nisbati helion magnetic moment to nuclear magneton ratio gelionning magnit momentining yadro magnetoniga nisbati helion mass (mâ‚•) gelionning massasi (mâ‚•) helion mass energy equivalent gelionning massa-energiya ekvivalenti helion mass energy equivalent in MeV MeV dagi gelionning massa-energiya ekvivalenti helion mass in u u dagi gelionning massasi helion molar mass (Mâ‚•) gelionning molyar massasi (Mâ‚•) helion-proton mass ratio gelion-proton massa nisbati helion relative atomic mass (Ar(h)) gelion nisbiy atom massasi (Ar(h)) helion shielding shift gelion ekranlash siljishi shielded helion gyromagnetic ratio ekranlangan gelionning giromagnit nisbati shielded helion gyromagnetic ratio in MHz/T MHz/T dagi ekranlangan gelionning giromagnit nisbati shielded helion magnetic moment ekranlangan gelionning magnit momenti shielded helion magnetic moment to Bohr magneton ratio ekranlangan gelionning magnit momentining Bor magnetoniga nisbati shielded helion magnetic moment to nuclear magneton ratio ekranlangan gelionning magnit momentining yadro magnetoniga nisbati shielded helion to proton magnetic moment ratio ekranlangan gelionning magnit momentining protonga nisbati shielded helion to shielded proton magnetic moment ratio ekranlangan gelionning magnit momentining ekranlangan protonga nisbati alpha particle mass alfa zarrachaning massasi alpha particle mass in u u dagi alfa zarrachaning massasi alpha particle mass energy equivalent alfa zarrachaning massa-energiya ekvivalenti alpha particle mass energy equivalent in MeV MeV dagi alfa zarrachaning massa-energiya ekvivalenti alpha particle-electron mass ratio alfa zarracha-elektron massa nisbati alpha particle-proton mass ratio alfa zarracha-proton massa nisbati alpha particle rms charge radius alfa zarrachaning o'rtacha kvadratik zaryad radiusi alpha particle molar mass alfa zarrachaning molyar massasi alpha particle relative atomic mass (Ar(α)) alfa zarracha nisbiy atom massasi (Ar(α)) atomic mass constant (mᵤ) atomic mass konstantasi (mᵤ) Avogadro constant Avogadro konstantasi Boltzmann constant (k) Boltsman konstantasi (k) Boltzmann constant in eV/K eV/K dagi Boltsman konstantasi Boltzmann constant in Hz/K Hz/K dagi Boltsman konstantasi Boltzmann constant in inverse meter per kelvin kelvinga teskari metr dagi Boltsman konstantasi electron volt (eV) elektronvolt (eV) Faraday constant (F) Faradey konstantasi (F) first radiation constant (câ‚�) birinchi nurlanish konstantasi (câ‚�) first radiation constant for spectral radiance spektral yorqinlik uchun birinchi nurlanish konstantasi molar gas constant (R) molyar gaz konstantasi (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) Loschmidt konstantasi (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) Loschmidt konstantasi (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant molyar Plank konstantasi second radiation constant (câ‚‚) ikkinchi nurlanish konstantasi (câ‚‚) Stefan-Boltzmann constant (σ) Stefan-Boltsman konstantasi (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ideal Si panjara oralig'i (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent atomic mass constant energy equivalent atomic mass constant energy equivalent in MeV MeV dagi atomic mass constant energy equivalent atomic mass unit-electron volt relationship atom massa birligi-elektronvolt munosabati molar mass constant (Mᵤ) molyar massa konstantasi (Mᵤ) molar mass of carbon-12 uglerod-12 ning molyar massasi molar volume of ideal gas (273.15 K, 100 kPa) ideal gazning molyar hajmi (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ideal gazning molyar hajmi (273.15 K, 101.325 kPa) molar volume of silicon kremniyning molyar hajmi Sackur-Tetrode constant (1 K, 100 kPa) Sakur-Tetrode konstantasi (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) Sakur-Tetrode konstantasi (1 K, 101.325 kPa) Wien frequency displacement law constant Wien chastota siljishi qonuni konstantasi Wien wavelength displacement law constant Wien to'lqin uzunligi siljishi qonuni konstantasi standard atmosphere (atm) standart atmosfera (atm) standard-state pressure (p°) standart holat bosimi (p°) Angstrom star (Ã…*) Angstrem yulduzi (Ã…*) Copper x unit mis x birligi Molybdenum x unit molibden x birligi atomic unit of magnetizability magnitlanuvchanlikning atom birligi atomic unit of mass (mâ‚‘) massaning atom birligi (mâ‚‘) atomic unit of momentum impulsning atom birligi atomic unit of permittivity dielektrik singdiruvchanlikning atom birligi atomic unit of time vaqtning atom birligi atomic unit of velocity tezlikning atom birligi hartree-hertz relationship hartri-gers munosabati hartree-inverse meter relationship hartri-teskari metr munosabati hartree-joule relationship hartri-joul munosabati hartree-kelvin relationship hartri-kelvin munosabati hartree-kilogram relationship hartri-kilogramm munosabati shielding difference of d and p in HD HD dagi d va p ekranlash farqi shielding difference of t and p in HT HT dagi t va p ekranlash farqi pi (Ï€) pi (Ï€) Euler's number (e) Eyler soni (e) golden ratio (φ) oltin nisbat (φ) Euler-Mascheroni constant (γ) Eyler-Maskeroni konstantasi (γ) nominal solar radius nominal Quyosh radiusi nominal solar total irradiance nominal Quyosh jami nurlanishi nominal solar luminosity nominal Quyosh yorqinligi nominal solar effective temperature nominal Quyosh effektiv harorati nominal solar mass parameter nominal Quyosh massa parametri nominal terrestrial equatorial radius nominal Yer ekvatorial radiusi nominal terrestrial polar radius nominal Yer qutb radiusi nominal terrestrial mass parameter nominal Yer massa parametri nominal jovian equatorial radius nominal Yupiter ekvatorial radiusi nominal jovian polar radius nominal Yupiter qutb radiusi nominal jovian mass parameter nominal Yupiter massa parametri average value of one minus the rate of TCG relative to TCB TCG ning TCB ga nisbatan tezligidan bir ayirilgan o'rtacha qiymat solar mass parameter (TCB-compatible) Quyosh massa parametri (TCB-mos) solar mass parameter (TDB-compatible) Quyosh massa parametri (TDB-mos) equatorial radius of the Earth (TT-compatible) Yerning ekvatorial radiusi (TT-mos) dynamical form factor of the Earth Yerning dinamik shakl faktori time rate of change in the dynamical form factor of the Earth Yerning dinamik shakl faktorining vaqt bo'yicha o'zgarish tezligi geocentric gravitational constant (TCB-compatible) geosentrik gravitatsiya konstantasi (TCB-mos) geocentric gravitational constant (TT-compatible) geosentrik gravitatsiya konstantasi (TT-mos) geocentric gravitational constant (TDB-compatible) geosentrik gravitatsiya konstantasi (TDB-mos) potential of the geoid geoid potensiali nominal mean angular velocity of the Earth (TT-compatible) Yerning nominal o'rtacha burchak tezligi (TT-mos) ratio mass of the Moon to the Earth Oyning Yerga massa nisbati ratio of the mass of the Sun to Mercury Quyosh massasining Merkuriyga nisbati ratio of the mass of the Sun to Venus Quyosh massasining Veneraga nisbati ratio of the mass of the Sun to Mars Quyosh massasining Marsga nisbati ratio of the mass of the Sun to Jupiter Quyosh massasining Yupiterga nisbati ratio of the mass of the Sun to Saturn Quyosh massasining Saturnga nisbati ratio of the mass of the Sun to Uranus Quyosh massasining Uranga nisbati ratio of the mass of the Sun to Neptune Quyosh massasining Neptunga nisbati ratio of the mass of the Sun to (134340) Pluto Quyosh massasining (134340) Plutonga nisbati ratio of the mass of the Sun to (136199) Eris Quyosh massasining (136199) Erisga nisbati ratio of the mass of (1) Ceres to the Sun (1) Serera massasining Quyoshga nisbati ratio of the mass of (2) Pallas to the Sun (2) Pallada massasining Quyoshga nisbati ratio of the mass of (4) Vesta to the Sun (4) Vesta massasining Quyoshga nisbati mean obliquity of the ecliptic at J2000.0 J2000.0 dagi ekliptikaning o'rtacha og'ishi Electromagnetic Elektromagnit Compton wavelength Kompton to'lqin uzunligi Astronomy Astronomiya ConstantsWidget Domain Soha Subdomain Quyi soha No match found Moslik topilmadi Name Nomi Value Qiymati Unit Birlik Search Qidirish All Hammasi CustomKeypadDialog Custom Keypad Maxsus klaviatura Rows: Qatorlar: Columns: Ustunlar: Copy preset: Andozani nusxalash: Basic Asosiy Scientific (wide) Ilmiy (keng) Scientific (narrow) Ilmiy (tor) Apply Qo'llash Row Qator Column Ustun Label Yorliq Behavior Amal Text Matn DiagnosticsDialog App Diagnostics Ilova diagnostikasi Copy to Clipboard Buferga nusxalash Editor Unit Birlik User unit Foydalanuvchi birligi User function Foydalanuvchi funksiyasi Argument Argument Current result:<br/>%1 Joriy natija:<br/>%1 Selection result:<br/>%1 Tanlangan natija:<br/>%1 Selection result: n/a Tanlangan natija: mavjud emas Selection result: %1 Tanlangan natija: %1 second soniya metre metr kilogram kilogramm mole mol radian radian steradian steradian degree Celsius Selsiy darajasi cubic metre kub metr cubic millimetre kub millimetr cubic centimetre kub santimetr cubic decimetre kub detsimetr cubic kilometre kub kilometr square millimetre kvadrat millimetr square kilometre kvadrat kilometr square metre kvadrat metr minute daqiqa hour soat day kun astronomical unit astronomik birlik degree daraja arcminute burchak daqiqasi arcsecond burchak soniyasi milliarcsecond milliburchak soniyasi microarcsecond mikroburchak soniyasi hectare gektar litre litr tonne tonna Dalton dalton electronvolt elektronvolt Angstrom angstrem atmosphere atmosfera atomic mass unit atom massa birligi British thermal unit Britaniya issiqlik birligi calorie kaloriya carat karat cup stakan cup (Imperial) stakan (imperial) cup (Japanese) stakan (yapon) cup (US) stakan (AQSH) degree Fahrenheit Farengeyt darajasi fathom fatom fluid ounce (Imperial) suyuqlik unsiyasi (imperial) fluid ounce (US) suyuqlik unsiyasi (AQSH) fluid dram (Imperial) suyuqlik draxmasi (imperial) fluid dram (US) suyuqlik draxmasi (AQSH) foot fut square foot kvadrat fut cubic foot kub fut gallon (Imperial) gallon (imperial) gallon (US) gallon (AQSH) gill (Imperial) gill (imperial) gill (US) gill (AQSH) gradian gradian grain greyn gram gramm Hartley Hartli Hartree energy unit Hartri energiya birligi horsepower ot kuchi inch dyuym square inch kvadrat dyuym cubic inch kub dyuym karat karat knot uzel lightminute yorug'lik daqiqasi lightsecond yorug'lik soniyasi lightyear yorug'lik yili long ton uzun tonna mile milya square mile kvadrat milya cubic mile kub milya mile per hour soatiga milya kilometre per hour soatiga kilometr nautical mile dengiz milyasi ounce unsiya parsec parsek pint (Imperial) pinta (imperial) pint (US) pinta (AQSH) pound funt pounds per square inch kvadrat dyuymga funt quart (Imperial) kvarta (imperial) quart (US) kvarta (AQSH) oil barrel neft barreli beer barrel (US) pivo barreli (AQSH) square yard kvadrat yard cubic yard kub yard short ton qisqa tonna tablespoon osh qoshiq tablespoon (Australian) osh qoshiq (Avstraliya) tablespoon (Imperial) osh qoshiq (imperial) tablespoon (US) osh qoshiq (AQSH) dessert spoon desert qoshiq teaspoon choy qoshiq teaspoon (Imperial) choy qoshiq (imperial) teaspoon (US) choy qoshiq (AQSH) turn burilish revolution aylanish revolution per minute daqiqadagi aylanish week hafta kilowatt hour kilovatt-soat millimetre of mercury simob ustunining millimetri yard yard Julian century Yulian asri Julian year Yulian yili sidereal year yulduz yili tropical year tropik yil Evaluator invalid expression ifoda yaroqsiz division by zero nolga bo'lish too time consuming - computation was rejected juda ko'p vaqt oladi - hisoblash rad etildi dimension mismatch - quantities with different dimensions cannot be compared, added, etc. o'lchamlar mos kelmadi - turli o'lchamli kattaliklarni taqqoslash, qo'shish va hokazo mumkin emas invalid dimension - operation might require dimensionless arguments o'lcham yaroqsiz - amal o'lchamsiz argumentlarni talab qilishi mumkin Computation aborted - encountered numerical instability Hisoblash to'xtatildi - sonli beqarorlikka duch kelindi invalid dimension - function might require dimensionless arguments o'lcham yaroqsiz - funksiya o'lchamsiz argumentlarni talab qilishi mumkin error xato unit must not be zero birlik nol bo'lmasligi kerak Conversion failed - dimension mismatch Aylantirish bajarilmadi - o'lchamlar mos kelmadi unknown function or variable noma'lum funksiya yoki o'zgaruvchi recursion not supported rekursiya qo'llab-quvvatlanmaydi cannot operate on a NaN NaN ustida amal bajarib bo'lmaydi underflow - tiny result is out of SpeedCrunch's number range pastki to'lib ketish - juda kichik natija SpeedCrunch sonlar oralig'idan tashqarida overflow - huge result is out of SpeedCrunch's number range to'lib ketish - juda katta natija SpeedCrunch sonlar oralig'idan tashqarida overflow - logic result exceeds maximum of 256 bits to'lib ketish - mantiqiy natija 256 bitlik maksimumdan oshdi overflow - integer result exceeds maximum limit for integers to'lib ketish - butun natija butun sonlar uchun maksimal chegaradan oshdi operation is not defined for these arguments bu argumentlar uchun amal aniqlanmagan wrong number of arguments argumentlar soni noto'g'ri does not take NaN as an argument NaN ni argument sifatida qabul qilmaydi result out of range natija oraliqdan tashqarida undefined for argument domain argument sohasi uchun aniqlanmagan computation too expensive hisoblash juda qimmat internal error, please report a bug ichki xato, iltimos xato haqida xabar bering syntax error sintaksis xatosi conversion target must be a unit aylantirish maqsadi birlik bo'lishi kerak unknown unit noma'lum birlik %1 is a reserved name, please choose another %1 band qilingan nom, boshqa nom tanlang %1 is a global user definition and cannot be overridden in this session. %1 global foydalanuvchi ta'rifi va bu sessiyada qayta belgilab bo'lmaydi. %1 is a variable name, please choose another or delete the variable %1 o'zgaruvchi nomi, boshqa nom tanlang yoki o'zgaruvchini o'chiring argument %1 is used more than once %1 argumenti bir martadan ortiq ishlatilgan %1 is a built-in unit name, please choose another %1 ichki birlik nomi, boshqa nom tanlang %1 is a user function name, please choose another or delete the function %1 foydalanuvchi funksiyasi nomi, boshqa nom tanlang yoki funksiyani o'chiring FunctionRepo max; trials; probability maksimum; sinovlar; ehtimollik trials; probability sinovlar; ehtimollik hits; trials; probability muvaffaqiyatlar; sinovlar; ehtimollik max; total; hits; trials maksimum; jami; muvaffaqiyatlar; sinovlar total; hits; trials jami; muvaffaqiyatlar; sinovlar count; total; hits; trials soni; jami; muvaffaqiyatlar; sinovlar dividend; divisor bo'linuvchi; bo'luvchi x; exponent_bits; significand_bits [; exponent_bias] x; eksponent_bitlari; mantissa_bitlari [; eksponent_siljishi] base; x asos; x value; modulo qiymat; modul base; exponent; modulo asos; daraja; modul events; average_events hodisalar; ortacha_hodisalar average_events ortacha_hodisalar x [; precision] x [; aniqlik] Absolute Value Absolyut qiymat Absolute Deviation Absolyut chetlanish Arc Cosine Arkkosinus Logical AND Mantiqiy VA Area Hyperbolic Cosine Teskari giperbolik kosinus Area Hyperbolic Sine Teskari giperbolik sinus Area Hyperbolic Tangent Teskari giperbolik tangens Arc Sine Arksinus Arc Tangent Arktangens Arc Tangent with two Arguments Ikki argumentli arktangens Average (Arithmetic Mean) O'rtacha (arifmetik o'rtacha) Binomial Cumulative Distribution Function Binomial kumulyativ taqsimot funksiyasi Binomial Distribution Mean Binomial taqsimot o'rtachasi Binomial Probability Mass Function Binomial ehtimollik massasi funksiyasi Binomial Distribution Variance Binomial taqsimot dispersiyasi Cube Root Kub ildiz Complex Conjugate Kompleks qo'shma Cosine Kosinus Hyperbolic Cosine Giperbolik kosinus Cotangent Kotangens Cosecant Kosekans Convert Unix timestamp to Date Unix vaqt belgisini sanaga aylantirish Degrees of Arc Burchak darajalari Error Function Xato funksiyasi Complementary Error Function To'ldiruvchi xato funksiyasi Exponential Eksponenta Fractional Part Kasr qismi Extension of Factorials [= (x-1)!] Faktoriallar kengaytmasi [= (x-1)!] Greatest Common Divisor Eng katta umumiy bo'luvchi Geometric Mean Geometrik o'rtacha Gradians of arc Burchak gradianlari Hypergeometric Cumulative Distribution Function Gipergeometrik kumulyativ taqsimot funksiyasi Hypergeometric Distribution Mean Gipergeometrik taqsimot o'rtachasi Hypergeometric Probability Mass Function Gipergeometrik ehtimollik massasi funksiyasi Hypergeometric Distribution Variance Gipergeometrik taqsimot dispersiyasi Integer Quotient Butun bo'linma Integer Part Butun qism Imaginary Part Mavhum qism Decode IEEE-754 Binary Value IEEE-754 ikkilik qiymatini dekodlash Encode IEEE-754 Binary Value IEEE-754 ikkilik qiymatini kodlash Decode 16-bit Half-Precision Value 16 bitli yarim aniqlikdagi qiymatni dekodlash Encode 16-bit Half-Precision Value 16 bitli yarim aniqlikdagi qiymatni kodlash Decode 32-bit Single-Precision Value 32 bitli yakka aniqlikdagi qiymatni dekodlash Encode 32-bit Single-Precision Value 32 bitli yakka aniqlikdagi qiymatni kodlash Decode 64-bit Double-Precision Value 64 bitli ikki karra aniqlikdagi qiymatni dekodlash Encode 64-bit Double-Precision Value 64 bitli ikki karra aniqlikdagi qiymatni kodlash Decode 128-bit Quad-Precision Value 128 bitli to'rt karra aniqlikdagi qiymatni dekodlash Encode 128-bit Quad-Precision Value 128 bitli to'rt karra aniqlikdagi qiymatni kodlash Binary Logarithm Ikkilik logarifm Common Logarithm O'nlik logarifm Natural Logarithm Natural logarifm Logarithm to Arbitrary Base Ixtiyoriy asosli logarifm Mask to a bit size Bit o'lchamiga maskalash Maximum Maksimum Median Value (50th Percentile) Median qiymat (50-persentil) Minimum Minimum Modulo Modul Euclidean Modulo Yevklid modulosi Modular Exponentiation Modulyar darajaga ko'tarish Combination (Binomial Coefficient) Kombinatsiya (binomial koeffitsient) Logical NOT Mantiqiy EMAS Permutation (Arrangement) Permutatsiya (joylashtirish) Convert to Binary Representation Ikkilik ko'rinishga aylantirish Arithmetic Arifmetika Chemistry Kimyo Complex Kompleks Combinatorics Kombinatorika Probability Ehtimollik Statistics Statistika Aggregation Agregatsiya Random Tasodifiy Base conversion Asosni almashtirish Number formatting Son formatlash Integer arithmetic Butun son arifmetikasi Special functions Maxsus funksiyalar Exponential & Logarithmic Eksponentsial & logarifmik Angle conversion Burchakni aylantirish Trigonometry Trigonometriya Bitwise Bitli amallar Floating point Suzuvchi nuqta Date & Time Sana & vaqt Linear algebra Chiziqli algebra unix_timestamp; x hours offset to GMT unix_vaqt_belgisi; GMT ga nisbatan x soat siljish yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; GMT ga nisbatan x soat siljish [digits] [raqamlar] max [; min] maksimum [; minimum] List Literal Ro'yxat literali Convert to Padded Binary Representation To'ldirilgan ikkilik ko'rinishga aylantirish Round Toward +∞ (Ceiling) +∞ tomonga yaxlitlash (yuqoriga) Cosine plus Imaginary Sine Kosinus va mavhum sinus yig'indisi Convert to Cis Complex Form Cis kompleks shakliga aylantirish Matrix Column Count Matritsa ustunlari soni Population Correlation Matrix (n) Bosh to'plam korrelyatsiya matritsasi (n) Sample Correlation Matrix (n-1) Tanlanma korrelyatsiya matritsasi (n-1) Count Sanoq Population Covariance Matrix (n) Bosh to'plam kovariatsiya matritsasi (n) Sample Covariance Matrix (n-1) Tanlanma kovariatsiya matritsasi (n-1) Cross Product Vektor ko'paytma Convert Date to Unix timestamp Sanani Unix vaqt belgisiga aylantirish Convert to Decimal Representation O'nlik ko'rinishga aylantirish Determinant Determinant Convert to Sexagesimal Notation Oltmishlik notatsiyaga aylantirish Dot Product Skalyar ko'paytma Convert to Engineering Notation Muhandislik notatsiyasiga aylantirish Convert to Exponential Complex Form Eksponentsial kompleks shaklga aylantirish Round Toward −∞ (Floor) −∞ tomonga yaxlitlash (pastga) Flatten Matrix Matritsani tekislash Least Common Multiple Eng kichik umumiy karrali Convert to Hexadecimal Representation O'n oltilik ko'rinishga aylantirish Convert to Padded Hexadecimal Representation To'ldirilgan o'n oltilik ko'rinishga aylantirish Inverse Matrix Teskari matritsa Round to 16-bit Half-Precision Value 16 bitli yarim aniqlikdagi qiymatgacha yaxlitlash Round to 32-bit Single-Precision Value 32 bitli yakka aniqlikdagi qiymatgacha yaxlitlash Round to 64-bit Double-Precision Value 64 bitli ikki karra aniqlikdagi qiymatgacha yaxlitlash Round to 128-bit Quad-Precision Value 128 bitli to'rt karra aniqlikdagi qiymatgacha yaxlitlash Residual from 16-bit Half-Precision Rounding 16 bitli yarim aniqlikdagi yaxlitlash qoldig'i Residual from 32-bit Single-Precision Rounding 32 bitli yakka aniqlikdagi yaxlitlash qoldig'i Residual from 64-bit Double-Precision Rounding 64 bitli ikki karra aniqlikdagi yaxlitlash qoldig'i Residual from 128-bit Quad-Precision Rounding 128 bitli to'rt karra aniqlikdagi yaxlitlash qoldig'i Substance Mass Modda massasi Molarity Molyarlik Molar Mass Molyar massa Median Absolute Deviation Median absolyut chetlanish Mean O'rtacha Numerical Value of Quantity Kattalikning son qiymati Random Decimal Number Tasodifiy o'nlik son Random Integer Number Tasodifiy butun son Convert to Rational Representation Ratsional ko'rinishga aylantirish Convert to Octal Representation Sakkizlik ko'rinishga aylantirish Convert to Padded Octal Representation To'ldirilgan sakkizlik ko'rinishga aylantirish Vector or Matrix Norm Vektor yoki matritsa normasi Logical OR Mantiqiy YOKI Population Count (Hamming Weight) Bir bitlar soni (Hamming og'irligi) Phase of Complex Number Kompleks son fazasi Poissonian Cumulative Distribution Function Puasson kumulyativ taqsimot funksiyasi Poissonian Distribution Mean Puasson taqsimot o'rtachasi Poissonian Probability Mass Function Puasson ehtimollik massasi funksiyasi Poissonian Distribution Variance Puasson taqsimot dispersiyasi Convert to Phasor Complex Form Fazor kompleks shaklga aylantirish Convert to Rectangular Complex Form To'g'ri burchakli kompleks shaklga aylantirish Round Half Away from Zero Yarimni noldan uzoqlashtirib yaxlitlash Round Half Even Yarimni juftga yaxlitlash Nth Root N-darajali ildiz Convert to Scientific Notation Ilmiy notatsiyaga aylantirish Matrix Row Count Matritsa qatorlari soni List or Matrix Shape Ro'yxat yoki matritsa shakli Summation Yig'indi Population Standard Deviation (n) Bosh to'plam standart og'ishi (n) Sample Standard Deviation (n-1) Tanlanma standart og'ishi (n-1) Round Toward Zero (Truncation) Nol tomonga yaxlitlash (kesish) Matrix Trace Matritsa izi Transpose Matrix Matritsani transponirlash Population Variance (n) Bosh to'plam dispersiyasi (n) Sample Variance (n-1) Tanlanma dispersiyasi (n-1) Product Ko'paytma Radians Radianlar Matrix Rank Matritsa rangi Real Part Haqiqiy qism Secant Sekans Arithmetic Shift Left Arifmetik chapga siljitish Arithmetic Shift Right Arifmetik o'ngga siljitish Signum Ishora Sine Sinus Hyperbolic Sine Giperbolik sinus Square Root Kvadrat ildiz Sum Yig'indi Tangent Tangens Convert to Trigonometric Complex Form Trigonometrik kompleks shaklga aylantirish Turns Burilishlar Hyperbolic Tangent Giperbolik tangens Sign-extend a value Qiymat ishorasini kengaytirish Logical XOR Mantiqiy XOR FunctionsWidget Domain Soha All Hammasi Name Nomi Search Qidirish No match found Moslik topilmadi Identifier Identifikator HistoryWidget Remove All Calculations Above Yuqoridagi barcha hisoblashlarni olib tashlash Remove This Calculation Bu hisoblashni olib tashlash Remove All Calculations Below Quyidagi barcha hisoblashlarni olib tashlash Keypad Inverse cosine Teskari kosinus The last result Oxirgi natija Inverse sine Teskari sinus Inverse tangent Teskari tangens Evaluate expression Ifodani hisoblash Division Bo'lish Multiplication Ko'paytirish Subtraction Ayirish Addition Qo'shish Clear expression Ifodani tozalash Cosine Kosinus Backspace Orqaga o'chirish Scientific notation Ilmiy notatsiya Exponential Eksponenta Factorial Faktorial Natural logarithm Natural logarifm Left parenthesis Chap qavs Nth root N-darajali ildiz Argument separator Argument ajratkichi Square Kvadrat Common logarithm O'nlik logarifm Modulo Modul Contextual percentage Kontekstli foiz Power Daraja Right parenthesis O'ng qavs Sine Sinus Square root Kvadrat ildiz Tangent Tangens Pi Pi Decimal separator O'nlik ajratgich MainWindow Radian Radian Degree Daraja Gradian Gradian Binary Ikkilik Octal Sakkizlik Hexadecimal O'n oltilik Sexagesimal Oltmishlik Engineering decimal Muhandislik o'nligi Scientific decimal Ilmiy o'nlik &Import... &Import qilish... &Quit &Chiqish Clear E&xpression I&fodani tozalash Clear &History Tarixni &tozalash &Copy &Nusxalash &Paste &Qo'yish &Select Expression Ifodani &tanlash &Constants &Konstantalar &Functions &Funksiyalar &History &Tarix &Status Bar &Holat satri Bitfield Bit maydoni Use&r Functions Foydalanuvchi &funksiyalari &Degree &Daraja &Radian &Radian &Gradian &Gradian Re&volution &Aylanish Auto-Insert a&ns a&ns ni avtomatik kiritish Automatic &Completion Avtomatik &to'ldirish &Built-in Functions &Ichki funksiyalar Built-in &Variables Ichki oÊ»zgaru&vchilar User &Functions &Foydalanuvchi funksiyalari User Va&riables Foydalanuvchi o'zga&ruvchilari Open a Private Tab on Startup Ishga tushganda maxfiy varaq ochish Open and focus a new private tab whenever SpeedCrunch starts. SpeedCrunch har ishga tushganda yangi maxfiy varaq ochish va uni faollashtirish. Syntax &Highlighting Sintaksisni &ajratib ko'rsatish Group Digits in &Input K&iritilgan raqamlarni guruhlash Automatic Input &Adjustments Kiritishni &avtomatik tuzatish Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Operatorlar, boÊ»shliqlar, qavslar va darajalarni avtomatik tuzatish hamda faqat yaroqli belgilar kiritishga ruxsat berish. Group input digits using the selected number format. Kiritilgan raqamlarni tanlangan son formatiga koÊ»ra guruhlash. &Blinking Cursor &Miltillovchi kursor Blink the cursor in the expression editor. Ifoda tahrirlagichida kursorni miltillatish. &Escape Clears Editor &Escape tahrirlagichni tozalaydi Clear the focused expression editor with Escape after dismissing any popup or preview. Qalqib chiquvchi oynalar yoki oldindan koÊ»rish yopilgach, faol ifoda tahrirlagichini Escape bilan tozalash. Keep Expression After Evaluation Hisoblashdan keyin ifodani saqlash Copy New Results Automatically Yangi natijalarni avtomatik nusxalash &Comma &Vergul &System Default &Tizim standarti &Dot &Nuqta Dot &And Comma Nuqta &va vergul Toward +∞ (&ceil) +∞ tomon (&ceil) Toward −∞ (&floor) −∞ tomon (&floor) &Binary &Ikkilik &Engineering &Muhandislik &Hexadecimal O'n &oltilik &Octal &Sakkizlik &Scientific &Ilmiy User &Manual Foydalanuvchi &qo'llanmasi Issues and &Feedback Muammolar va &fikr-mulohazalar &Donate &Xayriya qilish &About SpeedCrunch SpeedCrunch h&aqida App Diag&nostics Ilova diag&nostikasi S&plit Bo&Ê»lish Angle &Mode Burchak reji&mi &Complex Form Kom&pleks shakl New Tab Yangi varaq Constants Konstantalar Functions Funksiyalar History Tarix User Functions Foydalanuvchi funksiyalari &Font... &Shrift... &Language... &Til... &Session &Sessiya &Edit &Tahrirlash &View &Ko'rinish Se&ttings So&zlamalar &Decimal &O'nlik &Keypad &Klaviatura Always on &Top Har doim &tepada Disabled O'chirilgan Small Space Kichik bo'shliq Medium Space O'rta bo'shliq Large Space Katta bo'shliq &0 Digits &0 ta raqam &15 Digits &15 ta raqam &2 Digits &2 ta raqam &3 Digits &3 ta raqam &50 Digits &50 ta raqam &8 Digits &8 ta raqam &Sexagesimal &Oltmishlik Reset All Settings... Barcha sozlamalarni tiklash... &System &Tizim SpeedCrunch &Theme &SpeedCrunch mavzusi &Classic &Klassik &Modern &Zamonaviy Context Help Kontekst yordami &Help &Yordam Error Xato Can't read from file %1 %1 faylidan o'qib bo'lmadi Import Session Sessiyani import qilish Close Session Sessiyani yopish Angle Mode: Burchak rejimi: Notation: Notatsiya: Precision: Aniqlik: Turn Burilish Revolution Aylanish Fixed-point decimal Qo'zg'almas nuqtali o'nlik Rational Ratsional Automatic decimal Avtomatik o'nlik Automatic Avtomatik User &Definitions... Foydalanuvchi &ta'riflari... New &Tab Yangi &varaq New &Private Tab &Yangi maxfiy varaq Keep Saqlab qolish Make Private... Maxfiy qilish... New &Window Yangi &oyna &Open... &Ochish... &Rename... &Qayta nomlash... Clo&ne... Klo&nlash... &Close Tab V&araqni yopish Reopen Clo&sed Tab Yopilgan varaqni qayta ochi&sh Open Sessions &Folder Sessiyalar &jildini ochish &Undo &Bekor qilish &Redo Qayta&rish Cu&t &Kesish Copy &Last Result Oxirgi natijani nusxa&lash &Wrap in Parentheses Q&avs ichiga olish Full Scr&een Mode ToÊ»liq &ekran rejimi &Basic &Asosiy &Scientific (wide) &Ilmiy (keng) Scientific (narrow) Ilmiy (tor) &Custom... &Maxsus... Main &Menu Asosiy &menyu User &Variables Foydalanuvchi &o'zgaruvchilari &Left &Chapga &Right &OÊ»ngga &Up Y&uqoriga &Down &Pastga Close Pa&ne Pa&nelni yopish User &Units Foydalanuvchi &birliklari &Turn &Burilish If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Yangi ifoda +, -, * yoki / bilan boshlansa, SpeedCrunch avval "ans"ni kiritadi. &Accept with Enter &Enter bilan qabul qilish Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Joriy avtomatik toÊ»ldirish taklifini avval yoÊ»nalish tugmalari bilan tanlamasdan Enter bilan qabul qilish. &Units &Birliklar Show Live Result &Preview Jonli natija &ko'rinishini ko'rsatish Save &Window Position on Exit Chiqishda &oyna joylashuvini saqlash Hover Highlighting Ustiga olib borganda ajratish Group Integer Part Only Faqat butun qismni guruhlash Number Format... Son formati... Notation && Precision... Notatsiya && aniqlik... After pressing Enter, keep the entered expression selected in the editor. Enter bosilgandan keyin kiritilgan ifoda editorda tanlangan holda qolsin. Never Hech qachon Always Har doim Only for Single-Line Expressions Faqat bir satrli ifodalar uchun Simplify Displayed Expressions Ko'rsatilgan ifodalarni soddalashtirish History Size &Limit... Tarix hajmi &chegarasi... Remove Trailing &Zeroes &Oxirgi nollarni olib tashlash Nearest, Half &Away (round) Eng yaqin, yarimni &noldan uzoqlashtirib (round) Nearest, Half &Even (roundeven) Eng yaqin, yarimni &juftga (roundeven) Toward &Zero (trunc) &Nol tomonga (trunc) &Fixed-Point &Qo'zg'almas nuqtali &Rational &Ratsional &Exponential (m·sâ�»Â¹) &Eksponentsial (m·sâ�»Â¹) &Fractional (m/s) &Kasrli (m/s) &Rectangular (a + bi) &To'g'ri burchakli (a + bi) Exponential (reâ�±á¶¿) Eksponentsial (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Trigonometrik (r(cos θ + i·sin θ)) Phasor (r∠θ) Fazor (r∠θ) &Theme... &Mavzu... Check for &Updates &Yangilanishlarni tekshirish Source Code Manba kodi &Zoom &Masshtab &Results &Natijalar Unit Notation Birlik notatsiyasi Rounding Mode Yaxlitlash rejimi &Notation &Notatsiya &Imaginary Unit &Mavhum birlik &Window &Oyna &Editing &Tahrirlash A&utocomplete A&vtoto'ldirish Up/Down Arrow History Yuqori/pastga strelka tarixi &Appearance &Ko'rinish &Menus M&enyular &Docks Biriktirila&digan panellar &Input and Results K&iritish va natijalar &Disabled &O'chirilgan &Disable &O'chirish Close preview Ko'rib chiqishni yopish Rename... Qayta nomlash... Clone... Klonlash... Close Tab Varaqni yopish New Private Tab Yangi maxfiy varaq Open... Ochish... Reopen Closed Tab Yopilgan varaqni qayta ochish Split BoÊ»lish Left Chapga Right OÊ»ngga Up Yuqoriga Down Pastga Clear Tozalash Delete O'chirish %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Maxfiy seans: yopilganda mazmuni tashlab yuboriladi. Oddiy seansga aylantirish uchun Sessiya > Saqlab qolish bandini tanlang. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Maxfiy] Reset All Settings Barcha sozlamalarni tiklash Reset all settings to their default values? Barcha sozlamalar standart qiymatlariga tiklansinmi? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Bunga koÊ»rinish, tahrirlash, natija formatlari va oyna sozlamalari kiradi. Hisob-kitoblaringiz, ochiq seanslar va foydalanuvchi taʼriflari saqlanadi. The settings file could not be written. Sozlamalar faylini yozib boÊ»lmadi. Clear this session's calculations, unfinished expression, variables, functions, and units? Bu seansning hisob-kitoblari, tugallanmagan ifodasi, oÊ»zgaruvchilari, funksiyalari va birliklari tozalansinmi? Global user definitions are kept. Global foydalanuvchi taʼriflari saqlanadi. Make Session Private Seansni maxfiy qilish The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Saqlangan %1 seansi oÊ»chiriladi. Uning mazmuni maxfiy seansda ochiq qoladi va oÊ»sha seans yopilganda yoki SpeedCrunch dasturidan chiqilganda tashlab yuboriladi. Make Private Maxfiy qilish Could not delete the saved session %1. Saqlangan %1 seansini oÊ»chirib boÊ»lmadi. Keep Session Seansni saqlab qolish Could not save the session. It remains private. Seansni saqlab boÊ»lmadi. U maxfiyligicha qoladi. Clone Session Seansni klonlash Could not save session file %1. %1 seans faylini saqlab boÊ»lmadi. Could not delete session file %1. %1 seans faylini oÊ»chirib boÊ»lmadi. JSON file (*.json);;Any file (*.*) JSON fayli (*.json);;Har qanday fayl (*.*) Export session as JSON Sessiyani JSON sifatida eksport qilish The selected file is not valid JSON: %1 Tanlangan fayl yaroqli JSON emas: %1 The selected file is not a SpeedCrunch session JSON file. Tanlangan fayl SpeedCrunch sessiyasi JSON fayli emas. This file uses an obsolete SpeedCrunch session format and cannot be imported. Bu fayl eskirgan SpeedCrunch sessiya formatidan foydalanadi va import qilib bo'lmaydi. The selected JSON file is missing the required $schema field. Tanlangan JSON faylida kerakli $schema maydoni yo'q. The selected JSON file uses an unsupported JSON schema: %1 Tanlangan JSON fayli qo'llab-quvvatlanmaydigan JSON sxemasidan foydalanadi: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Tanlangan JSON faylida SpeedCrunch sessiyasi sxemasi identifikatori ($id) yo'q. The selected JSON file uses an unsupported SpeedCrunch session format: %1 Tanlangan JSON fayli qo'llab-quvvatlanmaydigan SpeedCrunch sessiya formatidan foydalanadi: %1 The selected JSON file is missing the required session name. Tanlangan JSON faylida kerakli sessiya nomi yo'q. The selected JSON file has an empty session name. Tanlangan JSON faylida sessiya nomi bo'sh. The selected JSON file has invalid or incomplete SpeedCrunch session data. Tanlangan JSON faylida yaroqsiz yoki to'liq bo'lmagan SpeedCrunch sessiyasi ma'lumotlari bor. Open Sessions Folder Sessiyalar jildini ochish Could not create the sessions folder: %1 Sessiyalar jildini yaratib bo'lmadi: %1 Could not open the sessions folder: %1 Sessiyalar jildini ochib bo'lmadi: %1 Editor and Results Font Tahrirlagich va natijalar shrifti Open Session Sessiyani ochish Community Hamjamiyat Rename Session Sessiya nomini o'zgartirish Clear Session Sessiyani tozalash Delete Session Sessiyani o'chirish Close Pane Panelni yopish User Variables Foydalanuvchi o'zgaruvchilari User Units Foydalanuvchi birliklari Clear History Tarixni tozalash Are you sure you want to clear the calculation history? Hisoblash tarixini tozalashni xohlaysizmi? Session name: Sessiya nomi: A session named %1 already exists. %1 nomli sessiya allaqachon mavjud. Could not create session file %1. %1 sessiya faylini yaratib bo'lmadi. Could not write session file %1. %1 sessiya fayliga yozib bo'lmadi. Are you sure you want to delete this session? Bu sessiyani o'chirishni xohlaysizmi? Custom Precision Maxsus aniqlik Fractional digits: Kasr raqamlari: Theme Mavzu Light Themes Yorug' mavzular Dark Themes Qorong'i mavzular Preview Ko'rib chiqish Colors Ranglar Select color for %1 %1 uchun rangni tanlang Import... Import qilish... Export... Eksport qilish... Import Theme Mavzuni import qilish Theme file (*.json);;All files (*) Mavzu fayli (*.json);;Barcha fayllar (*) Invalid theme file. Mavzu fayli yaroqsiz. Can't import theme "%1" because it conflicts with a built-in theme. "%1" mavzusini import qilib bo'lmaydi, chunki u ichki mavzu bilan ziddiyatda. Can't find a writable theme folder. Yozish mumkin bo'lgan mavzu papkasi topilmadi. Overwrite Theme Mavzuni qayta yozish A custom theme named "%1" already exists. Do you want to overwrite it? "%1" nomli maxsus mavzu allaqachon mavjud. Uni qayta yozishni xohlaysizmi? Can't overwrite theme file %1 %1 mavzu faylini qayta yozib bo'lmadi Can't copy theme file to %1 Mavzu faylini %1 ga nusxalab bo'lmadi Export Theme Mavzuni eksport qilish Can't export theme as "%1" because it conflicts with a built-in theme. Mavzuni "%1" sifatida eksport qilib bo'lmaydi, chunki u ichki mavzu bilan ziddiyatda. Can't write to file %1 %1 fayliga yozib bo'lmadi Global User Variable Global foydalanuvchi o'zgaruvchisi Global User Function Global foydalanuvchi funksiyasi Global User Unit Global foydalanuvchi birligi User Definitions Foydalanuvchi ta'riflari These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Bu ta'riflar global bo'lib, har bir seansga yuklanadi. Ularni seanslarda o'zgartirib bo'lmaydi va ular seans tahrirlovchisidagi bir xil nomli ta'riflardan ustun turadi. Har bir qatorga bittadan ta'rif kiriting. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Misollar: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Qo'llash Validate Tekshirish Test Results Sinov natijalari Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Import qilingan o'zgaruvchilar: %1 Import qilingan funksiyalar: %2 Import qilingan birliklar: %3 Xatolari bor qator raqamlari: %4 none yo'q Apply Results Qo'llash natijalari User definitions saved. Foydalanuvchi ta'riflari saqlandi. History Size Limit Tarix hajmi chegarasi Maximum number of history entries for this session (0 = unlimited): Bu sessiya uchun tarix yozuvlarining maksimal soni (0 = cheksiz): Text file (*.txt);;Any file (*.*) Matn fayli (*.txt);;Har qanday fayl (*.*) Could not recalculate from calculation %1: %2 %1 hisoblashidan qayta hisoblab bo'lmadi: %2 History Size Limit Reached Tarix hajmi chegarasiga yetildi This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Bu hisoblash tarixdagi oxirgi bo'sh joyni to'ldiradi. Keyingi hisoblashlar tarixdan eng eski hisoblashni olib tashlaydi. Chegarani Sessiya > Tarix hajmi chegarasi orqali oshirishingiz mumkin. Editing calculation. Press Esc twice to cancel. Hisoblash tahrirlanmoqda. Bekor qilish uchun Esc tugmasini ikki marta bosing. Calculation Settings Hisoblash sozlamalari Invalid recalculation start index Qayta hisoblash boshlanish indeksi yaroqsiz System Default Tizim standarti Language Til Select the language: Tilni tanlang: Custom Maxsus Decimal places: O'nlik xonalar: &Automatic &Avtomatik &Precision &Aniqlik Plain &text Oddiy &matn Formula &Book Formulalar &kitobi &Export &Eksport Export session as HTML Sessiyani HTML sifatida eksport qilish HTML file (*.html) HTML fayli (*.html) Export session as plain text Sessiyani oddiy matn sifatida eksport qilish ManualWindow SpeedCrunch Manual SpeedCrunch qo'llanmasi %1 - SpeedCrunch Manual %1 - SpeedCrunch qo'llanmasi NumberFormatDialog Number Format Son formati <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Natijalar va kiritilgan raqamlarni guruhlash uchun son formatini tanlang.</b><br/><br/>Eslatma: kiritilgan sonlarning aniq formatlari tanlangan koÊ»rsatish formatidan farq qilsa ham qabul qilinadi.<br/> QObject Global User Variable Global foydalanuvchi o'zgaruvchisi Global User Function Global foydalanuvchi funksiyasi Global User Unit Global foydalanuvchi birligi Backspace Orqaga o'chirish Clear expression Ifodani tozalash Evaluate expression Ifodani hisoblash Insert text Matn kiritish Automatic decimal Avtomatik o'nlik Fixed-point decimal Qo'zg'almas nuqtali o'nlik Engineering decimal Muhandislik o'nligi Scientific decimal Ilmiy o'nlik Rational Ratsional Binary Ikkilik Octal Sakkizlik Hexadecimal O'n oltilik Sexagesimal Oltmishlik Update Available Yangilanish mavjud A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Yangi versiya (%1) mavjud.<br/><a href="%2">Yuklab olish uchun veb-saytga o'ting.</a> Check for Updates Yangilanishlarni tekshirish SpeedCrunch %1 is up to date. SpeedCrunch %1 eng so'nggi versiyada. No connectivity. Please check your internet connection and try again. Ulanish yo'q. Internet aloqangizni tekshirib, qayta urinib ko'ring. Could not verify the latest available version. Eng so'nggi mavjud versiyani tekshirib bo'lmadi. ResultDisplay Scroll to bottom Pastga o'tish Edit Expression Ifodani tahrirlash Change Settings Sozlamalarni o'zgartirish New Tab Yangi varaq &Import... &Import qilish... &Export &Eksport Plain &text Oddiy &matn Copy Nusxalash Selection Tanlangan qism Select All Barchasini tanlash Expression Ifoda Result Natija Calculation Hisoblash Calculation as Single Line Bir qatordagi hisoblash Remove Olib tashlash This Calculation Bu hisoblash All Calculations Above Yuqoridagi barcha hisoblashlar All Calculations Below Pastdagi barcha hisoblashlar New Private Tab Yangi maxfiy varaq Session Sessiya Open... Ochish... Clone... Klonlash... Rename... Qayta nomlash... Keep Saqlab qolish Make Private... Maxfiy qilish... Clear Tozalash Delete O'chirish Close Yopish Split BoÊ»lish Left Chapga Right OÊ»ngga Up Yuqoriga Down Pastga Close Pane Panelni yopish Main Menu Asosiy menyu Cancel editing Tahrirlashni bekor qilish Copy result Natijani nusxalash Edit expression Ifodani tahrirlash Change settings Sozlamalarni o'zgartirish Remove calculation Hisoblashni olib tashlash ResultSlotsDialog Notation & Precision Notatsiya & aniqlik Result Line Natija satri Enabled Yoqilgan Notation Notatsiya Decimal Places O'nlik xonalar Main Line Asosiy satr Extra Line #1 Qo'shimcha satr #1 Extra Line #2 Qo'shimcha satr #2 Extra Line #3 Qo'shimcha satr #3 Extra Line #4 Qo'shimcha satr #4 Auto Avto UserFunctionListWidget Name Nomi Value Qiymati Description Tavsif Search Qidirish No match found Moslik topilmadi Insert Kiritish Edit Tahrirlash Delete O'chirish Delete All Hammasini o'chirish UserUnitListWidget Name Nomi Value Qiymati Description Tavsif Search Qidirish No match found Moslik topilmadi Insert Kiritish Edit Tahrirlash Delete O'chirish Delete All Hammasini o'chirish VariableListWidget Name Nomi Value Qiymati Description Tavsif Search Qidirish No match found Moslik topilmadi Insert Kiritish Edit Tahrirlash Delete O'chirish Delete All Hammasini o'chirish heldercorreia-speedcrunch-e7ca37f/src/resources/locale/vi.ts000066400000000000000000010657461526573132500244060ustar00rootroot00000000000000 AboutBox About SpeedCrunch Giá»›i thiệu SpeedCrunch Core developers Ngưá»�i phát triển chính Original author Tác giả gốc Close Ä�óng Math engine Công cụ toán há»�c Main author | Logo | Maintainer Tác giả chính | Logo | Ngưá»�i bảo trì Thanks Cảm Æ¡n Copyright (C) 2004-2026 The SpeedCrunch developers Bản quyá»�n (C) 2004-2026 Các nhà phát triển SpeedCrunch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version Chương trình này là phần má»�m tá»± do; bạn có thể phân phối lại và/hoặc sá»­a đổi nó theo các Ä‘iá»�u khoản cá»§a Giấy phép Công cá»™ng GNU do Free Software Foundation công bố; phiên bản 2 cá»§a Giấy phép hoặc (tùy chá»�n cá»§a bạn) bất kỳ phiên bản nào má»›i hÆ¡n This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Chương trình này được phân phối vá»›i hy vá»�ng rằng nó sẽ hữu ích, nhưng KHÔNG CÓ BẤT KỲ BẢO HÀNH NÀO; kể cả bảo hành ngụ ý vá»� KHẢ NÄ‚NG BÃ�N Ä�ƯỢC hoặc PHÙ HỢP VỚI MỘT MỤC Ä�Ã�CH CỤ THỂ. Xem Giấy phép Công cá»™ng GNU để biết thêm chi tiết. BitFieldWidget Reset bits to zero Ä�ặt lại các bit vá»� không Invert bits Ä�ảo các bit Shift bits left Dịch bit sang trái Shift bits right Dịch bit sang phải Book Index Mục lục Algebra Ä�ại số Quadratic Equation Phương trình bậc hai Logarithmic Base Conversion Chuyển đổi cÆ¡ số lôgarit Geometry Hình há»�c Circle Hình tròn Sector Hình quạt Sphere Hình cầu Cube Hình lập phương Cone Hình nón Cylinder Hình trụ Electronics Ä�iện tá»­ Ohm's Law Ä�ịnh luật Ôm Power Công suất Reactance Ä�iện kháng Resonance Cá»™ng hưởng Radio Frequency Tần số vô tuyến Antennas Ä‚ngten Characteristic Impedance (coax) Trở kháng đặc trưng (cáp đồng trục) Velocity of Propagation (coax) Vận tốc truyá»�n (cáp đồng trục) Standing Wave Ratio & Return Loss Tá»· số sóng đứng và suy hao phản hồi Free Space Wavelength Bước sóng trong không gian tá»± do resistance Ä‘iện trở voltage Ä‘iện áp current dòng Ä‘iện power công suất inductive reactance cảm kháng capacitive reactance dung kháng inductance Ä‘iện cảm capacitance Ä‘iện dung frequency tần số resonance frequency tần số cá»™ng hưởng area diện tích perimeter chu vi diameter đưá»�ng kính radius bán kính volume thể tích surface area diện tích bá»� mặt height chiá»�u cao slant height đưá»�ng sinh face diagonal đưá»�ng chéo mặt space diagonal đưá»�ng chéo không gian edge length độ dài cạnh arc length độ dài cung central angle (degrees) góc ở tâm (độ) input power công suất vào reflected power công suất phản xạ transmitted power công suất truyá»�n qua return loss suy hao phản hồi dielectric constant hằng số Ä‘iện môi outer conductor's inner diameter đưá»�ng kính trong cá»§a dây dẫn ngoài inner conductor's outer diameter đưá»�ng kính ngoài cá»§a dây dẫn trong speed of light tốc độ ánh sáng reflection coefficient hệ số phản xạ standing wave ratio tá»· số sóng đứng normalized impedance trở kháng chuẩn hóa frequency (Hz) tần số (Hz) BookDock Formula Book Sổ công thức ConstantCompletion Search constants Tìm hằng số No match found Không tìm thấy kết quả Constants Mathematics Toán há»�c Physics (CODATA 2022) Vật lý (CODATA 2022) Chemistry (IUPAC - CIAAW 2021) Hóa há»�c (IUPAC - CIAAW 2021) Uncategorized Chưa phân loại Universal Phổ quát Physicochemical Hóa lý Atomic & Nuclear — General Nguyên tá»­ và hạt nhân - Tổng quát Atomic & Nuclear — Electroweak Nguyên tá»­ và hạt nhân - Ä�iện yếu Atomic & Nuclear — Electron Nguyên tá»­ và hạt nhân - Electron Atomic & Nuclear — Muon Nguyên tá»­ và hạt nhân - Muon Atomic & Nuclear — Tau Nguyên tá»­ và hạt nhân - Tau Atomic & Nuclear — Proton Nguyên tá»­ và hạt nhân - Proton Atomic & Nuclear — Neutron Nguyên tá»­ và hạt nhân - Neutron Atomic & Nuclear — Deuteron Nguyên tá»­ và hạt nhân - Deuteron Atomic & Nuclear — Triton Nguyên tá»­ và hạt nhân - Triton Atomic & Nuclear — Helion Nguyên tá»­ và hạt nhân - Helion Atomic & Nuclear — Alpha particle Nguyên tá»­ và hạt nhân - Hạt alpha Atomic & Nuclear — Atomic units Nguyên tá»­ và hạt nhân - Ä�Æ¡n vị nguyên tá»­ Atomic & Nuclear — Energy conversion relationships Nguyên tá»­ và hạt nhân - Quan hệ chuyển đổi năng lượng Atomic & Nuclear — X-ray units Nguyên tá»­ và hạt nhân - Ä�Æ¡n vị tia X Atomic & Nuclear — Magnetic shielding corrections Nguyên tá»­ và hạt nhân - Hiệu chỉnh chắn từ Masses Khối lượng Lifetimes Thá»�i gian sống Molar Masses Khối lượng mol Electronegativity Ä�á»™ âm Ä‘iện Ionization Energy Năng lượng ion hóa Nominal Constants (IAU 2015) Hằng số danh nghÄ©a (IAU 2015) Current Best Estimates (IAU NSFA 2026-04) Ước lượng tốt nhất hiện tại (IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) trở kháng đặc trưng cá»§a chân không (Zâ‚€) reduced Planck constant (â„�) hằng số Planck rút gá»�n (â„�) vacuum electric permittivity (ϵ₀) hằng số Ä‘iện môi cá»§a chân không (ϵ₀) Newtonian constant of gravitation (G) hằng số hấp dẫn Newton (G) vacuum magnetic permeability (μ₀) độ từ thẩm cá»§a chân không (μ₀) Planck constant (h) hằng số Planck (h) speed of light in vacuum (c) tốc độ ánh sáng trong chân không (c) standard acceleration of gravity (gâ‚™) gia tốc trá»�ng trưá»�ng tiêu chuẩn (gâ‚™) Newtonian constant of gravitation over h-bar c hằng số hấp dẫn Newton trên h-bar c Planck length độ dài Planck Planck constant in eV/Hz (h) hằng số Planck theo eV/Hz (h) Planck mass khối lượng Planck Planck mass energy equivalent in GeV tương đương năng lượng khối lượng Planck theo GeV Planck temperature nhiệt độ Planck Planck time thá»�i gian Planck reduced Planck constant in eV·s (â„�) hằng số Planck rút gá»�n theo eV·s (â„�) reduced Planck constant times c in MeV·fm hằng số Planck rút gá»�n nhân c theo MeV·fm Bohr magneton magneton Bohr conductance quantum (Gâ‚€) lượng tá»­ độ dẫn (Gâ‚€) Coulomb constant (kâ‚‘) hằng số Coulomb (kâ‚‘) elementary charge (e) Ä‘iện tích cÆ¡ bản (e) elementary charge over h-bar Ä‘iện tích cÆ¡ bản trên h-bar conventional value of Josephson constant giá trị quy ước cá»§a hằng số Josephson Josephson constant hằng số Josephson conventional value of ampere-90 giá trị quy ước cá»§a ampere-90 conventional value of coulomb-90 giá trị quy ước cá»§a coulomb-90 conventional value of farad-90 giá trị quy ước cá»§a farad-90 conventional value of henry-90 giá trị quy ước cá»§a henry-90 conventional value of ohm-90 giá trị quy ước cá»§a ohm-90 conventional value of volt-90 giá trị quy ước cá»§a volt-90 conventional value of watt-90 giá trị quy ước cá»§a watt-90 magnetic flux quantum (Φ₀) lượng tá»­ từ thông (Φ₀) nuclear magneton magneton hạt nhân inverse of conductance quantum nghịch đảo cá»§a lượng tá»­ độ dẫn conventional value of von Klitzing constant giá trị quy ước cá»§a hằng số von Klitzing von Klitzing constant hằng số von Klitzing atomic unit of magnetic dipole moment đơn vị nguyên tá»­ cá»§a mômen lưỡng cá»±c từ atomic unit of magnetic flux density đơn vị nguyên tá»­ cá»§a mật độ từ thông Bohr magneton in eV/T magneton Bohr theo eV/T Bohr magneton in Hz/T magneton Bohr theo Hz/T Bohr magneton in inverse meter per tesla magneton Bohr theo mét nghịch đảo trên tesla Bohr magneton in K/T magneton Bohr theo K/T nuclear magneton in eV/T magneton hạt nhân theo eV/T nuclear magneton in inverse meter per tesla magneton hạt nhân theo mét nghịch đảo trên tesla nuclear magneton in K/T magneton hạt nhân theo K/T nuclear magneton in MHz/T magneton hạt nhân theo MHz/T Bohr radius (aâ‚€) bán kính Bohr (aâ‚€) fine-structure constant (α) hằng số cấu trúc tinh tế (α) Hartree energy (Eâ‚•) năng lượng Hartree (Eâ‚•) Hartree energy in eV năng lượng Hartree theo eV quantum of circulation lượng tá»­ tuần hoàn quantum of circulation times 2 lượng tá»­ tuần hoàn nhân 2 Rydberg constant (R∞) hằng số Rydberg (R∞) atomic mass unit-hartree relationship quan hệ đơn vị khối lượng nguyên tá»­-hartree atomic mass unit-hertz relationship quan hệ đơn vị khối lượng nguyên tá»­-hertz atomic mass unit-inverse meter relationship quan hệ đơn vị khối lượng nguyên tá»­-mét nghịch đảo atomic mass unit-joule relationship quan hệ đơn vị khối lượng nguyên tá»­-joule atomic mass unit-kelvin relationship quan hệ đơn vị khối lượng nguyên tá»­-kelvin atomic mass unit-kilogram relationship quan hệ đơn vị khối lượng nguyên tá»­-kilôgam atomic unit of 1st hyperpolarizability đơn vị nguyên tá»­ cá»§a siêu phân cá»±c bậc nhất atomic unit of 2nd hyperpolarizability đơn vị nguyên tá»­ cá»§a siêu phân cá»±c bậc hai atomic unit of charge (e) đơn vị nguyên tá»­ cá»§a Ä‘iện tích (e) atomic unit of charge density đơn vị nguyên tá»­ cá»§a mật độ Ä‘iện tích atomic unit of current đơn vị nguyên tá»­ cá»§a dòng Ä‘iện atomic unit of electric dipole moment đơn vị nguyên tá»­ cá»§a mômen lưỡng cá»±c Ä‘iện atomic unit of electric field đơn vị nguyên tá»­ cá»§a Ä‘iện trưá»�ng atomic unit of electric field gradient đơn vị nguyên tá»­ cá»§a gradient Ä‘iện trưá»�ng atomic unit of electric polarizability đơn vị nguyên tá»­ cá»§a độ phân cá»±c Ä‘iện atomic unit of electric potential đơn vị nguyên tá»­ cá»§a Ä‘iện thế atomic unit of electric quadrupole moment đơn vị nguyên tá»­ cá»§a mômen tứ cá»±c Ä‘iện atomic unit of action đơn vị nguyên tá»­ cá»§a tác dụng atomic unit of energy đơn vị nguyên tá»­ cá»§a năng lượng atomic unit of force đơn vị nguyên tá»­ cá»§a lá»±c atomic unit of length độ dài atomic unit of hertz-atomic mass unit relationship quan hệ hertz-đơn vị khối lượng nguyên tá»­ hertz-electron volt relationship quan hệ hertz-electronvolt hertz-hartree relationship quan hệ hertz-hartree hertz-inverse meter relationship quan hệ hertz-mét nghịch đảo hertz-joule relationship quan hệ hertz-joule hertz-kelvin relationship quan hệ hertz-kelvin hertz-kilogram relationship quan hệ hertz-kilôgam hyperfine transition frequency of Cs-133 tần số chuyển tiếp siêu tinh tế cá»§a Cs-133 inverse fine-structure constant (αâ�»Â¹) nghịch đảo hằng số cấu trúc tinh tế (αâ�»Â¹) inverse meter-atomic mass unit relationship quan hệ mét nghịch đảo-đơn vị khối lượng nguyên tá»­ inverse meter-electron volt relationship quan hệ mét nghịch đảo-electronvolt inverse meter-hartree relationship quan hệ mét nghịch đảo-hartree inverse meter-hertz relationship quan hệ mét nghịch đảo-hertz inverse meter-joule relationship quan hệ mét nghịch đảo-joule inverse meter-kelvin relationship quan hệ mét nghịch đảo-kelvin inverse meter-kilogram relationship quan hệ mét nghịch đảo-kilôgam joule-atomic mass unit relationship quan hệ joule-đơn vị khối lượng nguyên tá»­ joule-electron volt relationship quan hệ joule-electronvolt joule-hertz relationship quan hệ joule-hertz joule-hartree relationship quan hệ joule-hartree joule-inverse meter relationship quan hệ joule-mét nghịch đảo joule-kelvin relationship quan hệ joule-kelvin joule-kilogram relationship quan hệ joule-kilôgam kelvin-atomic mass unit relationship quan hệ kelvin-đơn vị khối lượng nguyên tá»­ kelvin-electron volt relationship quan hệ kelvin-electronvolt kelvin-hertz relationship quan hệ kelvin-hertz kelvin-hartree relationship quan hệ kelvin-hartree kelvin-inverse meter relationship quan hệ kelvin-mét nghịch đảo kelvin-joule relationship quan hệ kelvin-joule kelvin-kilogram relationship quan hệ kelvin-kilôgam kilogram-atomic mass unit relationship quan hệ kilôgam-đơn vị khối lượng nguyên tá»­ kilogram-electron volt relationship quan hệ kilôgam-electronvolt kilogram-hertz relationship quan hệ kilôgam-hertz kilogram-hartree relationship quan hệ kilôgam-hartree kilogram-inverse meter relationship quan hệ kilôgam-mét nghịch đảo kilogram-joule relationship quan hệ kilôgam-joule kilogram-kelvin relationship quan hệ kilôgam-kelvin lattice parameter of silicon (a) tham số mạng tinh thể cá»§a silic (a) luminous efficacy hiệu suất phát sáng natural unit of energy đơn vị tá»± nhiên cá»§a năng lượng natural unit of energy in MeV đơn vị tá»± nhiên cá»§a năng lượng theo MeV natural unit of action (â„�) đơn vị tá»± nhiên cá»§a tác dụng (â„�) natural unit of action in eV·s natural unit of action theo eV·s natural unit of length độ dài natural unit of natural unit of mass khối lượng natural unit of natural unit of momentum đơn vị tá»± nhiên cá»§a động lượng natural unit of momentum in MeV/c đơn vị tá»± nhiên cá»§a động lượng theo MeV/c natural unit of time thá»�i gian natural unit of natural unit of velocity đơn vị tá»± nhiên cá»§a vận tốc Rydberg constant times c in Hz Rydberg constant nhân c theo Hz Rydberg constant times hc in eV Rydberg constant nhân hc theo eV Rydberg constant times hc in J Rydberg constant nhân hc theo J Fermi coupling constant hằng số ghép Fermi weak mixing angle góc trá»™n yếu W to Z mass ratio tá»· số khối lượng W so vá»›i Z Thomson cross section (σₑ) tiết diện Thomson (σₑ) electron mass (mâ‚‘) khối lượng electron (mâ‚‘) electron mass in u khối lượng electron theo u electron mass energy equivalent (mₑ·c²) tương đương năng lượng khối lượng electron (mₑ·c²) electron mass energy equivalent in MeV tương đương năng lượng khối lượng electron theo MeV reduced Compton wavelength bước sóng Compton rút gá»�n classical electron radius (râ‚‘) bán kính electron cổ Ä‘iển (râ‚‘) electron charge to mass quotient thương số Ä‘iện tích trên khối lượng cá»§a electron electron-deuteron magnetic moment ratio tá»· số mômen từ electron-deuteron electron-deuteron mass ratio tá»· số khối lượng electron-deuteron electron g factor (gâ‚‘) hệ số g cá»§a electron (gâ‚‘) electron gyromagnetic ratio (γₑ) tá»· số từ hồi chuyển cá»§a electron (γₑ) electron gyromagnetic ratio in MHz/T tá»· số từ hồi chuyển cá»§a electron theo MHz/T electron-helion mass ratio tá»· số khối lượng electron-helion electron magnetic moment (μₑ) mômen từ cá»§a electron (μₑ) electron magnetic moment anomaly (aâ‚‘) dị thưá»�ng mômen từ cá»§a electron (aâ‚‘) electron magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a electron so vá»›i magneton Bohr electron magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a electron so vá»›i magneton hạt nhân electron molar mass (Mâ‚‘) khối lượng mol electron (Mâ‚‘) electron-muon magnetic moment ratio tá»· số mômen từ electron-muon electron-muon mass ratio tá»· số khối lượng electron-muon electron-neutron magnetic moment ratio tá»· số mômen từ electron-neutron electron-neutron mass ratio tá»· số khối lượng electron-neutron electron-proton magnetic moment ratio tá»· số mômen từ electron-proton electron-proton mass ratio tá»· số khối lượng electron-proton electron relative atomic mass (Ar(e)) khối lượng nguyên tá»­ tương đối cá»§a electron (Ar(e)) electron-tau mass ratio tá»· số khối lượng electron-tau electron to alpha particle mass ratio tá»· số khối lượng electron so vá»›i hạt alpha electron to shielded helion magnetic moment ratio tá»· số mômen từ cá»§a electron so vá»›i helion có chắn electron to shielded proton magnetic moment ratio tá»· số mômen từ cá»§a electron so vá»›i proton có chắn electron-triton mass ratio tá»· số khối lượng electron-triton electron volt-atomic mass unit relationship quan hệ electronvolt-đơn vị khối lượng nguyên tá»­ electron volt-hartree relationship quan hệ electronvolt-hartree electron volt-hertz relationship quan hệ electronvolt-hertz electron volt-inverse meter relationship quan hệ electronvolt-mét nghịch đảo electron volt-joule relationship quan hệ electronvolt-joule electron volt-kelvin relationship quan hệ electronvolt-kelvin electron volt-kilogram relationship quan hệ electronvolt-kilôgam hartree-atomic mass unit relationship quan hệ hartree-đơn vị khối lượng nguyên tá»­ hartree-electron volt relationship quan hệ hartree-electronvolt muon Compton wavelength bước sóng Compton cá»§a muon muon-electron mass ratio tá»· số khối lượng muon-electron muon g factor hệ số g cá»§a muon muon magnetic moment mômen từ cá»§a muon muon magnetic moment anomaly dị thưá»�ng mômen từ cá»§a muon muon magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a muon so vá»›i magneton Bohr muon magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a muon so vá»›i magneton hạt nhân muon mass khối lượng muon muon mass energy equivalent tương đương năng lượng khối lượng muon muon mass energy equivalent in MeV tương đương năng lượng khối lượng muon theo MeV muon mass in u khối lượng muon theo u muon molar mass khối lượng mol muon muon-neutron mass ratio tá»· số khối lượng muon-neutron muon-proton magnetic moment ratio tá»· số mômen từ muon-proton muon-proton mass ratio tá»· số khối lượng muon-proton muon-tau mass ratio tá»· số khối lượng muon-tau reduced muon Compton wavelength bước sóng Compton cá»§a reduced muon reduced tau Compton wavelength bước sóng Compton cá»§a reduced tau tau Compton wavelength bước sóng Compton cá»§a tau tau-electron mass ratio tá»· số khối lượng tau-electron tau mass khối lượng tau tau mass energy equivalent tương đương năng lượng khối lượng tau tau mass in u khối lượng tau theo u tau molar mass khối lượng mol tau tau-muon mass ratio tá»· số khối lượng tau-muon tau-neutron mass ratio tá»· số khối lượng tau-neutron tau-proton mass ratio tá»· số khối lượng tau-proton proton charge to mass quotient thương số Ä‘iện tích trên khối lượng cá»§a proton proton Compton wavelength bước sóng Compton cá»§a proton proton-electron mass ratio tá»· số khối lượng proton-electron proton g factor (gₚ) hệ số g cá»§a proton (gₚ) proton gyromagnetic ratio (γₚ) tá»· số từ hồi chuyển cá»§a proton (γₚ) proton gyromagnetic ratio in MHz/T tá»· số từ hồi chuyển cá»§a proton theo MHz/T proton magnetic moment (μₚ) mômen từ cá»§a proton (μₚ) proton magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a proton so vá»›i magneton Bohr proton magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a proton so vá»›i magneton hạt nhân proton magnetic shielding correction hiệu chỉnh chắn cá»§a proton magnetic proton mass (mₚ) khối lượng proton (mₚ) proton mass energy equivalent tương đương năng lượng khối lượng proton proton mass energy equivalent in MeV tương đương năng lượng khối lượng proton theo MeV proton mass in u khối lượng proton theo u proton molar mass (Mₚ) khối lượng mol proton (Mₚ) proton-muon mass ratio tá»· số khối lượng proton-muon proton-neutron magnetic moment ratio tá»· số mômen từ proton-neutron proton-neutron mass ratio tá»· số khối lượng proton-neutron proton relative atomic mass (Ar(p)) khối lượng nguyên tá»­ tương đối cá»§a proton (Ar(p)) proton rms charge radius bán kính Ä‘iện tích rms cá»§a proton proton-tau mass ratio tá»· số khối lượng proton-tau reduced proton Compton wavelength bước sóng Compton cá»§a reduced proton shielded proton gyromagnetic ratio tá»· số từ hồi chuyển cá»§a proton có chắn shielded proton gyromagnetic ratio in MHz/T tá»· số từ hồi chuyển cá»§a proton có chắn theo MHz/T shielded proton magnetic moment mômen từ cá»§a proton có chắn shielded proton magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a proton có chắn so vá»›i magneton Bohr shielded proton magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a proton có chắn so vá»›i magneton hạt nhân neutron Compton wavelength bước sóng Compton cá»§a neutron neutron-electron magnetic moment ratio tá»· số mômen từ neutron-electron neutron-electron mass ratio tá»· số khối lượng neutron-electron neutron g factor (gâ‚™) hệ số g cá»§a neutron (gâ‚™) neutron gyromagnetic ratio (γₙ) tá»· số từ hồi chuyển cá»§a neutron (γₙ) neutron gyromagnetic ratio in MHz/T tá»· số từ hồi chuyển cá»§a neutron theo MHz/T neutron magnetic moment (μₙ) mômen từ cá»§a neutron (μₙ) neutron magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a neutron so vá»›i magneton Bohr neutron magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a neutron so vá»›i magneton hạt nhân neutron mass (mâ‚™) khối lượng neutron (mâ‚™) neutron mass energy equivalent tương đương năng lượng khối lượng neutron neutron mass energy equivalent in MeV tương đương năng lượng khối lượng neutron theo MeV neutron mass in u khối lượng neutron theo u neutron molar mass (Mâ‚™) khối lượng mol neutron (Mâ‚™) neutron-muon mass ratio tá»· số khối lượng neutron-muon neutron-proton magnetic moment ratio tá»· số mômen từ neutron-proton neutron-proton mass difference chênh lệch khối lượng neutron-proton neutron-proton mass difference energy equivalent tương đương năng lượng chênh lệch khối lượng neutron-proton neutron-proton mass difference energy equivalent in MeV tương đương năng lượng chênh lệch khối lượng neutron-proton theo MeV neutron-proton mass difference in u chênh lệch khối lượng neutron-proton theo u neutron-proton mass ratio tá»· số khối lượng neutron-proton neutron relative atomic mass (Ar(n)) khối lượng nguyên tá»­ tương đối cá»§a neutron (Ar(n)) neutron-tau mass ratio tá»· số khối lượng neutron-tau neutron to shielded proton magnetic moment ratio tá»· số mômen từ cá»§a neutron so vá»›i proton có chắn reduced neutron Compton wavelength bước sóng Compton cá»§a reduced neutron deuteron-electron magnetic moment ratio tá»· số mômen từ deuteron-electron deuteron-electron mass ratio tá»· số khối lượng deuteron-electron deuteron g factor hệ số g cá»§a deuteron deuteron magnetic moment mômen từ cá»§a deuteron deuteron magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a deuteron so vá»›i magneton Bohr deuteron magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a deuteron so vá»›i magneton hạt nhân deuteron mass khối lượng deuteron deuteron mass energy equivalent tương đương năng lượng khối lượng deuteron deuteron mass energy equivalent in MeV tương đương năng lượng khối lượng deuteron theo MeV deuteron mass in u khối lượng deuteron theo u deuteron molar mass khối lượng mol deuteron deuteron-neutron magnetic moment ratio tá»· số mômen từ deuteron-neutron deuteron-proton magnetic moment ratio tá»· số mômen từ deuteron-proton deuteron-proton mass ratio tá»· số khối lượng deuteron-proton deuteron relative atomic mass (Ar(d)) khối lượng nguyên tá»­ tương đối cá»§a deuteron (Ar(d)) deuteron rms charge radius bán kính Ä‘iện tích rms cá»§a deuteron triton-electron mass ratio tá»· số khối lượng triton-electron triton g factor (gₜ) hệ số g cá»§a triton (gₜ) triton magnetic moment (μₜ) mômen từ cá»§a triton (μₜ) triton magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a triton so vá»›i magneton Bohr triton magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a triton so vá»›i magneton hạt nhân triton mass (mₜ) khối lượng triton (mₜ) triton mass energy equivalent tương đương năng lượng khối lượng triton triton mass energy equivalent in MeV tương đương năng lượng khối lượng triton theo MeV triton mass in u khối lượng triton theo u triton molar mass (Mₜ) khối lượng mol triton (Mₜ) triton-proton mass ratio tá»· số khối lượng triton-proton triton relative atomic mass (Ar(t)) khối lượng nguyên tá»­ tương đối cá»§a triton (Ar(t)) triton to proton magnetic moment ratio tá»· số mômen từ cá»§a triton so vá»›i proton helion-electron mass ratio tá»· số khối lượng helion-electron helion g factor (gâ‚•) hệ số g cá»§a helion (gâ‚•) helion magnetic moment (μₕ) mômen từ cá»§a helion (μₕ) helion magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a helion so vá»›i magneton Bohr helion magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a helion so vá»›i magneton hạt nhân helion mass (mâ‚•) khối lượng helion (mâ‚•) helion mass energy equivalent tương đương năng lượng khối lượng helion helion mass energy equivalent in MeV tương đương năng lượng khối lượng helion theo MeV helion mass in u khối lượng helion theo u helion molar mass (Mâ‚•) khối lượng mol helion (Mâ‚•) helion-proton mass ratio tá»· số khối lượng helion-proton helion relative atomic mass (Ar(h)) khối lượng nguyên tá»­ tương đối cá»§a helion (Ar(h)) helion shielding shift độ dịch chắn cá»§a helion shielded helion gyromagnetic ratio tá»· số từ hồi chuyển cá»§a helion có chắn shielded helion gyromagnetic ratio in MHz/T tá»· số từ hồi chuyển cá»§a helion có chắn theo MHz/T shielded helion magnetic moment mômen từ cá»§a helion có chắn shielded helion magnetic moment to Bohr magneton ratio tá»· số mômen từ cá»§a helion có chắn so vá»›i magneton Bohr shielded helion magnetic moment to nuclear magneton ratio tá»· số mômen từ cá»§a helion có chắn so vá»›i magneton hạt nhân shielded helion to proton magnetic moment ratio tá»· số mômen từ cá»§a helion có chắn so vá»›i proton shielded helion to shielded proton magnetic moment ratio tá»· số mômen từ cá»§a helion có chắn so vá»›i proton có chắn alpha particle mass khối lượng hạt alpha alpha particle mass in u khối lượng hạt alpha theo u alpha particle mass energy equivalent tương đương năng lượng khối lượng hạt alpha alpha particle mass energy equivalent in MeV tương đương năng lượng khối lượng hạt alpha theo MeV alpha particle-electron mass ratio tá»· số khối lượng hạt alpha-electron alpha particle-proton mass ratio tá»· số khối lượng hạt alpha-proton alpha particle rms charge radius bán kính Ä‘iện tích rms cá»§a hạt alpha alpha particle molar mass khối lượng mol hạt alpha alpha particle relative atomic mass (Ar(α)) khối lượng nguyên tá»­ tương đối cá»§a hạt alpha (Ar(α)) atomic mass constant (mᵤ) hằng số khối lượng nguyên tá»­ (mᵤ) Avogadro constant hằng số Avogadro Boltzmann constant (k) hằng số Boltzmann (k) Boltzmann constant in eV/K hằng số Boltzmann theo eV/K Boltzmann constant in Hz/K hằng số Boltzmann theo Hz/K Boltzmann constant in inverse meter per kelvin hằng số Boltzmann theo mét nghịch đảo trên kelvin electron volt (eV) electronvolt (eV) Faraday constant (F) hằng số Faraday (F) first radiation constant (câ‚�) hằng số bức xạ thứ nhất (câ‚�) first radiation constant for spectral radiance hằng số bức xạ thứ nhất cho độ chói phổ molar gas constant (R) hằng số khí mol (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) hằng số Loschmidt (nâ‚€, 273,15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) hằng số Loschmidt (nâ‚€, 273,15 K, 101,325 kPa) molar Planck constant hằng số Planck mol second radiation constant (câ‚‚) hằng số bức xạ thứ hai (câ‚‚) Stefan-Boltzmann constant (σ) hằng số Stefan-Boltzmann (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) khoảng cách mạng cá»§a Si lý tưởng (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent tương đương năng lượng cá»§a hằng số khối lượng nguyên tá»­ atomic mass constant energy equivalent in MeV tương đương năng lượng cá»§a hằng số khối lượng nguyên tá»­ theo MeV atomic mass unit-electron volt relationship quan hệ đơn vị khối lượng nguyên tá»­-electronvolt molar mass constant (Mᵤ) hằng số khối lượng mol (Mᵤ) molar mass of carbon-12 khối lượng mol cá»§a carbon-12 molar volume of ideal gas (273.15 K, 100 kPa) thể tích mol cá»§a khí lý tưởng (273,15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) thể tích mol cá»§a khí lý tưởng (273,15 K, 101,325 kPa) molar volume of silicon thể tích mol cá»§a silic Sackur-Tetrode constant (1 K, 100 kPa) hằng số Sackur-Tetrode (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) hằng số Sackur-Tetrode (1 K, 101,325 kPa) Wien frequency displacement law constant hằng số định luật dịch chuyển tần số Wien Wien wavelength displacement law constant hằng số định luật dịch chuyển bước sóng Wien standard atmosphere (atm) áp suất khí quyển tiêu chuẩn (atm) standard-state pressure (p°) áp suất trạng thái chuẩn (p°) Angstrom star (Ã…*) Angstrom sao (Ã…*) Copper x unit đơn vị x đồng Molybdenum x unit đơn vị x molypden atomic unit of magnetizability đơn vị nguyên tá»­ cá»§a độ từ hóa atomic unit of mass (mâ‚‘) khối lượng atomic unit of (mâ‚‘) atomic unit of momentum đơn vị nguyên tá»­ cá»§a động lượng atomic unit of permittivity đơn vị nguyên tá»­ cá»§a hằng số Ä‘iện môi atomic unit of time thá»�i gian atomic unit of atomic unit of velocity đơn vị nguyên tá»­ cá»§a vận tốc hartree-hertz relationship quan hệ hartree-hertz hartree-inverse meter relationship quan hệ hartree-mét nghịch đảo hartree-joule relationship quan hệ hartree-joule hartree-kelvin relationship quan hệ hartree-kelvin hartree-kilogram relationship quan hệ hartree-kilôgam shielding difference of d and p in HD chênh lệch chắn giữa d và p trong HD shielding difference of t and p in HT chênh lệch chắn giữa t và p trong HT pi (Ï€) pi (Ï€) Euler's number (e) Số Euler (e) golden ratio (φ) Tá»· lệ vàng (φ) Euler-Mascheroni constant (γ) Hằng số Euler-Mascheroni (γ) nominal solar radius bán kính Mặt Trá»�i danh nghÄ©a nominal solar total irradiance tổng độ chiếu xạ Mặt Trá»�i danh nghÄ©a nominal solar luminosity độ sáng Mặt Trá»�i danh nghÄ©a nominal solar effective temperature nhiệt độ hiệu dụng Mặt Trá»�i danh nghÄ©a nominal solar mass parameter tham số khối lượng Mặt Trá»�i danh nghÄ©a nominal terrestrial equatorial radius bán kính xích đạo Trái Ä�ất danh nghÄ©a nominal terrestrial polar radius bán kính cá»±c Trái Ä�ất danh nghÄ©a nominal terrestrial mass parameter tham số khối lượng Trái Ä�ất danh nghÄ©a nominal jovian equatorial radius bán kính xích đạo Sao Má»™c danh nghÄ©a nominal jovian polar radius bán kính cá»±c Sao Má»™c danh nghÄ©a nominal jovian mass parameter tham số khối lượng Sao Má»™c danh nghÄ©a average value of one minus the rate of TCG relative to TCB giá trị trung bình cá»§a má»™t trừ tốc độ TCG tương đối vá»›i TCB solar mass parameter (TCB-compatible) tham số khối lượng Mặt Trá»�i (tương thích TCB) solar mass parameter (TDB-compatible) tham số khối lượng Mặt Trá»�i (tương thích TDB) equatorial radius of the Earth (TT-compatible) bán kính xích đạo cá»§a Trái Ä�ất (tương thích TT) dynamical form factor of the Earth hệ số dạng động lá»±c cá»§a Trái Ä�ất time rate of change in the dynamical form factor of the Earth tốc độ thay đổi theo thá»�i gian cá»§a hệ số dạng động lá»±c cá»§a Trái Ä�ất geocentric gravitational constant (TCB-compatible) hằng số hấp dẫn địa tâm (tương thích TCB) geocentric gravitational constant (TT-compatible) hằng số hấp dẫn địa tâm (tương thích TT) geocentric gravitational constant (TDB-compatible) hằng số hấp dẫn địa tâm (tương thích TDB) potential of the geoid thế năng cá»§a geoid nominal mean angular velocity of the Earth (TT-compatible) vận tốc góc trung bình danh nghÄ©a cá»§a Trái Ä�ất (tương thích TT) ratio mass of the Moon to the Earth tá»· số khối lượng Mặt Trăng so vá»›i Trái Ä�ất ratio of the mass of the Sun to Mercury tá»· số khối lượng Mặt Trá»�i so vá»›i Sao Thá»§y ratio of the mass of the Sun to Venus tá»· số khối lượng Mặt Trá»�i so vá»›i Sao Kim ratio of the mass of the Sun to Mars tá»· số khối lượng Mặt Trá»�i so vá»›i Sao Há»�a ratio of the mass of the Sun to Jupiter tá»· số khối lượng Mặt Trá»�i so vá»›i Sao Má»™c ratio of the mass of the Sun to Saturn tá»· số khối lượng Mặt Trá»�i so vá»›i Sao Thổ ratio of the mass of the Sun to Uranus tá»· số khối lượng Mặt Trá»�i so vá»›i Sao Thiên Vương ratio of the mass of the Sun to Neptune tá»· số khối lượng Mặt Trá»�i so vá»›i Sao Hải Vương ratio of the mass of the Sun to (134340) Pluto tá»· số khối lượng Mặt Trá»�i so vá»›i (134340) Pluto ratio of the mass of the Sun to (136199) Eris tá»· số khối lượng Mặt Trá»�i so vá»›i (136199) Eris ratio of the mass of (1) Ceres to the Sun tá»· số khối lượng (1) Ceres so vá»›i Mặt Trá»�i ratio of the mass of (2) Pallas to the Sun tá»· số khối lượng (2) Pallas so vá»›i Mặt Trá»�i ratio of the mass of (4) Vesta to the Sun tá»· số khối lượng (4) Vesta so vá»›i Mặt Trá»�i mean obliquity of the ecliptic at J2000.0 độ nghiêng trung bình cá»§a hoàng đạo tại J2000.0 Electromagnetic Ä�iện từ Compton wavelength Bước sóng Compton Astronomy Thiên văn há»�c ConstantsWidget Domain Miá»�n Subdomain Miá»�n con No match found Không tìm thấy kết quả Name Tên Value Giá trị Unit Ä�Æ¡n vị Search Tìm kiếm All Tất cả CustomKeypadDialog Custom Keypad Bàn phím tùy chỉnh Rows: Hàng: Columns: Cá»™t: Copy preset: Sao chép mẫu định sẵn: Basic CÆ¡ bản Scientific (wide) Khoa há»�c (rá»™ng) Scientific (narrow) Khoa há»�c (hẹp) Apply Ã�p dụng Row Hàng Column Cá»™t Label Nhãn Behavior Hành vi Text Văn bản DiagnosticsDialog App Diagnostics Chẩn Ä‘oán ứng dụng Copy to Clipboard Sao chép vào bá»™ nhá»› tạm Editor Unit Ä�Æ¡n vị User unit Ä�Æ¡n vị ngưá»�i dùng User function Hàm ngưá»�i dùng Argument Ä�ối số Current result:<br/>%1 Kết quả hiện tại:<br/>%1 Selection result:<br/>%1 Kết quả vùng chá»�n:<br/>%1 Selection result: n/a Kết quả chá»�n: n/a Selection result: %1 Kết quả vùng chá»�n: %1 second giây metre mét kilogram kilôgam mole mol radian radian steradian steradian degree Celsius độ Celsius cubic metre mét khối cubic millimetre milimét khối cubic centimetre xentimét khối cubic decimetre đêximét khối cubic kilometre kilômét khối square millimetre milimét vuông square kilometre kilômét vuông square metre mét vuông minute phút hour giá»� day ngày astronomical unit đơn vị thiên văn degree độ arcminute phút cung arcsecond giây cung milliarcsecond mili giây cung microarcsecond micro giây cung hectare hecta litre lít tonne tấn Dalton dalton electronvolt electronvolt Angstrom angstrom atmosphere atmôtphe atomic mass unit đơn vị khối lượng nguyên tá»­ British thermal unit đơn vị nhiệt Anh calorie calo carat carat cup cốc cup (Imperial) cốc (Anh) cup (Japanese) cốc (Nhật) cup (US) cốc (Mỹ) degree Fahrenheit độ Fahrenheit fathom sải fluid ounce (Imperial) ounce lá»�ng (Anh) fluid ounce (US) ounce lá»�ng (Mỹ) fluid dram (Imperial) dram lá»�ng (Anh) fluid dram (US) dram lá»�ng (Mỹ) foot foot square foot foot vuông cubic foot foot khối gallon (Imperial) gallon (Anh) gallon (US) gallon (Mỹ) gill (Imperial) gill (Anh) gill (US) gill (Mỹ) gradian gradian grain grain gram gam Hartley hartley Hartree energy unit đơn vị năng lượng Hartree horsepower mã lá»±c inch inch square inch inch vuông cubic inch inch khối karat karat knot hải lý má»—i giá»� lightminute phút ánh sáng lightsecond giây ánh sáng lightyear năm ánh sáng long ton tấn dài mile dặm square mile dặm vuông cubic mile dặm khối mile per hour dặm má»—i giá»� kilometre per hour kilômét má»—i giá»� nautical mile hải lý ounce ounce parsec parsec pint (Imperial) pint (Anh) pint (US) pint (Mỹ) pound pound pounds per square inch pound trên inch vuông quart (Imperial) quart (Anh) quart (US) quart (Mỹ) oil barrel thùng dầu beer barrel (US) thùng bia (Mỹ) square yard yard vuông cubic yard yard khối short ton tấn ngắn tablespoon thìa canh tablespoon (Australian) thìa canh (Úc) tablespoon (Imperial) thìa canh (Anh) tablespoon (US) thìa canh (Mỹ) dessert spoon thìa tráng miệng teaspoon thìa cà phê teaspoon (Imperial) thìa cà phê (Anh) teaspoon (US) thìa cà phê (Mỹ) turn vòng revolution vòng quay revolution per minute vòng má»—i phút week tuần kilowatt hour kilowatt giá»� millimetre of mercury milimét thá»§y ngân yard yard Julian century thế ká»· Julius Julian year năm Julius sidereal year năm thiên văn tropical year năm chí tuyến Evaluator invalid expression biểu thức không hợp lệ division by zero chia cho 0 too time consuming - computation was rejected mất quá nhiá»�u thá»�i gian - phép tính bị từ chối dimension mismatch - quantities with different dimensions cannot be compared, added, etc. không khá»›p thứ nguyên - các đại lượng có thứ nguyên khác nhau không thể so sánh, cá»™ng, v.v. invalid dimension - operation might require dimensionless arguments thứ nguyên không hợp lệ - phép toán có thể yêu cầu đối số không thứ nguyên Computation aborted - encountered numerical instability Ä�ã há»§y tính toán - gặp mất ổn định số há»�c invalid dimension - function might require dimensionless arguments thứ nguyên không hợp lệ - hàm có thể yêu cầu đối số không thứ nguyên error lá»—i unit must not be zero đơn vị không được bằng 0 Conversion failed - dimension mismatch Chuyển đổi thất bại - không khá»›p thứ nguyên unknown function or variable không rõ hàm hoặc biến recursion not supported không há»— trợ đệ quy cannot operate on a NaN không thể tính toán vá»›i NaN underflow - tiny result is out of SpeedCrunch's number range tràn dưới - kết quả quá nhá»� nằm ngoài phạm vi số cá»§a SpeedCrunch overflow - huge result is out of SpeedCrunch's number range tràn trên - kết quả quá lá»›n nằm ngoài phạm vi số cá»§a SpeedCrunch overflow - logic result exceeds maximum of 256 bits tràn trên - kết quả logic vượt quá tối Ä‘a 256 bit overflow - integer result exceeds maximum limit for integers tràn trên - kết quả số nguyên vượt quá giá»›i hạn tối Ä‘a cho số nguyên operation is not defined for these arguments phép toán không được định nghÄ©a cho các đối số này wrong number of arguments sai số lượng đối số does not take NaN as an argument không nhận NaN làm đối số result out of range kết quả nằm ngoài phạm vi undefined for argument domain không xác định vá»›i miá»�n đối số computation too expensive tính toán quá tốn kém internal error, please report a bug lá»—i ná»™i bá»™, vui lòng báo lá»—i syntax error lá»—i cú pháp conversion target must be a unit đích chuyển đổi phải là má»™t đơn vị unknown unit không rõ đơn vị %1 is a reserved name, please choose another %1 là tên dành riêng, vui lòng chá»�n tên khác %1 is a global user definition and cannot be overridden in this session. %1 là định nghÄ©a ngưá»�i dùng toàn cục và không thể bị ghi đè trong phiên này. %1 is a variable name, please choose another or delete the variable %1 là tên biến, vui lòng chá»�n tên khác hoặc xóa biến argument %1 is used more than once đối số %1 sá»­ dụng nhiá»�u hÆ¡n má»™t lần %1 is a built-in unit name, please choose another %1 là tên đơn vị có sẵn, vui lòng chá»�n tên khác %1 is a user function name, please choose another or delete the function %1 là tên hàm ngưá»�i dùng, vui lòng chá»�n tên khác hoặc xóa hàm FunctionRepo max; trials; probability tối_Ä‘a; số_lần_thá»­; xác_suất trials; probability số_lần_thá»­; xác_suất hits; trials; probability số_lần_thành_công; số_lần_thá»­; xác_suất max; total; hits; trials tối_Ä‘a; tổng; số_lần_thành_công; số_lần_thá»­ total; hits; trials tổng; số_lần_thành_công; số_lần_thá»­ count; total; hits; trials số_lượng; tổng; số_lần_thành_công; số_lần_thá»­ dividend; divisor số_bị_chia; số_chia x; exponent_bits; significand_bits [; exponent_bias] x; bit_số_mÅ©; bit_phần_định_trị [; độ_lệch_số_mÅ©] base; x cÆ¡_số; x value; modulo giá_trị; môđun base; exponent; modulo cÆ¡_số; số_mÅ©; môđun events; average_events sá»±_kiện; số_sá»±_kiện_trung_bình average_events số_sá»±_kiện_trung_bình x [; precision] x [; độ_chính_xác] Absolute Value Giá trị tuyệt đối Absolute Deviation Ä�á»™ lệch tuyệt đối Arc Cosine Arccos Logical AND AND logic Area Hyperbolic Cosine Arcosh Area Hyperbolic Sine Arsinh Area Hyperbolic Tangent Artanh Arc Sine Arcsin Arc Tangent Arctan Arc Tangent with two Arguments Arctan vá»›i hai đối số Average (Arithmetic Mean) Trung bình cá»™ng Binomial Cumulative Distribution Function Hàm phân phối tích lÅ©y nhị thức Binomial Distribution Mean Trung bình cá»§a phân phối nhị thức Binomial Probability Mass Function Hàm khối xác suất nhị thức Binomial Distribution Variance Phương sai cá»§a phân phối nhị thức Cube Root Căn bậc ba Complex Conjugate Liên hợp phức Cosine Côsin Hyperbolic Cosine Côsin hyperbolic Cotangent Côtang Cosecant Côsec Convert Unix timestamp to Date Chuyển dấu thá»�i gian Unix thành ngày Degrees of Arc Ä�á»™ cung Error Function Hàm lá»—i Complementary Error Function Hàm lá»—i bù Exponential Hàm mÅ© Fractional Part Phần lẻ Extension of Factorials [= (x-1)!] Mở rá»™ng cá»§a giai thừa [= (x-1)!] Greatest Common Divisor Ước chung lá»›n nhất Geometric Mean Trung bình nhân Gradians of arc Grad cung Hypergeometric Cumulative Distribution Function Hàm phân phối tích lÅ©y siêu bá»™i Hypergeometric Distribution Mean Trung bình cá»§a phân phối siêu bá»™i Hypergeometric Probability Mass Function Hàm khối xác suất siêu bá»™i Hypergeometric Distribution Variance Phương sai cá»§a phân phối siêu bá»™i Integer Quotient Thương nguyên Integer Part Phần nguyên Imaginary Part Phần ảo Decode IEEE-754 Binary Value Giải mã giá trị nhị phân IEEE-754 Encode IEEE-754 Binary Value Mã hóa giá trị nhị phân IEEE-754 Decode 16-bit Half-Precision Value Giải mã giá trị bán chính xác 16 bit Encode 16-bit Half-Precision Value Mã hóa giá trị bán chính xác 16 bit Decode 32-bit Single-Precision Value Giải mã giá trị chính xác đơn 32 bit Encode 32-bit Single-Precision Value Mã hóa giá trị chính xác đơn 32 bit Decode 64-bit Double-Precision Value Giải mã giá trị chính xác kép 64 bit Encode 64-bit Double-Precision Value Mã hóa giá trị chính xác kép 64 bit Decode 128-bit Quad-Precision Value Giải mã giá trị chính xác bốn 128 bit Encode 128-bit Quad-Precision Value Mã hóa giá trị chính xác bốn 128 bit Binary Logarithm Lôgarit nhị phân Common Logarithm Lôgarit thập phân Natural Logarithm Lôgarit tá»± nhiên Logarithm to Arbitrary Base Lôgarit vá»›i cÆ¡ số tùy ý Mask to a bit size Tạo mặt nạ theo kích thước bit Maximum Lá»›n nhất Median Value (50th Percentile) Trung vị (phân vị thứ 50) Minimum Nhá»� nhất Modulo Phép lấy dư Euclidean Modulo Phép lấy dư Euclid Modular Exponentiation LÅ©y thừa môđun Combination (Binomial Coefficient) Tổ hợp (hệ số nhị thức) Logical NOT NOT logic Permutation (Arrangement) Chỉnh hợp Convert to Binary Representation Chuyển sang biểu diá»…n nhị phân Arithmetic Số há»�c Chemistry Hóa há»�c Complex Số phức Combinatorics Tổ hợp Probability Xác suất Statistics Thống kê Aggregation Tổng hợp Random Ngẫu nhiên Base conversion Chuyển đổi cÆ¡ số Number formatting Ä�ịnh dạng số Integer arithmetic Số há»�c số nguyên Special functions Hàm đặc biệt Exponential & Logarithmic Hàm mÅ© và lôgarit Angle conversion Chuyển đổi góc Trigonometry Lượng giác Bitwise Theo bit Floating point Dấu phẩy động Date & Time Ngày và giá»� Linear algebra Ä�ại số tuyến tính unix_timestamp; x hours offset to GMT dấu_thá»�i_gian_unix; độ_lệch_x_giá»�_so_vá»›i_GMT yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss; độ_lệch_x_giá»�_so_vá»›i_GMT [digits] [chữ_số] max [; min] tối_Ä‘a [; tối_thiểu] List Literal Danh sách literal Convert to Padded Binary Representation Chuyển sang biểu diá»…n nhị phân có đệm Round Toward +∞ (Ceiling) Làm tròn vá»� +∞ (ceil) Cosine plus Imaginary Sine Côsin cá»™ng sin ảo Convert to Cis Complex Form Chuyển sang dạng phức cis Matrix Column Count Số cá»™t ma trận Population Correlation Matrix (n) Ma trận tương quan tổng thể (n) Sample Correlation Matrix (n-1) Ma trận tương quan mẫu (n-1) Count Số lượng Population Covariance Matrix (n) Ma trận hiệp phương sai tổng thể (n) Sample Covariance Matrix (n-1) Ma trận hiệp phương sai mẫu (n-1) Cross Product Tích có hướng Convert Date to Unix timestamp Chuyển ngày thành dấu thá»�i gian Unix Convert to Decimal Representation Chuyển sang biểu diá»…n thập phân Determinant Ä�ịnh thức Convert to Sexagesimal Notation Chuyển sang ký hiệu lục thập phân Dot Product Tích vô hướng Convert to Engineering Notation Chuyển sang ký hiệu kỹ thuật Convert to Exponential Complex Form Chuyển sang dạng phức mÅ© Round Toward −∞ (Floor) Làm tròn vá»� −∞ (floor) Flatten Matrix Làm phẳng ma trận Least Common Multiple Bá»™i chung nhá»� nhất Convert to Hexadecimal Representation Chuyển sang biểu diá»…n thập lục phân Convert to Padded Hexadecimal Representation Chuyển sang biểu diá»…n thập lục phân có đệm Inverse Matrix Ma trận nghịch đảo Round to 16-bit Half-Precision Value Làm tròn vá»� giá trị bán chính xác 16 bit Round to 32-bit Single-Precision Value Làm tròn vá»� giá trị chính xác đơn 32 bit Round to 64-bit Double-Precision Value Làm tròn vá»� giá trị chính xác kép 64 bit Round to 128-bit Quad-Precision Value Làm tròn vá»� giá trị chính xác bốn 128 bit Residual from 16-bit Half-Precision Rounding Phần dư từ làm tròn bán chính xác 16 bit Residual from 32-bit Single-Precision Rounding Phần dư từ làm tròn chính xác đơn 32 bit Residual from 64-bit Double-Precision Rounding Phần dư từ làm tròn chính xác kép 64 bit Residual from 128-bit Quad-Precision Rounding Phần dư từ làm tròn chính xác bốn 128 bit Substance Mass Khối lượng chất Molarity Nồng độ mol Molar Mass Khối lượng mol Median Absolute Deviation Ä�á»™ lệch tuyệt đối trung vị Mean Trung bình Numerical Value of Quantity Giá trị số cá»§a đại lượng Random Decimal Number Số thập phân ngẫu nhiên Random Integer Number Số nguyên ngẫu nhiên Convert to Rational Representation Chuyển sang biểu diá»…n hữu tá»· Convert to Octal Representation Chuyển sang biểu diá»…n bát phân Convert to Padded Octal Representation Chuyển sang biểu diá»…n bát phân có đệm Vector or Matrix Norm Chuẩn vector hoặc ma trận Logical OR OR logic Population Count (Hamming Weight) Số bit 1 (trá»�ng số Hamming) Phase of Complex Number Pha cá»§a số phức Poissonian Cumulative Distribution Function Hàm phân phối tích lÅ©y Poisson Poissonian Distribution Mean Trung bình cá»§a phân phối Poisson Poissonian Probability Mass Function Hàm khối xác suất Poisson Poissonian Distribution Variance Phương sai cá»§a phân phối Poisson Convert to Phasor Complex Form Chuyển sang dạng phasor phức Convert to Rectangular Complex Form Chuyển sang dạng phức chữ nhật Round Half Away from Zero Làm tròn ná»­a ra xa 0 Round Half Even Làm tròn ná»­a chẵn Nth Root Căn bậc n Convert to Scientific Notation Chuyển sang ký hiệu khoa há»�c Matrix Row Count Số hàng ma trận List or Matrix Shape Kích thước danh sách hoặc ma trận Summation Tổng Population Standard Deviation (n) Ä�á»™ lệch chuẩn tổng thể (n) Sample Standard Deviation (n-1) Ä�á»™ lệch chuẩn mẫu (n-1) Round Toward Zero (Truncation) Làm tròn vá»� 0 (cắt cụt) Matrix Trace Vết ma trận Transpose Matrix Ma trận chuyển vị Population Variance (n) Phương sai tổng thể (n) Sample Variance (n-1) Phương sai mẫu (n-1) Product Tích Radians Radian Matrix Rank Hạng ma trận Real Part Phần thá»±c Secant Secant Arithmetic Shift Left Dịch trái số há»�c Arithmetic Shift Right Dịch phải số há»�c Signum Dấu Sine Sin Hyperbolic Sine Sin hyperbolic Square Root Căn bậc hai Sum Tổng Tangent Tang Convert to Trigonometric Complex Form Chuyển sang dạng phức lượng giác Turns Vòng Hyperbolic Tangent Tang hyperbolic Sign-extend a value Mở rá»™ng dấu cá»§a giá trị Logical XOR XOR logic FunctionsWidget Domain Miá»�n All Tất cả Name Tên Search Tìm kiếm No match found Không tìm thấy kết quả Identifier Ä�ịnh danh HistoryWidget Remove All Calculations Above Xóa tất cả phép tính phía trên Remove This Calculation Xóa phép tính này Remove All Calculations Below Xóa tất cả phép tính phía dưới Keypad Inverse cosine Côsin ngược The last result Kết quả cuối cùng Inverse sine Sin ngược Inverse tangent Tang ngược Evaluate expression Tính biểu thức Division Phép chia Multiplication Phép nhân Subtraction Phép trừ Addition Phép cá»™ng Clear expression Xóa biểu thức Cosine Côsin Backspace Xóa lùi Scientific notation Ký hiệu khoa há»�c Exponential Hàm mÅ© Factorial Giai thừa Natural logarithm Lôgarit tá»± nhiên Left parenthesis Dấu ngoặc trái Nth root Căn bậc n Argument separator Dấu phân cách đối số Square Bình phương Common logarithm Lôgarit thập phân Modulo Phép lấy dư Contextual percentage Phần trăm theo ngữ cảnh Power LÅ©y thừa Right parenthesis Dấu ngoặc phải Sine Sin Square root Căn bậc hai Tangent Tang Pi Pi Decimal separator Dấu phân cách thập phân MainWindow Radian Radian Degree Ä�á»™ Gradian Gradian Binary Nhị phân Octal Bát phân Hexadecimal Thập lục phân Sexagesimal Lục thập phân Engineering decimal Thập phân kỹ thuật Scientific decimal Thập phân khoa há»�c &Import... &Nhập... &Quit &Thoát Clear E&xpression Xóa &biểu thức Clear &History Xóa &lịch sá»­ &Copy &Sao chép &Paste &Dán &Select Expression &Chá»�n biểu thức &Constants &Hằng số &Functions &Hàm số &History &Lịch sá»­ &Status Bar Thanh &trạng thái Bitfield Trưá»�ng bit Use&r Functions Hàm &ngưá»�i dùng &Degree &Ä�á»™ &Radian &Radian &Gradian &Gradian Re&volution V&òng quay Auto-Insert a&ns Tá»± độ&ng chèn ans Automatic &Completion Tá»± động &hoàn thành &Built-in Functions &Hàm tích hợp Built-in &Variables &Biến tích hợp User &Functions H&àm tá»± định nghÄ©a User Va&riables B&iến ngưá»�i dùng Open a Private Tab on Startup Mở thẻ riêng tư khi khởi động Open and focus a new private tab whenever SpeedCrunch starts. Mở và chuyển tiêu Ä‘iểm đến má»™t thẻ riêng tư má»›i má»—i khi SpeedCrunch khởi động. Syntax &Highlighting Tô màu &cú pháp Group Digits in &Input Nh&óm chữ số đầu vào Automatic Input &Adjustments &Tá»± động Ä‘iá»�u chỉnh đầu vào Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. Tá»± động Ä‘iá»�u chỉnh toán tá»­, khoảng cách, dấu ngoặc và lÅ©y thừa, đồng thá»�i chỉ cho phép nhập ký tá»± hợp lệ. Group input digits using the selected number format. Nhóm các chữ số nhập vào theo định dạng số đã chá»�n. &Blinking Cursor &Con trá»� nhấp nháy Blink the cursor in the expression editor. Cho con trá»� nhấp nháy trong trình soạn thảo biểu thức. &Escape Clears Editor &Escape xóa ná»™i dung trình soạn thảo Clear the focused expression editor with Escape after dismissing any popup or preview. Xóa ná»™i dung trình soạn thảo biểu thức Ä‘ang có tiêu Ä‘iểm bằng Escape sau khi đóng má»�i cá»­a sổ bật lên hoặc bản xem trước. Keep Expression After Evaluation Giữ biểu thức sau khi tính Copy New Results Automatically Tá»± động sao chép kết quả má»›i &Comma Dấu &phẩy &System Default &Mặc định hệ thống &Dot Dấu &chấm Dot &And Comma Dấu chấm &và dấu phẩy Toward +∞ (&ceil) &Vá»� phía +∞ (ceil) Toward −∞ (&floor) Vá»� phía −∞ (&floor) &Binary &Nhị phân &Engineering &Kỹ thuật &Hexadecimal Hệ thập &lục phân &Octal Hệ &bát phân &Scientific &Khoa há»�c User &Manual Hướng &dẫn Issues and &Feedback &Vấn Ä‘á»� và phản hồi &Donate &Ủng há»™ &About SpeedCrunch &Giá»›i thiệu SpeedCrunch App Diag&nostics Chẩ&n Ä‘oán ứng dụng S&plit Ch&ia Angle &Mode C&hế độ góc &Complex Form Dạng số phứ&c New Tab Thẻ má»›i Constants Hằng số Functions Hàm số History Lịch sá»­ User Functions Hàm tá»± định nghÄ©a &Font... &Phông chữ... &Language... &Ngôn ngữ... &Session &Phiên làm việc &Edit &Sá»­a &View &Xem Se&ttings Cài đặ&t &Decimal &Thập phân &Keypad &Bàn phím Always on &Top &Luôn hiển thị lên trên Disabled Ä�ã tắt Small Space Khoảng trắng nhá»� Medium Space Khoảng trắng vừa Large Space Khoảng trắng lá»›n &0 Digits &0 chữ số &15 Digits &15 chữ số &2 Digits &2 chữ số &3 Digits &3 chữ số &50 Digits &50 chữ số &8 Digits &8 chữ số &Sexagesimal &Lục thập phân Reset All Settings... Ä�ặt lại má»�i thiết lập... &System &Hệ thống SpeedCrunch &Theme &Chá»§ Ä‘á»� SpeedCrunch &Classic &Cổ Ä‘iển &Modern &Hiện đại Context Help Trợ giúp theo ngữ cảnh &Help &Trợ giúp Error Lá»—i Can't read from file %1 Không thể Ä‘á»�c tệp %1 Import Session Nhập phiên Close Session Ä�óng phiên Angle Mode: Chế độ góc: Notation: Ký hiệu: Precision: Ä�á»™ chính xác: Turn Vòng Revolution Vòng quay Fixed-point decimal Thập phân cố định Rational Số hữu tá»· Automatic decimal Thập phân tá»± động Automatic Tá»± động User &Definitions... Ä�ịnh nghÄ©a &ngưá»�i dùng... New &Tab Thẻ &má»›i New &Private Tab T&hẻ riêng tư má»›i Keep Giữ lại Make Private... Chuyển sang riêng tư... New &Window Cá»­a sổ &má»›i &Open... &Mở... &Rename... &Ä�ổi tên... Clo&ne... Nh&ân bản... &Close Tab Ä�&óng thẻ Reopen Clo&sed Tab M&ở lại thẻ đã đóng Open Sessions &Folder Mở &thư mục phiên &Undo &Hoàn tác &Redo L&àm lại Cu&t Cắ&t Copy &Last Result S&ao chép kết quả cuối &Wrap in Parentheses &Ä�ặt trong dấu ngoặc đơn Full Scr&een Mode Ch&ế độ toàn màn hình &Basic &CÆ¡ bản &Scientific (wide) &Khoa há»�c (rá»™ng) Scientific (narrow) Khoa há»�c (hẹp) &Custom... &Tùy chỉnh... Main &Menu &Menu chính User &Variables &Biến ngưá»�i dùng &Left &Trái &Right &Phải &Up &Lên &Down &Xuống Close Pa&ne &Ä�óng khung User &Units Ä�Æ¡n &vị ngưá»�i dùng &Turn &Vòng If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. Nếu biểu thức má»›i bắt đầu bằng +, -, * hoặc /, SpeedCrunch sẽ chèn "ans" trước. &Accept with Enter &Chấp nhận bằng Enter Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. Chấp nhận gợi ý tá»± động hoàn thành hiện tại bằng Enter mà không cần chá»�n trước bằng các phím mÅ©i tên. &Units Ä�Æ¡n &vị Show Live Result &Preview Hiển thị &xem trước kết quả trá»±c tiếp Save &Window Position on Exit Lưu &vị trí cá»­a sổ khi thoát Hover Highlighting Tô sáng khi rê chuá»™t Group Integer Part Only Chỉ nhóm phần nguyên Number Format... Ä�ịnh dạng số... Notation && Precision... Ký hiệu và độ chính xác... After pressing Enter, keep the entered expression selected in the editor. Sau khi nhấn Enter, giữ biểu thức đã nhập được chá»�n trong trình soạn thảo. Never Không bao giá»� Always Luôn luôn Only for Single-Line Expressions Chỉ vá»›i biểu thức má»™t dòng Simplify Displayed Expressions Rút gá»�n biểu thức hiển thị History Size &Limit... &Giá»›i hạn kích thước lịch sá»­... Remove Trailing &Zeroes &Bá»� các số không ở cuối Nearest, Half &Away (round) Gần nhất, ná»­a &ra xa (round) Nearest, Half &Even (roundeven) Gần nhất, ná»­a &chẵn (roundeven) Toward &Zero (trunc) Vá»� &0 (trunc) &Fixed-Point Dấu phẩy &cố định &Rational Số &hữu tá»· &Exponential (m·sâ�»Â¹) Dạng &mÅ© (m·sâ�»Â¹) &Fractional (m/s) Dạng &phân số (m/s) &Rectangular (a + bi) Dạng &chữ nhật (a + bi) Exponential (reâ�±á¶¿) Dạng mÅ© (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) Dạng lượng giác (r(cos θ + i·sin θ)) Phasor (r∠θ) Dạng phasor (r∠θ) &Theme... &Chá»§ Ä‘á»�... Check for &Updates Kiểm tra &cập nhật Source Code Mã nguồn &Zoom &Thu phóng &Results &Kết quả Unit Notation Ký hiệu đơn vị Rounding Mode Chế độ làm tròn &Notation &Ký hiệu &Imaginary Unit Ä�Æ¡n vị &ảo &Window &Cá»­a sổ &Editing &Chỉnh sá»­a A&utocomplete Tá»± động &hoàn thành Up/Down Arrow History Lịch sá»­ bằng mÅ©i tên lên/xuống &Appearance &Giao diện &Menus T&rình đơn &Docks B&ảng neo &Input and Results &Ä�ầu vào và kết quả &Disabled Ä�ã &tắt &Disable &Tắt Close preview Ä�óng xem trước Rename... Ä�ổi tên... Clone... Nhân bản... Close Tab Ä�óng thẻ New Private Tab Thẻ riêng tư má»›i Open... Mở... Reopen Closed Tab Mở lại thẻ đã đóng Split Chia Left Trái Right Phải Up Lên Down Xuống Clear Xóa ná»™i dung Delete Xóa %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 Phiên riêng tư: ná»™i dung sẽ bị loại bá»� khi đóng. Chá»�n Phiên làm việc > Giữ lại để chuyển thành phiên thông thưá»�ng. SpeedCrunch - %1 [Private] SpeedCrunch - %1 [Riêng tư] Reset All Settings Ä�ặt lại má»�i thiết lập Reset all settings to their default values? Ä�ặt lại má»�i thiết lập vá»� giá trị mặc định? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. Bao gồm giao diện, chỉnh sá»­a, định dạng kết quả và tùy chá»�n cá»­a sổ. Các phép tính, phiên Ä‘ang mở và định nghÄ©a ngưá»�i dùng sẽ được giữ lại. The settings file could not be written. Không thể ghi tệp thiết lập. Clear this session's calculations, unfinished expression, variables, functions, and units? Xóa các phép tính, biểu thức chưa hoàn tất, biến, hàm và đơn vị cá»§a phiên này? Global user definitions are kept. Các định nghÄ©a ngưá»�i dùng toàn cục được giữ lại. Make Session Private Chuyển phiên sang riêng tư The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. Phiên đã lưu %1 sẽ bị xóa. Ná»™i dung vẫn mở trong má»™t phiên riêng tư và sẽ bị loại bá»� khi đóng phiên đó hoặc thoát SpeedCrunch. Make Private Chuyển sang riêng tư Could not delete the saved session %1. Không thể xóa phiên đã lưu %1. Keep Session Giữ lại phiên Could not save the session. It remains private. Không thể lưu phiên. Phiên vẫn riêng tư. Clone Session Nhân bản phiên Could not save session file %1. Không thể lưu tệp phiên %1. Could not delete session file %1. Không thể xóa tệp phiên %1. JSON file (*.json);;Any file (*.*) Tệp JSON (*.json);;Bất kỳ tệp nào (*.*) Export session as JSON Xuất phiên làm việc dưới dạng JSON The selected file is not valid JSON: %1 Tệp đã chá»�n không phải JSON hợp lệ: %1 The selected file is not a SpeedCrunch session JSON file. Tệp đã chá»�n không phải là tệp JSON phiên SpeedCrunch. This file uses an obsolete SpeedCrunch session format and cannot be imported. Tệp này dùng định dạng phiên SpeedCrunch lá»—i thá»�i và không thể nhập. The selected JSON file is missing the required $schema field. Tệp JSON đã chá»�n thiếu trưá»�ng $schema bắt buá»™c. The selected JSON file uses an unsupported JSON schema: %1 Tệp JSON đã chá»�n dùng lược đồ JSON không được há»— trợ: %1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). Tệp JSON đã chá»�n thiếu định danh lược đồ phiên SpeedCrunch ($id). The selected JSON file uses an unsupported SpeedCrunch session format: %1 Tệp JSON đã chá»�n dùng định dạng phiên SpeedCrunch không được há»— trợ: %1 The selected JSON file is missing the required session name. Tệp JSON đã chá»�n thiếu tên phiên bắt buá»™c. The selected JSON file has an empty session name. Tệp JSON đã chá»�n có tên phiên trống. The selected JSON file has invalid or incomplete SpeedCrunch session data. Tệp JSON đã chá»�n có dữ liệu phiên SpeedCrunch không hợp lệ hoặc không đầy đủ. Open Sessions Folder Mở thư mục phiên Could not create the sessions folder: %1 Không thể tạo thư mục phiên: %1 Could not open the sessions folder: %1 Không thể mở thư mục phiên: %1 Editor and Results Font Phông chữ cá»§a trình soạn thảo và kết quả Open Session Mở phiên Community Cá»™ng đồng Rename Session Ä�ổi tên phiên Clear Session Xóa ná»™i dung phiên Delete Session Xóa phiên Close Pane Ä�óng khung User Variables Biến ngưá»�i dùng User Units Ä�Æ¡n vị ngưá»�i dùng Clear History Xóa lịch sá»­ Are you sure you want to clear the calculation history? Bạn có chắc muốn xóa lịch sá»­ tính toán không? Session name: Tên phiên: A session named %1 already exists. Phiên có tên %1 đã tồn tại. Could not create session file %1. Không thể tạo tệp phiên %1. Could not write session file %1. Không thể ghi tệp phiên %1. Are you sure you want to delete this session? Bạn có chắc muốn xóa phiên này không? Custom Precision Ä�á»™ chính xác tùy chỉnh Fractional digits: Chữ số phần lẻ: Theme Chá»§ Ä‘á»� Light Themes Chá»§ Ä‘á»� sáng Dark Themes Chá»§ Ä‘á»� tối Preview Xem trước Colors Màu sắc Select color for %1 Chá»�n màu cho %1 Import... Nhập... Export... Xuất... Import Theme Nhập chá»§ Ä‘á»� Theme file (*.json);;All files (*) Tệp chá»§ Ä‘á»� (*.json);;Tất cả tệp (*) Invalid theme file. Tệp chá»§ Ä‘á»� không hợp lệ. Can't import theme "%1" because it conflicts with a built-in theme. Không thể nhập chá»§ Ä‘á»� "%1" vì xung đột vá»›i chá»§ Ä‘á»� có sẵn. Can't find a writable theme folder. Không tìm thấy thư mục chá»§ Ä‘á»� có thể ghi. Overwrite Theme Ghi đè chá»§ Ä‘á»� A custom theme named "%1" already exists. Do you want to overwrite it? Chá»§ Ä‘á»� tùy chỉnh tên "%1" đã tồn tại. Bạn có muốn ghi đè không? Can't overwrite theme file %1 Không thể ghi đè tệp chá»§ Ä‘á»� %1 Can't copy theme file to %1 Không thể sao chép tệp chá»§ Ä‘á»� tá»›i %1 Export Theme Xuất chá»§ Ä‘á»� Can't export theme as "%1" because it conflicts with a built-in theme. Không thể xuất chá»§ Ä‘á»� thành "%1" vì xung đột vá»›i chá»§ Ä‘á»� có sẵn. Can't write to file %1 Không thể ghi vào tệp %1 Global User Variable Biến ngưá»�i dùng toàn cục Global User Function Hàm ngưá»�i dùng toàn cục Global User Unit Ä�Æ¡n vị ngưá»�i dùng toàn cục User Definitions Ä�ịnh nghÄ©a cá»§a ngưá»�i dùng These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. Các định nghÄ©a này có phạm vi toàn cục và được nạp vào má»�i phiên. Không thể thay đổi chúng trong các phiên và chúng được ưu tiên hÆ¡n các định nghÄ©a cùng tên từ trình soạn thảo phiên. Nhập má»™t định nghÄ©a trên má»—i dòng. Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Ví dụ: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply Ã�p dụng Validate Kiểm tra tính hợp lệ Test Results Kết quả kiểm tra Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 Biến đã nhập: %1 Hàm đã nhập: %2 Ä�Æ¡n vị đã nhập: %3 Số dòng có lá»—i: %4 none không có Apply Results Kết quả áp dụng User definitions saved. Ä�ã lưu các định nghÄ©a cá»§a ngưá»�i dùng. History Size Limit Giá»›i hạn kích thước lịch sá»­ Maximum number of history entries for this session (0 = unlimited): Số mục lịch sá»­ tối Ä‘a cho phiên này (0 = không giá»›i hạn): Text file (*.txt);;Any file (*.*) Tệp văn bản (*.txt);;Tệp bất kỳ (*.*) Could not recalculate from calculation %1: %2 Không thể tính lại từ phép tính %1: %2 History Size Limit Reached Ä�ã đạt giá»›i hạn kích thước lịch sá»­ This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. Phép tính này lấp đầy vị trí lịch sá»­ cuối cùng còn lại. Các phép tính sau sẽ xóa phép tính cÅ© nhất khá»�i lịch sá»­. Bạn có thể tăng giá»›i hạn từ Phiên > Giá»›i hạn kích thước lịch sá»­. Editing calculation. Press Esc twice to cancel. Ä�ang sá»­a phép tính. Nhấn Esc hai lần để há»§y. Calculation Settings Cài đặt phép tính Invalid recalculation start index Chỉ số bắt đầu tính lại không hợp lệ System Default Mặc định hệ thống Language Ngôn ngữ Select the language: Chá»�n ngôn ngữ: Custom Tùy chỉnh Decimal places: Số chữ số thập phân: &Automatic &Tá»± động &Precision &Ä�á»™ chính xác Plain &text &Văn bản thuần Formula &Book Sổ &công thức &Export &Xuất Export session as HTML Xuất phiên làm việc thành HTML HTML file (*.html) Tệp HTML (*.html) Export session as plain text Xuất phiên làm việc dưới dạng văn bản thuần ManualWindow SpeedCrunch Manual Hướng dẫn sá»­ dụng SpeedCrunch %1 - SpeedCrunch Manual %1 - Hướng dẫn sá»­ dụng SpeedCrunch NumberFormatDialog Number Format Ä�ịnh dạng số <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>Chá»�n định dạng số cho kết quả và cách nhóm chữ số đầu vào.</b><br/><br/>Lưu ý: số nhập vào có định dạng rõ ràng vẫn được chấp nhận dù khác định dạng hiển thị đã chá»�n.<br/> QObject Global User Variable Biến ngưá»�i dùng toàn cục Global User Function Hàm ngưá»�i dùng toàn cục Global User Unit Ä�Æ¡n vị ngưá»�i dùng toàn cục Backspace Xóa lùi Clear expression Xóa biểu thức Evaluate expression Tính biểu thức Insert text Chèn văn bản Automatic decimal Thập phân tá»± động Fixed-point decimal Thập phân cố định Engineering decimal Thập phân kỹ thuật Scientific decimal Thập phân khoa há»�c Rational Số hữu tá»· Binary Nhị phân Octal Bát phân Hexadecimal Thập lục phân Sexagesimal Lục thập phân Update Available Có bản cập nhật A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> Có phiên bản má»›i hÆ¡n (%1).<br/><a href="%2">Truy cập trang web để tải xuống.</a> Check for Updates Kiểm tra cập nhật SpeedCrunch %1 is up to date. SpeedCrunch %1 đã là phiên bản má»›i nhất. No connectivity. Please check your internet connection and try again. Không có kết nối. Vui lòng kiểm tra kết nối Internet và thá»­ lại. Could not verify the latest available version. Không thể xác minh phiên bản má»›i nhất hiện có. ResultDisplay Scroll to bottom Cuá»™n xuống cuối Edit Expression Sá»­a biểu thức Change Settings Thay đổi cài đặt New Tab Thẻ má»›i &Import... &Nhập... &Export &Xuất Plain &text &Văn bản thuần Copy Sao chép Selection Vùng chá»�n Select All Chá»�n tất cả Expression Biểu thức Result Kết quả Calculation Phép tính Calculation as Single Line Phép tính trên má»™t dòng Remove Loại bá»� This Calculation Phép tính này All Calculations Above Tất cả phép tính phía trên All Calculations Below Tất cả phép tính phía dưới New Private Tab Thẻ riêng tư má»›i Session Phiên làm việc Open... Mở... Clone... Nhân bản... Rename... Ä�ổi tên... Keep Giữ lại Make Private... Chuyển sang riêng tư... Clear Xóa ná»™i dung Delete Xóa Close Ä�óng Split Chia Left Trái Right Phải Up Lên Down Xuống Close Pane Ä�óng khung Main Menu Menu chính Cancel editing Há»§y chỉnh sá»­a Copy result Sao chép kết quả Edit expression Sá»­a biểu thức Change settings Thay đổi cài đặt Remove calculation Xóa phép tính ResultSlotsDialog Notation & Precision Ký hiệu và độ chính xác Result Line Dòng kết quả Enabled Ä�ã bật Notation Ký hiệu Decimal Places Số chữ số thập phân Main Line Dòng chính Extra Line #1 Dòng phụ #1 Extra Line #2 Dòng phụ #2 Extra Line #3 Dòng phụ #3 Extra Line #4 Dòng phụ #4 Auto Tá»± động UserFunctionListWidget Name Tên Value Giá trị Description Mô tả Search Tìm kiếm No match found Không tìm thấy kết quả Insert Chèn Edit Sá»­a Delete Xóa Delete All Xóa tất cả UserUnitListWidget Name Tên Value Giá trị Description Mô tả Search Tìm kiếm No match found Không tìm thấy kết quả Insert Chèn Edit Sá»­a Delete Xóa Delete All Xóa tất cả VariableListWidget Name Tên Value Giá trị Description Mô tả Search Tìm kiếm No match found Không tìm thấy kết quả Insert Chèn Edit Sá»­a Delete Xóa Delete All Xóa tất cả heldercorreia-speedcrunch-e7ca37f/src/resources/locale/zh_CN.ts000066400000000000000000010332231526573132500247520ustar00rootroot00000000000000 AboutBox About SpeedCrunch 关于 SpeedCrunch Core developers 核心开å�‘者 Original author 原始作者 Close 关闭 Math engine 数学引擎 Main author | Logo | Maintainer 主è¦�作者 | 标志 | 维护者 Thanks 致谢 Copyright (C) 2004-2026 The SpeedCrunch developers 版æ�ƒæ‰€æœ‰ (C) 2004-2026 SpeedCrunch å¼€å�‘团队 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version 本程åº�是自由软件;根æ�®æ‚¨çš„选择,您å�¯ä»¥åœ¨ç”±è‡ªç”±è½¯ä»¶åŸºé‡‘会å�‘布的 GNU GPL v2 (或者更高的版本的)å��议下é‡�æ–°å�‘布并且/或者修改它。 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 本程åº�çš„å�‘布是希望对您有用,但是我们ä¸�能æ��供任何承诺;也没有æ��供针对特定目的适销性或适当性的担ä¿�。有关细节请查看 GNU GPL å��议。 BitFieldWidget Reset bits to zero å°†ä½�é‡�置为零 Invert bits å��转ä½� Shift bits left 左移ä½� Shift bits right å�³ç§»ä½� Book Index 索引 Algebra 代数 Quadratic Equation 一元二次方程 Logarithmic Base Conversion 对数æ�¢åº• Geometry 几何 Circle 圆 Sector 扇形 Sphere ç�ƒ Cube 正方体 Cone 圆锥 Cylinder 圆柱 Electronics 电å­�å­¦ Ohm's Law 欧姆定律 Power 电能 Reactance 电抗 Resonance è°�振 Radio Frequency 无线电 Antennas 天线 Characteristic Impedance (coax) 特性阻抗 (å�Œè½´) Velocity of Propagation (coax) 电ç£�波波速 (å�Œè½´) Standing Wave Ratio & Return Loss 驻波比和回波æ�Ÿè€— Free Space Wavelength 自由空间电ç£�波波长 resistance 电阻 voltage 电压 current 电æµ� power 电功率 inductive reactance 感抗 capacitive reactance 容抗 inductance 电感 capacitance 电容 frequency 电ç£�波频率 resonance frequency è°�振频率 area é�¢ç§¯ perimeter 周长 diameter 直径 radius å�Šå¾„ volume 体积 surface area 表é�¢ç§¯ height 高 slant height 斜高 face diagonal é�¢å¯¹è§’线 space diagonal 体对角线 edge length 棱长 arc length å¼§é•¿ central angle (degrees) 圆心角 (度) input power 输入功率 reflected power å��射功率 transmitted power å�‘射功率 return loss 回波æ�Ÿè€— dielectric constant 相对介电常数 outer conductor's inner diameter 外导体内径 inner conductor's outer diameter 内导体外径 speed of light 光速 reflection coefficient å��射系数 standing wave ratio 驻波比 normalized impedance 归一化阻抗 frequency (Hz) 电ç£�波频率 (赫兹) BookDock Formula Book å…¬å¼�手册 ConstantCompletion Search constants æ�œç´¢å¸¸é‡� No match found 未找到匹é…�项 Constants Mathematics æ•°å­¦ Physics (CODATA 2022) 物ç�†ï¼ˆCODATA 2022) Chemistry (IUPAC - CIAAW 2021) 化学(IUPAC - CIAAW 2021) Uncategorized 未分类 Universal 通用 Physicochemical 物ç�†åŒ–å­¦ Atomic & Nuclear — General 原å­�与核物ç�† - 通用 Atomic & Nuclear — Electroweak 原å­�与核物ç�† - 电弱 Atomic & Nuclear — Electron 原å­�与核物ç�† - 电å­� Atomic & Nuclear — Muon 原å­�与核物ç�† - μå­� Atomic & Nuclear — Tau 原å­�与核物ç�† - Ï„å­� Atomic & Nuclear — Proton 原å­�与核物ç�† - è´¨å­� Atomic & Nuclear — Neutron 原å­�与核物ç�† - 中å­� Atomic & Nuclear — Deuteron 原å­�与核物ç�† - 氘核 Atomic & Nuclear — Triton 原å­�与核物ç�† - æ°šæ ¸ Atomic & Nuclear — Helion 原å­�与核物ç�† - æ°¦-3æ ¸ Atomic & Nuclear — Alpha particle 原å­�与核物ç�† - α粒å­� Atomic & Nuclear — Atomic units 原å­�与核物ç�† - 原å­�å�•ä½� Atomic & Nuclear — Energy conversion relationships 原å­�与核物ç�† - 能é‡�æ�¢ç®—关系 Atomic & Nuclear — X-ray units 原å­�与核物ç�† - X射线å�•ä½� Atomic & Nuclear — Magnetic shielding corrections 原å­�与核物ç�† - ç£�å±�蔽修正 Masses è´¨é‡� Lifetimes 寿命 Molar Masses 摩尔质é‡� Electronegativity 电负性 Ionization Energy 电离能 Nominal Constants (IAU 2015) 标称常数(IAU 2015) Current Best Estimates (IAU NSFA 2026-04) 当å‰�最佳估计值(IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) 真空特性阻抗 (Zâ‚€) reduced Planck constant (â„�) 约化普朗克常数 (â„�) vacuum electric permittivity (ϵ₀) 真空电容率 (ϵ₀) Newtonian constant of gravitation (G) 牛顿引力常数 (G) vacuum magnetic permeability (μ₀) 真空ç£�导率 (μ₀) Planck constant (h) 普朗克常数 (h) speed of light in vacuum (c) 真空中的光速 (c) standard acceleration of gravity (gâ‚™) 标准é‡�力加速度 (gâ‚™) Newtonian constant of gravitation over h-bar c 牛顿引力常数除以 â„�c Planck length 普朗克长度 Planck constant in eV/Hz (h) 普朗克常数,å�•ä½�为eV/Hz (h) Planck mass 普朗克质é‡� Planck mass energy equivalent in GeV 普朗克质é‡�能é‡�当é‡�,å�•ä½�为GeV Planck temperature 普朗克温度 Planck time 普朗克时间 reduced Planck constant in eV·s (â„�) 约化普朗克常数,å�•ä½�为eV·s (â„�) reduced Planck constant times c in MeV·fm 约化普朗克常数乘以 c,å�•ä½�为MeV·fm Bohr magneton 玻尔ç£�å­� conductance quantum (Gâ‚€) 电导é‡�å­� (Gâ‚€) Coulomb constant (kâ‚‘) 库仑常数 (kâ‚‘) elementary charge (e) 基本电è�· (e) elementary charge over h-bar 基本电è�·é™¤ä»¥ â„� conventional value of Josephson constant 约定约瑟夫森常数值 Josephson constant 约瑟夫森常数 conventional value of ampere-90 安培-90 约定值 conventional value of coulomb-90 库仑-90 约定值 conventional value of farad-90 法拉-90 约定值 conventional value of henry-90 亨利-90 约定值 conventional value of ohm-90 欧姆-90 约定值 conventional value of volt-90 ä¼�特-90 约定值 conventional value of watt-90 瓦特-90 约定值 magnetic flux quantum (Φ₀) ç£�通é‡�å­� (Φ₀) nuclear magneton æ ¸ç£�å­� inverse of conductance quantum 电导é‡�å­�的倒数 conventional value of von Klitzing constant 约定冯·克里é�’常数值 von Klitzing constant 冯·克里é�’常数 atomic unit of magnetic dipole moment ç£�å�¶æž�矩的原å­�å�•ä½� atomic unit of magnetic flux density ç£�通密度的原å­�å�•ä½� Bohr magneton in eV/T 玻尔ç£�å­�,å�•ä½�为eV/T Bohr magneton in Hz/T 玻尔ç£�å­�,å�•ä½�为Hz/T Bohr magneton in inverse meter per tesla 玻尔ç£�å­�,å�•ä½�为倒数米æ¯�tesla Bohr magneton in K/T 玻尔ç£�å­�,å�•ä½�为K/T nuclear magneton in eV/T æ ¸ç£�å­�,å�•ä½�为eV/T nuclear magneton in inverse meter per tesla æ ¸ç£�å­�,å�•ä½�为倒数米æ¯�tesla nuclear magneton in K/T æ ¸ç£�å­�,å�•ä½�为K/T nuclear magneton in MHz/T æ ¸ç£�å­�,å�•ä½�为MHz/T Bohr radius (aâ‚€) 玻尔å�Šå¾„ (aâ‚€) fine-structure constant (α) 精细结构常数 (α) Hartree energy (Eâ‚•) 哈特里能é‡� (Eâ‚•) Hartree energy in eV 哈特里能é‡�,å�•ä½�为eV quantum of circulation 环é‡�é‡�å­� quantum of circulation times 2 环é‡�é‡�å­�乘以 2 Rydberg constant (R∞) 里德伯常数 (R∞) atomic mass unit-hartree relationship 原å­�è´¨é‡�å�•ä½�-哈特里关系 atomic mass unit-hertz relationship 原å­�è´¨é‡�å�•ä½�-赫兹关系 atomic mass unit-inverse meter relationship 原å­�è´¨é‡�å�•ä½�-倒数米关系 atomic mass unit-joule relationship 原å­�è´¨é‡�å�•ä½�-焦耳关系 atomic mass unit-kelvin relationship 原å­�è´¨é‡�å�•ä½�-开尔文关系 atomic mass unit-kilogram relationship 原å­�è´¨é‡�å�•ä½�-å�ƒå…‹å…³ç³» atomic unit of 1st hyperpolarizability 一阶超æž�化率的原å­�å�•ä½� atomic unit of 2nd hyperpolarizability 二阶超æž�化率的原å­�å�•ä½� atomic unit of charge (e) atomic unit的电è�· (e) atomic unit of charge density atomic unit的电è�· 密度 atomic unit of current atomic unit的电æµ� atomic unit of electric dipole moment atomic unit的电 å�¶æž�矩 atomic unit of electric field atomic unit的电 场 atomic unit of electric field gradient atomic unit的电 场梯度 atomic unit of electric polarizability atomic unit的电 æž�化率 atomic unit of electric potential atomic unit的电 势 atomic unit of electric quadrupole moment atomic unit的电 å››æž�矩 atomic unit of action atomic unit的作用é‡� atomic unit of energy atomic unit的能é‡� atomic unit of force atomic unit的力 atomic unit of length atomic unit的长度 hertz-atomic mass unit relationship 赫兹-原å­�è´¨é‡�å�•ä½�关系 hertz-electron volt relationship 赫兹-电å­�ä¼�特关系 hertz-hartree relationship 赫兹-哈特里关系 hertz-inverse meter relationship 赫兹-倒数米关系 hertz-joule relationship 赫兹-焦耳关系 hertz-kelvin relationship 赫兹-开尔文关系 hertz-kilogram relationship 赫兹-å�ƒå…‹å…³ç³» hyperfine transition frequency of Cs-133 铯-133 超精细跃è¿�频率 inverse fine-structure constant (αâ�»Â¹) 精细结构常数的倒数 (αâ�»Â¹) inverse meter-atomic mass unit relationship 倒数米-原å­�è´¨é‡�å�•ä½�关系 inverse meter-electron volt relationship 倒数米-电å­�ä¼�特关系 inverse meter-hartree relationship 倒数米-哈特里关系 inverse meter-hertz relationship 倒数米-赫兹关系 inverse meter-joule relationship 倒数米-焦耳关系 inverse meter-kelvin relationship 倒数米-开尔文关系 inverse meter-kilogram relationship 倒数米-å�ƒå…‹å…³ç³» joule-atomic mass unit relationship 焦耳-原å­�è´¨é‡�å�•ä½�关系 joule-electron volt relationship 焦耳-电å­�ä¼�特关系 joule-hertz relationship 焦耳-赫兹关系 joule-hartree relationship 焦耳-哈特里关系 joule-inverse meter relationship 焦耳-倒数米关系 joule-kelvin relationship 焦耳-开尔文关系 joule-kilogram relationship 焦耳-å�ƒå…‹å…³ç³» kelvin-atomic mass unit relationship 开尔文-原å­�è´¨é‡�å�•ä½�关系 kelvin-electron volt relationship 开尔文-电å­�ä¼�特关系 kelvin-hertz relationship 开尔文-赫兹关系 kelvin-hartree relationship 开尔文-哈特里关系 kelvin-inverse meter relationship 开尔文-倒数米关系 kelvin-joule relationship 开尔文-焦耳关系 kelvin-kilogram relationship 开尔文-å�ƒå…‹å…³ç³» kilogram-atomic mass unit relationship å�ƒå…‹-原å­�è´¨é‡�å�•ä½�关系 kilogram-electron volt relationship å�ƒå…‹-电å­�ä¼�特关系 kilogram-hertz relationship å�ƒå…‹-赫兹关系 kilogram-hartree relationship å�ƒå…‹-哈特里关系 kilogram-inverse meter relationship å�ƒå…‹-倒数米关系 kilogram-joule relationship å�ƒå…‹-焦耳关系 kilogram-kelvin relationship å�ƒå…‹-开尔文关系 lattice parameter of silicon (a) 硅的晶格å�‚æ•° (a) luminous efficacy å�‘光效能 natural unit of energy 能é‡�的自然å�•ä½� natural unit of energy in MeV 能é‡�的自然å�•ä½�,å�•ä½�为MeV natural unit of action (â„�) 作用é‡�的自然å�•ä½� (â„�) natural unit of action in eV·s 作用é‡�的自然å�•ä½�,å�•ä½�为eV·s natural unit of length 长度的自然å�•ä½� natural unit of mass è´¨é‡�的自然å�•ä½� natural unit of momentum 动é‡�的自然å�•ä½� natural unit of momentum in MeV/c 动é‡�的自然å�•ä½�,å�•ä½�为MeV/c natural unit of time 时间的自然å�•ä½� natural unit of velocity 速度的自然å�•ä½� Rydberg constant times c in Hz 里德伯常数乘以 c,å�•ä½�为Hz Rydberg constant times hc in eV 里德伯常数乘以 hc,å�•ä½�为eV Rydberg constant times hc in J 里德伯常数乘以 hc,å�•ä½�为J Fermi coupling constant 费米耦å�ˆå¸¸æ•° weak mixing angle 弱混å�ˆè§’ W to Z mass ratio W与Z è´¨é‡�之比 Thomson cross section (σₑ) 汤姆孙截é�¢ (σₑ) electron mass (mâ‚‘) 电å­� è´¨é‡� (mâ‚‘) electron mass in u 电å­� è´¨é‡�,å�•ä½�为u electron mass energy equivalent (mₑ·c²) 电å­� è´¨é‡�能é‡�当é‡� (mₑ·c²) electron mass energy equivalent in MeV 电å­� è´¨é‡�能é‡�当é‡�,å�•ä½�为MeV reduced Compton wavelength 约化康普顿波长 classical electron radius (râ‚‘) ç»�典电å­�å�Šå¾„ (râ‚‘) electron charge to mass quotient 电å­� è�·è´¨å•† electron-deuteron magnetic moment ratio 电å­�-氘核ç£�矩比 electron-deuteron mass ratio 电å­�-氘核质é‡�比 electron g factor (gâ‚‘) 电å­� g factor (gâ‚‘) electron gyromagnetic ratio (γₑ) 电å­� æ—‹ç£�比 (γₑ) electron gyromagnetic ratio in MHz/T 电å­� æ—‹ç£�比,å�•ä½�为MHz/T electron-helion mass ratio 电å­�-æ°¦-3核质é‡�比 electron magnetic moment (μₑ) 电å­� ç£�矩 (μₑ) electron magnetic moment anomaly (aâ‚‘) 电å­� ç£�矩å��常 (aâ‚‘) electron magnetic moment to Bohr magneton ratio 电å­� ç£�矩与玻尔ç£�å­�之比 electron magnetic moment to nuclear magneton ratio 电å­� ç£�矩与核ç£�å­�之比 electron molar mass (Mâ‚‘) 电å­� 摩尔质é‡� (Mâ‚‘) electron-muon magnetic moment ratio 电å­�-μå­�ç£�矩比 electron-muon mass ratio 电å­�-μå­�è´¨é‡�比 electron-neutron magnetic moment ratio 电å­�-中å­�ç£�矩比 electron-neutron mass ratio 电å­�-中å­�è´¨é‡�比 electron-proton magnetic moment ratio 电å­�-è´¨å­�ç£�矩比 electron-proton mass ratio 电å­�-è´¨å­�è´¨é‡�比 electron relative atomic mass (Ar(e)) 电å­� 相对原å­�è´¨é‡� (Ar(e)) electron-tau mass ratio 电å­�-Ï„å­�è´¨é‡�比 electron to alpha particle mass ratio 电å­�与α粒å­� è´¨é‡�之比 electron to shielded helion magnetic moment ratio 电å­�与å±�蔽 æ°¦-3æ ¸ ç£�矩之比 electron to shielded proton magnetic moment ratio 电å­�与å±�蔽 è´¨å­� ç£�矩之比 electron-triton mass ratio 电å­�-氚核质é‡�比 electron volt-atomic mass unit relationship 电å­�ä¼�特-原å­�è´¨é‡�å�•ä½�关系 electron volt-hartree relationship 电å­�ä¼�特-哈特里关系 electron volt-hertz relationship 电å­�ä¼�特-赫兹关系 electron volt-inverse meter relationship 电å­�ä¼�特-倒数米关系 electron volt-joule relationship 电å­�ä¼�特-焦耳关系 electron volt-kelvin relationship 电å­�ä¼�特-开尔文关系 electron volt-kilogram relationship 电å­�ä¼�特-å�ƒå…‹å…³ç³» hartree-atomic mass unit relationship 哈特里-原å­�è´¨é‡�å�•ä½�关系 hartree-electron volt relationship 哈特里-电å­�ä¼�特关系 muon Compton wavelength μå­� 康普顿波长 muon-electron mass ratio μå­�-电å­�è´¨é‡�比 muon g factor μå­� g factor muon magnetic moment μå­� ç£�矩 muon magnetic moment anomaly μå­� ç£�矩å��常 muon magnetic moment to Bohr magneton ratio μå­� ç£�矩与玻尔ç£�å­�之比 muon magnetic moment to nuclear magneton ratio μå­� ç£�矩与核ç£�å­�之比 muon mass μå­� è´¨é‡� muon mass energy equivalent μå­� è´¨é‡�能é‡�当é‡� muon mass energy equivalent in MeV μå­� è´¨é‡�能é‡�当é‡�,å�•ä½�为MeV muon mass in u μå­� è´¨é‡�,å�•ä½�为u muon molar mass μå­� 摩尔质é‡� muon-neutron mass ratio μå­�-中å­�è´¨é‡�比 muon-proton magnetic moment ratio μå­�-è´¨å­�ç£�矩比 muon-proton mass ratio μå­�-è´¨å­�è´¨é‡�比 muon-tau mass ratio μå­�-Ï„å­�è´¨é‡�比 reduced muon Compton wavelength reduced μå­� 康普顿波长 reduced tau Compton wavelength reduced Ï„å­� 康普顿波长 tau Compton wavelength Ï„å­� 康普顿波长 tau-electron mass ratio Ï„å­�-电å­�è´¨é‡�比 tau mass Ï„å­� è´¨é‡� tau mass energy equivalent Ï„å­� è´¨é‡�能é‡�当é‡� tau mass in u Ï„å­� è´¨é‡�,å�•ä½�为u tau molar mass Ï„å­� 摩尔质é‡� tau-muon mass ratio Ï„å­�-μå­�è´¨é‡�比 tau-neutron mass ratio Ï„å­�-中å­�è´¨é‡�比 tau-proton mass ratio Ï„å­�-è´¨å­�è´¨é‡�比 proton charge to mass quotient è´¨å­� è�·è´¨å•† proton Compton wavelength è´¨å­� 康普顿波长 proton-electron mass ratio è´¨å­�-电å­�è´¨é‡�比 proton g factor (gₚ) è´¨å­� g factor (gₚ) proton gyromagnetic ratio (γₚ) è´¨å­� æ—‹ç£�比 (γₚ) proton gyromagnetic ratio in MHz/T è´¨å­� æ—‹ç£�比,å�•ä½�为MHz/T proton magnetic moment (μₚ) è´¨å­� ç£�矩 (μₚ) proton magnetic moment to Bohr magneton ratio è´¨å­� ç£�矩与玻尔ç£�å­�之比 proton magnetic moment to nuclear magneton ratio è´¨å­� ç£�矩与核ç£�å­�之比 proton magnetic shielding correction è´¨å­� ç£�å±�蔽修正 proton mass (mₚ) è´¨å­� è´¨é‡� (mₚ) proton mass energy equivalent è´¨å­� è´¨é‡�能é‡�当é‡� proton mass energy equivalent in MeV è´¨å­� è´¨é‡�能é‡�当é‡�,å�•ä½�为MeV proton mass in u è´¨å­� è´¨é‡�,å�•ä½�为u proton molar mass (Mₚ) è´¨å­� 摩尔质é‡� (Mₚ) proton-muon mass ratio è´¨å­�-μå­�è´¨é‡�比 proton-neutron magnetic moment ratio è´¨å­�-中å­�ç£�矩比 proton-neutron mass ratio è´¨å­�-中å­�è´¨é‡�比 proton relative atomic mass (Ar(p)) è´¨å­� 相对原å­�è´¨é‡� (Ar(p)) proton rms charge radius è´¨å­� å�‡æ–¹æ ¹ç”µè�·å�Šå¾„ proton-tau mass ratio è´¨å­�-Ï„å­�è´¨é‡�比 reduced proton Compton wavelength reduced è´¨å­� 康普顿波长 shielded proton gyromagnetic ratio å±�蔽 è´¨å­� æ—‹ç£�比 shielded proton gyromagnetic ratio in MHz/T å±�蔽 è´¨å­� æ—‹ç£�比,å�•ä½�为MHz/T shielded proton magnetic moment å±�蔽 è´¨å­� ç£�矩 shielded proton magnetic moment to Bohr magneton ratio å±�蔽 è´¨å­� ç£�矩与玻尔ç£�å­�之比 shielded proton magnetic moment to nuclear magneton ratio å±�蔽 è´¨å­� ç£�矩与核ç£�å­�之比 neutron Compton wavelength 中å­� 康普顿波长 neutron-electron magnetic moment ratio 中å­�-电å­�ç£�矩比 neutron-electron mass ratio 中å­�-电å­�è´¨é‡�比 neutron g factor (gâ‚™) 中å­� g factor (gâ‚™) neutron gyromagnetic ratio (γₙ) 中å­� æ—‹ç£�比 (γₙ) neutron gyromagnetic ratio in MHz/T 中å­� æ—‹ç£�比,å�•ä½�为MHz/T neutron magnetic moment (μₙ) 中å­� ç£�矩 (μₙ) neutron magnetic moment to Bohr magneton ratio 中å­� ç£�矩与玻尔ç£�å­�之比 neutron magnetic moment to nuclear magneton ratio 中å­� ç£�矩与核ç£�å­�之比 neutron mass (mâ‚™) 中å­� è´¨é‡� (mâ‚™) neutron mass energy equivalent 中å­� è´¨é‡�能é‡�当é‡� neutron mass energy equivalent in MeV 中å­� è´¨é‡�能é‡�当é‡�,å�•ä½�为MeV neutron mass in u 中å­� è´¨é‡�,å�•ä½�为u neutron molar mass (Mâ‚™) 中å­� 摩尔质é‡� (Mâ‚™) neutron-muon mass ratio 中å­�-μå­�è´¨é‡�比 neutron-proton magnetic moment ratio 中å­�-è´¨å­�ç£�矩比 neutron-proton mass difference 中å­�-è´¨å­� è´¨é‡� difference neutron-proton mass difference energy equivalent 中å­�-è´¨å­� è´¨é‡� difference 能é‡� equivalent neutron-proton mass difference energy equivalent in MeV 中å­�-è´¨å­� è´¨é‡� difference 能é‡� equivalent,å�•ä½�为MeV neutron-proton mass difference in u 中å­�-è´¨å­� è´¨é‡� difference,å�•ä½�为u neutron-proton mass ratio 中å­�-è´¨å­�è´¨é‡�比 neutron relative atomic mass (Ar(n)) 中å­� 相对原å­�è´¨é‡� (Ar(n)) neutron-tau mass ratio 中å­�-Ï„å­�è´¨é‡�比 neutron to shielded proton magnetic moment ratio 中å­�与å±�蔽 è´¨å­� ç£�矩之比 reduced neutron Compton wavelength reduced 中å­� 康普顿波长 deuteron-electron magnetic moment ratio 氘核-电å­�ç£�矩比 deuteron-electron mass ratio 氘核-电å­�è´¨é‡�比 deuteron g factor 氘核 g factor deuteron magnetic moment 氘核 ç£�矩 deuteron magnetic moment to Bohr magneton ratio 氘核 ç£�矩与玻尔ç£�å­�之比 deuteron magnetic moment to nuclear magneton ratio 氘核 ç£�矩与核ç£�å­�之比 deuteron mass 氘核 è´¨é‡� deuteron mass energy equivalent 氘核 è´¨é‡�能é‡�当é‡� deuteron mass energy equivalent in MeV 氘核 è´¨é‡�能é‡�当é‡�,å�•ä½�为MeV deuteron mass in u 氘核 è´¨é‡�,å�•ä½�为u deuteron molar mass 氘核 摩尔质é‡� deuteron-neutron magnetic moment ratio 氘核-中å­�ç£�矩比 deuteron-proton magnetic moment ratio 氘核-è´¨å­�ç£�矩比 deuteron-proton mass ratio 氘核-è´¨å­�è´¨é‡�比 deuteron relative atomic mass (Ar(d)) 氘核 相对原å­�è´¨é‡� (Ar(d)) deuteron rms charge radius 氘核 å�‡æ–¹æ ¹ç”µè�·å�Šå¾„ triton-electron mass ratio æ°šæ ¸-电å­�è´¨é‡�比 triton g factor (gₜ) æ°šæ ¸ g factor (gₜ) triton magnetic moment (μₜ) æ°šæ ¸ ç£�矩 (μₜ) triton magnetic moment to Bohr magneton ratio æ°šæ ¸ ç£�矩与玻尔ç£�å­�之比 triton magnetic moment to nuclear magneton ratio æ°šæ ¸ ç£�矩与核ç£�å­�之比 triton mass (mₜ) æ°šæ ¸ è´¨é‡� (mₜ) triton mass energy equivalent æ°šæ ¸ è´¨é‡�能é‡�当é‡� triton mass energy equivalent in MeV æ°šæ ¸ è´¨é‡�能é‡�当é‡�,å�•ä½�为MeV triton mass in u æ°šæ ¸ è´¨é‡�,å�•ä½�为u triton molar mass (Mₜ) æ°šæ ¸ 摩尔质é‡� (Mₜ) triton-proton mass ratio æ°šæ ¸-è´¨å­�è´¨é‡�比 triton relative atomic mass (Ar(t)) æ°šæ ¸ 相对原å­�è´¨é‡� (Ar(t)) triton to proton magnetic moment ratio 氚核与质å­� ç£�矩之比 helion-electron mass ratio æ°¦-3æ ¸-电å­�è´¨é‡�比 helion g factor (gâ‚•) æ°¦-3æ ¸ g factor (gâ‚•) helion magnetic moment (μₕ) æ°¦-3æ ¸ ç£�矩 (μₕ) helion magnetic moment to Bohr magneton ratio æ°¦-3æ ¸ ç£�矩与玻尔ç£�å­�之比 helion magnetic moment to nuclear magneton ratio æ°¦-3æ ¸ ç£�矩与核ç£�å­�之比 helion mass (mâ‚•) æ°¦-3æ ¸ è´¨é‡� (mâ‚•) helion mass energy equivalent æ°¦-3æ ¸ è´¨é‡�能é‡�当é‡� helion mass energy equivalent in MeV æ°¦-3æ ¸ è´¨é‡�能é‡�当é‡�,å�•ä½�为MeV helion mass in u æ°¦-3æ ¸ è´¨é‡�,å�•ä½�为u helion molar mass (Mâ‚•) æ°¦-3æ ¸ 摩尔质é‡� (Mâ‚•) helion-proton mass ratio æ°¦-3æ ¸-è´¨å­�è´¨é‡�比 helion relative atomic mass (Ar(h)) æ°¦-3æ ¸ 相对原å­�è´¨é‡� (Ar(h)) helion shielding shift æ°¦-3æ ¸ å±�蔽ä½�ç§» shielded helion gyromagnetic ratio å±�蔽 æ°¦-3æ ¸ æ—‹ç£�比 shielded helion gyromagnetic ratio in MHz/T å±�蔽 æ°¦-3æ ¸ æ—‹ç£�比,å�•ä½�为MHz/T shielded helion magnetic moment å±�蔽 æ°¦-3æ ¸ ç£�矩 shielded helion magnetic moment to Bohr magneton ratio å±�蔽 æ°¦-3æ ¸ ç£�矩与玻尔ç£�å­�之比 shielded helion magnetic moment to nuclear magneton ratio å±�蔽 æ°¦-3æ ¸ ç£�矩与核ç£�å­�之比 shielded helion to proton magnetic moment ratio å±�蔽 æ°¦-3核与质å­� ç£�矩之比 shielded helion to shielded proton magnetic moment ratio å±�蔽 æ°¦-3核与å±�蔽 è´¨å­� ç£�矩之比 alpha particle mass α粒å­� è´¨é‡� alpha particle mass in u α粒å­� è´¨é‡�,å�•ä½�为u alpha particle mass energy equivalent α粒å­� è´¨é‡�能é‡�当é‡� alpha particle mass energy equivalent in MeV α粒å­� è´¨é‡�能é‡�当é‡�,å�•ä½�为MeV alpha particle-electron mass ratio α粒å­�-电å­�è´¨é‡�比 alpha particle-proton mass ratio α粒å­�-è´¨å­�è´¨é‡�比 alpha particle rms charge radius α粒å­� å�‡æ–¹æ ¹ç”µè�·å�Šå¾„ alpha particle molar mass α粒å­� 摩尔质é‡� alpha particle relative atomic mass (Ar(α)) α粒å­� 相对原å­�è´¨é‡� (Ar(α)) atomic mass constant (mᵤ) 原å­�è´¨é‡�常数 (mᵤ) Avogadro constant 阿ä¼�伽德罗常数 Boltzmann constant (k) 玻尔兹曼常数 (k) Boltzmann constant in eV/K 玻尔兹曼常数,å�•ä½�为eV/K Boltzmann constant in Hz/K 玻尔兹曼常数,å�•ä½�为Hz/K Boltzmann constant in inverse meter per kelvin 玻尔兹曼常数,å�•ä½�为倒数米æ¯�开尔文 electron volt (eV) 电å­�ä¼�特 (eV) Faraday constant (F) 法拉第常数 (F) first radiation constant (câ‚�) 第一è¾�射常数 (câ‚�) first radiation constant for spectral radiance 光谱è¾�亮度第一è¾�射常数 molar gas constant (R) 摩尔气体常数 (R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) 洛施密特常数 (nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) 洛施密特常数 (nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant 摩尔普朗克常数 second radiation constant (câ‚‚) 第二è¾�射常数 (câ‚‚) Stefan-Boltzmann constant (σ) 斯特藩-玻尔兹曼常数 (σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ç�†æƒ³ç¡…晶格间è·� (dâ‚‚â‚‚â‚€) atomic mass constant energy equivalent 原å­�è´¨é‡�常数能é‡�当é‡� atomic mass constant energy equivalent in MeV 原å­�è´¨é‡�常数能é‡�当é‡�,å�•ä½�为MeV atomic mass unit-electron volt relationship 原å­�è´¨é‡�å�•ä½�-电å­�ä¼�特关系 molar mass constant (Mᵤ) 摩尔质é‡�常数 (Mᵤ) molar mass of carbon-12 碳-12 的摩尔质é‡� molar volume of ideal gas (273.15 K, 100 kPa) ç�†æƒ³æ°”体摩尔体积 (273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ç�†æƒ³æ°”体摩尔体积 (273.15 K, 101.325 kPa) molar volume of silicon 硅的摩尔体积 Sackur-Tetrode constant (1 K, 100 kPa) è�¨å…‹å°”-特etrode常数 (1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) è�¨å…‹å°”-特etrode常数 (1 K, 101.325 kPa) Wien frequency displacement law constant ç»´æ�©é¢‘率ä½�移定律常数 Wien wavelength displacement law constant ç»´æ�©æ³¢é•¿ä½�移定律常数 standard atmosphere (atm) 标准大气压 (atm) standard-state pressure (p°) 标准æ€�压力 (p°) Angstrom star (Ã…*) 埃星 (Ã…*) Copper x unit 铜 X å�•ä½� Molybdenum x unit é’¼ X å�•ä½� atomic unit of magnetizability ç£�化率的原å­�å�•ä½� atomic unit of mass (mâ‚‘) è´¨é‡�的原å­�å�•ä½� (mâ‚‘) atomic unit of momentum 动é‡�的原å­�å�•ä½� atomic unit of permittivity 介电常数的原å­�å�•ä½� atomic unit of time 时间的原å­�å�•ä½� atomic unit of velocity 速度的原å­�å�•ä½� hartree-hertz relationship 哈特里-赫兹关系 hartree-inverse meter relationship 哈特里-倒数米关系 hartree-joule relationship 哈特里-焦耳关系 hartree-kelvin relationship 哈特里-开尔文关系 hartree-kilogram relationship 哈特里-å�ƒå…‹å…³ç³» shielding difference of d and p in HD å±�蔽差的då’Œp,å�•ä½�为HD shielding difference of t and p in HT å±�蔽差的tå’Œp,å�•ä½�为HT pi (Ï€) 圆周率 (Ï€) Euler's number (e) 欧拉数 (e) golden ratio (φ) 黄金比例 (φ) Euler-Mascheroni constant (γ) 欧拉-马歇罗尼常数 (γ) nominal solar radius 标称太阳å�Šå¾„ nominal solar total irradiance 标称太阳总è¾�照度 nominal solar luminosity 标称太阳光度 nominal solar effective temperature 标称太阳有效温度 nominal solar mass parameter 标称太阳质é‡�å�‚æ•° nominal terrestrial equatorial radius 标称地ç�ƒèµ¤é�“å�Šå¾„ nominal terrestrial polar radius 标称地ç�ƒæž�å�Šå¾„ nominal terrestrial mass parameter 标称地ç�ƒè´¨é‡�å�‚æ•° nominal jovian equatorial radius 标称木星赤é�“å�Šå¾„ nominal jovian polar radius 标称木星æž�å�Šå¾„ nominal jovian mass parameter 标称木星质é‡�å�‚æ•° average value of one minus the rate of TCG relative to TCB 1 å‡� TCG 相对于 TCB 速率的平å�‡å€¼ solar mass parameter (TCB-compatible) 太阳质é‡�å�‚æ•° (TCB-compatible) solar mass parameter (TDB-compatible) 太阳质é‡�å�‚æ•° (TDB-compatible) equatorial radius of the Earth (TT-compatible) 地ç�ƒèµ¤é�“å�Šå¾„ (TT-compatible) dynamical form factor of the Earth 地ç�ƒåŠ¨åŠ›å­¦å½¢çŠ¶å› å­� time rate of change in the dynamical form factor of the Earth 地ç�ƒåŠ¨åŠ›å­¦å½¢çŠ¶å› å­�的时间å�˜åŒ–率 geocentric gravitational constant (TCB-compatible) 地心引力常数 (TCB-compatible) geocentric gravitational constant (TT-compatible) 地心引力常数 (TT-compatible) geocentric gravitational constant (TDB-compatible) 地心引力常数 (TDB-compatible) potential of the geoid 大地水准é�¢åŠ¿ nominal mean angular velocity of the Earth (TT-compatible) 标称地ç�ƒå¹³å�‡è§’速度 (TT-compatible) ratio mass of the Moon to the Earth 月ç�ƒä¸Žåœ°ç�ƒè´¨é‡�比 ratio of the mass of the Sun to Mercury 太阳与水星质é‡�比 ratio of the mass of the Sun to Venus 太阳与金星质é‡�比 ratio of the mass of the Sun to Mars 太阳与ç�«æ˜Ÿè´¨é‡�比 ratio of the mass of the Sun to Jupiter 太阳与木星质é‡�比 ratio of the mass of the Sun to Saturn 太阳与土星质é‡�比 ratio of the mass of the Sun to Uranus 太阳与天王星质é‡�比 ratio of the mass of the Sun to Neptune 太阳与海王星质é‡�比 ratio of the mass of the Sun to (134340) Pluto 太阳与 (134340) 冥王星质é‡�比 ratio of the mass of the Sun to (136199) Eris 太阳与 (136199) 阋神星质é‡�比 ratio of the mass of (1) Ceres to the Sun (1) 谷神星与太阳质é‡�比 ratio of the mass of (2) Pallas to the Sun (2) 智神星与太阳质é‡�比 ratio of the mass of (4) Vesta to the Sun (4) ç�¶ç¥žæ˜Ÿä¸Žå¤ªé˜³è´¨é‡�比 mean obliquity of the ecliptic at J2000.0 J2000.0 时的黄é�“å¹³å�‡å€¾è§’ Electromagnetic 电ç£�å­¦ Compton wavelength 康普顿波长 Astronomy 天文 ConstantsWidget Domain 领域 Subdomain å­�领域 No match found 没有找到匹é…� Name å��ç§° Value 值 Unit å�•ä½� Search æ�œç´¢ All 全部 CustomKeypadDialog Custom Keypad 自定义键盘 Rows: 行: Columns: 列: Copy preset: å¤�制预设: Basic 基础 Scientific (wide) 科学(宽) Scientific (narrow) 科学(窄) Apply 应用 Row 行 Column 列 Label 标签 Behavior 行为 Text 文本 DiagnosticsDialog App Diagnostics 应用诊断 Copy to Clipboard å¤�制到剪贴æ�¿ Editor Unit å�•ä½� User unit 用户å�•ä½� User function 用户函数 Argument å�‚æ•° Current result:<br/>%1 当å‰�结果:<br/>%1 Selection result:<br/>%1 选区结果:<br/>%1 Selection result: n/a 选中结果:N/A Selection result: %1 选中结果:%1 second ç§’ metre ç±³ kilogram å�ƒå…‹ mole æ‘©å°” radian 弧度 steradian ç�ƒé�¢åº¦ degree Celsius æ‘„æ°�度 cubic metre 立方米 cubic millimetre 立方毫米 cubic centimetre 立方厘米 cubic decimetre 立方分米 cubic kilometre ç«‹æ–¹å�ƒç±³ square millimetre 平方毫米 square kilometre 平方å�ƒç±³ square metre 平方米 minute 分钟 hour å°�æ—¶ day æ—¥ astronomical unit 天文å�•ä½� degree 度 arcminute 角分 arcsecond è§’ç§’ milliarcsecond 毫角秒 microarcsecond 微角秒 hectare 公顷 litre å�‡ tonne å�¨ Dalton é�“尔顿 electronvolt 电å­�ä¼�特 Angstrom 埃 atmosphere 大气压 atomic mass unit 原å­�è´¨é‡�å�•ä½� British thermal unit 英热å�•ä½� calorie å�¡è·¯é‡Œ carat 克拉 cup æ�¯ cup (Imperial) æ�¯ï¼ˆè‹±åˆ¶ï¼‰ cup (Japanese) æ�¯ï¼ˆæ—¥åˆ¶ï¼‰ cup (US) æ�¯ï¼ˆç¾Žåˆ¶ï¼‰ degree Fahrenheit å�Žæ°�度 fathom 英寻 fluid ounce (Imperial) æ¶²é‡�盎å�¸ï¼ˆè‹±åˆ¶ï¼‰ fluid ounce (US) æ¶²é‡�盎å�¸ï¼ˆç¾Žåˆ¶ï¼‰ fluid dram (Imperial) æ¶²é‡�打兰(英制) fluid dram (US) æ¶²é‡�打兰(美制) foot 英尺 square foot 平方英尺 cubic foot 立方英尺 gallon (Imperial) 加仑(英制) gallon (US) 加仑(美制) gill (Imperial) å�Šè€³ï¼ˆè‹±åˆ¶ï¼‰ gill (US) å�Šè€³ï¼ˆç¾Žåˆ¶ï¼‰ gradian 百分度 grain 格令 gram å…‹ Hartley 哈特莱 Hartree energy unit 哈特里能é‡�å�•ä½� horsepower 马力 inch 英寸 square inch 平方英寸 cubic inch 立方英寸 karat å¼€ knot 节 lightminute 光分 lightsecond 光秒 lightyear 光年 long ton é•¿å�¨ mile 英里 square mile 平方英里 cubic mile 立方英里 mile per hour 英里æ¯�å°�æ—¶ kilometre per hour å�ƒç±³æ¯�å°�æ—¶ nautical mile 海里 ounce 盎å�¸ parsec ç§’å·®è·� pint (Imperial) å“�脱(英制) pint (US) å“�脱(美制) pound 磅 pounds per square inch 磅æ¯�平方英寸 quart (Imperial) 夸脱(英制) quart (US) 夸脱(美制) oil barrel 石油桶 beer barrel (US) 啤酒桶(美制) square yard 平方ç � cubic yard ç«‹æ–¹ç � short ton 短å�¨ tablespoon 汤匙 tablespoon (Australian) 汤匙(澳制) tablespoon (Imperial) 汤匙(英制) tablespoon (US) 汤匙(美制) dessert spoon 甜点匙 teaspoon 茶匙 teaspoon (Imperial) 茶匙(英制) teaspoon (US) 茶匙(美制) turn 圈 revolution 转 revolution per minute 转æ¯�分钟 week 周 kilowatt hour å�ƒç“¦æ—¶ millimetre of mercury 毫米汞柱 yard ç � Julian century 儒略世纪 Julian year 儒略年 sidereal year æ�’星年 tropical year 回归年 Evaluator invalid expression 无效的表达å¼� division by zero 被零除 too time consuming - computation was rejected 过于耗时 - 计算被拒ç»� dimension mismatch - quantities with different dimensions cannot be compared, added, etc. é‡�纲ä¸�匹é…� - ä¸�å�Œé‡�纲的数ä¸�能进行比较ã€�相加等 invalid dimension - operation might require dimensionless arguments 无效é‡�纲 - æ“�作å�¯èƒ½éœ€è¦�æ— é‡�纲å�‚æ•° Computation aborted - encountered numerical instability 计算中止 - é�‡åˆ°æ•°å€¼ä¸�稳定 invalid dimension - function might require dimensionless arguments 无效é‡�纲 - 函数å�¯èƒ½éœ€è¦�æ— é‡�纲å�‚æ•° error 错误 unit must not be zero å�•ä½�ä¸�能为零 Conversion failed - dimension mismatch 转æ�¢å¤±è´¥ - é‡�纲ä¸�匹é…� unknown function or variable 未知函数或å�˜é‡� recursion not supported ä¸�支æŒ�递归 cannot operate on a NaN ä¸�能对 NaN 进行æ“�作 underflow - tiny result is out of SpeedCrunch's number range 下溢出 - 太å°�的结果超出了 SpeedCrunch 的数值范围 overflow - huge result is out of SpeedCrunch's number range 上溢出 - 太大的结果超出了 SpeedCrunch 的数值范围 overflow - logic result exceeds maximum of 256 bits 上溢出 - 逻辑结果超出了最大 256 ä½�çš„é™�制 overflow - integer result exceeds maximum limit for integers 上溢出 - 整数结果超出了整数的最大é™�制 operation is not defined for these arguments 这些å�‚数未定义该è¿�ç®— wrong number of arguments å�‚æ•°æ•°é‡�错误 does not take NaN as an argument NaN ä¸�能作为å�‚æ•° result out of range 结果超出范围 undefined for argument domain 未定义为å�‚数域 computation too expensive 计算过于å¤�æ�‚ internal error, please report a bug 内部错误,请å��馈 Bug syntax error 语法错误 conversion target must be a unit 转æ�¢ç›®æ ‡å¿…须是å�•ä½� unknown unit 未知å�•ä½� %1 is a reserved name, please choose another %1 是一个ä¿�ç•™å��称,请选å�–å…¶ä»–å��ç§° %1 is a global user definition and cannot be overridden in this session. %1 是全局用户定义,ä¸�能在此会è¯�中覆盖。 %1 is a variable name, please choose another or delete the variable %1 是一个å�˜é‡�å��,请选å�–å…¶ä»–å��称或者删除å�˜é‡� argument %1 is used more than once å�‚æ•° %1 使用了超过一次 %1 is a built-in unit name, please choose another %1 是内置å�•ä½�å��称,请选择其他å��ç§° %1 is a user function name, please choose another or delete the function %1 是用户函数å��,请选å�–å…¶ä»–å��称或者删除函数 FunctionRepo max; trials; probability 最大; 试验数; 概率 trials; probability 试验数; 概率 hits; trials; probability å�ˆæ ¼æ•°; 试验数; 概率 max; total; hits; trials 最大; 总数; å�ˆæ ¼æ•°; 试验数 total; hits; trials 总数; å�ˆæ ¼æ•°; 试验数 count; total; hits; trials 计数; 总数; å�ˆæ ¼æ•°; 试验数 dividend; divisor 被除数; 除数 x; exponent_bits; significand_bits [; exponent_bias] x; 指数ä½�; 有效ä½� [; 指数å��å·®] base; x 基数; x value; modulo 值; 模 base; exponent; modulo 底数; 指数; 模数 events; average_events 事件; å¹³å�‡äº‹ä»¶ average_events å¹³å�‡äº‹ä»¶ x [; precision] x [; 精度] Absolute Value ç»�对值 Absolute Deviation ç»�对å��å·® Arc Cosine å��余弦 Logical AND 逻辑与 Area Hyperbolic Cosine 区域å�Œæ›²ä½™å¼¦ Area Hyperbolic Sine 区域å�Œæ›²æ­£å¼¦ Area Hyperbolic Tangent 区域å�Œæ›²æ­£åˆ‡ Arc Sine å��正弦 Arc Tangent å��正切 Arc Tangent with two Arguments 2 个å�‚æ•°çš„å��正切 Average (Arithmetic Mean) å¹³å�‡ (算术平å�‡å€¼) Binomial Cumulative Distribution Function 二项累积分布函数 Binomial Distribution Mean 二项分布平å�‡å€¼ Binomial Probability Mass Function 二项概率质é‡�函数 Binomial Distribution Variance 二项分布方差 Cube Root 立方根 Complex Conjugate 共轭å¤�æ•° Cosine 余弦 Hyperbolic Cosine å�Œæ›²ä½™å¼¦ Cotangent 余切 Cosecant 余割 Convert Unix timestamp to Date å°†Unix时间戳转æ�¢ä¸ºæ™®é€šæ—¶é—´ Degrees of Arc 弧度 Error Function 误差函数 Complementary Error Function 互补误差函数 Exponential 指数 Fractional Part å°�数部分 Extension of Factorials [= (x-1)!] 扩充阶乘 [伽马函数 = (x-1)!] Greatest Common Divisor 最大公约数 Geometric Mean 几何平å�‡æ•° Gradians of arc 将弧度转æ�¢ä¸ºç™¾åˆ†åº¦ Hypergeometric Cumulative Distribution Function 超几何累积分布函数 Hypergeometric Distribution Mean 超几何分布平å�‡å€¼ Hypergeometric Probability Mass Function 超几何概率质é‡�函数 Hypergeometric Distribution Variance 超几何分布方差 Integer Quotient 整数商 Integer Part 整数部分 Imaginary Part 虚部 Decode IEEE-754 Binary Value è§£ç � IEEE-754 二进制值 Encode IEEE-754 Binary Value ç¼–ç � IEEE-754 二进制值 Decode 16-bit Half-Precision Value è§£ç � 16 ä½�å�Šç²¾åº¦å€¼ Encode 16-bit Half-Precision Value ç¼–ç � 16 ä½�å�Šç²¾åº¦å€¼ Decode 32-bit Single-Precision Value è§£ç � 32 ä½�å�•精度值 Encode 32-bit Single-Precision Value ç¼–ç � 32 ä½�å�•精度值 Decode 64-bit Double-Precision Value è§£ç � 64 ä½�å�Œç²¾åº¦å€¼ Encode 64-bit Double-Precision Value ç¼–ç � 64 ä½�å�Œç²¾åº¦å€¼ Decode 128-bit Quad-Precision Value è§£ç � 128 ä½�四精度值 Encode 128-bit Quad-Precision Value ç¼–ç � 128 ä½�四精度值 Binary Logarithm 以2为底的对数 Common Logarithm 常用对数 Natural Logarithm 自然对数 Logarithm to Arbitrary Base 以给定数字为底的对数 Mask to a bit size 一个二进制ä½�大å°�的掩ç � Maximum 最大值 Median Value (50th Percentile) 中值 (50% 处) Minimum 最å°�值 Modulo 模 Euclidean Modulo 欧几里得å�–模 Modular Exponentiation 模幂è¿�ç®— Combination (Binomial Coefficient) 组å�ˆï¼ˆäºŒé¡¹å¼�系数) Logical NOT 逻辑é�ž Permutation (Arrangement) 排列(置æ�¢ï¼‰ Convert to Binary Representation 转æ�¢ä¸ºäºŒè¿›åˆ¶è¡¨ç¤º Arithmetic 算术 Chemistry 化学 Complex å¤�æ•° Combinatorics 组å�ˆæ•°å­¦ Probability 概率 Statistics 统计 Aggregation è�šå�ˆ Random éš�机 Base conversion 进制转æ�¢ Number formatting æ•°å­—æ ¼å¼�化 Integer arithmetic 整数算术 Special functions 特殊函数 Exponential & Logarithmic 指数与对数 Angle conversion 角度转æ�¢ Trigonometry 三角函数 Bitwise ä½�è¿�ç®— Floating point 浮点 Date & Time 日期与时间 Linear algebra 线性代数 unix_timestamp; x hours offset to GMT Unix时间戳;时区与GMT时间的时间之差 yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmss;相对 GMT å��ç§» x å°�æ—¶ [digits] [ä½�æ•°] max [; min] 最大值 [; 最å°�值] List Literal 列表字é�¢é‡� Convert to Padded Binary Representation 转æ�¢ä¸ºè¡¥é›¶äºŒè¿›åˆ¶è¡¨ç¤º Round Toward +∞ (Ceiling) å�‘ +∞ èˆ�入(上å�–整) Cosine plus Imaginary Sine 余弦加虚数正弦 Convert to Cis Complex Form 转æ�¢ä¸º Cis å¤�æ•°å½¢å¼� Matrix Column Count 矩阵列数 Population Correlation Matrix (n) 总体相关矩阵 (n) Sample Correlation Matrix (n-1) 样本相关矩阵 (n-1) Count 计数 Population Covariance Matrix (n) 总体å��方差矩阵 (n) Sample Covariance Matrix (n-1) 样本å��方差矩阵 (n-1) Cross Product å�‰ç§¯ Convert Date to Unix timestamp 将日期转æ�¢ä¸º Unix 时间戳 Convert to Decimal Representation 转æ�¢ä¸ºå��进制表示 Determinant 行列å¼� Convert to Sexagesimal Notation 转æ�¢ä¸ºå…­å��进制表示 Dot Product 点积 Convert to Engineering Notation 转æ�¢ä¸ºå·¥ç¨‹è¡¨ç¤ºæ³• Convert to Exponential Complex Form 转æ�¢ä¸ºæŒ‡æ•°å¤�æ•°å½¢å¼� Round Toward −∞ (Floor) å�‘ −∞ èˆ�入(下å�–整) Flatten Matrix 展平矩阵 Least Common Multiple 最å°�å…¬å€�æ•° Convert to Hexadecimal Representation 转æ�¢ä¸ºå��六进制表示 Convert to Padded Hexadecimal Representation 转æ�¢ä¸ºè¡¥é›¶å��六进制表示 Inverse Matrix 逆矩阵 Round to 16-bit Half-Precision Value èˆ�入为 16 ä½�å�Šç²¾åº¦å€¼ Round to 32-bit Single-Precision Value èˆ�入为 32 ä½�å�•精度值 Round to 64-bit Double-Precision Value èˆ�入为 64 ä½�å�Œç²¾åº¦å€¼ Round to 128-bit Quad-Precision Value èˆ�入为 128 ä½�四精度值 Residual from 16-bit Half-Precision Rounding 16 ä½�å�Šç²¾åº¦èˆ�入残差 Residual from 32-bit Single-Precision Rounding 32 ä½�å�•精度èˆ�入残差 Residual from 64-bit Double-Precision Rounding 64 ä½�å�Œç²¾åº¦èˆ�入残差 Residual from 128-bit Quad-Precision Rounding 128 ä½�四精度èˆ�入残差 Substance Mass 物质质é‡� Molarity 摩尔浓度 Molar Mass 摩尔质é‡� Median Absolute Deviation 中ä½�æ•°ç»�对å��å·® Mean å¹³å�‡å€¼ Numerical Value of Quantity é‡�的数值 Random Decimal Number éš�机å°�æ•° Random Integer Number éš�机整数 Convert to Rational Representation 转æ�¢ä¸ºæœ‰ç�†æ•°è¡¨ç¤º Convert to Octal Representation 转æ�¢ä¸ºå…«è¿›åˆ¶è¡¨ç¤º Convert to Padded Octal Representation 转æ�¢ä¸ºè¡¥é›¶å…«è¿›åˆ¶è¡¨ç¤º Vector or Matrix Norm å�‘é‡�或矩阵范数 Logical OR 逻辑或 Population Count (Hamming Weight) ä½�计数(汉明é‡�é‡�) Phase of Complex Number å¤�数的相 Poissonian Cumulative Distribution Function 泊æ�¾ç´¯ç§¯åˆ†å¸ƒå‡½æ•° Poissonian Distribution Mean 泊æ�¾åˆ†å¸ƒå¹³å�‡å€¼ Poissonian Probability Mass Function 泊æ�¾æ¦‚率质é‡�函数 Poissonian Distribution Variance 泊æ�¾åˆ†å¸ƒæ–¹å·® Convert to Phasor Complex Form 转æ�¢ä¸ºç›¸é‡�å¤�æ•°å½¢å¼� Convert to Rectangular Complex Form 转æ�¢ä¸ºç›´è§’å��æ ‡å¤�æ•°å½¢å¼� Round Half Away from Zero å�Šæ•°è¿œç¦»é›¶èˆ�å…¥ Round Half Even å�Šå�¶èˆ�å…¥ Nth Root n 次方根 Convert to Scientific Notation 转æ�¢ä¸ºç§‘学记数法 Matrix Row Count 矩阵行数 List or Matrix Shape 列表或矩阵形状 Summation 求和 Population Standard Deviation (n) 总体标准差 (n) Sample Standard Deviation (n-1) 样本标准差 (n-1) Round Toward Zero (Truncation) å�‘é›¶èˆ�入(截断) Matrix Trace 矩阵迹 Transpose Matrix 转置矩阵 Population Variance (n) 总体方差 (n) Sample Variance (n-1) 样本方差 (n-1) Product 乘积 Radians 弧度 Matrix Rank 矩阵秩 Real Part 实部 Secant 正割 Arithmetic Shift Left 算术左移 Arithmetic Shift Right 算术å�³ç§» Signum 符å�·å‡½æ•° Sine 正弦 Hyperbolic Sine å�Œæ›²æ­£å¼¦ Square Root 平方根 Sum 求和 Tangent 正切 Convert to Trigonometric Complex Form 转æ�¢ä¸ºä¸‰è§’å¤�æ•°å½¢å¼� Turns 圈 Hyperbolic Tangent å�Œæ›²æ­£åˆ‡ Sign-extend a value 对一个值进行符å�·æ‰©å±• Logical XOR 逻辑异或 FunctionsWidget Domain 领域 All 全部 Name å��ç§° Search æ�œç´¢ No match found 没有找到匹é…� Identifier 标识符 HistoryWidget Remove All Calculations Above 删除上方所有计算 Remove This Calculation 移除此计算 Remove All Calculations Below 删除下方所有计算 Keypad Inverse cosine å��余弦 The last result 上次计算的结果 Inverse sine å��正弦 Inverse tangent å��正切 Evaluate expression 计算表达å¼� Division 除法 Multiplication 乘法 Subtraction å‡�法 Addition 加法 Clear expression 清除表达å¼� Cosine 余弦 Backspace 退格 Scientific notation 科学计数法 Exponential 指数 Factorial 阶乘 Natural logarithm 自然对数 Left parenthesis 左括å�· Nth root n 次方根 Argument separator å�‚数分隔符 Square 平方 Common logarithm 常用对数 Modulo å�–模 Contextual percentage 上下文百分比 Power 幂 Right parenthesis å�³æ‹¬å�· Sine 正弦 Square root 平方根 Tangent 正切 Pi 圆周率 Decimal separator å°�数分隔符 MainWindow Radian 弧度 Degree 角度 Gradian 百分度 Binary 二进制 Octal 八进制 Hexadecimal å��六进制 Sexagesimal å…­å��进制 Engineering decimal 工程å��进制 Scientific decimal ç§‘å­¦å��进制 &Import... 导入(&I)... &Quit 退出(&Q) Clear E&xpression 清除表达å¼�(&X) Clear &History 清除历å�²(&H) &Copy å¤�制(&C) &Paste 粘贴(&P) &Select Expression 选择表达å¼�(&S) &Constants 常é‡�(&C) &Functions 函数(&F) &History 历å�²(&H) &Status Bar 状æ€�æ �(&S) Bitfield ä½�域 Use&r Functions 用户函数(&R) &Degree 角度(&D) &Radian 弧度(&R) &Gradian 百分度 Re&volution 转(&V) Auto-Insert a&ns 自动æ�’å…¥ ans(&N) Automatic &Completion 自动补全(&C) &Built-in Functions 内置函数(&B) Built-in &Variables 内置å�˜é‡�(&V) User &Functions 用户函数(&F) User Va&riables 用户å�˜é‡�(&R) Open a Private Tab on Startup å�¯åŠ¨æ—¶æ‰“å¼€éš�ç§�标签页 Open and focus a new private tab whenever SpeedCrunch starts. æ¯�次å�¯åЍ SpeedCrunch 时打开并è�šç„¦æ–°çš„éš�ç§�标签页。 Syntax &Highlighting 语法高亮(&H) Group Digits in &Input 对输入数字分组(&I) Automatic Input &Adjustments 自动调整输入(&A) Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. 自动调整è¿�算符ã€�é—´è·�ã€�括å�·å’Œå¹‚,并将输入é™�制为有效字符。 Group input digits using the selected number format. 按所选数字格å¼�对输入数字分组。 &Blinking Cursor 光标闪çƒ�(&B) Blink the cursor in the expression editor. 使表达å¼�编辑器中的光标闪çƒ�。 &Escape Clears Editor Escape 清空编辑器(&E) Clear the focused expression editor with Escape after dismissing any popup or preview. 关闭所有弹出窗å�£æˆ–预览å�Žï¼ŒæŒ‰ Escape 清空当å‰�è�šç„¦çš„表达å¼�编辑器。 Keep Expression After Evaluation 计算å�Žä¿�留表达å¼� Copy New Results Automatically 自动å¤�制新结果 &Comma 逗å�·(&C) &System Default 系统默认(&S) &Dot 点(&D) Dot &And Comma 点和逗å�·(&A) Toward +∞ (&ceil) è¶‹å�‘ +∞ (ceil)(&C) Toward −∞ (&floor) è¶‹å�‘ −∞ (floor)(&F) &Binary 二进制(&B) &Engineering 工程(&E) &Hexadecimal å��六进制(&H) &Octal 八进制(&O) &Scientific ç§‘å­¦(&S) User &Manual 用户手册(&M) Issues and &Feedback 问题与å��馈(&F) &Donate æ��èµ (&D) &About SpeedCrunch 关于 SpeedCrunch(&A) App Diag&nostics 应用诊断(&N) S&plit 拆分(&P) Angle &Mode 角度模å¼�(&M) &Complex Form å¤�æ•°å½¢å¼�(&C) New Tab 新建标签页 Constants 常数 Functions 函数 History 历å�² User Functions 用户函数 &Font... 字体(&F)... &Language... 语言(&L)... &Session 会è¯�(&S) &Edit 编辑(&E) &View 查看(&V) Se&ttings 设置(&T) &Decimal å��进制(&D) &Keypad 输入键盘(&K) Always on &Top 总在最å‰�(&T) Disabled ç¦�用 Small Space 窄分隔 Medium Space 中分隔 Large Space 宽分隔 &0 Digits &0 ä½� &15 Digits &15 ä½� &2 Digits &2 ä½� &3 Digits &3 ä½� &50 Digits &50 ä½� &8 Digits &8 ä½� &Sexagesimal å…­å��分制 Reset All Settings... é‡�置所有设置... &System 系统(&S) SpeedCrunch &Theme SpeedCrunch 主题(&T) &Classic ç»�å…¸(&C) &Modern 现代(&M) Context Help 上下文帮助 &Help 帮助(&H) Error 错误 Can't read from file %1 无法读å�–文件 %1 Import Session 导入会è¯� Close Session 关闭会è¯� Angle Mode: 角度模å¼�: Notation: 表示法: Precision: 精度: Turn 圈 Revolution 转 Fixed-point decimal 定点å°�æ•° Rational 有ç�†æ•° Automatic decimal 自动å°�æ•° Automatic 自动 User &Definitions... 用户定义(&D)... New &Tab 新建标签页(&T) New &Private Tab 新建éš�ç§�标签页(&P) Keep ä¿�ç•™ Make Private... 设为éš�ç§�会è¯�... New &Window 新建窗å�£(&W) &Open... 打开(&O)... &Rename... é‡�命å��(&R)... Clo&ne... 克隆(&N)... &Close Tab 关闭标签页(&C) Reopen Clo&sed Tab é‡�新打开已关闭的标签页(&S) Open Sessions &Folder 打开会è¯�文件夹(&F) &Undo 撤销(&U) &Redo é‡�å�š(&R) Cu&t 剪切(&T) Copy &Last Result å¤�制上次结果(&L) &Wrap in Parentheses 用括å�·æ‹¬èµ·(&W) Full Scr&een Mode å…¨å±�模å¼�(&E) &Basic 基础(&B) &Scientific (wide) 科学(宽)(&S) Scientific (narrow) 科学(窄) &Custom... 自定义(&C)... Main &Menu 主è�œå�•(&M) User &Variables 用户å�˜é‡�(&V) &Left å�‘å·¦(&L) &Right å�‘å�³(&R) &Up å�‘上(&U) &Down å�‘下(&D) Close Pa&ne 关闭窗格(&N) User &Units 用户å�•ä½�(&U) &Turn 圈(&T) If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. å¦‚果新表达å¼�以 +ã€�-ã€�* 或 / 开头,SpeedCrunch 会先æ�’å…¥ "ans"。 &Accept with Enter 按回车键接å�—(&A) Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. 按回车键接å�—当å‰�自动补全建议,无需先用方å�‘键选中。 &Units å�•ä½�(&U) Show Live Result &Preview 显示实时结果预览(&P) Save &Window Position on Exit 退出时ä¿�存窗å�£ä½�ç½®(&W) Hover Highlighting 悬å�œé«˜äº® Group Integer Part Only 仅分组整数部分 Number Format... æ•°å­—æ ¼å¼�... Notation && Precision... 表示法和精度... After pressing Enter, keep the entered expression selected in the editor. 按 Enter å�Žï¼Œåœ¨ç¼–辑器中ä¿�æŒ�选中已输入的表达å¼�。 Never 从ä¸� Always 始终 Only for Single-Line Expressions ä»…å�•行表达å¼� Simplify Displayed Expressions 简化显示的表达å¼� History Size &Limit... 历å�²å¤§å°�é™�制(&L)... Remove Trailing &Zeroes 移除末尾零(&Z) Nearest, Half &Away (round) 最近,å�Šæ•°è¿œç¦»é›¶(&A) (round) Nearest, Half &Even (roundeven) 最近,å�Šå�¶(&E) (roundeven) Toward &Zero (trunc) å�‘é›¶(&Z) (trunc) &Fixed-Point 定点(&F) &Rational 有ç�†æ•°(&R) &Exponential (m·sâ�»Â¹) 指数(&E) (m·sâ�»Â¹) &Fractional (m/s) 分数(&F) (m/s) &Rectangular (a + bi) ç›´è§’å��æ ‡(&R) (a + bi) Exponential (reâ�±á¶¿) 指数 (reâ�±á¶¿) Trigonometric (r(cos θ + i·sin θ)) 三角 (r(cos θ + i·sin θ)) Phasor (r∠θ) 相é‡� (r∠θ) &Theme... 主题(&T)... Check for &Updates 检查更新(&U) Source Code æº�代ç � &Zoom 缩放(&Z) &Results 结果(&R) Unit Notation å�•ä½�表示法 Rounding Mode èˆ�入模å¼� &Notation 表示法(&N) &Imaginary Unit 虚数å�•ä½�(&I) &Window 窗å�£(&W) &Editing 编辑(&E) A&utocomplete 自动完æˆ�(&U) Up/Down Arrow History 上下箭头历å�² &Appearance 外观(&A) &Menus è�œå�•(&M) &Docks å�œé� é�¢æ�¿(&D) &Input and Results 输入与结果(&I) &Disabled å·²ç¦�用(&D) &Disable ç¦�用(&D) Close preview 关闭预览 Rename... é‡�命å��... Clone... 克隆... Close Tab 关闭标签页 New Private Tab 新建éš�ç§�标签页 Open... 打开... Reopen Closed Tab é‡�新打开已关闭的标签页 Split 拆分 Left å�‘å·¦ Right å�‘å�³ Up å�‘上 Down å�‘下 Clear 清空 Delete 删除 %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 éš�ç§�会è¯�:关闭时丢弃内容。 选择“会è¯� > ä¿�ç•™â€�å�¯å°†å…¶è½¬ä¸ºæ™®é€šä¼šè¯�。 SpeedCrunch - %1 [Private] SpeedCrunch - %1 [éš�ç§�] Reset All Settings é‡�置所有设置 Reset all settings to their default values? 将所有设置é‡�置为默认值? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. 这包括外观ã€�编辑ã€�结果格å¼�和窗å�£å��好设置。您的计算ã€�已打开的会è¯�和用户定义将会ä¿�留。 The settings file could not be written. 无法写入设置文件。 Clear this session's calculations, unfinished expression, variables, functions, and units? 清空此会è¯�的计算ã€�未完æˆ�的表达å¼�ã€�å�˜é‡�ã€�函数和å�•ä½�? Global user definitions are kept. 全局用户定义会ä¿�留。 Make Session Private 将会è¯�设为éš�ç§� The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. å·²ä¿�存的会è¯� %1 将被删除。其内容将继续在éš�ç§�会è¯�中打开,并在关闭该会è¯�或退出 SpeedCrunch 时丢弃。 Make Private 设为éš�ç§�会è¯� Could not delete the saved session %1. 无法删除已ä¿�存的会è¯� %1。 Keep Session ä¿�留会è¯� Could not save the session. It remains private. 无法ä¿�存会è¯�。该会è¯�ä»�为éš�ç§�会è¯�。 Clone Session 克隆会è¯� Could not save session file %1. 无法ä¿�存会è¯�文件 %1。 Could not delete session file %1. 无法删除会è¯�文件 %1。 JSON file (*.json);;Any file (*.*) JSON 文件 (*.json);;任何文件 (*.*) Export session as JSON 将会è¯�导出为 JSON The selected file is not valid JSON: %1 所选文件ä¸�是有效的 JSON:%1 The selected file is not a SpeedCrunch session JSON file. 所选文件ä¸�是 SpeedCrunch 会è¯� JSON 文件。 This file uses an obsolete SpeedCrunch session format and cannot be imported. 此文件使用已过时的 SpeedCrunch 会è¯�æ ¼å¼�,无法导入。 The selected JSON file is missing the required $schema field. 所选 JSON 文件缺少必需的 $schema 字段。 The selected JSON file uses an unsupported JSON schema: %1 所选 JSON 文件使用ä¸�å�—支æŒ�çš„ JSON 架构:%1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). 所选 JSON 文件缺少 SpeedCrunch 会è¯�架构标识符 ($id)。 The selected JSON file uses an unsupported SpeedCrunch session format: %1 所选 JSON 文件使用ä¸�å�—支æŒ�çš„ SpeedCrunch 会è¯�æ ¼å¼�:%1 The selected JSON file is missing the required session name. 所选 JSON 文件缺少必需的会è¯�å��称。 The selected JSON file has an empty session name. 所选 JSON 文件的会è¯�å��称为空。 The selected JSON file has invalid or incomplete SpeedCrunch session data. 所选 JSON 文件包å�«æ— æ•ˆæˆ–ä¸�完整的 SpeedCrunch 会è¯�æ•°æ�®ã€‚ Open Sessions Folder 打开会è¯�文件夹 Could not create the sessions folder: %1 无法创建会è¯�文件夹:%1 Could not open the sessions folder: %1 无法打开会è¯�文件夹:%1 Editor and Results Font 编辑器与结果字体 Open Session 打开会è¯� Community 社区 Rename Session é‡�命å��会è¯� Clear Session 清除会è¯� Delete Session 删除会è¯� Close Pane 关闭窗格 User Variables 用户å�˜é‡� User Units 用户å�•ä½� Clear History 清除历å�² Are you sure you want to clear the calculation history? 确定è¦�清除计算历å�²å�—? Session name: 会è¯�å��称: A session named %1 already exists. å��为 %1 的会è¯�已存在。 Could not create session file %1. 无法创建会è¯�文件 %1。 Could not write session file %1. 无法写入会è¯�文件 %1。 Are you sure you want to delete this session? 确定è¦�删除此会è¯�å�—? Custom Precision 自定义精度 Fractional digits: å°�æ•°ä½�数: Theme 主题 Light Themes 浅色主题 Dark Themes 深色主题 Preview 预览 Colors 颜色 Select color for %1 选择 %1 的颜色 Import... 导入... Export... 导出... Import Theme 导入主题 Theme file (*.json);;All files (*) 主题文件 (*.json);;所有文件 (*) Invalid theme file. 无效的主题文件。 Can't import theme "%1" because it conflicts with a built-in theme. 无法导入主题 "%1",因为它与内置主题冲çª�。 Can't find a writable theme folder. 找ä¸�到å�¯å†™çš„主题文件夹。 Overwrite Theme 覆盖主题 A custom theme named "%1" already exists. Do you want to overwrite it? å��为 "%1" 的自定义主题已存在。è¦�覆盖它å�—? Can't overwrite theme file %1 无法覆盖主题文件 %1 Can't copy theme file to %1 无法将主题文件å¤�制到 %1 Export Theme 导出主题 Can't export theme as "%1" because it conflicts with a built-in theme. 无法将主题导出为 "%1",因为它与内置主题冲çª�。 Can't write to file %1 无法写入文件 %1 Global User Variable 全局用户å�˜é‡� Global User Function 全局用户函数 Global User Unit 全局用户å�•ä½� User Definitions 用户定义 These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. 这些定义是全局的,会加载到æ¯�个会è¯�中。 它们无法在会è¯�中修改,并优先于会è¯�编辑器中的å�Œå��定义。 æ¯�行输入一个定义。 Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] 示例: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply 应用 Validate 验è¯� Test Results 测试结果 Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 已导入的å�˜é‡�:%1 已导入的函数:%2 已导入的å�•ä½�:%3 存在错误的行å�·ï¼š%4 none æ—  Apply Results 应用结果 User definitions saved. 用户定义已ä¿�存。 History Size Limit 历å�²å¤§å°�é™�制 Maximum number of history entries for this session (0 = unlimited): 此会è¯�的最大历å�²æ�¡ç›®æ•°ï¼ˆ0 = æ— é™�制): Text file (*.txt);;Any file (*.*) 文本文档 (*.txt);;所有文件 (*.*) Could not recalculate from calculation %1: %2 无法从计算 %1 é‡�新计算:%2 History Size Limit Reached 已达到历å�²å¤§å°�é™�制 This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. 此计算å� ç”¨äº†æœ€å�Žä¸€ä¸ªå�¯ç”¨åކå�²æ§½ã€‚å�Žç»­è®¡ç®—将从历å�²ä¸­ç§»é™¤æœ€æ—§çš„计算。你å�¯ä»¥ä»Žâ€œä¼šè¯� > 历å�²å¤§å°�é™�制â€�增加é™�制。 Editing calculation. Press Esc twice to cancel. 正在编辑计算。按两次 Esc å�–消。 Calculation Settings 计算设置 Invalid recalculation start index 无效的é‡�新计算起始索引 System Default 系统默认(&D) Language 语言 Select the language: 选择语言: Custom 自定义 Decimal places: å°�æ•°ä½�数: &Automatic 自动(&A) &Precision 精确(&P) Plain &text 纯文本(&T) Formula &Book å…¬å¼�手册(&B) &Export 导出(&E) Export session as HTML 导出会è¯�到 HTML HTML file (*.html) HTML 文件 (*.html) Export session as plain text 导出会è¯�到纯文本 ManualWindow SpeedCrunch Manual SpeedCrunch 手册 %1 - SpeedCrunch Manual %1 - SpeedCrunch 手册 NumberFormatDialog Number Format æ•°å­—æ ¼å¼� <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>选择结果和输入数字分组所用的数字格å¼�。</b><br/><br/>注æ„�:对于输入的数字,å�ªè¦�æ ¼å¼�明确,å�³ä½¿ä¸Žæ‰€é€‰æ˜¾ç¤ºæ ¼å¼�ä¸�å�Œä¹Ÿä¼šè¢«æŽ¥å�—。<br/> QObject Global User Variable 全局用户å�˜é‡� Global User Function 全局用户函数 Global User Unit 全局用户å�•ä½� Backspace 退格 Clear expression 清除表达å¼� Evaluate expression 计算表达å¼� Insert text æ�’入文本 Automatic decimal 自动å°�æ•° Fixed-point decimal 定点å°�æ•° Engineering decimal 工程å°�æ•° Scientific decimal ç§‘å­¦å°�æ•° Rational 有ç�†æ•° Binary 二进制 Octal 八进制 Hexadecimal å��六进制 Sexagesimal å…­å��进制 Update Available 有å�¯ç”¨æ›´æ–° A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> 有新版本 (%1) å�¯ç”¨ã€‚<br/><a href="%2">访问网站下载。</a> Check for Updates 检查更新 SpeedCrunch %1 is up to date. SpeedCrunch %1 已是最新版本。 No connectivity. Please check your internet connection and try again. 无网络连接。请检查互è�”网连接å�Žé‡�试。 Could not verify the latest available version. 无法验è¯�最新å�¯ç”¨ç‰ˆæœ¬ã€‚ ResultDisplay Scroll to bottom 滚动到底部 Edit Expression 编辑表达å¼� Change Settings 更改设置 New Tab 新建标签页 &Import... 导入(&I)... &Export 导出(&E) Plain &text 纯文本(&T) Copy å¤�制 Selection 选中内容 Select All 全选 Expression 表达å¼� Result 结果 Calculation 计算 Calculation as Single Line å�•行计算 Remove 移除 This Calculation 此项计算 All Calculations Above 上方所有计算 All Calculations Below 下方所有计算 New Private Tab 新建éš�ç§�标签页 Session 会è¯� Open... 打开... Clone... 克隆... Rename... é‡�命å��... Keep ä¿�ç•™ Make Private... 设为éš�ç§�会è¯�... Clear 清空 Delete 删除 Close 关闭 Split 拆分 Left å�‘å·¦ Right å�‘å�³ Up å�‘上 Down å�‘下 Close Pane 关闭窗格 Main Menu 主è�œå�• Cancel editing å�–消编辑 Copy result å¤�制结果 Edit expression 编辑表达å¼� Change settings 更改设置 Remove calculation 删除计算 ResultSlotsDialog Notation & Precision 表示法和精度 Result Line 结果行 Enabled å·²å�¯ç”¨ Notation 表示法 Decimal Places å°�æ•°ä½�æ•° Main Line 主行 Extra Line #1 附加行 #1 Extra Line #2 附加行 #2 Extra Line #3 附加行 #3 Extra Line #4 附加行 #4 Auto 自动 UserFunctionListWidget Name å��ç§° Value 值 Description æ��è¿° Search æ�œç´¢ No match found 没有找到匹é…� Insert æ�’å…¥ Edit 编辑 Delete 删除 Delete All 全部删除 UserUnitListWidget Name å��ç§° Value 值 Description æ��è¿° Search æ�œç´¢ No match found 没有找到匹é…�项 Insert æ�’å…¥ Edit 编辑 Delete 删除 Delete All 全部删除 VariableListWidget Name å��ç§° Value 值 Description æ��è¿° Search æ�œç´¢ No match found 没有找到匹é…� Insert æ�’å…¥ Edit 编辑 Delete 删除 Delete All 全部删除 heldercorreia-speedcrunch-e7ca37f/src/resources/locale/zh_TW.ts000066400000000000000000010351031526573132500250030ustar00rootroot00000000000000 AboutBox About SpeedCrunch 關於 SpeedCrunch Core developers 核心開發團隊 Original author 原作者 Close 關閉 Math engine 數學引擎 Main author | Logo | Maintainer 主è¦�作者 | 標誌 | 維護者 Thanks 致è¬� Copyright (C) 2004-2026 The SpeedCrunch developers 版權所有 (C) 2004-2026 SpeedCrunch 開發團隊 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version 本程å¼�是自由軟體;你å�¯ä»¥ä¾�自由軟體基金會發布的 GNU General Public License æ¢�款é‡�新散布å�Š/或修改本程å¼�;授權æ¢�款å�¯ä½¿ç”¨ç¬¬ 2 版,或(ä¾�ä½ çš„é�¸æ“‡ï¼‰ä»»ä½•更新版本 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 散布本程å¼�是希望它有所助益,但ä¸�æ��供任何ä¿�證;甚至ä¸�包å�«é�©å”®æ€§æˆ–特定用途é�©ç”¨æ€§çš„默示ä¿�證。詳情請å�ƒé–± GNU General Public License。 BitFieldWidget Reset bits to zero å°‡ä½�å…ƒé‡�設為零 Invert bits å��轉ä½�å…ƒ Shift bits left å�‘å·¦ä½�ç§»ä½�å…ƒ Shift bits right å�‘å�³ä½�ç§»ä½�å…ƒ Book Index 索引 Algebra 代數 Quadratic Equation 二次方程å¼� Logarithmic Base Conversion å°�數基底轉æ�› Geometry 幾何 Circle 圓 Sector 扇形 Sphere ç�ƒ Cube 立方體 Cone 圓éŒ� Cylinder 圓柱 Electronics é›»å­� Ohm's Law æ­�姆定律 Power 功率 Reactance 阻抗 Resonance 共振 Radio Frequency å°„é » Antennas 天線 Characteristic Impedance (coax) 特性阻抗 (å�Œè»¸) Velocity of Propagation (coax) 傳播速度 (å�Œè»¸) Standing Wave Ratio & Return Loss é§�波比&&回波æ��耗 Free Space Wavelength 自由空間波長 resistance 電阻 voltage 電壓 current é›»æµ� power 功率 inductive reactance 感抗 capacitive reactance 容抗 inductance 電感 capacitance 電容 frequency 頻率 resonance frequency 共振頻率 area é�¢ç©� perimeter 周長 diameter 直徑 radius å�Šå¾‘ volume é«”ç©� surface area 表é�¢ç©� height 高度 slant height æ–œå�‘高度 face diagonal å¹³é�¢å°�è§’ç·š space diagonal 空間å°�è§’ç·š edge length 邊長 arc length å¼§é•· central angle (degrees) 中心角 (度) input power 輸入功率 reflected power å��射功率 transmitted power 發射功率 return loss 回波æ��耗 dielectric constant 介電常數 outer conductor's inner diameter 外導體內徑 inner conductor's outer diameter 內導體外徑 speed of light 光速 reflection coefficient å��射係數 standing wave ratio é§�波比 normalized impedance 歸一化阻抗 frequency (Hz) 頻率(Hz) BookDock Formula Book å…¬å¼�手冊 ConstantCompletion Search constants æ�œå°‹å¸¸æ•¸ No match found 沒有符å�ˆçš„çµ�æžœ Constants Mathematics 數學 Physics (CODATA 2022) 物ç�†ï¼ˆCODATA 2022) Chemistry (IUPAC - CIAAW 2021) 化學(IUPAC - CIAAW 2021) Uncategorized 未分類 Universal 通用 Physicochemical 物ç�†åŒ–å­¸ Atomic & Nuclear — General 原å­�與核å­� - 一般 Atomic & Nuclear — Electroweak 原å­�與核å­� - 電弱 Atomic & Nuclear — Electron 原å­�與核å­� - é›»å­� Atomic & Nuclear — Muon 原å­�與核å­� - ç·²å­� Atomic & Nuclear — Tau 原å­�與核å­� - é™¶å­� Atomic & Nuclear — Proton 原å­�與核å­� - 質å­� Atomic & Nuclear — Neutron 原å­�與核å­� - 中å­� Atomic & Nuclear — Deuteron 原å­�與核å­� - 氘核 Atomic & Nuclear — Triton 原å­�與核å­� - æ°šæ ¸ Atomic & Nuclear — Helion 原å­�與核å­� - æ°¦-3 æ ¸ Atomic & Nuclear — Alpha particle 原å­�與核å­� - α ç²’å­� Atomic & Nuclear — Atomic units 原å­�與核å­� - 原å­�å–®ä½� Atomic & Nuclear — Energy conversion relationships 原å­�與核å­� - 能é‡�轉æ�›é—œä¿‚ Atomic & Nuclear — X-ray units 原å­�與核å­� - X å°„ç·šå–®ä½� Atomic & Nuclear — Magnetic shielding corrections 原å­�與核å­� - ç£�å±�蔽修正 Masses 質é‡� Lifetimes 壽命 Molar Masses 莫耳質é‡� Electronegativity 電負度 Ionization Energy 游離能 Nominal Constants (IAU 2015) å��義常數(IAU 2015) Current Best Estimates (IAU NSFA 2026-04) ç›®å‰�最佳估計值(IAU NSFA 2026-04) characteristic impedance of vacuum (Zâ‚€) 真空特性阻抗(Z₀) reduced Planck constant (â„�) 約化普朗克常數(â„�) vacuum electric permittivity (ϵ₀) 真空電容率(ϵ₀) Newtonian constant of gravitation (G) 牛頓è�¬æœ‰å¼•力常數(G) vacuum magnetic permeability (μ₀) 真空ç£�導率(μ₀) Planck constant (h) 普朗克常數(h) speed of light in vacuum (c) 真空中的光速(c) standard acceleration of gravity (gâ‚™) 標準é‡�力加速度(gₙ) Newtonian constant of gravitation over h-bar c 牛頓é‡�力常數除以 â„�c Planck length 普朗克長度 Planck constant in eV/Hz (h) 普朗克常數(以 eV/Hz)(h) Planck mass 普朗克質é‡� Planck mass energy equivalent in GeV 普朗克質é‡�能é‡�ç•¶é‡�(以 GeV) Planck temperature 普朗克溫度 Planck time 普朗克時間 reduced Planck constant in eV·s (â„�) 約化普朗克常數(以 eV·s)(â„�) reduced Planck constant times c in MeV·fm 約化普朗克常數乘以 c(以 MeV·fm) Bohr magneton 波耳ç£�å­� conductance quantum (Gâ‚€) 電導é‡�å­�(G₀) Coulomb constant (kâ‚‘) 庫侖常數(kₑ) elementary charge (e) 基本電è�·ï¼ˆe) elementary charge over h-bar 基本電è�·é™¤ä»¥ â„� conventional value of Josephson constant 約定值: 約瑟夫森常數 Josephson constant 約瑟夫森常數 conventional value of ampere-90 約定值: ampere-90 conventional value of coulomb-90 約定值: coulomb-90 conventional value of farad-90 約定值: farad-90 conventional value of henry-90 約定值: henry-90 conventional value of ohm-90 約定值: ohm-90 conventional value of volt-90 約定值: volt-90 conventional value of watt-90 約定值: watt-90 magnetic flux quantum (Φ₀) ç£�通é‡�å­�(Φ₀) nuclear magneton æ ¸ç£�å­� inverse of conductance quantum 電導é‡�å­�的倒數 conventional value of von Klitzing constant 約定值: 馮克利é�’常數 von Klitzing constant 馮克利é�’常數 atomic unit of magnetic dipole moment 原å­�å–®ä½�: ç£�å�¶æ¥µçŸ© atomic unit of magnetic flux density 原å­�å–®ä½�: ç£�通密度 Bohr magneton in eV/T 波耳ç£�å­�(以 eV/T) Bohr magneton in Hz/T 波耳ç£�å­�(以 Hz/T) Bohr magneton in inverse meter per tesla 波耳ç£�å­�(以æ¯�特斯拉å��公尺 Bohr magneton in K/T 波耳ç£�å­�(以 K/T) nuclear magneton in eV/T æ ¸ç£�å­�(以 eV/T) nuclear magneton in inverse meter per tesla æ ¸ç£�å­�(以æ¯�特斯拉å��公尺 nuclear magneton in K/T æ ¸ç£�å­�(以 K/T) nuclear magneton in MHz/T æ ¸ç£�å­�(以 MHz/T) Bohr radius (aâ‚€) 波耳å�Šå¾‘(a₀) fine-structure constant (α) 精細çµ�構常數(α) Hartree energy (Eâ‚•) 哈特里能é‡�(Eₕ) Hartree energy in eV 哈特里能é‡�(以 eV) quantum of circulation ç’°æµ�é‡�å­� quantum of circulation times 2 ç’°æµ�é‡�å­�乘以 2 Rydberg constant (R∞) 芮得æŸ�常數(R∞) atomic mass unit-hartree relationship 原å­�質é‡�å–®ä½�-hartree 關係 atomic mass unit-hertz relationship 原å­�質é‡�å–®ä½�-赫茲 關係 atomic mass unit-inverse meter relationship 原å­�質é‡�å–®ä½�-å��公尺 關係 atomic mass unit-joule relationship 原å­�質é‡�å–®ä½�-焦耳 關係 atomic mass unit-kelvin relationship 原å­�質é‡�å–®ä½�-克耳文 關係 atomic mass unit-kilogram relationship 原å­�質é‡�å–®ä½�-公斤 關係 atomic unit of 1st hyperpolarizability 第一超極化率的原å­�å–®ä½� atomic unit of 2nd hyperpolarizability 第二超極化率的原å­�å–®ä½� atomic unit of charge (e) é›»è�·çš„原å­�å–®ä½�(e) atomic unit of charge density 原å­�å–®ä½�: é›»è�·å¯†åº¦ atomic unit of current 原å­�å–®ä½�: é›»æµ� atomic unit of electric dipole moment 原å­�å–®ä½�: é›»å�¶æ¥µçŸ© atomic unit of electric field 原å­�å–®ä½�: 電場 atomic unit of electric field gradient 原å­�å–®ä½�: 電場梯度 atomic unit of electric polarizability 原å­�å–®ä½�: 電極化率 atomic unit of electric potential 原å­�å–®ä½�: é›»ä½� atomic unit of electric quadrupole moment 原å­�å–®ä½�: 電四極矩 atomic unit of action 原å­�å–®ä½�: 作用é‡� atomic unit of energy 原å­�å–®ä½�: 能é‡� atomic unit of force 原å­�å–®ä½�: 力 atomic unit of length 原å­�å–®ä½�: 長度 hertz-atomic mass unit relationship 赫茲-原å­�質é‡�å–®ä½� 關係 hertz-electron volt relationship 赫茲-é›»å­� volt 關係 hertz-hartree relationship 赫茲-hartree 關係 hertz-inverse meter relationship 赫茲-å��公尺 關係 hertz-joule relationship 赫茲-焦耳 關係 hertz-kelvin relationship 赫茲-克耳文 關係 hertz-kilogram relationship 赫茲-公斤 關係 hyperfine transition frequency of Cs-133 Cs-133 的超精細èº�é�·é »çއ inverse fine-structure constant (αâ�»Â¹) 精細çµ�構常數倒數(αâ�»Â¹ï¼‰ inverse meter-atomic mass unit relationship å��公尺-原å­�質é‡�å–®ä½� 關係 inverse meter-electron volt relationship å��公尺-é›»å­� volt 關係 inverse meter-hartree relationship å��公尺-hartree 關係 inverse meter-hertz relationship å��公尺-赫茲 關係 inverse meter-joule relationship å��公尺-焦耳 關係 inverse meter-kelvin relationship å��公尺-克耳文 關係 inverse meter-kilogram relationship å��公尺-公斤 關係 joule-atomic mass unit relationship 焦耳-原å­�質é‡�å–®ä½� 關係 joule-electron volt relationship 焦耳-é›»å­� volt 關係 joule-hertz relationship 焦耳-赫茲 關係 joule-hartree relationship 焦耳-hartree 關係 joule-inverse meter relationship 焦耳-å��公尺 關係 joule-kelvin relationship 焦耳-克耳文 關係 joule-kilogram relationship 焦耳-公斤 關係 kelvin-atomic mass unit relationship 克耳文-原å­�質é‡�å–®ä½� 關係 kelvin-electron volt relationship 克耳文-é›»å­� volt 關係 kelvin-hertz relationship 克耳文-赫茲 關係 kelvin-hartree relationship 克耳文-hartree 關係 kelvin-inverse meter relationship 克耳文-å��公尺 關係 kelvin-joule relationship 克耳文-焦耳 關係 kelvin-kilogram relationship 克耳文-公斤 關係 kilogram-atomic mass unit relationship 公斤-原å­�質é‡�å–®ä½� 關係 kilogram-electron volt relationship 公斤-é›»å­� volt 關係 kilogram-hertz relationship 公斤-赫茲 關係 kilogram-hartree relationship 公斤-hartree 關係 kilogram-inverse meter relationship 公斤-å��公尺 關係 kilogram-joule relationship 公斤-焦耳 關係 kilogram-kelvin relationship 公斤-克耳文 關係 lattice parameter of silicon (a) 矽晶格å�ƒæ•¸ï¼ˆa) luminous efficacy 發光效能 natural unit of energy 自然單ä½�: 能é‡� natural unit of energy in MeV 自然單ä½�: 能é‡�(以 MeV) natural unit of action (â„�) 自然單ä½�: 作用é‡�(â„�) natural unit of action in eV·s 自然單ä½�: 作用é‡�(以 eV·s) natural unit of length 自然單ä½�: 長度 natural unit of mass 自然單ä½�: mass natural unit of momentum 自然單ä½�: å‹•é‡� natural unit of momentum in MeV/c 自然單ä½�: å‹•é‡�(以 MeV)/c natural unit of time 自然單ä½�: 時間 natural unit of velocity 自然單ä½�: 速度 Rydberg constant times c in Hz 芮得æŸ�常數乘以 c(以 Hz) Rydberg constant times hc in eV 芮得æŸ�常數乘以 hc(以 eV) Rydberg constant times hc in J 芮得æŸ�常數乘以 hc(以 J) Fermi coupling constant 費米耦å�ˆå¸¸æ•¸ weak mixing angle 弱混å�ˆè§’ W to Z mass ratio W 與 Z 的質é‡�比 Thomson cross section (σₑ) Thomson 截é�¢ï¼ˆÏƒâ‚‘) electron mass (mâ‚‘) é›»å­� mass(mₑ) electron mass in u é›»å­� mass(以 u) electron mass energy equivalent (mₑ·c²) é›»å­� 質é‡�能é‡�ç•¶é‡�(mₑ·c²) electron mass energy equivalent in MeV é›»å­� 質é‡�能é‡�ç•¶é‡�(以 MeV) reduced Compton wavelength reduced 康普頓波長 classical electron radius (râ‚‘) classical é›»å­� å�Šå¾‘(rₑ) electron charge to mass quotient é›»å­� é›»è�·è³ªé‡�商 electron-deuteron magnetic moment ratio é›»å­�-氘核 ç£�矩 ratio electron-deuteron mass ratio é›»å­�-氘核 質é‡�比 electron g factor (gâ‚‘) é›»å­� g å› å­�(gₑ) electron gyromagnetic ratio (γₑ) é›»å­� æ—‹ç£�比(γₑ) electron gyromagnetic ratio in MHz/T é›»å­� æ—‹ç£�比(以 MHz/T) electron-helion mass ratio é›»å­�-æ°¦-3 æ ¸ 質é‡�比 electron magnetic moment (μₑ) é›»å­� ç£�矩(μₑ) electron magnetic moment anomaly (aâ‚‘) é›»å­� ç£�矩異常(aₑ) electron magnetic moment to Bohr magneton ratio é›»å­� ç£�矩å°�波耳ç£�å­� ratio electron magnetic moment to nuclear magneton ratio é›»å­� ç£�矩å°�æ ¸ç£�å­� ratio electron molar mass (Mâ‚‘) é›»å­� 莫耳質é‡�(Mₑ) electron-muon magnetic moment ratio é›»å­�-ç·²å­� ç£�矩 ratio electron-muon mass ratio é›»å­�-ç·²å­� 質é‡�比 electron-neutron magnetic moment ratio é›»å­�-中å­� ç£�矩 ratio electron-neutron mass ratio é›»å­�-中å­� 質é‡�比 electron-proton magnetic moment ratio é›»å­�-質å­� ç£�矩 ratio electron-proton mass ratio é›»å­�-質å­� 質é‡�比 electron relative atomic mass (Ar(e)) é›»å­� 相å°�原å­�質é‡�(Ar(e)) electron-tau mass ratio é›»å­�-é™¶å­� 質é‡�比 electron to alpha particle mass ratio é›»å­�å°�α ç²’å­� 質é‡�比 electron to shielded helion magnetic moment ratio é›»å­�與å±�蔽氦-3 æ ¸ç£�矩之比 electron to shielded proton magnetic moment ratio é›»å­�與å±�蔽質å­�ç£�矩之比 electron-triton mass ratio é›»å­�-æ°šæ ¸ 質é‡�比 electron volt-atomic mass unit relationship é›»å­�ä¼�特-原å­�質é‡�å–®ä½�關係 electron volt-hartree relationship é›»å­�ä¼�特-哈特里關係 electron volt-hertz relationship é›»å­�ä¼�特-赫茲關係 electron volt-inverse meter relationship é›»å­�ä¼�特-å��公尺關係 electron volt-joule relationship é›»å­�ä¼�特-焦耳關係 electron volt-kelvin relationship é›»å­�ä¼�特-克耳文關係 electron volt-kilogram relationship é›»å­�ä¼�特-公斤關係 hartree-atomic mass unit relationship 哈特里-原å­�質é‡�å–®ä½�關係 hartree-electron volt relationship 哈特里-é›»å­�ä¼�特關係 muon Compton wavelength ç·²å­� 康普頓波長 muon-electron mass ratio ç·²å­�-é›»å­� 質é‡�比 muon g factor ç·²å­� g å› å­� muon magnetic moment ç·²å­� ç£�矩 muon magnetic moment anomaly ç·²å­� ç£�矩異常 muon magnetic moment to Bohr magneton ratio ç·²å­� ç£�矩å°�波耳ç£�å­� ratio muon magnetic moment to nuclear magneton ratio ç·²å­� ç£�矩å°�æ ¸ç£�å­� ratio muon mass ç·²å­� mass muon mass energy equivalent ç·²å­� 質é‡�能é‡�ç•¶é‡� muon mass energy equivalent in MeV ç·²å­� 質é‡�能é‡�ç•¶é‡�(以 MeV) muon mass in u ç·²å­� mass(以 u) muon molar mass ç·²å­� 莫耳質é‡� muon-neutron mass ratio ç·²å­�-中å­� 質é‡�比 muon-proton magnetic moment ratio ç·²å­�-質å­� ç£�矩 ratio muon-proton mass ratio ç·²å­�-質å­� 質é‡�比 muon-tau mass ratio ç·²å­�-é™¶å­� 質é‡�比 reduced muon Compton wavelength reduced ç·²å­� 康普頓波長 reduced tau Compton wavelength reduced é™¶å­� 康普頓波長 tau Compton wavelength é™¶å­� 康普頓波長 tau-electron mass ratio é™¶å­�-é›»å­� 質é‡�比 tau mass é™¶å­� mass tau mass energy equivalent é™¶å­� 質é‡�能é‡�ç•¶é‡� tau mass in u é™¶å­� mass(以 u) tau molar mass é™¶å­� 莫耳質é‡� tau-muon mass ratio é™¶å­�-ç·²å­� 質é‡�比 tau-neutron mass ratio é™¶å­�-中å­� 質é‡�比 tau-proton mass ratio é™¶å­�-質å­� 質é‡�比 proton charge to mass quotient 質å­� é›»è�·è³ªé‡�商 proton Compton wavelength 質å­� 康普頓波長 proton-electron mass ratio 質å­�-é›»å­� 質é‡�比 proton g factor (gₚ) 質å­� g å› å­�(gₚ) proton gyromagnetic ratio (γₚ) 質å­� æ—‹ç£�比(γₚ) proton gyromagnetic ratio in MHz/T 質å­� æ—‹ç£�比(以 MHz/T) proton magnetic moment (μₚ) 質å­� ç£�矩(μₚ) proton magnetic moment to Bohr magneton ratio 質å­� ç£�矩å°�波耳ç£�å­� ratio proton magnetic moment to nuclear magneton ratio 質å­� ç£�矩å°�æ ¸ç£�å­� ratio proton magnetic shielding correction 質å­� magnetic å±�蔽修正 proton mass (mₚ) 質å­� mass(mₚ) proton mass energy equivalent 質å­� 質é‡�能é‡�ç•¶é‡� proton mass energy equivalent in MeV 質å­� 質é‡�能é‡�ç•¶é‡�(以 MeV) proton mass in u 質å­� mass(以 u) proton molar mass (Mₚ) 質å­� 莫耳質é‡�(Mₚ) proton-muon mass ratio 質å­�-ç·²å­� 質é‡�比 proton-neutron magnetic moment ratio 質å­�-中å­� ç£�矩 ratio proton-neutron mass ratio 質å­�-中å­� 質é‡�比 proton relative atomic mass (Ar(p)) 質å­� 相å°�原å­�質é‡�(Ar(p)) proton rms charge radius 質å­� å�‡æ–¹æ ¹é›»è�·å�Šå¾‘ proton-tau mass ratio 質å­�-é™¶å­� 質é‡�比 reduced proton Compton wavelength reduced 質å­� 康普頓波長 shielded proton gyromagnetic ratio å±�蔽 質å­� æ—‹ç£�比 shielded proton gyromagnetic ratio in MHz/T å±�蔽 質å­� æ—‹ç£�比(以 MHz/T) shielded proton magnetic moment å±�蔽 質å­� ç£�矩 shielded proton magnetic moment to Bohr magneton ratio å±�蔽 質å­� ç£�矩å°�波耳ç£�å­� ratio shielded proton magnetic moment to nuclear magneton ratio å±�蔽 質å­� ç£�矩å°�æ ¸ç£�å­� ratio neutron Compton wavelength 中å­� 康普頓波長 neutron-electron magnetic moment ratio 中å­�-é›»å­� ç£�矩 ratio neutron-electron mass ratio 中å­�-é›»å­� 質é‡�比 neutron g factor (gâ‚™) 中å­� g å› å­�(gₙ) neutron gyromagnetic ratio (γₙ) 中å­� æ—‹ç£�比(γₙ) neutron gyromagnetic ratio in MHz/T 中å­� æ—‹ç£�比(以 MHz/T) neutron magnetic moment (μₙ) 中å­� ç£�矩(μₙ) neutron magnetic moment to Bohr magneton ratio 中å­� ç£�矩å°�波耳ç£�å­� ratio neutron magnetic moment to nuclear magneton ratio 中å­� ç£�矩å°�æ ¸ç£�å­� ratio neutron mass (mâ‚™) 中å­� mass(mₙ) neutron mass energy equivalent 中å­� 質é‡�能é‡�ç•¶é‡� neutron mass energy equivalent in MeV 中å­� 質é‡�能é‡�ç•¶é‡�(以 MeV) neutron mass in u 中å­� mass(以 u) neutron molar mass (Mâ‚™) 中å­� 莫耳質é‡�(Mₙ) neutron-muon mass ratio 中å­�-ç·²å­� 質é‡�比 neutron-proton magnetic moment ratio 中å­�-質å­� ç£�矩 ratio neutron-proton mass difference 中å­�-質å­� 質é‡�å·® neutron-proton mass difference energy equivalent 中å­�-質å­�質é‡�差的能é‡�ç•¶é‡� neutron-proton mass difference energy equivalent in MeV 中å­�-質å­�質é‡�差的能é‡�ç•¶é‡�(以 MeV) neutron-proton mass difference in u 中å­�-質å­� 質é‡�差(以 u) neutron-proton mass ratio 中å­�-質å­� 質é‡�比 neutron relative atomic mass (Ar(n)) 中å­� 相å°�原å­�質é‡�(Ar(n)) neutron-tau mass ratio 中å­�-é™¶å­� 質é‡�比 neutron to shielded proton magnetic moment ratio 中å­�å°�å±�蔽 質å­� ç£�矩 ratio reduced neutron Compton wavelength reduced 中å­� 康普頓波長 deuteron-electron magnetic moment ratio 氘核-é›»å­� ç£�矩 ratio deuteron-electron mass ratio 氘核-é›»å­� 質é‡�比 deuteron g factor 氘核 g å› å­� deuteron magnetic moment 氘核 ç£�矩 deuteron magnetic moment to Bohr magneton ratio 氘核 ç£�矩å°�波耳ç£�å­� ratio deuteron magnetic moment to nuclear magneton ratio 氘核 ç£�矩å°�æ ¸ç£�å­� ratio deuteron mass 氘核 mass deuteron mass energy equivalent 氘核 質é‡�能é‡�ç•¶é‡� deuteron mass energy equivalent in MeV 氘核 質é‡�能é‡�ç•¶é‡�(以 MeV) deuteron mass in u 氘核 mass(以 u) deuteron molar mass 氘核 莫耳質é‡� deuteron-neutron magnetic moment ratio 氘核-中å­� ç£�矩 ratio deuteron-proton magnetic moment ratio 氘核-質å­� ç£�矩 ratio deuteron-proton mass ratio 氘核-質å­� 質é‡�比 deuteron relative atomic mass (Ar(d)) 氘核 相å°�原å­�質é‡�(Ar(d)) deuteron rms charge radius 氘核 å�‡æ–¹æ ¹é›»è�·å�Šå¾‘ triton-electron mass ratio æ°šæ ¸-é›»å­� 質é‡�比 triton g factor (gₜ) æ°šæ ¸ g å› å­�(gₜ) triton magnetic moment (μₜ) æ°šæ ¸ ç£�矩(μₜ) triton magnetic moment to Bohr magneton ratio æ°šæ ¸ ç£�矩å°�波耳ç£�å­� ratio triton magnetic moment to nuclear magneton ratio æ°šæ ¸ ç£�矩å°�æ ¸ç£�å­� ratio triton mass (mₜ) æ°šæ ¸ mass(mₜ) triton mass energy equivalent æ°šæ ¸ 質é‡�能é‡�ç•¶é‡� triton mass energy equivalent in MeV æ°šæ ¸ 質é‡�能é‡�ç•¶é‡�(以 MeV) triton mass in u æ°šæ ¸ mass(以 u) triton molar mass (Mₜ) æ°šæ ¸ 莫耳質é‡�(Mₜ) triton-proton mass ratio æ°šæ ¸-質å­� 質é‡�比 triton relative atomic mass (Ar(t)) æ°šæ ¸ 相å°�原å­�質é‡�(Ar(t)) triton to proton magnetic moment ratio æ°šæ ¸å°�質å­� ç£�矩 ratio helion-electron mass ratio æ°¦-3 æ ¸-é›»å­� 質é‡�比 helion g factor (gâ‚•) æ°¦-3 æ ¸ g å› å­�(gₕ) helion magnetic moment (μₕ) æ°¦-3 æ ¸ ç£�矩(μₕ) helion magnetic moment to Bohr magneton ratio æ°¦-3 æ ¸ ç£�矩å°�波耳ç£�å­� ratio helion magnetic moment to nuclear magneton ratio æ°¦-3 æ ¸ ç£�矩å°�æ ¸ç£�å­� ratio helion mass (mâ‚•) æ°¦-3 æ ¸ mass(mₕ) helion mass energy equivalent æ°¦-3 æ ¸ 質é‡�能é‡�ç•¶é‡� helion mass energy equivalent in MeV æ°¦-3 æ ¸ 質é‡�能é‡�ç•¶é‡�(以 MeV) helion mass in u æ°¦-3 æ ¸ mass(以 u) helion molar mass (Mâ‚•) æ°¦-3 æ ¸ 莫耳質é‡�(Mₕ) helion-proton mass ratio æ°¦-3 æ ¸-質å­� 質é‡�比 helion relative atomic mass (Ar(h)) æ°¦-3 æ ¸ 相å°�原å­�質é‡�(Ar(h)) helion shielding shift æ°¦-3 æ ¸ å±�蔽ä½�ç§» shielded helion gyromagnetic ratio å±�蔽 æ°¦-3 æ ¸ æ—‹ç£�比 shielded helion gyromagnetic ratio in MHz/T å±�蔽 æ°¦-3 æ ¸ æ—‹ç£�比(以 MHz/T) shielded helion magnetic moment å±�蔽 æ°¦-3 æ ¸ ç£�矩 shielded helion magnetic moment to Bohr magneton ratio å±�蔽 æ°¦-3 æ ¸ ç£�矩å°�波耳ç£�å­� ratio shielded helion magnetic moment to nuclear magneton ratio å±�蔽 æ°¦-3 æ ¸ ç£�矩å°�æ ¸ç£�å­� ratio shielded helion to proton magnetic moment ratio å±�蔽 æ°¦-3 æ ¸å°�質å­� ç£�矩 ratio shielded helion to shielded proton magnetic moment ratio å±�蔽 æ°¦-3 æ ¸å°�å±�蔽 質å­� ç£�矩 ratio alpha particle mass α ç²’å­� mass alpha particle mass in u α ç²’å­� mass(以 u) alpha particle mass energy equivalent α ç²’å­� 質é‡�能é‡�ç•¶é‡� alpha particle mass energy equivalent in MeV α ç²’å­� 質é‡�能é‡�ç•¶é‡�(以 MeV) alpha particle-electron mass ratio α ç²’å­�-é›»å­� 質é‡�比 alpha particle-proton mass ratio α ç²’å­�-質å­� 質é‡�比 alpha particle rms charge radius α ç²’å­� å�‡æ–¹æ ¹é›»è�·å�Šå¾‘ alpha particle molar mass α ç²’å­� 莫耳質é‡� alpha particle relative atomic mass (Ar(α)) α ç²’å­� 相å°�原å­�質é‡�(Ar(α)) atomic mass constant (mᵤ) atomic mass constant(mᵤ) Avogadro constant 亞佛加厥常數 Boltzmann constant (k) 波茲曼常數(k) Boltzmann constant in eV/K 波茲曼常數(以 eV/K) Boltzmann constant in Hz/K 波茲曼常數(以 Hz)/K Boltzmann constant in inverse meter per kelvin 波茲曼常數(以å��公尺æ¯�克耳文 electron volt (eV) é›»å­� volt(eV) Faraday constant (F) 法拉第常數(F) first radiation constant (câ‚�) 第一輻射常數(câ‚�) first radiation constant for spectral radiance 光譜輻射亮度第一輻射常數 molar gas constant (R) 莫耳氣體常數(R) Loschmidt constant (nâ‚€, 273.15 K, 100 kPa) 洛施密特常數(nâ‚€, 273.15 K, 100 kPa) Loschmidt constant (nâ‚€, 273.15 K, 101.325 kPa) 洛施密特常數(nâ‚€, 273.15 K, 101.325 kPa) molar Planck constant 莫耳普朗克常數 second radiation constant (câ‚‚) 第二輻射常數(c₂) Stefan-Boltzmann constant (σ) å�²è’‚芬-波茲曼常數(σ) lattice spacing of ideal Si (dâ‚‚â‚‚â‚€) ç�†æƒ³çŸ½æ™¶æ ¼é–“è·�(d₂₂₀) atomic mass constant energy equivalent 原å­�質é‡�常數能é‡�ç•¶é‡� atomic mass constant energy equivalent in MeV 原å­�質é‡�常數能é‡�ç•¶é‡�(以 MeV) atomic mass unit-electron volt relationship 原å­�質é‡�å–®ä½�-é›»å­�ä¼�特關係 molar mass constant (Mᵤ) 莫耳質é‡�常數(Mᵤ) molar mass of carbon-12 碳-12 的莫耳質é‡� molar volume of ideal gas (273.15 K, 100 kPa) ç�†æƒ³æ°£é«”的莫耳體ç©�(273.15 K, 100 kPa) molar volume of ideal gas (273.15 K, 101.325 kPa) ç�†æƒ³æ°£é«”的莫耳體ç©�(273.15 K, 101.325 kPa) molar volume of silicon 矽的莫耳體ç©� Sackur-Tetrode constant (1 K, 100 kPa) 薩克爾-特特羅德常數(1 K, 100 kPa) Sackur-Tetrode constant (1 K, 101.325 kPa) 薩克爾-特特羅德常數(1 K, 101.325 kPa) Wien frequency displacement law constant ç¶­æ�©é »çއä½�移定律常數 Wien wavelength displacement law constant ç¶­æ�©æ³¢é•·ä½�移定律常數 standard atmosphere (atm) 標準大氣壓(atm) standard-state pressure (p°) 標準態壓力(p°) Angstrom star (Ã…*) 埃星(Å*) Copper x unit 銅 x å–®ä½� Molybdenum x unit 鉬 x å–®ä½� atomic unit of magnetizability 原å­�å–®ä½�: ç£�化率 atomic unit of mass (mâ‚‘) 原å­�å–®ä½�: mass(mₑ) atomic unit of momentum 原å­�å–®ä½�: å‹•é‡� atomic unit of permittivity 原å­�å–®ä½�: 電容率 atomic unit of time 原å­�å–®ä½�: 時間 atomic unit of velocity 原å­�å–®ä½�: 速度 hartree-hertz relationship hartree-赫茲 關係 hartree-inverse meter relationship hartree-å��公尺 關係 hartree-joule relationship hartree-焦耳 關係 hartree-kelvin relationship hartree-克耳文 關係 hartree-kilogram relationship hartree-公斤 關係 shielding difference of d and p in HD HD 中 d 與 p çš„å±�蔽差 shielding difference of t and p in HT HT 中 t 與 p çš„å±�蔽差 pi (Ï€) 圓周率 (Ï€) Euler's number (e) æ­�拉數(e) golden ratio (φ) 黃金比例(φ) Euler-Mascheroni constant (γ) æ­�拉-馬斯刻若尼常數(γ) nominal solar radius å��義太陽 å�Šå¾‘ nominal solar total irradiance å��義太陽 總輻照度 nominal solar luminosity å��義太陽 光度 nominal solar effective temperature å��義太陽 有效溫度 nominal solar mass parameter å��義太陽 質é‡�å�ƒæ•¸ nominal terrestrial equatorial radius å��義地ç�ƒ 赤é�“ å�Šå¾‘ nominal terrestrial polar radius å��義地ç�ƒ 極 å�Šå¾‘ nominal terrestrial mass parameter å��義地ç�ƒ 質é‡�å�ƒæ•¸ nominal jovian equatorial radius å��義木星 赤é�“ å�Šå¾‘ nominal jovian polar radius å��義木星 極 å�Šå¾‘ nominal jovian mass parameter å��義木星 質é‡�å�ƒæ•¸ average value of one minus the rate of TCG relative to TCB 一減去 TCG 相å°�æ–¼ TCB 速率的平å�‡å€¼ solar mass parameter (TCB-compatible) 太陽質é‡�å�ƒæ•¸ï¼ˆTCB 相容) solar mass parameter (TDB-compatible) 太陽質é‡�å�ƒæ•¸ï¼ˆTDB 相容) equatorial radius of the Earth (TT-compatible) 地ç�ƒèµ¤é�“å�Šå¾‘(TT 相容) dynamical form factor of the Earth 地ç�ƒå‹•力學形狀因å­� time rate of change in the dynamical form factor of the Earth 地ç�ƒå‹•力學形狀因å­�的時間變化率 geocentric gravitational constant (TCB-compatible) 地心引力常數(TCB-相容) geocentric gravitational constant (TT-compatible) 地心引力常數(TT-相容) geocentric gravitational constant (TDB-compatible) 地心引力常數(TDB-相容) potential of the geoid 大地水準é�¢çš„ä½�å‹¢ nominal mean angular velocity of the Earth (TT-compatible) 地ç�ƒå��義平å�‡è§’速度(TT 相容) ratio mass of the Moon to the Earth 月ç�ƒèˆ‡åœ°ç�ƒçš„質é‡�比 ratio of the mass of the Sun to Mercury 太陽與水星的質é‡�比 ratio of the mass of the Sun to Venus 太陽與金星的質é‡�比 ratio of the mass of the Sun to Mars 太陽與ç�«æ˜Ÿçš„質é‡�比 ratio of the mass of the Sun to Jupiter 太陽與木星的質é‡�比 ratio of the mass of the Sun to Saturn 太陽與土星的質é‡�比 ratio of the mass of the Sun to Uranus 太陽與天王星的質é‡�比 ratio of the mass of the Sun to Neptune 太陽與海王星的質é‡�比 ratio of the mass of the Sun to (134340) Pluto 太陽與(134340)冥王星的質é‡�比 ratio of the mass of the Sun to (136199) Eris 太陽與(136199)鬩神星的質é‡�比 ratio of the mass of (1) Ceres to the Sun (1)穀神星與太陽的質é‡�比 ratio of the mass of (2) Pallas to the Sun (2)智神星與太陽的質é‡�比 ratio of the mass of (4) Vesta to the Sun (4)ç�¶ç¥žæ˜Ÿèˆ‡å¤ªé™½çš„質é‡�比 mean obliquity of the ecliptic at J2000.0 J2000.0 的黃é�“å¹³å�‡å‚¾è§’ Electromagnetic é›»ç£� Compton wavelength 康普頓波長 Astronomy 天文 ConstantsWidget Domain 領域 Subdomain å­�領域 No match found 沒有符å�ˆçš„çµ�æžœ Name å��稱 Value 值 Unit å–®ä½� Search æ�œå°‹ All 全部 CustomKeypadDialog Custom Keypad 自訂é�µç›¤ Rows: 列數: Columns: 欄數: Copy preset: 複製é �設: Basic 基本 Scientific (wide) 科學(寬) Scientific (narrow) 科學(窄) Apply 套用 Row 列 Column 欄 Label 標籤 Behavior 行為 Text 文字 DiagnosticsDialog App Diagnostics 應用程å¼�診斷 Copy to Clipboard 複製到剪貼簿 Editor Unit å–®ä½� User unit 使用者單ä½� User function 使用者函數 Argument å�ƒæ•¸ Current result:<br/>%1 ç›®å‰�çµ�果:<br/>%1 Selection result:<br/>%1 é�¸å�–çµ�果:<br/>%1 Selection result: n/a é�¸ä¸­çµ�果:N/A Selection result: %1 é�¸ä¸­çµ�果:%1 second ç§’ metre 公尺 kilogram 公斤 mole 莫耳 radian 弧度 steradian ç�ƒé�¢å¼§åº¦ degree Celsius æ”�æ°�度 cubic metre 立方公尺 cubic millimetre 立方毫米 cubic centimetre 立方公分 cubic decimetre 立方分米 cubic kilometre 立方公里 square millimetre 平方毫米 square kilometre 平方公里 square metre 平方公尺 minute 分é�˜ hour å°�時 day æ—¥ astronomical unit 天文單ä½� degree 度 arcminute 角分 arcsecond è§’ç§’ milliarcsecond 毫角秒 microarcsecond 微角秒 hectare 公頃 litre å…¬å�‡ tonne 公噸 Dalton é�“爾頓 electronvolt é›»å­�ä¼�特 Angstrom 埃 atmosphere 大氣壓 atomic mass unit 原å­�質é‡�å–®ä½� British thermal unit 英制熱é‡�å–®ä½� calorie å�¡è·¯é‡Œ carat 克拉 cup æ�¯ cup (Imperial) æ�¯ï¼ˆè‹±åˆ¶ï¼‰ cup (Japanese) æ�¯ï¼ˆæ—¥åˆ¶ï¼‰ cup (US) æ�¯ï¼ˆç¾Žåˆ¶ï¼‰ degree Fahrenheit è�¯æ°�度 fathom 英尋 fluid ounce (Imperial) æ¶²é‡�盎å�¸ï¼ˆè‹±åˆ¶ï¼‰ fluid ounce (US) æ¶²é‡�盎å�¸ï¼ˆç¾Žåˆ¶ï¼‰ fluid dram (Imperial) æ¶²é‡�德拉姆(英制) fluid dram (US) æ¶²é‡�德拉姆(美制) foot 英尺 square foot 平方英尺 cubic foot 立方英尺 gallon (Imperial) 加侖(英制) gallon (US) 加侖(美制) gill (Imperial) å�Šè€³ï¼ˆè‹±åˆ¶ï¼‰ gill (US) å�Šè€³ï¼ˆç¾Žåˆ¶ï¼‰ gradian 百分度 grain 格令 gram 公克 Hartley 哈特è�Š Hartree energy unit 哈特里能é‡�å–®ä½� horsepower 馬力 inch 英寸 square inch 平方英寸 cubic inch 立方英寸 karat é–‹ knot 節 lightminute 光分 lightsecond 光秒 lightyear 光年 long ton 長噸 mile 英里 square mile 平方英里 cubic mile 立方英里 mile per hour 英里æ¯�å°�時 kilometre per hour 公里æ¯�å°�時 nautical mile 海里 ounce 盎å�¸ parsec ç§’å·®è·� pint (Imperial) å“�脫(英制) pint (US) å“�脫(美制) pound 磅 pounds per square inch 磅力æ¯�平方英寸 quart (Imperial) 夸脫(英制) quart (US) 夸脫(美制) oil barrel 油桶 beer barrel (US) 啤酒桶(美制) square yard 平方碼 cubic yard 立方碼 short ton 短噸 tablespoon 湯匙 tablespoon (Australian) 湯匙(澳制) tablespoon (Imperial) 湯匙(英制) tablespoon (US) 湯匙(美制) dessert spoon 甜點匙 teaspoon 茶匙 teaspoon (Imperial) 茶匙(英制) teaspoon (US) 茶匙(美制) turn 圈 revolution 轉 revolution per minute æ¯�分é�˜è½‰æ•¸ week 週 kilowatt hour å�ƒç“¦æ™‚ millimetre of mercury 毫米汞柱 yard 碼 Julian century 儒略世紀 Julian year 儒略年 sidereal year æ�†æ˜Ÿå¹´ tropical year 回歸年 Evaluator invalid expression 無效的表é�”å¼� division by zero 除以零 too time consuming - computation was rejected 計算時間é�Žé•·å·²å�œæ­¢ dimension mismatch - quantities with different dimensions cannot be compared, added, etc. é‡�ç¶±ä¸�符å�ˆ - ä¸�å�Œé‡�綱的數ä¸�能進行比較ã€�相加等 invalid dimension - operation might require dimensionless arguments 無效é‡�ç¶± - æ“�作å�¯èƒ½éœ€è¦�ç„¡é‡�ç¶±å�ƒæ•¸ Computation aborted - encountered numerical instability 計算中止 - é�‡åˆ°æ•¸å€¼ä¸�穩定 invalid dimension - function might require dimensionless arguments 無效é‡�ç¶± - 函數å�¯èƒ½éœ€è¦�ç„¡é‡�ç¶±å�ƒæ•¸ error 錯誤 unit must not be zero å–®ä½�ä¸�能為零 Conversion failed - dimension mismatch 轉æ�›å¤±æ•— - é‡�ç¶±ä¸�符å�ˆ unknown function or variable 未知函數或變數 recursion not supported ä¸�支æŒ�é�žæ­¸ cannot operate on a NaN ä¸�能å°� NaN 進行æ“�作 underflow - tiny result is out of SpeedCrunch's number range 下溢出 - 太å°�çš„çµ�果超出了 SpeedCrunch 的數值範åœ� overflow - huge result is out of SpeedCrunch's number range 上溢出 - 太大的çµ�果超出了 SpeedCrunch 的數值範åœ� overflow - logic result exceeds maximum of 256 bits 上溢出 - é‚�輯çµ�果超出了最大256ä½�çš„é™�制 overflow - integer result exceeds maximum limit for integers 上溢出 - 整數çµ�果超出了整數的最大é™�制 operation is not defined for these arguments æ­¤é�‹ç®—未å°�這些引數定義 wrong number of arguments å�ƒæ•¸æ•¸é‡�錯誤 does not take NaN as an argument NaN ä¸�能作為å�ƒæ•¸ result out of range çµ�果超出範åœ� undefined for argument domain 未定義為å�ƒæ•¸åŸŸ computation too expensive 計算é�Žæ–¼è¤‡é›œ internal error, please report a bug 內部錯誤,請回報錯誤 syntax error 語法錯誤 conversion target must be a unit 轉æ�›ç›®æ¨™å¿…須是單ä½� unknown unit 未知單ä½� %1 is a reserved name, please choose another %1 是一個ä¿�ç•™å��稱,請é�¸å�–å…¶ä»–å��稱 %1 is a global user definition and cannot be overridden in this session. %1 是全域使用者定義,無法在此工作階段中覆寫。 %1 is a variable name, please choose another or delete the variable %1 是一個變數å��,請é�¸å�–å…¶ä»–å��稱或者刪除變數 argument %1 is used more than once å�ƒæ•¸ %1 使用了超é�Žä¸€æ¬¡ %1 is a built-in unit name, please choose another %1 是內建單ä½�å��稱,請é�¸æ“‡å…¶ä»–å��稱 %1 is a user function name, please choose another or delete the function %1 是使用者函數å��,請é�¸å�–å…¶ä»–å��稱或者刪除函數 FunctionRepo max; trials; probability 最大; 試驗數; 概率 trials; probability 試驗數; 概率 hits; trials; probability å�ˆæ ¼æ•¸; 試驗數; 概率 max; total; hits; trials 最大; 總數; å�ˆæ ¼æ•¸; 試驗數 total; hits; trials 總數; å�ˆæ ¼æ•¸; 試驗數 count; total; hits; trials 計數; 總數; å�ˆæ ¼æ•¸; 試驗數 dividend; divisor 被除數; 除數 x; exponent_bits; significand_bits [; exponent_bias] x; 指數ä½�; 有效ä½� [; 指數å��å·®] base; x 基底; x value; modulo 值; 模 base; exponent; modulo 底數; 指數; 模數 events; average_events 事件; å¹³å�‡äº‹ä»¶ average_events å¹³å�‡äº‹ä»¶ x [; precision] x [; 精度] Absolute Value 絕å°�值 Absolute Deviation 絕å°�å��å·® Arc Cosine å��餘弦 Logical AND é‚�輯 AND Area Hyperbolic Cosine å�€åŸŸé›™æ›²é¤˜å¼¦ Area Hyperbolic Sine å�€åŸŸé›™æ›²æ­£å¼¦ Area Hyperbolic Tangent å�€åŸŸé›™æ›²æ­£åˆ‡ Arc Sine å��正弦 Arc Tangent å��正切 Arc Tangent with two Arguments 2 個å�ƒæ•¸çš„å��正切 Average (Arithmetic Mean) å¹³å�‡ (ç®—è¡“å¹³å�‡å€¼) Binomial Cumulative Distribution Function 二項累ç©�分佈函數 Binomial Distribution Mean 二項分佈平å�‡å€¼ Binomial Probability Mass Function 二項概率質é‡�函數 Binomial Distribution Variance 二項分佈方差 Cube Root 立方根 Complex Conjugate 共軛複數 Cosine 餘弦 Hyperbolic Cosine 雙曲餘弦 Cotangent 餘切 Cosecant 餘割 Convert Unix timestamp to Date å°‡ Unix 時間戳轉æ�›ç‚ºæ—¥æœŸ Degrees of Arc 角度 Error Function 誤差函數 Complementary Error Function 互補誤差函數 Exponential 指數 Fractional Part å°�數部分 Extension of Factorials [= (x-1)!] 擴充階乘 [伽馬函數 = (x-1)!] Greatest Common Divisor 最大公約數 Geometric Mean 幾何平å�‡æ•¸ Gradians of arc 梯度 Hypergeometric Cumulative Distribution Function 超幾何累ç©�分佈函數 Hypergeometric Distribution Mean 超幾何分佈平å�‡å€¼ Hypergeometric Probability Mass Function 超幾何概率質é‡�函數 Hypergeometric Distribution Variance 超幾何分佈方差 Integer Quotient 整數商 Integer Part 整數部分 Imaginary Part 虛部 Decode IEEE-754 Binary Value 解碼 IEEE-754 二進ä½�值 Encode IEEE-754 Binary Value 編碼 IEEE-754 二進ä½�值 Decode 16-bit Half-Precision Value 解碼16ä½�å�Šç²¾åº¦å€¼ Encode 16-bit Half-Precision Value 編碼16ä½�å�Šç²¾åº¦å€¼ Decode 32-bit Single-Precision Value 解碼32ä½�單精度值 Encode 32-bit Single-Precision Value 編碼32ä½�單精度值 Decode 64-bit Double-Precision Value 解碼64ä½�雙精度值 Encode 64-bit Double-Precision Value 編碼64ä½�雙精度值 Decode 128-bit Quad-Precision Value 解碼128ä½�四精度值 Encode 128-bit Quad-Precision Value 編碼128ä½�四精度值 Binary Logarithm 以2為底的å°�數 Common Logarithm 一般å°�數 Natural Logarithm 自然å°�數 Logarithm to Arbitrary Base 以給定數字為底的å°�數 Mask to a bit size 指定ä½�元大å°�çš„é�®ç½© Maximum 最大 Median Value (50th Percentile) 中ä½�數 Minimum 最å°� Modulo 模 Euclidean Modulo æ­�幾里得å�–模 Modular Exponentiation 模冪é�‹ç®— Combination (Binomial Coefficient) 組å�ˆï¼ˆäºŒé …å¼�係數) Logical NOT é‚�輯 NOT Permutation (Arrangement) 排列(置æ�›ï¼‰ Convert to Binary Representation 轉æ�›è‡³äºŒé€²ä½� Arithmetic ç®—è¡“ Chemistry 化學 Complex 複數 Combinatorics 組å�ˆæ•¸å­¸ Probability 機率 Statistics 統計 Aggregation 彙總 Random 隨機 Base conversion 基數轉æ�› Number formatting 數字格å¼�化 Integer arithmetic 整數算術 Special functions 特殊函數 Exponential & Logarithmic 指數與å°�數 Angle conversion 角度轉æ�› Trigonometry 三角函數 Bitwise ä½�å…ƒé�‹ç®— Floating point 浮點數 Date & Time 日期與時間 Linear algebra 線性代數 unix_timestamp; x hours offset to GMT Unix 時間戳;x 為相å°� GMT çš„å°�時å��ç§» yyyymmdd.hhmmss; x hours offset to GMT yyyymmdd.hhmmssï¼›x 為相å°� GMT çš„å°�時å��ç§» [digits] [ä½�數] max [; min] 最大值 [; 最å°�值] List Literal 列表常值 Convert to Padded Binary Representation 轉æ�›ç‚ºè£œé›¶äºŒé€²ä½�表示 Round Toward +∞ (Ceiling) æœ�å�‘ +∞ æ�¨å…¥ï¼ˆå¤©èбæ�¿ï¼‰ Cosine plus Imaginary Sine 餘弦加虛數正弦 Convert to Cis Complex Form 轉æ�›ç‚º Cis 複數形å¼� Matrix Column Count 矩陣欄數 Population Correlation Matrix (n) æ¯�體相關矩陣(n) Sample Correlation Matrix (n-1) 樣本相關矩陣(n-1) Count 計數 Population Covariance Matrix (n) æ¯�體共變異數矩陣(n) Sample Covariance Matrix (n-1) 樣本共變異數矩陣(n-1) Cross Product å�‰ç©� Convert Date to Unix timestamp 將日期轉æ�›ç‚º Unix 時間戳 Convert to Decimal Representation 轉æ�›è‡³å��進ä½� Determinant 行列å¼� Convert to Sexagesimal Notation 轉æ�›ç‚ºå…­å��進ä½�記法 Dot Product å…§ç©� Convert to Engineering Notation 轉æ�›ç‚ºå·¥ç¨‹è¨˜æ³• Convert to Exponential Complex Form 轉æ�›ç‚ºæŒ‡æ•¸è¤‡æ•¸å½¢å¼� Round Toward −∞ (Floor) æœ�å�‘ −∞ æ�¨å…¥ï¼ˆåœ°æ�¿ï¼‰ Flatten Matrix 攤平矩陣 Least Common Multiple 最å°�å…¬å€�數 Convert to Hexadecimal Representation 轉æ�›è‡³å��六進ä½� Convert to Padded Hexadecimal Representation 轉æ�›ç‚ºè£œé›¶å��六進ä½�表示 Inverse Matrix å��矩陣 Round to 16-bit Half-Precision Value æ�¨å…¥ç‚º 16 ä½�å…ƒå�Šç²¾ç¢ºåº¦å€¼ Round to 32-bit Single-Precision Value æ�¨å…¥ç‚º 32 ä½�元單精確度值 Round to 64-bit Double-Precision Value æ�¨å…¥ç‚º 64 ä½�元雙精確度值 Round to 128-bit Quad-Precision Value æ�¨å…¥ç‚º 128 ä½�元四å€�精確度值 Residual from 16-bit Half-Precision Rounding 16 ä½�å…ƒå�Šç²¾ç¢ºåº¦æ�¨å…¥æ®˜å·® Residual from 32-bit Single-Precision Rounding 32 ä½�元單精確度æ�¨å…¥æ®˜å·® Residual from 64-bit Double-Precision Rounding 64 ä½�元雙精確度æ�¨å…¥æ®˜å·® Residual from 128-bit Quad-Precision Rounding 128 ä½�元四å€�精確度æ�¨å…¥æ®˜å·® Substance Mass 物質質é‡� Molarity 莫耳濃度 Molar Mass 莫耳質é‡� Median Absolute Deviation 中ä½�數絕å°�å��å·® Mean å¹³å�‡å€¼ Numerical Value of Quantity é‡�的數值 Random Decimal Number 隨機å°�數 Random Integer Number 隨機整數 Convert to Rational Representation 轉æ�›ç‚ºæœ‰ç�†æ•¸è¡¨ç¤º Convert to Octal Representation 轉æ�›è‡³å…«é€²ä½� Convert to Padded Octal Representation 轉æ�›ç‚ºè£œé›¶å…«é€²ä½�表示 Vector or Matrix Norm å�‘é‡�或矩陣範數 Logical OR é‚�輯 OR Population Count (Hamming Weight) ä½�元計數(漢明é‡�é‡�) Phase of Complex Number 複數的相 Poissonian Cumulative Distribution Function 泊æ�¾ç´¯ç©�分佈函數 Poissonian Distribution Mean 泊æ�¾åˆ†ä½ˆå¹³å�‡å€¼ Poissonian Probability Mass Function 泊æ�¾æ¦‚率質é‡�函數 Poissonian Distribution Variance 泊æ�¾åˆ†ä½ˆæ–¹å·® Convert to Phasor Complex Form 轉æ�›ç‚ºç›¸é‡�複數形å¼� Convert to Rectangular Complex Form 轉æ�›ç‚ºçŸ©å½¢è¤‡æ•¸å½¢å¼� Round Half Away from Zero å�Šå€¼é� é›¢é›¶æ�¨å…¥ Round Half Even å�Šå€¼å�¶æ•¸æ�¨å…¥ Nth Root n 次方根 Convert to Scientific Notation 轉æ�›ç‚ºç§‘學記法 Matrix Row Count 矩陣列數 List or Matrix Shape 列表或矩陣形狀 Summation 總和 Population Standard Deviation (n) æ¯�體標準差(n) Sample Standard Deviation (n-1) 樣本標準差(n-1) Round Toward Zero (Truncation) æœ�å�‘é›¶æ�¨å…¥ï¼ˆæˆªæ–·ï¼‰ Matrix Trace 矩陣跡 Transpose Matrix 轉置矩陣 Population Variance (n) æ¯�體變異數(n) Sample Variance (n-1) 樣本變異數(n-1) Product 乘ç©� Radians 弧度 Matrix Rank 矩陣秩 Real Part 實部 Secant 正割 Arithmetic Shift Left 算術左移 Arithmetic Shift Right ç®—è¡“å�³ç§» Signum 符號函數 Sine 正弦 Hyperbolic Sine 雙曲正弦 Square Root 平方根 Sum å’Œ Tangent 正切 Convert to Trigonometric Complex Form 轉æ�›ç‚ºä¸‰è§’複數形å¼� Turns 圈數 Hyperbolic Tangent 雙曲正切 Sign-extend a value å°�一個值進行符號擴展 Logical XOR 互斥或閘 XOR FunctionsWidget Domain 領域 All 全部 Name å��稱 Search æ�œå°‹ No match found 沒有符å�ˆçš„çµ�æžœ Identifier 標識符 HistoryWidget Remove All Calculations Above 移除上方所有計算 Remove This Calculation 移除此計算 Remove All Calculations Below 移除下方所有計算 Keypad Inverse cosine å��餘弦 The last result 最後的çµ�æžœ Inverse sine å��正弦 Inverse tangent å��正切 Evaluate expression 計算表é�”å¼� Division 除法 Multiplication 乘法 Subtraction 減法 Addition 加法 Clear expression 清除表é�”å¼� Cosine 餘弦 Backspace 倒退é�µ Scientific notation 科學記號 Exponential 指數 Factorial 階乘 Natural logarithm 自然å°�數 Left parenthesis 左括號 Nth root n 次方根 Argument separator 引數分隔符號 Square 平方 Common logarithm 常用å°�數 Modulo 模數 Contextual percentage 情境百分比 Power 次方 Right parenthesis å�³æ‹¬è™Ÿ Sine 正弦 Square root 平方根 Tangent 正切 Pi 圓周率 Decimal separator å°�數分隔符 MainWindow Radian 弧度 Degree 角度 Gradian 梯度 Binary 二進ä½� Octal 八進ä½� Hexadecimal å��六進ä½� Sexagesimal å…­å��進ä½� Engineering decimal 工程å��進ä½� Scientific decimal ç§‘å­¸å��進ä½� &Import... 匯入(&I)... &Quit 離開(&Q) Clear E&xpression 清除表é�”å¼�(&X) Clear &History 清除歷å�²(&H) &Copy 複製(&C) &Paste 貼上(&P) &Select Expression é�¸æ“‡è¡¨é�”å¼�(&S) &Constants 常數(&C) &Functions 函數(&F) &History æ­·å�²(&H) &Status Bar 狀態欄(&S) Bitfield ä½�域 Use&r Functions 使用者函數(&R) &Degree 角度(&D) &Radian 徑度(&R) &Gradian 梯度(&G) Re&volution 轉(&V) Auto-Insert a&ns 自動æ�’å…¥ ans(&N) Automatic &Completion 自動完æˆ�(&C) &Built-in Functions 內建函數(&B) Built-in &Variables 內建變數(&V) User &Functions 使用者函數(&F) User Va&riables 使用者變數(&R) Open a Private Tab on Startup 啟動時開啟ç§�人分é � Open and focus a new private tab whenever SpeedCrunch starts. æ¯�次啟動 SpeedCrunch 時開啟新的ç§�人分é �並將焦點移至該分é �。 Syntax &Highlighting å�¥æ³•å��白(&H) Group Digits in &Input 將輸入數字分組(&I) Automatic Input &Adjustments 自動調整輸入(&A) Automatically adjust operators, spacing, brackets, and powers, and restrict input to valid characters. 自動調整é�‹ç®—å­�ã€�é–“è·�ã€�括號與次方,並將輸入é™�制為有效字元。 Group input digits using the selected number format. ä¾�所é�¸çš„æ•¸å­—æ ¼å¼�將輸入數字分組。 &Blinking Cursor 游標閃çˆ�(&B) Blink the cursor in the expression editor. 讓é�‹ç®—å¼�編輯器中的游標閃çˆ�。 &Escape Clears Editor Escape 清空編輯器(&E) Clear the focused expression editor with Escape after dismissing any popup or preview. 關閉所有快顯視窗或é �覽後,按 Escape 清空目å‰�å�–得焦點的é�‹ç®—å¼�編輯器。 Keep Expression After Evaluation 計算後ä¿�ç•™é�‹ç®—å¼� Copy New Results Automatically 自動複製新çµ�æžœ &Comma 逗號(&C) &System Default 系統é �設(&S) &Dot 點(&D) Dot &And Comma 點和逗號(&A) Toward +∞ (&ceil) æœ� +∞ (ceil)(&C) Toward −∞ (&floor) æœ� −∞ (floor)(&F) &Binary 二進ä½�(&B) &Engineering 工程(&E) &Hexadecimal å��六進ä½�(&H) &Octal 八進制(&O) &Scientific ç§‘å­¸(&S) User &Manual 使用者手冊(&M) Issues and &Feedback å•�題與æ„�見回饋(&F) &Donate æ��è´ˆ(&D) &About SpeedCrunch 關於 SpeedCrunch(&A) App Diag&nostics 應用程å¼�診斷(&N) S&plit 分割(&P) Angle &Mode 角度模å¼�(&M) &Complex Form 複數形å¼�(&C) New Tab 新增分é � Constants 常數 Functions 函數 History æ­·å�² User Functions 使用者函數 &Font... å­—åž‹(&F)... &Language... 語言(&L)... &Session 工作階段(&S) &Edit 編輯(&E) &View 檢視(&V) Se&ttings 設定(&T) &Decimal å��進ä½�(&D) &Keypad é�µç›¤(&K) Always on &Top 總在最上層(&T) Disabled å�œç”¨ Small Space å°� Medium Space 中 Large Space 大 &0 Digits &0ä½�數 &15 Digits &15ä½�數 &2 Digits &2ä½�數 &3 Digits &3ä½�數 &50 Digits &50ä½�數 &8 Digits &8ä½�數 &Sexagesimal å…­å��進ä½�(&S) Reset All Settings... é‡�設所有設定... &System 系統(&S) SpeedCrunch &Theme SpeedCrunch 佈景主題(&T) &Classic ç¶“å…¸(&C) &Modern ç�¾ä»£(&M) Context Help 內容幫助 &Help 說明(&H) Error 錯誤 Can't read from file %1 無法讀å�–檔案 %1 Import Session 匯入工作階段 Close Session 關閉工作階段 Angle Mode: 角度模å¼�: Notation: 記法: Precision: 精確度: Turn 圈 Revolution 轉 Fixed-point decimal 定點å°�數 Rational 有ç�†æ•¸ Automatic decimal 自動å°�數 Automatic 自動 User &Definitions... 使用者定義(&D)... New &Tab 新增分é �(&T) New &Private Tab 新增ç§�人分é �(&P) Keep ä¿�ç•™ Make Private... 設為ç§�人... New &Window 新增視窗(&W) &Open... 開啟(&O)... &Rename... é‡�新命å��(&R)... Clo&ne... 複製(&N)... &Close Tab 關閉分é �(&C) Reopen Clo&sed Tab é‡�新開啟已關閉的分é �(&S) Open Sessions &Folder 開啟工作階段資料夾(&F) &Undo 復原(&U) &Redo é‡�å�š(&R) Cu&t 剪下(&T) Copy &Last Result 複製上次çµ�æžœ(&L) &Wrap in Parentheses 以括號括ä½�(&W) Full Scr&een Mode 全螢幕模å¼�(&E) &Basic 基本(&B) &Scientific (wide) 科學(寬)(&S) Scientific (narrow) 科學(窄) &Custom... 自訂(&C)... Main &Menu 主é�¸å–®(&M) User &Variables 使用者變數(&V) &Left å�‘å·¦(&L) &Right å�‘å�³(&R) &Up å�‘上(&U) &Down å�‘下(&D) Close Pa&ne 關閉窗格(&N) User &Units 使用者單ä½�(&U) &Turn 圈(&T) If a new expression starts with +, -, *, or /, SpeedCrunch inserts "ans" first. 如果新的表é�”å¼�以 +ã€�-ã€�* 或 / 開頭,SpeedCrunch 會先æ�’å…¥ "ans"。 &Accept with Enter 按 Enter 接å�—(&A) Accept the current autocomplete suggestion with Enter without first selecting it with the arrow keys. 按 Enter é�µæŽ¥å�—ç›®å‰�的自動完æˆ�建議,無須先用方å�‘é�µé�¸å�–。 &Units å–®ä½�(&U) Show Live Result &Preview 顯示å�³æ™‚çµ�æžœé �覽(&P) Save &Window Position on Exit çµ�æ�Ÿæ™‚儲存視窗ä½�ç½®(&W) Hover Highlighting 游標å�œç•™å��白 Group Integer Part Only 僅群組整數部分 Number Format... 數字格å¼�... Notation && Precision... 記法與精確度... After pressing Enter, keep the entered expression selected in the editor. 按下 Enter 後,在編輯器中ä¿�留已輸入表é�”å¼�çš„é�¸å�–狀態。 Never æ°¸ä¸� Always 總是 Only for Single-Line Expressions 僅é™�單列表é�”å¼� Simplify Displayed Expressions 簡化顯示的表é�”å¼� History Size &Limit... æ­·å�²å¤§å°�é™�制(&L)... Remove Trailing &Zeroes 移除尾端零(&Z) Nearest, Half &Away (round) 最接近,å�Šå€¼é� é›¢é›¶ï¼ˆround)(&A) Nearest, Half &Even (roundeven) 最接近,å�Šå€¼å�¶æ•¸ï¼ˆroundeven)(&E) Toward &Zero (trunc) æœ�å�‘零(trunc)(&Z) &Fixed-Point 定點(&F) &Rational 有ç�†æ•¸(&R) &Exponential (m·sâ�»Â¹) 指數(&E)(m·sâ�»Â¹ï¼‰ &Fractional (m/s) 分數(&F)(m/s) &Rectangular (a + bi) 矩形(&R)(a + bi) Exponential (reâ�±á¶¿) 指數(reâ�±á¶¿ï¼‰ Trigonometric (r(cos θ + i·sin θ)) 三角(r(cos θ + i·sin θ)) Phasor (r∠θ) 相é‡�(r∠θ) &Theme... 佈景主題(&T)... Check for &Updates 檢查更新(&U) Source Code 原始碼 &Zoom 縮放(&Z) &Results çµ�æžœ(&R) Unit Notation å–®ä½�記法 Rounding Mode æ�¨å…¥æ¨¡å¼� &Notation 記法(&N) &Imaginary Unit 虛數單ä½�(&I) &Window 視窗(&W) &Editing 編輯(&E) A&utocomplete 自動完æˆ�(&U) Up/Down Arrow History 上/下方å�‘é�µæ­·å�² &Appearance 外觀(&A) &Menus é�¸å–®(&M) &Docks å�œé§�é�¢æ�¿(&D) &Input and Results 輸入與çµ�æžœ(&I) &Disabled å·²å�œç”¨(&D) &Disable å�œç”¨(&D) Close preview 關閉é �覽 Rename... é‡�新命å��... Clone... 複製... Close Tab 關閉分é � New Private Tab 新增ç§�人分é � Open... 開啟... Reopen Closed Tab é‡�新開啟已關閉的分é � Split 分割 Left å�‘å·¦ Right å�‘å�³ Up å�‘上 Down å�‘下 Clear 清空 Delete 刪除 %1 Private session: contents are discarded when closed. Choose Session > Keep to turn it into a regular session. %1 ç§�人工作階段:關閉時會æ�¨æ£„內容。 é�¸æ“‡ã€Œå·¥ä½œéšŽæ®µ > ä¿�ç•™ã€�å�³å�¯å°‡å…¶è½‰ç‚ºä¸€èˆ¬å·¥ä½œéšŽæ®µã€‚ SpeedCrunch - %1 [Private] SpeedCrunch - %1 [ç§�人] Reset All Settings é‡�設所有設定 Reset all settings to their default values? 將所有設定é‡�設為é �設值? This includes appearance, editing, result formats, and window preferences. Your calculations, open sessions, and user definitions will be kept. 這包括外觀ã€�編輯ã€�çµ�果格å¼�與視窗å��好設定。您的計算ã€�已開啟的工作階段å�Šä½¿ç”¨è€…定義都會ä¿�留。 The settings file could not be written. 無法寫入設定檔。 Clear this session's calculations, unfinished expression, variables, functions, and units? 清空此工作階段的計算ã€�未完æˆ�çš„é�‹ç®—å¼�ã€�變數ã€�函數與單ä½�? Global user definitions are kept. 全域使用者定義會ä¿�留。 Make Session Private 將工作階段設為ç§�人 The saved session %1 will be deleted. Its contents will stay open in a private session and will be discarded when that session is closed or SpeedCrunch exits. 已儲存的工作階段 %1 將被刪除。其內容會繼續在ç§�人工作階段中開啟,並在關閉該工作階段或çµ�æ�Ÿ SpeedCrunch 時æ�¨æ£„。 Make Private 設為ç§�人 Could not delete the saved session %1. 無法刪除已儲存的工作階段 %1。 Keep Session ä¿�留工作階段 Could not save the session. It remains private. 無法儲存工作階段。它ä»�為ç§�人工作階段。 Clone Session 複製工作階段 Could not save session file %1. 無法儲存工作階段檔案 %1。 Could not delete session file %1. 無法刪除工作階段檔案 %1。 JSON file (*.json);;Any file (*.*) JSON 檔案 (*.json);;任何檔案 (*.*) Export session as JSON 將工作階段匯出為 JSON The selected file is not valid JSON: %1 所é�¸æª”案ä¸�是有效的 JSON:%1 The selected file is not a SpeedCrunch session JSON file. 所é�¸æª”案ä¸�是 SpeedCrunch 工作階段 JSON 檔案。 This file uses an obsolete SpeedCrunch session format and cannot be imported. 此檔案使用已é�Žæ™‚çš„ SpeedCrunch 工作階段格å¼�,無法匯入。 The selected JSON file is missing the required $schema field. 所é�¸ JSON 檔案缺少必è¦�çš„ $schema 欄ä½�。 The selected JSON file uses an unsupported JSON schema: %1 所é�¸ JSON 檔案使用ä¸�支æ�´çš„ JSON ç¶±è¦�:%1 The selected JSON file is missing the SpeedCrunch session schema identifier ($id). 所é�¸ JSON 檔案缺少 SpeedCrunch 工作階段綱è¦�識別碼 ($id)。 The selected JSON file uses an unsupported SpeedCrunch session format: %1 所é�¸ JSON 檔案使用ä¸�支æ�´çš„ SpeedCrunch 工作階段格å¼�:%1 The selected JSON file is missing the required session name. 所é�¸ JSON 檔案缺少必è¦�的工作階段å��稱。 The selected JSON file has an empty session name. 所é�¸ JSON 檔案的工作階段å��稱是空的。 The selected JSON file has invalid or incomplete SpeedCrunch session data. 所é�¸ JSON 檔案å�«æœ‰ç„¡æ•ˆæˆ–ä¸�完整的 SpeedCrunch 工作階段資料。 Open Sessions Folder 開啟工作階段資料夾 Could not create the sessions folder: %1 無法建立工作階段資料夾:%1 Could not open the sessions folder: %1 無法開啟工作階段資料夾:%1 Editor and Results Font 編輯器與çµ�果字型 Open Session 開啟工作階段 Community 社群 Rename Session é‡�新命å��工作階段 Clear Session 清除工作階段 Delete Session 刪除工作階段 Close Pane 關閉窗格 User Variables 使用者變數 User Units 使用者單ä½� Clear History 清除歷å�²è¨˜éŒ„ Are you sure you want to clear the calculation history? 確定è¦�清除計算歷å�²è¨˜éŒ„嗎? Session name: 工作階段å��稱: A session named %1 already exists. å��為 %1 的工作階段已存在。 Could not create session file %1. 無法建立工作階段檔案 %1。 Could not write session file %1. 無法寫入工作階段檔案 %1。 Are you sure you want to delete this session? 確定è¦�刪除此工作階段嗎? Custom Precision 自訂精確度 Fractional digits: å°�數ä½�數: Theme 佈景主題 Light Themes 淺色佈景主題 Dark Themes 深色佈景主題 Preview é �覽 Colors 色彩 Select color for %1 é�¸å�– %1 的色彩 Import... 匯入... Export... 匯出... Import Theme 匯入佈景主題 Theme file (*.json);;All files (*) 佈景主題檔案 (*.json);;所有檔案 (*) Invalid theme file. 無效的佈景主題檔案。 Can't import theme "%1" because it conflicts with a built-in theme. 無法匯入佈景主題「%1ã€�,因為它與內建佈景主題è¡�çª�。 Can't find a writable theme folder. 找ä¸�到å�¯å¯«å…¥çš„佈景主題資料夾。 Overwrite Theme 覆寫佈景主題 A custom theme named "%1" already exists. Do you want to overwrite it? å��為「%1ã€�的自訂佈景主題已存在。è¦�覆寫它嗎? Can't overwrite theme file %1 無法覆寫佈景主題檔案 %1 Can't copy theme file to %1 無法將佈景主題檔案複製到 %1 Export Theme 匯出佈景主題 Can't export theme as "%1" because it conflicts with a built-in theme. 無法將佈景主題匯出為「%1ã€�,因為它與內建佈景主題è¡�çª�。 Can't write to file %1 無法寫入檔案 %1 Global User Variable 全域使用者變數 Global User Function 全域使用者函數 Global User Unit 全域使用者單ä½� User Definitions 使用者定義 These definitions are global and are loaded into every session. They are immutable for sessions and override same-name definitions from the session editor. Enter one definition per line. 這些定義是全域的,會載入到æ¯�個工作階段中。 它們無法在工作階段中修改,並優先於工作階段編輯器中的å�Œå��定義。 æ¯�行輸入一個定義。 Examples: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] 範例: my_rate=1.25 f(x)=x^2+1 [cm_s]=[centimetre/second] Apply 套用 Validate é©—è­‰ Test Results 測試çµ�æžœ Imported variables: %1 Imported functions: %2 Imported units: %3 Line numbers with errors: %4 已匯入的變數:%1 已匯入的函數:%2 已匯入的單ä½�:%3 有錯誤的行號:%4 none ç„¡ Apply Results 套用çµ�æžœ User definitions saved. 使用者定義已儲存。 History Size Limit æ­·å�²å¤§å°�é™�制 Maximum number of history entries for this session (0 = unlimited): 此工作階段的歷å�²é …目最大數é‡�(0 = ç„¡é™�制): Text file (*.txt);;Any file (*.*) 純文字檔 (*.txt);;所有檔案 (*.*) Could not recalculate from calculation %1: %2 無法從計算 %1 é‡�新計算:%2 History Size Limit Reached å·²é�”æ­·å�²å¤§å°�é™�制 This calculation fills the last available history slot. Future calculations will remove the oldest calculation from history. You can increase the limit from Session > History Size Limit. 此計算佔用了最後一個å�¯ç”¨çš„æ­·å�²ä½�置。之後的計算會從歷å�²ä¸­ç§»é™¤æœ€èˆŠçš„計算。你å�¯ä»¥å¾žã€Œå·¥ä½œéšŽæ®µ > æ­·å�²å¤§å°�é™�制ã€�增加é™�制。 Editing calculation. Press Esc twice to cancel. 正在編輯計算。按 Esc 兩次å�³å�¯å�–消。 Calculation Settings 計算設定 Invalid recalculation start index 無效的é‡�新計算起始索引 System Default 系統é �設 Language 語言 Select the language: é�¸æ“‡èªžè¨€: Custom 自訂 Decimal places: å°�數ä½�數: &Automatic 自動(&A) &Precision 精確度(&P) Plain &text 純文字(&T) Formula &Book å…¬å¼�手冊(&B) &Export 匯出(&E) Export session as HTML 將工作階段匯出為 HTML HTML file (*.html) HTML 檔案 (*.html) Export session as plain text 匯出æˆ�純文字 ManualWindow SpeedCrunch Manual SpeedCrunch 手冊 %1 - SpeedCrunch Manual %1 - SpeedCrunch 手冊 NumberFormatDialog Number Format 數字格å¼� <b>Select the number format for results and input digit grouping.</b><br/><br/>Note: for input numbers, obvious formats are accepted even when they differ from the selected display format.<br/> <b>é�¸æ“‡çµ�果與輸入數字分組所用的數字格å¼�。</b><br/><br/>注æ„�:輸入數字時,å�ªè¦�æ ¼å¼�明確,å�³ä½¿èˆ‡æ‰€é�¸çš„顯示格å¼�ä¸�å�Œä¹ŸæœƒæŽ¥å�—。<br/> QObject Global User Variable 全域使用者變數 Global User Function 全域使用者函數 Global User Unit 全域使用者單ä½� Backspace 倒退é�µ Clear expression 清除表é�”å¼� Evaluate expression 計算表é�”å¼� Insert text æ�’入文字 Automatic decimal 自動å°�數 Fixed-point decimal 定點å°�數 Engineering decimal 工程å°�數 Scientific decimal ç§‘å­¸å°�數 Rational 有ç�†æ•¸ Binary 二進ä½� Octal 八進ä½� Hexadecimal å��六進ä½� Sexagesimal å…­å��進ä½� Update Available 有å�¯ç”¨æ›´æ–° A newer version (%1) is available.<br/><a href="%2">Visit website to download.</a> 有較新版本(%1)å�¯ç”¨ã€‚<br/><a href="%2">å‰�往網站下載。</a> Check for Updates 檢查更新 SpeedCrunch %1 is up to date. SpeedCrunch %1 已是最新版本。 No connectivity. Please check your internet connection and try again. 沒有網路連線。請檢查網際網路連線後å†�試一次。 Could not verify the latest available version. 無法驗證最新å�¯ç”¨ç‰ˆæœ¬ã€‚ ResultDisplay Scroll to bottom æ�²å‹•到底部 Edit Expression 編輯表é�”å¼� Change Settings 變更設定 New Tab 新增分é � &Import... 匯入(&I)... &Export 匯出(&E) Plain &text 純文字(&T) Copy 複製 Selection é�¸å�–範åœ� Select All å…¨é�¸ Expression é�‹ç®—å¼� Result çµ�æžœ Calculation 計算 Calculation as Single Line 單行計算 Remove 移除 This Calculation 此項計算 All Calculations Above 上方所有計算 All Calculations Below 下方所有計算 New Private Tab 新增ç§�人分é � Session 工作階段 Open... 開啟... Clone... 複製... Rename... é‡�新命å��... Keep ä¿�ç•™ Make Private... 設為ç§�人... Clear 清空 Delete 刪除 Close 關閉 Split 分割 Left å�‘å·¦ Right å�‘å�³ Up å�‘上 Down å�‘下 Close Pane 關閉窗格 Main Menu 主é�¸å–® Cancel editing å�–消編輯 Copy result 複製çµ�æžœ Edit expression 編輯表é�”å¼� Change settings 變更設定 Remove calculation 移除計算 ResultSlotsDialog Notation & Precision 記法與精確度 Result Line çµ�果列 Enabled 已啟用 Notation 記法 Decimal Places å°�數ä½�數 Main Line 主列 Extra Line #1 é¡�外列 #1 Extra Line #2 é¡�外列 #2 Extra Line #3 é¡�外列 #3 Extra Line #4 é¡�外列 #4 Auto 自動 UserFunctionListWidget Name å��稱 Value 值 Description æ��è¿° Search æ�œå°‹ No match found 沒有符å�ˆçš„çµ�æžœ Insert æ�’å…¥ Edit 編輯 Delete 刪除 Delete All 全部刪除 UserUnitListWidget Name å��稱 Value 值 Description æ��è¿° Search æ�œå°‹ No match found 沒有符å�ˆçš„çµ�æžœ Insert æ�’å…¥ Edit 編輯 Delete 刪除 Delete All 全部刪除 VariableListWidget Name å��稱 Value 值 Description æ��è¿° Search æ�œå°‹ No match found 沒有符å�ˆçš„çµ�æžœ Insert æ�’å…¥ Edit 編輯 Delete 刪除 Delete All 全部刪除 heldercorreia-speedcrunch-e7ca37f/src/resources/speedcrunch.icns000066400000000000000000003031741526573132500253270ustar00rootroot00000000000000icns†|ic13¹‰PNG  IHDR\r¨fsRGB®Îé8eXIfMM*‡i  D"8s@IDATxì½ °eÇyö¿{ß>o™³c`b™0X@$APHB¤D‰”èØŽbU¥¢8ŽË®R\YªRªT*‹$')'å¸Êr,¥\ eRŽ,¢ŠûB¬³a³Ï¼ý½yûÍ÷}ÿß}ι÷¾Á3Aåõ{÷t÷¿õ߯§OŸ>f«nÕ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j��š:>j }xúüfíÞ{ŸßÔmvÕòRc»Õl{‡Õ6,/767j6Üa�nkttY‡uVtZ®Ä |…®aÍ�†Ó…ÇH)2Àìò({¹•ŠD�X´º8�× B@–2"‰”rêË�p‘ƒ` �xEAº™Ÿ�-“ ;)­Xø$¡0Û2²XÄœ òÊ" ’v2Ct[¯£cyÑ–;æµÆ|c¹c¬V³s�qª¿Û¨/7ë>sðàöóf__j+à¯9ðÿ7À'îøÜ¦¥Î®�¡ÝÝè°;P®{Њ®±ŽŽu�uUòjo.ýÀ–‰:¼ue��RCÀÿ!Ì©Ê�—t6qu¼Ó#,Ñ…¬ˆJŽ(C�‡³të q‰D¥ ˆKt¤ f÷œ @Yõ‘±‚ž€ô ¼ÁNJi°¿êˆü°³úÕeˆCÁ|Ét \‰�é%W¡õD#{®oè‘È¥Af§n„À¼7Ö1Šð1@Þ@ÝxxÎ:_;pà…³…Œ¿¾¡sý5ÊjÇ'îýâmèí?Ýèh<‚z'~[jèPøñK£)ã ÈÉ�6&ajÆ{µ1ÑQÍg…ó� Ë ª_ “@MGÌA�pT< „‹ô¨´bé1€…‘�‹Ôõ<2¬¼:…ìà\Î$>"⬩Hp‘^‰²À‡:ä–óx¢Kl).¥@zOh.•Nèî‰M|‘­àc™–P âÀ“’¥´þyÁOŒ @…ÁõTÍ:žÕwê ûó7?ý*šç$!ÿ§ÛcÎÿZ¹{ïýù›kË�ŸG~CáþZ­ŽY>JSÝ 7jh­^·î®.ëííÕ¯¯¯Ïº»{¬««Ó:;»ŒE­�EŒð¬ª?qiΑ;Uø$—T æ<Î(¶2Α„@MN»QÁHXüCsr2¥ÔQ$ ÷%Øã”“ÒÁ´—Î� D©ã”ŽÉyHG´ÓÐÃÄœ…JÀ�DèCž`–è$E ^ ]ÍÆ5¡~wâó d‰~‘¨$S_‚B;!o  ¸@º°Œ3ÐÕ‚Ž^渵³¥¥%üm¿ùÅ9[\\°……Ä—0ð{~™;‡–=„5–—çx…ô‡¶XûÖ�£O¿¦Äþš\ܶ?å™Ù¿ÿ ý=�Ï£Õþ-Ô‹‡ëµz?+ U•ùëBc´µÃkmxíZëëëWc_F[\X´¹¹9›ŸŸS…˜Ÿ_**ñE Y À£ŽˆP‰¨t œ8  Œ Ul´‡è˜§NFÕ?äÈÓ:Aè#@¨ƒpÒ2ùáHƒJî�Ë1ÈŽcžB‚'Ò _î`‹¥1J¼l“øtâ”ÞLE°‚• {ÒÄ{COú9­ãJ©“2þÉU8Mú‘×~¨V¯wZ½³n�08€°Ã–°L°°0o.ÌØ…ÙÕƒ%”?qš)x¡CÅå¤ùˆúýéÙå?9qâ¹™"¥ŸÎ�Šì§Su³ûî{t½-tý{X!ú1bïea5Øp}8A#ï³M›6ÙÆ�›Ôø™Ï陳ÉÉI›žžRÃçÈÀûØTQ“=Z�ãV±Ž€$Œú&Xb ‘_©Ã(° pšt…¯`4u0i¡„L÷%¦UÑGçQ¤º‘F[Íeã¿»—ò@8u" `Ù8‚ˆÏåòI*çL¡-øŸøLHI¶G2,‘Á—)m Π:I¿Ë JA}:£šHHë>õÎNëîì¶Þž>üz1+Ô„õbÖ¦f¦lú´j\Ì ¨kãùç KÝÿêèÑïcá§Ó…I~º”ß¿ÿg‡{¬ïWÑ­ÿ}4üݬ$±1]³îžnÛ¼y³mÛ¾ÝmvvÖΞ;gçÏŸS£_\\T%I…©Ê=|³ ã°¶E,*ž¼Ô¸€U¼¹¶-å2˜GVè@Ÿä”ù=$¢#? T!ñ.J€‹ÆSȉ„,䥟õ zÈ#Hb� ’zò)”¶SÇ¸ìø°CU¾Óé2² +º0aºB§T¼”¢˜ôSHp‡–¯ÒAä‰ÇùÊ44þ5ÓCeà­_n×ôXïݲ3Ÿ·t‹˜-°îèöЭu°ÑQû'XOüýC‡žoMç£ )[飭©´ûÍÚ}ûŸû* ýW˜¾ÝÌÚ»´„©(FüLïw]½Ë¶lÙ‚{»E;yò”�9}Ú¦0Ês*¯BÓ &…ï™×ªabäË\©òxý�–-,ëS@áSŠW0B³SCòXjœ¤sÞ‡_¢“˜RCsýœ'R=¹“̤JŠ»*„iù, šf( ú`v/$H¤–³%¬ä1ÝB_ÀÊÁB—/Eg‘ YË€O9…í‹�’*ÑAïÜ:%h,…²¼¬®gŒ2øÇšÂu¡�¾[³fP�Ãôô¤�OŽÙ’îÞ{Û__ªý÷hÉã§FÍxxØ®¿þzÛ°qƒ�ŽŽÚ;ïµÑ‘Ü×-©ÀØðéÊWò¯äZ1‰ÆA¾¢nG(U òŒ  rÄ5ÕNܬd ¿Dëa¤F¢.ò‘“a•.bÉ…Ü€‹®…>«¥„”¬^Èg:%~æBÈO (ï€9²l$„SSsO Èƒâ´E–)H¾P¦—B3&)IF*ã°±JìUyЯ„++¯ÎH. öaÁxxp�õàV�kc£6‡u#jÇ5†Hãqlkø/|ú9|´¯¡õGWI.ðuu4þ3¬êÿFG­6°„Fφ?00`{öÜ {üSé�>b“S“((ŸÆ1GEæJT�#’ Þ©ýJ yà…ËdŒ—j‹Ã ϵ3±ò$©!ª©ª±¸œ$·Y4"ááa%îzîÒ�žMÌe¥+|ÿßáÞȨUðAa�ò&¨øuQšNGLÁŸ)åI¹Ïú)bS" ñd¤Ð©0|à3[äd]Ré éÎòÎr‰B„˜òÀF¿ˆQ½»»Û®ß}½íÚµËΞ=c´),èu`E·V+²ã!\`³ Wn¡"ã+ëGÅ9 ƒ£Öä8iQ ‚2�Ä)¢©9<Ó'ÊL+ê²ì“Eò£±%pš)haÒ™]¤Æ*>A9Ú¹>‘ ’]€R@ºfY¡ŸÒo'3ƒW<1¡Lò¹sù)‘C¼ °ÊøR®°‘¬s¤‘<å¯T"5Ù®’\b€_•U¤‘HÊúK+twõØúáõZ+˜˜·Q̸ÅAˆhž¨-/ÿ½·�<ób’óQóW²ÇO\Ï{îüüT¯Õþ4êµKKþHoË–­vËÍ·h…ö�7^×”¿}Çúñ£á«<#«ðª™.u)×UA%"× 4EQàt¥Wi¨�% ÿLBM�ÇZè!6„BVšI$�| (Ñ39p;�®�~ˆòN¡H§Üˆ¶Ä�tÃ%¥F€ÃQÈe‚¶èDqr‰'јyƒ„^R�Ùs猑 @¥PLÄò%Wå_£3©ÐË€pº%‚¤W¥ò°§»×6¬Ýˆ¨ÓÎ��µ<9È�@cy kÿèàá§þy’õQò ;D´Ú»÷‘5ý]]¿…éþße‘,c‘¯ £þ-·Üb›7]eo½õ¦;vTÚê9n) FÁ«Y«õÿÈa‰�rŒ¬­EßjÑð„”\K\Š¢Í�€Ò ¿h°Eº©Ñââ\#q\}ÂJ¦"¾¤Ÿ¤ª!$zçGŒ$)O8ÃDÛV&0€3Mý#¯S’“‚´¢‹ƒUl‰"é˜âN’” •(%! /xJ0* <5uIGgN|Œ…6l|†›3Øø7lÜh·ß~»MOMÛ«¯¼ã^ÀfßÀ¡Ú­s&*�Pÿ�|e*§®€BšÍà5£\ø‰B°@Г´¨ ÎÍL,©±’Pô¸$ 2�‹V㕌©1 Ë‘^æ“Oð L|9•¤gøìRPÊR4%‹¿Y&ãJ¼èLH*¸N.£*Sò«ÃpÎWJ³èÀD ”tó¸¬Í4E°Rú‚äú@¢ ÉJVåm"‰‘Áñ¹»OXøn î6ìÄF£ ë6a“Y·�9c³x„Xš |§s±óWß<öĉóO4È–ô‘pwÝõØ­ÝõŽoÕ;j÷²ñ³²\·{7:…}vèà!ûÑ�^Õ#¿zÝ·hÊæÐ<•9§ü w¨€òÿ a,LÑÂO.h )AK$øõ«âE ¡•hÉè`ò•bŠ€ŸÀ‹@ÉwHÂ$´»qþ¸`B’ç(ò'B¯º‰ÅéDNŠj€€& 2 ÑŠ¤À œj¦Î)4#BZ�/B¥„ÚÛPV@Q™e~Â*D£@UŠ”òEº¦Ê q\¤žžñAž;ý¹ùY`ÐqtÔ®kÔ—>»nýÖ¿=q¦IÀO$ºr~>Duî¾ý³w×:;¿�G);—±+ÓÛ·wŸmÜ´Ñ^xþ9ÞêØ£ïÊâZgåQH Çk¥^f ×ÂÈWŽ)€K”2] ÆXF—ðÍ£–£ª×òèšfi~{ÀB®B^y=áf>ON€«Ë 2ñ$I’î W¥roR Dšt YÓÌ„H úLªr€4‹@˜� 7®ÛŒYÀ;*îG©ƒfù((¿|èÐ3ÏTe|ø±Âî~ÚJñîÛ»³¦oàáÝnÉåN¾»öߥýÚÏ=ó¬¦Pܮ銆ºeï"�¿¥#@Šb þTA<š€T+¤TôK”{µøË€àIt—+éØ,éb aŒ³bAESÌÌ œƒ/ñÃ�ÿðIä4JZI‰1 y‰–`ǧ†ëx\³€��ëBvhšõ“>ÈŒg½*›,Â+Pºx¢@¨U�9/%Ó¹ì"TÄ Ëéç ÄW%­Ê*ãKÈ£ÜT ·:0€ Ù„xÚ•·«›Ö_¥G×gGÏ`Çá’ÞIÀvõ“¶ÔøòÁwžùA«¬ò½¸çŽÏßU«w|Û*Ñø­{÷?~ßǵ?ÿYtŽKØÑÇ�VÅ#GÁÈSã§á}z\nðÎãļêÎø˜F¾cdq–âH¸ä;YŠ•¨J•LМ…‘žú!àáÂ* é!¹�L^òÅXºÜ%3â麶.·D�ƒ‰-ÙÊã¸&D¦ É-¨ÌQP6ñfó�¢ ×”lVˆôP3£M yñF_³¤÷Œ—”n“Ä ì^Æe$íÊ÷RfpKÐ×ÛgCÜšŽÙÖ:êƒx£ô±uë·wtôøOlMà'Öܵ÷‘[k�µ?Ä*év¾žÙ�·óî¿ÿ~³_xQƒ3oXÊ^(Š( yŠ‹:™†MȨ~”E!ˆ¨³§ „E_ò…w•§ÈЈ�W*yXØRz’áx¢È'ùô•nøŒQ>ý€ËÄ/Œ—($G˜à+‘–‚‰G©)�IF’êÉ94Ë+E†kÀª]Š_›™W3¬xf€ˆ48/â�²L\—$UÁä©B.’@!¥ÄséܤlO�ì7�'|Ç`x`X�·°ãöêïg7 m|düøOä¶°Ý=pÇÃÛjÝ]_C/¸“ûöùNþÇï¿{ÎÙË/¾ðìÜ ¥ò�ž…™ Õ�&ч“1âQA Ðà)ßÿÚg?ñ¤Î�ýŒÏ$É…– ½#o< |“XÊ£K¾Çüš`ò¥W`+ˆ2Ã@ú¿åT[sbžDi„L‘•}ò¼+ë™X ¢2°Åܪ…´ÌÓ‚$ ‰`…h\�%±íý-ò”\J�•üK  · s`vþ‚n xk›†v5:;þàê«?±u¥~œð}Àçüµzç×1òß»ŒÕþîî.»ïã÷Û(^Ñ}õå—µ›�od¹Cµ–}q ;{”Õ!´ÊŒCî4Äì8Ñ�VxÄ´?„“ã¢9ÑD™+ˆóQ)�t+ãöÔE§DA(ZgðNȵpx‘o¿›LôR I¨øŠðâ"áE |Æ$ӊЌȇ5·×š•hZ‚"XŠU4 ¼ŠËÚš(›¢‰¡ öX†å2 êŒHÜ ^ ŠP•¦^†”Ã%>€†ª\ÀÛ©|D8¸fÈf°�˜Û‹q;º¹Ö±tûΞõß8=}z¡Äýc¦÷cO(%ÐÛUÿmt-cäç}øþýwë±É+/q䇅òH Ã%˳¢Ñ°ÒÔ?Ém¡qªªÞø“0úÄð�5}å_™’´ú1¡%ù €’“~$ \"q*qIm�+HÎP°=OÐäÌ2^ð¥PÕ�X2•r¸HUGµ# ¬¼"A“Is@�°*wŠßDÓ-S¦p•g†‚ØCJ*há½7W¢H~³ÀR¼E¬ƒ²�Ñ©D†7‚µJ�@Çg¦úû~«Äý¡?ÔÀÝw~Žwü7Ì07Mpƒß°zöY> AÓÜŸ&qãæÆ¶ lt�FAƒ‰ª¹ñ ¯FOû’j¥?ö�)¥$�qvJ@è­Kw®ÄÍtšœØƒJzCJÖ_H1h NšD¸t§õ´O¯ÌSz-‚hN&Ô bÇêÚLH ÂÒ/â²K ØŽ�¤­® e ¨�®$$¤…ÈEW2ÒD¶O:4a¸�ߎÒaƒ@KBcèÂÜ Ö½ôn 7·Ñá6áîõk·½;2vü>„ˇ6¸ãŽG÷¡’ÿ6ó´´¸d»¯»Î6a—¿ß ¹*^´0^¥àÈU²h,üe- Ë`’ÑÚøÓhOŠ ÊLdL?è"9\¿Ï”%ÙÑ P-8I¢2É ? qŠ,“X§(d«OJl.D×DYen'©°WöÊHÙ ý;"£s ”¢`¼”�Yp)t3-”\*YÅ pBƒ2“ŸQÁ ›ü‚ª’EDÕPÔ™l•Ð qÚ•àÄúœ’iW©ª1ÉÁ#‘ñsèzm[ˆùÈÿ`¬ÿÎu×Ýw›h>„ˇÒð¾çnÿ3ŒðÃ|Ö¿ Ï�7ÚóÏ?¯G~¾ÚÏ̯œcG•ªJÐ&úå2-7~of´.“Á�âŠ6‡Õ!ˆÍ¹\DH¨v!܉•NâË ð¥,"ÄÈÅ\ ïÁÐ[]RÁX"+ɬ@AŒx§SHòP_�•(ØšI„)€E(ŒWp6… J¦#u3(Ú˜­À5 \9Z®( ºt £Œú’*U5–•‚l £xg`ë|¡ˆ=¾µµŽÆ?Û¿m?εüñ»¥èî¬ýÞ”ú8Gz.€Ü�©ÿÛo½eçGÎã9ÿÅTHÖ,1×£€5Ul6“rã÷âˆÂaÑ� <þ— , àAàd$eˆiè¿;]Ñ ˆNâ@Cz£ä9¢Íµ,Ÿ¬A’ü‚£Q ÌEC¥-d!J«Æªò¯JE@">�ÚÀ³Ð&\S4‘UÁŒU!‰îâ~Áóþ$|+É�b,¡/ÎÃYîüÂN­š°µ8h„m¡��B¨K÷�÷vþFIÐ�-øc_Ø¿ÿÑ;kVÿ]Lqºy4·øòàÎW_{Õ:y*k®œÈvª<%˜—±7/Ç“Žöpã–»€ZÖýàsN—Aþüeû“BÒ;¥® û¿ ÃQŽ ]J tßóP‘<‘ŒÇDœ8}‰²9­K–j,D†˜3ETù.¨<&Š2}9œØ['Fé%)ìz�µY€H36Å e3D�•¸«Tmbѱ uPÊ P+)$… )f%âj¬¯ ‹óÚ#Àóøò�¯‡uܽaxë�Œ�8U帲±Üv®¬X—öàƒvֵ߯ÂßѵïóóÀΗ_yæ)¨n5�°•‚tùj¨Iqј^á\ž§£´ ‰T�aاèÔ¼ç/ÇIW4"†ùï4‰šqçR@xî0^�Ïã—£Q)ÔÌ_N£™ÌiGÒ±D…`ÂЪŠÄ'»4•�“T@e¹­)$ÒJuaILá§�‹,bdO±ðSÔ%‡üf âÊrZ$’Zx T9TM�±*¤%ÞŒ–°è¡"^Në=ÃíØZ`-€&±mðM¶hCÑ$#E/�$U*ƪ�$­Õ÷ÚY†sð™™›Ö+ïkzý©€ð ûÍo|`°L{%Ã?¶`qnùïàEž¹Û�GvïܵÓ^í5 nldí ÕÖšÕD%—TÆ­&-ó\ò‰>õÐæ‘&aAËWô Üc…ïRƒ†‘R°MT)8�_¥/xšØJ$ÄØJ~‰°5˜ŒÑ„iæU<s ”ê{ú"|¥~´IRk´“qUÁÕX&Œ@[l“-ÚÒ4 Rü(AR¥ªÆÚŠÍ²Q—HÞŽ�·§f&±5¾O‹è©@½vScqùWW–yy˜KpÛm�­Ã¦†  ?˜ÊìÙ³ÇΜ9ƒ3üF4½iU¹�5ªTÉf™²5P�9‹=¹0E&/:#” … ŽfŒ±pV]Ëá6ñgòˆ•yr8²øYÉÏbÛÀ%ÅÛ"+›&“|§,bþoªc¶Æ§¤úaífû6øÎ†ÿ/ð‰>ñóYv!µ½>‚’¨ a+¨r©Ž*Ùb…dV‘:úЧzRP4é×-èvÄŽŸ8iãcãÚÎÎ�û:˜¿÷vÉr…EßÏŠ´[HNT„ Ó—àÄÛ* 8 DåLŒ™?YÞ×Ó�tB¶@ÿøwÀ|E;€R’—�£÷ Ù¿ÿ‘›jËü&Z?¿Áþ‰Ÿù”6ýœÇ×yu/)~T(Ž^pj†V|Â…&]¢"©Œàò�.â"N8ÿ)St¢Œñ9‰`IN°9�:¤‚__FB£çô¾¯¯#ú»æš]vÃMøJÒ5רZœ;×Û¿iöÚìBÝÎbê>=�¯)- !~ª »†!¾{iÚj #j±ó§$A»yK��À”ýÔÉ Ö…†Ý�;ˆ%LùèxØ1P_f‘¼Lãcwl´¾œ‹?Æ™r…Þ¤ÿ¬ áÖ ïú~›~ÇaMñ˜7Ã!¯�ÛÛiKkºl¾·a˜kØÉ©Svðôa{ãÈ[vàð!;yê´ŽƒgÞ9ƒdg�lí‰3u8¤O¸VSvZ@+ 6PNY¦sn‡dù]•çi9¾šN! 4 P ¡š[(Q$¾@6E}êÞƒ��CƒkñÒ ò„§;–—î|ãÐß*Ó^NøŠÎ0¢ü"zÿ*ÉÖMÛÔ‹�¤•¶†T©£¸Þ[q*[Rä2.BÍ~i'µ™š…ÄN¡WkeZ„%:E¬Ù�øœ|åps,âàq*¿VS-øY 8�x Fù�;·ÙMÛc7Þr£]…ÙU÷ð:[�ûøÓçpÚÌ$&Ý>²Ï`ké,n0™–ÉÑvÔ€pS�vŠ‘Ù. _Ðû@æ1e£Þ ž>³sGqž}gÚ!Gä§“f` -Û?;�ÄK9_µÛîîµ®Ù~ãÇs{æ—l`ßqê²¥yÜÛâ‹y’ ¦å9ìyŸÅìclk]¶¡{�mê»Ñöî¸Á.\û);ó‰óvàÜ{ùÐëöÚÛo؉Çñ ¸)éÌŽ 8�Iª5Õ‡µ¿FfÚ#³°*U5v1VâV¦nƒiÀÙž a)u¶ïfÛ„ï!6°`7a]6‰‘�#ï6Ì´è ^ŽÐ”3�š®Ž0§î4;GqÒ0Þ¹|Á:—ð1Kˆ#œ�~ëÖvÙLmÁ™4¼Á)zŸ8-žIk@™L�³ :™}ÕÚ ÝvÓ­;íÂQ„'pë‡[†Þë0+9¶`óg‘&Ø­øX@ßã”±ÜÑ…õ|ãO'gý6×»h§ÏÛëgÙso¾l¯¾õº�:uJ· ìøK6¤Œ²k�”ʰLè*� “²N�òr"¼�ƒÎ*Á2Ži¶ºVMÊt.Ÿúâ³ä� H¸j»ÓˆA§¥ §ª�$Fú‰@0ׯŒfÒ\áåbÏÝ„ûù;ï½Ý¶Ý¸Ûú7­·nØñ…©<^Tc퇎}¼'‡®·÷£’šfÃbRø äñ]2NÙ¥åWGá̈…f /ÖúÐè|=@:�¶MÝ&1{›˜YÔèŸÌKŸy¤=Yú  ´`\�CdMjÔÄK§lz?¦ÿë‡ ë€6wO( 7ìÀÅ0:æõ£Ö]·z7|ÐÖ{Óß‚èB.)›O0“Dçwëâ»åSŸ·‡î¹ßž}îy{ê•íe|(ö ž,ðIˆn cÕ5Ç«XÅ@B*¨®KÐö>t¾„$È+² m)!² mùU¾)ÈO‘cÞªm<Q­*?œ*ü&|Äóܹ³ˆ¢àpßé¹.L[6"³OLÙ0¹â%x0$º¶>€¬¤’“k�*�hœ[é2Hý+"5pEyIpøHÀc “—BbW‡Pâ ­‚EÒu&G®M×Ûþ»öÙ>4ü��[í$>1=c§�ž°ûPðýXZF#éœýž² =tغÞ:4zÄùÙ<ųéЇªñ'‡€Ï u¤y–ñ…šE̺<ŽÊóàºN;tnBê’–›yÈTCÂLdêlÔ Hô£²2gƒxÑ«ƒÀ±OÛõ÷÷á´››=3kÝx¬XïC„†^GC¯adïÀ= Æ{å 1 ûÖÀS ›ÀcÄy<‹\Àí¦�Ç)HGcè\ƒ|¯Agvrѹã^»­w«¸y¿=uðGöü�^ÁZÁ Ü¢ø÷$¤0•¾˜k‹n \AÊÅ?帬,1(.pº•�ø‰Ò“]:3 u²w£ñ0˜ÿ %\®ã@rÙnÿþ7b.øßBÐü¸þú=vøða›Ã,@+þȈ2&Ÿ™£Ñ¦+�|ä¹—>â#¥ŒPæ'šü"[OYÎ…Š“ˆâÌ!ÓżÇÕ‚KºÂGjôâv¸‚Ò­WÐã¥Ø£oÛ¶Ùùì§í±_ù9Ûv÷>;Œ�¢<9>e?Âo•¿ §¦gmߺ[ìÄ”˜­N¢qÙÖÓe§F—ØF4âcpÄ“w6AQÄU,9L\R…&it aqV Ó™ëÖ7ØaOL•ìåé‘�R“tÎZ(HP"ô«Ù¬øàG…ñ¢Ñ±d›oÞ Ž«s À¬mÜ%8 Œcçàù9[ÀºÀÒ¹Y[Dxi›„¦ñ”a–�;¬þ#-Þ®pÆÀî¢sç;‡ÇŽ3§ñý=¬ b¶0|zÉöîºÎnÄ–óþõC6‰‘rjÒ_¬Ñ�›¡õJ½KΣMÀÞ�—Ê´W¥ªøIŽÛN¨B„õ]Ÿ¶GxHjYD®³25ÎÎ\ƒ—\¼ÅІ »ïܹÃ~˜`fzÿv­—í�ž�á±ÏfŽhÃÃ�×À³ÿIóì:G¼*†EJ™ªp‰™óFq(A +bˆaB¹ÍaÒ¤N€ÍƦ8„H[–Ë(Q%�ô][ÇâªD ‡“¬ð"M�Oñ” �ðØp¶o»ÊøÄ½vëÇï°Ùõëì%4ò·N�·iLq»�‘>T†~T>~›Ïóïž²»®ÛeG–¨Fbˆà>‹yØ?Þaqê�lÐ4a+%� m£JC¢á-ï@»ˆÇ†¸ÚÆáº�š¸€v‡5vÆáÈ«ÉCïûTÌ ŽÊü:h�tð¯{”Þ klä v ¢AÏ™ÃL‚8êI=VÁ!Æ‘aÞP87|êŽa¼ý«-a¯¶(Ï÷ap‹‰OžÀlcÏ�u­Ÿ´Å£#vã`Ÿ]·ç»ÿÚ›í»X0|úåìì|“�üL¼ì¤dÀp[`3‘èDÙB¥å D1€_ÚÛÀÑ^åÒÂAºÌ%»pQ�~y˜OØ0'»ª^_â:À÷ƒý{Wd°móu_Á‘_�RQnBéˆõî»GcJ£\‡i¡ºò†j˜ý*>e‘�i™MDøA…^@â$2s“Éé—èê±òµ ÷ª›*}¨##ÿå23À SävÙ ˜ê?ú¹í±¯~ѱªÿZÊ#vt�£âTˆAŒ½h|hE[MÌa6€pvö�ažÉlëé´‘‰e»€GmÌ;þ0qιôlºŒ¤+›*œÚ–Û´ tã±__o— -ÛïNˆ¦lÏ�"é ΑÙoïÐhì†þÃ\ïAjÈð{»lýî«ìì�yëßÞm]èÀ–°¨Ç‘\r$˜%É,ç!ˆ‡IAçU}6Š]ƒsçpžÞQ`Ús ¶vÏ[8�…“¬6=oW¡S»mçµvÍµ×Øl5Š­É³èœ¨[‘vœüRZ ´‚ª·Á“5Žä"Ï5�ôíÓNÇ‚½à¨°‹€ú²žñI·R×ñ˜V{õìÙ#O x—+2XîèÀ±_î¸Ýt û¿UÙ’bŒÐø,ëplXÞë»É¼$,üà“†õŠLœHàty´CKEë •é’R±�áE� ¢¤¦èD-±¦ÒøCŠÏ(¢¡¶€Q}M¯}òS÷Ú–·\e?Ĉÿú‰ó6‹Ù@/ý0zõ.d ›8õÕz%d°‘¾qnÜ6`¯þ|Vj�­Cðè¬/þa ΃¾|þD€O9:1=`ï�¯¡ßårQnJ÷ñåèÒ…—æqNû¤òLy’½¡\Âøãc'0§qÛ€t‡*@`&¸kÈf§¹#tÑΙµí»û¬6ƒÜÍù(O[»5ÙÝE®‘°Ê2¥O ¤WÄ×÷ÚÔ[x£·Hw�——æa‹wçlí>ì:}ò:\ÜMÏY'ÞM¸ ;!o¼ça{òšëíñ~hoý€½ÚÙmß9;f‡§°¡´C¸!Ä�#>GSïPR>³v)Y;ƒ…Á°0Œï(LbôŸÀ¼Ÿ | �x .7bó`Ý®‚�ß<Ò¬Y/Í:0€,`Ñm��3‰QlÄ9‡…ƒs3KÖ‡­¿‡ sǺ.;7Â¯Õ }å'lTE5vÌH2<5ƒÀ¢ì”¨;±zÕǶØÄYvL°nU¸V1¼½Çαƒ J5$R�´’ «Ëè°è\×m“=xJq3 tV¤ë@çÂEÄ<µ¨ ôYÿœ©w Ûfi`¸eÌz€»~§P_{­uÃ~ç°-}zjJx­;I’RJ…-\ë…Šê¢[ÑIê-Ȳ˜ÎŠš1-¹Öö¦ûz5znLBÃg�eú4T%~÷3º\%@Œ4Ô/éX,J‡Î;þÞ©SG±i・4óüÀz::6C�u\äG>ÙHæfçÜ`Ô³ÔË—€JOh„*dí4�%ظ؀dE„qôÕÔ”U©‚szá/|BéTá<ˆkÍ B©B"K *Ôðƒ1vÇ7Ûc_úœ­»~·EEøÚëG5-_‡¡•Dõ|šƒ—lè¨6]ʇÇŒ\#¸„Æ5;Ïv/Û[Só6Á{q Â�· |ÆOués ÇIÖ/¥‰K. °�o‰®Ã¬áöpñîÈØ¢íÝÆqêßqvÂîAÇtõ}Û··î°¿xîá{*ÈgjdL²ê܆U˜Ç¨KnðQãÈn�S�V—¡iüΕ)ÑaÓ6\ÌÄvn¬µÁ­›�­_/ |pwÙúõØ´ÐIù™/Ž€<¤Å *hV% VbE÷ªú4!+… �Ô¢%i‚‹Qøê=ó))""‘6£…I#aº&ŒÃ„(�Š2å¸,ܯ߇ÇxŸ}ì!»çg²w:‡0ÕŸÆè‹ïƒr÷ØjK¡3¥°Ê2oÌ*Ç@†é¢ î¤ "6Ök7 Û‹Ñwaã ïíçQDZc•BæQ»Q�¢\¶!éK^—$›£Ai«-ø¹1„—q–¦¶}�Ø@v·×ïÄÛ\|��à(’P¾ê\!«šÞTµØ�Ýø«qm¾¿¿Çú6àþzòV@«“˜q×À}À¹#ó¶íº<îCçÅõ Õ¾@Y?XCذEÚ\D­mî·1<&l`!‘ÓjŽêEI’Ÿ� Þv„¼ñ£S¶ö¶­6òäAØ’8’Ò@ø/þæ'flž¢üÝŸû‚ÝxÝõö¯¿óÇxd}²‘?MÈ@'N×Ãe�ƒÝô“’Žtê¡ø«ÐJ¬Ä[æb8R.À°,ÙÁbû@Ù¾j]µÚòv]Ö† ËîõÆvŽÊ±ðÙ¿žßb´£ÚÌ+y‘ù"Ä‚MF¥“œXs˜öj¡‘YXeœž£µW ÆÎF'™CF‚‹À‹:oDA"€d¹˜šã™ý®]Ûì«ó°àt—[î²Ù™9»ií ½{h\;÷ÈÆF(¶Ð«œo"˜NÒ]#)bü'ïˆñå~l¯>€lFÐ0÷të^~³柲}¶â²°0«íÁ=¨¬|½·ñ>اS÷:>F±ÌÅ$×Ý rà½.w¼ÿK�+I!ü# Ê ³âCUðl#�•Ãb‘pàñ’¦ìª©”áP0Èõª*Ñ^É‚B†S­#€Eäé;DáUJ�ñ&Ç—xzñÎWÿÖ—ìúÏ œ*º| ¨ �ø©�4?+r7£Ððg1E?þî {÷Øq{î…çt2Òf¼mzí®ÝvãýA§˜@IDAT5·Øõ[÷Ø–õ[­ÏÁºHc�ÅÑt`?z`›xgÂ6`= wÛ„Õø(°£Û§Ç¹nˆÝ„ G>™¦2�û4v(wnÜjk~éWìÿxü�ìùgŸÕhZhôÜúKË”Eª�\™ œBž=·IBµŠÆ�¼’…åÆr÷Ó¹$ç}ú—Ý@'¾� GŰÈ…—õ æÂ;¤u„Ã&żÁ³±°23óš °²)¹YY�8JÌÄt'õ+é²#Q)šáMV\.ŒqÚÿ•¯þ¼]÷™OÛ7ðÖÚl7eãg#D£ëCÞ7cßùilÑ�}7uÆGû³€ÁÈ}ç–õöÖü6ÎõTþ˜¦èáCµåu<Ç[ƒCÙϼø²=ñ½'ì¥ç_²“8Q—:Õ¸�›¯|šJð»1_ü•Ë qÛ/Ñe4S”áJé³aK–�®—l 8uT Ç�”‰¿EE8Ñ@Ù¹n¤Ò¬" J:ƒFÅ£ôCËœ�-щPWÖ�),ÜMŒ°ƒØ÷z¿kqêôuWï¶[vïµ›¶ßlÛÖm³¾¥A<åÀíf Ì¼ÞÆzÀ�;p �G›xw >܇W’±ÞÑ‹Y’Î"Àþ ÜŸq;´æxŒý3 ÞôÙ/Úÿ„Nðit< Þr¨§Ë™A€zV]†” W%QŒõ*»R0Ãߌ*Äj°ÍƒoÁ÷þB—Ýää¨iÔ(÷Xð^!<³,A¥¤ªf*eŒ¼ª2€#X©’ø,„év‚‘tÈ‚|RËp`§SÅò�î ¤ÉGãÇ´’ºýâ—?o{ù´ýlF9#?ëv/*·õÒ±xÓNŒ'Ð!ôä=û›“ó¶ë{ÖÍÚ›£¾ õlRcÚÊÛJÆÐð¯ê·-Øhsö©Ú7þì»öòK¯`´Ç(†´p6¦ø´ò©ÓŠFÅ2ÌFÎwø¥GØÆ->èŒq?R…ŸbÀ„à™2áB†!hw&Ç«ÿ‡Ï{o+œ¦ªub çóyf–h&’:„Ô)�Rp*À¼�‚A†ñcÞÙÌãLA.pò÷ÃçžÖhn¸f�íÝs‡Ývõ­võÎ-š‘Õqbÿ3àOcç ; ß!)5t‘FÌ c^(R!aRΜN´MdŠÂîð[ÄXe¢Å/×]‘€9ò,¢=z1Bó²X™�é!™ŽQ8ò²ÒMÙ£P þ(G‡‚�€øˆN²BEJ)çWÈ¢ìpÞR,ù.w÷ƒ÷á½ýOþÒÏÙã³uûÑØÉyãGÝÃc8¼E‡t¹QgG_:¬N‡~ÔÖu–†Ò•ûðŸÇawlßhß;|£ pÌFêí8õ÷&lØY:zÔüÏìé§ŸÁ—v0SÀ¢cOOn&XâHW²Á‹çÀ>�‡ï4¥EÐ2/´+°Wš5…IEãö Ý"Jq…PÈ|ä×Ó§,dz±;”T”_²<îÌ19¦å? Š×aä†`_æGKÉĽCÀ¢!m¬t!é9ãáìˆ2æPn°CØá÷'k¿c7]{ƒ}‡Ô^[ßl·ì»Á6îÀëç°Š y J ¾ªKèÁÓ‡ØÐ¹&p#Ö~þÞÏ¢Š§LÚá.Ò©@Z¤»y…­P3 ¥�.Äó¦»öÚöØßø’=[°§OOäsòˆ_‹eNÿ¹pÆC<8êå⟸Cu’ÎŒ³ââE¼Ìr¯uÞ�õîXƒM*·á•­ø*ì‹ÿî/ì;ßþs;uú,Fü.,:bÄG‡#«%µ‘‰%5 p�¡Æ•tv= t›2�ðL™QØNöp¸Ð´³�Ô�pÚЃj _Šs‘j@žlB“�lêàA\¡o�±ì˜°w¤`ùi..ý¸vÁÂ[æñr˜¹ó*ÃVXÉà,…ƒ°Bâ¡,>UÃçÉžyÚ^xíel>ÚewÛg?÷é‡ì¦ ë­ç)6æ°+å§¥,6zv訚ö0é x³ßbøO?ù°ýc,$þèUì¾…ü4S–Rfir©žg0…WœÂ:L.�”ÔüÑR—ë.»ÈJ Àb‹ÿ¬—ÊÚªy’XyE š°8Y€ÎædÞˆUÅÏ2F•(**eP2ðåÙ)ËJÊx¥¦Œ)1Yq–q–]¯}éW¾h'6o·?å}#ب/+#ŸÁóÞhôÇŽ¼c8Êj½_Ñ¥štÔ!‚‚3†70S¸¯¦Þ³ œ–¼iÿ÷7¾e/bºOåº1âóK;Þ �•£ý2¶Êú,‰»þ¼ò+ïÊ,óÌ’}¦"‚ñ¢’Ê6RxíKšy%�Xp�ˆ$Õ•)ÃHNt.^ &—ÈTB¨[šå‡0lÆ-]©ŸÊÚ}Í<Øa�ši#!Ú‚!Y¹SÇm“nB7Þü0î· \/˜··ßz�Ù÷_|Úî¹õN{覻±â¿Ë†pùO$FTù:7g˜ó£ÇÁ ›¨ö¯é³_ÿÔÃö;8\ä�·ßö­—ÔJŠ¥œV}¢.îœâR? qôSøâ)\ {Ù…{ub¨È.U+bÄ9ª£GâJ^‡¥8QªLâ�U7‘�ØÄ»Ä+–�£R„òP2“‹$ ‘Ë�ŒJø¨ˆ¸Ï{è Ÿ²=÷Ým¿wú‚M#Î~lðýhàCX…’xÐòìüuXQ~¯£²Ñä >ï(9¶Tn3ˆ|õ?ƒ=õ­ÇíÿÍÚé3çÑðqp&:ê¬ÇgÔ÷õKÜ#�šN ÔëløÌã"ô<‚V �üÒDÙŽ$¢°3-æÚCÆv.àȰ‡ªt êœ.�YžÈ=eÑ€„eã�!ä! !–bC²xIK˜ßŸ{¹j_°z§ˆ§´!—ûåÉÃm³d„&0o�˜Apç»ï¼cÇ�¿kß{î)»ëÖ;ì³{ï·»6í²µüŠÞð<¡W?äëÖïPà�°uxú³�ÙÿºðM;9|±ªÕ9¬È53TÊSâHt)>ÁB%¦€·ð6á›Ä\Jôò;€PÊ=š!–‘ /ÜxDtµAãÀÍÊ-0<@ «¢Ç BZr¼Â8T^B¥�'@¨ô‘€|qy.“×ELý÷Üp­íô!ûÚè¼mïï²C“u›âpèÖcô§ò±CØŠ}ÿ#Øu6�—t¸> �•6‚pÊ.©CwŽr·õÙž‰³öõ?ø×öøŸ|·øxÞ¤d%•ŽÃû_.êÀŽ b ã¢òxá+û®T9�+J%¿‚ÒŒÊ9žX9—`‘ÜÏàˆ¤Kü‰ÃK§D˜òƒ!ì“bDÉn(Ÿäw[øœ/€È;†i3ÎÐprmÒóñ!oô‘ü á)ÕìH{ùöÙoÛ_yÁî¾íN{l:lEæ[ŠxaŠ­�P]l`_½î»éF»åÍ›ìüùó6‡�¯å[¦L§²Qˆ‰*�bq` åð ÈÁ«±A3\¦»ü€ ¨V¥Â@<´e±y³À#îEéªi«•+äF]Ñ €¬I†�L�v zØ¡¸’Ÿ—С\R“„rœÈáVË<‚{ä‹�Ø|vë/��Ùµkzíg6¯±ÇONÚ:Ü÷s Où¬ôÙ<Ç(¨“ôñ¤SZªC”óµWÞpî¸ýÉïý¾ýå_=‰ÑªŽE¾n 6@ûÔ Ÿò4’±+/¨¸$ÀÏó$`)ŸHƒ£&°t´ ctº ìñ&ŒtËt‰$8M™¡¤ DÔ© oÆKN»KèßXš �Ê_¿E®•팜Á°>K`‚Œ3ç|Àè��ö: ±/⣨ºÀ̉OChKí- ÏÛ8”ùÈéSöøù?±ç_{Ñ>¾ï.ûÂÞìΡÍÖ�Û†ýÉâØo1‚m7ßy×þð»ß²×_{ÝæñÞUr;SSw^>9’À%ßi Ž*mÊ{b �›Uš Ö™Hß·:€¢ÄRá„° ÿ”ÒÞdx�,§‚#QT^e�2TÑ]€ÐÁ” ”¦ PÑ&^ÄK �#*R:�Bq!>‚”ÆGI÷<°Ï6Þ~›ý[ìÝge:ˆ—Y¶`ÿC›ì� ®òS¾À殜ä‡;�&gÊ«tEI>f¨vË`¯]þ„ý¿¿û/ì{OüP/OñÅíœC&—0ÔÃç‘�ú„*¨Vÿ©9e*�©¸îjÊ�Ù@ÊQµ`‘!/)U z¡*Ã^éddêâ3Š¡L†±¼âÓèEcK£½“#c�/Œ–ŠÉ•H`4@øšìÞ{ï°þ®³gð2J÷ܬý¨ˆkq(ÅÎMÛ§7 ØØüŒ]@%ái:kpOxh çÕS –aä‹ÚrK4§ìlüCØLrgmÞžÿæ7í»ß}‹}ØÉ~º¥Eð~>ÊÓ7üù¸¼ ç�€‚¡0sLç×ÀHaT¡hRRJ´Ò/‡Ÿ%dû„ÔŒpB�–�ÔÁã¾BOº„?E#-yí`�W>Ñ!rQ�êú*–¥"\éÜÁÅAÄÍ*†AÂ2¤%½~±Á¢\Ù+ëö€ ?'Æ:Ä$Ø °ÌðÃÎÀ¯¿f¿{ò]Ð/ã^Ÿ_çÅÛ7=\cà"0ë‡óQc׆2à*­Ìeš¨Úû!°­Üö— ½ü€%�’u€F¡kÖ•`öÄÂD˜ßá¦AQ`dJ DYz!Êei¹|VCÁ´ åÕÕrÊ$“p† % ¸¯¯ÇîùäÇí `ÎaySCNÅ×c‡«û$V–^‡3îÜÐkßÅWi¶aD?�m¤°ªÌ|Æz¥¦Á$" ÞÜ�™ÂÈž°oÿñŸâ|x¾©çôKœòÏ•}Mõ¹ÀY Ó…æ §˜ë\ºÒ€¢ôü*ïÊ\؆ÜNžusˆÄË‚Æs &¼`‰„Ëò"XU4È¥„‹‹«K­³³Ó—q¢ágáâi’Qѱ,:êƒÌ†T¢ñ»](x”¥ê¦êKŠjacÇŒQ_,Ä£?–˲عÍâÀö*~ž9M{Ê¥<Ñ>Ù%…S}­æ®©€ÅåÚf”åðVº÷~B—ß(5W‡\QWÆŽÌám›F)>cÞ“‚€4àiîò(ãJ>å"䶆djòRºˆ¨˜šcðèi 4L�g®ß¸ç:[wãuöøŸ@eáh¼÷ø�ðyoß…Q‚£ýzlÜÙ»¶£ݾ{ÖÏ>`z|BÀ A8¤o¸lLéÇh²­¯ÛÖžz×þ÷oý‘Mã»yÎâ# ÅaŸÊÆ5ÄÑ,â—žÀHÍ�¼„§3ìx ¹/ÎrÊáéä‚ËVñty­84å%ÚG3a"\”ˆûz KÈ ßû‹\‘À«”g†W…pa…”¨l¾ªïȼÂ�L¨ªâR ;æÒyy¼µœËT–)‹ydá:2Ÿë"‚h@ÄE• 27ä@ a+îî[o²ƒ¸¯»ïßoÆá–›ñâMîÇ9½çfJ@{Æ©¹öÙ��gpï÷ÔÙÓØæ‹7ïЬ¹¥„F˜·�R:×®Å[{çðèO#Fg?z�)JßçÁï)I‹§Ðõ¥·ØY…os±¢hϺVúÑ€†Ž:*¯”“¬R~8<ŒNyœJsŠìË@!#P,‘It) JP­vÙPRƒ!))Äœ/*A �iªO„éde*…JE(¸( ?”DR( ž¡BVAV„2 ÕˆtÛ§<‡¾²+XÁ[Ãm 㤧Ì«;÷•÷P»¢=iHô.µœ�,Ç«DÈ-{à»§ª`!®Lø¾Â—ß4%W®F ç)=è\@Èa„|šŒ$ž° �¦BBÜ9âaY¯øàeú‚EÊÁ+¾¤›ð¢L÷1ýïÆBßÎkwáäÚ½äÓ ~;§ó˜J´Bè x;° ¯?��K`�…Š{ÂN—YÆQ�P w’ê©©P'o°¸xúÔ Ü2 ácæP«óS6ürã÷ʤœGÞ¨\Œ|Ðá^ rã=1´èE”ÑøÉ·%дH‰T$¤É�ßEÜ=^®˜Ó µ©†«ùœ'W–APÒ1á -Ê™ÎX²Œd«*ºˆ¥t›ý,@�xa\ÊäÛ¥‰”€ÍüX2h¬´,�JeUÍ -—l’‘tRr’•d'ǃ– „1�¬ˆ#²\‰úÀ—´~?ò|¢{$抩ʆ¾òâ $‡IxV ºœY†ÛÅE$„ÒbzΩÄ) 8�Ÿä!)|N[øh _²é·u[6áì~~íü¨ì¨ G|Ú9ºlûíÂáKv�'ÊÏ…£,â-×p6#Òt]DFl#ÇÙûKË\åÇœ ƒ�D•‰Iñ�*ƒÑm8Ï‹çAaf8uJ9½˜) Pg&a§ô°@*rgL$�Ù¢�Äœ Èœ^N@@á¹€ÉSŠø ìJãÖù� ¯�M`á²H¡OªetÖ…rhp——ê‘ç“yå_`S¾ä)^ðŠJvsB6xŸö³¬@‡¸fR‚4tÃØå$X•&å,Ñ&ª$‘ñ‚ƒÙeÛàßYá±ë—ë˜ó+à˜Ž€ò¤³ ^†ŒJ ¼æjD`®*°ˆ{v ú¤œ:…\àΛIðt"ˆ�‡¼þç`­öB0wÿ áÈ휺;»ÄwùYYذSã÷Õa–ûöÞn;Šgj«n¢e®Ñ4:¸ÂÏ9ƒ§ÁŠÂN†âT%Âí@ºÿ$ŽùIV8�–®�Oò•¬¨¼Ñà‚­ä”?Y2ˆJtUi E;®’Á�TÃçû˜id,X<”Ò=Yœ-I !Í<Š'FD¢1ÒVÍεL’ã8^…Êȉ$d¨Ñ ü‘+'„,½¡{ç °Ú¿ ñT¨‘Çýš4„@­Ã«4‰Ð&DE(µ!ÔÕ%¼•ÊÏîñ€Zê쥞Òü`þ•»­ [Ò°03À|ÐÔ {�ò$†¥…Õ™ur—¢Œ£0eÇ1�i’æuEBÄ–(‘n® 7Ë i�“n`q9æ quÉHWiÔ Ó&œæs&£‚qæÄ[(]AÃô²aœ9ÁL‰€Ó•’É0µ€ uû¨Ä—|éM4Ä¡O.\Y� =\k$šä':ùMyK8ÑVª±D?)�r…rÓGh0b±®úÖæï^¡4‘áPäðóÔ¹Q%£6‡•ÙT9“%— Ú†5‘¢)“á°å¨PC®h¤@ Nœd‹Zzä�ôâ}¾w ¬ð“[_Ìü6@•]Â.<Ò;ŽOé=óH+Ý*ø}$bèˆâLq´ ³}¶mÇVåƒ�E+ÉI­”ÆñsG #@÷Þ»ñ2š„fÁðr">�47~×8nÞ©cÄ÷]qEÕ‘™�¤zEbL¯ì<'eHs8iœYüï4 "E. ”u]J.µ¸/ùNW¢.E¦d.±ñƒ¶™=Cš)Ê…é%Œ ü©`&I�)'Ú’Ú(X”âbOL´~YOT‚ J¤8!A'/ªq`ç‹«÷îÎã#©cp6O¦`V”&‰„§‚î€Aãç�‡ph±Ÿ'À!Æu…} Û„±«oONá4`î Ôa• %}ê0ô¾>F|œ5�ÏaMÚécçìüè€ÝxË͘eô!-(¡ÿ¢è µ<Äk¨ 5¥¿Ò!XX‡Ë¸Q *v]Âpð0I„åI/�H@4Rzþ‰KPШácš¯{| )IŠ$(¯ì¨oK5­’€<-pçLW§s{KeåìˆH}øÁìrðñ¨¬ ò@Æä.ÒøIöË|%`±*0SW "]3-”çÔž_Lâ�4^v+ÐV^Vì²;tªgÉOy¥‚|�N¥$$‹ .{a 0èOQÒ»l’±rL™~k@`QJ� ìòòÕW÷?=ÍW:%x…†Í‚m8n_ûá·åXw8ò—}‘Ð7÷Lã'O�¶Î…N;|¼ÃÖo»ÅnÇëż£SÖpq e½êå9e T1$‡ö‘T¿(_I²G” ©*�‘LY‘”…'½\Ÿáó4bvN¸z ÇóêÜ~- ¹Ã”XЖ©<\妦 ‡¡=wìŒKòœÀзÌﵤœF$7þ2—Óë5g´œh’çùH±Š/¹lNIÛÈG)Îùeî±gñÍD6ø%6|„Ì‚©cú‰\Ñ!ó]zà²;€””ÌÌ É\¡’$5½&»€Ê*\fMùS,ްrŦ<Ê%©&)Oš;‚2^4ä‚'/%ùC>¿·J#9vªpôñAÈÞŒC<�ãƒÜÌ[æ…³�úÍY& vaðÀ;åK�në¶!›œY´Ãç6اý<>!¾C›Ž’:Ì ¯Êm ”YR>ƒŽžèUÓP$BÚ#Ëôˆ²�[â 8•—K�p¡”7NõÕð}çžÄ¹2Nî”)¹€…Gº”ˆ@´¡•Â%8é�7–3�D"°ƒ8G9 Ê®©s"*“€×%–ŠpQcƒ©` €7 ~Ò7Â!.Ç"‹fÞ‚yc£×HÏgÄ¢K\ág}=žX]Ò/d~@ï t¡ZªtR• ú%¥¥\ú¢ c+Ÿ Lþ—r&þË#•ÿˆM0ŸHxb"‹ÿ(O„.D�â ¸ÏêÀ ïãõ£\6r:Ü"lÄ-ÂÞŸÆcŽúlìü1-ÍGV¼ñÇ~øò vv5´éçíc‹6Û¿×~á«_¶«®ÂãFÈ¡FI/Wž¹)  ;•rOÝ�g%õÆ�HÉ1[äÖÕ#& ÿÎ$Ð5(E„*,Žô<�˜Çkƒ)£ B†œ»qñ(ý`NBÀS¢ªˆ£SbÙþ‰‚†Hzhj�Ô!_ ”D¢…˜ q«B[ÞJ €šöáUüY¸Ã\˜S¨ÜEéj©í‹»"¡$-åÎK€��—QþKøéÄáÈKJ)ûäp¤—ôX ãø÷½ìÀÇQO˜›gTþŠz8eDHvÔÞ�Ï+;Â*$¯,2㔩?J¢pй® XâybSÄy„—\Ãý:¾%‡^˜ûýU \£{̶aÿ>éS~¤ <;ˆDËYÁ… ùOyã×vQHèä'™Oü=÷öl¿ß~ùWÿ†]sÍ.9ÎW�ÝX”Dý=_Ê/ÉIO¯`’VF‘KqʦÁW¬ø‡|’HŸD>ó‹MJiq�Pׇ�`¢ = ¢åÊéR.eµpÊ^@¯±Éžn©Ä �pL'Ñ9×Ày¼i%!¿ªú‘/ |ëVÀ ò’ï¶§]JøÊl’Zà :R3�|n¿¨Ù_º·' Ó)\ÁŸ1€Zu)ê Yï/tÙ€ÛÅ«Œ«”«4A8ÙH±ÒΤ@¥Éâd ÅÂÞcEJɈªˆ‰-1&?D—ÄU�¾¨‹OLuaôcãÖ |6òA<è›a£x�WÏþ çÔé³ÂòàMû�ãþ ›ƒ`MêÕ‰­Ã�Ë8jZ· üÕ²=‰£ä;¶Ügû?þ5{à¾{°“°Ž×�¹ßœÊ'1è‡âLQve8PB3¬¸Û7~’OÚ›Œpº CÜG|<Ãç=þÿÇÜ{>yšw~ÙÞ»q=Þ¯™ÝÅbX,@‚$@$¤ŽæHŽ¡Ô…â‚¡Ýé?Qè…ôòg#îG�È 9 b,Ö»ñ~¦»§½wú|3+Ÿçùu÷ìîìŒâ®ºÏS••™••U•O=õ”)Ž/¤’¶'ž„É¡ Y)%bKB!±¸¸k¢Dªܑ²òœLJ”çÝ „"¥ܢj$RQà©?U ZÿäÓÜ¿„È£² -å]¼%cažiˆÈ]kó©ÀÄé}ÞGòYkRû¦Ä�­^Dåšþ ˜žL¼„?7i>ùþäæ $õ¼`½òHÁrª¸(Ú.ªÍ =U ¾8Yã]‹�–‚òJNá:ˆJ¤¤S½¢‰ôšJsæ)žßUffæ8-vÕú†Øù—ødÉÏïh_¿MÌ.óN¯÷}É Á#O| ·…E=ùïÐíW¼vö‘a@>vÿYïàäàíd%E¬ƒó÷Úì‹Ï=g¿ü½}vâ©óöÚß|ß®_»Áà"8n€œ9 ÄIþH³d[ »‹p�·‡7þB ™ä…Pzñ´$”@~ �RMçé»8 Ë{Ò&ÞQDäÑ %$ðkÙžâK™6H² Lü�H¡(÷ïJÇu•qÜ�¼0†E²äîòD‡†|5Úqž¬`LƒÊjìÞV6›øUPi4"Ò›w±jIȺ™*XI»ÕüÊ£^Ÿoö¡;ò–*Œ=Båmg7. ;±E'âÖ°WB�JÍÈFá‰ó§„¢#™ðI?ΫDˆ­{¹ú“¦¾kBËn.?˜·ƒtõyð¢ÑÓ_[|�2ÃïÞ‚ÿ‚gõy�°ÞùïÝáɯC#<¾¼�HÙýõ7¹3U³–ßHÿµwWíÇWöÛ¾/|Ë~ãøCûÎ?ø®�:uÜ{úîKŠ|Fš • _ªH9*ùJòÝÚíw” Oe �ˆ|Öž?ñƒ>\ÿ…$Y:†'é):â¤Cÿ/ÂŽRѽàûM°„KG„¨àÒ‡¯…B'â™iJ°Â%uÅÓÁ‚6D)Ø©sP3îÁ½é¯ìDå8ºìú(ü“De¶Éº�MžöòWªH„Â&‚ιÓYv¥«¨Ýi·2zôÐèȆH±Yt ?¥ªÊìrãs#�yÍ)À }fïÀ)Š’³ZA$dU–*�*$1 ˆ_S¸9¶Ú}åäÏ–8xóÒGWì—¿xÖn°õó"�P‹|ÆûúÅ_·5MfÖ[¬õ§!Ê‚7þ»ní'|àP[T‚¹Õ›vo³>/yEwÑ UÛ›šÙ²™¥.;tø¤ýÚ¸�|é vûÝwìý7Þ´k×oг`§!xúŠº’'‰™w_ñ†Ÿ$ ãç?´Rà"!N||ö"~wEg%´;£¤´šM¡+HðIV‚;AZ Ò� ^ãbn;ÄØ®hZp+h-L“»G‡®º�‰*¿VñÀMv¦P竺òü©ïiz¡DòUJ5UkdÖ‰ ±‘�V|B.ŒÜ‹ßç¯ìB|4Àãïêds+ÖOÊñB—qÀ�‚ô.–Xõ+�"¯¼ù@k�þ<ÓÅDI‰%i „¥°.8/ n-ÀŒ& wºGz¼‡_¹|Í^¼7egŒÙ{óÞ°vØÅIŽã†O|çÏN¶õâÉû.Ö^ôÄ0�Hk TJSãZaØÁ"£®¶[ÖÝ»Ÿ÷ÁÓÑPÚà¨ÇÀ[…ݹÓaÓ½6Æaã?wȾþÒmáúU»úÞ{v•£§îOL²”XTˆFºðL•,*’I—ð»Wù*Î×â“XP%´ÐUÁ¿"miü%ž›ûˆká× O–ÊdˆÔÄQò'§k»7r >UJ¼ Z0€ó_AÝ#Ü?}âY9á%Q…€·àȬ¼?å¹×N~( q3¦æ'_#FÁ*²òÔ,›¾¢7�² 5£ÇÿØ ÞüÉ€j¢ç¯d’°º¤¥yœŒ(«ÊD*Ôë4QIšc‘)á *gïXcbŽ˜º �_“a‰QÐÓŠ”Š?�¯]¹fÓ“Ó¶ÊàÝÉ}£6Áο[ì2»Êfn’€þ–çmòÞ=v j·a ée}@_ùõ²ÝW·O“¥uÓXÌ ØýÛ·9Qè]ÿÒ0ÚþŒ÷ªA>Ò•!Øâ¸ê‰û=‚vëµg_äd¢çìÂÌ”Í\ç«Ký(« ŒÁ"½ŸPä´Jñ\?ÜÃËII_ïùÑàj�92Á ²—ß•çì*Ž 9Í�¿âå$Aœc+÷pi¦WKá”MSÑJ—ò ZÅà Š¼ÖQ!Q˧¿(xÏ…s¨Ù´HÑ»LÉSÆÚ_Í0ôþ0óØÄŽ{•Dí�6–k’zê­M·Ênê¸"kaöx�Ç6™|4ê6–änR;´f7 ä$³ÝÚ �â‚$²,*ý«ê_Îa%Pƒ@Òµ¸@ÖÕ}ŠÈŸ0HLïÅwx¢Ïßy`ó�L ñù£'íÆ½;ÄS¼—ׂ~zdÏÏmÛS£'XÔÆòáMVnú+ÃÜÚ¢Ýâua�Ù\ËüVèlÐ#XâP‘Õ¹yFügmü@‡­­žõ× º@E0Ú+5¬Û–g»ìê†]ëY±�Þ}lR:jçžyÁž¡×±tÿ®MbîÞ¸n÷1Bff˜ŸÀɶzAï+óø² §~ö\™Ê§;ðâ¿”2p —U Ä "ïÎÆ˜\Ó91ÔÑ$ @È4½y¯,x¡mÐyÚe8Y$å÷"W“•ûÉ/r�„Ò›Ž `CæŒs0�7ÍÔó†äÑŸj2Âß F¢ôЈB# ÞJÞöF²I¯b-UùÝSzÑ|V÷Ø@Yl±ZEº"¨Q#2ˆÞ€•å€Ì9­‡åH8xDÁ“y�ŠxWA°rzg tW‰S"KàF(‘Ci‚)…H<ý£Ã9ú>xû{éìWí�{¼;göõZsv8Ê&8Çïê­[¶ÈfŸË|Ò[U§á©gÀø=*�ȯôlã:ÀÔ>D _ì¸foÏ޶熿À‘àÜMSƒ‹$òÊ"eß ÉL; µ/ƒ?`#ÇŸ²}§Ÿ¶£lU¶9;mm ÓÆØnìÁÔ¤ÍÍ/ðºÀ$_.Zr(=#NÉwx*��êØ®¶ ½ÓȪR°rQ> :¡ópÃ]ðÑ‹>PĽæ/ú…æ »Àm”eÍBx…"*GÍ·ÔŸúé_S‰o#ä4‘b\#Nœá�Ðjøêî—ŠØ0AurÁ1dI¨B;ÓɸGº{ÞŠN GµÍ[ˆ{jᑸîB~l  {ÇãúòÂ! ÚEˆ‰JV%çÏJöP³‚‚ã±*Hþ�ÚïE¥À¤hx7®É6ë Vƒ hдtS©ho¿ù޽ô5Ž‚:rÒ.¯ÎúŽÀîa–íöÍÛ¬ÃF^üÔЕ‡Núïnd4 x*0ñÞ¯]eúöí³s=öƒË·mz}Ù^gƒ�³ƒŸ³Ã§¼'ჇEö"°wíÅ¿«mœ κ݄öƶ#™í:h_õeë˜ß´Ë‹¶=?k+W5ÏîCnßâèª ›~ðÀØÓ~EF�ÑéMNÃùçNÂEÍá+ºN´ŒÛUÕ*V!¸‚N–CÁÉ6Z‘TåShO‰:¨0ð@–¯"1c«¯Bª\“ÒŸPULñPNñ—aÊÌŸôÑÍþª£µ£8q�UOåZ�šÁFD’*m{a#(s�¦•NåÄ,ð3yÛxv+!•áR¼ã÷Œ+3Ê”þ¥ý{Dè ˆçÝ3ÓÒ#DJqÄÄt–Šðÿ€r­£#=ç–—R¨Â‘¸4_m×uƒ§éµ·/Ú7_ü¶ýéìe;9¸ÏNö ÛŸð!£úFƒ×>�ÂÖ3Ÿ‚ª JŠWïâL¹WžÕøivvh�§÷áÃöàÚ}ßRlmsÉÞ™}�™wHãY[Úd¿ð[^ $NE›ˆêȪn[Õ6ÌÆ¤ë¶Dïá÷Öì'÷±{qßh¿õï?ný^¶Q}µ`¤³xÿ¾Ýºq˦&0 “6;ý€eʳÌ\äÕdu-f§!¿kDÙQ9 ‹»â)¥Y€Ü\Õ�$õÉ—$‰$ÕšåáŒ�89ž0ñT ;eI§ Ò*Up[c„�xú7$*^ݲÎÉŽœcóý^°Â¥ÄW€Ýé%‹‚éAˆwËB·á­ÓHŸGF…—ÊÓ]Ìý—ž$üì÷'`$jiT•p‚HÝÂxe®²VÀ™Éj�›0e)óžI¼ÄWl#nNTFx„„S\ÄçÍÁîõŽË*çþýø‡¯ÙK_ÿŠ íë³7î^³ ]£vbxŸ]}0É»{LÕãYOwI"ù×¾Þ5Ó¤ñ¾…°�ß?bLÏYçè˜m³¨h�w÷v*Ý{Ó—9]hÉ&gú¬oàœ cpøš,®µÈEl1T–$k�Ú}h’ñˆnÞ÷5Ëp…½§Úhø¼jhÎBûLö ÛWÏ�µÍgè°uTÇ]½…uz Ëô–d\àÕa~zÊæL3^Á|N»Õ¸‚JñYŠŒsT%îN¯;’±QVnì�JHòï˜Ys ‹ØÜà]_•ßš0SvdÒÍzQ1)žHÙk]@ Lžy÷X«ÑûÎ:™AG¬ ©¡JÁ=M4|z!.yÍÐ^÷à×ä–ÜwâGÜ }Ôðc=Sà–b£”rsI�Wã øT"×/™pXpHCÐ|(CUÅ*ô‘ÉRЮ')Ç¥pr”TaU’�¯,6•U3ù>üð¢½þW?²S¿þн~ïŽýÀîÛ7N?g3ÌõŸ£aÄû´ÒRCWzÑPšÓT!ŒpÕÿëó .^×Ó)†‡¬½#À“x��…~tï�}q¬ÏþúÃ÷lüàóvüÐSÖß;è¯2 î‚yø¹z$¯ @ÏÄbèVq¢Z¡Rß\Zµ¿¹Ï+[“_™×�¦�Ö=0fÝCû­ûøy…ï=ýÙ·ðhצÝ{0k| Ù˜ãkÈÜŒ­Ló rnÖ–ÔcàëÇÊâ’­,¯Ú*ej+u}úô=�¨.ŸÒø‹lQÆ•èx¢tTÊ®B?�tˆS$™îuTE! §¬ÊD|ø3:ù£#â4k36Ù(úZK"A·gR:nàDºÅ¯ÊÝ—¸uú޹'Yâ–è*¯ ¨¼üt«¢+�îylb4E‘(N—Å&èW·ª¬¡/("�Â3¥láJð)½ ;X£Ä ¤V¹’†ó°(Ý­KâÕ´N–A5 çÕÎSoÍþó_ü•ýÃóÇí(Oþ˳w17ì 'ÎÛ__|Ç嬺ò€œþ�9 §Nã“!‘Ìävfß~»Éã2«¿Ô5g �}»¶¶ù9›š�·kË=öÅ“ûì?}øÛ�ß±#Çìоcl"2æëôj }¹$sÊ­L”pªEÙÕD%Ÿ‹@o`ŠÞÁ܃†½m¶"Yéa´kO7;a©�>öC8>6dW{lkàr¶ûIGý䥃YŽmk ƒ®ð9”ÞCÇú¼­rr’ŒÂÒ4½z3ËüÉÇ"ù\_ÕxƒzZí&!¥ßÖ»ç!pDéºÃ5@AWâ�‡Jv·S= ÞÁ·ÖQ`# _“väÙÁ£ÈÖäêõA—4+E—pÜJsÂ’ŸdRÑ é>Æe&›É�î’{\ƒÃ*P’| ×OõøÀ%E`*©,wXooÒ.„?Õ:ÕåªR�uX õ‚QEǥʂÄt%^Ác î 4qpÎE¶ OÞ«P(S•GOú%¼g_»vÍ^ÿË¿·—çk6Ý;o7gïó9pÈ>ì´ýäÆe YOùBßÎH§¾Ú?Ð9Ñ褶?¹rÇŸþzÒÉHPÙ:ŒEF#£ÖÑ7`1(xp_¿½pxÌÞ½Ç7}œÄð ö Ù�±q=hýƒþy/¸GZ!üÒ¹@Š””Œ�Ë£Šƒ<Þñ¯} 9OJôòzcyÅÚ´,ÚŒ¯™*,wêe´qNB½”‘ÓãÖÅɸCÄŒÐÃhS×™ÞÃ=£“[kvƒ5 SS¶ÂëÄ&ƒ�ðÏñª±¨„^-sØôµïªÒy$å&aÂyÍ!XC€;é¹W8YW*ŠB¨öë³ôdˆ$o! \ x£^8°Â_›øžna(F�^­ˆ-¡–@ͤ‘|á‘ò6ð*¯$*o ñ™ï�oTk4Ü/—ÒI!Å‚za»‚¸ ´¼>×Ïa„�¦d¸<ʪJ otrŽÞ*�¦Öˆ¯ BQR3¾�JÀ’¬‹4!´¬þ¦Î„£Öÿï¾oÇNŸ° ¯ž´Ÿ¬_²ŸÝ»Ê«À vz߯¦0ìëïœ4Ú¯›èÀËÄ» û§¼©eVb4d½1"‹zrmLêÝÀ^§Ký+Ï>eSKoÛÄ⤠Œ3ÝxÎæ¦¬ã&“Žè�Œí·CÇ­³—}iÌZi¸«g�ú×=žRëÅѸè©ÉЇÍc¸ö ±ó�νÓ×I‰‡…Т|\�÷ [Z# ­dÉ(švJÝæ¨óû½]öÂñö³Û“¶�©ÔŸ;vÄ>˜[µÍ¹[à h0rŽ]’æØ,e†9 sèp‘КÏc€§AéÏï)®ˆ WP¨çÆ&â+ÿôy{ýþ%ûáÍ�ì—O>ËÒà›çi¦ò“T2Qê¨ë¯‡¢¿ðÔ9Ë翟N<ð§°7xÇ[8\¼áøm$Ûa?Ûì¶ï~ýçí_üõk|ÏŸ¶¾ž}¤ÑÉSsÍLÓhfîÛ™þyz ýìc8`ƒýƒÖËø‚Öñëë¤÷À”é"ÊiúuOW`²Ý’ßÏ`TëqrÎðë×}ðÔ¯}�ßJàe⋽´-NTšëܰɑ.;ÚÝg�k6ƒaX¦«ÐÉ^ˆ]G1Öð¬C9½¼t²´zsfÚ–9…éþõ›võòU¦Vßv£°Ìk„6Ëð¯)e�£j'E¶fÒO”?åe°ÔøÝ  `f=ðT7ñ‘ÝB1îÙ °±·Õ‘R[75žÂ;\•©dš¨ ¿5ê¿Ã½ÔÀq“WQ}Ï“1Í”¥ —_ Á];\JFÕvmÃD†£�„^úÒ9xÁÇël¤^”Z'ã„W®£DI>7ΕJN‹Ð °Úï&ßÓÿä_ý±ýö}ϾðôsöîÄu{wyʾxêiûë�Þò§c›?.i"ꈬõE`´·×wÖ¹Á`š¾çû+ y×€àÈtÄ»¦Fî·ÙqxÁ>dzñ·¿ü’ýû×ßç"£üÆf¢N¸EÃ9¾ÀVèyLòäì`$¾:j¼Ÿ%Ë}¼"ôõ÷Y7{v°¡M}ÿÒR«^‚t ´Ë/nQ>�Zû…ê:Rž<Ñ(ŸÔ»z yWÏaí>_Úö1¦ÀD©©6vRêbƒ�Æ^w´Y²×´.Ûë·õÃlýÜSvø‹›öÔâŠ-2ž0˲êûW1×®ØÄ­›6ËŠeEi…�—9å›íFáxÕ„/BùöZåý>%•ä‰ï02R‡•“tÎ=0Tމo¢”ØTû½f�üšš –ŽS„¨8ì@«ùMâ¡:-¨Ÿ5 cÿXîÀþ¿G–ŸS�:pØ–1_d�¼ŽÀJ%J%ž‘êÒPR#CÍpæé;M”*�L(ò^x4Xe ÷€¯|*ð\V�ÂuÒˆîO0¹æÎ´½xöY<±ÏnlÎÙèЈ�Ýo÷Væü�Ù–Dàd<Í©ˆä»É·xÖJc­ðÍ�OxsjÏ=÷´½¿Öc=½‘gàÞÈI=t­�Í6m•I>‹�ùé›0C£ãû>†EïÛZùè¯+?î ¹uÏFßÁ8Fe”+7 µ�PO!q�|Tøn$ M‘ÉKœÛ¾ŽžÛ¬w¦Ãú':mà^§õOuZïR‡uc44¦°MÏA½•6 Bïà°í?|ÒÎ^xÞ~á+¯Úè‘lÿÑÖ;€1`¢Óy\çsdt÷Q^£MK• ¶:Aó1­¡‚M­A\7꨿I—w¡Ê/½è®Y«€¸5ŠØ&�*_†Eí½ÐUž�, âlÿ«5T¢çd�g}=€Qß´v.¹2�9ÅÙÉ|).Õ'�T±N¡rmD— J]•ñ{ $ªî^Y*\1jžÆnÝbzí� »pôŒ�=h—'˜ÓØf´j�üÝÌöë¢rïã'‡Ç8R¼ÍÞŸ˜àI wç�ré}LÂ@IDAT”¼“Gý)µH: ¬ñ�zŠ~ß8}Ø>¸Ëd�¥yû…s‡í~ט=Xߦ;Ýo�ƒ#Öů£ÀÚØÄSº–1ðéÈ0�\pÇšmëÉÉ(ÿ6=ƒ&uóç³ÞÙ­Uëd?Äö¥Û\eè\=Õ5¼ÙÁ ‚R8 �¦>«ÁG� Ü , úTºÊ0HǦ¢õ8†[º–Û­wºÃ1ƒw»làA‡õ¬’–^_ºÔ3ضƒ¤¾ÖËëÃ~;~ò;óôKvê©lß±ãè¡›/&>=êŸ'¨¿4?ªJ'è^1Ý%eÖÊ,¥Š¦ 8>~7ÀITÝ¥((²ñ˸Uqxä—sX ˯*ãˆë‰š`¹ô(ôwï>fà±Çh÷^XWŠöʧÊÔ¨ÞŠñ—5Ï,•Ò‘©ôòxîóÈ€†4Q|›`Ea9'q 6º&¨ðm ;Ðñó">ùÁ ·ón¿¹Å2`æÿwP;»ºì�·Þ¶ùÿmÁþ›ßÿM;ýs§íúʼ=7vÔ~Þý†XžlÖ‹ ¼][ßæªuo¬Zƒ‡ôÊØ™PuÊÕ@vX©¸e]LBša”þ£;3ð$Ü�tȯ3:XùØÑIO£‹ÅP� âñ°«½› Gì 7™7 „XþÄ5L™Œ‚ÊSö{å/å\àD^Ç%ªèd�±g¹Ó†GPƒÙìcUå~Nk>Ùf7Vذ•õQtÈø2`ÇP<öŒ½üÒר‚ý¢]¼ø¶]þà-Æ ®ÙFÎù‹¹ ’eK¢Å Üê$MÔÉfœûë $âQ2%…¥¨«€àî2=âœG©¿ ±ô•XÁ7B?WPEñ*¿È¢øxî± €„÷n³W2Á¿d̳Xe$â<Ö3‘�QIXyDT–à&¨ó÷Âç05dç¡~ÊïŽP $ qÏ üÈ+CÐÎ|{Ý5²ßÍ'»ËW®Ø¿þ?þ¹}óÖ·ìô¯½b]§ûìÂØa{ëÁ—qw¿¯|@#ìf?@ÎÜà;ÛÚ2†€™y«Ì ã Ï©˜6ìßãyz+ßz‚ççÄÞœ´oŸ=bß{õy» RÏÖ§Ø ~�1HƒÕ‰EÝ’É¥ïuFÁWiåzÇ^ÄðÌ1sO+×´ h�'=½m]õâX»]z°ak¼Oõ­¹²ôÕ+ÄS†7ÚæC?0–áÒk‚oÎ<‰®Žn BkzI›{[¯õðë3H•qІ¨N¥^€*ºØc(tW‘–U¬Wœ 8ê²ÀXìœk³¾YW69�•¼ŒnÛS×0•wòE¢£cÌΟxÑÎ9oS/ý¢]¾þ¾½ÿîOÙ?á[dF€úOä5 �Íž²Ž€çöƒ�˾8FWlÓKЧGÿÑ+�aðG¹‡jãñ£ëû¥\œbŠ0¸ó›3ðј‚PÛíÌȈ�?©Ê|\ï³Á5Œ¿~ü}]LI.F�º¬â‹òU‰+0ß@Æ`Ëç6mX‡®2�y]>é³ÅL[;·2÷z¤‹›§_¶§Ž]°+Ÿc×Û?´Ëï¾n‹2ú*‚!�ü~)u%2°ÐY‰×-]‘�‡Ü%o�\ûšèäLY“a7ÎnHâúÝ)„£_”AÀ?Ûõ± €l•FF”»Ò˜[õQé: ·d´*ˆaqiZÚ�ºSv[�� rÁ=üy-Æ'ƒº75áЗ¤hX|$á)©wüÍ *j§*Q,VeºÉ‚ýÏÿ•½ýÓ7íßù¦ ~é‚}åÀ —  Ù{¡×[ó6�]]5p"²DO`–nººê+ ì­ðN¾Â¾k�c#U½ P’¿B{4¥¿7F‹�xl ,9UZÿUÉ'¼ÝÈŸð¼™znJ–Ò(“"u°Š»Ä;Ma^�"�¬ýÁ¢Àœ.üz:ÊeLá²Ç ¼’¸(üSﴚɧîú†*'ŸÐ:ü!¨tEõ)ê�7ˆºrÅ^|ñsöµoþ¢zú¸Mw¯±MØ,û ÒågÔ{‹­F­7m,»I{ô.˜JÛÇä¡ð6Yº»¶¸lƒÈ¼‰±¹Ç¨ý Vé�Ø?jϱ·ïÏðÚ@Oañ® AFÉ6¾ËMF•eo.4&õ˜ûyï㩹 -Ëxõ Ò‡ …dÚä=¾ckÉi!>Þ ù¬©GåUa‡'þZø ëÞ`¿Âá.¾Hh7"ŒÂ:Ÿ‚·øLçFãðîÝö ¯6Ë|â[%=½Ç¯v¬ÛjûºÍô°Þb�ÃT7Õ+ê²aŒÂÉõkŸî±±u^‰ô †4zmˆÚàRûz†vzYûÙÖ}?K£gùbp÷@¿-ðy53ÊÁ.‚—Ž~Î.œ|ÊÞyå-ûË?ÿS›ºú¡mòUÄçC”|ºÎÈÓ.ª€]¡»P*€˜|¬ I/å¶¢+Ô IVm�“XþS¡?¦{üyšÔ¦‰@ú È<€ÆgÀZ62@�ñlTy©<^‡àO` pð @uUM¬p¤^ªX'©¢ƒÁC®M¬FÍ€—’PõS3ÓõLÚéöè“UÝs…5*þõë×íÍ×ß´;ìþÓGe>8²ÏèÂ2AýHÑU�WŒ¤b¯xÚvOŸ½pê˜}Ägº» äµS™/óIðΡ‹Í„z 2J›tÛ;;ûi”QŒ!gr ‘{zÛmP³ñºéQôõ؇lBÅQš’GÆCt±Û�~›q.SÁI¿sv+�.¸0åw°·ÓÞ�]ô *�±nòë¿A¦*3°—5m¬_`ò´={h¿Í»ñ9¦�Gv›æ(5þ7píêgoÅÎ%{o{ÆnöÍØm$g¶YW@~»HV³.´K¦4¾¦èÁ뽨ƒ3‹Ö�¾Vz:mÙ¼‘Ðû:~„×¥ÎQ:xÖ:œ�_š¶õ……�Á3—9Ì»gܳ—ЇjÀž®�éæÞ›€ ãêèäý��¼T¥Ï€�-�¶ù xù¿ðD †8(P&éIáNyK¿«§T®J u6å T|òDT<”«@°õ«ÇR\=±ˆ*´ ìâ•ÒwFî7Ó.²«á–Zéè³OG}!ð8ùy×׆·nÞ²ßyß&.Ýd²Ë¶�÷�Ø>Vÿi×&_ÇŒWR8Sx—tÔ¾z0(§Y¢û·÷؈„oý�|û_ãéyŸŠ¿~ö˜]›ã «±ŒÊÖ&Û„ééKúîJVtÓS`8è@w‡ ñUãÒ4Ÿ›ù#Wµ,zaaܾ¥ Jž3ïGÊÇñá^f<.Ù’µæyN‹¾¼sk­BWO�­a(G‡ìÙ3§l•‰>Œ ô0˯“J­¯ Ñ[Ù²ƒÌ\œš%_bÁ{ý†uŠ…70 ×;0ˆ«ÆP(F€µÞMZü|÷AvN>43k]¼®,2pÚ>À—‹¡mÎ[X°!Œå‘Ãglèð1[ÚZaYóó$4V£<ÅI‰î•VÂë¹� Ãê‹ÊMBe„ð‹?Å}Ú¿š«|!‚4DËyõL@:W—þ+2ûe}ï|Wª¿l¡€†n#›u®Üçñ5’TJ(0ÝòGAd% $¿ù“:à…CüºREfT¹7ƒò+]ÿ¦�ùHg‹¥†"^ Q?�:|—•oßûЮ¾ó‘­²ëð0g†m„©¯<éy˜cÔ�U»‚§ÖéÑa{@ú£éYk4áÏзíæþâÉcv•5þÏ7ÿÍ Œ‡ª2ŠÃ68Ì{6ß÷лñ³C=vsŠFA£ÊòÈJ–ùô ulkM0Ž�ó{`‰¿ð4ãñ0qoL0è Åoò ¯ ^d™ q¥Ç0HÏ`…¯½€>ü2#c,‹±17'—¡D„-V Òåò€ o`¾lù.¯WYtt«cÃæy7Ð{?x2Õ€á(›¤îc¯‚žÑn»J/cf�S›áÑÅ+ݾ<~ÖÖ{ù¢03É+Á2t0W#›x2¨\DDøÊü¨‡Ùø�¤AßÊ(u^°·ÄK¾ùšÕjöŒX/ùkGïÊ‹ó?kvÂîó]ñ*_n‚¢põp€ŸÏÝ` r„} :§lŠ×“•Ÿèù w ØáÃg­}tÔ¦ç&}«4ÈY OZPÝ,•­ˆ‚:Rí­|Å#bçÐ iááH­…,bšñ�›÷øTì3±ò<‚Þ½sï¿°Ø¿ï¸/Ò`ØÁýãa0QàµðM¥DEkBJî]áõj'†ëµÒMñ”Ê«8ç+E˯—Û�®Užc�"Õˆ}É­žìzJ!²¢ÈÈil@ ‰\-�<µ!��OlSSSvõÒe»ôÆà½�låú=ë£ =Æ$›Q*û‰}c¬³ï²·¦ˆ�7¶ÜØBi‹ÿU*ôWÙ@dž×�%žØ�Ú0DkìëéG^åDì…?ýÏ vc„ØÞ|™…D6\†TÝ]u40)xãâÓÄ ?�•Ïžo±�Ø* ]2%VâêØ,wI_pÖèŽ,0÷ì�›æÉœ®¡�îõ{˜AvCWýé൧‡3û˜ö<84jýýÃ<{ý•!ç-¨A w‰|݆ÇeæÜ×@-¹â×…û˜ú|j��I˜<5­ýTNÐqv“;f½Úô2ç,ð•@¯?uÝE>”ÒÚvk™Cc™îUǧâ4€Y;Å' ·ªÑ+Ÿ&£1ñŠŸÎ¥ÌÅ@ÿu€Ò8¨W”­×€Z‰UŠ'²©«ûª\WžŒi�W-k8…²Ò ±éw´@ˆDÒ¯ç%«¨ËS;¡¨»¯_ð@¥‘ yˆ¢7xÅéµ@ƒ„2ŠÆ=FÓã.ƒ"š5¶ÚzÀŽ97Ø�è2Æàú[ïØÌ‡—mëî„-LLÛƒeûØñw� ÛÉ{´œÚ‹RYfÿþü¢ýÒ‰v]Ë…•Œº„T|í¸BÏA{wh[2mú,ˌ߻¯\¿ÀÊ]Þ%gS‡:­h«q•Ö(_-:xê¾Ë¡ªiPœùRžù4ŒT¤éb–IPÝÄŸ±È*7ÎÀÝ6ošƒù¥Áy©�ÃU:ëàà–>zMýzÝ=¥uZ’z¾Kxsdú&ƒ€‹‡»mŽ÷†A„¥‡tfá�uÓ+¸ËO›2èðî.¯}‡Æmz•½Ù6øD?Ãep ¹(ÅÕ>W§Ôç2úÝý.‰SÕ¤À÷«è">y?ìÞ#@oQ'T…Ø~ìÀc¬„%ùÐõwZiNÚØåT áÜ'k¬`=*ÔñŠS¸¦r3¤Z�çlæl•ˆ§üåÏ”">®:VK _.øáà§”•¶Ct¡±k±‹ïÝçO^ oðY‹êŸèަ1ˆ=Ô3Ыƒp˜ÍǤ›{LV¹ËÎ9o¿ý¶õó”á½xôÀ9ÂN@l+~˜ F69:lƒ°À{ô¾-^¼;i_>rÄþnRÃbRS4ùÕ#Ó+ôAÍÜšå\zƒ<»yRvñS/ÁÅWN*öò+ªQ­ÜlÃølÇh¹�ÕTU¶ã|{Ÿ­¾¤‰,Åù“NLq®#pƒNÝvõfd˜ÊKoèÝÉÛÏ$žƒ ŽN27Œ¾>`z²:Y“+ÍÂÐ:ùe�ä#ËÖÃÀ*_:ö“}~dïE>»®0ÏB½ƒNŒÀßUÿüþŠ½Æš‰—ùñç>¾u‘ΠòfeÀ‹f5¿( Â¦Ð4CÑx#ÂTÞôèý^Ÿô¢«/Zqׯæã¾LTÆ«øõ$Ò{¼ �7DMg¥ŽøDñ: î¥~Á[ãa Ö°Ø"_–ïØ­;w¬ã�·™õÇ B̆y_Ú¿ßk‘q˜½;fϼ°l¯ °;[�¶Áá:X�f�'«>=žæÓßϘø³ßYš¾ € Aþ´³°Òö!Dù¡`S­‘-Æ;5?@²AÛG7ZËwo±lY}#�ä7 ‰^e<ÅL´‚,óÿÚÍ{öõ~5â~vbÎ?ë&z�K½ÉÖ‹°t øqÇßÅ�âq�‹·Ú¨lÑLÍ­�a–J³ërºã+@ŸïÍ.1êßk×.?°¿è´÷�²ç™öü›»üæõ7ì/Ž^°»}£l¼²ÅLÂ6;3tÌÚ^ý¶ýˆù“ï½CO@e¥%ºŒØ^ŽH�×W‚Èk‰Ë ßUwB'Áÿ^hèU¸N�¿V�x2 à•d‡0MC��%P2·RBíÔ äüš(utñ©’QÅ £àÕí!4b’•r#Ⱥ멯§²œËÜ<äÀÆ%ÅR~”çúé@:j@½Dc÷�B1Ê×féÄ`aƒˆ{×üÂèU¡Ìdâ#Ú“ìœÓvE“Æn@½ô.3Š>Jï wL†á�õaºö´ö1æ pÐiÿ£ú|ø?@×1æ4ê ËDrÉÛOW¾¯“�n*ºVj5"Ce¥4Iˆ¯m¬Üfý�æñá»Áü Pê\Ø„¾”oבÊ"4äù+Ç!¿ž›Ò²04ò'ïØwŸ9Ç»y‡=\ïýaT%£^aÔÀ•Ö>vø6+F0‹¥ÊJZðÛX¹¸Ÿ½õ:zó=Þ):gìĉm»zeÚn1­z†Mk.žý¼}#ð­[oÙØŠýòÐaŒeEZ§�Ûæ—~ÍþžeÆÓ—>ò‹,N扔qÊiäÑï ¯G—‹dfí2y Mdl2ÉpÜ}ÂRrJù¥·ûÑCOÆxMUæ2ƒ{ ¢F!ù]-ç¡.x¨!¹s|.ÀšƒðSÑø�\±a]þš@è•ScSãW#®åOgVáVžXùqƒQˆŠI‰êëˆ,½îñ´�^�^Dçó4³œøE*G�óF$¼òº âƱÂÚ�å•Y?$ô&�ônçµ¥›‘în>i›°!º×ﲃQ7’ú0=#œ 0ºÏÚTkce!ÛípX Ï?h6ix-ÂO� C¿NÒ‰/ž}ä’§$&d˜†ú㛋žždS¶]’K2¸Ð\0(ú:!éÛµ[F~Y¼€šçý}£»Í.ñª¢ÏM vÈhzg,’ÉpRšn´•˜˜ÑÐÔëÚ†Núæh…ÉÞï4ÜÚ¶ÃGÇ1š—ìòeŸvÓ¶ÐÁ:|Þ. ´WØï±‹òþÐQR‹•Î �¶ÕW~Å^c0{áÖm7JÊV8e(]ÉX¹ Š·¸ðÕá°r‘ˆ¡¿*”žÈg„WuM~~RÂpOÄH%^¨žU¢íÓÕçÈÍ Vèáq¢ZÑžéT”G·0®qƒA„[  $ ~¯@tg«îkd )˜}Ì5Sȼ.¼•–¼÷à½Í`Sô âɯä д˜ ÂÚ„?`%yú�i@ z¥/Þ àL`œa»ñÛìkˆô(ôde5?Ÿ5ˆÔMÏ¡Ы½‡ùÔ¦�¢‡ÍLºðwb4ÚØtt›wçmpÛøô´M7ýðÀ–M3Áf�'·ïuHÂj”R+Yuç¢x=�d´c.aʤs—V9e="¶;wbØÞcÿ�fb„&YÑ)c(™ÅQLÊÏó CåI «Á{ÚE] åµ�õ Þ¦{CXîÖB¯½ðò ð¼fwØ«aiæS®Wí:‚&O½l/Lݰ3‹÷íR÷ˆÓhÇSŸ±…—ÉÞ\ø�¶Ž.Û|0ØÙq)™U°x�FÒÂ(H!ñ.ìD*wGt¿Ø$vÍRýR³Žú™.OÄdÊUuIKAe¤ß3+ dÅ-Jɨ¼Wt ¿pðŒ¬èÒSñzR꩟Ü3”Ú`\G<Ü×àë9QÁ%a¬‘š )EÞå¯J ô§ÁÁ”Y= 8«Qp×[J4øÀW%ŸH3è<¨–éšÑ]OU~¬:\b|�Ý@”œË(-ˆg=!}mèäd_´óP/Óyûxì¥ÑÏëEÛ±q›#¾›øâÚýÓ#ë!`àmåǹ’fd:Cž˜r.‘ØŒˆO¼vPûƆímzlüñêþ&*±F€®¸÷�à!Ï�C[TTG;Ø‚è}(É¡>¾0–°°*#Qt|Ú¥Év{ú¹£è�5 Ì^œŸ™°™›×¬ #ðúÁÓvhqÖ†˜U9Ïú=g{ÙÅô¹S/Ù,{=\zíïp�AQâúW¼ „¤ò'}è_˜­Ø-hpÄ ÜÄNú]ì+ìG÷‚‘>á*Mœ,gñײd¤cÔÀª!’¯"òX/œ‚Wסšpo_ÅE2<¦{B ‘¼©‡RöJ+i3¶!yäÕÑ+hÒíIÑ –7Ó#ù¥l¹`¬«žú2î zRpçµ!ÔΨ*œé ð0nä£ÁJ•%‚“Ûlhâ@8> ‚TູWñîWã�¡üäO<¼jU†¡ä^i*”iT†S¾1–ßf¹3o>Žàƒ’à䀲x\¼¿eŸ;1ÊVê³nŸXGF±ˆKs)ø¼PÒ‰ Í޳•Á¯Øñ§l×^ÿ �¢$ rF¹A O…é$nñ‡¾%µ Udí—üª@ÅSÝT8ÊÊ—dÓ kC·“ÀN=¶{l ‘Ú:ÿ)QÞ[勌Ì+æÎL{T¬Ôܸ¶Ee =Ö4™¢‘4ß ©wc)¢0MÂêþx”ªcíͯbžÂ&UƉ’\T IWïòºL‘ËŒQ>Tù£A˯”ï@¸;" C „å�´¦TÅþڱȟr-=9¿ °EO�§ª\Åð « žO<Ùg Ä"' Oݺaío1ÉêÚƒâæÉ—`/MAʧÙ�Iq1RÊ“Æôš#e«ž®c.=h·³çGíý·§|U¥^qz™a¨ý7˜T¤0ÊÇð0Ÿ?™Ñ=ßoÏ}ñ—lâÆ[æ T5>ñsç™Ö¥Õyl ¸%P�%9p!7£“·GD´0½n(N4S…ÅnM÷QC�mªÉ€ŒAÔŽ¢œ*W®°#¦ä=ó©ñj_M“>¯d ¸Ò„•Àã ú7}Õˆ†kå×j }¼·*˜¦¤ ’Rˆ•|U”Òû˜4 _½Ÿ»S#®h¡ôxòXXD}Ž8XpT-s Pmg†¯“ŒSœ>3ÌxÀ¬ëןøôu Ã.ôØßâèk€‘ƒÓ§_´‘ñ2½¥%$ ÂÉZ©õRǤ–[äÅ3Ñ' "wÓä-€ÂñÓõñÜ0™mAž¬®�J¾Ä)€ ^”æ•QäàÑ ¤‡æ±ÆQ%k>õ³Ò £¨:¸Ô$åºg„ZDf„ð6{í mÂ6*S0 ŽEH�¶ `•äÔ#O\%V%p' @Â¥ í’KK�^ÊNœÅÛ¨—�k{,‰Ä˜Þ…E¥"¾JÃcýB”¬E®VU‰OäÐwAOg_%f90T¿[?û‰o2r줼ð‚ݽð¢u}þ‚³ÛKZZìT.‰žðžX{ú܇Ùèô�‰Uê@äAJÉÁA 篒^44ðS›öÜÑA;<¾Ê²m–S—.½«�ND«*‡ö Ûõ)rO††û÷Ûù _°›.íØ¤×€Ðuˆ¤+¬ýÒÕÃ\K�Ü…Ú °x† ÝG {üûc€02[DTñúO�¯r± fé4zȈޫLÕ‚G`WXÝÇúÓ^`äµ®:0ó¸dô'Ü¡‘¥5µˆô±”Ÿ„邸(ÅW¸íEçP¯ÊÝ1/¹dŒj•ÜJ¼Z O}éÕûÀðˆæ˜ZH|e±Yõ´¦~Ž¡»Òð€àp¡®Iyr»'ÇÔ½ázšÉGr?Ÿ %bJ9—™é¸Ä®Ë÷Þ{›y jïŸ9o_üêWlä©ÏÙБã>ÿßB0É"f¼`‰îç,=}úóž(ðº× |¥©š@ÿú}”ãœÈ¼´¨±àíßxì{°%Ù:¯2š—À‰‘Ì(|Î9j·/òE@ï¡ÔÈXaë B0“ÓVå(X*³_ŒQNYÈ•×ÿ?Üc€¡\ÊVI=¤Ì(#•.§8›f(é’¿*R­‘³ùÔOܼ×X‚´†çï ²†÷ÈöÂ,yÎ(»±vCvUèU]Ÿ’¢âS;Wžx4�è�oo¹ªXz–+� ’Ï©ÊÅ@iå*J%’ã ) ~5&ýš52=m Qõé:Kݽª@æ†DòȨgB„î_–8 ôî[¯óŠpÜŽ}þ vîÕ¯Ú‘³Os *{’²Ï—@€}tÿ¯Ìñ SlÄS¯( ð½@ÀâëIy• ­5^.s\Ù™sŒ¼Ãî@ ‹¾ƒé�Ž ÛÝ9“a›•�ú·ãçžµ»W/ƒ+L½IÆS¹¦?�”A ¸húᤠ˜ õ ÀøK~�ÀE«%ñÐE¿:S vH}q¼«öÕ Ãô¯Ê„ú5ª•#�t’.1#ÜJœ�½·–Ô)|µKÅÛ€¸¸­µ†J5nM€Z¦Jè@èü¢µpöJkå�—†¨'q]ŠÖ˯¢Ä\ݨÑÞˆ•}ý‚»Ò•Ù §t£Ò—X$üñø�x!Å $…<Ú‚o|ŒiÐðU‰¹ñ %Ÿ› '¹ø2³qæò%›½~Õ®þý÷íØK¯Ø3_ýe;þÔ>ûõø"!m‰x�Ozµñ§¾ ­ç‰œŠw$áwç L¯Ó<ù‡˜Ð”ãú‚°Ÿ±‡MV .3¡H ¤�%Å2�œ–tüÔ3L¯þk?sQ=NéÑçB{`+¥½ùrv›ÎCõ…( _yù‰W–G“öQý�m\±˳„–À� :ª ¨@[•Òd8ޏã¢÷/ŸÐã•D‘ BVSÖ¾,>>¸ƒlG°Ð6eMP`îS§ʧç—Å­�¿5rR{Օκ¢Dõ´­u⥹‡044ï–­6§2I*[ø2¾ÂqÚÂÆË!M‹xÉ_8É�×M‰žöˆI�e·JOOe"±~žº¢ö2ŽiÔ‹Œ|tïÿ±[oþÔNåí¹_úU{åÙ³v‡Æ¯ýXNà©•ƒ^r“°,ÖÔzP�dr<`œñ€7Ölü([²-�p>˜}œêˆó1¶}c~Û¡ˆ¯z ‘{n™×–.šõ i‡«J¢¦jàJ_µ ¿×஢:ò3ùÛ(U)Ü ·Ö|SÉžT@Ç�œC[¢’&c#Òßõeê[pCAÖ¤ ê��LP±;]2šä¹k7ǤۉÙƒRc‰C†Üð6B b°U�“¤Äx#óî~4|Ñ: —xî%·„ÂCùŽïV¸5>BJ¯<áð:.ª×].ÚSV`5Þò¤%Nåêl ¶§ä…-C²‚�!Ð+C‡Ÿn¤n‚­Ìó¼zŠàƒ'~”» ÜÒ­öÞø·vçÝ·lë·Çzžy…[‰�$¹›“„RV1PO@ K=²o }ÈxÀóÇG9ui�ÃWý¿¯we<~Úƒ ‡ËÐÀ!*=e7/^T.ùß]‰(®èF U‚dœîJ \å«<‚§n ’Cj¿�C4‚ŸÅûD €çC‚KÉ{f´)Z ìÌšC ­ë E*|uÙ4›oGDa½ZCöi/`ÔX/¬¤Þ ­™›ð'öî˜ B…nÅj„HäáéO�‹[!Ikg`ý¼–„¼ f>ÖH'½ž˜,7"’oaEd³ñƒSè“�ž^áãüÁãcdž�@È%ÎD QxîæëÒ×øÁ˦ÿv7àÊ/C@ æ[ìm0Íšý?þßïÚ™¯ËžùÆoðIñ�ºõ&d\<µ-ýú$(†šuÐÉÜí3 =f˜©øÒÛ§�=ÂzàZ©Þ�6i㌂��A;>~‚×�.Fa"‘Þ_*…(SY³ÄŸq~ÏŒKÑ O�£e@<à Rý`ì8#?ãýÉ€LÜ¥‹ŠåyHÝx^üâ˜á«•ÑP�Ç'm(P ?ºü¡³&]$üjþ;ù¥x{¯JêQ¨›i6¹7d,(­˜„@i`5‰‹_±AÕÍ— 4Àçƒ`UE*Uª ·¦W±òF—‰=¼ñ“¶ –\…œžú®4¼ºë 'Á�Æï�hüª¬.gæ)¤sÞ¤C“v<½„?ˆ6SÑa,êÄa,;H}>a”ÿµSvéÿý¿mujžÿÍïÙÐøIÏ£‡ŒHÂp$cíÖ‡íg̨�§¹ü½ðêÂhÙsÛŠµ±&¡ƒõ ¬?æx &éìò¡wÕcÒ.Í#ãlIÆ&&Ó:D&¤ÕÔ¥`žC¿Héj@í+qOåO:@JÊß¡F}$ß5^ ;’wÃE–ì;â#ؤL hò]Ÿ »Ñ9cÓS…½ªf¨ÉO)$8¨-Øy·qt»Žl�ï‹ÇfªZåx㇇n6ìkßûC{úÌiëGo=0ïFgíüô×› l2¸·¹Ææ¤,=Þâ§7Î=µ}ûºìÞü[¯sžßýg9Ó�>'é¨`¶º¶l K3,\ZãT¦V Æ8@kƒ,ùUÆ>�ûx®#]¤$ýäBî‰/­]‚…´^ü*LâòÐL€�•õ§¾†i帢w'4<?…x«Ü*ªV°BQÛþPò]TƒY’*õ|‡Jö¢ÛK6áQ‘¸É§Æ°¥§‘ºû-.h�k}iÁ�†„åÑã�²BL-‡]ëúI¸+ÎãUA.&Ê�AW󊰢äã?篮3N�Ûë´qê”ëšò,™|½-T«$u¼Ú¶¶>ã©ì{-òz°Í]sã5õøöO^³·9GñÔo�†ö±/¸ðÐÜUGZÜ%‹ºõÞ{WúD·ÓÝïçäá/²àiqžü2çò¹q•eÊK«‹6·ø€=ç0¾|Ðf­L]¶í[’ÐùÁ÷¸�?µÜ‚cí‡}íšþúȾ'`¢ w§Ü*a3ä…Ìá�Hínë#ü^ñ@jÄ5MpU÷¥‰ç26�ÊÝïÎK�8ÿs�ä”+¹%ä¡T±Q‰hzÇßd“ËhBI> _ "VÒ€6ÅmDC$Œâí,0�LQUlC?©8þ’§Q°ä@ é®Ä~„hl)Sbø§@OG†A¼C‰Ê#þ~ ¿ÞïµRÏŸØ>NÀÎÅôd@:ÙÅX=€w~ð}fî·¯~ã7´ÓÚ~D¥…«ÁË/d­)ï’ ug—vØ<€‹ì¤ª�É·>¸k/<{È®°KóâóÿÁ§fº\Ú‘xˆmʽ_Ž0Û$àé¸+l¹µ:OÝAµ/1jˆë§€+h(%‘Ÿèý± €téƒ**,¤w½†ª+A«ŒT�Úãæ¢oݨœ]„¡ž\ûjŽ­¾ hÀH…–HqÙ…× ©½Ÿœžd®±<±Bþ)RPmç_MSwýpMÕöŠaåÙ¤8S™‚5…¢[B ™R´Äw´&näC�x×U2…¨ Å-Õ霫¿'ñC$…�͉ÖK´*ªÒô�@4:õ¢7 9|9`C“ V%~𣿵SL:÷ôçãS*ŒÁF¥ƒQU]ÃçuWîÐh'3ç}Eàü g7Ðð—ÖïØéÇl~Q»…ü:Ëp`�CKX$$ 9=/‘BéZµ?pëÜê$ ^D7)šØâò<¶�"½‘¸Qõ\¼:'-ÕÝßõYâ(%—Ü:Ïdç÷0íA±ƒñ;RÍàÃ0iƒÒŠÕJN-wȃC4Ur ðé` §æ:©yU¾¦Ç™´–@­K¾ã9Xd.i;lϧWÁ“$Ð'¿„Ö<[rTá>×OÑø]Dg£´øWcw¼J|~ž;ºûþ9èõúzúoj¿D„Òl?-C^œ¸oïÿô‡vìÄy륯ž+õ%Aã*2²23ô8k Ý–·17®ð´ç€–Kéï_ºk‡X0~p�mÛü³`›ö>`»4í»G‹_JïÏE\êpå«p“¦�^¼’/\Pù�Àɧ³›Á#@¤Û'ã�H*•`þtP­�šû±üÛ9"J»Í„•ñÈ©û g#@‹KU´wœ °rw’Ï™:\á%¾ß“åÃðJ¼ç?quˆ|…MªGÁÀUÃß`€Šå¨�ÆïÑ ^Wy N>�Üä/í=À%´�£Ž…|Qb-h�XÁ¡‚>+J¡®¨ä •¤—Açç�  ¸ºø…w¡¸’�L9 Oy�ºkÔ_ýx5¾vÖÃk#Wíñ·Ð;èÐ+ǰi�P¨Ðß¾ø¾MÞ¿QøD6ÄÓJË!C²¸ÊH~ל½qí#»?{‡¹ÿŸ¦±'Y~ÿÆeŽoã©?À®ÊœnŽë@�Ð#9¤'0÷ø…f—ÌñÈž7d‰{†kák¡jFÆØ)f™�ÄgvO‚GI<š“^¸äVEÝ6jA+7}Ïב[zßoqÒ’;§Æ'qVvUª`^P?ÍÍ…ª«djP‹ÏŸÄŒ*³V~%T²PËÝ;óŒ¿E_Ö¿éïHÐóZ`u45‡×Ð$­ ÞªÓ’—zì�ªñS[Õœýå™ –y<¹J§$ܦŒ\v¿ˆÏ´ H\TBü�lñf œ†¦Í0´¹‹Ãe Ôk”qàs`¿N¶óņ)ਰÙi»ë 2è]�¾T5Í,ÂnijvkêŠÝ�¾jœ:|ùîù Báê�ö­�ĽyÑNfýsº9ËQ8êi¸aR9H9ÜÜ�$]íKˆî»¡‚TÁs¹Ë1"¦µ°šŒÙÿد‘bfHJh¸r%-PÌá—õÜáøSƒÄ;C*žâx’5zCaÉ!ùïu×H=œÐ3É÷å5¾Ë&ãÇìûÌÍ0F@¯-2 ~Éš _ VÉ[yˆÚÃytâPW]w‰×J}uÔˆO’G½?! d%Mþv‹¡§¨æñ§‚„Qw�B‰W”‘:©9í†ÔqM_C+ -í¦Þ¡lXhÝ Oþêw^±_ý£ÖÑË3¥ýKöÿõ�lbâuQŒƒÙ^ü"òã¯êæûæ»@uC| ZI•2ŽÖ‚Û(‰¥ÙA‰_™ `-’kU^át„Z-MÆV‚Tø­œ\^!¹$’¿á¼?à„5uå× €F§Ÿ§>U³<á*ÜÂ3ÂꄎÔb£ sQÆã¦Í�U›œ½Í&Äô 8Ê\ TõPâm11ht°Ï–(óÉyŽ81‚h*ròBXb¬ÞÚ›—&í;'—mU›�2VË‘•(ñE‰(H\äy¸suîRò’Ï­ó/å¨ô£¶®³þ69ˆP­—õîŽ Ùƒ•e›Y^a©°Æ>”~xÔðÔ¸»1ÜI�ÖY‰Þ“ rku‰CE8%Èÿ‚T4ñsjBqâ»#J!Bp¬â›e,gò}B*;Rxxð ä"SšÍ§‰!üâíªrªÌ… Bx‚=óQãÕ¾�£gdŸÇüá#ÇìŸü£Ÿ·oÿòd§‹·ÙÃPŽŽ^_çÉÎI7[kôéU£Nväs… )#‡ûì·þÉ);0>hõ'oØôÔ=—W•Ë_U\N ªU ‡Ö—ŒT÷”¼gP®é² l ´‚ ËZ™^EJâåRÇ =ĵŽI;ñ‚—„vÑ×Qâ–NØNQ_€<¬ñÞÌìKEH²s^QÝ «`–›L�9Q˜~�ôïœ�šÞ@IDAT?vÌ:8éx­�\Û:ÕKó-¤SÊ~lˆ#ÎïxWEe[ç;ôä�´’Œ>Õvôö[;‡¢ªg ™K³¶¸°ˆÐs¨Z÷"ò%Šl?©’ÀW|8ÂñóÞH‚ãþØ@Ó&õÔ×rÍÚIä»]GºOùhq;s´Óú9òNª:\ûZ¸î ¨ñ;~Òþð·Ÿ·o>wǶ疙ö¾õ b g…-¡¦Q®ŠYU/ Uo©Ê�”5 ýtÛ*§ãÞ·oýþ~;xü«ö'ÿæ »úÑ%ïöǤ!ÑíJz@•Bê �©‚zp7q@’oÒpß�ªJ˜OñJLOÜŸþŠO± WòºGð‚Wñ˜SBÐä’üüžG þq­i*ZÿÔM²ôWxðŠÔ½�„çú“GèO{`hÐöŸ9g J›í,ÜÙ\ÀlÙ`_/çr‚Ðܼ !H�l"%YùÄ8fÿa¦±íôW8m‘Þƒx®.éÜN°÷ÅwGEj%Ç%iaEÚ‰ñ¡�‚›Q�yohô³qÒ(«EJœ÷dç YÀ:bwvC=É*Ò]OeêL½å®õô'O�¶ú{ÏÛ¯~ž ±Á9ñ}‡ÙØá»uõ‡œ÷ïûš5–•+ÞgU< ’ïå)?PºùÛmöÒ×·ìþÙ—ìË_ûçÒû+@V�H|o™kÁ‚»RˆŠ¸;7¤ò$Ïà•O•�â”!%º#SSªcÄÎYæ¥YIÅ£ð nŽäQKÚ…µÃ J€”Ní2¾¢U½áI-×$K⥴iÔ’@xž—$p.h‘ðaʸïÈIã¹OÔ¤y@µ÷ÙàÇ‘_bO~©ŠÅ}¡²Â'Ô�ÃI»ÙýG\ëäUpþÁ„­°tX_$W-«$Š_ä  䯓܉Ûù“*(GOq›WÝËŸ›]Ç}ôK”À£ÓµPd!Ñ6Zkž2ÒâB=�¤ˆ–œ¶`î d"‘Œ›ü¡yO.tû±ÞgΜµ?ú½çì›ÏÏÛöÊ]ëì;ÂúïYN­]´µå)»uýM޾¾€Tâ[K…0¢lP#ÇþäàÁ²>cÇžš±ø?�·ïþÁ/Ú¦‹ºš)æ¾”¡®Á©¡zÏNæ)ñã^AÝ“y+qª€ªrÔN5XI­ŠºËaˆõª¡¨¨B€Â•óVß{J¸ v>I¥O<-!çJ•Ž¿?8«]øké’ã§kü4f*àȾQçd¡µ¾Á8Ñc½®ßv x9°Ë.Mr°Œ:Ɇ®»åþ:zX€Ä >亰íËsö`r"61uÜR[²€UyrXª3Z|ÓˆÏâå.hö*jÖ Üf:»8zÀc¿DRµ`�<Ô¯õEž+¬‹8!Ÿ|¯¹Ô¾‡QÁŸ ­w·óçÏÛýÎÓöUëúꤴ žà|ø7|ÀO›CÎL¼ËZïq> ž±åÅË”€z7á”–ž*}*fñÎÆ4—n“饽C÷웿{Ð^üÜïÚ¿ÿ—cïþìxÐËðFZ7ö½eÎÆ[óT”VqNÍ'*CáJ`5¸f”GÔ<ˆ%ÃV¾ ÕÓ²Á °è ¤º…§Æ+ÍZ==Z�§HdÆ{l”�ÞÇ6~!Õù*ÜXøz*Oy(c�õÜ‹Ÿ·çŸæäáAëgk¯þžNNb�Ï‚û{mŠ)ÁKl!Ö… jð2бŒ¨È_ñ :õùOó¨D�tÿ7g'˜®O€2 ñôIüÒÖ­6dÔ«,Pº*Êç Oªkf&ö™î^ìPrOa#O%�Åù72çaE6Ü}i(u'‡ÝÈpTãG §Ÿ~ÚþÙï?c¿tž.ÿ �Ÿ¤:{ÆX¾m«‹Ìó× 5ò÷ú÷éÞ qÒ,ÇWÓMÌìHQú•*î=õäTìZÊ;È@ÑSÏvØoýáÓöëßû§Èœ¡¾kóJu�B5î)—ÈC3'¡ƒL#¯»øà5¥¶š\«Þ@"¹d,ÈêTŠÏo\`„œ"bJ¼Ëˆ_Áʘ¼+"üäO<à—ñ+VîWù±ü;Â~ã’F§ÆVÞ‚¢pÒ�_܈up¥Æ©îø™çŸ±—åÑûA;x¨Ë:†¯igâÎÊŒýlú¾Ml¬ØjOŸ=ä�ù¥t²�Å«@˜øÌ‡u ‚C=Bön†îݲ™¹%O/v3Bœ"ŠÏPEwùœ»RØã(]��„pwu¸°¨ {ÒÔè�â{B=%)åefw‹ �&sž‘*7»q b#äÏÐøÕé}îÂ3ö?ÿîû≠žü3žzßï;†N±¨ã †‰FLÃ÷N›ò�ËÃA�ß´Î�7bi)�¦ÞÕh0kT’§g#ÉŽÃvëþì»l?ÿ+£vú™Ÿ³þå {ûGØ,Ç\)_úTìÁ[î%·žFê&ó\jiè7Õ’HIXó‘lÙœv`²€ð…Ç#CàíÀÞ¬¹Š�"á@bÑ`šÈ™z U!ÿÖ/ÚtJWtFT‘FØ£CXž± ¥—šNœ?mû_yÙ~ªˆ¯ß 2à¹d÷à@Ÿ-²è_\¿gß>yÌ&ÅŸàSÀA郢�]d‹[;=¼Ž~uÿI›'o£ÿ7nÞ´%–˰«ì¼ˆHG¹—¾¼'‡ ôÉ-±ü¾˜º«q$ÿÂkà¶à9¼DªÛ_ Z@¤CùâZrÒ`F\! ,0<\€`ú+ <�Ÿ?eG~þU[K׉¿2â}jtØ>dï5ÊëïïÏØ«O�µndÒȾò §¼ðtL¸ÂúæßÕO÷# µ]X†­‰ÛvûÎ]/Õõ5ðšùÈÚQ ¿t’:ðÁýî?ñjd3ÜåÍ«ûBh‡>ÎåÉ€” J‰ ¹ ¢ßÞÎc¹deoAEIYiDJH>É·õî�‹w÷/¼ôœý¯¿ʾp„yýþäåjbOÇÐ [X¤ ×9æÙÿZ‹NÖ}fâ{05k½ýg¼—ÐÌSÈ¡t™ºNdÉéPÏQ›�¿S V²êµ`•×ÝI{îå ŒÀóöëÿý×ìü ϳ�kÊˈ©²(Gs5©YÄÏÁŠáo‡Kä"T¹9R~ÒÚECl$¡˜Ú—é·hwq“$åå|7R—ŽS.³Ç{?ÍŒ  MŠ æ“™Ä›°GE¼05çB«3O>sÖŽ~õ+¶Ä¼w‘ÊC¼ªS4ân~×f™ÝÙn÷Xÿqyþ|î=>Í̪݀�Áÿ×Þ›Çzv\÷�õ¶ßÛ÷î~½/d³»¹4ÅU¤¨È¢[¶á‘3EPf<ã ã?æ�Éd`xH$ƒ OØ’œxÈ#1²cI\¬…â"ŠK“löÂÞ—×ûÛ÷}>ßsªîòû½Ç–ØMŠ^½÷»·êœS§N�ªSÛ­[W<š::¬b×6?†Ïœ 7Æ'1|B)E#6¹sEJ¼’s©ýjùŠÞœH/g×aºxãïð\s9‡÷ë»õÀe�’*yqæB¥{ųRÊ‘%ŸQ¨@Ä©@ž8”ˆ«Ö#°}÷“Ýþ×/ílºÌùïœÝž)W½,ýuÛ¾ív’^‚7ÇHC¼­÷%a)¥Ü•ó/p|7ë½Àó‘€á�« Ø]ךù”ô4‡Ij2‘Tb}$K‹Ó,.…G?[ ó|0üúï|6ì¾çÇKµ�£²JmœÖ¬DªJæÎêÁ”–c\K~„xþoútñªŽç˜ QÌø‰Wäg0«=)M¯ÀYTÀ$.ú 'j�‘QFOÎG‰.7þœ^k*­ Íï|àÞ°é¯<&¶ÞòwŠ,“SOxôÛÓαßc>êY#ƒ#7Fà óû{¶æëZ�Ó½ŽEÃ&Îþ׈@Ÿ¯ÐûŸ?s†ž¦äÌdt)³°`U?ÕEú*œÓ èùõÔ W¥cõ 9ÝÒï­ïmàAX®›„£¸ äÊ!‡éªˆÅ_ŽñÖÎâ�+�R4G9AêšÂ§=þñ—¶…ûú/aüçœ$M FÜØº‰9Ü Ãõa/Hd�„*(Û‘‡ßÂ+¬\<ýcÛÐoU1ѽâðÓˆ¢¥y«Ã×øªÌ¢ã‘¯šÎ†šK¡§o8<þk­áoþÞÃá×~çɰç #‚ö.Ï•ÕubŒuÁ% ¸9¥ æ¸tM©Em%ªe&‘Å{N�‚àâÍé*fÞ'I #%E'ÉJQ³4lKåÇ`ÄrcMñSÂÆ…¸)ºQ¥€âÄaÃ@¸ëÓ�†ŽÇ £}0~\̰¤²�4èçßw‡'˜îSb‚C£´^¾<ö°cpSg»}sAp› ±¾¹™€Í¶ø×Aï?~êë;CÐi S2lÛ `†š w®ÕáøÕ�8À(„Ž¿D^Œ ^‰“qWT�nÁ÷{Ï[t>w2ýëRr?�„¦þ˜)ç³Z#U©�m˜×5?óØ'Â?ùâæp g�-½<‚ËŒßÙê5Ñй“O;«÷wÙtÕ±æÖ[Ëoœ#==Åìôö¼ZÚXRÌžâ60âhjè メS�0“A=…ŽÕΆþKã¡·8<ö«­á‹¿÷@øÍ¿ódØ÷Éûù¶]¿I ' ^ÙSÜœWÆ´(ˆ€R Ù³rNši’Ä#e¡Ì#zÇ¥«ŒÏ PÆŸ€ñî«Ý ¨ZVEL4ºëEýäÍèœ_Ë}vå’àFʓޱhm©„Ýwßv}î3aùàýa„G}|÷ò)¥³”…µ÷c3Æ=<·Æxô'çtæ sZ¸>ÆzÀÊ�’‡Þž È&mþ¡ñâNh»r)œ>þ®-þé%1åßæþÙ‚®Ín¬^£ ÊÅŒšô—r*¼»èK´jTÊ ŒÌAÎ%F¼¥Ûmz + êu¬ÊÀ{J�R4«T»U£ªÐõÝö'Ÿx üÃßî»Úχåyú[œQÅKdlî Óõ•°09hC|1TŸëJÅxI_üìÙ0_­<'™„Ñk‡m@OÏ.žíŸ#‚Wêõþ-[ÂüÔCù¾7×ÈË'|I&Vz)C<”F.RôGƒã¡§·><ô+maÿûÃÅSÛÂÑׇÂù£—½ÍçÖIŸ(8;†ÊÃÒ½Wqnª¤UV‹nQJÅs6Ρ„,TʼŒK–®Ò'Çêý RxíHÔé®Äpªðîãs­¹ÂËB›wn ý÷ õwÜ&9˜s›–ij†ázƒ �8Šæe¸¶wu„W®ðôGpè ‰X^®pÐéÖæð8ë?:~šá> ƒZ# ‡ÎèŸ� £ÇŽ„sW®AO~T/€k#‘ý©Îú&}–“”¡t"ÈAI²•1*€bt“½vïãzË €*¶1Át‰ž$¨Â™ ™gIKÆ¿ >i®€RA7ó\÷³O<þáw…íMg8 RFƒTBFž–,«ïu»ÂäØy,’¡:Æ*¸~Pfþ$¢Á# ßðBhmÿ-v“�…y­+XSš+Ûxè†.Mðh�^ež (‹¤-¾–ÿÈT�d–ÒB¡™dßJ}Øÿ‰Å°ÿÞMajü‘ðü�ß—Ž …ás| b|:ïÁ$©þŒ7wOÕ+½’3gÌc¢EPô;�ð1ƒpŽ%ÞYENñ2–.ƒÀ¨ÈCP{Þïý¾§$®N]â (ç–d�žxìV©„Þ�M¡—iÒ]Ÿy›µ†F'‰+óaãž�¡Â«ŸõKSà¤)n�ácêVaH˜½rÈZïˆ2œzh9Ñ©>yßD$,±¢ñô áλŸ ‹‡l@¥ÒÃhƒ¡&OlqâFJ§“ý£z;Rüø%'³U¥õåDUq9åC�«4·l ›˜\i½ö}n"ìylC¾8®ž˜ WO‡Q欳|ŸŽ§Êœ=㎠�8™;~º¹+™[„—œÌ…ÉâDObÁ=òI=|‰ F6¶\âÐ?É�ç3ã’ñMƯ§7êÅ55kc�¯gë–ÐsÏÝ¡éà}avÛöðßãûF¹c…}-Ç(‹ƒ3aË…}íáÎqF—¶‡ë§gÂ�3m}e$Ì�M„E¦;z$&‘½B¦Ü¸æÊ!ÁD¨{,€xÄ�ÇH:ðÚ–p1ª3àZYVH^ëân?a�[òy(q³a» ×Ti ]½=¡gçŽÐÎæ­ÀvÞÙ Ã8£í·ÔþÅ‘©ð«ýía„•øiò¬òÒÛjhM…ù©,* ùžG835^�-£-’R?îK=9zGf‰­µ„·–çöÝ~xñJ蟜s‡…ÃÇxËS±eü46êý¥gû³´+ýx­öZ8�.‡$Úµà‰’ì$Ò²ÔV�—QülžÛÔHªCôæICh•%«†(8+C�¾fØr8wædø¿þ˜óÛ÷óûÃÞÖ³¡ŽW{µÃK¿EöýÏ\z• À�¨z¼£ªzèÔS«r˜?Ч”ª×F®½Íë¦z_ànºþÖ07yÌŒ›mc,Vx|„QcÜíM­a†Ç|jltæœZëe�Næy1e–ó&9cþw½‚¬óæB{eCb°»gwØ0ͱS3œ3@ÃPGœ¶îq~Ía`_+ ÑÖ0q}{>¿FÎO„qæ¸S cø¨ýÒŠŒ[”£Ž“®­’¦Údúv]憜tK0Å'(LNWÔ}¤Å2d²3°DZ‘/Š÷¹:jA'-¼dÓÚÕz¶ „�ûÂGn/nÙÆÛ;Ùa©’€V+1ôçlÏ×ÇgÃCèáÇÃÓfÔJ2“Æ* úîÖÆpinÑŠŠ1p:kˆ!E®†Ehš‚p�]„g)»'z:Â¥×^ÿé¡023Ã!åóc úþ ò™†ÿJ<ûIZB.¶²«i& %O&wpÇ¢3šB2Õø"íûñ߆à}ˆ$�gN�� …§¾ó£pîò}áïýæ�áWv¶²�÷jXiê¥"ðL˜7þ¬ðHNÏÿÕ¤¢Q¹iH­´TÑ5rHÉ f•�F—Ï>:ºþVhgQ±gó}¶[L-ØràŒu £^^c:p% 1EY`Ⱦ°Âùô¦†¦jt$µ÷DÚG¨½eG8zêÏ8/ðtìÍÑ0|kÐgÈ‘Õ77~•¶¥i×òER˜Ë<®ò%â’Ü.£d—n *Ö–�:lïÖÜ-7|[}¾AM6NúõÖ3_#ZÁø× ¨‰’ ÚRZU?Ñ)}SÏŒÏ3%øƒÿ÷z8|ê¾ð»_Úv¶PQ¨˜KÙðY²ê†Ñzd¢^‘²F –ŠM¤~ž&´wmgz‘#¢O„žÖ]aaìu’e¨¯Ø42V>‘O'²,PyæIÏx"£«¬Ð_ŽžæáÂ4£di¢½<}>tußvõÝÎ ư|#’‹Cõ‚�Òqžêáçð/„¦&>rÁ2ysgCx|ïCát˜['ûiêÃÜør˜_³cóaf„¡-Gå-MÌ„‘avÅ1\^œ¡aà ‹eíNdÃFqô �›Ò€Êì8¶×ÖcÄ œ²£}ó�¬¸×wv±Õº“ý]áží¼ÏKFJ) ´ö‡k‹•0Ì衞/ä®Ð`%a™»üKìn / ó�?‘¡Ü†ì%hõ_Sªƒ0Šex…L%Ø�ú°côF¨ÿÁsáÅ¿ÆX ¨Ðˆ®0ï—q{ﯧ4zZ#IeŠ*Yñò[õµ\¸ÖCÞ¤1P5ÛÑÑNO.„9êb…0^b_å-V1>šÇï»Z~ðLxñ¹…kSÓœ ©~QòèäL;¬÷×ÈG�€žÚï*Ýçàä·»èkœòéÎó™˜*~Â(ÏNgy¦þhê)P“d{·èTGoѱ”�ÀÒƒFêyå·Ý­dñ9UÊhº‹ Úå ¨Æ¤°�´U¥m¢RL=«ìËK΂²EʺV›é¥f&ÇÃK/¼þõ¾þýw–ÃñÑÝô\œLáªZ*EUuë©ËÚ’=ÒÂocíê߇aò8‘ôs…¿¡ñãÌs Rzº)gÎS19¨’«…J/Ê�ZuÅimÚ®M_$}5^¼Š¥QÀGŽ]^ºö — Y/èÃ^׿çÕý2º+<½Ê1×{yJ²ÌÆ-¾)›¦,\ßÜÜ-çáÙÇ5/�–tP¦}�=ªôÑœ4cøö({2˜ó?8Ðm š«Rç.,‡{7õ„SÚÒg�”7ÖÄD:P.å<·)Q|=൱ÙÐÑÔ¶·0ú‚¨—FüÝ ì$޲¢Æ[{­,�æ Ò:Z¨Ä6šRo+YbIÜejÄ÷:žá÷ï|$ÌÌ�Qâž&ðÅÅI6atœ1¸0{ QÜ�Å"9É«E¦YzÏ»f{…ùyè ƒQ˜u�Žˆ£S£0N#ÐÇ>†öP £L;t³‘Ä‹vzå{1ÜÑ¿?,t4…asž¦¢¶D¼o¿>?Îê-¤´Œ�sÞ½ä/’#ËÞ®-á�‘±0ͳòÚê P·bDψøO ô„az× æ´o¡£}`×ÖðÚ¤¿@¥ì*®ñPÀ\® quþx$¾ÐÔð¥6=ÐÙš‰?Êæø„>õÍ >”[;Cù>F [YØÕV {ÛšÂ~î÷ñ˜ð!¦G3Ï|7<÷ôÂeŒ¿Â‰Nê–”Gxi Ð(ã§ðù¿ôâ¹O黂QÇì*™)ɨöBôò~.¼8触JÈÄɽ†Í/FÓÆ#Ó¾I¸ÀtMUûë'Ͼý†Ç|×[n6nܱ ‘ÿ{ê6‹l�¡­µ=LL�Š92Ñ×.£2�å8ÆHþª¸€…Ñ·ûÔók—'%Œ’öqi å‚·Ý[i¥aœ>:tíz8òîµðî•FŽ�ÞÌË9]œ!ÇÊ �z'¨­Âiè%§–·½÷ÎP¡Á˜šcóOœ« -ƒ™›bãÎnæó ë™Xé+ž"ãt÷±Q]˜CÅÓ ´�CG.L^e«éƪTqé.?NÐá…á°§÷Þ0ËñV³ >ÕpÒElŒ UoµǃáüÂ%“ÙbSç¤ò`æ 7æ&Â=Ý»ÃÛœÔóG*ÉÝGï_©ïïŒ3ò©k5T”4ÒEm!·š"é73,›µ¨ðüŒ>Æ92fX|€Þ¶£ÛVñ³|‹¹£ñ…�r§õ»[øAƒ mºoÅh»iPžèkµæNŒü>:k w6Õ…-ÈÒM}ibŽ8Ç´a‰wú[N Ǿýíð½ï¿ÈÉ@3l;fASÕ…y¿JŠA£-ë-Ð|ñ/æ-Ðs ÞT–Ä·{ "$¯PÊ«îj²È¦½r¿òµó±“9ÑEA¨×ÿîÄ™Ã'ûý:MvnÕ]b8¦f¼qÃ2ead29å|W(¢¥¹Ù.EŒݨLKZ¡Ž=°t¨ÆÇ[f†‘†‹áEÇÊóB#…I/Ï|Φ”4O/X$œoüäP8ñîùðÒý{Ó�m÷ïšã‘ÜuF¾úšŒË¥õ�&º7ÞÅÇC.!se\4>¬^ão‡Íý³À£�Ežák¯�Çm�z'wùÛ0xõî¦_¤eTf(ûiù]a:1§¹<妑…ÊTû&éi ƒ#K¬þ7„βòEIº”mœéW9òFxõÇ/„7O_´éƒ÷üh‰Ö\½#_‰Òãbm\Rg–M¡àd¹ö¬+£. ¦ÊUnœÎ‘éê±R½TL¼ÒNÊÔ) «Ç®ê¼4åU’ñ‘Å–z}’ê–Ü-7o�úü�}ûž>�p›ÔòÊ@+|îɆ))Gï)âMˆ@˸ísÝ*ms'Un�¬N‚6EZÀ{ ÕMÅ÷†@ SÜÒÉh@‘TÀR¬‚±ëWË?¼Þ9¼!ì¿{wxì¡ÍáÞ�‹ìлz�'V²% †¦VZ%æÅ-!ùgø=1#4,ô‡¾îûÙŒóxŸ¯{e¶(v¾\¯v—5n 7FÞ´Ï䆷 Å�d–áxá™�†K¼ŽÜï�½ÂÙᣌjØ`4ì% §®pŠÍøô9òÅ&þÜÐ5!�Èmg"�g3~Ò3U…"�&*üñ‰ á±¾ask/«øCakûfŒjœFŸÙ`8 ¢á¸`äf88Á@©ñscש;Œ¨…_SÃ*p†Õ�¡z÷æpŽÅ¿>>Ñ­<ÎѦÏ`Ô2ò+¸9GY˜�s_ä§²Q’ÒŒ­È“aM–Ó£¿~ò{˜C>ø ý>â±§:鳇†y˵Á0öÚOÂ�~úZ8{}Ô ªB<² -¥ÈHÑæü2~›ókÅ_‰äe�%H¥�Ò—OÕÁÐãM®èw˜CŒ^”¦KïLþpäp¸cߎðÈ[¯²›°«ñ$sC>6©‡ä¤¡Ç`ª?*8ë÷à­÷ÉG'N„–¾‡9Qvz¸€ÙÒ¿ÓsªhE¯G=¬ü_ž�â‘o/j$b|Tœ—‚^ROèâu’݇ûµ?àFå˜sUT�·÷݆WØî,nä—É"9™¦1¥ñ23…�ù7¼*ºÁW¡±Óá±Þ½ì¦›¡Wæ;z#çˆ(³Z4Ùë06�ÚhðZx¢�F¨]ë?ú¡C-ÆiÛ’Æßú›Þ˜ålƒIzðð'Yg™¥“xm‚½ú,ÉÛãCè5š°™»½» _¹Pù·Í°ez<´Ÿ>Ž¿ürxƒ{ÆÙð¤ó(oH1*MWyRD]°žßŒ_=¿ÒS'BšºD'Ÿ‡\«1`t S¤M~¿‹Yæ«ò,•ÁHKC“>NBã¨ÎL²38ö�o|£hÎïç¼Þ†@ ¯#ëï(í9¶Å¶ê%sHn.æ$†2-dáÕ=2|{Ó-CWóÉe� O5;iÛ|”6�Õj4 g× <.Ôas>u‚ê%W¬kÑ\pÅ>õæË7ÂñwN‡ç_:îxwxèáþ°w;ߘ«LaÔlžQéXj꥔.½—ëcï„m}†¦Å1z8 ]&Aº~úï¡óìfø ëúÌƉ‹Ï£�‚˜‚e*mɨ•þ“¬ܵå±ðûf™×¶òùòÞÞÍáèüqÒ'ÄS�/§tíNl»Ó8?õ|L@ÔD)…ÎÏ?Á÷Ûx�iÁ,ÃôŽÐÙÞZØíW׃Ì:)Gã¬3 eàsø4óé9½Ô†=O²¾K×júhtÚÜ~xéš=yp÷®ð;}(L³…í_uJÅÏ €9^ör®ÜÒê’à¶4t�¯ÐÚØsléìlï6%«ºKw…þ&Î*¯Ö²øŠpóx‰­Q¢49·ù%ƒ~*X*—� ¨œ‹Úî©…ÞöR4�§êgW¨es£áÝC#áôÑáùç¶„ý÷ï0=¸û®®0ÐË#§†éШ§$¶?«ˆ¬\?º>G^RŸŒAê ´`è?ξÿæô�ôˆ£±d”¢“ÝJÏÏ’;^£€ â^e�bßÀ'áóßÛ{öñú1ûüy«�õX"“âɨ•½£àCtÉ'#h­ì@¬0dnfŽßÌ7[ðWtÄx¹v`­¬ p[‰'é­Ç¯Y«×ž×ha±Òp§)ET¬‡eD)(OÊ‚-èñ•ž ¼¤4É¢à>Ó}€MUïŒÑ ßF«Zä#�hhDô¦@:q¿>PñÕã½™Yž2 L3{Ùܵe”#ᎾÞä�¾£ç.†)½ÀSåÙö}ÈøããÌ&z~­Y¥G}>)VÒe±\2Dl¬ÁÇ©¯ì2Ú¼\UÎr)òòŠÄÖµ‘QË䬯mÐH®¬46ýDô·ênKP_?te¥é*•vó<ÛD%¾öÌÎqVk4D4i!æÜ€ æ>ϩٔiœrõ«QÈSúnC !•«0ÕP©’¯°o`ÁÞú¢BXCà4öÉs†ºªtKLo®ž=®]8^}¾'l¿cG¸çÛý{ž ¡§c–RïçóP„Ê?;w5ŒUzCgç=a|üm`Ú¬ÂY­;yëìj˜£âaŽìJÔBü£xªØ6/èNòË0ä„W/wqê ï% »ûî =¼Ÿp�Ï›SuIG´MÈÂË8|³ÂÏŒC·3 ˜rˆNy_dê°ÀxRoêQä›~f�_ Cã|}x‹^´ny ZFðœµÞC‡ƒŒEÇl§FÆnרHÍ�!åO^=ZÜÁsìó“¼¥Hzjž9u>|é¾–ÐÇÂß5÷¬×…^š÷ÞÝ ÁúA5,ä[W{—¿\=Û?}e1ôÓðmåiÊé·Âzýc'Ï…!Þì«gž¯çû¶(Hšú3ãGG �]¨tGöêž?ªÜR&ªþÝ™ÇùåÀÞchÝëyp¿T¢!\âÙ[55·\ëj¶xyåZëJ8¹ÜÒ-ËÏ-q!ò¾}Oü9Êû--nê°W`Gynœ 0ËÙ YåÑØÏÇP%ÑÒ}�ˆX…Qˆ–Á“GX»8«JIÝ 2 ÿGÞB NÅFD[PÄ# œTÓÕ¿!ì¼k{ØpsØ +ìØÊsé66kÐè-Á�Þ‡xÎvŽI©l­¡©ó‘pìÚë W5Sõ‚×]�u×ó{4F¡¦P~Ã+‡ZµÂ€ui#¿–¦^�½Ÿ©Ër¸>Åzr�`|O½Ÿ˜4�qÏ3M˜cíb×#DíŠÓî8šõà2lý0jí”»“wÆGÃù‰ë¼Ö¬‚zã‘Þve#ò°Àh)ãçg~i5úYPsy�§Ó„ðÉ­á/Î ò^Ãï,òFåRØÂ¢åoÞ{ üp”3¬d�Öˆ‘_ÝåÜ8¹+ F†_?{}?Çó¿ãoqÈë™ÃáÂáCáÝÓgÂ5>Ý¥Å×Fz}é‚,_妊Œ]ó}ÖedôöSc¶–ñÑÿ•²; ëÂ/‰Ì�*YM$Ge41®(KêÌx©Îuôñ^OMFù(I=kØØù‹çþÓUŠ÷>·e ´ÉÏÓü~Kþé™i¦]òzí^CN •Q«üe•Hµr—©®Lf¡ŸÅøEèÃKç,~‘7†¦·Ô0"XäÑ¡> ÕÀ£¡ôÈF 0V‘¨X*çF<£—ø^ÜåKáÈ+m¡kS?Ÿ©Úî¸{SØËa�Á\Ý…pç†{øvÀ‹9<1B!jtäêWC"IÄO-¼+.RO/¬EÇF5ìBTï]!Žž“×ëq(=õ"S� ’ÖAS¿<ÆyM™¥:†æ ²¦$2L F=« ÀL?0ñQ�§ÆÂzq P B •¬³®3œšfÑ5-3’¨£!S³$“·†Pê´X2.¾´ ü—!"ˆ¥0Àžÿ‘YN3bK¶í§‡Wºd:ðæù‹áQNú±½¿ïÆjë6Fö²µµñFžÒ韞 w\½.9μöz8�lèQ¾šX”ÔN9Ÿë“>0míÕÝ÷ökäÂhLCòì½¾îPèb”ñ*˜Aâź8TWó)åלã#I„n²p6®HcP*ñÒM¾fÎP˜æô'95Thù ܆ËmlV¾�!óÖk]E+¾½ìEoâò<‡a(I7æWXr¬CþNºr•íš”[�\Zöç¼ÌÇÅ«”Ê º”-abC Â±^J[#`V£† ^'ˆFŒ¸¨²éYM‰=õÃç'Ãоøb[èd×àÀ®>VÙ5<¼ÿAž³7Óò” Ò…akë) k:¬NÃsŒ�©¹´XYGo­¯ -±°ºÀü{C_ �5ÏZQ‹ža²Lí±^ŸLô‘©ágÍ[ê™ké]�%å Oô)˜7ŠƒAÈÈå“Ah}¡Õ,-ê“ ©ÄjŒV€Bc`ÃLòF#8:xÁ~'_m/ý—×ÂSÛ·†mwl »ïbqï�°­ŸsðZ9y–ïÔ/Ý CçŒ?VàXÈ’qÛ¢"iÈpeЩ—vƒÕ —mº Õ/Lðí‚ëGC/£‹�þÝ̧Ï!?ñÈ`=ópõ¦röÈS žTÆ�ðr¢‘>Äsß9|÷Ú3D¡‘ ä–QF�¶Ö©q‚‡tdû"Ä>¶ûzC0:�©5ð]Œb´Þ2È�¦Z3P“#žò-מ�§Yøòýíá‡|\gc€ôË+¼J=úx­»�¯òΟ9®œ<Î_¸®��3e=¿Os|7h’°òZ^ò�õúZìÃðõR�Þ¥°5«µÆ¯|¡ˆ²&W4~ᥲ „ã æó •<Ù}-H-\¬I‚ïQðípYbó˜*Ù¦þÆôâàm™ÿ+‰ÛÖè™ä¾}ŸúÏèãq1žœ™ Ý=aœÂ«vòkG“œ²ž2«PI¥€‘.^p@Á[Žh!»XJÐUácPª&¶zIUò|Z ¾�?z[õ(�§Q�Ýáj;¸Äþfs\ŸDÀq#œ¾Î>^á4œÖî®Ð½¡; lë;vt‡m›[Ö ¼¸ÂQW¼ÙViä}öz½'/öµ´ìO&«^¹Â*}' M¼AOÚÞüIx¤ý7BWSŸí´ NQ+ŠcÍ€Œ™¸2Èzä3^À¬ÁÞÍIÇ‹à4«ý2–Ô£“4ù¢ºèÜCï«I ¾â"“°Ö˜˜Ñ‹2¶-­$°³{C856Lº6Œ”ñSN0KÓ£xòLø�{þÜÛÊK[MŒfÏ�åhô³áí‹—xmxŒ''< '®æî:°Ã YwtbL½|Ô`Û#^kMl¾O~l•b§õ8±ø­VÈ/m$˜¤¬1~ô$|â!B~-F,ÀoŠ2hõ%¥¨:&glµ´pÈÊäˆÞúU½”Æ—žúÁ~ 5ãÛân[ ið[Tøʽmfv:ôðˆ§™E2M ’²ôl_C~å°¬+•TTd´^sà·VþË •@¥@ÆÄ TÎWt€ÂÆk†Œßk°Q�ÍÅhÈè3ÉŽ*¿Ѫg“G•Pñ©/ƒz#þ ]f.rîÅðà¾'yÂð޽~‹P¦gåFvkZ—•ù%Ÿ$ÕbãÃÿ«×¯#¾pþ­üêåWh4§çãáO+ðjs­¢çùH@FÆæÙ� rò# ‘Ä» ô¾~3ômÔ‰^ԩܸL,42%8wîB¸Î [Cã¼ü¤åRF3ä1m‰UC¢a¼ä·_� ³Æ0 k¸o�ƒz}õøÒƒ È ÈÍMWÅ÷‹ßL#˜èõ“_3~âh„±`~ed›ï��J­‚E'N*&�>›õub2£€´^Ãtyºn©î[‰övÜ‹iß~aÿþO›,}AsûÞî~¶Ü¾f¼mc�e¯œéêÐÚ‚íTå Šë•ä/”Æ )—ª¶ #”ùdÍäÁþ($j Rõöªqxk�A^ºfJ:Å®ú7>¡��‡†´4 Þ£ocnÜÝ×z9:«oC[ØÐ×zº™:tÖ…];ö‡ ãÇXàE^ƒ^—ػ�3 öìÚËVÞ£–Nzº`mÔë뇡¤°ã2~=2ÜÓ¼?¼Å“vÊò£|©¯×Oέðtm_b=@rS+ù÷jFå_b¾´ƒ:À$6¼xîG¥³¸¹ÀÈE»ñ¦9½˜…­e~³Cü�1F‡ÇÂðø8Yå)�Z+tá�ç¢ñbØ2jlÁŠÕŒÓôžV÷1|MÍŒNq4ßç®jËü©ÜS‘Æa| /©ã²à*Æ/¾…î5^ҖŲPvI f'y-xSÿfk�ç™Ç(y“èµ�„)ßMÕ5 ÜlDù¨ÞÊà™Çñk¦&�3Ú”rL3òöÞK-´™³¥iÑdÐ2èT–2°¥Eâj˜m zT’Ð/Ñ¥» Pi[òfTÔ4§ÚLqº/mç0‘ÎÒ‹©ahЙ ô ­<>ëè>ÅÈ�í·]-ü*|1·B¯Á³öæ¡0vckhîÖWsÇCS3뽫´UÓµ‡¬ÖÂ[ékZ0к=ŒðmeI‹“± ¤2Ÿ”cÝëWXdgcÃâ8PiT[j5«cgP¿¶.ñ²OÛÈr¸põZØrƒ“Æ9˜ƒæuÜ îôl32¢×ƒuš”œŽP—á62¼—ñ™ÁsçßÃ.º¥ç=¾hÔã3™ ñ³Þ„ò(>fÈÂÛŸ%}Ê‘;å×ü Z9»’O‹q' Á"�•Ÿ—¢A"Êðº^=“{"wé82•.#a#@g-NÞàT'Ðê4¸ý‘ܾëmoX¬ün[ÛòÛâA‡===ÅñÙm¶UT)wòÃ9¦Ö‹bMò‘ù2�¸å�¨â âe‘ã«ÓN•@ä·BY…JÑ ¨ÝÕ,¨!Ž_èÔƒ.jåP�Ý-Ž$³ÂÏÓ÷Guâá’x�P˜gþëC ‹,¬r.ÇÁˆ_\Ô´Ç�7Z´rüBËq>eÖy·¥�)F+�yù¦Âι k úG8=+—Ñ5`pÃ탬ÙLZc`S[-š%o�kW8€^|…9;�'X¸äi„ÅØõlžÞ{Ž£ÀæìÝ{Œ›­ÄòÏÏó£7[´CÌœ Éeè¬à³+GªÐºEÑh]WÒ…ëR£¬e¨Ìð½�UœhøjTR„K†_¥gñËÊÀT­Ä-™¢UQo&ŸC,6Õw*{‹nó%R¿2!…»—­ÃM#B”_G§/LókiÕ6e¦Í‡›§f¿ãÌnßõ¶7/¾4æ­1Z»÷IDAT ?Àþí-ûèøˆm j⥌%„,÷–‡XÌŸÔS�¹¨äµÐ™Zs@0«�X‚¤Ò¨NÖb–(�•I#°‰î•Dýcª¶F ´•®ˆÀ¨PñZåeo� ©bÛ6¾¯†!OSô™ÓP—?µ5rÆ´·= Ã9És™bÞ¸‹€_"FÞši˜_Ãb›CËp4¬&]åÃŒ/ŽL”,=ñ“ܰVƒ ø·]µç¨ü�:±ß• ¶¤zwƒÄp2xÑ$#’,ž˜P�î¤Q†�Xðú0_�qÕZcàyóÞ?ñ'a¥+1J×2„]$s®z¥í8’“²MV‡%|â+5ärg!Ž, ÑfPKÏ뉓˜Þà«7ÿš;8ñøâeO—2býå¾ñÒ78¤âöºÛÞH¼¶ùé?™¨kúŸ)ð;¨˜zA¨‹Ó_†9y5W[uF¼Ú”¡‘:×Y]Z¨ ‚¶�CòÒ.ð̽%9kÙÀZ.¦P¨=©W1û7S0Sñ^”™´Á52 ¶ ÜŒœIºæÌ2X_LÄ sõnÆBbYMT]á5ņç&qT�Ý¢ßàб "Ú0½Vª'ÉÙF(Çœ{RPl5¼VϪô“ú¬a‰‘¤3}ÌL18z“ :õ/˜ãa€_æ ¹‚7�t—L5Zé9EÑ=ùórˆÒV7å[wåñèô�˜+`=Нr‰øŒ Xdž ,”2]fÍDo)2m>>ß´üU§¹ý×(éíg,Žwî~ô˼M÷uÕkžF:0T��æjÉZÏ·B°²¸*�J�ŒIõÌàÕžbAU%I�SÆ/1ÈÉ#N^AÄÇì:Òæe}ñæ1ˆ&¥ "?7‡P}åw0Þ”–ËŸ‡-m‰ŠùN2Ø´B8ød1À[ƒ"˜¥›aòrÂÈô(Á¢Z‹¤tE/ˆdJCœ}Ä]Ï E¢¡¢¤Ÿ~ Kñ’þäçGk� <—ÍyÚÈÀ‹ÚØ+‰Ì) tK¿ ¢|Ö½ �SSÿMÙJÛœƒñÆ´¢^ó°¡*%\Ô¯ëÇA‚ñï2óG€ÖZ{8˜¶§›¾^D*7=Þ\ùo¿õôW¾ž¢Ýîû6� §ÎîþÓ½wœ}†ŒüšöŒr°doWo�ñf‹EÕÎTõ]�Ë+—•�££®W ¨Œ.…JìSÀ¼9a*øRN$�”ûm„pS…·¼pw[sœ_Ýà­¢‹Žèš›§Û‚‘…E<3ÖœÆ{V¢¨!µ^Wé¹_ô‹l%,åœVLű4“0Áëxü'*KÛ|„d¤ú‰FN~¶`Gzš»+¬4ÄÏŠ×â&s‹ñ…4¼ Þùßš ¡œ�ù,¤˜‚º“·4¿ à­Çϱ…(¦Î7qò»ç¥œ è"/�òXH¥Ýq^b„€©BÔóœ¿�wG&xd*ÛÐöf¶Ô?;:þO=ÆsMò|0Üáº{÷£45Ô?O¥éPÅQ •ÛáÑë¹Â’ªÖ”&Gd¾Ì#Ñ=`¶sRF—B‘Âoµ…TBð¸«r0`£:à»b ÉvSÂeºD‹ ‘îD�h†p-:(«  g´º$‚ˆÈø%BÇÛÁ¦Y¢ÑˆU9ͲRe�L™�ÖÙN"goF#¾ÑHŠÔnÜ)Q0‰N´&ü ¹s;Ny¶xQ>'�r'˜€"�átKq#:%’ñs¾Õ”Â1`éá·»'ã´‘[©¡ða�©=¿â¥GÂ1ŠÝÄÑs¡Q4L§ÚúzìÝ�¡óƒÖ ø©Ú ¿ÿÔÓ_ûß‹q?ÿ:HOÍ,þËÖæÆ_çÍ­OÛT`Œ©@_ÄaŸÀo{Å’Iä…{R,¬<M)�ÅÉ ©T3LÙ“-p+À2^üÅ+ã—Ð ó¦ŠÄ«sPî«e�ã܇,x|è�‡€:}ÁÌ Jy•!Ç ’Zæ‘I&e”ˆ¸T‰åW¥”út@t±AHÐ`X…:Ao$‹Ú”¬âïÕÜdT0ʘ´šÁ…ÒŸ‹äL�­å<>XãY JñWAU_ˆµª×d‘Ú"6¿ËGŽ#Àn¦R|F/ˆ#mØÅWØua3±_µúª²†þzæ¯G³úÚ2oþ½¼ÔÜò/,ú|qi?àDÄþŽ;>ÈòG(¨GÛfÛÙ²ÚÑÚ†Çx™E/‘$­g²ä¢™/BQ ÔÆH%”aÊž¬ ¼*+Ö 2@æ1Æå�@Ô ¬Äà\ÒÀ骩 Û¿*‰\5~-”5ÆÉã{CºI†Œ§xçü«õ`[” í49%ÑØe¨E)¹ÄßÕ,ª"'ü…ˆ&c2ÑÙtÅ¢˜$ÛÃ1�œóÏ¥ÎR‚,á-FŒ–ðI†Œ›èIÆdÍh‹áSE'° &‘€O^„ÈÒÒ #_ ®èYùC ßîËH7*…Ž+ëÙÎ7xËqŠŸùÁfleeá³ßúÞ|Sl>hgEóA'"þ§O¿ö6™cs�[odžϱ' ‡5)׆Cø‚bá—vM¿bp—Ñy)¬I]â˜E*’;°•2�Eª )-X*&hþl¡.Ùq EPæ—"%(wô`Ó+t�ß«þAŠº½÷¯Æþ. !nÎ#ñN0Â0ÊðÎÁ%—ªZ’ÏóR ½G¹•èµàüÖ¾Þ,BÄW‘åÁÜ—¥Q‘ã ìžTˆª|I' ŠTÒS÷–ú˜ Ó£ã™Þ8Þýù°Œ_²~h €;}ú'ÈN§«–NŠŸeÅsÅöTf& sQ?j?5ì ó_®ÎÜG7©D¥‚*–†„3W[Pœá£§¦@³â­á%ŒòËгÌ”Ï4BH¼W½+oüœ›ÅJ±#yLGFWÌmWÅÜŒ5ËM‘®è§¼ôeð¼ Ÿ\¢c¼ˆ.,R�½ “ØîEºšˆºµ½eå�bEH"æ¾,�¨ˆ$†¾LI'‰Þ5°Éêþ¯ô€2wîÜk—9¿âË(äœÎtÓ"àÈÄ�}K@/ ±ù™ŸÔ§_­«.”Z ‡äÅ)Js@ 8C•1åPF”Ø`.çZÓô¼­‚M,¸ƒÕäœ{ž�b ù a‘b{¨ Ih‡®ŽK4_$Ù¯š>›/"åÜT–‰¬"³ŒH‹Z4žßbÜj®‘&K ÍÓÍÀJ? Ty\ï^ý"ý*ÈŒ§ã̸ä�¤]ôüfü—ÜøµâÏñhlû[þò/Âø•‘_H „Oœ{ù(«Ô_D9—µÁD„j:ÐDOÓÍQbåJZ¬›ÂN\s—•E­XlÀ2¦S V!ÊÁ$wMŽm‚,XM4ƒ9T|ãï=骢ĠßÊRQŽYŸâWÛg‘G&½²$D‰])àÑ�Ñ®‚wªx-à ÞDâÚK¡Â=£Í<äͽ«:nmjÕÆ2§ŒÃ~ ÄíZ-¡Ì®Í›8›¡™Ç}ƒìóç¬GŒŸXWiþÆÿ÷½¯¾ss ?Š_X ìœ:õ“×V––¾ˆ".©ÐG3G8öY«Ö}L 4:ðgßžùLùf Õ ‘Öý—Ñ)\2¼D£¸ÅÆ$ÂÍ@ßD» �H2c^�N‚»+ÓZ=z‘ØsPÊGbV´¶H�f›1µBÊY$óTs-còå ;‰­g¸×iÜod%�UG,Йwu|ι€/xÞd#PƒÊ™ÇÔ_·püÊ$S9ED *Ñ­£Q¨™ÖOØ4zÞFeÿDÏ¶Í æø›.qþ¡ÿÊÊêû¿ùݯüT¼QîÚ(Ó'Ͻò«Ÿ¿�ºl: ƒ×;ú\U_Ï›–•E¹Tkô– ÀY¤"™kP5�S R ,€„T-ŠDºeô%é<�âµ�·,JŸ32ž%ÖF·z,‹f¨5ð…¸J){ÀãëZË®–wFWà¿ Ó(^!~ômQ)(r6Ô%Çæ¾DñUˆ,h«{‰Öï)m/I¥ uFÒ¬sŠJS[èMÍ ‹}M­­¡wÇ6NYæ`œÁ˶ê¯9?îüÂòâ_ÿæw¾úBdõ »ùÎŽ_XòžðÈÈàåÞþmO³ðò+l6�õ‘Q)½‹£Åå9XÄk}Vl/^JUdU2Ö 2@æ1¶å�@@j�$D‰4%PI:ãï—XÅ –Wð‰÷+ÞÑ+:÷ê�‘³…2°{Jr‰cüÌ[¢4ÞzX _ONêýH .É’e¨_\�$‰T§‰7ã˜qQüŒ·âÚ&££D�#Œ� îq\ÄGP'~1¾¥/õ™•æ[±(‹XŠyÐ}^�±¼r¤œC–C‚ÆXñVKW…È¢ä•'±HqKw‹ž?�3\‰¥ŒÞjTJ¥ c;û²cUÇU™‘©Ñd—<†¾ +~9DÑe´î̓ÂY(ÝÈZ_¾’�ŠÔÉ£§:nDöxï��J4 'ó”‘'ŸóâËpJRòXD»'I#Èã;Úã‰^Ñø¥)ª}ì…Ý}‹s|/’güKè©Moúaüÿ®meùïþé³<”Ø|î)YJ2ìßû©¿‡zÿ9ÍgŸÞ�’õ‘=&Ôƒq]àCñÕI�»jnRQ–Ø{É¥QµÑ#¤ ‘s_Æ=ÒL½Jµ³Wîß�¤ÀCaë�b…Sè"ÿÏÃÉgpG¦9©Påò%º‚p€¢nrSLûÌH :ËiÍ——3§Ì9E¢ó»É½"4¯]<í,³lêŠÀ¤]ƒÅT½Ý£œ /ú¼FÃ'àÿFçûœq$s‰!:Kð¦¾æ´�/øòNÿÄõaû�‡Èô)2jî(ó×üÍg¾öÿD1?R·�Ô ¨™¡á‹olèÞú]>¾yOv©tÔóë+Cz]R A…�� ¦ì‘yV$â¤âIÕ¤È9¢J´N]¦ŠÅ›J9"ó`îËâ@JÙ WÈ<§u`º–IeÍã[O�GvŸÈª`-¯ì!ž"­ÑY|A‹sXÂØq`À«5ZLÏhPdi"d||Ìa0%›ÈÈãRÉ#ð¢�ñpnïŒ>ñ�Á ô3¶s΃B�YjÈ8ˆ!�° ÷9½·ƒ�=íý½a~j*Œ_¹NïO§D�¯ïøQ/_¬[\úò7ŸýÚŸG?r·�l M �^mmÛþõJŸ»©«{˜Þ¾YŠ×‡GçøÙ´ ½ÛNOÑÚ€6É¥!b^pö‹˘rÈ8hó¸9]î˰�{ ×Îèc­ÌÁ©º ¡ É]Þœ"!ªHáélŸ¨J0&:�Ÿó%l ˆ�,¬£¹”@-½ÀžZºGFvKQxÜÈÁžT$2L1mÁÎŒÔ�m Å|;©A8Îi¢x#ÉwÈøå ç‘òFHuÏ Ÿçùûí·Ì0_†?Ë÷ •ªæú�Mràë?[¨TþÁSßýà >²Îõô‘/ì®»žx€ï¦ÿ3*Ùoj…AÛÄc½ZÜÌsæ™LóÍ=ÝU ^v1‹YN3�1/‡R ,€ª�k«F6ȉsŸ�<œCóJ§&xòUr€¼+n?ó1î÷^Å3¸˜ÈÍÈå0p‚ˆëø”¹ºÇœ^”Ñ6EǬ@^%Ò%,’WÑ2äÃY: ëÕš‹ƒ£Ž ètE¼â�%âS-¨,r1] áü ëøè5å¡5€Í|©§•3ûôxoafÚVøøð‰>�JŇzù ¿òÔÓ_}-±ø(ß“ê>Ê2e«ßwç§¿ÄâàÿFe¼O¦áëœBÌ�«­­ÃÖ AS…9>©ED3rZ\Mmæ�H¨’ËérŸ”‚©Ê&­j ©•¢Y SÜT^~€Ø *áB# ©�Óð]”†ÌñLâE\)]'w£Ì-Ä 6À}’ÍîéQXŒ/ÖIx§K±O£2:a?ƒ0Hê^h’h)–P9LiØÌ+2'>èÚâd:SjE¼ÇS}‘žÌ°YÍoá3l­��4ua~ó/ö¯ lZ‡â�–£$ó6vO]_Êç�ƒËTóq6ÉÈH;yÃîwy±ä¢”îÜF†>©ÅÂ^¸Ðè@'iº ŸŽ'O‡‘*ã*ÀÜá/#ÂAk"2ªœ"YX±‰e 1®‚Æê J¢e‚EdjŠ.‚ó‰l#×<ªÇ]½Î”ÏÒ6r CídC¹æ/öõ¦ÃŒ¶ 0gÄp̘㔘™ ñÍ.BBW¤Nsò",…Š €èLJ Ÿ‹XfxϹ¡¹¨þp¤}¨t´†Îç×\~‘#ºgùžá<ëдvªÚ+íв•÷·þ›¦•™¯|ãÙoŒ)ý�“³|œ.ʺsç_ém­Ôý-jÆß§"> OO D×À‰+j š›[i ø¬5•\#==Pc°ÈwíÔ@ÈžÒ@¹È?WNî3|)˜ªaŠ-]²Ê „@)Z"Ïîð‰vˈÝc¼ ØéŠég‘Œ«ã%„‚Ž[«pi�,'/Œ*Ôûc ¢ËRLÆœGˆ©(=ðœ¿gÂ.�Kålt´`�«HÐ �Œ98ÜØÆèº™7ÉfÑád@Ô`ÀüÔ£ëTžFöšh%_?}–K´ZÌ›caOßçãˆ.¥hq²�¦®¬¦òü‡ÙÆÙÿø½ï}cØ>†SËÇPî’È»w?ÙÒZYú FÿˆÏÓ:wXQÛãC'U‹­£–+¶~š2hø&Ã×èA ˆТÛnµ Þ0”’еËaª «*0ÕôX EdtV¿ª˜ÐÌ-ÕâDlu?¥›–$DA†2OãÇÅ“u\.>øax¢pÈn4&{A"ÉÇ—�(RÞœE&¯ÅfNdF«P’^éà·øøÕ«›¾4'ì‰Ç»Ò÷¯'a¯¹ˆÆSñ€E'®6ážR22…ÍØÉ%@m`£ÇsÚ•WÇç„ÕhϾ>lºÀ‡Mæøø* {¶�_‷OŒÃƒÎb-J|7M• É*‡Õž¤*ŠÕ(X%PôdÁb*©öRE«n„ÔÏñ‘]F%úBb%/° ã (X§È„óžØc¸©d#mEQ½×=^Í›BÆÊ±Fa»ÅC| pÑt'¯7®Î(É­JÛ£F(LJ"3äH,P f¼ èâfy„ŸI†~÷ˆ–KiÉêÑe¤qHFæiô:)«ôuöŠöã_lX®\l©¿ÚÝ=;ôqzt—r¼~_×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬kà—Sÿ?s2>¶°¬IEND®B`‚ic11 ‰PNG  IHDR szzôsRGB®Îé8eXIfMM*‡i    �N@ɉIDATX åW[o\WþÎ}.¾Ä;3n.Ž“ú¢&.Ms1•Éi± AâhEA¢ðP)B€è ô�ÚH<ð@‘ ©B¥´J•8©…6½…8�ã8q’ÚŽ/ãKÆöñÌ™9ç ßÚgfâ¢ð ºíã}ö9ûìõ­o}kímà‹Þ´ÿGÀÁ=ßlK4Åi!zC ‰rˆ0 „eö>ü ä£>Ÿ…AÀç¾z–Ë2•�ïQvÙ ‡y÷ÜÈÝ�¦fëaŒÁCÏÿD×ôc\+#F¹B€ÆË4Fƒ¡2Î^�Æ¡G—4e@ÓfäøÈXæàT°Èç ˜2'ýhÑó itÝ 1,ž‹§r ‘q_zy& ²Ìw € –_~Çe`6áÉëcÖ Ày¿ B¯ÞH¯•[�щ£ùüÈLÂe˜ª7 C�Q€87ð¿È¾Dã%”‚"Š2Æd-ñ�–Å !CæŠcÝ�¥cjBåO��}ûŽdêb‰á¢Wl1t5yé�Ê{?ðQ*é­�dS#6njG*Õ†¦x= ùq­ŒÕé)ŒLÝÀÍ™;póyØ5 ‰àÑÈ„‘5m§÷êÕ³³ò®:IÛy†kªIzD9 ­¤¿TBªc 2OíÁžþ~$¬-pJ&ôå䦖ÑšèÝÓo5‹ËK×qêÂ?qîÚÇ(‘!“a$¡¼tX¶Ýjhø -üUÌÔšöxèS â-R®ÄW'ò�ßþb{wÃãB¹¸…ùì(–Gnañî¼¹% ÃÂ'­íè®Ûˆ Miü|ðûøjÏ—ðêù×qo1 Ç¢$0A&zŸ´/!Šã:�a;ƒ,lzîY”‘÷ ð?¼ˆ3g‡0sã& îZÄçˆE˜¢›–†fì~t¾×wúî�p쵓 Ë4é§qц®'#óëÐpY,J® IÄÕüÄ.Ô„ïùX¹p£<Á@UÛâÉúJÈw�г¬ŸË¯âô'ï`èÊE<Ýó¸<¢çb:b€#*"j5ªÆ…M£¦C™–¶îëA“`mÖÃøé·3f̦a­0Væz:©•@KÚéôÔbBsœùY1Õ˜C†5¡ÖjiX[�‹Vs]hMÆ5ØEÙÙÒ�ƒH66À/äQâ% ‰ZÅ ÄVZ-­x'©œˆÅaŒrHj� ™QÕVcÀ— '¢cÑ"×ó™ë ×ÇálÏ ,!ìé@÷£/¡°0 wî6ÜÙ{X]\€·¶L@”˜)â�a²f0}…èP•ìjFå]µÕ¨¥ò�ë¤R3u|ôö¿aìØ€†Í�àÚÜî-ÇÐÖÕ‹æýØœ(Ã^+!‘ó[\Aav“wFpóÖUÌMOÂ`uÒ¯bOj˜L0*Z¨¨Aɤ;³œöÂ[U%E¯„¹á;Hµl@ê‘�hhHBw_=�zÎsq‡ó;6uã©-ý8°u/¶´e0yîÊ}ªŸõB 3L&‹œ¦—îÍŒ½%vjÒ·¦úûdsã" %(²0nŒ`ùò5ø³3X^ZdA¡°tº‡U§cÎöPh.ÁH%Q`áٞʠ{k¦–²È-ÌD È…€1 íÒät ÉÿêFBy+Eë4^)°ãq¸÷×°üÞe¢û3ÆëÐ,V<§¡±ÖZ¶múak{ÆÝFèV _ûúpêï¯ÀÍ-)]¦Í5Å÷¨=` ¥ý03¡Ov6R ‰” üUMh4¨h]T]f@)Ò€5ß[Z‚;9ÅP cdèmL��bÃŽn46¦ÐžNc!;�{“·`²šò½n^úlâS‚ít\v=¦•4ŸÔÛŒ­¨:¿ZàÇ:Éa©¦P%Ý4º¢ó�Ú¶©0õ_ܽô7'›Ÿÿ!®ÌÏ#^£øtœ/½”öj«�GbHíé¼÷ý�õÛ‹?~ m~÷êz&±—m™¦"JÙ²ž’!�^&(´bÉÃõÜ8r«Šî²Ú�¤ "©Ú�@«QÅk)R”šêm¼üBú»Vñäॗ÷ãà‘n81�ÇtõÉ™ÅJ¾k’¶Ü·ë–Ú°"3i`qæ3µ½Z^æ:Ô� J¬Eýd�›’Øßí`q•©T ±=³ G_ìBÿ·:ðîÐ&>u‘_â™�u@ŸDVS3êŸÜ�¶�0X1]úg¼s¹ÉI†2N?% ˜ŽR*í€�ó+Í"•ï^žÁs¿¼�ïiÆž/p%´„.¦·Öaÿ³›ðØÀ�mÖL¹)d‘晢a* �aª'‹Þûqçÿ‚Íl1+a“]­Ùz ŒaSHÅtLLðë“è<ï2» Ø»/£%@:^‡L[«19š%‘X´‘*”‘óò*ÝŠsYÜ:ƒì‡—”ç¶ÍÔ«¸­NXàñáàö–'ËBÔ*¡¥Úñ±¿=¾‚±Wñ·?ß@:�@º-ŽºL’¼‡^Çã—Ãc��[Aqnþü ®‘àvmQØ‘ú…zÉÌó`w¶   yÐÝÙÿS"ýMÀÝJ…IP¯»Dp’†YR¢ã7ÔäÙ@<³xŽ´xo;¤œÏd¼…z¹D|6wFž-vê�?ü¶ àAødtÌ:ÞÓ81.*('U€/U@DFC:2-%"&'&3@?CGDXz‚“o,!(+;I,/332obG=50()*./..-?WTiz†~E*11,*+*28CSb�ŸK37()'4)€(E*8ˆt8>,&RÁz1'+1EKRU�� U@@>85/*('$U€H+=>?<4-*%"%%$3::<>¥}4:*(H´�2##(C m9?+'A”ׯ ‘•ĨFBD'%"Ir“–‚e>AII3$&'%#%+39CIKU€ U(*,./5=:U€ UTY\XNE@97€:3RSW[W{¬¯¦x>5=@MQSb¹Á¡~…�–S@DKLI¥ÊH;;99MTDFFGDŸ¼_OE=>?DCAB@TšÇàÔÇ¡X=EF>=>?F]�“¨çÛhGL<=>G@<88:UÌ¡MT=>IneD==@Z²„S0W?=CW€zt‡¨Ü¼[[\=;79I[l‚�|UXba3:>?@@BGMS\bcU€ UABCFHOVZ^aU�ic07Z}‰PNG  IHDR€€Ã>aËsRGB®Îé8eXIfMM*‡i € €kF&M@IDATxí½y”åÇußwß{ýzß§gz¶ÌŠ}!ÄÂÜEP©-\DJ´mÈò±ŽrâÈNœÄQrNFNr"ËZHʲÅĦ"‘2I�R�" ±0Xf_{zzßû½×�Ï÷Þª÷^ÓC´ÿÈT÷ûUÕ­[·nݺµþªêgvÕ\•ÀU \•ÀU \•ÀU \•ÀU \•ÀU \•ÀU \•ÀU üÿE…ÿT½ïöÛ^h]Û»¶VØ·V[Y3â×¹V°’ó´jV´5[-&W ÅqGv…_„4ÖVâϵˆŸ±"Òª­ÈS„ÝÈ”#®‘nryxbÃùÈ‹8‰€c]Ä›# °¶Z%Ï …Bá�“k…‘ryåÈ /kÅÕqøðc'Eçõ6¯»ÐÔ·,ÍvýêêÚÚ?êêìÞ6<¼Å:::ljfÚ¦&&]Õh¡H“Ï_úoÊWbÉ Ià(·]Þ!ÀFˆ„.'LÅž×Æä–Ä×_ÂË5]±Üx<…'<1–ÜNÙ#:aÇñô“É5_n<;8¢z~� EKiéˆC·hímÖÖÚNå¨ÚÂâ‚U*+gQ˜ß>|´ó_š=T½×Ë$i¿>äîºë�k 5ûß[Jå÷nݺÕúúzíÂ…q›˜˜P?çÚš/áò‹O\Œ0 JH!+Ùr À~ÇQXü³ Ï)Ôqœ¤ãŠž4ÒQüF:Y2ž£‹‹„“0e%˜t!чŽçÁ‘†2)C@v&¯€rºQ—P eèhï°Î¶.¯4ó‹ó’áƒDüµ#G¾óbÆ}­v3¯‰ÖÝoüÑÒ›ÿ^oOß¶�##6?7kgÏž»dÁ{K˜D ÂÉ7ÄÐjÈ[O 7 6ÕpÅ’ ë…ž€A¼—€ KÁAËýASt<Ü-á%xÝv„uñ•á¹&»ÝÀ!„Õq…‡ñÞ§×üìF% /ŠÂÀ¸«£ÛÊ ”çæl…Ö XXûå—�>ö¥L÷µØ1åz-ˆ{÷P“ÿGÃÃ[û·oßn§Nž´ ãã^ã‹i°S Ã^ûÕ÷¥_[?ý» ±æšÉo¨Šà™O9êÌáÉVq�SÄ�‚h6÷6„_)ª{êQ<~ œº·�•“ ;‘¼Wb7¢EªÂ�œd40ÔX©§»Wк†ŸÜ4¸}|bòÌãŽð¯Yî¼ýý¿Aú¿3²k¤Eƒ¼Ã‡_¶F³%ŸÖ‰_eˆé�Oñp»_�”Ašº¬žaòœqpx$90—�84œ‘uÅqÌœžì�†Qúá |êšü˜�9Øý)BSXÐŒ‹BV4Ñn@®f’‘T=9(�‹>x^fÐÌ€Z³§R¥Ry`ÓàŽÙ‰ÉÓ�¬Cþ>=¯Iî¼ãý¿JMü�Ý»¯)¨‰:rä0²¤pàIHQ�1·÷¬&y¨ÕÇÕ§B¦Ÿ[R�ô‡´RÎ2 {#Ø}®@r)ŽL¶EG^uPwzò¤†7áD Á›L=²a¬ óàzbõ %QOï"ºÀëxMAu")tieÉ:ÚÚ4k(¬T*ïÜ1:9yún ~`¸ë�ü(}×gv�Œ´”Ëe;vô(š©Å²á™!CÉV&ÜM�«­�pî‚TæãO°ˆ/Kn÷ºHÜŸ…£è˜d5#­ ÈáÙŽÀÑy¨C"-çc=Ì}õô‘é‰ë0²ãdžCsX 7 ."4AšÜÍÐHE]¦º_@+• Õjõ=ƒÛŸ@ ^JŒ|_VZ ü¾âØ=o|ß~V²þ`xË–VMñÖ~fߥ  �¹”A/ü¨þ‚¦¿ºhÜ/œz÷@ô(tÑp¨Ó%Å úA¡2�”SúXŠä?YN@Àºi –|ž‡äü§Ðº©{’CV“3ðêHõhîHô/úJh�só³^áÚZiÖ °oß=û׿2ß÷­wÜqG¹²j¿ÛÓÓ7¼yhÈŽ=’ )%ßQ´IŒîOÝ·ç@¡1 rŃ@ŠÞÝ[Ù—Ë�ÇKrMô"˜âèÏqR`DjŽtô^ÆMÐL+R�¯É¸w=FShr¦8MQΆk]<ç!R\wÏ+ã$tB#Lù�[˜ñÅ£Ö–Ö­,£þ®Êæ•´.ù¾ °¶å—K-åw�Œì´'OØjMsÖ‹® 8Žø&)àõ¿ìÖà�_}F  BïbeðŒç8In)éœ|¶4ƒ×‰Àyk@xõÈØðœï¦¸ ìäjê숱&p#Ñ}Õ°æÜ�ds@Øš>.,ÍûÂ+Šïžžhù¥¦D®Èù})Àm·ýèŽÕZíŸh‘gvvÖ�ÂSùigv=�\¤52ˆõWá+ºã×)é «Ào ®%áÖqr€p9šƒ2­Œ';$øÉq"0#'h“N=0£Ö! ŒjÆkvG„öEa &?Z-¬Ö*¾rÈÌøŸ\7rßö {eÏïKÊVù‡]�][úz{Xä9ã}P$sMüÉé?�õK�²a¸ ¼:bÝßÀmÄ©§%‡"ÆCL¦¾uÏTðy ïã}ª�^WyU©TY`©øô•…-¶$w…° /jøé­ø±ðÓDÝùhæ$šPêÎWàÖCp\o@.‚§(Ͳ[Z^²^¬•KåáµÖê?l¦º‘ûÒÔ/K/wj+öÔž={æXâ#Ñô ×›qEŠBõʽ6Gß.Mˆ?°ê;¢$(œdáú*œ H?•Z²±XYäQ_çO8BñÒÍ~8L4ôÚÕß6Ò]Yq A±ÞÞÞf��]ÖÕ¥_§/»¶sÞàTøÕª`Åæm–A×ìÜŒÍÍÍÛ~Õ<%©)oî¾ÄZñ!Wƒå3€Yäud�RÇ—O(ȸÉ똙#$òŒ¨Àmkmå•z ]¤Úo}ùå‡N%ôËZ-— m \«ØÏvvv tð÷䉓VÒ\ß9mBªC`Й\>1¯Bo2u�ëó H·)>Îf¼­µÅöîßc7¼é6Û}û¬{ç.ëèê±â|‰îªjc‹ôõôa-«ì9ã×B�o+ThÃù/l¥¥f³K þé)Ö\2(Ê9::k�Ýlg¥ÃJ…ªÍžg<°P�6ëóðrKy»Ýº}�ýäÞ÷Ø™ê¨}÷ܳöÐ3�Ú³‡ž÷–¡…UO½÷ožr]Ï„gËë@¸üyñ£Þ,¨¨â™wYÝl¸A"7”Ê«w�ùpûÒ®+Rþ�®žî‚úE­GGó•ýܸC,áHV= î–—VGìfXr7@Bz…Qs[£Ùà•ó�o¸ÙvÝy›m½ù:[Ý¼Õæ–©¡,VlF1æ¦+¦½UKÔ.•Ã8ç·FÃ_i¡É¬,Y¹½dlÀ¨Á� ZM8¸zßD…¿`ã/œ±{†ÌZzà›¤¯Õ²K¸ùŠ ÄHàÚÒV»qh›ýø=ï°ÇN6vìD`_ú¹¡ oÙûNæÌîeñg|‚=ФàB"ùìu eý+<ýá‰T½•SþÀ‹€xVk'^zÙΟ9k3³3Ìh(lðdœ#igfI0øˆŸÜš?À1ášé-¬v@m²]âµÛöÚ�Û÷Û¦žV ne«w …X[ eXšfü24heÆ•ÉE+  ˆ+ö‘ëî´]ƒ›í_|ùßÛÙÑ3ÖJe«o-câ'×°ä½tÍÞ$_eFc4xfÚry³¡�ƒNÓ€(q“(fIIHè_Ý«ÂTâMhr»&4å'…×[ü9J•Âû»î³íÿ¨}m™òÄ?@üôôŠídƒäÖî;7‡©)‘Q)ëú4ñ×lÙD¿ßa»OŸ±©Ç·/=ò¨½üü ,ÎL±°§i›öáǼ¼•…“lį Ø�[ÊWÌà …Ñ”xr|ÂÆÆÆìéC=š–—‡Pˆ½;÷ÚÍ{n¶ëwÜd;º·Z'ëFw²0¹b];†Y`ꨮdiÅV�Þ³ùúø/Øÿüåg/¼ð¢o­Ë È|¹ˆ= ñIª¹æãÉŸáV`Äsy³¡�ž�:\¹T%˜z�“¨ £àh’£n7kr½¶ƒ« ¢nr¼ðù³ÂÀî­ï¸×6ücö5:첿“¿@ß©fþôRÍ0ÀëA)æiJÕdÒ61(Ù.V7�ŽÚãÿæóöÔß=bçÏ�™d¯KZç—xœSÊPvð§d£°ÓB€ÈLʯ·Š�_�Œ(©™m¥‹P|§A¿;zþœ�:sÚ¾ñØ7hˆzlÏÈ^»ãº;ì�»o·½ýÃVê,Ùð=ƒV›X´b'ë÷�ÓÈ{JÛìÓ?ñ ûGö§öô Ï3�Ý�Su£–E’�Â÷\%üä¦àx¯±aùnˆÕ0MÂhÖN”lpÜ]áçéÑÈ�—5vVŠ”7�˜3¸B¡¾ñ�7Ûö�}ÄdI–a™ 0§VŸŒi•Ó‡àñ•¢ícàØècˆeüеCñçö…o>Bó>gåV �ÝJ^TR¸&}qÇåáA90øT1çæ_ñÔøk$ÇÓáÊ”ò!…ô Ü‘OÆ ðZ‚g)È2‹KÏ>ÿ”=ýÜ“ö…Þ>»í¦[í�Ûï³»:n±]­]V›f*¹H_MWÄŠæ>¤ÿÓ?e¿¹öÛÁ—^ðî@l*ÝæÂwÖ•B8¨lø/²Z�¥˜—5ζnÙó¡ŽŽÎÛµés†A’oóNÉ©@”´ó‘9è’¶pÈAxPVªý™; 2wnÝbwþê/Ú_UÙå„3µ ¡0›³sKUVÒˆ}­Ø­ Ü;»Zm˜·r‹ßxÈþÃ|Öž{–¦˜ð2}�¥^ Ø4÷DT³¯Á Þ`ª×Û7¦‚¯nDsòx‡¡¡$Àô)Ü §µ ­èÜã÷Á™‘bäØ>ƒhåM�^';yܾþÄ£öõ§³ñ"‹Y[m ³ßÓSDzJ^6ÃÛ-ûöÛcçNÙ$ë.¢ILâLæ•…ïP$ÿŒA¤�µZõ‰óç�~Ñ£¼ÊcCØ‚°ùvM…f8I bÈ$vR¢Îc<ê Ëë,'œ`2Çip$ #?öKŸ´—vî³3‹¶™‚ï À©M§«¦5‘ñ$pQÈ‹Óöø¿ü=ûÚø+Í{}`Æ+BUȬ÷Ó¾jëÓ)/ÀPjä!xpö‚zÔ6�Å”Ãô Ág¼¬a«‡”bšOWÃí0‡XGYNàüW�ß÷ö»íÅko°ÑÅ%ÛGÍ–ÐTãUÛ§èÿ[¬O¹á§«½l×��´?ÿ_þ9çŽY¯¨×¨íJ\VágEÍI{’ʈ'‹-§g,œOÁä~Ž—aØ"Ì )=bQØZ›�D+@·¡®Cû\Ž�_¢€ZÀŸš·Ï}åßÛWÿ†}øîwÚÇo¹ÇvtvÛCNØïa[Z`Ê3 1).&YM�€Õ•$!Õñ<Ö«>6VŸq“¹,Ù©ù–S ÉçúÒà/À!š$@Wá×�8$"#÷ž.4þ}ï°/±Ñ¢P-Ú}ƒ½v–·mÝå¢�£öûKµDÑ‘òëgÇíëÿë§íÈÑ㾆‰ªéjæ©íÔ4Մ̉xtuufS6Ü�u~äæ%a�¦gúx] )=Í.òÜ=#H ]Ô:°ê(eЮ")ƒ–T¤¨�´pS“ì÷ÿòóöÐÁÇí†köÚß=ý=›žœf¯/œè¢ð%è:åf'À:†sꂺ„ÒæØÍö† à‹L6ç]n‰ØŸa%%DÂQæ0ÃâC¶SÀí…Ï„{n¸û vbxˆõõ%ÛÄ‹œ#,Öìéh÷?ÎÀ°ávPÀmØûØ ñÂgþµ½ôò+·1Ë�–vøÄΜÔD*9ŒXóGr¸•âE?áÈ$·ûý!¡:·(áN‘¼ß×x‚‚vƒb I9rÓ¬pÍŠ$¬Vau•-WºV-�Ÿ8jG�õ€6w„Œ#I–;%Ô‹a*‰ «»°v {Cˆ%7RtiI ª[©øÅÕ_AJͧwJ_ôä Èü¤&ÀË^øNI£f³½,ødÉöf–F»Jô_ôá[Ú©5¬£ZV­,|F‚Ôë9øŒ}÷[�0¸Òæõó¼‘P�pbSä¡ÿâ!Ü,xÄGGF°D+å׉$Z9Ž ^iR±¦©‰syxˆ £ŽãÝqé¡ÐE®Ô"h){uµäTÉ+Ö4y*ñ"29.ç8å·¡$ /ëJWOüU+€GU‰(þÔ׊'½ª�BJÈ͹Ńjç‰cy sýáûî63�ë?0b{Xƒ/2i_fí|�À"¯\O�²´º<� ˆ‹ÙÞÓa}„3óì‚¥…ˆÂGR¸—™c?â6'É6ùAŽðŒ‚Ot@ÉúâqœžÀ*0ò-�U¾·�®†_!�DÀ­�›bp–…Š1V¨i�ƒáôo4ýÂs%‹ Æ„ì]iȸ-70E‘ô¯Ä\‘„`•?ý§„¤}x›ùQ¶#ÜSrÂ Ž¢7 Ó9¦F[wn³ÅÎ2»qÁÕ”�šPd9”�›x¸xÚÒÁë[Þò�a?b‘q€Öè£æ§$Àòð¤dÝ— ²œ�°ÂaâG¸õ+ùøö÷î>íKd”�£ØIrÊ$²¹`(œ†‘/C¤Tzë AlEPüúViž°�4½+IäÜ-˜h&•�ÚÕ¿l`6VˆŠ®ÿ’Û/APñûèW-‚' ¢j¾üü)ŽÂG¦ÃÅÚ¾™f^ï飈çM¼|™žà]:9Ze>¯5úo.WxÉ“—r= fÊn»_®ugÃ�\ >_Žï¸UBŒ9¾ÖéðäÊ ¾ð|½BI�ô„-¬PEnŠƒ3h‹ âé'gÆQá'ã�®Ã$?‡¦î$î\B^mn`¼�¹,ŽgFš¨Z¢ôÓŸçHü{¸{r¸láx¤p; §4ô~¡«¯‡¢e‘‡´EÆ­Œ–Ûé æ™–P&ÁXÜ÷™o£më¶ÐelYvòÁ•3ç©G¢é™ËBNx"¤„§áHÆ[Aü�£pE5�æ_5]5¾‡"ŸYZfÀàˆšÃÕ6>zÚØ™³¶Ònãv³½ÿ?û”uñ"ESHÑÑ_$˜ÓŸ šøhà)G„KJàH¾RBWDúù:ÛΣc6IôR¢¥X{9©¦;YÕtÅ ÓÃT¤ 6QX¢äF ½x*°‡J¸ETùbÕ³ÆV5ª»Ã70³ªDÌHÿrÏ+P€(@=erSé¼HHùOŒ®Ì* —3ë�ŽãxjÌf&8኿€t3¨-i¡„��®U?Úæg&#Ä¿±)vúö½Ó~ò—þ�í¿v¯­1�¬±kÈWÜ<]%ŽÌÇ+ _éñÓâ�vÜäÇW€ó¶®“SyHi(TŠ&Þc&œÀs+Žêd%¼Ð‡©¨½Ð�gµ[xJˆXþ¯i¢N*QÛ)tUœÀ‹ð\(ž<*ÌUé JwÃA ØðL7;´:Dj¬ò£p%˜X®‡y.õp>b*Ó�=uΨõ£(@›(.,²—ÔûéÎ�ŽÙ,‡5ŠvÕÔ–llåyÛÚ~›�MTm¾÷6»ã#»ìº£ß²çý&Ýà 6„®øÀ­^ J æB5SÂ0ì/uTr0ÙJ ÈÉò²ªƒ„)“sêΠ-:)¸AB. J¡¿ôïˆ ñP²ÇãAb)FbyŠ(ûµ'R@GU܈D²[i%³¦ËN7T§#F`ÂE).\cÅ©;Wi§^|ÉÆÙâµH\±­y»�®óË ¼ �bÉ…,‡ÀŠÔã¥Ì8¨ŒÃ+Ø$Á=rŒƒäÏŠ‚[^˨P=H€ “Ž¢ìÂæ‡¼Óº@ÄOdÜéÖA4éB'{�üe+@h€3.æ%¶Ägd8qçS²( Lç†R¼KÀ4ÍšäòÈCO²†Þ`e6tÔר|:Éñ®el0 ä]ù"J¡5�¹N?Î=k[Ø’ÛY¸žn¡•Ú:ÑÓÏž»»¬ç]7ÛíoãN±S6òêÔé“6ÊÎ ½ÅÔéß‹LÚ!Ó­Ô>:o Ï�d(w¹K�Ön=\H‘Ÿ( QPÁ;VÊnÐ’Ç]Blª)�+:üSè>˜Ã-*N©ŽàDy$€[ʉ$¼�û€�@­�~NXÅ/N}·šðž˜óˆ¸s®BÄTá ÃK�=g7½çM6ײhÏ¢‰ŸabØBÓÇä�Å¡U~îæmÛ®k®±CÇ�°ÃꬽaË›x?°‰i"ã ÊvfµË¦[hI¶m±îknµÛ;8Ì2kkãçmáì)«0˜=yʦÇ/ØÜÌŒ-ÑÝè²f�ÜÀ³–yƒwq*£üᬬäl5„�aBZTÅtÝ�C0"ú�ÂW¾CjÀTèªí¯·FÑ"™`€Lð"Î�l7Pƒ v|a¼ ш^*zOTó×ÀÀ]8Ø’Œ§ËSIû†Ü-޼/ ¸`aXËg¾}ðÉçìÎC§ìüVöï3¾˜ðù?§\ˆ_¤p¢— µs”{©oÐ+ãöÒô7m·£Û÷Ú@ÿ&tPf}]'~ÙøÿÒéj+÷Žk¹æza;ÖvýÎM£3SlÓ·êÔ³ŒQºœ1[d·ð"­Å÷/3ÑJ¥öþy¾°Ð`A;ºåܰ¢0å�üæ È£`Âå)‚¾m›�z@ƒžGr¢áRTw¥‡+P#Ü¡I¶ÍhŠu%ã€�[¨Fáó„g&q«€ÀÄOæRŠ€_}ž INÂJêÐÔkÜÙùEû»?ýŠø¹·ÛÙKwŽš[‚–#³> bbë×wçª :‡‡m|vÁ:jçmêÄk›ØcÛ¶ì²¾~ ›8R~í·s#hí<2Ïê"3�Õþnká•siÏnæulu–»œ:*ÒÕW™•pÔ{aÚØô¹Fk1qâ´Ír(†KùlnŠmÝ´R ­J:C¸3»�eDÎýµ0@ñâM¼÷ñJFÊ’IÊâòSÎ^÷8Ù¤Bîö0‚F—VÌI7þ+­+P1¡ÂÇæ'Ëé*…øoPmÒp‚ŠãË–Q\ÑÈFµ¢D+ðÌÏØŽk¯±âý»Ùßa= âf™Þù`Ý~ÔÍVìCìŸ�Í!œÐáLàùÕ;Ð7`Ï¿xĦfÏs £ÕöìÜi][¶[ E´=ª€’Ñ›xWá/°Èu�ÓÀ5Ξ¥–—QŠ6º—b Îö.ΰ ´¥h½ûxÿÐV´7TgÈGÕ8dËcã¶tö¬Í?a޳ÓÇOz—²ŒR(s¾ÕL­„ÿ)—(®ÉÚಓTtV-á8Ì…‚+iQ¾ö8š¥¸MÉ»I–Ž•$Q•ëòæ @” …©ÅéK›QÍñ�°ìuTEQ^Й‰\*ä"£<ÌqkEûúÿó }pÛÇlí-#ì÷ë°£§Oû! Í?úÚºQnì`PXÒ~?(1U¬Ppç»é–kí™#cС ׿ìð™Ãà•¸¤“£Ý]ÖÑCÁvñ±#æý:S ñh™~耟;(Wqóî©Ìëç²V¡)´¢–§P¢m(Cÿ0]ÊÍV»o•ê²ÍÐ"Lrîàì‹/ÚÉCÏÙ¹£‡Qº”×wA;FóŒdBš’fÔäxâ–SH`:¢ÇiÄ6>W”pן"!âNK)mlT/.k7�|ˆ‹n×Û·yúÆüÞÝÉç‡lic¦„ÃAîOžZG äìߺ›çØS/Ø^.cè½e—õöØ¢j 5j3{æŽLͱ@©ä´P0 ba³qÕzÙ;P¢•Ø´ÿf›ææ͇—–mŽ~}ŽËçiÂWhAÖ¬“A?µ²Æ[Ç"tʼ�/1þhño$e3c(Ëf—Ry™s…³p;ŠâœBqNšuœo±ÞZ·mbOßΛobòV»éÖ·Øæ×z74?O7BWF»�’¯ É4ÉK¢HbŠÅ¡ÀJ`Ï£*�ÊQ¸b¹Û£‰.0Qßá™Í$ª©µjå‰Ñ±Ëo ݸÐüŸ2ð¦(â+j¼€´W=0©EÀ o’Oœ:¶ã _ЋÑ0£ýy^ ñÿøS{ÛÙ÷Ù�?ó.«›�ws†¿ÈIje;[Å–´M,�PëPb¡è'‡n´¨ôYNûê€HGË�µ“~™)B‘�0¬ÐLWéZ*\çÒÊ~»9Æ‹ü•,sW@ o![yñÔ¦_±ƒ3 ìÊáV‘”¨ T¼††_Ž ÒBð[DØc„(Oz0…íìÜlýw¼Ën{ã;l’+d^zîQ{ú{ß´ÓG_"íe•­Â’’\$Í:•P $/†½¢æ'B™±BIˆ;•yu³±(®2è…/+41¸Ž `·2¡‡GqîA‹ŽŒðd'¿ÜZ(A»VcÕ�ûÚ¿ý ;s訽ï>d6ÙÓìîìá çþŠjæWhRu£QB1 ÔV– ìÀð&[¾@-çLxq­ß ¹J-¦h¨²ìÅo—B¯ÚPwÉÆf–­».wÿ°ÎÊ’ò 8Cœ8›ëooµ Îÿ¯VJÖ[è²}=[­½Ìgo–:¬›£âm(oK�îh>æV™Åp³w_Dé*ZwÿvÛzχì®Ûßa/~Æyôkv„skZ±d Z}‚�­RZ!•,·uEO~È2Iαfܦ€°@N“Ûð¿ÊsÃ.`Óàε·¶ß®·dóóœnU$ã 5s” 5›= ·£_”1Ç �žCµ“!üæìþžµO¯Ùu;vØ~ÎÐï÷QXÜÓA- ^–9M45=g­öwŽž°n„œ˜™µF~kÅ6èA0ýTƒ¶r²·—™Â<µºµ«½à–0.’êì°Î¾~ÿuôôZ'³Žvv(Ÿ¡Y¢¥gê9]`œ1´dÇ;Fm´cÌ.´OÙ\™Í¬%ZšzñÐI—ÔÇѵMÚØÉ g�}Œ›¹Bæ¶ÞlÛ¯ÙÃÝЙóþZò ‰$YJ ’E³q€:8..ÇKe’PZùÚˆ„¨.àÜù#¯í\€ �1€–b´MY©ÖSŽ*ì|¥Ç+™÷€ÄüúÐÒÈ™N[‹#ê˸™�]@/<ó¼½üÍ'­r–Búx£VêÈ÷<‹HM©é«À:Ø[ð‹H-Œ¶ô1Mœdç; YRk£ûºú8`ÚÓjz©[°¨…ê‚´’Dú~v�ÚY‚æ&ŽÄÏqØt¹•/wÐòèΡî!…öoáæ0ú‚ÅÖe›ì˜¶éö {¾6agVgm†Ck¬et0ÆØÄNça³¶òÅ� ³’]×î·AÎ ®á=Î˯%šlê¡ç]CAµ ^ªñ^K¸ÇaŽÑTøÒ2è"i)}m{­ ÐO ЮA -™p�UBɬg úül Ôæ§×+‚£ƒ¢˜ÂÔönêÐv(MjÊ­%ö.Ú¦z‡{ÖŽœãl qªF5´“�d%ëçæ�“ îæ)ÌIº„a ¬�éáìÒ¯šÊ [­›Âïb$ßIs>¶ÀàO +Aµj(^�Ö%8˜šÜÊ‘4^Fi2+¿šk•Ÿç=ü®ÍƒÖ¹…ï!qNqû ‹PÕ^^m·pQÍÎíXaÁŽ+6Án_-fmåz�Î,p'ÑùR§]³ó&Ú¹ÛÎq¾aq:NI*Ñ…ºËe-åsþäŸæ!�«Áy–UIfµ¶òÚ[€Á�ÑP+\"Re _óîdÂ: dÈz—ûè}o?iiÓ¤G''j ¤x-ÔF!嚺—ŸN�4hJ&šG<'UÍ}—£?„œ²!æiнð$„s" ß­L¯‰†+R-0@ÔÉ¥ !·ö×+-™¨%êU Z¹qø:kXeP¹À q� ´=]4GÝŽ„Zh:¹¨kh³us=~7ÓP½€*°‰éá¾-›úXql³).­ØÕÁÕp ,µB””#&pƒm{ã›íλïä:¸aèd“Zmf] »ÒÔQGÇ}<­1–‘wlîµåÅ Z#ô‚×Ñ�ƒZ­¶7Üó^û›/ü¡ó\áLœzK‚uæ¼ÂÕŃlIÓs£ê¯õ… ̆ �.dó$]x’) y…àwFHÌ®?`H}}ªõâS ‹âL�‹Œ+½2Ô §)´Ž× }”âI5 EPtšRj(ÇŸJW?a@C±eûª¡RP“ë~·<Ü[ú”RîR(ØE.‰:Êëá£ßø[{úóö﮻mÿÛÞe#×ÞÌkfúwÆ%ç¸ëh• i\¨tÐ;'zžùéðö;l’™ ÷ up/Ëή¿Óßôì?˜€OMO³irE&= Ce‹ô÷c6T.Ù z’N"ï‰ðrq9L‘´œ«•µÈ�ð2«AòÏ”©WÅråI±@jàÉå)»¥”ÔÄ'ˆþ*»kUã= 1ŠŽh‚ WYÔ ÓÛ7ÜRÏv„â&DpG& ¦1†šjÍ ÙÈúÔÿÌžû´]wÝkw}è£Ösã \WË21xJ_J VK$Ù×jSÜÒÇÒ²ö ,Ô¸ZŽî¡·o«íÜ{­û¦Ÿ�Œœ*Qñ®x6yÜyÓ6{ØÛÐl¨Ô3­T5ÝàINYÞ*ärë#(Gᡨ }�KQ‚oÑ ŒžBe#œÉ”œx�8QøâS×M…Ù\#^}@M5]I`ª�÷�ðHCJ!O(‡ÆŽJGHZjæ#Š\üT±#_ÐÎ>õ=;ö“·Ýoÿ ¤f-®˜ÐÖþ5кÇxh¸ß6q¥íôB�ÕMn@a-ÿ–ën±ƒßùfäÙe.Έ”XOn5@r¥¼‚Hõ ´Ë<7T€: 4òM^�O,hGÍw±’çÒóðõÌ]š“Ø=|QÞꨑ©f¯ÓTm¬å�¾’‚úI¦jY QŠÂK†ÌäÂW¾/LL»È%C¥…â$žãEž×hâµ>¡äkZ¨B!D·•›Kª³Óö�Ïü®M�;gïüä/Zß(@ÛP„2šÓz«ÙÁÂ� ]Ü8Zã^Äy^$u´õqû kúÂaU4ò&>/2‰×féIÑ#oá^»±HɲQjüðÈïiû¡0èˆZïC2GPPŽçhò…ƒ�d\™+ƒÂNˆQ:‘^"ØÀn¸DX:Iì×Ú¦ §’˜o S’’𯉎ÃM ÑÃAu:CJ\©¡ QËB5JZ›ðÅ*FN�ô[½iU^â*Ø�¼¨ºÿ}?ÅÕòÜ#LÓ¯#½Âna'wÚÚÁCc¶‡Í«ãS|“ˆoiIQ圛Ñeßš9eƒòh ìhf ° ¯j6V1<™”~3Mñð9=�aÈ.xrÑzdnçˆÊW3(8mÄ?y¹Hëby߬æž8ª`ž^:•HÞ9­€IUT¸)q€Á»‡:NrDhÄõxŽ¡ñóˆ‚ÂWÊT}=•Ý»ÆÀöèWÿÒFÜf##û!Ä!ÆF%:i�}8Íwˆ^>{ÔÎMpWà®^csÏñÀÖØÖÎæèË\¸+ySÊž¾ò—rÎ+xn¬ëˆ(GüBZžù<Â÷>W¸H!³šñ‚ñ²Éñ›Š^duo¯b4ƒi6 P¢,62õ®@S;…fE ·QdB�²J"#žg…X åN ÷õ�vPÊ©¬/|å_½®.Se(Á—¶–W«e[fMáå§¿m;w_KÍ׋V¸´ºuÅž9y‚›Q–ý*ú¾îqÚ´•Ëû|Ck#GÁP’€çK�0ÊCÆ èmIä$ã\Ú¾bP–¤åJÊoçȵ¾Î•P¢hœ IX‘š�,RMà•ìÞ·Þd/;ÇÅ™ ¾]Tc,À[G^,ù¦ÈËáS£6ÈëåÎnía€7gOôâÏ…ç 5?ÄEƒW)¢FzùÇEuíÈÞˆ‹`F5DÛ¸Uó%IŒ¢Ñp%Œˆïà •gTëטj~à÷Û/üƒûدÜÁÕìý¾«¶W4/ŒO§XBÕ=ûΖXó�u]…„5B1…¼‰~to^ûSá;{®� ,Åð’÷@5ñJ#â‹öºÂ÷w�¨§_Y‡R´øÙÆ’Ÿ'8yá%;?s†)à/‘Ú9ÿÀ~JAÊ%»FúÇFùôß[^4Pp!çÂ3‘vÝ/b'ÿ4ËHì¹ïrfcȱ‘µ¿¹óE�-óâ©“p%ntH;ÇN\û‹2%ûÈÇï±}„›BªcvóûäoÞËaÑ­œÿOH¤45`jVã8xÔt±Ñ$—äÈK<„›h8®xCÐÞÏgé; ÁšHy† SMÒõÂw š¯ÂoJ#T/”@c$�eÐ…–, QÐÔQímàHÛ8oõÆHË-¾äÂØ`•]G/?ÅQØjQ_›ÐU¬¤_t*üÄ›Ò÷uœ+(Ý+îTãKdÒÅãL¹�$žAð!EXg$s’©l”(±]ëçÿÞìÃ?5ÌiÞ³ ’Ù‚½óîV¾øq¿}æÓ�²«ö8skÄM¿©9½Œ2ØläݺqåSîUCëPõÐÁ—`(€‹!4Mµn‚$‚9-®‡'Å#ðÕ ?Ñ&ŽÒÕ ¯�J«¼v^åóu}œQe?ÛMÉ »âµÄ›ÊÎDÌž?a‹(‡.ŸŽqÉE¥™ÇΗxÇ$wäâ¢8�±î¹!FýÚ$TrN€ZÌÈŽ:VJHÈÁNNY÷á–¸çïW>öûÄ|…‹~±‡½t+£VZ:m…É#6²ó¬ýò}«½å½·²·-> ¡Œ®Ë¬Ó�tUæ±R—Ò «Î s@äÌeƒ§\ø)žÓ N%xq§¯^øyà%å�ôT®R4îBbaÿžkmÅ8¯•¶¢ŸÓWØPŒ5j··³…SQ”`iú‚ŸOô­Ýžñ̶Wÿð‹ðå8Î)nŠ59Áº¬ÙP\;EM\ë‘J¼¡J)‚Gx^=1%:šúüVnøüõŸ¹Í>ñN¾×7Ήš#OÆçŸØ‚ølÉbïߌ}Lã‚_{› mò¯†I˜aRºŠ¡f[ÆŸþ^ëµinî†<ätêL,FñB'œ^r58M ¹©ÙWáËäÂWœ/cmbÇ�·XËÐV°ÊÖÛÝo“4ï‹L[WUøàê]�Ö‘Êœb*ð–rúìIî†ÐrnnB©4ËH.oYÜM|çQ¶ÿÿrod6T€È™ÈÂÃ^O6Iî)½2y¨lg#çoþì­öÑ{hþ8Å»Àþ¸¥¹³6q�ÏÀ”ûÈ­´ô¾¥›EvúÙ»¢ß~ãŸ}Ðn¿ï&×ÕëY @„™`-)ZB²½U¨ó8¢ïÜ)#Í}„ð$IÁå ,O ÒB¸+Ç…Ÿ—º¾fëî»õ�wóýâNN•mûN6‘²-�Ñ@øIHOƒkÀVæìüÉãÒ«s…ùO5”7¸LOÌg2²2¬ Ï)€÷—^óƒJ£¹m¦*…˜$@þ×­Îuu÷Ú?þÔ­öÓwêCË:•ùÿeîÿa”<1ú"ŸYÕ�m^sT{´­º“‘p©Šà¶LÛ'ý:û™¿¿�ìñ9ÚÈ!#açAQNÙytF˜˜àÚÄX,­çÛé9¦\jøóü(¶¨óÔ{v)Bò§ž JZ«ƒ[7Ûöy·á=ÁËÓvj�s‹|Ðb†ƒ¨ÛøpT…Z®V@£ÿ+Ev/W9Q4zn”¦Qûs¾‚ƒœvh†ÛÉéi7ðñ^Æl¬Û€&a!™P†°=Q–‡(ÔúXB/Û§ÿÛŸ¿Ù~üöY �1¶òYö ß2­YdõkôÔs ö| ¨d¥íýìòiYf µ´À`yÁl¿ø�ï´þü[mËÈv�¥¦„$Q.ñ�P£�äÕ_˜¨CAß•C!)0ã{v�N¶¢*�>[+U!–‰ÿÃ+ž}Š‹rnÙ½ÓF>ô[b‰>z©sýÌ.p Þ±ÙEëá[ŒÝœqÐÌ`•�)-ì2.c�=ûÃä;ÇÌ|*)emÿÉÍäWŠõNApGR÷«¸œ6ßIDATÙx@k+a(-Èû³A°!rq#ŸŠ&¨¯îm´ÿîïÝhï¾�/uqAƒFúKì�_Y8AsÏN"U�UWf¹Òå§gFx£6æé¶ûØ™3M[A-¡¯W“ÚÕUµ·ÿh¯Ýzï›íéG'퉇�ØYÎ ¬òN§xÕo:«™gª°hRñ¿.'.HÁÄ|äC8BRžSp—Ú/á6L`Hîh/-ÇÖ¹Çxß3î¼ëN›ïêf»¯ƒ ‡5¦ƒ%;Ïi!IéÈÜ2GÙ†í¥“§èÿ™)Ð"´Ð÷yö9_^×Ì!^[gÂnîµD×�Û‘Oñçy%‡ ÌÆ €vŠY¯aÈ'¥³ž¬ç> °)D+|º°á·åÍvÿ¾Ó¶Ê­*ügëù9ê­~Nlêׂ{~†•À }6¸©—­R|¢†k_J §¹BŽûI\]ƒZþK§==Ëvßû»ì¶·Üj'_¸Á¾ýð ;óü¨-èš)‚.™P3.ƃÍb=‰we0už�£nÉKˆ Qì¬àA‰P LiåÚ)øM·Ýl×½ÿ=6¾cgØú%>°µW¯Ÿéì J¼Ö¡OWÓÕÓü�ÒýíÞ:lG9FÖÃA”±oý�¿Ò¦U¿‘œtƒç8òá^üˆpá*¯R’�‹Ÿ,]Læ’þœc]˜îÏ &û%´%¶:ÿíÓìÖ�[l°|F—qÔŠZ=yœÂ U3èaœi° nüjïx£u÷ 1âÔ%ûô»9·_eÝ`�i— K‘aSKz[l÷®k?0fSc×r¨´j§NÛ;m–x»¶Ê†K% )•ר,%±îyñĽp“–`y@ O;s¿jâýÓDV3Ý5Èy„¯§ÆßeÕk¯µyÞüm!ÎYÎ,–IKù“,†ø é ³(nƒ@`Ræ%h•9¤pýÜ´U¾Å•wß{†M¬ìFÖfXñ\ÑÄC2îox²+ìÈŠÇ» ¸P!¥Z´.)R‚9¯78U{düY�Avßþ᱃Ǯ³ßâ^¿ÛF8hI�Yc¤« Ê(®Ÿ‰QóK\½_×x çÆð^�5óöí>Zî 'Ùï¸RЕ/|€q�5vfÖeº‰^½mîÙLzÔ®çʹ½÷q,lb˜[<ªümêÔ,_ åÀ(‡=ª´D4¤£š…#‡Z'åÀ·ž§¹x‡«Lr§1£ÿV¶Š·q¥LÍÝ~ãuf·Þf“ÜQ4«>›Z}’÷ù×s¨´�RžÑŒ²�¨>s7Ç ¶L¾�.:n~Ž©áÍ\Zõ ¾}4Ç^ÂVN/å³Á“³%QaÖ€šŸžŸ(7™ þfÉ\DÎ…Õ �,¹"¸Õp›%PšïÇžxÎ>uäŒýêGî¶÷ÜÉr !Ú%ª‡j‰ž€8 ¹P›oŽ”§hòÙP)ar4|‘¦XãÿÕÄû´íÌÜIìÚÄ÷~·ØøÒ…Xc�µdm}¾…/„/ó½áÛÙ›Ï ÜÉ)›?�Mpücf‰ngŽîIGÀ¡Jénb}r¯@:%m-\ESd;ø g+\D1Ë<¾ÂÖð9”¡�ÉIÆ3z#Yâè˜XlfwðÍ|ïPŸ¯×1´Zª“¬mø´”îÀ·�ÓʬѲ ±•ì{øY;qnŒšÏ‰"¯ý1”€š‹o“‘/äî’Ä+™k  )&VL“šb\ìÜP ¸kö9ªs$¾.a.‚’Am³Š[8Œ;/Øÿ~Õ¾vÇ^ûÔ·ÚM#st�\¸¤…þùÖ--µ‡)㦽ÜvŠýl¬ìfPH¿NM졦WÀ]PënkK·MÑ­è¢é‰•qÛÊgÚÏÏ¡<Œ7$ ½”ÇÝZªÚŽk8�ÓZ±žë7qÙVÆle)Ù(ß Zd/^•›@èÊmØ‹ �œB�4Ç5¦¦NëÌp‰Ä5(Ç™“¬Ò±ys3§’–é––äµRÛ5——Ü5«Ñ©åÃŒö÷± è4÷hp[5Úûgpõáêí �úìÙ!N@YÕ¶2M‹ý[AU²ºtës#@´ÆêZ|¬�Dk}Þú²fC€Ü)€' ô”@sºuòu®’ð´O£cˆÐªb™ƒ’ßúÎ vðÅQûÀ»öۇ߶ɶö15d…°Ê+S×\�楟\®ŽsœÛAºv²s†�“~p³`½”R…åRu?åb?ïÕ§Ì î¤s¡Æ­£ƒûíÔØAæÖ,*¡'U„1ÐÉ×:ÙeSã¦}˜¢ žèBέ�ÛöÞ^;½0î¢" M-Ôè9xÕA-EÕÔ] ‚yî1>Ïq³ë»ìÉÓãÌãlLu EÔk õ×ReYéNÒ¢œ£D®ãbë£ó+Þ ôP»;€uQøƒ“cöüý¡=ùØw£ð™!èÛÁ¹ð³De»Û šË@Òv�ÚM”¸Æ:¼2ÃQà‚ýË)ëeÍÐÐŽ½ ~>Ì=A¼Ë^R�º~j¤r�´œàzH‚‘2{�„Êì«pUË“ÏÚ#ÏñY˜â�mÝÜÉ-`j"ùLÏ6ká2ˆÊ*×½ò·BÁwµo¡˜””c¼«4—Kk=ÜàÁz‚àW%>çɹw˜-ÖKHaP:Û6ïµÙ2ßUIzÄl|¢¦È�£ý\ 3³²ÀH½‡—4kìäõöÃÚœá)®f×-f›x•\fmcŒ®© �ëÃV*ܺ»ÍlñÞ‚½••½.Âvð"­Â¼�AÊÛIW6ðòóöÌïÿ¾=ùôAZ‚6º@¶�ëÈ à£q‹DwÁc‡œÅyd¡� ‡ÔÆEŸâãuù¿|ŒE…˘+hZkMZ)jÔ®B\o"Y‡¦ MÁâÍL9Ó ¬È‰×Z‘Ó[´ö¶5;wúœýÞçÆì«»ÕÞù–ívï-ÝvÝÞÖ¦½P«¤¹„"L¬rÀ²}{êÎ" 6Pr§_¡m«�[æ>AR±j&¡YÄìÊ7‚ Û ã�±ùQ‹{Ù`Q«M“,3>Èü®ÁÇV#G8�1Èn\]L=¾¢´Ù�I-Ò4’!ów­Wè¦Ýdv÷¾6Êâ} ä$}M{ÕôWèN–Õ*ÀS7ȇ¹'êäë-|[Q<ùmûë¿üK;ÍÆ.߀'j>-‚HX’õbu‡žŒÛî(gD<`<>¼Æ‡#ÖŽ8ð2� €…•Ãl_š¢_î×È´Ê÷‘h¦ï5œIz(I„5ôE @VíiϺ„UcjWb°¥oœ:~Ú>sìœ}uÇf{û;:ì¾·ôÛÞ]œ¹/3ΧÆ,®\àMÙw1-³O€[@(Œ–}³Þ º’…öi�åSÉ•1f<0·8i=Ý›¹mŒuñ³âO=&ŒPœâ©Ds=k7ôŒØîØÝ®¥eî ¤ ÐÆM•¤®i×µ²,èqSYÁN1vYá½ý—H1ðMjõÔÑ�/å“]qvpŒuŸöÖNÛ|ö9û›/ÛS�?á Ò\øªù�W¿’0‘%BýÂ'GÏo݉CSºÀ`šV'2¹:EùrŠñª–“ÕÐ(8p÷7{ºzïÖ>—Dä¨aÇq+é¼L _~J 2®(p¬æXŠ ƒn 0)…vÍ2j°›nÛe÷¼e‡ÝrK§ 22gEµ~yÅné³Ñ ׬0â_¦WˆK9ø¯FBè}y‡ ¯ñIVšÖɦ�ÜúUÒ�~¾È]ƒ*~ïb+ðÒϽÃúú·ººÙ—K_a×n•Aj•qí5¼dƒ\&yŠ/œÎryÄ�]{ìAµr¾¬­Â§v0Ó9@:^:jµÇ²Cßz˜�ŸSÌû¹¶¸–yÕì«æ7¾4ÇEÅ#¯=$Ñ‘Fðp‘®«²$×vf'j]¦gýÊׯ½Ï쟪q|U³a @Lf[Å¿]®Tî SOTˆ ÝÒ@±‰µz¢umαÉx,´Hh¼U·›R-"^ˆÍØwzÚûÆóÜ»7d7ܶÃn}Óf»á†»nû>W™Ú�³v�Õ,¯éL=¿M¸úP­/JÁ;øIßÊIœU¹ÜqeM—DÇ¡Œ 5¼JA¹W°È=µã¼¦-‚#¼5]§ÚŒ�ñ0pä¿mœ›Ÿ¶)–rûGÏ0~Ùagõ¡ �N¦5)k<À¦�m'�Ûä#ß²çXà9ÇöšVêK§Rå³�C$º{©¹ðÕMʸ�¡!m\ñï8�˜�’2 S¼e¬ðáMˆþíF…¯˜W¢Êû—+•åÿ¢ÐÞ‰b3R÷–LÒ@Ž'Q£ël9<Ä“µ;¹±¼k ðï¡>FРˆ1‚Ôb‚›8:qÖþ*ƒµÍ}víM{ìú[wÚÞýƒvÍÖvè`àXX"w²|¼Â›Æ5ÙôâºEdblÅz·t15œ5Y‹±^t%ÚŒÑÏtršõõõkÞük>ÂO5Œ<¨G_ežßÍ´or‘ëç™�è‘CÆìMÜ10ØÉU4LûºÇÏ[ËáC6ýäwíϲ –¥uZ·•õ„Ø[�‚0V“ß‚,óØÈ¥‘d˜ _cšºXs˜ VØa$!Øw£R�*+Ëz.}9�/k]‘T*­ß)——­T+7´1PR7àM>ЬðÌeLrƒá› ¼Á „:0Fðô·‰3ÿÑ5èn IÀ[m FÏ�·oŸ9o�þõãì-èD!zlÛÎ>®‘ïµ�#]6<\¶ÁšßŠÜÕ3§{~¦ŽXo×­ÖÇ®œ”ZOÒMäú‰¦¡•5�¥Ê4G "±Pû™=Ðë ‘4ØÂìc?Ã1oú®±VýŠtóß{܆X]<ýÜ vøèQ'\‹?-4ïm¼âU«¤÷ *l}A\ó|?K!)‹$Q¯ùà¢BU˜ÜÙN¾†¨éö¤$ÂQelÕçviÚpZX-|G!Ob#$…8pïo¡µÿ¬“Ë'§Æ=Áˆ|)™éL¹ Ó� åïE4ÈLü…"PFžia© –Ĥ,¾;˜I·^³jX§šÖÆma=]\3ÛÉÆÒA㵃µu¯qà²Óöïßm«�ÜÈš¼6ej}•ÓÙÚoµy.„ä]½ê§XÁ㦅ƭ^U¶¤U—H‡f¾„ûè‰ÓVŸµ%.|š¿0Éá .—dLàªÄ L_4Õ P7T«Ö«‰×êž7÷Z.¦ t¥Wjž„PÚ^øÊ«g”0w+ß@Tà"í–W'<áëÚ4hË´b\¹û�¿ô×ÿúP¼�LPß‹ðý·Þ¿“•�§;Û;4мy€âÕil\øÕõΠȴ|ʤg ·-P6[¥YŽþØe¢Pšip“R¨KqaSÐ:^fªUn£9¦fêzXÝC¨›Ç´øâ& XixÓϨßv0ô¯ðb§Âþ}}©L;›HÆ×x#¿¸QZÑ GmWs¬ýþZØñÅüÞä§\Fá/ÜK¾±øÊ’©—X8‚Wj?­a‰þajj²P¬Þö~þ¤çiƒG�Üx¼oÏ�ÿíþ�®úKÞÑ¿Ò4~&})XR™K~޿ĕmÕðl4àT KÁ’Ÿ?á[§A»€Ûq<4ÅKqêp9r|áyA©Р/–¾T˜õþš’SawÉV­Rdš«ï_$ó‚ÇM+ &ÞõªŠ—›øÜßËÎ5ß1„¯ô݆9ñç< îíŸç¨Ë¦›Ú¿¤Ú¿²ôé/~íO~Cð+1W4È„ZZ«Ÿfýå̇‡;y)’§„’§˜º”i¼VU¸jžîP̦¸^“›!®Rzü4ÒÎy'<—"¶6AxÍM£vçË#¥ø„«Öåô£Mœ{Ú*X‚H hÓ£2 Ñ…�¯Vd/8l/tlµ®â™_vG~3 Z\D†D/œî†’L4ä OXþ$�ô=›T]sË­ tUË£«µâ§ƒÎ•=å•›ññs³›¶/²§ÿ�v.6¨1RÓìu@|Ö‘ S°ÈAzÊ@OØ3Ø@q\�’a 7G“PTJ!Ü$p|ªu4õ¹0´èä5—8QOs­TE1û#TƒAýüݿܪÕ^ áÎM¹Ž­©i×^]£n½Â�)¨úw�ëU·’Á8ϲ“€Ã²¿aw®t~ª£xAÃ5í+s[ê û )Šÿò‹óÇCÈ›ï«Õ¾Áµ5=QûW·¾§“‘¹Ö9½ÊióžK³â7¼u—g*`)¬Y‡ÛÃËŒŒLÏ$ ¨ ³Râ%ƒdSÓ8Q2NÅ� ŸÁ¤ ð¥\Oaü‰¦P-€ Pˆ¬RN4=§â0é/9ø%+€è�ŒøŽ—b¯ã]és¥ÛÈ–¹Î–M·½e¢í_Õ#_¡c}ŠWiÿþ{÷±÷íï:Z;¶jÄ;¿(%Cb4—Nƒ´»Äm“¦›:¸ ɤðz°üú€$’ÛŽãÁeÂ#Üä ¨üУâx î×Äy-ö¼ˆ/  )ÌãSØê1<ž`(ÏôŸñ°ÔgÀëô Ü܉�s¸è�£5”VÓðNv"UY‡æ#WçØªòÖ/þÕn¸ô넚A­ p%Η_þÖa¾ëûŸ/WWÔ t´ó¾^…ÂOõË/yVå�”˜oþÉÊV$PS@`é)6±½:}`® „®3 FH•€ã dÊÑbðEáEÚ£ñðäÂëϺÿ"‡¯4ð�¾J£gsˆ×A u\�s¸‰¼¿�å‰Ufª +øñ)|¥ñ}�‚©xNLž~iÓÀŽ 4=`aƒåv®vgz(Aç¬x†šüŠ jÎŒ0Bï=Žãf�g:ÂULY¹ÀÜÃCꦿTÐ*8hèÏ� Sn‡¹•#zpž‹ËãI‹’/зžŠ+rNÒ©L ¤( wü â¸ÙŸ¢5††Š„=Ç)‘À÷اžnJCyÖ]…ÊòòìœêØßÿ³¿úÜ¿…Òd~`Pj(Áãƒ;gùØó{é Z%”DÁ`e�ãâóL‡/A<,g4‡8°ŽÛÀLr"8„ø’Žê)x˜Âýß­ Êé`��P<©¸ ®R¼”–윇 Ç5ƉXÆU¬¤$8 /h\ÎñŒ®F0÷*4¹Ãv¨Ò¢À¯“­i:¿Ä �Qßo~᫟ýß‚‹ìùš@INLžzdÓÀÎÑjmõ= œZ:xÙ¡ýqZ„Éž2¦ÿ†qHx�uI$™&Ì(ç –ƒ=a7¢HÔø¥îJ~G^¢�%Úþç(� ý€¡"á"”b åÀÛ� ;ÒHiñ/òXüÂãxÙîV¸SÌÈÀ‰ÉTO‹<Þç/±�f~~…šÿk¯µð%š×¬"‚<Ž<ÉË’ûY ééhgUŠZ¤[³ÕTe!W& )y$òìOIá�램^‚Å›"HÀJ!HDÚóŠH�AÄV\!êßñõ¦ ØQج* <°”Fr; C�œ—¸¦¢ˆªž�Ü ‘`‚vn!D­NÅñ=¾èæÓ6LõØṁ¯´#æg¿ð•ÏþQ|­æuQ1�¼¸e`Ç—X?@7°_óc)‚²ä{êR‹YLl»Tš!äº)ãu�Ðn w xä­ƒ¨ÿ:RÆÛ±²,/À„q=Öê~'©øîˆdy²B�ÒrKÄH:áÈJþz´:ÅMô„ïdä§�* ·š³õ¬ƒëîµápyVS½Êƒ¼ÿÈŸ}ås�8#¯Ãƒd_os˵û—™ìüW\�²½�ýnªQhÝt*³Êqΰ³àÈ.kòHT ˜;“°êP0¢LB“qÁ6¥¥‰„Œ×=O²A9²ÞÛ{Ó+<çšÚW¼+¾~â.ÛjŽHDðœ�莀çq�+8Bt<µ-&µ±Êª/©ëé /™j••³`ý�+»÷¡‡þ)ÍêëgÄÂÅìßÿæ�ltüuˆН` µêî}AÙT× £º|9^fLœ„µÎö˜À=¨Qøb¾^)šk‚ÏK s¥P©Ô£â F]A"R´Ü„±¶Qoú½„SzËå1DCØ &O(u¤¤³By~Oƒ�CZW˜�3ô¾€7ˆeúø^TiåRMëðJµRísk…ÒïüŃŸ9)ʯ·ñ¼¼ÞD›éÝ´÷-»j-…O0�ù(ª~KYhô×¥©Ÿ…ƒx±C‰x¡$–$P'”®@—v†*0&€1’vo<„—¡Ñ‘BøäQi�ç5ÑiË+ÚÀ4 `Âx®B¢å8ÀÀË0G8Hn u|GÕǦ�õºX…í@xñ]UzÛÈÇ%©ÙCðùbµð'þÐg�‰ôË(ÇÿQÌîÝ÷·w”Wïâ…Í��àÛÉåõÔ²ÁX?×35„Ib‰+÷gîšar«-�ÇP!äæ=ÄŸ#xqƒ“kž‘/å*b´‰–G!U)Mq¢à…¼EÍ}…yÓíµÙUZ)–ÔC¾P9äö€Øhª×Û´€ÚlJ˜€ÿø=Œ.|u|~ùÛ�<òï´Óð‡nÄãsà oÝÆ.°½¼Û߇àv’ñ!\vQˆþ~b]á‹CdbNž‹¸öú¸.7ò@£¢Pe«ŠòRЇã8…'�#†ÃTxÑv80Èée^O÷"Ž PPà%xpRc�á<Áàî{�´«‡¿øµÏsröª¹*�«¸*�«¸*�«¸*�«¸*�«¸*�«¸*�«¸*�žþ?a¨!Õ¡®ïâIEND®B`‚heldercorreia-speedcrunch-e7ca37f/src/resources/speedcrunch.ico000066400000000000000000013274561526573132500251570ustar00rootroot00000000000000 hv ˆ Þ  ¨f00 ¨%@@ (B¶D€€ (Þ† ( �(  ;%'<%(;%'B*-C+."F-0#H/2#K25#P6:#W=?#[AD#^EI"aINdMWeLVdLV<%(;$'=&)_>')Ã@(+ÞB*,ßD+/ÞF-1ÞK26ÞS9<ÞW=AßZBGÞ^FNÃcKT_hPZdLV9#&:%'_9#&ö:$&ÿ;#&ÿ<$'ÿ@+.ÿD45ÿK:9ÿP;:ÿP9=ÿT&*ÿ?'-ÿA*1ÿN76ÿ—ƒ\ÿ ˆdÿX?BÿU<@ßZ@C#>)+#;&(Þ<((ÿ@,+ÿF43ÿA*+ÿ>(+ÿ<&*ÿ='*ÿB,.ÿ[D=ÿ¹•yÿ¾•‡ÿV=?ÿQ8;ÞV<>#@+.#<(*Þ<')ÿ?*+ÿB,-ÿM<5ÿeS:ÿ†lFÿ–~Uÿ§“bÿز‘ÿÛ¨žÿ†`aÿG/3ÿJ15ÞN58#D/1#@+-Þ@+,ÿB,/ÿcZFÿ�˜SÿÁ¤Tÿ×¶fÿϱvÿÄž�ÿ¬~‚ÿnMVÿC,/ÿA*.ÿE-1ÞI04#H35#E/1ÞE.1ÿQ<<ÿ©¤qÿ²“[ÿ‡dJÿlRBÿ[D;ÿP97ÿD//ÿA+,ÿ@*,ÿA*,ÿB+.ÞF-1#L69#I25ßJ26ÿV?@ÿÀ¬mÿª�\ÿI26ÿB+/ÿ@*,ÿ?)*ÿ>))ÿC-/ÿN8@ÿC-.ÿD-.ßG/1#O9<"L59ÞN6:ÿS9?ÿ…kRÿȱiÿ ŽcÿybSÿaGEÿbCOÿwRkÿŒhŽÿpUqÿA+,ÿB--ÞF/0"Q;>O8<ÃQ8=ÿY=Dÿ[?GÿpWOÿ¢�mÿÇ£‹ÿ¿��ÿ»ƒ¥ÿ¢qžÿcFZÿ<&*ÿ:$&ÿ>(*ÃD./X?DT<@_S:?öWCÃV=BÞT:?ßO7;ÞI25ÞC-/Þ>)+Þ<')ß:%'Þ9%'Ã:%'_:$&;%'TC#R;>#M79#H24#C.0#@*-#>(+"=(*;%(;%':$'(0 ;$'5 "?(*B*-D,/F-0G/1I03K25M47P7:V=>Z@A\CE^EH`HLbJOaIQ[BO_FP9#&:$&A),?(+ A),[B*-{D+.E-/G.1I03J25M48T:<W=?Y@C[BF^EJ{`HN[bIQ lU]bJTbJU6"$9#&7!#=&)b=&)Ù>')þ>'*ÿ@(+ÿA),ÿC+.ÿD,0ÿF.2ÿI05ÿP69ÿS9<ÿU<@ÿW?CÿZBHÿ]EMþaIRÙeLVcbIVbJT^FP+F-/;%'b:$'õ:$&ÿ;%'ÿ<&(ÿ>')ÿ>'*ÿ>&*ÿ?&*ÿ@',ÿB*/ÿI03ÿL38ÿP8=ÿU() :%'Ù7"$ÿ8"%ÿ:#&ÿ:"$ÿ9"$ÿ?-.ÿGA@ÿOUNÿYhWÿckWÿjePÿfXDÿ\H<ÿQ:=ÿR;BÿYBJÿ[DNÿ^FQÿaIRÙaIQ aIPA,-?++[<((þ9$%ÿ7"#ÿ7"#ÿA=Bÿ\{zÿq­¥ÿzžÿ�ÍŸÿ‘Û™ÿ¥Ö‘ÿ¹ÆuÿƼdÿηXÿ²š[ÿq[MÿS=CÿYAIÿZCKÿ]ELþ`HM[aJOC./?+,{<((ÿ;''ÿ?15ÿPp†ÿX¤»ÿzÍÖÿÙÊÿ~Ëœÿj£uÿv“cÿ{†[ÿŒ�Hÿ¤�Iÿ͵RÿçÒhÿÖÁdÿ€lOÿSFÿbŸÁÿgÀÔÿ~ÊÊÿp”†ÿSTKÿC20ÿA*-ÿ@)-ÿA*0ÿI24ÿ_G<ÿ—‚TÿƵeÿ«š`ÿ_HGÿT;AÿW>Cÿ[BE^EGD/0?*,<))ÿ=*)ÿ>)(ÿLGLÿq¡¢ÿ]pjÿA,-ÿ<$'ÿ>'*ÿ?(+ÿ@*-ÿA+/ÿC-1ÿG03ÿQ9:ÿ¢Žiÿ°—kÿv\TÿP7=ÿT;?ÿX?B[BDB,/>(*:%'ÿ<((ÿ?++ÿ@++ÿF53ÿB--ÿA,,ÿ@+,ÿ?(+ÿ?(+ÿ?(,ÿ?)-ÿ?(-ÿ=(-ÿZC<ÿÆ¡†ÿÓ«—ÿ€b_ÿM58ÿR8;ÿV<>X?AD.1?*,:&'ÿ:%'ÿ=)*ÿA,,ÿB--ÿC..ÿB,-ÿ@*,ÿ>)+ÿ?)*ÿC-+ÿJ6/ÿ\H9ÿŒtXÿά�ÿíº•ÿØ£›ÿjMLÿJ25ÿN58ÿR8;U;=F02@+-<')ÿ<')ÿ>(*ÿ@*,ÿB,-ÿB..ÿP@8ÿiY>ÿ�vDÿ®�Wÿ»žfÿ½ªjÿÈ·rÿëÇ›ÿ궬ÿÏœ¤ÿ…^aÿE.2ÿE-2ÿG/4ÿK37N59H35B.0>)+ÿ?)+ÿA+-ÿB+.ÿG42ÿzyUÿ¥¢Vÿ¸¦SÿÖ³ZÿâÁmÿÞÀ|ÿÛ¹‡ÿÞ°–ÿÚž¦ÿ®z�ÿmMVÿC,/ÿA*.ÿB+/ÿD-1ÿI04K26L68E02A,.ÿB,.ÿE.0ÿF/2ÿ}z^ÿ§¯eÿµŸKÿ×RÿÃ�]ÿ²—^ÿŸ„ZÿŽp[ÿy[Uÿ^DCÿH11ÿ@*,ÿ@),ÿ@),ÿ@),ÿB+.ÿG.1I03O9<I35D/1ÿE/2ÿH03ÿS>>ÿ³±€ÿǰkÿ­}[ÿsRHÿT<:ÿI23ÿD.0ÿB-.ÿA,-ÿA,,ÿB--ÿC-.ÿC-.ÿB+-ÿA),ÿA*-ÿE,/G.1R<>K58G13ÿI15ÿK37ÿV@Aÿ¼±uÿÞÁuÿ|aNÿE-3ÿI14ÿF/1ÿD-/ÿB,.ÿC-.ÿC--ÿB,,ÿ?**ÿ>**ÿA,,ÿC,-ÿC-.ÿF/0I13U>AN7:J36ÿL47ÿO6;ÿR8>ÿ–XÿåËjÿ»£_ÿ`JBÿF/3ÿC,/ÿA*-ÿ>(*ÿ;&'ÿ:&&ÿ?*+ÿW?JÿbˆÿU>Iÿ@**ÿC--ÿG01I23W@DP9={L58ÿN5:ÿS9>ÿU:Aÿ`EGÿª’dÿÖÁqÿ±pÿ¥“lÿhXÿhOJÿ`DIÿmL[ÿ„\{ÿ¡rœÿ­ƒ½ÿb…ÿD.2ÿ?**ÿA,,ÿE//{F02V?CR;>[N7;þO6;ÿU:@ÿZ>Eÿ[>Fÿ^BHÿ€iWÿ² sÿäÈ›ÿî¢ÿÞ­ ÿÒ–¤ÿàœÓÿÓ“Øÿ£w¤ÿ]AVÿ;%'ÿ9$%ÿ;&'ÿ?)*þC-.[C./Q:>Q;? R;?ÙP7<ÿU;Aÿ[>Fÿ]@HÿZ=EÿT9@ÿW>BÿkQPÿ€a_ÿ‰fiÿ†`gÿxTfÿY&*iQWU>BcT<@õS9?ÿW)*ÿ:&'ÿ9$&ÿ9$&ÿ8$%ÿ7#%ÿ7"$ÿ9$&õ;%'cC+.1I25O7;H15W?DcW?CÙV=BþVÿO6;ÿK47ÿH14ÿD.0ÿ@+-ÿ=(*ÿ;&(ÿ:%'ÿ9$&ÿ9$&þ:%'Ù;%(c5!#9#%8"%O7;P8<kRWX?D YAF[Y@E{X?DV=BS;?P8<L58H25E/1B,/@*->)+=(*{<')[;%( C+/8#%8#%L49?',W>C]EJ`GL_FK]DIZAEV>BR:>N7:J46G13D.1C,/A+->)+:%(16!#À€€À( @ <$(=&(<&(>&)?'*@(+A),B*-C+.E,/F-1G.3I05N47R8:T:=UBX@DZAG[BI]DL\CK[AJ:$&5 ">')J14?'* A),C*-C+.E,/F-0G.1H/3J15K27P7:T;<VAZ@C[BF\DI\CJ s\_bIR[BO_GQ8"%8#%G.2>')+@)+…A),ÄB*-ÜC+-àD,.àE-/àF-1àH/2àI04àJ15àL37àQ8:àU;=àW=?àY?BàZADà\CGà^EJÜ`HNÄbJQ†bIR,t^b`GRaHT6"$7"$1<&(b=&)à=&(ÿ=&(ÿ=&)ÿ>')ÿ?(*ÿ@(+ÿA),ÿB*.ÿD,0ÿE-1ÿG.3ÿM36ÿP79ÿR8<ÿT:?ÿV'*ÿ?(+ÿ@),ÿA)-ÿB*.ÿC+0ÿD,1ÿJ14ÿN58ÿP7;ÿS:>ÿUDÿX@GÿZCKÿ\EOÿ_HSÿdLVóeMVbt^b[BOZDL:&&9%':%',:%'à7"$ÿ8#%ÿ9#%ÿ:$&ÿ;%'ÿ<%(ÿ<%'ÿ:#&ÿ:#%ÿ:%'ÿ<)*ÿ@./ÿB12ÿF33ÿH34ÿG24ÿI27ÿN6<ÿT8<ÿYuvÿr¯«ÿ}ÌÃÿ€Ò§ÿ€Ò ÿˆÖŸÿ”Þ”ÿ¥Ü“ÿµÎ~ÿÆÅjÿÏÂfÿÞÇ\ÿÛÁ_ÿ²šdÿjVLÿP:@ÿW@GÿYBJÿZCKÿ[DKÿ_HMÄ[CI ZBI;''=)*?++Ü;('ÿ<((ÿ;''ÿ=04ÿNizÿUŸ¸ÿnÀÏÿ}ÕÛÿyØÆÿƒ×¤ÿrÃŒÿs±zÿ‡¯oÿ‰¢jÿ–™Wÿ«œGÿ¼¦NÿÛÂRÿèÑ]ÿéÔoÿÔ¾dÿ~jOÿQ:AÿW?FÿX@GÿX@Gÿ]EJÜ\CHYAF;((>*+?+,à;((ÿ<((ÿ>))ÿZt�ÿf»çÿV±ËÿrÅÓÿ…ÐÏÿ‚Ĭÿq–}ÿR\KÿJ>7ÿF31ÿD.0ÿD-1ÿJ34ÿW?8ÿw_Bÿ°›WÿÔÁfÿÖÃ^ÿºªcÿcNIÿS;AÿV>CÿW>Dÿ[CFàZBEX?D;((>*+@,-à<)(ÿ<))ÿ=)(ÿG>Eÿc“®ÿoÃÔÿ{ÓÓÿsŸ“ÿQMHÿ@)+ÿ=%(ÿ>'*ÿ?(,ÿ@*.ÿA+/ÿB,1ÿF/3ÿI15ÿQ9:ÿŽzWÿ½­mÿ¯�_ÿŠs[ÿQ9>ÿT;@ÿU*+à<((ÿ=*)ÿ>*)ÿ>((ÿI<>ÿrš™ÿh‡€ÿE43ÿ<%'ÿ=&)ÿ>')ÿ>(*ÿ?(+ÿ@*-ÿA+.ÿB+0ÿC,1ÿG13ÿI14ÿ\E@ÿ°›sÿ®•gÿ ‚kÿT<@ÿR9=ÿS:>ÿX>BàW=AT;?8$%;'(=(*à9$&ÿ<((ÿ>**ÿ?++ÿ?**ÿE43ÿD0/ÿA,,ÿA,,ÿ@*+ÿ>(*ÿ>(*ÿ?(+ÿ@),ÿA*-ÿA+.ÿB+0ÿA+0ÿ>)-ÿiPGÿÒ­”ÿË¥�ÿ°�‚ÿUàU;>S9<8$&<')>)+à8$&ÿ:%'ÿ=()ÿ@,,ÿA--ÿB-,ÿB--ÿC-.ÿC..ÿC..ÿB,-ÿ@)+ÿ='*ÿ<%)ÿ:$)ÿ:$)ÿ;&)ÿF1/ÿs\Jÿ˧yÿuÿí¹«ÿ³‰ƒÿN58ÿN58ÿO68ÿT:<àS9;Q799%&=(*?*,à9%'ÿ;&'ÿ<')ÿ>)*ÿA,,ÿC..ÿD//ÿC..ÿ@+,ÿ=)*ÿ>**ÿC/,ÿK6/ÿV?3ÿbM<ÿs`Aÿ�|SÿÇ­{ÿëÉ–ÿóÆ›ÿ毘ÿÑ™˜ÿvUTÿF/2ÿJ14ÿK25ÿO69àN58L36:&'>)+@+-à;&(ÿ<')ÿ=(*ÿ?)+ÿ@*,ÿB,-ÿA,-ÿB..ÿTE;ÿqcEÿŽ{Cÿ·œTÿέfÿ×µpÿÕ¾|ÿͼlÿÒÅ{ÿëÌ�ÿè´£ÿݨ³ÿÆ“§ÿ…^bÿE-1ÿC,1ÿD-2ÿE-2ÿJ16àJ16G/4;')?+-B-/à<(*ÿ>)+ÿ@*,ÿA+-ÿB,.ÿ?),ÿTG>ÿ�Ž_ÿ¬ª]ÿ¹«Zÿ˯XÿÞ¸_ÿß¾qÿ׺xÿÕ¹‚ÿÓ²‚ÿ᳚ÿ몳ÿÚ•´ÿ¯}•ÿnOSÿC,.ÿA*.ÿB+.ÿC,/ÿD,0ÿI04àH/3F-1=)*A-.D/1à?*+ÿA+-ÿB-/ÿD-0ÿC,/ÿUG?ÿ•¢jÿ©²_ÿ­ =ÿ¶–BÿѦVÿܸaÿÜÁkÿ×¹rÿÓ¬|ÿÈ�„ÿµ‰�ÿ“nlÿiMLÿI11ÿ>(+ÿ?(,ÿ@)-ÿA)-ÿA*-ÿB+.ÿG.2àG.2D,0?*,C.0G13àA,.ÿC-/ÿE.1ÿG02ÿH14ÿ’�sÿ°¶sÿ­¢XÿÖTÿÇ’`ÿ«…\ÿ�sTÿx_KÿeM@ÿWA9ÿL84ÿE0/ÿA,,ÿA,,ÿC-.ÿC-.ÿA+-ÿ@),ÿ@(+ÿ@),ÿA*,ÿE-0àE-0C+.A,.F02I35àC-0ÿF/2ÿH14ÿI15ÿS>>ÿ´¶„ÿÐÁ|ÿÈ�`ÿ¡o\ÿ_DAÿI25ÿD-1ÿC-/ÿD./ÿD//ÿD//ÿD..ÿC-.ÿC--ÿC--ÿC-.ÿC-.ÿC-.ÿB+-ÿA),ÿ@),ÿD,/àC+.A),C.0H25K57àE/2ÿH14ÿJ36ÿL37ÿV?Aÿ¹³zÿßÊ|ÿÍ«nÿ]ECÿH04ÿJ25ÿH03ÿF.1ÿD-/ÿC,.ÿC-.ÿC..ÿC-.ÿB--ÿB,-ÿB,-ÿ?**ÿ?**ÿB,-ÿC,-ÿB,-ÿF.0àD,/B+-D/1I36M69àG14ÿJ36ÿM49ÿO6;ÿQ8=ÿŸŒ_ÿåÍpÿßÃjÿ‡qQÿF/4ÿH04ÿI14ÿG02ÿE.0ÿB,.ÿ@*,ÿ@*,ÿA+,ÿ@++ÿ=((ÿ;'&ÿO8BÿV?LÿA,,ÿB,,ÿB,-ÿG01àG/0D..F03K58O8;àI25ÿL48ÿO7;ÿR8=ÿS8?ÿjPKÿɰeÿèÎgÿÕ¾jÿ‹xYÿWB>ÿD.1ÿ@*-ÿ?),ÿ>(*ÿ;&'ÿ8$%ÿ7#$ÿ>)+ÿW=Fÿ†h‡ÿ°ŠÎÿz^�ÿ@++ÿA++ÿA+,ÿE/0àF./D--F03K58P9=ÜJ37ÿN5:ÿQ8=ÿU:@ÿW)*ÿ@*+ÿ@++ÿD./ÜE-.B,,F03G14 R;?ÄL59ÿO6;ÿS9>ÿWEÿ[?FÿYRÿ:%&ÿ9#%ÿ:%'ÿ<'(ÿ?)*ÿC-.ÄB,- A++E04|bfS=@†P8<ÿO6;ÿS9?ÿWBàO7<ÿR9>ÿWFÿ]?Hÿ[>FÿX=CÿU:@ÿQ7<ÿL38ÿJ37ÿM69ÿP8;ÿO7:ÿJ35ÿA+-ÿ:&&ÿ8$%ÿ9$&ÿ9$&ÿ8$&ÿ8#%ÿ8"$ÿ8"$ÿ;%'à:$',;%'@++D-2=&)|cjU>BbV>CóR9>ÿT:@ÿWÿP7;ÿM59ÿJ26ÿG03ÿD-/ÿA+-ÿ>)*ÿ<')ÿ;&(ÿ:%'ÿ9$&ÿ8$%ÿ8#%ÿ7"$ÿ7"$ÿ;$'ó;$'bH/439"&I25I265"W?CbY@EàV=BÿT:@ÿT:@ÿT:@ÿS9>ÿP7<ÿN6:ÿK37ÿI24ÿF/2ÿC-/ÿ@+-ÿ>)*ÿ<')ÿ:&'ÿ9$&ÿ8$%ÿ8$%ÿ8#%ÿ9$&ÿ;%(à;%'b-6!#7"$K48J27~diU=A,ZAF†ZBFÄY@EÜY@EàW?CàV=BàS;?àQ9<àN7:àK57àI25àF02àC.0àA,.à@*,à>)+à>(*à=(*Ü<'*Ä<&)†:%',K266!#7"$K48>'+U=B~eiO7= UP8<N7:K47I25F02C.0A,.?*,>(+<')<'):&(7#% N59:%'06!#J35M6:M5:N6;P7<P7<O7;M59L48I35G03D/1B-.?*,=(*;'(:%'9$&8$%7#%6"$5"$5"$5!$ðàÀ€€Ààð(0` $>%%=&)=&)>')>'*?(*@(+@(+A),B),B*-C+.D+/E,0F-1G.2H/4I05O57Q79R8;S9=T:>U<@W=AW>CX@EZAGZBI\CJ\CJZ>J;$&;%';%'=&)P6::#% >&)?'*@(+@(+A),B),B*-C+.D+/E,0F-1G.2H/4I05N57Q79R8:S9=T:>U<@W=AW>CX@EY?GU&)BA),ŒB*-¿C+.ØD,/àE,/àF-0àF.0àG.1àH/2àI03àJ04àK15àK36àM37àN49àO6:àU;<àW=>àX>?àY?AàZACà[BEà]CFà]EHà^FJà`GLØaINÀaIOŒ_FOBX>K aHR]DP`GR8"$7!#D-0;%'7?'*­@),ó@(+ÿ?(*ÿ?'*ÿ?(*ÿ@(+ÿ@)+ÿA),ÿB*,ÿB*-ÿC+.ÿD,/ÿE-0ÿF.1ÿG.2ÿH/4ÿJ16ÿO68ÿQ7:ÿR9;ÿT:=ÿU;?ÿV=AÿW>BÿX?DÿYAFÿ[BIÿ]FLÿ`IOÿdKSódLS­aHR7qZ_^FRaHS7!#6!#;$']>'*ä=&)ÿ;%'ÿ;%'ÿ<%(ÿ=&(ÿ=&)ÿ>')ÿ?'*ÿ?(+ÿ@(+ÿA),ÿB*-ÿB*.ÿC+/ÿD,0ÿE-1ÿF.3ÿH04ÿN57ÿP69ÿQ7:ÿR8<ÿS:>ÿT;@ÿVCÿX?FÿYAHÿZCJÿ\DMÿ^FPÿcKTÿfNVäcKU^F-E_FQ`GQ5"$6 C.2:#&]=&)ð;$'ÿ:#&ÿ:$&ÿ;$'ÿ<%'ÿ<%(ÿ=&)ÿ>&)ÿ?'*ÿ?'*ÿ@(*ÿ@(,ÿA),ÿA*-ÿC+/ÿD,0ÿE,1ÿE-2ÿH04ÿM46ÿO68ÿP7:ÿQ8<ÿR9>ÿT;?ÿUCÿW?FÿXAHÿZCJÿ[DMÿ]EPÿ_FRÿbKUÿgOXðcKU^pZ`^DP^DO9%%8#%7#%7<&)ä9$&ÿ8#%ÿ9$&ÿ9$&ÿ:$'ÿ:%'ÿ;%(ÿ<&(ÿ<&)ÿ=')ÿ>(*ÿ?(+ÿ?(+ÿ?)+ÿ?(+ÿ?),ÿ@)-ÿ@)-ÿA*.ÿC,0ÿH02ÿJ24ÿL47ÿN69ÿP8<ÿS:?ÿU+-ÿ?,.ÿB//ÿC.0ÿB-0ÿC-1ÿE.3ÿJ37ÿO8<ÿTK ]DNWAI:''<''<((B?)*ó7"$ÿ7!#ÿ7!#ÿ8"$ÿ9"%ÿ9#%ÿ:$&ÿ:$&ÿ:#&ÿ8"$ÿ6!ÿ6 "ÿ=++ÿF>=ÿOURÿYmfÿalÿoš|ÿu¥~ÿ�¨�ÿ‡Ÿyÿ�™oÿŠ�hÿ‡…`ÿwlGÿhWAÿWD>ÿG36ÿH17ÿP9>ÿV>EÿX@HÿYBJÿZCMÿ[DNÿ\EOÿ]EOÿ^EPÿcKRó_FOB^FO[BI:''U;??*+Œ?*+ÿ:&&ÿ8#%ÿ7"$ÿ8"$ÿ8#%ÿ9#%ÿ8#%ÿ6 "ÿ4 ÿ;,,ÿMRNÿg„}ÿ{­ ÿ~À§ÿ�Ë®ÿ„ѱÿ�Ù²ÿ�à©ÿ‘Þ¡ÿ›Üœÿ¥Ï–ÿªÂ‚ÿ¶¿wÿ½½qÿº²VÿÉ·Vÿ̲Vÿ©“Xÿs^NÿL7:ÿK5;ÿU=DÿXAHÿYBJÿZCLÿ[CMÿ[DMÿ[DMÿ`IOÿ`INŒwba[BJ:&&4"! A,,¿=))ÿ;''ÿ<''ÿ:%&ÿ8#%ÿ7"$ÿ5 "ÿ3ÿ;03ÿQciÿq¨§ÿ}ÌÆÿ~×Ùÿ}×Îÿ~Ò£ÿ|Ñ–ÿ~Ï—ÿ}Ë–ÿ�Ø�ÿ”׈ÿ¡×‰ÿ®Ö�ÿºÉoÿÆÅgÿÌÂeÿÕÆoÿáÊ`ÿäÊ\ÿæÍcÿßÃrÿ©‘fÿaNKÿJ5;ÿT=DÿX@HÿXAIÿYBJÿZCJÿZBJÿ]EKÿ`HMÀTDÿW?GÿX@HÿX@HÿXAHÿZBIÿ_GLØX?FY@G:'':''A-.à;((ÿ;('ÿ;((ÿ<((ÿ<('ÿHAIÿcޝÿ_´ÙÿU±ÒÿS¬ÄÿwÃÑÿ…ÑÜÿÓÊÿ�Ùºÿ‹Û±ÿyÑÿe sÿa~[ÿdkOÿ^YCÿXL?ÿUF<ÿYF;ÿcN:ÿu^@ÿ‡nAÿ´�PÿÙÂQÿèÓdÿèÔlÿæÒdÿæÐXÿμfÿgUMÿO8=ÿV>DÿW?EÿW?EÿW?EÿY@Fÿ^FIàW?DX?D9''9'&A-.à<))ÿ;((ÿ<((ÿ<))ÿ>)(ÿ[j€ÿj¼öÿe»âÿT¯Éÿa¶Èÿ}ÐÛÿ…ÍÐÿ„̹ÿƒ½¤ÿr�zÿSSHÿE42ÿ@(+ÿ>&+ÿ?',ÿ?(-ÿ@).ÿA*/ÿA+1ÿF/3ÿJ25ÿR99ÿqZFÿ«—\ÿ˹aÿϾgÿ˸XÿôdÿžŽcÿR<@ÿS;@ÿV=CÿV=CÿV>CÿX?Dÿ]DGàW>BW>C:'':''B..à<))ÿ<((ÿ<))ÿ=))ÿ=))ÿA/1ÿ\u�ÿmºßÿ_¶ÊÿvËÖÿyÖØÿ†Î½ÿpŽÿPGCÿ?(*ÿ=%(ÿ>'*ÿ?(+ÿ?(,ÿ@)-ÿA*.ÿA+.ÿB+0ÿB,1ÿD-2ÿI24ÿK35ÿJ26ÿQ:;ÿŠwTÿ²oÿ¾°jÿªšZÿµŸgÿpZRÿO7=ÿT;@ÿU*)ÿ>))ÿA-.ÿas�ÿ‚ÇÒÿ€ØÛÿ{Áµÿ]h^ÿ@*+ÿ;$&ÿ=&)ÿ>&)ÿ>'*ÿ>(*ÿ?(+ÿ@),ÿ@*-ÿA*.ÿA+/ÿB+0ÿB,1ÿE.2ÿI24ÿK35ÿK36ÿU==ÿ¦�iÿ¹©tÿ¨•\ÿ²—hÿ�tcÿN6<ÿS:?ÿS;?ÿT;?ÿU<@ÿ[ADàT;?T;?6"$6"$?*-à;'(ÿ<)(ÿ=*)ÿ=*)ÿ>**ÿ>**ÿ>**ÿC..ÿhxuÿz¬¡ÿVSNÿ@)*ÿ?)*ÿ=')ÿ=&)ÿ=')ÿ>')ÿ>(*ÿ?(+ÿ?(+ÿ@),ÿA*-ÿA+.ÿB+/ÿB+0ÿC,1ÿE/2ÿI24ÿK35ÿG/2ÿ…oYÿº¦}ÿ­•iÿ¬�iÿ£„tÿQ9=ÿQ8=ÿR9=ÿR9>ÿT:?ÿY@CàS9>S:>6#$6#$@*,à9$&ÿ9%&ÿ<((ÿ>**ÿ>**ÿ?++ÿ?++ÿ@++ÿB//ÿI98ÿA++ÿA,,ÿB--ÿA,,ÿ?)+ÿ>(*ÿ>')ÿ>'*ÿ>(+ÿ?(+ÿ?(+ÿ@),ÿA*-ÿA+.ÿB+/ÿB,0ÿC,2ÿD.2ÿE/1ÿA,.ÿŸ�oÿײšÿÁŸ…ÿ·”{ÿ¯ŽƒÿQ:<ÿP7:ÿP7;ÿQ8;ÿS9<ÿX>@àR8<R8<7#$7#$@+-à9%&ÿ8#%ÿ9%'ÿ=()ÿ?++ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿB--ÿB--ÿB--ÿC--ÿC--ÿB,-ÿ@)+ÿ?(*ÿ?(+ÿ?)+ÿ@(+ÿ?),ÿ@)-ÿ@*-ÿA*.ÿ@*.ÿ>)-ÿ:%+ÿ:&)ÿrZFÿÚµ�ÿë¼¥ÿç¹­ÿ蹯ÿ«…‚ÿM68ÿO69ÿO69ÿO79ÿQ8:ÿW=?àQ7:Q7:7#%6#$A+.à9%'ÿ8$&ÿ9%'ÿ:%'ÿ=()ÿ@++ÿA--ÿB--ÿB--ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿC..ÿA,,ÿ?)+ÿ>'*ÿ='*ÿ<&)ÿ;%(ÿ9$(ÿ8#'ÿ7#&ÿ<()ÿWC9ÿ˜~`ÿß»…ÿïÀ‡ÿð»‘ÿè³£ÿñ¹¯ÿ–qkÿJ25ÿM47ÿN57ÿN58ÿP79ÿU;=àP68P687#%7#$A,/à:&(ÿ9%&ÿ:&'ÿ;&(ÿ<&)ÿ=()ÿ@++ÿB..ÿC..ÿC..ÿD/.ÿD//ÿD//ÿC..ÿB--ÿ@++ÿ>)*ÿ;'(ÿ9%'ÿ7#&ÿ7#%ÿ:&'ÿ@-*ÿL90ÿ_L9ÿiKÿ´šjÿÞŠÿñ͘ÿòÉžÿñ¼�ÿê³™ÿÙž›ÿ˘“ÿaGEÿH13ÿJ25ÿK35ÿL36ÿN47ÿR9;àL36L368$%8$%B-/à;'(ÿ:%'ÿ;&(ÿ<'(ÿ=()ÿ=(*ÿ>)*ÿ@+,ÿB..ÿD//ÿD//ÿC..ÿ?++ÿ;'(ÿ:'(ÿ?-+ÿL90ÿaN9ÿw`Bÿ‹nHÿž€Rÿ¯’aÿ¶¡iÿ¿«bÿÅ´gÿλtÿîÔ›ÿóОÿòÉ¢ÿòæÿ䳜ÿÍ™£ÿË“œÿZYÿC,1ÿD.2ÿE.3ÿF.3ÿF/3ÿH04ÿM49àG/4G/48$&8$&C.0à<')ÿ;'(ÿ<')ÿ=(*ÿ>)*ÿ?*+ÿ@*,ÿ@*,ÿA+,ÿB-.ÿA,,ÿ<()ÿE42ÿ`SDÿƒwTÿ™‹Iÿ³ŸMÿÕ·XÿåÇmÿéÃsÿêÃuÿâÅÿÜÈ…ÿÒÀoÿÊ»lÿÖË„ÿêÔžÿç·™ÿߨŸÿÕ›°ÿË–ÃÿÃ�¦ÿ…_^ÿF-1ÿC*/ÿC,0ÿD-1ÿD,1ÿE-2ÿF.3ÿL37àF.3F.39%'9%'E/2à=(*ÿ<()ÿ=)*ÿ?)+ÿ@*,ÿ@+,ÿA+-ÿB,.ÿB+.ÿ<')ÿD21ÿuoWÿ¡¤kÿµµmÿ»±eÿ¼«^ÿ̯Xÿà·]ÿã¿iÿäÂyÿÚ»wÿк|ÿл‚ÿdzvÿÄ­vÿÙ·•ÿã«§ÿ䘹ÿá”ÇÿÕ—Âÿ³†•ÿlNLÿB+.ÿA*.ÿB*.ÿB+.ÿB,/ÿC,0ÿC,0ÿE-1ÿK26àE-1E-1:&(:&'F13à>*+ÿ>)+ÿ?*+ÿ@+-ÿA,.ÿC,/ÿC-/ÿD./ÿ?),ÿN>9ÿ’™nÿ°Áuÿ¯²Qÿ®¤?ÿ´¡@ÿ¼£SÿÒ­TÿÓ­YÿѰ_ÿÓ¸mÿÒ¸rÿÙ·|ÿᵊÿé±—ÿñ­§ÿ÷«·ÿò§¸ÿÚžªÿ­�ÿsTRÿI12ÿ>(,ÿ@)-ÿA*-ÿA*.ÿA*.ÿA+.ÿB+/ÿB+/ÿD,0ÿJ15àD,0D,0;();()G24à@+,ÿ?*,ÿA+.ÿB-.ÿC-/ÿD.0ÿE.1ÿD-/ÿI54ÿ‹‘hÿ ´lÿ ©\ÿ­§Oÿ«š4ÿ®’>ÿ½‘GÿתZÿá¹aÿæÇiÿæÍnÿâÅsÿܸvÿÒ¯|ÿ ÿ®�vÿ“xhÿr[PÿV@<ÿE//ÿ@+,ÿA*,ÿ@),ÿ?(,ÿ@(,ÿ@),ÿA),ÿA)-ÿA*-ÿB*.ÿC+/ÿI03àC+/C+/=(*=(*I36àA,.ÿA,-ÿC-/ÿD-0ÿE.1ÿF/2ÿG03ÿC,0ÿwn`ÿ³Â†ÿ¡«cÿ§§Xÿ­¡Pÿ½‘IÿÚ›`ÿÜ¥hÿË¢jÿµ•cÿ›�_ÿ‚iRÿnVGÿ^H=ÿS?8ÿJ63ÿD//ÿA,,ÿA+,ÿB,-ÿC-.ÿC..ÿD./ÿC-.ÿA+-ÿ@),ÿ@(+ÿ@(+ÿ@(+ÿ@),ÿ@),ÿB*.ÿH/2àB*-B*->)+>)+K57àC-0ÿB-/ÿD.0ÿF/1ÿG03ÿH14ÿI24ÿJ36ÿ¡¢‚ÿÌΓÿ¾±qÿµŸ\ÿÉ‘]ÿבlÿ¤zaÿqVKÿU==ÿI24ÿE/1ÿE/1ÿE/0ÿD//ÿC//ÿD//ÿD./ÿD..ÿC..ÿC--ÿC--ÿC-.ÿC-.ÿC./ÿC./ÿB-.ÿA+-ÿ@),ÿ@(+ÿ?(+ÿ@),ÿA*-ÿF.1àA*-A*-?+-?+,L79àD/1ÿD.0ÿF/2ÿG13ÿI14ÿJ25ÿJ25ÿS=?ÿ²¶…ÿÑЋÿÕ¼wÿ̦]ÿLJfÿsSPÿJ36ÿG/3ÿG/2ÿG/2ÿE.0ÿE.0ÿE/0ÿF00ÿE00ÿD//ÿD//ÿD..ÿC..ÿC-.ÿB--ÿB--ÿC--ÿC--ÿC-.ÿC-.ÿC-.ÿC-.ÿB+-ÿA),ÿ@),ÿA),ÿE-0à@(+@(+A,.@+.N8:àE02ÿE/2ÿG04ÿI25ÿJ36ÿL37ÿL38ÿU>Aÿµ³€ÿÕÑ‚ÿÞÁxÿݸlÿ•x`ÿG/4ÿL36ÿK25ÿI24ÿH03ÿG/2ÿE.0ÿD-/ÿC,.ÿC-.ÿD./ÿD//ÿD..ÿC-.ÿC--ÿB--ÿB,-ÿB,-ÿB--ÿB--ÿA,,ÿA,-ÿC,-ÿC--ÿC,-ÿB,-ÿC,.ÿF.0à@)+@)+B-/A,.O9<àG13ÿG03ÿI24ÿK36ÿL48ÿN59ÿO6:ÿP8=ÿ¦™pÿÝÑxÿãÊ~ÿÞÀsÿ¦�lÿF04ÿJ26ÿL37ÿK25ÿI14ÿH03ÿF/1ÿE.0ÿC,.ÿB+-ÿ@+,ÿA+-ÿC--ÿC..ÿB--ÿB,,ÿA,,ÿA,,ÿ@++ÿ<((ÿ9&%ÿ<((ÿA,,ÿB,-ÿC,-ÿC--ÿD./ÿI13àC-.D-.B-/B-/P:=àH15ÿH14ÿJ36ÿL48ÿN5:ÿP7;ÿQ8<ÿP6<ÿ|fUÿÙÄbÿæÍpÿäÈbÿÙ¾eÿwbOÿC,1ÿG03ÿJ25ÿJ25ÿI14ÿG02ÿE.1ÿD-/ÿB+-ÿA*,ÿ?)+ÿ?)+ÿ@*+ÿA+,ÿ@+,ÿ>**ÿ;'&ÿ7$#ÿD04ÿlRjÿW@Kÿ@++ÿB,,ÿB+,ÿB,,ÿC..ÿI12àC--C--D.1C.0R;>àI36ÿI25ÿK38ÿN59ÿP7;ÿQ7<ÿS8>ÿS9>ÿY?Dÿ­•fÿäÉcÿæËjÿåÉ]ÿÒ¼qÿ�nYÿK67ÿ@*.ÿC,/ÿE.1ÿF.1ÿD.0ÿC-/ÿA+-ÿ@*+ÿ>)*ÿ=')ÿ:%'ÿ7"$ÿ5""ÿ7$$ÿI58ÿv[rÿªƒÃÿ½–ëÿx^{ÿ@+*ÿA++ÿA++ÿA+,ÿB-.ÿH01àC,-C,-D.1D.1SÿT:@ÿV;AÿU:AÿfLMÿ»£jÿçÐrÿäÌmÿÖÁnÿʸnÿ±¡sÿ„tZÿXF@ÿD01ÿ<(+ÿ;&(ÿ:%'ÿ9$&ÿ7#$ÿ5"#ÿ6#$ÿ<(*ÿK4:ÿgHVÿ‘fƒÿ¶‰¹ÿÉ äÿÄ�æÿ„i�ÿD/1ÿ?**ÿ@++ÿ@++ÿA++ÿB,-ÿG01àC,,C,,E/1C,/S<@ØK58ÿK37ÿM5:ÿP7<ÿR8>ÿT:@ÿV**ÿ?**ÿ@*+ÿ@**ÿA,,ÿF/0ØA*+B+,F/29$& S=@ÀN7;ÿK38ÿN6:ÿQ8<ÿS9?ÿV;AÿX=CÿZ>Eÿ[>Fÿ[>FÿX))ÿ?)*ÿA,,ÿD/0¿>(( A++E03†osQ;?ŒSFÿY=CÿV:Aÿ`GJÿ‚m_ÿ¶¥ƒÿáË£ÿñǦÿõÁ ÿò»¨ÿéµ°ÿߥŸÿÚ™�ÿÚ•«ÿê¦Ûÿé›çÿÞ˜äÿÌ“Óÿ£} ÿeJYÿ?)-ÿ9#$ÿ9$&ÿ9$&ÿ9#%ÿ8#%ÿ9#%ÿ:$&ÿ;%&ÿ@*,ÿB-.ŒM59@*+E03K59L69BW@CóM59ÿN6;ÿQ8=ÿT:@ÿW(*ÿ8#$ÿ9$&ÿ:$&ÿ9$&ÿ8#%ÿ8#%ÿ8#%ÿ8"%ÿ8#%ÿ9#%ÿ='*ó;&(B;%(A*+C16G04;%) U>B­T=AÿM5:ÿQ8<ÿT9?ÿVFÿY=DÿWÿU:AÿWEÿZ>FÿZ>FÿY=DÿW)*ÿ=')ÿ<&(ÿ;&'ÿ:%'ÿ9$&ÿ9$%ÿ9$%ÿ8$%ÿ7#%ÿ7"$ÿ7"$ÿ7"$ÿ9#&ÿ=%(ä8#%79#%9$&F03B,/tY_Q9=^[CGðT<@ÿP8<ÿS9?ÿU;AÿW^[CHäX@EÿR:>ÿS8>ÿT9@ÿU:AÿU;AÿT:@ÿS9?ÿR8=ÿP7<ÿO6:ÿM49ÿK37ÿI25ÿG13ÿF/1ÿC-0ÿB,.ÿ@*,ÿ>)+ÿ<')ÿ;'(ÿ:&'ÿ9%'ÿ9$&ÿ8#%ÿ8$%ÿ8#%ÿ7"$ÿ6"$ÿ7#$ÿ;%(ÿ=&)ä9#&] 5 "7!#J37F/3t[`O7;7YAF­]DIóZAFÿW>BÿU;AÿT;@ÿT:?ÿS:>ÿR9=ÿQ8=ÿO7;ÿM59ÿL47ÿJ36ÿH14ÿF02ÿD.1ÿB-/ÿA+-ÿ?*,ÿ=(*ÿ<')ÿ;'(ÿ:&'ÿ:%'ÿ9$&ÿ9$%ÿ9%&ÿ:%'ÿ;&)ÿ='*ó<&)­7"$7F/34 "6!#K38D-1P8=@(- R:?BY@EŒ[CHÀ\DHØ\CHà\CHà[BGàZAEàX?DàW>CàU=AàSàP8<àN7:àL68àJ36àH25àF13àE/1àD.0àC-/àA,.àA+-à@*-à?*,à?),Ø=(+À;&)Œ8#%B0 8#%4!7!#J37M59L38Q9>‹rwB*/ L38N5:N5:M5:L48K37J26H24G13E/1D-0B-/@+-?*+=(*;'):&'9%'9$&8#%7#$7#$6"$5!#/ X&'>&)=&)>')>'*?'*?(*@(+@(+A),A),B*,B*-C*.D+/D+/E,0F-1F.1G.2H/4H/5K26O67Q69Q8:R9;S9=T:>U;?V<@W=AW>CW?DY@FZAHZBH\CJ[BI[CK<%'8%<%(<&(D,.8"#;$'=%(=&(>&)>')>'*?'*@(*@(+A(,A)-B)-B*.C+/C,0E,0E-2F-3H/4M35N47O68P79Q7;R8<S9>T:>T;@U;BU=BV>DVàX>?àY?@àZ@BàZACà\BDà\CEà]DGà^EHà^FIà_GKÞ`GLÓ_GLº_GL‹\DLLZ@K`HQ^FP^FP^FQ9#%9#$9#&8"$<%(i@(+ÉB*-øC+-ÿB*-ÿA),ÿA),ÿB*,ÿB*-ÿC+-ÿC+.ÿD,.ÿD,.ÿE,/ÿE-0ÿF.0ÿG.1ÿG/2ÿH/3ÿI04ÿJ15ÿJ16ÿK27ÿN58ÿR8:ÿT:<ÿT;=ÿU<>ÿV')ÿ>'*ÿ?'*ÿ?(*ÿ@(+ÿ@(+ÿA),ÿA*-ÿB*-ÿC*.ÿC+/ÿD,0ÿE-0ÿF-1ÿF.3ÿG/4ÿK25ÿO57ÿP69ÿQ7:ÿQ8;ÿR8<ÿS:>ÿT;?ÿU<@ÿV=AÿW>CÿW?DÿX@GÿYAHÿZBJÿ[DLÿ^FOÿcKSÿfOUýdKT¼_FQ:eLV`GSaHS8"$7!$XDF9#%W>')ã?(+ÿ;%'ÿ:$&ÿ;$'ÿ;%'ÿ<%(ÿ=&(ÿ=&(ÿ>&)ÿ>')ÿ?'*ÿ?'*ÿ@(+ÿ@(+ÿ@),ÿA*-ÿB*-ÿB*.ÿC+/ÿD,0ÿD,0ÿE-1ÿF-3ÿG/4ÿK25ÿN57ÿO68ÿP7:ÿQ8;ÿR8<ÿS9>ÿT;?ÿU;@ÿVCÿW?EÿX@GÿYAIÿZCJÿ[DLÿ\DNÿ]EOÿ`HRÿgOWÿfNWãaHSW�ƒm`GR`GR6"$8!#:$'8"$W=&)ì=&)ÿ9#%ÿ:#&ÿ;$&ÿ;$'ÿ<%'ÿ<%'ÿ=%(ÿ=&(ÿ>&)ÿ>&)ÿ?')ÿ?'*ÿ@(*ÿ@(*ÿ@(,ÿ@),ÿA*-ÿA*-ÿC+.ÿC+0ÿD,0ÿE-1ÿE-2ÿF.3ÿJ25ÿN56ÿO58ÿP79ÿP8:ÿR8<ÿR9>ÿS:?ÿT;@ÿUCÿW?DÿX@GÿYAHÿZCJÿ[DLÿ\DNÿ]EPÿ^FQÿ`HSÿfOXÿgOXíaHSWeLV_GR^FP5"$7!#7!#:<&(ã<&(ÿ8#%ÿ9#&ÿ9$&ÿ:$&ÿ:%'ÿ:%'ÿ;%(ÿ;&(ÿ<&)ÿ<&)ÿ=')ÿ>'*ÿ>(*ÿ?(+ÿ?(+ÿ@(+ÿ@),ÿA),ÿA)-ÿA*.ÿB+/ÿB,0ÿC,0ÿD,1ÿE-2ÿH04ÿL45ÿM47ÿN68ÿP7:ÿQ8<ÿR9>ÿS:?ÿT;@ÿU'*ÿ>(*ÿ>(*ÿ>'+ÿ>(+ÿ=(*ÿ=')ÿ='*ÿ='*ÿ='*ÿ='+ÿ>'+ÿ>(,ÿA*.ÿE-/ÿF/1ÿH03ÿI25ÿL47ÿN6:ÿP8=ÿS:?ÿT;AÿV=CÿV>DÿW?FÿX@HÿYBIÿZCLÿ[DNÿ\EOÿ^FQÿ_GRÿ_GSÿ`HSÿgOWÿcKT¼[BN^EP]DN8)'6"%7#%i='*ý7#%ÿ6!#ÿ7!$ÿ7"$ÿ8"$ÿ9#%ÿ9#%ÿ:#%ÿ:$&ÿ;$&ÿ;$'ÿ<%'ÿ<%'ÿ<%(ÿ<%'ÿ:$'ÿ9#%ÿ9"%ÿ7"%ÿ7!#ÿ6 #ÿ6!$ÿ7"%ÿ8$&ÿ:&(ÿ;(*ÿ;)+ÿ=*,ÿ?,-ÿ?+-ÿ?*-ÿ?*-ÿA+/ÿC-1ÿG04ÿK48ÿO8<ÿS;@ÿV>CÿW?EÿW@GÿXAIÿZCKÿZCMÿ\DNÿ\EPÿ]FQÿ^GRÿ^FQÿ`HRÿfNUý_FPi`HQ`ES:*(:&&8$$>)*É=')ÿ6!#ÿ7!#ÿ7!#ÿ8!#ÿ8"$ÿ9"$ÿ9#%ÿ:#%ÿ:#&ÿ;$&ÿ;$&ÿ:$&ÿ9#%ÿ8!$ÿ6 "ÿ4 ÿ5!ÿ9%&ÿ?20ÿGC?ÿRWPÿVfVÿe}iÿm‘tÿs™wÿ}Ÿ{ÿƒ™yÿƒ”pÿ‰�kÿ‚‡fÿ~}`ÿvnTÿdWBÿUD<ÿI78ÿB.3ÿD.3ÿJ38ÿP8>ÿT=CÿW?FÿW@HÿYBIÿZCKÿ[CMÿ[DNÿ\EOÿ]EPÿ]EPÿ]EOÿcKSÿbJRÉY@K\DMYCJ:'&:&&:&&KB,-ø='(ÿ9$%ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8#%ÿ9#%ÿ9#&ÿ:$&ÿ9#%ÿ7"$ÿ5 "ÿ3 ÿ5!"ÿ>1/ÿTTNÿj{oÿušŽÿz±¦ÿ{¾³ÿ~Ǹÿ…Í®ÿ‰Ü¯ÿ‡ß©ÿ‹Ý¡ÿ“Ü�ÿ¢ÔœÿŸÆŠÿ«Â€ÿ±¿yÿµ¼tÿ¹ºnÿ¬¦Gÿ²¤Rÿ¸£]ÿ•€SÿhVIÿI6:ÿD/4ÿK5:ÿS;BÿV?FÿXAHÿYBJÿZCKÿZCMÿ[DNÿ\DNÿ\DNÿ\DNÿ^FOÿdLRø\DLK\DLZAI:('D.0=))‹B-.ÿ;''ÿ;''ÿ:&&ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ8#%ÿ8"$ÿ6!#ÿ4!ÿ3ÿ:))ÿNOLÿe„~ÿz´©ÿ†ÑÌÿ‡ÖÇÿ~ѬÿÒ¥ÿ�Ò ÿ‡Ô¢ÿ”Ø®ÿ�Þ£ÿ“ÝŸÿ™Üœÿ�Ú—ÿ«Ø�ÿ¥È�ÿ±Áÿ¸¿wÿ½¼pÿļnÿÁ´XÿÕÁ[ÿáÅQÿâÅUÿÙÀbÿµ›kÿs\PÿI5:ÿH37ÿQ:@ÿV?FÿX@HÿYBIÿYBJÿZCKÿZCLÿZDLÿ[DLÿ[DKÿbKPÿ^FL‹fOSZBI:&&2 ?++¹A,,ÿ;''ÿ;''ÿ<''ÿ<''ÿ9%&ÿ8#%ÿ8"$ÿ6!#ÿ3!ÿ2ÿ9*,ÿKU[ÿk—žÿ|ÈÇÿ}ÔÎÿ„Ø×ÿsÓÚÿ~ÕËÿÑ£ÿzЗÿ~Ò“ÿ}͘ÿqÂ�ÿŠÖ‘ÿ�Ö†ÿ“Õ‚ÿœÔ€ÿ¬Ø‘ÿ±Ñ€ÿ¿ÈdÿÈÇcÿÌÅbÿÒÄfÿÛÌyÿãÌcÿäË`ÿäËbÿåÍdÿéÎuÿ×¹pÿžŠiÿYFHÿG28ÿQ:@ÿV?FÿW@HÿXAIÿYBIÿYBJÿZBJÿZBJÿZBIÿ`HMÿ_GLºR9CZAH:&&6#"A+,Ó?*+ÿ;''ÿ;'(ÿ;((ÿ<((ÿ<((ÿ:&'ÿ5"#ÿ1ÿ5#$ÿJQYÿ[‘¥ÿZ¬Æÿb·Ìÿ{ÏÒÿ€ÔÖÿuÓÝÿoÒÓÿzØÀÿ…Ö©ÿ|Ñ“ÿ�Ñ™ÿlÂŽÿf¹�ÿ‰ÎŽÿ“Ø„ÿ™Ö~ÿ¦Ø‡ÿ¤Ôƒÿ²ÑzÿÄÆUÿËÄJÿÒÄEÿÔÁPÿйRÿáÈOÿãÊOÿäÌWÿåÏ^ÿéÖzÿäÎrÿâËnÿÁ¯sÿhVNÿH38ÿR;AÿW?FÿW?GÿW@HÿXAHÿXAHÿXAHÿXAHÿ]EKÿ_GLÓU=DY@G:&'7$$B-.Þ>*+ÿ:''ÿ;((ÿ;((ÿ;((ÿ<((ÿ;''ÿ7#"ÿD:@ÿ`�—ÿ]®ÐÿW´ÖÿS­ÊÿT¬Äÿ~ÈÒÿƒÖÞÿtÒÙÿwÖÅÿxÙ·ÿ†Û¯ÿ…ÔšÿsÈ”ÿh¾…ÿk°wÿ|ªuÿ…¥jÿ�\ÿ{‚\ÿsuQÿvqQÿ€qFÿ‹yCÿžŠHÿª“KÿµœBÿÙÁVÿåÌLÿäÌOÿæÑaÿèÔnÿçÓjÿäÍUÿæÐ[ÿɶdÿfTMÿJ49ÿT=BÿW?EÿW?EÿW?FÿW?FÿX?FÿX?Fÿ\CHÿ_FJÞV=CX?E9''7%$B-.à>*+ÿ:''ÿ;('ÿ<((ÿ<))ÿ<))ÿ<((ÿTQ\ÿj¥ÔÿoÁôÿZµÚÿU°ÐÿR¬ÅÿZ°Ãÿ…ÎÚÿˆÍÛÿ…ÍÌÿ‰Ó½ÿ‰Ö¹ÿ�Ú·ÿ„Äšÿe—oÿ]oTÿSM?ÿJ94ÿE/0ÿB*.ÿ@(-ÿ@(-ÿA(.ÿ@*1ÿB+2ÿI24ÿQ97ÿ]E<ÿ|eIÿ¬•Oÿ×Â\ÿèÕnÿåÑfÿæÔqÿãÎ_ÿáËXÿâÏfÿ°¢pÿT@BÿO7=ÿU=CÿV>DÿW>DÿW>DÿW?DÿW?DÿZBFÿ^FHàU++ÿ;((ÿ;((ÿ<((ÿ<)(ÿ=))ÿ=)(ÿWWdÿh¯äÿjÀøÿeºÛÿT°ËÿV­ÂÿsÅÒÿ}ÕÝÿ†ÎÓÿ€ÉºÿƒË²ÿ�·�ÿo„rÿTMEÿC./ÿ>'*ÿ>&*ÿ?'+ÿ?),ÿ@)-ÿA*.ÿA+.ÿB*/ÿB+0ÿC,1ÿE.3ÿI24ÿJ24ÿJ15ÿO7:ÿnXJÿ¥’[ÿŲ^ÿǶdÿÉ·cÿıSÿ¼®dÿ·©cÿ…s^ÿK4:ÿS;@ÿU))ÿTWcÿj¬ØÿnÀäÿW±Çÿk½Ìÿ{ÓÝÿwÔ×ÿ‰ÙÊÿ…À«ÿn„uÿOC?ÿ?')ÿ=%(ÿ>'*ÿ>(*ÿ?)+ÿ@(+ÿ?),ÿ@)-ÿA*.ÿA+.ÿA+/ÿB+0ÿB,0ÿC,2ÿF03ÿJ34ÿK35ÿL36ÿK26ÿS<=ÿŠwTÿ½­fÿÆ·pÿ¿°fÿªœ[ÿ¯œ\ÿ±›oÿWBDÿO8=ÿT;@ÿT;AÿU*)ÿ>**ÿ?)(ÿSS]ÿr­ÊÿpÁÒÿ{ÐÛÿwÔÚÿ|×Ëÿ{¯šÿYTOÿ>()ÿ<$'ÿ=&)ÿ>&(ÿ>')ÿ>(*ÿ?(*ÿ@(+ÿ?)+ÿ@)-ÿA*-ÿA*.ÿA*.ÿB+/ÿB+0ÿB,1ÿC-2ÿH13ÿJ34ÿK35ÿL36ÿL37ÿR<=ÿŸ‰fÿÈ´~ÿ¶¨nÿ¨–Xÿ©“^ÿ¾¢rÿt\VÿL5:ÿS:?ÿT;@ÿT;@ÿT;@ÿT;@ÿX?Bÿ[BEàS:>U<@6#%3 !A,.à?+,ÿ<((ÿ<)(ÿ=*)ÿ>*)ÿ>*)ÿ>*)ÿ?*)ÿ?**ÿ>)(ÿXRWÿ�»Àÿ†ÙØÿ†ÔÍÿr”‡ÿJ;9ÿ<$&ÿ<&(ÿ<&(ÿ=&)ÿ=')ÿ>&)ÿ>'*ÿ>(*ÿ?(+ÿ@(+ÿ@)+ÿ@),ÿ@*.ÿA+.ÿA*.ÿB+/ÿB,1ÿB,1ÿD-2ÿH13ÿJ34ÿK35ÿL36ÿJ15ÿkSHÿµ qÿ·§wÿª•_ÿ§Ž`ÿ¹™qÿ�qeÿK4:ÿR9>ÿR:>ÿS:>ÿS:?ÿS:?ÿW>BÿZADàR8=T:?6"$3!?*-à<()ÿ:''ÿ=)(ÿ=*(ÿ=*)ÿ>**ÿ>**ÿ>**ÿ?+*ÿ?++ÿ?))ÿWQOÿy®£ÿlƒwÿG32ÿ@*+ÿ@+,ÿ?)*ÿ=')ÿ=&)ÿ=')ÿ=')ÿ>')ÿ>'*ÿ>(+ÿ?(+ÿ?(+ÿ@),ÿA)-ÿA+.ÿA+.ÿB+/ÿB+/ÿB,1ÿC,2ÿD-2ÿH13ÿJ34ÿK35ÿH03ÿV@<ÿ­™sÿº¥€ÿ°˜mÿ§Šcÿ³‘rÿ£…zÿM6:ÿQ8<ÿQ8=ÿQ9=ÿR9=ÿR9=ÿV<@ÿY@CàQ7;S9=6#$3 !@+-à<')ÿ7#$ÿ:&'ÿ=))ÿ=*)ÿ>**ÿ>**ÿ?*+ÿ?++ÿ@++ÿ@,+ÿ@++ÿL=<ÿE11ÿ@++ÿA,,ÿB,-ÿB,,ÿA+,ÿ?)*ÿ>'*ÿ=')ÿ>')ÿ>'*ÿ>(+ÿ?(+ÿ?(+ÿ?(+ÿ@),ÿA*-ÿA+-ÿA+.ÿB+/ÿB+0ÿB,1ÿC,2ÿD-2ÿG03ÿG12ÿA+-ÿ^FAÿά�ÿЭ”ÿ¿¡…ÿ©ˆhÿ¾œ‡ÿ¯Ž…ÿN7:ÿP7:ÿP7;ÿQ8;ÿQ8<ÿQ8<ÿU;>ÿY>AàP6:R8<6#$3 @+-à<')ÿ8#$ÿ8#%ÿ:%'ÿ=))ÿ>+*ÿ?++ÿ?++ÿ@++ÿ@++ÿA,,ÿA,,ÿ@+,ÿA,,ÿB,,ÿB,,ÿB--ÿB--ÿB--ÿB--ÿA+,ÿ?)+ÿ>')ÿ>'*ÿ?(+ÿ>(+ÿ?)+ÿ?(+ÿ?(,ÿ@),ÿ@*-ÿA+.ÿA+.ÿB+/ÿB+0ÿA+0ÿ@+0ÿ>).ÿ=(+ÿ?++ÿ—{hÿ代ÿå¶©ÿᳩÿϦ–ÿ׬ ÿ ~yÿL58ÿO69ÿO79ÿO7:ÿP7:ÿP7:ÿT;=ÿX>?àO69Q8:7#$3 !A+.à<')ÿ7#%ÿ8$&ÿ9$&ÿ:%'ÿ=()ÿ?++ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA-,ÿB--ÿB--ÿB--ÿC--ÿC--ÿB--ÿC..ÿC--ÿC--ÿC-.ÿA+,ÿ?(*ÿ?(*ÿ?(+ÿ?)+ÿ@),ÿ?(+ÿ?),ÿ@),ÿ?)-ÿ?*-ÿ?),ÿ>(,ÿ<&*ÿ9$)ÿ6"'ÿB/.ÿŽsSÿ㽄ÿî”ÿî¾�ÿÿñÄ»ÿö¿¹ÿ–srÿJ25ÿN58ÿO69ÿO69ÿO69ÿO69ÿS:<ÿW=?àN58Q7:6#%3!A,.à=(*ÿ8$%ÿ9%&ÿ:%'ÿ:%'ÿ:%'ÿ=')ÿ?++ÿA-,ÿB--ÿB--ÿB--ÿB--ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿC..ÿB--ÿ@*+ÿ>(*ÿ='*ÿ=')ÿ=&)ÿ<%(ÿ;%(ÿ:$'ÿ9$'ÿ7#&ÿ5"%ÿ7$&ÿG4/ÿu_Jÿ½ uÿìÉ“ÿîÀ„ÿﻈÿñ¹�ÿ籟ÿå®§ÿí´¤ÿuWSÿJ24ÿL46ÿM47ÿN57ÿN57ÿN58ÿR9;ÿV<=àM36O587#%3 !A,/à=(+ÿ8$&ÿ9%&ÿ:&'ÿ;&'ÿ;&(ÿ<&(ÿ=')ÿ?*+ÿA--ÿC..ÿC..ÿC..ÿC..ÿD/.ÿD//ÿD//ÿD..ÿD..ÿC..ÿB--ÿA,,ÿ@++ÿ>**ÿ=))ÿ;&'ÿ8#&ÿ5"$ÿ4 #ÿ4 #ÿ4!$ÿ8%&ÿ@-*ÿO<2ÿnXDÿž…Zÿͳ~ÿëÍ’ÿòΙÿòË ÿðÀ�ÿñ¹Žÿì¶�ÿÚŸšÿÛ¡Ÿÿ¿“‰ÿR99ÿJ24ÿK35ÿL35ÿM35ÿM46ÿM46ÿQ79ÿT:<àK24M468$%4!!C-/à>)+ÿ9%&ÿ:%'ÿ;&(ÿ;'(ÿ<'(ÿ=')ÿ=')ÿ=(*ÿ>*+ÿA--ÿC//ÿC//ÿC//ÿD//ÿD//ÿC//ÿB--ÿ@++ÿ=))ÿ;'(ÿ9&'ÿ8%&ÿ8%'ÿ<))ÿC0-ÿM81ÿXC6ÿgP<ÿybJÿ‡sOÿ›‡Sÿ¯œ]ÿ¼©dÿÌ´sÿìÒ‘ÿòÖ™ÿðΗÿñÉœÿóƤÿóŸÿì¶–ÿÕŸ™ÿÑ—�ÿÊ‘‘ÿoPPÿC,1ÿE/3ÿF/3ÿG/3ÿH04ÿH04ÿH04ÿL37ÿO69àF-3H058$&4!"C.0à?*,ÿ9%'ÿ;&(ÿ<&(ÿ<')ÿ<()ÿ=(*ÿ>)*ÿ>)+ÿ?)+ÿ?*+ÿA,-ÿD//ÿE00ÿD//ÿB--ÿ?+*ÿ;((ÿ8&'ÿ<**ÿG61ÿXG5ÿq_@ÿ•Mÿ­•TÿÁ¡aÿϨ`ÿÚ´jÿâ½sÿßÃÿØÄ|ÿѾhÿμjÿɹkÿοwÿìÕ¤ÿóÌ¢ÿóÉ¥ÿóƨÿÿâ´¤ÿȘ¢ÿÃ�³ÿÍ” ÿ„^[ÿD-0ÿC,1ÿC-1ÿD-2ÿD-2ÿE-2ÿE.3ÿE-3ÿI16ÿM49àD,2G.48$&4!#D.1à?+,ÿ:&'ÿ;'(ÿ<')ÿ=(*ÿ=)*ÿ>)*ÿ?*+ÿ@*,ÿ@*,ÿA*,ÿA*,ÿA,-ÿB-.ÿ@,,ÿ<'(ÿ<)*ÿN?:ÿodOÿ’‰_ÿ« ^ÿ°ŸAÿȲUÿܽWÿæÇcÿêÍ{ÿéÁrÿèÂuÿâÃ{ÿÛÂÿÜȈÿÒÀpÿ̼lÿʼqÿÞÓ�ÿëÜŸÿ罘ÿߪ“ÿØž™ÿÏ“«ÿÇŽÇÿÉ”ÉÿÈ’›ÿƒ^XÿE.0ÿB*/ÿC+/ÿC+0ÿC,0ÿD,1ÿD,1ÿE,1ÿE-2ÿI05ÿL37àD+1F.29%'5!#E/2à@+-ÿ;'(ÿ<()ÿ=)*ÿ>)+ÿ?)+ÿ@*,ÿ@+,ÿA+-ÿA+.ÿB+.ÿB+.ÿ@*,ÿ;&(ÿ;')ÿZLEÿŒ‰hÿ¬°xÿ¹ºsÿ¼´hÿ»¬bÿ¶¤QÿɬTÿÝ´Xÿãº`ÿçÈuÿéÅ{ÿãÁxÿØ¿~ÿÕ¿�ÿÔÀ†ÿɺwÿ¼­fÿô{ÿÕÀ�ÿØ´˜ÿÜ¡©ÿÜ�¸ÿÛŒÍÿÚ”ÔÿØŸÁÿµŠ‹ÿhKFÿA+.ÿA*.ÿB+.ÿB*.ÿB+.ÿB+/ÿC,/ÿC,0ÿD,0ÿD,0ÿH/4ÿK26àC*/E,1:&'6"#F03àA,/ÿ<')ÿ=)*ÿ?)+ÿ?*+ÿ@*-ÿA+-ÿB+.ÿB,.ÿC-/ÿC-/ÿB,.ÿ=')ÿC00ÿ~{bÿ±Á�ÿ¹Ågÿ´¶Rÿ³¬Nÿ´¥Kÿ»¨[ÿÌ´hÿݸ^ÿß¹dÿÙ´dÿÔ²fÿÒ²tÿƬpÿÅ­tÿÉ­yÿέ�ÿÓ«‰ÿؤ�ÿ襥ÿóŸµÿûšÅÿûžÎÿò¤Èÿá¡°ÿµ‰‰ÿyZWÿJ24ÿ?(,ÿ@*-ÿA*.ÿA*.ÿA*.ÿB*.ÿA+.ÿB,/ÿB,/ÿC,0ÿC,0ÿG/3ÿK25àB+/E-0:'(6#$F24àB-/ÿ=(*ÿ>)+ÿ?*,ÿA+-ÿA,.ÿB,/ÿC-/ÿD-/ÿD./ÿD./ÿ@*,ÿE12ÿ‰Œhÿ­Ã~ÿ£¶hÿ«¯]ÿ§ <ÿ¬�5ÿ´ž6ÿ¯•?ÿ¼™HÿÊ¢HÿɤNÿÏ­XÿÖ»bÿÜÇmÿáÆsÿèÄ|ÿîÀ‡ÿò¼’ÿõ¸žÿø·¨ÿø¸°ÿð·¯ÿÞ¯ ÿ¿œ‹ÿ•ujÿgKFÿG/0ÿ='*ÿ?(,ÿ@),ÿ@)-ÿ@)-ÿA)-ÿA)-ÿA)-ÿA).ÿA*.ÿB+.ÿB*/ÿB+/ÿG.2ÿJ14àB).D+/<()7$%H35àC.0ÿ>)+ÿ@*-ÿA+.ÿB,.ÿC-/ÿC./ÿD.0ÿE.1ÿF.1ÿD-0ÿA+-ÿyu\ÿ¤¸wÿš«dÿ�§Yÿ««]ÿ¯¢@ÿ¬˜2ÿª�?ÿ´‰AÿË›UÿÞ°aÿæ¼eÿéÇjÿêÎmÿéÐoÿæÊuÿß¼rÿ×µwÿ̯yÿ¹Ÿyÿ¥ŽoÿŽx`ÿs^RÿZE?ÿH32ÿA--ÿA,-ÿC-.ÿC,-ÿA*,ÿ?(,ÿ?),ÿ?(,ÿ@),ÿ@),ÿ@),ÿA),ÿA)-ÿA*-ÿA*.ÿA*.ÿE-1ÿI04àA)-C+/=(*8$&J36àE/1ÿ?*,ÿA,-ÿB,/ÿC-/ÿD-0ÿE.1ÿF/1ÿF/2ÿG03ÿC,/ÿ]LIÿ²¿�ÿ¡³oÿ�¨]ÿ£¦Uÿ«¦Sÿ¬œGÿ´�BÿÓ—\ÿæ¥eÿå®jÿÞ³pÿÒ®lÿ¾ mÿ¦‹gÿŽtZÿzaPÿgPCÿZE=ÿQ<7ÿI42ÿD./ÿA,-ÿA+,ÿB,-ÿC-.ÿC-.ÿC..ÿC..ÿD//ÿD./ÿC,.ÿA*-ÿ@),ÿ?'+ÿ@(+ÿ@(,ÿ@(+ÿ@(+ÿ@),ÿ@),ÿA),ÿD,0ÿH/2à@(,B*->)+9%&J47àF03ÿA+-ÿB-.ÿC-/ÿD.0ÿE.2ÿF/2ÿG03ÿH13ÿH14ÿD-0ÿ†pÿÌÖ¤ÿÀÀ…ÿ±¬lÿ³¨cÿ°ŸXÿÃ�Xÿå–fÿÞŸoÿ¹�iÿŽp[ÿoVMÿZB?ÿN88ÿH24ÿE01ÿD./ÿD./ÿC//ÿC//ÿD//ÿD./ÿD./ÿD..ÿC-.ÿC-.ÿC-.ÿC-.ÿC-.ÿC..ÿC..ÿC//ÿC./ÿB-.ÿA+-ÿ@),ÿ@(+ÿ@(+ÿ@(+ÿ@),ÿ@*,ÿ@),ÿD,/ÿG/2à@(+B*-?*,:&'L68àG14ÿB,.ÿC-/ÿD.0ÿF/1ÿG03ÿH04ÿH14ÿI25ÿJ24ÿK47ÿ¦§…ÿËÕ”ÿÎÆÿDzoÿ·œVÿÆ�Wÿä�mÿ¶…nÿrWQÿP9;ÿG/3ÿE-1ÿE-0ÿE.0ÿF/1ÿG12ÿG12ÿG10ÿF00ÿD0/ÿD//ÿD//ÿD..ÿD..ÿC..ÿC--ÿC--ÿC--ÿC,-ÿC--ÿC-.ÿC-.ÿC-.ÿC-.ÿC./ÿB-.ÿB+-ÿ@),ÿ?(+ÿ?(+ÿ?),ÿ@),ÿC+/ÿG.1à?'+A)-?+-;'(M7:àH24ÿB-/ÿD.1ÿF/2ÿG03ÿH14ÿI25ÿJ25ÿK26ÿJ26ÿR<>ÿ²´ˆÿÌÔ‰ÿÕɈÿ×¼uÿѯcÿÒ”^ÿ¤thÿR;>ÿH03ÿI14ÿI14ÿH03ÿG/2ÿF.1ÿE.0ÿE.0ÿE.0ÿF/0ÿF00ÿE00ÿD//ÿD//ÿD//ÿD..ÿC-.ÿC..ÿC-.ÿB--ÿB--ÿC,,ÿC--ÿC--ÿC-.ÿC--ÿC-.ÿC,.ÿD-.ÿC-.ÿC+-ÿA),ÿ@),ÿ?(+ÿC*.ÿF-0à>&)@(+@,.<')N8;àI45ÿD.0ÿE/2ÿG03ÿH14ÿI25ÿJ25ÿK37ÿL38ÿL38ÿS<@ÿ´±…ÿÐÒ�ÿØÍ„ÿݽsÿÞ¹jÿʦqÿ_GGÿH04ÿL36ÿK25ÿJ24ÿI14ÿH03ÿG/2ÿF.1ÿE.0ÿD-/ÿC,.ÿC,.ÿD./ÿD//ÿD//ÿD//ÿD..ÿC-.ÿC--ÿC--ÿB--ÿB,-ÿB,-ÿB,-ÿB--ÿB--ÿB,-ÿB,-ÿB,-ÿC,-ÿC--ÿC,-ÿC,-ÿC,-ÿB+-ÿD,.ÿF-0à>&)@(+B,.=(*O9;àJ47ÿE/1ÿF03ÿH14ÿI25ÿK36ÿK47ÿL48ÿN59ÿO5:ÿP7=ÿ§ž{ÿ×Ó�ÿÝÏÿâÃzÿÙ¸mÿ˰zÿ\GFÿF/2ÿL37ÿL37ÿK35ÿJ24ÿI14ÿH03ÿG/2ÿF.1ÿE-0ÿC-.ÿC+-ÿA+-ÿA+-ÿB-.ÿC..ÿD..ÿC..ÿC--ÿB--ÿB,-ÿB,,ÿB,,ÿB,,ÿB,-ÿ@,,ÿ>**ÿ>)*ÿ?+,ÿA,,ÿC,-ÿB,-ÿC,-ÿC-.ÿC..ÿG01ÿI13à@*+C,-B-/=)*P:<àK48ÿE/2ÿG14ÿI25ÿJ36ÿK38ÿM49ÿN6:ÿO6:ÿP7;ÿN5:ÿˆvcÿ×ËkÿáÎqÿçσÿàÄnÿßÅyÿ‰taÿA+/ÿH04ÿK37ÿL37ÿK35ÿJ24ÿI13ÿH03ÿF/1ÿE.0ÿD-/ÿC,.ÿB+-ÿ@*,ÿ?)+ÿ@*+ÿA+,ÿB--ÿC--ÿB--ÿA,,ÿA,,ÿA,,ÿ@+*ÿ>))ÿ:&&ÿ8%$ÿ9&%ÿ;''ÿ@+,ÿB,,ÿB,-ÿC,,ÿB,-ÿB-.ÿF00ÿJ23àB+,D-.B-/=)*Q:=àL58ÿF03ÿH25ÿJ36ÿK47ÿM59ÿN5:ÿP6;ÿP7;ÿQ8<ÿQ7<ÿbJLÿİdÿãÊaÿæÌpÿäÇ_ÿäÆWÿѹjÿlXMÿ@*.ÿE.1ÿI14ÿJ25ÿJ25ÿI14ÿH13ÿG/2ÿF.1ÿE.0ÿC,.ÿB+-ÿA*,ÿ?*,ÿ?)+ÿ?(*ÿ?(*ÿ@*+ÿA,,ÿ@++ÿ>**ÿ<((ÿ9&%ÿ6#"ÿ<**ÿgN`ÿ�e†ÿR=Cÿ?**ÿA+,ÿA,,ÿB+,ÿB,,ÿB,-ÿE/0ÿI12àA++C--C.0>)+R;>àM69ÿG14ÿJ25ÿK37ÿL59ÿN6:ÿO7;ÿQ7<ÿR8=ÿS9>ÿS9>ÿR8?ÿŠtdÿÝÃdÿäÈbÿçÍoÿãÇZÿæË`ÿϺxÿxfYÿE14ÿ?)-ÿD,0ÿF/2ÿG02ÿG/2ÿG/1ÿE.1ÿE.0ÿC-/ÿB+-ÿA*,ÿ?*+ÿ>)+ÿ=(*ÿ<&(ÿ:%'ÿ9$%ÿ8$%ÿ6##ÿ5#"ÿ?,-ÿeM\ÿžy«ÿÀ•êÿ½—ïÿt\rÿ?+*ÿA++ÿA+,ÿA++ÿA+,ÿA,,ÿE/0ÿH02àA++C,-D.1?),S(*ÿ?),ÿA*,ÿA*,ÿ@*,ÿ?)+ÿ>(*ÿ<'(ÿ;&'ÿ9%&ÿ8#%ÿ5!"ÿ3 ÿ2 ÿ8&'ÿO8>ÿzYlÿ®Œ¯ÿË£ãÿÊ õÿÀ›ðÿ…i�ÿE01ÿ?*+ÿ@++ÿA++ÿA++ÿA++ÿA+,ÿD./ÿH01àA*+C,,D.1?),S<@ÞN8;ÿI25ÿK37ÿM49ÿO6;ÿP7<ÿR8=ÿT9?ÿU:@ÿV;AÿW;BÿW**ÿ?++ÿ?**ÿ@++ÿ@*+ÿA*+ÿ@++ÿC./ÿG01Þ@**B,,E/1=')S**ÿ?**ÿ@**ÿ@*+ÿ@**ÿ@*+ÿC./ÿF/0Ó?))B+,E/25!Q:=ºT=AÿI26ÿL48ÿN6:ÿO7;ÿR8=ÿT9?ÿU;AÿWEÿ[>FÿZ>EÿY=DÿX))ÿ?**ÿ@**ÿ?**ÿD./ÿD./¹<&&A++E02^HLL6:‹XAEÿJ36ÿL48ÿN6;ÿP7<ÿR8>ÿT:@ÿV;BÿX=CÿY>Eÿ[?Fÿ\?Gÿ\?Gÿ\>Gÿ[>FÿY=DÿV;Aÿ\AGÿ}g`ÿ©—sÿʼƒÿìÞ¢ÿõݬÿóÉ ÿò˜ÿó¾�ÿò»¥ÿé¹®ÿÜ©›ÿÛ ™ÿØ™šÿÓŽ¢ÿÕ“Âÿì©äÿçœæÿáœéÿÝœíÿÜ íÿРÒÿ�xžÿbGYÿ?)+ÿ9#$ÿ9%&ÿ9$&ÿ9$&ÿ9#%ÿ9$&ÿ8#%ÿ:$&ÿ;%'ÿ='(ÿ>))ÿD/0ÿB--‹D11A*+E/2G14F14LYBFøN7:ÿL48ÿN6:ÿP7<ÿS9>ÿT:@ÿVFÿ\@Hÿ^AIÿ^AIÿ\@Hÿ[>FÿZ=EÿX=CÿV;AÿS8?ÿW=DÿoYXÿ›‡wÿŰ˜ÿ⾪ÿïÀ¤ÿô¾¥ÿÿê´µÿ寭ÿÞžŸÿÚ– ÿÝ—ªÿð¬Ðÿî¥æÿâ‘áÿÖ�×ÿ¿‡¼ÿ•o�ÿcKTÿ@+-ÿ8#%ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ;%'ÿA+-ø>)*K=)*A*+F,-G14?*-T=AÊW@CÿK38ÿN6:ÿP7<ÿR9>ÿT:@ÿVFÿ]@Hÿ^AJÿ^AIÿ]@Hÿ[?FÿY=EÿX=CÿVÿP6;ÿN5:ÿT<@ÿfNPÿ~dcÿ—yuÿ¨‡ˆÿ¶�•ÿ½–œÿ»Œ’ÿ¶…�ÿ·Š—ÿµ‰˜ÿšuŠÿ|Zoÿ`EOÿH15ÿ;&'ÿ8#%ÿ:$&ÿ:%&ÿ:$&ÿ9$&ÿ9$&ÿ9#%ÿ8$%ÿ8#%ÿ8#%ÿ8"$ÿ9#%ÿ8#%ÿ9"$ÿ=&)ÿ<&)É7"$9$&B,-H-2N8;K48j[DHýO8<ÿM5:ÿP7<ÿR8=ÿT:@ÿVEÿ\?Gÿ^@Iÿ]@Iÿ\@Hÿ[>FÿY=DÿWÿQ8<ÿP7;ÿN59ÿK26ÿH04ÿG03ÿG14ÿJ36ÿK47ÿK57ÿI45ÿF02ÿ@,-ÿ<()ÿ;&&ÿ:&&ÿ;&'ÿ;&(ÿ;%'ÿ:$&ÿ9$&ÿ:$&ÿ9$&ÿ9$&ÿ8#%ÿ8#%ÿ7#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ9#%ÿ>'*ý9$&i9#&8#G04H14B+.SFÿ\?Gÿ\?Gÿ[>FÿY>EÿX=CÿWÿT:@ÿV;BÿX=CÿY=DÿY=EÿY=EÿY=DÿX=CÿWÿQ7=ÿP7;ÿN6:ÿM48ÿK37ÿJ25ÿH14ÿG03ÿF/1ÿD.0ÿC-/ÿA+-ÿ@*,ÿ>)*ÿ=(*ÿ<')ÿ<&(ÿ;&(ÿ:%'ÿ9%&ÿ9$&ÿ9$&ÿ9$%ÿ8$%ÿ8$%ÿ8#%ÿ7#%ÿ7"$ÿ7"$ÿ7"#ÿ7"$ÿ<&)ÿ<%(ã7!#:8!#8"$G15G14VÿT:@ÿU;BÿWÿR8=ÿP7<ÿO6;ÿN59ÿL47ÿK36ÿI25ÿH04ÿF/2ÿE.0ÿC./ÿB,.ÿ@+-ÿ?)+ÿ>)*ÿ<()ÿ<'(ÿ;&(ÿ:%'ÿ:%'ÿ9$&ÿ8$&ÿ8$%ÿ9$%ÿ8#%ÿ7#%ÿ7#$ÿ7#%ÿ6"$ÿ7"$ÿ7!#ÿ<&(ÿ=&)ì7!#W;$'6!#7#$I25H15Û½¾L48WZBGã^FKÿT;@ÿP8<ÿR9>ÿT9?ÿU:AÿU;AÿU;AÿU;AÿT:@ÿT9?ÿS8?ÿR8=ÿP7<ÿO7;ÿN5:ÿL48ÿK37ÿJ25ÿH14ÿG03ÿF.2ÿD-0ÿC-/ÿA,-ÿ@*,ÿ?)+ÿ=(*ÿ<')ÿ;'(ÿ;&'ÿ:%'ÿ9%'ÿ9$&ÿ8$%ÿ8$%ÿ8$%ÿ8#%ÿ7#%ÿ7"$ÿ6"$ÿ6"$ÿ8#&ÿ>'*ÿ=&)ã6"$WmFJ6!#7!#J37H15V>BJ27:V>C¼`GLý\DHÿUÿR8=ÿR8>ÿS9?ÿS9>ÿR8>ÿQ8=ÿQ7<ÿP7;ÿO6;ÿN59ÿL48ÿK36ÿJ25ÿH14ÿG03ÿF/1ÿD.0ÿC-/ÿA,.ÿ@+-ÿ?*+ÿ=(*ÿ<()ÿ;&(ÿ:&'ÿ:%'ÿ9%&ÿ9$&ÿ8#%ÿ8#%ÿ7#$ÿ7#$ÿ7#$ÿ7"$ÿ6"$ÿ8#&ÿ<')ÿ?)+ý;%'¼6!"::%'5!#6!#J37I15L48E-2O7DÿW>CÿV>BÿV=AÿU)+ÿ=(*ÿ=(*ÿ=')ÿ<')ÿ<'(ÿ<()ÿ=(+ÿ?),ÿ?),ø;&)É7#$i3 6!#5!#6!#J37M49K38S:?F-2N6;KTBàU=@àSàQ9=àO8;àN8:àM69àK57àJ36àH25àG14àF02àE/1àD.1àC-0àB,/àA,.àA+-àA+-à@*-à?*,Þ>)+Ó<')º9%'‹6"$K1 9$%6!#6!#6!#L48B,.M59N6;fMR=%*F.3I05I15I06I15H04G03F/2F.2E.1C.0B,/B+.@*-?*,>)+<(*;'(:%'9%&7$%7#$6##5"#5!#5 "4 "4 !4 !3 !3!1,B,06!#5!#5"#5!#J36M5:M5:M5:N6;N6:N6:N5;N5:M59L48K37K36I25H24G13F/2D.1C-0B-/A,.?*,>)+=(*;');'(:&'9%'9$&8$&7#%7#$8#$7#$6"$6"$6"#5"#5"#6&ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÀÿÿÿþü?øððààÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀààððøü?þÿÿÿÀÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(€ >'*F1I>')>')>'*?'*?'*?(*@(*@(+@(+@(+A)+@),@),A),B),B),B*-B*-C*-C*.C+.C,.D+/E+/D+/D,/E,0F-1E-1E.2F.1G.2G.3G/3I/4H/4H05I06L36O67P68P69Q7:R8:Q8:R9:S9<S9=T9=T:>T;?U;?U;@V<@V<@V=AW=BW>CX>DW?DX@DY@EY@FZ@GYAHY@G_@FZ@G=&'=&(=&(=&(=&)=&)9/)>'*?'*?'*?'*?(*@(+@(+@(+@(+A)+A),@),A),B),B),B*-B*-C*-C*.C+.C,/D+/E+/D+/D,/E,0F-1E-1E-2F.1G.2G.3G/3I/4H/4H/5I06L36O67P68P69Q7:R8:Q8:R9:S9<S9=T9=T:>T;>U;?U;@V<@V<@V=AW=BW>CX>DW?DX@DY@FY@GZ@GYAGT8:[CI\CJ\CK\CK\DK[@J@++<%(<%(<%(<%(>&'=&(=&)F=&)t=&)œ=')º>')Î?'*Ù?'*Þ?'*à?(*à@(+à@(+à@(+à@(+à@)+à@)+àA),àA),àB),àB),àA*-àB*-àC*.àC*.àC+.àD+.àD+/àD+/àD+/àE,0àF,1àE-1àE-2àF.1àG-2àG-3àG/3àH/4àH/4àH/5àI05àL26àO67àP68àP68àQ6:àR7:àQ8:àQ9:àS9;àS8<àS9=àS:>àT;>àU;?àU;@àU<@àV<@àV=AàW=BàW>CàW>DàW?DàW?DàX@EßY@FÚY@GÎY@H»YAHžZBHv\CJH\CK\BJ\DM]DM^CM^DM^CC7$$;%';%';%':%&<%(<%(\<&(¥=&(Û>')÷@(,ÿC+.ÿF-0ÿH/2ÿI03ÿJ04ÿJ14ÿJ14ÿK24ÿK25ÿL25ÿL25ÿL25ÿL35ÿM46ÿM46ÿM46ÿN46ÿN47ÿN58ÿO59ÿO68ÿO68ÿP68ÿQ69ÿQ7:ÿP8:ÿQ8;ÿR8;ÿR8<ÿR9<ÿS:<ÿS9<ÿT9=ÿU;>ÿU;?ÿU;?ÿU<@ÿV=?ÿY?Aÿ\BBÿ]BCÿ]CCÿ]CCÿ^DDÿ^DEÿ_FEÿ_FEÿ`FFÿ`FGÿ`GHÿaHIÿbHIÿbIIÿcIJÿbJJÿdJKÿdKLÿdLMÿdLMÿeMNÿeMNÿeNOÿfMOÿeMPÿcKOÿaINÿ^FLÿ]DKø\CKÜ\CL§\DL^]DM[ES^DN^EP^DO`@P:$&& :$&;&;%'*;%'…<%'×=&)üA*-ÿG.1ÿI03ÿI03ÿG.2ÿE-0ÿD,.ÿC+-ÿB+-ÿC*.ÿC+-ÿC+-ÿC+.ÿD+.ÿD+/ÿC,/ÿD,.ÿE-/ÿE-/ÿE-0ÿF-0ÿF-0ÿF-1ÿF.1ÿG/2ÿG/1ÿH/1ÿH/2ÿH/2ÿH03ÿI04ÿJ04ÿJ05ÿJ25ÿJ25ÿK16ÿK26ÿL27ÿL37ÿL38ÿM49ÿN49ÿQ89ÿS9;ÿT:<ÿU;<ÿU;=ÿV<=ÿV<>ÿW=?ÿW=?ÿW>@ÿX>AÿX>BÿY?CÿY@CÿZACÿZADÿZADÿ[AEÿ[BFÿ\CFÿ\DFÿ\DHÿ]EIÿ^EIÿ_FKÿ`HMÿcKOÿfOQÿjRTÿkSUÿhQTÿcKQÿ^FNý]CNØ]DN‡^EN,Q`_^FPcMB_FO:#$:$&:$&:$&:$&;$'„;%'â>')ÿD,/ÿH/2ÿF-1ÿB*-ÿ?(*ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ>')ÿ>')ÿ>')ÿ>'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(+ÿ@(+ÿ@(+ÿA)+ÿA)+ÿA),ÿA),ÿB)-ÿB)-ÿB+-ÿB+.ÿC+.ÿC*.ÿC*.ÿC,/ÿD,0ÿE,0ÿE,1ÿE-0ÿF-1ÿF-2ÿF-2ÿG.3ÿG.3ÿG.4ÿG05ÿH05ÿM36ÿO57ÿO58ÿO69ÿQ79ÿQ7:ÿQ8:ÿQ8;ÿR8;ÿR9<ÿS9=ÿS:>ÿT:?ÿT:?ÿU;?ÿU<@ÿU<@ÿVCÿW?DÿW?EÿX?FÿX@GÿX@HÿYAHÿZBIÿ[CJÿ^FMÿbKPÿiQUÿlUXÿhPVÿaHQÿ^EOã^EO†^FP _FQ_GQ_GQXCI:#$9#&9#&:$&:$&Z:$&Ò<%(ÿD+/ÿG.2ÿB+-ÿ=&)ÿ<%'ÿ<%(ÿ<%(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ>&)ÿ>')ÿ>')ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(+ÿ@(+ÿ@(+ÿ@(+ÿA)+ÿA),ÿA),ÿA)-ÿB)-ÿB*-ÿB+-ÿC+.ÿC*.ÿC*.ÿC+/ÿD,0ÿE,0ÿE,1ÿE-0ÿE-0ÿF,2ÿF.2ÿG.3ÿF.3ÿG.4ÿH/4ÿH05ÿM46ÿO57ÿO57ÿO68ÿP69ÿQ7:ÿQ8:ÿQ8:ÿR8;ÿS8<ÿS9=ÿS:>ÿT:>ÿT;?ÿU;@ÿU<@ÿV<@ÿV=AÿW=BÿW>CÿW>CÿW?DÿW?EÿX@FÿX@GÿYAHÿYBIÿZCIÿ[CJÿ[DKÿ[CLÿ\CMÿ_FOÿgNTÿmVYÿiRWÿaIRÿ^FPÓ_FQ[_GQ_GR`GR_FQ8#%4#$9#%9#%9#&•:$&ö@),ÿF-1ÿA)-ÿ<%(ÿ;$'ÿ;%'ÿ;%'ÿ<%'ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ=&(ÿ=&)ÿ>&)ÿ>')ÿ>')ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ@(*ÿ@)+ÿ@(+ÿ@(+ÿ@)+ÿA),ÿA)-ÿA)-ÿB*-ÿB*-ÿC+-ÿB*.ÿC*.ÿC+/ÿD+/ÿD,0ÿE,1ÿE-0ÿE-1ÿE,1ÿF-2ÿG.3ÿF.3ÿF/4ÿH/4ÿI04ÿM46ÿO57ÿO57ÿO68ÿP69ÿP7:ÿQ8:ÿQ8:ÿQ8;ÿR8<ÿS9=ÿS:>ÿS:?ÿT;?ÿU;@ÿU<@ÿU;@ÿV=AÿW=BÿW>CÿW>DÿW?DÿX?EÿX@FÿY@GÿYAIÿZAIÿZBIÿ[CJÿ[DKÿ\DMÿ\DNÿ]DNÿ]DOÿ_GPÿgPVÿnW[ÿhPWÿ`GQ÷`GQ—_GR`HS]GP`HR8"$8#$9"%9#%.9#%½;$'ÿC+/ÿC+/ÿ<%(ÿ:$&ÿ:$&ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ>')ÿ>')ÿ>')ÿ>'*ÿ?'*ÿ?'*ÿ?(*ÿ@)+ÿ@(+ÿ@(+ÿ@(+ÿ@)+ÿA),ÿA)-ÿA*-ÿB*-ÿC*-ÿB*-ÿB+.ÿC+/ÿD+/ÿD+/ÿD,0ÿD-0ÿE-1ÿE,1ÿE-1ÿF-2ÿF.3ÿF/4ÿG/4ÿH04ÿM46ÿO57ÿN57ÿO68ÿP69ÿP6:ÿP7:ÿQ8:ÿQ8;ÿR8<ÿR9=ÿS9>ÿS:?ÿT;?ÿT;?ÿU;@ÿU;AÿUCÿW>CÿW?DÿW?EÿX@FÿY@GÿXAHÿYBIÿZBJÿ[CJÿ[DKÿ\DMÿ\DNÿ]DOÿ]DOÿ]EPÿ^FPÿaISÿlUZÿmU[ÿcITÿ`GR¿`HS.aHS`GS`GR7"$8"$8"%8"%:8#%Ò<%(ÿE,/ÿ?(+ÿ9#&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ>')ÿ>')ÿ>')ÿ>'*ÿ?'*ÿ?'*ÿ?(+ÿ?(*ÿ@(+ÿ@(+ÿ@(+ÿA),ÿA),ÿA*-ÿA*-ÿB*-ÿB)-ÿB*.ÿB+/ÿD+/ÿD+/ÿD,0ÿD-0ÿE,1ÿE,1ÿE-1ÿF-2ÿF-3ÿF/4ÿG/4ÿH04ÿM45ÿO56ÿN57ÿO68ÿP69ÿP69ÿP79ÿP7:ÿQ8;ÿR8<ÿR9<ÿR9=ÿS:?ÿT;?ÿT;?ÿT;@ÿU;@ÿUCÿW>CÿW?DÿW?EÿX?FÿX@GÿXAHÿYBIÿZBJÿ[CKÿ[CLÿ[DMÿ\DNÿ]DOÿ]EOÿ]EPÿ^FQÿ_FQÿ_GRÿhPXÿpX]ÿeLVÿ`GSÓaHS&(ÿ>&(ÿ>&)ÿ>&)ÿ?&)ÿ?')ÿ?')ÿ?'*ÿ?'+ÿ?(+ÿ?(*ÿ?(*ÿ?(+ÿ@(+ÿ@(,ÿ@),ÿA*,ÿA*-ÿB*-ÿB)-ÿB*-ÿB+.ÿC+/ÿD+/ÿD,0ÿD,0ÿD,0ÿE,1ÿE-1ÿE-2ÿE-2ÿF.3ÿG/4ÿH04ÿM45ÿN56ÿN47ÿO58ÿO69ÿP79ÿP79ÿP7:ÿQ8;ÿR8<ÿR9<ÿR9=ÿR:>ÿT:?ÿT;?ÿT;@ÿT;@ÿUCÿW?DÿW?EÿX?FÿX@GÿXAHÿYBHÿZBIÿZCKÿ[DLÿ[DMÿ\DNÿ\DNÿ]EPÿ]FQÿ^FQÿ_GQÿ_GSÿ_GSÿdMWÿpY^ÿfNWÿ`GSÙaHS&(ÿ>&)ÿ>&)ÿ>&)ÿ?&)ÿ?')ÿ?')ÿ?'*ÿ@'+ÿ@'*ÿ@(*ÿ@(*ÿ@(+ÿ@(,ÿ?),ÿ@),ÿA*,ÿA*-ÿA)-ÿA*-ÿB*.ÿC+.ÿC+/ÿC,0ÿD,0ÿD,0ÿD,0ÿE-1ÿE-2ÿE-2ÿE.3ÿG.3ÿH/4ÿM45ÿN46ÿN47ÿO57ÿO59ÿO79ÿP79ÿP7:ÿQ8:ÿQ7<ÿR8=ÿR9=ÿR:>ÿS:>ÿT;?ÿT;@ÿT<@ÿUCÿW?DÿW?EÿX?FÿW@GÿX@HÿYAHÿZBIÿZCJÿZDLÿ[DMÿ\DNÿ]ENÿ]EOÿ^FQÿ^FQÿ_GRÿ_GSÿ`HTÿ`HTÿdLWÿpY^ÿfNWÿ`GSÓ`HR/`HR`GRaGN7!#7!#7!#7!#¾;%'ÿD+/ÿ;$&ÿ9"$ÿ9"%ÿ9#%ÿ9#%ÿ:#&ÿ:$&ÿ:$&ÿ:$'ÿ:%'ÿ:%'ÿ:%'ÿ;%(ÿ;%(ÿ;&(ÿ;&(ÿ<&(ÿ<&)ÿ<&)ÿ<')ÿ=')ÿ=')ÿ='*ÿ='*ÿ>'*ÿ?(*ÿ?(*ÿ?(+ÿ@'*ÿ@'*ÿ@(*ÿ@(+ÿ@(,ÿ@),ÿ@),ÿ@),ÿA*,ÿ@)-ÿ@*-ÿA*.ÿB*.ÿC+/ÿC,0ÿC,0ÿD,0ÿD,0ÿD,1ÿE-2ÿE-2ÿE.3ÿF.3ÿG/4ÿL45ÿM46ÿM47ÿN57ÿO58ÿO69ÿO79ÿP7:ÿQ8:ÿQ7;ÿQ8<ÿR9=ÿR:>ÿS:>ÿS;?ÿT;@ÿT;@ÿUCÿW>DÿW?EÿX?FÿW@GÿX@HÿXAHÿZBIÿZCJÿZDKÿ[DMÿ\DNÿ]DNÿ\EOÿ]FPÿ^GQÿ_GRÿ_GSÿ`HSÿaITÿ`IUÿdLWÿpY^ÿeLVÿ`GR¿`GR_GR_FQ6"#7!#7!#7!#•9#%ÿD+/ÿ;%(ÿ7"$ÿ8#%ÿ8#%ÿ8#&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$'ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ;%(ÿ;%(ÿ;&(ÿ;&(ÿ<&(ÿ<&)ÿ<&)ÿ<')ÿ=')ÿ=')ÿ='*ÿ='*ÿ>'*ÿ>(+ÿ>)+ÿ>(+ÿ?(+ÿ?(+ÿ@(+ÿ@),ÿ@),ÿ@),ÿ@),ÿA),ÿA),ÿA*-ÿA*.ÿA*.ÿB*.ÿA+/ÿA+/ÿB+/ÿC+/ÿC+0ÿD+0ÿD,1ÿD-2ÿD-2ÿE-3ÿJ23ÿL35ÿK36ÿL46ÿM47ÿN58ÿN68ÿN79ÿP8:ÿQ7;ÿQ8<ÿQ8=ÿR9>ÿS:>ÿS;>ÿT;?ÿT;@ÿU;AÿUCÿW>DÿW?EÿW?FÿW@GÿX@HÿXAHÿYBIÿZBJÿZDKÿZDLÿ[DNÿ\DNÿ\DOÿ]FPÿ^GQÿ_GRÿ_GSÿ_HTÿ`HTÿaITÿ`HTÿdMWÿoX]ÿbITÿ`FQ–^GP_FP_FO;''C6"$6"$Z7"$öA*.ÿ='*ÿ7"$ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%(ÿ;%(ÿ;&(ÿ<&(ÿ<&(ÿ<&)ÿ<&)ÿ=')ÿ=')ÿ=')ÿ='*ÿ>'*ÿ>(+ÿ>(*ÿ>(+ÿ?(+ÿ@(+ÿ?(,ÿ?),ÿ?*,ÿ?)+ÿ?)+ÿ?(+ÿ?)+ÿ?),ÿ?(,ÿ?(,ÿ?(,ÿ>),ÿ>),ÿ>),ÿ?)-ÿ?(-ÿ?(-ÿ?*.ÿ@*/ÿA*/ÿE.0ÿG/1ÿG02ÿH13ÿI14ÿI25ÿJ36ÿK47ÿL58ÿN59ÿO6:ÿP7;ÿP8=ÿR9>ÿS:>ÿT;?ÿT;@ÿT;AÿUCÿV>CÿW?DÿW?FÿW@GÿX@GÿXAHÿYBIÿYBJÿZCKÿZCLÿ[DMÿ\DNÿ\DOÿ]EPÿ]FQÿ^GQÿ_GSÿ_GSÿ_HTÿ_HSÿ`HSÿ_GSÿhPXÿmU[ÿ`GQ÷_FQ[_FQbICZ'*ÿ>')ÿ>')ÿ='*ÿ>'*ÿ>'+ÿ='*ÿ<(*ÿ<')ÿ<')ÿ;%(ÿ:%(ÿ;%(ÿ;%(ÿ;$(ÿ;$(ÿ;$(ÿ<$'ÿ;%(ÿ<%(ÿ<%)ÿ<%)ÿ<&*ÿ=&*ÿ>'+ÿA*+ÿC+,ÿC*,ÿD,-ÿE,/ÿE-/ÿF.0ÿF.1ÿG02ÿH14ÿI36ÿK48ÿL59ÿN7;ÿP8=ÿR:>ÿS;?ÿS;@ÿT;AÿVCÿV?DÿW?EÿW?FÿW@GÿXAHÿYAIÿYBJÿZCKÿZCLÿ[DMÿ[DNÿ\DOÿ\EPÿ]EQÿ^FQÿ^GQÿ_GSÿ_GSÿ_GSÿ_GSÿ_GRÿ_GRÿlUZÿgPVÿ^EPÓ^FP^FP^EO;''4 "H<>5"$…8$&ÿD,0ÿ8#&ÿ6"$ÿ6!#ÿ6!#ÿ7!$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ:#&ÿ:$&ÿ;$&ÿ;$&ÿ;$&ÿ<$'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ<%(ÿ<%(ÿ=&(ÿ=&(ÿ=&)ÿ<&)ÿ<%(ÿ;%'ÿ:%'ÿ:$'ÿ9#'ÿ9#&ÿ8#%ÿ9#%ÿ9#%ÿ9"%ÿ8#%ÿ8$&ÿ9$&ÿ9%'ÿ8%(ÿ8&(ÿ8%(ÿ9&(ÿ9&)ÿ9&)ÿ9&)ÿ9'*ÿ9'*ÿ9'+ÿ<*+ÿ?+,ÿ>+,ÿ?+-ÿ@,.ÿA,.ÿB-/ÿB-/ÿC-/ÿE-0ÿE.1ÿG/2ÿH03ÿI26ÿK48ÿM6:ÿO8=ÿQ9>ÿS:?ÿTCÿV?DÿW?DÿW?FÿW?GÿW@HÿXAIÿYBIÿZBJÿZCLÿZCMÿ[DNÿ\DNÿ[DOÿ\EPÿ]EQÿ^FQÿ^GQÿ_GRÿ_GRÿ_GRÿ_GQÿ_FQÿaISÿnW[ÿ`HRÿ]EO†PM`^EOZÿS;AÿUCÿV?DÿW?EÿW?FÿW@HÿW@IÿXBIÿYBIÿZCKÿZCLÿZCMÿ[DNÿ\DNÿ[DOÿ\EPÿ]EQÿ]FQÿ]GQÿ^GQÿ^FQÿ^FQÿ^FQÿ]EPÿgOVÿiRWÿ]EOã]DN+]DN]DM:'&8#%:&&†;&'ÿD,0ÿ6"$ÿ5!#ÿ6!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ8!#ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9"$ÿ9"%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ<$'ÿ<$'ÿ;$&ÿ:$&ÿ:#%ÿ8"%ÿ7!$ÿ7 #ÿ7 "ÿ7 "ÿ6!#ÿ6!#ÿ6"$ÿ5"$ÿ4"$ÿ3!#ÿ3"ÿ4!ÿ5 !ÿ8$#ÿ<*(ÿA1-ÿF93ÿQH?ÿVRFÿ[\Mÿ`dSÿekYÿiq\ÿqvdÿsscÿqr`ÿqq`ÿqp_ÿtn\ÿoi[ÿicXÿe\Tÿ_SNÿXJHÿQAAÿG68ÿA/2ÿ>*.ÿ=(,ÿ=)-ÿ?,/ÿA.1ÿC/2ÿE03ÿG04ÿI16ÿK49ÿN7<ÿQ:?ÿTCÿW?EÿW?FÿW?GÿW@HÿXAIÿXBIÿZCJÿZCKÿZCLÿZCMÿ[DNÿ\DNÿ[DOÿ\EPÿ]EPÿ]EPÿ]FPÿ]FPÿ]FQÿ]EPÿ]EOÿ^FPÿmVYÿaHQÿ]DN†^DR]DM;((;&&;&&:&&×E./ÿB+-ÿ7"#ÿ6!#ÿ6!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ8!#ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9"%ÿ9#%ÿ9#&ÿ:$&ÿ:$&ÿ:$&ÿ:$'ÿ;$'ÿ;%'ÿ:$&ÿ:$&ÿ9#&ÿ8"%ÿ6!#ÿ6 "ÿ6!ÿ6"ÿ6 #ÿ5"$ÿ4"#ÿ3 "ÿ2 ÿ3ÿ6!!ÿ=*&ÿF81ÿQKAÿ\`Tÿeugÿw�}ÿq–{ÿg›zÿz¬Œÿ‘ʧÿ†Ð¢ÿ‡Ô£ÿŠÖ¢ÿ�Ö ÿ�×�ÿœÚ£ÿ§Ñ¤ÿ™Å�ÿœÅŽÿŸÄ‹ÿ¯Ã„ÿª¾‚ÿ¤º�ÿ£¶~ÿ¤²{ÿ¥­yÿ«­‚ÿ•”`ÿŠƒZÿ{pVÿi[OÿWGEÿI8<ÿ?-2ÿ=*.ÿ@,/ÿB/2ÿD04ÿG14ÿJ26ÿL59ÿN8=ÿR;AÿU=CÿV?EÿW?FÿW@GÿW@HÿXAIÿYBIÿZCJÿZCKÿZCLÿZCMÿ[CNÿ\DNÿ\DOÿ\DOÿ\DOÿ\DOÿ]EOÿ]EOÿ]EOÿ]DOÿ\DOÿfNTÿhPUÿ\CMØ\DM\DMYAI;&&:&&:&&]<''üJ24ÿ=((ÿ;&&ÿ9#$ÿ6!#ÿ6!#ÿ7!#ÿ7!#ÿ7!$ÿ7"$ÿ7"$ÿ7"$ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ9#&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ8#%ÿ6"$ÿ5 "ÿ5!ÿ5!ÿ5!"ÿ4"#ÿ3!#ÿ2"ÿ2 ÿ6"!ÿB0+ÿSG@ÿacZÿkwÿq˜‘ÿt¬¥ÿt¹³ÿsÁºÿrżÿ}ËÀÿ~ɯÿi¼˜ÿ�×´ÿ…Þ¯ÿ‚Ý©ÿ„Ü¥ÿ‡Û¢ÿŠÚŸÿ�Ú›ÿ‘Úšÿ¨Ù¨ÿ›Ç‘ÿ›Å‹ÿŸÅˆÿ©Â€ÿ«¿}ÿ®¾zÿ®½xÿ®ºtÿ®¸pÿº¿}ÿ³¶`ÿ¬ªFÿ¬¥EÿªŸDÿ­ŸXÿ³¤uÿ–„bÿq`VÿR@CÿA.4ÿ>+/ÿA.1ÿE14ÿH15ÿJ37ÿL6;ÿP:?ÿT=CÿV>EÿW?FÿW@HÿX@HÿXAIÿYBJÿZCJÿZCKÿZCLÿZCMÿ[CNÿ[DNÿ\DNÿ\DNÿ]DNÿ]DNÿ\DNÿ\DNÿ]DOÿ\DNÿ^FOÿlTWÿ^FNü\DL]\DM\DK:&&;''9&&¦@+,ÿG01ÿ;&&ÿ;&&ÿ;&&ÿ:%&ÿ7#$ÿ6"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#&ÿ:$&ÿ:$&ÿ9#%ÿ8"$ÿ6!#ÿ5 "ÿ5!ÿ5 !ÿ4!"ÿ3!#ÿ2!ÿ2ÿ8%#ÿG:4ÿ^^RÿŽ‚ÿޱŸÿ�Ä®ÿ“ÐÀÿ‘ÔÈÿŽÓËÿŠÒÊÿ†ÏÈÿ‚ÍÄÿ~ËÀÿ{˼ÿ�кÿŽÓ±ÿˆÞ°ÿ€Ý¨ÿ‚Ü¥ÿ…Ü¡ÿˆÚžÿ‹Úœÿ�Ù™ÿ‘Ø•ÿ¢Ú ÿ¦Í™ÿ�Ĉÿ›Â‡ÿ¦¿€ÿ­¾{ÿ°½xÿ³¼uÿ¶¼rÿ¸ºoÿ»ºqÿÀ½sÿ¯©Dÿ®£<ÿ±¢=ÿÏ¿gÿÝÇ\ÿÞÂSÿ×½\ÿÁªfÿ™†gÿjZWÿI7>ÿ?,0ÿB.2ÿF15ÿH26ÿK49ÿN8>ÿSEÿW?FÿW@HÿX@HÿXAIÿYBJÿZCJÿZCKÿZCLÿZCMÿ[CMÿ[DMÿ[DMÿ[DNÿ\DNÿ\DNÿ\DMÿ\DMÿ\DMÿ\CMÿhQUÿbKPÿ[CK§\CI[CJ:&&:&&:&&ÜF02ÿA,-ÿ:&&ÿ;''ÿ;''ÿ;''ÿ:&&ÿ8$%ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ8"%ÿ7"$ÿ5!#ÿ4!ÿ4 ÿ4!ÿ3!"ÿ2 "ÿ1ÿ6""ÿF84ÿ_cYÿt“„ÿ~¸¨ÿ’ÓÇÿŠÛÙÿ�ÛÓÿ~Ï´ÿzÍ­ÿ|ΩÿЧÿ‚Ñ¥ÿ†Ó¤ÿ‰Õ¥ÿ�Ö¦ÿ�שÿ§Þ¾ÿªåÀÿ—â±ÿ˜â°ÿ—á­ÿ—ߪÿ–Ý¥ÿ–Ü ÿ–Ú›ÿ—Ø–ÿœØ–ÿ®Õ¡ÿœÃˆÿ•¿†ÿ¨¾|ÿ¯½xÿ²¼vÿµ¼sÿ¹»pÿ¼ºmÿ¿¹iÿÉÁyÿº±Qÿ±£:ÿƶ^ÿÜÇcÿÝÂOÿßÂOÿáÃQÿâÅTÿáÆ[ÿÖ¿nÿ´Ÿ�ÿxc^ÿL:Aÿ@-2ÿC03ÿG26ÿJ37ÿM7=ÿR;BÿU>EÿW?FÿW@HÿX@HÿXAIÿXBIÿYCJÿZCJÿZCKÿZCLÿZCLÿZCLÿZDLÿZDMÿ[DMÿ[DMÿ[DLÿ[DLÿ[CLÿbKPÿgPSÿ[CJÜ[CJ[CJ9'&:'':''G;((÷I35ÿ<))ÿ:''ÿ;''ÿ;''ÿ<''ÿ<''ÿ<''ÿ:%&ÿ8#$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"%ÿ8#%ÿ7"$ÿ6"$ÿ4 "ÿ3!ÿ3 ÿ3!ÿ2 "ÿ1 ÿ1ÿ<+)ÿVRLÿpˆÿ~µ­ÿÍÅÿ|ÓÊÿ‡ØÎÿ�ÛÙÿtÔÓÿ„ØÔÿ‰Ó¿ÿxͧÿzÏ ÿzÏœÿzЙÿ{Жÿ{Ñ“ÿ{Ñ�ÿ‡Õ™ÿ…Í¢ÿŽÖ¤ÿ‡Ü–ÿŠÚ”ÿ‘Ú•ÿ—Û–ÿ�ܘÿ¢Üšÿ§ÜœÿªÝ�ÿ¬Üœÿ½à­ÿ­Ï�ÿ¥È‘ÿµÅ†ÿ¸Â€ÿ¸¿zÿº½tÿ¼»oÿ¾¹kÿÁ¸fÿÈ»nÿÇ»fÿ³UÿÜÊmÿÝÄSÿßÂPÿàÃQÿàÄTÿáÅVÿâÇXÿãÊ\ÿéÏ|ÿÜ·nÿ³—qÿs`_ÿH6=ÿA.2ÿF25ÿI37ÿL6<ÿQ;AÿU>EÿV?FÿW@GÿX@HÿXAIÿXAIÿYBIÿZBJÿZCKÿZCKÿZCKÿZDKÿZDKÿZDLÿ[CLÿ[CKÿ[CKÿ[DJÿ]FLÿjSUÿ\DJ÷[BIG[BIZBG6' :'&9'&u>**ÿI35ÿ;''ÿ;''ÿ;''ÿ;''ÿ<''ÿ<''ÿ<''ÿ<''ÿ;&&ÿ8#%ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ6!$ÿ5!#ÿ3!ÿ2ÿ3 ÿ2 "ÿ1!ÿ2 ÿ@10ÿ]__ÿ€¢ŸÿÆÄÿ|ÒÑÿyÒÏÿyÑËÿ€ÔÊÿ‘ÛØÿwÔØÿqÒ×ÿsÓØÿŽØÊÿ|Ï¡ÿzÏœÿzКÿ{Зÿ|Ñ•ÿ|Ñ‘ÿ‚Ô•ÿŠÒ¤ÿd½Œÿ}Șÿ�Û˜ÿ†×‹ÿ‰Ö‰ÿŒÖ…ÿ�Õ‚ÿ’Ôÿ–Ó}ÿ™Ó{ÿ£Õ‚ÿ·Þ ÿ¶×‘ÿ®ÍsÿÂÍrÿÇÍuÿÊÍxÿÌË{ÿÎÊ|ÿÎÈ{ÿÏÅxÿÐÂtÿ×ʆÿÝÏ€ÿáÌdÿâÉ[ÿâÇXÿáÆVÿáÅVÿáÆWÿâÇYÿãÉ[ÿæÏpÿèÅsÿå½aÿÏ´rÿ›Šuÿ\LRÿB04ÿE15ÿI37ÿL6;ÿQ;AÿU>EÿW?FÿW@GÿW@HÿX@IÿXAIÿYBIÿYBIÿYBJÿYBJÿZBJÿZCJÿZCJÿZCJÿ[CJÿ[BJÿZBJÿZCIÿiRTÿ^FLÿZAHuZBIcNF:&'8$-9&%�B,-ÿH12ÿ;'&ÿ;''ÿ;''ÿ;''ÿ;''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ9%&ÿ8#%ÿ8#%ÿ8#%ÿ7"$ÿ6!#ÿ4 "ÿ3 ÿ3 ÿ2 !ÿ1!ÿ2ÿA22ÿZcgÿe•¢ÿc®Ãÿ†ÎÙÿ{ÒÔÿyÑÎÿyÑËÿ{ÒÊÿ�ÙØÿzÔÞÿnÑÛÿoÑÙÿoÒÒÿŠÛÆÿ†Ô§ÿzÏšÿ{Иÿ|Еÿ|Ñ’ÿ~Ò‘ÿŽÕ£ÿnÓÿa»†ÿk¼ˆÿ“×�ÿ‰×ŠÿŒÖ‡ÿ�Ö„ÿ’Õ�ÿ•Ó~ÿ˜Ó{ÿ�Ó{ÿ¯Ú”ÿ£Ôˆÿ°Ö�ÿ¬Êfÿ¼ÆTÿÁÅQÿÅÄOÿÈÄMÿÌÄMÿÐÄNÿÔÅPÿÙÇYÿßÑ…ÿäÓ}ÿåÏgÿçÑmÿèÒqÿèÓsÿçÒrÿæÐpÿæÏmÿåÎkÿåÏnÿêЃÿÞ½hÿ×¼iÿÖ¼oÿ»§|ÿvffÿG4;ÿD14ÿI27ÿL6;ÿR;AÿU>EÿW?FÿW@GÿW@HÿW@HÿXAIÿXAIÿYBIÿYBIÿYBIÿYBIÿZBIÿYBIÿYBIÿZBIÿZBIÿYAIÿeNQÿ`IMÿYAHžS7<Y@G:&&:&&9%%»D.0ÿD//ÿ:'&ÿ;''ÿ;''ÿ;''ÿ;''ÿ;'(ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ;''ÿ8$&ÿ7"$ÿ5!#ÿ2!ÿ2ÿ2 ÿ1 !ÿ1ÿ>--ÿYaeÿhš«ÿ_¯ÊÿX°ËÿU®Æÿs¿Îÿ„ÓÔÿwÐÏÿvÏÎÿ‰Ö×ÿ�ÖáÿnÑÜÿoÑÙÿoÑÕÿsÕÆÿ~Ú¾ÿ‘Ú´ÿ{Иÿ{Жÿ|Ñ“ÿ|Ñ�ÿŒÖŸÿwÇšÿc¾‰ÿc»„ÿd¶~ÿ‹Ë—ÿ‘ØŽÿŽÖ„ÿ‘Õ‚ÿ”Ôÿ—Ó|ÿšÒyÿ¬ØŽÿ¨ÖŽÿžÐ|ÿ«Ô‡ÿ¸Ïvÿ¿ÅSÿÄÄPÿÇÃMÿÊÃJÿÍÂGÿÐÁDÿÓÀAÿØÆ]ÿȳQÿØÂ`ÿáÆFÿáÆFÿâÈJÿãÊPÿåÍWÿæÏ^ÿçÑfÿçÓlÿèÔsÿíÝ™ÿåцÿàË|ÿàÊÿßÊ€ÿÑ¿‹ÿ�‚}ÿNEÿW?FÿW?GÿW@GÿW@HÿW@HÿWAHÿXAHÿXAHÿXAHÿXAHÿYAHÿYBHÿYAIÿYAIÿY@HÿbJOÿbKNÿX@G»YAGYAG:&&:&&9&%ÎG02ÿB,-ÿ:&&ÿ;''ÿ;''ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ:((ÿ6#$ÿ2!ÿ2ÿ2!ÿ0ÿ7$$ÿSQTÿg‘£ÿb²ÑÿZ¶×ÿW¯ÌÿV®ÇÿU­Åÿ]±Çÿ…ÎÖÿuÏÐÿ�ÓÓÿ‰ØàÿoÑÝÿoÑÚÿoÑ×ÿrÔÌÿvؼÿwظÿ�Ý»ÿƒÓ�ÿ|Ñ“ÿ{Ñ�ÿˆÕšÿ‚Í ÿd¿Šÿe¿‡ÿe¹�ÿfµ{ÿy¾‡ÿš×•ÿ�Õ‚ÿ”Ôÿ—Ó}ÿ™Óyÿ§×‡ÿ­Ú”ÿŸÓÿ¢Ò|ÿ¨Ò|ÿÀÖ„ÿÆÇUÿÈÅNÿÊÄKÿÍÃHÿÐÂEÿÓÀAÿØÅUÿκZÿÀ¥6ÿÌ´TÿâÉVÿáÆFÿâÇIÿãÉKÿãÊLÿãÊMÿãËPÿãÌPÿçÓiÿêØÿèÓsÿâÉTÿãÌ[ÿäÎcÿæÑkÿàÎyÿ ‘sÿQ?EÿD15ÿI37ÿN8=ÿSEÿW?FÿW?FÿW?FÿW?GÿW?GÿX@HÿX@GÿX@HÿX@HÿX@HÿX@HÿXAHÿYAHÿX@Gÿ_GLÿdLOÿX@FÎY@FY@F:&&:&&:&&ÙH24ÿA,-ÿ:&'ÿ;''ÿ;('ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ:''ÿ8%%ÿ6"#ÿ3!"ÿ2 ÿH:<ÿd|Šÿf­Ìÿ[¶ÛÿXµ×ÿX³ÓÿT­ËÿS«ÈÿS«ÆÿS«ÄÿxÂÏÿƒÓÓÿŒÙÞÿsÒÞÿnÑÚÿoÑØÿqÒÑÿu׿ÿwعÿvÙµÿƒÜ¹ÿ�Ù¨ÿ{Ñ�ÿ‚Ô”ÿŠÒ£ÿgÀŽÿd¿‡ÿg½…ÿg¸~ÿhµzÿn¶yÿ˜Ð•ÿ˜×„ÿ˜Ò|ÿ›ÍwÿŸÈvÿ«Ç‰ÿš¹uÿ—±mÿ—«jÿ–¦gÿ£©pÿ­¤Yÿ°¥Nÿ·«NÿÀ±LÿÉ·HÿÓ¿OÿÓÁcÿŬ=ÿ¦5ÿ©?ÿÞÈdÿãÈIÿãÈKÿãÊLÿãÊNÿãËPÿãÌQÿæÑ`ÿêØ|ÿæÒfÿéØ{ÿäÍZÿâÊQÿâÊSÿãÌVÿäÎWÿàÌcÿ ‘oÿO>DÿF15ÿJ48ÿO9>ÿT=CÿW>EÿW?EÿW?EÿW?FÿW?FÿW?GÿW@GÿW@GÿW@GÿX@GÿX?GÿY@GÿX@FÿX@Fÿ^EKÿeLOÿX?FÚX?FX?F;'':'':''ßI35ÿ@,,ÿ:''ÿ:''ÿ:''ÿ;('ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ=((ÿ<((ÿ;''ÿ9$$ÿ7$#ÿ<++ÿ[[gÿ‚ªÉÿiºàÿW´ÜÿW³ØÿV³ÖÿU±ÒÿR«ÊÿR«ÇÿS¬ÄÿS¬ÁÿdµÅÿ Ûàÿ‡ØâÿwÓÝÿtÓÚÿrÒÕÿuÖÄÿvعÿvÙ¶ÿvÙ³ÿyÚ²ÿ’ݳÿ‚Ô”ÿŽÕ£ÿnÓÿc¿ˆÿf¿†ÿj¾ƒÿl·{ÿq°tÿt£kÿƒ�oÿ„‘bÿuwOÿjdEÿcUAÿ[J>ÿTA8ÿQ;6ÿO85ÿM65ÿL66ÿN87ÿQ;9ÿV@:ÿ_I>ÿnWAÿ~hLÿ‹tNÿ›ƒGÿ«’Eÿ·žAÿÒ½cÿåÍVÿäÊKÿãÊNÿãËPÿãÌQÿäÏXÿêØ{ÿçÓkÿæÒdÿèÖtÿèÕpÿäÍSÿäÍVÿäÎXÿäÏ[ÿæÐ]ÿàÌhÿ—ˆnÿK9@ÿH15ÿL5:ÿQ;@ÿU=CÿV>DÿV?DÿW?EÿW?EÿW?FÿW?FÿW?FÿW?FÿW?FÿW?FÿW?FÿX@FÿX?Eÿ\DIÿdMOÿX?EßX?EX?E:'':'':''àJ35ÿ@+,ÿ:''ÿ:''ÿ:''ÿ:''ÿ;('ÿ;((ÿ<((ÿ<((ÿ<()ÿ<))ÿ<))ÿ=))ÿ;((ÿ8%%ÿH67ÿp€”ÿr·íÿrÃþÿsÀçÿT±ÙÿU²×ÿV²ÕÿU°ÏÿR«ÇÿS¬ÅÿT¬ÂÿS¬¿ÿq¾Ëÿ¢Úæÿ�ÎÞÿ�ÏÜÿ�ÑÛÿ‘ÖÒÿ“ÚÇÿ�ÛÃÿ�Ü¿ÿ‰Ý»ÿ„ݶÿ’à¸ÿ›Ü­ÿwÈ™ÿeÀ‰ÿl½…ÿq®zÿq”iÿisTÿ^VCÿRA7ÿI31ÿC,.ÿ@(-ÿ?(-ÿ?(,ÿ?(-ÿ@)-ÿA).ÿB*/ÿB*/ÿB+0ÿA+1ÿA+1ÿB+2ÿC,2ÿH03ÿI13ÿK35ÿP78ÿYA=ÿjSDÿˆsVÿµ `ÿÓ¼UÿâÊRÿäÍQÿäÎSÿé×tÿèÕrÿæÒdÿæÒgÿçÔlÿëÚÿåÏZÿåÏXÿåÐZÿæÑ\ÿæÑ_ÿèÔbÿÛÍ…ÿ~plÿF39ÿJ26ÿN8=ÿSDÿV?DÿV?DÿW?DÿW?EÿW?EÿW?EÿW?EÿW?EÿW?EÿW?EÿW?Dÿ\DHÿdMNÿW?DàW?DW?D9''9''9''àI46ÿ@,,ÿ:''ÿ:''ÿ;''ÿ;''ÿ;((ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<((ÿSDGÿ{™·ÿo½úÿb¼ÿÿd¼üÿ{Åðÿ[µÙÿV²ÕÿV²ÒÿU¯ÌÿS¬ÅÿS¬ÃÿS¬Àÿe¶Åÿ†ÒÞÿˆ×âÿ‰ÊÚÿyÁÒÿ|ÄÌÿ‚ɼÿ…˸ÿˆÍ·ÿ‹Ï·ÿ�Ñ·ÿ’Ô·ÿ˜Ù»ÿ˜Õ´ÿo±‚ÿm‘lÿciRÿTF<ÿG10ÿA(,ÿ>&*ÿ>'*ÿ?(,ÿ@)-ÿ@)-ÿA).ÿA+.ÿA+.ÿ@*.ÿA*.ÿB*/ÿB*/ÿC+/ÿB,1ÿC,1ÿB,2ÿB-2ÿF/3ÿK34ÿK34ÿK34ÿK24ÿK25ÿL47ÿT=>ÿmWIÿš…VÿÉ´ZÿåÒlÿëØxÿæÒdÿæÒgÿæÓiÿæÔjÿéÙ}ÿæÓlÿâÌWÿáÌYÿàÌ[ÿßÌ[ÿàÑsÿÑÄxÿ·ªuÿaRVÿG05ÿL5:ÿQ:?ÿT=BÿU=CÿV=CÿV>CÿV>CÿV>CÿW>DÿW>DÿV>DÿW?DÿW?CÿW?DÿW>Dÿ\CGÿdLMÿW?CàW?CW?C9'&9'&9'&àI46ÿ@,-ÿ;''ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ<))ÿ=))ÿ=((ÿUEHÿyŸÄÿf½ÿÿb¼üÿb¼ùÿtÃõÿm½ÞÿU±ÒÿV²ÐÿU¯ÊÿS¬ÃÿS¬Áÿ[°Áÿ„ÍÙÿ{Õßÿ{ÔÝÿ’ÓÝÿ}ÃÏÿÇ¿ÿ�ɶÿ�Ê´ÿ�ʱÿ�Ê®ÿƒË­ÿ‡Æ¥ÿ€ªŽÿr{jÿWI@ÿF/0ÿ>'*ÿ='*ÿ>(*ÿ?(,ÿ?'+ÿ?(+ÿ?),ÿ@),ÿ@)-ÿ@)-ÿ@*.ÿA+.ÿA+.ÿ@*.ÿA*/ÿB*/ÿB*/ÿB+0ÿB,1ÿC,1ÿC,2ÿC-2ÿG03ÿK34ÿK34ÿK34ÿL35ÿL35ÿL36ÿK37ÿN6;ÿeOGÿ›‰gÿƳfÿн_ÿλ_ÿ̹`ÿʸaÿʹhÿÐÁuÿŰOÿïOÿ®Oÿŵ^ÿ¾²sÿ«�WÿƸiÿš‹tÿL9@ÿI16ÿO8=ÿS;AÿUCÿV>CÿV>CÿV=CÿV>CÿW>CÿW>CÿW>Cÿ\BFÿdKLÿW>CàW>CW>C:'&:'&:'&àJ56ÿ@,-ÿ:((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<)(ÿ=)(ÿ=))ÿ=))ÿ=))ÿ=))ÿ=((ÿREJÿrš¿ÿh¾úÿb¼÷ÿh¾õÿ{ÄçÿX³ÑÿV²ÎÿU¯ÇÿT¬ÁÿV­¿ÿ|ÅÒÿ�ÖàÿvÓÜÿvÓÚÿ�×ÜÿˆËÉÿ€É·ÿ�ʵÿ�ʲÿƒÌ°ÿˆÅ¨ÿ‚£Šÿji[ÿN:7ÿ?')ÿ=%(ÿ>&*ÿ>'+ÿ>(+ÿ>)+ÿ?),ÿ@(,ÿ@'+ÿ?(+ÿ?),ÿ@),ÿ@)-ÿ@).ÿ@*.ÿA+.ÿA+.ÿA+.ÿA*/ÿB*/ÿB*/ÿA,0ÿC,1ÿC,2ÿC,2ÿD.3ÿI23ÿK34ÿK35ÿK35ÿL35ÿL36ÿM46ÿL47ÿK37ÿO7;ÿjULÿ�‹^ÿº§\ÿ¼ªZÿ¼«]ÿ¼¬_ÿǹvÿ°Zÿ½©LÿÀ®Uÿµtÿª�[ÿ§˜Uÿ¾¬cÿÁ¯wÿl\]ÿG/4ÿL5:ÿR:?ÿT')ÿ>')ÿ?')ÿ>'*ÿ>(*ÿ>)*ÿ>)+ÿ?),ÿ@(,ÿ@(,ÿ?),ÿ@),ÿ@),ÿ@)-ÿ@*.ÿA*.ÿA+.ÿA+.ÿA+/ÿB+0ÿB*0ÿB+0ÿB,0ÿC,1ÿC,2ÿC-2ÿF/3ÿI33ÿJ34ÿK35ÿK35ÿL35ÿM36ÿM46ÿM48ÿL58ÿL48ÿZDCÿ�~\ÿ¹¨`ÿ½­^ÿ½­`ÿ´mÿɹpÿ¾¬PÿÄ·pÿ¯£cÿ§™Tÿ§—Wÿ³ `ÿ˵qÿ›‰uÿM8>ÿJ37ÿO8=ÿS;@ÿT<@ÿT<@ÿT*)ÿ>**ÿ>**ÿ>**ÿ>**ÿ=)(ÿP@Bÿr”°ÿj½ïÿlÀïÿxÃÝÿW³ÉÿT­ÁÿdµÄÿ‡ÒÝÿxÔÞÿwÓÛÿwÓØÿxÔÔÿ}ÙÃÿ–ÝÆÿ‹Î¸ÿ†´žÿotgÿL86ÿ=%'ÿ<%(ÿ=')ÿ=&)ÿ=')ÿ>'*ÿ?'*ÿ?'*ÿ>'*ÿ?(*ÿ?(*ÿ?)+ÿ?(+ÿ@(+ÿ?),ÿ?)-ÿ@)-ÿA)-ÿ@)-ÿ@*.ÿA*.ÿA*.ÿA+.ÿB+/ÿB+0ÿB+0ÿA+0ÿB,0ÿB,1ÿC,2ÿD-2ÿG03ÿJ33ÿJ34ÿK35ÿK35ÿL35ÿM36ÿM46ÿL48ÿL58ÿL47ÿU??ÿŽ}]ÿ¾¯iÿÀ²hÿ¿²gÿʾ{ÿǸoÿ¶ªlÿ¦™Tÿ¨˜Wÿ¨–Yÿ¬—^ÿÆ­nÿ¼¥|ÿbPSÿH14ÿM7<ÿR:?ÿS;@ÿT;@ÿT;@ÿT;@ÿU;AÿU*)ÿ>**ÿ>**ÿ>**ÿ>**ÿ=((ÿN=?ÿr�©ÿl¾êÿ}Çæÿ`·Êÿ[±Áÿ„ÍØÿ|ÕßÿwÓÛÿwÓÙÿxÓÖÿ{×Éÿ~ܽÿ�Öºÿ…–‰ÿUGCÿ>'(ÿ<%&ÿ=&(ÿ=&(ÿ>&)ÿ>&(ÿ=&(ÿ=&)ÿ>')ÿ>'*ÿ>'+ÿ>(+ÿ?(*ÿ?(*ÿ@)+ÿ@(*ÿ?(+ÿ?),ÿ@)-ÿ@*-ÿA*-ÿA*.ÿA*.ÿA*.ÿA*.ÿA+.ÿB+/ÿB+0ÿB+1ÿB+1ÿB,0ÿB,1ÿC,2ÿD-3ÿH13ÿJ33ÿJ34ÿJ35ÿK36ÿL35ÿM36ÿM46ÿL47ÿL58ÿK47ÿWBBÿ¥’uÿ͹„ÿ̺„ÿÑÑÿĹ…ÿ§šUÿ§˜Vÿ¨—Yÿ©•\ÿ§‘]ÿ½£lÿË®|ÿ‚niÿI15ÿM6:ÿQ9>ÿS:@ÿS;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿU;@ÿU;@ÿZ@DÿbIJÿU<@àU<@U<@:'':'':''àL68ÿA-.ÿ;((ÿ;)(ÿ;)(ÿ<))ÿ<))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=*)ÿ>*)ÿ>*)ÿ>**ÿ?**ÿ?**ÿ?**ÿ>)(ÿM;<ÿq�¡ÿzÃæÿsÀÒÿzÅÑÿ€ÕàÿvÓÜÿwÓÙÿxÓ×ÿyÖÎÿ€Û¿ÿ…¨ÿjndÿE/0ÿ:$'ÿ;&(ÿ<&(ÿ=&(ÿ=&(ÿ=&)ÿ>&)ÿ>&(ÿ>&(ÿ>&)ÿ>')ÿ>'*ÿ=(*ÿ>(+ÿ?(+ÿ@)+ÿ@(+ÿ@(*ÿ?)+ÿ?),ÿ@)-ÿ@*-ÿA*.ÿA+.ÿA*.ÿA*.ÿA*.ÿA+.ÿB+/ÿB+0ÿB+1ÿB,1ÿB,1ÿB,1ÿC-2ÿE.3ÿI23ÿJ34ÿJ34ÿJ35ÿK36ÿL35ÿM36ÿM46ÿM47ÿL58ÿJ36ÿgQJÿ¶™lÿŧnÿÀ©wÿ½±�ÿ©›Yÿ¨—Xÿ©•[ÿ©”^ÿ¦�^ÿ³˜hÿέ{ÿ ˆxÿN7=ÿK48ÿQ9=ÿS:?ÿS:?ÿS;?ÿT;?ÿT;?ÿT;?ÿT;@ÿT;@ÿT;@ÿT<@ÿT;?ÿZ@CÿbHJÿU;?àU*)ÿ>*)ÿ>*)ÿ>*)ÿ?*)ÿ?**ÿ?**ÿ?**ÿ?**ÿ>))ÿK9:ÿx�œÿ¢Ôáÿ–Ûâÿƒ×ßÿÖÜÿ|ÕÙÿ{ÖÔÿ‚ÙÂÿ‚¬˜ÿ\QLÿ>'(ÿ;$&ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ=&(ÿ=&)ÿ<'*ÿ=&)ÿ>&(ÿ>&(ÿ>&)ÿ?'*ÿ>'*ÿ=(*ÿ=(*ÿ>(+ÿ@),ÿ@(+ÿ@(*ÿ@)+ÿ@),ÿ@),ÿ@*-ÿ@+.ÿA+.ÿA*.ÿA*.ÿA*.ÿB+/ÿB+/ÿB+0ÿB,1ÿB,1ÿB,1ÿB,1ÿC-2ÿE.3ÿI23ÿJ34ÿJ34ÿJ35ÿK36ÿK36ÿM36ÿM46ÿM47ÿK37ÿK68ÿ”{`ÿÀ¦oÿµ£qÿ½¯„ÿ±¢jÿ¨•Yÿ©”]ÿª’`ÿ¦�`ÿ«�eÿ˨{ÿ¶˜€ÿYBGÿI37ÿO8=ÿR9>ÿR:>ÿR:>ÿS:>ÿS;>ÿS:>ÿS:>ÿT:?ÿT:?ÿT;?ÿT;?ÿY@CÿaHIÿT:?àT;?T;?5"$5"$5"$àI26ÿ@,-ÿ;((ÿ<((ÿ<)(ÿ<*(ÿ<*(ÿ=*)ÿ=*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ?**ÿ?**ÿ?*+ÿ?*+ÿ>))ÿL88ÿ�“”ÿ—ÖÒÿ‰×Ðÿ�ØÐÿ�ÛÑÿšÚÈÿ„šŒÿQ@>ÿ@**ÿ@++ÿ>()ÿ<&(ÿ<%(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=')ÿ=')ÿ=')ÿ=')ÿ>&)ÿ>&)ÿ>&*ÿ>'*ÿ>(*ÿ>(*ÿ?(+ÿ?(+ÿ@(+ÿ?)+ÿ@)+ÿA),ÿ@),ÿ@*-ÿ@+.ÿA+.ÿA+/ÿA*.ÿA*.ÿB+/ÿB+/ÿB+0ÿB,1ÿC,1ÿB,2ÿB,1ÿC-2ÿE.3ÿI23ÿJ34ÿJ34ÿJ35ÿK36ÿK36ÿL36ÿM36ÿK36ÿE/2ÿq[Nÿ´¡sÿ´£tÿ¸§}ÿ¼¬€ÿ©”]ÿ©’_ÿª�bÿ§‹bÿ¦ˆdÿÄŸxÿ „ÿfOQÿH16ÿO7<ÿQ9>ÿR9>ÿR9>ÿR9>ÿR:>ÿS:>ÿS:>ÿS:>ÿS:?ÿS:?ÿS:?ÿX?Bÿ`GIÿT:?àT:?T:?6"$6"$6"$àH15ÿ=(*ÿ8%&ÿ<((ÿ=)(ÿ=)(ÿ=*(ÿ=*(ÿ=*(ÿ=*)ÿ=*)ÿ>))ÿ>))ÿ>**ÿ>**ÿ>**ÿ>**ÿ?+*ÿ?+*ÿ?++ÿ?++ÿ?++ÿ>**ÿJ66ÿxІÿ~ÌÀÿwÑÁÿ�̵ÿw‡vÿK76ÿ?++ÿA,,ÿA,,ÿA,,ÿ@++ÿ>()ÿ=&(ÿ<&(ÿ<&(ÿ=&(ÿ=&)ÿ=')ÿ=')ÿ=')ÿ>')ÿ>')ÿ>'*ÿ>'+ÿ>(*ÿ>(*ÿ>(*ÿ?(+ÿ?'+ÿ?(+ÿ?)+ÿ@),ÿA),ÿA),ÿ@*-ÿ@+.ÿA+.ÿA+/ÿA*/ÿB*/ÿB+/ÿB+/ÿB+0ÿB,1ÿC,1ÿB,2ÿB,1ÿC-2ÿE.3ÿI23ÿJ34ÿJ34ÿJ35ÿK36ÿK36ÿL35ÿJ24ÿD-0ÿ]GAÿ«šrÿµ¤vÿ¶¡yÿÀ­‹ÿ¯šiÿª�aÿª�dÿ§‰cÿ¤…dÿº•sÿͨŽÿw_`ÿH05ÿN6;ÿP8=ÿQ9=ÿQ9=ÿQ9=ÿQ9>ÿR9>ÿR9>ÿR9>ÿR9>ÿR9>ÿS9>ÿW>Bÿ`GHÿS:>àS:>S:>6"$6"$6"$àI25ÿ=(*ÿ6#$ÿ8%%ÿ;('ÿ=)(ÿ=)(ÿ=)(ÿ=)(ÿ=*)ÿ=**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ?+*ÿ?+*ÿ?++ÿ?++ÿ?++ÿ>**ÿH44ÿt„€ÿ†Äµÿr~tÿG21ÿ?**ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿ@*+ÿ>()ÿ=')ÿ=')ÿ=&)ÿ=')ÿ=&)ÿ=')ÿ=')ÿ>')ÿ?')ÿ>'*ÿ>'+ÿ>(+ÿ>(*ÿ?(+ÿ?(+ÿ@'+ÿ?(+ÿ?),ÿ@),ÿA),ÿA)-ÿA*-ÿA+-ÿA+.ÿA+/ÿA+/ÿB*/ÿB+/ÿB+/ÿB+0ÿB,1ÿC,1ÿC,2ÿB-2ÿC-2ÿE.3ÿI23ÿJ34ÿJ34ÿJ35ÿJ36ÿJ25ÿG02ÿB*,ÿXA<ÿ¯›wÿ¸£zÿµŸzÿ¼¥‡ÿ¹¤ÿª�bÿª�eÿ¦‡eÿ¥„fÿ²Žtÿྫÿ…llÿG04ÿO6:ÿQ7<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8=ÿQ8=ÿR9=ÿR9=ÿR9=ÿR9=ÿW=Aÿ`FGÿS9=àS9=S9=6#$6#$6#$àJ36ÿ>)*ÿ7#$ÿ7#$ÿ8#%ÿ;&'ÿ=()ÿ=))ÿ=*)ÿ=*)ÿ=*)ÿ=**ÿ>**ÿ>**ÿ>**ÿ?**ÿ?**ÿ?**ÿ?*+ÿ@++ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ?++ÿI55ÿbYWÿH33ÿ@++ÿA,,ÿA,,ÿA,,ÿA,,ÿB,,ÿB,,ÿA,,ÿA,,ÿA,,ÿ@*+ÿ>()ÿ=')ÿ='*ÿ>'*ÿ>')ÿ=')ÿ=')ÿ>')ÿ?'*ÿ>'*ÿ>(+ÿ>)+ÿ>)+ÿ?(+ÿ?'+ÿ@'+ÿ?(+ÿ?),ÿ@),ÿA),ÿA)-ÿA*-ÿA+-ÿA+.ÿA+.ÿA+/ÿB*/ÿB+/ÿB+/ÿB+0ÿB,1ÿC,1ÿC,2ÿB-2ÿC-2ÿE.3ÿH13ÿJ33ÿJ34ÿI24ÿG03ÿB-/ÿ?'*ÿ^HBÿͬŽÿÕ´’ÿħˆÿºŸƒÿÀ©Žÿ­‘jÿª‹gÿ¦†fÿ¦ƒiÿÀ¡Žÿê°ÿ‰nlÿG14ÿN69ÿP7;ÿP7;ÿP8<ÿP8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿR8<ÿR8<ÿR8<ÿW<@ÿ`EFÿS8<àS9<S9<6#$6#$6#$àJ36ÿ>(*ÿ7"$ÿ8#%ÿ8#%ÿ8#%ÿ:%&ÿ<((ÿ=))ÿ=*)ÿ>*)ÿ>**ÿ>**ÿ>++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ@,+ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@++ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA--ÿA--ÿB--ÿB--ÿB,-ÿB,,ÿB,,ÿA+,ÿ?)*ÿ>')ÿ='*ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?')ÿ>'*ÿ>'*ÿ>(+ÿ?)+ÿ?),ÿ?(+ÿ?'+ÿ?'+ÿ?(,ÿ?),ÿ@),ÿA)-ÿA*-ÿA*-ÿA+-ÿA+.ÿA+.ÿA+/ÿB+0ÿC+/ÿB+/ÿA+0ÿB,1ÿC,1ÿC,2ÿB-2ÿC-2ÿD-3ÿG02ÿH12ÿE01ÿA-.ÿ@)+ÿ<(*ÿx`SÿÜ·™ÿ㺟ÿá¶¡ÿÙ¯›ÿѯžÿº�ÿ©‰hÿ¥ƒgÿµ•�ÿέ�ÿà´¤ÿ‰mkÿH24ÿN69ÿO7:ÿP7:ÿP7:ÿP7;ÿP7;ÿQ7;ÿQ7;ÿQ7;ÿQ8<ÿR8;ÿQ8;ÿV)*ÿ8#$ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9$&ÿ<'(ÿ>**ÿ>+*ÿ>+*ÿ>+*ÿ>++ÿ?++ÿ?++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@,+ÿA,+ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB+,ÿ?)+ÿ=(*ÿ>')ÿ>')ÿ>'*ÿ>(*ÿ?'*ÿ>'*ÿ>'*ÿ>(+ÿ?)+ÿ?),ÿ?(+ÿ?'+ÿ?(+ÿ?(,ÿ@),ÿ@),ÿ@)-ÿA*.ÿA*-ÿA+-ÿA+.ÿA+.ÿA+/ÿB+0ÿC+/ÿB+/ÿA+0ÿB,1ÿC,1ÿB,2ÿA,1ÿA+0ÿ@+0ÿ@+.ÿ@++ÿ@**ÿ<)*ÿF30ÿ¬�vÿ㻟ÿâ·¡ÿ㶤ÿå´§ÿæ´¬ÿݶ§ÿÀ”|ÿ´�{ÿˬœÿË£“ÿÓ¨�ÿedÿG14ÿN68ÿO79ÿO79ÿO79ÿP7:ÿP7:ÿP8:ÿP8:ÿP8:ÿP8:ÿP8;ÿQ7:ÿV<>ÿ^DDÿQ8:àQ8;Q8;7#$7#$6"$àJ46ÿ>)+ÿ7#$ÿ8#$ÿ8#%ÿ8#%ÿ8$&ÿ8$&ÿ8$&ÿ;&(ÿ>))ÿ?+*ÿ?+*ÿ?+*ÿ?++ÿ?++ÿ@++ÿ@+,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA-,ÿA--ÿA--ÿA--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB,-ÿB-,ÿB--ÿB--ÿC--ÿC--ÿB--ÿB--ÿB--ÿC--ÿC-.ÿA+-ÿ?)*ÿ>')ÿ>')ÿ>'*ÿ?(*ÿ?(+ÿ?(+ÿ>(+ÿ>(+ÿ?)+ÿ@),ÿ@(+ÿ?(+ÿ?(+ÿ?(,ÿ@),ÿ@),ÿ@)-ÿA*.ÿA*-ÿA+-ÿA+.ÿA+.ÿA+/ÿB+0ÿC+/ÿB+/ÿA+/ÿ@+0ÿ@*/ÿ?*/ÿ<(-ÿ;&+ÿ;%)ÿ;&*ÿ;(*ÿ=+)ÿ†n\ÿÝ» ÿ彦ÿä¹§ÿ䶨ÿ峩ÿ毫ÿè¹µÿÛª�ÿ丯ÿ嵫ÿÕ¦œÿÇž—ÿpXWÿH14ÿN58ÿO69ÿO69ÿO69ÿO69ÿO69ÿO7:ÿO79ÿP79ÿP79ÿP79ÿP7:ÿU<>ÿ^DDÿQ8:àQ8:Q8:7#$7#$7#$àK47ÿ>)+ÿ7#$ÿ8#%ÿ8$%ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ;%'ÿ=()ÿ?++ÿ?,+ÿ?,+ÿ?,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB-,ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿB--ÿB--ÿB--ÿB.-ÿB..ÿC-.ÿC--ÿC--ÿC--ÿB--ÿC--ÿC..ÿB..ÿA+,ÿ?(*ÿ>')ÿ>'*ÿ?(*ÿ?(+ÿ?(+ÿ?(+ÿ>(+ÿ?)+ÿ@),ÿ@(+ÿ?(+ÿ?(,ÿ?(,ÿ@),ÿ@),ÿ@)-ÿ@*.ÿ@*.ÿA+-ÿA+.ÿ@+.ÿ@*.ÿ@*/ÿ@).ÿ?(-ÿ<(,ÿ;'+ÿ;%*ÿ;$)ÿ9%)ÿ8&)ÿ6$(ÿ;((ÿ~dHÿܹ€ÿïÊ–ÿîÈ�ÿîǤÿîÅ«ÿí°ÿí¾´ÿí¿»ÿíÊÄÿöÇÀÿø¿½ÿöº¼ÿÕ¤¥ÿbKKÿJ25ÿM58ÿN58ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO79ÿP79ÿP79ÿP79ÿU;>ÿ]CDÿQ7:àQ7:Q7:7#$7#$6"$àK37ÿ>)+ÿ7#%ÿ7$%ÿ8$%ÿ9$%ÿ9$&ÿ9$&ÿ9$'ÿ9%'ÿ9%'ÿ:%'ÿ=')ÿ?+*ÿ@,+ÿ@,+ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,-ÿA,-ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿC--ÿC--ÿC--ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC--ÿC--ÿD--ÿC..ÿC./ÿB--ÿ@*+ÿ?(*ÿ?'*ÿ?(+ÿ?(+ÿ?(+ÿ?)+ÿ?(+ÿ?),ÿ@),ÿ@(+ÿ?(+ÿ?),ÿ?(,ÿ?),ÿ?),ÿ?),ÿ?)-ÿ?),ÿ>),ÿ>)+ÿ<(+ÿ;'*ÿ;&*ÿ;$(ÿ;$'ÿ:$'ÿ8%(ÿ8&)ÿ6$(ÿ5"&ÿI6/ÿ–}ZÿÞ¹wÿíÃÿíÀ�ÿî¿„ÿgÿð¼‹ÿñ»�ÿò»•ÿñÁ¨ÿîÈ¿ÿ÷ŶÿøÂ¸ÿûÅ¿ÿˤŸÿU>?ÿK36ÿL57ÿM57ÿN57ÿN58ÿN68ÿN68ÿO68ÿO58ÿO69ÿO69ÿP69ÿP69ÿT:=ÿ]BCÿP69àQ79Q797"%7"%6"$àK48ÿ>),ÿ7#%ÿ8$%ÿ8$%ÿ8$%ÿ9%&ÿ9%'ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ;%'ÿ<&(ÿ>**ÿ@,,ÿ@-,ÿA-,ÿA--ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC.-ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC-.ÿC--ÿC--ÿC.-ÿC..ÿC..ÿD..ÿC..ÿC..ÿC-.ÿD-.ÿD./ÿD..ÿC..ÿB,-ÿ@*+ÿ@(*ÿ?(+ÿ>(+ÿ?)+ÿ?)+ÿ>(+ÿ?(+ÿ?(+ÿ>'*ÿ>'*ÿ='+ÿ<'+ÿ<&*ÿ;&)ÿ;&)ÿ:&)ÿ:%(ÿ:$'ÿ:$&ÿ:$&ÿ9$'ÿ8$(ÿ8%(ÿ7$'ÿ5"&ÿ4"%ÿC0,ÿw`Gÿ¤uÿîОÿîLJÿìÁ�ÿí¿„ÿÿﻊÿð¹Œÿñ·Žÿñº™ÿ浨ÿÛ¦¡ÿò¼¯ÿöµ¦ÿö¸§ÿ¥�tÿK45ÿL36ÿM47ÿL47ÿM47ÿM47ÿN47ÿN58ÿN58ÿN58ÿO58ÿO58ÿO68ÿO68ÿT:<ÿ\BBÿO58àO69O696#%6#%6#%àL58ÿ?),ÿ8#%ÿ8$&ÿ8$&ÿ8%&ÿ9%&ÿ:%&ÿ:%'ÿ:%'ÿ:%(ÿ:&(ÿ;&(ÿ;&(ÿ<&(ÿ>))ÿ@,+ÿA-,ÿA-,ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC.-ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿC..ÿC..ÿC..ÿC./ÿC..ÿC.-ÿB--ÿA+,ÿ?(*ÿ='*ÿ<&)ÿ<')ÿ;'(ÿ;&(ÿ;%(ÿ:%'ÿ:$&ÿ9$&ÿ9#&ÿ9"&ÿ9"%ÿ9"%ÿ8"%ÿ8#&ÿ8$'ÿ7%'ÿ7%'ÿ6$&ÿ4"%ÿ3!$ÿ9&&ÿQ=4ÿƒnTÿ¾£rÿçÇ�ÿñΖÿòСÿðÌ—ÿí¿ƒÿÿ)ÿð¹Œÿñ¸Žÿò¸”ÿ뻩ÿÛ¡œÿÕ˜˜ÿé¶±ÿ÷º©ÿê² ÿy]UÿH13ÿK45ÿL46ÿL46ÿL46ÿM46ÿM46ÿN47ÿN57ÿN57ÿN57ÿN57ÿN57ÿN58ÿS:;ÿ[ABÿO57àO57O577#$7#$6#$àL59ÿ?*-ÿ8#&ÿ8$&ÿ9$&ÿ9$&ÿ9%&ÿ9%&ÿ:&'ÿ;&'ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ=')ÿ@++ÿA--ÿB.-ÿB..ÿB..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD/.ÿD//ÿD./ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿD..ÿD..ÿC//ÿC..ÿC..ÿC--ÿC--ÿB--ÿA,-ÿ@,-ÿ@+,ÿ?++ÿ>**ÿ>))ÿ<&(ÿ:$&ÿ9"%ÿ9"$ÿ8"$ÿ8"$ÿ9"$ÿ8"$ÿ8"$ÿ7#%ÿ6#&ÿ6#&ÿ6$&ÿ6#%ÿ5"%ÿ3!$ÿ3!$ÿ4"$ÿ=*(ÿR>3ÿw`Fÿ§�]ÿÕ½‰ÿíÑ—ÿñÑ“ÿñΕÿð̘ÿðÊ�ÿòϦÿîÀˆÿ(ÿðº‹ÿð¸Žÿñ·‘ÿヲÿߨ¡ÿÚš™ÿÔ•–ÿÝ©¦ÿö¿±ÿÅ—‡ÿV><ÿJ23ÿK35ÿK35ÿK35ÿK36ÿL36ÿL36ÿL36ÿM46ÿM46ÿM46ÿM46ÿN46ÿN46ÿS9;ÿ[AAÿO57àO57O577#%7#$7#$àL69ÿ?*-ÿ8$&ÿ9$&ÿ9$&ÿ9%'ÿ:%'ÿ:&'ÿ:&'ÿ;&'ÿ;&'ÿ;&(ÿ<&)ÿ<')ÿ<')ÿ<')ÿ=')ÿ=')ÿ?**ÿA-,ÿB.-ÿB..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD/.ÿD/.ÿD//ÿD//ÿD//ÿD//ÿD//ÿD./ÿC..ÿC..ÿC--ÿB--ÿA--ÿA--ÿ@,,ÿ?*+ÿ>))ÿ=((ÿ=((ÿ=''ÿ<''ÿ<&&ÿ<&&ÿ<&&ÿ;&'ÿ9%'ÿ7$&ÿ6$%ÿ6$%ÿ5$%ÿ5#%ÿ5"$ÿ4!#ÿ3 "ÿ2 "ÿ3 #ÿ7$%ÿ?,*ÿO<3ÿfQ?ÿƒjMÿ®–nÿÕ¸uÿçÈzÿñÕ�ÿòÙŸÿðÐ’ÿðΔÿðÌ—ÿðÊšÿñÈ�ÿóÍ©ÿñÅ—ÿﺊÿð¸�ÿñ·�ÿñ¼ ÿã°§ÿÙ›˜ÿÖ˜—ÿÓ˜•ÿÖœœÿåµ®ÿ„f\ÿF02ÿI24ÿJ34ÿK34ÿK34ÿK34ÿL35ÿL35ÿL35ÿM45ÿM45ÿN56ÿN56ÿN56ÿN55ÿR9:ÿZ@@ÿL36àL36L367$%7$%7$%àM69ÿ@+-ÿ8$&ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:&'ÿ;&(ÿ<'(ÿ<'(ÿ<')ÿ<')ÿ<')ÿ<')ÿ=')ÿ=')ÿ=')ÿ>)*ÿ@,,ÿB..ÿB//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC./ÿC./ÿD/.ÿD/.ÿD//ÿD//ÿD//ÿD//ÿC..ÿB..ÿA--ÿ?,,ÿ>**ÿ=))ÿ=((ÿ=('ÿ=''ÿ<''ÿ;''ÿ;''ÿ:'(ÿ9'(ÿ9((ÿ8''ÿ7&&ÿ7%%ÿ6$%ÿ4#$ÿ3!#ÿ2 "ÿ3!#ÿ7%&ÿ?,+ÿH5/ÿVC7ÿiVAÿkLÿ—ƒWÿ«—_ÿ¹¦dÿİiÿÊ­jÿÖº€ÿíÑŠÿîÑ…ÿñÙ ÿïÑ“ÿðÏ”ÿðÌ–ÿðÊšÿñÈ�ÿñÇŸÿóǦÿóʨÿð¹�ÿñ·�ÿòº™ÿè·ªÿÕ™–ÿΔ�ÿÔš—ÿÓ˜—ÿÕ—šÿ¬„~ÿO8:ÿC,1ÿD.2ÿE/2ÿF03ÿG03ÿH03ÿH03ÿH14ÿI14ÿI14ÿI14ÿJ14ÿJ15ÿI14ÿH04ÿM48ÿU;?ÿH/5àH05H058$%8$%8$%àM7:ÿ@+-ÿ8%&ÿ9%'ÿ:%'ÿ:%'ÿ;%'ÿ;&(ÿ;&(ÿ;'(ÿ;'(ÿ<'(ÿ='(ÿ=')ÿ='*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=)*ÿ?++ÿA--ÿC//ÿC//ÿD//ÿD//ÿD//ÿC//ÿC//ÿC//ÿD//ÿD0/ÿC//ÿC./ÿA-.ÿ@,,ÿ>**ÿ=))ÿ=((ÿ<''ÿ;''ÿ:''ÿ9((ÿ9((ÿ9''ÿ7&&ÿ6$%ÿ5#$ÿ4#$ÿ6$%ÿ9'(ÿ?-,ÿI52ÿT?7ÿaL>ÿqZFÿ‚jMÿ”yTÿ§Š^ÿ¹ sÿ¾ªqÿ­cÿ˶gÿÏ»hÿѾjÿͺhÿÉ·hÿȹjÿÉ·kÿ˱qÿåÌ“ÿòÙžÿðÓ–ÿðÏ’ÿðÍ•ÿð˘ÿðÈœÿñÇŸÿòÅ¡ÿóäÿõɰÿò½˜ÿò¸”ÿ踧ÿË•�ÿÆ�‰ÿÍ—£ÿÏ—¨ÿÕ—›ÿÀЇÿeIEÿB+1ÿC,2ÿD,2ÿD.2ÿD.3ÿD.3ÿE-3ÿE-3ÿD-3ÿE.4ÿF.4ÿF.4ÿF.4ÿG.4ÿG/4ÿG/4ÿL37ÿT;>ÿH/4àH/4H/48$&8$%8$%àN8:ÿA,-ÿ9%&ÿ9%&ÿ:%'ÿ:&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<'(ÿ<()ÿ=()ÿ=()ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ>)+ÿ>)+ÿ?)+ÿ?)+ÿ?*+ÿA,,ÿC//ÿD00ÿE00ÿE00ÿE00ÿD00ÿD0/ÿC//ÿB..ÿA.-ÿ?,,ÿ=**ÿ=((ÿ<((ÿ;((ÿ:((ÿ9((ÿ8''ÿ6%%ÿ5$$ÿ6$&ÿ:)*ÿB1/ÿRA;ÿeRBÿzeJÿ’|Xÿ§‹cÿ·”[ÿÆ¡^ÿÑ«aÿÚ³eÿáºjÿæ¿oÿéÃtÿèÄyÿßŃÿÜÊŠÿϺeÿλeÿϼgÿϼjÿʸiÿȸjÿȹkÿɺmÿɸoÿàΟÿôÛ³ÿòÔ¤ÿòÓ¥ÿòФÿòͤÿòˤÿòȤÿóŦÿô§ÿõïÿÿÛ¬•ÿÁ’‹ÿÁŒ�ÿÁ�»ÿÆ’¼ÿ×™ ÿÉ�ŽÿyYQÿD-0ÿC,1ÿC,1ÿC,1ÿD-1ÿD.1ÿD.2ÿD.3ÿE-2ÿE-2ÿD-3ÿE.3ÿF.3ÿF.3ÿF.3ÿF.3ÿF.4ÿK38ÿS;>ÿF.4àG/4G/48$&8$&8$&àO8;ÿA,.ÿ9%&ÿ:&'ÿ:&'ÿ:&(ÿ;&(ÿ<&(ÿ<')ÿ<')ÿ<')ÿ<()ÿ<()ÿ=)*ÿ>)*ÿ>)*ÿ>)+ÿ>)+ÿ>)+ÿ?)+ÿ?*+ÿ@*+ÿ@*+ÿ@*+ÿA+,ÿC..ÿE00ÿF00ÿF00ÿE0/ÿD/.ÿB.-ÿ?,+ÿ>*)ÿ=((ÿ<((ÿ;)(ÿ9((ÿ7&&ÿ5$%ÿ7%'ÿ?--ÿN=8ÿcSCÿziJÿ�}Kÿª—]ÿηnÿÙ½ZÿßÂYÿãÇ]ÿêÌyÿæº^ÿæ»bÿç¾iÿç¿nÿçÀsÿèÂuÿçÃxÿÞÂ}ÿÚÂÿÞÊ�ÿÓÁsÿλfÿϼiÿϽkÿʹjÿȹkÿɺmÿɺnÿÒÆ‚ÿìá¨ÿóÔªÿò›ÿóáÿóĦÿôÅ«ÿõưÿöÇ´ÿóÄ´ÿ꽯ÿܰ¤ÿЬ¢ÿ¿”•ÿ¼ˆ°ÿ·ˆ×ÿÅ‘ÀÿÛ�¡ÿΔ�ÿ‚`VÿF.1ÿB*/ÿC+0ÿC+1ÿC,1ÿC,1ÿC-1ÿC-1ÿC.2ÿD-2ÿD-2ÿD-2ÿD-2ÿE.3ÿE.3ÿE.3ÿE-3ÿE-3ÿJ27ÿS:>ÿF.3àF.3F.38$&8$&8$&àO8;ÿA,.ÿ:&'ÿ:&'ÿ;&'ÿ;&(ÿ;')ÿ;')ÿ<')ÿ<')ÿ<(*ÿ=(*ÿ=)*ÿ=)*ÿ>**ÿ?**ÿ?*+ÿ?*+ÿ?*+ÿ?*,ÿ@*,ÿ@*,ÿA*,ÿA*,ÿA*,ÿA+,ÿB,.ÿD/0ÿE00ÿD./ÿA,-ÿ?**ÿ>((ÿ<((ÿ;)(ÿ9''ÿ7%%ÿ;()ÿJ97ÿdULÿ„w`ÿ¤™sÿ« Wÿ³¥Jÿ´¢=ÿ»¦?ÿØÃgÿßÃTÿÞÀQÿâÅ[ÿãÉcÿéÑ€ÿéÃyÿç¾nÿç¿qÿçÀsÿèÁuÿèÃwÿàÂ{ÿÚÂÿÚÂ�ÿÝÇ‹ÿÚɈÿϼhÿнkÿϽlÿɺkÿɺlÿɺnÿÍÀyÿçÜ ÿðäœÿóà¬ÿóÅ�ÿò¼šÿñ¹œÿí´›ÿæ«™ÿÛ¢“ÿÒ™ŽÿÌ“�ÿÉ��ÿÃ�¿ÿ¹…Ýÿº†ÞÿΖ³ÿÝŸ�ÿÌ”Žÿ�_SÿF/1ÿB*0ÿC*/ÿC*/ÿD+/ÿD+0ÿC+0ÿC+0ÿD,0ÿD-0ÿD-1ÿD,1ÿD,1ÿD,1ÿE,1ÿE-2ÿE-2ÿE-2ÿE-2ÿJ16ÿS9=ÿF.3àG.3G.39$'9$'8$&àO9<ÿA,.ÿ:%'ÿ;&'ÿ;'(ÿ;'(ÿ;'(ÿ;')ÿ<(*ÿ=(*ÿ=(*ÿ>)*ÿ>)*ÿ>)*ÿ?*+ÿ?*+ÿ@*+ÿ@*,ÿ@*,ÿ@*,ÿA*,ÿA*-ÿA*-ÿA*-ÿA+-ÿA+-ÿA+,ÿ@+,ÿ@,-ÿ?+,ÿ>))ÿ=))ÿ;))ÿ9''ÿ9&'ÿG55ÿgYQÿŒƒkÿ¨£vÿ¶³tÿ¼¶kÿƾvÿ¼±Rÿ´¤7ÿ´Ÿ6ÿʵ_ÿѹXÿ̯LÿÛ´Vÿã¾aÿåÉlÿçÐxÿëΉÿç¿pÿç¿rÿèÁtÿèÂvÿãÂzÿÛÂ~ÿÚÂ�ÿÛăÿÜÅ…ÿßΕÿÒÀrÿоlÿϾnÿɺlÿÉ»nÿ˽sÿàÖ™ÿðäžÿíß™ÿëÛ£ÿçÇ¡ÿÝ­ŽÿÔ¡ŠÿÌš‡ÿÉ”ˆÿÊ�’ÿË�§ÿʈÄÿăßÿÀ„êÿÌ™×ÿן¥ÿÜ šÿ¾Œ‚ÿrSJÿD-.ÿA*.ÿB+/ÿC+0ÿC*/ÿC*/ÿD+/ÿC+0ÿC+0ÿC,0ÿD,0ÿD,0ÿD,1ÿD,1ÿD,1ÿE,1ÿE,1ÿE-2ÿE-2ÿE-2ÿJ15ÿR8<ÿF-2àF.2F.29%'9%'9%'àP9<ÿB,/ÿ:%'ÿ;'(ÿ;'(ÿ;()ÿ<()ÿ<()ÿ=)*ÿ=)*ÿ>)*ÿ?)+ÿ?)+ÿ?)+ÿ@*+ÿ@*,ÿ@*,ÿA+,ÿA+-ÿA+-ÿA+-ÿA+-ÿA+.ÿA+.ÿB+.ÿB+-ÿ@+,ÿ>)+ÿ:'(ÿ:%'ÿ;()ÿ9((ÿ:()ÿQA@ÿ{reÿŸŸ|ÿ¯µ|ÿ³¹rÿµ·jÿ¸´eÿ¼³bÿµfÿöfÿª–3ÿ´¡PÿÄ®^ÿÀ¥JÿÖ°Tÿâ¶Zÿâ·\ÿã¼bÿæÉmÿëÔ‹ÿèÃzÿçÀtÿèÂvÿæÃyÿÜÂ~ÿÚ€ÿÛÃÿÜÅ…ÿÜÆ†ÿàÌ“ÿÙɆÿпmÿͽnÿÆ·lÿôlÿÌÀ…ÿÛÑ”ÿÔȈÿÎÀ†ÿɺ‡ÿʳ“ÿÊ ŠÿΕ”ÿÓ�¨ÿ×�¿ÿÖ‰ÔÿÒ†ãÿ͆æÿБÙÿÝ£Ãÿ긿ÿ×¥œÿ¡xkÿ[B=ÿ@*-ÿA*.ÿB*.ÿA+.ÿA+/ÿB*/ÿB*.ÿB*.ÿC+.ÿB+/ÿB+/ÿC,0ÿC,/ÿD,0ÿC,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD-1ÿE,1ÿI05ÿQ8;ÿE,1àE,1E,19%&9%&9%&àQ:=ÿB-0ÿ:&(ÿ;')ÿ;')ÿ<()ÿ=)*ÿ=)*ÿ>)*ÿ>)*ÿ>)+ÿ?)+ÿ@),ÿ@*,ÿ@*,ÿ@*,ÿ@+-ÿA+-ÿA,-ÿB,.ÿB,.ÿB,.ÿB,.ÿB,.ÿB,.ÿA+-ÿ?),ÿ;'(ÿ:%'ÿ8&'ÿ7$&ÿN==ÿˆ€oÿµ¸�ÿ¿Ê�ÿ¼Ç…ÿ»Á~ÿ¼¾yÿ¼ºrÿ»´jÿ¶ªaÿ¯žYÿµ¥gÿª˜Nÿ¿«`ÿÀ¥JÿÔ®Rÿâ¶Yÿâ·\ÿâ·^ÿâ¸_ÿã»bÿèËzÿë̉ÿéÂuÿèÃxÿÞÂ}ÿÙÁÿØÁ�ÿ×À�ÿÔ¿�ÿѼ‚ÿκƒÿʼ‰ÿ¹«fÿ²¤aÿªž^ÿ¯¤lÿ¸†ÿÇ·�ÿ˱‰ÿÔ¬”ÿÞ¤¤ÿç�¹ÿë“ÆÿëŽÒÿç‹Úÿá‰ßÿÝŠÞÿÝ“Ôÿà¤Âÿç°·ÿ⫯ÿ¾‘�ÿy]VÿH21ÿ?*-ÿA*.ÿA*.ÿB*.ÿB*.ÿA+.ÿB+.ÿB*.ÿB*.ÿB*.ÿB+.ÿB+.ÿB,/ÿB,/ÿC,/ÿC,/ÿC,/ÿB,0ÿC,0ÿD,0ÿD,0ÿD,0ÿI05ÿQ8;ÿE,0àE-1E-1:&':&':%'àQ:>ÿC.0ÿ;&(ÿ;')ÿ<(*ÿ=(*ÿ>)*ÿ>)*ÿ>)*ÿ?)+ÿ?*+ÿ@*,ÿ@*-ÿ@*-ÿA+-ÿA+-ÿA+.ÿA,.ÿB,.ÿC,.ÿC-.ÿC-/ÿC-/ÿC-/ÿB,.ÿ@*-ÿ=')ÿ;%'ÿ8&'ÿ>,-ÿre]ÿ¯¶�ÿÁÔ�ÿºÊgÿ¸ÅZÿ¾Ä]ÿÀÁ^ÿ¾»_ÿ»´`ÿº°cÿº¬eÿºªeÿ±uÿÐÁ‹ÿɳeÿÖ¶cÿä»fÿä»dÿãºbÿãºbÿãºbÿâ¹bÿàºeÿãÃÿÜ·rÿϳrÿírÿ¿©rÿ»§qÿ¹¥pÿ·¤qÿ·£rÿ¸¤tÿ¼©€ÿ¹¤rÿ»žnÿÞzÿש˜ÿ窤ÿÿö�»ÿû—Åÿÿ“Íÿý�Ñÿ÷�Ôÿð�Öÿë’ÔÿëœÊÿð¨¼ÿí²³ÿà­ªÿ½’Žÿƒc]ÿP87ÿ?)-ÿ@).ÿA*.ÿ@*.ÿ@*-ÿA*.ÿB*.ÿA*.ÿA+.ÿA*.ÿB*.ÿB*.ÿB*.ÿB+.ÿB+/ÿB,/ÿB,/ÿC,/ÿC+/ÿC,0ÿC,0ÿD,0ÿD,0ÿD,0ÿH04ÿQ8;ÿD-0àE-0E-0:&'9&':&'àR;>ÿC.1ÿ;')ÿ<(*ÿ=(*ÿ=(*ÿ>)*ÿ?)+ÿ?*+ÿ@*+ÿ@*,ÿ@+,ÿ@+-ÿA+.ÿB+.ÿB,.ÿB,.ÿB,/ÿC-/ÿC-/ÿD-/ÿD-/ÿD./ÿC-/ÿA,-ÿ=(*ÿ<&'ÿ9&'ÿJ78ÿ�ŠpÿÁÑšÿ¶Ò�ÿ¶Îzÿ¾Êsÿ¯¶Lÿ«­Fÿ¨¥?ÿ§ :ÿªž7ÿ­�5ÿ±�3ÿ¶Ÿ5ÿÀ«[ÿıkÿ×µVÿä¼^ÿå¿fÿäÀlÿà¾qÿÚºqÿÒ²mÿÊ«iÿĦfÿçrÿ¾žoÿ¶�hÿ¸£kÿ¾¦oÿĪsÿË­yÿÒ¯ÿÚ±†ÿá±�ÿè±–ÿî®�ÿò«£ÿö¨«ÿù¥²ÿú¡·ÿûž¼ÿüšÁÿý—Æÿþ•Êÿý™Ëÿø§Ëÿõ°Àÿõº´ÿóº«ÿÜ©œÿ­‡~ÿw[UÿN77ÿ@),ÿ?(,ÿ@),ÿ@)-ÿ@).ÿ@).ÿ@)-ÿ@*-ÿA*.ÿA*.ÿA*.ÿA+.ÿA*.ÿB*.ÿB*.ÿA*.ÿA+.ÿB,.ÿB,/ÿB,/ÿB+/ÿC+/ÿB,/ÿB,0ÿC,0ÿC,0ÿH04ÿP7:ÿD,0àE-1E-1:'(:'(:&(àR(+ÿ>)+ÿ?),ÿ@*,ÿ@+,ÿ@+-ÿA+-ÿA,.ÿA,.ÿB,/ÿC,/ÿC-/ÿD-/ÿD-/ÿD./ÿD./ÿD./ÿD./ÿB-/ÿ?*,ÿ='(ÿ9&(ÿQ@?ÿœžzÿ¾ÕŽÿµÐ…ÿ§Àlÿ¥·fÿ²ºuÿ¥¥Iÿ£ ?ÿ¦ <ÿªŸ9ÿ­ž6ÿ°�3ÿ³œ0ÿ½§Kÿ®–Cÿ¸˜GÿÛ´WÿÓ¨AÿÉ¡@ÿÁš@ÿ¼—Aÿ»—Eÿ¾œKÿĤTÿ˯^ÿÔ½mÿÚÅyÿÝÃsÿãÅvÿèÅ{ÿëÄ�ÿîÁ‡ÿð¾Œÿñ»‘ÿò·–ÿó´›ÿô° ÿõ­¥ÿö©ªÿø¥¯ÿù£´ÿù¤·ÿù©¹ÿù³¸ÿøÀµÿö˯ÿñЯÿụÿ¾”ƒÿ�mcÿaGCÿF//ÿ>()ÿ>(,ÿ?)-ÿ@)-ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@),ÿ@)-ÿA)-ÿA).ÿA).ÿA*.ÿA*-ÿB*.ÿB*.ÿA*.ÿA*.ÿB,.ÿB,/ÿB+/ÿB+/ÿB+/ÿB+/ÿC+0ÿC+0ÿH/3ÿP6:ÿD+/àD,0D,0:'(:'(:'(àS=?ÿD01ÿ<()ÿ>(*ÿ>)+ÿ?)+ÿ?),ÿ?*,ÿ@*-ÿA+-ÿA,-ÿB,.ÿB,.ÿB-/ÿC-/ÿC-/ÿD-/ÿD./ÿD./ÿD.0ÿD.0ÿD.0ÿD./ÿB,.ÿ>(*ÿ;%(ÿN=>ÿœŸ|ÿ³Í€ÿ®Åƒÿš¯gÿ™ª`ÿ›§[ÿª°jÿ¯­Zÿ¦ ;ÿ©Ÿ:ÿ¬ž7ÿ¯�4ÿ²œ0ÿ»£Aÿ´�Oÿ¥ƒ-ÿ©‚5ÿ¸™Uÿº•?ÿ¼—BÿÄŸJÿΪSÿص[ÿßÀbÿäÈfÿæÏhÿçÓhÿèÔkÿêÑqÿêÍvÿëÉ{ÿíÆ€ÿîÂ…ÿᅧÿð»�ÿñ¸”ÿò¶˜ÿóµžÿó¶¢ÿõ¼¤ÿ÷ưÿ÷ϳÿõÕ°ÿïÔ¨ÿâÈœÿ˲�ÿ«‘xÿ†m_ÿdMHÿM65ÿC-.ÿA+-ÿA*,ÿ@)*ÿ?(*ÿ?),ÿ?)-ÿ?),ÿ?),ÿ@),ÿ@)-ÿ@)-ÿ@(,ÿ@),ÿA),ÿA)-ÿA)-ÿA)-ÿA)-ÿA),ÿB)-ÿA)-ÿA)-ÿA*-ÿB+.ÿB+.ÿB*/ÿB*.ÿB*.ÿC+.ÿC+/ÿH/3ÿP69ÿD+/àD+/D+/;();();()àS>@ÿE01ÿ=()ÿ>)*ÿ?)+ÿ?*,ÿ?*-ÿ@+-ÿ@+.ÿA+.ÿB,.ÿC-/ÿC-/ÿC-/ÿC./ÿC.0ÿD.0ÿE.0ÿE.0ÿE.1ÿE.1ÿE.1ÿD.0ÿ@+-ÿ>&(ÿE24ÿŽŠsÿ£¹sÿ©½ÿ˜¬iÿ—¨`ÿ›¨]ÿž§Yÿ¤©\ÿ¶´jÿª =ÿ¬ž7ÿ¯�5ÿ²œ1ÿ´›5ÿ®™Oÿ˜z/ÿ¡z/ÿ§~7ÿÁ™Vÿ׫]ÿà³aÿå»gÿçÁhÿèÅiÿçÈiÿçËiÿçÏiÿçÒiÿçÔjÿèÑnÿéÍrÿêÉvÿëÆxÿìÅ|ÿîÈ‚ÿïÊ…ÿï̆ÿïÑ�ÿåΛÿßÍ™ÿàÌŒÿн†ÿ¼¨€ÿ¡Žvÿ…qdÿhRKÿR=:ÿF11ÿB-.ÿB-.ÿC..ÿD./ÿD.0ÿD.0ÿD-.ÿB+,ÿ@)+ÿ@(,ÿ?(,ÿ?(+ÿ?)+ÿ?),ÿ?)-ÿ?)-ÿ?(,ÿ@),ÿA),ÿA)-ÿA)-ÿA(-ÿA),ÿA),ÿA)-ÿA)-ÿA)-ÿA*-ÿB+-ÿB+.ÿB*.ÿB*.ÿB*.ÿC*.ÿG/2ÿO69ÿC+/àC+/C+/<()<()<()àT>@ÿF02ÿ>)*ÿ>*+ÿ?*,ÿ@*,ÿ@+-ÿA+.ÿA,.ÿB,/ÿB,/ÿC-/ÿC./ÿC./ÿD./ÿD.0ÿD.1ÿE.1ÿF.1ÿF.1ÿF.2ÿF.1ÿC-0ÿ@*,ÿ>(*ÿwlcÿ¡²tÿ¦»zÿ�±pÿ–©`ÿš©^ÿž§Zÿ ¦Wÿ£¥Sÿ´±hÿ²§Jÿ®�4ÿ¯›2ÿ¨‘.ÿ¡�Eÿš|8ÿµ†?ÿϘTÿß§bÿæ°gÿèµiÿç¸hÿç»hÿç¿hÿçÂgÿçÆhÿçÊkÿçËiÿèÍlÿéÍpÿìЀÿèÆqÿäÀmÿß»oÿØ·qÿÏ·xÿïwÿ³ pÿ¢�nÿ‰vbÿvbTÿgQHÿV@<ÿK43ÿE./ÿB,-ÿB,.ÿC-.ÿC-.ÿC./ÿC./ÿC//ÿC..ÿC..ÿC./ÿE/0ÿE//ÿD..ÿB+-ÿA),ÿ@'+ÿ?(+ÿ?(+ÿ?)+ÿ?),ÿ>(,ÿ?(,ÿ@),ÿ@),ÿ?),ÿ@)-ÿ@(,ÿ@(,ÿ@),ÿ@)-ÿ@)-ÿ@*-ÿA*-ÿA+-ÿA*.ÿA*.ÿA*.ÿB*-ÿF.1ÿN58ÿB*.àB+.B+.<()<()<()àU>AÿG13ÿ>)+ÿ?*,ÿ?+,ÿ@+-ÿA,-ÿB,.ÿB,/ÿC-/ÿC-/ÿC-/ÿD.0ÿE.0ÿE.0ÿE.1ÿE/1ÿF/2ÿF/2ÿG/2ÿG/3ÿF/2ÿC-0ÿ>'*ÿVCEÿ°¶Žÿ¬Á|ÿ¢µxÿ•©aÿ™©^ÿ�¨[ÿ §Xÿ£¦Uÿ¦¥Qÿ®©Xÿ¼°^ÿ«˜1ÿ�ˆ*ÿ¢ŠAÿ¶�SÿÔ–Wÿæ¤eÿé©hÿè¬hÿç¯hÿç³hÿç·gÿè»fÿèÀhÿéÃkÿê˃ÿ寇ÿÚ¹~ÿÍ­}ÿ½Ÿxÿ«‘wÿ–|eÿ‚iVÿqZNÿcMFÿXC?ÿP:8ÿJ44ÿE00ÿC-.ÿC,-ÿB-.ÿC--ÿC..ÿD..ÿD-.ÿD..ÿD./ÿD./ÿC-.ÿC-/ÿC./ÿC./ÿC..ÿC..ÿC./ÿD./ÿD//ÿD//ÿD./ÿC,.ÿA)-ÿ?(+ÿ?(+ÿ@(+ÿ?(+ÿ?'+ÿ?'+ÿ@(+ÿ@(+ÿ?),ÿ@(,ÿ@(+ÿ@(+ÿ@)+ÿ@),ÿ@),ÿ@*,ÿ@*,ÿA*,ÿA)-ÿ@)-ÿA)-ÿF-1ÿN47ÿB*-àB*.B*.=(*<(*=(*àV>BÿG14ÿ>*,ÿ?+-ÿ@+-ÿA,.ÿB,.ÿC-.ÿC-/ÿC-/ÿC-0ÿD-0ÿD-0ÿE.1ÿF/1ÿF/1ÿG/2ÿG02ÿG03ÿG03ÿG03ÿF/3ÿB,/ÿ@(+ÿƒyrÿÊØ§ÿÃÖšÿŸ³mÿ˜©^ÿœ¨[ÿž¦Wÿ¢¥Tÿ¥¥Qÿ©¤Nÿ¬£Lÿ´¨_ÿœ‰5ÿª„8ÿÕ–`ÿçœgÿé hÿè£gÿè§fÿåªfÿà­fÿݳqÿãÀ�ÿضyÿŨxÿ®“rÿ–pÿ|e\ÿiRMÿYCAÿO99ÿI33ÿE00ÿC./ÿC./ÿC./ÿC//ÿD//ÿD/.ÿE//ÿD//ÿD./ÿD./ÿD./ÿD..ÿC..ÿD..ÿD-.ÿC..ÿD..ÿD-.ÿC-.ÿC-.ÿC-/ÿC..ÿC..ÿB..ÿC./ÿD..ÿD/.ÿC//ÿD/0ÿD./ÿC,/ÿA*-ÿ@),ÿ@(+ÿ?'+ÿ?'+ÿ@'+ÿ@(+ÿ@(+ÿ@(+ÿ@'+ÿ@'+ÿ@'+ÿ@(+ÿ@(,ÿ@),ÿ@),ÿ@),ÿA),ÿA),ÿA)-ÿF-1ÿN47ÿB*-àC*-C*-=(*=(*=(*àV?CÿG14ÿ?*,ÿ@+-ÿA,.ÿB,.ÿB-/ÿC-/ÿC-/ÿD-0ÿD-1ÿE.1ÿE.1ÿF.2ÿF/2ÿG02ÿG03ÿG03ÿG13ÿH14ÿH14ÿF03ÿB+.ÿN7:ÿ£¤ŒÿËØ¯ÿÐØ©ÿÆÍ–ÿµ»�ÿ¯²tÿ¯±mÿ¯®eÿ¯«]ÿ°¨Uÿ©�JÿŸ�Jÿ¿�Vÿá’aÿé˜gÿè›gÿèŸfÿå§jÿÛ«pÿʦvÿ²•uÿ–}lÿ}f_ÿdMKÿT>>ÿL67ÿH23ÿF12ÿF01ÿG11ÿG01ÿG00ÿG00ÿF00ÿE00ÿE00ÿD00ÿD00ÿD//ÿE//ÿE//ÿD./ÿD//ÿD//ÿD..ÿD..ÿC..ÿD..ÿC--ÿC..ÿC..ÿD--ÿD-.ÿC-.ÿC-/ÿC-.ÿC-.ÿB..ÿC./ÿD..ÿC/.ÿC//ÿC//ÿC./ÿC./ÿC-/ÿA,.ÿ@*,ÿ?(+ÿ?(,ÿ@(,ÿ@(,ÿ@),ÿ@(,ÿ@(,ÿA(,ÿ@(,ÿ@),ÿ@),ÿA*,ÿA*,ÿA),ÿA),ÿA*,ÿF.0ÿN57ÿB*,àB*-B*->)*>)*>)*àW@CÿH25ÿ@*-ÿA+.ÿB,.ÿB-/ÿC-/ÿC-/ÿC-0ÿE.0ÿE.1ÿF/2ÿF/2ÿG/3ÿG/3ÿG03ÿH13ÿH14ÿH14ÿH24ÿH24ÿF03ÿA*-ÿhTTÿÁɧÿÈÙ¡ÿÍΛÿȇÿǽ‚ÿ¶©oÿ³¤hÿ¸§kÿ¼©lÿ½©kÿ«–_ÿÅ�^ÿæ�gÿé’gÿé—gÿæ£qÿÕ¨|ÿ´–zÿŠrgÿgPOÿQ:=ÿG/3ÿD,/ÿD-/ÿE-0ÿF/0ÿH12ÿI33ÿI33ÿH22ÿH22ÿG11ÿG01ÿG00ÿF00ÿE00ÿE0/ÿD00ÿD00ÿD//ÿD//ÿD//ÿD./ÿD./ÿD//ÿD..ÿC..ÿC..ÿD--ÿC--ÿC-.ÿC-.ÿC--ÿD--ÿC-.ÿC,.ÿC-.ÿC-.ÿC./ÿC-.ÿC..ÿC./ÿC//ÿC..ÿC..ÿC./ÿC./ÿB./ÿA,-ÿ@*,ÿ?(+ÿ?(+ÿ?(+ÿ?)+ÿ?(+ÿ@(+ÿ@(+ÿ?(+ÿ?)+ÿ@*,ÿ@*,ÿ@),ÿ@),ÿ@),ÿE.0ÿM47ÿA*-àA*-A*->*+>*+>)+àXADÿH36ÿ@+.ÿB,/ÿC,/ÿC-/ÿC-/ÿD.0ÿD.0ÿE.1ÿF/1ÿG/2ÿG03ÿG03ÿG04ÿG04ÿH14ÿI25ÿI25ÿJ25ÿI25ÿG13ÿA+-ÿˆytÿËÙ¦ÿÂÔ�ÿÐÔžÿËÁ†ÿÌ¿ÿɸvÿµ¡]ÿ¯—Rÿ³—Pÿ²’LÿÀƒSÿçŠfÿé�fÿé™pÿÖ¤‚ÿ¥‰xÿpZWÿR;=ÿG03ÿF.2ÿG/2ÿG/2ÿG/1ÿF.1ÿE.0ÿE.0ÿE.0ÿF/0ÿG12ÿH23ÿH22ÿH22ÿG11ÿG00ÿF00ÿF00ÿE00ÿE//ÿD00ÿD00ÿD//ÿD//ÿD//ÿD..ÿD./ÿD./ÿD./ÿC..ÿC..ÿC--ÿC--ÿC-.ÿB--ÿC--ÿC--ÿC,-ÿD,-ÿD--ÿC-.ÿC-.ÿC-.ÿC-.ÿC./ÿC./ÿB-.ÿC..ÿC./ÿC./ÿB./ÿC..ÿC--ÿA+-ÿ?),ÿ?(+ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ?(+ÿ?*,ÿ?*,ÿ@*,ÿ@),ÿ?),ÿD-0ÿM46ÿA)-àA*-A*-?*,?*,?*,àYBEÿI36ÿA+.ÿB,/ÿB-/ÿC-0ÿD.0ÿD.1ÿE/1ÿF/2ÿF02ÿG02ÿG03ÿH14ÿH15ÿH15ÿI15ÿI25ÿJ35ÿK35ÿJ25ÿH13ÿE.1ÿž”†ÿÇØ—ÿÃÒ‰ÿÎÕ–ÿÑÈ�ÿξ|ÿÒ¾zÿÏ·qÿ»ŸYÿµ—Nÿ¿“Oÿâ‡bÿé‰fÿç›{ÿº—‡ÿpZXÿM69ÿG03ÿH13ÿI13ÿH13ÿH03ÿH03ÿG/2ÿG/1ÿF.1ÿE.0ÿE.0ÿE.0ÿE./ÿE/0ÿG12ÿH22ÿH12ÿG11ÿG00ÿF00ÿE00ÿE/0ÿD//ÿD00ÿD//ÿD//ÿD//ÿD..ÿD..ÿD..ÿD-.ÿD./ÿC./ÿC..ÿC--ÿC--ÿC--ÿB--ÿC--ÿB--ÿC,,ÿC,-ÿC--ÿC-.ÿD--ÿC-.ÿC-/ÿD-/ÿC-.ÿB-.ÿC-.ÿC-/ÿB-/ÿB-.ÿC-.ÿD-.ÿC-.ÿA+-ÿ@),ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ?(,ÿ?),ÿ?),ÿ@(,ÿ@(,ÿD,0ÿL26ÿA),àA),A),?+,?+,?+,àYBEÿJ47ÿA,.ÿB-/ÿB.0ÿD.0ÿE.1ÿE.1ÿF/2ÿF02ÿF03ÿG13ÿH14ÿI14ÿI25ÿI25ÿJ25ÿJ25ÿK26ÿK36ÿK36ÿI14ÿI26ÿª£�ÿÈÖ‘ÿÆÑ‡ÿËÒ‰ÿ×ЗÿÑ¿|ÿÔ½wÿؼuÿÔµkÿÀžSÿÀ’Lÿã†bÿæ–zÿ¦†}ÿWBDÿH13ÿJ24ÿJ24ÿJ24ÿI24ÿI14ÿH14ÿH03ÿH03ÿH/2ÿG/2ÿF.1ÿE.0ÿE.0ÿE.0ÿE./ÿD-/ÿD.0ÿF01ÿG11ÿG11ÿF00ÿF00ÿE00ÿE//ÿD//ÿD0/ÿD//ÿE//ÿD//ÿD..ÿD..ÿC..ÿD--ÿC..ÿC./ÿC..ÿB--ÿC--ÿB,-ÿB--ÿB--ÿB,-ÿC,,ÿC,-ÿB--ÿC--ÿC--ÿC--ÿC-.ÿD-.ÿC--ÿC-.ÿC-.ÿC-.ÿC,.ÿC-.ÿD-.ÿD-.ÿC-/ÿC,/ÿC+-ÿA),ÿ@(+ÿ?'+ÿ?'+ÿ?(,ÿ?),ÿ@(,ÿ@(+ÿD+/ÿL26ÿ@(+à@)+@)+?+-?+-?+-àZCFÿK57ÿA-.ÿB./ÿC.0ÿD.1ÿE.2ÿF/2ÿF/3ÿG03ÿG14ÿH14ÿH24ÿI24ÿJ25ÿJ26ÿK26ÿK26ÿK27ÿK37ÿL37ÿJ25ÿL6:ÿ¯ª“ÿÉÕŽÿÉÐ…ÿÌЂÿ×Ô“ÿ×ÃÿÖ¼tÿÚ»rÿݺoÿÚ´fÿÚPÿÜŽhÿµ‹‚ÿS=AÿI14ÿK36ÿK35ÿK25ÿJ24ÿJ24ÿI24ÿI14ÿI14ÿH03ÿH03ÿH/2ÿG/2ÿF.1ÿE.0ÿE.0ÿE.0ÿE./ÿD-/ÿC-/ÿD-/ÿF/0ÿF00ÿF10ÿF00ÿE00ÿE//ÿD//ÿD//ÿD//ÿD//ÿD..ÿD..ÿC..ÿC--ÿC--ÿC-.ÿC-.ÿB-.ÿB-.ÿB--ÿB--ÿB--ÿB--ÿC,,ÿC,,ÿB,-ÿB-.ÿC--ÿB--ÿB--ÿC--ÿC,-ÿB--ÿB--ÿC--ÿC,-ÿC,-ÿC--ÿD--ÿD--ÿD-.ÿD,.ÿD,-ÿD,-ÿB+,ÿ@)+ÿ@(+ÿ@(+ÿ@(+ÿ?(*ÿD+.ÿK25ÿ?(+à@(+@(+@,.@,.@,-à[DGÿK57ÿB-.ÿC./ÿD.0ÿE.1ÿE/2ÿF/3ÿG03ÿG04ÿH14ÿI24ÿI25ÿJ25ÿK25ÿK26ÿK37ÿK37ÿL38ÿL38ÿL48ÿK37ÿM6:ÿ®§’ÿÌÔŒÿËЃÿÎÐÿÕÑ…ÿÝË�ÿÙ»rÿܺoÿàºlÿà¹jÿÒ¯dÿÒ¢|ÿs[\ÿD-1ÿK26ÿL37ÿL36ÿK36ÿK25ÿK25ÿJ24ÿI24ÿI14ÿI14ÿH03ÿH03ÿH/2ÿG/1ÿF.1ÿE.0ÿE.0ÿE-0ÿD-/ÿD-/ÿC,.ÿC,.ÿC,.ÿD./ÿE00ÿE00ÿE/0ÿD//ÿD//ÿD//ÿD//ÿD//ÿD..ÿD..ÿC..ÿC--ÿC--ÿC--ÿC--ÿB--ÿB-.ÿB,-ÿB--ÿB-.ÿB--ÿC,,ÿB,,ÿB,-ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿB,-ÿB,-ÿC,-ÿC--ÿC--ÿC,-ÿC,-ÿD,-ÿC--ÿC--ÿB,-ÿA+-ÿ@),ÿ@'*ÿD+-ÿK24ÿ@(+à@(+@(+A+.A+.@+.à[EGÿK68ÿC-/ÿD.0ÿE.1ÿF/1ÿF/2ÿF03ÿG04ÿH14ÿI14ÿJ25ÿJ25ÿK26ÿK36ÿK37ÿL37ÿL48ÿM48ÿM49ÿM49ÿL48ÿL49ÿ¦œŒÿÐÕ�ÿÎЀÿÑÏ}ÿÔÎ{ÿßÑ�ÿݽvÿߺlÿá¹jÿÚ¶jÿ×·lÿʯ‰ÿZCEÿD-0ÿJ25ÿL37ÿL37ÿL36ÿK36ÿK35ÿK25ÿJ24ÿI24ÿI14ÿI13ÿH03ÿH03ÿG/2ÿG/1ÿF.1ÿE.0ÿE.0ÿD-/ÿD-/ÿC-.ÿC,.ÿB+.ÿB+-ÿB,-ÿC..ÿD/0ÿE//ÿD//ÿD//ÿD/.ÿD//ÿD./ÿD..ÿC..ÿC--ÿC--ÿB--ÿC--ÿB--ÿB--ÿB,-ÿB,,ÿB,-ÿA-.ÿB,-ÿC--ÿB--ÿB--ÿB,-ÿB--ÿB--ÿB,-ÿA,,ÿA,-ÿB--ÿB--ÿA,,ÿB,-ÿC,-ÿC,-ÿC--ÿC--ÿC,-ÿC,-ÿC,-ÿC--ÿC..ÿC./ÿC-/ÿC+-ÿE-/ÿK24ÿ?(*à@(+@(+A,.A,.A,.à\EHÿK68ÿC-0ÿE.1ÿF/1ÿF/2ÿF03ÿG13ÿH14ÿH25ÿJ25ÿJ26ÿK36ÿK37ÿK47ÿL47ÿL48ÿM48ÿN59ÿN5:ÿN5:ÿN5:ÿK27ÿ“…|ÿÒÓ�ÿÐÏ|ÿÓÎzÿÖÌwÿÞЂÿãÆ‚ÿá¹jÿÜ·jÿÖ¶lÿ׸nÿ˳ŒÿZEGÿB+-ÿH14ÿK36ÿL48ÿL37ÿL37ÿK36ÿK35ÿK25ÿJ24ÿI24ÿI14ÿI13ÿH03ÿH03ÿG/2ÿF.1ÿF.0ÿE.0ÿE-0ÿD-/ÿD-/ÿC,.ÿC,.ÿB+-ÿA*,ÿ@+,ÿA+-ÿB-.ÿD./ÿD//ÿD..ÿD/.ÿC//ÿC..ÿD..ÿC..ÿC--ÿB--ÿB--ÿB,,ÿB--ÿB--ÿB,,ÿB,,ÿB,,ÿB,-ÿB,,ÿB,-ÿB--ÿB--ÿA-.ÿA--ÿA,,ÿ?++ÿ?++ÿ@+,ÿ@,,ÿ@,,ÿA,,ÿC,,ÿC,-ÿB,-ÿB--ÿC,,ÿC,,ÿC,-ÿC,-ÿC--ÿC..ÿC./ÿD./ÿI02ÿN67ÿA+,àA+,A+,B,.B,.A,.à\EIÿL69ÿC.0ÿE/1ÿF/2ÿF03ÿG13ÿH14ÿH24ÿI25ÿJ36ÿK26ÿK37ÿL47ÿL48ÿM58ÿM59ÿN59ÿO59ÿO6:ÿO6:ÿO6:ÿL37ÿzgfÿÓÑ—ÿÖÒ„ÿÙуÿÛÎ|ÿÞÎyÿæÎŠÿß¹mÿÖµkÿÖ¶mÿ×·nÿÕ»Šÿm[Zÿ@),ÿD.1ÿI25ÿL37ÿL48ÿL37ÿL37ÿL36ÿK35ÿK25ÿJ24ÿI24ÿI14ÿI13ÿH03ÿG02ÿG/2ÿF.1ÿE.0ÿE.0ÿD-0ÿD-/ÿC,.ÿC,.ÿC+-ÿB+-ÿA*,ÿ@*,ÿ?*,ÿ@*,ÿB,-ÿC..ÿD..ÿD..ÿC..ÿC..ÿC..ÿC--ÿB--ÿB--ÿB,,ÿB,,ÿB--ÿA,,ÿA,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,-ÿB,,ÿ@+,ÿ?+,ÿ=**ÿ<((ÿ;'(ÿ<()ÿ>*+ÿ?+,ÿ@,,ÿB--ÿC,-ÿB,.ÿB-.ÿB--ÿC,-ÿC,-ÿB,.ÿB-.ÿC./ÿC./ÿC./ÿH12ÿP69ÿD-/àD./D./B-/B-/B-.à]FIÿM6:ÿD.1ÿE/2ÿF03ÿG13ÿH14ÿI24ÿI24ÿJ35ÿK26ÿK37ÿL38ÿM48ÿM59ÿN59ÿN6:ÿO6:ÿO6:ÿO6:ÿP7;ÿP7;ÿN5:ÿ_INÿǾ‘ÿÖÎlÿÝÑzÿáÒÿäÒ€ÿìÙšÿäÌ‹ÿÞÄ~ÿÝÂÿÜÀ~ÿÞÅ‹ÿœŠ€ÿB.1ÿC+.ÿE.1ÿI25ÿK36ÿL48ÿL37ÿL37ÿL36ÿK35ÿK25ÿJ24ÿI24ÿI13ÿH13ÿH03ÿG/2ÿG/1ÿF.1ÿE.0ÿE.0ÿD-/ÿC,/ÿC,.ÿC,-ÿB+-ÿA*-ÿ@*,ÿ?*,ÿ?),ÿ?)+ÿ@*+ÿA+,ÿC--ÿC..ÿC..ÿC..ÿC-.ÿC--ÿB--ÿB,-ÿA,,ÿB,,ÿB,,ÿA,,ÿA,,ÿA,,ÿB,+ÿA,+ÿ@++ÿ?++ÿ=))ÿ;''ÿ:%&ÿ;&&ÿ:''ÿ;''ÿ<''ÿ=)*ÿ@+,ÿA,,ÿB,-ÿC,-ÿB,-ÿB,-ÿB,-ÿC,-ÿC,-ÿB,-ÿC-.ÿC-.ÿC..ÿH01ÿO67ÿD-.àD-.D-.B-/A-/B-.à^FIÿN7:ÿE.1ÿF/3ÿF03ÿG14ÿH24ÿI24ÿJ35ÿK26ÿK36ÿK37ÿL48ÿM49ÿN5:ÿO6:ÿO6:ÿO7;ÿO7;ÿP7;ÿP7;ÿQ8;ÿQ7<ÿP8=ÿ¢“ÿÕÉ^ÿÕÃMÿÜÇZÿâËgÿéÔ…ÿèÐ{ÿâÅ[ÿãÇcÿäÉkÿæÍtÿÕÀŽÿdQQÿ?*-ÿC,.ÿE.1ÿH14ÿK36ÿL37ÿL37ÿL37ÿK36ÿK35ÿJ25ÿJ14ÿI14ÿI13ÿH03ÿG02ÿG/2ÿF.1ÿF.0ÿE.0ÿE-0ÿD-/ÿC,.ÿB,-ÿC+-ÿB+-ÿA*,ÿ@*,ÿ?*,ÿ?)+ÿ?)+ÿ?(+ÿ?)*ÿA*+ÿB,,ÿC.-ÿB..ÿC--ÿB--ÿB--ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿ@++ÿ@+*ÿ?*)ÿ<))ÿ;''ÿ:%%ÿ9$$ÿ8&&ÿ7&&ÿ7%%ÿ9''ÿ<''ÿ=((ÿ?*+ÿA+,ÿB,,ÿB,,ÿB,,ÿB,-ÿB+,ÿC,,ÿC,,ÿB,,ÿB--ÿB-.ÿC-.ÿH01ÿO67ÿC-.àC-.D-.B-/B./B-/à^GJÿN7:ÿE.1ÿF/3ÿG04ÿG14ÿH24ÿJ35ÿK26ÿK36ÿK37ÿL48ÿM49ÿM5:ÿO5:ÿO6;ÿO7;ÿP7;ÿP8;ÿP8;ÿQ8<ÿR8<ÿR8<ÿP5;ÿs]_ÿÒÃ~ÿÖÁCÿÝÅSÿèÑ}ÿåÊjÿèÐzÿãÅ\ÿáÂQÿâÃTÿãÄUÿåÊeÿ·£€ÿP(*ÿ?)*ÿA,,ÿB--ÿB--ÿB--ÿB,,ÿA,,ÿ@,,ÿ?*+ÿ?**ÿ=**ÿ;((ÿ;&%ÿ:%$ÿ9$%ÿ8%&ÿ6%%ÿ5#"ÿC00ÿdNUÿK89ÿ:&%ÿ;''ÿ>**ÿ@+,ÿB+,ÿB,,ÿA,,ÿB,,ÿB+,ÿB+,ÿB,,ÿB,,ÿB,-ÿB-.ÿB-.ÿG01ÿO66ÿC--àC--C--B-/B-/B-/à^GKÿN8;ÿE/2ÿF03ÿG14ÿH14ÿI25ÿJ36ÿK37ÿK47ÿL48ÿM58ÿN59ÿN6:ÿO6;ÿO6;ÿP7;ÿQ7<ÿQ8<ÿQ8<ÿR8=ÿR8=ÿS8=ÿS8=ÿU;Bÿ¨—ƒÿÞÈ[ÿâÊ`ÿäÉiÿäÇdÿçÍsÿçÍrÿâÃTÿãÅWÿãÅYÿãÇZÿåÌqÿ«˜~ÿN;=ÿ>*-ÿB,/ÿC,.ÿE-0ÿF/2ÿH14ÿI15ÿJ25ÿJ25ÿJ25ÿJ24ÿI14ÿI14ÿH13ÿG02ÿF/2ÿF.1ÿE.0ÿE.0ÿE-0ÿD-/ÿC,.ÿB+-ÿB+-ÿB+,ÿA*,ÿ@*,ÿ?*,ÿ?)+ÿ?)+ÿ?(*ÿ?(*ÿ>(*ÿ>')ÿ>')ÿ>)*ÿ?*+ÿ@,,ÿA,,ÿ?++ÿ>**ÿ<((ÿ:&'ÿ:%%ÿ9$$ÿ9%$ÿ8&%ÿ6%%ÿ4""ÿ<*)ÿfOXÿ£�¬ÿÁ™âÿ§‡¸ÿnWbÿF32ÿ?++ÿ@++ÿA+,ÿB+,ÿA,,ÿA,,ÿB++ÿB+,ÿB+,ÿA,,ÿB,,ÿB--ÿB-.ÿF01ÿN56ÿC--àC--C--C.0C-0C-0à_HKÿO8;ÿE/2ÿG03ÿH14ÿI25ÿJ26ÿK36ÿK37ÿL48ÿM59ÿN59ÿO6:ÿO6;ÿO7;ÿP7<ÿQ7<ÿR7=ÿR8=ÿS8=ÿS9>ÿS9>ÿS9>ÿS9>ÿR7=ÿkTXÿÑ¿“ÿäÊdÿßÀKÿãÇbÿåÊlÿéÒ€ÿãÆ\ÿãÅXÿãÇZÿãÈ]ÿäÉ^ÿæÍuÿ´£ˆÿZGIÿ=),ÿ@,.ÿB,.ÿC+.ÿD,/ÿE.1ÿF/3ÿH04ÿH14ÿH14ÿI14ÿH04ÿH03ÿH02ÿG02ÿF/1ÿE.1ÿE.0ÿE.0ÿD-/ÿC,/ÿB+.ÿB+-ÿA*,ÿA*,ÿ@*,ÿ?*,ÿ?)+ÿ?)+ÿ?)+ÿ>(*ÿ>(*ÿ>')ÿ=&(ÿ<&(ÿ;%'ÿ:&'ÿ:&(ÿ;&'ÿ:&&ÿ9$%ÿ8$$ÿ8$$ÿ7%%ÿ5$$ÿ4"!ÿ<*)ÿbKTÿž| ÿĘàÿÈ›õÿ—÷ÿ¿˜úÿ·šÕÿgRSÿ?+*ÿ@++ÿ@++ÿA+,ÿA+,ÿA,,ÿA++ÿB++ÿB+,ÿA+,ÿA,,ÿB--ÿB--ÿF01ÿM46ÿC,-àC,-C,-D.0D.0C.0à`HLÿO9<ÿF03ÿG14ÿH25ÿJ25ÿJ36ÿK37ÿK38ÿL59ÿM59ÿN6:ÿO6;ÿO7;ÿP7;ÿP7<ÿQ7=ÿR8>ÿS8>ÿS8>ÿS9?ÿS:?ÿS:?ÿT:?ÿT:?ÿS9?ÿ‹wuÿÞÇ~ÿßÁKÿàÄTÿåÊhÿéÑ}ÿçÍoÿãÆXÿãÈ\ÿäÉ^ÿäÉ_ÿçÎnÿßÍ‹ÿ¾­‰ÿveaÿD03ÿ<)+ÿ?,.ÿA+.ÿB+-ÿC+.ÿD,/ÿD.0ÿE/1ÿE/2ÿF/2ÿF/2ÿG/2ÿF/1ÿE/0ÿE.0ÿE.0ÿE.0ÿD-/ÿC,/ÿB+.ÿA+-ÿA*,ÿ@*+ÿ@*+ÿ?*+ÿ>)+ÿ>(*ÿ=(*ÿ<')ÿ<&(ÿ;%'ÿ:$&ÿ8#%ÿ7"#ÿ6!"ÿ6 "ÿ6 "ÿ6"#ÿ6$%ÿ6%%ÿ4#"ÿ3"!ÿ@--ÿjT[ÿ£€¤ÿÇ™ÝÿÍœóÿƘõÿ¿–öÿ¼•ùÿ¹—ìÿ‚i‚ÿE00ÿ@+,ÿ@++ÿ@++ÿA++ÿA+,ÿA+,ÿA+,ÿA++ÿA++ÿA+,ÿA+,ÿA,-ÿA--ÿF00ÿM56ÿC,-àB,-B,-D.1D.1D.1àaIMÿP9<ÿF03ÿG14ÿH25ÿJ35ÿK36ÿK37ÿL48ÿM49ÿN6:ÿO6;ÿO7;ÿP7;ÿQ7<ÿQ7<ÿR8=ÿS8>ÿS9?ÿT9?ÿT9@ÿT:@ÿU;@ÿU;@ÿU;@ÿU:@ÿX>Eÿ¤�„ÿâËuÿàÃNÿâÇ[ÿçÎrÿéÔ�ÿãÈ]ÿäÉ^ÿäÉ_ÿæÌgÿá΂ÿмkÿѽlÿ̺„ÿ¡‘~ÿcQPÿ@,/ÿ;(*ÿ>*-ÿ?+-ÿA*-ÿB*,ÿB*,ÿA*-ÿA+.ÿA+.ÿB,/ÿC,/ÿB,.ÿB,.ÿB,.ÿB,.ÿA,.ÿA+-ÿ@*,ÿ?),ÿ?)+ÿ=(*ÿ<()ÿ<')ÿ;'(ÿ:&(ÿ:%'ÿ8$&ÿ8#%ÿ7"$ÿ7!"ÿ7 "ÿ6 "ÿ5!"ÿ4"#ÿ3"#ÿ1 !ÿ0ÿ5$$ÿO<>ÿ}dtÿ¯�°ÿЩßÿПóÿǘõÿÁ•õÿ½”öÿ¼•øÿ¼™îÿŠp�ÿG21ÿ?**ÿ@++ÿ?++ÿ@++ÿA++ÿA++ÿ@++ÿA+,ÿA++ÿA++ÿA++ÿA++ÿA,-ÿA,-ÿE00ÿM56ÿC,,àC,-C,-D.1D.1D.1àaJMÿP:=ÿF04ÿH25ÿI25ÿJ36ÿK36ÿL37ÿM49ÿM5:ÿN5;ÿO7;ÿO7;ÿQ7<ÿR8<ÿR8=ÿS8>ÿT9>ÿT9?ÿT:@ÿU:AÿU:AÿV;AÿV;AÿV*,ÿ?*,ÿ?)+ÿ?(+ÿ?(*ÿ@'*ÿ?'*ÿ?()ÿ>()ÿ>()ÿ=(*ÿ=')ÿ=&)ÿ<&(ÿ;%'ÿ:$&ÿ9$%ÿ9#%ÿ8#$ÿ8"#ÿ8"$ÿ7"#ÿ6"#ÿ6"$ÿ5"$ÿ4"$ÿ3!#ÿ1 ÿ0ÿ5##ÿG35ÿkPYÿ›s‰ÿÑ·ÿÕ¤×ÿÜ»ëÿÖ±ìÿΧíÿ̧ñÿɦóÿÈ¥öÿáíÿŒq�ÿH33ÿ>**ÿ@++ÿ@++ÿ?*+ÿ?*+ÿ@++ÿA++ÿ@++ÿ@++ÿA*+ÿA++ÿA++ÿ@++ÿA,,ÿA,-ÿE/0ÿL46ÿC,,àC,,C,,D.1D.1D.1ßaJMÿQ:>ÿG14ÿH25ÿI35ÿJ36ÿK37ÿL48ÿM49ÿN5:ÿO6;ÿO7;ÿP7<ÿQ8=ÿR8=ÿS9>ÿT9?ÿT:?ÿT:@ÿU:AÿU;AÿV;AÿW;AÿWÿS9?ÿT:?ÿU:@ÿU;AÿV;AÿV;BÿWÿ@.0ÿ9&)ÿ6$&ÿ6#%ÿ6#%ÿ6#%ÿ6$%ÿ6$%ÿ6$%ÿ5$%ÿ5#$ÿ4"$ÿ4"#ÿ3!"ÿ2 !ÿ1 !ÿ2 !ÿ4##ÿ;))ÿF36ÿYDJÿtYgÿ•rŒÿ¶ŽªÿÊ�¹ÿÕ”Èÿ×”ÍÿÓ‘ÍÿÍ�ÎÿÊŽÏÿÌ™Õÿ¼�Ûÿ¦tÑÿ¾–ÛÿÇ›àÿ×áÿ¸“Ìÿ{arÿD//ÿ>**ÿ@*+ÿ?**ÿ?*+ÿ?++ÿ?++ÿ?**ÿ?**ÿ@*+ÿ@++ÿ@++ÿ@**ÿ@**ÿA*+ÿ@*+ÿ@++ÿ@,,ÿE/0ÿK35ÿB+,ÙB+,B+,D.1D.1D.0Ï^GJÿU?CÿG04ÿI25ÿJ36ÿK37ÿK48ÿL59ÿM5:ÿO6:ÿO7;ÿP7<ÿQ8=ÿR8>ÿS9?ÿT:?ÿT:@ÿU;AÿV;AÿW>ÿM;<ÿL:;ÿM;=ÿO=?ÿTADÿ]JMÿiSWÿw^eÿŠlvÿ �ÿ¸�«ÿÊ’ÁÿÙ™Ôÿá›áÿã›èÿ婿ÿÚ–ÍÿÔ�ËÿÑ�ÌÿÎ�ÍÿÊŽÏÿË”ÓÿĘÛÿ®{Õÿ¨vÏÿ°…ÔÿÉ£ãÿ®Œ»ÿiQ\ÿ=&(ÿ:%'ÿ<')ÿ>))ÿ>**ÿ?**ÿ?*+ÿ?++ÿ?**ÿ?**ÿ@**ÿ@*+ÿ@++ÿ@**ÿ@**ÿ@**ÿ@*+ÿ@++ÿ@,,ÿF01ÿJ24ÿB++ÎB+,B+,D/1D/1D.1»ZCGÿZCGÿG04ÿI26ÿJ36ÿK37ÿL48ÿM59ÿN6:ÿO6;ÿO7;ÿQ8<ÿR8=ÿS8>ÿT9?ÿT:@ÿU;AÿV;BÿW)*ÿ?*+ÿ>**ÿ?**ÿ@**ÿ@**ÿ?*+ÿ@**ÿ@**ÿ@**ÿ?**ÿ@*+ÿ@+,ÿG12ÿH12ÿA++ºB++B++D/18#"D.1žT>Aÿ`IMÿG14ÿI26ÿJ37ÿK38ÿL59ÿM5:ÿN6:ÿO7;ÿO7;ÿQ8<ÿR8=ÿS8>ÿT9@ÿT:AÿU;BÿVEÿY=DÿX=CÿX)*ÿ?**ÿ@**ÿ?**ÿ?)*ÿ@)*ÿ@**ÿ?**ÿ?**ÿ?++ÿI24ÿE/0ÿ@++�># A++F.-F03E/2vN8;ÿfOSÿI26ÿI25ÿJ26ÿK38ÿL49ÿN6:ÿO6;ÿO7;ÿP8<ÿQ8=ÿR8>ÿT9?ÿT:@ÿU:AÿV;BÿWEÿZ>Eÿ[>Eÿ[>Fÿ[>Fÿ[>Fÿ[>Fÿ[>EÿZ>EÿY=DÿX=CÿX=BÿW;@ÿY>Dÿycfÿ±¡�ÿÐÁ†ÿÒÂmÿÌ»fÿɺmÿÊ»rÿË»tÿÑăÿëߦÿóâ¯ÿòФÿñÊ–ÿðÈ“ÿòÈ™ÿóÈžÿóÉ£ÿôÊ©ÿôÊ­ÿõ˱ÿöϺÿèįÿÙ¨�ÿÚ¦’ÿÚ¤•ÿÛ¢—ÿÙž˜ÿÕ˜—ÿÏ�¢ÿǃ±ÿÇ�¶ÿÞ¢ËÿìªÒÿîªâÿé—ãÿæ–äÿã–åÿß–çÿÜ•èÿÙ•éÿÕ“ëÿØ¡ëÿÓ›ÕÿÎ�ÌÿÓœÓÿÅ•Ùÿ´Ôÿ®‚ÈÿŒm�ÿW?Fÿ;&&ÿ9$%ÿ:%&ÿ:%'ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9#&ÿ9$&ÿ9$&ÿ9$&ÿ9#&ÿ:%&ÿ='(ÿ>))ÿ?**ÿ?**ÿ?)*ÿ?)*ÿ?**ÿ?**ÿ?++ÿJ35ÿC-.ÿA++uA+,>/.D.0F03E/2HH26øhQTÿN7:ÿI25ÿJ36ÿK38ÿL49ÿN5:ÿO6;ÿO7;ÿP8<ÿQ8=ÿR8>ÿS9?ÿT:@ÿV;AÿW;BÿXEÿ[>Fÿ\?Fÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ\>Gÿ[>Fÿ[>FÿZ>EÿY=DÿX=CÿX=BÿWÿT9?ÿT:@ÿV;AÿWFÿ[?Gÿ\?Gÿ\@Hÿ]@Hÿ\@Hÿ\?Gÿ\?Gÿ\?Gÿ[>Fÿ[=EÿZ=DÿY=DÿX=CÿW=BÿW)*ÿD./ÿH23ÿ?++Û@++@++E03D/3E/3§U?CÿdMPÿI25ÿK37ÿK48ÿL49ÿN5:ÿO6;ÿO7<ÿQ8=ÿR8>ÿS9?ÿT:@ÿT:AÿU;BÿWFÿ\?Gÿ]@Hÿ]@Iÿ]AIÿ]@Iÿ]@Hÿ\@Hÿ\?Gÿ[>Gÿ[>FÿZ=EÿY=DÿX=CÿX=BÿWÿS9?ÿT:@ÿU;AÿV;BÿWGÿ\?Hÿ]@Iÿ]AIÿ^AIÿ^AIÿ^AIÿ]@Hÿ\?Gÿ\?Gÿ[>FÿZ=EÿY=DÿX=CÿX=BÿWÿQ6<ÿO6;ÿW>CÿnX[ÿ“|ÿº§œÿÚÁ¶ÿìÆ·ÿôdzÿõæÿö¾¤ÿõº¥ÿ뵪ÿç²®ÿç°°ÿç­³ÿé·¼ÿߨ£ÿÜ��ÿÝ› ÿØ•žÿבŸÿ×�¡ÿÝš°ÿö·Îÿù­Óÿí§ãÿê£éÿäŽäÿâ‘åÿà•áÿÙ—ÓÿÁ�¸ÿ›v�ÿpT_ÿL7:ÿ<&'ÿ9$%ÿ:%&ÿ:%'ÿ:%'ÿ:%'ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$%ÿ8$&ÿ8$&ÿ9$&ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8"%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9"%ÿ9#%ÿ9#%ÿ;$&ÿD,0ÿ;&(ü;'(];&(@,+E15F04F04F04Ø`JMÿ]FIÿI26ÿK48ÿM49ÿN5:ÿO6;ÿO7<ÿP8=ÿR8>ÿS9?ÿT:@ÿU;AÿVEÿ\>Gÿ]?Hÿ]@Iÿ^AIÿ_BJÿ_BJÿ^AIÿ]@Iÿ\@Hÿ\?Gÿ[>FÿZ=EÿY=DÿX=CÿXÿS8>ÿR8=ÿQ8<ÿO6;ÿN48ÿM48ÿR:>ÿ`JMÿxbdÿ•~ÿ³˜“ÿ˪¢ÿÙµ­ÿÞ¸µÿ丹ÿç·»ÿé´½ÿì¶Ãÿ趺ÿࡦÿàŸ¨ÿÜ™¦ÿÚ–§ÿÜš®ÿð¹Ìÿù¹ÒÿñµÍÿã­ÍÿѦÌÿº‹³ÿ¡{•ÿƒfsÿcLQÿK68ÿ=()ÿ:$&ÿ:%'ÿ;%'ÿ:%'ÿ:%'ÿ:%&ÿ:%'ÿ:$'ÿ:$&ÿ:$&ÿ9$&ÿ:$&ÿ:$&ÿ9$&ÿ9#%ÿ8#%ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ8"$ÿ9#%ÿ9#%ÿ8#%ÿ9#%ÿ9"$ÿ9"%ÿ8#%ÿ?(+ÿA*-ÿ9$&×9#&9$'?,+G04J69F04†O9<ÿkTWÿM59ÿK48ÿL59ÿN5:ÿO6;ÿO7<ÿP8<ÿQ8=ÿS9?ÿT:@ÿU;AÿVEÿ\>Fÿ]?Hÿ]@Iÿ^AIÿ_AJÿ_BJÿ^AIÿ]AIÿ\@Hÿ\?Gÿ[>FÿZ=EÿY=DÿX=CÿXÿS8=ÿR8=ÿQ8<ÿP7;ÿO6:ÿO5:ÿN59ÿL37ÿJ25ÿI15ÿM58ÿT>@ÿ_JMÿmX[ÿ{fiÿŠrvÿ–|‚ÿŸ„‹ÿ¥‹‘ÿ¥‡Œÿ¦†Œÿ£ƒŠÿž†ÿš}„ÿ–{�ÿˆmrÿw_cÿeORÿT?BÿG34ÿ?**ÿ;&'ÿ:%'ÿ;&(ÿ<&(ÿ<&(ÿ;&(ÿ;%'ÿ:%'ÿ:%'ÿ:$&ÿ:%&ÿ:%&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9#%ÿ8#%ÿ8#%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ9#%ÿ8#%ÿ8#%ÿ9"$ÿ9"$ÿ9#&ÿC+/ÿ;%(ÿ9$&…9$'9$%G04H14G14,G14ãcLOÿ^GJÿJ37ÿL49ÿM5:ÿO6;ÿO7<ÿP8<ÿQ8=ÿR9>ÿT9@ÿU:AÿV;BÿWEÿ[>Fÿ\?Gÿ]@Hÿ^@Iÿ^AIÿ^AIÿ]AIÿ]@Iÿ\@Hÿ\?Fÿ[>EÿZ=DÿX=DÿX=CÿXÿR8=ÿR8<ÿQ8;ÿP7;ÿO6:ÿO5:ÿN59ÿM48ÿL47ÿK36ÿK25ÿI24ÿH03ÿF/2ÿE.1ÿE-1ÿE-0ÿE.1ÿE/1ÿE01ÿE01ÿD/0ÿC./ÿA+-ÿ?)+ÿ=(*ÿ<'(ÿ<'(ÿ<')ÿ=')ÿ=')ÿ=()ÿ<'(ÿ<')ÿ;&(ÿ<&(ÿ;&(ÿ;%'ÿ:%'ÿ:%'ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ8#%ÿ8#%ÿ8"%ÿ8"$ÿ8"$ÿ8"$ÿ8#%ÿ8#%ÿ8"$ÿ8"$ÿ?'*ÿ@(,ÿ8#%â8$&+8$&9$&@00G03�peG14†O8;ÿmVYÿP9=ÿK48ÿM5:ÿN6;ÿO7<ÿP7<ÿQ8=ÿR9>ÿS9?ÿT:AÿU;BÿWFÿ[?Gÿ]?Gÿ]@Hÿ]@Iÿ]@Iÿ]@Iÿ\@Hÿ\?Gÿ[?FÿZ>EÿY=DÿX=CÿX=BÿWÿR8=ÿQ8<ÿQ8;ÿP7;ÿO6:ÿO5:ÿM59ÿL48ÿK37ÿK36ÿK35ÿJ35ÿI24ÿH14ÿG03ÿG/3ÿF/2ÿE.1ÿD.0ÿD-/ÿC-/ÿB-.ÿA,-ÿA+-ÿA*,ÿ@*,ÿ?*+ÿ>)+ÿ=(*ÿ=(*ÿ=')ÿ=')ÿ<'(ÿ<'(ÿ;&(ÿ;&(ÿ;&(ÿ;%'ÿ:%'ÿ:%'ÿ9$&ÿ9$&ÿ9$&ÿ:$%ÿ:$%ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ7#$ÿ7#%ÿ8#%ÿ8"%ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ8"$ÿ8"$ÿ:#&ÿD+/ÿ:#&ÿ8"%…5 8$&3""H04H15H14 H14Ó]EIÿgPTÿK49ÿL59ÿN6;ÿO7;ÿP7<ÿQ8<ÿR9=ÿS9>ÿT9@ÿU:AÿV;BÿW=CÿX=CÿY=DÿY>EÿZ>Fÿ[?Gÿ\?Gÿ]?Hÿ]?Hÿ\?Hÿ\?Gÿ[?FÿZ>FÿZ>EÿY=DÿX=CÿXÿR8=ÿQ8<ÿP8;ÿO7;ÿO6:ÿN5:ÿM49ÿL48ÿK37ÿK26ÿK25ÿJ25ÿI24ÿH13ÿG03ÿF/2ÿF/2ÿE.1ÿD.0ÿD-/ÿC,/ÿB,.ÿA,-ÿ@+,ÿA*,ÿ@*+ÿ?*+ÿ>)+ÿ=(*ÿ='*ÿ=')ÿ=')ÿ<&(ÿ<'(ÿ;&'ÿ;&'ÿ:&(ÿ;%'ÿ:%'ÿ:%'ÿ9$&ÿ9$&ÿ9$&ÿ9$%ÿ:$%ÿ9$%ÿ9$&ÿ9$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ7"$ÿ7#$ÿ7#%ÿ8"%ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ8!$ÿB*-ÿ>'*ÿ7"$Ò8"$8"$9$&C66?+'I25H15[K36÷iQUÿ]FJÿK48ÿM6:ÿN6;ÿO7<ÿQ8<ÿR9=ÿS9>ÿT9?ÿU:@ÿU;BÿVEÿZ>Fÿ[>Fÿ[>Fÿ\>Fÿ[>Gÿ[>FÿZ>FÿY>EÿY=DÿX=CÿX=BÿWÿR8=ÿQ8<ÿP7;ÿO7;ÿO6:ÿN59ÿM49ÿL48ÿK37ÿK26ÿJ25ÿI25ÿI24ÿH13ÿG02ÿF/2ÿE.1ÿD.1ÿD.0ÿD-/ÿC,/ÿB,.ÿA+-ÿ@+,ÿ@*+ÿ?*+ÿ?**ÿ>)+ÿ=(*ÿ='*ÿ<')ÿ<')ÿ<&(ÿ<&(ÿ;&'ÿ;&'ÿ:&'ÿ:%'ÿ:%'ÿ:$'ÿ9$&ÿ9$&ÿ9$&ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ9$&ÿ8$&ÿ8#%ÿ7#%ÿ7#%ÿ8#%ÿ8"$ÿ7"$ÿ7"$ÿ7#$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ7"$ÿ7!#ÿ>&)ÿC*-ÿ8"$ö7"$Z8"$%"3""H13G14F14H25—O8;ÿnVZÿW?DÿL59ÿN6;ÿO7<ÿP8<ÿQ8=ÿR9>ÿS9?ÿT9@ÿU:AÿU;BÿWEÿZ>EÿZ>EÿZ=EÿZ=EÿY=EÿY=DÿX=CÿX=CÿWÿR7=ÿQ7<ÿP8;ÿO7;ÿO6:ÿN6:ÿM59ÿM48ÿL37ÿK37ÿK26ÿJ25ÿI15ÿH14ÿH13ÿG02ÿF/1ÿE.0ÿD.0ÿC.0ÿC-/ÿC,/ÿB+.ÿA+-ÿ@*,ÿ?*+ÿ?**ÿ>)*ÿ=)*ÿ=(*ÿ=')ÿ<')ÿ<')ÿ;&(ÿ<&(ÿ;%'ÿ;&'ÿ:&'ÿ:%&ÿ9%'ÿ9$'ÿ9$&ÿ9$&ÿ9#&ÿ9$%ÿ9$%ÿ8$%ÿ9$%ÿ9$%ÿ8$&ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ7"$ÿ;%(ÿD+/ÿ9#%ÿ7!#–7#%7"$7"$H15I25I25I25¿U=AÿoW[ÿU=AÿM5:ÿO7<ÿP7<ÿP8<ÿR9=ÿS9>ÿT9?ÿU:@ÿU:AÿU;BÿWÿR8>ÿQ7=ÿQ7<ÿP7;ÿO7;ÿO6:ÿN59ÿM58ÿL47ÿK37ÿK26ÿJ26ÿI25ÿH15ÿG04ÿG03ÿG02ÿF/1ÿE.0ÿD./ÿC./ÿC-/ÿB,/ÿB+.ÿ@+-ÿ@*,ÿ?)+ÿ>**ÿ=)*ÿ=)*ÿ=()ÿ=')ÿ<')ÿ<')ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%&ÿ9%&ÿ9$&ÿ9$&ÿ9$&ÿ9#%ÿ9$%ÿ9$%ÿ8#%ÿ8#%ÿ8$%ÿ8$%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7!#ÿ7!#ÿ7"$ÿ7"$ÿ:$'ÿE,0ÿ;$'ÿ7!#¾7!#7!#7"$K.1I46I36I26/I26ÓX@EÿoW\ÿU=BÿM5:ÿO7<ÿP8<ÿP8=ÿR9>ÿS9>ÿT9?ÿU:@ÿU:AÿU;BÿV;CÿWÿS8=ÿR8=ÿQ7<ÿP7<ÿO6;ÿO6;ÿN5:ÿM59ÿL48ÿK47ÿK36ÿK25ÿJ25ÿI25ÿH15ÿG04ÿG/3ÿF/2ÿF/1ÿE.0ÿD./ÿC-/ÿB-/ÿA,.ÿA+.ÿ@*-ÿ@*,ÿ?)+ÿ>)*ÿ=)*ÿ<(*ÿ=()ÿ='(ÿ<')ÿ<&)ÿ;&(ÿ:&(ÿ:%'ÿ:%'ÿ:%'ÿ:%&ÿ9%&ÿ9$&ÿ8$&ÿ8$&ÿ8#%ÿ9$%ÿ9$%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ8#$ÿ7#%ÿ7#%ÿ7#%ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7!#ÿ7!#ÿ7!#ÿ:$'ÿD-1ÿ<%(ÿ7!#Ó7!#.7!#7!#8!!H04B.3J37J26;J26ÙYAEÿpX\ÿY@EÿN6;ÿP7<ÿP8<ÿQ8=ÿR9>ÿS9?ÿT9?ÿU:@ÿU:AÿU;BÿV;BÿWÿS8>ÿR8=ÿQ7<ÿP7;ÿO7;ÿO6;ÿO5:ÿN5:ÿM49ÿL48ÿK37ÿK36ÿJ25ÿJ24ÿI14ÿH14ÿG03ÿG/3ÿF.2ÿE.1ÿD.0ÿC./ÿC-/ÿB-.ÿA,.ÿ@+-ÿ@*-ÿ@),ÿ?)+ÿ>)*ÿ=(*ÿ<()ÿ<()ÿ<'(ÿ<'(ÿ;&(ÿ;&(ÿ:&(ÿ:%'ÿ:%'ÿ:$&ÿ:$&ÿ9%&ÿ9$%ÿ8$%ÿ8$&ÿ8#%ÿ9$%ÿ9$%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7"$ÿ7#$ÿ7#%ÿ7"%ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7!#ÿ7!#ÿ<%'ÿE-1ÿ;&)ÿ6!#Ù7!#;7!#7%%8!#H26G16K36J37;J26ÓV>BÿpW\ÿ`GLÿO7<ÿO7;ÿP8<ÿQ9=ÿR9>ÿS9>ÿT9?ÿT9@ÿU:@ÿU:AÿU:BÿV;BÿVÿR8=ÿQ7<ÿP7;ÿP7;ÿO6;ÿO6:ÿN5:ÿM49ÿM48ÿL37ÿK36ÿJ26ÿI25ÿI24ÿH14ÿG03ÿG03ÿF/2ÿE.1ÿD-1ÿC-0ÿC./ÿC-/ÿB,.ÿA,-ÿ@+-ÿ@*,ÿ?),ÿ?)+ÿ>)*ÿ=(*ÿ<')ÿ<')ÿ;'(ÿ;'(ÿ;&'ÿ;&(ÿ:&(ÿ:%'ÿ9%'ÿ9$&ÿ9$&ÿ9$&ÿ9$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8#%ÿ8#%ÿ7#%ÿ7"%ÿ7"$ÿ6"$ÿ7#$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7!#ÿ?'*ÿF-1ÿ;$'ÿ6!#Ó6!#;6"#6!#7!#H27H26K38J37/J27¿Q9>ÿkSWÿkRWÿUÿS9>ÿS9?ÿT9?ÿT9?ÿT:@ÿU:AÿU:AÿU;AÿU;AÿT:AÿT:@ÿT:@ÿT:?ÿT9?ÿT9?ÿS8?ÿR8>ÿQ8=ÿQ8<ÿP7<ÿP7;ÿO7;ÿO6:ÿN59ÿM59ÿL49ÿL38ÿK37ÿK36ÿJ25ÿI25ÿH24ÿG14ÿG03ÿG/2ÿF/2ÿE.1ÿD-0ÿC-/ÿC-/ÿB-/ÿB,.ÿA+-ÿ@+,ÿ?*+ÿ?)+ÿ>)+ÿ=)*ÿ=(*ÿ<')ÿ<')ÿ;'(ÿ;'(ÿ;&'ÿ;&'ÿ:%'ÿ:%'ÿ9%'ÿ9$&ÿ8$&ÿ9$&ÿ8#%ÿ8#%ÿ8$%ÿ8$$ÿ8$%ÿ7$%ÿ8#%ÿ8#%ÿ7#%ÿ7"%ÿ7"$ÿ6"$ÿ6"$ÿ7"#ÿ6"#ÿ6"$ÿ6"$ÿ9$&ÿC+/ÿD,0ÿ9#%ÿ6!#¾6!#.6!#6!#7!#I36A00K38K37J37–M59÷`GLÿqX]ÿcJOÿR:>ÿO7;ÿP8<ÿQ9=ÿR9>ÿS9>ÿS9>ÿS9?ÿT9?ÿT9@ÿT:@ÿT:@ÿT:@ÿT9?ÿS9?ÿS9>ÿS8>ÿS8=ÿR8=ÿQ8=ÿQ8<ÿP7<ÿO7;ÿO7;ÿO6:ÿN6:ÿM59ÿL48ÿK47ÿK37ÿK27ÿJ26ÿJ25ÿI24ÿH14ÿG13ÿF02ÿF/2ÿF.1ÿE.1ÿC-0ÿC-/ÿB,/ÿB,.ÿA,.ÿ@+-ÿ@*,ÿ?*+ÿ>)*ÿ=)*ÿ<(*ÿ<(*ÿ<')ÿ<&(ÿ;&(ÿ;&(ÿ:&'ÿ:&'ÿ:%&ÿ:%'ÿ9%'ÿ9$&ÿ8$&ÿ8#&ÿ8#%ÿ8#%ÿ8#%ÿ8$$ÿ8$$ÿ7$$ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ6!#ÿ5!#ÿ7#%ÿ@*-ÿG/3ÿ?(+ÿ6!#÷6!#–7!#6!#4$$6"#G25M49K37I46K48[K38ÓS:?ÿgOSÿpX\ÿcKOÿUÿR9>ÿR9>ÿR9?ÿS9?ÿS9?ÿS9>ÿR8>ÿR8>ÿQ8=ÿQ8=ÿQ8<ÿQ7<ÿP7<ÿO6;ÿO6;ÿN6;ÿN6:ÿM59ÿM48ÿL48ÿK37ÿK36ÿJ36ÿI25ÿI15ÿH14ÿG14ÿF03ÿF02ÿE/1ÿE.0ÿD-0ÿC-/ÿC-/ÿB,/ÿA+.ÿ@+-ÿ@+,ÿ@*,ÿ?)+ÿ>)*ÿ=)*ÿ<(*ÿ<')ÿ<')ÿ<&(ÿ;&(ÿ;%'ÿ:%'ÿ9&'ÿ9%&ÿ9%&ÿ9$&ÿ9$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ8#$ÿ8$$ÿ7#$ÿ7#$ÿ7#%ÿ7#%ÿ7"$ÿ6"$ÿ6"$ÿ6!$ÿ8#%ÿ?),ÿG03ÿC,/ÿ9$&ÿ5!#Ó6!#[5!#6!#7!#5!#H02J47J37L49K48K38†L49ãU),ÿ?)+ÿ>)*ÿ=(*ÿ<()ÿ;')ÿ;'(ÿ;&(ÿ;&(ÿ;&(ÿ:%'ÿ:%'ÿ9%&ÿ9%&ÿ8%&ÿ8$%ÿ8$%ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ7"$ÿ8#$ÿ7#$ÿ7#$ÿ6##ÿ6"$ÿ5"$ÿ7"$ÿ9$'ÿ>),ÿE.2ÿG/4ÿA+/ÿ9$&ÿ6!#ã6!#†6!#6!#6!#6!#3 J379'"K49vXVL49+L48†M49×Q9>ü]DIÿiPUÿoV[ÿnUZÿiPTÿcJOÿ_FJÿ\CGÿZAFÿYAFÿY@FÿYAEÿYAEÿY@DÿX@DÿX?DÿX?DÿX>CÿW>BÿV=BÿV=BÿUÿR:=ÿQ:<ÿP9<ÿO8<ÿO8<ÿO7;ÿN6:ÿM69ÿL68ÿK57ÿK57ÿK46ÿJ36ÿI35ÿH25ÿG14ÿF03ÿF02ÿE/1ÿE/1ÿD/1ÿC.0ÿC./ÿB-/ÿB,/ÿB,/ÿA+.ÿA+.ÿ@*-ÿ@*-ÿ?+,ÿ?*,ÿ?*+ÿ?),ÿ?)+ÿ?)+ÿ>(+ÿ>(*ÿ>(*ÿ>(*ÿ>(+ÿ@*-ÿB-/ÿE/2ÿH14ÿH15ÿE.2ÿ>(+ÿ7"%ü4!#×5!#†6!#+/ !6!#-!!5!#C66K38J27L49S9?M59M49]M4:¦M5:ÜP8=÷V>Cÿ]DIÿcJOÿgNSÿiPUÿjQVÿjQVÿiPUÿiPUÿiPUÿiPTÿhOTÿhOSÿgNSÿfMRÿfMQÿfLQÿeKPÿdKPÿcJOÿcJNÿbIMÿbIMÿaHLÿ`HKÿ_GKÿ^FJÿ^EIÿ]DIÿ\CHÿ\CGÿ[CFÿZBEÿYBEÿXADÿX@CÿW?BÿV>BÿU=AÿT<@ÿTÿQ;>ÿP:<ÿP9<ÿO8;ÿO8;ÿN7;ÿN7:ÿN6:ÿM59ÿL59ÿL58ÿK47ÿJ47ÿJ47ÿK36ÿK36ÿJ26ÿI25ÿI25ÿH14ÿG04ÿF.2ÿB-/ÿ?)+ÿ:&'ÿ6#%ø5"$Ü5!#§5!#]5!#4!#6!#6"#6"#0 @00L48K37M59N5:K48M5:M5:GM5:uL59žM5:»N5:ÏN5:ÚN5:ßN5:àN5:àN5:àN5:àN5:àM5:àM59àL49àL48àK48àK37àK36àJ26àJ26àI25àI25àH24àH14àG14àF03àF/2àE/1àE.1àD-1àC-0àC-/àB-.àB-.àA,.à@+-à?+,à?*+à>)+à>(+à=(*à<(*à;')à;')à;'(à;&'à:&'à:&'à9%&à9%'à9$&à9$&à8$&à8#%à7#%à7$%à7#$à7#$à8#$à7"$à7#$à6#$à6"$ß6"#Ù6!#Î5!#»5!#�5""u5"#H5"$5"$5!#5!#5!#5!#+J38N6:M59M6:N6;N6;9(-L5:N5:N5:N6:N6:N5:N5:M5:N6:N5:M59L59L48K48K37K36K36J36J26I25H24G14G14F03F02F/1E.1D.1C.0C-/C-/B-/A,.@+-?+,?*,?)+>)+=(*<(*;'*;');'(;&(:&':&'9%&9%'8$'9$&8$&8#%7#%7#%7#$7#$8#$7"$7#$7#$6"$6"$6"$6"$:$6"#5"#5"$6"$6"$4"$K49L'8K5:M5:N5:N5:N6:N6:N5:N5:M5:N6:N5:M59L59L48K48K37K37K36J36J26I25H24G14G14F03F02F/1E.1D.1C.0C-/C-/B-/A,.@+-?+,?*,?)+>)+=(*<(*;'*;');'(;&(:&':&'9%&9%'8%'9$&8$&8#%8#%7$%7#$7#$8#$7"$7#$7#$6"$6"$6"$6"$6"$7$!7"#ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿ€ÿÿÿÿÿü?ÿÿÿÿðÿÿÿÿàÿÿÿÿ€ÿÿÿÿÿÿÿþÿÿü?ÿÿøÿÿðÿÿàÿÿàÿÿÀÿÿ€ÿÿ€ÿÿÿÿÿÿÿþþþþü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?ü?þþþþÿÿÿÿÿÿÿ€ÿÿ€ÿÿÀÿÿàÿÿàÿÿðÿÿøÿÿü?ÿÿþÿÿÿÿÿÿÿ€ÿÿÿÿàÿÿÿÿðÿÿÿÿü?ÿÿÿÿÿ€ÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ( ?''?))>'*>'*?(*?(*?'*?'*?(*?(*?(*?(*@(+@(+@(+@(+@(+@(+@(+A)+A)+A)+@),@),A),A)+A),B*,B),B),B*,B*,B*-B*-A*-C*-C*.C*.C*.C*.C+.C,.C,/D,/E+/E+/E+/D+/D+/D+/D,/E,0F-1F-1F-1F-1E-1E-2E.2F.1G.1G.2G-3G.3G.3G/3H/3I/4H/4H/4H/4H/5H06I06J16J16M47P67O67P68P68P68Q69Q6:Q7:R8:R8:Q8:Q8:Q9:S9;S9;S9<S9=S9=T9=T:=S:>T:>T;>U;?U;?U;?U;@U<@V<@W<@V<@V<@V=AW=AW=AW=CW>CW>CX>DX>DW>CW@DW@DX@DY?FY@FY@FY?FY@FZ@GY@HV?HY@IC:00<&(>&)>')>')>')>')K)`='*?(* ?(*?'*?'*?(*?(*?(*@(*@(+@(+@(+@(+@(+@(+@(+A)+A)+A)+@),@),A),A)+A),B*,B),B),B*,B*,B*-B*-A*-C*-C*-C*.C*.C*.C+.C,.C,/D,/D+/E+/E+/D+/D+/D+/D,/E,0F-1F-1F-1F-1E-1E-2E.2F.1G.1G.2G-3G.3G.3G/3H/3I/4H/4H/4H/4H/5H06I06J16J16M46P67O67P68P68P68Q69Q6:Q7:R8:R8:Q8:Q8:Q9:S9;S9;S9<S9<S9=S9=T:=S:>T:>T;>T;?U;?U;?U;@U<@V<@W<@V<@V<@V=AW=AW=AW=CW>CW>CX>DX>DW>CW@DW@DX@DY?FY@FY@FY?FY@F Z?FS9EZAHZAI[BH[BHZCH[AK’rO5TU<(*<&(=&(=&)=&)>'*>&) >') >')<>')_>')|>')˜>'*°?'*¿?'*Ì?'*Ö?'*Ú?'*ß?(*á?(*á?(*á@(+á@(+á@(+á@(+á@(+á@(+á@(+á@(+áA)+áA)+á@),á@),áA),áA)+áA),áA*,áB),áB),áB),áB*,áB*-áB*-áA*-áB*-áC*.áC*.áC*.áC*.áC+.áC+.áC,/áD+.áE+/áE+/áE+/áD+/áD+/áD+/áD,/áE,0áF,1áF-1áF-1áF-1áE-1áE-2áE.2áF.1áG.1áG.1áG-3áG-3áG.3áG/3áH/3áI/4áH/4áH/4áH/4áH/5áH06áI06áI06áJ16áN47áP67áO67áP68áP68áP68áP69áQ6:áQ7:áR7:áR8:áQ8:áQ8:áQ9:áR9;áS9;áS9<áS9=áS9=áT9=áT9=áS:>áT:>áT;>áU;?áU;?áU;?áU;@áU<@áV<@áV<@áV<@áV<@áV=AáW=AáW=AáW=CáW>CáW>CáX>DáX>DáW>CáW?DáW@DáX@DáX@EßYAFÛYAG×Y@GÎZ@GÁZ@H±YAHšYAH~ZAHaZAH@[BH"[CH cS?\DK\CK\BJ[@I]EJI$I;$';$&<&'=&(=&(=&( =&).=&)^=&)�=&)¿>&)ß>')ò>')þ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(*ÿ@(*ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@)+ÿ@)+ÿ@)+ÿA),ÿA)+ÿA),ÿA*,ÿA),ÿB),ÿB),ÿB),ÿB*,ÿB*,ÿA*-ÿB*-ÿB*.ÿC*.ÿC*.ÿC*.ÿC+.ÿC+.ÿC+.ÿC+.ÿD+/ÿE+/ÿD+/ÿD+/ÿD+/ÿD+/ÿD,/ÿD,0ÿE,0ÿF,0ÿF-1ÿE-1ÿE-1ÿE-2ÿE.2ÿE.1ÿF.1ÿG.1ÿG-2ÿG-2ÿG-3ÿG.3ÿG/3ÿH/4ÿH/4ÿH/4ÿH/4ÿH/5ÿH05ÿI05ÿI05ÿI06ÿN47ÿO67ÿO67ÿP68ÿP68ÿP68ÿP68ÿP69ÿQ7:ÿR7:ÿR7:ÿQ8:ÿQ8:ÿQ9:ÿR9;ÿR9;ÿS9;ÿS8<ÿS9=ÿT9=ÿS9=ÿS9>ÿS:>ÿS;>ÿU;?ÿU;?ÿU;?ÿU;?ÿU<@ÿV<@ÿU<@ÿU<@ÿV=@ÿV=AÿW=AÿW=AÿW=BÿW>BÿW>CÿW>DÿW>CÿW?CÿW?DÿW?DÿX@EÿX@EÿXAEÿY@FÿZ@GÿZ@GÿZAHÿYAHÿYAHÿZAIþZBIô[CIá[CIÂ[CJ”\CJa\CK0\BJ ^HO\CL[CKXBJZBJ;$(=&(<%(<%(<%)<&'=&(@=&(‚=&(¾=&(é=&)ý=&)ÿ=&)ÿ=&)ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ?(+ÿ@),ÿA)-ÿB*-ÿC*-ÿC*-ÿC*-ÿC+-ÿC+-ÿC+-ÿD+.ÿD+.ÿD+.ÿD+.ÿD+.ÿD+.ÿD+.ÿD,.ÿD,.ÿD,.ÿE,/ÿE,/ÿE-/ÿE-/ÿE-/ÿE-/ÿF-/ÿF-/ÿF-/ÿF-/ÿE.0ÿF.1ÿF.1ÿG.2ÿG.1ÿG.1ÿG/1ÿG/1ÿG/1ÿG/1ÿH/2ÿI/2ÿH/3ÿH/3ÿH/3ÿH03ÿH03ÿH04ÿI04ÿJ04ÿJ04ÿJ15ÿI15ÿI16ÿI25ÿJ25ÿJ25ÿK25ÿK16ÿK16ÿK16ÿK27ÿL37ÿL38ÿL38ÿL38ÿL38ÿL49ÿM49ÿM48ÿM49ÿN5:ÿR9:ÿS:;ÿT:;ÿT:<ÿT:<ÿT:<ÿT:<ÿT;<ÿU;=ÿV;>ÿV;>ÿU<=ÿU=>ÿV=>ÿV=>ÿV=>ÿW=?ÿW=?ÿX=@ÿX=@ÿW=AÿW=AÿW>AÿX?BÿY?BÿY?BÿY?CÿY@BÿZ@CÿZ@CÿY@CÿYACÿZADÿ[ADÿ[ADÿ[BEÿ[BEÿ[CFÿ[CGÿ[CGÿ\CGÿ\DGÿ\DGÿ\DHÿ\DHÿ\EHÿ\EHÿ\DHÿ\CHÿ[BIÿZBHÿYAHÿY@IÿYAIÿZAHÿZBIÿ[CIÿ\CIÿ\DKþ\DKê\DKÂ\CL†\CKC[CK_EP\CM]CL[CK]BL;%'+*<%'<%'<%)<%(1<%(<&(Ç<&(ò=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ>'*ÿ@(,ÿD+.ÿH/2ÿL25ÿO58ÿQ7:ÿS8;ÿT9<ÿT:=ÿU:>ÿV:>ÿV:>ÿV;>ÿV;>ÿV<>ÿV<>ÿV;>ÿW;?ÿX<@ÿX<@ÿX<@ÿX<@ÿX<@ÿW<@ÿW=@ÿY=@ÿY>?ÿY>@ÿY?AÿY?AÿY>AÿY>AÿZ>AÿZ>AÿZ?AÿZ?AÿZ?Aÿ[?Bÿ[?Cÿ[@Cÿ[@Cÿ[ACÿ\ACÿ\ACÿ\ACÿ\BBÿ]BCÿ]BDÿ]BDÿ^BDÿ^BDÿ]DDÿ]DEÿ]DEÿ^DEÿ_DEÿ_DEÿ_DFÿ_DGÿ_EGÿ_FGÿ`FFÿ`FFÿ`FGÿaEGÿaFGÿaFGÿbGHÿcGIÿbGIÿbHIÿbHIÿbHJÿbIJÿcIJÿdIJÿdJJÿdKKÿhNLÿhNLÿjNMÿjOMÿjOMÿjOMÿjONÿjPNÿkQNÿkQNÿkQOÿkQOÿkQOÿlRPÿlSPÿmSPÿmSPÿmSQÿnSQÿnTQÿmTRÿnTRÿnTRÿnUSÿoVTÿoVTÿoVTÿoWTÿpWTÿpWTÿpWTÿpWTÿpXUÿqWUÿrXUÿrYVÿrYVÿrYWÿrYWÿrZWÿrZXÿs[Xÿs[Xÿs[Xÿs\Xÿs\Xÿs\Yÿt\Yÿs[Yÿs[YÿqZYÿnWWÿkSUÿfORÿbJNÿ^FLÿ\CJÿ[CJÿ[CJÿ\DKÿ\DLÿ\DLÿ\DLô\DMÊ\DL‚\CL5^BL^DN^DMTFK]DM:&&G .;%';%'<%'<%'Q<%(«<%(é<%(ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ@)+ÿF-0ÿL25ÿP6:ÿR7<ÿS8<ÿQ6:ÿN37ÿK15ÿH/2ÿF.0ÿE,/ÿC+.ÿC+.ÿC*.ÿC*-ÿC*-ÿC*-ÿC*-ÿC+-ÿC+-ÿC+-ÿC+.ÿD+.ÿD+.ÿD+.ÿD+.ÿC+.ÿC+.ÿD,.ÿE,.ÿE,.ÿE-/ÿE-/ÿE,/ÿE-/ÿE-/ÿE-/ÿF-/ÿF-/ÿF-/ÿF-0ÿF.1ÿF.1ÿF.2ÿF.1ÿG/1ÿG/1ÿG/1ÿG/1ÿH/1ÿH/2ÿG/2ÿH/2ÿH/3ÿH03ÿH03ÿH04ÿI04ÿI04ÿI03ÿI04ÿI05ÿI15ÿI25ÿJ24ÿJ25ÿJ15ÿJ16ÿK16ÿK25ÿL26ÿL27ÿL27ÿK38ÿK38ÿK38ÿL49ÿM49ÿM48ÿM48ÿO69ÿS9:ÿR9;ÿS9;ÿT:<ÿT:;ÿT:<ÿT;<ÿU;<ÿU;<ÿU;=ÿU;=ÿU;=ÿU<>ÿV<>ÿV=>ÿV=>ÿV=?ÿV=?ÿW=?ÿX=@ÿW=AÿW>AÿW>BÿX>BÿX?BÿX?CÿY@BÿY@BÿZ@CÿZ@CÿYACÿYADÿZADÿZ@Dÿ[AEÿ[AEÿ[BEÿ[CFÿ[BFÿ[CFÿ[DGÿ\DGÿ\DHÿ\DHÿ\EHÿ]EIÿ^EJÿ_FKÿaILÿbKNÿeNQÿjRTÿmVVÿq[Yÿt^[ÿv_\ÿs\ZÿnVVÿgPRÿ`INÿ]DLÿ\CLÿ\DMÿ\DMÿ\DMÿ]DNë^DN®^DMU^DM^DN^EOa¡^CO:$%<$(;$';$';%';%'b;%'À<%'÷<%'ÿ<%(ÿ<%(ÿ<%(ÿ@),ÿG/2ÿN58ÿS8;ÿQ7:ÿL35ÿG.1ÿB*-ÿ?(+ÿ>&)ÿ=&)ÿ=&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(*ÿ@(+ÿ@(+ÿ@(+ÿ?(+ÿ?(+ÿ?(+ÿ@(*ÿ@(+ÿA*+ÿA)+ÿA),ÿA),ÿA),ÿA),ÿA),ÿA),ÿA),ÿB),ÿB)-ÿB*-ÿB*.ÿB+.ÿB+.ÿB+.ÿC+-ÿC+-ÿD+.ÿC*.ÿC*.ÿC*.ÿC+/ÿD,/ÿD,0ÿD,0ÿE,0ÿE,0ÿE,0ÿE,0ÿE,1ÿE-1ÿE-1ÿF.1ÿF.1ÿF-2ÿF-2ÿF-2ÿF-2ÿG.2ÿH.3ÿG.3ÿG.4ÿG.4ÿG/5ÿG05ÿH05ÿI04ÿI05ÿK25ÿN56ÿN56ÿO58ÿO58ÿO58ÿP68ÿP69ÿP79ÿQ79ÿQ7:ÿQ7:ÿQ7:ÿQ8:ÿR8;ÿR8;ÿR8;ÿR8<ÿR9<ÿS9<ÿS9=ÿS9=ÿS9=ÿS:>ÿT:?ÿT:?ÿT:?ÿT;?ÿUBÿW?BÿW?CÿW?CÿW?EÿW?EÿX@EÿX?FÿY?FÿY?FÿX@GÿX@GÿX@GÿYAHÿZBHÿ[CIÿ]EKÿaINÿgPRÿnWWÿt]\ÿw`]ÿs\[ÿjSVÿaJQÿ]ENÿ\CNÿ]DNÿ]DNÿ^DOø]DNÄ]DNd^EO^FO^EO_DQ[EL=)):#&:$&:$';#';$'\;%'Ã;%'û;%'ÿ;%'ÿ;%'ÿ>')ÿE,0ÿN37ÿR7;ÿN48ÿG/2ÿA*,ÿ>')ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(*ÿ?(*ÿ@(+ÿ@(+ÿ?(+ÿ?(+ÿ@(+ÿ@(+ÿ@(+ÿA)+ÿA)+ÿA)+ÿA),ÿA),ÿA),ÿA),ÿ@),ÿA),ÿB)-ÿB)-ÿB*-ÿB*-ÿB+.ÿB+.ÿB+.ÿC+.ÿD+.ÿD+.ÿD+.ÿC*.ÿC*.ÿC+.ÿC,/ÿD,0ÿE,0ÿE,0ÿE,0ÿE,0ÿE,1ÿE,1ÿE-1ÿE-0ÿF.1ÿF.1ÿF-2ÿF-2ÿF-2ÿF.2ÿG.3ÿH.3ÿG.3ÿG.3ÿG.4ÿG/5ÿG05ÿH05ÿH05ÿI05ÿL26ÿN56ÿN56ÿO57ÿO58ÿO58ÿP69ÿP79ÿQ79ÿQ79ÿQ7:ÿQ7:ÿQ8:ÿQ8:ÿR8;ÿR8;ÿR8;ÿR8<ÿS9<ÿS9<ÿS9=ÿS9=ÿS:=ÿT:>ÿT:?ÿT:?ÿT:?ÿT;?ÿUBÿW?CÿW?CÿW?CÿW?DÿW@EÿW@FÿY?FÿY?FÿY@GÿX@GÿYAHÿYAHÿYBHÿZBIÿZBIÿ[BIÿ[BJÿZBJÿ[CJÿ]ELÿaJOÿiSUÿs]\ÿwa_ÿs\\ÿiQVÿ`GPÿ]DOÿ]DNÿ]DNÿ^EOü^EOÆ^EO`^EN_FP^GN_FO_II:%'9'*:$&:#%:$&D;$'µ;$'ù;$'ÿ;%'ÿ;%'ÿ?(*ÿH/2ÿP59ÿO59ÿH/2ÿ@),ÿ=%)ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(*ÿ@(+ÿ?(+ÿ?(+ÿ@(+ÿ@(*ÿ@(+ÿ@)+ÿ@)+ÿA)+ÿA)+ÿA),ÿA),ÿA),ÿ@),ÿA),ÿB)-ÿB)-ÿB)-ÿB*-ÿB+-ÿB+.ÿB+.ÿB+-ÿC+.ÿD+.ÿC*.ÿC*.ÿC*.ÿC+.ÿC+/ÿC,0ÿD,0ÿE,0ÿE,0ÿE,0ÿE,1ÿE,1ÿE-1ÿE-0ÿF-0ÿF-1ÿF-2ÿF-2ÿF-2ÿF.2ÿG.3ÿG.3ÿG.3ÿG.3ÿG.4ÿG/5ÿH/5ÿH05ÿH05ÿH05ÿL36ÿN56ÿO57ÿO57ÿO57ÿO58ÿO59ÿP69ÿQ79ÿQ79ÿQ7:ÿQ7:ÿQ8:ÿQ8:ÿQ8:ÿR8;ÿR8<ÿR8<ÿS9<ÿS9<ÿS9=ÿS9=ÿS:=ÿS:>ÿT:>ÿT:?ÿT:?ÿT;?ÿU;@ÿU;@ÿU<@ÿU=@ÿV<@ÿV<@ÿVCÿW?CÿW?CÿW?DÿW@DÿW@EÿW?FÿX?FÿY@GÿX@GÿX@GÿY@HÿYAHÿYBIÿYBIÿZBIÿ[CJÿ[CJÿ[CJÿ[CKÿ[CKÿ[DKÿ[CLÿ\EMÿbJPÿlTWÿv_^ÿx``ÿnVYÿbJQÿ^EOÿ^EOÿ^EOÿ^EOú^EP¸^FPG^GL_GQ\CQ^FR=$$:$&:$&:$&:$&!:$&‘:$&ï:$'ÿ;$'ÿ;$'ÿ?'*ÿI03ÿP6:ÿM37ÿC+.ÿ=&(ÿ<%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ@(+ÿ@(+ÿ@(+ÿ@)+ÿ@(+ÿ@(+ÿA)+ÿA)+ÿA),ÿA),ÿ@),ÿA),ÿA)-ÿA)-ÿB)-ÿB)-ÿB*-ÿB+-ÿB+.ÿB+-ÿC+.ÿD+.ÿC*.ÿC*.ÿC*.ÿC+.ÿC+.ÿC+/ÿD,0ÿE,0ÿE,0ÿE,0ÿE,1ÿE,1ÿE-1ÿE-0ÿE-0ÿF-1ÿF,2ÿF-2ÿF-2ÿF.2ÿG.3ÿG.3ÿF.3ÿG.3ÿG.4ÿG/4ÿH/5ÿH/5ÿH05ÿH05ÿL36ÿN56ÿO57ÿO57ÿO57ÿO57ÿO59ÿO69ÿP69ÿQ79ÿQ7:ÿQ7:ÿQ8:ÿQ8:ÿQ8:ÿQ8:ÿR8<ÿR8<ÿS8<ÿS8=ÿS9=ÿS9=ÿS:>ÿS:>ÿT:>ÿT:?ÿT;?ÿT;?ÿU;@ÿU;@ÿU<@ÿU=@ÿV<@ÿV<@ÿVCÿW>CÿW>CÿW?DÿW@DÿW@EÿX?EÿX?FÿX@GÿX@GÿY@HÿY@HÿYAHÿYAIÿYBIÿZBIÿZCIÿ[CJÿ[CKÿ[CKÿ[DLÿ[DLÿ[DLÿ\CMÿ\DMÿ\CMÿ_FOÿgOUÿt]]ÿycaÿpY[ÿcKRÿ]EPÿ^EPÿ_FPÿ_FPð_GP•_GP#`GP^FQ_FQ^DM:$&8#&9#&:$':$&X:$&Ñ:$&ÿ:$&ÿ:$&ÿ=&)ÿH.2ÿP4:ÿK15ÿA),ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(*ÿ?(+ÿ@(+ÿ@(+ÿ@(+ÿ@)+ÿ@(+ÿ@(+ÿ@(+ÿA)+ÿA)+ÿA),ÿ@),ÿA),ÿA)-ÿA)-ÿA)-ÿB)-ÿB*-ÿB*-ÿB+-ÿB+-ÿC+.ÿC+.ÿC*.ÿC*.ÿC*.ÿC+.ÿC+/ÿC+/ÿD+/ÿD,0ÿE,0ÿE,0ÿE,1ÿE-1ÿD-0ÿE-0ÿE-0ÿE,1ÿF,1ÿF,2ÿF-2ÿF.2ÿG.3ÿG.3ÿF.3ÿF.3ÿG.4ÿG/4ÿH/4ÿH/4ÿH/5ÿH05ÿL36ÿN56ÿO57ÿO57ÿO57ÿO57ÿO58ÿO69ÿP69ÿP6:ÿQ7:ÿQ7:ÿQ8:ÿQ8:ÿQ8:ÿQ8:ÿQ8;ÿR8<ÿS8<ÿS8=ÿS8=ÿS9=ÿS:>ÿS:>ÿS:>ÿT:?ÿT;?ÿU;?ÿU;@ÿU;@ÿU<@ÿU<@ÿU<@ÿVCÿW>CÿW>DÿW?DÿW@DÿW?EÿX?EÿX?FÿX@GÿX@GÿY@HÿYAHÿYAIÿYAIÿZAIÿZCIÿZCIÿZCJÿ[CKÿ[DKÿ[DLÿ[DLÿ[CMÿ\DMÿ\DMÿ\DNÿ]DNÿ]DNÿ_FOÿfMTÿs\]ÿxcaÿoX[ÿbJSÿ_FPÿ_FQÿ_FQÿ_FQÓ^FQZ]EP_GQ^GR`GP9#%9$&9#%9#&:$&�:$&ô:$&ÿ:$&ÿ;%'ÿC+/ÿN38ÿL26ÿA)-ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(*ÿ@(*ÿ@(+ÿ@)+ÿ@)+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿA)+ÿA)+ÿ@),ÿA),ÿA)-ÿA)-ÿA)-ÿA*-ÿB*-ÿB*-ÿB*-ÿB+,ÿC+.ÿC+.ÿB*.ÿB*.ÿC*.ÿC+.ÿC+/ÿC+/ÿD+/ÿD+/ÿD,0ÿE,0ÿE,1ÿE-1ÿD-0ÿE-0ÿE-0ÿE,1ÿE,1ÿF,1ÿF-2ÿF.2ÿG.3ÿF.3ÿF.3ÿF.3ÿF.4ÿG/4ÿH/4ÿH/4ÿH/4ÿH/5ÿM36ÿN56ÿO57ÿO57ÿO57ÿO57ÿO68ÿP68ÿP69ÿP6:ÿP6:ÿQ7:ÿQ8:ÿQ8:ÿQ8:ÿQ8:ÿQ8;ÿQ8;ÿR8<ÿS8=ÿS8=ÿS9=ÿS:>ÿS:>ÿS:>ÿS:?ÿS;?ÿU;?ÿU;@ÿU;@ÿU<@ÿU;@ÿU;@ÿUBÿW>CÿW>CÿW>DÿW?DÿW?DÿX?EÿX?EÿX@FÿX@FÿX@GÿY@HÿYAHÿYAIÿYAIÿZAIÿZBIÿZCIÿZCJÿ[CJÿ[DKÿ[DLÿ[DLÿ\DMÿ\DMÿ\DNÿ\DNÿ]DNÿ^EOÿ^EOÿ]EOÿ^FPÿfOUÿu__ÿxbbÿkTYÿ`GRÿ_FQÿ_GQÿ_GQõ`GQ“_GQ`GS^FQ^FR9#$9#%9#%9#%79#&Á9#&ÿ:$&ÿ:$&ÿ?'*ÿJ15ÿM38ÿC+.ÿ;%'ÿ:$&ÿ;$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ@(*ÿ@(+ÿ@)+ÿ@)+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@)+ÿ@)+ÿA),ÿA)-ÿA)-ÿA)-ÿA*-ÿA*-ÿB*-ÿB*-ÿB*,ÿC+-ÿC+-ÿB*.ÿB*.ÿB*.ÿC+.ÿC+/ÿC+/ÿD+/ÿD+/ÿD+/ÿD,0ÿD,1ÿE-1ÿD-0ÿE-0ÿE-0ÿE,1ÿE,1ÿE,1ÿF-1ÿF-2ÿG.3ÿF.3ÿF.3ÿF.3ÿF.4ÿF/4ÿH/4ÿH/4ÿH/4ÿH/5ÿM36ÿN56ÿO57ÿO57ÿO57ÿO58ÿO68ÿP68ÿP68ÿP69ÿP6:ÿP7:ÿQ8:ÿQ8:ÿQ8:ÿQ8:ÿQ8;ÿR8;ÿR8;ÿR8=ÿS8=ÿS9=ÿS9>ÿS:>ÿS:>ÿS:?ÿS;?ÿT;?ÿU;?ÿU;@ÿU<@ÿU;@ÿU;@ÿU;AÿU=AÿV=AÿW=BÿW=BÿW>CÿW>CÿW>CÿW>DÿW?DÿW?EÿX?EÿX?EÿX@FÿX@FÿY@GÿY@HÿXAHÿYAIÿZAIÿZBIÿZBIÿZBJÿ[CJÿ[DJÿ[DKÿ[DLÿ\CMÿ\DMÿ\DMÿ\DNÿ\DNÿ]DOÿ]DOÿ]EOÿ]EOÿ^FPÿ^FPÿ_GRÿiRXÿxcbÿu_`ÿfNUÿ`GQÿ`GQÿ`GQÿ`GRÃ_GR:cIS_FR`FR<8#%8#%9"$9#%Z9#%ß9#%ÿ9#&ÿ:$'ÿD+/ÿN48ÿH/2ÿ=&(ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ;$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ@(*ÿ@(*ÿ?(+ÿ@)+ÿ@)+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@)+ÿA)+ÿA),ÿA)-ÿA)-ÿA*-ÿA*-ÿA*-ÿB*-ÿB*-ÿC*-ÿC+-ÿB*-ÿB*.ÿB*.ÿB+.ÿC+/ÿC+/ÿD+/ÿD+/ÿD+/ÿD+/ÿD,0ÿD-1ÿD-0ÿE-0ÿE-0ÿE,1ÿE,1ÿE,1ÿE-1ÿF-2ÿG-2ÿF.3ÿF.3ÿF.3ÿF.4ÿF/4ÿG/4ÿH/4ÿH/4ÿI/4ÿM45ÿO56ÿO57ÿN57ÿN57ÿO58ÿO68ÿP68ÿP68ÿP69ÿP69ÿP7:ÿP7:ÿQ8:ÿQ8:ÿQ8;ÿQ8;ÿR8;ÿR8;ÿR8<ÿR8<ÿS9=ÿS9>ÿS9>ÿS:?ÿS;?ÿS;?ÿT;?ÿT;?ÿU;?ÿU<@ÿU;@ÿU;@ÿU;AÿUCÿW>CÿW>CÿW>DÿW?DÿW?EÿW?EÿX?FÿX@FÿX@FÿY@GÿYAGÿXAHÿXAIÿYAIÿZBIÿZBIÿZBJÿ[CJÿ[DKÿ[DKÿ[DKÿ\DLÿ\DMÿ\DNÿ\DNÿ]DOÿ]DOÿ]DOÿ\DOÿ^FOÿ^FPÿ^FPÿ^FQÿ^FQÿbKSÿq[]ÿ{dcÿmUZÿaGRÿ`FRÿ`GRÿ`GRá`GR]`DQ`GR_HSfMM8%8#%8#%8#%9#%v9#%ñ9#%ÿ9#%ÿ<%(ÿH/3ÿL27ÿA)-ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ;$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ@'*ÿ@(*ÿ?(+ÿ?)+ÿ@)+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿA)+ÿA),ÿA),ÿA)-ÿA*-ÿA*-ÿA*-ÿA*-ÿB*-ÿC*-ÿC*-ÿB*-ÿB*-ÿB*.ÿB+.ÿB+/ÿC+/ÿD+/ÿD+/ÿD+/ÿD+/ÿD+0ÿD-0ÿD-0ÿE-0ÿE-0ÿE,1ÿE,1ÿE,1ÿE-1ÿF-2ÿF-2ÿF-2ÿF.3ÿF.3ÿF.4ÿF/4ÿG/4ÿG/4ÿG/4ÿI04ÿM45ÿO56ÿO57ÿN57ÿN57ÿN58ÿO68ÿP68ÿP68ÿP69ÿP69ÿP7:ÿP7:ÿP7:ÿQ8:ÿQ8;ÿQ8;ÿR8;ÿR8<ÿR8<ÿR8<ÿR9=ÿS9>ÿS9>ÿS9?ÿS:?ÿS;?ÿT;@ÿT;?ÿTCÿW>CÿW>CÿW>CÿW?DÿW?EÿW?EÿW@FÿX?FÿX@FÿY@GÿXAGÿXAHÿXAHÿYAIÿZBIÿZBIÿ[BJÿ[CJÿ[CKÿ[DKÿ[CLÿ[DLÿ\DMÿ\DNÿ]DNÿ]DOÿ]DOÿ\DOÿ]EOÿ]EPÿ^FPÿ^FPÿ^GQÿ_GQÿ_GQÿ_FRÿiQXÿyccÿu]`ÿdKUÿ`GRÿ`HRÿ`HSò`HSx_HQ`HS`HTaFS8!$8"%8#%8#% 8#%�8#%ù9#%ÿ9#%ÿ>'*ÿL16ÿI/3ÿ<%)ÿ9#&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ;$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ@'*ÿ@'*ÿ?(+ÿ?)+ÿ?)*ÿ?(*ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ?(+ÿ@(+ÿ@(+ÿA),ÿA),ÿA),ÿA*-ÿA*-ÿA*-ÿA*-ÿB*-ÿC*-ÿC*-ÿB)-ÿB*-ÿB*-ÿB+.ÿB+/ÿC+/ÿD+/ÿD+/ÿD+/ÿD+0ÿD+0ÿD,0ÿC-0ÿD-0ÿE-0ÿE,1ÿE,1ÿE,1ÿE-1ÿF-2ÿF-2ÿE-2ÿF-2ÿF.3ÿF/4ÿF/4ÿG/4ÿG/4ÿG/4ÿH04ÿM45ÿO55ÿO56ÿN47ÿN57ÿN58ÿN68ÿO68ÿP68ÿP69ÿP69ÿP79ÿP79ÿP7:ÿP7:ÿQ7;ÿQ8;ÿR8;ÿR8<ÿR8<ÿR8<ÿR9=ÿR9=ÿS9>ÿS9?ÿS:?ÿT;?ÿT;?ÿT;?ÿTCÿW>CÿW>CÿW?CÿW?DÿW?EÿW?EÿW@FÿW?FÿY?GÿY@GÿXAGÿXAHÿYAHÿYBIÿYBIÿYBJÿ[BJÿ[CJÿ[CKÿ[CKÿ[DLÿ[DLÿ[DMÿ\DMÿ]DOÿ]DOÿ\DOÿ\EOÿ]EOÿ]EPÿ]EPÿ^FQÿ_GQÿ_GQÿ_FRÿ_FRÿ_FRÿdKUÿu^`ÿzbcÿhOXÿaGSÿaHSÿaHSúaHS�`HSaHSaIU`CQ9""8"$8"%8"%8"%˜8#%ý8#%ÿ8#%ÿA),ÿM27ÿE,0ÿ:$&ÿ9#%ÿ9#&ÿ9#&ÿ9#&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ;$'ÿ;$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=&)ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ?'*ÿ@'*ÿ?'*ÿ?'+ÿ?(+ÿ?(*ÿ?(*ÿ?(*ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(,ÿ@(,ÿA(,ÿA),ÿA*,ÿA*-ÿA*-ÿA*-ÿA*-ÿB*-ÿB*-ÿB)-ÿB)-ÿB*-ÿB+.ÿB+/ÿB+/ÿC+/ÿD+/ÿD+/ÿD+0ÿD+0ÿD,0ÿC,0ÿD-0ÿD-1ÿE,1ÿE,1ÿE,1ÿE-1ÿF-2ÿF-2ÿE-2ÿE-2ÿF-3ÿF.4ÿF/4ÿG/4ÿG/4ÿG/4ÿH04ÿM45ÿO56ÿO56ÿN46ÿN47ÿN58ÿN68ÿO68ÿO69ÿP69ÿP69ÿP79ÿP79ÿP79ÿP7:ÿP7;ÿQ8;ÿR8;ÿR8<ÿR8<ÿR9<ÿR9=ÿR9=ÿR9=ÿS9?ÿS:?ÿT:?ÿT;?ÿT;?ÿTCÿW>CÿW>CÿW?CÿW?DÿW?DÿW?EÿW@FÿW?FÿX?GÿY@GÿXAHÿXAHÿYAHÿYBHÿYBHÿYBJÿZBJÿ[CKÿ[CKÿ[CLÿ[DLÿ[DLÿ[DMÿ\DMÿ\DNÿ]DOÿ\DOÿ]EOÿ]EPÿ]EPÿ]FQÿ^FQÿ_FQÿ_FQÿ_GQÿ`GRÿ`GSÿ_GSÿaHTÿoX]ÿ{eeÿkSZÿ`GSÿ`GSÿaHSþaHT›`HS`IT`ITdMW<7"$8"$8"$8"$ž8"%þ8"%ÿ8#%ÿB+.ÿL27ÿA)-ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#&ÿ9#&ÿ9#&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ;$'ÿ;$'ÿ;$'ÿ<$'ÿ<%'ÿ;%'ÿ<%'ÿ<%'ÿ<%'ÿ=%'ÿ=%(ÿ=%(ÿ=%(ÿ=%(ÿ=%(ÿ=&(ÿ=&(ÿ>&(ÿ>&(ÿ>&(ÿ>&)ÿ>&)ÿ>&)ÿ>&)ÿ>&)ÿ?&)ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ@'*ÿ?'*ÿ?'+ÿ?(+ÿ?(*ÿ?(*ÿ?(*ÿ?(*ÿ@(+ÿ@(+ÿ?(+ÿ@(+ÿ@(,ÿ@(,ÿ@(,ÿ@),ÿA*,ÿA*,ÿA*-ÿA*-ÿB*-ÿB*-ÿB)-ÿB)-ÿB)-ÿB)-ÿB*-ÿB+.ÿC+/ÿC+/ÿC+/ÿD+/ÿD+0ÿD+0ÿD,0ÿC,0ÿD,0ÿD,0ÿD,1ÿE,1ÿE,1ÿE-1ÿF-2ÿF-2ÿE-2ÿE-2ÿE-3ÿF.3ÿG.4ÿG/4ÿG/4ÿG/4ÿH04ÿL45ÿN56ÿO56ÿN46ÿN46ÿN48ÿN58ÿO68ÿO69ÿO69ÿP69ÿP79ÿP79ÿP79ÿP79ÿP7;ÿP8;ÿQ8;ÿR8<ÿR8<ÿR9<ÿR9=ÿR9=ÿR9=ÿR9>ÿS:?ÿT:?ÿT:?ÿT;?ÿT<@ÿT;@ÿT;@ÿT;@ÿU<@ÿU<@ÿVCÿW?CÿW?DÿW?DÿW?EÿW@FÿW?FÿX?GÿX@GÿX@HÿX@HÿYAHÿYBHÿYBHÿYBIÿZCJÿZCKÿ[CKÿ[CLÿ[DLÿ[DMÿ[DMÿ\DNÿ\DNÿ\DNÿ\EOÿ]EOÿ]EPÿ]EPÿ^FQÿ^FQÿ^FQÿ_GQÿ`GQÿ`GRÿ_GSÿ_GSÿ_HTÿ_HTÿkT[ÿ{eeÿnW]ÿ`HTÿ`GSÿaHSÿaHS¡`HT`HT`GTfMM7"$7"$7"# 8"$˜8"$þ8"$ÿ8"%ÿC+/ÿK27ÿ>(+ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#&ÿ9#&ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$'ÿ<$'ÿ<$'ÿ<$'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ=%'ÿ=%'ÿ=%(ÿ=%(ÿ=%(ÿ=%(ÿ=%(ÿ=&(ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&)ÿ>&)ÿ>&)ÿ>&)ÿ?&)ÿ?&)ÿ?')ÿ?')ÿ?')ÿ?')ÿ?'*ÿ@'*ÿ@'*ÿ@'+ÿ@(+ÿ?'*ÿ?'*ÿ?(*ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ@(+ÿ@(+ÿ@(,ÿ@(,ÿ@(,ÿ@),ÿA*,ÿA*,ÿA*,ÿB*-ÿB*-ÿA*-ÿA)-ÿA)-ÿB*-ÿB*-ÿB*.ÿC+.ÿC+/ÿC+/ÿC+/ÿD+0ÿD+0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,1ÿE,1ÿE-1ÿF-2ÿF-2ÿE-2ÿE-2ÿE-3ÿE.3ÿF.3ÿG.3ÿG/4ÿG/4ÿH04ÿL45ÿN56ÿN56ÿN46ÿN46ÿN47ÿN58ÿO58ÿO69ÿO69ÿO69ÿP79ÿP79ÿP79ÿP79ÿP7:ÿP8;ÿQ8;ÿQ8<ÿR8<ÿR9<ÿR9=ÿR9=ÿR9=ÿR9>ÿR:>ÿS:?ÿT:?ÿT:?ÿT;@ÿT;@ÿT;@ÿT;@ÿT<@ÿU<@ÿVCÿV?CÿW?DÿW?DÿW?EÿW@EÿW?FÿX?GÿX@GÿW@HÿX@HÿYAHÿYBHÿYBHÿZBIÿZCIÿZCKÿZCKÿ[DLÿ[DLÿ[DMÿ[CMÿ\DNÿ\DNÿ\DNÿ]ENÿ]EOÿ]EPÿ]FQÿ^FQÿ^FQÿ^FQÿ^GQÿ_GRÿ_GRÿ_GSÿ_HTÿ`HTÿ`HTÿ`HTÿiQZÿ{eeÿpY^ÿaHTÿ`HSÿaHSÿaHT›`HU`GS`GR7"$7"$7!$7"$�7"$ý8"$ÿ8"$ÿD+/ÿK06ÿ=&*ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:#&ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$'ÿ<$'ÿ<$'ÿ<$'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ=%'ÿ=%(ÿ=%(ÿ=%(ÿ=%(ÿ=%(ÿ=&(ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&)ÿ>&)ÿ>&)ÿ>&)ÿ?&)ÿ?&)ÿ?')ÿ?')ÿ?')ÿ?')ÿ@'*ÿ?'*ÿ@'+ÿ@(+ÿ@'*ÿ@'*ÿ@'*ÿ@(*ÿ@(*ÿ@(*ÿ?(+ÿ@(+ÿ@(,ÿ@(,ÿ?(,ÿ?(,ÿ?),ÿ?),ÿ@*,ÿA*,ÿA*,ÿB*-ÿA*-ÿA)-ÿA)-ÿA*-ÿB*-ÿB*.ÿC*.ÿC+.ÿC+/ÿC+/ÿC+0ÿC+0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,1ÿE-1ÿF-2ÿF-2ÿE-2ÿE-2ÿE-3ÿE.3ÿF.3ÿG.3ÿG.4ÿG/4ÿH04ÿL45ÿN56ÿN56ÿM46ÿN46ÿN57ÿO57ÿO58ÿO59ÿO69ÿO69ÿO79ÿP79ÿP79ÿP79ÿP7:ÿP8:ÿQ8;ÿQ7<ÿQ7<ÿR9<ÿR9=ÿR9=ÿR9=ÿR9>ÿR:>ÿS:?ÿS:?ÿT:?ÿT;@ÿT;@ÿT;@ÿT;@ÿT<@ÿTCÿV?DÿW?DÿW@EÿW?EÿW?EÿX?GÿX@GÿW@HÿX@HÿYAHÿYAHÿYBIÿZBIÿZCIÿZCJÿZCKÿZDLÿ[DLÿ[DMÿ\CMÿ\DNÿ\DNÿ\DNÿ]ENÿ]EOÿ]EPÿ]FQÿ^FQÿ^FQÿ^GQÿ_GRÿ_GRÿ_GSÿ_HSÿ`HSÿ`HTÿ`HTÿ`HTÿ`HTÿgPYÿ{deÿqZ^ÿaHTÿ`GSÿaHSþaHS�_GQ`GR`GQ8!$7"$6"#7"$v7"$ù7"$ÿ8"$ÿC*.ÿL05ÿ=&(ÿ9"$ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$'ÿ<$'ÿ<$'ÿ<$(ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<%'ÿ=%(ÿ=%(ÿ=%(ÿ=%)ÿ=%(ÿ=%)ÿ=&)ÿ=&)ÿ>&)ÿ>&(ÿ>&)ÿ>&)ÿ>&)ÿ>&)ÿ>&)ÿ?&)ÿ?&)ÿ?')ÿ?')ÿ?')ÿ@')ÿ?'*ÿ?'+ÿ@(+ÿ@'*ÿ@'*ÿ@'*ÿ@'*ÿ@(*ÿ@(*ÿ?(*ÿ@(*ÿ@(+ÿ@(,ÿ@(,ÿ@(,ÿ?),ÿ?),ÿ?),ÿ@*,ÿA*,ÿA*-ÿA)-ÿ@)-ÿA)-ÿA*-ÿA*-ÿB*.ÿC*.ÿC*.ÿC+.ÿC+/ÿC+0ÿC+0ÿC,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD-1ÿE-2ÿF-2ÿE-2ÿE-2ÿE-3ÿE.3ÿF.3ÿF.3ÿG.4ÿG.4ÿH/4ÿL45ÿN56ÿN56ÿM46ÿM46ÿN57ÿN57ÿO57ÿO58ÿO59ÿO69ÿO79ÿO79ÿP79ÿP79ÿP8:ÿP8:ÿQ8:ÿQ7<ÿQ7<ÿQ8<ÿR9=ÿR9=ÿR9=ÿR9>ÿR:>ÿS:>ÿS:>ÿS:?ÿT;@ÿT;@ÿT;@ÿT;@ÿT<@ÿT<@ÿUCÿV>DÿW?DÿW@EÿW?EÿW?EÿX?FÿW@GÿW@HÿX@HÿXAHÿYAHÿYAIÿZBIÿZCJÿZCJÿZCKÿZDLÿZDLÿ[DMÿ\DMÿ\DNÿ\DNÿ\DNÿ]ENÿ]EOÿ\EOÿ]FQÿ^FQÿ^FQÿ^GQÿ_GRÿ_FRÿ_GSÿ`GSÿ`HSÿ`HSÿ`ITÿ`IUÿ`IUÿ`HTÿgOXÿ{deÿpY^ÿ`HTÿ`GSÿaHSú`HRy_GP`GR_HR5 "8!$7"$8"$[8"$ñ8"$ÿ8"$ÿB*-ÿL16ÿ>&)ÿ9"$ÿ9"$ÿ9"$ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:#&ÿ:#'ÿ:$'ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%'ÿ;%(ÿ;%(ÿ;%(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&)ÿ<&)ÿ<&)ÿ<&)ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ>'*ÿ>'*ÿ>'*ÿ?'*ÿ?'*ÿ?'*ÿ?'*ÿ?'+ÿ?(+ÿ@'*ÿ@'*ÿ@'*ÿ@'*ÿ@'*ÿ@(*ÿ?(*ÿ@(*ÿ@(+ÿ@(,ÿ@(,ÿ@(,ÿ@),ÿ@),ÿ@),ÿ@),ÿA*,ÿA*,ÿA*,ÿ@)-ÿ@)-ÿ@*-ÿ@*.ÿA*.ÿB*.ÿC*.ÿC*.ÿC+.ÿC+/ÿC,0ÿB,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿE-1ÿE-2ÿE-2ÿE-2ÿE-3ÿE.3ÿF.3ÿF.3ÿF.4ÿF.4ÿG/4ÿL45ÿN56ÿN56ÿM46ÿM46ÿM57ÿN57ÿO57ÿO58ÿO58ÿO59ÿO79ÿO79ÿO79ÿP79ÿP8:ÿQ8:ÿQ8:ÿQ7;ÿQ7;ÿQ8<ÿQ8=ÿR9=ÿR9=ÿR:>ÿR:>ÿS:>ÿS:>ÿS:>ÿS;?ÿT;@ÿT;@ÿT;@ÿT<@ÿUCÿV>DÿW>DÿW?EÿW?EÿX?FÿX?FÿW@FÿW@GÿX@HÿXAHÿXAHÿYAIÿZBIÿZCJÿZCJÿZCJÿZDKÿZDLÿZDMÿ[DMÿ\DNÿ\DNÿ\DNÿ]DNÿ]EOÿ\EOÿ]FPÿ^FQÿ^FQÿ_GRÿ_GRÿ_FSÿ_GSÿ`GSÿ_HSÿ`ITÿ`ITÿaIUÿaIUÿ`IUÿ`HTÿgPYÿ{eeÿnW]ÿ`GSÿaGSÿ`HRò`GR\aHP_HR_HO:##9"$8!#7!#88!#ß8"$ÿ8"$ÿ@(,ÿM27ÿ>'*ÿ8"$ÿ8"$ÿ9"$ÿ9"$ÿ9"%ÿ9"%ÿ9#&ÿ9#&ÿ9#&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ9$'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%(ÿ;%(ÿ;%(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&)ÿ<&)ÿ<&)ÿ<&)ÿ<')ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ='*ÿ='*ÿ>'*ÿ>(*ÿ?(*ÿ>(*ÿ>(+ÿ>)+ÿ>(+ÿ?(+ÿ@(+ÿ@'+ÿ@'+ÿ@'*ÿ?(*ÿ@(*ÿ@(+ÿ@(+ÿ@(,ÿ@(,ÿ@),ÿ@),ÿ@),ÿ@),ÿA),ÿB*,ÿA),ÿA),ÿA)-ÿ@*-ÿ@*-ÿ@*.ÿA*.ÿB*.ÿB*.ÿC*.ÿC+/ÿC,/ÿC,0ÿC,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿE,1ÿE-1ÿE-2ÿE-2ÿE-3ÿE.3ÿF.3ÿF.3ÿF.4ÿF.4ÿG.4ÿL34ÿN56ÿN56ÿM46ÿM46ÿM57ÿN57ÿO57ÿO58ÿO58ÿO58ÿO69ÿO79ÿO79ÿO79ÿP8:ÿQ8:ÿQ8:ÿQ7;ÿQ7;ÿQ8<ÿQ8=ÿQ8=ÿR9=ÿR:>ÿR:>ÿS:>ÿS:>ÿS:>ÿS;?ÿT;?ÿT;@ÿT;@ÿT;@ÿUCÿV>CÿV>DÿW>DÿW?EÿW?EÿW?FÿX?FÿW@FÿW@GÿX@HÿXAHÿXAHÿXAIÿYAIÿZBJÿZCJÿZCKÿZDKÿZDLÿZCLÿ[DMÿ\DNÿ\DNÿ]DNÿ]DOÿ\DOÿ\EPÿ]FPÿ]FPÿ^GQÿ_GRÿ_FRÿ_FSÿ_GSÿ`GSÿ_HSÿ_HTÿaITÿaIUÿaIUÿaIUÿ`IUÿ`HTÿhQZÿ{eeÿkSZÿaGSÿ`GRÿ`GRà_GR9`GR`DQ[II6 #7!#7!#7!#Á7!#ÿ8!#ÿ>&)ÿM27ÿA),ÿ8"$ÿ8"$ÿ8"%ÿ8"%ÿ8#%ÿ8#%ÿ8#%ÿ8#&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ9$'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%(ÿ;%(ÿ;%(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&)ÿ<&)ÿ<&)ÿ<&)ÿ<')ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ='*ÿ='*ÿ>'*ÿ?(*ÿ>(*ÿ>(+ÿ>)+ÿ>(+ÿ>(+ÿ>(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ@(+ÿ@)+ÿ@(,ÿ@(,ÿ@(,ÿ@),ÿ@),ÿ@),ÿ@),ÿA),ÿA),ÿA),ÿA),ÿA),ÿA*-ÿA*.ÿA*.ÿA*.ÿA*.ÿB*.ÿB*.ÿB*/ÿB+/ÿB,/ÿB,0ÿB,0ÿC,0ÿC,0ÿC,0ÿC+0ÿC+0ÿD,0ÿD,1ÿD,1ÿD-1ÿD-2ÿD-3ÿE.3ÿE.3ÿE.3ÿE.4ÿE.3ÿJ23ÿM45ÿM45ÿL46ÿL46ÿL46ÿM57ÿM57ÿN57ÿN58ÿO58ÿO69ÿO69ÿO79ÿO79ÿO7:ÿP8:ÿQ8:ÿQ7;ÿQ7;ÿQ8;ÿQ8<ÿQ8=ÿQ8>ÿR9>ÿR:>ÿS:>ÿS:>ÿS:>ÿS;?ÿT;?ÿT;?ÿT;@ÿT;@ÿU;AÿUCÿV>CÿW>DÿW>DÿW?EÿW?EÿW?FÿW?FÿW@FÿW@GÿX@GÿXAHÿXAHÿXAIÿYAIÿYBJÿZBJÿZCKÿZDKÿZDKÿZCLÿ[DMÿ[DNÿ[DNÿ\DNÿ]DOÿ\DOÿ\EPÿ]FPÿ]FPÿ]GQÿ^GQÿ_FRÿ_FSÿ`GSÿ`GSÿ_HSÿ_HTÿ`HTÿaIUÿaIUÿaITÿ`IUÿ`HTÿ`HTÿkT[ÿ{eeÿhOXÿ`FRÿ`FRÿ`GQÃ`GP_FQ_EQ6#%7!#6 #7!#‘7!#ÿ7!#ÿ:#&ÿK16ÿD+0ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8#&ÿ8#&ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ9$'ÿ9$'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%(ÿ;%(ÿ;%(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&)ÿ<&)ÿ<&)ÿ<&)ÿ<')ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ='*ÿ='*ÿ?'*ÿ>(*ÿ>(+ÿ>)+ÿ>(*ÿ>(*ÿ>(+ÿ>(+ÿ?(+ÿ?(+ÿ?(+ÿ@(+ÿ@),ÿ?),ÿ?),ÿ?),ÿ@*,ÿ@*,ÿ@),ÿ@),ÿA),ÿA),ÿ@),ÿ@),ÿA),ÿA*,ÿA*-ÿ@*.ÿA*.ÿA*.ÿA*-ÿA*-ÿA*.ÿA*.ÿ@+.ÿ@+.ÿA+/ÿA+/ÿA+/ÿB+/ÿB+/ÿB+/ÿC+0ÿC+0ÿC+/ÿC+0ÿC,1ÿC-2ÿD-1ÿD-2ÿD-2ÿD-3ÿD-2ÿH12ÿK33ÿK24ÿK24ÿK35ÿK35ÿL45ÿL46ÿL46ÿM47ÿM47ÿN57ÿN58ÿN58ÿN69ÿN79ÿO89ÿP7:ÿP7;ÿQ7;ÿQ8;ÿQ8<ÿQ8<ÿQ8=ÿQ9>ÿR:>ÿS:>ÿS:>ÿS:>ÿS;?ÿT;?ÿT;?ÿT;@ÿT;@ÿT;AÿU;AÿUCÿV>CÿV>DÿW>DÿW?EÿW?EÿW?EÿW?FÿW@FÿW@GÿX@GÿXAHÿXAHÿXAIÿYAIÿYBJÿYBJÿZBKÿZCKÿZDLÿZDLÿ[DLÿ[DMÿ[DNÿ\DNÿ]DNÿ\DOÿ\DOÿ]EPÿ]FQÿ]FQÿ^GQÿ_GQÿ_FSÿ_GSÿ`GSÿ_GSÿ_HTÿ`HTÿ`HTÿaITÿ`ITÿ`ITÿ`HTÿ`HTÿ_HTÿoX]ÿybcÿdKUÿ`FRÿ`GQÿ_GQ“\EP^FP^EO3""6$'7!#7!$X7!$ô7!$ÿ7"%ÿG/3ÿG/3ÿ8#%ÿ7"%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8#&ÿ8#&ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ9$'ÿ9$'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%(ÿ;%(ÿ;%(ÿ;%(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&)ÿ<&)ÿ<&)ÿ<&)ÿ<&)ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ='*ÿ>'*ÿ>'*ÿ>(+ÿ>)+ÿ>(*ÿ>(*ÿ>(*ÿ>(+ÿ>(+ÿ?(+ÿ?(+ÿ@(+ÿ@(,ÿ?(,ÿ?),ÿ?),ÿ?*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@),ÿ?(,ÿ?(,ÿ@)+ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ?*-ÿ?*-ÿ?*.ÿ?*.ÿ?*.ÿ@*-ÿ@*.ÿA*.ÿA).ÿA).ÿA).ÿA*/ÿ@+0ÿA+0ÿB+0ÿB+1ÿB+1ÿB+1ÿE/1ÿH12ÿI12ÿI02ÿI03ÿI24ÿI24ÿJ24ÿJ25ÿJ35ÿK35ÿL46ÿL47ÿL47ÿL47ÿM58ÿM68ÿN69ÿO6:ÿO6:ÿP7:ÿP7;ÿP7;ÿP8<ÿP8>ÿQ9>ÿR9>ÿS:>ÿS:>ÿS;?ÿT;?ÿT;?ÿT;@ÿS;@ÿT;@ÿU;AÿU;AÿUCÿV>CÿW>CÿW?EÿW?EÿW?FÿW?FÿW@FÿW@GÿX@GÿXAHÿXAHÿXAIÿYAIÿYBJÿYBJÿYBKÿZCKÿZDKÿZCLÿ[DLÿ[DMÿ[DMÿ[DNÿ\DNÿ\DOÿ\DOÿ]EPÿ]EPÿ]FQÿ]GQÿ^GQÿ^FRÿ_GSÿ`GSÿ_GSÿ_HSÿ_HTÿ_HTÿ_HTÿ`ITÿ`HSÿ`HTÿ`HTÿ_HTÿaHTÿu^`ÿt]_ÿ`GRÿ`GQÿ_GQõ^FQZ`FR\CKbKK6#$6"$6"$!6"$Ò6"$ÿ6"$ÿA+.ÿK37ÿ9%'ÿ6"$ÿ7"$ÿ7"%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8#&ÿ8#&ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ9$'ÿ:%'ÿ:%'ÿ:$&ÿ:%'ÿ:%'ÿ:$&ÿ:$&ÿ:$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%'ÿ<%(ÿ<&(ÿ<%)ÿ<&(ÿ<&)ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ>'*ÿ='*ÿ>'+ÿ>(+ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ>(+ÿ>(+ÿ?(+ÿ@(+ÿ@(+ÿ?(,ÿ?(,ÿ?),ÿ?*,ÿ>*+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ?(+ÿ>(+ÿ>'+ÿ>(+ÿ>)+ÿ>(+ÿ>(,ÿ>(,ÿ>(+ÿ>'+ÿ>',ÿ>',ÿ>(+ÿ=(+ÿ=(+ÿ=(+ÿ=(,ÿ<(,ÿ<(+ÿ<(+ÿ=(,ÿ>(,ÿ>',ÿ>',ÿ='-ÿ<(-ÿ=)-ÿ>).ÿ?).ÿ?).ÿ>).ÿA,.ÿE//ÿE.0ÿE.0ÿE.0ÿE/1ÿF02ÿF02ÿG03ÿG03ÿG13ÿH24ÿI25ÿI25ÿJ26ÿJ36ÿK47ÿL57ÿL58ÿM59ÿN69ÿN6:ÿO6:ÿO7;ÿO7<ÿP8=ÿQ8>ÿR9>ÿR:>ÿS;?ÿT;?ÿT;?ÿT;@ÿS;@ÿS;@ÿU;AÿU;AÿUCÿV>CÿW>CÿW?DÿW?EÿW?EÿW?FÿW?FÿW?GÿX@GÿXAHÿXAHÿXAIÿYAIÿYBIÿYBJÿYBJÿZCKÿZCKÿZCLÿ[CLÿ[DMÿ[DMÿ[DNÿ\DNÿ\DOÿ\DOÿ]EPÿ]EPÿ]EQÿ]FQÿ^GQÿ^FQÿ^GRÿ_GSÿ`GSÿ_GSÿ_GSÿ_HSÿ_HSÿ_GSÿ`GSÿ`HSÿ_HSÿ_GSÿ_GSÿdKUÿyccÿlUZÿ_GQÿ_GQÿ_FQÓ_EP"_FP^EN3#6"$7##6"$“6"$ÿ6"$ÿ;&)ÿM39ÿ>(+ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#&ÿ8#&ÿ8$%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#&ÿ9#&ÿ9#&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$'ÿ;$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ>&)ÿ=&*ÿ='*ÿ>'+ÿ>'*ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ>(+ÿ>(+ÿ?(+ÿ?(+ÿ?'+ÿ>'+ÿ>(+ÿ=)+ÿ=)+ÿ=)*ÿ=(*ÿ>(*ÿ>(*ÿ='*ÿ<&)ÿ<&)ÿ;&)ÿ;')ÿ;')ÿ<')ÿ;&)ÿ;&*ÿ;&)ÿ;%*ÿ;%)ÿ:&)ÿ;%)ÿ;%)ÿ<%)ÿ;&(ÿ;%(ÿ<%)ÿ<%)ÿ<%)ÿ=%)ÿ=%)ÿ=%)ÿ<%)ÿ<%)ÿ=&)ÿ>&*ÿ?&+ÿ?&+ÿ>&+ÿ@)+ÿD+,ÿD+,ÿC+,ÿD+-ÿD+.ÿE,.ÿE-/ÿE-/ÿE-0ÿE.0ÿE/1ÿF/2ÿF/2ÿF03ÿG13ÿG14ÿH25ÿI26ÿJ36ÿK47ÿL48ÿM59ÿM59ÿN6:ÿN7;ÿO7<ÿP8=ÿQ8=ÿR:>ÿS:>ÿS;?ÿT;?ÿS;@ÿS;@ÿT;@ÿT;AÿUCÿV>CÿV>CÿW>DÿW?DÿW?EÿW?FÿW?FÿW?GÿW?GÿX@HÿXAHÿXAIÿYAIÿYBIÿYBJÿYBJÿZCKÿZCKÿZCLÿZCLÿ[DMÿ[DMÿ[DNÿ\DNÿ\DOÿ[DOÿ\EPÿ]EPÿ]EQÿ]FQÿ^FQÿ^GQÿ^FQÿ^GRÿ_GSÿ`GSÿ`GSÿ`GSÿ`GSÿ`GSÿ`GSÿ_GSÿ_GSÿ_GRÿ`GSÿ_FRÿiQXÿzdcÿeNUÿ^FQÿ_FQÿ_FP”]FK^FN\CJ7$%6"$5"$E6"$ð6"$ÿ7#%ÿI15ÿE.2ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"%ÿ8"%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#&ÿ9#&ÿ9#&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$'ÿ;$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ>&)ÿ=&)ÿ=&*ÿ='*ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ=')ÿ=')ÿ=')ÿ='*ÿ>'*ÿ='*ÿ=&*ÿ<&*ÿ<'*ÿ;')ÿ;')ÿ:'(ÿ;'(ÿ;&(ÿ:%(ÿ9%'ÿ9$'ÿ9$&ÿ8$&ÿ9$'ÿ:$&ÿ;$&ÿ;$&ÿ<#&ÿ<#'ÿ<#'ÿ<#&ÿ<#&ÿ<#&ÿ="&ÿ="%ÿ<#&ÿ<#&ÿ<#&ÿ=#'ÿ=#'ÿ=$'ÿ<$(ÿ<$)ÿ<%)ÿ<%)ÿ=%)ÿ=%*ÿ=&*ÿ>&*ÿ?'*ÿC*+ÿC*+ÿC)*ÿC(*ÿC)*ÿD*+ÿE*,ÿE*-ÿE*-ÿF+-ÿF,-ÿG+.ÿF,.ÿF,/ÿF-/ÿF.0ÿF/1ÿF/3ÿF03ÿG14ÿH25ÿI26ÿJ37ÿK48ÿL59ÿM6:ÿN6;ÿN7;ÿO8<ÿQ9=ÿR:>ÿS:?ÿR;?ÿR;?ÿS;@ÿT;@ÿTCÿV>CÿV>CÿV>CÿV?DÿW?DÿW?FÿW?FÿW?GÿW?GÿX@HÿWAHÿXAHÿXAIÿYBHÿYBIÿYBJÿZBKÿZCKÿZCLÿZBLÿ[CMÿ[DMÿ[DNÿ\DNÿ\DNÿ[DOÿ[DOÿ]EPÿ]EPÿ]EQÿ]FQÿ^FQÿ^GQÿ^FQÿ^GRÿ_GSÿ_GSÿ`GSÿ_GSÿ_GSÿ_GSÿ_FSÿ_GRÿ`GRÿ`GQÿ_FRÿ_FRÿq[]ÿu__ÿ_GRÿ^FQÿ_FPð^EPF_FP_FR6!#5"$5"$5"$¶5"$ÿ5"$ÿA*.ÿL38ÿ9$'ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6!#ÿ7!$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#&ÿ9#&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ;$&ÿ;$'ÿ;$'ÿ;$'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ;%'ÿ<%'ÿ<%'ÿ<%(ÿ<%(ÿ<%(ÿ<%(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ>&(ÿ=&)ÿ=&*ÿ='*ÿ<&)ÿ=%(ÿ=%(ÿ=&(ÿ<&(ÿ<&(ÿ;%'ÿ<%'ÿ;%(ÿ;%(ÿ:$(ÿ:$(ÿ9%(ÿ8%'ÿ8%'ÿ7%&ÿ8$&ÿ9$%ÿ9#%ÿ9"$ÿ:"$ÿ:!$ÿ:"#ÿ:!$ÿ:"$ÿ;"$ÿ;#$ÿ:#%ÿ:#&ÿ:%'ÿ9%'ÿ8%(ÿ9&)ÿ9%(ÿ9%(ÿ9&)ÿ8')ÿ8')ÿ9'*ÿ9'*ÿ9'+ÿ9'+ÿ9'+ÿ8(,ÿ8(,ÿ9(+ÿ9(,ÿ9)-ÿ:)-ÿ;*-ÿ>--ÿ?--ÿ>,-ÿ>+-ÿ>,.ÿ?,.ÿ@-.ÿA-/ÿA,/ÿA-/ÿB-/ÿC,.ÿC-/ÿD+.ÿD,.ÿE,-ÿF,-ÿG,.ÿG,0ÿG-0ÿG.2ÿG/2ÿG03ÿG15ÿH26ÿI37ÿJ48ÿL59ÿL6:ÿN7<ÿP8<ÿQ9=ÿQ9>ÿQ:>ÿR:?ÿS:?ÿS;@ÿTCÿV>CÿV>CÿV?DÿV?DÿW?EÿW?FÿW?GÿW?GÿX?GÿW@HÿWAHÿXAIÿYBHÿYBIÿYBIÿZBJÿZCKÿZCLÿZBLÿZCLÿ[CMÿ[DMÿ[DNÿ\DNÿ\DOÿ[DOÿ[EPÿ]EPÿ]EPÿ]EQÿ]FQÿ^FQÿ^GQÿ^FQÿ^FQÿ_FRÿ_FSÿ_FSÿ_FSÿ_FRÿ_GRÿ_GRÿ_GQÿ_GQÿ_FQÿ_GQÿbKSÿxbaÿkTYÿ^FPÿ^FPÿ^EP·^DN^DO^DQ(((5"$5"$^5"$ú5"$ÿ8$'ÿM49ÿ@*-ÿ6"#ÿ6"$ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ7!#ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ<$'ÿ<$'ÿ<$'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ=%'ÿ=%'ÿ=%(ÿ=%(ÿ=%(ÿ=%(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ=&(ÿ<%)ÿ<&)ÿ;%(ÿ;%(ÿ;$'ÿ;$'ÿ:$'ÿ:$&ÿ9$&ÿ9#%ÿ8#&ÿ7"&ÿ7"%ÿ7"%ÿ8"$ÿ8!$ÿ9!#ÿ9!#ÿ:!#ÿ:!#ÿ:!#ÿ9"$ÿ8"%ÿ8#%ÿ7$&ÿ7%'ÿ7%'ÿ7%(ÿ7&(ÿ7&(ÿ7&(ÿ7')ÿ7')ÿ6')ÿ7')ÿ7&)ÿ7&)ÿ8&)ÿ8&(ÿ8&(ÿ8&)ÿ9&)ÿ8&)ÿ9&)ÿ9&)ÿ8&*ÿ9&*ÿ9&)ÿ8&*ÿ8&*ÿ9'*ÿ:(*ÿ=*+ÿ?+,ÿ>+,ÿ=+,ÿ>+,ÿ>+-ÿ?+-ÿ?,-ÿ?,.ÿ?,.ÿ?-/ÿ?.0ÿ@.0ÿ@.0ÿ@.0ÿ@/0ÿB/0ÿB.0ÿC.0ÿD-0ÿE-0ÿG-0ÿG-0ÿH-1ÿH/2ÿH03ÿH15ÿH26ÿI37ÿJ49ÿL5:ÿN7;ÿO8<ÿO8=ÿQ9>ÿR9>ÿR:?ÿS;@ÿTCÿV>CÿV?DÿV?DÿW?EÿW?EÿW?FÿW?GÿX?GÿW@HÿW@HÿWAIÿXAHÿYBIÿYBIÿYBIÿZCJÿZCKÿZCLÿZBLÿ[CMÿ[CMÿ[DNÿ\DNÿ\DNÿ\DOÿ[DOÿ\EPÿ]EPÿ]EQÿ]EQÿ]FQÿ^FQÿ^GQÿ^GQÿ^GQÿ_FQÿ_FRÿ_GRÿ_GRÿ_GRÿ^GQÿ^GQÿ^FQÿ_GQÿ_GQÿ^FQÿjRXÿxbaÿaJRÿ]EPÿ^EOú^EO_^EN9l;('5!#5 #5!#Å5"#ÿ5"$ÿD-2ÿJ16ÿ7"$ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ7!#ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ9"$ÿ9"$ÿ9"$ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ<$'ÿ<$'ÿ<$'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ=%'ÿ=%'ÿ=%(ÿ=%(ÿ=%(ÿ=%(ÿ<%(ÿ<%'ÿ=%'ÿ=%'ÿ<%'ÿ;%'ÿ:$'ÿ9#&ÿ8#&ÿ8#%ÿ7"%ÿ7"$ÿ7"$ÿ7!#ÿ8!"ÿ8 #ÿ8#ÿ9"ÿ9 "ÿ8 #ÿ8!#ÿ7"$ÿ7$&ÿ6$&ÿ6%'ÿ6%'ÿ6%'ÿ5%'ÿ6%'ÿ6%'ÿ6%'ÿ7%'ÿ7%'ÿ7%&ÿ7%&ÿ7$'ÿ7%'ÿ7$&ÿ7$&ÿ7$&ÿ7$&ÿ7$%ÿ7$%ÿ7#&ÿ7#&ÿ7#&ÿ7#&ÿ7#&ÿ7#&ÿ7#&ÿ7$&ÿ7$&ÿ7$&ÿ7$'ÿ7$'ÿ7$'ÿ:'(ÿ<((ÿ<'(ÿ<'(ÿ<()ÿ=()ÿ=()ÿ=(*ÿ=)*ÿ>)+ÿ>*,ÿ?+-ÿ?+-ÿ?,.ÿ?,.ÿ?-.ÿ@./ÿ@.0ÿA.0ÿA/1ÿA/2ÿB/2ÿC/2ÿD.2ÿE.1ÿG.1ÿH-1ÿI.2ÿI/3ÿH15ÿI26ÿI38ÿK59ÿL6:ÿN7;ÿO8<ÿP9=ÿQ:?ÿR;?ÿT;AÿUCÿV?DÿV?DÿV?EÿW?EÿW?EÿW?FÿX?GÿX?HÿW@HÿW@IÿXAIÿXBHÿYBIÿYBIÿZBJÿZCJÿZCLÿYBLÿZCMÿZCMÿ[CMÿ[DNÿ\DNÿ\DOÿ[DNÿ[DOÿ\EPÿ]EPÿ]EPÿ]EQÿ]EQÿ]FQÿ]GQÿ^GQÿ^GQÿ^GQÿ_GRÿ^GQÿ^GQÿ^FQÿ^FQÿ^FQÿ^FQÿ^FQÿ^FPÿ_GQÿu^_ÿnX[ÿ]EPÿ^EOÿ^EOÅ^DO^DN]DMD956!#8$%c6!#û5 "ÿ:%'ÿN49ÿ<'*ÿ5!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ7!#ÿ8!#ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9"$ÿ9"$ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ<$'ÿ<$'ÿ<$'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ<%'ÿ=%'ÿ=%'ÿ<%'ÿ<$'ÿ<$'ÿ;$'ÿ;$&ÿ;$&ÿ;$&ÿ:#&ÿ9#%ÿ8#%ÿ7"$ÿ7!$ÿ7 #ÿ8 "ÿ9!ÿ9!ÿ9!ÿ9 "ÿ8!#ÿ6!$ÿ6"%ÿ5$&ÿ5$&ÿ5$&ÿ5$&ÿ5$&ÿ6$&ÿ6$&ÿ6#%ÿ6#%ÿ6#%ÿ6#%ÿ6#%ÿ5"$ÿ6"$ÿ5"$ÿ5"#ÿ5"#ÿ5"$ÿ5"$ÿ4"$ÿ4"#ÿ4"$ÿ3!#ÿ3!#ÿ3!#ÿ3!#ÿ3!#ÿ4!#ÿ4!$ÿ4!$ÿ3!$ÿ3!$ÿ3!$ÿ4!$ÿ4!$ÿ4!%ÿ4!%ÿ4"$ÿ6$%ÿ8%&ÿ8%&ÿ8%&ÿ8%&ÿ9%&ÿ9&&ÿ9&'ÿ9&'ÿ:&(ÿ;'(ÿ<')ÿ=(*ÿ=(*ÿ=)+ÿ=*+ÿ>*+ÿ?+,ÿ@+-ÿ@,.ÿ@-/ÿA-0ÿA.1ÿA/2ÿA03ÿB03ÿC03ÿE/3ÿG.2ÿH.2ÿI.2ÿI/4ÿI16ÿH37ÿJ48ÿL5:ÿM7;ÿO8=ÿP9>ÿR:?ÿS;@ÿTCÿV?DÿV?DÿW?EÿW?EÿW?FÿW?FÿX?GÿW@HÿW@HÿW@IÿXAHÿXBIÿYBIÿYBJÿZCJÿZCKÿZCLÿZBLÿZCMÿZCMÿ[CNÿ[DNÿ\DNÿ\DOÿ[DNÿ[DOÿ\EPÿ\EPÿ]EPÿ]EQÿ]EQÿ]EQÿ]FQÿ]FQÿ]GQÿ^FQÿ^FQÿ^FQÿ^FQÿ^FQÿ^FQÿ]FQÿ]EPÿ^FPÿ^FOÿfOUÿxbaÿcJRÿ^EOÿ^EOü]DNd^DN\DI<'&;'';(':&&Â9$%ÿ6!#ÿF-1ÿH04ÿ5!#ÿ5!#ÿ5!#ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ8!#ÿ8!$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9"$ÿ9"$ÿ9"%ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:#&ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ<$'ÿ<$'ÿ<$'ÿ<$'ÿ<%'ÿ<%'ÿ;%'ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ:#&ÿ9#%ÿ8"%ÿ8"$ÿ7"$ÿ6!$ÿ7!#ÿ7 "ÿ8!ÿ9!ÿ9!ÿ8!ÿ7 "ÿ7!#ÿ6"$ÿ6$%ÿ5$&ÿ5$&ÿ5#&ÿ5$&ÿ5#%ÿ6#%ÿ5#$ÿ5"$ÿ5!$ÿ5!#ÿ5!"ÿ4 "ÿ4 "ÿ3 "ÿ3 "ÿ2 "ÿ2"ÿ2 "ÿ2 "ÿ3 "ÿ3!#ÿ5##ÿ6%%ÿ8&&ÿ;)(ÿ=+*ÿ@-,ÿB0.ÿE31ÿH63ÿJ96ÿL;8ÿM=:ÿO?=ÿO?=ÿP@?ÿQA?ÿQB@ÿQA@ÿQ@@ÿP??ÿP??ÿP??ÿN=>ÿM<<ÿL:<ÿI8:ÿG57ÿD25ÿB03ÿ?-0ÿ=*-ÿ<)+ÿ;(*ÿ:')ÿ:&(ÿ9'(ÿ:'(ÿ;()ÿ<(*ÿ=)*ÿ>*+ÿ?*,ÿ@+.ÿ@,/ÿ@-0ÿ@.1ÿA/2ÿB03ÿB04ÿC14ÿE03ÿG.2ÿH.2ÿI/3ÿI15ÿI26ÿJ48ÿK6:ÿM7;ÿO8=ÿP9>ÿR;@ÿS;AÿTCÿV?DÿW?EÿW?EÿW?FÿW?FÿX?GÿW@HÿW@HÿW@IÿX@IÿXBHÿXBIÿYBIÿZBJÿZCJÿZCKÿYBLÿZCLÿZCMÿZCMÿ[CNÿ[DNÿ\DNÿ\DOÿ[DNÿ[DOÿ[EPÿ\EPÿ]EPÿ]EPÿ]EPÿ]EQÿ]FQÿ]FQÿ]FPÿ]FPÿ^FQÿ^FQÿ^FQÿ]FQÿ]EPÿ]EPÿ]EPÿ]EOÿ^FOÿr\]ÿoX[ÿ^EOÿ]DNÿ]DNÃ\DM]DM]BL7#%:&&:&&S:&&ø:&&ÿ>)*ÿP6;ÿ<&)ÿ5 "ÿ5!#ÿ5!#ÿ6!#ÿ6!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ8!#ÿ8!$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9"$ÿ9"$ÿ9"%ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:#&ÿ:#&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$&ÿ;$'ÿ<$'ÿ<$'ÿ;$&ÿ;$&ÿ:$&ÿ:$&ÿ9#%ÿ9#%ÿ9"$ÿ7"$ÿ6!$ÿ6 #ÿ6 "ÿ7!ÿ7!ÿ8!ÿ8!ÿ7!ÿ6!"ÿ5"$ÿ4#%ÿ4#%ÿ4#%ÿ5#%ÿ6#$ÿ6"$ÿ5"$ÿ5!#ÿ5!#ÿ4!"ÿ4 "ÿ4 "ÿ3"ÿ2"ÿ2!ÿ2!ÿ2!ÿ4!!ÿ6#"ÿ;(&ÿ?-)ÿE3-ÿK:2ÿPA7ÿUH=ÿaVIÿkdTÿlkVÿru_ÿw~fÿ{…lÿ~Œqÿ‚“vÿ…˜zÿˆž~ÿŠ¢€ÿ‹¥‚ÿލ„ÿ¤²˜ÿš¥Œÿ“ ƒÿ•¡ƒÿ–¢ƒÿ–¡ƒÿ• ‚ÿ”Ÿ‚ÿ”ž�ÿš�~ÿ›™|ÿ–•|ÿŽ’}ÿ‹Ž|ÿˆˆxÿ…‚uÿ�|rÿ|umÿukhÿocbÿgZ[ÿaRVÿWHKÿN>BÿG6:ÿA/3ÿ=+.ÿ;(*ÿ:')ÿ;')ÿ<'*ÿ=(+ÿ>),ÿ>+-ÿ@,.ÿA-0ÿA.1ÿB/2ÿB03ÿC14ÿD04ÿE14ÿG/3ÿI/3ÿJ04ÿI26ÿI48ÿK5:ÿM7<ÿO8=ÿP:?ÿR;@ÿTCÿV?DÿW?EÿW?EÿW?FÿW?FÿX?GÿW@HÿW@HÿW@IÿXAHÿXAIÿXBIÿYBJÿZCJÿZCJÿZCKÿYBLÿZCMÿZCMÿZCMÿ[CNÿ[DNÿ\DNÿ\DOÿ\DOÿ[DNÿ[DOÿ\EPÿ\EPÿ]EPÿ]EPÿ]EPÿ]FPÿ]FPÿ]FPÿ]FPÿ]FPÿ]EPÿ]EPÿ]EPÿ]EPÿ]EOÿ\DOÿ\DOÿeMTÿxbaÿbJQÿ]DNÿ]DOø]DMT]DNXBN;'&;'&:&&­:&&ÿ:&&ÿI24ÿN69ÿ9$%ÿ6!"ÿ6!"ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ8!#ÿ8!$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9"$ÿ9"$ÿ9"%ÿ9"%ÿ9#%ÿ9#%ÿ9#&ÿ:#%ÿ:#&ÿ:#&ÿ:#&ÿ:#&ÿ:#&ÿ:#'ÿ:$'ÿ;$'ÿ;$'ÿ;$'ÿ;$'ÿ;$'ÿ;$'ÿ:$'ÿ:$'ÿ;#'ÿ:#&ÿ9#&ÿ9#%ÿ8#%ÿ7"$ÿ6!#ÿ5!"ÿ6 "ÿ6!ÿ7!ÿ8 ÿ8 ÿ6"ÿ5"$ÿ4#$ÿ4#$ÿ4#$ÿ4#$ÿ5"$ÿ5"$ÿ5!#ÿ5 "ÿ5 "ÿ4 "ÿ3!ÿ2!ÿ1 ÿ1 ÿ2 ÿ4!!ÿ9%#ÿ?+&ÿG4+ÿO>3ÿYK<ÿdZIÿtmYÿotZÿr€bÿt‹kÿt’qÿs™vÿy£€ÿ¥Åªÿ–ͧÿ‹Í¡ÿ‹Ñ¤ÿ‹Ô¥ÿŠÖ¥ÿ‹×¤ÿŒ×£ÿ�×¢ÿŽØ¡ÿ�ØŸÿ‘מÿ’×›ÿ©Þ®ÿ´×²ÿ˜Å’ÿšÆ‘ÿšÅ�ÿšÅ�ÿ›ÅŽÿœÅ�ÿžÅŒÿ­Ä…ÿ·Ã�ÿ®Á‚ÿ¢½„ÿŸ»„ÿ¡ºƒÿ¢¸ƒÿ£¶�ÿ¥´�ÿ¦±‚ÿ¥®�ÿ£¨€ÿ°±–ÿ£¢…ÿŽŒlÿ†€kÿ|shÿqebÿdVYÿWHNÿM+0ÿ;(,ÿ;(*ÿ<)+ÿ=*,ÿ?*-ÿ@,.ÿA-0ÿB.1ÿC/2ÿC14ÿB15ÿD15ÿG04ÿI/3ÿJ04ÿJ26ÿJ48ÿK6:ÿM7<ÿO9>ÿQ:?ÿS;AÿT=BÿU=CÿV?DÿW?EÿW?FÿW?FÿW?FÿW@GÿW@HÿW@IÿX@IÿXAHÿXAIÿXBIÿYBJÿZCJÿZCJÿZCKÿYBLÿZCMÿZCMÿZCMÿ[CNÿ[DNÿ\DNÿ\DNÿ\DOÿ[DOÿ[DOÿ[DOÿ\DOÿ\EOÿ\DPÿ\EPÿ\EOÿ\EOÿ\EOÿ]EOÿ]EPÿ]EPÿ]EOÿ]EOÿ\DOÿ\DOÿ]DOÿ^EOÿs\]ÿmVYÿ]DNÿ]DNÿ]DN®\CM\CM<&&;&&;'&4:&&ë:&&ÿ>()ÿS9=ÿD-.ÿ;&&ÿ:%%ÿ7"#ÿ6!"ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ8!#ÿ8!$ÿ8"$ÿ8"$ÿ8"%ÿ8"%ÿ8"%ÿ8"%ÿ9#%ÿ9#%ÿ9#%ÿ9#&ÿ9#&ÿ9$&ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$'ÿ:$'ÿ:$'ÿ;%'ÿ;%'ÿ;%'ÿ:%'ÿ:$&ÿ9$&ÿ9$&ÿ8#&ÿ8#%ÿ7"%ÿ6"$ÿ5!#ÿ5!#ÿ5 "ÿ6!ÿ7 ÿ7 ÿ6"ÿ5!#ÿ4"$ÿ4"%ÿ4#%ÿ4#$ÿ5"#ÿ5!#ÿ4!"ÿ4 !ÿ3!ÿ2 ÿ2 ÿ1 ÿ2 ÿ4!!ÿ:&#ÿB.'ÿM;.ÿXJ9ÿc[HÿmnYÿv‚lÿ{“}ÿ~¢�ÿ­šÿ¶¥ÿ¢Ì¼ÿ€¿ ÿj¹•ÿg¸“ÿcµ�ÿc¶�ÿ“гÿžâÁÿ‚Ü®ÿ‚Ü­ÿƒÜ«ÿƒÜ©ÿ„ܧÿ†Û¥ÿˆÚ£ÿŠÚ¡ÿŒÙŸÿ�ÙžÿŽÙœÿ�Ùšÿ•Ûžÿ¹á»ÿ›Ê˜ÿ•Æ�ÿ—Æ�ÿ˜Å�ÿšÅŒÿœÅŠÿ�ʼnÿ®Ä‚ÿ³Ã~ÿªÁÿ©¿~ÿ©¾~ÿ¦½|ÿ£»{ÿ¤ºyÿ¦¹wÿ¨¹uÿª¸sÿ¬·qÿ·¿‚ÿÄÊ’ÿ¥¬Tÿ¦©Uÿ¦§Yÿ¥¢^ÿ¡œdÿ˜�gÿŽ„jÿ€uiÿqdcÿaSXÿQBIÿF4;ÿ>,1ÿ;),ÿ<)+ÿ=*,ÿ?+-ÿA,/ÿA.1ÿB/2ÿC03ÿC15ÿD15ÿG15ÿI04ÿK04ÿK27ÿJ49ÿK6;ÿM8<ÿP9?ÿR;AÿSDÿV?EÿW?FÿW?FÿW?GÿW@GÿW@HÿW@IÿXAHÿXAIÿXAIÿXBIÿYCJÿZCJÿZCKÿZCKÿYBLÿZCMÿZCMÿZCMÿ[CNÿ[CNÿ\DNÿ\DNÿ\DNÿ\DOÿ\DOÿ\DOÿ\DOÿ]DOÿ\DOÿ]DOÿ]DOÿ]EOÿ]EOÿ]ENÿ]EOÿ\EOÿ\DOÿ]DOÿ]DOÿ]DOÿ\CNÿfOTÿw`_ÿ`GOÿ]DNÿ]DNë\DM4\DM[DL<&%9&&:&&�;&&ÿ;&&ÿF/0ÿR8<ÿ=''ÿ;&&ÿ;&&ÿ:%&ÿ8#$ÿ6!"ÿ6!#ÿ6!#ÿ6!#ÿ6!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!$ÿ7!$ÿ7"$ÿ8"$ÿ8"$ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#&ÿ9$&ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$'ÿ:$'ÿ:$'ÿ:$&ÿ9$&ÿ9$%ÿ8#%ÿ7#$ÿ6"$ÿ5!#ÿ5 #ÿ5"ÿ6!ÿ7 ÿ6 ÿ6 !ÿ4!#ÿ4#$ÿ4#$ÿ4#$ÿ5"$ÿ4"$ÿ4!#ÿ4!"ÿ3 !ÿ2!ÿ1 ÿ1ÿ2ÿ5"!ÿ=*%ÿI7,ÿVG9ÿd\Kÿps`ÿx‰vÿ}œŠÿ¬œÿ}¶ªÿ{½´ÿwÁºÿtĽÿsžÿqžÿożÿŠÐÇÿ’Ñ»ÿb¼˜ÿa¹”ÿ_µŽÿ�Ʀÿ¥âÄÿ„ܰÿ‚Û¬ÿƒÜ«ÿƒÜ©ÿ„ܧÿ…Û¥ÿ‡Û£ÿˆÛ¢ÿ‰Ú ÿŠÚžÿ‹Ú�ÿ�Ú›ÿ�Ùšÿ�Ù—ÿ®á²ÿ¬Ó¨ÿ–ÅŽÿ˜ÅŽÿšÅŒÿœÅ‹ÿ�ʼnÿŸÅˆÿ®Ã�ÿ¬Áÿ©Àÿ«¿~ÿ­¾|ÿ®¾zÿ®½yÿ«»xÿª¹vÿ©¸tÿ«·rÿ­·pÿ°·pÿÈÌ—ÿ±µaÿ§ªHÿªªGÿ«©Eÿ­¨Dÿª¢Bÿª¡EÿªŸLÿ§›Uÿ¡”`ÿ¦›‡ÿ–Š€ÿyjjÿ`QYÿLÿQ:@ÿS;BÿU=CÿV>DÿV?EÿW?FÿW?FÿW@GÿW@GÿW@HÿX@IÿXAHÿXAIÿXAIÿXBIÿZCJÿZCJÿZCKÿZCKÿYBLÿZCMÿZCMÿZCMÿ[CMÿ[CNÿ[DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ]DOÿ]DOÿ]DNÿ]DNÿ]DNÿ]ENÿ\ENÿ\DNÿ\DNÿ]DOÿ]DOÿ]DOÿ]DNÿ\DNÿ^FOÿu_^ÿiQUÿ\CMÿ\DMÿ\DM�]DN[DM333;'';'':&&È:&&ÿ;&'ÿQ7:ÿJ23ÿ;&&ÿ;&&ÿ;&&ÿ;&&ÿ;&&ÿ9$$ÿ7!"ÿ6!"ÿ6!#ÿ6!#ÿ6!#ÿ7!$ÿ7!$ÿ7!$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#&ÿ9$&ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9#&ÿ8#&ÿ8#%ÿ8#%ÿ7"$ÿ6"#ÿ4!#ÿ4 "ÿ4!ÿ6 ÿ6 ÿ6!ÿ5 "ÿ3"$ÿ3#$ÿ3#$ÿ4"$ÿ4"#ÿ4!"ÿ4 !ÿ3!ÿ1!ÿ0 ÿ1 ÿ4!!ÿ=*%ÿM:1ÿ`PBÿlgWÿv€qÿ|˜Šÿ}© ÿ{¶±ÿx½¼ÿuÁÃÿrÄÆÿpÄÇÿoÄÅÿoÄÄÿoÅÂÿpÅÀÿpžÿpŽÿqÅ»ÿvȼÿ ØÉÿoÀžÿ`·�ÿq¾›ÿ§ÞÃÿŠÞ´ÿ�Û¬ÿ‚ܪÿ‚Ü©ÿƒÜ¦ÿ„Ü¥ÿ…Ü£ÿ†Ü¢ÿˆÛ ÿŠÚžÿ‹Ú�ÿŒÚœÿŽÙšÿ�Ù˜ÿ‘Ø–ÿ�Û ÿºÝ·ÿšÆ�ÿ™ÅŒÿ›Å‹ÿœÅŠÿžÅˆÿ Ä†ÿ¨Á�ÿ©Àÿª¿~ÿ¬¾|ÿ®¾{ÿ¯½yÿ±½xÿ²½vÿ³¼uÿ±ºsÿ¯¸qÿ¯¶oÿ°µkÿÀÃ…ÿÂÄ‚ÿ©©Gÿ«©Fÿ­¨Dÿ®§Bÿ«¡=ÿ¬¡;ÿ®¡9ÿ°Ÿ6ÿ¿°YÿÝÐ�ÿÔÁhÿË·mÿ»¨wÿ¡�yÿƒtqÿeV^ÿN>FÿA/5ÿ=*-ÿ=*,ÿ?+.ÿA-0ÿB.2ÿC04ÿD15ÿE26ÿG26ÿJ04ÿJ15ÿJ37ÿJ6:ÿM8=ÿP:?ÿR;AÿTDÿV>EÿV?EÿW?GÿW@GÿW@GÿW@HÿX@HÿXAHÿXAIÿXAIÿXBJÿYCJÿZCJÿZCKÿZCKÿYBLÿZCLÿZCMÿZCMÿ[CMÿ[CMÿ[DNÿ[DNÿ[DNÿ[DNÿ[DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ]DOÿ]DOÿ]DNÿ\DNÿ\DNÿ\DMÿkTWÿs[\ÿ]EMÿ\DLÿ\DLÉ[CK[DK333<&&:&&:&&A:&&ó:&&ÿ?*+ÿU;?ÿ@*+ÿ;&&ÿ;&&ÿ;&&ÿ;&&ÿ;&&ÿ;&&ÿ:%%ÿ7"$ÿ6!#ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ:#%ÿ9#%ÿ:#&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:#%ÿ9#%ÿ8"%ÿ7"%ÿ6!$ÿ6!#ÿ5!"ÿ4 !ÿ5 ÿ6ÿ6ÿ5!ÿ4!#ÿ3"$ÿ4"$ÿ4"$ÿ4"#ÿ4!"ÿ3 !ÿ2 ÿ1 ÿ1ÿ2 ÿ8%#ÿD1+ÿXH<ÿvl\ÿŒŽxÿ—ª�ÿ§Ä¯ÿ¬ÑÄÿ©ÖÑÿ ××ÿ–ÔØÿ�Ñ×ÿ…ÍÔÿ~ÊÐÿyÈÌÿtÆÈÿqÅÅÿoÄÂÿoÄÀÿoľÿoļÿpÅ»ÿpƹÿpÅ·ÿ“ÓÆÿˆÌ¯ÿeº’ÿŸØ¼ÿ’à¸ÿÜ«ÿ�Ý©ÿ�ݨÿ‚ݦÿƒÜ¤ÿ„Ü£ÿ†Ü¢ÿˆÛ ÿ‰ÛŸÿ‹ÚžÿŒÚœÿŽÚšÿ�Ù™ÿ‘Ø—ÿ’Ø–ÿ”וÿ·áµÿ¨Í�ÿšÅŠÿœÅŠÿžÅ‰ÿŸÄ‡ÿ›Â‡ÿ£À�ÿª¿~ÿ¬¿}ÿ­¾{ÿ¯½yÿ°½xÿ²½wÿ´¼uÿµ¼sÿ·¼rÿ·»qÿ·¹nÿµ·kÿ·¸pÿÌÌ•ÿ°¯Sÿ¬¨Dÿ¯¨Cÿ¯¦@ÿ¬¡<ÿ®¡:ÿ¯ 7ÿ·§EÿÚ͉ÿÜÉdÿÛÃQÿÝÂQÿÞÁRÿÛ¿[ÿÒºiÿ¿«wÿ£’|ÿ�rrÿ`Q[ÿI9Aÿ?,1ÿ=),ÿ?+.ÿA-0ÿB/2ÿD04ÿD26ÿE36ÿH26ÿJ04ÿJ26ÿJ59ÿL7<ÿO9?ÿR:AÿTDÿV>EÿV?EÿW@GÿW@GÿW@GÿW@HÿX@HÿXAIÿXAIÿXAIÿXBJÿYCJÿZCJÿZCJÿZCKÿYBKÿZBLÿZCMÿZCMÿZCMÿ[CMÿ[DMÿ[DMÿ[DMÿ[DMÿ[DNÿ[DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DMÿ\DMÿ\DNÿ\DNÿ\DMÿ\DMÿaIQÿw`_ÿaJPÿ[DLÿ\DKó\CJB\CK^CJ<'&8%%:&&…:&&ÿ9&&ÿH13ÿQ8;ÿ;&'ÿ;&&ÿ;&&ÿ;&&ÿ;&'ÿ;&'ÿ;''ÿ;''ÿ;&'ÿ8$%ÿ6"#ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ9"$ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#&ÿ:$&ÿ:$&ÿ9$&ÿ9#%ÿ9#%ÿ9"$ÿ8"$ÿ7!#ÿ5 #ÿ4 "ÿ4!ÿ6 ÿ7ÿ6 ÿ5 "ÿ3"#ÿ3"$ÿ4"#ÿ4"#ÿ4!"ÿ4 "ÿ3!ÿ1 ÿ0ÿ2 ÿ:'$ÿJ7/ÿ_SDÿsvaÿ‚—~ÿ¥¾ªÿ ÓÊÿ«ÞÔÿŠÑ¹ÿ|εÿ€Ï¶ÿ†Ñ·ÿŒÔºÿ“Ö½ÿ™ØÁÿŸÛÅÿ¤ÜÉÿ¦ÝÍÿ¦ÜÏÿ£ÚÐÿžÙÐÿ˜ÖÎÿ�ÒËÿ‰ÏÇÿ‚ÍÂÿ{˼ÿuÉ·ÿ~͹ÿžØÀÿ•Ó³ÿ›â½ÿ~ܪÿÜ©ÿ€Ý¨ÿ�ݦÿƒÜ¥ÿ„ܤÿ…Ü¢ÿ‡Û¡ÿ‰ÛŸÿŠÚžÿŒÚœÿ�Ú›ÿ�Ù™ÿ‘Ø—ÿ’Ø–ÿ“וÿ”Ö’ÿ§Ü£ÿ¹Ù°ÿœÅŠÿ�ʼnÿŸÄ‡ÿœÃ‡ÿ”Àˆÿ¤¿€ÿ¬¿}ÿ­¾{ÿ®½zÿ°½xÿ²½wÿ³¼uÿ´¼tÿ¶¼rÿ¸»qÿº»oÿ»ºnÿ¼ºlÿ»¸iÿËÈ‹ÿÀ¾qÿ­§Aÿ°¨Aÿ¯¥>ÿ­¡:ÿ¯ 8ÿ³¢;ÿÒÅ~ÿÞÍsÿÚÂRÿÜÂQÿÞÁPÿßÁNÿàÂOÿàÃQÿàÃTÿÜÁ_ÿѺoÿº§}ÿ—ˆ}ÿrelÿSCNÿA06ÿ=*-ÿ?+.ÿA-0ÿC/3ÿD15ÿD36ÿF36ÿI15ÿK15ÿJ48ÿJ6;ÿN8>ÿQ:@ÿSEÿV?FÿW@GÿW@GÿW@HÿW@HÿX@HÿXAIÿXAIÿXAIÿXBIÿYBJÿZCJÿZCJÿZCKÿZCKÿYBLÿYBLÿZCLÿZCMÿ[CMÿ[DMÿ[DMÿ[DMÿ[DMÿ[DMÿ[DNÿ\DNÿ\DNÿ\DNÿ\DNÿ\DMÿ[DMÿ[DMÿ[DMÿ\DMÿ\DMÿ\DMÿ\CMÿ\DMÿr\\ÿiSUÿ[CKÿ\DKÿ\DK…^FLZBJ;'&;'& :&&À:&&ÿ;&'ÿQ8;ÿH13ÿ9&&ÿ:&'ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ9%&ÿ7#$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ7"$ÿ7!#ÿ5!"ÿ4 !ÿ4 ÿ5ÿ6ÿ5 ÿ4 "ÿ3"#ÿ3"$ÿ4"#ÿ4!"ÿ3 !ÿ3 ÿ1ÿ0ÿ2 ÿ:&$ÿJ80ÿ`WHÿw~jÿ…¡Šÿм¦ÿ†Ë¸ÿ—ÙËÿ¦ãáÿwÕ×ÿ“ÝÜÿšÚÉÿx̱ÿy̰ÿyÍ®ÿyͬÿy̪ÿyͨÿyΧÿ{Φÿ~Ϧÿ‚Ѧÿ‡Ó§ÿ�Õ©ÿ“Ø­ÿšÛ±ÿ Ý¶ÿ¤Þ»ÿ¦ß¿ÿ¦ÞÂÿ¤ÝÃÿ¿çÔÿÁëÔÿ å¿ÿ–ã¸ÿ‘á³ÿ‹à¯ÿˆÞªÿ†Ý¦ÿ…Ü£ÿ†Û ÿ‡Úžÿ‰Ú�ÿ‹ÚœÿŒÚ›ÿ�Ù™ÿ�Ù—ÿ’Ø—ÿ“וÿ•דÿ–Ö’ÿš×”ÿ¾àµÿ¥Ê“ÿžÄ‡ÿžÃ‡ÿ”Áˆÿ“¿‡ÿ§¿ÿ­¾|ÿ®½zÿ¯½yÿ±½wÿ³½vÿ´¼tÿ¶¼sÿ·¼qÿ¹»pÿ»ºnÿ¼ºlÿ¾ºkÿ¿¹iÿÆ¿uÿÑÌ�ÿ´­Iÿ²¨@ÿ°¤<ÿ® 9ÿ°Ÿ6ÿȺkÿàÑ�ÿÚÃTÿÛÂRÿÝÂPÿßÁOÿßÂPÿàÃQÿàÃRÿàÃSÿáÄTÿáÅUÿàÅ[ÿÚÁhÿ̺†ÿ°¡›ÿ~msÿYIUÿC29ÿ>*.ÿ?+.ÿB.1ÿD04ÿD25ÿE36ÿG26ÿJ15ÿJ37ÿJ5:ÿM7=ÿP:@ÿSEÿV?FÿW@GÿW@GÿW@HÿW@HÿX@HÿXAIÿXAIÿXAIÿXBIÿYBJÿZCJÿZCJÿZCJÿZCKÿZCLÿYBLÿYBLÿZBLÿZCLÿ[CLÿ[DMÿ[DLÿ[DLÿ[DMÿ[DMÿ[CMÿ[CMÿ[CMÿ[DMÿ[DMÿ[DMÿ[DLÿ[DLÿ[DLÿ[CLÿ[DLÿZCLÿiSUÿr\[ÿ\DKÿ[CKÿ[CJÁ[CH [CI7,(:'&:'&/:&&ê:&&ÿ>*+ÿU*.ÿ@,/ÿC/2ÿD15ÿD36ÿF37ÿI15ÿJ26ÿJ49ÿL7=ÿP:?ÿREÿV>FÿW@GÿW@GÿW@HÿW@HÿX@HÿXAHÿXAIÿXAIÿXBIÿYBJÿZBJÿZCJÿZCJÿZCKÿZCKÿZCLÿZCLÿZCLÿZCLÿZCLÿZCLÿZCLÿZDLÿZDLÿZDMÿZDMÿ[DMÿ[DLÿ[DLÿ[DLÿ[DLÿ[CLÿ[DKÿ[DKÿ[DLÿ[DKÿaJOÿv`]ÿ_HNÿ[CJÿ[CJê[CJ0[CJP?B@!(:&':''`:''ý9&&ÿE01ÿS;>ÿ;((ÿ:''ÿ:''ÿ:''ÿ:''ÿ;''ÿ;''ÿ;''ÿ;''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ:%%ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7"$ÿ7"$ÿ6!#ÿ5!#ÿ4 "ÿ2"ÿ2!ÿ3ÿ4ÿ4ÿ3 "ÿ2"#ÿ2!#ÿ2!"ÿ2 "ÿ2!ÿ1ÿ0ÿ2 ÿ>+(ÿUE<ÿpoaÿƒš‹ÿ‰º¬ÿ†ÌÁÿÑÊÿ{ÒËÿzÒÊÿyÒÈÿ~ÓÇÿ¦áÛÿŒÛÝÿsÔÔÿuÔÒÿtÔÑÿ�àÚÿ’Ö¾ÿxÌ®ÿyÌ®ÿzΦÿzÏ¢ÿzÏ ÿzÏ�ÿzÏœÿzЛÿ{Йÿ{Иÿ{Зÿ|Еÿ|Ñ”ÿ|Ñ’ÿ|Ñ‘ÿ{Ñ�ÿ�Ô’ÿ¥Þµÿ|Çžÿ›×²ÿŒÝžÿÚ‘ÿ‚Ú‘ÿ…Ú‘ÿ‰Ú“ÿ�Û•ÿ–Ü™ÿ�Þžÿ¤ß£ÿ«â©ÿ±ã®ÿµä²ÿ¸åµÿ¸åµÿ·ä³ÿ´â°ÿ°à«ÿ¬Þ¥ÿ¨Û�ÿ«ÜŸÿÄß¶ÿŸÅŽÿ’À‰ÿ’¿†ÿ—¾ƒÿª½zÿ®½xÿ°½wÿ²½vÿ´¼uÿµ¼sÿ·¼rÿ¸»pÿº»oÿ»ºmÿ½ºkÿ¾ºjÿÀ¹iÿÁ¸gÿ·dÿÍÁzÿÒÉ…ÿ»¬Cÿ¶§=ÿ»«IÿÛÏ‹ÿÝÊfÿÛÂRÿÜÂQÿÞÁOÿßÁOÿàÂPÿàÃRÿàÃRÿàÄTÿáÄUÿáÅWÿáÆXÿâÇXÿâÈZÿâÈZÿéÔ�ÿê˃ÿà¸bÿÒ°vÿ±™„ÿ�qwÿWGTÿB07ÿ?+.ÿB.1ÿC04ÿD25ÿE37ÿH26ÿJ15ÿJ49ÿL6<ÿO9?ÿR;BÿT=CÿU>EÿV>FÿW@GÿW@GÿW@HÿW@HÿX@HÿXAHÿXAIÿXAIÿXAIÿXBIÿYBJÿZBJÿZCJÿZCJÿZCKÿZCKÿZCKÿZCKÿZCLÿZCLÿZDLÿZDLÿZDKÿZDKÿZDLÿZDLÿ[DLÿ[DLÿ[CLÿ[CKÿ[CKÿ[DKÿ[DKÿ[DKÿ[CKÿ]ELÿt]\ÿfORÿZBJÿ[CJþ[BJ`[BJc?U:(&9$(:''’:''ÿ:''ÿM68ÿM69ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ;''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ;&&ÿ8#%ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"%ÿ8#%ÿ7#%ÿ7"$ÿ6"$ÿ6!#ÿ5!#ÿ4 "ÿ3!ÿ2 ÿ2ÿ4ÿ4ÿ2 "ÿ1"#ÿ2!#ÿ3!"ÿ2 !ÿ2 ÿ0ÿ/ÿ5""ÿG50ÿcZOÿ}‰|ÿб¤ÿˆÈÀÿ€ÐÌÿ{ÒÏÿyÑÎÿyÑÌÿzÑÊÿzÒÈÿzÒÆÿœÞÕÿšßàÿtÔÕÿuÔÒÿuÔÑÿtÔÐÿ„ÙÖÿ£ÞÓÿwʶÿwÌ«ÿzÏ ÿzÏŸÿzÏ�ÿzÏœÿzÏ›ÿ{Кÿ{Иÿ{Зÿ|Жÿ|Ñ”ÿ|Ñ“ÿ|Ñ‘ÿ|Ñ�ÿ}Ò�ÿŸÝ®ÿ‹Ð©ÿ_»‰ÿ�ÈŸÿ á¯ÿ�Ú‘ÿ‚Ù�ÿ„Ù�ÿ…Ø�ÿ‡×‹ÿˆÖŠÿ‰Öˆÿ‹Ö†ÿŒÖ…ÿŽÖ„ÿ’Ö„ÿ–Ö…ÿ›×ˆÿ ØŒÿ§Ú’ÿ®Ý˜ÿ´Þžÿºà¤ÿ¿â«ÿÕëÉÿÄÞ¶ÿ¸Ö¨ÿµÓ¦ÿ³Ï ÿ½Ë”ÿ¼ÇŒÿ¹Ä…ÿ¸À~ÿ·¾xÿ·¼tÿ¸»pÿ¹ºnÿº¹lÿ¼¹jÿ¾¹jÿÀ¹iÿÁ¸gÿ¸eÿÄ·dÿǸfÿØÍ‘ÿ´Sÿ¹¨@ÿÕÈ�ÿâÒyÿÝÈXÿÞÆVÿßÃQÿßÂOÿßÂPÿàÃQÿàÃRÿàÃSÿáÄUÿáÅVÿáÆWÿâÇXÿâÇYÿâÈ[ÿãÉ\ÿåÍhÿí×—ÿå½bÿäº]ÿáºgÿѱ{ÿ¬•†ÿwhsÿO?Kÿ@-2ÿ@,/ÿC/2ÿE15ÿE37ÿG36ÿJ15ÿJ38ÿK6<ÿO9?ÿR;AÿT=CÿU>DÿV>FÿW@GÿW@GÿW@GÿW@HÿX@HÿXAHÿXAHÿXAIÿXAIÿXBIÿYBIÿYBIÿZBJÿZBJÿZCKÿZCKÿZCKÿZCKÿZCKÿZCKÿZDKÿZDKÿZDKÿZDKÿZCLÿZCLÿ[CKÿ[CKÿ[CKÿ[CKÿ[CKÿ[DJÿ[CJÿ[CJÿ[CJÿnWWÿmVWÿ[BJÿ[BIÿZBI“^GJZAI:'':'' :'&À:'&ÿ;((ÿS;>ÿF13ÿ:'&ÿ:''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ;''ÿ9$%ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ6"$ÿ5!#ÿ4 "ÿ2 !ÿ1 ÿ2ÿ4ÿ4ÿ2!ÿ1!#ÿ2!#ÿ2!"ÿ2 !ÿ1 ÿ0ÿ0ÿ9&$ÿQ@:ÿrndÿ„›�ÿŠ¿·ÿ„ÎÌÿ|ÑÒÿxÑÑÿyÑÏÿyÑÎÿyÑÌÿzÑÊÿzÒÉÿyÒÆÿ�ÙÏÿ¥âáÿxÕÖÿtÔÓÿtÓÔÿrÓÕÿpÒ×ÿqÒØÿ ßßÿ‡Ñºÿy΢ÿzÏŸÿzÏžÿzÏœÿzÏœÿ{Кÿ{Иÿ{Зÿ{Жÿ|Ñ•ÿ|Ñ“ÿ|Ñ‘ÿ|Ñ‘ÿ{ÑŽÿ”Ú£ÿšÖ³ÿf¿�ÿ`»ˆÿh¼‹ÿ¤Ü´ÿ‰Ü–ÿƒÙ�ÿ…Ø�ÿ‡×Œÿˆ×‹ÿŠÖ‰ÿ‹Öˆÿ�Ö†ÿŽÖ…ÿ�Öƒÿ’Õ‚ÿ“Ô€ÿ”Ó~ÿ•Ó|ÿ—Ó{ÿ˜Òyÿ™Òxÿ›Ñvÿ³Û•ÿÄä´ÿÃߦÿªÏxÿ¯Ñ|ÿ¸ÓƒÿÊÕ†ÿÏ׎ÿÒØ”ÿÓ×™ÿÓÖ›ÿÑÔšÿÐÑ—ÿÍÌ‘ÿÊÈŠÿÈÅ‚ÿÆÀzÿŽrÿĺkÿŸgÿŶcÿƵ_ÿÒÄ~ÿÏÂtÿ˾lÿãÕ†ÿÞÉZÿßÈXÿáÈWÿâÇVÿáÆUÿáÅTÿàÃSÿàÃSÿáÄTÿáÅVÿáÆWÿâÆXÿâÇYÿâÈ[ÿãÉ\ÿãÉ]ÿãÊ^ÿëØ�ÿéÇ{ÿäº]ÿå»_ÿå¼aÿݺmÿÀ«„ÿ–‡‡ÿfXfÿG5>ÿ@,/ÿB.1ÿD14ÿE37ÿF37ÿJ15ÿJ38ÿK6;ÿO9?ÿR;AÿT=CÿU>EÿV>FÿW@GÿW@GÿW@GÿW@HÿW@HÿX@IÿXAHÿXAHÿXAIÿXBIÿYBIÿYBIÿYBIÿYBIÿYBJÿYBJÿYBKÿYBKÿZBKÿZBJÿZCJÿZCJÿZCJÿZCJÿZCKÿZCKÿ[CKÿ[CKÿ[CJÿ[BJÿ[BJÿZCJÿZCIÿZBIÿgPRÿs[[ÿ\CJÿZBIÿZBIÁYAH YAH:'&:'&!:'&à:'&ÿ>**ÿV=AÿA,-ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ:&&ÿ8#%ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7!$ÿ6!#ÿ5!#ÿ4!#ÿ3 "ÿ1!ÿ1 ÿ3ÿ3ÿ2 ÿ1!"ÿ2!#ÿ2!"ÿ2 "ÿ1 ÿ/ÿ0ÿ<)'ÿTFAÿkojÿ~›�ÿ§ÏÏÿƒÑÓÿyÑÕÿxÐÔÿxÐÑÿyÑÏÿyÑÎÿyÑÌÿzÑÊÿzÒÉÿyÒÇÿ…ÖÊÿªãßÿ€×ÚÿrÒ×ÿqÒÙÿpÑÚÿoÑÚÿoÑØÿnÑÖÿŠÙÛÿŸÝÁÿzÏŸÿzÏžÿzÏ�ÿzÏœÿzКÿ{Йÿ{Зÿ{Жÿ|Ñ•ÿ|Ñ“ÿ|Ñ’ÿ|Ñ‘ÿ{Ñ�ÿ‰×™ÿ£Ü·ÿnÕÿb¾‹ÿa»‡ÿ_·‚ÿŽÎ¥ÿœß¦ÿ„Ø�ÿ‡ØŒÿˆ×‹ÿ‰ÖŠÿ‹Öˆÿ�Ö†ÿŽÖ…ÿ�Ö„ÿ‘Õ‚ÿ“Ô€ÿ”Ôÿ•Ó~ÿ—Ó|ÿ™Ó{ÿšÒyÿ›Ñwÿ©×‡ÿÀâ¬ÿ¢ÔŠÿ¾Þ¥ÿ«Ïvÿ Èaÿ§Ç_ÿºÇWÿ½ÆVÿ¿ÇVÿÂÇXÿÆÈ\ÿÊÊaÿÎÌiÿÒÏqÿÕÒzÿØÔƒÿÚÕ‹ÿÛÕ�ÿÜÔ’ÿÛÒ’ÿÙÎŽÿ×ʈÿØÊˆÿâØ§ÿåÚ�ÿáÏmÿàÊ^ÿáÈZÿâÇWÿâÇVÿãÈVÿãÉWÿâÈWÿâÆVÿáÅVÿáÅWÿâÆXÿâÇYÿâÈZÿâÉ\ÿãÉ]ÿãÊ^ÿãÊ^ÿçÑtÿíÔ”ÿä¼aÿå¼aÿä½bÿÚ¼eÿÕ»jÿÍ·yÿ²¡Œÿ€s}ÿTDQÿA.3ÿA.0ÿD14ÿE36ÿF37ÿI15ÿI38ÿK6;ÿO9?ÿR;AÿT=CÿU>EÿV?EÿW@GÿW@GÿW@GÿW@GÿW@HÿW@IÿX@IÿXAHÿXAHÿXBIÿYBIÿYBIÿYBIÿYBIÿYBJÿYBJÿYBJÿYBJÿZBJÿZBJÿZCJÿZCJÿZCJÿZCJÿZCJÿZCJÿ[BJÿ[BJÿZBJÿZBJÿZBIÿZCIÿZBIÿ`INÿu^\ÿ^FLÿZBIÿZBIàZBH!ZBH9&&9&&>:&&ó:&&ÿC..ÿW=@ÿ>))ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<('ÿ;''ÿ9$%ÿ7"$ÿ7"$ÿ8"$ÿ8"%ÿ8"%ÿ8"%ÿ8#%ÿ8#%ÿ8"%ÿ7"$ÿ6"$ÿ5!#ÿ4 "ÿ3"ÿ2!ÿ2ÿ4ÿ3ÿ2!"ÿ1"#ÿ2!"ÿ2 "ÿ2 ÿ0ÿ0ÿ=+)ÿWIEÿnvsÿu›¢ÿj­¾ÿ^°Çÿ’ÎÜÿŠ×ÛÿwÐÓÿxÐÒÿyÑÐÿyÑÎÿyÑÍÿzÑËÿzÑÉÿzÒÈÿ}ÓÈÿ¥áÜÿŠÚâÿnÑÜÿoÑÜÿoÑÜÿoÑÚÿoÑØÿoÑ×ÿoÑÕÿy×Êÿ¨ãÌÿƒÒ¥ÿyÏœÿzÏœÿzЛÿ{Йÿ{Иÿ{Зÿ|Ñ•ÿ|Ñ”ÿ|Ñ’ÿ|Ñ‘ÿ|Ñ�ÿ�Ô’ÿ¥Þµÿ{Èžÿb¾‹ÿd¿Šÿaº…ÿ`·�ÿr¿�ÿ¨ß²ÿ‰Ù�ÿˆ×‹ÿ‰ÖŠÿ‹ÖˆÿŒÖ‡ÿŽÖ…ÿ�Ö„ÿ‘Õƒÿ“Ô�ÿ”Ôÿ•Ó~ÿ—Ó|ÿ˜Ó{ÿ™Òzÿ›Ñxÿ¢Ó}ÿÀâªÿ¨×‘ÿœÐ~ÿ°Ù–ÿ¼Ù“ÿ¢ÈbÿªÇ_ÿ¼ÇXÿ¾ÆUÿÀÅTÿÂÅRÿÃÄQÿÄÃOÿÆÃLÿÇÂJÿÉÃIÿÊÃHÿÍÃIÿÏÃKÿÒÄNÿÕÆTÿÙÉ\ÿÜËdÿáÒ{ÿëâ´ÿìà¡ÿéÚ‰ÿëÚ�ÿëÙŒÿëØ‰ÿê׃ÿéÕ|ÿçÓuÿæÑnÿåÎhÿäÌbÿãÊ^ÿâÈZÿâÇYÿâÈZÿãÉ[ÿãÉ]ÿãÊ^ÿãÊ`ÿãÌcÿíÚ—ÿèÄsÿå¼aÿݼeÿÖ»hÿÖ¼iÿÖ¼jÿÔ»qÿ݆ÿšŒ‹ÿeWfÿF3:ÿA-0ÿD04ÿE36ÿG48ÿI15ÿJ38ÿK6;ÿO9?ÿR;AÿT=CÿU>EÿV?EÿW?GÿW@GÿW@GÿW@GÿW@HÿW@IÿW@IÿX@IÿX@HÿXAHÿXBHÿYBHÿYBHÿYBIÿYBIÿYBJÿYBJÿYBJÿZBJÿZBIÿZCIÿZCIÿZBIÿZBIÿZBIÿYBJÿZBJÿZBIÿZBIÿZBIÿZBIÿZBIÿ\EKÿt][ÿbJNÿZAHÿZBIóZAH>ZAH;&(:&&:&&`:&&þ:&%ÿH13ÿT;=ÿ<''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<''ÿ<'(ÿ<((ÿ<((ÿ:&'ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ8#%ÿ8"$ÿ7"$ÿ6!#ÿ5!#ÿ3 "ÿ2!ÿ1ÿ4ÿ4ÿ2 !ÿ1!#ÿ2!#ÿ2!"ÿ1!ÿ0ÿ0ÿ<)(ÿWIFÿpxyÿtž©ÿh®Ãÿ\¯ÊÿW®ÉÿU®Çÿs¼Ïÿ�ÚßÿxÐÒÿyÐÐÿyÑÏÿyÑÍÿzÑËÿzÑÊÿyÑÊÿwÐÊÿ™ÜÙÿ—ÝæÿoÑÞÿoÑÜÿoÑÜÿoÑÚÿoÑÙÿoÑ×ÿoÑÖÿrÓÍÿu×½ÿ˜áËÿ˜ÚµÿyÏ›ÿzЛÿ{Йÿ{Иÿ{Зÿ|Еÿ|Ñ”ÿ|Ñ’ÿ|Ñ‘ÿ|Ñ�ÿ|Ò�ÿŸÝ­ÿ‹Ð©ÿb¾Œÿc¿Šÿd¿‰ÿb¹ƒÿb·€ÿd·€ÿœÓªÿ˜Ü›ÿ‡Ö‰ÿŠÖ‰ÿŒÖ‡ÿ�Ö†ÿ�Ö„ÿ�Õƒÿ’Õ�ÿ“Ôÿ•Ó~ÿ–Ó}ÿ˜Ó{ÿ™Òzÿ›Òxÿ�Òxÿ»ß¡ÿ±Û�ÿœÑ€ÿžÑÿ¤ÓƒÿÃÞ¤ÿ©Ëlÿ¬Ç]ÿ½ÆVÿÀÆTÿÁÅSÿÃÄQÿÄÄPÿÆÃNÿÈÃMÿÉÃKÿÊÃJÿÌÂHÿÎÂGÿÏÁEÿÐÀCÿÒÀAÿÓ¿?ÿÖÀAÿàÐzÿÒÃtÿâÒ‚ÿàÇKÿáÇKÿãÉSÿåÍ\ÿçÐgÿèÔrÿê×}ÿìÚ…ÿìÛŒÿíÝ�ÿíÝ‘ÿìÛŽÿëÙˆÿéÕ�ÿèÓzÿæÑsÿåÏmÿäÎiÿãÌdÿéÖ�ÿìÑŽÿß»bÿÖºfÿÖ»hÿÖ¼iÿÖ¼kÿ×½kÿ×¾nÿϹ~ÿ®ž�ÿwiwÿM;EÿA-0ÿD03ÿF36ÿF37ÿI15ÿJ38ÿK6<ÿO9?ÿREÿV?EÿW?FÿW?GÿW@GÿW@GÿW@GÿW@HÿW@IÿW@IÿW@IÿWAIÿXAIÿYAIÿYAHÿYAHÿYAIÿYAIÿYAIÿYAIÿYAIÿZAIÿYBIÿYBIÿYBIÿYBHÿYBIÿYBIÿZBIÿZBIÿZAIÿZAIÿYAIÿZBIÿqZYÿfOQÿYAHÿZAIþYAH`ZAIZ@I;'*:&%:&&}:&&ÿ9&%ÿL57ÿO8:ÿ;'&ÿ;'&ÿ;'&ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ<''ÿ<'(ÿ<'(ÿ<((ÿ<((ÿ<((ÿ=((ÿ=((ÿ=((ÿ=)(ÿ;'(ÿ9$&ÿ7#%ÿ8#%ÿ8#%ÿ7"$ÿ6"$ÿ5!#ÿ4 "ÿ2!ÿ1 ÿ2ÿ3ÿ3ÿ1 "ÿ1!#ÿ2!"ÿ2 !ÿ0ÿ0ÿ9'&ÿTFBÿoyyÿw¢¯ÿi±ÉÿZ¯ÌÿV®ÌÿW®ÊÿW®ÈÿW¯Æÿ\±Æÿ›ÔÜÿ„ÕÔÿxÑÏÿyÑÎÿyÑÍÿxÐÍÿvÐÎÿuÏÎÿ‹ÖÕÿ¢àçÿsÒßÿoÑÝÿoÑÜÿoÑÛÿoÑÙÿoÑØÿoÑÖÿqÒÑÿu×ÁÿvØ»ÿ‚ÛÁÿ¨âÆÿ~ÑžÿzЙÿ{Иÿ{Зÿ|Жÿ|Ñ”ÿ|Ñ“ÿ|Ñ‘ÿ|Ñ�ÿ{ÑŽÿ”Ú£ÿ›×³ÿf¿�ÿc¿Šÿd¿‰ÿd¾‡ÿb¸�ÿc·€ÿcµ}ÿ€Ã“ÿ¨ß¬ÿŠÖ‰ÿŒÖ‡ÿ�Ö†ÿŽÖ…ÿ�Õƒÿ’Õ�ÿ“Ô€ÿ”Óÿ–Ó}ÿ˜Ó{ÿ™ÓzÿšÒyÿœÑvÿ²Û“ÿºß§ÿ�Ò‚ÿžÑÿŸÑ}ÿ Ð{ÿ¹Ûšÿ¹Ô…ÿ­Æ[ÿ¿ÆUÿÁÅSÿÃÄRÿÄÄPÿÅÃNÿÇÃMÿÉÃLÿÊÃJÿÌÃIÿÍÂGÿÏÁFÿÐÁDÿÒÀCÿÓÀAÿÕÀ?ÿßÎmÿÔÅtÿ¿§;ÿׯyÿäÌ\ÿàÄAÿàÅCÿáÅCÿáÅDÿáÆDÿâÇFÿâÇHÿãÉMÿäËRÿåÍYÿæÐbÿèÔmÿêÖwÿëÙ�ÿìÚ‰ÿìÜ�ÿíÝ“ÿíÝ”ÿîß™ÿñâ²ÿâÍŒÿÝȃÿÛÅ}ÿÚÂxÿÙÀtÿØ¿qÿ׿oÿØ¿oÿÔ½xÿ¼«�ÿ‡z‚ÿTCOÿB.2ÿC03ÿE36ÿF37ÿJ15ÿJ38ÿL6<ÿP9?ÿSEÿW?FÿW?FÿW?FÿW?GÿW@GÿW@GÿW@HÿW@HÿW@HÿW@HÿWAIÿWAIÿXAIÿXAIÿXAIÿXAIÿXAIÿXAIÿXAIÿXAHÿYAHÿYBHÿYBHÿYBHÿYBHÿYBIÿYAIÿYAIÿYAIÿYAIÿYAIÿYAHÿlUVÿjRTÿX@HÿYAHÿYAH}YAHW?H;''I<<:&&™:&&ÿ:&&ÿP8;ÿK46ÿ:&%ÿ;'&ÿ;'&ÿ;'&ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;''ÿ;'(ÿ;'(ÿ;((ÿ<((ÿ<((ÿ=((ÿ=((ÿ=((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<)(ÿ<((ÿ9&'ÿ7#%ÿ6"$ÿ6"$ÿ5!#ÿ3 "ÿ2!ÿ1ÿ2ÿ3ÿ1!ÿ0!"ÿ1!"ÿ2 !ÿ1 ÿ/ÿ6##ÿN?<ÿlpqÿwŸ«ÿl´Íÿ^¶ÖÿW±ÑÿV®ÌÿW®ÊÿW®ÈÿW¯ÆÿW¯ÅÿU®ÂÿÃÐÿ˜ÚÛÿvÐÐÿvÏÑÿuÎÐÿuÏÐÿtÏÏÿ€ÒÑÿ¦áäÿ|ÕâÿnÑÝÿoÑÜÿoÑÛÿoÑÙÿoÑØÿoÑÖÿpÑÔÿtÕÆÿvؼÿwØ»ÿwعÿ¡ãÊÿ�تÿzЗÿ{Зÿ{Жÿ|Ñ•ÿ|Ñ“ÿ|Ñ‘ÿ|Ñ‘ÿ{ÑŽÿ‰Ö™ÿ¤Ü·ÿoÕÿb¾‹ÿd¿‰ÿd¿ˆÿe½…ÿc·€ÿd¶ÿe¶}ÿk¸ÿ¦Ø­ÿ•Ú‘ÿŒÖ†ÿŽÖ…ÿ�Öƒÿ‘Õ‚ÿ“Ô€ÿ”Ôÿ•Ó}ÿ—Ó|ÿ™ÓzÿšÒyÿ›Ñwÿ©×†ÿÀâ¬ÿ¡ÔˆÿžÑÿŸÑ~ÿ Ð|ÿ¡Ðzÿ¬Ó…ÿÅÜ�ÿ²Ç_ÿÀÅSÿÂÅRÿÄÄQÿÅÃOÿÇÃMÿÉÃLÿÊÃKÿËÃIÿÍÂGÿÏÁFÿÐÁEÿÑÀCÿÓÀAÿÔ¿?ÿÜÈ[ÿÛÍ�ÿÄ­Cÿ¾¤5ÿɲWÿåÒzÿàÅCÿáÅDÿáÅEÿáÆFÿâÇGÿâÇHÿâÈIÿãÈJÿãÉKÿãÊKÿãÊLÿãÉLÿãÊMÿãËOÿãÌQÿãÌSÿäÌWÿåÍ\ÿëÙ‚ÿòç´ÿìÜ”ÿèÔ|ÿé׈ÿéØ�ÿ騖ÿçØ™ÿæÖ™ÿäÓ—ÿâÐ’ÿÞÌ‘ÿ˼žÿ˜Œ”ÿ]M\ÿC/4ÿC03ÿE36ÿG37ÿJ15ÿJ48ÿL7<ÿP:@ÿSDÿV>EÿW?FÿW?FÿW?FÿW?FÿW?GÿX?GÿW@HÿW@HÿW@HÿW@HÿWAHÿWAHÿXAHÿXAHÿXAHÿXAHÿXAHÿXAHÿXAHÿXAHÿYAHÿYAHÿYAHÿYAHÿYAHÿXAHÿXAIÿXAIÿYAIÿYAHÿX@HÿiQSÿmVVÿXAGÿXAGÿYAGšY9JY@G9&%9&%:&&±:&&ÿ;&'ÿT;>ÿG12ÿ9&%ÿ;'&ÿ;'&ÿ;'&ÿ;'&ÿ;''ÿ;'(ÿ;'(ÿ;((ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<)(ÿ<))ÿ9&'ÿ6#$ÿ5!#ÿ3 "ÿ1!ÿ1ÿ3ÿ3ÿ1 "ÿ1!"ÿ1 "ÿ1 ÿ/ÿ2 ÿF43ÿfccÿw˜£ÿo³Íÿ_¶×ÿY´×ÿYµÕÿW°ÎÿW®ÊÿW®ÈÿW¯ÇÿW¯ÅÿW¯ÄÿU®Ãÿ`³Èÿ�ÖßÿzÐÕÿtÎÑÿuÏÐÿuÏÏÿyÐÏÿ¢ßàÿ‰ÙäÿnÑÝÿoÑÜÿoÑÛÿoÑÚÿoÑØÿoÑ×ÿoÑÕÿrÔËÿvؽÿvØ»ÿwغÿvØ·ÿŠÞÁÿ¥à½ÿ|Иÿ{Жÿ|Ñ•ÿ|Ñ“ÿ|Ñ’ÿ|Ñ‘ÿ|Ñ�ÿ€Ô’ÿ¥Þµÿ|ÉŸÿb¾‹ÿd¿Šÿd¿ˆÿe¿‡ÿf¼„ÿd¶ÿe¶}ÿg¶|ÿgµyÿŽÈ™ÿ¦Þ£ÿ�Ö„ÿ�Ö„ÿ‘Õ‚ÿ“Ô€ÿ”Ôÿ•Ó~ÿ—Ó|ÿ™Ó{ÿšÒyÿ›Ñwÿ¢Ó}ÿÀâªÿ©×’ÿ�ÑÿŸÑ~ÿ Ñ}ÿ¢Ð{ÿ¤Ïyÿ¥ÏxÿÂÜ�ÿ¿ÎrÿÁÄQÿÄÄQÿÅÃOÿÆÃMÿÈÃLÿÉÃKÿËÃIÿÍÂHÿÎÂGÿÏÁEÿÑÀCÿÓÀBÿÔÀ?ÿØÄLÿßÑ…ÿȳPÿ©8ÿ¿¤6ÿ¿¥;ÿÞÌ€ÿäÊSÿáÅDÿáÆFÿâÇGÿâÇHÿâÇIÿâÈJÿãÉKÿãÊLÿãÊMÿãÊNÿãÊOÿãËPÿãÌQÿãÌRÿãÍRÿäÍRÿæÑbÿíß•ÿéÕ{ÿëÛ�ÿáÇNÿáÆLÿâÈOÿâÊUÿäÍ\ÿåÏdÿçÒnÿèÕyÿêØ„ÿêÚ�ÿÞОÿ©ž—ÿaR_ÿD16ÿD03ÿE37ÿG36ÿJ15ÿJ59ÿM7=ÿQ:@ÿTDÿV?EÿW?FÿW?FÿW?FÿW?FÿX?FÿX?FÿX?GÿX?HÿX?HÿX@HÿW@HÿWAHÿXAHÿXAHÿXAHÿXAHÿX@HÿX@HÿX@HÿX@HÿY@HÿX@HÿXAHÿXAHÿXAHÿXAHÿXAHÿYAHÿY@HÿX?GÿdMPÿoYXÿYAGÿYAGÿYAG±Y@FY@F:&':&' :&&À:&&ÿ<''ÿV=@ÿE/0ÿ9&%ÿ:&&ÿ:'&ÿ;''ÿ;('ÿ;('ÿ;((ÿ<((ÿ<((ÿ<((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ;((ÿ;((ÿ8&'ÿ5"$ÿ1!ÿ2ÿ4ÿ2 ÿ1!"ÿ1!"ÿ1 !ÿ0ÿ0ÿ<*)ÿ]RQÿvŠ”ÿs¯Çÿb¶ÙÿY´ÙÿY´×ÿYµÖÿYµÓÿX°ÌÿW®ÉÿW®ÇÿV®ÆÿU­ÆÿS¬ÆÿS¬ÆÿR«ÅÿˆÈ×ÿ�ÖÙÿtÎÐÿuÏÏÿuÏÎÿ—ÛÚÿ—ÝæÿoÑÞÿoÑÜÿoÑÜÿoÑÚÿoÑÙÿoÑ×ÿoÑÕÿqÒÐÿu×ÀÿvØ»ÿwغÿwظÿwÙ·ÿzÚ·ÿ§äÈÿˆÕ¡ÿ{Еÿ|Ñ”ÿ|Ñ’ÿ|Ñ‘ÿ|Ñ�ÿ|ÒŽÿžÝ­ÿŒÐªÿc¾Œÿc¿Šÿd¿‰ÿe¿‡ÿf¾†ÿf»ƒÿe¶~ÿg¶|ÿhµ{ÿiµyÿuº�ÿ­Ü­ÿ“؉ÿ�Õ‚ÿ’Õ�ÿ“Ôÿ•Ó~ÿ–Ó|ÿ˜Ó{ÿ™Òzÿ›Òxÿ�Ñwÿºß ÿ²Ü�ÿ�Ñ€ÿŸÑÿ Ñ}ÿ¡Ð{ÿ£Ðyÿ¥Ïxÿ¦Îuÿ´Õ‰ÿÎÙ�ÿÃÅRÿÅÄOÿÆÃNÿÈÃLÿÉÃKÿËÃJÿÌÂHÿÎÂGÿÏÁEÿÐÀCÿÒÀBÿÔÀ@ÿÖÁCÿàÑ|ÿμbÿ©9ÿĨ8ÿ¿£5ÿ½¢3ÿлeÿæÑqÿáÆDÿáÇGÿâÇGÿâÇIÿâÈJÿãÉKÿãÊLÿãÊLÿãÊNÿãÊNÿãËOÿãËQÿãÌRÿãÍRÿäÎSÿåÏYÿîß‘ÿêØ|ÿåÐbÿìÝ‘ÿæÏhÿáÇLÿáÈNÿáÉPÿâÉQÿâÉQÿâÊRÿãÊSÿãËTÿãÌWÿäÎZÿÙÆoÿ¨šƒÿdUbÿD17ÿD14ÿE37ÿH26ÿK26ÿJ5:ÿM8=ÿQ;AÿTÿpv{ÿx¦»ÿg¶ØÿZµÜÿX´ÙÿY´×ÿYµÖÿYµÔÿY´ÒÿW®ËÿU­ÉÿS¬ÉÿR«ÉÿR«ÇÿS«ÆÿS¬ÅÿR«Ãÿi·Ëÿ�ÙÝÿwÐÐÿtÏÎÿŠÖÕÿ£àæÿtÒßÿoÑÜÿoÑÜÿoÑÚÿoÑÙÿoÑ×ÿoÑÖÿpÑÓÿtÖÅÿvؼÿwغÿwعÿwØ·ÿwÙµÿvÙ³ÿ”àÂÿžÝ³ÿ{Ñ“ÿ|Ñ’ÿ|Ñ‘ÿ|Ñ�ÿ{ÒŽÿ“Ú¢ÿ›×³ÿfÀ�ÿc¿Šÿd¿‰ÿe¿‡ÿf¾†ÿg¾…ÿgº�ÿf¶|ÿg¶{ÿiµzÿkµxÿl´vÿœÎ ÿ£Ü˜ÿ‘Ô€ÿ“Ôÿ”Óÿ–Ó}ÿ˜Ó{ÿ™ÓzÿšÒyÿœÑvÿ²Û“ÿ¼à¨ÿŸÒƒÿ Ñÿ¡Ñ}ÿ£Ð|ÿ¥Îzÿ§Íxÿ¨ÌwÿªÌvÿ­ÌxÿÎÚšÿÊÈbÿÅÂPÿÈÂOÿÊÃNÿËÃLÿÌÃJÿÎÂHÿÏÂFÿÐÁDÿÒÀBÿÔÀ@ÿÕÀ?ÿßÍlÿÕÅuÿª;ÿÄ©8ÿĨ7ÿ¿£5ÿ¾£4ÿêDÿãÑ„ÿãÉMÿâÇGÿâÇHÿâÈJÿãÉKÿãÉKÿãÊLÿãÊMÿãÊNÿãÊOÿãËQÿãÌRÿãÍRÿãÎSÿäÎTÿëÛƒÿìÜ‹ÿæÑcÿæÑbÿêØ{ÿìÛŠÿâÉPÿâÉPÿâÉQÿâÉRÿâÊSÿãËTÿãËVÿãÌWÿäÍXÿäÎYÿäÏZÿÚÇmÿ©›ƒÿcTaÿE27ÿD14ÿE37ÿI15ÿJ37ÿK6;ÿN9>ÿR;AÿU=CÿV>DÿW>EÿW?EÿW?EÿW?EÿW?EÿW?FÿW?FÿW?GÿW?GÿW?GÿW?GÿW?GÿW@GÿW@GÿW@GÿW@GÿW@GÿW@GÿW@HÿW@GÿX@GÿX@GÿY@GÿY@GÿY@GÿY@GÿX@FÿX@GÿX@Gÿ`HLÿsZYÿ\BHÿY?FÿX?FÎW?FX?F9&&9&&:&&×:&&ÿ>)*ÿX?BÿA,-ÿ:''ÿ;''ÿ;''ÿ:''ÿ:''ÿ;('ÿ;('ÿ;('ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ;''ÿ:&&ÿ8&%ÿ8$$ÿ9##ÿ6&&ÿ4#$ÿ4!"ÿ1 !ÿ1ÿA--ÿf]^ÿy—§ÿo³Ôÿ]µÝÿX´ÜÿY´ÚÿY´ØÿY´ÖÿYµÕÿX´ÔÿW²ÒÿS¬ÌÿR«ËÿR«ÉÿR«ÈÿS«ÆÿS¬ÅÿS¬ÄÿS¬ÃÿV­Âÿ”ÏÙÿ…ÔÔÿ~ÒÐÿ¦áäÿ}ÕáÿnÑÝÿoÑÜÿoÑÛÿoÑÙÿoÑØÿoÑÖÿpÑÕÿsÔÊÿvؽÿwØ»ÿwعÿwظÿwÙ¶ÿwÙ´ÿwÙ³ÿÛ¶ÿªäÃÿ‚Ó˜ÿ|Ñ‘ÿ|Ñ‘ÿ{ÑŽÿˆÖ˜ÿ¤Ü·ÿoÖÿb¾Šÿd¿‰ÿd¿ˆÿf¾†ÿg¾…ÿh½ƒÿh¹ÿg¶{ÿiµzÿkµyÿlµwÿl´uÿ€½†ÿ°Ý©ÿ”Õ�ÿ•Ôÿ—Ó}ÿšÒ{ÿ�ÑxÿžÍvÿ Érÿ¨Ézÿ»Í™ÿ¡ºzÿš±nÿ˜ªkÿ–£gÿ•ždÿ”˜bÿ’”`ÿ��^ÿŽ�^ÿ�Œ]ÿ™’kÿŸ‘`ÿ�ŽQÿ¢“Sÿ¨˜Sÿ­�Sÿ³¤Sÿº«RÿÁ±QÿȵOÿ͹KÿѼGÿÚÆ]ÿÛ̓ÿÅ®Dÿé8ÿÅ©7ÿħ6ÿ¿£5ÿ¿¤5ÿ¿¤6ÿÖÃtÿæÐgÿâÇFÿâÈIÿãÈKÿãÉKÿãÊLÿãÊMÿãÊNÿãÊOÿãËPÿãÌRÿãÍRÿãÍSÿäÎSÿéÖrÿîà•ÿæÒgÿæÑcÿæÒdÿçÓiÿîà—ÿæÏaÿãËQÿãËRÿâÊSÿãËTÿãËUÿãÌWÿãÍXÿäÎYÿäÎZÿäÏ\ÿåÏ]ÿÚÇoÿ¦™ƒÿ_P]ÿD15ÿD25ÿF36ÿJ15ÿJ48ÿL7<ÿO:?ÿRDÿW>EÿW?EÿW?EÿW?EÿW?EÿW?EÿW?EÿW?FÿW?FÿW?FÿW?FÿW@FÿW@FÿW@FÿW@FÿX@FÿX@FÿX?GÿX?GÿX?GÿX?GÿX?GÿX?FÿX@FÿX@FÿX@FÿX@FÿX?Fÿ^EKÿsZYÿ\CHÿX?FÿX@F×X?EX?E:&&:&&:''Û:''ÿ?*+ÿY?CÿA,-ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ;('ÿ;('ÿ;('ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ;''ÿ:&&ÿ8%%ÿ9$#ÿ:##ÿ7''ÿ6%&ÿ4"#ÿ6#$ÿR@Aÿ~‚�ÿžÀÔÿg·ÞÿY´ÞÿY´ÜÿY´ÚÿY´ØÿX³×ÿW³×ÿV²ÖÿV²ÕÿU°ÒÿR«ËÿR«ÉÿR«ÈÿR«ÆÿS¬ÆÿS¬ÄÿS¬ÃÿT¬ÁÿR¬Àÿu¾ÌÿœÚÛÿ Þßÿ‰ÙäÿmÐÝÿnÑÜÿoÑÛÿoÑÙÿoÑØÿoÑÖÿpÑÕÿqÓÏÿu׿ÿwØ»ÿwعÿwظÿwÙ¶ÿwÙ´ÿwÙ³ÿwÙ²ÿwÚ±ÿ�ãÃÿ–Ú¨ÿ{Ñ�ÿ|Ñ�ÿ€Ô‘ÿ¥Þ´ÿ}ÉŸÿb¾Šÿd¿Šÿd¿ˆÿf¾‡ÿg¾†ÿh½„ÿj¼‚ÿh¸}ÿhµzÿjµyÿkµwÿnµvÿq´tÿw´tÿ«Ïžÿ¤Í…ÿ™½qÿ—±jÿ’¡bÿ‹’Yÿ„ƒRÿ{sKÿxjLÿp_IÿeR>ÿ`L<ÿ[E9ÿWA8ÿU>7ÿS;6ÿQ86ÿO76ÿN66ÿL66ÿL66ÿN87ÿP99ÿS<;ÿV?<ÿZC>ÿ`IAÿgQEÿq\Iÿ}hLÿ‰sOÿ—�Rÿ«˜nÿ¬—aÿ°™Nÿº¡JÿÀ¦Cÿ§>ÿ¿¤8ÿ¿¥7ÿ¿¥6ÿȲRÿæÔ‚ÿãÈKÿãÈJÿãÉKÿãÊLÿãÊMÿãÊNÿãÊOÿãËPÿãÌQÿãÌRÿãÍRÿäÎSÿæÒcÿîá˜ÿèÔpÿæÑcÿæÒdÿæÒeÿæÒeÿë܇ÿëÙ€ÿäËQÿäÍSÿäÍTÿäÍUÿãÍWÿãÍXÿäÍYÿäÎZÿäÏ[ÿåÏ]ÿåÐ^ÿåÐ_ÿØÆsÿž‘‚ÿYJVÿD15ÿD36ÿH25ÿK15ÿJ59ÿM8=ÿQ;@ÿSDÿV>DÿV?DÿW?EÿW?EÿW?EÿW?EÿW?EÿW?EÿW?FÿW?FÿW?FÿW?FÿW?FÿW?FÿX?FÿX?FÿX?FÿX?FÿW?FÿW?FÿW?FÿX?FÿX@FÿX@FÿX@FÿX?EÿX?Eÿ]DIÿrZYÿ\DHÿX@EÿX@EÛX?EX?E;'';'';''ß:''ÿ?+,ÿY@Dÿ?+,ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ;('ÿ;('ÿ;('ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<((ÿ=((ÿ=((ÿ=((ÿ=((ÿ<'(ÿ:''ÿ8&&ÿ9$$ÿ:##ÿ7''ÿ6&&ÿD20ÿg]bÿ�œ¸ÿ{½óÿ˜Òùÿn½ãÿX³ÜÿX³ÛÿW²ÚÿV²ÙÿU²ØÿU²×ÿV²ÖÿV²ÔÿU°ÐÿR«ÊÿR«ÈÿR«ÇÿS¬ÆÿS¬ÅÿS¬ÃÿT¬ÂÿT¬ÁÿT­¿ÿ[°Áÿ­Ûáÿ²åìÿ†Øãÿ~ÖàÿyÔÞÿtÓÛÿqÒÙÿoÑ×ÿnÑÕÿoÑÒÿsÖÂÿvØ»ÿvعÿwظÿwÙ·ÿwÙµÿwÙ´ÿwÙ²ÿxÚ±ÿwÚ¯ÿ†Þ·ÿ¨â¼ÿ~Ò‘ÿ|ÒŽÿžÝ¬ÿ�Ъÿc¾Œÿd¿Šÿd¿‰ÿe¿‡ÿg¾†ÿg½„ÿi½‚ÿk¼�ÿj·|ÿmµyÿt´vÿy®rÿ~¥lÿ˜dÿ{ˆZÿ}[ÿynQÿhXAÿ^I:ÿT=5ÿM62ÿH10ÿE-.ÿC+.ÿA*.ÿA*.ÿA).ÿA).ÿA).ÿB*.ÿB*/ÿB*/ÿB*/ÿB*0ÿA+1ÿ@+1ÿA+1ÿA+1ÿB+1ÿB+2ÿC,2ÿC,1ÿD,2ÿG/4ÿL45ÿN66ÿR:9ÿW@=ÿ_HAÿkSHÿyaMÿ‰rRÿ™ƒSÿ§�Qÿ³›Lÿ»¢Fÿ¿§CÿÜË‚ÿæÏ^ÿãÉJÿãÊLÿãÊMÿãÊNÿãÊNÿãËPÿãÌQÿãÌRÿãÍRÿäÎSÿåÏYÿíß‘ÿêØ}ÿæÑbÿæÒdÿæÒeÿæÒfÿæÒgÿèÖqÿïá—ÿåÏ[ÿäÍTÿäÎUÿäÎVÿäÎXÿåÏXÿäÎYÿäÏ[ÿåÏ\ÿåÏ^ÿåÐ^ÿæÑ`ÿæÒbÿÔÃxÿ”‡€ÿSBNÿC14ÿE37ÿJ15ÿK37ÿK6;ÿO9>ÿR;@ÿT=BÿU>CÿV>DÿV>DÿV?DÿV?DÿV?DÿV?DÿV?DÿW?EÿW?EÿW?EÿW?FÿW?EÿW?FÿW?EÿW?EÿW?EÿW?EÿW?EÿW?EÿW@FÿW@FÿW@FÿW?FÿX?EÿX?EÿX?EÿW?Eÿ\DHÿr[Xÿ[DHÿW?EÿX?EßX>EX>E:'':'':''á:''ÿ?+,ÿY@Dÿ?+,ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ;('ÿ;('ÿ;('ÿ;('ÿ;((ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<()ÿ<()ÿ<))ÿ=))ÿ=))ÿ=))ÿ<((ÿ;((ÿ9&&ÿ7%%ÿ7""ÿ9%$ÿP@>ÿ||…ÿ‡²Ùÿr¿üÿe½þÿÈüÿ‹ËëÿU²ÜÿU±ÛÿU±ÚÿU²ØÿU²×ÿV²ÖÿV²ÔÿV²ÓÿT¯ÎÿR«ÉÿR«ÇÿS«ÆÿS¬ÅÿS¬ÄÿT¬ÂÿT¬ÁÿT­ÀÿS¬¾ÿm¹Çÿµáéÿ±ÝêÿŸÕãÿ¤Ùåÿ¦Ûåÿ¥Ýåÿ¢Ýäÿ�Ýâÿ—Üàÿ‘ÝÕÿŒÞÇÿ†ÜÂÿ�Û¾ÿ|ÚºÿyÚ¶ÿwÙ´ÿvÙ²ÿvÙ±ÿwÚ¯ÿwÚ®ÿxÚ­ÿ¤äÂÿŒØ�ÿ’Ù ÿœØ´ÿgÀ�ÿc¿Šÿd¿‰ÿe¿‡ÿf¾†ÿh¾…ÿl½ƒÿr¼�ÿyµ{ÿ|§qÿ}•fÿyYÿpiLÿdTAÿYD9ÿO84ÿG00ÿC+-ÿ@)-ÿ@(-ÿ?(-ÿ?)-ÿ?)-ÿ@*-ÿA*-ÿA*.ÿ@*.ÿA*.ÿA*.ÿA*.ÿB*.ÿC+/ÿC+/ÿC+/ÿC+/ÿC+1ÿB,1ÿB,1ÿB,1ÿB,1ÿB,2ÿC,2ÿC-2ÿD.2ÿE-3ÿI13ÿK33ÿK23ÿJ23ÿJ24ÿK34ÿM46ÿQ89ÿW@>ÿcLFÿs]Nÿ‡qUÿ›…Uÿ¹§rÿÛÉ}ÿßÇQÿãÊNÿãÊMÿãÊNÿãËOÿãËQÿãÌRÿãÍRÿäÎSÿäÎTÿëÛ‚ÿìÜ‹ÿæÑcÿæÒdÿæÒeÿæÒfÿæÒgÿæÓhÿçÓiÿíß’ÿé×vÿäÍSÿäÎVÿäÎWÿåÏXÿåÏXÿåÐZÿåÐ[ÿæÐ]ÿåÐ^ÿåÑ_ÿæÑaÿæÒbÿæÓfÿÒÇ›ÿƒx‚ÿK9BÿD25ÿG26ÿK15ÿJ49ÿM7<ÿP:?ÿS;@ÿT=BÿV>CÿV>DÿV>DÿV?DÿV?DÿV?DÿV?DÿV?DÿW?DÿW?DÿW?EÿW?EÿW?EÿW?EÿW?EÿW@EÿW@EÿW@EÿW@EÿW?EÿW?EÿW?EÿW?EÿW?EÿW?EÿW?EÿW@Dÿ[DGÿr[Xÿ[DHÿW?EÿX?DáX?DX?D9''9''9''á:''ÿ?+,ÿZ@Dÿ?+,ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ;('ÿ<('ÿ<('ÿ<((ÿ<((ÿ<()ÿ<()ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ=))ÿ=))ÿ<))ÿ;((ÿ:''ÿ7%%ÿ<)(ÿ_NOÿˆ“¤ÿ†¾ëÿk¿ÿÿd¼þÿc¼ýÿh¾üÿ–Ñõÿa·ÞÿT±ÚÿU²ØÿU²×ÿV²ÖÿV²ÕÿV²ÓÿV²ÑÿT®ÌÿR«ÇÿS«ÆÿS¬ÅÿS¬ÄÿT¬ÂÿT¬ÁÿT­ÀÿT­¾ÿ`²ÂÿœÕßÿ‘Üæÿ¦Úçÿ}ÃØÿ{ÂÖÿ}ÃÖÿ�ÅÖÿ†ÇÖÿŒÊ×ÿ”ÏÔÿ�ÖËÿ¤ÚÌÿ¨ÝÎÿªßÐÿªâÏÿ¨âÎÿ£ãËÿžâÇÿ—áÂÿ�à½ÿ‰Þ·ÿ�ݲÿ”â»ÿ®ä¼ÿ¤Ü¶ÿpÖÿb¾Šÿc¿‰ÿe¿ˆÿj¿†ÿq¼„ÿy´}ÿ}¢qÿ{ŠcÿqmRÿdSCÿV@8ÿK30ÿD+-ÿ@)+ÿ>(+ÿ>(,ÿ?(-ÿ@)-ÿ@)-ÿ@)-ÿA)-ÿ@*.ÿ@*.ÿ@*.ÿA*-ÿA*-ÿ@*.ÿ@*.ÿA*.ÿA*.ÿA*.ÿB*/ÿC+/ÿC+/ÿC+/ÿC+0ÿB+1ÿB,1ÿC,1ÿB,1ÿB,2ÿB,2ÿB,2ÿC-2ÿE.3ÿG/3ÿK33ÿK33ÿK33ÿK34ÿK34ÿK34ÿL34ÿK24ÿK25ÿM46ÿQ9;ÿZCCÿkVOÿŠvbÿ§“`ÿį_ÿØÂZÿáÉSÿãËQÿãÌQÿãÍRÿãÎSÿäÎSÿéÖqÿîà–ÿçÒhÿæÑcÿæÒdÿæÒfÿæÒgÿæÒhÿçÓiÿçÔjÿêÙ|ÿîà“ÿäÏXÿäÎWÿäÏXÿåÏXÿåÏYÿåÐ[ÿæÑ[ÿæÑ]ÿæÑ^ÿæÒ_ÿæÒaÿæÓbÿëÛ‚ÿàÖ›ÿ¯¥‡ÿm_jÿF4:ÿD26ÿI15ÿK37ÿK6;ÿO9>ÿQ;@ÿSCÿV>DÿV?DÿV?DÿV?DÿW?DÿW?DÿW?EÿW?EÿW?EÿW?EÿW?DÿW?DÿW?DÿW?DÿW?DÿW?DÿW?EÿW?EÿW?EÿW?DÿW?DÿW?Dÿ[DGÿrZXÿ[CGÿW?CÿW?DáW?DW?D9''9''9''á9''ÿ?+,ÿZAEÿ?+,ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ:''ÿ;''ÿ;''ÿ;''ÿ<((ÿ<((ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ=))ÿ=))ÿ<((ÿ:''ÿE21ÿlbgÿާÂÿ‚Áôÿg½ÿÿb»ÿÿb»ýÿc¼üÿb»ûÿ†ËùÿÅåÿT±ØÿU²×ÿV²ÖÿV²ÕÿV²ÔÿV²ÒÿV²ÐÿS­ÊÿR«ÆÿS¬ÆÿS¬ÄÿS¬ÃÿT¬ÁÿT­ÁÿT­¿ÿX®¿ÿ�Í×ÿ�ÚåÿvÓßÿ¢ÞçÿŽËÜÿyÁÕÿzÂÔÿzÂÒÿzÂÑÿzÂÎÿ}Ç¿ÿȸÿ€È·ÿ�ɶÿ„˶ÿ‡Ì·ÿŒÎ¸ÿ’Ѻÿ˜Ô½ÿž×Àÿ¤ÚÃÿ¨ÝÆÿ«àÇÿ®ãÉÿÁèÓÿ‚Ì£ÿa¾ŠÿgÀŠÿo¾‡ÿxµ�ÿ|¡sÿwƒ`ÿkdMÿ[H=ÿM63ÿD,.ÿ@(,ÿ>'+ÿ>'+ÿ?(+ÿ?(+ÿ?)+ÿ?),ÿ?),ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿA).ÿA*.ÿ@+.ÿA+.ÿA*.ÿA*.ÿ@*.ÿ@*.ÿA*.ÿA*.ÿA*/ÿB*/ÿB*/ÿC+/ÿC+/ÿC+0ÿB,1ÿC,1ÿC,1ÿC,1ÿB,2ÿB,2ÿB,2ÿC-2ÿE.3ÿI14ÿK34ÿK33ÿK34ÿJ34ÿK34ÿL34ÿL35ÿL35ÿL35ÿL35ÿL36ÿL47ÿO7:ÿZCCÿoYPÿ�|]ÿµ¡cÿÒ¼`ÿßÊXÿãÍSÿäÎSÿæÒbÿîá˜ÿèÕqÿæÑcÿæÒdÿæÒeÿæÒgÿæÒhÿçÓiÿçÔjÿçÕkÿçÖnÿïâ™ÿèÔlÿäÎWÿåÏXÿåÏYÿåÐ[ÿæÑ[ÿæÑ]ÿæÒ^ÿçÓ^ÿçÔ_ÿçÔ_ÿéÙrÿèÞžÿÓÆqÿɼrÿ�’…ÿ[LXÿC16ÿG16ÿK15ÿK49ÿM8<ÿQ:?ÿS;AÿT=AÿU=BÿU=CÿV=CÿV=CÿV>CÿV>CÿV>CÿV>CÿV>CÿW>CÿW>CÿW>DÿW>DÿW>DÿW>DÿW?DÿW?DÿW?DÿW?DÿW?DÿW?DÿW?DÿW?DÿW?DÿW>DÿW>Dÿ[CGÿrZWÿ[CFÿW?CÿW?CáW?CW?C9''9''9''á9''ÿ>+,ÿYAEÿ?+,ÿ:''ÿ:''ÿ:''ÿ:''ÿ;''ÿ;''ÿ;''ÿ;'(ÿ;((ÿ;((ÿ;((ÿ<)(ÿ<)(ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ=))ÿ<((ÿL88ÿxs|ÿ�´×ÿ}Á÷ÿf¼þÿb»ÿÿb»ýÿc»üÿc¼ûÿb¼úÿoÁùÿ•Ðïÿ[´ÙÿU²×ÿV²ÕÿV²ÔÿV²ÒÿV²ÑÿV²ÏÿS­ÈÿS¬ÆÿS¬ÅÿS¬ÃÿT¬ÂÿT­ÁÿT­¿ÿT¬½ÿÃÏÿ›ÜæÿxÓàÿvÓÝÿ‹Ùâÿ£×ãÿzÂÔÿzÂÒÿ{ÂÑÿ{ÂÐÿ~ÆÄÿ€É¹ÿ�É·ÿ�ɶÿ�ʵÿ�Ê´ÿ�ʲÿ�ʰÿ�ʯÿ�É®ÿ�ɬÿ�Ê«ÿ‚ʪÿ„̪ÿƒÌ«ÿ˜×¿ÿ�Ψÿt·…ÿ{¥yÿx…eÿjcOÿYE=ÿJ31ÿA*+ÿ>'*ÿ>'*ÿ>(+ÿ?(,ÿ?(,ÿ?'+ÿ?'+ÿ?(+ÿ?)+ÿ?),ÿ?),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@).ÿA).ÿA*.ÿ@+.ÿA+.ÿA+.ÿ@*.ÿ@*.ÿ@*.ÿA*.ÿA*.ÿB*/ÿB*/ÿB*/ÿB+/ÿC+/ÿB+0ÿB,1ÿC,1ÿC,1ÿC,2ÿB,2ÿB,2ÿB-2ÿC-2ÿF/3ÿJ23ÿK34ÿK34ÿK34ÿJ34ÿK34ÿL34ÿL35ÿL35ÿL35ÿL46ÿM47ÿL47ÿK36ÿL48ÿQ;>ÿbMJÿƒnZÿ¬™dÿÏ»cÿáÌ_ÿîß�ÿêÙ~ÿæÑbÿæÒdÿæÒeÿçÓgÿçÓhÿçÔiÿèÔjÿèÕkÿèÖlÿçÖlÿë݇ÿìÞ‹ÿäÎWÿäÎXÿãÎYÿâÍZÿâÍZÿàË[ÿßË[ÿÝÊ[ÿÛÈ[ÿÜÊbÿâ×–ÿŹtÿ½¯]ÿÍÀhÿÁµ~ÿ…y|ÿMÿR;@ÿTCÿV>CÿV>CÿV>CÿV>CÿV>CÿV>DÿV>DÿV>DÿV>DÿV>CÿV?CÿW?CÿW?CÿW?CÿW>CÿW>DÿW>DÿW>CÿW>Cÿ[CFÿrZVÿ[CFÿW?BÿW>BáW>BW>B9'&9'&9'&á9''ÿ>+,ÿYAEÿ?+,ÿ:''ÿ;''ÿ;''ÿ;''ÿ;'(ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<)(ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ=))ÿ=))ÿK65ÿwqzÿ�¶Ýÿp¾üÿa»ÿÿb»þÿc»ýÿc¼üÿc¼úÿc¼ùÿc¼øÿ�ÏõÿsÀßÿT±ÕÿV²ÔÿV²ÓÿV²ÑÿV²ÐÿV±ÎÿS­ÇÿS¬ÅÿS¬ÄÿT¬ÂÿT¬ÁÿT­ÀÿS¬¾ÿm¹Çÿ Úãÿ}ÕáÿwÓÞÿwÓÝÿzÔÜÿ§Þæÿ†Ç×ÿzÂÑÿ{ÂÐÿ|ÄÉÿ€É»ÿ�ɸÿ�ɶÿ�ʵÿ�Ê´ÿ�ʳÿ�ʱÿ‚ʯÿ‚ʯÿ‚Ê­ÿ‚ʬÿ‚ʪÿ‚Ë©ÿ…̨ÿ‚Ǧÿ‹ºŸÿ– ˆÿqlWÿ]IAÿL33ÿA),ÿ='+ÿ=(+ÿ>(+ÿ>(+ÿ>(*ÿ?(*ÿ@(,ÿ?(,ÿ?'+ÿ?'+ÿ?'+ÿ?(+ÿ?)+ÿ?),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@).ÿA*.ÿ@*.ÿA+.ÿA+.ÿA+.ÿ@+.ÿ@*.ÿ@*.ÿA*.ÿB*/ÿB*/ÿB*/ÿB*/ÿB+/ÿB+0ÿB,0ÿC,1ÿC,1ÿC,1ÿC,2ÿC,2ÿB,2ÿB-2ÿC-3ÿG03ÿK33ÿK34ÿK35ÿK34ÿK34ÿK34ÿK35ÿL35ÿL35ÿL35ÿM46ÿM47ÿM47ÿL47ÿL47ÿK48ÿO8;ÿ^HHÿkYÿ²¡xÿÙÊ�ÿàÌgÿâÍbÿàÌcÿßËcÿÝÉdÿÛÈdÿÚÆdÿ×ÅdÿÕÃeÿÓÁdÿÑÀdÿÐÀjÿÞÒ•ÿ͹ZÿDzMÿDZOÿŰOÿïOÿ®OÿÁ®PÿÀ­PÿÀ®Rÿσÿ¾³}ÿ¦˜Rÿ¨šUÿŸdÿÏÁoÿ¯¢…ÿj[gÿE38ÿG05ÿK05ÿK49ÿN7=ÿQ9?ÿS;AÿTCÿV>CÿV>CÿV>CÿV>CÿV>CÿV>CÿV>CÿV>CÿV>CÿV>CÿV>CÿW>CÿW>CÿW>CÿW>CÿW>CÿW>CÿW>Cÿ[BFÿqYVÿ[BFÿW>BÿW>CáW>CW>C9'&9'&9'&á9'&ÿ?+,ÿZBFÿ?+,ÿ:''ÿ;'(ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<)(ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ<))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=((ÿJ44ÿtoxÿ€±Þÿj¾þÿb»ýÿc¼üÿc¼ûÿc¼ùÿc¼øÿb¼öÿwÅöÿ�ÍèÿW³ÕÿV²ÓÿV²ÑÿV²ÐÿV²ÏÿV±ÍÿS­ÆÿS¬ÄÿT¬ÂÿT¬ÁÿT­ÀÿT­¾ÿ_²ÁÿœÕÞÿ…ØãÿvÓÞÿwÓÝÿwÓÜÿvÓÚÿ”ÜáÿœÓÞÿzÁÐÿ{ÃÍÿȾÿ�ɸÿ�É·ÿ�ɵÿ�Ê´ÿ�ʳÿ�ʱÿ‚ʰÿ‚ʯÿ‚Ê­ÿ‚ʬÿ‚Ë«ÿ‡Ëªÿ�Æ£ÿŒ¯�ÿ}‡qÿg[NÿQ;7ÿC+,ÿ>')ÿ>&*ÿ>'+ÿ>'+ÿ>(+ÿ>)+ÿ>)+ÿ>)+ÿ>)+ÿ@(+ÿ@(,ÿ@(,ÿ@'+ÿ?'+ÿ?'+ÿ>)+ÿ>),ÿ?),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@).ÿ@).ÿ@*.ÿ@*.ÿA+.ÿA+.ÿA+.ÿA+.ÿ@+/ÿ@*/ÿA*/ÿB*/ÿB*/ÿB*/ÿB*/ÿB+/ÿA+0ÿB,0ÿC,1ÿC,1ÿC,2ÿC,2ÿC,2ÿC-2ÿC-2ÿD.3ÿH23ÿK33ÿK34ÿK35ÿJ35ÿK34ÿK34ÿK35ÿL35ÿL35ÿL35ÿM46ÿM47ÿM47ÿL47ÿL48ÿL58ÿL48ÿO8;ÿ`KKÿ„r_ÿ¨–hÿ»©aÿÀ¬YÿÀ¬Xÿ¾«Yÿ½ªYÿ½ªYÿ¼ªZÿ½«[ÿ½«\ÿ¼«]ÿ¼«]ÿÍÀ„ÿ̼uÿ¼§Iÿ½©Lÿ¾©Lÿ¾ªMÿ¾ªNÿ¾«Oÿ½«OÿÊ»rÿǽ‹ÿ¨šWÿ§™Tÿ§™Uÿ»­`ÿÒÁlÿŵxÿ’…�ÿSBMÿD15ÿI/4ÿJ27ÿL6;ÿP9>ÿS:@ÿT;AÿUCÿV=CÿV=CÿV=CÿV=CÿV=CÿV=CÿV=CÿV=CÿV=CÿV>CÿW>CÿW>CÿW>CÿW>CÿW>CÿW>Bÿ[BFÿqXVÿ[AFÿW=CÿW>CáW>CW>C:'&9'&:'&á:'&ÿ?+,ÿ[BFÿ?,-ÿ:((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<)(ÿ=)(ÿ=)(ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=()ÿH33ÿpkuÿ€¯Úÿl¾üÿc¼ûÿc¼úÿc¼øÿc¼÷ÿc¼õÿf½õÿ–Ññÿi»ØÿU²ÑÿV²ÐÿV²ÏÿW²ÎÿV±ËÿS¬ÄÿS¬ÃÿT¬ÁÿT­ÀÿT­¿ÿW®¿ÿ�Ì×ÿ‘ÛåÿvÓßÿwÓÝÿwÓÜÿwÓÛÿwÓÚÿÖÚÿ©Ýãÿ�ÅÑÿ~ÆÃÿ�ɹÿ�É·ÿ�ɶÿ�ʵÿ�ʳÿ�ʲÿ‚ʰÿ‚ʯÿ‚Ê®ÿ‚ʬÿˆË«ÿ�Ä£ÿ�¨‹ÿ|zgÿ`NEÿJ31ÿ?(*ÿ<&(ÿ=')ÿ>')ÿ>'*ÿ>'+ÿ>'+ÿ>'+ÿ>)+ÿ>)+ÿ>)+ÿ>)+ÿ?)+ÿ@),ÿ@(,ÿ@',ÿ@'+ÿ@'+ÿ?(+ÿ>)+ÿ>),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@).ÿ@*.ÿ@*.ÿA*.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+.ÿ@+/ÿA*/ÿB*/ÿB*/ÿB*/ÿB*/ÿB+0ÿA,0ÿB,0ÿC,0ÿC,1ÿC,2ÿC,2ÿC,2ÿC-2ÿC-3ÿE/3ÿI23ÿJ33ÿK34ÿK35ÿK35ÿK34ÿK34ÿK35ÿL35ÿL35ÿL35ÿM46ÿM47ÿM47ÿL47ÿL48ÿL58ÿM58ÿL48ÿQ:=ÿgSOÿŒ{bÿ­œeÿº¨\ÿ¼©Xÿ¼©Yÿ¼ªZÿ½ª[ÿ½«\ÿ½¬]ÿ½¬^ÿ½¬^ÿ´mÿÔÈ‘ÿÀ¬Qÿ¾ªLÿ¾ªMÿ¾ªNÿ¾«Oÿ¾«OÿÅ´bÿÎÄ’ÿ¬ _ÿ¦˜Sÿ§šUÿ§™Vÿ²¢\ÿϽmÿ̹nÿ³£‚ÿqcmÿF4:ÿG/4ÿI15ÿJ4:ÿN8=ÿQ:?ÿS;@ÿTCÿV>CÿW>CÿW>BÿW=BÿW=Bÿ[AFÿqXWÿ[AFÿV=BÿW=BáW>BW=B:'&:'&:''á:'&ÿ?,,ÿ[BFÿ?,-ÿ:((ÿ:((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ=)(ÿ=)(ÿ=)(ÿ=))ÿ=))ÿ=))ÿ=))ÿ=)*ÿ=)*ÿ=**ÿ=**ÿ=**ÿ=**ÿ=))ÿG32ÿohpÿ�®Õÿm¿ùÿc¼øÿc¼÷ÿc¼öÿd¼õÿc»óÿ‚Éôÿ†ÈáÿU²ÐÿV²ÐÿV²ÎÿW³ÍÿV±ÉÿS¬ÃÿT¬ÁÿT­ÁÿT­¿ÿT¬½ÿ~ÂÎÿ›ÜæÿxÔßÿwÓÝÿwÓÜÿwÓÛÿwÓÚÿwÓØÿwÓ×ÿžÞáÿ–ÑÒÿȺÿ�É·ÿ�ɶÿ�ʵÿ�ʳÿ�ʲÿ�ʰÿ‚ʯÿ‚Ê®ÿˆË­ÿ‘Ã¥ÿޤ‹ÿxscÿ[F@ÿF-.ÿ>&)ÿ=&)ÿ>')ÿ>')ÿ=')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ>'+ÿ>(+ÿ>)+ÿ>)+ÿ>)+ÿ>)+ÿ?),ÿ@),ÿ@(,ÿ@(,ÿ@',ÿ@'+ÿ?(+ÿ?),ÿ?),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@).ÿ@).ÿ@*.ÿ@*.ÿA*.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+/ÿB+0ÿB*0ÿB*/ÿB*/ÿB*/ÿA+0ÿA,0ÿB,0ÿC,0ÿC,2ÿC,2ÿC,2ÿC,2ÿC-2ÿD-3ÿF03ÿJ33ÿJ33ÿK34ÿJ35ÿK35ÿK35ÿK35ÿK35ÿL35ÿL35ÿM36ÿM46ÿM46ÿM47ÿM48ÿL48ÿL58ÿM58ÿM58ÿM58ÿXCDÿzh[ÿ£’hÿ¸¦aÿ¼ªZÿ¼ª[ÿ½«\ÿ½¬]ÿ½¬^ÿ½¬_ÿ½­`ÿ½®aÿÑÆ�ÿɸjÿ½©Kÿ¾ªNÿ¾«Oÿ¾«OÿÀ¯WÿÐÅŽÿ´¨mÿ¦˜Rÿ§šTÿ§™Vÿ§˜Wÿ«›ZÿÉ·kÿ͹mÿıwÿ–‡‚ÿTDNÿE03ÿJ/4ÿI38ÿL6<ÿP9>ÿR;@ÿS<@ÿT')ÿ>')ÿ>')ÿ>')ÿ>')ÿ?')ÿ>'*ÿ>'*ÿ>'*ÿ>'*ÿ>(*ÿ>)+ÿ>)+ÿ>)+ÿ>),ÿ?),ÿ@),ÿ@(+ÿ@(,ÿ@(,ÿ?(,ÿ?(,ÿ?),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@).ÿ@*.ÿ@*.ÿA*.ÿA*.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+/ÿB+0ÿB+0ÿB*/ÿB*/ÿB*0ÿA+0ÿA,0ÿB,0ÿC,1ÿC,2ÿC,2ÿC,2ÿC-2ÿD-3ÿD-3ÿH13ÿJ33ÿJ33ÿJ34ÿJ35ÿK35ÿK35ÿK35ÿK35ÿL35ÿL35ÿM36ÿM46ÿM46ÿM47ÿM48ÿL58ÿL58ÿM58ÿM58ÿL47ÿQ;=ÿlYSÿ™‰gÿ¶¥dÿ½«\ÿ½¬\ÿ½¬^ÿ½¬_ÿ½­`ÿ½®aÿ½®aÿǺxÿÓÆŠÿ¾«Oÿ¾«Nÿ¾«Pÿ¾¬Qÿ΂ÿ¾´~ÿ¦˜Sÿ§™Tÿ§šUÿ§™Wÿ¨˜Wÿ¨—YÿÀ¬gÿÌ·oÿÊ´qÿ´¢„ÿo`jÿF48ÿI/3ÿI26ÿK5:ÿO8=ÿR:?ÿS;@ÿT**ÿ=))ÿF00ÿlagÿ‚©Ëÿo¿õÿd¼ôÿd¼òÿd¼ñÿc¼ïÿ‹Íñÿ{ÃÛÿU²ÍÿW³ÌÿW³ËÿV¯ÅÿT¬ÁÿT­ÀÿT­¾ÿ_²Áÿ›ÕÞÿ†ØãÿvÓÞÿwÓÝÿwÓÜÿwÓÛÿwÓÙÿwÓ×ÿxÓÖÿxÔÕÿ|ØÈÿ©ãÒÿ‘пÿ€Éµÿ�Ê´ÿ�ʳÿ�ʱÿ…˰ÿ�È­ÿ�­•ÿzwiÿZEAÿD,-ÿ<&)ÿ='*ÿ='*ÿ=')ÿ=&*ÿ=&*ÿ>')ÿ>')ÿ>')ÿ>')ÿ?')ÿ?'*ÿ>'*ÿ>'*ÿ>'*ÿ>(*ÿ>(*ÿ>)*ÿ>)*ÿ>)+ÿ?),ÿ?),ÿ@(+ÿ@(+ÿ@(,ÿ@(,ÿ?),ÿ?)-ÿ?)-ÿ@),ÿA),ÿ@),ÿ@),ÿ@)-ÿ@*.ÿ@*.ÿ@*.ÿA*.ÿA*.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+.ÿB+0ÿB+0ÿB+0ÿB*0ÿB*0ÿA*0ÿA,0ÿB,0ÿB,0ÿB,1ÿC,2ÿC,2ÿC,2ÿC-2ÿD-3ÿE.3ÿI23ÿJ33ÿJ34ÿJ34ÿJ35ÿK35ÿK35ÿK35ÿK35ÿL35ÿL35ÿM36ÿM46ÿM46ÿM47ÿL48ÿL58ÿL58ÿM58ÿM58ÿL58ÿN79ÿdPMÿ“‚fÿµ¥fÿ½¬^ÿ½¬_ÿ½­_ÿ½®aÿ¾®bÿ¾¯cÿ¿±fÿÔÊ•ÿų`ÿ¾«Nÿ¾«OÿÉ»qÿǽŒÿ¨›Wÿ§™Tÿ§šUÿ§™Vÿ¨˜Wÿ¨—Yÿ¨•Zÿ¶¡bÿ˵oÿË´pÿÅ®|ÿ‘�€ÿP@HÿG/2ÿJ15ÿJ59ÿN7<ÿP9>ÿR:?ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿU;AÿU;AÿU;AÿU**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>))ÿE0/ÿj^cÿ‚§Çÿq¿òÿd¼ñÿd¼ðÿc¼ïÿsÂïÿ”Ïæÿ[µÍÿW³ËÿX³ÊÿU¯ÄÿT­ÀÿT­¾ÿW®¾ÿ�ÌÖÿ‘ÛåÿvÓÞÿwÓÝÿwÓÜÿwÓÛÿwÓÙÿwÓØÿxÓÖÿxÓÖÿzÖÌÿ|Ú¾ÿ”àÈÿ¥ÛÌÿ�Ê´ÿ�ʳÿ‚˲ÿ‹Ê°ÿ’¸Ÿÿ�…uÿ_MGÿE..ÿ<%(ÿ=&(ÿ=&(ÿ=&)ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ='*ÿ>'*ÿ>'*ÿ?')ÿ?')ÿ?'*ÿ>'*ÿ>'*ÿ?(*ÿ?(*ÿ?(*ÿ>(*ÿ>)*ÿ?)+ÿ?)+ÿ?)+ÿ@(+ÿ@(+ÿ@(,ÿ?),ÿ?)-ÿ?)-ÿ@)-ÿ@)-ÿA),ÿA),ÿA),ÿ@)-ÿ@*.ÿ@*.ÿA*.ÿA*.ÿA*.ÿA*.ÿA+.ÿA+.ÿA+.ÿA+/ÿB+0ÿB+0ÿC+0ÿB+0ÿB*0ÿA+0ÿA+0ÿB,0ÿB,0ÿB,1ÿC,2ÿC,2ÿC-2ÿC-2ÿD-3ÿF/3ÿJ33ÿJ33ÿJ34ÿJ34ÿJ35ÿK35ÿK35ÿK36ÿK35ÿL35ÿL35ÿM36ÿM46ÿM46ÿM47ÿL48ÿL58ÿL58ÿM58ÿM58ÿL58ÿL58ÿ`MJÿ‘�fÿ¶¦hÿ½­_ÿ½­`ÿ½®bÿ¾¯cÿ¾°cÿ½¯cÿËÀƒÿÏÂ�ÿ½«NÿÄ´bÿÎÄ’ÿ­ `ÿ¦˜Sÿ§šUÿ§™Vÿ¨˜Wÿ¨—Xÿ©–Zÿ©•[ÿ­˜_ÿƯnÿ̳rÿ˱vÿ­š‡ÿdV_ÿF04ÿI03ÿI48ÿM7;ÿP9=ÿQ:?ÿS;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿU;AÿU;AÿU;AÿU*)ÿ>*)ÿ>*)ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>))ÿD/.ÿh[_ÿ‚¥Áÿr¿ïÿd¼ïÿd¼îÿe½ìÿ”Ðíÿp¾ÓÿV²ÉÿX³ÈÿU®ÂÿT­¿ÿT¬½ÿ}ÁÍÿœÜåÿxÔßÿwÓÝÿwÓÜÿwÓÛÿwÓÚÿwÓØÿxÓ×ÿxÓÖÿyÕÑÿ}ÙÁÿ~Ú¼ÿ‚ܾÿ­ãÑÿŠÎ¹ÿ†Ë³ÿ‘ªÿ‰˜†ÿi[RÿJ31ÿ=&(ÿ<%(ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=')ÿ=&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ='*ÿ>(*ÿ>(*ÿ?(*ÿ?'*ÿ>'*ÿ>'*ÿ>'*ÿ?(*ÿ?(*ÿ?(*ÿ?(*ÿ?)*ÿ?)+ÿ?)+ÿ?(+ÿ@(+ÿ@(+ÿ@),ÿ?),ÿ?)-ÿ?)-ÿ@)-ÿ@*-ÿA*-ÿA)-ÿA)-ÿA)-ÿ@*.ÿ@*.ÿA*.ÿA*.ÿA*.ÿA*.ÿA+.ÿA+.ÿA+.ÿB+/ÿB+0ÿB+0ÿC+0ÿC+0ÿB+1ÿA+0ÿB+0ÿB,0ÿB,0ÿB,1ÿC,2ÿC,2ÿC-2ÿD-3ÿD-3ÿH13ÿJ33ÿJ33ÿJ34ÿI34ÿJ35ÿK35ÿK36ÿK36ÿK35ÿL35ÿL35ÿM36ÿM36ÿM46ÿM47ÿL48ÿL58ÿL58ÿM58ÿM58ÿL58ÿL57ÿaMJÿ–†hÿ»¬mÿ¿±fÿ¾°dÿ¾¯bÿ½¯bÿ½¯cÿÁ´lÿÕË•ÿÄ´`ÿÐÅ�ÿµ©nÿ¦˜Rÿ§šTÿ§™Vÿ¨˜Wÿ¨—Xÿ©–Yÿ©•[ÿ©”\ÿ¨’]ÿ¿§kÿ̲tÿ̱uÿ¿¨ƒÿquÿJ7<ÿI/2ÿI37ÿL6:ÿN8=ÿP:>ÿR;@ÿS;@ÿS;@ÿS;@ÿS;@ÿS;@ÿS;@ÿS;@ÿT;@ÿT;@ÿT;AÿT;@ÿT;@ÿT<@ÿT<@ÿT<@ÿT<@ÿU<@ÿU<@ÿU;AÿU;AÿU;AÿU;AÿU;@ÿY@CÿpWUÿZACÿU<@ÿU=@áU=AU=@:'':'':''á:''ÿ@,,ÿ]CGÿA,,ÿ;('ÿ;('ÿ;('ÿ;('ÿ;((ÿ;))ÿ;))ÿ;))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ<))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>))ÿC.-ÿfX[ÿƒ¢¼ÿs¿íÿe¼íÿd¼ëÿ}Çíÿ�ÌßÿX³ÉÿX³ÇÿU®ÀÿS¬½ÿl¸Æÿ Úãÿ~ÕáÿvÓÝÿwÓÜÿwÓÛÿwÓÚÿwÓØÿxÓ×ÿxÓÖÿxÔÔÿ|ØÅÿ~Ú½ÿ~Ú¼ÿ}ÛºÿžãÊÿ¨ÖÃÿ�­™ÿwqfÿR=:ÿ?()ÿ<%&ÿ=&'ÿ=&(ÿ=&(ÿ=&(ÿ>&(ÿ=&)ÿ>&)ÿ>')ÿ>&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=&)ÿ=')ÿ>(*ÿ?(*ÿ?(+ÿ>(+ÿ>'+ÿ>(*ÿ>(*ÿ?(*ÿ?(*ÿ?(*ÿ@)+ÿ@)+ÿ?)+ÿ?(*ÿ@(*ÿ@(+ÿ?),ÿ?)-ÿ?)-ÿ@)-ÿ@)-ÿ@*-ÿA*-ÿA)-ÿA)-ÿA*-ÿ@*.ÿA*.ÿA*.ÿA*.ÿA*.ÿA*.ÿA+.ÿA+.ÿA+.ÿB+/ÿB+0ÿB+0ÿC+0ÿC+0ÿA+1ÿA+1ÿB+0ÿB,0ÿB,0ÿB,1ÿC,2ÿC,2ÿC-2ÿD-3ÿE.3ÿH13ÿJ33ÿJ33ÿJ34ÿI34ÿJ35ÿK35ÿK36ÿK36ÿK35ÿK35ÿL35ÿM36ÿM36ÿM46ÿM47ÿL48ÿL58ÿL58ÿM58ÿM58ÿL47ÿL57ÿhTPÿ¯¡‰ÿÓÅœÿÕȘÿÒÆ“ÿÏÃŒÿÌÀ…ÿȽ}ÿÕÌ›ÿÙÏŸÿ¾³}ÿ¦˜Sÿ§™Tÿ§šVÿ¨˜Wÿ¨˜Xÿ¨–Yÿ©•Zÿ©•\ÿ©”]ÿ¦�\ÿµ�fÿ̱uÿͰvÿÉ­}ÿ™‰ƒÿUDLÿH.1ÿI26ÿK59ÿO8<ÿQ9>ÿR:?ÿR;@ÿS;@ÿS;@ÿS;@ÿS;@ÿS;@ÿS;@ÿS;@ÿS;@ÿT;@ÿT;@ÿT;@ÿT<@ÿT<@ÿT;@ÿT;@ÿT;@ÿU;@ÿU;@ÿU;@ÿU;@ÿU;@ÿU;@ÿY@CÿoWUÿYACÿU=@ÿU<@áU<@U<@:'':'':''á;''ÿA,,ÿ]CGÿA,,ÿ;('ÿ;((ÿ;)(ÿ;)(ÿ;)(ÿ;)(ÿ;))ÿ;))ÿ;))ÿ<))ÿ<))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ>*)ÿ>*)ÿ>*)ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>)*ÿB--ÿdUXÿƒ ·ÿuÀêÿe½êÿi¿êÿ˜ÒéÿgºÍÿW²ÅÿT­¾ÿ^±Àÿ›ÔÝÿ‡ØãÿvÓÞÿwÓÝÿwÓÜÿwÓÛÿwÓÙÿwÓ×ÿxÓÖÿxÔÕÿz×Ëÿ~Ú¾ÿ~Ú¼ÿ~Û»ÿ„ܺÿ—гÿ•™�ÿaOKÿC,-ÿ;%'ÿ<&'ÿ=&'ÿ=&'ÿ=&'ÿ=&(ÿ=&(ÿ>&(ÿ=&(ÿ=&)ÿ>')ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&)ÿ=&)ÿ=&)ÿ=')ÿ>')ÿ>'*ÿ>(+ÿ>(+ÿ>(+ÿ>(+ÿ>(+ÿ?(*ÿ?(*ÿ?(*ÿ@)+ÿ@)+ÿ@(*ÿ?(*ÿ@(*ÿ?)*ÿ?)+ÿ?)-ÿ@)-ÿ@)-ÿ@)-ÿ@*-ÿA*-ÿA*.ÿA*.ÿA*-ÿ@*.ÿA*.ÿA*.ÿ@*.ÿA*.ÿA*.ÿA+.ÿA+.ÿB+/ÿB+/ÿB+0ÿB+0ÿC+0ÿC+1ÿB,1ÿA,1ÿB+0ÿB,0ÿB,1ÿB,1ÿC,2ÿC,2ÿC-2ÿD-3ÿE.3ÿI23ÿJ33ÿJ34ÿJ34ÿJ34ÿJ35ÿK35ÿK36ÿK36ÿK35ÿK35ÿL35ÿM36ÿM36ÿM46ÿM47ÿL48ÿL58ÿL58ÿM58ÿL58ÿK47ÿM79ÿuaYÿ´šxÿÉ­yÿ̱ÿÏ·ˆÿÒ¼�ÿÕÁ—ÿÙɤÿÔ˨ÿª�[ÿ§™Sÿ§šUÿ§™Wÿ¨˜Wÿ¨—Yÿ©•Zÿ©•\ÿ©”]ÿ©“^ÿ¥Ž]ÿ¬”bÿÊ®tÿͯwÿÍ­{ÿ°™ˆÿfV_ÿH.2ÿJ15ÿK48ÿN7;ÿQ8=ÿR:>ÿS:?ÿS:@ÿS:@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿU;@ÿU;@ÿU<@ÿU<@ÿY@CÿoVTÿY@CÿU<@ÿU<@áU<@U<@:'':'':''á:''ÿA,-ÿ]DHÿA,-ÿ;((ÿ;)(ÿ;)(ÿ;)(ÿ;)(ÿ;)(ÿ;)(ÿ;))ÿ<))ÿ<))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=*)ÿ>*)ÿ>*)ÿ>*)ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ?**ÿ?**ÿ?**ÿ>**ÿB,,ÿcRTÿ‚�²ÿvÀçÿe½èÿ‡ËëÿƒÈ×ÿV²ÃÿW®¾ÿŽËÖÿ’ÛåÿvÓÞÿwÓÝÿwÓÜÿwÓÛÿwÓÙÿwÓ×ÿxÓÖÿxÔÖÿyÕÐÿ}ÙÀÿ~Ú¼ÿÛ¼ÿŠÚºÿ�¹¡ÿvqgÿN98ÿ<&)ÿ;%(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ=&'ÿ=&'ÿ=&(ÿ>&(ÿ=&(ÿ=&)ÿ=')ÿ>')ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&)ÿ>&)ÿ>')ÿ>')ÿ>'*ÿ='*ÿ='*ÿ>(+ÿ>)+ÿ>)+ÿ?(+ÿ?(+ÿ@(+ÿ@)+ÿ@)*ÿ@(*ÿ@(*ÿ@(*ÿ?)*ÿ?)+ÿ?),ÿ@)-ÿ@)-ÿ@)-ÿ@*-ÿ@*-ÿA*.ÿA+.ÿ@*.ÿA*.ÿA*.ÿA*.ÿ@*.ÿA*.ÿA*.ÿA+.ÿA+.ÿB+/ÿB+/ÿB+0ÿB+0ÿC+0ÿB+1ÿB,1ÿB,1ÿB,1ÿB,0ÿB,1ÿB,1ÿC,2ÿC-2ÿC-2ÿD-3ÿF/3ÿJ23ÿJ33ÿJ34ÿJ34ÿJ34ÿJ35ÿJ35ÿK36ÿK36ÿK36ÿK35ÿL36ÿM36ÿM36ÿM46ÿM47ÿL48ÿL58ÿL58ÿM58ÿL47ÿJ36ÿS=>ÿ‹tcÿ¼Ÿnÿãiÿ£iÿäjÿÃ¥lÿ½¥qÿÊ¿šÿ³§lÿ¦™Sÿ§™Vÿ¨˜Wÿ¨—Xÿ©–Zÿ©•[ÿ©”]ÿ©“^ÿ©’_ÿ¥�^ÿ¦�_ÿħrÿήyÿάzÿ¿£†ÿzkqÿJ27ÿH04ÿJ48ÿN7:ÿQ8<ÿR9=ÿS:>ÿS:?ÿS:?ÿS:?ÿT;?ÿT;?ÿT;?ÿT;?ÿT;?ÿT;?ÿT;?ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT;@ÿT<@ÿT<@ÿU<@ÿU<@ÿU;@ÿY?CÿpUTÿY@CÿU<@ÿU<@áV<@V<@:'':'':''á:''ÿ@,-ÿ^EIÿA--ÿ;((ÿ;((ÿ;)(ÿ;)(ÿ;)(ÿ<)(ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ<))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=*)ÿ=*)ÿ=*)ÿ=*)ÿ>*)ÿ>*)ÿ?*)ÿ?*)ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿB,,ÿaOQÿ‚š­ÿw¿äÿpÃèÿ˜Òãÿ]´Äÿ{ÁÌÿœÜåÿxÔßÿwÓÝÿwÓÜÿwÓÛÿwÓÚÿwÓØÿxÓ×ÿxÓÖÿxÔÓÿ|ØÄÿ~Ú¼ÿ�Û½ÿ�Ô·ÿŠŸ�ÿcSOÿC,-ÿ;$'ÿ<&(ÿ<&(ÿ<&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&)ÿ=&)ÿ=')ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&)ÿ>&)ÿ?')ÿ>'*ÿ='*ÿ='*ÿ='*ÿ=(*ÿ=(*ÿ>)+ÿ?)+ÿ?)+ÿ@(,ÿ@)+ÿ@(*ÿ@(*ÿ@(*ÿ@)*ÿ?)*ÿ?)+ÿ?),ÿ@),ÿ@)-ÿ@)-ÿ@*-ÿ@*.ÿA*.ÿA+.ÿ@+.ÿA*.ÿA*.ÿA*.ÿ@*.ÿ@*.ÿA*.ÿA+.ÿA+/ÿB+/ÿB+/ÿB+/ÿB+0ÿC+0ÿB+1ÿB,1ÿB,1ÿB,1ÿB,1ÿB,1ÿB,1ÿC,1ÿC-2ÿD-3ÿD-3ÿG/3ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿK36ÿK36ÿK36ÿK35ÿL35ÿM36ÿM36ÿM46ÿM47ÿM48ÿL58ÿL58ÿL47ÿK36ÿH25ÿdOKÿ§Žnÿ¤lÿÃ¥kÿĦmÿ¿¥nÿ´¢qÿÀ²‰ÿĺŒÿ§™Vÿ¨˜Wÿ¨—Xÿ©–Zÿ©•[ÿ©”]ÿ©”^ÿ©“_ÿª‘`ÿ¥Œ^ÿ£Š_ÿ»žnÿέ{ÿΫ{ÿȨ„ÿ�}}ÿP:@ÿH/3ÿI48ÿM6;ÿP8=ÿQ9>ÿR:>ÿS:>ÿS:?ÿS:?ÿS:?ÿS;?ÿT;?ÿT;?ÿT;?ÿT;?ÿS;?ÿS;?ÿS;@ÿT;@ÿT;@ÿT;@ÿT<@ÿT<@ÿT*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ?*)ÿ?*)ÿ?*)ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿA++ÿ_MNÿ‚—¨ÿ{Áâÿ’ÐéÿŒÊÖÿ�Ùâÿ}ÕáÿuÒÝÿvÓÜÿvÓÛÿwÓÚÿwÓØÿxÓ×ÿxÓÖÿxÔÕÿ{×Éÿ~Ú½ÿ…Û¾ÿ’ɰÿ€…yÿVA?ÿ=&(ÿ:$&ÿ;%'ÿ<%'ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ=&(ÿ<&)ÿ<&*ÿ<'*ÿ=')ÿ=&(ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ>&)ÿ?&)ÿ?'*ÿ>'*ÿ>'*ÿ>'*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ>)+ÿ@),ÿ@),ÿ@(+ÿ@(*ÿ@(*ÿ@(*ÿ?)*ÿ@)+ÿ@)+ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@*-ÿ@*.ÿA+.ÿ@+.ÿA+.ÿA+.ÿA*/ÿA*.ÿA*.ÿA*.ÿA*.ÿA+.ÿB+/ÿB+/ÿB+/ÿB+/ÿB+0ÿB+1ÿB,1ÿB,1ÿC,1ÿB,1ÿB,1ÿB,1ÿB,1ÿC,1ÿC-2ÿD-3ÿD-3ÿG03ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿK36ÿK36ÿK36ÿK35ÿL35ÿM36ÿM36ÿM46ÿM46ÿM47ÿL48ÿK48ÿK46ÿH14ÿM8:ÿ†p`ÿ½ pÿĦlÿÁ¦nÿ·¤qÿ´£rÿ¶¦xÿËÁžÿ¯¡dÿ¨—Wÿ¨–Yÿ©•[ÿ©•\ÿ©”]ÿ©“^ÿª’`ÿ©�aÿ¥‹_ÿ£‰_ÿ±”iÿÍ«{ÿΫ}ÿÌ©‚ÿ¢Œ…ÿYDLÿG.2ÿH37ÿL6:ÿO8<ÿQ9>ÿR:?ÿR:?ÿR:?ÿR:?ÿR:?ÿR:?ÿS;?ÿS;?ÿS;?ÿS;?ÿS;?ÿS;?ÿS;>ÿS;?ÿT;?ÿT:?ÿT:?ÿT;?ÿT;?ÿT;?ÿT;?ÿT;?ÿU;?ÿY?CÿoUSÿY?BÿT;?ÿT;?áT;?T;?5"$5"$5"$á6#%ÿ?+,ÿ]EIÿ@--ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<)(ÿ<)(ÿ<)(ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ<*)ÿ<*)ÿ=*)ÿ=*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ?*)ÿ?*)ÿ?*)ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ>**ÿ@++ÿ]JKÿ“ž§ÿ´ÚæÿÆèíÿ¨âéÿ“Üäÿ�Úâÿ†Øßÿ€ÖÝÿ|ÕÚÿyÔØÿxÓÖÿwÓÕÿxÕÎÿ}Ú¿ÿ‰Ú½ÿ‘º¥ÿtmfÿM77ÿ?**ÿ>))ÿ<&(ÿ;%'ÿ;%'ÿ<%'ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&(ÿ<&)ÿ<'*ÿ<(*ÿ<')ÿ=')ÿ=&)ÿ>&(ÿ>&(ÿ>&(ÿ>&(ÿ?&)ÿ?&)ÿ?'*ÿ>'*ÿ>'*ÿ>'*ÿ>(*ÿ=(*ÿ=(*ÿ=(*ÿ>(+ÿ?),ÿ@),ÿ@)+ÿ@(+ÿ@(*ÿ?(*ÿ?)*ÿ@)+ÿ@)+ÿA),ÿ@),ÿ@),ÿ@),ÿ@*-ÿ@*.ÿA+.ÿ@+.ÿA+.ÿA+.ÿA+/ÿA*.ÿA*.ÿA*.ÿA*.ÿA+.ÿB+/ÿB+/ÿB+/ÿB+/ÿB+0ÿB+1ÿB,1ÿC,1ÿC,1ÿB,1ÿB,2ÿB,1ÿB,1ÿC,1ÿC-2ÿD-3ÿD-3ÿG03ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿK36ÿK36ÿK36ÿK35ÿL35ÿM36ÿM36ÿM46ÿM46ÿM47ÿL47ÿJ36ÿH25ÿE03ÿhSMÿ°”pÿænÿ¹¤pÿ´£rÿ´£sÿ³£sÿŸ”ÿ¾²ƒÿ¨–Xÿ©•Zÿ©•\ÿ©”]ÿ©“^ÿª’`ÿª‘aÿ©�bÿ¥Š`ÿ¤‰`ÿªŒeÿȦyÿΪÿΩ�ÿ°–ˆÿeQXÿH-2ÿH27ÿK5:ÿN7<ÿP8=ÿR9>ÿR9>ÿR9>ÿR9>ÿR9>ÿR9>ÿR9>ÿS:>ÿS:>ÿS:>ÿS:>ÿS:>ÿS:>ÿS:>ÿS:>ÿT:?ÿT:?ÿT:?ÿT;?ÿT;@ÿT;?ÿT;?ÿT;?ÿX?BÿnUSÿX?BÿT:?ÿT:?áT:?T:?5"$5"$5"$á5"$ÿ<'*ÿ\CHÿA--ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<)(ÿ<)(ÿ<)(ÿ<*(ÿ<*(ÿ<*)ÿ<*)ÿ=*)ÿ=*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ?*)ÿ?*)ÿ?*)ÿ>*)ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ?++ÿ\IHÿ›ž�ÿ½ÜÞÿŸÞÙÿ—ÛÖÿžÞÙÿ£àÛÿ¦áÞÿ§âßÿ¦âàÿ¢áßÿœàÝÿ™áÐÿ›ÝÅÿ�«›ÿiZVÿF00ÿ?**ÿ@++ÿ@++ÿ?*+ÿ=()ÿ;%'ÿ;%'ÿ<%'ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ=&(ÿ>&(ÿ=&)ÿ=&*ÿ='*ÿ=')ÿ<')ÿ=')ÿ=')ÿ=')ÿ=&)ÿ>&(ÿ>&(ÿ?&)ÿ?&*ÿ>'*ÿ>'*ÿ>'*ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ=(*ÿ>(,ÿ?(,ÿ?(,ÿ@(+ÿ@)+ÿ@)+ÿ?)*ÿ?)+ÿ@)+ÿA)+ÿA),ÿA),ÿ@),ÿ@),ÿ@*-ÿ@*.ÿ@+.ÿ@+.ÿA+.ÿA+.ÿA+/ÿA*/ÿA*.ÿA*.ÿA*.ÿA+/ÿB+/ÿB+/ÿB+/ÿB+/ÿB+0ÿB+1ÿB,1ÿC,1ÿC,1ÿC,1ÿB,2ÿB,1ÿB,1ÿB,1ÿC-2ÿD-3ÿD-3ÿH13ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿK36ÿK36ÿK36ÿK35ÿL35ÿM36ÿM36ÿM46ÿM46ÿL37ÿJ36ÿH25ÿD/2ÿS>=ÿœ‚hÿ»¤rÿ´£rÿ´£sÿ´¤tÿ´£uÿº©€ÿË¿�ÿ¬š`ÿ©•[ÿ©”]ÿ©“^ÿ©’_ÿª‘aÿª�bÿ©Žbÿ¤‰`ÿ¥ˆaÿ¦ˆcÿÀžuÿÏ©€ÿϨ�ÿ»�Šÿr^cÿI/3ÿH16ÿK5:ÿN7<ÿP8=ÿQ9>ÿR9>ÿR9>ÿR9>ÿR9>ÿR9>ÿR9>ÿR9>ÿS:>ÿS:>ÿS:>ÿS:>ÿS:>ÿS:>ÿS:?ÿS:?ÿT:?ÿT:?ÿT:?ÿS;?ÿS;?ÿS;?ÿS;?ÿW?BÿnTSÿX>BÿT:?ÿT:?áT:?T:?6"$6"$6"$á6"$ÿ<'*ÿ[AGÿ>)+ÿ:''ÿ;((ÿ<((ÿ<((ÿ<((ÿ<((ÿ<)(ÿ<*(ÿ<*(ÿ=*(ÿ=*(ÿ=*(ÿ=*)ÿ=*)ÿ=*)ÿ=*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ>*)ÿ=))ÿ=))ÿ=))ÿ=))ÿ>*)ÿ>*)ÿ>**ÿ?**ÿ?*+ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿYEEÿ�”–ÿ£ÖÒÿxÐÇÿvÐÄÿwÐÄÿzÑÃÿ~ÒÄÿƒÔÅÿ‰ÖÇÿ–ÝÁÿ¬Û¾ÿœ£—ÿaOMÿC-.ÿ@++ÿA+,ÿA+,ÿ@+,ÿ@+,ÿ@++ÿ?**ÿ='(ÿ;%'ÿ<%'ÿ<%(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ=&(ÿ>&(ÿ=&)ÿ='*ÿ='*ÿ=')ÿ=')ÿ=')ÿ=')ÿ=')ÿ=')ÿ=')ÿ>&)ÿ?&)ÿ?&*ÿ>&*ÿ>'*ÿ>'*ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ>(+ÿ?(,ÿ?(,ÿ?'+ÿ?(+ÿ@)+ÿ@)+ÿ?)+ÿ?)+ÿ@)+ÿA)+ÿA),ÿA),ÿ@),ÿ@)-ÿ@*-ÿ@+.ÿ@+.ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA*/ÿA*.ÿA*.ÿB*/ÿB+/ÿB+/ÿB+/ÿB+/ÿB+0ÿB+1ÿB,1ÿC,1ÿC,1ÿC,1ÿB,2ÿB,2ÿB,1ÿB-1ÿC-2ÿD-3ÿD-3ÿH13ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿJ36ÿK36ÿK36ÿK35ÿL35ÿM36ÿM36ÿM36ÿL35ÿJ25ÿH14ÿC.2ÿG24ÿƒn\ÿ±Ÿuÿ´£sÿ´¤tÿ´£uÿµ£wÿµ¢xÿÊ»�ÿ¸¨yÿ¨“[ÿ©“^ÿ©’_ÿª’`ÿª�bÿª�cÿ¨�cÿ¥ˆaÿ¥‡cÿ¤†dÿ¶”pÿΨ�ÿϧ‚ÿ¡Šÿ~ilÿK25ÿG14ÿK49ÿN6;ÿO8<ÿQ9=ÿQ9=ÿR9>ÿR9>ÿR9>ÿR9=ÿR9>ÿR9>ÿR9>ÿR:>ÿS:>ÿS:>ÿS:>ÿS:>ÿR:>ÿR:>ÿR:>ÿS:?ÿS:?ÿS:?ÿS:?ÿS:?ÿS:?ÿW>BÿmTSÿX>AÿT:>ÿT:?áT:?T:?6"$6"$6"$á6"$ÿ<'*ÿ[AGÿ<'*ÿ6#$ÿ9&'ÿ;((ÿ<)(ÿ<)(ÿ<)(ÿ=)(ÿ=)(ÿ=*(ÿ=*(ÿ=*(ÿ=*(ÿ=*(ÿ=*(ÿ=*)ÿ=*)ÿ=*)ÿ>*)ÿ>*)ÿ>*)ÿ=))ÿ=))ÿ=))ÿ=))ÿ=))ÿ=)*ÿ>)*ÿ>**ÿ>**ÿ>**ÿ?**ÿ?+*ÿ?+*ÿ?+*ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿYDDÿ’–•ÿŽÍÅÿyÑÅÿwÐÃÿwÐÁÿwÐÀÿvоÿ|Ó¹ÿ�ͪÿ‚�|ÿWDBÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA+,ÿ?)*ÿ<&(ÿ<%(ÿ<%(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&)ÿ='*ÿ=')ÿ=')ÿ=')ÿ=')ÿ>')ÿ>')ÿ=')ÿ=')ÿ>')ÿ>'*ÿ>&+ÿ>&*ÿ>'*ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ?(+ÿ?(,ÿ?(,ÿ?'+ÿ?'+ÿ?(+ÿ?)+ÿ?*,ÿ?),ÿ@)+ÿA)+ÿA),ÿA),ÿA),ÿ@)-ÿ@*-ÿ@+-ÿ@+.ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA*/ÿA*.ÿA*.ÿB*/ÿB+/ÿB+/ÿB+/ÿB+/ÿB+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,1ÿB,2ÿB,2ÿB,1ÿB-1ÿC-2ÿD-3ÿD-3ÿH13ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿJ36ÿK36ÿK36ÿK35ÿL35ÿL36ÿL36ÿL25ÿJ24ÿG03ÿC-0ÿD,/ÿr]Qÿ¬›uÿ´¤tÿ´£uÿµ£vÿµ¢xÿµ xÿ¿¬ŠÿȺ˜ÿª•_ÿ©“_ÿª’`ÿª‘aÿª�cÿª�dÿ¨‹cÿ¥‡bÿ¥‡dÿ¥†eÿ­Œkÿ̤€ÿЦ„ÿÇ£‹ÿŒwxÿM59ÿG04ÿJ48ÿM6;ÿO7<ÿP9=ÿP9=ÿP9=ÿQ9=ÿQ9=ÿQ9=ÿQ9=ÿQ9=ÿQ9>ÿQ9>ÿR9>ÿR:>ÿR:>ÿR:>ÿR:>ÿR:>ÿR9>ÿR9>ÿS9?ÿS9?ÿS9>ÿS9>ÿS:>ÿW>AÿmTSÿW>AÿS:>ÿT:>áS:>T:>6"$6"$6"$á6"$ÿ<'*ÿ[AFÿ<'*ÿ6"$ÿ6#$ÿ8&&ÿ;((ÿ<)(ÿ=)(ÿ=)(ÿ=)(ÿ=)(ÿ=*(ÿ=*(ÿ=*(ÿ=*(ÿ=*(ÿ=*(ÿ=*)ÿ<))ÿ<))ÿ=))ÿ=))ÿ=)*ÿ>)*ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ?+*ÿ?+*ÿ?+*ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿVBBÿƒŒ‰ÿŒËÁÿzÑÃÿwÐÀÿwпÿ}Ò¾ÿ‘ɬÿƒvÿR>=ÿ?++ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿ@++ÿ>(*ÿ=&(ÿ=&(ÿ=&)ÿ<&)ÿ<&(ÿ<&(ÿ<&(ÿ=&(ÿ=&(ÿ=&)ÿ=')ÿ=')ÿ=&)ÿ=')ÿ=')ÿ=')ÿ>')ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'+ÿ='+ÿ='+ÿ>'*ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ?(+ÿ?(,ÿ@'+ÿ?'+ÿ?'+ÿ?(+ÿ>)+ÿ?*,ÿ?*,ÿ@),ÿA)+ÿA),ÿA),ÿA),ÿA)-ÿ@*-ÿ@+-ÿ@+-ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿA*/ÿB*/ÿB*/ÿB+/ÿB+/ÿB+/ÿB+/ÿB+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,1ÿC,2ÿB,2ÿB,1ÿB-1ÿC-2ÿD-3ÿD-3ÿH13ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿJ36ÿK36ÿK36ÿK35ÿK35ÿK25ÿK25ÿI13ÿF/1ÿB-/ÿC),ÿhQIÿ¨—tÿ´¤uÿµ£vÿµ£wÿµ¡xÿ¶ yÿ·¡}ÿ̽¢ÿ³Ÿqÿ©‘_ÿª‘aÿª�cÿª�dÿªŽeÿ¨Šdÿ¥‡dÿ¥†eÿ¥…fÿ¨†hÿÅ�}ÿÐ¥…ÿÕ³Ÿÿ¡��ÿP7<ÿG04ÿK38ÿN5:ÿO6<ÿP8=ÿP8=ÿP8=ÿP9=ÿQ9=ÿQ9=ÿQ9=ÿQ9=ÿQ8=ÿQ8>ÿQ8>ÿQ9>ÿR9>ÿR9>ÿR9>ÿR9>ÿR9=ÿR9=ÿR9=ÿR9>ÿS9>ÿS9>ÿS9>ÿW>AÿlTSÿW>AÿS:=ÿS:=áS:=S:=6"#6"#6"$á6"$ÿ<'*ÿ[BGÿ<(*ÿ6#$ÿ7#$ÿ7#$ÿ8$%ÿ;''ÿ<)(ÿ=)(ÿ=)(ÿ=)(ÿ=)(ÿ=*(ÿ=*(ÿ=*(ÿ<)(ÿ<)(ÿ<))ÿ<))ÿ=)*ÿ=**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ?+*ÿ?+*ÿ?+*ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿT@@ÿ�ˆ…ÿŒÊ¾ÿzÑÁÿ}ÒÀÿ�ǰÿ}}rÿO::ÿ?**ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿ@*+ÿ>()ÿ=&)ÿ=')ÿ=')ÿ=')ÿ=&)ÿ=&)ÿ=&(ÿ=&)ÿ=&)ÿ=')ÿ=&)ÿ=&)ÿ=')ÿ=')ÿ=')ÿ>')ÿ>')ÿ>')ÿ?')ÿ?'*ÿ>'+ÿ='+ÿ='+ÿ>(+ÿ>(+ÿ>(*ÿ>(*ÿ>(*ÿ?(+ÿ?(+ÿ?(+ÿ@'+ÿ@'+ÿ?'+ÿ>(+ÿ>)+ÿ>),ÿ?*,ÿ@*,ÿA),ÿA),ÿA),ÿA)-ÿA)-ÿA*-ÿ@+-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿA*/ÿB*/ÿC*/ÿB+/ÿB+/ÿB+/ÿB+/ÿB+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,2ÿC,2ÿB-2ÿB,1ÿB-1ÿC-2ÿD-3ÿD-3ÿH03ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿJ35ÿK36ÿK36ÿJ35ÿJ24ÿI13ÿG02ÿD.0ÿB+-ÿC(*ÿbMEÿ¥”rÿ´£vÿµ£wÿµ¢xÿ¶ yÿ¶ {ÿµž{ÿİ•ÿò�ÿª‘`ÿª�bÿª�dÿªŽeÿ«�fÿ§‰eÿ¥†eÿ¥…eÿ¥„gÿ¦ƒhÿ»”wÿÖ®“ÿéÏÁÿª’�ÿS;@ÿF03ÿK37ÿN59ÿP6:ÿQ7<ÿQ7<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8=ÿQ8=ÿQ8=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9>ÿS9>ÿR9>ÿW=AÿlSRÿW>@ÿS9=ÿS9=áS9=S9=6"$6"#6"$á6"$ÿ<(*ÿ\CGÿ=(*ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ:&&ÿ<)(ÿ=)(ÿ=)(ÿ=)(ÿ<((ÿ<)(ÿ<))ÿ=))ÿ=*)ÿ=*)ÿ=*)ÿ=**ÿ=**ÿ=**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ?+*ÿ?+*ÿ?+*ÿ?++ÿ@++ÿ?++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ?++ÿS>>ÿ€„�ÿ�ɼÿ�Ƶÿ|zrÿN88ÿ@**ÿ@++ÿ@++ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿ?)*ÿ>')ÿ=')ÿ=')ÿ=')ÿ=')ÿ>')ÿ=')ÿ=&)ÿ=')ÿ=')ÿ=&(ÿ=&)ÿ=')ÿ=')ÿ=')ÿ>')ÿ>')ÿ?')ÿ?')ÿ?'*ÿ>'*ÿ>'+ÿ='+ÿ>)+ÿ>)+ÿ>(+ÿ>(*ÿ>(*ÿ?(+ÿ?(+ÿ?'+ÿ@'+ÿ@'+ÿ@'+ÿ>)+ÿ>),ÿ>),ÿ?*,ÿ@*,ÿA*,ÿA),ÿA),ÿA)-ÿA)-ÿA*-ÿ@+-ÿA+-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB*/ÿC*/ÿB+/ÿB+/ÿB+/ÿB+/ÿA+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,2ÿC,2ÿB-2ÿB,2ÿB-1ÿC-2ÿD-3ÿD-3ÿG03ÿJ33ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿJ35ÿJ35ÿJ36ÿJ25ÿI14ÿG02ÿE.0ÿB,.ÿB)+ÿA()ÿbNFÿ´œ~ÿ¿©ÿ¶£yÿµ yÿ¶ zÿ¶Ÿ|ÿ¶�}ÿº¡„ÿͽ¤ÿ¯—lÿª�cÿªŽeÿ«�eÿ«�gÿ¦ˆeÿ¥†eÿ¥…fÿ¦„hÿ¥‚iÿ´Žwÿçʸÿñͺÿ¯“�ÿU>CÿF03ÿK37ÿN59ÿP6:ÿQ7;ÿQ7<ÿQ7<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8=ÿQ8=ÿQ8=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9<ÿR9=ÿS8=ÿW<@ÿmRQÿW=@ÿS9=ÿS9=áS9=S9=6#$6#$6#$á6#$ÿ=(*ÿ]CGÿ=(*ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ8$%ÿ;''ÿ<((ÿ<()ÿ=()ÿ=))ÿ=*)ÿ=*)ÿ=*)ÿ=*)ÿ=*)ÿ=*)ÿ=**ÿ=**ÿ=**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ>**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ@+*ÿ@+*ÿ@+*ÿ@++ÿ@++ÿ@++ÿ@+,ÿ@+,ÿ@+,ÿ@+,ÿ@+,ÿ@+,ÿ@++ÿR==ÿ~~{ÿ{xsÿN89ÿ@++ÿA++ÿA++ÿA++ÿA++ÿA,+ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA++ÿ?)*ÿ=')ÿ=')ÿ=')ÿ=')ÿ>')ÿ=')ÿ='*ÿ>(*ÿ>')ÿ=&)ÿ=&)ÿ=')ÿ=')ÿ=')ÿ>')ÿ>')ÿ?')ÿ?'*ÿ?'*ÿ>'*ÿ>'+ÿ>(+ÿ>)+ÿ>)+ÿ>)+ÿ>(+ÿ>(+ÿ?(+ÿ?(+ÿ?'+ÿ@'+ÿ@'+ÿ@(+ÿ?)+ÿ>),ÿ>),ÿ?),ÿ@*,ÿA*,ÿA),ÿA)-ÿA)-ÿA)-ÿA*-ÿ@+-ÿA+-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB*/ÿC*/ÿB+/ÿB+/ÿB+/ÿB+/ÿA+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,2ÿC,2ÿB-2ÿB,2ÿB-1ÿC-2ÿD-3ÿD-3ÿG/3ÿJ23ÿJ33ÿJ34ÿJ34ÿJ34ÿJ34ÿI34ÿI24ÿI24ÿG03ÿE/1ÿB-.ÿ@*,ÿB')ÿ>*,ÿgSJÿǨŒÿÞ»˜ÿÒ³�ÿè„ÿ¸ }ÿµ�|ÿ¶œ~ÿ¶›~ÿÈ´žÿ½¨†ÿ©Žcÿ«�eÿ«�fÿªŒhÿ¦‡fÿ¥…fÿ¦„gÿ¦ƒiÿ§‚kÿŪšÿòϽÿòįÿ³–‘ÿWADÿF13ÿJ47ÿM69ÿO7:ÿP7;ÿQ7;ÿQ7;ÿQ7<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8<ÿQ8=ÿQ8=ÿR9<ÿR9<ÿR9<ÿR9<ÿR8<ÿR8<ÿR8<ÿR8<ÿW<@ÿmQQÿW<@ÿS8<ÿS9<áS9<S9<6#$6#$7#$á7#$ÿ=(*ÿ]CHÿ=(*ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ7"$ÿ7"$ÿ7"$ÿ8#%ÿ;&'ÿ=))ÿ=))ÿ=))ÿ=))ÿ=*)ÿ=*)ÿ=*)ÿ=*)ÿ=*)ÿ=*)ÿ=**ÿ=**ÿ=**ÿ>**ÿ>**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?*+ÿ?*+ÿ?*+ÿ?++ÿ?++ÿ?++ÿ@,+ÿ@,+ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿO9:ÿM88ÿ@++ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,-ÿA,-ÿA,-ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA*+ÿ?(*ÿ=')ÿ=')ÿ>')ÿ=')ÿ='*ÿ=(*ÿ>(*ÿ>')ÿ>')ÿ>&*ÿ=')ÿ=')ÿ=')ÿ>')ÿ>')ÿ?')ÿ?'*ÿ>'*ÿ>'*ÿ>'+ÿ>(+ÿ>)+ÿ>)+ÿ>)+ÿ>)+ÿ?(,ÿ?(+ÿ?(+ÿ?'*ÿ@'+ÿ@'+ÿ?(+ÿ?)+ÿ?),ÿ?),ÿ?),ÿ@),ÿA*,ÿA*,ÿA)-ÿA)-ÿA*-ÿ@*-ÿ@+-ÿA+-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB*0ÿC*/ÿC+/ÿB+/ÿB+/ÿB+/ÿA+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,2ÿC,2ÿB-2ÿB,2ÿB-1ÿC-2ÿD-3ÿD-3ÿF/3ÿI23ÿJ33ÿJ33ÿJ34ÿI33ÿH23ÿH13ÿF02ÿE/1ÿB-0ÿ@+-ÿA()ÿ?)*ÿ>,-ÿu_RÿЮ‘ÿ⼜ÿã¼�ÿ๜ÿÖ²–ÿƧŠÿ»ž‚ÿ¶›ÿ¾£�ÿ˹¡ÿ¬‘iÿ«�fÿ«�hÿª‹hÿ¦…fÿ¦„gÿ¦ƒiÿ¦�iÿ¸šˆÿÖ½°ÿ滦ÿóıÿµ—’ÿWBEÿF13ÿJ47ÿM68ÿN7:ÿO8:ÿP8:ÿP8:ÿP8;ÿP8;ÿP8;ÿP8;ÿP8;ÿP8;ÿQ8;ÿQ8;ÿQ8;ÿQ8;ÿQ7;ÿQ7<ÿQ7<ÿR8<ÿR8<ÿR8<ÿR8<ÿR8<ÿR8<ÿR8<ÿV**ÿ>**ÿ>**ÿ>**ÿ?*+ÿ?*+ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ@,+ÿ@,+ÿ@,+ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ?++ÿ@++ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA-,ÿA--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB,-ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿA,,ÿB,,ÿB,,ÿ@*+ÿ>(*ÿ=')ÿ>')ÿ=')ÿ='*ÿ=(*ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ='*ÿ=')ÿ>')ÿ?')ÿ?')ÿ?'*ÿ>'*ÿ>'*ÿ>'+ÿ>(+ÿ?)+ÿ?)+ÿ>)+ÿ>)+ÿ?),ÿ?(,ÿ?'+ÿ?'*ÿ@'+ÿ@'+ÿ?(+ÿ?),ÿ?),ÿ?),ÿ?),ÿ?),ÿ@*,ÿA*,ÿA*-ÿA)-ÿA*-ÿ@*-ÿA+-ÿA+-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB+0ÿC*/ÿC+/ÿB+/ÿB+/ÿB+/ÿA+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,2ÿC,2ÿC-2ÿB-2ÿB-1ÿC-1ÿD-3ÿD-3ÿE.3ÿH13ÿI33ÿI22ÿH23ÿG12ÿE01ÿD/0ÿA-/ÿ@+-ÿA(*ÿ@(*ÿ=+,ÿC10ÿ‹taÿÙ¶—ÿ⼜ÿ⻞ÿ⹟ÿ㸠ÿâ¶¡ÿÚ±œÿ˧‘ÿ¾žˆÿ͸¦ÿ¸ž}ÿªŒfÿ«Œiÿª‰iÿ¦„gÿ¦ƒhÿ¦�iÿ¯ŽzÿÓ¼¯ÿͪ˜ÿÚ¯œÿò±ÿµ–‘ÿWADÿG14ÿK47ÿM69ÿN7:ÿO7:ÿO7:ÿP7:ÿP7:ÿP7:ÿP7;ÿP7;ÿP7;ÿP7;ÿQ7;ÿQ7;ÿQ7;ÿQ7;ÿQ7;ÿQ7;ÿQ7<ÿQ7<ÿR8<ÿR8<ÿR8<ÿR8;ÿR8;ÿR8;ÿV<>ÿlQPÿV*)ÿ>*)ÿ>*)ÿ>*)ÿ>**ÿ>+*ÿ>++ÿ>++ÿ>++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ@,+ÿ@,+ÿ@,+ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA-,ÿA--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,-ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿ@*+ÿ>')ÿ=')ÿ='*ÿ=(*ÿ=(*ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ>(*ÿ>'*ÿ>')ÿ?')ÿ?'*ÿ>'*ÿ>'*ÿ>'*ÿ>(+ÿ>(+ÿ>(+ÿ?)+ÿ?)+ÿ?),ÿ?),ÿ?),ÿ?'+ÿ?'*ÿ@'+ÿ@'+ÿ?(+ÿ?(,ÿ?),ÿ@),ÿ?),ÿ?),ÿ@),ÿA*,ÿA*.ÿA*.ÿA*-ÿ@*-ÿA+-ÿA+-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB+0ÿC*0ÿC*/ÿB+/ÿB+/ÿB+/ÿA+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,1ÿC,2ÿC-2ÿB-2ÿB,1ÿC-1ÿC-2ÿC-3ÿD-2ÿF/2ÿH11ÿG11ÿE00ÿC//ÿ@--ÿ?+,ÿ@(*ÿ@()ÿ=+,ÿ<*,ÿQ=7ÿ¬�wÿປÿ⻞ÿ⺟ÿ⸠ÿâ·¡ÿã¶£ÿ䶤ÿäµ¥ÿݯ¡ÿÚµ©ÿͶ ÿ¬�iÿªŠiÿ©ˆjÿ¦„hÿ¦‚iÿª†pÿÌ´¦ÿÒ±¡ÿÉ¢‘ÿÒ¨˜ÿÿ±“ŽÿT?BÿG14ÿK47ÿM68ÿN7:ÿO7:ÿO7:ÿO7:ÿP7:ÿP7:ÿP7:ÿP7;ÿP7;ÿP7;ÿP7;ÿP7;ÿQ7;ÿQ7;ÿQ7;ÿQ8;ÿQ8;ÿQ8;ÿQ8;ÿR8;ÿR8;ÿR8;ÿR8;ÿQ8;ÿU<>ÿkQPÿU(*ÿ7"$ÿ8#$ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ:%&ÿ=((ÿ>))ÿ>))ÿ>**ÿ>**ÿ>+*ÿ>+*ÿ>+*ÿ>+*ÿ>++ÿ>++ÿ>++ÿ>++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ?++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿA,+ÿA,+ÿA,+ÿA,+ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿA,,ÿA,,ÿA-,ÿA--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,-ÿC,,ÿC,-ÿB,,ÿ@)*ÿ='*ÿ='*ÿ=(*ÿ=')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ>(*ÿ>(*ÿ?(*ÿ?'*ÿ?'*ÿ>'*ÿ>'*ÿ>'*ÿ>(+ÿ>(+ÿ>(+ÿ?)+ÿ?)+ÿ@),ÿ?),ÿ?),ÿ?(+ÿ?'+ÿ?'+ÿ?(+ÿ?(+ÿ?(,ÿ?),ÿ@),ÿ@),ÿ?),ÿ@),ÿ@),ÿA*.ÿA*.ÿA*-ÿ@*-ÿA*-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB+0ÿC*0ÿC*/ÿB+/ÿB+/ÿB+/ÿA+0ÿA,1ÿB,1ÿC,1ÿC,1ÿC,1ÿC,2ÿC,2ÿB,2ÿA,1ÿA,0ÿB,1ÿB,1ÿA+1ÿB-0ÿD./ÿB..ÿ@,,ÿ@*+ÿ@()ÿ?)*ÿ=+,ÿ=+,ÿ?++ÿs[Mÿ̪Žÿâ»�ÿ⺞ÿ⹟ÿâ·¡ÿã¶£ÿ㶤ÿäµ¥ÿä´§ÿ峨ÿæ´¬ÿèȾÿË£Šÿ·�sÿ«ˆkÿ¥‚iÿ§‚kÿè˜ÿÕ¸ªÿÊ£‘ÿÊ¢“ÿÍ£•ÿå·ªÿ¬�‰ÿP<>ÿG13ÿL46ÿM68ÿN79ÿO79ÿO79ÿO79ÿO79ÿP79ÿP79ÿP79ÿP7:ÿP7:ÿP8:ÿP8:ÿP8:ÿQ8:ÿQ8:ÿQ8:ÿQ8:ÿQ8:ÿP8;ÿP8;ÿQ8;ÿQ8;ÿQ8;ÿQ7;ÿU<>ÿkQOÿU<>ÿQ8:ÿR8;áR8;R8;6"#6"#6"#á6"#ÿ=(*ÿ^DIÿ>(*ÿ7#$ÿ8#$ÿ8#$ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9$&ÿ<'(ÿ>**ÿ>**ÿ>**ÿ>+*ÿ>+*ÿ>+*ÿ>+*ÿ>+*ÿ>+*ÿ>++ÿ>++ÿ?++ÿ?++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿA,+ÿA,+ÿA,+ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB-,ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿC--ÿC--ÿB+,ÿ?(+ÿ=(*ÿ=(*ÿ=')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ>(*ÿ>(*ÿ?(*ÿ@(+ÿ?'+ÿ>'*ÿ>'*ÿ>(*ÿ>(+ÿ>(+ÿ>(+ÿ?)+ÿ?)+ÿ@),ÿ@),ÿ?(+ÿ?(+ÿ?'+ÿ?'+ÿ?(+ÿ?(+ÿ?(,ÿ?),ÿ@),ÿ@),ÿ?),ÿ@),ÿ@)-ÿA*.ÿA*.ÿA*.ÿ@*-ÿA*-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB+0ÿC+0ÿC*/ÿC+/ÿB+/ÿB+/ÿA+0ÿA,1ÿB,1ÿC,1ÿC,1ÿB,1ÿB+1ÿB,1ÿA+1ÿ@+0ÿ?+/ÿ?+/ÿ?*/ÿ=).ÿ=)-ÿ>*+ÿA))ÿA((ÿ>**ÿ=,,ÿ=++ÿ;()ÿQ=5ÿ§ŠqÿÞ¸šÿ⺞ÿ⹟ÿâ·¡ÿã¶¢ÿã¶£ÿäµ¥ÿä´¦ÿ峨ÿ岩ÿå°©ÿëÀ¼ÿä½®ÿÖ¡�ÿÈ—ƒÿ´‰uÿº›‰ÿÖ½¯ÿË¥“ÿÊ¢’ÿË¢”ÿË •ÿÙ­¤ÿ£†‚ÿM:;ÿF13ÿK46ÿM58ÿN79ÿN79ÿN79ÿN79ÿN79ÿO79ÿO79ÿP79ÿP79ÿO7:ÿO7:ÿO8:ÿO8:ÿO8:ÿP8:ÿP8:ÿP8:ÿP8:ÿP7:ÿP7;ÿP7;ÿP7;ÿQ8:ÿQ8:ÿU<=ÿkQOÿU<=ÿQ8:ÿQ8:áQ8:Q8:7"$6"#7"$á7"$ÿ=)*ÿ^EIÿ=(*ÿ7#$ÿ8#$ÿ8#$ÿ8#$ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#&ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ;&(ÿ=))ÿ>**ÿ>**ÿ>+*ÿ>+*ÿ>+*ÿ?+*ÿ?+*ÿ?+*ÿ?++ÿ?++ÿ?++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@+,ÿ@+,ÿ@+,ÿ@+,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA-,ÿA-,ÿA-,ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿB,-ÿB,-ÿB,-ÿB,-ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB-,ÿB--ÿB--ÿB--ÿB--ÿC--ÿC--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿC-.ÿD..ÿC-.ÿA+-ÿ?)+ÿ>')ÿ=')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>'*ÿ>(*ÿ>(*ÿ?(*ÿ@(+ÿ?(+ÿ>'+ÿ>'*ÿ>(*ÿ>(+ÿ>(+ÿ>(+ÿ?)+ÿ@),ÿ@),ÿ@),ÿ@(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(,ÿ?(,ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@)-ÿA*.ÿA+.ÿA*.ÿ@*-ÿA*-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB+0ÿC+0ÿC*/ÿC+/ÿB+/ÿB+/ÿA+0ÿ@,0ÿA,1ÿB+0ÿB+0ÿA+0ÿA*0ÿ@*0ÿ>*/ÿ=).ÿ<(,ÿ;(,ÿ;&+ÿ;%*ÿ=$(ÿ>&)ÿ=*+ÿ=++ÿ=**ÿ;((ÿC0,ÿ…lVÿÒ®�ÿâº�ÿ⹟ÿ⸠ÿã¶¢ÿã¶£ÿ䵤ÿä´¦ÿä³§ÿ岩ÿ屪ÿ毪ÿè´²ÿëÈÁÿÛ§•ÿÕ�ŽÿÕ¤˜ÿéÈÀÿ൨ÿÏ¥–ÿË¢“ÿË •ÿËŸ–ÿ̤œÿ•zwÿK69ÿG14ÿK46ÿM58ÿN69ÿN69ÿN69ÿN79ÿN69ÿN79ÿN79ÿO79ÿO79ÿO69ÿO6:ÿO7:ÿO7:ÿO7:ÿO7:ÿP7:ÿP7:ÿP79ÿP79ÿP79ÿP7:ÿP7:ÿP7:ÿQ8:ÿU<=ÿkQOÿU<=ÿQ8:ÿQ8:áQ8:Q8:7#$7#$7#$á7#$ÿ=)*ÿ^EIÿ=)*ÿ7#$ÿ7#$ÿ8#$ÿ8#$ÿ8#$ÿ8#$ÿ8#%ÿ8#&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ:%'ÿ=()ÿ?**ÿ?**ÿ?+*ÿ?+*ÿ?+*ÿ?+*ÿ?+*ÿ?+*ÿ?++ÿ?+,ÿ?+,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA-,ÿA-,ÿA-,ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿC--ÿC--ÿC--ÿC--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿD--ÿD..ÿC./ÿB-.ÿ@+,ÿ>(*ÿ>')ÿ>')ÿ>')ÿ>')ÿ>')ÿ>'*ÿ>(*ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ?(+ÿ>(+ÿ>(*ÿ>(+ÿ>(+ÿ>(+ÿ?)+ÿ@),ÿ@),ÿ@),ÿ@(+ÿ@(+ÿ?(+ÿ?(+ÿ?(,ÿ?(,ÿ?(,ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@).ÿA+.ÿ@+.ÿ@*-ÿA*-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+.ÿA+/ÿA+/ÿA+/ÿB+0ÿB+0ÿC*/ÿB+/ÿA*.ÿA*/ÿ@*/ÿ?*/ÿ?+/ÿ@*/ÿ@*.ÿ?).ÿ>(.ÿ<(-ÿ:',ÿ9&*ÿ:$(ÿ<#'ÿ;$(ÿ:&*ÿ9',ÿ:(+ÿ;)*ÿ:''ÿ?,)ÿvbOÿ˱–ÿæÅ¬ÿåÁªÿä½§ÿ㹦ÿã·¥ÿ㵤ÿä´¥ÿ䲦ÿ岨ÿ屩ÿæ°ªÿ毬ÿæ®®ÿìÃÂÿá´§ÿÕŸ’ÿèļÿ÷ÇÀÿö¼¶ÿï·±ÿᮦÿÒ¤œÿÌŸ—ÿÃ�–ÿ‚liÿJ46ÿI25ÿK47ÿM58ÿO58ÿO59ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO79ÿO79ÿO79ÿP79ÿP79ÿP79ÿP79ÿP79ÿP7:ÿP7:ÿP7:ÿU<>ÿkQOÿU<>ÿQ8:ÿQ8:áQ8:Q8:7#$7#$7#$á7#$ÿ>)*ÿ_EJÿ=)*ÿ6#$ÿ7#$ÿ7#$ÿ8#$ÿ8#$ÿ8#%ÿ8$%ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ:$&ÿ<&(ÿ>))ÿ?**ÿ?+*ÿ?+*ÿ?++ÿ?,+ÿ?,+ÿ?,+ÿ?,,ÿ?,,ÿ?,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB-,ÿB-,ÿB-,ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB.-ÿB..ÿB-.ÿB--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿB--ÿB--ÿB--ÿC--ÿD--ÿC..ÿC./ÿC//ÿB-.ÿ@)+ÿ>'*ÿ>')ÿ?')ÿ>')ÿ>')ÿ>'*ÿ>(*ÿ?(*ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ>(+ÿ>(+ÿ>(+ÿ?)+ÿ@),ÿ@),ÿ@),ÿ@(+ÿ@(+ÿ?(+ÿ?(+ÿ?(,ÿ?(,ÿ?(,ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿA+.ÿ@+.ÿ@*.ÿA*-ÿA+-ÿA+.ÿB+.ÿA+.ÿA+.ÿA+.ÿ@+/ÿ@+/ÿA*/ÿA*/ÿA).ÿA*.ÿ@*-ÿ?)-ÿ>)-ÿ=)-ÿ<)-ÿ<(-ÿ<',ÿ;&+ÿ:%*ÿ;$)ÿ;#(ÿ:#'ÿ9$(ÿ8'*ÿ8'+ÿ9'*ÿ8%(ÿ6#'ÿ>*)ÿoX@ÿƧtÿîÏ›ÿñÔ§ÿñÔ¯ÿñÔµÿðÓºÿïѼÿîͽÿìɼÿëĺÿ鿸ÿ躵ÿèµ²ÿç²±ÿ篰ÿé¶¹ÿè½ÿ㻲ÿöËÄÿö¼¶ÿö»·ÿ÷»¸ÿøººÿó¶·ÿæ­®ÿÅ�™ÿt^\ÿI25ÿJ36ÿK47ÿM58ÿN58ÿO58ÿO58ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO79ÿO79ÿO79ÿP79ÿP79ÿP79ÿP79ÿP79ÿP7:ÿP7:ÿU;>ÿjPOÿU<=ÿQ7:ÿQ7:áQ7:Q7:7#$7#$7#$á7#$ÿ=)*ÿ_EJÿ=(*ÿ6"$ÿ7#$ÿ7#%ÿ7$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ:$&ÿ;&'ÿ=)*ÿ?++ÿ?,+ÿ?,+ÿ?,+ÿ?,+ÿ?,+ÿ?,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB-,ÿB-,ÿB-,ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿB--ÿB--ÿB.-ÿB.-ÿB..ÿB..ÿB..ÿC..ÿC-.ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿB--ÿC--ÿD--ÿC..ÿC./ÿC//ÿC..ÿA,-ÿ?)+ÿ?'*ÿ?')ÿ?')ÿ>')ÿ>'*ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?)+ÿ?)+ÿ>(+ÿ>(+ÿ>(+ÿ?),ÿ@),ÿ@),ÿ@(+ÿ@(+ÿ@(+ÿ?(+ÿ?)+ÿ?),ÿ?(,ÿ?(,ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@*.ÿ@+.ÿ@*.ÿA*-ÿ@+-ÿA+.ÿA*.ÿ@*-ÿ@*-ÿ@*-ÿ?*.ÿ?*.ÿ?).ÿ?).ÿ?(-ÿ?(,ÿ=(+ÿ<'+ÿ;&+ÿ9&*ÿ9%*ÿ:%)ÿ<#(ÿ<#'ÿ;#'ÿ9%)ÿ7'+ÿ7'*ÿ8&)ÿ8%(ÿ7$'ÿ5"%ÿ?-*ÿs]CÿÄ£iÿéÁ{ÿìÃ~ÿìÂÿíÂ�ÿîÂ…ÿîÉÿðÄ�ÿðÆ–ÿòÈžÿò˧ÿóͯÿóζÿóϼÿòÎÁÿñËÄÿðÉÆÿóØÖÿöÛÕÿøÊÄÿ÷ÄÀÿøÁ¾ÿø½½ÿøº½ÿù¸½ÿù·¾ÿÏ¡£ÿhRQÿH14ÿK36ÿL47ÿM58ÿM58ÿN58ÿN58ÿO58ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO69ÿO79ÿO79ÿO79ÿP79ÿP79ÿP79ÿP79ÿP79ÿP69ÿT:=ÿiOOÿU;=ÿQ7:ÿQ7:áQ7:Q7:7#$7#$7#$á6"$ÿ=(*ÿ_EJÿ>(+ÿ7"$ÿ7#%ÿ7$%ÿ7$%ÿ7$%ÿ7$%ÿ8$%ÿ8$%ÿ8$%ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ9%'ÿ9%'ÿ9%'ÿ:%'ÿ:%'ÿ<')ÿ?**ÿ@,+ÿ@,+ÿ@,+ÿ@,+ÿ@,+ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB-,ÿB-,ÿB-,ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC.-ÿB..ÿB..ÿB..ÿC..ÿC..ÿC..ÿC..ÿC-.ÿC--ÿC--ÿC--ÿC--ÿC--ÿD--ÿD--ÿC./ÿC//ÿC//ÿC..ÿC..ÿA+,ÿ?)+ÿ?'*ÿ?')ÿ?')ÿ?'*ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?)+ÿ?)+ÿ?)+ÿ>(+ÿ>(+ÿ?),ÿ@),ÿ@),ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ?)+ÿ?),ÿ?(-ÿ?(,ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ?)-ÿ?)-ÿ?*-ÿ?*-ÿ?*-ÿ@),ÿ?*,ÿ?*-ÿ@*-ÿ?),ÿ>),ÿ>),ÿ=(,ÿ=(,ÿ<',ÿ<'+ÿ;&*ÿ;%)ÿ:%(ÿ:$'ÿ;#&ÿ;"&ÿ:#'ÿ9$(ÿ8&)ÿ8'*ÿ8'*ÿ8&*ÿ7%)ÿ6#'ÿ5"%ÿ5#%ÿJ7.ÿ†nJÿͬmÿêÂ|ÿìÄÿìÀÿìÂ�ÿíÀ‚ÿíÀƒÿî¾…ÿÿÿ(ÿﺉÿð¹Šÿð¹�ÿñ¹�ÿòº”ÿò»™ÿôÅ©ÿò×Íÿö×ÌÿøÍ½ÿùÏÃÿùÑÈÿúÑÌÿúÐÎÿûÎÏÿùËÍÿ¾ž›ÿZEDÿH13ÿK36ÿL47ÿL57ÿL57ÿM57ÿM57ÿN58ÿN58ÿO68ÿO69ÿO68ÿN69ÿN69ÿN68ÿO68ÿO68ÿO68ÿO68ÿO69ÿO69ÿO79ÿO69ÿP69ÿP69ÿP69ÿP69ÿP69ÿT:=ÿiNNÿT:=ÿP6:ÿQ79áQ79Q797"$7"$7"$á6"$ÿ>(+ÿ`EKÿ>)+ÿ7#%ÿ7#%ÿ7$%ÿ7$%ÿ7$%ÿ7$%ÿ8$%ÿ9$%ÿ9$%ÿ9$%ÿ9$&ÿ9$&ÿ9$'ÿ9%'ÿ9%'ÿ9%'ÿ9%'ÿ9%'ÿ9%'ÿ:%'ÿ;%'ÿ;%'ÿ<&(ÿ>)*ÿ@++ÿ@,+ÿ@,+ÿ@,+ÿ@,+ÿ@,+ÿ@,,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,-ÿA,-ÿA,-ÿA--ÿA,-ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿA--ÿB--ÿB.-ÿB.-ÿB.-ÿB..ÿB..ÿB-.ÿB..ÿB-.ÿB-.ÿB-.ÿB--ÿB--ÿB--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC-.ÿC--ÿC--ÿC--ÿD--ÿD-.ÿD./ÿC//ÿC//ÿC..ÿC..ÿB--ÿA+,ÿ?(*ÿ?'*ÿ?'*ÿ?'*ÿ?(*ÿ?(+ÿ>(+ÿ>(+ÿ?(+ÿ?(+ÿ?)+ÿ?)+ÿ?)+ÿ?(+ÿ>(+ÿ?),ÿ@),ÿ@),ÿ@(+ÿ@(+ÿ@(+ÿ?(+ÿ?)+ÿ>),ÿ?(-ÿ?(,ÿ?(+ÿ?)+ÿ?(+ÿ?(+ÿ?(+ÿ?(,ÿ>(,ÿ>),ÿ>),ÿ>),ÿ>(+ÿ=(+ÿ=(+ÿ=(+ÿ<'*ÿ;'*ÿ:&)ÿ9&)ÿ9%)ÿ:$)ÿ;$(ÿ<"'ÿ<"%ÿ;"%ÿ:$&ÿ8%(ÿ7&*ÿ6'*ÿ7'*ÿ8&)ÿ8%(ÿ7#&ÿ5"%ÿ4"%ÿ<*'ÿaL8ÿ©’oÿÞ¾�ÿëÃ{ÿìÄ~ÿìÀÿì€ÿíÁ‚ÿíÀƒÿí¿…ÿÿÿ)ÿﻊÿðº‹ÿð¸Œÿñ¸Žÿñ·�ÿñ¶�ÿñ·•ÿòʸÿà°ªÿëżÿö½¨ÿõ·£ÿö·§ÿö¸ªÿ÷º®ÿø½³ÿðÀ²ÿ¢ˆ}ÿP:;ÿI14ÿK36ÿL47ÿM47ÿL47ÿL47ÿM47ÿM47ÿM47ÿN47ÿN58ÿN58ÿN58ÿN58ÿN58ÿN58ÿN58ÿO58ÿO58ÿO58ÿO59ÿO69ÿO69ÿO69ÿP69ÿP69ÿP69ÿP69ÿT:<ÿiNMÿT:<ÿP69ÿQ79áQ79Q797"$7"$7"$á7"$ÿ>)+ÿ`FKÿ>)+ÿ7#%ÿ7#%ÿ7#%ÿ7$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ9$%ÿ9$&ÿ9%&ÿ9%'ÿ9%'ÿ9%'ÿ9%'ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%'ÿ;%'ÿ;%'ÿ=')ÿ?*+ÿ@,+ÿ@,+ÿ@,,ÿ@,,ÿ@-,ÿ@-,ÿ@--ÿ@--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB.-ÿC.-ÿC.-ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿB..ÿB..ÿB..ÿB..ÿC-.ÿC-.ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC.-ÿC..ÿC..ÿC..ÿC..ÿD..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC-.ÿC-.ÿD--ÿD--ÿD-.ÿD./ÿD//ÿC..ÿC..ÿC..ÿC..ÿB--ÿA*,ÿ?(*ÿ?'*ÿ?'*ÿ@'*ÿ?(+ÿ>(+ÿ>(+ÿ?(+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ>(+ÿ?(,ÿ?),ÿ?(+ÿ?(+ÿ?(*ÿ?(*ÿ?(*ÿ>(*ÿ>(+ÿ>(,ÿ>'+ÿ>'+ÿ>'*ÿ='*ÿ='*ÿ='*ÿ<'*ÿ<'*ÿ;'*ÿ;'*ÿ;'*ÿ:&)ÿ:&(ÿ9&(ÿ:%(ÿ:$'ÿ:$&ÿ:#&ÿ;"%ÿ;"%ÿ:#&ÿ:#'ÿ9%(ÿ8&)ÿ7&)ÿ7&)ÿ7%(ÿ7%(ÿ6$'ÿ6#&ÿ5"%ÿ4!$ÿ9'&ÿS?1ÿŠqNÿɪuÿìÏŸÿóبÿìÄ~ÿìÃÿì€ÿíÁ‚ÿíÀƒÿí¿„ÿÿÿhÿﻊÿðº‹ÿð¹Œÿð¸Žÿñ¸�ÿñ¶�ÿñµ’ÿóǰÿå¹±ÿÖš”ÿಮÿöƸÿõ¶¤ÿöµ¦ÿö´§ÿ÷´¨ÿö·§ÿᯛÿƒi_ÿJ45ÿJ25ÿK36ÿL47ÿM47ÿM47ÿL47ÿL47ÿM47ÿM47ÿM47ÿN47ÿN58ÿN58ÿN58ÿN58ÿN58ÿN58ÿN58ÿO58ÿO58ÿO58ÿO59ÿO69ÿO69ÿO68ÿO68ÿP68ÿP68ÿT:;ÿiNMÿT:<ÿO69ÿO69áO69O696#%6#%7#%á7#%ÿ>)+ÿ`GLÿ>)+ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8$%ÿ8$%ÿ8$%ÿ8$&ÿ8%&ÿ9%&ÿ9%&ÿ9%&ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%'ÿ;%'ÿ;%(ÿ<')ÿ?*+ÿ@-,ÿA-,ÿA-,ÿA-,ÿA-,ÿA-,ÿA--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC.-ÿC.-ÿC.-ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC-.ÿC--ÿC--ÿC--ÿC.-ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD-.ÿC--ÿD-.ÿD./ÿD//ÿD..ÿC..ÿC..ÿC..ÿC..ÿB,-ÿA*+ÿ?(*ÿ@'*ÿ@'*ÿ?(+ÿ>(+ÿ>(+ÿ>(+ÿ>)*ÿ>)*ÿ>)*ÿ>(*ÿ>(*ÿ>(*ÿ>(+ÿ>(+ÿ>'*ÿ>'*ÿ>')ÿ=&)ÿ=')ÿ<')ÿ<'*ÿ;'*ÿ<&*ÿ;&)ÿ;&)ÿ:&(ÿ:%(ÿ9%(ÿ9$(ÿ8$(ÿ8$(ÿ8$'ÿ9$'ÿ:#&ÿ;"%ÿ;"%ÿ;"$ÿ:"%ÿ9#%ÿ8$'ÿ7%(ÿ6&)ÿ6&)ÿ7&)ÿ8%(ÿ8$'ÿ7$&ÿ6#%ÿ5"$ÿ4!$ÿ3!$ÿ9('ÿQ>1ÿ�iJÿ»ŸmÿãÈÿïÍ“ÿñΙÿõܵÿîÈŠÿìÂÿìÁ�ÿíÀƒÿí¿„ÿî¾…ÿÿhÿ*ÿðº‹ÿð¹Œÿð¸�ÿñ¸�ÿñ·�ÿñµ‘ÿóÁ¥ÿêùÿÛ¡šÿÖ™”ÿÖžœÿðÈÁÿ÷¸©ÿö´§ÿöµ¨ÿö¸§ÿõ¹§ÿÌ¡ŽÿhRKÿH13ÿJ34ÿK35ÿL46ÿM47ÿM46ÿL47ÿL47ÿM47ÿM47ÿM47ÿM47ÿN47ÿN47ÿN58ÿN58ÿN58ÿN58ÿN58ÿN57ÿO57ÿO57ÿO57ÿO58ÿO58ÿO68ÿO68ÿO68ÿO68ÿT:;ÿiNMÿS:;ÿO58ÿO59áO59O596#%6#%6#%á6#%ÿ>)+ÿ`GLÿ>)+ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8#&ÿ8$&ÿ8%&ÿ8%&ÿ8%&ÿ9%&ÿ9%&ÿ:%&ÿ:%&ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%(ÿ:&(ÿ:&(ÿ;&(ÿ<&(ÿ<&(ÿ<&(ÿ>)*ÿ@,+ÿA-,ÿA-,ÿA-,ÿA-,ÿA-,ÿA--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC.-ÿC.-ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC..ÿC-.ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC..ÿD..ÿC-.ÿD-.ÿD./ÿD./ÿD..ÿD..ÿC..ÿC..ÿC..ÿC--ÿB,,ÿ@)+ÿ?'*ÿ?'*ÿ>'*ÿ='*ÿ='*ÿ='*ÿ=(*ÿ=()ÿ=')ÿ<')ÿ<')ÿ<')ÿ<&*ÿ<&)ÿ<&)ÿ<%(ÿ;%(ÿ;%'ÿ:%'ÿ9%'ÿ9%(ÿ8$(ÿ8$(ÿ8#'ÿ8#&ÿ8#%ÿ9"%ÿ9"%ÿ:!$ÿ:!$ÿ:!$ÿ:"%ÿ9#%ÿ9#&ÿ8$&ÿ7%'ÿ7&(ÿ6&(ÿ6&(ÿ6&(ÿ7%(ÿ7$'ÿ6$&ÿ6#&ÿ6"%ÿ5!$ÿ3 #ÿ4"$ÿ>,(ÿYF7ÿ‡pOÿ¼¡nÿà†ÿîΑÿðÏ•ÿðÍ•ÿðÌ–ÿóÖ®ÿñÒ¢ÿìÁ€ÿíÀ‚ÿí¿„ÿî¾…ÿÿhÿ)ÿﻋÿð¹‹ÿð¸�ÿñ¸�ÿñ·�ÿñµ‘ÿò¼œÿïɼÿݦ ÿÚœ—ÿÖ˜–ÿÓ–•ÿæ¹¹ÿ÷Àµÿöµ¦ÿõ¸¦ÿö¹§ÿð¶¤ÿªˆxÿT?<ÿI23ÿK34ÿK45ÿL35ÿL46ÿM46ÿM46ÿL46ÿL46ÿM46ÿM46ÿM46ÿM46ÿN46ÿN47ÿN57ÿN57ÿN57ÿN57ÿN57ÿN57ÿO57ÿO57ÿO57ÿN58ÿN58ÿN68ÿN68ÿN58ÿS9;ÿhNLÿS9;ÿO57ÿO57áO57O576#%6#%6#%á6#%ÿ>)+ÿaGLÿ?)+ÿ8#%ÿ8#%ÿ8#&ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ9%&ÿ9%&ÿ9%&ÿ9%&ÿ:%&ÿ:%&ÿ:%&ÿ:%'ÿ:%'ÿ:%(ÿ:&(ÿ:&(ÿ:&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&(ÿ=')ÿ?**ÿA-,ÿA-,ÿA-,ÿA-,ÿA-,ÿA--ÿA--ÿA--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC--ÿC.-ÿC.-ÿC.-ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿC..ÿD..ÿC..ÿC..ÿC./ÿC..ÿC-.ÿC--ÿC--ÿB--ÿB--ÿA--ÿB--ÿA,,ÿ@*+ÿ>'*ÿ=&*ÿ<&)ÿ<&)ÿ;&(ÿ;&(ÿ;&(ÿ:&(ÿ:&(ÿ:&'ÿ9%'ÿ9%(ÿ9$'ÿ9$'ÿ9$&ÿ8#&ÿ8#%ÿ8"%ÿ8"$ÿ8"$ÿ9"%ÿ9!%ÿ:!$ÿ: #ÿ: #ÿ9!#ÿ9!#ÿ8"$ÿ8#&ÿ7$'ÿ6%(ÿ6&(ÿ6&(ÿ6&(ÿ7%'ÿ7%'ÿ7%'ÿ7$&ÿ6#%ÿ5#$ÿ5"$ÿ3!$ÿ2 #ÿ3!$ÿ:''ÿL8/ÿmXAÿ Œmÿɯ}ÿäÆˆÿîÏ�ÿðГÿðÏ•ÿðÍ•ÿðÌ–ÿð˘ÿñΡÿôÚ¶ÿîÇÿíÀƒÿî¿…ÿÿÿ)ÿﻋÿðº‹ÿð¸�ÿñ¸Žÿñ·�ÿñ¶‘ÿò·•ÿòʸÿᯨÿÚ�—ÿÛœ™ÿÕ˜—ÿÓ”•ÿÚ£¦ÿôÉÁÿöº¦ÿõ¹¦ÿö¹¨ÿà­›ÿ‚g\ÿJ45ÿI24ÿJ35ÿK45ÿK35ÿK35ÿK46ÿL46ÿL46ÿL46ÿL46ÿL46ÿM46ÿL46ÿM46ÿM46ÿM47ÿM57ÿM57ÿM57ÿM57ÿM57ÿM57ÿN57ÿN57ÿN47ÿN47ÿN48ÿN58ÿN57ÿR9;ÿhMLÿS9:ÿO57ÿO57áO57O576#$6#$7#%á6#%ÿ>),ÿaGMÿ?),ÿ8#%ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9%&ÿ9%&ÿ9%&ÿ9%&ÿ:%&ÿ:%'ÿ:&'ÿ:&'ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ>))ÿ@,+ÿA-,ÿA-,ÿA-,ÿB--ÿB-.ÿB..ÿB..ÿB..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD/.ÿD/.ÿD/.ÿD..ÿD./ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD/.ÿC//ÿC//ÿC./ÿC..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC..ÿC--ÿC--ÿB--ÿB-.ÿB-.ÿB-.ÿB--ÿA,,ÿA,,ÿA,,ÿ@,,ÿ@++ÿ?++ÿ?++ÿ?**ÿ=()ÿ;%(ÿ9$(ÿ8$'ÿ8$&ÿ8$&ÿ8$&ÿ7$%ÿ8#%ÿ8#%ÿ9#$ÿ9"%ÿ:"$ÿ:!$ÿ:!#ÿ: #ÿ: "ÿ: "ÿ9!"ÿ8!#ÿ8"$ÿ7#&ÿ7#&ÿ6$'ÿ6$'ÿ6%'ÿ6%'ÿ6%'ÿ6%'ÿ6$'ÿ6$'ÿ6$&ÿ6$&ÿ6#%ÿ5"$ÿ5"#ÿ4!#ÿ3!#ÿ2 "ÿ3"#ÿ:('ÿI6/ÿeP>ÿ�uQÿ·›eÿÜÄ’ÿïØ§ÿïÑ‘ÿïÑ‘ÿðГÿðÏ”ÿðΕÿðÌ–ÿð̘ÿðÊšÿðÉ›ÿô×¶ÿðÌ›ÿí¾ƒÿÿÿhÿﻊÿðº‹ÿð¹Œÿñ¸Žÿñ¸�ÿñ¶‘ÿñµ’ÿóǰÿ庲ÿÚž˜ÿÛœ™ÿÚ›šÿÕ–—ÿÔ”–ÿÔ—™ÿêýÿöÁ¯ÿö¸§ÿô·§ÿÀ—„ÿaJDÿH12ÿJ24ÿK34ÿK35ÿK35ÿK35ÿK35ÿK35ÿK36ÿK46ÿK46ÿL46ÿL46ÿL46ÿL46ÿL36ÿM36ÿM46ÿM47ÿM47ÿM47ÿM47ÿM47ÿM47ÿN46ÿN46ÿN46ÿN47ÿN47ÿN57ÿR9:ÿhMLÿS9:ÿO57ÿO57áO57O577#$7#$7#$á7#$ÿ>),ÿaGMÿ>*,ÿ7$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9%&ÿ9%&ÿ9%'ÿ9&'ÿ:&'ÿ;&'ÿ;&'ÿ;&'ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ=&)ÿ=&)ÿ=')ÿ>()ÿ@++ÿB.-ÿB.-ÿB.-ÿB.-ÿB..ÿB..ÿB..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD/.ÿD/.ÿD/.ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD./ÿD./ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD/.ÿD/.ÿC//ÿC//ÿC./ÿC..ÿC-.ÿC--ÿB--ÿB--ÿB--ÿB,,ÿB,,ÿA,,ÿ@,,ÿ?,,ÿ?,,ÿ?++ÿ>++ÿ>**ÿ=**ÿ=))ÿ<))ÿ<((ÿ<((ÿ<((ÿ<''ÿ;$&ÿ9"%ÿ9!$ÿ9!#ÿ:!#ÿ9!#ÿ9!"ÿ9!"ÿ9!"ÿ9!#ÿ9"$ÿ8"$ÿ8#%ÿ7#%ÿ7#%ÿ6$&ÿ6$&ÿ5%&ÿ5%'ÿ5%'ÿ5%'ÿ6$'ÿ6$'ÿ6$&ÿ6#%ÿ6#%ÿ6"$ÿ5"$ÿ5!$ÿ4!#ÿ3!#ÿ2!#ÿ2 "ÿ3!"ÿ6$$ÿ?-)ÿQ>3ÿlXBÿ�xSÿ¶™eÿÔ¶tÿæÆ{ÿïÕ‘ÿôá³ÿðÒ•ÿïÑ‘ÿïÐ’ÿðÏ”ÿðΕÿðÍ–ÿð̘ÿðË™ÿðÉ›ÿðÈœÿóΩÿôÖ²ÿÿÿhÿ*ÿðº‹ÿð¹Œÿð¸Žÿñ¸�ÿñ·�ÿñµ‘ÿóÁ¥ÿëúÿÛ¡šÿÚœ˜ÿÛœšÿÚššÿÕ•—ÿÓ––ÿÓ˜”ÿÝ®¬ÿõɾÿ÷·©ÿ籞ÿ’tdÿO86ÿI23ÿJ34ÿK34ÿK34ÿK34ÿK35ÿK34ÿK34ÿK35ÿK35ÿK35ÿK35ÿL35ÿL35ÿL35ÿL35ÿL35ÿL35ÿM36ÿM46ÿM46ÿM46ÿM46ÿM46ÿM46ÿN46ÿN46ÿN46ÿN46ÿN57ÿS9:ÿhMLÿS9:ÿO57ÿO57áO57O577#$7#$7#$á7#$ÿ>*,ÿaHNÿ>*-ÿ7$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ9%'ÿ9&'ÿ:&'ÿ:&'ÿ:&'ÿ;&'ÿ;&'ÿ;&'ÿ;&'ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&)ÿ<')ÿ<')ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ=()ÿ>**ÿA-,ÿB.-ÿB.-ÿB.-ÿB..ÿB..ÿB..ÿB..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD/.ÿD/.ÿD/.ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD./ÿC..ÿC..ÿC..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC.-ÿC..ÿC..ÿB..ÿB..ÿB--ÿA--ÿA,,ÿ@+,ÿ@++ÿ?++ÿ?**ÿ?**ÿ=)*ÿ<)*ÿ<)*ÿ<))ÿ<()ÿ<((ÿ<''ÿ<&&ÿ=&&ÿ=%%ÿ=%%ÿ=%%ÿ>%%ÿ>%%ÿ<$&ÿ:#%ÿ8"$ÿ7"$ÿ7#$ÿ6$%ÿ6$%ÿ5%&ÿ5%&ÿ5%&ÿ5%'ÿ5%'ÿ6%'ÿ6$&ÿ6$&ÿ6$%ÿ6#%ÿ5#%ÿ5#$ÿ5#$ÿ5"$ÿ5"$ÿ5!#ÿ4!#ÿ3 "ÿ3 "ÿ2!ÿ2"ÿ3 #ÿ6$%ÿ>-+ÿL:3ÿ`L<ÿ~iRÿ¤�hÿÁ¥jÿÙºuÿçÇ{ÿìÌ}ÿíÎ~ÿîÒ‡ÿôá²ÿñÕ›ÿïÐ�ÿïÐ’ÿðÏ“ÿðΕÿðÍ•ÿðÌ—ÿðË™ÿðÊšÿðÈœÿñÈžÿñÈ ÿö×»ÿðÅ•ÿ'ÿ*ÿﺋÿð¹Œÿð¸�ÿñ¸�ÿñ·�ÿñµ‘ÿò»›ÿïɼÿݦ ÿÚœ˜ÿÛœšÿÛ››ÿؘšÿÔ—•ÿÓš•ÿÓ˜–ÿÕœ�ÿïÇÃÿõº­ÿÄš†ÿeNFÿH12ÿJ33ÿK44ÿK44ÿK34ÿK34ÿK34ÿK34ÿK34ÿK34ÿK34ÿK35ÿK35ÿL35ÿL35ÿL35ÿL35ÿL35ÿL35ÿM35ÿM35ÿM46ÿM46ÿM46ÿN56ÿN56ÿN56ÿN56ÿO56ÿO56ÿO56ÿS9:ÿhMLÿS9:ÿN56ÿN56áN56N567$%7#%7$%á7$%ÿ>*,ÿbINÿ?*-ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$'ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ;&'ÿ;&'ÿ;&'ÿ;&(ÿ<&)ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ=')ÿ=()ÿ@++ÿB--ÿB.-ÿB.-ÿB..ÿB..ÿB..ÿC..ÿC..ÿD..ÿC..ÿC..ÿC..ÿC..ÿD..ÿD..ÿC..ÿC..ÿC..ÿC..ÿC..ÿD/.ÿD/.ÿD/.ÿD/.ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿC./ÿC..ÿC..ÿB--ÿB--ÿB--ÿB--ÿB-,ÿA-,ÿA--ÿ@,,ÿ?,,ÿ?++ÿ>++ÿ=**ÿ=)*ÿ<))ÿ<((ÿ<''ÿ<''ÿ=&'ÿ=&&ÿ=&&ÿ=%%ÿ=%%ÿ=%%ÿ<&&ÿ<&&ÿ;&&ÿ;&&ÿ:''ÿ:((ÿ:((ÿ9()ÿ9(*ÿ7()ÿ6&(ÿ5%'ÿ5%&ÿ5%&ÿ6$&ÿ5$%ÿ6$%ÿ6#%ÿ6#%ÿ6#$ÿ6"$ÿ5!#ÿ5!#ÿ5!"ÿ4 "ÿ3 "ÿ3 !ÿ2 "ÿ1"ÿ1"ÿ2 "ÿ5#$ÿ;((ÿE2.ÿS?7ÿeRAÿ{gLÿ”{XÿªŽbÿ»œgÿÊ®yÿêÔ£ÿíÍ~ÿíÌ{ÿìÍ|ÿíÎ}ÿíÏ€ÿóÞªÿòÙ¥ÿïÐ�ÿïÐ’ÿðГÿðÏ•ÿðÍ•ÿðÌ—ÿðË™ÿðÊšÿðÉœÿñÈ�ÿñÈžÿòÆŸÿôϲÿôÑ­ÿ)ÿﻋÿð¹‹ÿð¸�ÿñ¸�ÿñ·�ÿñ¶‘ÿñ·•ÿòʸÿá°©ÿÚœ—ÿÛœšÿÚ›šÿÓ”•ÿÓ˜•ÿÓš”ÿÓ™–ÿÓ——ÿÔ–˜ÿãµ·ÿæ»­ÿ�o`ÿI35ÿD-2ÿF03ÿH13ÿH24ÿJ34ÿK34ÿK44ÿL44ÿL34ÿL34ÿL34ÿL34ÿK45ÿL45ÿM45ÿM45ÿM45ÿM45ÿM45ÿM45ÿM45ÿN45ÿN56ÿN56ÿN56ÿN56ÿN56ÿN56ÿN56ÿN55ÿN55ÿR89ÿfLKÿQ79ÿK25ÿK25áJ15J257$%7$%7$%á7$%ÿ?*,ÿcINÿ?*,ÿ8$%ÿ8$&ÿ8$&ÿ9$&ÿ9%'ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ;&'ÿ<&(ÿ<'(ÿ<'(ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ=')ÿ=')ÿ=')ÿ>')ÿ>')ÿ>()ÿ?)*ÿA,,ÿC.-ÿC.-ÿB..ÿC./ÿC./ÿC..ÿC./ÿC./ÿC./ÿC./ÿC./ÿD./ÿD./ÿD./ÿC..ÿD..ÿD..ÿD..ÿD..ÿD/.ÿE/.ÿE/.ÿD/.ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿC//ÿC//ÿC..ÿC..ÿB..ÿB--ÿA--ÿ@,,ÿ@++ÿ?++ÿ>+*ÿ>+*ÿ=**ÿ<**ÿ<))ÿ<((ÿ=((ÿ=''ÿ=&&ÿ=%%ÿ=%%ÿ=%%ÿ<%&ÿ<&&ÿ;''ÿ:((ÿ:((ÿ9()ÿ9))ÿ8))ÿ8))ÿ8((ÿ8((ÿ9((ÿ9((ÿ9''ÿ9''ÿ9'(ÿ8&'ÿ7%&ÿ6#%ÿ5"#ÿ5"#ÿ4!"ÿ4!"ÿ4!"ÿ3!"ÿ3 "ÿ3 "ÿ2!ÿ2!ÿ1!ÿ2!ÿ4!#ÿ7%&ÿ>,*ÿG51ÿTA9ÿeRBÿyeMÿ�zXÿ¡Œ_ÿ²œeÿ¾ªiÿIJkÿȲkÿË«jÿ˪jÿʪkÿàË�ÿïÓŽÿìÌ{ÿíÍ}ÿíÎ~ÿñÚ�ÿóÞ¯ÿïÑ‘ÿïÑ‘ÿðГÿðÏ”ÿðÍ•ÿðÌ–ÿð˘ÿðÊšÿðÉ›ÿñÈ�ÿñÈžÿòÇŸÿòÅ¡ÿóǦÿö×½ÿð¿’ÿð¹‹ÿð¸�ÿñ¸Žÿñ·�ÿñ¶‘ÿñµ’ÿóǯÿ溲ÿÚž˜ÿÛ�™ÿÖ˜—ÿÉŽŽÿЖ’ÿמ—ÿÓ™•ÿÓ˜—ÿÔ–˜ÿÔ•šÿÖŸ¡ÿ¸›�ÿ\E@ÿB+1ÿC,2ÿD.2ÿD/2ÿD/2ÿE/2ÿE/3ÿF03ÿG03ÿH14ÿI13ÿI13ÿJ13ÿJ24ÿJ34ÿK35ÿL35ÿL35ÿL35ÿL35ÿL35ÿL34ÿL34ÿL35ÿL45ÿL45ÿL45ÿK35ÿJ35ÿJ24ÿJ14ÿI04ÿM48ÿbHIÿL38ÿH/5ÿH05áH05H058$%7$%8$%á8$%ÿ?*,ÿcINÿ?*,ÿ8$%ÿ8$&ÿ8%'ÿ9%'ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:&'ÿ;&(ÿ;'(ÿ;'(ÿ;'(ÿ<'(ÿ<'(ÿ<'(ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ='*ÿ=(*ÿ=)*ÿ=)*ÿ?+,ÿA.-ÿB/.ÿB//ÿB//ÿB//ÿB//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿD//ÿD//ÿD/.ÿE//ÿE//ÿE//ÿE//ÿD//ÿD//ÿC//ÿC..ÿC..ÿB..ÿB--ÿA--ÿ@--ÿ@,,ÿ?++ÿ>++ÿ=**ÿ<))ÿ;((ÿ<('ÿ<''ÿ='&ÿ=&&ÿ=%%ÿ=%%ÿ=&&ÿ<''ÿ;''ÿ:((ÿ9))ÿ9))ÿ8()ÿ8()ÿ8))ÿ9((ÿ9((ÿ9((ÿ9''ÿ8''ÿ8&&ÿ8&&ÿ8%%ÿ7%%ÿ7$$ÿ7$$ÿ7$$ÿ6#$ÿ6#$ÿ5#$ÿ4"#ÿ2 !ÿ1!ÿ1!ÿ1 !ÿ2!"ÿ5$%ÿ:((ÿ@.-ÿI72ÿTA9ÿbNAÿs^Jÿ…qTÿ˜ƒ\ÿ©”cÿ·¢iÿîlÿʶmÿκmÿÊ·iÿÉ·gÿÉ·gÿÈ·hÿȸiÿɳjÿÊ«jÿÊ©jÿÓ¹„ÿîØ¢ÿíÍ}ÿíÎ}ÿïÕ�ÿôà³ÿðÒ•ÿïÑ‘ÿïÐ’ÿðÏ”ÿðΕÿðÌ–ÿð̘ÿðËšÿðÉ›ÿñÈ�ÿñÈžÿñÇŸÿòÆ ÿòÄ¢ÿóãÿöѺÿóʦÿð¸‹ÿñ¸Žÿñ¸�ÿñ¶‘ÿñµ‘ÿóÁ¤ÿëĺÿÛ¡›ÿÙ›—ÿÍ’�ÿÀˆ‡ÿΖ�ÿÛ¡™ÿÖœšÿÓ˜—ÿÔ—˜ÿÔ–šÿÔ•šÿÀކÿw]RÿE/3ÿB+1ÿD,2ÿD,2ÿD-2ÿD.2ÿD.2ÿD.2ÿD/2ÿE/2ÿE/2ÿE.2ÿE.2ÿE.2ÿE.2ÿE/2ÿE/3ÿF/3ÿG/3ÿG/3ÿG/3ÿG/3ÿG/3ÿG/3ÿG/3ÿG/4ÿG/4ÿG/4ÿG/4ÿG/4ÿG/4ÿG/4ÿG/4ÿL37ÿbGIÿL38ÿH/4ÿH/5áH05H058$%8$%8$%á8$%ÿ?*,ÿcJNÿ?*,ÿ8$%ÿ8%&ÿ9%'ÿ9%'ÿ9%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%(ÿ;&(ÿ;&(ÿ;'(ÿ;'(ÿ;'(ÿ;'(ÿ;'(ÿ<'(ÿ<'(ÿ<'(ÿ<')ÿ=')ÿ=')ÿ=')ÿ=')ÿ='*ÿ='*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=)*ÿ=)*ÿ>*+ÿ@-,ÿB/.ÿB/.ÿB//ÿB//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿC//ÿD0/ÿD0/ÿD0/ÿD00ÿD//ÿC//ÿC..ÿC..ÿC..ÿB--ÿA--ÿ@,,ÿ?++ÿ>++ÿ=**ÿ<))ÿ<((ÿ=''ÿ=''ÿ=&&ÿ=%%ÿ<%%ÿ;&&ÿ:('ÿ:((ÿ9))ÿ9))ÿ9))ÿ9))ÿ9))ÿ9((ÿ9((ÿ9''ÿ8&'ÿ8&&ÿ8&&ÿ7%%ÿ7$$ÿ7$$ÿ7$$ÿ6$$ÿ5##ÿ4##ÿ4""ÿ4""ÿ4""ÿ4"#ÿ5$%ÿ7&'ÿ:**ÿ?/.ÿE53ÿM<7ÿWD=ÿcODÿr\LÿƒkTÿ–}^ÿª•xÿ°œpÿµŸcÿÀªhÿDzjÿÌ·kÿϺjÿлhÿϼgÿмgÿϼhÿλhÿȶfÿȶfÿÈ·hÿÈ·iÿȸkÿȹkÿÉ´kÿʬlÿË­qÿåÑ¥ÿïÒˆÿîцÿôá²ÿñÕœÿïÐ�ÿïÐ’ÿðÏ”ÿðΕÿðÍ–ÿðÌ—ÿðË™ÿðÉšÿðÈœÿñÈžÿñÇŸÿòÆ ÿòÅ¢ÿóÄ£ÿó¤ÿõÇ®ÿöÓ»ÿñº‘ÿñ¸�ÿñ·�ÿñµ‘ÿò»›ÿðʽÿݦ ÿÑ–‘ÿÁ‰‡ÿ»…ƒÿÏ—�ÿÛ¡™ÿÑš©ÿÍ•§ÿÓ—˜ÿÔ–šÿÕ•›ÿË“�ÿ�o`ÿO87ÿB+1ÿC,2ÿC,2ÿD,2ÿD,2ÿD-2ÿD.2ÿD.3ÿD.3ÿD.3ÿE.3ÿE.3ÿE-3ÿE-3ÿE-3ÿE-3ÿD.3ÿD.3ÿF.4ÿF.4ÿF.4ÿF.4ÿF.4ÿF.4ÿF.4ÿF.4ÿG.4ÿG.4ÿG/4ÿG/4ÿG/4ÿG/4ÿG/4ÿL37ÿbGIÿL37ÿH/3ÿH/4áH/5H/58$%8$%8$%á8$%ÿ?*,ÿcJOÿ?+-ÿ8%&ÿ9%&ÿ9%&ÿ9%'ÿ9%'ÿ9%'ÿ9%'ÿ:%'ÿ:%'ÿ;%(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;'(ÿ;'(ÿ;'(ÿ<'(ÿ<'(ÿ='(ÿ='(ÿ=')ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ>(*ÿ>(*ÿ>(*ÿ>(*ÿ>)*ÿ>)*ÿ>)*ÿ@+,ÿB.-ÿC//ÿC//ÿC//ÿC//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿC//ÿC//ÿD//ÿD0/ÿC0/ÿC//ÿC//ÿB//ÿB..ÿA-.ÿ@--ÿ?,,ÿ>++ÿ=**ÿ<))ÿ<((ÿ=''ÿ=&&ÿ=%%ÿ=%%ÿ<&&ÿ;''ÿ:((ÿ9))ÿ8))ÿ8))ÿ8))ÿ8((ÿ9((ÿ9''ÿ9&&ÿ8&&ÿ7%%ÿ7%%ÿ7$$ÿ6$$ÿ5##ÿ5##ÿ4"#ÿ4""ÿ4""ÿ5#$ÿ7&&ÿ:**ÿ@//ÿH65ÿQ>:ÿ[G@ÿgRGÿt_OÿƒkVÿ“z]ÿ¢‡cÿ°”hÿ½ŸkÿɨlÿÓ°oÿÛ¸sÿâ½wÿäÁzÿâË‘ÿàÑ™ÿϹcÿιbÿιcÿιdÿκeÿλeÿϼfÿϼhÿϼiÿͺiÿȶfÿȶgÿÈ·iÿȸjÿȹkÿȺkÿɺmÿɵmÿʬlÿÙÁ‘ÿðÙŸÿóÞ¨ÿòÙ¥ÿïÐ�ÿïÐ’ÿðГÿðΕÿðÍ•ÿðÌ—ÿðË™ÿðÊšÿðÈœÿñÈžÿñÈŸÿòÆ ÿòÅ¡ÿóÄ£ÿóäÿó¦ÿôÀ§ÿ÷ÒÀÿóáÿñ¶�ÿñ¶‘ÿò·•ÿòʸÿÚ«¥ÿÃŒ‡ÿ·‚€ÿ¼‡ƒÿÓ›‘ÿØ �ÿÃ’¾ÿÄ‘½ÿÔ˜œÿÔ–™ÿÔ•›ÿÑ••ÿ¦|nÿ]D=ÿC+0ÿC,1ÿD,2ÿC,2ÿC,2ÿD,2ÿD,2ÿD-2ÿD.2ÿD.3ÿD.3ÿD.3ÿE.3ÿE-3ÿE-3ÿE-3ÿE-3ÿD-3ÿD-3ÿE.4ÿF.4ÿF.4ÿF.4ÿF.4ÿF.4ÿF.4ÿF.4ÿF.4ÿG.4ÿG.4ÿG/4ÿG/4ÿG/4ÿG/3ÿK37ÿaGIÿL37ÿH/4ÿH/4áH/4H/48$%8$%8$%á8$%ÿ?+-ÿdKOÿ@+-ÿ9%&ÿ9%&ÿ9%&ÿ9%&ÿ9%'ÿ9%'ÿ9%'ÿ:&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<'(ÿ<'(ÿ<'(ÿ<')ÿ=()ÿ=()ÿ=()ÿ=()ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ>(*ÿ=(*ÿ=(*ÿ=(*ÿ=(+ÿ>(+ÿ>)+ÿ>)+ÿ>)+ÿ>)+ÿ>*+ÿ>*+ÿ?*+ÿA--ÿC//ÿD00ÿC00ÿD00ÿD00ÿD00ÿD00ÿD00ÿD00ÿD00ÿD00ÿD00ÿD00ÿD/0ÿD/0ÿD//ÿC//ÿC/.ÿC/.ÿC/.ÿB.-ÿA--ÿ?--ÿ>,,ÿ=++ÿ<**ÿ<))ÿ<((ÿ=&'ÿ>&&ÿ=&&ÿ<''ÿ:((ÿ9))ÿ8))ÿ8))ÿ8))ÿ9((ÿ9''ÿ8''ÿ8&&ÿ7&%ÿ7%%ÿ6$$ÿ6$$ÿ5##ÿ4##ÿ4"#ÿ4##ÿ6%&ÿ:()ÿ?./ÿG65ÿTA>ÿcOIÿq\Sÿ�hVÿ“x]ÿ¤†dÿ´”hÿÁŸkÿ˧kÿÔ¯kÿÚ´kÿ߸jÿã»hÿå¼gÿæ¾hÿç¿jÿèÀnÿèÂrÿéÃuÿèÃxÿÞÂ|ÿÛÂ�ÿäÕ¤ÿÒ¿qÿ͸aÿιdÿκeÿλeÿλfÿϼgÿϼiÿϼjÿͺiÿȶgÿÈ·hÿȸjÿȹkÿȹkÿɺlÿɺnÿÉ»oÿʵoÿγyÿíݺÿöä½ÿñÖ�ÿðÔ™ÿðÑ–ÿðÏ–ÿðÍ•ÿðÌ–ÿðË—ÿðÊ™ÿðÈ›ÿñÈ�ÿñÈžÿòÆŸÿòÅ¡ÿòÄ¢ÿóäÿó¦ÿôÀ§ÿô¿¨ÿöȶÿöÏ·ÿò·’ÿð´‘ÿê¾§ÿϨ¢ÿ¶ƒÿ´€}ÿÁ‹†ÿÕ�“ÿΙ­ÿ²ˆØÿ½�ÈÿÙœ ÿÖ˜šÿÔ–›ÿÒ•—ÿ³…xÿkPDÿE.0ÿC,0ÿD,1ÿD,1ÿC,1ÿC,1ÿC,1ÿD,1ÿD,1ÿD-1ÿD.2ÿD.2ÿD.2ÿD.3ÿD.3ÿE-3ÿE-3ÿE-3ÿE-3ÿD-3ÿD-3ÿE.3ÿF.4ÿF.4ÿF.4ÿF.3ÿF.3ÿF.3ÿF.3ÿF.3ÿG.3ÿG.3ÿG/4ÿG/4ÿG/4ÿK37ÿaGIÿK37ÿG/4ÿG/4áG/4G/48$&8$&8$&á8%&ÿ@+-ÿeKPÿ@+-ÿ9%&ÿ9%&ÿ9%&ÿ9%&ÿ:%'ÿ:&'ÿ:&(ÿ:&(ÿ:&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ<&(ÿ<')ÿ<()ÿ<()ÿ<()ÿ<()ÿ=()ÿ=()ÿ=()ÿ>()ÿ=(*ÿ=(*ÿ=(+ÿ=(+ÿ=)+ÿ=)+ÿ=)+ÿ=)+ÿ>)+ÿ>)+ÿ?)+ÿ?)*ÿ?)*ÿ?)*ÿ?**ÿ?**ÿ?**ÿ?**ÿ@++ÿB.-ÿD0/ÿD0/ÿD0/ÿE0/ÿE0/ÿE0/ÿE0/ÿE0/ÿE0/ÿE0/ÿE00ÿD00ÿD0/ÿC//ÿC//ÿB..ÿB..ÿA.-ÿ@-,ÿ?,+ÿ=+*ÿ<))ÿ<((ÿ=''ÿ=&&ÿ<''ÿ;((ÿ:))ÿ9**ÿ8)*ÿ9))ÿ9((ÿ9''ÿ9''ÿ8&&ÿ7%%ÿ7$$ÿ6$$ÿ5##ÿ4##ÿ4##ÿ5$%ÿ8((ÿ?./ÿH76ÿVECÿhVOÿyfUÿ�x^ÿ¡Šeÿ³šjÿÄ©kÿÒºxÿàÆ•ÿß¶hÿâ·bÿä¸_ÿä¹]ÿä¹[ÿä¹[ÿä¹Zÿäº]ÿä»aÿå¼fÿæ¾lÿçÀqÿèÁtÿèÂuÿèÃwÿèÃxÿáÂ{ÿÚÁ~ÿÚÁ}ÿáΙÿÜÌ�ÿ͸bÿκeÿκeÿλfÿϼgÿϼhÿϼjÿмkÿ̺iÿÈ·hÿȸjÿȸkÿȹkÿɺlÿɺmÿɺoÿÊ»pÿÊ»oÿÒÁƒÿðâÅÿ÷ÞÁÿôصÿõÚ¹ÿõÛºÿõÛ¹ÿõÚ·ÿôØ´ÿôÖ°ÿóÒ«ÿòΨÿòÌ¥ÿòÉ£ÿòÆ¢ÿòÄ¢ÿóãÿó¤ÿôÀ¦ÿô¿¨ÿõ¿©ÿö¿­ÿõÐÀÿ岓ÿÖ¨�ÿÅ£›ÿ³ƒÿ¶‚~ÿÈ‘ŠÿÒœ ÿ½ŽÊÿ¨€ëÿ¿ŽÆÿÚ�žÿÛœ�ÿÕ—›ÿÓ•˜ÿº‹}ÿuZKÿG01ÿB+0ÿC,0ÿC,0ÿD,1ÿD,1ÿC,1ÿC,1ÿC,1ÿD,1ÿD-1ÿD-1ÿD.1ÿD.1ÿD.2ÿD.2ÿD.2ÿE-2ÿE-2ÿE-2ÿE-2ÿD-2ÿE-2ÿE.2ÿE.3ÿF.3ÿF.3ÿF.3ÿF.3ÿF.3ÿF.3ÿF.3ÿF.3ÿF.4ÿF/4ÿF/4ÿJ37ÿ`GIÿJ37ÿF.4ÿG.4áG.4G.48$&8$&8$&á8$&ÿ@+-ÿeKPÿ@+-ÿ9%&ÿ9%&ÿ:%'ÿ:&'ÿ:&'ÿ:&'ÿ:&(ÿ:&(ÿ:&(ÿ:&(ÿ;&(ÿ<&(ÿ<&(ÿ<&(ÿ<&)ÿ<')ÿ<')ÿ<')ÿ<')ÿ<()ÿ<()ÿ=()ÿ=()ÿ=()ÿ=(*ÿ=)*ÿ=)*ÿ=)+ÿ>)+ÿ>)+ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ?*+ÿ@*+ÿ?*+ÿ?*+ÿ@*+ÿA,-ÿD//ÿE00ÿE00ÿE00ÿE00ÿE00ÿE00ÿE00ÿE00ÿE0/ÿD//ÿD/.ÿC/.ÿB.-ÿA--ÿ@,,ÿ>,+ÿ=+*ÿ=*)ÿ=((ÿ>'&ÿ='&ÿ<('ÿ;))ÿ9**ÿ9**ÿ9))ÿ9))ÿ9((ÿ8''ÿ8&&ÿ8%%ÿ6$$ÿ5##ÿ4"#ÿ4#$ÿ7&'ÿ>-/ÿI88ÿYHEÿkYPÿ~kWÿ�|[ÿ¡�aÿÅ´ŽÿÕ¿yÿÚ¿fÿàÄbÿâÆ^ÿãÆZÿâÅWÿâÆXÿìÖŽÿå¾gÿá´Rÿâ¶Uÿâ·Xÿã¸\ÿåºaÿæ¼gÿæ¾lÿç¿pÿç¿sÿçÀtÿèÁuÿèÂuÿèÂvÿéÃxÿäÃzÿÛÁ~ÿÚÁ~ÿÚÂÿÜÆˆÿãÕ¥ÿнlÿκeÿλeÿϼgÿϼhÿϼjÿмkÿнkÿ˺jÿÈ·iÿȸkÿȹkÿȺlÿɺmÿɺnÿÉ»pÿÊ»oÿÍ¿xÿæÞ®ÿóæ°ÿõÙ¶ÿñ•ÿñÁ—ÿò›ÿóÄ ÿóƦÿôÉ­ÿõ̳ÿöϹÿöÒ½ÿ÷ÔÀÿ÷ÕÂÿ÷ÕÂÿ÷ÔÀÿ÷Ò½ÿ÷Ϻÿ÷Ë·ÿõƳÿォÿ⯠ÿÕ®¤ÿ̪™ÿÄ£˜ÿ¶ˆƒÿ¼†�ÿË“˜ÿÅ’¾ÿ®‚èÿ¨~ðÿÅ’½ÿÛžœÿÜ�žÿÛšŸÿÔ–™ÿ¾Œÿ}`NÿJ33ÿA)0ÿB*0ÿC+0ÿC,0ÿC,0ÿC,1ÿC,1ÿB,1ÿB,1ÿB,1ÿC,1ÿD-1ÿC-1ÿD.1ÿD.1ÿD.2ÿD.2ÿD-2ÿE-2ÿE-2ÿE-2ÿD-2ÿD-2ÿE-2ÿE.2ÿE.3ÿE.3ÿE.3ÿE.3ÿE.3ÿE.3ÿE.3ÿE.3ÿE.3ÿF.3ÿF.4ÿJ27ÿ`FIÿJ27ÿF.3ÿF.3áF.3F.38$&8$&8$&á8$&ÿ@+-ÿeLPÿ@+-ÿ9%&ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:&(ÿ;&(ÿ;&(ÿ<&)ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ=')ÿ<')ÿ<()ÿ<(*ÿ<)*ÿ<)*ÿ=)*ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ>)+ÿ>)+ÿ>)+ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ@*+ÿ@*+ÿ@*+ÿ@*+ÿ@*+ÿ@*+ÿ@*+ÿ@*+ÿ@*+ÿA+,ÿC-.ÿE00ÿE00ÿE00ÿF00ÿF00ÿF00ÿE00ÿE//ÿD//ÿC..ÿB.-ÿ@-,ÿ?,+ÿ=**ÿ=)(ÿ=''ÿ?'&ÿ>'&ÿ<)(ÿ:**ÿ:**ÿ9*)ÿ9))ÿ9((ÿ9'&ÿ8&%ÿ7%%ÿ5$$ÿ4##ÿ5$$ÿ9'(ÿB12ÿQ@?ÿdSMÿyiZÿŽ~aÿŸŽbÿ¬š_ÿµ¢Wÿ¹¤Mÿº£BÿоrÿåÑÿßÃQÿßÂOÿàÂPÿàÃQÿàÃRÿàÃSÿáÄSÿçÐvÿê̇ÿã·[ÿåºbÿæ¼hÿç½mÿç¿oÿç¿pÿç¿qÿç¿rÿçÀsÿèÁtÿèÁuÿèÂvÿéÃwÿæÃyÿÜÁ}ÿÚÁ~ÿÚÂÿÚ€ÿÚÂ�ÿäÓ¢ÿØÉ…ÿκdÿϼfÿϼhÿϼiÿмkÿнkÿнlÿʹjÿȸjÿȹkÿȺkÿɺmÿɺnÿÉ»pÿÊ»pÿ˼rÿßÖ¢ÿñç¬ÿïä™ÿõæºÿòÈ¡ÿñ¿•ÿò¾–ÿò¾˜ÿò¼™ÿò»™ÿòº›ÿò¹�ÿò¹Ÿÿó¹¢ÿôº¦ÿõ¼«ÿö¿°ÿöÁµÿòÁ¸ÿé½¶ÿܵ¯ÿѬ§ÿÌ©¤ÿÌ«¦ÿʳ­ÿ¼”ŽÿÀ‰‘ÿÄ�»ÿµ…âÿ¨|÷ÿ°ƒæÿÍ—²ÿÛŸ›ÿÜ��ÿÜœ ÿÙšœÿ¿Œ~ÿ`NÿL53ÿB*0ÿC*0ÿC*/ÿC*/ÿD+/ÿD+0ÿD+0ÿC+1ÿC+1ÿB+1ÿB+1ÿB,1ÿC,1ÿC-1ÿC-1ÿC-1ÿC.1ÿC.2ÿC.2ÿC-2ÿD-2ÿD-2ÿD-2ÿC-2ÿC-2ÿD-2ÿD-2ÿD-3ÿE-3ÿE-3ÿE-3ÿE-3ÿE-3ÿE-3ÿE-2ÿE-2ÿF-2ÿJ26ÿ`FHÿJ27ÿF.3ÿF.3áF.3F.38$&8$&8$&á8$&ÿ?*-ÿeKQÿA,.ÿ:%'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ;&'ÿ;&(ÿ;&)ÿ;')ÿ;')ÿ<')ÿ<')ÿ<')ÿ=')ÿ<')ÿ<')ÿ<'*ÿ<(*ÿ<(*ÿ=)*ÿ=)*ÿ=)*ÿ=)*ÿ>)*ÿ>)+ÿ>)+ÿ?**ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ?*+ÿ@*+ÿA*,ÿA*+ÿA),ÿA*,ÿA*,ÿA*,ÿA*,ÿA*,ÿA*,ÿB,-ÿD./ÿE00ÿF01ÿF00ÿE/0ÿE//ÿD./ÿC..ÿA--ÿ@,,ÿ>**ÿ=))ÿ>''ÿ?'&ÿ=''ÿ;))ÿ:*)ÿ:*)ÿ:)(ÿ:((ÿ9''ÿ8&&ÿ7%%ÿ5$#ÿ5##ÿ7&&ÿ@//ÿO>>ÿfVRÿ…vmÿ™‹rÿ§™iÿ²¥dÿ¸¬Zÿ¸ªNÿ´¤Bÿ´¢:ÿ´ 6ÿ´ž1ÿîSÿâІÿßÃUÿßÁNÿàÂPÿàÃQÿàÃRÿáÄUÿâÆZÿãÈ`ÿåÌmÿïÙŸÿèÀtÿç½lÿç¾nÿç¿oÿç¿pÿç¿qÿç¿rÿçÀsÿçÀtÿèÁuÿèÂvÿèÃwÿèÃyÿÞÂ|ÿÚÁ~ÿÚÂÿÚ€ÿÚ‚ÿÚÂÿßÊ‘ÿâÔ¡ÿϽiÿϼgÿϼiÿϼjÿнkÿнkÿϾlÿʹkÿȹkÿȹkÿɺlÿɺnÿÉ»oÿÊ»pÿÊ»oÿ×Í’ÿðç³ÿïã™ÿïã˜ÿòç­ÿôÙ´ÿñÀ–ÿò¾˜ÿò½™ÿò¼šÿòºœÿòº�ÿòºŸÿó¹ ÿô·¢ÿóµ¢ÿî± ÿ婚ÿÚž“ÿЕ�ÿË‘ŠÿÉ�‹ÿÊ��ÿÊ‘�ÿÉ’•ÿÇž²ÿÁ�Äÿºƒàÿ°~ôÿ­}õÿ»‰ÖÿÔ›§ÿÜŸšÿÛ��ÿÜœŸÿÚ››ÿ¿�}ÿ~_KÿL52ÿA*0ÿC+0ÿC+0ÿC*/ÿC*/ÿC*/ÿD+/ÿD+/ÿD+/ÿD+0ÿC+0ÿC+0ÿC+0ÿC+1ÿD,0ÿD,1ÿD,1ÿD-1ÿD-1ÿD-2ÿD,2ÿD,2ÿD,2ÿE,2ÿD,2ÿD,2ÿE,2ÿE,1ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿJ16ÿ`EHÿJ27ÿF.3ÿF.3áF.3F.38$&8$&8$&á8$&ÿ@+.ÿfLQÿA,.ÿ9&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ;&'ÿ;&'ÿ;&(ÿ;'(ÿ;'(ÿ;')ÿ;')ÿ<')ÿ<')ÿ<')ÿ<'*ÿ<(*ÿ<(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=)+ÿ=)+ÿ>**ÿ>**ÿ>**ÿ?**ÿ?**ÿ?**ÿ?*+ÿ?*+ÿ?*,ÿ@),ÿ@),ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿA*,ÿA*,ÿA*,ÿA*,ÿA*,ÿA+,ÿA+,ÿA+,ÿA+,ÿA+,ÿA+-ÿC-/ÿD00ÿE00ÿE/0ÿD//ÿC..ÿA,-ÿ?++ÿ>)*ÿ>((ÿ?&'ÿ>''ÿ<))ÿ:**ÿ:**ÿ:))ÿ:((ÿ9'&ÿ8%%ÿ6$$ÿ5##ÿ9'(ÿF44ÿ[JIÿvg`ÿ“†uÿªŸ€ÿ¹¯€ÿÉÂ�ÿÍÇ‹ÿ´¬Iÿ³©Bÿ´§=ÿ²£:ÿ° 6ÿ³Ÿ5ÿ´ž2ÿ¼¦BÿÝ͇ÿáÇ`ÿßÁNÿßÁOÿÛ¾PÿÞ¿UÿãÆ`ÿäÉgÿåÊkÿåÌmÿåÌmÿìÙ“ÿìÌ�ÿç½lÿç¾oÿç¿pÿç¿pÿç¿qÿç¿sÿçÀtÿèÁuÿèÂuÿèÃwÿéÃxÿáÂ{ÿÚÁ~ÿÚÂ~ÿÚ€ÿÚÂ�ÿÛÃÿÛÄ„ÿÛÅ…ÿåÖ¨ÿÖÅ|ÿÏ»hÿϼjÿмkÿнkÿоlÿϾmÿɹkÿȹkÿɺlÿɺmÿÉ»oÿÊ»pÿÊ»oÿÑÅ„ÿìä´ÿðå�ÿïã˜ÿïâšÿðâ ÿõæ¿ÿòËŸÿò¾™ÿò¼šÿò»œÿó»žÿòºžÿð¶�ÿê°›ÿᨖÿן�ÿΘ‹ÿÊ“ˆÿÈ‘‰ÿÉ‘ŠÿÊ�ŠÿÊ�‹ÿÊŽ’ÿÈ‹§ÿ†Èÿ½„æÿ¸€òÿ³~ôÿµ�ëÿÆ‘ÂÿØŸžÿÛŸšÿÛž�ÿÜœŸÿØ›˜ÿ·‰wÿwYGÿK31ÿB*/ÿB+0ÿB+0ÿC+0ÿC+0ÿC*/ÿC*/ÿC*/ÿD+/ÿD+/ÿD+/ÿC+0ÿC+0ÿC+0ÿC+0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD-0ÿD-1ÿD,1ÿD,1ÿE,1ÿE,1ÿD,1ÿD,1ÿE,1ÿE,1ÿE-1ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿE-2ÿJ15ÿ`EGÿK16ÿG.3ÿG.3áG.3G.38$&8$&8$&á8$&ÿ@+.ÿfMQÿ@,.ÿ9%'ÿ:&'ÿ:&'ÿ;&'ÿ;&'ÿ;&(ÿ;'(ÿ;'(ÿ;'(ÿ;'(ÿ;'(ÿ;')ÿ;'*ÿ;(*ÿ<(*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=(+ÿ=)+ÿ>)*ÿ>)*ÿ>**ÿ>**ÿ>**ÿ>**ÿ?**ÿ@)+ÿ@)+ÿ@*+ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿA*,ÿA*,ÿA*,ÿA*,ÿA*,ÿA*,ÿA*-ÿA+-ÿA+-ÿA+,ÿA+,ÿA+,ÿ@+,ÿ@+-ÿB-.ÿB./ÿB..ÿ@,,ÿ>++ÿ>))ÿ?''ÿ?''ÿ=))ÿ;*+ÿ;**ÿ;))ÿ:'(ÿ9&&ÿ7$$ÿ6$#ÿ9'&ÿE34ÿ^MLÿ}ngÿ›�}ÿ±©‡ÿ»·„ÿ½º{ÿ¼¸oÿºµgÿ½¶hÿÐË‘ÿ·¯Nÿ²§=ÿµ§<ÿ³¢9ÿ²Ÿ5ÿ´ž3ÿ¸ 7ÿÖÅ{ÿâËnÿÚ½MÿÓ·MÿʯLÿήPÿßµXÿã½`ÿåÈiÿåÌmÿåÌnÿæÍnÿèÒ|ÿïØ¡ÿèÀrÿç¿oÿç¿pÿç¿qÿç¿sÿçÀtÿèÁuÿèÂuÿèÂvÿéÃxÿäÃzÿÛÁ~ÿÚÁ~ÿÚÂÿÚÂ�ÿÚÂÿÛÄ„ÿÛÄ„ÿÛÅ„ÿâÏšÿßÑ™ÿϼiÿмkÿнkÿоlÿпnÿξnÿɺkÿɺlÿɺmÿɺoÿÉ»pÿÊ»oÿÍ¿xÿæÞ®ÿñæ¤ÿïã˜ÿïâšÿïá›ÿïàœÿõæ·ÿõÙ±ÿòÅšÿﺙÿê´—ÿâ­”ÿÙ¥ŽÿÐ�ŠÿÊ—‡ÿÈ•†ÿÇ“†ÿÈ“‡ÿÉ’ˆÿÉ‘‰ÿÊ�ŽÿÊ��ÿÉŠ·ÿƆÓÿƒçÿ¾�îÿ»€ðÿ¹�ñÿÀ‹ÛÿÑ™­ÿÚ¡™ÿÛ šÿÛž�ÿÜ��ÿÔ›“ÿ«�nÿkPAÿF//ÿB*.ÿB+/ÿB+/ÿB+0ÿB+0ÿC+0ÿC*0ÿC*/ÿC*/ÿC*/ÿC*/ÿD+/ÿD+/ÿC+0ÿC+0ÿC+0ÿC+0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD-0ÿD,1ÿD,1ÿD,1ÿE,1ÿD,1ÿD,1ÿE,1ÿE,1ÿE,1ÿE,1ÿE-2ÿE-2ÿF-2ÿF-2ÿF-2ÿF-2ÿF-2ÿJ15ÿ`DGÿK15ÿF-2ÿF.2áF.2F.29%'9%'9%'á9%'ÿ@,.ÿfMRÿ@,.ÿ9%'ÿ:%'ÿ;&'ÿ;&(ÿ;'(ÿ;'(ÿ;'(ÿ;'(ÿ<'(ÿ;'(ÿ;')ÿ;()ÿ;(*ÿ<(*ÿ<(*ÿ=(*ÿ=(*ÿ=)+ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ>)*ÿ?)+ÿ?)+ÿ?*+ÿ?*+ÿ?*+ÿ@*+ÿ@*+ÿ@*+ÿA*,ÿA*,ÿA*-ÿA*-ÿA*-ÿA*-ÿA*-ÿA*-ÿA*-ÿA+-ÿA+-ÿA+-ÿA*-ÿA*-ÿA+-ÿA+-ÿA,-ÿA+-ÿ@+,ÿ@*,ÿ?*,ÿ>),ÿ=)+ÿ=*,ÿ=*+ÿ?()ÿ?''ÿ=))ÿ;*+ÿ;**ÿ;))ÿ:((ÿ9&&ÿ7$$ÿ7$%ÿ?-.ÿVDDÿxidÿ™�ÿ°¬‹ÿº¹‰ÿ¹»}ÿ¶¹qÿµ¶jÿ¶µgÿ¸´eÿº³dÿ»²`ÿÌÃÿƽoÿ´¦;ÿ¶¦;ÿ´¡7ÿ´Ÿ4ÿµž2ÿʸgÿÙÆ{ÿʯLÿ¨Jÿ¾¥JÿÇ©NÿݳWÿâ¶Yÿâ¶Zÿã»_ÿäÆiÿæÍnÿæÎpÿæÎqÿîÛ�ÿëɆÿç¾oÿç¿qÿç¿rÿçÀtÿèÁtÿèÁuÿèÂvÿéÃwÿæÃyÿÜÁ}ÿÚÁ~ÿÚÂÿÚÂ�ÿÚÂÿÛÃÿÛÄ„ÿÛÅ„ÿÜÆ…ÿÝÈ‹ÿåØªÿÓÂvÿнjÿоlÿоmÿпoÿξnÿɺlÿɺmÿɺnÿÉ»pÿÊ»pÿʼrÿßÖ¢ÿñè¬ÿðä˜ÿðãšÿïâ›ÿîßœÿëÚšÿç× ÿäбÿصŽÿШ‡ÿÊœƒÿÇ—‚ÿÆ•ƒÿÇ•„ÿÇ•…ÿÈ”…ÿÈ“†ÿÊ‘ŒÿÌ�šÿÎŒ°ÿΉÊÿ̆ßÿÉ„éÿƃëÿÂìÿ¿�íÿÁ†çÿÕ¢×ÿ㺽ÿÛ¢˜ÿÛ šÿÛžœÿÚž›ÿÊ—‰ÿ—t_ÿ]E:ÿC-/ÿA*.ÿB*.ÿB+.ÿB+.ÿA+.ÿA+/ÿB+/ÿB+0ÿC*/ÿC*/ÿC*/ÿC*/ÿC*/ÿD+/ÿD+/ÿC+0ÿC+0ÿC+0ÿC+0ÿC,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD-1ÿD,1ÿD,1ÿD,1ÿD,1ÿD,1ÿD,1ÿE,1ÿE,1ÿE,1ÿE,1ÿE-2ÿF-2ÿF-2ÿF-2ÿF-2ÿE-1ÿI15ÿ^DFÿI14ÿE-1ÿF-2áF-2F-29%'9%'9%'á9%'ÿ@,.ÿfMRÿA,.ÿ9%'ÿ:%(ÿ:&(ÿ;'(ÿ;'(ÿ;'(ÿ<'(ÿ;'(ÿ;')ÿ;()ÿ<()ÿ<()ÿ<()ÿ<(*ÿ<(+ÿ=)*ÿ=)*ÿ>)*ÿ>)*ÿ>)*ÿ>)+ÿ?(+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ?*+ÿ@*+ÿ@*+ÿ@*,ÿA*,ÿA*,ÿA*,ÿA+-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+-ÿB+-ÿB+-ÿB+-ÿB+-ÿA,-ÿA+-ÿ@+,ÿ?*,ÿ>*+ÿ<(*ÿ:')ÿ9%'ÿ<%&ÿ>'(ÿ<*+ÿ;++ÿ;**ÿ;()ÿ9&'ÿ7$$ÿ8&&ÿF45ÿfUTÿ��xÿª¥�ÿ·¹Žÿ·½ƒÿ²¹vÿ°·nÿ²¶kÿ´µjÿ¶µhÿ¸´fÿº³dÿ¼³bÿ½²_ÿÄ·jÿÓÉ‹ÿ¹ªBÿ·¥9ÿ²ž5ÿ«”/ÿµ¡OÿÐÀƒÿÀ¨Oÿ¼£Hÿ½¤JÿƨMÿܳVÿâ¶Yÿâ¶Zÿâ·[ÿâ·\ÿâ¹_ÿäÃgÿæÍpÿçÏqÿêÖ‡ÿïÕžÿç¿qÿç¿rÿçÀsÿçÁtÿèÁuÿèÂvÿèÃwÿèÃyÿÞÂ|ÿÚÁ~ÿÚÂÿÚ€ÿÚ‚ÿÛÃÿÛÄ„ÿÛÅ„ÿÜÆ…ÿÜÆ‡ÿÜÆ‡ÿäÔ£ÿÜΑÿнjÿоmÿпnÿÐÀpÿ;oÿɺmÿɺnÿÊ»pÿʼpÿʼpÿ×Ì‘ÿîå²ÿêß–ÿåÙ“ÿßÑ�ÿØÉ�ÿÑÁ‰ÿË»†ÿȶ…ÿɺ›ÿÇ«�ÿÆ£�ÿÇŸ‚ÿÆ—‚ÿÆ•ƒÿÈ•†ÿÊ“ŽÿΑ�ÿÓŽ²ÿÕŠÉÿÕˆÚÿÓ†ãÿІæÿÍ…çÿÊ„èÿǃêÿÆ…èÿÏ“Öÿߦ¿ÿè±¹ÿìÇÉÿÞ¨¢ÿÛŸ›ÿÖ�•ÿ¹ŒyÿbPÿO:5ÿA*.ÿA*.ÿB*.ÿB*.ÿB*.ÿB+.ÿA+.ÿA+.ÿA+/ÿB+/ÿB*/ÿB*.ÿB*.ÿB*.ÿB*.ÿC*/ÿC+/ÿC+/ÿC+/ÿC+0ÿC+0ÿC,0ÿC,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,1ÿD,1ÿD,1ÿC,1ÿD,1ÿD,1ÿE,1ÿD,1ÿD,0ÿD,0ÿD-1ÿE-1ÿE-1ÿE-1ÿE,1ÿI04ÿ^DFÿI04ÿE,1ÿF,1áF,1F,19%'9%'9%'á9%'ÿA,.ÿgNSÿA,/ÿ:%'ÿ:&(ÿ:&(ÿ:&(ÿ;'(ÿ;'(ÿ;')ÿ;()ÿ<()ÿ<()ÿ<()ÿ<(*ÿ<(*ÿ=)*ÿ=)*ÿ=)*ÿ=)*ÿ>)*ÿ?(+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ@)+ÿ@),ÿ@*,ÿ@*,ÿ@+,ÿ@+,ÿ@+,ÿ@+,ÿA+,ÿA+,ÿA+-ÿA+-ÿA+.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+.ÿA+.ÿB+.ÿB+.ÿB+.ÿB+.ÿA+-ÿA+-ÿ@*,ÿ>)+ÿ<(*ÿ:'(ÿ9%&ÿ;#%ÿ:%'ÿ8()ÿ:)*ÿ;))ÿ:((ÿ8%%ÿ9&'ÿI88ÿo`]ÿ˜�‚ÿ±±“ÿ¶¾�ÿ±¼~ÿ­¸sÿ­¶oÿ¯¶mÿ²¶lÿ´¶jÿµµhÿ·´fÿº´eÿ»³cÿ½²aÿÀ²_ÿÁ±]ÿÑŇÿ½¯[ÿ¦“1ÿ›‡,ÿ ‹:ÿȺ‚ÿíZÿ½£Gÿ½¤IÿŨMÿÛ²VÿâµYÿâ¶Zÿâ·[ÿâ·\ÿâ·]ÿâ·^ÿâ¸_ÿäÀfÿæÌpÿèÑwÿïܤÿéÅÿç¿rÿçÀtÿèÁuÿèÂvÿèÃwÿéÃxÿáÂ{ÿÚÁ~ÿÚÂÿÚ€ÿÚÂ�ÿÛÃÿÛÄ„ÿÛÅ„ÿÛÅ…ÿÜÆ†ÿÜÆˆÿÜljÿàÌ“ÿ䨩ÿÒÁrÿпnÿÑÀpÿÑÁpÿͽoÿǸmÿÅ·mÿôlÿ¿°iÿÀ³wÿÑÉŸÿÐʼnÿʾ€ÿƺ€ÿÄ·€ÿĵ�ÿÄ´�ÿÅ´‚ÿųƒÿÇ·�ÿÉ´šÿǤ„ÿÊ¡‹ÿÏ™–ÿÕ’¦ÿÜ�ºÿߌÌÿàŠÙÿÞ‰ßÿÛˆáÿ؇âÿÕ‡ãÿцäÿÎ…æÿ̆åÿÑ‘ØÿÝ£Âÿ段ÿ箵ÿ笷ÿí¾Èÿã·²ÿÊ—‡ÿ�yeÿfMAÿF01ÿ@).ÿ@*.ÿA*.ÿA*.ÿB*.ÿB*.ÿB*.ÿB+.ÿA+.ÿA+.ÿB+/ÿB+/ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB+.ÿB+.ÿB+/ÿB+/ÿB+/ÿB,/ÿB,/ÿB,/ÿC,/ÿC,/ÿC,/ÿC,/ÿC,0ÿC,0ÿC,0ÿB,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,1ÿD,1ÿE,1ÿE,1ÿI04ÿ^DFÿI04ÿE,1ÿE,1áE,1E,19%'9%&9%'á9%'ÿA,.ÿhNSÿB,/ÿ:&(ÿ:&(ÿ;&(ÿ;&(ÿ;&)ÿ;')ÿ<()ÿ<()ÿ<()ÿ<(*ÿ=)*ÿ=)*ÿ=)*ÿ=)*ÿ=)*ÿ>(*ÿ>)+ÿ>)+ÿ>)+ÿ?)+ÿ@)+ÿ@)+ÿ@),ÿ@),ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@+,ÿ@+,ÿ@+,ÿ@+-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+.ÿB,.ÿB,.ÿB,.ÿB,.ÿB,.ÿB,.ÿB,.ÿB,.ÿB,.ÿB,.ÿB+.ÿA+-ÿ@*,ÿ?*+ÿ=)*ÿ:'(ÿ:%&ÿ;$%ÿ:&'ÿ8()ÿ8'(ÿ7%'ÿ6#%ÿ8%&ÿI78ÿufdÿ¨Ÿ—ÿ¿À©ÿ¼Ç›ÿ±À†ÿ¬ºyÿ¬¸sÿ­¶pÿ®µmÿ°µkÿ³µiÿ´µhÿ·´fÿ¹´eÿ»³cÿ½³aÿ½°^ÿ¹©[ÿ± Uÿ¶¥hÿ¾²zÿš†/ÿ™„/ÿ¿°uÿÈ´jÿ½£Gÿ½¤IÿçLÿÙ±UÿáµYÿâ¶Yÿâ·[ÿâ·\ÿâ·]ÿâ·^ÿâ¸_ÿâ¸`ÿã¹`ÿä¾eÿæÉnÿìÙ’ÿíÒ˜ÿçÀsÿèÁuÿèÂuÿèÃvÿéÃxÿäÃzÿÛÁ~ÿÚÂ~ÿÚ€ÿÚÂ�ÿÛÃÿÛÄ„ÿÛÅ„ÿÜÆ…ÿÝLJÿÝLjÿÝljÿÜÇŠÿÛÆŠÿâÓ§ÿÒăÿƶiÿ³iÿ¾¯gÿ¶§cÿ¯¡`ÿ¬ž`ÿ©›^ÿ©œcÿ½´ŽÿÅ»†ÿø|ÿĸ~ÿ÷ÿĶ€ÿĵ€ÿŵ‚ÿdz†ÿ̯�ÿÓªšÿݧ´ÿä—·ÿé’ÅÿìŽÑÿëŒØÿé‹Ûÿæ‹ÜÿâŠÝÿ߉Þÿ܉ßÿÙˆáÿÕ†ãÿÔ‡âÿÖ‘×ÿÞ¢Âÿ宵ÿç±³ÿç®¶ÿç­¸ÿ笶ÿÞ«­ÿ»œŽÿ{^OÿQ:6ÿB,.ÿA*.ÿA*.ÿA*.ÿA*.ÿA*.ÿA*.ÿB*.ÿB*.ÿB*.ÿB+.ÿA+.ÿA+.ÿB+.ÿB+/ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB+.ÿB+.ÿB+.ÿB+/ÿB,/ÿB,/ÿB,/ÿB,/ÿC,/ÿC,/ÿC,/ÿC,/ÿC,/ÿC,0ÿB,0ÿB,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,1ÿE,1ÿI05ÿ^DFÿI04ÿE,1ÿE,1áE,1E,1:%&:%&:%&á:%'ÿB,/ÿhOTÿB-/ÿ:&(ÿ;&(ÿ;&(ÿ;')ÿ;')ÿ;')ÿ<()ÿ<(*ÿ=)*ÿ=)*ÿ=)*ÿ=)*ÿ=)*ÿ>(*ÿ>)*ÿ>)*ÿ>)*ÿ>)+ÿ?)+ÿ?),ÿ@),ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*-ÿ@*-ÿ@*-ÿ@+-ÿ@+-ÿA,-ÿA,-ÿA,-ÿB,-ÿB,-ÿB,.ÿB,.ÿB,/ÿB,/ÿB,/ÿB,/ÿB,/ÿB,/ÿB,/ÿB,/ÿB,.ÿB+.ÿA*-ÿ?),ÿ=(*ÿ:')ÿ;%&ÿ<$%ÿ9'(ÿ9()ÿ9'(ÿ7%&ÿ5"$ÿ@./ÿk[Zÿ¥œ‘ÿÇÈŸÿÈÓ�ÿÉÕ�ÿÉÕ”ÿËÕ™ÿÌÔ›ÿËÑšÿÉΗÿÆÊ‘ÿÃʼnÿÁÁ�ÿ¿½xÿ¾¹pÿ¼µiÿ¶­bÿ¯¢[ÿ¨™Uÿ¤“Rÿ¤‘Pÿ¨“Rÿôƒÿ¥’Dÿ³¢`ÿ̺yÿ½¤Iÿ½¤Iÿ¦LÿذTÿáµYÿâ¶Yÿâ·Zÿâ·\ÿâ·]ÿâ·^ÿâ¸_ÿâ¸_ÿã¹`ÿãºaÿãºbÿã¼dÿçÊvÿðÛ¦ÿéÄ{ÿèÁuÿèÂvÿéÃxÿæÃzÿÝÂ}ÿÚÂÿÛÀÿÚÃ�ÿÚÂÿÚƒÿØÁ‚ÿÖÀ�ÿÓ½€ÿк€ÿË·~ÿȳ|ÿİzÿÀ¬xÿÀ¯„ÿ½²ˆÿ­ž^ÿ¬�]ÿ«�]ÿ§™\ÿ¦˜\ÿ¦™]ÿ§™^ÿ¶®ƒÿŽŒÿù|ÿĹ~ÿƶ�ÿʳ‡ÿѯ�ÿÙª›ÿ䣩ÿÿö–Äÿú’Íÿù�Òÿ÷�ÔÿóŽÖÿð�Öÿí�ØÿêŒÙÿæ‹ÚÿãŠÜÿà‰Þÿ݈ßÿÛŠÝÿá“Òÿ磿ÿ毳ÿè²²ÿç±´ÿ篶ÿ箵ÿß©«ÿÀ•�ÿŒl`ÿ\D>ÿD.0ÿ@).ÿ@+.ÿA+.ÿA+.ÿA*-ÿA*-ÿA*.ÿA*.ÿB*.ÿB*.ÿB*.ÿB*.ÿA+.ÿA+.ÿA+.ÿB+.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB+.ÿB+.ÿB+.ÿB+/ÿB,/ÿB,/ÿB,/ÿB,/ÿC,/ÿC,/ÿC+/ÿC,/ÿC,/ÿC,0ÿB,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,1ÿI04ÿ^CFÿI04ÿE-0ÿE-0áE-0E-0:%':%':%'á:&'ÿB-/ÿiOTÿB-/ÿ;&(ÿ;')ÿ;')ÿ;')ÿ;')ÿ;'*ÿ<(*ÿ<(*ÿ=)*ÿ=)*ÿ=)*ÿ>(*ÿ>)*ÿ>)*ÿ>)*ÿ?)*ÿ?)+ÿ?)+ÿ?*,ÿ?*,ÿ@*,ÿ@*,ÿ@*,ÿ@*-ÿ@*-ÿ@*-ÿ@*-ÿA+-ÿA+-ÿA+-ÿA,-ÿA,-ÿA,.ÿA,.ÿB,.ÿB,.ÿC,.ÿC,.ÿC,/ÿC,/ÿC,/ÿC,/ÿC-/ÿC,/ÿC-/ÿB,/ÿB,.ÿA+.ÿ@*,ÿ>)+ÿ;')ÿ;%'ÿ<$&ÿ:'(ÿ9()ÿ9'(ÿ7$%ÿ9&'ÿXFGÿ•ŠƒÿÄÆ¬ÿÄÖ�ÿÌÛ›ÿ°ÄZÿ±ÃVÿ´ÃWÿ¸ÃXÿ»Ä[ÿÀÆ`ÿÅÉgÿÊËoÿÎÎxÿÐ΀ÿψÿÌÇŠÿÊÃŒÿżŠÿÀ¶…ÿ¼±ÿ¹«wÿµ¥mÿ±žbÿ¾­yÿǹˆÿ̽ƒÿÀ¨Pÿ¼£GÿÁ¥IÿÖ¯Rÿá´WÿáµXÿâ¶Zÿâ·[ÿâ·]ÿâ·]ÿâ·_ÿâ¸_ÿã¹`ÿãºaÿãºbÿãºcÿã»dÿã¼eÿíÒ“ÿíÍ�ÿèÂuÿéÃwÿçÂxÿÛ¿zÿÓ»zÿϸyÿË´wÿưvÿ­uÿ¾©sÿ»§qÿ¹¥pÿ·£pÿ¶¢qÿµ¢qÿµ¢qÿµ¢rÿµ£sÿ¶¤vÿ½²Žÿ¯£iÿ«œ\ÿª�]ÿ¦š\ÿ§™]ÿ©™_ÿµ¤yÿ͸šÿÓ³ŽÿÛ®—ÿã©¢ÿ죭ÿóŸ·ÿùšÀÿý—Æÿþ•Êÿÿ“Ìÿÿ’Îÿþ‘Ðÿú�Ñÿ÷�ÓÿôŽÔÿñŽÖÿî�×ÿëŒÙÿç‹ÚÿäŠÛÿäŽ×ÿè˜Ëÿ糧ÿó°°ÿê´¯ÿç²²ÿè±´ÿç°³ÿÞ«ªÿ—�ÿ‘rdÿbIAÿG01ÿ?).ÿ@).ÿ@*.ÿA*.ÿ@+.ÿ@+.ÿ@*.ÿ@*-ÿA*-ÿA*.ÿA*.ÿB*.ÿB*.ÿB*.ÿB*.ÿA+.ÿA+.ÿA+.ÿB+.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿA*.ÿB+.ÿB+.ÿB+.ÿB,/ÿB,/ÿB,/ÿB,/ÿB,/ÿC,/ÿC+0ÿC+/ÿC,/ÿC,/ÿB,0ÿB,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿH14ÿ^CEÿI14ÿE-0ÿE-0áE-0E-0:&'9&':&'á:&'ÿB-.ÿiOTÿC-0ÿ;&)ÿ;')ÿ;')ÿ;')ÿ;'*ÿ<(*ÿ<(*ÿ<(*ÿ=(*ÿ>(*ÿ>)*ÿ>)*ÿ>)*ÿ?)*ÿ?)+ÿ?)+ÿ?*+ÿ?*+ÿ@*+ÿ@*,ÿ@*-ÿ?*-ÿ@*-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+-ÿA+.ÿA+.ÿB+.ÿB,.ÿB,.ÿB,.ÿB-.ÿB-.ÿC-.ÿC-.ÿC-.ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿB,/ÿA,.ÿ@+-ÿ>),ÿ<(*ÿ<%'ÿ=$&ÿ:')ÿ:()ÿ9'(ÿ7$%ÿD12ÿvgcÿ°­”ÿÔÝ·ÿ¹Ô‹ÿ­ÌtÿÉÚœÿ¼Ënÿ³ÂUÿµÂTÿ·ÁRÿ¹ÁPÿ»ÀNÿ»½Kÿ¸¸Gÿ³°Bÿ­§>ÿª¢<ÿ«¡=ÿ¯£Aÿ´¦Gÿ¹ªPÿ¾¯YÿódÿÇ·nÿʺvÿÒ‹ÿâÙ¸ÿÙÊ“ÿÒÀ~ÿѾzÿÝÀxÿæÂuÿå¾nÿä¼gÿãºcÿâ¸`ÿâ·^ÿâ·]ÿâ·^ÿâ¸^ÿã¹`ÿãºbÿä»cÿã»dÿâ»dÿà¹cÿß½sÿáÄ”ÿÕ®kÿЮlÿĨlÿº£lÿ¶¡jÿ´Ÿjÿ³žkÿ³Ÿlÿ³Ÿmÿ³ mÿ´¡mÿµ¡nÿµ¡pÿµ¢qÿµ¢qÿµ£qÿµ£rÿ¶¤tÿ·¥uÿ¾­ˆÿ¿¬ƒÿ» lÿâvÿÊ¡ÿÕ¢Šÿࣗÿì§©ÿô¦±ÿ÷¢´ÿú ¹ÿûž¼ÿüœ¿ÿü›Áÿü™Ãÿý—Åÿý–Èÿþ”Êÿþ’Íÿþ‘Ïÿû�Ñÿø�ÒÿõŽÔÿò�ÕÿïŒ×ÿìŽÖÿë—Ïÿî¥Ãÿó«µÿö°¯ÿõµ­ÿì´¯ÿç²²ÿæ±°ÿÚª¥ÿ½”‹ÿ�pdÿbJBÿI10ÿ@),ÿ?(,ÿ@).ÿ@).ÿ@).ÿ@).ÿA*.ÿA*.ÿ@+.ÿ@*-ÿ@*-ÿ@*-ÿ@*.ÿA*.ÿA*.ÿB*.ÿB*.ÿA*.ÿA+.ÿA+.ÿA+.ÿA*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿA*.ÿB+.ÿB+.ÿB+.ÿB,/ÿB,/ÿB,/ÿB,/ÿB,/ÿC,0ÿC+0ÿC+/ÿC,/ÿC,0ÿB,0ÿB,0ÿC,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿD,0ÿH03ÿ]CEÿH14ÿD-0ÿD-0áD-0D-09&'9&'9&'á:&'ÿC-/ÿjPUÿC.0ÿ;')ÿ;')ÿ;'*ÿ<(*ÿ<(*ÿ<(*ÿ<(*ÿ=(*ÿ=)*ÿ=)*ÿ>)*ÿ?)*ÿ?)+ÿ?)+ÿ?*+ÿ@*+ÿ@*+ÿ@*,ÿ?*,ÿ?*,ÿ@+-ÿ@+-ÿ@+-ÿA+-ÿA+.ÿA+.ÿB+.ÿB+.ÿB+.ÿB,.ÿB,.ÿB,.ÿB-.ÿB-.ÿB-/ÿC-/ÿC-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD-/ÿC-/ÿB,.ÿA+-ÿ?*,ÿ<(*ÿ<&(ÿ=$&ÿ;')ÿ:()ÿ9&(ÿ8$&ÿS@Bÿ‘†{ÿ½Ã–ÿÒà­ÿ¾Ø”ÿ¬Ësÿ®Êqÿ¾ÓˆÿÊÕŒÿµÂTÿ·ÂSÿ¸ÀQÿµºMÿ°²Hÿª©Cÿ§£?ÿ¦ <ÿ§Ÿ;ÿ©Ÿ:ÿ«ž8ÿ¬ž6ÿ­�5ÿ®œ3ÿ°œ0ÿ²›/ÿ³›-ÿ·ž3ÿ˹rÿÊ»†ÿͺmÿÆ­NÿÛ»aÿçÃpÿèÈzÿêË„ÿë΋ÿìÏ�ÿìÏ�ÿëÎŽÿëÌŠÿéÉ„ÿçÅ|ÿâ¿sÿÜ·jÿÕ±dÿΪ^ÿǤZÿ Wÿ¾�Wÿé}ÿ¿—eÿ¹•\ÿ³œfÿ²�hÿ³žiÿ²žjÿ³žkÿ³Ÿlÿ³ mÿ´¡mÿ¶¡oÿ¸¢qÿ»¤sÿÀ§vÿÅ©zÿË«~ÿÒ¬„ÿÙ®Šÿà¯�ÿ篗ÿí°žÿð­Ÿÿô¬¥ÿö«©ÿø©¬ÿø§¯ÿù¥±ÿù¤³ÿù¢µÿú¡¸ÿúŸºÿû�½ÿû›¿ÿüšÂÿü˜Äÿý–Çÿþ•Éÿþ“Ìÿÿ‘Îÿý�Ñÿú�Òÿö‘Óÿó—Îÿò£Äÿó²¹ÿô½²ÿöÁ°ÿöº°ÿõ¶­ÿï¶­ÿ㱬ÿÒ¥�ÿ°Œ€ÿƒg\ÿ\E?ÿG11ÿ@*-ÿ@),ÿA),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@).ÿ@).ÿA).ÿA*.ÿ@*.ÿ@*-ÿ@*-ÿ@*-ÿ@*.ÿA*.ÿA*.ÿA*.ÿA*.ÿ@*.ÿ@*.ÿA+.ÿA+.ÿA*-ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿA*.ÿA*.ÿA*.ÿB+.ÿB,.ÿB,/ÿB,/ÿB,/ÿB,/ÿB,/ÿC+/ÿC+/ÿC+/ÿC+/ÿB,/ÿB,0ÿC,0ÿC,0ÿC,0ÿD,0ÿC,0ÿC,0ÿC,0ÿG03ÿ]CEÿH14ÿD-1ÿE-1áE-1E-1:&':&':&'á:&'ÿB./ÿjQUÿC./ÿ;'(ÿ<(*ÿ<(*ÿ<(*ÿ<(*ÿ=(*ÿ=)*ÿ=)*ÿ=(*ÿ>(*ÿ>(+ÿ?)+ÿ?*+ÿ@*+ÿ@*+ÿ@*,ÿ?*,ÿ?*,ÿ@+,ÿ@+,ÿ@+-ÿ@+-ÿ@+.ÿA+.ÿA+.ÿB,.ÿB,.ÿB,.ÿB,.ÿB,/ÿC,/ÿC,/ÿC,/ÿC-/ÿC-/ÿC-/ÿC-/ÿC./ÿD./ÿD./ÿD./ÿD./ÿD./ÿD./ÿC-.ÿB,.ÿ@+,ÿ=)+ÿ<'(ÿ=%&ÿ;'(ÿ:()ÿ9''ÿ;'(ÿbPPÿ¥Ÿ‹ÿ¾Í‘ÿÅÛ–ÿÅÜžÿ­Ìvÿ®Ësÿ±ËpÿµÌtÿÎÚšÿ¸Á^ÿ­³Kÿ§ªGÿ£¤Cÿ¢¡@ÿ¤¡?ÿ¦ =ÿ§ <ÿ¨Ÿ:ÿªŸ9ÿ¬ž7ÿ­�6ÿ¯�4ÿ°�3ÿ²œ1ÿ³œ0ÿµ›.ÿDz`ÿ¼©eÿ¦Ž<ÿ̺xÿѬAÿÞ°Bÿß±Dÿß²Dÿà´Fÿá¶Kÿâ·Pÿá¹VÿÞ¹^ÿÚ¸gÿÔ¶nÿͲsÿÈ®uÿĬwÿëzÿ«{ÿªzÿÁ©wÿÀ¦qÿì€ÿÂ¥�ÿ´‘bÿ²•dÿ´�iÿ·¡kÿ»¤mÿÀ©pÿƬsÿͱvÿÕ´zÿÛ·ÿḃÿ湈ÿ뺌ÿî¹�ÿð¹“ÿò·–ÿó¶™ÿô´œÿô²žÿô° ÿõ¯£ÿõ­¥ÿö«¨ÿöªªÿ÷¨­ÿø¦¯ÿø¥²ÿù£´ÿù¡·ÿúŸ¹ÿúž¼ÿûœ¾ÿüšÁÿü™Ãÿý—Æÿþ•Éÿþ“Ëÿþ•Ìÿü�Éÿø¬Ãÿ÷ÆÌÿõĹÿôÁ¬ÿõÀ¬ÿõ¿¬ÿõ½«ÿòº¨ÿä± ÿÄœŽÿ�|pÿsYOÿS=8ÿC-.ÿ?(,ÿ?)-ÿ@)-ÿ@*-ÿA),ÿA),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿA).ÿ@).ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@*.ÿA*.ÿB*.ÿB*.ÿA*.ÿA*.ÿ@*.ÿ@+.ÿ@*.ÿA*-ÿA*.ÿA*.ÿA*.ÿA*.ÿA*.ÿA*.ÿ@*.ÿA*.ÿA+.ÿA,.ÿA,/ÿA,/ÿA,/ÿA,/ÿB,/ÿB+/ÿB+/ÿB+/ÿB+/ÿA,/ÿB,0ÿB,0ÿB,0ÿC,0ÿD,0ÿD,0ÿD,0ÿH/3ÿ]BEÿH04ÿD,1ÿE,1áE,1E,1:&(:&(:'(á:'(ÿB./ÿjQUÿC.0ÿ;')ÿ<()ÿ<(*ÿ=(*ÿ=)*ÿ=)*ÿ=(*ÿ>(*ÿ>(+ÿ>(+ÿ>)+ÿ?)+ÿ@*+ÿ@*,ÿ?*,ÿ@+,ÿ@+,ÿ@+,ÿ@+-ÿ@+-ÿA+-ÿA+-ÿA,.ÿA,.ÿA,.ÿB,/ÿC,/ÿC,/ÿC,/ÿC,/ÿC,/ÿC-/ÿC-/ÿC-/ÿD-/ÿD./ÿD./ÿD./ÿD./ÿD./ÿD./ÿD./ÿD.0ÿC-/ÿB-/ÿ@,-ÿ>*,ÿ<(*ÿ=%'ÿ<&(ÿ9)*ÿ9'(ÿ<)+ÿn]\ÿ°¯”ÿ¼Ñ‹ÿ¸Ô‚ÿÉÞ¤ÿ°Ï}ÿ®Ësÿ°Êqÿ®Åmÿ¨¼fÿ¹Ä†ÿ·ºsÿŸ Bÿ ¡Bÿ¢¡@ÿ¤¡?ÿ¥¡=ÿ§ <ÿ¨Ÿ;ÿªŸ9ÿ¬ž7ÿ­�6ÿ®�5ÿ°�3ÿ²œ1ÿ³œ0ÿ´š-ÿÁªLÿƵuÿ¤‰1ÿ��'ÿʱqÿä½`ÿß²Dÿà³Fÿß³FÿÛ°FÿÔªEÿË¢CÿœAÿ½˜@ÿº•?ÿ¸”?ÿ¸”@ÿ¹•Bÿº–Eÿº˜Iÿ»šNÿ½�Tÿ¿¢]ÿèfÿʵ|ÿÑÀ‘ÿѼ‚ÿÕ¼zÿÙ¾sÿßÃtÿäÅxÿèÆ{ÿëÆ~ÿíÅ�ÿîÄ„ÿï†ÿïÀ‰ÿð¿‹ÿð½Žÿð»�ÿñ¹“ÿñ¸•ÿò¶˜ÿó´šÿó³�ÿô±Ÿÿô¯¢ÿõ®¤ÿö¬§ÿöª©ÿ÷©¬ÿ÷§®ÿø¥±ÿø£³ÿù¢¶ÿú ¸ÿúž»ÿûœ¾ÿüšÀÿüšÂÿü�Âÿú¦Àÿø´»ÿöÄ´ÿôϯÿôÓ¬ÿõÛ»ÿøÕÂÿô¾§ÿò½¦ÿèµ ÿÑ£�ÿ­ˆvÿƒgZÿ_HAÿJ31ÿ@*+ÿ?(*ÿ?)+ÿ?),ÿ?)-ÿ@)-ÿ@)-ÿ@)-ÿA),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿA).ÿA).ÿB).ÿB).ÿA).ÿA*.ÿA*.ÿA*.ÿA*-ÿA*-ÿB*.ÿB*.ÿB*.ÿB*.ÿA*.ÿ@*.ÿ@*.ÿA*.ÿA,.ÿA,.ÿA,/ÿA,/ÿB,/ÿB,/ÿB+/ÿB+/ÿC+/ÿC+/ÿB+/ÿB,/ÿC,0ÿC,0ÿC+0ÿD+0ÿD+0ÿD+0ÿH/3ÿ]AEÿH/3ÿD+0ÿD,0áD,0D,0:'(:'(:'(á:'(ÿB.0ÿjRVÿC/0ÿ<()ÿ<()ÿ=()ÿ=)*ÿ=)*ÿ>(*ÿ>(+ÿ>(+ÿ>)+ÿ?)+ÿ?)+ÿ?),ÿ>),ÿ?*,ÿ@+,ÿ@+,ÿ@+-ÿ@+-ÿA+-ÿA,-ÿA,-ÿA,-ÿA,.ÿB,.ÿB,/ÿB,/ÿB,/ÿC-/ÿC-/ÿC-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD./ÿD./ÿD./ÿD./ÿD./ÿD./ÿD./ÿC-/ÿB,.ÿ@+-ÿ=)+ÿ=&(ÿ=%'ÿ:)*ÿ9')ÿ=+,ÿtdcÿµ·˜ÿºÒ‡ÿ°ÐuÿÊߣÿ¶Ò‡ÿ©Æqÿ¦¾lÿ ´fÿœ­aÿš¨]ÿ£®hÿÁÄŒÿ¤¤Hÿ¡¡@ÿ£¡@ÿ¥¡>ÿ§ <ÿ¨Ÿ;ÿªŸ9ÿ«ž8ÿ­�6ÿ®�5ÿ°�3ÿ²�2ÿ³œ0ÿ´›.ÿ»¢<ÿ˺yÿª‘?ÿ „'ÿ«‡,ÿÇ¡TÿãÄ|ÿØ­DÿÏ¥AÿÅž@ÿ¾˜>ÿ¹”>ÿ·“>ÿ¸”@ÿ¸”@ÿ¹•@ÿ¸”Aÿ¹•Bÿ»—Dÿ¾›HÿÄ¢LÿË«QÿÑ´Wÿؾ\ÿÞÇaÿãÐhÿçÓmÿèÒnÿêÑqÿêÏtÿëÍvÿëËxÿëÉ{ÿìÇ}ÿìÆ€ÿíÄ‚ÿîÂ…ÿîÁ‡ÿᅧÿï½�ÿð¼�ÿñº’ÿñ¸”ÿò·—ÿòµ™ÿó³œÿô²žÿô°¡ÿõ®£ÿõ­¦ÿö«¨ÿö©«ÿ÷§­ÿø¥°ÿø£³ÿù¢µÿù¡·ÿù¤¸ÿùª¸ÿ÷µ´ÿõÁ±ÿôÌ­ÿóÓ©ÿòÕ§ÿóÕ§ÿóÓ¨ÿóÑ©ÿðΪÿé͸ÿЧ’ÿ®ŠxÿŠl_ÿgNGÿO76ÿB+-ÿ?(*ÿ?(*ÿ?)*ÿ@)*ÿ?)*ÿ?)+ÿ?)-ÿ?)-ÿ?)-ÿ?)-ÿ@)-ÿ@),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@),ÿ@),ÿ@),ÿ@),ÿA)-ÿA)-ÿB).ÿA).ÿA).ÿA).ÿA).ÿA).ÿA)-ÿA)-ÿB).ÿB).ÿB).ÿB).ÿA).ÿA*.ÿA).ÿA*.ÿB+.ÿB,.ÿB+/ÿB+/ÿB+/ÿB+/ÿB*/ÿB*/ÿC*/ÿC*/ÿB*/ÿC+/ÿC+/ÿC+0ÿC+0ÿC+0ÿD+/ÿH/3ÿ]ADÿH/2ÿD+/ÿD+/áD,/D+/:'(:'(:'(á:'(ÿC/0ÿkRVÿC/0ÿ<()ÿ=))ÿ=))ÿ=()ÿ>(*ÿ>(+ÿ>)+ÿ?)+ÿ?)+ÿ?),ÿ>),ÿ?*,ÿ?*,ÿ?*,ÿ@+-ÿ@+-ÿA+-ÿA,-ÿA,-ÿA,.ÿB,.ÿB,.ÿB,.ÿB,.ÿB-/ÿB-/ÿC-/ÿC-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD-/ÿD./ÿD./ÿD./ÿD.0ÿD.0ÿD.0ÿD.0ÿD.0ÿD-/ÿC-.ÿA+.ÿ>*,ÿ='*ÿ>%'ÿ;(*ÿ9(*ÿ=*,ÿscbÿ¸¹šÿ¹Ó†ÿ¬ÍnÿÃÙ˜ÿ¶ÌŽÿœ¶iÿ˜­eÿ—©aÿ˜©_ÿš©]ÿœ¨\ÿ�§Zÿ¼Àˆÿ±±bÿ¢ >ÿ¥¡>ÿ¦ <ÿ¨ ;ÿ©Ÿ:ÿ«ž8ÿ­ž7ÿ®�6ÿ¯�4ÿ±�2ÿ³œ1ÿ´›/ÿ·�2ÿ˸pÿ´žSÿ¡…'ÿ­Š.ÿµ‹3ÿ¯†7ÿÀ¥pÿ¾šIÿ¸’;ÿ·’=ÿ¸“=ÿ·“>ÿ·“?ÿ¸•@ÿ»—BÿÀœGÿȤNÿÑ®VÿÙ¸]ÿßÁcÿäÈgÿçÍiÿèÐiÿèÒjÿèÓiÿçÕiÿçÔkÿèÒmÿéÐpÿéÏrÿêÍuÿêËwÿëÊzÿìÈ|ÿìÆÿíÅ‚ÿíÄÿîÁ‡ÿïÀ‰ÿフÿð¼Žÿð»‘ÿñ¹“ÿò·–ÿò¶˜ÿó´›ÿó²�ÿô° ÿõ®¢ÿõ¬¥ÿö«¨ÿöª«ÿ÷«¯ÿ÷¯°ÿöµ®ÿõ½¬ÿôÆ©ÿòϧÿñÖ¤ÿñÙ¢ÿñØ¢ÿò×£ÿòÕ¥ÿðÒ¥ÿéË¢ÿÚ¼™ÿÁ¤‰ÿ¢‡rÿ�j^ÿdMGÿQ:8ÿG11ÿD-/ÿD,.ÿB+.ÿA*,ÿ@)+ÿ@(*ÿ@(*ÿ@(*ÿ?)*ÿ?)+ÿ?),ÿ?)-ÿ?)-ÿ?)-ÿ?),ÿ?),ÿ?),ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@)-ÿ@(,ÿ@),ÿ@),ÿ@),ÿA),ÿA),ÿA)-ÿA)-ÿA)-ÿA)-ÿA)-ÿA)-ÿA)-ÿA),ÿA)-ÿB)-ÿB).ÿB).ÿA).ÿA).ÿA).ÿA).ÿA*.ÿB+.ÿB+.ÿB+.ÿB+/ÿB+/ÿB*/ÿB*.ÿB*.ÿC*.ÿB*.ÿB*.ÿC+.ÿC+/ÿC+/ÿC+/ÿC+/ÿH/2ÿ]ADÿH/2ÿD+/ÿD+/áD+/D+/:'):'):()á:()ÿC/1ÿkSWÿD/0ÿ<()ÿ<))ÿ>()ÿ>(*ÿ>)*ÿ>)+ÿ?)+ÿ?),ÿ>),ÿ?*,ÿ?*,ÿ?*,ÿ?*-ÿ@*-ÿ@*-ÿA+-ÿA,-ÿA,.ÿB,.ÿB,.ÿB,.ÿB-.ÿB-.ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿD-/ÿD./ÿD.0ÿD.0ÿD.0ÿD.0ÿD.0ÿD.0ÿD.0ÿD.0ÿD.0ÿD.0ÿD.0ÿD-/ÿC,.ÿ@+-ÿ>)+ÿ?&(ÿ=&(ÿ:)+ÿ;(+ÿm\\ÿ¶¶šÿ·Ð†ÿ¢Âgÿ´Ê„ÿ¶È•ÿ•«fÿ”¨bÿ–©aÿ˜©`ÿš©^ÿœ¨\ÿ�¨Zÿž¦Xÿ¬²nÿÁÀ‚ÿ¥¢@ÿ¦ =ÿ§ ;ÿ©Ÿ:ÿ«ž9ÿ¬ž7ÿ­�6ÿ¯�4ÿ±�2ÿ³œ1ÿ´œ0ÿµ›-ÿDz_ÿ¾ªgÿžƒ)ÿ¡�+ÿ¨€0ÿŸx.ÿ›u-ÿ©‹Rÿ¼ aÿ·’;ÿ·“=ÿº”?ÿ¿šEÿÈ¢NÿÓ¬VÿÛµ^ÿâ½dÿæÃgÿèÆiÿèÈiÿçÊiÿçËiÿçÍiÿçÏiÿçÐiÿçÒiÿçÔiÿçÔjÿèÓlÿèÑoÿéÏqÿêÎtÿêÌvÿëÊyÿëÉ|ÿìÇ~ÿíÅ�ÿíăÿî†ÿîÀˆÿï¿‹ÿð½�ÿð»�ÿñ¹“ÿñ·•ÿò¶˜ÿó´šÿó³œÿó´ ÿò¶£ÿó¼ ÿó›ÿôÌ¥ÿöÙ¶ÿöâ¼ÿõæ»ÿõç»ÿõæ¸ÿôã³ÿóÞ®ÿðÙªÿèÏ¢ÿÙ¿˜ÿÄ«‹ÿ¨�yÿŠrcÿoXOÿYD?ÿL75ÿE00ÿC./ÿC-/ÿD./ÿD./ÿE.0ÿD-/ÿD-/ÿD-.ÿB+-ÿA)+ÿ@(*ÿ@(*ÿ@(*ÿ?)+ÿ?),ÿ?),ÿ?),ÿ?(,ÿ?),ÿ>),ÿ?),ÿ?),ÿ?),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ?(-ÿ@(,ÿ@),ÿ@),ÿ@),ÿA),ÿA),ÿA)-ÿA)-ÿA)-ÿA)-ÿA)-ÿA(-ÿA),ÿA),ÿA),ÿB),ÿB)-ÿB)-ÿA)-ÿA)-ÿA)-ÿA)-ÿA*-ÿB+-ÿB+-ÿB+-ÿB+.ÿB+.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿC*.ÿC+.ÿC+.ÿC+/ÿC+/ÿG/2ÿ\ADÿH/2ÿD+/ÿD+/áD+/D+/;();();()á;()ÿC/1ÿkSWÿD01ÿ<()ÿ=(*ÿ=(*ÿ>)*ÿ?)*ÿ?)+ÿ>),ÿ?),ÿ?*,ÿ?*,ÿ?*-ÿ@*-ÿ@*-ÿ@+-ÿ@+-ÿA+.ÿA,.ÿB,.ÿB,.ÿB-.ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC./ÿC./ÿC.0ÿC.0ÿD.0ÿD.0ÿD.0ÿE-0ÿE-0ÿE-0ÿE-0ÿE-0ÿE.0ÿE.1ÿE/1ÿD.0ÿC./ÿB,.ÿ?*,ÿ>(*ÿ?%'ÿ;(*ÿ9(*ÿ_NOÿ«¦“ÿ¯Âƒÿ–²_ÿ¡·oÿºÉšÿ™®mÿ”©bÿ–©bÿ˜©`ÿ™©^ÿ›¨]ÿ�¨[ÿž§Yÿ ¦Xÿ£§YÿÃËÿ¯«Rÿ§Ÿ:ÿ¨Ÿ:ÿªŸ9ÿ¬ž7ÿ­�6ÿ¯�5ÿ°�3ÿ²œ1ÿ³œ0ÿµ›-ÿÀ¨KÿÁ¯tÿ–}/ÿ’t'ÿ y.ÿ x/ÿœv.ÿ›v.ÿ }:ÿ¼¡lÿÅžLÿϤRÿÚ®\ÿâ¶dÿæ¼gÿè¾iÿèÀiÿçÂhÿçÃhÿçÅhÿçÇiÿçÈiÿçÊiÿçÌiÿçÎiÿçÐiÿçÑiÿçÓiÿçÔiÿèÓkÿèÒnÿéÐpÿéÎsÿêÍvÿëËxÿëÉ{ÿìÈ}ÿìÆ€ÿíăÿîÂ…ÿîÁ‡ÿ￉ÿï¿‹ÿフÿᅩÿïÁ‹ÿîÉÿídžÿðÒ�ÿåÏ¡ÿÝÍ™ÿðâ¥ÿîÞ‰ÿïÞ‹ÿïÝ�ÿïÜ�ÿîÚ–ÿêÖ�ÿàÍ ÿÑ¿žÿ½¬–ÿ¥’ƒÿˆsfÿnYPÿ[FAÿM87ÿF11ÿC./ÿC..ÿC./ÿC//ÿC//ÿC./ÿD./ÿD./ÿD./ÿD.0ÿD.0ÿD.0ÿE//ÿD-.ÿC+,ÿA)+ÿ@(*ÿ@(*ÿ@(+ÿ@(,ÿ?),ÿ?),ÿ?(+ÿ>)+ÿ>),ÿ?),ÿ?),ÿ?),ÿ?),ÿ?)-ÿ?)-ÿ?)-ÿ?(,ÿ@(,ÿ@),ÿ@),ÿA),ÿA),ÿA),ÿA)-ÿ@)-ÿA)-ÿA)-ÿA)-ÿA(,ÿA),ÿA),ÿA),ÿB),ÿB)-ÿA)-ÿA)-ÿA)-ÿA)-ÿA*-ÿA*-ÿB+-ÿB+-ÿB+-ÿB+.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿB*.ÿC*.ÿC+.ÿC+.ÿC+/ÿG/2ÿ\ADÿH/2ÿC+/ÿD+/áC+/D+/;();');()á;()ÿD01ÿlTXÿE/1ÿ<()ÿ=)*ÿ=)*ÿ>)*ÿ>)+ÿ>)+ÿ?*+ÿ?*,ÿ?*-ÿ?*-ÿ@*-ÿ@+-ÿ@+-ÿA+.ÿA+.ÿA+.ÿA,.ÿB,.ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC./ÿC./ÿC./ÿC./ÿC./ÿC.0ÿD-0ÿD-0ÿE-0ÿE.0ÿE.1ÿE.1ÿE.1ÿE.1ÿE.1ÿE.1ÿF.1ÿE/1ÿD.0ÿC-/ÿA,.ÿ>*+ÿ@'(ÿ>&(ÿ:(*ÿO=?ÿ�“‰ÿ®º‡ÿ”®_ÿ™°cÿºÊ˜ÿ¡µyÿ”©bÿ•©bÿ—©aÿ™©_ÿ›©]ÿ�¨[ÿž§ZÿŸ§Yÿ¡¦Wÿ¢¥Tÿ¶·uÿ¿ºtÿ¨Ÿ9ÿªŸ9ÿ¬ž8ÿ­�6ÿ®�5ÿ°�3ÿ²�2ÿ³œ0ÿ´š.ÿ³š7ÿµ¥kÿ‘{8ÿŒp%ÿžx-ÿ£z/ÿŸx/ÿ¢{3ÿ²‡@ÿƘPÿÜ­gÿå´hÿç¶hÿè¸iÿçºhÿç»hÿç½hÿç¿hÿçÁhÿçÃhÿçÄhÿçÆhÿçÈiÿçÊiÿçËiÿçÍiÿçÏiÿçÑiÿçÓiÿçÔiÿçÔkÿèÒmÿèÑoÿéÏrÿêÍtÿêËvÿêÉwÿêÆwÿêÄvÿêÂuÿêÇyÿêÌ|ÿêÎ{ÿêÐ{ÿêÒ{ÿêÔ|ÿê×}ÿëØ}ÿíÞ�ÿëá®ÿØËŠÿÓňÿèÛ®ÿäÑ�ÿÙĉÿÊ´ƒÿ¸¡zÿ£‹oÿŒubÿv_TÿcLGÿT?<ÿK55ÿF01ÿC./ÿC-.ÿC-.ÿC..ÿC./ÿC./ÿD//ÿD//ÿC//ÿC//ÿC..ÿC..ÿD./ÿD./ÿD.0ÿD.0ÿE/0ÿE/0ÿE./ÿE..ÿC,,ÿA*+ÿ@(+ÿ@(+ÿ@(,ÿ@(,ÿ@(,ÿ?'+ÿ>(+ÿ>)+ÿ?)+ÿ?)+ÿ?),ÿ?),ÿ?)-ÿ?)-ÿ>(-ÿ>(,ÿ?(,ÿ?),ÿ@),ÿA),ÿA),ÿA),ÿ@)-ÿ@)-ÿA)-ÿA)-ÿA(-ÿA(,ÿA),ÿA),ÿA),ÿA),ÿA)-ÿA)-ÿA)-ÿA)-ÿA*-ÿA*-ÿA*-ÿB+-ÿB+-ÿB+-ÿB*.ÿB*.ÿB*.ÿB*.ÿA*.ÿB*.ÿC*.ÿC*.ÿC+.ÿB+.ÿF/2ÿ[@DÿF/2ÿC+/ÿC+/áC+/C+/<')<')<()á<()ÿD01ÿlTXÿE/2ÿ=(*ÿ>)*ÿ>)+ÿ>)+ÿ?*+ÿ?*+ÿ?*+ÿ?*,ÿ@*,ÿ@+-ÿ@+-ÿ@+.ÿA+.ÿA+.ÿA,.ÿA,.ÿB,/ÿB,/ÿB,/ÿC-/ÿC./ÿC./ÿC./ÿC./ÿC./ÿC-/ÿD-/ÿD-/ÿD.0ÿD.1ÿD.1ÿD.1ÿE.1ÿF.1ÿF.1ÿF.1ÿF.1ÿF.1ÿF.1ÿF.1ÿE.1ÿE.0ÿC-/ÿ@+-ÿ>)+ÿ@&(ÿ<(*ÿ@/0ÿˆyvÿ³¹’ÿ™²fÿ”®]ÿ´Å�ÿ«½‡ÿ“©cÿ•©bÿ—©aÿ™©_ÿš©]ÿœ¨\ÿž§ZÿŸ§Yÿ ¦Wÿ¢¦Vÿ¤¦Sÿªª[ÿÇÉÿ®¤Dÿ«ž7ÿ­ž6ÿ®�5ÿ¯�4ÿ²�2ÿ³œ0ÿ®–.ÿ¤‹-ÿ©˜]ÿ•�FÿŠo$ÿ�w,ÿ¦|1ÿ²…<ÿÅ“MÿØ¢]ÿä¬fÿè±iÿè²hÿç´hÿçµhÿç·hÿç¹hÿç»hÿç½hÿç¾hÿçÀhÿçÂhÿçÄhÿçÅhÿçÇiÿçÉiÿçËiÿçÍiÿçÏiÿçÐiÿçÑiÿçÒiÿçÑiÿèÑqÿéÑyÿæÅeÿåÂdÿåÀcÿå¿cÿå¿dÿåÀeÿåÀfÿçÆlÿêÒyÿëØ�ÿëØ„ÿê׆ÿèÕ‡ÿãЇÿÜɆÿ×Çžÿ¿®�ÿ¬˜vÿœˆoÿ’}oÿ�k^ÿoXPÿ`IFÿT><ÿL55ÿG01ÿE./ÿD-.ÿC-.ÿC-/ÿC./ÿD./ÿD./ÿD./ÿC-.ÿC..ÿC./ÿC./ÿC./ÿD//ÿC//ÿC./ÿC..ÿC..ÿC..ÿC./ÿD.0ÿD.0ÿE/0ÿE/0ÿE//ÿE//ÿD..ÿC,-ÿA*,ÿ@(+ÿ@(,ÿ@(,ÿ@'+ÿ?'+ÿ?(+ÿ?(+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ?),ÿ>),ÿ>(,ÿ>(,ÿ?(,ÿ?(,ÿ@),ÿ@),ÿ@),ÿ@),ÿ?)-ÿ@)-ÿ@)-ÿ@)-ÿA(,ÿ@(,ÿA(,ÿA),ÿA),ÿA),ÿA)-ÿA)-ÿA)-ÿA)-ÿA*-ÿA*-ÿA*-ÿA*-ÿA+-ÿB+.ÿA*.ÿA*.ÿA*.ÿA*.ÿ@*.ÿA*.ÿB*.ÿB*.ÿB*.ÿF.2ÿ[@CÿF/2ÿB+.ÿC+.áC+.C+.<()<()<()á<()ÿE/1ÿmTXÿE02ÿ=)*ÿ>)+ÿ>)+ÿ?*+ÿ>*+ÿ>*,ÿ?*,ÿ@+,ÿ@+,ÿ@+-ÿA+.ÿA+.ÿA,.ÿA,.ÿB,/ÿB,/ÿB,/ÿB,/ÿC-/ÿC-/ÿC./ÿC./ÿC-/ÿD-/ÿD-/ÿD.0ÿD.0ÿD.0ÿD.0ÿE.0ÿE.1ÿE.1ÿE.1ÿF.1ÿF.2ÿF/2ÿF/2ÿG/2ÿG/2ÿG/2ÿF.1ÿE.0ÿC-/ÿ@+-ÿ?(*ÿ?'(ÿ;)*ÿgWXÿ°®—ÿ¢¶rÿ’­[ÿ«¾~ÿµÅ”ÿ•«fÿ•©cÿ–©aÿ˜©`ÿš©^ÿœ¨\ÿ�¨ZÿŸ§Yÿ ¦Xÿ¢¦Vÿ¤¦Tÿ¥¥Rÿ§¤Pÿ¿»|ÿ½³cÿ¬�5ÿ®�6ÿ¯�4ÿ±�2ÿ°™0ÿ¤�,ÿš‚(ÿ£�Nÿœ‹VÿŠo&ÿ¢{1ÿ¼‰CÿÓ™Vÿã¥cÿè«hÿè­iÿç®hÿç¯hÿç±hÿç³hÿçµhÿç·hÿç¸hÿçºhÿç¼hÿç¾hÿç¿hÿçÁhÿçÃhÿçÅhÿçÆhÿçÉlÿçÉiÿæÉhÿæÈiÿæÇjÿæÅlÿæÄoÿçÄrÿéÇ}ÿïסÿçÃpÿçÀkÿçÁoÿçÂsÿåÁwÿá¿zÿܺ{ÿÔ³{ÿÊ­|ÿ¿©ÿ±�yÿ¤�qÿ”hÿ…p`ÿvaWÿiSPÿ]FDÿU>=ÿN88ÿH33ÿE/0ÿC-.ÿC--ÿC--ÿC-.ÿD..ÿD..ÿE-.ÿE-.ÿD./ÿD./ÿD./ÿD./ÿD./ÿD-/ÿC-.ÿC-.ÿC./ÿC./ÿC./ÿC//ÿC//ÿC..ÿC..ÿC..ÿC..ÿC..ÿC./ÿD/0ÿE/0ÿE./ÿE//ÿE//ÿD//ÿD./ÿC-.ÿB+-ÿA),ÿ@',ÿ@'+ÿ?'+ÿ?'+ÿ?(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ?),ÿ>(,ÿ>(+ÿ>(+ÿ?(+ÿ?(+ÿ@)+ÿ@),ÿ@),ÿ?),ÿ?)-ÿ?)-ÿ@)-ÿ@(,ÿ@(,ÿ@(,ÿ@(,ÿ@),ÿ@),ÿ@),ÿ@)-ÿ@)-ÿ@)-ÿ@*-ÿ@*-ÿ@*-ÿ@*-ÿ@*-ÿA+-ÿA*-ÿA*.ÿA*.ÿA*.ÿ@*.ÿ@*.ÿB*-ÿB*-ÿB*-ÿF.0ÿ[@BÿF.1ÿB*.ÿB*.áB*.B*.<()<()=()á<()ÿE/2ÿnUYÿF02ÿ>)*ÿ?*+ÿ?*+ÿ>*+ÿ>*,ÿ?*,ÿ?+,ÿ@+,ÿA+-ÿA+-ÿA+-ÿA,.ÿB,/ÿB,/ÿB,/ÿB,/ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿD-/ÿD.0ÿD.0ÿD.0ÿE.0ÿE.0ÿE.0ÿE.0ÿE.0ÿE/1ÿE/2ÿF/2ÿF/2ÿF/2ÿG/2ÿG/2ÿG/2ÿG/2ÿG/2ÿF.1ÿD-1ÿB,/ÿ?*,ÿ@')ÿ=')ÿH79ÿ¢˜�ÿ¾Ê–ÿ–°_ÿ ¶nÿ»Ê›ÿš¯nÿ”©bÿ–©bÿ˜©`ÿ™©^ÿ›¨]ÿ�¨[ÿŸ§Yÿ ¦Xÿ¡¦Vÿ£¦Uÿ¥¥Sÿ§¥Qÿ¨¤Nÿ²¬_ÿÉÁ�ÿ¯Ÿ:ÿ¯�4ÿ°�2ÿª•/ÿœ†+ÿ–~'ÿžŠ>ÿ£“aÿ•w3ÿ¹‡DÿÚš\ÿç£fÿé§hÿè¨gÿèªhÿç«hÿç­hÿç¯hÿç±hÿç²hÿç´hÿç¶hÿç¸hÿç¹hÿç»hÿç½hÿç¾gÿçÀeÿæÁdÿæÁbÿéË{ÿìÑ�ÿçÂqÿçÃtÿèÄyÿéÅ~ÿêÆƒÿéLJÿçÅ‹ÿâÂŒÿ߯£ÿÒ¶�ÿäzÿ´—vÿ¦‹qÿ•|jÿ†obÿxbZÿlVQÿaLJÿYCBÿQ;;ÿL66ÿI33ÿF11ÿD//ÿC..ÿC--ÿD--ÿD..ÿD//ÿD//ÿD./ÿD..ÿD..ÿD..ÿD..ÿD..ÿD..ÿD-.ÿE-.ÿD..ÿD./ÿD./ÿD./ÿD./ÿC-/ÿC-.ÿC-.ÿC-/ÿC./ÿC./ÿC//ÿC./ÿC..ÿC..ÿC..ÿC..ÿB..ÿC./ÿD//ÿD./ÿE./ÿE//ÿE//ÿD//ÿD/0ÿE/0ÿD./ÿC+.ÿA),ÿ@'+ÿ?'+ÿ?'+ÿ?(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ?(,ÿ?'+ÿ?'+ÿ?'+ÿ?'+ÿ@(+ÿ@)+ÿ@)+ÿ@)+ÿ?)+ÿ?),ÿ?),ÿ@(,ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@),ÿ@)+ÿ?),ÿ@),ÿ@),ÿ@),ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿA*-ÿA*,ÿA*-ÿA*-ÿ@*-ÿ@*-ÿA*-ÿA)-ÿB)-ÿF-0ÿZ@BÿF.1ÿB*-ÿB*.áB*.B*.=(*<(*=(*á=(*ÿF/2ÿoTYÿF03ÿ>)+ÿ?*+ÿ>*,ÿ?*,ÿ?+,ÿ?+,ÿ?+-ÿ@+-ÿ@+-ÿA,-ÿB,.ÿB,.ÿB,/ÿB,/ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC.0ÿC.0ÿD.0ÿE.0ÿE.0ÿE.0ÿE.1ÿE/1ÿF/1ÿF/1ÿF/1ÿF/1ÿF/2ÿF/2ÿF/2ÿG/3ÿG/3ÿH/3ÿH03ÿG/3ÿF/2ÿD.1ÿB,/ÿ?),ÿ@')ÿ<)+ÿsefÿÊ˰ÿ¾ÕŠÿ­Ävÿ»Ê™ÿ¢µyÿ”¨bÿ–©bÿ—©`ÿ™©_ÿ›©]ÿ�¨[ÿž§Yÿ §Xÿ¡¦Wÿ£¦Uÿ¥¦Sÿ§¥Rÿ¨¤Pÿ©¤Nÿ«£NÿÇ¿�ÿº«Rÿ®›1ÿ¤�.ÿ—‚*ÿ•~(ÿš„1ÿ°›hÿ¹ŒTÿÖ•Zÿè gÿé¢hÿè¤gÿè¥gÿè§gÿè©gÿç«hÿç¬hÿç®hÿç°hÿç²hÿç´hÿçµgÿç·gÿæ¹eÿæ»cÿæ½bÿæ¾cÿæÀgÿçÂlÿêÉ|ÿñÚ¬ÿëÌ•ÿæÅŒÿàÀ�ÿÖ¸Žÿɬ‹ÿ¹ž„ÿ©�|ÿ—~qÿ…nfÿu_[ÿgRPÿ\GFÿS>?ÿM99ÿI45ÿE12ÿD00ÿC//ÿC//ÿC//ÿD..ÿD..ÿE/.ÿE//ÿE//ÿD0/ÿD//ÿD..ÿE..ÿE./ÿD//ÿD//ÿD./ÿD..ÿD..ÿC..ÿD..ÿD..ÿD..ÿD-.ÿD-.ÿD..ÿD..ÿD./ÿE./ÿD./ÿC-.ÿC-.ÿC-.ÿC-/ÿC-/ÿC./ÿC//ÿC..ÿC..ÿC..ÿC..ÿC..ÿB..ÿC./ÿD//ÿD..ÿD..ÿD//ÿD//ÿD//ÿD/0ÿD/0ÿE/0ÿE.0ÿC,.ÿA)-ÿ?(,ÿ?'+ÿ?(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ?'+ÿ?'+ÿ?'+ÿ?'+ÿ@'+ÿ@'+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(,ÿ@(,ÿ@'+ÿ@'+ÿ@'+ÿ@'+ÿ@(+ÿ@(+ÿ@)+ÿ@)+ÿ@(,ÿ@),ÿ@),ÿ@*,ÿ@),ÿ@),ÿ@),ÿ@),ÿA),ÿA),ÿA)-ÿA)-ÿ@)-ÿA)-ÿA)-ÿA)-ÿF-0ÿZ?BÿF-0ÿB*-ÿB*.áB*.B*.<(*<(*<(*á=(*ÿF/2ÿoUZÿG03ÿ>)+ÿ>*,ÿ?*,ÿ?+,ÿ?+,ÿ@+-ÿ@+-ÿ@,-ÿA,-ÿA,.ÿB,.ÿB,.ÿC-.ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC.0ÿC-0ÿD-0ÿD-0ÿD-0ÿE.1ÿE/1ÿF/1ÿF/1ÿF/1ÿF/1ÿF/1ÿF/2ÿG/2ÿG/2ÿG03ÿG03ÿG03ÿG03ÿG03ÿG03ÿF03ÿF/2ÿD-1ÿ@+.ÿ@)+ÿ?&)ÿH79ÿ£™•ÿÖÞ¼ÿ¼Ó„ÿÎߥÿ½Ï˜ÿ–«eÿ•©bÿ—©aÿ™©_ÿš©]ÿœ¨\ÿž§ZÿŸ§Yÿ¡¦Wÿ£¦Vÿ¤¦Tÿ¦¥Rÿ¨¤Pÿ©¤Nÿ«£Mÿ«¢Jÿ»±fÿŹsÿŸ‹-ÿ”€)ÿ”(ÿ™€*ÿº“UÿÜ�nÿç›fÿéžhÿèŸgÿè¡gÿè£gÿè¥gÿè¦gÿè¨gÿçªhÿç¬hÿç®hÿæ¯gÿã®cÿá³lÿèÀvÿæ¼eÿçÁkÿèÄrÿêÆzÿèǃÿäĈÿܽ‹ÿÓ»žÿÀ©˜ÿ¨�~ÿ•}sÿ‚kfÿqZXÿbLLÿWABÿP9;ÿK45ÿH22ÿF00ÿE//ÿE//ÿD//ÿD//ÿE//ÿE0/ÿD00ÿD00ÿD00ÿD00ÿD/0ÿE//ÿE//ÿE/.ÿE//ÿE//ÿD//ÿD//ÿD/.ÿE..ÿE..ÿD//ÿD//ÿD..ÿD..ÿD..ÿC..ÿD..ÿD..ÿD-.ÿD-.ÿC-.ÿD..ÿD..ÿD..ÿE./ÿD-/ÿC-.ÿC-.ÿC-.ÿC-.ÿC-/ÿC-/ÿC./ÿC..ÿC..ÿC..ÿC..ÿB..ÿB..ÿC//ÿD./ÿD..ÿD..ÿD/.ÿC/.ÿC//ÿD/0ÿD/0ÿE/0ÿE.0ÿD.0ÿC,/ÿA*.ÿ@),ÿ?(,ÿ?(+ÿ@(+ÿ@(+ÿ?(+ÿ?'+ÿ?'+ÿ?'+ÿ?'+ÿ@'+ÿ@'+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(,ÿ@',ÿ@'+ÿ@'+ÿ@'+ÿ@'+ÿ@'+ÿ@(+ÿ@(+ÿ@(+ÿ@(,ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿA),ÿA),ÿA)-ÿ@)-ÿ@)-ÿA)-ÿA)-ÿE-0ÿZ?BÿF-0ÿB)-ÿC*-áC+-C+-=(*=(*=(*á=(*ÿF03ÿoUZÿF03ÿ>)+ÿ?*,ÿ?+,ÿ?+-ÿ@+-ÿ@+-ÿ@,-ÿA,.ÿA,.ÿA,.ÿB-.ÿC-/ÿC-/ÿC-/ÿC-/ÿC-/ÿC.0ÿC-0ÿD-0ÿD-0ÿD-0ÿD-1ÿD.1ÿE.1ÿF/1ÿF/1ÿF/1ÿF/2ÿG/2ÿG02ÿG02ÿG02ÿG02ÿG02ÿG03ÿG03ÿH04ÿH04ÿH04ÿG03ÿF/2ÿD-1ÿ@+.ÿA(+ÿ>&)ÿj[]ÿ··¤ÿÄÒ©ÿÑà«ÿÏà­ÿ»ÒŠÿ«Àvÿ˜«bÿ˜¨^ÿš¨]ÿœ¨\ÿž§ZÿŸ§Yÿ ¦Wÿ¢¦Vÿ¤¦Tÿ¦¥Rÿ¨¥Qÿ©¤Oÿª£Nÿ¬£Lÿ®¢Jÿ®¡Lÿ³©sÿ™‡7ÿ”'ÿ¢‚1ÿÉ�Oÿå—fÿé™gÿè›gÿè�gÿèŸgÿè gÿè¢gÿè¤gÿè¦gÿè¨gÿç©fÿâ©dÿÛ¨_ÿÔ¨^ÿϨaÿÓ²wÿêÓ¨ÿçÈŒÿÝÀŽÿд�ÿ½£‡ÿ¦Ž|ÿŽwnÿzd`ÿhSSÿZEFÿQ;=ÿK67ÿH23ÿG11ÿF01ÿF00ÿG00ÿG00ÿG00ÿG10ÿF10ÿF00ÿE00ÿE00ÿE00ÿE00ÿE0/ÿD00ÿD00ÿD00ÿD00ÿD/0ÿD//ÿE//ÿE//ÿE/.ÿD//ÿD//ÿD//ÿD//ÿD..ÿD..ÿD//ÿD//ÿD..ÿD..ÿC..ÿC..ÿD..ÿD..ÿD-.ÿD--ÿC-.ÿC..ÿD..ÿD..ÿE..ÿD-.ÿD-.ÿD-.ÿC-.ÿC-.ÿC-/ÿB-/ÿC-/ÿC-.ÿC..ÿC..ÿC..ÿB..ÿB..ÿC//ÿD..ÿD..ÿD..ÿC/.ÿC/.ÿC//ÿC//ÿC//ÿD./ÿD./ÿD.0ÿD.0ÿC-/ÿB+.ÿ@*-ÿ@),ÿ@),ÿ?),ÿ?(+ÿ?(+ÿ?'+ÿ?'+ÿ@'+ÿ@'+ÿ@'+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@'+ÿ@'+ÿ@'+ÿ@'+ÿ@'+ÿ@'+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@),ÿ@(,ÿA),ÿA),ÿA),ÿ@)-ÿA*-ÿA)-ÿF-0ÿ[?BÿG-0ÿC*-ÿC*-áC*-C*-=(*=(*=(+á=(+ÿF03ÿoV[ÿG04ÿ>),ÿ?*,ÿ@*-ÿ@+-ÿ@,-ÿA,-ÿA,.ÿA,.ÿA,.ÿB-.ÿB-/ÿB-/ÿC-.ÿC-.ÿC./ÿC-0ÿD-0ÿD-0ÿD-0ÿD.1ÿE.1ÿE.1ÿE.1ÿE.1ÿE.2ÿF/2ÿG02ÿG02ÿG02ÿG02ÿG02ÿH03ÿH03ÿH03ÿG03ÿG03ÿG14ÿG14ÿG14ÿG03ÿF/2ÿD.1ÿA+.ÿA(*ÿD-0ÿ’‡„ÿµ¾šÿ®Á�ÿáéÍÿÔàµÿÎܧÿËÚŸÿ¹Çˆÿ¥³pÿ¢®gÿ «`ÿ ¨[ÿ ¦Wÿ¡¥Uÿ£¥Sÿ¤¥Qÿ§¤Pÿ¨¤Nÿª£Nÿ«£Lÿ®¢Kÿ¬ŸHÿ›�>ÿ¡”[ÿ¤”Tÿ¯„;ÿÚ�\ÿé•hÿè—gÿè™gÿèšgÿèœgÿèžgÿè gÿè¡gÿè£fÿå¤dÿÝ¥aÿÕ§bÿÑ«jÿѯvÿв‚ÿË®Šÿ½¢Šÿ¯šŽÿ–wÿ|fcÿhRSÿ[EEÿQ;;ÿK65ÿI33ÿH22ÿH22ÿH22ÿH23ÿH22ÿH22ÿH22ÿH12ÿG11ÿG11ÿG01ÿG00ÿG10ÿF10ÿF00ÿE00ÿE00ÿE00ÿE0/ÿE0/ÿD00ÿD00ÿD00ÿD00ÿD//ÿD//ÿE//ÿE//ÿE/.ÿD//ÿD./ÿD//ÿD//ÿD//ÿD..ÿD//ÿD./ÿD..ÿD..ÿC..ÿC..ÿC..ÿD..ÿD--ÿC--ÿC-.ÿC..ÿC..ÿD..ÿD-.ÿD--ÿD--ÿD-.ÿD-.ÿC-.ÿB-/ÿB-/ÿC-.ÿC-.ÿC-.ÿC-.ÿB..ÿB..ÿC//ÿC./ÿD..ÿD..ÿD..ÿC/.ÿC//ÿC//ÿC//ÿC//ÿD..ÿC..ÿC./ÿC./ÿD.0ÿC./ÿB-.ÿA+-ÿ@),ÿ?(,ÿ?(+ÿ?(+ÿ?(,ÿ?(,ÿ@(,ÿ@(,ÿA(,ÿ@(,ÿ@),ÿ@),ÿ@(,ÿ@(+ÿ@'+ÿ@(,ÿ@(+ÿA(,ÿA',ÿ@(,ÿ@(,ÿ@(+ÿ@),ÿ@),ÿ@*,ÿA*,ÿA*,ÿA*,ÿA*,ÿA),ÿA),ÿB*,ÿB*,ÿA*,ÿA*-ÿB*-ÿF.0ÿZ?BÿF.0ÿB*-ÿC*-áB*-C*->)*=)*>)*á=)*ÿF04ÿpV[ÿG14ÿ?*,ÿ@*-ÿ@*-ÿ@+-ÿA,.ÿA,.ÿA,.ÿB-.ÿB-/ÿB-/ÿB-.ÿC-.ÿC./ÿC./ÿD-/ÿD-/ÿD-0ÿD.1ÿE.1ÿE.1ÿE.1ÿE.1ÿF.2ÿF/2ÿF/2ÿF/2ÿG02ÿG02ÿH03ÿH03ÿG03ÿG13ÿG13ÿG13ÿG13ÿH13ÿH14ÿH15ÿG15ÿG04ÿF/3ÿD-1ÿA+.ÿA&)ÿVBEÿ¯ªŸÿ®¾ŽÿÄÓ¨ÿÜäÃÿÏÑ¥ÿÎΟÿÒÒ¥ÿÖÕ¨ÿÏΣÿÄØÿ•ÿÂÂ’ÿ¿À‹ÿ¼½ƒÿ¸¸yÿµ³nÿ²¯dÿ°ª[ÿ®§Tÿ®¤Nÿ­¡Iÿ��@ÿ’ƒ9ÿšˆDÿÇ—iÿã�cÿé“hÿè”gÿè–gÿè˜gÿèšgÿèœgÿè�gÿèŸfÿã¢eÿݨfÿ×®oÿÓ²}ÿϲŠÿéŽÿ¯–†ÿ“|vÿxbbÿbLNÿQ;=ÿI24ÿE.1ÿD-/ÿE-/ÿG01ÿI32ÿJ43ÿJ43ÿI33ÿI33ÿH33ÿH23ÿH22ÿH22ÿH22ÿH12ÿG11ÿG11ÿG01ÿG00ÿG10ÿF10ÿF00ÿE00ÿE00ÿE00ÿE//ÿD0/ÿD00ÿD00ÿD00ÿD00ÿD//ÿD//ÿD//ÿE//ÿE//ÿD/.ÿD./ÿD./ÿD//ÿD//ÿD//ÿD./ÿD..ÿD..ÿD..ÿC..ÿC..ÿC..ÿD-.ÿD--ÿC--ÿC-.ÿC..ÿC..ÿC..ÿC--ÿD--ÿD--ÿD--ÿD-.ÿD-.ÿC-/ÿC,/ÿC-.ÿC-.ÿC-.ÿC-.ÿB-.ÿB..ÿC./ÿC..ÿD..ÿD..ÿC..ÿC/.ÿC//ÿC//ÿC//ÿC./ÿD..ÿC..ÿC./ÿC./ÿC./ÿC./ÿC./ÿB..ÿA+-ÿ?),ÿ?(+ÿ?(+ÿ?(,ÿ@(,ÿ@(,ÿ@(,ÿA(,ÿ@),ÿ@),ÿ@),ÿ@),ÿ@(+ÿ@(,ÿ@(,ÿA(,ÿA(,ÿA(,ÿ@(,ÿ@),ÿ@),ÿ@),ÿA*,ÿA*,ÿA*,ÿA*,ÿA*,ÿA),ÿA),ÿA),ÿA*,ÿA*,ÿA*,ÿA*,ÿE-0ÿY?AÿE.0ÿA*,ÿB*-áB*-B*->)*>)*>)*á>)*ÿG14ÿpW\ÿF14ÿ?*-ÿ@*-ÿ@+-ÿA+.ÿA+.ÿA,.ÿB-.ÿB-/ÿB-/ÿC-.ÿC..ÿC./ÿC-/ÿC-/ÿD-/ÿD.0ÿE.0ÿE.1ÿE.1ÿE.2ÿF.2ÿF/2ÿF/2ÿF/2ÿF/2ÿG/3ÿG/3ÿG03ÿG13ÿG13ÿG13ÿH13ÿH14ÿH14ÿH14ÿH14ÿH14ÿH14ÿH15ÿG14ÿF03ÿC.1ÿB+.ÿA')ÿr`bÿ»¼¦ÿÁϦÿÊܧÿÌܦÿÒÔ¨ÿÃÁ†ÿÅÁ…ÿÇÀ„ÿÈÀƒÿ½²vÿ­¡hÿ°£jÿµ¨qÿ»­xÿÀ²ÿÅ·†ÿÈ»‹ÿ˾�ÿÌÀ�ÿË¿‰ÿ¹®wÿ¤˜dÿ£’XÿÊUÿæŽfÿé�gÿè’gÿè”gÿè–gÿè—gÿè™gÿç›fÿã¡hÿÞ«pÿÚ¶€ÿÔ·�ÿê‘ÿ§�…ÿˆqoÿkTVÿV?BÿK36ÿF.1ÿE-0ÿE.0ÿE.0ÿE.0ÿE.1ÿE.0ÿE.0ÿF/0ÿH12ÿI33ÿJ43ÿI33ÿI33ÿH33ÿH23ÿH22ÿH22ÿH22ÿH12ÿG11ÿG11ÿG01ÿG00ÿG10ÿF10ÿF00ÿE00ÿE00ÿE00ÿE//ÿD0/ÿD00ÿD00ÿD00ÿD/0ÿD//ÿD//ÿD//ÿE//ÿE//ÿD..ÿD./ÿD./ÿD./ÿD//ÿD//ÿD./ÿD..ÿD..ÿC..ÿC..ÿC..ÿC..ÿD--ÿD--ÿC--ÿC-.ÿC-.ÿC..ÿC..ÿC--ÿC--ÿD--ÿD--ÿD--ÿD-.ÿC-/ÿC,.ÿC,.ÿC-.ÿC-.ÿB-.ÿB-.ÿC./ÿC./ÿC-.ÿD..ÿD..ÿC..ÿC//ÿC//ÿC//ÿC//ÿC..ÿC..ÿC..ÿC./ÿC./ÿC./ÿC./ÿC//ÿC//ÿB..ÿA+,ÿ?)+ÿ>(+ÿ>(+ÿ?(+ÿ?(+ÿ@(,ÿ@(,ÿ@),ÿ?),ÿ@),ÿ@(+ÿ@(+ÿ@(,ÿ@(,ÿA(,ÿA(,ÿ@(,ÿ@(,ÿ@),ÿ@),ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@*,ÿ@),ÿ@)+ÿ@)+ÿ@*+ÿ@*,ÿ@*,ÿE-0ÿY?BÿE-0ÿA*-ÿA*-áA*-A*->)+>)+>)+á>)+ÿF13ÿpX\ÿG25ÿ?*-ÿ@+-ÿA+.ÿA+.ÿA+.ÿB,/ÿB-/ÿB-.ÿC-.ÿC./ÿC-/ÿC-/ÿC-/ÿC-0ÿD.0ÿE.0ÿE.0ÿE.1ÿF.1ÿF/2ÿF/2ÿF/2ÿG/2ÿG/3ÿG/3ÿG03ÿG03ÿG03ÿH03ÿH14ÿH14ÿH14ÿH14ÿH24ÿI24ÿI24ÿI24ÿI24ÿH24ÿH14ÿF03ÿC.1ÿB+-ÿE*-ÿ��ÿÌиÿÏÞ±ÿÀÕ‘ÿÃÖ“ÿØÝ´ÿÈÄŒÿÆÁ„ÿÈÀƒÿÊ¿‚ÿË¿ÿ½¯oÿ«›\ÿª™Xÿ«™Vÿ­˜Uÿ¯˜Tÿ±˜Tÿ´™Uÿ¸œYÿ¶›[ÿ¢ŠVÿ¥‹[ÿΑlÿè�hÿèŽgÿè�gÿè‘gÿè“gÿè•gÿè–fÿåžkÿà®yÿÚ¹Œÿ˱•ÿ¯˜‹ÿŠtqÿhRTÿS<@ÿI14ÿG.1ÿF.1ÿG/2ÿG/1ÿF.1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.1ÿE.0ÿE.0ÿF/0ÿH11ÿI33ÿI33ÿI33ÿH33ÿH23ÿH22ÿH22ÿH22ÿG12ÿG11ÿG11ÿG01ÿG00ÿF10ÿF00ÿF00ÿE00ÿE00ÿE/0ÿE//ÿD0/ÿD00ÿD00ÿD00ÿD/0ÿD//ÿD//ÿD//ÿD//ÿE//ÿE..ÿD..ÿD./ÿD./ÿC//ÿD//ÿD./ÿD..ÿD..ÿC..ÿC..ÿC..ÿC..ÿD--ÿC--ÿC--ÿC-.ÿC-.ÿC..ÿB-.ÿB--ÿC--ÿC--ÿD--ÿD--ÿC--ÿC,.ÿD,.ÿD,.ÿD-.ÿC-.ÿB-.ÿB-.ÿC./ÿC-.ÿC-.ÿC-.ÿC-.ÿC..ÿC./ÿC//ÿC//ÿC./ÿC..ÿC..ÿC..ÿC./ÿC./ÿC./ÿC./ÿC./ÿB//ÿC..ÿC..ÿA,-ÿ@*+ÿ?)+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?)+ÿ?(+ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ@(+ÿ@(+ÿ?(+ÿ?(+ÿ?(+ÿ?*+ÿ?*,ÿ?*,ÿ@*,ÿ@*,ÿ@*,ÿ@),ÿ@),ÿ@),ÿ@),ÿ?),ÿ@*,ÿE-0ÿY?AÿE-0ÿA*-ÿA*-áA*-A*-?)+?)+?)+á>)+ÿG24ÿqX\ÿG25ÿ?+-ÿ@+.ÿ@+.ÿB,.ÿB,/ÿB,/ÿC,.ÿC-.ÿC./ÿC-/ÿC-/ÿC-0ÿC.0ÿD.0ÿD.0ÿD.0ÿE.1ÿF/1ÿF/1ÿF/2ÿG/2ÿG/3ÿG/3ÿG03ÿG03ÿH03ÿG04ÿG04ÿG04ÿH14ÿH24ÿI24ÿI24ÿI25ÿI25ÿI25ÿI25ÿI25ÿI25ÿH14ÿF02ÿC.0ÿA*-ÿN47ÿ­¡žÿÙáÃÿÂ×—ÿÀÔŽÿÁÓŒÿÓݪÿÒΞÿÇÀƒÿÉÀ‚ÿË¿€ÿÌ¿ÿÍ¿}ÿÀ¯mÿ®œZÿ­™Wÿ¯™Uÿ±˜Tÿ²˜Rÿ´—Qÿµ—Oÿ®�Jÿ™|@ÿ¾€Pÿæ‰dÿè‹fÿè�gÿè�gÿè‘gÿè’fÿç™kÿã¬}ÿÚ¹’ÿĬ–ÿ�ˆ�ÿt^_ÿW@CÿJ25ÿG/2ÿG/2ÿH03ÿH03ÿH/2ÿH/2ÿG/2ÿG/2ÿG.1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.0ÿE.1ÿE.0ÿE.0ÿE.0ÿF/0ÿH11ÿI23ÿI33ÿH33ÿH23ÿH22ÿH22ÿH22ÿG11ÿG11ÿG11ÿG00ÿG00ÿF10ÿF00ÿF00ÿE00ÿE00ÿE/0ÿE//ÿD0/ÿD00ÿD00ÿD00ÿD//ÿD//ÿD//ÿD//ÿD//ÿD//ÿE..ÿE..ÿD..ÿD./ÿC./ÿD./ÿD./ÿD//ÿD..ÿC..ÿC..ÿC..ÿC-.ÿC--ÿC--ÿC--ÿC-.ÿC-.ÿC..ÿB--ÿB--ÿC--ÿC--ÿC--ÿC--ÿC--ÿD,-ÿD,-ÿD,-ÿD-.ÿC-.ÿC-.ÿC./ÿC-/ÿC-.ÿC-.ÿC-.ÿC-.ÿC-/ÿC./ÿC./ÿC./ÿC..ÿB..ÿC..ÿC..ÿC./ÿC./ÿC./ÿC./ÿC./ÿB./ÿC..ÿC..ÿC..ÿC--ÿA+-ÿ@),ÿ?(+ÿ>(+ÿ?(+ÿ?(+ÿ?)+ÿ?(*ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ@(+ÿ?(+ÿ?(+ÿ?(+ÿ?)+ÿ?*,ÿ?*,ÿ?*,ÿ@*,ÿ@*,ÿ@),ÿ@),ÿ@),ÿ@),ÿ?),ÿ?),ÿE-/ÿY?@ÿE-0ÿA*-ÿA*-áA*-A*->*+>*+>*+á>*+ÿG24ÿrY]ÿH35ÿ?+-ÿ@+.ÿA,.ÿA,/ÿB,/ÿC,.ÿC-/ÿC-/ÿC-/ÿC-/ÿC.0ÿD.0ÿD.0ÿD.0ÿD.1ÿE/1ÿE/1ÿF/1ÿG/2ÿG/2ÿG02ÿG03ÿG03ÿH04ÿG04ÿG04ÿG04ÿH14ÿH14ÿH15ÿH15ÿI25ÿI25ÿJ25ÿJ25ÿJ24ÿJ34ÿJ34ÿI34ÿH23ÿG02ÿD/1ÿ@*-ÿ\EGÿÇÀ¸ÿÎݪÿ¿Ó�ÿÂÓ�ÿÂÒ‹ÿÊ×–ÿÚÚ¯ÿÊÁ…ÿË¿€ÿÌ¿ÿÍ¿~ÿÏ¿|ÿоzÿ®jÿ°›Wÿ°˜Tÿ±˜Sÿ³—Qÿµ—Pÿ¶—Nÿ²’Kÿ¶‚Mÿã†dÿè‰fÿè‹fÿèŒfÿèŽgÿè�gÿè¢yÿß·”ÿĬ™ÿ—‚}ÿiTVÿP9<ÿH03ÿH02ÿI13ÿI13ÿH04ÿH03ÿH03ÿH03ÿH03ÿH/2ÿG/2ÿG/2ÿG/1ÿF.1ÿF.1ÿF/0ÿE/0ÿE.0ÿE.1ÿE.0ÿE.0ÿE.0ÿE./ÿF/0ÿG12ÿH23ÿH33ÿH23ÿH22ÿH22ÿH12ÿG11ÿG11ÿG11ÿG00ÿG00ÿF10ÿF00ÿE00ÿE00ÿE00ÿE//ÿD//ÿD0/ÿD00ÿD00ÿD00ÿD//ÿE//ÿD//ÿD//ÿD//ÿD./ÿE..ÿE..ÿD..ÿC..ÿC./ÿD./ÿD./ÿD//ÿC//ÿC..ÿC..ÿC..ÿC--ÿC--ÿC--ÿC--ÿC-.ÿC-.ÿB-.ÿB--ÿB--ÿC--ÿC--ÿC--ÿB--ÿC,-ÿC,-ÿD,-ÿD,-ÿD--ÿC--ÿC-.ÿD./ÿD-.ÿD-.ÿC-.ÿC-.ÿC-/ÿC-/ÿC-/ÿC./ÿC-/ÿC-.ÿB-.ÿB-.ÿC-.ÿC./ÿC./ÿC./ÿC./ÿB./ÿB..ÿC..ÿC..ÿC..ÿD..ÿD-.ÿB,-ÿ@*,ÿ>(+ÿ?(+ÿ?(+ÿ?(*ÿ?(*ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?),ÿ?*,ÿ?*,ÿ?*,ÿ@*,ÿ@*,ÿ@),ÿ@),ÿ@),ÿ?),ÿ?),ÿD,/ÿY>AÿE-/ÿA),ÿA)-áA)-A)->*,>*,?*,á>*,ÿG24ÿrY]ÿH35ÿ@+-ÿA,.ÿA,/ÿA,/ÿB,.ÿC-/ÿC-/ÿC-/ÿC-/ÿC.0ÿD.0ÿD.0ÿD.1ÿE/1ÿE/1ÿE/1ÿE/1ÿF/2ÿF02ÿG02ÿH02ÿG03ÿG04ÿG04ÿG14ÿH14ÿH15ÿH15ÿH15ÿH15ÿI15ÿI24ÿJ24ÿJ34ÿJ35ÿJ35ÿJ35ÿJ35ÿJ25ÿI14ÿG03ÿD.1ÿA),ÿnVYÿÏ̹ÿÆØ™ÿÁÓŒÿÃÓŒÿÄÒŠÿÆÒ‰ÿÙÝ­ÿÒÈ’ÿ˾~ÿÍ¿~ÿÏ¿|ÿп{ÿÒ¾zÿÓ½xÿÅ­hÿ³šUÿ²—Qÿµ—Pÿ¶—Oÿ·—Mÿ¾“OÿÞ†`ÿé†fÿèˆfÿèŠfÿè‹eÿé‘lÿ볕ÿÒ·¡ÿ ‹…ÿlVXÿO7:ÿH03ÿI13ÿI24ÿI14ÿH13ÿI13ÿI13ÿH14ÿH03ÿH03ÿH03ÿH03ÿH/2ÿG/2ÿG/2ÿG/1ÿF.1ÿF.1ÿF/1ÿE/0ÿE.0ÿE.1ÿE.0ÿE.0ÿE.0ÿE./ÿE./ÿE.0ÿG12ÿH23ÿH23ÿH22ÿH22ÿH12ÿG11ÿG11ÿG11ÿG00ÿG10ÿF10ÿF00ÿE00ÿE00ÿE00ÿE//ÿD//ÿD0/ÿD00ÿD00ÿD/0ÿD//ÿE//ÿE//ÿD//ÿD//ÿD..ÿD..ÿE..ÿE..ÿD..ÿC..ÿD-.ÿD-.ÿD./ÿC//ÿC//ÿC..ÿC-.ÿC--ÿC--ÿC--ÿC--ÿC-.ÿC-.ÿB--ÿB--ÿB--ÿC--ÿC--ÿB--ÿB--ÿC,,ÿC,-ÿC,-ÿC,-ÿC--ÿC--ÿD..ÿD-.ÿD-.ÿD-.ÿC-.ÿC-.ÿC-/ÿC-/ÿC-/ÿC-/ÿC-.ÿB-.ÿB-.ÿB-.ÿC-.ÿC-/ÿC-/ÿC-/ÿB-/ÿB-.ÿB-.ÿB..ÿC..ÿD..ÿD..ÿD./ÿD./ÿB,.ÿ@*-ÿ?),ÿ?(+ÿ?(*ÿ?(*ÿ?(*ÿ?(*ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?),ÿ?),ÿ?*,ÿ?*,ÿ?*,ÿ@),ÿ@),ÿ@(,ÿ@(,ÿ@(,ÿ?(,ÿC+/ÿX=AÿE,/ÿA),ÿA)-áA)-A)-?*,?*,?*,á?*,ÿH35ÿrZ^ÿI35ÿ@+-ÿA,.ÿB,.ÿB,.ÿB-/ÿB-/ÿC-/ÿC-0ÿD.0ÿD.0ÿD.0ÿD.1ÿE/1ÿE/1ÿE/1ÿF/2ÿF/2ÿF02ÿF02ÿG03ÿG03ÿG03ÿG13ÿH14ÿH15ÿH15ÿH15ÿI15ÿI14ÿI24ÿI25ÿI25ÿJ25ÿJ25ÿK25ÿK25ÿK25ÿK25ÿJ25ÿJ14ÿH03ÿD.1ÿA*-ÿ}hjÿÒÓ¸ÿÅÖ“ÿÂÓ‹ÿÄÒ‹ÿÅÒ‰ÿÆÑ†ÿÑØ™ÿÛÔ§ÿÍ¿~ÿο}ÿп{ÿѾzÿÓ½xÿÕ½wÿÖ¼uÿȬeÿ¶™Rÿµ—Oÿ·—Nÿ¸–KÿÇ�Rÿç…eÿè†fÿèˆfÿè‰eÿê’oÿ浚ÿÁ®¥ÿklÿS'+ÿ?'+ÿ?'+ÿ?(+ÿ?(,ÿ?(,ÿ?),ÿ?),ÿ?),ÿ@(,ÿ@(,ÿ@(,ÿ@(,ÿ?(,ÿC+/ÿX'*ÿ>'+ÿ?'+ÿ?'+ÿ?(,ÿ?(,ÿ?(,ÿ?),ÿ?),ÿ@),ÿ@(,ÿ@(,ÿ@(,ÿ?(,ÿD+/ÿX'*ÿ>'+ÿ?'+ÿ?(,ÿ@(,ÿ@(,ÿ@(,ÿ@),ÿ@),ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿD+/ÿX<@ÿD+/ÿ@(+ÿ@(+á@(+@(+?+-?+-?+-á@+-ÿI46ÿt[`ÿJ46ÿA,.ÿB-.ÿB-.ÿB-.ÿB./ÿC./ÿC-0ÿD-1ÿD.1ÿE.1ÿE.1ÿF.2ÿF/2ÿF/2ÿG03ÿF03ÿF03ÿG13ÿG14ÿG14ÿG14ÿH14ÿH24ÿI25ÿJ25ÿJ24ÿJ25ÿJ25ÿJ26ÿK26ÿK26ÿK26ÿK26ÿK26ÿK26ÿK27ÿK37ÿL47ÿL47ÿK36ÿI25ÿF03ÿE/2ÿ™‰ˆÿ×Ú´ÿÅÓ‹ÿÅшÿÈчÿÉÐ…ÿÊЄÿÌЂÿÑÓ‰ÿáÚ«ÿÔÀ~ÿÓ½xÿÕ½vÿ×¼tÿØ»sÿÚ»rÿܺpÿݺoÿÞºmÿѪ]ÿ¾–Jÿº“Hÿׇ\ÿé„gÿé¤�ÿ¶ šÿ`KNÿG/3ÿJ25ÿK36ÿK36ÿK36ÿK35ÿJ25ÿK25ÿK25ÿJ24ÿJ24ÿJ25ÿI24ÿI24ÿI24ÿH14ÿI13ÿI14ÿH14ÿH03ÿH03ÿH03ÿH02ÿH/2ÿG/2ÿG/2ÿF.1ÿF.1ÿF/1ÿE/0ÿE.0ÿE.1ÿE.0ÿE-0ÿE.0ÿE./ÿD-/ÿD-/ÿC-/ÿC,/ÿC,.ÿD-/ÿF/0ÿG01ÿG11ÿF11ÿF00ÿF10ÿF10ÿF00ÿE00ÿE00ÿE/0ÿE//ÿD//ÿD//ÿD//ÿD0/ÿC//ÿD//ÿD//ÿE//ÿE//ÿD./ÿD..ÿD..ÿD..ÿC..ÿC..ÿC-.ÿC--ÿD--ÿD--ÿD..ÿC..ÿC-.ÿC-.ÿB-.ÿB..ÿB..ÿC..ÿC--ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿB--ÿB--ÿC,,ÿC,,ÿC,,ÿC,,ÿB,-ÿB,-ÿC-.ÿC--ÿC--ÿC--ÿB--ÿB--ÿB--ÿB--ÿC-.ÿC,.ÿC,-ÿB--ÿB--ÿB--ÿC--ÿC--ÿD--ÿD--ÿC,.ÿC,-ÿC,-ÿC,-ÿC--ÿD--ÿE--ÿE--ÿD--ÿD-.ÿD-.ÿD-.ÿD,.ÿD,-ÿE,.ÿE-.ÿE--ÿD,,ÿA*+ÿ@(*ÿ?'*ÿ?'+ÿ@(+ÿ@(+ÿ@(+ÿ@(+ÿ@)+ÿ@(+ÿ@(*ÿ@(*ÿ?(+ÿC+.ÿW<@ÿC+.ÿ?(+ÿ?(+á?(+?(+?+-?+-?+-á@+-ÿI46ÿu[`ÿJ47ÿA-.ÿB-.ÿB-.ÿC./ÿC./ÿC-/ÿD-0ÿD.1ÿD.1ÿE.2ÿE.2ÿF/2ÿG/2ÿF/3ÿF/3ÿG03ÿG13ÿG14ÿG14ÿH14ÿH24ÿH25ÿH25ÿI24ÿJ24ÿJ24ÿJ25ÿK25ÿK26ÿK26ÿK26ÿK27ÿK27ÿK37ÿK37ÿK37ÿK37ÿL37ÿL47ÿK37ÿJ26ÿH14ÿF03ÿš‹ŠÿØÛ³ÿÆÒ‰ÿÇчÿÉÐ…ÿÊЄÿÌЃÿÎÐ�ÿÏÐÿÞÛ£ÿÛÉ�ÿÕ¼uÿ×¼uÿØ»tÿÚ»rÿܺpÿݺoÿÞºmÿàºlÿá¹jÿÑ©Zÿ³“Iÿ̈Wÿë‘wÿÑ®£ÿr`bÿE.2ÿH04ÿJ25ÿK36ÿL36ÿK36ÿK36ÿK35ÿK35ÿK25ÿK25ÿK24ÿJ24ÿJ25ÿJ25ÿI24ÿI24ÿI14ÿH13ÿI14ÿH14ÿH03ÿH03ÿH03ÿH02ÿH/2ÿG/2ÿG/1ÿF.1ÿF.1ÿF/0ÿE.0ÿE.1ÿE.0ÿE.0ÿE-0ÿE./ÿE./ÿD-/ÿD-/ÿC-/ÿC,/ÿC,.ÿC,.ÿD,/ÿE./ÿF01ÿF01ÿF00ÿF10ÿF00ÿF00ÿE00ÿE00ÿE//ÿD//ÿD//ÿD//ÿD//ÿD//ÿC//ÿD//ÿD//ÿE//ÿD//ÿD..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC--ÿC--ÿC--ÿC--ÿD-.ÿD..ÿC--ÿB--ÿB-.ÿB-.ÿB-.ÿC..ÿB--ÿB--ÿB,-ÿB--ÿB--ÿB--ÿA--ÿB,,ÿC,,ÿC,,ÿC,,ÿB,,ÿB,-ÿB-.ÿB-.ÿC--ÿC--ÿB--ÿB--ÿB--ÿB--ÿB--ÿC-.ÿC,-ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿB--ÿC--ÿB--ÿB,-ÿB,-ÿB,-ÿC,-ÿC,-ÿD--ÿD--ÿD--ÿD--ÿD--ÿD-.ÿD,-ÿD,-ÿD,-ÿE,-ÿE,-ÿE--ÿD--ÿC,,ÿB*+ÿ@)+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(+ÿ?(*ÿ?(*ÿ?(*ÿC+.ÿW<@ÿD+.ÿ@(+ÿ@(+á@(+@(+@,-@,-@,.á@,-ÿI46ÿu\`ÿJ57ÿA-.ÿB-/ÿC./ÿC./ÿC-/ÿD-0ÿD.0ÿD.0ÿE.1ÿE/2ÿE/2ÿF/3ÿF/3ÿF/3ÿG03ÿG04ÿG14ÿH14ÿH24ÿH25ÿH25ÿI24ÿI24ÿI25ÿJ25ÿJ25ÿK25ÿK25ÿK26ÿK27ÿK37ÿK37ÿK37ÿK37ÿK37ÿL38ÿL38ÿL38ÿL48ÿL47ÿK36ÿI25ÿF14ÿ˜ˆ‡ÿÙÚ´ÿÇÒ‰ÿÉÐ…ÿÊЄÿËЃÿÍÐ�ÿÏÐÿÐÏ}ÿ×Ô�ÿâÕ¥ÿ×½vÿ×»tÿÙ»rÿÛºpÿܺoÿÞºnÿàºlÿáºjÿâ¹iÿÛ¶iÿĦ\ÿÇ�Wÿè§”ÿ¥��ÿK69ÿD.1ÿH04ÿJ26ÿK37ÿL37ÿL36ÿL36ÿK36ÿK36ÿK35ÿK25ÿK25ÿK24ÿJ24ÿJ24ÿJ25ÿI24ÿI24ÿI14ÿH13ÿI13ÿH14ÿH03ÿH03ÿH03ÿH02ÿH/2ÿG/2ÿG/1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿE./ÿE./ÿD-/ÿD-.ÿC-/ÿC,/ÿC,.ÿC,.ÿC+.ÿC,.ÿE./ÿF/0ÿF00ÿE10ÿF00ÿE00ÿE00ÿE00ÿE//ÿD//ÿD//ÿD//ÿD//ÿC/.ÿD//ÿD//ÿD//ÿD//ÿD./ÿD..ÿD..ÿD..ÿC..ÿC..ÿC-.ÿC--ÿC--ÿB--ÿC--ÿC-.ÿD-.ÿC--ÿB--ÿB--ÿB-.ÿB-.ÿC-.ÿB--ÿB--ÿB-.ÿB-.ÿB--ÿA--ÿB,-ÿC,,ÿC,,ÿC,,ÿC,,ÿB,,ÿB,-ÿB-.ÿB,-ÿC--ÿC--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,-ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,-ÿB,-ÿB,-ÿC,-ÿC,-ÿC--ÿC--ÿC--ÿC--ÿC--ÿC,-ÿC,-ÿC,-ÿC,-ÿD,-ÿD,-ÿD--ÿC--ÿC--ÿC--ÿB,.ÿA+-ÿ@),ÿ?(+ÿ?(+ÿ?(+ÿ@(*ÿ@(*ÿ@(*ÿC+-ÿV;?ÿD+.ÿ@(+ÿ@(+á@(+@(+@,.@,.@,.á@,.ÿI47ÿu]`ÿJ56ÿB-.ÿC./ÿC./ÿC-/ÿD.0ÿD.0ÿD.0ÿE.1ÿE/1ÿE/2ÿF/3ÿF/3ÿF03ÿG03ÿG04ÿG04ÿH04ÿH15ÿH25ÿI24ÿI24ÿI24ÿJ25ÿJ25ÿJ25ÿJ25ÿK26ÿK36ÿK36ÿK36ÿK37ÿK37ÿL38ÿL38ÿL38ÿL48ÿL48ÿL48ÿL48ÿL48ÿL47ÿJ26ÿG04ÿ’‚‚ÿÙÚ¶ÿÊÒˆÿÊЄÿËЃÿÍÐ�ÿÏЀÿÐÏ~ÿÑÏ}ÿÔÏ}ÿãÛ¦ÿÜÄÿØ»rÿÛºqÿܺoÿݺnÿߺlÿáºkÿâ¹iÿÞ·iÿÕµkÿÔµjÿÔ§jÿÙ²£ÿ}hiÿA*-ÿE/1ÿH14ÿJ26ÿK26ÿL37ÿL37ÿL36ÿL36ÿK36ÿK36ÿK35ÿK35ÿK25ÿK25ÿJ24ÿJ24ÿJ25ÿI24ÿI24ÿI14ÿH13ÿI13ÿH14ÿH03ÿH03ÿH03ÿH/2ÿG/2ÿG/2ÿG/1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿD-/ÿD-/ÿD-.ÿC,/ÿC,/ÿC,.ÿC+.ÿB+-ÿB+-ÿB,-ÿD-.ÿE0/ÿE00ÿF00ÿE00ÿE00ÿE//ÿE//ÿD//ÿD//ÿD//ÿD//ÿC/.ÿD//ÿD//ÿD//ÿD//ÿD..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC--ÿC--ÿB--ÿB--ÿC--ÿC--ÿC--ÿC--ÿC--ÿC--ÿB--ÿB--ÿB,-ÿB,-ÿB,-ÿB-.ÿB-.ÿB..ÿA-.ÿB--ÿC,,ÿC,,ÿC,,ÿB,,ÿB,,ÿB-.ÿB,.ÿB,-ÿC--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,-ÿB,-ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,,ÿB,-ÿB,-ÿB,-ÿC,-ÿC,-ÿC--ÿC--ÿC--ÿC--ÿC--ÿC,-ÿC,-ÿC,-ÿC,-ÿD,-ÿD,-ÿC--ÿC--ÿC--ÿC..ÿC./ÿC-/ÿB,-ÿA*,ÿ@(+ÿ@'*ÿ@'*ÿ@(*ÿD+-ÿV<>ÿC+.ÿ@(+ÿ@(+á@(+@(+@+.@+.A+.á@,.ÿJ57ÿu]`ÿJ57ÿB-.ÿC./ÿC-/ÿD.0ÿD.0ÿD.0ÿE.1ÿE/1ÿF/1ÿF/2ÿF/2ÿF03ÿF04ÿF04ÿG04ÿH14ÿH15ÿI15ÿI24ÿI24ÿI25ÿJ25ÿJ25ÿJ25ÿK26ÿK36ÿK36ÿK36ÿK36ÿL37ÿL37ÿL38ÿL48ÿL48ÿL48ÿM48ÿM49ÿM49ÿM49ÿM49ÿL38ÿK37ÿG03ÿ†vwÿÙ×¹ÿÌÒŠÿÊЃÿÌЂÿÎЀÿÐÏÿÑÏ}ÿÓÎ|ÿÔÍyÿÞÖ’ÿãЛÿÚºqÿܺoÿݺnÿߺmÿàºkÿâ¹jÿà¸iÿ×¶jÿÕ¶kÿÖ¶kÿÛ¹yÿ̳¢ÿfORÿA)+ÿD.0ÿG03ÿJ25ÿK37ÿK37ÿL37ÿL37ÿL37ÿL36ÿL36ÿK36ÿK36ÿK35ÿK25ÿK25ÿJ24ÿJ24ÿJ25ÿI24ÿI24ÿI14ÿH13ÿI13ÿH14ÿH03ÿH03ÿH03ÿH/2ÿG/2ÿG/2ÿG/1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿD-/ÿD-.ÿC-.ÿC,/ÿC,.ÿC,.ÿC+.ÿB+-ÿB+-ÿA*-ÿB+-ÿC..ÿD//ÿE00ÿE00ÿE00ÿE//ÿD//ÿD//ÿD//ÿD//ÿC..ÿD/.ÿD//ÿD//ÿD//ÿC./ÿD..ÿD..ÿD..ÿC..ÿC..ÿC--ÿC--ÿC--ÿB--ÿB--ÿC--ÿC,-ÿC--ÿB--ÿB--ÿC--ÿC--ÿB,-ÿB,,ÿB,,ÿB,-ÿB,.ÿB-.ÿA-.ÿA-.ÿB--ÿC--ÿC--ÿC,,ÿB,,ÿB--ÿB,-ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,,ÿB,-ÿB,-ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿA--ÿA,,ÿB,,ÿB,-ÿB,-ÿC,-ÿC,-ÿC,-ÿB--ÿC--ÿC--ÿC--ÿC,,ÿC,-ÿC,-ÿC,-ÿC,-ÿC,-ÿC,-ÿC--ÿC--ÿC--ÿC..ÿC./ÿC./ÿD./ÿC-.ÿB*-ÿA(+ÿ@'*ÿD+-ÿV<>ÿC+-ÿ@(*ÿ@(+á@(+@(+A+.A+.A+.áA,.ÿJ56ÿu^aÿJ67ÿA-/ÿC-/ÿD.0ÿD.0ÿD.0ÿE.1ÿE/1ÿF/1ÿF/2ÿF/2ÿF02ÿF03ÿF04ÿG04ÿG15ÿH15ÿI14ÿI14ÿI25ÿJ25ÿJ25ÿJ25ÿJ26ÿK36ÿK36ÿK36ÿK36ÿK37ÿK37ÿL47ÿL47ÿM47ÿM48ÿM49ÿM49ÿM49ÿM49ÿM49ÿN59ÿM59ÿM48ÿK38ÿH04ÿygiÿÖÒºÿÏÔ�ÿÌЂÿÎЀÿÏÐÿÑÏ}ÿÒÎ|ÿÔÎzÿÖÍxÿÙÏ}ÿçÙ¦ÿÞ¾xÿݺnÿߺmÿàºkÿâ¹jÿâ¹iÿÙ¶jÿÕ¶kÿÖ¶lÿÖ¶lÿÛ¿�ÿÆ´¥ÿ]GJÿB(*ÿC-0ÿF/2ÿI14ÿK26ÿK37ÿL37ÿL37ÿL37ÿL37ÿL36ÿL36ÿK36ÿK36ÿK35ÿK25ÿK25ÿK24ÿJ24ÿJ25ÿI24ÿI24ÿI14ÿI13ÿI13ÿH14ÿH03ÿH03ÿH03ÿH/2ÿG/2ÿG/2ÿG.1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿD-0ÿD-/ÿD-/ÿD-/ÿD-.ÿC-.ÿC,.ÿC,.ÿC,.ÿB+-ÿB+-ÿB+-ÿA*,ÿA+,ÿA+,ÿB-.ÿD//ÿE00ÿE/0ÿE//ÿD//ÿD//ÿD//ÿD./ÿC..ÿD/.ÿD//ÿD//ÿC//ÿC..ÿD..ÿD..ÿD..ÿC..ÿC..ÿC--ÿC--ÿB--ÿB--ÿB--ÿC,-ÿC,-ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,,ÿB,,ÿC,,ÿB,,ÿB,-ÿA,.ÿA,.ÿB,-ÿB,-ÿC--ÿC--ÿB--ÿB--ÿB-.ÿB,-ÿB,-ÿB,-ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,,ÿA,,ÿA,,ÿA,-ÿA,-ÿA,-ÿA--ÿB--ÿA--ÿA,-ÿA,,ÿB,,ÿB,-ÿC,-ÿC,-ÿC,-ÿC,-ÿB--ÿB--ÿC--ÿC,-ÿC,,ÿC,,ÿC,-ÿC,-ÿC,-ÿC,-ÿC,-ÿC--ÿC--ÿC..ÿC..ÿC./ÿC./ÿD./ÿE./ÿE,.ÿC+,ÿE-/ÿW<>ÿC+-ÿ?(*ÿ@(*á@(+@(+A,/A,/A,/áA+.ÿJ47ÿv^bÿK67ÿB-/ÿC.0ÿC.0ÿD.0ÿE.1ÿE/1ÿF/1ÿF/2ÿF/2ÿF02ÿF03ÿF03ÿG13ÿG15ÿG15ÿH14ÿI14ÿI25ÿJ25ÿJ25ÿJ26ÿK36ÿK36ÿK36ÿK36ÿK37ÿK37ÿK47ÿK47ÿL47ÿM48ÿM48ÿM48ÿM49ÿN59ÿN59ÿN5:ÿN5:ÿN5:ÿN5:ÿM49ÿL48ÿI05ÿiUYÿÎǵÿÓÖ’ÿÍЀÿÏÐÿÑÏ~ÿÒÎ|ÿÔÎ{ÿÖÍyÿ×ÌxÿØÌuÿäטÿäÊŽÿÞ¹lÿàºlÿáºjÿâ¹iÿÛ·iÿÕµkÿÖ¶kÿÖ¶mÿÖ¶mÿÛ¾�ÿȶ¦ÿ\JMÿA'*ÿC,.ÿD/1ÿH04ÿJ25ÿK36ÿL37ÿL48ÿL37ÿL37ÿL37ÿL37ÿL36ÿK36ÿK36ÿK35ÿK25ÿK25ÿK24ÿJ24ÿJ25ÿI24ÿI24ÿI14ÿH13ÿI13ÿH14ÿH03ÿH03ÿH03ÿH/2ÿG/2ÿG/2ÿF.1ÿF.1ÿF/1ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿD-/ÿD-/ÿD-.ÿC,.ÿC,.ÿC,.ÿC+.ÿB+-ÿB+-ÿA*-ÿA*,ÿ@+,ÿ@*,ÿ@+,ÿB-.ÿD//ÿE//ÿD//ÿD//ÿD//ÿD//ÿC..ÿD..ÿD/.ÿD/.ÿD//ÿC./ÿC..ÿD..ÿD..ÿC..ÿC..ÿC--ÿC--ÿC--ÿB--ÿB--ÿB--ÿB,,ÿB,,ÿB--ÿB--ÿB--ÿB--ÿB,-ÿA,,ÿB,,ÿC,,ÿC,,ÿB,,ÿA,-ÿB,-ÿB,-ÿB,-ÿC,-ÿB,-ÿB--ÿB-.ÿB-.ÿB--ÿB-.ÿA-.ÿB-.ÿB--ÿB--ÿA--ÿA,,ÿ@++ÿ@++ÿ@++ÿ@+,ÿA+,ÿA+,ÿA,,ÿA--ÿ@,-ÿA,,ÿA,,ÿB,,ÿB,,ÿC,-ÿC,-ÿC,-ÿB,-ÿB--ÿB--ÿC--ÿC,,ÿC,,ÿC,,ÿC,-ÿC,-ÿC,-ÿB,-ÿC,-ÿC--ÿC..ÿC..ÿC..ÿC..ÿC./ÿD./ÿE-.ÿE-.ÿI01ÿZ?AÿE./ÿ@)+ÿ?)*á?(*?(*A,.A,.B,.áA,.ÿJ57ÿv^bÿK58ÿB-/ÿC.0ÿC.0ÿD.1ÿE/1ÿF/1ÿF/2ÿF/2ÿF02ÿF03ÿG03ÿG13ÿG14ÿH14ÿH14ÿH25ÿI25ÿJ25ÿJ25ÿK26ÿK36ÿK36ÿK36ÿK37ÿK37ÿK47ÿK47ÿL48ÿL48ÿL48ÿM48ÿM58ÿN58ÿN59ÿN5:ÿN5:ÿN5:ÿO5:ÿO5:ÿO5:ÿN5:ÿM49ÿK26ÿZEIÿÀ¶«ÿÔÖ”ÿÍÏ|ÿÐÏ~ÿÒÏ}ÿÓÎ{ÿÕÍyÿÖÍxÿØÌwÿÚËtÿßЀÿéÖ¡ÿà»oÿáºjÿã¹iÿÞ·iÿÕµkÿÕ¶kÿÖ¶lÿÖ·nÿÖ·nÿÛ½}ÿϼ©ÿfVXÿ?)+ÿD*-ÿB-0ÿE/2ÿI14ÿK26ÿK36ÿL47ÿL48ÿL48ÿL37ÿL37ÿL37ÿL36ÿK36ÿK36ÿK35ÿK25ÿK25ÿK24ÿJ24ÿJ25ÿI24ÿI24ÿI14ÿH13ÿI13ÿH14ÿH03ÿH03ÿH03ÿH/2ÿG/2ÿG/2ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿC,/ÿD-.ÿC-.ÿC,.ÿC,.ÿC,.ÿC+.ÿB+-ÿB+-ÿA*,ÿA+,ÿ@+,ÿ@*,ÿ?*,ÿ@+,ÿB,-ÿD..ÿD//ÿD//ÿD//ÿD./ÿC..ÿD..ÿD..ÿD/.ÿC//ÿC..ÿC..ÿD..ÿD..ÿC..ÿC-.ÿC--ÿC--ÿB--ÿB--ÿB--ÿB,-ÿB,,ÿB,,ÿB--ÿB--ÿB--ÿB--ÿA,,ÿA,,ÿA,,ÿB,,ÿB,,ÿB,,ÿB,-ÿC,,ÿC,,ÿB,,ÿB,,ÿB,-ÿB--ÿB-.ÿB,-ÿB,-ÿA-.ÿA-.ÿA-.ÿA--ÿ@--ÿ@,,ÿ?++ÿ>++ÿ>**ÿ>**ÿ?*+ÿ?*+ÿ@+,ÿ@,,ÿ@,,ÿ@,,ÿA,,ÿA,,ÿB,,ÿC,,ÿC,-ÿC,-ÿB,-ÿB,-ÿB--ÿB--ÿC,,ÿC,,ÿC,,ÿC,,ÿC,-ÿC,-ÿB,-ÿB,-ÿC,-ÿC--ÿC..ÿC..ÿC..ÿC./ÿC./ÿD./ÿE-.ÿI12ÿ[@BÿH12ÿD..ÿC..áB--B--B,.B,.B,.áA,.ÿK57ÿw^bÿK58ÿB-/ÿC.0ÿD.1ÿD/1ÿE/1ÿF/2ÿF02ÿF02ÿF03ÿG03ÿG13ÿG14ÿH14ÿH14ÿH24ÿI25ÿI25ÿI26ÿJ36ÿK36ÿK36ÿK27ÿK37ÿK47ÿK47ÿL48ÿL48ÿL48ÿL58ÿM58ÿM59ÿM59ÿN59ÿN59ÿO59ÿO5:ÿO6:ÿO6:ÿO6:ÿO6:ÿO6:ÿN59ÿM48ÿP9=ÿªœ™ÿØØ ÿÊËoÿÐÎzÿÓÎzÿÕÍyÿÖÍxÿ×ÌwÿÚËuÿÛËsÿÝËrÿéÙœÿåÄ�ÿâ¹hÿà¸iÿ×¶jÿÕ¶kÿÖ¶lÿÖ¶nÿÖ·oÿ×·oÿÙ»wÿØÄ©ÿ{jlÿ>,.ÿC*,ÿC+.ÿC.1ÿF03ÿI25ÿK36ÿL37ÿL47ÿL48ÿL48ÿL37ÿL37ÿL37ÿL36ÿK36ÿK36ÿK35ÿK25ÿK25ÿK24ÿJ24ÿJ25ÿI24ÿI24ÿI14ÿI13ÿI13ÿH03ÿH03ÿG03ÿG02ÿH/2ÿG/2ÿG/1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿD-0ÿD-/ÿD-/ÿC,/ÿD-.ÿC-.ÿC,.ÿC,.ÿC,.ÿB+-ÿB+-ÿA*-ÿA*,ÿA+,ÿ@*,ÿ@*,ÿ?*,ÿ?*,ÿ@)+ÿA+,ÿC-.ÿD//ÿD//ÿC..ÿD..ÿD..ÿD..ÿD/.ÿC./ÿC..ÿC..ÿD..ÿC..ÿC..ÿC--ÿC--ÿC--ÿB--ÿB--ÿB--ÿB,,ÿB,,ÿB,,ÿB--ÿB--ÿB--ÿA,,ÿA,,ÿA,,ÿA,,ÿB,,ÿA,,ÿA,,ÿB,,ÿC,,ÿC,,ÿC,,ÿB,,ÿB,,ÿB--ÿB,-ÿB,,ÿA,-ÿ@+-ÿ?+-ÿ?+-ÿ?+,ÿ>++ÿ=**ÿ<))ÿ;))ÿ;))ÿ<))ÿ=*+ÿ>*+ÿ?+,ÿ?,,ÿ@,,ÿ@,,ÿA-,ÿA--ÿC,,ÿC,-ÿC,-ÿC,-ÿB,-ÿB,-ÿB--ÿB,-ÿC,,ÿC,,ÿC,,ÿC,-ÿC,-ÿB-.ÿB-.ÿB,-ÿC-.ÿC./ÿC//ÿC//ÿC//ÿC//ÿD./ÿD./ÿI12ÿ[@CÿH12ÿD-/ÿD./áD./D./B,.B,.B-/áA,.ÿK58ÿw^cÿL68ÿC-0ÿD.1ÿD/1ÿE/1ÿE/2ÿF/2ÿF02ÿF03ÿG03ÿG13ÿG14ÿH14ÿH14ÿH24ÿI24ÿI24ÿJ25ÿJ36ÿJ36ÿK26ÿK27ÿK37ÿK37ÿL37ÿL48ÿL48ÿM58ÿM58ÿM59ÿM59ÿM59ÿN59ÿN59ÿO6:ÿO6:ÿO6:ÿO6:ÿP6:ÿP6:ÿP6:ÿO6:ÿO6:ÿM59ÿK37ÿŒ{}ÿàÜ¿ÿÙØ’ÿÙÖ�ÿÛÖ�ÿÛÓˆÿÚЂÿÛÎ{ÿÛÌvÿÜËsÿÝÊoÿäуÿëјÿâ¸hÿÙ¶iÿÕ¶kÿÖ¶lÿÖ¶mÿÖ·oÿ×·oÿ׸pÿعsÿÞÇ¡ÿ›Š‰ÿC14ÿ@,.ÿD*,ÿC,/ÿD.1ÿG03ÿJ25ÿK36ÿL37ÿL37ÿM48ÿL48ÿL37ÿL37ÿL37ÿL36ÿL36ÿK36ÿK35ÿK25ÿK25ÿK24ÿJ24ÿJ15ÿI24ÿI24ÿH14ÿI13ÿI13ÿH03ÿH03ÿG03ÿG/2ÿG/2ÿG/2ÿF.1ÿF.1ÿF/1ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿC,/ÿC,/ÿC-.ÿC,.ÿC,-ÿC,-ÿC+.ÿB+-ÿB+-ÿA*,ÿA*,ÿ@+,ÿ@*,ÿ?*,ÿ?*,ÿ?),ÿ@)+ÿ?)+ÿA+,ÿB-.ÿC..ÿD..ÿD..ÿD..ÿD..ÿC/.ÿC..ÿC..ÿC..ÿC..ÿC..ÿC-.ÿC--ÿC--ÿB--ÿB--ÿB--ÿB,-ÿB,,ÿA,,ÿB,,ÿB,-ÿB--ÿB,-ÿA,,ÿA,,ÿA,,ÿA,,ÿB,,ÿA,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB--ÿB,,ÿB++ÿA++ÿ@++ÿ>*+ÿ=)+ÿ<)*ÿ;()ÿ;'(ÿ;&'ÿ:&&ÿ:&&ÿ:&'ÿ:'(ÿ<(*ÿ>)+ÿ?*,ÿ?+,ÿ@,,ÿ@,-ÿA--ÿB--ÿC--ÿC--ÿC-.ÿB-.ÿB-.ÿB-.ÿB-.ÿB--ÿC--ÿC--ÿC--ÿC--ÿB-.ÿB-.ÿB-.ÿB-.ÿC-/ÿC./ÿC./ÿC./ÿC./ÿC./ÿD-/ÿH02ÿ[?CÿH02ÿD-.ÿD-.áD-.D-.A-/A-/B-/áA,.ÿK58ÿx_cÿL59ÿC-0ÿD.1ÿE.1ÿE/2ÿE/2ÿF02ÿF03ÿF03ÿG13ÿG14ÿH14ÿH14ÿH24ÿI24ÿI24ÿJ25ÿJ35ÿJ36ÿK27ÿK27ÿK37ÿK37ÿL38ÿL38ÿL48ÿM58ÿM59ÿM59ÿM59ÿN59ÿN69ÿN6:ÿN6:ÿO6:ÿO6:ÿP6:ÿO6:ÿO6;ÿO6;ÿO7;ÿO7;ÿO7;ÿN6:ÿK37ÿmY]ÿÒɶÿÜ׊ÿ×ÑwÿÞ׋ÿãÛ™ÿæÜ�ÿçÝŸÿèÜžÿèÛ›ÿèÙ•ÿèבÿïÝ­ÿâÃÿØ»wÿ×¹sÿ׸pÿÖ·oÿÖ·nÿ×·oÿ׸pÿ׸pÿÞÄ�ÿ¿®¤ÿXEHÿ>+.ÿB,/ÿD*-ÿB,/ÿD.2ÿG04ÿI25ÿK36ÿL37ÿL37ÿL48ÿL48ÿL37ÿL37ÿL37ÿL36ÿL36ÿK36ÿK35ÿK25ÿK25ÿJ24ÿJ24ÿJ15ÿI24ÿI24ÿH14ÿI13ÿI13ÿH03ÿH03ÿG03ÿG/2ÿG/2ÿG/2ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿC,/ÿC,.ÿC,.ÿC,.ÿC,-ÿC,-ÿB+-ÿB+-ÿA*-ÿA*,ÿA+,ÿ@*,ÿ@*,ÿ?*,ÿ?*,ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ@*,ÿB,-ÿC-.ÿD..ÿD..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC..ÿC--ÿC--ÿB--ÿB--ÿB--ÿB--ÿB,,ÿA,,ÿA,,ÿB,,ÿB,-ÿB--ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB,+ÿB,,ÿB,,ÿA,,ÿ@,,ÿ@,,ÿ@+,ÿ@++ÿ?**ÿ>))ÿ<))ÿ;((ÿ:&'ÿ:&&ÿ<$%ÿ=$%ÿ<%&ÿ<&&ÿ<%%ÿ<%%ÿ;&'ÿ;()ÿ=)*ÿ>*,ÿ?*,ÿ@+,ÿA,-ÿA,-ÿB,-ÿC,-ÿC,-ÿB,.ÿB,.ÿB,.ÿB,.ÿB,-ÿB,-ÿC,-ÿC,-ÿC,-ÿC,-ÿB,.ÿB,.ÿB,.ÿB-.ÿC-/ÿC-/ÿC..ÿC..ÿD..ÿD--ÿH01ÿ[?AÿH01ÿD-.ÿE-.áE-.E-.B-/B-/B-/áB-.ÿL68ÿx_dÿL59ÿC-0ÿD.1ÿE.2ÿE/2ÿF02ÿF03ÿF03ÿF13ÿG14ÿH14ÿH14ÿI24ÿI24ÿI24ÿJ35ÿJ35ÿJ25ÿK26ÿK37ÿK37ÿK38ÿK38ÿL38ÿM48ÿM49ÿM49ÿM59ÿN59ÿN6:ÿN6:ÿN6:ÿO6:ÿO6:ÿO6:ÿO6;ÿO7;ÿP7;ÿP7;ÿP7;ÿP7;ÿP7;ÿP7;ÿO7;ÿM59ÿV?Dÿµ¨ ÿÛÔˆÿËÃJÿÎÃMÿÖÇ]ÿÙÉcÿÜÊfÿßÌjÿâÎpÿåÐwÿéÖ†ÿóæ¹ÿîÝ©ÿèÓ�ÿèÓ–ÿçÒ™ÿåИÿãÍ•ÿáÉ‘ÿ߯‹ÿÝÂ…ÿÞĉÿÚȱÿƒrsÿA,/ÿ@-0ÿB,/ÿD*-ÿC-/ÿD/2ÿG03ÿI25ÿK36ÿL36ÿL37ÿL48ÿL48ÿL37ÿL37ÿL37ÿL36ÿK36ÿK36ÿK35ÿK25ÿK25ÿJ24ÿJ14ÿJ15ÿI24ÿI24ÿH13ÿI13ÿH13ÿH03ÿG03ÿG03ÿG/2ÿG/2ÿG/1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.0ÿE.0ÿD-0ÿD-/ÿC-/ÿC,/ÿC,.ÿC,.ÿC,-ÿC,-ÿC+-ÿB+-ÿB+-ÿA*,ÿA*,ÿ@+,ÿ@*,ÿ?*,ÿ?*,ÿ?),ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ?(+ÿ@)+ÿB+,ÿC--ÿD..ÿC..ÿC.-ÿC..ÿC..ÿB..ÿB..ÿC--ÿC--ÿC--ÿB--ÿB--ÿB--ÿB,,ÿA,,ÿA,,ÿA,,ÿB,,ÿB,-ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB,+ÿB,+ÿA,+ÿA++ÿ@++ÿ?++ÿ>++ÿ>)*ÿ=))ÿ;((ÿ9&&ÿ9%%ÿ:$$ÿ;#$ÿ:%&ÿ:'(ÿ9))ÿ9))ÿ:))ÿ<''ÿ=%%ÿ;&&ÿ<()ÿ>)*ÿ?*+ÿ@*+ÿA,,ÿA,,ÿB,,ÿB,,ÿC,,ÿC,,ÿB,-ÿB,-ÿB,-ÿB+,ÿB+,ÿB,,ÿC,,ÿC,,ÿC,,ÿC,,ÿC,-ÿC,-ÿC-.ÿC-.ÿC-.ÿD-.ÿD..ÿD..ÿD--ÿH00ÿ[?AÿH01ÿD-.ÿD-.áD-.D-.B-/B-/B-/áB-.ÿL68ÿy_dÿM69ÿD-1ÿE.2ÿE.2ÿF/2ÿF/3ÿF03ÿF13ÿF14ÿG14ÿH14ÿI24ÿI24ÿI24ÿJ35ÿJ35ÿJ25ÿK26ÿK36ÿK36ÿK37ÿK38ÿK48ÿL48ÿM49ÿM49ÿN49ÿN59ÿN6:ÿO6:ÿO6:ÿO6:ÿO6;ÿO7;ÿP7;ÿP7;ÿO7:ÿP7:ÿP7:ÿP7;ÿP7;ÿQ7<ÿQ7<ÿP7<ÿO7;ÿN5:ÿ�|}ÿÜÓ¨ÿÑÇXÿÎÂHÿÓÃMÿÙÇ\ÿÛÈ]ÿÝÇ[ÿÞÆYÿàÆXÿêÖ‡ÿë×�ÿìØ“ÿâÄXÿáÃUÿãÆ]ÿåÉeÿæÌoÿçÐzÿéÓ…ÿêÕŽÿêÖ–ÿíݲÿ¿°§ÿWCFÿ?+-ÿ@-0ÿB,/ÿE*-ÿD,/ÿC.1ÿF03ÿI14ÿJ25ÿK36ÿL37ÿL37ÿL48ÿL37ÿL37ÿL37ÿL36ÿK36ÿK36ÿK35ÿK25ÿK25ÿJ24ÿJ15ÿI14ÿI24ÿI14ÿI13ÿI13ÿH03ÿH02ÿG03ÿG/2ÿG/2ÿG/2ÿF.1ÿF.1ÿF/0ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿC,/ÿC,.ÿB,.ÿB+.ÿC,-ÿC,-ÿB+-ÿB+-ÿA*-ÿA*,ÿ@+,ÿ@*,ÿ@*,ÿ?*,ÿ?*,ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ>(*ÿ?(*ÿ@)+ÿA+,ÿB--ÿC--ÿC.-ÿC..ÿC..ÿB..ÿB-.ÿC--ÿC--ÿB--ÿB--ÿB--ÿB,-ÿB,,ÿA,,ÿA,,ÿA,,ÿB,,ÿB,,ÿA,,ÿA,,ÿA,,ÿA,,ÿ@,,ÿ@,,ÿ@++ÿA+*ÿ@+*ÿ@**ÿ>**ÿ=))ÿ<))ÿ;((ÿ:&&ÿ:%%ÿ:$$ÿ;##ÿ9$$ÿ8&'ÿ8'(ÿ8''ÿ8''ÿ9''ÿ:((ÿ:**ÿ;))ÿ>&&ÿ=''ÿ=)*ÿ?)+ÿ@*+ÿA+,ÿB,,ÿB,,ÿC,,ÿC,,ÿC,,ÿC,,ÿC,-ÿC,-ÿC+-ÿC+,ÿC+,ÿC,,ÿC,,ÿC,,ÿC,,ÿC,,ÿC,-ÿB,-ÿB-.ÿB-.ÿC-.ÿC-.ÿC..ÿD-.ÿH00ÿZ?@ÿG01ÿC-.ÿD-.áD-.D-.A-/A-/B-/áB-.ÿL58ÿy`dÿM69ÿD-1ÿE.2ÿF/2ÿF/3ÿF/3ÿF03ÿF14ÿG14ÿG14ÿH24ÿH24ÿI24ÿJ35ÿJ35ÿJ25ÿK26ÿK36ÿK36ÿK37ÿK37ÿL48ÿL49ÿL49ÿM49ÿN59ÿN5:ÿN5:ÿO5:ÿO6:ÿO6;ÿO7;ÿP7;ÿO7;ÿO7:ÿO7;ÿO7;ÿP7;ÿP8;ÿQ8;ÿQ8;ÿQ8;ÿQ8<ÿQ8<ÿP8<ÿN5:ÿfPUÿɽ­ÿÛÐwÿÐÁFÿÒÁEÿ×ÃMÿÝÇ[ÿÞÇ[ÿàÆXÿçÑyÿìØ“ÿãÇeÿëÖ�ÿæÌqÿàÀNÿáÁPÿáÁPÿáÂQÿáÂRÿâÃSÿâÄUÿãÅXÿæÊeÿãÏœÿ”ƒ€ÿD03ÿ@+.ÿA-0ÿB,/ÿD*-ÿD,.ÿC.1ÿE/3ÿH14ÿI25ÿK36ÿK36ÿL37ÿK37ÿL37ÿL37ÿL37ÿL36ÿK36ÿK36ÿK35ÿJ25ÿK24ÿJ24ÿJ15ÿI14ÿI24ÿH14ÿI13ÿI13ÿH02ÿH02ÿG03ÿG/2ÿF/2ÿG/1ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿD-0ÿD-/ÿC-/ÿC,/ÿC,.ÿB+.ÿB+-ÿC,-ÿC+-ÿB+,ÿB+-ÿA*,ÿA+,ÿ@+,ÿ@*,ÿ?*,ÿ?*,ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ?(+ÿ?(*ÿ?(*ÿ?(*ÿ?)*ÿ@*+ÿB,,ÿC.-ÿC..ÿB..ÿB..ÿB--ÿC--ÿB--ÿB--ÿB--ÿB--ÿB,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA+,ÿA,,ÿA,,ÿ@,,ÿ@++ÿ?++ÿ?**ÿ?*)ÿ?*)ÿ>)(ÿ<((ÿ:''ÿ9''ÿ9&&ÿ:$$ÿ;##ÿ:$$ÿ8&&ÿ7''ÿ7''ÿ8&'ÿ7&&ÿ7%&ÿ8&&ÿ:''ÿ:))ÿ:))ÿ=%%ÿ<''ÿ<))ÿ=)*ÿ?*+ÿ@+,ÿA+,ÿB,,ÿB,,ÿB,,ÿB,,ÿA,,ÿB,,ÿB,-ÿB+-ÿB+,ÿB+,ÿB+,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,-ÿB-.ÿB-.ÿB-.ÿC-.ÿC-.ÿC-.ÿH00ÿY?@ÿG00ÿC--ÿC-.áC-.C-.B./B./B./áB-/ÿL59ÿz`eÿN69ÿD.0ÿF/2ÿF/3ÿF/3ÿF03ÿF04ÿG04ÿG14ÿH24ÿH24ÿH24ÿI35ÿJ35ÿK25ÿK26ÿK36ÿK36ÿK37ÿK37ÿL47ÿL48ÿL48ÿM49ÿM5:ÿM5:ÿN5:ÿO5:ÿO5;ÿO6;ÿP6;ÿO7:ÿO7:ÿO7;ÿP7;ÿP8;ÿP8;ÿP8;ÿP8;ÿQ8<ÿR8<ÿR8<ÿR8<ÿR7=ÿR7=ÿQ6<ÿR8>ÿž��ÿàÕ ÿÔÄOÿÓÀDÿÖÀBÿÛÃNÿ߯XÿäÌiÿíÛ™ÿåÊmÿãÇbÿçÎwÿë×�ÿáÂRÿáÁQÿáÂRÿáÃSÿâÃTÿâÄUÿâÄVÿãÅXÿãÅWÿçÎsÿÓ£ÿvdeÿ?*-ÿ@,.ÿA-0ÿA,0ÿD*-ÿE+.ÿC-0ÿD/2ÿG03ÿH14ÿJ25ÿJ26ÿK37ÿK37ÿK37ÿL37ÿL37ÿL36ÿK36ÿK35ÿJ35ÿJ25ÿJ24ÿJ24ÿJ15ÿI14ÿI14ÿH13ÿI13ÿH13ÿH02ÿG02ÿG02ÿG/2ÿF/2ÿF/1ÿF.1ÿF/1ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿC,/ÿC,.ÿB,.ÿB+.ÿB+-ÿC+-ÿB+,ÿB+,ÿA*-ÿA*,ÿ@+,ÿ@*,ÿ?*,ÿ?*,ÿ?*,ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ>(*ÿ?(*ÿ?(*ÿ?(*ÿ>(*ÿ>')ÿ@)*ÿA,,ÿB.-ÿB..ÿB-.ÿB--ÿC--ÿB--ÿB--ÿB--ÿB,,ÿA,,ÿA,,ÿA,,ÿA,,ÿA,,ÿ@++ÿ@*+ÿ@++ÿ?++ÿ?++ÿ>**ÿ=))ÿ<)(ÿ<('ÿ;'&ÿ9&%ÿ9%%ÿ:$$ÿ;#$ÿ9$$ÿ8&&ÿ7''ÿ7''ÿ7&&ÿ7%%ÿ6$$ÿ5##ÿ=+*ÿA0.ÿ9''ÿ9((ÿ:))ÿ=%%ÿ<''ÿ<))ÿ=**ÿ?*+ÿ@+,ÿA+,ÿA+,ÿB,,ÿB,,ÿB,,ÿA,,ÿA,,ÿB,,ÿB,,ÿB+,ÿB+,ÿB+,ÿB+,ÿB,,ÿB,,ÿB,,ÿB,,ÿB,,ÿB--ÿB-.ÿB-.ÿB-.ÿC-.ÿC-.ÿH00ÿY?@ÿH00ÿC--ÿC--áC-.C-.B./B./B-/áB,/ÿL69ÿzaeÿN69ÿE.0ÿF/1ÿF/2ÿF/3ÿF04ÿG04ÿG04ÿG14ÿH24ÿH24ÿI35ÿI35ÿJ25ÿK26ÿK36ÿK37ÿK37ÿK37ÿL47ÿL48ÿL48ÿM48ÿM59ÿN5:ÿN5:ÿN5;ÿO6;ÿP6;ÿO6:ÿO6;ÿO7;ÿP7;ÿP8;ÿP8;ÿP8;ÿQ8<ÿQ8<ÿQ7<ÿQ7<ÿQ8<ÿR8<ÿR8<ÿR8<ÿR8=ÿR8=ÿO5;ÿnX]ÿϯÿÞÏrÿÕ¿Aÿ׿AÿÙ¿@ÿàÆUÿìÚ•ÿçÎyÿãÇbÿäÈeÿäÉhÿìÙ•ÿåÉgÿáÂQÿáÃSÿâÃTÿâÃUÿâÄVÿãÅXÿãÅXÿãÆXÿãÇ[ÿéÒ†ÿÄ´ ÿfSVÿ=(+ÿ@+.ÿA-0ÿA-0ÿC+.ÿE*-ÿD,/ÿC.1ÿE/2ÿG03ÿI14ÿI25ÿJ26ÿK36ÿK26ÿK26ÿK36ÿL36ÿK36ÿK35ÿJ25ÿJ25ÿJ24ÿJ14ÿJ14ÿI14ÿI14ÿI13ÿI13ÿH03ÿH02ÿG02ÿG/2ÿF/2ÿF/2ÿF.1ÿF.1ÿE/0ÿE.0ÿE.1ÿE.0ÿE-0ÿD-/ÿC-/ÿC,/ÿC,.ÿB+.ÿB+-ÿB+-ÿC+-ÿB+,ÿB+,ÿA*,ÿA+,ÿ@+,ÿ@*,ÿ?*,ÿ?*,ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ>(*ÿ?(*ÿ?(*ÿ?(*ÿ>(*ÿ>')ÿ>')ÿ>')ÿ?)*ÿ@,,ÿB--ÿB--ÿB--ÿB--ÿB--ÿB--ÿB,-ÿB,,ÿA,,ÿ@,,ÿ@++ÿ@++ÿ?*+ÿ>**ÿ>)*ÿ>**ÿ=))ÿ<))ÿ:((ÿ9'&ÿ9&%ÿ:%$ÿ;$#ÿ:#"ÿ9$#ÿ7&&ÿ6''ÿ6''ÿ7&&ÿ6%%ÿ6##ÿ5""ÿ8&$ÿO;9ÿ€hpÿŒs€ÿ]IHÿ@/-ÿ:%%ÿ<%%ÿ;''ÿ=))ÿ>**ÿ?**ÿ@++ÿA+,ÿA+,ÿB+,ÿB,,ÿB,,ÿA,,ÿA,,ÿA,,ÿB,,ÿB+,ÿB+,ÿB+,ÿB+,ÿB+,ÿB,,ÿA,,ÿB,,ÿB,,ÿB--ÿB--ÿB-.ÿB-.ÿB-.ÿB-.ÿG/1ÿY>@ÿH00ÿC--ÿC--áC--C--B-/B-/B-/áB-/ÿL69ÿzaeÿM7:ÿE.1ÿF/2ÿF/2ÿF03ÿF04ÿG04ÿG14ÿH14ÿH14ÿI25ÿI35ÿI25ÿJ26ÿJ36ÿK37ÿK37ÿK47ÿL48ÿL48ÿM48ÿM58ÿM59ÿN59ÿN59ÿN6;ÿO6;ÿO6:ÿO6:ÿO6;ÿP7;ÿP7;ÿP7;ÿP8<ÿQ8<ÿQ7<ÿQ8<ÿQ8<ÿQ8<ÿR8=ÿR8=ÿR8=ÿS8=ÿS8=ÿS8=ÿS8>ÿR7=ÿT:@ÿž��ÿâÕ£ÿÚÄNÿØ¿?ÿÛ¿>ÿæÑvÿéÓƒÿãÇcÿäÈdÿäÈfÿäÈfÿéÒ‚ÿêÔ‡ÿáÂRÿâÃTÿâÃUÿâÄVÿãÅWÿãÅXÿãÅXÿãÆZÿãÇ[ÿäÉaÿèÓ‘ÿº«œÿ`NQÿ=(*ÿ?+-ÿA-0ÿ@-0ÿB,/ÿD+-ÿD+-ÿC,/ÿD.1ÿE/2ÿG03ÿH14ÿI25ÿJ26ÿJ26ÿK26ÿK26ÿK26ÿK36ÿK35ÿJ25ÿJ25ÿJ24ÿJ15ÿI14ÿI14ÿH14ÿI13ÿH13ÿH02ÿH02ÿG02ÿG/2ÿF/2ÿF/1ÿF.1ÿF/1ÿE/0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿC,/ÿC,.ÿB,.ÿB+.ÿB+-ÿB+-ÿB+,ÿB+,ÿA*,ÿA*,ÿ@+,ÿ@*,ÿ?*,ÿ?*,ÿ?),ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ?(+ÿ?(*ÿ?(*ÿ?(*ÿ?(*ÿ>'*ÿ>')ÿ>')ÿ>')ÿ=')ÿ>)*ÿ@*+ÿA,,ÿA--ÿB--ÿB--ÿA,-ÿA+,ÿ@++ÿ@++ÿ?++ÿ?**ÿ>**ÿ<))ÿ<((ÿ;'(ÿ:''ÿ9&&ÿ8%%ÿ9$$ÿ:#"ÿ:#"ÿ9$#ÿ7&&ÿ6'&ÿ6''ÿ7%&ÿ7$%ÿ6##ÿ4""ÿ5$#ÿG42ÿq[_ÿ§ˆ¥ÿÆŸÞÿÈ æÿ±’¹ÿ€hpÿS<9ÿ<)(ÿ:''ÿ=)*ÿ>++ÿ?*+ÿ@++ÿ@++ÿA+,ÿB+,ÿB+,ÿB,,ÿA,,ÿA,,ÿA,,ÿA,,ÿB++ÿB++ÿB+,ÿB+,ÿB+,ÿB+,ÿA,,ÿA,,ÿB,,ÿB,,ÿB--ÿB--ÿB-.ÿB-.ÿB-.ÿG/1ÿY>@ÿH/0ÿD--ÿC--áC--C--C-0C-0C-0áC-/ÿM69ÿzafÿM7:ÿE.1ÿF/2ÿF02ÿF03ÿG03ÿG14ÿH14ÿH14ÿI15ÿI25ÿI25ÿJ26ÿJ36ÿK37ÿK37ÿK47ÿL48ÿL48ÿM48ÿM59ÿM59ÿN59ÿN59ÿN6:ÿO6:ÿO6:ÿO6;ÿO6;ÿP7;ÿP7;ÿQ7<ÿQ7<ÿQ7<ÿQ8<ÿQ8<ÿR8=ÿR8=ÿR8=ÿR8=ÿR8=ÿR8=ÿS8=ÿS8=ÿS9=ÿS9>ÿS9>ÿQ6<ÿiRXÿÈ»­ÿäÑ}ÿÚ¿=ÿãËbÿèÓ€ÿßÁPÿãÆ`ÿäÈfÿäÈgÿåÈgÿæËoÿíÛ™ÿäÇ`ÿâÃTÿâÄVÿãÅWÿãÅXÿãÅXÿãÆYÿãÇ[ÿãÈ\ÿãÈ\ÿæËeÿèÓ•ÿºªœÿcQTÿ=(+ÿ>*,ÿ@,/ÿ@-0ÿ@-0ÿC,.ÿD*-ÿD+.ÿD,/ÿD.1ÿE/2ÿF03ÿH14ÿH15ÿI15ÿJ25ÿJ25ÿJ25ÿJ25ÿJ25ÿJ25ÿJ24ÿJ24ÿJ15ÿI14ÿI14ÿH03ÿI13ÿH03ÿH02ÿG02ÿG/1ÿF/2ÿF/2ÿE.1ÿE.1ÿE/0ÿE.0ÿE.1ÿE.0ÿD-0ÿD-/ÿC,/ÿC,/ÿB,.ÿB+.ÿB+-ÿB+-ÿB*-ÿB+,ÿB+,ÿA*+ÿA+,ÿ@*,ÿ@*,ÿ?*,ÿ?*,ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ>(*ÿ?(*ÿ?(*ÿ?(*ÿ>(*ÿ>')ÿ>')ÿ>')ÿ=')ÿ=')ÿ=')ÿ=()ÿ>)*ÿ?++ÿ@,,ÿA,,ÿ@++ÿ?**ÿ>**ÿ=**ÿ=))ÿ<((ÿ:''ÿ8&&ÿ8%%ÿ9$$ÿ:#$ÿ:##ÿ9##ÿ8%$ÿ7'&ÿ6'&ÿ7'&ÿ7&%ÿ6%$ÿ5##ÿ4!"ÿ4##ÿB0.ÿgRTÿž€–ÿÄ�ÔÿËŸïÿÆ™õÿØöÿÅœóÿÀ�Þÿ£ˆ¦ÿta`ÿM96ÿ@,,ÿ?++ÿ?++ÿ@++ÿ@++ÿ@++ÿA+,ÿB+,ÿB+,ÿB,,ÿA,,ÿA,,ÿA,,ÿA+,ÿB++ÿB++ÿB+,ÿB+,ÿB+,ÿA+,ÿA,,ÿA,,ÿB,,ÿB--ÿB--ÿB--ÿB-.ÿB-.ÿF/1ÿY=@ÿG/0ÿD,-ÿC--áC--C--C-0C-0C-0áC-0ÿM7:ÿ{bfÿN7:ÿE.1ÿF02ÿF03ÿG03ÿG03ÿH14ÿH14ÿH15ÿI25ÿI25ÿJ26ÿJ36ÿK36ÿK37ÿJ47ÿK48ÿL48ÿM48ÿM59ÿM59ÿN59ÿN5:ÿO6:ÿO6:ÿO6:ÿO6;ÿO7;ÿO7;ÿO7<ÿP7<ÿQ7<ÿQ8<ÿQ8<ÿR7=ÿR8=ÿR8=ÿR8=ÿS8=ÿS9>ÿS9>ÿS9>ÿS9>ÿS9>ÿS9>ÿS9>ÿS9>ÿR9>ÿR8>ÿ�z}ÿßѬÿåÎmÿéÕ…ÿßÂRÿÞ¾FÿàÂRÿäÈeÿåÈgÿåÉiÿåÉiÿë׎ÿéÑ}ÿâÃTÿâÅWÿãÅXÿãÅXÿãÆYÿãÇZÿãÇ\ÿãÈ]ÿäÉ^ÿäÉ^ÿæÌgÿèÔ”ÿÀ±Ÿÿn]^ÿ?+-ÿ=(+ÿ@+.ÿ@,/ÿ@-0ÿA-/ÿB+.ÿD*-ÿE+-ÿD,/ÿD-0ÿD.1ÿF/3ÿF03ÿH04ÿI14ÿI14ÿI25ÿI24ÿI14ÿI14ÿI24ÿI14ÿI14ÿI14ÿH04ÿI03ÿI13ÿH02ÿH02ÿG02ÿG/1ÿF/2ÿF/1ÿE.1ÿE/1ÿE.0ÿE.1ÿE.0ÿE-0ÿD-0ÿD-/ÿC,/ÿC,.ÿB,.ÿB+.ÿB+-ÿB*-ÿA*,ÿA*,ÿA*+ÿA*+ÿ@+,ÿ@*,ÿ?*,ÿ?*,ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ?)+ÿ>(*ÿ>(*ÿ?(*ÿ?(*ÿ>(*ÿ>')ÿ>')ÿ>')ÿ=')ÿ<')ÿ<&(ÿ<&'ÿ;&(ÿ;&(ÿ;')ÿ=)*ÿ>)*ÿ=))ÿ<((ÿ;((ÿ:''ÿ9&&ÿ8$%ÿ9##ÿ:""ÿ:""ÿ9##ÿ7%%ÿ6&'ÿ6'&ÿ7&&ÿ7%%ÿ6$$ÿ5#"ÿ3"!ÿ4""ÿA.-ÿdNPÿ˜{�ÿÁšÌÿÍ ìÿÉ›óÿƘôÿĘõÿ˜öÿÀ—öÿ¾˜÷ÿÁ�óÿȰ×ÿ�y~ÿS>:ÿ?++ÿ@+,ÿ@++ÿ@++ÿ@++ÿA++ÿB+,ÿB+,ÿB+,ÿA+,ÿA,,ÿA,,ÿA+,ÿA++ÿB++ÿB++ÿB+,ÿB+,ÿA+,ÿA+,ÿA+,ÿA,,ÿB--ÿB--ÿB--ÿB--ÿB-.ÿF/1ÿX=@ÿG/0ÿD,-ÿC,-áC--C--C.0C.0C.0áC-0ÿM7:ÿ|cgÿN8;ÿE/1ÿF03ÿF03ÿF03ÿG14ÿH14ÿH15ÿI25ÿI25ÿJ26ÿJ36ÿK36ÿK37ÿK37ÿK48ÿK48ÿL48ÿM59ÿM59ÿN59ÿN5:ÿO6:ÿO6:ÿO6;ÿO6;ÿO7;ÿO7;ÿP7<ÿP7<ÿP8<ÿQ8<ÿR7=ÿR7=ÿR7=ÿR8=ÿS8>ÿS9>ÿS9>ÿS9>ÿS9>ÿS9>ÿS9>ÿS9>ÿS9>ÿT9?ÿT9>ÿT9?ÿR8>ÿ]DJÿ³£Ÿÿîá¼ÿäÊhÿݾDÿÞ¿HÿÞÀJÿáÄYÿåÈhÿåÉjÿåÊjÿèÏxÿíÛ—ÿãÆ[ÿãÅWÿãÅXÿãÆYÿãÆZÿãÇ\ÿãÈ]ÿäÉ]ÿäÉ^ÿäÉ_ÿäÉ`ÿæÌfÿê×”ÿÏ´ÿ�rrÿG36ÿ<')ÿ?*,ÿ@+.ÿ@-0ÿ?.0ÿ@-/ÿB+.ÿD*,ÿE*-ÿC+.ÿC,/ÿC.1ÿD.2ÿF/2ÿG/3ÿG03ÿH13ÿH13ÿH13ÿH13ÿH13ÿH04ÿH04ÿH04ÿH03ÿH03ÿH03ÿH02ÿG02ÿG/1ÿF/1ÿF/1ÿE.1ÿE.1ÿE/0ÿE.0ÿE.1ÿE.0ÿD-0ÿD-/ÿC,/ÿC,.ÿB,.ÿB+.ÿB+-ÿB+-ÿA*,ÿA*,ÿA*,ÿA*+ÿ@+,ÿ@*,ÿ?*,ÿ?*,ÿ?),ÿ@)+ÿ?)+ÿ?)+ÿ?)+ÿ?(+ÿ>(*ÿ>(*ÿ?(*ÿ>(*ÿ=')ÿ=&(ÿ=&(ÿ<&(ÿ;&(ÿ;%'ÿ:%&ÿ:%&ÿ9%&ÿ8$&ÿ7$&ÿ7$&ÿ8%&ÿ9&&ÿ9%%ÿ:$$ÿ:##ÿ:##ÿ9##ÿ7$$ÿ6&&ÿ6&&ÿ6&&ÿ6%&ÿ6%%ÿ6$#ÿ5#"ÿ3!!ÿ4#"ÿA/-ÿdNQÿ—y�ÿšÉÿСêÿÌœòÿÈ™óÿÆ™ôÿĘõÿ˜öÿÀ—öÿ½–÷ÿº•ùÿ»˜÷ÿº ÏÿydeÿE00ÿ@++ÿ@,,ÿ@++ÿ@++ÿ@++ÿ@++ÿA++ÿB+,ÿB+,ÿA+,ÿA+,ÿA,,ÿA,,ÿA++ÿA++ÿB++ÿB++ÿB+,ÿB+,ÿA+,ÿA+,ÿA,,ÿA--ÿB--ÿB--ÿB--ÿB--ÿF/1ÿX=@ÿF/0ÿC,-ÿC,-áC,-C,-C.0C.0D.0áC.0ÿM7:ÿ{cgÿN8;ÿE/2ÿF03ÿF03ÿF14ÿG14ÿH14ÿI25ÿI25ÿJ25ÿJ36ÿK36ÿK37ÿJ37ÿK37ÿK48ÿL48ÿL59ÿL59ÿN59ÿN5:ÿO6:ÿO6:ÿO6;ÿO7;ÿO7;ÿO7;ÿP7;ÿP7;ÿP8<ÿQ7=ÿQ7=ÿQ7=ÿR7=ÿS8>ÿS8>ÿS8>ÿS9>ÿS9>ÿS9?ÿS9?ÿS:?ÿS:?ÿS:?ÿS:?ÿS:?ÿT:?ÿT:?ÿT:?ÿR8=ÿq[`ÿÍÀ¶ÿèÒ‡ÿÞÀIÿÞÀIÿÞÁJÿßÂMÿãÇ_ÿåÊkÿæËlÿæËmÿíÛ—ÿçÎsÿãÅVÿãÆXÿãÆZÿãÇ[ÿãÈ\ÿäÉ]ÿäÉ^ÿäÉ_ÿäÉ`ÿåÊaÿåËcÿëÙ“ÿàÑ ÿÐÁ¦ÿœŽŠÿXGIÿ<(+ÿ=(*ÿ?*-ÿ?,.ÿ?-/ÿ?-0ÿ@,/ÿB+-ÿD*,ÿD),ÿC+-ÿB,/ÿB,0ÿC-1ÿD.1ÿE/2ÿF/2ÿF02ÿF02ÿF02ÿG03ÿG03ÿG03ÿG/3ÿG/2ÿH/2ÿG/2ÿG02ÿF/1ÿF/1ÿF/1ÿE.1ÿE.1ÿE/1ÿE.0ÿE.1ÿE.0ÿE-0ÿD-/ÿD-/ÿC,/ÿC,.ÿB+.ÿB+-ÿB+-ÿB*-ÿA*,ÿA*,ÿ@*+ÿ@+,ÿ@*,ÿ?*+ÿ?*,ÿ?*,ÿ?)+ÿ?)+ÿ>)*ÿ>)*ÿ>(*ÿ=')ÿ=')ÿ=')ÿ=')ÿ<&)ÿ<%(ÿ;%'ÿ;%'ÿ:%&ÿ9$&ÿ8#%ÿ7#$ÿ6#$ÿ5"$ÿ5"#ÿ5 "ÿ7!ÿ8!ÿ9 !ÿ9"#ÿ8$$ÿ7&&ÿ6&&ÿ6&&ÿ6&&ÿ6%%ÿ6$$ÿ5##ÿ4""ÿ3!!ÿ5$#ÿD32ÿiTWÿš{�ÿÚÊÿÒ¢éÿÏ�ñÿËšòÿÉ™óÿÇ™ôÿĘõÿÁ—öÿ¾•÷ÿº”øÿ¸“ùÿ»—øÿ¹›×ÿhpÿG31ÿ?*+ÿ@+,ÿ@,,ÿ@++ÿ@++ÿ@++ÿ@++ÿA++ÿA++ÿA+,ÿA+,ÿA+,ÿA+,ÿA,,ÿA++ÿA++ÿA++ÿB++ÿB++ÿB+,ÿA+,ÿA+,ÿA+,ÿA,-ÿA--ÿB--ÿB--ÿB--ÿF00ÿX=?ÿF/0ÿC,-ÿC,-áB,-B,-D.0D.0D.1áD.0ÿN8:ÿ|cgÿO8;ÿF/2ÿF03ÿF03ÿG14ÿG14ÿH15ÿI25ÿJ25ÿJ25ÿJ36ÿK37ÿK37ÿK37ÿK38ÿL38ÿL59ÿL59ÿM59ÿM5:ÿN6:ÿO6:ÿO6;ÿO7;ÿO7;ÿP7<ÿP7;ÿP8;ÿQ8<ÿQ7<ÿQ7<ÿQ7=ÿR8>ÿR8>ÿS8>ÿS8>ÿS8>ÿS8?ÿS9?ÿS:?ÿS:?ÿT:?ÿT:?ÿT:?ÿT:?ÿT:@ÿT:?ÿT:?ÿU:@ÿT:?ÿT9?ÿŠvzÿÜζÿæÎuÿÞÀIÿßÁLÿßÂMÿàÄQÿäÉeÿæËmÿæÌlÿéÔ‚ÿìÙ‘ÿãÆYÿãÆYÿãÇ[ÿãÈ\ÿãÈ]ÿäÉ^ÿäÉ_ÿäÉ`ÿåÊaÿåÊaÿéÖ…ÿàДÿϺgÿÓÀxÿ×ÇŸÿ¹«ŸÿxhiÿF36ÿ;&)ÿ=(*ÿ>*,ÿ?,.ÿ?-/ÿ?-/ÿ?-/ÿA+.ÿB*,ÿC)+ÿC),ÿC*-ÿC+.ÿB,/ÿB-0ÿC.0ÿC.0ÿD.0ÿD.1ÿE.2ÿE/2ÿF/2ÿF.1ÿF.1ÿF.1ÿF.1ÿF/1ÿE.0ÿE.0ÿE.0ÿD-0ÿD.0ÿD./ÿD-0ÿD.0ÿD-0ÿC-/ÿC,/ÿB,.ÿB,.ÿA+.ÿA+-ÿA+-ÿA*,ÿ@*,ÿ@*+ÿ?*+ÿ?*+ÿ?*+ÿ?)*ÿ>)*ÿ>)+ÿ>(*ÿ>(*ÿ=(*ÿ=(*ÿ=')ÿ<&)ÿ;&(ÿ;&(ÿ;&(ÿ:%'ÿ9$&ÿ9$%ÿ8#%ÿ7#%ÿ6"$ÿ6!#ÿ6 "ÿ7 !ÿ7!ÿ7 ÿ7!ÿ6!ÿ4!"ÿ3"#ÿ3#$ÿ4$%ÿ6%&ÿ6%%ÿ6$$ÿ5##ÿ4""ÿ3!!ÿ2!!ÿ7&%ÿK97ÿnY^ÿ¨’žÿ̦ÓÿÔ¢êÿÑ�ðÿÍšñÿËšòÿÈ™óÿŘôÿÁ–õÿ¾•öÿ»”÷ÿ¹“øÿ¹”ùÿ¼˜øÿ¼�Ýÿˆp}ÿL75ÿ?**ÿ@+,ÿ@+,ÿ@+,ÿ@+,ÿ@++ÿ@++ÿ@++ÿA++ÿA++ÿA++ÿA+,ÿA+,ÿA+,ÿA+,ÿA++ÿA++ÿA++ÿA++ÿA++ÿB++ÿA+,ÿA+,ÿA+,ÿA,-ÿA,-ÿA--ÿB--ÿB--ÿF00ÿX>?ÿF/0ÿC,-ÿC,-áB,-B,-D.1D.1D.1áD.1ÿN8;ÿ}dhÿO8;ÿF/2ÿF03ÿF14ÿG14ÿG15ÿH25ÿH25ÿJ25ÿJ35ÿK36ÿK37ÿK37ÿK38ÿL38ÿL48ÿL49ÿM59ÿM5:ÿN6:ÿN6:ÿO6;ÿO7;ÿO7;ÿP7<ÿP7;ÿP8;ÿQ7<ÿQ7<ÿQ7<ÿR8=ÿR8=ÿR8>ÿS8>ÿS8?ÿS9?ÿS9?ÿS9?ÿT9?ÿT9?ÿT:@ÿT:@ÿT:@ÿT:@ÿT:@ÿU;@ÿT;@ÿU;@ÿU:@ÿU;@ÿT:?ÿY?Eÿ Ž�ÿäÕ²ÿäËhÿßÁKÿßÃNÿàÃNÿáÆVÿåËiÿæÍnÿçÎrÿîÝœÿæÌjÿãÆZÿãÈ\ÿãÈ]ÿäÉ^ÿäÉ^ÿäÉ`ÿåÉaÿåÊ`ÿèÑvÿåלÿмmÿιeÿκfÿѽoÿ×ÅŽÿ̾¦ÿ¡’ŽÿeSUÿ@-/ÿ:&(ÿ=(*ÿ>*,ÿ?+-ÿ?,.ÿ?-/ÿ?,/ÿ@,.ÿA*,ÿB)+ÿC(+ÿD),ÿC*,ÿB+-ÿA+-ÿA,.ÿA,.ÿA,/ÿB-0ÿC-0ÿC-0ÿD-0ÿD-0ÿD-0ÿD-/ÿD./ÿD-/ÿC-/ÿC-.ÿC-/ÿC-/ÿC-/ÿC-/ÿC,/ÿC,/ÿB,.ÿB+.ÿA+-ÿA+-ÿ@*-ÿ@*,ÿ@),ÿ?)+ÿ?)+ÿ>)*ÿ>)*ÿ=)*ÿ=)*ÿ=()ÿ<()ÿ<')ÿ<')ÿ;'(ÿ;&(ÿ;&(ÿ:%'ÿ9%&ÿ8$&ÿ7$&ÿ7#%ÿ6"$ÿ6"#ÿ7!#ÿ7 "ÿ7 !ÿ8!ÿ8 ÿ7 ÿ5 !ÿ4!"ÿ3#$ÿ3#%ÿ3#$ÿ3#$ÿ4"#ÿ3!#ÿ3!"ÿ3 !ÿ2 !ÿ2 ÿ3"!ÿ<,+ÿVCEÿ‚muÿ£�žÿǤÉÿ߸îÿÓžðÿÏšðÿÌ™ñÿȘòÿÄ—ôÿÁ–õÿ¾”öÿ¼”öÿ»“÷ÿ»”÷ÿ¼–øÿ½™øÿ¿žâÿŽu…ÿP;8ÿ?**ÿ@++ÿ@++ÿ@++ÿ@+,ÿ?+,ÿ@++ÿ@++ÿ@++ÿA++ÿA++ÿA++ÿA++ÿ@+,ÿA+,ÿA+,ÿA*,ÿA++ÿA++ÿA++ÿA++ÿA++ÿA++ÿA+,ÿA+,ÿA+,ÿA,-ÿA,-ÿA--ÿA--ÿF00ÿX=?ÿG//ÿC,,ÿC,-áB,-B,-D.1D.1D.1áD.1ÿN8;ÿ}dhÿO9<ÿF/2ÿF14ÿG14ÿG14ÿH25ÿH25ÿI25ÿI35ÿJ35ÿK36ÿK36ÿK37ÿK38ÿL48ÿL49ÿM49ÿM4:ÿN6:ÿN6:ÿN6;ÿO7;ÿO7;ÿP7;ÿP7;ÿP8;ÿQ7<ÿQ7<ÿQ7<ÿR8=ÿR8=ÿR8=ÿS8>ÿS9?ÿS9?ÿT9?ÿT9?ÿT9@ÿT9@ÿT9@ÿU:@ÿU;@ÿU;@ÿU;@ÿU;@ÿU;AÿU;AÿU;AÿU;AÿU;AÿV;@ÿT:?ÿaHMÿ°¡ŸÿçØ¬ÿãÉbÿßÃMÿàÄPÿàÅQÿâÈ[ÿæÌmÿæÍoÿë×�ÿëÖ‰ÿãÇ[ÿãÈ]ÿäÉ]ÿäÉ^ÿäÉ_ÿåÉaÿåÊaÿæÎjÿéÙœÿÔÂyÿιdÿκfÿϺhÿϺhÿ͹hÿÍ»wÿÔÄ™ÿĶ¥ÿ”…ƒÿ]KMÿ?+.ÿ:&(ÿ<'*ÿ=)+ÿ>*,ÿ>+-ÿ>,.ÿ>,.ÿ>,.ÿ?+-ÿ@*-ÿB)+ÿB(+ÿB(*ÿB)+ÿA)+ÿ@*,ÿ@*-ÿ?*-ÿ?+-ÿ@+-ÿA+.ÿA+.ÿA+.ÿA,.ÿA,-ÿA,-ÿA+-ÿ@+-ÿA+-ÿA,-ÿA+.ÿ@+.ÿA+-ÿ@*-ÿ@*,ÿ@*,ÿ?*,ÿ>)+ÿ>(+ÿ>(*ÿ>(*ÿ=')ÿ=()ÿ<'(ÿ;')ÿ;'(ÿ:'(ÿ:''ÿ9&'ÿ9%'ÿ9%'ÿ8$&ÿ8$&ÿ7#%ÿ6"$ÿ7"$ÿ7!#ÿ7!#ÿ7 "ÿ8!ÿ8 ÿ8!ÿ6 "ÿ5!#ÿ4"#ÿ4#$ÿ3#$ÿ3#$ÿ3#$ÿ3"#ÿ3!"ÿ3 "ÿ2 !ÿ1 ÿ0ÿ/ÿ4#$ÿG56ÿlY[ÿ—}Žÿº“ÁÿÕ­åÿ׳ãÿÛ·íÿÑžñÿË—ñÿÇ–òÿÄ•ôÿÁ•õÿÀ•öÿ¾”öÿ½”öÿ¼”÷ÿ½•÷ÿ½—÷ÿ¾™÷ÿÀŸäÿ“y�ÿR>;ÿ?**ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ?*,ÿ?*+ÿ@++ÿ@++ÿA++ÿA++ÿA++ÿA++ÿ@++ÿ@++ÿA+,ÿA*,ÿA*+ÿA++ÿA++ÿA++ÿA++ÿA++ÿA++ÿA++ÿA+,ÿA,-ÿA,-ÿA,-ÿA--ÿE00ÿX=?ÿF//ÿC,,ÿC,,áC,-C,-C-1C-1D.1áD.1ÿO8;ÿ~eiÿO9<ÿE03ÿF14ÿG14ÿH15ÿH25ÿH25ÿI25ÿI35ÿJ36ÿJ36ÿK36ÿK37ÿL38ÿL49ÿM49ÿM49ÿN5:ÿN5:ÿN6;ÿO7;ÿO7;ÿO7;ÿO7;ÿP8;ÿQ7<ÿQ7<ÿR8<ÿR8=ÿR8=ÿS8=ÿS8>ÿS9>ÿT9>ÿT9?ÿT9@ÿT9@ÿT:@ÿU:@ÿU:@ÿU:AÿU:AÿU;AÿV;AÿV;AÿV;AÿV;AÿV;AÿV;AÿV;AÿV;AÿV;AÿT9?ÿiPVÿ¼­¨ÿéÙ§ÿãÉ`ÿàÄPÿàÅRÿáÆTÿãÊaÿæÍpÿçÑzÿîÞžÿäËeÿäÉ]ÿäÉ^ÿäÉ_ÿåÉ`ÿåÊaÿåËdÿêÙ’ÿÚɇÿθdÿκfÿϺgÿϺiÿÏ»jÿ̸hÿȵfÿÉ·kÿп�ÿÓÅŸÿÀ³¤ÿ”†…ÿ_NPÿ@-0ÿ9%(ÿ:&(ÿ<(*ÿ=)+ÿ>*,ÿ>+-ÿ>+-ÿ>+.ÿ>,.ÿ>+.ÿ?+,ÿ@)+ÿ@(*ÿA()ÿA'*ÿ@'*ÿ@(*ÿ@(*ÿ@(+ÿ@(+ÿ?(+ÿ?)+ÿ>)+ÿ>)+ÿ>)+ÿ>)+ÿ>)+ÿ>**ÿ>)+ÿ=),ÿ=)+ÿ=(+ÿ=(*ÿ=(*ÿ<(*ÿ<')ÿ;')ÿ;&(ÿ;&(ÿ:%'ÿ:%'ÿ9%&ÿ9%&ÿ8$&ÿ7$%ÿ8$%ÿ8$%ÿ8#$ÿ8"$ÿ8"#ÿ9!#ÿ9!#ÿ8 "ÿ8 !ÿ8 "ÿ7!"ÿ6!#ÿ5"#ÿ5"$ÿ4#%ÿ4$%ÿ3#%ÿ4#$ÿ4"#ÿ4"#ÿ3!"ÿ3 !ÿ2 !ÿ1 ÿ0ÿ/ÿ3"#ÿ@//ÿ[FIÿƒgpÿ°Š�ÿÕªÇÿâ¸Þÿá¸æÿà½íÿèÔóÿàÁôÿײôÿÒ­õÿΨõÿÊ¢öÿÆž÷ÿÁ™÷ÿ¿–öÿ¿–öÿ¿–öÿ¾–÷ÿ¾˜÷ÿÀŸäÿ“yŽÿT?>ÿ?**ÿ?++ÿ@++ÿ@++ÿ@++ÿ@++ÿ@++ÿ?++ÿ?*+ÿ?*+ÿ@++ÿ@++ÿA++ÿA++ÿA++ÿ@++ÿ@++ÿ@++ÿA*,ÿA*+ÿA*+ÿA++ÿA++ÿA++ÿ@++ÿ@++ÿA++ÿA+,ÿA,-ÿA,-ÿA,-ÿA,-ÿD/0ÿW=?ÿF//ÿC,,ÿC,,áC,,C,,D.1D.1D.1áD.1ÿO8;ÿ}fiÿO9<ÿF03ÿG14ÿG14ÿH25ÿH25ÿI25ÿI35ÿJ36ÿJ36ÿK36ÿK37ÿL37ÿL48ÿM48ÿM49ÿM5:ÿN5:ÿN5;ÿO6;ÿO7;ÿO7<ÿO7;ÿO8;ÿP7<ÿQ7<ÿR8<ÿR8=ÿR8=ÿS8=ÿS9>ÿS9>ÿT9>ÿT9?ÿT9?ÿT:@ÿT:@ÿT:AÿU:AÿU:AÿV:AÿV:AÿV;AÿV),ÿ>(*ÿ?'*ÿ?&)ÿ@&(ÿ@%(ÿ@&(ÿ@&(ÿ@&(ÿ?&(ÿ?&(ÿ>&(ÿ=''ÿ=''ÿ=&)ÿ=&(ÿ<&(ÿ=&(ÿ=%(ÿ<%'ÿ<%'ÿ;$&ÿ;$&ÿ;$%ÿ:#%ÿ;#$ÿ:#$ÿ:"#ÿ:"#ÿ9!#ÿ9!"ÿ9!"ÿ9!"ÿ9!"ÿ8!#ÿ8"#ÿ7"$ÿ6#$ÿ5#%ÿ5$%ÿ4$&ÿ4$&ÿ4$%ÿ4#%ÿ4#$ÿ4"$ÿ4"#ÿ4!"ÿ3 !ÿ2 ÿ1ÿ0ÿ0ÿ4"#ÿ@//ÿXEGÿ}ckÿ¦�’ÿÉ–³ÿÚ�ÇÿÚšÍÿÓ“ÍÿÎ�ÎÿË’ÐÿÖ±àÿÕºèÿÕ°æÿÎ¥ãÿЫæÿÒ±êÿÔµíÿÕ¸ðÿÖºòÿÖºôÿÕ¹õÿѵ÷ÿαøÿÇ©æÿ“yŽÿT>=ÿ?*+ÿ?*+ÿ?++ÿ?++ÿ?++ÿ@++ÿ@++ÿ@++ÿ?++ÿ?*+ÿ?*+ÿ?*+ÿ@++ÿA++ÿA++ÿA++ÿ@++ÿ@++ÿ@++ÿ@++ÿA*+ÿA*+ÿA*+ÿA++ÿA++ÿA++ÿ@++ÿ@++ÿA++ÿA,,ÿA,-ÿA,-ÿA,-ÿD/0ÿV=?ÿF//ÿC,,ÿC,,áC,,C,,D.1D.1D.2ßD.1ÿN8;ÿ}eiÿP:=ÿF03ÿG14ÿH15ÿH25ÿI25ÿI35ÿJ35ÿJ36ÿJ36ÿK37ÿK37ÿK47ÿL48ÿM48ÿM59ÿN5:ÿN5:ÿO5;ÿO6;ÿO6<ÿO7;ÿO8;ÿP7<ÿP7<ÿQ8=ÿR8=ÿR8=ÿS8>ÿS9>ÿT9>ÿT9>ÿT9?ÿT:?ÿT:?ÿT:@ÿT:AÿU:AÿU:AÿU;AÿV;AÿV;AÿW;AÿW;AÿWÿF03ÿG14ÿH25ÿH25ÿI25ÿI35ÿJ36ÿJ36ÿK36ÿJ37ÿK37ÿK48ÿL48ÿM49ÿN59ÿN59ÿO5;ÿO6;ÿO6<ÿO6;ÿO7;ÿP7<ÿP7<ÿQ8<ÿQ8=ÿR8=ÿS8>ÿS9>ÿT9>ÿT9?ÿT9?ÿT:?ÿT:?ÿT:@ÿU:@ÿU:@ÿU;AÿU;AÿV;AÿV;AÿW;AÿW;AÿW;AÿW;BÿWÿR9>ÿS9>ÿT9?ÿT9?ÿT:?ÿT:@ÿT:@ÿU:@ÿU;@ÿU;AÿV;AÿV;AÿV;AÿV;BÿW**ÿ?++ÿ?++ÿ@*+ÿ@**ÿ?**ÿ?*+ÿ?*+ÿ?++ÿ?++ÿ?++ÿ@++ÿ?*+ÿ?**ÿ?**ÿ?**ÿ@*+ÿ@*+ÿ@*+ÿ@++ÿ@++ÿ@++ÿ@++ÿ@**ÿ@**ÿ@**ÿ@*+ÿA*+ÿA*+ÿ@*+ÿ@++ÿ@++ÿ@,,ÿ@,,ÿA,,ÿA,,ÿF01ÿUÿR9>ÿS9>ÿS9?ÿT:?ÿT:?ÿT:@ÿU:@ÿU;@ÿU;AÿV;AÿV;AÿV;AÿV,.ÿ8&(ÿ5#%ÿ5#$ÿ5"$ÿ6#%ÿ7#%ÿ7#%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ7$%ÿ7$%ÿ7$%ÿ7$%ÿ6#%ÿ6#$ÿ6#$ÿ6"$ÿ6"#ÿ5"#ÿ5"#ÿ4!"ÿ4!"ÿ3!"ÿ2 !ÿ1 ÿ0 ÿ0 ÿ0ÿ1 !ÿ4##ÿ:))ÿC23ÿQ?AÿdQTÿ{emÿ•xˆÿ¯‹¥ÿÆ™ÀÿÖ¡Õÿè½åÿã¨ÒÿÜ•ÊÿÙ’Êÿ×�ÊÿÕ�ÊÿÔ�ËÿÒ�ËÿÐ�ÌÿÏ�ÍÿÎ�ÎÿÌ�ÎÿÊŽÏÿÉŽÏÿÈ�ÑÿÕ®ßÿ¾”ÝÿªvÕÿ¨vÔÿ¤rÎÿ©zÏÿбäÿÉ�àÿÖßÿÁ–àÿÁ–àÿÄžÝÿ¯�²ÿpX^ÿD//ÿ=()ÿ?++ÿ?++ÿ?++ÿ?++ÿ@**ÿ?**ÿ?**ÿ?*+ÿ?*+ÿ?++ÿ?++ÿ?++ÿ?*+ÿ?**ÿ?**ÿ?**ÿ@**ÿ@*+ÿ@*+ÿ@*+ÿ@++ÿ@++ÿ@++ÿ@*+ÿ@**ÿ@**ÿ@**ÿ@*+ÿA*+ÿ@*+ÿ@*+ÿ@++ÿ@++ÿ@,,ÿ@,,ÿ@,,ÿG11ÿT;>ÿD-.ÿB+,ÿB+,ÍB+,B+,D.0D.0 E/1ÁE/2ÿI25ÿ{cgÿZCGÿE/4ÿG15ÿH25ÿI25ÿI35ÿJ36ÿK36ÿK37ÿK37ÿK48ÿL48ÿL48ÿL59ÿM59ÿM5:ÿN6:ÿO6;ÿO6;ÿO7;ÿP7<ÿP7<ÿQ8=ÿQ8=ÿR7=ÿR8>ÿS9>ÿS9?ÿS:?ÿT:?ÿT:@ÿU:@ÿU;@ÿU;AÿV;AÿV;AÿV;BÿW**ÿ?++ÿ?**ÿ?**ÿ?**ÿ?**ÿ?*+ÿ?*+ÿ?++ÿ?++ÿ>++ÿ?**ÿ?**ÿ?**ÿ?**ÿ@**ÿ@*+ÿ@*+ÿ?*+ÿ@++ÿ@++ÿ@*+ÿ@**ÿ@**ÿ@**ÿ@**ÿ@*+ÿ@*+ÿ@*+ÿ@*+ÿ@++ÿ@,,ÿ@,,ÿ@,,ÿH22ÿT;=ÿC,-ÿB+,ÿB+,ÀA+, A+,D01C/0E/2²E/2ÿG03ÿx`dÿ_HLÿE/3ÿG15ÿH15ÿI25ÿJ35ÿJ36ÿK36ÿJ37ÿK37ÿK48ÿL48ÿL59ÿM59ÿM5:ÿN6:ÿN6:ÿO6;ÿO7;ÿP7;ÿP7;ÿQ8<ÿQ8=ÿR7=ÿR8>ÿS8>ÿS8?ÿS9?ÿT:?ÿT:@ÿT:@ÿT;@ÿU;AÿV;AÿV;AÿW()ÿ>**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?*+ÿ?++ÿ>++ÿ>**ÿ?**ÿ?**ÿ?**ÿ@**ÿ@**ÿ@**ÿ?*+ÿ?*+ÿ@++ÿ@*+ÿ@**ÿ@**ÿ@**ÿ@**ÿ@**ÿ@**ÿ@*+ÿ@*+ÿ@*+ÿ@,,ÿ@,,ÿ@,,ÿI34ÿR:<ÿB,,ÿB++ÿB+,±B++B++C.0+" E/2šF/2ÿF/2ÿrZ^ÿgPTÿF03ÿG14ÿH15ÿH25ÿI26ÿJ36ÿK37ÿJ37ÿK47ÿK48ÿL48ÿL59ÿM59ÿN5:ÿN6:ÿO6;ÿO6;ÿO7;ÿP7;ÿQ7;ÿQ8<ÿR8=ÿR7>ÿR8>ÿS8>ÿS8?ÿT9?ÿT:@ÿT:@ÿT;@ÿU;AÿU;AÿV;BÿW))ÿ?**ÿ?**ÿ?**ÿ?*+ÿ>*+ÿ>**ÿ>**ÿ?**ÿ?**ÿ@**ÿ@**ÿ@**ÿ?**ÿ?*+ÿ?*+ÿ@*+ÿ@**ÿ@**ÿ@**ÿ@**ÿ@**ÿ?**ÿ?**ÿ@*+ÿ@*+ÿ@+,ÿ@,,ÿ@,,ÿL57ÿP8:ÿA+,ÿB++ÿB++˜U@HB+,E03F/2E/2~F/2ÿE/2ÿkSWÿpX\ÿF03ÿH14ÿH25ÿI25ÿI26ÿJ36ÿJ37ÿK37ÿK48ÿL48ÿL49ÿM59ÿM5:ÿN6:ÿN6:ÿO6;ÿO7;ÿO7;ÿO7;ÿP8<ÿQ8<ÿR7=ÿR8=ÿS8>ÿS8?ÿT9?ÿT9@ÿT9@ÿT:@ÿU;AÿU;AÿU;BÿV()ÿ?**ÿ?**ÿ>*+ÿ>**ÿ>**ÿ>**ÿ?**ÿ@**ÿ@**ÿ@**ÿ?**ÿ?**ÿ?*+ÿ?*+ÿ@**ÿ@**ÿ@**ÿ@**ÿ@**ÿ@**ÿ?**ÿ?**ÿ@*+ÿ@+,ÿ@+,ÿ@+,ÿN79ÿM67ÿ@+,ÿA++ÿB++|A++C--C00F/2E/2aF/2þE/2ÿaJNÿxaeÿH25ÿH15ÿH25ÿI26ÿI26ÿJ36ÿJ27ÿK37ÿK48ÿL48ÿL59ÿM59ÿM5:ÿN6:ÿO6;ÿO6;ÿO7;ÿO7;ÿP8;ÿP8<ÿQ7<ÿR8=ÿS8=ÿS8>ÿT9?ÿT9@ÿT9@ÿT:@ÿT:AÿU;AÿU;BÿVEÿY>DÿY=DÿY=DÿY=DÿX=CÿXCÿ}hlÿ»­¬ÿäÚÊÿÚÊ‹ÿ͹[ÿË·Uÿ͹^ÿÏ»gÿнmÿоnÿоpÿоqÿ˺oÿɹnÿɺoÿʺpÿÊ»qÿÊ»rÿË»sÿË»tÿ˼vÿ˼uÿÕÉ�ÿôíÑÿöèÃÿõæ»ÿóå°ÿòã©ÿñá¤ÿñߟÿðÝ›ÿðÚ—ÿð×”ÿðÕ“ÿðÔ“ÿðÒ”ÿðÑ•ÿðЖÿñϘÿñΚÿñÍ›ÿñÌ�ÿòËžÿôѬÿõײÿïÀˆÿñÉœÿê˳ÿÚ¬‘ÿÙ¨ŽÿÙ§�ÿÚ¦‘ÿÚ¥’ÿÚ¤”ÿÚ¢•ÿÚ¢–ÿÙŸ–ÿÒ™–ÿÉŒ¤ÿƬÿĆ®ÿÅ…¯ÿѱÿÅ�±ÿÔŸÄÿì¸Òÿé Åÿé ÇÿéŸÈÿé�Éÿí¯Õÿñ»çÿëšâÿê˜âÿè—äÿæ—äÿå–äÿä–åÿâ–æÿà–æÿÞ•çÿÝ•çÿÛ•èÿÚ•éÿØ”êÿâ³íÿÙ£ÔÿÐŽËÿÏ�ÍÿÎ�ÍÿÌ�ÎÿÊŽÏÿÉŽÏÿÉŽÏÿÕ§Ùÿϧßÿµ}Òÿ²{Òÿ°{Óÿ®{Ôÿ¬zÕÿ§yÑÿ«‚Ïÿ¥„µÿ~fuÿQ;<ÿ<&'ÿ:%&ÿ:%&ÿ:%'ÿ:$'ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ:$&ÿ:%'ÿ:$'ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ:$&ÿ;%'ÿ='(ÿ>)*ÿ>)*ÿ>**ÿ>**ÿ>**ÿ?**ÿ@**ÿ@**ÿ?**ÿ?**ÿ?**ÿ?*+ÿ?)*ÿ@**ÿ@**ÿ@**ÿ@**ÿ@**ÿ?**ÿ?**ÿ?**ÿ@+,ÿ@+,ÿ@+,ÿQ9;ÿI34ÿ@+,ÿA++þA++_A++C++F.1E.1?F/2ôE/2ÿW@DÿgkÿM6:ÿH15ÿH25ÿI26ÿI36ÿJ37ÿK27ÿK38ÿK48ÿL48ÿM59ÿM59ÿN6:ÿN6:ÿO6;ÿO7;ÿO7;ÿO7;ÿP8<ÿP8<ÿQ7=ÿR8=ÿS8=ÿS8>ÿT9?ÿT9@ÿT9@ÿT:AÿU:AÿU:AÿV;BÿVEÿZ>EÿZ>FÿZ>FÿZ>FÿZ>Fÿ[>Fÿ[=FÿZ=EÿZ=EÿZ>EÿZ>EÿY>DÿY=DÿY=DÿX=CÿX=CÿX)*ÿ>**ÿ?**ÿ?**ÿ@**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?)*ÿ?)*ÿ?)*ÿ@**ÿ@**ÿ@**ÿ?**ÿ?**ÿ?**ÿ?++ÿ?+,ÿB-.ÿS:=ÿF01ÿ@+,ÿA++óA++=A++E/2E/2"F03áF03ÿN8<ÿ€hlÿU>AÿG14ÿI25ÿI26ÿJ35ÿJ26ÿK27ÿJ38ÿK38ÿL49ÿM59ÿM5:ÿN6:ÿN6;ÿO6;ÿO7;ÿO7;ÿP7;ÿP8<ÿQ7<ÿQ8=ÿR8=ÿR8>ÿT9>ÿT9?ÿT9?ÿT:@ÿU:AÿU:AÿV;BÿV;BÿV;BÿW=BÿW=BÿX=CÿX=CÿY=CÿY=DÿY=DÿZ=DÿZ>EÿZ>EÿZ>EÿZ>Eÿ[>Eÿ[>Eÿ[>Fÿ[>Fÿ[>Fÿ[>Fÿ[>Fÿ[>Fÿ[=FÿZ=EÿZ>EÿZ>EÿY>DÿY=DÿY=DÿX=CÿX))ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?**ÿ?))ÿ?)*ÿ?)*ÿ?)*ÿ@**ÿ@**ÿ?**ÿ?**ÿ?**ÿ?++ÿ?++ÿD.0ÿT:=ÿC-.ÿ@+,ÿA++àA++ A++D/1C/2 F03ÁF03ÿI26ÿ{cgÿaJNÿG14ÿI26ÿI25ÿJ35ÿJ26ÿK27ÿJ38ÿK38ÿL49ÿM59ÿN5:ÿN6:ÿO6;ÿO7;ÿO7;ÿO7;ÿP8<ÿP8<ÿQ7=ÿQ8=ÿR8=ÿR8>ÿS9>ÿT9?ÿT:?ÿT:@ÿU:AÿU;BÿV;BÿV;BÿW;BÿWEÿZ>Eÿ[>Eÿ[>Fÿ[>Fÿ[>Fÿ[>Fÿ[>Fÿ[>Gÿ[>Gÿ[>Gÿ[>Gÿ[>Fÿ[>Fÿ[>Fÿ[=EÿZ>EÿZ>EÿZ>DÿY=DÿY=DÿX=CÿX)*ÿ?**ÿ?**ÿ?**ÿ?))ÿ?))ÿ?)*ÿ?)*ÿ?)*ÿ@**ÿ?**ÿ?**ÿ?**ÿ?++ÿ?++ÿH23ÿQ8;ÿA,-ÿ@+,ÿA*+ÀA++ A++D/2V5:F03”F03ÿF03ÿoW[ÿpX]ÿG14ÿI26ÿI25ÿJ36ÿJ26ÿK36ÿK37ÿK38ÿL49ÿL49ÿM5:ÿN6:ÿO6;ÿO7;ÿO7;ÿO7;ÿP8<ÿP8<ÿQ8=ÿR8=ÿR8>ÿS9>ÿS9?ÿT9?ÿT:@ÿU:@ÿU:@ÿV;BÿV;BÿW;BÿWEÿZ>Eÿ[>Eÿ[>Fÿ[>Fÿ[?Fÿ\?Fÿ\?Fÿ\?Fÿ\?Fÿ\?Fÿ\?Gÿ\?Gÿ[?Gÿ[>Gÿ\>Gÿ[>Fÿ[>Fÿ[=FÿZ>EÿZ>EÿY>DÿY=DÿY=DÿX=CÿX))ÿ?**ÿ?)*ÿ?))ÿ?))ÿ?)*ÿ?)*ÿ?)*ÿ?**ÿ?**ÿ?**ÿ?++ÿ?++ÿL57ÿL57ÿ?++ÿ@+,ÿA*+’D.5@**J)F03E03aF03þE03ÿ_HLÿ}eiÿK58ÿI26ÿI35ÿJ36ÿK26ÿJ37ÿK37ÿK38ÿL49ÿL4:ÿM5:ÿN6;ÿO6;ÿO7;ÿO7;ÿP8;ÿP8<ÿQ7<ÿQ8=ÿR8=ÿR8>ÿS9>ÿS9?ÿT9?ÿT:@ÿU:@ÿU;AÿV;AÿW;BÿWEÿY>EÿZ>EÿZ>Fÿ[?Fÿ\?Fÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ[>Gÿ\>Gÿ\>Fÿ[>Fÿ[=FÿZ=EÿZ>EÿY>DÿY=DÿX=CÿX=CÿX((ÿ?))ÿ?))ÿ?)*ÿ?)*ÿ>)*ÿ?**ÿ?**ÿ?**ÿ@,,ÿQ8;ÿG12ÿ?++ÿ@++ýA*,_A+,\6*B77E/2E/20F03ëE03ÿP:>ÿ‚jnÿV?BÿH15ÿJ35ÿJ26ÿK26ÿJ37ÿK37ÿK48ÿL48ÿL49ÿM5:ÿN5;ÿN6;ÿO7;ÿO7;ÿP8<ÿP8<ÿQ7=ÿQ8=ÿR8>ÿR8>ÿS9>ÿT9?ÿT:?ÿT:@ÿT:@ÿV;AÿV;AÿW;BÿWEÿZ>EÿZ>FÿZ?Fÿ[?Fÿ\?Gÿ\?Gÿ]?Gÿ]@Gÿ\@Gÿ\@Hÿ\@Gÿ]@Gÿ]?Gÿ\?Gÿ\?Gÿ\?Gÿ[?Gÿ\>Gÿ\>Fÿ[>Fÿ[=EÿZ=EÿZ>EÿY=DÿY=DÿX=CÿX'(ÿ?))ÿ?))ÿ>)*ÿ>)*ÿ?**ÿ?**ÿC./ÿR:<ÿB-.ÿ?++ÿ?++ê@++/@++5'*D/1D.1 F03ÂF14ÿH26ÿybfÿfPSÿH14ÿJ35ÿJ26ÿK26ÿJ37ÿK37ÿK48ÿL48ÿM49ÿM5:ÿN5;ÿN6;ÿO6;ÿO7;ÿP8<ÿP8<ÿQ7=ÿR8=ÿR8>ÿS9>ÿS9?ÿT9?ÿT:@ÿT:@ÿT:AÿU;AÿV;BÿWFÿZ?Fÿ[?Gÿ[?Gÿ\?Gÿ\@Hÿ\@Hÿ\@Hÿ\@Hÿ\@Hÿ\@Hÿ\@Hÿ\@Hÿ]@Gÿ]?Gÿ\?Gÿ\?Gÿ[?Gÿ\>Gÿ[>Fÿ[>FÿZ=EÿZ=EÿY>DÿY=DÿX=CÿX=CÿX)*ÿ>)*ÿ>**ÿI34ÿP8:ÿ?++ÿ?++ÿ?++À@,+ @,+B04J25E04†F14ÿE03ÿfPTÿzcfÿJ37ÿJ35ÿJ26ÿK36ÿJ37ÿK37ÿL48ÿL48ÿM49ÿM59ÿN5:ÿN6;ÿO6;ÿO7;ÿP8<ÿQ8<ÿQ8=ÿR8=ÿR8>ÿS9>ÿS9?ÿT9?ÿT:@ÿT:@ÿU;AÿU;AÿV;BÿWFÿ[?Fÿ[?Gÿ\?Gÿ\@Hÿ\@Hÿ]@Hÿ]@Hÿ]@Iÿ]@Iÿ]@Iÿ]@Hÿ]@Hÿ\@Hÿ\@Hÿ]?Gÿ\?Gÿ\?Gÿ[>Gÿ[>Gÿ[>Fÿ[=FÿZ=EÿZ=EÿY=DÿY=DÿX=CÿXÿR6<ÿT9?ÿdKQÿ„ptÿ¯¡¡ÿÕɾÿéÞÂÿñä·ÿòá¦ÿñÝœÿðÚ�ÿñÛ£ÿòÚ§ÿöâÂÿõÑ´ÿóÆ¥ÿôŨÿôĨÿòœÿòÀ™ÿò¿›ÿò¿œÿò¾žÿó½Ÿÿó¼ ÿôº¢ÿôº£ÿô¹¥ÿë¶©ÿæ´¬ÿç²®ÿ籯ÿç°°ÿè±´ÿìÈÆÿÝ«ŸÿÚ¡–ÿÛ¡™ÿÛ šÿÜŸ›ÿÜž�ÿÝ�ŸÿÛšžÿÖ–›ÿÖ•œÿÖ“žÿ×’Ÿÿב¡ÿ×�¡ÿ×�£ÿ׎¤ÿÞ¡ºÿî»äÿì äÿì¥æÿñ¹ìÿè�àÿçŒàÿåŒàÿãŒàÿâŒáÿà‹âÿߊâÿ݉ãÿÛ‰äÿÚ‰åÿÚ‹åÿÞŽäÿâ“äÿã—åÿãœçÿä¤êÿç°íÿè½ëÿÛ¼Úÿ¾§¶ÿ�|€ÿaLNÿE12ÿ;%'ÿ:$&ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ9$&ÿ:$&ÿ:$&ÿ;$&ÿ;$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9%&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9$&ÿ8#&ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ9#%ÿ9#&ÿ9$&ÿ9#&ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ:#%ÿ:#%ÿ;%&ÿ<'(ÿ>)*ÿO7:ÿI34ÿ?++ÿ?++ÿ?++„=**A,,D-0F14E04CF14ôF04ÿS=AÿƒlpÿT>AÿI25ÿJ26ÿK36ÿK37ÿK37ÿL48ÿL48ÿM59ÿM59ÿN5:ÿN6;ÿO6;ÿO6;ÿO7<ÿQ7<ÿQ8=ÿR8=ÿR8>ÿS9>ÿS9?ÿT:?ÿT:@ÿT:@ÿU;AÿU;AÿV;BÿVFÿ[>Gÿ\?Gÿ\@Hÿ]@Hÿ]@Hÿ]@Iÿ]AIÿ^AIÿ^AIÿ^AIÿ]AIÿ]@Iÿ]@Hÿ\@Hÿ\@Hÿ]?Gÿ\?Gÿ\?Gÿ[>Gÿ[>Fÿ[>FÿZ=EÿZ=EÿY=DÿY=DÿX=CÿXÿS8>ÿQ6<ÿP6;ÿW>BÿlVZÿ�|ÿ¶¨¥ÿ×ʾÿéÜÃÿñà»ÿóÞ¯ÿòÛ©ÿõÞµÿ÷ÛÃÿôŨÿôÄ©ÿõêÿô¦ÿòÀ›ÿò¿œÿò¾�ÿó½Ÿÿó¼ ÿô»¡ÿôº£ÿô¹¤ÿî·¨ÿæ´¬ÿç³­ÿ籯ÿç±°ÿç°±ÿ箲ÿì¿Ãÿ廳ÿÛ —ÿÛ šÿÜŸ›ÿÜŸœÿÝ�žÿÝœŸÿÛ™ŸÿÖ•œÿÖ”�ÿ×’Ÿÿב ÿ×�¡ÿ×�£ÿ׎¤ÿÛ˜®ÿóÃÔÿø²×ÿìŸáÿé�åÿï¸ìÿëŸåÿå‹àÿäŒàÿâŒáÿá‹âÿß‹âÿÝŠãÿÜŠäÿÛŠåÿÝ‹äÿá�âÿã�âÿâ‘äÿã–åÿážãÿØ¡×ÿÙ¼ÿž€’ÿu^dÿS>?ÿ@*+ÿ:%&ÿ:%'ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ;$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ8#&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ:#%ÿ9#%ÿ9#%ÿ9#&ÿ9#&ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ:#%ÿ9#%ÿ9#%ÿ9#%ÿ>'+ÿO5:ÿA,-ÿ>*+ÿ?++ó?++A?++A++IIIE03E03F14ÊG15ÿH36ÿybfÿjSVÿH25ÿJ26ÿJ37ÿK37ÿK37ÿL48ÿL48ÿM59ÿM59ÿN5:ÿN6:ÿO6;ÿO7;ÿO7<ÿP7<ÿQ8=ÿR8=ÿR8>ÿS9>ÿT9?ÿT:@ÿT:@ÿT:AÿU;AÿU;BÿVFÿ[>Gÿ[>Gÿ\?Hÿ\?Hÿ]@Hÿ]AIÿ^AIÿ]AIÿ^AIÿ^AIÿ^AIÿ^AIÿ^AIÿ]AIÿ]@Hÿ\@Hÿ]@Gÿ\?Gÿ\?Gÿ[>Gÿ[>Gÿ[>Fÿ[=EÿZ=EÿZ=DÿY=DÿX=CÿXÿS8>ÿR8=ÿR7=ÿQ8<ÿO6:ÿO6:ÿX@DÿnX\ÿŽ|~ÿ²£¡ÿÑúÿåÖÄÿðÞÅÿøæÕÿ÷лÿöǯÿõĬÿõÁ¬ÿó¿¢ÿò¾œÿó½žÿó¼Ÿÿó»¡ÿôº£ÿô¹¤ÿñ¸¦ÿ絫ÿç³­ÿç²®ÿç±°ÿç°±ÿ篲ÿç®´ÿ鲺ÿìÆÆÿÝ¥žÿÜŸšÿÜŸœÿÜžžÿÝœŸÿÝ›¡ÿÚ˜ŸÿÖ”�ÿדžÿב ÿ×�¡ÿ×�¢ÿ×�¤ÿÙ‘¨ÿì»Ìÿü¼Õÿü¯Îÿô©×ÿé�äÿê©éÿî³ëÿä�àÿâŒáÿáŒâÿà‹âÿÞŠãÿ܉äÿÞ‹äÿã�âÿç”ãÿç›ãÿä¢áÿÛ¤ÕÿÆ�½ÿ¥‡—ÿ~gmÿ\HJÿE02ÿ;%'ÿ:$&ÿ;%'ÿ;&'ÿ;&'ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ9$'ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$%ÿ9$%ÿ9$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9$&ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ8"%ÿ8"%ÿ8#%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9"%ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ:#%ÿ9#%ÿ9#%ÿ9#%ÿD,/ÿI15ÿ:%(ÿ;&(ÿ=()È?*+?*+@@@E..H39F14‚G15ÿF14ÿbKOÿhkÿM69ÿI26ÿJ37ÿK37ÿK38ÿL48ÿL49ÿM59ÿM59ÿN5:ÿO6:ÿO6;ÿO7<ÿO7<ÿP7=ÿP8=ÿR8>ÿS9>ÿS9?ÿT9?ÿT:@ÿT:@ÿT:AÿU;AÿV;BÿVFÿ[>Gÿ\>Gÿ\?Hÿ]?Hÿ]@Iÿ^AIÿ]AIÿ^AIÿ^BIÿ_BIÿ_AIÿ^AIÿ^AIÿ^AIÿ]@Iÿ]@Hÿ\@Hÿ]?Gÿ\?Gÿ[?Gÿ[>GÿZ>FÿZ=FÿZ=EÿZ=EÿY=DÿY=DÿX=CÿXÿS9>ÿS9>ÿS8>ÿR8=ÿR7=ÿQ8<ÿQ8<ÿP7;ÿO6:ÿN49ÿO59ÿV>AÿhQUÿ‚oqÿ¢‘‘ÿ³±ÿÚÇÃÿèÎÇÿòÑÇÿ÷ÎÃÿ÷ɹÿõèÿô¿¢ÿô¼¡ÿôº¢ÿô¹£ÿó¸¥ÿ鵪ÿæ³­ÿç²®ÿç±°ÿç°°ÿ篲ÿç®´ÿç­µÿ謶ÿíÂÉÿã²®ÿÜžšÿÜž�ÿÝœŸÿÝ› ÿÞš¡ÿÚ—Ÿÿדžÿב ÿ×�¡ÿ×�¢ÿ×�¤ÿØŽ¥ÿå¯ÁÿûÂ×ÿü°Îÿû¯Ïÿù¯Ïÿï¦Úÿæžæÿíºîÿæ—äÿáŠâÿà‹âÿß�äÿá‘åÿæ™äÿé¢áÿä§ÙÿÕ¥Êÿ¾™±ÿž‚�ÿ{djÿ\HIÿG23ÿ=')ÿ:%'ÿ:%'ÿ;%'ÿ;%'ÿ:%'ÿ;&'ÿ;&'ÿ;%'ÿ;%&ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ9$'ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9#&ÿ9#%ÿ9$%ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ8#%ÿ8"$ÿ8"%ÿ8#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ8#%ÿ9#%ÿ9#%ÿ9"%ÿ9"%ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ:$&ÿK15ÿB+.ÿ9$&ÿ9$'ÿ9$'€8%(:!%F/0F04F045G15ëG15ÿN8<ÿ‚knÿ^HKÿH15ÿJ37ÿK37ÿK38ÿL48ÿL49ÿM59ÿN5:ÿN5:ÿO6;ÿO6;ÿO7<ÿO7<ÿP7=ÿP8=ÿQ8>ÿR9>ÿS9?ÿT9?ÿT:@ÿT:@ÿT;AÿU;AÿV;BÿVEÿ[>Gÿ\?Gÿ\?Hÿ]?Hÿ^@Iÿ]@Iÿ^AIÿ^BIÿ^BJÿ_BJÿ_BJÿ_BIÿ^AIÿ^AIÿ]AIÿ]@Hÿ\@Hÿ]?Gÿ\?Gÿ\?Fÿ[>FÿZ>FÿZ>FÿZ=EÿZ=EÿY=DÿY=DÿX=CÿXÿS9>ÿS8>ÿS8>ÿR7=ÿQ8<ÿQ8<ÿP7<ÿP7;ÿO6;ÿO6:ÿO5:ÿN48ÿM48ÿP7;ÿ[CGÿmX[ÿ†suÿ£‘’ÿ¾«¬ÿÓ½½ÿãÉÂÿíÍÀÿó̽ÿõɹÿöÄ´ÿî¾²ÿ踲ÿèµ°ÿè²°ÿç°°ÿ篱ÿ箳ÿç­´ÿ笶ÿ誷ÿë´ÁÿêÁÂÿÜŸžÿÝœžÿÝ› ÿÞš¡ÿÞš¢ÿÙ• ÿבŸÿ×�¡ÿ×�¡ÿ×�£ÿ×�¤ÿࢶÿ÷Ä×ÿü²Ïÿû¯Ïÿú¯Ïÿø¯Ðÿö¯Òÿì¦ßÿëµîÿìµìÿä�ãÿá¢àÿܦ×ÿÓ¥ÈÿÁœ²ÿ§‰˜ÿˆqxÿkVYÿT?@ÿD/0ÿ<')ÿ;%'ÿ;%'ÿ<&(ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ;%'ÿ;%&ÿ:%&ÿ:%'ÿ:%'ÿ:%'ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9#&ÿ9#%ÿ9#%ÿ8$%ÿ8$&ÿ8$&ÿ8$&ÿ8$&ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ8#%ÿ8"$ÿ8"$ÿ8"%ÿ9#%ÿ9#%ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ9#%ÿ9"%ÿ9"$ÿ9"%ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ8#%ÿ@(+ÿL16ÿ;&(ÿ9$&ÿ9$'ê9$'39$'<%'F04F/3G15®G25ÿG15ÿlVYÿybfÿK37ÿJ37ÿK37ÿK48ÿL48ÿL49ÿM59ÿM5:ÿN5:ÿO6;ÿO6;ÿO7<ÿO7<ÿP7<ÿQ8=ÿQ8>ÿR9>ÿS9?ÿT9?ÿT:@ÿT:@ÿU;AÿU;AÿV;BÿVEÿ[>Fÿ\?Gÿ]?Hÿ]?Iÿ^@Iÿ]@Iÿ^AIÿ^BJÿ_AJÿ_AJÿ_BJÿ_BJÿ_AIÿ^AIÿ^AIÿ]@Iÿ\@Hÿ\@Gÿ\?Gÿ\?Fÿ[>Fÿ[>FÿZ>FÿY=EÿY=EÿY=DÿY=DÿX=CÿXÿS9=ÿS8=ÿS8=ÿR8=ÿQ8=ÿQ8<ÿP7<ÿP7;ÿO6;ÿO6:ÿO6:ÿO5:ÿO69ÿN59ÿM48ÿK36ÿK26ÿN7:ÿV@CÿdORÿyfhÿ‘}ÿ§””ÿ»¨¦ÿÍ·µÿÖÀ¿ÿÞÄÄÿ䯯ÿçÅÇÿéÂÅÿê¿Äÿë¼Ãÿë¸ÂÿëµÁÿë²Àÿë°ÁÿðÈÑÿã­¯ÿߟ¤ÿßž¥ÿà�¦ÿà�§ÿÛ—¤ÿÙ•¤ÿÙ•¥ÿÙ•§ÿÚ•©ÿÞž²ÿóÉ×ÿýÁ×ÿü»Óÿù¾Õÿö¿ÔÿñÀÓÿë¾Ïÿß¹ÊÿϯÇÿ©ºÿ«� ÿ–}‡ÿimÿgSTÿT@AÿF23ÿ>)+ÿ;&(ÿ;&(ÿ<&(ÿ<')ÿ<&(ÿ<&(ÿ<&(ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ;%&ÿ:%&ÿ:%&ÿ:%'ÿ:%'ÿ9$'ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9#&ÿ9#%ÿ9#%ÿ8#%ÿ8$%ÿ8$&ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ9"%ÿ9#%ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ9"%ÿ9"$ÿ9"$ÿ9"%ÿ9"%ÿ9#%ÿ8#%ÿ9#%ÿH/3ÿE,0ÿ9$&ÿ9$&ÿ9$&¬:#&9#&E/6G15G04TG25øG15ÿS=@ÿ…mpÿZBFÿI26ÿK37ÿJ48ÿK48ÿL49ÿM59ÿN5:ÿN5:ÿO6;ÿO6;ÿO7<ÿO7<ÿP7<ÿQ8<ÿQ8=ÿR9>ÿR9?ÿS9?ÿT:@ÿT:@ÿU;AÿU;AÿV;BÿVEÿ[>Eÿ\>Fÿ\?Gÿ]?Hÿ]?Iÿ]@Iÿ]@Iÿ^AIÿ_AJÿ_AJÿ_BKÿ_AJÿ^BJÿ^BIÿ^AIÿ^AIÿ]@Iÿ\@Hÿ\@Hÿ\?Gÿ\?Fÿ[>Fÿ[>EÿZ>EÿY=EÿY=EÿX=DÿX=DÿX=CÿXÿS9=ÿS8=ÿR8=ÿR7=ÿQ8=ÿQ8<ÿP7;ÿP7;ÿO6;ÿO6:ÿO6:ÿN5:ÿN5:ÿN59ÿN59ÿM58ÿM48ÿL47ÿK26ÿI14ÿI14ÿJ25ÿM79ÿT?Aÿ_JMÿlXZÿ{gjÿŒy|ÿšˆ‹ÿ§”˜ÿ´ ¤ÿÀ©¯ÿȰ·ÿδ½ÿÔ¸ÂÿعÅÿÝÂÍÿÜÀÆÿÙ´¼ÿÙ´¼ÿÚ³½ÿÚ²½ÿÖ¯ºÿÔ­¹ÿÓ¬¸ÿÑ«·ÿΩµÿÒ¶¾ÿÓ¹Àÿʬ´ÿÀ¥«ÿ³šŸÿ¥Ž’ÿ•€ƒÿ„pqÿr^`ÿbNPÿT@AÿH45ÿA,-ÿ=()ÿ;&'ÿ<'(ÿ<')ÿ<')ÿ<')ÿ<')ÿ=')ÿ<')ÿ<&(ÿ<&(ÿ<&(ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:$'ÿ:$&ÿ:%&ÿ:%&ÿ:%&ÿ:%'ÿ9$'ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9#&ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ8$%ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8"%ÿ9"$ÿ9"$ÿ9"$ÿ9"$ÿ9"%ÿ8#%ÿ='*ÿK27ÿ<&(ÿ9$&ÿ9$&ø9$&S9$&9$)G03G04F04G15ÃH26ÿH25ÿqZ]ÿx`dÿK48ÿJ37ÿJ48ÿK48ÿK49ÿM59ÿN5:ÿN5:ÿO6;ÿO6;ÿO7<ÿO7<ÿP7<ÿQ8<ÿQ8=ÿR9>ÿR9?ÿS8?ÿS9@ÿT:@ÿU;AÿU;AÿV;BÿVEÿ[>Fÿ\?Gÿ]?Gÿ]?Hÿ^@Iÿ]@Iÿ^AIÿ^AJÿ_AJÿ_AJÿ_BJÿ^BJÿ^AIÿ^AIÿ^AIÿ]@Iÿ\@Hÿ\@Gÿ\?Gÿ\?Fÿ[>Fÿ[>EÿZ>EÿY=DÿY=EÿX=DÿX=DÿX=CÿXÿS9>ÿS8=ÿS8<ÿR8<ÿQ8<ÿQ8<ÿP7<ÿP7;ÿO6;ÿO6:ÿO6:ÿN5:ÿN5:ÿM49ÿM59ÿM58ÿM48ÿL47ÿK37ÿK36ÿK36ÿK25ÿJ35ÿI24ÿH03ÿG03ÿF/3ÿG04ÿI25ÿL58ÿQ:=ÿV@Cÿ]GIÿbMOÿhSVÿnZ\ÿs^aÿwdfÿyfgÿzgiÿ|ijÿ|hjÿzfhÿxdfÿuadÿp]_ÿkWZÿeRTÿ]IKÿWBDÿQ<>ÿJ57ÿE12ÿ@,-ÿ>)*ÿ=')ÿ<&)ÿ<')ÿ<')ÿ=()ÿ=()ÿ=()ÿ=()ÿ=()ÿ<')ÿ<')ÿ<')ÿ<')ÿ<')ÿ<&(ÿ<&(ÿ<&(ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:$'ÿ:$&ÿ9$&ÿ:%&ÿ:%&ÿ:%&ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9#&ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8$%ÿ8$%ÿ8#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8"%ÿ8"$ÿ9"$ÿ9"$ÿ9"$ÿ9"$ÿ9"%ÿG.3ÿE-1ÿ8#%ÿ9$&ÿ9$&Â9$&9$&9#$@4)I15G14eH15üH14ÿT>Aÿ…nqÿ\EHÿJ26ÿJ38ÿK48ÿK49ÿL59ÿM5:ÿN5:ÿO6;ÿO6;ÿO7<ÿO7<ÿP7<ÿP8<ÿQ8=ÿR9=ÿR9>ÿS8?ÿS9@ÿT9@ÿT:AÿU;AÿV;BÿVEÿZ>Fÿ\?Fÿ\?Gÿ]?Gÿ]@Hÿ]@Iÿ^@Iÿ^AIÿ^AJÿ_AJÿ^BJÿ^BIÿ^AIÿ]AIÿ]AIÿ]@Hÿ\@Hÿ]@Gÿ\?Gÿ\?Fÿ[>FÿZ>EÿZ>EÿY=DÿY=DÿX=DÿX=DÿX=CÿXÿS9>ÿR8=ÿR8<ÿR7<ÿQ8<ÿQ8<ÿP7;ÿP7;ÿO6;ÿO6:ÿO6:ÿN5:ÿN5:ÿM49ÿM49ÿM48ÿM48ÿL47ÿK37ÿK36ÿK36ÿK25ÿJ35ÿJ24ÿI25ÿI25ÿH15ÿG14ÿG04ÿG03ÿG/2ÿF.1ÿF.1ÿD-0ÿD,/ÿC,/ÿC,.ÿB,.ÿB,-ÿB,-ÿB,-ÿA+-ÿA+-ÿA+,ÿA*,ÿ@*,ÿ?),ÿ?)+ÿ?)+ÿ?(+ÿ?)+ÿ?)+ÿ?)+ÿ>)+ÿ>)*ÿ>)+ÿ>(*ÿ=(*ÿ=(*ÿ>'*ÿ>()ÿ=()ÿ=()ÿ=()ÿ<'(ÿ<'(ÿ<')ÿ<')ÿ;')ÿ;&(ÿ<&(ÿ<&(ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:$'ÿ:$&ÿ9$&ÿ9$&ÿ:%&ÿ:%&ÿ9$&ÿ9$&ÿ:$&ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ9$&ÿ9#&ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ9#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ8#%ÿ8#%ÿ8#%ÿ8"%ÿ8"$ÿ8"$ÿ8"$ÿ9"$ÿ9"$ÿ>&*ÿK06ÿ;%(ÿ8#%ÿ8$&û9$&c8$&H# F02G03G03H15ÆH25ÿI25ÿoW[ÿ|dhÿM59ÿJ37ÿK48ÿK49ÿL59ÿL5:ÿN5:ÿO6;ÿO6;ÿO7<ÿO7<ÿP7<ÿP8<ÿQ8=ÿR9=ÿR9>ÿS8>ÿS9@ÿT9@ÿT:AÿU;AÿV;BÿVEÿZ>Fÿ[>Fÿ\?Gÿ]?Gÿ]@Hÿ]@Hÿ]@Iÿ^@Iÿ^AIÿ^AIÿ^AIÿ^AIÿ]AIÿ^AIÿ]@Iÿ]@Hÿ\@Hÿ]?Gÿ\?Gÿ\?Fÿ[>FÿZ>EÿZ>EÿY=DÿY=DÿX=CÿX=CÿX=CÿWÿS9>ÿS9=ÿR8=ÿR8<ÿR7<ÿQ8;ÿQ8;ÿP7;ÿP7;ÿO6:ÿO6:ÿO6:ÿN5:ÿN5:ÿM49ÿM48ÿL48ÿL38ÿL47ÿL37ÿK36ÿK36ÿK25ÿJ35ÿJ25ÿI25ÿI24ÿH14ÿG14ÿG04ÿG03ÿH03ÿG/3ÿG/2ÿF/2ÿF.1ÿE.1ÿE-0ÿD.0ÿD./ÿD./ÿC./ÿC-/ÿB-/ÿB-.ÿB,.ÿB,-ÿA+-ÿA+-ÿA+-ÿA*,ÿ@*,ÿ?),ÿ?*+ÿ?*+ÿ>)*ÿ=)+ÿ=(*ÿ=(*ÿ=(*ÿ>'*ÿ>')ÿ=')ÿ=()ÿ=()ÿ<'(ÿ<'(ÿ<'(ÿ<')ÿ;')ÿ;&(ÿ;&(ÿ<&(ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:$'ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ:%&ÿ9$%ÿ:$%ÿ:$%ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ9#&ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ7#$ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ9#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8#%ÿ8#%ÿ8"%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ:#%ÿH.3ÿD+/ÿ8"%ÿ8#%ÿ8$&Ä8$&8$&:$&ÿÿG15G14`H15úH15ÿQ:>ÿ„mpÿdLPÿI26ÿK48ÿK49ÿL59ÿL59ÿM5:ÿN6:ÿO6;ÿO7;ÿO7<ÿP7<ÿP8<ÿQ8<ÿQ8=ÿR9=ÿS8>ÿS9?ÿT9@ÿT9AÿU:AÿU;BÿVEÿZ>FÿZ>Fÿ[?Gÿ\?Gÿ]?Gÿ]@Hÿ^@Hÿ]@Iÿ]@Iÿ]@Iÿ]@Iÿ]@Iÿ^@Iÿ]AIÿ]@Hÿ\@Hÿ\@Gÿ\?Gÿ\?Fÿ[?Fÿ[>FÿZ>EÿZ=EÿY=DÿY=DÿX=CÿX=CÿX=CÿWÿS9>ÿS8=ÿR8=ÿQ8<ÿQ7<ÿQ8;ÿQ8;ÿP7:ÿP7;ÿO6:ÿO6:ÿO6:ÿN5:ÿN59ÿM49ÿM49ÿL48ÿL37ÿK37ÿK37ÿK36ÿK36ÿK25ÿJ35ÿJ25ÿI25ÿI24ÿH14ÿG13ÿG04ÿG03ÿG03ÿG/2ÿG/2ÿF.2ÿF.1ÿE.1ÿE-0ÿD.0ÿD-/ÿD-/ÿC./ÿC-/ÿB-/ÿB-.ÿB,.ÿB,-ÿA+-ÿA+,ÿA+-ÿA*,ÿ@*,ÿ?*+ÿ?*+ÿ>*+ÿ>)*ÿ=)+ÿ=(*ÿ=(*ÿ=(*ÿ>'*ÿ=')ÿ=')ÿ=')ÿ=()ÿ<'(ÿ<'(ÿ<'(ÿ<'(ÿ;'(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:$'ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ:$%ÿ:$%ÿ:$%ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8#%ÿ9#%ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ7"$ÿ7#$ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ9#%ÿ8"%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ8"$ÿ8"%ÿ8"%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿA),ÿK16ÿ:$&ÿ8"$ÿ8"%ù8#&^7#&!#H/3G03F/3H15¸I25ÿH15ÿfORÿ„lpÿR;?ÿJ37ÿK48ÿL59ÿL59ÿM5:ÿM6:ÿN6;ÿO6;ÿO7<ÿP7<ÿP8<ÿQ8<ÿQ8=ÿR9=ÿR8>ÿS9>ÿT9?ÿT9@ÿU:AÿU:AÿV;BÿVEÿZ>Fÿ[>Fÿ[?Gÿ\?Gÿ]?Gÿ]@Hÿ]@Hÿ^@Iÿ^@Iÿ^@Iÿ]@Iÿ]?Iÿ]?Hÿ]@Hÿ\@Hÿ\?Gÿ[?Gÿ[?Fÿ[>Fÿ[>EÿZ>EÿY=DÿY=DÿX=CÿX=CÿX=BÿXÿS9>ÿR8=ÿR8=ÿQ8<ÿQ8<ÿP8;ÿP7;ÿP7:ÿO7;ÿO6:ÿO6:ÿO5:ÿN5:ÿN59ÿM49ÿM48ÿL48ÿK37ÿK37ÿK37ÿK36ÿK36ÿK25ÿJ35ÿJ25ÿI25ÿI24ÿH14ÿG13ÿG03ÿG03ÿG03ÿF/2ÿF/2ÿF.1ÿF.1ÿE.1ÿE-0ÿD.0ÿD-/ÿD-/ÿC-/ÿC-/ÿB-.ÿB,.ÿA,.ÿA,-ÿA+-ÿA+,ÿA*,ÿA*,ÿ@*,ÿ@*,ÿ?*+ÿ>)+ÿ>)*ÿ=)+ÿ=(*ÿ=(*ÿ=(*ÿ=')ÿ=')ÿ=')ÿ=')ÿ=')ÿ<'(ÿ<'(ÿ<'(ÿ<'(ÿ;'(ÿ;&(ÿ;&(ÿ;&(ÿ:&(ÿ;&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8#%ÿ9$%ÿ:$%ÿ:$%ÿ:$%ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#&ÿ8#%ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ7"$ÿ7"$ÿ7#$ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ;$&ÿK16ÿA)-ÿ8"$ÿ8"$ÿ8"$¶8#%8#%:$'K28I25H14GI25ðI25ÿM58ÿ|dhÿs[`ÿK48ÿK48ÿL49ÿL59ÿM5:ÿM6:ÿN6;ÿO6;ÿO7<ÿP7<ÿP8<ÿQ8<ÿQ8=ÿR9=ÿR9>ÿS8>ÿS9?ÿT9?ÿU:AÿU:AÿU:BÿVEÿZ>FÿZ>Fÿ[>Fÿ[?Gÿ\?Gÿ]?Gÿ]?Gÿ]?Hÿ]?Hÿ]?Iÿ]?Hÿ]?Hÿ\?Hÿ\?Hÿ\?Gÿ[?Gÿ[?FÿZ?FÿZ>FÿZ>EÿZ=EÿY=DÿY=DÿX=CÿX=CÿX=BÿXÿS9>ÿR8=ÿR8=ÿQ8<ÿQ8<ÿP8;ÿP7;ÿP7:ÿO7;ÿP6:ÿO6:ÿO5:ÿN5:ÿN59ÿM49ÿM48ÿL38ÿK37ÿK37ÿK26ÿK26ÿK26ÿK25ÿJ35ÿJ25ÿI25ÿI24ÿH14ÿG13ÿH03ÿG02ÿG03ÿF/2ÿF/2ÿF.1ÿF.1ÿE.1ÿE-0ÿD.0ÿD-/ÿD-/ÿC-/ÿC,/ÿB-.ÿB,.ÿA,.ÿA,-ÿ@+-ÿA+,ÿA*,ÿA*+ÿ@*,ÿ?*+ÿ?*+ÿ>)+ÿ>)*ÿ=)+ÿ=(*ÿ=(*ÿ=(*ÿ=')ÿ=')ÿ=')ÿ=')ÿ=')ÿ<&(ÿ<'(ÿ<'(ÿ<'(ÿ;&(ÿ;&'ÿ;&'ÿ;&(ÿ:&(ÿ:&(ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:$'ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8#%ÿ9$%ÿ:$%ÿ:$%ÿ:$%ÿ9$%ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7#$ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ8!$ÿ8!$ÿ8"$ÿ8"$ÿF-1ÿI/4ÿ8#%ÿ7"$ÿ8"$ï8"$E8#%7$(C./G03F/2I25•I25ÿI24ÿXADÿ‡otÿ`IMÿJ37ÿL49ÿL59ÿM5:ÿM6:ÿN6;ÿN6;ÿO7<ÿO7<ÿP7<ÿQ8<ÿQ8=ÿR9=ÿR9>ÿS8>ÿS9?ÿT9?ÿT:@ÿU:AÿU:BÿU;BÿVEÿZ>FÿZ>Fÿ[>Fÿ[?Gÿ[?Gÿ\?Gÿ]?Gÿ]?Gÿ]?Hÿ\?Hÿ\?Hÿ\?Gÿ\>Gÿ[>Gÿ[?GÿZ?FÿZ>FÿZ>EÿZ>EÿY=DÿY=DÿY=CÿX=CÿX=BÿX=BÿWÿS9>ÿR8=ÿR8=ÿQ8<ÿQ8<ÿP8;ÿO7;ÿO7;ÿO7;ÿP6:ÿO6:ÿO59ÿN5:ÿN59ÿM49ÿL48ÿL38ÿK37ÿK37ÿK26ÿK26ÿJ25ÿJ25ÿJ35ÿJ25ÿI25ÿH24ÿH14ÿG13ÿH03ÿG02ÿG02ÿF/2ÿF/2ÿE.1ÿE.1ÿE.1ÿD.0ÿD.0ÿD-/ÿD-/ÿC-/ÿC,/ÿB,.ÿB,.ÿA,.ÿA,-ÿ@+-ÿ@+,ÿA*,ÿA*+ÿ@*+ÿ?*+ÿ?*+ÿ>)+ÿ>)*ÿ=)+ÿ=(*ÿ=(*ÿ=(*ÿ=')ÿ<')ÿ<')ÿ=')ÿ=')ÿ<&(ÿ<&(ÿ<'(ÿ<'(ÿ;'(ÿ;&'ÿ;&'ÿ;&'ÿ:&(ÿ:&(ÿ:%'ÿ;%'ÿ:%'ÿ:%'ÿ:%'ÿ:$'ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ:$%ÿ9$%ÿ9$%ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#&ÿ8#%ÿ8#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7#$ÿ7#%ÿ8#%ÿ7"%ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7!#ÿ8!#ÿ8!#ÿ@(+ÿM27ÿ=&(ÿ7"$ÿ7"$ÿ7"$“9$%8#$9 #G04H15G14#I25ÓJ25ÿI25ÿiQTÿ…mqÿT=AÿK38ÿL59ÿM5:ÿM5:ÿN6;ÿN6;ÿO7<ÿO7<ÿP7<ÿP8<ÿQ8=ÿQ9=ÿR9>ÿS8>ÿS9>ÿT9?ÿT9?ÿU:@ÿU:AÿU:BÿU;BÿV;CÿWEÿZ>FÿZ>FÿZ>Fÿ[>Fÿ[?Fÿ\?Gÿ\?Gÿ\?Gÿ\?Gÿ\>Gÿ[>Gÿ[>Gÿ[>FÿZ>FÿZ>FÿZ>EÿY>EÿY=EÿY=DÿY=DÿX=CÿX=CÿX=BÿXÿS8>ÿS8=ÿR8=ÿR8<ÿQ7<ÿP8<ÿP8;ÿO7;ÿP7;ÿO6;ÿO6:ÿO6:ÿO59ÿN59ÿM59ÿM49ÿL48ÿL38ÿK37ÿK37ÿK26ÿK26ÿJ25ÿJ25ÿJ35ÿI25ÿI25ÿH14ÿH14ÿG13ÿH03ÿG02ÿG/2ÿF/1ÿF/2ÿE.1ÿD.1ÿD.0ÿD.0ÿD.0ÿD-/ÿD-/ÿC-/ÿC,/ÿB,.ÿB+.ÿA+-ÿA,-ÿ@+-ÿ@+,ÿ@*,ÿ@*+ÿ@*+ÿ?**ÿ?**ÿ>)+ÿ>)*ÿ=)+ÿ>(*ÿ=(*ÿ=(*ÿ=')ÿ<')ÿ<')ÿ<')ÿ=&)ÿ<&(ÿ<&(ÿ<&(ÿ<'(ÿ;&(ÿ;&'ÿ;&'ÿ;&'ÿ:&'ÿ:&(ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7#$ÿ8#%ÿ7#%ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7!$ÿ7!#ÿ;$&ÿL16ÿB*.ÿ8"$ÿ7"$ÿ7"$Ò7"$"7"$8#$I33A/4I25H25ZI25õJ36ÿM58ÿyaeÿzbgÿN6;ÿL49ÿL5:ÿM5:ÿN6:ÿN6;ÿO7;ÿO7<ÿP7<ÿP8<ÿQ8<ÿQ8=ÿR9=ÿR8>ÿS8>ÿS9?ÿT9?ÿU:@ÿU:@ÿU:AÿU;BÿV;CÿV;CÿW=BÿX=CÿX=CÿY=DÿX=DÿY=DÿY=EÿY>EÿZ>EÿZ>FÿZ>FÿZ>FÿZ>Fÿ[>Fÿ[>Fÿ[>Fÿ[>Fÿ[>Gÿ[>FÿZ>FÿZ=FÿZ=EÿY>EÿY=EÿX=DÿY=DÿX=CÿX=CÿX=BÿX=BÿWÿS8>ÿR7=ÿR7=ÿQ8<ÿQ7<ÿP8;ÿP8;ÿO7:ÿP7;ÿO6:ÿO6:ÿN6:ÿN59ÿN59ÿM48ÿM48ÿL48ÿL38ÿK37ÿK37ÿK26ÿK26ÿJ25ÿI25ÿI24ÿI25ÿI24ÿH14ÿH14ÿG13ÿH03ÿG02ÿG/2ÿF/1ÿE/1ÿE.1ÿD.1ÿD-0ÿD.0ÿD.0ÿD-/ÿD-/ÿC,/ÿC,/ÿB,.ÿB+.ÿA+-ÿ@+-ÿ@+-ÿ@+,ÿ@*,ÿ?*+ÿ@*+ÿ?**ÿ?**ÿ>)*ÿ>)*ÿ=)+ÿ=(*ÿ=(*ÿ=(*ÿ=')ÿ<')ÿ<')ÿ<')ÿ<&)ÿ<&(ÿ<&(ÿ<&(ÿ<&(ÿ;&(ÿ;&'ÿ;&'ÿ;&'ÿ:&'ÿ:&'ÿ:%'ÿ:%'ÿ9%'ÿ:%'ÿ:%'ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ9$%ÿ9$%ÿ9$%ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8#$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7!#ÿ8"$ÿH.3ÿH.2ÿ9"$ÿ8"$ÿ7"$ô7"$X7"$9##5##F25G04D/3H25“I36ÿJ25ÿS;?ÿƒkoÿnV[ÿL49ÿL59ÿM5:ÿM6:ÿN6;ÿN6;ÿO7<ÿP7<ÿP8<ÿQ8<ÿQ8=ÿR9=ÿR9>ÿS8>ÿS9?ÿT9?ÿT9@ÿU:@ÿU:@ÿU:BÿU;BÿV;CÿVEÿZ>EÿZ>EÿZ>EÿZ>Fÿ[>Eÿ[>Eÿ[>EÿZ>EÿZ=FÿZ=FÿZ=EÿY=EÿY=EÿX=DÿY=DÿY=CÿX=CÿX=CÿX=BÿXÿS8>ÿR7=ÿR7=ÿQ8<ÿQ8<ÿP8;ÿP7;ÿO7:ÿO7;ÿO6:ÿN6:ÿN69ÿN59ÿN58ÿM48ÿM48ÿL48ÿL38ÿK37ÿK27ÿK26ÿJ26ÿJ25ÿI25ÿI14ÿH15ÿH14ÿH14ÿH13ÿG13ÿH03ÿG02ÿF/2ÿF/1ÿE/1ÿE.0ÿD.0ÿD-0ÿC.0ÿC./ÿD-/ÿD-/ÿC,/ÿC,/ÿB,.ÿA+.ÿA+-ÿ@*-ÿ@*,ÿ@+,ÿ@*,ÿ?*+ÿ?*+ÿ?**ÿ?**ÿ>)*ÿ>)*ÿ=(+ÿ>(*ÿ=(*ÿ=(*ÿ=')ÿ<')ÿ<')ÿ<')ÿ<&)ÿ;&(ÿ<&(ÿ<&(ÿ<&(ÿ;%(ÿ;&'ÿ;&'ÿ;&'ÿ:&'ÿ:%'ÿ:%&ÿ:%'ÿ9%'ÿ9%'ÿ:%'ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ8$&ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ7"$ÿ7"#ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿ7!$ÿD+/ÿL16ÿ:#&ÿ7!#ÿ8!#ÿ7"$‘7"$7"$8#$H14H15H14I25ÄJ36ÿI25ÿ[CGÿˆptÿeMRÿK48ÿM5:ÿM6:ÿN6;ÿN6;ÿO7<ÿO7<ÿP7<ÿP8<ÿQ8<ÿQ8=ÿR9=ÿR8>ÿS8>ÿS9?ÿT9?ÿT:@ÿU:@ÿU:AÿU;BÿU;BÿV;CÿVEÿY=EÿZ=EÿZ=EÿZ=EÿZ=EÿY=EÿY=EÿY=EÿX=DÿY=DÿY=DÿX=CÿX=CÿW=BÿWÿS9?ÿS8>ÿR8>ÿR8>ÿR7=ÿR8=ÿQ7<ÿQ7<ÿP8;ÿO7;ÿO7;ÿO7;ÿO6:ÿN6:ÿN59ÿM59ÿM58ÿM48ÿM47ÿL47ÿL37ÿK37ÿK27ÿK26ÿJ26ÿJ25ÿI25ÿI15ÿH15ÿH14ÿH14ÿH13ÿG03ÿG02ÿG02ÿF/2ÿF/1ÿE/1ÿE.0ÿD.0ÿD-0ÿC.0ÿC./ÿC-/ÿC-/ÿC,/ÿB,/ÿB,.ÿA+.ÿA+-ÿ@*-ÿ@*,ÿ@*,ÿ@*,ÿ?*+ÿ?)+ÿ>**ÿ>**ÿ>)*ÿ>)*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ=')ÿ<')ÿ<')ÿ<')ÿ<&)ÿ;&(ÿ;&(ÿ<&(ÿ<&(ÿ;%'ÿ;%'ÿ;%'ÿ:&'ÿ:&'ÿ:%'ÿ:%&ÿ:%&ÿ9%'ÿ9%'ÿ9%'ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ8#%ÿ8#%ÿ9$%ÿ9$%ÿ8$%ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7"%ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ7!$ÿ7!#ÿ7"#ÿ7"$ÿ7"$ÿ7"$ÿ8"$ÿ8"$ÿ7"$ÿ7"$ÿ7"$ÿA),ÿN38ÿ=&)ÿ7!#ÿ7!#ÿ7!#Â7"#7"#7"$;11K77I35H25:I36áJ36ÿI26ÿdLOÿ‰quÿ_GLÿK49ÿM5:ÿN6:ÿN6;ÿO6;ÿO7<ÿP7<ÿP8<ÿP8<ÿQ8=ÿR9=ÿR9>ÿS8>ÿS9?ÿT9?ÿT9?ÿU:@ÿU:@ÿU:AÿU;AÿU;BÿV;CÿVÿS9>ÿS8>ÿR8>ÿQ7=ÿQ7=ÿQ8<ÿQ7<ÿP7;ÿP7;ÿO7;ÿP7;ÿO6;ÿO6:ÿN6:ÿN59ÿM59ÿM58ÿL48ÿL47ÿL37ÿK36ÿK37ÿK26ÿK26ÿJ26ÿJ25ÿI25ÿI15ÿH15ÿH14ÿG04ÿG03ÿH03ÿG02ÿG02ÿF/1ÿF/1ÿE.1ÿE.0ÿD.0ÿD-/ÿC./ÿC-/ÿC-/ÿC-/ÿC,/ÿB,/ÿB,.ÿA+.ÿA+-ÿ@*-ÿ@*,ÿ@*,ÿ@)+ÿ?*+ÿ?)+ÿ>**ÿ>**ÿ=)*ÿ=)*ÿ=()ÿ=()ÿ=(*ÿ='*ÿ=')ÿ<')ÿ<')ÿ<')ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;%'ÿ;%'ÿ;%'ÿ:%'ÿ:&'ÿ:%'ÿ:%&ÿ:%&ÿ9%&ÿ9%'ÿ9%'ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9#&ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ9$%ÿ8$%ÿ8$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7"%ÿ7"$ÿ6"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7!$ÿ7!#ÿ7!#ÿ7"#ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ?'+ÿO39ÿ@(+ÿ7!#ÿ7!#ÿ7!#à7!#97!#8!$5 F-4H/4I57I26]J36òJ26ÿK37ÿjRVÿˆptÿ\DIÿL49ÿM6:ÿN6;ÿN6;ÿO7<ÿO7<ÿP7<ÿP8<ÿP8=ÿQ8=ÿR9=ÿR9>ÿS8>ÿS9?ÿT9?ÿT9@ÿU:@ÿU:@ÿU:AÿU;AÿU;BÿV;CÿV;BÿWÿS9>ÿS8=ÿR8=ÿR8=ÿQ7=ÿQ7=ÿQ8<ÿQ7<ÿP7;ÿP6;ÿO6:ÿP7;ÿO6:ÿN6:ÿN69ÿM59ÿM59ÿL48ÿL48ÿK47ÿL37ÿK36ÿK36ÿK26ÿK26ÿJ25ÿJ25ÿI25ÿH15ÿH15ÿG04ÿG04ÿG03ÿG03ÿG02ÿG02ÿF/1ÿF/1ÿE.0ÿE.0ÿD.0ÿD-/ÿC./ÿC-/ÿC-/ÿB-/ÿB,/ÿB,.ÿB+.ÿA+.ÿA+-ÿ@*-ÿ@*,ÿ@*,ÿ@)+ÿ?)+ÿ?)+ÿ>**ÿ=**ÿ=)*ÿ=)*ÿ=()ÿ=()ÿ=()ÿ=')ÿ=')ÿ<')ÿ<')ÿ<')ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ:&(ÿ;%'ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:%&ÿ:%&ÿ:%&ÿ9%&ÿ9%&ÿ9%&ÿ9$&ÿ8$&ÿ8$&ÿ9$&ÿ9$&ÿ9#&ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8$%ÿ8$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7"%ÿ7"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7!$ÿ7!#ÿ7!#ÿ7!#ÿ7"#ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ='*ÿO49ÿC*.ÿ7!#ÿ7!#ÿ7!#ñ7!#[7!%7!"7!#H14G14D.1I26yJ36úJ37ÿL48ÿnV[ÿ‡osÿ[CHÿL49ÿN6;ÿN6;ÿO7;ÿO7<ÿP7<ÿP8<ÿP8<ÿP8=ÿQ9=ÿR9>ÿS8>ÿS9>ÿS9?ÿT9?ÿT9@ÿU:@ÿU:@ÿU:AÿU;AÿU;BÿV;CÿV;CÿWÿS9>ÿR8=ÿR8=ÿR7<ÿQ7=ÿP8<ÿP7<ÿP7<ÿP7;ÿO6;ÿO6;ÿO6;ÿO6:ÿN6:ÿN59ÿM59ÿM58ÿL48ÿL47ÿK47ÿK37ÿK36ÿK26ÿK25ÿJ25ÿJ25ÿI25ÿI24ÿH15ÿH14ÿG04ÿH04ÿG03ÿG/3ÿF/2ÿG/2ÿF/1ÿF/1ÿE.0ÿD.0ÿD./ÿC./ÿC./ÿC-/ÿC-/ÿB-/ÿB,/ÿA,.ÿA+.ÿA+.ÿA+-ÿ@*-ÿ@*,ÿ@),ÿ@)+ÿ?)+ÿ>)*ÿ>**ÿ=)+ÿ=)*ÿ<)*ÿ=()ÿ=()ÿ=()ÿ=')ÿ<')ÿ<')ÿ<')ÿ<')ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ:&(ÿ:%'ÿ;%'ÿ;%'ÿ:%'ÿ:%'ÿ:$&ÿ:%&ÿ9%&ÿ9%&ÿ9%&ÿ9$&ÿ9$%ÿ8$&ÿ8$&ÿ8$&ÿ9$&ÿ8#&ÿ8#%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ8$%ÿ8#%ÿ8#$ÿ8#$ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7"%ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7"$ÿ7"$ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7"#ÿ7"$ÿ6"$ÿ<')ÿN4:ÿE-1ÿ7!#ÿ7!#ÿ7!#ù7!#w7"$7!#7!"G14H25G25I26�J37ýK37ÿL49ÿqX]ÿ‡osÿ]DIÿL49ÿN6;ÿN6;ÿO7<ÿO7<ÿP7<ÿP8<ÿP8<ÿP8=ÿQ9=ÿR9>ÿS8>ÿS9>ÿT9?ÿT9?ÿT9@ÿU:@ÿU:@ÿU:AÿU;AÿU;BÿV;CÿV;CÿWÿS9>ÿS8=ÿR8=ÿR8=ÿQ7<ÿQ7<ÿP8<ÿP7<ÿO7;ÿP7;ÿO6:ÿP6;ÿO5;ÿO5:ÿN5:ÿN59ÿM59ÿM58ÿL48ÿK47ÿK37ÿK36ÿK36ÿK25ÿK25ÿJ25ÿJ24ÿI25ÿI15ÿH15ÿH14ÿG04ÿH03ÿG03ÿG/3ÿF/2ÿF.2ÿF/1ÿE/1ÿE.0ÿD.0ÿD-/ÿC./ÿC./ÿC-/ÿC-/ÿB,.ÿB,/ÿA,.ÿA+.ÿA+-ÿ@+-ÿ@*-ÿ@*,ÿ@),ÿ?)+ÿ?)+ÿ>)*ÿ>)*ÿ=)+ÿ=)*ÿ<)*ÿ<()ÿ<()ÿ=()ÿ='(ÿ<'(ÿ<')ÿ<')ÿ<')ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ:&(ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ:$&ÿ:$&ÿ9%&ÿ9%&ÿ9%&ÿ9$&ÿ9$%ÿ8$%ÿ8$&ÿ8$&ÿ8$&ÿ8#&ÿ9#%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ8#$ÿ8#$ÿ7#$ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7"%ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7"$ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ6!#ÿ='*ÿN5:ÿE.2ÿ7"$ÿ7!#ÿ7!#ý7!#Ž7"$7"$7!$I25I25H15J26šK37ÿK37ÿM49ÿoW[ÿˆptÿ`HLÿM5:ÿN6;ÿO7;ÿO7<ÿP7<ÿP7<ÿP8<ÿP8=ÿP8=ÿQ9=ÿR9>ÿS8>ÿS9?ÿT9?ÿT9?ÿT9@ÿU:@ÿU:@ÿU:AÿU:AÿU;BÿU;BÿV;CÿVÿS9>ÿS8>ÿR8=ÿR8=ÿQ7<ÿQ7<ÿP8;ÿP7;ÿO7;ÿO7;ÿO6;ÿO6:ÿO6;ÿO5:ÿN5:ÿN59ÿM59ÿM59ÿL48ÿL48ÿK47ÿK37ÿK36ÿK36ÿJ25ÿJ25ÿJ24ÿJ24ÿI25ÿI15ÿH15ÿG14ÿG04ÿG03ÿG/3ÿF/2ÿF/2ÿE.2ÿE.1ÿE.1ÿE.0ÿD.0ÿD-/ÿC./ÿC./ÿC-/ÿC-/ÿB,.ÿB,.ÿA,.ÿ@+.ÿ@+-ÿ@*-ÿ@*,ÿ@*,ÿ@),ÿ?)+ÿ?)+ÿ>)*ÿ>)*ÿ=(*ÿ=(*ÿ<)*ÿ<()ÿ<()ÿ<()ÿ='(ÿ<'(ÿ<'(ÿ<')ÿ<')ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ:%(ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ:%'ÿ:$&ÿ:$&ÿ9$&ÿ9%&ÿ9%&ÿ9$&ÿ9$%ÿ8$%ÿ8$%ÿ8$&ÿ8$&ÿ7#%ÿ8$%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7"%ÿ7"$ÿ8#$ÿ7#$ÿ7#$ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ?'*ÿO5:ÿD-1ÿ6"$ÿ6!$ÿ6!#ÿ7!#š7!$7!$7"$C,7J35I26H17J37 K37ÿK37ÿM49ÿkSWÿŠrvÿgOSÿN5;ÿN6;ÿO7<ÿO7<ÿP7<ÿP8<ÿP8<ÿP8=ÿP9=ÿQ9=ÿR9>ÿS8>ÿS9?ÿT9?ÿT9?ÿT9@ÿU:@ÿU:@ÿU:@ÿU:AÿU:BÿU;BÿU;BÿV;BÿVÿS9>ÿS8=ÿR8=ÿR8=ÿQ7<ÿQ7<ÿP8;ÿP7;ÿO7;ÿO7;ÿO6:ÿO6;ÿN5;ÿO5:ÿN5:ÿN49ÿM49ÿM48ÿL48ÿL47ÿK47ÿK37ÿK36ÿK26ÿJ25ÿI25ÿI24ÿI25ÿI24ÿH14ÿH14ÿG04ÿG04ÿG03ÿG/3ÿF/2ÿF/2ÿE.1ÿE.1ÿD-0ÿD.0ÿD.0ÿD-/ÿC./ÿC-/ÿC-/ÿB-.ÿB,.ÿA,.ÿA,-ÿ@+-ÿ@+-ÿ?*-ÿ@*,ÿ@*,ÿ@),ÿ?)+ÿ?(+ÿ>)*ÿ>)*ÿ=(*ÿ=(*ÿ<(*ÿ<()ÿ<()ÿ<()ÿ<'(ÿ<'(ÿ<'(ÿ<'(ÿ<&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ:%(ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ9%'ÿ:$&ÿ:$&ÿ9$&ÿ9$&ÿ9%&ÿ9$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$&ÿ7#%ÿ8$%ÿ9$%ÿ9$%ÿ9$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7"%ÿ7"$ÿ7"$ÿ7#$ÿ7#$ÿ7#$ÿ7#%ÿ7#%ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"$ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿ7!#ÿB*-ÿQ5;ÿC+/ÿ6"#ÿ6"#ÿ6!$ÿ6!#Ÿ6!#7!#7!$<E,1J37I37H26J37šK37þK38ÿK48ÿeMQÿ‰quÿqX]ÿQ8=ÿN5:ÿO7<ÿO7<ÿP7<ÿP8<ÿP8<ÿP8=ÿQ9=ÿQ9=ÿR9>ÿS8>ÿS9>ÿS9?ÿT9?ÿT9?ÿT:@ÿU:@ÿU:@ÿU:@ÿU:AÿU:BÿU:BÿU;BÿVÿR9>ÿR8=ÿR8=ÿR8=ÿQ7<ÿQ7<ÿP8;ÿP7;ÿO7;ÿO7;ÿO6;ÿO6:ÿN6;ÿN5:ÿN5:ÿN59ÿM49ÿM49ÿL48ÿL38ÿK47ÿK37ÿK36ÿK36ÿJ25ÿJ25ÿI25ÿI24ÿI25ÿI14ÿH14ÿH13ÿG04ÿH03ÿG03ÿG/3ÿF/2ÿF.2ÿE.1ÿD.1ÿD-0ÿD-0ÿD./ÿC./ÿC./ÿC-/ÿC-/ÿB-.ÿB,.ÿA,-ÿA+-ÿ@+-ÿ@+-ÿ?*-ÿ@*,ÿ?*,ÿ@)+ÿ?)+ÿ?(+ÿ>)*ÿ>)*ÿ=(*ÿ<(*ÿ<')ÿ<')ÿ<()ÿ<')ÿ<'(ÿ;'(ÿ<'(ÿ<'(ÿ<&'ÿ;&'ÿ;&(ÿ;&(ÿ:&(ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ9$'ÿ9$&ÿ:$&ÿ9$&ÿ9$&ÿ9$&ÿ9$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ7#%ÿ8$%ÿ8$%ÿ9$%ÿ9$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ7"$ÿ7"$ÿ6"$ÿ7#$ÿ7#$ÿ7#$ÿ7#%ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ6"$ÿ7!#ÿ7!#ÿ7!#ÿ8"$ÿF-1ÿR6;ÿA)-ÿ6!#ÿ6!#ÿ6"#ý6!#š7!#6!#6!#3$F/8J47J37J36J37�K37úK38ÿK38ÿ]DIÿ…mqÿ|dhÿW>CÿN5:ÿO7<ÿO7<ÿP7<ÿP8<ÿP8<ÿP8=ÿQ9=ÿQ9=ÿR9>ÿS8>ÿS9>ÿS9?ÿT9?ÿT9?ÿT9?ÿU:@ÿU:@ÿU:@ÿU:AÿU:AÿU:BÿU:BÿV;BÿV;BÿV;BÿV;BÿV;BÿU;BÿU;BÿU;AÿU;AÿU;AÿU;AÿT;AÿT:@ÿU:@ÿU:@ÿT:@ÿT:@ÿT9@ÿT9@ÿT9?ÿS8?ÿS8?ÿS9>ÿR9>ÿR8>ÿQ8=ÿQ8=ÿQ7<ÿQ7<ÿQ8;ÿP7;ÿP7<ÿO7;ÿO6;ÿO6:ÿO6:ÿN5:ÿN5:ÿM5:ÿM49ÿM49ÿM48ÿL38ÿL38ÿK37ÿK37ÿK36ÿK36ÿJ25ÿJ25ÿI24ÿI24ÿH25ÿH14ÿH14ÿH13ÿG03ÿG03ÿG/3ÿF/2ÿF/2ÿE.2ÿE.1ÿD.1ÿD-0ÿC.0ÿC-/ÿC./ÿC./ÿC-/ÿC-/ÿB-.ÿB,.ÿA,-ÿA+-ÿ@+,ÿ@+,ÿ@*,ÿ@*,ÿ?),ÿ?)+ÿ?)+ÿ>)*ÿ>)*ÿ=(+ÿ=(*ÿ<(*ÿ<')ÿ<')ÿ<')ÿ<')ÿ<'(ÿ;'(ÿ;'(ÿ<'(ÿ;&'ÿ;&'ÿ;&'ÿ;&(ÿ:&(ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ9%'ÿ9$'ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9$&ÿ9#%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ7#$ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ7#$ÿ7#$ÿ7#$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ6!$ÿ6!#ÿ6!#ÿ;$'ÿL26ÿP5:ÿ>'*ÿ6!#ÿ6!#ÿ6!#ú6!#�5"#6!#7!#8!$D/4K36J26H16J37yK38òK48ÿK38ÿUÿS8>ÿS8>ÿS9?ÿS9?ÿT9?ÿT9?ÿT9?ÿT9@ÿU:@ÿU:@ÿU:AÿU:AÿU:AÿU;AÿU;AÿU;AÿU;AÿU;AÿU;AÿU;AÿU;AÿT:AÿT:@ÿT:@ÿT:@ÿT:@ÿT:?ÿT9?ÿT9?ÿT9?ÿT9?ÿS8?ÿS8?ÿS8>ÿR8>ÿR8>ÿQ8=ÿQ8=ÿQ7<ÿP7<ÿQ8<ÿP8;ÿP7;ÿO7;ÿO7;ÿO6;ÿO6:ÿN6:ÿN59ÿM59ÿM59ÿL49ÿL49ÿL48ÿL38ÿK37ÿK27ÿK26ÿK36ÿJ26ÿJ25ÿI25ÿI24ÿH25ÿH24ÿG14ÿG13ÿG03ÿH03ÿG02ÿG/2ÿF/2ÿF/2ÿE.1ÿE.1ÿD-1ÿD-0ÿC.0ÿC-/ÿC-/ÿC-/ÿC-/ÿC-.ÿB,.ÿB,.ÿA,-ÿ@+-ÿ@+,ÿ?*,ÿ@*,ÿ?*+ÿ?),ÿ>)+ÿ>)+ÿ>)*ÿ>)*ÿ=(+ÿ=(*ÿ<(*ÿ<')ÿ<')ÿ<')ÿ<&(ÿ;'(ÿ;'(ÿ;'(ÿ;'(ÿ;&'ÿ;&'ÿ;&'ÿ;&'ÿ:&(ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ9%'ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ9$&ÿ9#&ÿ9#%ÿ8#%ÿ8#%ÿ8$%ÿ8$%ÿ8#%ÿ7#$ÿ8$$ÿ8$%ÿ8$%ÿ8$%ÿ7$%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ7#$ÿ7"$ÿ7"#ÿ6"#ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ6!#ÿ6!#ÿ@),ÿP6;ÿK26ÿ;$&ÿ7!#ÿ6!#ÿ6!#ò6!#x6!#6!#6"#5 I11J27I26B/2J37]K38áK48ÿK38ÿO6;ÿkSWÿŠquÿv]bÿV>CÿN6;ÿO7<ÿP7<ÿP8<ÿP8<ÿP8=ÿP8=ÿQ9=ÿR9>ÿR9>ÿS8>ÿS8>ÿS9?ÿS9?ÿT9?ÿT9?ÿT9?ÿT9?ÿT9@ÿT9AÿT9AÿT:AÿU:AÿT;AÿT;AÿT:AÿT:@ÿT:@ÿT:@ÿT:@ÿT:@ÿT:@ÿT:@ÿT9?ÿT9?ÿS9?ÿT9>ÿT9>ÿS8>ÿS8>ÿS8>ÿR8>ÿR7>ÿQ8=ÿQ8=ÿQ8<ÿP7<ÿP7<ÿO8;ÿP7;ÿO7;ÿO7;ÿO6;ÿO6:ÿO6:ÿN59ÿN59ÿM59ÿM48ÿL49ÿL48ÿK38ÿK38ÿK37ÿK27ÿK36ÿK36ÿJ25ÿJ25ÿI24ÿI24ÿH25ÿH14ÿG14ÿG13ÿF03ÿG02ÿG02ÿG/2ÿF/2ÿF.2ÿE.1ÿE.1ÿD-0ÿC-0ÿC.0ÿC-/ÿC-/ÿB,/ÿB,/ÿB-.ÿB,.ÿA,.ÿA,-ÿ@+-ÿ@+,ÿ?*,ÿ@*+ÿ?*+ÿ?)+ÿ>)+ÿ>(+ÿ=)*ÿ>)*ÿ=(*ÿ=(*ÿ<(*ÿ=')ÿ<')ÿ<')ÿ<&(ÿ;&(ÿ;'(ÿ;'(ÿ;'(ÿ:&'ÿ:&'ÿ;&'ÿ;&'ÿ:&'ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ9%'ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ9#&ÿ9#%ÿ8#%ÿ8#%ÿ8#%ÿ8$%ÿ7#%ÿ7#$ÿ8$$ÿ8$$ÿ8$%ÿ7$%ÿ7$%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7#%ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ7"#ÿ6"#ÿ6"#ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ9$'ÿI04ÿR7=ÿD,0ÿ7"$ÿ7!#ÿ7!#ÿ6!#à6!#\4!!6!#6!#3&&I26H25N4;K379K48ÄK48ÿL49ÿL48ÿ[CGÿfjÿ‡nsÿhOTÿQ9>ÿO6;ÿP7<ÿP8<ÿP8<ÿP8=ÿP8=ÿQ9=ÿQ9=ÿR9>ÿR8>ÿS8>ÿS8>ÿS9>ÿS9?ÿS9?ÿT9?ÿT9?ÿT9?ÿT9@ÿT9@ÿT9@ÿT:@ÿT:@ÿT:@ÿT:@ÿT:@ÿT:@ÿT:@ÿT:?ÿT9?ÿT9?ÿS9?ÿS9?ÿS9>ÿS9>ÿS8>ÿS8=ÿS8=ÿR8>ÿR7>ÿQ8=ÿQ8=ÿQ8<ÿP7<ÿP7<ÿO8;ÿO7;ÿO7<ÿO7;ÿO6;ÿO6:ÿO6:ÿN5:ÿN59ÿM59ÿM48ÿL48ÿL48ÿK38ÿK38ÿK37ÿK27ÿK26ÿK36ÿJ26ÿJ25ÿI25ÿI24ÿH25ÿH24ÿG14ÿG14ÿF13ÿF03ÿF02ÿG/2ÿF/1ÿF/1ÿE.1ÿE.1ÿD.1ÿD-0ÿC.0ÿC-/ÿC-/ÿC-/ÿB,/ÿB,/ÿA,.ÿB,.ÿA,-ÿA+-ÿ@+-ÿ@+,ÿ?*,ÿ@*+ÿ?)+ÿ?)*ÿ>)*ÿ>(+ÿ=)*ÿ=)*ÿ=(*ÿ=(*ÿ<'*ÿ<')ÿ<')ÿ<')ÿ<&(ÿ;&(ÿ;&(ÿ;'(ÿ;&(ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:%'ÿ:%&ÿ:%'ÿ:%'ÿ9%'ÿ9%'ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7#$ÿ8$$ÿ8$$ÿ8$$ÿ8$$ÿ7$%ÿ7#%ÿ7#%ÿ7#%ÿ8#%ÿ8#%ÿ7#%ÿ7#%ÿ7"%ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6!$ÿ6"#ÿ6"#ÿ6"#ÿ6"#ÿ6"$ÿ6"$ÿ8#%ÿB,/ÿQ7=ÿM49ÿ<&)ÿ6!#ÿ6!#ÿ6!#ÿ7!#Ã6!#97"#5!#5!"I26H15K48J37K48’K48õL49ÿL48ÿP7<ÿjQUÿˆnsÿ€glÿ`HMÿP8=ÿO6;ÿP8<ÿP8<ÿP8<ÿP8=ÿP8=ÿQ9=ÿR9=ÿR9>ÿR9>ÿS8>ÿS8>ÿS8>ÿS9>ÿS9>ÿS9?ÿS9?ÿS9@ÿS9@ÿS9@ÿS:@ÿT:@ÿT:?ÿT:?ÿT9?ÿT9?ÿT9?ÿS9?ÿS9?ÿS9>ÿS9>ÿR8>ÿR8>ÿR8=ÿR8=ÿR8=ÿR7=ÿQ8=ÿQ8=ÿQ8<ÿP7<ÿP7<ÿO7;ÿO7;ÿO7<ÿO7;ÿO7;ÿO6;ÿO6:ÿN6:ÿN59ÿM59ÿM59ÿM48ÿL48ÿL47ÿK37ÿK37ÿK37ÿK27ÿJ36ÿK36ÿJ25ÿJ25ÿI24ÿI24ÿH25ÿH14ÿG14ÿG13ÿF03ÿG02ÿF02ÿF/2ÿF/1ÿF/1ÿE.0ÿE.0ÿD-0ÿD-0ÿC.0ÿC-/ÿC-/ÿC-/ÿB,/ÿB,/ÿA+.ÿA+.ÿA,-ÿA+-ÿ@+,ÿ@+,ÿ@*,ÿ?*+ÿ?)+ÿ>)*ÿ>)*ÿ=)*ÿ=)*ÿ<(+ÿ<(*ÿ<(*ÿ<')ÿ<')ÿ<')ÿ<&)ÿ<&(ÿ;&(ÿ;&(ÿ;&(ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ:%&ÿ:%&ÿ:%&ÿ:%'ÿ9%'ÿ9$'ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7"$ÿ8$$ÿ8$$ÿ8$$ÿ8$$ÿ7$$ÿ7#$ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7#%ÿ7"%ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6!#ÿ5!#ÿ6"#ÿ6"#ÿ6"#ÿ6"$ÿ?),ÿO5:ÿR8>ÿC,0ÿ7"$ÿ6!#ÿ6!#ÿ6!#ô6!#’6!#6!#5!#6 #H06O79K37H24J47ZK48ÓL49ÿL49ÿM49ÿV=AÿsZ_ÿ‰qvÿ|diÿ`GLÿQ8=ÿO6;ÿP8<ÿP8<ÿP8<ÿP8=ÿQ8=ÿR9=ÿR9=ÿR9=ÿR9>ÿR9>ÿR8>ÿS8>ÿS8>ÿS8>ÿS8>ÿS8?ÿS8?ÿS8?ÿS9?ÿT9?ÿS9?ÿS9?ÿS9?ÿS9>ÿS9>ÿS9>ÿR8>ÿR8>ÿR8=ÿR8=ÿQ8=ÿQ7=ÿR7<ÿQ8<ÿQ8<ÿQ8<ÿP7<ÿP7<ÿO7;ÿO6;ÿO6<ÿO7;ÿO7;ÿN6;ÿN6:ÿN6:ÿN59ÿN59ÿM59ÿM48ÿL48ÿL47ÿK37ÿK37ÿK36ÿK26ÿJ26ÿJ36ÿJ26ÿJ25ÿI25ÿI14ÿH15ÿH14ÿG14ÿG14ÿF13ÿF03ÿF02ÿF/2ÿE/1ÿE/1ÿE.1ÿE.0ÿD.0ÿD-/ÿC-0ÿC./ÿC-/ÿC-/ÿB,/ÿB,/ÿA,.ÿA+.ÿ@+.ÿ@+-ÿ@+-ÿ@+,ÿ?*,ÿ@*+ÿ?*+ÿ?)+ÿ>)*ÿ>)*ÿ=)*ÿ=)*ÿ<(*ÿ<(*ÿ;(*ÿ<')ÿ<')ÿ<')ÿ<&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ:%'ÿ:%'ÿ:&'ÿ:&'ÿ9&'ÿ9%&ÿ:%&ÿ:%&ÿ9%&ÿ9%'ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7"$ÿ8#$ÿ8$$ÿ8$$ÿ8$$ÿ7$$ÿ7#$ÿ7#$ÿ7#%ÿ7#%ÿ6#%ÿ7#%ÿ7#%ÿ7"$ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6!#ÿ5!#ÿ4!"ÿ6"$ÿ>)+ÿM58ÿT:?ÿI15ÿ:%(ÿ6!#ÿ6!#ÿ6!#ÿ6!#Ó6!#Y5!"6!#3"#8!%E11J37J36K58J37"K48•L49ðM49ÿM49ÿN5:ÿY@Eÿu]bÿ‰quÿfkÿeLPÿT;?ÿO7;ÿO7;ÿP8<ÿP8<ÿP8=ÿQ8=ÿQ9=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9>ÿR9>ÿR9>ÿR9>ÿR9>ÿR9?ÿR9?ÿR9>ÿS9>ÿS9>ÿS9>ÿR8>ÿR8>ÿR8>ÿR8=ÿR8=ÿQ8=ÿQ8=ÿQ7<ÿP8<ÿP8<ÿQ8<ÿP7;ÿP7;ÿP7<ÿO7;ÿO6;ÿO6<ÿO6;ÿO6;ÿN6;ÿN6:ÿN6:ÿM5:ÿM59ÿM59ÿM48ÿL48ÿL48ÿK47ÿK37ÿK36ÿK36ÿK26ÿJ35ÿJ36ÿI25ÿI25ÿI14ÿI14ÿH15ÿH04ÿG04ÿG13ÿF03ÿG03ÿF02ÿF/2ÿE/1ÿE/1ÿD.0ÿD.0ÿD-0ÿD-/ÿC./ÿC-/ÿC-/ÿC-/ÿB,/ÿB,/ÿA,.ÿA+.ÿ@+-ÿ@*-ÿ?*-ÿ@+,ÿ?*,ÿ@*+ÿ?*+ÿ?)*ÿ>)*ÿ>(*ÿ=)*ÿ=)*ÿ<()ÿ<(*ÿ;'*ÿ<')ÿ;')ÿ<')ÿ<&(ÿ;&(ÿ;&(ÿ;&(ÿ;%(ÿ:%'ÿ:%'ÿ:%'ÿ:&'ÿ9&'ÿ9%&ÿ9%&ÿ:%&ÿ9%&ÿ9%&ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8$&ÿ8#&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8"%ÿ7"$ÿ8#$ÿ8#$ÿ8$$ÿ8$$ÿ7$$ÿ7#$ÿ7#$ÿ7#$ÿ7#%ÿ6#%ÿ6#%ÿ7#%ÿ7"$ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$ÿ6!$ÿ5!#ÿ7#%ÿ@*-ÿN5:ÿS:?ÿJ26ÿ<'(ÿ6"#ÿ6!#ÿ6!#ÿ6!#ð6!#”6!##6!"6!#6!#/K27I-2J38I26K48FL49·L49úM59ÿM49ÿN5:ÿY@EÿrY^ÿ‡osÿ…lpÿpW[ÿ\CGÿQ9=ÿO7;ÿO7;ÿP8<ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ9=ÿR9=ÿR9=ÿR9=ÿR9=ÿR9>ÿQ9>ÿQ8>ÿR8>ÿR8>ÿR8>ÿR8=ÿR8=ÿR8=ÿQ8=ÿQ8=ÿQ7=ÿQ8<ÿP8<ÿP8<ÿP8;ÿO7;ÿP7;ÿP7;ÿO7;ÿO6;ÿO6;ÿO6;ÿO6;ÿN5;ÿN5:ÿN6:ÿM5:ÿM59ÿL59ÿL58ÿL48ÿL48ÿL47ÿK37ÿK36ÿK36ÿK26ÿJ35ÿJ35ÿI25ÿI25ÿH25ÿH14ÿH15ÿH14ÿG04ÿG04ÿF03ÿF03ÿF02ÿF/2ÿE/2ÿE/1ÿE.1ÿD.0ÿD.0ÿC-/ÿC-/ÿC./ÿC-.ÿC-/ÿC,/ÿB,/ÿB,.ÿA+.ÿA+.ÿ@+-ÿ@*-ÿ?*,ÿ?*,ÿ?*,ÿ?*+ÿ?)+ÿ>)*ÿ>)*ÿ=)*ÿ=)*ÿ<(*ÿ<()ÿ;()ÿ;')ÿ;')ÿ;')ÿ;&)ÿ<&(ÿ;&(ÿ;&(ÿ;&(ÿ;%(ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ9%&ÿ9%&ÿ9%&ÿ9%&ÿ9%&ÿ9$%ÿ9$%ÿ8$&ÿ8$&ÿ8$&ÿ8#&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7"%ÿ7"$ÿ8#$ÿ8#$ÿ8#$ÿ7$$ÿ7$$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ6#%ÿ6#%ÿ6#%ÿ7"$ÿ7"$ÿ7"$ÿ6"$ÿ6"$ÿ5!#ÿ7#%ÿ<&*ÿG/3ÿR8=ÿS:?ÿH04ÿ;%(ÿ5!#ÿ6"#ÿ7"#ÿ6!#ú6!#¸6!#F5!#6!#6#%5!$L07J38J37L49J37K38_L49ÅM59üN5:ÿM4:ÿM4:ÿU=BÿhPTÿgkÿ‰puÿ�hlÿmUYÿ]DIÿS;?ÿO7;ÿO7;ÿP7;ÿQ8<ÿQ8<ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ8=ÿQ7=ÿQ7<ÿQ8<ÿP8<ÿP8<ÿP8<ÿO7;ÿO7;ÿO7;ÿO7;ÿO7;ÿO6;ÿO6;ÿO6;ÿO6;ÿN5;ÿN5:ÿN5:ÿM5:ÿM59ÿL59ÿL58ÿL48ÿK48ÿL47ÿK37ÿK37ÿK36ÿK26ÿJ25ÿJ35ÿJ25ÿI24ÿI24ÿH14ÿH14ÿG15ÿG04ÿG04ÿG03ÿF/3ÿG/3ÿF02ÿF/2ÿE/1ÿE/1ÿD.0ÿD.0ÿC.0ÿC-/ÿC./ÿC-.ÿC-/ÿC-/ÿB,/ÿB,/ÿA,.ÿA+.ÿ@+-ÿ@*-ÿ?*-ÿ?*,ÿ>),ÿ?)+ÿ?)+ÿ?)+ÿ>)*ÿ>)*ÿ=)*ÿ=)*ÿ<(*ÿ<()ÿ;()ÿ;'(ÿ;')ÿ;')ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ;&(ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ9$&ÿ9%&ÿ9%&ÿ8%&ÿ8%&ÿ9$&ÿ9$%ÿ9$%ÿ8$%ÿ8$&ÿ8$&ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ8#%ÿ7"$ÿ7#$ÿ8#$ÿ8#$ÿ8#$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ6#$ÿ6#%ÿ6"%ÿ6"$ÿ6!#ÿ6"$ÿ8#&ÿ=(+ÿG03ÿQ8=ÿV;AÿP6;ÿC,0ÿ8$&ÿ5!#ÿ5!#ÿ5!#ÿ6!#ü6"#Æ6!#_6!"6!#6!#6!#0 E03O6<K38M5:K38L48dM59ÂM59øN5:ÿN5:ÿM5:ÿP8=ÿZBGÿmUZÿ€glÿˆotÿ„joÿw^bÿiPTÿ]DIÿV=BÿQ9=ÿP7;ÿO7;ÿO7;ÿO7;ÿP7;ÿP7;ÿP7;ÿP7<ÿP7<ÿO7<ÿP7<ÿP7<ÿP7<ÿP7<ÿP7;ÿO7;ÿO7;ÿO7;ÿO7;ÿO6;ÿO7;ÿO6;ÿO6;ÿN6:ÿN6:ÿO5:ÿN59ÿN5:ÿM5:ÿM4:ÿM49ÿL49ÿL48ÿL48ÿK48ÿK47ÿJ37ÿJ37ÿJ36ÿJ36ÿJ26ÿJ25ÿJ25ÿI24ÿI24ÿH24ÿH14ÿG14ÿG14ÿF04ÿF04ÿF03ÿF/3ÿF/2ÿF/2ÿF.2ÿE.1ÿE/1ÿD.0ÿD.0ÿC-0ÿC-/ÿB-/ÿB-.ÿB-.ÿB-.ÿB,.ÿB,.ÿA,.ÿA+.ÿ@+-ÿ@*-ÿ?*-ÿ?*,ÿ>),ÿ>)+ÿ>)+ÿ>(+ÿ>(*ÿ>)*ÿ=(*ÿ=)*ÿ<(*ÿ<()ÿ;()ÿ;'(ÿ;'(ÿ;'(ÿ;&(ÿ;&(ÿ:&(ÿ:&(ÿ:&(ÿ:%'ÿ:%'ÿ:%'ÿ:%'ÿ9%'ÿ9$'ÿ9$&ÿ9$&ÿ9$&ÿ8%&ÿ8%&ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8$%ÿ8#%ÿ8#%ÿ7#%ÿ8#%ÿ8#%ÿ8#%ÿ7"%ÿ7"$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ7#$ÿ7"$ÿ6"#ÿ6"#ÿ6"#ÿ6"#ÿ6#$ÿ7$%ÿ9%'ÿ>(+ÿE.2ÿM59ÿT;@ÿV=BÿR8>ÿG04ÿ<&)ÿ6"$ÿ4!"ÿ5!#ÿ5!#ÿ5!#ø5!#Ã5!#d6"#6!#6!"5!!8!$I16È–�K38N59K38L48TM59®N5:êN5:ÿN5;ÿN5:ÿN5:ÿP8=ÿX@EÿfNSÿu]bÿ�hmÿ‡nsÿ†lqÿ€fkÿx_cÿpW\ÿhOTÿcJOÿ_FKÿ\CHÿ[BFÿY@EÿY@EÿX@EÿX@EÿX@EÿY@EÿY@DÿX@DÿX@DÿX?CÿX?CÿX?CÿX?DÿX?CÿW>CÿW>CÿW>CÿV>BÿW=BÿV=BÿV=AÿV=AÿUÿS:>ÿS:>ÿR:=ÿR:=ÿQ:<ÿQ9<ÿP9<ÿP9<ÿO8<ÿO8;ÿN7;ÿN7;ÿN7;ÿN6:ÿN6:ÿN69ÿN59ÿM59ÿL58ÿL58ÿL57ÿK57ÿK46ÿJ46ÿJ46ÿJ46ÿJ46ÿJ35ÿI35ÿI24ÿH25ÿH25ÿG14ÿG14ÿF13ÿF03ÿF/2ÿF/2ÿE/2ÿE/1ÿE/1ÿD/1ÿD/1ÿD/1ÿC.0ÿB.0ÿB-/ÿB-/ÿB-/ÿB,.ÿB,.ÿA,.ÿA,/ÿA,.ÿA+.ÿA+-ÿA+-ÿA+-ÿ@+-ÿ@*-ÿ@*,ÿ@*,ÿ?*,ÿ?*,ÿ>*,ÿ>*+ÿ>*+ÿ>)+ÿ>)+ÿ>)+ÿ>)+ÿ>(+ÿ>(+ÿ>(+ÿ>(+ÿ>(+ÿ>(*ÿ='*ÿ=(*ÿ=(*ÿ=(*ÿ>(*ÿ>)+ÿ?),ÿA*-ÿC-0ÿF03ÿJ47ÿO7;ÿT;?ÿW=BÿW>BÿS:?ÿK59ÿC-1ÿ;&)ÿ7#%ÿ5!#ÿ6!#ÿ5!#ÿ5!#ÿ5!#ë5!#­5!#T5!#5!#6"#015"#J177.K38M59J36L483M59‚M5:ÉN5;óN6;ÿN6;ÿN6;ÿM5:ÿN6;ÿQ9>ÿW?Dÿ_FKÿiQVÿrZ_ÿyaeÿgkÿ‚inÿƒkpÿ„kqÿ…lqÿ…lqÿ…lqÿ…kqÿ…kpÿ„kpÿ„jpÿ„joÿ„joÿ„joÿ„joÿƒinÿƒinÿƒimÿ‚hmÿ‚hmÿ�hmÿ�glÿ�flÿ€fkÿ€fkÿ€fkÿ€ejÿdjÿdjÿ~ciÿ~ciÿ}biÿ}bhÿ|bgÿ|bgÿ|agÿ{afÿ{afÿ{`eÿ{`eÿz`dÿy_cÿy_cÿx^cÿx^cÿx]bÿw]bÿv\aÿv\aÿv[aÿu[`ÿu[`ÿuZ`ÿtY_ÿtY^ÿsX^ÿsY]ÿrX]ÿqW\ÿqW\ÿqW\ÿqV[ÿpV[ÿoUZÿoUZÿoUYÿnTYÿnSYÿmSXÿlSXÿlRWÿkRWÿkQVÿkPVÿjPUÿjOUÿiPTÿiOSÿhOSÿhOSÿhNSÿgMRÿfMRÿfMQÿeLQÿfLQÿfKPÿeKOÿdJOÿcJPÿcJOÿcINÿcINÿcINÿcHMÿbHNÿaGMÿaGLÿaGLÿ`GLÿ`FKÿ`FKÿ_FJÿ_FJÿ^EJÿ^EJÿ^EJÿ^DIÿ^CHÿ^CIÿ^CHÿ]CHÿ]CHÿ\BGÿ\BFÿ\BGÿ\BFÿ\BFÿZAFÿZ@EÿZ?EÿY>DÿX=CÿUBÿW>CÿX?DÿX?DÿX?DÿX?DÿX?DÿX?DÿX?DÿX?DÿX?DÿX?DÿX?CÿW>CÿW>CÿW>CÿW>BÿV>BÿV=BÿU=AÿU=AÿU=AÿUÿR:>ÿR:>ÿQ:=ÿQ:=ÿQ:=ÿQ9<ÿQ9<ÿP9<ÿP8<ÿO8<ÿO8;ÿN7;ÿN7:ÿN7:ÿN6:ÿM6:ÿM6:ÿM59ÿM58ÿM58ÿL48ÿL57ÿK57ÿK46ÿJ46ÿK46ÿJ46ÿI46ÿI35ÿH35ÿH35ÿH24ÿH24ÿG13ÿG13ÿF13ÿF03ÿF03ÿF/2ÿE/2ÿE/1ÿD/1ÿD/1ÿC.1ÿC.1ÿC.0ÿC.0ÿB./ÿC-/ÿB-/ÿB-/ÿB,.ÿA,.ÿA,.ÿA,.ÿA,.ÿ@+.ÿ@+-ÿ@+-ÿA+-ÿ@+-ÿ@*-ÿ@*,ÿ@*,ÿ?*,ÿ?*,ÿ?),ÿ>)+ÿ>*+ÿ=*+ÿ=)+ÿ>)+ÿ>(*ÿ>(*ÿ>(*ÿ>(+ÿ>(+ÿ>(+ÿ='*ÿ=(*ÿ=(*ÿ=(*ÿ=(*ÿ<()ÿ;')ÿ;&(ÿ:%'ÿ9$&ÿ7#%ÿ6"$ÿ5"#ÿ5"#ÿ5"#ÿ6"#ÿ5"#ÿ5"#ÿ5"$þ5"$ê5"$Á6"$…6!#B5!$5 !5!#6!#7 5"%K15I14L48M5:Q8?L58 M5:0M5:`N6;“N6;ÁN6;àN6;óN6;þN6;ÿN6;ÿO6;ÿO6;ÿO6;ÿO6;ÿO6;ÿO5:ÿN5:ÿN5:ÿN5:ÿN5:ÿN5:ÿN5;ÿN5;ÿN5:ÿN5:ÿN5:ÿN5:ÿM5:ÿM59ÿM59ÿM49ÿL59ÿL48ÿL48ÿK48ÿK48ÿK37ÿK37ÿK37ÿK37ÿJ27ÿJ27ÿJ26ÿJ36ÿJ26ÿI25ÿI25ÿI25ÿH24ÿH24ÿH24ÿH14ÿG14ÿG14ÿG03ÿF03ÿF02ÿF/2ÿF/2ÿE/1ÿE.1ÿD.1ÿD.1ÿD-1ÿD-0ÿD-0ÿC-0ÿC-/ÿB-/ÿB-.ÿB-.ÿB-.ÿA,.ÿA,.ÿ@,-ÿ@+-ÿ?+-ÿ?+,ÿ?*,ÿ?*+ÿ>*+ÿ>)+ÿ>)+ÿ>(+ÿ=(*ÿ=(*ÿ<(*ÿ<(*ÿ;(*ÿ;')ÿ;')ÿ;')ÿ;'(ÿ;'(ÿ;'(ÿ;&'ÿ:&'ÿ:&'ÿ:&'ÿ:&'ÿ9%&ÿ9%&ÿ9%'ÿ9%'ÿ9%'ÿ9$&ÿ9$&ÿ9$&ÿ8$&ÿ8$&ÿ8#&ÿ8#%ÿ8#%ÿ7#%ÿ7$%ÿ7$%ÿ7#$ÿ7#$ÿ7#$ÿ8#$ÿ8#$ÿ8#$ÿ7"%ÿ7"$ÿ7#$ÿ7#$ÿ7#$ÿ6#$ÿ6#$ÿ6"$ÿ6"$ÿ6"$ÿ7"$ÿ6"$ÿ6"$ÿ6"$ÿ6"$þ6"#ô6"#à5"#Á5"#”5"$a5"$/6"$ 6!#6!#5!$5"&5"%@L7;J25L58M5:N6;YM5:aM6;~N6:›N6;²O6;ÁO6;ÏN6:ØN6:ÜN6:ßN6:áN6:áN6:áN5:áN5:áN5;áN5;áM5;áN6:áN6:áN6:áN5:áM5:áM59áM59áL59áL49áL48áL48áK48áK47áK37áK37áK36áJ36áK37áK36áJ36áJ26áI25áI25áI35áH24áH24áG24áH14áH14áG14áG03áF03áF02áF/2áF/2áE/1áE.1áE.1áD.1áD-1áC-0áD.0áC-0áC-/áC-/áC-.áB-/áB-/áA,.áA,.á@,-á@+-á?+-á?+,á?*,á?*+á?*+á?)+á?)+á>(+á>(*á=)*á=(*á<(*á<(*á;')á;')á;')á;'(á;'(á;'(á;&'á:&'á:&'á:&'á:&'á9%&á9%&á9%'á9%'á9%'á8$&á9$&á9$&á9$&á8$&á8$&á8#%á8#%á7#%á7#%á7$%á7#%á7#$á7#$á8#$á8#$á8#$á8"$á7"$á7#$á7#$á7#$á7#$á6#$ß6"$Û6"$Ö6"$Í6"$À6"$±6"$™6"$}6"$`6"#>6"#!5"# .!"5"$5"$6"$6"$7"$$$$S46H9CL59L49M5:N5:N6;O6;9#!L59K49 L48M59M59N69N6:N5:N5:N5:N5:N5;M5;M5:M5:N6:N5:M5:M59M59M59L49L48L48K48K48K37J37K37K36J26K36K36J36J26I25I25H25H24H24G25G14G14G13G03F03G02F/2F/2E/1E.1D.0D.1D-1C.0C.0C-/C-/C-/C,.B-/B-/A,.A,.@,-@+-?+-?+,>*,?*+?)+?)*>)+>(+>(*=)*=(*<(*<(*;');');&);&(;'(;'(;&':&':&':&':&'9%&9%&9%&9%'8%'8$&9$&9$&9$&8$&8#&8#%8#%7#%7#%7$%7#$7#$7#$8#$8#$8#$7"$7"$7#$7#$7#$7#$6#%6!$6"$5"$5"$ 6!$. 6"$6"#6"#6"#5!#6"#&/9!#G38F59L48L6:K49L48M59M59N69N6:N5:N5:N5:N5:N5;M5;M5:M5:N6:N5:M5:M59M59M59L59L48L48K48K48K37J37K37K36J26K36K36J36J26I25I25I25H24H24G25G14G14G14G03F03G02F/2F/2E/1E.1D.0D.1D-1C.0C.0C-0C-/C-/C,.B-/B-/A,.A,.@,-@+-?+-?+,>*,?*+?*+?)+?)+>(+>(*=)*=(*<(*<(*;');');&);'(;'(;'(;&':&':&':&':&'9%&9%&9%'9%'8%'8$&9$&9$&9$&8$&8$&8#%8#%7#%7#%7$%7#%7#$7#$8#$8#$8#$8"$7"$7#$7#$7#$7#$6#%6!$6!#5"$6"$6"$6"$7$#7""ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü?ÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿü?ÿÿÿÿÿÿøÿÿÿÿÿÿðÿÿÿÿÿÿðÿÿÿÿÿÿàÿÿÿÿÿÿÀÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿü?ÿÿÿÿü?ÿÿÿÿøÿÿÿÿøÿÿÿÿðÿÿÿÿðÿÿÿÿàÿÿÿÿàÿÿÿÿÀÿÿÿÿÀÿÿÿÿÀÿÿÿÿ€ÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿü?ÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿ€ÿÿÿÿÀÿÿÿÿÀÿÿÿÿÀÿÿÿÿàÿÿÿÿàÿÿÿÿðÿÿÿÿðÿÿÿÿøÿÿÿÿøÿÿÿÿü?ÿÿÿÿü?ÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÀÿÿÿÿÿÿàÿÿÿÿÿÿðÿÿÿÿÿÿðÿÿÿÿÿÿøÿÿÿÿÿÿü?ÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿü?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿheldercorreia-speedcrunch-e7ca37f/src/resources/speedcrunch.png000066400000000000000000002176751526573132500251710ustar00rootroot00000000000000‰PNG  IHDR\r¨fsRGB®ÎéDeXIfMM*‡i   gêI@IDATxì½ °eÇyö¿{ß>o™³c`b™0X@$APHB¤D‰”èØŽbU¥¢8ŽË®R\YªRªT*‹$')'å¸Êr,¥\ eRŽ,¢ŠûB¬³a³Ï¼ý½yûÍ÷}ÿß}ι÷¾Á3Aåõ{÷t÷¿õ߯§OŸ>f«nÕ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j�U ¬Z`Õ«XµÀªV-°j��š:>j }xúüfíÞ{ŸßÔmvÕòRc»Õl{‡Õ6,/767j6Üa�nkttY‡uVtZ®Ä |…®aÍ�†Ó…ÇH)2Àìò({¹•ŠD�X´º8�× B@–2"‰”rêË�p‘ƒ` �xEAº™Ÿ�-“ ;)­Xø$¡0Û2²XÄœ òÊ" ’v2Ct[¯£cyÑ–;æµÆ|c¹c¬V³s�qª¿Û¨/7ë>sðàöóf__j+à¯9ðÿ7À'îøÜ¦¥Î®�¡ÝÝè°;P®{Њ®±ŽŽu�uUòjo.ýÀ–‰:¼ue��RCÀÿ!Ì©Ê�—t6qu¼Ó#,Ñ…¬ˆJŽ(C�‡³të q‰D¥ ˆKt¤ f÷œ @Yõ‘±‚ž€ô ¼ÁNJi°¿êˆü°³úÕeˆCÁ|Ét \‰�é%W¡õD#{®oè‘È¥Af§n„À¼7Ö1Šð1@Þ@ÝxxÎ:_;pà…³…Œ¿¾¡sý5ÊjÇ'îýâmèí?Ýèh<‚z'~[jèPøñK£)ã ÈÉ�6&ajÆ{µ1ÑQÍg…ó� Ë ª_ “@MGÌA�pT< „‹ô¨´bé1€…‘�‹Ôõ<2¬¼:…ìà\Î$>"⬩Hp‘^‰²À‡:ä–óx¢Kl).¥@zOh.•Nèî‰M|‘­àc™–P âÀ“’¥´þyÁOŒ @…ÁõTÍ:žÕwê ûó7?ý*šç$!ÿ§ÛcÎÿZ¹{ïýù›kË�ŸG~CáþZ­ŽY>JSÝ 7jh­^·î®.ëííÕ¯¯¯Ïº»{¬««Ó:;»ŒE­�EŒð¬ª?qiΑ;Uø$—T æ<Î(¶2Α„@MN»QÁHXüCsr2¥ÔQ$ ÷%Øã”“ÒÁ´—Î� D©ã”ŽÉyHG´ÓÐÃÄœ…JÀ�DèCž`–è$E ^ ]ÍÆ5¡~wâó d‰~‘¨$S_‚B;!o  ¸@º°Œ3ÐÕ‚Ž^渵³¥¥%üm¿ùÅ9[\\°……Ä—0ð{~™;‡–=„5–—çx…ô‡¶XûÖ�£O¿¦Äþš\ܶ?å™Ù¿ÿ ý=�Ï£Õþ-Ô‹‡ëµz?+ U•ùëBc´µÃkmxíZëëëWc_F[\X´¹¹9›ŸŸS…˜Ÿ_**ñE Y À£ŽˆP‰¨t œ8  Œ Ul´‡è˜§NFÕ?äÈÓ:Aè#@¨ƒpÒ2ùáHƒJî�Ë1ÈŽcžB‚'Ò _î`‹¥1J¼l“øtâ”ÞLE°‚• {ÒÄ{COú9­ãJ©“2þÉU8Mú‘×~¨V¯wZ½³n�08€°Ã–°L°°0o.ÌØ…ÙÕƒ%”?qš)x¡CÅå¤ùˆúýéÙå?9qâ¹™"¥ŸÎ�Šì§Su³ûî{t½-tý{X!ú1bïea5Øp}8A#ï³M›6ÙÆ�›Ôø™Ï陳ÉÉI›žžRÃçÈÀûØTQ“=Z�ãV±Ž€$Œú&Xb ‘_©Ã(° pšt…¯`4u0i¡„L÷%¦UÑGçQ¤º‘F[Íeã¿»—ò@8u" `Ù8‚ˆÏåòI*çL¡-øŸøLHI¶G2,‘Á—)m Π:I¿Ë JA}:£šHHë>õÎNëîì¶Þž>üz1+Ô„õbÖ¦f¦lú´j\Ì ¨kãùç KÝÿêèÑïcá§Ó…I~º”ß¿ÿg‡{¬ïWÑ­ÿ}4üݬ$±1]³îžnÛ¼y³mÛ¾ÝmvvÖΞ;gçÏŸS£_\\T%I…©Ê=|³ ã°¶E,*ž¼Ô¸€U¼¹¶-å2˜GVè@Ÿä”ù=$¢#? T!ñ.J€‹ÆSȉ„,䥟õ zÈ#Hb� ’zò)”¶SÇ¸ìø°CU¾Óé2² +º0aºB§T¼”¢˜ôSHp‡–¯ÒAä‰ÇùÊ44þ5ÓCeà­_n×ôXïݲ3Ÿ·t‹˜-°îèöЭu°ÑQû'XOüýC‡žoMç£ )[飭©´ûÍÚ}ûŸû* ýW˜¾ÝÌÚ»´„©(FüLïw]½Ë¶lÙ‚{»E;yò”�9}Ú¦0Ês*¯BÓ &…ï™×ªabäË\©òxý�–-,ëS@áSŠW0B³SCòXjœ¤sÞ‡_¢“˜RCsýœ'R=¹“̤JŠ»*„iù, šf( ú`v/$H¤–³%¬ä1ÝB_ÀÊÁB—/Eg‘ YË€O9…í‹�’*ÑAïÜ:%h,…²¼¬®gŒ2øÇšÂu¡�¾[³fP�Ãôô¤�OŽÙ’îÞ{Û__ªý÷hÉã§FÍxxØ®¿þzÛ°qƒ�ŽŽÚ;ïµÑ‘Ü×-©ÀØðéÊWò¯äZ1‰ÆA¾¢nG(U òŒ  rÄ5ÕNܬd ¿Dëa¤F¢.ò‘“a•.bÉ…Ü€‹®…>«¥„”¬^Èg:%~æBÈO (ï€9²l$„SSsO Èƒâ´E–)H¾P¦—B3&)IF*ã°±JìUyЯ„++¯ÎH. öaÁxxp�õàV�kc£6‡u#jÇ5†Hãqlkø/|ú9|´¯¡õGWI.ðuu4þ3¬êÿFG­6°„Fφ?00`{öÜ {üSé�>b“S“((ŸÆ1GEæJT�#’ Þ©ýJ yà…ËdŒ—j‹Ã ϵ3±ò$©!ª©ª±¸œ$·Y4"ááa%îzîÒ�žMÌe¥+|ÿßáÞȨUðAa�ò&¨øuQšNGLÁŸ)åI¹Ïú)bS" ñd¤Ð©0|à3[äd]Ré éÎòÎr‰B„˜òÀF¿ˆQ½»»Û®ß}½íÚµËΞ=c´),èu`E·V+²ã!\`³ Wn¡"ã+ëGÅ9 ƒ£Öä8iQ ‚2�Ä)¢©9<Ó'ÊL+ê²ì“Eò£±%pš)haÒ™]¤Æ*>A9Ú¹>‘ ’]€R@ºfY¡ŸÒo'3ƒW<1¡Lò¹sù)‘C¼ °ÊøR®°‘¬s¤‘<å¯T"5Ù®’\b€_•U¤‘HÊúK+twõØúáõZ+˜˜·Q̸ÅAˆhž¨-/ÿ½·�<ób’óQóW²ÇO\Ï{îüüT¯Õþ4êµKKþHoË–­vËÍ·h…ö�7^×”¿}Çúñ£á«<#«ðª™.u)×UA%"× 4EQàt¥Wi¨�% ÿLBM�ÇZè!6„BVšI$�| (Ñ39p;�®�~ˆòN¡H§Üˆ¶Ä�tÃ%¥F€ÃQÈe‚¶èDqr‰'јyƒ„^R�Ùs猑 @¥PLÄò%Wå_£3©ÐË€pº%‚¤W¥ò°§»×6¬Ýˆ¨ÓÎ��µ<9È�@cy kÿèàá§þy’õQò ;D´Ú»÷‘5ý]]¿…éþße‘,c‘¯ £þ-·Üb›7]eo½õ¦;vTÚê9n) FÁ«Y«õÿÈa‰�rŒ¬­EßjÑð„”\K\Š¢Í�€Ò ¿h°Eº©Ñââ\#q\}ÂJ¦"¾¤Ÿ¤ª!$zçGŒ$)O8ÃDÛV&0€3Mý#¯S’“‚´¢‹ƒUl‰"é˜âN’” •(%! /xJ0* <5uIGgN|Œ…6l|†›3Øø7lÜh·ß~»MOMÛ«¯¼ã^ÀfßÀ¡Ú­s&*�Pÿ�|e*§®€BšÍà5£\ø‰B°@Г´¨ ÎÍL,©±’Pô¸$ 2�‹V㕌©1 Ë‘^æ“Oð L|9•¤gøìRPÊR4%‹¿Y&ãJ¼èLH*¸N.£*Sò«ÃpÎWJ³èÀD ”tó¸¬Í4E°Rú‚äú@¢ ÉJVåm"‰‘Áñ¹»OXøn î6ìÄF£ ë6a“Y·�9c³x„Xš |§s±óWß<öĉóO4È–ô‘pwÝõØ­ÝõŽoÕ;j÷²ñ³²\·{7:…}vèà!ûÑ�^Õ#¿zÝ·hÊæÐ<•9§ü w¨€òÿ a,LÑÂO.h )AK$øõ«âE ¡•hÉè`ò•bŠ€ŸÀ‹@ÉwHÂ$´»qþ¸`B’ç(ò'B¯º‰ÅéDNŠj€€& 2 ÑŠ¤À œj¦Î)4#BZ�/B¥„ÚÛPV@Q™e~Â*D£@UŠ”òEº¦Ê q\¤žžñAž;ý¹ùY`ÐqtÔ®kÔ—>»nýÖ¿=q¦IÀO$ºr~>Duî¾ý³w×:;¿�G);—±+ÓÛ·wŸmÜ´Ñ^xþ9ÞêØ£ïÊâZgåQH Çk¥^f ×ÂÈWŽ)€K”2] ÆXF—ðÍ£–£ª×òèšfi~{ÀB®B^y=áf>ON€«Ë 2ñ$I’î W¥roR Dšt YÓÌ„H úLªr€4‹@˜� 7®ÛŒYÀ;*îG©ƒfù((¿|èÐ3ÏTe|ø±Âî~ÚJñîÛ»³¦oàáÝnÉåN¾»öߥýÚÏ=ó¬¦Pܮ銆ºeï"�¿¥#@Šb þTA<š€T+¤TôK”{µøË€àIt—+éØ,éb aŒ³bAESÌÌ œƒ/ñÃ�ÿðIä4JZI‰1 y‰–`ǧ†ëx\³€��ëBvhšõ“>ÈŒg½*›,Â+Pºx¢@¨U�9/%Ó¹ì"TÄ Ëéç ÄW%­Ê*ãKÈ£ÜT ·:0€ Ù„xÚ•·«›Ö_¥G×gGÏ`Çá’ÞIÀvõ“¶ÔøòÁwžùA«¬ò½¸çŽÏßU«w|Û*Ñø­{÷?~ßǵ?ÿYtŽKØÑÇ�VÅ#GÁÈSã§á}z\nðÎãļêÎø˜F¾cdq–âH¸ä;YŠ•¨J•LМ…‘žú!àáÂ* é!¹�L^òÅXºÜ%3â麶.·D�ƒ‰-ÙÊã¸&D¦ É-¨ÌQP6ñfó�¢ ×”lVˆôP3£M yñF_³¤÷Œ—”n“Ä ì^Æe$íÊ÷RfpKÐ×ÛgCÜšŽÙÖ:êƒx£ô±uë·wtôøOlMà'Öܵ÷‘[k�µ?Ä*év¾žÙ�·óî¿ÿ~³_xQƒ3oXÊ^(Š( yŠ‹:™†MȨ~”E!ˆ¨³§ „E_ò…w•§ÈЈ�W*yXØRz’áx¢È'ùô•nøŒQ>ý€ËÄ/Œ—($G˜à+‘–‚‰G©)�IF’êÉ94Ë+E†kÀª]Š_›™W3¬xf€ˆ48/â�²L\—$UÁä©B.’@!¥ÄséܤlO�ì7�'|Ç`x`X�·°ãöêïg7 m|düøOä¶°Ý=pÇÃÛjÝ]_C/¸“ûöùNþÇï¿{ÎÙË/¾ðìÜ ¥ò�ž…™ Õ�&ч“1âQA Ðà)ßÿÚg?ñ¤Î�ýŒÏ$É…– ½#o< |“XÊ£K¾Çüš`ò¥W`+ˆ2Ã@ú¿åT[sbžDi„L‘•}ò¼+ë™X ¢2°Åܪ…´ÌÓ‚$ ‰`…h\�%±íý-ò”\J�•üK  · s`vþ‚n xk›†v5:;þàê«?±u¥~œð}Àçüµzç×1òß»ŒÕþîî.»ïã÷Û(^Ñ}õå—µ›�od¹Cµ–}q ;{”Õ!´ÊŒCî4Äì8Ñ�VxÄ´?„“ã¢9ÑD™+ˆóQ)�t+ãöÔE§DA(ZgðNȵpx‘o¿›LôR I¨øŠðâ"áE |Æ$ӊЌȇ5·×š•hZ‚"XŠU4 ¼ŠËÚš(›¢‰¡ öX†å2 êŒHÜ ^ ŠP•¦^†”Ã%>€†ª\ÀÛ©|D8¸fÈf°�˜Û‹q;º¹Ö±tûΞõß8=}z¡Äýc¦÷cO(%ÐÛUÿmt-cäç}øþýwë±É+/q䇅òH Ã%˳¢Ñ°ÒÔ?Ém¡qªªÞø“0úÄð�5}å_™’´ú1¡%ù €’“~$ \"q*qIm�+HÎP°=OÐäÌ2^ð¥PÕ�X2•r¸HUGµ# ¬¼"A“Is@�°*wŠßDÓ-S¦p•g†‚ØCJ*há½7W¢H~³ÀR¼E¬ƒ²�Ñ©D†7‚µJ�@Çg¦úû~«Äý¡?ÔÀÝw~Žwü7Ì07Mpƒß°zöY> AÓÜŸ&qãæÆ¶ lt�FAƒ‰ª¹ñ ¯FOû’j¥?ö�)¥$�qvJ@è­Kw®ÄÍtšœØƒJzCJÖ_H1h NšD¸t§õ´O¯ÌSz-‚hN&Ô bÇêÚLH ÂÒ/â²K ØŽ�¤­® e ¨�®$$¤…ÈEW2ÒD¶O:4a¸�ߎÒaƒ@KBcèÂÜ Ö½ôn 7·Ñá6áîõk·½;2vü>„ˇ6¸ãŽG÷¡’ÿ6ó´´¸d»¯»Î6a—¿ß ¹*^´0^¥àÈU²h,üe- Ë`’ÑÚøÓhOŠ ÊLdL?è"9\¿Ï”%ÙÑ P-8I¢2É ? qŠ,“X§(d«OJl.D×DYen'©°WöÊHÙ ý;"£s ”¢`¼”�Yp)t3-”\*YÅ pBƒ2“ŸQÁ ›ü‚ª’EDÕPÔ™l•Ð qÚ•àÄúœ’iW©ª1ÉÁ#‘ñsèzm[ˆùÈÿ`¬ÿÎu×Ýw›h>„ˇÒð¾çnÿ3ŒðÃ|Ö¿ Ï�7ÚóÏ?¯G~¾ÚÏ̯œcG•ªJÐ&úå2-7~of´.“Á�âŠ6‡Õ!ˆÍ¹\DH¨v!܉•NâË ð¥,"ÄÈÅ\ ïÁÐ[]RÁX"+ɬ@AŒx§SHòP_�•(ØšI„)€E(ŒWp6… J¦#u3(Ú˜­À5 \9Z®( ºt £Œú’*U5–•‚l £xg`ë|¡ˆ=¾µµŽÆ?Û¿m?εüñ»¥èî¬ýÞ”ú8Gz.€Ü�©ÿÛo½eçGÎã9ÿÅTHÖ,1×£€5Ul6“rã÷âˆÂaÑ� <þ— , àAàd$eˆiè¿;]Ñ ˆNâ@Cz£ä9¢Íµ,Ÿ¬A’ü‚£Q ÌEC¥-d!J«Æªò¯JE@">�ÚÀ³Ð&\S4‘UÁŒU!‰îâ~Áóþ$|+É�b,¡/ÎÃYîüÂN­š°µ8h„m¡��B¨K÷�÷vþFIÐ�-øc_Ø¿ÿÑ;kVÿ]Lqºy4·øòàÎW_{Õ:y*k®œÈvª<%˜—±7/Ç“Žöpã–»€ZÖýàsN—Aþüeû“BÒ;¥® û¿ ÃQŽ ]J tßóP‘<‘ŒÇDœ8}‰²9­K–j,D†˜3ETù.¨<&Š2}9œØ['Fé%)ìz�µY€H36Å e3D�•¸«Tmbѱ uPÊ P+)$… )f%âj¬¯ ‹óÚ#Àóøò�¯‡uܽaxë�Œ�8U帲±Üv®¬X—öàƒvֵ߯ÂßѵïóóÀΗ_yæ)¨n5�°•‚tùj¨Iqј^á\ž§£´ ‰T�aاèÔ¼ç/ÇIW4"†ùï4‰šqçR@xî0^�Ïã—£Q)ÔÌ_N£™ÌiGÒ±D…`ÂЪŠÄ'»4•�“T@e¹­)$ÒJuaILá§�‹,bdO±ðSÔ%‡üf âÊrZ$’Zx T9TM�±*¤%ÞŒ–°è¡"^Në=ÃíØZ`-€&±mðM¶hCÑ$#E/�$U*ƪ�$­Õ÷ÚY†sð™™›Ö+ïkzý©€ð ûÍo|`°L{%Ã?¶`qnùïàEž¹Û�GvïܵÓ^í5 nldí ÕÖšÕD%—TÆ­&-ó\ò‰>õÐæ‘&aAËWô Üc…ïRƒ†‘R°MT)8�_¥/xšØJ$ÄØJ~‰°5˜ŒÑ„iæU<s ”ê{ú"|¥~´IRk´“qUÁÕX&Œ@[l“-ÚÒ4 Rü(AR¥ªÆÚŠÍ²Q—HÞŽ�·§f&±5¾O‹è©@½vScqùWW–yy˜KpÛm�­Ã¦†  ?˜ÊìÙ³ÇΜ9ƒ3üF4½iU¹�5ªTÉf™²5P�9‹=¹0E&/:#” … ŽfŒ±pV]Ëá6ñgòˆ•yr8²øYÉÏbÛÀ%ÅÛ"+›&“|§,bþoªc¶Æ§¤úaífû6øÎ†ÿ/ð‰>ñóYv!µ½>‚’¨ a+¨r©Ž*Ùb…dV‘:úЧzRP4é×-èvÄŽŸ8iãcãÚÎÎ�û:˜¿÷vÉr…EßÏŠ´[HNT„ Ó—àÄÛ* 8 DåLŒ™?YÞ×Ó�tB¶@ÿøwÀ|E;€R’—�£÷ Ù¿ÿ‘›jËü&Z?¿Áþ‰Ÿù”6ýœÇ×yu/)~T(Ž^pj†V|Â…&]¢"©Œàò�.â"N8ÿ)St¢Œñ9‰`IN°9�:¤‚__FB£çô¾¯¯#ú»æš]vÃMøJÒ5רZœ;×Û¿iöÚìBÝÎbê>=�¯)- !~ª »†!¾{iÚj #j±ó§$A»yK��À”ýÔÉ Ö…†Ý�;ˆ%LùèxØ1P_f‘¼Lãcwl´¾œ‹?Æ™r…Þ¤ÿ¬ áÖ ïú~›~ÇaMñ˜7Ã!¯�ÛÛiKkºl¾·a˜kØÉ©Svðôa{ãÈ[vàð!;yê´ŽƒgÞ9ƒdg�lí‰3u8¤O¸VSvZ@+ 6PNY¦sn‡dù]•çi9¾šN! 4 P ¡š[(Q$¾@6E}êÞƒ��CƒkñÒ ò„§;–—î|ãÐß*Ó^NøŠÎ0¢ü"zÿ*ÉÖMÛÔ‹�¤•¶†T©£¸Þ[q*[Rä2.BÍ~i'µ™š…ÄN¡WkeZ„%:E¬Ù�øœ|åps,âàq*¿VS-øY 8�x Fù�;·ÙMÛc7Þr£]…ÙU÷ð:[�ûøÓçpÚÌ$&Ý>²Ï`ké,n0™–ÉÑvÔ€pS�vŠ‘Ù. _Ðû@æ1e£Þ ž>³sGqž}gÚ!Gä§“f` -Û?;�ÄK9_µÛîîµ®Ù~ãÇs{æ—l`ßqê²¥yÜÛâ‹y’ ¦å9ìyŸÅìclk]¶¡{�mê»Ñöî¸Á.\û);ó‰óvàÜ{ùÐëöÚÛo؉Çñ ¸)éÌŽ 8�Iª5Õ‡µ¿FfÚ#³°*U5v1VâV¦nƒiÀÙž a)u¶ïfÛ„ï!6°`7a]6‰‘�#ï6Ì´è ^ŽÐ”3�š®Ž0§î4;GqÒ0Þ¹|Á:—ð1Kˆ#œ�~ëÖvÙLmÁ™4¼Á)zŸ8-žIk@™L�³ :™}ÕÚ ÝvÓ­;íÂQ„'pë‡[†Þë0+9¶`óg‘&Ø­øX@ßã”±ÜÑ…õ|ãO'gý6×»h§ÏÛëgÙso¾l¯¾õº�:uJ· ìøK6¤Œ²k�”ʰLè*� “²N�òr"¼�ƒÎ*Á2Ži¶ºVMÊt.Ÿúâ³ä� H¸j»ÓˆA§¥ §ª�$Fú‰@0ׯŒfÒ\áåbÏÝ„ûù;ï½Ý¶Ý¸Ûú7­·nØñ…©<^Tc퇎}¼'‡®·÷£’šfÃbRø äñ]2NÙ¥åWGá̈…f /ÖúÐè|=@:�¶MÝ&1{›˜YÔèŸÌKŸy¤=Yú  ´`\�CdMjÔÄK§lz?¦ÿë‡ ë€6wO( 7ìÀÅ0:æõ£Ö]·z7|ÐÖ{Óß‚èB.)›O0“Dçwëâ»åSŸ·‡î¹ßž}îy{ê•íe|(ö ž,ðIˆn cÕ5Ç«XÅ@B*¨®KÐö>t¾„$È+² m)!² mùU¾)ÈO‘cÞªm<Q­*?œ*ü&|Äóܹ³ˆ¢àpßé¹.L[6"³OLÙ0¹â%x0$º¶>€¬¤’“k�*�hœ[é2Hý+"5pEyIpøHÀc “—BbW‡Pâ ­‚EÒu&G®M×Ûþ»öÙ>4ü��[í$>1=c§�ž°ûPðýXZF#éœýž² =tغÞ:4zÄùÙ<ųéЇªñ'‡€Ï u¤y–ñ…šE̺<ŽÊóàºN;tnBê’–›yÈTCÂLdêlÔ Hô£²2gƒxÑ«ƒÀ±OÛõ÷÷á´››=3kÝx¬XïC„†^GC¯adïÀ= Æ{å 1 ûÖÀS ›ÀcÄy<‹\Àí¦�Ç)HGcè\ƒ|¯Agvrѹã^»­w«¸y¿=uðGöü�^ÁZÁ Ü¢ø÷$¤0•¾˜k‹n \AÊÅ?帬,1(.pº•�ø‰Ò“]:3 u²w£ñ0˜ÿ %\®ã@rÙnÿþ7b.øßBÐü¸þú=vøða›Ã,@+þȈ2&Ÿ™£Ñ¦+�|ä¹—>â#¥ŒPæ'šü"[OYÎ…Š“ˆâÌ!ÓżÇÕ‚KºÂGjôâv¸‚Ò­WÐã¥Ø£oÛ¶Ùùì§í±_ù9Ûv÷>;Œ�¢<9>e?Âo•¿ §¦gmߺ[ìÄ”˜­N¢qÙÖÓe§F—ØF4âcpÄ“w6AQÄU,9L\R…&it aqV Ó™ëÖ7ØaOL•ìåé‘�R“tÎZ(HP"ô«Ù¬øàG…ñ¢Ñ±d›oÞ Ž«s À¬mÜ%8 Œcçàù9[ÀºÀÒ¹Y[Dxi›„¦ñ”a–�;¬þ#-Þ®pÆÀî¢sç;‡ÇŽ3§ñý=¬ b¶0|zÉöîºÎnÄ–óþõC6‰‘rjÒ_¬Ñ�›¡õJ½KΣMÀÞ�—Ê´W¥ªøIŽÛN¨B„õ]Ÿ¶GxHjYD®³25ÎÎ\ƒ—\¼ÅІ »ïܹÃ~˜`fzÿv­—í�ž�á±ÏfŽhÃÃ�×À³ÿIóì:G¼*†EJ™ªp‰™óFq(A +bˆaB¹ÍaÒ¤N€ÍƦ8„H[–Ë(Q%�ô][ÇâªD ‡“¬ð"M�Oñ” �ðØp¶o»ÊøÄ½vëÇï°Ùõëì%4ò·N�·iLq»�‘>T†~T>~›Ïóïž²»®ÛeG–¨Fbˆà>‹yØ?Þaqê�lÐ4a+%� m£JC¢á-ï@»ˆÇ†¸ÚÆáº�š¸€v‡5vÆáÈ«ÉCïûTÌ ŽÊü:h�tð¯{”Þ klä v ¢AÏ™ÃL‚8êI=VÁ!Æ‘aÞP87|êŽa¼ý«-a¯¶(Ï÷ap‹‰OžÀlcÏ�u­Ÿ´Å£#vã`Ÿ]·ç»ÿÚ›í»X0|úåìì|“�üL¼ì¤dÀp[`3‘èDÙB¥å D1€_ÚÛÀÑ^åÒÂAºÌ%»pQ�~y˜OØ0'»ª^_â:À÷ƒý{Wd°móu_Á‘_�RQnBéˆõî»GcJ£\‡i¡ºò†j˜ý*>e‘�i™MDøA…^@â$2s“Éé—èê±òµ ÷ª›*}¨##ÿå23À SävÙ ˜ê?ú¹í±¯~ѱªÿZÊ#vt�£âTˆAŒ½h|hE[MÌa6€pvö�ažÉlëé´‘‰e»€GmÌ;þ0qιôlºŒ¤+›*œÚ–Û´ tã±__o— -ÛïNˆ¦lÏ�"é ΑÙoïÐhì†þÃ\ïAjÈð{»lýî«ìì�yëßÞm]èÀ–°¨Ç‘\r$˜%É,ç!ˆ‡IAçU}6Š]ƒsçpžÞQ`Ús ¶vÏ[8�…“¬6=oW¡S»mçµvÍµ×Øl5Š­É³èœ¨[‘vœüRZ ´‚ª·Á“5Žä"Ï5�ôíÓNÇ‚½à¨°‹€ú²žñI·R×ñ˜V{õìÙ#O x—+2XîèÀ±_î¸Ýt û¿UÙ’bŒÐø,ëplXÞë»É¼$,üà“†õŠLœHàty´CKEë •é’R±�áE� ¢¤¦èD-±¦ÒøCŠÏ(¢¡¶€Q}M¯}òS÷Ú–·\e?Ĉÿú‰ó6‹Ù@/ý0zõ.d ›8õÕz%d°‘¾qnÜ6`¯þ|Vj�­Cðè¬/þa ΃¾|þD€O9:1=`ï�¯¡ßårQnJ÷ñåèÒ…—æqNû¤òLy’½¡\Âøãc'0§qÛ€t‡*@`&¸kÈf§¹#tÑΙµí»û¬6ƒÜÍù(O[»5ÙÝE®‘°Ê2¥O ¤WÄ×÷ÚÔ[x£·Hw�——æa‹wçlí>ì:}ò:\ÜMÏY'ÞM¸ ;!o¼ça{òšëíñ~hoý€½ÚÙmß9;f‡§°¡´C¸!Ä�#>GSïPR>³v)Y;ƒ…Á°0Œï(LbôŸÀ¼Ÿ | �x .7bó`Ý®‚�ß<Ò¬Y/Í:0€,`Ñm��3‰QlÄ9‡…ƒs3KÖ‡­¿‡ sǺ.;7Â¯Õ }å'lTE5vÌH2<5ƒÀ¢ì”¨;±zÕǶØÄYvL°nU¸V1¼½Çαƒ J5$R�´’ «Ëè°è\×m“=xJq3 tV¤ë@çÂEÄ<µ¨ ôYÿœ©w Ûfi`¸eÌz€»~§P_{­uÃ~ç°-}zjJx­;I’RJ…-\ë…Šê¢[ÑIê-Ȳ˜ÎŠš1-¹Öö¦ûz5znLBÃg�eú4T%~÷3º\%@Œ4Ô/éX,J‡Î;þÞ©SG±i・4óüÀz::6C�u\äG>ÙHæfçÜ`Ô³ÔË—€JOh„*dí4�%ظ؀dE„qôÕÔ”U©‚szá/|BéTá<ˆkÍ B©B"K *Ôðƒ1vÇ7Ûc_úœ­»~·EEøÚëG5-_‡¡•Dõ|šƒ—lè¨6]ʇÇŒ\#¸„Æ5;Ïv/Û[Só6Á{q Â�· |ÆOués ÇIÖ/¥‰K. °�o‰®Ã¬áöpñîÈØ¢íÝÆqêßqvÂîAÇtõ}Û··î°¿xîá{*ÈgjdL²ê܆U˜Ç¨KnðQãÈn�S�V—¡iüΕ)ÑaÓ6\ÌÄvn¬µÁ­›�­_/ |pwÙúõØ´ÐIù™/Ž€<¤Å *hV% VbE÷ªú4!+… �Ô¢%i‚‹Qøê=ó))""‘6£…I#aº&ŒÃ„(�Š2å¸,ܯ߇ÇxŸ}ì!»çg²w:‡0ÕŸÆè‹ïƒr÷ØjK¡3¥°Ê2oÌ*Ç@†é¢ î¤ "6Ök7 Û‹Ñwaã ïíçQDZc•BæQ»Q�¢\¶!éK^—$›£Ai«-ø¹1„—q–¦¶}�Ø@v·×ïÄÛ\|��à(’P¾ê\!«šÞTµØ�Ýø«qm¾¿¿Çú6àþzòV@«“˜q×À}À¹#ó¶íº<îCçÅõ Õ¾@Y?XCذEÚ\D­mî·1<&l`!‘ÓjŽêEI’Ÿ� Þv„¼ñ£S¶ö¶­6òäAØ’8’Ò@ø/þæ'flž¢üÝŸû‚ÝxÝõö¯¿óÇxd}²‘?MÈ@'N×Ãe�ƒÝô“’Žtê¡ø«ÐJ¬Ä[æb8R.À°,ÙÁbû@Ù¾j]µÚòv]Ö† ËîõÆvŽÊ±ðÙ¿žßb´£ÚÌ+y‘ù"Ä‚MF¥“œXs˜öj¡‘YXeœž£µW ÆÎF'™CF‚‹À‹:oDA"€d¹˜šã™ý®]Ûì«ó°àt—[î²Ù™9»ií ½{h\;÷ÈÆF(¶Ð«œo"˜NÒ]#)bü'ïˆñå~l¯>€lFÐ0÷të^~³柲}¶â²°0«íÁ=¨¬|½·ñ>اS÷:>F±ÌÅ$×Ý rà½.w¼ÿK�+I!ü# Ê ³âCUðl#�•Ãb‘pàñ’¦ìª©”áP0Èõª*Ñ^É‚B†S­#€Eäé;DáUJ�ñ&Ç—xzñÎWÿÖ—ìúÏ œ*º| ¨ �ø©�4?+r7£Ððg1E?þî {÷Øq{î…çt2Òf¼mzí®ÝvãýA§˜@IDAT5·Øõ[÷Ø–õ[­ÏÁºHc�ÅÑt`?z`›xgÂ6`= wÛ„Õø(°£Û§Ç¹nˆÝ„ G>™¦2�û4v(wnÜjk~éWìÿxü�ìùgŸÕhZhôÜúKË”Eª�\™ œBž=·IBµŠÆ�¼’…åÆr÷Ó¹$ç}ú—Ý@'¾� GŰÈ…—õ æÂ;¤u„Ã&żÁ³±°23óš °²)¹YY�8JÌÄt'õ+é²#Q)šáMV\.ŒqÚÿ•¯þ¼]÷™OÛ7ðÖÚl7eãg#D£ëCÞ7cßùilÑ�}7uÆGû³€ÁÈ}ç–õöÖü6ÎõTþ˜¦èáCµåu<Ç[ƒCÙϼø²=ñ½'ì¥ç_²“8Q—:Õ¸�›¯|šJð»1_ü•Ë qÛ/Ñe4S”áJé³aK–�®—l 8uT Ç�”‰¿EE8Ñ@Ù¹n¤Ò¬" J:ƒFÅ£ôCËœ�-щPWÖ�),ÜMŒ°ƒØ÷z¿kqêôuWï¶[vïµ›¶ßlÛÖm³¾¥A<åÀíf Ì¼ÞÆzÀ�;p �G›xw >܇W’±ÞÑ‹Y’Î"Àþ ÜŸq;´æxŒý3 ÞôÙ/Úÿ„Nðit< Þr¨§Ë™A€zV]†” W%QŒõ*»R0Ãߌ*Äj°ÍƒoÁ÷þB—Ýää¨iÔ(÷Xð^!<³,A¥¤ªf*eŒ¼ª2€#X©’ø,„év‚‘tÈ‚|RËp`§SÅò�î ¤ÉGãÇ´’ºýâ—?o{ù´ýlF9#?ëv/*·õÒ±xÓNŒ'Ð!ôä=û›“ó¶ë{ÖÍÚ›£¾ õlRcÚÊÛJÆÐð¯ê·-Øhsö©Ú7þì»öòK¯`´Ç(†´p6¦ø´ò©ÓŠFÅ2ÌFÎwø¥GØÆ->èŒq?R…ŸbÀ„à™2áB†!hw&Ç«ÿ‡Ï{o+œ¦ªub çóyf–h&’:„Ô)�Rp*À¼�‚A†ñcÞÙÌãLA.pò÷ÃçžÖhn¸f�íÝs‡Ývõ­võÎ-š‘Õqbÿ3àOcç ; ß!)5t‘FÌ c^(R!aRΜN´MdŠÂîð[ÄXe¢Å/×]‘€9ò,¢=z1Bó²X™�é!™ŽQ8ò²ÒMÙ£P þ(G‡‚�€øˆN²BEJ)çWÈ¢ìpÞR,ù.w÷ƒ÷á½ýOþÒÏÙã³uûÑØÉyãGÝÃc8¼E‡t¹QgG_:¬N‡~ÔÖu–†Ò•ûðŸÇawlßhß;|£ pÌFêí8õ÷&lØY:zÔüÏìé§ŸÁ—v0SÀ¢cOOn&XâHW²Á‹çÀ>�‡ï4¥EÐ2/´+°Wš5…IEãö Ý"Jq…PÈ|ä×Ó§,dz±;”T”_²<îÌ19¦å? Š×aä†`_æGKÉĽCÀ¢!m¬t!é9ãáìˆ2æPn°CØá÷'k¿c7]{ƒ}‡Ô^[ßl·ì»Á6îÀëç°Š y J ¾ªKèÁÓ‡ØÐ¹&p#Ö~þÞÏ¢Š§LÚá.Ò©@Z¤»y…­P3 ¥�.Äó¦»öÚöØßø’=[°§OOäsòˆ_‹eNÿ¹pÆC<8êå⟸Cu’ÎŒ³ââE¼Ìr¯uÞ�õîXƒM*·á•­ø*ì‹ÿî/ì;ßþs;uú,Fü.,:bÄG‡#«%µ‘‰%5 p�¡Æ•tv= t›2�ðL™QØNöp¸Ð´³�Ô�pÚЃj _Šs‘j@žlB“�lêàA\¡o�±ì˜°w¤`ùi..ý¸vÁÂ[æñr˜¹ó*ÃVXÉà,…ƒ°Bâ¡,>UÃçÉžyÚ^xíel>ÚewÛg?÷é‡ì¦ ë­ç)6æ°+å§¥,6zv訚ö0é x³ßbøO?ù°ýc,$þèUì¾…ü4S–Rfir©žg0…WœÂ:L.�”ÔüÑR—ë.»ÈJ Àb‹ÿ¬—ÊÚªy’XyE š°8Y€ÎædÞˆUÅÏ2F•(**eP2ðåÙ)ËJÊx¥¦Œ)1Yq–q–]¯}éW¾h'6o·?å}#ب/+#ŸÁóÞhôÇŽ¼c8Êj½_Ñ¥štÔ!‚‚3†70S¸¯¦Þ³ œ–¼iÿ÷7¾e/bºOåº1âóK;Þ �•£ý2¶Êú,‰»þ¼ò+ïÊ,óÌ’}¦"‚ñ¢’Ê6RxíKšy%�Xp�ˆ$Õ•)ÃHNt.^ &—ÈTB¨[šå‡0lÆ-]©ŸÊÚ}Í<Øa�ši#!Ú‚!Y¹SÇm“nB7Þü0î· \/˜··ßz�Ù÷_|Úî¹õN{覻±â¿Ë†pùO$FTù:7g˜ó£ÇÁ ›¨ö¯é³_ÿÔÃö;8\ä�·ßö­—ÔJŠ¥œV}¢.îœâR? qôSøâ)\ {Ù…{ub¨È.U+bÄ9ª£GâJ^‡¥8QªLâ�U7‘�ØÄ»Ä+–�£R„òP2“‹$ ‘Ë�ŒJø¨ˆ¸Ï{è Ÿ²=÷Ým¿wú‚M#Î~lðýhàCX…’xÐòìüuXQ~¯£²Ñä >ï(9¶Tn3ˆ|õ?ƒ=õ­ÇíÿÍÚé3çÑðqp&:ê¬ÇgÔ÷õKÜ#�šN ÔëløÌã"ô<‚V �üÒDÙŽ$¢°3-æÚCÆv.àȰ‡ªt êœ.�YžÈ=eÑ€„eã�!ä! !–bC²xIK˜ßŸ{¹j_°z§ˆ§´!—ûåÉÃm³d„&0o�˜Apç»ï¼cÇ�¿kß{î)»ëÖ;ì³{ï·»6í²µüŠÞð<¡W?äëÖïPà�°uxú³�ÙÿºðM;9|±ªÕ9¬È53TÊSâHt)>ÁB%¦€·ð6á›Ä\Jôò;€PÊ=š!–‘ /ÜxDtµAãÀÍÊ-0<@ «¢Ç BZr¼Â8T^B¥�'@¨ô‘€|qy.“×ELý÷Üp­íô!ûÚè¼mïï²C“u›âpèÖcô§ò±CØŠ}ÿ#Øu6�—t¸> �•6‚pÊ.©CwŽr·õÙž‰³öõ?ø×öøŸ|·øxÞ¤d%•ŽÃû_.êÀŽ b ã¢òxá+û®T9�+J%¿‚ÒŒÊ9žX9—`‘ÜÏàˆ¤Kü‰ÃK§D˜òƒ!ì“bDÉn(Ÿäw[øœ/€È;†i3ÎÐprmÒóñ!oô‘ü á)ÕìH{ùöÙoÛ_yÁî¾íN{l:lEæ[ŠxaŠ­�P]l`_½î»éF»åÍ›ìüùó6‡�¯å[¦L§²Qˆ‰*�bq` åð ÈÁ«±A3\¦»ü€ ¨V¥Â@<´e±y³À#îEéªi«•+äF]Ñ €¬I†�L�v zØ¡¸’Ÿ—С\R“„rœÈáVË<‚{ä‹�Ø|vë/��Ùµkzíg6¯±ÇONÚ:Ü÷s Où¬ôÙ<Ç(¨“ôñ¤SZªC”óµWÞpî¸ýÉïý¾ýå_=‰ÑªŽE¾n 6@ûÔ Ÿò4’±+/¨¸$ÀÏó$`)ŸHƒ£&°t´ ctº ìñ&ŒtËt‰$8M™¡¤ DÔ© oÆKN»KèßXš �Ê_¿E®•팜Á°>K`‚Œ3ç|Àè��ö: ±/⣨ºÀ̉OChKí- ÏÛ8”ùÈéSöøù?±ç_{Ñ>¾ï.ûÂÞìΡÍÖ�Û†ýÉâØo1‚m7ßy×þð»ß²×_{ÝæñÞUr;SSw^>9’À%ßi Ž*mÊ{b �›Uš Ö™Hß·:€¢ÄRá„° ÿ”ÒÞdx�,§‚#QT^e�2TÑ]€ÐÁ” ”¦ PÑ&^ÄK �#*R:�Bq!>‚”ÆGI÷<°Ï6Þ~›ý[ìÝge:ˆ—Y¶`ÿC›ì� ®òS¾À殜ä‡;�&gÊ«tEI>f¨vË`¯]þ„ý¿¿û/ì{OüP/OñÅíœC&—0ÔÃç‘�ú„*¨Vÿ©9e*�©¸îjÊ�Ù@ÊQµ`‘!/)U z¡*Ã^éddêâ3Š¡L†±¼âÓèEcK£½“#c�/Œ–ŠÉ•H`4@øšìÞ{ï°þ®³gð2J÷ܬý¨ˆkq(ÅÎMÛ§7 ØØüŒ]@%ái:kpOxh çÕS –aä‹ÚrK4§ìlüCØLrgmÞžÿæ7í»ß}‹}ØÉ~º¥Eð~>ÊÓ7üù¸¼ ç�€‚¡0sLç×ÀHaT¡hRRJ´Ò/‡Ÿ%dû„ÔŒpB�–�ÔÁã¾BOº„?E#-yí`�W>Ñ!rQ�êú*–¥"\éÜÁÅAÄÍ*†AÂ2¤%½~±Á¢\Ù+ëö€ ?'Æ:Ä$Ø °ÌðÃÎÀ¯¿f¿{ò]Ð/ã^Ÿ_çÅÛ7=\cà"0ë‡óQc׆2à*­Ìeš¨Úû!°­Üö— ½ü€%�’u€F¡kÖ•`öÄÂD˜ßá¦AQ`dJ DYz!Êei¹|VCÁ´ åÕÕrÊ$“p† % ¸¯¯ÇîùäÇí `ÎaySCNÅ×c‡«û$V–^‡3îÜÐkßÅWi¶aD?�m¤°ªÌ|Æz¥¦Á$" ÞÜ�™ÂÈž°oÿñŸâ|x¾©çôKœòÏ•}Mõ¹ÀY Ó…æ §˜ë\ºÒ€¢ôü*ïÊ\؆ÜNžusˆÄË‚Æs &¼`‰„Ëò"XU4È¥„‹‹«K­³³Ó—q¢ágáâi’Qѱ,:êƒÌ†T¢ñ»](x”¥ê¦êKŠjacÇŒQ_,Ä£?–˲عÍâÀö*~ž9M{Ê¥<Ñ>Ù%…S}­æ®©€ÅåÚf”åðVº÷~B—ß(5W‡\QWÆŽÌám›F)>cÞ“‚€4àiîò(ãJ>å"䶆djòRºˆ¨˜šcðèi 4L�g®ß¸ç:[wãuöøŸ@eáh¼÷ø�ðyoß…Q‚£ýzlÜÙ»¶£ݾ{ÖÏ>`z|BÀ A8¤o¸lLéÇh²­¯ÛÖžz×þ÷oý‘Mã»yÎâ# ÅaŸÊÆ5ÄÑ,â—žÀHÍ�¼„§3ìx ¹/ÎrÊáéä‚ËVñty­84å%ÚG3a"\”ˆûz KÈ ßû‹\‘À«”g†W…pa…”¨l¾ªïȼÂ�L¨ªâR ;æÒyy¼µœËT–)‹ydá:2Ÿë"‚h@ÄE• 27ä@ a+îî[o²ƒ¸¯»ïßoÆá–›ñâMîÇ9½çfJ@{Æ©¹öÙ��gpï÷ÔÙÓØæ‹7ïЬ¹¥„F˜·�R:×®Å[{çðèO#Fg?z�)JßçÁï)I‹§Ðõ¥·ØY…os±¢hϺVúÑ€†Ž:*¯”“¬R~8<ŒNyœJsŠìË@!#P,‘It) JP­vÙPRƒ!))Äœ/*A �iªO„éde*…JE(¸( ?”DR( ž¡BVAV„2 ÕˆtÛ§<‡¾²+XÁ[Ãm 㤧Ì«;÷•÷P»¢=iHô.µœ�,Ç«DÈ-{à»§ª`!®Lø¾Â—ß4%W®F ç)=è\@Èa„|šŒ$ž° �¦BBÜ9âaY¯øàeú‚EÊÁ+¾¤›ð¢L÷1ýïÆBßÎkwáäÚ½äÓ ~;§ó˜J´Bè x;° ¯?��K`�…Š{ÂN—YÆQ�P w’ê©©P'o°¸xúÔ Ü2 ácæP«óS6ürã÷ʤœGÞ¨\Œ|Ðá^ rã=1´èE”ÑøÉ·%дH‰T$¤É�ßEÜ=^®˜Ó µ©†«ùœ'W–APÒ1á -Ê™ÎX²Œd«*ºˆ¥t›ý,@�xa\ÊäÛ¥‰”€ÍüX2h¬´,�JeUÍ -—l’‘tRr’•d'ǃ– „1�¬ˆ#²\‰úÀ—´~?ò|¢{$抩ʆ¾òâ $‡IxV ºœY†ÛÅE$„ÒbzΩÄ) 8�Ÿä!)|N[øh _²é·u[6áì~~íü¨ì¨ G|Ú9ºlûíÂáKv�'ÊÏ…£,â-×p6#Òt]DFl#ÇÙûKË\åÇœ ƒ�D•‰Iñ�*ƒÑm8Ï‹çAaf8uJ9½˜) Pg&a§ô°@*rgL$�Ù¢�Äœ Èœ^N@@á¹€ÉSŠø ìJãÖù� ¯�M`á²H¡OªetÖ…rhp——ê‘ç“yå_`S¾ä)^ðŠJvsB6xŸö³¬@‡¸fR‚4tÃØå$X•&å,Ñ&ª$‘ñ‚ƒÙeÛàßYá±ë—ë˜ó+à˜Ž€ò¤³ ^†ŒJ ¼æjD`®*°ˆ{v ú¤œ:…\àΛIðt"ˆ�‡¼þç`­öB0wÿ áÈ휺;»ÄwùYYذSã÷Õa–ûöÞn;Šgj«n¢e®Ñ4:¸ÂÏ9ƒ§ÁŠÂN†âT%Âí@ºÿ$ŽùIV8�–®�Oò•¬¨¼Ñà‚­ä”?Y2ˆJtUi E;®’Á�TÃçû˜id,X<”Ò=Yœ-I !Í<Š'FD¢1ÒVÍεL’ã8^…Êȉ$d¨Ñ ü‘+'„,½¡{ç °Ú¿ ñT¨‘Çýš4„@­Ã«4‰Ð&DE(µ!ÔÕ%¼•ÊÏîñ€Zê쥞Òü`þ•»­ [Ò°03À|ÐÔ {�ò$†¥…Õ™ur—¢Œ£0eÇ1�i’æuEBÄ–(‘n® 7Ë i�“n`q9æ quÉHWiÔ Ó&œæs&£‚qæÄ[(]AÃô²aœ9ÁL‰€Ó•’É0µ€ uû¨Ä—|éM4Ä¡O.\Y� =\k$šä':ùMyK8ÑVª±D?)�r…rÓGh0b±®úÖæï^¡4‘áPäðóÔ¹Q%£6‡•ÙT9“%— Ú†5‘¢)“á°å¨PC®h¤@ Nœd‹Zzä�ôâ}¾w ¬ð“[_Ìü6@•]Â.<Ò;ŽOé=óH+Ý*ø}$bèˆâLq´ ³}¶mÇVåƒ�E+ÉI­”ÆñsG #@÷Þ»ñ2š„fÁðr">�47~×8nÞ©cÄ÷]qEÕ‘™�¤zEbL¯ì<'eHs8iœYüï4 "E. ”u]J.µ¸/ùNW¢.E¦d.±ñƒ¶™=Cš)Ê…é%Œ ü©`&I�)'Ú’Ú(X”âbOL´~YOT‚ J¤8!A'/ªq`ç‹«÷îÎã#©cp6O¦`V”&‰„§‚î€Aãç�‡ph±Ÿ'À!Æu…} Û„±«oONá4`î Ôa• %}ê0ô¾>F|œ5�ÏaMÚécçìüè€ÝxË͘eô!-(¡ÿ¢è µ<Äk¨ 5¥¿Ò!XX‡Ë¸Q *v]Âpð0I„åI/�H@4Rzþ‰KPШácš¯{| )IŠ$(¯ì¨oK5­’€<-pçLW§s{KeåìˆH}øÁìrðñ¨¬ ò@Æä.ÒøIöË|%`±*0SW "]3-”çÔž_Lâ�4^v+ÐV^Vì²;tªgÉOy¥‚|�N¥$$‹ .{a 0èOQÒ»l’±rL™~k@`QJ� ìòòÕW÷?=ÍW:%x…†Í‚m8n_ûá·åXw8ò—}‘Ð7÷Lã'O�¶Î…N;|¼ÃÖo»ÅnÇëż£SÖpq e½êå9e T1$‡ö‘T¿(_I²G” ©*�‘LY‘”…'½\Ÿáó4bvN¸z ÇóêÜ~- ¹Ã”XЖ©<\妦 ‡¡=wìŒKòœÀзÌﵤœF$7þ2—Óë5g´œh’çùH±Š/¹lNIÛÈG)Îùeî±gñÍD6ø%6|„Ì‚©cú‰\Ñ!ó]zà²;€””ÌÌ É\¡’$5½&»€Ê*\fMùS,ްrŦ<Ê%©&)Oš;‚2^4ä‚'/%ùC>¿·J#9vªpôñAÈÞŒC<�ãƒÜÌ[æ…³�úÍY& vaðÀ;åK�në¶!›œY´Ãç6اý<>!¾C›Ž’:Ì ¯Êm ”YR>ƒŽžèUÓP$BÚ#Ëôˆ²�[â 8•—K�p¡”7NõÕð}çžÄ¹2Nî”)¹€…Gº”ˆ@´¡•Â%8é�7–3�D"°ƒ8G9 Ê®©s"*“€×%–ŠpQcƒ©` €7 ~Ò7Â!.Ç"‹fÞ‚yc£×HÏgÄ¢K\ág}=žX]Ò/d~@ï t¡ZªtR• ú%¥¥\ú¢ c+Ÿ Lþ—r&þË#•ÿˆM0ŸHxb"‹ÿ(O„.D�â ¸ÏêÀ ïãõ£\6r:Ü"lÄ-ÂÞŸÆcŽúlìü1-ÍGV¼ñÇ~øò vv5´éçíc‹6Û¿×~á«_¶«®ÂãFÈ¡FI/Wž¹)  ;•rOÝ�g%õÆ�HÉ1[äÖÕ#& ÿÎ$Ð5(E„*,Žô<�˜Çkƒ)£ B†œ»qñ(ý`NBÀS¢ªˆ£SbÙþ‰‚†Hzhj�Ô!_ ”D¢…˜ q«B[ÞJ €šöáUüY¸Ã\˜S¨ÜEéj©í‹»"¡$-åÎK€��—QþKøéÄáÈKJ)ûäp¤—ôX ãø÷½ìÀÇQO˜›gTþŠz8eDHvÔÞ�Ï+;Â*$¯,2㔩?J¢pй® XâybSÄy„—\Ãý:¾%‡^˜ûýU \£{̶aÿ>éS~¤ <;ˆDËYÁ… ùOyã×vQHèä'™Oü=÷öl¿ß~ùWÿ†]sÍ.9ÎW�ÝX”Dý=_Ê/ÉIO¯`’VF‘KqʦÁW¬ø‡|’HŸD>ó‹MJiq�Pׇ�`¢ = ¢åÊéR.eµpÊ^@¯±Éžn©Ä �pL'Ñ9×Ày¼i%!¿ªú‘/ |ëVÀ ò’ï¶§]JøÊl’Zà :R3�|n¿¨Ù_º·' Ó)\ÁŸ1€Zu)ê Yï/tÙ€ÛÅ«Œ«”«4A8ÙH±ÒΤ@¥Éâd ÅÂÞcEJɈªˆ‰-1&?D—ÄU�¾¨‹OLuaôcãÖ |6òA<è›a£x�WÏþ çÔé³ÂòàMû�ãþ ›ƒ`MêÕ‰­Ã�Ë8jZ· üÕ²=‰£ä;¶Ügû?þ5{à¾{°“°Ž×�¹ßœÊ'1è‡âLQve8PB3¬¸Û7~’OÚ›Œpº CÜG|<Ãç=þÿÇÜ{>yšw~ÙÞ»q=Þ¯™ÝÅbX,@‚$@$¤ŽæHŽ¡Ô…â‚¡Ýé?Qè…ôòg#îG�È 9 b,Ö»ñ~¦»§½wú|3+Ÿçùu÷ìîìŒâ®ºÏS••™••U•O=õ”)Ž/¤’¶'ž„É¡ Y)%bKB!±¸¸k¢Dªܑ²òœLJ”çÝ „"¥ܢj$RQà©?U ZÿäÓÜ¿„È£² -å]¼%cažiˆÈ]kó©ÀÄé}ÞGòYkRû¦Ä�­^Dåšþ ˜žL¼„?7i>ùþäæ $õ¼`½òHÁrª¸(Ú.ªÍ =U ¾8Yã]‹�–‚òJNá:ˆJ¤¤S½¢‰ôšJsæ)žßUffæ8-vÕú†Øù—ødÉÏïh_¿MÌ.óN¯÷}É Á#O| ·…E=ùïÐíW¼vö‘a@>vÿYïàäàíd%E¬ƒó÷Úì‹Ï=g¿ü½}vâ©óöÚß|ß®_»Áà"8n€œ9 ÄIþH³d[ »‹p�·‡7þB ™ä…Pzñ´$”@~ �RMçé»8 Ë{Ò&ÞQDäÑ %$ðkÙžâK™6H² Lü�H¡(÷ïJÇu•qÜ�¼0†E²äîòD‡†|5Úqž¬`LƒÊjìÞV6›øUPi4"Ò›w±jIȺ™*XI»ÕüÊ£^Ÿoö¡;ò–*Œ=Båmg7. ;±E'âÖ°WB�JÍÈFá‰ó§„¢#™ðI?ΫDˆ­{¹ú“¦¾kBËn.?˜·ƒtõyð¢ÑÓ_[|�2ÃïÞ‚ÿ‚gõy�°ÞùïÝáɯC#<¾¼�HÙýõ7¹3U³–ßHÿµwWíÇWöÛ¾/|Ë~ãøCûÎ?ø®�:uÜ{úîKŠ|Fš • _ªH9*ùJòÝÚíw” Oe �ˆ|Öž?ñƒ>\ÿ…$Y:†'é):â¤Cÿ/ÂŽRѽàûM°„KG„¨àÒ‡¯…B'â™iJ°Â%uÅÓÁ‚6D)Ø©sP3îÁ½é¯ìDå8ºìú(ü“De¶Éº�MžöòWªH„Â&‚ιÓYv¥«¨Ýi·2zôÐèȆH±Yt ?¥ªÊìrãs#�yÍ)À }fïÀ)Š’³ZA$dU–*�*$1 ˆ_S¸9¶Ú}åäÏ–8xóÒGWì—¿xÖn°õó"�P‹|ÆûúÅ_·5MfÖ[¬õ§!Ê‚7þ»ní'|àP[T‚¹Õ›vo³>/yEwÑ UÛ›šÙ²™¥.;tø¤ýÚ¸�|é vûÝwìý7Þ´k×oг`§!xúŠº’'‰™w_ñ†Ÿ$ ãç?´Rà"!N||ö"~wEg%´;£¤´šM¡+HðIV‚;AZ Ò� ^ãbn;ÄØ®hZp+h-L“»G‡®º�‰*¿VñÀMv¦P竺òü©ïiz¡DòUJ5UkdÖ‰ ±‘�V|B.ŒÜ‹ßç¯ìB|4Àãïêds+ÖOÊñB—qÀ�‚ô.–Xõ+�"¯¼ù@k�þ<ÓÅDI‰%i „¥°.8/ n-ÀŒ& wºGz¼‡_¹|Í^¼7egŒÙ{óÞ°vØÅIŽã†O|çÏN¶õâÉû.Ö^ôÄ0�Hk TJSãZaØÁ"£®¶[ÖÝ»Ÿ÷ÁÓÑPÚà¨ÇÀ[…ݹÓaÓ½6Æaã?wȾþÒmáúU»úÞ{v•£§îOL²”XTˆFºðL•,*’I—ð»Wù*Î×â“XP%´ÐUÁ¿"miü%ž›ûˆká× O–ÊdˆÔÄQò'§k»7r >UJ¼ Z0€ó_AÝ#Ü?}âY9á%Q…€·àȬ¼?å¹×N~( q3¦æ'_#FÁ*²òÔ,›¾¢7�² 5£ÇÿØ ÞüÉ€j¢ç¯d’°º¤¥yœŒ(«ÊD*Ôë4QIšc‘)á *gïXcbŽ˜º �_“a‰QÐÓŠ”Š?�¯]¹fÓ“Ó¶ÊàÝÉ}£6Áο[ì2»Êfn’€þ–çmòÞ=v j·a ée}@_ùõ²ÝW·O“¥uÓXÌ ØýÛ·9Qè]ÿÒ0ÚþŒ÷ªA>Ò•!Øâ¸ê‰û=‚vëµg_äd¢çìÂÌ”Í\ç«Ký(« ŒÁ"½ŸPä´Jñ\?ÜÃËII_ïùÑàj�92Á ²—ß•çì*Ž 9Í�¿âå$Aœc+÷pi¦WKá”MSÑJ—ò ZÅà Š¼ÖQ!Q˧¿(xÏ…s¨Ù´HÑ»LÉSÆÚ_Í0ôþ0óØÄŽ{•Dí�6–k’zê­M·Ênê¸"kaöx�Ç6™|4ê6–änR;´f7 ä$³ÝÚ �â‚$²,*ý«ê_Îa%Pƒ@Òµ¸@ÖÕ}ŠÈŸ0HLïÅwx¢Ïßy`ó�L ñù£'íÆ½;ÄS¼—ׂ~zdÏÏmÛS£'XÔÆòáMVnú+ÃÜÚ¢Ýâua�Ù\ËüVèlÐ#XâP‘Õ¹yFügmü@‡­­žõ× º@E0Ú+5¬Û–g»ìê†]ëY±�Þ}lR:jçžyÁž¡×±tÿ®MbîÞ¸n÷1Bff˜ŸÀɶzAï+óø² §~ö\™Ê§;ðâ¿”2p —U Ä "ïÎÆ˜\Ó91ÔÑ$ @È4½y¯,x¡mÐyÚe8Y$å÷"W“•ûÉ/r�„Ò›Ž `CæŒs0�7ÍÔó†äÑŸj2Âß F¢ôЈB# ÞJÞöF²I¯b-UùÝSzÑ|V÷Ø@Yl±ZEº"¨Q#2ˆÞ€•å€Ì9­‡åH8xDÁ“y�ŠxWA°rzg tW‰S"KàF(‘Ci‚)…H<ý£Ã9ú>xû{éìWí�{¼;göõZsv8Ê&8Çïê­[¶ÈfŸË|Ò[U§á©gÀø=*�ȯôlã:ÀÔ>D _ì¸foÏ޶熿À‘àÜMSƒ‹$òÊ"eß ÉL; µ/ƒ?`#ÇŸ²}§Ÿ¶£lU¶9;mm ÓÆØnìÁÔ¤ÍÍ/ðºÀ$_.Zr(=#NÉwx*��êØ®¶ ½ÓȪR°rQ> :¡ópÃ]ðÑ‹>PĽæ/ú…æ »Àm”eÍBx…"*GÍ·ÔŸúé_S‰o#ä4‘b\#Nœá�Ðjøêî—ŠØ0AurÁ1dI¨B;ÓɸGº{ÞŠN GµÍ[ˆ{jᑸîB~l  {ÇãúòÂ! ÚEˆ‰JV%çÏJöP³‚‚ã±*Hþ�ÚïE¥À¤hx7®É6ë Vƒ hдtS©ho¿ù޽ô5Ž‚:rÒ.¯ÎúŽÀîa–íöÍÛ¬ÃF^üÔЕ‡Núïnd4 x*0ñÞ¯]eúöí³s=öƒË·mz}Ù^gƒ�³ƒŸ³Ã§¼'ჇEö"°wíÅ¿«mœ κ݄öƶ#™í:h_õeë˜ß´Ë‹¶=?k+W5ÏîCnßâèª ›~ðÀØÓ~EF�ÑéMNÃùçNÂEÍá+ºN´ŒÛUÕ*V!¸‚N–CÁÉ6Z‘TåShO‰:¨0ð@–¯"1c«¯Bª\“ÒŸPULñPNñ—aÊÌŸôÑÍþª£µ£8q�UOåZ�šÁFD’*m{a#(s�¦•NåÄ,ð3yÛxv+!•áR¼ã÷Œ+3Ê”þ¥ý{Dè ˆçÝ3ÓÒ#DJqÄÄt–Šðÿ€r­£#=ç–—R¨Â‘¸4_m×uƒ§éµ·/Ú7_ü¶ýéìe;9¸ÏNö ÛŸð!£úFƒ×>�ÂÖ3Ÿ‚ª JŠWïâL¹WžÕøivvh�§÷áÃöàÚ}ßRlmsÉÞ™}�™wHãY[Úd¿ð[^ $NE›ˆêȪn[Õ6ÌÆ¤ë¶Dïá÷Öì'÷±{qßh¿õï?ný^¶Q}µ`¤³xÿ¾Ýºq˦&0 “6;ý€eʳÌ\äÕdu-f§!¿kDÙQ9 ‹»â)¥Y€Ü\Õ�$õÉ—$‰$ÕšåáŒ�89ž0ñT ;eI§ Ò*Up[c„�xú7$*^ݲÎÉŽœcóý^°Â¥ÄW€Ýé%‹‚éAˆwËB·á­ÓHŸGF…—ÊÓ]Ìý—ž$üì÷'`$jiT•p‚HÝÂxe®²VÀ™Éj�›0e)óžI¼ÄWl#nNTFx„„S\ÄçÍÁîõŽË*çþýø‡¯ÙK_ÿŠ íë³7î^³ ]£vbxŸ]}0É»{LÕãYOwI"ù×¾Þ5Ó¤ñ¾…°�ß?bLÏYçè˜m³¨h�w÷v*Ý{Ó—9]hÉ&gú¬oàœ cpøš,®µÈEl1T–$k�Ú}h’ñˆnÞ÷5Ëp…½§Úhø¼jhÎBûLö ÛWÏ�µÍgè°uTÇ]½…uz Ëô–d\àÕa~zÊæL3^Á|N»Õ¸‚JñYŠŒsT%îN¯;’±QVnì�JHòï˜Ys ‹ØÜà]_•ßš0SvdÒÍzQ1)žHÙk]@ Lžy÷X«ÑûÎ:™AG¬ ©¡JÁ=M4|z!.yÍÐ^÷à×ä–ÜwâGÜ }Ôðc=Sà–b£”rsI�Wã øT"×/™pXpHCÐ|(CUÅ*ô‘ÉRЮ')Ç¥pr”TaU’�¯,6•U3ù>üð¢½þW?²S¿þн~ïŽýÀîÛ7N?g3ÌõŸ£aÄû´ÒRCWzÑPšÓT!ŒpÕÿëó .^×Ó)†‡¬½#À“x��…~tï�}q¬ÏþúÃ÷lüàóvüÐSÖß;è¯2 î‚yø¹z$¯ @ÏÄbèVq¢Z¡Rß\Zµ¿¹Ï+[“_™×�¦�Ö=0fÝCû­ûøy…ï=ýÙ·ðhצÝ{0k| Ù˜ãkÈÜŒ­Ló rnÖ–ÔcàëÇÊâ’­,¯Ú*ej+u}úô=�¨.ŸÒø‹lQÆ•èx¢tTÊ®B?�tˆS$™îuTE! §¬ÊD|ø3:ù£#â4k36Ù(úZK"A·gR:nàDºÅ¯ÊÝ—¸uú޹'Yâ–è*¯ ¨¼üt«¢+�îylb4E‘(N—Å&èW·ª¬¡/("�Â3¥láJð)½ ;X£Ä ¤V¹’†ó°(Ý­KâÕ´N–A5 çÕÎSoÍþó_ü•ýÃóÇí(Oþ˳w17ì 'ÎÛ__|Ç嬺ò€œþ�9 §Nã“!‘Ìävfß~»Éã2«¿Ô5g �}»¶¶ù9›š�·kË=öÅ“ûì?}øÛ�ß±#Çìоcl"2æëôj }¹$sÊ­L”pªEÙÕD%Ÿ‹@o`ŠÞÁ܃†½m¶"Yéa´kO7;a©�>öC8>6dW{lkàr¶ûIGý䥃YŽmk ƒ®ð9”ÞCÇú¼­rr’ŒÂÒ4½z3ËüÉÇ"ù\_ÕxƒzZí&!¥ßÖ»ç!pDéºÃ5@AWâ�‡Jv·S= ÞÁ·ÖQ`# _“väÙÁ£ÈÖäêõA—4+E—pÜJsÂ’ŸdRÑ é>Æe&›É�î’{\ƒÃ*P’| ×OõøÀ%E`*©,wXooÒ.„?Õ:ÕåªR�uX õ‚QEǥʂÄt%^Ác î 4qpÎE¶ OÞ«P(S•GOú%¼g_»vÍ^ÿË¿·—çk6Ý;o7gïó9pÈ>ì´ýäÆe YOùBßÎH§¾Ú?Ð9Ñ褶?¹rÇŸþzÒÉHPÙ:ŒEF#£ÖÑ7`1(xp_¿½pxÌÞ½Ç7}œÄð ö Ù�±q=hýƒþy/¸GZ!üÒ¹@Š””Œ�Ë£Šƒ<Þñ¯} 9OJôòzcyÅÚ´,ÚŒ¯™*,wêe´qNB½”‘ÓãÖÅɸCÄŒÐÃhS×™ÞÃ=£“[kvƒ5 SS¶ÂëÄ&ƒ�ðÏñª±¨„^-sØôµïªÒy$å&aÂyÍ!XC€;é¹W8YW*ŠB¨öë³ôdˆ$o! \ x£^8°Â_›øžna(F�^­ˆ-¡–@ͤ‘|á‘ò6ð*¯$*o ñ™ï�oTk4Ü/—ÒI!Å‚za»‚¸ ´¼>×Ïa„�¦d¸<ʪJ otrŽÞ*�¦Öˆ¯ BQR3¾�JÀ’¬‹4!´¬þ¦Î„£Öÿï¾oÇNŸ° ¯ž´Ÿ¬_²ŸÝ»Ê«À vz߯¦0ìëïœ4Ú¯›èÀËÄ» û§¼©eVb4d½1"‹zrmLêÝÀ^§Ký+Ï>eSKoÛÄ⤠Œ3ÝxÎæ¦¬ã&“Žè�Œí·CÇ­³—}iÌZi¸«g�ú×=žRëÅѸè©ÉЇÍc¸ö ±ó�νÓ×I‰‡…Т|\�÷ [Z# ­dÉ(švJÝæ¨óû½]öÂñö³Û“¶�©ÔŸ;vÄ>˜[µÍ¹[à h0rŽ]’æØ,e†9 sèp‘КÏc€§AéÏï)®ˆ WP¨çÆ&â+ÿôy{ýþ%ûáÍ�ì—O>ËÒà›çi¦ò“T2Qê¨ë¯‡¢¿ðÔ9Ë翟N<ð§°7xÇ[8\¼áøm$Ûa?Ûì¶ï~ýçí_üõk|ÏŸ¶¾ž}¤ÑÉSsÍLÓhfîÛ™þyz ýìc8`ƒýƒÖËø‚Öñëë¤÷À”é"ÊiúuOW`²Ý’ßÏ`TëqrÎðë×}ðÔ¯}�ßJàe⋽´-NTšëܰɑ.;ÚÝg�k6ƒaX¦«ÐÉ^ˆ]G1Öð¬C9½¼t²´zsfÚ–9…éþõ›võòU¦Vßv£°Ìk„6Ëð¯)e�£j'E¶fÒO”?åe°ÔøÝ  `f=ðT7ñ‘ÝB1îÙ °±·Õ‘R[75žÂ;\•©dš¨ ¿5ê¿Ã½ÔÀq“WQ}Ï“1Í”¥ —_ Á];\JFÕvmÃD†£�„^úÒ9xÁÇël¤^”Z'ã„W®£DI>7ΕJN‹Ð °Úï&ßÓÿä_ý±ýö}ϾðôsöîÄu{wyʾxêiûë�Þò§c›?.i"ꈬõE`´·×wÖ¹Á`š¾çû+ y×€àÈtÄ»¦Fî·ÙqxÁ>dzñ·¿ü’ýû×ßç"£üÆf¢N¸EÃ9¾ÀVèyLòäì`$¾:j¼Ÿ%Ë}¼"ôõ÷Y7{v°¡M}ÿÒR«^‚t ´Ë/nQ>�Zû…ê:Rž<Ñ(ŸÔ»z yWÏaí>_Úö1¦ÀD©©6vRêbƒ�Æ^w´Y²×´.Ûë·õÃlýÜSvø‹›öÔâŠ-2ž0˲êûW1×®ØÄ­›6ËŠeEi…�—9å›íFáxÕ„/BùöZåý>%•ä‰ï02R‡•“tÎ=0Tމo¢”ØTû½f�üšš –ŽS„¨8ì@«ùMâ¡:-¨Ÿ5 cÿXîÀþ¿G–ŸS�:pØ–1_d�¼ŽÀJ%J%ž‘êÒPR#CÍpæé;M”*�L(ò^x4Xe ÷€¯|*ð\V�ÂuÒˆîO0¹æÎ´½xöY<±ÏnlÎÙèЈ�Ýo÷Væü�Ù–Dàd<Í©ˆä»É·xÖJc­ðÍ�OxsjÏ=÷´½¿Öc=½‘gàÞÈI=t­�Í6m•I>‹�ùé›0C£ãû>†EïÛZùè¯+?î ¹uÏFßÁ8Fe”+7 µ�PO!q�|Tøn$ M‘ÉKœÛ¾ŽžÛ¬w¦Ãú':mà^§õOuZïR‡uc44¦°MÏA½•6 Bïà°í?|ÒÎ^xÞ~á+¯Úè‘lÿÑÖ;€1`¢Óy\çsdt÷Q^£MK• ¶:Aó1­¡‚M­A\7꨿I—w¡Ê/½è®Y«€¸5ŠØ&�*_†Eí½ÐUž�, âlÿ«5T¢çd�g}=€Qß´v.¹2�9ÅÙÉ|).Õ'�T±N¡rmD— J]•ñ{ $ªî^Y*\1jžÆnÝbzí� »pôŒ�=h—'˜ÓØf´j�üÝÌöë¢rïã'‡Ç8R¼ÍÞŸ˜àI wç�ré}LÂ@IDAT”¼“Gý)µH: ¬ñ�zŠ~ß8}Ø>¸Ëd�¥yû…s‡í~ט=Xߦ;Ýo�ƒ#Öů£ÀÚØÄSº–1ðéÈ0�\pÇšmëÉÉ(ÿ6=ƒ&uóç³ÞÙ­Uëd?Äö¥Û\eè\=Õ5¼ÙÁ ‚R8 �¦>«ÁG� Ü , úTºÊ0HǦ¢õ8†[º–Û­wºÃ1ƒw»làA‡õ¬’–^_ºÔ3ضƒ¤¾ÖËëÃ~;~ò;óôKvê©lß±ãè¡›/&>=êŸ'¨¿4?ªJ'è^1Ý%eÖÊ,¥Š¦ 8>~7ÀITÝ¥((²ñ˸Uqxä—sX ˯*ãˆë‰š`¹ô(ôwï>fà±Çh÷^XWŠöʧÊÔ¨ÞŠñ—5Ï,•Ò‘©ôòxîóÈ€†4Q|›`Ea9'q 6º&¨ðm ;Ðñó">ùÁ ·ón¿¹Å2`æÿwP;»ºì�·Þ¶ùÿmÁþ›ßÿM;ýs§íúʼ=7vÔ~Þý†XžlÖ‹ ¼][ßæªuo¬Zƒ‡ôÊØ™PuÊÕ@vX©¸e]LBša”þ£;3ð$Ü�tȯ3:XùØÑIO£‹ÅP� âñ°«½› Gì 7™7 „XþÄ5L™Œ‚ÊSö{å/å\àD^Ç%ªèd�±g¹Ó†GPƒÙìcUå~Nk>Ùf7Vذ•õQtÈø2`ÇP<öŒ½üÒר‚ý¢]¼ø¶]þà-Æ ®ÙFÎù‹¹ ’eK¢Å Üê$MÔÉfœûë $âQ2%…¥¨«€àî2=âœG©¿ ±ô•XÁ7B?WPEñ*¿È¢øxî± €„÷n³W2Á¿d̳Xe$â<Ö3‘�QIXyDT–à&¨ó÷Âç05dç¡~ÊïŽP $ qÏ üÈ+CÐÎ|{Ý5²ßÍ'»ËW®Ø¿þ?þ¹}óÖ·ìô¯½b]§ûìÂØa{ëÁ—qw¿¯|@#ìf?@ÎÜà;ÛÚ2†€™y«Ì ã Ï©˜6ìßãyz+ßz‚ççÄÞœ´oŸ=bß{õy» RÏÖ§Ø ~�1HƒÕ‰EÝ’É¥ïuFÁWiåzÇ^ÄðÌ1sO+×´ h�'=½m]õâX»]z°ak¼Oõ­¹²ôÕ+ÄS†7ÚæC?0–áÒk‚oÎ<‰®Žn BkzI›{[¯õðë3H•qІ¨N¥^€*ºØc(tW‘–U¬Wœ 8ê²ÀXìœk³¾YW69�•¼ŒnÛS×0•wòE¢£cÌΟxÑÎ9oS/ý¢]¾þ¾½ÿîOÙ?á[dF€úOä5 �Íž²Ž€çöƒ�˾8FWlÓKЧGÿÑ+�aðG¹‡jãñ£ëû¥\œbŠ0¸ó›3ðј‚PÛíÌȈ�?©Ê|\ï³Á5Œ¿~ü}]LI.F�º¬â‹òU‰+0ß@Æ`Ëç6mX‡®2�y]>é³ÅL[;·2÷z¤‹›§_¶§Ž]°+Ÿc×Û?´Ëï¾n‹2ú*‚!�ü~)u%2°ÐY‰×-]‘�‡Ü%o�\ûšèäLY“a7ÎnHâúÝ)„£_”AÀ?Ûõ± €l•FF”»Ò˜[õQé: ·d´*ˆaqiZÚ�ºSv[�� rÁ=üy-Æ'ƒº75áЗ¤hX|$á)©wüÍ *j§*Q,VeºÉ‚ýÏÿ•½ýÓ7íßù¦ ~é‚}åÀ —  Ù{¡×[ó6�]]5p"²DO`–nººê+ ì­ðN¾Â¾k�c#U½ P’¿B{4¥¿7F‹�xl ,9UZÿUÉ'¼ÝÈŸð¼™znJ–Ò(“"u°Š»Ä;Ma^�"�¬ýÁ¢Àœ.üz:ÊeLá²Ç ¼’¸(üSﴚɧîú†*'ŸÐ:ü!¨tEõ)ê�7ˆºrÅ^|ñsöµoþ¢zú¸Mw¯±MØ,û ÒågÔ{‹­F­7m,»I{ô.˜JÛÇä¡ð6Yº»¶¸lƒÈ¼‰±¹Ç¨ý Vé�Ø?jϱ·ïÏðÚ@Oañ® AFÉ6¾ËMF•eo.4&õ˜ûyï㩹 -Ëxõ Ò‡ …dÚä=¾ckÉi!>Þ ù¬©GåUa‡'þZø ëÞ`¿Âá.¾Hh7"ŒÂ:Ÿ‚·øLçFãðîÝö ¯6Ë|â[%=½Ç¯v¬ÛjûºÍô°Þb�ÃT7Õ+ê²aŒÂÉõkŸî±±u^‰ô †4zmˆÚàRûz†vzYûÙÖ}?K£gùbp÷@¿-ðy53ÊÁ.‚—Ž~Î.œ|ÊÞyå-ûË?ÿS›ºú¡mòUÄçC”|ºÎÈÓ.ª€]¡»P*€˜|¬ I/å¶¢+Ô IVm�“XþS¡?¦{üyšÔ¦‰@ú È<€ÆgÀZ62@�ñlTy©<^‡àO` pð @uUM¬p¤^ªX'©¢ƒÁC®M¬FÍ€—’PõS3ÓõLÚéöè“UÝs…5*þõë×íÍ×ß´;ìþÓGe>8²ÏèÂ2AýHÑU�WŒ¤b¯xÚvOŸ½pê˜}Ägº» äµS™/óIðΡ‹Í„z 2J›tÛ;;ûi”QŒ!gr ‘{zÛmP³ñºéQôõ؇lBÅQš’GÆCt±Û�~›q.SÁI¿sv+�.¸0åw°·ÓÞ�]ô *�±nòë¿A¦*3°—5m¬_`ò´={h¿Í»ñ9¦�Gv›æ(5þ7píêgoÅÎ%{o{ÆnöÍØm$g¶YW@~»HV³.´K¦4¾¦èÁ뽨ƒ3‹Ö�¾Vz:mÙ¼‘Ðû:~„×¥ÎQ:xÖ:œ�_š¶õ……�Á3—9Ì»gܳ—ЇjÀž®�éæÞ›€ ãêèäý��¼T¥Ï€�-�¶ù xù¿ðD †8(P&éIáNyK¿«§T®J u6å T|òDT<”«@°õ«ÇR\=±ˆ*´ ìâ•ÒwFî7Ó.²«á–Zéè³OG}!ð8ùy×׆·nÞ²ßyß&.Ýd²Ë¶�÷�Ø>Vÿi×&_ÇŒWR8Sx—tÔ¾z0(§Y¢û·÷؈„oý�|û_ãéyŸŠ¿~ö˜]›ã «±ŒÊÖ&Û„ééKúîJVtÓS`8è@w‡ ñUãÒ4Ÿ›ù#Wµ,zaaܾ¥ Jž3ïGÊÇñá^f<.Ù’µæyN‹¾¼sk­BWO�­a(G‡ìÙ3§l•‰>Œ ô0˯“J­¯ Ñ[Ù²ƒÌ\œš%_bÁ{ý†uŠ…70 ×;0ˆ«ÆP(F€µÞMZü|÷AvN>43k]¼®,2pÚ>À—‹¡mÎ[X°!Œå‘Ãglèð1[ÚZaYóó$4V£<ÅI‰î•VÂë¹� Ãê‹ÊMBe„ð‹?Å}Ú¿š«|!‚4DËyõL@:W—þ+2ûe}ï|Wª¿l¡€†n#›u®Üçñ5’TJ(0ÝòGAd% $¿ù“:à…CüºREfT¹7ƒò+]ÿ¦�ùHg‹¥†"^ Q?�:|—•oßûЮ¾ó‘­²ëð0g†m„©¯<éy˜cÔ�U»‚§ÖéÑa{@ú£éYk4áÏзíæþâÉcv•5þÏ7ÿÍ Œ‡ª2ŠÃ68Ì{6ß÷лñ³C=vsŠFA£ÊòÈJ–ùô ulkM0Ž�ó{`‰¿ð4ãñ0qoL0è Åoò ¯ ^d™ q¥Ç0HÏ`…¯½€>ü2#c,‹±17'—¡D„-V Òåò€ o`¾lù.¯WYtt«cÃæy7Ð{?x2Õ€á(›¤îc¯‚žÑn»J/cf�S›áÑÅ+ݾ<~ÖÖ{ù¢03É+Á2t0W#›x2¨\DDøÊü¨‡Ùø�¤AßÊ(u^°·ÄK¾ùšÕjöŒX/ùkGïÊ‹ó?kvÂîó]ñ*_n‚¢põp€ŸÏÝ` r„} :§lŠ×“•Ÿèù w ØáÃg­}tÔ¦ç&}«4ÈY OZPÝ,•­ˆ‚:Rí­|Å#bçÐ iááH­…,bšñ�›÷øTì3±ò<‚Þ½sï¿°Ø¿ï¸/Ò`ØÁýãa0QàµðM¥DEkBJî]áõj'†ëµÒMñ”Ê«8ç+E˯—Û�®Užc�"Õˆ}É­žìzJ!²¢ÈÈil@ ‰\-�<µ!��OlSSSvõÒe»ôÆà½�låú=ë£ =Æ$›Q*û‰}c¬³ï²·¦ˆ�7¶ÜØBi‹ÿU*ôWÙ@dž×�%žØ�Ú0DkìëéG^åDì…?ýÏ vc„ØÞ|™…D6\†TÝ]u40)xãâÓÄ ?�•Ïžo±�Ø* ]2%VâêØ,wI_pÖèŽ,0÷ì�›æÉœ®¡�îõ{˜AvCWýé൧‡3û˜ö<84jýýÃ<{ý•!ç-¨A w‰|݆ÇeæÜ×@-¹â×…û˜ú|j��I˜<5­ýTNÐqv“;f½Úô2ç,ð•@¯?uÝE>”ÒÚvk™Cc™îUǧâ4€Y;Å' ·ªÑ+Ÿ&£1ñŠŸÎ¥ÌÅ@ÿu€Ò8¨W”­×€Z‰UŠ'²©«ûª\WžŒi�W-k8…²Ò ±éw´@ˆDÒ¯ç%«¨ËS;¡¨»¯_ð@¥‘ yˆ¢7xÅéµ@ƒ„2ŠÆ=FÓã.ƒ"š5¶ÚzÀŽ97Ø�è2Æàú[ïØÌ‡—mëî„-LLÛƒeûØñw� ÛÉ{´œÚ‹RYfÿþü¢ýÒ‰v]Ë…•Œº„T|í¸BÏA{wh[2mú,ˌ߻¯\¿ÀÊ]Þ%gS‡:­h«q•Ö(_-:xê¾Ë¡ªiPœùRžù4ŒT¤éb–IPÝÄŸ±È*7ÎÀÝ6ošƒù¥Áy©�ÃU:ëàà–>zMýzÝ=¥uZ’z¾Kxsdú&ƒ€‹‡»mŽ÷†A„¥‡tfá�uÓ+¸ËO›2èðî.¯}‡Æmz•½Ù6øD?Ãep ¹(ÅÕ>W§Ôç2úÝý.‰SÕ¤À÷«è">y?ìÞ#@oQ'T…Ø~ìÀc¬„%ùÐõwZiNÚØåT áÜ'k¬`=*ÔñŠS¸¦r3¤Z�çlæl•ˆ§üåÏ”">®:VK _.øáà§”•¶Ct¡±k±‹ïÝçO^ oðY‹êŸèަ1ˆ=Ô3Ыƒp˜ÍǤ›{LV¹ËÎ9o¿ý¶õó”á½xôÀ9ÂN@l+~˜ F69:lƒ°À{ô¾-^¼;i_>rÄþnRÃbRS4ùÕ#Ó+ôAÍÜšå\zƒ<»yRvñS/ÁÅWN*öò+ªQ­ÜlÃølÇh¹�ÕTU¶ã|{Ÿ­¾¤‰,Åù“NLq®#pƒNÝvõfd˜ÊKoèÝÉÛÏ$žƒ ŽN27Œ¾>`z²:Y“+ÍÂÐ:ùe�ä#ËÖÃÀ*_:ö“}~dïE>»®0ÏB½ƒNŒÀßUÿüþŠ½Æš‰—ùñç>¾u‘ΠòfeÀ‹f5¿( Â¦Ð4CÑx#ÂTÞôèý^Ÿô¢«/Zqׯæã¾LTÆ«øõ$Ò{¼ �7DMg¥ŽøDñ: î¥~Á[ãa Ö°Ø"_–ïØ­;w¬ã�·™õÇ B̆y_Ú¿ßk‘q˜½;fϼ°l¯ °;[�¶Áá:X�f�'«>=žæÓßϘø³ßYš¾ € Aþ´³°Òö!Dù¡`S­‘-Æ;5?@²AÛG7ZËwo±lY}#�ä7 ‰^e<ÅL´‚,óÿÚÍ{öõ~5â~vbÎ?ë&z�K½ÉÖ‹°t øqÇßÅ�âq�‹·Ú¨lÑLÍ­�a–J³ërºã+@ŸïÍ.1êßk×.?°¿è´÷�²ç™öü›»üæõ7ì/Ž^°»}£l¼²ÅLÂ6;3tÌÚ^ý¶ýˆù“ï½CO@e¥%ºŒØ^ŽH�×W‚Èk‰Ë ßUwB'Áÿ^hèU¸N�¿V�x2 à•d‡0MC��%P2·RBíÔ äüš(utñ©’QÅ £àÕí!4b’•r#Ⱥ멯§²œËÜ<äÀÆ%ÅR~”çúé@:j@½Dc÷�B1Ê×féÄ`aƒˆ{×üÂèU¡Ìdâ#Ú“ìœÓvE“Æn@½ô.3Š>Jï wL†á�õaºö´ö1æ pÐiÿ£ú|ø?@×1æ4ê ËDrÉÛOW¾¯“�n*ºVj5"Ce¥4Iˆ¯m¬Üfý�æñá»Áü Pê\Ø„¾”oבÊ"4äù+Ç!¿ž›Ò²04ò'ïØwŸ9Ç»y‡=\ïýaT%£^aÔÀ•Ö>vø6+F0‹¥ÊJZðÛX¹¸Ÿ½õ:zó=Þ):gìĉm»zeÚn1­z†Mk.žý¼}#ð­[oÙØŠýòÐaŒeEZ§�Ûæ—~ÍþžeÆÓ—>ò‹,N扔qÊiäÑï ¯G—‹dfí2y Mdl2ÉpÜ}ÂRrJù¥·ûÑCOÆxMUæ2ƒ{ ¢F!ù]-ç¡.x¨!¹s|.ÀšƒðSÑø�\±a]þš@è•ScSãW#®åOgVáVžXùqƒQˆŠI‰êëˆ,½îñ´�^�^Dçó4³œøE*G�óF$¼òº âƱÂÚ�å•Y?$ô&�ônçµ¥›‘în>i›°!º×ﲃQ7’ú0=#œ 0ºÏÚTkce!ÛípX Ï?h6ix-ÂO� C¿NÒ‰/ž}ä’§$&d˜†ú㛋žždS¶]’K2¸Ð\0(ú:!éÛµ[F~Y¼€šçý}£»Í.ñª¢ÏM vÈhzg,’ÉpRšn´•˜˜ÑÐÔëÚ†Núæh…ÉÞï4ÜÚ¶ÃGÇ1š—ìòeŸvÓ¶ÐÁ:|Þ. ´WØï±‹òþÐQR‹•Î �¶ÕW~Å^c0{áÖm7JÊV8e(]ÉX¹ Š·¸ðÕá°r‘ˆ¡¿*”žÈg„WuM~~RÂpOÄH%^¨žU¢íÓÕçÈÍ Vèáq¢ZÑžéT”G·0®qƒA„[  $ ~¯@tg«îkd )˜}Ì5Sȼ.¼•–¼÷à½Í`Sô âɯä д˜ ÂÚ„?`%yú�i@ z¥/Þ àL`œa»ñÛìkˆô(ôde5?Ÿ5ˆÔMÏ¡Ы½‡ùÔ¦�¢‡ÍLºðwb4ÚØtt›wçmpÛøô´M7ýðÀ–M3Áf�'·ïuHÂj”R+Yuç¢x=�d´c.aʤs—V9e="¶;wbØÞcÿ�fb„&YÑ)c(™ÅQLÊÏó CåI «Á{ÚE] åµ�õ Þ¦{CXîÖB¯½ðò ð¼fwØ«aiæS®Wí:‚&O½l/Lݰ3‹÷íR÷ˆÓhÇSŸ±…—ÉÞ\ø�¶Ž.Û|0ØÙq)™U°x�FÒÂ(H!ñ.ìD*wGt¿Ø$vÍRýR³Žú™.OÄdÊUuIKAe¤ß3+ dÅ-Jɨ¼Wt ¿pðŒ¬èÒSñzR꩟Ü3”Ú`\G<Ü×àë9QÁ%a¬‘š )EÞå¯J ô§ÁÁ”Y= 8«Qp×[J4øÀW%ŸH3è<¨–éšÑ]OU~¬:\b|�Ý@”œË(-ˆg=!}mèäd_´óP/Óyûxì¥ÑÏëEÛ±q›#¾›øâÚýÓ#ë!`àmåǹ’fd:Cž˜r.‘ØŒˆO¼vPûƆímzlüñêþ&*±F€®¸÷�à!Ï�C[TTG;Ø‚è}(É¡>¾0–°°*#Qt|Ú¥Év{ú¹£è�5 Ì^œŸ™°™›×¬ #ðúÁÓvhqÖ†˜U9Ïú=g{ÙÅô¹S/Ù,{=\zíïp�AQâúW¼ „¤ò'}è_˜­Ø-hpÄ ÜÄNú]ì+ìG÷‚‘>á*Mœ,gñײd¤cÔÀª!’¯"òX/œ‚Wסšpo_ÅE2<¦{B ‘¼©‡RöJ+i3¶!yäÕÑ+hÒíIÑ –7Ó#ù¥l¹`¬«žú2î zRpçµ!ÔΨ*œé ð0nä£ÁJ•%‚“Ûlhâ@8> ‚TູWñîWã�¡üäO<¼jU†¡ä^i*”iT†S¾1–ßf¹3o>Žàƒ’à䀲x\¼¿eŸ;1ÊVê³nŸXGF±ˆKs)ø¼PÒ‰ Í޳•Á¯Øñ§l×^ÿ �¢$ rF¹A O…é$nñ‡¾%µ Udí—üª@ÅSÝT8ÊÊ—dÓ kC·“ÀN=¶{l ‘Ú:ÿ)QÞ[勌Ì+æÎL{T¬Ôܸ¶Ee =Ö4™¢‘4ß ©wc)¢0MÂêþx”ªcíͯbžÂ&UƉ’\T IWïòºL‘ËŒQ>Tù£A˯”ï@¸;" C „å�´¦TÅþڱȟr-=9¿ °EO�§ª\Åð « žO<Ùg Ä"' Oݺaío1ÉêÚƒâæÉ—`/MAʧÙ�Iq1RÊ“Æôš#e«ž®c.=h·³çGíý·§|U¥^qz™a¨ý7˜T¤0ÊÇð0Ÿ?™Ñ=ßoÏ}ñ—lâÆ[æ T5>ñsç™Ö¥Õyl ¸%P�%9p!7£“·GD´0½n(N4S…ÅnM÷QC�mªÉ€ŒAÔŽ¢œ*W®°#¦ä=ó©ñj_M“>¯d ¸Ò„•Àã ú7}Õˆ†kå×j }¼·*˜¦¤ ’Rˆ•|U”Òû˜4 _½Ÿ»S#®h¡ôxòXXD}Ž8XpT-s Pmg†¯“ŒSœ>3ÌxÀ¬ëןøôu Ã.ôØßâèk€‘ƒÓ§_´‘ñ2½¥%$ ÂÉZ©õRǤ–[äÅ3Ñ' "wÓä-€ÂñÓõñÜ0™mAž¬®�J¾Ä)€ ^”æ•QäàÑ ¤‡æ±ÆQ%k>õ³Ò £¨:¸Ô$åºg„ZDf„ð6{í mÂ6*S0 ŽEH�¶ `•äÔ#O\%V%p' @Â¥ í’KK�^ÊNœÅÛ¨—�k{,‰Ä˜Þ…E¥"¾JÃcýB”¬E®VU‰OäÐwAOg_%f90T¿[?û‰o2r줼ð‚ݽð¢u}þ‚³ÛKZZìT.‰žðžX{ú܇Ùèô�‰Uê@äAJÉÁA 篒^44ðS›öÜÑA;<¾Ê²m–S—.½«�ND«*‡ö Ûõ)rO††û÷Ûù _°›.íØ¤×€Ðuˆ¤+¬ýÒÕÃ\K�Ü…Ú °x† ÝG {üûc€02[DTñúO�¯r± fé4zȈޫLÕ‚G`WXÝÇúÓ^`äµ®:0ó¸dô'Ü¡‘¥5µˆô±”Ÿ„邸(ÅW¸íEçP¯ÊÝ1/¹dŒj•ÜJ¼Z O}éÕûÀðˆæ˜ZH|e±Yõ´¦~Ž¡»Òð€àp¡®Iyr»'ÇÔ½ázšÉGr?Ÿ %bJ9—™é¸Ä®Ë÷Þ{›y jïŸ9o_üêWlä©ÏÙБã>ÿßB0É"f¼`‰îç,=}úóž(ðº× |¥©š@ÿú}”ãœÈ¼´¨±àíßxì{°%Ù:¯2š—À‰‘Ì(|Î9j·/òE@ï¡ÔÈXaë B0“ÓVå(X*³_ŒQNYÈ•×ÿ?Üc€¡\ÊVI=¤Ì(#•.§8›f(é’¿*R­‘³ùÔOܼ×X‚´†çï ²†÷ÈöÂ,yÎ(»±vCvUèU]Ÿ’¢âS;Wžx4�è�oo¹ªXz–+� ’Ï©ÊÅ@iå*J%’ã ) ~5&ýš52=m Qõé:Kݽª@æ†DòȨgB„î_–8 ôî[¯óŠpÜŽ}þ vîÕ¯Ú‘³Os *{’²Ï—@€}tÿ¯Ìñ SlÄS¯( ð½@ÀâëIy• ­5^.s\Ù™sŒ¼Ãî@ ‹¾ƒé�Ž ÛÝ9“a›•�ú·ãçžµ»W/ƒ+L½IÆS¹¦?�”A ¸húᤠ˜ õ ÀøK~�ÀE«%ñÐE¿:S vH}q¼«öÕ Ãô¯Ê„ú5ª•#�t’.1#ÜJœ�½·–Ô)|µKÅÛ€¸¸­µ†J5nM€Z¦Jè@èü¢µpöJkå�—†¨'q]ŠÖ˯¢Ä\ݨÑÞˆ•}ý‚»Ò•Ù §t£Ò—X$üñø�x!Å $…<Ú‚o|ŒiÐðU‰¹ñ %Ÿ› '¹ø2³qæò%›½~Õ®þý÷íØK¯Ø3_ýe;þÔ>ûõø"!m‰x�Ozµñ§¾ ­ç‰œŠw$áwç L¯Ó<ù‡˜Ð”ãú‚°Ÿ±‡MV .3¡H ¤�%Å2�œ–tüÔ3L¯þk?sQ=NéÑçB{`+¥½ùrv›ÎCõ…( _yù‰W–G“öQý�m\±˳„–À� :ª ¨@[•Òd8ޏã¢÷/ŸÐã•D‘ BVSÖ¾,>>¸ƒlG°Ð6eMP`îS§ʧç—Å­�¿5rR{Օκ¢Dõ´­u⥹‡044ï–­6§2I*[ø2¾ÂqÚÂÆË!M‹xÉ_8É�×M‰žöˆI�e·JOOe"±~žº¢ö2ŽiÔ‹Œ|tïÿ±[oþÔNåí¹_úU{åÙ³v‡Æ¯ýXNà©•ƒ^r“°,ÖÔzP�dr<`œñ€7Ölü([²-�p>˜}œêˆó1¶}c~Û¡ˆ¯z ‘{n™×–.šõ i‡«J¢¦jàJ_µ ¿×஢:ò3ùÛ(U)Ü ·Ö|SÉžT@Ç�œC[¢’&c#Òßõeê[pCAÖ¤ ê��LP±;]2šä¹k7ǤۉÙƒRc‰C†Üð6B b°U�“¤Äx#óî~4|Ñ: —xî%·„ÂCùŽïV¸5>BJ¯<áð:.ª×].ÚSV`5Þò¤%Nåêl ¶§ä…-C²‚�!Ð+C‡Ÿn¤n‚­Ìó¼zŠàƒ'~”» ÜÒ­öÞø·vçÝ·lë·Çzžy…[‰�$¹›“„RV1PO@ K=²o }ÈxÀóÇG9ui�ÃWý¿¯we<~Úƒ ‡ËÐÀ!*=e7/^T.ùß]‰(®èF U‚dœîJ \å«<‚§n ’Cj¿�C4‚ŸÅûD €çC‚KÉ{f´)Z ìÌšC ­ë E*|uÙ4›oGDa½ZCöi/`ÔX/¬¤Þ ­™›ð'öî˜ B…nÅj„HäáéO�‹[!Ikg`ý¼–„¼ f>ÖH'½ž˜,7"’oaEd³ñƒSè“�ž^áãüÁãcdž�@È%ÎD QxîæëÒ×øÁ˦ÿv7àÊ/C@ æ[ìm0Íšý?þßïÚ™¯ËžùÆoðIñ�ºõ&d\<µ-ýú$(†šuÐÉÜí3 =f˜©øÒÛ§�=ÂzàZ©Þ�6i㌂��A;>~‚×�.Fa"‘Þ_*…(SY³ÄŸq~ÏŒKÑ O�£e@<à Rý`ì8#?ãýÉ€LÜ¥‹ŠåyHÝx^üâ˜á«•ÑP�Ç'm(P ?ºü¡³&]$üjþ;ù¥x{¯JêQ¨›i6¹7d,(­˜„@i`5‰‹_±AÕÍ— 4Àçƒ`UE*Uª ·¦W±òF—‰=¼ñ“¶ –\…œžú®4¼ºë 'Á�Æï�hüª¬.gæ)¤sÞ¤C“v<½„?ˆ6SÑa,êÄa,;H}>a”ÿµSvéÿý¿mujžÿÍïÙÐøIÏ£‡ŒHÂp$cíÖ‡íg̨�§¹ü½ðêÂhÙsÛŠµ±&¡ƒõ ¬?æx &éìò¡wÕcÒ.Í#ãlIÆ&&Ó:D&¤ÕÔ¥`žC¿Héj@í+qOåO:@JÊß¡F}$ß5^ ;’wÃE–ì;â#ؤL hò]Ÿ »Ñ9cÓS…½ªf¨ÉO)$8¨-Øy·qt»Žl�ï‹ÇfªZåx㇇n6ìkßûC{úÌiëGo=0ïFgíüô×› l2¸·¹Ææ¤,=Þâ§7Î=µ}ûºìÞü[¯sžßýg9Ó�>'é¨`¶º¶l K3,\ZãT¦V Æ8@kƒ,ùUÆ>�ûx®#]¤$ýäBî‰/­]‚…´^ü*LâòÐL€�•õ§¾†i帢w'4<?…x«Ü*ªV°BQÛþPò]TƒY’*õ|‡Jö¢ÛK6áQ‘¸É§Æ°¥§‘ºû-.h�k}iÁ�†„åÑã�²BL-‡]ëúI¸+ÎãUA.&Ê�AW󊰢äã?篮3N�Ûë´qê”ëšò,™|½-T«$u¼Ú¶¶>ã©ì{-òz°Í]sã5õøöO^³·9GñÔo�†ö±/¸ðÐÜUGZÜ%‹ºõÞ{WúD·ÓÝïçäá/²àiqžü2çò¹q•eÊK«‹6·ø€=ç0¾|Ðf­L]¶í[’ÐùÁ÷¸�?µÜ‚cí‡}íšþúȾ'`¢ w§Ü*a3ä…Ìá�Hínë#ü^ñ@jÄ5MpU÷¥‰ç26�ÊÝïÎK�8ÿs�ä”+¹%ä¡T±Q‰hzÇßd“ËhBI> _ "VÒ€6ÅmDC$Œâí,0�LQUlC?©8þ’§Q°ä@ é®Ä~„hl)Sbø§@OG†A¼C‰Ê#þ~ ¿ÞïµRÏŸØ>NÀÎÅôd@:ÙÅX=€w~ð}fî·¯~ã7´ÓÚ~D¥…«ÁË/d­)ï’ ug—vØ<€‹ì¤ª�É·>¸k/<{È®°KóâóÿÁ§fº\Ú‘xˆmʽ_Ž0Û$àé¸+l¹µ:OÝAµ/1jˆë§€+h(%‘Ÿèý± €téƒ**,¤w½†ª+A«ŒT�Úãæ¢oݨœ]„¡ž\ûjŽ­¾ hÀH…–HqÙ…× ©½Ÿœžd®±<±Bþ)RPmç_MSwýpMÕöŠaåÙ¤8S™‚5…¢[B ™R´Äw´&näC�x×U2…¨ Å-Õ霫¿'ñC$…�͉ÖK´*ªÒô�@4:õ¢7 9|9`C“ V%~𣿵SL:÷ôçãS*ŒÁF¥ƒQU]ÃçuWîÐh'3ç}Eàü g7Ðð—ÖïØéÇl~Q»…ü:Ëp`�CKX$$ 9=/‘BéZµ?pëÜê$ ^D7)šØâò<¶�"½‘¸Qõ\¼:'-ÕÝßõYâ(%—Ü:Ïdç÷0íA±ƒñ;RÍàÃ0iƒÒŠÕJN-wȃC4Ur ðé` §æ:©yU¾¦Ç™´–@­K¾ã9Xd.i;lϧWÁ“$Ð'¿„Ö<[rTá>×OÑø]Dg£´øWcw¼J|~ž;ºûþ9èõúzúoj¿D„Òl?-C^œ¸oïÿô‡vìÄy륯ž+õ%Aã*2²23ô8k Ý–·17®ð´ç€–Kéï_ºk‡X0~p�mÛü³`›ö>`»4í»G‹_JïÏE\êpå«p“¦�^¼’/\Pù�Àɧ³›Á#@¤Û'ã�H*•`þtP­�šû±üÛ9"J»Í„•ñÈ©û g#@‹KU´wœ °rw’Ï™:\á%¾ß“åÃðJ¼ç?quˆ|…MªGÁÀUÃß`€Šå¨�ÆïÑ ^Wy N>�Üä/í=À%´�£Ž…|Qb-h�XÁ¡‚>+J¡®¨ä •¤—Açç�  ¸ºø…w¡¸’�L9 Oy�ºkÔ_ýx5¾vÖÃk#Wíñ·Ð;èÐ+ǰi�P¨Ðß¾ø¾MÞ¿QøD6ÄÓJË!C²¸ÊH~ל½qí#»?{‡¹ÿŸ¦±'Y~ÿÆeŽoã©?À®ÊœnŽë@�Ð#9¤'0÷ø…f—ÌñÈž7d‰{†kák¡jFÆØ)f™�ÄgvO‚GI<š“^¸äVEÝ6jA+7}Ïב[zßoqÒ’;§Æ'qVvUª`^P?ÍÍ…ª«djP‹ÏŸÄŒ*³V~%T²PËÝ;óŒ¿E_Ö¿éïHÐóZ`u45‡×Ð$­ ÞªÓ’—zì�ªñS[Õœýå™ –y<¹J§$ܦŒ\v¿ˆÏ´ H\TBü�lñf œ†¦Í0´¹‹Ãe Ôk”qàs`¿N¶óņ)ਰÙi»ë 2è]�¾T5Í,ÂnijvkêŠÝ�¾jœ:|ùîù Báê�ö­�ĽyÑNfýsº9ËQ8êi¸aR9H9ÜÜ�$]íKˆî»¡‚TÁs¹Ë1"¦µ°šŒÙÿد‘bfHJh¸r%-PÌá—õÜáøSƒÄ;C*žâx’5zCaÉ!ùïu×H=œÐ3É÷å5¾Ë&ãÇìûÌÍ0F@¯-2 ~Éš _ VÉ[yˆÚÃytâPW]w‰×J}uÔˆO’G½?! d%Mþv‹¡§¨æñ§‚„Qw�B‰W”‘:©9í†ÔqM_C+ -í¦Þ¡lXhÝ Oþêw^±_ý£ÖÑË3¥ýKöÿõ�lbâuQŒƒÙ^ü"òã¯êæûæ»@uC| ZI•2ŽÖ‚Û(‰¥ÙA‰_™ `-’kU^át„Z-MÆV‚Tø­œ\^!¹$’¿á¼?à„5uå× €F§Ÿ§>U³<á*ÜÂ3ÂꄎÔb£ sQÆã¦Í�U›œ½Í&Äô 8Ê\ TõPâm11ht°Ï–(óÉyŽ81‚h*ròBXb¬ÞÚ›—&í;'—mU›�2VË‘•(ñE‰(H\äy¸suîRò’Ï­ó/å¨ô£¶®³þ69ˆP­—õîŽ Ùƒ•e›Y^a©°Æ>”~xÔðÔ¸»1ÜI�ÖY‰Þ“ rku‰CE8%Èÿ‚T4ñsjBqâ»#J!Bp¬â›e,gò}B*;Rxxð ä"SšÍ§‰!üâíªrªÌ… Bx‚=óQãÕ¾�£gdŸÇüá#ÇìŸü£Ÿ·oÿòd§‹·ÙÃPŽŽ^_çÉÎI7[kôéU£Nväs… )#‡ûì·þÉ);0>hõ'oØôÔ=—W•Ë_U\N ªU ‡Ö—ŒT÷”¼gP®é² l ´‚ ËZ™^EJâåRÇ =ĵŽI;ñ‚—„vÑ×Qâ–NØNQ_€<¬ñÞÌìKEH²s^QÝ «`–›L�9Q˜~�ôïœ�šÞ@IDAT?vÌ:8éx­�\Û:ÕKó-¤SÊ~lˆ#ÎïxWEe[ç;ôä�´’Œ>Õvôö[;‡¢ªg ™K³¶¸°ˆÐs¨Z÷"ò%Šl?©’ÀW|8ÂñóÞH‚ãþØ@Ó&õÔ×rÍÚIä»]GºOùhq;s´Óú9òNª:\ûZ¸î ¨ñ;~Òþð·Ÿ·o>wǶ疙ö¾õ b g…-¡¦Q®ŠYU/ Uo©Ê�”5 ýtÛ*§ãÞ·oýþ~;xü«ö'ÿæ »úÑ%ïöǤ!ÑíJz@•Bê �©‚zp7q@’oÒpß�ªJ˜OñJLOÜŸþŠO± WòºGð‚Wñ˜SBÐä’üüžG þq­i*ZÿÔM²ôWxðŠÔ½�„çú“GèO{`hÐöŸ9g J›í,ÜÙ\ÀlÙ`_/çr‚Ðܼ !H�l"%YùÄ8fÿa¦±íôW8m‘Þƒx®.éÜN°÷ÅwGEj%Ç%iaEÚ‰ñ¡�‚›Q�yohô³qÒ(«EJœ÷dç YÀ:bwvC=É*Ò]OeêL½å®õô'O�¶ú{ÏÛ¯~ž ±Á9ñ}‡ÙØá»uõ‡œ÷ïûš5–•+ÞgU< ’ïå)?PºùÛmöÒ×·ìþÙ—ìË_ûçÒû+@V�H|o™kÁ‚»RˆŠ¸;7¤ò$Ïà•O•�â”!%º#SSªcÄÎYæ¥YIÅ£ð nŽäQKÚ…µÃ J€”Ní2¾¢U½áI-×$K⥴iÔ’@xž—$p.h‘ðaʸïÈIã¹OÔ¤y@µ÷ÙàÇ‘_bO~©ŠÅ}¡²Â'Ô�ÃI»ÙýG\ëäUpþÁ„­°tX_$W-«$Š_ä  䯓܉Ûù“*(GOq›WÝËŸ›]Ç}ôK”À£ÓµPd!Ñ6Zkž2ÒâB=�¤ˆ–œ¶`î d"‘Œ›ü¡yO.tû±ÞgΜµ?ú½çì›ÏÏÛöÊ]ëì;ÂúïYN­]´µå)»uýM޾¾€Tâ[K…0¢lP#ÇþäàÁ²>cÇžš±ø?�·ïþÁ/Ú¦‹ºš)æ¾”¡®Á©¡zÏNæ)ñã^AÝ“y+qª€ªrÔN5XI­ŠºËaˆõª¡¨¨B€Â•óVß{J¸ v>I¥O<-!çJ•Ž¿?8«]øké’ã§kü4f*àȾQçd¡µ¾Á8Ñc½®ßv x9°Ë.Mr°Œ:Ɇ®»åþ:zX€Ä >亰íËsö`r"61uÜR[²€UyrXª3Z|ÓˆÏâå.hö*jÖ Üf:»8zÀc¿DRµ`�<Ô¯õEž+¬‹8!Ÿ|¯¹Ô¾‡QÁŸ ­w·óçÏÛýÎÓöUëúꤴ žà|ø7|ÀO›CÎL¼ËZïq> ž±åÅË”€z7á”–ž*}*fñÎÆ4—n“饽C÷웿{Ð^üÜïÚ¿ÿ—cïþìxÐËðFZ7ö½eÎÆ[óT”VqNÍ'*CáJ`5¸f”GÔ<ˆ%ÃV¾ ÕÓ²Á °è ¤º…§Æ+ÍZ==Z�§HdÆ{l”�ÞÇ6~!Õù*ÜXøz*Oy(c�õÜ‹Ÿ·çŸæäáAëgk¯þžNNb�Ï‚û{mŠ)ÁKl!Ö… jð2бŒ¨È_ñ :õùOó¨D�tÿ7g'˜®O€2 ñôIüÒÖ­6dÔ«,Pº*Êç Oªkf&ö™î^ìPrOa#O%�Åù72çaE6Ü}i(u'‡ÝÈpTãG §Ÿ~ÚþÙï?c¿tž.ÿ �Ÿ¤:{ÆX¾m«‹Ìó× 5ò÷ú÷éÞ qÒ,ÇWÓMÌìHQú•*î=õäTìZÊ;È@ÑSÏvØoýáÓöëßû§Èœ¡¾kóJu�B5î)—ÈC3'¡ƒL#¯»øà5¥¶š\«Þ@"¹d,ÈêTŠÏo\`„œ"bJ¼Ëˆ_Áʘ¼+"üäO<à—ñ+VîWù±ü;Â~ã’F§ÆVÞ‚¢pÒ�_܈up¥Æ©îø™çŸ±—åÑûA;x¨Ë:†¯igâÎÊŒýlú¾Ml¬ØjOŸ=ä�ù¥t²�Å«@˜øÌ‡u ‚C=Bön†îݲ™¹%O/v3Bœ"ŠÏPEwùœ»RØã(]��„pwu¸°¨ {ÒÔè�â{B=%)åefw‹ �&sž‘*7»q b#äÏÐøÕé}îÂ3ö?ÿîû≠žü3žzßï;†N±¨ã †‰FLÃ÷N›ò�ËÃA�ß´Î�7bi)�¦ÞÕh0kT’§g#ÉŽÃvëþì»l?ÿ+£vú™Ÿ³þå {ûGØ,Ç\)_úTìÁ[î%·žFê&ó\jiè7Õ’HIXó‘lÙœv`²€ð…Ç#CàíÀÞ¬¹Š�"á@bÑ`šÈ™z U!ÿÖ/ÚtJWtFT‘FØ£CXž± ¥—šNœ?mû_yÙ~ªˆ¯ß 2à¹d÷à@Ÿ-²è_\¿gß>yÌ&ÅŸàSÀA郢�]d‹[;=¼Ž~uÿI›'o£ÿ7nÞ´%–˰«ì¼ˆHG¹—¾¼'‡ ôÉ-±ü¾˜º«q$ÿÂkà¶à9¼DªÛ_ Z@¤CùâZrÒ`F\! ,0<\€`ú+ <�Ÿ?eG~þU[K׉¿2â}jtØ>dï5ÊëïïÏØ«O�µndÒȾò §¼ðtL¸ÂúæßÕO÷# µ]X†­‰ÛvûÎ]/Õõ5ðšùÈÚQ ¿t’:ðÁýî?ñjd3ÜåÍ«ûBh‡>ÎåÉ€” J‰ ¹ ¢ßÞÎc¹deoAEIYiDJH>É·õî�‹w÷/¼ôœý¯¿ʾp„yýþäåjbOÇÐ [X¤ ×9æÙÿZ‹NÖ}fâ{05k½ýg¼—ÐÌSÈ¡t™ºNdÉéPÏQ›�¿S V²êµ`•×ÝI{îå ŒÀóöëÿý×ìü ϳ�kÊˈ©²(Gs5©YÄÏÁŠáo‡Kä"T¹9R~ÒÚECl$¡˜Ú—é·hwq“$åå|7R—ŽS.³Ç{?ÍŒ  MŠ æ“™Ä›°GE¼05çB«3O>sÖŽ~õ+¶Ä¼w‘ÊC¼ªS4ân~×f™ÝÙn÷Xÿqyþ|î=>Í̪݀�Áÿ×Þ›Çzv\÷�õ¶ßÛ÷î~½/d³»¹4ÅU¤¨È¢[¶á‘3EPf<ã ã?æ�Éd`xH$ƒ OØ’œxÈ#1²cI\¬…â"ŠK“löÂÞ—×ûÛ÷}>ßsªîòû½Ç–ØMŠ^½÷»·êœS§N�ªSÛ­[W<š::¬b×6?†Ïœ 7Æ'1|B)E#6¹sEJ¼’s©ýjùŠÞœH/g×aºxãïð\s9‡÷ë»õÀe�’*yqæB¥{ųRÊ‘%ŸQ¨@Ä©@ž8”ˆ«Ö#°}÷“Ýþ×/ílºÌùïœÝž)W½,ýuÛ¾ív’^‚7ÇHC¼­÷%a)¥Ü•ó/p|7ë½Àó‘€á�« Ø]ךù”ô4‡Ij2‘Tb}$K‹Ó,.…G?[ ó|0üúï|6ì¾çÇKµ�£²JmœÖ¬DªJæÎêÁ”–c\K~„xþoútñªŽç˜ QÌø‰Wäg0«=)M¯ÀYTÀ$.ú 'j�‘QFOÎG‰.7þœ^k*­ Íï|àÞ°é¯<&¶ÞòwŠ,“SOxôÛÓαßc>êY#ƒ#7Fà óû{¶æëZ�Ó½ŽEÃ&Îþ׈@Ÿ¯ÐûŸ?s†ž¦äÌdt)³°`U?ÕEú*œÓ èùõÔ W¥cõ 9ÝÒï­ïmàAX®›„£¸ äÊ!‡éªˆÅ_ŽñÖÎâ�+�R4G9AêšÂ§=þñ—¶…ûú/aüçœ$M FÜØº‰9Ü Ãõa/Hd�„*(Û‘‡ßÂ+¬\<ýcÛÐoU1ѽâðÓˆ¢¥y«Ã×øªÌ¢ã‘¯šÎ†šK¡§o8<þk­áoþÞÃá×~çɰç #‚ö.Ï•ÕubŒuÁ% ¸9¥ æ¸tM©Em%ªe&‘Å{N�‚àâÍé*fÞ'I #%E'ÉJQ³4lKåÇ`ÄrcMñSÂÆ…¸)ºQ¥€âÄaÃ@¸ëÓ�†ŽÇ £}0~\̰¤²�4èçßw‡'˜îSb‚C£´^¾<ö°cpSg»}sAp› ±¾¹™€Í¶ø×Aï?~êë;CÐi S2lÛ `†š w®ÕáøÕ�8À(„Ž¿D^Œ ^‰“qWT�nÁ÷{Ï[t>w2ýëRr?�„¦þ˜)ç³Z#U©�m˜×5?óØ'Â?ùâæp g�-½<‚ËŒßÙê5Ñй“O;«÷wÙtÕ±æÖ[Ëoœ#==Åìôö¼ZÚXRÌžâ60âhjè メS�0“A=…ŽÕΆþKã¡·8<ö«­á‹¿÷@øÍ¿ódØ÷Éûù¶]¿I ' ^ÙSÜœWÆ´(ˆ€R Ù³rNši’Ä#e¡Ì#zÇ¥«ŒÏ PÆŸ€ñî«Ý ¨ZVEL4ºëEýäÍèœ_Ë}vå’àFʓޱhm©„Ýwßv}î3aùàýa„G}|÷ò)¥³”…µ÷c3Æ=<·Æxô'çtæ sZ¸>ÆzÀÊ�’‡Þž È&mþ¡ñâNh»r)œ>þ®-þé%1åßæþÙ‚®Ín¬^£ ÊÅŒšô—r*¼»èK´jTÊ ŒÌAÎ%F¼¥Ûmz + êu¬ÊÀ{J�R4«T»U£ªÐõÝö'Ÿx üÃßî»Úχåyú[œQÅKdlî Óõ•°09hC|1TŸëJÅxI_üìÙ0_­<'™„Ñk‡m@OÏ.žíŸ#‚Wêõþ-[ÂüÔCù¾7×ÈË'|I&Vz)C<”F.RôGƒã¡§·><ô+maÿûÃÅSÛÂÑׇÂù£—½ÍçÖIŸ(8;†ÊÃÒ½Wqnª¤UV‹nQJÅs6Ρ„,TʼŒK–®Ò'Çêý RxíHÔé®Äpªðîãs­¹ÂËB›wn ý÷ õwÜ&9˜s›–ij†ázƒ �8Šæe¸¶wu„W®ðôGpè ‰X^®pÐéÖæð8ë?:~šá> ƒZ# ‡ÎèŸ� £ÇŽ„sW®AO~T/€k#‘ý©Îú&}–“”¡t"ÈAI²•1*€bt“½vïãzË €*¶1Át‰ž$¨Â™ ™gIKÆ¿ >i®€RA7ó\÷³O<þáw…íMg8 RFƒTBFž–,«ïu»ÂäØy,’¡:Æ*¸~Pfþ$¢Á# ßðBhmÿ-v“�…y­+XSš+Ûxè†.Mðh�^ež (‹¤-¾–ÿÈT�d–ÒB¡™dßJ}Øÿ‰Å°ÿÞMajü‘ðü�ß—Ž …ás| b|:ïÁ$©þŒ7wOÕ+½’3gÌc¢EPô;�ð1ƒpŽ%ÞYENñ2–.ƒÀ¨ÈCP{Þïý¾§$®N]â (ç–d�žxìV©„Þ�M¡—iÒ]Ÿy›µ†F'‰+óaãž�¡Â«ŸõKSà¤)n�ácêVaH˜½rÈZïˆ2œzh9Ñ©>yßD$,±¢ñô áλŸ ‹‡l@¥ÒÃhƒ¡&OlqâFJ§“ý£z;Rüø%'³U¥õåDUq9åC�«4·l ›˜\i½ö}n"ìylC¾8®ž˜ WO‡Q欳|ŸŽ§Êœ=㎠�8™;~º¹+™[„—œÌ…ÉâDObÁ=òI=|‰ F6¶\âÐ?É�ç3ã’ñMƯ§7êÅ55kc�¯gë–ÐsÏÝ¡éà}avÛöðßãûF¹c…}-Ç(‹ƒ3aË…}íáÎqF—¶‡ë§gÂ�3m}e$Ì�M„E¦;z$&‘½B¦Ü¸æÊ!ÁD¨{,€xÄ�ÇH:ðÚ–p1ª3àZYVH^ëân?a�[òy(q³a» ×Ti ]½=¡gçŽÐÎæ­ÀvÞÙ Ã8£í·ÔþÅ‘©ð«ýía„•øiò¬òÒÛjhM…ù©,* ùžG835^�-£-’R?îK=9zGf‰­µ„·–çöÝ~xñJ蟜s‡…ÃÇxËS±eü46êý¥gû³´+ýx­öZ8�.‡$Úµà‰’ì$Ò²ÔV�—QülžÛÔHªCôæICh•%«†(8+C�¾fØr8wædø¿þ˜óÛ÷óûÃÞÖ³¡ŽW{µÃK¿EöýÏ\z• À�¨z¼£ªzèÔS«r˜?Ч”ª×F®½Íë¦z_ànºþÖ07yÌŒ›mc,Vx|„QcÜíM­a†Ç|jltæœZëe�Næy1e–ó&9cþw½‚¬óæB{eCb°»gwØ0ͱS3œ3@ÃPGœ¶îq~Ía`_+ ÑÖ0q}{>¿FÎO„qæ¸S cø¨ýÒŠŒ[”£Ž“®­’¦Údúv]憜tK0Å'(LNWÔ}¤Å2d²3°DZ‘/Š÷¹:jA'-¼dÓÚÕz¶ „�ûÂGn/nÙÆÛ;Ùa©’€V+1ôçlÏ×ÇgÃCèáÇÃÓfÔJ2“Æ* úîÖÆpinÑŠŠ1p:kˆ!E®†Ehš‚p�]„g)»'z:Â¥×^ÿé¡023Ã!åóc úþ ò™†ÿJ<ûIZB.¶²«i& %O&wpÇ¢3šB2Õø"íûñ߆à}ˆ$�gN�� …§¾ó£pîò}áïýæ�áWv¶²�÷jXiê¥"ðL˜7þ¬ðHNÏÿÕ¤¢Q¹iH­´TÑ5rHÉ f•�F—Ï>:ºþVhgQ±gó}¶[L-ØràŒu £^^c:p% 1EY`Ⱦ°Âùô¦†¦jt$µ÷DÚG¨½eG8zêÏ8/ðtìÍÑ0|kÐgÈ‘Õ77~•¶¥i×òER˜Ë<®ò%â’Ü.£d—n *Ö–�:lïÖÜ-7|[}¾AM6NúõÖ3_#ZÁø× ¨‰’ ÚRZU?Ñ)}SÏŒÏ3%øƒÿ÷z8|ê¾ð»_Úv¶PQ¨˜KÙðY²ê†Ñzd¢^‘²F –ŠM¤~ž&´wmgz‘#¢O„žÖ]aaìu’e¨¯Ø42V>‘O'²,PyæIÏx"£«¬Ð_ŽžæáÂ4£di¢½<}>tußvõÝÎ ư|#’‹Cõ‚�Òqžêáçð/„¦&>rÁ2ysgCx|ïCát˜['ûiêÃÜør˜_³cóaf„¡-Gå-MÌ„‘avÅ1\^œ¡aà ‹eíNdÃFqô �›Ò€Êì8¶×ÖcÄ œ²£}ó�¬¸×wv±Õº“ý]áží¼ÏKFJ) ´ö‡k‹•0Ì衞/ä®Ð`%a™»üKìn / ó�?‘¡Ü†ì%hõ_Sªƒ0Šex…L%Ø�ú°côF¨ÿÁsáÅ¿ÆX ¨Ðˆ®0ï—q{ﯧ4zZ#IeŠ*Yñò[õµ\¸ÖCÞ¤1P5ÛÑÑNO.„9êb…0^b_å-V1>šÇï»Z~ðLxñ¹…kSÓœ ©~QòèäL;¬÷×ÈG�€žÚï*Ýçàä·»èkœòéÎó™˜*~Â(ÏNgy¦þhê)P“d{·èTGoѱ”�ÀÒƒFêyå·Ý­dñ9UÊhº‹ Úå ¨Æ¤°�´U¥m¢RL=«ìËK΂²EʺV›é¥f&ÇÃK/¼þõ¾þýw–ÃñÑÝô\œLáªZ*EUuë©ËÚ’=ÒÂocíê߇aò8‘ôs…¿¡ñãÌs Rzº)gÎS19¨’«…J/Ê�ZuÅimÚ®M_$}5^¼Š¥QÀGŽ]^ºö — Y/èÃ^׿çÕý2º+<½Ê1×{yJ²ÌÆ-¾)›¦,\ßÜÜ-çáÙÇ5/�–tP¦}�=ªôÑœ4cøö({2˜ó?8Ðm š«Rç.,‡{7õ„SÚÒg�”7ÖÄD:P.å<·)Q|=൱ÙÐÑÔ¶·0ú‚¨—FüÝ ì$޲¢Æ[{­,�æ Ò:Z¨Ä6šRo+YbIÜejÄ÷:žá÷ï|$ÌÌ�Qâž&ðÅÅI6atœ1¸0{ QÜ�Å"9É«E¦YzÏ»f{…ùyè ƒQ˜u�Žˆ£S£0N#ÐÇ>†öP £L;t³‘Ä‹vzå{1ÜÑ¿?,t4…asž¦¢¶D¼o¿>?Îê-¤´Œ�sÞ½ä/’#ËÞ®-á�‘±0ͳòÚê P·bDψøO ô„az× æ´o¡£}`×ÖðÚ¤¿@¥ì*®ñPÀ\® quþx$¾ÐÔð¥6=ÐÙš‰?Êæø„>õÍ >”[;Cù>F [YØÕV {ÛšÂ~î÷ñ˜ð!¦G3Ï|7<÷ôÂeŒ¿Â‰Nê–”Gxi Ð(ã§ðù¿ôâ¹O黂QÇì*™)ɨöBôò~.¼8触JÈÄɽ†Í/FÓÆ#Ó¾I¸ÀtMUûë'Ͼý†Ç|×[n6nܱ ‘ÿ{ê6‹l�¡­µ=LL�Š92Ñ×.£2�å8ÆHþª¸€…Ñ·ûÔók—'%Œ’öqi å‚·Ý[i¥aœ>:tíz8òîµðî•FŽ�ÞÌË9]œ!ÇÊ �z'¨­Âiè%§–·½÷ÎP¡Á˜šcóOœ« -ƒ™›bãÎnæó ë™Xé+ž"ãt÷±Q]˜CÅÓ ´�CG.L^e«éƪTqé.?NÐá…á°§÷Þ0ËñV³ >ÕpÒElŒ UoµǃáüÂ%“ÙbSç¤ò`æ 7æ&Â=Ý»ÃÛœÔóG*ÉÝGï_©ïïŒ3ò©k5T”4ÒEm!·š"é73,›µ¨ðüŒ>Æ92fX|€Þ¶£ÛVñ³|‹¹£ñ…�r§õ»[øAƒ mºoÅh»iPžèkµæNŒü>:k w6Õ…-ÈÒM}ibŽ8Ç´a‰wú[N Ǿýíð½ï¿ÈÉ@3l;fASÕ…y¿JŠA£-ë-Ð|ñ/æ-Ðs ÞT–Ä·{ "$¯PÊ«îj²È¦½r¿òµó±“9ÑEA¨×ÿîÄ™Ã'ûý:MvnÕ]b8¦f¼qÃ2ead29å|W(¢¥¹Ù.EŒݨLKZ¡Ž=°t¨ÆÇ[f†‘†‹áEÇÊóB#…I/Ï|Φ”4O/X$œoüäP8ñîùðÒý{Ó�m÷ïšã‘ÜuF¾úšŒË¥õ�&º7ÞÅÇC.!se\4>¬^ão‡Íý³À£�Ežák¯�Çm�z'wùÛ0xõî¦_¤eTf(ûiù]a:1§¹<妑…ÊTû&éi ƒ#K¬þ7„βòEIº”mœéW9òFxõÇ/„7O_´éƒ÷üh‰Ö\½#_‰Òãbm\Rg–M¡àd¹ö¬+£. ¦ÊUnœÎ‘éê±R½TL¼ÒNÊÔ) «Ç®ê¼4åU’ñ‘Å–z}’ê–Ü-7o�úü�}ûž>�p›ÔòÊ@+|îɆ))Gï)âMˆ@˸ísÝ*ms'Un�¬N‚6EZÀ{ ÕMÅ÷†@ SÜÒÉh@‘TÀR¬‚±ëWË?¼Þ9¼!ì¿{wxì¡ÍáÞ�‹ìлz�'V²% †¦VZ%æÅ-!ùgø=1#4,ô‡¾îûÙŒóxŸ¯{e¶(v¾\¯v—5n 7FÞ´Ï䆷 Å�d–áxá™�†K¼ŽÜï�½ÂÙᣌjØ`4ì% §®pŠÍøô9òÅ&þÜÐ5!�Èmg"�g3~Ò3U…"�&*üñ‰ á±¾ask/«øCakûfŒjœFŸÙ`8 ¢á¸`äf88Á@©ñscש;Œ¨…_SÃ*p†Õ�¡z÷æpŽÅ¿>>Ñ­<ÎѦÏ`Ô2ò+¸9GY˜�s_ä§²Q’ÒŒ­È“aM–Ó£¿~ò{˜C>ø ý>â±§:鳇†y˵Á0öÚOÂ�~úZ8{}Ô ªB<² -¥ÈHÑæü2~›ókÅ_‰äe�%H¥�Ò—OÕÁÐãM®èw˜CŒ^”¦KïLþpäp¸cߎðÈ[¯²›°«ñ$sC>6©‡ä¤¡Ç`ª?*8ë÷à­÷ÉG'N„–¾‡9Qvz¸€ÙÒ¿ÓsªhE¯G=¬ü_ž�â‘o/j$b|Tœ—‚^ROèâu’݇ûµ?àFå˜sUT�·÷݆WØî,nä—É"9™¦1¥ñ23…�ù7¼*ºÁW¡±Óá±Þ½ì¦›¡Wæ;z#çˆ(³Z4Ùë06�ÚhðZx¢�F¨]ë?ú¡C-ÆiÛ’Æßú›Þ˜ålƒIzðð'Yg™¥“xm‚½ú,ÉÛãCè5š°™»½» _¹Pù·Í°ez<´Ÿ>Ž¿ürxƒ{ÆÙð¤ó(oH1*MWyRD]°žßŒ_=¿ÒS'BšºD'Ÿ‡\«1`t S¤M~¿‹Yæ«ò,•ÁHKC“>NBã¨ÎL²38ö�o|£hÎïç¼Þ†@ ¯#ëï(í9¶Å¶ê%sHn.æ$†2-dáÕ=2|{Ó-CWóÉe� O5;iÛ|”6�Õj4 g× <.Ôas>u‚ê%W¬kÑ\pÅ>õæË7ÂñwN‡ç_:îxwxèáþ°w;ߘ«LaÔlžQéXj꥔.½—ëcï„m}†¦Å1z8 ]&Aº~úï¡óìfø ëúÌƉ‹Ï£�‚˜‚e*mɨ•þ“¬ܵå±ðûf™×¶òùòÞÞÍáèüqÒ'ÄS�/§tíNl»Ó8?õ|L@ÔD)…ÎÏ?Á÷Ûx�iÁ,ÃôŽÐÙÞZØíW׃Ì:)Gã¬3 eàsø4óé9½Ô†=O²¾K×júhtÚÜ~xéš=yp÷®ð;}(L³…í_uJÅÏ €9^ör®ÜÒê’à¶4t�¯ÐÚØsléìlï6%«ºKw…þ&Î*¯Ö²øŠpóx‰­Q¢49·ù%ƒ~*X*—� ¨œ‹Úî©…ÞöR4�§êgW¨es£áÝC#áôÑáùç¶„ý÷ï0=¸û®®0ÐË#§†éШ§$¶?«ˆ¬\?º>G^RŸŒAê ´`è?ξÿæô�ôˆ£±d”¢“ÝJÏÏ’;^£€ â^e�bßÀ'áóßÛ{öñú1ûüy«�õX"“âɨ•½£àCtÉ'#h­ì@¬0dnfŽßÌ7[ðWtÄx¹v`­¬ p[‰'é­Ç¯Y«×ž×ha±Òp§)ET¬‡eD)(OÊ‚-èñ•ž ¼¤4É¢à>Ó}€MUïŒÑ ßF«Zä#�hhDô¦@:q¿>PñÕã½™Yž2 L3{Ùܵe”#ᎾÞä�¾£ç.†)½ÀSåÙö}ÈøããÌ&z~­Y¥G}>)VÒe±\2Dl¬ÁÇ©¯ì2Ú¼\UÎr)òòŠÄÖµ‘QË䬯mÐH®¬46ýDô·ênKP_?te¥é*•vó<ÛD%¾öÌÎqVk4D4i!æÜ€ æ>ϩٔiœrõ«QÈSúnC !•«0ÕP©’¯°o`ÁÞú¢BXCà4öÉs†ºªtKLo®ž=®]8^}¾'l¿cG¸çÛý{ž ¡§c–RïçóP„Ê?;w5ŒUzCgç=a|üm`Ú¬ÂY­;yëìj˜£âaŽìJÔBü£xªØ6/èNòË0ä„W/wqê ï% »ûî =¼Ÿp�Ï›SuIG´MÈÂË8|³ÂÏŒC·3 ˜rˆNy_dê°ÀxRoêQä›~f�_ Cã|}x‹^´ny ZFðœµÞC‡ƒŒEÇl§FÆnרHÍ�!åO^=ZÜÁsìó“¼¥Hzjž9u>|é¾–ÐÇÂß5÷¬×…^š÷ÞÝ ÁúA5,ä[W{—¿\=Û?}e1ôÓðmåiÊé·Âzýc'Ï…!Þì«gž¯çû¶(Hšú3ãGG �]¨tGöêž?ªÜR&ªþÝ™ÇùåÀÞchÝëyp¿T¢!\âÙ[55·\ëj¶xyåZëJ8¹ÜÒ-ËÏ-q!ò¾}Oü9Êû--nê°W`Gynœ 0ËÙ YåÑØÏÇP%ÑÒ}�ˆX…Qˆ–Á“GX»8«JIÝ 2 ÿGÞB NÅFD[PÄ# œTÓÕ¿!ì¼k{ØpsØ +ìØÊsé66kÐè-Á�Þ‡xÎvŽI©l­¡©ó‘pìÚë W5Sõ‚×]�u×ó{4F¡¦P~Ã+‡ZµÂ€ui#¿–¦^�½Ÿ©Ër¸>Åzr�`|O½Ÿ˜4�qÏ3M˜cíb×#DíŠÓî8šõà2lý0jí”»“wÆGÃù‰ë¼Ö¬‚zã‘Þve#ò°Àh)ãçg~i5úYPsy�§Ó„ðÉ­á/Î ò^Ãï,òFåRØÂ¢åoÞ{ üp”3¬d�Öˆ‘_ÝåÜ8¹+ F†_?{}?Çó¿ãoqÈë™ÃáÂáCáÝÓgÂ5>Ý¥Å×Fz}é‚,_妊Œ]ó}ÖedôöSc¶–ñÑÿ•²; ëÂ/‰Ì�*YM$Ge41®(KêÌx©Îuôñ^OMFù(I=kØØù‹çþÓUŠ÷>·e ´ÉÏÓü~Kþé™i¦]òzí^CN •Q«üe•Hµr—©®Lf¡ŸÅøEèÃKç,~‘7†¦·Ô0"XäÑ¡> ÕÀ£¡ôÈF 0V‘¨X*çF<£—ø^ÜåKáÈ+m¡kS?Ÿ©Úî¸{SØËa�Á\Ý…pç†{øvÀ‹9<1B!jtäêWC"IÄO-¼+.RO/¬EÇF5ìBTï]!Žž“×ëq(=õ"S� ’ÖAS¿<ÆyM™¥:†æ ²¦$2L F=« ÀL?0ñQ�§ÆÂzq P B •¬³®3œšfÑ5-3’¨£!S³$“·†Pê´X2.¾´ ü—!"ˆ¥0Àžÿ‘YN3bK¶í§‡Wºd:ðæù‹áQNú±½¿ïÆjë6Fö²µµñFžÒ韞 w\½.9μöz8�lèQ¾šX”ÔN9Ÿë“>0míÕÝ÷ökäÂhLCòì½¾îPèb”ñ*˜Aâź8TWó)åלã#I„n²p6®HcP*ñÒM¾fÎP˜æô'95Thù ܆ËmlV¾�!óÖk]E+¾½ìEoâò<‡a(I7æWXr¬CþNºr•íš”[�\Zöç¼ÌÇÅ«”Ê º”-abC Â±^J[#`V£† ^'ˆFŒ¸¨²éYM‰=õÃç'Ãоøb[èd×àÀ®>VÙ5<¼ÿAž³7Óò” Ò…akë) k:¬NÃsŒ�©¹´XYGo­¯ -±°ºÀü{C_ �5ÏZQ‹ža²Lí±^ŸLô‘©ágÍ[ê™ké]�%å Oô)˜7ŠƒAÈÈå“Ah}¡Õ,-ê“ ©ÄjŒV€Bc`ÃLòF#8:xÁ~'_m/ý—×ÂSÛ·†mwl »ïbqï�°­ŸsðZ9y–ïÔ/Ý CçŒ?VàXÈ’qÛ¢"iÈpeЩ—vƒÕ —mº Õ/Lðí‚ëGC/£‹�þÝ̧Ï!?ñÈ`=ópõ¦röÈS žTÆ�ðr¢‘>Äsß9|÷Ú3D¡‘ ä–QF�¶Ö©q‚‡tdû"Ä>¶ûzC0:�©5ð]Œb´Þ2È�¦Z3P“#žò-מ�§Yøòýíá‡|\gc€ôË+¼J=úx­»�¯òΟ9®œ<Î_¸®��3e=¿Os|7h’°òZ^ò�õúZìÃðõR�Þ¥°5«µÆ¯|¡ˆ²&W4~ᥲ „ã æó •<Ù}-H-\¬I‚ïQðípYbó˜*Ù¦þÆôâàm™ÿ+‰ÛÖè™ä¾}ŸúÏèãq1žœ™ Ý=aœÂ«vòkG“œ²ž2«PI¥€‘.^p@Á[Žh!»XJÐUácPª&¶zIUò|Z ¾�?z[õ(�§Q�Ýáj;¸Äþfs\ŸDÀq#œ¾Î>^á4œÖî®Ð½¡; lë;vt‡m›[Ö ¼¸ÂQW¼ÙViä}öz½'/öµ´ìO&«^¹Â*}' M¼AOÚÞüIx¤ý7BWSŸí´ NQ+ŠcÍ€Œ™¸2Èzä3^À¬ÁÞÍIÇ‹à4«ý2–Ô£“4ù¢ºèÜCï«I ¾â"“°Ö˜˜Ñ‹2¶-­$°³{C856Lº6Œ”ñSN0KÓ£xòLø�{þÜÛÊK[MŒfÏ�åhô³áí‹—xmxŒ''< '®æî:°Ã YwtbL½|Ô`Û#^kMl¾O~l•b§õ8±ø­VÈ/m$˜¤¬1~ô$|â!B~-F,ÀoŠ2hõ%¥¨:&glµ´pÈÊäˆÞúU½”Æ—žúÁ~ 5ãÛân[ ið[Tøʽmfv:ôðˆ§™E2M ’²ôl_C~å°¬+•TTd´^sà·VþË •@¥@ÆÄ TÎWt€ÂÆk†Œßk°Q�ÍÅhÈè3ÉŽ*¿Ѫg“G•Pñ©/ƒz#þ ]f.rîÅðà¾'yÂð޽~‹P¦gåFvkZ—•ù%Ÿ$ÕbãÃÿ«×¯#¾pþ­üêåWh4§çãáO+ðjs­¢çùH@FÆæÙ� rò# ‘Ä» ô¾~3ômÔ‰^ԩܸL,42%8wîB¸Î [Cã¼ü¤åRF3ä1m‰UC¢a¼ä·_� ³Æ0 k¸o�ƒz}õøÒƒ È ÈÍMWÅ÷‹ßL#˜èõ“_3~âh„±`~ed›ï��J­‚E'N*&�>›õub2£€´^Ãtyºn©î[‰övÜ‹iß~aÿþO›,}AsûÞî~¶Ü¾f¼mc�e¯œéêÐÚ‚íTå Šë•ä/”Æ )—ª¶ #”ùdÍäÁþ($j Rõöªqxk�A^ºfJ:Å®ú7>¡��‡†´4 Þ£ocnÜÝ×z9:«oC[ØÐ×zº™:tÖ…];ö‡ ãÇXàE^ƒ^—ػ�3 öìÚËVÞ£–Nzº`mÔë뇡¤°ã2~=2ÜÓ¼?¼Å“vÊò£|©¯×Oέðtm_b=@rS+ù÷jFå_b¾´ƒ:À$6¼xîG¥³¸¹ÀÈE»ñ¦9½˜…­e~³Cü�1F‡ÇÂðø8Yå)�Z+tá�ç¢ñbØ2jlÁŠÕŒÓôžV÷1|MÍŒNq4ßç®jËü©ÜS‘Æa| /©ã²à*Æ/¾…î5^ҖŲPvI f'y-xSÿfk�ç™Ç(y“èµ�„)ßMÕ5 ÜlDù¨ÞÊà™Çñk¦&�3Ú”rL3òöÞK-´™³¥iÑdÐ2èT–2°¥Eâj˜m zT’Ð/Ñ¥» Pi[òfTÔ4§ÚLqº/mç0‘ÎÒ‹©ahЙ ô ­<>ëè>ÅÈ�í·]-ü*|1·B¯Á³öæ¡0vckhîÖWsÇCS3뽫´UÓµ‡¬ÖÂ[ékZ0к=ŒðmeI‹“± ¤2Ÿ”cÝëWXdgcÃâ8PiT[j5«cgP¿¶.ñ²OÛÈr¸põZØrƒ“Æ9˜ƒæuÜ îôl32¢×ƒuš”œŽP—á62¼—ñ™ÁsçßÃ.º¥ç=¾hÔã3™ ñ³Þ„ò(>fÈÂÛŸ%}Ê‘;å×ü Z9»’O‹q' Á"�•Ÿ—¢A"Êðº^=“{"wé82•.#a#@g-NÞàT'Ðê4¸ý‘ܾëmoX¬ün[ÛòÛâA‡===ÅñÙm¶UT)wòÃ9¦Ö‹bMò‘ù2�¸å�¨â âe‘ã«ÓN•@ä·BY…JÑ ¨ÝÕ,¨!Ž_èÔƒ.jåP�Ý-Ž$³ÂÏÓ÷Guâá’x�P˜gþëC ‹,¬r.ÇÁˆ_\Ô´Ç�7Z´rüBËq>eÖy·¥�)F+�yù¦Âι k úG8=+—Ñ5`pÃ탬ÙLZc`S[-š%o�kW8€^|…9;�'X¸äi„ÅØõlžÞ{Ž£ÀæìÝ{Œ›­ÄòÏÏó£7[´CÌœ Éeè¬à³+GªÐºEÑh]WÒ…ëR£¬e¨Ìð½�UœhøjTR„K†_¥gñËÊÀT­Ä-™¢UQo&ŸC,6Õw*{‹nó%R¿2!…»—­ÃM#B”_G§/LókiÕ6e¦Í‡›§f¿ãÌnßõ¶7/¾4æ­1Z»÷IDAT ?Àþí-ûèøˆm j⥌%„,÷–‡XÌŸÔS�¹¨äµÐ™Zs@0«�X‚¤Ò¨NÖb–(�•I#°‰î•Dýcª¶F ´•®ˆÀ¨PñZåeo� ©bÛ6¾¯†!OSô™ÓP—?µ5rÆ´·= Ã9És™bÞ¸‹€_"FÞši˜_Ãb›CËp4¬&]åÃŒ/ŽL”,=ñ“ܰVƒ ø·]µç¨ü�:±ß• ¶¤zwƒÄp2xÑ$#’,ž˜P�î¤Q†�Xðú0_�qÕZcàyóÞ?ñ'a¥+1J×2„]$s®z¥í8’“²MV‡%|â+5ärg!Ž, ÑfPKÏ뉓˜Þà«7ÿš;8ñøâeO—2býå¾ñÒ78¤âöºÛÞH¼¶ùé?™¨kúŸ)ð;¨˜zA¨‹Ó_†9y5W[uF¼Ú”¡‘:×Y]Z¨ ‚¶�CòÒ.ð̽%9kÙÀZ.¦P¨=©W1û7S0Sñ^”™´Á52 ¶ ÜŒœIºæÌ2X_LÄ sõnÆBbYMT]á5ņç&qT�Ý¢ßàб "Ú0½Vª'ÉÙF(Çœ{RPl5¼VϪô“ú¬a‰‘¤3}ÌL18z“ :õ/˜ãa€_æ ¹‚7�t—L5Zé9EÑ=ùórˆÒV7å[wåñèô�˜+`=Нr‰øŒ Xdž ,”2]fÍDo)2m>>ß´üU§¹ý×(éíg,Žwî~ô˼M÷uÕkžF:0T��æjÉZÏ·B°²¸*�J�ŒIõÌàÕžbAU%I�SÆ/1ÈÉ#N^AÄÇì:Òæe}ñæ1ˆ&¥ "?7‡P}åw0Þ”–ËŸ‡-m‰ŠùN2Ø´B8ød1À[ƒ"˜¥›aòrÂÈô(Á¢Z‹¤tE/ˆdJCœ}Ä]Ï E¢¡¢¤Ÿ~ Kñ’þäçGk� <—ÍyÚÈÀ‹ÚØ+‰Ì) tK¿ ¢|Ö½ �SSÿMÙJÛœƒñÆ´¢^ó°¡*%\Ô¯ëÇA‚ñï2óG€ÖZ{8˜¶§›¾^D*7=Þ\ùo¿õôW¾ž¢Ýîû6� §ÎîþÓ½wœ}†ŒüšöŒr°doWo�ñf‹EÕÎTõ]�Ë+—•�££®W ¨Œ.…JìSÀ¼9a*øRN$�”ûm„pS…·¼pw[sœ_Ýà­¢‹Žèš›§Û‚‘…E<3ÖœÆ{V¢¨!µ^Wé¹_ô‹l%,åœVLű4“0Áëxü'*KÛ|„d¤ú‰FN~¶`Gzš»+¬4ÄÏŠ×â&s‹ñ…4¼ Þùßš ¡œ�ù,¤˜‚º“·4¿ à­Çϱ…(¦Î7qò»ç¥œ è"/�òXH¥Ýq^b„€©BÔóœ¿�wG&xd*ÛÐöf¶Ô?;:þO=ÆsMò|0Üáº{÷£45Ô?O¥éPÅQ •ÛáÑë¹Â’ªÖ”&Gd¾Ì#Ñ=`¶sRF—B‘Âoµ…TBð¸«r0`£:à»b ÉvSÂeºD‹ ‘îD�h†p-:(«  g´º$‚ˆÈø%BÇÛÁ¦Y¢ÑˆU9ͲRe�L™�ÖÙN"goF#¾ÑHŠÔnÜ)Q0‰N´&ü ¹s;Ny¶xQ>'�r'˜€"�átKq#:%’ñs¾Õ”Â1`éá·»'ã´‘[©¡ða�©=¿â¥GÂ1ŠÝÄÑs¡Q4L§ÚúzìÝ�¡óƒÖ ø©Ú ¿ÿÔÓ_ûß‹q?ÿ:HOÍ,þËÖæÆ_çÍ­OÛT`Œ©@_ÄaŸÀo{Å’Iä…{R,¬<M)�ÅÉ ©T3LÙ“-p+À2^üÅ+ã—Ð ó¦ŠÄ«sPî«e�ã܇,x|è�‡€:}ÁÌ Jy•!Ç ’Zæ‘I&e”ˆ¸T‰åW¥”út@t±AHÐ`X…:Ao$‹Ú”¬âïÕÜdT0ʘ´šÁ…ÒŸ‹äL�­å<>XãY JñWAU_ˆµª×d‘Ú"6¿ËGŽ#Àn¦R|F/ˆ#mØÅWØua3±_µúª²†þzæ¯G³úÚ2oþ½¼ÔÜò/,ú|qi?àDÄþŽ;>ÈòG(¨GÛfÛÙ²ÚÑÚ†Çx™E/‘$­g²ä¢™/BQ ÔÆH%”aÊž¬ ¼*+Ö 2@æ1Æå�@Ô ¬Äà\ÒÀ骩 Û¿*‰\5~-”5ÆÉã{CºI†Œ§xçü«õ`[” í49%ÑØe¨E)¹ÄßÕ,ª"'ü…ˆ&c2ÑÙtÅ¢˜$ÛÃ1�œóÏ¥ÎR‚,á-FŒ–ðI†Œ›èIÆdÍh‹áSE'° &‘€O^„ÈÒÒ #_ ®èYùC ßîËH7*…Ž+ëÙÎ7xËqŠŸùÁfleeá³ßúÞ|Sl>hgEóA'"þ§O¿ö6™cs�[odžϱ' ‡5)׆Cø‚bá—vM¿bp—Ñy)¬I]â˜E*’;°•2�Eª )-X*&hþl¡.Ùq EPæ—"%(wô`Ó+t�ß«þAŠº½÷¯Æþ. !nÎ#ñN0Â0ÊðÎÁ%—ªZ’ÏóR ½G¹•èµàüÖ¾Þ,BÄW‘åÁÜ—¥Q‘ã ìžTˆª|I' ŠTÒS÷–ú˜ Ó£ã™Þ8Þýù°Œ_²~h €;}ú'ÈN§«–NŠŸeÅsÅöTf& sQ?j?5ì ó_®ÎÜG7©D¥‚*–†„3W[Pœá£§¦@³â­á%ŒòËгÌ”Ï4BH¼W½+oüœ›ÅJ±#yLGFWÌmWÅÜŒ5ËM‘®è§¼ôeð¼ Ÿ\¢c¼ˆ.,R�½ “ØîEºšˆºµ½eå�bEH"æ¾,�¨ˆ$†¾LI'‰Þ5°Éêþ¯ô€2wîÜk—9¿âË(äœÎtÓ"àÈÄ�}K@/ ±ù™ŸÔ§_­«.”Z ‡äÅ)Js@ 8C•1åPF”Ø`.çZÓô¼­‚M,¸ƒÕäœ{ž�b ù a‘b{¨ Ih‡®ŽK4_$Ù¯š>›/"åÜT–‰¬"³ŒH‹Z4žßbÜj®‘&K ÍÓÍÀJ? Ty\ï^ý"ý*ÈŒ§ã̸ä�¤]ôüfü—ÜøµâÏñhlû[þò/Âø•‘_H „Oœ{ù(«Ô_D9—µÁD„j:ÐDOÓÍQbåJZ¬›ÂN\s—•E­XlÀ2¦S V!ÊÁ$wMŽm‚,XM4ƒ9T|ãï=骢ĠßÊRQŽYŸâWÛg‘G&½²$D‰])àÑ�Ñ®‚wªx-à ÞDâÚK¡Â=£Í<äͽ«:nmjÕÆ2§ŒÃ~ ÄíZ-¡Ì®Í›8›¡™Ç}ƒìóç¬GŒŸXWiþÆÿ÷½¯¾ss ?Š_X ìœ:õ“×V––¾ˆ".©ÐG3G8öY«Ö}L 4:ðgßžùLùf Õ ‘Öý—Ñ)\2¼D£¸ÅÆ$ÂÍ@ßD» �H2c^�N‚»+ÓZ=z‘ØsPÊGbV´¶H�f›1µBÊY$óTs-còå ;‰­g¸×iÜod%�UG,Йwu|ι€/xÞd#PƒÊ™ÇÔ_·püÊ$S9ED *Ñ­£Q¨™ÖOØ4zÞFeÿDÏ¶Í æø›.qþ¡ÿÊÊêû¿ùݯüT¼QîÚ(Ó'Ͻò«Ÿ¿�ºl: ƒ×;ú\U_Ï›–•E¹Tkô– ÀY¤"™kP5�S R ,€„T-ŠDºeô%é<�âµ�·,JŸ32ž%ÖF·z,‹f¨5ð…¸J){ÀãëZË®–wFWà¿ Ó(^!~ômQ)(r6Ô%Çæ¾DñUˆ,h«{‰Öï)m/I¥ uFÒ¬sŠJS[èMÍ ‹}M­­¡wÇ6NYæ`œÁ˶ê¯9?îüÂòâ_ÿæw¾úBdõ »ùÎŽ_XòžðÈÈàåÞþmO³ðò+l6�õ‘Q)½‹£Åå9XÄk}Vl/^JUdU2Ö 2@æ1¶å�@@j�$D‰4%PI:ãï—XÅ –Wð‰÷+ÞÑ+:÷ê�‘³…2°{Jr‰cüÌ[¢4ÞzX _ONêýH .É’e¨_\�$‰T§‰7ã˜qQüŒ·âÚ&££D�#Œ� îq\ÄGP'~1¾¥/õ™•æ[±(‹XŠyÐ}^�±¼r¤œC–C‚ÆXñVKW…È¢ä•'±HqKw‹ž?�3\‰¥ŒÞjTJ¥ c;û²cUÇU™‘©Ñd—<†¾ +~9DÑe´î̓ÂY(ÝÈZ_¾’�ŠÔÉ£§:nDöxï��J4 'ó”‘'ŸóâËpJRòXD»'I#Èã;Úã‰^Ñø¥)ª}ì…Ý}‹s|/’güKè©Moúaüÿ®meùïþé³<”Ø|î)YJ2ìßû©¿‡zÿ9ÍgŸÞ�’õ‘=&Ôƒq]àCñÕI�»jnRQ–Ø{É¥QµÑ#¤ ‘s_Æ=ÒL½Jµ³Wîß�¤ÀCaë�b…Sè"ÿÏÃÉgpG¦9©Påò%º‚p€¢nrSLûÌH :ËiÍ——3§Ì9E¢ó»É½"4¯]<í,³lêŠÀ¤]ƒÅT½Ý£œ /ú¼FÃ'àÿFçûœq$s‰!:Kð¦¾æ´�/øòNÿÄõaû�‡Èô)2jî(ó×üÍg¾öÿD1?R·�Ô ¨™¡á‹olèÞú]>¾yOv©tÔóë+Cz]R A…�� ¦ì‘yV$â¤âIÕ¤È9¢J´N]¦ŠÅ›J9"ó`îËâ@JÙ WÈ<§u`º–IeÍã[O�GvŸÈª`-¯ì!ž"­ÑY|A‹sXÂØq`À«5ZLÏhPdi"d||Ìa0%›ÈÈãRÉ#ð¢�ñpnïŒ>ñ�Á ô3¶s΃B�YjÈ8ˆ!�° ÷9½·ƒ�=íý½a~j*Œ_¹NïO§D�¯ïøQ/_¬[\úò7ŸýÚŸG?r·�l M �^mmÛþõJŸ»©«{˜Þ¾YŠ×‡GçøÙ´ ½ÛNOÑÚ€6É¥!b^pö‹˘rÈ8hó¸9]î˰�{ ×Îèc­ÌÁ©º ¡ É]Þœ"!ªHáélŸ¨J0&:�Ÿó%l ˆ�,¬£¹”@-½ÀžZºGFvKQxÜÈÁžT$2L1mÁÎŒÔ�m Å|;©A8Îi¢x#ÉwÈøå ç‘òFHuÏ Ÿçùûí·Ì0_†?Ë÷ •ªæú�Mràë?[¨TþÁSßýà >²Îõô‘/ì®»žx€ï¦ÿ3*Ùoj…AÛÄc½ZÜÌsæ™LóÍ=ÝU ^v1‹YN3�1/‡R ,€ª�k«F6ȉsŸ�<œCóJ§&xòUr€¼+n?ó1î÷^Å3¸˜ÈÍÈå0p‚ˆëø”¹ºÇœ^”Ñ6EǬ@^%Ò%,’WÑ2äÃY: ëÕš‹ƒ£Ž ètE¼â�%âS-¨,r1] áü ëøè5å¡5€Í|©§•3ûôxoafÚVøøð‰>�JŇzù ¿òÔÓ_}-±ø(ß“ê>Ê2e«ßwç§¿ÄâàÿFe¼O¦áëœBÌ�«­­ÃÖ AS…9>©ED3rZ\Mmæ�H¨’ËérŸ”‚©Ê&­j ©•¢Y SÜT^~€Ø *áB# ©�Óð]”†ÌñLâE\)]'w£Ì-Ä 6À}’ÍîéQXŒ/ÖIx§K±O£2:a?ƒ0Hê^h’h)–P9LiØÌ+2'>èÚâd:SjE¼ÇS}‘žÌ°YÍoá3l­��4ua~ó/ö¯ lZ‡â�–£$ó6vO]_Êç�ƒËTóq6ÉÈH;yÃîwy±ä¢”îÜF†>©ÅÂ^¸Ðè@'iº ŸŽ'O‡‘*ã*ÀÜá/#ÂAk"2ªœ"YX±‰e 1®‚Æê J¢e‚EdjŠ.‚ó‰l#×<ªÇ]½Î”ÏÒ6r CídC¹æ/öõ¦ÃŒ¶ 0gÄp̘㔘™ ñÍ.BBW¤Nsò",…Š €èLJ Ÿ‹XfxϹ¡¹¨þp¤}¨t´†Îç×\~‘#ºgùžá<ëдvªÚ+íв•÷·þ›¦•™¯|ãÙoŒ)ý�“³|œ.ʺsç_ém­Ôý-jÆß§"> OO D×À‰+j š›[i ø¬5•\#==Pc°ÈwíÔ@ÈžÒ@¹È?WNî3|)˜ªaŠ-]²Ê „@)Z"Ïîð‰vˈÝc¼ ØéŠég‘Œ«ã%„‚Ž[«pi�,'/Œ*Ôûc ¢ËRLÆœGˆ©(=ðœ¿gÂ.�Kålt´`�«HÐ �Œ98ÜØÆèº™7ÉfÑád@Ô`ÀüÔ£ëTžFöšh%_?}–K´ZÌ›caOßçãˆ.¥hq²�¦®¬¦òü‡ÙÆÙÿø½ï}cØ>†SËÇPî’È»w?ÙÒZYú FÿˆÏÓ:wXQÛãC'U‹­£–+¶~š2hø&Ã×èA ˆТÛnµ Þ0”’еËaª «*0ÕôX EdtV¿ª˜ÐÌ-ÕâDlu?¥›–$DA†2OãÇÅ“u\.>øax¢pÈn4&{A"ÉÇ—�(RÞœE&¯ÅfNdF«P’^éà·øøÕ«›¾4'ì‰Ç»Ò÷¯'a¯¹ˆÆSñ€E'®6ážR22…ÍØÉ%@m`£ÇsÚ•WÇç„ÕhϾ>lºÀ‡Mæøø* {¶�_‷OŒÃƒÎb-J|7M• É*‡Õž¤*ŠÕ(X%PôdÁb*©öRE«n„ÔÏñ‘]F%úBb%/° ã (X§È„óžØc¸©d#mEQ½×=^Í›BÆÊ±Fa»ÅC| pÑt'¯7®Î(É­JÛ£F(LJ"3äH,P f¼ èâfy„ŸI†~÷ˆ–KiÉêÑe¤qHFæiô:)«ôuöŠöã_lX®\l©¿ÚÝ=;ôqzt—r¼~_×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬k`]ëX×ÀºÖ5°®�u ¬kà—Sÿ?s2>¶°¬IEND®B`‚heldercorreia-speedcrunch-e7ca37f/src/resources/speedcrunch.qrc000066400000000000000000000044101526573132500251470ustar00rootroot00000000000000 speedcrunch.png color-schemes/Terminal.json color-schemes/Tomorrow.json color-schemes/Tomorrow Night.json color-schemes/Tomorrow Night Eighties.json color-schemes/Tomorrow Night Blue.json color-schemes/Tomorrow Night Bright.json color-schemes/Solarized Dark.json color-schemes/Solarized Light.json color-schemes/Standard.json color-schemes/Sublime.json color-schemes/Breeze.json color-schemes/Breeze Dark.json color-schemes/Black on White.json color-schemes/White on Black.json color-schemes/Nord Dark.json color-schemes/Nord Light.json color-schemes/Dracula.json color-schemes/Catppuccin Latte.json color-schemes/Catppuccin Macchiato.json color-schemes/One Dark.json color-schemes/Monokai.json color-schemes/GitHub Dark.json color-schemes/GitHub Light.json color-schemes/Gruvbox Dark.json color-schemes/Gruvbox Light.json color-schemes/Tokyo Day.json color-schemes/Tokyo Night.json color-schemes/Rose Pine Moon.json color-schemes/Rose Pine Dawn.json color-schemes/Carbonfox.json color-schemes/Dawnfox.json color-schemes/Dayfox.json color-schemes/Duskfox.json color-schemes/Nightfox.json color-schemes/Nordfox.json color-schemes/Terafox.json color-schemes/Sonokai Default.json color-schemes/Sonokai Atlantis.json color-schemes/Sonokai Andromeda.json color-schemes/Sonokai Shusia.json color-schemes/Sonokai Maia.json color-schemes/Sonokai Espresso.json heldercorreia-speedcrunch-e7ca37f/src/resources/speedcrunch.rc.in000066400000000000000000000014041526573132500253730ustar00rootroot00000000000000# if defined(UNDER_CE) # include # else # include # endif SPEEDCRUNCH_ICON ICON DISCARDABLE "@CMAKE_CURRENT_SOURCE_DIR@/resources/speedcrunch.ico" VS_VERSION_INFO VERSIONINFO FILEVERSION @speedcrunch_VERSION_RC@ PRODUCTVERSION @speedcrunch_VERSION_RC@ FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif FILEOS VOS__WINDOWS32 FILETYPE VFT_APP FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" BEGIN VALUE "CompanyName", "SpeedCrunch developers\0" VALUE "FileVersion", "@speedcrunch_VERSION@\0" VALUE "ProductVersion", "@speedcrunch_VERSION@\0" VALUE "LegalCopyright", "Copyright 2004-2026 SpeedCrunch developers\0" END END END /* End of Version info */ heldercorreia-speedcrunch-e7ca37f/src/tests/000077500000000000000000000000001526573132500212665ustar00rootroot00000000000000heldercorreia-speedcrunch-e7ca37f/src/tests/README.md000066400000000000000000000075341526573132500225560ustar00rootroot00000000000000# UI tests Build the tests with CMake: ```sh cmake -S src -B src/build -DBUILD_TESTING=ON cmake --build src/build --parallel ``` The tests that used to live together in `testdisplayui.cpp` now have separate executables, grouped by component: | Executable | Coverage | | --- | --- | | `testdisplayui` | Result display, calculation copying and formatting | | `testeditorappearanceui` | Editor and display styles, geometry and popups | | `testkeypadui` | Keypad input, appearance and zoom | | `testbitfieldui` | Bitfield colors and system appearance | | `testthemesui` | Color schemes, theme previews and generated surfaces | | `testmenusui` | Menus, context menus and dropdown appearance | | `testdockappearanceui` | Dock appearance, tabs, headers and header buttons | | `testdocklayoutui` | Dock layout, spacing, scrolling and Formula Book | | `testfocusui` | Focus, active panes, clipboard routing and tooltips | | `testsettingsui` | Settings, dialogs, shared fonts and manual formatting | | `teststatusbarui` | Status bar appearance, controls and persistence | | `testsessionsui` | Session tabs, layout, import, export and shortcuts | | `testprivatesessionsui` | Private sessions and startup restoration | All 15 UI suites share one label, `ui`. This includes the component suites above and the existing editor and dock widget suites. Run them in parallel: ```sh ctest --test-dir src/build -L ui --parallel --output-on-failure ``` With CTest 3.29 or newer, `--parallel` without a number normally chooses the worker limit from the machine's processor count, with a minimum of two. When running under a build job server, it uses the available job tokens instead. Older CTest versions need an explicit number. A number such as `--parallel 6` limits how many tests can run at once. It does not require six CPU cores. See the [CTest parallel option](https://cmake.org/cmake/help/latest/manual/ctest.1.html#cmdoption-ctest-j) for details. The build command's `--parallel` option uses the native build tool's default when no number is given. CTest's label summary adds up the test durations for this group. Parallel tests overlap, so use `Total Test time (real)` to compare elapsed runtime. `testdisplayui` now covers only the result display. To run exactly its former coverage, select UI tests and exclude the two existing widget suites: ```sh ctest --test-dir src/build -L ui -E '^(testeditorui|testdocksui)$' --parallel --output-on-failure ``` To run the entire test set, omit the label. To work on one component, select its executable and optionally pass a Qt Test function name: ```sh ctest --test-dir src/build -R '^testkeypadui$' --output-on-failure src/build/testkeypadui keypad_power_button_uses_exponent_label_but_inserts_caret ``` Each executable uses `UiTestFixture` to create its own temporary settings, sessions and cache directories. Tests use Qt's offscreen platform unless `QT_QPA_PLATFORM` is already set. This lets separate processes run without sharing application storage or desktop focus. For native platform checks, run one suite at a time so desktop focus and the clipboard cannot interfere: ```sh QT_QPA_PLATFORM=cocoa ctest --test-dir src/build -L ui --parallel 1 --output-on-failure ``` Use the appropriate Qt platform name on other systems. ## Adding tests Put new tests in the suite for the component they exercise. Keep a test and its `_data` provider together. Cross-window checks belong with the feature they cover, such as keypad zoom or status bar persistence. `mainwindowtesthelpers.h` and `mainwindowtesthelpers.cpp` contain shared window, menu, rendering and session helpers. CMake compiles the common application sources and resources once in the `mainwindowuitest` object library, then links them into each executable. The object library carries the `SPEEDCRUNCH_UI_TEST` definition to each suite. When adding a component suite, register it in CMake's `mainwindow_ui_tests` list. heldercorreia-speedcrunch-e7ca37f/src/tests/editorgeometrytesthelpers.h000066400000000000000000000024201526573132500267620ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef SPEEDCRUNCH_EDITORGEOMETRYTESTHELPERS_H #define SPEEDCRUNCH_EDITORGEOMETRYTESTHELPERS_H #include #include #include #include namespace EditorGeometryTestHelpers { inline int visibleTextHeight(const QPlainTextEdit& editor, int maximumLines = 5) { QTextCursor first(editor.document()); QTextCursor last(first); int remaining = maximumLines; for (QTextBlock block = editor.document()->begin(); block.isValid(); block = block.next()) { editor.document()->documentLayout()->blockBoundingRect(block); const QTextLayout* layout = block.layout(); const int count = qMin(remaining, layout->lineCount()); if (count > 0) last.setPosition(block.position() + layout->lineAt(count - 1).textStart()); remaining -= count; if (remaining == 0) break; } // Both rectangles have the same scroll offset, even after the editor // scrolls past its first five lines. Measure the rendered cursor span. return editor.cursorRect(last).bottom() - editor.cursorRect(first).top() + 1; } } // namespace EditorGeometryTestHelpers #endif heldercorreia-speedcrunch-e7ca37f/src/tests/mainwindowtesthelpers.cpp000066400000000000000000000413601526573132500264350ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" namespace MainWindowTestHelpers { QJsonObject themeJson(QJsonObject colors) { colors.insert(QStringLiteral("$schema"), QString::fromLatin1(ColorScheme::SchemaDraft)); colors.insert(QStringLiteral("$id"), QString::fromLatin1(ColorScheme::SchemaId)); return colors; } QString themeJsonString(QJsonObject colors) { return QString::fromUtf8(QJsonDocument(themeJson(colors)).toJson(QJsonDocument::Compact)); } QJsonObject sessionJson(const QString& name) { QJsonObject historyEntry; HistoryEntry(QStringLiteral("6*7"), Quantity(42)).serialize(historyEntry); QJsonArray history; history.append(historyEntry); QJsonObject values; values.insert(QLatin1String(SessionJsonKeys::Schema), QLatin1String(SessionJsonKeys::SchemaDialect)); values.insert(QLatin1String(SessionJsonKeys::Id), QLatin1String(SessionJsonKeys::SchemaId)); values.insert(QLatin1String(SessionJsonKeys::Session), name); values.insert(QLatin1String(SessionJsonKeys::Limit), 1000); values.insert(QLatin1String(SessionJsonKeys::History), history); values.insert(QLatin1String(SessionJsonKeys::Variables), QJsonArray()); values.insert(QLatin1String(SessionJsonKeys::Functions), QJsonArray()); values.insert(QLatin1String(SessionJsonKeys::Units), QJsonArray()); values.insert(QLatin1String(SessionJsonKeys::Globals), QJsonArray()); return values; } void writeFile(const QString& filePath, const QByteArray& data) { QFile file(filePath); QVERIFY(file.open(QIODevice::WriteOnly)); QCOMPARE(file.write(data), qint64(data.size())); } QJsonObject startupSessionWindow(const QString& name, const QString& id) { const QJsonObject tab { { QStringLiteral("name"), name }, { QStringLiteral("editor"), QJsonObject { { QStringLiteral("text"), QStringLiteral("saved draft") } } } }; return QJsonObject { { QStringLiteral("id"), id }, { QStringLiteral("root"), QJsonObject { { QStringLiteral("type"), QStringLiteral("tabs") }, { QStringLiteral("active"), name }, { QStringLiteral("tabs"), QJsonArray { tab } } } } }; } QWidget* paneWidgetForDisplay(ResultDisplay* display) { QWidget* widget = display; while (widget != nullptr && !qobject_cast(widget->parentWidget())) widget = widget->parentWidget(); return widget; } void appendPaneScrollValues(const QJsonObject& node, QList* values) { const QString type = node.value(QStringLiteral("type")).toString(); if (type == QLatin1String("pane")) { const QJsonArray tabs = node.value(QStringLiteral("tabs")).toArray(); for (const QJsonValue& tabValue : tabs) { const QJsonObject scroll = tabValue.toObject().value(QStringLiteral("scroll")).toObject(); if (scroll.contains(QStringLiteral("value"))) values->append(scroll.value(QStringLiteral("value")).toInt(-1)); } return; } if (type != QLatin1String("split")) return; const QJsonArray children = node.value(QStringLiteral("children")).toArray(); for (const QJsonValue& childValue : children) { if (childValue.isObject()) appendPaneScrollValues(childValue.toObject(), values); } } void appendPaneEditorTexts(const QJsonObject& node, QStringList* texts) { const QString type = node.value(QStringLiteral("type")).toString(); if (type == QLatin1String("pane")) { const QString active = node.value(QStringLiteral("active")).toString(); const QJsonArray tabs = node.value(QStringLiteral("tabs")).toArray(); for (const QJsonValue& tabValue : tabs) { const QJsonObject tab = tabValue.toObject(); if (tab.value(QStringLiteral("name")).toString() != active) continue; const QJsonObject editor = tab.value(QStringLiteral("editor")).toObject(); if (editor.contains(QStringLiteral("text"))) texts->append(editor.value(QStringLiteral("text")).toString()); } return; } if (type != QLatin1String("split")) return; const QJsonArray children = node.value(QStringLiteral("children")).toArray(); for (const QJsonValue& childValue : children) { if (childValue.isObject()) appendPaneEditorTexts(childValue.toObject(), texts); } } bool menuContainsActionText(const QMenu* menu, const QString& text) { for (QAction* action : menu->actions()) { if (action->text() == text) return true; if (action->menu() != nullptr && menuContainsActionText(action->menu(), text)) return true; } return false; } QMenu* menuWithTitle(const QMenuBar* menuBar, const QString& title) { for (QAction* action : menuBar->actions()) { QMenu* menu = action->menu(); if (menu != nullptr && menu->title() == title) return menu; } return nullptr; } QAction* directMenuActionWithText(const QMenu* menu, const QString& text) { for (QAction* action : menu->actions()) { if (action->text() == text) return action; } return nullptr; } QMenu* directSubmenuWithTitle(const QMenu* menu, const QString& title) { QAction* action = directMenuActionWithText(menu, title); return action != nullptr ? action->menu() : nullptr; } QList topLevelMainWindows() { QList windows; for (QWidget* widget : QApplication::topLevelWidgets()) { if (MainWindow* window = qobject_cast(widget)) windows.append(window); } return windows; } bool rejectActiveDialogWithTitle(const QString& title) { QDialog* dialog = qobject_cast(QApplication::activeModalWidget()); if (dialog == nullptr) return false; const bool matches = dialog->windowTitle() == title; dialog->reject(); return matches; } bool contextMenuContainsMainMenu(MenuTestResultDisplay* display) { QMenu* menu = display->createContextMenu(display->rect().center()); const bool mainMenuSeen = menuContainsActionText(menu, QStringLiteral("Main Menu")); delete menu; return mainMenuSeen; } bool editorHasPrimaryOutline(const Editor* editor, const QColor& primary) { return editor != nullptr && editor->styleSheet().contains( QStringLiteral("border: %1px solid %2") .arg(UiConfig::OutlineStrokeWidth) .arg(primary.name())); } bool anyEditorHasPrimaryOutline(const QList& editors, const QColor& primary) { for (const Editor* editor : editors) { if (editorHasPrimaryOutline(editor, primary)) return true; } return false; } bool colorsAreClose(const QColor& actual, const QColor& expected, int tolerance) { return qAbs(actual.red() - expected.red()) <= tolerance && qAbs(actual.green() - expected.green()) <= tolerance && qAbs(actual.blue() - expected.blue()) <= tolerance; } QRect imageRectForWidgetRect(const QImage& image, const QRect& rect) { const qreal scale = image.devicePixelRatio(); return QRect(qRound(rect.x() * scale), qRound(rect.y() * scale), qRound(rect.width() * scale), qRound(rect.height() * scale)); } QPoint firstPixelMatchingColor(const QImage& image, const QRect& rect, const QColor& color, int tolerance) { const QRect bounded = rect.intersected(image.rect()); for (int y = bounded.top(); y <= bounded.bottom(); ++y) { for (int x = bounded.left(); x <= bounded.right(); ++x) { if (colorsAreClose(image.pixelColor(x, y), color, tolerance)) return QPoint(x, y); } } return QPoint(-1, -1); } QPoint firstPixelMatchingColorBlend(const QImage& image, const QRect& rect, const QColor& foreground, const QColor& background, int tolerance) { const int redDelta = foreground.red() - background.red(); const int greenDelta = foreground.green() - background.green(); const int blueDelta = foreground.blue() - background.blue(); const int squaredDistance = redDelta * redDelta + greenDelta * greenDelta + blueDelta * blueDelta; if (squaredDistance == 0) return QPoint(-1, -1); const QRect bounded = rect.intersected(image.rect()); for (int y = bounded.top(); y <= bounded.bottom(); ++y) { for (int x = bounded.left(); x <= bounded.right(); ++x) { const QColor pixel = image.pixelColor(x, y); // Antialiased glyphs can contain only partial foreground coverage. // Check the blend's hue as well as its contrast with the background. const qreal coverage = qreal((pixel.red() - background.red()) * redDelta + (pixel.green() - background.green()) * greenDelta + (pixel.blue() - background.blue()) * blueDelta) / squaredDistance; if (coverage < 0.25 || coverage > 1.0) continue; const QColor blended(qRound(background.red() + coverage * redDelta), qRound(background.green() + coverage * greenDelta), qRound(background.blue() + coverage * blueDelta)); if (colorsAreClose(pixel, blended, tolerance)) return QPoint(x, y); } } return QPoint(-1, -1); } QPoint firstPixelDistinctFromColor(const QImage& image, const QRect& rect, const QColor& color, int minimumChannelDistance) { const QRect bounded = rect.intersected(image.rect()); for (int y = bounded.top(); y <= bounded.bottom(); ++y) { for (int x = bounded.left(); x <= bounded.right(); ++x) { const QColor pixel = image.pixelColor(x, y); const int distance = qMax(qAbs(pixel.red() - color.red()), qMax(qAbs(pixel.green() - color.green()), qAbs(pixel.blue() - color.blue()))); if (distance >= minimumChannelDistance) return QPoint(x, y); } } return QPoint(-1, -1); } QPushButton* keypadButtonWithText(Keypad* keypad, const QString& text) { if (keypad == nullptr) return nullptr; for (QPushButton* button : keypad->findChildren()) { if (button->text() == text) return button; } return nullptr; } QAction* keypadModeAction(MainWindow* window, Settings::KeypadMode mode) { if (window == nullptr) return nullptr; for (QAction* action : window->findChildren()) { if (action->isCheckable() && action->data().isValid() && action->data().toInt() == static_cast(mode)) { return action; } } return nullptr; } QColor keypadPrimaryStateBackgroundForTest(const QColor& primary, const QColor& stateBackground, const QColor& normalBackground) { Oklch primaryOklch = qColorToOklch(primary); const Oklch stateOklch = qColorToOklch(stateBackground); const Oklch normalOklch = qColorToOklch(normalBackground); const double offset = stateOklch.l - normalOklch.l; if (qAbs(offset) < 1e-9) return primary; primaryOklch.l = qBound(0.0, primaryOklch.l + offset, 1.0); return oklchToValidSrgbQColor(primaryOklch); } QColor keypadPrimaryHueFillForTest(const QColor& primary, const QColor& stateBackground, const QColor& normalBackground, int primaryPercent) { const double primaryRatio = double(qBound(0, primaryPercent, 100)) / 100.0; if (primaryRatio <= 0.0) return stateBackground; const QColor primaryStateBackground = keypadPrimaryStateBackgroundForTest(primary, stateBackground, normalBackground); if (primaryRatio >= 1.0) return primaryStateBackground; const Oklch stateOklch = qColorToOklch(stateBackground); const Oklch primaryStateOklch = qColorToOklch(primaryStateBackground); return oklchToValidSrgbQColor(Oklch { stateOklch.l + (primaryStateOklch.l - stateOklch.l) * primaryRatio, stateOklch.c + (primaryStateOklch.c - stateOklch.c) * primaryRatio, primaryStateOklch.h, stateOklch.alpha }); } QImage dockSeparatorPrimitiveImage(QWidget* widget, QStyle::State state, const QRect& separatorRect, const QSize& imageSize) { QImage image(imageSize, QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QStyleOption option; option.rect = separatorRect; option.state = state; option.palette = widget->palette(); QPainter painter(&image); QApplication::style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &option, &painter, widget); return image; } QImage dockSeparatorPrimitiveImage(QWidget* widget, QStyle::State state, const QSize& size) { return dockSeparatorPrimitiveImage(widget, state, QRect(QPoint(0, 0), size), size); } QColor dockSeparatorPrimitiveColor(QWidget* widget, QStyle::State state) { const QImage image = dockSeparatorPrimitiveImage(widget, state); return image.pixelColor(image.rect().center()); } QRect sessionTabPillRect(const QTabBar* tabBar) { return tabBar->tabRect(tabBar->currentIndex()).adjusted(2, 3, -2, 0); } QColor selectedSessionTabFillColor(QTabBar* tabBar) { const QRect pill = sessionTabPillRect(tabBar); const QImage image = tabBar->grab().toImage(); return image.pixelColor(pill.left() + 6, pill.center().y()); } bool selectedSessionTabHasBottomIndicator(QTabBar* tabBar, const QColor& color) { const QRect pill = sessionTabPillRect(tabBar); const QImage image = tabBar->grab().toImage(); const int firstY = qMax(pill.top(), pill.bottom() - UiConfig::ActiveSessionTabIndicatorStrokeWidth); for (int y = firstY; y <= pill.bottom(); ++y) { for (int x = pill.left() + 4; x <= pill.right() - 4; ++x) { if (image.rect().contains(x, y) && colorsAreClose(image.pixelColor(x, y), color)) return true; } } return false; } Editor* editorForDisplay(ResultDisplay* display) { QWidget* page = display != nullptr ? display->parentWidget() : nullptr; return page ? page->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; } QTabBar* tabBarForDisplay(ResultDisplay* display) { QWidget* pane = paneWidgetForDisplay(display); return pane ? pane->findChild() : nullptr; } QString visibleResultPreviewText(const MainWindow& window) { for (QLabel* label : window.findChildren()) { if (!label->isVisible()) continue; const QString text = label->text(); if (text.contains(QStringLiteral("Current result:")) || text.contains(QStringLiteral("Selection result:"))) { return text; } } return QString(); } void sendTabDragMouseEvent(QTabBar* tabBar, QEvent::Type type, const QPoint& pos, Qt::MouseButton button, Qt::MouseButtons buttons) { QMouseEvent event(type, QPointF(pos), QPointF(tabBar->mapToGlobal(pos)), button, buttons, Qt::NoModifier); QCoreApplication::sendEvent(tabBar, &event); } QKeyCombination restoreClosedTabShortcut() { return QKeyCombination(Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_T); } QKeyCombination nextSessionTabShortcut() { #if defined(Q_OS_MACOS) return QKeyCombination(Qt::ControlModifier | Qt::AltModifier, Qt::Key_Right); #else return QKeyCombination(Qt::ControlModifier, Qt::Key_PageDown); #endif } QKeyCombination previousSessionTabShortcut() { #if defined(Q_OS_MACOS) return QKeyCombination(Qt::ControlModifier | Qt::AltModifier, Qt::Key_Left); #else return QKeyCombination(Qt::ControlModifier, Qt::Key_PageUp); #endif } bool focusIsWithin(QWidget* target) { QWidget* focused = QApplication::focusWidget(); if (target == nullptr || focused == nullptr) return false; if (focused == target || target->isAncestorOf(focused)) return true; if (QAbstractItemView* view = qobject_cast(target)) { QWidget* viewport = view->viewport(); return focused == viewport || (viewport != nullptr && viewport->isAncestorOf(focused)); } return false; } } // namespace MainWindowTestHelpers heldercorreia-speedcrunch-e7ca37f/src/tests/mainwindowtesthelpers.h000066400000000000000000000352151526573132500261040ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #ifndef SPEEDCRUNCH_MAINWINDOWTESTHELPERS_H #define SPEEDCRUNCH_MAINWINDOWTESTHELPERS_H #include "core/colorscheme.h" #include "core/evaluator.h" #include "core/session.h" #include "core/sessionjsonkeys.h" #include "core/settings.h" #include "core/userdefinitions.h" #include "gui/aboutbox.h" #include "gui/bitfieldwidget.h" #include "gui/bookdock.h" #include "gui/constantswidget.h" #include "gui/dockliststyle.h" #include "gui/editor.h" #include "gui/syntaxhighlighter.h" #include "gui/functionswidget.h" #include "gui/gtkmenupalette.h" #include "gui/historywidget.h" #include "gui/keypad.h" #include "gui/mainwindow.h" #include "gui/menustyleutils.h" #include "gui/manualwindow.h" #include "gui/notationandprecisiondialog.h" #include "gui/oklchutils.h" #include "gui/resultdisplay.h" #include "gui/themedlineedit.h" #include "gui/uiconfig.h" #include "gui/userfunctionlistwidget.h" #include "gui/userunitlistwidget.h" #include "gui/variablelistwidget.h" #include "math/quantity.h" #include "core/functions.h" #include "uitestfixture.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace MainWindowTestHelpers { class TransparentMenuBarTestStyle : public QProxyStyle { public: TransparentMenuBarTestStyle() : QProxyStyle(QStyleFactory::create(QStringLiteral("Fusion"))) {} void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override { if (element != CE_MenuBarEmptyArea) QProxyStyle::drawControl(element, option, painter, widget); } void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = nullptr) const override { if (element != PE_PanelMenuBar) QProxyStyle::drawPrimitive(element, option, painter, widget); } }; class MenuBarPaletteTestStyle : public QProxyStyle { public: explicit MenuBarPaletteTestStyle(const QPalette& platformPalette) : QProxyStyle(QStyleFactory::create(QStringLiteral("Fusion"))) , m_platformPalette(platformPalette) {} void polish(QWidget* widget) override { QProxyStyle::polish(widget); // Breeze gives menu bars their own desktop header palette. if (qobject_cast(widget)) widget->setPalette(m_platformPalette); } private: QPalette m_platformPalette; }; class DockHeaderButtonTestStyle : public QProxyStyle { public: explicit DockHeaderButtonTestStyle(bool framed) : QProxyStyle(QStyleFactory::create(QStringLiteral("Fusion"))) , m_framed(framed) {} int pixelMetric(PixelMetric metric, const QStyleOption* option = nullptr, const QWidget* widget = nullptr) const override { if (metric == PM_SmallIconSize) return 16; return QProxyStyle::pixelMetric(metric, option, widget); } int styleHint(StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override { if (hint == SH_DockWidget_ButtonsHaveFrame) return m_framed; return QProxyStyle::styleHint(hint, option, widget, returnData); } private: bool m_framed; }; QJsonObject themeJson(QJsonObject colors); QString themeJsonString(QJsonObject colors); QJsonObject sessionJson(const QString& name); void writeFile(const QString& filePath, const QByteArray& data); QJsonObject startupSessionWindow(const QString& name, const QString& id); QWidget* paneWidgetForDisplay(ResultDisplay* display); void appendPaneScrollValues(const QJsonObject& node, QList* values); void appendPaneEditorTexts(const QJsonObject& node, QStringList* texts); bool menuContainsActionText(const QMenu* menu, const QString& text); QMenu* menuWithTitle(const QMenuBar* menuBar, const QString& title); QAction* directMenuActionWithText(const QMenu* menu, const QString& text); QMenu* directSubmenuWithTitle(const QMenu* menu, const QString& title); QList topLevelMainWindows(); bool rejectActiveDialogWithTitle(const QString& title); class MenuTestResultDisplay : public ResultDisplay { public: explicit MenuTestResultDisplay(QWidget* parent = nullptr) : ResultDisplay(parent) { } using ResultDisplay::createContextMenu; }; class BadgeTestResultDisplay : public ResultDisplay { public: explicit BadgeTestResultDisplay(QWidget* parent = nullptr) : ResultDisplay(parent) { } QRect copyBadgeRect(int historyIndex) const { return copyGlyphBadgeRectForHistoryIndex(historyIndex); } QRect editBadgeRect(int historyIndex) const { return editGlyphBadgeRectForHistoryIndex(historyIndex); } QRect settingsBadgeRect(int historyIndex) const { return settingsGlyphBadgeRectForHistoryIndex(historyIndex); } QRect removeBadgeRect(int historyIndex) const { return removeGlyphBadgeRectForHistoryIndex(historyIndex); } }; bool contextMenuContainsMainMenu(MenuTestResultDisplay* display); bool editorHasPrimaryOutline(const Editor* editor, const QColor& primary); bool anyEditorHasPrimaryOutline(const QList& editors, const QColor& primary); bool colorsAreClose(const QColor& actual, const QColor& expected, int tolerance = 2); QRect imageRectForWidgetRect(const QImage& image, const QRect& rect); QPoint firstPixelMatchingColor(const QImage& image, const QRect& rect, const QColor& color, int tolerance); QPoint firstPixelMatchingColorBlend(const QImage& image, const QRect& rect, const QColor& foreground, const QColor& background, int tolerance); QPoint firstPixelDistinctFromColor(const QImage& image, const QRect& rect, const QColor& color, int minimumChannelDistance); class FunctionsTestTranslator : public QTranslator { public: QString translate(const char* context, const char* sourceText, const char* disambiguation = nullptr, int n = -1) const override { Q_UNUSED(disambiguation); Q_UNUSED(n); if (qstrcmp(context, "FunctionsWidget") == 0 && qstrcmp(sourceText, "Domain") == 0) { return QStringLiteral("Translated Domain"); } return QString(); } }; QPushButton* keypadButtonWithText(Keypad* keypad, const QString& text); QAction* keypadModeAction(MainWindow* window, Settings::KeypadMode mode); QColor keypadPrimaryStateBackgroundForTest(const QColor& primary, const QColor& stateBackground, const QColor& normalBackground); QColor keypadPrimaryHueFillForTest(const QColor& primary, const QColor& stateBackground, const QColor& normalBackground, int primaryPercent); QImage dockSeparatorPrimitiveImage(QWidget* widget, QStyle::State state, const QRect& separatorRect, const QSize& imageSize); QImage dockSeparatorPrimitiveImage(QWidget* widget, QStyle::State state, const QSize& size = QSize(32, 8)); QColor dockSeparatorPrimitiveColor(QWidget* widget, QStyle::State state); QRect sessionTabPillRect(const QTabBar* tabBar); QColor selectedSessionTabFillColor(QTabBar* tabBar); bool selectedSessionTabHasBottomIndicator(QTabBar* tabBar, const QColor& color); Editor* editorForDisplay(ResultDisplay* display); QTabBar* tabBarForDisplay(ResultDisplay* display); QString visibleResultPreviewText(const MainWindow& window); struct MainWindowStateGuard { Settings* settings = Settings::instance(); QString oldColorScheme = settings->colorScheme; QString oldCustomColorSchemeJson = settings->customColorSchemeJson; Settings::MenuAppearance oldMenuAppearance = settings->menuAppearance; Settings::DockAppearance oldDockAppearance = settings->dockAppearance; Settings::StatusBarAppearance oldStatusBarAppearance = settings->statusBarAppearance; QString oldSessionLayoutJson = settings->sessionLayoutJson; QString oldConstantsDockDomain = settings->constantsDockDomain; QString oldConstantsDockSubdomain = settings->constantsDockSubdomain; QString oldConstantsDockSearchText = settings->constantsDockSearchText; QByteArray oldWindowState = settings->windowState; QByteArray oldWindowGeometry = settings->windowGeometry; bool oldConstantsDockVisible = settings->constantsDockVisible; bool oldFunctionsDockVisible = settings->functionsDockVisible; bool oldHistoryDockVisible = settings->historyDockVisible; bool oldKeypadVisible = settings->keypadVisible; bool oldFormulaBookDockVisible = settings->formulaBookDockVisible; bool oldVariablesDockVisible = settings->variablesDockVisible; bool oldUserFunctionsDockVisible = settings->userFunctionsDockVisible; bool oldUserUnitsDockVisible = settings->userUnitsDockVisible; bool oldBitfieldVisible = settings->bitfieldVisible; Settings::KeypadMode oldKeypadMode = settings->keypadMode; int oldKeypadZoomPercent = settings->keypadZoomPercent; bool oldWindowPositionSave = settings->windowPositionSave; bool oldStatusBarVisible = settings->statusBarVisible; char oldAngleUnit = settings->angleUnit; char oldResultFormat = settings->resultFormat; int oldResultPrecision = settings->resultPrecision; bool oldHasNumberFormatStyleSetting = settings->hasNumberFormatStyleSetting; QByteArray oldSkipUpdateCheck = qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); bool hadSkipUpdateCheck = qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); MainWindowStateGuard() { settings->windowPositionSave = false; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); } ~MainWindowStateGuard() { settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; settings->menuAppearance = oldMenuAppearance; settings->dockAppearance = oldDockAppearance; settings->statusBarAppearance = oldStatusBarAppearance; settings->sessionLayoutJson = oldSessionLayoutJson; settings->constantsDockDomain = oldConstantsDockDomain; settings->constantsDockSubdomain = oldConstantsDockSubdomain; settings->constantsDockSearchText = oldConstantsDockSearchText; settings->windowState = oldWindowState; settings->windowGeometry = oldWindowGeometry; settings->constantsDockVisible = oldConstantsDockVisible; settings->functionsDockVisible = oldFunctionsDockVisible; settings->historyDockVisible = oldHistoryDockVisible; settings->keypadVisible = oldKeypadVisible; settings->formulaBookDockVisible = oldFormulaBookDockVisible; settings->variablesDockVisible = oldVariablesDockVisible; settings->userFunctionsDockVisible = oldUserFunctionsDockVisible; settings->userUnitsDockVisible = oldUserUnitsDockVisible; settings->bitfieldVisible = oldBitfieldVisible; settings->keypadMode = oldKeypadMode; settings->keypadZoomPercent = oldKeypadZoomPercent; settings->windowPositionSave = oldWindowPositionSave; settings->statusBarVisible = oldStatusBarVisible; settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } }; struct PrivateSessionStorage { QTemporaryDir directory; QByteArray previousRoot = qgetenv("SPEEDCRUNCH_UI_TEST_STORAGE"); PrivateSessionStorage() { qputenv("SPEEDCRUNCH_UI_TEST_STORAGE", directory.path().toUtf8()); for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) QDir().mkpath(path); UiTestFixture::resetSettings(); } ~PrivateSessionStorage() { qputenv("SPEEDCRUNCH_UI_TEST_STORAGE", previousRoot); } QString path(const QString& name) const { return QDir(Settings::getDataPath()).filePath(QStringLiteral("sessions/%1.json").arg(name)); } }; void sendTabDragMouseEvent(QTabBar* tabBar, QEvent::Type type, const QPoint& pos, Qt::MouseButton button, Qt::MouseButtons buttons); QKeyCombination restoreClosedTabShortcut(); QKeyCombination nextSessionTabShortcut(); QKeyCombination previousSessionTabShortcut(); bool focusIsWithin(QWidget* target); } // namespace MainWindowTestHelpers #endif heldercorreia-speedcrunch-e7ca37f/src/tests/testbitfieldui.cpp000066400000000000000000000472431526573132500250240ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" using namespace MainWindowTestHelpers; class TestBitfieldUi : public QObject { Q_OBJECT private slots: void initTestCase(); void init() { UiTestFixture::resetSettings(); } void bitfield_selected_bit_keeps_primary_fill_while_hovered(); void system_bitfield_keeps_on_and_off_bits_distinct_data(); void system_bitfield_keeps_on_and_off_bits_distinct(); void system_bitfield_paints_background_data(); void system_bitfield_paints_background(); void system_bitfield_background_is_visible_in_window_data(); void system_bitfield_background_is_visible_in_window(); void bitfield_buttons_use_configured_generated_shades(); void repeated_bit_theme_keeps_state_repainting(); }; void TestBitfieldUi::initTestCase() { // Fail before a file-operation test can open an unhandled error dialog. for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) { QVERIFY2(QDir().mkpath(path), qPrintable(QStringLiteral("Cannot create test storage at %1").arg(path))); QTemporaryFile probe(QDir(path).filePath(QStringLiteral("storage-probe-XXXXXX"))); QVERIFY2(probe.open(), qPrintable(QStringLiteral("Cannot write test storage at %1: %2") .arg(path, probe.errorString()))); } } void TestBitfieldUi::bitfield_selected_bit_keeps_primary_fill_while_hovered() { const QColor background(QStringLiteral("#202124")); const QColor foreground(QStringLiteral("#d6d8dc")); const QColor hoverBackground(QStringLiteral("#4a5568")); const QColor hoverForeground(QStringLiteral("#f8fafc")); const QColor primaryBackground(QStringLiteral("#2f80ed")); const QColor primaryForeground(QStringLiteral("#ffffff")); const QColor popupBackground(QStringLiteral("#30384a")); const QColor popupForeground(QStringLiteral("#f4f7ff")); const QColor popupOutline(QStringLiteral("#596274")); BitWidget bit(3); bit.setThemeColors(background, foreground, hoverBackground, hoverForeground, primaryBackground, primaryForeground); bit.setToolTipThemeColors(popupBackground, popupForeground, popupOutline, 8); bit.resize(48, 48); bit.show(); QVERIFY(QTest::qWaitForWindowExposed(&bit)); const QPoint sampledFill(4, 4); QTest::mouseMove(&bit, bit.rect().center()); QTRY_VERIFY(bit.underMouse()); QCOMPARE(bit.toolTip(), QString()); QFrame* summaryPopup = bit.findChild(QStringLiteral("bitSummaryPopup")); QTRY_VERIFY(summaryPopup != nullptr && summaryPopup->isVisible()); QLabel* summaryPopupLabel = summaryPopup->findChild(QStringLiteral("bitSummaryPopupLabel")); QVERIFY(summaryPopupLabel != nullptr); QCOMPARE(summaryPopupLabel->text(), QStringLiteral("23 = 8")); QVERIFY(summaryPopup->styleSheet().contains(popupBackground.name())); QVERIFY(summaryPopup->styleSheet().contains(popupForeground.name())); QVERIFY(summaryPopup->styleSheet().contains(QStringLiteral("border: %1px solid %2") .arg(UiConfig::PopupOutlineStrokeWidth) .arg(popupOutline.name()))); QVERIFY(!summaryPopup->mask().isEmpty()); QTRY_COMPARE(bit.grab().toImage().pixelColor(sampledFill).name(), hoverBackground.name()); bit.setState(true); QTRY_COMPARE(bit.grab().toImage().pixelColor(sampledFill).name(), primaryBackground.name()); } void TestBitfieldUi::system_bitfield_keeps_on_and_off_bits_distinct_data() { QTest::addColumn("dark"); QTest::addColumn("switchFromTheme"); QTest::newRow("dark-system-startup") << true << false; QTest::newRow("light-system-startup") << false << false; QTest::newRow("dark-switch-from-theme") << true << true; QTest::newRow("light-switch-from-theme") << false << true; } void TestBitfieldUi::system_bitfield_keeps_on_and_off_bits_distinct() { QFETCH(bool, dark); QFETCH(bool, switchFromTheme); MainWindowStateGuard guard; const QPalette originalPalette = QApplication::palette(); const auto restorePalette = qScopeGuard([originalPalette]() { QApplication::setPalette(originalPalette); }); const auto systemPalette = [originalPalette](bool dark) { QPalette palette = originalPalette; palette.setColor(QPalette::Window, QColor(dark ? "#202020" : "#eeeeee")); palette.setColor(QPalette::WindowText, QColor(dark ? "#ffffff" : "#000000")); // Some system palettes use the same neutral shade for both roles. palette.setColor(QPalette::Mid, palette.color(QPalette::Window)); palette.setColor(QPalette::Button, QColor(dark ? "#383838" : "#dddddd")); palette.setColor(QPalette::ButtonText, palette.color(QPalette::WindowText)); palette.setColor(QPalette::Highlight, QColor(dark ? "#246fc0" : "#185ca8")); palette.setColor(QPalette::HighlightedText, QColor("#ffffff")); return palette; }; QApplication::setPalette(systemPalette(dark)); guard.settings->dockAppearance = switchFromTheme ? Settings::DockAppearanceSpeedCrunch : Settings::DockAppearanceSystem; guard.settings->bitfieldVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QMenu* appearance = window.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); if (switchFromTheme) appearance->actions().at(0)->trigger(); BitFieldWidget* field = window.findChild(); QVERIFY(field); QDockWidget* dock = window.findChild(QStringLiteral("BitfieldDock")); QVERIFY(dock); dock->setFloating(true); dock->resize(700, 240); dock->move(20, 20); dock->show(); QVERIFY(QTest::qWaitForWindowExposed(dock)); BitWidget* onBit = nullptr; BitWidget* offBit = nullptr; for (BitWidget* bit : field->findChildren()) { if (bit->text() == QStringLiteral("0")) onBit = bit; if (bit->text() == QStringLiteral("1")) offBit = bit; } QVERIFY(onBit); QVERIFY(offBit); field->clear(); onBit->setState(true); offBit->setState(false); const auto fill = [](BitWidget* bit) { const QImage image = bit->grab().toImage(); const int inset = qRound(2 * bit->devicePixelRatioF()); return image.pixelColor(inset, inset).rgba(); }; for (bool useDark : {dark, !dark}) { const QPalette palette = systemPalette(useDark); QApplication::setPalette(palette); QTest::mouseMove(dock->windowHandle(), QPoint(1, 1)); QTRY_COMPARE(fill(onBit), palette.color(QPalette::Highlight).rgba()); QTRY_COMPARE(fill(offBit), palette.color(QPalette::Window).rgba()); QVERIFY(fill(onBit) != fill(offBit)); QCOMPARE(onBit->palette().color(QPalette::WindowText).rgba(), palette.color(QPalette::HighlightedText).rgba()); QTest::mouseMove(dock->windowHandle(), offBit->mapTo(dock, offBit->rect().center())); QTRY_VERIFY(offBit->underMouse()); QTRY_COMPARE(fill(offBit), palette.color(QPalette::Button).rgba()); QVERIFY(fill(onBit) != fill(offBit)); QTest::mouseMove(dock->windowHandle(), onBit->mapTo(dock, onBit->rect().center())); QTRY_VERIFY(onBit->underMouse()); QTRY_COMPARE(fill(onBit), palette.color(QPalette::Highlight).rgba()); QSignalSpy changes(field, &BitFieldWidget::bitsChanged); QTest::mouseClick(onBit, Qt::LeftButton); QVERIFY(!onBit->state()); QTRY_COMPARE(fill(onBit), palette.color(QPalette::Button).rgba()); QCOMPARE(changes.count(), 1); QCOMPARE(changes.takeFirst().at(0).toString(), QStringLiteral("0b0")); QTest::mouseClick(onBit, Qt::LeftButton); QVERIFY(onBit->state()); QTRY_COMPARE(fill(onBit), palette.color(QPalette::Highlight).rgba()); QCOMPARE(changes.count(), 1); QCOMPARE(changes.takeFirst().at(0).toString(), QStringLiteral("0b1")); } } void TestBitfieldUi::system_bitfield_paints_background_data() { QTest::addColumn("dark"); QTest::addColumn("floating"); QTest::addColumn("switchFromTheme"); for (bool dark : {false, true}) { for (bool floating : {false, true}) { for (bool switchFromTheme : {false, true}) { const QString name = QStringLiteral("%1-%2-%3") .arg(dark ? "dark" : "light", floating ? "floating" : "attached", switchFromTheme ? "switch-from-theme" : "system-startup"); QTest::newRow(qPrintable(name)) << dark << floating << switchFromTheme; } } } } void TestBitfieldUi::system_bitfield_paints_background() { QFETCH(bool, dark); QFETCH(bool, floating); QFETCH(bool, switchFromTheme); MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([original]() { QApplication::setPalette(original); }); QPalette native = original; native.setColor(QPalette::Window, QColor(dark ? "#202020" : "#eeeeee")); native.setColor(QPalette::WindowText, QColor(dark ? "#ffffff" : "#000000")); QApplication::setPalette(native); guard.settings->dockAppearance = switchFromTheme ? Settings::DockAppearanceSpeedCrunch : Settings::DockAppearanceSystem; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#631840")}}); guard.settings->bitfieldVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(QStringLiteral("BitfieldDock")); BitFieldWidget* field = window.findChild(); QMenu* appearance = window.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(dock); QVERIFY(field); QVERIFY(appearance); dock->setFloating(floating); dock->show(); dock->raise(); const auto background = [field]() { const QImage image = field->grab().toImage(); const int inset = qRound(2 * field->devicePixelRatioF()); return image.pixelColor(inset, inset).rgba(); }; if (!switchFromTheme) QTRY_COMPARE(background(), native.color(QPalette::Window).rgba()); else QTRY_VERIFY(background() != native.color(QPalette::Window).rgba()); for (int cycle = 0; cycle < 2; ++cycle) { appearance->actions().at(0)->trigger(); QTRY_COMPARE(background(), native.color(QPalette::Window).rgba()); native.setColor(QPalette::Window, QColor(cycle ? "#303030" : "#dddddd")); QApplication::setPalette(native); QTRY_COMPARE(background(), native.color(QPalette::Window).rgba()); appearance->actions().at(1)->trigger(); QTRY_VERIFY(background() != native.color(QPalette::Window).rgba()); } } void TestBitfieldUi::system_bitfield_background_is_visible_in_window_data() { system_bitfield_paints_background_data(); } void TestBitfieldUi::system_bitfield_background_is_visible_in_window() { QFETCH(bool, dark); QFETCH(bool, floating); QFETCH(bool, switchFromTheme); MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([original]() { QApplication::setPalette(original); }); QPalette native = original; native.setColor(QPalette::Window, QColor(dark ? "#202020" : "#eeeeee")); native.setColor(QPalette::WindowText, QColor(dark ? "#ffffff" : "#000000")); QApplication::setPalette(native); guard.settings->dockAppearance = switchFromTheme ? Settings::DockAppearanceSpeedCrunch : Settings::DockAppearanceSystem; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#062852")}}); guard.settings->bitfieldVisible = true; guard.settings->constantsDockVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); MainWindow window(false); window.resize(1000, 700); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(QStringLiteral("BitfieldDock")); BitFieldWidget* field = window.findChild(); QMenu* appearance = window.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(dock); QVERIFY(field); QVERIFY(appearance); window.addDockWidget(Qt::RightDockWidgetArea, dock); dock->setFloating(floating); dock->show(); dock->raise(); const auto background = [field]() { // Capture the parent so QWidget::grab cannot force a hidden background fill. QWidget* root = field->window(); const QImage image = root->grab().toImage(); const QPoint point = field->mapTo(root, QPoint(2, 2)); return image.pixelColor(qRound(point.x() * root->devicePixelRatioF()), qRound(point.y() * root->devicePixelRatioF())).rgba(); }; if (switchFromTheme) appearance->actions().at(0)->trigger(); QTRY_COMPARE(background(), native.color(QPalette::Window).rgba()); for (int cycle = 0; cycle < 2; ++cycle) { appearance->actions().at(1)->trigger(); QTRY_VERIFY(background() != native.color(QPalette::Window).rgba()); appearance->actions().at(0)->trigger(); QTRY_COMPARE(background(), native.color(QPalette::Window).rgba()); native.setColor(QPalette::Window, QColor(cycle ? "#303030" : "#dddddd")); QApplication::setPalette(native); QTRY_COMPARE(background(), native.color(QPalette::Window).rgba()); } } void TestBitfieldUi::bitfield_buttons_use_configured_generated_shades() { MainWindowStateGuard guard; Settings* settings = guard.settings; settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{{QStringLiteral("background"), QStringLiteral("#e5eee8")}}); settings->bitfieldVisible = true; settings->keypadVisible = false; const QVector shades = generateOklchShades(QColor(QStringLiteral("#e5eee8")), 6, ThemePolarity::Light); const QVector foregrounds = aaForegroundsForBackgrounds(shades); const QColor buttonFill = shades.at(UiConfig::BitfieldButtonFillShade); const QColor buttonForeground = foregrounds.at(UiConfig::BitfieldButtonFillShade); const QColor buttonHoverFill = shades.at(UiConfig::BitfieldButtonHoverFillShade); const QColor buttonHoverForeground = foregrounds.at(UiConfig::BitfieldButtonHoverFillShade); const QColor buttonPressedFill = shades.at(UiConfig::BitfieldButtonPressedFillShade); const QColor buttonPressedForeground = foregrounds.at(UiConfig::BitfieldButtonPressedFillShade); const QColor popupBackground = shades.at(UiConfig::CompletionPopupBackgroundShade); const QColor popupForeground = foregrounds.at(UiConfig::CompletionPopupBackgroundShade); const QColor popupOutline = shades.at(UiConfig::CompletionPopupOutlineShade); MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); BitFieldWidget* bitfield = window.findChild(); QVERIFY(bitfield != nullptr); const QList buttons = bitfield->findChildren(); QCOMPARE(buttons.size(), 4); QPushButton* shiftLeftButton = nullptr; for (QPushButton* button : buttons) { if (button->text() == QLatin1String("<<")) shiftLeftButton = button; const QString style = button->styleSheet(); QCOMPARE(button->toolTip(), QString()); QCOMPARE(button->palette().color(QPalette::Button).name(), buttonFill.name()); QCOMPARE(button->palette().color(QPalette::ButtonText).name(), buttonForeground.name()); QVERIFY(style.contains(QStringLiteral("background-color: %1") .arg(buttonFill.name()))); QVERIFY(style.contains(QStringLiteral("color: %1").arg(buttonForeground.name()))); QVERIFY(style.contains(QStringLiteral("background-color: %1") .arg(buttonHoverFill.name()))); QVERIFY(style.contains(QStringLiteral("color: %1").arg(buttonHoverForeground.name()))); QVERIFY(style.contains(QStringLiteral("background-color: %1") .arg(buttonPressedFill.name()))); QVERIFY(style.contains(QStringLiteral("color: %1") .arg(buttonPressedForeground.name()))); } QVERIFY(shiftLeftButton != nullptr); const QPoint buttonCenter = shiftLeftButton->rect().center(); QMouseEvent moveEvent(QEvent::MouseMove, QPointF(buttonCenter), QPointF(shiftLeftButton->mapToGlobal(buttonCenter)), Qt::NoButton, Qt::NoButton, Qt::NoModifier); QCoreApplication::sendEvent(shiftLeftButton, &moveEvent); QFrame* summaryPopup = bitfield->findChild(QStringLiteral("bitfieldButtonSummaryPopup")); QTRY_VERIFY(summaryPopup != nullptr && summaryPopup->isVisible()); QLabel* summaryPopupLabel = summaryPopup->findChild(QStringLiteral("bitfieldButtonSummaryPopupLabel")); QVERIFY(summaryPopupLabel != nullptr); QCOMPARE(summaryPopupLabel->text(), QStringLiteral("Shift bits left")); QVERIFY(summaryPopup->styleSheet().contains(popupBackground.name())); QVERIFY(summaryPopup->styleSheet().contains(popupForeground.name())); QVERIFY(summaryPopup->styleSheet().contains(QStringLiteral("border: %1px solid %2") .arg(UiConfig::PopupOutlineStrokeWidth) .arg(popupOutline.name()))); QVERIFY(!summaryPopup->mask().isEmpty()); } void TestBitfieldUi::repeated_bit_theme_keeps_state_repainting() { class StyleCounter : public QObject { public: int changes = 0; bool eventFilter(QObject*, QEvent* event) override { if (event->type() == QEvent::StyleChange) ++changes; return false; } } counter; const QColor background("#202124"); const QColor selected("#2f80ed"); BitWidget bit(3); const auto applyColors = [&]() { bit.setThemeColors(background, QColor("#d6d8dc"), background, QColor("#ffffff"), selected, QColor("#ffffff")); }; applyColors(); bit.resize(48, 48); bit.show(); QVERIFY(QTest::qWaitForWindowExposed(&bit)); QCoreApplication::processEvents(); bit.installEventFilter(&counter); for (int i = 0; i < 5; ++i) applyColors(); QCOMPARE(counter.changes, 0); bit.setState(true); QCOMPARE(bit.grab().toImage().pixelColor(4, 4).name(), selected.name()); applyColors(); QCOMPARE(bit.grab().toImage().pixelColor(4, 4).name(), selected.name()); bit.setState(false); QCOMPARE(bit.grab().toImage().pixelColor(4, 4).name(), background.name()); } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testbitfieldui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testcmath.cpp000066400000000000000000001700201526573132500237660ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2015-2017, 2020, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "math/cmath.h" #include "math/floatnum/floatconst.h" #include "tests/testcommon.h" #include #include #include using namespace std; typedef CNumber::Format Format; #define CHECK(x,y) check_value(__FILE__,__LINE__,#x,x,y) #define CHECK_FORMAT(f,x,y) check_format(__FILE__,__LINE__,#x,x,f,y) #define CHECK_PRECISE(x,y) check_precise(__FILE__,__LINE__,#x,x,y) #define CHECK_KNOWN_ISSUE(x,y,n) check_value(__FILE__,__LINE__,#x,x,y,n) #define CHECK_KNOWN_ISSUE_PRECISE(x,y,n) check_precise(__FILE__,__LINE__,#x,x,y,n) static int cmath_total_tests = 0; static int cmath_failed_tests = 0; static int cmath_new_failed_tests = 0; CNumber PI; static void check_value(const char* file, int line, const char* msg, const CNumber& n, const char* expected, int issue = 0) { ++cmath_total_tests; string result = CMath::format(n, Format::Fixed()).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, cmath_failed_tests, cmath_new_failed_tests, issue); } static void check_format(const char* file, int line, const char* msg, const CNumber& n, Format format, const char* expected) { ++cmath_total_tests; string result = CMath::format(n, format).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, cmath_failed_tests, cmath_new_failed_tests, 0); } static void check_precise(const char* file, int line, const char* msg, const CNumber& n, const char* expected, int issue = 0) { ++cmath_total_tests; string result = CMath::format(n, Format::Fixed() + Format::Precision(50)).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, cmath_failed_tests, cmath_new_failed_tests, issue); } void test_create() { // Real numbers CHECK(CNumber("1"), "1"); CHECK(CNumber("2"), "2"); CHECK(CNumber("1.0"), "1"); CHECK(CNumber("1e-3"), "0.001"); CHECK(CNumber("1.0e-3"), "0.001"); // Complex number CHECK(CNumber("0+1j"), "1j"); CHECK(CNumber("1+1j"), "1+1j"); CHECK(CNumber("2+2j"), "2+2j"); CHECK(CNumber("0+1.0j"), "1j"); CHECK(CNumber("0.0+1.0j"), "1j"); CHECK(CNumber("1.0+1.0j"), "1+1j"); CHECK(CNumber("1e-3+1e-3j"), "0.001+0.001j"); CHECK(CNumber("1.0e-3+1.0e-3j"), "0.001+0.001j"); // Too large or too small. CHECK(CNumber("1e1000000000"), "NaN"); CHECK(CNumber("1e-1000000000"), "NaN"); CHECK_FORMAT(Format::Scientific() + Format::Precision(2), CNumber("1e1000000000"), "NaN"); CHECK_FORMAT(Format::Scientific() + Format::Precision(2), CNumber("1e-1000000000"), "NaN"); CHECK(CMath::i()*CMath::i(), "-1"); // Long numbers, like in session history CHECK(CNumber("0+1.000000000000000000000000000000000000000000000000000000000000000000000000000000j"), "1j"); } void test_format() { Format f = Format::Fixed(); Format n = Format::Engineering(); Format e = Format::Scientific(); Format g = Format::General(); // Fixed decimal digits. CHECK_FORMAT(f + Format::Precision(0), CNumber("NaN"), "NaN"); CHECK_FORMAT(f + Format::Precision(0), CNumber("0"), "0"); CHECK_FORMAT(f + Format::Precision(0), CNumber("1.1"), "1"); CHECK_FORMAT(f + Format::Precision(1), CNumber("2.11"), "2.1"); CHECK_FORMAT(f + Format::Precision(2), CNumber("3.111"), "3.11"); CHECK_FORMAT(f + Format::Precision(1), CNumber("4.001"), "4.0"); CHECK_FORMAT(f + Format::Precision(3), CNumber("4.1111"), "4.111"); CHECK_FORMAT(f + Format::Precision(2), CNumber("3.14"), "3.14"); CHECK_FORMAT(f + Format::Precision(3), CNumber("3.14"), "3.140"); CHECK_FORMAT(f + Format::Precision(5), CNumber("3.14"), "3.14000"); CHECK_FORMAT(f + Format::Precision(7), CNumber("3.14"), "3.1400000"); CHECK_FORMAT(f + Format::Precision(7), CNumber("-0.001"), "-0.0010000"); CHECK_FORMAT(f + Format::Precision(8), CNumber("-0.001"), "-0.00100000"); CHECK_FORMAT(f + Format::Precision(9), CNumber("-0.001"), "-0.001000000"); CHECK_FORMAT(f + Format::Precision(-1), CNumber("4.000000000000000000000000000000000000000000001"), "4"); CHECK_FORMAT(f + Format::Precision(0), CNumber("1.19502868068833652008E-6"), "0"); CHECK_FORMAT(f + Format::Precision(1), CNumber("1.19502868068833652008E-6"), "0.0"); CHECK_FORMAT(f + Format::Precision(2), CNumber("1.19502868068833652008E-6"), "0.00"); CHECK_FORMAT(f + Format::Precision(3), CNumber("1.19502868068833652008E-6"), "0.000"); CHECK_FORMAT(f + Format::Precision(3), CNumber("1.195028680688336520083456938469843765E-6"), "0.000"); CHECK_FORMAT(f + Format::Precision(3), CNumber("-1.19502868068833652008E-6"), "0.000"); CHECK_FORMAT(f + Format::Precision(3), CNumber("0.0004999"), "0.000"); CHECK_FORMAT(f + Format::Precision(3), CNumber("0.0005"), "0.000"); CHECK_FORMAT(f + Format::Precision(6), CNumber("1.19502868068833652008E-6"), "0.000001"); // Engineering notation. CHECK_FORMAT(n + Format::Precision(0), CNumber("NaN"), "NaN"); CHECK_FORMAT(n + Format::Precision(0), CNumber("0"), "0"); CHECK_FORMAT(n + Format::Precision(0), CNumber("3.14"), "3.14e0"); CHECK_FORMAT(n + Format::Precision(1), CNumber("3.14"), "3.14e0"); CHECK_FORMAT(n + Format::Precision(2), CNumber("3.14"), "3.14e0"); CHECK_FORMAT(n + Format::Precision(3), CNumber("3.14"), "3.140e0"); CHECK_FORMAT(n + Format::Precision(5), CNumber("3.14"), "3.14000e0"); CHECK_FORMAT(n + Format::Precision(7), CNumber("3.14"), "3.1400000e0"); CHECK_FORMAT(n + Format::Precision(3), CNumber("-0.001"), "-1.000e-3"); CHECK_FORMAT(n + Format::Precision(2), CNumber("0.0001"), "100.e-6"); CHECK_FORMAT(n + Format::Precision(2), CNumber("0.001"), "1.00e-3"); CHECK_FORMAT(n + Format::Precision(2), CNumber("0.01"), "10.0e-3"); CHECK_FORMAT(n + Format::Precision(2), CNumber("0.1"), "100.e-3"); CHECK_FORMAT(n + Format::Precision(2), CNumber("1"), "1.00e0"); CHECK_FORMAT(n + Format::Precision(2), CNumber("10"), "10.0e0"); CHECK_FORMAT(n + Format::Precision(2), CNumber("100"), "100.e0"); CHECK_FORMAT(n + Format::Precision(2), CNumber("1000"), "1.00e3"); CHECK_FORMAT(n + Format::Precision(2), CNumber("10000"), "10.0e3"); CHECK_FORMAT(n + Format::Precision(2), CNumber("100000"), "100.e3"); CHECK_FORMAT(n + Format::Precision(2), CNumber("1000000"), "1.00e6"); CHECK_FORMAT(n + Format::Precision(2), CNumber("10000000"), "10.0e6"); // Scientific notation. CHECK_FORMAT(e + Format::Precision(0), CNumber("NaN"), "NaN"); CHECK_FORMAT(e + Format::Precision(0), CNumber("0"), "0"); CHECK_FORMAT(e + Format::Precision(0), CNumber("3.14"), "3e0"); CHECK_FORMAT(e + Format::Precision(1), CNumber("3.14"), "3.1e0"); CHECK_FORMAT(e + Format::Precision(2), CNumber("3.14"), "3.14e0"); CHECK_FORMAT(e + Format::Precision(3), CNumber("3.14"), "3.140e0"); CHECK_FORMAT(e + Format::Precision(5), CNumber("3.14"), "3.14000e0"); CHECK_FORMAT(e + Format::Precision(7), CNumber("3.14"), "3.1400000e0"); CHECK_FORMAT(e + Format::Precision(3), CNumber("-0.001"), "-1.000e-3"); CHECK_FORMAT(e + Format::Precision(2), CNumber("0.0001"), "1.00e-4"); CHECK_FORMAT(e + Format::Precision(2), CNumber("0.001"), "1.00e-3"); CHECK_FORMAT(e + Format::Precision(2), CNumber("0.01"), "1.00e-2"); CHECK_FORMAT(e + Format::Precision(2), CNumber("0.1"), "1.00e-1"); CHECK_FORMAT(e + Format::Precision(2), CNumber("1"), "1.00e0"); CHECK_FORMAT(e + Format::Precision(2), CNumber("10"), "1.00e1"); CHECK_FORMAT(e + Format::Precision(2), CNumber("100"), "1.00e2"); CHECK_FORMAT(e + Format::Precision(2), CNumber("1000"), "1.00e3"); CHECK_FORMAT(e + Format::Precision(2), CNumber("10000"), "1.00e4"); CHECK_FORMAT(e + Format::Precision(2), CNumber("100000"), "1.00e5"); CHECK_FORMAT(e + Format::Precision(2), CNumber("1000000"), "1.00e6"); CHECK_FORMAT(e + Format::Precision(2), CNumber("10000000"), "1.00e7"); // General format. CHECK_FORMAT(g + Format::Precision(-1), PI, "3.14159265358979323846"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0"), "0"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.000000001"), "1.000e-9"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.00000001"), "1.000e-8"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.0000001"), "1.000e-7"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.000001"), "1.000e-6"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.00001"), "1.000e-5"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.0001"), "1.000e-4"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.001"), "0.001"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.01"), "0.010"); CHECK_FORMAT(g + Format::Precision(3), CNumber("0.1"), "0.100"); CHECK_FORMAT(g + Format::Precision(3), CNumber("10"), "10.000"); CHECK_FORMAT(g + Format::Precision(3), CNumber("100"), "100.000"); CHECK_FORMAT(g + Format::Precision(3), CNumber("1000"), "1000.000"); CHECK_FORMAT(g + Format::Precision(3), CNumber("10000"), "10000.000"); CHECK_FORMAT(g + Format::Precision(3), CNumber("100000"), "100000.000"); CHECK_FORMAT(g + Format::Precision(3), CNumber("1000000"), "1000000.000"); CHECK_FORMAT(g + Format::Precision(3), CNumber("10000000"), "10000000.000"); CHECK_FORMAT(g + Format::Precision(3), CNumber("100000000"), "100000000.000"); CHECK_FORMAT(g + Format::Precision(3), CNumber("1403.1977"), "1403.198"); CHECK_FORMAT(g + Format::Precision(3), CNumber("2604.1980"), "2604.198"); CHECK_FORMAT(g + Format::Precision(3), CNumber("2.47e4"), "24700.000"); } void test_op() { // Addition. CHECK(CNumber(0) + CNumber(0), "0"); CHECK(CNumber(1) + CNumber(0), "1"); CHECK(CNumber(1) + CNumber(1), "2"); CHECK(CNumber(1) + CNumber(2), "3"); CHECK(CNumber(1) + CNumber(10), "11"); CHECK(CNumber(1) + CNumber(100), "101"); CHECK(CNumber(1) + CNumber(1000), "1001"); CHECK(CNumber(5) + CNumber("NaN"), "NaN"); CHECK(CNumber("NaN") + CNumber(5), "NaN"); // Subtraction. CHECK(CNumber(0) - CNumber(0), "0"); CHECK(CNumber(1) - CNumber(0), "1"); CHECK(CNumber(1) - CNumber(2), "-1"); CHECK(CNumber(1) - CNumber("NaN"), "NaN"); CHECK(CNumber("NaN") - CNumber(1), "NaN"); // Division. CHECK(CNumber(1) / CNumber(2), "0.5"); CHECK(CNumber(1) / CMath::sin(PI), "NaN"); CHECK(CNumber(1) / CNumber("NaN"), "NaN"); CHECK(CNumber("NaN") / CNumber(4), "NaN"); // Division by zero. CHECK(CNumber(1) / CNumber(0), "NaN"); CHECK(CNumber(1) / CMath::sin(0), "NaN"); CHECK(CNumber(1) / CMath::sin(PI), "NaN"); CHECK(CNumber(1) / CMath::cos(PI/2), "NaN"); CHECK(CNumber(1) / CMath::tan(0), "NaN"); CHECK(CNumber(1) / CMath::tan(PI), "NaN"); CHECK(CNumber(1) / CMath::trunc("0.123"), "NaN"); CHECK(CNumber(1) / CMath::round("0.456"), "NaN"); CHECK(CNumber(1) / CMath::binomialPmf(1, 10, 0), "NaN"); CHECK_PRECISE(CNumber(1) / CNumber(3), "0.33333333333333333333333333333333333333333333333333"); CHECK_PRECISE(CNumber(2) / CNumber(3), "0.66666666666666666666666666666666666666666666666667"); CHECK_PRECISE(CNumber(1) / CNumber(7), "0.14285714285714285714285714285714285714285714285714"); CHECK_PRECISE(CNumber(2) / CNumber(7), "0.28571428571428571428571428571428571428571428571429"); CHECK_PRECISE(CNumber(3) / CNumber(7), "0.42857142857142857142857142857142857142857142857143"); CHECK_PRECISE(CNumber(4) / CNumber(7), "0.57142857142857142857142857142857142857142857142857"); CHECK_PRECISE(CNumber(1) / CNumber(9), "0.11111111111111111111111111111111111111111111111111"); // Multiplication. CHECK(CNumber(0)* CNumber(0), "0"); CHECK(CNumber("1.0")* CNumber("0.0"), "0"); CHECK(CNumber(1)* CNumber(1), "1"); CHECK(CNumber(3)* CNumber(-4), "-12"); CHECK(CNumber(-2)* CNumber(5), "-10"); CHECK(CNumber(6)* CNumber(7), "42"); CHECK(CNumber("1.5")* CNumber("1.5"), "2.25"); CHECK(CNumber(4) * CNumber("NaN"), "NaN"); CHECK(CNumber("NaN") * CNumber(4), "NaN"); } void test_functions() { CHECK(PI, "3.14159265358979323846"); CHECK_PRECISE(PI, "3.14159265358979323846264338327950288419716939937511"); CHECK(CMath::abs("NaN"), "NaN"); CHECK(CMath::abs("0"), "0"); CHECK(CMath::abs("1"), "1"); CHECK(CMath::abs("100"), "100"); CHECK(CMath::abs("-100"), "100"); CHECK(CMath::abs("-3.14159"), "3.14159"); CHECK(CMath::abs("-0.00000014159"), "0.00000014159"); CHECK(CMath::conj("NaN"), "NaN"); CHECK(CMath::conj("1"), "1"); CHECK(CMath::conj("1j"), "-1j"); CHECK(CMath::conj("1+1j"), "1-1j"); CHECK(CMath::floor("NaN"), "NaN"); CHECK(CMath::floor("0"), "0"); CHECK(CMath::floor("5"), "5"); CHECK(CMath::floor("-5"), "-5"); CHECK(CMath::floor("3.14"), "3"); CHECK(CMath::floor("1.77"), "1"); CHECK(CMath::floor("-2.6041980"), "-3"); CHECK(CMath::floor("2.6041980"), "2"); CHECK(CMath::floor("0.000001"), "0"); CHECK(CMath::floor("-0.000001"), "-1"); CHECK(CMath::floor(CNumber(1) / 3 * 3), "1"); CHECK(CMath::ceil("NaN"), "NaN"); CHECK(CMath::ceil("0"), "0"); CHECK(CMath::ceil("5"), "5"); CHECK(CMath::ceil("-5"), "-5"); CHECK(CMath::ceil("3.14"), "4"); CHECK(CMath::ceil("1.77"), "2"); CHECK(CMath::ceil("-2.6041980"), "-2"); CHECK(CMath::ceil("2.6041980"), "3"); CHECK(CMath::ceil("0.000001"), "1"); CHECK(CMath::ceil("-0.000001"), "0"); CHECK(CMath::ceil(CMath::log(2, 128)), "7"); CHECK(CMath::gcd("NaN", "NaN"), "NaN"); CHECK(CMath::gcd("NaN", "5"), "NaN"); CHECK(CMath::gcd("5", "NaN"), "NaN"); CHECK(CMath::gcd("0", "0"), "0"); CHECK(CMath::gcd("0", "5"), "5"); CHECK(CMath::gcd("5", "0"), "5"); CHECK(CMath::gcd("0", "-5"), "5"); CHECK(CMath::gcd("-5", "0"), "5"); CHECK(CMath::gcd("9", "-27"), "9"); CHECK(CMath::gcd("99", "103"), "1"); CHECK(CMath::gcd("-102", "306"), "102"); CHECK(CMath::round("NaN"), "NaN"); CHECK(CMath::round("3.14"), "3"); CHECK(CMath::round("-1.77"), "-2"); CHECK(CMath::round("NaN", 3), "NaN"); CHECK(CMath::round("0.005", -3), "0"); CHECK(CMath::round("0.005", 2), "0"); CHECK(CMath::round("3.14159", 4), "3.1416"); CHECK(CMath::round("3.14159", 3), "3.142"); CHECK(CMath::round("3.14159", 2), "3.14"); CHECK(CMath::round("3.14159", 1), "3.1"); CHECK(CMath::round("3.14159", 0), "3"); CHECK(CMath::round("-2.6041980", 4), "-2.6042"); CHECK(CMath::round("-2.6041980", 3), "-2.604"); CHECK(CMath::round("-2.6041980", 2), "-2.6"); CHECK(CMath::round("-2.6041980", 1), "-2.6"); CHECK(CMath::round("-2.6041980", 0), "-3"); CHECK(CMath::trunc("NaN"), "NaN"); CHECK(CMath::trunc("0"), "0"); CHECK(CMath::trunc("3.14"), "3"); CHECK(CMath::trunc("1.77"), "1"); CHECK(CMath::trunc("NaN", 3), "NaN"); CHECK(CMath::trunc("0.00013", -3), "0"); CHECK(CMath::trunc("0.00013", 4), "0.0001"); CHECK(CMath::trunc("3.14159", 4), "3.1415"); CHECK(CMath::trunc("3.14159", 3), "3.141"); CHECK(CMath::trunc("3.14159", 2), "3.14"); CHECK(CMath::trunc("3.14159", 1), "3.1"); CHECK(CMath::trunc("3.14159", 0), "3"); CHECK(CMath::trunc("-2.6041980", 4), "-2.6041"); CHECK(CMath::trunc("-2.6041980", 3), "-2.604"); CHECK(CMath::trunc("-2.6041980", 2), "-2.6"); CHECK(CMath::trunc("-2.6041980", 1), "-2.6"); CHECK(CMath::trunc("-2.6041980", 0), "-2"); CHECK(CMath::trunc("-2.6041980", 999), "-2.604198"); CHECK(CMath::trunc("-2.6041980", -2), "0"); CHECK(CMath::integer("NaN"), "NaN"); CHECK(CMath::integer("0"), "0"); CHECK(CMath::integer("0.25"), "0"); CHECK(CMath::integer("0.85"), "0"); CHECK(CMath::integer("14.0377"), "14"); CHECK(CMath::integer("-0.25"), "0"); CHECK(CMath::integer("-0.85"), "0"); CHECK(CMath::integer("-14.0377"), "-14"); CHECK(CMath::frac("NaN"), "NaN"); CHECK(CMath::frac("0"), "0"); CHECK(CMath::frac("3.14159"), "0.14159"); CHECK(CMath::frac("0.14159"), "0.14159"); CHECK(CMath::frac("-3.14159"), "-0.14159"); CHECK(CMath::frac("-0.14159"), "-0.14159"); CHECK(CMath::sqrt("NaN"), "NaN"); CHECK(CMath::sqrt(-1), "1j"); CHECK(CMath::sqrt(0), "0"); CHECK(CMath::sqrt(1), "1"); CHECK(CMath::sqrt(4), "2"); CHECK(CMath::sqrt(9), "3"); CHECK(CMath::sqrt(16), "4"); CHECK(CMath::sqrt("0.04"), "0.2"); CHECK(CMath::sqrt("0.09"), "0.3"); CHECK(CMath::sqrt("0.16"), "0.4"); CHECK_PRECISE(CMath::sqrt(2), "1.41421356237309504880168872420969807856967187537695"); CHECK_PRECISE(CMath::sqrt(3), "1.73205080756887729352744634150587236694280525381038"); CHECK_PRECISE(CMath::sqrt(5), "2.23606797749978969640917366873127623544061835961153"); CHECK_PRECISE(CMath::sqrt(7), "2.64575131106459059050161575363926042571025918308245"); CHECK_PRECISE(CMath::sqrt(8), "2.82842712474619009760337744841939615713934375075390"); CHECK_PRECISE(CMath::sqrt(10), "3.16227766016837933199889354443271853371955513932522"); CHECK_PRECISE(CMath::sqrt(11), "3.31662479035539984911493273667068668392708854558935"); CHECK_PRECISE(CMath::sqrt(12), "3.46410161513775458705489268301174473388561050762076"); CHECK_PRECISE(CMath::sqrt(13), "3.60555127546398929311922126747049594625129657384525"); CHECK_PRECISE(CMath::sqrt(14), "3.74165738677394138558374873231654930175601980777873"); CHECK_PRECISE(CMath::sqrt(15), "3.87298334620741688517926539978239961083292170529159"); CHECK_PRECISE(CMath::sqrt(17), "4.12310562561766054982140985597407702514719922537362"); CHECK_PRECISE(CMath::sqrt(18), "4.24264068711928514640506617262909423570901562613084"); CHECK_PRECISE(CMath::sqrt(19), "4.35889894354067355223698198385961565913700392523244"); CHECK_PRECISE(CMath::sqrt(20), "4.47213595499957939281834733746255247088123671922305"); CHECK(CMath::cbrt("NaN"), "NaN"); CHECK(CMath::cbrt(0), "0"); CHECK(CMath::cbrt(1), "1"); CHECK(CMath::cbrt(-1), "-1"); CHECK(CMath::cbrt(8), "2"); CHECK(CMath::cbrt(-8), "-2"); CHECK(CMath::cbrt(27), "3"); CHECK(CMath::cbrt(-27), "-3"); CHECK(CMath::cbrt(64), "4"); CHECK(CMath::cbrt(-64), "-4"); CHECK(CMath::cbrt("0.008"), "0.2"); CHECK(CMath::cbrt("-0.008"), "-0.2"); CHECK(CMath::cbrt("0.027"), "0.3"); CHECK(CMath::cbrt("-0.027"), "-0.3"); CHECK(CMath::cbrt("0.064"), "0.4"); CHECK(CMath::cbrt("-0.064"), "-0.4"); CHECK_PRECISE(CMath::cbrt(2), "1.25992104989487316476721060727822835057025146470151"); CHECK_PRECISE(CMath::cbrt(3), "1.44224957030740838232163831078010958839186925349935"); CHECK_PRECISE(CMath::cbrt(-20), "-2.71441761659490657151808946967948920480510776948910"); CHECK(CMath::sgn("NaN"), "NaN"); CHECK(CMath::sgn(0), "0"); CHECK(CMath::sgn(1), "1"); CHECK(CMath::sgn(-1), "-1"); CHECK(CMath::sgn(2), "1"); CHECK(CMath::sgn(-2), "-1"); CHECK(CMath::factorial("NaN"), "NaN"); CHECK(CMath::factorial(-1), "NaN"); CHECK(CMath::factorial(0), "1"); CHECK(CMath::factorial(1), "1"); CHECK(CMath::factorial(2), "2"); CHECK(CMath::factorial(3), "6"); CHECK(CMath::factorial(4), "24"); CHECK(CMath::factorial(5), "120"); CHECK(CMath::factorial(6), "720"); CHECK(CMath::factorial(7), "5040"); CHECK(CMath::factorial(8), "40320"); CHECK_PRECISE(CMath::factorial("5.23"), "178.50732778544229114185259335979946974446422321576241"); CHECK(CMath::factorial("-5"), "NaN"); CHECK(CMath::factorial("NaN", "NaN"), "NaN"); CHECK(CMath::factorial("NaN", 7), "NaN"); CHECK(CMath::factorial(8, "NaN"), "NaN"); CHECK(CMath::factorial(8, 0), "0"); CHECK(CMath::factorial(8, 6), "336"); CHECK(CMath::factorial(8, 7), "56"); CHECK(CMath::factorial(8, 8), "8"); CHECK(CMath::nCr("NaN", "NaN"), "NaN"); CHECK(CMath::nCr("NaN", 5), "NaN"); CHECK(CMath::nCr(5, "NaN"), "NaN"); CHECK(CMath::nCr(21, -1), "0"); CHECK(CMath::nCr(-21, 2), "231"); CHECK(CMath::nCr(21, 0), "1"); CHECK(CMath::nCr(21, 1), "21"); CHECK(CMath::nCr(21, 2), "210"); CHECK(CMath::nCr(21, 3), "1330"); CHECK(CMath::nCr(21, 19), "210"); CHECK(CMath::nCr(21, 20), "21"); CHECK(CMath::nCr(21, 21), "1"); CHECK(CMath::nCr(21, 22), "0"); CHECK(CMath::nCr(0, 0), "1"); CHECK(CMath::nPr("NaN", "NaN"), "NaN"); CHECK(CMath::nPr("NaN", 5), "NaN"); CHECK(CMath::nPr(5, "NaN"), "NaN"); CHECK(CMath::nPr(21, 22), "0"); CHECK(CMath::nPr(-21, 2), "462"); CHECK(CMath::nPr(21, -1), "0.04545454545454545455"); CHECK(CMath::nPr(0, 0), "1"); CHECK(CMath::nPr(21, 0), "1"); CHECK(CMath::nPr(21, 1), "21"); CHECK(CMath::nPr(21, 2), "420"); CHECK(CMath::nPr(21, 3), "7980"); CHECK(CMath::nPr(21, 4), "143640"); CHECK(CMath::nPr(21, 5), "2441880"); CHECK(CMath::nPr(21, 6), "39070080"); CHECK(CMath::nPr(21, 7), "586051200"); CHECK(CMath::raise("NaN", "NaN"), "NaN"); CHECK(CMath::raise("NaN", "0"), "NaN"); CHECK(CMath::raise("-1", "NaN"), "NaN"); CHECK(CMath::raise(10, -3), "0.001"); CHECK(CMath::raise(10, -2), "0.01"); CHECK(CMath::raise(10, -1), "0.1"); CHECK(CMath::raise(10, 0), "1"); CHECK(CMath::raise(10, 1), "10"); CHECK(CMath::raise(10, 2), "100"); CHECK(CMath::raise(10, 3), "1000"); CHECK(CMath::raise(10, 4), "10000"); CHECK(CMath::raise("2", "2"), "4"); CHECK(CMath::raise("3", "3"), "27"); CHECK(CMath::raise("4", "4"), "256"); CHECK(CMath::raise("-27", CNumber("1") / CNumber("3")), "1.5+2.59807621135331594029j"); CHECK(CMath::raise("-27", CNumber("-1") / CNumber("3")), "0.16666666666666666667-0.28867513459481288225j"); CHECK_PRECISE(CMath::raise("2", "0.1"), "1.07177346253629316421300632502334202290638460497756"); CHECK_PRECISE(CMath::raise("2", "0.2"), "1.14869835499703500679862694677792758944385088909780"); CHECK_PRECISE(CMath::raise("2", "0.3"), "1.23114441334491628449939306916774310987613776110082"); // See https://en.wikipedia.org/wiki/Exponentiation#Powers_of_zero CHECK_KNOWN_ISSUE(CMath::raise("0", "1"), "0", 728); CHECK_KNOWN_ISSUE(CMath::raise("0", "1.5"), "0", 728); CHECK_KNOWN_ISSUE(CMath::raise("0", "2"), "0", 728); CHECK_KNOWN_ISSUE(CMath::raise("0", "1+1j"), "0", 718); CHECK_KNOWN_ISSUE(CMath::raise("0", "1.5+1j"), "0", 718); CHECK_KNOWN_ISSUE(CMath::raise("0", "2+1j"), "0", 718); CHECK(CMath::exp("NaN"), "NaN"); CHECK(CMath::exp("0"), "1"); CHECK_PRECISE(CMath::exp("0.1"), "1.10517091807564762481170782649024666822454719473752"); CHECK_PRECISE(CMath::exp("0.2"), "1.22140275816016983392107199463967417030758094152050"); CHECK_PRECISE(CMath::exp("0.3"), "1.34985880757600310398374431332800733037829969735937"); CHECK_PRECISE(CMath::exp("0.4"), "1.49182469764127031782485295283722228064328277393743"); CHECK_PRECISE(CMath::exp("0.5"), "1.64872127070012814684865078781416357165377610071015"); CHECK_PRECISE(CMath::exp("0.6"), "1.82211880039050897487536766816286451338223880854644"); CHECK_PRECISE(CMath::exp("0.7"), "2.01375270747047652162454938858306527001754239414587"); CHECK_PRECISE(CMath::exp("0.8"), "2.22554092849246760457953753139507675705363413504848"); CHECK_PRECISE(CMath::exp("0.9"), "2.45960311115694966380012656360247069542177230644008"); CHECK_PRECISE(CMath::exp("1.0"), "2.71828182845904523536028747135266249775724709369996"); CHECK_PRECISE(CMath::exp("100"), "26881171418161354484126255515800135873611118.77374192241519160861528028703490956400000000000000"/*"91415887109722"*/); CHECK(CMath::binomialPmf("NaN", "NaN", "NaN"), "NaN"); CHECK(CMath::binomialPmf("NaN", "NaN", "0.5"), "NaN"); CHECK(CMath::binomialPmf("NaN", "10", "NaN"), "NaN"); CHECK(CMath::binomialPmf("NaN", "10", "0.5"), "NaN"); CHECK(CMath::binomialPmf("5", "NaN", "NaN"), "NaN"); CHECK(CMath::binomialPmf("5", "NaN", "0.5"), "NaN"); CHECK(CMath::binomialPmf("5", "10", "NaN"), "NaN"); CHECK(CMath::binomialPmf("5", "10", "0.5"), "0.24609375"); CHECK(CMath::binomialPmf("-5", "10", "0.5"), "0"); CHECK_PRECISE(CMath::binomialPmf("5", "10", "0.5"), "0.24609375000000000000000000000000000000000000000000"); CHECK(CMath::binomialCdf("NaN", "NaN", "NaN"), "NaN"); CHECK(CMath::binomialCdf("NaN", "NaN", "0.5"), "NaN"); CHECK(CMath::binomialCdf("NaN", "10", "NaN"), "NaN"); CHECK(CMath::binomialCdf("NaN", "10", "0.5"), "NaN"); CHECK(CMath::binomialCdf("5", "NaN", "NaN"), "NaN"); CHECK(CMath::binomialCdf("5", "NaN", "0.5"), "NaN"); CHECK(CMath::binomialCdf("5", "10", "NaN"), "NaN"); CHECK(CMath::binomialCdf("5", "10", "0.5"), "0.623046875"); CHECK(CMath::binomialCdf("-5", "10", "0.5"), "0"); CHECK_PRECISE(CMath::binomialCdf("5", "10", "0.5"), "0.62304687500000000000000000000000000000000000000000"); CHECK(CMath::binomialMean("NaN", "NaN"), "NaN"); CHECK(CMath::binomialMean("NaN", "0.5"), "NaN"); CHECK(CMath::binomialMean("10", "NaN"), "NaN"); CHECK(CMath::binomialMean("10", "0.5"), "5"); CHECK(CMath::binomialMean("-10", "0.5"), "NaN"); CHECK_PRECISE(CMath::binomialMean("10", "0.5"), "5.00000000000000000000000000000000000000000000000000"); CHECK(CMath::binomialVariance("NaN", "NaN"), "NaN"); CHECK(CMath::binomialVariance("NaN", "0.5"), "NaN"); CHECK(CMath::binomialVariance("10", "NaN"), "NaN"); CHECK(CMath::binomialVariance("10", "0.5"), "2.5"); CHECK(CMath::binomialVariance("-10", "0.5"), "NaN"); CHECK_PRECISE(CMath::binomialVariance("10", "0.5"), "2.50000000000000000000000000000000000000000000000000"); CHECK(CMath::hypergeometricPmf("NaN", "NaN", "NaN", "NaN"), "NaN"); CHECK(CMath::hypergeometricPmf("NaN", "NaN", "NaN", "5"), "NaN"); CHECK(CMath::hypergeometricPmf("NaN", "NaN", "10", "NaN"), "NaN"); CHECK(CMath::hypergeometricPmf("NaN", "NaN", "10", "5"), "NaN"); CHECK(CMath::hypergeometricPmf("1", "15", "NaN", "NaN"), "NaN"); CHECK(CMath::hypergeometricPmf("1", "15", "NaN", "5"), "NaN"); CHECK(CMath::hypergeometricPmf("1", "15", "10", "NaN"), "NaN"); CHECK(CMath::hypergeometricPmf("-1", "15", "10", "5"), "0"); CHECK(CMath::hypergeometricPmf("1", "15", "10", "5"), "0.01665001665001665002"); CHECK_PRECISE(CMath::hypergeometricPmf("1", "15", "10", "5"), "0.01665001665001665001665001665001665001665001665002"); CHECK(CMath::hypergeometricCdf("NaN", "NaN", "NaN", "NaN"), "NaN"); CHECK(CMath::hypergeometricCdf("NaN", "NaN", "NaN", "5"), "NaN"); CHECK(CMath::hypergeometricCdf("NaN", "NaN", "10", "NaN"), "NaN"); CHECK(CMath::hypergeometricCdf("NaN", "NaN", "10", "5"), "NaN"); CHECK(CMath::hypergeometricCdf("1", "15", "NaN", "NaN"), "NaN"); CHECK(CMath::hypergeometricCdf("1", "15", "NaN", "5"), "NaN"); CHECK(CMath::hypergeometricCdf("1", "15", "10", "NaN"), "NaN"); CHECK(CMath::hypergeometricCdf("-1", "15", "10", "5"), "0"); CHECK(CMath::hypergeometricCdf("1", "15", "10", "5"), "0.01698301698301698302"); CHECK_PRECISE(CMath::hypergeometricCdf("1", "15", "10", "5"), "0.01698301698301698301698301698301698301698301698302"); CHECK(CMath::hypergeometricMean("NaN", "NaN", "NaN"), "NaN"); CHECK(CMath::hypergeometricMean("NaN", "NaN", "5"), "NaN"); CHECK(CMath::hypergeometricMean("15", "10", "NaN"), "NaN"); CHECK(CMath::hypergeometricMean("15", "10", "5"), "3.33333333333333333333"); CHECK_PRECISE(CMath::hypergeometricMean("15", "10", "5"), "3.33333333333333333333333333333333333333333333333333"); CHECK(CMath::hypergeometricVariance("NaN", "NaN", "NaN"), "NaN"); CHECK(CMath::hypergeometricVariance("NaN", "NaN", "5"), "NaN"); CHECK(CMath::hypergeometricVariance("15", "10", "NaN"), "NaN"); CHECK(CMath::hypergeometricVariance("15", "10", "5"), "0.79365079365079365079"); CHECK_PRECISE(CMath::hypergeometricVariance("15", "10", "5"), "0.79365079365079365079365079365079365079365079365079"); CHECK(CMath::poissonPmf("NaN", "NaN"), "NaN"); CHECK(CMath::poissonPmf("NaN", "5"), "NaN"); CHECK(CMath::poissonPmf("2", "NaN"), "NaN"); CHECK(CMath::poissonPmf("-2", "5"), "0"); CHECK(CMath::poissonPmf("2", "5"), "0.08422433748856833871"); CHECK_PRECISE(CMath::poissonPmf("2", "5"), "0.08422433748856833870795060528935530311061981284194"); CHECK(CMath::poissonCdf("NaN", "NaN"), "NaN"); CHECK(CMath::poissonCdf("NaN", "5"), "NaN"); CHECK(CMath::poissonCdf("2", "NaN"), "NaN"); CHECK(CMath::poissonCdf("-2", "5"), "0"); CHECK(CMath::poissonCdf("2", "5"), "0.12465201948308114129"); CHECK_PRECISE(CMath::poissonCdf("2", "5"), "0.12465201948308114128776689582824584860371732300607"); CHECK(CMath::poissonMean("NaN"), "NaN"); CHECK(CMath::poissonMean("5"), "5"); CHECK(CMath::poissonMean("-5"), "NaN"); CHECK_PRECISE(CMath::poissonMean("5"), "5.00000000000000000000000000000000000000000000000000"); CHECK(CMath::poissonVariance("NaN"), "NaN"); CHECK(CMath::poissonVariance("5"), "5"); CHECK(CMath::poissonVariance("-5"), "NaN"); CHECK_PRECISE(CMath::poissonVariance("5"), "5.00000000000000000000000000000000000000000000000000"); CHECK(CMath::ln("NaN"), "NaN"); CHECK(CMath::ln("-0.1"), "-2.30258509299404568402+3.14159265358979323846j"); CHECK(CMath::ln("0"), "NaN"); CHECK(CMath::ln("0.00000000001"), "-25.3284360229345025242"); CHECK_PRECISE(CMath::ln("0.1"), "-2.30258509299404568401799145468436420760110148862877"); CHECK_PRECISE(CMath::ln("0.2"), "-1.60943791243410037460075933322618763952560135426852"); CHECK_PRECISE(CMath::ln("0.3"), "-1.20397280432593599262274621776183850295361093080602"); CHECK_PRECISE(CMath::ln("0.4"), "-0.91629073187415506518352721176801107145010121990826"); CHECK_PRECISE(CMath::ln("0.5"), "-0.69314718055994530941723212145817656807550013436026"); CHECK_PRECISE(CMath::ln("0.6"), "-0.51082562376599068320551409630366193487811079644577"); CHECK_PRECISE(CMath::ln("0.7"), "-0.35667494393873237891263871124118447796401675904691"); CHECK_PRECISE(CMath::ln("0.8"), "-0.22314355131420975576629509030983450337460108554801"); CHECK_PRECISE(CMath::ln("0.9"), "-0.10536051565782630122750098083931279830612037298327"); CHECK_PRECISE(CMath::ln("1.0"), "0"); CHECK_PRECISE(CMath::ln("1.1"), "0.09531017980432486004395212328076509222060536530864"); CHECK_PRECISE(CMath::ln("1.2"), "0.18232155679395462621171802515451463319738933791449"); CHECK_PRECISE(CMath::ln("1.3"), "0.26236426446749105203549598688095439720416645613143"); CHECK_PRECISE(CMath::ln("1.4"), "0.33647223662121293050459341021699209011148337531334"); CHECK_PRECISE(CMath::ln("1.5"), "0.40546510810816438197801311546434913657199042346249"); CHECK_PRECISE(CMath::ln("1.6"), "0.47000362924573555365093703114834206470089904881225"); CHECK_PRECISE(CMath::ln("1.7"), "0.53062825106217039623154316318876232798710152395697"); CHECK_PRECISE(CMath::ln("1.8"), "0.58778666490211900818973114061886376976937976137698"); CHECK_PRECISE(CMath::ln("1.9"), "0.64185388617239477599103597720348932963627777267036"); CHECK_PRECISE(CMath::ln("2.0"), "0.69314718055994530941723212145817656807550013436026"); CHECK_PRECISE(CMath::ln("3.0"), "1.09861228866810969139524523692252570464749055782275"); CHECK_PRECISE(CMath::ln("4.0"), "1.38629436111989061883446424291635313615100026872051"); CHECK_PRECISE(CMath::ln("100"), "4.60517018598809136803598290936872841520220297725755"); // Issue 965 CHECK_KNOWN_ISSUE_PRECISE(CMath::ln(CMath::raise("16", "3")), "8.31776616671934371300678545749811881690600161232306", 965); CHECK_KNOWN_ISSUE_PRECISE(CMath::log("2", CMath::raise("16", "3")), "12.00000000000000000000000000000000000000000000000000", 965); CHECK(CMath::lg("NaN"), "NaN"); CHECK(CMath::lg("-1"), "1.36437635384184134749j"); CHECK(CMath::lg("0"), "NaN"); CHECK(CMath::lg("1e-5"), "-5"); CHECK(CMath::lg("1e-4"), "-4"); CHECK(CMath::lg("1e-3"), "-3"); CHECK(CMath::lg("10"), "1"); CHECK(CMath::lg("100"), "2"); CHECK(CMath::lg("1000"), "3"); CHECK(CMath::lg("10000"), "4"); CHECK(CMath::lg("1e5"), "5"); CHECK(CMath::lg("1e6"), "6"); CHECK(CMath::lg("1e7"), "7"); CHECK(CMath::lg("1e8"), "8"); CHECK(CMath::lg("1e9"), "9"); CHECK(CMath::lg("1e10"), "10"); CHECK(CMath::lg("0.00000000001"), "-11"); CHECK(CMath::lb("NaN"), "NaN"); CHECK(CMath::lb("-1"), "4.53236014182719380963j"); CHECK(CMath::lb("0"), "NaN"); CHECK(CMath::lb("1"), "0"); CHECK(CMath::lb("2"), "1"); CHECK(CMath::lb("4"), "2"); CHECK(CMath::lb("8"), "3"); CHECK(CMath::lb("16"), "4"); CHECK(CMath::lb("32"), "5"); CHECK(CMath::lb("0.00000000001"), "-36.54120904376098582657"); CHECK(CMath::log("NaN", "NaN"), "NaN"); CHECK(CMath::log("1", "NaN"), "NaN"); CHECK(CMath::log("NaN", "1"), "NaN"); CHECK(CMath::log("123", "1234"), "1.47916531845224081828"); CHECK(CMath::log("0.123", "0.1234"), "0.99845065797473594741"); CHECK(CMath::log("0.00000000001", "0.00000000000001"), "1.27272727272727272727"); CHECK(CMath::sin("NaN"), "NaN"); CHECK(CMath::sin("0"), "0"); CHECK(CMath::sin(PI), "0"); CHECK(CMath::sin(PI*2), "0"); CHECK(CMath::sin(PI*(-1)), "0"); CHECK(CMath::sin(PI*(-3)), "0"); CHECK(CMath::sin(PI*6/3), "0"); CHECK(CMath::sin(PI*9/3), "0"); CHECK(CMath::sin(PI/2), "1"); CHECK(CMath::sin(PI/4), "0.7071067811865475244"); CHECK(CMath::sin(PI/3), "0.86602540378443864676"); CHECK(CMath::sin(PI*2/3), "0.86602540378443864676"); CHECK(CMath::sin(PI*4/3), "-0.86602540378443864676"); CHECK(CMath::sin(PI*5/3), "-0.86602540378443864676"); CHECK(CMath::sin(PI*7/3), "0.86602540378443864676"); CHECK_PRECISE(CMath::sin("0.0"), "0"); CHECK_PRECISE(CMath::sin("0.1"), "0.09983341664682815230681419841062202698991538801798"); CHECK_PRECISE(CMath::sin("0.2"), "0.19866933079506121545941262711838975037020672954021"); CHECK_PRECISE(CMath::sin("0.3"), "0.29552020666133957510532074568502737367783211174262"); CHECK_PRECISE(CMath::sin("0.4"), "0.38941834230865049166631175679570526459306018344396"); CHECK_PRECISE(CMath::sin("0.5"), "0.47942553860420300027328793521557138808180336794060"); CHECK_PRECISE(CMath::sin("0.6"), "0.56464247339503535720094544565865790710988808499415"); CHECK_PRECISE(CMath::sin("0.7"), "0.64421768723769105367261435139872018306581384457369"); CHECK_PRECISE(CMath::sin("0.8"), "0.71735609089952276162717461058138536619278523779142"); CHECK_PRECISE(CMath::sin("0.9"), "0.78332690962748338846138231571354862314014792572031"); CHECK_PRECISE(CMath::sin("1.0"), "0.84147098480789650665250232163029899962256306079837"); CHECK_PRECISE(CMath::sin("2.0"), "0.90929742682568169539601986591174484270225497144789"); CHECK_PRECISE(CMath::sin("3.0"), "0.14112000805986722210074480280811027984693326425227"); CHECK_PRECISE(CMath::sin("4.0"), "-0.75680249530792825137263909451182909413591288733647"); CHECK_PRECISE(CMath::sin("5.0"), "-0.95892427466313846889315440615599397335246154396460"); CHECK_PRECISE(CMath::sin("1e22"), "-0.85220084976718880177270589375302936826176215041004"); CHECK(CMath::cos("NaN"), "NaN"); CHECK(CMath::cos(PI/2), "0"); CHECK(CMath::cos(PI*3/2), "0"); CHECK(CMath::cos(PI/2*(-1)*9), "0"); CHECK(CMath::cos(0), "1"); CHECK(CMath::cos(PI*6/3), "1"); CHECK(CMath::cos(PI*9/3), "-1"); CHECK(CMath::cos(PI/1), "-1"); CHECK(CMath::cos(PI/3), "0.5"); CHECK(CMath::cos(PI*2/3), "-0.5"); CHECK(CMath::cos(PI*4/3), "-0.5"); CHECK(CMath::cos(PI*5/3), "0.5"); CHECK(CMath::cos(PI*7/3), "0.5"); CHECK(CMath::cos(PI/4), "0.7071067811865475244"); CHECK_PRECISE(CMath::cos("0.0"), "1.00000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::cos("0.1"), "0.99500416527802576609556198780387029483857622541508"); CHECK_PRECISE(CMath::cos("0.2"), "0.98006657784124163112419651674816887739352436080657"); CHECK_PRECISE(CMath::cos("0.3"), "0.95533648912560601964231022756804989824421408263204"); CHECK_PRECISE(CMath::cos("0.4"), "0.92106099400288508279852673205180161402585956931985"); CHECK_PRECISE(CMath::cos("0.5"), "0.87758256189037271611628158260382965199164519710974"); CHECK_PRECISE(CMath::cos("0.6"), "0.82533561490967829724095249895537603887809103918847"); CHECK_PRECISE(CMath::cos("0.7"), "0.76484218728448842625585999019186490926821055037370"); CHECK_PRECISE(CMath::cos("0.8"), "0.69670670934716542092074998164232492610178601370806"); CHECK_PRECISE(CMath::cos("0.9"), "0.62160996827066445648471615140713350872176136659124"); CHECK_PRECISE(CMath::cos("1.0"), "0.54030230586813971740093660744297660373231042061792"); CHECK_PRECISE(CMath::cos("2.0"), "-0.41614683654714238699756822950076218976600077107554"); CHECK_PRECISE(CMath::cos("3.0"), "-0.98999249660044545727157279473126130239367909661559"); CHECK_PRECISE(CMath::cos("4.0"), "-0.65364362086361191463916818309775038142413359664622"); CHECK_PRECISE(CMath::cos("1e22"), "0.52321478539513894549759447338470949214091997243939"); CHECK(CMath::tan("NaN"), "NaN"); CHECK(CMath::tan(PI/2), "NaN"); CHECK(CMath::tan(PI/2*3), "NaN"); CHECK(CMath::tan(PI/2*5), "NaN"); CHECK(CMath::tan(PI/2*(-3)), "NaN"); CHECK(CMath::tan(PI/2*(-5)), "NaN"); CHECK(CMath::tan(PI/1), "0"); CHECK(CMath::tan(PI*(-3)), "0"); CHECK(CMath::tan(PI*11), "0"); CHECK(CMath::tan(PI/4), "1"); CHECK(CMath::tan(PI/3), "1.73205080756887729353"); CHECK_PRECISE(CMath::tan("0.0"), "0"); CHECK_PRECISE(CMath::tan("0.1"), "0.10033467208545054505808004578111153681900480457644"); CHECK_PRECISE(CMath::tan("0.2"), "0.20271003550867248332135827164753448262687566965163"); CHECK_PRECISE(CMath::tan("0.3"), "0.30933624960962323303530367969829466725781590680046"); CHECK_PRECISE(CMath::tan("0.4"), "0.42279321873816176198163542716529033394198977271569"); CHECK_PRECISE(CMath::tan("0.5"), "0.54630248984379051325517946578028538329755172017979"); CHECK_PRECISE(CMath::tan("0.6"), "0.68413680834169231707092541746333574524265408075678"); CHECK_PRECISE(CMath::tan("0.7"), "0.84228838046307944812813500221293771718722125080420"); CHECK_PRECISE(CMath::tan("0.8"), "1.02963855705036401274636117282036528416821960677231"); CHECK_PRECISE(CMath::tan("0.9"), "1.26015821755033913713457548539574847783362583439629"); CHECK_PRECISE(CMath::tan("1.0"), "1.55740772465490223050697480745836017308725077238152"); CHECK_PRECISE(CMath::tan("2.0"), "-2.18503986326151899164330610231368254343201774622766"); CHECK_PRECISE(CMath::tan("3.0"), "-0.14254654307427780529563541053391349322609228490180"); CHECK_PRECISE(CMath::tan("4.0"), "1.15782128234957758313734241826732392311976276736714"); CHECK(CMath::cot("NaN"), "NaN"); CHECK(CMath::cot(0), "NaN"); CHECK(CMath::cot(PI), "NaN"); CHECK(CMath::cot(PI*2), "NaN"); CHECK(CMath::cot(PI*3), "NaN"); CHECK(CMath::cot(PI*(-1)), "NaN"); CHECK(CMath::cot(PI*(-2)), "NaN"); CHECK(CMath::cot(PI*(-3)), "NaN"); CHECK(CMath::cot(PI/2), "0"); CHECK(CMath::cot(PI/2*3), "0"); CHECK(CMath::cot(PI/2*5), "0"); CHECK(CMath::cot(PI/(-2)), "0"); CHECK(CMath::cot(PI/(-2)*3), "0"); CHECK(CMath::cot(PI/(-2)*5), "0"); CHECK_PRECISE(CMath::cot("0.1"), "9.96664442325923785979411268927059390763024832915145"); CHECK_PRECISE(CMath::cot("0.2"), "4.93315487558689365736801632174474118540562176228750"); CHECK_PRECISE(CMath::cot("0.3"), "3.23272814376582751371392053451257979612306377207793"); CHECK_PRECISE(CMath::cot("0.4"), "2.36522242003911058702332902504860335138937304631794"); CHECK_PRECISE(CMath::cot("0.5"), "1.83048772171245191926801943896881662375810794801613"); CHECK_PRECISE(CMath::cot("0.6"), "1.46169594707810214033930842740714256443262393263873"); CHECK_PRECISE(CMath::cot("0.7"), "1.18724183212667935367236269369115744209994867903861"); CHECK_PRECISE(CMath::cot("0.8"), "0.97121460065047441252084679894165650872369163680112"); CHECK_PRECISE(CMath::cot("0.9"), "0.79355114784231712550449309982343541572162687887550"); CHECK_PRECISE(CMath::cot("1.0"), "0.64209261593433070300641998659426562023027811391817"); CHECK_PRECISE(CMath::cot("2.0"), "-0.45765755436028576375027741043204727642848632923167"); CHECK_PRECISE(CMath::cot("3.0"), "-7.01525255143453346942855137952647657829310335209635"); CHECK_PRECISE(CMath::cot("4.0"), "0.86369115445061661394651434594081763350176570849799"); CHECK(CMath::sec("NaN"), "NaN"); CHECK(CMath::sec(0), "1"); CHECK(CMath::sec(PI), "-1"); CHECK(CMath::sec(PI*2), "1"); CHECK(CMath::sec(PI*3), "-1"); CHECK(CMath::sec(PI*(-1)), "-1"); CHECK(CMath::sec(PI*(-2)), "1"); CHECK(CMath::sec(PI*(-3)), "-1"); CHECK(CMath::sec(PI/2), "NaN"); CHECK(CMath::sec(PI/2*3), "NaN"); CHECK(CMath::sec(PI/2*5), "NaN"); CHECK(CMath::sec(PI/(-2)), "NaN"); CHECK(CMath::sec(PI/(-2)*3), "NaN"); CHECK(CMath::sec(PI/(-2)*5), "NaN"); CHECK_PRECISE(CMath::sec("0.1"), "1.00502091840045542846511410131163581939665289709269"); CHECK_PRECISE(CMath::sec("0.2"), "1.02033884494119268979243277684919018946197757380999"); CHECK_PRECISE(CMath::sec("0.3"), "1.04675160153808560093279084558703692841456893499328"); CHECK_PRECISE(CMath::sec("0.4"), "1.08570442838323870311392995515876310121797526730283"); CHECK_PRECISE(CMath::sec("0.5"), "1.13949392732454912231332776820494992842372524604900"); CHECK_PRECISE(CMath::sec("0.6"), "1.21162831451231670461455512137241473057527998567989"); CHECK_PRECISE(CMath::sec("0.7"), "1.30745925973359386987467283530531145422836345495873"); CHECK_PRECISE(CMath::sec("0.8"), "1.43532419967223980049695240816284402319218304405383"); CHECK_PRECISE(CMath::sec("0.9"), "1.60872581046604951302401286230639310432053967212693"); CHECK_PRECISE(CMath::sec("1.0"), "1.85081571768092561791175324139865019347039665509401"); CHECK_PRECISE(CMath::sec("2.0"), "-2.40299796172238098975460040142006622624512109315453"); CHECK_PRECISE(CMath::sec("3.0"), "-1.01010866590799375130303648146319295518501902819060"); CHECK_PRECISE(CMath::sec("4.0"), "-1.52988565646639757462951092293735504703880002436905"); CHECK(CMath::csc("NaN"), "NaN"); CHECK(CMath::csc(0), "NaN"); CHECK(CMath::csc(PI), "NaN"); CHECK(CMath::csc(PI*2), "NaN"); CHECK(CMath::csc(PI*3), "NaN"); CHECK(CMath::csc(PI*(-1)), "NaN"); CHECK(CMath::csc(PI*(-2)), "NaN"); CHECK(CMath::csc(PI*(-3)), "NaN"); CHECK(CMath::csc(PI/2), "1"); CHECK(CMath::csc(PI/2*3), "-1"); CHECK(CMath::csc(PI/2*5), "1"); CHECK(CMath::csc(PI/(-2)), "-1"); CHECK(CMath::csc(PI/(-2)*3), "1"); CHECK(CMath::csc(PI/(-2)*5), "-1"); CHECK_PRECISE(CMath::csc("0.1"), "10.01668613163477664870635254208068373689462246452006"); CHECK_PRECISE(CMath::csc("0.2"), "5.03348954767234420242609636752585272222462656686394"); CHECK_PRECISE(CMath::csc("0.3"), "3.38386336182412258496047655147742034395467222595556"); CHECK_PRECISE(CMath::csc("0.4"), "2.56793245554778307034468729669613783401624871596957"); CHECK_PRECISE(CMath::csc("0.5"), "2.08582964293348818577250167545929030196230958681696"); CHECK_PRECISE(CMath::csc("0.6"), "1.77103219668772537337461210710543723169043983943920"); CHECK_PRECISE(CMath::csc("0.7"), "1.55227032695710391198997364095492783063640855362864"); CHECK_PRECISE(CMath::csc("0.8"), "1.39400781938863617450248222610694684266568140951681"); CHECK_PRECISE(CMath::csc("0.9"), "1.27660621345889549601564565223201364314354454128779"); CHECK_PRECISE(CMath::csc("1.0"), "1.18839510577812121626159945237455100352782983409796"); CHECK_PRECISE(CMath::csc("2.0"), "1.09975017029461646675669739702631289665876444314985"); CHECK_PRECISE(CMath::csc("3.0"), "7.08616739573718591821753227246127986736644022513951"); CHECK_PRECISE(CMath::csc("4.0"), "-1.32134870881090237769679175637286490993025203772967"); CHECK(CMath::arctan("NaN"), "NaN"); CHECK(CMath::arctan("0.10033467208545054505808004578111153681900480457644"), "0.1"); CHECK(CMath::arctan("0.20271003550867248332135827164753448262687566965163"), "0.2"); CHECK(CMath::arctan("0.30933624960962323303530367969829466725781590680046"), "0.3"); CHECK(CMath::arctan("0.42279321873816176198163542716529033394198977271569"), "0.4"); CHECK(CMath::arctan("0.54630248984379051325517946578028538329755172017979"), "0.5"); CHECK(CMath::arctan("0.68413680834169231707092541746333574524265408075678"), "0.6"); CHECK(CMath::arctan("0.84228838046307944812813500221293771718722125080420"), "0.7"); CHECK(CMath::arctan("1.02963855705036401274636117282036528416821960677231"), "0.8"); CHECK(CMath::arctan("1.26015821755033913713457548539574847783362583439629"), "0.9"); CHECK(CMath::arctan("1.55740772465490223050697480745836017308725077238152"), "1"); CHECK_PRECISE(CMath::arctan("0.0"), "0"); CHECK_PRECISE(CMath::arctan("0.1"), "0.09966865249116202737844611987802059024327832250431"); CHECK_PRECISE(CMath::arctan("0.2"), "0.19739555984988075837004976519479029344758510378785"); CHECK_PRECISE(CMath::arctan("0.3"), "0.29145679447786709199560462143289119350316759901207"); CHECK_PRECISE(CMath::arctan("0.4"), "0.38050637711236488630358791681043310449740571365810"); CHECK_PRECISE(CMath::arctan("0.5"), "0.46364760900080611621425623146121440202853705428612"); CHECK_PRECISE(CMath::arctan("0.6"), "0.54041950027058415544357836460859991013514825146259"); CHECK_PRECISE(CMath::arctan("1.0"), "0.78539816339744830961566084581987572104929234984378"); CHECK_PRECISE(CMath::arctan("-0.1"), "-0.09966865249116202737844611987802059024327832250431"); CHECK_PRECISE(CMath::arctan("-0.2"), "-0.19739555984988075837004976519479029344758510378785"); CHECK_PRECISE(CMath::arctan("-0.3"), "-0.29145679447786709199560462143289119350316759901207"); CHECK_PRECISE(CMath::arctan("-0.4"), "-0.38050637711236488630358791681043310449740571365810"); CHECK_PRECISE(CMath::arctan("-0.5"), "-0.46364760900080611621425623146121440202853705428612"); CHECK_PRECISE(CMath::arctan("-0.6"), "-0.54041950027058415544357836460859991013514825146259"); CHECK_PRECISE(CMath::arctan("-1.0"), "-0.78539816339744830961566084581987572104929234984378"); CHECK(CMath::arcsin("NaN"), "NaN"); CHECK(CMath::arcsin("-1"), "-1.57079632679489661923"); CHECK(CMath::arcsin("0"), "0"); CHECK(CMath::arcsin("1"), "1.57079632679489661923"); CHECK(CMath::arcsin("0.09983341664682815230681419841062202698991538801798"), "0.1"); CHECK(CMath::arcsin("0.19866933079506121545941262711838975037020672954021"), "0.2"); CHECK(CMath::arcsin("0.29552020666133957510532074568502737367783211174262"), "0.3"); CHECK(CMath::arcsin("0.38941834230865049166631175679570526459306018344396"), "0.4"); CHECK(CMath::arcsin("0.47942553860420300027328793521557138808180336794060"), "0.5"); CHECK(CMath::arcsin("0.56464247339503535720094544565865790710988808499415"), "0.6"); CHECK(CMath::arcsin("0.64421768723769105367261435139872018306581384457369"), "0.7"); CHECK(CMath::arcsin("0.71735609089952276162717461058138536619278523779142"), "0.8"); CHECK_PRECISE(CMath::arcsin("0.0"), "0"); CHECK_PRECISE(CMath::arcsin("0.1"), "0.10016742116155979634552317945269331856867597222963"); CHECK_PRECISE(CMath::arcsin("0.2"), "0.20135792079033079145512555221762341024003808140223"); CHECK_PRECISE(CMath::arcsin("0.3"), "0.30469265401539750797200296122752916695456003170678"); CHECK_PRECISE(CMath::arcsin("0.4"), "0.41151684606748801938473789761733560485570113512703"); CHECK(CMath::arccos("NaN"), "NaN"); CHECK(CMath::arccos("-1"), "3.14159265358979323846"); CHECK(CMath::arccos("0"), "1.57079632679489661923"); CHECK(CMath::arccos("1"), "0"); CHECK_PRECISE(CMath::arccos("0.1"), "1.47062890563333682288579851218705812352990872745792"); CHECK_PRECISE(CMath::arccos("0.2"), "1.36943840600456582777619613942212803185854661828532"); CHECK_PRECISE(CMath::arccos("0.3"), "1.26610367277949911125931873041222227514402466798078"); CHECK_PRECISE(CMath::arccos("0.4"), "1.15927948072740859984658379402241583724288356456053"); CHECK(CMath::sinh("NaN"), "NaN"); CHECK_PRECISE(CMath::sinh("0.1"), "0.10016675001984402582372938352190502351492091687856"); CHECK_PRECISE(CMath::sinh("0.2"), "0.20133600254109398762556824301031737297449484262574"); CHECK_PRECISE(CMath::sinh("0.3"), "0.30452029344714261895843526700509522909802423268018"); CHECK_PRECISE(CMath::sinh("0.4"), "0.41075232580281550854021001384469810435315092436331"); CHECK_PRECISE(CMath::sinh("0.5"), "0.52109530549374736162242562641149155910592898261148"); CHECK_PRECISE(CMath::sinh("0.6"), "0.63665358214824127112345437546514831902496342592790"); CHECK_PRECISE(CMath::sinh("0.7"), "0.75858370183953350345987464759276815415493761421703"); CHECK_PRECISE(CMath::sinh("0.8"), "0.88810598218762300657471757318975698055970959688815"); CHECK_PRECISE(CMath::sinh("0.9"), "1.02651672570817527595833616197842235379403446513485"); CHECK_PRECISE(CMath::sinh("1.0"), "1.17520119364380145688238185059560081515571798133410"); CHECK(CMath::cosh("NaN"), "NaN"); CHECK_PRECISE(CMath::cosh("0.1"), "1.00500416805580359898797844296834164470962627785896"); CHECK_PRECISE(CMath::cosh("0.2"), "1.02006675561907584629550375162935679733308609889476"); CHECK_PRECISE(CMath::cosh("0.3"), "1.04533851412886048502530904632291210128027546467919"); CHECK_PRECISE(CMath::cosh("0.4"), "1.08107237183845480928464293899252417629013184957412"); CHECK_PRECISE(CMath::cosh("0.5"), "1.12762596520638078522622516140267201254784711809867"); CHECK_PRECISE(CMath::cosh("0.6"), "1.18546521824226770375191329269771619435727538261853"); CHECK_PRECISE(CMath::cosh("0.7"), "1.25516900563094301816467474099029711586260477992884"); CHECK_PRECISE(CMath::cosh("0.8"), "1.33743494630484459800481995820531977649392453816033"); CHECK_PRECISE(CMath::cosh("0.9"), "1.43308638544877438784179040162404834162773784130523"); CHECK_PRECISE(CMath::cosh("1.0"), "1.54308063481524377847790562075706168260152911236586"); CHECK(CMath::tanh("NaN"), "NaN"); CHECK_PRECISE(CMath::tanh("0.1"), "0.09966799462495581711830508367835218353896209577673"); CHECK_PRECISE(CMath::tanh("0.2"), "0.19737532022490400073815731881101566838937268384235"); CHECK_PRECISE(CMath::tanh("0.3"), "0.29131261245159090581822127282376592815359680491761"); CHECK_PRECISE(CMath::tanh("0.4"), "0.37994896225522488526774812389687331051318437437140"); CHECK_PRECISE(CMath::tanh("0.5"), "0.46211715726000975850231848364367254873028928033011"); CHECK_PRECISE(CMath::tanh("0.6"), "0.53704956699803528586182530492689670598284198771923"); CHECK_PRECISE(CMath::tanh("0.7"), "0.60436777711716349630868718310382647501556664741686"); CHECK_PRECISE(CMath::tanh("0.8"), "0.66403677026784896368484465640024285007465529270892"); CHECK_PRECISE(CMath::tanh("0.9"), "0.71629787019902442081144378305809486317486516460076"); CHECK_PRECISE(CMath::tanh("1.0"), "0.76159415595576488811945828260479359041276859725794"); CHECK(CMath::arcosh("NaN"), "NaN"); CHECK_PRECISE(CMath::arcosh("1.00500416805580359898797844296834164470962627785896"), "0.10000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::arcosh("1.02006675561907584629550375162935679733308609889476"), "0.20000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::arcosh("1.04533851412886048502530904632291210128027546467919"), "0.30000000000000000000000000000000000000000000000001"); CHECK_PRECISE(CMath::arcosh("1.08107237183845480928464293899252417629013184957412"), "0.40000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::arcosh("1.12762596520638078522622516140267201254784711809867"), "0.50000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::arcosh("1.18546521824226770375191329269771619435727538261853"), "0.60000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::arcosh("1.25516900563094301816467474099029711586260477992884"), "0.70000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::arcosh("1.33743494630484459800481995820531977649392453816033"), "0.79999999999999999999999999999999999999999999999999"); CHECK_PRECISE(CMath::arcosh("1.43308638544877438784179040162404834162773784130523"), "0.90000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::arcosh("1.54308063481524377847790562075706168260152911236586"), "1.00000000000000000000000000000000000000000000000000"); CHECK(CMath::artanh("NaN"), "NaN"); CHECK_PRECISE(CMath::artanh("0.09966799462495581711830508367835218353896209577673"), "0.10000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::artanh("0.19737532022490400073815731881101566838937268384235"), "0.20000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::artanh("0.29131261245159090581822127282376592815359680491761"), "0.30000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::artanh("0.37994896225522488526774812389687331051318437437140"), "0.40000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::artanh("0.46211715726000975850231848364367254873028928033011"), "0.50000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::artanh("0.53704956699803528586182530492689670598284198771923"), "0.60000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::artanh("0.60436777711716349630868718310382647501556664741686"), "0.70000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::artanh("0.66403677026784896368484465640024285007465529270892"), "0.80000000000000000000000000000000000000000000000001"); CHECK_PRECISE(CMath::artanh("0.71629787019902442081144378305809486317486516460076"), "0.90000000000000000000000000000000000000000000000000"); CHECK_PRECISE(CMath::artanh("0.76159415595576488811945828260479359041276859725794"), "1.00000000000000000000000000000000000000000000000001"); CHECK(CMath::decodeIeee754("NaN", "NaN", "NaN"), "NaN"); CHECK(CMath::decodeIeee754("1", "-1", "1"), "NaN"); CHECK(CMath::decodeIeee754("1", "1", "0"), "NaN"); CHECK(CMath::decodeIeee754("1", "1.5", "1"), "NaN"); CHECK(CMath::decodeIeee754("0", "5", "10"), "0"); CHECK(CMath::decodeIeee754("0x7ff00000", "8", "23"), "NaN"); CHECK(CMath::decodeIeee754("0xffc0feed", "8", "23"), "NaN"); CHECK(CMath::decodeIeee754("0x7fffffff", "8", "23"), "NaN"); CHECK(CMath::decodeIeee754("0x8000", "5", "10"), "0"); CHECK_PRECISE(CMath::decodeIeee754("0x00800000", "8", "23"), "0.00000000000000000000000000000000000001175494350822"); CHECK_PRECISE(CMath::decodeIeee754("0x006f6eed", "8", "23"), "0.00000000000000000000000000000000000001023353274603"); CHECK(CMath::decodeIeee754("0x41200000", "8", "23"), "10"); CHECK(CMath::decodeIeee754("0xc1200000", "8", "23"), "-10"); CHECK(CMath::decodeIeee754("0x3fc00000", "8", "23"), "1.5"); CHECK_PRECISE(CMath::decodeIeee754("0x3dcccccd", "8", "23"), "0.10000000149011611938476562500000000000000000000000"); CHECK(CMath::decodeIeee754("0x7f7fffff", "8", "23"), "340282346638528859811704183484516925440"); CHECK(CMath::decodeIeee754("0x418100b9", "8", "23"), "16.1253528594970703125"); CHECK(CMath::decodeIeee754("0x4024000000000000", "11", "52"), "10"); CHECK(CMath::decodeIeee754("0x01", "4", "3", "-2"), "1"); CHECK(CMath::decodeIeee754("0x07", "4", "3", "-2"), "7"); CHECK(CMath::decodeIeee754("0x08", "4", "3", "-2"), "8"); CHECK(CMath::decodeIeee754("0xf1", "4", "3", "-2"), "-73728"); CHECK(CMath::decodeIeee754("0x77", "4", "3", "-2"), "122880"); CHECK(CMath::decodeIeee754("0x5", "2", "1"), "3"); CHECK_PRECISE(CMath::decodeIeee754("0x3ffd5555555555555555555555555555", "15", "112"), "0.33333333333333333333333333333333331728391713010637"); CHECK(CMath::encodeIeee754("NaN", "NaN", "NaN"), "NaN"); CHECK(CMath::encodeIeee754("1", "NaN", "NaN"), "NaN"); CHECK(CMath::encodeIeee754("1", "-1", "1"), "NaN"); CHECK(CMath::encodeIeee754("1", "1", "0"), "NaN"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("NaN", "5", "10"), "0x7FFF"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("NaN", "11", "52"), "0x7FFFFFFFFFFFFFFF"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("0", "5", "10"), "0"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("1.17549435E-38", "8", "23"), "0x800000"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("10", "8", "23"), "0x41200000"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("-10", "8", "23"), "0xC1200000"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("1.5", "8", "23"), "0x3FC00000"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("0.999755859375", "5", "10"), "0x3C00"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("340282346638528859811704183484516925440","8", "23"), "0x7F7FFFFF"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("9999999999999999999999999999999999", "5", "10"), "0x7C00"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("-0.1", "8", "23"), "0xBDCCCCCD"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("-0.1", "11", "52"), "0xBFB999999999999A"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("16.1253528594970703125", "8", "23"), "0x418100B9"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("1", "4", "3", "-2"), "0x1"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("7", "4", "3", "-2"), "0x7"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("8", "4", "3", "-2"), "0x8"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("-73728", "4", "3", "-2"), "0xF1"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("122880", "4", "3", "-2"), "0x77"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("3", "2", "1"), "0x5"); CHECK_FORMAT(Format::Hexadecimal() + Format::Fixed(), CMath::encodeIeee754("1.5", "2", "1"), "0x3"); } void test_branches() { /* Test behavior of complex functions relative to branch cuts */ /* artanh */ /* Branch cuts: ]-inf;-1], [1;+inf[ */ CHECK(CMath::artanh("1.5-0.0000001j"), "0.8047189562170405873-1.57079624679489661923j"); CHECK(CMath::artanh("1.5"), "0.8047189562170501873-1.57079632679489661923j"); CHECK(CMath::artanh("1.5+0.0000001j"), "0.8047189562170405873+1.57079624679489661923j"); CHECK(CMath::artanh("-1.5-0.0000001j"), "-0.8047189562170405873-1.57079624679489661923j"); CHECK(CMath::artanh("-1.5"), "-0.8047189562170501873+1.57079632679489661923j"); CHECK(CMath::artanh("-1.5+0.0000001j"), "-0.8047189562170405873+1.57079624679489661923j"); /* arcosh */ /* Branch cut: ]-inf;-1] */ CHECK(CMath::arcosh("-1.5-0.0000001j"), "0.96242365011921226156-3.14159256414707413847j"); CHECK(CMath::arcosh("-1.5"), "0.962423650119206895+3.14159265358979323846j"); CHECK(CMath::arcosh("-1.5+0.0000001j"), "0.96242365011921226156+3.14159256414707413847j"); CHECK(CMath::arcosh("1.5-0.0000001j"), "0.96242365011921226156-0.00000008944271909999j"); CHECK(CMath::arcosh("1.5"), "0.962423650119206895"); CHECK(CMath::arcosh("1.5+0.0000001j"), "0.96242365011921226156+0.00000008944271909999j"); /* arsinh */ /* Branch cuts: ]-j*inf;-j], ]j;j*inf] */ CHECK(CMath::arsinh("-0.0000001+1.5j"), "-0.96242365011921226156+1.57079623735217751924j"); CHECK(CMath::arsinh("1.5j"), "0.962423650119206895+1.57079632679489661923j"); CHECK(CMath::arsinh("0.0000001+1.5j"), "0.96242365011921226156+1.57079623735217751924j"); CHECK(CMath::arsinh("-0.0000001-1.5j"), "-0.96242365011921226156-1.57079623735217751924j"); CHECK(CMath::arsinh("-1.5j"), "-0.962423650119206895-1.57079632679489661923j"); CHECK(CMath::arsinh("0.0000001+1.5j"), "0.96242365011921226156+1.57079623735217751924j"); } int main(int, char**) { cmath_total_tests = 0; cmath_failed_tests = 0; floatmath_init(); PI = CMath::pi(); test_create(); test_format(); test_op(); test_functions(); test_branches(); if (!cmath_failed_tests) return 0; cout << cmath_total_tests << " total, " << cmath_failed_tests << " failed, " << cmath_new_failed_tests << " new" << endl; return cmath_new_failed_tests; } heldercorreia-speedcrunch-e7ca37f/src/tests/testcommon.h000066400000000000000000000013111526573132500236230ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2016 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include #include using namespace std; void DisplayErrorOnMismatch(const char* file, int line, const char* msg, const std::string& result, const char* expected, int& failed, int& newFailed, int issue = 0) { if (result != expected) { ++failed; cerr << file << "[" << line << "]\t" << msg; if (issue) cerr << "\t[ISSUE " << issue << "]"; else { cerr << "\t[NEW]"; ++newFailed; } cerr << endl; cerr << "\tResult : " << result << endl << "\tExpected : " << expected << endl; } } heldercorreia-speedcrunch-e7ca37f/src/tests/testdisplayui.cpp000066400000000000000000001352001526573132500246760ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" #include "core/numberformatter.h" using namespace MainWindowTestHelpers; class TestDisplayUi : public QObject { Q_OBJECT private slots: void history_reuse_respects_input_adjustments_data(); void history_reuse_respects_input_adjustments(); void user_definition_comments_survive_creation_and_editing_data(); void user_definition_comments_survive_creation_and_editing(); void result_display_keeps_comments_literal_data(); void result_display_keeps_comments_literal(); void initTestCase(); void init() { UiTestFixture::resetSettings(); } void result_display_insets_viewport_horizontally(); void result_display_scrollbar_hover_keeps_viewport_width_stable(); void result_display_hover_action_badges_use_hover_and_primary_colors_data(); void result_display_hover_action_badges_use_hover_and_primary_colors(); void result_display_hover_action_badges_trigger_when_clicked(); void result_display_scroll_to_bottom_button_uses_custom_tooltip(); void result_display_context_menu_hides_main_menu_when_menu_bar_visible(); void result_display_copies_entire_calculation_data(); void result_display_copies_entire_calculation(); void result_display_copies_generated_simplification_and_formats(); void result_display_preserves_unreduced_quotients_data(); void result_display_preserves_unreduced_quotients(); void result_display_reduces_combinable_quotient_factors_data(); void result_display_reduces_combinable_quotient_factors(); void result_display_copies_calculation_as_single_line_data(); void result_display_copies_calculation_as_single_line(); void result_display_copies_expression_and_result_data(); void result_display_copies_expression_and_result(); void result_display_context_menu_tracks_session_state_data(); void result_display_context_menu_tracks_session_state(); void result_display_context_menu_copies_selection(); void result_display_remove_menu_targets_clicked_calculation(); }; void TestDisplayUi::history_reuse_respects_input_adjustments_data() { QTest::addColumn("adjustments"); QTest::addColumn("source"); for (bool adjustments : {false, true}) { for (int source = 0; source < 5; ++source) { QTest::newRow(qPrintable(QStringLiteral("%1-%2").arg(adjustments).arg(source))) << adjustments << source; } } } void TestDisplayUi::history_reuse_respects_input_adjustments() { QFETCH(bool, adjustments); QFETCH(int, source); MainWindowStateGuard guard; Settings::instance()->autoCalc = false; Settings::instance()->historyDockVisible = true; MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); ResultDisplay* display = window.findChild(); QVERIFY(display); Editor* editor = editorForDisplay(display); QVERIFY(editor); editor->setAutoCompletionEnabled(false); const QString stored = QString::fromUtf8("2³ × 3 ? keep ² × ->\t"); editor->setText(stored); QVERIFY(QMetaObject::invokeMethod(&window, "evaluateEditorExpression")); const Session* session = display->session(); QCOMPARE(session->historySize(), 1); const QString rendered = display->toPlainText(); QAction* action = window.findChild(QStringLiteral("AutomaticInputAdjustmentsAction")); QVERIFY(action); action->setChecked(adjustments); QCOMPARE(Settings::instance()->automaticInputAdjustments, adjustments); editor->clear(); if (source == 0 || source == 3) { if (source == 3) { QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight")); editor = editorForDisplay(display); QVERIFY(editor); } QTextCursor cursor(display->document()->firstBlock()); display->setTextCursor(cursor); const QPoint point = display->cursorRect(cursor).center(); QTest::mouseDClick(display->viewport(), Qt::LeftButton, Qt::NoModifier, point); QTest::mouseRelease(display->viewport(), Qt::LeftButton, Qt::NoModifier, point); } else if (source == 1 || source == 4) { HistoryWidget* history = window.findChild(); QVERIFY(history); QListWidget* list = history->findChild(); QVERIFY(list); QCOMPARE(list->count(), 1); if (source == 4) { editor->setText(QStringLiteral("? keep ")); editor->setCursorPosition(editor->text().size()); } QVERIFY(QMetaObject::invokeMethod(list, "itemActivated", Qt::DirectConnection, Q_ARG(QListWidgetItem*, list->item(0)))); } else { QVERIFY(QMetaObject::invokeMethod(&window, "startHistoryEntryEdit", Qt::DirectConnection, Q_ARG(int, 0))); } const QString expected = source == 4 ? QStringLiteral("? keep ") + stored : adjustments ? stored : QString::fromUtf8("2^3 * 3 ? keep ² × ->\t"); QCOMPARE(editor->text(), expected); QCOMPARE(session->historyEntryAtRef(0).expr(), stored); QCOMPARE(display->toPlainText(), rendered); if (source != 2) { editor->undo(); QCOMPARE(editor->text(), source == 4 ? QStringLiteral("? keep ") : QString()); } else if (!adjustments) { editor->selectAll(); QTest::keyClicks(editor, "2^4"); QCOMPARE(editor->text(), QStringLiteral("2^4")); QVERIFY(QMetaObject::invokeMethod(&window, "evaluateEditorExpression")); QCOMPARE(session->historySize(), 1); QCOMPARE(session->historyEntryAtRef(0).expr(), QStringLiteral("2^4")); QCOMPARE(NumberFormatter::format(session->historyEntryAtRef(0).result()), QStringLiteral("16")); } } void TestDisplayUi::user_definition_comments_survive_creation_and_editing_data() { QTest::addColumn("definition"); QTest::addColumn("dockName"); QTest::addColumn("paste"); for (bool paste : {false, true}) { const QByteArray mode = paste ? "paste" : "type"; QTest::newRow(QByteArray("variable-").append(mode).constData()) << QStringLiteral("examplevar = 4") << QStringLiteral("VariablesDock") << paste; QTest::newRow(QByteArray("function-").append(mode).constData()) << QStringLiteral("examplefunc(x) = x*2") << QStringLiteral("UserFunctionsDock") << paste; QTest::newRow(QByteArray("unit-").append(mode).constData()) << QStringLiteral("[exampleunit] = 4[m]") << QStringLiteral("UserUnitsDock") << paste; } } void TestDisplayUi::user_definition_comments_survive_creation_and_editing() { QFETCH(QString, definition); QFETCH(QString, dockName); QFETCH(bool, paste); MainWindowStateGuard guard; Settings* settings = Settings::instance(); settings->variablesDockVisible = true; settings->userFunctionsDockVisible = true; settings->userUnitsDockVisible = true; settings->leaveLastExpression = false; MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); ResultDisplay* display = window.findChild(); QDockWidget* dock = window.findChild(dockName); QVERIFY(editor); QVERIFY(display); QVERIFY(dock); dock->show(); dock->raise(); QWidget* widget = dock->widget(); QTreeWidget* tree = widget->findChild(); QVERIFY(tree); const QString comment = QStringLiteral("2*2 pi sqrt(4) 10000 [m * s^2] -> [km] 'note' ? 3/2-1"); const QString suffix = QStringLiteral(" ? ") + comment; const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([&]() { QApplication::clipboard()->setText(oldClipboard); }); editor->clear(); if (paste) { QApplication::clipboard()->setText(definition + suffix); editor->paste(); } else { editor->setText(definition); editor->setCursorPosition(editor->text().size()); QTest::keyClicks(editor, QStringLiteral("?") + comment); } QVERIFY2(editor->text().endsWith(suffix), qPrintable(editor->text())); QVERIFY(QMetaObject::invokeMethod(&window, "evaluateEditorExpression")); for (int edit = 0; edit < 2; ++edit) { QVERIFY(QMetaObject::invokeMethod(widget, "updateList")); QTreeWidgetItem* item = nullptr; for (int i = 0; i < tree->topLevelItemCount(); ++i) { if (tree->topLevelItem(i)->text(0).startsWith(QStringLiteral("example"))) item = tree->topLevelItem(i); } QVERIFY(item); const QString expectedComment = comment + (edit ? QStringLiteral(" 5*5") : QString()); QCOMPARE(item->text(2), expectedComment); QVERIFY(!item->text(1).contains(QLatin1Char('?'))); QVERIFY2(display->toPlainText().contains(QStringLiteral(" ? ") + expectedComment), qPrintable(display->toPlainText())); display->setSession(display->session()); QVERIFY(display->toPlainText().contains(QStringLiteral(" ? ") + expectedComment)); tree->setCurrentItem(item); item->setSelected(true); editor->clear(); QVERIFY(QMetaObject::invokeMethod(widget, "editItem")); QVERIFY2(editor->text().endsWith(QStringLiteral(" ? ") + expectedComment), qPrintable(editor->text())); if (edit == 0) { editor->setCursorPosition(editor->text().size()); editor->insert(QStringLiteral(" 5*5")); QVERIFY(QMetaObject::invokeMethod(&window, "evaluateEditorExpression")); } } } void TestDisplayUi::result_display_keeps_comments_literal_data() { QTest::addColumn("expression"); QTest::newRow("arithmetic") << QStringLiteral("2*2"); QTest::newRow("unit") << QStringLiteral("2*[m]"); QTest::newRow("conversion") << QStringLiteral("2[m] -> [cm]"); QTest::newRow("angle") << QStringLiteral("1°"); QTest::newRow("angle-conversion") << QStringLiteral("1° in [rad]"); QTest::newRow("list") << QStringLiteral("{2*2;3}"); QTest::newRow("comment-only") << QString(); } void TestDisplayUi::result_display_keeps_comments_literal() { QFETCH(QString, expression); const QString comment = QStringLiteral("2*2 pi sqrt(4) 10000 [m * s^2] -> [km] 'note' ? 3/2-1\tµ"); const QString source = expression + QStringLiteral(" ? ") + comment; Session session; Evaluator* evaluator = session.evaluator(); evaluator->setExpression(source); Quantity result = evaluator->evalUpdateAns(); QVERIFY2(evaluator->error().isEmpty(), qPrintable(evaluator->error())); const QString interpreted = evaluator->interpretedExpression(); if (!interpreted.isEmpty()) QCOMPARE(interpreted.mid(interpreted.indexOf(QLatin1Char('?')) + 2), comment); for (const QString& displayInterpreted : {QString(), interpreted}) { ResultDisplay display; display.setSession(&session); display.append(source, result, displayInterpreted); const QString line = display.document()->firstBlock().text(); QCOMPARE(line.mid(line.indexOf(QLatin1Char('?')) + 2), comment); } } void TestDisplayUi::initTestCase() { // Fail before a file-operation test can open an unhandled error dialog. for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) { QVERIFY2(QDir().mkpath(path), qPrintable(QStringLiteral("Cannot create test storage at %1").arg(path))); QTemporaryFile probe(QDir(path).filePath(QStringLiteral("storage-probe-XXXXXX"))); QVERIFY2(probe.open(), qPrintable(QStringLiteral("Cannot write test storage at %1: %2") .arg(path, probe.errorString()))); } } void TestDisplayUi::result_display_insets_viewport_horizontally() { ResultDisplay display; display.resize(320, 200); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); const QRect viewportGeometry = display.viewport()->geometry(); QVERIFY(viewportGeometry.left() > 0); QVERIFY(display.width() - viewportGeometry.right() - 1 > 0); } void TestDisplayUi::result_display_scrollbar_hover_keeps_viewport_width_stable() { ResultDisplay display; display.resize(360, 160); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); Quantity value; for (int i = 0; i < 40; ++i) display.append(QStringLiteral("123456789012345678901234567890"), value); QScrollBar* scrollBar = display.verticalScrollBar(); QVERIFY(scrollBar->maximum() > scrollBar->minimum()); const QRect initialViewportGeometry = display.viewport()->geometry(); QEvent enterEvent(QEvent::Enter); QCoreApplication::sendEvent(scrollBar, &enterEvent); QCOMPARE(display.viewport()->geometry(), initialViewportGeometry); QEvent leaveEvent(QEvent::Leave); QCoreApplication::sendEvent(scrollBar, &leaveEvent); QCOMPARE(display.viewport()->geometry(), initialViewportGeometry); } void TestDisplayUi::result_display_hover_action_badges_use_hover_and_primary_colors_data() { QTest::addColumn("fontPixelSize"); QTest::newRow("default-font") << 0; QTest::newRow("small-badges") << 12; QTest::newRow("even-badge-diameter") << 13; } void TestDisplayUi::result_display_hover_action_badges_use_hover_and_primary_colors() { QFETCH(int, fontPixelSize); BadgeTestResultDisplay display; if (fontPixelSize > 0) { QFont font = display.font(); font.setPixelSize(fontPixelSize); display.setFont(font); } const QColor resultBackground(QStringLiteral("#101820")); const QColor hoverColor(QStringLiteral("#2a3038")); const QColor primaryColor(QStringLiteral("#79b8ff")); const QColor popupBackground(QStringLiteral("#45465f")); const QColor popupForeground(QStringLiteral("#f0ecff")); const QColor popupOutline(QStringLiteral("#696a80")); const QColor expectedBadgeFill = aaForegroundForBackground(hoverColor, 7.0); display.setThemeSurfaceColor(resultBackground); display.setThemeToolTipColors(popupBackground, popupForeground, popupOutline); display.setThemeInteractionColors(hoverColor, primaryColor, QColor(QStringLiteral("#111111")), QColor(QStringLiteral("#eeeeee")), QColor(QStringLiteral("#222222")), QColor(QStringLiteral("#ffffff"))); Session session; session.addHistoryEntry(HistoryEntry(QStringLiteral("120 / 8"), Quantity(15))); display.setSession(&session); display.resize(420, 120); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); const QRect copyRect = display.copyBadgeRect(0); const QRect editRect = display.editBadgeRect(0); QVERIFY(copyRect.isValid()); QVERIFY(editRect.isValid()); // A preceding data row can leave the cursor at the target position. QTest::mouseMove(display.viewport(), QPoint(1, 1)); QTest::mouseMove(display.viewport(), QPoint(18, copyRect.center().y())); QTRY_VERIFY(display.viewport()->cursor().shape() != Qt::PointingHandCursor); QCOMPARE(display.viewport()->toolTip(), QString()); QImage rowHoverImage = display.viewport()->grab().toImage(); // The center can lie on a copy-glyph stroke at some font sizes. QVERIFY2(firstPixelMatchingColor(rowHoverImage, imageRectForWidgetRect(rowHoverImage, copyRect), expectedBadgeFill, 3) != QPoint(-1, -1), qPrintable(QStringLiteral("badge fill did not use %1") .arg(expectedBadgeFill.name()))); const QPoint defaultIconPixel = firstPixelMatchingColorBlend(rowHoverImage, imageRectForWidgetRect(rowHoverImage, copyRect), hoverColor, expectedBadgeFill, 10); QVERIFY2(defaultIconPixel.x() >= 0, qPrintable(QStringLiteral("copy glyph did not use hover color %1") .arg(hoverColor.name()))); QTest::mouseMove(display.viewport(), copyRect.center()); QTRY_COMPARE(display.viewport()->cursor().shape(), Qt::PointingHandCursor); QCOMPARE(display.viewport()->toolTip(), QString()); QFrame* actionPopup = display.findChild(QStringLiteral("resultActionPopup")); QTRY_VERIFY(actionPopup != nullptr && actionPopup->isVisible()); QLabel* actionPopupLabel = actionPopup->findChild(QStringLiteral("resultActionPopupLabel")); QVERIFY(actionPopupLabel != nullptr); QCOMPARE(actionPopupLabel->text(), QStringLiteral("Copy result")); QVERIFY(actionPopup->styleSheet().contains(popupBackground.name())); QVERIFY(actionPopup->styleSheet().contains(popupForeground.name())); QVERIFY(actionPopup->styleSheet().contains(QStringLiteral("border: %1px solid %2") .arg(UiConfig::PopupOutlineStrokeWidth) .arg(popupOutline.name()))); QVERIFY(!actionPopup->mask().isEmpty()); QVERIFY(actionPopup->testAttribute(Qt::WA_TransparentForMouseEvents)); QImage copyHoverImage = display.viewport()->grab().toImage(); const QPoint primaryIconPixel = firstPixelMatchingColorBlend(copyHoverImage, imageRectForWidgetRect(copyHoverImage, copyRect), primaryColor, expectedBadgeFill, 10); QVERIFY2(primaryIconPixel.x() >= 0, qPrintable(QStringLiteral("hovered copy glyph did not use primary color %1") .arg(primaryColor.name()))); const QPoint editHoverPixel = firstPixelMatchingColorBlend(copyHoverImage, imageRectForWidgetRect(copyHoverImage, editRect), hoverColor, expectedBadgeFill, 10); QVERIFY2(editHoverPixel.x() >= 0, qPrintable(QStringLiteral("non-hovered edit glyph did not keep hover color %1") .arg(hoverColor.name()))); QTest::mouseMove(display.viewport(), QPoint(18, copyRect.center().y())); QTRY_VERIFY(display.viewport()->cursor().shape() != Qt::PointingHandCursor); QCOMPARE(display.viewport()->toolTip(), QString()); QTRY_VERIFY(actionPopup == nullptr || !actionPopup->isVisible()); } void TestDisplayUi::result_display_copies_entire_calculation_data() { QTest::addColumn("lines"); QTest::addColumn("failed"); QTest::addColumn("precedingEntries"); QTest::newRow("simple") << QStringList({QStringLiteral("120 / 8"), QStringLiteral("= 15")}) << false << 1; QTest::newRow("simplification-and-formats") << QStringList({QStringLiteral("1:120:3600"), QStringLiteral("= 4:00:00"), QStringLiteral("= 14400 s"), QStringLiteral("= 1.44 × 10â�´ s")}) << false << 1; QTest::newRow("wrapped-unicode-and-units") << QStringList({QStringLiteral("123456789 [m] − 98765432 [m] + 1 [m] + 2 [m]"), QStringLiteral("= 24\u2009567\u2009360 m"), QStringLiteral("= 2.456736 × 10â�· m")}) << false << 1; QTest::newRow("failed") << QStringList({QStringLiteral("1 / 0")}) << true << 1; QTest::newRow("displayed-history-limit") << QStringList({QStringLiteral("120 / 8"), QStringLiteral("= 15")}) << false << 801; } void TestDisplayUi::result_display_copies_entire_calculation() { QFETCH(QStringList, lines); QFETCH(bool, failed); QFETCH(int, precedingEntries); const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([oldClipboard]() { QApplication::clipboard()->setText(oldClipboard); }); Session session; session.setHistoryLimit(0); for (int i = 0; i < precedingEntries; ++i) session.addHistoryEntry(HistoryEntry(QStringLiteral("2 + 3"), Quantity(5))); HistoryEntry entry(lines.first(), failed ? DMath::nan() : Quantity(15)); entry.setRenderedLines(lines); session.addHistoryEntry(entry); session.addHistoryEntry(HistoryEntry(QStringLiteral("7 + 8"), Quantity(15))); MenuTestResultDisplay display; display.resize(250, 350); display.setSession(&session); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); QVERIFY(display.toPlainText().contains(lines.join(QLatin1Char('\n')))); // Keep a selection in another calculation while copying the clicked one. QTextCursor selection(display.document()->firstBlock()); selection.select(QTextCursor::BlockUnderCursor); display.setTextCursor(selection); const int selectionStart = display.textCursor().selectionStart(); const int selectionEnd = display.textCursor().selectionEnd(); if (qstrcmp(QTest::currentDataTag(), "wrapped-unicode-and-units") == 0) { const QTextBlock expressionBlock = display.document()->find(lines.first()).block(); QVERIFY(expressionBlock.layout()->lineCount() > 1); } for (const QString& line : lines) { QTextCursor clickedLine = display.document()->find(line); QVERIFY(!clickedLine.isNull()); clickedLine.movePosition(QTextCursor::StartOfBlock); display.verticalScrollBar()->setValue(clickedLine.blockNumber()); QCoreApplication::processEvents(); QScopedPointer menu(display.createContextMenu(display.cursorRect(clickedLine).center())); QMenu* copyMenu = directSubmenuWithTitle(menu.data(), QStringLiteral("Copy")); QVERIFY(copyMenu != nullptr); QAction* action = directMenuActionWithText(copyMenu, QStringLiteral("Calculation")); QVERIFY(action != nullptr); QVERIFY(action->isEnabled()); QApplication::clipboard()->setText(QStringLiteral("unchanged")); action->trigger(); QCOMPARE(QApplication::clipboard()->text(), lines.join(QLatin1Char('\n'))); QCOMPARE(display.textCursor().selectionStart(), selectionStart); QCOMPARE(display.textCursor().selectionEnd(), selectionEnd); } } void TestDisplayUi::result_display_copies_generated_simplification_and_formats() { const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([oldClipboard]() { QApplication::clipboard()->setText(oldClipboard); }); Settings::instance()->simplifyResultExpressions = true; Session session; Evaluator* evaluator = session.evaluator(); const QString expression = QStringLiteral("1:120:3600"); evaluator->setExpression(expression); const Quantity value = evaluator->eval(); QVERIFY2(evaluator->error().isEmpty(), qPrintable(evaluator->error())); EvaluationContext context; context.main.fmt = 'f'; context.main.prec = 2; context.extras = {{'e', 2}, {'r', -1}}; session.addHistoryEntry(HistoryEntry(expression, value, evaluator->interpretedExpression(), context)); MenuTestResultDisplay display; display.resize(600, 350); display.setSession(&session); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); const QString expected = display.toPlainText().trimmed(); QVERIFY(expected.contains(QStringLiteral("= 4:00:00\n"))); QCOMPARE(expected.count(QLatin1Char('\n')), 4); // A later format change must not change the text copied from older lines. Settings::instance()->resultFormat = 'h'; Settings::instance()->simplifyResultExpressions = false; QScopedPointer menu(display.createContextMenu(display.cursorRect(QTextCursor(display.document())).center())); QMenu* copyMenu = directSubmenuWithTitle(menu.data(), QStringLiteral("Copy")); QVERIFY(copyMenu != nullptr); QAction* action = directMenuActionWithText(copyMenu, QStringLiteral("Calculation")); QVERIFY(action != nullptr); action->trigger(); QCOMPARE(QApplication::clipboard()->text(), expected); } void TestDisplayUi::result_display_preserves_unreduced_quotients_data() { QTest::addColumn("expression"); QTest::newRow("previous-answer") << QStringLiteral("ans/9"); QTest::newRow("decimal-denominator") << QStringLiteral("ans/0.25"); QTest::newRow("constant") << QStringLiteral("e/7"); QTest::newRow("function") << QStringLiteral("cos(pi)/11"); QTest::newRow("power") << QStringLiteral("ans^2/13"); QTest::newRow("product") << QStringLiteral("ans*e/5"); QTest::newRow("grouped-denominator") << QStringLiteral("ans/(17*e)"); QTest::newRow("negative-numerator") << QStringLiteral("(-ans)/8"); QTest::newRow("negative-denominator") << QStringLiteral("ans/(-6)"); QTest::newRow("sum") << QStringLiteral("ans/10+e/7"); QTest::newRow("comment") << QStringLiteral("ans/12 ? previous answer"); QTest::newRow("unicode-division") << QString::fromUtf8("ans÷16"); } void TestDisplayUi::result_display_preserves_unreduced_quotients() { QFETCH(QString, expression); Settings::instance()->simplifyResultExpressions = true; Settings::instance()->multipleResultLinesEnabled = false; Session session; Evaluator* evaluator = session.evaluator(); evaluator->setExpression(QStringLiteral("4")); QCOMPARE(evaluator->evalUpdateAns(), Quantity(4)); evaluator->setExpression(expression); const Quantity value = evaluator->evalUpdateAns(); QVERIFY2(evaluator->error().isEmpty(), qPrintable(evaluator->error())); const QString interpreted = evaluator->interpretedExpression(); const QString withoutComment = interpreted.section(QLatin1Char('?'), 0, 0).trimmed(); QCOMPARE(Evaluator::simplifyInterpretedExpression(interpreted), withoutComment); QCOMPARE(Evaluator::formatInterpretedExpressionSimplifiedForDisplay(interpreted, evaluator), Evaluator::formatInterpretedExpressionForDisplay(withoutComment, evaluator)); EvaluationContext context; context.main.fmt = 'f'; context.main.prec = 20; session.addHistoryEntry(HistoryEntry(expression, value, interpreted, context)); ResultDisplay display; display.setSession(&session); const QStringList lines = display.toPlainText().trimmed().split(QLatin1Char('\n')); QCOMPARE(lines.size(), 2); if (expression == QStringLiteral("ans/9")) QCOMPARE(lines.last(), QStringLiteral("= 0.44444444444444444444")); } void TestDisplayUi::result_display_reduces_combinable_quotient_factors_data() { QTest::addColumn("expression"); QTest::addColumn("simplified"); QTest::newRow("repeated-factor") << QStringLiteral("ans*ans/25") << QStringLiteral("1/25*ans^2"); QTest::newRow("numeric-coefficient") << QStringLiteral("6*ans/15") << QStringLiteral("2/5*ans"); QTest::newRow("numeric-denominators") << QStringLiteral("ans/2/7") << QStringLiteral("1/14*ans"); QTest::newRow("cancellation") << QStringLiteral("ans*e/e/8") << QStringLiteral("1/8*ans"); QTest::newRow("neutral-factor") << QStringLiteral("ans/1") << QStringLiteral("ans"); } void TestDisplayUi::result_display_reduces_combinable_quotient_factors() { QFETCH(QString, expression); QFETCH(QString, simplified); Settings::instance()->simplifyResultExpressions = true; Settings::instance()->multipleResultLinesEnabled = false; Session session; Evaluator* evaluator = session.evaluator(); evaluator->setExpression(QStringLiteral("4")); QCOMPARE(evaluator->evalUpdateAns(), Quantity(4)); evaluator->setExpression(expression); const Quantity value = evaluator->evalUpdateAns(); QVERIFY2(evaluator->error().isEmpty(), qPrintable(evaluator->error())); const QString interpreted = evaluator->interpretedExpression(); QCOMPARE(Evaluator::simplifyInterpretedExpression(interpreted), simplified); session.addHistoryEntry(HistoryEntry(expression, value, interpreted)); ResultDisplay display; display.setSession(&session); const QStringList lines = display.toPlainText().trimmed().split(QLatin1Char('\n')); QCOMPARE(lines.size(), 3); QCOMPARE(lines.at(1), QStringLiteral("= ") + Evaluator::formatInterpretedExpressionForDisplay(simplified, evaluator)); } void TestDisplayUi::result_display_copies_calculation_as_single_line_data() { QTest::addColumn("lines"); QTest::addColumn("expected"); QTest::addColumn("failed"); QTest::newRow("simple") << QStringList({QStringLiteral("120 / 8"), QStringLiteral("= 15")}) << QStringLiteral("120 / 8 = 15") << false; QTest::newRow("simplification-and-formats") << QStringList({QStringLiteral("1:120:3600"), QStringLiteral("= 4:00:00"), QStringLiteral("= 14400 s"), QStringLiteral("= 1.44 × 10â�´ s")}) << QStringLiteral("1:120:3600 = 4:00:00 = 14400 s = 1.44 × 10â�´ s") << false; QTest::newRow("wrapped-unicode-and-spacing") << QStringList({QStringLiteral("123456789 [m] − 98765432 [m] + 1 [m] + 2 [m]"), QStringLiteral("= 24\u2009567\u2009360 m"), QStringLiteral("= 2.456736 × 10â�· m")}) << QStringLiteral("123456789 [m] − 98765432 [m] + 1 [m] + 2 [m] = 24\u2009567\u2009360 m = 2.456736 × 10â�· m") << false; QTest::newRow("failed") << QStringList({QStringLiteral("1 / 0")}) << QStringLiteral("1 / 0") << true; } void TestDisplayUi::result_display_copies_calculation_as_single_line() { QFETCH(QStringList, lines); QFETCH(QString, expected); QFETCH(bool, failed); const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([oldClipboard]() { QApplication::clipboard()->setText(oldClipboard); }); Session session; session.addHistoryEntry(HistoryEntry(QStringLiteral("2 + 3"), Quantity(5))); HistoryEntry entry(lines.first(), failed ? DMath::nan() : Quantity(15)); entry.setRenderedLines(lines); session.addHistoryEntry(entry); session.addHistoryEntry(HistoryEntry(QStringLiteral("7 + 8"), Quantity(15))); MenuTestResultDisplay display; display.resize(250, 350); display.setSession(&session); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); QTextCursor selection(display.document()->firstBlock()); selection.select(QTextCursor::BlockUnderCursor); display.setTextCursor(selection); const int selectionStart = selection.selectionStart(); const int selectionEnd = selection.selectionEnd(); if (qstrcmp(QTest::currentDataTag(), "wrapped-unicode-and-spacing") == 0) QVERIFY(display.document()->find(lines.first()).block().layout()->lineCount() > 1); // Copy the recorded text even after the current display settings change. Settings::instance()->resultFormat = 'h'; Settings::instance()->simplifyResultExpressions = false; for (const QString& line : lines) { QTextCursor clickedLine = display.document()->find(line); QVERIFY(!clickedLine.isNull()); clickedLine.movePosition(QTextCursor::StartOfBlock); display.verticalScrollBar()->setValue(clickedLine.blockNumber()); QCoreApplication::processEvents(); QScopedPointer menu(display.createContextMenu(display.cursorRect(clickedLine).center())); QMenu* copyMenu = directSubmenuWithTitle(menu.data(), QStringLiteral("Copy")); QVERIFY(copyMenu != nullptr); QAction* action = directMenuActionWithText(copyMenu, QStringLiteral("Calculation as Single Line")); QVERIFY(action != nullptr); QVERIFY(action->isEnabled()); QApplication::clipboard()->setText(QStringLiteral("unchanged")); action->trigger(); QCOMPARE(QApplication::clipboard()->text(), expected); QCOMPARE(display.textCursor().selectionStart(), selectionStart); QCOMPARE(display.textCursor().selectionEnd(), selectionEnd); } } void TestDisplayUi::result_display_copies_expression_and_result_data() { QTest::addColumn("failed"); QTest::newRow("result") << false; QTest::newRow("failed") << true; } void TestDisplayUi::result_display_copies_expression_and_result() { QFETCH(bool, failed); const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([oldClipboard]() { QApplication::clipboard()->setText(oldClipboard); }); Session session; const QString expression = failed ? QStringLiteral("1 / 0") : QStringLiteral("2 + 3"); session.addHistoryEntry(HistoryEntry(expression, failed ? DMath::nan() : Quantity(5))); MenuTestResultDisplay display; display.resize(400, 200); display.setSession(&session); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); const QTextCursor expressionCursor(display.document()->firstBlock()); QScopedPointer menu(display.createContextMenu(display.cursorRect(expressionCursor).center())); QMenu* copyMenu = directSubmenuWithTitle(menu.data(), QStringLiteral("Copy")); QVERIFY(copyMenu != nullptr); QAction* copyExpression = directMenuActionWithText(copyMenu, QStringLiteral("Expression")); QAction* copyResult = directMenuActionWithText(copyMenu, QStringLiteral("Result")); QVERIFY(copyExpression != nullptr); QVERIFY(copyResult != nullptr); QVERIFY(copyExpression->isEnabled()); QCOMPARE(copyResult->isEnabled(), !failed); copyExpression->trigger(); QCOMPARE(QApplication::clipboard()->text(), expression); if (!failed) { copyResult->trigger(); QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("5")); } } void TestDisplayUi::result_display_context_menu_tracks_session_state_data() { QTest::addColumn("hasCalculation"); QTest::addColumn("isPrivate"); QTest::newRow("empty") << false << false; QTest::newRow("calculation") << true << false; QTest::newRow("private-calculation") << true << true; } void TestDisplayUi::result_display_context_menu_tracks_session_state() { QFETCH(bool, hasCalculation); QFETCH(bool, isPrivate); Session session; session.setPrivate(isPrivate); if (hasCalculation) session.addHistoryEntry(HistoryEntry(QStringLiteral("2 + 3"), Quantity(5))); MenuTestResultDisplay display; display.resize(400, 200); display.setSession(&session); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); const QTextCursor cursor(display.document()->firstBlock()); QScopedPointer menu(display.createContextMenu(display.cursorRect(cursor).center())); QMenu* copyMenu = directSubmenuWithTitle(menu.data(), QStringLiteral("Copy")); QVERIFY(copyMenu != nullptr); QCOMPARE(copyMenu->isEnabled(), hasCalculation); const QString selectAllText = QStringLiteral("Select All\t") + QKeySequence(QKeySequence::SelectAll).toString(QKeySequence::NativeText); QAction* selectAll = directMenuActionWithText(menu.data(), selectAllText); QVERIFY(selectAll != nullptr); QCOMPARE(selectAll->isEnabled(), hasCalculation); QMenu* sessionMenu = directSubmenuWithTitle(menu.data(), QStringLiteral("Session")); QVERIFY(sessionMenu != nullptr); QAction* privacyAction = directMenuActionWithText(sessionMenu, isPrivate ? QStringLiteral("Keep") : QStringLiteral("Make Private...")); QVERIFY(privacyAction != nullptr); QVERIFY(directMenuActionWithText(sessionMenu, isPrivate ? QStringLiteral("Make Private...") : QStringLiteral("Keep")) == nullptr); QSignalSpy privacySpy(&display, &ResultDisplay::convertSessionPrivacyRequested); privacyAction->trigger(); QCOMPARE(privacySpy.count(), 1); QAction* openAction = directMenuActionWithText(sessionMenu, QStringLiteral("Open...")); QVERIFY(openAction != nullptr); QSignalSpy openSpy(&display, &ResultDisplay::openSessionRequested); openAction->trigger(); QCOMPARE(openSpy.count(), 1); } void TestDisplayUi::result_display_context_menu_copies_selection() { const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([oldClipboard]() { QApplication::clipboard()->setText(oldClipboard); }); Session session; session.addHistoryEntry(HistoryEntry(QStringLiteral("2 + 3"), Quantity(5))); MenuTestResultDisplay display; display.resize(400, 200); display.setSession(&session); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); QTextCursor cursor(display.document()->firstBlock()); cursor.select(QTextCursor::BlockUnderCursor); display.setTextCursor(cursor); QScopedPointer menu(display.createContextMenu(display.cursorRect(cursor).center())); QMenu* copyMenu = directSubmenuWithTitle(menu.data(), QStringLiteral("Copy")); QVERIFY(copyMenu != nullptr); QAction* selectionAction = directMenuActionWithText(copyMenu, QStringLiteral("Selection\t") + QKeySequence(QKeySequence::Copy).toString(QKeySequence::NativeText)); QVERIFY(selectionAction != nullptr); QVERIFY(selectionAction->isEnabled()); selectionAction->trigger(); QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("2 + 3")); QCOMPARE(display.textCursor().selectedText(), QStringLiteral("2 + 3")); QAction* selectAll = directMenuActionWithText(menu.data(), QStringLiteral("Select All\t") + QKeySequence(QKeySequence::SelectAll).toString(QKeySequence::NativeText)); QVERIFY(selectAll != nullptr); selectAll->trigger(); QCOMPARE(display.textCursor().selectionStart(), 0); QCOMPARE(display.textCursor().selectionEnd(), display.document()->characterCount() - 1); } void TestDisplayUi::result_display_remove_menu_targets_clicked_calculation() { Session session; for (int i = 0; i < 3; ++i) session.addHistoryEntry(HistoryEntry(QString::number(i), Quantity(i))); MenuTestResultDisplay display; display.resize(400, 300); display.setSession(&session); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); QTextCursor clicked = display.document()->find(QStringLiteral("1")); QVERIFY(!clicked.isNull()); QScopedPointer menu(display.createContextMenu(display.cursorRect(clicked).center())); QMenu* removeMenu = directSubmenuWithTitle(menu.data(), QStringLiteral("Remove")); QVERIFY(removeMenu != nullptr); QSignalSpy removeSpy(&display, &ResultDisplay::removeHistoryEntryRequested); QSignalSpy aboveSpy(&display, &ResultDisplay::removeHistoryEntriesAboveRequested); QSignalSpy belowSpy(&display, &ResultDisplay::removeHistoryEntriesBelowRequested); const QList spies = {&removeSpy, &aboveSpy, &belowSpy}; const QStringList labels = {QStringLiteral("This Calculation"), QStringLiteral("All Calculations Above"), QStringLiteral("All Calculations Below")}; for (int i = 0; i < labels.size(); ++i) { QAction* action = directMenuActionWithText(removeMenu, labels.at(i)); QVERIFY(action != nullptr); action->trigger(); for (int j = 0; j < spies.size(); ++j) { QCOMPARE(spies.at(j)->count(), i == j ? 1 : 0); if (i == j) QCOMPARE(spies.at(j)->first().first().toInt(), 1); spies.at(j)->clear(); } } } void TestDisplayUi::result_display_hover_action_badges_trigger_when_clicked() { BadgeTestResultDisplay display; Session session; session.addHistoryEntry(HistoryEntry(QStringLiteral("120 / 8"), Quantity(15))); display.setSession(&session); display.resize(420, 120); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); const QRect copyRect = display.copyBadgeRect(0); const QRect editRect = display.editBadgeRect(0); const QRect settingsRect = display.settingsBadgeRect(0); const QRect removeRect = display.removeBadgeRect(0); QVERIFY(copyRect.isValid()); QVERIFY(editRect.isValid()); QVERIFY(settingsRect.isValid()); QVERIFY(removeRect.isValid()); QApplication::clipboard()->clear(); QTest::mouseMove(display.viewport(), copyRect.center()); QTest::mouseClick(display.viewport(), Qt::LeftButton, Qt::NoModifier, copyRect.center()); QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("15")); QSignalSpy editSpy(&display, &ResultDisplay::editHistoryEntryRequested); QTest::mouseMove(display.viewport(), editRect.center()); QTest::mouseClick(display.viewport(), Qt::LeftButton, Qt::NoModifier, editRect.center()); QCOMPARE(editSpy.count(), 1); QCOMPARE(editSpy.takeFirst().at(0).toInt(), 0); QSignalSpy settingsSpy(&display, &ResultDisplay::editHistoryEntryContextRequested); QTest::mouseMove(display.viewport(), settingsRect.center()); QTest::mouseClick(display.viewport(), Qt::LeftButton, Qt::NoModifier, settingsRect.center()); QCOMPARE(settingsSpy.count(), 1); QCOMPARE(settingsSpy.takeFirst().at(0).toInt(), 0); QSignalSpy removeSpy(&display, &ResultDisplay::removeHistoryEntryRequested); QTest::mouseMove(display.viewport(), removeRect.center()); QTest::mouseClick(display.viewport(), Qt::LeftButton, Qt::NoModifier, removeRect.center()); QCOMPARE(removeSpy.count(), 1); QCOMPARE(removeSpy.takeFirst().at(0).toInt(), 0); } void TestDisplayUi::result_display_scroll_to_bottom_button_uses_custom_tooltip() { ResultDisplay display; const QColor popupBackground(QStringLiteral("#45465f")); const QColor popupForeground(QStringLiteral("#f0ecff")); const QColor popupOutline(QStringLiteral("#696a80")); display.setThemeToolTipColors(popupBackground, popupForeground, popupOutline); display.resize(360, 160); display.show(); QVERIFY(QTest::qWaitForWindowExposed(&display)); Quantity value; for (int i = 0; i < 40; ++i) display.append(QStringLiteral("123456789012345678901234567890"), value); QScrollBar* scrollBar = display.verticalScrollBar(); QVERIFY(scrollBar->maximum() > scrollBar->minimum()); scrollBar->setValue(scrollBar->minimum()); QCoreApplication::processEvents(); QToolButton* scrollToBottomButton = display.findChild(QStringLiteral("ScrollToBottomButton")); QVERIFY(scrollToBottomButton != nullptr); QTRY_VERIFY(scrollToBottomButton->isVisible()); QCOMPARE(scrollToBottomButton->toolTip(), QString()); const QPoint buttonCenter = scrollToBottomButton->rect().center(); QMouseEvent moveEvent(QEvent::MouseMove, QPointF(buttonCenter), QPointF(scrollToBottomButton->mapToGlobal(buttonCenter)), Qt::NoButton, Qt::NoButton, Qt::NoModifier); QCoreApplication::sendEvent(scrollToBottomButton, &moveEvent); QFrame* actionPopup = display.findChild(QStringLiteral("resultActionPopup")); QTRY_VERIFY(actionPopup != nullptr && actionPopup->isVisible()); QLabel* actionPopupLabel = actionPopup->findChild(QStringLiteral("resultActionPopupLabel")); QVERIFY(actionPopupLabel != nullptr); QCOMPARE(actionPopupLabel->text(), QStringLiteral("Scroll to bottom")); QVERIFY(actionPopup->styleSheet().contains(popupBackground.name())); QVERIFY(actionPopup->styleSheet().contains(popupForeground.name())); QVERIFY(actionPopup->styleSheet().contains(QStringLiteral("border: %1px solid %2") .arg(UiConfig::PopupOutlineStrokeWidth) .arg(popupOutline.name()))); QVERIFY(!actionPopup->mask().isEmpty()); QVERIFY(actionPopup->testAttribute(Qt::WA_TransparentForMouseEvents)); QEvent leaveEvent(QEvent::Leave); QCoreApplication::sendEvent(scrollToBottomButton, &leaveEvent); QTRY_VERIFY(actionPopup == nullptr || !actionPopup->isVisible()); } void TestDisplayUi::result_display_context_menu_hides_main_menu_when_menu_bar_visible() { MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; QMainWindow window; window.menuBar()->addMenu(QStringLiteral("File"))->addAction(QStringLiteral("Dummy")); MenuTestResultDisplay* display = new MenuTestResultDisplay(&window); display->setThemeInteractionColors(QColor(QStringLiteral("#333333")), QColor(QStringLiteral("#5588ff")), QColor(QStringLiteral("#111111")), QColor(QStringLiteral("#eeeeee")), QColor(QStringLiteral("#222222")), QColor(QStringLiteral("#ffffff"))); window.setCentralWidget(display); window.resize(360, 180); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QVERIFY(window.menuBar()->isVisible()); QVERIFY(!contextMenuContainsMainMenu(display)); QSignalSpy importSessionSpy(display, &ResultDisplay::importSessionRequested); QSignalSpy exportJsonSpy(display, &ResultDisplay::exportSessionJsonRequested); QSignalSpy exportPlainTextSpy(display, &ResultDisplay::exportSessionPlainTextRequested); QSignalSpy exportHtmlSpy(display, &ResultDisplay::exportSessionHtmlRequested); QMenu* menu = display->createContextMenu(display->rect().center()); QMenu* sessionMenu = directSubmenuWithTitle(menu, QStringLiteral("Session")); QVERIFY(sessionMenu != nullptr); QAction* importAction = directMenuActionWithText(sessionMenu, QStringLiteral("&Import...")); QVERIFY(importAction != nullptr); QMenu* exportMenu = directSubmenuWithTitle(sessionMenu, QStringLiteral("&Export")); QVERIFY(exportMenu != nullptr); QVERIFY(directMenuActionWithText(exportMenu, QStringLiteral("JSON")) != nullptr); QVERIFY(directMenuActionWithText(exportMenu, QStringLiteral("Plain &text")) != nullptr); QVERIFY(directMenuActionWithText(exportMenu, QStringLiteral("&HTML")) != nullptr); importAction->trigger(); directMenuActionWithText(exportMenu, QStringLiteral("JSON"))->trigger(); directMenuActionWithText(exportMenu, QStringLiteral("Plain &text"))->trigger(); directMenuActionWithText(exportMenu, QStringLiteral("&HTML"))->trigger(); QCOMPARE(importSessionSpy.size(), 1); QCOMPARE(exportJsonSpy.size(), 1); QCOMPARE(exportPlainTextSpy.size(), 1); QCOMPARE(exportHtmlSpy.size(), 1); QVERIFY(menu->styleSheet().contains(QStringLiteral("#111111"))); QVERIFY(menu->styleSheet().contains(QStringLiteral("#eeeeee"))); QVERIFY(menu->styleSheet().contains(QStringLiteral("#222222"))); QVERIFY(menu->styleSheet().contains(QStringLiteral("#ffffff"))); QVERIFY(menu->styleSheet().contains(QStringLiteral("border-radius: 8px"))); delete menu; window.menuBar()->hide(); QVERIFY(!window.menuBar()->isVisible()); QVERIFY(contextMenuContainsMainMenu(display)); } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testdisplayui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testdmath.cpp000066400000000000000000000160231526573132500237710ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2016-2017, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "math/quantity.h" #include "math/rational.h" #include "core/units.h" #include "tests/testcommon.h" #include #include #include #include #include using namespace std; typedef Quantity::Format Format; #define CHECK(x,y) check_value(__FILE__,__LINE__,#x,x,y) #define CHECK_FORMAT(f,x,y) check_format(__FILE__,__LINE__,#x,x,f,y) #define CHECK_PRECISE(x,y) check_precise(__FILE__,__LINE__,#x,x,y) #define CHECK_KNOWN_ISSUE(x,y,n) check_value(__FILE__,__LINE__,#x,x,y,n) #define CHECK_STRING(x,y) {++dmath_total_tests; DisplayErrorOnMismatch(__FILE__,__LINE__,#x,x,y,dmath_failed_tests,dmath_new_failed_tests);} static int dmath_total_tests = 0; static int dmath_failed_tests = 0; static int dmath_new_failed_tests = 0; static void check_value(const char* file, int line, const char* msg, const Quantity& q, const char* expected, int issue = 0) { ++dmath_total_tests; string result = DMath::format(q, Format::Fixed()).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, dmath_failed_tests, dmath_new_failed_tests, issue); } static void check_format(const char* file, int line, const char* msg, const Quantity& q, Format format, const char* expected) { ++dmath_total_tests; string result = DMath::format(q, format).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, dmath_failed_tests, dmath_new_failed_tests, 0); } //static void check_precise(const char* file, int line, const char* msg, const Quantity& q, const char* expected) //{ // ++dmath_total_tests; // string result = DMath::format(q, Format::Fixed() + Format::Precision(50)).toStdString(); // DisplayErrorOnMismatch(file, line, msg, result, expected, dmath_failed_tests, dmath_new_failed_tests, 0); //} void test_rational() { CHECK_STRING(HMath::format(Rational(123,456).toHNumber()).toStdString(), "0.26973684210526315789"); CHECK_STRING(Rational(22./7).toString().toStdString(), "22/7"); CHECK_STRING(Rational(-12345./96457).toString().toStdString(), "-12345/96457"); CHECK_STRING(Rational(HNumber("-1234")/HNumber("7895")).toString().toStdString(), "-1234/7895"); CHECK_STRING(Rational(HNumber("-1235000")/HNumber("78950000")).toString().toStdString(), "-247/15790"); CHECK_STRING(Rational(HNumber("1")/HNumber("7")).toString().toStdString(), "1/7"); CHECK_STRING(Rational(0.).toString().toStdString(), "0"); CHECK_STRING(Rational(HNumber(0)).toString().toStdString(), "0"); Rational approx; CHECK_STRING((Rational::approximate(HNumber("1") / HNumber("2"), 1000000, HNumber("1e-20"), &approx) ? approx.toString() : QString("invalid")).toStdString(), "1/2"); } void test_create() { CHECK(Units::metre(), "1 metre"); CHECK(Quantity(CNumber("123.45+654j")), "123.45+654j"); CHECK(Quantity(HNumber("123.45")), "123.45"); } void test_basic() { CHECK(Units::metre(), "1 metre"); CHECK(Quantity(5) * Units::metre(), "5 metre"); CHECK(Units::candela() + Units::second(), "NaN"); CHECK(Quantity(3)*Units::mole() - Quantity(HNumber("2.5"))*Units::mole(), "500 mmol"); CHECK(Units::kilogram()/Units::second(), "1 kilogram·secondâ�»Â¹"); CHECK(Units::metre()*Units::metre(), "1 metre²"); CHECK(-Quantity(5)*Units::metre(), "-5 metre"); CNumber foot = CNumber("0.3"); Quantity a(Quantity(123)*Units::metre()); a.setDisplayUnit(foot, "foot"); CHECK(a, "410 foot"); CHECK(a*Units::second(), "123 metre·second"); // Issue 615 CHECK(a/Units::second(), "123 metre·secondâ�»Â¹"); // CHECK(a*HNumber(5), "2050 foot"); // CHECK(a/HNumber(5), "82 foot"); // CHECK(DMath::raise(Units::metre(), 0),"1"); CHECK(DMath::raise(Units::metre(), Quantity(0)),"1"); CHECK(DMath::raise(Units::metre(), 0) + DMath::raise(Units::second(), 0),"2"); CHECK(DMath::raise(Units::metre(), Quantity(0)) + DMath::raise(Units::second(), Quantity(0)),"2"); } void test_functions() { Quantity tmp1; CHECK(DMath::abs(Quantity(CNumber("3+4j"))*Units::metre()), "5 metre"); CHECK(DMath::round(CNumber("1.234"), 1), "1.2"); CHECK(DMath::round(Quantity(CNumber("1.234"))*Units::joule(), 0), "NaN"); DMath::complexMode = true; tmp1 = Quantity(CNumber("3+4j"))*Units::ohm(); CHECK(DMath::conj(Quantity(CNumber("3"))*Units::ohm()), "3 ohm"); CHECK(DMath::conj(Quantity(CNumber("3+4j"))*Units::ohm()), "(3-4j) ohm"); DMath::complexMode = false; CHECK(DMath::conj(Quantity(CNumber("3"))*Units::ohm()), "3 ohm"); // for a complex number declared in complex mode, ensure that if we've switched to real mode // and call this function that the imaginary part is stripped. CHECK(DMath::conj(tmp1), "3 ohm"); DMath::complexMode = true; CHECK(DMath::trunc(CNumber("1.274"), 1), "1.2"); CHECK(DMath::trunc(Quantity(CNumber("1.234"))*Units::joule(), 0), "NaN"); CHECK(DMath::real(Quantity(CNumber("3+4j"))*Units::metre()), "3 metre"); CHECK(DMath::imag(Quantity(CNumber("3+4j"))*Units::metre()), "4 metre"); CHECK(DMath::sqrt(Quantity(CNumber("36"))*Units::second()), "6 second^(1/2)"); CHECK(DMath::cbrt(Quantity(CNumber("125"))*Units::second()), "5 second^(1/3)"); CHECK(DMath::raise(Quantity(CNumber("2")), DMath::pi()), "8.82497782707628762386"); CHECK(DMath::raise(Quantity(CNumber("2"))*Units::ampere(), DMath::pi()), "NaN"); CHECK(DMath::raise(Quantity(CNumber("-2"))*Units::ampere(), Quantity(CNumber("1.5"))), "NaN"); DMath::complexMode = false; CHECK(DMath::raise(Quantity(CNumber("-2"))*Units::ampere(), Quantity(CNumber("0.6"))), "-1.51571656651039808235 ampere^(3/5)"); CHECK(DMath::raise(Quantity(CNumber("-8"))*Units::ampere(), Quantity(CNumber("2") / CNumber("3"))), "4 ampere^(2/3)"); DMath::complexMode = true; CHECK(DMath::raise(Quantity(CNumber("-2"))*Units::ampere(), Quantity(CNumber("0.6"))), "(-0.46838217770735830743+1.44153211743623063689j) ampere^(3/5)"); // this should do it for all wrapped functions that do not accept dimensional arguments... CHECK(DMath::sin(Quantity(DMath::pi())), "0"); CHECK(DMath::sin(Units::metre()), "NaN"); } void test_format() { Quantity a = Quantity(CNumber("12365234.45647")); CHECK_FORMAT(Format::Binary() + Format::Fixed() + Format::Precision(10), a, "0b101111001010110110110010.0111010011"); a *= Units::coulomb(); CHECK_FORMAT(Format::Binary() + Format::Fixed() + Format::Precision(10), a, "0b1100.0101110110 MC"); } int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); dmath_total_tests = 0; dmath_failed_tests = 0; test_rational(); test_create(); test_basic(); test_functions(); test_format(); cerr.flush(); if (!dmath_failed_tests) return 0; cout << dmath_total_tests << " total, " << dmath_failed_tests << " failed, " << dmath_new_failed_tests << " new" << endl; return dmath_new_failed_tests; } heldercorreia-speedcrunch-e7ca37f/src/tests/testdockappearanceui.cpp000066400000000000000000001636171526573132500262060ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" #include "core/startupdiagnostics.h" using namespace MainWindowTestHelpers; class TestDockAppearanceUi : public QObject { Q_OBJECT private slots: void initTestCase(); void init() { UiTestFixture::resetSettings(); } void dock_refresh_reuses_unchanged_appearance_work_data(); void dock_refresh_reuses_unchanged_appearance_work(); void themed_header_metrics_refresh_after_font_change_data(); void themed_header_metrics_refresh_after_font_change(); void dock_appearance_defaults_to_theme_and_persists(); void dock_appearance_switches_all_windows_data(); void dock_appearance_switches_all_windows(); void dock_tabs_follow_appearance_data(); void dock_tabs_follow_appearance(); void system_docks_follow_palette_and_theme_changes(); void system_dock_separators_use_thin_system_colors_data(); void system_dock_separators_use_thin_system_colors(); void dock_headers_follow_appearance_data(); void dock_headers_follow_appearance(); void system_dock_headers_paint_system_background_data(); void system_dock_headers_paint_system_background(); void system_dock_controls_keep_aligned_rows_data(); void system_dock_controls_keep_aligned_rows(); void dock_header_buttons_render_full_size_data(); void dock_header_buttons_render_full_size(); void dock_header_buttons_render_full_size_on_first_run_data(); void dock_header_buttons_render_full_size_on_first_run(); void dock_header_buttons_stay_centered_in_title_bar_data(); void dock_header_buttons_stay_centered_in_title_bar(); void dock_header_buttons_keep_theme_after_redocking_data(); void dock_header_buttons_keep_theme_after_redocking(); void themed_headers_keep_native_scrollbar_styles(); }; void TestDockAppearanceUi::dock_refresh_reuses_unchanged_appearance_work_data() { QTest::addColumn("system"); QTest::newRow("theme") << false; QTest::newRow("system") << true; } void TestDockAppearanceUi::dock_refresh_reuses_unchanged_appearance_work() { QFETCH(bool, system); MainWindowStateGuard guard; guard.settings->constantsDockVisible = true; guard.settings->dockAppearance = system ? Settings::DockAppearanceSystem : Settings::DockAppearanceSpeedCrunch; guard.settings->sessionLayoutJson.clear(); guard.settings->windowState.clear(); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); StartupDiagnostics::begin(); const auto finishRecording = qScopeGuard([]() { StartupDiagnostics::firstPaintFinished(); StartupDiagnostics::finishWhenIdle(); }); QVERIFY(QMetaObject::invokeMethod(&window, "colorSchemeChanged", Qt::DirectConnection)); QCoreApplication::processEvents(); const auto snapshot = StartupDiagnostics::snapshot(); int skippedChromePalettes = 0; for (const auto& assignment : snapshot.appearanceAssignments) { const auto& call = snapshot.appearanceCalls.at(assignment.call - 1); if (call.name == QLatin1String("Apply dock chrome appearance") && call.context == QLatin1String("Deferred dock refresh") && assignment.palette) { skippedChromePalettes += assignment.skipped; } } QVERIFY(skippedChromePalettes > 0); if (!system) { int reusedHeaders = 0; for (const auto& phase : snapshot.phases) { if (phase.name == QLatin1String("Reuse native dock header metrics")) reusedHeaders += phase.calls; } QVERIFY(reusedHeaders > 0); } } void TestDockAppearanceUi::themed_header_metrics_refresh_after_font_change_data() { QTest::addColumn("modelFont"); QTest::newRow("widget-font") << false; QTest::newRow("model-font") << true; } void TestDockAppearanceUi::themed_header_metrics_refresh_after_font_change() { QFETCH(bool, modelFont); MainWindowStateGuard guard; guard.settings->constantsDockVisible = true; guard.settings->dockAppearance = Settings::DockAppearanceSpeedCrunch; guard.settings->sessionLayoutJson.clear(); guard.settings->windowState.clear(); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); QDockWidget* constants = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constants); QTreeWidget* table = constants->findChild(); QVERIFY(table); QHeaderView* header = table->header(); const int oldHeight = header->sizeHint().height(); StartupDiagnostics::begin(); const auto finishRecording = qScopeGuard([]() { StartupDiagnostics::firstPaintFinished(); StartupDiagnostics::finishWhenIdle(); }); QVERIFY(QMetaObject::invokeMethod(&window, "colorSchemeChanged", Qt::DirectConnection)); const auto measuredHeaders = []() { for (const auto& phase : StartupDiagnostics::snapshot().phases) { if (phase.name == QLatin1String("Measure native dock header metrics")) return phase.calls; } return 0; }; const int initialMeasurements = measuredHeaders(); QVERIFY(initialMeasurements > 0); QFont font = header->font(); font.setPixelSize(header->fontMetrics().height() + 12); if (modelFont) table->headerItem()->setFont(0, font); else header->setFont(font); QCoreApplication::processEvents(); QVERIFY(measuredHeaders() > initialMeasurements); QVERIFY(header->sizeHint().height() > oldHeight); } void TestDockAppearanceUi::themed_headers_keep_native_scrollbar_styles() { MainWindowStateGuard guard; guard.settings->constantsDockVisible = true; guard.settings->functionsDockVisible = true; guard.settings->variablesDockVisible = true; guard.settings->userFunctionsDockVisible = true; guard.settings->userUnitsDockVisible = true; MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QMenu* appearance = window.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); for (int mode : {1, 0, 1}) { appearance->actions().at(mode)->trigger(); QCoreApplication::processEvents(); int headersChecked = 0; for (QDockWidget* dock : window.findChildren()) { for (QHeaderView* header : dock->widget()->findChildren()) { QVERIFY(header->horizontalScrollBar()->styleSheet().isEmpty()); QVERIFY(header->verticalScrollBar()->styleSheet().isEmpty()); QVERIFY(header->cornerWidget() == nullptr); ++headersChecked; } } QVERIFY(headersChecked > 0); } } void TestDockAppearanceUi::initTestCase() { // Fail before a file-operation test can open an unhandled error dialog. for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) { QVERIFY2(QDir().mkpath(path), qPrintable(QStringLiteral("Cannot create test storage at %1").arg(path))); QTemporaryFile probe(QDir(path).filePath(QStringLiteral("storage-probe-XXXXXX"))); QVERIFY2(probe.open(), qPrintable(QStringLiteral("Cannot write test storage at %1: %2") .arg(path, probe.errorString()))); } } void TestDockAppearanceUi::system_dock_separators_use_thin_system_colors_data() { QTest::addColumn("systemAtStartup"); QTest::addColumn("classic"); for (bool system : {false, true}) { for (bool classic : {false, true}) { const QString name = QStringLiteral("%1-%2") .arg(system ? "system-startup" : "theme-startup", classic ? "classic" : "modern"); QTest::newRow(qPrintable(name)) << system << classic; } } } void TestDockAppearanceUi::system_dock_separators_use_thin_system_colors() { QFETCH(bool, systemAtStartup); QFETCH(bool, classic); MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([original]() { QApplication::setPalette(original); }); QPalette native = original; native.setColor(QPalette::Window, QColor("#eeeeee")); native.setColor(QPalette::Mid, QColor("#999999")); native.setColor(QPalette::Highlight, QColor("#2878b8")); QApplication::setPalette(native); guard.settings->dockAppearance = systemAtStartup ? Settings::DockAppearanceSystem : Settings::DockAppearanceSpeedCrunch; guard.settings->editorDisplayStyle = classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; guard.settings->constantsDockVisible = true; guard.settings->functionsDockVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#631840")}}); MainWindow first(false); MainWindow second(false); first.setAnimated(false); second.setAnimated(false); first.resize(1100, 760); first.show(); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&first)); QVERIFY(QTest::qWaitForWindowExposed(&second)); auto* constants = first.findChild(QStringLiteral("ConstantsDock")); auto* functions = first.findChild(QStringLiteral("FunctionsDock")); QVERIFY(constants); QVERIFY(functions); first.removeDockWidget(functions); first.addDockWidget(Qt::RightDockWidgetArea, functions); first.splitDockWidget(constants, functions, Qt::Vertical); functions->show(); QMenu* appearance = first.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); QCursor::setPos(first.mapToGlobal(QPoint(-20, -20))); QCoreApplication::processEvents(); const auto verify = [&](bool system) { for (MainWindow* window : {&first, &second}) { const QColor normal = system ? native.color(QPalette::Mid) : window->property("speedcrunchDockSeparatorNormalColor").value(); const QColor active = system ? native.color(QPalette::Highlight) : window->property("speedcrunchDockSeparatorActiveColor").value(); const int width = system ? 1 : UiConfig::DockSplitterStrokeWidth; // Include a native one-pixel handle so painting outside its bounds is visible. for (int extent : {1, 8}) { for (bool horizontal : {false, true}) { const QSize size = horizontal ? QSize(32, extent) : QSize(extent, 32); for (QStyle::State state : {QStyle::State(QStyle::State_None), QStyle::State(QStyle::State_MouseOver), QStyle::State(QStyle::State_Sunken)}) { const QImage image = dockSeparatorPrimitiveImage(window, state, QRect(QPoint(0, 0), size), size + QSize(2, 2)); const int start = (extent - 1) / 2 - (width - 1) / 2; for (int offset = 0; offset < extent + 2; ++offset) { const QColor pixel = horizontal ? image.pixelColor(16, offset) : image.pixelColor(offset, 16); if (offset >= start && offset < start + width) QCOMPARE(pixel.rgba(), (state == QStyle::State_None ? normal : active).rgba()); else if (system && offset < extent) QCOMPARE(pixel, native.color(QPalette::Window)); else QCOMPARE(pixel.alpha(), 0); } } } } } if (!system) return; // Check actual window painting at the dock/editor and dock/dock boundaries. const QRect upper = constants->geometry(); const QRect lower = functions->geometry(); const QRect center = first.centralWidget()->geometry(); const QRect vertical(center.right() + 1, upper.top(), upper.left() - center.right() - 1, upper.height()); const QRect horizontal(upper.left(), upper.bottom() + 1, upper.width(), lower.top() - upper.bottom() - 1); const QImage image = first.grab().toImage(); for (const QRect& gap : {vertical, horizontal}) { QVERIFY(!gap.isEmpty()); const QPoint sample = gap.center(); const qreal ratio = image.devicePixelRatio(); QCOMPARE(image.pixelColor(qRound(sample.x() * ratio), qRound(sample.y() * ratio)), native.color(QPalette::Mid)); if (gap.width() > 1 && gap.height() > 1) { const QPoint edge = gap.width() > gap.height() ? QPoint(sample.x(), gap.top()) : QPoint(gap.left(), sample.y()); QCOMPARE(image.pixelColor(qRound(edge.x() * ratio), qRound(edge.y() * ratio)), native.color(QPalette::Window)); } } }; verify(systemAtStartup); if (QTest::currentTestFailed()) return; for (bool system : {true, false, true}) { appearance->actions().at(system ? 0 : 1)->trigger(); QCoreApplication::processEvents(); verify(system); if (QTest::currentTestFailed()) return; } constants->setFloating(true); QCoreApplication::processEvents(); constants->setFloating(false); QTRY_COMPARE(constants->geometry().left(), functions->geometry().left()); verify(true); if (QTest::currentTestFailed()) return; native.setColor(QPalette::Window, QColor("#252525")); native.setColor(QPalette::Mid, QColor("#686868")); native.setColor(QPalette::Highlight, QColor("#6cb5ee")); QApplication::setPalette(native); for (MainWindow* window : {&first, &second}) QTRY_COMPARE(window->property("speedcrunchDockSeparatorNormalColor").value(), native.color(QPalette::Mid)); verify(true); } void TestDockAppearanceUi::dock_appearance_defaults_to_theme_and_persists() { MainWindowStateGuard guard; Settings* settings = guard.settings; QSettings persisted(Settings::getConfigPath() + QStringLiteral("/SpeedCrunch.ini"), QSettings::IniFormat); const QString key = QStringLiteral("SpeedCrunch/Display/DockAppearance"); persisted.remove(key); persisted.sync(); settings->load(); QCOMPARE(settings->dockAppearance, Settings::DockAppearanceSpeedCrunch); const QString scheme = settings->colorScheme; const Settings::MenuAppearance menus = settings->menuAppearance; for (const auto appearance : {Settings::DockAppearanceSystem, Settings::DockAppearanceSpeedCrunch}) { settings->dockAppearance = appearance; settings->save(); settings->dockAppearance = appearance == Settings::DockAppearanceSystem ? Settings::DockAppearanceSpeedCrunch : Settings::DockAppearanceSystem; settings->load(); QCOMPARE(settings->dockAppearance, appearance); QCOMPARE(settings->colorScheme, scheme); QCOMPARE(settings->menuAppearance, menus); } persisted.setValue(key, 99); persisted.sync(); settings->load(); QCOMPARE(settings->dockAppearance, Settings::DockAppearanceSpeedCrunch); } void TestDockAppearanceUi::dock_appearance_switches_all_windows_data() { QTest::addColumn("floating"); QTest::addColumn("themedMenus"); QTest::newRow("attached-system-menus") << false << false; QTest::newRow("attached-themed-menus") << false << true; QTest::newRow("floating-system-menus") << true << false; QTest::newRow("floating-themed-menus") << true << true; } void TestDockAppearanceUi::dock_appearance_switches_all_windows() { QFETCH(bool, floating); QFETCH(bool, themedMenus); MainWindowStateGuard guard; guard.settings->dockAppearance = Settings::DockAppearanceSpeedCrunch; guard.settings->menuAppearance = themedMenus ? Settings::MenuAppearanceSpeedCrunch : Settings::MenuAppearanceSystem; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#232136")}}); guard.settings->constantsDockVisible = true; guard.settings->formulaBookDockVisible = true; guard.settings->bitfieldVisible = true; MainWindow first(false); MainWindow second(false); first.show(); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&first)); QVERIFY(QTest::qWaitForWindowExposed(&second)); QCoreApplication::processEvents(); QMenu* firstAppearance = first.findChild(QStringLiteral("DockAppearanceMenu")); QMenu* secondAppearance = second.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(firstAppearance); QVERIFY(secondAppearance); QVERIFY(firstAppearance->actions().size() >= 2); QVERIFY(firstAppearance->actions().at(1)->isChecked()); QVERIFY(secondAppearance->actions().at(1)->isChecked()); QDockWidget* constants = first.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constants); constants->setFloating(floating); constants->show(); QTest::qWait(50); QLineEdit* search = constants->findChild(); QComboBox* combo = constants->findChild(); QTreeWidget* table = constants->findChild(); QVERIFY(search); QVERIFY(combo); QVERIFY(table); const QString themedSearchStyle = search->styleSheet(); const QString themedComboStyle = combo->styleSheet(); const QColor themedBase = table->palette().color(QPalette::Base); Editor* editor = first.findChild(); QVERIFY(editor); const QPalette editorPalette = editor->palette(); const QString editorStyle = editor->styleSheet(); const QString dockTitleStyle = constants->styleSheet(); for (int cycle = 0; cycle < 2; ++cycle) { firstAppearance->actions().at(0)->trigger(); QCoreApplication::processEvents(); QCOMPARE(guard.settings->dockAppearance, Settings::DockAppearanceSystem); QVERIFY(firstAppearance->actions().at(0)->isChecked()); QVERIFY(secondAppearance->actions().at(0)->isChecked()); QVERIFY(!firstAppearance->actions().at(1)->isChecked()); for (const auto group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (const auto role : {QPalette::Base, QPalette::Text, QPalette::Highlight, QPalette::HighlightedText}) QCOMPARE(editor->palette().color(group, role).rgba(), editorPalette.color(group, role).rgba()); } QCOMPARE(editor->styleSheet(), editorStyle); QVERIFY(constants->styleSheet().isEmpty()); for (MainWindow* window : {&first, &second}) { for (QDockWidget* dock : window->findChildren()) { QVERIFY(dock->widget()); QCOMPARE(dock->widget()->palette().color(QPalette::Window).rgba(), MenuStyle::systemPalette(dock->widget()).color(QPalette::Window).rgba()); for (QLineEdit* edit : dock->widget()->findChildren()) { QVERIFY(edit->styleSheet().isEmpty()); QCOMPARE(edit->palette().color(QPalette::Base).rgba(), MenuStyle::systemPalette(edit).color(QPalette::Base).rgba()); if (auto* themed = dynamic_cast(edit)) QVERIFY(!themed->cursorColor().isValid()); } } } QVERIFY(search->styleSheet().isEmpty()); QVERIFY(combo->styleSheet().isEmpty()); QVERIFY(table->styleSheet().isEmpty()); QCOMPARE(table->frameShape(), QFrame::NoFrame); QVERIFY(table->verticalScrollBar()->styleSheet().isEmpty()); QVERIFY(table->cornerWidget()); QVERIFY(table->cornerWidget()->styleSheet().isEmpty()); QVERIFY(!table->property("dockListHoverBackground").isValid()); QCOMPARE(table->palette().color(QPalette::Base).rgba(), MenuStyle::systemPalette(table).color(QPalette::Base).rgba()); search->setFocus(); QCoreApplication::processEvents(); combo->showPopup(); QCoreApplication::processEvents(); QVERIFY(combo->view()->styleSheet().isEmpty()); QCOMPARE(combo->view()->palette().color(QPalette::Base).rgba(), MenuStyle::systemComboPopupPalette(combo).color(QPalette::Base).rgba()); QVERIFY(!combo->findChild(QStringLiteral("speedcrunchDockComboBoxChevron"))->isVisible()); combo->hidePopup(); QVERIFY(table->model()->rowCount() > 0); const QModelIndex index = table->model()->index(0, 0); QStyleOptionViewItem option; option.initFrom(table); option.widget = table; option.rect = QRect(0, 0, 240, 30); option.state |= QStyle::State_Selected | QStyle::State_HasFocus | QStyle::State_MouseOver; QImage actual(option.rect.size(), QImage::Format_ARGB32_Premultiplied); QImage expected(actual.size(), actual.format()); actual.fill(Qt::transparent); expected.fill(Qt::transparent); QPainter actualPainter(&actual); table->itemDelegate()->paint(&actualPainter, option, index); actualPainter.end(); QPainter expectedPainter(&expected); QStyledItemDelegate nativeDelegate; nativeDelegate.paint(&expectedPainter, option, index); expectedPainter.end(); QCOMPARE(actual, expected); QTextBrowser* browser = first.findChild(); QVERIFY(browser); QCOMPARE(browser->palette().color(QPalette::Base).rgba(), MenuStyle::systemPalette(browser).color(QPalette::Base).rgba()); BitFieldWidget* bits = first.findChild(); QVERIFY(bits); for (QPushButton* button : bits->findChildren()) QVERIFY(button->styleSheet().isEmpty()); secondAppearance->actions().at(1)->trigger(); QCoreApplication::processEvents(); QCOMPARE(guard.settings->dockAppearance, Settings::DockAppearanceSpeedCrunch); QVERIFY(firstAppearance->actions().at(1)->isChecked()); QCOMPARE(constants->styleSheet(), dockTitleStyle); QCOMPARE(search->styleSheet(), themedSearchStyle); QCOMPARE(combo->styleSheet(), themedComboStyle); QCOMPARE(table->palette().color(QPalette::Base).rgba(), themedBase.rgba()); } firstAppearance->actions().at(0)->trigger(); MainWindow third(false); QMenu* thirdAppearance = third.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(thirdAppearance); QVERIFY(thirdAppearance->actions().at(0)->isChecked()); QDockWidget* thirdConstants = third.findChild(QStringLiteral("ConstantsDock")); QVERIFY(thirdConstants); QVERIFY(thirdConstants->findChild()->styleSheet().isEmpty()); QCOMPARE(guard.settings->menuAppearance, themedMenus ? Settings::MenuAppearanceSpeedCrunch : Settings::MenuAppearanceSystem); } void TestDockAppearanceUi::dock_tabs_follow_appearance_data() { QTest::addColumn("systemAtStartup"); QTest::addColumn("dark"); for (bool system : {false, true}) { for (bool dark : {false, true}) { const QString name = QStringLiteral("%1-%2") .arg(system ? "system-startup" : "theme-startup", dark ? "dark" : "light"); QTest::newRow(qPrintable(name)) << system << dark; } } } void TestDockAppearanceUi::dock_tabs_follow_appearance() { QFETCH(bool, systemAtStartup); QFETCH(bool, dark); MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([original]() { QApplication::setPalette(original); }); QPalette native = original; native.setColor(QPalette::Window, QColor(dark ? "#252525" : "#eeeeee")); native.setColor(QPalette::WindowText, QColor(dark ? "#eeeeee" : "#252525")); native.setColor(QPalette::Button, native.color(QPalette::Window)); native.setColor(QPalette::ButtonText, native.color(QPalette::WindowText)); QApplication::setPalette(native); guard.settings->dockAppearance = systemAtStartup ? Settings::DockAppearanceSystem : Settings::DockAppearanceSpeedCrunch; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->constantsDockVisible = true; guard.settings->functionsDockVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#631840")}}); MainWindow first(false); MainWindow second(false); first.show(); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&first)); QVERIFY(QTest::qWaitForWindowExposed(&second)); QMenu* appearance = first.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); const auto findTabs = [](MainWindow* window) -> QTabBar* { for (QTabBar* bar : window->findChildren()) { for (int index = 0; index < bar->count(); ++index) { if (bar->tabText(index) == QStringLiteral("Constants")) return bar; } } return nullptr; }; const auto verify = [&](MainWindow* window, bool system) { QTabBar* bar = findTabs(window); QVERIFY(bar); if (!system) { QVERIFY(bar->styleSheet().contains(QStringLiteral("border-radius: 10px"))); QVERIFY(!bar->drawBase()); return; } QVERIFY(bar->styleSheet().isEmpty()); QVERIFY(bar->drawBase()); QCOMPARE(bar->cursor().shape(), Qt::ArrowCursor); for (const auto group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (const auto role : {QPalette::Window, QPalette::WindowText, QPalette::Button, QPalette::ButtonText, QPalette::Highlight, QPalette::HighlightedText}) { QTRY_COMPARE(bar->palette().color(group, role).rgba(), MenuStyle::systemPalette(bar).color(group, role).rgba()); } } const QPoint unusedSpace(bar->width() - 2, bar->height() / 2); bool insideTab = false; for (int index = 0; index < bar->count(); ++index) insideTab |= bar->tabRect(index).contains(unusedSpace); if (!insideTab && bar->isVisible()) { const QImage image = window->grab().toImage(); const QPoint mapped = bar->mapTo(window, unusedSpace); QCOMPARE(image.pixelColor(qRound(mapped.x() * window->devicePixelRatioF()), qRound(mapped.y() * window->devicePixelRatioF())).rgba(), MenuStyle::systemPalette(bar).color(QPalette::Window).rgba()); } for (bool selected : {false, true}) { QStyleOptionTab option; option.initFrom(bar); option.rect = QRect(0, 0, 140, 32); option.shape = bar->shape(); option.text = QStringLiteral("Constants"); option.position = QStyleOptionTab::Beginning; option.state.setFlag(QStyle::State_Selected, selected); QImage actual(option.rect.size(), QImage::Format_ARGB32_Premultiplied); QImage expected(actual.size(), actual.format()); actual.fill(Qt::transparent); expected.fill(Qt::transparent); QPainter actualPainter(&actual); bar->style()->drawControl(QStyle::CE_TabBarTab, &option, &actualPainter, bar); actualPainter.end(); QPainter expectedPainter(&expected); QApplication::style()->drawControl(QStyle::CE_TabBarTab, &option, &expectedPainter, bar); expectedPainter.end(); QCOMPARE(actual, expected); } }; QCoreApplication::processEvents(); verify(&first, systemAtStartup); verify(&second, systemAtStartup); for (bool system : {true, false, true, false}) { appearance->actions().at(system ? 0 : 1)->trigger(); QCoreApplication::processEvents(); verify(&first, system); verify(&second, system); } appearance->actions().at(0)->trigger(); native.setColor(QPalette::Window, QColor(dark ? "#353535" : "#dddddd")); QApplication::setPalette(native); QCoreApplication::processEvents(); verify(&first, true); verify(&second, true); QDockWidget* functions = first.findChild(QStringLiteral("FunctionsDock")); QDockWidget* constants = first.findChild(QStringLiteral("ConstantsDock")); QVERIFY(functions); QVERIFY(constants); functions->setFloating(true); functions->setFloating(false); first.tabifyDockWidget(constants, functions); functions->show(); QCoreApplication::processEvents(); verify(&first, true); QVERIFY(QMetaObject::invokeMethod(&first, "setHistoryDockVisible", Q_ARG(bool, true))); QCoreApplication::processEvents(); verify(&first, true); QCOMPARE(guard.settings->menuAppearance, Settings::MenuAppearanceSpeedCrunch); } void TestDockAppearanceUi::dock_headers_follow_appearance_data() { QTest::addColumn("systemAtStartup"); QTest::addColumn("floating"); QTest::addColumn("dark"); for (bool system : {false, true}) { for (bool floating : {false, true}) { for (bool dark : {false, true}) { const QString name = QStringLiteral("%1-%2-%3") .arg(system ? "system-startup" : "theme-startup", floating ? "floating" : "attached", dark ? "dark" : "light"); QTest::newRow(qPrintable(name)) << system << floating << dark; } } } } void TestDockAppearanceUi::dock_headers_follow_appearance() { QFETCH(bool, systemAtStartup); QFETCH(bool, floating); QFETCH(bool, dark); MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([original]() { QApplication::setPalette(original); }); QPalette native = original; native.setColor(QPalette::Window, QColor(dark ? "#252525" : "#eeeeee")); native.setColor(QPalette::WindowText, QColor(dark ? "#eeeeee" : "#252525")); native.setColor(QPalette::Button, native.color(QPalette::Window)); native.setColor(QPalette::ButtonText, native.color(QPalette::WindowText)); QApplication::setPalette(native); guard.settings->dockAppearance = systemAtStartup ? Settings::DockAppearanceSystem : Settings::DockAppearanceSpeedCrunch; guard.settings->constantsDockVisible = true; guard.settings->functionsDockVisible = true; guard.settings->formulaBookDockVisible = true; guard.settings->bitfieldVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#631840")}}); MainWindow first(false); MainWindow second(false); first.show(); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&first)); QVERIFY(QTest::qWaitForWindowExposed(&second)); QMenu* appearance = first.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); QDockWidget* constants = first.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constants); constants->setFloating(floating); constants->show(); QDockWidget reference; reference.setPalette(native); reference.ensurePolished(); const QStringList names {QStringLiteral("qt_dockwidget_closebutton"), QStringLiteral("qt_dockwidget_floatbutton")}; const auto verifyNative = [&](QDockWidget* dock) { QVERIFY(dock->styleSheet().isEmpty()); for (auto group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (auto role : {QPalette::Window, QPalette::WindowText, QPalette::Button, QPalette::ButtonText}) QCOMPARE(dock->palette().color(group, role).rgba(), native.color(group, role).rgba()); } QStyleOptionDockWidget option; option.initFrom(dock); option.rect = QRect(0, 0, 240, 30); option.title = dock->windowTitle(); option.closable = dock->features().testFlag(QDockWidget::DockWidgetClosable); option.floatable = dock->features().testFlag(QDockWidget::DockWidgetFloatable); option.movable = dock->features().testFlag(QDockWidget::DockWidgetMovable); option.verticalTitleBar = dock->features().testFlag(QDockWidget::DockWidgetVerticalTitleBar); QImage actual(option.rect.size(), QImage::Format_ARGB32_Premultiplied); actual.fill(Qt::transparent); QImage expected = actual; QPainter actualPainter(&actual); dock->style()->drawControl(QStyle::CE_DockWidgetTitle, &option, &actualPainter, dock); actualPainter.end(); QPainter expectedPainter(&expected); QApplication::style()->drawControl(QStyle::CE_DockWidgetTitle, &option, &expectedPainter, dock); expectedPainter.end(); QCOMPARE(actual, expected); for (const QString& name : names) { QAbstractButton* button = dock->findChild(name, Qt::FindDirectChildrenOnly); QAbstractButton* referenceButton = reference.findChild(name); QVERIFY(button); QVERIFY(referenceButton); QVERIFY(!button->property("speedcrunchDockHeaderButton").toBool()); QVERIFY(button->styleSheet().isEmpty()); QCOMPARE(button->minimumSize(), referenceButton->minimumSize()); QCOMPARE(button->maximumSize(), referenceButton->maximumSize()); QCOMPARE(button->iconSize(), referenceButton->iconSize()); QCOMPARE(button->cursor().shape(), referenceButton->cursor().shape()); const auto standard = name == names.first() ? QStyle::SP_TitleBarCloseButton : QStyle::SP_TitleBarNormalButton; const QImage icon = button->icon().pixmap(QSize(24, 24)).toImage(); const QImage nativeIcon = QApplication::style()->standardIcon(standard, &option, dock).pixmap(QSize(24, 24)).toImage(); QCOMPARE(icon, nativeIcon); const QPoint center = button->rect().center(); QEnterEvent enter(center, button->mapTo(button->window(), center), button->mapToGlobal(center)); QCoreApplication::sendEvent(button, &enter); QCOMPARE(button->icon().pixmap(QSize(24, 24)).toImage(), nativeIcon); } }; for (bool system : {systemAtStartup, !systemAtStartup, systemAtStartup, true}) { appearance->actions().at(system ? 0 : 1)->trigger(); QCoreApplication::processEvents(); for (MainWindow* window : {&first, &second}) { for (QDockWidget* dock : window->findChildren()) { if (system) { verifyNative(dock); if (QTest::currentTestFailed()) return; } else { QVERIFY(!dock->styleSheet().isEmpty()); for (const QString& name : names) { QAbstractButton* button = dock->findChild(name, Qt::FindDirectChildrenOnly); QVERIFY(button); QVERIFY(button->property("speedcrunchDockHeaderButton").toBool()); QCOMPARE(button->size(), QSize(18, 18)); } } } } } for (bool floatingState : {true, false}) { constants->setFloating(floatingState); QCoreApplication::processEvents(); verifyNative(constants); if (QTest::currentTestFailed()) return; } native.setColor(QPalette::Window, QColor(dark ? "#353535" : "#dddddd")); native.setColor(QPalette::Button, native.color(QPalette::Window)); QApplication::setPalette(native); QCoreApplication::processEvents(); for (MainWindow* window : {&first, &second}) { for (QDockWidget* dock : window->findChildren()) { QTRY_COMPARE(dock->palette().color(QPalette::Window).rgba(), native.color(QPalette::Window).rgba()); verifyNative(dock); if (QTest::currentTestFailed()) return; } } MainWindow third(false); for (QDockWidget* dock : third.findChildren()) { verifyNative(dock); if (QTest::currentTestFailed()) return; } QAbstractButton* floatButton = constants->findChild(names.last()); QTest::mouseClick(floatButton, Qt::LeftButton); QVERIFY(constants->isFloating()); constants->setFloating(false); QCoreApplication::processEvents(); verifyNative(constants); if (QTest::currentTestFailed()) return; QAbstractButton* closeButton = constants->findChild(names.first()); QTest::mouseClick(closeButton, Qt::LeftButton); QVERIFY(!constants->isVisible()); } void TestDockAppearanceUi::system_dock_headers_paint_system_background_data() { QTest::addColumn("switchFromTheme"); QTest::addColumn("darkSystem"); for (bool switching : {false, true}) { for (bool dark : {false, true}) { const QString name = QStringLiteral("%1-%2") .arg(switching ? "switch-from-theme" : "system-startup", dark ? "dark-system" : "light-system"); QTest::newRow(qPrintable(name)) << switching << dark; } } } void TestDockAppearanceUi::system_dock_headers_paint_system_background() { QFETCH(bool, switchFromTheme); QFETCH(bool, darkSystem); MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([original]() { QApplication::setPalette(original); }); QPalette native = original; native.setColor(QPalette::Window, QColor(darkSystem ? "#252525" : "#eeeeee")); native.setColor(QPalette::WindowText, QColor(darkSystem ? "#eeeeee" : "#252525")); QApplication::setPalette(native); guard.settings->dockAppearance = switchFromTheme ? Settings::DockAppearanceSpeedCrunch : Settings::DockAppearanceSystem; guard.settings->constantsDockVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#631840")}}); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(dock); if (switchFromTheme) { QMenu* appearance = window.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); appearance->actions().first()->trigger(); } QCoreApplication::processEvents(); // Render the whole window so a transparent header exposes its parent fill. // Painting CE_DockWidgetTitle alone cannot detect that background leak. const auto verifyHeader = [&]() { const QAbstractButton* button = dock->findChild( QStringLiteral("qt_dockwidget_floatbutton"), Qt::FindDirectChildrenOnly); QVERIFY(button); const QPoint sample(button->geometry().left() - 8, button->geometry().center().y()); QVERIFY(dock->rect().contains(sample)); QVERIFY(sample.y() < dock->widget()->geometry().top()); QStyleOptionDockWidget option; option.initFrom(dock); option.rect = QRect(0, 0, dock->width(), dock->widget()->geometry().top()); option.title = dock->windowTitle(); option.closable = dock->features().testFlag(QDockWidget::DockWidgetClosable); option.floatable = dock->features().testFlag(QDockWidget::DockWidgetFloatable); option.movable = dock->features().testFlag(QDockWidget::DockWidgetMovable); // Preserve any background the native title painter adds, such as the // Windows style's gradient, over the system window surface. QImage expected(option.rect.size(), QImage::Format_ARGB32_Premultiplied); expected.fill(native.color(QPalette::Window)); QPainter painter(&expected); QApplication::style()->drawControl(QStyle::CE_DockWidgetTitle, &option, &painter, dock); painter.end(); const QImage image = window.grab().toImage(); const QPoint position = dock->mapTo(&window, sample); QCOMPARE(image.pixelColor(qRound(position.x() * image.devicePixelRatio()), qRound(position.y() * image.devicePixelRatio())), expected.pixelColor(sample)); }; verifyHeader(); if (QTest::currentTestFailed()) return; native.setColor(QPalette::Window, QColor(darkSystem ? "#353535" : "#dddddd")); QApplication::setPalette(native); QTRY_COMPARE(dock->palette().color(QPalette::Window), native.color(QPalette::Window)); verifyHeader(); } void TestDockAppearanceUi::system_dock_controls_keep_aligned_rows_data() { QTest::addColumn("switchFromTheme"); QTest::addColumn("wide"); QTest::addColumn("subdomains"); QTest::addColumn("largeFont"); for (bool switching : {false, true}) { for (bool wide : {false, true}) { for (bool subdomains : {false, true}) { for (bool largeFont : {false, true}) { const QString name = QStringLiteral("%1-%2-%3-%4") .arg(switching ? "switch" : "startup", wide ? "wide" : "compact", subdomains ? "subdomains" : "no-subdomains", largeFont ? "large-font" : "default-font"); QTest::newRow(qPrintable(name)) << switching << wide << subdomains << largeFont; } } } } } void TestDockAppearanceUi::system_dock_controls_keep_aligned_rows() { QFETCH(bool, switchFromTheme); QFETCH(bool, wide); QFETCH(bool, subdomains); QFETCH(bool, largeFont); MainWindowStateGuard guard; guard.settings->dockAppearance = switchFromTheme ? Settings::DockAppearanceSpeedCrunch : Settings::DockAppearanceSystem; guard.settings->constantsDockVisible = true; guard.settings->constantsDockDomain.clear(); guard.settings->constantsDockSubdomain.clear(); guard.settings->functionsDockVisible = true; guard.settings->sessionLayoutJson.clear(); guard.settings->windowState.clear(); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); if (largeFont) { QFont font = window.font(); font.setPointSize(font.pointSize() + 4); window.setFont(font); } if (switchFromTheme) { QMenu* appearance = window.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); appearance->actions().at(0)->trigger(); } for (const char* name : {"ConstantsDock", "FunctionsDock"}) { QDockWidget* dock = window.findChild(QString::fromLatin1(name)); QVERIFY(dock); dock->setFloating(true); dock->resize(wide ? 900 : 380, 480); dock->show(); if (auto* constants = qobject_cast(dock->widget())) { QComboBox* domain = constants->findChild(); QVERIFY(domain); constants->restoreState(domain->itemText(subdomains ? 0 : 1), QString(), QString()); } QTest::qWait(50); QWidget* content = dock->widget(); QLineEdit* search = content->findChild(); QVERIFY(search); const auto layoutRect = [content](QComboBox* combo) { QStyleOptionComboBox option; option.initFrom(combo); option.rect = combo->rect(); QRect rect = combo->style()->subElementRect(QStyle::SE_ComboBoxLayoutItem, &option, combo); if (rect.isEmpty()) rect = combo->rect(); rect.translate(combo->mapTo(content, QPoint())); return rect; }; QList combos; for (QComboBox* combo : content->findChildren()) { if (combo->isVisible()) { combos.append(layoutRect(combo)); } } QVERIFY(!combos.isEmpty()); std::sort(combos.begin(), combos.end(), [](const QRect& a, const QRect& b) { return a.top() == b.top() ? a.left() < b.left() : a.top() < b.top(); }); const QRect searchRect(search->mapTo(content, QPoint()), search->size()); QCOMPARE(combos.first().left(), searchRect.left()); QCOMPARE(combos.last().right(), searchRect.right()); QCOMPARE(combos.first().top(), UiConfig::DockSearchRowVerticalPadding); QCOMPARE(searchRect.top() - (combos.last().bottom() + 1), UiConfig::DockSearchRowVerticalPadding); if (QString::fromLatin1(name) == QStringLiteral("ConstantsDock")) QCOMPARE(combos.size(), subdomains ? 2 : 1); if (combos.size() == 2) { if (wide) QCOMPARE(combos.first().top(), combos.last().top()); else QCOMPARE(combos.last().top() - (combos.first().bottom() + 1), UiConfig::DockSearchRowVerticalPadding); } } } void TestDockAppearanceUi::system_docks_follow_palette_and_theme_changes() { MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([original]() { QApplication::setPalette(original); }); guard.settings->dockAppearance = Settings::DockAppearanceSpeedCrunch; guard.settings->constantsDockVisible = true; MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(dock); QLineEdit* search = dock->findChild(); QTreeWidget* table = dock->findChild(); QVERIFY(search); QVERIFY(table); search->setText(QStringLiteral("no matching constant 987654321")); QLabel* noMatch = nullptr; QTRY_VERIFY(([&]() { for (QLabel* label : table->viewport()->findChildren()) { if (label->property("dockListNoMatchLabel").toBool()) noMatch = label; } return noMatch != nullptr; })()); QMenu* appearance = window.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); appearance->actions().at(0)->trigger(); QVERIFY(!noMatch->styleSheet().contains(QStringLiteral("color:"))); QPalette changed = original; changed.setColor(QPalette::Base, QColor("#304050")); changed.setColor(QPalette::Text, QColor("#f1f2f3")); changed.setColor(QPalette::Window, QColor("#405060")); changed.setColor(QPalette::WindowText, QColor("#f1f2f3")); changed.setColor(QPalette::Highlight, QColor("#108030")); QApplication::setPalette(changed); QTRY_COMPARE(search->palette().color(QPalette::Base).rgba(), changed.color(QPalette::Base).rgba()); QTRY_COMPARE(table->palette().color(QPalette::Highlight).rgba(), changed.color(QPalette::Highlight).rgba()); QTRY_COMPARE(noMatch->palette().color(QPalette::WindowText).rgba(), changed.color(QPalette::WindowText).rgba()); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#730a24")}}); window.colorSchemeChanged(); QCoreApplication::processEvents(); QCOMPARE(search->palette().color(QPalette::Base).rgba(), changed.color(QPalette::Base).rgba()); QVERIFY(search->styleSheet().isEmpty()); QVERIFY(table->styleSheet().isEmpty()); } void TestDockAppearanceUi::dock_header_buttons_render_full_size_data() { QTest::addColumn("framed"); QTest::addColumn("background"); QTest::newRow("dark-framed") << true << QStringLiteral("#402034"); QTest::newRow("dark-unframed") << false << QStringLiteral("#402034"); QTest::newRow("light-framed") << true << QStringLiteral("#f4e8ee"); QTest::newRow("light-unframed") << false << QStringLiteral("#f4e8ee"); } void TestDockAppearanceUi::dock_header_buttons_render_full_size() { QFETCH(bool, framed); QFETCH(QString, background); MainWindowStateGuard guard; Settings* settings = guard.settings; settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); settings->windowState.clear(); settings->constantsDockVisible = true; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(dock != nullptr); dock->setFloating(false); dock->show(); dock->raise(); QCoreApplication::processEvents(); QAbstractButton* closeButton = dock->findChild( QStringLiteral("qt_dockwidget_closebutton")); QAbstractButton* floatButton = dock->findChild( QStringLiteral("qt_dockwidget_floatbutton")); QVERIFY(closeButton != nullptr); QVERIFY(floatButton != nullptr); for (QAbstractButton* button : {closeButton, floatButton}) { auto* style = new DockHeaderButtonTestStyle(framed); style->setParent(button); button->setStyle(style); QCOMPARE(button->style()->styleHint(QStyle::SH_DockWidget_ButtonsHaveFrame, nullptr, button), int(framed)); QCOMPARE(button->style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, button), 16); QVERIFY(button->isVisible()); for (bool hovered : {false, true}) { QEvent hoverEvent(hovered ? QEvent::Enter : QEvent::Leave); QCoreApplication::sendEvent(button, &hoverEvent); const QImage rendered = button->grab().toImage(); const qreal dpr = rendered.devicePixelRatio(); const QImage expected = button->icon().pixmap(button->iconSize(), dpr).toImage(); QCOMPARE(rendered.size(), expected.size()); // Compare the actual widget's symbol with the full-size source icon. // Checking iconSize() alone misses Qt's private dock-button scaling. const QRect symbolRect(qRound(4 * dpr), qRound(4 * dpr), qRound(10 * dpr), qRound(10 * dpr)); for (int y = symbolRect.top(); y <= symbolRect.bottom(); ++y) { for (int x = symbolRect.left(); x <= symbolRect.right(); ++x) { QVERIFY2(colorsAreClose(rendered.pixelColor(x, y), expected.pixelColor(x, y), 3), qPrintable(QStringLiteral("%1 symbol differs at %2,%3") .arg(button->objectName()).arg(x).arg(y))); } } } } QTest::mouseClick(floatButton, Qt::LeftButton); QTRY_VERIFY(dock->isFloating()); dock->setFloating(false); QTRY_VERIFY(closeButton->isVisible()); QTest::mouseClick(closeButton, Qt::LeftButton); QTRY_VERIFY(!dock->isVisible()); } void TestDockAppearanceUi::dock_header_buttons_render_full_size_on_first_run_data() { dock_header_buttons_render_full_size_data(); } void TestDockAppearanceUi::dock_header_buttons_render_full_size_on_first_run() { Settings* settings = Settings::instance(); const bool oldHasNumberFormatStyleSetting = settings->hasNumberFormatStyleSetting; const auto restoreSettings = qScopeGuard([&]() { settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; }); settings->hasNumberFormatStyleSetting = false; // Exercise the shared fixture with fresh first-run settings; no window // guard should need to suppress this dialog on its own. UiTestFixture::resetSettings(); QVERIFY(settings->hasNumberFormatStyleSetting); dock_header_buttons_render_full_size(); QVERIFY(QApplication::activeModalWidget() == nullptr); QVERIFY(settings->hasNumberFormatStyleSetting); } void TestDockAppearanceUi::dock_header_buttons_stay_centered_in_title_bar_data() { QTest::addColumn("fontPixelSize"); QTest::addColumn("verticalTitleBar"); QTest::newRow("small-horizontal") << 9 << false; QTest::newRow("normal-horizontal") << 13 << false; QTest::newRow("large-horizontal") << 22 << false; QTest::newRow("small-vertical") << 9 << true; QTest::newRow("large-vertical") << 22 << true; } void TestDockAppearanceUi::dock_header_buttons_stay_centered_in_title_bar() { QFETCH(int, fontPixelSize); QFETCH(bool, verticalTitleBar); MainWindowStateGuard guard; guard.settings->windowState.clear(); guard.settings->constantsDockVisible = true; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(dock != nullptr); dock->setFloating(false); dock->show(); dock->raise(); if (verticalTitleBar) dock->setFeatures(dock->features() | QDockWidget::DockWidgetVerticalTitleBar); QFont font = dock->font(); font.setPixelSize(fontPixelSize); dock->setFont(font); for (const QSize size : {QSize(800, 600), QSize(1050, 750)}) { window.resize(size); QCoreApplication::processEvents(); const int titleExtent = verticalTitleBar ? dock->widget()->geometry().left() : dock->widget()->geometry().top(); QVERIFY(titleExtent >= 18); for (const QString& name : {QStringLiteral("qt_dockwidget_closebutton"), QStringLiteral("qt_dockwidget_floatbutton")}) { QAbstractButton* button = dock->findChild(name); QVERIFY(button != nullptr); QVERIFY(button->isVisible()); const QRect rect = button->geometry(); const int twiceButtonCenter = verticalTitleBar ? 2 * rect.x() + rect.width() : 2 * rect.y() + rect.height(); QVERIFY2(qAbs(twiceButtonCenter - titleExtent) <= 1, qPrintable(QStringLiteral("%1 center %2 differs from title center %3") .arg(name).arg(twiceButtonCenter / 2.0) .arg(titleExtent / 2.0))); } } } void TestDockAppearanceUi::dock_header_buttons_keep_theme_after_redocking_data() { QTest::addColumn("background"); QTest::addColumn("dockName"); QTest::newRow("dark-constants") << QStringLiteral("#402034") << QStringLiteral("ConstantsDock"); QTest::newRow("light-constants") << QStringLiteral("#f4e8ee") << QStringLiteral("ConstantsDock"); QTest::newRow("dark-functions") << QStringLiteral("#402034") << QStringLiteral("FunctionsDock"); QTest::newRow("light-functions") << QStringLiteral("#f4e8ee") << QStringLiteral("FunctionsDock"); } void TestDockAppearanceUi::dock_header_buttons_keep_theme_after_redocking() { QFETCH(QString, background); QFETCH(QString, dockName); MainWindowStateGuard guard; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); guard.settings->windowState.clear(); guard.settings->constantsDockVisible = true; guard.settings->functionsDockVisible = true; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(dockName); QVERIFY(dock != nullptr); dock->setFloating(false); dock->show(); dock->raise(); QCoreApplication::processEvents(); const QStringList buttonNames {QStringLiteral("qt_dockwidget_closebutton"), QStringLiteral("qt_dockwidget_floatbutton")}; QList buttons; QList expectedIcons; for (const QString& name : buttonNames) { QAbstractButton* button = dock->findChild(name); QVERIFY(button != nullptr); button->setAttribute(Qt::WA_UnderMouse, false); QEvent leaveEvent(QEvent::Leave); QCoreApplication::sendEvent(button, &leaveEvent); const QImage icon = button->icon().pixmap(button->iconSize()).toImage(); QVERIFY(!icon.isNull()); QVERIFY(colorsAreClose(icon.pixelColor(2, 9), button->property("speedcrunchDockHeaderButtonFill").value())); buttons.append(button); expectedIcons.append(icon); } for (int cycle = 0; cycle < 2; ++cycle) { dock->setFloating(true); QVERIFY(dock->isFloating()); dock->setFloating(false); QVERIFY(!dock->isFloating()); // Check before a paint, queued theme update, or hover can repair an icon. for (bool processEvents : {false, true}) { if (processEvents) QCoreApplication::processEvents(); for (int i = 0; i < buttons.size(); ++i) { QVERIFY(!buttons.at(i)->underMouse()); const QImage icon = buttons.at(i)->icon().pixmap(buttons.at(i)->iconSize()).toImage(); QVERIFY2(icon == expectedIcons.at(i), qPrintable(buttonNames.at(i))); } } } } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testdockappearanceui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testdocklayoutui.cpp000066400000000000000000002545601526573132500254220ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" using namespace MainWindowTestHelpers; class TestDockLayoutUi : public QObject { Q_OBJECT private slots: void initTestCase(); void init() { UiTestFixture::resetSettings(); } void lazy_docks_stay_uncreated_until_opened(); void lazy_docks_restore_saved_layouts_data(); void lazy_docks_restore_saved_layouts(); void lazy_docks_restore_each_windows_open_panels(); void opening_docks_keeps_floating_panels_independent(); void floating_docks_survive_repeated_quit_data(); void floating_docks_survive_repeated_quit(); void dock_list_selected_row_keeps_primary_fill_while_hovered(); void functions_dock_retranslates_domain_label_after_language_change(); void side_docks_keep_full_height_data(); void side_docks_keep_full_height(); void dock_search_rows_use_configured_vertical_padding_data(); void dock_search_rows_use_configured_vertical_padding(); void themed_dock_controls_have_equal_visible_gaps_data(); void themed_dock_controls_have_equal_visible_gaps(); void themed_dock_lists_use_compact_spacing_data(); void themed_dock_lists_use_compact_spacing(); void dock_first_control_matches_shared_vertical_spacing_data(); void dock_first_control_matches_shared_vertical_spacing(); void formula_book_text_scales_with_zoom_data(); void formula_book_text_scales_with_zoom(); void formula_book_links_follow_dock_appearance_data(); void formula_book_links_follow_dock_appearance(); void formula_book_ignores_repeated_appearance_events_data(); void formula_book_ignores_repeated_appearance_events(); void formula_book_combines_palette_changes(); void startup_styling_keeps_formula_book_document(); void formula_book_retranslation_refreshes_cached_page(); void restored_constants_dock_empty_filter_fills_header(); void dock_scroll_corner_uses_scrollbar_track_fill(); void dock_separator_style_uses_primary_while_hovered_or_dragged(); void constants_dock_uses_configured_narrow_minimum_width(); void view_dock_menu_tracks_and_changes_only_active_window(); void closing_and_reopening_docks_keeps_attached_widgets(); void dock_column_orders_survive_relaunch_data(); void dock_column_orders_survive_relaunch(); void dock_column_orders_are_per_window(); void invalid_dock_column_orders_use_defaults_data(); void invalid_dock_column_orders_use_defaults(); }; void TestDockLayoutUi::dock_column_orders_survive_relaunch_data() { QTest::addColumn("workspaceLayout"); QTest::addColumn("hidden"); QTest::newRow("open-workspace") << true << false; QTest::newRow("hidden-workspace") << true << true; QTest::newRow("open-settings") << false << false; QTest::newRow("hidden-settings") << false << true; } void TestDockLayoutUi::dock_column_orders_survive_relaunch() { QFETCH(bool, workspaceLayout); QFETCH(bool, hidden); MainWindowStateGuard guard; PrivateSessionStorage storage; const QStringList names {QStringLiteral("ConstantsDock"), QStringLiteral("FunctionsDock"), QStringLiteral("VariablesDock"), QStringLiteral("UserFunctionsDock"), QStringLiteral("UserUnitsDock")}; const QList setters {"setConstantsDockVisible", "setFunctionsDockVisible", "setVariablesDockVisible", "setUserFunctionsDockVisible", "setUserUnitsDockVisible"}; for (int launch = 0; launch < 3; ++launch) { if (launch != 0) { guard.settings->load(); if (!workspaceLayout) guard.settings->sessionLayoutJson.clear(); } MainWindow window(launch != 0); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); // Save once without ever opening the hidden panels on this launch. if (hidden && launch == 1) { QCOMPARE(window.findChildren().size(), 0); } else { for (int i = 0; i < names.size(); ++i) { QVERIFY(QMetaObject::invokeMethod(&window, setters.at(i).constData(), Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QDockWidget* dock = window.findChild(names.at(i)); QVERIFY(dock); QTreeWidget* table = dock->findChild(); QVERIFY(table); QHeaderView* header = table->header(); if (launch == 0) { for (int visual = 0; visual < header->count(); ++visual) QCOMPARE(header->logicalIndex(visual), visual); header->moveSection(header->count() - 1, 0); QEvent languageChange(QEvent::LanguageChange); QCoreApplication::sendEvent(table->parentWidget(), &languageChange); QCoreApplication::processEvents(); } for (int visual = 0; visual < header->count(); ++visual) QCOMPARE(header->logicalIndex(visual), (visual + header->count() - 1) % header->count()); if (hidden) dock->hide(); } } window.persistSessionAndSettingsForShutdown(); } } void TestDockLayoutUi::dock_column_orders_are_per_window() { MainWindowStateGuard guard; PrivateSessionStorage storage; { MainWindow first(false); MainWindow second(false); for (MainWindow* window : {&first, &second}) { QVERIFY(QMetaObject::invokeMethod(window, "setVariablesDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QHeaderView* header = window->findChild()->findChild()->header(); header->moveSection(window == &first ? 2 : 1, 0); window->findChild()->setText(QStringLiteral("2+3")); QVERIFY(QMetaObject::invokeMethod(window, "evaluateEditorExpression", Qt::DirectConnection)); } first.persistSessionAndSettingsForShutdown(); } guard.settings->load(); QJsonObject layout = QJsonDocument::fromJson(guard.settings->sessionLayoutJson.toUtf8()).object(); const QJsonArray windows = layout.value(QStringLiteral("windows")).toArray(); QCOMPARE(windows.size(), 2); const auto selectWindow = [&](int index) { const QJsonObject record = windows.at(index).toObject(); layout.insert(QStringLiteral("windows"), QJsonArray{record}); layout.insert(QStringLiteral("activeWindow"), record.value(QStringLiteral("id"))); guard.settings->sessionLayoutJson = QString::fromUtf8(QJsonDocument(layout).toJson(QJsonDocument::Compact)); }; // Restore each record without relying on the once-per-process window spawn. selectWindow(0); MainWindow restored; selectWindow(1); MainWindow other; restored.show(); other.show(); for (MainWindow* window : {&restored, &other}) { QTRY_COMPARE(window->findChild()->session()->historySize(), 1); VariableListWidget* variables = window->findChild(); QVERIFY(variables); QHeaderView* header = variables->findChild()->header(); const QList expected = window == &restored ? QList{2, 0, 1} : QList{1, 0, 2}; for (int visual = 0; visual < expected.size(); ++visual) QCOMPARE(header->logicalIndex(visual), expected.at(visual)); } } void TestDockLayoutUi::invalid_dock_column_orders_use_defaults_data() { QTest::addColumn("order"); QTest::newRow("duplicate") << QJsonArray{1, 1, 0}; QTest::newRow("negative") << QJsonArray{2, -1, 0}; QTest::newRow("out-of-range") << QJsonArray{2, 3, 0}; QTest::newRow("missing-column") << QJsonArray{2, 0}; QTest::newRow("extra-column") << QJsonArray{2, 0, 1, 3}; QTest::newRow("text") << QJsonArray{2, QStringLiteral("1"), 0}; QTest::newRow("fraction") << QJsonArray{2, 0.5, 0}; } void TestDockLayoutUi::invalid_dock_column_orders_use_defaults() { QFETCH(QJsonArray, order); Settings::instance()->dockColumnOrdersJson = QString::fromUtf8(QJsonDocument( QJsonObject{{QStringLiteral("VariablesDock"), order}}).toJson(QJsonDocument::Compact)); MainWindow window(false); QVERIFY(QMetaObject::invokeMethod(&window, "setVariablesDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QTreeWidget* table = window.findChild()->findChild(); for (int visual = 0; visual < table->columnCount(); ++visual) QCOMPARE(table->header()->logicalIndex(visual), visual); } void TestDockLayoutUi::initTestCase() { // Fail before a file-operation test can open an unhandled error dialog. for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) { QVERIFY2(QDir().mkpath(path), qPrintable(QStringLiteral("Cannot create test storage at %1").arg(path))); QTemporaryFile probe(QDir(path).filePath(QStringLiteral("storage-probe-XXXXXX"))); QVERIFY2(probe.open(), qPrintable(QStringLiteral("Cannot write test storage at %1: %2") .arg(path, probe.errorString()))); } } void TestDockLayoutUi::lazy_docks_stay_uncreated_until_opened() { MainWindowStateGuard guard; PrivateSessionStorage storage; MainWindow window(false); QCOMPARE(window.findChildren().size(), 0); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); QVERIFY(editor); editor->setText(QStringLiteral("6*7")); QVERIFY(QMetaObject::invokeMethod(&window, "evaluateEditorExpression", Qt::DirectConnection)); QCOMPARE(window.findChild()->session()->historySize(), 1); QCOMPARE(window.findChildren().size(), 0); const QStringList setters {QStringLiteral("setFormulaBookDockVisible"), QStringLiteral("setConstantsDockVisible"), QStringLiteral("setFunctionsDockVisible"), QStringLiteral("setHistoryDockVisible"), QStringLiteral("setVariablesDockVisible"), QStringLiteral("setUserFunctionsDockVisible"), QStringLiteral("setUserUnitsDockVisible"), QStringLiteral("setBitfieldVisible")}; for (int i = 0; i < setters.size(); ++i) { const QByteArray setter = setters.at(i).toLatin1(); const auto setVisible = [&](bool visible) { return i == 7 ? QMetaObject::invokeMethod(&window, setter.constData(), Qt::DirectConnection, Q_ARG(bool, visible)) : QMetaObject::invokeMethod(&window, setter.constData(), Qt::DirectConnection, Q_ARG(bool, visible), Q_ARG(bool, false)); }; QVERIFY(setVisible(true)); QCoreApplication::processEvents(); QCOMPARE(window.findChildren().size(), i + 1); QVERIFY(setVisible(false)); QVERIFY(setVisible(true)); QCOMPARE(window.findChildren().size(), i + 1); QVERIFY(setVisible(false)); } } void TestDockLayoutUi::lazy_docks_restore_saved_layouts_data() { QTest::addColumn("format"); QTest::newRow("workspace-open-dock-list") << 0; QTest::newRow("older-workspace") << 1; QTest::newRow("older-window-state") << 2; } void TestDockLayoutUi::lazy_docks_restore_saved_layouts() { QFETCH(int, format); MainWindowStateGuard guard; PrivateSessionStorage storage; QByteArray state; QString layout; QPoint floatingPosition; { MainWindow source(false); source.resize(960, 640); source.show(); QVERIFY(QTest::qWaitForWindowExposed(&source)); for (const char* setter : {"setConstantsDockVisible", "setFunctionsDockVisible", "setUserUnitsDockVisible"}) QVERIFY(QMetaObject::invokeMethod(&source, setter, Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QDockWidget* units = source.findChild(QStringLiteral("UserUnitsDock")); QVERIFY(units); units->setFloating(true); units->move(160, 120); units->resize(350, 280); floatingPosition = units->pos(); units->hide(); source.findChild(QStringLiteral("ConstantsDock"))->raise(); QCoreApplication::processEvents(); source.persistSessionAndSettingsForShutdown(); state = source.saveState(1); layout = guard.settings->sessionLayoutJson; } UiTestFixture::resetSettings(); guard.settings->windowState = state; if (format != 2) { if (format == 1) { QJsonObject saved = QJsonDocument::fromJson(layout.toUtf8()).object(); QJsonArray windows = saved.value(QStringLiteral("windows")).toArray(); QJsonObject window = windows.first().toObject(); window.remove(QStringLiteral("openDocks")); windows[0] = window; saved.insert(QStringLiteral("windows"), windows); layout = QString::fromUtf8(QJsonDocument(saved).toJson(QJsonDocument::Compact)); } guard.settings->sessionLayoutJson = layout; } { MainWindow restored; restored.show(); QVERIFY(QTest::qWaitForWindowExposed(&restored)); QTRY_COMPARE(restored.findChildren().size(), 2); QDockWidget* constants = restored.findChild(QStringLiteral("ConstantsDock")); QDockWidget* functions = restored.findChild(QStringLiteral("FunctionsDock")); QVERIFY(constants && functions); QVERIFY(!constants->isHidden() && !functions->isHidden()); QVERIFY(restored.tabifiedDockWidgets(constants).contains(functions)); QTabBar* dockTabs = nullptr; for (QTabBar* bar : restored.findChildren()) { for (int i = 0; i < bar->count(); ++i) { if (bar->tabText(i) == constants->windowTitle()) dockTabs = bar; } } QVERIFY(dockTabs); QCOMPARE(dockTabs->tabText(dockTabs->currentIndex()), constants->windowTitle()); QVERIFY(!restored.findChild(QStringLiteral("UserUnitsDock"))); // Saving before opening the absent dock must retain its saved placement. restored.persistSessionAndSettingsForShutdown(); } { MainWindow reopened; reopened.show(); QVERIFY(QTest::qWaitForWindowExposed(&reopened)); QTRY_COMPARE(reopened.findChildren().size(), 2); QVERIFY(QMetaObject::invokeMethod(&reopened, "setUserUnitsDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QDockWidget* units = reopened.findChild(QStringLiteral("UserUnitsDock")); QVERIFY(units); QVERIFY(units->isFloating()); QCOMPARE(units->pos(), floatingPosition); QVERIFY(units->findChild()); QCOMPARE(reopened.findChildren().size(), 3); } } void TestDockLayoutUi::lazy_docks_restore_each_windows_open_panels() { MainWindowStateGuard guard; PrivateSessionStorage storage; { MainWindow first(false); QVERIFY(QMetaObject::invokeMethod(&first, "setConstantsDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); MainWindow second(false); QVERIFY(QMetaObject::invokeMethod(&second, "setConstantsDockVisible", Qt::DirectConnection, Q_ARG(bool, false), Q_ARG(bool, false))); QVERIFY(QMetaObject::invokeMethod(&second, "setFunctionsDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); first.persistSessionAndSettingsForShutdown(); } MainWindow restored; const auto cleanup = qScopeGuard([&]() { for (MainWindow* window : topLevelMainWindows()) { if (window != &restored) delete window; } }); restored.show(); QTRY_COMPARE(topLevelMainWindows().size(), 2); for (MainWindow* window : topLevelMainWindows()) { QCOMPARE(window->findChildren().size(), 1); const QString name = window->findChild()->objectName(); QCOMPARE(name, window == &restored ? QStringLiteral("ConstantsDock") : QStringLiteral("FunctionsDock")); } } void TestDockLayoutUi::opening_docks_keeps_floating_panels_independent() { MainWindowStateGuard guard; guard.settings->sessionLayoutJson.clear(); guard.settings->windowState.clear(); guard.settings->formulaBookDockVisible = false; guard.settings->constantsDockVisible = false; guard.settings->functionsDockVisible = false; guard.settings->historyDockVisible = false; guard.settings->variablesDockVisible = false; guard.settings->userFunctionsDockVisible = false; guard.settings->userUnitsDockVisible = false; guard.settings->bitfieldVisible = false; MainWindow window(false); window.resize(960, 640); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QVERIFY(QMetaObject::invokeMethod(&window, "setConstantsDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QDockWidget* constants = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constants); constants->setFloating(true); constants->move(180, 140); constants->resize(480, 360); QCoreApplication::processEvents(); const QRect floatingGeometry = constants->geometry(); QVERIFY(QMetaObject::invokeMethod(&window, "setFunctionsDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QDockWidget* functions = window.findChild(QStringLiteral("FunctionsDock")); QVERIFY(functions); QTRY_VERIFY(functions->isVisible()); QVERIFY(!functions->isFloating()); QVERIFY(constants->isFloating()); QCOMPARE(constants->parentWidget(), &window); QTRY_VERIFY(constants->isVisible()); QCOMPARE(constants->geometry(), floatingGeometry); // New docked panels should still join the existing docked tab group. QVERIFY(QMetaObject::invokeMethod(&window, "setVariablesDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QDockWidget* variables = window.findChild(QStringLiteral("VariablesDock")); QVERIFY(variables); QVERIFY(window.tabifiedDockWidgets(functions).contains(variables)); QVERIFY(!window.tabifiedDockWidgets(functions).contains(constants)); QCOMPARE(constants->parentWidget(), &window); QTRY_VERIFY(constants->isVisible()); QCOMPARE(constants->geometry(), floatingGeometry); } void TestDockLayoutUi::floating_docks_survive_repeated_quit_data() { QTest::addColumn("mixedLayout"); QTest::addColumn("workspaceLayout"); QTest::newRow("all-floating-workspace") << false << true; QTest::newRow("mixed-workspace") << true << true; QTest::newRow("all-floating-settings") << false << false; QTest::newRow("mixed-settings") << true << false; } void TestDockLayoutUi::floating_docks_survive_repeated_quit() { QFETCH(bool, mixedLayout); QFETCH(bool, workspaceLayout); MainWindowStateGuard guard; PrivateSessionStorage storage; const QVariant previousShutdown = qApp->property("speedcrunchShutdownInProgress"); const auto restoreShutdown = qScopeGuard([&]() { qApp->setProperty("speedcrunchShutdownInProgress", previousShutdown); }); class CloseFloatingDocksFirst : public QObject { public: bool receivedQuit = false; bool eventFilter(QObject* watched, QEvent* event) override { if (watched == qApp && event->type() == QEvent::Quit) { receivedQuit = true; // Qt can close floating windows before the main window. Force // that order so the regression does not depend on widget order. for (QWidget* widget : QApplication::topLevelWidgets()) { if (auto* dock = qobject_cast(widget)) dock->close(); } } return false; } } closeDocksFirst; // Application filters run in reverse installation order. MainWindow must // handle Quit before this filter starts closing the floating docks. qApp->installEventFilter(&closeDocksFirst); const QStringList names {QStringLiteral("BookDock"), QStringLiteral("ConstantsDock"), QStringLiteral("FunctionsDock"), QStringLiteral("HistoryDock"), QStringLiteral("VariablesDock"), QStringLiteral("UserFunctionsDock"), QStringLiteral("UserUnitsDock"), QStringLiteral("BitfieldDock")}; const QList setters {"setFormulaBookDockVisible", "setConstantsDockVisible", "setFunctionsDockVisible", "setHistoryDockVisible", "setVariablesDockVisible", "setUserFunctionsDockVisible", "setUserUnitsDockVisible", "setBitfieldVisible"}; QStringList expectedOpen = names; if (mixedLayout) expectedOpen.removeAll(QStringLiteral("UserUnitsDock")); QHash floatingGeometry; // Save and relaunch twice, then check the third launch as well. for (int launch = 0; launch < 3; ++launch) { if (launch != 0) { guard.settings->load(); if (!workspaceLayout) guard.settings->sessionLayoutJson.clear(); } MainWindow window(launch != 0); window.resize(960, 640); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); if (launch == 0) { for (int i = 0; i < names.size(); ++i) { const bool opened = i == 7 ? QMetaObject::invokeMethod(&window, setters.at(i).constData(), Qt::DirectConnection, Q_ARG(bool, true)) : QMetaObject::invokeMethod(&window, setters.at(i).constData(), Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false)); QVERIFY(opened); QDockWidget* dock = window.findChild(names.at(i)); QVERIFY(dock); dock->setFloating(!mixedLayout || i >= 2); if (dock->isFloating()) { dock->move(160 + i * 20, 120 + i * 15); dock->resize(480, 360); } if (!expectedOpen.contains(names.at(i))) dock->close(); } QCoreApplication::processEvents(); for (QDockWidget* dock : window.findChildren()) { if (dock->isFloating()) floatingGeometry.insert(dock->objectName(), dock->geometry()); } } else { QTRY_COMPARE(window.findChildren().size(), expectedOpen.size()); } for (int i = 0; i < names.size(); ++i) { QDockWidget* dock = window.findChild(names.at(i)); if (!expectedOpen.contains(names.at(i))) { QVERIFY(!dock || dock->isHidden()); continue; } QVERIFY(dock); QTRY_VERIFY(dock->isVisible()); QCOMPARE(dock->isFloating(), !mixedLayout || i >= 2); if (dock->isFloating()) QTRY_COMPARE(dock->geometry(), floatingGeometry.value(names.at(i))); } // main.cpp also publishes this flag before QApplication handles Quit. qApp->setProperty("speedcrunchShutdownInProgress", true); closeDocksFirst.receivedQuit = false; QEvent quit(QEvent::Quit); QCoreApplication::sendEvent(qApp, &quit); QVERIFY(closeDocksFirst.receivedQuit); QVERIFY(!window.isVisible()); const QJsonArray windows = QJsonDocument::fromJson(guard.settings->sessionLayoutJson.toUtf8()) .object().value(QStringLiteral("windows")).toArray(); QCOMPARE(windows.size(), 1); QCOMPARE(windows.first().toObject().value(QStringLiteral("openDocks")).toArray(), QJsonArray::fromStringList(expectedOpen)); qApp->setProperty("speedcrunchShutdownInProgress", previousShutdown); } } void TestDockLayoutUi::dock_list_selected_row_keeps_primary_fill_while_hovered() { const QColor background(QStringLiteral("#202124")); const QColor foreground(QStringLiteral("#d6d8dc")); const QColor hoverBackground(QStringLiteral("#4a5568")); const QColor hoverForeground(QStringLiteral("#f8fafc")); const QColor primaryBackground(QStringLiteral("#2f80ed")); const QColor primaryForeground(QStringLiteral("#ffffff")); const QColor inactiveBackground(QStringLiteral("#3b4252")); const QColor inactiveForeground(QStringLiteral("#eceff4")); QTreeWidget table; table.setColumnCount(3); table.setRootIsDecorated(false); table.setSelectionBehavior(QAbstractItemView::SelectRows); table.header()->hide(); DockListStyle::apply(&table); table.setProperty("dockListHoverBackground", hoverBackground); table.setProperty("dockListHoverForeground", hoverForeground); table.setProperty("dockListActiveSelectionBackground", primaryBackground); table.setProperty("dockListActiveSelectionForeground", primaryForeground); table.setProperty("dockListInactiveSelectionBackground", inactiveBackground); table.setProperty("dockListInactiveSelectionForeground", inactiveForeground); table.setStyleSheet(QStringLiteral( "QAbstractItemView { background-color: %1; color: %2; border: 0; }") .arg(background.name(), foreground.name())); auto* item = new QTreeWidgetItem(&table, QStringList{ QStringLiteral("x"), QStringLiteral("42"), QStringLiteral("m") }); table.setColumnWidth(0, 70); table.setColumnWidth(1, 70); table.setColumnWidth(2, 70); table.resize(260, 80); table.show(); QVERIFY(QTest::qWaitForWindowExposed(&table)); const QModelIndex index = table.indexFromItem(item, 0); const QModelIndex secondColumnIndex = table.indexFromItem(item, 1); const QRect itemRect = table.visualRect(index); const QRect secondColumnRect = table.visualRect(secondColumnIndex); QVERIFY(itemRect.isValid()); QVERIFY(secondColumnRect.isValid()); const QPoint sampledFill(itemRect.right() - 4, itemRect.center().y()); const QPoint sampledColumnBoundary(secondColumnRect.left() + 1, itemRect.top() + 2); const QPoint sampledRoundedCorner(itemRect.left() + 1, itemRect.top() + 1); QTest::mouseMove(table.viewport(), itemRect.center()); QTRY_COMPARE(table.property("dockListHoveredRow").toInt(), 0); QImage hoveredImage = table.viewport()->grab().toImage(); QVERIFY2(colorsAreClose(hoveredImage.pixelColor(sampledFill), hoverBackground, 24), qPrintable(QStringLiteral("hover sample is %1, expected %2") .arg(hoveredImage.pixelColor(sampledFill).name(), hoverBackground.name()))); QVERIFY2(colorsAreClose(hoveredImage.pixelColor(sampledColumnBoundary), hoverBackground, 32), qPrintable(QStringLiteral("column-boundary hover sample is %1, expected %2") .arg(hoveredImage.pixelColor(sampledColumnBoundary).name(), hoverBackground.name()))); QVERIFY(!colorsAreClose(hoveredImage.pixelColor(sampledRoundedCorner), hoverBackground, 8)); QVERIFY(hoveredImage.pixelColor(sampledFill).name() != primaryBackground.name()); table.setCurrentItem(item); item->setSelected(true); table.setFocus(Qt::OtherFocusReason); QTRY_VERIFY(table.hasFocus()); QTRY_COMPARE(table.viewport()->grab().toImage().pixelColor(sampledFill).name(), primaryBackground.name()); } void TestDockLayoutUi::functions_dock_retranslates_domain_label_after_language_change() { FunctionsWidget widget; widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); QLabel* domainLabel = nullptr; for (QLabel* label : widget.findChildren()) { if (label->text() == QStringLiteral("Domain")) { domainLabel = label; break; } } QVERIFY(domainLabel != nullptr); FunctionsTestTranslator translator; QCoreApplication::installTranslator(&translator); QEvent languageChange(QEvent::LanguageChange); QCoreApplication::sendEvent(&widget, &languageChange); QCOMPARE(domainLabel->text(), QStringLiteral("Translated Domain")); QCoreApplication::removeTranslator(&translator); } void TestDockLayoutUi::side_docks_keep_full_height_data() { QTest::addColumn("restorePath"); QTest::newRow("fresh-layout") << 0; QTest::newRow("saved-settings") << 1; QTest::newRow("session-layout") << 2; QTest::newRow("new-window") << 3; } void TestDockLayoutUi::side_docks_keep_full_height() { QFETCH(int, restorePath); MainWindowStateGuard guard; Settings* settings = guard.settings; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->keypadMode = Settings::KeypadModeBasicWide; settings->keypadVisible = true; settings->constantsDockVisible = true; settings->functionsDockVisible = true; settings->historyDockVisible = true; settings->bitfieldVisible = true; MainWindow source(false); for (QDockWidget* dock : source.findChildren()) dock->hide(); struct DockSpec { const char* name; Qt::DockWidgetArea area; }; const DockSpec docks[] = { { "ConstantsDock", Qt::LeftDockWidgetArea }, { "FunctionsDock", Qt::RightDockWidgetArea }, { "HistoryDock", Qt::TopDockWidgetArea }, { "BitfieldDock", Qt::BottomDockWidgetArea } }; for (const DockSpec& spec : docks) { QDockWidget* dock = source.findChild(QString::fromLatin1(spec.name)); QVERIFY(dock != nullptr); source.removeDockWidget(dock); source.addDockWidget(spec.area, dock); dock->show(); } source.resize(1500, 1000); source.show(); QVERIFY(QTest::qWaitForWindowExposed(&source)); QPointer restored; const auto cleanup = qScopeGuard([&restored]() { delete restored.data(); }); MainWindow* window = &source; if (restorePath != 0) { // Older layouts can give the top and bottom docks all four corners. source.setCorner(Qt::TopLeftCorner, Qt::TopDockWidgetArea); source.setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea); source.setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea); source.setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea); const QByteArray state = source.saveState(1); if (restorePath == 3) { const QList windowsBefore = topLevelMainWindows(); QVERIFY(QMetaObject::invokeMethod(&source, "showNewSessionWindow", Qt::DirectConnection)); QTRY_VERIFY(([&]() { for (MainWindow* candidate : topLevelMainWindows()) { if (!windowsBefore.contains(candidate)) { restored = candidate; return true; } } return false; }())); } else { if (restorePath == 1) settings->windowState = state; restored = new MainWindow(false); if (restorePath == 2) { QVERIFY(QMetaObject::invokeMethod(restored.data(), "restoreWindowLayoutState", Qt::DirectConnection, Q_ARG(QByteArray, state))); } } window = restored.data(); window->resize(1500, 1000); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); } QCOMPARE(window->corner(Qt::TopLeftCorner), Qt::LeftDockWidgetArea); QCOMPARE(window->corner(Qt::BottomLeftCorner), Qt::LeftDockWidgetArea); QCOMPARE(window->corner(Qt::TopRightCorner), Qt::RightDockWidgetArea); QCOMPARE(window->corner(Qt::BottomRightCorner), Qt::RightDockWidgetArea); QList attached; for (const DockSpec& spec : docks) { QDockWidget* dock = window->findChild(QString::fromLatin1(spec.name)); QVERIFY(dock != nullptr); QTRY_VERIFY(dock->isVisible()); QVERIFY(!dock->isFloating()); QCOMPARE(window->dockWidgetArea(dock), spec.area); attached.append(dock); } QVERIFY(window->findChild() != nullptr); QDockWidget* left = attached.at(0); QDockWidget* right = attached.at(1); QDockWidget* top = attached.at(2); QDockWidget* bottom = attached.at(3); for (QDockWidget* side : { left, right }) { QTRY_COMPARE(side->geometry().top(), top->geometry().top()); QTRY_COMPARE(side->geometry().bottom(), bottom->geometry().bottom()); } for (QDockWidget* horizontal : { top, bottom }) { QTRY_VERIFY(horizontal->geometry().left() > left->geometry().right()); QTRY_VERIFY(horizontal->geometry().right() < right->geometry().left()); QTRY_COMPARE(horizontal->geometry().left(), window->centralWidget()->geometry().left()); QTRY_COMPARE(horizontal->geometry().right(), window->centralWidget()->geometry().right()); } } void TestDockLayoutUi::dock_search_rows_use_configured_vertical_padding_data() { QTest::addColumn("dock"); QTest::addColumn("topPadding"); for (const QString& dock : {QStringLiteral("constants"), QStringLiteral("functions")}) QTest::newRow(qPrintable(dock)) << dock << UiConfig::DockSearchRowVerticalPadding; for (const QString& dock : {QStringLiteral("user-variables"), QStringLiteral("user-functions"), QStringLiteral("user-units")}) QTest::newRow(qPrintable(dock)) << dock << 6; } void TestDockLayoutUi::dock_search_rows_use_configured_vertical_padding() { QFETCH(QString, dock); QFETCH(int, topPadding); QWidget owner; QWidget* widget = nullptr; if (dock == QStringLiteral("constants")) widget = new ConstantsWidget(&owner); else if (dock == QStringLiteral("functions")) widget = new FunctionsWidget(&owner); else if (dock == QStringLiteral("user-variables")) widget = new VariableListWidget(&owner); else if (dock == QStringLiteral("user-functions")) widget = new UserFunctionListWidget(&owner); else if (dock == QStringLiteral("user-units")) widget = new UserUnitListWidget(&owner); QVERIFY(widget); widget->resize(420, 360); widget->show(); QLineEdit* search = widget->findChild(); QTreeWidget* list = widget->findChild(); QVERIFY(search); QVERIFY(list); QWidget* row = search->parentWidget(); QVERIFY(row->layout()); widget->layout()->activate(); row->layout()->activate(); QCOMPARE(row->layout()->contentsMargins(), QMargins(8, topPadding, 8, UiConfig::DockSearchRowVerticalPadding)); const int searchTop = search->mapTo(widget, QPoint()).y(); const int rowTop = row->mapTo(widget, QPoint()).y(); QCOMPARE(searchTop - rowTop, topPadding); QCOMPARE(list->y() - (searchTop + search->height()), UiConfig::DockSearchRowVerticalPadding); } void TestDockLayoutUi::themed_dock_lists_use_compact_spacing_data() { QTest::addColumn("dockName"); QTest::addColumn("light"); for (bool light : {false, true}) { for (const QString& dock : {QStringLiteral("ConstantsDock"), QStringLiteral("FunctionsDock"), QStringLiteral("VariablesDock"), QStringLiteral("UserFunctionsDock"), QStringLiteral("UserUnitsDock"), QStringLiteral("HistoryDock")}) { const QString name = (light ? QStringLiteral("light-") : QStringLiteral("dark-")) + dock; QTest::newRow(qPrintable(name)) << dock << light; } } } void TestDockLayoutUi::themed_dock_lists_use_compact_spacing() { QFETCH(QString, dockName); QFETCH(bool, light); MainWindowStateGuard guard; guard.settings->dockAppearance = Settings::DockAppearanceSystem; guard.settings->constantsDockVisible = true; guard.settings->functionsDockVisible = true; guard.settings->variablesDockVisible = true; guard.settings->userFunctionsDockVisible = true; guard.settings->userUnitsDockVisible = true; guard.settings->historyDockVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QString(light ? "#e5eee8" : "#27314a")}}); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(dockName); QMenu* appearance = window.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(dock); QVERIFY(appearance); dock->setFloating(true); dock->resize(500, 400); dock->show(); QAbstractItemView* list = nullptr; for (QAbstractItemView* view : dock->findChildren()) { if (!qobject_cast(view) && !qobject_cast(view->parentWidget())) { if (qobject_cast(view) || qobject_cast(view)) { list = view; break; } } } QVERIFY(list); QCoreApplication::processEvents(); const auto firstRow = [list]() { if (list->model()->rowCount() == 0) { if (QTreeWidget* tree = qobject_cast(list)) new QTreeWidgetItem(tree, QStringList{QStringLiteral("Sample"), QStringLiteral("123")}); else qobject_cast(list)->addItem(QStringLiteral("Sample")); } list->doItemsLayout(); return list->model()->index(0, 0); }; const QModelIndex first = firstRow(); QVERIFY(first.isValid()); const int nativeRowHeight = list->visualRect(first).height(); const int nativeInset = list->viewport()->x(); QTreeWidget* tree = qobject_cast(list); const int nativeHeaderHeight = tree ? tree->header()->height() : 0; for (int cycle = 0; cycle < 2; ++cycle) { appearance->actions().at(1)->trigger(); QCoreApplication::processEvents(); QCOMPARE(list->contentsMargins(), QMargins()); QVERIFY(list->viewport()->x() <= nativeInset); QCOMPARE(list->visualRect(firstRow()).height(), nativeRowHeight); if (tree) { QCOMPARE(tree->header()->height(), nativeHeaderHeight); } appearance->actions().at(0)->trigger(); QCoreApplication::processEvents(); QCOMPARE(list->viewport()->x(), nativeInset); if (tree) QCOMPARE(tree->header()->height(), nativeHeaderHeight); } } void TestDockLayoutUi::themed_dock_controls_have_equal_visible_gaps_data() { QTest::addColumn("dockName"); QTest::addColumn("wide"); QTest::addColumn("light"); QTest::addColumn("subdomains"); for (bool light : {false, true}) { const QByteArray theme = light ? "light-" : "dark-"; for (const QString& dock : {QStringLiteral("ConstantsDock"), QStringLiteral("FunctionsDock"), QStringLiteral("VariablesDock"), QStringLiteral("UserFunctionsDock"), QStringLiteral("UserUnitsDock")}) { const QByteArray name = theme + dock.toUtf8(); QTest::newRow(name.constData()) << dock << false << light << true; } const QByteArray wideName = theme + "constants-wide"; QTest::newRow(wideName.constData()) << QStringLiteral("ConstantsDock") << true << light << true; for (bool wide : {false, true}) { const QByteArray name = theme + (wide ? "constants-single-wide" : "constants-single"); QTest::newRow(name.constData()) << QStringLiteral("ConstantsDock") << wide << light << false; } } } void TestDockLayoutUi::themed_dock_controls_have_equal_visible_gaps() { QFETCH(QString, dockName); QFETCH(bool, wide); QFETCH(bool, light); QFETCH(bool, subdomains); MainWindowStateGuard guard; Settings* settings = guard.settings; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->constantsDockVisible = dockName == QStringLiteral("ConstantsDock"); settings->functionsDockVisible = dockName == QStringLiteral("FunctionsDock"); settings->variablesDockVisible = dockName == QStringLiteral("VariablesDock"); settings->userFunctionsDockVisible = dockName == QStringLiteral("UserFunctionsDock"); settings->userUnitsDockVisible = dockName == QStringLiteral("UserUnitsDock"); settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->bitfieldVisible = false; settings->keypadVisible = false; settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject { {QStringLiteral("background"), light ? QStringLiteral("#f0f6ef") : QStringLiteral("#1f3229")} }); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(dockName); QVERIFY(dock); dock->setFloating(true); dock->resize(wide ? 800 : 320, 480); QWidget* content = dock->widget(); if (ConstantsWidget* constants = qobject_cast(content)) { QComboBox* domain = constants->findChild(); QVERIFY(domain); constants->restoreState(domain->itemText(subdomains ? 0 : 1), QString(), QString()); } QCoreApplication::processEvents(); QTest::qWait(30); QLineEdit* search = content->findChild(); QTreeWidget* table = content->findChild(); QVERIFY(search); QVERIFY(table); QVERIFY(table->header()->isVisible()); const auto top = [content](QWidget* widget) { return widget->mapTo(content, QPoint()).y(); }; const auto bottom = [&top](QWidget* widget) { return top(widget) + widget->height(); }; // Measure the painted header, including any padding inside the table. QCOMPARE(top(table->header()->viewport()) - bottom(search), UiConfig::DockSearchRowVerticalPadding); QList combos; for (QComboBox* combo : content->findChildren()) { if (combo->isVisible()) combos.append(combo); } if (!combos.isEmpty()) { if (dockName == QStringLiteral("ConstantsDock")) QCOMPARE(combos.size(), subdomains ? 2 : 1); QComboBox* lowest = combos.first(); for (QComboBox* combo : combos) { if (bottom(combo) > bottom(lowest)) lowest = combo; } QCOMPARE(top(search) - bottom(lowest), UiConfig::DockSearchRowVerticalPadding); if (combos.size() == 2) { if (wide) { QCOMPARE(top(combos.first()), top(combos.last())); } else { QComboBox* upper = top(combos.first()) < top(combos.last()) ? combos.first() : combos.last(); QComboBox* lower = upper == combos.first() ? combos.last() : combos.first(); QCOMPARE(top(lower) - bottom(upper), UiConfig::DockSearchRowVerticalPadding); } } } } void TestDockLayoutUi::dock_first_control_matches_shared_vertical_spacing_data() { QTest::addColumn("light"); QTest::newRow("dark") << false; QTest::newRow("light") << true; } void TestDockLayoutUi::dock_first_control_matches_shared_vertical_spacing() { QFETCH(bool, light); MainWindowStateGuard guard; Settings* settings = guard.settings; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->constantsDockVisible = true; settings->functionsDockVisible = true; settings->variablesDockVisible = true; settings->userFunctionsDockVisible = true; settings->userUnitsDockVisible = true; settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->bitfieldVisible = false; settings->keypadVisible = false; settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject { {QStringLiteral("background"), light ? QStringLiteral("#f0f6ef") : QStringLiteral("#1f3229")} }); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); for (const QString& name : {QStringLiteral("ConstantsDock"), QStringLiteral("FunctionsDock"), QStringLiteral("VariablesDock"), QStringLiteral("UserFunctionsDock"), QStringLiteral("UserUnitsDock")}) { QDockWidget* dock = window.findChild(name); QVERIFY(dock); dock->setFloating(true); dock->resize(320, 480); dock->show(); QCoreApplication::processEvents(); QWidget* content = dock->widget(); QWidget* first = content->findChild(); QVERIFY(first); for (QComboBox* combo : content->findChildren()) { if (combo->isVisible() && combo->mapTo(content, QPoint()).y() < first->mapTo(content, QPoint()).y()) first = combo; } QTRY_COMPARE(first->mapTo(content, QPoint()).y(), UiConfig::DockSearchRowVerticalPadding); } } void TestDockLayoutUi::formula_book_links_follow_dock_appearance_data() { QTest::addColumn("dark"); QTest::addColumn("systemAtStartup"); QTest::newRow("dark-system-startup") << true << true; QTest::newRow("light-system-startup") << false << true; QTest::newRow("dark-switch-from-theme") << true << false; QTest::newRow("light-switch-from-theme") << false << false; } void TestDockLayoutUi::formula_book_links_follow_dock_appearance() { QFETCH(bool, dark); QFETCH(bool, systemAtStartup); MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([original]() { QApplication::setPalette(original); }); QPalette native = original; native.setColor(QPalette::Base, QColor(dark ? "#202020" : "#fafafa")); native.setColor(QPalette::Text, QColor(dark ? "#eeeeee" : "#202020")); // Keep the system link color even when a contrast adjustment would change it. native.setColor(QPalette::Link, QColor(dark ? "#343c4b" : "#c1c7d0")); QApplication::setPalette(native); guard.settings->dockAppearance = systemAtStartup ? Settings::DockAppearanceSystem : Settings::DockAppearanceSpeedCrunch; guard.settings->formulaBookDockVisible = true; guard.settings->windowState.clear(); guard.settings->sessionLayoutJson.clear(); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#27314a")}}); MainWindow first(false); MainWindow second(false); first.show(); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&first)); QVERIFY(QTest::qWaitForWindowExposed(&second)); QMenu* appearance = first.findChild(QStringLiteral("DockAppearanceMenu")); QVERIFY(appearance); const auto verifyLinks = [&](BookDock* book, bool system, const QColor& nativeLink) { QTextBrowser* browser = book->findChild(); QVERIFY(browser); const QColor background = browser->palette().color(QPalette::Base); const QColor formulaColor = system ? nativeLink : aaForegroundForBackground(background, browser->palette().color(QPalette::Link)); const QColor navigationColor = system ? nativeLink : generateSecondaryLinkFromBackground(background, formulaColor); int navigationLinks = 0; int formulaLinks = 0; for (QTextBlock block = browser->document()->begin(); block.isValid(); block = block.next()) { for (auto it = block.begin(); !it.atEnd(); ++it) { const QTextCharFormat format = it.fragment().charFormat(); if (!format.isAnchor()) continue; const bool formula = format.anchorHref().startsWith(QStringLiteral("formula:")); QCOMPARE(format.foreground().color().rgba(), (formula ? formulaColor : navigationColor).rgba()); if (formula) ++formulaLinks; else ++navigationLinks; } } QVERIFY(navigationLinks > 0); QCOMPARE(formulaLinks > 0, book->currentPage() != QStringLiteral("index")); }; for (bool system : {systemAtStartup, !systemAtStartup, systemAtStartup}) { appearance->actions().at(system ? 0 : 1)->trigger(); QCoreApplication::processEvents(); for (MainWindow* window : {&first, &second}) { BookDock* book = window->findChild(QStringLiteral("BookDock")); QVERIFY(book); for (const QString& page : {QStringLiteral("index"), QStringLiteral("electronics/ohmslaw")}) { book->openPage(QUrl(page)); verifyLinks(book, system, native.color(QPalette::Link)); if (QTest::currentTestFailed()) return; } } } appearance->actions().at(0)->trigger(); native.setColor(QPalette::Link, QColor(dark ? "#b8a0eb" : "#6321a0")); QApplication::setPalette(native); QCoreApplication::processEvents(); for (MainWindow* window : {&first, &second}) { BookDock* book = window->findChild(QStringLiteral("BookDock")); QVERIFY(book); QTextBrowser* browser = book->findChild(); QVERIFY(browser); QTRY_COMPARE(browser->palette().color(QPalette::Link).rgba(), native.color(QPalette::Link).rgba()); QCOMPARE(book->currentPage(), QStringLiteral("electronics/ohmslaw")); verifyLinks(book, true, native.color(QPalette::Link)); if (QTest::currentTestFailed()) return; book->openPage(QUrl(QStringLiteral("index"))); verifyLinks(book, true, native.color(QPalette::Link)); if (QTest::currentTestFailed()) return; } } void TestDockLayoutUi::formula_book_text_scales_with_zoom_data() { QTest::addColumn("page"); QTest::addColumn("formula"); QTest::addColumn("caption"); QTest::addColumn("variable"); QTest::addColumn("unit"); QTest::newRow("geometry") << QStringLiteral("geometry/circle") << QStringLiteral("A =") << QStringLiteral("radius") << QStringLiteral("r") << QString(); QTest::newRow("electronics") << QStringLiteral("electronics/ohmslaw") << QStringLiteral("R =") << QStringLiteral("resistance") << QStringLiteral("R") << QStringLiteral("Ω"); QTest::newRow("compound-unit") << QStringLiteral("rf/propagation") << QStringLiteral("= 3e8") << QStringLiteral("dielectric constant") << QStringLiteral("e") << QStringLiteral("m·s"); } void TestDockLayoutUi::formula_book_text_scales_with_zoom() { QFETCH(QString, page); QFETCH(QString, formula); QFETCH(QString, caption); QFETCH(QString, variable); QFETCH(QString, unit); BookDock dock; dock.resize(800, 600); dock.show(); QVERIFY(QTest::qWaitForWindowExposed(&dock)); dock.openPage(QUrl(page)); QTextBrowser* browser = dock.findChild(); QVERIFY(browser != nullptr); // Inspect laid-out glyph fonts so relative sizes and the document's zoom // are resolved by Qt, including fonts inside caption table cells. const auto pixelSize = [&](const QString& text, bool backwards = false) -> qreal { QTextDocument* document = browser->document(); document->documentLayout()->documentSize(); const QTextCursor cursor = document->find( text, backwards ? document->characterCount() - 1 : 0, backwards ? QTextDocument::FindBackward | QTextDocument::FindWholeWords : QTextDocument::FindFlags()); if (cursor.isNull()) return -1; const QTextBlock block = cursor.block(); const auto runs = block.layout()->glyphRuns(cursor.selectionStart() - block.position(), 1); return runs.isEmpty() ? -1 : runs.first().rawFont().pixelSize(); }; const auto sizes = [&]() { return QList { pixelSize(QStringLiteral("Index")), pixelSize(formula), pixelSize(caption), pixelSize(variable, true) }; }; const QList original = sizes(); for (qreal size : original) QVERIFY(size > 0); const qreal originalBaseSize = browser->document()->defaultFont().pointSizeF(); for (int steps : { 4, -4 }) { browser->zoomIn(steps); const qreal scale = browser->document()->defaultFont().pointSizeF() / originalBaseSize; const QList zoomed = sizes(); for (qsizetype i = 0; i < original.size(); ++i) { QVERIFY2(steps > 0 ? zoomed[i] > original[i] : zoomed[i] < original[i], qPrintable(QStringLiteral("text sample %1 does not follow zoom").arg(i))); QVERIFY(qAbs(zoomed[i] / original[i] - scale) < 0.1); } if (!unit.isEmpty()) QCOMPARE(pixelSize(unit), pixelSize(formula)); // Reloading content must retain the same sizes at the current zoom. dock.openPage(QUrl(QStringLiteral("index"))); dock.openPage(QUrl(page)); QCOMPARE(sizes(), zoomed); dock.setContentSurfaceColors(QColor(steps > 0 ? "#202020" : "#303030"), QColor("#eeeeee")); QCOMPARE(sizes(), zoomed); dock.retranslateText(); QCOMPARE(sizes(), zoomed); browser->zoomOut(steps); QCOMPARE(sizes(), original); } if (!unit.isEmpty()) QCOMPARE(pixelSize(unit), pixelSize(formula)); } void TestDockLayoutUi::restored_constants_dock_empty_filter_fills_header() { MainWindowStateGuard guard; Settings* settings = guard.settings; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->constantsDockVisible = true; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->keypadMode = Settings::KeypadModeDisabled; settings->keypadVisible = false; settings->statusBarVisible = false; settings->hasNumberFormatStyleSetting = true; settings->constantsDockDomain.clear(); settings->constantsDockSubdomain.clear(); settings->constantsDockSearchText = QStringLiteral("no-such-constant-filter-value"); MainWindow window; window.resize(900, 500); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* constantsDock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constantsDock != nullptr); QLineEdit* searchBox = constantsDock->findChild(); QTreeWidget* table = constantsDock->findChild(); QVERIFY(searchBox != nullptr); QVERIFY(table != nullptr); QVERIFY(table->header() != nullptr); QCOMPARE(searchBox->text(), QStringLiteral("no-such-constant-filter-value")); QCOMPARE(table->topLevelItemCount(), 0); QTRY_VERIFY2(table->header()->length() >= table->header()->width() - 1, qPrintable(QStringLiteral("length=%1 header=%2 sections=%3,%4,%5") .arg(table->header()->length()) .arg(table->header()->width()) .arg(table->header()->sectionSize(0)) .arg(table->header()->sectionSize(1)) .arg(table->header()->sectionSize(2)))); } void TestDockLayoutUi::dock_scroll_corner_uses_scrollbar_track_fill() { MainWindowStateGuard guard; Settings* settings = guard.settings; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{{QStringLiteral("background"), QStringLiteral("#1f3229")}}); settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->constantsDockVisible = true; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->windowPositionSave = false; settings->hasNumberFormatStyleSetting = true; const QColor base(QStringLiteral("#1f3229")); const QVector shades = generateOklchShades(base, 6, ThemePolarity::Dark); const QColor expectedTrackFill = shades.at(UiConfig::DockBackgroundShade); MainWindow window; window.resize(700, 420); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); QDockWidget* constantsDock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constantsDock != nullptr); QTreeWidget* table = constantsDock->findChild(); QVERIFY(table != nullptr); table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); for (int column = 0; column < table->columnCount(); ++column) table->setColumnWidth(column, 240); constantsDock->show(); constantsDock->raise(); window.resizeDocks(QList { constantsDock }, QList { UiConfig::ConstantsDockMinimumWidth }, Qt::Horizontal); QCoreApplication::processEvents(); QWidget* corner = table->cornerWidget(); QVERIFY(corner != nullptr); QCOMPARE(corner->palette().color(QPalette::Window).name(), expectedTrackFill.name()); QVERIFY(corner->styleSheet().contains(expectedTrackFill.name())); QVERIFY(corner->styleSheet().contains(QStringLiteral("border: 0"))); QTRY_VERIFY(table->horizontalScrollBar()->isVisible()); QTRY_VERIFY(table->verticalScrollBar()->isVisible()); QTRY_VERIFY(corner->isVisible()); const QImage image = corner->grab().toImage(); QVERIFY(!image.isNull()); QVERIFY(image.width() > 1); QVERIFY(image.height() > 1); const QList samplePoints { QPoint(0, 0), QPoint(image.width() - 1, 0), QPoint(0, image.height() - 1), QPoint(image.width() - 1, image.height() - 1), image.rect().center() }; for (const QPoint& point : samplePoints) { const QColor sampled = image.pixelColor(point); QVERIFY2(colorsAreClose(sampled, expectedTrackFill, 3), qPrintable(QStringLiteral("corner sample %1,%2 is %3, expected %4") .arg(point.x()) .arg(point.y()) .arg(sampled.name(), expectedTrackFill.name()))); } } void TestDockLayoutUi::dock_separator_style_uses_primary_while_hovered_or_dragged() { MainWindowStateGuard guard; guard.settings->hasNumberFormatStyleSetting = true; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); const QColor normal(QStringLiteral("#123456")); const QColor primary(QStringLiteral("#abcdef")); QWidget propertyOwner; propertyOwner.setProperty("speedcrunchDockSeparatorNormalColor", normal); propertyOwner.setProperty("speedcrunchDockSeparatorActiveColor", primary); propertyOwner.resize(96, 64); QWidget styleHost(&propertyOwner); styleHost.resize(64, 32); styleHost.move(0, 0); propertyOwner.show(); QVERIFY(QTest::qWaitForWindowExposed(&propertyOwner)); QCursor::setPos(styleHost.mapToGlobal(QPoint(50, 24))); QCoreApplication::processEvents(); QCOMPARE(dockSeparatorPrimitiveColor(&styleHost, QStyle::State_None).name(), normal.name()); QCursor::setPos(styleHost.mapToGlobal(QPoint(4, 4))); QCoreApplication::processEvents(); QCOMPARE(dockSeparatorPrimitiveColor(&styleHost, QStyle::State_None).name(), primary.name()); QImage horizontalSeparator = dockSeparatorPrimitiveImage(&styleHost, QStyle::State_None, QSize(32, 8)); const int horizontalStrokeTop = (horizontalSeparator.height() - UiConfig::DockSplitterStrokeWidth) / 2; const int horizontalStrokeBottom = horizontalStrokeTop + UiConfig::DockSplitterStrokeWidth - 1; for (int y = horizontalStrokeTop; y <= horizontalStrokeBottom; ++y) QCOMPARE(horizontalSeparator.pixelColor(horizontalSeparator.width() / 2, y).name(), primary.name()); if (horizontalStrokeTop > 0) QCOMPARE(horizontalSeparator.pixelColor(horizontalSeparator.width() / 2, horizontalStrokeTop - 1).alpha(), 0); if (horizontalStrokeBottom + 1 < horizontalSeparator.height()) QCOMPARE(horizontalSeparator.pixelColor(horizontalSeparator.width() / 2, horizontalStrokeBottom + 1).alpha(), 0); QImage verticalSeparator = dockSeparatorPrimitiveImage(&styleHost, QStyle::State_None, QSize(8, 32)); const int verticalStrokeLeft = (verticalSeparator.width() - UiConfig::DockSplitterStrokeWidth) / 2; const int verticalStrokeRight = verticalStrokeLeft + UiConfig::DockSplitterStrokeWidth - 1; for (int x = verticalStrokeLeft; x <= verticalStrokeRight; ++x) QCOMPARE(verticalSeparator.pixelColor(x, verticalSeparator.height() / 2).name(), primary.name()); if (verticalStrokeLeft > 0) QCOMPARE(verticalSeparator.pixelColor(verticalStrokeLeft - 1, verticalSeparator.height() / 2).alpha(), 0); if (verticalStrokeRight + 1 < verticalSeparator.width()) QCOMPARE(verticalSeparator.pixelColor(verticalStrokeRight + 1, verticalSeparator.height() / 2).alpha(), 0); QCursor::setPos(styleHost.mapToGlobal(QPoint(4, 1))); QCoreApplication::processEvents(); QImage thinHorizontalSeparator = dockSeparatorPrimitiveImage(&styleHost, QStyle::State_None, QRect(0, 0, 32, 1), QSize(32, 3)); QCOMPARE(thinHorizontalSeparator.pixelColor(thinHorizontalSeparator.width() / 2, 1).name(), primary.name()); QCOMPARE(thinHorizontalSeparator.pixelColor(thinHorizontalSeparator.width() / 2, 2).alpha(), 0); QCursor::setPos(styleHost.mapToGlobal(QPoint(1, 4))); QCoreApplication::processEvents(); QImage thinVerticalSeparator = dockSeparatorPrimitiveImage(&styleHost, QStyle::State_None, QRect(0, 0, 1, 32), QSize(3, 32)); QCOMPARE(thinVerticalSeparator.pixelColor(1, thinVerticalSeparator.height() / 2).name(), primary.name()); QCOMPARE(thinVerticalSeparator.pixelColor(2, thinVerticalSeparator.height() / 2).alpha(), 0); QCursor::setPos(styleHost.mapToGlobal(QPoint(50, 24))); QCoreApplication::processEvents(); QCOMPARE(dockSeparatorPrimitiveColor(&styleHost, QStyle::State_Sunken).name(), primary.name()); } void TestDockLayoutUi::constants_dock_uses_configured_narrow_minimum_width() { Settings* settings = Settings::instance(); struct SettingsGuard { Settings* settings; bool oldConstantsDockVisible; bool oldFunctionsDockVisible; bool oldHistoryDockVisible; bool oldFormulaBookDockVisible; bool oldVariablesDockVisible; bool oldUserFunctionsDockVisible; bool oldUserUnitsDockVisible; bool oldBitfieldVisible; Settings::KeypadMode oldKeypadMode; bool oldKeypadVisible; bool oldHasNumberFormatStyleSetting; QByteArray oldSkipUpdateCheck; bool hadSkipUpdateCheck; ~SettingsGuard() { settings->constantsDockVisible = oldConstantsDockVisible; settings->functionsDockVisible = oldFunctionsDockVisible; settings->historyDockVisible = oldHistoryDockVisible; settings->formulaBookDockVisible = oldFormulaBookDockVisible; settings->variablesDockVisible = oldVariablesDockVisible; settings->userFunctionsDockVisible = oldUserFunctionsDockVisible; settings->userUnitsDockVisible = oldUserUnitsDockVisible; settings->bitfieldVisible = oldBitfieldVisible; settings->keypadMode = oldKeypadMode; settings->keypadVisible = oldKeypadVisible; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } } guard { settings, settings->constantsDockVisible, settings->functionsDockVisible, settings->historyDockVisible, settings->formulaBookDockVisible, settings->variablesDockVisible, settings->userFunctionsDockVisible, settings->userUnitsDockVisible, settings->bitfieldVisible, settings->keypadMode, settings->keypadVisible, settings->hasNumberFormatStyleSetting, qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK") }; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); settings->constantsDockVisible = true; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->keypadMode = Settings::KeypadModeDisabled; settings->keypadVisible = false; settings->hasNumberFormatStyleSetting = true; MainWindow window; window.resize(900, 500); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* constantsDock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constantsDock != nullptr); QCOMPARE(constantsDock->minimumWidth(), UiConfig::ConstantsDockMinimumWidth); QVERIFY(constantsDock->widget()->minimumSizeHint().width() <= UiConfig::ConstantsDockMinimumWidth); } void TestDockLayoutUi::view_dock_menu_tracks_and_changes_only_active_window() { MainWindowStateGuard guard; Settings* settings = guard.settings; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->constantsDockVisible = false; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->statusBarVisible = true; settings->windowPositionSave = false; settings->hasNumberFormatStyleSetting = true; MainWindow firstWindow; firstWindow.resize(800, 500); firstWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&firstWindow)); MainWindow secondWindow; secondWindow.resize(800, 500); secondWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&secondWindow)); struct DockSpec { const char* setter; const char* objectName; const char* actionText; bool hasFocusArgument; }; const DockSpec dockSpecs[] = { { "setFormulaBookDockVisible", "BookDock", "Formula &Book", true }, { "setConstantsDockVisible", "ConstantsDock", "&Constants", true }, { "setFunctionsDockVisible", "FunctionsDock", "&Functions", true }, { "setVariablesDockVisible", "VariablesDock", "User &Variables", true }, { "setUserFunctionsDockVisible", "UserFunctionsDock", "Use&r Functions", true }, { "setUserUnitsDockVisible", "UserUnitsDock", "User &Units", true }, { "setHistoryDockVisible", "HistoryDock", "&History", true }, { "setBitfieldVisible", "BitfieldDock", "Bitfield", false } }; const auto setDockVisible = [](MainWindow* window, const DockSpec& spec, bool visible) { if (!spec.hasFocusArgument) { return QMetaObject::invokeMethod(window, spec.setter, Qt::DirectConnection, Q_ARG(bool, visible)); } return QMetaObject::invokeMethod(window, spec.setter, Qt::DirectConnection, Q_ARG(bool, visible), Q_ARG(bool, false)); }; const auto dockIsVisible = [](MainWindow* window, const DockSpec& spec) { QDockWidget* dock = window->findChild(QString::fromLatin1(spec.objectName)); return dock != nullptr && dock->isVisible(); }; QMenu* firstViewMenu = menuWithTitle(firstWindow.menuBar(), QStringLiteral("&View")); QMenu* secondViewMenu = menuWithTitle(secondWindow.menuBar(), QStringLiteral("&View")); QVERIFY(firstViewMenu != nullptr); QVERIFY(secondViewMenu != nullptr); for (const DockSpec& spec : dockSpecs) { QVERIFY(setDockVisible(&firstWindow, spec, true)); QVERIFY(dockIsVisible(&firstWindow, spec)); QVERIFY(!dockIsVisible(&secondWindow, spec)); } firstWindow.raise(); firstWindow.activateWindow(); firstWindow.setFocus(Qt::OtherFocusReason); QTRY_COMPARE(QApplication::activeWindow(), static_cast(&firstWindow)); QEvent firstWindowActivate(QEvent::WindowActivate); QCoreApplication::sendEvent(&firstWindow, &firstWindowActivate); QCoreApplication::processEvents(); for (const DockSpec& spec : dockSpecs) { QAction* firstAction = directMenuActionWithText( firstViewMenu, QString::fromLatin1(spec.actionText)); QAction* secondAction = directMenuActionWithText( secondViewMenu, QString::fromLatin1(spec.actionText)); QVERIFY(firstAction != nullptr); QVERIFY(secondAction != nullptr); QVERIFY(firstAction->isChecked()); QVERIFY(secondAction->isChecked()); // Simulate the native menu dispatching the inactive window's action. secondAction->trigger(); QCoreApplication::processEvents(); QVERIFY(!dockIsVisible(&firstWindow, spec)); QVERIFY(!dockIsVisible(&secondWindow, spec)); QVERIFY(!firstAction->isChecked()); QVERIFY(!secondAction->isChecked()); } for (const DockSpec& spec : dockSpecs) { QVERIFY(setDockVisible(&secondWindow, spec, true)); QVERIFY(!dockIsVisible(&firstWindow, spec)); QVERIFY(dockIsVisible(&secondWindow, spec)); } secondWindow.raise(); secondWindow.activateWindow(); secondWindow.setFocus(Qt::OtherFocusReason); QTRY_COMPARE(QApplication::activeWindow(), static_cast(&secondWindow)); QEvent secondWindowActivate(QEvent::WindowActivate); QCoreApplication::sendEvent(&secondWindow, &secondWindowActivate); QCoreApplication::processEvents(); for (const DockSpec& spec : dockSpecs) { QAction* firstAction = directMenuActionWithText( firstViewMenu, QString::fromLatin1(spec.actionText)); QAction* secondAction = directMenuActionWithText( secondViewMenu, QString::fromLatin1(spec.actionText)); QVERIFY(firstAction->isChecked()); QVERIFY(secondAction->isChecked()); firstAction->trigger(); QCoreApplication::processEvents(); QVERIFY(!dockIsVisible(&firstWindow, spec)); QVERIFY(!dockIsVisible(&secondWindow, spec)); QVERIFY(!firstAction->isChecked()); QVERIFY(!secondAction->isChecked()); } } void TestDockLayoutUi::closing_and_reopening_docks_keeps_attached_widgets() { constexpr int dockLayoutStateVersion = 1; Settings* appSettings = Settings::instance(); struct SettingsGuard { Settings* settings; QByteArray oldSkipUpdateCheck; bool hadSkipUpdateCheck; QString oldSessionLayoutJson; QByteArray oldWindowState; bool oldConstantsDockVisible; bool oldFunctionsDockVisible; bool oldHistoryDockVisible; bool oldKeypadVisible; bool oldFormulaBookDockVisible; bool oldVariablesDockVisible; bool oldUserFunctionsDockVisible; bool oldUserUnitsDockVisible; bool oldBitfieldVisible; bool oldHasNumberFormatStyleSetting; ~SettingsGuard() { settings->sessionLayoutJson = oldSessionLayoutJson; settings->windowState = oldWindowState; settings->constantsDockVisible = oldConstantsDockVisible; settings->functionsDockVisible = oldFunctionsDockVisible; settings->historyDockVisible = oldHistoryDockVisible; settings->keypadVisible = oldKeypadVisible; settings->formulaBookDockVisible = oldFormulaBookDockVisible; settings->variablesDockVisible = oldVariablesDockVisible; settings->userFunctionsDockVisible = oldUserFunctionsDockVisible; settings->userUnitsDockVisible = oldUserUnitsDockVisible; settings->bitfieldVisible = oldBitfieldVisible; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } } guard { appSettings, qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), appSettings->sessionLayoutJson, appSettings->windowState, appSettings->constantsDockVisible, appSettings->functionsDockVisible, appSettings->historyDockVisible, appSettings->keypadVisible, appSettings->formulaBookDockVisible, appSettings->variablesDockVisible, appSettings->userFunctionsDockVisible, appSettings->userUnitsDockVisible, appSettings->bitfieldVisible, appSettings->hasNumberFormatStyleSetting }; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); appSettings->sessionLayoutJson.clear(); appSettings->windowState.clear(); appSettings->constantsDockVisible = false; appSettings->functionsDockVisible = false; appSettings->historyDockVisible = false; appSettings->keypadVisible = false; appSettings->formulaBookDockVisible = false; appSettings->variablesDockVisible = false; appSettings->userFunctionsDockVisible = false; appSettings->userUnitsDockVisible = false; appSettings->bitfieldVisible = false; appSettings->hasNumberFormatStyleSetting = true; QByteArray legacyDockState; QByteArray populatedDockState; { MainWindow window; window.show(); QCoreApplication::processEvents(); struct DockSpec { const char* setter; const char* objectName; bool hasFocusArgument; }; const DockSpec dockSpecs[] = { { "setBitfieldVisible", "BitfieldDock", false }, { "setFormulaBookDockVisible", "BookDock", true }, { "setConstantsDockVisible", "ConstantsDock", true }, { "setFunctionsDockVisible", "FunctionsDock", true }, { "setHistoryDockVisible", "HistoryDock", true }, { "setVariablesDockVisible", "VariablesDock", true }, { "setUserFunctionsDockVisible", "UserFunctionsDock", true }, { "setUserUnitsDockVisible", "UserUnitsDock", true } }; const auto invokeVisible = [&window](const DockSpec& spec, bool visible) { if (!spec.hasFocusArgument) { return QMetaObject::invokeMethod(&window, spec.setter, Qt::DirectConnection, Q_ARG(bool, visible)); } return QMetaObject::invokeMethod(&window, spec.setter, Qt::DirectConnection, Q_ARG(bool, visible), Q_ARG(bool, false)); }; const auto dockCount = [&window](const QString& objectName) { int count = 0; for (QDockWidget* dock : window.findChildren()) { if (dock->objectName() == objectName) ++count; } return count; }; for (const DockSpec& spec : dockSpecs) { const QString objectName = QString::fromLatin1(spec.objectName); QPointer originalDock = window.findChild(objectName); QVERIFY(originalDock == nullptr); QCOMPARE(dockCount(objectName), 0); QVERIFY(invokeVisible(spec, true)); QCoreApplication::processEvents(); originalDock = window.findChild(objectName); QVERIFY(originalDock != nullptr); QCOMPARE(dockCount(objectName), 1); originalDock->close(); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); QVERIFY(originalDock != nullptr); QVERIFY(!originalDock->isVisible()); QVERIFY(window.dockWidgetArea(originalDock) != Qt::NoDockWidgetArea); QCOMPARE(dockCount(objectName), 1); const QByteArray hiddenState = window.saveState(dockLayoutStateVersion); QVERIFY(window.restoreState(hiddenState, dockLayoutStateVersion)); QVERIFY(invokeVisible(spec, true)); QCoreApplication::processEvents(); QCOMPARE(window.findChild(objectName), originalDock.data()); QCOMPARE(dockCount(objectName), 1); } legacyDockState = window.saveState(); populatedDockState = window.saveState(dockLayoutStateVersion); } appSettings->constantsDockVisible = false; appSettings->functionsDockVisible = false; appSettings->historyDockVisible = false; appSettings->formulaBookDockVisible = false; appSettings->variablesDockVisible = false; appSettings->userFunctionsDockVisible = false; appSettings->userUnitsDockVisible = false; appSettings->bitfieldVisible = false; { appSettings->windowState = legacyDockState; MainWindow legacyStateWindow; legacyStateWindow.show(); QCoreApplication::processEvents(); QDockWidget* bitfield = legacyStateWindow.findChild(QStringLiteral("BitfieldDock")); QVERIFY(bitfield == nullptr); } { appSettings->windowState = populatedDockState; MainWindow restoredWindow; restoredWindow.show(); QCoreApplication::processEvents(); const char* dockNames[] = { "BitfieldDock", "BookDock", "ConstantsDock", "FunctionsDock", "HistoryDock", "VariablesDock", "UserFunctionsDock", "UserUnitsDock" }; for (const char* dockName : dockNames) QCOMPARE(restoredWindow.findChildren(QString::fromLatin1(dockName)).size(), 1); QDockWidget* bitfield = restoredWindow.findChild(QStringLiteral("BitfieldDock")); QVERIFY(bitfield != nullptr); QVERIFY(bitfield->isVisible()); } } void TestDockLayoutUi::formula_book_ignores_repeated_appearance_events_data() { QTest::addColumn("system"); QTest::newRow("theme") << false; QTest::newRow("system") << true; } void TestDockLayoutUi::formula_book_ignores_repeated_appearance_events() { QFETCH(bool, system); MainWindowStateGuard guard; guard.settings->dockAppearance = system ? Settings::DockAppearanceSystem : Settings::DockAppearanceSpeedCrunch; BookDock dock; dock.resize(400, 240); dock.show(); QVERIFY(QTest::qWaitForWindowExposed(&dock)); dock.openPage(QUrl(QStringLiteral("electronics/ohmslaw"))); QCoreApplication::processEvents(); auto* browser = dock.findChild(); QVERIFY(browser); QTextCursor selection = browser->document()->find(QStringLiteral("Index")); QVERIFY(!selection.isNull()); browser->setTextCursor(selection); const QString selectedText = browser->textCursor().selectedText(); const int revision = browser->document()->revision(); const int scroll = browser->verticalScrollBar()->value(); QSignalSpy contents(browser->document(), &QTextDocument::contentsChanged); for (int i = 0; i < 12; ++i) { for (QWidget* widget : {static_cast(&dock), static_cast(browser)}) { QEvent style(QEvent::StyleChange); QCoreApplication::sendEvent(widget, &style); QEvent palette(QEvent::PaletteChange); QCoreApplication::sendEvent(widget, &palette); } } QCoreApplication::processEvents(); QCOMPARE(contents.count(), 0); QCOMPARE(browser->document()->revision(), revision); QCOMPARE(browser->textCursor().selectedText(), selectedText); QCOMPARE(browser->verticalScrollBar()->value(), scroll); QCOMPARE(dock.currentPage(), QStringLiteral("electronics/ohmslaw")); } void TestDockLayoutUi::formula_book_combines_palette_changes() { MainWindowStateGuard guard; guard.settings->dockAppearance = Settings::DockAppearanceSpeedCrunch; BookDock dock; dock.openPage(QUrl(QStringLiteral("electronics/ohmslaw"))); QCoreApplication::processEvents(); auto* browser = dock.findChild(); QVERIFY(browser); const QString text = browser->toPlainText(); browser->zoomIn(3); const QFont font = browser->document()->defaultFont(); QSignalSpy contents(browser->document(), &QTextDocument::contentsChanged); dock.setContentSurfaceColors(QColor("#202020"), QColor("#dddddd")); dock.setContentSurfaceColors(QColor("#303030"), QColor("#eeeeee")); dock.setContentSurfaceColors(QColor("#404040"), QColor("#ffffff")); QCOMPARE(contents.count(), 0); QCoreApplication::processEvents(); QVERIFY(contents.count() > 0); QVERIFY2(contents.count() <= 2, "A palette burst should rebuild the document once"); QCOMPARE(browser->palette().color(QPalette::Base), QColor("#404040")); QCOMPARE(browser->palette().color(QPalette::Text), QColor("#ffffff")); QCOMPARE(browser->document()->defaultFont(), font); QCOMPARE(browser->toPlainText(), text); QCOMPARE(dock.currentPage(), QStringLiteral("electronics/ohmslaw")); // A pending appearance refresh must not bring back the previous page. dock.setContentSurfaceColors(QColor("#505050"), QColor("#eeeeee")); dock.openPage(QUrl(QStringLiteral("index"))); QCOMPARE(dock.currentPage(), QStringLiteral("index")); const QString indexText = browser->toPlainText(); QCoreApplication::processEvents(); QCOMPARE(browser->toPlainText(), indexText); } void TestDockLayoutUi::startup_styling_keeps_formula_book_document() { MainWindowStateGuard guard; guard.settings->dockAppearance = Settings::DockAppearanceSpeedCrunch; guard.settings->formulaBookDockVisible = true; guard.settings->sessionLayoutJson.clear(); guard.settings->windowState.clear(); MainWindow window(false); auto* dock = window.findChild(QStringLiteral("BookDock")); QVERIFY(dock); dock->hide(); auto* browser = dock->findChild(); QVERIFY(browser); QSignalSpy contents(browser->document(), &QTextDocument::contentsChanged); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); QVERIFY2(contents.count() <= 2, "Startup should render the final book palette once"); QVERIFY(!browser->toPlainText().isEmpty()); QVERIFY(dock->isHidden()); const int settledCount = contents.count(); QCoreApplication::processEvents(); QCOMPARE(contents.count(), settledCount); QCOMPARE(window.findChildren().size(), 1); } void TestDockLayoutUi::formula_book_retranslation_refreshes_cached_page() { class BookTranslator : public QTranslator { public: QString translate(const char* context, const char* source, const char* = nullptr, int = -1) const override { if (qstrcmp(context, "Book") == 0 && qstrcmp(source, "Index") == 0) return QStringLiteral("Translated book index"); return QString(); } } translator; BookDock dock; dock.openPage(QUrl(QStringLiteral("electronics/ohmslaw"))); QCoreApplication::processEvents(); auto* browser = dock.findChild(); QVERIFY(browser); QVERIFY(!browser->toPlainText().contains(QStringLiteral("Translated book index"))); QCoreApplication::installTranslator(&translator); const auto removeTranslator = qScopeGuard([&]() { QCoreApplication::removeTranslator(&translator); }); dock.retranslateText(); QVERIFY(browser->toPlainText().contains(QStringLiteral("Translated book index"))); QCOMPARE(dock.currentPage(), QStringLiteral("electronics/ohmslaw")); QCoreApplication::processEvents(); QVERIFY(browser->toPlainText().contains(QStringLiteral("Translated book index"))); } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testdocklayoutui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testdocksui.cpp000066400000000000000000000460211526573132500243360ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/evaluator.h" #include "core/session.h" #include "core/settings.h" #include "gui/constantswidget.h" #include "gui/genericdock.h" #include "gui/splittertreeutils.h" #include "gui/userunitlistwidget.h" #include "gui/variablelistwidget.h" #include "uitestfixture.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class ConstantsTestTranslator : public QTranslator { public: QString translate(const char* context, const char* sourceText, const char* disambiguation = nullptr, int n = -1) const override { Q_UNUSED(disambiguation); Q_UNUSED(n); if (qstrcmp(context, "Constants") == 0 && qstrcmp(sourceText, "pi (Ï€)") == 0) { return QStringLiteral("translated pi"); } return QString(); } }; class TestableConstantsWidget : public ConstantsWidget { public: using ConstantsWidget::handleItem; using ConstantsWidget::updateList; }; class TestableWaylandDock : public GenericDock { public: explicit TestableWaylandDock(QWidget* parent) : GenericDock("TestDocksUi", "Test dock", parent) { } QRect titleRect() const { QStyleOptionDockWidget option; initStyleOption(&option); return option.rect; } bool waylandMoves = true; int moveRequests = 0; protected: bool usesWaylandWindowMoves() const override { return waylandMoves; } void startWindowMove() override { ++moveRequests; } }; class TestDocksUi : public QObject { Q_OBJECT private slots: void init() { UiTestFixture::resetSettings(); } void floating_wayland_dock_uses_system_move_data(); void floating_wayland_dock_uses_system_move(); void floating_wayland_dock_keeps_title_controls(); void constants_dock_inserts_pi_symbol_with_translated_name(); void constants_search_navigates_and_flushes_pending_filter(); void constants_columns_fit_after_hidden_filter_changes(); void constants_summary_popup_ignores_header_and_padding_data(); void constants_summary_popup_ignores_header_and_padding(); void user_units_dock_shows_rhs_and_description_after_definition(); void user_variables_dock_keeps_existing_value_text_after_new_definition(); void splitter_normalization_removes_single_child_nested_splitter_after_pane_close_shape(); }; void TestDocksUi::constants_search_navigates_and_flushes_pending_filter() { TestableConstantsWidget widget; auto* search = widget.findChild(); auto* list = widget.findChild(); auto* domain = widget.findChild(); QVERIFY(search && list && domain); widget.restoreState(domain->itemText(0), QString(), QString()); widget.resize(600, 400); widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); search->setFocus(); QSignalSpy inserted(&widget, &ConstantsWidget::constantSelected); QTest::keyClicks(search, "PROTON"); QTest::keyClick(search, Qt::Key_Down); QVERIFY(search->hasFocus()); QVERIFY(list->topLevelItemCount() > 1); QCOMPARE(list->indexOfTopLevelItem(list->currentItem()), 1); for (int i = 0; i < list->topLevelItemCount(); ++i) QVERIFY(list->topLevelItem(i)->text(0).contains(QStringLiteral("proton"), Qt::CaseInsensitive)); QTest::keyClick(search, Qt::Key_Up); QCOMPARE(list->indexOfTopLevelItem(list->currentItem()), 0); search->setText(QStringLiteral("Euler's number")); QTest::keyClick(search, Qt::Key_Return); QCOMPARE(inserted.count(), 1); QCOMPARE(inserted.takeFirst().at(0).toString(), QStringLiteral("e")); search->setText(QStringLiteral("kg")); QTest::keyClick(search, Qt::Key_Down); QVERIFY(list->topLevelItemCount() > 0); for (int i = 0; i < list->topLevelItemCount(); ++i) { auto* item = list->topLevelItem(i); QVERIFY(item->text(0).contains(QStringLiteral("kg"), Qt::CaseInsensitive) || item->text(2).contains(QStringLiteral("kg"), Qt::CaseInsensitive)); } search->setText(QStringLiteral("no such constant 49236")); QTest::keyClick(search, Qt::Key_Return); QCOMPARE(list->topLevelItemCount(), 0); QCOMPARE(inserted.count(), 0); QTest::keyClick(search, Qt::Key_Up); QVERIFY(list->currentItem() == nullptr); } void TestDocksUi::constants_columns_fit_after_hidden_filter_changes() { TestableConstantsWidget widget; QTreeWidget* list = widget.findChild(); QVERIFY(list); QVERIFY(list->topLevelItemCount() > 0); QComboBox* domain = widget.findChild(); QVERIFY(domain); const QString allDomains = domain->itemText(0); widget.restoreState(allDomains, QString(), QStringLiteral("pi")); QVERIFY(list->topLevelItemCount() > 0); widget.resize(500, 400); widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); const auto verifyColumnWidths = [list]() { for (int column = 0; column < list->columnCount(); ++column) { const int width = list->columnWidth(column); list->resizeColumnToContents(column); QCOMPARE(list->columnWidth(column), width); } }; verifyColumnWidths(); widget.hide(); widget.restoreState(QString(), QString(), QStringLiteral("no-such-constant")); QCOMPARE(list->topLevelItemCount(), 0); widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); QTRY_VERIFY(list->header()->length() >= list->viewport()->width()); widget.restoreState(QString(), QString(), QStringLiteral("")); QVERIFY(list->topLevelItemCount() > 0); verifyColumnWidths(); const QByteArray headerState = list->header()->saveState(); widget.hide(); widget.show(); QCOMPARE(list->header()->saveState(), headerState); } void TestDocksUi::floating_wayland_dock_uses_system_move_data() { QTest::addColumn("vertical"); QTest::newRow("horizontal-title") << false; QTest::newRow("vertical-title") << true; } void TestDocksUi::floating_wayland_dock_uses_system_move() { QFETCH(bool, vertical); QMainWindow window; auto* dock = new TestableWaylandDock(&window); if (vertical) dock->setFeatures(dock->features() | QDockWidget::DockWidgetVerticalTitleBar); window.setCentralWidget(new QWidget(&window)); window.addDockWidget(Qt::RightDockWidgetArea, dock); window.resize(640, 480); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); const QPoint titlePos = dock->titleRect().center(); QVERIFY(!dock->titleRect().isEmpty()); // Attached docks keep Qt's docking behavior. QTest::mouseClick(dock, Qt::LeftButton, Qt::NoModifier, titlePos); QCOMPARE(dock->moveRequests, 0); QVERIFY(!dock->isFloating()); dock->setFloating(true); QVERIFY(QTest::qWaitForWindowExposed(dock)); QCoreApplication::processEvents(); // Offscreen uses native decorations. Qt retains the attached title rect, // allowing us to exercise the Wayland event route without a compositor. QVERIFY(dock->titleRect().contains(titlePos)); const QRect originalGeometry = dock->geometry(); QTest::mouseClick(dock, Qt::RightButton, Qt::NoModifier, titlePos); QCOMPARE(dock->moveRequests, 0); const QPoint contentPos(dock->width() - 20, dock->height() - 20); QVERIFY(!dock->titleRect().contains(contentPos)); QTest::mouseClick(dock, Qt::LeftButton, Qt::NoModifier, contentPos); QCOMPARE(dock->moveRequests, 0); for (int attempt = 1; attempt <= 2; ++attempt) { QTest::mousePress(dock, Qt::LeftButton, Qt::NoModifier, titlePos); QCOMPARE(dock->moveRequests, attempt); const QPoint movedPos = titlePos + QPoint(QApplication::startDragDistance() + 20, 30); QMouseEvent move(QEvent::MouseMove, QPointF(movedPos), QPointF(dock->mapToGlobal(movedPos)), Qt::NoButton, Qt::LeftButton, Qt::NoModifier); QCoreApplication::sendEvent(dock, &move); QTest::mouseRelease(dock, Qt::LeftButton, Qt::NoModifier, movedPos); QCOMPARE(dock->geometry(), originalGeometry); QVERIFY(QWidget::mouseGrabber() != dock); QVERIFY(dock->isFloating()); } // A custom title bar owns its input handling. dock->setTitleBarWidget(new QWidget(dock)); QCoreApplication::processEvents(); QTest::mouseClick(dock, Qt::LeftButton, Qt::NoModifier, titlePos); QCOMPARE(dock->moveRequests, 2); dock->setTitleBarWidget(nullptr); dock->setFloating(false); QCoreApplication::processEvents(); dock->waylandMoves = false; dock->setFloating(true); QTest::mouseClick(dock, Qt::LeftButton, Qt::NoModifier, titlePos); QCOMPARE(dock->moveRequests, 2); } void TestDocksUi::floating_wayland_dock_keeps_title_controls() { QMainWindow window; auto* dock = new TestableWaylandDock(&window); window.addDockWidget(Qt::RightDockWidgetArea, dock); window.resize(640, 480); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); const QPoint titlePos = dock->titleRect().center(); dock->setFloating(true); QCoreApplication::processEvents(); QTest::mouseDClick(dock, Qt::LeftButton, Qt::NoModifier, titlePos); QVERIFY(!dock->isFloating()); QCOMPARE(dock->moveRequests, 0); dock->setFloating(true); dock->setFeatures(dock->features() & ~QDockWidget::DockWidgetFloatable); QTest::mouseDClick(dock, Qt::LeftButton, Qt::NoModifier, titlePos); QVERIFY(dock->isFloating()); dock->setFeatures(dock->features() | QDockWidget::DockWidgetFloatable); dock->setFloating(false); auto* floatButton = dock->findChild(QStringLiteral("qt_dockwidget_floatbutton")); auto* closeButton = dock->findChild(QStringLiteral("qt_dockwidget_closebutton")); QVERIFY(floatButton != nullptr); QVERIFY(closeButton != nullptr); QTest::mouseClick(floatButton, Qt::LeftButton); QVERIFY(dock->isFloating()); // Expose Qt's client title buttons on the offscreen backend as on Wayland. floatButton->show(); closeButton->show(); const QPoint buttonPos = floatButton->geometry().center(); QTest::mouseClick(dock, Qt::LeftButton, Qt::NoModifier, buttonPos); QCOMPARE(dock->moveRequests, 0); QTest::mouseClick(floatButton, Qt::LeftButton); QVERIFY(!dock->isFloating()); QTest::mouseClick(floatButton, Qt::LeftButton); QVERIFY(dock->isFloating()); closeButton->show(); QTest::mouseClick(closeButton, Qt::LeftButton); QVERIFY(dock->isHidden()); QCOMPARE(dock->moveRequests, 0); } void TestDocksUi::constants_dock_inserts_pi_symbol_with_translated_name() { ConstantsTestTranslator translator; QCoreApplication::installTranslator(&translator); TestableConstantsWidget widget; widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); widget.updateList(); QTreeWidget* tree = widget.findChild(); QVERIFY(tree != nullptr); QTreeWidgetItem* piItem = nullptr; for (int i = 0; i < tree->topLevelItemCount(); ++i) { QTreeWidgetItem* item = tree->topLevelItem(i); if (item && item->text(0) == QStringLiteral("translated pi")) { piItem = item; break; } } QVERIFY(piItem != nullptr); QSignalSpy spy(&widget, &ConstantsWidget::constantSelected); widget.handleItem(piItem); QCOMPARE(spy.count(), 1); QCOMPARE(spy.takeFirst().at(0).toString(), QString::fromUtf8("Ï€")); QCoreApplication::removeTranslator(&translator); } void TestDocksUi::constants_summary_popup_ignores_header_and_padding_data() { QTest::addColumn("eventType"); QTest::addColumn("sendToViewport"); for (bool sendToViewport : {false, true}) { const QByteArray target = sendToViewport ? "viewport-" : "tree-"; QTest::newRow(QByteArray(target + "mouse").constData()) << int(QEvent::MouseMove) << sendToViewport; QTest::newRow(QByteArray(target + "hover").constData()) << int(QEvent::HoverMove) << sendToViewport; QTest::newRow(QByteArray(target + "tooltip").constData()) << int(QEvent::ToolTip) << sendToViewport; } } void TestDocksUi::constants_summary_popup_ignores_header_and_padding() { QFETCH(int, eventType); QFETCH(bool, sendToViewport); ConstantsWidget widget; widget.resize(420, 360); QTreeWidget* tree = widget.findChild(); QVERIFY(tree != nullptr); tree->setStyleSheet(QStringLiteral("QTreeWidget { padding: 6px 8px; border: 0; }")); widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); QVERIFY(tree->topLevelItemCount() > 0); QTreeWidgetItem* firstItem = tree->topLevelItem(0); tree->scrollToItem(firstItem); QCoreApplication::processEvents(); QWidget* viewport = tree->viewport(); QWidget* target = sendToViewport ? viewport : tree; const QPoint rowPos = tree->visualItemRect(firstItem).center(); QVERIFY(viewport->rect().contains(rowPos)); const auto sendPosition = [&](const QPoint& viewportPos) { const QPoint pos = viewport->mapTo(target, viewportPos); const QPoint globalPos = viewport->mapToGlobal(viewportPos); if (eventType == QEvent::MouseMove) { QMouseEvent event(QEvent::MouseMove, QPointF(pos), QPointF(globalPos), Qt::NoButton, Qt::NoButton, Qt::NoModifier); QCoreApplication::sendEvent(target, &event); } else if (eventType == QEvent::HoverMove) { QHoverEvent event(QEvent::HoverMove, QPointF(pos), QPointF(globalPos), QPointF(pos)); QCoreApplication::sendEvent(target, &event); } else { QHelpEvent event(QEvent::ToolTip, pos, globalPos); QCoreApplication::sendEvent(target, &event); } }; // Header and padding positions must not resolve to the first constant. const QList outsidePositions = { viewport->mapFrom(tree, QPoint(rowPos.x(), 1)), viewport->mapFromGlobal(tree->header()->mapToGlobal(tree->header()->rect().center())), QPoint(rowPos.x(), -1), QPoint(-1, rowPos.y()), QPoint(viewport->width(), rowPos.y()), QPoint(rowPos.x(), viewport->height()) }; for (const QPoint& outsidePos : outsidePositions) { QVERIFY(!viewport->rect().contains(outsidePos)); sendPosition(rowPos); QFrame* popup = widget.findChild(QStringLiteral("constantsSummaryPopup")); QVERIFY(popup != nullptr); QVERIFY(popup->isVisible()); QLabel* label = popup->findChild(QStringLiteral("constantsSummaryPopupLabel")); QVERIFY(label != nullptr); QCOMPARE(label->text(), firstItem->toolTip(tree->indexAt(rowPos).column())); sendPosition(outsidePos); QVERIFY2(!popup->isVisible(), qPrintable(QStringLiteral("Popup remains visible at (%1, %2)") .arg(outsidePos.x()).arg(outsidePos.y()))); sendPosition(outsidePos); QVERIFY(!popup->isVisible()); } } void TestDocksUi::user_units_dock_shows_rhs_and_description_after_definition() { Session session; Evaluator* evaluator = session.evaluator(); evaluator->unsetAllUserUnits(); evaluator->setExpression(QStringLiteral("[cm_s] = 2 [cm/s] ? speed alias")); const Quantity result = evaluator->eval(); QVERIFY(!result.isNan()); UserUnitListWidget widget; widget.setEvaluator(evaluator); widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); widget.updateList(); QTreeWidget* tree = widget.findChild(); QVERIFY(tree != nullptr); QCOMPARE(tree->topLevelItemCount(), 1); QTreeWidgetItem* item = tree->topLevelItem(0); QVERIFY(item != nullptr); QCOMPARE(item->text(0), QStringLiteral("cm_s")); QCOMPARE(item->text(1), QStringLiteral("2[cm/s]")); QCOMPARE(item->text(2), QStringLiteral("speed alias")); } void TestDocksUi::user_variables_dock_keeps_existing_value_text_after_new_definition() { Session session; Evaluator* evaluator = session.evaluator(); Settings* settings = Settings::instance(); evaluator->unsetAllUserDefinedVariables(); const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; settings->resultFormat = 'f'; settings->resultPrecision = 0; evaluator->setExpression(QStringLiteral("v_fixed = 100000")); QVERIFY(!evaluator->eval().isNan()); VariableListWidget widget; widget.setEvaluator(evaluator); widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); widget.updateList(); QTreeWidget* tree = widget.findChild(); QVERIFY(tree != nullptr); QTreeWidgetItem* fixedItem = nullptr; for (int i = 0; i < tree->topLevelItemCount(); ++i) { QTreeWidgetItem* item = tree->topLevelItem(i); if (item && item->text(0) == QStringLiteral("v_fixed")) { fixedItem = item; break; } } QVERIFY(fixedItem != nullptr); const QString fixedValueBefore = fixedItem->text(1); QVERIFY(!fixedValueBefore.isEmpty()); settings->resultFormat = 'e'; settings->resultPrecision = 2; evaluator->setExpression(QStringLiteral("v_sci = 100000")); QVERIFY(!evaluator->eval().isNan()); widget.updateList(); fixedItem = nullptr; for (int i = 0; i < tree->topLevelItemCount(); ++i) { QTreeWidgetItem* item = tree->topLevelItem(i); if (item && item->text(0) == QStringLiteral("v_fixed")) { fixedItem = item; break; } } QVERIFY(fixedItem != nullptr); QCOMPARE(fixedItem->text(1), fixedValueBefore); settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; } void TestDocksUi::splitter_normalization_removes_single_child_nested_splitter_after_pane_close_shape() { QSplitter root(Qt::Horizontal); QWidget* leftPane = new QWidget(); QSplitter* nested = new QSplitter(Qt::Vertical); QWidget* topPane = new QWidget(); QWidget* bottomPane = new QWidget(); nested->addWidget(topPane); nested->addWidget(bottomPane); root.addWidget(leftPane); root.addWidget(nested); // Simulate closing one pane from a nested splitter. topPane->setParent(nullptr); topPane->deleteLater(); QCoreApplication::processEvents(); normalizeSplitterTree(&root); QCoreApplication::processEvents(); QCOMPARE(root.count(), 2); QVERIFY(root.widget(0) != nullptr); QVERIFY(root.widget(1) != nullptr); QVERIFY(qobject_cast(root.widget(0)) == nullptr); QVERIFY(qobject_cast(root.widget(1)) == nullptr); } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testdocksui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testeditorappearanceui.cpp000066400000000000000000001261171526573132500265460ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" #include "editorgeometrytesthelpers.h" #include "core/startupdiagnostics.h" #include "gui/startupfontpreparation.h" using namespace MainWindowTestHelpers; class TestEditorAppearanceUi : public QObject { Q_OBJECT private slots: void initTestCase(); void init() { UiTestFixture::resetSettings(); } void startup_font_preparation_finishes_before_teardown_data(); void startup_font_preparation_finishes_before_teardown(); void first_result_display_records_constructor_stages(); void editor_display_style_defaults_to_modern_and_persists(); void editor_display_style_switches_all_windows_and_preserves_work(); void editor_display_style_preserves_result_selection_and_copy(); void classic_editor_display_renders_and_tracks_active_pane_data(); void classic_editor_display_renders_and_tracks_active_pane(); void classic_editor_display_restores_split_panes(); void classic_focus_line_follows_open_windows_and_sessions_data(); void classic_focus_line_follows_open_windows_and_sessions(); void classic_vertical_pane_dividers_contrast_with_input_data(); void classic_vertical_pane_dividers_contrast_with_input(); void classic_separator_thickness_preserves_input_geometry_data(); void classic_separator_thickness_preserves_input_geometry(); void typing_long_expressions_keeps_editor_height_stable_data(); void typing_long_expressions_keeps_editor_height_stable(); void editor_popups_follow_style_padding_data(); void editor_popups_follow_style_padding(); void live_result_follows_editor_height_on_history_recall_data(); void live_result_follows_editor_height_on_history_recall(); }; void TestEditorAppearanceUi::initTestCase() { // Fail before a file-operation test can open an unhandled error dialog. for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) { QVERIFY2(QDir().mkpath(path), qPrintable(QStringLiteral("Cannot create test storage at %1").arg(path))); QTemporaryFile probe(QDir(path).filePath(QStringLiteral("storage-probe-XXXXXX"))); QVERIFY2(probe.open(), qPrintable(QStringLiteral("Cannot write test storage at %1: %2") .arg(path, probe.errorString()))); } } void TestEditorAppearanceUi::startup_font_preparation_finishes_before_teardown_data() { QTest::addColumn("explicitWait"); QTest::newRow("scope-exit") << false; QTest::newRow("repeated-wait") << true; } void TestEditorAppearanceUi::startup_font_preparation_finishes_before_teardown() { QFETCH(bool, explicitWait); StartupDiagnostics::begin(); const auto finishRecording = qScopeGuard([]() { StartupDiagnostics::firstPaintFinished(); StartupDiagnostics::finishWhenIdle(); }); { StartupFontPreparation preparation; if (explicitWait) { preparation.wait(); preparation.wait(); } } const auto snapshot = StartupDiagnostics::snapshot(); int workerCalls = 0; int waitCalls = 0; int asyncCalls = 0; for (const auto& phase : snapshot.phases) { if (phase.name == QStringLiteral("Prepare font database")) { workerCalls += phase.calls; QVERIFY(phase.worker); } else if (phase.name == QStringLiteral("Wait for font preparation")) { waitCalls += phase.calls; QVERIFY(!phase.worker); } else if (phase.name == QStringLiteral("Prepare font database (async total)")) { asyncCalls += phase.calls; } QCOMPARE(phase.running, 0); } const int expected = QApplication::platformName() == QLatin1String("cocoa") ? 1 : 0; QCOMPARE(workerCalls, expected); QCOMPARE(waitCalls, expected); QCOMPARE(asyncCalls, expected); StartupDiagnostics::firstPaintFinished(); StartupDiagnostics::finishWhenIdle(); QVERIFY(StartupDiagnostics::snapshot().complete); } void TestEditorAppearanceUi::first_result_display_records_constructor_stages() { StartupDiagnostics::begin(); const auto finishRecording = qScopeGuard([]() { StartupDiagnostics::firstPaintFinished(); StartupDiagnostics::finishWhenIdle(); }); MainWindow window(false); const auto snapshot = StartupDiagnostics::snapshot(); const auto findPhase = [&](const QString& name) -> const StartupDiagnostics::Phase* { for (const auto& phase : snapshot.phases) { if (phase.name == name) return &phase; } return nullptr; }; const auto* display = findPhase(QStringLiteral("Construct initial result display")); const auto* controls = findPhase(QStringLiteral("Initialize result display controls")); const auto* editor = findPhase(QStringLiteral("Construct initial expression editor")); const auto* highlighter = findPhase(QStringLiteral("Initialize syntax highlighter")); const auto* pane = findPhase(QStringLiteral("Create and bind initial session pane")); QVERIFY(display); QVERIFY(controls); QVERIFY(editor); QVERIFY(highlighter); QVERIFY(pane); QCOMPARE(display->calls, 1); QCOMPARE(controls->calls, 1); QCOMPARE(editor->calls, 1); QCOMPARE(highlighter->calls, 2); QCOMPARE(pane->calls, 1); QVERIFY(display->firstStartNs <= highlighter->firstStartNs); QVERIFY(highlighter->firstStartNs <= controls->firstStartNs); QVERIFY(controls->firstStartNs + controls->totalNs <= display->firstStartNs + display->totalNs); QVERIFY(display->firstStartNs + display->totalNs <= editor->firstStartNs); QVERIFY(editor->firstStartNs + editor->totalNs <= pane->firstStartNs); } void TestEditorAppearanceUi::editor_display_style_defaults_to_modern_and_persists() { Settings* settings = Settings::instance(); QCOMPARE(settings->editorDisplayStyle, Settings::EditorDisplayModern); for (const auto style : {Settings::EditorDisplayClassic, Settings::EditorDisplayModern}) { settings->editorDisplayStyle = style; settings->save(); settings->editorDisplayStyle = style == Settings::EditorDisplayModern ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; settings->load(); QCOMPARE(settings->editorDisplayStyle, style); } QSettings persisted(Settings::getConfigPath() + QStringLiteral("/SpeedCrunch.ini"), QSettings::IniFormat); const QString key = QStringLiteral("SpeedCrunch/Display/EditorDisplayStyle"); persisted.remove(key); persisted.sync(); settings->load(); QCOMPARE(settings->editorDisplayStyle, Settings::EditorDisplayModern); persisted.setValue(key, 99); persisted.sync(); settings->load(); QCOMPARE(settings->editorDisplayStyle, Settings::EditorDisplayModern); settings->editorDisplayStyle = Settings::EditorDisplayClassic; settings->save(); QVERIFY(settings->resetToDefaults()); QCOMPARE(settings->editorDisplayStyle, Settings::EditorDisplayModern); } void TestEditorAppearanceUi::editor_display_style_switches_all_windows_and_preserves_work() { Settings* settings = Settings::instance(); settings->autoCalc = false; MainWindow first(false); MainWindow second(false); for (MainWindow* window : {&first, &second}) { QVERIFY(QMetaObject::invokeMethod(window, "splitActivePaneRight", Qt::DirectConnection)); QVERIFY(QMetaObject::invokeMethod(window, "showNewSessionDialog", Qt::DirectConnection)); window->resize(900, 600); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); } const auto editors = first.findChildren() + second.findChildren(); const auto displays = first.findChildren() + second.findChildren(); QCOMPARE(editors.size(), 4); QCOMPARE(displays.size(), 4); QMap modernHeights; QMap modernInsets; QMap modernColors; QMap results; QMap modernGutters; for (Editor* editor : editors) { editor->setText(QStringLiteral("1234+56")); QTextCursor cursor = editor->textCursor(); cursor.setPosition(2); cursor.setPosition(5, QTextCursor::KeepAnchor); editor->setTextCursor(cursor); modernHeights.insert(editor, editor->height()); modernInsets.insert(editor, editor->viewport()->x()); modernColors.insert(editor, editor->palette().color(QPalette::Base)); } for (ResultDisplay* display : displays) { Session* session = const_cast(display->session()); QVERIFY(session); session->addHistoryEntry(HistoryEntry(QStringLiteral("6*7"), Quantity(42))); display->refresh(); results.insert(display, display->toPlainText()); modernGutters.insert(display, display->viewport()->x()); } QMenu* menu = first.findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(menu); QVERIFY(menu->actions().size() >= 2); QVERIFY(menu->actions().at(1)->isChecked()); for (const bool classic : {true, false, true}) { menu->actions().at(classic ? 0 : 1)->trigger(); QCOMPARE(settings->editorDisplayStyle, classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern); QCoreApplication::processEvents(); for (MainWindow* window : {&first, &second}) { QMenu* windowMenu = window->findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(windowMenu); QCOMPARE(windowMenu->actions().at(0)->isChecked(), classic); QCOMPARE(windowMenu->actions().at(1)->isChecked(), !classic); } for (Editor* editor : editors) { QCOMPARE(editor->text(), QStringLiteral("1234+56")); QCOMPARE(editor->textCursor().anchor(), 2); QCOMPARE(editor->textCursor().position(), 5); if (classic) { QVERIFY(editor->height() < modernHeights.value(editor)); QVERIFY(editor->viewport()->x() < modernInsets.value(editor)); } else { QCOMPARE(editor->height(), modernHeights.value(editor)); QCOMPARE(editor->viewport()->x(), modernInsets.value(editor)); } } for (ResultDisplay* display : displays) { QCOMPARE(display->toPlainText(), results.value(display)); QCOMPARE(display->session()->historySize(), 1); QCOMPARE(display->viewport()->x(), classic ? 4 : modernGutters.value(display)); } } // Inactive tabs share their pane's widgets, and new panes inherit Classic. for (MainWindow* window : {&first, &second}) { for (ResultDisplay* display : window->findChildren()) { QTabBar* tabs = tabBarForDisplay(display); QVERIFY(tabs); for (int index = 0; index < tabs->count(); ++index) { tabs->setCurrentIndex(index); QCOMPARE(display->viewport()->x(), 4); Editor* editor = editorForDisplay(display); const QColor expected = modernColors.value(editor); QCOMPARE(editor->palette().color(QPalette::Base).rgba(), expected.rgba()); } } QVERIFY(QMetaObject::invokeMethod(window, "splitActivePaneDown", Qt::DirectConnection)); for (ResultDisplay* display : window->findChildren()) QCOMPARE(display->viewport()->x(), 4); } MainWindow third(false); QCOMPARE(third.findChild()->viewport()->x(), 4); QVERIFY(third.findChild(QStringLiteral("EditorDisplayStyleMenu"))->actions().at(0)->isChecked()); QTimer::singleShot(0, &first, []() { auto* dialog = qobject_cast(QApplication::activeModalWidget()); QVERIFY(dialog); dialog->button(QMessageBox::Yes)->click(); }); first.findChild(QStringLiteral("ResetAllSettingsAction"))->trigger(); QCOMPARE(settings->editorDisplayStyle, Settings::EditorDisplayModern); for (MainWindow* window : {&first, &second, &third}) { QVERIFY(window->findChild(QStringLiteral("EditorDisplayStyleMenu"))->actions().at(1)->isChecked()); for (ResultDisplay* display : window->findChildren()) QVERIFY(display->viewport()->x() > 0); } } void TestEditorAppearanceUi::editor_display_style_preserves_result_selection_and_copy() { Settings::instance()->autoCalc = false; MainWindow window(false); ResultDisplay* display = window.findChild(); Editor* editor = window.findChild(); QVERIFY(display); QVERIFY(editor); editor->setText(QStringLiteral("123+456")); Session* session = const_cast(display->session()); session->addHistoryEntry(HistoryEntry(QStringLiteral("6*7"), Quantity(42))); display->refresh(); QTextCursor selection = display->textCursor(); selection.select(QTextCursor::Document); display->setTextCursor(selection); const QString selectedText = selection.selectedText(); QVERIFY(!selectedText.isEmpty()); QSignalSpy edits(editor, &Editor::textChanged); QMenu* menu = window.findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(menu); QAction* classic = directMenuActionWithText(menu, QStringLiteral("&Classic")); QVERIFY(classic); QActionGroup* styles = classic->actionGroup(); QVERIFY(styles); for (QAction* action : styles->actions()) { action->trigger(); QCOMPARE(display->textCursor().selectedText(), selectedText); QCOMPARE(editor->text(), QStringLiteral("123+456")); QCOMPARE(edits.count(), 0); QApplication::clipboard()->clear(); QVERIFY(QMetaObject::invokeMethod(&window, "copy", Qt::DirectConnection)); QCOMPARE(QApplication::clipboard()->text(), display->toPlainText()); } } void TestEditorAppearanceUi::classic_editor_display_renders_and_tracks_active_pane_data() { QTest::addColumn("background"); QTest::newRow("dark") << QStringLiteral("#310b28"); QTest::newRow("light") << QStringLiteral("#eeeeee"); } void TestEditorAppearanceUi::classic_editor_display_renders_and_tracks_active_pane() { QFETCH(QString, background); MainWindowStateGuard guard; guard.settings->editorDisplayStyle = Settings::EditorDisplayClassic; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); guard.settings->constantsDockVisible = true; guard.settings->cursorBlinking = false; MainWindow window(false); window.resize(900, 600); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QCoreApplication::processEvents(); const auto displays = window.findChildren(); QCOMPARE(displays.size(), 2); QMenu* styles = window.findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(styles); styles->actions().at(1)->trigger(); QCoreApplication::processEvents(); const QColor inactiveColor = editorForDisplay(displays.first())->palette().color(QPalette::Base); styles->actions().at(0)->trigger(); QCoreApplication::processEvents(); const QColor primary = generatePrimaryFromBackground(QColor(background)); const auto separatorColor = [](Editor* editor) { const QImage image = editor->grab().toImage(); return image.pixelColor(image.width() / 2, 0).rgba(); }; QMap geometry; for (ResultDisplay* display : displays) { Editor* editor = editorForDisplay(display); QVERIFY(editor); QCOMPARE(editor->geometry().left(), display->geometry().left()); QCOMPARE(editor->width(), display->width()); QCOMPARE(editor->geometry().top(), display->geometry().bottom() + 1); const QColor expected = inactiveColor; QCOMPARE(editor->palette().color(QPalette::Base).rgba(), expected.rgba()); const int editorTextX = editor->viewport()->x() + editor->cursorRect().x(); const int displayTextX = display->viewport()->x() + display->cursorRect().x(); QCOMPARE(editorTextX, displayTextX); QCOMPARE(editorTextX, UiConfig::ClassicTextInset); QVERIFY(editor->height() - editor->viewport()->geometry().bottom() - 1 >= UiConfig::ClassicEditorVerticalPadding); geometry.insert(editor, editor->geometry()); const QImage image = editor->grab().toImage(); QCOMPARE(image.pixelColor(0, image.height() / 2).rgba(), expected.rgba()); } for (ResultDisplay* activeDisplay : displays) { Editor* activeEditor = editorForDisplay(activeDisplay); QTest::mouseClick(activeEditor->viewport(), Qt::LeftButton); QTRY_COMPARE(separatorColor(activeEditor), primary.rgba()); for (ResultDisplay* display : displays) { Editor* editor = editorForDisplay(display); QCOMPARE(editor->geometry(), geometry.value(editor)); const QColor expected = inactiveColor; QCOMPARE(editor->palette().color(QPalette::Base).rgba(), expected.rgba()); QCOMPARE(editor->viewport()->palette().color(QPalette::Base).rgba(), expected.rgba()); const QImage image = editor->grab().toImage(); for (const QPoint point : {QPoint(0, image.height() / 2), QPoint(image.width() / 2, image.height() / 2), QPoint(image.width() - 1, image.height() - 1)}) { QCOMPARE(image.pixelColor(point).rgba(), expected.rgba()); } if (display != activeDisplay) QTRY_COMPARE(separatorColor(editor), inactiveColor.rgba()); } // Selecting history keeps the pane's input destination indicated. QTest::mouseClick(activeDisplay->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(20, 20)); QTRY_COMPARE(separatorColor(activeEditor), primary.rgba()); } QDockWidget* constants = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constants); auto* search = constants->findChild(); QVERIFY(search); search->setFocus(); QTRY_VERIFY(search->hasFocus()); for (ResultDisplay* display : displays) { QTRY_COMPARE(separatorColor(editorForDisplay(display)), inactiveColor.rgba()); QCOMPARE(editorForDisplay(display)->palette().color(QPalette::Base).rgba(), inactiveColor.rgba()); } // The inactive fill follows the Modern input color after a theme change. guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#213c31")}}); QVERIFY(QMetaObject::invokeMethod(&window, "colorSchemeChanged", Qt::DirectConnection)); styles->actions().at(1)->trigger(); const QColor updatedInactiveColor = editorForDisplay(displays.first())->palette().color(QPalette::Base); styles->actions().at(0)->trigger(); for (ResultDisplay* display : displays) QCOMPARE(editorForDisplay(display)->palette().color(QPalette::Base).rgba(), updatedInactiveColor.rgba()); } void TestEditorAppearanceUi::classic_editor_display_restores_split_panes() { MainWindowStateGuard guard; guard.settings->editorDisplayStyle = Settings::EditorDisplayClassic; { MainWindow original(false); QVERIFY(QMetaObject::invokeMethod(&original, "splitActivePaneRight", Qt::DirectConnection)); QVERIFY(QMetaObject::invokeMethod(&original, "showNewSessionDialog", Qt::DirectConnection)); for (Editor* editor : original.findChildren()) editor->setText(QStringLiteral("123+456")); original.persistSessionAndSettingsForShutdown(); } QVERIFY(!guard.settings->sessionLayoutJson.isEmpty()); MainWindow restored; restored.show(); QCoreApplication::processEvents(); const auto displays = restored.findChildren(); QCOMPARE(displays.size(), 2); QMenu* menu = restored.findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(menu); QVERIFY(menu->actions().at(0)->isChecked()); menu->actions().at(1)->trigger(); const QColor inactiveColor = editorForDisplay(displays.first())->palette().color(QPalette::Base); menu->actions().at(0)->trigger(); for (ResultDisplay* display : displays) { QCOMPARE(display->viewport()->x(), 4); Editor* editor = editorForDisplay(display); QVERIFY(editor); QCOMPARE(editor->text(), QStringLiteral("123+456")); const QColor expected = inactiveColor; QCOMPARE(editor->palette().color(QPalette::Base).rgba(), expected.rgba()); } menu->actions().at(1)->trigger(); for (ResultDisplay* display : displays) QVERIFY(display->viewport()->x() > 0); } void TestEditorAppearanceUi::classic_focus_line_follows_open_windows_and_sessions_data() { QTest::addColumn("background"); QTest::newRow("dark") << QStringLiteral("#310b28"); QTest::newRow("light") << QStringLiteral("#eeeeee"); } void TestEditorAppearanceUi::classic_focus_line_follows_open_windows_and_sessions() { QFETCH(QString, background); MainWindowStateGuard guard; guard.settings->editorDisplayStyle = Settings::EditorDisplayClassic; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); guard.settings->autoCalc = false; guard.settings->cursorBlinking = false; MainWindow window(false); window.resize(900, 600); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); QVERIFY(editor); editor->setText(QStringLiteral("1234+56")); const QString draft = editor->text(); QTest::mouseClick(editor->viewport(), Qt::LeftButton); QCoreApplication::processEvents(); const int height = editor->height(); const QRect viewport = editor->viewport()->geometry(); const QColor fill = editor->palette().color(QPalette::Base); const QColor primary = generatePrimaryFromBackground(QColor(background)); const auto topColor = [](Editor* input) { const QImage image = input->grab().toImage(); return image.pixelColor(image.width() / 2, 0).rgba(); }; const auto checkActiveLine = [&](bool visible) { window.activateWindow(); QCoreApplication::processEvents(); QTest::mouseClick(editor->viewport(), Qt::LeftButton); QCoreApplication::processEvents(); QTRY_VERIFY(editor->hasFocus()); QTRY_COMPARE(topColor(editor), visible ? primary.rgba() : fill.rgba()); QVERIFY(editor->cursorWidth() > 0); QCOMPARE(editor->height(), height); QCOMPARE(editor->viewport()->geometry().top(), viewport.top()); QCOMPARE(editor->viewport()->height(), viewport.height()); QCOMPARE(editor->palette().color(QPalette::Base).rgba(), fill.rgba()); }; checkActiveLine(false); QCOMPARE(editor->text(), draft); // Style changes keep the Modern outline and suppress the single Classic line. QMenu* styles = window.findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(styles); styles->actions().at(1)->trigger(); QCoreApplication::processEvents(); const QPixmap modern = editor->grab(); QCOMPARE(modern.toImage().pixelColor(modern.width() / 2, qRound(UiConfig::ModernEditorTopMargin * modern.devicePixelRatio())).rgba(), primary.rgba()); styles->actions().at(0)->trigger(); checkActiveLine(false); QVERIFY(QMetaObject::invokeMethod(&window, "showNewSessionDialog", Qt::DirectConnection)); checkActiveLine(false); QVERIFY(QMetaObject::invokeMethod(&window, "showNewSessionDialog", Qt::DirectConnection)); checkActiveLine(false); QTabBar* tabs = tabBarForDisplay(window.findChild()); QVERIFY(tabs); QCOMPARE(tabs->count(), 3); for (int index = 0; index < tabs->count(); ++index) { tabs->setCurrentIndex(index); checkActiveLine(false); } QVERIFY(QMetaObject::invokeMethod(&window, "closeCurrentSession", Qt::DirectConnection)); checkActiveLine(false); tabs->setCurrentIndex(1); QVERIFY(QMetaObject::invokeMethod(&window, "closeCurrentSession", Qt::DirectConnection)); checkActiveLine(false); QCOMPARE(editor->text(), draft); QVERIFY(QMetaObject::invokeMethod(&window, "showNewPrivateSession", Qt::DirectConnection)); checkActiveLine(false); QVERIFY(QMetaObject::invokeMethod(&window, "closeCurrentSession", Qt::DirectConnection)); checkActiveLine(false); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); checkActiveLine(true); QPointer otherEditor; for (Editor* input : window.findChildren()) { if (input != editor) otherEditor = input; } QVERIFY(otherEditor); QTest::mouseClick(otherEditor->viewport(), Qt::LeftButton); QVERIFY(QMetaObject::invokeMethod(&window, "closeCurrentPane", Qt::DirectConnection)); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); checkActiveLine(false); // Multiple tabs stay unmarked after the second window closes as well. QVERIFY(QMetaObject::invokeMethod(&window, "showNewSessionDialog", Qt::DirectConnection)); checkActiveLine(false); { MainWindow second(false); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&second)); checkActiveLine(true); second.close(); checkActiveLine(false); } checkActiveLine(false); { // Destruction also updates the remaining window without a close event. MainWindow second(false); checkActiveLine(true); } checkActiveLine(false); QVERIFY(QMetaObject::invokeMethod(&window, "closeCurrentSession", Qt::DirectConnection)); checkActiveLine(false); QCOMPARE(editor->text(), draft); } void TestEditorAppearanceUi::classic_vertical_pane_dividers_contrast_with_input_data() { QTest::addColumn("background"); QTest::addColumn("keypadVisible"); QTest::newRow("dark") << QStringLiteral("#310b28") << false; QTest::newRow("light") << QStringLiteral("#eeeeee") << false; QTest::newRow("dark-keypad") << QStringLiteral("#310b28") << true; QTest::newRow("light-keypad") << QStringLiteral("#eeeeee") << true; } void TestEditorAppearanceUi::classic_vertical_pane_dividers_contrast_with_input() { QFETCH(QString, background); QFETCH(bool, keypadVisible); MainWindowStateGuard guard; guard.settings->editorDisplayStyle = Settings::EditorDisplayClassic; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); guard.settings->keypadMode = keypadVisible ? Settings::KeypadModeBasicWide : Settings::KeypadModeDisabled; MainWindow window(false); window.resize(1000, 900); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneDown", Qt::DirectConnection)); QCoreApplication::processEvents(); QSplitter* root = window.findChild(QStringLiteral("MainSplitContainer")); QVERIFY(root); QCOMPARE(root->orientation(), Qt::Horizontal); QSplitterHandle* divider = root->handle(1); QVERIFY(divider); auto* styles = window.findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(styles); const auto displays = window.findChildren(); QCOMPARE(displays.size(), 3); QTest::mouseMove(displays.first()->viewport(), QPoint(30, 30)); for (const bool classic : {true, false, true}) { styles->actions().at(classic ? 0 : 1)->trigger(); QCoreApplication::processEvents(); QCOMPARE(root->handleWidth(), UiConfig::SessionPaneSplitterWidth); const QPixmap pixmap = divider->grab(); const QImage image = pixmap.toImage(); const QColor dividerColor = image.pixelColor(image.width() / 2, image.height() / 2); for (ResultDisplay* display : displays) { Editor* editor = editorForDisplay(display); QVERIFY(editor); const QColor fill = editor->palette().color(QPalette::Base); if (classic) QVERIFY(dividerColor.rgba() != fill.rgba()); else QCOMPARE(dividerColor.rgba(), fill.rgba()); const QPoint position = divider->mapFromGlobal( editor->mapToGlobal(QPoint(0, editor->height() / 2))); const int row = qRound(position.y() * pixmap.devicePixelRatio()); QVERIFY(row >= 0 && row < image.height()); QCOMPARE(image.pixelColor(image.width() / 2, row).rgba(), dividerColor.rgba()); if (classic) { const QImage editorImage = editor->grab().toImage(); QCOMPARE(editorImage.pixelColor(0, editorImage.height() / 2).rgba(), fill.rgba()); } } } } void TestEditorAppearanceUi::classic_separator_thickness_preserves_input_geometry_data() { QTest::addColumn("background"); QTest::newRow("dark") << QStringLiteral("#310b28"); QTest::newRow("light") << QStringLiteral("#eeeeee"); } void TestEditorAppearanceUi::classic_separator_thickness_preserves_input_geometry() { QFETCH(QString, background); MainWindowStateGuard guard; guard.settings->editorDisplayStyle = Settings::EditorDisplayClassic; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); guard.settings->autoCalc = false; MainWindow window(false); window.resize(700, 600); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); const auto editors = window.findChildren(); QCOMPARE(editors.size(), 2); QMap geometry; QMap viewportGeometry; QMap cursorGeometry; QMap cursors; for (Editor* editor : editors) { editor->setText(QStringLiteral("1234567890+").repeated(12)); QCoreApplication::processEvents(); QVERIFY(editor->document()->begin().layout()->lineCount() > 1); geometry.insert(editor, editor->geometry()); viewportGeometry.insert(editor, editor->viewport()->geometry()); cursorGeometry.insert(editor, editor->cursorRect()); cursors.insert(editor, editor->textCursor()); } const QColor primary = generatePrimaryFromBackground(QColor(background)); const auto pixelAtRow = [](Editor* editor, int row) { const QPixmap pixmap = editor->grab(); const QImage image = pixmap.toImage(); return image.pixelColor(image.width() / 2, qRound(row * pixmap.devicePixelRatio())).rgba(); }; for (int cycle = 0; cycle < 2; ++cycle) { for (Editor* activeEditor : editors) { QTest::mouseClick(activeEditor->viewport(), Qt::LeftButton); activeEditor->setTextCursor(cursors.value(activeEditor)); QTRY_VERIFY(activeEditor->hasFocus()); QCoreApplication::processEvents(); QTRY_COMPARE(pixelAtRow(activeEditor, 0), primary.rgba()); for (Editor* editor : editors) { const QColor base = editor->palette().color(QPalette::Base); if (editor == activeEditor) { QCOMPARE(pixelAtRow(editor, 1), primary.rgba()); } else { QCOMPARE(pixelAtRow(editor, 0), base.rgba()); QCOMPARE(pixelAtRow(editor, 1), base.rgba()); } QCOMPARE(pixelAtRow(editor, 2), base.rgba()); QCOMPARE(editor->geometry(), geometry.value(editor)); QCOMPARE(editor->viewport()->geometry(), viewportGeometry.value(editor)); QCOMPARE(editor->cursorRect().topLeft(), cursorGeometry.value(editor).topLeft()); QCOMPARE(editor->cursorRect().height(), cursorGeometry.value(editor).height()); } } } } void TestEditorAppearanceUi::typing_long_expressions_keeps_editor_height_stable_data() { QTest::addColumn("classic"); QTest::addColumn("split"); QTest::newRow("modern-single-pane") << false << false; QTest::newRow("modern-split-panes") << false << true; QTest::newRow("classic-single-pane") << true << false; QTest::newRow("classic-split-panes") << true << true; } void TestEditorAppearanceUi::typing_long_expressions_keeps_editor_height_stable() { QFETCH(bool, classic); QFETCH(bool, split); MainWindowStateGuard guard; guard.settings->editorDisplayStyle = classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; guard.settings->autoCalc = false; MainWindow window(false); window.resize(700, 600); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); if (split) QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); Editor* editor = window.findChildren().last(); editor->setAutoCompletionEnabled(false); QTest::mouseClick(editor->viewport(), Qt::LeftButton); QCoreApplication::processEvents(); editor->setText(QString()); QCoreApplication::processEvents(); const int singleLineHeight = editor->height(); const int singleLineTextHeight = EditorGeometryTestHelpers::visibleTextHeight(*editor); int cappedHeight = -1; class ResizeRecorder : public QObject { public: QList heights; QList viewportHeights; Editor* editor = nullptr; bool eventFilter(QObject* object, QEvent* event) override { if (event->type() == QEvent::Resize) { const int height = static_cast(event)->size().height(); (object == editor ? heights : viewportHeights).append(height); } return false; } } recorder; recorder.editor = editor; editor->installEventFilter(&recorder); editor->viewport()->installEventFilter(&recorder); const QString input = QStringLiteral("123+456+789+").repeated(50); for (const QChar ch : input) { const int previousHeight = editor->height(); const int previousViewportHeight = editor->viewport()->height(); QTest::keyClicks(editor, QString(ch)); QCoreApplication::processEvents(); QVERIFY2(editor->height() >= previousHeight, qPrintable(QStringLiteral("Editor shrinks from %1 to %2 with %3 characters and %4 lines") .arg(previousHeight).arg(editor->height()).arg(editor->text().size()) .arg(editor->document()->begin().layout()->lineCount()))); for (const int height : recorder.heights) QVERIFY2(height >= previousHeight, qPrintable(QStringLiteral("Editor shrinks from %1 to %2") .arg(previousHeight).arg(height))); for (const int height : recorder.viewportHeights) QVERIFY2(height >= previousViewportHeight, qPrintable(QStringLiteral("Viewport shrinks from %1 to %2") .arg(previousViewportHeight).arg(height))); recorder.heights.clear(); recorder.viewportHeights.clear(); const int visibleLines = qBound(1, editor->document()->begin().layout()->lineCount(), 5); QCOMPARE(editor->height(), singleLineHeight + EditorGeometryTestHelpers::visibleTextHeight(*editor) - singleLineTextHeight); if (visibleLines == 5) { if (cappedHeight < 0) cappedHeight = editor->height(); QCOMPARE(editor->height(), cappedHeight); } QVERIFY(editor->cursorRect().top() >= 0); QVERIFY(editor->cursorRect().bottom() < editor->viewport()->height()); } QVERIFY(cappedHeight > singleLineHeight); QCOMPARE(editor->height(), cappedHeight); QVERIFY(editor->document()->begin().layout()->lineCount() > 5); editor->selectAll(); QTest::keyClicks(editor, QStringLiteral("1")); QCoreApplication::processEvents(); QCOMPARE(editor->height(), singleLineHeight); editor->undo(); QCoreApplication::processEvents(); QCOMPARE(editor->height(), cappedHeight); QVERIFY(editor->cursorRect().top() >= 0); QVERIFY(editor->cursorRect().bottom() < editor->viewport()->height()); } void TestEditorAppearanceUi::editor_popups_follow_style_padding_data() { QTest::addColumn("initialStyle"); QTest::addColumn("popupKind"); for (const auto style : {Settings::EditorDisplayClassic, Settings::EditorDisplayModern}) { for (const QString& kind : {QStringLiteral("current"), QStringLiteral("selection"), QStringLiteral("error")}) { const QString name = QStringLiteral("%1-%2") .arg(style == Settings::EditorDisplayClassic ? QStringLiteral("classic") : QStringLiteral("modern"), kind); QTest::newRow(qPrintable(name)) << int(style) << kind; } } } void TestEditorAppearanceUi::editor_popups_follow_style_padding() { QFETCH(int, initialStyle); QFETCH(QString, popupKind); Settings* settings = Settings::instance(); settings->editorDisplayStyle = static_cast(initialStyle); MainWindow window(false); window.resize(900, 600); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneDown", Qt::DirectConnection)); QCoreApplication::processEvents(); const auto displays = window.findChildren(); QCOMPARE(displays.size(), 3); auto* popup = window.findChild(QStringLiteral("EditorStatePopup")); QVERIFY(popup); auto* styles = window.findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(styles); int operand = 24; for (ResultDisplay* display : displays) { Editor* editor = editorForDisplay(display); QVERIFY(editor); QTest::mouseClick(editor->viewport(), Qt::LeftButton); if (popupKind == QLatin1String("error")) { editor->setText(QStringLiteral("1/0")); QTest::keyClick(editor, Qt::Key_Return); QTRY_VERIFY(!popup->text().isEmpty()); QVERIFY(!popup->text().contains(QStringLiteral("Current result:"))); } else { editor->setText(QStringLiteral("1+%1").arg(operand++)); editor->setCursorPosition(editor->text().size()); editor->refreshAutoCalc(); if (popupKind == QLatin1String("selection")) { QTextCursor selection = editor->textCursor(); selection.setPosition(0); selection.setPosition(1, QTextCursor::KeepAnchor); editor->setTextCursor(selection); QTRY_VERIFY(popup->text().contains(QStringLiteral("Selection result:"))); QCOMPARE(popup->text(), QStringLiteral("Selection result:
    1")); } else { QTRY_VERIFY(popup->text().contains(QStringLiteral("Current result:"))); QCOMPARE(popup->text(), QStringLiteral("Current result:
    %1").arg(operand)); } } QTRY_VERIFY(popup->isVisible()); const QString message = popup->text(); for (const auto style : {static_cast(initialStyle), initialStyle == Settings::EditorDisplayClassic ? Settings::EditorDisplayModern : Settings::EditorDisplayClassic}) { styles->actions().at(style == Settings::EditorDisplayClassic ? 0 : 1)->trigger(); const int inset = style == Settings::EditorDisplayClassic ? UiConfig::ClassicTextInset : UiConfig::ResultTooltipStartMargin; QTRY_COMPARE(popup->mapToGlobal(QPoint(0, 0)).x(), editor->mapToGlobal(QPoint(inset, 0)).x()); QTRY_COMPARE(popup->mapToGlobal(QPoint(0, popup->height())).y(), editor->mapToGlobal(QPoint(0, 0)).y()); QCOMPARE(popup->text(), message); QVERIFY(popup->isVisible()); } } } void TestEditorAppearanceUi::live_result_follows_editor_height_on_history_recall_data() { QTest::addColumn("classic"); QTest::addColumn("split"); QTest::newRow("modern-single-pane") << false << false; QTest::newRow("modern-split-panes") << false << true; QTest::newRow("classic-single-pane") << true << false; QTest::newRow("classic-split-panes") << true << true; } void TestEditorAppearanceUi::live_result_follows_editor_height_on_history_recall() { QFETCH(bool, classic); QFETCH(bool, split); MainWindowStateGuard guard; guard.settings->editorDisplayStyle = classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; guard.settings->upDownArrowBehavior = Settings::UpDownArrowBehaviorAlways; MainWindow window(false); window.resize(700, 600); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); if (split) QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); Editor* editor = window.findChildren().last(); editor->setAutoCompletionEnabled(false); editor->setAutoCalcEnabled(false); QTest::mouseClick(editor->viewport(), Qt::LeftButton); editor->setText(QStringLiteral("1+2+").repeated(300) + QStringLiteral("3")); const QString expression = editor->document()->toRawText(); QTest::keyClick(editor, Qt::Key_Return); QTRY_VERIFY(editor->text().isEmpty()); QCoreApplication::processEvents(); const int singleLineHeight = editor->height(); editor->setAutoCalcEnabled(true); QTest::keyClick(editor, Qt::Key_Up); QCOMPARE(editor->document()->toRawText(), expression); auto* popup = window.findChild(QStringLiteral("EditorStatePopup")); QVERIFY(popup); QTRY_VERIFY(popup->isVisible()); QVERIFY(popup->text().contains(QStringLiteral("Current result:"))); QCoreApplication::processEvents(); QVERIFY(editor->height() > singleLineHeight); QVERIFY(editor->document()->firstBlock().layout()->lineCount() > 5); const int inset = classic ? UiConfig::ClassicTextInset : UiConfig::ResultTooltipStartMargin; QCOMPARE(popup->mapToGlobal(QPoint(0, popup->height())), editor->mapToGlobal(QPoint(inset, 0))); QTest::keyClick(editor, Qt::Key_Down); QTRY_VERIFY(editor->text().isEmpty()); QTRY_COMPARE(editor->height(), singleLineHeight); QVERIFY(!popup->isVisible()); } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testeditorappearanceui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testeditorui.cpp000066400000000000000000010666701526573132500245360ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/editor.h" #include "gui/editorutils.h" #include "gui/oklchutils.h" #include "gui/syntaxhighlighter.h" #include "gui/uiconfig.h" #include "core/colorscheme.h" #include "core/constants.h" #include "core/evaluator.h" #include "core/session.h" #include "core/settings.h" #include "core/unicodechars.h" #include "core/mathdsl.h" #include "core/numberformatter.h" #include "core/units.h" #include "core/userfunction.h" #include "core/userunit.h" #include "uitestfixture.h" #include "editorgeometrytesthelpers.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { QJsonObject themeJson(QJsonObject colors) { colors.insert(QStringLiteral("$schema"), QString::fromLatin1(ColorScheme::SchemaDraft)); colors.insert(QStringLiteral("$id"), QString::fromLatin1(ColorScheme::SchemaId)); return colors; } QString themeJsonString(QJsonObject colors) { return QString::fromUtf8(QJsonDocument(themeJson(colors)).toJson(QJsonDocument::Compact)); } } class TestEditorUi : public QObject { Q_OBJECT private slots: void init() { UiTestFixture::resetSettings(); } void raw_input_preserves_text_data(); void raw_input_preserves_text(); void history_recall_respects_input_adjustments_data(); void history_recall_respects_input_adjustments(); void raw_input_keeps_character_navigation_and_deletion(); void raw_input_preserves_calculator_commands(); void raw_input_switch_preserves_document_and_restores_adjustments(); void raw_input_preserves_visible_digit_grouping(); void raw_input_preserves_tab_completion_data(); void raw_input_preserves_tab_completion(); void automatic_input_adjustments_survive_settings_reload(); void preserves_comment_text_during_input_data(); void preserves_comment_text_during_input(); void normalizes_only_expression_text_when_replacing_comment_selection(); void blocks_consecutive_plus(); void respects_keyboard_layout_for_equals_and_plus_data(); void respects_keyboard_layout_for_equals_and_plus(); void wraps_left_shift_operator_and_blocks_immediate_duplicate_less_than(); void wraps_right_shift_operator_and_blocks_immediate_duplicate_greater_than(); void blocks_consecutive_caret(); void blocks_plus_after_caret(); void blocks_leading_operators_when_auto_ans_is_off_except_configured_exceptions(); void keeps_disallowed_start_chars_blocked_when_auto_ans_is_on(); void allows_special_function_symbols_as_leading_chars(); void allows_list_start_after_operators(); void highlights_list_braces_as_parentheses(); void input_digit_grouping_formats_only_integer_digits_data(); void input_digit_grouping_formats_only_integer_digits(); void input_digit_grouping_preserves_typing_selection_and_undo(); void input_digit_grouping_survives_settings_reload(); void input_digit_grouping_follows_number_format_data(); void input_digit_grouping_follows_number_format(); void input_digit_grouping_paints_separator_glyphs_data(); void input_digit_grouping_paints_separator_glyphs(); void auto_ans_rewrite_helper_handles_tilde_and_factorial(); void blocks_operator_right_after_open_square_bracket(); void inserts_value_unit_space_brackets_after_number_or_symbol(); void inserts_closing_square_bracket_only_with_spaces_to_right_data(); void inserts_closing_square_bracket_only_with_spaces_to_right(); void ignores_space_on_empty_or_all_space_editor(); void auto_inserts_space_before_question_comment_only_with_non_space_content(); void inserts_middle_dot_on_space_after_identifier_or_closed_group(); void inserts_parenthesis_pair_and_places_cursor_inside(); void does_not_insert_implicit_mul_sequence_before_open_paren_after_number_or_symbol(); void does_not_insert_implicit_mul_for_zero_radix_prefix_letters(); void allows_unit_conversion_tail_after_spaced_subtraction_operator(); void converts_double_minus_sequence_to_unit_conversion_with_placeholder(); void converts_double_minus_sequence_to_unit_conversion_after_masculine_ordinal_degree(); void inserts_unit_conversion_with_placeholder_when_typing_arrow_symbol(); void treats_spaced_unit_conversion_as_atomic_navigation_and_edit_token(); void treats_spaced_shift_operators_as_atomic_navigation_and_edit_tokens(); void backspace_removes_typed_operator_after_unit(); void editing_keys_bypass_typing_restrictions_data(); void editing_keys_bypass_typing_restrictions(); void undo_redo_shortcuts_preserve_expression_data(); void undo_redo_shortcuts_preserve_expression(); void typing_undoes_one_key_at_a_time_data(); void typing_undoes_one_key_at_a_time(); void non_printable_key_payloads_do_not_replace_selection(); void clipboard_shortcuts_do_not_insert_key_payloads_data(); void clipboard_shortcuts_do_not_insert_key_payloads(); void copy_shortcut_preserves_editor_state_data(); void copy_shortcut_preserves_editor_state(); void highlight_refresh_preserves_text_and_selection_without_edit_signals(); void primary_theme_changes_preserve_document_highlighting_data(); void primary_theme_changes_preserve_document_highlighting(); void highlight_refresh_updates_document_once_data(); void highlight_refresh_updates_document_once(); void editor_text_line_is_vertically_centered_data(); void editor_text_line_is_vertically_centered(); void unchanged_primary_theme_avoids_editor_style_refresh_data(); void unchanged_primary_theme_avoids_editor_style_refresh(); void treats_spaced_question_comment_as_atomic_navigation_and_edit_token(); void treats_spaced_equal_as_atomic_navigation_and_edit_token(); void treats_leading_question_comment_as_atomic_navigation_and_edit_token(); void ignores_space_right_after_spaced_unit_conversion_operator(); void unit_bracket_context_accepts_div_mul_and_rejects_addition(); void unit_bracket_context_blocks_space_and_ops_when_only_spaces(); void unit_bracket_context_accepts_quote_marks_as_arc_units(); void unit_bracket_context_accepts_quote_marks_via_ime_commit(); void unit_bracket_context_allows_letter_after_middle_dot(); void unit_bracket_context_disallows_variables_and_constants(); void evaluator_accepts_compact_arc_symbol_units(); void unit_bracket_context_allows_digits_and_minus_only_in_exponent_positions(); void converts_caret_exponents_to_superscripts_globally(); void keeps_scientific_notation_exponent_minus_unwrapped(); void blocks_shift_operator_tail_after_non_plus_operator(); void rewrites_superscript_exponent_for_radix_and_inserts_mul_space_globally(); void typing_asterisk_after_superscript_power_keeps_explicit_multiplication(); void auto_inserts_zero_before_dot_in_configured_contexts(); void allows_unrestricted_typing_inside_question_comment_context(); void allows_currency_symbols_after_operators(); void blocks_dead_circumflex_key_after_existing_caret(); void blocks_dead_circumflex_key_after_multiplication_operator(); void blocks_regular_caret_after_multiplication_operator(); void blocks_ime_preedit_caret_echo_after_existing_caret(); void blocks_ime_commit_caret_after_existing_caret(); void blocks_ime_commit_caret_after_multiplication_operator(); void finds_completion_keyword_after_superscript_power(); void completes_replacing_trailing_identifier_after_superscript_power(); void completes_identifier_immediately_after_digit(); void completes_pi_identifier_as_pi_symbol(); void accepts_degree_alias_in_unit_brackets_and_normalizes_to_degree_sign(); void offers_unit_completion_for_degree_symbol_in_unit_context(); void matches_micro_units_when_typing_u_in_unit_context(); void unit_context_completion_excludes_user_variables(); void unit_context_completion_excludes_built_in_functions(); void unit_context_completion_excludes_user_functions(); void unit_context_completion_excludes_built_in_variables(); void unit_context_completion_includes_angle_units_and_long_forms(); void unit_context_completion_includes_small_positive_si_prefixed_symbols(); void unit_context_completion_excludes_prefixed_square_and_cubic_metre(); void completes_binary_prefixed_information_unit_to_short_form_in_unit_context(); void completes_day_unit_to_short_form_in_unit_context(); void completes_hour_unit_to_short_form_in_unit_context(); void completes_affine_temperature_units_in_unit_context(); void completes_arc_units_in_unit_context(); void tooltip_does_not_duplicate_degree_symbol_for_explicit_angle_conversion(); void tooltip_does_not_append_angle_mode_symbol_after_explicit_arcsecond_unit(); void tooltip_formats_arcminute_and_arcsecond_results_without_expression(); void tooltip_rewrites_composite_canonical_angle_symbols_to_aliases(); void tooltip_shows_radian_suffix_for_negative_sexagesimal_literal(); void tooltip_trig_output_does_not_append_angle_mode_suffix(); void tooltip_shows_only_result_for_non_trig_sexagesimal_expression(); void tooltip_shows_only_result_for_repeated_trig_with_degree_sign(); void tooltip_shows_only_result_for_mixed_revolution_aliases(); void tooltip_shows_only_result_for_literal_number_products(); void tooltip_shows_only_result_data(); void tooltip_shows_only_result(); void tooltip_keeps_quantsp_before_degree_celsius(); void tooltip_handles_affine_temperature_units_without_arrow_and_with_conversion(); void tooltip_shows_selection_result_when_selecting_with_shift_arrows(); void tooltip_shows_selection_result_when_selecting_all_with_keyboard_shortcut(); void tooltip_shows_selection_result_when_selecting_with_mouse(); void tooltip_does_not_refresh_current_result_on_caret_arrow_move(); void tooltip_does_not_refresh_current_result_on_mouse_caret_reposition(); void tooltip_refreshes_current_result_on_char_deletion(); void enter_evaluates_when_completion_popup_has_no_explicit_interaction(); void completion_popup_enter_respects_accept_with_enter_data(); void completion_popup_enter_respects_accept_with_enter(); void enter_accepts_completion_for_names_and_units_data(); void enter_accepts_completion_for_names_and_units(); void enter_evaluates_without_completion_when_accept_with_enter_is_enabled(); void completion_popup_arrow_keys_change_selection(); void completion_popup_tab_accepts_selected_item(); void completion_popup_closes_when_clicking_elsewhere(); void completion_popup_clicking_row_accepts_item(); void completion_popup_mouse_selection_keeps_focus_on_owning_editor(); void completion_popup_scrollbar_click_keeps_popup_open(); void completion_popup_mouse_wheel_scrolls_popup(); void completion_popup_escape_closes_and_stays_closed(); void completion_popup_escape_keeps_focus_on_owning_editor(); void completion_popup_reopens_after_typing_following_escape(); void completion_popup_reopens_after_retyping_deleted_letter_data(); void completion_popup_reopens_after_retyping_deleted_letter(); void completion_popup_shows_for_two_character_prefixes(); void completion_popup_uses_positionable_nonactivating_surface(); void completion_popup_keeps_editor_widgets_non_native_data(); void completion_popup_keeps_editor_widgets_non_native(); void completion_popup_follows_editor_geometry_data(); void completion_popup_follows_editor_geometry(); void completion_popup_geometry_avoids_editor_overlap_data(); void completion_popup_geometry_avoids_editor_overlap(); void completion_popup_shortens_tall_lists_without_covering_editor(); void completion_popups_configure_editor_anchor_data(); void completion_popups_configure_editor_anchor(); void completion_popup_compositor_geometry_data(); void completion_popup_compositor_geometry(); void constant_search_filters_without_editing_expression(); void constant_search_inserts_selected_result_data(); void constant_search_inserts_selected_result(); void constant_search_closes_without_stealing_outside_focus(); void constant_search_layout_follows_popup_resize(); void constant_search_inline_units_preserve_full_insertion_data(); void constant_search_inline_units_preserve_full_insertion(); void constant_search_renders_units_in_secondary_shade_data(); void constant_search_renders_units_in_secondary_shade(); void constant_completion_popup_follows_wrapped_editor_cursor(); void completion_popup_uses_configured_surface_colors(); void constant_completion_popup_uses_configured_surface_colors(); void inactive_editor_does_not_show_completion_popup(); void enter_evaluates_when_cursor_is_immediately_after_operator(); void completion_popup_uses_expected_icons_for_all_symbol_types(); void wrap_selection_method_wraps_selected_text(); void wrap_selection_method_wraps_whole_expression_without_selection(); void matching_parentheses_use_parens_and_generated_foreground_colors(); void keeps_wrapped_cursor_line_visible_at_height_cap(); void rewrites_operators_in_scrolled_expression_data(); void rewrites_operators_in_scrolled_expression(); void classic_editor_keeps_wrapped_input_visible_and_preserves_undo(); void classic_completion_popups_follow_text_inset_data(); void classic_completion_popups_follow_text_inset(); void editor_height_adds_only_one_line_height_per_visible_line(); void editor_keeps_unit_descenders_inside_viewport(); void adding_second_wrapped_character_keeps_first_line_visible(); void editor_fill_color_is_15_percent_lighter_for_dark_background_role(); void editor_fill_color_is_15_percent_darker_for_light_background_role(); void themed_cursor_has_only_two_states_at_display_scale_data(); void themed_cursor_has_only_two_states_at_display_scale(); void non_blinking_cursor_stays_visible_data(); void non_blinking_cursor_stays_visible(); void cursor_blinking_survives_settings_reload(); void cursor_free_painting_preserves_text_and_selections_data(); void cursor_free_painting_preserves_text_and_selections(); }; static QTreeWidget* s_completionPopupTree() { const auto topLevelWidgets = QApplication::topLevelWidgets(); for (QWidget* widget : topLevelWidgets) { if (!widget || !widget->isVisible()) continue; if (widget->objectName() != QStringLiteral("editorCompletionPopup")) continue; if (QTreeWidget* tree = qobject_cast(widget)) return tree; } QWidget* popup = QApplication::activePopupWidget(); if (popup) { if (QTreeWidget* tree = qobject_cast(popup)) return tree; } for (QWidget* widget : topLevelWidgets) { if (!widget || !widget->isVisible()) continue; if (!(widget->windowFlags() & (Qt::Popup | Qt::Tool)) && widget->objectName() != QStringLiteral("editorCompletionPopup")) continue; if (QTreeWidget* tree = qobject_cast(widget)) return tree; } return nullptr; } static QString s_popupSymbolForIdentifier(QTreeWidget* popup, const QString& identifier) { if (!popup) return QString(); for (int i = 0; i < popup->topLevelItemCount(); ++i) { QTreeWidgetItem* item = popup->topLevelItem(i); if (item && item->text(1) == identifier) return item->text(0); } return QString(); } static QTreeWidget* s_completionPopupTreeContaining(const QString& identifierPrefix) { const auto topLevelWidgets = QApplication::topLevelWidgets(); for (QWidget* widget : topLevelWidgets) { if (!widget || !widget->isVisible()) continue; if (widget->objectName() != QStringLiteral("editorCompletionPopup")) continue; QTreeWidget* tree = qobject_cast(widget); if (!tree) continue; for (int i = 0; i < tree->topLevelItemCount(); ++i) { QTreeWidgetItem* item = tree->topLevelItem(i); if (item && item->text(1).startsWith(identifierPrefix)) return tree; } } return nullptr; } static QList s_constantCompletionPopupTrees() { QList trees; QWidget* popup = QApplication::activePopupWidget(); if (!popup || popup->objectName() != QStringLiteral("constantCompletionPopup")) return trees; trees = popup->findChildren(); std::sort(trees.begin(), trees.end(), [](QTreeWidget* left, QTreeWidget* right) { return left->objectName() < right->objectName(); }); return trees; } static bool s_editorOrViewportHasFocus(Editor* editor) { QWidget* focusWidget = QApplication::focusWidget(); return editor->hasFocus() || editor->viewport()->hasFocus() || focusWidget == editor || focusWidget == editor->viewport(); } void TestEditorUi::blocks_consecutive_plus() { // State: "1" // Action: type '+' twice. // Expected: second '+' is ignored. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Plus, Qt::NoModifier); const QString afterFirstPlus = editor.text(); QVERIFY(afterFirstPlus.contains(MathDsl::AddOp)); QTest::keyClick(&editor, Qt::Key_Plus, Qt::NoModifier); QCOMPARE(editor.text(), afterFirstPlus); } void TestEditorUi::respects_keyboard_layout_for_equals_and_plus_data() { QTest::addColumn("key"); QTest::addColumn("modifiers"); QTest::addColumn("payload"); QTest::addColumn("initial"); QTest::addColumn("expected"); QTest::newRow("portuguese-shift-equals") << int(Qt::Key_Equal) << Qt::KeyboardModifiers(Qt::ShiftModifier) << QStringLiteral("=") << QStringLiteral("foo") << QStringLiteral("foo = "); QTest::newRow("shift-zero-equals-payload") << int(Qt::Key_0) << Qt::KeyboardModifiers(Qt::ShiftModifier) << QStringLiteral("=") << QStringLiteral("foo") << QStringLiteral("foo = "); QTest::newRow("unshifted-equals") << int(Qt::Key_Equal) << Qt::KeyboardModifiers(Qt::NoModifier) << QStringLiteral("=") << QStringLiteral("foo") << QStringLiteral("foo = "); QTest::newRow("us-shift-equals-plus-payload") << int(Qt::Key_Equal) << Qt::KeyboardModifiers(Qt::ShiftModifier) << QStringLiteral("+") << QStringLiteral("1") << QStringLiteral("1 + "); QTest::newRow("plus-key") << int(Qt::Key_Plus) << Qt::KeyboardModifiers(Qt::NoModifier) << QStringLiteral("+") << QStringLiteral("1") << QStringLiteral("1 + "); QTest::newRow("shift-equals-without-payload") << int(Qt::Key_Equal) << Qt::KeyboardModifiers(Qt::ShiftModifier) << QString() << QStringLiteral("foo") << QStringLiteral("foo = "); QTest::newRow("shift-equals-blocks-duplicate") << int(Qt::Key_Equal) << Qt::KeyboardModifiers(Qt::ShiftModifier) << QStringLiteral("=") << QStringLiteral("foo = ") << QStringLiteral("foo = "); QTest::newRow("shift-plus-blocks-duplicate") << int(Qt::Key_Equal) << Qt::KeyboardModifiers(Qt::ShiftModifier) << QStringLiteral("+") << QStringLiteral("1 + ") << QStringLiteral("1 + "); } void TestEditorUi::respects_keyboard_layout_for_equals_and_plus() { QFETCH(int, key); QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(QString, payload); QFETCH(QString, initial); QFETCH(QString, expected); Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(initial); editor.setCursorPosition(editor.text().size()); QKeyEvent event(QEvent::KeyPress, key, modifiers, payload); QApplication::sendEvent(&editor, &event); QCOMPARE(editor.document()->toRawText(), expected); } void TestEditorUi::wraps_left_shift_operator_and_blocks_immediate_duplicate_less_than() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("foo")); editor.setCursorPosition(editor.text().size()); QKeyEvent lessByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("<")); QApplication::sendEvent(&editor, &lessByText); const QString afterFirstLess = editor.text(); QCOMPARE(afterFirstLess, QStringLiteral("foo") + MathDsl::buildWrappedToken(MathDsl::ShiftLeftOp)); QApplication::sendEvent(&editor, &lessByText); QCOMPARE(editor.text(), afterFirstLess); } void TestEditorUi::wraps_right_shift_operator_and_blocks_immediate_duplicate_greater_than() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("foo")); editor.setCursorPosition(editor.text().size()); QKeyEvent greaterByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral(">")); QApplication::sendEvent(&editor, &greaterByText); const QString afterFirstGreater = editor.text(); QCOMPARE(afterFirstGreater, QStringLiteral("foo") + MathDsl::buildWrappedToken(MathDsl::ShiftRightOp)); QApplication::sendEvent(&editor, &greaterByText); QCOMPARE(editor.text(), afterFirstGreater); } void TestEditorUi::blocks_consecutive_caret() { // State: "2" // Action: type '^' twice. // Expected: second '^' is ignored. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("^")); const QString afterFirstCaret = editor.text(); QVERIFY(afterFirstCaret.contains(QLatin1Char('^'))); QTest::keyClicks(&editor, QStringLiteral("^")); QCOMPARE(editor.text(), afterFirstCaret); } void TestEditorUi::blocks_plus_after_caret() { // State: "2^" // Action: type '+'. // Expected: '+' is ignored. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2^")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Plus, Qt::NoModifier); QCOMPARE(editor.text(), QStringLiteral("2^")); } void TestEditorUi::blocks_leading_operators_when_auto_ans_is_off_except_configured_exceptions() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const bool autoAnsBackup = settings->autoAns; settings->autoAns = false; const auto resetEmpty = [&editor]() { editor.setText(QString()); editor.setCursorPosition(0); }; const auto sendTextKey = [&editor](const QString& s) { QKeyEvent byText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, s); QApplication::sendEvent(&editor, &byText); }; const auto sendImeCommit = [&editor](const QString& s) { QList attrs; QInputMethodEvent imeEvent(QString(), attrs); imeEvent.setCommitString(s); QApplication::sendEvent(&editor, &imeEvent); }; resetEmpty(); QTest::keyClick(&editor, Qt::Key_Plus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QString(MathDsl::AddOp)); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QString(MathDsl::MulCrossOp)); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QString(MathDsl::MulDotOp)); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); QTest::keyClick(&editor, Qt::Key_Slash, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QString(MathDsl::DivOp)); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QStringLiteral("!")); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QStringLiteral("^")); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QStringLiteral(")")); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QStringLiteral(":")); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QVERIFY(!editor.document()->toRawText().isEmpty()); const QString afterFirstLeadingMinus = editor.document()->toRawText(); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), afterFirstLeadingMinus); editor.setCursorPosition(0); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), afterFirstLeadingMinus); resetEmpty(); sendTextKey(QString(MathDsl::SubOp)); QVERIFY(!editor.document()->toRawText().isEmpty()); const QString afterFirstLeadingMinusByImeBase = editor.document()->toRawText(); sendImeCommit(QString(MathDsl::SubOp)); QCOMPARE(editor.document()->toRawText(), afterFirstLeadingMinusByImeBase); resetEmpty(); QTest::keyClicks(&editor, QStringLiteral("~")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("~")); resetEmpty(); sendTextKey(QStringLiteral("(")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("()")); QCOMPARE(editor.textCursor().position(), 1); resetEmpty(); sendTextKey(QStringLiteral("'")); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QStringLiteral("\"")); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendTextKey(QStringLiteral("#")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("#")); resetEmpty(); sendTextKey(QStringLiteral("?")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("? ")); resetEmpty(); sendTextKey(QString::fromUtf8("€")); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("€")); resetEmpty(); sendTextKey(QString::fromUtf8("Ж")); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("Ж")); settings->autoAns = autoAnsBackup; } void TestEditorUi::keeps_disallowed_start_chars_blocked_when_auto_ans_is_on() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const bool autoAnsBackup = settings->autoAns; settings->autoAns = true; const auto resetEmpty = [&editor]() { editor.setText(QString()); editor.setCursorPosition(0); }; const auto sendImeCommit = [&editor](const QString& s) { QList attrs; QInputMethodEvent imeEvent(QString(), attrs); imeEvent.setCommitString(s); QApplication::sendEvent(&editor, &imeEvent); }; // Allowed starters in auto-ans mode. resetEmpty(); sendImeCommit(QStringLiteral("!")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("!")); resetEmpty(); sendImeCommit(QStringLiteral("~")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("~")); // Disallowed symbols still stay blocked. resetEmpty(); sendImeCommit(QString::fromUtf8("§")); QCOMPARE(editor.document()->toRawText(), QString()); resetEmpty(); sendImeCommit(QStringLiteral("]")); QCOMPARE(editor.document()->toRawText(), QString()); settings->autoAns = autoAnsBackup; } void TestEditorUi::allows_special_function_symbols_as_leading_chars() { const bool autoAnsOff = false; const bool autoAnsOn = true; const QList allowedStarters = { UnicodeChars::Summation, UnicodeChars::SquareRoot, UnicodeChars::CubeRoot, UnicodeChars::LowLine, UnicodeChars::DollarSign, MathDsl::ListStart, QChar(0x0436), // Ж QChar(0x03C0) // Ï€ }; for (const QChar ch : allowedStarters) { QVERIFY(EditorUtils::isAllowedLeadingCharAtExpressionStart(ch, autoAnsOff)); QVERIFY(EditorUtils::isAllowedLeadingCharAtExpressionStart(ch, autoAnsOn)); } QVERIFY(!EditorUtils::isAllowedLeadingCharAtExpressionStart(QChar(0x00A7), autoAnsOff)); // § QVERIFY(!EditorUtils::isAllowedLeadingCharAtExpressionStart(QChar(0x00A7), autoAnsOn)); // § } void TestEditorUi::allows_list_start_after_operators() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString listStart(MathDsl::ListStart); const QVector> cases = { {QStringLiteral("1+"), QStringLiteral("1+")}, {QStringLiteral("1-"), QStringLiteral("1") + QString(MathDsl::SubOp)}, {QStringLiteral("1/"), QStringLiteral("1/")}, {QStringLiteral("1*"), QStringLiteral("1") + QString(MathDsl::MulCrossOp)}, {QStringLiteral("1^"), QStringLiteral("1^")} }; for (const auto& testCase : cases) { editor.setText(testCase.first); editor.setCursorPosition(editor.text().size()); QKeyEvent openListByText( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, listStart); QApplication::sendEvent(&editor, &openListByText); QCOMPARE(editor.document()->toRawText(), testCase.second + listStart); } } void TestEditorUi::highlights_list_braces_as_parentheses() { Settings* settings = Settings::instance(); const bool oldSyntaxHighlighting = settings->syntaxHighlighting; settings->syntaxHighlighting = true; QPlainTextEdit editor; SyntaxHighlighter highlighter(&editor); QJsonObject colors; colors.insert(QStringLiteral("number"), QStringLiteral("#111111")); colors.insert(QStringLiteral("parens"), QStringLiteral("#123456")); colors.insert(QStringLiteral("list"), QStringLiteral("#123456")); colors.insert(QStringLiteral("operator"), QStringLiteral("#222222")); colors.insert(QStringLiteral("separator"), QStringLiteral("#333333")); highlighter.setColorScheme(ColorScheme(QJsonDocument(themeJson(colors)))); editor.setPlainText(QStringLiteral("{1; 2}")); highlighter.rehighlight(); const QList formats = editor.document()->firstBlock().layout()->formats(); auto colorAt = [&formats](int pos) { for (const QTextLayout::FormatRange& range : formats) { if (pos >= range.start && pos < range.start + range.length) return range.format.foreground().color(); } return QColor(); }; const QColor parensColor(QStringLiteral("#123456")); QCOMPARE(colorAt(0), parensColor); QCOMPARE(colorAt(5), parensColor); settings->syntaxHighlighting = oldSyntaxHighlighting; } void TestEditorUi::auto_ans_rewrite_helper_handles_tilde_and_factorial() { const auto modeTilde = EditorUtils::autoAnsRewriteModeForLeadingOperator(QStringLiteral("~")); QCOMPARE(modeTilde, EditorUtils::AutoAnsAppendAns); QCOMPARE(EditorUtils::applyAutoAnsRewrite(QStringLiteral("~"), modeTilde), QStringLiteral("~ans")); const auto modeFactorial = EditorUtils::autoAnsRewriteModeForLeadingOperator(QStringLiteral("!")); QCOMPARE(modeFactorial, EditorUtils::AutoAnsPrependAns); QCOMPARE(EditorUtils::applyAutoAnsRewrite(QStringLiteral("!"), modeFactorial), QStringLiteral("ans!")); } void TestEditorUi::blocks_operator_right_after_open_square_bracket() { // State: "[" // Action: type '-'. // Expected: operator is ignored at start of unit-bracket context. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("[")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QCOMPARE(editor.text(), QStringLiteral("[")); } void TestEditorUi::inserts_value_unit_space_brackets_after_number_or_symbol() { // State: "2" and "Ï€" // Action: type '[' via text-based key event. // Expected: append "[]". Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2")); editor.setCursorPosition(editor.text().size()); QKeyEvent bracketByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("[")); QApplication::sendEvent(&editor, &bracketByText); const QString actualAfterNumber = editor.document()->toRawText(); QCOMPARE(actualAfterNumber, QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[]")); editor.setText(QString::fromUtf8("Ï€")); editor.setCursorPosition(editor.text().size()); QApplication::sendEvent(&editor, &bracketByText); const QString actualAfterSymbol = editor.document()->toRawText(); QCOMPARE(actualAfterSymbol, QString::fromUtf8("Ï€") + QString(MathDsl::QuantSp) + QStringLiteral("[]")); editor.setText(QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[m]") + QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp) + QStringLiteral("(pi)")); editor.setCursorPosition(editor.text().size()); QApplication::sendEvent(&editor, &bracketByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[m]") + QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp) + QStringLiteral("(pi)") + QString(MathDsl::QuantSp) + QStringLiteral("[]")); editor.setText(QStringLiteral("2 [K] in ")); editor.setCursorPosition(editor.text().size()); QApplication::sendEvent(&editor, &bracketByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2 [K] in") + QString(MathDsl::QuantSp) + QStringLiteral("[]")); } void TestEditorUi::inserts_closing_square_bracket_only_with_spaces_to_right_data() { QTest::addColumn("initialText"); QTest::addColumn("cursorPosition"); QTest::addColumn("expectedText"); QTest::addColumn("expectedCursorPosition"); const QString unitSpace = QString(MathDsl::QuantSp); QTest::newRow("empty") << QString() << 0 << QStringLiteral("[]") << 1; QTest::newRow("end") << QStringLiteral("2") << 1 << QStringLiteral("2") + unitSpace + QStringLiteral("[]") << 3; QTest::newRow("before-trailing-spaces") << QStringLiteral("2 ") << 1 << QStringLiteral("2") + unitSpace + QStringLiteral("[] ") << 3; QTest::newRow("after-trailing-spaces") << QStringLiteral("2 ") << 4 << QStringLiteral("2") + unitSpace + QStringLiteral("[]") << 3; QTest::newRow("before-unicode-space") << QStringLiteral("2") + unitSpace << 1 << QStringLiteral("2") + unitSpace + QStringLiteral("[]") + unitSpace << 3; QTest::newRow("before-operator") << QStringLiteral("2+3") << 1 << QStringLiteral("2") + unitSpace + QStringLiteral("[+3") << 3; QTest::newRow("before-unit-and-existing-close") << QStringLiteral("2m]") << 1 << QStringLiteral("2") + unitSpace + QStringLiteral("[m]") << 3; QTest::newRow("before-existing-close") << QStringLiteral("2]") << 1 << QStringLiteral("2") + unitSpace + QStringLiteral("[]") << 3; QTest::newRow("inside-spaces-before-content") << QStringLiteral("2 +3") << 2 << QStringLiteral("2") + unitSpace + QStringLiteral("[ +3") << 3; QTest::newRow("start-before-content") << QStringLiteral("2") << 0 << QStringLiteral("[2") << 1; QTest::newRow("after-closed-group") << QStringLiteral("(2)+3") << 3 << QStringLiteral("(2)") + unitSpace + QStringLiteral("[+3") << 5; } void TestEditorUi::inserts_closing_square_bracket_only_with_spaces_to_right() { QFETCH(QString, initialText); QFETCH(int, cursorPosition); QFETCH(QString, expectedText); QFETCH(int, expectedCursorPosition); Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); for (const int key : {Qt::Key_unknown, Qt::Key_BracketLeft}) { editor.setText(initialText); editor.setCursorPosition(cursorPosition); QKeyEvent openBracket(QEvent::KeyPress, key, Qt::NoModifier, key == Qt::Key_unknown ? QStringLiteral("[") : QString()); QApplication::sendEvent(&editor, &openBracket); QCOMPARE(editor.document()->toRawText(), expectedText); QCOMPARE(editor.textCursor().position(), expectedCursorPosition); } } void TestEditorUi::ignores_space_on_empty_or_all_space_editor() { // State: empty editor and whitespace-only editor. // Action: type SPACE. // Expected: first leading space inserts; repeated space after space is ignored. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QString()); editor.setCursorPosition(0); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.text(), QStringLiteral(" ")); const QString allSpaces = QStringLiteral(" ") + QString(MathDsl::QuantSp) + QStringLiteral(" "); editor.setText(allSpaces); editor.setCursorPosition(editor.text().size()); const QString beforeSpaceOnAllSpaces = editor.document()->toRawText(); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), beforeSpaceOnAllSpaces); } void TestEditorUi::auto_inserts_space_before_question_comment_only_with_non_space_content() { // State: content with non-space, empty, and whitespace-only. // Action: type '?'. // Expected: " ? " only when non-space already exists. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2+2")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("?")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2+2 ? ")); editor.setText(QString()); editor.setCursorPosition(0); QTest::keyClicks(&editor, QStringLiteral("?")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("? ")); editor.setText(QStringLiteral(" ")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("?")); QCOMPARE(editor.document()->toRawText(), QStringLiteral(" ? ")); editor.setText(QStringLiteral("2+2")); editor.setCursorPosition(editor.text().size()); QKeyEvent questionByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("?")); QApplication::sendEvent(&editor, &questionByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2+2 ? ")); } void TestEditorUi::inserts_middle_dot_on_space_after_identifier_or_closed_group() { Settings* settings = Settings::instance(); const bool autoCompletionBackup = settings->autoCompletion; const bool builtInFnBackup = settings->autoCompletionBuiltInFunctions; const bool builtInVarBackup = settings->autoCompletionBuiltInVariables; const bool userFnBackup = settings->autoCompletionUserFunctions; const bool userVarBackup = settings->autoCompletionUserVariables; settings->autoCompletion = true; settings->autoCompletionBuiltInFunctions = false; settings->autoCompletionBuiltInVariables = true; settings->autoCompletionUserFunctions = false; settings->autoCompletionUserVariables = false; struct AutoCompletionRestoreGuard { Settings* settings; bool autoCompletion; bool builtInFunctions; bool builtInVariables; bool userFunctions; bool userVariables; ~AutoCompletionRestoreGuard() { settings->autoCompletion = autoCompletion; settings->autoCompletionBuiltInFunctions = builtInFunctions; settings->autoCompletionBuiltInVariables = builtInVariables; settings->autoCompletionUserFunctions = userFunctions; settings->autoCompletionUserVariables = userVariables; } } autoCompletionRestoreGuard { settings, autoCompletionBackup, builtInFnBackup, builtInVarBackup, userFnBackup, userVarBackup}; Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("p")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); const QString completedIdentifier = editor.document()->toRawText(); const QString piSymbol = QString(UnicodeChars::Pi); QVERIFY(completedIdentifier == QStringLiteral("p ") || completedIdentifier == QStringLiteral("pi ") || completedIdentifier == piSymbol + QStringLiteral(" ")); editor.setText(QStringLiteral("cos(3)")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("cos(3) ")); } void TestEditorUi::inserts_parenthesis_pair_and_places_cursor_inside() { // State: multiple states (empty, numbers, before operator, function name). // Action: type '(' (text path and keycode path). // Expected: auto-insert "()" only when right side is empty/spaces-only. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString groupStart = QString(MathDsl::GroupStart); const QString groupEnd = QString(MathDsl::GroupEnd); const QString groupPair = groupStart + groupEnd; const auto verifyParenInsertionAt = [&editor](const QString& initialText, int cursorPos) { editor.setText(initialText); editor.setCursorPosition(cursorPos); QKeyEvent openParenByText( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(MathDsl::GroupStart)); QApplication::sendEvent(&editor, &openParenByText); const QString after = editor.document()->toRawText(); const int cursor = editor.textCursor().position(); QVERIFY(cursor > 0); QVERIFY(cursor < after.size()); QCOMPARE(after.at(cursor - 1), QLatin1Char('(')); QCOMPARE(after.at(cursor), QLatin1Char(')')); }; verifyParenInsertionAt(QString(), 0); verifyParenInsertionAt(QStringLiteral("2"), 1); verifyParenInsertionAt(QStringLiteral("1 "), 1); // only spaces to the right editor.setText(QStringLiteral("1+2")); editor.setCursorPosition(1); QKeyEvent openParenByText( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(MathDsl::GroupStart)); QApplication::sendEvent(&editor, &openParenByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1(+2")); QCOMPARE(editor.textCursor().position(), 2); editor.setText(QStringLiteral("1)")); editor.setCursorPosition(1); QApplication::sendEvent(&editor, &openParenByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1()")); QCOMPARE(editor.textCursor().position(), 2); editor.setText(QStringLiteral("cos")); editor.setCursorPosition(editor.text().size()); QKeyEvent openParenByTextForFunction( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(MathDsl::GroupStart)); QApplication::sendEvent(&editor, &openParenByTextForFunction); QCOMPARE(editor.document()->toRawText(), QStringLiteral("cos") + groupPair); QCOMPARE(editor.textCursor().position(), 4); editor.setText(QString::fromUtf8("cos³")); editor.setCursorPosition(editor.text().size()); QApplication::sendEvent(&editor, &openParenByTextForFunction); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("cos³") + groupPair); QCOMPARE(editor.textCursor().position(), 5); editor.setText(QString::fromUtf8("2 piâ�»Â²Â³ · cos")); editor.setCursorPosition(editor.text().size()); QApplication::sendEvent(&editor, &openParenByTextForFunction); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("2 piâ�»Â²Â³ · cos") + groupPair); QCOMPARE(editor.textCursor().position(), QString::fromUtf8("2 piâ�»Â²Â³ · cos(").size()); Session session; Evaluator* evaluator = session.evaluator(); editor.setSession(&session); evaluator->unsetAllUserFunctions(); evaluator->setUserFunction(UserFunction( QStringLiteral("user_fun"), QStringList() << QStringLiteral("x"), QStringLiteral("x"))); editor.setText(QStringLiteral("user_fun")); editor.setCursorPosition(editor.text().size()); QApplication::sendEvent(&editor, &openParenByTextForFunction); QCOMPARE(editor.document()->toRawText(), QStringLiteral("user_fun") + groupPair); QCOMPARE(editor.textCursor().position(), QStringLiteral("user_fun(").size()); evaluator->unsetAllUserFunctions(); editor.setText(QStringLiteral("3")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_ParenLeft, Qt::NoModifier); const QString afterKeyCodePath = editor.document()->toRawText(); const int cursorAfterKeyCodePath = editor.textCursor().position(); QVERIFY(cursorAfterKeyCodePath > 0); QVERIFY(cursorAfterKeyCodePath < afterKeyCodePath.size()); QCOMPARE(afterKeyCodePath.at(cursorAfterKeyCodePath - 1), QLatin1Char('(')); QCOMPARE(afterKeyCodePath.at(cursorAfterKeyCodePath), QLatin1Char(')')); } void TestEditorUi::does_not_insert_implicit_mul_sequence_before_open_paren_after_number_or_symbol() { // State: "2" and "Ï€". // Action: type '(' via text-based key event. // Expected: insert "()" without implicit multiplication prefix. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); auto typeGroupStartByText = [&editor]() { QKeyEvent openParenByText( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("(")); QApplication::sendEvent(&editor, &openParenByText); }; editor.setText(QStringLiteral("2")); editor.setCursorPosition(editor.text().size()); typeGroupStartByText(); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2()")); editor.setText(QString::fromUtf8("2³")); editor.setCursorPosition(editor.text().size()); typeGroupStartByText(); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("2³()")); editor.setText(QString::fromUtf8("Ï€")); editor.setCursorPosition(editor.text().size()); typeGroupStartByText(); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("Ï€()")); editor.setText(QString::fromUtf8("pi³")); editor.setCursorPosition(editor.text().size()); typeGroupStartByText(); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("pi³()")); } void TestEditorUi::does_not_insert_implicit_mul_for_zero_radix_prefix_letters() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("0")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("b")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("0b")); editor.setText(QStringLiteral("0")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("o")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("0o")); editor.setText(QStringLiteral("0")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("x")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("0x")); } void TestEditorUi::allows_unit_conversion_tail_after_spaced_subtraction_operator() { // State: "1", then subtraction operator formatting. // Action: type GreaterThanSign via text-based key event. // Expected: convert to spaced "→ []", cursor inside brackets, parser sees UnitConversion. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); const QString afterMinus = editor.document()->toRawText(); QVERIFY(afterMinus.contains(MathDsl::SubOp)); QKeyEvent greaterByText( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(UnicodeChars::GreaterThanSign)); QApplication::sendEvent(&editor, &greaterByText); const QString afterGreater = editor.document()->toRawText(); const QString arrowSequence = QString(MathDsl::SubWrapSp) + QString(MathDsl::TransOp) + QString(MathDsl::SubWrapSp) + QStringLiteral("[]"); QVERIFY(afterGreater.contains(arrowSequence)); QVERIFY(!afterGreater.contains(UnicodeChars::GreaterThanSign)); QCOMPARE(editor.textCursor().position(), afterGreater.size() - 1); const Tokens tokens = Evaluator::instance()->scan(afterGreater); bool hasUnitConversion = false; for (const Token& token : tokens) { if (token.isOperator() && token.asOperator() == Token::UnitConversion) { hasUnitConversion = true; break; } } QVERIFY(hasUnitConversion); } void TestEditorUi::converts_double_minus_sequence_to_unit_conversion_with_placeholder() { // State: "1". // Action: type '--'. // Expected: convert to spaced "→ []", cursor inside brackets, parser sees UnitConversion. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); const QString afterDoubleMinus = editor.document()->toRawText(); const QString arrowSequence = QString(MathDsl::SubWrapSp) + QString(MathDsl::TransOp) + QString(MathDsl::SubWrapSp) + QStringLiteral("[]"); QVERIFY(afterDoubleMinus.contains(arrowSequence)); QCOMPARE(editor.textCursor().position(), afterDoubleMinus.size() - 1); const Tokens tokens = Evaluator::instance()->scan(afterDoubleMinus); bool hasUnitConversion = false; for (const Token& token : tokens) { if (token.isOperator() && token.asOperator() == Token::UnitConversion) { hasUnitConversion = true; break; } } QVERIFY(hasUnitConversion); } void TestEditorUi::converts_double_minus_sequence_to_unit_conversion_after_masculine_ordinal_degree() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString conversion = QString(MathDsl::SubWrapSp) + QString(MathDsl::TransOp) + QString(MathDsl::SubWrapSp) + QStringLiteral("[]"); const QPair cases[] = { {QString::fromUtf8("12º"), QString::fromUtf8("12°") + conversion}, {QString::fromUtf8("23°"), QString::fromUtf8("23°") + conversion}, {QString::fromUtf8("23′"), QString::fromUtf8("23′") + conversion}, {QString::fromUtf8("23″"), QString::fromUtf8("23″") + conversion} }; for (const auto& tc : cases) { editor.setText(tc.first); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); const QString actual = editor.document()->toRawText(); QCOMPARE(actual, tc.second); QCOMPARE(editor.textCursor().position(), actual.size() - 1); } } void TestEditorUi::inserts_unit_conversion_with_placeholder_when_typing_arrow_symbol() { // State: "1". // Action: type "→" directly. // Expected: insert " → []", with cursor inside brackets. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1")); editor.setCursorPosition(editor.text().size()); QKeyEvent rightArrowByText( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(MathDsl::TransOp)); QApplication::sendEvent(&editor, &rightArrowByText); const QString expected = QStringLiteral("1") + QString(MathDsl::SubWrapSp) + QString(MathDsl::TransOp) + QString(MathDsl::SubWrapSp) + QStringLiteral("[]"); QCOMPARE(editor.document()->toRawText(), expected); QCOMPARE(editor.textCursor().position(), expected.size() - 1); } void TestEditorUi::treats_spaced_unit_conversion_as_atomic_navigation_and_edit_token() { // State: "1→2". // Action: use Left/Right, Alt+Left/Right, Backspace, Delete near token. // Expected: grouped " → " behaves as one atomic token. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString arrowToken = QString(MathDsl::SubWrapSp) + QString(MathDsl::TransOp) + QString(MathDsl::SubWrapSp); const QString expression = QStringLiteral("1") + arrowToken + QStringLiteral("2"); editor.setText(expression); editor.setCursorPosition(4); // between arrow and trailing space QTest::keyClick(&editor, Qt::Key_Left, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 1); QTest::keyClick(&editor, Qt::Key_Right, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 4); editor.setText(expression); editor.setCursorPosition(4); // right after grouped token QTest::keyClick(&editor, Qt::Key_Left, Qt::AltModifier); QCOMPARE(editor.textCursor().position(), 1); editor.setCursorPosition(1); // right before grouped token QTest::keyClick(&editor, Qt::Key_Right, Qt::AltModifier); QCOMPARE(editor.textCursor().position(), 4); editor.setText(expression); editor.setCursorPosition(4); // immediately after grouped token QTest::keyClick(&editor, Qt::Key_Backspace, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); editor.setText(expression); editor.setCursorPosition(1); // immediately before grouped token QTest::keyClick(&editor, Qt::Key_Delete, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); } void TestEditorUi::treats_spaced_shift_operators_as_atomic_navigation_and_edit_tokens() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString leftShift = MathDsl::buildWrappedToken(MathDsl::ShiftLeftOp); const QString rightShift = MathDsl::buildWrappedToken(MathDsl::ShiftRightOp); const QString leftExpression = QStringLiteral("1") + leftShift + QStringLiteral("2"); const QString rightExpression = QStringLiteral("1") + rightShift + QStringLiteral("2"); editor.setText(leftExpression); editor.setCursorPosition(5); // right after grouped token QTest::keyClick(&editor, Qt::Key_Left, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 1); QTest::keyClick(&editor, Qt::Key_Right, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 5); QTest::keyClick(&editor, Qt::Key_Backspace, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); editor.setText(leftExpression); editor.setCursorPosition(1); // right before grouped token QTest::keyClick(&editor, Qt::Key_Delete, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); editor.setText(rightExpression); editor.setCursorPosition(5); // right after grouped token QTest::keyClick(&editor, Qt::Key_Left, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 1); QTest::keyClick(&editor, Qt::Key_Right, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 5); QTest::keyClick(&editor, Qt::Key_Backspace, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); editor.setText(rightExpression); editor.setCursorPosition(1); // right before grouped token QTest::keyClick(&editor, Qt::Key_Delete, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); } void TestEditorUi::backspace_removes_typed_operator_after_unit() { Editor editor; QTest::keyClicks(&editor, QStringLiteral("2 [g")); QTest::keyClick(&editor, Qt::Key_Right); // Leave the auto-inserted unit brackets. QTest::keyClicks(&editor, QStringLiteral("/")); const QString quantity = QStringLiteral("2") + MathDsl::QuantSp + QStringLiteral("[g]"); const QString division = MathDsl::buildWrappedToken(MathDsl::DivOp, MathDsl::DivWrap); QCOMPARE(editor.document()->toRawText(), quantity + division); // Native Backspace events carry a control character; QTest::keyClick // does not reproduce that payload on every platform. QKeyEvent backspace(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier, QString(QChar(0x08))); QApplication::sendEvent(&editor, &backspace); QCOMPARE(editor.document()->toRawText(), quantity); QCOMPARE(editor.textCursor().position(), quantity.size()); } void TestEditorUi::editing_keys_bypass_typing_restrictions_data() { QTest::addColumn("expression"); QTest::addColumn("position"); QTest::addColumn("key"); QTest::addColumn("payload"); QTest::addColumn("expected"); QTest::addColumn("expectedPosition"); const QList operators = { MathDsl::AddOp, MathDsl::SubOp, MathDsl::DivOp, MathDsl::MulCrossOp, MathDsl::PowOp }; const QStringList prefixes = { QStringLiteral("2"), QStringLiteral("2") + MathDsl::QuantSp + QStringLiteral("[g]"), QStringLiteral("2") + MathDsl::QuantSp + QStringLiteral("[g") }; for (int context = 0; context < prefixes.size(); ++context) { for (const QChar op : operators) { const QString token = context == 2 || op == MathDsl::PowOp ? QString(op) : MathDsl::buildWrappedToken(op); const QString expression = prefixes.at(context) + token; const QByteArray name = QStringLiteral("context-%1-op-%2") .arg(context).arg(uint(op.unicode())).toLatin1(); QTest::newRow(QByteArray(name + "-backspace").constData()) << expression << int(expression.size()) << int(Qt::Key_Backspace) << QString(QChar(0x08)) << prefixes.at(context) << int(prefixes.at(context).size()); QTest::newRow(QByteArray(name + "-delete").constData()) << expression + QStringLiteral("7") << int(expression.size()) << int(Qt::Key_Delete) << QString(QChar(0x7f)) << expression << int(expression.size()); QTest::newRow(QByteArray(name + "-escape").constData()) << expression << int(expression.size()) << int(Qt::Key_Escape) << QString(QChar(0x1b)) << expression << int(expression.size()); QTest::newRow(QByteArray(name + "-tab").constData()) << expression << int(expression.size()) << int(Qt::Key_Tab) << QString(QChar(0x09)) << expression << int(expression.size()); } } QTest::newRow("delete-at-expression-start") << QStringLiteral("7") << 0 << int(Qt::Key_Delete) << QString(QChar(0x7f)) << QString() << 0; QTest::newRow("backspace-in-leading-whitespace") << QStringLiteral(" 7") << 2 << int(Qt::Key_Backspace) << QString(QChar(0x08)) << QStringLiteral(" 7") << 1; QTest::newRow("escape-in-empty-editor") << QString() << 0 << int(Qt::Key_Escape) << QString(QChar(0x1b)) << QString() << 0; } void TestEditorUi::editing_keys_bypass_typing_restrictions() { QFETCH(QString, expression); QFETCH(int, position); QFETCH(int, key); QFETCH(QString, payload); QFETCH(QString, expected); QFETCH(int, expectedPosition); Editor editor; editor.setText(expression); editor.setCursorPosition(position); QSignalSpy escapeSpy(&editor, SIGNAL(escapePressed())); QKeyEvent event(QEvent::KeyPress, key, Qt::NoModifier, payload); QApplication::sendEvent(&editor, &event); QCOMPARE(editor.document()->toRawText(), expected); QCOMPARE(editor.textCursor().position(), expectedPosition); QCOMPARE(escapeSpy.count(), key == Qt::Key_Escape ? 1 : 0); } void TestEditorUi::undo_redo_shortcuts_preserve_expression_data() { QTest::addColumn("expression"); QTest::addColumn("position"); QTest::addColumn("selectionLength"); QTest::addColumn("shortcutPosition"); QTest::addColumn("payload"); const QStringList expressions = { QStringLiteral("123456"), QStringLiteral("12+34"), QStringLiteral("12[m/s]"), QString::fromUtf8("12°34′56″"), QStringLiteral("12 ? comment") }; const QStringList payloads = {QString(), QString(QChar(0x1a)), QStringLiteral("z")}; const QList shortcutPositions = {3, 3, 5, 4, 7}; for (int context = 0; context < expressions.size(); ++context) { for (int payload = 0; payload < payloads.size(); ++payload) { for (int selectionLength : {0, 2}) { const QByteArray name = QStringLiteral("context-%1-payload-%2-selection-%3") .arg(context).arg(payload).arg(selectionLength).toLatin1(); QTest::newRow(name.constData()) << expressions.at(context) << 2 << selectionLength << shortcutPositions.at(context) << payloads.at(payload); } } } } void TestEditorUi::undo_redo_shortcuts_preserve_expression() { QFETCH(QString, expression); QFETCH(int, position); QFETCH(int, selectionLength); QFETCH(int, shortcutPosition); QFETCH(QString, payload); const auto undoBindings = QKeySequence::keyBindings(QKeySequence::Undo); const auto redoBindings = QKeySequence::keyBindings(QKeySequence::Redo); QVERIFY(!undoBindings.isEmpty()); QVERIFY(!redoBindings.isEmpty()); for (const QKeySequence& undoBinding : undoBindings) { for (const QKeySequence& redoBinding : redoBindings) { Editor editor; editor.setAutoCompletionEnabled(false); editor.setText(expression); const QString original = editor.document()->toRawText(); QTextCursor cursor = editor.textCursor(); cursor.setPosition(position); cursor.setPosition(position + selectionLength, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); QTest::keyClicks(&editor, QStringLiteral("9")); const QString edited = editor.document()->toRawText(); QVERIFY(edited != original); editor.setCursorPosition(shortcutPosition); // Native shortcuts can carry a control character or printable text. const auto undoKey = undoBinding[0]; QKeyEvent undoEvent(QEvent::KeyPress, undoKey.key(), undoKey.keyboardModifiers(), payload); QVERIFY(undoEvent.matches(QKeySequence::Undo)); QApplication::sendEvent(&editor, &undoEvent); QCOMPARE(editor.document()->toRawText(), original); QVERIFY(editor.document()->isRedoAvailable()); // Keep a selection active to catch accidental replacement by shortcut text. cursor = editor.textCursor(); cursor.setPosition(0); cursor.setPosition(2, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); const auto redoKey = redoBinding[0]; const QString redoPayload = payload.isEmpty() ? QString() : payload.at(0).isPrint() ? QStringLiteral("z") : QString(QChar(0x19)); QKeyEvent redoEvent(QEvent::KeyPress, redoKey.key(), redoKey.keyboardModifiers(), redoPayload); QVERIFY(redoEvent.matches(QKeySequence::Redo)); QApplication::sendEvent(&editor, &redoEvent); QCOMPARE(editor.document()->toRawText(), edited); QApplication::sendEvent(&editor, &redoEvent); QCOMPARE(editor.document()->toRawText(), edited); QApplication::sendEvent(&editor, &undoEvent); QCOMPARE(editor.document()->toRawText(), original); QVERIFY(!editor.document()->isUndoAvailable()); QApplication::sendEvent(&editor, &undoEvent); QCOMPARE(editor.document()->toRawText(), original); QVERIFY(editor.document()->isRedoAvailable()); } } } void TestEditorUi::typing_undoes_one_key_at_a_time_data() { QTest::addColumn("input"); QTest::addColumn("inputMethod"); for (bool inputMethod : {false, true}) { const QByteArray prefix = inputMethod ? "ime-" : "key-"; QTest::newRow(QByteArray(prefix + "digits").constData()) << QStringLiteral("12345") << inputMethod; QTest::newRow(QByteArray(prefix + "operators").constData()) << QStringLiteral("12+34") << inputMethod; QTest::newRow(QByteArray(prefix + "units").constData()) << QStringLiteral("12[m/s]") << inputMethod; QTest::newRow(QByteArray(prefix + "degrees").constData()) << QString::fromUtf8("12º34'56\"") << inputMethod; QTest::newRow(QByteArray(prefix + "superscript-rewrite").constData()) << QStringLiteral("12^34") << inputMethod; if (!inputMethod) { QTest::newRow("key-unit-conversion-rewrite") << QStringLiteral("12--") << false; QTest::newRow("key-parenthesis-pair") << QStringLiteral("12+(34") << false; } } } void TestEditorUi::typing_undoes_one_key_at_a_time() { QFETCH(QString, input); QFETCH(bool, inputMethod); Editor editor; editor.setAutoCompletionEnabled(false); editor.setText(QString()); QStringList states = {editor.document()->toRawText()}; for (const QChar ch : input) { if (inputMethod) { QInputMethodEvent event; event.setCommitString(QString(ch)); QApplication::sendEvent(&editor, &event); } else if (ch.unicode() < 128) { QTest::keyClicks(&editor, QString(ch)); } else { QKeyEvent event(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(ch)); QApplication::sendEvent(&editor, &event); } const QString state = editor.document()->toRawText(); if (state != states.last()) states.append(state); } QVERIFY(states.size() > 2); for (int i = states.size() - 2; i >= 0; --i) { QVERIFY(editor.document()->isUndoAvailable()); editor.undo(); QCOMPARE(editor.document()->toRawText(), states.at(i)); } QVERIFY(!editor.document()->isUndoAvailable()); for (int i = 1; i < states.size(); ++i) { QVERIFY(editor.document()->isRedoAvailable()); editor.redo(); QCOMPARE(editor.document()->toRawText(), states.at(i)); } QVERIFY(!editor.document()->isRedoAvailable()); } void TestEditorUi::non_printable_key_payloads_do_not_replace_selection() { for (ushort code : {0x01, 0x19, 0x1a, 0x7f}) { Editor editor; editor.setText(QStringLiteral("123456")); QTextCursor cursor = editor.textCursor(); cursor.setPosition(2); cursor.setPosition(4, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); QKeyEvent event(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(QChar(code))); QApplication::sendEvent(&editor, &event); QCOMPARE(editor.document()->toRawText(), QStringLiteral("123456")); QCOMPARE(editor.textCursor().selectedText(), QStringLiteral("34")); QVERIFY(!editor.document()->isUndoAvailable()); } } void TestEditorUi::clipboard_shortcuts_do_not_insert_key_payloads_data() { QTest::addColumn("cutPayload"); QTest::addColumn("pastePayload"); QTest::newRow("empty") << QString() << QString(); QTest::newRow("control-characters") << QString(QChar(0x18)) << QString(QChar(0x16)); QTest::newRow("printable-letters") << QStringLiteral("x") << QStringLiteral("v"); } void TestEditorUi::clipboard_shortcuts_do_not_insert_key_payloads() { QFETCH(QString, cutPayload); QFETCH(QString, pastePayload); Editor editor; editor.setText(QStringLiteral("123456")); QTextCursor cursor = editor.textCursor(); cursor.setPosition(2); cursor.setPosition(4, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); const auto cutKey = QKeySequence(QKeySequence::Cut)[0]; QKeyEvent cutEvent(QEvent::KeyPress, cutKey.key(), cutKey.keyboardModifiers(), cutPayload); QApplication::sendEvent(&editor, &cutEvent); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1256")); QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("34")); const auto pasteKey = QKeySequence(QKeySequence::Paste)[0]; QKeyEvent pasteEvent(QEvent::KeyPress, pasteKey.key(), pasteKey.keyboardModifiers(), pastePayload); QApplication::sendEvent(&editor, &pasteEvent); QCOMPARE(editor.document()->toRawText(), QStringLiteral("123456")); editor.undo(); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1256")); editor.undo(); QCOMPARE(editor.document()->toRawText(), QStringLiteral("123456")); } void TestEditorUi::copy_shortcut_preserves_editor_state_data() { QTest::addColumn("payload"); QTest::addColumn("selectText"); QTest::newRow("empty-selection") << QString() << true; QTest::newRow("control-character-selection") << QString(QChar(0x03)) << true; QTest::newRow("printable-letter-selection") << QStringLiteral("c") << true; QTest::newRow("empty-no-selection") << QString() << false; QTest::newRow("control-character-no-selection") << QString(QChar(0x03)) << false; QTest::newRow("printable-letter-no-selection") << QStringLiteral("c") << false; } void TestEditorUi::copy_shortcut_preserves_editor_state() { QFETCH(QString, payload); QFETCH(bool, selectText); Editor editor; // MainWindow routes this signal to the widget whose selection is copied. // Use the editor as that widget here to exercise the clipboard operation. connect(&editor, &Editor::copySequencePressed, &editor, &QPlainTextEdit::copy); QSignalSpy copySpy(&editor, &Editor::copySequencePressed); QVERIFY(copySpy.isValid()); editor.setText(QStringLiteral("123456")); editor.setCursorPosition(6); QTest::keyClicks(&editor, "78"); editor.undo(); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1234567")); QVERIFY(editor.document()->isUndoAvailable()); QVERIFY(editor.document()->isRedoAvailable()); QTextCursor cursor = editor.textCursor(); cursor.setPosition(2); if (selectText) cursor.setPosition(4, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); QApplication::clipboard()->setText(QStringLiteral("unchanged")); const auto copyKey = QKeySequence(QKeySequence::Copy)[0]; QKeyEvent copyEvent(QEvent::KeyPress, copyKey.key(), copyKey.keyboardModifiers(), payload); copyEvent.ignore(); QApplication::sendEvent(&editor, ©Event); QVERIFY(copyEvent.isAccepted()); QCOMPARE(copySpy.count(), 1); QCOMPARE(QApplication::clipboard()->text(), selectText ? QStringLiteral("34") : QStringLiteral("unchanged")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1234567")); QCOMPARE(editor.textCursor().position(), cursor.position()); QCOMPARE(editor.textCursor().anchor(), cursor.anchor()); QVERIFY(editor.document()->isUndoAvailable()); QVERIFY(editor.document()->isRedoAvailable()); editor.redo(); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12345678")); editor.undo(); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1234567")); editor.undo(); QCOMPARE(editor.document()->toRawText(), QStringLiteral("123456")); } void TestEditorUi::highlight_refresh_preserves_text_and_selection_without_edit_signals() { Editor editor; editor.setText(QStringLiteral("123456")); QTextCursor cursor = editor.textCursor(); cursor.setPosition(2); cursor.setPosition(4, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); QSignalSpy textChangedSpy(&editor, &Editor::textChanged); QVERIFY(textChangedSpy.isValid()); editor.setThemePrimaryColor(QColor(QStringLiteral("#334455")), true); editor.rehighlight(); QCOMPARE(textChangedSpy.count(), 0); editor.setSession(nullptr); QCOMPARE(textChangedSpy.count(), 0); QCOMPARE(editor.document()->toRawText(), QStringLiteral("123456")); QCOMPARE(editor.textCursor().position(), cursor.position()); QCOMPARE(editor.textCursor().anchor(), cursor.anchor()); QVERIFY(!editor.document()->isUndoAvailable()); } void TestEditorUi::primary_theme_changes_preserve_document_highlighting_data() { QTest::addColumn("classic"); QTest::newRow("modern") << false; QTest::newRow("classic") << true; } void TestEditorUi::primary_theme_changes_preserve_document_highlighting() { QFETCH(bool, classic); Settings* settings = Settings::instance(); settings->editorDisplayStyle = classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; settings->inputDigitGrouping = true; Editor editor; editor.setAutoCalcEnabled(false); editor.setAutoCompletionEnabled(false); editor.setThemePrimaryColor(QColor(QStringLiteral("#334455")), false); editor.insertPlainText(QStringLiteral("123456 + sin(2)")); editor.rehighlight(); QCoreApplication::processEvents(); QTextCursor cursor = editor.textCursor(); cursor.setPosition(2); cursor.setPosition(8, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); const auto formats = editor.document()->firstBlock().layout()->formats(); QVERIFY(!formats.isEmpty()); const int revision = editor.document()->revision(); QSignalSpy documentChanged(editor.document(), &QTextDocument::contentsChanged); QSignalSpy textChanged(&editor, &Editor::textChanged); const QString inactiveStyle = editor.styleSheet(); editor.setThemePrimaryColor(QColor(QStringLiteral("#334455")), true); QVERIFY(editor.styleSheet() != inactiveStyle); editor.setThemePrimaryColor(QColor(QStringLiteral("#556677")), true); QCOMPARE(editor.cursorColor(), QColor(QStringLiteral("#556677"))); editor.setThemePrimaryColor(QColor(QStringLiteral("#556677")), false); QPalette viewportPalette = editor.viewport()->palette(); viewportPalette.setColor(QPalette::Base, Qt::transparent); editor.viewport()->setPalette(viewportPalette); editor.setThemePrimaryColor(QColor(QStringLiteral("#556677")), false); QCOMPARE(editor.viewport()->palette().color(QPalette::Base), editor.palette().color(QPalette::Base)); QCOMPARE(documentChanged.count(), 0); QCOMPARE(textChanged.count(), 0); QCOMPARE(editor.document()->revision(), revision); QCOMPARE(editor.document()->firstBlock().layout()->formats(), formats); QCOMPARE(editor.textCursor().position(), cursor.position()); QCOMPARE(editor.textCursor().anchor(), cursor.anchor()); QVERIFY(editor.document()->isUndoAvailable()); editor.undo(); QVERIFY(editor.text().isEmpty()); } void TestEditorUi::highlight_refresh_updates_document_once_data() { QTest::addColumn("preview"); QTest::newRow("configured-theme") << false; QTest::newRow("preview-theme") << true; } void TestEditorUi::highlight_refresh_updates_document_once() { QFETCH(bool, preview); Settings* settings = Settings::instance(); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{ {QStringLiteral("number"), QStringLiteral("#123456")}, {QStringLiteral("background"), QStringLiteral("#102030")} }); Editor editor; editor.setAutoCalcEnabled(false); editor.setAutoCompletionEnabled(false); editor.setText(QStringLiteral("123456")); const auto refreshTheme = [&]() { if (preview) { editor.setThemePreviewColorScheme(ColorScheme(QJsonDocument::fromJson( settings->customColorSchemeJson.toUtf8()))); } else { editor.rehighlight(); } }; refreshTheme(); QCoreApplication::processEvents(); QCOMPARE(editor.document()->firstBlock().layout()->formats().first().format.foreground().color(), QColor(QStringLiteral("#123456"))); QSignalSpy documentChanged(editor.document(), &QTextDocument::contentsChanged); QSignalSpy textChanged(&editor, &Editor::textChanged); settings->customColorSchemeJson = themeJsonString(QJsonObject{ {QStringLiteral("number"), QStringLiteral("#abcdef")}, {QStringLiteral("background"), QStringLiteral("#102030")} }); refreshTheme(); QCOMPARE(documentChanged.count(), 1); QCOMPARE(textChanged.count(), 0); QCOMPARE(editor.document()->firstBlock().layout()->formats().first().format.foreground().color(), QColor(QStringLiteral("#abcdef"))); QCOMPARE(editor.text(), QStringLiteral("123456")); } void TestEditorUi::unchanged_primary_theme_avoids_editor_style_refresh_data() { QTest::addColumn("classic"); QTest::newRow("modern") << false; QTest::newRow("classic") << true; } void TestEditorUi::unchanged_primary_theme_avoids_editor_style_refresh() { QFETCH(bool, classic); Settings::instance()->editorDisplayStyle = classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; Editor editor; editor.setAutoCompletionEnabled(false); const QColor primary(QStringLiteral("#334455")); editor.setThemePrimaryColor(primary, true); editor.setText(QStringLiteral("123+456")); editor.setCursorPosition(editor.text().size()); class StyleChangeRecorder : public QObject { public: int count = 0; bool eventFilter(QObject*, QEvent* event) override { if (event->type() == QEvent::StyleChange) ++count; return false; } } recorder; editor.installEventFilter(&recorder); for (int i = 0; i < 5; ++i) { QTest::keyClicks(&editor, QStringLiteral("1")); editor.setThemePrimaryColor(primary, true); } QCOMPARE(recorder.count, 0); QCOMPARE(editor.text(), QStringLiteral("123+45611111")); const QString activeStyle = editor.styleSheet(); editor.setThemePrimaryColor(primary, false); QVERIFY(recorder.count > 0); QVERIFY(editor.styleSheet() != activeStyle); recorder.count = 0; editor.setThemePrimaryColor(primary, false); QCOMPARE(recorder.count, 0); editor.setThemePrimaryColor(QColor(QStringLiteral("#556677")), true); QVERIFY(recorder.count > 0); QVERIFY(editor.styleSheet() != activeStyle); QPalette viewportPalette = editor.viewport()->palette(); viewportPalette.setColor(QPalette::Base, Qt::transparent); editor.viewport()->setPalette(viewportPalette); editor.setThemePrimaryColor(QColor(QStringLiteral("#556677")), true); QCOMPARE(editor.viewport()->palette().color(QPalette::Base), editor.palette().color(QPalette::Base)); } void TestEditorUi::editor_text_line_is_vertically_centered_data() { QTest::addColumn("classic"); QTest::addColumn("pixelSize"); QTest::addColumn("lineCount"); QTest::addColumn("fixedFont"); QTest::addColumn("wrapped"); for (const bool classic : {false, true}) { for (const int pixelSize : {16, 24, 32}) { for (const int lineCount : {1, 5}) { const QByteArray name = QByteArray(classic ? "classic-" : "modern-") + QByteArray::number(pixelSize) + '-' + QByteArray::number(lineCount); QTest::newRow(name.constData()) << classic << pixelSize << lineCount << false << false; QTest::newRow(QByteArray(name + "-fixed").constData()) << classic << pixelSize << lineCount << true << false; if (lineCount > 1) { QTest::newRow(QByteArray(name + "-wrapped").constData()) << classic << pixelSize << lineCount << false << true; QTest::newRow(QByteArray(name + "-fixed-wrapped").constData()) << classic << pixelSize << lineCount << true << true; } } } } } void TestEditorUi::editor_text_line_is_vertically_centered() { QFETCH(bool, classic); QFETCH(int, pixelSize); QFETCH(int, lineCount); QFETCH(bool, fixedFont); QFETCH(bool, wrapped); Settings::instance()->editorDisplayStyle = classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; Settings::instance()->inputDigitGrouping = false; Editor editor; QFont font = fixedFont ? QFontDatabase::systemFont(QFontDatabase::FixedFont) : editor.font(); font.setPixelSize(pixelSize); editor.setFont(font); editor.setFixedWidth(400); editor.rehighlight(); editor.setThemePrimaryColor(QColor(QStringLiteral("#90aaff")), true); QStringList lines; for (int i = 0; i < lineCount; ++i) lines.append(QStringLiteral("23323323")); editor.setText(lines.join(QLatin1Char('\n'))); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); if (wrapped) { const int decorations = editor.width() - editor.viewport()->width(); editor.setFixedWidth(decorations + qCeil(QFontMetricsF(font).horizontalAdvance(lines.first())) + 2 * int(editor.document()->documentMargin()) + 1); editor.setText(lines.join(QString())); } QCoreApplication::processEvents(); QCOMPARE(editor.document()->lineCount(), lineCount); QTextCursor first(editor.document()); QTextCursor last(editor.document()); last.movePosition(QTextCursor::End); const QRect firstLine = editor.cursorRect(first).translated(editor.viewport()->pos()); const QRect lastLine = editor.cursorRect(last).translated(editor.viewport()->pos()); const int top = classic ? UiConfig::OutlineStrokeWidth : UiConfig::ModernEditorTopMargin; const int bottom = editor.height() - (classic ? 0 : UiConfig::ModernEditorBottomMargin); QVERIFY2(qAbs((firstLine.top() + lastLine.bottom() + 1) - (top + bottom)) <= 1, qPrintable(QStringLiteral("Text spans %1..%2 inside editor area %3..%4") .arg(firstLine.top()).arg(lastLine.bottom() + 1).arg(top).arg(bottom))); } void TestEditorUi::treats_spaced_question_comment_as_atomic_navigation_and_edit_token() { // State: "1 ? 2". // Action: use Left/Right, Alt+Left/Right, Backspace, Delete near token. // Expected: grouped " ? " behaves as one atomic token. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString commentToken = QStringLiteral(" ? "); const QString expression = QStringLiteral("1") + commentToken + QStringLiteral("2"); editor.setText(expression); editor.setCursorPosition(4); // between '?' and trailing space QTest::keyClick(&editor, Qt::Key_Left, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 1); QTest::keyClick(&editor, Qt::Key_Right, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 4); editor.setText(expression); editor.setCursorPosition(4); // right after grouped token QTest::keyClick(&editor, Qt::Key_Left, Qt::AltModifier); QCOMPARE(editor.textCursor().position(), 1); editor.setCursorPosition(1); // right before grouped token QTest::keyClick(&editor, Qt::Key_Right, Qt::AltModifier); QCOMPARE(editor.textCursor().position(), 4); editor.setText(expression); editor.setCursorPosition(4); // immediately after grouped token QTest::keyClick(&editor, Qt::Key_Backspace, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); editor.setText(expression); editor.setCursorPosition(1); // immediately before grouped token QTest::keyClick(&editor, Qt::Key_Delete, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); } void TestEditorUi::treats_spaced_equal_as_atomic_navigation_and_edit_token() { // State: "1", then type '=' with editor insertion rules. // Action: navigate/edit around grouped token. // Expected: grouped " = " behaves as one atomic token. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Equal, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1 = ")); editor.insert(QStringLiteral("2")); const QString expression = editor.document()->toRawText(); QCOMPARE(expression, QStringLiteral("1 = 2")); editor.setCursorPosition(4); // right after grouped token QTest::keyClick(&editor, Qt::Key_Left, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 1); editor.setCursorPosition(1); // right before grouped token QTest::keyClick(&editor, Qt::Key_Right, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 4); editor.setCursorPosition(4); // immediately after grouped token QTest::keyClick(&editor, Qt::Key_Backspace, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); editor.setText(expression); editor.setCursorPosition(1); // immediately before grouped token QTest::keyClick(&editor, Qt::Key_Delete, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12")); } void TestEditorUi::treats_leading_question_comment_as_atomic_navigation_and_edit_token() { // State: "? 2" (comment token at start of editor). // Action: use Left/Right, Alt+Left/Right, Backspace, Delete near token. // Expected: grouped "? " behaves as one atomic token. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString expression = QStringLiteral("? 2"); editor.setText(expression); editor.setCursorPosition(1); // between '?' and trailing space QTest::keyClick(&editor, Qt::Key_Left, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 0); QTest::keyClick(&editor, Qt::Key_Right, Qt::NoModifier); QCOMPARE(editor.textCursor().position(), 2); editor.setText(expression); editor.setCursorPosition(2); // right after grouped token QTest::keyClick(&editor, Qt::Key_Left, Qt::AltModifier); QCOMPARE(editor.textCursor().position(), 0); editor.setCursorPosition(0); // right before grouped token QTest::keyClick(&editor, Qt::Key_Right, Qt::AltModifier); QCOMPARE(editor.textCursor().position(), 2); editor.setText(expression); editor.setCursorPosition(2); // immediately after grouped token QTest::keyClick(&editor, Qt::Key_Backspace, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2")); editor.setText(expression); editor.setCursorPosition(0); // immediately before grouped token QTest::keyClick(&editor, Qt::Key_Delete, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2")); } void TestEditorUi::ignores_space_right_after_spaced_unit_conversion_operator() { // State: after conversion to spaced "→ []" token with cursor inside []. // Action: type SPACE. // Expected: ignored because current [] unit context is empty. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QKeyEvent greaterByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral(">")); QApplication::sendEvent(&editor, &greaterByText); const QString beforeSpace = editor.document()->toRawText(); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), beforeSpace); } void TestEditorUi::unit_bracket_context_accepts_div_mul_and_rejects_addition() { // State: unmatched "[m" unit context. // Action: type '+', '/', and '*'. // Expected: '+' rejected; '/' and multiplication accepted. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); const QString beforePlus = editor.document()->toRawText(); QTest::keyClick(&editor, Qt::Key_Plus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), beforePlus); QTest::keyClick(&editor, Qt::Key_Slash, Qt::NoModifier); const QString afterSlash = editor.document()->toRawText(); QVERIFY(afterSlash.contains(MathDsl::DivOp)); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); const QString afterMul = editor.document()->toRawText(); QVERIFY(afterMul.contains(MathDsl::MulCrossOp) || afterMul.contains(MathDsl::MulDotOp)); } void TestEditorUi::unit_bracket_context_blocks_space_and_ops_when_only_spaces() { // State: unmatched "[ " and cursor at end. // Action: type SPACE and operator keys. // Expected: all are ignored while unit context has only whitespace. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString onlySpaces = QStringLiteral("[ "); editor.setText(onlySpaces); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), onlySpaces); editor.setText(onlySpaces); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), onlySpaces); editor.setText(onlySpaces); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Slash, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), onlySpaces); editor.setText(onlySpaces); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), onlySpaces); editor.setText(onlySpaces); editor.setCursorPosition(editor.text().size()); QKeyEvent shiftSlashByText(QEvent::KeyPress, Qt::Key_unknown, Qt::ShiftModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &shiftSlashByText); QCOMPARE(editor.document()->toRawText(), onlySpaces); editor.setText(onlySpaces); editor.setCursorPosition(editor.text().size()); QKeyEvent keypadSlash(QEvent::KeyPress, Qt::Key_division, Qt::KeypadModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &keypadSlash); QCOMPARE(editor.document()->toRawText(), onlySpaces); } void TestEditorUi::unit_bracket_context_accepts_quote_marks_as_arc_units() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("[")); editor.setCursorPosition(editor.text().size()); QKeyEvent apostropheByText( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("'")); QApplication::sendEvent(&editor, &apostropheByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[") + QString(UnicodeChars::Prime)); editor.setText(QStringLiteral("[")); editor.setCursorPosition(editor.text().size()); QKeyEvent quoteByText( QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("\"")); QApplication::sendEvent(&editor, "eByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[") + QString(UnicodeChars::DoublePrime)); } void TestEditorUi::unit_bracket_context_accepts_quote_marks_via_ime_commit() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QList imeAttributes; editor.setText(QStringLiteral("[")); editor.setCursorPosition(editor.text().size()); QInputMethodEvent apostropheCommit(QString(), imeAttributes); apostropheCommit.setCommitString(QStringLiteral("'")); QApplication::sendEvent(&editor, &apostropheCommit); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[") + QString(UnicodeChars::Prime)); editor.setText(QStringLiteral("[")); editor.setCursorPosition(editor.text().size()); QInputMethodEvent quoteCommit(QString(), imeAttributes); quoteCommit.setCommitString(QStringLiteral("\"")); QApplication::sendEvent(&editor, "eCommit); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[") + QString(UnicodeChars::DoublePrime)); } void TestEditorUi::unit_bracket_context_allows_letter_after_middle_dot() { // State: "2 [m·]" with cursor after '·'. // Action: type letter and then digit. // Expected: letter accepted; digit rejected. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2 [m·]")); editor.setCursorPosition(5); // right after middle-dot, before ']' QTest::keyClicks(&editor, QStringLiteral("s")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2 [m·s]")); editor.setText(QStringLiteral("2 [m·]")); editor.setCursorPosition(5); // right after middle-dot, before ']' QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2 [m·]")); } void TestEditorUi::unit_bracket_context_disallows_variables_and_constants() { // State: expressions "2[foo]", "2[e]", "2[pi]". // Action: evaluate with foo defined as variable. // Expected: all fail with "unknown unit". Session session; Evaluator* evaluator = session.evaluator(); evaluator->setVariable(QStringLiteral("foo"), Quantity(3)); evaluator->setExpression(QStringLiteral("2[foo]")); evaluator->evalUpdateAns(); QVERIFY(evaluator->error().contains(QStringLiteral("unknown unit"), Qt::CaseInsensitive)); evaluator->setExpression(QStringLiteral("2[e]")); evaluator->evalUpdateAns(); QVERIFY(evaluator->error().contains(QStringLiteral("unknown unit"), Qt::CaseInsensitive)); evaluator->setExpression(QStringLiteral("2[pi]")); evaluator->evalUpdateAns(); QVERIFY(evaluator->error().contains(QStringLiteral("unknown unit"), Qt::CaseInsensitive)); evaluator->unsetVariable(QStringLiteral("foo")); } void TestEditorUi::evaluator_accepts_compact_arc_symbol_units() { Session session; Evaluator* evaluator = session.evaluator(); const auto tokensDebug = [evaluator](const QString& expr) { const Tokens tokens = evaluator->scan(expr); QStringList parts; for (const Token& token : tokens) { parts.append(QStringLiteral("{t=%1,text='%2'}") .arg(static_cast(token.type())) .arg(token.text())); } return QStringLiteral("valid=%1 tokens=%2") .arg(tokens.valid() ? QStringLiteral("true") : QStringLiteral("false")) .arg(parts.join(QStringLiteral(", "))); }; evaluator->setExpression(QString::fromUtf8("1 [′]")); evaluator->evalUpdateAns(); QVERIFY2(evaluator->error().isEmpty(), qPrintable(QStringLiteral("Unexpected error for [′]: %1 (%2)") .arg(evaluator->error(), tokensDebug(QString::fromUtf8("1 [′]"))))); evaluator->setExpression(QString::fromUtf8("1 [″]")); evaluator->evalUpdateAns(); QVERIFY2(evaluator->error().isEmpty(), qPrintable(QStringLiteral("Unexpected error for [″]: %1 (%2)") .arg(evaluator->error(), tokensDebug(QString::fromUtf8("1 [″]"))))); } void TestEditorUi::unit_bracket_context_allows_digits_and_minus_only_in_exponent_positions() { // State: many "[m...]" exponent-denominator states. // Action: type digits, minus, slash, letters in each state. // Expected: only grammar-valid unit-exponent forms are accepted. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m2")); editor.setText(QStringLiteral("[m^")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2); editor.setText(QStringLiteral("[m^")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("x")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^")); editor.setText(QStringLiteral("[m^")); editor.setCursorPosition(editor.text().size()); QList imeAttributes; QInputMethodEvent imeLetterEvent(QString(), imeAttributes); imeLetterEvent.setCommitString(QStringLiteral("x")); QApplication::sendEvent(&editor, &imeLetterEvent); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^")); editor.setText(QStringLiteral("[m^(")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(2")); editor.setText(QStringLiteral("[m^2")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("3")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^23")); editor.setText(QStringLiteral("[m^2")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2 + QString(MathDsl::MulDotOp)); editor.setText(QStringLiteral("[s") + MathDsl::Pow2); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[s") + MathDsl::Pow2 + QString(MathDsl::MulDotOp)); editor.setText(QStringLiteral("[m^2")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashAfterPlainExponent(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashAfterPlainExponent); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2 + QString(MathDsl::DivOp)); editor.setText(QStringLiteral("[m^2")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2 + QString(MathDsl::MulDotOp)); editor.setText(QStringLiteral("[m^2")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("e")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^2")); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("eter")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[meter")); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_ParenLeft, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m()")); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QKeyEvent nestedBracketByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("[")); QApplication::sendEvent(&editor, &nestedBracketByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m")); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QKeyEvent closeBracketByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("]")); QApplication::sendEvent(&editor, &closeBracketByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m]")); editor.setText(QStringLiteral("[s^222")); editor.setCursorPosition(editor.text().size()); QKeyEvent closeBracketAfterExponent(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("]")); QApplication::sendEvent(&editor, &closeBracketAfterExponent); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[s") + MathDsl::Pow2 + MathDsl::Pow2 + MathDsl::Pow2 + QStringLiteral("]")); editor.setText(QStringLiteral("[m]")); editor.setCursorPosition(editor.text().size()); QKeyEvent chainedBracketByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("[")); QApplication::sendEvent(&editor, &chainedBracketByText); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m]")); editor.setText(QStringLiteral("[m]")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_ParenLeft, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m]()")); editor.setText(QStringLiteral("[]") + QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp) + QStringLiteral("()")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_ParenLeft, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[]") + QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp) + QStringLiteral("()") + QStringLiteral("()")); editor.setText(QStringLiteral("[m^(2")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("3")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(23")); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m")); editor.setText(QStringLiteral("[m^")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::PowNeg); editor.setText(QStringLiteral("[m^(")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(") + QString(MathDsl::SubOp)); editor.setText(QStringLiteral("[m") + MathDsl::PowNeg); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::PowNeg + MathDsl::Pow2); editor.setText(QStringLiteral("[m^(") + QString(MathDsl::SubOp)); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("2")); editor.setText(QStringLiteral("[m^(1")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText1(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText1); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(1/")); // m^/ -> reject slash right after exponent start. editor.setText(QStringLiteral("[m^")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashAfterExponentStart(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashAfterExponentStart); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^")); // mâ�»/ -> reject slash right after signed exponent start. editor.setText(QStringLiteral("[m") + MathDsl::PowNeg); editor.setCursorPosition(editor.text().size()); QKeyEvent slashAfterSignedExponentStart(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashAfterSignedExponentStart); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::PowNeg); editor.setText(QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("1")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText2(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText2); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("1/")); QKeyEvent slashByText3(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText3); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("1/")); // m^2/3 -> reject digit after slash (non-parenthesized exponent). editor.setText(QStringLiteral("[m^2")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText4(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText4); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2 + QStringLiteral("/")); QTest::keyClicks(&editor, QStringLiteral("s")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2 + QStringLiteral("/s")); editor.setText(QStringLiteral("[m^3")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText4b(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText4b); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow3 + QStringLiteral("/")); QTest::keyClicks(&editor, QStringLiteral("s")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow3 + QStringLiteral("/s")); // m²·/ -> reject slash right after multiplication separator. editor.setText(QStringLiteral("[m") + MathDsl::Pow2 + QString(MathDsl::MulDotOp)); editor.setCursorPosition(editor.text().size()); QKeyEvent slashAfterMulDot(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashAfterMulDot); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2 + QString(MathDsl::MulDotOp)); editor.setText(QStringLiteral("[m^2")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText4c(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText4c); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2 + QStringLiteral("/")); QTest::keyClicks(&editor, QStringLiteral("3")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::Pow2 + QStringLiteral("/")); // m^/ + "/" -> trim invalid slash after exponent start. editor.setText(QStringLiteral("[m^/")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText4d(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText4d); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^")); // m^-2/3 -> reject digit after slash (non-parenthesized signed exponent). editor.setText(QStringLiteral("[m^") + QString(MathDsl::SubOp) + QStringLiteral("2")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText5(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText5); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::PowNeg + MathDsl::Pow2 + QStringLiteral("/")); QTest::keyClicks(&editor, QStringLiteral("3")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m") + MathDsl::PowNeg + MathDsl::Pow2 + QStringLiteral("/")); // m^(2/3 -> accept digit after slash (parenthesized exponent). editor.setText(QStringLiteral("[m^(2")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText6(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText6); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(2/")); QTest::keyClicks(&editor, QStringLiteral("s")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(2/")); QTest::keyClicks(&editor, QStringLiteral("3")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(2/3")); // m².3 -> allow radix and following digits inside parenthesized exponent rewrite. editor.setText(QStringLiteral("[m") + MathDsl::Pow2); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(2.)")); QCOMPARE(editor.textCursor().position(), editor.document()->toRawText().size() - 1); QTest::keyClicks(&editor, QStringLiteral("3")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(2.3)")); QCOMPARE(editor.textCursor().position(), editor.document()->toRawText().size() - 1); // m^(-2/3 -> accept digit after slash (parenthesized signed exponent). editor.setText(QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("2")); editor.setCursorPosition(editor.text().size()); QKeyEvent slashByText7(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("/")); QApplication::sendEvent(&editor, &slashByText7); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("2/")); QTest::keyClicks(&editor, QStringLiteral("s")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("2/")); QTest::keyClicks(&editor, QStringLiteral("3")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("2/3")); editor.setText(QStringLiteral("[m^(-2")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("3")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m^(") + QString(MathDsl::SubOp) + QStringLiteral("23")); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QKeyEvent deadTilde(QEvent::KeyPress, Qt::Key_Dead_Tilde, Qt::NoModifier); QApplication::sendEvent(&editor, &deadTilde); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m")); editor.setText(QStringLiteral("3 + ")); editor.setCursorPosition(editor.text().size()); QKeyEvent deadTildeAfterPlus(QEvent::KeyPress, Qt::Key_Dead_Tilde, Qt::NoModifier); QApplication::sendEvent(&editor, &deadTildeAfterPlus); QCOMPARE(editor.document()->toRawText(), QStringLiteral("3 + ~")); editor.setText(QStringLiteral("3 + ")); editor.setCursorPosition(editor.text().size()); QKeyEvent regularTildeAfterPlus( QEvent::KeyPress, Qt::Key_AsciiTilde, Qt::NoModifier, QStringLiteral("~")); QApplication::sendEvent(&editor, ®ularTildeAfterPlus); QCOMPARE(editor.document()->toRawText(), QStringLiteral("3 + ~")); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QList deadImeAttrs; QInputMethodEvent deadTildePreedit(QStringLiteral("~"), deadImeAttrs); QApplication::sendEvent(&editor, &deadTildePreedit); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[m")); editor.setText(QStringLiteral("[s") + MathDsl::Pow2); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("^")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[s") + MathDsl::Pow2); editor.setText(QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[m/s") + QString(MathDsl::MulDotOp)); editor.setCursorPosition(editor.text().size()); QKeyEvent deadCircumflexInUnitAfterDot(QEvent::KeyPress, Qt::Key_Dead_Circumflex, Qt::NoModifier); QApplication::sendEvent(&editor, &deadCircumflexInUnitAfterDot); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[m/s") + QString(MathDsl::MulDotOp)); QList caretImeAttrs; QInputMethodEvent caretCommitAfterDot(QString(), caretImeAttrs); caretCommitAfterDot.setCommitString(QStringLiteral("^")); QApplication::sendEvent(&editor, &caretCommitAfterDot); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[m/s") + QString(MathDsl::MulDotOp)); QInputMethodEvent caretPreeditAfterDot(QString::fromUtf8("ˆ"), caretImeAttrs); QApplication::sendEvent(&editor, &caretPreeditAfterDot); QInputMethodEvent digitCommitAfterCaretPreedit(QString(), caretImeAttrs); digitCommitAfterCaretPreedit.setCommitString(QStringLiteral("2")); QApplication::sendEvent(&editor, &digitCommitAfterCaretPreedit); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[m/s") + QString(MathDsl::MulDotOp) + QStringLiteral("2")); editor.setText(QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[m") + MathDsl::Pow2 + QStringLiteral("/s")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[m") + MathDsl::Pow2 + QStringLiteral("/s^")); } void TestEditorUi::converts_caret_exponents_to_superscripts_globally() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("s^")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("s") + MathDsl::Pow2); editor.setText(QStringLiteral("s^")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("s") + MathDsl::PowNeg + MathDsl::Pow2); editor.setText(QStringLiteral("[s^")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[s") + MathDsl::Pow2); editor.setText(QStringLiteral("s")); editor.setCursorPosition(editor.text().size()); QKeyEvent deadCircumflex(QEvent::KeyPress, Qt::Key_Dead_Circumflex, Qt::NoModifier); QApplication::sendEvent(&editor, &deadCircumflex); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("s") + MathDsl::Pow2); editor.setText(QStringLiteral("s")); editor.setCursorPosition(editor.text().size()); QList imeAttrs; QInputMethodEvent imeWithCaretPreedit(QString::fromUtf8("ˆ"), imeAttrs); QApplication::sendEvent(&editor, &imeWithCaretPreedit); QInputMethodEvent imeDigitCommit(QString(), imeAttrs); imeDigitCommit.setCommitString(QStringLiteral("2")); QApplication::sendEvent(&editor, &imeDigitCommit); QCOMPARE(editor.document()->toRawText(), QStringLiteral("s") + MathDsl::Pow2); editor.setText(QStringLiteral("s") + MathDsl::Pow2); editor.setCursorPosition(editor.text().size()); QInputMethodEvent imeCaretCommit(QString(), imeAttrs); imeCaretCommit.setCommitString(QStringLiteral("^")); QApplication::sendEvent(&editor, &imeCaretCommit); QCOMPARE(editor.document()->toRawText(), QStringLiteral("s") + MathDsl::Pow2); editor.setText(QStringLiteral("s") + MathDsl::Pow2); editor.setCursorPosition(editor.text().size()); QInputMethodEvent imeCaretPreeditAfterSup(QString::fromUtf8("ˆ"), imeAttrs); QApplication::sendEvent(&editor, &imeCaretPreeditAfterSup); QInputMethodEvent imePowNegCommit(QString(), imeAttrs); imePowNegCommit.setCommitString(QString(MathDsl::PowNeg)); QApplication::sendEvent(&editor, &imePowNegCommit); QCOMPARE(editor.document()->toRawText(), QStringLiteral("s") + MathDsl::Pow2); } void TestEditorUi::keeps_scientific_notation_exponent_minus_unwrapped() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1e")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Minus, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1e") + QString(MathDsl::SubOp)); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1e") + QString(MathDsl::SubOp) + QStringLiteral("2")); } void TestEditorUi::blocks_shift_operator_tail_after_non_plus_operator() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("foo -")); editor.setCursorPosition(editor.text().size()); QKeyEvent lessByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral("<")); QApplication::sendEvent(&editor, &lessByText); QCOMPARE(editor.text(), QStringLiteral("foo ") + QString(MathDsl::SubOp)); editor.setText(QStringLiteral("foo /")); editor.setCursorPosition(editor.text().size()); QKeyEvent greaterByText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QStringLiteral(">")); QApplication::sendEvent(&editor, &greaterByText); QCOMPARE(editor.text(), QStringLiteral("foo /")); } void TestEditorUi::rewrites_superscript_exponent_for_radix_and_inserts_mul_space_globally() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2 ")); editor.setText(QString::fromUtf8("piâ�´")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Comma, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("pi^(4.)")); QCOMPARE(editor.textCursor().position(), editor.document()->toRawText().size() - 1); editor.setText(QString::fromUtf8("piâ�´")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("pi^(4.)")); QCOMPARE(editor.textCursor().position(), editor.document()->toRawText().size() - 1); editor.setText(QString::fromUtf8("piâ�´")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("piâ�´ ")); editor.setText(QString::fromUtf8("2²")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QString::fromUtf8("2² ")); editor.setText(QString::fromUtf8("piâ�´")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); QVERIFY2(!editor.document()->toRawText().contains(QLatin1Char('^')), qPrintable(QStringLiteral("after first *: ") + editor.document()->toRawText())); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); QVERIFY2(!editor.document()->toRawText().contains(QLatin1Char('^')), qPrintable(editor.document()->toRawText())); } void TestEditorUi::typing_asterisk_after_superscript_power_keeps_explicit_multiplication() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString multiply = QString(MathDsl::MulCrossWrapSp) + QString(MathDsl::MulCrossOp) + QString(MathDsl::MulCrossWrapSp); editor.setText(QStringLiteral("2") + multiply + QStringLiteral("3") + multiply + QStringLiteral("10") + multiply + QStringLiteral("10") + QString(MathDsl::Pow2)); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Asterisk, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("2") + multiply + QStringLiteral("3") + multiply + QStringLiteral("10") + multiply + QStringLiteral("10") + QString(MathDsl::Pow2) + multiply); QVERIFY(!editor.document()->toRawText().contains(MathDsl::MulDotOp)); } void TestEditorUi::auto_inserts_zero_before_dot_in_configured_contexts() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const auto sendTextKey = [&editor](const QString& s) { QKeyEvent byText(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, s); QApplication::sendEvent(&editor, &byText); }; editor.setText(QString()); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("0.")); editor.setText(QString()); editor.setCursorPosition(editor.text().size()); sendTextKey(QStringLiteral(".")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("0.")); editor.setText(QStringLiteral("1 + ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1 + 0.")); editor.setText(QStringLiteral("1 + ")); editor.setCursorPosition(editor.text().size()); sendTextKey(QStringLiteral(".")); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1 + 0.")); editor.setText(QStringLiteral(" ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral(" 0.")); editor.setText(QStringLiteral("1 × ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1 × 0.")); editor.setText(QStringLiteral("1 − ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1 − 0.")); editor.setText(QStringLiteral("1 / ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1 / 0.")); editor.setText(QStringLiteral(" ( ) ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral(" ( ) × 0.")); editor.setText(QStringLiteral("[x] ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("[x] × 0.")); editor.setText(QStringLiteral("pi")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("pi × 0.")); editor.setText(QStringLiteral("pi ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Comma, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("pi × 0.")); editor.setText(QStringLiteral("12")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("12.")); editor.setText(QStringLiteral("0,")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Comma, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("0,")); } void TestEditorUi::preserves_comment_text_during_input_data() { QTest::addColumn("comment"); QTest::newRow("multiplication") << QStringLiteral("2*2"); QTest::newRow("expression-aliases") << QStringLiteral("pi sqrt(4) cbrt(8) summation(k) 2/3-1 'quoted' \"text\" Ω μ º ð�›‘"); QTest::newRow("units-and-conversions") << QStringLiteral("10000 [m * s^2] -> [km] 2*[m] ? pi"); QTest::newRow("unfinished-syntax") << QStringLiteral("[sqrt(2^ + + ^^ --"); QTest::newRow("spacing") << QStringLiteral("2*2 pi\t10000 [m/s]"); } void TestEditorUi::preserves_comment_text_during_input() { QFETCH(QString, comment); const QString prefix = QStringLiteral("examplevar = 2*2"); const QString suffix = QStringLiteral(" ? ") + comment; const QString expression = prefix + suffix; Session session; QCOMPARE(session.evaluator()->autoFix(QStringLiteral("4") + suffix), QStringLiteral("4") + suffix); QCOMPARE(EditorUtils::normalizeExpressionOperators(expression), EditorUtils::normalizeExpressionOperators(prefix) + suffix); QCOMPARE(EditorUtils::normalizeExpressionOperatorsForEditorInput(expression), EditorUtils::normalizeExpressionOperatorsForEditorInput(prefix) + suffix); Editor editor; editor.setText(expression); QCOMPARE(editor.text(), EditorUtils::normalizeExpressionOperatorsForEditorInput(prefix) + suffix); editor.setText(QStringLiteral("4 ? ")); editor.setCursorPosition(editor.text().size()); editor.insert(comment); QCOMPARE(editor.text(), QStringLiteral("4 ? ") + comment); const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([&]() { QApplication::clipboard()->setText(oldClipboard); }); editor.setText(QStringLiteral("4 ? ")); editor.setCursorPosition(editor.text().size()); QApplication::clipboard()->setText(comment); editor.paste(); QCOMPARE(editor.text(), QStringLiteral("4 ? ") + comment); editor.setText(QStringLiteral("4 ? ")); editor.setCursorPosition(editor.text().size()); QInputMethodEvent commit; commit.setCommitString(comment); QApplication::sendEvent(&editor, &commit); QCOMPARE(editor.text(), QStringLiteral("4 ? ") + comment); } void TestEditorUi::normalizes_only_expression_text_when_replacing_comment_selection() { Editor editor; editor.setText(QStringLiteral("4 ? old")); QTextCursor cursor = editor.textCursor(); cursor.setPosition(4); cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); editor.insert(QStringLiteral("2*2")); QCOMPARE(editor.text(), QStringLiteral("4 ? 2*2")); cursor.setPosition(2); cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); editor.insert(QStringLiteral("*2 ? 3*3")); QCOMPARE(editor.text(), QStringLiteral("4 ×2 ? 3*3")); } void TestEditorUi::allows_unrestricted_typing_inside_question_comment_context() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1 ? pi")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Period, Qt::NoModifier); QTest::keyClick(&editor, Qt::Key_Comma, Qt::NoModifier); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QTest::keyClick(&editor, Qt::Key_Space, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("1 ? pi., ")); } void TestEditorUi::allows_currency_symbols_after_operators() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("$123 + ")); editor.setCursorPosition(editor.text().size()); QTest::keyClick(&editor, Qt::Key_Dollar, Qt::NoModifier); QCOMPARE(editor.document()->toRawText(), QStringLiteral("$123 + $")); } void TestEditorUi::blocks_dead_circumflex_key_after_existing_caret() { // State: "2^". // Action: send dead-circumflex key press. // Expected: event is consumed; no duplicate caret. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2^")); editor.setCursorPosition(editor.text().size()); QKeyEvent deadCircumflex(QEvent::KeyPress, Qt::Key_Dead_Circumflex, Qt::NoModifier); QApplication::sendEvent(&editor, &deadCircumflex); QCOMPARE(editor.text(), QStringLiteral("2^")); } void TestEditorUi::blocks_dead_circumflex_key_after_multiplication_operator() { // State: "3 × ". // Action: send dead-circumflex key press. // Expected: event is consumed; no caret is inserted. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("3") + QString(MathDsl::MulCrossOp) + QStringLiteral(" ")); editor.setCursorPosition(editor.text().size()); QKeyEvent deadCircumflex(QEvent::KeyPress, Qt::Key_Dead_Circumflex, Qt::NoModifier); QApplication::sendEvent(&editor, &deadCircumflex); QCOMPARE(editor.text(), QStringLiteral("3") + QString(MathDsl::MulCrossOp) + QStringLiteral(" ")); } void TestEditorUi::blocks_regular_caret_after_multiplication_operator() { // State: "3 × ". // Action: type regular caret '^'. // Expected: caret is ignored. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("3") + QString(MathDsl::MulCrossOp) + QStringLiteral(" ")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QStringLiteral("^")); QCOMPARE(editor.text(), QStringLiteral("3") + QString(MathDsl::MulCrossOp) + QStringLiteral(" ")); } void TestEditorUi::blocks_ime_preedit_caret_echo_after_existing_caret() { // State: "2^". // Action: send IME preedit caret echo. // Expected: preedit echo is ignored. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2^")); editor.setCursorPosition(editor.text().size()); QList attributes; QInputMethodEvent imeEvent(QString::fromUtf8("ˆ"), attributes); QApplication::sendEvent(&editor, &imeEvent); QCOMPARE(editor.text(), QStringLiteral("2^")); } void TestEditorUi::blocks_ime_commit_caret_after_existing_caret() { // State: "2^". // Action: send IME commit "^". // Expected: committed caret is ignored. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2^")); editor.setCursorPosition(editor.text().size()); QList attributes; QInputMethodEvent imeEvent(QString(), attributes); imeEvent.setCommitString(QStringLiteral("^")); QApplication::sendEvent(&editor, &imeEvent); QCOMPARE(editor.text(), QStringLiteral("2^")); } void TestEditorUi::blocks_ime_commit_caret_after_multiplication_operator() { // State: "3 × ". // Action: send IME commit "^". // Expected: committed caret is ignored. Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("3") + QString(MathDsl::MulCrossOp) + QStringLiteral(" ")); editor.setCursorPosition(editor.text().size()); QList attributes; QInputMethodEvent imeEvent(QString(), attributes); imeEvent.setCommitString(QStringLiteral("^")); QApplication::sendEvent(&editor, &imeEvent); QCOMPARE(editor.text(), QStringLiteral("3") + QString(MathDsl::MulCrossOp) + QStringLiteral(" ")); } void TestEditorUi::finds_completion_keyword_after_superscript_power() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QString::fromUtf8("pi²c")); editor.setCursorPosition(editor.text().size()); const QString keyword = editor.getKeyword(); QVERIFY(!keyword.isEmpty()); QVERIFY(keyword.startsWith(QLatin1Char('c'))); } void TestEditorUi::completes_replacing_trailing_identifier_after_superscript_power() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QString::fromUtf8("pi²") + QString(MathDsl::MulDotOp) + QStringLiteral("c")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("cos: Built-in function")))); QCOMPARE( editor.text(), QString::fromUtf8("pi²") + QString(MathDsl::MulDotOp) + QStringLiteral("cos()")); } void TestEditorUi::completes_identifier_immediately_after_digit() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("3c")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QVERIFY(!s_popupSymbolForIdentifier(popup, QStringLiteral("cos")).isEmpty()); popup->hide(); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("cos: Built-in function")))); QCOMPARE(editor.text(), QStringLiteral("3cos()")); } void TestEditorUi::completes_pi_identifier_as_pi_symbol() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("p")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("pi: Archimedes' constant Pi")))); QCOMPARE(editor.text(), QString::fromUtf8("Ï€")); } void TestEditorUi::accepts_degree_alias_in_unit_brackets_and_normalizes_to_degree_sign() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("100 [")); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, QString::fromUtf8("ºC")); QCOMPARE(editor.text(), QString::fromUtf8("100 [°C")); // QTest::keyClicks() rejects U+02DA in qasciikey, so verify via setText(). editor.setText(QString::fromUtf8("100 [ËšC")); QCOMPARE(editor.text(), QString::fromUtf8("100 [°C")); } void TestEditorUi::offers_unit_completion_for_degree_symbol_in_unit_context() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QString::fromUtf8("100 [°")); editor.setCursorPosition(editor.text().size()); const auto localizedChoice = [](const QString& identifier, UnitId id) { return QStringLiteral("%1:%2").arg(identifier, tr(unitLocalizedName(id))); }; const QStringList degreeChoices = editor.matchFragment(QString::fromUtf8("°"), true); QVERIFY(!degreeChoices.isEmpty()); QVERIFY(degreeChoices.contains(localizedChoice(QString::fromUtf8("°"), UnitId::Degree))); QVERIFY(degreeChoices.contains(localizedChoice(QString::fromUtf8("°C"), UnitId::DegreeCelsius))); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("u:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [u")); } void TestEditorUi::matches_micro_units_when_typing_u_in_unit_context() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const auto localizedChoice = [](const QString& identifier) { return QStringLiteral("%1:%2").arg( identifier, tr(unitLocalizedIdentifierName(identifier).toUtf8().constData())); }; const QStringList uChoices = editor.matchFragment(QStringLiteral("u"), true); QVERIFY(uChoices.contains(localizedChoice(QString::fromUtf8("µm")))); QVERIFY(uChoices.contains(localizedChoice(QString::fromUtf8("µs")))); QVERIFY(uChoices.contains(localizedChoice(QString::fromUtf8("µas")))); QVERIFY(!uChoices.contains(localizedChoice(QStringLiteral("uas")))); } void TestEditorUi::unit_context_completion_excludes_user_variables() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Session session; Evaluator* evaluator = session.evaluator(); editor.setSession(&session); evaluator->setVariable(QStringLiteral("foo"), Quantity(3)); const QStringList unitChoices = editor.matchFragment(QStringLiteral("fo"), true); for (const QString& choice : unitChoices) QVERIFY2(!choice.startsWith(QStringLiteral("foo:")), qPrintable(choice)); evaluator->unsetVariable(QStringLiteral("foo")); } void TestEditorUi::unit_context_completion_excludes_built_in_functions() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QStringList choices = editor.matchFragment(QStringLiteral("si"), true); for (const QString& choice : choices) QVERIFY2(!choice.startsWith(QStringLiteral("sin:")), qPrintable(choice)); } void TestEditorUi::unit_context_completion_excludes_user_functions() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Session session; Evaluator* evaluator = session.evaluator(); editor.setSession(&session); evaluator->setUserFunction(UserFunction( QStringLiteral("foof"), QStringList() << QStringLiteral("x"), QStringLiteral("x"))); const QStringList choices = editor.matchFragment(QStringLiteral("foo"), true); for (const QString& choice : choices) QVERIFY2(!choice.startsWith(QStringLiteral("foof:")), qPrintable(choice)); evaluator->unsetUserFunction(QStringLiteral("foof")); } void TestEditorUi::unit_context_completion_excludes_built_in_variables() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QStringList ansChoices = editor.matchFragment(QStringLiteral("an"), true); const QStringList eChoices = editor.matchFragment(QStringLiteral("e"), true); const QStringList piChoices = editor.matchFragment(QStringLiteral("pi"), true); for (const QString& choice : ansChoices) QVERIFY2(!choice.startsWith(QStringLiteral("ans:")), qPrintable(choice)); for (const QString& choice : eChoices) QVERIFY2(!choice.startsWith(QStringLiteral("e:")), qPrintable(choice)); for (const QString& choice : piChoices) QVERIFY2(!choice.startsWith(QStringLiteral("pi:")), qPrintable(choice)); } void TestEditorUi::unit_context_completion_includes_angle_units_and_long_forms() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const auto localizedChoice = [](const QString& identifier, UnitId id) { return QStringLiteral("%1:%2").arg(identifier, tr(unitLocalizedName(id))); }; const auto descriptionFor = [](const QStringList& choices, const QString& identifier) { for (const QString& choice : choices) { if (choice.startsWith(identifier + QStringLiteral(":"))) return choice.mid(identifier.size() + 1); } return QString(); }; const QStringList radChoices = editor.matchFragment(QStringLiteral("rad"), true); QVERIFY(radChoices.contains(localizedChoice(QStringLiteral("rad"), UnitId::Radian))); QVERIFY(radChoices.contains(localizedChoice(QStringLiteral("radian"), UnitId::Radian))); const QStringList arcChoices = editor.matchFragment(QStringLiteral("arc"), true); QVERIFY(arcChoices.contains(localizedChoice(QStringLiteral("arcminute"), UnitId::Arcminute))); QVERIFY(arcChoices.contains(localizedChoice(QStringLiteral("arcsecond"), UnitId::Arcsecond))); QVERIFY(arcChoices.contains(localizedChoice(QStringLiteral("arcsec"), UnitId::Arcsecond))); const QStringList masChoices = editor.matchFragment(QStringLiteral("mas"), true); QVERIFY(masChoices.contains(localizedChoice(QStringLiteral("mas"), UnitId::Milliarcsecond))); const QStringList uasChoices = editor.matchFragment(QStringLiteral("u"), true); QVERIFY(uasChoices.contains(localizedChoice(QString::fromUtf8("µas"), UnitId::Microarcsecond))); const QStringList milliArcChoices = editor.matchFragment(QStringLiteral("milliarc"), true); QVERIFY(milliArcChoices.contains(localizedChoice(QStringLiteral("milliarcsecond"), UnitId::Milliarcsecond))); const QStringList microArcChoices = editor.matchFragment(QStringLiteral("microarc"), true); QVERIFY(microArcChoices.contains(localizedChoice(QStringLiteral("microarcsecond"), UnitId::Microarcsecond))); const QStringList turnChoices = editor.matchFragment(QStringLiteral("turn"), true); QVERIFY(turnChoices.contains(localizedChoice(QStringLiteral("turn"), UnitId::Turn))); const QStringList gradChoices = editor.matchFragment(QStringLiteral("grad"), true); QVERIFY(gradChoices.contains(localizedChoice(QStringLiteral("gradian"), UnitId::Gradian))); const QStringList gonChoices = editor.matchFragment(QStringLiteral("gon"), true); QVERIFY(gonChoices.contains(localizedChoice(QStringLiteral("gon"), UnitId::Gradian))); const QStringList aChoices = editor.matchFragment(QStringLiteral("a"), true); const QString acDescription = descriptionFor(aChoices, QStringLiteral("ac")); const QString aCDescription = descriptionFor(aChoices, QStringLiteral("aC")); QVERIFY(!acDescription.isEmpty()); QVERIFY(!aCDescription.isEmpty()); QCOMPARE(acDescription, QStringLiteral("acre")); QVERIFY(aCDescription != QStringLiteral("acre")); QVERIFY(aCDescription != tr("Unit")); } void TestEditorUi::unit_context_completion_includes_small_positive_si_prefixed_symbols() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const auto hasCompletionIdentifier = [](const QStringList& choices, const QString& identifier) { for (const QString& choice : choices) { if (choice.startsWith(identifier + QStringLiteral(":"))) return true; } return false; }; const QStringList choices = editor.matchFragment(QStringLiteral("da"), true); QVERIFY(hasCompletionIdentifier(choices, QStringLiteral("dag"))); QVERIFY(hasCompletionIdentifier(choices, QStringLiteral("daL"))); QVERIFY(hasCompletionIdentifier(choices, QStringLiteral("dam"))); QVERIFY(hasCompletionIdentifier(choices, QStringLiteral("daN"))); QVERIFY(hasCompletionIdentifier(choices, QStringLiteral("daPa"))); } void TestEditorUi::unit_context_completion_excludes_prefixed_square_and_cubic_metre() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const auto hasCompletionIdentifier = [](const QStringList& choices, const QString& identifier) { for (const QString& choice : choices) { if (choice.startsWith(identifier + QStringLiteral(":"))) return true; } return false; }; const QStringList choices = editor.matchFragment(QStringLiteral("deci"), true); QVERIFY(!hasCompletionIdentifier(choices, QStringLiteral("decisquare_metre"))); QVERIFY(!hasCompletionIdentifier(choices, QStringLiteral("decicubic_metre"))); } void TestEditorUi::completes_binary_prefixed_information_unit_to_short_form_in_unit_context() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1 [meb")); editor.setCursorPosition(editor.text().size()); const QStringList mebChoices = editor.matchFragment(QStringLiteral("meb"), true); const QString mebibyteChoice = QStringLiteral("%1:%2").arg( QStringLiteral("mebibyte"), tr(unitLocalizedIdentifierName(QStringLiteral("mebibyte")).toUtf8().constData())); QVERIFY(mebChoices.contains(mebibyteChoice)); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("mebibyte:Unit")))); QCOMPARE(editor.text(), QStringLiteral("1 [MiB")); } void TestEditorUi::completes_day_unit_to_short_form_in_unit_context() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1 [d")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("day:Unit")))); QCOMPARE(editor.text(), QStringLiteral("1 [d")); } void TestEditorUi::completes_hour_unit_to_short_form_in_unit_context() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1 [h")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("hour:Unit")))); QCOMPARE(editor.text(), QStringLiteral("1 [h")); } void TestEditorUi::completes_affine_temperature_units_in_unit_context() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("100 [c")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("degree_celsius:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°C")); editor.setText(QStringLiteral("100 [f")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("degree_fahrenheit:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°F")); editor.setText(QString::fromUtf8("100 [º")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QString::fromUtf8("ºC:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°C")); editor.setText(QString::fromUtf8("100 [Ëš")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QString::fromUtf8("ËšC:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°C")); editor.setText(QString::fromUtf8("100 [Ëš")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QString::fromUtf8("ËšF:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°F")); editor.setText(QStringLiteral("100 [deg")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("degC:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°C")); editor.setText(QStringLiteral("100 [ce")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("Cel:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°C")); editor.setText(QStringLiteral("100 [deg")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("degF:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°F")); editor.setText(QStringLiteral("100 [fa")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("Fah:Unit")))); QCOMPARE(editor.text(), QString::fromUtf8("100 [°F")); } void TestEditorUi::completes_arc_units_in_unit_context() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1 [arc")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("arcminute:Unit")))); QVERIFY(editor.text() != QStringLiteral("1 [arc")); editor.setText(QStringLiteral("1 [arc")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "autoComplete", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("arcsecond:Unit")))); QVERIFY(editor.text() != QStringLiteral("1 [arc")); } void TestEditorUi::tooltip_does_not_duplicate_degree_symbol_for_explicit_angle_conversion() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; settings->angleUnit = 'd'; settings->resultFormat = 'f'; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1 [rev] -> [°]")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QCOMPARE(message, QString::fromUtf8("Current result:
    360°")); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_does_not_append_angle_mode_symbol_after_explicit_arcsecond_unit() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; settings->angleUnit = 'd'; settings->resultFormat = 'f'; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1 [rev] -> [arcsec]")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QVERIFY(message.contains(QString(UnicodeChars::DoublePrime))); QVERIFY(!message.contains(QString(UnicodeChars::DoublePrime) + UnicodeChars::DegreeSign)); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_formats_arcminute_and_arcsecond_results_without_expression() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; settings->angleUnit = 'r'; settings->resultFormat = 'f'; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1 [arcmin]")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString arcminuteMessage = spy.takeLast().at(0).toString(); QVERIFY2(arcminuteMessage.contains(QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r')), qPrintable(QStringLiteral("Arcminute tooltip: %1").arg(arcminuteMessage))); QVERIFY(!arcminuteMessage.contains(UnicodeChars::Prime)); QVERIFY(!arcminuteMessage.contains(QLatin1Char('='))); editor.setText(QStringLiteral("1 [arcsec]")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString arcsecondMessage = spy.takeLast().at(0).toString(); QVERIFY2(arcsecondMessage.contains(QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r')), qPrintable(QStringLiteral("Arcsecond tooltip: %1").arg(arcsecondMessage))); QVERIFY(!arcsecondMessage.contains(UnicodeChars::DoublePrime)); QVERIFY(!arcsecondMessage.contains(QLatin1Char('='))); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_rewrites_composite_canonical_angle_symbols_to_aliases() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; settings->angleUnit = 'r'; settings->resultFormat = 'f'; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QString::fromUtf8("1 [rad/m] -> [″/m]")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString arcsecondMessage = spy.takeLast().at(0).toString(); QVERIFY2(arcsecondMessage.contains(Units::arcsecondAliasSymbol()), qPrintable(QStringLiteral("Arcsecond composite tooltip: %1").arg(arcsecondMessage))); QVERIFY2(!arcsecondMessage.contains(QString::fromUtf8("″/m")), qPrintable(QStringLiteral("Arcsecond composite tooltip: %1").arg(arcsecondMessage))); editor.setText(QString::fromUtf8("1 [rad/m] -> [′/m]")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString arcminuteMessage = spy.takeLast().at(0).toString(); QVERIFY2(arcminuteMessage.contains(Units::arcminuteAliasSymbol()), qPrintable(QStringLiteral("Arcminute composite tooltip: %1").arg(arcminuteMessage))); QVERIFY2(!arcminuteMessage.contains(QString::fromUtf8("′/m")), qPrintable(QStringLiteral("Arcminute composite tooltip: %1").arg(arcminuteMessage))); editor.setText(QString::fromUtf8("1 [rad/m] -> [°/m]")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString degreeMessage = spy.takeLast().at(0).toString(); QVERIFY2(degreeMessage.contains(Units::degreeAliasSymbol()), qPrintable(QStringLiteral("Degree composite tooltip: %1").arg(degreeMessage))); QVERIFY2(!degreeMessage.contains(QString::fromUtf8("°/m")), qPrintable(QStringLiteral("Degree composite tooltip: %1").arg(degreeMessage))); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_shows_radian_suffix_for_negative_sexagesimal_literal() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; settings->angleUnit = 'r'; settings->resultFormat = 'f'; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QString::fromUtf8("−57°17′44.80624709635515647336″")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QVERIFY(message.contains(QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r'))); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_trig_output_does_not_append_angle_mode_suffix() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; settings->resultFormat = 'f'; struct Case { char angleUnit; QString forbiddenSuffix; }; const QList cases = { {'r', QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r')}, {'d', Units::angleModeUnitSymbol('d')} }; for (const Case& c : cases) { settings->angleUnit = c.angleUnit; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QString::fromUtf8("cos(180°)")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QString normalizedMessage = message; normalizedMessage.replace(QString(MathDsl::SubOp), QString(MathDsl::SubOpAl1)); QCOMPARE(normalizedMessage, QStringLiteral("Current result:
    -1")); QVERIFY2(!message.contains(QStringLiteral("cos(")), qPrintable(QStringLiteral("Expected scalar trig result, got: %1").arg(message))); const QStringList lines = normalizedMessage.split(QStringLiteral("
    ")); QVERIFY2(!lines.isEmpty(), qPrintable(QStringLiteral("Unexpected empty tooltip message: %1").arg(message))); const QString resultLine = lines.last(); QVERIFY2(!resultLine.contains(c.forbiddenSuffix), qPrintable(QStringLiteral("Unexpected angle suffix in tooltip result line: %1").arg(message))); QVERIFY(!resultLine.contains(QString(MathDsl::UnitStart))); QVERIFY(!resultLine.contains(QString(MathDsl::UnitEnd))); } settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_shows_only_result_for_non_trig_sexagesimal_expression() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; settings->angleUnit = 'd'; settings->resultFormat = 'f'; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); const QString expression = QString::fromUtf8("round(2.8°) + round(2.8°) + round(2.8°)"); editor.setText(expression); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QCOMPARE(message, QString::fromUtf8("Current result:
    9°")); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_shows_only_result_for_repeated_trig_with_degree_sign() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; const bool oldSimplify = settings->simplifyResultExpressions; settings->angleUnit = 'd'; settings->resultFormat = 'f'; settings->simplifyResultExpressions = true; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); const QString expression = QString::fromUtf8( "cos(180°) + cos(180°) + cos(180°) + cos(180°)"); editor.setText(expression); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QString normalizedMessage = message; normalizedMessage.replace(QString(MathDsl::SubOp), QString(MathDsl::SubOpAl1)); QCOMPARE(normalizedMessage, QStringLiteral("Current result:
    -4")); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; settings->simplifyResultExpressions = oldSimplify; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_shows_only_result_for_mixed_revolution_aliases() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; const bool oldSimplify = settings->simplifyResultExpressions; settings->angleUnit = 'd'; settings->resultFormat = 'f'; settings->simplifyResultExpressions = true; Evaluator::instance()->initializeAngleUnits(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); const QString expression = QString::fromUtf8( "cos(180[rev]) + cos(180[rev]) + cos(180[rev]) + cos(180 [revolution])"); editor.setText(expression); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QCOMPARE(message, QStringLiteral("Current result:
    4")); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; settings->simplifyResultExpressions = oldSimplify; Evaluator::instance()->initializeAngleUnits(); } void TestEditorUi::tooltip_shows_only_result_for_literal_number_products() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldResultFormat = settings->resultFormat; const bool oldSimplify = settings->simplifyResultExpressions; settings->resultFormat = 'f'; settings->simplifyResultExpressions = true; QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("pi*2^(-2)*pi+3*4*3")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); const QStringList lines = message.split(QStringLiteral("
    ")); QCOMPARE(lines.size(), 2); QCOMPARE(lines.first(), QStringLiteral("Current result:")); QVERIFY(lines.last().startsWith(QStringLiteral("38.467"))); QVERIFY(!message.contains(QLatin1Char('='))); QSignalSpy interpretedSpy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("pi*2^(-2)*pi+3^2*4")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!interpretedSpy.isEmpty()); const QString interpretedMessage = interpretedSpy.takeLast().at(0).toString(); QCOMPARE(interpretedMessage, message); settings->resultFormat = oldResultFormat; settings->simplifyResultExpressions = oldSimplify; } void TestEditorUi::tooltip_shows_only_result_data() { QTest::addColumn("selection"); QTest::addColumn("simplify"); QTest::addColumn("extraResult"); QTest::addColumn("expression"); QTest::addColumn("expectedResult"); for (bool selection : {false, true}) { for (bool simplify : {false, true}) { const QString prefix = QStringLiteral("%1-%2") .arg(selection ? QStringLiteral("selection") : QStringLiteral("current"), simplify ? QStringLiteral("simplify") : QStringLiteral("plain")); QTest::newRow(qPrintable(prefix + QStringLiteral("-complete"))) << selection << simplify << false << QStringLiteral("1+24") << QStringLiteral("25"); QTest::newRow(qPrintable(prefix + QStringLiteral("-incomplete"))) << selection << simplify << false << QStringLiteral("1+24+") << QStringLiteral("25"); QTest::newRow(qPrintable(prefix + QStringLiteral("-extra-result"))) << selection << simplify << true << QStringLiteral("1+24") << QString::fromUtf8("25
    2.5 × 10¹"); } } } void TestEditorUi::tooltip_shows_only_result() { QFETCH(bool, selection); QFETCH(bool, simplify); QFETCH(bool, extraResult); QFETCH(QString, expression); QFETCH(QString, expectedResult); Settings* settings = Settings::instance(); settings->resultFormat = 'f'; settings->resultPrecision = -1; settings->simplifyResultExpressions = simplify; settings->multipleResultLinesEnabled = extraResult; settings->secondaryResultEnabled = extraResult; settings->alternativeResultFormat = 'e'; settings->secondaryResultPrecision = -1; Editor editor; editor.setText(expression); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); if (selection) editor.autoCalcSelection(expression); else editor.refreshAutoCalc(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); const QString title = selection ? QStringLiteral("Selection result:") : QStringLiteral("Current result:"); QCOMPARE(message, title + QStringLiteral("
    ") + expectedResult); } void TestEditorUi::tooltip_keeps_quantsp_before_degree_celsius() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldResultFormat = settings->resultFormat; settings->resultFormat = 'f'; QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QString::fromUtf8("77 [°F] -> [°C]")); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); const QString expected = QStringLiteral("Current result:
    25") + QString(MathDsl::QuantSp) + QString::fromUtf8("°C"); QCOMPARE(message, expected); settings->resultFormat = oldResultFormat; } void TestEditorUi::tooltip_handles_affine_temperature_units_without_arrow_and_with_conversion() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); Settings* settings = Settings::instance(); const char oldResultFormat = settings->resultFormat; settings->resultFormat = 'f'; struct Case { QString expression; QString expected; }; const QList cases = { {QString::fromUtf8("100 [°C]"), QStringLiteral("100") + QString(MathDsl::QuantSp) + QString::fromUtf8("°C")}, {QString::fromUtf8("203 [°F]"), QStringLiteral("203") + QString(MathDsl::QuantSp) + QString::fromUtf8("°F")}, {QString::fromUtf8("1 [K] -> [°C]"), QString(MathDsl::SubOp) + QStringLiteral("272.15") + QString(MathDsl::QuantSp) + QString::fromUtf8("°C")}, {QString::fromUtf8("1 [K] -> [°F]"), QString(MathDsl::SubOp) + QStringLiteral("457.87") + QString(MathDsl::QuantSp) + QString::fromUtf8("°F")} }; for (const Case& c : cases) { QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(c.expression); editor.setCursorPosition(editor.text().size()); editor.refreshAutoCalc(); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QCOMPARE(message, QStringLiteral("Current result:
    ") + c.expected); } settings->resultFormat = oldResultFormat; } void TestEditorUi::tooltip_shows_selection_result_when_selecting_with_shift_arrows() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1+24")); editor.setCursorPosition(editor.text().size()); QCoreApplication::processEvents(); QTest::keyClick(&editor, Qt::Key_Left, Qt::ShiftModifier); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QVERIFY2(message.contains(QStringLiteral("Selection result:")), qPrintable(QStringLiteral("Expected selection result message, got: %1").arg(message))); QCOMPARE(message, QStringLiteral("Selection result:
    4")); } void TestEditorUi::tooltip_shows_selection_result_when_selecting_all_with_keyboard_shortcut() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1+24")); editor.setCursorPosition(editor.text().size()); QCoreApplication::processEvents(); spy.clear(); const QList bindings = QKeySequence::keyBindings(QKeySequence::SelectAll); QVERIFY(!bindings.isEmpty()); const QKeyCombination selectAll = bindings.first()[0]; QTest::keyClick(&editor, selectAll.key(), selectAll.keyboardModifiers()); QCoreApplication::processEvents(); QVERIFY2(editor.textCursor().hasSelection(), qPrintable(QStringLiteral("Expected select-all selection, got cursor position %1") .arg(editor.textCursor().position()))); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QVERIFY2(message.contains(QStringLiteral("Selection result:")), qPrintable(QStringLiteral("Expected selection result message, got: %1").arg(message))); QCOMPARE(message, QStringLiteral("Selection result:
    25")); } void TestEditorUi::tooltip_shows_selection_result_when_selecting_with_mouse() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1+24")); editor.setCursorPosition(editor.text().size()); QCoreApplication::processEvents(); spy.clear(); QTextCursor cursor = editor.textCursor(); cursor.setPosition(3); const QPoint selectionStart = editor.cursorRect(cursor).center(); cursor.setPosition(4); const QPoint selectionEnd = editor.cursorRect(cursor).center(); QTest::mousePress(editor.viewport(), Qt::LeftButton, Qt::NoModifier, selectionStart); QTest::mouseMove(editor.viewport(), selectionEnd); QCoreApplication::processEvents(); QVERIFY(spy.isEmpty()); QTest::mouseRelease(editor.viewport(), Qt::LeftButton, Qt::NoModifier, selectionEnd); QCoreApplication::processEvents(); QVERIFY2(editor.textCursor().hasSelection(), qPrintable(QStringLiteral("Expected mouse selection, got cursor position %1") .arg(editor.textCursor().position()))); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QVERIFY2(message.contains(QStringLiteral("Selection result:")), qPrintable(QStringLiteral("Expected selection result message, got: %1").arg(message))); QCOMPARE(message, QStringLiteral("Selection result:
    4")); } void TestEditorUi::tooltip_does_not_refresh_current_result_on_caret_arrow_move() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1+24")); editor.setCursorPosition(editor.text().size()); QCoreApplication::processEvents(); spy.clear(); QTest::keyClick(&editor, Qt::Key_Left); QCoreApplication::processEvents(); QVERIFY2(spy.isEmpty(), qPrintable(QStringLiteral("Caret movement should not refresh the result tooltip, got: %1") .arg(spy.isEmpty() ? QString() : spy.takeLast().at(0).toString()))); } void TestEditorUi::tooltip_does_not_refresh_current_result_on_mouse_caret_reposition() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1+24")); editor.setCursorPosition(editor.text().size()); QCoreApplication::processEvents(); spy.clear(); QTextCursor cursor = editor.textCursor(); cursor.setPosition(1); const QPoint clickPosition = editor.cursorRect(cursor).center(); QTest::mouseClick(editor.viewport(), Qt::LeftButton, Qt::NoModifier, clickPosition); QCoreApplication::processEvents(); QVERIFY2(spy.isEmpty(), qPrintable(QStringLiteral("Mouse caret movement should not refresh the result tooltip, got: %1") .arg(spy.isEmpty() ? QString() : spy.takeLast().at(0).toString()))); } void TestEditorUi::tooltip_refreshes_current_result_on_char_deletion() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QSignalSpy spy(&editor, SIGNAL(autoCalcMessageAvailable(const QString&))); editor.setText(QStringLiteral("1+24")); editor.setCursorPosition(editor.text().size()); QCoreApplication::processEvents(); spy.clear(); QTest::keyClick(&editor, Qt::Key_Backspace); QCoreApplication::processEvents(); QVERIFY(!spy.isEmpty()); const QString message = spy.takeLast().at(0).toString(); QVERIFY2(message.contains(QStringLiteral("Current result:")), qPrintable(QStringLiteral("Expected current result message after deletion, got: %1").arg(message))); QCOMPARE(message, QStringLiteral("Current result:
    3")); } void TestEditorUi::enter_evaluates_when_completion_popup_has_no_explicit_interaction() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString input = QStringLiteral("co"); editor.setText(input); editor.setCursorPosition(input.size()); QSignalSpy returnPressedSpy(&editor, SIGNAL(returnPressed())); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTest::keyClick(popup, Qt::Key_Return, Qt::NoModifier); QCoreApplication::processEvents(); QCOMPARE(returnPressedSpy.count(), 1); QCOMPARE(editor.text(), input); } void TestEditorUi::completion_popup_enter_respects_accept_with_enter_data() { QTest::addColumn("enabled"); QTest::addColumn("navigated"); QTest::addColumn("sendToPopup"); QTest::addColumn("key"); for (bool enabled : {false, true}) { for (bool navigated : {false, true}) { for (bool sendToPopup : {false, true}) { for (int key : {Qt::Key_Return, Qt::Key_Enter}) { const QString name = QStringLiteral("%1-%2-%3-%4") .arg(enabled ? "enabled" : "disabled") .arg(navigated ? "arrow-selection" : "first-suggestion") .arg(sendToPopup ? "popup" : "editor") .arg(key == Qt::Key_Return ? "return" : "keypad-enter"); QTest::newRow(qPrintable(name)) << enabled << navigated << sendToPopup << key; } } } } } void TestEditorUi::completion_popup_enter_respects_accept_with_enter() { QFETCH(bool, enabled); QFETCH(bool, navigated); QFETCH(bool, sendToPopup); QFETCH(int, key); Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("cos")); editor.setCursorPosition(editor.text().size()); QSignalSpy returnPressedSpy(&editor, &Editor::returnPressed); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QWidget* target = sendToPopup ? static_cast(popup) : &editor; if (navigated) QTest::keyClick(target, Qt::Key_Down); QVERIFY(popup->currentItem()); const QString completion = popup->currentItem()->text(1) + QStringLiteral("()"); Settings::instance()->autoCompletionAcceptWithEnter = enabled; QTest::keyClick(target, Qt::Key(key)); QVERIFY(!popup->isVisible()); if (enabled || navigated) { QCOMPARE(returnPressedSpy.count(), 0); QCOMPARE(editor.text(), completion); QCOMPARE(editor.textCursor().position(), completion.size() - 1); QTRY_VERIFY(s_editorOrViewportHasFocus(&editor)); QTest::keyClick(&editor, Qt::Key(key)); QCOMPARE(returnPressedSpy.count(), 1); } else { QCOMPARE(returnPressedSpy.count(), 1); QCOMPARE(editor.text(), QStringLiteral("cos")); } } void TestEditorUi::enter_accepts_completion_for_names_and_units_data() { QTest::addColumn("input"); QTest::addColumn("expected"); QTest::addColumn("inputAdjustments"); QTest::addColumn("key"); for (bool inputAdjustments : {false, true}) { for (int key : {Qt::Key_Return, Qt::Key_Tab}) { const QByteArray prefix = QByteArray(inputAdjustments ? "adjusted-" : "raw-") + (key == Qt::Key_Return ? "enter-" : "tab-"); QTest::newRow(QByteArray(prefix + "user-variable").constData()) << QStringLiteral("entervar") << QStringLiteral("entervariable") << inputAdjustments << key; QTest::newRow(QByteArray(prefix + "user-function").constData()) << QStringLiteral("enterfun") << QStringLiteral("enterfunction()") << inputAdjustments << key; QTest::newRow(QByteArray(prefix + "unit").constData()) << QStringLiteral("[met") << QStringLiteral("[m") << inputAdjustments << key; } } } void TestEditorUi::enter_accepts_completion_for_names_and_units() { QFETCH(QString, input); QFETCH(QString, expected); QFETCH(bool, inputAdjustments); QFETCH(int, key); Settings::instance()->autoCompletionAcceptWithEnter = true; Settings::instance()->automaticInputAdjustments = inputAdjustments; Editor editor; editor.evaluator()->setVariable(QStringLiteral("entervariable"), Quantity(42)); editor.evaluator()->setUserFunction(UserFunction( QStringLiteral("enterfunction"), QStringList{QStringLiteral("x")}, QStringLiteral("x"))); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(input); editor.setCursorPosition(editor.text().size()); QSignalSpy returnPressedSpy(&editor, &Editor::returnPressed); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTest::keyClick(&editor, Qt::Key(key)); QCOMPARE(editor.text(), expected); QCOMPARE(returnPressedSpy.count(), 0); QVERIFY(!popup->isVisible()); } void TestEditorUi::enter_evaluates_without_completion_when_accept_with_enter_is_enabled() { Settings::instance()->autoCompletionAcceptWithEnter = true; Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2+2")); editor.setCursorPosition(editor.text().size()); QSignalSpy returnPressedSpy(&editor, &Editor::returnPressed); QVERIFY(!s_completionPopupTree()); QTest::keyClick(&editor, Qt::Key_Return); QCOMPARE(returnPressedSpy.count(), 1); QCOMPARE(editor.text(), QStringLiteral("2+2")); } void TestEditorUi::completion_popup_arrow_keys_change_selection() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("co")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QVERIFY(popup->topLevelItemCount() > 1); QTreeWidgetItem* initialItem = popup->currentItem(); QVERIFY(initialItem); QTest::keyClick(popup, Qt::Key_Down, Qt::NoModifier); QCoreApplication::processEvents(); QVERIFY(popup->currentItem()); QVERIFY(popup->currentItem() != initialItem); popup->hide(); } void TestEditorUi::completion_popup_tab_accepts_selected_item() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("co")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTreeWidgetItem* cosItem = nullptr; for (int i = 0; i < popup->topLevelItemCount(); ++i) { QTreeWidgetItem* item = popup->topLevelItem(i); if (item != nullptr && item->text(1) == QStringLiteral("cos")) { cosItem = item; break; } } QVERIFY(cosItem); popup->setCurrentItem(cosItem); QTest::keyClick(&editor, Qt::Key_Tab); QCoreApplication::processEvents(); QCOMPARE(editor.text(), QStringLiteral("cos()")); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&editor), 1000); } void TestEditorUi::completion_popup_closes_when_clicking_elsewhere() { QWidget container; QVBoxLayout layout(&container); Editor editor; QPushButton button(QStringLiteral("Other")); layout.addWidget(&editor); layout.addWidget(&button); container.resize(800, 400); container.show(); QVERIFY(QTest::qWaitForWindowExposed(&container)); editor.setFocus(); editor.setText(QStringLiteral("co")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTest::mouseClick(&container, Qt::LeftButton, Qt::NoModifier, QPoint(container.width() - 2, container.height() - 2)); QCoreApplication::processEvents(); QVERIFY(!popup->isVisible()); QTest::qWait(250); QVERIFY(!popup->isVisible()); popup->hide(); } void TestEditorUi::completion_popup_clicking_row_accepts_item() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("co")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTreeWidgetItem* cosItem = nullptr; for (int i = 0; i < popup->topLevelItemCount(); ++i) { QTreeWidgetItem* item = popup->topLevelItem(i); if (item != nullptr && item->text(1) == QStringLiteral("cos")) { cosItem = item; break; } } QVERIFY(cosItem); popup->scrollToItem(cosItem); const QRect itemRect = popup->visualItemRect(cosItem); QVERIFY(!itemRect.isEmpty()); QTest::mouseClick(popup->viewport(), Qt::LeftButton, Qt::NoModifier, itemRect.center()); QCoreApplication::processEvents(); QCOMPARE(editor.text(), QStringLiteral("cos()")); } void TestEditorUi::completion_popup_mouse_selection_keeps_focus_on_owning_editor() { QWidget container; QVBoxLayout layout(&container); Editor firstEditor; Editor secondEditor; layout.addWidget(&firstEditor); layout.addWidget(&secondEditor); container.show(); QVERIFY(QTest::qWaitForWindowExposed(&container)); container.activateWindow(); secondEditor.setFocus(); QCoreApplication::processEvents(); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&secondEditor), 1000); firstEditor.setFocus(); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&firstEditor), 1000); firstEditor.setText(QStringLiteral("co")); firstEditor.setCursorPosition(firstEditor.text().size()); QVERIFY(QMetaObject::invokeMethod( &firstEditor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTreeWidgetItem* cosItem = nullptr; for (int i = 0; i < popup->topLevelItemCount(); ++i) { QTreeWidgetItem* item = popup->topLevelItem(i); if (item != nullptr && item->text(1) == QStringLiteral("cos")) { cosItem = item; break; } } QVERIFY(cosItem); popup->scrollToItem(cosItem); const QRect itemRect = popup->visualItemRect(cosItem); QVERIFY(!itemRect.isEmpty()); QTest::mouseClick(popup->viewport(), Qt::LeftButton, Qt::NoModifier, itemRect.center()); QCoreApplication::processEvents(); QCOMPARE(firstEditor.text(), QStringLiteral("cos()")); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&firstEditor), 1000); QVERIFY(!s_editorOrViewportHasFocus(&secondEditor)); } void TestEditorUi::completion_popup_scrollbar_click_keeps_popup_open() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("[m")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QVERIFY(popup->verticalScrollBar()->isVisible()); QTest::mouseClick(popup->verticalScrollBar(), Qt::LeftButton); QCoreApplication::processEvents(); QVERIFY(popup->isVisible()); popup->hide(); } void TestEditorUi::completion_popup_mouse_wheel_scrolls_popup() { Settings* settings = Settings::instance(); const bool userVariablesBackup = settings->autoCompletionUserVariables; settings->autoCompletionUserVariables = true; struct UserVariablesCompletionRestore { Settings* settings; bool value; ~UserVariablesCompletionRestore() { settings->autoCompletionUserVariables = value; } } restore { settings, userVariablesBackup }; Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); for (int i = 0; i < 30; ++i) editor.evaluator()->setVariable(QStringLiteral("wheel_var_%1").arg(i), Quantity(i)); editor.setText(QStringLiteral("wheel_var_")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT( (popup = s_completionPopupTreeContaining(QStringLiteral("wheel_var_"))) != nullptr, 1000); QVERIFY2(popup->verticalScrollBar()->maximum() > popup->verticalScrollBar()->minimum(), qPrintable(QStringLiteral("min=%1 max=%2 rows=%3") .arg(popup->verticalScrollBar()->minimum()) .arg(popup->verticalScrollBar()->maximum()) .arg(popup->topLevelItemCount()))); popup->verticalScrollBar()->setValue(popup->verticalScrollBar()->minimum()); QVERIFY(popup->topLevelItemCount() > 8); const int initialValue = popup->verticalScrollBar()->value(); const QPoint globalWheelPosition = popup->viewport()->mapToGlobal(popup->viewport()->rect().center()); QWheelEvent wheelEvent( editor.mapFromGlobal(globalWheelPosition), globalWheelPosition, QPoint(), QPoint(0, -120), Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); QCoreApplication::sendEvent(&editor, &wheelEvent); QVERIFY2(popup->verticalScrollBar()->value() > initialValue, qPrintable(QStringLiteral("initial=%1 current=%2 max=%3") .arg(initialValue) .arg(popup->verticalScrollBar()->value()) .arg(popup->verticalScrollBar()->maximum()))); popup->hide(); } void TestEditorUi::completion_popup_escape_closes_and_stays_closed() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("co")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTest::keyClick(popup, Qt::Key_Escape); QCoreApplication::processEvents(); QVERIFY(!popup->isVisible()); QTest::qWait(250); QVERIFY(!popup->isVisible()); } void TestEditorUi::completion_popup_escape_keeps_focus_on_owning_editor() { QWidget container; QVBoxLayout layout(&container); Editor firstEditor; Editor secondEditor; layout.addWidget(&firstEditor); layout.addWidget(&secondEditor); container.show(); QVERIFY(QTest::qWaitForWindowExposed(&container)); container.activateWindow(); firstEditor.setFocus(); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&firstEditor), 1000); firstEditor.setText(QStringLiteral("co")); firstEditor.setCursorPosition(firstEditor.text().size()); QVERIFY(QMetaObject::invokeMethod( &firstEditor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&firstEditor), 1000); QVERIFY(!s_editorOrViewportHasFocus(&secondEditor)); QTest::keyClick(&firstEditor, Qt::Key_Escape); QCoreApplication::processEvents(); QVERIFY(!popup->isVisible()); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&firstEditor), 1000); QVERIFY(!s_editorOrViewportHasFocus(&secondEditor)); } void TestEditorUi::completion_popup_reopens_after_typing_following_escape() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("co")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTest::keyClick(popup, Qt::Key_Escape); QCoreApplication::processEvents(); QVERIFY(!popup->isVisible()); editor.insert(QStringLiteral("s")); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QVERIFY(popup->isVisible()); popup->hide(); } void TestEditorUi::completion_popup_reopens_after_retyping_deleted_letter_data() { QTest::addColumn("initialText"); QTest::addColumn("letter"); QTest::addColumn("processDeletion"); QTest::addColumn("dismissWithEscape"); QTest::newRow("a-immediate") << QString() << QStringLiteral("a") << false << false; QTest::newRow("a-delayed") << QString() << QStringLiteral("a") << true << false; QTest::newRow("c-delayed") << QString() << QStringLiteral("c") << true << false; QTest::newRow("s-delayed") << QString() << QStringLiteral("s") << true << false; QTest::newRow("co-immediate") << QStringLiteral("c") << QStringLiteral("o") << false << false; QTest::newRow("unit-delayed") << QStringLiteral("1[") << QStringLiteral("m") << true << false; QTest::newRow("escape-delayed") << QString() << QStringLiteral("a") << true << true; } void TestEditorUi::completion_popup_reopens_after_retyping_deleted_letter() { QFETCH(QString, initialText); QFETCH(QString, letter); QFETCH(bool, processDeletion); QFETCH(bool, dismissWithEscape); Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.activateWindow(); editor.setFocus(); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&editor), 1000); editor.setText(initialText); editor.setCursorPosition(editor.text().size()); QTest::keyClicks(&editor, letter); const QString completedText = editor.text(); const int completedPosition = editor.textCursor().position(); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); for (int cycle = 0; cycle < 2; ++cycle) { if (dismissWithEscape) { QTest::keyClick(&editor, Qt::Key_Escape); QVERIFY(!popup->isVisible()); } QTest::keyClick(&editor, Qt::Key_Backspace); QCOMPARE(editor.text(), initialText); if (processDeletion) QTest::qWait(50); QTest::keyClicks(&editor, letter); QCOMPARE(editor.text(), completedText); QCOMPARE(editor.textCursor().position(), completedPosition); QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); } popup->hide(); } void TestEditorUi::completion_popup_shows_for_two_character_prefixes() { for (const QString& prefix : {QStringLiteral("co"), QStringLiteral("si")}) { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(prefix); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QVERIFY(popup->isVisible()); popup->hide(); } } void TestEditorUi::completion_popup_uses_positionable_nonactivating_surface() { QWidget firstWindow; QWidget secondWindow; QVBoxLayout firstLayout(&firstWindow); QVBoxLayout secondLayout(&secondWindow); // Match application startup: construct the editor before placing it in a pane. Editor editor; editor.setAutoCompletionEnabled(false); firstLayout.addWidget(&editor); firstWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&firstWindow)); editor.setFocus(); EditorCompletion* completion = editor.findChild(); QVERIFY(completion); completion->showCompletion({QStringLiteral("cos:Cosine")}); QTreeWidget* popup = s_completionPopupTree(); QVERIFY(popup); QCOMPARE(popup->windowType(), Qt::ToolTip); QVERIFY(popup->testAttribute(Qt::WA_ShowWithoutActivating)); QCOMPARE(popup->focusPolicy(), Qt::NoFocus); QCOMPARE(popup->windowHandle()->transientParent(), firstWindow.windowHandle()); QVERIFY(s_editorOrViewportHasFocus(&editor)); popup->hide(); // Moving an existing pane into another window must refresh the native parent. secondLayout.addWidget(&editor); firstWindow.hide(); secondWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&secondWindow)); editor.setFocus(); completion->showCompletion({QStringLiteral("cos:Cosine")}); QCOMPARE(popup->windowHandle()->transientParent(), secondWindow.windowHandle()); QVERIFY(s_editorOrViewportHasFocus(&editor)); popup->hide(); } void TestEditorUi::completion_popup_keeps_editor_widgets_non_native_data() { QTest::addColumn("constants"); QTest::newRow("autocomplete") << false; QTest::newRow("constants") << true; } void TestEditorUi::completion_popup_keeps_editor_widgets_non_native() { QFETCH(bool, constants); QWidget window; QVBoxLayout layout(&window); Editor editor; editor.setAutoCompletionEnabled(false); layout.addWidget(&editor); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); editor.setFocus(); QVERIFY(!editor.testAttribute(Qt::WA_NativeWindow)); QVERIFY(!editor.viewport()->testAttribute(Qt::WA_NativeWindow)); QVERIFY(!editor.verticalScrollBar()->testAttribute(Qt::WA_NativeWindow)); if (constants) { QTest::keyClick(&editor, Qt::Key_Space, Qt::ControlModifier); QVERIFY(QApplication::activePopupWidget()); } else { EditorCompletion* completion = editor.findChild(); QVERIFY(completion); completion->showCompletion({QStringLiteral("cos:Cosine")}); QVERIFY(s_completionPopupTree()); } QCoreApplication::processEvents(); // Forcing native siblings creates extra Wayland subsurfaces for the text // viewport and scrollbars and changes their backing-store composition. QVERIFY(!editor.testAttribute(Qt::WA_NativeWindow)); QVERIFY(!editor.viewport()->testAttribute(Qt::WA_NativeWindow)); QVERIFY(!editor.verticalScrollBar()->testAttribute(Qt::WA_NativeWindow)); if (QWidget* popup = constants ? QApplication::activePopupWidget() : s_completionPopupTree()) popup->hide(); } void TestEditorUi::completion_popup_follows_editor_geometry_data() { QTest::addColumn("wrapped"); QTest::addColumn("nearBottom"); QTest::addColumn("nearRight"); QTest::newRow("below") << false << false << false; QTest::newRow("above") << false << true << false; QTest::newRow("right-edge") << false << false << true; QTest::newRow("wrapped") << true << false << false; QTest::newRow("wrapped-above") << true << true << false; } void TestEditorUi::completion_popup_follows_editor_geometry() { QFETCH(bool, wrapped); QFETCH(bool, nearBottom); QFETCH(bool, nearRight); Editor editor; editor.setAutoCompletionEnabled(false); editor.setFixedWidth(340); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString input = wrapped ? QStringLiteral("1234567890 + ").repeated(30) + QStringLiteral("co") : QStringLiteral("123 + co"); editor.setText(input); editor.setCursorPosition(input.size()); QCoreApplication::processEvents(); const QRect screen = editor.screen()->availableGeometry(); const int x = nearRight ? screen.right() - 40 : screen.left() + 30; const int y = nearBottom ? screen.bottom() - editor.height() + 1 : screen.top() + 80; editor.move(x, y); QCoreApplication::processEvents(); QTextCursor anchor = editor.textCursor(); anchor.movePosition(QTextCursor::StartOfWord); const int anchorX = editor.viewport()->mapToGlobal(editor.cursorRect(anchor).topLeft()).x(); EditorCompletion* completion = editor.findChild(); QVERIFY(completion); completion->showCompletion({QStringLiteral("cos:Cosine"), QStringLiteral("cosh:Hyperbolic cosine")}); QTreeWidget* popup = s_completionPopupTree(); QVERIFY(popup); const QPoint editorTop = editor.mapToGlobal(QPoint(0, 0)); const int belowY = editorTop.y() + editor.height(); const int expectedY = belowY + popup->height() > screen.bottom() + 1 ? editorTop.y() - popup->height() : belowY; const int expectedX = qBound(screen.left(), anchorX, screen.right() + 1 - popup->width()); QCOMPARE(popup->geometry().topLeft(), QPoint(expectedX, expectedY)); QVERIFY(screen.contains(popup->geometry())); if (wrapped) QVERIFY(editor.verticalScrollBar()->value() > 0); popup->hide(); } void TestEditorUi::completion_popup_geometry_avoids_editor_overlap_data() { QTest::addColumn("bounds"); QTest::addColumn("editor"); QTest::addColumn("height"); QTest::addColumn("expected"); QTest::newRow("below") << QRect(0, 0, 600, 400) << QRect(30, 100, 400, 60) << 100 << QRect(50, 160, 200, 100); QTest::newRow("above-at-window-bottom") << QRect(0, 0, 600, 400) << QRect(30, 330, 400, 60) << 100 << QRect(50, 230, 200, 100); QTest::newRow("shrink-above") << QRect(0, 0, 600, 400) << QRect(30, 200, 400, 60) << 300 << QRect(50, 0, 200, 200); QTest::newRow("shrink-below") << QRect(0, 0, 600, 400) << QRect(30, 80, 400, 60) << 300 << QRect(50, 140, 200, 260); QTest::newRow("negative-screen-origin") << QRect(0, -400, 600, 400) << QRect(30, -200, 400, 60) << 300 << QRect(50, -400, 200, 200); QTest::newRow("no-space") << QRect(0, 0, 600, 60) << QRect(30, 0, 400, 60) << 100 << QRect(); } void TestEditorUi::completion_popup_geometry_avoids_editor_overlap() { QFETCH(QRect, bounds); QFETCH(QRect, editor); QFETCH(int, height); QFETCH(QRect, expected); const QRect popup = EditorUtils::completionPopupGeometry(editor, 50, QSize(200, height), bounds); QCOMPARE(popup, expected); QVERIFY(!popup.intersects(editor)); if (popup.isValid()) QVERIFY(bounds.contains(popup)); } void TestEditorUi::completion_popup_shortens_tall_lists_without_covering_editor() { Editor editor; editor.setAutoCompletionEnabled(false); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QRect screen = editor.screen()->availableGeometry(); editor.move(screen.left() + 20, screen.center().y() - editor.height() / 2); QTreeWidget* popup = editor.findChild(QStringLiteral("editorCompletionPopup")); QVERIFY(popup); QFont font = popup->font(); font.setPixelSize(qMax(1, screen.height() / 8)); popup->setFont(font); QStringList choices; for (int i = 0; i < 8; ++i) choices.append(QStringLiteral("%1:x").arg(i)); EditorCompletion* completion = editor.findChild(); QVERIFY(completion); completion->showCompletion(choices); QCoreApplication::processEvents(); QVERIFY(popup->isVisible()); const QRect editorRect(editor.mapToGlobal(QPoint(0, 0)), editor.size()); QVERIFY(!popup->geometry().intersects(editorRect)); QVERIFY(popup->geometry().top() >= screen.top()); QVERIFY(popup->geometry().bottom() <= screen.bottom()); QVERIFY(popup->verticalScrollBar()->maximum() > 0); popup->hide(); } void TestEditorUi::completion_popups_configure_editor_anchor_data() { QTest::addColumn("constants"); QTest::newRow("autocomplete") << false; QTest::newRow("constants") << true; } void TestEditorUi::completion_popups_configure_editor_anchor() { QFETCH(bool, constants); QWidget window; QVBoxLayout layout(&window); layout.addStretch(); Editor editor; editor.setAutoCompletionEnabled(false); editor.setFixedWidth(340); layout.addWidget(&editor); window.resize(400, 400); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); // Constant completion is normally constructed lazily on Ctrl+Space. ConstantCompletion* constantCompletion = constants ? new ConstantCompletion(&editor) : nullptr; QWidget* popup = editor.findChild(constants ? QStringLiteral("constantCompletionPopup") : QStringLiteral("editorCompletionPopup")); QVERIFY(popup); // Both popups must configure the very first native surface created by show(). QVERIFY(!popup->windowHandle()); QRect previousAnchor; for (const bool wrapped : {false, true}) { const QString input = wrapped ? QStringLiteral("1234567890 + ").repeated(30) + QStringLiteral("co") : QStringLiteral("123 + co"); editor.setText(input); editor.setCursorPosition(input.size()); editor.setFocus(); QCoreApplication::processEvents(); QTextCursor cursor = editor.textCursor(); if (!constants) cursor.movePosition(QTextCursor::StartOfWord); const QRect editorRect(editor.mapTo(&window, QPoint()), editor.size()); const int cursorX = editor.viewport()->mapTo(&window, editor.cursorRect(cursor).topLeft()).x(); const QRect expected(qBound(editorRect.left(), cursorX, editorRect.right()), editorRect.top(), 1, editorRect.height()); if (constants) { constantCompletion->showCompletion(); } else { editor.findChild()->showCompletion({QStringLiteral("cos:Cosine")}); } QVERIFY(popup->isVisible()); QWindow* native = popup->windowHandle(); QVERIFY(native); QCOMPARE(native->transientParent(), window.windowHandle()); QCOMPARE(native->property("_q_waylandPopupAnchorRect").toRect(), expected); QCOMPARE(native->property("_q_waylandPopupAnchor").value(), Qt::Edges(Qt::BottomEdge | Qt::LeftEdge)); QCOMPARE(native->property("_q_waylandPopupGravity").value(), Qt::Edges(Qt::BottomEdge | Qt::RightEdge)); const uint constraints = native->property("_q_waylandPopupConstraintAdjustment").toUInt(); QVERIFY(constraints & 1); // slide_x QVERIFY(constraints & 8); // flip_y QVERIFY(constraints & 32); // resize_y QVERIFY(!(constraints & 2)); // slide_y would overlap the editor if (wrapped) { QVERIFY(expected != previousAnchor); QVERIFY(editor.verticalScrollBar()->value() > 0); } previousAnchor = expected; popup->hide(); } } void TestEditorUi::completion_popup_compositor_geometry_data() { QTest::addColumn("editor"); QTest::addColumn("cursorX"); QTest::addColumn("requested"); QTest::addColumn("expectedAnchor"); QTest::addColumn("expectedPopup"); QTest::newRow("below-bottom-of-parent") << QRect(10, 340, 400, 60) << 50 << QSize(200, 100) << QRect(50, 340, 1, 60) << QRect(50, 400, 200, 100); QTest::newRow("negative-guessed-origin") << QRect(-600, -400, 400, 60) << -550 << QSize(200, 100) << QRect(-550, -400, 1, 60) << QRect(-550, -340, 200, 100); QTest::newRow("word-start-scrolled-off-left") << QRect(10, 340, 400, 60) << -50 << QSize(200, 100) << QRect(10, 340, 1, 60) << QRect(10, 400, 200, 100); QTest::newRow("cursor-scrolled-off-right") << QRect(10, 340, 400, 60) << 500 << QSize(200, 100) << QRect(409, 340, 1, 60) << QRect(409, 400, 200, 100); QTest::newRow("tall-and-wide-list") << QRect(10, 340, 400, 60) << 50 << QSize(1000, 1000) << QRect(50, 340, 1, 60) << QRect(50, 400, 800, 270); QTest::newRow("editor-fills-output") << QRect(10, 0, 400, 600) << 50 << QSize(200, 100) << QRect(50, 0, 1, 600) << QRect(); } void TestEditorUi::completion_popup_compositor_geometry() { QFETCH(QRect, editor); QFETCH(int, cursorX); QFETCH(QSize, requested); QFETCH(QRect, expectedAnchor); QFETCH(QRect, expectedPopup); const QRect anchor = EditorUtils::completionPopupAnchorRect(editor, cursorX); QCOMPARE(anchor, expectedAnchor); const QRect popup = EditorUtils::completionPopupCompositorGeometry(anchor, requested, QSize(800, 600)); QCOMPARE(popup, expectedPopup); QVERIFY(!popup.intersects(editor)); if (popup.isValid()) { // xdg-shell flip_y reflects both anchor and gravity, placing the bottom // of the popup at the editor's top, regardless of the parent's origin. const QRect flipped(QPoint(anchor.left(), anchor.top() - popup.height()), popup.size()); QVERIFY(!flipped.intersects(editor)); QCOMPARE(flipped.bottom() + 1, editor.top()); } } void TestEditorUi::constant_search_filters_without_editing_expression() { Editor editor; editor.setAutoCompletionEnabled(false); editor.setText(QStringLiteral("12+34")); QTextCursor cursor = editor.textCursor(); cursor.setPosition(3); cursor.setPosition(5, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QSignalSpy evaluated(&editor, &Editor::returnPressed); QSignalSpy changed(&editor, &Editor::textChanged); QTest::keyClick(&editor, Qt::Key_Space, Qt::ControlModifier); QPointer popup = QApplication::activePopupWidget(); QVERIFY(popup); auto* search = popup->findChild(QStringLiteral("constantCompletionSearch")); auto* list = popup->findChild(); QVERIFY(search && list); QTRY_VERIFY(search->hasFocus()); QCOMPARE(list->topLevelItemCount(), Constants::instance()->list().size()); QTest::keyClick(search, Qt::Key_Tab, Qt::ShiftModifier); QVERIFY(list->hasFocus()); QTest::keyClick(list, Qt::Key_Tab, Qt::ShiftModifier); QVERIFY(search->hasFocus()); QTest::keyClick(search, Qt::Key_Tab, Qt::ShiftModifier); QVERIFY(list->hasFocus()); QTest::keyClick(list, Qt::Key_P); QVERIFY(search->hasFocus()); QCOMPARE(search->text(), QStringLiteral("p")); search->clear(); QTest::keyClicks(search, "PROTON"); QVERIFY(list->topLevelItemCount() > 1); for (int i = 0; i < list->topLevelItemCount(); ++i) QVERIFY(list->topLevelItem(i)->text(0).contains(QStringLiteral("proton"), Qt::CaseInsensitive)); QTest::keyClick(search, Qt::Key_Down); QCOMPARE(list->indexOfTopLevelItem(list->currentItem()), 1); QTest::keyClick(search, Qt::Key_Up); QCOMPARE(list->indexOfTopLevelItem(list->currentItem()), 0); QVERIFY(search->hasFocus()); QTest::keyClick(search, Qt::Key_Backspace); QCOMPARE(search->text(), QStringLiteral("PROTO")); search->setText(QStringLiteral("kg")); QVERIFY(list->topLevelItemCount() > 0); for (int i = 0; i < list->topLevelItemCount(); ++i) { auto* item = list->topLevelItem(i); QVERIFY(item->data(0, Qt::AccessibleTextRole).toString().contains(QStringLiteral("kg"), Qt::CaseInsensitive)); } search->clear(); QCOMPARE(list->topLevelItemCount(), Constants::instance()->list().size()); search->setText(QStringLiteral("no such constant 49236")); QCOMPARE(list->topLevelItemCount(), 0); QTest::keyClick(search, Qt::Key_Down); QTest::keyClick(search, Qt::Key_Return); QTest::keyClick(search, Qt::Key_Tab); QVERIFY(popup->isVisible()); QVERIFY(search->hasFocus()); QVERIFY(list->currentItem() == nullptr); QCOMPARE(evaluated.count(), 0); QCOMPARE(changed.count(), 0); QCOMPARE(editor.text(), QStringLiteral("12+34")); QTest::keyClick(search, Qt::Key_Escape); QVERIFY(!popup || !popup->isVisible()); QTRY_VERIFY(s_editorOrViewportHasFocus(&editor)); QCOMPARE(editor.textCursor().selectionStart(), 3); QCOMPARE(editor.textCursor().selectionEnd(), 5); QCOMPARE(editor.text(), QStringLiteral("12+34")); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QVERIFY(popup.isNull()); } void TestEditorUi::constant_search_inserts_selected_result_data() { QTest::addColumn("query"); QTest::addColumn("expected"); QTest::addColumn("mouse"); QTest::addColumn("acceptKey"); QTest::addColumn("listFocus"); QTest::newRow("pi") << QStringLiteral("pi (π)") << QString(UnicodeChars::Pi) << false << int(Qt::Key_Return) << false; QTest::newRow("e-click") << QStringLiteral("Euler's number") << QStringLiteral("e") << true << int(Qt::Key_Return) << false; QTest::newRow("unit") << QStringLiteral("speed of light in vacuum") << QStringLiteral("299792458 [m·s�¹]") << false << int(Qt::Key_Return) << false; QTest::newRow("pi-tab") << QStringLiteral("pi (π)") << QString(UnicodeChars::Pi) << false << int(Qt::Key_Tab) << false; QTest::newRow("unit-tab") << QStringLiteral("speed of light in vacuum") << QStringLiteral("299792458 [m·s�¹]") << false << int(Qt::Key_Tab) << false; QTest::newRow("e-tab-from-list") << QStringLiteral("Euler's number") << QStringLiteral("e") << false << int(Qt::Key_Tab) << true; } void TestEditorUi::constant_search_inserts_selected_result() { QFETCH(QString, query); QFETCH(QString, expected); QFETCH(bool, mouse); QFETCH(int, acceptKey); QFETCH(bool, listFocus); QWidget window; QVBoxLayout layout(&window); Editor editor; Editor other; layout.addWidget(&editor); layout.addWidget(&other); editor.setAutoCompletionEnabled(false); editor.setText(QStringLiteral("12+34")); QSignalSpy evaluated(&editor, &Editor::returnPressed); QTextCursor cursor = editor.textCursor(); cursor.setPosition(3); cursor.setPosition(5, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); editor.setFocus(); QTest::keyClick(&editor, Qt::Key_Space, Qt::ControlModifier); QPointer popup = QApplication::activePopupWidget(); QVERIFY(popup); auto* search = popup->findChild(QStringLiteral("constantCompletionSearch")); auto* list = popup->findChild(); QVERIFY(search && list); search->setText(query); QCOMPARE(list->topLevelItemCount(), 1); if (mouse) { QTest::mouseClick(list->viewport(), Qt::LeftButton, Qt::NoModifier, list->visualItemRect(list->currentItem()).center()); } else { if (listFocus) { QTest::keyClick(search, Qt::Key_Tab, Qt::ShiftModifier); QVERIFY(list->hasFocus()); } QTest::keyClick(listFocus ? static_cast(list) : search, static_cast(acceptKey)); } QCOMPARE(editor.text(), QStringLiteral("12+") + expected); QCOMPARE(evaluated.count(), 0); QVERIFY(other.text().isEmpty()); QTRY_VERIFY(s_editorOrViewportHasFocus(&editor)); editor.undo(); QCOMPARE(editor.text(), QStringLiteral("12+34")); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QVERIFY(popup.isNull()); } void TestEditorUi::constant_search_closes_without_stealing_outside_focus() { QWidget window; QVBoxLayout layout(&window); Editor editor; QLineEdit other; layout.addWidget(&editor); layout.addWidget(&other); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); editor.setFocus(); QTest::keyClick(&editor, Qt::Key_Space, Qt::ControlModifier); QPointer popup = QApplication::activePopupWidget(); QVERIFY(popup); popup->hide(); other.setFocus(); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QVERIFY(popup.isNull()); QVERIFY(other.hasFocus()); QVERIFY(editor.text().isEmpty()); } void TestEditorUi::constant_search_layout_follows_popup_resize() { Editor editor; editor.setAutoCompletionEnabled(false); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); ConstantCompletion completion(&editor); completion.showCompletion(); QWidget* popup = QApplication::activePopupWidget(); QVERIFY(popup); auto* search = popup->findChild(QStringLiteral("constantCompletionSearch")); auto* constants = popup->findChild(); QVERIFY(search && constants); popup->resize(340, 150); QCoreApplication::processEvents(); QVERIFY(popup->rect().contains(search->geometry())); QVERIFY(popup->rect().contains(constants->geometry())); QVERIFY(constants->height() > constants->sizeHintForRow(0)); QTRY_VERIFY(constants->verticalScrollBar()->maximum() > 0); search->setText(QStringLiteral("no such constant 49236")); popup->resize(300, 130); QCoreApplication::processEvents(); QLabel* empty = nullptr; for (auto* label : popup->findChildren()) { if (label->property("dockListNoMatchLabel").toBool()) empty = label; } QVERIFY(empty); QVERIFY(empty->isVisible()); QCOMPARE(empty->geometry(), constants->viewport()->rect()); QVERIFY(popup->rect().contains(constants->geometry())); popup->hide(); } void TestEditorUi::constant_search_inline_units_preserve_full_insertion_data() { QTest::addColumn("rightToLeft"); QTest::newRow("left-to-right") << false; QTest::newRow("right-to-left") << true; } void TestEditorUi::constant_search_inline_units_preserve_full_insertion() { QFETCH(bool, rightToLeft); Editor editor; editor.setAutoCompletionEnabled(false); editor.setLayoutDirection(rightToLeft ? Qt::RightToLeft : Qt::LeftToRight); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); ConstantCompletion completion(&editor); QSignalSpy inserted(&completion, &ConstantCompletion::selectedCompletion); completion.showCompletion(); QWidget* popup = QApplication::activePopupWidget(); QVERIFY(popup); auto* search = popup->findChild(QStringLiteral("constantCompletionSearch")); auto* list = popup->findChild(); QVERIFY(search && list); const QString name = QStringLiteral("electron mass energy equivalent in MeV"); search->setText(name); QCOMPARE(list->topLevelItemCount(), 1); auto* item = list->currentItem(); QVERIFY(item); QCOMPARE(item->data(0, Qt::AccessibleTextRole).toString(), name + QStringLiteral(" MeV")); QVERIFY(item->toolTip(0).contains(QStringLiteral("MeV"))); popup->resize(230, 140); QFont font = list->font(); font.setPointSizeF(font.pointSizeF() * 1.5); list->setFont(font); QCoreApplication::processEvents(); const QPixmap rendered = list->viewport()->grab(); QVERIFY(!rendered.isNull()); // A narrow row may elide the label, but insertion keeps the full quantity. QTest::keyClick(search, Qt::Key_Return); QCOMPARE(inserted.count(), 1); QCOMPARE(inserted.first().first().toString(), QStringLiteral("0.51099895069%1[MeV]").arg(QChar(MathDsl::QuantSp))); } void TestEditorUi::constant_search_renders_units_in_secondary_shade_data() { QTest::addColumn("background"); QTest::addColumn("foreground"); QTest::addColumn("selected"); QTest::addColumn("expected"); QTest::newRow("dark") << QColor(QStringLiteral("#454257")) << QColor(QStringLiteral("#f7f5fc")) << false << QColor(QStringLiteral("#cdcbe0")); QTest::newRow("light") << QColor(QStringLiteral("#f3f3f3")) << QColor(QStringLiteral("#202025")) << false << QColor(QStringLiteral("#282828")); QTest::newRow("selected") << QColor(QStringLiteral("#5c586f")) << QColor(QStringLiteral("#f7f5fc")) << true << QColor(QStringLiteral("#cdcbe0")); QTest::newRow("neutral") << QColor(Qt::white) << QColor(Qt::black) << false << QColor(QStringLiteral("#606060")); } void TestEditorUi::constant_search_renders_units_in_secondary_shade() { QFETCH(QColor, background); QFETCH(QColor, foreground); QFETCH(bool, selected); QFETCH(QColor, expected); Editor editor; editor.setThemePreviewColorScheme(ColorScheme::fromJsonObject(themeJson({ {QStringLiteral("background"), background.name()}, {QStringLiteral("unit"), expected.name()} }))); ConstantCompletion completion(&editor); auto* popup = editor.findChild(QStringLiteral("constantCompletionPopup")); QVERIFY(popup); auto* list = popup->findChild(); auto* search = popup->findChild(QStringLiteral("constantCompletionSearch")); QVERIFY(list && search); search->setText(QStringLiteral("electron mass energy equivalent in MeV")); QCOMPARE(list->topLevelItemCount(), 1); auto* item = list->topLevelItem(0); // Paint the unit alone so name antialiasing cannot mimic its secondary color. item->setText(0, QStringLiteral(" ")); QFont font = list->font(); font.setPixelSize(32); list->setFont(font); QPalette palette = list->palette(); for (auto group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { palette.setColor(group, QPalette::Base, background); palette.setColor(group, QPalette::Highlight, background); palette.setColor(group, QPalette::Text, foreground); palette.setColor(group, QPalette::HighlightedText, foreground); } list->setPalette(palette); QStyleOptionViewItem option; option.initFrom(list); option.rect = QRect(0, 0, 400, 64); option.state = QStyle::State_Enabled | QStyle::State_Active; if (selected) option.state |= QStyle::State_Selected; option.font = font; option.fontMetrics = QFontMetrics(font); for (const QColor& unitColor : {expected, QColor(QStringLiteral("#789abc"))}) { editor.setThemePreviewColorScheme(ColorScheme::fromJsonObject(themeJson({ {QStringLiteral("background"), background.name()}, {QStringLiteral("unit"), unitColor.name()} }))); QImage image(option.rect.size(), QImage::Format_ARGB32_Premultiplied); image.fill(background); QPainter painter(&image); list->itemDelegate()->paint(&painter, option, list->model()->index(0, 0)); painter.end(); int unitPixels = 0; int mainTextPixels = 0; for (int y = 0; y < image.height(); ++y) { for (int x = 0; x < image.width(); ++x) { const QRgb pixel = image.pixel(x, y); unitPixels += pixel == unitColor.rgba(); mainTextPixels += pixel == foreground.rgba(); } } QVERIFY(unitPixels > 20); QCOMPARE(mainTextPixels, 0); } } void TestEditorUi::constant_completion_popup_follows_wrapped_editor_cursor() { QWidget window; QVBoxLayout layout(&window); Editor editor; editor.setAutoCompletionEnabled(false); editor.setFixedWidth(340); layout.addWidget(&editor); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); editor.setFocus(); const QString input = QStringLiteral("1234567890 + ").repeated(30); editor.setText(input); editor.setCursorPosition(input.size()); QCoreApplication::processEvents(); const QRect screen = editor.screen()->availableGeometry(); window.move(screen.left() + 30, screen.top() + 80); QCoreApplication::processEvents(); const int anchorX = editor.viewport()->mapToGlobal(editor.cursorRect().topLeft()).x(); QTest::keyClick(&editor, Qt::Key_Space, Qt::ControlModifier); QWidget* popup = QApplication::activePopupWidget(); QVERIFY(popup); QCOMPARE(popup->objectName(), QStringLiteral("constantCompletionPopup")); QCOMPARE(popup->windowHandle()->transientParent(), window.windowHandle()); const QPoint editorTop = editor.mapToGlobal(QPoint(0, 0)); const int belowY = editorTop.y() + editor.height(); const int expectedY = belowY + popup->height() > screen.bottom() + 1 ? editorTop.y() - popup->height() : belowY; const int expectedX = qBound(screen.left(), anchorX, screen.right() + 1 - popup->width()); QCOMPARE(popup->geometry().topLeft(), QPoint(expectedX, expectedY)); QVERIFY(editor.verticalScrollBar()->value() > 0); popup->hide(); } void TestEditorUi::completion_popup_uses_configured_surface_colors() { const QColor background(QStringLiteral("#334455")); const QColor foreground(QStringLiteral("#f4f7fb")); const QColor scrollbarThumb(QStringLiteral("#556677")); const QColor scrollbarThumbForeground(QStringLiteral("#ffffff")); const QColor selectedRow(QStringLiteral("#667788")); const QColor selectedRowForeground(QStringLiteral("#101418")); const QColor outline(QStringLiteral("#778899")); const int cornerRadius = 11; Editor editor; editor.setThemeCompletionColors(background, foreground, scrollbarThumb, scrollbarThumbForeground, selectedRow, selectedRowForeground, outline, cornerRadius); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("co")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QCOMPARE(popup->palette().color(QPalette::Base), background); QCOMPARE(popup->palette().color(QPalette::Text), foreground); QCOMPARE(popup->palette().color(QPalette::Highlight), selectedRow); QCOMPARE(popup->palette().color(QPalette::HighlightedText), selectedRowForeground); QCOMPARE(popup->cursor().shape(), Qt::PointingHandCursor); QCOMPARE(popup->viewport()->cursor().shape(), Qt::PointingHandCursor); QVERIFY(popup->styleSheet().contains(QStringLiteral("background: #556677"))); QVERIFY(popup->styleSheet().contains(QStringLiteral("QScrollBar:horizontal"))); QVERIFY(popup->styleSheet().contains(QStringLiteral("QScrollBar::handle:horizontal"))); QVERIFY(popup->styleSheet().contains(QStringLiteral("border: %1px solid #778899") .arg(UiConfig::PopupOutlineStrokeWidth))); QVERIFY(popup->styleSheet().contains(QStringLiteral("border-radius: 11px"))); popup->hide(); } void TestEditorUi::constant_completion_popup_uses_configured_surface_colors() { const QColor background(QStringLiteral("#334455")); const QColor foreground(QStringLiteral("#f4f7fb")); const QColor scrollbarThumb(QStringLiteral("#556677")); const QColor scrollbarThumbForeground(QStringLiteral("#ffffff")); const QColor selectedRow(QStringLiteral("#667788")); const QColor selectedRowForeground(QStringLiteral("#101418")); const QColor outline(QStringLiteral("#778899")); const int cornerRadius = 11; Editor editor; editor.setThemeCompletionColors(background, foreground, scrollbarThumb, scrollbarThumbForeground, selectedRow, selectedRowForeground, outline, cornerRadius); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QTest::keyClick(&editor, Qt::Key_Space, Qt::ControlModifier); QList popupTrees; QTRY_VERIFY_WITH_TIMEOUT(!(popupTrees = s_constantCompletionPopupTrees()).isEmpty(), 1000); QCOMPARE(popupTrees.count(), 1); for (QTreeWidget* popup : popupTrees) { QCOMPARE(popup->palette().color(QPalette::Base), background); QCOMPARE(popup->palette().color(QPalette::Text), foreground); QCOMPARE(popup->palette().color(QPalette::Highlight), selectedRow); QCOMPARE(popup->palette().color(QPalette::HighlightedText), selectedRowForeground); QCOMPARE(popup->cursor().shape(), Qt::PointingHandCursor); QCOMPARE(popup->viewport()->cursor().shape(), Qt::PointingHandCursor); QVERIFY(popup->styleSheet().contains(QStringLiteral("background: #556677"))); QVERIFY(popup->styleSheet().contains(QStringLiteral("QScrollBar:horizontal"))); QVERIFY(popup->styleSheet().contains(QStringLiteral("QScrollBar::handle:horizontal"))); QVERIFY(popup->styleSheet().contains(QStringLiteral("border: %1px solid #778899") .arg(UiConfig::PopupOutlineStrokeWidth))); QVERIFY(popup->styleSheet().contains(QStringLiteral("border-radius: 11px"))); } if (QWidget* popup = QApplication::activePopupWidget()) popup->hide(); } void TestEditorUi::inactive_editor_does_not_show_completion_popup() { QWidget container; QVBoxLayout layout(&container); Editor firstEditor; Editor secondEditor; layout.addWidget(&firstEditor); layout.addWidget(&secondEditor); container.show(); QVERIFY(QTest::qWaitForWindowExposed(&container)); firstEditor.setFocus(); firstEditor.setText(QStringLiteral("co")); firstEditor.setCursorPosition(firstEditor.text().size()); secondEditor.setFocus(); QCoreApplication::processEvents(); QVERIFY(QMetaObject::invokeMethod( &firstEditor, "triggerAutoComplete", Qt::DirectConnection)); QCoreApplication::processEvents(); QVERIFY(s_completionPopupTree() == nullptr); QTest::qWait(250); QVERIFY(s_completionPopupTree() == nullptr); } void TestEditorUi::enter_evaluates_when_cursor_is_immediately_after_operator() { struct Case { QString expression; QChar op; }; const QList cases = { { QStringLiteral("2 + 3"), QLatin1Char('+') }, { QString::fromUtf8("2 − 3"), QChar(MathDsl::SubOp) }, { QStringLiteral("2 / 3"), QLatin1Char('/') }, { QString::fromUtf8("2 × 3"), QChar(MathDsl::MulCrossOp) }, { QString::fromUtf8("2 [rad·s�¹]"), QChar(MathDsl::MulDotOp) }, { QStringLiteral("2 [rad/s]"), QLatin1Char('/') }, }; for (const Case& c : cases) { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(c.expression); const int opPos = c.expression.indexOf(c.op); QVERIFY2(opPos >= 0, qPrintable(QStringLiteral("Operator not found in expression: %1").arg(c.expression))); editor.setCursorPosition(opPos + 1); QSignalSpy returnPressedSpy(&editor, SIGNAL(returnPressed())); QTest::keyClick(&editor, Qt::Key_Return, Qt::NoModifier); QCoreApplication::processEvents(); QCOMPARE(returnPressedSpy.count(), 1); QCOMPARE(editor.text(), c.expression); } } void TestEditorUi::completion_popup_uses_expected_icons_for_all_symbol_types() { Settings* settings = Settings::instance(); const bool builtInFnBackup = settings->autoCompletionBuiltInFunctions; const bool builtInVarBackup = settings->autoCompletionBuiltInVariables; const bool userFnBackup = settings->autoCompletionUserFunctions; const bool userVarBackup = settings->autoCompletionUserVariables; settings->autoCompletionBuiltInFunctions = true; settings->autoCompletionBuiltInVariables = true; settings->autoCompletionUserFunctions = true; settings->autoCompletionUserVariables = true; struct SettingsRestoreGuard { Settings* settings; bool builtInFn; bool builtInVar; bool userFn; bool userVar; ~SettingsRestoreGuard() { settings->autoCompletionBuiltInFunctions = builtInFn; settings->autoCompletionBuiltInVariables = builtInVar; settings->autoCompletionUserFunctions = userFn; settings->autoCompletionUserVariables = userVar; } } settingsRestoreGuard {settings, builtInFnBackup, builtInVarBackup, userFnBackup, userVarBackup}; Session session; Evaluator* evaluator = session.evaluator(); evaluator->unsetAllUserUnits(); evaluator->unsetAllUserFunctions(); evaluator->unsetVariable(QStringLiteral("icon_user_var")); evaluator->unsetVariable(QStringLiteral("s")); evaluator->setExpression(QStringLiteral("icon_user_var = 7")); QVERIFY(!evaluator->eval().isNan()); evaluator->setExpression(QStringLiteral("s = 9")); QVERIFY(!evaluator->eval().isNan()); evaluator->setVariable(QStringLiteral("ans"), Quantity(9), Variable::BuiltIn); evaluator->setUserFunction(UserFunction( QStringLiteral("icon_user_func"), QStringList() << QStringLiteral("t"), QStringLiteral("t"))); evaluator->setExpression(QStringLiteral("2[m]")); const Quantity iconUserUnitValue = evaluator->eval(); QVERIFY(!iconUserUnitValue.isNan()); evaluator->setUserUnit(UserUnit( QStringLiteral("icon_user_unit"), iconUserUnitValue, QStringLiteral("2[m]"), QStringLiteral("[icon_user_unit]=2[m]"))); Editor editor; editor.setSession(&session); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("si")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QCOMPARE(s_popupSymbolForIdentifier(popup, QStringLiteral("sin")), QString::fromUtf8("📚 ƒ")); popup->hide(); editor.setText(QStringLiteral("icon_user_f")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QCOMPARE(s_popupSymbolForIdentifier(popup, QStringLiteral("icon_user_func")), QString::fromUtf8("👤 ƒ")); popup->hide(); editor.setText(QStringLiteral("a")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QCOMPARE(s_popupSymbolForIdentifier(popup, QStringLiteral("ans")), QString::fromUtf8("� �")); popup->hide(); editor.setText(QStringLiteral("icon_user_")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QCOMPARE(s_popupSymbolForIdentifier(popup, QStringLiteral("icon_user_var")), QString::fromUtf8("👤 �")); popup->hide(); editor.setText(QStringLiteral("s")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QCOMPARE(s_popupSymbolForIdentifier(popup, QStringLiteral("s")), QString::fromUtf8("👤 �")); popup->hide(); editor.setText(QStringLiteral("[met")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QCOMPARE(s_popupSymbolForIdentifier(popup, QStringLiteral("metre")), QString::fromUtf8("📚 �")); popup->hide(); editor.setText(QStringLiteral("[icon_user_u")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QCOMPARE(s_popupSymbolForIdentifier(popup, QStringLiteral("icon_user_unit")), QString::fromUtf8("👤 �")); popup->hide(); } void TestEditorUi::wrap_selection_method_wraps_selected_text() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1+2")); QTextCursor cursor = editor.textCursor(); cursor.setPosition(0); cursor.setPosition(1, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); editor.wrapSelection(); QCOMPARE(editor.text(), QStringLiteral("(1)+2")); } void TestEditorUi::wrap_selection_method_wraps_whole_expression_without_selection() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("1+2")); editor.setCursorPosition(0); editor.wrapSelection(); QCOMPARE(editor.text(), QStringLiteral("(1+2)")); } void TestEditorUi::matching_parentheses_use_parens_and_generated_foreground_colors() { const QColor parensColor(QStringLiteral("#c8a2c8")); const QColor resultBackground(QStringLiteral("#102030")); const QColor generatedForeground = aaForegroundForBackground(parensColor); const ColorScheme scheme = ColorScheme::fromJsonObject(themeJson(QJsonObject{ {QStringLiteral("parens"), parensColor.name()}, {QStringLiteral("background"), QStringLiteral("#010203")} })); QVERIFY(scheme.isValid()); Editor editor; editor.setThemeSurfaceColor(QColor(QStringLiteral("#203040")), resultBackground); editor.setThemePreviewColorScheme(scheme); editor.setText(QStringLiteral("()")); editor.setCursorPosition(editor.text().size()); QVERIFY(QMetaObject::invokeMethod( &editor, "doMatchingPar", Qt::DirectConnection)); const QList selections = editor.extraSelections(); QCOMPARE(selections.count(), 2); for (const QTextEdit::ExtraSelection& selection : selections) { QCOMPARE(selection.format.background().color(), parensColor); QCOMPARE(selection.format.foreground().color(), generatedForeground); QVERIFY(selection.format.foreground().color() != resultBackground); } } void TestEditorUi::keeps_wrapped_cursor_line_visible_at_height_cap() { Editor editor; editor.setFixedWidth(220); editor.resize(220, 80); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral( "12 + 312 + 3 + 12 + 312 + 3 + 123 + 123 + 12 + 3 + 123 + " "123 + 14 + 2 + 123 + 12 + 3 + 12 + 3 + 12 + 3 + " "345345345 + 345345 + 345345345 + 345345345453453453434 + " "234 + 234 + 234 + 23423423 + 4234 + 234")); editor.setCursorPosition(editor.text().size()); QTRY_VERIFY(editor.document()->begin().layout()->lineCount() > 5); QTRY_VERIFY(editor.cursorRect().top() >= editor.viewport()->rect().top()); QTRY_VERIFY(editor.cursorRect().bottom() <= editor.viewport()->rect().bottom()); } void TestEditorUi::rewrites_operators_in_scrolled_expression_data() { QTest::addColumn("input"); QTest::addColumn("token"); QTest::addColumn("cursorOffset"); QTest::addColumn("inputMethod"); QTest::addColumn("style"); const QString conversion = MathDsl::buildWrappedToken(MathDsl::TransOp, MathDsl::SubWrapSp) + QStringLiteral("[]"); for (int style : {int(Settings::EditorDisplayModern), int(Settings::EditorDisplayClassic)}) { const QByteArray prefix = style == Settings::EditorDisplayModern ? "modern-" : "classic-"; QTest::newRow(QByteArray(prefix + "double-minus").constData()) << QStringLiteral("--") << conversion << 1 << false << style; QTest::newRow(QByteArray(prefix + "arrow").constData()) << QStringLiteral("->") << conversion << 1 << false << style; QTest::newRow(QByteArray(prefix + "power").constData()) << QStringLiteral("**") << QStringLiteral("^") << 0 << false << style; QTest::newRow(QByteArray(prefix + "superscript").constData()) << QStringLiteral("^2") << QString(MathDsl::Pow2) << 0 << false << style; QTest::newRow(QByteArray(prefix + "ime-superscript").constData()) << QStringLiteral("^2") << QString(MathDsl::Pow2) << 0 << true << style; } } void TestEditorUi::rewrites_operators_in_scrolled_expression() { QFETCH(QString, input); QFETCH(QString, token); QFETCH(int, cursorOffset); QFETCH(bool, inputMethod); QFETCH(int, style); Settings::instance()->editorDisplayStyle = Settings::EditorDisplayStyle(style); Editor editor; editor.setAutoCompletionEnabled(false); editor.setAutoCalcEnabled(false); editor.setFixedWidth(220); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString expression = QStringLiteral("1234567890+").repeated(40) + QStringLiteral("1"); editor.setText(expression); editor.setCursorPosition(editor.text().size()); QVERIFY(editor.document()->firstBlock().layout()->lineCount() > 5); QVERIFY(editor.verticalScrollBar()->value() > 0); const auto type = [&](const QString& text) { if (inputMethod) { QInputMethodEvent event; event.setCommitString(text); QApplication::sendEvent(&editor, &event); } else { QTest::keyClicks(&editor, text); } }; type(input.left(1)); const QString beforeRewrite = editor.document()->toRawText(); type(input.mid(1)); const QString afterRewrite = editor.document()->toRawText(); QCOMPARE(afterRewrite, expression + token); QCOMPARE(editor.textCursor().position(), afterRewrite.size() - cursorOffset); QVERIFY(editor.cursorRect().top() >= 0); QVERIFY(editor.cursorRect().bottom() < editor.viewport()->height()); editor.undo(); QCOMPARE(editor.document()->toRawText(), beforeRewrite); editor.undo(); QCOMPARE(editor.document()->toRawText(), expression); editor.redo(); editor.redo(); QCOMPARE(editor.document()->toRawText(), afterRewrite); QVERIFY(editor.cursorRect().top() >= 0); QVERIFY(editor.cursorRect().bottom() < editor.viewport()->height()); } void TestEditorUi::classic_editor_keeps_wrapped_input_visible_and_preserves_undo() { Settings* settings = Settings::instance(); settings->autoCalc = false; settings->editorDisplayStyle = Settings::EditorDisplayClassic; Editor editor; editor.setFixedWidth(220); editor.rehighlight(); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2 [gypq]")); editor.setCursorPosition(editor.text().size()); const int singleLineHeight = editor.height(); const int singleLineTextHeight = EditorGeometryTestHelpers::visibleTextHeight(editor); QVERIFY(editor.cursorRect().bottom() < editor.viewport()->height()); editor.setText(QStringLiteral("1\n2\n3\n4\n5")); QCOMPARE(editor.height() - singleLineHeight, EditorGeometryTestHelpers::visibleTextHeight(editor) - singleLineTextHeight); const QString input = QStringLiteral("1234567890+").repeated(30); editor.setText(input); editor.setCursorPosition(input.size()); QTRY_VERIFY(editor.document()->firstBlock().layout()->lineCount() > 5); QTRY_COMPARE(editor.height() - singleLineHeight, EditorGeometryTestHelpers::visibleTextHeight(editor) - singleLineTextHeight); QTRY_VERIFY(editor.cursorRect().top() >= 0); QTRY_VERIFY(editor.cursorRect().bottom() < editor.viewport()->height()); QTest::keyClicks(&editor, QStringLiteral("2")); QCOMPARE(editor.text(), input + QStringLiteral("2")); settings->editorDisplayStyle = Settings::EditorDisplayModern; editor.rehighlight(); QTRY_VERIFY(editor.cursorRect().top() >= 0); QTRY_VERIFY(editor.cursorRect().bottom() < editor.viewport()->height()); editor.undo(); QCOMPARE(editor.text(), input); settings->editorDisplayStyle = Settings::EditorDisplayClassic; editor.rehighlight(); editor.redo(); QCOMPARE(editor.text(), input + QStringLiteral("2")); QTRY_VERIFY(editor.cursorRect().top() >= 0); QTRY_VERIFY(editor.cursorRect().bottom() < editor.viewport()->height()); } void TestEditorUi::classic_completion_popups_follow_text_inset_data() { QTest::addColumn("constant"); QTest::newRow("symbol-completion") << false; QTest::newRow("constant-completion") << true; } void TestEditorUi::classic_completion_popups_follow_text_inset() { QFETCH(bool, constant); Settings::instance()->editorDisplayStyle = Settings::EditorDisplayClassic; Editor editor; editor.setAutoCompletionEnabled(false); editor.setFixedWidth(340); editor.rehighlight(); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QRect screen = editor.screen()->availableGeometry(); editor.move(screen.left() + 20, screen.top() + 80); editor.setText(constant ? QString() : QStringLiteral("co")); editor.setCursorPosition(editor.text().size()); QCoreApplication::processEvents(); QWidget* popup = nullptr; if (constant) { QTest::keyClick(&editor, Qt::Key_Space, Qt::ControlModifier); popup = QApplication::activePopupWidget(); } else { auto* completion = editor.findChild(); QVERIFY(completion); completion->showCompletion({QStringLiteral("cos:Cosine"), QStringLiteral("cosh:Hyperbolic cosine")}); popup = s_completionPopupTree(); } QVERIFY(popup); const int textX = editor.mapToGlobal(QPoint(UiConfig::ClassicTextInset, 0)).x(); QCOMPARE(popup->geometry().left(), textX); QVERIFY(screen.contains(popup->geometry())); popup->hide(); } void TestEditorUi::editor_height_adds_only_one_line_height_per_visible_line() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setText(QStringLiteral("1")); const int singleLineHeight = editor.height(); const int singleLineTextHeight = EditorGeometryTestHelpers::visibleTextHeight(editor); editor.setText(QStringLiteral("1\n2\n3\n4\n5")); QCOMPARE(editor.height() - singleLineHeight, EditorGeometryTestHelpers::visibleTextHeight(editor) - singleLineTextHeight); } void TestEditorUi::editor_keeps_unit_descenders_inside_viewport() { Editor editor; editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); editor.setText(QStringLiteral("2 [gypq]")); editor.setCursorPosition(editor.text().size()); QVERIFY(editor.cursorRect().bottom() < editor.viewport()->rect().bottom()); } void TestEditorUi::adding_second_wrapped_character_keeps_first_line_visible() { Editor editor; editor.setFixedWidth(260); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); const QString prefix(QStringLiteral("12345678901234567890")); editor.setText(prefix); editor.setCursorPosition(editor.text().size()); while (editor.document()->begin().layout()->lineCount() < 2) editor.insert(QStringLiteral("1")); const int firstWrappedScrollValue = editor.verticalScrollBar()->value(); editor.insert(QStringLiteral("2")); QCOMPARE(editor.document()->begin().layout()->lineCount(), 2); QCOMPARE(firstWrappedScrollValue, 0); QCOMPARE(editor.verticalScrollBar()->value(), 0); } void TestEditorUi::editor_fill_color_is_15_percent_lighter_for_dark_background_role() { Settings* settings = Settings::instance(); const QString oldColorScheme = settings->colorScheme; const QString oldCustomColorSchemeJson = settings->customColorSchemeJson; QJsonObject colors; colors.insert(QStringLiteral("background"), QStringLiteral("#202020")); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(colors); Editor editor; editor.rehighlight(); const QColor expected = QColor(QStringLiteral("#202020")).lighter(115); const QColor activeBase = editor.palette().color(QPalette::Active, QPalette::Base); const QColor inactiveBase = editor.palette().color(QPalette::Inactive, QPalette::Base); QCOMPARE(activeBase.name(QColor::HexArgb), expected.name(QColor::HexArgb)); QCOMPARE(inactiveBase.name(QColor::HexArgb), expected.name(QColor::HexArgb)); settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; } void TestEditorUi::editor_fill_color_is_15_percent_darker_for_light_background_role() { Settings* settings = Settings::instance(); const QString oldColorScheme = settings->colorScheme; const QString oldCustomColorSchemeJson = settings->customColorSchemeJson; QJsonObject colors; colors.insert(QStringLiteral("background"), QStringLiteral("#d0d0d0")); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(colors); Editor editor; editor.rehighlight(); const QColor expected = QColor(QStringLiteral("#d0d0d0")).darker(115); const QColor activeBase = editor.palette().color(QPalette::Active, QPalette::Base); const QColor inactiveBase = editor.palette().color(QPalette::Inactive, QPalette::Base); QCOMPARE(activeBase.name(QColor::HexArgb), expected.name(QColor::HexArgb)); QCOMPARE(inactiveBase.name(QColor::HexArgb), expected.name(QColor::HexArgb)); settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; } void TestEditorUi::themed_cursor_has_only_two_states_at_display_scale_data() { QTest::addColumn("scale"); QTest::newRow("100-percent") << qreal(1); QTest::newRow("125-percent") << qreal(1.25); QTest::newRow("150-percent") << qreal(1.5); QTest::newRow("200-percent") << qreal(2); } void TestEditorUi::themed_cursor_has_only_two_states_at_display_scale() { QFETCH(qreal, scale); Editor editor; editor.setAutoCalcEnabled(false); editor.setAutoCompletionEnabled(false); const QColor primary(QStringLiteral("#ff3377")); editor.setThemePrimaryColor(primary, false); editor.setText(QStringLiteral("123")); editor.setCursorPosition(3); editor.resize(400, editor.height()); editor.show(); editor.activateWindow(); editor.setFocus(); QTRY_VERIFY(editor.hasFocus()); const QRect cursor = editor.cursorRect(); const QRect themedCursor(cursor.x() + (cursor.width() - 2) / 2, cursor.y(), 2, cursor.height()); const QRect sample(qFloor((themedCursor.left() - 2) * scale), qFloor(themedCursor.center().y() * scale), qCeil(6 * scale), 1); const auto render = [&]() { QImage image(QSize(qCeil(editor.viewport()->width() * scale), qCeil(editor.viewport()->height() * scale)), QImage::Format_ARGB32_Premultiplied); image.setDevicePixelRatio(scale); image.fill(Qt::transparent); QPainter painter(&image); editor.viewport()->render(&painter); return image; }; editor.setCustomCursorVisible(false); const QImage hidden = render(); QImage visible = hidden.copy(); { QPainter painter(&visible); painter.fillRect(themedCursor, primary); } const QImage hiddenSample = hidden.copy(sample); const QImage visibleSample = visible.copy(sample); QVERIFY(hiddenSample != visibleSample); // Even a hidden custom cursor must not leave Qt's independently blinking // zero-width cursor behind at fractional display scales. const int flashTime = qMax(1000, QApplication::cursorFlashTime()); QElapsedTimer elapsed; elapsed.start(); while (elapsed.elapsed() < flashTime) { QVERIFY(render().copy(sample) == hiddenSample); QTest::qWait(20); } editor.setCustomCursorVisible(true); bool sawVisible = false; bool sawHidden = false; elapsed.restart(); while (elapsed.elapsed() < flashTime * 2) { const QImage actual = render().copy(sample); QVERIFY2(actual == visibleSample || actual == hiddenSample, "Cursor shows an extra color or width during its blink cycle"); sawVisible |= actual == visibleSample; sawHidden |= actual == hiddenSample; QTest::qWait(20); } QVERIFY(sawVisible); QVERIFY(sawHidden); } void TestEditorUi::non_blinking_cursor_stays_visible_data() { QTest::addColumn("scale"); QTest::newRow("100-percent") << qreal(1); QTest::newRow("125-percent") << qreal(1.25); QTest::newRow("150-percent") << qreal(1.5); } void TestEditorUi::non_blinking_cursor_stays_visible() { QFETCH(qreal, scale); Editor editor; editor.setAutoCalcEnabled(false); editor.setAutoCompletionEnabled(false); const QColor primary(QStringLiteral("#ff3377")); editor.setThemePrimaryColor(primary, false); editor.setText(QStringLiteral("123")); editor.setCursorPosition(3); editor.resize(400, editor.height()); editor.show(); editor.activateWindow(); editor.setFocus(); QTRY_VERIFY(editor.hasFocus()); QVERIFY(editor.isCursorBlinkingEnabled()); const auto cursorPixel = [&]() { QImage image(QSize(qCeil(editor.viewport()->width() * scale), qCeil(editor.viewport()->height() * scale)), QImage::Format_ARGB32_Premultiplied); image.setDevicePixelRatio(scale); image.fill(Qt::transparent); QPainter painter(&image); editor.viewport()->render(&painter); const QRect cursor = editor.cursorRect(); const int cursorX = cursor.x() + (cursor.width() - 2) / 2 + 1; return image.pixelColor(qFloor(cursorX * scale), qFloor(cursor.center().y() * scale)); }; const int flashTime = qMax(1000, QApplication::cursorFlashTime()); QTRY_VERIFY_WITH_TIMEOUT(cursorPixel().rgba() != primary.rgba(), flashTime * 2); editor.setCursorBlinkingEnabled(false); QCOMPARE(cursorPixel().rgba(), primary.rgba()); // Editing, focus changes and theme updates must keep the cursor steady. QTest::keyClick(&editor, Qt::Key_Left); QTest::keyClick(&editor, Qt::Key_4); editor.clearFocus(); QVERIFY(cursorPixel().rgba() != primary.rgba()); editor.setFocus(); QTRY_VERIFY(editor.hasFocus()); editor.setThemePrimaryColor(primary, false); QElapsedTimer elapsed; elapsed.start(); while (elapsed.elapsed() < flashTime * 2) { QCOMPARE(cursorPixel().rgba(), primary.rgba()); QTest::qWait(20); } editor.setCustomCursorVisible(false); QVERIFY(cursorPixel().rgba() != primary.rgba()); editor.setCustomCursorVisible(true); QCOMPARE(cursorPixel().rgba(), primary.rgba()); editor.setCursorBlinkingEnabled(true); QTRY_VERIFY_WITH_TIMEOUT(cursorPixel().rgba() != primary.rgba(), flashTime * 2); QTRY_COMPARE_WITH_TIMEOUT(cursorPixel().rgba(), primary.rgba(), flashTime * 2); } void TestEditorUi::cursor_blinking_survives_settings_reload() { Settings* settings = Settings::instance(); QVERIFY(settings->cursorBlinking); for (bool enabled : {false, true}) { settings->cursorBlinking = enabled; settings->save(); settings->cursorBlinking = !enabled; settings->load(); QCOMPARE(settings->cursorBlinking, enabled); Editor editor; QCOMPARE(editor.isCursorBlinkingEnabled(), enabled); } settings->cursorBlinking = false; QVERIFY(settings->resetToDefaults()); QVERIFY(settings->cursorBlinking); } void TestEditorUi::cursor_free_painting_preserves_text_and_selections_data() { QTest::addColumn("text"); QTest::addColumn("selectText"); QTest::newRow("placeholder") << QString() << false; QTest::newRow("syntax-highlighting") << QStringLiteral("sin(123) + 456") << false; QTest::newRow("selected-wrapped-text") << QStringLiteral("123 + 456 + 789 + 123 + 456 + 789 + 123 + 456\n123 + 456") << true; QTest::newRow("full-width-selection") << QStringLiteral("123\n456\n789") << false; } void TestEditorUi::cursor_free_painting_preserves_text_and_selections() { QFETCH(QString, text); QFETCH(bool, selectText); class NativePaintingEditor : public Editor { protected: void paintEvent(QPaintEvent* event) override { QPlainTextEdit::paintEvent(event); } }; NativePaintingEditor reference; Editor editor; for (Editor* target : { static_cast(&reference), &editor }) { target->setAutoCalcEnabled(false); target->setAutoCompletionEnabled(false); target->setThemePrimaryColor(QColor(QStringLiteral("#ff3377")), false); target->setPlaceholderText(QStringLiteral("Enter an expression")); target->setText(text); target->setCursorPosition(0); target->setCustomCursorVisible(false); target->setTextInteractionFlags(Qt::TextSelectableByMouse); target->resize(220, target->height()); target->show(); if (selectText) target->selectAll(); if (qstrcmp(QTest::currentDataTag(), "full-width-selection") == 0) { QTextEdit::ExtraSelection selection; selection.cursor = target->textCursor(); selection.cursor.setPosition(4); selection.format.setBackground(QColor(QStringLiteral("#557799"))); selection.format.setProperty(QTextFormat::FullWidthSelection, true); target->setExtraSelections({ selection }); // Exercise explicit block backgrounds as well as extra selections. QTextCursor blockCursor(target->document()); QTextBlockFormat format; format.setBackground(QColor(QStringLiteral("#774455"))); blockCursor.setBlockFormat(format); } } QCoreApplication::processEvents(); reference.clearFocus(); editor.clearFocus(); const QImage expected = reference.viewport()->grab().toImage(); const QImage actual = editor.viewport()->grab().toImage(); QVERIFY2(actual == expected, "Cursor-free painting changes Qt's text, background, or selection rendering"); } void TestEditorUi::input_digit_grouping_formats_only_integer_digits_data() { QTest::addColumn("input"); QTest::addColumn>("positions"); QTest::newRow("short") << QStringLiteral("999") << QList{}; QTest::newRow("thousand") << QStringLiteral("1000") << QList{0}; QTest::newRow("million") << QStringLiteral("1234567") << QList{0, 3}; QTest::newRow("fraction") << QStringLiteral("1234.56789") << QList{0}; QTest::newRow("comma-fraction") << QStringLiteral("1234,56789") << QList{0}; QTest::newRow("fraction-only") << QStringLiteral("0.1234567") << QList{}; QTest::newRow("scientific") << QStringLiteral("1000e1234") << QList{0}; QTest::newRow("hex") << QStringLiteral("0x12345") << QList{2}; QTest::newRow("hex-alias") << QStringLiteral("#12345") << QList{1}; QTest::newRow("binary") << QStringLiteral("0b10101010") << QList{5}; QTest::newRow("octal") << QStringLiteral("0o1234567") << QList{2, 5}; QTest::newRow("decimal-prefix") << QStringLiteral("0d1234567") << QList{2, 5}; QTest::newRow("expression") << QStringLiteral("1000 + 20000") << QList{0, 8}; QTest::newRow("identifier-comment") << QStringLiteral("x1234 ? 1000") << QList{}; QTest::newRow("unit-power") << QStringLiteral("1000[m²] + 2000") << QList{0, 11}; QTest::newRow("manual-spaces") << QStringLiteral("1 234 567") << QList{}; QTest::newRow("manual-underscores") << QStringLiteral("1_234_567") << QList{}; } void TestEditorUi::input_digit_grouping_formats_only_integer_digits() { QFETCH(QString, input); QFETCH(QList, positions); Settings* settings = Settings::instance(); settings->numberFormatStyle = Settings::NumberFormatThreeDigitSpaceDot; settings->applyNumberFormatStyle(); QPlainTextEdit inputEdit; SyntaxHighlighter inputHighlighter(&inputEdit, true); inputEdit.setPlainText(input); QPlainTextEdit display; SyntaxHighlighter displayHighlighter(&display); display.setPlainText(input); auto groupedPositions = [](QPlainTextEdit& edit) { QList result; for (const auto& range : edit.document()->firstBlock().layout()->formats()) { if (range.format.hasProperty(SyntaxHighlighter::InputDigitSeparator)) { for (int pos = range.start; pos < range.start + range.length; ++pos) result.append(pos); } } return result; }; for (bool highlighting : {true, false}) { settings->syntaxHighlighting = highlighting; for (bool grouping : {false, true, false}) { settings->inputDigitGrouping = grouping; inputHighlighter.rehighlight(); displayHighlighter.rehighlight(); QCOMPARE(groupedPositions(inputEdit), grouping ? positions : QList{}); QVERIFY(groupedPositions(display).isEmpty()); QCOMPARE(inputEdit.toPlainText(), input); } } } void TestEditorUi::input_digit_grouping_preserves_typing_selection_and_undo() { Settings::instance()->numberFormatStyle = Settings::NumberFormatThreeDigitSpaceDot; Settings::instance()->applyNumberFormatStyle(); Settings::instance()->inputDigitGrouping = true; Editor editor; editor.setAutoCalcEnabled(false); editor.setAutoCompletionEnabled(false); editor.show(); QTest::keyClicks(&editor, "1000"); editor.rehighlight(); QCOMPARE(editor.text(), QStringLiteral("1000")); QCOMPARE(editor.textCursor().position(), 4); bool hasGap = false; for (const auto& range : editor.document()->firstBlock().layout()->formats()) hasGap |= range.format.hasProperty(SyntaxHighlighter::InputDigitSeparator); QVERIFY(hasGap); QTest::keyClick(&editor, Qt::Key_Left); QCOMPARE(editor.textCursor().position(), 3); QTest::keyClick(&editor, Qt::Key_Backspace); QCOMPARE(editor.text(), QStringLiteral("100")); editor.undo(); QCOMPARE(editor.text(), QStringLiteral("1000")); editor.redo(); QCOMPARE(editor.text(), QStringLiteral("100")); editor.undo(); editor.selectAll(); editor.copy(); QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("1000")); const QTextCursor before = editor.textCursor(); Settings::instance()->inputDigitGrouping = false; editor.rehighlight(); QCOMPARE(editor.textCursor().position(), before.position()); QCOMPARE(editor.textCursor().anchor(), before.anchor()); editor.undo(); QCOMPARE(editor.text(), QStringLiteral("100")); } void TestEditorUi::input_digit_grouping_follows_number_format_data() { QTest::addColumn("style"); QTest::addColumn("expected"); QTest::newRow("ungrouped-dot") << int(Settings::NumberFormatNoGroupingDot) << QStringLiteral("1234567.1234567"); QTest::newRow("ungrouped-comma") << int(Settings::NumberFormatNoGroupingComma) << QStringLiteral("1234567,1234567"); QTest::newRow("si-dot") << int(Settings::NumberFormatSIDot) << QStringLiteral("1 234 567.123 456 7"); QTest::newRow("si-comma") << int(Settings::NumberFormatSIComma) << QStringLiteral("1 234 567,123 456 7"); QTest::newRow("comma-dot") << int(Settings::NumberFormatThreeDigitCommaDot) << QStringLiteral("1,234,567.1234567"); QTest::newRow("comma-dot-fraction") << int(Settings::NumberFormatThreeDigitCommaDotFraction) << QStringLiteral("1,234,567.123,456,7"); QTest::newRow("dot-comma") << int(Settings::NumberFormatThreeDigitDotComma) << QStringLiteral("1.234.567,1234567"); QTest::newRow("dot-comma-fraction") << int(Settings::NumberFormatThreeDigitDotCommaFraction) << QStringLiteral("1.234.567,123.456.7"); QTest::newRow("space-dot") << int(Settings::NumberFormatThreeDigitSpaceDot) << QStringLiteral("1 234 567.1234567"); QTest::newRow("space-comma") << int(Settings::NumberFormatThreeDigitSpaceComma) << QStringLiteral("1 234 567,1234567"); QTest::newRow("underscore-dot") << int(Settings::NumberFormatThreeDigitUnderscoreDot) << QStringLiteral("1_234_567.1234567"); QTest::newRow("underscore-dot-fraction") << int(Settings::NumberFormatThreeDigitUnderscoreDotFraction) << QStringLiteral("1_234_567.123_456_7"); QTest::newRow("underscore-comma") << int(Settings::NumberFormatThreeDigitUnderscoreComma) << QStringLiteral("1_234_567,1234567"); QTest::newRow("underscore-comma-fraction") << int(Settings::NumberFormatThreeDigitUnderscoreCommaFraction) << QStringLiteral("1_234_567,123_456_7"); QTest::newRow("indian") << int(Settings::NumberFormatIndianCommaDot) << QStringLiteral("12,34,567.1234567"); } void TestEditorUi::input_digit_grouping_follows_number_format() { QFETCH(int, style); QFETCH(QString, expected); Settings* settings = Settings::instance(); settings->numberFormatStyle = static_cast(style); settings->applyNumberFormatStyle(); settings->inputDigitGrouping = true; const QString raw = QStringLiteral("1234567") + QChar(settings->decimalSeparator()) + QStringLiteral("1234567"); Editor editor; editor.setText(raw); editor.rehighlight(); const auto displayedText = [&editor]() { QString display = editor.text(); const auto ranges = editor.document()->firstBlock().layout()->formats(); for (auto it = ranges.crbegin(); it != ranges.crend(); ++it) { const QString radix = it->format.stringProperty(SyntaxHighlighter::InputRadixReplacement); if (!radix.isEmpty()) display.replace(it->start, 1, radix); const QString separator = it->format.stringProperty(SyntaxHighlighter::InputDigitSeparator); if (!separator.isEmpty()) { for (int pos = it->start + it->length - 1; pos >= it->start; --pos) display.insert(pos + 1, separator); } } return display; }; for (bool syntaxHighlighting : {true, false}) { settings->syntaxHighlighting = syntaxHighlighting; editor.rehighlight(); QCOMPARE(displayedText(), expected); QCOMPARE(editor.text(), raw); QCOMPARE(NumberFormatter::formatNumericLiteralForDisplay(raw), expected); } if (settings->decimalSeparator() == ',') { editor.setText(QStringLiteral("1234567.1234567")); editor.rehighlight(); QCOMPARE(displayedText(), expected); } editor.setText(expected); editor.rehighlight(); QCOMPARE(displayedText(), expected); settings->inputDigitGrouping = false; editor.setText(raw); editor.rehighlight(); QCOMPARE(displayedText(), raw); } void TestEditorUi::input_digit_grouping_paints_separator_glyphs_data() { QTest::addColumn("themed"); QTest::addColumn("selected"); QTest::newRow("native") << false << false; QTest::newRow("native-selected") << false << true; QTest::newRow("themed") << true << false; QTest::newRow("themed-selected") << true << true; } void TestEditorUi::input_digit_grouping_paints_separator_glyphs() { QFETCH(bool, themed); QFETCH(bool, selected); Settings* settings = Settings::instance(); settings->inputDigitGrouping = true; Editor editor; QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont); font.setPointSize(20); editor.setFont(font); editor.setAutoCalcEnabled(false); editor.setAutoCompletionEnabled(false); editor.resize(600, 120); editor.show(); editor.clearFocus(); editor.setThemePrimaryColor(themed ? QColor(QStringLiteral("#2277aa")) : QColor(), false); for (auto style : {Settings::NumberFormatThreeDigitCommaDot, Settings::NumberFormatThreeDigitDotComma, Settings::NumberFormatThreeDigitUnderscoreDot}) { settings->numberFormatStyle = style; settings->applyNumberFormatStyle(); editor.setText(QStringLiteral("1234567.56")); editor.rehighlight(); if (selected) editor.selectAll(); QCoreApplication::processEvents(); editor.clearFocus(); const auto separatorWidth = [&editor]() { for (const auto& range : editor.document()->firstBlock().layout()->formats()) { if (range.format.hasProperty(SyntaxHighlighter::InputDigitSeparator)) return range.format.fontLetterSpacing(); } return qreal(0); }; const QString separator = settings->digitGroupingSeparator(); QCOMPARE(separatorWidth(), QFontMetricsF(editor.font()).horizontalAdvance(separator)); editor.increaseFontPointSize(); // Hinting can give adjacent point sizes the same glyph width. // The gap must follow the current font's metrics in either case. QCOMPARE(separatorWidth(), QFontMetricsF(editor.font()).horizontalAdvance(separator)); QVERIFY(separatorWidth() > 0); const QImage withSeparators = editor.viewport()->grab().toImage(); QTextLayout* layout = editor.document()->firstBlock().layout(); auto formats = layout->formats(); for (auto& range : formats) { range.format.clearProperty(SyntaxHighlighter::InputDigitSeparator); range.format.clearProperty(SyntaxHighlighter::InputRadixReplacement); } layout->setFormats(formats); editor.viewport()->update(); const QImage withoutSeparators = editor.viewport()->grab().toImage(); QVERIFY2(withSeparators != withoutSeparators, "Input separators must paint glyphs, not just gaps"); } } void TestEditorUi::history_recall_respects_input_adjustments_data() { QTest::addColumn("stored"); QTest::addColumn("raw"); QTest::addColumn("adjustments"); const QList> expressions { {QString::fromUtf8("2³"), QStringLiteral("2^3")}, {QString::fromUtf8("2¹²"), QStringLiteral("2^12")}, {QString::fromUtf8("2�³"), QStringLiteral("2^(-3)")}, {QString::fromUtf8("sin²(1)"), QStringLiteral("sin(1)^2")}, {QString::fromUtf8("sin²(1)³"), QStringLiteral("(sin(1)^2)^3")}, {QString::fromUtf8("2[m²/s�³]"), QStringLiteral("2[m^2/s^(-3)]")}, {QString::fromUtf8("2 × 3 · 4 / 2 − 1"), QStringLiteral("2 * 3 * 4 / 2 - 1")}, {QString::fromUtf8("2[m] → [cm]"), QStringLiteral("2[m] -> [cm]")}, {QString::fromUtf8("2³ ? 4² × pi -> [m] ?\t"), QString::fromUtf8("2^3 ? 4² × pi -> [m] ?\t")} }; for (int i = 0; i < expressions.size(); ++i) { for (bool adjustments : {false, true}) { QTest::newRow(qPrintable(QStringLiteral("%1-%2").arg(i).arg(adjustments))) << expressions.at(i).first << expressions.at(i).second << adjustments; } } } void TestEditorUi::history_recall_respects_input_adjustments() { QFETCH(QString, stored); QFETCH(QString, raw); QFETCH(bool, adjustments); Settings::instance()->automaticInputAdjustments = adjustments; Session session; session.addHistoryEntry(HistoryEntry(QStringLiteral("7"), Quantity(7))); session.addHistoryEntry(HistoryEntry(stored, Quantity(8))); Editor editor; editor.setSession(&session); editor.setAutoCompletionEnabled(false); editor.setAutoCalcEnabled(false); const QString draft = QString::fromUtf8("unfinished² ? keep ×"); editor.setText(draft); QVERIFY(QMetaObject::invokeMethod(&editor, "historyBack")); const QString expected = adjustments ? stored : raw; QCOMPARE(editor.text(), expected); QCOMPARE(editor.cursorPosition(), expected.size()); QVERIFY(QMetaObject::invokeMethod(&editor, "historyBack")); QCOMPARE(editor.text(), QStringLiteral("7")); QVERIFY(QMetaObject::invokeMethod(&editor, "historyForward")); QCOMPARE(editor.text(), expected); QVERIFY(QMetaObject::invokeMethod(&editor, "historyForward")); QCOMPARE(editor.text(), draft); QCOMPARE(session.historyEntryAtRef(1).expr(), stored); Evaluator evaluator; evaluator.setExpression(evaluator.autoFix(stored)); const QString originalResult = NumberFormatter::format(evaluator.eval()); QVERIFY2(evaluator.error().isEmpty(), qPrintable(evaluator.error())); evaluator.setExpression(evaluator.autoFix(expected)); QCOMPARE(NumberFormatter::format(evaluator.eval()), originalResult); QVERIFY2(evaluator.error().isEmpty(), qPrintable(evaluator.error())); } void TestEditorUi::raw_input_preserves_text_data() { QTest::addColumn("input"); QTest::newRow("operators") << QStringLiteral("1+2*3/4--5**2"); QTest::newRow("powers") << QStringLiteral("2^3 + 2[m^2]"); QTest::newRow("spaces-and-brackets") << QStringLiteral(" 2 (3) [m] ?text"); QTest::newRow("invalid-characters") << QStringLiteral("@|++^^[ +3?{}]"); QTest::newRow("decimal-and-units") << QStringLiteral(".5[m / s^2]"); QTest::newRow("unicode") << QString::fromUtf8("2 × 3 ÷ 4 − 5 → [µm²]"); } void TestEditorUi::raw_input_preserves_text() { QFETCH(QString, input); Settings::instance()->automaticInputAdjustments = false; for (int source = 0; source < 4; ++source) { Editor editor; editor.setAutoCompletionEnabled(false); editor.setAutoCalcEnabled(false); switch (source) { case 0: // Qt's keyClicks only supports ASCII. Send Unicode text through // key events too, as keyboard layouts can produce these glyphs. for (QChar ch : input) { QKeyEvent key(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, QString(ch)); QApplication::sendEvent(&editor, &key); } break; case 1: for (QChar ch : input) { QInputMethodEvent commit; commit.setCommitString(QString(ch)); QApplication::sendEvent(&editor, &commit); } break; case 2: editor.insert(input); break; case 3: editor.setText(input); break; } QCOMPARE(editor.text(), input); editor.setCursorPosition(editor.text().size()); QInputMethodEvent replacement; replacement.setCommitString(QStringLiteral("*^@"), -1, 1); QApplication::sendEvent(&editor, &replacement); QCOMPARE(editor.text(), input.chopped(1) + QStringLiteral("*^@")); editor.selectAll(); QApplication::clipboard()->setText(input); QSignalSpy bulkEvaluation(&editor, &Editor::bulkEvaluationStarted); editor.paste(); QCOMPARE(editor.text(), input.trimmed()); QCOMPARE(bulkEvaluation.count(), 0); editor.undo(); QCOMPARE(editor.text(), input.chopped(1) + QStringLiteral("*^@")); editor.redo(); QCOMPARE(editor.text(), input.trimmed()); } } void TestEditorUi::raw_input_keeps_character_navigation_and_deletion() { Settings::instance()->automaticInputAdjustments = false; Editor editor; editor.setText(QStringLiteral("1 + 2")); editor.setCursorPosition(4); QTest::keyClick(&editor, Qt::Key_Left); QCOMPARE(editor.cursorPosition(), 3); QTest::keyClick(&editor, Qt::Key_Right); QCOMPARE(editor.cursorPosition(), 4); QTest::keyClick(&editor, Qt::Key_Backspace); QCOMPARE(editor.text(), QStringLiteral("1 +2")); editor.undo(); editor.setCursorPosition(1); editor.doDelete(); QCOMPARE(editor.text(), QStringLiteral("1+ 2")); editor.undo(); editor.setCursorPosition(4); editor.doBackspace(); QCOMPARE(editor.text(), QStringLiteral("1 +2")); editor.undo(); editor.setCursorPosition(1); QTest::keyClick(&editor, Qt::Key_Delete); QCOMPARE(editor.text(), QStringLiteral("1+ 2")); } void TestEditorUi::raw_input_preserves_calculator_commands() { Settings::instance()->automaticInputAdjustments = false; Editor editor; editor.setAutoCompletionEnabled(false); QTest::keyClicks(&editor, "2^3"); QCOMPARE(editor.text(), QStringLiteral("2^3")); QSignalSpy enter(&editor, &Editor::returnPressed); QSignalSpy escape(&editor, &Editor::escapePressed); QTest::keyClick(&editor, Qt::Key_Return); QCOMPARE(enter.count(), 1); QCOMPARE(editor.text(), QStringLiteral("2^3")); QTest::keyClick(&editor, Qt::Key_Escape); QCOMPARE(escape.count(), 1); QTest::keyClick(&editor, Qt::Key_Tab); QCOMPARE(editor.text(), QStringLiteral("2^3")); editor.setHistoryArrowNavigationEnabled(false); QTest::keyClick(&editor, Qt::Key_Home); QTest::keyClick(&editor, Qt::Key_Right, Qt::ShiftModifier); QCOMPARE(editor.textCursor().selectedText(), QStringLiteral("2")); QTest::keyClicks(&editor, "@"); QCOMPARE(editor.text(), QStringLiteral("@^3")); } void TestEditorUi::raw_input_switch_preserves_document_and_restores_adjustments() { Settings::instance()->automaticInputAdjustments = false; Editor editor; editor.setAutoCompletionEnabled(false); editor.setAutoCalcEnabled(false); editor.setText(QStringLiteral("1+2*3^4")); editor.setCursorPosition(3); QTextCursor cursor = editor.textCursor(); cursor.setPosition(5, QTextCursor::KeepAnchor); editor.setTextCursor(cursor); QSignalSpy changed(&editor, &Editor::textChanged); Settings::instance()->automaticInputAdjustments = true; editor.refreshInputMode(); QCOMPARE(changed.count(), 0); QCOMPARE(editor.text(), QStringLiteral("1+2*3^4")); QCOMPARE(editor.textCursor().position(), 5); QCOMPARE(editor.textCursor().anchor(), 3); editor.clear(); QTest::keyClicks(&editor, "2^3"); QCOMPARE(editor.text(), QString::fromUtf8("2³")); Settings::instance()->automaticInputAdjustments = false; editor.refreshInputMode(); QTest::keyClicks(&editor, "+4"); QCOMPARE(editor.text(), QString::fromUtf8("2³+4")); } void TestEditorUi::raw_input_preserves_visible_digit_grouping() { Settings* settings = Settings::instance(); settings->automaticInputAdjustments = false; settings->inputDigitGrouping = true; settings->digitGrouping = 3; settings->numberFormatStyle = Settings::NumberFormatThreeDigitCommaDot; settings->applyNumberFormatStyle(); Editor editor; editor.setAutoCompletionEnabled(false); editor.setAutoCalcEnabled(false); editor.setText(QStringLiteral("1234567.123456")); editor.setCustomCursorVisible(false); editor.refreshInputMode(); editor.setFixedWidth(500); editor.show(); QCoreApplication::processEvents(); bool hasSeparator = false; for (const auto& range : editor.document()->firstBlock().layout()->formats()) { hasSeparator |= range.format.hasProperty(SyntaxHighlighter::InputDigitSeparator); } QVERIFY(hasSeparator); const QImage raw = editor.viewport()->grab().toImage(); settings->automaticInputAdjustments = true; editor.refreshInputMode(); QCOMPARE(raw, editor.viewport()->grab().toImage()); settings->automaticInputAdjustments = false; editor.refreshInputMode(); QCOMPARE(raw, editor.viewport()->grab().toImage()); settings->inputDigitGrouping = false; settings->digitGrouping = 0; editor.rehighlight(); QVERIFY(raw != editor.viewport()->grab().toImage()); for (const auto& range : editor.document()->firstBlock().layout()->formats()) QVERIFY(!range.format.hasProperty(SyntaxHighlighter::InputDigitSeparator)); QCOMPARE(editor.text(), QStringLiteral("1234567.123456")); } void TestEditorUi::raw_input_preserves_tab_completion_data() { QTest::addColumn("rawInput"); QTest::newRow("automatic-editing") << false; QTest::newRow("raw-input") << true; } void TestEditorUi::raw_input_preserves_tab_completion() { QFETCH(bool, rawInput); Settings::instance()->automaticInputAdjustments = !rawInput; Editor editor; editor.setAutoCalcEnabled(false); editor.show(); QVERIFY(QTest::qWaitForWindowExposed(&editor)); editor.setFocus(); QTest::keyClicks(&editor, "co"); QVERIFY(QMetaObject::invokeMethod(&editor, "triggerAutoComplete", Qt::DirectConnection)); QTreeWidget* popup = nullptr; QTRY_VERIFY_WITH_TIMEOUT((popup = s_completionPopupTree()) != nullptr, 1000); QTreeWidgetItem* selected = nullptr; for (int i = 0; i < popup->topLevelItemCount(); ++i) { QTreeWidgetItem* item = popup->topLevelItem(i); if (item->text(1) == QStringLiteral("cos")) { selected = item; break; } } QVERIFY(selected); popup->setCurrentItem(selected); QTest::keyClick(&editor, Qt::Key_Tab); QCOMPARE(editor.text(), QStringLiteral("cos") + MathDsl::GroupStart + MathDsl::GroupEnd); QCOMPARE(editor.cursorPosition(), editor.text().size() - 1); QTRY_VERIFY_WITH_TIMEOUT(s_editorOrViewportHasFocus(&editor), 1000); } void TestEditorUi::automatic_input_adjustments_survive_settings_reload() { Settings* settings = Settings::instance(); QVERIFY(settings->automaticInputAdjustments); for (bool enabled : {true, false}) { settings->automaticInputAdjustments = enabled; settings->save(); settings->automaticInputAdjustments = !enabled; settings->load(); QCOMPARE(settings->automaticInputAdjustments, enabled); } settings->automaticInputAdjustments = false; QVERIFY(settings->resetToDefaults()); QVERIFY(settings->automaticInputAdjustments); } void TestEditorUi::input_digit_grouping_survives_settings_reload() { Settings* settings = Settings::instance(); QVERIFY(settings->inputDigitGrouping); for (bool enabled : {true, false}) { settings->inputDigitGrouping = enabled; settings->numberFormatStyle = Settings::NumberFormatThreeDigitCommaDot; settings->applyNumberFormatStyle(); QCOMPARE(settings->inputDigitGrouping, enabled); settings->save(); settings->inputDigitGrouping = !enabled; settings->load(); QCOMPARE(settings->inputDigitGrouping, enabled); } } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testeditorui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testevaluator.cpp000066400000000000000000017012701526573132500247040ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006-2010, 2013-2019, 2022, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "core/evaluator.h" #include "core/colorscheme.h" #include "core/complexform.h" #include "core/numberformatter.h" #include "core/settings.h" #include "core/session.h" #include "core/sessionjsonkeys.h" #include "core/unicodechars.h" #include "gui/editorutils.h" #include "gui/displayformatutils.h" #include "gui/functiontooltiputils.h" #include "gui/resultdisplay.h" #include "gui/resultlineformatutils.h" #include "gui/simplifiedexpressionutils.h" #include "math/cmath.h" #include "core/mathdsl.h" #include "core/units.h" #include "tests/testcommon.h" #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace { QJsonObject themeJson(QJsonObject colors) { colors.insert(QStringLiteral("$schema"), QString::fromLatin1(ColorScheme::SchemaDraft)); colors.insert(QStringLiteral("$id"), QString::fromLatin1(ColorScheme::SchemaId)); return colors; } QString themeJsonString(QJsonObject colors) { return QString::fromUtf8(QJsonDocument(themeJson(colors)).toJson(QJsonDocument::Compact)); } QJsonObject sessionJson(QJsonObject values = QJsonObject()) { values.insert(QLatin1String(SessionJsonKeys::Schema), QLatin1String(SessionJsonKeys::SchemaDialect)); values.insert(QLatin1String(SessionJsonKeys::Id), QLatin1String(SessionJsonKeys::SchemaId)); return values; } } typedef Quantity::Format Format; static Evaluator* eval = 0; static Session* evalSession = 0; static int eval_total_tests = 0; static int eval_failed_tests = 0; static int eval_new_failed_tests = 0; static const QString space(MathDsl::AddWrap); static const QString slash = space + QString(MathDsl::DivOp) + space; #define CHECK_AUTOFIX(s,p) checkAutoFix(__FILE__,__LINE__,#s,s,p) #define CHECK_DIV_BY_ZERO(s) checkDivisionByZero(__FILE__,__LINE__,#s,s) #define CHECK_EVAL(x,y) checkEval(__FILE__,__LINE__,#x,x,y) #define CHECK_EVAL_FORMAT(x,y) checkEval(__FILE__,__LINE__,#x,x,y,0,false,true) #define CHECK_EVAL_FORMAT_HAS_SLASH(x) checkEvalFormatSlash(__FILE__, __LINE__, #x, x, true) #define CHECK_EVAL_FORMAT_NO_SLASH(x) checkEvalFormatSlash(__FILE__, __LINE__, #x, x, false) #define CHECK_EVAL_FORMAT_MEDIUM_SPACED_SLASH(x) checkEvalFormatMediumSpacedSlash(__FILE__, __LINE__, #x, x) #define CHECK_EVAL_FORMAT_EXACT(x,y) checkEvalFormatExact(__FILE__, __LINE__, #x, x, y) #define CHECK_EVAL_KNOWN_ISSUE(x,y,n) checkEval(__FILE__,__LINE__,#x,x,y,n) #define CHECK_EVAL_PRECISE(x,y) checkEvalPrecise(__FILE__,__LINE__,#x,x,y) #define CHECK_EVAL_FAIL(x) checkEval(__FILE__,__LINE__,#x,x,"",0,true) #define CHECK_EVAL_FORMAT_FAIL(x) checkEval(__FILE__,__LINE__,#x,x,"",0,true,true) #define CHECK_INTERPRETED(x,y) checkInterpreted(__FILE__,__LINE__,#x,x,y) #define CHECK_DISPLAY_INTERPRETED(x,y) checkDisplayInterpreted(__FILE__,__LINE__,#x,x,y) #define CHECK_DISPLAY_SIMPLIFIED_INTERPRETED(x,y) checkDisplaySimplifiedInterpreted(__FILE__,__LINE__,#x,x,y) #define CHECK_USERFUNC_SET(x) checkEval(__FILE__,__LINE__,#x,x,"NaN") #define CHECK_USERFUNC_SET_FAIL(x) checkEval(__FILE__,__LINE__,#x,x,"",0,true) #define CHECK_USERFUNC_DESC(n,d) checkUserFunctionDescription(__FILE__,__LINE__,#n,n,d) #define CHECK_USERFUNC_INTERPRETED(n,e) checkUserFunctionInterpreted(__FILE__,__LINE__,#n,n,e) #define CHECK_USERVAR_DESC(n,d) checkUserVariableDescription(__FILE__,__LINE__,#n,n,d) #define CHECK_USERUNIT_DESC(n,d) checkUserUnitDescription(__FILE__,__LINE__,#n,n,d) static void checkAutoFix(const char* file, int line, const char* msg, const char* expr, const char* fixed) { ++eval_total_tests; string r = eval->autoFix(QString(expr)).toStdString(); DisplayErrorOnMismatch(file, line, msg, r, fixed, eval_failed_tests, eval_new_failed_tests); } static void checkDivisionByZero(const char* file, int line, const char* msg, const QString& expr) { ++eval_total_tests; eval->setExpression(expr); Quantity rn = eval->evalUpdateAns(); if (eval->error().isEmpty()) { ++eval_failed_tests; cerr << file << "[" << line << "]\t" << msg << endl << "\tError: " << "division by zero not caught" << endl; } } static void checkEval(const char* file, int line, const char* msg, const QString& expr, const char* expected, int issue = 0, bool shouldFail = false, bool format = false) { ++eval_total_tests; eval->setExpression(expr); Quantity rn = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { if (!shouldFail) { ++eval_failed_tests; cerr << file << "[" << line << "]\t" << msg; if (issue) cerr << "\t[ISSUE " << issue << "]"; else { cerr << "\t[NEW]"; ++eval_new_failed_tests; } cerr << endl; cerr << "\tError: " << eval->error().toUtf8().constData() << endl; } } else { QString result = (format ? NumberFormatter::format(rn) : DMath::format(rn, Format::Fixed())); result.replace(QString::fromUtf8("−"), "-"); QString expectedText = QString::fromUtf8(expected); if (shouldFail || result != expectedText) { ++eval_failed_tests; cerr << file << "[" << line << "]\t" << msg; if (issue) cerr << "\t[ISSUE " << issue << "]"; else { cerr << "\t[NEW]"; ++eval_new_failed_tests; } cerr << endl; cerr << "\tResult : " << result.toUtf8().constData() << endl << "\tExpected : " << (shouldFail ? "should fail" : expectedText.toUtf8().constData()) << endl; } } } static void checkEvalFormatSlash(const char* file, int line, const char* msg, const QString& expr, bool shouldHaveSlash) { ++eval_total_tests; eval->setExpression(expr); Quantity rn = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } QString result = NumberFormatter::format(rn); result.replace(QString::fromUtf8("−"), "-"); const bool hasSlash = result.contains('/'); if (hasSlash != shouldHaveSlash) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tResult : " << result.toUtf8().constData() << endl << "\tExpected '/' : " << (shouldHaveSlash ? "yes" : "no") << endl; } } static void checkEvalFormatMediumSpacedSlash(const char* file, int line, const char* msg, const QString& expr) { ++eval_total_tests; eval->setExpression(expr); Quantity rn = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } QString result = NumberFormatter::format(rn); result.replace(QString::fromUtf8("−"), "-"); const QString mediumSlash = slash; if (!result.contains(mediumSlash)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tResult : " << result.toUtf8().constData() << endl << "\tExpected medium slash : " << mediumSlash.toUtf8().constData() << endl; } } static void checkEvalFormatExact(const char* file, int line, const char* msg, const QString& expr, const QString& expected) { ++eval_total_tests; eval->setExpression(expr); Quantity rn = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } QString result = NumberFormatter::format(rn); result.replace(QString::fromUtf8("−"), "-"); if (result != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tResult : " << result.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } static void checkEvalPrecise(const char* file, int line, const char* msg, const QString& expr, const char* expected) { ++eval_total_tests; eval->setExpression(expr); Quantity rn = eval->evalUpdateAns(); // We compare up to 50 decimals, not exact number because it's often difficult // to represent the result as an irrational number, e.g. PI. string result = DMath::format(rn, Format::Fixed() + Format::Precision(50)).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, eval_failed_tests, eval_new_failed_tests, 0); } static void checkInterpreted(const char* file, int line, const char* msg, const QString& expr, const char* expected) { ++eval_total_tests; eval->setExpression(expr); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } const QString interpreted = eval->interpretedExpression(); if (interpreted != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tInterpreted: " << interpreted.toUtf8().constData() << endl << "\tExpected : " << expected << endl; } } static string toCodePointList(const QString& text) { const QVector cps = text.toUcs4(); std::ostringstream os; for (int i = 0; i < cps.size(); ++i) { if (i > 0) os << " "; os << "U+" << std::uppercase << std::hex << std::setfill('0') << std::setw(4) << cps.at(i); } return os.str(); } static bool hasSpacedOperatorsInsideUnitBrackets(const QString& text) { int pos = 0; while (true) { const int open = text.indexOf(QLatin1Char('['), pos); if (open < 0) return false; const int close = text.indexOf(QLatin1Char(']'), open + 1); if (close < 0) return false; const QString segment = text.mid(open + 1, close - open - 1); if (segment.contains(QStringLiteral(" ·")) || segment.contains(QStringLiteral("· ")) || segment.contains(QStringLiteral(" ×")) || segment.contains(QStringLiteral("× ")) || segment.contains(QStringLiteral(" /")) || segment.contains(QStringLiteral("/ "))) { return true; } pos = close + 1; } } static void checkDisplayInterpreted(const char* file, int line, const char* msg, const QString& expr, const QString& expected) { ++eval_total_tests; eval->setExpression(eval->autoFix(expr)); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } const QString interpreted = eval->interpretedExpression(); const QString displayed = Evaluator::formatInterpretedExpressionForDisplay(interpreted, eval); if (displayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tDisplayed : " << displayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl << "\tDisplayed code points: " << toCodePointList(displayed) << endl << "\tExpected code points: " << toCodePointList(expected) << endl; } } class TestableResultDisplay : public ResultDisplay { public: explicit TestableResultDisplay(QWidget* parent = 0) : ResultDisplay(parent) { setSession(evalSession); } using ResultDisplay::blockRangeForHistoryIndex; using ResultDisplay::historyIndexAtPosition; using ResultDisplay::markHistoryBlockIndexCacheDirty; using ResultDisplay::mouseDoubleClickEvent; using ResultDisplay::scrollEdgeFadeHeightForCurrentFont; QPoint pointForBlockStart(int blockNumber) const { QTextBlock block = document()->findBlockByNumber(blockNumber); if (!block.isValid()) return QPoint(-1, -1); QTextCursor cursor(block); const QRect rect = cursorRect(cursor); if (!rect.isValid()) return QPoint(-1, -1); return rect.center(); } }; void test_result_display_scroll_edge_gradient_height_scales_with_font_zoom() { TestableResultDisplay display; QFont font = display.font(); font.setPointSize(10); display.setFont(font); const int smallFade = display.scrollEdgeFadeHeightForCurrentFont(); font.setPointSize(14); display.setFont(font); const int mediumFade = display.scrollEdgeFadeHeightForCurrentFont(); font.setPointSize(20); display.setFont(font); const int largeFade = display.scrollEdgeFadeHeightForCurrentFont(); ++eval_total_tests; if (!(smallFade > 0 && mediumFade > 0 && largeFade > 0)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tscroll edge gradient heights stay positive\t[NEW]" << endl << "\tSmall : " << smallFade << endl << "\tMedium : " << mediumFade << endl << "\tLarge : " << largeFade << endl; } ++eval_total_tests; if (!(smallFade < mediumFade && mediumFade < largeFade)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tscroll edge gradient heights scale with font zoom\t[NEW]" << endl << "\tSmall : " << smallFade << endl << "\tMedium : " << mediumFade << endl << "\tLarge : " << largeFade << endl; } } void test_result_display_history_mapping_after_multiple_lines_toggle_with_comment_only_entry() { Settings* settings = Settings::instance(); Session* session = evalSession; const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; const bool oldSecondaryResultEnabled = settings->secondaryResultEnabled; const char oldAlternativeResultFormat = settings->alternativeResultFormat; const int oldSecondaryResultPrecision = settings->secondaryResultPrecision; const bool oldComplexNumbers = settings->complexNumbers; const bool oldSecondaryComplexNumbers = settings->secondaryComplexNumbers; const char oldSecondaryResultComplexForm = settings->secondaryResultComplexForm; settings->multipleResultLinesEnabled = true; settings->secondaryResultEnabled = true; settings->alternativeResultFormat = 'r'; settings->secondaryResultPrecision = -1; settings->complexNumbers = false; settings->secondaryComplexNumbers = false; settings->secondaryResultComplexForm = ComplexForm::Rectangular; session->clearHistory(); session->addHistoryEntry(HistoryEntry(QStringLiteral("2/3"), Quantity(2) / Quantity(3))); session->addHistoryEntry(HistoryEntry(QStringLiteral("? comment-only history entry"), CMath::nan())); session->addHistoryEntry(HistoryEntry(QStringLiteral("1+1"), Quantity(2))); auto checkMapping = [](const char* file, int line, const char* label, TestableResultDisplay& display, int expectedHistorySize) { ++eval_total_tests; if (expectedHistorySize <= 0) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << label << "\t[NEW]" << endl << "\tError: expectedHistorySize <= 0" << endl; return; } for (int historyIndex = 0; historyIndex < expectedHistorySize; ++historyIndex) { int startBlock = -1; int endBlock = -1; const bool hasRange = display.blockRangeForHistoryIndex(historyIndex, startBlock, endBlock); if (!hasRange || startBlock < 0 || endBlock < startBlock) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << label << "\t[NEW]" << endl << "\tInvalid range for history index " << historyIndex << endl; continue; } const QPoint probe = display.pointForBlockStart(startBlock); const int mappedIndex = display.historyIndexAtPosition(probe); if (mappedIndex != historyIndex) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << label << "\t[NEW]" << endl << "\tHistory index: " << historyIndex << endl << "\tMapped index : " << mappedIndex << endl << "\tBlock range : [" << startBlock << ", " << endBlock << "]" << endl; } } }; TestableResultDisplay display; display.resize(800, 600); display.refresh(); const int historySize = session->historySize(); checkMapping(__FILE__, __LINE__, "result display mapping before toggle", display, historySize); settings->multipleResultLinesEnabled = false; display.markHistoryBlockIndexCacheDirty(); checkMapping(__FILE__, __LINE__, "result display mapping after toggle with stale blocks", display, historySize); settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; settings->secondaryResultEnabled = oldSecondaryResultEnabled; settings->alternativeResultFormat = oldAlternativeResultFormat; settings->secondaryResultPrecision = oldSecondaryResultPrecision; settings->complexNumbers = oldComplexNumbers; settings->secondaryComplexNumbers = oldSecondaryComplexNumbers; settings->secondaryResultComplexForm = oldSecondaryResultComplexForm; } static void checkDisplaySimplifiedInterpreted(const char* file, int line, const char* msg, const QString& expr, const QString& expected) { ++eval_total_tests; eval->setExpression(eval->autoFix(expr)); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } const QString interpreted = eval->interpretedExpression(); const QString displayed = Evaluator::formatInterpretedExpressionSimplifiedForDisplay(interpreted, eval); if (displayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tDisplayed : " << displayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl << "\tDisplayed code points: " << toCodePointList(displayed) << endl << "\tExpected code points: " << toCodePointList(expected) << endl; } } static void checkSuppressSimplifiedExpressionLine(const char* file, int line, const char* msg, const QString& expr, bool expectedSuppressed) { ++eval_total_tests; eval->setExpression(expr); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } const QString interpreted = Evaluator::formatInterpretedExpressionForDisplay(eval->interpretedExpression(), eval); const QString simplified = Evaluator::formatInterpretedExpressionSimplifiedForDisplay(eval->interpretedExpression(), eval); const bool suppressed = SimplifiedExpressionUtils::shouldSuppressSimplifiedExpressionLine( interpreted, simplified); if (suppressed != expectedSuppressed) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl << "\tInterpreted: " << interpreted.toUtf8().constData() << endl << "\tSimplified : " << simplified.toUtf8().constData() << endl << "\tSuppressed : " << (suppressed ? "true" : "false") << endl << "\tExpected : " << (expectedSuppressed ? "true" : "false") << endl; } } static void checkUserFunctionDescription(const char* file, int line, const char* msg, const QString& functionName, const QString& expectedDescription) { ++eval_total_tests; const auto userFunctions = eval->getUserFunctions(); for (const auto& function : userFunctions) { if (function.name() == functionName) { if (function.description() != expectedDescription) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl; cerr << "\tDescription: " << function.description().toLatin1().constData() << endl << "\tExpected : " << expectedDescription.toLatin1().constData() << endl; } return; } } ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl; cerr << "\tError: user function not found: " << functionName.toLatin1().constData() << endl; } static void checkUserFunctionInterpreted(const char* file, int line, const char* msg, const QString& functionName, const QString& expectedInterpreted) { ++eval_total_tests; const auto userFunctions = eval->getUserFunctions(); for (const auto& function : userFunctions) { if (function.name() == functionName) { if (function.interpretedExpression() != expectedInterpreted) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl; cerr << "\tInterpreted: " << function.interpretedExpression().toUtf8().constData() << endl << "\tExpected : " << expectedInterpreted.toUtf8().constData() << endl; } return; } } ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl; cerr << "\tError: user function not found: " << functionName.toLatin1().constData() << endl; } static void checkUserVariableDescription(const char* file, int line, const char* msg, const QString& variableName, const QString& expectedDescription) { ++eval_total_tests; if (!eval->hasVariable(variableName)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl; cerr << "\tError: user variable not found: " << variableName.toLatin1().constData() << endl; return; } const auto variable = eval->getVariable(variableName); if (variable.description() != expectedDescription) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl; cerr << "\tDescription: " << variable.description().toLatin1().constData() << endl << "\tExpected : " << expectedDescription.toLatin1().constData() << endl; } } static void checkUserUnitDescription(const char* file, int line, const char* msg, const QString& unitName, const QString& expectedDescription) { ++eval_total_tests; const UserUnit* unit = eval->getUserUnit(unitName); if (!unit) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl; cerr << "\tError: user unit not found: " << unitName.toLatin1().constData() << endl; return; } if (unit->description() != expectedDescription) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << msg << "\t[NEW]" << endl; cerr << "\tDescription: " << unit->description().toLatin1().constData() << endl << "\tExpected : " << expectedDescription.toLatin1().constData() << endl; } } void test_constants() { CHECK_EVAL("1", "1"); CHECK_EVAL_FAIL("pi()"); CHECK_EVAL_FAIL("e()"); CHECK_EVAL_FAIL("ans()"); CHECK_EVAL_FAIL("sqrt(pi())"); CHECK_EVAL_FAIL("cos(pi()"); // Subscript Unicode letters/digits are accepted in identifiers. CHECK_EVAL(QString::fromUtf8("foo₀=2"), "2"); CHECK_EVAL(QString::fromUtf8("foo₀+1"), "3"); CHECK_USERFUNC_SET(QString::fromUtf8("f₀(x)=x+1")); CHECK_EVAL(QString::fromUtf8("f₀(2)"), "3"); CHECK_EVAL(QString::fromUtf8("xᵢ=4"), "4"); CHECK_EVAL(QString::fromUtf8("xᵢ*3"), "12"); } void test_exponentiation() { CHECK_EVAL("2e10", "20000000000"); CHECK_EVAL("2E10", "20000000000"); CHECK_EVAL("2e-10", "0.0000000002"); CHECK_EVAL("2E0xa", "20000000000"); CHECK_EVAL("2e-0xa", "0.0000000002"); CHECK_EVAL("0b10b10", "8"); CHECK_EVAL("0b10B10", "8"); CHECK_EVAL("0b10b-10", "0.5"); CHECK_EVAL("0b10b0d2", "8"); CHECK_EVAL("0b10b-0d2", "0.5"); CHECK_EVAL("0o2o10", "33554432"); CHECK_EVAL("0o2O10", "33554432"); CHECK_EVAL("0o2C10", "33554432"); CHECK_EVAL("0o2o-10", "0.00000011920928955078"); CHECK_EVAL("0o2o0d8", "33554432"); CHECK_EVAL("0o2o-0d8", "0.00000011920928955078"); CHECK_EVAL("0x2h10", "36893488147419103232"); CHECK_EVAL("0x2H10", "36893488147419103232"); CHECK_EVAL("0x2h-10", "0.00000000000000000011"); CHECK_EVAL("0x2h0d16", "36893488147419103232"); CHECK_EVAL("0x2h-0d16", "0.00000000000000000011"); CHECK_EVAL_FAIL("0x2o11"); CHECK_EVAL_FAIL("0b2C11"); CHECK_EVAL_FAIL("0o2b11"); } void test_unary() { CHECK_EVAL("-0", "0"); CHECK_EVAL("-1", "-1"); CHECK_EVAL("--1", "1"); CHECK_EVAL("---1", "-1"); CHECK_EVAL("----1", "1"); CHECK_EVAL("-----1", "-1"); CHECK_EVAL("------1", "1"); CHECK_EVAL("-ABS(1)", "-1"); CHECK_EVAL("-ABS(-2)", "-2"); CHECK_EVAL("--ABS(-3)", "3"); CHECK_EVAL("---ABS(-4)", "-4"); // Operator ^ has higher precedence than unary minus. CHECK_EVAL("-1^0", "-1"); CHECK_EVAL("-1^1", "-1"); CHECK_EVAL("-1^2", "-1"); CHECK_EVAL("-1^3", "-1"); CHECK_EVAL("-2^0", "-1"); CHECK_EVAL("-2^1", "-2"); CHECK_EVAL("-2^2", "-4"); CHECK_EVAL("-2^3", "-8"); CHECK_EVAL("-2^4", "-16"); CHECK_EVAL("-2^5", "-32"); CHECK_EVAL("-2^6", "-64"); CHECK_EVAL("-2^7", "-128"); CHECK_EVAL("-2^8", "-256"); CHECK_EVAL("-2^9", "-512"); CHECK_EVAL("-2^10", "-1024"); CHECK_EVAL("(5-7)^2", "4"); CHECK_EVAL("-(5-7)^2", "-4"); CHECK_EVAL("-cos(pi)^3", "1"); CHECK_EVAL("1*(-cos(pi)^2)", "-1"); CHECK_EVAL("3^3^3", "7625597484987"); CHECK_EVAL("1/-1^2", "-1"); CHECK_EVAL("1*-1^2", "-1"); // Factorial has higher precedence than unary minus. CHECK_EVAL("-1!", "-1"); CHECK_EVAL("-2!", "-2"); CHECK_EVAL("-3!", "-6"); // Unicode minus sign CHECK_EVAL("−1", "-1"); CHECK_EVAL("−(2*3)", "-6"); CHECK_EVAL("2*−1", "-2"); CHECK_EVAL("2e−1", "0.2"); CHECK_INTERPRETED("−pi", "-pi"); CHECK_INTERPRETED("--pi", "pi"); CHECK_INTERPRETED("---pi", "-pi"); CHECK_INTERPRETED("----pi", "pi"); } void test_binary_power_operator() { // See http://en.wikipedia.org/wiki/Empty_product. CHECK_EVAL("0^0", "NaN"); CHECK_EVAL("1^0", "1"); CHECK_EVAL("1^1", "1"); CHECK_EVAL("1^2", "1"); CHECK_EVAL("1^3", "1"); CHECK_EVAL("2^0", "1"); CHECK_EVAL("2^1", "2"); CHECK_EVAL("2^2", "4"); CHECK_EVAL("2^3", "8"); CHECK_EVAL("2^4", "16"); CHECK_EVAL("2^5", "32"); CHECK_EVAL("2^6", "64"); CHECK_EVAL("2^7", "128"); CHECK_EVAL("2^8", "256"); CHECK_EVAL("2^9", "512"); CHECK_EVAL("2^10", "1024"); CHECK_EVAL("(-13)^(1/3)", "-2.3513346877207574895"); CHECK_EVAL("(-13)^(1/9)", "-1.32975454563978597291"); CHECK_EVAL("(-13)^(1/27)", "-1.0996567925533755264"); CHECK_EVAL("(-13)^(1/3.123)", "2.27347485100383238372"); CHECK_EVAL("(-13)^(1/9.123)", "1.32465488702830785593"); CHECK_EVAL("(-13)^(1/27.123)", "1.09918315510346486963"); } void test_binary_arithmetic_operator_variants() { CHECK_EVAL("0+0", "0"); CHECK_EVAL("1+0", "1"); CHECK_EVAL("0+1", "1"); CHECK_EVAL("1+1", "2"); CHECK_EVAL("0-0", "0"); CHECK_EVAL("1-0", "1"); CHECK_EVAL("0-1", "-1"); CHECK_EVAL("1-1", "0"); CHECK_EVAL("0−0", "0"); CHECK_EVAL("1−0", "1"); CHECK_EVAL("0−1", "-1"); CHECK_EVAL("1−1", "0"); CHECK_EVAL("2*3", "6"); CHECK_EVAL("2×3", "6"); CHECK_EVAL("2·3", "6"); // U+22C5 Dot operator. CHECK_EVAL("3*2", "6"); CHECK_EVAL("3×2", "6"); CHECK_EVAL("3·2", "6"); CHECK_EVAL("10/2", "5"); CHECK_EVAL("10÷2", "5"); CHECK_EVAL("10⧸2", "5"); // U+29F8 Big solidus. CHECK_EVAL("2/10", "0.2"); CHECK_EVAL("2÷10", "0.2"); CHECK_EVAL("2⧸10", "0.2"); CHECK_EVAL("1/(1/(1/0.2425-4)-8)-12", "0"); CHECK_EVAL("1/(1/(1/(2425/10000)-4)-8)-12", "0"); CHECK_EVAL("1/(1/(1/(1/(1/(1/0.25636-3)-1)-9)-12)-1)-48", "0"); CHECK_EVAL("1/(1/(1/(1/(1/(1/(25636/100000)-3)-1)-9)-12)-1)-48", "0"); } void test_lists_and_matrices() { CHECK_EVAL("{1;2;3;4;5}", "{1; 2; 3; 4; 5}"); CHECK_EVAL("mylist = {1; 2; 3; 4; 5}", "{1; 2; 3; 4; 5}"); CHECK_EVAL("l1 = {1; 2; 3}", "{1; 2; 3}"); CHECK_EVAL("d = {1; 2; 3; 4; 5}", "{1; 2; 3; 4; 5}"); CHECK_DISPLAY_INTERPRETED("d", "d"); CHECK_EVAL("d", "{1; 2; 3; 4; 5}"); CHECK_EVAL("average(mylist)", "3"); CHECK_EVAL("mean(mylist)", "3"); CHECK_EVAL("geomean(mylist)", "2.60517108469735189233"); CHECK_EVAL("median(mylist)", "3"); CHECK_EVAL("absdev(mylist)", "1.2"); CHECK_EVAL("mad(mylist)", "1"); CHECK_EVAL("stdevp(mylist)", "1.4142135623730950488"); CHECK_EVAL("stdevs(mylist)", "1.581138830084189666"); CHECK_EVAL("min(mylist)", "1"); CHECK_EVAL("max(mylist)", "5"); CHECK_EVAL("sum(mylist)", "15"); CHECK_EVAL("varp(mylist)", "2"); CHECK_EVAL("vars(mylist)", "2.5"); CHECK_EVAL("count(mylist)", "5"); CHECK_EVAL("shape(mylist)", "{5}"); CHECK_EVAL("{1;2;3} + {4;5;6}", "{5; 7; 9}"); CHECK_EVAL("{4;5;6} - {1;2;3}", "{3; 3; 3}"); CHECK_EVAL("2 * {1;2;3}", "{2; 4; 6}"); CHECK_EVAL("{2;4;6} / 2", "{1; 2; 3}"); CHECK_EVAL("{1; 2; 3} * {{1}; {2}; {3}}", "14"); CHECK_EVAL("{4; 5; 6} * {{1}; {2}; {3}}", "32"); CHECK_EVAL("{7; 8} * {{9}; {10}}", "143"); CHECK_EVAL_FAIL("1 + l1"); CHECK_EVAL_FAIL("l1 + 1"); CHECK_EVAL_FAIL("1 + {1; 2; 3}"); CHECK_EVAL_FAIL("{1; 2; 3} + 1"); CHECK_EVAL_FAIL("1 - l1"); CHECK_EVAL_FAIL("l1 - 1"); CHECK_EVAL_FAIL("{1; 2} * {4; 5}"); CHECK_EVAL_FAIL("{1; 2; 3} * {2; 3; 4}"); CHECK_EVAL_FAIL("{1; 2; 3} / {2; 3; 4}"); CHECK_EVAL_FAIL("2 / {1; 2; 3}"); ++eval_total_tests; eval->setExpression(QStringLiteral("2 / {1; 2; 3}")); eval->evalUpdateAns(); if (!eval->error().contains(QStringLiteral("operation is not defined for these arguments"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tscalar divided by list error message\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } CHECK_DISPLAY_INTERPRETED("2 * {1;2;3} + {4;5;6}", "2 × {1; 2; 3} + {4; 5; 6}"); CHECK_DISPLAY_INTERPRETED("2 × {1;2;3} + {4;5;6}", "2 × {1; 2; 3} + {4; 5; 6}"); CHECK_DISPLAY_INTERPRETED("{{1;2};{3;4}} × {{5;6};{7;8}}", "{{1; 2}; {3; 4}} × {{5; 6}; {7; 8}}"); CHECK_DISPLAY_INTERPRETED("2{1; cos(400 [gon]) + 1; 3} + {4; 5; 6}", QStringLiteral("2 × {1; cos(400") + QString(MathDsl::QuantSp) + QStringLiteral("[gon]) + 1; 3} + {4; 5; 6}")); CHECK_EVAL("2 * {1;2;3} + {4;5;6}", "{6; 9; 12}"); CHECK_EVAL("2{1; cos(400 [gon]) + 1; 3} + {4; 5; 6}", "{6; 9; 12}"); CHECK_EVAL("dot({1;2;3}; {4;5;6})", "32"); CHECK_EVAL("cross({1;0;0}; {0;1;0})", "{0; 0; 1}"); CHECK_EVAL("norm({3; 4})", "5"); CHECK_EVAL("mat = {{1;2;3};{4;5;6}}", "{{1; 2; 3}; {4; 5; 6}}"); CHECK_EVAL("flatten(mat)", "{1; 2; 3; 4; 5; 6}"); CHECK_EVAL("sum(flatten(mat))", "21"); CHECK_EVAL("average(flatten(mat))", "3.5"); CHECK_EVAL("min(flatten(mat))", "1"); CHECK_EVAL("max(flatten(mat))", "6"); CHECK_EVAL("sum(mat)", "21"); CHECK_EVAL("average(mat)", "3.5"); CHECK_EVAL("geomean(mat)", "2.99379516552390895491"); CHECK_EVAL("absdev(mat)", "1.5"); CHECK_EVAL("mad(mat)", "1.5"); CHECK_EVAL("count(mat)", "6"); CHECK_EVAL("rows(mat)", "2"); CHECK_EVAL("cols(mat)", "3"); CHECK_EVAL("shape(mat)", "{2; 3}"); CHECK_EVAL("transpose(mat)", "{{1; 4}; {2; 5}; {3; 6}}"); CHECK_EVAL("mat2 = {{7;8;9};{10;11;12}}", "{{7; 8; 9}; {10; 11; 12}}"); CHECK_EVAL("mat + mat2", "{{8; 10; 12}; {14; 16; 18}}"); CHECK_EVAL("2 * mat", "{{2; 4; 6}; {8; 10; 12}}"); CHECK_EVAL("mat / 2", "{{0.5; 1; 1.5}; {2; 2.5; 3}}"); CHECK_EVAL("mat * {1; 2; 3}", "{{14}; {32}}"); CHECK_EVAL("{{1}; {2}; {3}} * {4; 5; 6}", "{{4; 5; 6}; {8; 10; 12}; {12; 15; 18}}"); CHECK_EVAL("{{1; 2; 3}; {4; 5; 6}} * {{7; 8}; {9; 10}; {11; 12}}", "{{58; 64}; {139; 154}}"); CHECK_EVAL("{{1; 2}; {3; 4}; {5; 6}} * {{7; 8; 9}; {10; 11; 12}}", "{{27; 30; 33}; {61; 68; 75}; {95; 106; 117}}"); CHECK_EVAL("{{2; 0}; {1; 3}} * {{4; 1}; {2; 2}}", "{{8; 2}; {10; 7}}"); CHECK_EVAL("{{1; 0; 2}; {-1; 3; 1}; {3; 1; 0}} * {{3; 1; 2}; {2; 1; 1}; {1; 0; 0}}", "{{5; 1; 2}; {4; 2; 1}; {11; 4; 7}}"); CHECK_EVAL("{{1; 2; 3; 4}; {5; 6; 7; 8}} * {{1; 0}; {0; 1}; {1; 0}; {0; 1}}", "{{4; 6}; {12; 14}}"); CHECK_EVAL("{{1; 2}; {3; 4}; {5; 6}; {7; 8}} * {{1; 0; 1; 0}; {0; 1; 0; 1}}", "{{1; 2; 1; 2}; {3; 4; 3; 4}; {5; 6; 5; 6}; {7; 8; 7; 8}}"); CHECK_EVAL("{{1; 2; 3}; {4; 5; 6}} * {{7}; {8}; {9}}", "{{50}; {122}}"); CHECK_EVAL("{1; 2; 3} * {{4; 5}; {6; 7}; {8; 9}}", "{40; 46}"); CHECK_EVAL("{{2}; {3}; {4}} * {5; 6; 7}", "{{10; 12; 14}; {15; 18; 21}; {20; 24; 28}}"); CHECK_EVAL_FAIL("{{1}; {2}} * {{4}; {5}}"); CHECK_EVAL("{{1; 2}; {3; 4}} * {{5; 6; 7}; {8; 9; 10}}", "{{21; 24; 27}; {47; 54; 61}}"); CHECK_EVAL("norm({{1; 2}; {3; 4}})", "5.47722557505166113457"); CHECK_EVAL("A = {{1;2};{3;4}}", "{{1; 2}; {3; 4}}"); CHECK_EVAL("B = {{5;6};{7;8}}", "{{5; 6}; {7; 8}}"); CHECK_EVAL("A * B", "{{19; 22}; {43; 50}}"); CHECK_EVAL("det(A)", "-2"); CHECK_EVAL("inv(A)", "{{-2; 1}; {1.5; -0.5}}"); CHECK_EVAL("trace(A)", "5"); CHECK_EVAL("rank({{1; 2}; {2; 4}})", "1"); CHECK_EVAL("X = {{1;2}; {2;3}; {3;4}}", "{{1; 2}; {2; 3}; {3; 4}}"); CHECK_EVAL("covp(X)", "{{0.66666666666666666667; 0.66666666666666666667}; {0.66666666666666666667; 0.66666666666666666667}}"); CHECK_EVAL("covs(X)", "{{1; 1}; {1; 1}}"); CHECK_EVAL("corrp(X)", "{{1; 1}; {1; 1}}"); CHECK_EVAL("corrs(X)", "{{1; 1}; {1; 1}}"); CHECK_EVAL("mad(1; 2; 100)", "1"); CHECK_EVAL_FAIL("{{{1}}}"); CHECK_EVAL_FAIL("{{{1;2};{3;4}}}"); CHECK_EVAL_FAIL("{{1; {2; 3}}}"); CHECK_EVAL_FAIL("{{1;2};{3}}"); CHECK_EVAL_FAIL("var(1; 2)"); CHECK_EVAL_FAIL("stddev(1; 2)"); CHECK_EVAL_FAIL("cov(X)"); CHECK_EVAL_FAIL("corr(X)"); CHECK_EVAL_FAIL("{1[m]; 2[m]}"); CHECK_EVAL_FAIL("{1; 2}[m]"); CHECK_EVAL_FAIL("{1; 2} * [m]"); } void test_units_conversion_parentheses() { // Check that parentheses are added in unit conversion results when needed. CHECK_EVAL("1[metre] -> [10 metre]", "0.1 10·metre"); CHECK_EVAL("1[metre] -> [.1 metre]", "10 .1·metre"); CHECK_EVAL("1[metre] -> [-1 metre]", "-1 -1 metre"); CHECK_EVAL("1[metre] -> [0xa metre]", "0.1 0xa·metre"); CHECK_EVAL("1[metre second] -> [10 metre second]", "0.1 10·metre·second"); CHECK_EVAL("1[metre] -> [metre + metre]", "0.5 metre + metre"); CHECK_EVAL("1[metre] -> [metre - 2metre]", "-1 metre - 2metre"); CHECK_EVAL("1[metre] -> [metre]", "1 metre"); CHECK_EVAL("1[10 metre] -> [metre]", "10 metre"); CHECK_EVAL("1[metre] in [metre]", "1 metre"); CHECK_EVAL("1[metre] IN [metre]", "1 metre"); CHECK_EVAL("50[yard] + 2[foot] in [cm]", "4632.96 cm"); CHECK_EVAL("10[metre] in (1[yard] + 2[foot])", "6.56167979002624671916 (1[yard] + 2[foot])"); CHECK_EVAL(QString::fromUtf8("1[metre] −> [cm]"), "100 cm"); CHECK_EVAL(QString::fromUtf8("1[metre] → [cm]"), "100 cm"); CHECK_EVAL(QString::fromUtf8("[hectare] → [m²] → [hectare]"), "1 hectare"); CHECK_EVAL_FAIL("12 -> [3]"); CHECK_EVAL_FAIL("12 -> 3"); CHECK_EVAL_FAIL("12 in [3]"); CHECK_EVAL_FAIL("12 in 3"); CHECK_EVAL_FAIL("12[g] in 3"); CHECK_EVAL_FAIL("12[g] in [3]"); } void test_units_display_propagation() { // Display-unit propagation should be symmetric for scalar multiplication. CHECK_EVAL("3 * 2[metre]", "6 metre"); CHECK_EVAL("2[metre] * 3", "6 metre"); } void test_units_short_aliases_and_si_prefixes() { CHECK_EVAL("[m]", "1 metre"); CHECK_EVAL("[kg]", "1 kg"); CHECK_EVAL("[F]", "1 farad"); CHECK_EVAL("[V]", "1 volt"); CHECK_EVAL("[Eh]", "1 Eh"); CHECK_EVAL("[mol]", "1 mole"); CHECK_EVAL(QString::fromUtf8("[Ω]"), "1 ohm"); CHECK_EVAL("[ha]", "1 ha"); CHECK_EVAL("[in]", "1 in"); CHECK_EVAL("[ft]", "1 ft"); CHECK_EVAL("[foot] -> [in]", "12 in"); CHECK_EVAL("[in] -> [inch]", "1 inch"); CHECK_EVAL("[kilometre] -> [metre]", "1000 metre"); CHECK_EVAL("[km] -> [metre]", "1000 metre"); CHECK_EVAL("[milligram] -> [gram]", "0.001 gram"); CHECK_EVAL("[mg] -> [gram]", "0.001 gram"); CHECK_EVAL("[megaelectronvolt] -> [electronvolt]", "1000000 electronvolt"); CHECK_EVAL("[MeV] -> [eV]", "1000000 eV"); CHECK_EVAL_FAIL("[electron_volt]"); CHECK_EVAL_FAIL("[megaelectron_volt]"); CHECK_EVAL("[picovolt] -> [volt]", "0.000000000001 volt"); CHECK_EVAL("[pV] -> [volt]", "0.000000000001 volt"); CHECK_EVAL(QString::fromUtf8("[ha] -> [m²]"), u8"10000 m²"); CHECK_EVAL("[ac] -> [acre]", "1 acre"); CHECK_EVAL("[rpm] -> [revolution_per_minute]", "1 revolution_per_minute"); CHECK_EVAL("[mph] -> [mile_per_hour]", "1 mile_per_hour"); CHECK_EVAL("[kph] -> [kilometre_per_hour]", "1 kilometre_per_hour"); CHECK_EVAL("[kWh] -> [kilowatt_hour]", "1 kilowatt_hour"); CHECK_EVAL("[mmHg] -> [millimetre_of_mercury]", "1 millimetre_of_mercury"); CHECK_EVAL("[st] -> [stone]", "1 stone"); CHECK_EVAL("[dsp] -> [dessert_spoon]", "1 dessert_spoon"); CHECK_EVAL("[quad] -> [quad]", "1 quad"); CHECK_EVAL("[century_julian] -> [day]", "36525 day"); CHECK_EVAL("[cy_jul] -> [year_julian]", "100 year_julian"); CHECK_EVAL("[year_julian] -> [century_julian]", "0.01 century_julian"); CHECK_EVAL("[fluid_ounce_imp] -> [fluid_ounce_imp]", "1 fluid_ounce_imp"); CHECK_EVAL("[floz_imp] -> [fluid_ounce_imp]", "1 fluid_ounce_imp"); CHECK_EVAL("[fluid_ounce_us] -> [fluid_ounce_us]", "1 fluid_ounce_us"); CHECK_EVAL("[floz_us] -> [fluid_ounce_us]", "1 fluid_ounce_us"); CHECK_EVAL("[fluid_dram_imp] -> [fluid_dram_imp]", "1 fluid_dram_imp"); CHECK_EVAL("[fldr_imp] -> [fluid_dram_imp]", "1 fluid_dram_imp"); CHECK_EVAL("[fluid_dram_us] -> [fluid_dram_us]", "1 fluid_dram_us"); CHECK_EVAL("[fldr_us] -> [fluid_dram_us]", "1 fluid_dram_us"); CHECK_EVAL("[gill_imp] -> [gill_imp]", "1 gill_imp"); CHECK_EVAL("[gill_us] -> [gill_us]", "1 gill_us"); CHECK_EVAL("[square_inch] -> [square_inch]", "1 square_inch"); CHECK_EVAL(QString::fromUtf8("[in²] -> [square_inch]"), "1 square_inch"); CHECK_EVAL("[square_foot] -> [square_foot]", "1 square_foot"); CHECK_EVAL(QString::fromUtf8("[ft²] -> [square_foot]"), "1 square_foot"); CHECK_EVAL("[square_yard] -> [square_yard]", "1 square_yard"); CHECK_EVAL(QString::fromUtf8("[yd²] -> [square_yard]"), "1 square_yard"); CHECK_EVAL("[cubic_foot] -> [cubic_foot]", "1 cubic_foot"); CHECK_EVAL(QString::fromUtf8("[ft³] -> [cubic_foot]"), "1 cubic_foot"); CHECK_EVAL("[cubic_yard] -> [cubic_yard]", "1 cubic_yard"); CHECK_EVAL(QString::fromUtf8("[yd³] -> [cubic_yard]"), "1 cubic_yard"); CHECK_EVAL("[cubic_inch] -> [cubic_inch]", "1 cubic_inch"); CHECK_EVAL(QString::fromUtf8("[in³] -> [cubic_inch]"), "1 cubic_inch"); CHECK_EVAL("[cubic_millimetre] -> [cubic_millimetre]", "1 cubic_millimetre"); CHECK_EVAL(QString::fromUtf8("[mm³] -> [cubic_millimetre]"), "1 cubic_millimetre"); CHECK_EVAL("[square_millimetre] -> [square_millimetre]", "1 square_millimetre"); CHECK_EVAL(QString::fromUtf8("[mm²] -> [square_millimetre]"), "1 square_millimetre"); CHECK_EVAL("[cubic_centimetre] -> [cubic_centimetre]", "1 cubic_centimetre"); CHECK_EVAL(QString::fromUtf8("[cm³] -> [cubic_centimetre]"), "1 cubic_centimetre"); CHECK_EVAL("[cc] -> [cubic_centimetre]", "1 cubic_centimetre"); CHECK_EVAL("[cubic_decimetre] -> [cubic_decimetre]", "1 cubic_decimetre"); CHECK_EVAL(QString::fromUtf8("[dm³] -> [cubic_decimetre]"), "1 cubic_decimetre"); CHECK_EVAL("[cubic_kilometre] -> [cubic_kilometre]", "1 cubic_kilometre"); CHECK_EVAL(QString::fromUtf8("[km³] -> [cubic_kilometre]"), "1 cubic_kilometre"); CHECK_EVAL("[square_kilometre] -> [square_kilometre]", "1 square_kilometre"); CHECK_EVAL(QString::fromUtf8("[km²] -> [square_kilometre]"), "1 square_kilometre"); CHECK_EVAL("[barrel_oil] -> [barrel_oil]", "1 barrel_oil"); CHECK_EVAL("[bbl_oil] -> [barrel_oil]", "1 barrel_oil"); CHECK_EVAL("[barrel_beer_us] -> [barrel_beer_us]", "1 barrel_beer_us"); CHECK_EVAL("[bbl_beer] -> [barrel_beer_us]", "1 barrel_beer_us"); CHECK_EVAL("[square_mile] -> [square_mile]", "1 square_mile"); CHECK_EVAL(QString::fromUtf8("[mi²] -> [square_mile]"), "1 square_mile"); CHECK_EVAL("[cubic_mile] -> [cubic_mile]", "1 cubic_mile"); CHECK_EVAL(QString::fromUtf8("[mi³] -> [cubic_mile]"), "1 cubic_mile"); CHECK_EVAL("[gallon_imp] -> [gallon_imp]", "1 gallon_imp"); CHECK_EVAL("[gal_imp] -> [gallon_imp]", "1 gallon_imp"); CHECK_EVAL("[gallon_us] -> [gallon_us]", "1 gallon_us"); CHECK_EVAL("[gal_us] -> [gallon_us]", "1 gallon_us"); CHECK_EVAL("[pint_imp] -> [pint_imp]", "1 pint_imp"); CHECK_EVAL("[pt_imp] -> [pint_imp]", "1 pint_imp"); CHECK_EVAL("[pint_us] -> [pint_us]", "1 pint_us"); CHECK_EVAL("[pt_us] -> [pint_us]", "1 pint_us"); CHECK_EVAL("[quart_imp] -> [quart_imp]", "1 quart_imp"); CHECK_EVAL("[qt_imp] -> [quart_imp]", "1 quart_imp"); CHECK_EVAL("[quart_us] -> [quart_us]", "1 quart_us"); CHECK_EVAL("[qt_us] -> [quart_us]", "1 quart_us"); CHECK_EVAL("[tablespoon_imp] -> [tablespoon_imp]", "1 tablespoon_imp"); CHECK_EVAL("[tbsp_imp] -> [tablespoon_imp]", "1 tablespoon_imp"); CHECK_EVAL("[tablespoon_us] -> [tablespoon_us]", "1 tablespoon_us"); CHECK_EVAL("[tbsp_us] -> [tablespoon_us]", "1 tablespoon_us"); CHECK_EVAL("[tablespoon_au] -> [tablespoon_au]", "1 tablespoon_au"); CHECK_EVAL("[tbsp_au] -> [tablespoon_au]", "1 tablespoon_au"); CHECK_EVAL("[teaspoon_imp] -> [teaspoon_imp]", "1 teaspoon_imp"); CHECK_EVAL("[tsp_imp] -> [teaspoon_imp]", "1 teaspoon_imp"); CHECK_EVAL("[teaspoon_us] -> [teaspoon_us]", "1 teaspoon_us"); CHECK_EVAL("[tsp_us] -> [teaspoon_us]", "1 teaspoon_us"); CHECK_EVAL("[cup_imp] -> [cup_imp]", "1 cup_imp"); CHECK_EVAL("[cup_jp] -> [cup_jp]", "1 cup_jp"); CHECK_EVAL("[cup_us] -> [cup_us]", "1 cup_us"); CHECK_EVAL("[fluid_ounce_imp] -> [litre]", "0.0284130625 litre"); CHECK_EVAL("[litre] -> [fluid_ounce_imp]", "35.19507972785404600437 fluid_ounce_imp"); CHECK_EVAL("[fluid_ounce_us] -> [litre]", "0.0295735295625 litre"); CHECK_EVAL("[litre] -> [fluid_ounce_us]", "33.81402270184299716863 fluid_ounce_us"); CHECK_EVAL("[fluid_dram_imp] -> [litre]", "0.0035516328125 litre"); CHECK_EVAL("[litre] -> [fluid_dram_imp]", "281.56063782283236803495 fluid_dram_imp"); CHECK_EVAL("[fluid_dram_us] -> [litre]", "0.0036966911953125 litre"); CHECK_EVAL("[litre] -> [fluid_dram_us]", "270.51218161474397734902 fluid_dram_us"); CHECK_EVAL("[gallon_imp] -> [litre]", "4.54609 litre"); CHECK_EVAL("[litre] -> [gallon_imp]", "0.21996924829908778753 gallon_imp"); CHECK_EVAL("[gallon_us] -> [litre]", "3.785411784 litre"); CHECK_EVAL("[litre] -> [gallon_us]", "0.26417205235814841538 gallon_us"); CHECK_EVAL("[gill_imp] -> [litre]", "0.1420653125 litre"); CHECK_EVAL("[litre] -> [gill_imp]", "7.03901594557080920087 gill_imp"); CHECK_EVAL("[gill_us] -> [litre]", "0.11829411825 litre"); CHECK_EVAL("[litre] -> [gill_us]", "8.45350567546074929216 gill_us"); CHECK_EVAL("[pint_imp] -> [litre]", "0.56826125 litre"); CHECK_EVAL("[litre] -> [pint_imp]", "1.75975398639270230022 pint_imp"); CHECK_EVAL("[pint_us] -> [litre]", "0.473176473 litre"); CHECK_EVAL("[litre] -> [pint_us]", "2.11337641886518732304 pint_us"); CHECK_EVAL("[quart_imp] -> [litre]", "1.1365225 litre"); CHECK_EVAL("[litre] -> [quart_imp]", "0.87987699319635115011 quart_imp"); CHECK_EVAL("[quart_us] -> [litre]", "0.946352946 litre"); CHECK_EVAL("[litre] -> [quart_us]", "1.05668820943259366152 quart_us"); CHECK_EVAL("[cubic_foot] -> [litre]", "28.316846592 litre"); CHECK_EVAL("[litre] -> [cubic_foot]", "0.03531466672148859025 cubic_foot"); CHECK_EVAL("[cubic_foot] -> [cubic_metre]", "0.028316846592 cubic_metre"); CHECK_EVAL("[cubic_metre] -> [cubic_foot]", "35.31466672148859025044 cubic_foot"); CHECK_EVAL("[cubic_yard] -> [cubic_metre]", "0.764554857984 cubic_metre"); CHECK_EVAL("[cubic_metre] -> [cubic_yard]", "1.3079506193143922315 cubic_yard"); CHECK_EVAL("[cubic_inch] -> [litre]", "0.016387064 litre"); CHECK_EVAL("[litre] -> [cubic_inch]", "61.02374409473228395276 cubic_inch"); CHECK_EVAL("[cubic_inch] -> [cubic_metre]", "0.000016387064 cubic_metre"); CHECK_EVAL("[cubic_metre] -> [cubic_inch]", "61023.74409473228395275688 cubic_inch"); CHECK_EVAL("[cubic_millimetre] -> [cubic_metre]", "0.000000001 cubic_metre"); CHECK_EVAL("[cubic_metre] -> [cubic_millimetre]", "1000000000 cubic_millimetre"); CHECK_EVAL("[cubic_millimetre] -> [litre]", "0.000001 litre"); CHECK_EVAL("[litre] -> [cubic_millimetre]", "1000000 cubic_millimetre"); CHECK_EVAL("[cubic_centimetre] -> [cubic_metre]", "0.000001 cubic_metre"); CHECK_EVAL("[cubic_metre] -> [cubic_centimetre]", "1000000 cubic_centimetre"); CHECK_EVAL("[cubic_centimetre] -> [litre]", "0.001 litre"); CHECK_EVAL("[litre] -> [cubic_centimetre]", "1000 cubic_centimetre"); CHECK_EVAL("[cubic_decimetre] -> [cubic_metre]", "0.001 cubic_metre"); CHECK_EVAL("[cubic_metre] -> [cubic_decimetre]", "1000 cubic_decimetre"); CHECK_EVAL("[cubic_decimetre] -> [litre]", "1 litre"); CHECK_EVAL("[litre] -> [cubic_decimetre]", "1 cubic_decimetre"); CHECK_EVAL("[cubic_kilometre] -> [cubic_metre]", "1000000000 cubic_metre"); CHECK_EVAL("[cubic_metre] -> [cubic_kilometre]", "0.000000001 cubic_kilometre"); CHECK_EVAL("[cubic_kilometre] -> [litre]", "1000000000000 litre"); CHECK_EVAL("[litre] -> [cubic_kilometre]", "0.000000000001 cubic_kilometre"); CHECK_EVAL("[cubic_mile] -> [cubic_metre]", "4168181825.440579584 cubic_metre"); CHECK_EVAL("[cubic_metre] -> [cubic_mile]", "0.00000000023991275858 cubic_mile"); CHECK_EVAL("[barrel_oil] -> [litre]", "158.987294928 litre"); CHECK_EVAL("[litre] -> [barrel_oil]", "0.00628981077043210513 barrel_oil"); CHECK_EVAL("[barrel_beer_us] -> [litre]", "119.240471196 litre"); CHECK_EVAL("[litre] -> [barrel_beer_us]", "0.00838641436057614017 barrel_beer_us"); CHECK_EVAL("[square_inch] -> [square_metre]", "0.00064516 square_metre"); CHECK_EVAL("[square_metre] -> [square_inch]", "1550.00310000620001240002 square_inch"); CHECK_EVAL("[square_foot] -> [square_metre]", "0.09290304 square_metre"); CHECK_EVAL("[square_metre] -> [square_foot]", "10.76391041670972230833 square_foot"); CHECK_EVAL("[square_yard] -> [square_metre]", "0.83612736 square_metre"); CHECK_EVAL("[square_metre] -> [square_yard]", "1.19599004630108025648 square_yard"); CHECK_EVAL("[square_mile] -> [square_metre]", "2589988.110336 square_metre"); CHECK_EVAL("[square_metre] -> [square_mile]", "0.00000038610215854245 square_mile"); CHECK_EVAL("[square_millimetre] -> [square_metre]", "0.000001 square_metre"); CHECK_EVAL("[square_metre] -> [square_millimetre]", "1000000 square_millimetre"); CHECK_EVAL("[square_kilometre] -> [square_metre]", "1000000 square_metre"); CHECK_EVAL("[square_metre] -> [square_kilometre]", "0.000001 square_kilometre"); CHECK_EVAL("[tablespoon_imp] -> [litre]", "0.0177581640625 litre"); CHECK_EVAL("[litre] -> [tablespoon_imp]", "56.31212756456647360699 tablespoon_imp"); CHECK_EVAL("[tablespoon_us] -> [litre]", "0.01478676478125 litre"); CHECK_EVAL("[litre] -> [tablespoon_us]", "67.62804540368599433725 tablespoon_us"); CHECK_EVAL("[tablespoon_au] -> [litre]", "0.02 litre"); CHECK_EVAL("[litre] -> [tablespoon_au]", "50 tablespoon_au"); CHECK_EVAL("[teaspoon_imp] -> [litre]", "0.00591938802083333333 litre"); CHECK_EVAL("[litre] -> [teaspoon_imp]", "168.93638269369942082097 teaspoon_imp"); CHECK_EVAL("[teaspoon_us] -> [litre]", "0.00492892159375 litre"); CHECK_EVAL("[litre] -> [teaspoon_us]", "202.88413621105798301176 teaspoon_us"); CHECK_EVAL("[cup_imp] -> [litre]", "0.284130625 litre"); CHECK_EVAL("[litre] -> [cup_imp]", "3.51950797278540460044 cup_imp"); CHECK_EVAL("[cup_jp] -> [litre]", "0.2 litre"); CHECK_EVAL("[litre] -> [cup_jp]", "5 cup_jp"); CHECK_EVAL("[cup_us] -> [litre]", "0.2365882365 litre"); CHECK_EVAL("[litre] -> [cup_us]", "4.22675283773037464608 cup_us"); CHECK_EVAL("[gal_imp] -> [gal_us]", "1.20094992550485492967 gal_us"); CHECK_EVAL("[floz_imp] -> [floz_us]", "0.96075994040388394374 floz_us"); CHECK_EVAL("[qt_imp] -> [qt_us]", "1.20094992550485492967 qt_us"); CHECK_EVAL("[pt_imp] -> [pt_us]", "1.20094992550485492967 pt_us"); CHECK_EVAL("[kilometre_per_hour] -> [metre/second]", u8"0.27777777777777777778 metre·second�¹"); CHECK_EVAL("3.6[kilometre_per_hour] -> [metre/second]", u8"1 metre·second�¹"); CHECK_EVAL("1[metre/second] -> [kilometre_per_hour]", "3.6 kilometre_per_hour"); CHECK_EVAL("[mile_per_hour] -> [kilometre_per_hour]", "1.609344 kilometre_per_hour"); CHECK_EVAL("1.609344[kilometre_per_hour] -> [mile_per_hour]", "1 mile_per_hour"); CHECK_EVAL("1e15[Btu] -> [quad]", "1 quad"); CHECK_EVAL_FORMAT("1[Btu]", u8"1[Btu]"); CHECK_EVAL_FORMAT("1[Btu] -> [J]", u8"1055.05585262[J]"); CHECK_EVAL_FORMAT("1[british_thermal_unit]", u8"1[Btu]"); CHECK_EVAL("1[Btu] -> [joule]", "1055.05585262 joule"); CHECK_EVAL("1[british_thermal_unit] -> [joule]", "1055.05585262 joule"); CHECK_EVAL_FORMAT("1[british_thermal_unit] -> [J]", u8"1055.05585262[J]"); CHECK_EVAL("[mV] -> [volt]", "0.001 volt"); CHECK_EVAL("[MV] -> [volt]", "1000000 volt"); CHECK_EVAL_FAIL("[Mv] -> [volt]"); CHECK_EVAL(QString::fromUtf8("[m²] -> [m²]"), u8"1 m²"); CHECK_EVAL(QString::fromUtf8("[m³] -> [m³]"), u8"1 m³"); CHECK_EVAL(QString::fromUtf8("[mm²] -> [m²]"), u8"0.000001 m²"); CHECK_EVAL(QString::fromUtf8("[mm³] -> [m³]"), u8"0.000000001 m³"); CHECK_EVAL(QString::fromUtf8("1¹ [m]"), "1 metre"); CHECK_EVAL("1^(1) [s]", "1 second"); CHECK_DISPLAY_INTERPRETED( QStringLiteral("[m]"), QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[m]")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("[m]"), QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[m]")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("[m] + [m]"), QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[m]") + QString(MathDsl::AddWrap) + QStringLiteral("+") + QString(MathDsl::AddWrap) + QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[m]")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("[m] + [m]"), QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[m]") + QString(MathDsl::AddWrap) + QStringLiteral("+") + QString(MathDsl::AddWrap) + QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[m]")); CHECK_INTERPRETED(QString::fromUtf8("2[m²]+3[mm²]"), "2[m^2]+3[mm^2]"); CHECK_EVAL("2[]", "2"); CHECK_INTERPRETED("2[]", "2"); CHECK_DISPLAY_INTERPRETED("2[]", "2"); CHECK_EVAL(QString::fromUtf8("[µV] -> [volt]"), "0.000001 volt"); CHECK_EVAL(QString::fromUtf8("[μV] -> [volt]"), "0.000001 volt"); CHECK_EVAL("[uV] -> [volt]", "0.000001 volt"); CHECK_EVAL("[um] -> [metre]", "0.000001 metre"); CHECK_EVAL_FAIL("[uB] -> [byte]"); CHECK_EVAL("[kB] -> [byte]", "1000 byte"); CHECK_EVAL("[MB] -> [byte]", "1000000 byte"); CHECK_EVAL_FAIL("[daB] -> [byte]"); CHECK_EVAL_FAIL("[dab] -> [bit]"); CHECK_EVAL_FAIL("[hB] -> [byte]"); CHECK_EVAL_FAIL("[hb] -> [bit]"); CHECK_EVAL("[hl] -> [litre]", "100 litre"); CHECK_EVAL("[hL] -> [litre]", "100 litre"); CHECK_EVAL("[daL] -> [litre]", "10 litre"); CHECK_EVAL("[dam] -> [metre]", "10 metre"); CHECK_EVAL("[daN] -> [newton]", "10 newton"); CHECK_EVAL("[daPa] -> [pascal]", "10 pascal"); CHECK_EVAL("[1 daL]", "1 daL"); CHECK_EVAL("[1 dam]", "1 dam"); CHECK_EVAL("[1 daN]", "1 daN"); CHECK_EVAL("[1 daPa]", "1 daPa"); CHECK_EVAL("[dag] -> [gram]", "10 gram"); CHECK_EVAL("[dag] -> [kilogram]", "0.01 kilogram"); CHECK_EVAL("[KiB] -> [byte]", "1024 byte"); CHECK_EVAL("[kb] -> [b]", "1000 b"); CHECK_EVAL("[Kib] -> [b]", "1024 b"); CHECK_EVAL("[1 kibibyte] -> [KiB]", "1 KiB"); CHECK_EVAL("[1 quebibit] -> [Qib]", "1 Qib"); CHECK_EVAL_FORMAT("1[byte]+2[byte]", "3[B]"); CHECK_EVAL_FORMAT("1[bit]+2[bit]", "3[b]"); CHECK_EVAL_FORMAT("2[MB]+3[PB]+4[TB]", "3.004000002[PB]"); CHECK_EVAL_FAIL("1[B]+8[b]"); CHECK_EVAL("[mm] -> [metre]", "0.001 metre"); CHECK_EVAL("[km] -> [metre]", "1000 metre"); CHECK_EVAL("[kpc] -> [parsec]", "1000 parsec"); CHECK_EVAL("[Mpc] -> [parsec]", "1000000 parsec"); CHECK_EVAL("[hm] -> [metre]", "100 metre"); CHECK_EVAL_FAIL("[hV] -> [volt]"); CHECK_EVAL("[hPa] -> [pascal]", "100 pascal"); CHECK_EVAL(QString::fromUtf8("[kΩ] -> [ohm]"), "1000 ohm"); CHECK_EVAL_FORMAT("2[coulomb]+3[mC]", "2.003[C]"); CHECK_EVAL_FORMAT("[C^3*m^3*J^(-2)]", u8"1[C³·J�²·m³]"); CHECK_EVAL_FORMAT("[C^4*m^4*J^(-3)]", u8"1[C�·J�³·m�]"); CHECK_EVAL_FORMAT("[A^4*s^10/(kg^3*m^2)]", u8"1[C�·J�³·m�]"); CHECK_EVAL_FORMAT("1081.20238677[C*m^(-3)]", u8"1081.20238677[C·m�³]"); CHECK_EVAL_FORMAT("[J/(K*mol)]", u8"1[J·mol�¹·K�¹]"); } void test_units_energy_per_geometry_display_scale() { CHECK_EVAL("4[J/m^3]", u8"4 joule / metre³"); CHECK_EVAL("7[J/m^2]", u8"7 joule / metre²"); CHECK_EVAL("4[TJ/m^3]", u8"4000000000000 joule / metre³"); CHECK_EVAL("ans in [J/m^3]", u8"4000000000000 J·m�³"); CHECK_EVAL("7[TJ/m^2]", u8"7000000000000 joule / metre²"); CHECK_EVAL("4[mJ/m^3]", u8"0.004 joule / metre³"); CHECK_EVAL("7[mJ/m^2]", u8"0.007 joule / metre²"); CHECK_EVAL("4[J/cm^3]", u8"4000000 joule / metre³"); CHECK_EVAL("7[J/cm^2]", u8"70000 joule / metre²"); CHECK_EVAL("4[kJ/cm^3]", u8"4000000000 joule / metre³"); CHECK_EVAL("7[kJ/cm^2]", u8"70000000 joule / metre²"); CHECK_EVAL("2[kWh/m^3]", u8"7200000 joule / metre³"); CHECK_EVAL("2[kWh/m^2]", u8"7200000 joule / metre²"); CHECK_EVAL("4[TJ] / 2[m^3]", u8"2000000000000 joule / metre³"); CHECK_EVAL("7[TJ] / 2[m^2]", u8"3500000000000 joule / metre²"); CHECK_EVAL_FORMAT("4[TJ/m^3]", u8"4000000000000[J / m³]"); CHECK_EVAL_FORMAT("7[TJ/m^2]", u8"7000000000000[J / m²]"); CHECK_EVAL("4[TJ/m^3] in [TJ/m^3]", u8"4 TJ·m�³"); CHECK_EVAL("7[TJ/m^2] in [TJ/m^2]", u8"7 TJ·m�²"); } void test_units_named_derived_canonicalization() { CHECK_EVAL_FORMAT("[kg*m^2/s^2]", "1[J]"); CHECK_EVAL_FORMAT("[Pa*m^3]", "1[J]"); CHECK_EVAL_FORMAT("[C*V]", "1[J]"); CHECK_EVAL_FORMAT("[N*m/s]", "1[W]"); CHECK_EVAL_FORMAT("[C/s]", "1[A]"); CHECK_EVAL_FORMAT("[A*s]", "1[C]"); CHECK_EVAL_FORMAT("[J/s]", "1[W]"); CHECK_EVAL_FORMAT("[kg*m^2/s^3]", "1[W]"); CHECK_EVAL_FORMAT("[V*A]", "1[W]"); CHECK_EVAL_FORMAT("[W/A]", "1[V]"); CHECK_EVAL_FORMAT("[J/C]", "1[V]"); CHECK_EVAL_FORMAT("[V/A]", u8"1[Ω]"); CHECK_EVAL_FORMAT("[A/V]", "1[S]"); CHECK_EVAL_FORMAT("[1/ohm]", "1[S]"); CHECK_EVAL_FORMAT(QString::fromUtf8("[1/Ω]"), "1[S]"); CHECK_EVAL_FORMAT("[C/V]", "1[F]"); CHECK_EVAL_FORMAT("[V*s]", "1[Wb]"); CHECK_EVAL_FORMAT("[Wb/m^2]", "1[T]"); CHECK_EVAL_FORMAT("[Wb/A]", "1[H]"); CHECK_EVAL_FORMAT("[kg*m/s^2]", "1[N]"); CHECK_EVAL_FORMAT("[N/m^2]", "1[Pa]"); CHECK_EVAL_FORMAT("[cd*sr]", "1[lm]"); CHECK_EVAL_FORMAT("[cd*sr*m^2]", u8"1[lm·m²]"); CHECK_EVAL_FORMAT("[lm/m^2]", "1[lx]"); CHECK_EVAL_FORMAT("[mol/s]", "1[kat]"); } void test_units_derived_si_recognition_and_disambiguation() { CHECK_EVAL("[metre]", "1 metre"); CHECK_EVAL("[kilogram]", "1 kg"); CHECK_EVAL("[tonne]", "1 tonne"); CHECK_EVAL("[t]", "1 t"); CHECK_EVAL("1[tonne] -> [kilogram]", "1000 kilogram"); CHECK_EVAL("1[t] -> [kilogram]", "1000 kilogram"); CHECK_EVAL("1000[kilogram] -> [tonne]", "1 tonne"); CHECK_EVAL("2.51 [t] + 3.2 [kg] + 2342.7 [g]", "2.5155427 t"); CHECK_EVAL("0.00000001 [t] + 3.2 [kg] + 2342.7 [g]", "5.54271 kilogram"); CHECK_EVAL("3.2 [kg] + 0.00000001 [t] + 2342.7 [g]", "5.54271 kilogram"); CHECK_EVAL("1200 [g] + 0.0005 [t]", "1.7 kilogram"); CHECK_EVAL("2 [t] - 500 [kg]", "1.5 t"); CHECK_EVAL("0.002 [t] - 500 [g]", "1.5 kilogram"); CHECK_EVAL("1 [s] + 1 [min] + 1 [h] - 1 [min]", "1.00027777777777777778 h"); CHECK_EVAL("1 [s] + 1 [min] + 1 [h] - 1.1 [min]", "59.91666666666666666667 minute"); CHECK_EVAL("1 [s] + 1 [min] - 1.1 [min]", "-5 second"); CHECK_EVAL("0.0001 [s] + 0.89999 [ms] + 1 [ns] + 1 [ps]", u8"999.991001 µs"); CHECK_EVAL("0.0001 [s] + 0.899999 [ms] + 1 [ns] + 1 [ps]", "1.000000001 ms"); CHECK_EVAL("0.0001 [m] + 0.899999 [mm] + 1 [nm] + 1 [pm]", "1.000000001 mm"); CHECK_EVAL("0.1 [m]", "100 mm"); CHECK_EVAL("0.01 [m]", "10 mm"); CHECK_EVAL("0.001 [m]", "1 mm"); CHECK_EVAL("0.1 [g]", "100 mg"); CHECK_EVAL("0.01 [g]", "10 mg"); CHECK_EVAL("0.001 [g]", "1 mg"); CHECK_EVAL(QString::fromUtf8("0.0001 [g]"), u8"100 µg"); CHECK_EVAL("0.1 [L]", "100 mL"); CHECK_EVAL("0.01 [L]", "10 mL"); CHECK_EVAL("0.001 [L]", "1 mL"); CHECK_EVAL(QString::fromUtf8("0.0001 [L]"), u8"100 µL"); CHECK_EVAL("0.1 [s]", "100 ms"); CHECK_EVAL("0.01 [s]", "10 ms"); CHECK_EVAL("0.001 [s]", "1 ms"); CHECK_EVAL(QString::fromUtf8("0.0001 [s]"), u8"100 µs"); CHECK_EVAL("0.1 [Pa]", "100 mPa"); CHECK_EVAL("0.01 [Pa]", "10 mPa"); CHECK_EVAL("0.001 [Pa]", "1 mPa"); CHECK_EVAL(QString::fromUtf8("0.0001 [Pa]"), u8"100 µPa"); CHECK_EVAL("[ps]", "1 ps"); CHECK_EVAL("1 [ps]", "1 ps"); CHECK_EVAL(QString::fromUtf8("1 × 10�¹² [s]"), "1 ps"); CHECK_EVAL("[second]", "1 second"); CHECK_EVAL("[coulomb/second]", "1 ampere"); CHECK_EVAL("[lumen/steradian]", "1 candela"); CHECK_EVAL("[1/second]", "1 second�¹"); CHECK_EVAL("[newton*metre]", "1 newton·metre"); CHECK_EVAL("[newton*metre] -> [joule]", "1 joule"); CHECK_EVAL("[joule/metre^3] -> [pascal]", "1 pascal"); CHECK_EVAL("[watt*second] -> [joule]", "1 joule"); CHECK_EVAL("[revolution/minute] -> [revolution_per_minute]", "1 revolution_per_minute"); CHECK_EVAL("[1609.344 metre/hour] -> [mile_per_hour]", "1 mile_per_hour"); CHECK_EVAL("[1000 metre/hour] -> [kilometre_per_hour]", "1 kilometre_per_hour"); CHECK_EVAL("[kilometre/hour]", "1 kilometre_per_hour"); CHECK_EVAL("[km/hour]", "1 kilometre_per_hour"); CHECK_EVAL("[km/h]", "1 kilometre_per_hour"); CHECK_EVAL("[mile/hour]", "1 mile_per_hour"); CHECK_EVAL("[mi/h]", "1 mile_per_hour"); CHECK_EVAL("[nautical_mile/hour]", "1 knot"); CHECK_EVAL("[nmi/h]", "1 knot"); CHECK_EVAL("1[km] / 1[h]", "1 kilometre_per_hour"); CHECK_EVAL("1[mi] / 1[h]", "1 mile_per_hour"); CHECK_EVAL("1[nmi] / 1[h]", "1 knot"); CHECK_EVAL("[kilowatt*hour] -> [kilowatt_hour]", "1 kilowatt_hour"); CHECK_EVAL("[133.322387415*pascal] -> [millimetre_of_mercury]", "1 millimetre_of_mercury"); CHECK_EVAL("[14*pound] -> [stone]", "1 stone"); CHECK_EVAL("[10*millilitre] -> [dessert_spoon]", "1 dessert_spoon"); CHECK_EVAL("[watt*volt]", "1 volt²·ampere"); CHECK_EVAL("[volt*ampere]", "1 watt"); CHECK_EVAL("[volt*second/metre^2]", "1 tesla"); CHECK_EVAL("[becquerel]", "1 becquerel"); CHECK_EVAL("[2 becquerel + 3 becquerel]", "5 becquerel"); CHECK_EVAL("[sievert]", "1 sievert"); CHECK_EVAL("[2 sievert + 3 sievert]", "5 sievert"); CHECK_EVAL_FAIL("1[hertz] + 1[becquerel]"); CHECK_EVAL_FAIL("1[gray] + 1[sievert]"); CHECK_EVAL("a=10", "10"); CHECK_EVAL("mg=3", "3"); CHECK_EVAL("l=2", "2"); CHECK_EVAL("a+mg+l", "15"); eval->unsetVariable("a"); eval->unsetVariable("mg"); eval->unsetVariable("l"); } void test_units_conversion_compatibility_and_canonicalization() { // Conversion compatibility and canonicalization regressions. CHECK_EVAL("[volt] -> [joule/coulomb]", u8"1 joule·coulomb�¹"); CHECK_EVAL("[joule/coulomb] -> [volt]", "1 volt"); CHECK_EVAL("[watt] -> [joule/second]", u8"1 joule·second�¹"); CHECK_EVAL("[joule/second] -> [watt]", "1 watt"); CHECK_EVAL("[ampere] -> [coulomb/second]", u8"1 coulomb·second�¹"); CHECK_EVAL("[coulomb/second] -> [ampere]", "1 ampere"); CHECK_EVAL("[volt] -> [ohm*ampere]", "1 ohm*ampere"); CHECK_EVAL("[ohm*ampere] -> [volt]", "1 volt"); CHECK_EVAL("[watt] -> [volt*ampere]", "1 volt*ampere"); CHECK_EVAL("[volt*ampere] -> [watt]", "1 watt"); CHECK_EVAL_FAIL("[volt] -> [watt]"); CHECK_EVAL_FAIL("[watt] -> [volt]"); CHECK_EVAL_FAIL("[volt] -> [ampere]"); CHECK_EVAL_FAIL("[ampere] -> [volt]"); CHECK_EVAL("[volt] -> [volt]", "1 volt"); CHECK_EVAL("[watt] -> [watt]", "1 watt"); CHECK_EVAL("[ampere] -> [ampere]", "1 ampere"); CHECK_EVAL("[kg*m^2/s^4] -> [kg*m^2/s^4]", u8"1 kg·m²·s��"); CHECK_EVAL("[volt^2] -> [volt^2]", "1 volt²"); CHECK_EVAL("[volt^2] -> [1 * (ohm * ampere)^2]", "1 1 * (ohm * ampere)²"); } void test_units_temperature_affine_conversions() { CHECK_EVAL("25[degree_celsius] -> [kelvin]", "298.15 kelvin"); CHECK_EVAL("0[degree_celsius] -> [degree_fahrenheit]", "32 degree_fahrenheit"); CHECK_EVAL("32[degree_fahrenheit] -> [degree_celsius]", "0 degree_celsius"); CHECK_EVAL("77[degree_fahrenheit] -> [kelvin]", "298.15 kelvin"); CHECK_EVAL("298.15[kelvin] -> [degree_fahrenheit]", "77 degree_fahrenheit"); CHECK_EVAL(QString::fromUtf8("0[°C] -> [kelvin]"), "273.15 kelvin"); CHECK_EVAL(QString::fromUtf8("0[˚C] -> [kelvin]"), "273.15 kelvin"); CHECK_EVAL(QString::fromUtf8("32[°F] -> [°C]"), "0 °C"); CHECK_EVAL(QString::fromUtf8("77[°F] -> [°C]"), "25 °C"); CHECK_EVAL(QString::fromUtf8("273.15[kelvin] -> [°C]"), "0 °C"); CHECK_EVAL(QString::fromUtf8("0[°C] -> [°F]"), "32 °F"); CHECK_EVAL(QString::fromUtf8("32[ºF] -> [ºC]"), "0 °C"); CHECK_EVAL(QString::fromUtf8("32[˚F] -> [˚C]"), "0 °C"); CHECK_EVAL_FORMAT(QString::fromUtf8("1[°C]"), u8"1[°C]"); CHECK_EVAL_FORMAT(QString::fromUtf8("1[˚C]"), u8"1[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("1[ºC]"), u8"1[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("1[degree_celsius]"), u8"1[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("1[degC]"), u8"1[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("1[Cel]"), u8"1[°C]"); CHECK_EVAL_FORMAT(QString::fromUtf8("203[°F]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QString::fromUtf8("203[˚F]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("203[ºF]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("203[degree_fahrenheit]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("203[degF]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("203[Fah]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QString::fromUtf8("1 [°C]"), u8"1[°C]"); CHECK_EVAL_FORMAT(QString::fromUtf8("203 [°F]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("1[oC]"), u8"1[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("203[oF]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QString::fromUtf8("1[°C] -> [°F]"), u8"33.8[°F]"); CHECK_EVAL_FORMAT(QString::fromUtf8("1[°F] -> [°C]"), u8"-17.22222222222222222222[°C]"); CHECK_EVAL_FORMAT(QString::fromUtf8("100[°C] -> [°C]"), u8"100[°C]"); CHECK_EVAL_FORMAT(QString::fromUtf8("100[˚C] -> [˚C]"), u8"100[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("100[ºC] -> [ºC]"), u8"100[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("100[degree_celsius] -> [degree_celsius]"), u8"100[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("100[degC] -> [degC]"), u8"100[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("100[Cel] -> [Cel]"), u8"100[°C]"); CHECK_EVAL_FORMAT(QString::fromUtf8("203[°F] -> [°F]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QString::fromUtf8("203[˚F] -> [˚F]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("203[ºF] -> [ºF]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("203[degree_fahrenheit] -> [degree_fahrenheit]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("203[degF] -> [degF]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("203[Fah] -> [Fah]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QStringLiteral("100[oC] -> [oC]"), u8"100[°C]"); CHECK_EVAL_FORMAT(QStringLiteral("203[oF] -> [oF]"), u8"203[°F]"); CHECK_EVAL_FORMAT(QString::fromUtf8("1 [°C] → [°F]"), u8"33.8[°F]"); CHECK_EVAL_FORMAT(QString::fromUtf8("1 [°F] → [°C]"), u8"-17.22222222222222222222[°C]"); CHECK_EVAL_FORMAT(QString::fromUtf8("1[K] -> [°C]"), u8"-272.15[°C]"); CHECK_EVAL_FORMAT(QString::fromUtf8("1[K] -> [°F]"), u8"-457.87[°F]"); CHECK_DISPLAY_INTERPRETED( QStringLiteral("100 [degC]"), QString::fromUtf8("100") + QString(MathDsl::QuantSp) + QString::fromUtf8("[°C]")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("100 [Cel]"), QString::fromUtf8("100") + QString(MathDsl::QuantSp) + QString::fromUtf8("[°C]")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("100 [K] → [°C]"), QString::fromUtf8("100") + QString(MathDsl::QuantSp) + QString::fromUtf8("[K]") + QString(MathDsl::AddWrap) + QString::fromUtf8("→") + QString(MathDsl::AddWrap) + QString::fromUtf8("[°C]")); // Scalar arithmetic on affine displays should use the shown temperature // scale instead of raw base-Kelvin storage. CHECK_EVAL(QString::fromUtf8("2 [°C] -> [°C]"), "2 °C"); CHECK_EVAL(QString::fromUtf8("ans"), "2 °C"); CHECK_EVAL(QString::fromUtf8("2*ans"), "4 °C"); CHECK_EVAL(QString::fromUtf8("ans/2"), "2 °C"); CHECK_EVAL(QString::fromUtf8("71.2 [°F] + 3 [°F]"), "74.2 °F"); CHECK_EVAL(QString::fromUtf8("71.2 [°F] - 3 [°F]"), "68.2 °F"); } void test_units_grouping_and_inverse_presentation() { Settings* settings = Settings::instance(); const char oldStyle = settings->unitNegativeExponentStyle; settings->unitNegativeExponentStyle = Settings::UnitNegativeExponentSuperscript; setRuntimeUnitNegativeExponentStyle(Settings::UnitNegativeExponentSuperscript); CHECK_EVAL_FORMAT("[m^2*s^-2]", u8"1[J·kg�¹]"); CHECK_EVAL("molmass(C6H12O6) * molmass(C6H12O6)", u8"32456.184336 g²·mol�²"); CHECK_EVAL_FORMAT("molmass(C6H12O6) * molmass(C6H12O6)", u8"32456.184336[g²·mol�²]"); CHECK_EVAL_FORMAT("molmass(C6H12O6) * molmass(C6H12O6) -> [g²/mol²]", u8"32456.184336[g²·mol�²]"); settings->unitNegativeExponentStyle = Settings::UnitNegativeExponentFraction; setRuntimeUnitNegativeExponentStyle(Settings::UnitNegativeExponentFraction); // If there is at least one positive exponent, render negative exponents // in denominator form for readability. CHECK_EVAL_FORMAT("[m*kg*s^-1]", u8"1[kg·m/s]"); CHECK_EVAL_FORMAT("[kg*m^-1*s^-1]", u8"1[Pa·s]"); CHECK_EVAL_FORMAT("[m^2*s^-1]", u8"1[m²/s]"); CHECK_EVAL_FORMAT("[kg*m^2*s^-1]", u8"1[kg·m²/s]"); CHECK_EVAL_FORMAT("[m*s^-1]", u8"1[m/s]"); CHECK_EVAL_FORMAT("[m/s]", u8"1[m/s]"); // If all exponents are negative, keep inverse-only exponent notation. CHECK_EVAL_FORMAT("[1/s]", u8"1[s�¹]"); CHECK_EVAL_FORMAT("[s^-1]", u8"1[s�¹]"); CHECK_EVAL_FORMAT("[1/(m*s^2)]", u8"1[m�¹·s�²]"); CHECK_EVAL_FORMAT("[m^-1*s^-2]", u8"1[m�¹·s�²]"); CHECK_EVAL_FORMAT("[m^-1/s^2]", u8"1[m�¹·s�²]"); settings->unitNegativeExponentStyle = oldStyle; setRuntimeUnitNegativeExponentStyle(oldStyle); } void test_units_preferred_derived_forms_regressions() { // Derived units should remain intact (no base expansion). CHECK_EVAL_FORMAT("5[N]", "5[N]"); CHECK_EVAL_FORMAT("12[J]", "12[J]"); CHECK_EVAL_FORMAT("3[W]", "3[W]"); CHECK_EVAL_FORMAT("9[Pa]", "9[Pa]"); CHECK_EVAL_FORMAT("2[V]", "2[V]"); CHECK_EVAL_FORMAT("7[ohm]", u8"7[Ω]"); CHECK_EVAL_FORMAT("4[F]", "4[F]"); CHECK_EVAL_FORMAT("6[H]", "6[H]"); CHECK_EVAL_FORMAT("8[T]", "8[T]"); CHECK_EVAL_FORMAT("1[Hz]", "1[Hz]"); // Combinations of derived units. CHECK_EVAL_FORMAT("3[N*m]", u8"3[N·m]"); CHECK_EVAL_FORMAT("10[J*s]", u8"10[J·s]"); CHECK_EVAL_FORMAT("2[W*h]", u8"2[W·h]"); CHECK_EVAL_FORMAT("5[Pa*s]", u8"5[Pa·s]"); CHECK_EVAL_FORMAT("7[V*A]", "7[W]"); CHECK_EVAL_FORMAT("4[ohm*m]", u8"4[Ω·m]"); CHECK_EVAL_FORMAT("6[F*V]", "6[C]"); CHECK_EVAL_FORMAT("8[H*A]", "8[Wb]"); CHECK_EVAL_FORMAT("9[T*m^2]", "9[Wb]"); // Powers of derived units. CHECK_EVAL_FORMAT("2[J^2]", u8"2[J²]"); CHECK_EVAL_FORMAT("4[N^3]", u8"4[N³]"); CHECK_EVAL_FORMAT("6[Pa^(-1)]", u8"6[Pa�¹]"); CHECK_EVAL_FORMAT("8[W^2]", u8"8[W²]"); CHECK_EVAL_FORMAT("3[V^3]", u8"3[V³]"); CHECK_EVAL_FORMAT("5[ohm^2]", u8"5[Ω²]"); // Mixed derived units should keep derived components. CHECK_EVAL_FORMAT("5[J*Pa]", u8"5[J·Pa]"); CHECK_EVAL_FORMAT("7[N*W]", u8"7[N·W]"); CHECK_EVAL_FORMAT("3[V*Hz]", u8"3[V·Hz]"); CHECK_EVAL_FORMAT("9[ohm*F]", u8"9[Ω·F]"); CHECK_EVAL_FORMAT("2[T*H]", u8"2[T·H]"); // Expressions combining values should preserve derived units. CHECK_EVAL_FORMAT("2[J] + 3[J]", "5[J]"); CHECK_EVAL_FORMAT("4[N] * 5[m]", u8"20[N·m]"); CHECK_EVAL_FORMAT("6[W] / 2[s]", u8"3[W / s]"); CHECK_EVAL_FORMAT("3[V] * 2[A]", "6[W]"); CHECK_EVAL_FORMAT("8[Pa] * 4[m^2]", "32[N]"); // Unit cancellation. CHECK_EVAL("10[N] / 2[N]", "5"); CHECK_EVAL("6[J] / 3[J]", "2"); CHECK_EVAL("8[W] / 4[W]", "2"); // Prefer derived units over base expansion. CHECK_EVAL_FORMAT("3[kg*m*s^(-2)]", "3[N]"); CHECK_EVAL_FORMAT("5[kg*m^2*s^(-2)]", "5[J]"); CHECK_EVAL_FORMAT("7[kg*m^(-1)*s^(-2)]", "7[Pa]"); // Avoid expanding when already in preferred derived form. CHECK_EVAL_FORMAT("2[N*m]", u8"2[N·m]"); CHECK_EVAL_FORMAT("4[J/s]", "4[W]"); CHECK_EVAL_FORMAT("6[W*s]", u8"6[W·s]"); // Edge cases. CHECK_EVAL_FORMAT("1[N*m/m]", "1[N]"); CHECK_EVAL_FORMAT("2[J/s]", "2[W]"); CHECK_EVAL_FORMAT("3[W*s/s]", "3[W]"); CHECK_EVAL_FORMAT("4[V*A/A]", "4[V]"); } void test_binary() { test_binary_power_operator(); test_binary_arithmetic_operator_variants(); } void test_units() { test_units_conversion_parentheses(); test_units_display_propagation(); test_units_short_aliases_and_si_prefixes(); test_units_energy_per_geometry_display_scale(); test_units_named_derived_canonicalization(); test_units_derived_si_recognition_and_disambiguation(); test_units_conversion_compatibility_and_canonicalization(); test_units_temperature_affine_conversions(); test_units_grouping_and_inverse_presentation(); test_units_preferred_derived_forms_regressions(); // Add/subtract must not mix a plain scalar with an explicitly unit-tagged // quantity, even when the unit dimension is mathematically dimensionless. CHECK_EVAL_FAIL("2 + 358 [deg]"); CHECK_EVAL_FAIL("2 - 358 [deg]"); // Multiplication remains valid with explicit angle units. ++eval_total_tests; eval->setExpression(QStringLiteral("2 * 358 [deg]")); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tmultiply scalar by explicit angle unit\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } // Exponentiation over explicit value+unit attachment is ambiguous. CHECK_EVAL_FAIL("2[kg]^2"); CHECK_EVAL_FAIL(QString::fromUtf8("2[kg]²")); // numval: numerical value in base SI unless a target display unit is explicit. CHECK_EVAL("numval(3)", "3"); CHECK_EVAL("numval(3 [m/s])", "3"); CHECK_EVAL("numval(3 [km/s])", "3000"); CHECK_EVAL("numval(3 [km/s] -> [cm/s])", "300000"); } void test_unit_expression_powers() { CHECK_EVAL("(2[m])^2", u8"4 metre²"); CHECK_EVAL(QString::fromUtf8("(2[m])²"), u8"4 metre²"); CHECK_EVAL("((2[m]))**2", u8"4 metre²"); CHECK_EVAL("(2[m])^-2", u8"0.25 metre�²"); CHECK_EVAL(QString::fromUtf8("(2[m])�²"), u8"0.25 metre�²"); CHECK_EVAL("(2[m]+3[m])^2", u8"25 metre²"); CHECK_EVAL("(2[m]/1[m])^2", "4"); CHECK_EVAL("(2[m]/1[m])^(-2)", "0.25"); CHECK_EVAL("[m]^2", u8"1 metre²"); CHECK_EVAL("sqrt(4[m^2])^2", u8"4 metre²"); CHECK_EVAL("((2[m/s])^2)/(4[m^2/s^2])", "1"); CHECK_EVAL(QString::fromUtf8("(2[m])²+(3[m])²"), u8"13 metre²"); CHECK_EVAL(QString::fromUtf8("1 × 10�³ + (2[m]/1[m])²"), "4.001"); CHECK_EVAL_FAIL("2[m]^(-2)"); CHECK_EVAL_FAIL(QString::fromUtf8("2[m]�²")); CHECK_EVAL_FAIL("(2[m])[s]^2"); CHECK_EVAL_FAIL("2[]^2"); Session reportSession; Evaluator* reportEvaluator = reportSession.evaluator(); const auto checkReportExpression = [&](const QString& expression, const char* expected) { ++eval_total_tests; reportEvaluator->setExpression(expression); const Quantity result = reportEvaluator->evalUpdateAns(); const QString actual = reportEvaluator->error().isEmpty() ? DMath::format(result, Format::Fixed()) : reportEvaluator->error(); DisplayErrorOnMismatch(__FILE__, __LINE__, qPrintable(expression), actual.toStdString(), expected, eval_failed_tests, eval_new_failed_tests); }; checkReportExpression(QStringLiteral("c=299792458[m/s]"), u8"299792458 metre·second�¹"); checkReportExpression( QStringLiteral("1+1.602e-19[coulomb]*1[kV]/(9.109e-31[kg]*c^2)"), "1.00195681786123383108"); checkReportExpression( QStringLiteral("c*sqrt(1-(1+1.602e-19[coulomb]*1[kV]/(9.109e-31[kg]*c^2))^-2)"), u8"18727260.54958148079607995581 metre·second�¹"); checkReportExpression( QString::fromUtf8("c × sqrt(1 − (1 + (1.602 × 10�¹�[coulomb] × 1[kV])" " / (9.109 × 10�³¹[kg] × c²))�²)"), u8"18727260.54958148079607995581 metre·second�¹"); } void test_percent_operator() { CHECK_EVAL("50%", "0.5"); CHECK_EVAL("(20+30)%", "0.5"); CHECK_EVAL("50%%", "0.005"); CHECK_EVAL("-50%", "-0.5"); CHECK_EVAL("1000+12%", "1120"); CHECK_EVAL(QString::fromUtf8("100\u205F+\u205F12%"), "112"); CHECK_EVAL("1000-12%", "880"); CHECK_EVAL("1000+125%", "2250"); CHECK_EVAL("1000+(12%)", "1120"); CHECK_EVAL("1000-(12%)", "880"); CHECK_EVAL("1000+(-12%)", "880"); CHECK_EVAL("1000-(-12%)", "1120"); CHECK_EVAL("1000+(10+2)%", "1120"); CHECK_EVAL("1000-(10+2)%", "880"); CHECK_EVAL("1000+10%+10%", "1210"); CHECK_EVAL("1000-10%-10%", "810"); CHECK_EVAL("1000+10%-10%", "990"); CHECK_EVAL("1000-10%+10%", "990"); CHECK_EVAL("100+10%+10%+10%", "133.1"); CHECK_EVAL("1000*12%", "120"); CHECK_EVAL("12%*1000", "120"); CHECK_EVAL("1000/25%", "4000"); CHECK_EVAL("200+(10%*2)", "200.2"); CHECK_EVAL("200+10%^2", "200.01"); CHECK_EVAL("100+(10%+10%)", "100.11"); CHECK_EVAL("100-(10%+10%)", "99.89"); CHECK_EVAL("100-(10%-5%)", "99.905"); CHECK_EVAL("1+2+3+10%", "6.6"); CHECK_EVAL("1+(2+3)+10%", "6.6"); CHECK_EVAL("(1+2+3)+10%", "6.6"); CHECK_EVAL("1+2+(3+10%)", "6.3"); CHECK_EVAL("1+99-10%", "90"); CHECK_EVAL("(1+99)-10%", "90"); CHECK_EVAL("1+(99-10%)", "90.1"); CHECK_EVAL("200[metre]+10%", "220 metre"); CHECK_EVAL("200[metre]-10%", "180 metre"); CHECK_EVAL("200[metre]+10%+10%", "242 metre"); CHECK_EVAL_FAIL("%"); CHECK_EVAL_FAIL("100+%"); CHECK_INTERPRETED("1000+12%", "1000+12%"); CHECK_INTERPRETED("1+99+10%", "(1+99)+10%"); CHECK_INTERPRETED("1+2+3+10%", "(1+2+3)+10%"); CHECK_INTERPRETED("1+(2+3)+10%", "(1+(2+3))+10%"); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1+99+10%"), QStringLiteral("100") + QString(MathDsl::AddWrap) + QStringLiteral("+") + QString(MathDsl::AddWrap) + QStringLiteral("10%")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("cos pi cos pi + 10%"), QString::fromUtf8("cos²(pi)") + QString(MathDsl::AddWrap) + QStringLiteral("+") + QString(MathDsl::AddWrap) + QStringLiteral("10%")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1 + cos pi cos pi + 10%"), QStringLiteral("(cos²(pi)") + QString(MathDsl::AddWrap) + QStringLiteral("+") + QString(MathDsl::AddWrap) + QStringLiteral("1)") + QString(MathDsl::AddWrap) + QStringLiteral("+") + QString(MathDsl::AddWrap) + QStringLiteral("10%")); CHECK_EVAL(Evaluator::simplifyInterpretedExpression("100+12%"), "112"); CHECK_EVAL(Evaluator::simplifyInterpretedExpression("1+2+3+10%"), "6.6"); CHECK_EVAL(Evaluator::simplifyInterpretedExpression("1+(2+3)+10%"), "6.6"); CHECK_EVAL(Evaluator::simplifyInterpretedExpression("1+cos pi cos pi+10%"), "2.2"); } void test_bitwise_complement_operator() { CHECK_EVAL("~~~~1", "1"); CHECK_EVAL("~-~1", "-3"); CHECK_EVAL("-~-1", "0"); CHECK_EVAL("~~-1", "-1"); CHECK_EVAL("(~2)^3", "-27"); CHECK_EVAL("~(2^3)", "-9"); CHECK_EVAL("~2^3", "-9"); CHECK_EVAL("~(-5)", "4"); CHECK_EVAL("-~(-1)", "0"); CHECK_EVAL("-5 & 3", "3"); CHECK_EVAL("-5 | 3", "-5"); CHECK_EVAL("-5 ^ 3", "-125"); CHECK_EVAL("~0 >> 1", "-1"); CHECK_EVAL("~0 << 1", "-2"); CHECK_EVAL("-1 >> 1", "-1"); CHECK_EVAL("-8 >> 2", "-2"); CHECK_EVAL("-9 >> 2", "-3"); CHECK_EVAL("~1 & 1", "0"); CHECK_EVAL("~1 | 1", "-1"); CHECK_EVAL("1 | 2 & 3", "3"); CHECK_EVAL("(1 | 2) & 3", "3"); CHECK_EVAL("1 | (2 & 3)", "3"); CHECK_EVAL("2*~3", "-8"); CHECK_EVAL("~3*2", "-8"); CHECK_EVAL("~(3*2)", "-7"); CHECK_EVAL("~2^3&7", "7"); CHECK_EVAL("~(2^3&7)", "-1"); CHECK_EVAL("(~2^3)&7", "7"); CHECK_EVAL("~(~(~1))", "-2"); CHECK_EVAL("~(~(~(~1)))", "1"); CHECK_EVAL("~5", "-6"); CHECK_EVAL("~(~5)", "5"); CHECK_EVAL("~(~(~5))", "-6"); CHECK_EVAL("~(2^3) + ~3! * (~1 & 3) << 1", "-46"); // Regression: keep unary minus and bitwise complement/function-not consistent. CHECK_EVAL("not(-1)", "0"); CHECK_EVAL("~(-1)", "0"); CHECK_EVAL("-not(-1)", "0"); CHECK_EVAL("-~(-1)", "0"); CHECK_EVAL("not(not(not(not(1))))", "1"); CHECK_EVAL("not(-not(1))", "-3"); CHECK_EVAL("-not(-1)", "0"); CHECK_EVAL("not(not(-1))", "-1"); CHECK_EVAL("(not(2))^3", "-27"); CHECK_EVAL("not(2^3)", "-9"); CHECK_EVAL("not(2^3)", "-9"); CHECK_EVAL("not(-5)", "4"); CHECK_EVAL("not(0) >> 1", "-1"); CHECK_EVAL("not(0) << 1", "-2"); CHECK_EVAL("not(1) & 1", "0"); CHECK_EVAL("not(1) | 1", "-1"); CHECK_EVAL("2*not(3)", "-8"); CHECK_EVAL("not(3)*2", "-8"); CHECK_EVAL("not(3*2)", "-7"); CHECK_EVAL("not(2^3&7)", "-1"); CHECK_EVAL("not(2^3&7)", "-1"); CHECK_EVAL("(not(2^3))&7", "7"); CHECK_EVAL("not(not(not(1)))", "-2"); CHECK_EVAL("not(not(not(not(1))))", "1"); CHECK_EVAL("not(5)", "-6"); CHECK_EVAL("not(not(5))", "5"); CHECK_EVAL("not(not(not(5)))", "-6"); CHECK_EVAL("not(2^3) + not(3!) * (not(1) & 3) << 1", "-46"); } void test_divide_by_zero() { CHECK_DIV_BY_ZERO("1/0"); CHECK_DIV_BY_ZERO("1 / sin 0"); CHECK_DIV_BY_ZERO("1/sin(pi)"); CHECK_DIV_BY_ZERO("1/sin (pi"); CHECK_DIV_BY_ZERO("1/sin pi"); CHECK_DIV_BY_ZERO("1 / cos (pi/2)"); CHECK_DIV_BY_ZERO("1 / cos(pi/2"); CHECK_DIV_BY_ZERO("1/cos(pi/2)"); CHECK_DIV_BY_ZERO("1/tan(0)"); CHECK_DIV_BY_ZERO("1/tan 0"); CHECK_DIV_BY_ZERO("-1/trunc(0.123)"); CHECK_DIV_BY_ZERO("1/round(0.456)"); CHECK_DIV_BY_ZERO("-1/binompmf(1;10;0)"); CHECK_DIV_BY_ZERO("-345.3 / binompmf (1; 10; 0)"); CHECK_DIV_BY_ZERO("mod(1;0)"); CHECK_DIV_BY_ZERO("emod(1;0)"); CHECK_DIV_BY_ZERO("powmod(2;10;0)"); } void test_radix_char() { // Backup current settings Settings* settings = Settings::instance(); char radixCharacter = settings->radixCharacter(); settings->setRadixCharacter('*'); CHECK_EVAL("1+.5", "1.5"); CHECK_EVAL("1+,5", "1.5"); CHECK_EVAL(".5*,5", "0.25"); CHECK_EVAL("1.01+2,02", "3.03"); CHECK_EVAL("0b1.0 + 1", "2"); CHECK_EVAL("0b1.1 * 1", "1.5"); CHECK_EVAL("0b01.010 / 1", "1.25"); CHECK_EVAL("-0b.010 - 1", "-1.25"); CHECK_EVAL("0o.7 + 1", "1.875"); CHECK_EVAL("-0o.7 + 1", "0.125"); CHECK_EVAL("0x.f + 1", "1.9375"); CHECK_EVAL("-0x.f + 1", "0.0625"); CHECK_EVAL("1/.1", "10"); // ISSUE 151 CHECK_EVAL("1/,1", "10"); // ISSUE 151 // Test automatic detection of radix point when multiple choices are possible CHECK_EVAL("1,234.567", "1234.567"); CHECK_EVAL("1.234,567", "1234.567"); CHECK_EVAL("1,2,3", "123"); CHECK_EVAL("1.2.3", "123"); CHECK_EVAL("1,234,567.89", "1234567.89"); CHECK_EVAL("1.234.567,89", "1234567.89"); CHECK_EVAL("1,234.567,89", "1234.56789"); CHECK_EVAL("1.234,567.89", "1234.56789"); settings->setRadixCharacter('.'); CHECK_EVAL("1+0.5", "1.5"); CHECK_EVAL("1+0,5", "1.5"); CHECK_EVAL("1/.1", "10"); CHECK_EVAL("1/,1", "10"); CHECK_EVAL("1,234.567", "1234.567"); CHECK_EVAL("1.234,567", "1234.567"); CHECK_EVAL("1,2,3", "123"); CHECK_EVAL("1.2.3", "123"); CHECK_EVAL("1,234,567.89", "1234567.89"); CHECK_EVAL("1.234.567,89", "1234567.89"); CHECK_EVAL("1,234.567,89", "1234.56789"); CHECK_EVAL("1.234,567.89", "1234.56789"); settings->setRadixCharacter(','); CHECK_EVAL("1+0.5", "1.5"); CHECK_EVAL("1+0,5", "1.5"); CHECK_EVAL("1/.1", "10"); CHECK_EVAL("1/,1", "10"); CHECK_EVAL("1,234.567", "1234.567"); CHECK_EVAL("1.234,567", "1234.567"); CHECK_EVAL("1,2,3", "123"); CHECK_EVAL("1.2.3", "123"); CHECK_EVAL("1,234,567.89", "1234567.89"); CHECK_EVAL("1.234.567,89", "1234567.89"); CHECK_EVAL("1,234.567,89", "1234.56789"); CHECK_EVAL("1.234,567.89", "1234.56789"); // Restore old settings settings->setRadixCharacter(radixCharacter); } void test_thousand_sep() { // Common separators. CHECK_EVAL("12_345.678_9", "12345.6789"); CHECK_EVAL("1234_5.67_89", "12345.6789"); CHECK_EVAL("1234_56", "123456"); CHECK_EVAL("_123456", "123456"); CHECK_EVAL("123456_", "123456"); CHECK_EVAL("123___456", "123456"); CHECK_EVAL("._123456", "0.123456"); CHECK_EVAL("12 345.678 9", "12345.6789"); // CHECK_EVAL("12'345.678'9", "12345.6789"); CHECK_EVAL(QString::fromUtf8("12·345.678·9"), "37333.224"); CHECK_EVAL(QString::fromUtf8("12٫345.678٫9"), "12345.6789"); CHECK_EVAL(QString::fromUtf8("12٬345.678٬9"), "12345.6789"); CHECK_EVAL(QString::fromUtf8("12˙345.678˙9"), "12345.6789"); CHECK_EVAL(QString::fromUtf8("12⎖345.678⎖9"), "12345.6789"); // Punctuation/symbol separators. CHECK_EVAL("12$345.678~9", "12345.6789"); CHECK_EVAL("12`345.678@9", "12345.6789"); CHECK_EVAL(QString::fromUtf8("12€345.678€9"), "12345.6789"); CHECK_EVAL(QString::fromUtf8("12£345.678£9"), "12345.6789"); CHECK_EVAL(QString::fromUtf8("12¥345.678¥9"), "12345.6789"); CHECK_EVAL(QString::fromUtf8("12₩345.678₩9"), "12345.6789"); // Prefix/suffix separators are still accepted. CHECK_EVAL("$ 1234.567", "1234.567"); CHECK_EVAL("1234.567 $", "1234.567"); CHECK_EVAL(QString::fromUtf8("€ 1234.567"), "1234.567"); CHECK_EVAL(QString::fromUtf8("1234.567 ¥"), "1234.567"); CHECK_EVAL("$-10", "-10"); CHECK_EVAL("$+10", "10"); // Unicode letters between digits must not be silently ignored. CHECK_EVAL_FAIL(QString::fromUtf8("12天2")); CHECK_EVAL_FAIL(QString::fromUtf8("12é2")); CHECK_EVAL_FAIL(QString::fromUtf8("12ä2")); CHECK_EVAL_FAIL(QString::fromUtf8("12ß2")); CHECK_EVAL_FAIL(QString::fromUtf8("12Ж2")); CHECK_EVAL_FAIL(QString::fromUtf8("12π2")); CHECK_EVAL_FAIL(QString::fromUtf8("12Ω2")); CHECK_EVAL_FAIL(QString::fromUtf8("12क2")); CHECK_EVAL_FAIL(QString::fromUtf8("12م2")); CHECK_EVAL_FAIL(QString::fromUtf8("12�2")); CHECK_EVAL_FAIL(QString::fromUtf8("12한2")); CHECK_EVAL_FAIL(QString::fromUtf8("1天234")); CHECK_EVAL_FAIL(QString::fromUtf8("12天345.67")); CHECK_EVAL_FAIL(QString::fromUtf8("12.34天56")); CHECK_EVAL_FAIL(QString::fromUtf8("12e3天4")); CHECK_EVAL_FAIL(QString::fromUtf8("0x1天2")); CHECK_EVAL_FAIL(QString::fromUtf8("0b10天01")); CHECK_EVAL_FAIL(QString::fromUtf8("0o12天34")); } void test_number_format_decimal_separator() { Settings* settings = Settings::instance(); const Settings::NumberFormatStyle oldNumberFormatStyle = settings->numberFormatStyle; settings->numberFormatStyle = Settings::NumberFormatNoGroupingDot; settings->applyNumberFormatStyle(); CHECK_EVAL_FORMAT_EXACT("1/2", QStringLiteral("0.5")); settings->numberFormatStyle = Settings::NumberFormatNoGroupingComma; settings->applyNumberFormatStyle(); CHECK_EVAL_FORMAT_EXACT("1/2", QStringLiteral("0,5")); settings->numberFormatStyle = oldNumberFormatStyle; settings->applyNumberFormatStyle(); } void test_number_format_styles_matrix() { struct NumberFormatCase { Settings::NumberFormatStyle style; QString base; QString shortValue; QString negative; QString integerOnly; }; const NumberFormatCase cases[] = { {Settings::NumberFormatNoGroupingDot, QStringLiteral("1234567.1234567"), QStringLiteral("1234.56"), QStringLiteral("-1234567.1234567"), QStringLiteral("1234567")}, {Settings::NumberFormatNoGroupingComma, QStringLiteral("1234567,1234567"), QStringLiteral("1234,56"), QStringLiteral("-1234567,1234567"), QStringLiteral("1234567")}, {Settings::NumberFormatSIDot, QStringLiteral("1 234 567.123 456 7"), QStringLiteral("1 234.56"), QStringLiteral("-1 234 567.123 456 7"), QStringLiteral("1 234 567")}, {Settings::NumberFormatSIComma, QStringLiteral("1 234 567,123 456 7"), QStringLiteral("1 234,56"), QStringLiteral("-1 234 567,123 456 7"), QStringLiteral("1 234 567")}, {Settings::NumberFormatThreeDigitCommaDot, QStringLiteral("1,234,567.1234567"), QStringLiteral("1,234.56"), QStringLiteral("-1,234,567.1234567"), QStringLiteral("1,234,567")}, {Settings::NumberFormatThreeDigitCommaDotFraction, QStringLiteral("1,234,567.123,456,7"), QStringLiteral("1,234.56"), QStringLiteral("-1,234,567.123,456,7"), QStringLiteral("1,234,567")}, {Settings::NumberFormatThreeDigitDotComma, QStringLiteral("1.234.567,1234567"), QStringLiteral("1.234,56"), QStringLiteral("-1.234.567,1234567"), QStringLiteral("1.234.567")}, {Settings::NumberFormatThreeDigitDotCommaFraction, QStringLiteral("1.234.567,123.456.7"), QStringLiteral("1.234,56"), QStringLiteral("-1.234.567,123.456.7"), QStringLiteral("1.234.567")}, {Settings::NumberFormatThreeDigitSpaceDot, QStringLiteral("1 234 567.1234567"), QStringLiteral("1 234.56"), QStringLiteral("-1 234 567.1234567"), QStringLiteral("1 234 567")}, {Settings::NumberFormatThreeDigitSpaceComma, QStringLiteral("1 234 567,1234567"), QStringLiteral("1 234,56"), QStringLiteral("-1 234 567,1234567"), QStringLiteral("1 234 567")}, {Settings::NumberFormatThreeDigitUnderscoreDot, QStringLiteral("1_234_567.1234567"), QStringLiteral("1_234.56"), QStringLiteral("-1_234_567.1234567"), QStringLiteral("1_234_567")}, {Settings::NumberFormatThreeDigitUnderscoreDotFraction, QStringLiteral("1_234_567.123_456_7"), QStringLiteral("1_234.56"), QStringLiteral("-1_234_567.123_456_7"), QStringLiteral("1_234_567")}, {Settings::NumberFormatThreeDigitUnderscoreComma, QStringLiteral("1_234_567,1234567"), QStringLiteral("1_234,56"), QStringLiteral("-1_234_567,1234567"), QStringLiteral("1_234_567")}, {Settings::NumberFormatThreeDigitUnderscoreCommaFraction, QStringLiteral("1_234_567,123_456_7"), QStringLiteral("1_234,56"), QStringLiteral("-1_234_567,123_456_7"), QStringLiteral("1_234_567")}, {Settings::NumberFormatIndianCommaDot, QStringLiteral("12,34,567.1234567"), QStringLiteral("1,234.56"), QStringLiteral("-12,34,567.1234567"), QStringLiteral("12,34,567")} }; Settings* settings = Settings::instance(); const Settings::NumberFormatStyle oldNumberFormatStyle = settings->numberFormatStyle; const bool oldDigitGroupingIntegerPartOnly = settings->digitGroupingIntegerPartOnly; auto checkValue = [&](const QString& label, const QString& actual, const QString& expected, int style) { ++eval_total_tests; if (actual != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label.toUtf8().constData() << "\t[NEW]" << endl << "\tStyle : " << style << endl << "\tResult : " << actual.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } }; for (const auto& item : cases) { settings->numberFormatStyle = item.style; settings->applyNumberFormatStyle(); checkValue( QStringLiteral("base literal formatting"), DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("1234567.1234567")), item.base, static_cast(item.style)); checkValue( QStringLiteral("short literal formatting"), DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("1234.56")), item.shortValue, static_cast(item.style)); checkValue( QStringLiteral("negative literal formatting"), DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("-1234567.1234567")), item.negative, static_cast(item.style)); checkValue( QStringLiteral("integer literal formatting"), DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("1234567")), item.integerOnly, static_cast(item.style)); } settings->numberFormatStyle = oldNumberFormatStyle; settings->applyNumberFormatStyle(); settings->digitGroupingIntegerPartOnly = oldDigitGroupingIntegerPartOnly; } void test_tolerant_number_input_with_dot_style() { Settings* settings = Settings::instance(); const Settings::NumberFormatStyle oldNumberFormatStyle = settings->numberFormatStyle; settings->numberFormatStyle = Settings::NumberFormatNoGroupingDot; settings->applyNumberFormatStyle(); CHECK_EVAL("1,56", "1.56"); CHECK_EVAL("12,56", "12.56"); CHECK_EVAL("123,56", "123.56"); CHECK_EVAL("1234,56", "1234.56"); CHECK_EVAL("1,234.56", "1234.56"); CHECK_EVAL("1.234,56", "1234.56"); CHECK_EVAL("1,23456", "1.23456"); CHECK_EVAL("1.23456", "1.23456"); CHECK_EVAL("1,234,566.789,012", "1234566.789012"); CHECK_EVAL("1.234.566,789.012", "1234566.789012"); settings->numberFormatStyle = oldNumberFormatStyle; settings->applyNumberFormatStyle(); } void test_number_format_style_behavior_all_supported_styles() { struct NumberFormatBehaviorCase { Settings::NumberFormatStyle style; QString displayExpected; }; const NumberFormatBehaviorCase cases[] = { {Settings::NumberFormatNoGroupingDot, QStringLiteral("1234567.12345")}, {Settings::NumberFormatNoGroupingComma, QStringLiteral("1234567,12345")}, {Settings::NumberFormatThreeDigitCommaDot, QStringLiteral("1,234,567.12345")}, {Settings::NumberFormatThreeDigitDotComma, QStringLiteral("1.234.567,12345")}, {Settings::NumberFormatThreeDigitSpaceDot, QStringLiteral("1 234 567.12345")}, {Settings::NumberFormatSIDot, QStringLiteral("1 234 567.123 45")}, {Settings::NumberFormatThreeDigitSpaceComma, QStringLiteral("1 234 567,12345")}, {Settings::NumberFormatSIComma, QStringLiteral("1 234 567,123 45")}, {Settings::NumberFormatThreeDigitCommaDotFraction, QStringLiteral("1,234,567.123,45")}, {Settings::NumberFormatThreeDigitDotCommaFraction, QStringLiteral("1.234.567,123.45")}, {Settings::NumberFormatThreeDigitUnderscoreDot, QStringLiteral("1_234_567.12345")}, {Settings::NumberFormatThreeDigitUnderscoreDotFraction, QStringLiteral("1_234_567.123_45")}, {Settings::NumberFormatThreeDigitUnderscoreComma, QStringLiteral("1_234_567,12345")}, {Settings::NumberFormatThreeDigitUnderscoreCommaFraction, QStringLiteral("1_234_567,123_45")}, {Settings::NumberFormatIndianCommaDot, QStringLiteral("12,34,567.12345")} }; Settings* settings = Settings::instance(); const Settings::NumberFormatStyle oldNumberFormatStyle = settings->numberFormatStyle; auto checkValue = [&](const QString& label, const QString& actual, const QString& expected, int style) { ++eval_total_tests; if (actual != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label.toUtf8().constData() << "\t[NEW]" << endl << "\tStyle : " << style << endl << "\tResult : " << actual.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } }; for (const auto& item : cases) { settings->numberFormatStyle = item.style; settings->applyNumberFormatStyle(); checkValue( QStringLiteral("style display sample formatting"), DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("1234567.12345")), item.displayExpected, static_cast(item.style)); eval->setExpression(QStringLiteral("1234567.12345")); Quantity evaluated = eval->evalUpdateAns(); QString exact = NumberFormatter::format(evaluated); exact.replace(QString::fromUtf8("−"), "-"); QString exactExpected = QStringLiteral("1234567"); exactExpected += QChar(settings->decimalSeparator()); exactExpected += QStringLiteral("12345"); checkValue( QStringLiteral("style selected exact evaluation formatting"), exact, exactExpected, static_cast(item.style)); } settings->numberFormatStyle = oldNumberFormatStyle; settings->applyNumberFormatStyle(); } void test_tolerant_number_input_all_styles() { Settings* settings = Settings::instance(); const Settings::NumberFormatStyle oldNumberFormatStyle = settings->numberFormatStyle; const Settings::NumberFormatStyle styles[] = { Settings::NumberFormatNoGroupingDot, Settings::NumberFormatNoGroupingComma, Settings::NumberFormatSIDot, Settings::NumberFormatSIComma, Settings::NumberFormatThreeDigitCommaDot, Settings::NumberFormatThreeDigitCommaDotFraction, Settings::NumberFormatThreeDigitDotComma, Settings::NumberFormatThreeDigitDotCommaFraction, Settings::NumberFormatThreeDigitSpaceDot, Settings::NumberFormatThreeDigitSpaceComma, Settings::NumberFormatThreeDigitUnderscoreDot, Settings::NumberFormatThreeDigitUnderscoreDotFraction, Settings::NumberFormatThreeDigitUnderscoreComma, Settings::NumberFormatThreeDigitUnderscoreCommaFraction, Settings::NumberFormatIndianCommaDot }; const struct { const char* expr; const char* expected; } cases[] = { {"1,56", "1.56"}, {"12,56", "12.56"}, {"123,56", "123.56"}, {"1234,56", "1234.56"}, {"1,234.56", "1234.56"}, {"1.234,56", "1234.56"}, {"1,23456", "1.23456"}, {"1.23456", "1.23456"}, {"1,234,566.789,012", "1234566.789012"}, {"1.234.566,789.012", "1234566.789012"}, // Ambiguous mixed separators: keep parsing permissive for copy/paste. {"1.123123,123123,32", "1.12312312312332"}, {"1,234,566.564,454545,45.23", "12345665644545454523"}, {"1.23.23,42342 242.4", "12323.423422424"}, {"12,3.23,42342 242.4", "12323423422424"} }; for (const auto style : styles) { settings->numberFormatStyle = style; settings->applyNumberFormatStyle(); for (const auto& c : cases) CHECK_EVAL(c.expr, c.expected); } settings->numberFormatStyle = oldNumberFormatStyle; settings->applyNumberFormatStyle(); } void test_settings_default_result_line_behavior() { Settings* settings = Settings::instance(); const bool oldComplexNumbers = settings->complexNumbers; const bool oldMultipleLinesEnabled = settings->multipleResultLinesEnabled; const bool oldSecondaryEnabled = settings->secondaryResultEnabled; const bool oldTertiaryEnabled = settings->tertiaryResultEnabled; const bool oldQuaternaryEnabled = settings->quaternaryResultEnabled; const bool oldQuinaryEnabled = settings->quinaryResultEnabled; const char oldImaginaryUnit = settings->imaginaryUnit; const Settings::NumberFormatStyle oldNumberFormatStyle = settings->numberFormatStyle; // Emulate first-launch defaults for this behavior check. settings->complexNumbers = false; settings->multipleResultLinesEnabled = false; settings->secondaryResultEnabled = false; settings->tertiaryResultEnabled = false; settings->quaternaryResultEnabled = false; settings->quinaryResultEnabled = false; settings->imaginaryUnit = 'i'; settings->numberFormatStyle = Settings::NumberFormatNoGroupingDot; settings->applyNumberFormatStyle(); auto checkBool = [](const char* file, int line, const char* label, bool actual, bool expected) { ++eval_total_tests; if (actual != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << label << "\t[NEW]" << endl << "\tResult : " << (actual ? "true" : "false") << endl << "\tExpected : " << (expected ? "true" : "false") << endl; } }; auto checkChar = [](const char* file, int line, const char* label, char actual, char expected) { ++eval_total_tests; if (actual != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << label << "\t[NEW]" << endl << "\tResult : " << actual << endl << "\tExpected : " << expected << endl; } }; auto checkInt = [](const char* file, int line, const char* label, int actual, int expected) { ++eval_total_tests; if (actual != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << label << "\t[NEW]" << endl << "\tResult : " << actual << endl << "\tExpected : " << expected << endl; } }; checkBool(__FILE__, __LINE__, "complex numbers default disabled", settings->complexNumbers, false); checkBool(__FILE__, __LINE__, "multiple result lines default disabled", settings->multipleResultLinesEnabled, false); checkBool(__FILE__, __LINE__, "secondary line default disabled", settings->secondaryResultEnabled, false); checkBool(__FILE__, __LINE__, "tertiary line default disabled", settings->tertiaryResultEnabled, false); checkBool(__FILE__, __LINE__, "quaternary line default disabled", settings->quaternaryResultEnabled, false); checkBool(__FILE__, __LINE__, "quinary line default disabled", settings->quinaryResultEnabled, false); checkChar(__FILE__, __LINE__, "default imaginary unit", settings->imaginaryUnit, 'i'); checkInt(__FILE__, __LINE__, "default number format style", static_cast(settings->numberFormatStyle), static_cast(Settings::NumberFormatNoGroupingDot)); settings->complexNumbers = oldComplexNumbers; settings->multipleResultLinesEnabled = oldMultipleLinesEnabled; settings->secondaryResultEnabled = oldSecondaryEnabled; settings->tertiaryResultEnabled = oldTertiaryEnabled; settings->quaternaryResultEnabled = oldQuaternaryEnabled; settings->quinaryResultEnabled = oldQuinaryEnabled; settings->imaginaryUnit = oldImaginaryUnit; settings->numberFormatStyle = oldNumberFormatStyle; settings->applyNumberFormatStyle(); } void test_extra_result_lines_profile_formatting() { Settings* settings = Settings::instance(); const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; const bool oldSecondaryResultEnabled = settings->secondaryResultEnabled; const bool oldTertiaryResultEnabled = settings->tertiaryResultEnabled; const bool oldQuaternaryResultEnabled = settings->quaternaryResultEnabled; const bool oldQuinaryResultEnabled = settings->quinaryResultEnabled; const char oldAlternativeResultFormat = settings->alternativeResultFormat; const char oldTertiaryResultFormat = settings->tertiaryResultFormat; const char oldQuaternaryResultFormat = settings->quaternaryResultFormat; const char oldQuinaryResultFormat = settings->quinaryResultFormat; const int oldSecondaryResultPrecision = settings->secondaryResultPrecision; const int oldTertiaryResultPrecision = settings->tertiaryResultPrecision; const int oldQuaternaryResultPrecision = settings->quaternaryResultPrecision; const int oldQuinaryResultPrecision = settings->quinaryResultPrecision; const bool oldComplexNumbers = settings->complexNumbers; const bool oldSecondaryComplexNumbers = settings->secondaryComplexNumbers; const bool oldTertiaryComplexNumbers = settings->tertiaryComplexNumbers; const bool oldQuaternaryComplexNumbers = settings->quaternaryComplexNumbers; const bool oldQuinaryComplexNumbers = settings->quinaryComplexNumbers; const char oldSecondaryResultComplexForm = settings->secondaryResultComplexForm; const char oldTertiaryResultComplexForm = settings->tertiaryResultComplexForm; const char oldQuaternaryResultComplexForm = settings->quaternaryResultComplexForm; const char oldQuinaryResultComplexForm = settings->quinaryResultComplexForm; const char oldImaginaryUnit = settings->imaginaryUnit; const Settings::NumberFormatStyle oldNumberFormatStyle = settings->numberFormatStyle; settings->numberFormatStyle = Settings::NumberFormatNoGroupingDot; settings->applyNumberFormatStyle(); settings->multipleResultLinesEnabled = true; settings->secondaryResultEnabled = true; settings->tertiaryResultEnabled = true; settings->quaternaryResultEnabled = true; settings->quinaryResultEnabled = true; settings->alternativeResultFormat = 'f'; settings->tertiaryResultFormat = 'e'; settings->quaternaryResultFormat = 'b'; settings->quinaryResultFormat = 'r'; settings->secondaryResultPrecision = 2; settings->tertiaryResultPrecision = 4; settings->quaternaryResultPrecision = -1; settings->quinaryResultPrecision = -1; settings->complexNumbers = true; settings->secondaryComplexNumbers = true; settings->tertiaryComplexNumbers = true; settings->quaternaryComplexNumbers = true; settings->quinaryComplexNumbers = true; settings->secondaryResultComplexForm = ComplexForm::Rectangular; settings->tertiaryResultComplexForm = ComplexForm::Exponential; settings->quaternaryResultComplexForm = ComplexForm::Phasor; settings->quinaryResultComplexForm = ComplexForm::Rectangular; settings->imaginaryUnit = 'j'; CMath::setImaginaryUnitSymbol(QLatin1Char('j')); DMath::complexMode = true; eval->initializeBuiltInVariables(); auto checkCondition = [](const char* file, int line, const char* label, bool condition, const QString& result, const QString& expectedHint) { ++eval_total_tests; if (!condition) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << file << "[" << line << "]\t" << label << "\t[NEW]" << endl << "\tResult : " << result.toUtf8().constData() << endl << "\tExpected : " << expectedHint.toUtf8().constData() << endl; } }; eval->setExpression(QStringLiteral("1234.56789")); const Quantity realValue = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_total_tests; ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\treal value eval for extra line profiles\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString line2 = NumberFormatter::format(realValue, settings->alternativeResultFormat, settings->secondaryResultPrecision, settings->complexNumbers && settings->secondaryComplexNumbers, settings->secondaryResultComplexForm); const QString line3 = NumberFormatter::format(realValue, settings->tertiaryResultFormat, settings->tertiaryResultPrecision, settings->complexNumbers && settings->tertiaryComplexNumbers, settings->tertiaryResultComplexForm); const QString line4 = NumberFormatter::format(realValue, settings->quaternaryResultFormat, settings->quaternaryResultPrecision, settings->complexNumbers && settings->quaternaryComplexNumbers, settings->quaternaryResultComplexForm); const QString line5 = NumberFormatter::format(realValue, settings->quinaryResultFormat, settings->quinaryResultPrecision, settings->complexNumbers && settings->quinaryComplexNumbers, settings->quinaryResultComplexForm); checkCondition(__FILE__, __LINE__, "line2 fixed precision", line2 == QStringLiteral("1234.57"), line2, QStringLiteral("1234.57")); checkCondition(__FILE__, __LINE__, "line3 scientific notation", line3.contains(QLatin1Char('e')), line3, QStringLiteral("contains 'e'")); checkCondition(__FILE__, __LINE__, "line4 binary notation", line4.startsWith(QStringLiteral("0b")), line4, QStringLiteral("starts with 0b")); checkCondition(__FILE__, __LINE__, "line5 rational notation", line5.contains(QLatin1Char('/')), line5, QStringLiteral("contains '/'")); } eval->setExpression(QStringLiteral("1+1j")); const Quantity complexValue = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_total_tests; ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcomplex value eval for extra line profiles\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString cartesian = NumberFormatter::format(complexValue, 'f', 3, true, ComplexForm::Rectangular); const QString polarExp = NumberFormatter::format(complexValue, 'f', 3, true, ComplexForm::Exponential); const QString trigonometric = NumberFormatter::format(complexValue, 'f', 3, true, ComplexForm::Trigonometric); const QString cis = NumberFormatter::format(complexValue, 'f', 3, true, ComplexForm::Cis); const QString polarAngle = NumberFormatter::format(complexValue, 'f', 3, true, ComplexForm::Phasor); checkCondition(__FILE__, __LINE__, "rectangular complex form", cartesian.contains(QLatin1Char('j')), cartesian, QStringLiteral("contains imaginary unit j")); checkCondition(__FILE__, __LINE__, "exponential complex form", polarExp.contains(QStringLiteral("exp(")), polarExp, QStringLiteral("contains exp(")); checkCondition(__FILE__, __LINE__, "trigonometric complex form", trigonometric.contains(QStringLiteral("cos(")) && trigonometric.contains(QStringLiteral("sin(")), trigonometric, QStringLiteral("contains cos( and sin(")); checkCondition(__FILE__, __LINE__, "cis complex form", cis.contains(QStringLiteral("cis(")), cis, QStringLiteral("contains cis(")); checkCondition(__FILE__, __LINE__, "phasor complex form", polarAngle.contains(QString::fromUtf8("∠")), polarAngle, QString::fromUtf8("contains ∠")); } settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; settings->secondaryResultEnabled = oldSecondaryResultEnabled; settings->tertiaryResultEnabled = oldTertiaryResultEnabled; settings->quaternaryResultEnabled = oldQuaternaryResultEnabled; settings->quinaryResultEnabled = oldQuinaryResultEnabled; settings->alternativeResultFormat = oldAlternativeResultFormat; settings->tertiaryResultFormat = oldTertiaryResultFormat; settings->quaternaryResultFormat = oldQuaternaryResultFormat; settings->quinaryResultFormat = oldQuinaryResultFormat; settings->secondaryResultPrecision = oldSecondaryResultPrecision; settings->tertiaryResultPrecision = oldTertiaryResultPrecision; settings->quaternaryResultPrecision = oldQuaternaryResultPrecision; settings->quinaryResultPrecision = oldQuinaryResultPrecision; settings->complexNumbers = oldComplexNumbers; settings->secondaryComplexNumbers = oldSecondaryComplexNumbers; settings->tertiaryComplexNumbers = oldTertiaryComplexNumbers; settings->quaternaryComplexNumbers = oldQuaternaryComplexNumbers; settings->quinaryComplexNumbers = oldQuinaryComplexNumbers; settings->secondaryResultComplexForm = oldSecondaryResultComplexForm; settings->tertiaryResultComplexForm = oldTertiaryResultComplexForm; settings->quaternaryResultComplexForm = oldQuaternaryResultComplexForm; settings->quinaryResultComplexForm = oldQuinaryResultComplexForm; settings->imaginaryUnit = oldImaginaryUnit; CMath::setImaginaryUnitSymbol(QChar(oldImaginaryUnit)); DMath::complexMode = oldComplexNumbers; eval->initializeBuiltInVariables(); settings->numberFormatStyle = oldNumberFormatStyle; settings->applyNumberFormatStyle(); } void test_sexagesimal() { // Backup current settings Settings* settings = Settings::instance(); char angleUnit = settings->angleUnit; char resultFormat = settings->resultFormat; int resultPrecision = settings->resultPrecision; settings->angleUnit = 'd'; settings->resultFormat = 's'; settings->resultPrecision = 2; Evaluator::instance()->initializeAngleUnits(); // Coverage for the documentation tables in doc/src/userguide/syntax.rst // ("Sexagesimal Values"): fixed-point decimal and sexagesimal columns. CHECK_EVAL("0", "0"); CHECK_EVAL("°'56", "0.01555555555555555556°"); CHECK_EVAL("56\"", "0.01555555555555555556°"); CHECK_EVAL("56[arcsecond]", "0.01555555555555555556°"); CHECK_EVAL("56[arcsec]", "0.01555555555555555556°"); CHECK_EVAL("56[mas]", "0.00001555555555555556°"); CHECK_EVAL("56[milliarcsecond]", "0.00001555555555555556°"); CHECK_EVAL(QString::fromUtf8("56[µas]"), "0.00000001555555555556°"); CHECK_EVAL("56[microarcsecond]", "0.00000001555555555556°"); CHECK_EVAL("[mas] -> [milliarcsecond]", "1 milliarcsecond"); CHECK_EVAL(QString::fromUtf8("[µas] -> [microarcsecond]"), "1 microarcsecond"); CHECK_EVAL("[uas] -> [microarcsecond]", "1 microarcsecond"); CHECK_EVAL("[milliarcsecond] -> [mas]", "1 mas"); CHECK_EVAL("[microarcsecond] -> [uas]", "1 uas"); CHECK_EVAL("1[mas] -> [arcsecond]", "0.001 arcsecond"); CHECK_EVAL("1[mas] -> [arcsec]", "0.001 arcsec"); CHECK_EVAL("1000[mas] -> [arcsecond]", "1 arcsecond"); CHECK_EVAL("1000[milliarcsecond] -> [arcsec]", "1 arcsec"); CHECK_EVAL(QString::fromUtf8("1[µas] -> [arcsecond]"), "0.000001 arcsecond"); CHECK_EVAL("1[uas] -> [arcsec]", "0.000001 arcsec"); CHECK_EVAL("1000000[uas] -> [arcsecond]", "1 arcsecond"); CHECK_EVAL("1000000[microarcsecond] -> [arcsec]", "1 arcsec"); CHECK_EVAL("1[arcsecond] -> [mas]", "1000 mas"); CHECK_EVAL("1[arcsec] -> [milliarcsecond]", "1000 milliarcsecond"); CHECK_EVAL(QString::fromUtf8("1[arcsecond] -> [µas]"), "1000000 µas"); CHECK_EVAL("1[arcsec] -> [uas]", "1000000 uas"); CHECK_EVAL("1[arcminute] -> [mas]", "60000 mas"); CHECK_EVAL("1[arcmin] -> [milliarcsecond]", "60000 milliarcsecond"); CHECK_EVAL(QString::fromUtf8("1[arcminute] -> [µas]"), "60000000 µas"); CHECK_EVAL("1[arcmin] -> [uas]", "60000000 uas"); CHECK_EVAL("60000[mas] -> [arcmin]", "1 arcmin"); CHECK_EVAL("60000[milliarcsecond] -> [arcminute]", "1 arcminute"); CHECK_EVAL(QString::fromUtf8("60000000[µas] -> [arcmin]"), "1 arcmin"); CHECK_EVAL("60000000[uas] -> [arcminute]", "1 arcminute"); CHECK_EVAL("3600000[mas] -> [degree]", "1°"); CHECK_EVAL("3600000000[uas] -> [degree]", "1°"); CHECK_EVAL("((123456789[mas] -> [arcsec]) -> [mas])", "123456789 mas"); CHECK_EVAL("((123456789[milliarcsecond] -> [arcsecond]) -> [milliarcsecond])", "123456789 milliarcsecond"); CHECK_EVAL(QString::fromUtf8("((123456789[µas] -> [arcsec]) -> [µas])"), "123456789 µas"); CHECK_EVAL("((123456789[uas] -> [arcsecond]) -> [uas])", "123456789 uas"); CHECK_EVAL("56.78\"", "0.01577222222222222222°"); CHECK_EVAL("8.4381406e4\"", "23.43927944444444444444°"); CHECK_EVAL(QString::fromUtf8("8.4381406e4″"), "23.43927944444444444444°"); CHECK_EVAL(QString::fromUtf8("8.4381406e4 ″"), "23.43927944444444444444°"); CHECK_EVAL("°34", "0.56666666666666666667°"); CHECK_EVAL("34'", "0.56666666666666666667°"); CHECK_EVAL(QString::fromUtf8("34′"), "0.56666666666666666667°"); CHECK_EVAL("34[arcminute]", "0.56666666666666666667°"); CHECK_EVAL("34[arcmin]", "0.56666666666666666667°"); CHECK_EVAL("34'56", "0.58222222222222222222°"); CHECK_EVAL(QString::fromUtf8("34′56″"), "0.58222222222222222222°"); CHECK_EVAL("12°", "12°"); CHECK_EVAL("12°34", "12.56666666666666666667°"); CHECK_EVAL("12°34.5", "12.575°"); CHECK_EVAL("12°34'56", "12.58222222222222222222°"); CHECK_EVAL("12°34'56.78", "12.58243888888888888889°"); CHECK_EVAL("0[second]", "0 second"); CHECK_EVAL("::56", "56 second"); CHECK_EVAL("56[second]", "56 second"); CHECK_EVAL(":34", "2040 second"); CHECK_EVAL("34[minute]", "2040 second"); CHECK_EVAL("12:", "43200 second"); CHECK_EVAL("12[hour]", "43200 second"); CHECK_EVAL("12:34", "45240 second"); CHECK_EVAL("12:34.5", "45270 second"); CHECK_EVAL("12:34:56", "45296 second"); CHECK_EVAL("12:34:56.78", "45296.78 second"); CHECK_EVAL_FORMAT("0", "0°00′00″"); CHECK_EVAL_FORMAT("°'56", "0°00′56.00″"); CHECK_EVAL_FORMAT("56\"", "0°00′56.00″"); CHECK_EVAL_FORMAT("56[arcsecond]", "0°00′56.00″"); CHECK_EVAL_FORMAT("56.78\"", "0°00′56.78″"); CHECK_EVAL_FORMAT("°34", "0°34′00.00″"); CHECK_EVAL_FORMAT("34'", "0°34′00.00″"); CHECK_EVAL_FORMAT("34[arcminute]", "0°34′00.00″"); CHECK_EVAL_FORMAT("34'56", "0°34′56.00″"); CHECK_EVAL_FORMAT("12°", "12°00′00.00″"); CHECK_EVAL_FORMAT("12°34", "12°34′00.00″"); CHECK_EVAL_FORMAT("12°34.5", "12°34′30.00″"); CHECK_EVAL_FORMAT("12°34'56", "12°34′56.00″"); CHECK_EVAL_FORMAT("12°34'56.78", "12°34′56.78″"); CHECK_EVAL_FORMAT("0[second]", "0:00:00"); CHECK_EVAL_FORMAT("::56", "0:00:56.00"); CHECK_EVAL_FORMAT("56[second]", "0:00:56.00"); CHECK_EVAL_FORMAT(":34", "0:34:00.00"); CHECK_EVAL_FORMAT("34[minute]", "0:34:00.00"); CHECK_EVAL_FORMAT("12:", "12:00:00.00"); CHECK_EVAL_FORMAT("12[hour]", "12:00:00.00"); CHECK_EVAL_FORMAT("12:34", "12:34:00.00"); CHECK_EVAL_FORMAT("12:34.5", "12:34:30.00"); CHECK_EVAL_FORMAT("12:34:56", "12:34:56.00"); CHECK_EVAL_FORMAT("12:34:56.78", "12:34:56.78"); CHECK_EVAL_FORMAT_FAIL(":"); CHECK_EVAL_FORMAT_FAIL("::"); CHECK_EVAL_FORMAT_FAIL("0:::"); CHECK_EVAL_FORMAT_FAIL("1.2:34.56"); CHECK_EVAL_FORMAT_FAIL("12:3.4:56.78"); CHECK_EVAL_FORMAT("0:", "0:00:00"); CHECK_EVAL_FORMAT("::56", "0:00:56.00"); CHECK_EVAL_FORMAT("56[second]", "0:00:56.00"); CHECK_EVAL_FORMAT(":34", "0:34:00.00"); CHECK_EVAL_FORMAT(":34:", "0:34:00.00"); CHECK_EVAL_FORMAT(":34.5:", "0:34:30.00"); CHECK_EVAL_FORMAT("34.5[minute]", "0:34:30.00"); CHECK_EVAL_FORMAT("12:", "12:00:00.00"); CHECK_EVAL_FORMAT("12::", "12:00:00.00"); CHECK_EVAL_FORMAT("12.3:", "12:18:00.00"); CHECK_EVAL_FORMAT("12.3[hour]", "12:18:00.00"); CHECK_EVAL_FORMAT("12:34", "12:34:00.00"); CHECK_EVAL_FORMAT("12:34:", "12:34:00.00"); CHECK_EVAL_FORMAT("12:34.", "12:34:00.00"); CHECK_EVAL_FORMAT("12:34.5", "12:34:30.00"); CHECK_EVAL_FORMAT("12:34:56", "12:34:56.00"); CHECK_EVAL_FORMAT("12:34:56.", "12:34:56.00"); CHECK_EVAL_FORMAT("12:34:56.78", "12:34:56.78"); CHECK_EVAL("1:30 / 4:00", "0.375"); CHECK_EVAL("(1:30) / (4:00)", "0.375"); CHECK_EVAL_FORMAT("-0:", "0:00:00"); CHECK_EVAL_FORMAT("-::56", "-0:00:56.00"); CHECK_EVAL_FORMAT("-:34", "-0:34:00.00"); CHECK_EVAL_FORMAT("-12:", "-12:00:00.00"); CHECK_EVAL_FORMAT("-12:34", "-12:34:00.00"); CHECK_EVAL_FORMAT("-12:34.5", "-12:34:30.00"); CHECK_EVAL_FORMAT("-12:34:56", "-12:34:56.00"); CHECK_EVAL_FORMAT("-12:34:56.78", "-12:34:56.78"); CHECK_EVAL_FORMAT_FAIL("°"); CHECK_EVAL_FORMAT_FAIL("°'"); CHECK_EVAL_FORMAT_FAIL("°0\""); CHECK_EVAL_FORMAT_FAIL("1.2°34.56"); CHECK_EVAL_FORMAT_FAIL("12°3.4'56.78\""); CHECK_EVAL_FORMAT_FAIL("56\"7"); CHECK_EVAL_FORMAT_FAIL("56.78\"9"); CHECK_EVAL_FORMAT_FAIL("34'\"5"); CHECK_EVAL_FORMAT_FAIL("12°'\"3"); CHECK_EVAL_FORMAT_FAIL("12°34'56.78\"9"); CHECK_EVAL_FORMAT("0", "0°00′00″"); CHECK_EVAL_FORMAT("°'56", "0°00′56.00″"); CHECK_EVAL_FORMAT("'56", "0°00′56.00″"); CHECK_EVAL_FORMAT("56\"", "0°00′56.00″"); CHECK_EVAL_FORMAT("56[arcsecond]", "0°00′56.00″"); CHECK_EVAL_FORMAT("56.78\"", "0°00′56.78″"); CHECK_EVAL_FORMAT("°34", "0°34′00.00″"); CHECK_EVAL_FORMAT("34'", "0°34′00.00″"); CHECK_EVAL_FORMAT("34.5'", "0°34′30.00″"); CHECK_EVAL_FORMAT("34'\"", "0°34′00.00″"); CHECK_EVAL_FORMAT("34.5'\"", "0°34′30.00″"); CHECK_EVAL_FORMAT("34.5[arcminute]", "0°34′30.00″"); CHECK_EVAL_FORMAT("34'56", "0°34′56.00″"); eval->setExpression(QStringLiteral("34'56")); eval->evalUpdateAns(); ++eval_total_tests; if (eval->error().isEmpty() && eval->interpretedExpression().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsexagesimal interpreted expression is not empty\t[NEW]" << endl << "\tExpression: 34'56" << endl; } eval->setExpression(QString::fromUtf8("°34")); eval->evalUpdateAns(); ++eval_total_tests; if (eval->error().isEmpty() && eval->interpretedExpression().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsexagesimal interpreted expression is not empty\t[NEW]" << endl << "\tExpression: °34" << endl; } CHECK_EVAL_FORMAT("12°", "12°00′00.00″"); CHECK_EVAL_FORMAT(QString::fromUtf8("12º"), "12°00′00.00″"); CHECK_EVAL_FORMAT(QString::fromUtf8("12˚"), "12°00′00.00″"); CHECK_EVAL_FORMAT(QString::fromUtf8("12∘"), "12°00′00.00″"); CHECK_EVAL_FORMAT("12°'", "12°00′00.00″"); CHECK_EVAL_FORMAT("12°'\"", "12°00′00.00″"); CHECK_EVAL_FORMAT("12.3°", "12°18′00.00″"); CHECK_EVAL_FORMAT(QString::fromUtf8("12.3º"), "12°18′00.00″"); CHECK_EVAL_FORMAT("12.3°'", "12°18′00.00″"); CHECK_EVAL_FORMAT("12.3°'\"", "12°18′00.00″"); CHECK_EVAL_FORMAT("12°34", "12°34′00.00″"); CHECK_EVAL_FORMAT(QString::fromUtf8("12º34"), "12°34′00.00″"); CHECK_EVAL_FORMAT("12°34'", "12°34′00.00″"); CHECK_EVAL_FORMAT("12°34.", "12°34′00.00″"); CHECK_EVAL_FORMAT("12°34.5", "12°34′30.00″"); CHECK_EVAL_FORMAT("12°34.5'", "12°34′30.00″"); CHECK_EVAL_FORMAT("12°34'56", "12°34′56.00″"); CHECK_EVAL_FORMAT("12°34'56.", "12°34′56.00″"); CHECK_EVAL_FORMAT("12°34'56.78", "12°34′56.78″"); CHECK_EVAL_FORMAT("12°34'56.78\"", "12°34′56.78″"); CHECK_EVAL_FORMAT("-0", "0°00′00″"); CHECK_EVAL_FORMAT("-°'56", "-0°00′56.00″"); CHECK_EVAL_FORMAT("-56\"", "-0°00′56.00″"); CHECK_EVAL_FORMAT("-°34", "-0°34′00.00″"); CHECK_EVAL_FORMAT("-34'", "-0°34′00.00″"); CHECK_EVAL_FORMAT("-12°", "-12°00′00.00″"); CHECK_EVAL_FORMAT("-12.3°", "-12°18′00.00″"); CHECK_EVAL_FORMAT("-12°34", "-12°34′00.00″"); CHECK_EVAL_FORMAT("-12°34.5", "-12°34′30.00″"); CHECK_EVAL_FORMAT("-12°34'56", "-12°34′56.00″"); CHECK_EVAL_FORMAT("-12°34'56.78", "-12°34′56.78″"); CHECK_EVAL_FORMAT("-12°34'56.78\"", "-12°34′56.78″"); settings->angleUnit = 'g'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT("100.5", "90°27′00.00″"); CHECK_EVAL_FORMAT("-200.3", "-180°16′12.00″"); CHECK_EVAL_FORMAT("12°", "12°00′00.00″"); CHECK_EVAL_FORMAT("12.3[degree]", "12°18′00.00″"); settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT("pi", "180°00′00.00″"); CHECK_EVAL_FORMAT("-pi", "-180°00′00.00″"); CHECK_EVAL_FORMAT("2*pi [rad]", "360°00′00.00″"); CHECK_EVAL_FORMAT("12°", "12°00′00.00″"); CHECK_EVAL_FORMAT("12.3[degree]", "12°18′00.00″"); settings->angleUnit = 't'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT("0.25", "90°00′00.00″"); CHECK_EVAL_FORMAT("-0.5", "-180°00′00.00″"); CHECK_EVAL_FORMAT("12°", "12°00′00.00″"); CHECK_EVAL_FORMAT("12.3[degree]", "12°18′00.00″"); settings->resultPrecision = 32; CHECK_EVAL_FORMAT("::56.78901234567890123456789012345678", "0:00:56.78901234567890123456789012345678"); CHECK_EVAL_FORMAT(":34.56789012345678901234567890123456", "0:34:34.07340740740734074074073407407360"); CHECK_EVAL_FORMAT("12.34567890123456789012345678901234:", "12:20:44.44404444444440444444444044442400"); settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT("56.78901234567890123456789012345678\"", "0°00′56.78901234567890123456789012345678″"); CHECK_EVAL_FORMAT("34.56789012345678901234567890123456'", "0°34′34.07340740740734074074073407407360″"); CHECK_EVAL_FORMAT("12.34567890123456789012345678901234°", "12°20′44.44404444444440444444444044442400″"); // Round-trip drift checks: arcsec ⇄ DMS ⇄ radians and radians ⇄ arcsec. CHECK_EVAL( "((((12°34′56.7890123456″ -> [radian]) -> [arcsecond]) -> [radian]) - (12°34′56.7890123456″ -> [radian])) -> [radian]", "0 radian"); CHECK_EVAL( "((((1.234567890123456e-4[radian] -> [arcsecond]) -> [radian]) - (1.234567890123456e-4[radian])) -> [radian])", "0 radian"); // Restore old settings settings->angleUnit = angleUnit; settings->resultFormat = resultFormat; settings->resultPrecision = resultPrecision; Evaluator::instance()->initializeAngleUnits(); } void test_dms_function_formats_like_sexagesimal_notation() { Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; settings->angleUnit = 'd'; settings->resultFormat = 'g'; settings->resultPrecision = 2; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT("dms(62[s])", "0:01:02.00"); CHECK_EVAL_FORMAT("dms(12.3[degree])", "12°18′00.00″"); CHECK_EVAL_FORMAT("dms(0.25[turn])", "90°00′00.00″"); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; Evaluator::instance()->initializeAngleUnits(); } void test_rational_format() { Settings* settings = Settings::instance(); const char angleUnit = settings->angleUnit; const char resultFormat = settings->resultFormat; const int resultPrecision = settings->resultPrecision; const bool complexNumbers = settings->complexNumbers; const char imaginaryUnit = settings->imaginaryUnit; const char resultComplexForm = settings->resultComplexForm; const bool complexMode = DMath::complexMode; settings->resultFormat = 'r'; settings->resultPrecision = -1; settings->complexNumbers = false; DMath::complexMode = false; eval->initializeBuiltInVariables(); const QString dotOperator(MathDsl::MulDotOp); const QString dotSpacing = QString(MathDsl::MulDotWrapSp); const QString piSymbol = QStringLiteral("pi"); const auto piOver = [&](int denominator) { return piSymbol + slash + QString::number(denominator); }; const auto nPiOver = [&](int numerator, int denominator) { return QString::number(numerator) + dotSpacing + dotOperator + dotSpacing + piSymbol + slash + QString::number(denominator); }; const auto nPi = [&](int numerator) { return QString::number(numerator) + dotSpacing + dotOperator + dotSpacing + piSymbol; }; const auto signedPiOver = [&](int numerator, int denominator) -> QString { if (numerator == 1) return piOver(denominator); if (numerator == -1) return QStringLiteral("-") + piOver(denominator); return nPiOver(numerator, denominator); }; ++eval_total_tests; QString direct = NumberFormatter::format(Quantity(HNumber("0.5")), 'r'); direct.replace(QString::fromUtf8("−"), "-"); const QString expectedDirect = QStringLiteral("1") + slash + QStringLiteral("2"); if (direct != expectedDirect) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tdirect NumberFormatter rational formatting\t[NEW]" << endl << "\tResult : " << direct.toLatin1().constData() << endl << "\tExpected : " << expectedDirect.toLatin1().constData() << endl; } CHECK_EVAL_FORMAT_HAS_SLASH("1/3"); CHECK_EVAL_FORMAT_HAS_SLASH("2/4"); CHECK_EVAL_FORMAT_HAS_SLASH("-10/4"); CHECK_EVAL_FORMAT_MEDIUM_SPACED_SLASH("2/4"); CHECK_EVAL_FORMAT("0", "0"); CHECK_EVAL_FORMAT_HAS_SLASH("0.1"); CHECK_EVAL_FORMAT_HAS_SLASH("1000001/1000000"); CHECK_EVAL_FORMAT_HAS_SLASH("0.5[metre]"); CHECK_EVAL_FORMAT_HAS_SLASH("-0.5[metre]"); CHECK_EVAL_FORMAT_MEDIUM_SPACED_SLASH("0.5[metre]"); CHECK_EVAL_FORMAT_HAS_SLASH("1/1000000"); CHECK_EVAL_FORMAT_HAS_SLASH("355/113"); // Must fall back to float for denominator overflow / non-rational / huge numerator. CHECK_EVAL_FORMAT_NO_SLASH("1/1000001"); CHECK_EVAL_FORMAT_NO_SLASH("sqrt(2)"); CHECK_EVAL_FORMAT_NO_SLASH("0.333333333333333333333333333333"); CHECK_EVAL_FORMAT_NO_SLASH("3000000000"); CHECK_EVAL_FORMAT_NO_SLASH("exp(1)"); settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT_EXACT("arcsin(-1)", signedPiOver(-1, 2)); CHECK_EVAL_FORMAT_EXACT("arcsin(-sqrt(3)/2)", signedPiOver(-1, 3)); CHECK_EVAL_FORMAT_EXACT("arcsin(-sqrt(2)/2)", signedPiOver(-1, 4)); CHECK_EVAL_FORMAT_EXACT("arcsin(-1/2)", signedPiOver(-1, 6)); CHECK_EVAL_FORMAT_EXACT("arcsin(0)", "0"); CHECK_EVAL_FORMAT_EXACT("arcsin(1/2)", piOver(6)); CHECK_EVAL_FORMAT_EXACT("arcsin(sqrt(2)/2)", piOver(4)); CHECK_EVAL_FORMAT_EXACT("arcsin(sqrt(3)/2)", piOver(3)); CHECK_EVAL_FORMAT_EXACT("arcsin(1)", piOver(2)); CHECK_EVAL_FORMAT_EXACT("arccos(-1)", piSymbol); CHECK_EVAL_FORMAT_EXACT("arccos(-sqrt(3)/2)", nPiOver(5, 6)); CHECK_EVAL_FORMAT_EXACT("arccos(-sqrt(2)/2)", nPiOver(3, 4)); CHECK_EVAL_FORMAT_EXACT("arccos(-1/2)", nPiOver(2, 3)); CHECK_EVAL_FORMAT_EXACT("arccos(0)", piOver(2)); CHECK_EVAL_FORMAT_EXACT("arccos(1/2)", piOver(3)); CHECK_EVAL_FORMAT_EXACT("arccos(sqrt(2)/2)", piOver(4)); CHECK_EVAL_FORMAT_EXACT("arccos(sqrt(3)/2)", piOver(6)); CHECK_EVAL_FORMAT_EXACT("arccos(1)", "0"); CHECK_EVAL_FORMAT_EXACT("arctan(-sqrt(3))", signedPiOver(-1, 3)); CHECK_EVAL_FORMAT_EXACT("arctan(-1)", signedPiOver(-1, 4)); CHECK_EVAL_FORMAT_EXACT("arctan(-sqrt(3)/3)", signedPiOver(-1, 6)); CHECK_EVAL_FORMAT_EXACT("arctan(0)", "0"); CHECK_EVAL_FORMAT_EXACT("arctan(sqrt(3)/3)", piOver(6)); CHECK_EVAL_FORMAT_EXACT("arctan(1)", piOver(4)); CHECK_EVAL_FORMAT_EXACT("arctan(sqrt(3))", piOver(3)); CHECK_EVAL_FORMAT_NO_SLASH("sin(1)"); CHECK_EVAL_FORMAT_NO_SLASH("cos(1)"); CHECK_EVAL_FORMAT_NO_SLASH("tan(1)"); CHECK_EVAL_FORMAT_EXACT("arcsin(sqrt(3)/22)", "0.07881114207211010205"); CHECK_EVAL_FORMAT_NO_SLASH("arcsin(0.1)"); CHECK_EVAL_FORMAT_NO_SLASH("arccos(0.1)"); CHECK_EVAL_FORMAT_NO_SLASH("arctan(0.1)"); CHECK_EVAL_FORMAT_EXACT("sin(pi/4)", QStringLiteral("sqrt(2)") + slash + QStringLiteral("2")); CHECK_EVAL_FORMAT_EXACT("sin(pi/3)", QStringLiteral("sqrt(3)") + slash + QStringLiteral("2")); CHECK_EVAL_FORMAT_EXACT("cos(pi/6)", QStringLiteral("sqrt(3)") + slash + QStringLiteral("2")); CHECK_EVAL_FORMAT_EXACT("tan(pi/3)", QStringLiteral("sqrt(3)")); CHECK_EVAL_FORMAT_EXACT("tan(pi/6)", QStringLiteral("sqrt(3)") + slash + QStringLiteral("3")); settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT_EXACT("sin(45)", QStringLiteral("sqrt(2)") + slash + QStringLiteral("2")); CHECK_EVAL_FORMAT_EXACT("cos(30)", QStringLiteral("sqrt(3)") + slash + QStringLiteral("2")); CHECK_EVAL_FORMAT_EXACT("tan(60)", QStringLiteral("sqrt(3)")); CHECK_EVAL_FORMAT_EXACT("tan(30)", QStringLiteral("sqrt(3)") + slash + QStringLiteral("3")); CHECK_EVAL_FORMAT_EXACT("radians(0)", "0"); CHECK_EVAL_FORMAT_EXACT("radians(30)", piOver(6)); CHECK_EVAL_FORMAT_EXACT("radians(45)", piOver(4)); CHECK_EVAL_FORMAT_EXACT("radians(60)", piOver(3)); CHECK_EVAL_FORMAT_EXACT("radians(90)", piOver(2)); CHECK_EVAL_FORMAT_EXACT("radians(120)", nPiOver(2, 3)); CHECK_EVAL_FORMAT_EXACT("radians(135)", nPiOver(3, 4)); CHECK_EVAL_FORMAT_EXACT("radians(150)", nPiOver(5, 6)); CHECK_EVAL_FORMAT_EXACT("radians(180)", piSymbol); CHECK_EVAL_FORMAT_EXACT("radians(210)", nPiOver(7, 6)); CHECK_EVAL_FORMAT_EXACT("radians(225)", nPiOver(5, 4)); CHECK_EVAL_FORMAT_EXACT("radians(240)", nPiOver(4, 3)); CHECK_EVAL_FORMAT_EXACT("radians(270)", nPiOver(3, 2)); CHECK_EVAL_FORMAT_EXACT("radians(300)", nPiOver(5, 3)); CHECK_EVAL_FORMAT_EXACT("radians(315)", nPiOver(7, 4)); CHECK_EVAL_FORMAT_EXACT("radians(330)", nPiOver(11, 6)); CHECK_EVAL_FORMAT_EXACT("radians(360)", nPi(2)); settings->complexNumbers = true; settings->imaginaryUnit = 'i'; CMath::setImaginaryUnitSymbol(QLatin1Char('i')); settings->resultComplexForm = ComplexForm::Rectangular; DMath::complexMode = true; eval->initializeBuiltInVariables(); CHECK_EVAL_FORMAT("1+i", "1+1i"); CHECK_EVAL_FORMAT_NO_SLASH("1+i"); settings->imaginaryUnit = 'j'; CMath::setImaginaryUnitSymbol(QLatin1Char('j')); eval->initializeBuiltInVariables(); CHECK_EVAL_FORMAT("1+j", "1+1j"); CHECK_EVAL_FORMAT_NO_SLASH("1+j"); // Explicit non-decimal format should still take precedence. CHECK_EVAL_FORMAT("hex(31)", "0x1F"); settings->angleUnit = angleUnit; settings->resultFormat = resultFormat; settings->resultPrecision = resultPrecision; settings->complexNumbers = complexNumbers; settings->imaginaryUnit = imaginaryUnit; CMath::setImaginaryUnitSymbol(QChar(imaginaryUnit)); settings->resultComplexForm = resultComplexForm; DMath::complexMode = complexMode; eval->initializeBuiltInVariables(); Evaluator::instance()->initializeAngleUnits(); } void test_function_root() { Settings* settings = Settings::instance(); const bool oldComplexNumbers = settings->complexNumbers; const bool oldComplexMode = DMath::complexMode; for (const bool complex : {false, true}) { settings->complexNumbers = complex; DMath::complexMode = complex; eval->initializeBuiltInVariables(); CHECK_EVAL("root(5; 32)", "2"); CHECK_EVAL("root(32; 1)", "1"); CHECK_EVAL("ROOT(4; 81)", "3"); CHECK_EVAL("root(5; -32)", "-2"); CHECK_EVAL("root(7; -128)", "-2"); CHECK_EVAL("root(5; 0.00032)", "0.2"); CHECK_EVAL("root(5; -0.00032)", "-0.2"); CHECK_EVAL("root(5; 0)", "0"); CHECK_EVAL("root(2; 0)", "0"); CHECK_EVAL("root(1; -32)", "-32"); CHECK_EVAL("root(2; 81)", "9"); CHECK_EVAL("root(3; -27)", "-3"); CHECK_EVAL("root(2147483648; 1)", "1"); CHECK_EVAL("root(2147483649; -1)", "-1"); CHECK_EVAL("root(5; 32 [m^5])/(2 [m])", "1"); CHECK_EVAL("root(5; -32 [m^5])/(-2 [m])", "1"); CHECK_EVAL("root(4; 81 [m^4])/(3 [m])", "1"); CHECK_EVAL("root(2; 4 [m^2])/(2 [m])", "1"); CHECK_EVAL("root(3; -27 [m^3])/(-3 [m])", "1"); CHECK_EVAL("root(1; 7 [cm])/(7 [cm])", "1"); CHECK_EVAL("root(5; 32 [cm^5])/(2 [cm])", "1"); CHECK_EVAL("root(5; 32 [m^5/s^5])/(2 [m/s])", "1"); CHECK_EVAL("root(5; 2)^5", "2"); // The first argument is always the index, even for the old argument order. CHECK_EVAL_FAIL("root(-32; 5)"); CHECK_EVAL_FAIL("root(32)"); CHECK_EVAL_FAIL("root(5; 32; 1)"); CHECK_EVAL_FAIL("root(0; 32)"); CHECK_EVAL_FAIL("root(-5; 32)"); CHECK_EVAL_FAIL("root(2.5; 32)"); CHECK_EVAL_FAIL("root(5 [m]; 32)"); CHECK_EVAL_FAIL("root(2147483648; 1 [m])"); CHECK_EVAL_FAIL("root(5; {1; 32})"); CHECK_EVAL_FAIL("root({1; 5}; 32)"); if (complex) { CHECK_EVAL("root(2; -16)", "4i"); CHECK_EVAL("root(2; -1)", "1i"); CHECK_EVAL("root(2; -81)", "9i"); CHECK_EVAL("root(2; -0.25)", "0.5i"); CHECK_EVAL("root(4; -1)", "0.7071067811865475244+0.7071067811865475244i"); CHECK_EVAL("root(6; -64)", "1.73205080756887729353+1i"); CHECK_EVAL("root(8; -256)", "1.84775906502257351226+0.76536686473017954346i"); CHECK_EVAL("root(2; 3+4i)", "2+1i"); CHECK_EVAL("root(2; 3-4i)", "2-1i"); CHECK_EVAL("root(2; -3+4i)", "1+2i"); CHECK_EVAL("root(2; -3-4i)", "1-2i"); CHECK_EVAL("root(3; -8i)", "1.73205080756887729353-1i"); CHECK_EVAL("root(4; 16i)", "1.84775906502257351226+0.76536686473017954346i"); CHECK_EVAL("root(4; -16i)", "1.84775906502257351226-0.76536686473017954346i"); CHECK_EVAL("root(5; 32i)", "1.90211303259030714423+0.6180339887498948482i"); CHECK_EVAL("root(2; -16 [m^2])", "4i metre"); CHECK_EVAL("root(2; (3+4i) [m^2])", "(2+1i) metre"); CHECK_EVAL("root(2; -1)+root(2; -81)", "10i"); CHECK_EVAL("2*root(2; -16)", "8i"); CHECK_EVAL("root(4; -16)", "1.4142135623730950488+1.4142135623730950488i"); CHECK_EVAL("root(3; 8i)", "1.73205080756887729353+1i"); CHECK_EVAL("root(5; 1+i)^5", "1+1i"); CHECK_EVAL("phase(root(5; 1+i))*5/phase(1+i)", "1"); CHECK_EVAL("root(1; 1+i)", "1+1i"); CHECK_EVAL("root(4; -16 [m^4])/(root(4; -16)*1 [m])", "1"); CHECK_EVAL_FAIL("root(i; 32)"); CHECK_EVAL_FAIL("root(5+i; 32)"); } else { CHECK_EVAL_FAIL("root(2; -16)"); CHECK_EVAL_FAIL("root(4; -16)"); } } settings->complexNumbers = oldComplexNumbers; DMath::complexMode = oldComplexMode; eval->initializeBuiltInVariables(); } void test_function_basic() { CHECK_EVAL("ABS(0)", "0"); CHECK_EVAL("ABS(1)", "1"); CHECK_EVAL("ABS(-1)", "1"); CHECK_EVAL("ABS(--1)", "1"); CHECK_EVAL("ABS(---1)", "1"); CHECK_EVAL("ABS((1))", "1"); CHECK_EVAL("ABS((-1))", "1"); CHECK_EVAL("ABS(1/2)", "0.5"); CHECK_EVAL("ABS(-1/2)", "0.5"); CHECK_EVAL("ABS(-1/-2)", "0.5"); CHECK_EVAL("ABS(1/-2)", "0.5"); CHECK_EVAL("INT(0)", "0"); CHECK_EVAL("INT(1)", "1"); CHECK_EVAL("INT(-1)", "-1"); CHECK_EVAL("INT(0.5)", "0"); CHECK_EVAL("INT(-0.75)", "0"); CHECK_EVAL("INT(-0.9999*1)", "0"); CHECK_EVAL("INT(0.9999*1)", "0"); CHECK_EVAL("INT(2.1)", "2"); CHECK_EVAL("INT(-3.4)", "-3"); CHECK_EVAL("log(0.123; 0.1234)", "0.99845065797473594741"); CHECK_EVAL("log10(0.00000000001)", "-11"); CHECK_EVAL("log10(1e-3)", "-3"); CHECK_EVAL("log2(0.00000000001)", "-36.54120904376098582657"); CHECK_EVAL("log2(32)", "5"); CHECK_EVAL("ln(100)", "4.60517018598809136804"); CHECK_EVAL("ln(4.0)", "1.38629436111989061883"); CHECK_EVAL("0!", "1"); CHECK_EVAL("1!", "1"); CHECK_EVAL("2!", "2"); CHECK_EVAL("3!", "6"); CHECK_EVAL("4!", "24"); CHECK_EVAL("5!", "120"); CHECK_EVAL("6!", "720"); CHECK_EVAL("7!", "5040"); CHECK_EVAL("(1+1)!^2", "4"); CHECK_EVAL("(-27)^(1/3)", "-3"); CHECK_EVAL("(-27)^(-1/3)", "-0.33333333333333333333"); CHECK_EVAL("(-1)^(1/3)", "-1"); CHECK_EVAL("(-1)^(1/7)", "-1"); CHECK_EVAL("(-1)^(2/3)", "1"); CHECK_EVAL("(-1)^(1/2)", "NaN"); CHECK_EVAL_PRECISE("exp((1)/2) + exp((1)/2)", "3.29744254140025629369730157562832714330755220142030"); CHECK_EVAL("√(81)", "9"); CHECK_EVAL("∛(-27)", "-3"); CHECK_INTERPRETED("sqrt(81)", "√(81)"); CHECK_INTERPRETED("cbrt(-27)", "∛(-27)"); CHECK_INTERPRETED("√(81)", "√(81)"); CHECK_INTERPRETED("∛(-27)", "∛(-27)"); // Test functions composition CHECK_EVAL("log(10;log(10;1e100))", "2"); CHECK_EVAL("log(10;abs(-100))", "2"); CHECK_EVAL("abs(log(10;100))", "2"); CHECK_EVAL("abs(abs(-100))", "100"); CHECK_EVAL("sum(10;abs(-100);1)", "111"); CHECK_EVAL("sum(abs(-100);10;1)", "111"); CHECK_EVAL("sum(10;1;abs(-100))", "111"); CHECK_EVAL("ieee754_half_decode(0x7E00)", "NaN"); CHECK_EVAL("hex(ieee754_half_encode(1))", "0x3C00"); CHECK_EVAL("hex(ieee754_half_encode(0.99951171875))", "0x3BFF"); CHECK_EVAL("hex(ieee754_half_encode(0.999755859375))", "0x3C00"); CHECK_EVAL("ieee754_round_half(0.999755859375)", "1"); CHECK_EVAL("ieee754_round_float(pi) - ieee754_single_decode(ieee754_single_encode(pi))", "0"); CHECK_EVAL("ieee754_round_double(pi) - ieee754_double_decode(ieee754_double_encode(pi))", "0"); CHECK_EVAL("ieee754_round_quad(pi) - ieee754_quad_decode(ieee754_quad_encode(pi))", "0"); CHECK_EVAL("ieee754_half_residual(0.999755859375) - (0.999755859375 - ieee754_round_half(0.999755859375))", "0"); CHECK_EVAL("ieee754_float_residual(pi) - (pi - ieee754_round_float(pi))", "0"); CHECK_EVAL("ieee754_double_residual(pi) - (pi - ieee754_round_double(pi))", "0"); CHECK_EVAL("ieee754_quad_residual(pi) - (pi - ieee754_round_quad(pi))", "0"); CHECK_EVAL("ieee754_double_residual(pi)", "0.00000000000000012246"); CHECK_EVAL("ieee754_double_residual(pi/2)", "0.00000000000000006123"); CHECK_EVAL("pi/2", "1.57079632679489661923"); CHECK_EVAL_PRECISE("ieee754_double_residual(pi/2)", "0.00000000000000006123233995736765886130329661375005"); CHECK_EVAL_PRECISE("ieee754_double_residual(ieee754_double_residual(pi/2))", "-0.00000000000000000000000000000000149738490485916978"); CHECK_EVAL_PRECISE("ieee754_double_residual(ieee754_double_residual(ieee754_double_residual(pi/2)))", "0.00000000000000000000000000000000000000000000000006"); CHECK_EVAL("molmass(H)", u8"1.008 g·mol�¹"); CHECK_EVAL("molmass(He)", u8"4.0026 g·mol�¹"); CHECK_EVAL("molmass(C6H12O6)", u8"180.156 g·mol�¹"); CHECK_EVAL(QString::fromUtf8("molmass(H₂O)"), u8"18.015 g·mol�¹"); CHECK_EVAL(QString::fromUtf8("molmass(NaCl)"), u8"58.44 g·mol�¹"); CHECK_EVAL(QString::fromUtf8("molmass(C₆H�₂O₆)"), u8"180.156 g·mol�¹"); CHECK_EVAL(QString::fromUtf8("molmass(Na₂SO₄)"), u8"142.036 g·mol�¹"); CHECK_EVAL("molmass(C6H12O6)*molmass(C6H12O6)", u8"32456.184336 g²·mol�²"); { ++eval_total_tests; const QString expr = QStringLiteral("molmass(C6H12O6)*molmass(C6H12O6)"); eval->setExpression(expr); const Quantity value = eval->evalNoAssign(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tmolmass product tooltip/result formatting eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QStringList lines = ResultLineFormatUtils::formatResultLinesForDisplay( expr, eval->interpretedExpression(), value, true, true, eval); const bool hasCompactSuperscript = lines.last().contains(QString::fromUtf8("g²·mol�²")); const bool hasCompactFraction = lines.last().contains(QString::fromUtf8("g²/mol²")); const bool hasInverseOnlySuperscript = lines.last().contains(QString::fromUtf8("1·mol�²")); const bool hasInverseOnlyFraction = lines.last().contains(QString::fromUtf8("1/mol²")); if (lines.isEmpty() || (!hasCompactSuperscript && !hasCompactFraction) || hasInverseOnlySuperscript || hasInverseOnlyFraction) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tmolmass product tooltip/result keeps gram numerator\t[NEW]" << endl << "\tResult line: " << (lines.isEmpty() ? "" : lines.last()).toUtf8().constData() << endl; } } } CHECK_EVAL_FAIL("molmass()"); CHECK_EVAL_FAIL("molmass(C6H12O6;H2O)"); CHECK_EVAL_FAIL("molmass(c6h12o6)"); CHECK_EVAL_FAIL("molmass(H0)"); CHECK_EVAL_FAIL("molmass(H2O1x)"); CHECK_EVAL_FAIL("molmass(Xx2)"); CHECK_EVAL_FAIL(QString::fromUtf8("molmass(K4[Fe(CN)6]·3H2O)")); CHECK_EVAL("mass(1;C6H12O6)", "180.156 g"); CHECK_EVAL("mass(2;H2O)", "36.03 g"); CHECK_EVAL(QString::fromUtf8("mass(0.5;H₂O)"), "9.0075 g"); CHECK_EVAL("mass(1;C6H12O6)-molmass(C6H12O6)*1[mol]", "0 g"); CHECK_EVAL_FAIL("mass()"); CHECK_EVAL_FAIL("mass(1)"); CHECK_EVAL_FAIL("mass(1;C6H12O6;H2O)"); CHECK_EVAL_FAIL("mass(1;c6h12o6)"); CHECK_EVAL_FAIL("mass(1;H0)"); CHECK_EVAL("molarity(0.50;1.00)", "0.5 mol/L"); CHECK_EVAL("molarity(1[mol];2[L])", "0.5 mol/L"); CHECK_EVAL("molarity(1;2[L])", "0.5 mol/L"); CHECK_EVAL("molarity(1[mol];2)", "0.5 mol/L"); CHECK_EVAL("molarity(3[mmol];2[mL])", "1.5 mol/L"); CHECK_EVAL("molarity(250[umol];500[mL])", "0.0005 mol/L"); CHECK_EVAL("molarity(0.75[mol];300[mL])", "2.5 mol/L"); CHECK_EVAL("molarity(3[mmol];2[mL])-molarity(0.003[mol];0.002[L])", "0 mol/L"); CHECK_EVAL("molarity(1[mol];2[L])-0.5[mol/L]", "0 mol/L"); CHECK_EVAL_FAIL("molarity()"); CHECK_EVAL_FAIL("molarity(1)"); CHECK_EVAL_FAIL("molarity(1;2;3)"); CHECK_EVAL_FAIL("molarity(1[g];1[L])"); CHECK_EVAL_FAIL("molarity(1[mol];1[s])"); } void test_function_trig() { CHECK_EVAL_PRECISE("pi", "3.14159265358979323846264338327950288419716939937511"); CHECK_EVAL("sin(0)", "0"); CHECK_EVAL("cos(0)", "1"); CHECK_EVAL("tan(0)", "0"); CHECK_EVAL("sin(pi)", "0"); CHECK_EVAL("cos(pi)", "-1"); CHECK_EVAL("tan(pi)", "0"); CHECK_EVAL("sin(-pi)", "0"); CHECK_EVAL("cos(-pi)", "-1"); CHECK_EVAL("tan(-pi)", "0"); CHECK_EVAL("sin(--pi)", "0"); CHECK_EVAL("cos(--pi)", "-1"); CHECK_EVAL("tan(--pi)", "0"); CHECK_EVAL("sin(pi/2)", "1"); CHECK_EVAL("cos(pi/2)", "0"); CHECK_EVAL("sin(-pi/2)", "-1"); CHECK_EVAL("cos(-pi/2)", "0"); CHECK_EVAL("sin(-pi/2) + sin(pi/2)", "0"); CHECK_EVAL("sin(-pi/2) - sin(pi/2)", "-2"); CHECK_EVAL("cos(-pi/2) + cos(pi/2)", "0"); CHECK_EVAL("cos(-pi/2) - cos(pi/2)", "0"); CHECK_EVAL("arcsin(sin(1))", "1"); CHECK_EVAL("arccos(cos(1))", "1"); CHECK_EVAL("arctan(tan(1))", "1"); CHECK_EVAL("arcsin(0)", "0"); CHECK_EVAL("arccos(1)", "0"); CHECK_EVAL("arctan(0)", "0"); CHECK_EVAL("degrees(0)", "0"); CHECK_EVAL("degrees(pi/2)", "90"); CHECK_EVAL("degrees(pi)", "180"); CHECK_EVAL("degrees(3*pi/2)", "270"); CHECK_EVAL("degrees(2*pi)", "360"); CHECK_EVAL("radians(0)", "0"); CHECK_EVAL("radians(90)/pi", "0.5"); CHECK_EVAL("radians(180)/pi", "1"); CHECK_EVAL("radians(270)/pi", "1.5"); CHECK_EVAL("radians(360)/pi", "2"); CHECK_EVAL("gradians(0)", "0"); CHECK_EVAL("gradians(pi/2)", "100"); CHECK_EVAL("gradians(pi)", "200"); CHECK_EVAL("gradians(3*pi/2)", "300"); CHECK_EVAL("gradians(2*pi)", "400"); CHECK_EVAL("turns(0)", "0"); CHECK_EVAL("turns(pi/2)", "0.25"); CHECK_EVAL("turns(pi)", "0.5"); CHECK_EVAL("turns(3*pi/2)", "0.75"); CHECK_EVAL("turns(2*pi)", "1"); } void test_function_tanh_range() { CHECK_EVAL("tanh(0)", "0"); CHECK_EVAL_PRECISE("tanh(58)", "0.99999999999999999999999999999999999999999999999999"); CHECK_EVAL_PRECISE("tanh(-58)", "-0.99999999999999999999999999999999999999999999999999"); CHECK_EVAL_PRECISE("tanh(59)", "1.00000000000000000000000000000000000000000000000000"); CHECK_EVAL_PRECISE("tanh(-59)", "-1.00000000000000000000000000000000000000000000000000"); // Straddle the old exp(2*x) and exp(x) intermediate range boundaries. const char* magnitudes[] = { "1e8", "618095478", "618095480", "1e9", "1236190956", "1236190958", "1e10", "1e100", "9.99999999999999999999e536870911" }; for (const char* magnitude : magnitudes) { CHECK_EVAL(QStringLiteral("tanh(%1)").arg(QLatin1String(magnitude)), "1"); CHECK_EVAL(QStringLiteral("tanh(-%1)").arg(QLatin1String(magnitude)), "-1"); } // Errors from genuinely unrepresentable results must still reach the user. CHECK_EVAL_FAIL("exp(1e10)"); CHECK_EVAL_FAIL("exp(-1e10)"); CHECK_EVAL_FAIL("sinh(1e10)"); CHECK_EVAL_FAIL("cosh(1e10)"); } void test_function_stat() { CHECK_EVAL_FAIL("MIN(0)"); CHECK_EVAL("MIN(0; 1)", "0"); CHECK_EVAL("MIN(0; 2)", "0"); CHECK_EVAL("MIN(-1; 0)", "-1"); CHECK_EVAL("MIN(-1; 1)", "-1"); CHECK_EVAL("MIN(-0.01; 0)", "-0.01"); CHECK_EVAL("MIN(0; 1; 2)", "0"); CHECK_EVAL("MIN(-1; 0; 1; 2)", "-1"); CHECK_EVAL("MIN(-2; -1; 0; 1; 2)", "-2"); CHECK_EVAL_FAIL("MAX(0)"); CHECK_EVAL("MAX(0; 1)", "1"); CHECK_EVAL("MAX(0; 2)", "2"); CHECK_EVAL("MAX(-1; 0)", "0"); CHECK_EVAL("MAX(-1; 1)", "1"); CHECK_EVAL("MAX(0.01; 0)", "0.01"); CHECK_EVAL("MAX(0; 1; 2)", "2"); CHECK_EVAL("MAX(-1; 0; 1; 2)", "2"); CHECK_EVAL("MAX(-2; -1; 0; 1; 2)", "2"); CHECK_EVAL_FAIL("SUM(1)"); CHECK_EVAL("SUM(100;1)", "101"); CHECK_EVAL("SUM(-100;1)", "-99"); CHECK_EVAL("SUM(0;0;0)", "0"); CHECK_EVAL("SUM(100;-1)", "99"); CHECK_EVAL("SUM(-100;-1)", "-101"); CHECK_EVAL("SUM(1;2;3;4;5;6)", "21"); CHECK_EVAL("SUM(1;-2;3;-4;5;-6)", "-3"); CHECK_EVAL_FAIL("SUMMATION(1;10)"); CHECK_EVAL_FAIL("SUMMATION(1;2;3;4)"); CHECK_EVAL_FAIL("SUMMATION(1.5;10;n)"); CHECK_EVAL_FAIL("SUMMATION(1[metre];10;n)"); CHECK_EVAL_FAIL("SUMMATION(1;10;n+unknown_var)"); CHECK_EVAL("SUMMATION(1;1;n)", "1"); CHECK_EVAL("SUMMATION(3;3;2+n)", "5"); CHECK_EVAL("SUMMATION(1;4;3)", "12"); CHECK_EVAL("SUMMATION(-2;2;n)", "0"); CHECK_EVAL("SUMMATION(1;10;2+n)", "75"); CHECK_EVAL("∑(1;10;2+n)", "75"); CHECK_EVAL("SUMMATION(10;1;n)", "55"); CHECK_EVAL("SUMMATION(-1;-4;n)", "-10"); CHECK_EVAL("SUMMATION(1;4;n^2)", "30"); CHECK_EVAL("SUMMATION(1;4;1/n)", "2.08333333333333333333"); CHECK_EVAL("SUMMATION(1;3;n[metre])", "NaN"); CHECK_EVAL("SUMMATION(1;3;n^2+n)", "20"); CHECK_INTERPRETED("summation(1;10;n+1)", "∑(1; 10; n+1)"); CHECK_EVAL_FAIL("sigma(1;10;n+1)"); CHECK_INTERPRETED("∑(1;10;n+1)", "∑(1; 10; n+1)"); CHECK_EVAL("SUMMATION(1;3;SUMMATION(1;2;1))", "6"); CHECK_EVAL_FAIL("SUMMATION(1;3;SUMMATION(1;n;1))"); CHECK_EVAL("f(k)=k^2", "NaN"); CHECK_EVAL_FAIL("SUMMATION(1;4;f(n))"); CHECK_EVAL("x=10", "10"); CHECK_EVAL("SUMMATION(1;3;n+x)", "36"); CHECK_EVAL("x", "10"); CHECK_EVAL("n=123", "123"); CHECK_EVAL("SUMMATION(1;3;n)", "6"); CHECK_EVAL("n", "123"); CHECK_EVAL_FAIL("PRODUCT(-1)"); CHECK_EVAL("PRODUCT(100;0)", "0"); CHECK_EVAL("PRODUCT(100;1)", "100"); CHECK_EVAL("PRODUCT(-100;1)", "-100"); CHECK_EVAL("PRODUCT(-100;-1)", "100"); CHECK_EVAL("PRODUCT(1;1;1)", "1"); CHECK_EVAL("PRODUCT(1;2;3;4;5;6)", "720"); CHECK_EVAL("PRODUCT(1;-2;3;-4;5;-6)", "-720"); CHECK_EVAL_FAIL("AVERAGE(0)"); CHECK_EVAL("AVERAGE(0;0)", "0"); CHECK_EVAL("AVERAGE(0;0;0)", "0"); CHECK_EVAL("AVERAGE(0;1)", "0.5"); CHECK_EVAL("AVERAGE(0;1;2)", "1"); CHECK_EVAL("AVERAGE(0;1;0)*3", "1"); CHECK_EVAL("AVERAGE(1;1;1)", "1"); CHECK_EVAL("AVERAGE(2;2;2)", "2"); CHECK_EVAL("AVERAGE(3;3;3)", "3"); CHECK_EVAL("AVERAGE(0.25;0.75)", "0.5"); CHECK_EVAL("AVERAGE(2.25;4.75)", "3.5"); CHECK_EVAL("AVERAGE(1/3;2/3)", "0.5"); CHECK_EVAL("123 + average(2;3;4;)", "126"); CHECK_EVAL_FAIL("GEOMEAN(-1e20;0;-1)"); CHECK_EVAL_FAIL("GEOMEAN(5)"); CHECK_EVAL("GEOMEAN(1;1)", "1"); CHECK_EVAL("GEOMEAN(1;4)", "2"); CHECK_EVAL("GEOMEAN(4;9)", "6"); CHECK_EVAL("GEOMEAN(3.6;8.1)", "5.4"); CHECK_EVAL("GEOMEAN(3;4;18)", "6"); CHECK_EVAL("GEOMEAN(1;1;1)", "1"); CHECK_EVAL("GEOMEAN(1;1;1;1)", "1"); CHECK_EVAL_FAIL("GEOMEAN(1;1;1;-1)"); CHECK_EVAL("VARP(1;-1)", "1"); CHECK_EVAL("VARS(1;-1)", "2"); CHECK_EVAL("VARP(5[metre]; 13[metre])", "16 metre²"); CHECK_EVAL("VARS(5[metre]; 13[metre])", "32 metre²"); CHECK_EVAL_FAIL("VARIANCE(1;-1)"); CHECK_EVAL_FAIL("VAR(1;-1)"); // for complex tests of VARP/VARS see test_complex CHECK_EVAL("int(rand())", "0"); CHECK_EVAL("rand(0)", "0"); CHECK_EVAL_FAIL("rand(1;2)"); CHECK_EVAL_FAIL("rand(-1)"); CHECK_EVAL_FAIL("rand(1.5)"); CHECK_EVAL_FAIL("rand(1[metre])"); CHECK_EVAL_FAIL("rand(1000)"); CHECK_EVAL("randint(0)", "0"); CHECK_EVAL("randint(5;5)", "5"); CHECK_EVAL("randint(-3;-3)", "-3"); CHECK_EVAL("int(randint(9)/10)", "0"); CHECK_EVAL("int(randint(-9)/10)", "0"); CHECK_EVAL("int(randint(3;1)/10)", "0"); CHECK_EVAL_FAIL("randint()"); CHECK_EVAL_FAIL("randint(1;2;3)"); CHECK_EVAL_FAIL("randint(1.5)"); CHECK_EVAL_FAIL("randint(1;2.5)"); CHECK_EVAL_FAIL("randint(1[metre])"); } void test_function_logic() { CHECK_EVAL_FAIL("and(1)"); CHECK_EVAL_FAIL("or(2)"); CHECK_EVAL_FAIL("xor(3)"); CHECK_EVAL_FAIL("popcount()"); CHECK_EVAL_FAIL("popcount(1;2)"); CHECK_EVAL_FAIL("popcount(1[metre])"); CHECK_EVAL_FAIL("popcount(2^300)"); CHECK_EVAL("and(0;0)", "0"); CHECK_EVAL("and(0;1)", "0"); CHECK_EVAL("and(1;0)", "0"); CHECK_EVAL("and(1;1)", "1"); CHECK_EVAL("or(0;0)", "0"); CHECK_EVAL("or(0;1)", "1"); CHECK_EVAL("or(1;0)", "1"); CHECK_EVAL("or(1;1)", "1"); CHECK_EVAL("xor(0;0)", "0"); CHECK_EVAL("xor(0;1)", "1"); CHECK_EVAL("xor(1;0)", "1"); CHECK_EVAL("xor(1;1)", "0"); CHECK_EVAL("popcount(0)", "0"); CHECK_EVAL("popcount(1)", "1"); CHECK_EVAL("popcount(2^254)", "1"); CHECK_EVAL("popcount(2^255-1)", "255"); CHECK_EVAL("popcount(-2^255)", "1"); CHECK_EVAL("popcount(15)", "4"); CHECK_EVAL("popcount(0xF0F0)", "8"); CHECK_EVAL("popcount(3.9)", "2"); CHECK_EVAL("popcount(-3.9)", "255"); CHECK_EVAL("popcount(0.9)", "0"); CHECK_EVAL("popcount(-0.9)", "256"); CHECK_EVAL("popcount(-1)", "256"); CHECK_EVAL("popcount(and(0x123456789ABCDEF0; not(0x123456789ABCDEF0)))", "0"); CHECK_EVAL("popcount(or(0x123456789ABCDEF0; not(0x123456789ABCDEF0)))", "256"); CHECK_EVAL("popcount(123456789) + popcount(not(123456789))", "256"); CHECK_EVAL("popcount(-123456789) + popcount(not(-123456789))", "256"); } void test_function_discrete() { CHECK_EVAL("idiv(10;3)", "3"); CHECK_EVAL("idiv(-10;3)", "-3"); CHECK_EVAL("idiv(10;-3)", "-3"); CHECK_EVAL("idiv(-10;-3)", "3"); CHECK_EVAL("mod(10;3)", "1"); CHECK_EVAL("mod(-10;3)", "-1"); CHECK_EVAL("mod(10;-3)", "1"); CHECK_EVAL("mod(-10;-3)", "-1"); CHECK_EVAL("emod(10;3)", "1"); CHECK_EVAL("emod(-10;3)", "2"); CHECK_EVAL("emod(10;-3)", "-2"); CHECK_EVAL("emod(-10;-3)", "-1"); CHECK_EVAL("emod(-1;360)", "359"); CHECK_EVAL("emod(360;360)", "0"); CHECK_EVAL("emod(361;360)", "1"); CHECK_EVAL("emod(-360;360)", "0"); CHECK_EVAL("emod(-361;360)", "359"); CHECK_EVAL("emod(721;360)", "1"); CHECK_EVAL("emod(-721;360)", "359"); CHECK_EVAL("emod(0;360)", "0"); CHECK_EVAL("emod(180;360)", "180"); CHECK_EVAL("emod(-180;360)", "180"); CHECK_EVAL("emod(1;-360)", "-359"); CHECK_EVAL("emod(359;-360)", "-1"); CHECK_EVAL("emod(360;-360)", "0"); CHECK_EVAL("emod(-1;-360)", "-1"); CHECK_EVAL("emod(-361;-360)", "-1"); CHECK_EVAL("emod(2.5;2)", "0.5"); CHECK_EVAL("emod(-2.5;2)", "1.5"); CHECK_EVAL("powmod(2;10;7)", "2"); CHECK_EVAL("powmod(3;233;353)", "248"); CHECK_EVAL("powmod(-3;233;353)", "105"); CHECK_EVAL("powmod(123456789;0;97)", "1"); CHECK_EVAL("powmod(123456789;1234567;1)", "0"); CHECK_EVAL("powmod(123456789;1234567;-97)", "-80"); CHECK_EVAL_FAIL("powmod(2;-1;5)"); CHECK_EVAL_FAIL("powmod(2;3.5;5)"); CHECK_EVAL_FAIL("powmod(2.5;3;5)"); CHECK_EVAL("gcd(12;18)", "6"); CHECK_EVAL("gcd(36;56;210)", "2"); CHECK_EVAL("gcd(28;120;126)", "2"); CHECK_EVAL("lcm(12;18)", "36"); CHECK_EVAL("lcm(36;56;210)", "2520"); CHECK_EVAL("lcm(0;5)", "0"); CHECK_EVAL("lcm(-9;27)", "27"); CHECK_EVAL("round(5.5e-10;2)", "0"); CHECK_EVAL("round(5.5*10^-10;2)", "0"); CHECK_EVAL("round(0.00000000055;2)", "0"); CHECK_EVAL("ncr(-3;-1)", "0"); CHECK_EVAL("ncr(-3;0)", "1"); CHECK_EVAL("ncr(-3;1)", "-3"); CHECK_EVAL("ncr(-3;2)", "6"); CHECK_EVAL("ncr(-3;3)", "-10"); CHECK_EVAL("ncr(-3;4)", "15"); CHECK_EVAL("ncr(-3;5)", "-21"); CHECK_EVAL("ncr(-2;-1)", "0"); CHECK_EVAL("ncr(-2;0)", "1"); CHECK_EVAL("ncr(-2;1)", "-2"); CHECK_EVAL("ncr(-2;2)", "3"); CHECK_EVAL("ncr(-2;3)", "-4"); CHECK_EVAL("ncr(-2;4)", "5"); CHECK_EVAL("ncr(-2;5)", "-6"); CHECK_EVAL("ncr(-1;-1)", "0"); CHECK_EVAL("ncr(-1;0)", "1"); CHECK_EVAL("ncr(-1;1)", "-1"); CHECK_EVAL("ncr(-1;2)", "1"); CHECK_EVAL("ncr(-1;3)", "-1"); CHECK_EVAL("ncr(-1;4)", "1"); CHECK_EVAL("ncr(-1;5)", "-1"); CHECK_EVAL("ncr(0;-1)", "0"); CHECK_EVAL("ncr(0;0)", "1"); CHECK_EVAL("ncr(0;1)", "0"); CHECK_EVAL("ncr(1;-1)", "0"); CHECK_EVAL("ncr(1;0)", "1"); CHECK_EVAL("ncr(1;1)", "1"); CHECK_EVAL("ncr(1;2)", "0"); CHECK_EVAL("ncr(2;-1)", "0"); CHECK_EVAL("ncr(2;0)", "1"); CHECK_EVAL("ncr(2;1)", "2"); CHECK_EVAL("ncr(2;2)", "1"); CHECK_EVAL("ncr(2;3)", "0"); CHECK_EVAL("ncr(3;-1)", "0"); CHECK_EVAL("ncr(3;0)", "1"); CHECK_EVAL("ncr(3;1)", "3"); CHECK_EVAL("ncr(3;2)", "3"); CHECK_EVAL("ncr(3;3)", "1"); CHECK_EVAL("ncr(3;4)", "0"); CHECK_EVAL("ncr(4;-1)", "0"); CHECK_EVAL("ncr(4;0)", "1"); CHECK_EVAL("ncr(4;1)", "4"); CHECK_EVAL("ncr(4;2)", "6"); CHECK_EVAL("ncr(4;3)", "4"); CHECK_EVAL("ncr(4;4)", "1"); CHECK_EVAL("ncr(4;5)", "0"); } void test_function_simplified() { /* Tests for standard functions */ CHECK_EVAL("abs 123", "123"); CHECK_EVAL("abs -123", "123"); /* (issue #600) */ CHECK_EVAL("10 + abs 123", "133"); CHECK_EVAL("10 + abs -123", "133"); /* (issue #600) */ CHECK_EVAL("abs 123 + 10", "133"); CHECK_EVAL("abs -123 + 10", "133"); /* (issue #600) */ CHECK_EVAL("10 * abs 123", "1230"); CHECK_EVAL("abs 123 * 10", "1230"); /* Postfix factorial in user function bodies. Complex mode is the app default and the case that used to reject the definition. */ { Settings* settings = Settings::instance(); const bool oldComplexNumbers = settings->complexNumbers; const bool oldComplexMode = DMath::complexMode; for (const bool complexNumbers : {false, true}) { settings->complexNumbers = complexNumbers; DMath::complexMode = complexNumbers; CHECK_USERFUNC_SET("fact1(n) = n!"); CHECK_EVAL("fact1(5)", "120"); CHECK_USERFUNC_SET("fact2(n) = n! / 2"); CHECK_EVAL("fact2(6)", "360"); CHECK_USERFUNC_SET("fact3(x) = 2*x!"); CHECK_EVAL("fact3(3)", "12"); } settings->complexNumbers = oldComplexNumbers; DMath::complexMode = oldComplexMode; } /* Tests for user functions (issue #600, cf. discussion) */ CHECK_USERFUNC_SET("func2(x) = abs(x)"); CHECK_EVAL("func2 123", "123"); CHECK_EVAL("func2 -123", "123"); CHECK_EVAL("10 + func2 123", "133"); CHECK_EVAL("10 + func2 -123", "133"); CHECK_EVAL("func2 123 + 10", "133"); CHECK_EVAL("func2 -123 + 10", "133"); CHECK_EVAL("10 * func2 123", "1230"); CHECK_EVAL("func2 123 * 10", "1230"); CHECK_USERFUNC_SET("f(x) = 5[metre] + x"); /* (issue #656) */ CHECK_EVAL("f(2[metre])", "7 metre"); /* (issue #656) */ CHECK_EVAL_FAIL("f(2)"); /* (issue #656) */ /* Tests for priority management (issue #451) */ CHECK_EVAL("log10 10^2", "2"); CHECK_EVAL("frac 3!", "0"); CHECK_EVAL("-log10 10", "-1"); CHECK_EVAL("2*-log10 10", "-2"); CHECK_EVAL("--log10 10", "1"); CHECK_EVAL("-ln 10", "-2.30258509299404568402"); CHECK_EVAL("-log2 8", "-3"); CHECK_EVAL("-sin 1", "-0.84147098480789650665"); CHECK_EVAL("-cos pi", "1"); CHECK_EVAL("-tan 1", "-1.55740772465490223051"); CHECK_EVAL("-arcsin 1", "-1.57079632679489661923"); CHECK_EVAL("-arccos 0", "-1.57079632679489661923"); CHECK_EVAL("-arctan 1", "-0.78539816339744830962"); CHECK_EVAL("2*-sin 1", "-1.68294196961579301331"); CHECK_EVAL("--sin 1", "0.84147098480789650665"); CHECK_EVAL("10 + -cos pi", "11"); } void test_auto_fix_parentheses() { CHECK_AUTOFIX("sin(1)", "sin(1)"); CHECK_AUTOFIX("sin(1", "sin(1)"); CHECK_AUTOFIX("x+(8-2", "x+(8-2)"); CHECK_AUTOFIX("x+(8-2)", "x+(8-2)"); CHECK_AUTOFIX("x+(8-(2*1", "x+(8-(2*1))"); CHECK_AUTOFIX("x+(8-(2*1)", "x+(8-(2*1))"); CHECK_AUTOFIX("x+(8-(2*1))", "x+(8-(2*1))"); CHECK_AUTOFIX("{1; 2", "{1; 2}"); CHECK_AUTOFIX("2 * {1; 2", "2 * {1; 2}"); CHECK_EVAL(eval->autoFix(QStringLiteral("{1; 2")), "{1; 2}"); CHECK_AUTOFIX("x + sin (pi", "x + sin (pi)"); CHECK_AUTOFIX("2[m3", "2[m3]"); CHECK_AUTOFIX("3([m])", "3[m]"); CHECK_AUTOFIX("3(([[[m]]]))", "3[[[m]]]"); CHECK_AUTOFIX("3(((([[[m]]])))", "3[[[m]]]"); CHECK_AUTOFIX("3(((((((([[([m])]]))))", "3[[[m]]]"); CHECK_AUTOFIX("4[L] -> [dL", "4[L] -> [dL]"); CHECK_AUTOFIX("3[[m]]", "3[[m]]"); CHECK_AUTOFIX("3[[m]", "3[[m]]"); CHECK_AUTOFIX("3[[m", "3[[m]]"); } void test_auto_fix_ans() { CHECK_AUTOFIX("sin", "sin(ans)"); CHECK_AUTOFIX("cos", "cos(ans)"); CHECK_AUTOFIX("tan", "tan(ans)"); CHECK_AUTOFIX("abs", "abs(ans)"); CHECK_AUTOFIX("exp", "exp(ans)"); CHECK_AUTOFIX("log10", "log10(ans)"); CHECK_AUTOFIX("sqrt", "√(ans)"); CHECK_AUTOFIX("cbrt", "∛(ans)"); } void test_auto_fix_trailing_equal() { CHECK_AUTOFIX("1+2=", "1+2"); CHECK_AUTOFIX("1==", "1"); CHECK_AUTOFIX("1/3====", "1/3"); CHECK_AUTOFIX("sin(x+y)=", "sin(x+y)"); CHECK_AUTOFIX("1+2+", "1+2"); CHECK_AUTOFIX("1++++", "1"); CHECK_AUTOFIX("2**", "2"); CHECK_AUTOFIX("3/", "3"); CHECK_AUTOFIX("5+cos pi (", "5+cos pi"); CHECK_AUTOFIX("123 + average(2;3;4;", "123 + average(2;3;4)"); ++eval_total_tests; const QString fixedTrailingPlus = eval->autoFix(QString::fromUtf8("1+2+")); eval->setExpression(fixedTrailingPlus); const Quantity trailingPlusResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix trailing plus eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl << "\tAutoFix: " << fixedTrailingPlus.toUtf8().constData() << endl; } else { QString formatted = DMath::format(trailingPlusResult, Format::Fixed()); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QStringLiteral("3")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix trailing plus eval\t[NEW]" << endl << "\tResult : " << formatted.toLatin1().constData() << endl << "\tExpected : 3" << endl << "\tAutoFix : " << fixedTrailingPlus.toUtf8().constData() << endl; } } ++eval_total_tests; const QString fixedTrailingFunctionSep = eval->autoFix(QString::fromUtf8("123 + average(2;3;4;")); eval->setExpression(fixedTrailingFunctionSep); const Quantity trailingFunctionSepResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix trailing function separator eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl << "\tAutoFix: " << fixedTrailingFunctionSep.toUtf8().constData() << endl; } else { QString formatted = DMath::format(trailingFunctionSepResult, Format::Fixed()); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QStringLiteral("126")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix trailing function separator eval\t[NEW]" << endl << "\tResult : " << formatted.toLatin1().constData() << endl << "\tExpected : 126" << endl << "\tAutoFix : " << fixedTrailingFunctionSep.toUtf8().constData() << endl; } } } void test_auto_fix_untouch() { CHECK_AUTOFIX("sin(x)", "sin(x)"); CHECK_AUTOFIX("sin((x/y))", "sin((x/y))"); CHECK_AUTOFIX("ans", "ans"); CHECK_AUTOFIX("sin(ans)", "sin(ans)"); CHECK_AUTOFIX("tan(ans)", "tan(ans)"); CHECK_AUTOFIX("x=1.2", "x=1.2"); CHECK_AUTOFIX("1/sin pi", "1/sin pi"); } void test_auto_fix_powers() { CHECK_AUTOFIX("3¹", "3^1"); CHECK_AUTOFIX("3�¹", "3^(-1)"); CHECK_AUTOFIX("3¹²³������", "3^123456789"); CHECK_AUTOFIX("3²�", "3^20"); CHECK_AUTOFIX("cos²(pi)", "cos(pi)^2"); CHECK_AUTOFIX("cos² (pi)", "cos(pi)^2"); CHECK_AUTOFIX("cos^2(pi)", "cos(pi)^2"); CHECK_AUTOFIX("cos^(-1)(pi)", "cos(pi)^(-1)"); CHECK_AUTOFIX("2cos^3(pi)", "2cos(pi)^3"); CHECK_AUTOFIX("7 + 3²� * 4", "7 + 3^20 * 4"); CHECK_AUTOFIX("2×pi", "2·pi"); CHECK_AUTOFIX("2×a", "2·a"); CHECK_AUTOFIX("4·5", "4·5"); CHECK_AUTOFIX("2 × pi pi", "2·pi·pi"); CHECK_AUTOFIX("2 ×pi× pi", "2·pi·pi"); CHECK_AUTOFIX("Ω+μ", "Ω+µ"); CHECK_AUTOFIX("uV+uA", "uV+uA"); CHECK_AUTOFIX("2×sin(33×3×sin(23)×cos(−pi))×sin(23234)×23⧸2−sin(−12) − 12−12", "2·sin(33×3·sin(23)·cos(−pi))·sin(23234)·23⧸2−sin(−12) − 12−12"); CHECK_AUTOFIX("2 ×pi× pi + 2^12.000−2", "2·pi·pi + 2^12.000−2"); CHECK_AUTOFIX("4/2[s]", "4/2·[s]"); CHECK_AUTOFIX("1[metre] in [metre]", "1[metre] in [metre]"); CHECK_AUTOFIX("1[metre] IN [metre]", "1[metre] IN [metre]"); CHECK_AUTOFIX("sqrt(16)+cbrt(27)", "√(16)+∛(27)"); CHECK_AUTOFIX("asqrt(16)+cbrtfoo(27)", "asqrt(16)+cbrtfoo(27)"); CHECK_AUTOFIX("2 + 3^() + 4", "2 + 3 + 4"); CHECK_AUTOFIX("2 + 3 ^ ( ) + 4", "2 + 3 + 4"); ++eval_total_tests; eval->setExpression(eval->autoFix(QStringLiteral("4/2[s]"))); const Quantity autoFixedValueUnitDivisionResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix value-unit denominator grouping eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString formatted = DMath::format(autoFixedValueUnitDivisionResult, Format::Fixed()); if (formatted != QStringLiteral("2 second")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix value-unit denominator grouping eval\t[NEW]" << endl << "\tResult : " << formatted.toUtf8().constData() << endl << "\tExpected : 2 second" << endl; } } ++eval_total_tests; const QString fixedNoOpPower = eval->autoFix(QString::fromUtf8("2 + 3^() + 4")); eval->setExpression(fixedNoOpPower); const Quantity fixedNoOpPowerResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix empty parenthesized power eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl << "\tAutoFix: " << fixedNoOpPower.toUtf8().constData() << endl; } else { QString formatted = DMath::format(fixedNoOpPowerResult, Format::Fixed()); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QStringLiteral("9")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix empty parenthesized power eval\t[NEW]" << endl << "\tResult : " << formatted.toLatin1().constData() << endl << "\tExpected : 9" << endl << "\tAutoFix : " << fixedNoOpPower.toUtf8().constData() << endl; } } // Selection text copied from result display may contain medium spaces and // paragraph separators; auto-fix should still produce a valid expression. ++eval_total_tests; const QString selectionText = QString::fromUtf8( "−1 · (2²) · 69\u2029− 39 × 2� − 828 · (2²) + 39"); const QString fixedSelectionText = eval->autoFix(selectionText); eval->setExpression(fixedSelectionText); Quantity selectionResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix display selection text eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl << "\tAutoFix: " << fixedSelectionText.toUtf8().constData() << endl; } else { QString formatted = DMath::format(selectionResult, Format::Fixed()); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QStringLiteral("-4797")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix display selection text eval\t[NEW]" << endl << "\tResult : " << formatted.toLatin1().constData() << endl << "\tExpected : -4797" << endl << "\tAutoFix : " << fixedSelectionText.toUtf8().constData() << endl; } } ++eval_total_tests; const QString fixedFunctionPowerSelection = eval->autoFix(QString::fromUtf8("1+cos²(pi)")); eval->setExpression(fixedFunctionPowerSelection); const Quantity fixedFunctionPowerResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix function superscript eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl << "\tAutoFix: " << fixedFunctionPowerSelection.toUtf8().constData() << endl; } else { QString formatted = DMath::format(fixedFunctionPowerResult, Format::Fixed()); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QStringLiteral("2")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix function superscript eval\t[NEW]" << endl << "\tResult : " << formatted.toUtf8().constData() << endl << "\tExpected : 2" << endl << "\tAutoFix : " << fixedFunctionPowerSelection.toUtf8().constData() << endl; } } ++eval_total_tests; const QString fixedImplicitMulFunctionPower = eval->autoFix(QString::fromUtf8("2cos³(pi)")); eval->setExpression(fixedImplicitMulFunctionPower); const Quantity fixedImplicitMulFunctionPowerResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix implicit mul function superscript eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl << "\tAutoFix: " << fixedImplicitMulFunctionPower.toUtf8().constData() << endl; } else { QString formatted = DMath::format(fixedImplicitMulFunctionPowerResult, Format::Fixed()); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QStringLiteral("-2")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix implicit mul function superscript eval\t[NEW]" << endl << "\tResult : " << formatted.toUtf8().constData() << endl << "\tExpected : -2" << endl << "\tAutoFix : " << fixedImplicitMulFunctionPower.toUtf8().constData() << endl; } } ++eval_total_tests; const QString fixedImplicitMulFunctionPower2 = eval->autoFix(QString::fromUtf8("2cos²(pi)")); eval->setExpression(fixedImplicitMulFunctionPower2); const Quantity fixedImplicitMulFunctionPowerResult2 = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix implicit mul function superscript eval 2\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl << "\tAutoFix: " << fixedImplicitMulFunctionPower2.toUtf8().constData() << endl; } else { QString formatted = DMath::format(fixedImplicitMulFunctionPowerResult2, Format::Fixed()); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QStringLiteral("2")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix implicit mul function superscript eval 2\t[NEW]" << endl << "\tResult : " << formatted.toUtf8().constData() << endl << "\tExpected : 2" << endl << "\tAutoFix : " << fixedImplicitMulFunctionPower2.toUtf8().constData() << endl; } } ++eval_total_tests; const QString fixedCaretFunctionPower = eval->autoFix(QString::fromUtf8("2cos^3(pi)")); eval->setExpression(fixedCaretFunctionPower); const Quantity fixedCaretFunctionPowerResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix caret function power eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl << "\tAutoFix: " << fixedCaretFunctionPower.toUtf8().constData() << endl; } else { QString formatted = DMath::format(fixedCaretFunctionPowerResult, Format::Fixed()); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QStringLiteral("-2")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tautofix caret function power eval\t[NEW]" << endl << "\tResult : " << formatted.toUtf8().constData() << endl << "\tExpected : -2" << endl << "\tAutoFix : " << fixedCaretFunctionPower.toUtf8().constData() << endl; } } } void test_auto_fix_shift_add_sub() { CHECK_AUTOFIX("0x4f<<8+0x4c", "(0x4f << 8) + 0x4c"); CHECK_AUTOFIX("0x4f >> 8 + 0x4c", "(0x4f >> 8) + 0x4c"); CHECK_AUTOFIX("0x4f<<8-0x4c", "(0x4f << 8) - 0x4c"); // Keep explicit RHS grouping untouched. CHECK_AUTOFIX("0x4f<<(8+0x4c)", "0x4f<<(8+0x4c)"); } void test_comments() { CHECK_EVAL("ncr(3;3) ? this is because foo", "1"); CHECK_EVAL("? this is a comment-only line", "NaN"); CHECK_EVAL(" ? this is an indented comment-only line", "NaN"); CHECK_EVAL("21", "21"); CHECK_EVAL("? foo", "NaN"); CHECK_EVAL("1+ans", "22"); } void test_comments_do_not_change_result_formatting() { Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; const bool oldSimplify = settings->simplifyResultExpressions; const bool oldMultipleResultLines = settings->multipleResultLinesEnabled; settings->resultFormat = 'g'; settings->simplifyResultExpressions = true; Session session; Evaluator* evaluator = session.evaluator(); const struct { const char* expression; const char* comment; } cases[] = { { "2", "\"" }, { "2", "'" }, { "2", u8"° ′ ″" }, { "2", "[rad]" }, { "2", "sin(pi)" }, { "pi", "\"" }, { "pi", "arctan(1) -> [rad]" }, { u8"180°", u8"∠" }, { u8"180°", "sin(pi)" }, { u8"180° -> [rad]", "-> [degree]" }, { "arctan(1)", "-> [degree]" }, { "1:30", "-> [s]" }, { "2[m]", "[rad] \"" }, { "cos(pi)*cos(pi)", "? \" [rad] -> [degree]" }, { "2", "([} = 1/0 ? \"" } }; for (char angleUnit : {'r', 'd'}) { settings->angleUnit = angleUnit; evaluator->initializeBuiltInVariables(); for (bool multipleLines : {false, true}) { settings->multipleResultLinesEnabled = multipleLines; for (const auto& tc : cases) { const QString expression = QString::fromUtf8(tc.expression); evaluator->setExpression(expression); const Quantity expectedValue = evaluator->evalUpdateAns(); const QString expectedInterpreted = evaluator->interpretedExpression(); const QStringList expectedLines = ResultLineFormatUtils::formatResultLinesForDisplay( expression, expectedInterpreted, expectedValue, false, true, evaluator); const QStringList expectedResultOnly = ResultLineFormatUtils::formatResultLinesForDisplay( expression, expectedInterpreted, expectedValue, false, true, evaluator, true); const QString expectedSimplified = ResultLineFormatUtils::simplifiedExpressionLineForDisplay( expectedInterpreted, expression, true, evaluator); // Match compact comments too, since whitespace is optional before '?'. for (const QString& separator : {QStringLiteral("?"), QStringLiteral(" ? ")}) { const QString commented = expression + separator + QString::fromUtf8(tc.comment); evaluator->setExpression(evaluator->autoFix(commented)); const Quantity value = evaluator->evalUpdateAns(); const QString interpreted = evaluator->interpretedExpression(); const QStringList lines = ResultLineFormatUtils::formatResultLinesForDisplay( commented, interpreted, value, true, true, evaluator); const QStringList resultOnly = ResultLineFormatUtils::formatResultLinesForDisplay( commented, interpreted, value, false, true, evaluator, true); const QString simplified = ResultLineFormatUtils::simplifiedExpressionLineForDisplay( interpreted, commented, true, evaluator); ++eval_total_tests; if (!evaluator->error().isEmpty() || DMath::format(value, Format::Fixed()) != DMath::format(expectedValue, Format::Fixed()) || lines.mid(1) != expectedLines || resultOnly != expectedResultOnly || simplified != expectedSimplified || !lines.first().endsWith(QString::fromUtf8(tc.comment))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcomments leave results unchanged\t[NEW]" << endl << "\tExpression: " << commented.toUtf8().constData() << endl << "\tError : " << qPrintable(evaluator->error()) << endl << "\tResult : " << lines.join(QLatin1Char('\n')).toUtf8().constData() << endl << "\tExpected : " << expectedLines.join(QLatin1Char('\n')).toUtf8().constData() << endl; } } } } } settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; settings->simplifyResultExpressions = oldSimplify; settings->multipleResultLinesEnabled = oldMultipleResultLines; } void test_comment_and_description_edge_cases() { // Autofix should normalize spacing before comments while preserving comment text. CHECK_AUTOFIX("x=1?foo", "x=1 ? foo"); CHECK_AUTOFIX("x=1 ? foo bar", "x=1 ? foo bar"); CHECK_AUTOFIX("1+2 ? foo ? bar", "1+2 ? foo ? bar"); // Interpreted and display-interpreted output should preserve comment tails. CHECK_INTERPRETED("2×pi ? calc area", "2·pi ? calc area"); CHECK_DISPLAY_INTERPRETED( "2*3?c", QStringLiteral("2") + space + QString(MathDsl::MulCrossOp) + space + QStringLiteral("3 ? c")); CHECK_INTERPRETED("1[metre] -> [cm]", u8"1[metre]→cm"); CHECK_INTERPRETED("1[metre] in [cm]", u8"1[metre]→cm"); CHECK_INTERPRETED(QString::fromUtf8("1° in [rad]"), u8"1[degree]→rad"); CHECK_INTERPRETED(QString::fromUtf8("1′ in [rad]"), u8"1[arcminute]→rad"); CHECK_INTERPRETED(QString::fromUtf8("1″ in [rad]"), u8"1[arcsecond]→rad"); const QString compactAngleConversionCases[][2] = { {QString::fromUtf8("1° in [rad]"), QString::fromUtf8("1° → [rad]")}, {QString::fromUtf8("1′ in [rad]"), QString::fromUtf8("1′ → [rad]")}, {QString::fromUtf8("1″ in [rad]"), QString::fromUtf8("1″ → [rad]")} }; for (const auto& tc : compactAngleConversionCases) { eval->setExpression(tc[0]); eval->evalUpdateAns(); ++eval_total_tests; const QString displayed = ResultLineFormatUtils::formattedExpressionLineForDisplay( tc[0], eval->interpretedExpression(), eval); if (displayed != tc[1]) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcompact angle in-conversion display\t[NEW]" << endl << "\tExpression: " << tc[0].toUtf8().constData() << endl << "\tDisplayed : " << displayed.toUtf8().constData() << endl << "\tExpected : " << tc[1].toUtf8().constData() << endl; } } // Explicit empty description should be stored as empty. CHECK_EVAL("vardesc2 = 1 ? ", "1"); CHECK_USERVAR_DESC("vardesc2", ""); CHECK_USERFUNC_SET("funcdesc2(x) = x + 1 ? "); CHECK_USERFUNC_DESC("funcdesc2", ""); // Description text should preserve punctuation and additional question marks. CHECK_EVAL("vardesc3 = 3 ? unit m/s ? approx", "3"); CHECK_USERVAR_DESC("vardesc3", "unit m/s ? approx"); } void test_user_functions() { // Check user functions can be defined and used CHECK_USERFUNC_SET("func1(x;b) = x * b + 10"); CHECK_USERFUNC_SET("gf(x) = cos x^-pi"); CHECK_USERFUNC_INTERPRETED("gf", "cos(x^(-pi))"); CHECK_EVAL("func1(2;5)", "20"); // = 2 * 5 + 10 // Check some expected error conditions CHECK_EVAL_FAIL("func1()"); CHECK_EVAL_FAIL("func1(2)"); CHECK_EVAL_FAIL("func1(2;5;1)"); // Check user functions can call other user functions CHECK_USERFUNC_SET("func2(x;b) = func1(x;b) - 10"); CHECK_EVAL("func2(2;5)", "10"); // = (2 * 5 + 10) - 10 // Check user functions can be redefined CHECK_USERFUNC_SET("func2(x;b) = 10 + func1(x;b)"); CHECK_EVAL("func2(2;5)", "30"); // = 10 + (2 * 5 + 10) // Check user functions can refer to other user functions not defined CHECK_USERFUNC_SET("func2(x;b) = 10 * x + func3(x;b)"); CHECK_EVAL_FAIL("func2(2;5)"); CHECK_USERFUNC_SET("func3(x;b) = x - b"); CHECK_EVAL("func2(2;5)", "17"); // = 10 * 2 + (2 - 5) // Check user functions can call builtin functions CHECK_USERFUNC_SET("func2(x;b) = sum(func1(x;b);5)"); CHECK_EVAL("func2(2;5)", "25"); // = sum((2 * 5 + 10);5) // Check recursive user functions are not allowed CHECK_USERFUNC_SET("func_r(x) = x * func_r(x)"); CHECK_EVAL_FAIL("func_r(1)"); CHECK_USERFUNC_SET("func_r1(x) = x * func_r2(x)"); CHECK_USERFUNC_SET("func_r2(x) = x + func_r1(x)"); CHECK_EVAL_FAIL("func_r1(1)"); // Check user functions can refer to user variables CHECK_USERFUNC_SET("func1(x;b) = x * b - var1"); CHECK_EVAL_FAIL("func1(2;5)"); CHECK_EVAL("var1 = 5", "5"); CHECK_EVAL("func1(2;5)", "5"); // = 2 * 5 - 5 // Check conflicts between the names of user functions arguments and user variables CHECK_EVAL("arg1 = 10", "10"); CHECK_USERFUNC_SET("func1(arg1;arg2) = arg1 * arg2"); CHECK_EVAL("func1(2;5)", "10"); // = 2 * 5 (not 10 * 5) // Check user functions names can not mask builtin functions CHECK_USERFUNC_SET_FAIL("sum(x;b) = x * b"); // Check user functions names can not mask user variables CHECK_EVAL("var1 = 5", "5"); CHECK_USERFUNC_SET_FAIL("var1(x;b) = x * b"); // Check user functions can take no argument CHECK_EVAL("func1() = 2 * 10", "20"); // NOTE: we use CHECK_EVAL to define the function, because its result is known at definition // time. CHECK_USERFUNC_SET expects NaN, which is what is returned when the function body // contains at least one component whose value can not be known at definition time // (e.g., reference to user function arguments or to user/builtin functions). CHECK_EVAL("func1()", "20"); // = 2 * 5 // Check optional descriptions on user function definitions. CHECK_USERFUNC_SET("funcdesc(x) = x + 1 ? Calculate Foo"); CHECK_USERFUNC_DESC("funcdesc", "Calculate Foo"); CHECK_EVAL("funcdesc(2)", "3"); CHECK_USERFUNC_SET( QStringLiteral("testshift(x)=1") + space + QStringLiteral("<<") + space + QStringLiteral("x+0")); CHECK_EVAL("testshift(8)", "256"); // Check redefining a function without description clears it. CHECK_USERFUNC_SET("funcdesc(x) = x + 2"); CHECK_USERFUNC_DESC("funcdesc", ""); // Check optional descriptions on user variable definitions. CHECK_EVAL("vardesc = 7 ? Lucky seven", "7"); CHECK_USERVAR_DESC("vardesc", "Lucky seven"); CHECK_EVAL("vardesc", "7"); // Check redefining a variable without description clears it. CHECK_EVAL("vardesc = 8", "8"); CHECK_USERVAR_DESC("vardesc", ""); } void test_user_units() { CHECK_INTERPRETED(QString::fromUtf8("[foounit] = [m�]"), "[foounit]=[m^5]"); CHECK_EVAL("[two_cubic_metres] = 2[m^3]", "2 cubic_metre"); CHECK_EVAL("1[two_cubic_metres] -> [m^3]", "2 m³"); CHECK_EVAL("[ten_metres] = 10[m]", "10 metre"); CHECK_EVAL("3[ten_metres] -> [m]", "30 m"); CHECK_EVAL("[cm_s] = [cm/s]", "0.01 metre·second�¹"); CHECK_EVAL("100[cm_s] -> [m/s]", "1 m·s�¹"); CHECK_EVAL("[unit_desc] = [m/s] ? speed alias", "1 metre·second�¹"); CHECK_USERUNIT_DESC("unit_desc", "speed alias"); } void test_complex() { // Check for basic complex number processing CHECK_EVAL("1j", "1i"); CHECK_EVAL("0.1j", "0.1i"); CHECK_EVAL(".1j", "0.1i"); CHECK_EVAL("1E12j", "1000000000000i"); CHECK_EVAL("0.1E12j", "100000000000i"); CHECK_EVAL("1E-12j", "0.000000000001i"); CHECK_EVAL("0.1E-12j", "0.0000000000001i"); // Check for some bugs introduced by first versions of complex number processing CHECK_EVAL("0.1", "0.1"); // Check for basic complex number evaluation CHECK_EVAL("(1+1j)*(1-1j)", "2"); CHECK_EVAL("(1+1j)*(1+1j)", "2i"); CHECK_EVAL("VARP(1j;-1j)", "1"); CHECK_EVAL("VARS(1j;-1j)", "2"); CHECK_EVAL("VARP(1j;-1j;1;-1)", "1"); CHECK_EVAL("VARP(2j;-2j;1;-1)", "2.5"); CHECK_EVAL("VARS(2j;-2j;1;-1)", "3.33333333333333333333"); } void test_angle_mode(Settings* settings) { const char savedExponentStyle = settings->unitNegativeExponentStyle; settings->unitNegativeExponentStyle = Settings::UnitNegativeExponentSuperscript; setRuntimeUnitNegativeExponentStyle(Settings::UnitNegativeExponentSuperscript); const auto checkAngularRateDisplayContains = [&](const QString& expression, char angleUnit, const QString& angleSymbol) { settings->angleUnit = angleUnit; Evaluator::instance()->initializeAngleUnits(); ++eval_total_tests; eval->setExpression(expression); const QString display = NumberFormatter::format(eval->evalUpdateAns()); const QString expectedAngleToken = angleUnit == 'd' ? Units::degreeAliasSymbol() : angleSymbol; const bool hasAngleSymbol = display.contains(expectedAngleToken); const bool hasSuperscriptPerSecond = display.contains(QString::fromUtf8("s�¹")); const bool hasSlashPerSecond = display.contains(QStringLiteral("/s")) || display.contains(QStringLiteral("/ s")); if (!eval->error().isEmpty() || !hasAngleSymbol || !hasSuperscriptPerSecond || hasSlashPerSecond) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tangle mode angular-rate display unit\t[NEW]" << endl << "\tExpression: " << expression.toUtf8().constData() << endl << "\tResult: " << display.toUtf8().constData() << endl << "\tError: " << qPrintable(eval->error()) << endl; } }; const auto checkAngleCompositeProductDisplayContains = [&](const QString& expression, char angleUnit, const QString& angleSymbol, const QStringList& requiredTokens = QStringList{QString(::unitSymbol(UnitId::Second))}, const QStringList& forbiddenTokens = QStringList{}) { settings->angleUnit = angleUnit; Evaluator::instance()->initializeAngleUnits(); ++eval_total_tests; eval->setExpression(expression); const QString display = NumberFormatter::format(eval->evalUpdateAns()); const QString expectedAngleToken = angleUnit == 'd' ? Units::degreeAliasSymbol() : angleSymbol; const bool hasAngleToken = display.contains(expectedAngleToken); bool hasRequiredTokens = true; for (const QString& token : requiredTokens) { if (!display.contains(token)) { hasRequiredTokens = false; break; } } bool hasForbiddenTokens = false; for (const QString& token : forbiddenTokens) { if (display.contains(token)) { hasForbiddenTokens = true; break; } } if (!eval->error().isEmpty() || !hasAngleToken || !hasRequiredTokens || hasForbiddenTokens) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tangle mode composite-angle product display unit\t[NEW]" << endl << "\tExpression: " << expression.toUtf8().constData() << endl << "\tResult: " << display.toUtf8().constData() << endl << "\tError: " << qPrintable(eval->error()) << endl; } }; const auto checkCompositeAngleAliasDisplay = [&](const QString& expression, const QString& expectedAlias, const QString& forbiddenSymbol) { ++eval_total_tests; eval->setExpression(expression); const QString display = NumberFormatter::format(eval->evalUpdateAns()); if (!eval->error().isEmpty() || !display.contains(expectedAlias) || display.contains(forbiddenSymbol)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcomposite angle alias display unit\t[NEW]" << endl << "\tExpression: " << expression.toUtf8().constData() << endl << "\tResult: " << display.toUtf8().constData() << endl << "\tError: " << qPrintable(eval->error()) << endl; } }; const auto checkDivByAngleKeepsAngleDisplay = [&](const QString& expression, const QString& expectedAngleToken) { ++eval_total_tests; eval->setExpression(expression); const QString display = NumberFormatter::format(eval->evalUpdateAns()); if (!eval->error().isEmpty() || !display.contains(QString(::unitSymbol(UnitId::Metre))) || !display.contains(expectedAngleToken) || display.endsWith(QStringLiteral("[m]"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tlength-per-angle keeps angle denominator display unit\t[NEW]" << endl << "\tExpression: " << expression.toUtf8().constData() << endl << "\tResult: " << display.toUtf8().constData() << endl << "\tError: " << qPrintable(eval->error()) << endl; } }; const auto checkAngleExponentAliasInInterpretedExpression = [&](const QString& expression, const QString& expectedToken, const QString& forbiddenToken) { ++eval_total_tests; eval->setExpression(expression); eval->evalUpdateAns(); const QString interpreted = Evaluator::formatInterpretedExpressionForDisplay( eval->interpretedExpression(), eval); if (!eval->error().isEmpty() || !interpreted.contains(expectedToken) || interpreted.contains(forbiddenToken)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tangle exponent alias preserved in interpreted expression\t[NEW]" << endl << "\tExpression: " << expression.toUtf8().constData() << endl << "\tInterpreted: " << interpreted.toUtf8().constData() << endl << "\tError: " << qPrintable(eval->error()) << endl; } }; const auto checkAngleInversePowerUnitDisplay = [&](const QString& expression, const QString& expectedUnitToken) { ++eval_total_tests; eval->setExpression(expression); const QString display = NumberFormatter::format(eval->evalUpdateAns()); const QString bracketedExpectedToken = QString(MathDsl::UnitStart) + expectedUnitToken + QString(MathDsl::UnitEnd); if (!eval->error().isEmpty() || !display.contains(bracketedExpectedToken)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texplicit angle inverse-power keeps display unit\t[NEW]" << endl << "\tExpression: " << expression.toUtf8().constData() << endl << "\tResult: " << display.toUtf8().constData() << endl << "\tError: " << qPrintable(eval->error()) << endl; } }; settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL("sin(pi)", "0"); CHECK_EVAL("arcsin(-1)", "-1.57079632679489661923"); CHECK_EVAL("arccos(0)", "1.57079632679489661923"); CHECK_EVAL("tan(arctan(1))", "1"); CHECK_EVAL("tan(arctan2(1;1))", "1"); CHECK_EVAL("sin(arcsin(0.25))", "0.25"); CHECK_EVAL("cos(arccos(0.25))", "0.25"); CHECK_EVAL("tan(arctan(0.25))", "0.25"); CHECK_EVAL("sin(1j)", "1.17520119364380145688i"); CHECK_EVAL("arcsin(-2)", "-1.57079632679489661923+1.31695789692481670863i"); CHECK_EVAL("[radian]","1 rad"); CHECK_EVAL("[rad]","1 rad"); CHECK_EVAL("cos(pi*[rad])", "-1"); CHECK_EVAL(QString::fromUtf8("cos(180°)"), "-1"); CHECK_EVAL("cos(180*[degree])", "-1"); CHECK_EVAL("cos(200*[gradian])", "-1"); CHECK_EVAL("cos(200*[gon])", "-1"); CHECK_EVAL("cos(0.5*[turn])", "-1"); CHECK_EVAL("cos(0.5*[revolution])", "-1"); CHECK_EVAL("cos(0.5*[rev])", "-1"); CHECK_EVAL("[degree]","0.01745329251994329577 rad"); CHECK_EVAL("[deg]","0.01745329251994329577 rad"); CHECK_EVAL(QString::fromUtf8("[˚]"), "0.01745329251994329577 rad"); CHECK_EVAL("[gradian]","0.01570796326794896619 rad"); CHECK_EVAL("[gon]","0.01570796326794896619 rad"); CHECK_EVAL("[turn]","6.28318530717958647693 rad"); CHECK_EVAL("[tr]","6.28318530717958647693 rad"); CHECK_EVAL("[revolution]","6.28318530717958647693 rad"); CHECK_EVAL("[rev]","6.28318530717958647693 rad"); CHECK_EVAL("1 [tr]", "6.28318530717958647693 rad"); CHECK_EVAL(QString::fromUtf8("2 [µrad]"), "0.000002 rad"); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second]"), 'r', Units::angleModeUnitSymbol('r')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second metre]"), 'r', Units::angleModeUnitSymbol('r')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·s·m]"), 'r', Units::angleModeUnitSymbol('r')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·J·m·J·s/J²]"), 'r', Units::angleModeUnitSymbol('r'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Joule))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·m·N]"), 'r', Units::angleModeUnitSymbol('r'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Newton))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·kg·m^3·s^-1]"), 'r', Units::angleModeUnitSymbol('r'), QStringList{QString(::unitSymbol(UnitId::Joule)), QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Kilogram))}); checkCompositeAngleAliasDisplay(QString::fromUtf8("1 [rad/m] -> [°/m]"), Units::degreeAliasSymbol(), QString(UnicodeChars::DegreeSign)); checkCompositeAngleAliasDisplay(QString::fromUtf8("1 [rad/m] -> [′/m]"), Units::arcminuteAliasSymbol(), QString(UnicodeChars::Prime)); checkCompositeAngleAliasDisplay(QString::fromUtf8("1 [rad/m] -> [″/m]"), Units::arcsecondAliasSymbol(), QString(UnicodeChars::DoublePrime)); checkAngleExponentAliasInInterpretedExpression( QStringLiteral("1 [arcmin²]"), QStringLiteral("arcmin") + MathDsl::Pow2, QString(UnicodeChars::Prime) + MathDsl::Pow2); checkAngleExponentAliasInInterpretedExpression( QStringLiteral("1 [arcmin") + MathDsl::PowNeg + MathDsl::Pow1 + QStringLiteral("]"), QStringLiteral("arcmin") + MathDsl::PowNeg + MathDsl::Pow1, QString(UnicodeChars::Prime) + MathDsl::PowNeg + MathDsl::Pow1); checkDivByAngleKeepsAngleDisplay(QStringLiteral("1 [m/arcmin]"), Units::angleModeUnitSymbol('r')); checkAngularRateDisplayContains(QStringLiteral("360 [deg second^-1]"), 'r', Units::angleModeUnitSymbol('r')); checkAngularRateDisplayContains(QStringLiteral("1 [rev/min]"), 'r', Units::angleModeUnitSymbol('r')); checkAngularRateDisplayContains(QStringLiteral("1 [rev*min^-1]"), 'r', Units::angleModeUnitSymbol('r')); checkAngularRateDisplayContains(QStringLiteral("1 [rpm]"), 'r', Units::angleModeUnitSymbol('r')); settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL("sin(180)", "0"); CHECK_EVAL("arcsin(-1)", "-90"); CHECK_EVAL("arccos(0)", "90"); CHECK_EVAL("arctan(1)", "45"); CHECK_EVAL("arctan2(1;1)", "45"); CHECK_EVAL("sin(arcsin(0.25))", "0.25"); CHECK_EVAL("cos(arccos(0.25))", "0.25"); CHECK_EVAL("tan(arctan(0.25))", "0.25"); CHECK_EVAL_FAIL("sin(1j)"); CHECK_EVAL("arcsin(-2)", "-90+75.4561292902168920041i"); CHECK_EVAL("[radian]","57.2957795130823208768°"); CHECK_EVAL("[rad]","57.2957795130823208768°"); CHECK_EVAL("cos(pi*[rad])", "-1"); CHECK_EVAL("cos(180[rad])", "-0.59846006905785813897"); CHECK_EVAL("cos(180*[degree])", "-1"); CHECK_EVAL("cos(200*[gradian])", "-1"); CHECK_EVAL("cos(200*[gon])", "-1"); CHECK_EVAL("cos(0.5*[turn])", "-1"); CHECK_EVAL("cos(0.5*[revolution])", "-1"); CHECK_EVAL("cos(0.5*[rev])", "-1"); CHECK_EVAL("pi [rad]", "180°"); CHECK_EVAL("pi[rad] -> [°]", "180°"); CHECK_EVAL("[degree]","1°"); CHECK_EVAL("[deg]","1°"); CHECK_EVAL("1 -> [degree]", "1°"); CHECK_EVAL("1 -> [deg]", "1°"); CHECK_EVAL("[gradian]","0.9°"); CHECK_EVAL("[gon]","0.9°"); CHECK_EVAL("[turn]","360°"); CHECK_EVAL("[tr]","360°"); CHECK_EVAL("[revolution]","360°"); CHECK_EVAL("[rev]","360°"); CHECK_EVAL("1 [tr]", "360°"); CHECK_EVAL(QString::fromUtf8("2 [µrad]"), "0.00011459155902616464°"); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second]"), 'd', Units::angleModeUnitSymbol('d')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second metre]"), 'd', Units::angleModeUnitSymbol('d')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·s·m]"), 'd', Units::angleModeUnitSymbol('d')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·J·m·J·s/J²]"), 'd', Units::angleModeUnitSymbol('d'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Joule))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·m·N]"), 'd', Units::angleModeUnitSymbol('d'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Newton))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·kg·m^3·s^-1]"), 'd', Units::angleModeUnitSymbol('d'), QStringList{QString(::unitSymbol(UnitId::Joule)), QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Kilogram))}); ++eval_total_tests; eval->setExpression(QStringLiteral("360 [deg second^-1]")); { const QString display = NumberFormatter::format(eval->evalUpdateAns()); if (!eval->error().isEmpty() || !display.contains(QStringLiteral("deg")) || !display.contains(QString::fromUtf8("s�¹")) || display.contains(QString::fromUtf8("°"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tdegree alias preserved in composite angle unit\t[NEW]" << endl << "\tResult: " << display.toUtf8().constData() << endl << "\tError : " << qPrintable(eval->error()) << endl; } } checkAngularRateDisplayContains(QStringLiteral("360 [deg second^-1]"), 'd', Units::angleModeUnitSymbol('d')); checkAngularRateDisplayContains(QStringLiteral("1 [rev/min]"), 'd', Units::angleModeUnitSymbol('d')); checkAngularRateDisplayContains(QStringLiteral("1 [rev*min^-1]"), 'd', Units::angleModeUnitSymbol('d')); checkAngularRateDisplayContains(QStringLiteral("1 [rpm]"), 'd', Units::angleModeUnitSymbol('d')); checkDivByAngleKeepsAngleDisplay(QStringLiteral("1 [m/arcmin]"), Units::degreeAliasSymbol()); CHECK_EVAL_KNOWN_ISSUE("arcsin(0.25)", "14.47751218592992387877", 781); settings->angleUnit = 'g'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL("sin(200)", "0"); CHECK_EVAL("arcsin(-1)", "-100"); CHECK_EVAL("arccos(0)", "100"); CHECK_EVAL("arctan(1)", "50"); CHECK_EVAL("arctan2(1;1)", "50"); CHECK_EVAL("sin(arcsin(0.25))", "0.25"); CHECK_EVAL("cos(arccos(0.25))", "0.25"); CHECK_EVAL("tan(arctan(0.25))", "0.25"); CHECK_EVAL_FAIL("sin(1j)"); CHECK_EVAL("arcsin(-2)", "-100+83.84014365579654667122i"); CHECK_EVAL("[radian]","63.66197723675813430755 gon"); CHECK_EVAL("[rad]","63.66197723675813430755 gon"); CHECK_EVAL("cos(pi*[rad])", "-1"); CHECK_EVAL("cos(180*[degree])", "-1"); CHECK_EVAL("cos(200*[gradian])", "-1"); CHECK_EVAL("cos(200*[gon])", "-1"); CHECK_EVAL("cos(0.5*[turn])", "-1"); CHECK_EVAL("cos(0.5*[revolution])", "-1"); CHECK_EVAL("cos(0.5*[rev])", "-1"); CHECK_EVAL("[degree]","1.11111111111111111111 gon"); CHECK_EVAL("[deg]","1.11111111111111111111 gon"); CHECK_EVAL("[gradian]","1 gon"); CHECK_EVAL("[gon]","1 gon"); CHECK_EVAL("[turn]","400 gon"); CHECK_EVAL("[tr]","400 gon"); CHECK_EVAL("[revolution]","400 gon"); CHECK_EVAL("[rev]","400 gon"); CHECK_EVAL("1 [tr]", "400 gon"); checkAngleInversePowerUnitDisplay( QStringLiteral("1 [arcmin") + MathDsl::PowNeg + MathDsl::Pow2 + QStringLiteral("]"), Units::angleModeUnitSymbol('g') + QString(MathDsl::PowNeg) + QString(MathDsl::Pow2)); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second]"), 'g', Units::angleModeUnitSymbol('g')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second metre]"), 'g', Units::angleModeUnitSymbol('g')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·s·m]"), 'g', Units::angleModeUnitSymbol('g')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·J·m·J·s/J²]"), 'g', Units::angleModeUnitSymbol('g'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Joule))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·m·N]"), 'g', Units::angleModeUnitSymbol('g'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Newton))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·kg·m^3·s^-1]"), 'g', Units::angleModeUnitSymbol('g'), QStringList{QString(::unitSymbol(UnitId::Joule)), QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Kilogram))}); checkAngularRateDisplayContains(QStringLiteral("1 [rev/min]"), 'g', Units::angleModeUnitSymbol('g')); checkAngularRateDisplayContains(QStringLiteral("1 [rev*min^-1]"), 'g', Units::angleModeUnitSymbol('g')); checkAngularRateDisplayContains(QStringLiteral("1 [rpm]"), 'g', Units::angleModeUnitSymbol('g')); settings->angleUnit = 't'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL("sin(0.5)", "0"); CHECK_EVAL("arcsin(-1)", "-0.25"); CHECK_EVAL("arccos(0)", "0.25"); CHECK_EVAL("arctan(1)", "0.125"); CHECK_EVAL("arctan2(1;1)", "0.125"); CHECK_EVAL("sin(arcsin(0.25))", "0.25"); CHECK_EVAL("cos(arccos(0.25))", "0.25"); CHECK_EVAL("tan(arctan(0.25))", "0.25"); CHECK_EVAL_FAIL("sin(1j)"); CHECK_EVAL("arcsin(-2)", "-0.25+0.20960035913949136668i"); CHECK_EVAL("[radian]","0.15915494309189533577 tr"); CHECK_EVAL("[rad]","0.15915494309189533577 tr"); CHECK_EVAL("cos(pi*[rad])", "-1"); CHECK_EVAL("cos(180*[degree])", "-1"); CHECK_EVAL("cos(200*[gradian])", "-1"); CHECK_EVAL("cos(200*[gon])", "-1"); CHECK_EVAL("cos(0.5*[turn])", "-1"); CHECK_EVAL("cos(0.5*[revolution])", "-1"); CHECK_EVAL("cos(0.5*[rev])", "-1"); CHECK_EVAL("[degree]","0.00277777777777777778 tr"); CHECK_EVAL("[deg]","0.00277777777777777778 tr"); CHECK_EVAL("[gradian]","0.0025 tr"); CHECK_EVAL("[gon]","0.0025 tr"); CHECK_EVAL("[turn]","1 tr"); CHECK_EVAL("[tr]","1 tr"); CHECK_EVAL("[revolution]","1 tr"); CHECK_EVAL("[rev]","1 tr"); CHECK_EVAL("1 [tr]", "1 tr"); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second]"), 't', Units::angleModeUnitSymbol('t')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second metre]"), 't', Units::angleModeUnitSymbol('t')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·s·m]"), 't', Units::angleModeUnitSymbol('t')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·J·m·J·s/J²]"), 't', Units::angleModeUnitSymbol('t'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Joule))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·m·N]"), 't', Units::angleModeUnitSymbol('t'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Newton))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·kg·m^3·s^-1]"), 't', Units::angleModeUnitSymbol('t'), QStringList{QString(::unitSymbol(UnitId::Joule)), QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Kilogram))}); checkAngularRateDisplayContains(QStringLiteral("1 [rev/min]"), 't', Units::angleModeUnitSymbol('t')); checkAngularRateDisplayContains(QStringLiteral("1 [rev*min^-1]"), 't', Units::angleModeUnitSymbol('t')); checkAngularRateDisplayContains(QStringLiteral("1 [rpm]"), 't', Units::angleModeUnitSymbol('t')); settings->angleUnit = 'v'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL("sin(0.5)", "0"); CHECK_EVAL("arcsin(-1)", "-0.25"); CHECK_EVAL("arccos(0)", "0.25"); CHECK_EVAL("arctan(1)", "0.125"); CHECK_EVAL("arctan2(1;1)", "0.125"); CHECK_EVAL("sin(arcsin(0.25))", "0.25"); CHECK_EVAL("cos(arccos(0.25))", "0.25"); CHECK_EVAL("tan(arctan(0.25))", "0.25"); CHECK_EVAL_FAIL("sin(1j)"); CHECK_EVAL("arcsin(-2)", "-0.25+0.20960035913949136668i"); CHECK_EVAL("[radian]","0.15915494309189533577 rev"); CHECK_EVAL("[rad]","0.15915494309189533577 rev"); CHECK_EVAL("cos(pi*[rad])", "-1"); CHECK_EVAL("cos(180*[degree])", "-1"); CHECK_EVAL("cos(200*[gradian])", "-1"); CHECK_EVAL("cos(200*[gon])", "-1"); CHECK_EVAL("cos(0.5*[turn])", "-1"); CHECK_EVAL("cos(0.5*[revolution])", "-1"); CHECK_EVAL("cos(0.5*[rev])", "-1"); CHECK_EVAL("[degree]","0.00277777777777777778 rev"); CHECK_EVAL("[deg]","0.00277777777777777778 rev"); CHECK_EVAL("[gradian]","0.0025 rev"); CHECK_EVAL("[gon]","0.0025 rev"); CHECK_EVAL("[turn]","1 rev"); CHECK_EVAL("[tr]","1 rev"); CHECK_EVAL("[revolution]","1 rev"); CHECK_EVAL("[rev]","1 rev"); CHECK_EVAL("1 [tr]", "1 rev"); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second]"), 'v', Units::angleModeUnitSymbol('v')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg second metre]"), 'v', Units::angleModeUnitSymbol('v')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·s·m]"), 'v', Units::angleModeUnitSymbol('v')); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·J·m·J·s/J²]"), 'v', Units::angleModeUnitSymbol('v'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Joule))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·m·N]"), 'v', Units::angleModeUnitSymbol('v'), QStringList{QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Newton))}); checkAngleCompositeProductDisplayContains(QStringLiteral("360 [deg·kg·m^3·s^-1]"), 'v', Units::angleModeUnitSymbol('v'), QStringList{QString(::unitSymbol(UnitId::Joule)), QString(::unitSymbol(UnitId::Metre)), QString(::unitSymbol(UnitId::Second))}, QStringList{QString(::unitSymbol(UnitId::Kilogram))}); checkAngularRateDisplayContains(QStringLiteral("1 [rev/min]"), 'v', Units::angleModeUnitSymbol('v')); checkAngularRateDisplayContains(QStringLiteral("1 [rev*min^-1]"), 'v', Units::angleModeUnitSymbol('v')); checkAngularRateDisplayContains(QStringLiteral("1 [rpm]"), 'v', Units::angleModeUnitSymbol('v')); settings->unitNegativeExponentStyle = savedExponentStyle; setRuntimeUnitNegativeExponentStyle(savedExponentStyle); } void test_implicit_multiplication() { CHECK_EVAL("av = 5", "5"); CHECK_EVAL("5av", "25"); CHECK_EVAL("5.av", "25"); CHECK_EVAL("5.0av", "25"); CHECK_EVAL("5e2av", "2500"); CHECK_EVAL_FAIL("a5"); CHECK_EVAL("av 5", "25"); CHECK_EVAL("2av^3", "250"); CHECK_EVAL("bb=2", "2"); CHECK_EVAL_FAIL("ab"); CHECK_EVAL("b=3", "3"); CHECK_EVAL("av b", "15"); CHECK_EVAL("av[b]", "5 b"); CHECK_EVAL("eps = 10", "10"); CHECK_EVAL("5 eps", "50"); CHECK_EVAL("Eren = 1001", "1001"); CHECK_EVAL("7 Eren", "7007"); CHECK_EVAL("Eren 5", "5005"); CHECK_EVAL("f() = 123", "123"); CHECK_EVAL("2f()", "246"); CHECK_EVAL("5 5", "55"); CHECK_INTERPRETED("av*b", "av·b"); CHECK_INTERPRETED("av*(b)", "av·b"); CHECK_INTERPRETED("sin(pi)*cos(pi)", "sin(pi)·cos(pi)"); CHECK_INTERPRETED("f()*av", "f()·av"); CHECK_INTERPRETED("sqrt(4)*av", "√(4)·av"); CHECK_INTERPRETED("av*2", "av·2"); CHECK_INTERPRETED("2*av", "2·av"); CHECK_INTERPRETED("2*3", "2×3"); // Check implicit multiplication between numbers fails // CHECK_EVAL_FAIL("10. 0.2"); CHECK_EVAL_FAIL("10 0x10"); CHECK_EVAL_FAIL("10 #10"); CHECK_EVAL_FAIL("0b104"); CHECK_EVAL_FAIL("0b10 4"); CHECK_EVAL_FAIL("0b10 0x4"); CHECK_EVAL_FAIL("0o109"); CHECK_EVAL_FAIL("0o10 9"); CHECK_EVAL_FAIL("0o10 0x9"); // CHECK_EVAL_FAIL("12.12.12"); CHECK_EVAL_FAIL("12e12.12"); CHECK_EVAL("0b10av", "10"); CHECK_EVAL("0o2av", "10"); CHECK_EVAL("5(5)", "25"); CHECK_EVAL("av sin(pi/2)", "5"); CHECK_EVAL("av sqrt(4)", "10"); CHECK_EVAL("av sqrt(av^2)", "25"); CHECK_INTERPRETED("2×sin pi", "2·sin(pi)"); CHECK_INTERPRETED("av sin(pi/2)", "av·sin(pi/2)"); CHECK_INTERPRETED("av sqrt(4)", "av·√(4)"); CHECK_INTERPRETED("av sqrt(av^2)", "av·√(av^2)"); /* Tests issue 538 */ /* 3 sin (3 pi) was evaluated but not 3 sin (3) */ CHECK_EVAL("3 sin (3 pi)", "0"); CHECK_EVAL("3 sin (3)", "0.4233600241796016663"); CHECK_INTERPRETED("3 sin (3 pi)", "3·sin(3·pi)"); CHECK_INTERPRETED("3 sin (3)", "3·sin(3)"); CHECK_EVAL("2 (2 + 1)", "6"); CHECK_EVAL("2 (av)", "10"); CHECK_INTERPRETED("2 (2 + 1)", "2·(2+1)"); CHECK_INTERPRETED("2 (av)", "2·av"); CHECK_INTERPRETED("(1+2)(3+4)", "(1+2)·(3+4)"); CHECK_INTERPRETED("(-1+2)(3-4)", "(-1+2)·(3-4)"); /* Tests issue 598 */ CHECK_EVAL("2(av)^3", "250"); CHECK_INTERPRETED("2(av)^3", "2·av^3"); CHECK_EVAL("6/2(2+1)", "9"); CHECK_INTERPRETED("6/2(2+1)", "(6/2)·(2+1)"); CHECK_INTERPRETED("1/2 sqrt(3)", "(1/2)·√(3)"); CHECK_INTERPRETED("1/2(2+3)", "(1/2)·(2+3)"); CHECK_INTERPRETED("4/2[s]", "4/2[s]"); CHECK_INTERPRETED("2/3(4/5)", "(2/3)·((4/5))"); CHECK_INTERPRETED("10\\3(2)", "(10\\3)·2"); CHECK_INTERPRETED("-2(3+4)", "-(2·(3+4))"); CHECK_INTERPRETED("~2(3)", "~(2·3)"); CHECK_INTERPRETED("2^2(2)", "2^2·2"); CHECK_INTERPRETED("2^2(2)(2)", "2^2·(2·2)"); CHECK_INTERPRETED("2^2(2*2)", "2^2·(2×2)"); CHECK_INTERPRETED("2^2(2)+3", "2^2·2+3"); CHECK_INTERPRETED("2 sin pi cos pi + 2", "2·sin(pi)·cos(pi)+2"); CHECK_INTERPRETED("1[metre second^-1]", "1[metre·second^(-1)]"); CHECK_INTERPRETED("1[second^-2]", "1[second^(-2)]"); CHECK_INTERPRETED("1/2^3", "1/2^3"); CHECK_INTERPRETED("2^12!", "2^(12!)"); CHECK_INTERPRETED("2^12.1!", "2^(12.1!)"); CHECK_INTERPRETED("1/2!", "1/(2!)"); CHECK_INTERPRETED("2^12-2", "2^12-2"); CHECK_INTERPRETED("2^12.-2", "2^12-2"); CHECK_INTERPRETED("2^12.000-2", "2^12-2"); CHECK_INTERPRETED("2^12.12", "2^(12.12)"); CHECK_INTERPRETED("2^12.000-2+1/(1×2^3×3)-2^12!+2^12.1!", "2^12-2+1/(1·(2^3)·3)-2^(12!)+2^(12.1!)"); CHECK_INTERPRETED("123.567 × 10^0", "123.567·10^0"); CHECK_INTERPRETED(QString::fromUtf8("pi −−−−−3"), "pi-3"); CHECK_INTERPRETED(QString::fromUtf8("pi −−−−−−3"), "pi+3"); CHECK_INTERPRETED("1/(1×2^3×3)", "1/(1·(2^3)·3)"); CHECK_INTERPRETED("x=1/2 sqrt(3)", "x=(1/2)·√(3)"); CHECK_INTERPRETED("gf(t)=t/2 sqrt(3)", "gf(t)=(t/2)·√(3)"); CHECK_INTERPRETED("sin 23 cos 232323×pi×pi 2", "sin(23)·cos(232323)·pi·pi·2"); CHECK_INTERPRETED("sin 23 cos 232323×pi×pi 2×cos pi×pi×23", "sin(23)·cos(232323)·pi·pi·2·cos(pi)·pi·23"); CHECK_INTERPRETED("sin 23 cos 232323×pi×pi 2×cos pi×pi×23 23 × 323", "sin(23)·cos(232323)·pi·pi·2·cos(pi)·pi·2323×323"); CHECK_DISPLAY_INTERPRETED(QString::fromUtf8("123.567 × 10�"), QString::fromUtf8("123.567 × 10�")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED(QString::fromUtf8("123.567 × 10�"), QString::fromUtf8("123.567 × 10�")); CHECK_EVAL("2^2(2)", "8"); CHECK_EVAL("2^2(2)(2)", "16"); CHECK_EVAL("2^2(2*2)", "16"); CHECK_EVAL("2^2(2)+3", "11"); CHECK_EVAL_FAIL("pi (2)"); CHECK_EVAL_KNOWN_ISSUE("2(7.5−0.5)+4(12−0.75)", "59", 1155); CHECK_EVAL_KNOWN_ISSUE("2+2(5)", "12", 1155); } void test_display_interpreted_spacing() { Settings* settings = Settings::instance(); const QString dot(MathDsl::MulDotOp); const QString multiplication = QString(MathDsl::MulCrossOp); const QString unicodeMinusSign(UnicodeChars::MinusSign); const QString dotSpaced = space + dot + space; const QString plus = space + QStringLiteral("+") + space; const QString minus = space + unicodeMinusSign + space; const QString times = space + multiplication + space; const QString divide = space + QStringLiteral("/") + space; const QString integerDivide = space + QStringLiteral("\\") + space; const QString equals = space + QStringLiteral("=") + space; const QString shiftLeft = space + QStringLiteral("<<") + space; const QString shiftRight = space + QStringLiteral(">>") + space; CHECK_DISPLAY_INTERPRETED( "sin(2·pi+3)-1+2×3·sin(pi)", QString::fromUtf8("sin(2") + dotSpaced + QStringLiteral("pi") + plus + QStringLiteral("3)") + minus + QStringLiteral("1") + plus + QStringLiteral("2") + times + QStringLiteral("3") + dotSpaced + QStringLiteral("sin(pi)")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("2×sin pi"), QString::fromUtf8("2") + dotSpaced + QStringLiteral("sin(pi)")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("2 * 358 [deg]"), QString::fromUtf8("2") + times + QStringLiteral("358") + QString::fromUtf8("°")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("2 [deg] * 3"), QStringLiteral("2") + QString::fromUtf8("°") + times + QStringLiteral("3")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("360 [°]"), QStringLiteral("360") + QString::fromUtf8("°")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("360 [deg]"), QStringLiteral("360") + QString::fromUtf8("°")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("360 [degree]"), QStringLiteral("360") + QString::fromUtf8("°")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("360 [°/s]"), QString::fromUtf8("360") + QString(MathDsl::QuantSp) + QStringLiteral("[deg/s]")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("360 [deg/s]"), QString::fromUtf8("360") + QString(MathDsl::QuantSp) + QStringLiteral("[deg/s]")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("360 [degree/s]"), QString::fromUtf8("360") + QString(MathDsl::QuantSp) + QStringLiteral("[deg/s]")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("360 [s�¹·°]"), QString::fromUtf8("360") + QString(MathDsl::QuantSp) + QString::fromUtf8("[deg · s�¹]")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("2 * x"), QString::fromUtf8("2") + dotSpaced + QStringLiteral("x")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("2 sin pi cos pi + 2"), QString::fromUtf8("2") + dotSpaced + QStringLiteral("sin(pi)") + dotSpaced + QStringLiteral("cos(pi)") + plus + QStringLiteral("2")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("2 sin pi cos pi + 2 × 23 / cos pi − sin −pi^2"), QString::fromUtf8("2") + dotSpaced + QStringLiteral("sin(pi)") + dotSpaced + QStringLiteral("cos(pi)") + plus + QStringLiteral("2") + times + QStringLiteral("23") + divide + QStringLiteral("cos(pi)") + minus + QStringLiteral("sin((") + unicodeMinusSign + QString::fromUtf8("pi)²)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("23/2+10\\3"), QStringLiteral("23") + divide + QStringLiteral("2") + plus + QStringLiteral("10") + integerDivide + QStringLiteral("3")); const bool complexNumbers = settings->complexNumbers; const char imaginaryUnit = settings->imaginaryUnit; const bool complexMode = DMath::complexMode; settings->complexNumbers = true; settings->imaginaryUnit = 'i'; CMath::setImaginaryUnitSymbol(QLatin1Char('i')); DMath::complexMode = true; eval->initializeBuiltInVariables(); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2+3i"), QStringLiteral("2+3i")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2-3i"), QString::fromUtf8("2−3i")); settings->imaginaryUnit = 'j'; CMath::setImaginaryUnitSymbol(QLatin1Char('j')); eval->initializeBuiltInVariables(); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2+3j"), QStringLiteral("2+3j")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2-3j"), QString::fromUtf8("2−3j")); DMath::complexMode = complexMode; settings->complexNumbers = complexNumbers; settings->imaginaryUnit = imaginaryUnit; CMath::setImaginaryUnitSymbol(QChar(imaginaryUnit)); eval->initializeBuiltInVariables(); CHECK_DISPLAY_INTERPRETED( QStringLiteral("1<<2"), QStringLiteral("1") + shiftLeft + QStringLiteral("2")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("1>>2"), QStringLiteral("1") + shiftRight + QStringLiteral("2")); CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("sin -12"), QString::fromUtf8("sin(") + unicodeMinusSign + QStringLiteral("12)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("1[metre second^-1]"), QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[") + QStringLiteral("m") + dotSpaced + QString::fromUtf8("s�¹]") ); CHECK_DISPLAY_INTERPRETED( QStringLiteral("1[second^-2]"), QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[") + QString::fromUtf8("s�²]")); ++eval_total_tests; eval->setExpression(QStringLiteral("4.0015061833e-3[kg*mol^-1]")); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tunit spacing with narrow no-break space\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString unitJoin = QString(MathDsl::QuantSp) + QStringLiteral("["); const QString interpretedDisplayed = Evaluator::formatInterpretedExpressionForDisplay(eval->interpretedExpression(), eval); const QString simplifiedDisplayed = DisplayFormatUtils::applyDigitGroupingForDisplay( Evaluator::formatInterpretedExpressionSimplifiedForDisplay(eval->interpretedExpression(), eval)); const QString resultDisplayed = DisplayFormatUtils::applyDigitGroupingForDisplay( NumberFormatter::format(eval->evalUpdateAns())); if (!interpretedDisplayed.contains(unitJoin) || !simplifiedDisplayed.contains(unitJoin) || !resultDisplayed.contains(unitJoin)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tunit spacing with narrow no-break space\t[NEW]" << endl << "\tInterpreted: " << interpretedDisplayed.toUtf8().constData() << endl << "\tSimplified : " << simplifiedDisplayed.toUtf8().constData() << endl << "\tResult : " << resultDisplayed.toUtf8().constData() << endl; } } ++eval_total_tests; eval->setExpression(QStringLiteral("x=0.5")); eval->evalUpdateAns(); eval->setExpression(QStringLiteral("x[m]")); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tvalue-unit spacing for variable attachment\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString interpretedDisplayed = Evaluator::formatInterpretedExpressionForDisplay(eval->interpretedExpression(), eval); const QString expected = QStringLiteral("x") + QString(MathDsl::QuantSp) + QStringLiteral("[m]"); if (interpretedDisplayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tvalue-unit spacing for variable attachment\t[NEW]" << endl << "\tDisplayed: " << interpretedDisplayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } ++eval_total_tests; eval->setExpression(QStringLiteral("ffff()=1")); eval->evalUpdateAns(); eval->setExpression(QStringLiteral("ffff()[m]")); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tvalue-unit spacing for function attachment\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString interpretedDisplayed = Evaluator::formatInterpretedExpressionForDisplay(eval->interpretedExpression(), eval); const QString expected = QStringLiteral("ffff()") + QString(MathDsl::QuantSp) + QStringLiteral("[m]"); if (interpretedDisplayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tvalue-unit spacing for function attachment\t[NEW]" << endl << "\tDisplayed: " << interpretedDisplayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } ++eval_total_tests; const QString valueUnitMulDisplayed = DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("750 · [h]")); const QString valueUnitMulExpected = QStringLiteral("750") + QString(MathDsl::QuantSp) + QStringLiteral("[h]"); if (valueUnitMulDisplayed != valueUnitMulExpected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tvalue-unit multiplication keeps bracketed unit formatting\t[NEW]" << endl << "\tDisplayed : " << valueUnitMulDisplayed.toUtf8().constData() << endl << "\tExpected : " << valueUnitMulExpected.toUtf8().constData() << endl; } ++eval_total_tests; eval->setExpression(QStringLiteral("750 · [h]")); const Quantity valueUnitMulResult = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult lines keep bracketed unit attachment\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QStringList lines = ResultLineFormatUtils::formatResultLinesForDisplay( QStringLiteral("750 · [h]"), eval->interpretedExpression(), valueUnitMulResult, true, true, eval); const QString expectedLine = QStringLiteral("750") + QString(MathDsl::QuantSp) + QStringLiteral("[h]"); if (lines.isEmpty() || lines.first() != expectedLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult lines keep bracketed unit attachment\t[NEW]" << endl << "\tFirst line: " << (lines.isEmpty() ? "" : lines.first().toUtf8().constData()) << endl << "\tExpected : " << expectedLine.toUtf8().constData() << endl; } } ++eval_total_tests; { const QString explicitGrouped = ResultLineFormatUtils::formattedExpressionLineForDisplay( QStringLiteral("4/(2[s])"), QStringLiteral("4/2[s]")); const QString expected = QStringLiteral("4") + divide + QStringLiteral("(2") + QString(MathDsl::QuantSp) + QStringLiteral("[s])"); if (explicitGrouped != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tpreserve explicit denominator grouping for unit attachment\t[NEW]" << endl << "\tDisplayed: " << explicitGrouped.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } ++eval_total_tests; { const QString implicitGrouped = ResultLineFormatUtils::formattedExpressionLineForDisplay( QStringLiteral("4/2[s]"), QStringLiteral("4/2[s]")); const QString expected = QStringLiteral("4") + divide + QStringLiteral("2") + QString(MathDsl::QuantSp) + QStringLiteral("[s]"); if (implicitGrouped != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tkeep implicit denominator unit attachment ungrouped\t[NEW]" << endl << "\tDisplayed: " << implicitGrouped.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } ++eval_total_tests; eval->setExpression(QString::fromUtf8("4[s·s]/(2[s])")); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcombine repeated unit factors in interpreted display\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString interpretedDisplayed = ResultLineFormatUtils::formattedExpressionLineForDisplay( QString::fromUtf8("4[s·s]/(2[s])"), eval->interpretedExpression(), eval); const QString expected = QStringLiteral("4") + QString(MathDsl::QuantSp) + QString::fromUtf8("[s²]") + divide + QStringLiteral("(2") + QString(MathDsl::QuantSp) + QStringLiteral("[s])"); if (interpretedDisplayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcombine repeated unit factors in interpreted display\t[NEW]" << endl << "\tDisplayed: " << interpretedDisplayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } ++eval_total_tests; eval->setExpression(QString::fromUtf8("4[s·s/s]/(2[s])")); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcancel unit factors in interpreted display\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString interpretedDisplayed = ResultLineFormatUtils::formattedExpressionLineForDisplay( QString::fromUtf8("4[s·s/s]/(2[s])"), eval->interpretedExpression(), eval); const QString expected = QStringLiteral("4") + QString(MathDsl::QuantSp) + QStringLiteral("[s]") + divide + QStringLiteral("(2") + QString(MathDsl::QuantSp) + QStringLiteral("[s])"); if (interpretedDisplayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcancel unit factors in interpreted display\t[NEW]" << endl << "\tDisplayed: " << interpretedDisplayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } CHECK_DISPLAY_INTERPRETED( QStringLiteral("cos(pi)^2"), QStringLiteral("cos") + QString::fromUtf8("²") + QStringLiteral("(pi)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("1/2^3"), QStringLiteral("1") + divide + QStringLiteral("2³")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2^12!"), QStringLiteral("2^(12!)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2^12.1!"), QStringLiteral("2^(12.1!)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("1/2!"), QStringLiteral("1") + divide + QStringLiteral("(2!)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2^12-2"), QString::fromUtf8("2¹²") + minus + QStringLiteral("2")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2^12.-2"), QString::fromUtf8("2¹²") + minus + QStringLiteral("2")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2^12.000-2"), QString::fromUtf8("2¹²") + minus + QStringLiteral("2")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2^12.000-2+1/(1×2^3×3)-2^12!+2^12.1!"), QString::fromUtf8("2¹²") + minus + QStringLiteral("2") + plus + QStringLiteral("1") + divide + QStringLiteral("(1") + times + QStringLiteral("(2³)") + times + QStringLiteral("3)") + minus + QStringLiteral("2^(12!)") + plus + QStringLiteral("2^(12.1!)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("1/(1×2^3×3)"), QStringLiteral("1") + divide + QStringLiteral("(1") + times + QStringLiteral("(2³)") + times + QStringLiteral("3)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2^123"), QString::fromUtf8("2¹²³")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("2^12.12"), QStringLiteral("2^(12.12)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2*e*e-1"), QStringLiteral("2") + dotSpaced + QString::fromUtf8("e²") + minus + QStringLiteral("1")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1+2*2*2+pi*pi^2+average(2;3;4)"), QString::fromUtf8("2³") + plus + QString::fromUtf8("pi³") + plus + QStringLiteral("average(2;3;4)") + plus + QStringLiteral("1")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QString::fromUtf8("1+2*2*2+π*π^2+average(2;3;4)"), QString::fromUtf8("2³") + plus + QString::fromUtf8("π³") + plus + QStringLiteral("average(2;3;4)") + plus + QStringLiteral("1")); CHECK_EVAL("foo1=2", "2"); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("foo1 foo1 + foo1 foo1 foo1 foo1 foo1 × 2 × foo1^4"), QString::fromUtf8("foo1²") + plus + QString::fromUtf8("foo1�") + dotSpaced + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("sin(pi)*sin(pi)"), QString::fromUtf8("sin²(pi)")); CHECK_USERFUNC_SET("f(x)=x"); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("f(pi)*f(pi)"), QString::fromUtf8("f²(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QString::fromUtf8("f(pi)·f(pi)"), QString::fromUtf8("f²(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QString::fromUtf8("f(pi) · f(pi)"), QString::fromUtf8("f²(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("sin(pi)*2*sin(pi)^2"), QString::fromUtf8("sin³(pi)") + dotSpaced + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2*cos(pi)^2*cos(pi)^2/(3*cos(pi))"), QStringLiteral("2") + slash + QStringLiteral("3") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1*cos(pi)^2*cos(pi)^2/(2*cos(pi))"), QStringLiteral("1") + slash + QStringLiteral("2") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1*cos(pi)^2*cos(pi)^2/(13*cos(pi))"), QStringLiteral("1") + slash + QStringLiteral("13") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1024*cos(pi)^2*cos(pi)^2/(64*cos(pi))"), QString(UnicodeChars::MinusSign) + QStringLiteral("16") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1024*cos(pi)^2*cos(pi)^2/(-64*cos(pi))"), QString(UnicodeChars::MinusSign) + QStringLiteral("16") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1024*cos(pi)^2*cos(pi)^2/(-64*cos(pi))"), QStringLiteral("16") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("5*cos(pi)^4/(10*cos(pi))"), QStringLiteral("1") + slash + QStringLiteral("2") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("6*cos(pi)^4/(3*cos(pi))"), QStringLiteral("2") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-6*cos(pi)^4/(3*cos(pi))"), QString(UnicodeChars::MinusSign) + QStringLiteral("2") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("6*cos(pi)^4/(-3*cos(pi))"), QString(UnicodeChars::MinusSign) + QStringLiteral("2") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-6*cos(pi)^4/(-3*cos(pi))"), QStringLiteral("2") + dotSpaced + QString::fromUtf8("cos³(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("14*cos(pi)^7/(21*cos(pi)^2)"), QStringLiteral("2") + slash + QStringLiteral("3") + dotSpaced + QString::fromUtf8("cos�(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("14*cos(pi)^7/(7*cos(pi)^2)"), QStringLiteral("2") + dotSpaced + QString::fromUtf8("cos�(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("(2*cos(pi)/(3*pi*4))*(343+4343)"), QStringLiteral("781") + dotSpaced + QStringLiteral("cos(pi)") + slash + QStringLiteral("pi")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("(2*cos(pi)/(3*pi*4))*(343+4343)+2*e"), QStringLiteral("781") + dotSpaced + QStringLiteral("cos(pi)") + slash + QStringLiteral("pi") + plus + QStringLiteral("2") + dotSpaced + QStringLiteral("e")); CHECK_EVAL("(-1024*cos(pi)^2*cos(pi)^2/(64*cos(pi)))", "16"); CHECK_EVAL("(1024*cos(pi)^2*cos(pi)^2/(-64*cos(pi)))", "16"); CHECK_EVAL("(-1024*cos(pi)^2*cos(pi)^2/(-64*cos(pi)))", "-16"); CHECK_EVAL("(1*cos(pi)^2*cos(pi)^2/(13*cos(pi)))", "-0.07692307692307692308"); CHECK_EVAL("(1*cos(pi)^2*cos(pi)^2/(2*cos(pi)))", "-0.5"); CHECK_EVAL("(2*cos(pi)^2*cos(pi)^2/(3*cos(pi)))", "-0.66666666666666666667"); CHECK_AUTOFIX("2*cos(pi)^2*cos^2(pi)/(3*cos(pi))", "2·cos(pi)^2·cos(pi)^2/(3·cos(pi))"); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1+pi pi pi/2+3"), QStringLiteral("1") + slash + QStringLiteral("2") + dotSpaced + QString::fromUtf8("pi³") + plus + QStringLiteral("4")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1+2*3/pi*pi*pi/2+3"), QStringLiteral("3") + dotSpaced + QStringLiteral("pi") + plus + QStringLiteral("4")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1+2*3/pi*pi*pi*pi/2+3"), QStringLiteral("3") + dotSpaced + QString::fromUtf8("pi²") + plus + QStringLiteral("4")); CHECK_EVAL("abc()=2", "2"); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("abc()*abc()^3/abc()"), QString::fromUtf8("abc³()")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2*abc()^4/(8*abc())"), QStringLiteral("1") + slash + QStringLiteral("4") + dotSpaced + QString::fromUtf8("abc³()")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-2*abc()^4/(8*abc())"), QString(UnicodeChars::MinusSign) + QStringLiteral("1") + slash + QStringLiteral("4") + dotSpaced + QString::fromUtf8("abc³()")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2*abc()^4/(-8*abc())"), QString(UnicodeChars::MinusSign) + QStringLiteral("1") + slash + QStringLiteral("4") + dotSpaced + QString::fromUtf8("abc³()")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-2*abc()^4/(-8*abc())"), QStringLiteral("1") + slash + QStringLiteral("4") + dotSpaced + QString::fromUtf8("abc³()")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1+(2*3/abc())*abc()*abc()/2+3*pi*pi*2+1"), QStringLiteral("3") + dotSpaced + QStringLiteral("abc()") + plus + QStringLiteral("6") + dotSpaced + QString::fromUtf8("pi²") + plus + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1+(2*3/abc())*4*abc()*abc()/2+3*pi*pi*2+1"), QStringLiteral("12") + dotSpaced + QStringLiteral("abc()") + plus + QStringLiteral("6") + dotSpaced + QString::fromUtf8("pi²") + plus + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2+3+1+2*3/e*4*e*e/2+3*pi*pi*2+1+cos(pi)^8/cos(pi)^2"), QStringLiteral("12") + dotSpaced + QStringLiteral("e") + plus + QStringLiteral("6") + dotSpaced + QString::fromUtf8("pi²") + plus + QString::fromUtf8("cos�(pi)") + plus + QStringLiteral("7")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2+3*pi*pi*pi/pi*pi*pi/pi+1+e^5/e^2-23-1/(cos(pi)*cos(pi))"), QStringLiteral("3") + dotSpaced + QString::fromUtf8("pi³") + plus + QString::fromUtf8("e³") + minus + QStringLiteral("1") + divide + QString::fromUtf8("cos²(pi)") + minus + QStringLiteral("20")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2+3*pi*pi*pi/pi*pi*pi/pi+1+e^5/e^2-23-1/(5.5+3*cos(pi)*cos(pi)+2)"), QStringLiteral("3") + dotSpaced + QString::fromUtf8("pi³") + plus + QString::fromUtf8("e³") + minus + QStringLiteral("1") + divide + QStringLiteral("(3") + dotSpaced + QString::fromUtf8("cos²(pi)") + plus + QStringLiteral("7.5)") + minus + QStringLiteral("20")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1-5.5*2+3*pi*pi*pi/pi/pi+1+e^5/e^2-23-1/(5.67+4*cos(pi)*cos(pi)+2-8/2+1)+9/3+2"), QStringLiteral("3") + dotSpaced + QStringLiteral("pi") + plus + QString::fromUtf8("e³") + minus + QStringLiteral("1") + divide + QStringLiteral("(4") + dotSpaced + QString::fromUtf8("cos²(pi)") + plus + QStringLiteral("4.67)") + minus + QStringLiteral("27")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("(12/68)[metre]"), QStringLiteral("(12") + slash + QStringLiteral("68)") + QStringLiteral("[m]")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("12/(68[metre])"), QStringLiteral("12") + divide + QStringLiteral("68") + QString(MathDsl::QuantSp) + QStringLiteral("[m]")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("12/68*1000"), QStringLiteral("176.470588235294")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2+cos(-pi^2)+pi+3+pi"), QStringLiteral("cos(") + QString(UnicodeChars::MinusSign) + QString::fromUtf8("pi²)") + plus + QStringLiteral("2") + dotSpaced + QStringLiteral("pi") + plus + QStringLiteral("5")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1+1e78+cos(pi)-1e78-1"), QStringLiteral("cos(pi)") + minus + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1-1e7+cos(pi)-1e7+1e7-1+1e7"), QStringLiteral("cos(pi)") + minus + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1-100+cos(pi)-100+100-1+100"), QStringLiteral("cos(pi)") + minus + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1-e+cos(pi)-e+e-1+e"), QStringLiteral("cos(pi)") + minus + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-2*3*2"), QString(UnicodeChars::MinusSign) + QStringLiteral("2") + times + QStringLiteral("3") + times + QStringLiteral("2")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2*3*(-2)"), QStringLiteral("2") + times + QStringLiteral("3") + times + QStringLiteral("(") + QString(UnicodeChars::MinusSign) + QStringLiteral("2)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("−1/2/cos pi −1.345 sin(−pi^2+2.5/cos(e)) × 4 sin(−pi^2+2.5/cos(e))+ 4 tan(2) ×5 tan(2) ×6 tan 2 ×7 −1.23"), QString(UnicodeChars::MinusSign) + QStringLiteral("1") + slash + QStringLiteral("2") + slash + QStringLiteral("cos(") + QStringLiteral("pi)") + minus + QStringLiteral("1.345") + dotSpaced + QStringLiteral("sin(") + QString(UnicodeChars::MinusSign) + QString::fromUtf8("pi²") + plus + QStringLiteral("2.5") + slash + QStringLiteral("cos(e))") + dotSpaced + QStringLiteral("4") + dotSpaced + QStringLiteral("sin(") + QString(UnicodeChars::MinusSign) + QString::fromUtf8("pi²") + plus + QStringLiteral("2.5") + slash + QStringLiteral("cos(e))") + plus + QStringLiteral("4") + dotSpaced + QStringLiteral("tan(2)") + dotSpaced + QStringLiteral("5") + dotSpaced + QStringLiteral("tan(2)") + dotSpaced + QStringLiteral("6") + dotSpaced + QStringLiteral("tan(2)") + dotSpaced + QStringLiteral("7") + minus + QStringLiteral("1.23")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("−1/2/cos pi −1.345 sin(−pi^2+2.5/cos(e)) × 4 sin(−pi^2+2.5/cos(e))+ 4 tan(2) ×5 tan(2) ×6 tan 2 ×7 −1.23"), QString(UnicodeChars::MinusSign) + QStringLiteral("1") + slash + QStringLiteral("2") + slash + QStringLiteral("cos(") + QStringLiteral("pi)") + minus + QStringLiteral("5.38") + dotSpaced + QStringLiteral("sin²(") + QString(UnicodeChars::MinusSign) + QString::fromUtf8("pi²") + plus + QStringLiteral("2.5") + slash + QStringLiteral("cos(e))") + plus + QStringLiteral("840") + dotSpaced + QStringLiteral("tan³(2)") + minus + QStringLiteral("1.23")); ++eval_total_tests; eval->setExpression(QStringLiteral("-1+1e78+cos(pi)-1e78-1")); Quantity largeCancellationBase = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tlarge cancellation base eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString simplifiedLargeCancellationExpr = Evaluator::simplifyInterpretedExpression(eval->interpretedExpression()); eval->setExpression(simplifiedLargeCancellationExpr); Quantity largeCancellationSimplified = eval->evalNoAssign(); const QString simplifiedValue = DMath::format(largeCancellationSimplified, Format::Fixed()); if (!eval->error().isEmpty() || simplifiedValue != QLatin1String("-3")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tlarge cancellation simplified eval\t[NEW]" << endl << "\tSimplified expression: " << simplifiedLargeCancellationExpr.toUtf8().constData() << endl << "\tResult : " << simplifiedValue.toUtf8().constData() << endl << "\tExpected : -3" << endl; } } CHECK_DISPLAY_INTERPRETED( QString::fromUtf8("12×1/2/3/4×23+23−sin(2)+23 cos(23)"), QStringLiteral("12") + times + QStringLiteral("1") + divide + QStringLiteral("2") + divide + QStringLiteral("3") + divide + QStringLiteral("4") + times + QStringLiteral("23") + plus + QStringLiteral("23") + minus + QStringLiteral("sin(2)") + plus + QStringLiteral("23") + dotSpaced + QStringLiteral("cos(23)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("x=1/2 sqrt(3)"), QStringLiteral("x") + equals + QStringLiteral("(1") + divide + QStringLiteral("2)") + dotSpaced + QStringLiteral("√(3)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("gf(t)=t/2 sqrt(3)"), QStringLiteral("gf(t)") + equals + QStringLiteral("(t") + divide + QStringLiteral("2)") + dotSpaced + QStringLiteral("√(3)")); } void test_format() { Settings* settings = Settings::instance(); const char savedResultFormat = settings->resultFormat; CHECK_EVAL("bin(123)", "0b1111011"); CHECK_EVAL("oct(123)", "0o173"); CHECK_EVAL("hex(123)", "0x7B"); CHECK_EVAL("sci(123)", "1.23e2"); CHECK_EVAL("eng(123)", "123e0"); CHECK_EVAL("sci(12341)", "1.2341e4"); CHECK_EVAL("eng(12341)", "12.341e3"); CHECK_EVAL("1+sci(123456.789)", "123457.789"); CHECK_EVAL("sci(123456.789)+1", "123457.789"); CHECK_EVAL("1+eng(123456.789)", "123457.789"); CHECK_EVAL("eng(123456.789)+1", "123457.789"); CHECK_EVAL("eng(0.000123456)", "123.456e-6"); CHECK_EVAL("eng(0.000123456; -3)", "0.123456e-3"); CHECK_EVAL("eng(0.000123456; -6)", "123.456e-6"); CHECK_EVAL("eng(0.000123456; 0)", "0.000123456"); CHECK_EVAL("eng(0.000123456; 3)", "0.000000123456e3"); CHECK_EVAL("eng(0.000123456; 6)", "0.000000000123456e6"); CHECK_EVAL("eng(0.000123456; -3)", "0.123456e-3"); CHECK_EVAL("eng(0.000123456; -12)", "123456000e-12"); CHECK_EVAL_FORMAT_EXACT("rat(0.5)", QStringLiteral("1") + slash + QStringLiteral("2")); CHECK_EVAL_FORMAT_EXACT("ratio(0.5)", QStringLiteral("1") + slash + QStringLiteral("2")); CHECK_EVAL_FORMAT_EXACT("rational(0.5)", QStringLiteral("1") + slash + QStringLiteral("2")); CHECK_EVAL_FORMAT_NO_SLASH("rat(exp(1))"); CHECK_EVAL("binpad(15)", "0b00001111"); CHECK_EVAL("hexpad(15)", "0x0F"); CHECK_EVAL("octpad(15)", "0o017"); CHECK_EVAL("binpad(1536)", "0b0000011000000000"); CHECK_EVAL("hexpad(1536)", "0x0600"); CHECK_EVAL("octpad(1536)", "0o003000"); CHECK_EVAL("binpad(1536; 32)", "0b00000000000000000000011000000000"); CHECK_EVAL("hexpad(1536; 32)", "0x00000600"); CHECK_EVAL("octpad(1536; 32)", "0o00000003000"); CHECK_EVAL("binpad(-5)", "-0b00000101"); CHECK_EVAL("hexpad(-255; 16)", "-0x00FF"); CHECK_EVAL("octpad(-9)", "-0o011"); // Explicit widths below current representation should not truncate. CHECK_EVAL("binpad(255; 7)", "0b11111111"); CHECK_EVAL("hexpad(255; 4)", "0xFF"); CHECK_EVAL("octpad(511; 8)", "0o777"); // Width rounding per radix digit size. CHECK_EVAL("binpad(5; 9)", "0b000000101"); CHECK_EVAL("hexpad(5; 9)", "0x005"); CHECK_EVAL("octpad(5; 9)", "0o005"); CHECK_EVAL("octpad(9; 10)", "0o0011"); // Zero and byte boundary transitions. CHECK_EVAL("binpad(0)", "0"); CHECK_EVAL("hexpad(0)", "0"); CHECK_EVAL("octpad(0)", "0"); CHECK_EVAL("binpad(256)", "0b0000000100000000"); CHECK_EVAL("hexpad(256)", "0x0100"); CHECK_EVAL("octpad(256)", "0o000400"); settings->resultFormat = 's'; CHECK_EVAL("bin(23.45)", "0b10111.01110011001100110011"); CHECK_EVAL("hex(23.45)", "0x17.73333333333333333333"); CHECK_EVAL("oct(23.45)", "0o27.34631463146314631463"); CHECK_EVAL("sci(23.45)", "2.345e1"); CHECK_EVAL("eng(23.45)", "23.45e0"); CHECK_EVAL("binpad(23)", "0b00010111"); CHECK_EVAL("hexpad(23)", "0x17"); CHECK_EVAL("octpad(23)", "0o027"); settings->resultFormat = 'r'; CHECK_EVAL("sci(23.45)", "2.345e1"); CHECK_EVAL("eng(23.45)", "23.45e0"); CHECK_EVAL("bin(23.45)", "0b10111.01110011001100110011"); CHECK_EVAL("hex(23.45)", "0x17.73333333333333333333"); CHECK_EVAL("oct(23.45)", "0o27.34631463146314631463"); CHECK_EVAL("binpad(23)", "0b00010111"); CHECK_EVAL("hexpad(23)", "0x17"); CHECK_EVAL("octpad(23)", "0o027"); settings->resultFormat = savedResultFormat; CHECK_EVAL_FAIL("binpad(1.5)"); CHECK_EVAL_FAIL("binpad(1[metre])"); CHECK_EVAL_FAIL("hexpad(1+j)"); CHECK_EVAL_FAIL("hexpad(10; 0)"); CHECK_EVAL_FAIL("octpad(10; -8)"); CHECK_EVAL_FAIL("binpad(10; 3.5)"); CHECK_EVAL_FAIL("binpad(10; 1e1000)"); CHECK_EVAL_FAIL("eng(1; [metre])"); CHECK_EVAL_FAIL("eng(1; 3.14)"); CHECK_EVAL_FAIL("eng(0.000123456; -1)"); CHECK_EVAL_FAIL("eng(0.000123456; -2)"); CHECK_EVAL_FAIL("eng(0.000123456; -4)"); CHECK_EVAL_FAIL("eng(0.000123456; 2)"); CHECK_EVAL("expform(3+4j)", "5 · exp(i · 0.92729521800161223243)"); CHECK_EVAL("rectform(3+4j)", "3+4i"); CHECK_EVAL("trigform(3+4j)", "5 · (cos(0.92729521800161223243) + i · sin(0.92729521800161223243))"); CHECK_EVAL("cisform(3+4j)", "5 · cis(0.92729521800161223243)"); CHECK_EVAL_FORMAT_EXACT("phasorform(3+4j)", QString::fromUtf8("5 ∠ 0.92729521800161223243")); CHECK_EVAL("cis(pi)", "-1"); const char savedComplexForm = settings->resultComplexForm; const char savedAngleUnit = settings->angleUnit; const char savedImaginaryUnit = settings->imaginaryUnit; const QString phasorOp(MathDsl::PhasorOp); const QString piOver2 = QStringLiteral("pi") + space + MathDsl::DivOp + space + QStringLiteral("2"); const QString piOver4 = QStringLiteral("pi") + space + MathDsl::DivOp + space + QStringLiteral("4"); settings->imaginaryUnit = 'i'; CMath::setImaginaryUnitSymbol(QLatin1Char('i')); settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL(QStringLiteral("3 ") + phasorOp + QStringLiteral(" pi"), "-3"); CHECK_EVAL(QStringLiteral("3 ") + phasorOp + QStringLiteral(" (pi/2)"), "3i"); CHECK_EVAL(QStringLiteral("3 ") + phasorOp + QString::fromUtf8(" 90°"), "3i"); CHECK_EVAL(QStringLiteral("3 ") + phasorOp + QStringLiteral(" 200[gon]"), "-3"); settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL(QStringLiteral("3 ") + phasorOp + QStringLiteral(" 90"), "3i"); CHECK_EVAL(QStringLiteral("2 * 3 ") + phasorOp + QStringLiteral(" 180"), "-6"); CHECK_DISPLAY_INTERPRETED( QStringLiteral("3") + phasorOp + QString::fromUtf8("90°"), QStringLiteral("3") + space + phasorOp + space + QString::fromUtf8("90°")); settings->resultComplexForm = ComplexForm::Phasor; settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT_EXACT("1+1j", QString::fromUtf8("1.4142135623730950488 ∠ (") + piOver4 + QStringLiteral(")")); CHECK_EVAL_FORMAT_EXACT("rectform(1+1j)", QString::fromUtf8("1+1i")); CHECK_EVAL_FORMAT_EXACT("expform(1+1j)", QString::fromUtf8("1.4142135623730950488 · exp(i · ") + piOver4 + QStringLiteral(")")); CHECK_EVAL_FORMAT_EXACT("trigform(1+1j)", QString::fromUtf8("1.4142135623730950488 · (cos(") + piOver4 + QString::fromUtf8(") + i · sin(") + piOver4 + QStringLiteral("))")); CHECK_EVAL_FORMAT_EXACT("cisform(1+1j)", QString::fromUtf8("1.4142135623730950488 · cis(") + piOver4 + QStringLiteral(")")); CHECK_EVAL_FORMAT_EXACT("phasorform(1+1j)", QString::fromUtf8("1.4142135623730950488 ∠ (") + piOver4 + QStringLiteral(")")); settings->imaginaryUnit = 'j'; CMath::setImaginaryUnitSymbol(QLatin1Char('j')); settings->resultComplexForm = ComplexForm::Cis; CHECK_EVAL_FORMAT_EXACT("sqrt(-1)", QString::fromUtf8("1 · cis(") + piOver2 + QStringLiteral(")")); settings->resultComplexForm = ComplexForm::Phasor; CHECK_EVAL_FORMAT_EXACT("sqrt(-1)", QString::fromUtf8("1 ∠ (") + piOver2 + QStringLiteral(")")); settings->resultComplexForm = ComplexForm::Exponential; CHECK_EVAL_FORMAT_EXACT("sqrt(-1)", QString::fromUtf8("1 · exp(j · ") + piOver2 + QStringLiteral(")")); settings->resultComplexForm = ComplexForm::Trigonometric; CHECK_EVAL_FORMAT_EXACT("sqrt(-1)", QString::fromUtf8("1 · (cos(") + piOver2 + QString::fromUtf8(") + j · sin(") + piOver2 + QStringLiteral("))")); settings->imaginaryUnit = 'i'; CMath::setImaginaryUnitSymbol(QLatin1Char('i')); settings->resultComplexForm = ComplexForm::Phasor; settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT_EXACT("1+1j", QString::fromUtf8("1.4142135623730950488 ∠ 45")); CHECK_EVAL_FORMAT_EXACT("expform(1+1j)", QString::fromUtf8("1.4142135623730950488 · exp(i · 0.78539816339744830962)")); CHECK_EVAL_FORMAT_EXACT("trigform(1+1j)", QString::fromUtf8("1.4142135623730950488 · (cos(45) + i · sin(45))")); CHECK_EVAL_FORMAT_EXACT("cisform(1+1j)", QString::fromUtf8("1.4142135623730950488 · cis(45)")); CHECK_EVAL("cis(180)", "-1"); settings->angleUnit = 'g'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT_EXACT("1+1j", QString::fromUtf8("1.4142135623730950488 ∠ 50")); settings->angleUnit = 't'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT_EXACT("1+1j", QString::fromUtf8("1.4142135623730950488 ∠ 0.125")); settings->angleUnit = 'v'; Evaluator::instance()->initializeAngleUnits(); CHECK_EVAL_FORMAT_EXACT("1+1j", QString::fromUtf8("1.4142135623730950488 ∠ 0.125")); settings->resultComplexForm = savedComplexForm; settings->angleUnit = savedAngleUnit; settings->imaginaryUnit = savedImaginaryUnit; CMath::setImaginaryUnitSymbol(QChar(savedImaginaryUnit)); Evaluator::instance()->initializeAngleUnits(); } void test_result_rounding_mode_formatting() { Settings* settings = Settings::instance(); const char savedMode = settings->resultRoundingMode; auto checkFixed0 = [&](const char* label, const char* value, const char* expected) { ++eval_total_tests; QString formatted = NumberFormatter::format( Quantity(HNumber(value)), 'f', 0, false, 'c'); formatted.replace(QString::fromUtf8("−"), "-"); if (formatted != QString::fromUtf8(expected)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tResult : " << formatted.toUtf8().constData() << endl << "\tExpected : " << expected << endl; } }; settings->resultRoundingMode = Settings::ResultRoundingHalfAwayFromZero; setRuntimeResultRoundingMode(settings->resultRoundingMode); checkFixed0("half-away +2.5", "2.5", "3"); checkFixed0("half-away -2.5", "-2.5", "-3"); CHECK_EVAL("round(2.5)", "3"); CHECK_EVAL("round(2.5[m])", "3 metre"); CHECK_EVAL("round(123.45[cm]; 1)", "1.2 metre"); CHECK_EVAL("roundeven(2.5)", "2"); CHECK_EVAL("roundeven(3.5)", "4"); CHECK_EVAL("roundeven(2.5[m])", "2 metre"); CHECK_EVAL("roundeven(124.5[cm])", "1 metre"); settings->resultRoundingMode = Settings::ResultRoundingHalfEven; setRuntimeResultRoundingMode(settings->resultRoundingMode); checkFixed0("half-even +2.5", "2.5", "2"); checkFixed0("half-even +3.5", "3.5", "4"); checkFixed0("half-even -2.5", "-2.5", "-2"); CHECK_EVAL("round(2.5)", "3"); CHECK_EVAL("round(2.5[m])", "3 metre"); CHECK_EVAL("roundeven(-2.5)", "-2"); settings->resultRoundingMode = Settings::ResultRoundingTowardZero; setRuntimeResultRoundingMode(settings->resultRoundingMode); checkFixed0("toward-zero +2.9", "2.9", "2"); checkFixed0("toward-zero -2.9", "-2.9", "-2"); checkFixed0("toward-zero +2.5", "2.5", "2"); CHECK_EVAL("trunc(2.9[m])", "2 metre"); CHECK_EVAL("trunc(-2.9[m])", "-2 metre"); CHECK_EVAL("trunc(123.45[cm]; 1)", "1.2 metre"); settings->resultRoundingMode = Settings::ResultRoundingTowardPositiveInfinity; setRuntimeResultRoundingMode(settings->resultRoundingMode); checkFixed0("toward-plus-inf +2.1", "2.1", "3"); checkFixed0("toward-plus-inf -2.1", "-2.1", "-2"); CHECK_EVAL("ceil(2.1[m])", "3 metre"); CHECK_EVAL("ceil(-2.1[m])", "-2 metre"); CHECK_EVAL("ceil(123.1[cm])", "2 metre"); settings->resultRoundingMode = Settings::ResultRoundingTowardNegativeInfinity; setRuntimeResultRoundingMode(settings->resultRoundingMode); checkFixed0("toward-minus-inf +2.9", "2.9", "2"); checkFixed0("toward-minus-inf -2.1", "-2.1", "-3"); CHECK_EVAL("floor(2.9[m])", "2 metre"); CHECK_EVAL("floor(-2.1[m])", "-3 metre"); CHECK_EVAL("floor(123.9[cm])", "1 metre"); settings->resultRoundingMode = savedMode; setRuntimeResultRoundingMode(savedMode); } void test_datetime() { // NOTE We cannot test datetime() with only 1 argument as it depends on current timezone (and DST?) CHECK_EVAL("datetime(1538242871; 0)", "20180929.174111"); CHECK_EVAL("datetime(1514761200; 1)", "20180101.000000"); CHECK_EVAL("datetime(1514764800; -1)", "20171231.230000"); CHECK_EVAL("datetime(1551464695;13.75)", "20190302.080955"); // GMT +13:45 CHECK_EVAL("datetime(1551464695; -3.5)", "20190301.145455"); // GMT -03:30 } void test_epoch() { // NOTE We avoid testing epoch() with only 1 argument because it depends on local timezone (and DST). CHECK_EVAL("epoch(20180929.174111; 0)", "1538242871"); CHECK_EVAL("epoch(20180101.000000; 1)", "1514761200"); CHECK_EVAL("epoch(20171231.230000; -1)", "1514764800"); CHECK_EVAL("epoch(20190302.080955; 13.75)", "1551464695"); CHECK_EVAL("epoch(20190301.145455; -3.5)", "1551464695"); } void test_expression_operator_normalization() { const QString normalized = EditorUtils::normalizeExpressionOperators( QString::fromUtf8("1+2 8/4÷2 " "9-4 9�4 9﹣4 9�4 9‑4 9–4 9—4 9―4 9�4 " "2∗3·4·5∙6*7⨉8⨯9✕10✖11")); const std::string normalizedStd = normalized.toStdString(); ++eval_total_tests; DisplayErrorOnMismatch(__FILE__, __LINE__, "normalizeExpressionOperators", normalizedStd, "1+2 8⧸4⧸2 " "9−4 9−4 9−4 9−4 9−4 9−4 9−4 9−4 9−4 " "2×3×4×5×6×7×8×9×10×11", eval_failed_tests, eval_new_failed_tests); const QStringList parsed = EditorUtils::parsePastedExpressions( QString::fromUtf8("1+2\n" "8/4\n" "10÷2\n" "9-4\n" "9�4\n" "9﹣4\n" "9�4\n" "9‑4\n" "9–4\n" "9—4\n" "9―4\n" "9�4\n" "2∗3\n" "4·5\n\n" "6✖7")); if (parsed.size() != 15 || parsed.at(0) != QString::fromUtf8("1+2") || parsed.at(1) != QString::fromUtf8("8⧸4") || parsed.at(2) != QString::fromUtf8("10⧸2") || parsed.at(3) != QString::fromUtf8("9−4") || parsed.at(4) != QString::fromUtf8("9−4") || parsed.at(5) != QString::fromUtf8("9−4") || parsed.at(6) != QString::fromUtf8("9−4") || parsed.at(7) != QString::fromUtf8("9−4") || parsed.at(8) != QString::fromUtf8("9−4") || parsed.at(9) != QString::fromUtf8("9−4") || parsed.at(10) != QString::fromUtf8("9−4") || parsed.at(11) != QString::fromUtf8("9−4") || parsed.at(12) != QString::fromUtf8("2×3") || parsed.at(13) != QString::fromUtf8("4×5") || parsed.at(14) != QString::fromUtf8("6×7")) { ++eval_total_tests; ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tparsePastedExpressions\t[NEW]" << endl << "\tResult : " << parsed.join("|").toUtf8().constData() << endl << "\tExpected : 1+2|8⧸4|10⧸2|" "9−4|9−4|9−4|9−4|9−4|9−4|9−4|9−4|9−4|" "2×3|4×5|6×7" << endl; } else { ++eval_total_tests; } const QString editorNormalized = EditorUtils::normalizeExpressionOperatorsForEditorInput( QString::fromUtf8("2·3 4·5 6*7 8/4 10÷2 9⧸3 � � � � Ω μ sqrt cbrt asqrt cbrtfoo")); const std::string editorNormalizedStd = editorNormalized.toStdString(); ++eval_total_tests; DisplayErrorOnMismatch(__FILE__, __LINE__, "normalizeExpressionOperatorsForEditorInput", editorNormalizedStd, "2·3 4·5 6×7 8/4 10/2 9/3 π π π π Ω µ √ ∛ asqrt cbrtfoo", eval_failed_tests, eval_new_failed_tests); const QString implicitMulWithLatinLetter = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QStringLiteral("a")); { const QString expected = QStringLiteral("a"); ++eval_total_tests; if (implicitMulWithLatinLetter != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped implicit multiplication after digit (latin)\t[NEW]" << endl << "\tResult : " << implicitMulWithLatinLetter.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString implicitMulWithNonLatinLetter = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QString::fromUtf8("2"), 1, QString::fromUtf8("β")); { const QString expected = QString::fromUtf8("β"); ++eval_total_tests; if (implicitMulWithNonLatinLetter != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped implicit multiplication after digit (non-latin)\t[NEW]" << endl << "\tResult : " << implicitMulWithNonLatinLetter.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString implicitMulWithSuperscriptDigit = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QString::fromUtf8("2³"), 2, QStringLiteral("x")); { const QString expected = QStringLiteral("x"); ++eval_total_tests; if (implicitMulWithSuperscriptDigit != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped implicit multiplication after superscript digit\t[NEW]" << endl << "\tResult : " << implicitMulWithSuperscriptDigit.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString implicitMulWithOpeningParAfterDigit = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QStringLiteral("(")); { const QString expected = QString(MathDsl::MulCrossWrapSp) + QString(MathDsl::MulCrossOp) + QString(MathDsl::MulCrossWrapSp) + QStringLiteral("("); ++eval_total_tests; if (implicitMulWithOpeningParAfterDigit != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped implicit multiplication before opening par after digit\t[NEW]" << endl << "\tResult : " << implicitMulWithOpeningParAfterDigit.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString implicitMulWithOpeningBracketAfterLetterAndSpaces = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QString::fromUtf8("β "), 4, QStringLiteral("[")); { const QString expected = QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp) + QStringLiteral("["); ++eval_total_tests; if (implicitMulWithOpeningBracketAfterLetterAndSpaces != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped implicit multiplication before opening bracket after non-latin letter and spaces\t[NEW]" << endl << "\tResult : " << implicitMulWithOpeningBracketAfterLetterAndSpaces.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString implicitMulWithOpeningParAfterSuperscriptAndSpaces = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QString::fromUtf8("2³ "), 5, QStringLiteral("(")); { const QString expected = QString(MathDsl::MulCrossWrapSp) + QString(MathDsl::MulCrossOp) + QString(MathDsl::MulCrossWrapSp) + QStringLiteral("("); ++eval_total_tests; if (implicitMulWithOpeningParAfterSuperscriptAndSpaces != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped implicit multiplication before opening par after superscript and spaces\t[NEW]" << endl << "\tResult : " << implicitMulWithOpeningParAfterSuperscriptAndSpaces.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString implicitMulWithOpeningParAfterVariableSuperscript = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QString::fromUtf8("pi³"), 3, QStringLiteral("(")); { const QString expected = QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp) + QStringLiteral("("); ++eval_total_tests; if (implicitMulWithOpeningParAfterVariableSuperscript != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped implicit multiplication before opening par after variable superscript\t[NEW]" << endl << "\tResult : " << implicitMulWithOpeningParAfterVariableSuperscript.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString noImplicitMulWithOpeningParAfterOperator = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2+"), 2, QStringLiteral("(")); { const QString expected = QStringLiteral("("); ++eval_total_tests; if (noImplicitMulWithOpeningParAfterOperator != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tno implicit multiplication before opening par after operator\t[NEW]" << endl << "\tResult : " << noImplicitMulWithOpeningParAfterOperator.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString noImplicitMulWithLetterAfterLetter = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("ab"), 2, QStringLiteral("c")); { const QString expected = QStringLiteral("c"); ++eval_total_tests; if (noImplicitMulWithLetterAfterLetter != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tno implicit multiplication with letter typed after letter\t[NEW]" << endl << "\tResult : " << noImplicitMulWithLetterAfterLetter.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString noImplicitMulWithDigitAfterLetter = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("a"), 1, QStringLiteral("2")); { const QString expected = QStringLiteral("2"); ++eval_total_tests; if (noImplicitMulWithDigitAfterLetter != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tno implicit multiplication with digit typed after letter\t[NEW]" << endl << "\tResult : " << noImplicitMulWithDigitAfterLetter.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedAdditionAfterDigit = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QStringLiteral("+")); { const QString expected = QString(MathDsl::AddWrap) + QString(MathDsl::AddOp) + QString(MathDsl::AddWrap); ++eval_total_tests; if (typedAdditionAfterDigit != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped addition after digit uses configured spacing\t[NEW]" << endl << "\tResult : " << typedAdditionAfterDigit.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedSubtractionAfterSuperscriptDigit = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QString::fromUtf8("2³"), 2, QString::fromUtf8("−")); { const QString expected = QString(MathDsl::SubWrapSp) + QString(MathDsl::SubOp) + QString(MathDsl::SubWrapSp); ++eval_total_tests; if (typedSubtractionAfterSuperscriptDigit != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped subtraction after superscript uses configured spacing\t[NEW]" << endl << "\tResult : " << typedSubtractionAfterSuperscriptDigit.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedDivisionAfterDigit = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QStringLiteral("/")); { const QString expected = QString(MathDsl::DivWrap) + QString(MathDsl::DivOp) + QString(MathDsl::DivWrap); ++eval_total_tests; if (typedDivisionAfterDigit != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped division after digit uses configured spacing\t[NEW]" << endl << "\tResult : " << typedDivisionAfterDigit.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedMultiplicationAfterDigit = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QString::fromUtf8("×")); { const QString expected = QString(MathDsl::MulCrossWrapSp) + QString(MathDsl::MulCrossOp) + QString(MathDsl::MulCrossWrapSp); ++eval_total_tests; if (typedMultiplicationAfterDigit != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped multiplication after digit uses configured spacing\t[NEW]" << endl << "\tResult : " << typedMultiplicationAfterDigit.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedAdditionAfterNonLatinLetterAndSpaces = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QString::fromUtf8("β "), 4, QStringLiteral("+")); { const QString expected = QString(MathDsl::AddOp) + QString(MathDsl::AddWrap); ++eval_total_tests; if (typedAdditionAfterNonLatinLetterAndSpaces != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped addition after non-latin letter and spaces uses configured spacing\t[NEW]" << endl << "\tResult : " << typedAdditionAfterNonLatinLetterAndSpaces.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedDivisionAfterSuperscriptAndSpaces = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QString::fromUtf8("2³ "), 5, QStringLiteral("/")); { const QString expected = QString(MathDsl::DivOp) + QString(MathDsl::DivWrap); ++eval_total_tests; if (typedDivisionAfterSuperscriptAndSpaces != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped division after superscript and spaces uses configured spacing\t[NEW]" << endl << "\tResult : " << typedDivisionAfterSuperscriptAndSpaces.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedSubtractionAfterClosingParenAndSpaces = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("(2) "), 5, QString::fromUtf8("−")); { const QString expected = QString(MathDsl::SubOp) + QString(MathDsl::SubWrapSp); ++eval_total_tests; if (typedSubtractionAfterClosingParenAndSpaces != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped subtraction after closing paren and spaces uses configured spacing\t[NEW]" << endl << "\tResult : " << typedSubtractionAfterClosingParenAndSpaces.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedAdditionAfterClosingBracket = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("[2]"), 3, QStringLiteral("+")); { const QString expected = QString(MathDsl::AddWrap) + QString(MathDsl::AddOp) + QString(MathDsl::AddWrap); ++eval_total_tests; if (typedAdditionAfterClosingBracket != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped addition after closing bracket uses configured spacing\t[NEW]" << endl << "\tResult : " << typedAdditionAfterClosingBracket.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedAdditionAfterLetter = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("a"), 1, QStringLiteral("+")); { const QString expected = QString(MathDsl::AddWrap) + QString(MathDsl::AddOp) + QString(MathDsl::AddWrap); ++eval_total_tests; if (typedAdditionAfterLetter != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped addition after letter uses configured spacing\t[NEW]" << endl << "\tResult : " << typedAdditionAfterLetter.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString typedAdditionAfterTrailingSpace = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2 "), 2, QStringLiteral("+")); { const QString expected = QString(MathDsl::AddOp) + QString(MathDsl::AddWrap); ++eval_total_tests; if (typedAdditionAfterTrailingSpace != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped addition after trailing space avoids duplicate left space\t[NEW]" << endl << "\tResult : " << typedAdditionAfterTrailingSpace.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString scientificNotationWithLowerE = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QStringLiteral("e")); { const QString expected = QStringLiteral("e"); ++eval_total_tests; if (scientificNotationWithLowerE != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped scientific notation lower e exception\t[NEW]" << endl << "\tResult : " << scientificNotationWithLowerE.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString scientificNotationWithUpperE = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QStringLiteral("E")); { const QString expected = QStringLiteral("E"); ++eval_total_tests; if (scientificNotationWithUpperE != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped scientific notation upper E exception\t[NEW]" << endl << "\tResult : " << scientificNotationWithUpperE.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString inOperatorPrefixWithLowerI = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QStringLiteral("i")); { const QString expected = QStringLiteral(" i"); ++eval_total_tests; if (inOperatorPrefixWithLowerI != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped in-operator prefix lower i exception\t[NEW]" << endl << "\tResult : " << inOperatorPrefixWithLowerI.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString inOperatorPrefixWithUpperI = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2"), 1, QStringLiteral("I")); { const QString expected = QStringLiteral(" I"); ++eval_total_tests; if (inOperatorPrefixWithUpperI != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped in-operator prefix upper I exception\t[NEW]" << endl << "\tResult : " << inOperatorPrefixWithUpperI.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString inOperatorPrefixWithExistingSpace = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("2 "), 2, QStringLiteral("i")); { const QString expected = QStringLiteral("i"); ++eval_total_tests; if (inOperatorPrefixWithExistingSpace != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped in-operator prefix keeps existing spacing\t[NEW]" << endl << "\tResult : " << inOperatorPrefixWithExistingSpace.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } const QString plainIdentifierContinuationWithI = EditorUtils::adjustedTypedTextForImplicitMultiplicationAfterDigit( QStringLiteral("p"), 1, QStringLiteral("i")); { const QString expected = QStringLiteral("i"); ++eval_total_tests; if (plainIdentifierContinuationWithI != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\ttyped i after identifier keeps plain identifier continuation\t[NEW]" << endl << "\tResult : " << plainIdentifierContinuationWithI.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } ++eval_total_tests; if (!EditorUtils::shouldIgnoreTypedSpaceAfterDigit(QStringLiteral("2"), 1) || !EditorUtils::shouldIgnoreTypedSpaceAfterDigit(QStringLiteral("pi"), 2) || !EditorUtils::shouldIgnoreTypedSpaceAfterDigit(QStringLiteral("cos(3)"), 6) || !EditorUtils::shouldIgnoreTypedSpaceAfterDigit(QString::fromUtf8("2³"), 2) || EditorUtils::shouldIgnoreTypedSpaceAfterDigit(QStringLiteral("2+"), 2)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tignore typed space after digit/superscript\t[NEW]" << endl << "\tResult : mismatch" << endl << "\tExpected : true,true,true,true,false" << endl; } const QStringList parsedForEditor = EditorUtils::parsePastedExpressionsForEditorInput( QString::fromUtf8("2·3\n" "4·5\n" "6*7\n" "8/4\n" "10÷2\n" "9⧸3\n" "�+1\n" "�+1\n" "�+1\n" "�+1\n" "sqrt(4)\n" "cbrt(8)\n" "asqrt(4)")); if (parsedForEditor.size() != 13 || parsedForEditor.at(0) != QString::fromUtf8("2·3") || parsedForEditor.at(1) != QString::fromUtf8("4·5") || parsedForEditor.at(2) != QString::fromUtf8("6×7") || parsedForEditor.at(3) != QString::fromUtf8("8/4") || parsedForEditor.at(4) != QString::fromUtf8("10/2") || parsedForEditor.at(5) != QString::fromUtf8("9/3") || parsedForEditor.at(6) != QString::fromUtf8("π+1") || parsedForEditor.at(7) != QString::fromUtf8("π+1") || parsedForEditor.at(8) != QString::fromUtf8("π+1") || parsedForEditor.at(9) != QString::fromUtf8("π+1") || parsedForEditor.at(10) != QString::fromUtf8("√(4)") || parsedForEditor.at(11) != QString::fromUtf8("∛(8)") || parsedForEditor.at(12) != QString::fromUtf8("asqrt(4)")) { ++eval_total_tests; ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tparsePastedExpressionsForEditorInput\t[NEW]" << endl << "\tResult : " << parsedForEditor.join("|").toUtf8().constData() << endl << "\tExpected : 2·3|4·5|6×7|8/4|10/2|9/3|π+1|π+1|π+1|π+1|√(4)|∛(8)|asqrt(4)" << endl; } else { ++eval_total_tests; } const QString piDisplay = UnicodeChars::normalizePiForDisplay( QString::fromUtf8("pi � � � � alpha_pi beta pi2 pi² -pi +pi/pi")); ++eval_total_tests; DisplayErrorOnMismatch(__FILE__, __LINE__, "normalizePiForDisplay", piDisplay.toStdString(), "π π π π π alpha_pi beta pi2 π² -π +π/π", eval_failed_tests, eval_new_failed_tests); ++eval_total_tests; eval->setExpression(QString::fromUtf8("2pi pi^2")); eval->evalUpdateAns(); const QString threadExpressionDisplay = UnicodeChars::normalizePiForDisplay( Evaluator::formatInterpretedExpressionForDisplay(eval->interpretedExpression(), eval)); DisplayErrorOnMismatch(__FILE__, __LINE__, "normalizePiForDisplay thread expression", threadExpressionDisplay.toStdString(), "2 · π · π²", eval_failed_tests, eval_new_failed_tests); ++eval_total_tests; QString ignoredTrailing; const bool ignoreTrailingPlus = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1+2+"), &ignoredTrailing); if (!ignoreTrailingPlus || ignoredTrailing != QString::fromUtf8("1+2")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken trailing plus\t[NEW]" << endl << "\tResult : " << (ignoreTrailingPlus ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1+2" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingMultiPlus = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1++++"), &ignoredTrailing); if (!ignoreTrailingMultiPlus || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken multi plus\t[NEW]" << endl << "\tResult : " << (ignoreTrailingMultiPlus ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingMultiMinus = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("2-------"), &ignoredTrailing); if (!ignoreTrailingMultiMinus || ignoredTrailing != QString::fromUtf8("2")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken multi minus\t[NEW]" << endl << "\tResult : " << (ignoreTrailingMultiMinus ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 2" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingSingleMinus = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1-"), &ignoredTrailing); if (!ignoreTrailingSingleMinus || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken single minus\t[NEW]" << endl << "\tResult : " << (ignoreTrailingSingleMinus ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingDoubleMinus = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1--"), &ignoredTrailing); if (!ignoreTrailingDoubleMinus || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken double minus\t[NEW]" << endl << "\tResult : " << (ignoreTrailingDoubleMinus ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingTripleMinus = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1---"), &ignoredTrailing); if (!ignoreTrailingTripleMinus || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken triple minus\t[NEW]" << endl << "\tResult : " << (ignoreTrailingTripleMinus ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingUnicodeMinus = EditorUtils::expressionWithoutIgnorableTrailingToken( QString::fromUtf8("1−−−"), &ignoredTrailing); if (!ignoreTrailingUnicodeMinus || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken unicode minus\t[NEW]" << endl << "\tResult : " << (ignoreTrailingUnicodeMinus ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingMixedPlusMinusA = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1++--++-"), &ignoredTrailing); if (!ignoreTrailingMixedPlusMinusA || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken mixed +/- A\t[NEW]" << endl << "\tResult : " << (ignoreTrailingMixedPlusMinusA ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingMixedPlusMinusB = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1--+++-"), &ignoredTrailing); if (!ignoreTrailingMixedPlusMinusB || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken mixed +/- B\t[NEW]" << endl << "\tResult : " << (ignoreTrailingMixedPlusMinusB ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingSemicolon = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("average(2;3;4;"), &ignoredTrailing); if (!ignoreTrailingSemicolon || ignoredTrailing != QString::fromUtf8("average(2;3;4")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken trailing semicolon\t[NEW]" << endl << "\tResult : " << (ignoreTrailingSemicolon ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : average(2;3;4" << endl; } ignoredTrailing.clear(); const bool ignoreTrailingSingleStar = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1*"), &ignoredTrailing); if (!ignoreTrailingSingleStar || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken single star\t[NEW]" << endl << "\tResult : " << (ignoreTrailingSingleStar ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingDoubleStar = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1**"), &ignoredTrailing); if (!ignoreTrailingDoubleStar || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken double star\t[NEW]" << endl << "\tResult : " << (ignoreTrailingDoubleStar ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingCaret = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1^"), &ignoredTrailing); if (!ignoreTrailingCaret || ignoredTrailing != QString::fromUtf8("1")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken caret\t[NEW]" << endl << "\tResult : " << (ignoreTrailingCaret ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 1" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingBackslash = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("3\\"), &ignoredTrailing); if (!ignoreTrailingBackslash || ignoredTrailing != QString::fromUtf8("3")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken trailing backslash\t[NEW]" << endl << "\tResult : " << (ignoreTrailingBackslash ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 3" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingSinglePar = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("4("), &ignoredTrailing); if (!ignoreTrailingSinglePar || ignoredTrailing != QString::fromUtf8("4")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken single parenthesis\t[NEW]" << endl << "\tResult : " << (ignoreTrailingSinglePar ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 4" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingMultiPar = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("5(((("), &ignoredTrailing); if (!ignoreTrailingMultiPar || ignoredTrailing != QString::fromUtf8("5")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken multi parenthesis\t[NEW]" << endl << "\tResult : " << (ignoreTrailingMultiPar ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 5" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingDiv = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("3/"), &ignoredTrailing); if (!ignoreTrailingDiv || ignoredTrailing != QString::fromUtf8("3")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken trailing slash\t[NEW]" << endl << "\tResult : " << (ignoreTrailingDiv ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 3" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool ignoreTrailingPar = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("5+cos pi ("), &ignoredTrailing); if (!ignoreTrailingPar || ignoredTrailing != QString::fromUtf8("5+cos pi")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken trailing open parenthesis\t[NEW]" << endl << "\tResult : " << (ignoreTrailingPar ? ignoredTrailing : QString("")).toUtf8().constData() << endl << "\tExpected : 5+cos pi" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool rejectTrailingStar = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1+2+*"), &ignoredTrailing); if (rejectTrailingStar) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken reject +*\t[NEW]" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool rejectTrailingDoubleDiv = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("3//"), &ignoredTrailing); if (rejectTrailingDoubleDiv) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken reject //\t[NEW]" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool rejectInvalidParen = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("5+cos pi ()"), &ignoredTrailing); if (rejectInvalidParen) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken reject ()\t[NEW]" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool rejectTrailingTripleStar = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1***"), &ignoredTrailing); if (rejectTrailingTripleStar) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken reject ***\t[NEW]" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool rejectClosingParen = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1)"), &ignoredTrailing); if (rejectClosingParen) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken reject )\t[NEW]" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool rejectClosingParens = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("1)))"), &ignoredTrailing); if (rejectClosingParens) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken reject )))\t[NEW]" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool rejectOnlyPlus = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("+"), &ignoredTrailing); if (rejectOnlyPlus) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken reject +\t[NEW]" << endl; } ++eval_total_tests; ignoredTrailing.clear(); const bool rejectOnlyMixedPlusMinus = EditorUtils::expressionWithoutIgnorableTrailingToken(QString::fromUtf8("-+-+-++--+"), &ignoredTrailing); if (rejectOnlyMixedPlusMinus) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\texpressionWithoutIgnorableTrailingToken reject mixed +/- only\t[NEW]" << endl; } } void test_session_history_limit() { Session defaultSession; ++eval_total_tests; if (defaultSession.historyLimit() != 1000) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tdefault history limit\t[NEW]" << endl; } Session session; session.setHistoryLimit(3); ++eval_total_tests; if (session.nextHistoryEntryReachesLimit()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\thistory limit warning before first entry\t[NEW]" << endl; } session.addHistoryEntry(HistoryEntry("1+1", Quantity(2))); session.addHistoryEntry(HistoryEntry("2+2", Quantity(4))); ++eval_total_tests; if (!session.nextHistoryEntryReachesLimit()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\thistory limit warning at final free slot\t[NEW]" << endl; } session.addHistoryEntry(HistoryEntry("3+3", Quantity(6))); ++eval_total_tests; if (session.nextHistoryEntryReachesLimit()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\thistory limit warning after limit reached\t[NEW]" << endl; } session.addHistoryEntry(HistoryEntry("4+4", Quantity(8))); session.addHistoryEntry(HistoryEntry("5+5", Quantity(10))); ++eval_total_tests; const QList history = session.historyToList(); if (history.size() != 3 || history.at(0).expr() != "3+3" || history.at(2).expr() != "5+5") { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\thistory trim on add\t[NEW]" << endl; } QJsonObject serializedSession; session.serialize(serializedSession); ++eval_total_tests; const QString serializedSchema = serializedSession.value(QLatin1String(SessionJsonKeys::Schema)).toString(); const QString serializedId = serializedSession.value(QLatin1String(SessionJsonKeys::Id)).toString(); if (serializedSession.value(QLatin1String(SessionJsonKeys::Limit)).toInt(-1) != 3 || serializedSchema != QLatin1String(SessionJsonKeys::SchemaDialect) || serializedId != QLatin1String(SessionJsonKeys::SchemaId) || serializedSession.contains(QLatin1String("scheme"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsession serializes schema metadata and history limit\t[NEW]" << endl; } session.setHistoryLimit(2); ++eval_total_tests; const QList trimmedHistory = session.historyToList(); if (trimmedHistory.size() != 2 || trimmedHistory.at(0).expr() != "4+4" || trimmedHistory.at(1).expr() != "5+5") { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\thistory trim on apply limit\t[NEW]" << endl; } QJsonObject json = sessionJson(); QJsonArray histEntries; for (int i = 1; i <= 4; ++i) { QJsonObject entry; HistoryEntry(QString::number(i), Quantity(i)).serialize(entry); histEntries.append(entry); } json[QLatin1String(SessionJsonKeys::Limit)] = 2; json["history"] = histEntries; Session loaded; loaded.deSerialize(json, false); ++eval_total_tests; const QList loadedHistory = loaded.historyToList(); if (loaded.historyLimit() != 2 || loadedHistory.size() != 2 || loadedHistory.at(0).expr() != "3" || loadedHistory.at(1).expr() != "4") { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\thistory trim on deserialize\t[NEW]" << endl; } QJsonObject jsonWithCommentTail = sessionJson(); QJsonArray histWithCommentTail; { QJsonObject entry; HistoryEntry("21", Quantity(21)).serialize(entry); histWithCommentTail.append(entry); } { QJsonObject entry; HistoryEntry("? foo", CMath::nan()).serialize(entry); histWithCommentTail.append(entry); } jsonWithCommentTail["history"] = histWithCommentTail; Session loadedWithCommentTail; loadedWithCommentTail.setHistoryLimit(0); loadedWithCommentTail.deSerialize(jsonWithCommentTail, false); ++eval_total_tests; if (!loadedWithCommentTail.hasVariable("ans") || DMath::format(loadedWithCommentTail.getVariable("ans").value(), Format::Fixed()) != "21") { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tans recovery on deserialize with comment tail\t[NEW]" << endl; } Session unlimited; unlimited.setHistoryLimit(0); for (int i = 0; i < 4; ++i) unlimited.addHistoryEntry(HistoryEntry(QString("u%1").arg(i), Quantity(i))); ++eval_total_tests; if (unlimited.historyToList().size() != 4) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\thistory unlimited mode\t[NEW]" << endl; } } void test_session_deserialize_without_history() { Session source; Session restored; Evaluator* sourceEvaluator = source.evaluator(); Evaluator* restoredEvaluator = restored.evaluator(); source.addVariable(Variable("persistedVar", Quantity(42), Variable::UserDefined, "Saved variable")); source.addUserFunction(UserFunction("persistedFunc", QStringList() << "x", "x+1")); source.addHistoryEntry(HistoryEntry("1+1", Quantity(2))); source.setEditorText("2+2"); QJsonObject json; source.serialize(json); json.remove("history"); restored.deSerialize(json, false); ++eval_total_tests; const bool hasVar = restored.hasVariable("persistedVar") && DMath::format(restored.getVariable("persistedVar").value(), Format::Fixed()) == "42"; const bool hasVarDescription = restored.hasVariable("persistedVar") && restored.getVariable("persistedVar").description() == "Saved variable"; const bool hasFunc = restored.hasUserFunction("persistedFunc"); const bool omitsEditorText = restored.editorText().isEmpty(); const bool hasNoHistory = restored.historyToList().isEmpty(); if (!hasVar || !hasVarDescription || !hasFunc || !omitsEditorText || !hasNoHistory) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsession deserialize without history keeps vars/functions\t[NEW]" << endl; } ++eval_total_tests; if (sourceEvaluator != source.evaluator() || restoredEvaluator != restored.evaluator()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsession deserialize keeps evaluators session-owned\t[NEW]" << endl; } } void test_session_owns_distinct_evaluator_state() { Session left; Session right; left.evaluator()->setExpression(QStringLiteral("left_only = 11")); left.evaluator()->evalUpdateAns(); right.evaluator()->setExpression(QStringLiteral("right_only = 22")); right.evaluator()->evalUpdateAns(); ++eval_total_tests; if (left.evaluator() == right.evaluator() || !left.evaluator()->hasVariable(QStringLiteral("left_only")) || left.evaluator()->hasVariable(QStringLiteral("right_only")) || !right.evaluator()->hasVariable(QStringLiteral("right_only")) || right.evaluator()->hasVariable(QStringLiteral("left_only"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsessions own isolated evaluators\t[NEW]" << endl; } } void test_session_globals_deserialize_preserves_existing_definitions() { Settings* settings = Settings::instance(); const QString previousDefinitions = settings->startupUserDefinitions; settings->startupUserDefinitions.clear(); QJsonObject sessionWithGlobals = sessionJson(); sessionWithGlobals[QLatin1String(SessionJsonKeys::Session)] = QStringLiteral("Untitled-1"); QJsonArray globals; globals.append(QStringLiteral("global_var=42")); sessionWithGlobals[QLatin1String(SessionJsonKeys::Globals)] = globals; Session first; first.deSerialize(sessionWithGlobals, false); QJsonObject sessionWithEmptyGlobals = sessionJson(); sessionWithEmptyGlobals[QLatin1String(SessionJsonKeys::Session)] = QStringLiteral("Untitled-2"); sessionWithEmptyGlobals[QLatin1String(SessionJsonKeys::Globals)] = QJsonArray(); Session second; second.deSerialize(sessionWithEmptyGlobals, false); ++eval_total_tests; if (settings->startupUserDefinitions != QStringLiteral("global_var=42")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsession empty globals do not clear loaded globals\t[NEW]" << endl << "\tActual : " << settings->startupUserDefinitions.toUtf8().constData() << endl << "\tExpected : global_var=42" << endl; } QJsonObject sessionWithOtherGlobals = sessionJson(); sessionWithOtherGlobals[QLatin1String(SessionJsonKeys::Session)] = QStringLiteral("Untitled-3"); QJsonArray otherGlobals; otherGlobals.append(QStringLiteral("other_global=24")); sessionWithOtherGlobals[QLatin1String(SessionJsonKeys::Globals)] = otherGlobals; Session third; third.deSerialize(sessionWithOtherGlobals, false); ++eval_total_tests; if (settings->startupUserDefinitions != QStringLiteral("global_var=42")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsession globals do not replace existing startup definitions\t[NEW]" << endl << "\tActual : " << settings->startupUserDefinitions.toUtf8().constData() << endl << "\tExpected : global_var=42" << endl; } settings->startupUserDefinitions = previousDefinitions; } void test_session_deserialize_rejects_invalid_schema_without_mutating() { Session session; session.addHistoryEntry(HistoryEntry("1+1", Quantity(2))); session.addVariable(Variable("kept", Quantity(7), Variable::UserDefined)); session.setEditorText("kept editor"); QJsonObject invalid; invalid[QLatin1String(SessionJsonKeys::Schema)] = QLatin1String(SessionJsonKeys::SchemaDialect); invalid[QLatin1String(SessionJsonKeys::Id)] = QStringLiteral("https://speedcrunch.org/schemas/session-v2.schema.json"); invalid[QLatin1String(SessionJsonKeys::History)] = QJsonArray(); invalid[QLatin1String(SessionJsonKeys::Variables)] = QJsonArray(); const int deserializeResult = session.deSerialize(invalid, false); ++eval_total_tests; const bool historyKept = session.historySize() == 1 && session.historyEntryAt(0).expr() == QStringLiteral("1+1"); const bool variableKept = session.hasVariable(QStringLiteral("kept")) && DMath::format(session.getVariable(QStringLiteral("kept")).value(), Format::Fixed()) == "7"; if (deserializeResult != false || !historyKept || !variableKept || session.editorText() != QStringLiteral("kept editor")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsession deserialize rejects invalid schema without mutating\t[NEW]" << endl; } QJsonObject obsolete = sessionJson(); obsolete[QLatin1String("scheme")] = 1; obsolete[QLatin1String(SessionJsonKeys::History)] = QJsonArray(); obsolete[QLatin1String(SessionJsonKeys::Variables)] = QJsonArray(); const int obsoleteResult = session.deSerialize(obsolete, false); ++eval_total_tests; const bool historyStillKept = session.historySize() == 1 && session.historyEntryAt(0).expr() == QStringLiteral("1+1"); const bool variableStillKept = session.hasVariable(QStringLiteral("kept")) && DMath::format(session.getVariable(QStringLiteral("kept")).value(), Format::Fixed()) == "7"; if (obsoleteResult != false || !historyStillKept || !variableStillKept || session.editorText() != QStringLiteral("kept editor")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsession deserialize rejects obsolete scheme key without mutating\t[NEW]" << endl; } } void test_function_usage_tooltip() { auto checkTooltip = [](const QString& expression, int cursorPosition, const QString& expected, const char* label) { ++eval_total_tests; const QString actual = FunctionTooltipUtils::activeFunctionUsageTooltip( eval, expression, cursorPosition); if (actual != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tActual : " << actual.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } }; checkTooltip( "gcd(", 4, "gcd(n1; n2; ...)", "tooltip shows built-in usage with HTML subscript" ); checkTooltip( "gcd(3;", 6, "gcd(n1; n2; ...)", "tooltip highlights second parametre after first separator" ); checkTooltip( "gcd(3;4;", 8, "gcd(n1; n2; ...)", "tooltip highlights variadic placeholder when typing further arguments" ); checkTooltip( "gcd(abs(3);", 11, "gcd(n1; n2; ...)", "tooltip tracks outer function in nested calls" ); checkTooltip( "lcm(", 4, "lcm(n1; n2; ...)", "tooltip shows usage for lcm" ); checkTooltip( "lcm", 3, "lcm(n1; n2; ...)", "tooltip shows usage when cursor is after typed function name" ); checkTooltip( "mass()", 5, "mass(mol; formula)", "tooltip shows usage when cursor is inside empty function call" ); checkTooltip( "mass()", 6, "mass(mol; formula)", "tooltip shows usage at closing parenthesis boundary of empty function call" ); checkTooltip( "2+3", 3, "", "no tooltip outside function calls" ); eval->setExpression("fff(pao;barro;gis)=pao+barro+gis"); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsetup user function for tooltip\t[NEW]" << endl << "\tError: " << eval->error().toUtf8().constData() << endl; return; } checkTooltip( "fff(1;", 6, "fff(pao;barro;gis)", "tooltip highlights current user-function parametre" ); } void test_grouped_numeric_literal_display_format() { Settings* settings = Settings::instance(); const Settings::NumberFormatStyle oldNumberFormatStyle = settings->numberFormatStyle; const bool oldDigitGroupingIntegerPartOnly = settings->digitGroupingIntegerPartOnly; struct GroupingCase { Settings::NumberFormatStyle style; QString separator; bool indian; }; const GroupingCase cases[] = { {Settings::NumberFormatThreeDigitCommaDot, QStringLiteral(","), false}, {Settings::NumberFormatThreeDigitUnderscoreDot, QStringLiteral("_"), false}, {Settings::NumberFormatIndianCommaDot, QStringLiteral(","), true} }; for (const auto& groupingCase : cases) { settings->numberFormatStyle = groupingCase.style; settings->applyNumberFormatStyle(); settings->digitGroupingIntegerPartOnly = false; ++eval_total_tests; const QString groupedLiteral = DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("234936")); const QString expectedLiteral = groupingCase.indian ? QString(QStringLiteral("2") + groupingCase.separator + QStringLiteral("34") + groupingCase.separator + QStringLiteral("936")) : QString(QStringLiteral("234") + groupingCase.separator + QStringLiteral("936")); if (groupedLiteral != expectedLiteral) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tgroup numeric literal for display\t[NEW]" << endl << "\tStyle : " << static_cast(groupingCase.style) << endl << "\tResult : " << groupedLiteral.toUtf8().constData() << endl << "\tExpected : " << expectedLiteral.toUtf8().constData() << endl; } ++eval_total_tests; const QString groupedFractional = DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("12345.6789")); const QString expectedFractional = (groupingCase.indian ? QStringLiteral("12") + groupingCase.separator + QStringLiteral("345.") : QStringLiteral("12") + groupingCase.separator + QStringLiteral("345.")) + QStringLiteral("678") + groupingCase.separator + QStringLiteral("9"); if (groupedFractional != expectedFractional) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tgroup fractional when integer-only is off\t[NEW]" << endl << "\tStyle : " << static_cast(groupingCase.style) << endl << "\tResult : " << groupedFractional.toUtf8().constData() << endl << "\tExpected : " << expectedFractional.toUtf8().constData() << endl; } settings->digitGroupingIntegerPartOnly = true; ++eval_total_tests; const QString groupedIntegerOnly = DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("12345.6789")); const QString expectedIntegerOnly = QStringLiteral("12") + groupingCase.separator + QStringLiteral("345.6789"); if (groupedIntegerOnly != expectedIntegerOnly) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tkeep fractional ungrouped when integer-only is on\t[NEW]" << endl << "\tStyle : " << static_cast(groupingCase.style) << endl << "\tResult : " << groupedIntegerOnly.toUtf8().constData() << endl << "\tExpected : " << expectedIntegerOnly.toUtf8().constData() << endl; } settings->digitGroupingIntegerPartOnly = false; eval->setExpression("234234+234+234+234"); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate grouped dedup baseline\t[NEW]" << endl << "\tStyle : " << static_cast(groupingCase.style) << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString groupedResult = DisplayFormatUtils::applyDigitGroupingForDisplay(NumberFormatter::format(value)); if (groupedResult != expectedLiteral) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tgrouped literal matches formatted result\t[NEW]" << endl << "\tStyle : " << static_cast(groupingCase.style) << endl << "\tLiteral : " << expectedLiteral.toUtf8().constData() << endl << "\tResult : " << groupedResult.toUtf8().constData() << endl; } } } settings->numberFormatStyle = oldNumberFormatStyle; settings->applyNumberFormatStyle(); settings->digitGroupingIntegerPartOnly = oldDigitGroupingIntegerPartOnly; } void test_pasted_standalone_numeric_literal_reformatting() { Settings* settings = Settings::instance(); const Settings::NumberFormatStyle oldStyle = settings->numberFormatStyle; const bool oldIntegerOnly = settings->digitGroupingIntegerPartOnly; settings->numberFormatStyle = Settings::NumberFormatNoGroupingDot; settings->applyNumberFormatStyle(); settings->digitGroupingIntegerPartOnly = true; QString formatted; ++eval_total_tests; const bool okFlatDotDecimal = NumberFormatter::tryFormatStandaloneNumericLiteralForDisplay( QStringLiteral("15.999"), &formatted); if (!okFlatDotDecimal || formatted != QStringLiteral("15.999")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tpreserve decimal dot in no-grouping dot style paste\t[NEW]" << endl << "\tResult : " << (okFlatDotDecimal ? formatted : QString("")).toUtf8().constData() << endl << "\tExpected : 15.999" << endl; } settings->numberFormatStyle = Settings::NumberFormatNoGroupingComma; settings->applyNumberFormatStyle(); settings->digitGroupingIntegerPartOnly = true; ++eval_total_tests; const bool okFlatCommaDecimal = NumberFormatter::tryFormatStandaloneNumericLiteralForDisplay( QStringLiteral("15,999"), &formatted); if (!okFlatCommaDecimal || formatted != QStringLiteral("15,999")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tpreserve decimal comma in no-grouping comma style paste\t[NEW]" << endl << "\tResult : " << (okFlatCommaDecimal ? formatted : QString("")).toUtf8().constData() << endl << "\tExpected : 15,999" << endl; } settings->numberFormatStyle = Settings::NumberFormatThreeDigitDotComma; settings->applyNumberFormatStyle(); settings->digitGroupingIntegerPartOnly = true; ++eval_total_tests; const bool okUsGrouped = NumberFormatter::tryFormatStandaloneNumericLiteralForDisplay( QStringLiteral("1,234,567.890123"), &formatted); if (!okUsGrouped || formatted != QStringLiteral("1.234.567,890123")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tformat pasted standalone grouped decimal\t[NEW]" << endl << "\tResult : " << (okUsGrouped ? formatted : QString("")).toUtf8().constData() << endl << "\tExpected : 1.234.567,890123" << endl; } ++eval_total_tests; const bool okPlain = NumberFormatter::tryFormatStandaloneNumericLiteralForDisplay( QStringLiteral("-1234567.890123"), &formatted); if (!okPlain || formatted != QStringLiteral("-1.234.567,890123")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tformat pasted standalone plain decimal\t[NEW]" << endl << "\tResult : " << (okPlain ? formatted : QString("")).toUtf8().constData() << endl << "\tExpected : -1.234.567,890123" << endl; } ++eval_total_tests; const bool okExpression = NumberFormatter::tryFormatStandaloneNumericLiteralForDisplay( QStringLiteral("1,234+5"), &formatted); if (okExpression) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tdo not treat expressions as standalone numeric literal\t[NEW]" << endl << "\tResult : " << formatted.toUtf8().constData() << endl << "\tExpected : " << endl; } ++eval_total_tests; const bool okUpperExponent = NumberFormatter::tryFormatStandaloneNumericLiteralForDisplay( QStringLiteral("1.23E+45"), &formatted); if (!okUpperExponent || formatted != QStringLiteral("1,23e+45")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalize standalone numeric exponent marker to lower e\t[NEW]" << endl << "\tResult : " << (okUpperExponent ? formatted : QString("")).toUtf8().constData() << endl << "\tExpected : 1,23e+45" << endl; } settings->numberFormatStyle = oldStyle; settings->applyNumberFormatStyle(); settings->digitGroupingIntegerPartOnly = oldIntegerOnly; } void test_display_root_aliases_for_result_lines() { ++eval_total_tests; const QString sqrtDisplay = DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("sqrt(2)/2")); if (sqrtDisplay != QString::fromUtf8("√(2) / 2")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tformat sqrt alias for display\t[NEW]" << endl << "\tResult : " << sqrtDisplay.toUtf8().constData() << endl << "\tExpected : √(2) / 2" << endl; } ++eval_total_tests; const QString cbrtDisplay = DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("cbrt(8)")); if (cbrtDisplay != QString::fromUtf8("∛(8)")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tformat cbrt alias for display\t[NEW]" << endl << "\tResult : " << cbrtDisplay.toUtf8().constData() << endl << "\tExpected : ∛(8)" << endl; } ++eval_total_tests; const QString untouchedIdentifier = DisplayFormatUtils::applyDigitGroupingForDisplay(QStringLiteral("asqrt(2)+cbrtfoo(8)")); if (untouchedIdentifier != QStringLiteral("asqrt(2) + cbrtfoo(8)")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tdo not rewrite root-like identifiers\t[NEW]" << endl << "\tResult : " << untouchedIdentifier.toUtf8().constData() << endl << "\tExpected : asqrt(2) + cbrtfoo(8)" << endl; } } void test_display_spacing_stability_for_unit_conversion() { ++eval_total_tests; const QString input = QStringLiteral("3") + QString(MathDsl::QuantSp) + QString::fromUtf8("[kg·m²/s�] → [kg·m²/s�]"); const QString output = DisplayFormatUtils::applyDigitGroupingForDisplay(input); if (output != input) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tunit conversion display stability\t[NEW]" << endl << "\tResult : " << output.toUtf8().constData() << endl << "\tExpected : " << input.toUtf8().constData() << endl; } } void test_display_conversion_with_unicode_spaces_and_cross_units() { ++eval_total_tests; const QString expr = QString::fromUtf8("3 [kg×m²/s�]�→�[kg×m²/s�]"); eval->setExpression(eval->autoFix(expr)); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tunicode conversion display\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } const QString interpreted = eval->interpretedExpression(); const QString displayed = DisplayFormatUtils::applyDigitGroupingForDisplay( Evaluator::formatInterpretedExpressionForDisplay(interpreted, eval)); const QString expected = QStringLiteral("3") + QString(MathDsl::QuantSp) + QString::fromUtf8("[kg·m²/s�] → kg·m²/s�"); if (displayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tunicode conversion display\t[NEW]" << endl << "\tDisplayed : " << displayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl << "\tDisplayed code points: " << toCodePointList(displayed) << endl << "\tExpected code points: " << toCodePointList(expected) << endl; } ++eval_total_tests; const QString simplifiedDisplayed = DisplayFormatUtils::applyDigitGroupingForDisplay( Evaluator::formatInterpretedExpressionSimplifiedForDisplay(interpreted, eval)); const bool corrupted = simplifiedDisplayed.contains(QStringLiteral("//")) || simplifiedDisplayed.contains(QStringLiteral("··")) || hasSpacedOperatorsInsideUnitBrackets(simplifiedDisplayed); if (corrupted) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tunicode conversion simplified display\t[NEW]" << endl << "\tSimplified: " << simplifiedDisplayed.toUtf8().constData() << endl << "\tSimplified code points: " << toCodePointList(simplifiedDisplayed) << endl; } } void test_preserve_brackets_for_displayed_conversion_target() { ++eval_total_tests; const QString source = QString::fromUtf8("3[kg·m²/s�] -> [kg·m²/s�]"); const QString interpretedDisplayed = QStringLiteral("3") + QString(MathDsl::QuantSp) + QString::fromUtf8("[kg·m²/s�] → kg·m²/s�"); const QString expected = QStringLiteral("3") + QString(MathDsl::QuantSp) + QString::fromUtf8("[kg·m²/s�] → [kg·m²/s�]"); const QString preserved = DisplayFormatUtils::preserveConversionTargetBracketsForDisplay( interpretedDisplayed, source); if (preserved != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tpreserve conversion target brackets\t[NEW]" << endl << "\tResult : " << preserved.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } void test_preserve_brackets_for_displayed_conversion_target_without_source_hint() { ++eval_total_tests; const QString source = QString::fromUtf8("3[m] -> km"); const QString interpretedDisplayed = QStringLiteral("3") + QString(MathDsl::QuantSp) + QString::fromUtf8("[m] → km"); const QString expected = QStringLiteral("3") + QString(MathDsl::QuantSp) + QString::fromUtf8("[m] → [km]"); const QString preserved = DisplayFormatUtils::preserveConversionTargetBracketsForDisplay( interpretedDisplayed, source); if (preserved != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tpreserve conversion target brackets without source hint\t[NEW]" << endl << "\tResult : " << preserved.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } void test_result_display_preserves_conversion_target_brackets() { Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry( QString::fromUtf8("3 [m] → [km]"), Quantity(3) / Quantity(1000), QString::fromUtf8("3[m]→km"))); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString displayed = display.document()->findBlockByNumber(0).text(); const QString expected = QStringLiteral("3") + QString(MathDsl::QuantSp) + QString::fromUtf8("[m] → [km]"); if (displayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display preserve conversion target brackets\t[NEW]" << endl << "\tDisplayed: " << displayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } session->clearHistory(); } void test_result_display_preserves_converted_sexagesimal_expression_line() { Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); const QString expression = QString::fromUtf8("179°59′59″ → [rad]"); eval->setExpression(expression); eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate converted sexagesimal expression display\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString displayed = ResultLineFormatUtils::formattedExpressionLineForDisplay( expression, eval->interpretedExpression(), eval); const QString expected = QString::fromUtf8("179°59′59″ → [rad]"); ++eval_total_tests; if (displayed != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tpreserve converted sexagesimal expression line\t[NEW]" << endl << "\tDisplayed : " << displayed.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl << "\tInterpreted: " << eval->interpretedExpression().toUtf8().constData() << endl; } } settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); } void test_result_display_adds_normalized_sexagesimal_simplification_line() { Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; settings->simplifyResultExpressions = true; eval->setExpression(QStringLiteral("1:120:3600")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate sexagesimal normalization case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->simplifyResultExpressions = oldSimplifyResultExpressions; return; } Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry( QStringLiteral("1:120:3600"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString simplifiedLine = display.document()->findBlockByNumber(1).text(); if (simplifiedLine != QStringLiteral("= 4:00:00")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalized sexagesimal line\t[NEW]" << endl << "\tLine : " << simplifiedLine.toUtf8().constData() << endl << "\tExpected : = 4:00:00" << endl; } ++eval_total_tests; const QString scalarLine = display.document()->findBlockByNumber(2).text(); if (!scalarLine.contains(QStringLiteral("s")) || scalarLine.contains(QString(MathDsl::UnitStart)) || scalarLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tscalar seconds line keeps unit\t[NEW]" << endl << "\tLine : " << scalarLine.toUtf8().constData() << endl << "\tExpected : contains s without []" << endl; } session->clearHistory(); settings->simplifyResultExpressions = oldSimplifyResultExpressions; } void test_result_display_highlights_simplified_expression_line() { Settings* settings = Settings::instance(); const bool oldSyntaxHighlighting = settings->syntaxHighlighting; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const QString oldColorScheme = settings->colorScheme; const QString oldCustomColorSchemeJson = settings->customColorSchemeJson; const char oldAngleUnit = settings->angleUnit; settings->syntaxHighlighting = true; settings->simplifyResultExpressions = true; settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); QJsonObject colors; colors.insert(QStringLiteral("number"), QStringLiteral("#101010")); colors.insert(QStringLiteral("function"), QStringLiteral("#123456")); colors.insert(QStringLiteral("operator"), QStringLiteral("#654321")); colors.insert(QStringLiteral("result"), QStringLiteral("#abcdef")); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(colors); eval->setExpression(QStringLiteral("2 * cos(pi) * sin(pi) * cos(pi)")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\thighlight simplified expression line setup\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry( QStringLiteral("2 * cos(pi) * sin(pi) * cos(pi)"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); display.rehighlight(); auto colorAt = [](const QTextBlock& block, int position) { const auto formats = block.layout()->formats(); for (const QTextLayout::FormatRange& range : formats) { if (position >= range.start && position < range.start + range.length) return range.format.foreground().color(); } return QColor(); }; const QTextBlock simplifiedBlock = display.document()->findBlockByNumber(1); const QTextBlock resultBlock = display.document()->findBlockByNumber(2); const int simplifiedFunctionPos = simplifiedBlock.text().indexOf(QString::fromUtf8("cos²")); const int simplifiedExponentPos = simplifiedBlock.text().indexOf(QString::fromUtf8("²")); const int resultTextPos = resultBlock.text().startsWith(QStringLiteral("= ")) ? 2 : 1; ++eval_total_tests; const QColor simplifiedFunctionColor = colorAt(simplifiedBlock, simplifiedFunctionPos); if (simplifiedFunctionPos < 0 || simplifiedFunctionColor != QColor(QStringLiteral("#123456"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsimplified expression line uses syntax highlighting\t[NEW]" << endl << "\tLine : " << simplifiedBlock.text().toUtf8().constData() << endl << "\tColor: " << simplifiedFunctionColor.name().toUtf8().constData() << endl; } ++eval_total_tests; const QColor simplifiedExponentColor = colorAt(simplifiedBlock, simplifiedExponentPos); if (simplifiedExponentPos < 0 || simplifiedExponentColor != QColor(QStringLiteral("#101010"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsimplified expression function exponent uses number highlighting\t[NEW]" << endl << "\tLine : " << simplifiedBlock.text().toUtf8().constData() << endl << "\tColor: " << simplifiedExponentColor.name().toUtf8().constData() << endl; } ++eval_total_tests; const QColor resultColor = colorAt(resultBlock, resultTextPos); if (resultColor != QColor(QStringLiteral("#abcdef"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tformatted result line keeps result highlighting\t[NEW]" << endl << "\tLine : " << resultBlock.text().toUtf8().constData() << endl << "\tColor: " << resultColor.name().toUtf8().constData() << endl; } session->clearHistory(); } settings->syntaxHighlighting = oldSyntaxHighlighting; settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); } void test_result_display_highlights_primary_result_with_extra_result_line() { Settings* settings = Settings::instance(); const bool oldSyntaxHighlighting = settings->syntaxHighlighting; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const QString oldColorScheme = settings->colorScheme; const QString oldCustomColorSchemeJson = settings->customColorSchemeJson; const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; const bool oldSecondaryResultEnabled = settings->secondaryResultEnabled; const char oldAlternativeResultFormat = settings->alternativeResultFormat; const int oldSecondaryResultPrecision = settings->secondaryResultPrecision; const bool oldComplexNumbers = settings->complexNumbers; const bool oldSecondaryComplexNumbers = settings->secondaryComplexNumbers; const char oldSecondaryResultComplexForm = settings->secondaryResultComplexForm; settings->syntaxHighlighting = true; settings->simplifyResultExpressions = true; settings->multipleResultLinesEnabled = true; settings->secondaryResultEnabled = true; settings->alternativeResultFormat = 'b'; settings->secondaryResultPrecision = -1; settings->complexNumbers = false; settings->secondaryComplexNumbers = false; settings->secondaryResultComplexForm = ComplexForm::Rectangular; QJsonObject colors; colors.insert(QStringLiteral("number"), QStringLiteral("#101010")); colors.insert(QStringLiteral("operator"), QStringLiteral("#654321")); colors.insert(QStringLiteral("result"), QStringLiteral("#abcdef")); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(colors); Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry(QStringLiteral("12 + 1212"), Quantity(1224))); TestableResultDisplay display; display.resize(800, 600); display.refresh(); display.rehighlight(); auto colorAt = [](const QTextBlock& block, int position) { const auto formats = block.layout()->formats(); for (const QTextLayout::FormatRange& range : formats) { if (position >= range.start && position < range.start + range.length) return range.format.foreground().color(); } return QColor(); }; const QTextBlock primaryResultBlock = display.document()->findBlockByNumber(1); const QTextBlock secondaryResultBlock = display.document()->findBlockByNumber(2); ++eval_total_tests; const QColor primaryResultColor = colorAt(primaryResultBlock, 2); if (primaryResultColor != QColor(QStringLiteral("#abcdef"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tprimary result keeps result highlighting with extra result line\t[NEW]" << endl << "\tLine : " << primaryResultBlock.text().toUtf8().constData() << endl << "\tColor: " << primaryResultColor.name().toUtf8().constData() << endl; } ++eval_total_tests; const QColor secondaryResultColor = colorAt(secondaryResultBlock, 2); if (secondaryResultColor != QColor(QStringLiteral("#abcdef"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsecondary result keeps result highlighting\t[NEW]" << endl << "\tLine : " << secondaryResultBlock.text().toUtf8().constData() << endl << "\tColor: " << secondaryResultColor.name().toUtf8().constData() << endl; } session->clearHistory(); settings->syntaxHighlighting = oldSyntaxHighlighting; settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; settings->secondaryResultEnabled = oldSecondaryResultEnabled; settings->alternativeResultFormat = oldAlternativeResultFormat; settings->secondaryResultPrecision = oldSecondaryResultPrecision; settings->complexNumbers = oldComplexNumbers; settings->secondaryComplexNumbers = oldSecondaryComplexNumbers; settings->secondaryResultComplexForm = oldSecondaryResultComplexForm; } void test_result_display_highlights_primary_sexagesimal_result_with_extra_result_line() { Settings* settings = Settings::instance(); const bool oldSyntaxHighlighting = settings->syntaxHighlighting; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const QString oldColorScheme = settings->colorScheme; const QString oldCustomColorSchemeJson = settings->customColorSchemeJson; const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; const bool oldSecondaryResultEnabled = settings->secondaryResultEnabled; const char oldResultFormat = settings->resultFormat; const char oldAlternativeResultFormat = settings->alternativeResultFormat; const int oldResultPrecision = settings->resultPrecision; const int oldSecondaryResultPrecision = settings->secondaryResultPrecision; const bool oldComplexNumbers = settings->complexNumbers; const bool oldSecondaryComplexNumbers = settings->secondaryComplexNumbers; const char oldResultComplexForm = settings->resultComplexForm; const char oldSecondaryResultComplexForm = settings->secondaryResultComplexForm; settings->syntaxHighlighting = true; settings->simplifyResultExpressions = true; settings->multipleResultLinesEnabled = true; settings->secondaryResultEnabled = true; settings->resultFormat = 's'; settings->alternativeResultFormat = 'h'; settings->resultPrecision = -1; settings->secondaryResultPrecision = -1; settings->complexNumbers = false; settings->secondaryComplexNumbers = false; settings->resultComplexForm = ComplexForm::Rectangular; settings->secondaryResultComplexForm = ComplexForm::Rectangular; QJsonObject colors; colors.insert(QStringLiteral("number"), QStringLiteral("#101010")); colors.insert(QStringLiteral("operator"), QStringLiteral("#654321")); colors.insert(QStringLiteral("result"), QStringLiteral("#abcdef")); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(colors); Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry(QStringLiteral("12"), Quantity(12))); TestableResultDisplay display; display.resize(800, 600); display.refresh(); display.rehighlight(); auto colorAt = [](const QTextBlock& block, int position) { const auto formats = block.layout()->formats(); for (const QTextLayout::FormatRange& range : formats) { if (position >= range.start && position < range.start + range.length) return range.format.foreground().color(); } return QColor(); }; const QTextBlock sexagesimalResultBlock = display.document()->findBlockByNumber(1); const QTextBlock hexResultBlock = display.document()->findBlockByNumber(2); ++eval_total_tests; const QColor sexagesimalResultColor = colorAt(sexagesimalResultBlock, 2); if (sexagesimalResultColor != QColor(QStringLiteral("#abcdef"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tprimary sexagesimal result keeps result highlighting with extra result line\t[NEW]" << endl << "\tLine : " << sexagesimalResultBlock.text().toUtf8().constData() << endl << "\tColor: " << sexagesimalResultColor.name().toUtf8().constData() << endl; } ++eval_total_tests; const QColor hexResultColor = colorAt(hexResultBlock, 2); if (hexResultColor != QColor(QStringLiteral("#abcdef"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\textra hex result keeps result highlighting after sexagesimal result\t[NEW]" << endl << "\tLine : " << hexResultBlock.text().toUtf8().constData() << endl << "\tColor: " << hexResultColor.name().toUtf8().constData() << endl; } session->clearHistory(); settings->syntaxHighlighting = oldSyntaxHighlighting; settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; settings->secondaryResultEnabled = oldSecondaryResultEnabled; settings->resultFormat = oldResultFormat; settings->alternativeResultFormat = oldAlternativeResultFormat; settings->resultPrecision = oldResultPrecision; settings->secondaryResultPrecision = oldSecondaryResultPrecision; settings->complexNumbers = oldComplexNumbers; settings->secondaryComplexNumbers = oldSecondaryComplexNumbers; settings->resultComplexForm = oldResultComplexForm; settings->secondaryResultComplexForm = oldSecondaryResultComplexForm; } void test_result_display_highlights_primary_radian_result_with_pi_factor_line() { Settings* settings = Settings::instance(); const bool oldSyntaxHighlighting = settings->syntaxHighlighting; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const QString oldColorScheme = settings->colorScheme; const QString oldCustomColorSchemeJson = settings->customColorSchemeJson; const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; const bool oldSecondaryResultEnabled = settings->secondaryResultEnabled; const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; const char oldAlternativeResultFormat = settings->alternativeResultFormat; const int oldResultPrecision = settings->resultPrecision; const int oldSecondaryResultPrecision = settings->secondaryResultPrecision; const bool oldComplexNumbers = settings->complexNumbers; const bool oldSecondaryComplexNumbers = settings->secondaryComplexNumbers; const char oldResultComplexForm = settings->resultComplexForm; const char oldSecondaryResultComplexForm = settings->secondaryResultComplexForm; settings->syntaxHighlighting = true; settings->simplifyResultExpressions = true; settings->multipleResultLinesEnabled = true; settings->secondaryResultEnabled = true; settings->angleUnit = 'r'; settings->resultFormat = 'g'; settings->alternativeResultFormat = 'p'; settings->resultPrecision = -1; settings->secondaryResultPrecision = -1; settings->complexNumbers = false; settings->secondaryComplexNumbers = false; settings->resultComplexForm = ComplexForm::Rectangular; settings->secondaryResultComplexForm = ComplexForm::Rectangular; Evaluator::instance()->initializeAngleUnits(); QJsonObject colors; colors.insert(QStringLiteral("number"), QStringLiteral("#101010")); colors.insert(QStringLiteral("operator"), QStringLiteral("#654321")); colors.insert(QStringLiteral("result"), QStringLiteral("#abcdef")); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(colors); eval->setExpression(QString::fromUtf8("12°")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate radian pi-factor display case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry(QString::fromUtf8("12°"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); display.rehighlight(); auto colorAt = [](const QTextBlock& block, int position) { const auto formats = block.layout()->formats(); for (const QTextLayout::FormatRange& range : formats) { if (position >= range.start && position < range.start + range.length) return range.format.foreground().color(); } return QColor(); }; const QTextBlock radianResultBlock = display.document()->findBlockByNumber(1); const QTextBlock piFactorResultBlock = display.document()->findBlockByNumber(2); ++eval_total_tests; const QColor radianResultColor = colorAt(radianResultBlock, 2); if (radianResultColor != QColor(QStringLiteral("#abcdef"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tprimary radian result keeps result highlighting with pi-factor result line\t[NEW]" << endl << "\tLine : " << radianResultBlock.text().toUtf8().constData() << endl << "\tColor: " << radianResultColor.name().toUtf8().constData() << endl; } ++eval_total_tests; const QColor piFactorResultColor = colorAt(piFactorResultBlock, 2); if (piFactorResultColor != QColor(QStringLiteral("#abcdef"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tpi-factor result keeps result highlighting\t[NEW]" << endl << "\tLine : " << piFactorResultBlock.text().toUtf8().constData() << endl << "\tColor: " << piFactorResultColor.name().toUtf8().constData() << endl; } session->clearHistory(); } settings->syntaxHighlighting = oldSyntaxHighlighting; settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; settings->secondaryResultEnabled = oldSecondaryResultEnabled; settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; settings->alternativeResultFormat = oldAlternativeResultFormat; settings->resultPrecision = oldResultPrecision; settings->secondaryResultPrecision = oldSecondaryResultPrecision; settings->complexNumbers = oldComplexNumbers; settings->secondaryComplexNumbers = oldSecondaryComplexNumbers; settings->resultComplexForm = oldResultComplexForm; settings->secondaryResultComplexForm = oldSecondaryResultComplexForm; Evaluator::instance()->initializeAngleUnits(); } void test_result_display_adds_normalized_sexagesimal_simplification_line_for_arithmetic() { Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; settings->simplifyResultExpressions = true; eval->setExpression(QStringLiteral("23:50:40 + 5:20:50")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate sexagesimal arithmetic normalization case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->simplifyResultExpressions = oldSimplifyResultExpressions; return; } Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry( QStringLiteral("23:50:40 + 5:20:50"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString simplifiedLine = display.document()->findBlockByNumber(1).text(); if (simplifiedLine != QStringLiteral("= 29:11:30")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalized sexagesimal arithmetic line\t[NEW]" << endl << "\tLine : " << simplifiedLine.toUtf8().constData() << endl << "\tExpected : = 29:11:30" << endl; } ++eval_total_tests; const QString scalarLine = display.document()->findBlockByNumber(2).text(); if (!scalarLine.contains(QStringLiteral("s")) || scalarLine.contains(QString(MathDsl::UnitStart)) || scalarLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tscalar seconds arithmetic line keeps unit\t[NEW]" << endl << "\tLine : " << scalarLine.toUtf8().constData() << endl << "\tExpected : contains s without []" << endl; } session->clearHistory(); settings->simplifyResultExpressions = oldSimplifyResultExpressions; } void test_result_display_preserves_fractional_seconds_in_normalized_sexagesimal_line() { Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; settings->simplifyResultExpressions = true; eval->setExpression(QStringLiteral("12:34:56.75 + 1:25:30.50")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate fractional sexagesimal arithmetic normalization case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->simplifyResultExpressions = oldSimplifyResultExpressions; return; } Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry( QStringLiteral("12:34:56.75 + 1:25:30.50"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString simplifiedLine = display.document()->findBlockByNumber(1).text(); if (simplifiedLine != QStringLiteral("= 14:00:27.25")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalized sexagesimal arithmetic fractional seconds line\t[NEW]" << endl << "\tLine : " << simplifiedLine.toUtf8().constData() << endl << "\tExpected : = 14:00:27.25" << endl; } ++eval_total_tests; const QString scalarLine = display.document()->findBlockByNumber(2).text(); if (!scalarLine.contains(QStringLiteral("50427.25")) || !scalarLine.contains(QStringLiteral("s")) || scalarLine.contains(QString(MathDsl::UnitStart)) || scalarLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tscalar seconds fractional arithmetic line keeps value and unit\t[NEW]" << endl << "\tLine : " << scalarLine.toUtf8().constData() << endl << "\tExpected : contains 50427.25 and s without []" << endl; } session->clearHistory(); settings->simplifyResultExpressions = oldSimplifyResultExpressions; } void test_result_display_normalized_sexagesimal_line_with_time_conversion_target() { Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; settings->simplifyResultExpressions = true; eval->setExpression(QStringLiteral("5:59:59.875 + 0:00:00.250 -> [ms]")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate sexagesimal conversion normalization case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->simplifyResultExpressions = oldSimplifyResultExpressions; return; } Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry( QStringLiteral("5:59:59.875 + 0:00:00.250 -> [ms]"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString simplifiedLine = display.document()->findBlockByNumber(1).text(); if (simplifiedLine != QString::fromUtf8("= 6:00:00.125 → [ms]")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalized sexagesimal conversion line\t[NEW]" << endl << "\tLine : " << simplifiedLine.toUtf8().constData() << endl << "\tExpected : = 6:00:00.125 → [ms]" << endl; } ++eval_total_tests; const QString scalarLine = display.document()->findBlockByNumber(2).text(); if (!scalarLine.contains(QStringLiteral("21600125")) || !scalarLine.contains(QStringLiteral("ms")) || scalarLine.contains(QString(MathDsl::UnitStart)) || scalarLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tscalar milliseconds conversion line keeps value and unit\t[NEW]" << endl << "\tLine : " << scalarLine.toUtf8().constData() << endl << "\tExpected : contains 21600125 and ms without []" << endl; } session->clearHistory(); settings->simplifyResultExpressions = oldSimplifyResultExpressions; } void test_sexagesimal_arithmetic_with_per_term_conversion_targets() { eval->setExpression(QString::fromUtf8("−5:59:59.875 → [ms] + 0:00:00.250 → [ms]")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate per-term converted sexagesimal arithmetic\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } ++eval_total_tests; const QString scalar = NumberFormatter::format(value); // Result rendering may use Unicode minus and omit a space before [unit]. // Normalize only the minus sign so the assertion focuses on numeric value. const QString scalarAsciiMinus = QString(scalar).replace(UnicodeChars::MinusSign, QLatin1Char('-')); if (!scalarAsciiMinus.contains(QStringLiteral("-21599625")) || !scalar.contains(QStringLiteral("[ms]"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tper-term converted sexagesimal arithmetic scalar result\t[NEW]" << endl << "\tResult : " << scalar.toUtf8().constData() << endl << "\tExpected : contains -21599625 and [ms]" << endl; } } void test_result_display_mixed_per_term_time_conversions() { Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; settings->simplifyResultExpressions = true; eval->setExpression(QString::fromUtf8("−5:59:59.875 → [h] + 0:00:00.250 → [s] − 10:0:0 → [ms]")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate mixed per-term time conversions\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->simplifyResultExpressions = oldSimplifyResultExpressions; return; } Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry( QString::fromUtf8("−5:59:59.875 → [h] + 0:00:00.250 → [s] − 10:0:0 → [ms]"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString simplifiedLine = display.document()->findBlockByNumber(1).text(); if (simplifiedLine != QString::fromUtf8("= −15:59:59.625 → [ms]")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tmixed per-term time conversions normalized line\t[NEW]" << endl << "\tLine : " << simplifiedLine.toUtf8().constData() << endl << "\tExpected : = −15:59:59.625 → [ms]" << endl; } ++eval_total_tests; const QString scalarLine = display.document()->findBlockByNumber(2).text(); if (!scalarLine.contains(QStringLiteral("57599625")) || !scalarLine.contains(QStringLiteral("ms")) || scalarLine.contains(QString(MathDsl::UnitStart)) || scalarLine.contains(QString(MathDsl::UnitEnd)) || !scalarLine.contains(QString(UnicodeChars::MinusSign))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tmixed per-term time conversions scalar line\t[NEW]" << endl << "\tLine : " << scalarLine.toUtf8().constData() << endl << "\tExpected : contains −57599625 and ms without []" << endl; } session->clearHistory(); settings->simplifyResultExpressions = oldSimplifyResultExpressions; } void test_result_display_mixed_per_term_time_conversions_in_sexagesimal_notation() { Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const char oldResultFormat = settings->resultFormat; settings->simplifyResultExpressions = true; settings->resultFormat = 's'; eval->setExpression(QString::fromUtf8("−5:59:59.875 → [h] + 0:00:00.250 → [s] − 10:0:0 → [ms]")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate mixed per-term time conversions in sexagesimal notation\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->resultFormat = oldResultFormat; return; } Session* session = evalSession; session->clearHistory(); session->addHistoryEntry(HistoryEntry( QString::fromUtf8("−5:59:59.875 → [h] + 0:00:00.250 → [s] − 10:0:0 → [ms]"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString simplifiedLine = display.document()->findBlockByNumber(1).text(); if (simplifiedLine != QString::fromUtf8("= −15:59:59.625 → [ms]")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tmixed per-term sexagesimal normalized line keeps conversion target brackets\t[NEW]" << endl << "\tLine : " << simplifiedLine.toUtf8().constData() << endl << "\tExpected : = −15:59:59.625 → [ms]" << endl; } ++eval_total_tests; const QString scalarLine = display.document()->findBlockByNumber(2).text(); if (scalarLine != QString::fromUtf8("= −15:59:59.625")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tmixed per-term sexagesimal final value line\t[NEW]" << endl << "\tLine : " << scalarLine.toUtf8().constData() << endl << "\tExpected : = −15:59:59.625" << endl; } session->clearHistory(); settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->resultFormat = oldResultFormat; } void test_result_display_time_unit_sum_respects_decimal_and_sexagesimal_notation_modes() { Settings* settings = Settings::instance(); Session* session = evalSession; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; settings->simplifyResultExpressions = false; settings->multipleResultLinesEnabled = false; settings->resultPrecision = -1; struct Case { const char* expression; char resultFormat; QString expectedLine; const char* label; }; const Case cases[] = { { "0.00000001 [min] + 1 [s] + 0.9997 [h] ? sexagesimal notation mode", 's', QStringLiteral("= 0:59:59.9200006"), "time unit sum in sexagesimal notation" }, { "0.00000001 [min] + 1 [s] + 0.9997 [h] ? automatic decimal notation mode", 'g', QStringLiteral("= 59.99866667666666666667") + QString(MathDsl::QuantSp) + QStringLiteral("min"), "time unit sum in automatic decimal notation" } }; for (const Case& tc : cases) { settings->resultFormat = tc.resultFormat; const QString expression = QString::fromLatin1(tc.expression); eval->setExpression(expression); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate " << tc.label << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; continue; } session->clearHistory(); session->addHistoryEntry(HistoryEntry( expression, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); const QString resultLine = display.document()->findBlockByNumber(1).text(); ++eval_total_tests; if (resultLine != tc.expectedLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << tc.label << "\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : " << tc.expectedLine.toUtf8().constData() << endl; } } session->clearHistory(); settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; } void test_result_display_strips_unit_brackets_and_double_click_restores_canonical_unit_expression() { Session* session = evalSession; session->clearHistory(); eval->setExpression(QStringLiteral("2[s]")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate result display unit strip case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; session->clearHistory(); return; } session->addHistoryEntry(HistoryEntry( QStringLiteral("2[s]"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString displayedResultLine = display.document()->findBlockByNumber(1).text(); if (!displayedResultLine.contains(QStringLiteral("s")) || displayedResultLine.contains(QString(MathDsl::UnitStart)) || displayedResultLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display strips unit brackets\t[NEW]" << endl << "\tDisplayed: " << displayedResultLine.toUtf8().constData() << endl << "\tExpected : contains s and no []" << endl; } QString selectedExpression; QObject::connect(&display, &ResultDisplay::expressionSelected, [&selectedExpression](const QString& text) { selectedExpression = text; }); QTextCursor cursor(display.document()->findBlockByNumber(1)); display.setTextCursor(cursor); const QPoint eventPos = display.pointForBlockStart(1); QMouseEvent event( QEvent::MouseButtonDblClick, QPointF(eventPos), QPointF(display.mapToGlobal(eventPos)), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); display.mouseDoubleClickEvent(&event); const QString expectedSelectedExpression = QStringLiteral("2") + QString(MathDsl::QuantSp) + QString(MathDsl::UnitStart) + QStringLiteral("s") + QString(MathDsl::UnitEnd); ++eval_total_tests; if (selectedExpression != expectedSelectedExpression) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tdouble-click restores canonical unit expression\t[NEW]" << endl << "\tSelected: " << selectedExpression.toUtf8().constData() << endl << "\tExpected: " << expectedSelectedExpression.toUtf8().constData() << endl; } session->clearHistory(); } void test_result_display_double_click_selects_list_result() { Session* session = evalSession; session->clearHistory(); eval->setExpression(QStringLiteral("{1; 2; 3}")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate list result display case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; session->clearHistory(); return; } session->addHistoryEntry(HistoryEntry( QStringLiteral("{1; 2; 3}"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); QString selectedExpression; QObject::connect(&display, &ResultDisplay::expressionSelected, [&selectedExpression](const QString& text) { selectedExpression = text; }); QTextCursor cursor(display.document()->findBlockByNumber(1)); display.setTextCursor(cursor); const QPoint eventPos = display.pointForBlockStart(1); QMouseEvent event( QEvent::MouseButtonDblClick, QPointF(eventPos), QPointF(display.mapToGlobal(eventPos)), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); display.mouseDoubleClickEvent(&event); ++eval_total_tests; if (selectedExpression != QStringLiteral("{1; 2; 3}")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tdouble-click selects list result\t[NEW]" << endl << "\tSelected: " << selectedExpression.toUtf8().constData() << endl << "\tExpected: {1; 2; 3}" << endl; } session->clearHistory(); } void test_result_display_uses_base10_exponent_notation() { Session* session = evalSession; Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; settings->simplifyResultExpressions = false; settings->resultFormat = 'g'; settings->resultPrecision = -1; session->clearHistory(); const struct { const char* expr; QString expectedResultLine; } cases[] = { { "1.23e45", QString::fromUtf8("= 1.23 × 10��") }, { "123e-45", QString::fromUtf8("= 1.23 × 10��³") } }; for (const auto& tc : cases) { eval->setExpression(QString::fromLatin1(tc.expr)); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate scientific result display case\t[NEW]" << endl << "\tExpression: " << tc.expr << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; session->clearHistory(); return; } session->clearHistory(); session->addHistoryEntry(HistoryEntry( QString::fromLatin1(tc.expr), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); if (resultLine != tc.expectedResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display uses base-10 exponent notation\t[NEW]" << endl << "\tExpression: " << tc.expr << endl << "\tResult : " << resultLine.toUtf8().constData() << endl << "\tExpected : " << tc.expectedResultLine.toUtf8().constData() << endl; } } settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; session->clearHistory(); } void test_result_display_scientific_units_use_unprefixed_si_units() { Session* session = evalSession; Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; settings->simplifyResultExpressions = false; settings->resultFormat = 'e'; settings->resultPrecision = -1; session->clearHistory(); const QString quantitySpace(MathDsl::QuantSp); const struct { const char* expr; QString expectedResultLine; } cases[] = { { "0.0000000001234234235234 [m]", QString::fromUtf8("= 1.234234235234 × 10�¹�") + quantitySpace + QStringLiteral("m") } }; for (const auto& tc : cases) { eval->setExpression(QString::fromLatin1(tc.expr)); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate scientific unit display case\t[NEW]" << endl << "\tExpression: " << tc.expr << endl << "\tError: " << qPrintable(eval->error()) << endl; continue; } session->clearHistory(); session->addHistoryEntry(HistoryEntry( QString::fromLatin1(tc.expr), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); if (resultLine != tc.expectedResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display uses unprefixed SI unit in scientific notation\t[NEW]" << endl << "\tExpression: " << tc.expr << endl << "\tResult : " << resultLine.toUtf8().constData() << endl << "\tExpected : " << tc.expectedResultLine.toUtf8().constData() << endl; } } settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; session->clearHistory(); } void test_result_display_omits_zero_power_of_ten_generically() { Session* session = evalSession; Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; settings->simplifyResultExpressions = false; settings->resultPrecision = -1; session->clearHistory(); const struct { const char* expr; char resultFormat; QString expectedResultLine; } cases[] = { { "4.091", 'g', QString::fromUtf8("= 4.091") }, { "4.091", 'e', QString::fromUtf8("= 4.091") }, { "4.091", 'n', QString::fromUtf8("= 4.091") }, { "4.091", 'f', QString::fromUtf8("= 4.091") }, { "2 [m]", 'e', QStringLiteral("= 2") + QString(MathDsl::QuantSp) + QStringLiteral("m") }, { "2 [m]", 'n', QStringLiteral("= 2") + QString(MathDsl::QuantSp) + QStringLiteral("m") }, { "sci(4.091)", 'e', QString::fromUtf8("= 4.091") }, { "eng(4.091)", 'e', QString::fromUtf8("= 4.091") }, { "sci(4.091)", 'n', QString::fromUtf8("= 4.091") }, { "eng(4.091)", 'n', QString::fromUtf8("= 4.091") }, { "sci(4.091) ? automatic decimal", 'g', QString::fromUtf8("= 4.091") }, { "eng(4.091) ? automatic decimal", 'g', QString::fromUtf8("= 4.091") }, { "4.091 ? here notation = engineering", 'g', QString::fromUtf8("= 4.091") }, { "4.091 ? here notation = scientific", 'g', QString::fromUtf8("= 4.091") } }; for (const auto& tc : cases) { settings->resultFormat = tc.resultFormat; eval->setExpression(QString::fromLatin1(tc.expr)); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate zero exponent omission case\t[NEW]" << endl << "\tExpression: " << tc.expr << endl << "\tError: " << qPrintable(eval->error()) << endl; continue; } session->clearHistory(); session->addHistoryEntry(HistoryEntry( QString::fromLatin1(tc.expr), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); if (resultLine != tc.expectedResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display omits zero scientific power generically\t[NEW]" << endl << "\tExpression: " << tc.expr << endl << "\tResult : " << resultLine.toUtf8().constData() << endl << "\tExpected : " << tc.expectedResultLine.toUtf8().constData() << endl; } } settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; session->clearHistory(); } void test_result_display_double_click_preserves_compact_angle_suffix() { Session* session = evalSession; Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(QStringLiteral("(21600 / 2)[arcminute]")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate compact angle suffix paste case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); return; } session->addHistoryEntry(HistoryEntry( QStringLiteral("(21600 / 2)[arcminute]"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); QString selectedExpression; QObject::connect(&display, &ResultDisplay::expressionSelected, [&selectedExpression](const QString& text) { selectedExpression = text; }); QTextCursor cursor(display.document()->findBlockByNumber(1)); display.setTextCursor(cursor); const QPoint eventPos = display.pointForBlockStart(1); QMouseEvent event( QEvent::MouseButtonDblClick, QPointF(eventPos), QPointF(display.mapToGlobal(eventPos)), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); display.mouseDoubleClickEvent(&event); ++eval_total_tests; if (selectedExpression != QString::fromUtf8("180°")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tdouble-click preserves compact angle suffix\t[NEW]" << endl << "\tSelected: " << selectedExpression.toUtf8().constData() << endl << "\tExpected: 180°" << endl; } settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); } void test_result_display_keeps_quantsp_before_degree_celsius_and_fahrenheit() { Session* session = evalSession; session->clearHistory(); eval->setExpression(QString::fromUtf8("77 [°F] -> [°C]")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate fahrenheit to celsius display spacing case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; session->clearHistory(); return; } session->addHistoryEntry(HistoryEntry( QString::fromUtf8("77 [°F] -> [°C]"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); const QString expectedSuffix = QString(MathDsl::QuantSp) + QString::fromUtf8("°C"); if (!resultLine.endsWith(expectedSuffix)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display keeps QuantSp before °C\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : ends with " << expectedSuffix.toUtf8().constData() << endl; } session->clearHistory(); } void test_result_display_shows_angle_mode_unit_suffix_for_explicit_angle_input() { Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; const char oldImaginaryUnit = settings->imaginaryUnit; const char oldResultFormat = settings->resultFormat; const char oldResultComplexForm = settings->resultComplexForm; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; Session* session = evalSession; session->clearHistory(); auto checkAngleModeSuffix = [&](char angleUnit, const QString& expectedSuffix, bool expectNoSpaceBeforeUnit, const char* label) { settings->angleUnit = angleUnit; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(QStringLiteral("2 [arcsecond]")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } session->addHistoryEntry(HistoryEntry( QStringLiteral("2 [arcsecond]"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); const QString expectedEnding = expectNoSpaceBeforeUnit ? expectedSuffix : (QString(MathDsl::QuantSp) + expectedSuffix); const bool degreeSpacingOk = !expectNoSpaceBeforeUnit || (!resultLine.endsWith(QString(MathDsl::QuantSp) + expectedSuffix) && !resultLine.endsWith(QStringLiteral(" ") + expectedSuffix)); if (!resultLine.endsWith(expectedEnding) || resultLine.contains(QString(MathDsl::UnitStart)) || resultLine.contains(QString(MathDsl::UnitEnd)) || !degreeSpacingOk) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : ends with " << expectedEnding.toUtf8().constData() << " and has no []" << endl; } }; auto checkSingleFieldAngleLiteralsKeepAutomaticDegreeOutput = [&]() { settings->angleUnit = 'd'; settings->resultFormat = 'g'; settings->simplifyResultExpressions = true; Evaluator::instance()->initializeAngleUnits(); struct Case { QString expression; QString expectedResultLine; }; const Case cases[] = { {QStringLiteral("12 [deg]"), QString::fromUtf8("= 12°")}, {QString::fromUtf8("12°"), QString::fromUtf8("= 12°")}, {QString::fromUtf8("12 [′]"), QString::fromUtf8("= 0.2°")}, {QStringLiteral("12 [arcmin]"), QString::fromUtf8("= 0.2°")}, {QString::fromUtf8("12′"), QString::fromUtf8("= 0.2°")} }; for (const Case& tc : cases) { session->clearHistory(); eval->setExpression(tc.expression); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display single-field angle literal output\t[NEW]" << endl << "\tExpression: " << tc.expression.toUtf8().constData() << endl << "\tError: " << qPrintable(eval->error()) << endl; continue; } session->addHistoryEntry(HistoryEntry( tc.expression, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); if (resultLine != tc.expectedResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display single-field angle literal output\t[NEW]" << endl << "\tExpression: " << tc.expression.toUtf8().constData() << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : " << tc.expectedResultLine.toUtf8().constData() << endl; } } }; auto checkTrigOutputHasNoAngleSuffix = [&](char angleUnit, const char* label) { settings->angleUnit = angleUnit; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(QString::fromUtf8("uf_trig_wrap(x)=sin(x)")); eval->evalUpdateAns(); const QString expressions[] = { QString::fromUtf8("cos(180°)"), QString::fromUtf8("uf_trig_wrap(90°)"), QStringLiteral("uf_trig_wrap((pi/2)[rad])") }; for (const QString& expr : expressions) { session->clearHistory(); eval->setExpression(expr); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tExpression: " << expr.toUtf8().constData() << endl << "\tError: " << qPrintable(eval->error()) << endl; continue; } session->addHistoryEntry(HistoryEntry( expr, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); const QString angleSuffixSpaced = QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol(angleUnit); const QString angleSuffixCompact = Units::angleModeUnitSymbol(angleUnit); if (resultLine.endsWith(angleSuffixSpaced) || resultLine.endsWith(angleSuffixCompact) || resultLine.contains(QString(MathDsl::UnitStart)) || resultLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tExpression: " << expr.toUtf8().constData() << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : scalar trig result with no angle suffix or []" << endl; } } }; auto checkScientificAngleUnitSpacing = [&](const QString& expr, const QString& expectedSuffix, const char* label) { const char previousResultFormat = settings->resultFormat; settings->angleUnit = 'd'; settings->resultFormat = 'e'; settings->simplifyResultExpressions = false; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(expr); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->resultFormat = previousResultFormat; return; } session->addHistoryEntry(HistoryEntry( expr, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); const QString expectedEnding = QString(MathDsl::QuantSp) + expectedSuffix; const bool hasScientificPower = resultLine.contains(QString::fromUtf8("× 10")); if (!hasScientificPower || !resultLine.endsWith(expectedEnding) || resultLine.endsWith(QStringLiteral(" ") + expectedSuffix)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : scientific notation and ending with " << expectedEnding.toUtf8().constData() << endl; } settings->resultFormat = previousResultFormat; }; auto checkSimplifiedLineForRepeatedTrigWithDegreeSignInResultDisplay = [&]() { settings->angleUnit = 'd'; settings->simplifyResultExpressions = true; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(QString::fromUtf8( "cos(180°) + cos(180°) + cos(180°) + cos(180°)")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display simplified line for repeated trig degree-sign input\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } session->addHistoryEntry(HistoryEntry( QString::fromUtf8("cos(180°) + cos(180°) + cos(180°) + cos(180°)"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString line1 = display.document()->findBlockByNumber(1).text(); QString line2 = display.document()->findBlockByNumber(2).text(); line2.replace(QString(MathDsl::SubOp), QString(MathDsl::SubOpAl1)); const QString wrappedDot = QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp); // Guard the exact display contract: grouped coefficients must keep // wrapped middle-dot spacing ("4 · cos(...)"), not compact "4·cos(...)". const bool hasBracketedDegreeArg = line1.contains(QString::fromUtf8("cos(180")) && line1.contains(QString::fromUtf8("[°])")); const bool hasCompactDegreeArg = line1.contains(QString::fromUtf8("cos(180")) && line1.contains(QString::fromUtf8("°)")); const bool hasSimplifiedTrigLine = line1.startsWith(QStringLiteral("= ")) && line1.contains(QString::fromUtf8("4")) && line1.contains(wrappedDot) && (hasBracketedDegreeArg || hasCompactDegreeArg); const bool hasFinalResultLine = line2.startsWith(QStringLiteral("= ")) && line2.contains(QStringLiteral("-4")); if (!hasSimplifiedTrigLine || !hasFinalResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display simplified line for repeated trig degree-sign input\t[NEW]" << endl << "\tText : " << display.document()->toPlainText().toUtf8().constData() << endl << "\tExpected : simplified trig line and final = -4 line" << endl; } }; auto checkSimplifiedLineForMixedDegreeAliasesInResultDisplay = [&]() { settings->angleUnit = 'd'; settings->simplifyResultExpressions = true; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); const QString expr = QString::fromUtf8( "cos(180[deg]) + cos(180[degree]) + cos(180 [°])+ cos(180 [deg])"); eval->setExpression(expr); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display simplified line for mixed degree aliases\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } session->addHistoryEntry(HistoryEntry( expr, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); const QString line1 = display.document()->findBlockByNumber(1).text(); QString line2 = display.document()->findBlockByNumber(2).text(); line2.replace(QString(MathDsl::SubOp), QString(MathDsl::SubOpAl1)); const bool hasBracketedDegreeArg = line1.contains(QString::fromUtf8("cos(180")) && line1.contains(QString::fromUtf8("[°])")); const bool hasCompactDegreeArg = line1.contains(QString::fromUtf8("cos(180")) && line1.contains(QString::fromUtf8("°)")); const bool hasSimplifiedTrigLine = line1.startsWith(QStringLiteral("= ")) && line1.contains(QString::fromUtf8("4")) && (hasBracketedDegreeArg || hasCompactDegreeArg); const bool hasFinalResultLine = line2.startsWith(QStringLiteral("= ")) && line2.contains(QStringLiteral("-4")); ++eval_total_tests; if (!hasSimplifiedTrigLine || !hasFinalResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display simplified line for mixed degree aliases\t[NEW]" << endl << "\tText : " << display.document()->toPlainText().toUtf8().constData() << endl << "\tExpected : simplified trig line with coefficient 4 and final = -4 line" << endl; } }; auto checkCisOutputsWithExplicitAngleUnitsHaveNoRadianSuffix = [&]() { settings->angleUnit = 'r'; settings->imaginaryUnit = 'j'; settings->resultFormat = 'g'; settings->resultComplexForm = ComplexForm::Rectangular; CMath::setImaginaryUnitSymbol(QLatin1Char('j')); Evaluator::instance()->initializeAngleUnits(); struct Case { QString expression; QString expectedExpressionLine; QString expectedResultLine; }; const Case cases[] = { { QString::fromUtf8("3cis(90°)"), QStringLiteral("3") + QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp) + QString::fromUtf8("cis(90°)"), QStringLiteral("= 3j") }, { QStringLiteral("3 * cis(200 [gon])"), QString(), QString::fromUtf8("= −3") } }; for (const Case& tc : cases) { session->clearHistory(); eval->setExpression(tc.expression); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display cis with explicit angle input has no radian suffix\t[NEW]" << endl << "\tExpression: " << tc.expression.toUtf8().constData() << endl << "\tError : " << qPrintable(eval->error()) << endl; continue; } session->addHistoryEntry(HistoryEntry( tc.expression, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString expressionLine = display.document()->findBlockByNumber(0).text(); const QString resultLine = display.document()->findBlockByNumber(1).text(); const bool expressionLineOk = tc.expectedExpressionLine.isEmpty() || expressionLine == tc.expectedExpressionLine; if (!expressionLineOk || resultLine != tc.expectedResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display cis with explicit angle input has no radian suffix\t[NEW]" << endl << "\tExpression: " << tc.expression.toUtf8().constData() << endl << "\tExpr line : " << expressionLine.toUtf8().constData() << endl << "\tExpected : " << tc.expectedExpressionLine.toUtf8().constData() << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : " << tc.expectedResultLine.toUtf8().constData() << endl; } } }; auto checkPhasorOutputsWithExplicitAngleUnitsHaveNoRadianSuffix = [&]() { settings->angleUnit = 'r'; settings->imaginaryUnit = 'j'; settings->resultFormat = 'g'; settings->resultComplexForm = ComplexForm::Rectangular; CMath::setImaginaryUnitSymbol(QLatin1Char('j')); Evaluator::instance()->initializeAngleUnits(); const QString phasorOp(MathDsl::PhasorOp); struct Case { QString expression; QString expectedResultLine; }; const Case cases[] = { { QStringLiteral("3 ") + phasorOp + QStringLiteral(" 200 [gon]"), QString::fromUtf8("= −3") }, { QStringLiteral("3 ") + phasorOp + QString::fromUtf8(" 200°"), QString() }, { QStringLiteral("3 ") + phasorOp + QStringLiteral(" 200 [rev]"), QStringLiteral("= 3") }, { QStringLiteral("pi ") + phasorOp + QString::fromUtf8(" 0°"), QString() } }; for (const Case& tc : cases) { session->clearHistory(); eval->setExpression(tc.expression); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display phasor with explicit angle input has no radian suffix\t[NEW]" << endl << "\tExpression: " << tc.expression.toUtf8().constData() << endl << "\tError : " << qPrintable(eval->error()) << endl; continue; } session->addHistoryEntry(HistoryEntry( tc.expression, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); const bool expectedLineOk = tc.expectedResultLine.isEmpty() || resultLine == tc.expectedResultLine; const bool hasAngleSuffix = resultLine.endsWith(QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r')) || resultLine.endsWith(QStringLiteral(" ") + Units::angleModeUnitSymbol('r')) || resultLine.endsWith(Units::angleModeUnitSymbol('r')); if (!expectedLineOk || hasAngleSuffix || resultLine.contains(QString(MathDsl::UnitStart)) || resultLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display phasor with explicit angle input has no radian suffix\t[NEW]" << endl << "\tExpression: " << tc.expression.toUtf8().constData() << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : complex phasor result with no angle suffix or []" << endl; } } }; checkAngleModeSuffix('r', Units::angleModeUnitSymbol('r'), false, "result display angle suffix in radian mode"); checkAngleModeSuffix('d', Units::angleModeUnitSymbol('d'), true, "result display angle suffix in degree mode"); checkAngleModeSuffix('g', Units::angleModeUnitSymbol('g'), false, "result display angle suffix in gradian mode"); checkAngleModeSuffix('t', Units::angleModeUnitSymbol('t'), false, "result display angle suffix in turn mode"); checkAngleModeSuffix('v', Units::angleModeUnitSymbol('v'), false, "result display angle suffix in revolution mode"); checkSingleFieldAngleLiteralsKeepAutomaticDegreeOutput(); checkTrigOutputHasNoAngleSuffix('r', "result display trig output has no radian suffix"); checkTrigOutputHasNoAngleSuffix('d', "result display trig output has no degree suffix"); checkCisOutputsWithExplicitAngleUnitsHaveNoRadianSuffix(); checkPhasorOutputsWithExplicitAngleUnitsHaveNoRadianSuffix(); checkSimplifiedLineForRepeatedTrigWithDegreeSignInResultDisplay(); checkSimplifiedLineForMixedDegreeAliasesInResultDisplay(); checkScientificAngleUnitSpacing( QStringLiteral("1e8 [arcsecond]"), QString::fromUtf8("°"), "result display scientific degree suffix keeps QuantSp"); checkScientificAngleUnitSpacing( QStringLiteral("1e8 [arcsecond] -> [arcminute]"), QString::fromUtf8("′"), "result display scientific arcminute suffix keeps QuantSp"); checkScientificAngleUnitSpacing( QStringLiteral("1e8 [arcsecond] -> [arcsecond]"), QString::fromUtf8("″"), "result display scientific arcsecond suffix keeps QuantSp"); settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(QString::fromUtf8("1°2′3″")); const Quantity sexagesimalValue = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display angle suffix for sexagesimal literal\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { session->addHistoryEntry(HistoryEntry( QString::fromUtf8("1°2′3″"), sexagesimalValue, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); const QString expectedEnding = QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r'); if (!resultLine.endsWith(expectedEnding) || resultLine.contains(QString(MathDsl::UnitStart)) || resultLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display angle suffix for sexagesimal literal\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : ends with " << expectedEnding.toUtf8().constData() << " and has no []" << endl; } } settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(QString::fromUtf8("−57°17′44.80624709635515647336″")); const Quantity negativeSexagesimalValue = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display angle suffix for negative sexagesimal literal\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { session->addHistoryEntry(HistoryEntry( QString::fromUtf8("−57°17′44.80624709635515647336″"), negativeSexagesimalValue, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); const QString expectedEnding = QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r'); if (!resultLine.endsWith(expectedEnding) || resultLine.contains(QString(MathDsl::UnitStart)) || resultLine.contains(QString(MathDsl::UnitEnd))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display angle suffix for negative sexagesimal literal\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : ends with " << expectedEnding.toUtf8().constData() << " and has no []" << endl; } } settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(QStringLiteral("1 [rev]→[°]")); const Quantity degreeConversionValue = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display spacing for degree conversion target\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { session->addHistoryEntry(HistoryEntry( QStringLiteral("1 [rev]→[°]"), degreeConversionValue, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); if (!resultLine.endsWith(QStringLiteral("360°"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display spacing for degree conversion target\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : ends with 360°" << endl; } } settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(QStringLiteral("1 [rev] -> [arcmin]")); const Quantity arcminuteConversionValue = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display spacing for arcminute conversion target\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { session->addHistoryEntry(HistoryEntry( QStringLiteral("1 [rev] -> [arcmin]"), arcminuteConversionValue, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString resultLine = display.document()->findBlockByNumber(1).text(); if (!resultLine.endsWith(QString::fromUtf8("21600′"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display spacing for arcminute conversion target\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : ends with 21600′" << endl; } } settings->angleUnit = oldAngleUnit; settings->imaginaryUnit = oldImaginaryUnit; settings->resultFormat = oldResultFormat; settings->resultComplexForm = oldResultComplexForm; settings->simplifyResultExpressions = oldSimplifyResultExpressions; CMath::setImaginaryUnitSymbol(QChar(oldImaginaryUnit)); Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); } void test_value_unit_separator_normalization() { const QString expectedWithSeparator = QStringLiteral("1") + QString(MathDsl::QuantSp) + QStringLiteral("[kg]"); const QString expectedHexWithSeparator = QStringLiteral("0xA") + QString(MathDsl::QuantSp) + QStringLiteral("[kg]"); ++eval_total_tests; const QString noSpaceInput = DisplayFormatUtils::applyValueUnitSpacingForDisplay(QStringLiteral("1[kg]")); if (noSpaceInput != expectedWithSeparator) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalize value-unit without space\t[NEW]" << endl << "\tResult : " << noSpaceInput.toUtf8().constData() << endl << "\tExpected : " << expectedWithSeparator.toUtf8().constData() << endl; } ++eval_total_tests; const QString regularSpaceInput = DisplayFormatUtils::applyValueUnitSpacingForDisplay(QStringLiteral("1 [kg]")); if (regularSpaceInput != expectedWithSeparator) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalize value-unit regular space\t[NEW]" << endl << "\tResult : " << regularSpaceInput.toUtf8().constData() << endl << "\tExpected : " << expectedWithSeparator.toUtf8().constData() << endl; } ++eval_total_tests; const QString noSpaceHexInput = DisplayFormatUtils::applyValueUnitSpacingForDisplay(QStringLiteral("0xA[kg]")); if (noSpaceHexInput != expectedHexWithSeparator) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalize value-unit hex without space\t[NEW]" << endl << "\tResult : " << noSpaceHexInput.toUtf8().constData() << endl << "\tExpected : " << expectedHexWithSeparator.toUtf8().constData() << endl; } ++eval_total_tests; const QString regularSpaceHexInput = DisplayFormatUtils::applyValueUnitSpacingForDisplay(QStringLiteral("0xA [kg]")); if (regularSpaceHexInput != expectedHexWithSeparator) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tnormalize value-unit hex regular space\t[NEW]" << endl << "\tResult : " << regularSpaceHexInput.toUtf8().constData() << endl << "\tExpected : " << expectedHexWithSeparator.toUtf8().constData() << endl; } } void test_result_display_preserves_standalone_sexagesimal_angles_without_implicit_conversion() { Settings* settings = Settings::instance(); Session* session = evalSession; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; const char oldAngleUnit = settings->angleUnit; settings->simplifyResultExpressions = false; settings->multipleResultLinesEnabled = false; settings->resultPrecision = -1; settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); struct Case { char format; const char* label; }; const Case cases[] = { {'s', "sexagesimal format preserves standalone sexagesimal angle"}, {'g', "automatic decimal format preserves standalone sexagesimal angle"} }; for (const Case& tc : cases) { settings->resultFormat = tc.format; session->clearHistory(); eval->setExpression(QString::fromUtf8("1°2′3″")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << tc.label << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; continue; } session->addHistoryEntry(HistoryEntry( QString::fromUtf8("1°2′3″"), value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); const QString resultLine = display.document()->findBlockByNumber(1).text(); const QString expressionLine = display.document()->findBlockByNumber(0).text(); ++eval_total_tests; if (expressionLine != QString::fromUtf8("1°2′3″")) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << tc.label << " expression line\t[NEW]" << endl << "\tLine : " << expressionLine.toUtf8().constData() << endl << "\tExpected : 1°2′3″" << endl; } ++eval_total_tests; if (!resultLine.contains(QString::fromUtf8("°")) || !resultLine.contains(QString::fromUtf8("′")) || !resultLine.contains(QString::fromUtf8("″")) || resultLine.contains(QString::fromUtf8("[″]")) || resultLine.contains(QString::fromUtf8("1.034"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << tc.label << " result line\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : sexagesimal angle with no implicit [″] or decimal degrees" << endl; } } settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); } void test_result_display_adds_simplified_line_for_unit_conversion_when_interpreted_is_empty() { Settings* settings = Settings::instance(); Session* session = evalSession; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const char oldUnitExponentStyle = settings->unitNegativeExponentStyle; settings->simplifyResultExpressions = true; settings->unitNegativeExponentStyle = Settings::UnitNegativeExponentSuperscript; setRuntimeUnitNegativeExponentStyle(Settings::UnitNegativeExponentSuperscript); session->clearHistory(); const QString expression = QStringLiteral("molmass(C6H12O6) * molmass(C6H12O6) -> [g²/mol²]"); eval->setExpression(expression); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display simplified line for conversion expression\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { // Reproduce the display path where interpreted text may be empty. session->addHistoryEntry(HistoryEntry(expression, value, QString())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString line1 = display.document()->findBlockByNumber(1).text(); const QString line2 = display.document()->findBlockByNumber(2).text(); const bool hasSimplifiedLine = line1.startsWith(QStringLiteral("= ")) && line1.contains(QString::fromUtf8("molmass²(C6H12O6)")); const bool hasFinalResultLine = line2.startsWith(QStringLiteral("= ")) && line2.contains(QString::fromUtf8("32456.184336")) && line2.contains(QString::fromUtf8("g²")) && line2.contains(QString::fromUtf8("mol�²")); if (!hasSimplifiedLine || !hasFinalResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display simplified line for conversion expression\t[NEW]" << endl << "\tText : " << display.document()->toPlainText().toUtf8().constData() << endl << "\tExpected : simplified molmass² line and final result line" << endl; } } settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->unitNegativeExponentStyle = oldUnitExponentStyle; setRuntimeUnitNegativeExponentStyle(oldUnitExponentStyle); session->clearHistory(); } void test_result_display_adds_simplified_line_for_unit_conversion_with_interpreted_expression() { Settings* settings = Settings::instance(); Session* session = evalSession; const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const char oldUnitExponentStyle = settings->unitNegativeExponentStyle; settings->simplifyResultExpressions = true; settings->unitNegativeExponentStyle = Settings::UnitNegativeExponentSuperscript; setRuntimeUnitNegativeExponentStyle(Settings::UnitNegativeExponentSuperscript); session->clearHistory(); const QString expression = QStringLiteral("molmass(C6H12O6) * molmass(C6H12O6) -> [g²/mol²]"); eval->setExpression(expression); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display simplified line for conversion with interpreted expression\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { session->addHistoryEntry(HistoryEntry(expression, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); ++eval_total_tests; const QString line1 = display.document()->findBlockByNumber(1).text(); const QString line2 = display.document()->findBlockByNumber(2).text(); const bool hasSimplifiedLine = line1.startsWith(QStringLiteral("= ")) && line1.contains(QString::fromUtf8("molmass²(C6H12O6)")); const bool hasFinalResultLine = line2.startsWith(QStringLiteral("= ")) && line2.contains(QString::fromUtf8("32456.184336")) && line2.contains(QString::fromUtf8("g²")) && line2.contains(QString::fromUtf8("mol�²")); if (!hasSimplifiedLine || !hasFinalResultLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display simplified line for conversion with interpreted expression\t[NEW]" << endl << "\tText : " << display.document()->toPlainText().toUtf8().constData() << endl << "\tExpected : simplified molmass² line and final result line" << endl; } } settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->unitNegativeExponentStyle = oldUnitExponentStyle; setRuntimeUnitNegativeExponentStyle(oldUnitExponentStyle); session->clearHistory(); } void test_result_display_shows_pi_multiples_for_radian_angle_results() { Settings* settings = Settings::instance(); Session* session = evalSession; const char oldAngleUnit = settings->angleUnit; const char oldResultFormat = settings->resultFormat; const bool oldSimplify = settings->simplifyResultExpressions; const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; settings->resultFormat = 'g'; settings->simplifyResultExpressions = false; settings->multipleResultLinesEnabled = false; auto normalizeDisplaySpaces = [](QString text) { text.replace(MathDsl::QuantSp, QLatin1Char(' ')); text.replace(UnicodeChars::NoBreakSpace, QLatin1Char(' ')); return text; }; auto checkPiLine = [&](char angleUnit, const QString& expression, const QString& expectedPiLine, const char* label) { settings->angleUnit = angleUnit; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(expression); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } session->addHistoryEntry(HistoryEntry(expression, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); const QString text = display.document()->toPlainText(); const QString normalizedText = normalizeDisplaySpaces(text); const QString normalizedExpected = normalizeDisplaySpaces(expectedPiLine); ++eval_total_tests; if (!normalizedText.contains(normalizedExpected)) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tExpression: " << expression.toUtf8().constData() << endl << "\tText : " << text.toUtf8().constData() << endl << "\tExpected : contains " << expectedPiLine.toUtf8().constData() << endl; } }; const QString radSuffix = QString(MathDsl::QuantSp) + Units::angleModeUnitSymbol('r'); const QString multiplication = QString(MathDsl::MulDotWrapSp) + QString(MathDsl::MulDotOp) + QString(MathDsl::MulDotWrapSp); const QString division = QString(MathDsl::DivWrap) + QString(MathDsl::DivOp) + QString(MathDsl::DivWrap); checkPiLine( 'r', QString::fromUtf8("360°"), QStringLiteral("= 2") + multiplication + QString::fromUtf8("π") + radSuffix, "result display adds 2·pi rad line for 360 degree input in radian mode"); checkPiLine( 'd', QString::fromUtf8("180° -> [rad]"), QStringLiteral("= ") + QString::fromUtf8("π") + radSuffix, "result display adds pi rad line for explicit degree-to-radian conversion"); checkPiLine( 'r', QString::fromUtf8("270°"), QStringLiteral("= 3") + division + QStringLiteral("2") + multiplication + QString::fromUtf8("π") + radSuffix, "result display adds 3/2·pi rad line for 270 degree input in radian mode"); checkPiLine( 'd', QStringLiteral("50 [gon] -> [rad]"), QStringLiteral("= ") + QString::fromUtf8("π") + division + QStringLiteral("4") + radSuffix, "result display adds pi/4 rad line for gradian-to-radian conversion"); checkPiLine( 'r', QString::fromUtf8("180″"), QStringLiteral("= ") + QString::fromUtf8("π") + division + QStringLiteral("3600") + radSuffix, "result display adds pi/3600 rad line for arcsecond input in radian mode"); checkPiLine( 'r', QString::fromUtf8("180°"), QStringLiteral("= ") + QString::fromUtf8("π") + radSuffix, "result display adds pi rad line for degree input in radian mode"); checkPiLine( 'r', QString::fromUtf8("180′"), QStringLiteral("= ") + QString::fromUtf8("π") + division + QStringLiteral("60") + radSuffix, "result display adds pi/60 rad line for arcminute input in radian mode"); auto checkArctanDedup = [&](const QString& expression, const QString& expectedPiLine, const QString& redundantLine, const char* label) { settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); eval->setExpression(expression); const Quantity arctanValue = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } session->addHistoryEntry(HistoryEntry(expression, arctanValue, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); const QString text = display.document()->toPlainText(); const QStringList lines = normalizeDisplaySpaces(text).split(QLatin1Char('\n')); const bool hasPiLine = lines.contains(normalizeDisplaySpaces(expectedPiLine)); const bool hasRedundantLine = lines.contains(normalizeDisplaySpaces(redundantLine)); ++eval_total_tests; if (!hasPiLine || hasRedundantLine) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\t" << label << "\t[NEW]" << endl << "\tText : " << text.toUtf8().constData() << endl << "\tExpected : contains " << expectedPiLine.toUtf8().constData() << " and does not contain " << redundantLine.toUtf8().constData() << endl; } }; checkArctanDedup( QStringLiteral("arctan(1)"), QStringLiteral("= ") + QString::fromUtf8("π") + division + QStringLiteral("4") + radSuffix, QStringLiteral("= ") + QString::fromUtf8("π") + division + QStringLiteral("4"), "result display omits redundant trig symbolic line when pi/4 rad line exists"); checkArctanDedup( QString::fromUtf8("arctan(−1)"), QStringLiteral("= ") + QString::fromUtf8("−π") + division + QStringLiteral("4") + radSuffix, QStringLiteral("= ") + QString::fromUtf8("-π") + division + QStringLiteral("4"), "result display omits redundant trig symbolic line when -pi/4 rad line exists"); settings->angleUnit = oldAngleUnit; settings->resultFormat = oldResultFormat; settings->simplifyResultExpressions = oldSimplify; settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); } void test_result_display_compacts_bracketed_degree_inside_trig_call() { Settings* settings = Settings::instance(); Session* session = evalSession; const char oldAngleUnit = settings->angleUnit; settings->angleUnit = 'r'; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); const QString expr = QString::fromUtf8("tan(180°)"); eval->setExpression(expr); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate tan(180°) compact-degree display case\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); return; } session->addHistoryEntry(HistoryEntry(expr, value, eval->interpretedExpression())); TestableResultDisplay display; display.resize(800, 600); display.refresh(); const QString expressionLine = display.document()->findBlockByNumber(0).text(); const QString resultLine = display.document()->findBlockByNumber(1).text(); ++eval_total_tests; if (expressionLine != expr) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display keeps compact degree suffix in trig expression line\t[NEW]" << endl << "\tLine : " << expressionLine.toUtf8().constData() << endl << "\tExpected : " << expr.toUtf8().constData() << endl; } ++eval_total_tests; if (!resultLine.startsWith(QStringLiteral("= 0"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult display tan(180°) numeric line\t[NEW]" << endl << "\tLine : " << resultLine.toUtf8().constData() << endl << "\tExpected : starts with '= 0'" << endl; } settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); session->clearHistory(); } void test_trig_symbolic_fraction_half() { eval->setExpression(QStringLiteral("cos(pi/3)")); const Quantity value = eval->evalUpdateAns(); ++eval_total_tests; if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tevaluate cos(pi/3) for trig symbolic fraction\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; return; } const QString expected = QStringLiteral("1") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("2"); const QString symbolic = NumberFormatter::formatTrigSymbolic(value); ++eval_total_tests; if (symbolic != expected) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tformat trig symbolic half\t[NEW]" << endl << "\tResult : " << symbolic.toUtf8().constData() << endl << "\tExpected : " << expected.toUtf8().constData() << endl; } } void test_interpreted_quotient_simplification() { const QString dot = space + QString(MathDsl::MulDotOp) + space; const QString plus = space + QString(MathDsl::AddOp) + space; const QString minus(UnicodeChars::MinusSign); struct SimplificationCase { QString expression; QString simplified; QString displayed; }; const SimplificationCase cases[] = { {QStringLiteral("ans/9"), QStringLiteral("ans/9"), QStringLiteral("ans") + slash + QStringLiteral("9")}, {QStringLiteral("ans/0.25"), QStringLiteral("ans/0.25"), QStringLiteral("ans") + slash + QStringLiteral("0.25")}, {QStringLiteral("e/7"), QStringLiteral("e/7"), QStringLiteral("e") + slash + QStringLiteral("7")}, {QStringLiteral("cos(pi)/11"), QStringLiteral("cos(pi)/11"), QStringLiteral("cos(pi)") + slash + QStringLiteral("11")}, {QStringLiteral("ans^2/13"), QStringLiteral("ans^2/13"), QString::fromUtf8("ans²") + slash + QStringLiteral("13")}, {QStringLiteral("ans*e/5"), QString::fromUtf8("ans·e/5"), QStringLiteral("ans") + dot + QStringLiteral("e") + slash + QStringLiteral("5")}, {QStringLiteral("ans/(17*e)"), QString::fromUtf8("ans/(17·e)"), QStringLiteral("ans") + slash + QStringLiteral("(17") + dot + QStringLiteral("e)")}, {QStringLiteral("(-ans)/8"), QStringLiteral("-ans/8"), minus + QStringLiteral("ans") + slash + QStringLiteral("8")}, {QStringLiteral("ans/(-6)"), QStringLiteral("ans/(-6)"), QStringLiteral("ans") + slash + QStringLiteral("(") + minus + QStringLiteral("6)")}, {QStringLiteral("ans/10+e/7"), QStringLiteral("ans/10+e/7"), QStringLiteral("ans") + slash + QStringLiteral("10") + plus + QStringLiteral("e") + slash + QStringLiteral("7")}, {QStringLiteral("ans/12 ? previous answer"), QStringLiteral("ans/12"), QStringLiteral("ans") + slash + QStringLiteral("12")}, {QString::fromUtf8("ans÷16"), QStringLiteral("ans/16"), QStringLiteral("ans") + slash + QStringLiteral("16")}, {QStringLiteral("ans*ans/25"), QStringLiteral("1/25*ans^2"), QStringLiteral("1") + slash + QStringLiteral("25") + dot + QString::fromUtf8("ans²")}, {QStringLiteral("6*ans/15"), QStringLiteral("2/5*ans"), QStringLiteral("2") + slash + QStringLiteral("5") + dot + QStringLiteral("ans")}, {QStringLiteral("ans/2/7"), QStringLiteral("1/14*ans"), QStringLiteral("1") + slash + QStringLiteral("14") + dot + QStringLiteral("ans")}, {QStringLiteral("ans*e/e/8"), QStringLiteral("1/8*ans"), QStringLiteral("1") + slash + QStringLiteral("8") + dot + QStringLiteral("ans")}, {QStringLiteral("ans/1"), QStringLiteral("ans"), QStringLiteral("ans")} }; for (const SimplificationCase& testCase : cases) { CHECK_EVAL("4", "4"); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED(testCase.expression, testCase.displayed); if (!eval->error().isEmpty()) continue; ++eval_total_tests; const QString simplified = Evaluator::simplifyInterpretedExpression(eval->interpretedExpression()); if (simplified != testCase.simplified) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tinterpreted quotient simplification\t[NEW]" << endl << "\tExpression : " << qPrintable(testCase.expression) << endl << "\tSimplified : " << qPrintable(simplified) << endl << "\tExpected : " << qPrintable(testCase.simplified) << endl; } } } void test_non_informative_numeric_simplified_row_suppression() { checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "suppress simplified line for 1+2-3/2", QStringLiteral("1+2-3/2"), true); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "suppress simplified line for 1+.5-1.5+3", QStringLiteral("1+.5-1.5+3"), true); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "suppress simplified line for unicode multiply/divide arithmetic", QString::fromUtf8("2/3×4"), true); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "suppress simplified line for numeric arithmetic with superscript power", QString::fromUtf8("213+12312+123+123×123/1×(312.12312312³)"), true); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "suppress simplified line for numeric arithmetic with suffix comment", QString::fromUtf8("213+12312+123+123×123/1×(312.12312312³) ? ?????"), true); ++eval_total_tests; { Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; const bool oldMultipleResultLinesEnabled = settings->multipleResultLinesEnabled; const char oldResultFormat = settings->resultFormat; const int oldResultPrecision = settings->resultPrecision; settings->simplifyResultExpressions = true; settings->multipleResultLinesEnabled = false; settings->resultFormat = 'f'; settings->resultPrecision = 3; const QStringList expressions = { QString::fromUtf8("213+12312+123+123×123/1×(312.12312312³)"), QString::fromUtf8("213+12312+123+123×123/1×(312.12312312³) ? ?????") }; for (const QString& expr : expressions) { eval->setExpression(expr); const Quantity value = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult lines suppress duplicate numeric simplification\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QStringList lines = ResultLineFormatUtils::formatResultLinesForDisplay( expr, eval->interpretedExpression(), value, true, true, eval); if (lines.size() != 2 || lines.last().contains(QStringLiteral("876131"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult lines suppress duplicate numeric simplification\t[NEW]" << endl << "\tExpression: " << expr.toUtf8().constData() << endl << "\tLine count: " << lines.size() << endl; for (const QString& line : lines) cerr << "\tLine: " << line.toUtf8().constData() << endl; } } } settings->simplifyResultExpressions = oldSimplifyResultExpressions; settings->multipleResultLinesEnabled = oldMultipleResultLinesEnabled; settings->resultFormat = oldResultFormat; settings->resultPrecision = oldResultPrecision; } checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "do not suppress symbolic simplification", QStringLiteral("2*e*e-1"), false); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "suppress commutative swap for 1+cos(pi)", QStringLiteral("1+cos(pi)"), true); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "suppress additive reorder for 2*cos(3)+3-cbrt(3)", QStringLiteral("2*cos(3)+3-cbrt(3)"), true); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "do not suppress symbolic reduction with trailing 1 multiplier", QStringLiteral("cos (pi)^2/ cos pi 1"), false); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "do not suppress symbolic reduction with explicit multiplication by 1", QStringLiteral("1*cos(pi)^2/cos(pi)"), false); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("cos (pi)^2/ cos pi 1"), QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("1*cos(pi)^2/cos(pi)"), QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("2*cos(pi)^2/cos(pi)"), QStringLiteral("2") + QString(MathDsl::AddWrap) + QString(MathDsl::MulDotOp) + QString(MathDsl::AddWrap) + QStringLiteral("cos(pi)")); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "do not suppress symbolic reduction when wrapped factor is multiplied", QStringLiteral("(cos(pi)^2/cos(pi))*2"), false); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("(cos(pi)^2/cos(pi))*2"), QStringLiteral("2") + QString(MathDsl::AddWrap) + QString(MathDsl::MulDotOp) + QString(MathDsl::AddWrap) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QString::fromUtf8("cos(π) · cos(π) · cos(π) · cos(π)"), QString::fromUtf8("cos�(π)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QString::fromUtf8("cos(π) · cos(π) · cos(π) · cos(pi)"), QString::fromUtf8("cos�(π)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QString::fromUtf8("cos(π) · cos(pi) · cos(π) · cos(pi)"), QString::fromUtf8("cos�(π)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QString::fromUtf8("cos(π) · cos(π) · cos(π) ? foo"), QString::fromUtf8("cos³(π)")); ++eval_total_tests; { Settings* settings = Settings::instance(); const bool oldSimplifyResultExpressions = settings->simplifyResultExpressions; settings->simplifyResultExpressions = true; const QString expr = QString::fromUtf8("cos(π) · cos(π) · cos(π) ? foo"); eval->setExpression(expr); const Quantity value = eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult lines omit comment from simplified expression\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QStringList lines = ResultLineFormatUtils::formatResultLinesForDisplay( expr, eval->interpretedExpression(), value, true, true, eval); const QString expectedSimplified = QString::fromUtf8("= cos³(π)"); if (lines.size() < 3 || !lines.first().contains(QStringLiteral("? foo")) || lines.at(1) != expectedSimplified || lines.at(1).contains(QStringLiteral("? foo"))) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tresult lines omit comment from simplified expression\t[NEW]" << endl << "\tLine count: " << lines.size() << endl; for (const QString& line : lines) cerr << "\tLine: " << line.toUtf8().constData() << endl; } } settings->simplifyResultExpressions = oldSimplifyResultExpressions; } CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("(2*cos(pi)/(3*pi*4))*(343+4343)-2*e"), QStringLiteral("781") + QString(MathDsl::AddWrap) + QString(MathDsl::MulDotOp) + QString(MathDsl::AddWrap) + QStringLiteral("cos(pi)") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("pi") + QString(MathDsl::AddWrap) + QString(UnicodeChars::MinusSign) + QString(MathDsl::AddWrap) + QStringLiteral("2") + QString(MathDsl::AddWrap) + QString(MathDsl::MulDotOp) + QString(MathDsl::AddWrap) + QStringLiteral("e")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("cos(pi)^2/cos(pi)"), QStringLiteral("cos²(pi)") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("cos(pi)^2/cos(pi) 1"), QStringLiteral("cos²(pi)") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("cos(pi)") + QString(MathDsl::AddWrap) + QString(MathDsl::MulDotOp) + QString(MathDsl::AddWrap) + QStringLiteral("1")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("cos(pi/3)^2^3"), QStringLiteral("cos(") + QStringLiteral("pi") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("3)^(2") + QString::fromUtf8("³)") ); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("cos(pi/3)^2^3"), QString::fromUtf8("cos�(pi") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("3)")); CHECK_DISPLAY_INTERPRETED( QStringLiteral("(cos(pi/3))^2^3"), QStringLiteral("cos(") + QStringLiteral("pi") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("3)^(2") + QString::fromUtf8("³)") ); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("(cos(pi/3))^2^3"), QString::fromUtf8("cos�(pi") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("3)")); ++eval_total_tests; { const QString superscriptInput = QString::fromUtf8("cos²(pi/3)³"); const QString normalized = eval->autoFix(superscriptInput); const QString expectedNormalized = QStringLiteral("(cos(pi/3)^2)^3"); if (normalized != expectedNormalized) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcos²(pi/3)^3 autofix\t[NEW]" << endl << "\tNormalized: " << normalized.toUtf8().constData() << endl << "\tExpected : " << expectedNormalized.toUtf8().constData() << endl; } else { eval->setExpression(normalized); eval->evalUpdateAns(); if (!eval->error().isEmpty()) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcos²(pi/3)^3 eval\t[NEW]" << endl << "\tError: " << qPrintable(eval->error()) << endl; } else { const QString displayed = Evaluator::formatInterpretedExpressionForDisplay( eval->interpretedExpression(), eval); const QString expectedDisplayed = QString::fromUtf8("(cos²(pi") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("3))") + QString::fromUtf8("³"); const QString expectedSimplified = QString::fromUtf8("cos�(pi") + QString(MathDsl::AddWrap) + QStringLiteral("/") + QString(MathDsl::AddWrap) + QStringLiteral("3)"); const QString simplifiedDisplayed = Evaluator::formatInterpretedExpressionSimplifiedForDisplay( eval->interpretedExpression(), eval); if (displayed != expectedDisplayed || simplifiedDisplayed != expectedSimplified) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tcos²(pi/3)^3 display\t[NEW]" << endl << "\tDisplayed: " << displayed.toUtf8().constData() << endl << "\tExpected : " << expectedDisplayed.toUtf8().constData() << endl << "\tSimplif. : " << simplifiedDisplayed.toUtf8().constData() << endl << "\tExpected : " << expectedSimplified.toUtf8().constData() << endl; } } } } checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "do not suppress symbolic reduction with -1 multiplier", QStringLiteral("-1*cos(pi)^2/cos(pi)+1"), false); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2/cos(pi)+1"), QString(UnicodeChars::MinusSign) + QStringLiteral("cos(pi)") + QString(MathDsl::AddWrap) + QStringLiteral("+") + QString(MathDsl::AddWrap) + QStringLiteral("1")); checkSuppressSimplifiedExpressionLine( __FILE__, __LINE__, "do not suppress symbolic reduction with divide by -1", QStringLiteral("-1*cos(pi)^2/cos(pi)/-1"), false); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2/cos(pi)/-1"), QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2/cos(pi)/(-1)"), QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2/cos(pi)/1"), QString(UnicodeChars::MinusSign) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2/cos(pi)*1"), QString(UnicodeChars::MinusSign) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2/cos(pi)*(-1)"), QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("cos(pi)*(-1)"), QString(UnicodeChars::MinusSign) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("cos(pi)*-1"), QString(UnicodeChars::MinusSign) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)"), QString(UnicodeChars::MinusSign) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("(-1)*cos(pi)"), QString(UnicodeChars::MinusSign) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("(-1) cos(pi)"), QString(UnicodeChars::MinusSign) + QStringLiteral("cos(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2*cos(pi)*cos(pi)/cos(pi)^2"), QString::fromUtf8("−cos²(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2*cos(pi)*cos(pi)/-cos(pi)^2"), QString::fromUtf8("cos²(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("-1*cos(pi)^2*cos(pi)*cos(pi)/(-cos(pi)^2)"), QString::fromUtf8("cos²(pi)")); CHECK_DISPLAY_SIMPLIFIED_INTERPRETED( QStringLiteral("0-1*cos(pi)^2*cos(pi)*cos(pi)/(-cos(pi)^2)"), QString::fromUtf8("cos²(pi)")); { Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); eval->setExpression(QStringLiteral("cos(pi)*cos(pi)*cos(pi)+cos(pi[rad])+cos(pi[rad])")); eval->evalUpdateAns(); const QString interpreted = eval->interpretedExpression(); const QString simplified = Evaluator::simplifyInterpretedExpression(interpreted); ++eval_total_tests; if (eval->error().isEmpty() && simplified == interpreted) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsimplify trig expression with explicit angle unit\t[NEW]" << endl << "\tInterpreted: " << interpreted.toUtf8().constData() << endl << "\tSimplified : " << simplified.toUtf8().constData() << endl; } const QString interpretedDisplay = Evaluator::formatInterpretedExpressionForDisplay(interpreted, eval); const QString simplifiedDisplay = Evaluator::formatInterpretedExpressionSimplifiedForDisplay(interpreted, eval); ++eval_total_tests; if (eval->error().isEmpty() && simplifiedDisplay == interpretedDisplay) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tshow simplified display line for trig with explicit angle unit\t[NEW]" << endl << "\tInterpreted: " << interpretedDisplay.toUtf8().constData() << endl << "\tSimplified : " << simplifiedDisplay.toUtf8().constData() << endl; } settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); } { Settings* settings = Settings::instance(); const char oldAngleUnit = settings->angleUnit; settings->angleUnit = 'd'; Evaluator::instance()->initializeAngleUnits(); const QString expr = QString::fromUtf8( "cos(pi)*cos(pi)*cos(pi)+cos(pi[rad])+cos(pi[°])+cos(pi[rad])"); CHECK_EVAL(expr, "-0.00600462826322460879"); eval->setExpression(expr); eval->evalUpdateAns(); const QString interpreted = eval->interpretedExpression(); const QString simplified = Evaluator::simplifyInterpretedExpression(interpreted); ++eval_total_tests; const QString expectedSimplified = QStringLiteral("cos(pi)^3+2") + QString(MathDsl::MulDotOp) + QString::fromUtf8("cos(pi[rad])+cos(pi[°])"); if (eval->error().isEmpty() && simplified != expectedSimplified) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << __FILE__ << "[" << __LINE__ << "]\tsimplify mixed explicit angle units in degree mode\t[NEW]" << endl << "\tInterpreted: " << interpreted.toUtf8().constData() << endl << "\tSimplified : " << simplified.toUtf8().constData() << endl << "\tExpected : " << expectedSimplified.toUtf8().constData() << endl; } settings->angleUnit = oldAngleUnit; Evaluator::instance()->initializeAngleUnits(); } } void test_unit_lookup_registry_aliases() { const auto check = [](bool passed, const QString& message) { ++eval_total_tests; if (!passed) { ++eval_failed_tests; ++eval_new_failed_tests; cerr << "Unit lookup: " << message.toUtf8().constData() << "\t[NEW]" << endl; } }; const auto& registered = Units::builtInUnitValues(); const QStringList identifiers {QStringLiteral("Pa"), QStringLiteral("pA"), QStringLiteral("hPa"), QStringLiteral("hectopascal"), QStringLiteral("KiB"), QStringLiteral("sr")}; const QHash displayNames { {QStringLiteral("Pa"), QStringLiteral("pascal")}, {QStringLiteral("hPa"), QStringLiteral("hPa")}, {QStringLiteral("hectopascal"), QStringLiteral("hectopascal")}, {QStringLiteral("KiB"), QStringLiteral("KiB")}, {QStringLiteral("sr"), QStringLiteral("sr")} }; for (const char mode : {'r', 'd', 'g', 't', 'v'}) { const auto lookup = Units::builtInUnitLookup(mode); const QString context = QStringLiteral("angle mode %1: ").arg(QLatin1Char(mode)); QStringList missing; for (auto it = registered.constBegin(); it != registered.constEnd(); ++it) { if (!lookup.contains(it.key())) missing.append(it.key()); } check(missing.isEmpty(), context + QStringLiteral("missing identifiers: ") + missing.join(QLatin1Char(' '))); for (const QString& identifier : identifiers) { const auto actual = lookup.constFind(identifier); const auto expected = registered.constFind(identifier); check(actual != lookup.constEnd() && expected != registered.constEnd() && actual.value() == expected.value(), context + identifier + QStringLiteral(" changes value or dimension")); } for (auto it = displayNames.constBegin(); it != displayNames.constEnd(); ++it) { const auto actual = lookup.constFind(it.key()); check(actual != lookup.constEnd() && actual.value().hasUnit() && actual.value().unitName() == it.value() && actual.value().unit() == actual.value().numericValue(), context + it.key() + QStringLiteral(" loses its display unit")); } check(!lookup.value(QStringLiteral("Pa")).sameDimension(lookup.value(QStringLiteral("pA"))), context + QStringLiteral("Pa and pA must remain distinct")); } Units::builtInUnitLookup(Settings::instance()->angleUnit); } int main(int argc, char* argv[]) { if (qEnvironmentVariableIsEmpty("QT_QPA_PLATFORM")) qputenv("QT_QPA_PLATFORM", "offscreen"); QApplication app(argc, argv); Settings* settings = Settings::instance(); settings->angleUnit = 'r'; settings->numberFormatStyle = Settings::NumberFormatNoGroupingDot; settings->applyNumberFormatStyle(); settings->complexNumbers = false; settings->imaginaryUnit = 'i'; settings->resultRoundingMode = Settings::ResultRoundingHalfAwayFromZero; setRuntimeResultRoundingMode(settings->resultRoundingMode); CMath::setImaginaryUnitSymbol(QLatin1Char('i')); DMath::complexMode = false; static Session mainSession; evalSession = &mainSession; eval = evalSession->evaluator(); eval->initializeBuiltInVariables(); test_constants(); test_exponentiation(); test_unary(); test_binary(); test_units(); test_unit_lookup_registry_aliases(); test_unit_expression_powers(); test_percent_operator(); test_bitwise_complement_operator(); test_divide_by_zero(); test_radix_char(); test_thousand_sep(); test_number_format_decimal_separator(); test_number_format_styles_matrix(); test_tolerant_number_input_with_dot_style(); test_number_format_style_behavior_all_supported_styles(); test_tolerant_number_input_all_styles(); test_settings_default_result_line_behavior(); test_extra_result_lines_profile_formatting(); test_sexagesimal(); test_dms_function_formats_like_sexagesimal_notation(); test_rational_format(); test_function_basic(); test_function_root(); test_function_trig(); test_function_tanh_range(); test_function_stat(); test_function_logic(); test_function_discrete(); test_function_simplified(); test_lists_and_matrices(); test_auto_fix_parentheses(); test_auto_fix_ans(); test_auto_fix_trailing_equal(); test_auto_fix_powers(); test_auto_fix_shift_add_sub(); test_auto_fix_untouch(); test_comments(); test_comments_do_not_change_result_formatting(); test_comment_and_description_edge_cases(); test_result_display_history_mapping_after_multiple_lines_toggle_with_comment_only_entry(); test_result_display_scroll_edge_gradient_height_scales_with_font_zoom(); test_user_functions(); test_user_units(); test_implicit_multiplication(); test_display_interpreted_spacing(); settings->complexNumbers = true; DMath::complexMode = true; eval->initializeBuiltInVariables(); test_complex(); test_function_tanh_range(); test_format(); test_result_rounding_mode_formatting(); test_datetime(); test_epoch(); test_expression_operator_normalization(); test_session_history_limit(); test_session_deserialize_without_history(); test_session_owns_distinct_evaluator_state(); test_session_globals_deserialize_preserves_existing_definitions(); test_session_deserialize_rejects_invalid_schema_without_mutating(); test_function_usage_tooltip(); test_grouped_numeric_literal_display_format(); test_pasted_standalone_numeric_literal_reformatting(); test_display_root_aliases_for_result_lines(); test_display_spacing_stability_for_unit_conversion(); test_display_conversion_with_unicode_spaces_and_cross_units(); test_preserve_brackets_for_displayed_conversion_target(); test_preserve_brackets_for_displayed_conversion_target_without_source_hint(); test_result_display_preserves_conversion_target_brackets(); test_result_display_preserves_converted_sexagesimal_expression_line(); test_result_display_adds_normalized_sexagesimal_simplification_line(); test_result_display_highlights_simplified_expression_line(); test_result_display_highlights_primary_result_with_extra_result_line(); test_result_display_highlights_primary_sexagesimal_result_with_extra_result_line(); test_result_display_highlights_primary_radian_result_with_pi_factor_line(); test_result_display_adds_normalized_sexagesimal_simplification_line_for_arithmetic(); test_result_display_preserves_fractional_seconds_in_normalized_sexagesimal_line(); test_result_display_normalized_sexagesimal_line_with_time_conversion_target(); test_sexagesimal_arithmetic_with_per_term_conversion_targets(); test_result_display_mixed_per_term_time_conversions(); test_result_display_mixed_per_term_time_conversions_in_sexagesimal_notation(); test_result_display_time_unit_sum_respects_decimal_and_sexagesimal_notation_modes(); test_result_display_strips_unit_brackets_and_double_click_restores_canonical_unit_expression(); test_result_display_double_click_selects_list_result(); test_result_display_uses_base10_exponent_notation(); test_result_display_scientific_units_use_unprefixed_si_units(); test_result_display_omits_zero_power_of_ten_generically(); test_result_display_double_click_preserves_compact_angle_suffix(); test_result_display_shows_angle_mode_unit_suffix_for_explicit_angle_input(); test_result_display_keeps_quantsp_before_degree_celsius_and_fahrenheit(); test_value_unit_separator_normalization(); test_result_display_preserves_standalone_sexagesimal_angles_without_implicit_conversion(); test_result_display_adds_simplified_line_for_unit_conversion_when_interpreted_is_empty(); test_result_display_adds_simplified_line_for_unit_conversion_with_interpreted_expression(); test_result_display_shows_pi_multiples_for_radian_angle_results(); test_result_display_compacts_bracketed_degree_inside_trig_call(); test_trig_symbolic_fraction_half(); test_interpreted_quotient_simplification(); test_non_informative_numeric_simplified_row_suppression(); test_angle_mode(settings); if (!eval_failed_tests) return 0; cout << eval_total_tests << " total, " << eval_failed_tests << " failed, " << eval_new_failed_tests << " new" << endl; return eval_new_failed_tests; } heldercorreia-speedcrunch-e7ca37f/src/tests/testfloatnum.c000066400000000000000000005714631526573132500241770ustar00rootroot00000000000000/* testfloatnum.c: regression test for floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. Copyright (C) 2026 @heldercorreia This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ /*====================================================================== REGRESSION TESTS =======================================================================*/ /* a few tests depend on 32 bit integer size, fix this in future!! */ #include "math/floatnum/floatconst.h" #include "math/floatnum/floatcommon.h" #include "math/floatnum/floatconvert.h" #include "math/floatnum/floatlog.h" #include "math/floatnum/floatexp.h" #include "math/floatnum/floattrig.h" #include "math/floatnum/floathmath.h" #include "math/floatnum/floatipower.h" #include "math/floatnum/floatpower.h" #include "math/floatnum/floatgamma.h" #include "math/floatnum/floatlogic.h" #include "math/floatnum/floaterf.h" #include #include #include #include #ifdef _FLOATNUMTEST #ifndef FLOATNUM_TEST_DEBUG #define FLOATNUM_TEST_DEBUG 0 #endif static int should_print_message(const char* msg) { return strstr(msg, "FAILED") != NULL || strstr(msg, "failed") != NULL || strstr(msg, "IMPRECISE") != NULL || strstr(msg, "imprecise") != NULL; } static int filtered_printf(const char* fmt, ...) { int result = 0; va_list args; if (!FLOATNUM_TEST_DEBUG && !should_print_message(fmt)) return 0; va_start(args, fmt); result = vprintf(fmt, args); va_end(args); return result; } #define printf(...) filtered_printf(__VA_ARGS__) /* From math/floaterf.c */ char erfseries(floatnum x, int digits); char erfcsum(floatnum x, int digits); char erfcasymptotic(floatnum x, int digits); /* From math/floatgamma.c */ char binetasymptotic(floatnum x, int digits); #define msbu (1u << (sizeof(unsigned)*8-1)) #define maxu (msbu + (msbu-1)) #define msbi (1 << (sizeof(int)*8-2)) #define maxi (msbi + (msbi -1)) #define mini (-maxi - 1) static int g_total_tests = 0; static int g_failed_tests = 0; static int g_new_failed_tests = 0; #define tc_out(value, digits, base, mode, result) \ _tc_out(__FILE__,__LINE__, #value"/"#digits"/"#base"/"#mode, \ value, digits, base, mode, result) #define tc_in(expr, result) \ _tc_in(__FILE__,__LINE__, #expr, expr, result) void DisplayErrorOnStrMismatch(const char* file, int line, const char* msg, const char *result, const char* expected, int *failed, int *newFailed, int issue) { if (strcmp(result, expected) != 0) { ++(*failed); fprintf(stderr, "%s[%d]\t%s\tFAILED\n", file, line, msg); if (issue) fprintf(stderr, "\t[ISSUE %d]\n", issue); else { fprintf(stderr, "\t[NEW]\n"); ++(*newFailed); } fprintf(stderr, "\tResult : %s\n", result); fprintf(stderr, "\tExpected : %s\n", expected); } } static const char* float2str(const floatstruct* x) { static char buffer[350]; float_getscientific(buffer, 110, x); return buffer; } void DisplayErrorOnFloatMismatch(const char* file, int line, const char* msg, const floatstruct* result, const floatstruct* expected, int *failed, int *newFailed, int issue) { int cmp; if (float_isnan(result) && float_isnan(expected)) cmp = 0; else cmp = float_cmp(expected, result); if (cmp != 0) { ++(*failed); fprintf(stderr, "%s[%d]\t%s\tFAILED\n", file, line, msg); if (issue) fprintf(stderr, "\t[ISSUE %d]\n", issue); else { fprintf(stderr, "\t[NEW]\n"); ++(*newFailed); } fprintf(stderr, "\tResult : %s\n", float2str(result)); fprintf(stderr, "\tExpected : %s\n", float2str(expected)); } } static char logequiv(int v1, int v2) { return ((v1 == 0) && (v2 == 0)) || ((v1 != 0) && (v2 != 0)); } static unsigned rol(unsigned u) { return (u << 1) | (u >> (sizeof(unsigned)*8-1)); } static unsigned hash(floatnum x) { unsigned result; bc_num bc; char* p; int i; result = 0; if (x) { bc = x->significand; result = rol(x->exponent) ^ (unsigned)(uintptr_t)bc; if (bc) { result = rol(result) ^ bc->n_sign; result = rol(result) ^ bc->n_len; result = rol(result) ^ bc->n_scale; p = bc->n_value; result = rol(result) ^ (unsigned)(uintptr_t)p; for (i = 0; i++ <= bc->n_scale;) result = rol(result) ^ *(p++); } } return result; } static char istruenan(floatnum x) { return x->exponent == EXPNAN && x->significand == NULL; } static signed char _cmp(floatnum v1, floatnum v2) { if (float_isnan(v1) && float_isnan(v2)) return 0; return float_cmp(v1, v2); } static char mantcmp(bc_num b, const char* s) { char* p; int lg, i; p = b->n_value; lg = (int)strlen(s); if (maxdigits < lg) lg = maxdigits; while (s[lg-1] == '0') --lg; if (lg != b->n_scale + 1) return 0; for (i = -1; ++i < lg;) if (s[i] - '0' != *(p++)) return 0; return 1; } static int scmp(floatnum v, char* s) { char buf[30]; float_getscientific(buf, 30, v); return strcmp(buf, s) == 0; } static char* maxexp(char* buf, char* significand) { int lg; lg = (int)strlen(significand); memcpy(buf, significand, lg); sprintf(buf + lg, "%d", float_getrange()); return buf; } static char* minexp(char* buf, char* significand) { int lg; lg = (int)strlen(significand); memcpy(buf, significand, lg); sprintf(buf+lg, "%d", -float_getrange()-1); return buf; } static int tc_fail(int i) { printf("test case %d failed", i + 1); return 0; } static int tc_longadd(unsigned v1, unsigned v2, unsigned r1, unsigned r2) { unsigned x1, x2, y1, y2; x1 = v1; x2 = v2; y1 = v2; y2 = v1; _longadd(&x1, &x2); _longadd(&y1, &y2); return x1 == r1 && x2 == r2 && y1 == r1 && y2 == r2; } static int test_longadd() { static struct{ unsigned v1; unsigned v2; unsigned r1; unsigned r2; } testcases[] = { {0, 0, 0, 0}, {1, 2, 3, 0}, {msbu, 2, msbu+2, 0}, {1, msbu, msbu+1, 0}, {maxu-1, 1, maxu, 0}, {maxu, 1, 0, 1}, {maxu, maxu, maxu-1, 1}, }; int i; printf("testing _longadd\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longadd(testcases[i].v1, testcases[i].v2, testcases[i].r1, testcases[i].r2)) return tc_fail(i); return 1; } static int tc_longmul(unsigned v1, unsigned v2, unsigned r1, unsigned r2) { unsigned x1, x2, y1, y2; x1 = v1; x2 = v2; y1 = v2; y2 = v1; _longmul(&x1, &x2); _longmul(&y1, &y2); return x1 == r1 && x2 == r2 && y1 == r1 && y2 == r2; } static int test_longmul() { static struct{ unsigned v1; unsigned v2; unsigned r1; unsigned r2; } testcases[] = { {0, 0, 0, 0}, {0, 1, 0, 0}, {1, 2, 2, 0}, {msbu, 2, 0, 1}, {1, msbu, msbu, 0}, {maxu-1, 1, maxu-1, 0}, {maxu, 2, maxu-1, 1}, {maxu, maxu, 1, maxu-1}, }; int i; printf("testing _longmul\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longmul(testcases[i].v1, testcases[i].v2, testcases[i].r1, testcases[i].r2)) return tc_fail(i); return 1; } static int tc_longshr(unsigned v1, unsigned v2, char shift, unsigned result) { unsigned r; r = _longshr(v1, v2, shift); return r == result; } static int test_longshr() { static struct{ unsigned v1; unsigned v2; char shift; unsigned r; } testcases[] = { {0, 0, 5, 0}, {47, 12, 3, msbu+5}, }; int i; printf("testing _longshr\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longshr(testcases[i].v1, testcases[i].v2, testcases[i].shift, testcases[i].r)) return tc_fail(i); return 1; } static int tc_checkadd(int v1, int v2, char ok, int result) { int x, y; x = v1; y = v2; return _checkadd(&x, v2) == ok && _checkadd(&y, v1) == ok && x == result && y == result; } static int test_checkadd() { static struct{ int v1; int v2; char ok; int r; } testcases[] = { {0, 0, 1, 0}, {1, 0, 1, 1}, {maxi, 0, 1, maxi}, {0, mini, 1, mini}, {maxi, 1, 0, mini}, {mini, -1, 0, maxi}, }; int i; printf("testing _checkadd\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_checkadd(testcases[i].v1, testcases[i].v2, testcases[i].ok, testcases[i].r)) return tc_fail(i); return 1; } static int tc_checkmul(int v1, int v2, char ok, int result) { int x, y; x = v1; y = v2; return _checkmul(&x, v2) == ok && _checkmul(&y, v1) == ok && x == result && y == result; } static int test_checkmul() { int i; static struct{ int v1; int v2; char ok; int r; } testcases[] = { {0, 0, 1, 0}, {1, 1, 1, 1}, {-1, 1, 1, -1}, {-1, -1, 1, 1}, {maxi, 1, 1, maxi}, {maxi, 2, 0, -2}, {1, mini, 1, mini}, {-1, mini, 0, mini}, {2, mini, 0, 0}, }; printf("testing _checkmul\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_checkmul(testcases[i].v1, testcases[i].v2, testcases[i].ok, testcases[i].r)) return tc_fail(i); return 1; } static int tc_longarrayadd(unsigned x1, unsigned x2, unsigned x3, unsigned smd, unsigned r1, unsigned r2, unsigned r3, unsigned r4, int length) { unsigned a[3]; unsigned r; a[0] = x1; a[1] = x2; a[2] = x3; r = _longarrayadd(a, length, smd); return a[0] == r1 && a[1] == r2 && a[2] == r3 && r == r4; } static int test_longarrayadd() { int i; static struct{ unsigned x1; unsigned x2; unsigned x3; unsigned smd; unsigned r1; unsigned r2; unsigned r3; unsigned r4; int lg; } testcases[] = { {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,3}, {1,2,3,4,5,2,3,0,3}, {maxu,2,3,4,3,3,3,0,3}, {maxu,maxu,3,4,3,0,4,0,3}, {maxu,maxu,maxu,4,3,0,0,1,3}, {0,0,0,1,0,0,0,1,0}, {1,0,0,1,2,0,0,0,1}, {maxu,0,0,1,0,0,0,1,1}, }; printf("testing _longarrayadd\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longarrayadd(testcases[i].x1, testcases[i].x2, testcases[i].x3, testcases[i].smd, testcases[i].r1, testcases[i].r2, testcases[i].r3, testcases[i].r4, testcases[i].lg)) return tc_fail(i); return 1; } static int tc_longarraymul(unsigned x1, unsigned x2, unsigned x3, unsigned factor, unsigned r1, unsigned r2, unsigned r3, unsigned r4, int lg) { unsigned a[3]; unsigned r; a[0] = x1; a[1] = x2; a[2] = x3; r = _longarraymul(a, lg, factor); return a[0] == r1 && a[1] == r2 && a[2] == r3 && r == r4; } static int test_longarraymul() { int i; static struct{ unsigned x1; unsigned x2; unsigned x3; unsigned smd; unsigned r1; unsigned r2; unsigned r3; unsigned r4; int lg; } testcases[] = { {0,0,0,0,0,0,0,0,0}, {0,0,0,7,0,0,0,0,0}, {7,0,0,7,49,0,0,0,1}, {0,0,0,3,0,0,0,0,3}, {1,2,3,4,4,8,12,0,3}, {maxu,0,0,4,maxu-3,0,0,3,1}, {maxu,2,3,4,maxu-3,11,12,0,3}, {maxu,maxu,3,4,maxu-3,maxu,15,0,3}, {maxu,maxu,maxu,4,maxu-3,maxu,maxu,3,3}, {maxu,0,0,maxu,1,maxu-1,0,0,3}, {maxu,maxu,maxu,maxu,1,maxu,maxu,maxu-1,3}, }; printf("testing _longarraymul\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_longarraymul(testcases[i].x1, testcases[i].x2, testcases[i].x3, testcases[i].smd, testcases[i].r1, testcases[i].r2, testcases[i].r3, testcases[i].r4, testcases[i].lg)) return tc_fail(i); return 1; } static int tc_isnan(void* s, int exp, char result) { floatstruct f; float_geterror(); f.significand = s; f.exponent = exp; return float_isnan(&f) == result && exp == f.exponent && f.significand == s && float_geterror() == Success; } static int test_isnan() { static struct{ void* s; int exp; char result; } testcases[] = { {NULL, EXPNAN, 1}, {NULL, EXPZERO, 0}, {NULL, 0, 1}, {(void*)1, 0, 0}, {(void*)1, EXPNAN, 0}, }; int i; printf("testing float_isnan\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_isnan(testcases[i].s, testcases[i].exp, testcases[i].result)) return tc_fail(i); return 1; } static int tc_iszero(void* s, int exp, char result) { floatstruct f; float_geterror(); f.significand = s; f.exponent = exp; return float_iszero(&f) == result && exp == f.exponent && f.significand == s && float_geterror() == Success; } static int test_iszero() { static struct{ void* s; int exp; char result; } testcases[] = { {NULL, EXPNAN, 0}, {NULL, EXPZERO, 1}, {NULL, 0, 0}, {(void*)1, 0, 0}, {(void*)1, EXPZERO, 0}, }; int i; printf("testing float_iszero\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_iszero(testcases[i].s, testcases[i].exp, testcases[i].result)) return tc_fail(i); return 1; } static int tc_create(void* s, int exp) { floatstruct f; float_geterror(); f.significand = s; f.exponent = exp; float_create(&f); return istruenan(&f) && float_geterror() == Success; } static int test_create() { static struct{ void* s; int exp; } testcases[] = { {NULL, EXPNAN}, {NULL, EXPZERO}, {NULL, 0}, {(void*)1, 0}, {(void*)1, EXPNAN}, {(void*)1, EXPZERO}, }; int i; printf("testing float_create\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_create(testcases[i].s, testcases[i].exp)) return tc_fail(i); return 1; } static int tc_setnan(char one, int exp) { floatstruct f; int refs; float_geterror(); refs = _one_->n_refs; f.significand = NULL; if (one) f.significand = bc_copy_num(_one_); f.exponent = exp; float_setnan(&f); return istruenan(&f) && refs == _one_->n_refs && float_geterror() == Success; } static int test_setnan() { static struct{ char one; int exp; } testcases[] = { {0, EXPNAN}, {0, EXPZERO}, {0, 0}, {1, 0}, {1, EXPNAN}, {1, EXPZERO}, }; int i; printf("testing float_setnan\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setnan(testcases[i].one, testcases[i].exp)) return tc_fail(i); return 1; } static int tc_setzero(char one, int exp) { floatstruct f; int refs; float_geterror(); refs = _one_->n_refs; f.significand = NULL; if (one) f.significand = bc_copy_num(_one_); f.exponent = exp; float_setzero(&f); return float_iszero(&f) && refs == _one_->n_refs && float_geterror() == Success; } static int test_setzero() { static struct{ char one; int exp; } testcases[] = { {0, EXPNAN}, {0, EXPZERO}, {0, 0}, {1, 0}, {1, EXPNAN}, {1, EXPZERO}, }; int i; printf("testing float_setzero\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setzero(testcases[i].one, testcases[i].exp)) return tc_fail(i); return 1; } static int tc_setsignificand(const char* mant, int mlg, const char* result, int dot, int zeros) { floatstruct f; int refs; int save; int z, d, i; char retvalue; float_create(&f); retvalue = 1; float_geterror(); /* test zero or NaN cases */ if (result == NULL || result[0] == '0') { z = -1; refs = _one_->n_refs; f.exponent = 12; f.significand = bc_copy_num(_one_); f.significand->n_sign = MINUS; d = float_setsignificand(&f, &z, mant, mlg); if (result == NULL) retvalue = istruenan(&f); else if (result[0] == '0') retvalue = float_iszero(&f); retvalue = retvalue && refs == _one_->n_refs && dot == d && z == zeros && float_geterror() == Success; } if (retvalue) { /* test NULL zeros pointer */ d = float_setsignificand(&f, NULL, mant, mlg); if (result == NULL) retvalue = istruenan(&f); else if (result[0] == '0') retvalue = float_iszero(&f); else retvalue = f.significand != NULL && f.exponent == 0 && f.significand->n_len == 1 && f.significand->n_sign == PLUS && mantcmp(f.significand, result); retvalue = retvalue && dot == d && float_geterror() == Success; } if (retvalue && result != NULL && result[0] != '0') { save = maxdigits; for (i = 0; retvalue && ++i <= save;) { maxdigits = i; refs = _one_->n_refs; f.exponent = 12; f.significand = bc_copy_num(_one_); f.significand->n_sign = MINUS; z = -1; d = float_setsignificand(&f, &z, mant, mlg); retvalue = f.significand != NULL && refs == _one_->n_refs && f.significand->n_len == 1 && f.significand->n_sign == PLUS && mantcmp(f.significand, result) && dot == d && z == zeros && f.exponent == 0 && float_geterror() == Success; } maxdigits = save; } _one_->n_sign = PLUS; float_setnan(&f); float_free(&f); return retvalue; } static int test_setsignificand() { static struct{ const char* mant; int lg; const char* result; int dot; int zeros; } testcases[] = { {NULL, -1, NULL, -1, 0}, {NULL, 0, NULL, -1, 0}, {"", NULLTERMINATED, NULL, -1, 0}, {".", NULLTERMINATED, NULL, -1, 0}, {"x", NULLTERMINATED, NULL, -1, 0}, {"-1", NULLTERMINATED, NULL, -1, 0}, {"+1", NULLTERMINATED, NULL, -1, 0}, {"1E", NULLTERMINATED, NULL, -1, 0}, {"1.E", NULLTERMINATED, NULL, -1, 0}, {"-1.E", NULLTERMINATED, NULL, -1, 0}, {"1E1", NULLTERMINATED, NULL, -1, 0}, {"1.E1", NULLTERMINATED, NULL, -1, 0}, {"1.1E1", NULLTERMINATED, NULL, -1, 0}, {"1.1e1", NULLTERMINATED, NULL, -1, 0}, {"1E+1", NULLTERMINATED, NULL, -1, 0}, {"1.E+1", NULLTERMINATED, NULL, -1, 0}, {"1.1E+1", NULLTERMINATED, NULL, -1, 0}, {"1.1e+1", NULLTERMINATED, NULL, -1, 0}, {"1.1(1)", NULLTERMINATED, NULL, -1, 0}, {"1.1(+1)", NULLTERMINATED, NULL, -1, 0}, {"+1E1", NULLTERMINATED, NULL, -1, 0}, {"+1.E1", NULLTERMINATED, NULL, -1, 0}, {"+1.1E1", NULLTERMINATED, NULL, -1, 0}, {"+1.1e1", NULLTERMINATED, NULL, -1, 0}, {"+1.1(1)", NULLTERMINATED, NULL, -1, 0}, {"+1.1(+1)", NULLTERMINATED, NULL, -1, 0}, {"-1.E1", NULLTERMINATED, NULL, -1, 0}, {"1.E-1", NULLTERMINATED, NULL, -1, 0}, {"-1.E-1", NULLTERMINATED, NULL, -1, 0}, {"1111111111111111111111E1", NULLTERMINATED, NULL, -1, 0}, {"E1", NULLTERMINATED, NULL, -1, 0}, {".e", NULLTERMINATED, NULL, -1, 0}, {".1e", NULLTERMINATED, NULL, -1, 0}, {"1.e1", NULLTERMINATED, NULL, -1, 0}, {"e1.", NULLTERMINATED, NULL, -1, 0}, {".1.", NULLTERMINATED, NULL, -1, 0}, {"1..", NULLTERMINATED, NULL, -1, 0}, {"1.000000000000000000.0", NULLTERMINATED, NULL, -1, 0}, {"0", NULLTERMINATED, "0", -1, 0}, {"0.", NULLTERMINATED, "0", -1, 0}, {".0", NULLTERMINATED, "0", -1, 0}, {"000", NULLTERMINATED, "0", -1, 0}, {"00000000000", NULLTERMINATED, "0", -1, 0}, {".00000000000", NULLTERMINATED, "0", -1, 0}, {"00000000000.", NULLTERMINATED, "0", -1, 0}, {"000000.00000", NULLTERMINATED, "0", -1, 0}, {"1", -1, NULL, -1, 0}, {"1", 0, NULL, -1, 0}, {"1", 1, "1", -1, 0}, {"1", NULLTERMINATED, "1", -1, 0}, {"12", 1, "1", -1, 0}, {"12", NULLTERMINATED, "12", -1, 0}, {".1", NULLTERMINATED, "1", 0, 0}, {"1.", NULLTERMINATED, "1", 1, 0}, {"1.2", NULLTERMINATED, "12", 1, 0}, {"01.2", NULLTERMINATED, "12", 2, 1}, {"00.000000000000012", NULLTERMINATED, "12", 2, 15}, {"12.3456789000", NULLTERMINATED, "123456789", 2, 0}, {"12345678900.0", NULLTERMINATED, "123456789", 11, 0}, {"12345678901", NULLTERMINATED, "12345678901", -1, 0}, {"123456789012", NULLTERMINATED, "12345678901", -1, 0}, {"1.2345678901", NULLTERMINATED, "12345678901", 1, 0}, {"0.12345678901", NULLTERMINATED, "12345678901", 1, 1}, {"0.012345678901", NULLTERMINATED, "12345678901", 1, 2}, {"1234567890183456789", NULLTERMINATED, "12345678901", -1, 0}, {"12345678900123456789", NULLTERMINATED, "123456789", -1, 0}, {"12345678901234567.89", NULLTERMINATED, "12345678901", 17, 0}, }; int i, save; printf("testing float_setsignificand\n"); save = maxdigits; maxdigits = 11; for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setsignificand(testcases[i].mant, testcases[i].lg, testcases[i].result, testcases[i].dot, testcases[i].zeros)) return tc_fail(i); maxdigits = save; return 1; } static int tc_getsignificand(const char* value, int bufsz, const char* result) { char buf[30]; int lg, i, j; unsigned h; floatstruct f; char retvalue; static int exp[] = {-2, -1, 0, 1, 2, EXPNAN, EXPZERO, MAXEXP, -MAXEXP-1}; static int sign[] = {PLUS, MINUS}; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_geterror(); if (float_isnan(&f) || float_iszero(&f)) { memset(buf, '?', 30); h = hash(&f); lg = (int)strlen(result); retvalue = float_getsignificand(buf+1, bufsz, &f) == lg && buf[0] == '?' && buf[lg + 1] == '?' && memcmp(buf + 1, result, lg) == 0 && h == hash(&f) && float_geterror() == Success; } else for (i = sizeof(exp)/sizeof(int); --i >= 0;) for (j = -1; ++j < 2;) { lg = (int)strlen(result); memset(buf, '?', 30); f.significand->n_sign = sign[j]; f.exponent = exp[i]; h = hash(&f); retvalue = float_getsignificand(buf+1, bufsz, &f) == lg && h == hash(&f) && buf[0] == '?' && buf[lg + 1] == '?' && memcmp(buf + 1, result, lg) == 0 && float_geterror() == Success; } float_free(&f); return retvalue; } static int test_getsignificand() { static const char v1[] = "1"; static const char v2[] = "12345678901"; static struct{ const char* value; int bufsz; const char* result; } testcases[] = { {v1, -1, ""}, {v1, 0, ""}, {v1, 1, "1"}, {v1, 2, "1"}, {"N", 0, ""}, {"N", 1, "N"}, {"N", 2, "N"}, {"0", 0, ""}, {"0", 1, "0"}, {"0", 2, "0"}, {v2, 1, "1"}, {v2, 2, "12"}, {v2, 10, "1234567890"}, {v2, 11, "12345678901"}, {v2, 12, "12345678901"}, }; int i; printf("testing float_getsignificand\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getsignificand(testcases[i].value, testcases[i].bufsz, testcases[i].result)) return tc_fail(i); return 1; } static int tc_setexponent(const char* value, int exp, int range, int result, char valid) { floatstruct f; int save, i; char buf[30]; static int sign[] = {PLUS, MINUS}; save = float_setrange(range); float_geterror(); float_create(&f); for (i = -1; ++i < 2;) { float_setsignificand(&f, NULL, value, NULLTERMINATED); if (!float_isnan(&f) && !float_iszero(&f)) { f.exponent = -123; f.significand->n_sign = sign[i]; } float_setexponent(&f, exp); buf[float_getsignificand(buf, 30, &f)] = '\0'; if (valid) { if (strcmp(buf, value) != 0 || f.exponent != result || (f.significand && f.significand->n_sign != sign[i])) return 0; } else if(!istruenan(&f)) return 0; } float_free(&f); float_setrange(save); return float_geterror() == Success; } static int test_setexponent() { int i; static struct{ const char* mant; int exp; int range; int result; char valid; } testcases[] = { {"N", 0, 100, EXPNAN, 1}, {"N", 1, 100, EXPNAN, 1}, {"N", -1, 100, EXPNAN, 1}, {"N", EXPNAN, 100, EXPNAN, 1}, {"N", 100, 100, EXPNAN, 1}, {"N", EXPZERO, 100, EXPNAN, 1}, {"0", 0, 100, EXPZERO, 1}, {"0", 1, 100, EXPZERO, 1}, {"0", -1, 100, EXPZERO, 1}, {"0", EXPNAN, 100, EXPZERO, 1}, {"0", EXPNAN - 1, 100, EXPZERO, 1}, {"0", EXPZERO, 100, EXPZERO, 1}, {"1", 0, 100, 0, 1}, {"12", 100, 100, 100, 1}, {"12", 101, 100, 0, 0}, {"13", -101, 100, -101, 1}, {"121", -102, 100, 0, 0}, {"1432", EXPNAN, 100, 0, 0}, {"1432", EXPZERO, 100, 0, 0}, {"1432", MAXEXP, MAXEXP, MAXEXP, 1}, {"1432", -MAXEXP-1, MAXEXP, -MAXEXP-1, 1}, }; printf("testing float_setexponent\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setexponent(testcases[i].mant, testcases[i].exp, testcases[i].range, testcases[i].result, testcases[i].valid)) return tc_fail(i); return 1; } static int tc_getexponent(const char* value, int exp, int result) { floatstruct f; unsigned h; char retvalue; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); if (!float_isnan(&f) && !float_iszero(&f)) float_setexponent(&f, exp); h = hash(&f); float_geterror(); retvalue = float_getexponent(&f) == result && hash(&f) == h && float_geterror() == Success; float_free(&f); return retvalue; } static int test_getexponent() { static struct{ const char* value; int exp; int result; } testcases[] = { {"N", 0, 0}, {"0", 0, 0}, {"1", 0, 0}, {"1234", 5, 5}, {"24413", -7, -7}, {"623", MAXEXP, MAXEXP}, {"6355", -MAXEXP-1, -MAXEXP-1}, }; int i, save; printf("testing float_getexponent\n"); save = float_setrange(MAXEXP); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getexponent(testcases[i].value, testcases[i].exp, testcases[i].result)) return tc_fail(i); float_setrange(save); return 1; } static int tc_setsign(const char* value, int exp) { floatstruct f; unsigned h, hm; int i; static signed char invsign[] = {2, -2, 127, 126, -128, -127}; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_setexponent(&f, exp); h = hash(&f); if (f.significand) f.significand->n_sign = MINUS; hm = hash(&f); float_geterror(); float_setsign(&f, 0); if ((f.significand && f.significand->n_sign != MINUS) || hm != hash(&f)) return 0; float_setsign(&f, 1); if ((f.significand && f.significand->n_sign != PLUS) || h != hash(&f)) return 0; float_setsign(&f, 0); if ((f.significand && f.significand->n_sign != PLUS) || h != hash(&f)) return 0; float_setsign(&f, 1); if ((f.significand && f.significand->n_sign != PLUS) || h != hash(&f)) return 0; float_setsign(&f, -1); if ((f.significand && f.significand->n_sign != MINUS) || hm != hash(&f)) return 0; float_setsign(&f, -1); if ((f.significand && f.significand->n_sign != MINUS) || hm != hash(&f)) return 0; for (i = sizeof(invsign)/sizeof(signed char); --i >= 0;) { float_setsignificand(&f, NULL, value, NULLTERMINATED); float_setexponent(&f, exp); float_setsign(&f, invsign[i]); if (!istruenan(&f)) return 0; } return float_geterror() == Success; } static int test_setsign() { int i; static struct{ const char* value; int exp; } testcases[] = { {"N", 0}, {"0", 0}, {"1", 0}, {"123", 12}, {"18766", -12}, }; printf("testing float_setsign\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setsign(testcases[i].value, testcases[i].exp)) return tc_fail(i); return 1; } static int tc_getsign(const char* value, int exp, signed char sign, signed char result) { floatstruct f; unsigned h; char retvalue; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_setsign(&f, sign); float_setexponent(&f, exp); h = hash(&f); float_geterror(); retvalue = float_getsign(&f) == result && hash(&f) == h && float_geterror() == Success; float_free(&f); return retvalue; } static int test_getsign() { int i; static struct{ const char* mant; int exp; signed char sign; signed char result; } testcases[] = { {"N", 0, 0, 0}, {"0", 0, 0, 0}, {"1", 0, 1, 1}, {"123", 0, -1, -1}, {"281", 3772, 1, 1}, {"373", 31912, -1, -1}, {"232", -233, 1, 1}, {"123", -1442, -1, -1}, }; printf("testing float_getsign\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getsign(testcases[i].mant, testcases[i].exp, testcases[i].sign, testcases[i].result)) return tc_fail(i); return 1; } static int tc_getlength(const char* value, int result) { floatstruct f; int i; int save; unsigned h; static int exp[] = {0, -1, 1, MAXEXP, -MAXEXP-1}; save = float_setrange(MAXEXP); float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_geterror(); if (float_isnan(&f) || float_iszero(&f)) { h = hash(&f); if (float_getlength(&f) != 0 || h != hash(&f)) return 0; } else { for (i = sizeof(exp)/sizeof(int); --i >= 0;) { float_setexponent(&f, exp[i]); h = hash(&f); if (float_getlength(&f) != result || h != hash(&f)) return 0; float_setsign(&f, -1); h = hash(&f); if (float_getlength(&f) != result || h != hash(&f)) return 0; } } float_free(&f); float_setrange(save); return float_geterror() == Success; } static int test_getlength() { int i; static struct{ const char* mant; int result; } testcases[] = { {"N", 0}, {"0", 0}, {"1", 1}, {"12", 2}, {"123", 3}, {"1234", 4}, {"12345", 5}, {"123456", 6}, {"1234567", 7}, {"12345678", 8}, {"123456789", 9}, }; printf("testing float_getlength\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getlength(testcases[i].mant, testcases[i].result)) return tc_fail(i); return 1; } static int tc_getdigit(const char* value) { floatstruct f; int i, j, k, save, lg; unsigned h; static signed char sign[] = {1, -1}; static int exp[] = {0, -1, 1, MAXEXP, -MAXEXP-1}; float_create(&f); float_setsignificand(&f, NULL, value, NULLTERMINATED); float_geterror(); if (float_getlength(&f) == 0) { h = hash(&f); for (k = -5; ++k < 5;) if (float_getdigit(&f, k) != 0 || h != hash(&f)) return 0; } else { lg = (int)strlen(value); save = float_setrange(MAXEXP); for (i = sizeof(exp)/sizeof(exp[0]); --i >= 0;) for (j = -1; ++j < 2;) { float_setexponent(&f, exp[i]); float_setsign(&f, sign[j]); h = hash(&f); for (k = lg + 3; --k > -3;) if (k < 0 || k >= lg) { if (float_getdigit(&f, k) != 0 || h != hash(&f)) return 0; } else if (float_getdigit(&f, k) != value[k] - '0' || h != hash(&f)) return 0; } float_setrange(save); } float_free(&f); return float_geterror() == Success; } static int test_getdigit() { int i; static struct{ const char* mant; } testcases[] = { {"N"}, {"0"}, {"1"}, {"12"}, {"123"}, {"123456789"}, {"104"}, }; printf("testing float_getdigit\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getdigit(testcases[i].mant)) return tc_fail(i); return 1; } static int tc_getscientific(const char* s, int exp, int sz, const char* result) { floatstruct f; char r[30]; char buf[30]; int lg; unsigned h; float_create(&f); float_setsignificand(&f, NULL, s, NULLTERMINATED); float_setexponent(&f, exp); memset(buf, '?', 30); h = hash(&f); float_geterror(); lg = (int)strlen(result); r[0] = '\0'; if (lg == 0) { if (float_getscientific(buf+1, sz, &f) != -1 || h != hash(&f) || buf[0] != '?' || buf[1] != '?') return 0; } else { memcpy(r, result, lg+1); if (float_getlength(&f) != 0) sprintf(r + lg, "%d", exp); lg = (int)strlen(r); if (float_getscientific(buf+1, sz, &f) != lg || h != hash(&f) || buf[0] != '?' || buf[lg + 2] != '?' || memcmp(buf + 1, r, lg) != 0) return 0; if (float_getlength(&f) != 0) { float_setsign(&f, -1); h = hash(&f); if (float_getscientific(buf+1, sz+1, &f) != lg+1 || h != hash(&f) || buf[0] != '?' || buf[lg + 3] != '?' || buf[1] != '-' || memcmp(buf + 2, r, lg) != 0) return 0; } } float_free(&f); return float_geterror() == Success; } static int test_getscientific() { int i; static struct{ const char* mant; int exp; int sz; const char* result; } testcases[] = { {"N", 0, -1, ""}, {"N", 0, 0, ""}, {"N", 0, 1, ""}, {"N", 0, 2, ""}, {"N", 0, 3, ""}, {"N", 0, 4, "NaN"}, {"N", 0, 5, "NaN"}, {"0", 0, -1, ""}, {"0", 0, 0, ""}, {"0", 0, 1, ""}, {"0", 0, 2, "0"}, {"0", 0, 3, "0"}, {"1", 0, -1, ""}, {"1", 0, 0, ""}, {"1", 0, 1, ""}, {"1", 0, 2, ""}, {"1", 0, 3, ""}, {"1", 0, 4, ""}, {"1", 0, 5, "1.e"}, {"1", 0, 6, "1.e"}, {"12", 0, 4, ""}, {"12", 0, 5, "1.e"}, {"12", 0, 6, "1.2e"}, {"12", 0, 7, "1.2e"}, {"12", 10, 5, ""}, {"12", 10, 6, "1.e"}, {"12", 10, 7, "1.2e"}, {"12", 10, 8, "1.2e"}, {"12345678001", 10, 12, "1.234567e"}, {"12345678001", 10, 13, "1.2345678e"}, {"12345678001", 10, 14, "1.23456780e"}, {"12345678001", 10, 15, "1.234567800e"}, {"12345678001", 10, 16, "1.2345678001e"}, {"12345678001", -10, 13, "1.234567e"}, {"12345678001", -10, 14, "1.2345678e"}, {"12345678001", -10, 15, "1.23456780e"}, {"12345678001", -10, 16, "1.234567800e"}, {"12345678001", -10, 17, "1.2345678001e"}, {"12", 1, 6, "1.2e"}, {"12", -1, 7, "1.2e"}, {"12", MAXEXP, 25, "1.2e"}, {"12", -MAXEXP-1, 25, "1.2e"}, }; int save; printf("testing float_getscientific\n"); save = float_setrange(MAXEXP); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_getscientific(testcases[i].mant, testcases[i].exp, testcases[i].sz, testcases[i].result)) return tc_fail(i); float_setrange(save); return 1; } static int tc_setscientific(const char* value, const char* result) { floatstruct f; char v[40]; char buf[30]; int sz, refs; signed char sign; float_create(&f); float_geterror(); refs = _one_->n_refs; f.exponent = 12; f.significand = bc_copy_num(_one_); float_setscientific(&f, value, NULLTERMINATED); float_getscientific(buf, sizeof(buf), &f); if (refs != _one_->n_refs || strcmp(buf, result) != 0) return 0; sz = (int)strlen(value); memset(v, '1', sizeof(v)); memcpy(v+1, value, sz); float_setscientific(&f, v+1, sz); float_getscientific(buf, sizeof(buf), &f); if (strcmp(buf, result) != 0) return 0; v[0] = '+'; float_setscientific(&f, v, sz+1); float_getscientific(buf, sizeof(buf), &f); if (strcmp(buf, result) != 0) return 0; v[0] = '-'; float_setscientific(&f, v, sz+1); sign = float_getsign(&f); float_setsign(&f, 1); float_getscientific(buf, sizeof(buf), &f); if (sign > 0 || strcmp(buf, result) != 0) return 0; float_free(&f); return float_geterror() == Success; } static int test_setscientific() { int i; static struct{ const char* value; const char* result; } testcases[] = { {"", "NaN"}, {"E", "NaN"}, {".", "NaN"}, {"x", "NaN"}, {"0Ex", "NaN"}, {"0xEx", "NaN"}, {"EE0", "NaN"}, {"00.0.0", "NaN"}, {"0", "0"}, {"0E0", "0"}, {"0E+0", "0"}, {"0E-0", "0"}, {"0E+999999999999999999999999999999", "0"}, {"0E-999999999999999999999999999999", "0"}, {"0000", "0"}, {".0000", "0"}, {"0000.", "0"}, {"00.00", "0"}, {"0000E1", "0"}, {".0000E-1", "0"}, {"0000.E+12", "0"}, {"00.00E-13", "0"}, {"1", "1.e0"}, {"9", "9.e0"}, {"1.", "1.e0"}, {"1.0", "1.e0"}, {"10", "1.e1"}, {"0.1", "1.e-1"}, {"100", "1.e2"}, {"0.01", "1.e-2"}, {"1E0", "1.e0"}, {"1e0", "1.e0"}, {"01e0", "1.e0"}, {"01.e0", "1.e0"}, {"1e1", "1.e1"}, {"1e-1", "1.e-1"}, {"1.e-1", "1.e-1"}, {"1.0e-1", "1.e-1"}, {"01.0e-1", "1.e-1"}, {"0.1e-1", "1.e-2"}, {"10e-1", "1.e0"}, {"100e-1", "1.e1"}, {"1e1000", "1.e1000"}, {"1e-1000", "1.e-1000"}, {"1.234567890123456789e0", "1.23456789012345e0"}, {"1E3000000000000000000000000000000", "NaN"}, {"1E-3000000000000000000000000000000", "NaN"}, }; int save; char buf[30]; printf("testing float_setscientific, 1. block\n"); save = float_setrange(MAXEXP); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setscientific(testcases[i].value, testcases[i].result)) return tc_fail(i); float_setrange(save); printf("testing float_setscientific, 2. block\n"); maxexp(buf, "2.e"); /* maximum exponent 2.eMAXEXP */ if (!tc_setscientific(buf, buf)) return tc_fail(0); buf[1] = '0'; /* combined overflow 20eMAXEXP */ if (!tc_setscientific(buf, "NaN")) return tc_fail(1); ++buf[strlen(buf)-1]; buf[1] = '.'; /* overflow limit 2.e(MAXEXP+1) */ if (!tc_setscientific(buf, "NaN")) return tc_fail(2); minexp(buf, "1.e"); /* minimum exponent */ if (!tc_setscientific(buf, buf)) return tc_fail(3); buf[0] = '.'; buf[1] = '1'; /* combined underflow */ if (!tc_setscientific(buf, "NaN")) return tc_fail(4); buf[0] = '1'; buf[1] = '.'; ++buf[strlen(buf)-1]; /* underflow limit */ if (!tc_setscientific(buf, "NaN")) return tc_fail(5); return 1; } static int tc_setinteger(int value) { floatstruct f, g; char buf[50]; char r[50]; int err; sprintf(r, "%d", value); float_create(&f); float_create(&g); float_geterror(); float_setinteger(&f, value); err = float_geterror(); float_setasciiz(&g, r); float_getscientific(buf, 50, &f); float_getscientific(r, 50, &g); float_free(&f); float_free(&g); return strcmp(buf, r) == 0 && err == Success; } static int test_setinteger() { int i; static struct{ int value; } testcases[] = { {0}, {1}, {9}, {10}, {-1}, {-9}, {-10}, {maxi}, {mini}, }; printf("testing float_setinteger\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_setinteger(testcases[i].value)) return tc_fail(i); return 1; } static int tc_neg(const char* value, signed char result, int error) { floatstruct f; unsigned h; int errcode; signed char sign; char retvalue; char err; float_create(&f); float_setasciiz(&f, value); h = hash(&f); float_geterror(); err = float_neg(&f); errcode = float_geterror(); sign = float_getsign(&f); if (sign != 0) float_neg(&f); retvalue = result == sign && h == hash(&f) && errcode == error && logequiv(errcode, !err); float_free(&f); return retvalue; } static int test_neg() { int i; static struct{ const char* value; signed char result; int error; } testcases[] = { {"NaN", 0, NoOperand}, {"0", 0, Success}, {"1.23", -1, Success}, {"-1.23", 1, Success}, }; printf("testing float_changesign\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_neg(testcases[i].value, testcases[i].result, testcases[i].error)) return tc_fail(i); return 1; } static int tc_abs(const char* value, int error) { floatstruct f; unsigned h; int errcode; signed char sign; char err, retvalue; float_create(&f); float_setasciiz(&f, value); sign = float_getsign(&f); h = hash(&f); float_geterror(); err = float_abs(&f); errcode = float_geterror(); if (sign) retvalue = float_getsign(&f) == 1; else retvalue = float_getsign(&f) == 0; float_setsign(&f, sign); retvalue = retvalue && h == hash(&f) && error == errcode && logequiv(!err, errcode); float_free(&f); return retvalue; } static int test_abs() { int i; static struct{ const char* value; int error; } testcases[] = { {"NaN", NoOperand}, {"0", Success}, {"1.23", Success}, {"-1.23", Success}, }; printf("testing float_abs\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_abs(testcases[i].value, testcases[i].error)) return tc_fail(i); return 1; } static int tc_cmp(const char* val1, const char* val2, signed char result) { floatstruct v1; floatstruct v2; signed char revres, res; float_create(&v1); float_create(&v2); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_geterror(); revres = float_cmp(&v2, &v1); if (revres != UNORDERED) revres = -revres; else if (float_geterror() != NoOperand) return 0; res = float_cmp(&v1, &v2); if (res == UNORDERED && float_geterror() != NoOperand) return 0; float_free(&v1); float_free(&v2); return res == result && revres == result && float_geterror() == Success; } static int test_cmp() { int i; static struct{ const char* value1; const char* value2; signed char result; } testcases[] = { {"NaN", "NaN", UNORDERED}, {"NaN", "0", UNORDERED}, {"NaN", "1", UNORDERED}, {"NaN", "-1", UNORDERED}, {"0", "0", 0}, {"1", "0", 1}, {"10", "0", 1}, {".1", "0", 1}, {"-1", "0", -1}, {"-10", "0", -1}, {"-.1", "0", -1}, {"1", "10", -1}, {"1", "1", 0}, {"1", ".1", 1}, {"1", "-10", 1}, {"1", "-1", 1}, {"1", "-.1", 1}, {"-1", "10", -1}, {"-1", ".1", -1}, {"-1", "-10", 1}, {"-1", "-.1", -1}, {"-1", "-1", 0}, {"1.01", "1", 1}, {"1.01", "1.02", -1}, {"1.021", "1.011", 1}, {"1.011", "1.01", 1}, {"1.011", "1.011", 0}, {"-1.01", "-1", -1}, {"-1.01", "-1.02", 1}, {"-1.021", "-1.011", -1}, {"-1.011", "-1.01", -1}, {"-1.011", "-1.011", 0}, }; printf("testing float_cmp\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_cmp(testcases[i].value1, testcases[i].value2, testcases[i].result)) return tc_fail(i); return 1; } static int tc_copy(const char* source, int digits, int error, const char* result) { floatstruct src, dest; floatnum s, d; int refs, save, code; char err, retvalue; char buf[60]; refs = _one_->n_refs; float_create(&src); float_create(&dest); s = &src; d = &dest; dest.significand = bc_copy_num(_one_); dest.exponent = 12; save = float_setprecision(50); float_setasciiz(s, source); float_setprecision(save); float_geterror(); err = float_copy(d, s, digits); code = float_geterror(); float_getscientific(buf, sizeof(buf), d); retvalue = refs == _one_->n_refs && code == error && logequiv(code, !err) && strcmp(result, buf) == 0; if (retvalue) { err = float_copy(s, s, digits); code = float_geterror(); float_getscientific(buf, sizeof(buf), d); retvalue = code == error && logequiv(code, !err) && strcmp(result, buf) == 0; } float_free(s); float_free(d); return retvalue; } static int test_copy() { int i; static struct{ const char* src; int digits; const char* result; int error; } testcases[] = { {"NaN", -10, "NaN", InvalidPrecision}, {"NaN", EXACT, "NaN", Success}, {"NaN", 0, "NaN", InvalidPrecision}, {"NaN", 1, "NaN", Success}, {"NaN", 15, "NaN", Success}, {"NaN", 16, "NaN", InvalidPrecision}, {"0", -10, "NaN", InvalidPrecision}, {"0", EXACT, "0", Success}, {"0", 0, "NaN", InvalidPrecision}, {"0", 1, "0", Success}, {"0", 15, "0", Success}, {"0", 16, "NaN", InvalidPrecision}, {"12305", EXACT, "1.2305e4", Success}, {"12305", -1, "NaN", InvalidPrecision}, {"12305", 0, "NaN", InvalidPrecision}, {"12305", 1, "1.e4", Success}, {"12305", 2, "1.2e4", Success}, {"12305", 3, "1.23e4", Success}, {"12305", 4, "1.23e4", Success}, {"12305", 5, "1.2305e4", Success}, {"12305", 6, "1.2305e4", Success}, {"-12305", 5, "-1.2305e4", Success}, {"1.234567890123456789", 0, "NaN", InvalidPrecision}, {"1.234567890123456789", 1, "1.e0", Success}, {"1.234567890123456789", 14, "1.2345678901234e0", Success}, {"1.234567890123456789", 15, "1.23456789012345e0", Success}, {"1.23456789012345006789", 16, "NaN", InvalidPrecision}, {"1.23456789012345006789", EXACT, "NaN", InvalidPrecision}, }; printf("testing float_copy\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_copy(testcases[i].src, testcases[i].digits, testcases[i].error, testcases[i].result)) return tc_fail(i); return 1; } static int tc_move(const char* value) { floatstruct f, g; int save, refs, code; char retvalue; char buf[50]; float_create(&f); refs = _one_->n_refs; g.significand = bc_copy_num(_one_); g.exponent = 12; save = float_setprecision(50); float_setasciiz(&f, value); float_setprecision(save); float_geterror(); float_move(&g, &f); code = float_geterror(); float_getscientific(buf, sizeof(buf), &g); retvalue = refs == _one_->n_refs && float_isnan(&f) && strcmp(buf, value) == 0 && code == Success; float_free(&g); return retvalue; } static int test_move() { int i; static struct{ const char* value; } testcases[] = { {"NaN"}, {"0"}, {"1.e0"}, {"1.e-1"}, {"1.e1"}, {"-1.e1"}, {"1.234567890123456789e0"}, }; printf("testing float_move\n"); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_move(testcases[i].value)) return tc_fail(i); return 1; } static int tc_round(const char* value, int digits, const char* up, const char* down, int roundflags, Error error) { floatstruct f, g; Error code; int flag, refs, save, cmp, cd; char buf[50]; roundmode rm; char err; float_create(&f); flag = 1; refs = _one_->n_refs; g.significand = bc_copy_num(_one_); g.exponent = 0; save = float_setprecision(50); float_setasciiz(&f, value); float_setprecision(save); float_geterror(); err = float_round(&g, &f, digits, 5); code = float_geterror(); if (err != 0 || code != InvalidParam || !float_isnan(&g) || refs != _one_->n_refs) return 0; for (rm = TONEAREST; rm <= TOMINUSINFINITY; ++rm) { refs = _one_->n_refs; g.significand = bc_copy_num(_one_); g.exponent = 0; save = float_setprecision(50); float_setasciiz(&f, value); float_setprecision(save); float_geterror(); err = float_round(&g, &f, digits, rm); code = float_geterror(); float_getscientific(buf, sizeof(buf), &g); cd = Success; if ((flag & roundflags) != 0) { if (*up == 'N') cd = error; cmp = strcmp(buf, up); } else { if (*down == 'N') cd = error; cmp = strcmp(buf, down); } if (cmp != 0 || code != cd || !logequiv(code, !err)) return 0; float_geterror(); err = float_round(&f, &f, digits, rm); code = float_geterror(); float_getscientific(buf, sizeof(buf), &f); cd = Success; if ((flag & roundflags) != 0) { if (*up == 'N') cd = error; cmp = strcmp(buf, up); } else { if (*down == 'N') cd = error; cmp = strcmp(buf, down); } if (cmp != 0 || code != cd || !logequiv(code, !err)) return 0; flag *=2; } float_free(&f); float_free(&g); return 1; } #define FN 1 #define FZ 2 #define FI 4 #define FU 8 #define FD 16 static int test_round() { int i; static struct{ const char* value; int digits; const char* up; const char* down; int roundflags; Error error; } testcases[] = { {"NaN", -1, "NaN", "NaN", 0, InvalidPrecision}, {"NaN", 0, "NaN", "NaN", 0, InvalidPrecision}, {"NaN", 16, "NaN", "NaN", 0, InvalidPrecision}, {"NaN", 1, "NaN", "NaN", 0, NoOperand}, {"0", -1, "NaN", "NaN", 0, InvalidPrecision}, {"0", 0, "NaN", "NaN", 0, InvalidPrecision}, {"0", 16, "NaN", "NaN", 0, InvalidPrecision}, {"0", 1, "0", "0", 0, Success}, {"1", -1, "NaN", "NaN", 0, InvalidPrecision}, {"1", 0, "NaN", "NaN", 0, InvalidPrecision}, {"1", 16, "NaN", "NaN", 0, InvalidPrecision}, {"1", 1, "1.e0", "1.e0", 0, Success}, {"1", 2, "1.e0", "1.e0", 0, Success}, {"1", 15, "1.e0", "1.e0", 0, Success}, {"-1", -1, "NaN", "NaN", 0, InvalidPrecision}, {"-1", 0, "NaN", "NaN", 0, InvalidPrecision}, {"-1", 16, "NaN", "NaN", 0, InvalidPrecision}, {"-1", 1, "-1.e0", "-1.e0", 0, Success}, {"-1", 2, "-1.e0", "-1.e0", 0, Success}, {"-1", 15, "-1.e0", "-1.e0", 0, Success}, {"1.903", 1, "2.e0", "1.e0", FN+FI+FU, Success}, {"1.903", 2, "2.e0", "1.9e0", FI+FU, Success}, {"1.903", 3, "1.91e0", "1.9e0", FI+FU, Success}, {"1.903", 4, "1.903e0", "1.903e0", 0, Success}, {"1.903", 5, "1.903e0", "1.903e0", 0, Success}, {"19.03", 1, "2.e1", "1.e1", FN+FI+FU, Success}, {"19.03", 2, "2.e1", "1.9e1", FI+FU, Success}, {"19.03", 3, "1.91e1", "1.9e1", FI+FU, Success}, {"19.03", 4, "1.903e1", "1.903e1", 0, Success}, {"19.03", 5, "1.903e1", "1.903e1", 0, Success}, {"0.1903", 1, "2.e-1", "1.e-1", FN+FI+FU, Success}, {"0.1903", 2, "2.e-1", "1.9e-1", FI+FU, Success}, {"0.1903", 3, "1.91e-1", "1.9e-1", FI+FU, Success}, {"0.1903", 4, "1.903e-1", "1.903e-1", 0, Success}, {"0.1903", 5, "1.903e-1", "1.903e-1", 0, Success}, {"-1.903", 1, "-1.e0", "-2.e0", FZ+FU, Success}, {"-1.903", 2, "-1.9e0", "-2.e0", FN+FZ+FU, Success}, {"-1.903", 3, "-1.9e0", "-1.91e0", FN+FZ+FU, Success}, {"-1.903", 4, "-1.903e0", "-1.903e0", 0, Success}, {"-1.903", 5, "-1.903e0", "-1.903e0", 0, Success}, {"1.29903", 1, "2.e0", "1.e0", FI+FU, Success}, {"1.29903", 2, "1.3e0", "1.2e0", FN+FI+FU, Success}, {"1.29903", 3, "1.3e0", "1.29e0", FN+FI+FU, Success}, {"1.29903", 4, "1.3e0", "1.299e0", FI+FU, Success}, {"1.29903", 5, "1.2991e0", "1.299e0", FI+FU, Success}, {"1.29903", 6, "1.29903e0", "1.29903e0", 0, Success}, {"9.99", 1, "1.e1", "9.e0", FN+FI+FU, Success}, {"9.99", 2, "1.e1", "9.9e0", FN+FI+FU, Success}, {"9.99", 3, "9.99e0", "9.99e0", 0, Success}, {"1.5", 1, "2.e0", "1.e0", FN+FI+FU, Success}, {"2.5", 1, "3.e0", "2.e0", FI+FU, Success}, {"9.99e100", 1, "NaN", "9.e100", FN+FI+FU, Overflow}, {"9.99e100", 2, "NaN", "9.9e100", FN+FI+FU, Overflow}, {"9.99e100", 3, "9.99e100", "9.99e100", 0, Success}, {"9.995e100", 3, "NaN", "9.99e100", FN+FI+FU, Overflow}, }; int save; printf("testing float_round\n"); save = float_setrange(100); for(i = -1; ++i < sizeof(testcases)/sizeof(testcases[0]);) if(!tc_round(testcases[i].value, testcases[i].digits, testcases[i].up, testcases[i].down, testcases[i].roundflags, testcases[i].error)) return tc_fail(i); float_setrange(save); return 1; } static int tc_add(char* msg, char* val1, char* val2, int digits, char* result) { floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct sum; int lg; char ok; char buf[30]; float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create(&sum); printf("%s", msg); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_add(&sum, &v1, &v2, digits); float_getscientific(buf, 30, &sum); lg = (int)strlen(result); ok = _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0 && lg == strlen(buf) && memcmp(buf, result, lg) == 0? TRUE : FALSE; float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free(&sum); return ok; } static int test_add() { floatstruct v1; floatstruct v2; floatstruct save; char nmb[30]; char nmb2[30]; printf("\ntesting float_add\n"); float_create(&v1); float_create(&v2); float_create(&save); maxexp(nmb, "+9.9e"); if (!tc_add("invalid length\n", "0", "0", 0, "NaN")) return FALSE; if (!tc_add("NaN, both op\n", "NaN", "NaN", 3, "NaN")) return FALSE; if (!tc_add("NaN, first op\n", "NaN", "0", 3, "NaN")) return FALSE; if (!tc_add("NaN, second op\n", "0", "NaN", 3, "NaN")) return FALSE; if (!tc_add("0 + 0\n", "0", "0", 3, "0")) return FALSE; if (!tc_add("0 + 1\n", "0", "1", 3, "1.e0")) return FALSE; if (!tc_add("1 + 0\n", "1", "0", 3, "1.e0")) return FALSE; if (!tc_add("1 + 1\n", "1", "1", EXACT, "2.e0")) return FALSE; if (!tc_add("1 + 0.1\n", "1", "0.1", EXACT, "1.1e0")) return FALSE; if (!tc_add("0.1 + 1\n", "0.1", "1", EXACT, "1.1e0")) return FALSE; if (!tc_add("scale overflow, 1E-20 + 1\n", "1.E-20", "1", EXACT, "NaN")) return FALSE; if (!tc_add("1E-20 + 1\n", "1.E-20", "1", 10, "1.e0")) return FALSE; if (!tc_add("1.234 + 0.1\n", "1.234", "0.1", EXACT, "1.334e0")) return FALSE; if (!tc_add("1.234 + 0.12345\n", "1.234", "0.12345", EXACT, "1.35745e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 5\n", "1.234", "0.12345", 5, "1.3574e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 4\n", "1.234", "0.12345", 4, "1.357e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 3\n", "1.234", "0.12345", 3, "1.35e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 2\n", "1.234", "0.12345", 2, "1.3e0")) return FALSE; if (!tc_add("1.234 + 0.12345, lg 1\n", "1.234", "0.12345", 1, "1.e0")) return FALSE; if (!tc_add("123.001 + (-122.85)\n", "123.001", "-122.85", 1, "2.e-1")) return FALSE; if (!tc_add("123.0014 + (-122.954)\n", "123.0014", "-122.954", 1, "5.e-2")) return FALSE; if (!tc_add("123.0014 + (-122.9954)\n", "123.0014", "-122.9954", 1, "6.e-3")) return FALSE; if (!tc_add("123 + (-122.9954)\n", "123", "-122.9954", 1, "5.e-3")) return FALSE; if (!tc_add("2 + (-1.9954)\n", "2", "-1.9954", 1, "5.e-3")) return FALSE; if (!tc_add("(-1.9954) + 2\n", "-1.9954", "2", 1, "5.e-3")) return FALSE; if (!tc_add("1 + (-0.9954)\n", "1", "-0.9954", 1, "5.e-3")) return FALSE; if (!tc_add("1.00001 + (-0.9954)\n", "1.00001", "-0.9954", 1, "5.e-3")) return FALSE; if (!tc_add("1.00001 + (-0.99)\n", "1.00001", "-0.99", 1, "1.e-2")) return FALSE; if (!tc_add("1.00001 + (-0.9999999)\n", "1.00001", "-0.9999999", 1, "2.e-5")) return FALSE; if (!tc_add("max + 1E-10000\n", nmb, "1E-10000", 2, nmb+1)) return FALSE; if (!tc_add("overflow\n", nmb, nmb, 2, "NaN")) return FALSE; if (!tc_add("2 + (-1)\n", "2", "-1", 2, "1.e0")) return FALSE; if (!tc_add("(-1) + 2\n", "-1", "2", 2, "1.e0")) return FALSE; if (!tc_add("2 + (-0.1)\n", "2", "-0.1", EXACT, "1.9e0")) return FALSE; if (!tc_add("1 + (-0.1)\n", "1", "-0.1", EXACT, "9.e-1")) return FALSE; if (!tc_add("1 + (-0.1), lg 1\n", "1", "-0.1", 1, "9.e-1")) return FALSE; if (!tc_add("123 + (-100)\n", "123", "-100", EXACT, "2.3e1")) return FALSE; if (!tc_add("(-123) + 100\n", "-123", "100", EXACT, "-2.3e1")) return FALSE; if (!tc_add("123 + (-120)\n", "123", "-120", EXACT, "3.e0")) return FALSE; if (!tc_add("123 + (-124)\n", "123", "-124", EXACT, "-1.e0")) return FALSE; if (!tc_add("123 + (-123)\n", "123", "-123", EXACT, "0")) return FALSE; if (!tc_add("123.04 + (-123)\n", "123.04", "-123", EXACT, "4.e-2")) return FALSE; if (!tc_add("123.04 + (-123)\n", "123.04", "-123", 1, "4.e-2")) return FALSE; if (!tc_add("123.24 + (-123.11)\n", "123.24", "-123.11", 1, "1.3e-1")) return FALSE; if (!tc_add("123.046 + (-123.115)\n", "123.046", "-123.115", 1, "-7.e-2")) return FALSE; if (!tc_add("123 + (-120), lg 1\n", "123", "-120", 1, "3.e0")) return FALSE; if (!tc_add("underflow\n", minexp(nmb, "1.1e"), minexp(nmb2, "-1e"), 5, "NaN")) return FALSE; if (!tc_add("underflow due to borrow\n", minexp(nmb, "2.0001e"), minexp(nmb2, "-1.99955e"), 5, "NaN")) return FALSE; if (!tc_add("underflow due to cancel\n", minexp(nmb, "1.234e"), minexp(nmb2, "-1.231e"), 5, "NaN")) return FALSE; printf("%s\n", "in place add, first"); float_setscientific(&v1, "120", NULLTERMINATED); float_setscientific(&v2, "-3.4e-1", NULLTERMINATED); float_copy(&save, &v2, EXACT); float_add(&v1, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v1); if (memcmp("1.1966e2", nmb, 9) != 0 || _cmp(&v2, &save) != 0) return FALSE; printf("%s\n", "in place add, second"); float_copy(&save, &v1, EXACT); float_add(&v2, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("1.1932e2", nmb, 9) != 0 || _cmp(&v1, &save) != 0) return FALSE; printf("%s\n", "in place add, both"); float_add(&v2, &v2, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("2.3864e2", nmb, 9) != 0) return FALSE; float_free(&v1); float_free(&v2); float_free(&save); return TRUE; } static int tc_sub(char* msg, char* val1, char* val2, int digits, char* result) { floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct diff; int lg; char ok; char buf[30]; float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create(&diff); printf("%s", msg); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_sub(&diff, &v1, &v2, digits); float_getscientific(buf, 30, &diff); lg = (int)strlen(result); ok = _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0 && lg == strlen(buf) && memcmp(buf, result, lg) == 0? TRUE : FALSE; float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free(&diff); return ok; } static int test_sub() { floatstruct v1; floatstruct v2; floatstruct save; char nmb[30]; printf("\ntesting float_sub\n"); float_create(&v1); float_create(&v2); float_create(&save); if (!tc_sub("invalid length\n", "0", "0", 0, "NaN")) return FALSE; if (!tc_sub("NaN, both op\n", "NaN", "NaN", 3, "NaN")) return FALSE; if (!tc_sub("NaN, first op\n", "NaN", "0", 3, "NaN")) return FALSE; if (!tc_sub("NaN, second op\n", "0", "NaN", 3, "NaN")) return FALSE; if (!tc_sub("0 - 0\n", "0", "0", 3, "0")) return FALSE; if (!tc_sub("0 - 1\n", "0", "1", 3, "-1.e0")) return FALSE; if (!tc_sub("1 - 0\n", "1", "0", 3, "1.e0")) return FALSE; if (!tc_sub("1 - 1\n", "1", "1", EXACT, "0")) return FALSE; if (!tc_sub("1 - 0.1\n", "1", "0.1", EXACT, "9.e-1")) return FALSE; if (!tc_sub("0.1 - 1\n", "0.1", "1", EXACT, "-9.e-1")) return FALSE; printf("%s\n", "in place sub, first"); float_setscientific(&v1, "120", NULLTERMINATED); float_setscientific(&v2, "-3.4e-1", NULLTERMINATED); float_copy(&save, &v2, EXACT); float_sub(&v1, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v1); if (memcmp("1.2034e2", nmb, 9) != 0 || _cmp(&v2, &save) != 0) return FALSE; printf("%s\n", "in place sub, second"); float_copy(&save, &v1, EXACT); float_sub(&v2, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("1.2068e2", nmb, 9) != 0 || _cmp(&v1, &save) != 0) return FALSE; printf("%s\n", "in place sub, both"); float_sub(&v2, &v2, &v2, EXACT); if (!float_iszero(&v2)) return FALSE; float_free(&v1); float_free(&v2); float_free(&save); return TRUE; } static int tc_mul(char* msg, char* val1, char* val2, int digits, char* result) { floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct prod; int lg; char ok; char buf[30]; float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create(&prod); printf("%s", msg); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_mul(&prod, &v1, &v2, digits); float_getscientific(buf, 30, &prod); lg = (int)strlen(result); ok = _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0 && lg == strlen(buf) && memcmp(buf, result, lg) == 0? TRUE : FALSE; float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free(&prod); return ok; } static int test_mul() { floatstruct v1; floatstruct v2; floatstruct save; char nmb[30]; char nmb2[30]; printf("\ntesting float_mul\n"); float_create(&v1); float_create(&v2); float_create(&save); if (!tc_mul("invalid length\n", "0", "0", 0, "NaN")) return FALSE; if (!tc_mul("NaN, both op\n", "NaN", "NaN", 3, "NaN")) return FALSE; if (!tc_mul("NaN, first op\n", "NaN", "0", 3, "NaN")) return FALSE; if (!tc_mul("NaN, second op\n", "0", "NaN", 3, "NaN")) return FALSE; if (!tc_mul("0 * 0\n", "0", "0", 3, "0")) return FALSE; if (!tc_mul("0 * 1\n", "0", "1", 3, "0")) return FALSE; if (!tc_mul("1 * 0\n", "1", "0", 3, "0")) return FALSE; if (!tc_mul("1 * 1\n", "1", "1", EXACT, "1.e0")) return FALSE; if (!tc_mul("1 * -1\n", "1", "-1", EXACT, "-1.e0")) return FALSE; if (!tc_mul("-1 * 1\n", "-1", "1", EXACT, "-1.e0")) return FALSE; if (!tc_mul("-1 * -1\n", "-1", "-1", EXACT, "1.e0")) return FALSE; if (!tc_mul("2 * 3\n", "2", "3", EXACT, "6.e0")) return FALSE; if (!tc_mul("3 * 4\n", "3", "4", EXACT, "1.2e1")) return FALSE; if (!tc_mul("123 * 456\n", "123", "456", EXACT, "5.6088e4")) return FALSE; if (!tc_mul("3E100 * 4E-100\n", "3E100", "4E-100", EXACT, "1.2e1")) return FALSE; if (!tc_mul("big exp diff\n", maxexp(nmb, "5e"), minexp(nmb2, "2e"), EXACT, "1.e0")) return FALSE; if (!tc_mul("almost overflow\n", maxexp(nmb, "4.9e"), "2", EXACT, maxexp(nmb2, "9.8e"))) return FALSE; if (!tc_mul("overflow\n", maxexp(nmb, "5e"), "2", EXACT, "NaN")) return FALSE; if (!tc_mul("big overflow\n", maxexp(nmb, "5e"), nmb, EXACT, "NaN")) return FALSE; if (!tc_mul("almost underflow\n", minexp(nmb, "5e"), "0.2", EXACT, minexp(nmb2, "1.e"))) return FALSE; if (!tc_mul("underflow\n", minexp(nmb, "4e"), "0.2", EXACT, "NaN")) return FALSE; if (!tc_mul("big underflow\n", minexp(nmb, "1e"), nmb, EXACT, "NaN")) return FALSE; if (!tc_mul("scale overflow\n", "1.2345678901", "1.2345678901", EXACT, "NaN")) return FALSE; printf("%s\n", "in place mul, first"); float_setscientific(&v1, "2", NULLTERMINATED); float_setscientific(&v2, "-3", NULLTERMINATED); float_copy(&save, &v2, EXACT); float_mul(&v1, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v1); if (memcmp("-6.e0", nmb, 6) != 0 || _cmp(&v2, &save) != 0) return FALSE; printf("%s\n", "in place mul, second"); float_copy(&save, &v1, EXACT); float_mul(&v2, &v1, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("1.8e1", nmb, 6) != 0 || _cmp(&v1, &save) != 0) return FALSE; printf("%s\n", "in place mul, both"); float_mul(&v2, &v2, &v2, EXACT); float_getscientific(nmb, 30, &v2); if (memcmp("3.24e2", nmb, 7) != 0) return FALSE; float_free(&v1); float_free(&v2); float_free(&save); return TRUE; } static int tc_div(char* msg, char* val1, char* val2, int digits, char* result) { floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct quot; int lg; char ok; char buf[30]; float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create("); printf("%s", msg); float_setscientific(", "1.823452", NULLTERMINATED); float_setscientific(&v1, val1, NULLTERMINATED); float_setscientific(&v2, val2, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_div(", &v1, &v2, digits); float_getscientific(buf, 30, "); lg = (int)strlen(result); ok = _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0 && lg == strlen(buf) && memcmp(buf, result, lg) == 0? TRUE : FALSE; float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free("); return ok; } static int test_div() { floatstruct v1; floatstruct v2; floatstruct save; char nmb[30]; char nmb2[30]; printf("\ntesting float_div\n"); float_create(&v1); float_create(&v2); float_create(&save); if(!tc_div("invalid digits\n", "1", "1", EXACT, "NaN")) return FALSE; if(!tc_div("NaN, both\n", "NaN", "NaN", 5, "NaN")) return FALSE; if(!tc_div("NaN, first\n", "NaN", "1", 5, "NaN")) return FALSE; if(!tc_div("NaN, second\n", "1", "NaN", 5, "NaN")) return FALSE; if(!tc_div("0/1\n", "0", "1", 5, "0")) return FALSE; if(!tc_div("1/0\n", "1", "0", 5, "NaN")) return FALSE; if(!tc_div("0/0\n", "0", "0", 5, "NaN")) return FALSE; if(!tc_div("1/1\n", "1", "1", 5, "1.e0")) return FALSE; if(!tc_div("(-1)/1\n", "-1", "1", 5, "-1.e0")) return FALSE; if(!tc_div("1/(-1)\n", "1", "-1", 5, "-1.e0")) return FALSE; if(!tc_div("(-1)/(-1)\n", "-1", "-1", 5, "1.e0")) return FALSE; if(!tc_div("1/2\n", "1", "2", 5, "5.e-1")) return FALSE; if(!tc_div("1/3\n", "1", "3", 5, "3.3333e-1")) return FALSE; if(!tc_div("4/3\n", "4", "3", 5, "1.33333e0")) return FALSE; if(!tc_div("40/0.3\n", "40", "0.3", 5, "1.33333e2")) return FALSE; if(!tc_div("0.4/0.03\n", "0.4", "0.03", 5, "1.33333e1")) return FALSE; if(!tc_div("400/30\n", "400", "30", 5, "1.33333e1")) return FALSE; if(!tc_div("400/30000\n", "400", "30000", 5, "1.33333e-2")) return FALSE; if(!tc_div("0.0004/0.3\n", "0.0004", "0.3", 5, "1.33333e-3")) return FALSE; if(!tc_div("integer quotient, 1/3\n", "1", "3", INTQUOT, "0")) return FALSE; if(!tc_div("integer quotient, 4/3\n", "4", "3", INTQUOT, "1.e0")) return FALSE; if(!tc_div("integer quotient, 4/3\n", "4", "3", INTQUOT, "1.e0")) return FALSE; if(!tc_div("integer quotient, 4/3\n", "4", "0.3", INTQUOT, "1.3e1")) return FALSE; if(!tc_div("integer quotient, 1/3\n", "1", "0.3", INTQUOT, "3.e0")) return FALSE; if(!tc_div("integer quotient, 1/30\n", "1", "30", INTQUOT, "0")) return FALSE; if(!tc_div("almost overflow\n", maxexp(nmb, "1.e"), "0.3", 5, maxexp(nmb2, "3.3333e"))) return FALSE; if(!tc_div("overflow\n", maxexp(nmb, "4.e"), "0.3", 5, "NaN")) return FALSE; if(!tc_div("big overflow\n", maxexp(nmb, "4.e"), minexp(nmb2, "1.e"), 5, "NaN")) return FALSE; if(!tc_div("almost underflow\n", minexp(nmb, "4.e"), "3", 5, minexp(nmb2, "1.33333e"))) return FALSE; if(!tc_div("underflow\n", minexp(nmb, "1.e"), "3", 5, "NaN")) return FALSE; if(!tc_div("big underflow\n", minexp(nmb, "1.e"), maxexp(nmb2, "1.e"), 5, "NaN")) return FALSE; if(!tc_div("scale overflow\n", "1", "2", 20, "NaN")) return FALSE; printf("%s\n", "in place div, first"); float_setscientific(&v1, "1", NULLTERMINATED); float_setscientific(&v2, "-2", NULLTERMINATED); float_copy(&save, &v2, EXACT); float_div(&v1, &v1, &v2, 5); float_getscientific(nmb, 30, &v1); if (memcmp("-5.e-1", nmb, 7) != 0 || _cmp(&v2, &save) != 0) return FALSE; printf("%s\n", "in place div, second"); float_copy(&save, &v1, EXACT); float_div(&v2, &v1, &v2, 5); float_getscientific(nmb, 30, &v2); if (memcmp("2.5e-1", nmb, 7) != 0 || _cmp(&v1, &save) != 0) return FALSE; printf("%s\n", "in place div, both"); float_div(&v2, &v2, &v2, 5); float_getscientific(nmb, 30, &v2); if (memcmp("1.e0", nmb, 5) != 0) return FALSE; float_free(&v1); float_free(&v2); float_free(&save); return TRUE; } static int tc_sqrt(char* msg, char* val, int digits, char* result) { floatstruct v; int lg; char buf[30]; printf("%s", msg); float_create(&v); float_setscientific(&v, val, NULLTERMINATED); float_sqrt(&v, digits); float_round(&v, &v, digits - 1, TONEAREST); float_getscientific(buf, 30, &v); float_free(&v); lg = (int)strlen(result); return strlen(buf) == lg && memcmp(buf, result, lg) == 0? TRUE : FALSE; } static int test_sqrt() { printf("\ntesting float_sqrt\n"); if (!tc_sqrt("invalid length\n", "1", 0, "NaN")) return FALSE; if (!tc_sqrt("NaN\n", "NaN", 5, "NaN")) return FALSE; if (!tc_sqrt("negative value\n", "-1", 5, "NaN")) return FALSE; if (!tc_sqrt("0\n", "0", 5, "0")) return FALSE; if (!tc_sqrt("1\n", "1", 5, "1.e0")) return FALSE; if (!tc_sqrt("4\n", "4", 5, "2.e0")) return FALSE; if (!tc_sqrt("16\n", "16", 5, "4.e0")) return FALSE; if (!tc_sqrt("0.64\n", "0.64", 5, "8.e-1")) return FALSE; if (!tc_sqrt("0.04\n", "0.04", 5, "2.e-1")) return FALSE; return TRUE; } static int tc_int(char* msg, char* value, char* result) { floatstruct f; int lg; char buf[30]; printf("%s", msg); float_create(&f); float_setscientific(&f, value, NULLTERMINATED); float_int(&f); float_getscientific(buf, 30, &f); lg = (int)strlen(result); float_free(&f); return (lg == strlen(buf) && memcmp(buf, result, lg) == 0); } static int test_int() { printf("\ntesting float_int\n"); if (!tc_int("NaN\n", "NaN", "NaN")) return FALSE; if (!tc_int("0\n", "0", "0")) return FALSE; if (!tc_int("1\n", "1", "1.e0")) return FALSE; if (!tc_int("10\n", "10", "1.e1")) return FALSE; if (!tc_int("10.1\n", "10.1", "1.e1")) return FALSE; if (!tc_int("0.1\n", "0.1", "0")) return FALSE; if (!tc_int("-1\n", "-1", "-1.e0")) return FALSE; if (!tc_int("-10\n", "-10", "-1.e1")) return FALSE; if (!tc_int("-10.1\n", "-10.1", "-1.e1")) return FALSE; if (!tc_int("-0.1\n", "-0.1", "0")) return FALSE; return TRUE; } static int tc_frac(char* msg, char* value) { floatstruct f, r; printf("%s", msg); float_create(&f); float_create(&r); float_setscientific(&f, value, NULLTERMINATED); float_copy(&r, &f, EXACT); float_int(&r); float_sub(&r, &f, &r, EXACT); float_frac(&f); return _cmp(&f, &r) == 0; } static int test_frac() { printf("\ntesting float_frac\n"); if (!tc_frac("NaN\n", "NaN")) return FALSE; if (!tc_frac("0\n", "0")) return FALSE; if (!tc_frac("1\n", "1")) return FALSE; if (!tc_frac("10\n", "10")) return FALSE; if (!tc_frac("10.1\n", "10.1")) return FALSE; if (!tc_frac("0.1\n", "0.1")) return FALSE; if (!tc_frac("-1\n", "-1")) return FALSE; if (!tc_frac("-10\n", "-10")) return FALSE; if (!tc_frac("-10.1\n", "-10.1")) return FALSE; if (!tc_frac("-0.1\n", "-0.1")) return FALSE; if (!tc_frac("10.000000001\n", ".000000001")) return FALSE; return TRUE; } static int tc_divmod(char* msg, char* dvd, char* dvs, int dig, char* q, char* r) { int result; floatstruct v1; floatstruct v2; floatstruct b1; floatstruct b2; floatstruct r1; floatstruct r2; printf("%s", msg); float_create(&v1); float_create(&v2); float_create(&b1); float_create(&b2); float_create(&r1); float_create(&r2); float_setscientific(&r1, "-1.821923", NULLTERMINATED); float_setscientific(&r2, "-1.821923", NULLTERMINATED); float_setscientific(&v1, dvd, NULLTERMINATED); float_setscientific(&v2, dvs, NULLTERMINATED); float_copy(&b1, &v1, EXACT); float_copy(&b2, &v2, EXACT); float_divmod(&r1, &r2, &v1, &v2, dig); result = (scmp(&r1, q) && scmp(&r2, r) && _cmp(&v1, &b1) == 0 && _cmp(&v2, &b2) == 0); float_free(&v1); float_free(&v2); float_free(&b1); float_free(&b2); float_free(&r1); float_free(&r2); return result; } static int test_divmod() { floatstruct f1; floatstruct f2; floatstruct f3; floatstruct vlg; int save; char nmb1[30]; char nmb2[30]; printf("\ntesting float_divmod\n"); float_create(&f1); float_create(&f2); float_create(&f3); float_create(&vlg); float_setinteger(&f1, 1); printf("%s", "test rem == quot\n"); float_divmod(&f1, &f1, &f1, &f1, 5); if (!float_isnan(&f1)) return FALSE; if (!tc_divmod("NaN, both\n", "NaN", "NaN", 5, "NaN", "NaN")) return FALSE; if (!tc_divmod("NaN, 1. op\n", "NaN", "1", 5, "NaN", "NaN")) return FALSE; if (!tc_divmod("NaN, 2. op\n", "1", "NaN", 5, "NaN", "NaN")) return FALSE; if (!tc_divmod("invalid digits\n", "1", "1", -5, "NaN", "NaN")) return FALSE; if (!tc_divmod("test divide by 0\n", "1", "0", 5, "NaN", "NaN")) return FALSE; if (!tc_divmod("test scale too long\n", "1", "1", 100, "NaN", "NaN")) return FALSE; if (!tc_divmod("0/1\n", "0", "1", 5, "0", "0")) return FALSE; if (!tc_divmod("1/100, INTQUOT\n", "1", "100", INTQUOT, "0", "1.e0")) return FALSE; if (!tc_divmod("INTQUOT, scale too long\n", "1e100", "1", INTQUOT, "NaN", "NaN")) return FALSE; if (!tc_divmod("1/2, INTQUOT\n", "1", "2", INTQUOT, "0", "1.e0")) return FALSE; if (!tc_divmod("3/2, INTQUOT\n", "3", "2", INTQUOT, "1.e0", "1.e0")) return FALSE; if (!tc_divmod("4/2, INTQUOT\n", "4", "2", INTQUOT, "2.e0", "0")) return FALSE; if (!tc_divmod("213/13, lg 3\n", "213", "13", 3, "1.63e1", "1.1e0")) return FALSE; if (!tc_divmod("17/16, INTQUOT\n", "17", "16", INTQUOT, "1.e0", "1.e0")) return FALSE; if (!tc_divmod("1.7/1.6, INTQUOT\n", "1.7", "1.6", INTQUOT, "1.e0", "1.e-1")) return FALSE; if (!tc_divmod("1.7/1.6, lg 3\n", "1.7", "1.6", 3, "1.06e0", "4.e-3")) return FALSE; if (!tc_divmod("underflow in quot\n", minexp(nmb1, "1.7e"), "1.6e1", 3, "NaN", "NaN")) return FALSE; if (!tc_divmod("overflow in quot\n", maxexp(nmb1, "1.7e"), "1.6e-1", 3, "NaN", "NaN")) return FALSE; if (!tc_divmod("underflow in rem\n", minexp(nmb1, "1.7e"), minexp(nmb2, "1.6e"), INTQUOT, "NaN", "NaN")) return FALSE; printf("%s", "long divisor\n"); float_setzero(&f1); float_setzero(&f2); save = float_setprecision(20); float_setasciiz(&f3, "12345678901234567890"); float_copy(&vlg, &f3, EXACT); float_setprecision(save); float_divmod(&f1, &f2, &f3, &f3, 3); if (!float_isnan(&f1) || !float_isnan(&f2) || float_cmp(&vlg, &f3) != 0) return FALSE; printf("%s", "dividend and divisor overwritten by quotient\n"); float_setinteger(&f1, 2); float_setnan(&f2); float_divmod(&f1, &f2, &f1, &f1, 3); if (!scmp(&f1, "1.e0") || !scmp(&f2, "0")) return FALSE; printf("%s", "dividend and divisor overwritten by remainder\n"); float_setinteger(&f1, 2); float_setnan(&f2); float_divmod(&f2, &f1, &f1, &f1, 3); if (!scmp(&f2, "1.e0") || !scmp(&f1, "0")) return FALSE; printf("%s", "dividend overwritten by quotient, divisor by remainder\n"); float_setinteger(&f1, 213); float_setinteger(&f2, 13); float_divmod(&f1, &f2, &f1, &f2, 3); if (!scmp(&f1, "1.63e1") || !scmp(&f2, "1.1e0")) return FALSE; printf("%s", "dividend overwritten by remainder, divisor by quotient\n"); float_setinteger(&f1, 213); float_setinteger(&f2, 13); float_divmod(&f2, &f1, &f1, &f2, 3); if (!scmp(&f2, "1.63e1") || !scmp(&f1, "1.1e0")) return FALSE; float_free(&f1); float_free(&f2); float_free(&f3); float_free(&vlg); return TRUE; } static void _relerror(floatnum x1, floatnum x2) { float_sub(x1, x1, x2, 3); if (!float_iszero(x1)) float_div(x1, x1, x2, 3); float_abs(x1); } static char _cmprelerror(floatnum x1, floatnum x2, int exp) { _relerror(x1, x2); return (float_iszero(x1) || float_getexponent(x1) < exp); } static void _sub_ulp(floatnum x, int sz) { floatstruct delta; if (!float_iszero(x)) { float_create(&delta); float_setinteger(&delta, 1); float_setexponent(&delta, float_getexponent(x)-sz); float_setsign(&delta, float_getsign(x)); float_sub(x, x, &delta, EXACT); float_free(&delta); } } static int test_coshminus1near0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing coshminus1near0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); coshminus1near0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "0.005"); float_setasciiz(&tmp, ".000012500026041688368065243678286383060391" "9872831398280829063464786043942297654015309" "5900368700065231210065496027359337789353280" "9524874015321513239965"); coshminus1near0(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".00001"); for (i = -1; ++i <= 1000;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); coshminus1near0(&x,100); coshminus1near0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _coshminus1near0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_artanhnear0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing artanhnear0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); artanhnear0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing correct replacement of artanh by id */ printf("small x handling:\n"); float_setasciiz(&x, "6.7e-51"); float_copy(&x1, &x, EXACT); artanhnear0(&x, 100); artanhnear0(&x1, 110); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "0.01"); artanhnear0(&x, 100); float_setasciiz(&x1,".0100003333533347620158821075514042238870" "97308807344335621654492648224836625944612" "34119694455592889442890269461918262602394" "9110421598243"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".0001", NULLTERMINATED); for (i = -101; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); artanhnear0(&x,100); artanhnear0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error artanhnear0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_arctannear0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing arctannear0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); arctannear0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing correct replacement of arctan by id */ printf("small x handling:\n"); float_setasciiz(&x, "6.7e-51"); float_copy(&x1, &x, EXACT); arctannear0(&x, 100); arctannear0(&x1, 110); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "0.01"); arctannear0(&x, 100); float_setasciiz(&x1,".00999966668666523820634011620927954856136935" "254437663962793941819645655320405877997944664" "518667409041670798128407565295492085345632123"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == 0.01\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".0001", NULLTERMINATED); for (i = -101; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); arctannear0(&x,100); arctannear0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error arctannear0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_cosminus1near0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing cosminus1near0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); cosminus1near0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "0.01"); cosminus1near0(&x, 100); float_setasciiz(&x1,"-.4999958333472221974206624779332678752941601" "972288887772423135353991187035650836487445623" "870262734376943805848695816541718420700624513737e-4"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == 0.01\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".0001", NULLTERMINATED); for (i = -1; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); cosminus1near0(&x,100); cosminus1near0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error cosminus1near0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_lnxplus1near0() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("testing _lnxplus1near0\n"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); /* verifying function result */ printf("verifying result:\n"); float_setasciiz(&x, "0.01"); float_setasciiz(&tmp,".009950330853168082848215357544260741688" "6796099400587978646095597668666642476389" "1103268569656276016116452560517384648478"); _lnxplus1near0(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("verifying special argument x == 0:\n"); float_setzero(&x); _lnxplus1near0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* overall scan for maximum relative error */ printf("testing error limit:\n"); float_setzero(&max); float_setscientific(&tmp, ".0002", NULLTERMINATED); for (i = -100; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _lnxplus1near0(&x,100); _lnxplus1near0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _lnxplus1near0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_lnreduce() { floatstruct max, x, step, delta, ofs, tmp, lnfactor, cmp; int i; char buf[50]; printf("testing _reduce\n"); float_create(&x); float_create(&max); float_create(&step); float_create(&delta); float_create(&ofs); float_create(&tmp); float_create(&lnfactor); float_create(&cmp); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.005"); float_setasciiz(&delta, "0.0049999999"); float_setasciiz(&cmp, "0.01"); printf("testing boundary case -0.4\n"); float_setasciiz(&x, "-.4"); _lnreduce(&x, &lnfactor, 10); float_abs(&x); if (float_cmp(&x, &cmp) > 0) { float_getscientific(buf, 50, &x); printf("reduction failed for x=-0.4: %s\n", buf); return 0; } float_abs(&lnfactor); float_getsignificand(buf, 1, &lnfactor); if (float_getexponent(&lnfactor) >= 0 || (float_getexponent(&lnfactor) == -1 && buf[0] >= '7')) { printf("guess incorrect for x=-0.4\n"); return 1; } for (i = -41; ++i < 100;) { if (i == -1 || i == 0) continue; float_muli(&tmp, &step, i, EXACT); float_add(&tmp, &tmp, &ofs, EXACT); float_sub(&x, &tmp, &delta, EXACT); _lnreduce(&x, &lnfactor, 10); float_abs(&x); if(float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_cmp(&x, &cmp) > 0) { float_getscientific(buf, 50, &x); printf("reduction failed for test case %d: %s\n", i, buf); return 0; } } float_abs(&lnfactor); float_getsignificand(buf, 1, &lnfactor); if (float_getexponent(&lnfactor) >= 0 || (float_getexponent(&lnfactor) == -1 && buf[0] >= '7')) { printf("guess incorrect for test case %d\n", i); return 1; } float_add(&x, &tmp, &delta, EXACT); _lnreduce(&x, &lnfactor, 10); float_abs(&x); if(float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_cmp(&x, &cmp) >0) { float_getscientific(buf, 50, &x); printf("reduction failed for test case %d: %s\n", i, buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max reduced value: %s\n", buf); float_free(&x); float_free(&max); float_free(&step); float_free(&delta); float_free(&ofs); float_free(&tmp); float_free(&lnfactor); float_free(&cmp); return 1; } static int test_lnxplus1lt1() { floatstruct x, x1, max, step, ofs, tmp, ref; int i; char buf[50]; printf("testing _lnxplus1lt1\n"); float_create(&x); float_create(&x1); float_create(&max); float_create(&step); float_create(&ofs); float_create(&tmp); float_create(&ref); printf("verifying special argument x == 0:\n"); float_setzero(&x); _lnxplus1lt1(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } printf("verifying special argument x == -0.4:\n"); float_copy(&x, &cMinus0_4, EXACT); _lnxplus1lt1(&x, 100); float_setasciiz(&x1, "-.510825623765990683205514096303661934878110" "79644576827017795355783668469448904879775651" "81232794475220119962739557576971573560010034"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED\n"); return 0; } printf("verifying function results\n"); float_setasciiz(&step, "0.005"); float_copy(&ref, &step, EXACT); float_copy(&x, &step, EXACT); _lnxplus1near0(&ref, 130); i = 1; while(float_cmp(&x, &c1) < 0) { float_copy(&x1, &x, EXACT); _lnxplus1lt1(&x, 100); float_muli(&tmp, &ref, i, 130); _relerror(&tmp, &x); if (float_getexponent(&tmp) >= -99) { float_getscientific(buf, 50, &tmp); printf("%s\n", buf); printf("FAILED for test case %d\n", i); return 0; } float_mul(&tmp, &step, &x1, 130); float_add(&tmp, &tmp, &step, EXACT); float_add(&x, &x1, &tmp, 130); ++i; } float_setasciiz(&step, "-0.005"); float_copy(&ref, &step, EXACT); float_copy(&x, &step, EXACT); _lnxplus1near0(&ref, 130); i = 1; while(float_cmp(&x, &cMinus0_4) >= 0) { float_copy(&x1, &x, EXACT); _lnxplus1lt1(&x, 100); float_muli(&tmp, &ref, i, 130); _relerror(&tmp, &x); if (float_getexponent(&tmp) >= -99) { float_getscientific(buf, 50, &tmp); printf("%s\n", buf); printf("FAILED for test case %d\n", i); return 0; } float_mul(&tmp, &step, &x1, 130); float_add(&tmp, &tmp, &step, EXACT); float_add(&x, &x1, &tmp, 130); ++i; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.00117436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = -41; ++i < 100;) { float_setinteger(&tmp, i); float_mul(&tmp, &tmp, &step, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _lnxplus1lt1(&x, 100); _lnxplus1lt1(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _lnxplus1: %s\n", buf); float_free(&x); float_free(&x1); float_free(&max); float_free(&step); float_free(&ofs); float_free(&tmp); float_free(&ref); return 1; } static int test_ln() { floatstruct x, max, step, ofs, tmp; int i; char buf[50]; printf("testing _ln\n"); float_create(&x); float_create(&max); float_create(&step); float_create(&ofs); float_create(&tmp); printf("verifying special argument x == 1:\n"); float_copy(&x, &c1, EXACT); _ln(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } printf("verifying function results:\n"); for (i = 1; ++i < 10;) { switch(i) { case 2: float_copy(&tmp, &cLn2, 110); break; case 3: float_copy(&tmp, &cLn3, 110); break; case 4: float_muli(&tmp, &cLn2, 2, 110); break; case 5: float_sub(&tmp, &cLn10, &cLn2, 110); break; case 6: float_add(&tmp, &cLn2, &cLn3, 110); break; case 7: float_copy(&tmp, &cLn7, 110); break; case 8: float_muli(&tmp, &cLn2, 3, 110); break; case 9: float_muli(&tmp, &cLn3, 2, 110); break; } float_setinteger(&x, i); _ln(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { float_getscientific(buf, 50, &tmp); printf("FAILED for argument %d: %s\n", i, buf); return 0; } } printf("testing exponent handling\n"); float_setinteger(&x, 20); _ln(&x, 100); float_add(&tmp, &cLn2, &cLn10, 110); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for exponent 1\n"); return 0; } float_setasciiz(&x, "0.2"); _ln(&x, 100); float_sub(&tmp, &cLn2, &cLn10, 110); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for exponent -1\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 19; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); if (i > 63) float_setexponent(&tmp, -1); float_copy(&tmp, &x, EXACT); _ln(&x, 100); _ln(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _ln: %s\n", buf); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); float_free(&tmp); return 1; } static int test_lnxplus1() { floatstruct x, x1; printf("testing _lnxplus1\n"); float_create(&x); float_create(&x1); printf("verifying function results:\n"); float_setasciiz(&x, "-.3"); _lnxplus1(&x, 100); float_copy(&x1, &cLn7, 110); float_sub(&x1, &x1, &cLn10, 110); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED x == -0.3\n"); return 0; } float_setasciiz(&x, "6"); _lnxplus1(&x, 100); if (!_cmprelerror(&x, &cLn7, -99)) { printf("FAILED x == 6\n"); return 0; } float_free(&x); float_free(&x1); return 1; } static int test_artanh1minusx() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _artanh1minusx\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_copy(&x, &c1Div2, EXACT); _artanh1minusx(&x, 100); float_copy(&tmp, &cLn3, 110); float_mul(&tmp, &tmp, &c1Div2, 110); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 50;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _artanh1minusx(&x, 100); _artanh1minusx(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _artanh1minusx: %s\n", buf); float_free(&x); float_free(&tmp); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_artanhlt0_5() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _artanhlt0_5\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_copy(&x, &c1Div2, EXACT); _artanhlt0_5(&x, 100); float_copy(&tmp, &cLn3, 110); float_mul(&tmp, &tmp, &c1Div2, 110); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 50;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _artanhlt0_5(&x, 100); _artanhlt0_5(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _artanh1minusx: %s\n", buf); float_free(&x); float_free(&tmp); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arsinh() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arsinh\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arsinh(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "1e-1000"); float_copy(&tmp, &x, EXACT); _arsinh(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==1e-1000\n"); return 0; } float_setasciiz(&x, "0.1"); float_setasciiz(&tmp, ".099834078899207563327303124704769443267712" "9117088250107423826956515917683936134651063" "484492769032061884984061246778732266658350084462074"); _arsinh(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==0.1\n"); return 0; } float_setasciiz(&x, "4"); float_setasciiz(&tmp, "2.09471254726110129424482284606552865345315" "1048198673265886805979926247949695627249150" "4293654887408011476586881386829965289261091"); _arsinh(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==4\n"); return 0; } float_setasciiz(&x, "1e100"); float_muli(&tmp, &cLn10, 100, 110); float_add(&tmp, &tmp, &cLn2, 110); _arsinh(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==1e100\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arsinh(&x, 100); _arsinh(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arsinh: %s\n", buf); float_free(&x); float_free(&tmp); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arcoshxplus1() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arcoshxplus1\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arcoshxplus1(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setinteger(&x, 10); float_setasciiz(&tmp, "3.08896990484460301791647985373629509453345" "4441136435131225532448209215351305027698930" "521085626874864770396311532541165684221072841899917"); _arcoshxplus1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==10\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.00147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arcoshxplus1(&x, 100); _arcoshxplus1(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arcoshxplus1(&x, 100); _arcoshxplus1(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arcoshxplus1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_coshminus1lt1() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _coshminus1lt1"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _coshminus1lt1(&x, 100); if (!float_iszero(&x)) { printf("FAILED x== 0\n"); return 0; } /* testing the validity of the reduction */ printf("verifying result:\n"); float_setasciiz(&x, "0.5"); float_copy(&tmp, &x, EXACT); float_arcoshxplus1(&x, 110); _coshminus1lt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for arcosh(1.5)-1\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".001"); for (i = -1; ++i <= 1000;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _coshminus1lt1(&x,100); _coshminus1lt1(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _coshminus1lt1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_sinhlt1() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _sinhlt1"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _sinhlt1(&x, 100); if (!float_iszero(&x)) { printf("FAILED for x== 0\n"); return 0; } printf("verifying positive result:\n"); float_setasciiz(&x, "1"); float_copy(&tmp, &x, EXACT); float_arsinh(&x, 110); _sinhlt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("verifying negative result:\n"); float_setasciiz(&x, "-1"); float_copy(&tmp, &x, EXACT); float_arsinh(&x, 110); _sinhlt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".001"); for (i = -1; ++i <= 1000;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _sinhlt1(&x,100); _sinhlt1(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _sinhlt1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_expminus1lt1() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _expminus1lt1"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _expminus1lt1(&x, 100); if (!float_iszero(&x)) { printf("FAILED for x== 0\n"); return 0; } printf("verifying positive result:\n"); float_setasciiz(&x, "1"); float_copy(&tmp, &x, EXACT); float_lnxplus1(&x, 110); _expminus1lt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("verifying negative result:\n"); float_setasciiz(&x, "-.5"); float_copy(&tmp, &x, EXACT); float_lnxplus1(&x, 110); _expminus1lt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".001"); for (i = -1001; ++i <= 1000;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _expminus1lt1(&x,100); _expminus1lt1(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _expminus1lt1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_expltln10() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _expltln10"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _expltln10(&x, 100); if (float_cmp(&x, &c1) != 0) { printf("FAILED\n"); return 0; } float_setasciiz(&tmp, ".1"); for (i = 0; ++i < 24;) { float_muli(&x1, &tmp, i, EXACT); float_copy(&x, &x1, EXACT); _expltln10(&x, 100); float_ln(&x, 110); if(!_cmprelerror(&x, &x1, -99)) { float_getscientific(buf, 50, &x1); printf("FAILED for x == %s\n", buf); return 0; } } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = -1; ++i <= 460;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _expltln10(&x,100); _expltln10(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _expltln10: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_exp() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _exp"); float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("verifying special argument x == 0:\n"); float_setzero(&x); _exp(&x, 100); if (float_cmp(&x, &c1) != 0) { printf("FAILED\n"); return 0; } printf("verifying results:\n"); float_setasciiz(&tmp, "1"); for (i = -2; ++i < 9;) { float_setexponent(&tmp, i); float_copy(&x, &tmp, EXACT); _exp(&x, 100); float_ln(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { float_getscientific(buf, 50, &tmp); printf("FAILED for x == %s\n", buf); return 0; } } float_setasciiz(&tmp, "-1"); for (i = -2; ++i < 9;) { float_setexponent(&tmp, i); float_copy(&x, &tmp, EXACT); _exp(&x, 100); float_ln(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { float_getscientific(buf, 50, &tmp); printf("FAILED for x == %s\n", buf); return 0; } } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = -461; ++i <= 0;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _exp(&x,100); _exp(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_muli(&x, &cLn10, EXPMAX, 110); float_copy(&x1, &x, EXACT); _exp(&x,100); _exp(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for near overflow case: "); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } float_getscientific(buf, 50, &max); printf("max error _exp: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_expminus1() { floatstruct x, tmp; printf("%s\n", "testing _expminus1"); float_create(&x); float_create(&tmp); printf("verifying special argument x == 0:\n"); float_setzero(&x); _expminus1(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } printf("verifying results:\n"); float_setasciiz(&x, "-1e100000"); float_setinteger(&tmp, -1); _expminus1(&x, 100); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == -1e100000\n"); return 0; } float_setasciiz(&x, "-1"); float_setinteger(&tmp, -1); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == -1\n"); return 0; } float_setasciiz(&x, "-1e-10"); float_copy(&tmp, &x, EXACT); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == -1e-10\n"); return 0; } float_setasciiz(&x, "1e-10"); float_copy(&tmp, &x, EXACT); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 1e-10\n"); return 0; } float_setasciiz(&x, "1"); float_copy(&tmp, &x, EXACT); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 1\n"); return 0; } float_setasciiz(&x, "100000"); float_copy(&tmp, &x, EXACT); _expminus1(&x, 100); float_lnxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 100000\n"); return 0; } float_free(&tmp); float_free(&x); return 1; } static int test_coshminus1() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _coshminus1"); float_create(&x); float_create(&tmp); float_create(&x1); float_create(&max); float_setzero(&max); printf("verifying function results:\n"); float_setzero(&x); _coshminus1(&x, 100); if (!float_iszero(&x)) { printf("FAILED for x == 0\n"); return 0; } float_setasciiz(&x, ".1"); float_copy(&tmp, &x, EXACT); _coshminus1(&x, 100); float_arcoshxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 0.1\n"); return 0; } float_setasciiz(&x, "2"); float_copy(&tmp, &x, EXACT); _coshminus1(&x, 100); float_arcoshxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 2\n"); return 0; } float_setasciiz(&x, "10000"); float_copy(&tmp, &x, EXACT); _coshminus1(&x, 100); float_arcoshxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 10000\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = 200; ++i <= 500;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _coshminus1(&x,100); _coshminus1(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _coshminus1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_tanhlt0_5() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _tanhlt0_5"); float_create(&x); float_create(&tmp); float_create(&x1); float_create(&max); float_setzero(&max); printf("verifying function results:\n"); float_setzero(&x); _tanhlt0_5(&x, 100); if (!float_iszero(&x)) { printf("FAILED for x == 0\n"); return 0; } float_setasciiz(&x, ".1"); float_copy(&tmp, &x, EXACT); _tanhlt0_5(&x, 100); float_artanh(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 0.1\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = 0; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _tanhlt0_5(&x,100); _tanhlt0_5(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _tanhlt0_5: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_tanhminus1gt0() { floatstruct x, x1, tmp, max; int i; char buf[50]; printf("%s\n", "testing _tanhminus1gt0"); float_create(&x); float_create(&tmp); float_create(&x1); float_create(&max); float_setzero(&max); float_setasciiz(&x, "1"); float_copy(&tmp, &x, EXACT); _tanhminus1gt0(&x, 100); float_artanhxplus1(&x, 110); if(!_cmprelerror(&x, &tmp, -99)) { printf("FAILED for x == 1\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setasciiz(&tmp, ".005"); for (i = 0; ++i <= 300;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); _tanhminus1gt0(&x,100); _tanhminus1gt0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } for (i = 1; i <= EXPMAX;) { float_setinteger(&x, 1); _sub_ulp(&x, 101); float_setexponent(&x, i); i*=10; float_copy(&x1, &x, EXACT); _tanhminus1gt0(&x,100); _tanhminus1gt0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _tanhminus1gt0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_tanh_range() { const char* inputs[] = { "1e8", "618095478", "618095480", "1e9", "1236190956", "1236190958", "1e10", "1e100" }; const int precisions[] = { 1, 20, 50, 83, 100 }; floatstruct x; int p, i, sign, offset, ok = 1; Error error; float_create(&x); for (p = 0; p < (int)(sizeof(precisions)/sizeof(precisions[0])); ++p) for (sign = -1; sign <= 1; sign += 2) { for (i = 0; i <= (int)(sizeof(inputs)/sizeof(inputs[0])); ++i) { float_geterror(); if (i == (int)(sizeof(inputs)/sizeof(inputs[0]))) { float_setinteger(&x, 9); float_setexponent(&x, float_getrange()); } else float_setasciiz(&x, inputs[i]); float_setsign(&x, (signed char)sign); ok = float_tanh(&x, precisions[p]); error = float_geterror(); if (!ok || error != Success || float_cmp(&x, sign > 0? &c1 : &cMinus1) != 0) { printf("FAILED tanh range: input %d, sign %d, digits %d, error %d\n", i, sign, precisions[p], error); float_free(&x); return 0; } } /* Check both sides of the conservative, precision-dependent cutoff. */ for (offset = precisions[p] == 1? 0 : -1; offset <= 1; ++offset) { float_setinteger(&x, sign*(2*precisions[p] + offset)); ok = float_tanh(&x, precisions[p]); float_round(&x, &x, precisions[p], TONEAREST); error = float_geterror(); if (!ok || error != Success || float_cmp(&x, sign > 0? &c1 : &cMinus1) != 0) { printf("FAILED tanh cutoff: sign %d, digits %d, offset %d\n", sign, precisions[p], offset); float_free(&x); return 0; } } } /* A correction invisible at 50 digits must remain visible at 100 digits. */ float_setinteger(&x, 100); ok = float_tanh(&x, 100); error = float_geterror(); if (!ok || error != Success || float_cmp(&x, &c1) >= 0) { printf("FAILED tanh precision: tanh(100) must remain below 1 at 100 digits\n"); float_free(&x); return 0; } float_setasciiz(&x, "1e10"); ok = float_exp(&x, 100); error = float_geterror(); if (ok || error != Overflow || !float_isnan(&x)) { printf("FAILED genuine exp overflow\n"); float_free(&x); return 0; } float_setasciiz(&x, "-1e10"); ok = float_exp(&x, 100); error = float_geterror(); if (ok || error != Underflow || !float_isnan(&x)) { printf("FAILED genuine exp underflow\n"); float_free(&x); return 0; } float_setasciiz(&x, "1e10"); ok = float_tanhminus1(&x, 100); error = float_geterror(); if (ok || error != Underflow || !float_isnan(&x)) { printf("FAILED genuine tanh(x)-1 underflow\n"); float_free(&x); return 0; } float_free(&x); return 1; } static int test_arctanlt1() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arctanlt1\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arctanlt1(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.46364760900080611621425623146121440202853" "7054286120263810933088720197864165741705300" "60028398488789255652985225119083751350581818162501"); _arctanlt1(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arctanlt1(&x, 100); _arctanlt1(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arctanlt1: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arctan() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arctan\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); float_setasciiz(&x, "-1.5"); float_setasciiz(&tmp, "-.98279372324732906798571061101466601449687" "7453631628556761425088317988071549796035389" "70653437281731110816513970201193676622994103918188"); _arctan(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-1.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 200; ++i < 400;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arctan(&x, 100); _arctan(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arctan: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arccosxplus1lt0_5() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arccosxplus1lt0_5\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arccosxplus1lt0_5(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "1.04719755119659774615421446109316762806572" "3133125035273658314864102605468762069666209" "34494178070568932738269550442743554903128153651686"); _arccosxplus1lt0_5(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 100;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arccosxplus1lt0_5(&x, 100); _arccosxplus1lt0_5(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arccosxplus1lt0_5: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arcsinlt0_5() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arcsinlt0_5\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arccosxplus1lt0_5(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.52359877559829887307710723054658381403286" "1566562517636829157432051302734381034833104" "67247089035284466369134775221371777451564076825843"); _arcsinlt0_5(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 100;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arcsinlt0_5(&x, 100); _arcsinlt0_5(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arcsinlt0_5: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arccos() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arccos\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setinteger(&x, 1); _arccos(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==1\n"); return 0; } float_setasciiz(&x, "0.5"); float_setasciiz(&tmp, "1.04719755119659774615421446109316762806572" "3133125035273658314864102605468762069666209" "34494178070568932738269550442743554903128153651686"); _arccos(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==0.5\n"); return 0; } float_setzero(&x); _arccos(&x, 100); if (!_cmprelerror(&x, &cPiDiv2, -99)) { printf("FAILED for x==0\n"); return 0; } float_setinteger(&x, -1); _arccos(&x, 100); if (!_cmprelerror(&x, &cPi, -99)) { printf("FAILED for x==-1\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.01"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = -100; ++i < 100;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arccos(&x, 100); _arccos(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arccos: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_arcsin() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _arcsin\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _arcsin(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.52359877559829887307710723054658381403286" "1566562517636829157432051302734381034833104" "67247089035284466369134775221371777451564076825843"); _arcsin(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } float_setinteger(&x, 1); _arcsin(&x, 100); if (!_cmprelerror(&x, &cPiDiv2, -99)) { printf("FAILED for x==1\n"); return 0; } float_setinteger(&x, -1); _arcsin(&x, 100); float_neg(&x); if (!_cmprelerror(&x, &cPiDiv2, -99)) { printf("FAILED for x==-1\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _arcsin(&x, 100); _arcsin(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _arcsin: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_cosminus1ltPiDiv4() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _cosminus1ltPiDiv4\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _cosminus1ltPiDiv4(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.12241743810962728388371841739617034800835" "4802890255947002389131684049236725786052594" "205815915317741644521599406890946006586172"); _cosminus1ltPiDiv4(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 158;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _cosminus1ltPiDiv4(&x, 100); _cosminus1ltPiDiv4(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _cosminus1ltPiDiv4: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_sinltPiDiv4() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _sinltPiDiv4\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _sinltPiDiv4(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.47942553860420300027328793521557138808180" "3367940600675188616613125535000287814832209" "63127468434826908613209108450571741781109374860994"); _sinltPiDiv4(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 158;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _sinltPiDiv4(&x, 100); _sinltPiDiv4(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _sinltPiDiv4: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_tanltPiDiv4() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _tanltPiDiv4\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _tanltPiDiv4(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&x, "-0.5"); float_setasciiz(&tmp, "-.54630248984379051325517946578028538329755" "1720179791246164091385932907510518025815715" "1806482706562185891048626002641142654932300911684"); _tanltPiDiv4(&x, 100); if (!_cmprelerror(&tmp, &x, -99)) { printf("FAILED for x==-0.5\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.005"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 0; ++i < 158;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _tanltPiDiv4(&x, 100); _tanltPiDiv4(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _tanltPiDiv4: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_cos() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _cos\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _cos(&x, 100); if(float_cmp(&x, &c1)!=0) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&step, "0.1"); for (i = 0; ++i < 15;) { float_muli(&x, &step, i, EXACT); float_add(&tmp, &x, &x, EXACT); _cos(&x, 100); _cos(&tmp, 100); float_mul(&x, &x, &x, 110); float_add(&x, &x, &x, EXACT); float_sub(&x, &x, &c1, EXACT); if (!_cmprelerror(&tmp, &x, -95)) { printf("FAILED for testcase %d\n", i); return 0; } } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = -63; ++i < 63;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _cos(&x, 100); _cos(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _cos: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_sin() { floatstruct x, tmp, max, step, ofs; int i; printf("testing _sin\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _sin(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&step, "0.1"); for (i = 0; ++i < 32;) { float_muli(&x, &step, i, EXACT); float_sub(&tmp, &x, &cPiDiv2, 110); _sin(&x, 100); _cos(&tmp, 100); if (!_cmprelerror(&tmp, &x, -95)) { printf("FAILED for testcase %d\n", i); return 0; } } float_setasciiz(&step, "0.5"); for (i = -7; ++i < 0;) { float_muli(&x, &step, i, EXACT); float_copy(&tmp, &x, EXACT); float_abs(&tmp); _sin(&x, 100); _sin(&tmp, 100); float_neg(&tmp); if (!_cmprelerror(&tmp, &x, -95)) { printf("FAILED for testcase %d\n", i); return 0; } } float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_tan() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _tan\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying function results:\n"); float_setzero(&x); _tan(&x, 100); if(!float_iszero(&x)) { printf("FAILED for x==0\n"); return 0; } float_setasciiz(&step, "0.1"); for (i = -32; ++i < 32;) { if (i == 0) continue; float_muli(&x, &step, i, EXACT); float_copy(&tmp, &x, EXACT); float_copy(&ofs, &x, EXACT); _sin(&x, 100); _cos(&tmp, 100); float_div(&tmp, &x, &tmp, 110); _tan(&ofs, 100); if (!_cmprelerror(&tmp, &ofs, -95)) { printf("FAILED for testcase %d\n", i); return 0; } } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = -63; ++i < 63;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _tan(&x, 100); _tan(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _tan: %s\n", buf); return 1; } static int tc_floatnum2longint(char* value, int lg, unsigned x0, unsigned x1, unsigned x2) { floatstruct x; t_longint longint; float_create(&x); float_setasciiz(&x, value); _floatnum2longint(&longint, &x); float_free(&x); return lg == longint.length && (lg == 0 || x0 == longint.value[0]) && (lg < 32 || x1 == longint.value[1]) && (lg < 64 || x2 == longint.value[2]); } static int test_floatnum2longint() { /* depends on wordsize!! */ printf("testing floatnum2longint\n"); if (!tc_floatnum2longint("0", 0, 0, 0, 0)) return 0; if (!tc_floatnum2longint("1", 1, 1, 0, 0)) return 0; if (!tc_floatnum2longint("1234567890", 1, 1234567890, 0, 0)) return 0; if (!tc_floatnum2longint("8589934592", 2, 0, 2, 0)) return 0; return 1; } static int tc_longint2floatnum(unsigned x0, unsigned x1, unsigned x2, int lg, char* value) { /* depends on wordsize!! */ floatstruct x, y; t_longint l; int i; float_create(&x); float_create(&y); for (i = 0; i < UARRAYLG; ++i) l.value[i] = 0; l.value[0] = x0; l.value[1] = x1; l.value[2] = x2; l.length = lg; float_setasciiz(&y, value); _longint2floatnum(&x, &l); if (float_cmp(&x, &y) != 0) { printf("conversion FAILED"); return 0; } float_free(&x); float_free(&y); return 1; } static int test_longint2floatnum() { printf("testing longint2floatnum\n"); if (!tc_longint2floatnum(0, 0, 0, 0, "0")) return 0; if (!tc_longint2floatnum(1, 0, 0, 1, "1")) return 0; if (!tc_longint2floatnum(2000000000, 0, 0, 1, "2000000000")) return 0; if (!tc_longint2floatnum(0, 2, 0, 2, "8589934592")) return 0; if (!tc_longint2floatnum(1000000, 2, 0, 2, "8590934592")) return 0; return 1; } static int tc_raiseposi(char* base, unsigned exponent) { floatstruct x, y; int expx, result; float_create(&x); float_create(&y); float_setasciiz(&x, base); float_copy(&y, &x, EXACT); float_abs(&y); float_lg(&y, 100); _raiseposi(&x, &expx, exponent, 100); float_abs(&x); float_lg(&x, 199); float_addi(&x, &x, expx, 100); float_divi(&x, &x, exponent, 100); result = _cmprelerror(&x, &y, 95); float_free(&x); float_free(&y); return result; } static int test_raiseposi() { floatstruct x, tmp, max, step, ofs; int expx; int i, j; char buf[50]; printf("testing _raiseposi\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); if (!tc_raiseposi("1", 1)) return 0; if (!tc_raiseposi("2", 1)) return 0; if (!tc_raiseposi("2", 2)) return 0; if (!tc_raiseposi("2", 3)) return 0; float_setinteger(&x, -1); _raiseposi(&x, &expx, 3, 100); if (float_cmp(&x, &cMinus1) != 0 || expx != 0) { printf("test case -1 ^ 3 FAILED"); return 0; } _raiseposi(&x, &expx, 2, 100); if (float_cmp(&x, &c1) != 0 || expx != 0) { printf("test case -1 ^ 2 FAILED"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "1"); float_setasciiz(&ofs, "1.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for (j = 0; j++ < 30;) for(i = 0; ++i < 10;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _raiseposi(&x, &expx, (1 << j)-1, 100); _raiseposi(&tmp, &expx, (1 << j)-1, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _raiseposi: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_raisei() { floatstruct x, y; printf ("testing _raisei\n"); float_create(&x); float_create(&y); float_copy(&x, &c1, EXACT); _raisei(&x, 0, 100); if (float_cmp(&x, &c1) != 0) { printf("test case 1^0 FAILED\n"); return 0; } _raisei(&x, 1, 100); if (float_cmp(&x, &c1) != 0) { printf("test case 1^1 FAILED\n"); return 0; } _raisei(&x, 100, 100); if (float_cmp(&x, &c1) != 0) { printf("test case 1^100 FAILED\n"); return 0; } float_copy(&x, &c2, EXACT); _raisei(&x, 0, 100); if (float_cmp(&x, &c1) != 0) { printf("test case 2^0 FAILED\n"); return 0; } float_copy(&x, &c2, EXACT); _raisei(&x, 1, 100); if (float_cmp(&x, &c2) != 0) { printf("test case 2^1 FAILED\n"); return 0; } float_setinteger(&y, 4); _raisei(&x, 2, 100); if (float_cmp(&x, &y) != 0) { printf("test case 2^2 FAILED\n"); return 0; } float_copy(&x, &c2, EXACT); _raisei(&x, -1, 100); if (float_cmp(&x, &c1Div2) != 0) { printf("test case 2^-1 FAILED\n"); return 0; } float_free(&y); float_free(&x); return 1; } static int test_binetasymptotic() { floatstruct x, y, tmp; int i; printf("testing lngammaseries\n"); float_create(&x); float_create(&y); float_create(&tmp); printf("verifying result\n"); float_setinteger(&tmp, 77); float_ln(&tmp, 110); float_setasciiz(&y, "76.5"); float_mul(&tmp, &tmp, &y, 110); float_setinteger(&y, 2); for (i = 2; ++i < 77;) float_muli(&y, &y, i, EXACT); float_ln(&y, 110); float_sub(&y, &y, &tmp, 110); float_addi(&y, &y, 77, 110); float_sub(&y, &y, &cLnSqrt2PiMinusHalf, 110); float_sub(&y, &y, &c1Div2, 110); float_setinteger(&x, 77); binetasymptotic(&x, 100); if (!_cmprelerror(&y, &x, -95)) { printf("verification FAILED\n"); return 0; } float_free(&x); float_free(&y); float_free(&tmp); return 1; } static int tc_pochhammer(char* x, char* n, char* result) { floatstruct fx, fn, fr; float_create(&fx); float_create(&fn); float_create(&fr); float_setasciiz(&fx, x); float_setasciiz(&fn, n); float_setasciiz(&fr, result); float_pochhammer(&fx, &fn, 100); if (float_isnan(&fr)) return float_isnan(&fx); if (!_cmprelerror(&fr, &fx, -95)) { printf("verification FAILED\n"); return 0; } return 1; } static int test_pochhammer() { printf("testing _pochhammer\n"); printf("verifying results\n"); if (!tc_pochhammer("0", "0", "1")) return 0; if (!tc_pochhammer("1", "0", "1")) return 0; if (!tc_pochhammer("-1", "0", "1")) return 0; if (!tc_pochhammer("1e100000", "0", "1")) return 0; if (!tc_pochhammer("-1e100000", "0", "1")) return 0; if (!tc_pochhammer("0.5", "0", "1")) return 0; if (!tc_pochhammer("-0.5", "0", "1")) return 0; if (!tc_pochhammer("0", "1", "0")) return 0; if (!tc_pochhammer("1", "1", "1")) return 0; if (!tc_pochhammer("-1", "1", "-1")) return 0; if (!tc_pochhammer("1e100000", "1", "1e100000")) return 0; if (!tc_pochhammer("-1e100000", "1", "-1e100000")) return 0; if (!tc_pochhammer("0.5", "1", "0.5")) return 0; if (!tc_pochhammer("-0.5", "1", "-0.5")) return 0; if (!tc_pochhammer("0", "2", "0")) return 0; if (!tc_pochhammer("1", "2", "2")) return 0; if (!tc_pochhammer("-1", "2", "0")) return 0; if (!tc_pochhammer("1e100000", "2", "1e200000")) return 0; if (!tc_pochhammer("-1e100000", "2", "1e200000")) return 0; if (!tc_pochhammer("0.5", "2", "0.75")) return 0; if (!tc_pochhammer("-0.5", "2", "-0.25")) return 0; if (!tc_pochhammer("1", "100", "93326215443944152681699238856266700490715968264381621468592963895217" "59999322991560894146397615651828625369792082722375825118521091686400" "0000000000000000000000")) return 0; if (!tc_pochhammer("-100", "101", "0")) return 0; if (!tc_pochhammer("-100", "100", "93326215443944152681699238856266700490715968264381621468592963895217" "59999322991560894146397615651828625369792082722375825118521091686400" "0000000000000000000000")) return 0; if (!tc_pochhammer("1", "-1", "NaN")) return 0; if (!tc_pochhammer("2", "-1", "1")) return 0; if (!tc_pochhammer("2", "-2", "NaN")) return 0; if (!tc_pochhammer("1.5", "-1", "2")) return 0; if (!tc_pochhammer("1.5", "-2", "-4")) return 0; if (!tc_pochhammer("1.5", "-100", "-.000000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000378414024807910640737099845525006763221785165860" "06641218189552393913245454474853055919575212143764296945522753626016" "300639832411419246985800884362")) return 0; if (!tc_pochhammer("-1.5", "100", "40242764267707289912333641217950774848709656376758843494819950464847" "04420564703857828107982141126998570896720926829585700250010032188267" "20546901916750645.18900647214084211566623156559209401240552373723543")) return 0; if (!tc_pochhammer("-3", "-1", "-0.25")) return 0; if (!tc_pochhammer("-1e100000", "-1", "-1e-100000")) return 0; if (!tc_pochhammer("-2.2", "1.3", "4.793948981105061902495028514824576929486499142574590370996037700670" "07956370445687178188113235399766021571905874962934089400569549735499" "47062783690929661636680480933415006255499710782394427770555172981506")) return 0; return 1; } static int test_lngamma() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _lngamma\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying results\n"); float_copy(&x, &c3, EXACT); _lngamma(&x, 100); if(!_cmprelerror(&x, &cLn2, -95)) { printf("verification FAILED\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 100; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _lngamma(&x, 100); _lngamma(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error _lngamma: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_gamma() { floatstruct x, tmp, max, step, ofs; int i; char buf[50]; printf("testing _gamma\n"); float_create(&x); float_create(&tmp); float_create(&max); float_create(&step); float_create(&ofs); printf("verifying results\n"); float_setasciiz(&x, "0.2"); float_setasciiz(&tmp, "4.590843711998803053204758275929152003434109998293403" "01778885313623003927310644499897403940828778507456912"); _gamma(&x, 100); if(!_cmprelerror(&x, &tmp, -95)) { printf("verification FAILED\n"); return 0; } float_setasciiz(&x, "-30.2"); float_setasciiz(&tmp, "-1.0165368282364803216788184978362164979757349922035594" "1791712115025420329582124053302476303836291973429411315e-32"); _gamma(&x, 100); if(!_cmprelerror(&x, &tmp, -95)) { printf("verification FAILED\n"); return 0; } float_setasciiz(&x, "-1.5"); float_setasciiz(&tmp, "0.75"); float_div(&tmp, &cSqrtPi, &tmp, 110); _gamma(&x, 100); if(!_cmprelerror(&x, &tmp, -95)) { printf("verification FAILED\n"); return 0; } float_setasciiz(&x, "10"); float_setasciiz(&tmp, "362880"); _gamma(&x, 100); if(!_cmprelerror(&x, &tmp, -95)) { printf("verification FAILED\n"); return 0; } printf("testing error limit:\n"); float_setzero(&max); float_setasciiz(&step, "0.05"); float_setasciiz(&ofs, "0.000147436738983647399324678823992433673" "24672389823467828246764829833467849839838778485784386584539" "85343784568643548923998439823432792346"); for(i = 100; ++i < 200;) { float_muli(&tmp, &step, i, EXACT); float_add(&x, &tmp, &ofs, EXACT); float_copy(&tmp, &x, EXACT); _gamma(&x, 100); _gamma(&tmp, 110); _relerror(&x, &tmp); if (float_cmp(&x, &max) > 0) { float_copy(&max, &x, EXACT); if (float_getexponent(&x) >= -99) { printf("exceeding error in test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } printf("testing asymptotic series of gamma:\n"); for(i = 0; ++i < 100;) { float_setasciiz(&x, "1.01"); printf("testing precision %d: ", i); _gamma(&x, i); printf("asymptotic series converging\n"); } float_getscientific(buf, 50, &max); printf("max error _gamma: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&max); float_free(&step); float_free(&ofs); return 1; } static int test_gammaint() { floatstruct x, y; printf("testing _gammaint\n"); float_create(&x); float_create(&y); printf("verifying results\n"); float_setinteger(&x, 1); float_setinteger(&y, 1); _gammaint(&x, 100); if (float_cmp(&x, &y) != 0) { printf("verification FAILED\n"); return 0; } float_setinteger(&x, 2); float_setinteger(&y, 1); _gammaint(&x, 100); if (float_cmp(&x, &y) != 0) { printf("verification FAILED\n"); return 0; } float_setinteger(&x, 3); float_setinteger(&y, 2); _gammaint(&x, 100); if (float_cmp(&x, &y) != 0) { printf("verification FAILED\n"); return 0; } float_free(&x); float_free(&y); return 1; } static int tc_gamma0_5(char* value) { floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); float_copy(&y, &x, EXACT); _gamma0_5(&x, 100); _gamma(&y, 100); if (!_cmprelerror(&x, &y, -95)) { printf("verification FAILED\n"); return 0; } float_free(&x); float_free(&y); return 1; } static int test_gamma0_5() { printf("testing _gamma0_5\n"); printf("verifying results\n"); if (!tc_gamma0_5(".5")) return 0; if (!tc_gamma0_5("-.5")) return 0; if (!tc_gamma0_5("1.5")) return 0; if (!tc_gamma0_5("-1.5")) return 0; if (!tc_gamma0_5("-30.5")) return 0; if (!tc_gamma0_5("30.5")) return 0; return 1; } static int tc_floatnum2logic(char* value, unsigned x0, unsigned x1, unsigned x2) { floatstruct x; t_longint r; float_create(&x); float_setasciiz(&x, value); _floatnum2logic(&r, &x); float_free(&x); return r.value[0] == x0 && r.value[1] == x1 && r.value[2] == x2; } static int test_floatnum2logic() { /* based on the size of unsigned */ printf("testing _floatnum2logic\n"); if(!tc_floatnum2logic("0", 0, 0, 0)) return 0; if(!tc_floatnum2logic("1", 1, 0, 0)) return 0; if(!tc_floatnum2logic("-1", ~0u, ~0u, ~0u)) return 0; if(!tc_floatnum2logic("-2147483648", ~2147483647u, ~0u, ~0u)) return 0; if(!tc_floatnum2logic("8589934592", 0, 2, 0)) return 0; return 1; } static int tc_logic2floatnum(char* value) { t_longint l; floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); _floatnum2logic(&l, &x); _logic2floatnum(&y, &l); if (float_cmp(&x, &y) != 0) { printf("test case %s FAILED\n", value); return 0; } float_free(&x); float_free(&y); return 1; } static int test_logic2floatnum() { printf("testing _logic2floatnum\n"); if(!tc_logic2floatnum("0")) return 0; if(!tc_logic2floatnum("1")) return 0; if(!tc_logic2floatnum("-1")) return 0; if(!tc_logic2floatnum("-2147483648")) return 0; if(!tc_logic2floatnum("-2147483649")) return 0; if(!tc_logic2floatnum("4294967295")) return 0; if(!tc_logic2floatnum("-4294967296")) return 0; if(!tc_logic2floatnum("8589934592")) return 0; return 1; } static int tc_not(char* value, char* result) { floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); float_setasciiz(&y, result); float_not(&x); if (float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_not() { printf("testing float_not\n"); if (!tc_not("0", "-1")) return 0; if (!tc_not("1", "-2")) return 0; if (!tc_not("-1", "0")) return 0; if (!tc_not("-2", "1")) return 0; return 1; } static int test_and() { floatstruct x, y; printf("testing float_and\n"); float_create(&x); float_create(&y); float_setasciiz(&x, "5"); float_setasciiz(&y, "6"); float_and(&x, &x, &y); float_setasciiz(&y, "4"); if (float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_or() { floatstruct x, y; printf("testing float_or\n"); float_create(&x); float_create(&y); float_setasciiz(&x, "5"); float_setasciiz(&y, "6"); float_or(&x, &x, &y); float_setasciiz(&y, "7"); if (float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_xor() { floatstruct x, y; printf("testing float_xor\n"); float_create(&x); float_create(&y); float_setasciiz(&x, "5"); float_setasciiz(&y, "6"); float_xor(&x, &x, &y); float_setasciiz(&y, "3"); if (float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } #define tc_shl(value, shift, result) \ _tc_shl(__FILE__,__LINE__, #value"/"#shift, value, shift, result) static void _tc_shl(const char* file, int line, char* msg, char* value, char* shift, char* result) { floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); float_setasciiz(&y, shift); float_shl(&x, &x, &y); float_setasciiz(&y, result); DisplayErrorOnFloatMismatch(file, line, msg, &x, &y, &g_failed_tests, &g_new_failed_tests, 0); float_free(&x); float_free(&y); } static int test_shl() { printf("testing float_shl\n"); tc_shl("0", "0", "0"); tc_shl("-1", "0", "-1"); tc_shl("1", "1", "2"); tc_shl("1", "32", "4294967296"); tc_shl("1", "64", "18446744073709551616"); tc_shl("1", "96", "0"); tc_shl("1", "95", "-39614081257132168796771975168"); tc_shl("1", "1000", "0"); tc_shl("4294967295", "1", "8589934590"); return 1; } static int tc_shr(char* value, char* shift, char* result) { floatstruct x, y; float_create(&x); float_create(&y); float_setasciiz(&x, value); float_setasciiz(&y, shift); float_shr(&x, &x, &y); float_setasciiz(&y, result); if(float_cmp(&x, &y) != 0) return 0; float_free(&x); float_free(&y); return 1; } static int test_shr() { printf("testing float_shr\n"); if (!tc_shr("0", "0", "0")) return 0; if (!tc_shr("1", "1", "0")) return 0; if (!tc_shr("2", "1", "1")) return 0; if (!tc_shr("4294967296", "32", "1")) return 0; if (!tc_shr("-1", "32", "-1")) return 0; if (!tc_shr("-4", "1", "-2")) return 0; if (!tc_shr("-39614081257132168796771975168", "94", "-2")) return 0; return 1; } static void _tc_out(const char* file, int line, char* msg, char* value, int digits, char base, char mode, char* result) { char intbuf[150]; char fracbuf[150]; char buffer[350]; t_otokens tokens; floatstruct x; ++g_total_tests; float_create(&x); float_setasciiz(&x, value); tokens.intpart.sz = sizeof(intbuf); tokens.intpart.buf = intbuf; tokens.fracpart.sz = 150; tokens.fracpart.buf = fracbuf; if (float_out(&tokens, &x, digits, base, mode) != Success) { if (result != NULL && *result != '\0') { DisplayErrorOnStrMismatch(file, line, msg, "ERROR", result, &g_failed_tests, &g_new_failed_tests, 0); } return; } cattokens(buffer, 350, &tokens, 0, IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_LDG_ZERO); float_free(&x); DisplayErrorOnStrMismatch(file, line, msg, buffer, result, &g_failed_tests, &g_new_failed_tests, 0); } static int test_out() { t_ioparams iop[4] = { // base, expbase, dot, basetag, expbegin, expend, cmpltag, maxdigits {10, 10, '.', "0d", "(", ")", "", 70}, {16, 10, '.', "0x", "(", ")", "sF", 70}, {2, 10, '.', "0b", "(", ")", "s1", 70}, {8, 10, '.', "0o", "(", ")", "s7", 70} }; t_ioparams saveiop[4]; int i; io_rounding_mode savedRoundMode = float_get_output_rounding_mode(); // Use our own ioparams to make sure the results are the expected ones for (i = 0 ; i < sizeof(iop) / sizeof(t_ioparams) ; ++i) { saveiop[i] = *getioparams(iop[i].base); setioparams(&iop[i]); } float_set_output_rounding_mode(IO_ROUND_HALF_AWAY_FROM_ZERO); printf("testing float_out\n"); tc_out("NaN", 0, 10, IO_MODE_SCIENTIFIC, "NaN"); tc_out("0", 0, IO_BASE_NAN, IO_MODE_SCIENTIFIC, ""); tc_out("0", 0, IO_BASE_ZERO, IO_MODE_SCIENTIFIC, ""); tc_out("1", 0, IO_BASE_NAN, IO_MODE_SCIENTIFIC, ""); tc_out("0", 0, 5, IO_MODE_SCIENTIFIC, ""); tc_out("0", 0, 10, -1, ""); tc_out("0", 0, 10, IO_MODE_SCIENTIFIC, "0"); tc_out("1", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d0)"); tc_out("-1", 0, 10, IO_MODE_SCIENTIFIC, "-0d1(+0d0)"); tc_out("1.000000002", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d0)"); tc_out("1.0002", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.0(+0d0)"); tc_out("1.07", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.1(+0d0)"); tc_out("1.2", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.2(+0d0)"); tc_out("1.2", 2, 10, IO_MODE_SCIENTIFIC, "+0d1.20(+0d0)"); tc_out("10", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d1)"); tc_out("100", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d2)"); tc_out("1e12345678", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d12345678)"); tc_out("1.234e12345678", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(+0d12345678)"); tc_out("1.234e12345678", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.2(+0d12345678)"); tc_out("1.234e12345678", 3, 10, IO_MODE_SCIENTIFIC, "+0d1.234(+0d12345678)"); tc_out("1.234e12345678", 4, 10, IO_MODE_SCIENTIFIC, "+0d1.2340(+0d12345678)"); tc_out("0.1", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(-0d1)"); tc_out("1.234e-12345678", 0, 10, IO_MODE_SCIENTIFIC, "+0d1(-0d12345678)"); tc_out("1.234e-12345678", 1, 10, IO_MODE_SCIENTIFIC, "+0d1.2(-0d12345678)"); tc_out("1.234e-12345678", 3, 10, IO_MODE_SCIENTIFIC, "+0d1.234(-0d12345678)"); tc_out("1.234e-12345678", 4, 10, IO_MODE_SCIENTIFIC, "+0d1.2340(-0d12345678)"); tc_out("1", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d0)"); tc_out("15", 0, 16, IO_MODE_SCIENTIFIC, "+0xF(+0d0)"); tc_out("16", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d1)"); tc_out("17", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d1)"); tc_out("18", 1, 16, IO_MODE_SCIENTIFIC, "+0x1.2(+0d1)"); tc_out("4096", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d3)"); tc_out("6144", 0, 16, IO_MODE_SCIENTIFIC, "+0x2(+0d3)"); tc_out("1099511627776", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d10)"); tc_out("18446744073709551616", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d16)"); tc_out("18446744073709551616", 15, 16, IO_MODE_SCIENTIFIC, "+0x1.000000000000000(+0d16)"); tc_out("1.8", 0, 16, IO_MODE_SCIENTIFIC, "+0x2(+0d0)"); tc_out("-1.5", 1, 16, IO_MODE_SCIENTIFIC, "-0x1.8(+0d0)"); tc_out("0.5", 0, 16, IO_MODE_SCIENTIFIC, "+0x8(-0d1)"); tc_out("0.25", 0, 16, IO_MODE_SCIENTIFIC, "+0x4(-0d1)"); tc_out("0.125", 0, 16, IO_MODE_SCIENTIFIC, "+0x2(-0d1)"); tc_out("0.0625", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(-0d1)"); tc_out("0.03125", 0, 16, IO_MODE_SCIENTIFIC, "+0x8(-0d2)"); tc_out("0.75", 0, 16, IO_MODE_SCIENTIFIC, "+0xC(-0d1)"); tc_out("0.96875", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(+0d0)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 0, 16, IO_MODE_SCIENTIFIC, "+0x1(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 16, 16, IO_MODE_SCIENTIFIC, "+0x1.0000000000000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 15, 16, IO_MODE_SCIENTIFIC, "+0x1.000000000000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 14, 16, IO_MODE_SCIENTIFIC, "+0x1.00000000000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 13, 16, IO_MODE_SCIENTIFIC, "+0x1.0000000000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 12, 16, IO_MODE_SCIENTIFIC, "+0x1.000000000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 11, 16, IO_MODE_SCIENTIFIC, "+0x1.00000000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 10, 16, IO_MODE_SCIENTIFIC, "+0x1.0000000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 9, 16, IO_MODE_SCIENTIFIC, "+0x1.000000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 8, 16, IO_MODE_SCIENTIFIC, "+0x1.00000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 7, 16, IO_MODE_SCIENTIFIC, "+0x1.0000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 6, 16, IO_MODE_SCIENTIFIC, "+0x1.000000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 5, 16, IO_MODE_SCIENTIFIC, "+0x1.00000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 4, 16, IO_MODE_SCIENTIFIC, "+0x1.0000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 3, 16, IO_MODE_SCIENTIFIC, "+0x1.000(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 2, 16, IO_MODE_SCIENTIFIC, "+0x1.00(-0d16)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 1, 16, IO_MODE_SCIENTIFIC, "+0x1.0(-0d16)"); tc_out("1", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(+0d0)"); tc_out("2", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(+0d1)"); tc_out("3", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(+0d2)"); tc_out("3", 1, 2, IO_MODE_SCIENTIFIC, "+0b1.1(+0d1)"); tc_out("3", 2, 2, IO_MODE_SCIENTIFIC, "+0b1.10(+0d1)"); tc_out("0.5", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(-0d1)"); tc_out("0.25", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(-0d2)"); tc_out("0.75", 0, 2, IO_MODE_SCIENTIFIC, "+0b1(-0d1)"); tc_out("-0.75", 1, 2, IO_MODE_SCIENTIFIC, "-0b1.1(-0d1)"); tc_out("1", 0, 8, IO_MODE_SCIENTIFIC, "+0o1(+0d0)"); tc_out("2", 0, 8, IO_MODE_SCIENTIFIC, "+0o2(+0d0)"); tc_out("4", 0, 8, IO_MODE_SCIENTIFIC, "+0o4(+0d0)"); tc_out("8", 0, 8, IO_MODE_SCIENTIFIC, "+0o1(+0d1)"); tc_out("16", 0, 8, IO_MODE_SCIENTIFIC, "+0o2(+0d1)"); tc_out("0.5", 0, 8, IO_MODE_SCIENTIFIC, "+0o4(-0d1)"); tc_out("0.75", 0, 8, IO_MODE_SCIENTIFIC, "+0o6(-0d1)"); tc_out("0.875", 0, 8, IO_MODE_SCIENTIFIC, "+0o7(-0d1)"); tc_out("0.9375", 1, 8, IO_MODE_SCIENTIFIC, "+0o7.4(-0d1)"); tc_out("0.9375", 0, 8, IO_MODE_SCIENTIFIC, "+0o1(+0d0)"); tc_out("NaN", 1, 10, IO_MODE_FIXPOINT, "NaN"); tc_out("0", 1, IO_BASE_NAN, IO_MODE_FIXPOINT, ""); tc_out("0", 1, IO_BASE_ZERO, IO_MODE_FIXPOINT, ""); tc_out("1", 1, IO_BASE_NAN, IO_MODE_FIXPOINT, ""); tc_out("0", 1, 5, IO_MODE_FIXPOINT, ""); tc_out("0", 1, 10, IO_MODE_FIXPOINT, "0"); tc_out("1", 0, 10, IO_MODE_FIXPOINT, "+0d1(+0d0)"); tc_out("1", 1, 10, IO_MODE_FIXPOINT, "+0d1.0(+0d0)"); tc_out("10", 0, 10, IO_MODE_FIXPOINT, "+0d10(+0d0)"); tc_out("-10", 0, 10, IO_MODE_FIXPOINT, "-0d10(+0d0)"); tc_out("10", 3, 10, IO_MODE_FIXPOINT, "+0d10.000(+0d0)"); tc_out("10.1", 0, 10, IO_MODE_FIXPOINT, "+0d10(+0d0)"); tc_out("10.1", 1, 10, IO_MODE_FIXPOINT, "+0d10.1(+0d0)"); tc_out("10.1", 2, 10, IO_MODE_FIXPOINT, "+0d10.10(+0d0)"); tc_out("10.12", 1, 10, IO_MODE_FIXPOINT, "+0d10.1(+0d0)"); tc_out("10.16", 1, 10, IO_MODE_FIXPOINT, "+0d10.2(+0d0)"); tc_out("10.86", 0, 10, IO_MODE_FIXPOINT, "+0d11(+0d0)"); tc_out("0.1", 1, 10, IO_MODE_FIXPOINT, "+0d.1(+0d0)"); tc_out("0.12", 1, 10, IO_MODE_FIXPOINT, "+0d.1(+0d0)"); tc_out("0.0123", 2, 10, IO_MODE_FIXPOINT, "+0d.01(+0d0)"); tc_out("18446744073709551616", 0, 10, IO_MODE_FIXPOINT, "+0d18446744073709551616(+0d0)"); tc_out("0.75", 1, 16, IO_MODE_FIXPOINT, "+0x.C(+0d0)"); tc_out("18446744073709551616", 0, 16, IO_MODE_FIXPOINT, "+0x10000000000000000(+0d0)"); tc_out("18446744073709551615", 0, 16, IO_MODE_FIXPOINT, "+0xFFFFFFFFFFFFFFFF(+0d0)"); tc_out("18446744073709551615", 1, 16, IO_MODE_FIXPOINT, "+0xFFFFFFFFFFFFFFFF.0(+0d0)"); tc_out("5.42101086242752217003726400434970855712890625e-20", 16, 16, IO_MODE_FIXPOINT, "+0x.0000000000000001(+0d0)"); tc_out("-0.75", 2, 2, IO_MODE_FIXPOINT, "-0b.11(+0d0)"); tc_out("0.9375", 2, 8, IO_MODE_FIXPOINT, "+0o.74(+0d0)"); tc_out("4.9375", 2, 8, IO_MODE_FIXPOINT, "+0o4.74(+0d0)"); tc_out("4.9375", 1, 8, IO_MODE_FIXPOINT, "+0o5.0(+0d0)"); tc_out("4.9375", 0, 10, IO_MODE_FIXPOINT, "+0d5(+0d0)"); tc_out("4.9375", 0, 16, IO_MODE_FIXPOINT, "+0x5(+0d0)"); tc_out("4.9375", 0, 8, IO_MODE_FIXPOINT, "+0o5(+0d0)"); tc_out("4.9375", 0, 2, IO_MODE_FIXPOINT, "+0b101(+0d0)"); tc_out("1.23", 2, 10, IO_MODE_ENG, "+0d1.23(+0d0)"); tc_out("12.3", 2, 10, IO_MODE_ENG, "+0d12.3(+0d0)"); tc_out("123", 2, 10, IO_MODE_ENG, "+0d123(+0d0)"); tc_out("1234", 2, 10, IO_MODE_ENG, "+0d1.23(+0d3)"); tc_out("0.1234", 2, 10, IO_MODE_ENG, "+0d123(-0d3)"); tc_out("0.0123", 2, 10, IO_MODE_ENG, "+0d12.3(-0d3)"); tc_out("0.00123", 2, 10, IO_MODE_ENG, "+0d1.23(-0d3)"); tc_out("0.000123", 2, 10, IO_MODE_ENG, "+0d123(-0d6)"); tc_out("-0.000123", 2, 10, IO_MODE_ENG, "-0d123(-0d6)"); tc_out("0", 0, 16, IO_MODE_COMPLEMENT, "0"); tc_out("1", 0, 16, IO_MODE_COMPLEMENT, "0x1(+0d0)"); tc_out("-1", 0, 16, IO_MODE_COMPLEMENT, "0xsF(+0d0)"); tc_out("-2", 0, 16, IO_MODE_COMPLEMENT, "0xsFE(+0d0)"); tc_out("-16", 0, 16, IO_MODE_COMPLEMENT, "0xsF0(+0d0)"); tc_out("-17", 0, 16, IO_MODE_COMPLEMENT, "0xsFEF(+0d0)"); // Output rounding mode coverage. float_set_output_rounding_mode(IO_ROUND_HALF_AWAY_FROM_ZERO); tc_out("2.5", 0, 10, IO_MODE_FIXPOINT, "+0d3(+0d0)"); tc_out("-2.5", 0, 10, IO_MODE_FIXPOINT, "-0d3(+0d0)"); float_set_output_rounding_mode(IO_ROUND_HALF_EVEN); tc_out("2.5", 0, 10, IO_MODE_FIXPOINT, "+0d2(+0d0)"); tc_out("3.5", 0, 10, IO_MODE_FIXPOINT, "+0d4(+0d0)"); tc_out("-2.5", 0, 10, IO_MODE_FIXPOINT, "-0d2(+0d0)"); float_set_output_rounding_mode(IO_ROUND_TOWARD_ZERO); tc_out("2.9", 0, 10, IO_MODE_FIXPOINT, "+0d2(+0d0)"); tc_out("-2.9", 0, 10, IO_MODE_FIXPOINT, "-0d2(+0d0)"); tc_out("2.5", 0, 10, IO_MODE_FIXPOINT, "+0d2(+0d0)"); float_set_output_rounding_mode(IO_ROUND_TOWARD_PLUS_INFINITY); tc_out("2.21", 1, 10, IO_MODE_FIXPOINT, "+0d2.3(+0d0)"); tc_out("-2.21", 1, 10, IO_MODE_FIXPOINT, "-0d2.2(+0d0)"); float_set_output_rounding_mode(IO_ROUND_TOWARD_MINUS_INFINITY); tc_out("2.29", 1, 10, IO_MODE_FIXPOINT, "+0d2.2(+0d0)"); tc_out("-2.21", 1, 10, IO_MODE_FIXPOINT, "-0d2.3(+0d0)"); // Restore default ioparams for (i = 0 ; i < sizeof(iop) / sizeof(t_ioparams) ; ++i) { setioparams(&saveiop[i]); } float_set_output_rounding_mode(savedRoundMode); return 1; } static void _tc_in(const char* file, int line, char* msg, const char* text, char* result) { t_itokens tokens; floatstruct x; floatstruct r; float_create(&x); float_create(&r); float_setasciiz(&r, result); parse(&tokens, &text); float_in(&x, &tokens); DisplayErrorOnFloatMismatch(file, line, msg, &x, &r, &g_failed_tests, &g_new_failed_tests, 0); float_free(&x); float_free(&r); } static int test_in() { printf("testing float_in\n"); tc_in("", "NaN"); tc_in("NaN", "NaN"); tc_in("0", "0"); tc_in("0.", "0"); tc_in(".0", "0"); tc_in("+0", "0"); tc_in("0d0", "0"); tc_in("+0d0", "0"); tc_in("-0", "0"); tc_in("0000", "0"); tc_in(".0000", "0"); tc_in("00.00", "0"); tc_in("1", "1"); tc_in("0d1", "1"); tc_in("1.", "1"); tc_in("1.00", "1"); tc_in("001.00", "1"); tc_in("+1", "1"); tc_in("-1", "-1"); tc_in("10", "10"); tc_in("010", "10"); tc_in("010.00", "10"); tc_in("123456789", "123456789"); tc_in("0.1", "0.1"); tc_in(".1", "0.1"); tc_in(".1000", "0.1"); tc_in("000.1000", "0.1"); tc_in(".01000", "0.01"); tc_in(".0123456789000", "0.0123456789"); tc_in("2.1", "2.1"); tc_in("001234.567800", "1234.5678"); tc_in("0012340.567800", "12340.5678"); tc_in("001234.0567800", "1234.05678"); tc_in("0012340.0567800", "12340.05678"); tc_in("1e0", "1"); tc_in("1(0)", "1"); tc_in("1e+0", "1"); tc_in("1e-0", "1"); tc_in("0d1e-0d0", "1"); tc_in("1e1", "10"); tc_in("1e+1", "10"); tc_in("1e-1", "0.1"); tc_in("1.e-1", "0.1"); tc_in("1.2e-1", "0.12"); tc_in("0.2e-1", "0.02"); tc_in("12e-1", "1.2"); tc_in("12e-2", "0.12"); tc_in("12e1", "120"); tc_in("0.12e1", "1.2"); tc_in("0.12e2", "12"); tc_in("0x0", "0"); tc_in("0x1", "1"); tc_in("0x1.0", "1"); tc_in("0x0001", "1"); tc_in("0x0001.00", "1"); tc_in("-0x1", "-1"); tc_in("+0x1", "1"); tc_in("0xA", "10"); tc_in("0xa", "10"); tc_in("0x10", "16"); tc_in("0x10000000000000000", "18446744073709551616"); tc_in("0xFFFFFFFFFFFFFFFF", "18446744073709551615"); tc_in("0x.8", "0.5"); tc_in("0x.4", "0.25"); tc_in("0x.08", "0.03125"); tc_in("0x1.2", "1.125"); tc_in("0x10.C", "16.75"); tc_in("0x1(1)", "16"); tc_in("0x1(-1)", "0.0625"); tc_in("0x1(A)", "1099511627776"); tc_in("0x1(0d10)", "1099511627776"); tc_in("0x1(10)", "18446744073709551616"); tc_in("0x1.1(1)", "17"); tc_in("0x1h1", "16"); tc_in("0x1H-1", "0.0625"); tc_in("0x1hA", "1099511627776"); tc_in("0x1H0d10", "1099511627776"); tc_in("0x1h10", "18446744073709551616"); tc_in("0x1.1H1", "17"); tc_in("0b0", "0"); tc_in("0b1", "1"); tc_in("0b1.0", "1"); tc_in("-0b1", "-1"); tc_in("0b10", "2"); tc_in("0b11", "3"); tc_in("0b.11", ".75"); tc_in("0b1.1", "1.5"); tc_in("0b1.1(-1)", "0.75"); tc_in("0b1.1(1)", "3"); tc_in("0b1.1(0b1)", "3"); tc_in("0b1.1(10)", "6"); tc_in("0b1.1b-1", "0.75"); tc_in("0b1.1B1", "3"); tc_in("0b1.1b0b1", "3"); tc_in("0b1.1B10", "6"); tc_in("0o0", "0"); tc_in("0o1", "1"); tc_in("0o1.0", "1"); tc_in("-0o1", "-1"); tc_in("0o10", "8"); tc_in("0o14", "12"); tc_in("0o.6", ".75"); tc_in("0o1.1", "1.125"); tc_in("0o1.4(-1)", "0.1875"); tc_in("0o1.4(1)", "12"); tc_in("0o1.4(0o1)", "12"); tc_in("0o2(10)", "33554432"); tc_in("0o1.4o-1", "0.1875"); tc_in("0o1.4O1", "12"); tc_in("0o1.4C0o1", "12"); tc_in("0o2o10", "33554432"); tc_in("0xsF", "-1"); tc_in("0xsFF", "-1"); tc_in("0xsFE", "-2"); tc_in("0xsFFE", "-2"); tc_in("0xsF0", "-16"); tc_in("0xsF01", "-255"); tc_in("0bs1", "-1"); tc_in("0bs11", "-1"); tc_in("0bs10", "-2"); tc_in("0bs110", "-2"); tc_in("0bs101", "-3"); tc_in("0os7", "-1"); tc_in("0os77", "-1"); tc_in("0os76", "-2"); tc_in("0os70", "-8"); tc_in("0os767", "-9"); tc_in("0os701", "-63"); return 1; } static int test_erfnear0() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); float_setzero(&max); printf("%s\n", "testing erfnear0"); printf("verifying special argument x == 0:\n"); float_setzero(&x); erfnear0(&x, 100); if (!float_iszero(&x)) { printf("FAILED\n"); return 0; } /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "2.7"); float_ln(&x, 100); erfnear0(&x, 100); float_setasciiz(&x1,".7443248085801137476495167988933711046591685164758118184461636179213" "12059356598790281111307476902061005913670963660509168"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == ln 2.7\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".005", NULLTERMINATED); for (i = -1; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); erfnear0(&x,100); erfnear0(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error erfnear0: %s\n", buf); float_free(&tmp); float_free(&x); float_free(&x1); float_free(&max); return 1; } static int test_erfcasymptotic() { floatstruct x, x1, tmp, max; int i; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); printf("%s\n", "testing erfcasymptotic"); /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&x, "16"); erfcasymptotic(&x, 100); float_setasciiz(&x1,".99805820883474330725563527001359438444222962655197" "570407974747783849037252552071214598018034509890346" "673633987464964958201780044076702727433644232998947" "151419098605560850226039542578816264384967072263818"); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == 16\n"); return 0; } printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setzero(&max); float_setscientific(&tmp, ".005", NULLTERMINATED); for (i = -1; ++i <= 100;) { float_muli(&x, &tmp, i, EXACT); float_addi(&x, &x, 16, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); erfcasymptotic(&x,100); erfcasymptotic(&x1, 110); _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -99) { printf("exceeding error for test case %d: ", i); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } float_getscientific(buf, 50, &max); printf("max error erfcasymptotic: %s\n", buf); printf("testing convergence:\n"); float_copy(&x, &c2, EXACT); if (!erfcasymptotic(&x, 1)) { printf("convergence failed for 1 digit"); return 0; } float_setasciiz(&max, "0.92"); float_copy(&tmp, &max, EXACT); float_ln(&max, 100); float_sub(&max, &c1, &max, 100); float_mul(&max, &tmp, &max, 100); float_mul(&x1, &c1Div2, &cLn2, 100); for (i = 1; ++i <= 100;) { float_muli(&x, &cLn10, i, 100); float_add(&x, &x, &x1, 100); float_div(&x, &x, &max, 100); float_sqrt(&x, 100); if (!erfcasymptotic(&x, i)) { printf("convergence failed for %d digits", i); return 0; } } printf("convergence ok\n"); float_free(&max); float_free(&tmp); float_free(&x); float_free(&x1); return 1; } static int test_erfcsum() { printf("testing erfcsum IGNORED\n"); return 1; #if 0 /* Keep this already disabled test out of the compiled code. */ floatstruct x, x1, tmp, max; int i, prec; char buf[50]; float_create(&x); float_create(&x1); float_create(&tmp); float_create(&max); printf("testing erfcsum\n"); printf("testing error limit:\n"); /* overall scan for maximum relative error */ float_setscientific(&tmp, ".4", NULLTERMINATED); for (prec = 1; ++prec <= 100;) { float_muli(&tmp, &cLn10, prec, 4); float_setasciiz(&x, "0.3466"); float_add(&tmp, &tmp, &x, 4); float_setasciiz(&x, "0.9967"); float_div(&tmp, &tmp, &x, 4); float_sqrt(&tmp, 4); float_sub(&tmp, &tmp, &c1Div2, 4); float_divi(&tmp, &tmp, 20, 4); float_setzero(&max); for (i = -1; ++i <= 20;) { float_muli(&x, &tmp, i, EXACT); float_add(&x, &x, &c1Div2, EXACT); _sub_ulp(&x, 101); float_copy(&x1, &x, EXACT); if (!erfcsum(&x1, prec+1) || !erfcsum(&x, prec)) { printf("no convergence test case %d, prec %d: ", i, prec); return 0; } _relerror(&x1, &x); if (float_cmp(&x1, &max) > 0) { float_copy(&max, &x1, EXACT); if (float_getexponent(&x1) >= -prec+1) { printf("exceeding error for test case %d, prec %d: ", i, prec); float_getscientific(buf, 50, &max); printf("%s\n", buf); return 0; } } } } float_getscientific(buf, 50, &max); printf("max error erfcsum: %s\n", buf); /* testing the validity of the series evaluation */ printf("verifying result:\n"); float_setasciiz(&tmp, "20"); float_divi(&tmp, &tmp, 7, 110); float_mul(&x, &tmp, &tmp, 110); erfcsum(&x, 100); /* we cannot know the free parameter alpha earlier, as it might be changed during the last series evaluation */ float_mul(&x1, &tmp, &c2Pi, 110); float_div(&x1, &x1, &erfcalpha, 110); _exp(&x1, 110); float_sub(&x1, &c1, &x1, 110); float_div(&x1, &c2, &x1, 110); /* erfc (20/7) */ float_setasciiz(&max,"0.00005331231138832281466765963565935" "9917631684842756273950127577016997393" "623370565496031160355771016945224924345871"); float_sub(&x1, &max, &x1, 110); float_div(&x1, &x1, &tmp, 110); float_div(&x1, &x1, &erfcalpha, 110); float_mul(&x1, &x1, &cPi, 110); float_mul(&max, &tmp, &tmp, 110); float_copy(&tmp, &max, EXACT); _exp(&tmp, 110); float_reciprocal(&max, 110); float_mul(&x1, &x1, &tmp, 110); float_sub(&x1, &x1, &max, 110); float_mul(&x1, &x1, &c1Div2, 110); if (!_cmprelerror(&x1, &x, -99)) { printf("FAILED for x == 20/7\n"); return 0; } float_free(&x); float_free(&x1); float_free(&tmp); float_free(&max); return 1; #endif } static int test_erfc() { printf("testing erfc IGNORED\n"); return 1; #if 0 /* Keep this already disabled test out of the compiled code. */ int prec, i; floatstruct x, x1, step1; floatstruct results[40]; printf("testing erfc\n"); float_create(&x); float_create(&x1); float_create(&step1); for (i = -1; ++i < 40;) float_create(&results[i]); printf("testing special values\n"); float_setzero(&x); float_erfc(&x, 100); if (float_cmp(&x, &c1) != 0) return 0; float_setasciiz(&x, "-1e1000000"); float_erfc(&x, 100); if (float_cmp(&x, &c2) != 0) return 0; printf("verifying results\n"); float_setinteger(&x, 7); float_reciprocal(&x, 110); float_erfc(&x, 100); float_setasciiz(&step1, "0.83989287327126887336609000468499807511227817903" "914160714981066604747285032020973498955714529213539694928510963"); if (!_cmprelerror(&step1, &x, -99)) { printf("FAILED for x == 1/7\n"); return 0; } float_setinteger(&x, 20); float_divi(&x, &x, 7, 110); float_erfc(&x, 100); float_setasciiz(&step1, "0.00005331231138832281466765963565935991763168484275" "6273950127577016997393623370565496031160355771016945224924345871"); if (!_cmprelerror(&step1, &x, -99)) { printf("FAILED for x == 20/7\n"); return 0; } float_setinteger(&x, 93); float_divi(&x, &x, 7, 110); float_erfc(&x, 100); float_setasciiz(&step1, "9.31989223711981967164397263120561981131962901479240254614838756" "73754394641320672442272563375006637085970867544e-79"); if (!_cmprelerror(&step1, &x, -98)) { printf("FAILED for x == 93/7\n"); return 0; } float_setasciiz(&x, "283.6"); float_erfc(&x, 100); float_setasciiz(&step1, "2.787423261346745115871691439975638770369249289940553698308352" "9939376478760274499258439317477920123004576049401e-34933"); if (!_cmprelerror(&step1, &x, -95)) { printf("FAILED for x == 283.6\n"); return 0; } float_setasciiz(&step1, "0.1"); printf("precision test for erfc\n"); for (prec = 0; ++prec <= 100;) { printf("%d\n", prec); /* clear all cached coefficients */ erfcdigits = 0; for (i = 0; ++i < 100;) { float_setinteger(&x, 1); float_setexponent(&x, -i); _sub_ulp(&x, prec); float_copy(&x1, &x, EXACT); float_erfc(&x, prec); float_erfc(&x1, prec+4); if (!_cmprelerror(&x, &x1, -prec)) { printf("evaluation IMPRECISE for 1e-%d\n", i); return 0; } } for (i = 0; ++i <= 39;) { if (i < 10) float_muli(&x, &step1, i, EXACT); else if (i < 30) float_setinteger(&x, i-9); else float_setinteger(&x, (i-25)*(i-25)); _sub_ulp(&x, prec); if(!float_erfc(&x, prec)) { printf("evaluation FAILED for case %d\n", i); return 0; } float_move(&results[i], &x); } for (i = 0; ++i <= 39;) { if (i < 10) float_muli(&x, &step1, i, EXACT); else if (i < 30) float_setinteger(&x, i-9); else float_setinteger(&x, (i-25)*(i-25)); _sub_ulp(&x, prec); if(!float_erfc(&x, prec+4)) { printf("evaluation FAILED for case %d\n", i); return 0; } if (!_cmprelerror(&x, &results[i], -prec)) { printf("evaluation IMPRECISE for case %d\n", i); return 0; } } } float_free(&x); float_free(&step1); float_free(&x1); for (i = -1; ++i < 40;) float_free(&results[i]); return 1; #endif } static int test_erf() { int prec, i; floatstruct x, x1, step; printf("testing erf\n"); float_create(&x); float_create(&step); float_create(&x1); printf("verifying special x"); float_setzero(&x); if (!float_erf(&x,100) || !float_iszero(&x)) return 0; float_setasciiz(&x, "1e1000000"); if (!float_erf(&x, 100) || float_cmp(&x, &c1) != 0) return 0; float_copy(&x1, &c1, EXACT); float_copy(&x, &cMinus1, EXACT); if (!float_erf(&x, 100) || !float_erf(&x1, 100)) return 0; float_neg(&x); if (float_cmp(&x, &x1) != 0) return 0; float_setasciiz(&step, "0.05"); printf("precision test for erf\n"); for (prec = 0; ++prec <= 100;) { printf("%d\n", prec); for (i = 0; ++i <= 39;) { if (i < 10) { float_copy(&x, &c1, EXACT); float_setexponent(&x, -3-i*i); } else if (i < 30) float_muli(&x, &step, i-9, EXACT); else float_setinteger(&x, 2 + (i-30)*(i-30)); _sub_ulp(&x, prec); float_copy(&x1, &x, EXACT); if(!float_erf(&x, prec) || !float_erf(&x1, prec+4)) { printf("evaluation FAILED for case %d\n", i); return 0; } if (!_cmprelerror(&x, &x1, -prec)) { printf("evaluation IMPRECISE for case %d\n", i); return 0; } } } float_free(&x); float_free(&step); float_free(&x1); return 1; } static int testfailed(char* msg) { fprintf(stderr, "%s FAILED\n", msg); return 1; } #endif /* _FLOATNUMTEST */ int main(void) { #ifdef _FLOATNUMTEST int scalesave; printf("\ntest of floatlong\n"); floatmath_init(); float_stdconvert(); maxdigits = 150; if(!test_longadd()) return testfailed("_longadd"); if(!test_longmul()) return testfailed("_longmul"); if(!test_longshr()) return testfailed("_longshr"); if(!test_checkadd()) return testfailed("_checkadd"); if(!test_checkmul()) return testfailed("_checkmul"); if(!test_longarrayadd()) return testfailed("_longarrayadd"); if(!test_longarraymul()) return testfailed("_longarrayadd"); printf("\ntest of setting/modifying values \n"); scalesave = maxdigits; maxdigits = 15; if(!test_create()) return testfailed("float_create"); if(!test_isnan()) return testfailed("float_isnan"); if(!test_iszero()) return testfailed("float_iszero"); if(!test_setnan()) return testfailed("float_setnan"); if(!test_setzero()) return testfailed("float_setzero"); if(!test_setsignificand()) return testfailed("float_setsignificand"); if(!test_getsignificand()) return testfailed("float_getsignificand"); if(!test_setexponent()) return testfailed("float_setexponent"); if(!test_getexponent()) return testfailed("float_getexponent"); if(!test_setsign()) return testfailed("float_setsign"); if(!test_getsign()) return testfailed("float_getsign"); if(!test_getlength()) return testfailed("float_getlength"); if(!test_getdigit()) return testfailed("float_getdigit"); if(!test_getscientific()) return testfailed("float_getscientific"); if(!test_setscientific()) return testfailed("float_setscientific"); if(!test_setinteger()) return testfailed("float_setinteger"); printf("\ntest of basic arithmetic \n"); if(!test_neg()) return testfailed("float_changesign"); if(!test_abs()) return testfailed("float_abs"); if(!test_cmp()) return testfailed("float_cmp"); if(!test_copy()) return testfailed("float_copy"); if(!test_move()) return testfailed("float_move"); if(!test_round()) return testfailed("float_round"); if(!test_add()) return testfailed("float_add"); if(!test_sub()) return testfailed("float_sub"); if(!test_mul()) return testfailed("float_mul"); if(!test_div()) return testfailed("float_div"); if(!test_sqrt()) return testfailed("float_sqrt"); if(!test_int()) return testfailed("float_int"); if(!test_frac()) return testfailed("float_frac"); if(!test_divmod()) return testfailed("float_divmod"); printf("\nall floatnum tests PASSED\n\n"); maxdigits = scalesave; if(!test_floatnum2longint()) return testfailed("_floatnum2longint"); if(!test_longint2floatnum()) return testfailed("_longint2floatnum"); if(!test_out()) return testfailed("float_out"); if(!test_in()) return testfailed("float_in"); if(!test_floatnum2logic()) return testfailed("_floatnum2logic"); if(!test_logic2floatnum()) return testfailed("_logic2floatnum"); if(!test_not()) return testfailed("float_not"); if(!test_and()) return testfailed("float_and"); if(!test_or()) return testfailed("float_or"); if(!test_xor()) return testfailed("float_xor"); if(!test_shl()) return testfailed("float_shl"); if(!test_shr()) return testfailed("float_shr"); if(!test_raisei()) return testfailed("_raisei"); if(!test_raiseposi()) return testfailed("_raiseposi"); if(!test_coshminus1near0()) return testfailed("coshminus1near0"); if(!test_artanhnear0()) return testfailed("artanhnear0"); if(!test_cosminus1near0()) return testfailed("cosminus1near0"); if(!test_arctannear0()) return testfailed("arctannear0"); if(!test_lnxplus1near0()) return testfailed("_lnxplus1near0"); if(!test_lnreduce()) return testfailed("_lnreduce"); if(!test_lnxplus1lt1()) return testfailed("_lnxplus1lt1"); if(!test_ln()) return testfailed("_ln"); if(!test_lnxplus1()) return testfailed("_lnxplus1"); if(!test_artanh1minusx()) return testfailed("_artanh1minusx"); if(!test_artanhlt0_5()) return testfailed("_artanhlt0_5"); if(!test_arsinh()) return testfailed("_arsinh"); if(!test_arcoshxplus1()) return testfailed("_arcoshxplus1"); if(!test_coshminus1lt1()) return testfailed("_coshminus1lt1"); if(!test_sinhlt1()) return testfailed("_sinhlt1"); if(!test_expminus1lt1()) return testfailed("_expminus1lt1"); if(!test_expltln10()) return testfailed("_expltln10"); if(!test_exp()) return testfailed("_exp"); if(!test_expminus1()) return testfailed("_expminus1"); if(!test_coshminus1()) return testfailed("_coshminus1"); if(!test_tanhlt0_5()) return testfailed("_tanhlt0_5"); if(!test_tanhminus1gt0()) return testfailed("_tanhminus1gt0"); if(!test_tanh_range()) return testfailed("float_tanh range"); if(!test_arctanlt1()) return testfailed("_arctanlt1"); if(!test_arctan()) return testfailed("_arctan"); if(!test_arccosxplus1lt0_5()) return testfailed("_arccosxplus1lt0_5"); if(!test_arcsinlt0_5()) return testfailed("_arcsinlt0_5"); if(!test_arccos()) return testfailed("_arccos"); if(!test_arcsin()) return testfailed("_arcsin"); if(!test_cosminus1ltPiDiv4()) return testfailed("_cosminus1ltPiDiv4"); if(!test_sinltPiDiv4()) return testfailed("_sinltPiDiv4"); if(!test_tanltPiDiv4()) return testfailed("_tanltPiDiv4"); if(!test_cos()) return testfailed("_cos"); if(!test_sin()) return testfailed("_sin"); if(!test_tan()) return testfailed("_tan"); if(!test_binetasymptotic()) return testfailed("lngammaseries"); if(!test_pochhammer()) return testfailed("_pochhammer"); if(!test_lngamma()) return testfailed("_lngamma"); if(!test_gamma()) return testfailed("_gamma"); if(!test_gammaint()) return testfailed("_gammaint"); if(!test_gamma0_5()) return testfailed("_gamma0_5"); if(!test_erfnear0()) return testfailed("erfnear0"); if(!test_erfcasymptotic()) return testfailed("erfcasymptotic"); if(!test_erfcsum()) return testfailed("erfcsum"); if(!test_erfc()) return testfailed("erfc"); if(!test_erf()) return testfailed("erf"); printf("\nall tests PASSED\n"); #endif /* _FLOATNUMTEST */ return 0; } heldercorreia-speedcrunch-e7ca37f/src/tests/testfocusui.cpp000066400000000000000000002425771526573132500243700ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" using namespace MainWindowTestHelpers; class TestFocusUi : public QObject { Q_OBJECT private slots: void initTestCase(); void init() { UiTestFixture::resetSettings(); } void destroying_focused_window_handles_focus_change_safely_data(); void destroying_focused_window_handles_focus_change_safely(); void main_window_applies_primary_role_to_active_editor_and_dock_selection(); void current_result_tooltip_stays_hidden_after_escape_and_arrow_caret_move(); void current_result_tooltip_stays_hidden_after_escape_and_mouse_caret_move(); void current_result_tooltip_hides_when_dragging_splitters(); void f6_cycles_focus_between_editor_and_visible_dock_controls_data(); void f6_cycles_focus_between_editor_and_visible_dock_controls(); void f6_cycles_focus_with_another_main_window_visible(); void f6_cycles_focus_with_another_main_window_visible_data(); void dock_search_focus_suppresses_editor_primary_outline_across_panes(); void constants_dock_activation_returns_to_active_editor_data(); void constants_dock_activation_returns_to_active_editor(); void constant_popup_inserts_into_owning_pane(); void constant_search_takes_primary_focus_from_editor_data(); void constant_search_takes_primary_focus_from_editor(); void constant_search_paints_editor_without_focus_ring(); void dock_selection_inserts_into_active_session_pane_after_focus_transfer(); void clicking_tab_activates_own_pane_in_nested_split_layout(); void active_pane_survives_window_reactivation_focus_replay(); void extra_window_activation_restores_own_active_tab_indicator(); void startup_focuses_editor_with_visible_dock_input_data(); void startup_focuses_editor_with_visible_dock_input(); void focused_dock_search_survives_window_reactivation_focus_replay(); void focusing_loaded_pane_preserves_its_current_scroll_position(); void clipboard_actions_follow_active_pane_data(); void clipboard_actions_follow_active_pane(); void edit_commands_follow_active_editor_data(); void edit_commands_follow_active_editor(); void copy_shortcut_preserves_display_selection_in_other_pane(); void escape_clears_only_the_focused_editor_data(); void escape_clears_only_the_focused_editor(); void escape_dismisses_completion_and_preview_before_clearing(); void escape_still_cancels_history_edit_data(); void escape_still_cancels_history_edit(); }; void TestFocusUi::destroying_focused_window_handles_focus_change_safely_data() { QTest::addColumn("bitfield"); QTest::addColumn("floating"); QTest::newRow("editor") << false << false; QTest::newRow("attached-bitfield") << true << false; QTest::newRow("floating-bitfield") << true << true; } void TestFocusUi::destroying_focused_window_handles_focus_change_safely() { QFETCH(bool, bitfield); QFETCH(bool, floating); Settings::instance()->bitfieldVisible = bitfield; QSignalSpy focusChanges(qApp, &QApplication::focusChanged); { MainWindow window; window.show(); if (bitfield) { auto* dock = window.findChild(QStringLiteral("BitfieldDock")); QVERIFY(dock != nullptr); dock->setFloating(floating); dock->show(); QTRY_VERIFY(dock->isVisible()); } window.activateWindow(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); QVERIFY(editor != nullptr); editor->setFocus(); QTRY_VERIFY(editor->hasFocus()); focusChanges.clear(); } QVERIFY(!focusChanges.isEmpty()); QCOMPARE(QApplication::focusWidget(), nullptr); } void TestFocusUi::constant_search_paints_editor_without_focus_ring() { MainWindowStateGuard guard; guard.settings->editorDisplayStyle = Settings::EditorDisplayModern; guard.settings->autoCalc = false; guard.settings->constantsDockVisible = true; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString(QJsonObject{ {QStringLiteral("background"), QStringLiteral("#454257")}, {QStringLiteral("primary"), QStringLiteral("#e7a840")} }); MainWindow window; window.resize(1000, 600); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); auto* editor = window.findChild(); auto* dock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(editor && dock); editor->setText(QString()); dock->show(); dock->raise(); auto* dockSearch = dock->findChild(); QVERIFY(dockSearch); dockSearch->setFocus(); QTRY_VERIFY(dockSearch->hasFocus()); QTest::qWait(150); const QRect editorRect = QRect(editor->mapTo(&window, QPoint()), editor->size()) .adjusted(-2, -2, 2, 2).intersected(window.rect()); const QImage unfocused = window.grab(editorRect).toImage(); QTest::mouseClick(editor->viewport(), Qt::LeftButton); QTRY_VERIFY(editor->hasFocus()); QTRY_VERIFY(editorHasPrimaryOutline(editor, QColor(QStringLiteral("#e7a840")))); QVERIFY(window.grab(editorRect).toImage() != unfocused); QTest::keyClick(editor, Qt::Key_Space, Qt::ControlModifier); QPointer popup = QApplication::activePopupWidget(); QVERIFY(popup); auto* search = popup->findChild(QStringLiteral("constantCompletionSearch")); QVERIFY(search); QTRY_VERIFY(search->hasFocus()); QTest::qWait(400); QCOMPARE(window.grab(editorRect).toImage(), unfocused); QTest::keyClick(search, Qt::Key_Escape); QTRY_VERIFY(editor->hasFocus()); QVERIFY(window.grab(editorRect).toImage() != unfocused); } void TestFocusUi::constant_search_takes_primary_focus_from_editor_data() { QTest::addColumn("classic"); QTest::addColumn("closeKey"); for (bool classic : {false, true}) { for (Qt::Key key : {Qt::Key_Escape, Qt::Key_Return, Qt::Key_Tab}) { const QString name = QStringLiteral("%1-%2").arg(classic ? "classic" : "modern").arg(key); QTest::newRow(qPrintable(name)) << classic << int(key); } } } void TestFocusUi::constant_search_takes_primary_focus_from_editor() { QFETCH(bool, classic); QFETCH(int, closeKey); MainWindowStateGuard guard; guard.settings->editorDisplayStyle = classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; guard.settings->autoCalc = false; guard.settings->colorScheme = QStringLiteral("Custom"); const QColor primary(QStringLiteral("#e7a840")); guard.settings->customColorSchemeJson = themeJsonString(QJsonObject{ {QStringLiteral("background"), QStringLiteral("#454257")}, {QStringLiteral("primary"), primary.name()} }); const auto hasPrimaryOutline = [classic, primary](const Editor* editor) { return editor->styleSheet().contains(QStringLiteral("%1: %2px solid %3") .arg(classic ? "border-top" : "border").arg(UiConfig::OutlineStrokeWidth).arg(primary.name())); }; MainWindow window; MainWindow otherWindow; QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); otherWindow.show(); window.show(); window.activateWindow(); QVERIFY(QTest::qWaitForWindowExposed(&window)); const auto editors = window.findChildren(); QCOMPARE(editors.size(), 2); Editor* target = editors.first(); target->setAutoCompletionEnabled(false); target->setText(QStringLiteral("12+34")); QTest::mouseClick(target->viewport(), Qt::LeftButton); QTRY_VERIFY(hasPrimaryOutline(target)); QTest::keyClick(target, Qt::Key_Space, Qt::ControlModifier); QPointer popup = QApplication::activePopupWidget(); QVERIFY(popup); auto* search = dynamic_cast(popup->findChild(QStringLiteral("constantCompletionSearch"))); QVERIFY(search); QTRY_VERIFY(search->hasFocus()); QCOMPARE(search->cursorColor(), primary); QVERIFY(search->styleSheet().contains(QStringLiteral("QLineEdit:focus { border: %1px solid %2") .arg(UiConfig::OutlineStrokeWidth).arg(primary.name()))); for (Editor* editor : editors + otherWindow.findChildren()) QVERIFY(!hasPrimaryOutline(editor)); search->setText(QStringLiteral("Euler's number")); QTest::keyClick(search, Qt::Key_Down); window.colorSchemeChanged(); QTRY_VERIFY(search->hasFocus()); QVERIFY(!hasPrimaryOutline(target)); QTest::keyClick(search, static_cast(closeKey)); QVERIFY(!popup || !popup->isVisible()); QTRY_VERIFY(target->hasFocus()); QTRY_VERIFY(hasPrimaryOutline(target)); QCOMPARE(target->text(), closeKey == Qt::Key_Escape ? QStringLiteral("12+34") : QStringLiteral("12+34e")); QVERIFY(editors.last()->text().isEmpty()); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); } void TestFocusUi::constants_dock_activation_returns_to_active_editor_data() { QTest::addColumn("mouse"); QTest::addColumn("floating"); QTest::newRow("enter-docked") << false << false; QTest::newRow("double-click-docked") << true << false; QTest::newRow("enter-floating") << false << true; QTest::newRow("double-click-floating") << true << true; } void TestFocusUi::constants_dock_activation_returns_to_active_editor() { QFETCH(bool, mouse); QFETCH(bool, floating); Settings::instance()->constantsDockVisible = true; MainWindow window; MainWindow otherWindow; window.resize(950, 650); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); otherWindow.show(); window.show(); window.activateWindow(); QVERIFY(QTest::qWaitForWindowExposed(&window)); auto editors = window.findChildren(); QCOMPARE(editors.size(), 2); Editor* target = editors.last(); Editor* other = editors.first(); for (Editor* editor : editors) { editor->setAutoCompletionEnabled(false); editor->setText(QString()); } QTest::mouseClick(target->viewport(), Qt::LeftButton); QTRY_VERIFY(target->hasFocus()); auto* constants = window.findChild(); auto* dock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constants && dock); auto* list = constants->findChild(); auto* search = constants->findChild(); auto* domain = constants->findChild(); QVERIFY(list && search && domain); constants->restoreState(domain->itemText(0), QString(), QStringLiteral("Euler's number")); dock->show(); dock->raise(); dock->setFloating(floating); QCoreApplication::processEvents(); QCOMPARE(list->topLevelItemCount(), 1); auto* otherEditor = otherWindow.findChild(); QVERIFY(otherEditor); const QString otherText = otherEditor->text(); const QPoint row = list->visualItemRect(list->topLevelItem(0)).center(); if (mouse) { QTest::mouseClick(list->viewport(), Qt::LeftButton, Qt::NoModifier, row); QVERIFY(target->text().isEmpty()); QTest::mouseDClick(list->viewport(), Qt::LeftButton, Qt::NoModifier, row); } else { // Leave the dock click's delayed focus recovery pending during insertion. QTest::mouseClick(search, Qt::LeftButton); QTest::keyClick(search, Qt::Key_Down); QVERIFY(search->hasFocus()); QTest::keyClick(search, Qt::Key_Return); } QTRY_COMPARE(target->text(), QStringLiteral("e")); QVERIFY(other->text().isEmpty()); QCOMPARE(otherEditor->text(), otherText); QTRY_VERIFY(target->hasFocus()); QTest::qWait(300); QVERIFY(target->hasFocus()); QTest::keyClicks(target, "+1"); QCOMPARE(target->text(), QStringLiteral("e + 1")); } void TestFocusUi::constant_popup_inserts_into_owning_pane() { MainWindow window; MainWindow otherWindow; QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); otherWindow.show(); window.show(); window.activateWindow(); QVERIFY(QTest::qWaitForWindowExposed(&window)); const auto editors = window.findChildren(); QCOMPARE(editors.size(), 2); for (Editor* editor : editors) { editor->setAutoCompletionEnabled(false); editor->setText(QString()); } Editor* target = editors.first(); QTest::mouseClick(target->viewport(), Qt::LeftButton); QTest::keyClick(target, Qt::Key_Space, Qt::ControlModifier); QPointer popup = QApplication::activePopupWidget(); QVERIFY(popup); auto* search = popup->findChild(QStringLiteral("constantCompletionSearch")); auto* list = popup->findChild(); QVERIFY(search && list); QTest::qWait(400); QVERIFY(search->hasFocus()); search->setText(QStringLiteral("Euler's number")); QCOMPARE(list->topLevelItemCount(), 1); QTest::mouseClick(list->viewport(), Qt::LeftButton, Qt::NoModifier, list->visualItemRect(list->currentItem()).center()); QTRY_COMPARE(target->text(), QStringLiteral("e")); QVERIFY(editors.last()->text().isEmpty()); QTRY_VERIFY(target->hasFocus()); QTest::qWait(300); QVERIFY(target->hasFocus()); QVERIFY(otherWindow.findChild()->text().isEmpty()); } void TestFocusUi::escape_clears_only_the_focused_editor_data() { QTest::addColumn("enabled"); QTest::newRow("default-off") << false; QTest::newRow("enabled") << true; } void TestFocusUi::escape_clears_only_the_focused_editor() { QFETCH(bool, enabled); Settings::instance()->autoCalc = false; Settings::instance()->escapeClearsEditor = enabled; MainWindow first; MainWindow second; QVERIFY(QMetaObject::invokeMethod(&first, "splitActivePaneRight", Qt::DirectConnection)); first.show(); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&first)); QVERIFY(QTest::qWaitForWindowExposed(&second)); const QList editors = first.findChildren() + second.findChildren(); QVERIFY(editors.size() >= 3); for (Editor* target : editors) { for (Editor* editor : editors) { editor->setAutoCompletionEnabled(false); editor->setText(QStringLiteral("123\n456")); } target->window()->activateWindow(); target->setFocus(); QTRY_VERIFY(target->hasFocus()); QTest::keyClick(target, Qt::Key_Escape); for (Editor* editor : editors) { QCOMPARE(editor->text(), enabled && editor == target ? QString() : QStringLiteral("123\n456")); } QVERIFY(target->hasFocus()); QTest::keyClick(target, Qt::Key_Escape); QCOMPARE(target->text(), enabled ? QString() : QStringLiteral("123\n456")); } first.activateWindow(); QLineEdit search(&first); search.show(); search.setFocus(); QTRY_VERIFY(search.hasFocus()); for (Editor* editor : editors) editor->setText(QStringLiteral("789")); QTest::keyClick(&search, Qt::Key_Escape); for (Editor* editor : editors) QCOMPARE(editor->text(), QStringLiteral("789")); } void TestFocusUi::escape_dismisses_completion_and_preview_before_clearing() { Settings::instance()->escapeClearsEditor = true; Settings::instance()->autoCalc = false; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); QVERIFY(editor); editor->setFocus(); QTRY_VERIFY(editor->hasFocus()); editor->setText(QStringLiteral("co")); editor->setCursorPosition(editor->text().size()); QVERIFY(QMetaObject::invokeMethod(editor, "triggerAutoComplete", Qt::DirectConnection)); auto completionPopup = []() -> QTreeWidget* { for (QWidget* widget : QApplication::topLevelWidgets()) { if (auto* tree = qobject_cast(widget)) { if (tree->isVisible()) return tree; } } return nullptr; }; QTRY_VERIFY(completionPopup()); QTreeWidget* popup = completionPopup(); QTest::keyClick(popup, Qt::Key_Escape); QVERIFY(!popup->isVisible()); QCOMPARE(editor->text(), QStringLiteral("co")); QTRY_VERIFY(editor->hasFocus()); QTest::keyClick(editor, Qt::Key_Escape); QVERIFY(editor->text().isEmpty()); editor->setAutoCompletionEnabled(false); editor->setAutoCalcEnabled(true); editor->setText(QStringLiteral("1+24")); editor->refreshAutoCalc(); QTRY_VERIFY(visibleResultPreviewText(window).contains(QStringLiteral("Current result:"))); QTest::keyClick(editor, Qt::Key_Escape); QTRY_VERIFY(visibleResultPreviewText(window).isEmpty()); QCOMPARE(editor->text(), QStringLiteral("1+24")); QTest::keyClick(editor, Qt::Key_Escape); QVERIFY(editor->text().isEmpty()); } void TestFocusUi::escape_still_cancels_history_edit_data() { escape_clears_only_the_focused_editor_data(); } void TestFocusUi::escape_still_cancels_history_edit() { QFETCH(bool, enabled); Settings::instance()->escapeClearsEditor = enabled; Settings::instance()->autoCalc = false; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); ResultDisplay* display = window.findChild(); QVERIFY(editor); QVERIFY(display); editor->setAutoCompletionEnabled(false); editor->setFocus(); editor->setText(QStringLiteral("2+3")); QTest::keyClick(editor, Qt::Key_Return); const int count = display->session()->historySize(); QVERIFY(count > 0); QVERIFY(QMetaObject::invokeMethod(&window, "startHistoryEntryEdit", Qt::DirectConnection, Q_ARG(int, count - 1))); editor->setText(QStringLiteral("6+7")); QTest::keyClick(editor, Qt::Key_Escape); QCOMPARE(editor->text(), QStringLiteral("6+7")); QTest::keyClick(editor, Qt::Key_Escape); QVERIFY(editor->text().isEmpty()); QCOMPARE(display->session()->historySize(), count); editor->setText(QStringLiteral("8+9")); QTest::keyClick(editor, Qt::Key_Return); QCOMPARE(display->session()->historySize(), count + 1); } void TestFocusUi::initTestCase() { // Fail before a file-operation test can open an unhandled error dialog. for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) { QVERIFY2(QDir().mkpath(path), qPrintable(QStringLiteral("Cannot create test storage at %1").arg(path))); QTemporaryFile probe(QDir(path).filePath(QStringLiteral("storage-probe-XXXXXX"))); QVERIFY2(probe.open(), qPrintable(QStringLiteral("Cannot write test storage at %1: %2") .arg(path, probe.errorString()))); } } void TestFocusUi::main_window_applies_primary_role_to_active_editor_and_dock_selection() { Settings* settings = Settings::instance(); struct SettingsGuard { Settings* settings; QString oldColorScheme; QString oldCustomColorSchemeJson; bool oldConstantsDockVisible; bool oldHasNumberFormatStyleSetting; QByteArray oldSkipUpdateCheck; bool hadSkipUpdateCheck; ~SettingsGuard() { settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; settings->constantsDockVisible = oldConstantsDockVisible; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } } guard { settings, settings->colorScheme, settings->customColorSchemeJson, settings->constantsDockVisible, settings->hasNumberFormatStyleSetting, qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK") }; const QColor base(QStringLiteral("#1f3229")); const QColor generatedPrimary = generatePrimaryFromBackground(base); const QColor configuredPrimary(QStringLiteral("#d94f8c")); const QVector shades = generateOklchShades(base, 6, ThemePolarity::Dark); const QVector foregrounds = aaForegroundsForBackgrounds(shades); QVERIFY(generatedPrimary.isValid()); QVERIFY(configuredPrimary.isValid()); QVERIFY(generatedPrimary.name() != configuredPrimary.name()); qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{ {QStringLiteral("background"), base.name()}, {QStringLiteral("primary"), configuredPrimary.name()} }); settings->constantsDockVisible = true; settings->hasNumberFormatStyleSetting = true; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); QVERIFY(editor != nullptr); QCOMPARE(editor->palette().color(QPalette::Text).name(), configuredPrimary.name()); QVERIFY(editor->palette().color(QPalette::Base).name() != configuredPrimary.name()); QTRY_VERIFY(editor->styleSheet().contains(QStringLiteral("color: %1;").arg(configuredPrimary.name()))); QTRY_VERIFY(editorHasPrimaryOutline(editor, configuredPrimary)); QVERIFY(QMetaObject::invokeMethod(&window, "showNewSessionDialog", Qt::DirectConnection)); QCoreApplication::processEvents(); QTRY_VERIFY(editorHasPrimaryOutline(editor, configuredPrimary)); QDockWidget* constantsDock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constantsDock != nullptr); QTreeWidget* table = constantsDock->findChild(); QVERIFY(table != nullptr); QCOMPARE(table->property("dockListActiveSelectionBackground").value().name(), configuredPrimary.name()); QCOMPARE(table->property("dockListActiveSelectionForeground").value().name(), aaForegroundForBackground(configuredPrimary).name()); QCOMPARE(table->property("dockListInactiveSelectionBackground").value().name(), shades.at(4).name()); QCOMPARE(table->property("dockListInactiveSelectionForeground").value().name(), foregrounds.at(4).name()); settings->customColorSchemeJson = themeJsonString(QJsonObject{ {QStringLiteral("background"), base.name()} }); window.colorSchemeChanged(); QCoreApplication::processEvents(); QCOMPARE(editor->palette().color(QPalette::Text).name(), generatedPrimary.name()); QVERIFY(editor->styleSheet().contains(QStringLiteral("color: %1;").arg(generatedPrimary.name()))); QCOMPARE(table->property("dockListActiveSelectionBackground").value().name(), generatedPrimary.name()); QCOMPARE(table->property("dockListInactiveSelectionBackground").value().name(), shades.at(4).name()); } void TestFocusUi::current_result_tooltip_stays_hidden_after_escape_and_arrow_caret_move() { MainWindowStateGuard guard; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); QVERIFY(editor != nullptr); editor->setFocus(); editor->setText(QStringLiteral("1+24")); editor->setCursorPosition(editor->text().size()); editor->refreshAutoCalc(); QTRY_VERIFY(visibleResultPreviewText(window).contains(QStringLiteral("Current result:"))); QTest::keyClick(editor, Qt::Key_Escape); QTRY_VERIFY(visibleResultPreviewText(window).isEmpty()); QTest::keyClick(editor, Qt::Key_Left); QTRY_VERIFY2(visibleResultPreviewText(window).isEmpty(), qPrintable(QStringLiteral("Caret movement should not reopen the result tooltip, got: %1") .arg(visibleResultPreviewText(window)))); } void TestFocusUi::current_result_tooltip_stays_hidden_after_escape_and_mouse_caret_move() { MainWindowStateGuard guard; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); QVERIFY(editor != nullptr); editor->setFocus(); editor->setText(QStringLiteral("1+24")); editor->setCursorPosition(editor->text().size()); editor->refreshAutoCalc(); QTRY_VERIFY(visibleResultPreviewText(window).contains(QStringLiteral("Current result:"))); QTest::keyClick(editor, Qt::Key_Escape); QTRY_VERIFY(visibleResultPreviewText(window).isEmpty()); QTextCursor cursor = editor->textCursor(); cursor.setPosition(1); const QPoint clickPosition = editor->cursorRect(cursor).center(); QTest::mouseClick(editor->viewport(), Qt::LeftButton, Qt::NoModifier, clickPosition); QTRY_VERIFY2(visibleResultPreviewText(window).isEmpty(), qPrintable(QStringLiteral("Mouse caret movement should not reopen the result tooltip, got: %1") .arg(visibleResultPreviewText(window)))); } void TestFocusUi::current_result_tooltip_hides_when_dragging_splitters() { MainWindowStateGuard guard; MainWindow window; window.resize(900, 500); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QCoreApplication::processEvents(); Editor* editor = window.findChild(); QVERIFY(editor != nullptr); editor->setFocus(); editor->setText(QStringLiteral("1+24")); editor->setCursorPosition(editor->text().size()); editor->refreshAutoCalc(); QTRY_VERIFY(visibleResultPreviewText(window).contains(QStringLiteral("Current result:"))); QSplitter* splitContainer = window.findChild(QStringLiteral("MainSplitContainer")); QVERIFY(splitContainer != nullptr); QVERIFY(splitContainer->count() > 1); QSplitterHandle* handle = splitContainer->handle(1); QVERIFY(handle != nullptr); const QPoint handleCenter = handle->rect().center(); QTest::mousePress(handle, Qt::LeftButton, Qt::NoModifier, handleCenter); QTest::mouseMove(handle, handleCenter + QPoint(8, 0)); QTest::mouseRelease(handle, Qt::LeftButton, Qt::NoModifier, handleCenter + QPoint(8, 0)); QTRY_VERIFY(visibleResultPreviewText(window).isEmpty()); editor->setText(QStringLiteral("1+25")); editor->setCursorPosition(editor->text().size()); editor->refreshAutoCalc(); QTRY_VERIFY(visibleResultPreviewText(window).contains(QStringLiteral("Current result:"))); window.setCursor(Qt::SplitHCursor); QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, window.rect().center()); QTest::mouseMove(&window, window.rect().center() + QPoint(8, 0)); QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, window.rect().center() + QPoint(8, 0)); window.unsetCursor(); QTRY_VERIFY(visibleResultPreviewText(window).isEmpty()); } void TestFocusUi::f6_cycles_focus_between_editor_and_visible_dock_controls_data() { QTest::addColumn("savedDockLayout"); QTest::newRow("default-layout") << false; QTest::newRow("saved-visible-dock") << true; } void TestFocusUi::f6_cycles_focus_between_editor_and_visible_dock_controls() { QFETCH(bool, savedDockLayout); MainWindowStateGuard guard; Settings* settings = guard.settings; if (savedDockLayout) { settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->constantsDockVisible = true; MainWindow previousWindow(false); settings->windowState = previousWindow.saveState(1); } // Saved layouts can re-show docks after the visibility settings below. settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->constantsDockVisible = false; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->keypadMode = Settings::KeypadModeDisabled; settings->keypadVisible = false; settings->hasNumberFormatStyleSetting = true; MainWindow window; window.resize(900, 500); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Editor* editor = window.findChild(); QVERIFY(editor != nullptr); editor->setFocus(); QTRY_VERIFY(focusIsWithin(editor)); QTest::keyClick(editor, Qt::Key_F6); QCoreApplication::processEvents(); QVERIFY(focusIsWithin(editor)); QVERIFY(QMetaObject::invokeMethod(&window, "setConstantsDockVisible", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(bool, false))); QCoreApplication::processEvents(); QDockWidget* constantsDock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constantsDock != nullptr); QLineEdit* searchBox = constantsDock->findChild(); QTreeWidget* table = constantsDock->findChild(); QVERIFY(searchBox != nullptr); QVERIFY(table != nullptr); QVERIFY(searchBox->isVisible()); QVERIFY(table->isVisible()); // F6 is explicit focus intent and must supersede delayed focus restoration // scheduled by a recent window activation. QEvent windowActivate(QEvent::WindowActivate); QCoreApplication::sendEvent(&window, &windowActivate); QCoreApplication::processEvents(); editor->setFocus(); QTRY_VERIFY(focusIsWithin(editor)); QTest::keyClick(editor, Qt::Key_F6); QCoreApplication::processEvents(); QTRY_VERIFY(focusIsWithin(searchBox)); QTest::keyClick(searchBox, Qt::Key_F6); QCoreApplication::processEvents(); QTRY_VERIFY(focusIsWithin(table)); QTest::qWait(175); QVERIFY(focusIsWithin(table)); QTest::keyClick(table, Qt::Key_F6); QCoreApplication::processEvents(); QTRY_VERIFY(focusIsWithin(editor)); QVERIFY(QMetaObject::invokeMethod(&window, "cycleFocusBackward", Qt::DirectConnection)); QCoreApplication::processEvents(); QTRY_VERIFY(focusIsWithin(table)); } void TestFocusUi::f6_cycles_focus_with_another_main_window_visible() { QFETCH(bool, floatingDock); MainWindowStateGuard guard; Settings* settings = guard.settings; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->constantsDockVisible = true; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->keypadMode = Settings::KeypadModeDisabled; settings->keypadVisible = false; settings->hasNumberFormatStyleSetting = true; MainWindow firstWindow(false); MainWindow secondWindow(false); firstWindow.show(); secondWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&firstWindow)); QVERIFY(QTest::qWaitForWindowExposed(&secondWindow)); for (MainWindow* window : {&firstWindow, &secondWindow}) { window->activateWindow(); Editor* editor = window->findChild(); QDockWidget* dock = window->findChild(QStringLiteral("ConstantsDock")); QVERIFY(editor != nullptr); QVERIFY(dock != nullptr); dock->setFloating(floatingDock); window->activateWindow(); QLineEdit* searchBox = dock->findChild(); QTreeWidget* table = dock->findChild(); QVERIFY(searchBox != nullptr); QVERIFY(table != nullptr); editor->setFocus(); QTRY_VERIFY(focusIsWithin(editor)); QTest::keyClick(editor, Qt::Key_F6); QTRY_VERIFY(focusIsWithin(searchBox)); if (floatingDock) dock->activateWindow(); QTest::keyClick(searchBox, Qt::Key_F6); QTRY_VERIFY(focusIsWithin(table)); QTest::keyClick(table, Qt::Key_F6); QTRY_VERIFY(focusIsWithin(editor)); QTest::keyClick(editor, Qt::Key_F6, Qt::ShiftModifier); QTRY_VERIFY(focusIsWithin(table)); QTest::keyClick(table, Qt::Key_F6, Qt::ShiftModifier); QTRY_VERIFY(focusIsWithin(searchBox)); QTest::keyClick(searchBox, Qt::Key_F6, Qt::ShiftModifier); QTRY_VERIFY(focusIsWithin(editor)); } } void TestFocusUi::f6_cycles_focus_with_another_main_window_visible_data() { QTest::addColumn("floatingDock"); QTest::newRow("docked") << false; QTest::newRow("floating") << true; } void TestFocusUi::dock_search_focus_suppresses_editor_primary_outline_across_panes() { Settings* settings = Settings::instance(); struct SettingsGuard { Settings* settings; QString oldColorScheme; QString oldCustomColorSchemeJson; QString oldSessionLayoutJson; bool oldConstantsDockVisible; bool oldFunctionsDockVisible; bool oldHistoryDockVisible; bool oldKeypadVisible; bool oldFormulaBookDockVisible; bool oldVariablesDockVisible; bool oldUserFunctionsDockVisible; bool oldUserUnitsDockVisible; bool oldBitfieldVisible; bool oldWindowPositionSave; bool oldHasNumberFormatStyleSetting; QByteArray oldSkipUpdateCheck; bool hadSkipUpdateCheck; ~SettingsGuard() { settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; settings->sessionLayoutJson = oldSessionLayoutJson; settings->constantsDockVisible = oldConstantsDockVisible; settings->functionsDockVisible = oldFunctionsDockVisible; settings->historyDockVisible = oldHistoryDockVisible; settings->keypadVisible = oldKeypadVisible; settings->formulaBookDockVisible = oldFormulaBookDockVisible; settings->variablesDockVisible = oldVariablesDockVisible; settings->userFunctionsDockVisible = oldUserFunctionsDockVisible; settings->userUnitsDockVisible = oldUserUnitsDockVisible; settings->bitfieldVisible = oldBitfieldVisible; settings->windowPositionSave = oldWindowPositionSave; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } } guard { settings, settings->colorScheme, settings->customColorSchemeJson, settings->sessionLayoutJson, settings->constantsDockVisible, settings->functionsDockVisible, settings->historyDockVisible, settings->keypadVisible, settings->formulaBookDockVisible, settings->variablesDockVisible, settings->userFunctionsDockVisible, settings->userUnitsDockVisible, settings->bitfieldVisible, settings->windowPositionSave, settings->hasNumberFormatStyleSetting, qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK") }; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{{QStringLiteral("background"), QStringLiteral("#1f3229")}}); settings->sessionLayoutJson.clear(); settings->constantsDockVisible = true; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->windowPositionSave = false; settings->hasNumberFormatStyleSetting = true; const QColor primary = generatePrimaryFromBackground(QColor(QStringLiteral("#1f3229"))); MainWindow window; window.resize(900, 500); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QCoreApplication::processEvents(); QTRY_COMPARE(window.findChildren().size(), 2); const QVector shades = generateOklchShades(QColor(QStringLiteral("#1f3229")), 6, ThemePolarity::Dark); const QColor selectedTabFill = shades.at(UiConfig::SelectedSessionTabFillShade); QList tabBars; for (ResultDisplay* display : window.findChildren()) { QTabBar* tabBar = tabBarForDisplay(display); QVERIFY(tabBar != nullptr); QVERIFY(tabBar->isVisible()); QVERIFY(tabBar->count() > 0); tabBars.append(tabBar); } QCOMPARE(tabBars.size(), 2); for (QTabBar* tabBar : tabBars) { QVERIFY2(colorsAreClose(selectedSessionTabFillColor(tabBar), selectedTabFill), qPrintable(QStringLiteral("fill=%1 expected=%2") .arg(selectedSessionTabFillColor(tabBar).name(), selectedTabFill.name()))); } QCOMPARE(std::count_if(tabBars.cbegin(), tabBars.cend(), [&primary](QTabBar* tabBar) { return selectedSessionTabHasBottomIndicator(tabBar, primary); }), 1); QDockWidget* constantsDock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constantsDock != nullptr); QLineEdit* searchBox = constantsDock->findChild(); QVERIFY(searchBox != nullptr); QList editors = window.findChildren(); QTRY_VERIFY(anyEditorHasPrimaryOutline(editors, primary)); constantsDock->show(); constantsDock->raise(); QCoreApplication::processEvents(); QTest::mouseClick(searchBox, Qt::LeftButton); QTRY_VERIFY(searchBox->hasFocus()); QTRY_VERIFY(!anyEditorHasPrimaryOutline(window.findChildren(), primary)); for (int i = 0; i < editors.size(); ++i) { editors.at(i)->setText(QStringLiteral("pane %1").arg(i + 1)); QCoreApplication::processEvents(); QVERIFY(searchBox->hasFocus()); QVERIFY2(!anyEditorHasPrimaryOutline(window.findChildren(), primary), qPrintable(editors.at(i)->styleSheet())); } } void TestFocusUi::dock_selection_inserts_into_active_session_pane_after_focus_transfer() { Settings* settings = Settings::instance(); struct SettingsGuard { Settings* settings; QString oldSessionLayoutJson; bool oldConstantsDockVisible; bool oldFunctionsDockVisible; bool oldHistoryDockVisible; bool oldKeypadVisible; bool oldFormulaBookDockVisible; bool oldVariablesDockVisible; bool oldUserFunctionsDockVisible; bool oldUserUnitsDockVisible; bool oldBitfieldVisible; bool oldWindowPositionSave; bool oldHasNumberFormatStyleSetting; QByteArray oldSkipUpdateCheck; bool hadSkipUpdateCheck; ~SettingsGuard() { settings->sessionLayoutJson = oldSessionLayoutJson; settings->constantsDockVisible = oldConstantsDockVisible; settings->functionsDockVisible = oldFunctionsDockVisible; settings->historyDockVisible = oldHistoryDockVisible; settings->keypadVisible = oldKeypadVisible; settings->formulaBookDockVisible = oldFormulaBookDockVisible; settings->variablesDockVisible = oldVariablesDockVisible; settings->userFunctionsDockVisible = oldUserFunctionsDockVisible; settings->userUnitsDockVisible = oldUserUnitsDockVisible; settings->bitfieldVisible = oldBitfieldVisible; settings->windowPositionSave = oldWindowPositionSave; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } } guard { settings, settings->sessionLayoutJson, settings->constantsDockVisible, settings->functionsDockVisible, settings->historyDockVisible, settings->keypadVisible, settings->formulaBookDockVisible, settings->variablesDockVisible, settings->userFunctionsDockVisible, settings->userUnitsDockVisible, settings->bitfieldVisible, settings->windowPositionSave, settings->hasNumberFormatStyleSetting, qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK") }; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); settings->sessionLayoutJson.clear(); settings->constantsDockVisible = true; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->windowPositionSave = false; settings->hasNumberFormatStyleSetting = true; MainWindow window; window.resize(900, 500); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); ResultDisplay* firstDisplay = window.findChild(); QVERIFY(firstDisplay != nullptr); QWidget* firstPage = firstDisplay->parentWidget(); Editor* firstEditor = firstPage ? firstPage->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; QVERIFY(firstEditor != nullptr); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QCoreApplication::processEvents(); QTRY_COMPARE(window.findChildren().size(), 2); const QList displays = window.findChildren(); ResultDisplay* secondDisplay = displays.first() == firstDisplay ? displays.last() : displays.first(); QWidget* secondPage = secondDisplay->parentWidget(); Editor* secondEditor = secondPage ? secondPage->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; QVERIFY(secondEditor != nullptr); secondEditor->setText(QString()); firstEditor->setText(QStringLiteral("x")); firstEditor->setCursorPosition(firstEditor->text().size()); QWidget* firstPane = paneWidgetForDisplay(firstDisplay); QWidget* secondPane = paneWidgetForDisplay(secondDisplay); QVERIFY(firstPane != nullptr); QVERIFY(secondPane != nullptr); QCOMPARE(firstPane->objectName(), QStringLiteral("SessionPane")); QCOMPARE(secondPane->objectName(), QStringLiteral("SessionPane")); QDockWidget* constantsDock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constantsDock != nullptr); QTreeWidget* constantsList = constantsDock->findChild(); QVERIFY(constantsList != nullptr); constantsDock->show(); constantsDock->raise(); QCoreApplication::processEvents(); QTest::mouseClick(constantsList->viewport(), Qt::LeftButton, Qt::NoModifier, constantsList->viewport()->rect().center()); QTRY_VERIFY(constantsList->hasFocus()); QVERIFY(QMetaObject::invokeMethod(&window, "insertConstantIntoEditor", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("pi")))); QVERIFY2(firstEditor->text() == QStringLiteral("x") && secondEditor->text() == QStringLiteral("pi"), qPrintable(QStringLiteral("first='%1' second='%2'") .arg(firstEditor->text(), secondEditor->text()))); } void TestFocusUi::clicking_tab_activates_own_pane_in_nested_split_layout() { Settings* settings = Settings::instance(); struct SettingsGuard { Settings* settings; QString oldColorScheme; QString oldCustomColorSchemeJson; QString oldSessionLayoutJson; bool oldConstantsDockVisible; bool oldFunctionsDockVisible; bool oldHistoryDockVisible; bool oldKeypadVisible; bool oldFormulaBookDockVisible; bool oldVariablesDockVisible; bool oldUserFunctionsDockVisible; bool oldUserUnitsDockVisible; bool oldBitfieldVisible; bool oldWindowPositionSave; bool oldHasNumberFormatStyleSetting; QByteArray oldSkipUpdateCheck; bool hadSkipUpdateCheck; ~SettingsGuard() { settings->colorScheme = oldColorScheme; settings->customColorSchemeJson = oldCustomColorSchemeJson; settings->sessionLayoutJson = oldSessionLayoutJson; settings->constantsDockVisible = oldConstantsDockVisible; settings->functionsDockVisible = oldFunctionsDockVisible; settings->historyDockVisible = oldHistoryDockVisible; settings->keypadVisible = oldKeypadVisible; settings->formulaBookDockVisible = oldFormulaBookDockVisible; settings->variablesDockVisible = oldVariablesDockVisible; settings->userFunctionsDockVisible = oldUserFunctionsDockVisible; settings->userUnitsDockVisible = oldUserUnitsDockVisible; settings->bitfieldVisible = oldBitfieldVisible; settings->windowPositionSave = oldWindowPositionSave; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } } guard { settings, settings->colorScheme, settings->customColorSchemeJson, settings->sessionLayoutJson, settings->constantsDockVisible, settings->functionsDockVisible, settings->historyDockVisible, settings->keypadVisible, settings->formulaBookDockVisible, settings->variablesDockVisible, settings->userFunctionsDockVisible, settings->userUnitsDockVisible, settings->bitfieldVisible, settings->windowPositionSave, settings->hasNumberFormatStyleSetting, qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK") }; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{{QStringLiteral("background"), QStringLiteral("#1f3229")}}); settings->sessionLayoutJson.clear(); settings->constantsDockVisible = false; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->windowPositionSave = false; settings->hasNumberFormatStyleSetting = true; const QColor primary = generatePrimaryFromBackground(QColor(QStringLiteral("#1f3229"))); MainWindow window; window.resize(900, 600); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QCoreApplication::processEvents(); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneDown", Qt::DirectConnection)); QCoreApplication::processEvents(); QTRY_COMPARE(window.findChildren().size(), 3); QList displays = window.findChildren(); std::sort(displays.begin(), displays.end(), [](ResultDisplay* lhs, ResultDisplay* rhs) { const QPoint lhsPos = lhs->mapToGlobal(QPoint(0, 0)); const QPoint rhsPos = rhs->mapToGlobal(QPoint(0, 0)); if (lhsPos.y() != rhsPos.y()) return lhsPos.y() < rhsPos.y(); return lhsPos.x() < rhsPos.x(); }); ResultDisplay* paneA = displays.at(0); ResultDisplay* paneB = displays.at(1); ResultDisplay* paneC = displays.at(2); QVERIFY(paneA->mapToGlobal(QPoint(0, 0)).x() < paneB->mapToGlobal(QPoint(0, 0)).x()); QVERIFY(paneC->mapToGlobal(QPoint(0, 0)).y() > paneB->mapToGlobal(QPoint(0, 0)).y()); Editor* editorA = editorForDisplay(paneA); Editor* editorB = editorForDisplay(paneB); Editor* editorC = editorForDisplay(paneC); QTabBar* tabA = tabBarForDisplay(paneA); QTabBar* tabB = tabBarForDisplay(paneB); QTabBar* tabC = tabBarForDisplay(paneC); QVERIFY(editorA != nullptr); QVERIFY(editorB != nullptr); QVERIFY(editorC != nullptr); QVERIFY(tabA != nullptr); QVERIFY(tabB != nullptr); QVERIFY(tabC != nullptr); QVERIFY(qAbs(tabA->mapToGlobal(QPoint(0, 0)).x() - paneA->mapToGlobal(QPoint(0, 0)).x()) < 8); QVERIFY(qAbs(tabB->mapToGlobal(QPoint(0, 0)).x() - paneB->mapToGlobal(QPoint(0, 0)).x()) < 8); QVERIFY(qAbs(tabC->mapToGlobal(QPoint(0, 0)).x() - paneC->mapToGlobal(QPoint(0, 0)).x()) < 8); QTest::mouseClick(paneB->viewport(), Qt::LeftButton, Qt::NoModifier, paneB->viewport()->rect().center()); QTRY_VERIFY(editorHasPrimaryOutline(editorB, primary)); QVERIFY(selectedSessionTabHasBottomIndicator(tabB, primary)); QVERIFY(tabA->count() > 0); QTest::mouseClick(tabA, Qt::LeftButton, Qt::NoModifier, tabA->tabRect(0).center()); QTRY_VERIFY2(editorHasPrimaryOutline(editorA, primary), qPrintable(QStringLiteral("A=%1 B=%2 C=%3 tabA=%4 tabB=%5 tabC=%6 focus=%7") .arg(editorHasPrimaryOutline(editorA, primary)) .arg(editorHasPrimaryOutline(editorB, primary)) .arg(editorHasPrimaryOutline(editorC, primary)) .arg(selectedSessionTabHasBottomIndicator(tabA, primary)) .arg(selectedSessionTabHasBottomIndicator(tabB, primary)) .arg(selectedSessionTabHasBottomIndicator(tabC, primary)) .arg(QApplication::focusWidget() ? QString::fromLatin1(QApplication::focusWidget()->metaObject()->className()) : QStringLiteral("")))); QVERIFY(selectedSessionTabHasBottomIndicator(tabA, primary)); QVERIFY(!editorHasPrimaryOutline(editorC, primary)); QVERIFY(!selectedSessionTabHasBottomIndicator(tabC, primary)); } void TestFocusUi::active_pane_survives_window_reactivation_focus_replay() { MainWindowStateGuard guard; Settings* settings = Settings::instance(); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{{QStringLiteral("background"), QStringLiteral("#1f3229")}}); settings->sessionLayoutJson.clear(); settings->constantsDockVisible = false; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->hasNumberFormatStyleSetting = true; const QColor primary = generatePrimaryFromBackground(QColor(QStringLiteral("#1f3229"))); MainWindow window; window.resize(900, 500); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QCoreApplication::processEvents(); QTRY_COMPARE(window.findChildren().size(), 3); QList displays = window.findChildren(); std::sort(displays.begin(), displays.end(), [](ResultDisplay* lhs, ResultDisplay* rhs) { return lhs->mapToGlobal(QPoint(0, 0)).x() < rhs->mapToGlobal(QPoint(0, 0)).x(); }); ResultDisplay* firstDisplay = displays.at(0); Editor* firstEditor = editorForDisplay(firstDisplay); QVERIFY(firstEditor != nullptr); QTest::mouseClick(firstDisplay->viewport(), Qt::LeftButton, Qt::NoModifier, firstDisplay->viewport()->rect().center()); QTRY_VERIFY(editorHasPrimaryOutline(firstEditor, primary)); for (ResultDisplay* display : displays) { Editor* editor = editorForDisplay(display); QVERIFY(editor != nullptr); QFocusEvent focusIn(QEvent::FocusIn, Qt::OtherFocusReason); QCoreApplication::sendEvent(editor->viewport(), &focusIn); } QCoreApplication::processEvents(); QVERIFY(QMetaObject::invokeMethod(&window, "insertTextIntoEditor", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("p")))); QVERIFY2(firstEditor->text() == QStringLiteral("p"), qPrintable(QStringLiteral("passive replay pane0='%1' pane1='%2' pane2='%3'") .arg(editorForDisplay(displays.at(0))->text(), editorForDisplay(displays.at(1))->text(), editorForDisplay(displays.at(2))->text()))); firstEditor->clear(); // Let pane-creation focus timers settle, then reselect the first pane so // WindowDeactivate captures the same stable state as a real app switch. QCoreApplication::processEvents(); QTest::mouseClick(firstDisplay->viewport(), Qt::LeftButton, Qt::NoModifier, firstDisplay->viewport()->rect().center()); QTRY_VERIFY(editorHasPrimaryOutline(firstEditor, primary)); QEvent windowDeactivate(QEvent::WindowDeactivate); QCoreApplication::sendEvent(&window, &windowDeactivate); QEvent windowActivate(QEvent::WindowActivate); QCoreApplication::sendEvent(&window, &windowActivate); for (ResultDisplay* display : displays) { Editor* editor = editorForDisplay(display); QVERIFY(editor != nullptr); QFocusEvent focusIn(QEvent::FocusIn, Qt::OtherFocusReason); QCoreApplication::sendEvent(editor->viewport(), &focusIn); } QCoreApplication::processEvents(); QVERIFY(QMetaObject::invokeMethod(&window, "insertTextIntoEditor", Qt::DirectConnection, Q_ARG(QString, QStringLiteral("z")))); QVERIFY2(firstEditor->text() == QStringLiteral("z"), qPrintable(QStringLiteral("after activation pane0='%1' pane1='%2' pane2='%3'") .arg(editorForDisplay(displays.at(0))->text(), editorForDisplay(displays.at(1))->text(), editorForDisplay(displays.at(2))->text()))); QTRY_VERIFY2(editorHasPrimaryOutline(firstEditor, primary), qPrintable(QStringLiteral("pane0=%1 pane1=%2 pane2=%3 focus=%4") .arg(editorHasPrimaryOutline(editorForDisplay(displays.at(0)), primary)) .arg(editorHasPrimaryOutline(editorForDisplay(displays.at(1)), primary)) .arg(editorHasPrimaryOutline(editorForDisplay(displays.at(2)), primary)) .arg(QApplication::focusWidget() ? QString::fromLatin1(QApplication::focusWidget()->metaObject()->className()) : QStringLiteral("")))); for (int i = 1; i < displays.size(); ++i) QVERIFY(!editorHasPrimaryOutline(editorForDisplay(displays.at(i)), primary)); } void TestFocusUi::extra_window_activation_restores_own_active_tab_indicator() { MainWindowStateGuard guard; Settings* settings = Settings::instance(); settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{{QStringLiteral("background"), QStringLiteral("#1f3229")}}); settings->sessionLayoutJson.clear(); settings->constantsDockVisible = false; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->hasNumberFormatStyleSetting = true; const QColor primary = generatePrimaryFromBackground(QColor(QStringLiteral("#1f3229"))); MainWindow primaryWindow; primaryWindow.resize(800, 500); primaryWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&primaryWindow)); MainWindow extraWindow; extraWindow.resize(900, 500); extraWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&extraWindow)); QList extraDisplays = extraWindow.findChildren(); QCOMPARE(extraDisplays.size(), 1); ResultDisplay* extraDisplay = extraDisplays.constFirst(); QTabBar* extraTabBar = tabBarForDisplay(extraDisplay); QVERIFY(extraTabBar != nullptr); QTest::mouseClick(extraDisplay->viewport(), Qt::LeftButton, Qt::NoModifier, extraDisplay->viewport()->rect().center()); QVERIFY(QMetaObject::invokeMethod(&extraWindow, "showNewSessionDialog", Qt::DirectConnection)); QCoreApplication::processEvents(); QTRY_COMPARE(extraTabBar->count(), 2); QTRY_VERIFY(extraTabBar->isVisible()); QTRY_VERIFY(selectedSessionTabHasBottomIndicator(extraTabBar, primary)); ResultDisplay* primaryDisplay = primaryWindow.findChild(); QVERIFY(primaryDisplay != nullptr); QTest::mouseClick(primaryDisplay->viewport(), Qt::LeftButton, Qt::NoModifier, primaryDisplay->viewport()->rect().center()); QCoreApplication::processEvents(); QEvent primaryDeactivate(QEvent::WindowDeactivate); QCoreApplication::sendEvent(&primaryWindow, &primaryDeactivate); QEvent extraActivate(QEvent::WindowActivate); QCoreApplication::sendEvent(&extraWindow, &extraActivate); QCoreApplication::processEvents(); QTRY_VERIFY(selectedSessionTabHasBottomIndicator(extraTabBar, primary)); } void TestFocusUi::startup_focuses_editor_with_visible_dock_input_data() { QTest::addColumn("dockName"); QTest::addColumn("startupMode"); QTest::addColumn("privateTab"); for (const QString& dock : {QStringLiteral("ConstantsDock"), QStringLiteral("FunctionsDock"), QStringLiteral("VariablesDock"), QStringLiteral("UserFunctionsDock"), QStringLiteral("UserUnitsDock")}) { for (const QString& mode : {QStringLiteral("fresh"), QStringLiteral("legacy"), QStringLiteral("tabs"), QStringLiteral("split"), QStringLiteral("new-window")}) { for (bool privateTab : {false, true}) { if (mode == QLatin1String("new-window") && privateTab) continue; const QString row = QStringLiteral("%1-%2-%3") .arg(dock, mode, privateTab ? QStringLiteral("private") : QStringLiteral("ordinary")); QTest::newRow(qPrintable(row)) << dock << mode << privateTab; } } } } void TestFocusUi::startup_focuses_editor_with_visible_dock_input() { QFETCH(QString, dockName); QFETCH(QString, startupMode); QFETCH(bool, privateTab); MainWindowStateGuard guard; PrivateSessionStorage storage; const auto resetSettings = qScopeGuard([]() { UiTestFixture::resetSettings(); }); Settings* settings = Settings::instance(); settings->openPrivateTabOnStartup = privateTab; settings->constantsDockVisible = dockName == QLatin1String("ConstantsDock"); settings->functionsDockVisible = dockName == QLatin1String("FunctionsDock"); settings->variablesDockVisible = dockName == QLatin1String("VariablesDock"); settings->userFunctionsDockVisible = dockName == QLatin1String("UserFunctionsDock"); settings->userUnitsDockVisible = dockName == QLatin1String("UserUnitsDock"); settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->bitfieldVisible = false; settings->keypadVisible = false; settings->hasNumberFormatStyleSetting = true; const bool savedLayout = startupMode == QLatin1String("tabs") || startupMode == QLatin1String("split"); const QString activeName = savedLayout ? QStringLiteral("Saved-Active") : QStringLiteral("Untitled-1"); if (savedLayout || startupMode == QLatin1String("legacy")) { // Legacy history is migrated after the initial session name is chosen. const QString sessionPath = savedLayout ? storage.path(activeName) : QDir(Settings::getDataPath()).filePath(QStringLiteral("history.json")); QDir().mkpath(QFileInfo(sessionPath).path()); writeFile(sessionPath, QJsonDocument(sessionJson(activeName)).toJson()); } if (savedLayout) { QJsonObject savedWindow = startupSessionWindow(activeName, QStringLiteral("saved")); if (startupMode == QLatin1String("split")) { const QString firstName = QStringLiteral("Saved-First"); writeFile(storage.path(firstName), QJsonDocument(sessionJson(firstName)).toJson()); QJsonObject firstPane = startupSessionWindow(firstName, QString()) .value(QStringLiteral("root")).toObject(); QJsonObject activePane = savedWindow.value(QStringLiteral("root")).toObject(); firstPane.insert(QStringLiteral("type"), QStringLiteral("pane")); activePane.insert(QStringLiteral("type"), QStringLiteral("pane")); savedWindow.insert(QStringLiteral("root"), QJsonObject { { QStringLiteral("type"), QStringLiteral("split") }, { QStringLiteral("active"), activeName }, { QStringLiteral("orientation"), QStringLiteral("horizontal") }, { QStringLiteral("children"), QJsonArray { firstPane, activePane } } }); } settings->sessionLayoutJson = QString::fromUtf8(QJsonDocument(QJsonObject { { QStringLiteral("scheme"), 1 }, { QStringLiteral("kind"), QStringLiteral("session-layout") }, { QStringLiteral("activeWindow"), QStringLiteral("saved") }, { QStringLiteral("windows"), QJsonArray { savedWindow } } }).toJson(QJsonDocument::Compact)); } MainWindow window(startupMode != QLatin1String("new-window")); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QDockWidget* dock = window.findChild(dockName); QVERIFY(dock != nullptr); QTRY_VERIFY(dock->isVisible()); QLineEdit* search = dock->findChild(); QVERIFY(search != nullptr); const auto focusedDisplay = [&window]() -> ResultDisplay* { for (ResultDisplay* display : window.findChildren()) { Editor* editor = paneWidgetForDisplay(display)->findChild(); if (editor != nullptr && focusIsWithin(editor)) return display; } return nullptr; }; QTRY_VERIFY(focusedDisplay() != nullptr); QTRY_COMPARE(window.findChildren().size(), startupMode == QLatin1String("split") ? 2 : 1); QTRY_VERIFY(focusedDisplay() != nullptr && focusedDisplay()->session()->isPrivate() == privateTab); if (!privateTab) QTRY_VERIFY(focusedDisplay() != nullptr && focusedDisplay()->session()->name() == activeName); if (!privateTab && (savedLayout || startupMode == QLatin1String("legacy"))) QTRY_VERIFY(focusedDisplay() != nullptr && focusedDisplay()->session()->historySize() == 1); if (privateTab && (savedLayout || startupMode == QLatin1String("legacy"))) QTRY_VERIFY(focusedDisplay() != nullptr && tabBarForDisplay(focusedDisplay())->count() == 2); // Delayed window activation must keep the editor selected after restoration. QTest::qWait(400); QVERIFY(focusedDisplay() != nullptr); QVERIFY(!search->hasFocus()); // Once startup finishes, choosing the dock search must still work normally. QTest::mouseClick(search, Qt::LeftButton); QTRY_VERIFY(search->hasFocus()); QTest::qWait(400); QVERIFY(search->hasFocus()); } void TestFocusUi::focused_dock_search_survives_window_reactivation_focus_replay() { MainWindowStateGuard guard; Settings* settings = Settings::instance(); settings->sessionLayoutJson.clear(); settings->constantsDockVisible = true; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->hasNumberFormatStyleSetting = true; MainWindow window; window.resize(900, 500); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QCoreApplication::processEvents(); QTRY_COMPARE(window.findChildren().size(), 2); QDockWidget* constantsDock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(constantsDock != nullptr); QLineEdit* searchBox = constantsDock->findChild(); QVERIFY(searchBox != nullptr); constantsDock->show(); constantsDock->raise(); QCoreApplication::processEvents(); QTest::mouseClick(searchBox, Qt::LeftButton); QTRY_VERIFY(searchBox->hasFocus()); QEvent windowDeactivate(QEvent::WindowDeactivate); QCoreApplication::sendEvent(&window, &windowDeactivate); QEvent windowActivate(QEvent::WindowActivate); QCoreApplication::sendEvent(&window, &windowActivate); for (Editor* editor : window.findChildren()) { QFocusEvent focusIn(QEvent::FocusIn, Qt::OtherFocusReason); QCoreApplication::sendEvent(editor->viewport(), &focusIn); } QCoreApplication::processEvents(); QTRY_VERIFY(searchBox->hasFocus()); QTest::keyClicks(searchBox, "mol"); QCOMPARE(searchBox->text(), QStringLiteral("mol")); } void TestFocusUi::focusing_loaded_pane_preserves_its_current_scroll_position() { Settings* appSettings = Settings::instance(); struct SettingsGuard { Settings* settings; QByteArray oldSkipUpdateCheck; bool hadSkipUpdateCheck; QString oldSessionLayoutJson; bool oldConstantsDockVisible; bool oldFunctionsDockVisible; bool oldHistoryDockVisible; bool oldKeypadVisible; bool oldFormulaBookDockVisible; bool oldVariablesDockVisible; bool oldUserFunctionsDockVisible; bool oldUserUnitsDockVisible; bool oldBitfieldVisible; bool oldWindowPositionSave; bool oldHasNumberFormatStyleSetting; ~SettingsGuard() { settings->sessionLayoutJson = oldSessionLayoutJson; settings->constantsDockVisible = oldConstantsDockVisible; settings->functionsDockVisible = oldFunctionsDockVisible; settings->historyDockVisible = oldHistoryDockVisible; settings->keypadVisible = oldKeypadVisible; settings->formulaBookDockVisible = oldFormulaBookDockVisible; settings->variablesDockVisible = oldVariablesDockVisible; settings->userFunctionsDockVisible = oldUserFunctionsDockVisible; settings->userUnitsDockVisible = oldUserUnitsDockVisible; settings->bitfieldVisible = oldBitfieldVisible; settings->windowPositionSave = oldWindowPositionSave; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } } guard { appSettings, qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), appSettings->sessionLayoutJson, appSettings->constantsDockVisible, appSettings->functionsDockVisible, appSettings->historyDockVisible, appSettings->keypadVisible, appSettings->formulaBookDockVisible, appSettings->variablesDockVisible, appSettings->userFunctionsDockVisible, appSettings->userUnitsDockVisible, appSettings->bitfieldVisible, appSettings->windowPositionSave, appSettings->hasNumberFormatStyleSetting }; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); appSettings->sessionLayoutJson.clear(); appSettings->constantsDockVisible = false; appSettings->functionsDockVisible = false; appSettings->historyDockVisible = false; appSettings->keypadVisible = false; appSettings->formulaBookDockVisible = false; appSettings->variablesDockVisible = false; appSettings->userFunctionsDockVisible = false; appSettings->userUnitsDockVisible = false; appSettings->bitfieldVisible = false; appSettings->windowPositionSave = false; appSettings->hasNumberFormatStyleSetting = true; MainWindow window; window.resize(900, 500); window.show(); QCoreApplication::processEvents(); ResultDisplay* firstDisplay = window.findChild(); Editor* firstEditor = window.findChild(); QVERIFY(firstDisplay != nullptr); QVERIFY(firstEditor != nullptr); for (int i = 0; i < 80; ++i) { firstEditor->setText(QString::number(i)); QVERIFY(QMetaObject::invokeMethod(&window, "evaluateEditorExpression", Qt::DirectConnection)); } QCoreApplication::processEvents(); QScrollBar* firstScrollBar = firstDisplay->verticalScrollBar(); QVERIFY(firstScrollBar->maximum() > 20); firstScrollBar->setValue(10); QCOMPARE(firstScrollBar->value(), 10); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QCoreApplication::processEvents(); const QList displays = window.findChildren(); QCOMPARE(displays.size(), 2); ResultDisplay* secondDisplay = displays.first() == firstDisplay ? displays.last() : displays.first(); QWidget* secondPage = secondDisplay->parentWidget(); Editor* secondEditor = secondPage ? secondPage->findChild(QString(), Qt::FindDirectChildrenOnly) : nullptr; QVERIFY(secondEditor != nullptr); QTRY_VERIFY(secondEditor->hasFocus()); // Make the already-loaded first pane diverge from the scroll snapshot that // was captured when focus moved to the second pane. firstScrollBar->setValue(20); QCOMPARE(firstScrollBar->value(), 20); QTest::mouseClick(firstDisplay->viewport(), Qt::LeftButton, Qt::NoModifier, firstDisplay->viewport()->rect().center()); QCoreApplication::processEvents(); QTRY_VERIFY(firstEditor->hasFocus()); QTabBar* secondTabBar = paneWidgetForDisplay(secondDisplay)->findChild(); QVERIFY(secondTabBar != nullptr); QVERIFY(secondTabBar->isVisible()); QTest::mouseClick(secondTabBar, Qt::LeftButton, Qt::NoModifier, secondTabBar->tabRect(secondTabBar->currentIndex()).center()); QCoreApplication::processEvents(); QTRY_VERIFY(secondEditor->hasFocus()); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); QCOMPARE(firstScrollBar->value(), 20); } void TestFocusUi::clipboard_actions_follow_active_pane_data() { QTest::addColumn("split"); QTest::addColumn("restore"); QTest::addColumn("shortcut"); for (const bool shortcut : {false, true}) { const QByteArray method = shortcut ? "shortcut" : "menu"; QTest::newRow(QByteArray(method + "-fresh").constData()) << false << false << shortcut; QTest::newRow(QByteArray(method + "-split").constData()) << true << false << shortcut; QTest::newRow(QByteArray(method + "-restored").constData()) << false << true << shortcut; QTest::newRow(QByteArray(method + "-restored-split").constData()) << true << true << shortcut; } } void TestFocusUi::clipboard_actions_follow_active_pane() { QFETCH(bool, split); QFETCH(bool, restore); QFETCH(bool, shortcut); MainWindowStateGuard guard; guard.settings->sessionLayoutJson.clear(); guard.settings->windowState.clear(); guard.settings->windowGeometry.clear(); guard.settings->hasNumberFormatStyleSetting = true; const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([oldClipboard]() { QApplication::clipboard()->setText(oldClipboard); }); if (restore) { MainWindow source; if (split) QVERIFY(QMetaObject::invokeMethod(&source, "splitActivePaneRight", Qt::DirectConnection)); source.persistSessionAndSettingsForShutdown(); QVERIFY(!guard.settings->sessionLayoutJson.isEmpty()); } MainWindow window; window.show(); window.activateWindow(); QVERIFY(QTest::qWaitForWindowExposed(&window)); if (restore) { QTRY_COMPARE(window.findChildren().size(), split ? 2 : 1); QTRY_VERIFY(window.findChildren().first()->count() > 0); // Restoration replaces the initial editor asynchronously, even for one pane. QTest::qWait(400); } else if (split) { QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QTRY_COMPARE(window.findChildren().size(), 2); } const QList editors = window.findChildren(); QMenu* editMenu = menuWithTitle(window.menuBar(), QStringLiteral("&Edit")); QVERIFY(editMenu != nullptr); QAction* copyAction = directMenuActionWithText(editMenu, QStringLiteral("&Copy")); QAction* pasteAction = directMenuActionWithText(editMenu, QStringLiteral("&Paste")); QVERIFY(copyAction != nullptr); QVERIFY(pasteAction != nullptr); for (Editor* editor : editors) { QTest::mouseClick(editor->viewport(), Qt::LeftButton); QTRY_VERIFY(editor->hasFocus()); editor->setText(QStringLiteral("123456")); QTextCursor cursor = editor->textCursor(); cursor.setPosition(2); cursor.setPosition(4, QTextCursor::KeepAnchor); editor->setTextCursor(cursor); QApplication::clipboard()->setText(QStringLiteral("unchanged")); if (shortcut) { const QKeyCombination key = QKeySequence(QKeySequence::Copy)[0]; QTest::keyClick(editor, key.key(), key.keyboardModifiers()); } else { copyAction->trigger(); } QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("34")); QCOMPARE(editor->text(), QStringLiteral("123456")); QApplication::clipboard()->setText(QStringLiteral("78")); if (shortcut) { const QKeyCombination key = QKeySequence(QKeySequence::Paste)[0]; // Exercise the menu shortcut path as well as the widget's own handler. QTest::keyClick(&window, key.key(), key.keyboardModifiers()); } else { pasteAction->trigger(); } QCOMPARE(editor->text(), QStringLiteral("127856")); editor->undo(); QCOMPARE(editor->text(), QStringLiteral("123456")); editor->clear(); } } void TestFocusUi::edit_commands_follow_active_editor_data() { QTest::addColumn("split"); QTest::addColumn("shortcut"); QTest::addColumn("foreignMenu"); QTest::newRow("menu") << false << false << false; QTest::newRow("shortcuts") << false << true << false; QTest::newRow("split-menu") << true << false << false; QTest::newRow("split-shortcuts") << true << true << false; QTest::newRow("another-windows-menu") << true << false << true; } void TestFocusUi::edit_commands_follow_active_editor() { QFETCH(bool, split); QFETCH(bool, shortcut); QFETCH(bool, foreignMenu); MainWindowStateGuard guard; guard.settings->autoCalc = false; const QString oldClipboard = QApplication::clipboard()->text(); const auto restoreClipboard = qScopeGuard([oldClipboard]() { QApplication::clipboard()->setText(oldClipboard); }); MainWindow window(false); MainWindow other(false); window.show(); other.show(); window.activateWindow(); QVERIFY(QTest::qWaitForWindowExposed(&window)); if (split) QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); Editor* editor = window.findChildren().last(); ResultDisplay* display = window.findChildren().last(); QVERIFY(editor && display); editor->setFocus(); QTRY_VERIFY(editor->hasFocus()); QMenu* menu = menuWithTitle((foreignMenu ? other : window).menuBar(), QStringLiteral("&Edit")); QVERIFY(menu); QAction* undo = directMenuActionWithText(menu, QStringLiteral("&Undo")); QAction* redo = directMenuActionWithText(menu, QStringLiteral("&Redo")); QAction* cut = directMenuActionWithText(menu, QStringLiteral("Cu&t")); QAction* copy = directMenuActionWithText(menu, QStringLiteral("&Copy")); QVERIFY(undo && redo && cut && copy); const auto invoke = [shortcut, &window](QAction* action, QKeySequence::StandardKey standardKey) { if (shortcut) { const QKeyCombination key = QKeySequence(standardKey)[0]; QTest::keyClick(&window, key.key(), key.keyboardModifiers()); } else { action->trigger(); } }; editor->setText(QStringLiteral("12")); QVERIFY(!undo->isEnabled()); QVERIFY(!redo->isEnabled()); QVERIFY(!cut->isEnabled()); QVERIFY(!copy->isEnabled()); editor->setCursorPosition(2); editor->insertPlainText(QStringLiteral("3")); QVERIFY(undo->isEnabled()); invoke(undo, QKeySequence::Undo); QCOMPARE(editor->text(), QStringLiteral("12")); QVERIFY(redo->isEnabled()); invoke(redo, QKeySequence::Redo); QCOMPARE(editor->text(), QStringLiteral("123")); QTextCursor cursor = editor->textCursor(); cursor.setPosition(1); cursor.setPosition(2, QTextCursor::KeepAnchor); editor->setTextCursor(cursor); QVERIFY(cut->isEnabled()); QVERIFY(copy->isEnabled()); invoke(cut, QKeySequence::Cut); QCOMPARE(editor->text(), QStringLiteral("13")); QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("2")); invoke(undo, QKeySequence::Undo); QCOMPARE(editor->text(), QStringLiteral("123")); cursor = editor->textCursor(); cursor.clearSelection(); editor->setTextCursor(cursor); display->setPlainText(QStringLiteral("9876")); cursor = display->textCursor(); cursor.setPosition(1); cursor.setPosition(3, QTextCursor::KeepAnchor); display->setTextCursor(cursor); QVERIFY(copy->isEnabled()); QVERIFY(!cut->isEnabled()); invoke(copy, QKeySequence::Copy); QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("87")); QCOMPARE(display->textCursor().selectedText(), QStringLiteral("87")); cursor.clearSelection(); display->setTextCursor(cursor); QVERIFY(!copy->isEnabled()); QVERIFY(other.findChild()->text().isEmpty()); } void TestFocusUi::copy_shortcut_preserves_display_selection_in_other_pane() { MainWindowStateGuard guard; guard.settings->sessionLayoutJson.clear(); guard.settings->windowState.clear(); guard.settings->windowGeometry.clear(); guard.settings->hasNumberFormatStyleSetting = true; MainWindow window; window.show(); window.activateWindow(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); QTRY_COMPARE(window.findChildren().size(), 2); const QList displays = window.findChildren(); for (ResultDisplay* display : displays) { display->setPlainText(QStringLiteral("123456")); QTextCursor cursor = display->textCursor(); cursor.setPosition(2); cursor.setPosition(4, QTextCursor::KeepAnchor); display->setTextCursor(cursor); Editor* editor = display->parentWidget()->findChild(); QVERIFY(editor != nullptr); QTRY_VERIFY(editor->hasFocus()); QApplication::clipboard()->setText(QStringLiteral("unchanged")); const QKeyCombination key = QKeySequence(QKeySequence::Copy)[0]; QTest::keyClick(editor, key.key(), key.keyboardModifiers()); QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("34")); } } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testfocusui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testhmath.cpp000066400000000000000000001667211526573132500240100ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2006-2010, 2014-2016, 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "math/hmath.h" #include "math/floatnum/floatconst.h" #include "tests/testcommon.h" #include #include #include #include using namespace std; typedef HNumber::Format Format; #define CHECK(x,y) check_value(__FILE__,__LINE__,#x,x,y) #define CHECK_FORMAT(f,x,y) check_format(__FILE__,__LINE__,#x,x,f,y) #define CHECK_PRECISE(x,y) check_precise(__FILE__,__LINE__,#x,x,y) #define CHECK_KNOWN_ISSUE(x,y,n) check_value(__FILE__,__LINE__,#x,x,y,n) static int hmath_total_tests = 0; static int hmath_failed_tests = 0; static int hmath_new_failed_tests = 0; HNumber PI; static void check_value(const char* file, int line, const char* msg, const HNumber& n, const char* expected, int issue = 0) { ++hmath_total_tests; string result = HMath::format(n, HNumber::Format::Fixed()).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, hmath_failed_tests, hmath_new_failed_tests, issue); } static void check_format(const char* file, int line, const char* msg, const HNumber& n, Format format, const char* expected) { ++hmath_total_tests; string result = HMath::format(n, format).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, hmath_failed_tests, hmath_new_failed_tests); } static void check_precise(const char* file, int line, const char* msg, const HNumber& n, const char* expected) { ++hmath_total_tests; string result = HMath::format(n, Format::Fixed() + Format::Precision(50)).toStdString(); DisplayErrorOnMismatch(file, line, msg, result, expected, hmath_failed_tests, hmath_new_failed_tests); } void test_remove_trailing_zeroes() { Format trimmed = Format::Fixed() + Format::Precision(3); trimmed.removeTrailingZeroes = true; CHECK_FORMAT(trimmed, HNumber("1.9999"), "2"); CHECK_FORMAT(trimmed, HNumber("1200"), "1200"); CHECK_FORMAT(trimmed, HNumber("1.203"), "1.203"); CHECK_FORMAT(trimmed, HNumber("-0.0001"), "0"); CHECK_FORMAT(trimmed, HNumber("NaN"), "NaN"); CHECK_FORMAT(Format(trimmed), HNumber("3.14"), "3.14"); CHECK_FORMAT(Format::Scientific() + trimmed, HNumber("1e20"), "1e20"); CHECK_FORMAT(trimmed + Format::Decimal(), HNumber("3.14"), "3.14"); CHECK_FORMAT(Format::Engineering() + Format::ForcedExponent(3) + trimmed, HNumber("1200"), "1.2e3"); CHECK_FORMAT(Format::Binary() + Format::PadBits(8) + trimmed, HNumber("1.5"), "0b00000001.1"); CHECK_FORMAT(Format::Fixed() + Format::Precision(3), HNumber("3.14"), "3.140"); } void test_create() { CHECK(HNumber("1.0"), "1"); CHECK(HNumber("2.0"), "2"); CHECK(HNumber("1e-3"), "0.001"); // Too large or too small. CHECK(HNumber("1e1000000000"), "NaN"); CHECK(HNumber("1e-1000000000"), "NaN"); CHECK_FORMAT(Format::Scientific() + Format::Precision(2), HNumber("1e1000000000"), "NaN"); CHECK_FORMAT(Format::Scientific() + Format::Precision(2), HNumber("1e-1000000000"), "NaN"); } void test_format() { // Fixed decimal digits. Format f = Format::Fixed(); CHECK_FORMAT(f + Format::Precision(0), HNumber("NaN"), "NaN"); CHECK_FORMAT(f + Format::Precision(0), HNumber("0"), "0"); CHECK_FORMAT(f + Format::Precision(0), HNumber("1.1"), "1"); CHECK_FORMAT(f + Format::Precision(1), HNumber("2.11"), "2.1"); CHECK_FORMAT(f + Format::Precision(2), HNumber("3.111"), "3.11"); CHECK_FORMAT(f + Format::Precision(1), HNumber("4.001"), "4.0"); CHECK_FORMAT(f + Format::Precision(3), HNumber("4.1111"), "4.111"); CHECK_FORMAT(f + Format::Precision(2), HNumber("3.14"), "3.14"); CHECK_FORMAT(f + Format::Precision(3), HNumber("3.14"), "3.140"); CHECK_FORMAT(f + Format::Precision(5), HNumber("3.14"), "3.14000"); CHECK_FORMAT(f + Format::Precision(7), HNumber("3.14"), "3.1400000"); CHECK_FORMAT(f + Format::Precision(7), HNumber("-0.001"), "-0.0010000"); CHECK_FORMAT(f + Format::Precision(8), HNumber("-0.001"), "-0.00100000"); CHECK_FORMAT(f + Format::Precision(9), HNumber("-0.001"), "-0.001000000"); CHECK_FORMAT(f + Format::Precision(-1), HNumber("4.000000000000000000000000000000000000000000001"), "4"); CHECK_FORMAT(f + Format::Precision(0), HNumber("1.19502868068833652008E-6"), "0"); CHECK_FORMAT(f + Format::Precision(1), HNumber("1.19502868068833652008E-6"), "0.0"); CHECK_FORMAT(f + Format::Precision(2), HNumber("1.19502868068833652008E-6"), "0.00"); CHECK_FORMAT(f + Format::Precision(3), HNumber("1.19502868068833652008E-6"), "0.000"); CHECK_FORMAT(f + Format::Precision(3), HNumber("1.195028680688336520083456938469843765E-6"), "0.000"); CHECK_FORMAT(f + Format::Precision(3), HNumber("-1.19502868068833652008E-6"), "0.000"); CHECK_FORMAT(f + Format::Precision(3), HNumber("0.0004999"), "0.000"); CHECK_FORMAT(f + Format::Precision(3), HNumber("0.0005"), "0.000"); CHECK_FORMAT(f + Format::Precision(6), HNumber("1.19502868068833652008E-6"), "0.000001"); CHECK_FORMAT(f + Format::Precision(-1) + Format::Hexadecimal(), HNumber("0.6"), "0x0.9999999999999999999A"); /* Issue 659 */ // Engineering notation. Format n = Format::Engineering(); CHECK_FORMAT(n + Format::Precision(0), HNumber("NaN"), "NaN"); CHECK_FORMAT(n + Format::Precision(0), HNumber("0"), "0"); CHECK_FORMAT(n + Format::Precision(0), HNumber("3.14"), "3.14e0"); CHECK_FORMAT(n + Format::Precision(1), HNumber("3.14"), "3.14e0"); CHECK_FORMAT(n + Format::Precision(2), HNumber("3.14"), "3.14e0"); CHECK_FORMAT(n + Format::Precision(3), HNumber("3.14"), "3.140e0"); CHECK_FORMAT(n + Format::Precision(5), HNumber("3.14"), "3.14000e0"); CHECK_FORMAT(n + Format::Precision(7), HNumber("3.14"), "3.1400000e0"); CHECK_FORMAT(n + Format::Precision(3), HNumber("-0.001"), "-1.000e-3"); CHECK_FORMAT(n + Format::Precision(2), HNumber("0.0001"), "100.e-6"); CHECK_FORMAT(n + Format::Precision(2), HNumber("0.001"), "1.00e-3"); CHECK_FORMAT(n + Format::Precision(2), HNumber("0.01"), "10.0e-3"); CHECK_FORMAT(n + Format::Precision(2), HNumber("0.1"), "100.e-3"); CHECK_FORMAT(n + Format::Precision(2), HNumber("1"), "1.00e0"); CHECK_FORMAT(n + Format::Precision(2), HNumber("10"), "10.0e0"); CHECK_FORMAT(n + Format::Precision(2), HNumber("100"), "100.e0"); CHECK_FORMAT(n + Format::Precision(2), HNumber("1000"), "1.00e3"); CHECK_FORMAT(n + Format::Precision(2), HNumber("10000"), "10.0e3"); CHECK_FORMAT(n + Format::Precision(2), HNumber("100000"), "100.e3"); CHECK_FORMAT(n + Format::Precision(2), HNumber("1000000"), "1.00e6"); CHECK_FORMAT(n + Format::Precision(2), HNumber("10000000"), "10.0e6"); // Scientific notation. Format e = Format::Scientific(); CHECK_FORMAT(e + Format::Precision(0), HNumber("NaN"), "NaN"); CHECK_FORMAT(e + Format::Precision(0), HNumber("0"), "0"); CHECK_FORMAT(e + Format::Precision(0), HNumber("3.14"), "3e0"); CHECK_FORMAT(e + Format::Precision(1), HNumber("3.14"), "3.1e0"); CHECK_FORMAT(e + Format::Precision(2), HNumber("3.14"), "3.14e0"); CHECK_FORMAT(e + Format::Precision(3), HNumber("3.14"), "3.140e0"); CHECK_FORMAT(e + Format::Precision(5), HNumber("3.14"), "3.14000e0"); CHECK_FORMAT(e + Format::Precision(7), HNumber("3.14"), "3.1400000e0"); CHECK_FORMAT(e + Format::Precision(3), HNumber("-0.001"), "-1.000e-3"); CHECK_FORMAT(e + Format::Precision(2), HNumber("0.0001"), "1.00e-4"); CHECK_FORMAT(e + Format::Precision(2), HNumber("0.001"), "1.00e-3"); CHECK_FORMAT(e + Format::Precision(2), HNumber("0.01"), "1.00e-2"); CHECK_FORMAT(e + Format::Precision(2), HNumber("0.1"), "1.00e-1"); CHECK_FORMAT(e + Format::Precision(2), HNumber("1"), "1.00e0"); CHECK_FORMAT(e + Format::Precision(2), HNumber("10"), "1.00e1"); CHECK_FORMAT(e + Format::Precision(2), HNumber("100"), "1.00e2"); CHECK_FORMAT(e + Format::Precision(2), HNumber("1000"), "1.00e3"); CHECK_FORMAT(e + Format::Precision(2), HNumber("10000"), "1.00e4"); CHECK_FORMAT(e + Format::Precision(2), HNumber("100000"), "1.00e5"); CHECK_FORMAT(e + Format::Precision(2), HNumber("1000000"), "1.00e6"); CHECK_FORMAT(e + Format::Precision(2), HNumber("10000000"), "1.00e7"); // General format. Format g = Format::General(); CHECK_FORMAT(g + Format::Precision(-1), PI, "3.14159265358979323846"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0"), "0"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.000000001"), "1.000e-9"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.00000001"), "1.000e-8"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.0000001"), "1.000e-7"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.000001"), "1.000e-6"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.00001"), "1.000e-5"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.0001"), "1.000e-4"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.001"), "0.001"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.01"), "0.010"); CHECK_FORMAT(g + Format::Precision(3), HNumber("0.1"), "0.100"); CHECK_FORMAT(g + Format::Precision(3), HNumber("10"), "10.000"); CHECK_FORMAT(g + Format::Precision(3), HNumber("100"), "100.000"); CHECK_FORMAT(g + Format::Precision(3), HNumber("1000"), "1000.000"); CHECK_FORMAT(g + Format::Precision(3), HNumber("10000"), "10000.000"); CHECK_FORMAT(g + Format::Precision(3), HNumber("100000"), "100000.000"); CHECK_FORMAT(g + Format::Precision(3), HNumber("1000000"), "1000000.000"); CHECK_FORMAT(g + Format::Precision(3), HNumber("10000000"), "10000000.000"); CHECK_FORMAT(g + Format::Precision(3), HNumber("100000000"), "100000000.000"); CHECK_FORMAT(g + Format::Precision(3), HNumber("1403.1977"), "1403.198"); CHECK_FORMAT(g + Format::Precision(3), HNumber("2604.1980"), "2604.198"); CHECK_FORMAT(g + Format::Precision(3), HNumber("2.47e4"), "24700.000"); } void test_op() { // Addition. CHECK(HNumber(0) + HNumber(0), "0"); CHECK(HNumber(1) + HNumber(0), "1"); CHECK(HNumber(1) + HNumber(1), "2"); CHECK(HNumber(1) + HNumber(2), "3"); CHECK(HNumber(1) + HNumber(10), "11"); CHECK(HNumber(1) + HNumber(100), "101"); CHECK(HNumber(1) + HNumber(1000), "1001"); CHECK(HNumber("NaN") + HNumber(1000), "NaN"); CHECK(HNumber(1000) + HNumber("NaN"), "NaN"); // Subtraction. CHECK(HNumber(0) - HNumber(0), "0"); CHECK(HNumber(1) - HNumber(0), "1"); CHECK(HNumber(1) - HNumber(2), "-1"); CHECK(HNumber("NaN") - HNumber(1000), "NaN"); CHECK(HNumber(1000) - HNumber("NaN"), "NaN"); // Division. CHECK(HNumber(1) / HNumber(2), "0.5"); CHECK(HNumber(1) / HMath::sin(PI), "NaN"); CHECK(HNumber("NaN") / HNumber(1000), "NaN"); CHECK(HNumber(1000) / HNumber("NaN"), "NaN"); // Division by zero. CHECK(HNumber(1) / HNumber(0), "NaN"); CHECK(HNumber(1) / HMath::sin(0), "NaN"); CHECK(HNumber(1) / HMath::sin(PI), "NaN"); CHECK(HNumber(1) / HMath::cos(PI/2), "NaN"); CHECK(HNumber(1) / HMath::tan(0), "NaN"); CHECK(HNumber(1) / HMath::tan(PI), "NaN"); CHECK(HNumber(1) / HMath::trunc("0.123"), "NaN"); CHECK(HNumber(1) / HMath::round("0.456"), "NaN"); CHECK(HNumber(1) / HMath::binomialPmf(1, 10, 0), "NaN"); CHECK_PRECISE(HNumber(1) / HNumber(3), "0.33333333333333333333333333333333333333333333333333"); CHECK_PRECISE(HNumber(2) / HNumber(3), "0.66666666666666666666666666666666666666666666666667"); CHECK_PRECISE(HNumber(1) / HNumber(7), "0.14285714285714285714285714285714285714285714285714"); CHECK_PRECISE(HNumber(2) / HNumber(7), "0.28571428571428571428571428571428571428571428571429"); CHECK_PRECISE(HNumber(3) / HNumber(7), "0.42857142857142857142857142857142857142857142857143"); CHECK_PRECISE(HNumber(4) / HNumber(7), "0.57142857142857142857142857142857142857142857142857"); CHECK_PRECISE(HNumber(1) / HNumber(9), "0.11111111111111111111111111111111111111111111111111"); // Multiplication. CHECK(HNumber(0)* HNumber(0), "0"); CHECK(HNumber("1.0")* HNumber("0.0"), "0"); CHECK(HNumber(1)* HNumber(1), "1"); CHECK(HNumber(3)* HNumber(-4), "-12"); CHECK(HNumber(-2)* HNumber(5), "-10"); CHECK(HNumber(6)* HNumber(7), "42"); CHECK(HNumber("1.5")* HNumber("1.5"), "2.25"); CHECK(HNumber("NaN") * HNumber(1000), "NaN"); CHECK(HNumber(1000) * HNumber("NaN"), "NaN"); } void test_functions() { CHECK(PI, "3.14159265358979323846"); CHECK_PRECISE(PI, "3.14159265358979323846264338327950288419716939937511"); CHECK(HMath::abs("NaN"), "NaN"); CHECK(HMath::abs("0"), "0"); CHECK(HMath::abs("1"), "1"); CHECK(HMath::abs("100"), "100"); CHECK(HMath::abs("-100"), "100"); CHECK(HMath::abs("-3.14159"), "3.14159"); CHECK(HMath::abs("-0.00000014159"), "0.00000014159"); CHECK(HMath::floor("NaN"), "NaN"); CHECK(HMath::floor("0"), "0"); CHECK(HMath::floor("5"), "5"); CHECK(HMath::floor("-5"), "-5"); CHECK(HMath::floor("3.14"), "3"); CHECK(HMath::floor("1.77"), "1"); CHECK(HMath::floor("-2.6041980"), "-3"); CHECK(HMath::floor("2.6041980"), "2"); CHECK(HMath::floor("0.000001"), "0"); CHECK(HMath::floor("-0.000001"), "-1"); CHECK(HMath::floor(HNumber(1) / 3 * 3), "1"); CHECK(HMath::ceil("NaN"), "NaN"); CHECK(HMath::ceil("0"), "0"); CHECK(HMath::ceil("5"), "5"); CHECK(HMath::ceil("-5"), "-5"); CHECK(HMath::ceil("3.14"), "4"); CHECK(HMath::ceil("1.77"), "2"); CHECK(HMath::ceil("-2.6041980"), "-2"); CHECK(HMath::ceil("2.6041980"), "3"); CHECK(HMath::ceil("0.000001"), "1"); CHECK(HMath::ceil("-0.000001"), "0"); CHECK(HMath::ceil(HMath::log(2, 128)), "7"); CHECK(HMath::gcd("NaN", "NaN"), "NaN"); CHECK(HMath::gcd("NaN", "5"), "NaN"); CHECK(HMath::gcd("5", "NaN"), "NaN"); CHECK(HMath::gcd("0", "0"), "0"); CHECK(HMath::gcd("0", "5"), "5"); CHECK(HMath::gcd("5", "0"), "5"); CHECK(HMath::gcd("0", "-5"), "5"); CHECK(HMath::gcd("-5", "0"), "5"); CHECK(HMath::gcd("9", "-27"), "9"); CHECK(HMath::gcd("99", "103"), "1"); CHECK(HMath::gcd("-102", "306"), "102"); CHECK(HMath::lcm("NaN", "NaN"), "NaN"); CHECK(HMath::lcm("NaN", "5"), "NaN"); CHECK(HMath::lcm("5", "NaN"), "NaN"); CHECK(HMath::lcm("0", "0"), "0"); CHECK(HMath::lcm("0", "5"), "0"); CHECK(HMath::lcm("5", "0"), "0"); CHECK(HMath::lcm("9", "-27"), "27"); CHECK(HMath::lcm("99", "103"), "10197"); CHECK(HMath::lcm("-102", "306"), "306"); CHECK(HMath::round("NaN"), "NaN"); CHECK(HMath::round("3.14"), "3"); CHECK(HMath::round("-1.77"), "-2"); CHECK(HMath::round("NaN", 3), "NaN"); CHECK(HMath::round("0.005", -3), "0"); CHECK(HMath::round("0.005", 2), "0"); CHECK(HMath::round("0.00000000055", 2), "0"); CHECK(HMath::round("3.14159", 4), "3.1416"); CHECK(HMath::round("3.14159", 3), "3.142"); CHECK(HMath::round("3.14159", 2), "3.14"); CHECK(HMath::round("3.14159", 1), "3.1"); CHECK(HMath::round("3.14159", 0), "3"); CHECK(HMath::round("-2.6041980", 4), "-2.6042"); CHECK(HMath::round("-2.6041980", 3), "-2.604"); CHECK(HMath::round("-2.6041980", 2), "-2.6"); CHECK(HMath::round("-2.6041980", 1), "-2.6"); CHECK(HMath::round("-2.6041980", 0), "-3"); CHECK(HMath::round("0.5", 0), "0"); CHECK(HMath::round("1.5", 0), "2"); CHECK(HMath::round("2.5", 0), "2"); CHECK(HMath::round("3.5", 0), "4"); CHECK(HMath::round("-0.5", 0), "0"); CHECK(HMath::round("-1.5", 0), "-2"); CHECK(HMath::trunc("NaN"), "NaN"); CHECK(HMath::trunc("0"), "0"); CHECK(HMath::trunc("3.14"), "3"); CHECK(HMath::trunc("1.77"), "1"); CHECK(HMath::trunc("NaN", 3), "NaN"); CHECK(HMath::trunc("0.00013", -3), "0"); CHECK(HMath::trunc("0.00013", 4), "0.0001"); CHECK(HMath::trunc("3.14159", 4), "3.1415"); CHECK(HMath::trunc("3.14159", 3), "3.141"); CHECK(HMath::trunc("3.14159", 2), "3.14"); CHECK(HMath::trunc("3.14159", 1), "3.1"); CHECK(HMath::trunc("3.14159", 0), "3"); CHECK(HMath::trunc("-2.6041980", 4), "-2.6041"); CHECK(HMath::trunc("-2.6041980", 3), "-2.604"); CHECK(HMath::trunc("-2.6041980", 2), "-2.6"); CHECK(HMath::trunc("-2.6041980", 1), "-2.6"); CHECK(HMath::trunc("-2.6041980", 0), "-2"); CHECK(HMath::trunc("-2.6041980", 999), "-2.604198"); CHECK(HMath::trunc("-2.6041980", -2), "0"); CHECK(HMath::integer("NaN"), "NaN"); CHECK(HMath::integer("0"), "0"); CHECK(HMath::integer("0.25"), "0"); CHECK(HMath::integer("0.85"), "0"); CHECK(HMath::integer("14.0377"), "14"); CHECK(HMath::integer("-0.25"), "0"); CHECK(HMath::integer("-0.85"), "0"); CHECK(HMath::integer("-14.0377"), "-14"); CHECK(HMath::frac("NaN"), "NaN"); CHECK(HMath::frac("0"), "0"); CHECK(HMath::frac("3.14159"), "0.14159"); CHECK(HMath::frac("0.14159"), "0.14159"); CHECK(HMath::frac("-3.14159"), "-0.14159"); CHECK(HMath::frac("-0.14159"), "-0.14159"); CHECK(HMath::sqrt("NaN"), "NaN"); CHECK(HMath::sqrt(-1), "NaN"); CHECK(HMath::sqrt(0), "0"); CHECK(HMath::sqrt(1), "1"); CHECK(HMath::sqrt(4), "2"); CHECK(HMath::sqrt(9), "3"); CHECK(HMath::sqrt(16), "4"); CHECK(HMath::sqrt("0.04"), "0.2"); CHECK(HMath::sqrt("0.09"), "0.3"); CHECK(HMath::sqrt("0.16"), "0.4"); CHECK_PRECISE(HMath::sqrt(2), "1.41421356237309504880168872420969807856967187537695"); CHECK_PRECISE(HMath::sqrt(3), "1.73205080756887729352744634150587236694280525381038"); CHECK_PRECISE(HMath::sqrt(5), "2.23606797749978969640917366873127623544061835961153"); CHECK_PRECISE(HMath::sqrt(7), "2.64575131106459059050161575363926042571025918308245"); CHECK_PRECISE(HMath::sqrt(8), "2.82842712474619009760337744841939615713934375075390"); CHECK_PRECISE(HMath::sqrt(10), "3.16227766016837933199889354443271853371955513932522"); CHECK_PRECISE(HMath::sqrt(11), "3.31662479035539984911493273667068668392708854558935"); CHECK_PRECISE(HMath::sqrt(12), "3.46410161513775458705489268301174473388561050762076"); CHECK_PRECISE(HMath::sqrt(13), "3.60555127546398929311922126747049594625129657384525"); CHECK_PRECISE(HMath::sqrt(14), "3.74165738677394138558374873231654930175601980777873"); CHECK_PRECISE(HMath::sqrt(15), "3.87298334620741688517926539978239961083292170529159"); CHECK_PRECISE(HMath::sqrt(17), "4.12310562561766054982140985597407702514719922537362"); CHECK_PRECISE(HMath::sqrt(18), "4.24264068711928514640506617262909423570901562613084"); CHECK_PRECISE(HMath::sqrt(19), "4.35889894354067355223698198385961565913700392523244"); CHECK_PRECISE(HMath::sqrt(20), "4.47213595499957939281834733746255247088123671922305"); CHECK(HMath::cbrt("NaN"), "NaN"); CHECK(HMath::cbrt(0), "0"); CHECK(HMath::cbrt(1), "1"); CHECK(HMath::cbrt(-1), "-1"); CHECK(HMath::cbrt(8), "2"); CHECK(HMath::cbrt(-8), "-2"); CHECK(HMath::cbrt(27), "3"); CHECK(HMath::cbrt(-27), "-3"); CHECK(HMath::cbrt(64), "4"); CHECK(HMath::cbrt(-64), "-4"); CHECK(HMath::cbrt("0.008"), "0.2"); CHECK(HMath::cbrt("-0.008"), "-0.2"); CHECK(HMath::cbrt("0.027"), "0.3"); CHECK(HMath::cbrt("-0.027"), "-0.3"); CHECK(HMath::cbrt("0.064"), "0.4"); CHECK(HMath::cbrt("-0.064"), "-0.4"); CHECK_PRECISE(HMath::cbrt(2), "1.25992104989487316476721060727822835057025146470151"); CHECK_PRECISE(HMath::cbrt(3), "1.44224957030740838232163831078010958839186925349935"); CHECK_PRECISE(HMath::cbrt(-20), "-2.71441761659490657151808946967948920480510776948910"); CHECK(HMath::sgn("NaN"), "NaN"); CHECK(HMath::sgn(0), "0"); CHECK(HMath::sgn(1), "1"); CHECK(HMath::sgn(-1), "-1"); CHECK(HMath::sgn(2), "1"); CHECK(HMath::sgn(-2), "-1"); CHECK(HMath::factorial("NaN"), "NaN"); CHECK(HMath::factorial(-1), "NaN"); CHECK(HMath::factorial(0), "1"); CHECK(HMath::factorial(1), "1"); CHECK(HMath::factorial(2), "2"); CHECK(HMath::factorial(3), "6"); CHECK(HMath::factorial(4), "24"); CHECK(HMath::factorial(5), "120"); CHECK(HMath::factorial(6), "720"); CHECK(HMath::factorial(7), "5040"); CHECK(HMath::factorial(8), "40320"); CHECK_PRECISE(HMath::factorial("5.23"), "178.50732778544229114185259335979946974446422321576241"); CHECK(HMath::factorial("-5"), "NaN"); CHECK(HMath::factorial("NaN", "NaN"), "NaN"); CHECK(HMath::factorial("NaN", 7), "NaN"); CHECK(HMath::factorial(8, "NaN"), "NaN"); CHECK(HMath::factorial(8, 0), "0"); CHECK(HMath::factorial(8, 6), "336"); CHECK(HMath::factorial(8, 7), "56"); CHECK(HMath::factorial(8, 8), "8"); CHECK(HMath::nCr("NaN", "NaN"), "NaN"); CHECK(HMath::nCr("NaN", 5), "NaN"); CHECK(HMath::nCr(5, "NaN"), "NaN"); CHECK(HMath::nCr(21, -1), "0"); CHECK(HMath::nCr(-21, 2), "231"); CHECK(HMath::nCr(21, 0), "1"); CHECK(HMath::nCr(21, 1), "21"); CHECK(HMath::nCr(21, 2), "210"); CHECK(HMath::nCr(21, 3), "1330"); CHECK(HMath::nCr(21, 19), "210"); CHECK(HMath::nCr(21, 20), "21"); CHECK(HMath::nCr(21, 21), "1"); CHECK(HMath::nCr(21, 22), "0"); CHECK(HMath::nCr(0, 0), "1"); CHECK(HMath::nPr("NaN", "NaN"), "NaN"); CHECK(HMath::nPr("NaN", 5), "NaN"); CHECK(HMath::nPr(5, "NaN"), "NaN"); CHECK(HMath::nPr(21, 22), "0"); CHECK(HMath::nPr(-21, 2), "462"); CHECK(HMath::nPr(21, -1), "0.04545454545454545455"); CHECK(HMath::nPr(0, 0), "1"); CHECK(HMath::nPr(21, 0), "1"); CHECK(HMath::nPr(21, 1), "21"); CHECK(HMath::nPr(21, 2), "420"); CHECK(HMath::nPr(21, 3), "7980"); CHECK(HMath::nPr(21, 4), "143640"); CHECK(HMath::nPr(21, 5), "2441880"); CHECK(HMath::nPr(21, 6), "39070080"); CHECK(HMath::nPr(21, 7), "586051200"); CHECK(HMath::raise("NaN", "NaN"), "NaN"); CHECK(HMath::raise("NaN", "0"), "NaN"); CHECK(HMath::raise("-1", "NaN"), "NaN"); CHECK(HMath::raise("0", "0"), "NaN"); CHECK(HMath::raise(10, -3), "0.001"); CHECK(HMath::raise(10, -2), "0.01"); CHECK(HMath::raise(10, -1), "0.1"); CHECK(HMath::raise(10, 0), "1"); CHECK(HMath::raise(10, 1), "10"); CHECK(HMath::raise(10, 2), "100"); CHECK(HMath::raise(10, 3), "1000"); CHECK(HMath::raise(10, 4), "10000"); CHECK(HMath::raise("2", "2"), "4"); CHECK(HMath::raise("3", "3"), "27"); CHECK(HMath::raise("4", "4"), "256"); CHECK(HMath::raise("-27", HNumber("1") / HNumber("3")), "-3"); CHECK(HMath::raise("-27", HNumber("-1") / HNumber("3")), "-0.33333333333333333333"); CHECK(HMath::raise("-1", HNumber("1") / HNumber("7")), "-1"); CHECK(HMath::raise("-1", HNumber("2") / HNumber("3")), "1"); CHECK(HMath::raise("-8", HNumber("2") / HNumber("3")), "4"); CHECK(HMath::raise("-13", HNumber("1") / HNumber("3")), "-2.3513346877207574895"); CHECK(HMath::raise("-13", HNumber("1") / HNumber("9")), "-1.32975454563978597291"); CHECK(HMath::raise("-13", HNumber("1") / HNumber("27")), "-1.0996567925533755264"); CHECK(HMath::raise("-13", HNumber("1") / HNumber("3.123")), "2.27347485100383238372"); CHECK(HMath::raise("-13", HNumber("1") / HNumber("9.123")), "1.32465488702830785593"); CHECK(HMath::raise("-13", HNumber("1") / HNumber("27.123")), "1.09918315510346486963"); CHECK(HMath::raise("-2", HMath::pi()), "NaN"); CHECK_PRECISE(HMath::raise("2", "0.1"), "1.07177346253629316421300632502334202290638460497756"); CHECK_PRECISE(HMath::raise("2", "0.2"), "1.14869835499703500679862694677792758944385088909780"); CHECK_PRECISE(HMath::raise("2", "0.3"), "1.23114441334491628449939306916774310987613776110082"); CHECK(HMath::exp("NaN"), "NaN"); CHECK(HMath::exp("0"), "1"); CHECK_PRECISE(HMath::exp("0.1"), "1.10517091807564762481170782649024666822454719473752"); CHECK_PRECISE(HMath::exp("0.2"), "1.22140275816016983392107199463967417030758094152050"); CHECK_PRECISE(HMath::exp("0.3"), "1.34985880757600310398374431332800733037829969735937"); CHECK_PRECISE(HMath::exp("0.4"), "1.49182469764127031782485295283722228064328277393743"); CHECK_PRECISE(HMath::exp("0.5"), "1.64872127070012814684865078781416357165377610071015"); CHECK_PRECISE(HMath::exp("0.6"), "1.82211880039050897487536766816286451338223880854644"); CHECK_PRECISE(HMath::exp("0.7"), "2.01375270747047652162454938858306527001754239414587"); CHECK_PRECISE(HMath::exp("0.8"), "2.22554092849246760457953753139507675705363413504848"); CHECK_PRECISE(HMath::exp("0.9"), "2.45960311115694966380012656360247069542177230644008"); CHECK_PRECISE(HMath::exp("1.0"), "2.71828182845904523536028747135266249775724709369996"); CHECK_PRECISE(HMath::exp("100"), "26881171418161354484126255515800135873611118.77374192241519160861528028703490956400000000000000"/*"91415887109722"*/); CHECK(HMath::binomialPmf("NaN", "NaN", "NaN"), "NaN"); CHECK(HMath::binomialPmf("NaN", "NaN", "0.5"), "NaN"); CHECK(HMath::binomialPmf("NaN", "10", "NaN"), "NaN"); CHECK(HMath::binomialPmf("NaN", "10", "0.5"), "NaN"); CHECK(HMath::binomialPmf("5", "NaN", "NaN"), "NaN"); CHECK(HMath::binomialPmf("5", "NaN", "0.5"), "NaN"); CHECK(HMath::binomialPmf("5", "10", "NaN"), "NaN"); CHECK(HMath::binomialPmf("5", "10", "0.5"), "0.24609375"); CHECK(HMath::binomialPmf("-5", "10", "0.5"), "0"); CHECK_PRECISE(HMath::binomialPmf("5", "10", "0.5"), "0.24609375000000000000000000000000000000000000000000"); CHECK(HMath::binomialCdf("NaN", "NaN", "NaN"), "NaN"); CHECK(HMath::binomialCdf("NaN", "NaN", "0.5"), "NaN"); CHECK(HMath::binomialCdf("NaN", "10", "NaN"), "NaN"); CHECK(HMath::binomialCdf("NaN", "10", "0.5"), "NaN"); CHECK(HMath::binomialCdf("5", "NaN", "NaN"), "NaN"); CHECK(HMath::binomialCdf("5", "NaN", "0.5"), "NaN"); CHECK(HMath::binomialCdf("5", "10", "NaN"), "NaN"); CHECK(HMath::binomialCdf("5", "10", "0.5"), "0.623046875"); CHECK(HMath::binomialCdf("-5", "10", "0.5"), "0"); CHECK_PRECISE(HMath::binomialCdf("5", "10", "0.5"), "0.62304687500000000000000000000000000000000000000000"); CHECK(HMath::binomialMean("NaN", "NaN"), "NaN"); CHECK(HMath::binomialMean("NaN", "0.5"), "NaN"); CHECK(HMath::binomialMean("10", "NaN"), "NaN"); CHECK(HMath::binomialMean("10", "0.5"), "5"); CHECK(HMath::binomialMean("-10", "0.5"), "NaN"); CHECK_PRECISE(HMath::binomialMean("10", "0.5"), "5.00000000000000000000000000000000000000000000000000"); CHECK(HMath::binomialVariance("NaN", "NaN"), "NaN"); CHECK(HMath::binomialVariance("NaN", "0.5"), "NaN"); CHECK(HMath::binomialVariance("10", "NaN"), "NaN"); CHECK(HMath::binomialVariance("10", "0.5"), "2.5"); CHECK(HMath::binomialVariance("-10", "0.5"), "NaN"); CHECK_PRECISE(HMath::binomialVariance("10", "0.5"), "2.50000000000000000000000000000000000000000000000000"); CHECK(HMath::hypergeometricPmf("NaN", "NaN", "NaN", "NaN"), "NaN"); CHECK(HMath::hypergeometricPmf("NaN", "NaN", "NaN", "5"), "NaN"); CHECK(HMath::hypergeometricPmf("NaN", "NaN", "10", "NaN"), "NaN"); CHECK(HMath::hypergeometricPmf("NaN", "NaN", "10", "5"), "NaN"); CHECK(HMath::hypergeometricPmf("1", "15", "NaN", "NaN"), "NaN"); CHECK(HMath::hypergeometricPmf("1", "15", "NaN", "5"), "NaN"); CHECK(HMath::hypergeometricPmf("1", "15", "10", "NaN"), "NaN"); CHECK(HMath::hypergeometricPmf("-1", "15", "10", "5"), "0"); CHECK(HMath::hypergeometricPmf("1", "15", "10", "5"), "0.01665001665001665002"); CHECK_PRECISE(HMath::hypergeometricPmf("1", "15", "10", "5"), "0.01665001665001665001665001665001665001665001665002"); CHECK(HMath::hypergeometricCdf("NaN", "NaN", "NaN", "NaN"), "NaN"); CHECK(HMath::hypergeometricCdf("NaN", "NaN", "NaN", "5"), "NaN"); CHECK(HMath::hypergeometricCdf("NaN", "NaN", "10", "NaN"), "NaN"); CHECK(HMath::hypergeometricCdf("NaN", "NaN", "10", "5"), "NaN"); CHECK(HMath::hypergeometricCdf("1", "15", "NaN", "NaN"), "NaN"); CHECK(HMath::hypergeometricCdf("1", "15", "NaN", "5"), "NaN"); CHECK(HMath::hypergeometricCdf("1", "15", "10", "NaN"), "NaN"); CHECK(HMath::hypergeometricCdf("-1", "15", "10", "5"), "0"); CHECK(HMath::hypergeometricCdf("1", "15", "10", "5"), "0.01698301698301698302"); CHECK_PRECISE(HMath::hypergeometricCdf("1", "15", "10", "5"), "0.01698301698301698301698301698301698301698301698302"); CHECK(HMath::hypergeometricMean("NaN", "NaN", "NaN"), "NaN"); CHECK(HMath::hypergeometricMean("NaN", "NaN", "5"), "NaN"); CHECK(HMath::hypergeometricMean("15", "10", "NaN"), "NaN"); CHECK(HMath::hypergeometricMean("15", "10", "5"), "3.33333333333333333333"); CHECK_PRECISE(HMath::hypergeometricMean("15", "10", "5"), "3.33333333333333333333333333333333333333333333333333"); CHECK(HMath::hypergeometricVariance("NaN", "NaN", "NaN"), "NaN"); CHECK(HMath::hypergeometricVariance("NaN", "NaN", "5"), "NaN"); CHECK(HMath::hypergeometricVariance("15", "10", "NaN"), "NaN"); CHECK(HMath::hypergeometricVariance("15", "10", "5"), "0.79365079365079365079"); CHECK_PRECISE(HMath::hypergeometricVariance("15", "10", "5"), "0.79365079365079365079365079365079365079365079365079"); CHECK(HMath::poissonPmf("NaN", "NaN"), "NaN"); CHECK(HMath::poissonPmf("NaN", "5"), "NaN"); CHECK(HMath::poissonPmf("2", "NaN"), "NaN"); CHECK(HMath::poissonPmf("-2", "5"), "0"); CHECK(HMath::poissonPmf("2", "5"), "0.08422433748856833871"); CHECK_PRECISE(HMath::poissonPmf("2", "5"), "0.08422433748856833870795060528935530311061981284194"); CHECK(HMath::poissonCdf("NaN", "NaN"), "NaN"); CHECK(HMath::poissonCdf("NaN", "5"), "NaN"); CHECK(HMath::poissonCdf("2", "NaN"), "NaN"); CHECK(HMath::poissonCdf("-2", "5"), "0"); CHECK(HMath::poissonCdf("2", "5"), "0.12465201948308114129"); CHECK_PRECISE(HMath::poissonCdf("2", "5"), "0.12465201948308114128776689582824584860371732300607"); CHECK(HMath::poissonMean("NaN"), "NaN"); CHECK(HMath::poissonMean("5"), "5"); CHECK(HMath::poissonMean("-5"), "NaN"); CHECK_PRECISE(HMath::poissonMean("5"), "5.00000000000000000000000000000000000000000000000000"); CHECK(HMath::poissonVariance("NaN"), "NaN"); CHECK(HMath::poissonVariance("5"), "5"); CHECK(HMath::poissonVariance("-5"), "NaN"); CHECK_PRECISE(HMath::poissonVariance("5"), "5.00000000000000000000000000000000000000000000000000"); CHECK(HMath::ln("NaN"), "NaN"); CHECK(HMath::ln("-0.1"), "NaN"); CHECK(HMath::ln("0"), "NaN"); CHECK(HMath::ln("0.00000000001"), "-25.3284360229345025242"); CHECK_PRECISE(HMath::ln("0.1"), "-2.30258509299404568401799145468436420760110148862877"); CHECK_PRECISE(HMath::ln("0.2"), "-1.60943791243410037460075933322618763952560135426852"); CHECK_PRECISE(HMath::ln("0.3"), "-1.20397280432593599262274621776183850295361093080602"); CHECK_PRECISE(HMath::ln("0.4"), "-0.91629073187415506518352721176801107145010121990826"); CHECK_PRECISE(HMath::ln("0.5"), "-0.69314718055994530941723212145817656807550013436026"); CHECK_PRECISE(HMath::ln("0.6"), "-0.51082562376599068320551409630366193487811079644577"); CHECK_PRECISE(HMath::ln("0.7"), "-0.35667494393873237891263871124118447796401675904691"); CHECK_PRECISE(HMath::ln("0.8"), "-0.22314355131420975576629509030983450337460108554801"); CHECK_PRECISE(HMath::ln("0.9"), "-0.10536051565782630122750098083931279830612037298327"); CHECK_PRECISE(HMath::ln("1.0"), "0"); CHECK_PRECISE(HMath::ln("1.1"), "0.09531017980432486004395212328076509222060536530864"); CHECK_PRECISE(HMath::ln("1.2"), "0.18232155679395462621171802515451463319738933791449"); CHECK_PRECISE(HMath::ln("1.3"), "0.26236426446749105203549598688095439720416645613143"); CHECK_PRECISE(HMath::ln("1.4"), "0.33647223662121293050459341021699209011148337531334"); CHECK_PRECISE(HMath::ln("1.5"), "0.40546510810816438197801311546434913657199042346249"); CHECK_PRECISE(HMath::ln("1.6"), "0.47000362924573555365093703114834206470089904881225"); CHECK_PRECISE(HMath::ln("1.7"), "0.53062825106217039623154316318876232798710152395697"); CHECK_PRECISE(HMath::ln("1.8"), "0.58778666490211900818973114061886376976937976137698"); CHECK_PRECISE(HMath::ln("1.9"), "0.64185388617239477599103597720348932963627777267036"); CHECK_PRECISE(HMath::ln("2.0"), "0.69314718055994530941723212145817656807550013436026"); CHECK_PRECISE(HMath::ln("3.0"), "1.09861228866810969139524523692252570464749055782275"); CHECK_PRECISE(HMath::ln("4.0"), "1.38629436111989061883446424291635313615100026872051"); CHECK_PRECISE(HMath::ln("100"), "4.60517018598809136803598290936872841520220297725755"); CHECK(HMath::lg("NaN"), "NaN"); CHECK(HMath::lg("-1"), "NaN"); CHECK(HMath::lg("0"), "NaN"); CHECK(HMath::lg("1e-5"), "-5"); CHECK(HMath::lg("1e-4"), "-4"); CHECK(HMath::lg("1e-3"), "-3"); CHECK(HMath::lg("10"), "1"); CHECK(HMath::lg("100"), "2"); CHECK(HMath::lg("1000"), "3"); CHECK(HMath::lg("10000"), "4"); CHECK(HMath::lg("1e5"), "5"); CHECK(HMath::lg("1e6"), "6"); CHECK(HMath::lg("1e7"), "7"); CHECK(HMath::lg("1e8"), "8"); CHECK(HMath::lg("1e9"), "9"); CHECK(HMath::lg("1e10"), "10"); CHECK(HMath::lg("0.00000000001"), "-11"); CHECK(HMath::lb("NaN"), "NaN"); CHECK(HMath::lb("-1"), "NaN"); CHECK(HMath::lb("0"), "NaN"); CHECK(HMath::lb("1"), "0"); CHECK(HMath::lb("2"), "1"); CHECK(HMath::lb("4"), "2"); CHECK(HMath::lb("8"), "3"); CHECK(HMath::lb("16"), "4"); CHECK(HMath::lb("32"), "5"); CHECK(HMath::lb("0.00000000001"), "-36.54120904376098582657"); CHECK(HMath::log("NaN", "NaN"), "NaN"); CHECK(HMath::log("1", "NaN"), "NaN"); CHECK(HMath::log("NaN", "1"), "NaN"); CHECK(HMath::log("123", "1234"), "1.47916531845224081828"); CHECK(HMath::log("0.123", "0.1234"), "0.99845065797473594741"); CHECK(HMath::log("0.00000000001", "0.00000000000001"), "1.27272727272727272727"); CHECK(HMath::sin("NaN"), "NaN"); CHECK(HMath::sin("0"), "0"); CHECK(HMath::sin(PI), "0"); CHECK(HMath::sin(PI*2), "0"); CHECK(HMath::sin(PI*(-1)), "0"); CHECK(HMath::sin(PI*(-3)), "0"); CHECK(HMath::sin(PI*6/3), "0"); CHECK(HMath::sin(PI*9/3), "0"); CHECK(HMath::sin(PI/2), "1"); CHECK(HMath::sin(PI/4), "0.7071067811865475244"); CHECK(HMath::sin(PI/3), "0.86602540378443864676"); CHECK(HMath::sin(PI*2/3), "0.86602540378443864676"); CHECK(HMath::sin(PI*4/3), "-0.86602540378443864676"); CHECK(HMath::sin(PI*5/3), "-0.86602540378443864676"); CHECK(HMath::sin(PI*7/3), "0.86602540378443864676"); CHECK_PRECISE(HMath::sin("0.0"), "0"); CHECK_PRECISE(HMath::sin("0.1"), "0.09983341664682815230681419841062202698991538801798"); CHECK_PRECISE(HMath::sin("0.2"), "0.19866933079506121545941262711838975037020672954021"); CHECK_PRECISE(HMath::sin("0.3"), "0.29552020666133957510532074568502737367783211174262"); CHECK_PRECISE(HMath::sin("0.4"), "0.38941834230865049166631175679570526459306018344396"); CHECK_PRECISE(HMath::sin("0.5"), "0.47942553860420300027328793521557138808180336794060"); CHECK_PRECISE(HMath::sin("0.6"), "0.56464247339503535720094544565865790710988808499415"); CHECK_PRECISE(HMath::sin("0.7"), "0.64421768723769105367261435139872018306581384457369"); CHECK_PRECISE(HMath::sin("0.8"), "0.71735609089952276162717461058138536619278523779142"); CHECK_PRECISE(HMath::sin("0.9"), "0.78332690962748338846138231571354862314014792572031"); CHECK_PRECISE(HMath::sin("1.0"), "0.84147098480789650665250232163029899962256306079837"); CHECK_PRECISE(HMath::sin("2.0"), "0.90929742682568169539601986591174484270225497144789"); CHECK_PRECISE(HMath::sin("3.0"), "0.14112000805986722210074480280811027984693326425227"); CHECK_PRECISE(HMath::sin("4.0"), "-0.75680249530792825137263909451182909413591288733647"); CHECK_PRECISE(HMath::sin("5.0"), "-0.95892427466313846889315440615599397335246154396460"); CHECK_PRECISE(HMath::sin("1e22"), "-0.85220084976718880177270589375302936826176215041004"); CHECK(HMath::cos("NaN"), "NaN"); CHECK(HMath::cos(PI/2), "0"); CHECK(HMath::cos(PI*3/2), "0"); CHECK(HMath::cos(PI/2*(-1)*9), "0"); CHECK(HMath::cos(0), "1"); CHECK(HMath::cos(PI*6/3), "1"); CHECK(HMath::cos(PI*9/3), "-1"); CHECK(HMath::cos(PI/1), "-1"); CHECK(HMath::cos(PI/3), "0.5"); CHECK(HMath::cos(PI*2/3), "-0.5"); CHECK(HMath::cos(PI*4/3), "-0.5"); CHECK(HMath::cos(PI*5/3), "0.5"); CHECK(HMath::cos(PI*7/3), "0.5"); CHECK(HMath::cos(PI/4), "0.7071067811865475244"); CHECK_PRECISE(HMath::cos("0.0"), "1.00000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::cos("0.1"), "0.99500416527802576609556198780387029483857622541508"); CHECK_PRECISE(HMath::cos("0.2"), "0.98006657784124163112419651674816887739352436080657"); CHECK_PRECISE(HMath::cos("0.3"), "0.95533648912560601964231022756804989824421408263204"); CHECK_PRECISE(HMath::cos("0.4"), "0.92106099400288508279852673205180161402585956931985"); CHECK_PRECISE(HMath::cos("0.5"), "0.87758256189037271611628158260382965199164519710974"); CHECK_PRECISE(HMath::cos("0.6"), "0.82533561490967829724095249895537603887809103918847"); CHECK_PRECISE(HMath::cos("0.7"), "0.76484218728448842625585999019186490926821055037370"); CHECK_PRECISE(HMath::cos("0.8"), "0.69670670934716542092074998164232492610178601370806"); CHECK_PRECISE(HMath::cos("0.9"), "0.62160996827066445648471615140713350872176136659124"); CHECK_PRECISE(HMath::cos("1.0"), "0.54030230586813971740093660744297660373231042061792"); CHECK_PRECISE(HMath::cos("2.0"), "-0.41614683654714238699756822950076218976600077107554"); CHECK_PRECISE(HMath::cos("3.0"), "-0.98999249660044545727157279473126130239367909661559"); CHECK_PRECISE(HMath::cos("4.0"), "-0.65364362086361191463916818309775038142413359664622"); CHECK_PRECISE(HMath::cos("1e22"), "0.52321478539513894549759447338470949214091997243939"); CHECK(HMath::tan("NaN"), "NaN"); CHECK(HMath::tan(PI/2), "NaN"); CHECK(HMath::tan(PI/2*3), "NaN"); CHECK(HMath::tan(PI/2*5), "NaN"); CHECK(HMath::tan(PI/2*(-3)), "NaN"); CHECK(HMath::tan(PI/2*(-5)), "NaN"); CHECK(HMath::tan(PI/1), "0"); CHECK(HMath::tan(PI*(-3)), "0"); CHECK(HMath::tan(PI*11), "0"); CHECK(HMath::tan(PI/4), "1"); CHECK(HMath::tan(PI/3), "1.73205080756887729353"); CHECK_PRECISE(HMath::tan("0.0"), "0"); CHECK_PRECISE(HMath::tan("0.1"), "0.10033467208545054505808004578111153681900480457644"); CHECK_PRECISE(HMath::tan("0.2"), "0.20271003550867248332135827164753448262687566965163"); CHECK_PRECISE(HMath::tan("0.3"), "0.30933624960962323303530367969829466725781590680046"); CHECK_PRECISE(HMath::tan("0.4"), "0.42279321873816176198163542716529033394198977271569"); CHECK_PRECISE(HMath::tan("0.5"), "0.54630248984379051325517946578028538329755172017979"); CHECK_PRECISE(HMath::tan("0.6"), "0.68413680834169231707092541746333574524265408075678"); CHECK_PRECISE(HMath::tan("0.7"), "0.84228838046307944812813500221293771718722125080420"); CHECK_PRECISE(HMath::tan("0.8"), "1.02963855705036401274636117282036528416821960677231"); CHECK_PRECISE(HMath::tan("0.9"), "1.26015821755033913713457548539574847783362583439629"); CHECK_PRECISE(HMath::tan("1.0"), "1.55740772465490223050697480745836017308725077238152"); CHECK_PRECISE(HMath::tan("2.0"), "-2.18503986326151899164330610231368254343201774622766"); CHECK_PRECISE(HMath::tan("3.0"), "-0.14254654307427780529563541053391349322609228490180"); CHECK_PRECISE(HMath::tan("4.0"), "1.15782128234957758313734241826732392311976276736714"); CHECK(HMath::cot("NaN"), "NaN"); CHECK(HMath::cot(0), "NaN"); CHECK(HMath::cot(PI), "NaN"); CHECK(HMath::cot(PI*2), "NaN"); CHECK(HMath::cot(PI*3), "NaN"); CHECK(HMath::cot(PI*(-1)), "NaN"); CHECK(HMath::cot(PI*(-2)), "NaN"); CHECK(HMath::cot(PI*(-3)), "NaN"); CHECK(HMath::cot(PI/2), "0"); CHECK(HMath::cot(PI/2*3), "0"); CHECK(HMath::cot(PI/2*5), "0"); CHECK(HMath::cot(PI/(-2)), "0"); CHECK(HMath::cot(PI/(-2)*3), "0"); CHECK(HMath::cot(PI/(-2)*5), "0"); CHECK_PRECISE(HMath::cot("0.1"), "9.96664442325923785979411268927059390763024832915145"); CHECK_PRECISE(HMath::cot("0.2"), "4.93315487558689365736801632174474118540562176228750"); CHECK_PRECISE(HMath::cot("0.3"), "3.23272814376582751371392053451257979612306377207793"); CHECK_PRECISE(HMath::cot("0.4"), "2.36522242003911058702332902504860335138937304631794"); CHECK_PRECISE(HMath::cot("0.5"), "1.83048772171245191926801943896881662375810794801613"); CHECK_PRECISE(HMath::cot("0.6"), "1.46169594707810214033930842740714256443262393263873"); CHECK_PRECISE(HMath::cot("0.7"), "1.18724183212667935367236269369115744209994867903861"); CHECK_PRECISE(HMath::cot("0.8"), "0.97121460065047441252084679894165650872369163680112"); CHECK_PRECISE(HMath::cot("0.9"), "0.79355114784231712550449309982343541572162687887550"); CHECK_PRECISE(HMath::cot("1.0"), "0.64209261593433070300641998659426562023027811391817"); CHECK_PRECISE(HMath::cot("2.0"), "-0.45765755436028576375027741043204727642848632923167"); CHECK_PRECISE(HMath::cot("3.0"), "-7.01525255143453346942855137952647657829310335209635"); CHECK_PRECISE(HMath::cot("4.0"), "0.86369115445061661394651434594081763350176570849799"); CHECK(HMath::sec("NaN"), "NaN"); CHECK(HMath::sec(0), "1"); CHECK(HMath::sec(PI), "-1"); CHECK(HMath::sec(PI*2), "1"); CHECK(HMath::sec(PI*3), "-1"); CHECK(HMath::sec(PI*(-1)), "-1"); CHECK(HMath::sec(PI*(-2)), "1"); CHECK(HMath::sec(PI*(-3)), "-1"); CHECK(HMath::sec(PI/2), "NaN"); CHECK(HMath::sec(PI/2*3), "NaN"); CHECK(HMath::sec(PI/2*5), "NaN"); CHECK(HMath::sec(PI/(-2)), "NaN"); CHECK(HMath::sec(PI/(-2)*3), "NaN"); CHECK(HMath::sec(PI/(-2)*5), "NaN"); CHECK_PRECISE(HMath::sec("0.1"), "1.00502091840045542846511410131163581939665289709269"); CHECK_PRECISE(HMath::sec("0.2"), "1.02033884494119268979243277684919018946197757380999"); CHECK_PRECISE(HMath::sec("0.3"), "1.04675160153808560093279084558703692841456893499328"); CHECK_PRECISE(HMath::sec("0.4"), "1.08570442838323870311392995515876310121797526730283"); CHECK_PRECISE(HMath::sec("0.5"), "1.13949392732454912231332776820494992842372524604900"); CHECK_PRECISE(HMath::sec("0.6"), "1.21162831451231670461455512137241473057527998567989"); CHECK_PRECISE(HMath::sec("0.7"), "1.30745925973359386987467283530531145422836345495873"); CHECK_PRECISE(HMath::sec("0.8"), "1.43532419967223980049695240816284402319218304405383"); CHECK_PRECISE(HMath::sec("0.9"), "1.60872581046604951302401286230639310432053967212693"); CHECK_PRECISE(HMath::sec("1.0"), "1.85081571768092561791175324139865019347039665509401"); CHECK_PRECISE(HMath::sec("2.0"), "-2.40299796172238098975460040142006622624512109315453"); CHECK_PRECISE(HMath::sec("3.0"), "-1.01010866590799375130303648146319295518501902819060"); CHECK_PRECISE(HMath::sec("4.0"), "-1.52988565646639757462951092293735504703880002436905"); CHECK(HMath::csc("NaN"), "NaN"); CHECK(HMath::csc(0), "NaN"); CHECK(HMath::csc(PI), "NaN"); CHECK(HMath::csc(PI*2), "NaN"); CHECK(HMath::csc(PI*3), "NaN"); CHECK(HMath::csc(PI*(-1)), "NaN"); CHECK(HMath::csc(PI*(-2)), "NaN"); CHECK(HMath::csc(PI*(-3)), "NaN"); CHECK(HMath::csc(PI/2), "1"); CHECK(HMath::csc(PI/2*3), "-1"); CHECK(HMath::csc(PI/2*5), "1"); CHECK(HMath::csc(PI/(-2)), "-1"); CHECK(HMath::csc(PI/(-2)*3), "1"); CHECK(HMath::csc(PI/(-2)*5), "-1"); CHECK_PRECISE(HMath::csc("0.1"), "10.01668613163477664870635254208068373689462246452006"); CHECK_PRECISE(HMath::csc("0.2"), "5.03348954767234420242609636752585272222462656686394"); CHECK_PRECISE(HMath::csc("0.3"), "3.38386336182412258496047655147742034395467222595556"); CHECK_PRECISE(HMath::csc("0.4"), "2.56793245554778307034468729669613783401624871596957"); CHECK_PRECISE(HMath::csc("0.5"), "2.08582964293348818577250167545929030196230958681696"); CHECK_PRECISE(HMath::csc("0.6"), "1.77103219668772537337461210710543723169043983943920"); CHECK_PRECISE(HMath::csc("0.7"), "1.55227032695710391198997364095492783063640855362864"); CHECK_PRECISE(HMath::csc("0.8"), "1.39400781938863617450248222610694684266568140951681"); CHECK_PRECISE(HMath::csc("0.9"), "1.27660621345889549601564565223201364314354454128779"); CHECK_PRECISE(HMath::csc("1.0"), "1.18839510577812121626159945237455100352782983409796"); CHECK_PRECISE(HMath::csc("2.0"), "1.09975017029461646675669739702631289665876444314985"); CHECK_PRECISE(HMath::csc("3.0"), "7.08616739573718591821753227246127986736644022513951"); CHECK_PRECISE(HMath::csc("4.0"), "-1.32134870881090237769679175637286490993025203772967"); CHECK(HMath::arctan("NaN"), "NaN"); CHECK(HMath::arctan("0.10033467208545054505808004578111153681900480457644"), "0.1"); CHECK(HMath::arctan("0.20271003550867248332135827164753448262687566965163"), "0.2"); CHECK(HMath::arctan("0.30933624960962323303530367969829466725781590680046"), "0.3"); CHECK(HMath::arctan("0.42279321873816176198163542716529033394198977271569"), "0.4"); CHECK(HMath::arctan("0.54630248984379051325517946578028538329755172017979"), "0.5"); CHECK(HMath::arctan("0.68413680834169231707092541746333574524265408075678"), "0.6"); CHECK(HMath::arctan("0.84228838046307944812813500221293771718722125080420"), "0.7"); CHECK(HMath::arctan("1.02963855705036401274636117282036528416821960677231"), "0.8"); CHECK(HMath::arctan("1.26015821755033913713457548539574847783362583439629"), "0.9"); CHECK(HMath::arctan("1.55740772465490223050697480745836017308725077238152"), "1"); CHECK_PRECISE(HMath::arctan("0.0"), "0"); CHECK_PRECISE(HMath::arctan("0.1"), "0.09966865249116202737844611987802059024327832250431"); CHECK_PRECISE(HMath::arctan("0.2"), "0.19739555984988075837004976519479029344758510378785"); CHECK_PRECISE(HMath::arctan("0.3"), "0.29145679447786709199560462143289119350316759901207"); CHECK_PRECISE(HMath::arctan("0.4"), "0.38050637711236488630358791681043310449740571365810"); CHECK_PRECISE(HMath::arctan("0.5"), "0.46364760900080611621425623146121440202853705428612"); CHECK_PRECISE(HMath::arctan("0.6"), "0.54041950027058415544357836460859991013514825146259"); CHECK_PRECISE(HMath::arctan("1.0"), "0.78539816339744830961566084581987572104929234984378"); CHECK_PRECISE(HMath::arctan("-0.1"), "-0.09966865249116202737844611987802059024327832250431"); CHECK_PRECISE(HMath::arctan("-0.2"), "-0.19739555984988075837004976519479029344758510378785"); CHECK_PRECISE(HMath::arctan("-0.3"), "-0.29145679447786709199560462143289119350316759901207"); CHECK_PRECISE(HMath::arctan("-0.4"), "-0.38050637711236488630358791681043310449740571365810"); CHECK_PRECISE(HMath::arctan("-0.5"), "-0.46364760900080611621425623146121440202853705428612"); CHECK_PRECISE(HMath::arctan("-0.6"), "-0.54041950027058415544357836460859991013514825146259"); CHECK_PRECISE(HMath::arctan("-1.0"), "-0.78539816339744830961566084581987572104929234984378"); CHECK(HMath::arctan2(0, 0), "NaN"); CHECK(HMath::arctan2(0, 1), "1.57079632679489661923"); CHECK(HMath::arctan2(0, -1), "-1.57079632679489661923"); CHECK(HMath::arctan2(1, 0), "0"); CHECK(HMath::arctan2(-1, 0), "3.14159265358979323846"); CHECK(HMath::arctan2(1, 1), "0.78539816339744830962"); CHECK(HMath::arctan2(1, -1), "-0.78539816339744830962"); CHECK(HMath::arctan2(-1, 1), "2.35619449019234492885"); CHECK(HMath::arctan2(-1, -1), "-2.35619449019234492885"); CHECK(HMath::arcsin("NaN"), "NaN"); CHECK(HMath::arcsin("-1"), "-1.57079632679489661923"); CHECK(HMath::arcsin("0"), "0"); CHECK(HMath::arcsin("1"), "1.57079632679489661923"); CHECK(HMath::arcsin("0.09983341664682815230681419841062202698991538801798"), "0.1"); CHECK(HMath::arcsin("0.19866933079506121545941262711838975037020672954021"), "0.2"); CHECK(HMath::arcsin("0.29552020666133957510532074568502737367783211174262"), "0.3"); CHECK(HMath::arcsin("0.38941834230865049166631175679570526459306018344396"), "0.4"); CHECK(HMath::arcsin("0.47942553860420300027328793521557138808180336794060"), "0.5"); CHECK(HMath::arcsin("0.56464247339503535720094544565865790710988808499415"), "0.6"); CHECK(HMath::arcsin("0.64421768723769105367261435139872018306581384457369"), "0.7"); CHECK(HMath::arcsin("0.71735609089952276162717461058138536619278523779142"), "0.8"); CHECK_PRECISE(HMath::arcsin("0.0"), "0"); CHECK_PRECISE(HMath::arcsin("0.1"), "0.10016742116155979634552317945269331856867597222963"); CHECK_PRECISE(HMath::arcsin("0.2"), "0.20135792079033079145512555221762341024003808140223"); CHECK_PRECISE(HMath::arcsin("0.3"), "0.30469265401539750797200296122752916695456003170678"); CHECK_PRECISE(HMath::arcsin("0.4"), "0.41151684606748801938473789761733560485570113512703"); CHECK(HMath::arccos("NaN"), "NaN"); CHECK(HMath::arccos("-1"), "3.14159265358979323846"); CHECK(HMath::arccos("0"), "1.57079632679489661923"); CHECK(HMath::arccos("1"), "0"); CHECK_PRECISE(HMath::arccos("0.1"), "1.47062890563333682288579851218705812352990872745792"); CHECK_PRECISE(HMath::arccos("0.2"), "1.36943840600456582777619613942212803185854661828532"); CHECK_PRECISE(HMath::arccos("0.3"), "1.26610367277949911125931873041222227514402466798078"); CHECK_PRECISE(HMath::arccos("0.4"), "1.15927948072740859984658379402241583724288356456053"); CHECK(HMath::sinh("NaN"), "NaN"); CHECK_PRECISE(HMath::sinh("0.1"), "0.10016675001984402582372938352190502351492091687856"); CHECK_PRECISE(HMath::sinh("0.2"), "0.20133600254109398762556824301031737297449484262574"); CHECK_PRECISE(HMath::sinh("0.3"), "0.30452029344714261895843526700509522909802423268018"); CHECK_PRECISE(HMath::sinh("0.4"), "0.41075232580281550854021001384469810435315092436331"); CHECK_PRECISE(HMath::sinh("0.5"), "0.52109530549374736162242562641149155910592898261148"); CHECK_PRECISE(HMath::sinh("0.6"), "0.63665358214824127112345437546514831902496342592790"); CHECK_PRECISE(HMath::sinh("0.7"), "0.75858370183953350345987464759276815415493761421703"); CHECK_PRECISE(HMath::sinh("0.8"), "0.88810598218762300657471757318975698055970959688815"); CHECK_PRECISE(HMath::sinh("0.9"), "1.02651672570817527595833616197842235379403446513485"); CHECK_PRECISE(HMath::sinh("1.0"), "1.17520119364380145688238185059560081515571798133410"); CHECK(HMath::cosh("NaN"), "NaN"); CHECK_PRECISE(HMath::cosh("0.1"), "1.00500416805580359898797844296834164470962627785896"); CHECK_PRECISE(HMath::cosh("0.2"), "1.02006675561907584629550375162935679733308609889476"); CHECK_PRECISE(HMath::cosh("0.3"), "1.04533851412886048502530904632291210128027546467919"); CHECK_PRECISE(HMath::cosh("0.4"), "1.08107237183845480928464293899252417629013184957412"); CHECK_PRECISE(HMath::cosh("0.5"), "1.12762596520638078522622516140267201254784711809867"); CHECK_PRECISE(HMath::cosh("0.6"), "1.18546521824226770375191329269771619435727538261853"); CHECK_PRECISE(HMath::cosh("0.7"), "1.25516900563094301816467474099029711586260477992884"); CHECK_PRECISE(HMath::cosh("0.8"), "1.33743494630484459800481995820531977649392453816033"); CHECK_PRECISE(HMath::cosh("0.9"), "1.43308638544877438784179040162404834162773784130523"); CHECK_PRECISE(HMath::cosh("1.0"), "1.54308063481524377847790562075706168260152911236586"); CHECK(HMath::tanh("NaN"), "NaN"); CHECK_PRECISE(HMath::tanh("0.1"), "0.09966799462495581711830508367835218353896209577673"); CHECK_PRECISE(HMath::tanh("0.2"), "0.19737532022490400073815731881101566838937268384235"); CHECK_PRECISE(HMath::tanh("0.3"), "0.29131261245159090581822127282376592815359680491761"); CHECK_PRECISE(HMath::tanh("0.4"), "0.37994896225522488526774812389687331051318437437140"); CHECK_PRECISE(HMath::tanh("0.5"), "0.46211715726000975850231848364367254873028928033011"); CHECK_PRECISE(HMath::tanh("0.6"), "0.53704956699803528586182530492689670598284198771923"); CHECK_PRECISE(HMath::tanh("0.7"), "0.60436777711716349630868718310382647501556664741686"); CHECK_PRECISE(HMath::tanh("0.8"), "0.66403677026784896368484465640024285007465529270892"); CHECK_PRECISE(HMath::tanh("0.9"), "0.71629787019902442081144378305809486317486516460076"); CHECK_PRECISE(HMath::tanh("1.0"), "0.76159415595576488811945828260479359041276859725794"); CHECK(HMath::arcosh("NaN"), "NaN"); CHECK_PRECISE(HMath::arcosh("1.00500416805580359898797844296834164470962627785896"), "0.10000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::arcosh("1.02006675561907584629550375162935679733308609889476"), "0.20000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::arcosh("1.04533851412886048502530904632291210128027546467919"), "0.30000000000000000000000000000000000000000000000001"); CHECK_PRECISE(HMath::arcosh("1.08107237183845480928464293899252417629013184957412"), "0.40000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::arcosh("1.12762596520638078522622516140267201254784711809867"), "0.50000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::arcosh("1.18546521824226770375191329269771619435727538261853"), "0.60000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::arcosh("1.25516900563094301816467474099029711586260477992884"), "0.70000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::arcosh("1.33743494630484459800481995820531977649392453816033"), "0.79999999999999999999999999999999999999999999999999"); CHECK_PRECISE(HMath::arcosh("1.43308638544877438784179040162404834162773784130523"), "0.90000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::arcosh("1.54308063481524377847790562075706168260152911236586"), "1.00000000000000000000000000000000000000000000000000"); CHECK(HMath::artanh("NaN"), "NaN"); CHECK_PRECISE(HMath::artanh("0.09966799462495581711830508367835218353896209577673"), "0.10000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::artanh("0.19737532022490400073815731881101566838937268384235"), "0.20000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::artanh("0.29131261245159090581822127282376592815359680491761"), "0.30000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::artanh("0.37994896225522488526774812389687331051318437437140"), "0.40000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::artanh("0.46211715726000975850231848364367254873028928033011"), "0.50000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::artanh("0.53704956699803528586182530492689670598284198771923"), "0.60000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::artanh("0.60436777711716349630868718310382647501556664741686"), "0.70000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::artanh("0.66403677026784896368484465640024285007465529270892"), "0.80000000000000000000000000000000000000000000000001"); CHECK_PRECISE(HMath::artanh("0.71629787019902442081144378305809486317486516460076"), "0.90000000000000000000000000000000000000000000000000"); CHECK_PRECISE(HMath::artanh("0.76159415595576488811945828260479359041276859725794"), "1.00000000000000000000000000000000000000000000000001"); CHECK(HMath::decodeIeee754("NaN", "NaN", "NaN"), "NaN"); CHECK(HMath::decodeIeee754("1", "-1", "1"), "NaN"); CHECK(HMath::decodeIeee754("1", "1", "0"), "NaN"); CHECK(HMath::decodeIeee754("1", "1.5", "1"), "NaN"); CHECK(HMath::decodeIeee754("0", "5", "10"), "0"); CHECK(HMath::decodeIeee754("0x7ff00000", "8", "23"), "NaN"); CHECK(HMath::decodeIeee754("0xffc0feed", "8", "23"), "NaN"); CHECK(HMath::decodeIeee754("0x7fffffff", "8", "23"), "NaN"); CHECK(HMath::decodeIeee754("0x8000", "5", "10"), "0"); CHECK_PRECISE(HMath::decodeIeee754("0x00800000", "8", "23"), "0.00000000000000000000000000000000000001175494350822"); CHECK_PRECISE(HMath::decodeIeee754("0x006f6eed", "8", "23"), "0.00000000000000000000000000000000000001023353274603"); CHECK(HMath::decodeIeee754("0x41200000", "8", "23"), "10"); CHECK(HMath::decodeIeee754("0xc1200000", "8", "23"), "-10"); CHECK(HMath::decodeIeee754("0x3fc00000", "8", "23"), "1.5"); CHECK_PRECISE(HMath::decodeIeee754("0x3dcccccd", "8", "23"), "0.10000000149011611938476562500000000000000000000000"); CHECK(HMath::decodeIeee754("0x7f7fffff", "8", "23"), "340282346638528859811704183484516925440"); CHECK(HMath::decodeIeee754("0x418100b9", "8", "23"), "16.1253528594970703125"); CHECK(HMath::decodeIeee754("0x4024000000000000", "11", "52"), "10"); CHECK(HMath::decodeIeee754("0x01", "4", "3", "-2"), "1"); CHECK(HMath::decodeIeee754("0x07", "4", "3", "-2"), "7"); CHECK(HMath::decodeIeee754("0x08", "4", "3", "-2"), "8"); CHECK(HMath::decodeIeee754("0xf1", "4", "3", "-2"), "-73728"); CHECK(HMath::decodeIeee754("0x77", "4", "3", "-2"), "122880"); CHECK(HMath::decodeIeee754("0x5", "2", "1"), "3"); CHECK_PRECISE(HMath::decodeIeee754("0x3ffd5555555555555555555555555555", "15", "112"), "0.33333333333333333333333333333333331728391713010637"); CHECK(HMath::encodeIeee754("NaN", "NaN", "NaN"), "NaN"); CHECK(HMath::encodeIeee754("1", "NaN", "NaN"), "NaN"); CHECK(HMath::encodeIeee754("1", "-1", "1"), "NaN"); CHECK(HMath::encodeIeee754("1", "1", "0"), "NaN"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("NaN", "5", "10"), "0x7FFF"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("NaN", "11", "52"), "0x7FFFFFFFFFFFFFFF"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("0", "5", "10"), "0"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("1.17549435E-38", "8", "23"), "0x800000"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("10", "8", "23"), "0x41200000"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("-10", "8", "23"), "0xC1200000"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("1.5", "8", "23"), "0x3FC00000"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("0.999755859375", "5", "10"), "0x3C00"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("340282346638528859811704183484516925440","8", "23"), "0x7F7FFFFF"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("9999999999999999999999999999999999", "5", "10"), "0x7C00"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("-0.1", "8", "23"), "0xBDCCCCCD"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("-0.1", "11", "52"), "0xBFB999999999999A"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("16.1253528594970703125", "8", "23"), "0x418100B9"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("1", "4", "3", "-2"), "0x1"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("7", "4", "3", "-2"), "0x7"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("8", "4", "3", "-2"), "0x8"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("-73728", "4", "3", "-2"), "0xF1"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("122880", "4", "3", "-2"), "0x77"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("3", "2", "1"), "0x5"); CHECK_FORMAT(Format::Fixed() + Format::Hexadecimal(), HMath::encodeIeee754("1.5", "2", "1"), "0x3"); } int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); hmath_total_tests = 0; hmath_failed_tests = 0; floatmath_init(); PI = HMath::pi(); test_create(); test_remove_trailing_zeroes(); test_format(); test_op(); test_functions(); if (!hmath_failed_tests) return 0; cout << hmath_total_tests << " total, " << hmath_failed_tests << " failed, " << hmath_new_failed_tests << " new" << endl; return hmath_new_failed_tests; } heldercorreia-speedcrunch-e7ca37f/src/tests/testkeypadui.cpp000066400000000000000000001460301526573132500245110ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" using namespace MainWindowTestHelpers; class TestKeypadUi : public QObject { Q_OBJECT private slots: void initTestCase(); void init() { UiTestFixture::resetSettings(); } void classic_keypad_boundary_follows_bordering_panes_data(); void classic_keypad_boundary_follows_bordering_panes(); void classic_keypad_boundary_restores_nested_panes(); void keypad_buttons_use_custom_themed_tooltips(); void custom_keypad_action_stays_checked_after_dialog_accepts(); void keypad_power_button_uses_exponent_label_but_inserts_caret(); void keypad_nth_root_button_inserts_root_data(); void keypad_nth_root_button_inserts_root(); void keypad_zoom_round_trip_restores_button_sizes_data(); void keypad_zoom_round_trip_restores_button_sizes(); void keypad_fifty_percent_zoom_scales_and_restores_data(); void keypad_fifty_percent_zoom_scales_and_restores(); void keypad_fifty_percent_zoom_survives_settings_reload(); void keypad_appearance_defaults_to_modern_and_persists(); void keypad_appearance_switches_all_windows_data(); void keypad_appearance_switches_all_windows(); void keypad_input_stays_in_own_window_data(); void keypad_input_stays_in_own_window(); void keypad_view_menu_tracks_and_changes_only_active_window(); }; void TestKeypadUi::initTestCase() { // Fail before a file-operation test can open an unhandled error dialog. for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) { QVERIFY2(QDir().mkpath(path), qPrintable(QStringLiteral("Cannot create test storage at %1").arg(path))); QTemporaryFile probe(QDir(path).filePath(QStringLiteral("storage-probe-XXXXXX"))); QVERIFY2(probe.open(), qPrintable(QStringLiteral("Cannot write test storage at %1: %2") .arg(path, probe.errorString()))); } } void TestKeypadUi::classic_keypad_boundary_follows_bordering_panes_data() { QTest::addColumn("background"); QTest::newRow("dark") << QStringLiteral("#310b28"); QTest::newRow("light") << QStringLiteral("#eeeeee"); } void TestKeypadUi::classic_keypad_boundary_follows_bordering_panes() { QFETCH(QString, background); MainWindowStateGuard guard; guard.settings->editorDisplayStyle = Settings::EditorDisplayClassic; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); guard.settings->keypadMode = Settings::KeypadModeBasicWide; guard.settings->autoCalc = false; MainWindow window(false); window.resize(1000, 900); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); auto* styles = window.findChild(QStringLiteral("EditorDisplayStyleMenu")); QVERIFY(styles); const auto checkBoundary = [&window, &guard](int expectedCount) { QCoreApplication::processEvents(); QVERIFY(window.findChildren(QStringLiteral("ClassicKeypadSeparator")).isEmpty()); Keypad* keypad = window.findChild(); const bool classic = guard.settings->editorDisplayStyle == Settings::EditorDisplayClassic; const int keypadTop = keypad ? keypad->parentWidget()->mapToGlobal(QPoint()).y() : -1; int borderingCount = 0; for (ResultDisplay* display : window.findChildren()) { QWidget* pane = paneWidgetForDisplay(display); QVERIFY(pane); const bool bordersKeypad = keypad && pane->mapToGlobal(QPoint(0, pane->height())).y() == keypadTop; if (!classic || !bordersKeypad) continue; ++borderingCount; Editor* editor = editorForDisplay(display); QVERIFY(editor); QCOMPARE(editor->mapToGlobal(QPoint(0, editor->height())).y(), keypadTop); } QCOMPARE(borderingCount, expectedCount); }; checkBoundary(1); Editor* leftEditor = window.findChild(); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); checkBoundary(2); Editor* upperRightEditor = qobject_cast(QApplication::focusWidget()); QVERIFY(upperRightEditor); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneDown", Qt::DirectConnection)); checkBoundary(2); QPointer lowerRightEditor = qobject_cast(QApplication::focusWidget()); QVERIFY(lowerRightEditor); QTest::mouseClick(upperRightEditor->viewport(), Qt::LeftButton); QVERIFY(QMetaObject::invokeMethod(&window, "splitActivePaneRight", Qt::DirectConnection)); checkBoundary(2); // Both children of the upper horizontal split stay above the keypad. QCOMPARE(window.findChildren().size(), 4); window.resize(1100, 1000); checkBoundary(2); for (QSplitter* splitter : window.findChildren()) { QList sizes = splitter->sizes(); if (sizes.size() > 1) { sizes[0] += 30; sizes[1] = qMax(1, sizes[1] - 30); splitter->setSizes(sizes); } } checkBoundary(2); MainWindow other(false); QVERIFY(QMetaObject::invokeMethod(&other, "restoreWindowKeypadLayout", Qt::DirectConnection, Q_ARG(bool, false), Q_ARG(int, int(Settings::KeypadModeDisabled)))); other.show(); styles->actions().at(1)->trigger(); checkBoundary(0); const QColor inactiveColor = leftEditor->palette().color(QPalette::Base); styles->actions().at(0)->trigger(); checkBoundary(2); QVERIFY(other.findChildren(QStringLiteral("ClassicKeypadSeparator")).isEmpty()); QCOMPARE(leftEditor->palette().color(QPalette::Base).rgba(), inactiveColor.rgba()); QVERIFY(QMetaObject::invokeMethod(&window, "restoreWindowKeypadLayout", Qt::DirectConnection, Q_ARG(bool, false), Q_ARG(int, int(Settings::KeypadModeDisabled)))); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); checkBoundary(0); for (const auto mode : {Settings::KeypadModeScientificWide, Settings::KeypadModeScientificNarrow}) { QVERIFY(QMetaObject::invokeMethod(&window, "restoreWindowKeypadLayout", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(int, int(mode)))); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); checkBoundary(2); } guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#213c31")}}); QVERIFY(QMetaObject::invokeMethod(&window, "colorSchemeChanged", Qt::DirectConnection)); checkBoundary(2); QVERIFY(leftEditor->palette().color(QPalette::Base).rgba() != inactiveColor.rgba()); // Closing the bottom pane brings the two upper panes down to the keypad. QVERIFY(lowerRightEditor); QTest::mouseClick(lowerRightEditor->viewport(), Qt::LeftButton); QVERIFY(QMetaObject::invokeMethod(&window, "closeCurrentPane", Qt::DirectConnection)); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); checkBoundary(3); } void TestKeypadUi::classic_keypad_boundary_restores_nested_panes() { MainWindowStateGuard guard; guard.settings->editorDisplayStyle = Settings::EditorDisplayClassic; guard.settings->keypadMode = Settings::KeypadModeBasicWide; { MainWindow original(false); QVERIFY(QMetaObject::invokeMethod(&original, "splitActivePaneRight", Qt::DirectConnection)); QVERIFY(QMetaObject::invokeMethod(&original, "splitActivePaneDown", Qt::DirectConnection)); original.persistSessionAndSettingsForShutdown(); } MainWindow restored; restored.resize(1000, 900); restored.show(); QVERIFY(QTest::qWaitForWindowExposed(&restored)); QCoreApplication::processEvents(); Keypad* keypad = restored.findChild(); QVERIFY(keypad); const int keypadTop = keypad->parentWidget()->mapToGlobal(QPoint()).y(); const auto displays = restored.findChildren(); QCOMPARE(displays.size(), 3); QVERIFY(restored.findChildren(QStringLiteral("ClassicKeypadSeparator")).isEmpty()); int borderingCount = 0; for (ResultDisplay* display : displays) { QWidget* pane = paneWidgetForDisplay(display); const bool bordersKeypad = pane->mapToGlobal(QPoint(0, pane->height())).y() == keypadTop; if (!bordersKeypad) continue; ++borderingCount; Editor* editor = editorForDisplay(display); QVERIFY(editor); QCOMPARE(editor->mapToGlobal(QPoint(0, editor->height())).y(), keypadTop); } QCOMPARE(borderingCount, 2); } void TestKeypadUi::keypad_buttons_use_custom_themed_tooltips() { MainWindowStateGuard guard; Settings* settings = guard.settings; settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{{QStringLiteral("background"), QStringLiteral("#e5eee8")}}); settings->keypadMode = Settings::KeypadModeBasicWide; settings->keypadVisible = true; settings->bitfieldVisible = false; const QVector shades = generateOklchShades(QColor(QStringLiteral("#e5eee8")), 6, ThemePolarity::Light); const QVector foregrounds = aaForegroundsForBackgrounds(shades); const QColor popupBackground = shades.at(UiConfig::CompletionPopupBackgroundShade); const QColor popupForeground = foregrounds.at(UiConfig::CompletionPopupBackgroundShade); const QColor popupOutline = shades.at(UiConfig::CompletionPopupOutlineShade); MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Keypad* keypad = window.findChild(); QVERIFY(keypad != nullptr); QPushButton* plusButton = keypadButtonWithText(keypad, QStringLiteral("+")); QVERIFY(plusButton != nullptr); QCOMPARE(plusButton->toolTip(), QString()); const QPoint buttonCenter = plusButton->rect().center(); QMouseEvent moveEvent(QEvent::MouseMove, QPointF(buttonCenter), QPointF(plusButton->mapToGlobal(buttonCenter)), Qt::NoButton, Qt::NoButton, Qt::NoModifier); QCoreApplication::sendEvent(plusButton, &moveEvent); QFrame* summaryPopup = keypad->findChild(QStringLiteral("keypadSummaryPopup")); QTRY_VERIFY(summaryPopup != nullptr && summaryPopup->isVisible()); QLabel* summaryPopupLabel = summaryPopup->findChild(QStringLiteral("keypadSummaryPopupLabel")); QVERIFY(summaryPopupLabel != nullptr); QCOMPARE(summaryPopupLabel->text(), QStringLiteral("Addition")); QVERIFY(summaryPopup->styleSheet().contains(popupBackground.name())); QVERIFY(summaryPopup->styleSheet().contains(popupForeground.name())); QVERIFY(summaryPopup->styleSheet().contains(QStringLiteral("border: %1px solid %2") .arg(UiConfig::PopupOutlineStrokeWidth) .arg(popupOutline.name()))); QVERIFY(!summaryPopup->mask().isEmpty()); } void TestKeypadUi::custom_keypad_action_stays_checked_after_dialog_accepts() { Settings* settings = Settings::instance(); struct SettingsGuard { Settings* settings; Settings::KeypadMode oldKeypadMode; bool oldKeypadVisible; Settings::CustomKeypad oldCustomKeypad; bool oldHasNumberFormatStyleSetting; QByteArray oldSkipUpdateCheck; bool hadSkipUpdateCheck; ~SettingsGuard() { settings->keypadMode = oldKeypadMode; settings->keypadVisible = oldKeypadVisible; settings->customKeypad = oldCustomKeypad; settings->hasNumberFormatStyleSetting = oldHasNumberFormatStyleSetting; if (hadSkipUpdateCheck) qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", oldSkipUpdateCheck); else qunsetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"); } } guard { settings, settings->keypadMode, settings->keypadVisible, settings->customKeypad, settings->hasNumberFormatStyleSetting, qgetenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK"), qEnvironmentVariableIsSet("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK") }; qputenv("SPEEDCRUNCH_TEST_SKIP_UPDATE_CHECK", "1"); settings->keypadMode = Settings::KeypadModeBasicWide; settings->keypadVisible = true; settings->hasNumberFormatStyleSetting = true; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QAction* basicAction = keypadModeAction(&window, Settings::KeypadModeBasicWide); QAction* customAction = keypadModeAction(&window, Settings::KeypadModeCustom); QVERIFY(basicAction != nullptr); QVERIFY(customAction != nullptr); QVERIFY(basicAction->isChecked()); QTimer::singleShot(0, &window, []() { QDialog* dialog = qobject_cast(QApplication::activeModalWidget()); if (dialog != nullptr) dialog->accept(); }); QVERIFY(QMetaObject::invokeMethod(&window, "setKeypadMode", Qt::DirectConnection, Q_ARG(QAction*, customAction))); QCoreApplication::processEvents(); QCOMPARE(settings->keypadMode, Settings::KeypadModeCustom); QVERIFY(customAction->isChecked()); QVERIFY(!basicAction->isChecked()); } void TestKeypadUi::keypad_power_button_uses_exponent_label_but_inserts_caret() { const QString powerLabel = QString::fromUtf8("xʸ"); for (const Keypad::LayoutMode layoutMode : { Keypad::LayoutModeScientificWide, Keypad::LayoutModeScientificNarrow }) { const QList presetButtons = Keypad::presetCustomButtons(layoutMode, QLatin1Char('.')); bool foundPowerButton = false; for (const auto& button : presetButtons) { QVERIFY(button.label != QStringLiteral("^")); if (button.label != powerLabel) continue; foundPowerButton = true; QCOMPARE(button.action, int(Settings::CustomKeypadActionInsertText)); QCOMPARE(button.text, QStringLiteral("^")); } QVERIFY(foundPowerButton); } MainWindowStateGuard guard; Settings* settings = Settings::instance(); settings->keypadMode = Settings::KeypadModeScientificWide; settings->keypadVisible = true; settings->hasNumberFormatStyleSetting = true; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Keypad* keypad = window.findChild(); QVERIFY(keypad != nullptr); QPushButton* powerButton = keypadButtonWithText(keypad, powerLabel); QVERIFY(powerButton != nullptr); QCOMPARE(keypadButtonWithText(keypad, QStringLiteral("^")), nullptr); Editor* editor = window.findChild(); QVERIFY(editor != nullptr); editor->setText(QStringLiteral("2")); editor->setCursorPosition(editor->text().size()); QTest::mouseClick(powerButton, Qt::LeftButton); QTRY_COMPARE(editor->text(), QStringLiteral("2^")); } void TestKeypadUi::keypad_nth_root_button_inserts_root_data() { QTest::addColumn("layoutMode"); QTest::addColumn("custom"); QTest::newRow("scientific-wide") << int(Keypad::LayoutModeScientificWide) << false; QTest::newRow("scientific-narrow") << int(Keypad::LayoutModeScientificNarrow) << false; QTest::newRow("custom-wide") << int(Keypad::LayoutModeScientificWide) << true; QTest::newRow("custom-narrow") << int(Keypad::LayoutModeScientificNarrow) << true; } void TestKeypadUi::keypad_nth_root_button_inserts_root() { QFETCH(int, layoutMode); QFETCH(bool, custom); const Function* rootFunction = FunctionRepo::instance()->find(QStringLiteral("root")); QVERIFY(rootFunction != nullptr); QCOMPARE(rootFunction->usage(), QStringLiteral("n; x")); MainWindowStateGuard guard; Settings* settings = guard.settings; const auto oldCustomKeypad = settings->customKeypad; const auto customGuard = qScopeGuard([&]() { settings->customKeypad = oldCustomKeypad; }); settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->keypadVisible = true; settings->hasNumberFormatStyleSetting = true; const auto layout = static_cast(layoutMode); const bool wide = layout == Keypad::LayoutModeScientificWide; const QString rootLabel = QString::fromUtf8("�√"); int rows = 0; int columns = 0; const auto preset = Keypad::presetCustomButtons(layout, QLatin1Char('.'), &rows, &columns); int rootButtonCount = 0; int squareButtonCount = 0; int separatorButtonCount = 0; for (const auto& button : preset) { QVERIFY(button.label != QString::fromUtf8("∛")); QVERIFY(button.text != QStringLiteral("cbrt(")); QVERIFY(button.label != QStringLiteral("x")); QVERIFY(button.label != QStringLiteral("x=")); if (button.label == QString::fromUtf8("x²")) { ++squareButtonCount; QCOMPARE(button.action, int(Settings::CustomKeypadActionInsertText)); QCOMPARE(button.text, QStringLiteral("^2")); } if (button.label == QStringLiteral(";")) { ++separatorButtonCount; QCOMPARE(button.action, int(Settings::CustomKeypadActionInsertText)); QCOMPARE(button.text, QStringLiteral(";")); } if (button.label != rootLabel) continue; ++rootButtonCount; QCOMPARE(button.action, int(Settings::CustomKeypadActionInsertText)); QCOMPARE(button.text, QStringLiteral("root(")); QCOMPARE(button.row, wide ? 1 : 5); QCOMPARE(button.column, wide ? 5 : 1); } QCOMPARE(rootButtonCount, 1); QCOMPARE(squareButtonCount, 1); QCOMPARE(separatorButtonCount, 1); if (custom) { settings->keypadMode = Settings::KeypadModeCustom; settings->customKeypad.rows = rows; settings->customKeypad.columns = columns; settings->customKeypad.buttons.clear(); for (const auto& button : preset) { settings->customKeypad.buttons.append({button.row, button.column, button.label, button.text, static_cast(button.action)}); } } else { settings->keypadMode = wide ? Settings::KeypadModeScientificWide : Settings::KeypadModeScientificNarrow; } MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); Keypad* keypad = window.findChild(); QVERIFY(keypad != nullptr); const QStringList expectedRows = wide ? QStringList{ QString::fromUtf8("7 8 9 ÷ √ x² E exp ⌧ ⌫"), QString::fromUtf8("4 5 6 × xʸ �√ ln log10 π ans"), QString::fromUtf8("1 2 3 − sin arcsin cos arccos ( )"), QString::fromUtf8("0 . = + tan arctan mod ; % !")} : QStringList{ QString::fromUtf8("7 8 9 ÷ ⌧"), QString::fromUtf8("4 5 6 × ⌫"), QString::fromUtf8("1 2 3 − ("), QStringLiteral("0 . = + )"), QString::fromUtf8("√ x² E exp π"), QString::fromUtf8("xʸ �√ ln log10 ans"), QStringLiteral("sin arcsin cos arccos mod"), QStringLiteral("tan arctan % ! ;")}; QGridLayout* grid = qobject_cast(keypad->layout()); QVERIFY(grid != nullptr); QCOMPARE(rows, expectedRows.size()); QCOMPARE(columns, wide ? 10 : 5); QCOMPARE(grid->count(), 40); for (int row = 0; row < expectedRows.size(); ++row) { const QStringList labels = expectedRows.at(row).split(QLatin1Char(' ')); QCOMPARE(labels.size(), columns); for (int column = 0; column < columns; ++column) { QLayoutItem* item = grid->itemAtPosition(row, column); QVERIFY(item != nullptr); QPushButton* button = qobject_cast(item->widget()); QVERIFY(button != nullptr); const QString expectedLabel = labels.at(column) == QStringLiteral(".") ? QString(settings->radixCharacter()) : labels.at(column); QCOMPARE(button->text(), expectedLabel); QVERIFY(button->isVisible()); } } QPushButton* rootButton = keypadButtonWithText(keypad, rootLabel); QVERIFY(rootButton != nullptr); QCOMPARE(keypadButtonWithText(keypad, QString::fromUtf8("∛")), nullptr); if (!custom) { const QPoint center = rootButton->rect().center(); QHelpEvent tooltipEvent(QEvent::ToolTip, center, rootButton->mapToGlobal(center)); QCoreApplication::sendEvent(rootButton, &tooltipEvent); QFrame* popup = keypad->findChild(QStringLiteral("keypadSummaryPopup")); QTRY_VERIFY(popup != nullptr && popup->isVisible()); QLabel* label = popup->findChild(QStringLiteral("keypadSummaryPopupLabel")); QVERIFY(label != nullptr); QCOMPARE(label->text(), Keypad::tr("Nth root")); } Editor* editor = window.findChild(); ResultDisplay* display = window.findChild(); QVERIFY(editor != nullptr); QVERIFY(display != nullptr); editor->setText(QString()); editor->setAutoCompletionEnabled(false); QTest::mouseClick(rootButton, Qt::LeftButton); QCOMPARE(editor->text(), custom ? QStringLiteral("root()") : QStringLiteral("root(")); QCOMPARE(editor->cursorPosition(), 5); const auto clickButton = [keypad](const QString& label) { QTest::mouseClick(keypadButtonWithText(keypad, label), Qt::LeftButton); }; clickButton(QStringLiteral("5")); clickButton(QStringLiteral(";")); clickButton(QStringLiteral("3")); clickButton(QStringLiteral("2")); if (!custom) clickButton(QStringLiteral(")")); QCOMPARE(editor->text(), QStringLiteral("root(5;32)")); QPushButton* equalsButton = keypadButtonWithText(keypad, QStringLiteral("=")); QVERIFY(equalsButton != nullptr); const int historySize = display->session()->historySize(); QTest::mouseClick(equalsButton, Qt::LeftButton); QCOMPARE(display->session()->historySize(), historySize + 1); const Quantity result = display->session()->historyEntryAtRef(historySize).result(); QVERIFY(result.numericValue().real == HNumber(2)); QVERIFY(result.numericValue().imag.isZero()); editor->setText(QString()); clickButton(QStringLiteral("7")); clickButton(QString::fromUtf8("x²")); QCOMPARE(editor->text(), QString::fromUtf8("7²")); clickButton(QStringLiteral("=")); QCOMPARE(display->session()->historySize(), historySize + 2); const Quantity squared = display->session()->historyEntryAtRef(historySize + 1).result(); // Complex-mode powers can leave rounding noise beyond the displayed digits. QVERIFY2(HMath::abs(squared.numericValue().real - HNumber(49)) < HNumber("1e-50"), qPrintable(HMath::format(squared.numericValue().real, HNumber::Format::Fixed() + HNumber::Format::Precision(70)))); QVERIFY(squared.numericValue().imag.isZero()); } void TestKeypadUi::keypad_input_stays_in_own_window_data() { QTest::addColumn("mode"); QTest::newRow("basic") << int(Settings::KeypadModeBasicWide); QTest::newRow("scientific-wide") << int(Settings::KeypadModeScientificWide); QTest::newRow("scientific-narrow") << int(Settings::KeypadModeScientificNarrow); QTest::newRow("custom") << int(Settings::KeypadModeCustom); } void TestKeypadUi::keypad_input_stays_in_own_window() { QFETCH(int, mode); MainWindowStateGuard guard; Settings* settings = guard.settings; const auto oldCustomKeypad = settings->customKeypad; struct CustomKeypadGuard { Settings* settings; Settings::CustomKeypad keypad; ~CustomKeypadGuard() { settings->customKeypad = keypad; } } customGuard { settings, oldCustomKeypad }; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->keypadMode = static_cast(mode); settings->keypadVisible = true; settings->hasNumberFormatStyleSetting = true; if (mode == Settings::KeypadModeCustom) { settings->customKeypad.rows = 1; settings->customKeypad.columns = 3; settings->customKeypad.buttons.clear(); settings->customKeypad.buttons.append( { 0, 0, QStringLiteral("7"), QStringLiteral("7"), Settings::CustomKeypadActionInsertText }); settings->customKeypad.buttons.append( { 0, 1, QString::fromUtf8("⌫"), QString(), Settings::CustomKeypadActionBackspace }); settings->customKeypad.buttons.append( { 0, 2, QStringLiteral("="), QString(), Settings::CustomKeypadActionEvaluateExpression }); } MainWindow firstWindow; firstWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&firstWindow)); MainWindow secondWindow; secondWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&secondWindow)); Editor* firstEditor = firstWindow.findChild(); Editor* secondEditor = secondWindow.findChild(); ResultDisplay* firstDisplay = firstWindow.findChild(); ResultDisplay* secondDisplay = secondWindow.findChild(); QVERIFY(firstEditor != nullptr); QVERIFY(secondEditor != nullptr); QVERIFY(firstDisplay != nullptr); QVERIFY(secondDisplay != nullptr); Keypad* firstKeypad = firstWindow.findChild(); Keypad* secondKeypad = secondWindow.findChild(); QPushButton* firstDigit = keypadButtonWithText(firstKeypad, QStringLiteral("7")); QPushButton* secondDigit = keypadButtonWithText(secondKeypad, QStringLiteral("7")); QPushButton* firstBackspace = keypadButtonWithText(firstKeypad, QString::fromUtf8("⌫")); QPushButton* firstEquals = keypadButtonWithText(firstKeypad, QStringLiteral("=")); QVERIFY(firstDigit != nullptr); QVERIFY(secondDigit != nullptr); QVERIFY(firstBackspace != nullptr); QVERIFY(firstEquals != nullptr); secondWindow.activateWindow(); secondEditor->setFocus(); QTRY_VERIFY(secondEditor->hasFocus()); // Let the activation focus replay finish before exercising the keypad. QTest::qWait(400); firstEditor->setText(QString()); secondEditor->setText(QString()); QTest::mouseClick(secondDigit, Qt::LeftButton); QCOMPARE(secondEditor->text(), QStringLiteral("7")); QCOMPARE(firstEditor->text(), QString()); // No explicit window activation or editor focus before this click. QTest::mouseClick(firstDigit, Qt::LeftButton); QCOMPARE(firstEditor->text(), QStringLiteral("7")); QCOMPARE(secondEditor->text(), QStringLiteral("7")); QTest::mouseClick(firstBackspace, Qt::LeftButton); QCOMPARE(firstEditor->text(), QString()); QCOMPARE(secondEditor->text(), QStringLiteral("7")); QTest::mouseClick(firstDigit, Qt::LeftButton); const int firstHistorySize = firstDisplay->session()->historySize(); const int secondHistorySize = secondDisplay->session()->historySize(); QTest::mouseClick(firstEquals, Qt::LeftButton); QCOMPARE(firstDisplay->session()->historySize(), firstHistorySize + 1); QCOMPARE(secondDisplay->session()->historySize(), secondHistorySize); QCOMPARE(secondEditor->text(), QStringLiteral("7")); QTest::mouseClick(secondDigit, Qt::LeftButton); QCOMPARE(secondEditor->text(), QStringLiteral("77")); } void TestKeypadUi::keypad_appearance_defaults_to_modern_and_persists() { const auto resetSettings = qScopeGuard([]() { UiTestFixture::resetSettings(); }); UiTestFixture::resetSettings(); Settings* settings = Settings::instance(); QCOMPARE(settings->keypadAppearance, Settings::KeypadAppearanceModern); for (const auto appearance : {Settings::KeypadAppearanceClassic, Settings::KeypadAppearanceModern}) { settings->keypadAppearance = appearance; settings->save(); settings->keypadAppearance = appearance == Settings::KeypadAppearanceClassic ? Settings::KeypadAppearanceModern : Settings::KeypadAppearanceClassic; settings->load(); QCOMPARE(settings->keypadAppearance, appearance); } QSettings persisted(Settings::getConfigPath() + QStringLiteral("/SpeedCrunch.ini"), QSettings::IniFormat); persisted.setValue(QStringLiteral("SpeedCrunch/Display/KeypadAppearance"), 99); persisted.sync(); settings->load(); QCOMPARE(settings->keypadAppearance, Settings::KeypadAppearanceModern); settings->keypadAppearance = Settings::KeypadAppearanceClassic; settings->resetToDefaults(); QCOMPARE(settings->keypadAppearance, Settings::KeypadAppearanceModern); } void TestKeypadUi::keypad_appearance_switches_all_windows_data() { QTest::addColumn("mode"); QTest::newRow("scientific-wide") << int(Settings::KeypadModeScientificWide); QTest::newRow("scientific-narrow") << int(Settings::KeypadModeScientificNarrow); QTest::newRow("basic") << int(Settings::KeypadModeBasicWide); QTest::newRow("custom") << int(Settings::KeypadModeCustom); } void TestKeypadUi::keypad_appearance_switches_all_windows() { QFETCH(int, mode); MainWindowStateGuard guard; Settings* settings = guard.settings; const auto oldAppearance = settings->keypadAppearance; const auto oldCustomKeypad = settings->customKeypad; const auto restoreKeypad = qScopeGuard([=]() { settings->keypadAppearance = oldAppearance; settings->customKeypad = oldCustomKeypad; }); settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->keypadAppearance = Settings::KeypadAppearanceModern; settings->keypadMode = static_cast(mode); settings->keypadZoomPercent = 100; settings->colorScheme = QStringLiteral("Terminal"); settings->customKeypad.rows = 1; settings->customKeypad.columns = 2; settings->customKeypad.buttons.clear(); Settings::CustomKeypadButton description; description.label = QStringLiteral("7"); description.text = QStringLiteral("7"); description.action = Settings::CustomKeypadActionInsertText; description.row = 0; description.column = 0; settings->customKeypad.buttons.append(description); description.label = QStringLiteral("long custom label"); description.column = 1; settings->customKeypad.buttons.append(description); MainWindow first; MainWindow second; first.show(); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&first)); QVERIFY(QTest::qWaitForWindowExposed(&second)); QAction zoom; zoom.setData(150); QVERIFY(QMetaObject::invokeMethod(&second, "setKeypadZoom", Qt::DirectConnection, Q_ARG(QAction*, &zoom))); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); auto* firstKeypad = first.findChild(); auto* secondKeypad = second.findChild(); QVERIFY(firstKeypad != nullptr); QVERIFY(secondKeypad != nullptr); auto* firstButton = keypadButtonWithText(firstKeypad, QStringLiteral("7")); auto* secondButton = keypadButtonWithText(secondKeypad, QStringLiteral("7")); QVERIFY(firstButton != nullptr); QVERIFY(secondButton != nullptr); const QSize firstModernSize = firstButton->size(); const QSize secondModernSize = secondButton->size(); const QFont firstFont = firstButton->font(); const QColor firstColor = firstButton->palette().color(QPalette::Button); auto* menu = first.findChild(QStringLiteral("KeypadAppearanceMenu")); auto* secondMenu = second.findChild(QStringLiteral("KeypadAppearanceMenu")); QVERIFY(menu != nullptr); QVERIFY(secondMenu != nullptr); QVERIFY(menu->actions().size() >= 2); QVERIFY(menu->actions().at(1)->isChecked()); QVERIFY(menu->actions().at(0)->actionGroup()->isExclusive()); menu->actions().at(0)->trigger(); QCoreApplication::processEvents(); QCOMPARE(settings->keypadAppearance, Settings::KeypadAppearanceClassic); QVERIFY(secondMenu->actions().at(0)->isChecked()); QVERIFY(!secondMenu->actions().at(1)->isChecked()); QVERIFY(firstButton->height() < firstModernSize.height()); QVERIFY(secondButton->height() < secondModernSize.height()); QVERIFY(firstButton->width() > firstButton->height()); QVERIFY(secondButton->height() > firstButton->height()); QCOMPARE(firstButton->font(), firstFont); QCOMPARE(firstButton->palette().color(QPalette::Button), firstColor); const QSize classicSize = firstButton->size(); for (QPushButton* button : firstKeypad->findChildren()) { if (button->isHidden()) continue; QCOMPARE(button->size(), classicSize); QVERIFY(button->width() >= button->fontMetrics().horizontalAdvance(button->text()) + 4); QVERIFY(button->height() >= button->fontMetrics().lineSpacing() + 4); } for (int percent : {50, 150, 200, 100}) { zoom.setData(percent); QVERIFY(QMetaObject::invokeMethod(&first, "setKeypadZoom", Qt::DirectConnection, Q_ARG(QAction*, &zoom))); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); firstKeypad = first.findChild(); firstButton = keypadButtonWithText(firstKeypad, QStringLiteral("7")); QVERIFY(firstButton != nullptr); QVERIFY(firstButton->width() > firstButton->height()); if (percent == 100) QCOMPARE(firstButton->size(), classicSize); else if (percent == 50) QVERIFY(firstButton->height() < classicSize.height()); else QVERIFY(firstButton->height() > classicSize.height()); } MainWindow third; auto* thirdButton = keypadButtonWithText(third.findChild(), QStringLiteral("7")); QVERIFY(thirdButton != nullptr); QCOMPARE(thirdButton->size(), classicSize); QSignalSpy pressed(firstKeypad, mode == Settings::KeypadModeCustom ? SIGNAL(customButtonPressed(int,QString)) : SIGNAL(buttonPressed(Keypad::Button))); firstButton->click(); QCOMPARE(pressed.count(), 1); menu->actions().at(1)->trigger(); QCoreApplication::processEvents(); QCOMPARE(firstButton->size(), firstModernSize); QCOMPARE(secondButton->size(), secondModernSize); QCOMPARE(thirdButton->size(), firstModernSize); QCOMPARE(firstButton->font(), firstFont); QVERIFY(secondMenu->actions().at(1)->isChecked()); } void TestKeypadUi::keypad_zoom_round_trip_restores_button_sizes_data() { QTest::addColumn("mode"); QTest::newRow("scientific-wide") << int(Settings::KeypadModeScientificWide); QTest::newRow("scientific-narrow") << int(Settings::KeypadModeScientificNarrow); QTest::newRow("basic") << int(Settings::KeypadModeBasicWide); QTest::newRow("custom") << int(Settings::KeypadModeCustom); } void TestKeypadUi::keypad_zoom_round_trip_restores_button_sizes() { QFETCH(int, mode); MainWindowStateGuard guard; Settings* settings = guard.settings; const auto oldCustomKeypad = settings->customKeypad; const auto restoreCustomKeypad = qScopeGuard([settings, oldCustomKeypad]() { settings->customKeypad = oldCustomKeypad; }); settings->customKeypad.rows = 1; settings->customKeypad.columns = 1; settings->customKeypad.buttons.clear(); Settings::CustomKeypadButton customButton; customButton.label = QStringLiteral("7"); customButton.text = QStringLiteral("7"); customButton.row = 0; customButton.column = 0; customButton.action = Settings::CustomKeypadActionInsertText; settings->customKeypad.buttons.append(customButton); settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->keypadMode = static_cast(mode); settings->keypadVisible = true; settings->keypadZoomPercent = 100; settings->constantsDockVisible = false; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QCoreApplication::processEvents(); const auto button = [&window]() { return keypadButtonWithText(window.findChild(), QStringLiteral("7")); }; QVERIFY(button() != nullptr); const QSize originalSize = button()->size(); const QFont originalFont = button()->font(); const QSize originalKeypadSize = window.findChild()->size(); for (int zoom : {150, 200, 150}) { QAction zoomAction; zoomAction.setData(zoom); QVERIFY(QMetaObject::invokeMethod(&window, "setKeypadZoom", Qt::DirectConnection, Q_ARG(QAction*, &zoomAction))); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); QVERIFY(button() != nullptr); QVERIFY(button()->width() > originalSize.width()); QVERIFY(button()->font().pointSizeF() > originalFont.pointSizeF()); zoomAction.setData(100); QVERIFY(QMetaObject::invokeMethod(&window, "setKeypadZoom", Qt::DirectConnection, Q_ARG(QAction*, &zoomAction))); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); QVERIFY(button() != nullptr); QCOMPARE(button()->font(), originalFont); QCOMPARE(button()->size(), originalSize); QCOMPARE(window.findChild()->size(), originalKeypadSize); } } void TestKeypadUi::keypad_fifty_percent_zoom_scales_and_restores_data() { QTest::addColumn("mode"); QTest::newRow("scientific-wide") << int(Settings::KeypadModeScientificWide); QTest::newRow("scientific-narrow") << int(Settings::KeypadModeScientificNarrow); QTest::newRow("basic") << int(Settings::KeypadModeBasicWide); QTest::newRow("custom") << int(Settings::KeypadModeCustom); } void TestKeypadUi::keypad_fifty_percent_zoom_scales_and_restores() { QFETCH(int, mode); MainWindowStateGuard guard; Settings* settings = guard.settings; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->keypadMode = static_cast(mode); settings->keypadVisible = true; settings->keypadZoomPercent = 100; settings->constantsDockVisible = false; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); window.activateWindow(); QTRY_COMPARE(QApplication::activeWindow(), static_cast(&window)); const auto button = [&window]() { return keypadButtonWithText(window.findChild(), QStringLiteral("7")); }; QVERIFY(button() != nullptr); const QSize originalSize = button()->size(); const QFont originalFont = button()->font(); QMenu* zoomMenu = directSubmenuWithTitle( window.findChild(QStringLiteral("KeypadAppearanceMenu")), QStringLiteral("&Zoom")); QVERIFY(zoomMenu != nullptr); const QList zoomActions = zoomMenu->actions(); QVERIFY(zoomActions.size() >= 3); const auto flushEvents = []() { QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); }; zoomActions.at(0)->trigger(); flushEvents(); QVERIFY(button() != nullptr); const QSize halfSize = button()->size(); const QFont halfFont = button()->font(); QVERIFY(halfSize.width() < originalSize.width()); QVERIFY(halfSize.height() < originalSize.height()); QCOMPARE(halfFont.pointSizeF(), originalFont.pointSizeF() * 0.5); QVERIFY(zoomActions.at(0)->isChecked()); QVERIFY(!zoomActions.at(1)->isChecked()); QCOMPARE(settings->keypadZoomPercent, 50); zoomActions.at(2)->trigger(); flushEvents(); zoomActions.at(0)->trigger(); flushEvents(); QVERIFY(button() != nullptr); QCOMPARE(button()->size(), halfSize); QCOMPARE(button()->font(), halfFont); zoomActions.at(1)->trigger(); flushEvents(); QVERIFY(button() != nullptr); QCOMPARE(button()->size(), originalSize); QCOMPARE(button()->font(), originalFont); QVERIFY(QMetaObject::invokeMethod(&window, "restoreWindowKeypadZoom", Qt::DirectConnection, Q_ARG(int, 50))); flushEvents(); QVERIFY(button() != nullptr); QCOMPARE(button()->size(), halfSize); QCOMPARE(button()->font(), halfFont); window.persistSessionAndSettingsForShutdown(); const QJsonArray savedWindows = QJsonDocument::fromJson(settings->sessionLayoutJson.toUtf8()) .object().value(QStringLiteral("windows")).toArray(); QCOMPARE(savedWindows.size(), 1); QCOMPARE(savedWindows.first().toObject().value(QStringLiteral("keypadZoomPercent")).toInt(), 50); } void TestKeypadUi::keypad_fifty_percent_zoom_survives_settings_reload() { const auto resetSettings = qScopeGuard([]() { UiTestFixture::resetSettings(); }); UiTestFixture::resetSettings(); MainWindowStateGuard guard; Settings* settings = guard.settings; settings->keypadZoomPercent = 50; settings->keypadMode = Settings::KeypadModeBasicWide; settings->save(); settings->keypadZoomPercent = 100; settings->load(); QCOMPARE(settings->keypadZoomPercent, 50); MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QMenu* zoomMenu = directSubmenuWithTitle( window.findChild(QStringLiteral("KeypadAppearanceMenu")), QStringLiteral("&Zoom")); QVERIFY(zoomMenu != nullptr); QVERIFY(!zoomMenu->actions().isEmpty()); QVERIFY(zoomMenu->actions().first()->isChecked()); QCOMPARE(zoomMenu->actions().first()->data().toInt(), 50); } void TestKeypadUi::keypad_view_menu_tracks_and_changes_only_active_window() { MainWindowStateGuard guard; Settings* settings = guard.settings; settings->sessionLayoutJson.clear(); settings->windowState.clear(); settings->windowGeometry.clear(); settings->constantsDockVisible = false; settings->functionsDockVisible = false; settings->historyDockVisible = false; settings->keypadMode = Settings::KeypadModeDisabled; settings->keypadVisible = false; settings->keypadZoomPercent = 100; settings->formulaBookDockVisible = false; settings->variablesDockVisible = false; settings->userFunctionsDockVisible = false; settings->userUnitsDockVisible = false; settings->bitfieldVisible = false; settings->statusBarVisible = true; settings->windowPositionSave = false; settings->hasNumberFormatStyleSetting = true; MainWindow firstWindow; firstWindow.resize(800, 500); firstWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&firstWindow)); MainWindow secondWindow; secondWindow.resize(800, 500); secondWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&secondWindow)); QVERIFY(QMetaObject::invokeMethod( &firstWindow, "restoreWindowKeypadLayout", Qt::DirectConnection, Q_ARG(bool, true), Q_ARG(int, static_cast(Settings::KeypadModeBasicWide)))); QVERIFY(QMetaObject::invokeMethod(&firstWindow, "restoreWindowKeypadZoom", Qt::DirectConnection, Q_ARG(int, 150))); QVERIFY(firstWindow.findChild() != nullptr); QVERIFY(secondWindow.findChild() == nullptr); QMenu* firstViewMenu = menuWithTitle(firstWindow.menuBar(), QStringLiteral("&View")); QMenu* secondViewMenu = menuWithTitle(secondWindow.menuBar(), QStringLiteral("&View")); QVERIFY(firstViewMenu != nullptr); QVERIFY(secondViewMenu != nullptr); QMenu* firstKeypadMenu = directSubmenuWithTitle(firstViewMenu, QStringLiteral("&Keypad")); QMenu* secondKeypadMenu = directSubmenuWithTitle(secondViewMenu, QStringLiteral("&Keypad")); QVERIFY(firstKeypadMenu != nullptr); QVERIFY(secondKeypadMenu != nullptr); QMenu* firstZoomMenu = directSubmenuWithTitle( firstWindow.findChild(QStringLiteral("KeypadAppearanceMenu")), QStringLiteral("&Zoom")); QMenu* secondZoomMenu = directSubmenuWithTitle( secondWindow.findChild(QStringLiteral("KeypadAppearanceMenu")), QStringLiteral("&Zoom")); QVERIFY(firstZoomMenu != nullptr); QVERIFY(secondZoomMenu != nullptr); const auto actionForMode = [](QMenu* menu, Settings::KeypadMode mode) { for (QAction* action : menu->actions()) { if (action->data().isValid() && action->data().toInt() == static_cast(mode)) { return action; } } return static_cast(nullptr); }; const auto checkedModeCount = [](QMenu* menu) { int count = 0; for (QAction* action : menu->actions()) { if (action->isCheckable() && action->data().isValid() && action->isChecked()) ++count; } return count; }; const auto actionForZoom = [](QMenu* menu, int zoomPercent) { for (QAction* action : menu->actions()) { if (action->data().isValid() && action->data().toInt() == zoomPercent) return action; } return static_cast(nullptr); }; const auto checkedZoomCount = [](QMenu* menu) { int count = 0; for (QAction* action : menu->actions()) { if (action->isCheckable() && action->isChecked()) ++count; } return count; }; firstWindow.raise(); firstWindow.activateWindow(); firstWindow.setFocus(Qt::OtherFocusReason); QTRY_COMPARE(QApplication::activeWindow(), static_cast(&firstWindow)); QEvent firstWindowActivate(QEvent::WindowActivate); QCoreApplication::sendEvent(&firstWindow, &firstWindowActivate); QCoreApplication::processEvents(); QAction* firstBasicAction = actionForMode(firstKeypadMenu, Settings::KeypadModeBasicWide); QAction* secondBasicAction = actionForMode(secondKeypadMenu, Settings::KeypadModeBasicWide); QAction* firstDisableAction = actionForMode(firstKeypadMenu, Settings::KeypadModeDisabled); QAction* secondDisableAction = actionForMode(secondKeypadMenu, Settings::KeypadModeDisabled); QVERIFY(firstBasicAction != nullptr); QVERIFY(secondBasicAction != nullptr); QVERIFY(firstDisableAction != nullptr); QVERIFY(secondDisableAction != nullptr); QVERIFY(firstBasicAction->isChecked()); QVERIFY(secondBasicAction->isChecked()); QVERIFY(!firstDisableAction->isChecked()); QVERIFY(!secondDisableAction->isChecked()); QCOMPARE(checkedModeCount(firstKeypadMenu), 1); QCOMPARE(checkedModeCount(secondKeypadMenu), 1); QVERIFY(firstZoomMenu->menuAction()->isEnabled()); QVERIFY(secondZoomMenu->menuAction()->isEnabled()); QVERIFY(actionForZoom(firstZoomMenu, 150)->isChecked()); QVERIFY(actionForZoom(secondZoomMenu, 150)->isChecked()); QCOMPARE(checkedZoomCount(firstZoomMenu), 1); QCOMPARE(checkedZoomCount(secondZoomMenu), 1); secondWindow.raise(); secondWindow.activateWindow(); secondWindow.setFocus(Qt::OtherFocusReason); QTRY_COMPARE(QApplication::activeWindow(), static_cast(&secondWindow)); QEvent secondWindowActivate(QEvent::WindowActivate); QCoreApplication::sendEvent(&secondWindow, &secondWindowActivate); QCoreApplication::processEvents(); QVERIFY(!firstZoomMenu->menuAction()->isEnabled()); QVERIFY(!secondZoomMenu->menuAction()->isEnabled()); QVERIFY(actionForZoom(firstZoomMenu, 100)->isChecked()); QVERIFY(actionForZoom(secondZoomMenu, 100)->isChecked()); QCOMPARE(checkedZoomCount(firstZoomMenu), 1); QCOMPARE(checkedZoomCount(secondZoomMenu), 1); // Simulate the native menu dispatching the inactive window's actions. firstBasicAction->trigger(); QCoreApplication::processEvents(); QVERIFY(firstWindow.findChild() != nullptr); QVERIFY(secondWindow.findChild() != nullptr); QVERIFY(firstZoomMenu->menuAction()->isEnabled()); QVERIFY(secondZoomMenu->menuAction()->isEnabled()); QAction* firstZoom200Action = actionForZoom(firstZoomMenu, 200); QVERIFY(firstZoom200Action != nullptr); firstZoom200Action->trigger(); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); QVERIFY(actionForZoom(firstZoomMenu, 200)->isChecked()); QVERIFY(actionForZoom(secondZoomMenu, 200)->isChecked()); QCOMPARE(checkedZoomCount(firstZoomMenu), 1); QCOMPARE(checkedZoomCount(secondZoomMenu), 1); firstWindow.raise(); firstWindow.activateWindow(); firstWindow.setFocus(Qt::OtherFocusReason); QTRY_COMPARE(QApplication::activeWindow(), static_cast(&firstWindow)); QCoreApplication::sendEvent(&firstWindow, &firstWindowActivate); QCoreApplication::processEvents(); QVERIFY(actionForZoom(firstZoomMenu, 150)->isChecked()); QVERIFY(actionForZoom(secondZoomMenu, 150)->isChecked()); QCOMPARE(checkedZoomCount(firstZoomMenu), 1); QCOMPARE(checkedZoomCount(secondZoomMenu), 1); secondDisableAction->trigger(); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCoreApplication::processEvents(); QVERIFY(firstWindow.findChild() == nullptr); QVERIFY(secondWindow.findChild() != nullptr); QAction* firstDisabledAction = actionForMode(firstKeypadMenu, Settings::KeypadModeDisabled); QAction* secondDisabledAction = actionForMode(secondKeypadMenu, Settings::KeypadModeDisabled); QVERIFY(firstDisabledAction != nullptr); QVERIFY(secondDisabledAction != nullptr); QVERIFY(firstDisabledAction->isChecked()); QVERIFY(secondDisabledAction->isChecked()); QVERIFY(!firstBasicAction->isChecked()); QVERIFY(!secondBasicAction->isChecked()); QCOMPARE(checkedModeCount(firstKeypadMenu), 1); QCOMPARE(checkedModeCount(secondKeypadMenu), 1); QVERIFY(!firstZoomMenu->menuAction()->isEnabled()); QVERIFY(!secondZoomMenu->menuAction()->isEnabled()); QVERIFY(actionForZoom(firstZoomMenu, 150)->isChecked()); QVERIFY(actionForZoom(secondZoomMenu, 150)->isChecked()); QCOMPARE(checkedZoomCount(firstZoomMenu), 1); QCOMPARE(checkedZoomCount(secondZoomMenu), 1); } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testkeypadui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testmenusui.cpp000066400000000000000000002362221526573132500243660ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "mainwindowtesthelpers.h" using namespace MainWindowTestHelpers; class TestMenusUi : public QObject { Q_OBJECT private slots: void initTestCase(); void init() { UiTestFixture::resetSettings(); } void menu_bar_keeps_themed_contrast_with_platform_palette_data(); void menu_bar_keeps_themed_contrast_with_platform_palette(); void menu_appearance_defaults_to_theme_and_persists(); void menu_bar_restores_native_painting_after_theme_switch_data(); void menu_bar_restores_native_painting_after_theme_switch(); void system_menus_restore_style_polished_foreground_and_hover_colors_data(); void system_menus_restore_style_polished_foreground_and_hover_colors(); void gtk_menus_use_hover_colors_instead_of_the_list_accent_data(); void gtk_menus_use_hover_colors_instead_of_the_list_accent(); void dock_dropdowns_follow_menu_appearance_data(); void dock_dropdowns_follow_menu_appearance(); void system_dropdowns_use_the_native_popup_selection_palette_data(); void system_dropdowns_use_the_native_popup_selection_palette(); void macos_system_menus_use_cocoa_style_and_selection_colors(); void editor_context_menu_paints_system_background_data(); void editor_context_menu_paints_system_background(); void menu_appearance_switches_all_windows_without_changing_other_controls(); void system_menus_preserve_platform_roles_and_follow_palette_changes_data(); void system_menus_preserve_platform_roles_and_follow_palette_changes(); void precision_menu_editor_uses_system_colors(); void dock_context_menus_follow_menu_theme_data(); void dock_context_menus_follow_menu_theme(); void precision_menu_editor_uses_themed_colors_data(); void precision_menu_editor_uses_themed_colors(); void menu_theme_cache_keeps_bar_and_popup_colors_separate(); void menu_theme_cache_reloads_named_themes_on_refresh(); void menu_theme_cache_follows_the_fallback_palette(); void themed_menu_icons_preserve_shape_and_follow_item_state_data(); void themed_menu_icons_preserve_shape_and_follow_item_state(); void context_menu_icons_follow_theme_changes_data(); void context_menu_icons_follow_theme_changes(); void disabled_menu_icons_keep_visible_state_data(); void disabled_menu_icons_keep_visible_state(); void disabled_context_menu_labels_are_dimmed_data(); void disabled_context_menu_labels_are_dimmed(); }; void TestMenusUi::disabled_context_menu_labels_are_dimmed_data() { QTest::addColumn("styleName"); QTest::addColumn("background"); for (const QString& style : {QStringLiteral("Fusion"), QStringLiteral("Windows")}) { QTest::newRow(qPrintable(style + QStringLiteral("-dark"))) << style << QStringLiteral("#232136"); QTest::newRow(qPrintable(style + QStringLiteral("-light"))) << style << QStringLiteral("#e5eee8"); } } void TestMenusUi::disabled_context_menu_labels_are_dimmed() { QFETCH(QString, styleName); QFETCH(QString, background); MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); QScopedPointer style(QStyleFactory::create(styleName)); QVERIFY(style != nullptr); QMenu menu; menu.setStyle(style.data()); menu.setFont(QFont(menu.font().family(), 16)); QPixmap glyph(16, 16); glyph.fill(Qt::transparent); QPainter painter(&glyph); painter.fillRect(QRect(3, 3, 10, 10), Qt::black); painter.end(); const QIcon original(glyph); QAction* action = menu.addAction(original, QStringLiteral("Copy selected expression\tCtrl+C")); menu.ensurePolished(); MenuStyle::apply(&menu); menu.popup(QPoint(20, 20)); QCoreApplication::processEvents(); const auto coverage = [&](const QImage& image, const QRect& rect) { const QColor foreground = menu.palette().color(QPalette::WindowText); const QColor fill = menu.palette().color(QPalette::Window); const int dr = foreground.red() - fill.red(); const int dg = foreground.green() - fill.green(); const int db = foreground.blue() - fill.blue(); const int distance = dr * dr + dg * dg + db * db; qreal maximum = 0; const QRect bounded = imageRectForWidgetRect(image, rect).intersected(image.rect()); for (int y = bounded.top(); y <= bounded.bottom(); ++y) { for (int x = bounded.left(); x <= bounded.right(); ++x) { const QColor pixel = image.pixelColor(x, y); const qreal value = qreal((pixel.red() - fill.red()) * dr + (pixel.green() - fill.green()) * dg + (pixel.blue() - fill.blue()) * db) / distance; maximum = qMax(maximum, value); } } return maximum; }; const QRect row = menu.actionGeometry(action); const int shortcutWidth = menu.fontMetrics().horizontalAdvance(QStringLiteral("Ctrl+C")) + 20; const QRect label = row.adjusted(36, 2, -shortcutWidth, -2); const QRect shortcut(row.right() - shortcutWidth + 4, row.top() + 2, shortcutWidth - 12, row.height() - 4); const QImage enabled = menu.grab().toImage(); for (const QRect& rect : {label, shortcut}) QVERIFY(coverage(enabled, rect) > 0.8); action->setEnabled(false); const QImage disabled = menu.grab().toImage(); for (const QRect& rect : {label, shortcut}) { const qreal disabledCoverage = coverage(disabled, rect); QVERIFY2(disabledCoverage > 0.25 && disabledCoverage < 0.65, qPrintable(QStringLiteral("Disabled text coverage: %1").arg(disabledCoverage))); } action->setEnabled(true); const QImage restored = menu.grab().toImage(); for (const QRect& rect : {label, shortcut}) QVERIFY(coverage(restored, rect) > 0.8); menu.hide(); guard.settings->menuAppearance = Settings::MenuAppearanceSystem; MenuStyle::refresh(); QCOMPARE(action->icon().cacheKey(), original.cacheKey()); } void TestMenusUi::disabled_menu_icons_keep_visible_state_data() { QTest::addColumn("background"); QTest::addColumn("sourceFadesDisabled"); QTest::addColumn("scale"); for (const bool dark : {false, true}) { for (const bool sourceFadesDisabled : {false, true}) { for (const qreal scale : {1.0, 1.25, 2.0}) { const QByteArray name = QStringLiteral("dark-%1-native-fade-%2-scale-%3") .arg(dark).arg(sourceFadesDisabled).arg(scale).toLatin1(); QTest::newRow(name.constData()) << (dark ? QStringLiteral("#232136") : QStringLiteral("#e5eee8")) << sourceFadesDisabled << scale; } } } } void TestMenusUi::disabled_menu_icons_keep_visible_state() { QFETCH(QString, background); QFETCH(bool, sourceFadesDisabled); QFETCH(qreal, scale); MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); QIcon source; for (const QIcon::Mode mode : {QIcon::Normal, QIcon::Disabled}) { QPixmap glyph(32, 32); glyph.setDevicePixelRatio(2.0); glyph.fill(Qt::transparent); QPainter painter(&glyph); // Windows font icons use an opaque gray tint. Other engines can // reduce opacity, which must survive recoloring without another fade. const QColor color = mode == QIcon::Disabled ? QColor(128, 128, 128, sourceFadesDisabled ? 96 : 255) : QColor(Qt::black); painter.fillRect(QRect(3, 3, 10, 10), color); painter.end(); source.addPixmap(glyph, mode); } QMenu menu; QAction* action = menu.addAction(source, QStringLiteral("Copy")); menu.ensurePolished(); MenuStyle::apply(&menu); const QImage enabled = action->icon().pixmap(QSize(16, 16), scale, QIcon::Normal).toImage(); const QImage disabled = action->icon().pixmap(QSize(16, 16), scale, QIcon::Disabled).toImage(); const QPoint center(disabled.width() / 2, disabled.height() / 2); QCOMPARE(enabled.pixelColor(center).alpha(), 255); QCOMPARE(disabled.pixelColor(center).alpha(), sourceFadesDisabled ? 96 : 128); QCOMPARE(disabled.pixelColor(0, 0).alpha(), 0); const auto composite = [&](const QImage& glyph) { QImage surface(glyph.size(), QImage::Format_ARGB32_Premultiplied); surface.setDevicePixelRatio(glyph.devicePixelRatio()); surface.fill(menu.palette().color(QPalette::Window)); QPainter painter(&surface); painter.drawImage(QPointF(), glyph); return surface; }; const QColor enabledPixel = composite(enabled).pixelColor(center); const QColor disabledPixel = composite(disabled).pixelColor(center); const QColor fill = menu.palette().color(QPalette::Window); QVERIFY(disabledPixel != enabledPixel); QVERIFY(qAbs(qGray(disabledPixel.rgb()) - qGray(fill.rgb())) < qAbs(qGray(enabledPixel.rgb()) - qGray(fill.rgb()))); action->setEnabled(false); menu.popup(QPoint(20, 20)); QCoreApplication::processEvents(); const QImage rendered = menu.grab().toImage(); const QRect row = imageRectForWidgetRect(rendered, menu.actionGeometry(action)); const QRect iconArea(row.x(), row.y(), qRound(24 * rendered.devicePixelRatio()), row.height()); QVERIFY(firstPixelMatchingColor(rendered, iconArea, disabledPixel, 4) != QPoint(-1, -1)); action->setEnabled(true); const QImage restored = menu.grab().toImage(); QVERIFY(firstPixelMatchingColor(restored, iconArea, enabledPixel, 4) != QPoint(-1, -1)); menu.hide(); guard.settings->menuAppearance = Settings::MenuAppearanceSystem; MenuStyle::refresh(); QCOMPARE(action->icon().cacheKey(), source.cacheKey()); } void TestMenusUi::themed_menu_icons_preserve_shape_and_follow_item_state_data() { QTest::addColumn("mode"); QTest::addColumn("checked"); QTest::addColumn("scale"); for (const QIcon::Mode mode : {QIcon::Normal, QIcon::Active, QIcon::Selected, QIcon::Disabled}) { for (const bool checked : {false, true}) { for (const qreal scale : {1.0, 1.25, 2.0}) { const QByteArray name = QStringLiteral("mode-%1-checked-%2-scale-%3") .arg(int(mode)).arg(checked).arg(scale).toLatin1(); QTest::newRow(name.constData()) << int(mode) << checked << scale; } } } } void TestMenusUi::themed_menu_icons_preserve_shape_and_follow_item_state() { QFETCH(int, mode); QFETCH(bool, checked); QFETCH(qreal, scale); const auto iconMode = static_cast(mode); const auto state = checked ? QIcon::On : QIcon::Off; QIcon source; for (const QIcon::State sourceState : {QIcon::Off, QIcon::On}) { QPixmap mask(32, 32); mask.setDevicePixelRatio(2.0); mask.fill(Qt::transparent); QPainter painter(&mask); painter.fillRect(sourceState == QIcon::On ? QRect(3, 2, 4, 12) : QRect(2, 3, 12, 4), Qt::black); painter.fillRect(QRect(10, 10, 3, 3), QColor(0, 0, 0, 128)); painter.end(); for (const QIcon::Mode sourceMode : {QIcon::Normal, QIcon::Active, QIcon::Selected, QIcon::Disabled}) source.addPixmap(mask, sourceMode, sourceState); } const qint64 sourceKey = source.cacheKey(); const QPixmap original = source.pixmap(QSize(16, 16), scale, iconMode, state); QPalette palette; palette.setColor(QPalette::Active, QPalette::WindowText, QColor("#ecf4fa")); palette.setColor(QPalette::Disabled, QPalette::WindowText, QColor("#a9afb9")); palette.setColor(QPalette::Active, QPalette::HighlightedText, QColor("#292035")); const QIcon themed = MenuStyle::themedIcon(source, palette); const QPixmap actual = themed.pixmap(QSize(16, 16), scale, iconMode, state); QCOMPARE(actual.size(), original.size()); QCOMPARE(actual.devicePixelRatio(), original.devicePixelRatio()); const QColor expected = palette.color(iconMode == QIcon::Disabled ? QPalette::Disabled : QPalette::Active, iconMode == QIcon::Active || iconMode == QIcon::Selected ? QPalette::HighlightedText : QPalette::WindowText); const QImage image = actual.toImage(); const QImage mask = original.toImage(); int opaquePixels = 0; for (int y = 0; y < image.height(); ++y) { for (int x = 0; x < image.width(); ++x) { const QColor pixel = image.pixelColor(x, y); QCOMPARE(pixel.alpha(), mask.pixelColor(x, y).alpha()); if (pixel.alpha() == 255) { QCOMPARE(pixel, expected); ++opaquePixels; } } } QVERIFY(opaquePixels > 0); QImage painted(actual.size(), QImage::Format_ARGB32_Premultiplied); painted.setDevicePixelRatio(actual.devicePixelRatio()); painted.fill(Qt::transparent); QPainter painter(&painted); themed.paint(&painter, QRect(QPoint(), actual.deviceIndependentSize().toSize()), Qt::AlignCenter, iconMode, state); painter.end(); QCOMPARE(painted, image.convertToFormat(QImage::Format_ARGB32_Premultiplied)); QCOMPARE(source.cacheKey(), sourceKey); QCOMPARE(source.pixmap(QSize(16, 16), scale, iconMode, state).toImage(), mask); QVERIFY(MenuStyle::themedIcon(QIcon(), palette).isNull()); } void TestMenusUi::context_menu_icons_follow_theme_changes_data() { QTest::addColumn("styleName"); QTest::addColumn("classic"); QTest::newRow("fusion-modern") << QStringLiteral("Fusion") << false; QTest::newRow("fusion-classic") << QStringLiteral("Fusion") << true; QTest::newRow("windows-modern") << QStringLiteral("Windows") << false; QTest::newRow("windows-classic") << QStringLiteral("Windows") << true; } void TestMenusUi::context_menu_icons_follow_theme_changes() { QFETCH(QString, styleName); QFETCH(bool, classic); MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSystem; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->editorDisplayStyle = classic ? Settings::EditorDisplayClassic : Settings::EditorDisplayModern; QScopedPointer style(QStyleFactory::create(styleName)); QVERIFY(style != nullptr); Editor editor; editor.insert(QStringLiteral("123")); editor.selectAll(); QScopedPointer menu(editor.createStandardContextMenu()); menu->setStyle(style.data()); menu->ensurePolished(); MenuStyle::apply(menu.data()); QAction* copy = menu->findChild(QStringLiteral("edit-copy")); QVERIFY(copy != nullptr); const QIcon native = copy->icon(); // Supply a glyph on offscreen platforms without native icons. QPixmap glyph(16, 16); glyph.fill(Qt::transparent); QPainter painter(&glyph); painter.fillRect(QRect(4, 3, 8, 10), Qt::black); painter.end(); if (copy->icon().isNull()) copy->setIcon(QIcon(glyph)); const QIcon original = copy->icon(); const auto verify = [&](QAction* action) { QVERIFY(!action->icon().isNull()); for (const QIcon::Mode mode : {QIcon::Normal, QIcon::Active, QIcon::Selected, QIcon::Disabled}) { const QImage image = action->icon().pixmap(QSize(16, 16), mode).toImage(); const QColor expected = menu->palette().color(mode == QIcon::Disabled ? QPalette::Disabled : QPalette::Active, mode == QIcon::Active || mode == QIcon::Selected ? QPalette::HighlightedText : QPalette::WindowText); QVERIFY(firstPixelMatchingColor(image, image.rect(), expected, 4) != QPoint(-1, -1)); } menu->popup(QPoint(20, 20)); QCoreApplication::processEvents(); for (const bool selected : {false, true}) { menu->setActiveAction(selected ? action : nullptr); const QImage rendered = menu->grab().toImage(); const qreal dpr = rendered.devicePixelRatio(); const QRect row = menu->actionGeometry(action); const QRect iconArea(qRound(row.x() * dpr), qRound(row.y() * dpr), qRound(qMin(24, row.width()) * dpr), qRound(row.height() * dpr)); QVERIFY(firstPixelMatchingColor(rendered, iconArea, menu->palette().color(selected ? QPalette::HighlightedText : QPalette::WindowText), 4) != QPoint(-1, -1)); } menu->setActiveAction(nullptr); menu->hide(); }; for (const QString& background : {QStringLiteral("#232136"), QStringLiteral("#e5eee8")}) { guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); MenuStyle::refresh(); QCoreApplication::processEvents(); verify(copy); const qint64 themedKey = copy->icon().cacheKey(); MenuStyle::apply(menu.data()); QCOMPARE(copy->icon().cacheKey(), themedKey); QIcon replacement(glyph); copy->setIcon(replacement); verify(copy); QAction* added = menu->addAction(QIcon(glyph), QStringLiteral("Later action")); verify(added); guard.settings->menuAppearance = Settings::MenuAppearanceSystem; MenuStyle::refresh(); QCOMPARE(copy->icon().cacheKey(), replacement.cacheKey()); copy->setIcon(original); } if (!native.isNull()) QCOMPARE(copy->icon().cacheKey(), native.cacheKey()); } void TestMenusUi::menu_theme_cache_keeps_bar_and_popup_colors_separate() { MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->colorScheme = QStringLiteral("Custom"); QMenu popup; QMenuBar bar; bar.setNativeMenuBar(false); for (const QColor base : {QColor("#232136"), QColor("#e5eee8")}) { guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), base.name()}}); MenuStyle::apply(&popup); MenuStyle::apply(&bar); const auto shades = generateOklchShades(base, 6, themePolarityForBackground(base)); QCOMPARE(popup.palette().color(QPalette::Window), shades.at(UiConfig::DockHeaderShade)); QCOMPARE(bar.palette().color(QPalette::Window), shades.at(UiConfig::WindowBackgroundShade)); QCOMPARE(popup.palette().color(QPalette::Highlight), shades.at(UiConfig::DockUnfocusedSelectedItemShade)); QCOMPARE(bar.palette().color(QPalette::Highlight), popup.palette().color(QPalette::Highlight)); QMenu override; const QColor overrideFill("#123456"); MenuStyle::setThemeColors(&override, overrideFill, Qt::white, Qt::blue, Qt::white); QCOMPARE(override.palette().color(QPalette::Window), overrideFill); MenuStyle::apply(&popup); MenuStyle::apply(&bar); QCOMPARE(popup.palette().color(QPalette::Window), shades.at(UiConfig::DockHeaderShade)); QCOMPARE(bar.palette().color(QPalette::Window), shades.at(UiConfig::WindowBackgroundShade)); } } void TestMenusUi::menu_theme_cache_reloads_named_themes_on_refresh() { MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->colorScheme = QStringLiteral("Menu cache test"); const QString directory = ColorScheme::fileSystemSearchPaths().first(); QVERIFY(QDir().mkpath(directory)); const QString path = QDir(directory).filePath(guard.settings->colorScheme + QStringLiteral(".json")); const auto removeTheme = qScopeGuard([&]() { QFile::remove(path); }); QMenu popup; for (const QColor base : {QColor("#232136"), QColor("#e5eee8")}) { QFile file(path); QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Truncate)); const QByteArray json = themeJsonString( QJsonObject{{QStringLiteral("background"), base.name()}}).toUtf8(); QCOMPARE(file.write(json), qint64(json.size())); file.close(); MenuStyle::refresh(); MenuStyle::apply(&popup); const auto shades = generateOklchShades(base, 6, themePolarityForBackground(base)); QCOMPARE(popup.palette().color(QPalette::Window), shades.at(UiConfig::DockHeaderShade)); } } void TestMenusUi::menu_theme_cache_follows_the_fallback_palette() { MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString(QJsonObject()); const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([&]() { QApplication::setPalette(original); MenuStyle::refresh(); }); QMenu popup; for (const QColor base : {QColor("#232136"), QColor("#e5eee8")}) { QPalette palette = original; palette.setColor(QPalette::Base, base); QApplication::setPalette(palette); MenuStyle::apply(&popup); const auto shades = generateOklchShades(base, 6, themePolarityForBackground(base)); QCOMPARE(popup.palette().color(QPalette::Window), shades.at(UiConfig::DockHeaderShade)); } } void TestMenusUi::initTestCase() { // Fail before a file-operation test can open an unhandled error dialog. for (const QString& path : {Settings::getConfigPath(), Settings::getDataPath(), Settings::getCachePath()}) { QVERIFY2(QDir().mkpath(path), qPrintable(QStringLiteral("Cannot create test storage at %1").arg(path))); QTemporaryFile probe(QDir(path).filePath(QStringLiteral("storage-probe-XXXXXX"))); QVERIFY2(probe.open(), qPrintable(QStringLiteral("Cannot write test storage at %1: %2") .arg(path, probe.errorString()))); } } void TestMenusUi::menu_bar_keeps_themed_contrast_with_platform_palette_data() { QTest::addColumn("darkPlatform"); QTest::addColumn("background"); QTest::newRow("dark-desktop-dark-theme") << true << QStringLiteral("#232136"); QTest::newRow("light-desktop-dark-theme") << false << QStringLiteral("#232136"); QTest::newRow("dark-desktop-light-theme") << true << QStringLiteral("#e5eee8"); QTest::newRow("light-desktop-light-theme") << false << QStringLiteral("#e5eee8"); } void TestMenusUi::menu_bar_keeps_themed_contrast_with_platform_palette() { QFETCH(bool, darkPlatform); QFETCH(QString, background); MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), background}}); MainWindow window; QMenuBar* bar = window.menuBar(); bar->setNativeMenuBar(false); QPalette platformPalette = QApplication::palette(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { platformPalette.setColor(group, QPalette::Window, darkPlatform ? QColor("#1e1e1e") : QColor("#efefef")); platformPalette.setColor(group, QPalette::WindowText, darkPlatform ? QColor("#eff0f1") : QColor("#232629")); platformPalette.setColor(group, QPalette::ButtonText, platformPalette.color(group, QPalette::WindowText)); } auto* platformStyle = new MenuBarPaletteTestStyle(platformPalette); platformStyle->setParent(bar); bar->setStyle(platformStyle); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); window.colorSchemeChanged(); QCoreApplication::processEvents(); const auto verifyTheme = [bar](const QColor& base) { const QVector shades = generateOklchShades(base, 6, themePolarityForBackground(base)); const QColor fill = shades.at(UiConfig::WindowBackgroundShade); const QColor text = aaForegroundForBackground(fill); const QColor selectedFill = shades.at(UiConfig::DockUnfocusedSelectedItemShade); const QColor selectedText = aaForegroundForBackground(selectedFill); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { QCOMPARE(bar->palette().color(group, QPalette::Window), fill); QCOMPARE(bar->palette().color(group, QPalette::WindowText), text); QCOMPARE(bar->palette().color(group, QPalette::ButtonText), text); QCOMPARE(bar->palette().color(group, QPalette::Highlight), selectedFill); QCOMPARE(bar->palette().color(group, QPalette::HighlightedText), selectedText); } const QImage rendered = bar->grab().toImage(); const qreal dpr = rendered.devicePixelRatio(); QCOMPARE(rendered.pixelColor(qRound((bar->width() - 4) * dpr), qRound(bar->height() / 2.0 * dpr)).name(), fill.name()); // Check painted glyphs as well as palette roles. Native styles may // choose a different text role or selection color when drawing items. for (const QStyle::State state : {QStyle::State(QStyle::State_Enabled | QStyle::State_Active), QStyle::State(QStyle::State_Enabled), QStyle::State(QStyle::State_None), QStyle::State(QStyle::State_Enabled | QStyle::State_Selected), QStyle::State(QStyle::State_Enabled | QStyle::State_Selected | QStyle::State_Sunken)}) { QStyleOptionMenuItem option; option.initFrom(bar); option.state = state; option.rect = QRect(0, 0, 100, bar->height()); option.text = QStringLiteral("Session"); const bool selected = state.testFlag(QStyle::State_Selected); const QColor expectedFill = selected ? selectedFill : fill; const QColor expectedText = selected ? selectedText : text; QImage item(option.rect.size(), QImage::Format_ARGB32_Premultiplied); item.fill(fill); QPainter painter(&item); painter.setFont(bar->font()); bar->style()->drawControl(QStyle::CE_MenuBarItem, &option, &painter, bar); painter.end(); QCOMPARE(item.pixelColor(1, 1).name(), expectedFill.name()); int textPixels = 0; for (int y = 0; y < item.height(); ++y) { for (int x = 0; x < item.width(); ++x) { const QColor pixel = item.pixelColor(x, y); if (qAbs(pixel.red() - expectedText.red()) < 24 && qAbs(pixel.green() - expectedText.green()) < 24 && qAbs(pixel.blue() - expectedText.blue()) < 24) ++textPixels; } } QVERIFY2(textPixels > 10, "Menu bar text does not use the contrasting theme color."); } }; verifyTheme(QColor(background)); const QColor switchedBackground(background == QLatin1String("#232136") ? QStringLiteral("#e5eee8") : QStringLiteral("#232136")); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), switchedBackground.name()}}); window.colorSchemeChanged(); QCoreApplication::processEvents(); verifyTheme(switchedBackground); } void TestMenusUi::menu_bar_restores_native_painting_after_theme_switch_data() { QTest::addColumn("styleName"); QTest::newRow("fusion") << QStringLiteral("Fusion"); QTest::newRow("windows") << QStringLiteral("Windows"); } void TestMenusUi::menu_bar_restores_native_painting_after_theme_switch() { QFETCH(QString, styleName); MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSystem; MainWindow window(false); QMenuBar* bar = window.menuBar(); bar->setNativeMenuBar(false); QScopedPointer style(QStyleFactory::create(styleName)); QVERIFY(style != nullptr); bar->setStyle(style.data()); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); MenuStyle::refresh(); QCoreApplication::processEvents(); const bool nativeStyledBackground = bar->testAttribute(Qt::WA_StyledBackground); const QImage nativeRendering = bar->grab().toImage(); QMenu* appearance = window.findChild(QStringLiteral("MenuAppearanceMenu")); QVERIFY(appearance != nullptr); for (int cycle = 0; cycle < 2; ++cycle) { appearance->actions().at(1)->trigger(); QCoreApplication::processEvents(); QVERIFY(bar->testAttribute(Qt::WA_StyledBackground)); // Switch from an open menu, as users do, then let the style finish. bool switched = false; QTimer::singleShot(0, &window, [&]() { appearance->actions().at(0)->trigger(); appearance->close(); switched = true; }); appearance->exec(bar->mapToGlobal(QPoint(0, bar->height()))); QVERIFY(switched); QCoreApplication::processEvents(); QVERIFY(bar->styleSheet().isEmpty()); QCOMPARE(bar->testAttribute(Qt::WA_StyledBackground), nativeStyledBackground); QCOMPARE(bar->grab().toImage(), nativeRendering); } bar->setStyle(nullptr); } void TestMenusUi::dock_dropdowns_follow_menu_appearance_data() { QTest::addColumn("darkSystem"); QTest::addColumn("floating"); QTest::newRow("dark-attached") << true << false; QTest::newRow("light-attached") << false << false; QTest::newRow("dark-floating") << true << true; QTest::newRow("light-floating") << false << true; } void TestMenusUi::dock_dropdowns_follow_menu_appearance() { QFETCH(bool, darkSystem); QFETCH(bool, floating); MainWindowStateGuard guard; const QPalette original = QApplication::palette(); const auto restorePalette = qScopeGuard([&]() { QApplication::setPalette(original); MenuStyle::refresh(); }); QPalette native = original; for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (const QPalette::ColorRole role : {QPalette::Window, QPalette::Base, QPalette::Button}) native.setColor(group, role, QColor(darkSystem ? "#202428" : "#eeeeee")); for (const QPalette::ColorRole role : {QPalette::WindowText, QPalette::Text, QPalette::ButtonText}) native.setColor(group, role, QColor(group == QPalette::Disabled ? "#808890" : (darkSystem ? "#f0f0f0" : "#202020"))); native.setColor(group, QPalette::Highlight, QColor("#354faf")); native.setColor(group, QPalette::HighlightedText, QColor("#ffffff")); } QApplication::setPalette(native); guard.settings->menuAppearance = Settings::MenuAppearanceSystem; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), darkSystem ? "#e5eee8" : "#232136"}}); guard.settings->constantsDockVisible = true; guard.settings->functionsDockVisible = true; MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QMenu* appearance = window.findChild(QStringLiteral("MenuAppearanceMenu")); QVERIFY(appearance != nullptr); for (const char* dockName : {"ConstantsDock", "FunctionsDock"}) { appearance->actions().at(0)->trigger(); QDockWidget* dock = window.findChild(QString::fromLatin1(dockName)); QVERIFY(dock != nullptr); dock->setFloating(floating); dock->show(); QComboBox* combo = dock->findChild(); QVERIFY(combo != nullptr); QCoreApplication::processEvents(); QAbstractItemView* view = combo->view(); const auto nativeFrame = view->frameShape(); const bool nativeViewportFill = view->viewport()->autoFillBackground(); const QPalette closedPalette = combo->palette(); for (const int mode : {0, 1, 0, 1, 0}) { appearance->actions().at(mode)->trigger(); combo->showPopup(); const auto closePopup = qScopeGuard([combo]() { combo->hidePopup(); }); QCoreApplication::processEvents(); QVERIFY(view->isVisible()); QWidget* popup = view->window(); QCOMPARE(combo->palette(), closedPalette); if (mode == 0) { QVERIFY(view->styleSheet().isEmpty()); QVERIFY(view->verticalScrollBar()->styleSheet().isEmpty()); QVERIFY(!combo->styleSheet().contains(QStringLiteral("QComboBox QAbstractItemView"))); QCOMPARE(view->frameShape(), nativeFrame); QCOMPARE(view->viewport()->autoFillBackground(), nativeViewportFill); QVERIFY(popup->mask().isEmpty()); for (QWidget* surface : {static_cast(view), view->viewport(), popup}) { const QPalette expected = MenuStyle::systemPalette(surface); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (const QPalette::ColorRole role : {QPalette::Base, QPalette::Text, QPalette::Highlight, QPalette::HighlightedText}) QCOMPARE(surface->palette().color(group, role), expected.color(group, role)); } } const QImage image = view->viewport()->grab().toImage(); int backgroundPixels = 0; for (int y = 0; y < image.height(); ++y) { for (int x = 0; x < image.width(); ++x) backgroundPixels += image.pixelColor(x, y).name() == native.color(QPalette::Base).name(); } QVERIFY2(backgroundPixels > image.width() * image.height() / 3, qPrintable(QStringLiteral("%1: expected %2, view %3, viewport %4, painted %5") .arg(QString::fromLatin1(dockName), native.color(QPalette::Base).name(), view->palette().color(QPalette::Base).name(), view->viewport()->palette().color(QPalette::Base).name(), image.pixelColor(5, 5).name()))); } else { QVERIFY(!view->styleSheet().isEmpty()); QVERIFY(!view->verticalScrollBar()->styleSheet().isEmpty()); QVERIFY(!popup->mask().isEmpty()); QCOMPARE(view->frameShape(), QFrame::NoFrame); QVERIFY(view->palette().color(QPalette::Base) != native.color(QPalette::Base)); } // Refresh an already-open dropdown without changing other controls. appearance->actions().at(1 - mode)->trigger(); QCoreApplication::processEvents(); QCOMPARE(view->styleSheet().isEmpty(), mode == 1); } appearance->actions().at(0)->trigger(); combo->showPopup(); const auto closePopup = qScopeGuard([combo]() { combo->hidePopup(); }); for (const QPalette::ColorRole role : {QPalette::Window, QPalette::Base, QPalette::Button}) native.setColor(role, QColor(darkSystem ? "#292e36" : "#e1f0fd")); native.setColor(QPalette::Highlight, QColor("#6850aa")); QApplication::setPalette(native); QCoreApplication::processEvents(); QCOMPARE(view->palette().color(QPalette::Base), native.color(QPalette::Base)); QCOMPARE(view->palette().color(QPalette::Highlight), native.color(QPalette::Highlight)); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#433229")}}); window.colorSchemeChanged(); QCoreApplication::processEvents(); QVERIFY(view->styleSheet().isEmpty()); QCOMPARE(view->palette().color(QPalette::Base), native.color(QPalette::Base)); QCOMPARE(view->viewport()->palette().color(QPalette::Base), native.color(QPalette::Base)); } } void TestMenusUi::system_dropdowns_use_the_native_popup_selection_palette_data() { QTest::addColumn("editable"); QTest::newRow("menu-popup") << false; QTest::newRow("list-popup") << true; } void TestMenusUi::system_dropdowns_use_the_native_popup_selection_palette() { QFETCH(bool, editable); MainWindowStateGuard guard; const QPalette originalMenu = QApplication::palette("QMenu"); const QPalette originalList = QApplication::palette("QListView"); const auto restorePalettes = qScopeGuard([&]() { QApplication::setPalette(originalMenu, "QMenu"); QApplication::setPalette(originalList, "QListView"); MenuStyle::refresh(); }); QPalette nativeMenu = originalMenu; QPalette nativeList = originalList; for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { nativeMenu.setColor(group, QPalette::Highlight, QColor("#427dc0")); nativeMenu.setColor(group, QPalette::HighlightedText, QColor("#fefefe")); nativeList.setColor(group, QPalette::Highlight, QColor("#1a4266")); nativeList.setColor(group, QPalette::HighlightedText, QColor("#eeeeee")); } QApplication::setPalette(nativeMenu, "QMenu"); QApplication::setPalette(nativeList, "QListView"); guard.settings->menuAppearance = Settings::MenuAppearanceSystem; guard.settings->constantsDockVisible = true; MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); auto* dock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(dock != nullptr); auto* combo = dock->findChild(); QVERIFY(combo != nullptr); combo->setEditable(editable); QStyleOptionComboBox option; option.initFrom(combo); option.editable = editable; const bool menuPopup = QApplication::style()->styleHint(QStyle::SH_ComboBox_Popup, &option, combo); const QPalette expected = menuPopup ? nativeMenu : nativeList; QMenu* appearance = window.findChild(QStringLiteral("MenuAppearanceMenu")); QVERIFY(appearance != nullptr); for (const int mode : {0, 1, 0}) { appearance->actions().at(mode)->trigger(); combo->showPopup(); const auto closePopup = qScopeGuard([combo]() { combo->hidePopup(); }); QCoreApplication::processEvents(); if (mode != 0) continue; for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { QCOMPARE(combo->view()->palette().color(group, QPalette::Highlight), expected.color(group, QPalette::Highlight)); QCOMPARE(combo->view()->palette().color(group, QPalette::HighlightedText), expected.color(group, QPalette::HighlightedText)); } QStyleOptionViewItem selected; selected.initFrom(combo->view()); selected.rect = QRect(0, 0, 240, 40); selected.state = QStyle::State_Active | QStyle::State_Enabled | QStyle::State_Selected; selected.palette.setCurrentColorGroup(QPalette::Active); QImage image(selected.rect.size(), QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QPainter painter(&image); combo->itemDelegate()->paint(&painter, selected, combo->model()->index(0, combo->modelColumn())); painter.end(); QCOMPARE(image.pixelColor(220, 20).name(), expected.color(QPalette::Active, QPalette::Highlight).name()); } } void TestMenusUi::macos_system_menus_use_cocoa_style_and_selection_colors() { #if defined(Q_OS_MACOS) if (QApplication::platformName() != QLatin1String("cocoa")) { QTest::qSkip("Native macOS theme verification requires the Cocoa backend.", __FILE__, __LINE__); return; } MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSystem; guard.settings->constantsDockVisible = true; MainWindow window(false); QStyle* nativeStyle = QApplication::style(); while (auto* proxy = qobject_cast(nativeStyle)) nativeStyle = proxy->baseStyle(); QCOMPARE(nativeStyle->objectName(), QStringLiteral("macos")); const QPalette nativeMenu = QApplication::palette("QMenu"); QScopedPointer menu(window.findChild()->createStandardContextMenu()); menu->ensurePolished(); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); auto* dock = window.findChild(QStringLiteral("ConstantsDock")); QVERIFY(dock != nullptr); auto* combo = dock->findChild(); QVERIFY(combo != nullptr); combo->showPopup(); const auto closePopup = qScopeGuard([combo]() { combo->hidePopup(); }); QCoreApplication::processEvents(); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { QCOMPARE(menu->palette().color(group, QPalette::Highlight), nativeMenu.color(group, QPalette::Highlight)); QCOMPARE(combo->view()->palette().color(group, QPalette::Highlight), nativeMenu.color(group, QPalette::Highlight)); QCOMPARE(combo->view()->palette().color(group, QPalette::HighlightedText), nativeMenu.color(group, QPalette::HighlightedText)); } #else QTest::qSkip("Native macOS theme verification requires macOS.", __FILE__, __LINE__); #endif } void TestMenusUi::editor_context_menu_paints_system_background_data() { QTest::addColumn("editorBackground"); QTest::newRow("dark-editor") << QStringLiteral("#232136"); QTest::newRow("light-editor") << QStringLiteral("#e5eee8"); } void TestMenusUi::editor_context_menu_paints_system_background() { QFETCH(QString, editorBackground); MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSystem; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), editorBackground}}); MainWindow window(false); auto* editor = window.findChild(); QVERIFY(editor != nullptr); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); const auto openContextMenu = [&]() { const QPoint pos(8, 8); QContextMenuEvent event(QContextMenuEvent::Mouse, pos, editor->viewport()->mapToGlobal(pos)); QCoreApplication::sendEvent(editor->viewport(), &event); auto* menu = qobject_cast(QApplication::activePopupWidget()); if (menu != nullptr) menu->setAttribute(Qt::WA_DeleteOnClose, false); return menu; }; QScopedPointer context(openContextMenu()); QVERIFY(context != nullptr); QCOMPARE(context->parentWidget(), editor->viewport()); // Palette checks alone miss inherited stylesheets that suppress painting. const auto panelImage = [](QMenu* menu) { menu->ensurePolished(); QImage image(180, 120, QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QStyleOption option; option.initFrom(menu); option.rect = image.rect(); option.state = QStyle::State_Enabled | QStyle::State_Active; QPainter painter(&image); menu->style()->drawPrimitive(QStyle::PE_PanelMenu, &option, &painter, menu); painter.end(); return image; }; const auto verifyBackground = [&](QMenu* menu) { QMenu reference; const QImage expected = panelImage(&reference); const QPoint center = expected.rect().center(); QVERIFY(expected.pixelColor(center).alpha() > 0); const QImage actual = panelImage(menu); QCOMPARE(actual.pixelColor(center), expected.pixelColor(center)); }; verifyBackground(context.data()); context->close(); // Check both a retained popup and a newly created one after switching back. guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; MenuStyle::refresh(); context->ensurePolished(); const QImage themed = panelImage(context.data()); QCOMPARE(themed.pixelColor(themed.rect().center()).rgba(), context->palette().color(QPalette::Window).rgba()); guard.settings->menuAppearance = Settings::MenuAppearanceSystem; MenuStyle::refresh(); QCoreApplication::processEvents(); verifyBackground(context.data()); QScopedPointer fresh(openContextMenu()); QVERIFY(fresh != nullptr); verifyBackground(fresh.data()); } void TestMenusUi::menu_appearance_defaults_to_theme_and_persists() { MainWindowStateGuard guard; Settings* settings = guard.settings; QCOMPARE(settings->menuAppearance, Settings::MenuAppearanceSpeedCrunch); const QString scheme = settings->colorScheme; for (const Settings::MenuAppearance appearance : {Settings::MenuAppearanceSpeedCrunch, Settings::MenuAppearanceSystem}) { settings->menuAppearance = appearance; settings->save(); settings->menuAppearance = appearance == Settings::MenuAppearanceSystem ? Settings::MenuAppearanceSpeedCrunch : Settings::MenuAppearanceSystem; settings->load(); QCOMPARE(settings->menuAppearance, appearance); QCOMPARE(settings->colorScheme, scheme); } QSettings persisted(Settings::getConfigPath() + QStringLiteral("/SpeedCrunch.ini"), QSettings::IniFormat); const QString key = QStringLiteral("SpeedCrunch/Display/MenuAppearance"); persisted.remove(key); persisted.sync(); settings->load(); QCOMPARE(settings->menuAppearance, Settings::MenuAppearanceSpeedCrunch); persisted.setValue(key, 99); persisted.sync(); settings->load(); QCOMPARE(settings->menuAppearance, Settings::MenuAppearanceSpeedCrunch); } void TestMenusUi::menu_appearance_switches_all_windows_without_changing_other_controls() { MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSystem; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#232136")}}); guard.settings->constantsDockVisible = true; MainWindow first(false); MainWindow second(false); first.menuBar()->setNativeMenuBar(false); second.menuBar()->setNativeMenuBar(false); first.show(); second.show(); QVERIFY(QTest::qWaitForWindowExposed(&first)); QVERIFY(QTest::qWaitForWindowExposed(&second)); MenuStyle::refresh(); QMenu* firstAppearance = first.findChild(QStringLiteral("MenuAppearanceMenu")); QMenu* secondAppearance = second.findChild(QStringLiteral("MenuAppearanceMenu")); QVERIFY(firstAppearance != nullptr); QVERIFY(secondAppearance != nullptr); QVERIFY(firstAppearance->actions().size() >= 2); QVERIFY(firstAppearance->actions().at(0)->isChecked()); QVERIFY(secondAppearance->actions().at(0)->isChecked()); Editor* editor = first.findChild(); ResultDisplay* display = first.findChild(); QDockWidget* constants = first.findChild(QStringLiteral("ConstantsDock")); QVERIFY(editor != nullptr); QVERIFY(display != nullptr); QVERIFY(constants != nullptr); const QPalette editorPalette = editor->palette(); const QPalette displayPalette = display->palette(); const QPalette dockPalette = constants->palette(); const QString editorStyle = editor->styleSheet(); // Keep a context menu alive across both switches to catch stale palettes // and styles that would otherwise survive until the next popup. QScopedPointer context(editor->createStandardContextMenu()); context->ensurePolished(); QVERIFY(context->styleSheet().isEmpty()); firstAppearance->actions().at(1)->trigger(); QCOMPARE(guard.settings->menuAppearance, Settings::MenuAppearanceSpeedCrunch); QVERIFY(firstAppearance->actions().at(1)->isChecked()); QVERIFY(secondAppearance->actions().at(1)->isChecked()); for (QMenuBar* bar : {first.menuBar(), second.menuBar()}) QVERIFY(!bar->styleSheet().isEmpty()); QVERIFY(!context->styleSheet().isEmpty()); QMenu* child = context->addMenu(QStringLiteral("Nested")); child->addAction(QStringLiteral("Disabled"))->setEnabled(false); child->ensurePolished(); QVERIFY(!child->styleSheet().isEmpty()); QCOMPARE(child->palette().color(QPalette::Window).name(), context->palette().color(QPalette::Window).name()); secondAppearance->actions().at(0)->trigger(); QCOMPARE(guard.settings->menuAppearance, Settings::MenuAppearanceSystem); QVERIFY(firstAppearance->actions().at(0)->isChecked()); QVERIFY(secondAppearance->actions().at(0)->isChecked()); // Desktop styles can change palettes while menus are polished. Check // color restoration separately with an explicit style palette. for (QWidget* menu : {static_cast(first.menuBar()), static_cast(second.menuBar()), static_cast(context.data()), static_cast(child)}) { QVERIFY(menu->styleSheet().isEmpty()); } QCOMPARE(editor->palette(), editorPalette); QCOMPARE(display->palette(), displayPalette); QCOMPARE(constants->palette(), dockPalette); QCOMPARE(editor->styleSheet(), editorStyle); } void TestMenusUi::system_menus_restore_style_polished_foreground_and_hover_colors_data() { QTest::addColumn("background"); QTest::newRow("light-style") << QColor("#eeeeee"); QTest::newRow("dark-style") << QColor("#454358"); } void TestMenusUi::system_menus_restore_style_polished_foreground_and_hover_colors() { QFETCH(QColor, background); MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), QStringLiteral("#232136")}}); MainWindow window(false); QMenuBar* bar = window.menuBar(); bar->setNativeMenuBar(false); QPalette native = QApplication::palette(bar); const bool dark = background.lightness() < 128; const QColor foreground(dark ? "#eeeeee" : "#242424"); const QColor disabledForeground(dark ? "#999999" : "#777777"); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { native.setColor(group, QPalette::Window, background); native.setColor(group, QPalette::Button, background); for (const QPalette::ColorRole role : {QPalette::WindowText, QPalette::ButtonText}) native.setColor(group, role, group == QPalette::Disabled ? disabledForeground : foreground); native.setColor(group, QPalette::Highlight, QColor(dark ? "#656378" : "#cccccc")); native.setColor(group, QPalette::HighlightedText, foreground); } auto* style = new MenuBarPaletteTestStyle(native); style->setParent(bar); bar->setStyle(style); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QMenu* appearance = window.findChild(QStringLiteral("MenuAppearanceMenu")); QVERIFY(appearance != nullptr); for (int cycle = 0; cycle < 3; ++cycle) { appearance->actions().at(1)->trigger(); QCoreApplication::processEvents(); appearance->actions().at(0)->trigger(); QCoreApplication::processEvents(); QVERIFY(bar->styleSheet().isEmpty()); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (const QPalette::ColorRole role : {QPalette::Window, QPalette::WindowText, QPalette::Button, QPalette::ButtonText, QPalette::Highlight, QPalette::HighlightedText}) QCOMPARE(bar->palette().color(group, role), native.color(group, role)); } for (const QStyle::State state : {QStyle::State(QStyle::State_Enabled | QStyle::State_Active), QStyle::State(QStyle::State_Enabled), QStyle::State(QStyle::State_None)}) { QStyleOptionMenuItem option; option.initFrom(bar); option.state = state; option.palette.setCurrentColorGroup(state & QStyle::State_Enabled ? state & QStyle::State_Active ? QPalette::Active : QPalette::Inactive : QPalette::Disabled); option.rect = QRect(0, 0, 200, 32); option.text = QStringLiteral("Menu foreground"); option.font = bar->font(); QImage image(option.rect.size(), QImage::Format_ARGB32_Premultiplied); image.fill(native.color(QPalette::Window)); QPainter painter(&image); bar->style()->drawControl(QStyle::CE_MenuBarItem, &option, &painter, bar); painter.end(); QVERIFY(firstPixelMatchingColor(image, image.rect(), native.color(option.palette.currentColorGroup(), QPalette::ButtonText), 12) != QPoint(-1, -1)); } } } void TestMenusUi::gtk_menus_use_hover_colors_instead_of_the_list_accent_data() { QTest::addColumn("dark"); QTest::newRow("light-menu") << false; QTest::newRow("dark-menu") << true; } void TestMenusUi::gtk_menus_use_hover_colors_instead_of_the_list_accent() { QFETCH(bool, dark); // Model GTK's CSS states and Cairo's pixel buffer without requiring a // GNOME session. This also checks translucent disabled text and cleanup. struct Widget { unsigned state = 0; Widget* child = nullptr; bool destroyed = false; }; static bool darkTheme; static int widgetCount; static int surfaceCount; darkTheme = dark; widgetCount = surfaceCount = 0; GtkMenuPalette::Api api{}; api.popoverNew = [](void*) -> void* { ++widgetCount; return new Widget; }; api.modelButtonNew = []() -> void* { ++widgetCount; return new Widget; }; api.add = [](void* menu, void* item) { static_cast(menu)->child = static_cast(item); }; api.context = [](void* widget) { return widget; }; api.setState = [](void* widget, unsigned state) { static_cast(widget)->state = state; }; api.color = [](void*, unsigned state, GtkMenuPalette::Rgba* color) { const double component = state & (1 << 3) ? 0 : darkTheme ? 238.0 / 255 : 36.0 / 255; *color = {component, component, component, state & (1 << 3) ? 0.5 : 1}; }; api.background = [](void* context, void* painter, double, double, double, double) { auto* widget = static_cast(context); auto* image = static_cast(painter); if (widget->child) { image->fill(QColor(darkTheme ? "#202020" : "#f0f0f0")); } else if (widget->state & (1 << 1)) { // GTK themes can express hover colors with translucent CSS. QPainter paint(image); paint.fillRect(image->rect(), darkTheme ? QColor(255, 255, 255, 32) : QColor(0, 0, 0, 32)); } }; api.destroyWidget = [](void* widget) { auto* menu = static_cast(widget); delete menu->child; menu->child = nullptr; menu->destroyed = true; --widgetCount; }; api.refSink = [](void* widget) { return widget; }; api.unref = [](void* widget) { auto* menu = static_cast(widget); Q_ASSERT(menu->destroyed); delete menu; --widgetCount; }; api.surfaceForData = [](unsigned char* data, int format, int width, int height, int stride) -> void* { Q_ASSERT(format == 0); ++surfaceCount; return new QImage(data, width, height, stride, QImage::Format_ARGB32_Premultiplied); }; api.createPainter = [](void* surface) { return surface; }; api.destroyPainter = [](void*) {}; api.flushSurface = [](void*) {}; api.destroySurface = [](void* surface) { delete static_cast(surface); --surfaceCount; }; QPalette fallback; fallback.setColor(QPalette::Highlight, QColor("#e95420")); const QPalette palette = GtkMenuPalette::read(api, fallback); const QColor fill(dark ? "#202020" : "#f0f0f0"); const QColor selected(dark ? "#3c3c3c" : "#d2d2d2"); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { QCOMPARE(palette.color(group, QPalette::Window), fill); QCOMPARE(palette.color(group, QPalette::Highlight), selected); if (group != QPalette::Disabled) { QCOMPARE(palette.color(group, QPalette::ButtonText), QColor(dark ? "#eeeeee" : "#242424")); QCOMPARE(palette.color(group, QPalette::HighlightedText), palette.color(group, QPalette::ButtonText)); } } QCOMPARE(palette.color(QPalette::Disabled, QPalette::ButtonText), QColor(dark ? "#101010" : "#787878")); QCOMPARE(palette.color(QPalette::Link), fallback.color(QPalette::Link)); QCOMPARE(fallback.color(QPalette::Highlight), QColor("#e95420")); QCOMPARE(widgetCount, 0); QCOMPARE(surfaceCount, 0); } void TestMenusUi::system_menus_preserve_platform_roles_and_follow_palette_changes_data() { QTest::addColumn("darkPlatform"); QTest::newRow("dark-system-light-calculator") << true; QTest::newRow("light-system-dark-calculator") << false; } void TestMenusUi::system_menus_preserve_platform_roles_and_follow_palette_changes() { QFETCH(bool, darkPlatform); MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSystem; const QPalette original = QApplication::palette(); const QPalette originalMenu = QApplication::palette("QMenu"); const QPalette originalBar = QApplication::palette("QMenuBar"); const auto restorePalette = qScopeGuard([&]() { QApplication::setPalette(original); QApplication::setPalette(originalMenu, "QMenu"); QApplication::setPalette(originalBar, "QMenuBar"); MenuStyle::refresh(); }); const auto platformPalette = [&original](bool dark) { QPalette palette = original; for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { const QColor fill(dark ? "#202428" : "#eeeeee"); const QColor text(group == QPalette::Disabled ? "#808890" : (dark ? "#f0f0f0" : "#202020")); for (const QPalette::ColorRole role : {QPalette::Window, QPalette::Base, QPalette::Button}) palette.setColor(group, role, fill); for (const QPalette::ColorRole role : {QPalette::WindowText, QPalette::Text, QPalette::ButtonText}) palette.setColor(group, role, text); palette.setColor(group, QPalette::Highlight, QColor("#354faf")); palette.setColor(group, QPalette::HighlightedText, QColor("#ffffff")); } return palette; }; QPalette menuPalette = platformPalette(darkPlatform); QPalette barPalette = menuPalette; barPalette.setColor(QPalette::Highlight, QColor("#246044")); QApplication::setPalette(menuPalette, "QMenu"); QApplication::setPalette(barPalette, "QMenuBar"); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString(QJsonObject{ {QStringLiteral("background"), darkPlatform ? QStringLiteral("#e5eee8") : QStringLiteral("#232136")} }); MainWindow window(false); window.menuBar()->setNativeMenuBar(false); auto* transparentStyle = new TransparentMenuBarTestStyle; transparentStyle->setParent(window.menuBar()); window.menuBar()->setStyle(transparentStyle); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); MenuStyle::refresh(); QScopedPointer editorMenu(window.findChild()->createStandardContextMenu()); editorMenu->ensurePolished(); MenuTestResultDisplay result; QScopedPointer resultMenu(result.createContextMenu(QPoint())); resultMenu->ensurePolished(); const auto verifyPalette = [](QWidget* widget, const QPalette& expected) { widget->ensurePolished(); QVERIFY(widget->styleSheet().isEmpty()); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (const QPalette::ColorRole role : {QPalette::Window, QPalette::Text, QPalette::WindowText, QPalette::ButtonText, QPalette::Highlight, QPalette::HighlightedText}) { QCOMPARE(widget->palette().color(group, role), expected.color(group, role)); } } }; verifyPalette(window.menuBar(), barPalette); const QImage barImage = window.menuBar()->grab().toImage(); const QPoint backgroundPixel(barImage.width() - 4, barImage.height() / 2); QCOMPARE(barImage.pixelColor(backgroundPixel), barPalette.color(QPalette::Button)); for (QMenu* menu : window.findChildren()) verifyPalette(menu, menuPalette); verifyPalette(editorMenu.data(), menuPalette); verifyPalette(resultMenu.data(), menuPalette); for (QMenu* submenu : resultMenu->findChildren()) verifyPalette(submenu, menuPalette); for (bool enabled : {true, false}) { QStyleOptionMenuItem option; option.initFrom(editorMenu.data()); option.menuItemType = QStyleOptionMenuItem::Normal; option.rect = QRect(0, 0, 160, 28); option.text = QStringLiteral("Menu item"); option.state = enabled ? QStyle::State(QStyle::State_Enabled | QStyle::State_Selected) : QStyle::State(QStyle::State_None); option.palette.setCurrentColorGroup(enabled ? QPalette::Active : QPalette::Disabled); option.font = editorMenu->font(); const QColor fill = menuPalette.color(enabled ? QPalette::Highlight : QPalette::Window); const QColor text = enabled ? menuPalette.color(QPalette::HighlightedText) : menuPalette.color(QPalette::Disabled, QPalette::Text); QImage image(option.rect.size(), QImage::Format_ARGB32_Premultiplied); image.fill(fill); QPainter painter(&image); painter.setFont(option.font); editorMenu->style()->drawControl(QStyle::CE_MenuItem, &option, &painter, editorMenu.data()); painter.end(); QVERIFY(firstPixelMatchingColor(image, image.rect(), text, 12) != QPoint(-1, -1)); } menuPalette = platformPalette(!darkPlatform); barPalette = menuPalette; barPalette.setColor(QPalette::Highlight, QColor("#246044")); QApplication::setPalette(menuPalette, "QMenu"); QApplication::setPalette(barPalette, "QMenuBar"); QCoreApplication::processEvents(); verifyPalette(window.menuBar(), barPalette); verifyPalette(editorMenu.data(), menuPalette); verifyPalette(resultMenu.data(), menuPalette); } void TestMenusUi::precision_menu_editor_uses_system_colors() { MainWindowStateGuard guard; guard.settings->menuAppearance = Settings::MenuAppearanceSystem; guard.settings->statusBarVisible = true; guard.settings->resultPrecision = -1; MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); bool inspected = false; QTimer::singleShot(0, &window, [&]() { QMenu* menu = qobject_cast(QApplication::activePopupWidget()); if (menu == nullptr) return; const auto closeMenu = qScopeGuard([menu]() { menu->close(); }); QSpinBox* spin = menu->findChild(); QVERIFY(spin != nullptr); QVERIFY(!spin->isEnabled()); QVERIFY(spin->styleSheet().isEmpty()); QVERIFY(menu->styleSheet().isEmpty()); QCOMPARE(spin->palette().color(QPalette::Disabled, QPalette::Base), QApplication::palette(spin).color(QPalette::Disabled, QPalette::Base)); QCOMPARE(spin->palette().color(QPalette::Disabled, QPalette::Text), QApplication::palette(spin).color(QPalette::Disabled, QPalette::Text)); inspected = true; }); QVERIFY(QMetaObject::invokeMethod(&window, "showPrecisionContextMenu", Qt::DirectConnection, Q_ARG(QPoint, QPoint()))); QVERIFY(inspected); } void TestMenusUi::dock_context_menus_follow_menu_theme_data() { QTest::addColumn("darkSystem"); QTest::addColumn("floating"); QTest::newRow("dark-system-attached") << true << false; QTest::newRow("light-system-attached") << false << false; QTest::newRow("dark-system-floating") << true << true; QTest::newRow("light-system-floating") << false << true; } void TestMenusUi::dock_context_menus_follow_menu_theme() { QFETCH(bool, darkSystem); QFETCH(bool, floating); MainWindowStateGuard guard; const QPalette originalMenuPalette = QApplication::palette("QMenu"); const auto restorePalette = qScopeGuard([&]() { QApplication::setPalette(originalMenuPalette, "QMenu"); MenuStyle::refresh(); }); QPalette native = originalMenuPalette; for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { const QColor background(darkSystem ? "#202428" : "#eeeeee"); const QColor foreground(group == QPalette::Disabled ? "#808890" : (darkSystem ? "#f0f0f0" : "#202020")); for (const QPalette::ColorRole role : {QPalette::Window, QPalette::Base, QPalette::Button}) native.setColor(group, role, background); for (const QPalette::ColorRole role : {QPalette::WindowText, QPalette::Text, QPalette::ButtonText}) native.setColor(group, role, foreground); native.setColor(group, QPalette::Highlight, QColor("#354faf")); native.setColor(group, QPalette::HighlightedText, QColor("#ffffff")); } QApplication::setPalette(native, "QMenu"); const QColor calculatorBackground(darkSystem ? "#e5eee8" : "#232136"); guard.settings->colorScheme = QStringLiteral("Custom"); guard.settings->customColorSchemeJson = themeJsonString( QJsonObject{{QStringLiteral("background"), calculatorBackground.name()}}); guard.settings->historyDockVisible = true; guard.settings->variablesDockVisible = true; guard.settings->userFunctionsDockVisible = true; guard.settings->userUnitsDockVisible = true; Session historySession; historySession.addHistoryEntry(HistoryEntry(QStringLiteral("1+1"), Quantity(2))); MainWindow window(false); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QMenu* appearance = window.findChild(QStringLiteral("MenuAppearanceMenu")); QVERIFY(appearance != nullptr); HistoryWidget* history = window.findChild(); QVERIFY(history != nullptr); history->setSession(&historySession); const QVector shades = generateOklchShades( calculatorBackground, 6, themePolarityForBackground(calculatorBackground)); for (const char* dockName : {"HistoryDock", "VariablesDock", "UserFunctionsDock", "UserUnitsDock"}) { QDockWidget* dock = window.findChild(QString::fromLatin1(dockName)); QVERIFY(dock != nullptr); dock->setFloating(floating); dock->show(); dock->raise(); QCoreApplication::processEvents(); QAbstractItemView* list = dock->findChild(); QVERIFY(list != nullptr); const QPalette listPalette = list->palette(); const QString listStyle = list->styleSheet(); for (const int mode : {0, 1, 0}) { appearance->actions().at(mode)->trigger(); const QColor expectedBackground = mode == 0 ? native.color(QPalette::Window) : shades.at(UiConfig::DockHeaderShade); const auto inspectPopup = [&](QWidget* target, const QPoint& pos) { bool inspected = false; QTimer inspector; inspector.setSingleShot(true); connect(&inspector, &QTimer::timeout, &window, [&]() { auto* menu = qobject_cast(QApplication::activePopupWidget()); QVERIFY2(menu != nullptr, dockName); const auto closeMenu = qScopeGuard([menu]() { menu->close(); }); QVERIFY(!menu->actions().isEmpty()); QCOMPARE(menu->palette().color(QPalette::Window).name(), expectedBackground.name()); if (mode == 0) { QVERIFY(menu->styleSheet().isEmpty()); for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive, QPalette::Disabled}) { for (const QPalette::ColorRole role : {QPalette::WindowText, QPalette::Text, QPalette::Highlight, QPalette::HighlightedText}) QCOMPARE(menu->palette().color(group, role), native.color(group, role)); } } else { QVERIFY(!menu->styleSheet().isEmpty()); } // Check the pixels too. An inherited stylesheet can replace // a correct menu palette when the popup is painted. const QImage image = menu->grab().toImage(); QColor paintedBackground = expectedBackground; if (mode == 0) { // Native styles may shade the palette's background. // Compare with the same style without a themed parent. QMenu reference; reference.ensurePolished(); QStyleOption option; option.initFrom(&reference); option.rect = image.rect(); QImage nativeBackground(image.size(), QImage::Format_ARGB32_Premultiplied); nativeBackground.fill(native.color(QPalette::Window)); QPainter painter(&nativeBackground); reference.style()->drawPrimitive(QStyle::PE_PanelMenu, &option, &painter, &reference); painter.end(); paintedBackground = nativeBackground.pixelColor(nativeBackground.rect().center()); } const QRect interior = image.rect().adjusted(5, 5, -5, -5); int matchingPixels = 0; for (int y = interior.top(); y <= interior.bottom(); ++y) { for (int x = interior.left(); x <= interior.right(); ++x) { if (image.pixelColor(x, y).name() == paintedBackground.name()) ++matchingPixels; } } QVERIFY2(matchingPixels > interior.width() * interior.height() / 2, dockName); inspected = true; }); inspector.start(0); QContextMenuEvent event(QContextMenuEvent::Mouse, pos, target->mapToGlobal(pos)); QCoreApplication::sendEvent(target, &event); QCoreApplication::processEvents(); inspector.stop(); QVERIFY2(inspected, dockName); }; const QPoint listPos = list->model()->rowCount() > 0 ? list->visualRect(list->model()->index(0, 0)).center() : QPoint(8, 8); inspectPopup(list->viewport(), listPos); if (QLineEdit* search = dock->findChild()) inspectPopup(search, QPoint(8, 8)); QCOMPARE(list->palette(), listPalette); QCOMPARE(list->styleSheet(), listStyle); } } } void TestMenusUi::precision_menu_editor_uses_themed_colors_data() { QTest::addColumn("smallFont"); QTest::newRow("default-font") << false; QTest::newRow("small-antialiased-font") << true; } void TestMenusUi::precision_menu_editor_uses_themed_colors() { QFETCH(bool, smallFont); MainWindowStateGuard guard; Settings* settings = guard.settings; settings->menuAppearance = Settings::MenuAppearanceSpeedCrunch; settings->colorScheme = QStringLiteral("Custom"); settings->customColorSchemeJson = themeJsonString(QJsonObject{ {QStringLiteral("background"), QStringLiteral("#300a24")} }); settings->statusBarVisible = true; settings->resultPrecision = 8; settings->hasNumberFormatStyleSetting = true; MainWindow window; window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); QString failure; QColor menuTextColor; QColor labelTextColor; QColor spinBackgroundColor; QColor spinTextColor; QColor spinArrowColor; QImage spinImage; qreal spinImageDevicePixelRatio = 1.0; QRect spinEditRect; QTimer::singleShot(0, &window, [&]() { QMenu* menu = qobject_cast(QApplication::activePopupWidget()); if (menu == nullptr) { failure = QStringLiteral("Precision popup menu was not found."); return; } QLabel* precisionLabel = nullptr; for (QLabel* label : menu->findChildren()) { if (label->text() == QStringLiteral("Decimal places:")) { precisionLabel = label; break; } } if (precisionLabel == nullptr) { failure = QStringLiteral("Precision editor label was not found."); menu->close(); return; } QSpinBox* precisionSpin = menu->findChild(); if (precisionSpin == nullptr) { failure = QStringLiteral("Precision editor spin box was not found."); menu->close(); return; } if (smallFont) { QFont font = precisionSpin->font(); font.setPixelSize(8); font.setWeight(QFont::Thin); font.setStyleStrategy(QFont::PreferAntialias); precisionSpin->setFont(font); } menuTextColor = menu->palette().color(QPalette::WindowText); labelTextColor = precisionLabel->palette().color(QPalette::WindowText); spinBackgroundColor = precisionSpin->palette().color(QPalette::Base); spinTextColor = precisionSpin->palette().color(QPalette::Text); spinArrowColor = precisionSpin->palette().color(QPalette::ButtonText); QStyleOptionSpinBox option; option.initFrom(precisionSpin); option.subControls = QStyle::SC_All; spinEditRect = precisionSpin->style()->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxEditField, precisionSpin); const QPixmap spinPixmap = precisionSpin->grab(); spinImageDevicePixelRatio = spinPixmap.devicePixelRatio(); spinImage = spinPixmap.toImage(); menu->close(); }); QVERIFY(QMetaObject::invokeMethod(&window, "showPrecisionContextMenu", Qt::DirectConnection, Q_ARG(QPoint, QPoint()))); QVERIFY2(failure.isEmpty(), qPrintable(failure)); QVERIFY(menuTextColor.isValid()); QCOMPARE(labelTextColor.name(), menuTextColor.name()); const QColor base(QStringLiteral("#300a24")); const QVector shades = generateOklchShades(base, 6, ThemePolarity::Dark); const QVector foregrounds = aaForegroundsForBackgrounds(shades); QCOMPARE(spinBackgroundColor.name(), shades.at(UiConfig::DockUnfocusedSelectedItemShade).name()); QCOMPARE(spinTextColor.name(), foregrounds.at(UiConfig::DockUnfocusedSelectedItemShade).name()); QCOMPARE(spinArrowColor.name(), foregrounds.at(UiConfig::DockUnfocusedSelectedItemShade).name()); const auto imageRect = [spinImageDevicePixelRatio](const QRect& logicalRect) { return QRect(qRound(logicalRect.x() * spinImageDevicePixelRatio), qRound(logicalRect.y() * spinImageDevicePixelRatio), qRound(logicalRect.width() * spinImageDevicePixelRatio), qRound(logicalRect.height() * spinImageDevicePixelRatio)); }; const QColor expectedBackground = shades.at(UiConfig::DockUnfocusedSelectedItemShade); const QColor expectedForeground = foregrounds.at(UiConfig::DockUnfocusedSelectedItemShade); QVERIFY(firstPixelMatchingColor(spinImage, imageRect(spinEditRect), expectedBackground, 4) != QPoint(-1, -1)); QVERIFY(firstPixelMatchingColorBlend(spinImage, imageRect(spinEditRect), expectedForeground, expectedBackground, 8) != QPoint(-1, -1)); const int arrowColumnWidth = qRound(18 * spinImageDevicePixelRatio); const QRect arrowColumn(spinImage.width() - arrowColumnWidth, 0, arrowColumnWidth, spinImage.height()); const int arrowInset = qRound(3 * spinImageDevicePixelRatio); const QRect arrowInterior = arrowColumn.adjusted(arrowInset, arrowInset, -arrowInset, -arrowInset); const QRect upArrowImageRect(arrowInterior.x(), arrowInterior.y(), arrowInterior.width(), arrowInterior.height() / 2); const QRect downArrowImageRect(arrowInterior.x(), arrowInterior.center().y() + 1, arrowInterior.width(), arrowInterior.height() - arrowInterior.height() / 2); QVERIFY(firstPixelDistinctFromColor(spinImage, upArrowImageRect, expectedBackground, 48) != QPoint(-1, -1)); QVERIFY(firstPixelDistinctFromColor(spinImage, downArrowImageRect, expectedBackground, 48) != QPoint(-1, -1)); } int main(int argc, char** argv) { return UiTestFixture::run(argc, argv); } #include "testmenusui.moc" heldercorreia-speedcrunch-e7ca37f/src/tests/testoklch.cpp000066400000000000000000000607131526573132500240010ustar00rootroot00000000000000// SPDX-FileCopyrightText: 2026 SpeedCrunch developers // SPDX-License-Identifier: GPL-2.0-or-later #include "gui/oklchutils.h" #include "gui/uiconfig.h" #include #include #include #include #include #include namespace { constexpr double kExpectedAaMinimumContrast = 7.0; constexpr double kExpectedAaaMinimumContrast = 7.0; double srgbToLinear(double channel) { return channel <= 0.04045 ? channel / 12.92 : std::pow((channel + 0.055) / 1.055, 2.4); } double relativeLuminance(const QColor& color) { return 0.2126 * srgbToLinear(color.redF()) + 0.7152 * srgbToLinear(color.greenF()) + 0.0722 * srgbToLinear(color.blueF()); } double contrastRatio(const QColor& first, const QColor& second) { const double firstLuminance = relativeLuminance(first); const double secondLuminance = relativeLuminance(second); return (std::max(firstLuminance, secondLuminance) + 0.05) / (std::min(firstLuminance, secondLuminance) + 0.05); } double bestBlackOrWhiteContrast(const QColor& background) { return std::max(contrastRatio(QColor(Qt::black), background), contrastRatio(QColor(Qt::white), background)); } bool colorsAreClose(const QColor& first, const QColor& second) { return std::abs(first.red() - second.red()) <= 1 && std::abs(first.green() - second.green()) <= 1 && std::abs(first.blue() - second.blue()) <= 1 && std::abs(first.alpha() - second.alpha()) <= 1; } double hueDistance(double first, double second) { const double difference = std::abs(first - second); return std::min(difference, 360.0 - difference); } void verifyValidColor(const QColor& color) { QVERIFY(color.isValid()); QVERIFY(color.redF() >= 0.0 && color.redF() <= 1.0); QVERIFY(color.greenF() >= 0.0 && color.greenF() <= 1.0); QVERIFY(color.blueF() >= 0.0 && color.blueF() <= 1.0); QVERIFY(color.alphaF() >= 0.0 && color.alphaF() <= 1.0); } } // namespace class TestOklchUtils : public QObject { Q_OBJECT private slots: void colors_round_trip_through_oklch(); void gamut_fitting_handles_excessive_chroma_and_preserves_alpha(); void shades_handle_empty_and_single_counts(); void percentage_shades_follow_requested_distance(); void shade_chroma_decays_away_from_base(); void light_shades_decrease_in_lightness(); void dark_shades_increase_in_lightness(); void default_foregrounds_meet_aa_and_choose_neutral_extremes(); void preferred_tint_is_kept_when_it_passes_aa(); void preferred_tint_is_adjusted_to_pass_aa(); void foregrounds_support_light_tints_dark_tints_and_aaa(); void visually_lost_tint_falls_back_to_black_or_white(); void foreground_vector_matches_background_vector(); void generated_surface_text_meets_readability_target_data(); void generated_surface_text_meets_readability_target(); void terminal_dock_and_popup_text_keep_tint_with_stronger_contrast(); void generated_links_keep_visible_tints_at_stronger_contrast(); void primary_from_dark_neutral_background_is_chromatic_and_readable(); void primary_from_black_background_is_valid_and_readable(); void primary_from_light_neutral_background_is_darker_chromatic_accent(); void primary_from_saturated_background_keeps_hue_family_and_gains_prominence(); void primary_generation_handles_gamut_edges(); void generated_primary_meets_minimum_contrast_for_representative_backgrounds(); void preferred_blue_link_is_adjusted_to_aa_on_dark_formula_book_surface(); void secondary_link_is_readable_neutral_and_hue_distinct(); void secondary_link_tracks_theme_hue_when_it_is_distinct(); void html_report_contains_generation_inputs_and_outputs(); }; void TestOklchUtils::colors_round_trip_through_oklch() { const QVector colors = { QColor(Qt::white), QColor(Qt::black), QColor(QStringLiteral("#00ff00")) }; for (const QColor& original : colors) { const QColor roundTrip = oklchToQColor(qColorToOklch(original)); QVERIFY(colorsAreClose(roundTrip, original)); } } void TestOklchUtils::gamut_fitting_handles_excessive_chroma_and_preserves_alpha() { const QColor fitted = oklchToValidSrgbQColor({0.62, 1.2, 145.0, 0.35}); verifyValidColor(fitted); QVERIFY(std::abs(fitted.alphaF() - 0.35) < 0.001); } void TestOklchUtils::shades_handle_empty_and_single_counts() { const QColor base(QStringLiteral("#3c7655")); QVERIFY(generateOklchShades(base, 0, ThemePolarity::Light).isEmpty()); QVERIFY(generateOklchShades(base, -1, ThemePolarity::Dark).isEmpty()); const QVector single = generateOklchShades(base, 1, ThemePolarity::Light); QCOMPARE(single.size(), 1); verifyValidColor(single.first()); QVERIFY(colorsAreClose(single.first(), base)); } void TestOklchUtils::percentage_shades_follow_requested_distance() { const QColor base(QStringLiteral("#466353")); const double factor = 0.10; const double baseLightness = qColorToOklch(base).l; const QVector dark = generateOklchShades(base, 5, ThemePolarity::Dark, factor); const QVector light = generateOklchShades(base, 5, ThemePolarity::Light, factor); QCOMPARE(dark.size(), 5); QCOMPARE(light.size(), 5); QVERIFY(colorsAreClose(dark.at(1), base)); QVERIFY(colorsAreClose(light.at(1), base)); const double darkShade0L = qColorToOklch(dark.at(0)).l; const double darkShade2L = qColorToOklch(dark.at(2)).l; const double darkShade3L = qColorToOklch(dark.at(3)).l; QVERIFY(std::abs(darkShade0L - baseLightness * (1.0 - factor)) < 0.004); QVERIFY(std::abs(darkShade2L - (baseLightness + (1.0 - baseLightness) * factor)) < 0.004); QVERIFY(std::abs(darkShade3L - (baseLightness + (1.0 - baseLightness) * factor * 2.0)) < 0.004); const double lightShade0L = qColorToOklch(light.at(0)).l; const double lightShade2L = qColorToOklch(light.at(2)).l; const double lightShade3L = qColorToOklch(light.at(3)).l; QVERIFY(std::abs(lightShade0L - (baseLightness + (1.0 - baseLightness) * factor)) < 0.004); QVERIFY(std::abs(lightShade2L - baseLightness * (1.0 - factor)) < 0.004); QVERIFY(std::abs(lightShade3L - baseLightness * (1.0 - factor * 2.0)) < 0.004); } void TestOklchUtils::shade_chroma_decays_away_from_base() { const QColor base(QStringLiteral("#8a3f68")); const QVector shades = generateOklchShades(base, 5, ThemePolarity::Dark, 0.10); QCOMPARE(shades.size(), 5); const double baseChroma = qColorToOklch(shades.at(1)).c; QVERIFY(baseChroma > 0.01); QVERIFY(qColorToOklch(shades.at(0)).c < baseChroma); QVERIFY(qColorToOklch(shades.at(2)).c < baseChroma); QVERIFY(qColorToOklch(shades.at(3)).c < qColorToOklch(shades.at(2)).c); QVERIFY(qColorToOklch(shades.at(4)).c < qColorToOklch(shades.at(3)).c); } void TestOklchUtils::light_shades_decrease_in_lightness() { const QVector> palettes = { generateOklchShades(QColor(QStringLiteral("#67a87b")), 7, ThemePolarity::Light), generateOklchShades(QColor(QStringLiteral("#010101")), 7, ThemePolarity::Light) }; for (const QVector& shades : palettes) { QCOMPARE(shades.size(), 7); for (int i = 0; i < shades.size(); ++i) { verifyValidColor(shades.at(i)); if (i > 0) { QVERIFY(qColorToOklch(shades.at(i)).l <= qColorToOklch(shades.at(i - 1)).l + 1e-6); } } } } void TestOklchUtils::dark_shades_increase_in_lightness() { const QVector> palettes = { generateOklchShades(QColor(QStringLiteral("#24372c")), 7, ThemePolarity::Dark), generateOklchShades(QColor(QStringLiteral("#fefefe")), 7, ThemePolarity::Dark) }; for (const QVector& shades : palettes) { QCOMPARE(shades.size(), 7); for (int i = 0; i < shades.size(); ++i) { verifyValidColor(shades.at(i)); if (i > 0) { QVERIFY(qColorToOklch(shades.at(i)).l >= qColorToOklch(shades.at(i - 1)).l - 1e-6); } } } } void TestOklchUtils::default_foregrounds_meet_aa_and_choose_neutral_extremes() { const QColor whiteBackground(Qt::white); const QColor blackBackground(Qt::black); QCOMPARE(aaForegroundForBackground(whiteBackground), QColor(Qt::black)); QCOMPARE(aaForegroundForBackground(blackBackground), QColor(Qt::white)); const QVector backgrounds = { whiteBackground, blackBackground, QColor(QStringLiteral("#888888")), QColor(QStringLiteral("#174128")) }; for (const QColor& background : backgrounds) { const QColor foreground = aaForegroundForBackground(background); const double contrast = contrastRatio(foreground, background); if (bestBlackOrWhiteContrast(background) >= kExpectedAaMinimumContrast) QVERIFY(contrast >= kExpectedAaMinimumContrast); else QCOMPARE(contrast, bestBlackOrWhiteContrast(background)); } const QColor greenForeground = aaForegroundForBackground(QColor(QStringLiteral("#174128"))); QVERIFY(greenForeground != QColor(Qt::black)); QVERIFY(greenForeground != QColor(Qt::white)); } void TestOklchUtils::preferred_tint_is_kept_when_it_passes_aa() { const QColor background(QStringLiteral("#10241a")); const QColor tint(QStringLiteral("#c8edcf")); const QColor foreground = aaForegroundForBackground(background, tint); QCOMPARE(foreground.name(), tint.name()); QVERIFY(contrastRatio(foreground, background) >= kExpectedAaMinimumContrast); } void TestOklchUtils::preferred_tint_is_adjusted_to_pass_aa() { const QColor background(QStringLiteral("#14251b")); const QColor tint(QStringLiteral("#416750")); QVERIFY(contrastRatio(tint, background) < kExpectedAaMinimumContrast); const QColor foreground = aaForegroundForBackground(background, tint); QVERIFY(contrastRatio(foreground, background) >= kExpectedAaMinimumContrast); QVERIFY(foreground != QColor(Qt::black)); QVERIFY(foreground != QColor(Qt::white)); QVERIFY(foreground.name() != tint.name()); } void TestOklchUtils::foregrounds_support_light_tints_dark_tints_and_aaa() { const QColor darkBackground(QStringLiteral("#123526")); const QColor paleGreen(QStringLiteral("#c8eed5")); const QColor lightBackground(QStringLiteral("#e5f2e8")); const QColor darkGreen(QStringLiteral("#16442d")); const QColor paleForeground = aaForegroundForBackground(darkBackground, paleGreen); const QColor darkForeground = aaForegroundForBackground(lightBackground, darkGreen); QVERIFY(contrastRatio(paleForeground, darkBackground) >= kExpectedAaMinimumContrast); QVERIFY(contrastRatio(darkForeground, lightBackground) >= kExpectedAaMinimumContrast); QVERIFY(paleForeground != QColor(Qt::black) && paleForeground != QColor(Qt::white)); QVERIFY(darkForeground != QColor(Qt::black) && darkForeground != QColor(Qt::white)); QVERIFY(contrastRatio( aaForegroundForBackground(QColor(Qt::black), paleGreen, kExpectedAaaMinimumContrast), QColor(Qt::black)) >= kExpectedAaaMinimumContrast); } void TestOklchUtils::visually_lost_tint_falls_back_to_black_or_white() { const QColor background(QStringLiteral("#6f6f6f")); const QColor saturatedTint(QStringLiteral("#0000ff")); const QColor foreground = aaForegroundForBackground(background, saturatedTint); QVERIFY(foreground == QColor(Qt::black) || foreground == QColor(Qt::white)); QCOMPARE(contrastRatio(foreground, background), bestBlackOrWhiteContrast(background)); } void TestOklchUtils::foreground_vector_matches_background_vector() { const QVector backgrounds = { QColor(QStringLiteral("#10241a")), QColor(QStringLiteral("#315d43")), QColor(QStringLiteral("#6f6f6f")), QColor(QStringLiteral("#888888")), QColor(QStringLiteral("#e5f2e8")) }; const QVector defaults = aaForegroundsForBackgrounds(backgrounds); const QVector tinted = aaForegroundsForBackgrounds( backgrounds, QColor(QStringLiteral("#49845c"))); QCOMPARE(defaults.size(), backgrounds.size()); QCOMPARE(tinted.size(), backgrounds.size()); for (int i = 0; i < backgrounds.size(); ++i) { const double defaultContrast = contrastRatio(defaults.at(i), backgrounds.at(i)); const double tintedContrast = contrastRatio(tinted.at(i), backgrounds.at(i)); if (bestBlackOrWhiteContrast(backgrounds.at(i)) >= kExpectedAaMinimumContrast) { QVERIFY(defaultContrast >= kExpectedAaMinimumContrast); QVERIFY(tintedContrast >= kExpectedAaMinimumContrast); } else { QCOMPARE(defaultContrast, bestBlackOrWhiteContrast(backgrounds.at(i))); QCOMPARE(tintedContrast, bestBlackOrWhiteContrast(backgrounds.at(i))); } } } void TestOklchUtils::generated_surface_text_meets_readability_target_data() { QTest::addColumn("base"); QTest::newRow("terminal") << QColor(QStringLiteral("#300a24")); QTest::newRow("dark-green") << QColor(QStringLiteral("#174128")); QTest::newRow("light-green") << QColor(QStringLiteral("#e5f2e8")); QTest::newRow("middle-gray") << QColor(QStringLiteral("#888888")); QTest::newRow("saturated-blue") << QColor(QStringLiteral("#0000ff")); QTest::newRow("saturated-yellow") << QColor(QStringLiteral("#ffff00")); QTest::newRow("black") << QColor(Qt::black); QTest::newRow("white") << QColor(Qt::white); } void TestOklchUtils::generated_surface_text_meets_readability_target() { QFETCH(QColor, base); const QVector shades = generateOklchShades(base, 6, themePolarityForBackground(base)); const QVector foregrounds = aaForegroundsForBackgrounds(shades); const QVector tinted = aaForegroundsForBackgrounds( shades, QColor(QStringLiteral("#49845c"))); QCOMPARE(foregrounds.size(), shades.size()); QCOMPARE(tinted.size(), shades.size()); for (int i = 0; i < shades.size(); ++i) { for (const QColor& foreground : {foregrounds.at(i), tinted.at(i)}) { QCOMPARE(foreground, QColor(foreground.name())); for (const QColor& background : {shades.at(i), QColor(shades.at(i).name())}) { const double contrast = contrastRatio(foreground, background); if (bestBlackOrWhiteContrast(background) >= 10.0) { QVERIFY2(contrast >= 10.0, qPrintable(QStringLiteral("Shade %1: %2 on %3 gives %4:1") .arg(i).arg(foreground.name(), background.name()) .arg(contrast, 0, 'f', 6))); } else { QVERIFY(foreground == QColor(Qt::black) || foreground == QColor(Qt::white)); QCOMPARE(contrast, bestBlackOrWhiteContrast(background)); } } } } } void TestOklchUtils::terminal_dock_and_popup_text_keep_tint_with_stronger_contrast() { const QVector shades = generateOklchShades( QColor(QStringLiteral("#300a24")), 6, ThemePolarity::Dark); for (const int shade : {UiConfig::DockBackgroundShade, UiConfig::DockHeaderShade, UiConfig::CompletionPopupBackgroundShade}) { const QColor background(shades.at(shade).name()); const QColor previous = aaForegroundForBackground(shades.at(shade), 7.0); const QColor foreground = aaForegroundForBackground(shades.at(shade)); QVERIFY(contrastRatio(foreground, background) >= 10.0); QVERIFY(contrastRatio(foreground, background) > contrastRatio(previous, background) + 2.9); QVERIFY(foreground != QColor(Qt::white)); QVERIFY(qColorToOklch(foreground).c >= 0.015); } } void TestOklchUtils::generated_links_keep_visible_tints_at_stronger_contrast() { for (const QColor& background : {QColor(QStringLiteral("#333348")), QColor(QStringLiteral("#232136")), QColor(QStringLiteral("#e5f2e8"))}) { const QColor formulaLink = aaForegroundForBackground(background, QColor(Qt::blue)); const QColor sectionLink = generateSecondaryLinkFromBackground(background, formulaLink); for (const QColor& link : {formulaLink, sectionLink}) { QVERIFY(link.isValid()); QCOMPARE(link, QColor(link.name())); QVERIFY(contrastRatio(link, background) >= 10.0); QVERIFY(qColorToOklch(link).c >= 0.015); } } } void TestOklchUtils::primary_from_dark_neutral_background_is_chromatic_and_readable() { const QColor background(QStringLiteral("#232136")); const QColor primary = generatePrimaryFromBackground(background); const Oklch backgroundOklch = qColorToOklch(background); const Oklch primaryOklch = qColorToOklch(primary); verifyValidColor(primary); QVERIFY(primaryOklch.c >= 0.05); QVERIFY(primaryOklch.l > backgroundOklch.l); QVERIFY(contrastRatio(primary, background) >= 3.0); if (backgroundOklch.c < 0.02) QVERIFY(hueDistance(primaryOklch.h, 250.0) < 8.0); else QVERIFY(hueDistance(primaryOklch.h, backgroundOklch.h) < 12.0); } void TestOklchUtils::primary_from_black_background_is_valid_and_readable() { const QColor background(QStringLiteral("#000000")); const QColor primary = generatePrimaryFromBackground(background); const Oklch primaryOklch = qColorToOklch(primary); verifyValidColor(primary); QVERIFY(primaryOklch.c >= 0.05); QVERIFY(primaryOklch.l > 0.65); QVERIFY(hueDistance(primaryOklch.h, 250.0) < 8.0); QVERIFY(contrastRatio(primary, background) >= 3.0); } void TestOklchUtils::primary_from_light_neutral_background_is_darker_chromatic_accent() { const QColor background(QStringLiteral("#f5f5f5")); const QColor primary = generatePrimaryFromBackground(background); const Oklch backgroundOklch = qColorToOklch(background); const Oklch primaryOklch = qColorToOklch(primary); verifyValidColor(primary); QVERIFY(primaryOklch.c >= 0.04); QVERIFY(primaryOklch.l < backgroundOklch.l); QVERIFY(hueDistance(primaryOklch.h, 250.0) < 8.0); QVERIFY(contrastRatio(primary, background) >= 3.0); } void TestOklchUtils::primary_from_saturated_background_keeps_hue_family_and_gains_prominence() { const QColor background(QStringLiteral("#003b46")); const QColor primary = generatePrimaryFromBackground(background); const Oklch backgroundOklch = qColorToOklch(background); const Oklch primaryOklch = qColorToOklch(primary); verifyValidColor(primary); QVERIFY(hueDistance(primaryOklch.h, backgroundOklch.h) < 12.0); QVERIFY(primaryOklch.c > backgroundOklch.c); QVERIFY(primaryOklch.l > backgroundOklch.l); QVERIFY(contrastRatio(primary, background) >= 3.0); } void TestOklchUtils::primary_generation_handles_gamut_edges() { const QVector backgrounds = { QColor(QStringLiteral("#ff0000")), QColor(QStringLiteral("#00ff00")), QColor(QStringLiteral("#0000ff")), QColor(QStringLiteral("#00ffff")), QColor(QStringLiteral("#ff00ff")), QColor(QStringLiteral("#ffff00")), QColor(QStringLiteral("#ffffff")), QColor(QStringLiteral("#000000")) }; for (const QColor& background : backgrounds) verifyValidColor(generatePrimaryFromBackground(background)); } void TestOklchUtils::generated_primary_meets_minimum_contrast_for_representative_backgrounds() { const QVector backgrounds = { QColor(QStringLiteral("#232136")), QColor(QStringLiteral("#000000")), QColor(QStringLiteral("#f5f5f5")), QColor(QStringLiteral("#003b46")), QColor(QStringLiteral("#101010")), QColor(QStringLiteral("#fafafa")), QColor(QStringLiteral("#663399")), QColor(QStringLiteral("#e6d9b8")) }; for (const QColor& background : backgrounds) { const QColor primary = generatePrimaryFromBackground(background); verifyValidColor(primary); QVERIFY(contrastRatio(primary, background) >= 3.0); } } void TestOklchUtils::preferred_blue_link_is_adjusted_to_aa_on_dark_formula_book_surface() { const QColor background(QStringLiteral("#333348")); const QColor preferredLink(QStringLiteral("#0000ff")); QVERIFY(contrastRatio(preferredLink, background) < kExpectedAaMinimumContrast); const QColor formulaLink = aaForegroundForBackground(background, preferredLink); verifyValidColor(formulaLink); QVERIFY(contrastRatio(formulaLink, background) >= kExpectedAaMinimumContrast); QVERIFY(formulaLink != QColor(Qt::black)); QVERIFY(formulaLink != QColor(Qt::white)); } void TestOklchUtils::secondary_link_is_readable_neutral_and_hue_distinct() { const QColor background(QStringLiteral("#232136")); const QColor primaryLink = generatePrimaryFromBackground(background); const QColor secondaryLink = generateSecondaryLinkFromBackground(background, primaryLink); const Oklch primaryOklch = qColorToOklch(primaryLink); const Oklch secondaryOklch = qColorToOklch(secondaryLink); verifyValidColor(secondaryLink); QVERIFY(contrastRatio(secondaryLink, background) >= kExpectedAaMinimumContrast); QVERIFY(hueDistance(secondaryOklch.h, primaryOklch.h) >= 45.0); QVERIFY(secondaryOklch.c < primaryOklch.c); } void TestOklchUtils::secondary_link_tracks_theme_hue_when_it_is_distinct() { const QColor background(QStringLiteral("#123526")); const QColor primaryLink(QStringLiteral("#d6c2ff")); const QColor secondaryLink = generateSecondaryLinkFromBackground(background, primaryLink); const Oklch backgroundOklch = qColorToOklch(background); const Oklch primaryOklch = qColorToOklch(primaryLink); const Oklch secondaryOklch = qColorToOklch(secondaryLink); verifyValidColor(secondaryLink); QVERIFY(contrastRatio(secondaryLink, background) >= kExpectedAaMinimumContrast); QVERIFY(hueDistance(secondaryOklch.h, primaryOklch.h) >= 45.0); QVERIFY(hueDistance(secondaryOklch.h, backgroundOklch.h) < 18.0); } void TestOklchUtils::html_report_contains_generation_inputs_and_outputs() { const QColor base(QStringLiteral("#333b4a")); const QVector backgrounds = generateOklchShades(base, 3, ThemePolarity::Dark, 0.1); const QVector foregrounds = aaForegroundsForBackgrounds(backgrounds); const QString path = writeOklchGenerationHtmlReport(base, 1, 1, ThemePolarity::Dark, 0.1, false, backgrounds, foregrounds); if (!UiConfig::OklchThemeDebugReportEnabled) { QVERIFY(path.isEmpty()); return; } QVERIFY(!path.isEmpty()); QVERIFY(path.startsWith(QDir::tempPath())); QVERIFY(path.endsWith(QStringLiteral("/speedcrunch-oklch-theme-report.html"))); QFile report(path); QVERIFY(report.open(QIODevice::ReadOnly | QIODevice::Text)); const QString html = QString::fromUtf8(report.readAll()); QVERIFY(html.contains(QStringLiteral("